summaryrefslogblamecommitdiffstats
path: root/arch/powerpc/kernel/setup_64.c
blob: adf2084f214b2bd01d5aa3ef2a613e66b7b66a05 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                     
             
 
                         






                         










                              
                          
                      
                          
                           
                         
                      
 
                   
                      


                          



                        





                         





                       
                         
                     
                     
                      
                              
                          
                     
                           






                                    
                         

                   
                                    







                                    
  

                                
                                                     
                                     


                

                                                                


                                                          







                                                                  





                                                                    
                                           
                   



                                                                           

         

      

                 
                                 

                                        
                                   

                               
                               
 

                                               
 






                                                               
                                

                               
                                                                      

                                                     
                                                                   
















                                                                               




                                            
                                



                                              

                       
                                                   
                                        






                                                                      
                                             
 
          

                                                                   
           






















                                                                              
                                                                         


         

                                          












                                                                       



                                            





                                                             
                                                              













                                                                

                                                       

                                                                 
                               
                                         
 
                                                                         

                                       
                          
 

                                                        


                                                                  
                                                          

          


                                                              


                                         
                                                                         
                                      
                          
 
          

                                                                            
           
                               
 

                                            
                             
 


                                                       


                                                                      
                                                         
           
                                   
 
                                   











                                                                       

 


                                
                                              
                                     
 

                                                       





                                                                      
                                   


                       
 
                                                     











                                                                           

                           
                           
              
 


                            





                                                                             
           
 

                                                                          
                                                              




                                                 
                                              


                              
                                                                 


                                        
                                            
 
  

                                                                      



                                                                      









                                                                             




                                                    


























































                                                                  
                                       
 

                                                        


                                             















                                                                               
 



                                                         

                                                                     

                                                                      
                                                                    
                                                                      















                                                                      

         
                                   

                                                   
 


                                             




                                                                   
                                        
 








                                                             
                                           
                                
      

 
                                     
 
                                       


                       

                                                                 
           
                                  
                                                       
                                                             
                                                                 
                                                       
                                                             
                                                                 

         
 
                        
                                    

                       
                         

                                  










                                                                  
         

                                                   
                                                               
 

      

                                                                  

                                                                       
   
                                      
 
                  










                                                                         
                                                        
 
                                  



                                                                                


                                                                           


                                                                                
      
         

 
                 


                                                                               
 


                                                                             
 



                                                       
 







                                                                


                                                      























                                                                               



                                                                       

      
 








                                                  
 
                                                                         

                             
      












                                                                        
                                      




                                            
/*
 * 
 * Common boot and setup code.
 *
 * Copyright (C) 2001 PPC64 Team, IBM Corp
 *
 *      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.
 */

#define DEBUG

#include <linux/export.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/initrd.h>
#include <linux/seq_file.h>
#include <linux/ioport.h>
#include <linux/console.h>
#include <linux/utsname.h>
#include <linux/tty.h>
#include <linux/root_dev.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/unistd.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/bootmem.h>
#include <linux/pci.h>
#include <linux/lockdep.h>
#include <linux/memblock.h>
#include <linux/memory.h>
#include <linux/nmi.h>

#include <asm/io.h>
#include <asm/kdump.h>
#include <asm/prom.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/smp.h>
#include <asm/elf.h>
#include <asm/machdep.h>
#include <asm/paca.h>
#include <asm/time.h>
#include <asm/cputable.h>
#include <asm/sections.h>
#include <asm/btext.h>
#include <asm/nvram.h>
#include <asm/setup.h>
#include <asm/rtas.h>
#include <asm/iommu.h>
#include <asm/serial.h>
#include <asm/cache.h>
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/firmware.h>
#include <asm/xmon.h>
#include <asm/udbg.h>
#include <asm/kexec.h>
#include <asm/code-patching.h>
#include <asm/livepatch.h>
#include <asm/opal.h>
#include <asm/cputhreads.h>

#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...)
#endif

int spinning_secondaries;
u64 ppc64_pft_size;

struct ppc64_caches ppc64_caches = {
	.l1d = {
		.block_size = 0x40,
		.log_block_size = 6,
	},
	.l1i = {
		.block_size = 0x40,
		.log_block_size = 6
	},
};
EXPORT_SYMBOL_GPL(ppc64_caches);

#if defined(CONFIG_PPC_BOOK3E) && defined(CONFIG_SMP)
void __init setup_tlb_core_data(void)
{
	int cpu;

	BUILD_BUG_ON(offsetof(struct tlb_core_data, lock) != 0);

	for_each_possible_cpu(cpu) {
		int first = cpu_first_thread_sibling(cpu);

		/*
		 * If we boot via kdump on a non-primary thread,
		 * make sure we point at the thread that actually
		 * set up this TLB.
		 */
		if (cpu_first_thread_sibling(boot_cpuid) == first)
			first = boot_cpuid;

		paca[cpu].tcd_ptr = &paca[first].tcd;

		/*
		 * If we have threads, we need either tlbsrx.
		 * or e6500 tablewalk mode, or else TLB handlers
		 * will be racy and could produce duplicate entries.
		 * Should we panic instead?
		 */
		WARN_ONCE(smt_enabled_at_boot >= 2 &&
			  !mmu_has_feature(MMU_FTR_USE_TLBRSRV) &&
			  book3e_htw_mode != PPC_HTW_E6500,
			  "%s: unsupported MMU configuration\n", __func__);
	}
}
#endif

#ifdef CONFIG_SMP

static char *smt_enabled_cmdline;

/* Look for ibm,smt-enabled OF option */
void __init check_smt_enabled(void)
{
	struct device_node *dn;
	const char *smt_option;

	/* Default to enabling all threads */
	smt_enabled_at_boot = threads_per_core;

	/* Allow the command line to overrule the OF option */
	if (smt_enabled_cmdline) {
		if (!strcmp(smt_enabled_cmdline, "on"))
			smt_enabled_at_boot = threads_per_core;
		else if (!strcmp(smt_enabled_cmdline, "off"))
			smt_enabled_at_boot = 0;
		else {
			int smt;
			int rc;

			rc = kstrtoint(smt_enabled_cmdline, 10, &smt);
			if (!rc)
				smt_enabled_at_boot =
					min(threads_per_core, smt);
		}
	} else {
		dn = of_find_node_by_path("/options");
		if (dn) {
			smt_option = of_get_property(dn, "ibm,smt-enabled",
						     NULL);

			if (smt_option) {
				if (!strcmp(smt_option, "on"))
					smt_enabled_at_boot = threads_per_core;
				else if (!strcmp(smt_option, "off"))
					smt_enabled_at_boot = 0;
			}

			of_node_put(dn);
		}
	}
}

/* Look for smt-enabled= cmdline option */
static int __init early_smt_enabled(char *p)
{
	smt_enabled_cmdline = p;
	return 0;
}
early_param("smt-enabled", early_smt_enabled);

#endif /* CONFIG_SMP */

/** Fix up paca fields required for the boot cpu */
static void __init fixup_boot_paca(void)
{
	/* The boot cpu is started */
	get_paca()->cpu_start = 1;
	/* Allow percpu accesses to work until we setup percpu data */
	get_paca()->data_offset = 0;
}

static void __init configure_exceptions(void)
{
	/*
	 * Setup the trampolines from the lowmem exception vectors
	 * to the kdump kernel when not using a relocatable kernel.
	 */
	setup_kdump_trampoline();

	/* Under a PAPR hypervisor, we need hypercalls */
	if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
		/* Enable AIL if possible */
		pseries_enable_reloc_on_exc();

		/*
		 * Tell the hypervisor that we want our exceptions to
		 * be taken in little endian mode.
		 *
		 * We don't call this for big endian as our calling convention
		 * makes us always enter in BE, and the call may fail under
		 * some circumstances with kdump.
		 */
#ifdef __LITTLE_ENDIAN__
		pseries_little_endian_exceptions();
#endif
	} else {
		/* Set endian mode using OPAL */
		if (firmware_has_feature(FW_FEATURE_OPAL))
			opal_configure_cores();

		/* AIL on native is done in cpu_ready_for_interrupts() */
	}
}

static void cpu_ready_for_interrupts(void)
{
	/*
	 * Enable AIL if supported, and we are in hypervisor mode. This
	 * is called once for every processor.
	 *
	 * If we are not in hypervisor mode the job is done once for
	 * the whole partition in configure_exceptions().
	 */
	if (early_cpu_has_feature(CPU_FTR_HVMODE) &&
	    early_cpu_has_feature(CPU_FTR_ARCH_207S)) {
		unsigned long lpcr = mfspr(SPRN_LPCR);
		mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3);
	}

	/* Set IR and DR in PACA MSR */
	get_paca()->kernel_msr = MSR_KERNEL;
}

/*
 * Early initialization entry point. This is called by head.S
 * with MMU translation disabled. We rely on the "feature" of
 * the CPU that ignores the top 2 bits of the address in real
 * mode so we can access kernel globals normally provided we
 * only toy with things in the RMO region. From here, we do
 * some early parsing of the device-tree to setup out MEMBLOCK
 * data structures, and allocate & initialize the hash table
 * and segment tables so we can start running with translation
 * enabled.
 *
 * It is this function which will call the probe() callback of
 * the various platform types and copy the matching one to the
 * global ppc_md structure. Your platform can eventually do
 * some very early initializations from the probe() routine, but
 * this is not recommended, be very careful as, for example, the
 * device-tree is not accessible via normal means at this point.
 */

void __init early_setup(unsigned long dt_ptr)
{
	static __initdata struct paca_struct boot_paca;

	/* -------- printk is _NOT_ safe to use here ! ------- */

	/* Identify CPU type */
	identify_cpu(0, mfspr(SPRN_PVR));

	/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
	initialise_paca(&boot_paca, 0);
	setup_paca(&boot_paca);
	fixup_boot_paca();

	/* -------- printk is now safe to use ------- */

	/* Enable early debugging if any specified (see udbg.h) */
	udbg_early_init();

 	DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr);

	/*
	 * Do early initialization using the flattened device
	 * tree, such as retrieving the physical memory map or
	 * calculating/retrieving the hash table size.
	 */
	early_init_devtree(__va(dt_ptr));

	/* Now we know the logical id of our boot cpu, setup the paca. */
	setup_paca(&paca[boot_cpuid]);
	fixup_boot_paca();

	/*
	 * Configure exception handlers. This include setting up trampolines
	 * if needed, setting exception endian mode, etc...
	 */
	configure_exceptions();

	/* Apply all the dynamic patching */
	apply_feature_fixups();
	setup_feature_keys();

	/* Initialize the hash table or TLB handling */
	early_init_mmu();

	/*
	 * At this point, we can let interrupts switch to virtual mode
	 * (the MMU has been setup), so adjust the MSR in the PACA to
	 * have IR and DR set and enable AIL if it exists
	 */
	cpu_ready_for_interrupts();

	DBG(" <- early_setup()\n");

#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
	/*
	 * This needs to be done *last* (after the above DBG() even)
	 *
	 * Right after we return from this function, we turn on the MMU
	 * which means the real-mode access trick that btext does will
	 * no longer work, it needs to switch to using a real MMU
	 * mapping. This call will ensure that it does
	 */
	btext_map();
#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
}

#ifdef CONFIG_SMP
void early_setup_secondary(void)
{
	/* Mark interrupts disabled in PACA */
	get_paca()->soft_enabled = 0;

	/* Initialize the hash table or TLB handling */
	early_init_mmu_secondary();

	/*
	 * At this point, we can let interrupts switch to virtual mode
	 * (the MMU has been setup), so adjust the MSR in the PACA to
	 * have IR and DR set.
	 */
	cpu_ready_for_interrupts();
}

#endif /* CONFIG_SMP */

#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
static bool use_spinloop(void)
{
	if (!IS_ENABLED(CONFIG_PPC_BOOK3E))
		return true;

	/*
	 * When book3e boots from kexec, the ePAPR spin table does
	 * not get used.
	 */
	return of_property_read_bool(of_chosen, "linux,booted-from-kexec");
}

void smp_release_cpus(void)
{
	unsigned long *ptr;
	int i;

	if (!use_spinloop())
		return;

	DBG(" -> smp_release_cpus()\n");

	/* All secondary cpus are spinning on a common spinloop, release them
	 * all now so they can start to spin on their individual paca
	 * spinloops. For non SMP kernels, the secondary cpus never get out
	 * of the common spinloop.
	 */

	ptr  = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
			- PHYSICAL_START);
	*ptr = ppc_function_entry(generic_secondary_smp_init);

	/* And wait a bit for them to catch up */
	for (i = 0; i < 100000; i++) {
		mb();
		HMT_low();
		if (spinning_secondaries == 0)
			break;
		udelay(1);
	}
	DBG("spinning_secondaries = %d\n", spinning_secondaries);

	DBG(" <- smp_release_cpus()\n");
}
#endif /* CONFIG_SMP || CONFIG_KEXEC_CORE */

/*
 * Initialize some remaining members of the ppc64_caches and systemcfg
 * structures
 * (at least until we get rid of them completely). This is mostly some
 * cache informations about the CPU that will be used by cache flush
 * routines and/or provided to userland
 */

static void init_cache_info(struct ppc_cache_info *info, u32 size, u32 lsize,
			    u32 bsize, u32 sets)
{
	info->size = size;
	info->sets = sets;
	info->line_size = lsize;
	info->block_size = bsize;
	info->log_block_size = __ilog2(bsize);
	info->blocks_per_page = PAGE_SIZE / bsize;

	if (sets == 0)
		info->assoc = 0xffff;
	else
		info->assoc = size / (sets * lsize);
}

static bool __init parse_cache_info(struct device_node *np,
				    bool icache,
				    struct ppc_cache_info *info)
{
	static const char *ipropnames[] __initdata = {
		"i-cache-size",
		"i-cache-sets",
		"i-cache-block-size",
		"i-cache-line-size",
	};
	static const char *dpropnames[] __initdata = {
		"d-cache-size",
		"d-cache-sets",
		"d-cache-block-size",
		"d-cache-line-size",
	};
	const char **propnames = icache ? ipropnames : dpropnames;
	const __be32 *sizep, *lsizep, *bsizep, *setsp;
	u32 size, lsize, bsize, sets;
	bool success = true;

	size = 0;
	sets = -1u;
	lsize = bsize = cur_cpu_spec->dcache_bsize;
	sizep = of_get_property(np, propnames[0], NULL);
	if (sizep != NULL)
		size = be32_to_cpu(*sizep);
	setsp = of_get_property(np, propnames[1], NULL);
	if (setsp != NULL)
		sets = be32_to_cpu(*setsp);
	bsizep = of_get_property(np, propnames[2], NULL);
	lsizep = of_get_property(np, propnames[3], NULL);
	if (bsizep == NULL)
		bsizep = lsizep;
	if (lsizep != NULL)
		lsize = be32_to_cpu(*lsizep);
	if (bsizep != NULL)
		bsize = be32_to_cpu(*bsizep);
	if (sizep == NULL || bsizep == NULL || lsizep == NULL)
		success = false;

	/*
	 * OF is weird .. it represents fully associative caches
	 * as "1 way" which doesn't make much sense and doesn't
	 * leave room for direct mapped. We'll assume that 0
	 * in OF means direct mapped for that reason.
	 */
	if (sets == 1)
		sets = 0;
	else if (sets == 0)
		sets = 1;

	init_cache_info(info, size, lsize, bsize, sets);

	return success;
}

void __init initialize_cache_info(void)
{
	struct device_node *cpu = NULL, *l2, *l3 = NULL;
	u32 pvr;

	DBG(" -> initialize_cache_info()\n");

	/*
	 * All shipping POWER8 machines have a firmware bug that
	 * puts incorrect information in the device-tree. This will
	 * be (hopefully) fixed for future chips but for now hard
	 * code the values if we are running on one of these
	 */
	pvr = PVR_VER(mfspr(SPRN_PVR));
	if (pvr == PVR_POWER8 || pvr == PVR_POWER8E ||
	    pvr == PVR_POWER8NVL) {
						/* size    lsize   blk  sets */
		init_cache_info(&ppc64_caches.l1i, 0x8000,   128,  128, 32);
		init_cache_info(&ppc64_caches.l1d, 0x10000,  128,  128, 64);
		init_cache_info(&ppc64_caches.l2,  0x80000,  128,  0,   512);
		init_cache_info(&ppc64_caches.l3,  0x800000, 128,  0,   8192);
	} else
		cpu = of_find_node_by_type(NULL, "cpu");

	/*
	 * We're assuming *all* of the CPUs have the same
	 * d-cache and i-cache sizes... -Peter
	 */
	if (cpu) {
		if (!parse_cache_info(cpu, false, &ppc64_caches.l1d))
			DBG("Argh, can't find dcache properties !\n");

		if (!parse_cache_info(cpu, true, &ppc64_caches.l1i))
			DBG("Argh, can't find icache properties !\n");

		/*
		 * Try to find the L2 and L3 if any. Assume they are
		 * unified and use the D-side properties.
		 */
		l2 = of_find_next_cache_node(cpu);
		of_node_put(cpu);
		if (l2) {
			parse_cache_info(l2, false, &ppc64_caches.l2);
			l3 = of_find_next_cache_node(l2);
			of_node_put(l2);
		}
		if (l3) {
			parse_cache_info(l3, false, &ppc64_caches.l3);
			of_node_put(l3);
		}
	}

	/* For use by binfmt_elf */
	dcache_bsize = ppc64_caches.l1d.block_size;
	icache_bsize = ppc64_caches.l1i.block_size;

	DBG(" <- initialize_cache_info()\n");
}

/* This returns the limit below which memory accesses to the linear
 * mapping are guarnateed not to cause a TLB or SLB miss. This is
 * used to allocate interrupt or emergency stacks for which our
 * exception entry path doesn't deal with being interrupted.
 */
static __init u64 safe_stack_limit(void)
{
#ifdef CONFIG_PPC_BOOK3E
	/* Freescale BookE bolts the entire linear mapping */
	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E))
		return linear_map_top;
	/* Other BookE, we assume the first GB is bolted */
	return 1ul << 30;
#else
	/* BookS, the first segment is bolted */
	if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
		return 1UL << SID_SHIFT_1T;
	return 1UL << SID_SHIFT;
#endif
}

void __init irqstack_early_init(void)
{
	u64 limit = safe_stack_limit();
	unsigned int i;

	/*
	 * Interrupt stacks must be in the first segment since we
	 * cannot afford to take SLB misses on them.
	 */
	for_each_possible_cpu(i) {
		softirq_ctx[i] = (struct thread_info *)
			__va(memblock_alloc_base(THREAD_SIZE,
					    THREAD_SIZE, limit));
		hardirq_ctx[i] = (struct thread_info *)
			__va(memblock_alloc_base(THREAD_SIZE,
					    THREAD_SIZE, limit));
	}
}

#ifdef CONFIG_PPC_BOOK3E
void __init exc_lvl_early_init(void)
{
	unsigned int i;
	unsigned long sp;

	for_each_possible_cpu(i) {
		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
		critirq_ctx[i] = (struct thread_info *)__va(sp);
		paca[i].crit_kstack = __va(sp + THREAD_SIZE);

		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
		dbgirq_ctx[i] = (struct thread_info *)__va(sp);
		paca[i].dbg_kstack = __va(sp + THREAD_SIZE);

		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
		mcheckirq_ctx[i] = (struct thread_info *)__va(sp);
		paca[i].mc_kstack = __va(sp + THREAD_SIZE);
	}

	if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC))
		patch_exception(0x040, exc_debug_debug_book3e);
}
#endif

/*
 * Stack space used when we detect a bad kernel stack pointer, and
 * early in SMP boots before relocation is enabled. Exclusive emergency
 * stack for machine checks.
 */
void __init emergency_stack_init(void)
{
	u64 limit;
	unsigned int i;

	/*
	 * Emergency stacks must be under 256MB, we cannot afford to take
	 * SLB misses on them. The ABI also requires them to be 128-byte
	 * aligned.
	 *
	 * Since we use these as temporary stacks during secondary CPU
	 * bringup, we need to get at them in real mode. This means they
	 * must also be within the RMO region.
	 */
	limit = min(safe_stack_limit(), ppc64_rma_size);

	for_each_possible_cpu(i) {
		struct thread_info *ti;
		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
		klp_init_thread_info(ti);
		paca[i].emergency_sp = (void *)ti + THREAD_SIZE;

#ifdef CONFIG_PPC_BOOK3S_64
		/* emergency stack for machine check exception handling. */
		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
		klp_init_thread_info(ti);
		paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE;
#endif
	}
}

#ifdef CONFIG_SMP
#define PCPU_DYN_SIZE		()

static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
{
	return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align,
				    __pa(MAX_DMA_ADDRESS));
}

static void __init pcpu_fc_free(void *ptr, size_t size)
{
	free_bootmem(__pa(ptr), size);
}

static int pcpu_cpu_distance(unsigned int from, unsigned int to)
{
	if (cpu_to_node(from) == cpu_to_node(to))
		return LOCAL_DISTANCE;
	else
		return REMOTE_DISTANCE;
}

unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(__per_cpu_offset);

void __init setup_per_cpu_areas(void)
{
	const size_t dyn_size = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE;
	size_t atom_size;
	unsigned long delta;
	unsigned int cpu;
	int rc;

	/*
	 * Linear mapping is one of 4K, 1M and 16M.  For 4K, no need
	 * to group units.  For larger mappings, use 1M atom which
	 * should be large enough to contain a number of units.
	 */
	if (mmu_linear_psize == MMU_PAGE_4K)
		atom_size = PAGE_SIZE;
	else
		atom_size = 1 << 20;

	rc = pcpu_embed_first_chunk(0, dyn_size, atom_size, pcpu_cpu_distance,
				    pcpu_fc_alloc, pcpu_fc_free);
	if (rc < 0)
		panic("cannot initialize percpu area (err=%d)", rc);

	delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
	for_each_possible_cpu(cpu) {
                __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
		paca[cpu].data_offset = __per_cpu_offset[cpu];
	}
}
#endif

#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
unsigned long memory_block_size_bytes(void)
{
	if (ppc_md.memory_block_size)
		return ppc_md.memory_block_size();

	return MIN_MEMORY_BLOCK_SIZE;
}
#endif

#if defined(CONFIG_PPC_INDIRECT_PIO) || defined(CONFIG_PPC_INDIRECT_MMIO)
struct ppc_pci_io ppc_pci_io;
EXPORT_SYMBOL(ppc_pci_io);
#endif

#ifdef CONFIG_HARDLOCKUP_DETECTOR
u64 hw_nmi_get_sample_period(int watchdog_thresh)
{
	return ppc_proc_freq * watchdog_thresh;
}

/*
 * The hardlockup detector breaks PMU event based branches and is likely
 * to get false positives in KVM guests, so disable it by default.
 */
static int __init disable_hardlockup_detector(void)
{
	hardlockup_detector_disable();

	return 0;
}
early_initcall(disable_hardlockup_detector);
#endif
ffstat' width='100%'> -rw-r--r--arch/blackfin/kernel/cplb-mpu/Makefile6
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cacheinit.c4
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbinfo.c136
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbinit.c50
-rw-r--r--arch/blackfin/kernel/cplb-mpu/cplbmgr.c119
-rw-r--r--arch/blackfin/kernel/cplb-nompu/Makefile8
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cacheinit.c25
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbhdlr.S130
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbinfo.c195
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbinit.c521
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbmgr.S646
-rw-r--r--arch/blackfin/kernel/cplb-nompu/cplbmgr.c287
-rw-r--r--arch/blackfin/kernel/cplbinfo.c177
-rw-r--r--arch/blackfin/kernel/early_printk.c4
-rw-r--r--arch/blackfin/kernel/entry.S5
-rw-r--r--arch/blackfin/kernel/fixed_code.S6
-rw-r--r--arch/blackfin/kernel/init_task.c1
-rw-r--r--arch/blackfin/kernel/ipipe.c428
-rw-r--r--arch/blackfin/kernel/irqchip.c48
-rw-r--r--arch/blackfin/kernel/kgdb.c127
-rw-r--r--arch/blackfin/kernel/kgdb_test.c123
-rw-r--r--arch/blackfin/kernel/mcount.S70
-rw-r--r--arch/blackfin/kernel/module.c152
-rw-r--r--arch/blackfin/kernel/process.c32
-rw-r--r--arch/blackfin/kernel/ptrace.c23
-rw-r--r--arch/blackfin/kernel/reboot.c26
-rw-r--r--arch/blackfin/kernel/setup.c230
-rw-r--r--arch/blackfin/kernel/time-ts.c2
-rw-r--r--arch/blackfin/kernel/time.c162
-rw-r--r--arch/blackfin/kernel/traps.c125
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S9
-rw-r--r--arch/blackfin/lib/checksum.c4
-rw-r--r--arch/blackfin/lib/ins.S272
-rw-r--r--arch/blackfin/lib/muldi3.S68
-rw-r--r--arch/blackfin/lib/muldi3.c99
-rw-r--r--arch/blackfin/mach-bf518/Kconfig233
-rw-r--r--arch/blackfin/mach-bf518/Makefile5
-rw-r--r--arch/blackfin/mach-bf518/boards/Kconfig12
-rw-r--r--arch/blackfin/mach-bf518/boards/Makefile5
-rw-r--r--arch/blackfin/mach-bf518/boards/ezbrd.c714
-rw-r--r--arch/blackfin/mach-bf518/dma.c118
-rw-r--r--arch/blackfin/mach-bf518/include/mach/anomaly.h79
-rw-r--r--arch/blackfin/mach-bf518/include/mach/bf518.h132
-rw-r--r--arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h169
-rw-r--r--arch/blackfin/mach-bf518/include/mach/blackfin.h105
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF512.h46
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF514.h48
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF516.h213
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF518.h282
-rw-r--r--arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h1208
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF512.h42
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF514.h113
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF516.h490
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF518.h651
-rw-r--r--arch/blackfin/mach-bf518/include/mach/defBF51x_base.h1940
-rw-r--r--arch/blackfin/mach-bf518/include/mach/dma.h33
-rw-r--r--arch/blackfin/mach-bf518/include/mach/gpio.h60
-rw-r--r--arch/blackfin/mach-bf518/include/mach/irq.h260
-rw-r--r--arch/blackfin/mach-bf518/include/mach/mem_map.h108
-rw-r--r--arch/blackfin/mach-bf518/include/mach/portmux.h190
-rw-r--r--arch/blackfin/mach-bf518/ints-priority.c99
-rw-r--r--arch/blackfin/mach-bf527/Kconfig34
-rw-r--r--arch/blackfin/mach-bf527/Makefile2
-rw-r--r--arch/blackfin/mach-bf527/boards/cm_bf527.c129
-rw-r--r--arch/blackfin/mach-bf527/boards/ezbrd.c108
-rw-r--r--arch/blackfin/mach-bf527/boards/ezkit.c194
-rw-r--r--arch/blackfin/mach-bf527/dma.c2
-rw-r--r--arch/blackfin/mach-bf527/head.S146
-rw-r--r--arch/blackfin/mach-bf527/include/mach/anomaly.h10
-rw-r--r--arch/blackfin/mach-bf527/include/mach/bf527.h8
-rw-r--r--arch/blackfin/mach-bf527/include/mach/bfin_sir.h142
-rw-r--r--arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h102
-rw-r--r--arch/blackfin/mach-bf527/include/mach/dma.h32
-rw-r--r--arch/blackfin/mach-bf527/include/mach/gpio.h68
-rw-r--r--arch/blackfin/mach-bf527/include/mach/irq.h32
-rw-r--r--arch/blackfin/mach-bf527/include/mach/mem_map.h6
-rw-r--r--arch/blackfin/mach-bf527/include/mach/portmux.h2
-rw-r--r--arch/blackfin/mach-bf527/ints-priority.c16
-rw-r--r--arch/blackfin/mach-bf533/Kconfig2
-rw-r--r--arch/blackfin/mach-bf533/Makefile2
-rw-r--r--arch/blackfin/mach-bf533/boards/H8606.c24
-rw-r--r--arch/blackfin/mach-bf533/boards/blackstamp.c28
-rw-r--r--arch/blackfin/mach-bf533/boards/cm_bf533.c39
-rw-r--r--arch/blackfin/mach-bf533/boards/ezkit.c26
-rw-r--r--arch/blackfin/mach-bf533/boards/generic_board.c35
-rw-r--r--arch/blackfin/mach-bf533/boards/ip0x.c24
-rw-r--r--arch/blackfin/mach-bf533/boards/stamp.c62
-rw-r--r--arch/blackfin/mach-bf533/dma.c2
-rw-r--r--arch/blackfin/mach-bf533/head.S137
-rw-r--r--arch/blackfin/mach-bf533/include/mach/anomaly.h11
-rw-r--r--arch/blackfin/mach-bf533/include/mach/bf533.h4
-rw-r--r--arch/blackfin/mach-bf533/include/mach/bfin_sir.h125
-rw-r--r--arch/blackfin/mach-bf533/include/mach/blackfin.h7
-rw-r--r--arch/blackfin/mach-bf533/include/mach/cdefBF532.h177
-rw-r--r--arch/blackfin/mach-bf533/include/mach/dma.h40
-rw-r--r--arch/blackfin/mach-bf533/include/mach/gpio.h34
-rw-r--r--arch/blackfin/mach-bf533/include/mach/irq.h14
-rw-r--r--arch/blackfin/mach-bf533/include/mach/mem_init.h297
-rw-r--r--arch/blackfin/mach-bf533/include/mach/mem_map.h6
-rw-r--r--arch/blackfin/mach-bf533/include/mach/portmux.h5
-rw-r--r--arch/blackfin/mach-bf537/Kconfig34
-rw-r--r--arch/blackfin/mach-bf537/Makefile2
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537.c69
-rw-r--r--arch/blackfin/mach-bf537/boards/generic_board.c121
-rw-r--r--arch/blackfin/mach-bf537/boards/minotaur.c56
-rw-r--r--arch/blackfin/mach-bf537/boards/pnav10.c60
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c294
-rw-r--r--arch/blackfin/mach-bf537/boards/tcm_bf537.c73
-rw-r--r--arch/blackfin/mach-bf537/dma.c2
-rw-r--r--arch/blackfin/mach-bf537/head.S146
-rw-r--r--arch/blackfin/mach-bf537/include/mach/anomaly.h13
-rw-r--r--arch/blackfin/mach-bf537/include/mach/bf537.h2
-rw-r--r--arch/blackfin/mach-bf537/include/mach/bfin_sir.h142
-rw-r--r--arch/blackfin/mach-bf537/include/mach/blackfin.h2
-rw-r--r--arch/blackfin/mach-bf537/include/mach/cdefBF534.h91
-rw-r--r--arch/blackfin/mach-bf537/include/mach/dma.h32
-rw-r--r--arch/blackfin/mach-bf537/include/mach/gpio.h68
-rw-r--r--arch/blackfin/mach-bf537/include/mach/irq.h32
-rw-r--r--arch/blackfin/mach-bf537/include/mach/mem_init.h303
-rw-r--r--arch/blackfin/mach-bf537/include/mach/mem_map.h6
-rw-r--r--arch/blackfin/mach-bf537/include/mach/portmux.h1
-rw-r--r--arch/blackfin/mach-bf537/ints-priority.c16
-rw-r--r--arch/blackfin/mach-bf538/Kconfig164
-rw-r--r--arch/blackfin/mach-bf538/Makefile5
-rw-r--r--arch/blackfin/mach-bf538/boards/Kconfig12
-rw-r--r--arch/blackfin/mach-bf538/boards/Makefile5
-rw-r--r--arch/blackfin/mach-bf538/boards/ezkit.c606
-rw-r--r--arch/blackfin/mach-bf538/dma.c161
-rw-r--r--arch/blackfin/mach-bf538/include/mach/anomaly.h132
-rw-r--r--arch/blackfin/mach-bf538/include/mach/bf538.h124
-rw-r--r--arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h183
-rw-r--r--arch/blackfin/mach-bf538/include/mach/blackfin.h101
-rw-r--r--arch/blackfin/mach-bf538/include/mach/cdefBF538.h2108
-rw-r--r--arch/blackfin/mach-bf538/include/mach/cdefBF539.h240
-rw-r--r--arch/blackfin/mach-bf538/include/mach/defBF539.h4243
-rw-r--r--arch/blackfin/mach-bf538/include/mach/dma.h41
-rw-r--r--arch/blackfin/mach-bf538/include/mach/gpio.h79
-rw-r--r--arch/blackfin/mach-bf538/include/mach/irq.h211
-rw-r--r--arch/blackfin/mach-bf538/include/mach/mem_map.h113
-rw-r--r--arch/blackfin/mach-bf538/include/mach/portmux.h107
-rw-r--r--arch/blackfin/mach-bf538/ints-priority.c94
-rw-r--r--arch/blackfin/mach-bf548/Kconfig2
-rw-r--r--arch/blackfin/mach-bf548/Makefile2
-rw-r--r--arch/blackfin/mach-bf548/boards/cm_bf548.c166
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c160
-rw-r--r--arch/blackfin/mach-bf548/dma.c2
-rw-r--r--arch/blackfin/mach-bf548/head.S158
-rw-r--r--arch/blackfin/mach-bf548/include/mach/anomaly.h6
-rw-r--r--arch/blackfin/mach-bf548/include/mach/bf548.h14
-rw-r--r--arch/blackfin/mach-bf548/include/mach/bfin_sir.h166
-rw-r--r--arch/blackfin/mach-bf548/include/mach/blackfin.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h114
-rw-r--r--arch/blackfin/mach-bf548/include/mach/dma.h32
-rw-r--r--arch/blackfin/mach-bf548/include/mach/gpio.h12
-rw-r--r--arch/blackfin/mach-bf548/include/mach/irq.h2
-rw-r--r--arch/blackfin/mach-bf548/include/mach/mem_init.h255
-rw-r--r--arch/blackfin/mach-bf548/include/mach/mem_map.h6
-rw-r--r--arch/blackfin/mach-bf548/include/mach/portmux.h1
-rw-r--r--arch/blackfin/mach-bf561/Kconfig8
-rw-r--r--arch/blackfin/mach-bf561/Makefile3
-rw-r--r--arch/blackfin/mach-bf561/atomic.S919
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c39
-rw-r--r--arch/blackfin/mach-bf561/boards/ezkit.c89
-rw-r--r--arch/blackfin/mach-bf561/boards/generic_board.c35
-rw-r--r--arch/blackfin/mach-bf561/boards/tepla.c34
-rw-r--r--arch/blackfin/mach-bf561/dma.c2
-rw-r--r--arch/blackfin/mach-bf561/head.S136
-rw-r--r--arch/blackfin/mach-bf561/include/mach/anomaly.h16
-rw-r--r--arch/blackfin/mach-bf561/include/mach/bf561.h2
-rw-r--r--arch/blackfin/mach-bf561/include/mach/bfin_sir.h125
-rw-r--r--arch/blackfin/mach-bf561/include/mach/blackfin.h4
-rw-r--r--arch/blackfin/mach-bf561/include/mach/cdefBF561.h103
-rw-r--r--arch/blackfin/mach-bf561/include/mach/defBF561.h5
-rw-r--r--arch/blackfin/mach-bf561/include/mach/dma.h16
-rw-r--r--arch/blackfin/mach-bf561/include/mach/gpio.h68
-rw-r--r--arch/blackfin/mach-bf561/include/mach/mem_init.h295
-rw-r--r--arch/blackfin/mach-bf561/include/mach/mem_map.h80
-rw-r--r--arch/blackfin/mach-bf561/include/mach/portmux.h1
-rw-r--r--arch/blackfin/mach-bf561/include/mach/smp.h22
-rw-r--r--arch/blackfin/mach-bf561/secondary.S215
-rw-r--r--arch/blackfin/mach-bf561/smp.c167
-rw-r--r--arch/blackfin/mach-common/Makefile4
-rw-r--r--arch/blackfin/mach-common/cache-c.c24
-rw-r--r--arch/blackfin/mach-common/cache.S6
-rw-r--r--arch/blackfin/mach-common/clocks-init.c94
-rw-r--r--arch/blackfin/mach-common/cpufreq.c6
-rw-r--r--arch/blackfin/mach-common/dpmc_modes.S3
-rw-r--r--arch/blackfin/mach-common/entry.S141
-rw-r--r--arch/blackfin/mach-common/head.S163
-rw-r--r--arch/blackfin/mach-common/interrupt.S82
-rw-r--r--arch/blackfin/mach-common/ints-priority.c546
-rw-r--r--arch/blackfin/mach-common/irqpanic.c12
-rw-r--r--arch/blackfin/mach-common/lock.S4
-rw-r--r--arch/blackfin/mach-common/pm.c25
-rw-r--r--arch/blackfin/mach-common/smp.c476
-rw-r--r--arch/blackfin/mm/init.c50
-rw-r--r--arch/blackfin/mm/sram-alloc.c339
-rw-r--r--arch/blackfin/oprofile/Makefile3
-rw-r--r--arch/blackfin/oprofile/bfin_oprofile.c18
-rw-r--r--arch/blackfin/oprofile/common.c168
-rw-r--r--arch/blackfin/oprofile/op_blackfin.h98
-rw-r--r--arch/blackfin/oprofile/op_model_bf533.c161
-rw-r--r--arch/blackfin/oprofile/timer_int.c73
-rw-r--r--arch/cris/Kconfig2
-rw-r--r--arch/cris/arch-v10/kernel/entry.S2
-rw-r--r--arch/cris/arch-v32/drivers/iop_fw_load.c6
-rw-r--r--arch/cris/arch-v32/kernel/entry.S2
-rw-r--r--arch/cris/arch-v32/kernel/irq.c4
-rw-r--r--arch/cris/arch-v32/kernel/signal.c2
-rw-r--r--arch/cris/arch-v32/kernel/smp.c4
-rw-r--r--arch/cris/include/arch-v10/arch/swab.h (renamed from arch/cris/include/arch-v10/arch/byteorder.h)16
-rw-r--r--arch/cris/include/arch-v32/arch/byteorder.h20
-rw-r--r--arch/cris/include/arch-v32/arch/swab.h24
-rw-r--r--arch/cris/include/asm/atomic.h4
-rw-r--r--arch/cris/include/asm/bitops.h1
-rw-r--r--arch/cris/include/asm/byteorder.h19
-rw-r--r--arch/cris/include/asm/smp.h1
-rw-r--r--arch/cris/include/asm/swab.h8
-rw-r--r--arch/cris/kernel/process.c1
-rw-r--r--arch/frv/kernel/init_task.c1
-rw-r--r--arch/frv/kernel/ptrace.c11
-rw-r--r--arch/h8300/Kconfig2
-rw-r--r--arch/h8300/include/asm/atomic.h3
-rw-r--r--arch/h8300/include/asm/bitops.h1
-rw-r--r--arch/h8300/include/asm/byteorder.h7
-rw-r--r--arch/h8300/include/asm/mmu.h1
-rw-r--r--arch/h8300/include/asm/swab.h10
-rw-r--r--arch/h8300/kernel/init_task.c1
-rw-r--r--arch/h8300/kernel/syscalls.S2
-rw-r--r--arch/ia64/Kconfig4
-rw-r--r--arch/ia64/configs/bigsur_defconfig2
-rw-r--r--arch/ia64/configs/generic_defconfig2
-rw-r--r--arch/ia64/configs/zx1_defconfig2
-rw-r--r--arch/ia64/hp/common/sba_iommu.c12
-rw-r--r--arch/ia64/hp/sim/hpsim_irq.c2
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/include/asm/acpi-ext.h1
-rw-r--r--arch/ia64/include/asm/atomic.h6
-rw-r--r--arch/ia64/include/asm/byteorder.h36
-rw-r--r--arch/ia64/include/asm/dma-mapping.h2
-rw-r--r--arch/ia64/include/asm/irq.h2
-rw-r--r--arch/ia64/include/asm/kvm.h6
-rw-r--r--arch/ia64/include/asm/kvm_host.h198
-rw-r--r--arch/ia64/include/asm/machvec.h7
-rw-r--r--arch/ia64/include/asm/machvec_init.h1
-rw-r--r--arch/ia64/include/asm/machvec_sn2.h2
-rw-r--r--arch/ia64/include/asm/smp.h1
-rw-r--r--arch/ia64/include/asm/sn/acpi.h2
-rw-r--r--arch/ia64/include/asm/swab.h34
-rw-r--r--arch/ia64/include/asm/swiotlb.h39
-rw-r--r--arch/ia64/include/asm/topology.h11
-rw-r--r--arch/ia64/include/asm/unistd.h2
-rw-r--r--arch/ia64/kernel/acpi.c4
-rw-r--r--arch/ia64/kernel/entry.S2
-rw-r--r--arch/ia64/kernel/init_task.c1
-rw-r--r--arch/ia64/kernel/iosapic.c35
-rw-r--r--arch/ia64/kernel/irq.c26
-rw-r--r--arch/ia64/kernel/kprobes.c12
-rw-r--r--arch/ia64/kernel/msi_ia64.c12
-rw-r--r--arch/ia64/kernel/pci-dma.c2
-rw-r--r--arch/ia64/kernel/smpboot.c10
-rw-r--r--arch/ia64/kernel/sys_ia64.c2
-rw-r--r--arch/ia64/kernel/time.c18
-rw-r--r--arch/ia64/kernel/topology.c2
-rw-r--r--arch/ia64/kernel/unaligned.c6
-rw-r--r--arch/ia64/kvm/Makefile6
-rw-r--r--arch/ia64/kvm/asm-offsets.c11
-rw-r--r--arch/ia64/kvm/kvm-ia64.c110
-rw-r--r--arch/ia64/kvm/kvm_lib.c15
-rw-r--r--arch/ia64/kvm/kvm_minstate.h4
-rw-r--r--arch/ia64/kvm/misc.h3
-rw-r--r--arch/ia64/kvm/mmio.c38
-rw-r--r--arch/ia64/kvm/process.c29
-rw-r--r--arch/ia64/kvm/vcpu.c76
-rw-r--r--arch/ia64/kvm/vcpu.h5
-rw-r--r--arch/ia64/kvm/vmm.c29
-rw-r--r--arch/ia64/kvm/vmm_ivt.S1469
-rw-r--r--arch/ia64/kvm/vtlb.c4
-rw-r--r--arch/ia64/mm/init.c2
-rw-r--r--arch/ia64/pci/pci.c27
-rw-r--r--arch/ia64/sn/kernel/io_acpi_init.c103
-rw-r--r--arch/ia64/sn/kernel/io_common.c5
-rw-r--r--arch/ia64/sn/kernel/irq.c6
-rw-r--r--arch/ia64/sn/kernel/msi_sn.c7
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c27
-rw-r--r--arch/ia64/sn/kernel/tiocx.c3
-rw-r--r--arch/ia64/sn/pci/pci_dma.c6
-rw-r--r--arch/ia64/xen/time.c4
-rw-r--r--arch/m32r/Kconfig1
-rw-r--r--arch/m32r/configs/m32104ut_defconfig2
-rw-r--r--arch/m32r/kernel/init_task.c1
-rw-r--r--arch/m32r/kernel/smpboot.c8
-rw-r--r--arch/m68k/Kconfig3
-rw-r--r--arch/m68k/amiga/amiints.c12
-rw-r--r--arch/m68k/amiga/cia.c4
-rw-r--r--arch/m68k/amiga/config.c3
-rw-r--r--arch/m68k/apollo/config.c7
-rw-r--r--arch/m68k/atari/atakeyb.c10
-rw-r--r--arch/m68k/atari/stdma.c5
-rw-r--r--arch/m68k/atari/time.c5
-rw-r--r--arch/m68k/bvme6000/config.c1
-rw-r--r--arch/m68k/hp300/time.c3
-rw-r--r--arch/m68k/include/asm/Kbuild (renamed from include/asm-m68k/Kbuild)0
-rw-r--r--arch/m68k/include/asm/MC68328.h (renamed from arch/m68knommu/include/asm/MC68328.h)0
-rw-r--r--arch/m68k/include/asm/MC68332.h (renamed from arch/m68knommu/include/asm/MC68332.h)0
-rw-r--r--arch/m68k/include/asm/MC68EZ328.h (renamed from arch/m68knommu/include/asm/MC68EZ328.h)0
-rw-r--r--arch/m68k/include/asm/MC68VZ328.h (renamed from arch/m68knommu/include/asm/MC68VZ328.h)0
-rw-r--r--arch/m68k/include/asm/a.out-core.h (renamed from include/asm-m68k/a.out-core.h)0
-rw-r--r--arch/m68k/include/asm/a.out.h (renamed from include/asm-m68k/a.out.h)0
-rw-r--r--arch/m68k/include/asm/adb_iop.h (renamed from include/asm-m68k/adb_iop.h)0
-rw-r--r--arch/m68k/include/asm/amigahw.h (renamed from include/asm-m68k/amigahw.h)0
-rw-r--r--arch/m68k/include/asm/amigaints.h (renamed from include/asm-m68k/amigaints.h)0
-rw-r--r--arch/m68k/include/asm/amigayle.h (renamed from include/asm-m68k/amigayle.h)0
-rw-r--r--arch/m68k/include/asm/amipcmcia.h (renamed from include/asm-m68k/amipcmcia.h)0
-rw-r--r--arch/m68k/include/asm/anchor.h (renamed from arch/m68knommu/include/asm/anchor.h)0
-rw-r--r--arch/m68k/include/asm/apollodma.h (renamed from include/asm-m68k/apollodma.h)0
-rw-r--r--arch/m68k/include/asm/apollohw.h (renamed from include/asm-m68k/apollohw.h)0
-rw-r--r--arch/m68k/include/asm/atafd.h (renamed from include/asm-m68k/atafd.h)0
-rw-r--r--arch/m68k/include/asm/atafdreg.h (renamed from include/asm-m68k/atafdreg.h)0
-rw-r--r--arch/m68k/include/asm/atari_joystick.h (renamed from include/asm-m68k/atari_joystick.h)0
-rw-r--r--arch/m68k/include/asm/atari_stdma.h (renamed from include/asm-m68k/atari_stdma.h)0
-rw-r--r--arch/m68k/include/asm/atari_stram.h (renamed from include/asm-m68k/atari_stram.h)0
-rw-r--r--arch/m68k/include/asm/atarihw.h (renamed from include/asm-m68k/atarihw.h)0
-rw-r--r--arch/m68k/include/asm/atariints.h (renamed from include/asm-m68k/atariints.h)0
-rw-r--r--arch/m68k/include/asm/atarikb.h (renamed from include/asm-m68k/atarikb.h)0
-rw-r--r--arch/m68k/include/asm/atomic.h5
-rw-r--r--arch/m68k/include/asm/atomic_mm.h (renamed from include/asm-m68k/atomic.h)3
-rw-r--r--arch/m68k/include/asm/atomic_no.h (renamed from arch/m68knommu/include/asm/atomic.h)2
-rw-r--r--arch/m68k/include/asm/auxvec.h (renamed from arch/m68knommu/include/asm/auxvec.h)0
-rw-r--r--arch/m68k/include/asm/bitops.h5
-rw-r--r--arch/m68k/include/asm/bitops_mm.h (renamed from include/asm-m68k/bitops.h)5
-rw-r--r--arch/m68k/include/asm/bitops_no.h (renamed from arch/m68knommu/include/asm/bitops.h)1
-rw-r--r--arch/m68k/include/asm/blinken.h (renamed from include/asm-m68k/blinken.h)0
-rw-r--r--arch/m68k/include/asm/bootinfo.h5
-rw-r--r--arch/m68k/include/asm/bootinfo_mm.h (renamed from include/asm-m68k/bootinfo.h)0
-rw-r--r--arch/m68k/include/asm/bootinfo_no.h (renamed from arch/m68knommu/include/asm/bootinfo.h)0
-rw-r--r--arch/m68k/include/asm/bootstd.h (renamed from arch/m68knommu/include/asm/bootstd.h)0
-rw-r--r--arch/m68k/include/asm/bug.h5
-rw-r--r--arch/m68k/include/asm/bug_mm.h (renamed from include/asm-m68k/bug.h)0
-rw-r--r--arch/m68k/include/asm/bug_no.h (renamed from arch/m68knommu/include/asm/bug.h)0
-rw-r--r--arch/m68k/include/asm/bugs.h5
-rw-r--r--arch/m68k/include/asm/bugs_mm.h (renamed from include/asm-m68k/bugs.h)0
-rw-r--r--arch/m68k/include/asm/bugs_no.h (renamed from arch/m68knommu/include/asm/bugs.h)0
-rw-r--r--arch/m68k/include/asm/bvme6000hw.h (renamed from include/asm-m68k/bvme6000hw.h)0
-rw-r--r--arch/m68k/include/asm/byteorder.h6
-rw-r--r--arch/m68k/include/asm/cache.h5
-rw-r--r--arch/m68k/include/asm/cache_mm.h (renamed from include/asm-m68k/cache.h)0
-rw-r--r--arch/m68k/include/asm/cache_no.h (renamed from arch/m68knommu/include/asm/cache.h)0
-rw-r--r--arch/m68k/include/asm/cachectl.h (renamed from include/asm-m68k/cachectl.h)0
-rw-r--r--arch/m68k/include/asm/cacheflush.h5
-rw-r--r--arch/m68k/include/asm/cacheflush_mm.h (renamed from include/asm-m68k/cacheflush.h)0
-rw-r--r--arch/m68k/include/asm/cacheflush_no.h (renamed from arch/m68knommu/include/asm/cacheflush.h)11
-rw-r--r--arch/m68k/include/asm/checksum.h5
-rw-r--r--arch/m68k/include/asm/checksum_mm.h (renamed from include/asm-m68k/checksum.h)0
-rw-r--r--arch/m68k/include/asm/checksum_no.h (renamed from arch/m68knommu/include/asm/checksum.h)0
-rw-r--r--arch/m68k/include/asm/coldfire.h (renamed from arch/m68knommu/include/asm/coldfire.h)0
-rw-r--r--arch/m68k/include/asm/commproc.h (renamed from arch/m68knommu/include/asm/commproc.h)0
-rw-r--r--arch/m68k/include/asm/contregs.h (renamed from include/asm-m68k/contregs.h)0
-rw-r--r--arch/m68k/include/asm/cputime.h (renamed from include/asm-m68k/cputime.h)0
-rw-r--r--arch/m68k/include/asm/current.h5
-rw-r--r--arch/m68k/include/asm/current_mm.h (renamed from include/asm-m68k/current.h)0
-rw-r--r--arch/m68k/include/asm/current_no.h (renamed from arch/m68knommu/include/asm/current.h)0
-rw-r--r--arch/m68k/include/asm/dbg.h (renamed from arch/m68knommu/include/asm/dbg.h)0
-rw-r--r--arch/m68k/include/asm/delay.h5
-rw-r--r--arch/m68k/include/asm/delay_mm.h (renamed from include/asm-m68k/delay.h)0
-rw-r--r--arch/m68k/include/asm/delay_no.h (renamed from arch/m68knommu/include/asm/delay.h)0
-rw-r--r--arch/m68k/include/asm/device.h (renamed from arch/m68knommu/include/asm/device.h)0
-rw-r--r--arch/m68k/include/asm/div64.h5
-rw-r--r--arch/m68k/include/asm/div64_mm.h (renamed from include/asm-m68k/div64.h)0
-rw-r--r--arch/m68k/include/asm/div64_no.h (renamed from arch/m68knommu/include/asm/div64.h)0
-rw-r--r--arch/m68k/include/asm/dma-mapping.h5
-rw-r--r--arch/m68k/include/asm/dma-mapping_mm.h (renamed from include/asm-m68k/dma-mapping.h)0
-rw-r--r--arch/m68k/include/asm/dma-mapping_no.h (renamed from arch/m68knommu/include/asm/dma-mapping.h)4
-rw-r--r--arch/m68k/include/asm/dma.h5
-rw-r--r--arch/m68k/include/asm/dma_mm.h (renamed from include/asm-m68k/dma.h)0
-rw-r--r--arch/m68k/include/asm/dma_no.h (renamed from arch/m68knommu/include/asm/dma.h)0
-rw-r--r--arch/m68k/include/asm/dsp56k.h (renamed from include/asm-m68k/dsp56k.h)0
-rw-r--r--arch/m68k/include/asm/dvma.h (renamed from include/asm-m68k/dvma.h)0
-rw-r--r--arch/m68k/include/asm/elf.h5
-rw-r--r--arch/m68k/include/asm/elf_mm.h (renamed from include/asm-m68k/elf.h)0
-rw-r--r--arch/m68k/include/asm/elf_no.h (renamed from arch/m68knommu/include/asm/elf.h)0
-rw-r--r--arch/m68k/include/asm/elia.h (renamed from arch/m68knommu/include/asm/elia.h)0
-rw-r--r--arch/m68k/include/asm/emergency-restart.h (renamed from arch/m68knommu/include/asm/emergency-restart.h)0
-rw-r--r--arch/m68k/include/asm/entry.h5
-rw-r--r--arch/m68k/include/asm/entry_mm.h (renamed from include/asm-m68k/entry.h)0
-rw-r--r--arch/m68k/include/asm/entry_no.h (renamed from arch/m68knommu/include/asm/entry.h)0
-rw-r--r--arch/m68k/include/asm/errno.h (renamed from include/asm-m68k/errno.h)0
-rw-r--r--arch/m68k/include/asm/fb.h5
-rw-r--r--arch/m68k/include/asm/fb_mm.h (renamed from include/asm-m68k/fb.h)0
-rw-r--r--arch/m68k/include/asm/fb_no.h (renamed from arch/m68knommu/include/asm/fb.h)0
-rw-r--r--arch/m68k/include/asm/fbio.h (renamed from include/asm-m68k/fbio.h)0
-rw-r--r--arch/m68k/include/asm/fcntl.h (renamed from include/asm-m68k/fcntl.h)0
-rw-r--r--arch/m68k/include/asm/flat.h (renamed from arch/m68knommu/include/asm/flat.h)0
-rw-r--r--arch/m68k/include/asm/floppy.h (renamed from include/asm-m68k/floppy.h)0
-rw-r--r--arch/m68k/include/asm/fpu.h5
-rw-r--r--arch/m68k/include/asm/fpu_mm.h (renamed from include/asm-m68k/fpu.h)0
-rw-r--r--arch/m68k/include/asm/fpu_no.h (renamed from arch/m68knommu/include/asm/fpu.h)0
-rw-r--r--arch/m68k/include/asm/futex.h (renamed from arch/m68knommu/include/asm/futex.h)0
-rw-r--r--arch/m68k/include/asm/hardirq.h5
-rw-r--r--arch/m68k/include/asm/hardirq_mm.h (renamed from include/asm-m68k/hardirq.h)0
-rw-r--r--arch/m68k/include/asm/hardirq_no.h (renamed from arch/m68knommu/include/asm/hardirq.h)0
-rw-r--r--arch/m68k/include/asm/hp300hw.h (renamed from include/asm-m68k/hp300hw.h)0
-rw-r--r--arch/m68k/include/asm/hw_irq.h5
-rw-r--r--arch/m68k/include/asm/hw_irq_mm.h (renamed from include/asm-m68k/hw_irq.h)0
-rw-r--r--arch/m68k/include/asm/hw_irq_no.h (renamed from arch/m68knommu/include/asm/hw_irq.h)0
-rw-r--r--arch/m68k/include/asm/hwtest.h (renamed from include/asm-m68k/hwtest.h)0
-rw-r--r--arch/m68k/include/asm/ide.h (renamed from include/asm-m68k/ide.h)0
-rw-r--r--arch/m68k/include/asm/idprom.h (renamed from include/asm-m68k/idprom.h)0
-rw-r--r--arch/m68k/include/asm/intersil.h (renamed from include/asm-m68k/intersil.h)0
-rw-r--r--arch/m68k/include/asm/io.h5
-rw-r--r--arch/m68k/include/asm/io_mm.h (renamed from include/asm-m68k/io.h)0
-rw-r--r--arch/m68k/include/asm/io_no.h (renamed from arch/m68knommu/include/asm/io.h)0
-rw-r--r--arch/m68k/include/asm/ioctl.h (renamed from arch/m68knommu/include/asm/ioctl.h)0
-rw-r--r--arch/m68k/include/asm/ioctls.h (renamed from include/asm-m68k/ioctls.h)0
-rw-r--r--arch/m68k/include/asm/ipcbuf.h (renamed from include/asm-m68k/ipcbuf.h)0
-rw-r--r--arch/m68k/include/asm/irq.h5
-rw-r--r--arch/m68k/include/asm/irq_mm.h (renamed from include/asm-m68k/irq.h)0
-rw-r--r--arch/m68k/include/asm/irq_no.h (renamed from arch/m68knommu/include/asm/irq.h)0
-rw-r--r--arch/m68k/include/asm/irq_regs.h (renamed from arch/m68knommu/include/asm/irq_regs.h)0
-rw-r--r--arch/m68k/include/asm/kdebug.h (renamed from arch/m68knommu/include/asm/kdebug.h)0
-rw-r--r--arch/m68k/include/asm/kmap_types.h5
-rw-r--r--arch/m68k/include/asm/kmap_types_mm.h (renamed from include/asm-m68k/kmap_types.h)0
-rw-r--r--arch/m68k/include/asm/kmap_types_no.h (renamed from arch/m68knommu/include/asm/kmap_types.h)0
-rw-r--r--arch/m68k/include/asm/linkage.h (renamed from include/asm-m68k/linkage.h)0
-rw-r--r--arch/m68k/include/asm/local.h (renamed from include/asm-m68k/local.h)0
-rw-r--r--arch/m68k/include/asm/m5206sim.h (renamed from arch/m68knommu/include/asm/m5206sim.h)0
-rw-r--r--arch/m68k/include/asm/m520xsim.h (renamed from arch/m68knommu/include/asm/m520xsim.h)0
-rw-r--r--arch/m68k/include/asm/m523xsim.h (renamed from arch/m68knommu/include/asm/m523xsim.h)0
-rw-r--r--arch/m68k/include/asm/m5249sim.h (renamed from arch/m68knommu/include/asm/m5249sim.h)0
-rw-r--r--arch/m68k/include/asm/m5272sim.h (renamed from arch/m68knommu/include/asm/m5272sim.h)0
-rw-r--r--arch/m68k/include/asm/m527xsim.h (renamed from arch/m68knommu/include/asm/m527xsim.h)0
-rw-r--r--arch/m68k/include/asm/m528xsim.h (renamed from arch/m68knommu/include/asm/m528xsim.h)0
-rw-r--r--arch/m68k/include/asm/m5307sim.h (renamed from arch/m68knommu/include/asm/m5307sim.h)0
-rw-r--r--arch/m68k/include/asm/m532xsim.h (renamed from arch/m68knommu/include/asm/m532xsim.h)0
-rw-r--r--arch/m68k/include/asm/m5407sim.h (renamed from arch/m68knommu/include/asm/m5407sim.h)0
-rw-r--r--arch/m68k/include/asm/m68360.h (renamed from arch/m68knommu/include/asm/m68360.h)0
-rw-r--r--arch/m68k/include/asm/m68360_enet.h (renamed from arch/m68knommu/include/asm/m68360_enet.h)0
-rw-r--r--arch/m68k/include/asm/m68360_pram.h (renamed from arch/m68knommu/include/asm/m68360_pram.h)0
-rw-r--r--arch/m68k/include/asm/m68360_quicc.h (renamed from arch/m68knommu/include/asm/m68360_quicc.h)0
-rw-r--r--arch/m68k/include/asm/m68360_regs.h (renamed from arch/m68knommu/include/asm/m68360_regs.h)0
-rw-r--r--arch/m68k/include/asm/mac_asc.h (renamed from include/asm-m68k/mac_asc.h)0
-rw-r--r--arch/m68k/include/asm/mac_baboon.h (renamed from include/asm-m68k/mac_baboon.h)0
-rw-r--r--arch/m68k/include/asm/mac_iop.h (renamed from include/asm-m68k/mac_iop.h)0
-rw-r--r--arch/m68k/include/asm/mac_mouse.h (renamed from include/asm-m68k/mac_mouse.h)0
-rw-r--r--arch/m68k/include/asm/mac_oss.h (renamed from include/asm-m68k/mac_oss.h)0
-rw-r--r--arch/m68k/include/asm/mac_psc.h (renamed from include/asm-m68k/mac_psc.h)0
-rw-r--r--arch/m68k/include/asm/mac_via.h (renamed from include/asm-m68k/mac_via.h)0
-rw-r--r--arch/m68k/include/asm/machdep.h5
-rw-r--r--arch/m68k/include/asm/machdep_mm.h (renamed from include/asm-m68k/machdep.h)0
-rw-r--r--arch/m68k/include/asm/machdep_no.h (renamed from arch/m68knommu/include/asm/machdep.h)0
-rw-r--r--arch/m68k/include/asm/machines.h (renamed from include/asm-m68k/machines.h)0
-rw-r--r--arch/m68k/include/asm/machw.h (renamed from include/asm-m68k/machw.h)0
-rw-r--r--arch/m68k/include/asm/macintosh.h (renamed from include/asm-m68k/macintosh.h)0
-rw-r--r--arch/m68k/include/asm/macints.h (renamed from include/asm-m68k/macints.h)0
-rw-r--r--arch/m68k/include/asm/math-emu.h (renamed from include/asm-m68k/math-emu.h)0
-rw-r--r--arch/m68k/include/asm/mc146818rtc.h5
-rw-r--r--arch/m68k/include/asm/mc146818rtc_mm.h (renamed from include/asm-m68k/mc146818rtc.h)0
-rw-r--r--arch/m68k/include/asm/mc146818rtc_no.h (renamed from arch/m68knommu/include/asm/mc146818rtc.h)0
-rw-r--r--arch/m68k/include/asm/mcfcache.h (renamed from arch/m68knommu/include/asm/mcfcache.h)0
-rw-r--r--arch/m68k/include/asm/mcfdma.h (renamed from arch/m68knommu/include/asm/mcfdma.h)0
-rw-r--r--arch/m68k/include/asm/mcfmbus.h (renamed from arch/m68knommu/include/asm/mcfmbus.h)0
-rw-r--r--arch/m68k/include/asm/mcfne.h (renamed from arch/m68knommu/include/asm/mcfne.h)0
-rw-r--r--arch/m68k/include/asm/mcfpci.h (renamed from arch/m68knommu/include/asm/mcfpci.h)0
-rw-r--r--arch/m68k/include/asm/mcfpit.h (renamed from arch/m68knommu/include/asm/mcfpit.h)0
-rw-r--r--arch/m68k/include/asm/mcfsim.h (renamed from arch/m68knommu/include/asm/mcfsim.h)0
-rw-r--r--arch/m68k/include/asm/mcfsmc.h (renamed from arch/m68knommu/include/asm/mcfsmc.h)0
-rw-r--r--arch/m68k/include/asm/mcftimer.h (renamed from arch/m68knommu/include/asm/mcftimer.h)0
-rw-r--r--arch/m68k/include/asm/mcfuart.h (renamed from arch/m68knommu/include/asm/mcfuart.h)0
-rw-r--r--arch/m68k/include/asm/mcfwdebug.h (renamed from arch/m68knommu/include/asm/mcfwdebug.h)0
-rw-r--r--arch/m68k/include/asm/md.h (renamed from include/asm-m68k/md.h)0
-rw-r--r--arch/m68k/include/asm/mman.h (renamed from include/asm-m68k/mman.h)0
-rw-r--r--arch/m68k/include/asm/mmu.h5
-rw-r--r--arch/m68k/include/asm/mmu_context.h5
-rw-r--r--arch/m68k/include/asm/mmu_context_mm.h (renamed from include/asm-m68k/mmu_context.h)0
-rw-r--r--arch/m68k/include/asm/mmu_context_no.h (renamed from arch/m68knommu/include/asm/mmu_context.h)0
-rw-r--r--arch/m68k/include/asm/mmu_mm.h (renamed from include/asm-m68k/mmu.h)0
-rw-r--r--arch/m68k/include/asm/mmu_no.h (renamed from arch/m68knommu/include/asm/mmu.h)1
-rw-r--r--arch/m68k/include/asm/mmzone.h (renamed from include/asm-m68k/mmzone.h)0
-rw-r--r--arch/m68k/include/asm/module.h5
-rw-r--r--arch/m68k/include/asm/module_mm.h (renamed from include/asm-m68k/module.h)0
-rw-r--r--arch/m68k/include/asm/module_no.h (renamed from arch/m68knommu/include/asm/module.h)0
-rw-r--r--arch/m68k/include/asm/motorola_pgalloc.h (renamed from include/asm-m68k/motorola_pgalloc.h)0
-rw-r--r--arch/m68k/include/asm/motorola_pgtable.h (renamed from include/asm-m68k/motorola_pgtable.h)0
-rw-r--r--arch/m68k/include/asm/movs.h (renamed from include/asm-m68k/movs.h)0
-rw-r--r--arch/m68k/include/asm/msgbuf.h (renamed from include/asm-m68k/msgbuf.h)0
-rw-r--r--arch/m68k/include/asm/mutex.h (renamed from arch/m68knommu/include/asm/mutex.h)0
-rw-r--r--arch/m68k/include/asm/mvme147hw.h (renamed from include/asm-m68k/mvme147hw.h)0
-rw-r--r--arch/m68k/include/asm/mvme16xhw.h (renamed from include/asm-m68k/mvme16xhw.h)0
-rw-r--r--arch/m68k/include/asm/nettel.h (renamed from arch/m68knommu/include/asm/nettel.h)0
-rw-r--r--arch/m68k/include/asm/nubus.h (renamed from include/asm-m68k/nubus.h)0
-rw-r--r--arch/m68k/include/asm/openprom.h (renamed from include/asm-m68k/openprom.h)0
-rw-r--r--arch/m68k/include/asm/oplib.h (renamed from include/asm-m68k/oplib.h)0
-rw-r--r--arch/m68k/include/asm/page.h5
-rw-r--r--arch/m68k/include/asm/page_mm.h (renamed from include/asm-m68k/page.h)0
-rw-r--r--arch/m68k/include/asm/page_no.h (renamed from arch/m68knommu/include/asm/page.h)0
-rw-r--r--arch/m68k/include/asm/page_offset.h5
-rw-r--r--arch/m68k/include/asm/page_offset_mm.h (renamed from include/asm-m68k/page_offset.h)0
-rw-r--r--arch/m68k/include/asm/page_offset_no.h (renamed from arch/m68knommu/include/asm/page_offset.h)0
-rw-r--r--arch/m68k/include/asm/param.h5
-rw-r--r--arch/m68k/include/asm/param_mm.h (renamed from include/asm-m68k/param.h)0
-rw-r--r--arch/m68k/include/asm/param_no.h (renamed from arch/m68knommu/include/asm/param.h)0
-rw-r--r--arch/m68k/include/asm/parport.h (renamed from include/asm-m68k/parport.h)0
-rw-r--r--arch/m68k/include/asm/pci.h5
-rw-r--r--arch/m68k/include/asm/pci_mm.h (renamed from include/asm-m68k/pci.h)0
-rw-r--r--arch/m68k/include/asm/pci_no.h (renamed from arch/m68knommu/include/asm/pci.h)2
-rw-r--r--arch/m68k/include/asm/percpu.h (renamed from include/asm-m68k/percpu.h)0
-rw-r--r--arch/m68k/include/asm/pgalloc.h5
-rw-r--r--arch/m68k/include/asm/pgalloc_mm.h (renamed from include/asm-m68k/pgalloc.h)0
-rw-r--r--arch/m68k/include/asm/pgalloc_no.h (renamed from arch/m68knommu/include/asm/pgalloc.h)0
-rw-r--r--arch/m68k/include/asm/pgtable.h5
-rw-r--r--arch/m68k/include/asm/pgtable_mm.h (renamed from include/asm-m68k/pgtable.h)0
-rw-r--r--arch/m68k/include/asm/pgtable_no.h (renamed from arch/m68knommu/include/asm/pgtable.h)0
-rw-r--r--arch/m68k/include/asm/poll.h (renamed from include/asm-m68k/poll.h)0
-rw-r--r--arch/m68k/include/asm/posix_types.h (renamed from include/asm-m68k/posix_types.h)0
-rw-r--r--arch/m68k/include/asm/processor.h5
-rw-r--r--arch/m68k/include/asm/processor_mm.h (renamed from include/asm-m68k/processor.h)0
-rw-r--r--arch/m68k/include/asm/processor_no.h (renamed from arch/m68knommu/include/asm/processor.h)0
-rw-r--r--arch/m68k/include/asm/ptrace.h5
-rw-r--r--arch/m68k/include/asm/ptrace_mm.h (renamed from include/asm-m68k/ptrace.h)0
-rw-r--r--arch/m68k/include/asm/ptrace_no.h (renamed from arch/m68knommu/include/asm/ptrace.h)0
-rw-r--r--arch/m68k/include/asm/q40_master.h (renamed from include/asm-m68k/q40_master.h)0
-rw-r--r--arch/m68k/include/asm/q40ints.h (renamed from include/asm-m68k/q40ints.h)0
-rw-r--r--arch/m68k/include/asm/quicc_simple.h (renamed from arch/m68knommu/include/asm/quicc_simple.h)0
-rw-r--r--arch/m68k/include/asm/raw_io.h (renamed from include/asm-m68k/raw_io.h)0
-rw-r--r--arch/m68k/include/asm/resource.h (renamed from include/asm-m68k/resource.h)0
-rw-r--r--arch/m68k/include/asm/rtc.h (renamed from include/asm-m68k/rtc.h)0
-rw-r--r--arch/m68k/include/asm/sbus.h (renamed from include/asm-m68k/sbus.h)0
-rw-r--r--arch/m68k/include/asm/scatterlist.h5
-rw-r--r--arch/m68k/include/asm/scatterlist_mm.h (renamed from include/asm-m68k/scatterlist.h)0
-rw-r--r--arch/m68k/include/asm/scatterlist_no.h (renamed from arch/m68knommu/include/asm/scatterlist.h)0
-rw-r--r--arch/m68k/include/asm/sections.h (renamed from include/asm-m68k/sections.h)0
-rw-r--r--arch/m68k/include/asm/segment.h5
-rw-r--r--arch/m68k/include/asm/segment_mm.h (renamed from include/asm-m68k/segment.h)0
-rw-r--r--arch/m68k/include/asm/segment_no.h (renamed from arch/m68knommu/include/asm/segment.h)0
-rw-r--r--arch/m68k/include/asm/sembuf.h (renamed from include/asm-m68k/sembuf.h)0
-rw-r--r--arch/m68k/include/asm/serial.h (renamed from include/asm-m68k/serial.h)0
-rw-r--r--arch/m68k/include/asm/setup.h5
-rw-r--r--arch/m68k/include/asm/setup_mm.h (renamed from include/asm-m68k/setup.h)0
-rw-r--r--arch/m68k/include/asm/setup_no.h (renamed from arch/m68knommu/include/asm/setup.h)2
-rw-r--r--arch/m68k/include/asm/shm.h (renamed from include/asm-m68k/shm.h)0
-rw-r--r--arch/m68k/include/asm/shmbuf.h (renamed from include/asm-m68k/shmbuf.h)0
-rw-r--r--arch/m68k/include/asm/shmparam.h (renamed from include/asm-m68k/shmparam.h)0
-rw-r--r--arch/m68k/include/asm/sigcontext.h5
-rw-r--r--arch/m68k/include/asm/sigcontext_mm.h (renamed from include/asm-m68k/sigcontext.h)0
-rw-r--r--arch/m68k/include/asm/sigcontext_no.h (renamed from arch/m68knommu/include/asm/sigcontext.h)0
-rw-r--r--arch/m68k/include/asm/siginfo.h5
-rw-r--r--arch/m68k/include/asm/siginfo_mm.h (renamed from include/asm-m68k/siginfo.h)0
-rw-r--r--arch/m68k/include/asm/siginfo_no.h (renamed from arch/m68knommu/include/asm/siginfo.h)0
-rw-r--r--arch/m68k/include/asm/signal.h5
-rw-r--r--arch/m68k/include/asm/signal_mm.h (renamed from include/asm-m68k/signal.h)0
-rw-r--r--arch/m68k/include/asm/signal_no.h (renamed from arch/m68knommu/include/asm/signal.h)0
-rw-r--r--arch/m68k/include/asm/smp.h (renamed from arch/m68knommu/include/asm/smp.h)0
-rw-r--r--arch/m68k/include/asm/socket.h (renamed from include/asm-m68k/socket.h)0
-rw-r--r--arch/m68k/include/asm/sockios.h (renamed from include/asm-m68k/sockios.h)0
-rw-r--r--arch/m68k/include/asm/spinlock.h (renamed from include/asm-m68k/spinlock.h)0
-rw-r--r--arch/m68k/include/asm/stat.h (renamed from include/asm-m68k/stat.h)0
-rw-r--r--arch/m68k/include/asm/statfs.h (renamed from include/asm-m68k/statfs.h)0
-rw-r--r--arch/m68k/include/asm/string.h5
-rw-r--r--arch/m68k/include/asm/string_mm.h (renamed from include/asm-m68k/string.h)0
-rw-r--r--arch/m68k/include/asm/string_no.h (renamed from arch/m68knommu/include/asm/string.h)0
-rw-r--r--arch/m68k/include/asm/sun3-head.h (renamed from include/asm-m68k/sun3-head.h)0
-rw-r--r--arch/m68k/include/asm/sun3_pgalloc.h (renamed from include/asm-m68k/sun3_pgalloc.h)0
-rw-r--r--arch/m68k/include/asm/sun3_pgtable.h (renamed from include/asm-m68k/sun3_pgtable.h)0
-rw-r--r--arch/m68k/include/asm/sun3ints.h (renamed from include/asm-m68k/sun3ints.h)0
-rw-r--r--arch/m68k/include/asm/sun3mmu.h (renamed from include/asm-m68k/sun3mmu.h)0
-rw-r--r--arch/m68k/include/asm/sun3x.h (renamed from include/asm-m68k/sun3x.h)0
-rw-r--r--arch/m68k/include/asm/sun3xflop.h (renamed from include/asm-m68k/sun3xflop.h)0
-rw-r--r--arch/m68k/include/asm/sun3xprom.h (renamed from include/asm-m68k/sun3xprom.h)0
-rw-r--r--arch/m68k/include/asm/suspend.h (renamed from include/asm-m68k/suspend.h)0
-rw-r--r--arch/m68k/include/asm/swab.h5
-rw-r--r--arch/m68k/include/asm/swab_mm.h (renamed from include/asm-m68k/byteorder.h)9
-rw-r--r--arch/m68k/include/asm/swab_no.h24
-rw-r--r--arch/m68k/include/asm/system.h5
-rw-r--r--arch/m68k/include/asm/system_mm.h (renamed from include/asm-m68k/system.h)0
-rw-r--r--arch/m68k/include/asm/system_no.h (renamed from arch/m68knommu/include/asm/system.h)2
-rw-r--r--arch/m68k/include/asm/termbits.h (renamed from include/asm-m68k/termbits.h)0
-rw-r--r--arch/m68k/include/asm/termios.h (renamed from include/asm-m68k/termios.h)0
-rw-r--r--arch/m68k/include/asm/thread_info.h5
-rw-r--r--arch/m68k/include/asm/thread_info_mm.h (renamed from include/asm-m68k/thread_info.h)0
-rw-r--r--arch/m68k/include/asm/thread_info_no.h (renamed from arch/m68knommu/include/asm/thread_info.h)0
-rw-r--r--arch/m68k/include/asm/timex.h5
-rw-r--r--arch/m68k/include/asm/timex_mm.h (renamed from include/asm-m68k/timex.h)0
-rw-r--r--arch/m68k/include/asm/timex_no.h (renamed from arch/m68knommu/include/asm/timex.h)0
-rw-r--r--arch/m68k/include/asm/tlb.h (renamed from include/asm-m68k/tlb.h)0
-rw-r--r--arch/m68k/include/asm/tlbflush.h5
-rw-r--r--arch/m68k/include/asm/tlbflush_mm.h (renamed from include/asm-m68k/tlbflush.h)0
-rw-r--r--arch/m68k/include/asm/tlbflush_no.h (renamed from arch/m68knommu/include/asm/tlbflush.h)0
-rw-r--r--arch/m68k/include/asm/topology.h (renamed from arch/m68knommu/include/asm/topology.h)0
-rw-r--r--arch/m68k/include/asm/traps.h5
-rw-r--r--arch/m68k/include/asm/traps_mm.h (renamed from include/asm-m68k/traps.h)0
-rw-r--r--arch/m68k/include/asm/traps_no.h (renamed from arch/m68knommu/include/asm/traps.h)0
-rw-r--r--arch/m68k/include/asm/types.h (renamed from include/asm-m68k/types.h)0
-rw-r--r--arch/m68k/include/asm/uaccess.h5
-rw-r--r--arch/m68k/include/asm/uaccess_mm.h (renamed from include/asm-m68k/uaccess.h)0
-rw-r--r--arch/m68k/include/asm/uaccess_no.h (renamed from arch/m68knommu/include/asm/uaccess.h)0
-rw-r--r--arch/m68k/include/asm/ucontext.h5
-rw-r--r--arch/m68k/include/asm/ucontext_mm.h (renamed from include/asm-m68k/ucontext.h)0
-rw-r--r--arch/m68k/include/asm/ucontext_no.h (renamed from arch/m68knommu/include/asm/ucontext.h)0
-rw-r--r--arch/m68k/include/asm/unaligned.h5
-rw-r--r--arch/m68k/include/asm/unaligned_mm.h (renamed from include/asm-m68k/unaligned.h)0
-rw-r--r--arch/m68k/include/asm/unaligned_no.h (renamed from arch/m68knommu/include/asm/unaligned.h)0
-rw-r--r--arch/m68k/include/asm/unistd.h5
-rw-r--r--arch/m68k/include/asm/unistd_mm.h (renamed from include/asm-m68k/unistd.h)4
-rw-r--r--arch/m68k/include/asm/unistd_no.h (renamed from arch/m68knommu/include/asm/unistd.h)0
-rw-r--r--arch/m68k/include/asm/user.h (renamed from include/asm-m68k/user.h)0
-rw-r--r--arch/m68k/include/asm/virtconvert.h (renamed from include/asm-m68k/virtconvert.h)0
-rw-r--r--arch/m68k/include/asm/xor.h1
-rw-r--r--arch/m68k/include/asm/zorro.h (renamed from include/asm-m68k/zorro.h)0
-rw-r--r--arch/m68k/kernel/.gitignore1
-rw-r--r--arch/m68k/kernel/entry.S4
-rw-r--r--arch/m68k/kernel/process.c1
-rw-r--r--arch/m68k/kernel/setup.c11
-rw-r--r--arch/m68k/kernel/signal.c15
-rw-r--r--arch/m68k/kernel/traps.c2
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds1
-rw-r--r--arch/m68k/mac/baboon.c3
-rw-r--r--arch/m68k/mac/config.c12
-rw-r--r--arch/m68k/mac/debug.c1
-rw-r--r--arch/m68k/mac/iop.c10
-rw-r--r--arch/m68k/mac/macints.c15
-rw-r--r--arch/m68k/mac/misc.c1
-rw-r--r--arch/m68k/mac/oss.c25
-rw-r--r--arch/m68k/mac/psc.c12
-rw-r--r--arch/m68k/mac/via.c35
-rw-r--r--arch/m68k/math-emu/fp_log.c1
-rw-r--r--arch/m68k/mm/init.c4
-rw-r--r--arch/m68k/mm/motorola.c7
-rw-r--r--arch/m68k/mvme147/config.c6
-rw-r--r--arch/m68k/mvme16x/config.c1
-rw-r--r--arch/m68k/q40/config.c3
-rw-r--r--arch/m68k/sun3/config.c8
-rw-r--r--arch/m68k/sun3/mmu_emu.c1
-rw-r--r--arch/m68k/sun3/sun3ints.c9
-rw-r--r--arch/m68k/sun3x/config.c1
-rw-r--r--arch/m68knommu/Kconfig27
-rw-r--r--arch/m68knommu/Makefile1
-rw-r--r--arch/m68knommu/include/asm/byteorder.h27
-rw-r--r--arch/m68knommu/include/asm/cachectl.h1
-rw-r--r--arch/m68knommu/include/asm/cputime.h6
-rw-r--r--arch/m68knommu/include/asm/errno.h1
-rw-r--r--arch/m68knommu/include/asm/fcntl.h1
-rw-r--r--arch/m68knommu/include/asm/hwtest.h1
-rw-r--r--arch/m68knommu/include/asm/ioctls.h1
-rw-r--r--arch/m68knommu/include/asm/ipcbuf.h1
-rw-r--r--arch/m68knommu/include/asm/linkage.h1
-rw-r--r--arch/m68knommu/include/asm/local.h6
-rw-r--r--arch/m68knommu/include/asm/math-emu.h1
-rw-r--r--arch/m68knommu/include/asm/md.h1
-rw-r--r--arch/m68knommu/include/asm/mman.h1
-rw-r--r--arch/m68knommu/include/asm/movs.h1
-rw-r--r--arch/m68knommu/include/asm/msgbuf.h1
-rw-r--r--arch/m68knommu/include/asm/openprom.h1
-rw-r--r--arch/m68knommu/include/asm/oplib.h1
-rw-r--r--arch/m68knommu/include/asm/percpu.h6
-rw-r--r--arch/m68knommu/include/asm/poll.h1
-rw-r--r--arch/m68knommu/include/asm/posix_types.h1
-rw-r--r--arch/m68knommu/include/asm/resource.h1
-rw-r--r--arch/m68knommu/include/asm/rtc.h1
-rw-r--r--arch/m68knommu/include/asm/sections.h7
-rw-r--r--arch/m68knommu/include/asm/sembuf.h1
-rw-r--r--arch/m68knommu/include/asm/shm.h1
-rw-r--r--arch/m68knommu/include/asm/shmbuf.h1
-rw-r--r--arch/m68knommu/include/asm/shmparam.h1
-rw-r--r--arch/m68knommu/include/asm/socket.h1
-rw-r--r--arch/m68knommu/include/asm/sockios.h1
-rw-r--r--arch/m68knommu/include/asm/spinlock.h1
-rw-r--r--arch/m68knommu/include/asm/stat.h1
-rw-r--r--arch/m68knommu/include/asm/statfs.h1
-rw-r--r--arch/m68knommu/include/asm/termbits.h1
-rw-r--r--arch/m68knommu/include/asm/termios.h1
-rw-r--r--arch/m68knommu/include/asm/tlb.h1
-rw-r--r--arch/m68knommu/include/asm/types.h1
-rw-r--r--arch/m68knommu/include/asm/user.h1
-rw-r--r--arch/m68knommu/kernel/Makefile1
-rw-r--r--arch/m68knommu/kernel/comempci.c980
-rw-r--r--arch/m68knommu/kernel/init_task.c1
-rw-r--r--arch/m68knommu/kernel/signal.c15
-rw-r--r--arch/m68knommu/kernel/syscalltable.S4
-rw-r--r--arch/m68knommu/platform/5307/config.c2
-rw-r--r--arch/m68knommu/platform/532x/config.c8
-rw-r--r--arch/m68knommu/platform/coldfire/entry.S15
-rw-r--r--arch/m68knommu/platform/coldfire/pit.c2
-rw-r--r--arch/mips/Kconfig78
-rw-r--r--arch/mips/Makefile40
-rw-r--r--arch/mips/alchemy/Kconfig5
-rw-r--r--arch/mips/alchemy/common/Makefile4
-rw-r--r--arch/mips/alchemy/common/au1xxx_irqmap.c205
-rw-r--r--arch/mips/alchemy/common/clocks.c65
-rw-r--r--arch/mips/alchemy/common/cputable.c52
-rw-r--r--arch/mips/alchemy/common/dbdma.c65
-rw-r--r--arch/mips/alchemy/common/irq.c745
-rw-r--r--arch/mips/alchemy/common/power.c406
-rw-r--r--arch/mips/alchemy/common/reset.c2
-rw-r--r--arch/mips/alchemy/common/setup.c71
-rw-r--r--arch/mips/alchemy/common/sleeper.S118
-rw-r--r--arch/mips/alchemy/common/time.c311
-rw-r--r--arch/mips/alchemy/db1x00/init.c62
-rw-r--r--arch/mips/alchemy/devboards/Makefile18
-rw-r--r--arch/mips/alchemy/devboards/db1x00/Makefile (renamed from arch/mips/alchemy/db1x00/Makefile)2
-rw-r--r--arch/mips/alchemy/devboards/db1x00/board_setup.c (renamed from arch/mips/alchemy/db1x00/board_setup.c)37
-rw-r--r--arch/mips/alchemy/devboards/db1x00/irqmap.c (renamed from arch/mips/alchemy/db1x00/irqmap.c)24
-rw-r--r--arch/mips/alchemy/devboards/pb1000/Makefile (renamed from arch/mips/alchemy/pb1000/Makefile)2
-rw-r--r--arch/mips/alchemy/devboards/pb1000/board_setup.c (renamed from arch/mips/alchemy/pb1000/board_setup.c)30
-rw-r--r--arch/mips/alchemy/devboards/pb1100/Makefile (renamed from arch/mips/alchemy/pb1100/Makefile)2
-rw-r--r--arch/mips/alchemy/devboards/pb1100/board_setup.c (renamed from arch/mips/alchemy/pb1100/board_setup.c)47
-rw-r--r--arch/mips/alchemy/devboards/pb1200/Makefile (renamed from arch/mips/alchemy/pb1200/Makefile)3
-rw-r--r--arch/mips/alchemy/devboards/pb1200/board_setup.c (renamed from arch/mips/alchemy/pb1200/board_setup.c)34
-rw-r--r--arch/mips/alchemy/devboards/pb1200/irqmap.c (renamed from arch/mips/alchemy/pb1200/irqmap.c)94
-rw-r--r--arch/mips/alchemy/devboards/pb1200/platform.c (renamed from arch/mips/alchemy/pb1200/platform.c)0
-rw-r--r--arch/mips/alchemy/devboards/pb1500/Makefile (renamed from arch/mips/alchemy/pb1500/Makefile)2
-rw-r--r--arch/mips/alchemy/devboards/pb1500/board_setup.c (renamed from arch/mips/alchemy/pb1500/board_setup.c)44
-rw-r--r--arch/mips/alchemy/devboards/pb1550/Makefile (renamed from arch/mips/alchemy/pb1550/Makefile)2
-rw-r--r--arch/mips/alchemy/devboards/pb1550/board_setup.c (renamed from arch/mips/alchemy/pb1550/board_setup.c)34
-rw-r--r--arch/mips/alchemy/devboards/pm.c229
-rw-r--r--arch/mips/alchemy/devboards/prom.c (renamed from arch/mips/alchemy/pb1200/init.c)26
-rw-r--r--arch/mips/alchemy/mtx-1/board_setup.c12
-rw-r--r--arch/mips/alchemy/mtx-1/init.c2
-rw-r--r--arch/mips/alchemy/mtx-1/irqmap.c18
-rw-r--r--arch/mips/alchemy/pb1000/init.c57
-rw-r--r--arch/mips/alchemy/pb1000/irqmap.c38
-rw-r--r--arch/mips/alchemy/pb1100/init.c60
-rw-r--r--arch/mips/alchemy/pb1100/irqmap.c40
-rw-r--r--arch/mips/alchemy/pb1500/init.c58
-rw-r--r--arch/mips/alchemy/pb1500/irqmap.c46
-rw-r--r--arch/mips/alchemy/pb1550/init.c58
-rw-r--r--arch/mips/alchemy/pb1550/irqmap.c43
-rw-r--r--arch/mips/alchemy/xxs1500/board_setup.c12
-rw-r--r--arch/mips/alchemy/xxs1500/init.c2
-rw-r--r--arch/mips/alchemy/xxs1500/irqmap.c31
-rw-r--r--arch/mips/cavium-octeon/Kconfig85
-rw-r--r--arch/mips/cavium-octeon/Makefile16
-rw-r--r--arch/mips/cavium-octeon/csrc-octeon.c58
-rw-r--r--arch/mips/cavium-octeon/dma-octeon.c32
-rw-r--r--arch/mips/cavium-octeon/executive/Makefile13
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-bootmem.c586
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-l2c.c734
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-sysinfo.c116
-rw-r--r--arch/mips/cavium-octeon/executive/octeon-model.c358
-rw-r--r--arch/mips/cavium-octeon/flash_setup.c84
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c497
-rw-r--r--arch/mips/cavium-octeon/octeon-memcpy.S521
-rw-r--r--arch/mips/cavium-octeon/serial.c136
-rw-r--r--arch/mips/cavium-octeon/setup.c927
-rw-r--r--arch/mips/cavium-octeon/smp.c211
-rw-r--r--arch/mips/configs/bigsur_defconfig2
-rw-r--r--arch/mips/configs/cavium-octeon_defconfig943
-rw-r--r--arch/mips/configs/emma2rh_defconfig2
-rw-r--r--arch/mips/configs/fulong_defconfig4
-rw-r--r--arch/mips/configs/ip27_defconfig2
-rw-r--r--arch/mips/configs/msp71xx_defconfig2
-rw-r--r--arch/mips/configs/mtx1_defconfig4
-rw-r--r--arch/mips/configs/pnx8335-stb225_defconfig4
-rw-r--r--arch/mips/configs/rbtx49xx_defconfig2
-rw-r--r--arch/mips/include/asm/atomic.h57
-rw-r--r--arch/mips/include/asm/byteorder.h52
-rw-r--r--arch/mips/include/asm/cpu-features.h3
-rw-r--r--arch/mips/include/asm/cpu.h14
-rw-r--r--arch/mips/include/asm/hazards.h4
-rw-r--r--arch/mips/include/asm/io.h14
-rw-r--r--arch/mips/include/asm/irq.h3
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1000.h89
-rw-r--r--arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h5
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h78
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h64
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/irq.h244
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h131
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/war.h26
-rw-r--r--arch/mips/include/asm/mach-generic/dma-coherence.h26
-rw-r--r--arch/mips/include/asm/mach-ip27/dma-coherence.h26
-rw-r--r--arch/mips/include/asm/mach-ip27/topology.h5
-rw-r--r--arch/mips/include/asm/mach-ip32/dma-coherence.h26
-rw-r--r--arch/mips/include/asm/mach-jazz/dma-coherence.h26
-rw-r--r--arch/mips/include/asm/mach-lemote/dma-coherence.h26
-rw-r--r--arch/mips/include/asm/mach-rc32434/gpio.h5
-rw-r--r--arch/mips/include/asm/mach-rc32434/irq.h3
-rw-r--r--arch/mips/include/asm/mach-rc32434/rb.h3
-rw-r--r--arch/mips/include/asm/mipsregs.h22
-rw-r--r--arch/mips/include/asm/module.h2
-rw-r--r--arch/mips/include/asm/octeon/cvmx-asm.h128
-rw-r--r--arch/mips/include/asm/octeon/cvmx-bootinfo.h262
-rw-r--r--arch/mips/include/asm/octeon/cvmx-bootmem.h288
-rw-r--r--arch/mips/include/asm/octeon/cvmx-ciu-defs.h1616
-rw-r--r--arch/mips/include/asm/octeon/cvmx-gpio-defs.h219
-rw-r--r--arch/mips/include/asm/octeon/cvmx-iob-defs.h530
-rw-r--r--arch/mips/include/asm/octeon/cvmx-ipd-defs.h877
-rw-r--r--arch/mips/include/asm/octeon/cvmx-l2c-defs.h963
-rw-r--r--arch/mips/include/asm/octeon/cvmx-l2c.h325
-rw-r--r--arch/mips/include/asm/octeon/cvmx-l2d-defs.h369
-rw-r--r--arch/mips/include/asm/octeon/cvmx-l2t-defs.h141
-rw-r--r--arch/mips/include/asm/octeon/cvmx-led-defs.h240
-rw-r--r--arch/mips/include/asm/octeon/cvmx-mio-defs.h2004
-rw-r--r--arch/mips/include/asm/octeon/cvmx-packet.h61
-rw-r--r--arch/mips/include/asm/octeon/cvmx-pow-defs.h698
-rw-r--r--arch/mips/include/asm/octeon/cvmx-spinlock.h232
-rw-r--r--arch/mips/include/asm/octeon/cvmx-sysinfo.h152
-rw-r--r--arch/mips/include/asm/octeon/cvmx.h505
-rw-r--r--arch/mips/include/asm/octeon/octeon-feature.h119
-rw-r--r--arch/mips/include/asm/octeon/octeon-model.h321
-rw-r--r--arch/mips/include/asm/octeon/octeon.h248
-rw-r--r--arch/mips/include/asm/processor.h69
-rw-r--r--arch/mips/include/asm/ptrace.h6
-rw-r--r--arch/mips/include/asm/smp.h4
-rw-r--r--arch/mips/include/asm/stackframe.h17
-rw-r--r--arch/mips/include/asm/swab.h55
-rw-r--r--arch/mips/include/asm/termios.h100
-rw-r--r--arch/mips/include/asm/time.h24
-rw-r--r--arch/mips/include/asm/txx9/tx4939.h1
-rw-r--r--arch/mips/jazz/irq.c2
-rw-r--r--arch/mips/kernel/Makefile5
-rw-r--r--arch/mips/kernel/asm-offsets.c31
-rw-r--r--arch/mips/kernel/branch.c33
-rw-r--r--arch/mips/kernel/cevt-bcm1480.c4
-rw-r--r--arch/mips/kernel/cevt-ds1287.c2
-rw-r--r--arch/mips/kernel/cevt-gt641xx.c2
-rw-r--r--arch/mips/kernel/cevt-r4k.c4
-rw-r--r--arch/mips/kernel/cevt-sb1250.c4
-rw-r--r--arch/mips/kernel/cevt-smtc.c2
-rw-r--r--arch/mips/kernel/cevt-txx9.c2
-rw-r--r--arch/mips/kernel/cpu-probe.c31
-rw-r--r--arch/mips/kernel/csrc-r4k.c2
-rw-r--r--arch/mips/kernel/genex.S10
-rw-r--r--arch/mips/kernel/i8253.c2
-rw-r--r--arch/mips/kernel/init_task.c1
-rw-r--r--arch/mips/kernel/irq-gic.c6
-rw-r--r--arch/mips/kernel/irq.c1
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c3
-rw-r--r--arch/mips/kernel/octeon_switch.S506
-rw-r--r--arch/mips/kernel/ptrace32.c64
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/smp-cmp.c6
-rw-r--r--arch/mips/kernel/smp-mt.c2
-rw-r--r--arch/mips/kernel/smp.c7
-rw-r--r--arch/mips/kernel/smtc.c6
-rw-r--r--arch/mips/kernel/stacktrace.c24
-rw-r--r--arch/mips/kernel/traps.c37
-rw-r--r--arch/mips/kernel/vpe.c2
-rw-r--r--arch/mips/lib/Makefile1
-rw-r--r--arch/mips/lib/memcpy-inatomic.S2
-rw-r--r--arch/mips/lib/memcpy.S2
-rw-r--r--arch/mips/mm/Makefile1
-rw-r--r--arch/mips/mm/c-octeon.c307
-rw-r--r--arch/mips/mm/c-r4k.c22
-rw-r--r--arch/mips/mm/cache.c6
-rw-r--r--arch/mips/mm/cex-oct.S70
-rw-r--r--arch/mips/mm/dma-default.c25
-rw-r--r--arch/mips/mm/fault.c21
-rw-r--r--arch/mips/mm/tlb-r4k.c5
-rw-r--r--arch/mips/mm/tlbex.c1
-rw-r--r--arch/mips/mti-malta/malta-smtc.c6
-rw-r--r--arch/mips/nxp/pnx8550/common/time.c1
-rw-r--r--arch/mips/pci/pci-ip27.c6
-rw-r--r--arch/mips/pci/pci-rc32434.c11
-rw-r--r--arch/mips/pci/pci.c24
-rw-r--r--arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c2
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c6
-rw-r--r--arch/mips/rb532/devices.c57
-rw-r--r--arch/mips/rb532/gpio.c90
-rw-r--r--arch/mips/rb532/irq.c27
-rw-r--r--arch/mips/rb532/serial.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-smp.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c2
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c8
-rw-r--r--arch/mips/sibyte/bcm1480/smp.c8
-rw-r--r--arch/mips/sibyte/sb1250/irq.c8
-rw-r--r--arch/mips/sibyte/sb1250/smp.c8
-rw-r--r--arch/mips/sni/time.c2
-rw-r--r--arch/mips/txx9/generic/setup_tx4939.c22
-rw-r--r--arch/mips/txx9/rbtx4939/setup.c1
-rw-r--r--arch/mn10300/kernel/entry.S2
-rw-r--r--arch/mn10300/kernel/init_task.c1
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/Makefile2
-rw-r--r--arch/parisc/include/asm/atomic.h11
-rw-r--r--arch/parisc/include/asm/byteorder.h76
-rw-r--r--arch/parisc/include/asm/checksum.h2
-rw-r--r--arch/parisc/include/asm/dma-mapping.h2
-rw-r--r--arch/parisc/include/asm/io.h12
-rw-r--r--arch/parisc/include/asm/mmu_context.h13
-rw-r--r--arch/parisc/include/asm/module.h6
-rw-r--r--arch/parisc/include/asm/processor.h4
-rw-r--r--arch/parisc/include/asm/smp.h2
-rw-r--r--arch/parisc/include/asm/swab.h66
-rw-r--r--arch/parisc/include/asm/uaccess.h2
-rw-r--r--arch/parisc/kernel/drivers.c40
-rw-r--r--arch/parisc/kernel/hpmc.S8
-rw-r--r--arch/parisc/kernel/init_task.c1
-rw-r--r--arch/parisc/kernel/irq.c17
-rw-r--r--arch/parisc/kernel/module.c216
-rw-r--r--arch/parisc/kernel/pci-dma.c2
-rw-r--r--arch/parisc/kernel/pdc_cons.c2
-rw-r--r--arch/parisc/kernel/perf.c4
-rw-r--r--arch/parisc/kernel/processor.c68
-rw-r--r--arch/parisc/kernel/setup.c11
-rw-r--r--arch/parisc/kernel/smp.c47
-rw-r--r--arch/parisc/kernel/time.c4
-rw-r--r--arch/parisc/kernel/topology.c4
-rw-r--r--arch/parisc/kernel/traps.c9
-rw-r--r--arch/parisc/kernel/unwind.c2
-rw-r--r--arch/parisc/lib/iomap.c2
-rw-r--r--arch/parisc/lib/memcpy.c2
-rw-r--r--arch/parisc/mm/fault.c58
-rw-r--r--arch/powerpc/Kconfig10
-rw-r--r--arch/powerpc/boot/Makefile4
-rw-r--r--arch/powerpc/boot/cuboot-warp.c43
-rw-r--r--arch/powerpc/boot/dts/gef_sbc610.dts15
-rw-r--r--arch/powerpc/boot/dts/haleakala.dts5
-rw-r--r--arch/powerpc/boot/dts/kilauea.dts5
-rw-r--r--arch/powerpc/boot/dts/makalu.dts5
-rw-r--r--arch/powerpc/boot/dts/mpc8313erdb.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc8315erdb.dts4
-rw-r--r--arch/powerpc/boot/dts/mpc836x_mds.dts43
-rw-r--r--arch/powerpc/boot/dts/mpc836x_rdk.dts19
-rw-r--r--arch/powerpc/boot/dts/mpc8544ds.dts4
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds.dts6
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts2
-rw-r--r--arch/powerpc/boot/dts/mpc8641_hpcn.dts56
-rw-r--r--arch/powerpc/boot/dts/sequoia.dts2
-rw-r--r--arch/powerpc/boot/dts/warp.dts42
-rw-r--r--arch/powerpc/boot/install.sh14
-rw-r--r--arch/powerpc/configs/40x/acadia_defconfig76
-rw-r--r--arch/powerpc/configs/40x/ep405_defconfig87
-rw-r--r--arch/powerpc/configs/40x/hcu4_defconfig78
-rw-r--r--arch/powerpc/configs/40x/kilauea_defconfig76
-rw-r--r--arch/powerpc/configs/40x/makalu_defconfig76
-rw-r--r--arch/powerpc/configs/40x/virtex_defconfig53
-rw-r--r--arch/powerpc/configs/40x/walnut_defconfig84
-rw-r--r--arch/powerpc/configs/44x/arches_defconfig60
-rw-r--r--arch/powerpc/configs/44x/bamboo_defconfig76
-rw-r--r--arch/powerpc/configs/44x/canyonlands_defconfig60
-rw-r--r--arch/powerpc/configs/44x/ebony_defconfig84
-rw-r--r--arch/powerpc/configs/44x/katmai_defconfig76
-rw-r--r--arch/powerpc/configs/44x/rainier_defconfig83
-rw-r--r--arch/powerpc/configs/44x/sam440ep_defconfig81
-rw-r--r--arch/powerpc/configs/44x/sequoia_defconfig83
-rw-r--r--arch/powerpc/configs/44x/taishan_defconfig83
-rw-r--r--arch/powerpc/configs/44x/virtex5_defconfig53
-rw-r--r--arch/powerpc/configs/44x/warp_defconfig140
-rw-r--r--arch/powerpc/configs/52xx/cm5200_defconfig83
-rw-r--r--arch/powerpc/configs/52xx/lite5200b_defconfig86
-rw-r--r--arch/powerpc/configs/52xx/motionpro_defconfig85
-rw-r--r--arch/powerpc/configs/52xx/pcm030_defconfig82
-rw-r--r--arch/powerpc/configs/52xx/tqm5200_defconfig89
-rw-r--r--arch/powerpc/configs/83xx/asp8347_defconfig95
-rw-r--r--arch/powerpc/configs/83xx/mpc8313_rdb_defconfig109
-rw-r--r--arch/powerpc/configs/83xx/mpc8315_rdb_defconfig109
-rw-r--r--arch/powerpc/configs/83xx/mpc832x_mds_defconfig90
-rw-r--r--arch/powerpc/configs/83xx/mpc832x_rdb_defconfig95
-rw-r--r--arch/powerpc/configs/83xx/mpc834x_itx_defconfig106
-rw-r--r--arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig104
-rw-r--r--arch/powerpc/configs/83xx/mpc834x_mds_defconfig88
-rw-r--r--arch/powerpc/configs/83xx/mpc836x_mds_defconfig97
-rw-r--r--arch/powerpc/configs/83xx/mpc836x_rdk_defconfig94
-rw-r--r--arch/powerpc/configs/83xx/mpc837x_mds_defconfig88
-rw-r--r--arch/powerpc/configs/83xx/mpc837x_rdb_defconfig94
-rw-r--r--arch/powerpc/configs/83xx/sbc834x_defconfig78
-rw-r--r--arch/powerpc/configs/85xx/ksi8560_defconfig79
-rw-r--r--arch/powerpc/configs/85xx/mpc8536_ds_defconfig115
-rw-r--r--arch/powerpc/configs/85xx/mpc8540_ads_defconfig66
-rw-r--r--arch/powerpc/configs/85xx/mpc8544_ds_defconfig115
-rw-r--r--arch/powerpc/configs/85xx/mpc8560_ads_defconfig73
-rw-r--r--arch/powerpc/configs/85xx/mpc8568mds_defconfig90
-rw-r--r--arch/powerpc/configs/85xx/mpc8572_ds_defconfig123
-rw-r--r--arch/powerpc/configs/85xx/mpc85xx_cds_defconfig69
-rw-r--r--arch/powerpc/configs/85xx/sbc8548_defconfig60
-rw-r--r--arch/powerpc/configs/85xx/sbc8560_defconfig66
-rw-r--r--arch/powerpc/configs/85xx/stx_gp3_defconfig92
-rw-r--r--arch/powerpc/configs/85xx/tqm8540_defconfig85
-rw-r--r--arch/powerpc/configs/85xx/tqm8541_defconfig92
-rw-r--r--arch/powerpc/configs/85xx/tqm8548_defconfig88
-rw-r--r--arch/powerpc/configs/85xx/tqm8555_defconfig92
-rw-r--r--arch/powerpc/configs/85xx/tqm8560_defconfig92
-rw-r--r--arch/powerpc/configs/86xx/gef_sbc610_defconfig139
-rw-r--r--arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig87
-rw-r--r--arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig115
-rw-r--r--arch/powerpc/configs/86xx/sbc8641d_defconfig106
-rw-r--r--arch/powerpc/configs/adder875_defconfig65
-rw-r--r--arch/powerpc/configs/c2k_defconfig122
-rw-r--r--arch/powerpc/configs/cell_defconfig2
-rw-r--r--arch/powerpc/configs/celleb_defconfig2
-rw-r--r--arch/powerpc/configs/chrp32_defconfig4
-rw-r--r--arch/powerpc/configs/ep8248e_defconfig77
-rw-r--r--arch/powerpc/configs/ep88xc_defconfig65
-rw-r--r--arch/powerpc/configs/g5_defconfig4
-rw-r--r--arch/powerpc/configs/linkstation_defconfig114
-rw-r--r--arch/powerpc/configs/maple_defconfig4
-rw-r--r--arch/powerpc/configs/mgcoge_defconfig74
-rw-r--r--arch/powerpc/configs/mgsuvd_defconfig63
-rw-r--r--arch/powerpc/configs/mpc5200_defconfig104
-rw-r--r--arch/powerpc/configs/mpc7448_hpc2_defconfig71
-rw-r--r--arch/powerpc/configs/mpc8272_ads_defconfig77
-rw-r--r--arch/powerpc/configs/mpc83xx_defconfig111
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig124
-rw-r--r--arch/powerpc/configs/mpc866_ads_defconfig64
-rw-r--r--arch/powerpc/configs/mpc86xx_defconfig147
-rw-r--r--arch/powerpc/configs/mpc885_ads_defconfig65
-rw-r--r--arch/powerpc/configs/pasemi_defconfig2
-rw-r--r--arch/powerpc/configs/pmac32_defconfig4
-rw-r--r--arch/powerpc/configs/ppc40x_defconfig81
-rw-r--r--arch/powerpc/configs/ppc44x_defconfig83
-rw-r--r--arch/powerpc/configs/ppc64_defconfig30
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig4
-rw-r--r--arch/powerpc/configs/pq2fads_defconfig87
-rw-r--r--arch/powerpc/configs/prpmc2800_defconfig100
-rw-r--r--arch/powerpc/configs/pseries_defconfig4
-rw-r--r--arch/powerpc/configs/storcenter_defconfig89
-rw-r--r--arch/powerpc/include/asm/atomic.h4
-rw-r--r--arch/powerpc/include/asm/byteorder.h83
-rw-r--r--arch/powerpc/include/asm/cell-pmu.h2
-rw-r--r--arch/powerpc/include/asm/disassemble.h80
-rw-r--r--arch/powerpc/include/asm/hugetlb.h6
-rw-r--r--arch/powerpc/include/asm/ioctls.h2
-rw-r--r--arch/powerpc/include/asm/kexec.h55
-rw-r--r--arch/powerpc/include/asm/kvm_44x.h61
-rw-r--r--arch/powerpc/include/asm/kvm_host.h116
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h83
-rw-r--r--arch/powerpc/include/asm/mmu-44x.h1
-rw-r--r--arch/powerpc/include/asm/oprofile_impl.h6
-rw-r--r--arch/powerpc/include/asm/ps3.h10
-rw-r--r--arch/powerpc/include/asm/qe.h56
-rw-r--r--arch/powerpc/include/asm/qe_ic.h21
-rw-r--r--arch/powerpc/include/asm/rtas.h2
-rw-r--r--arch/powerpc/include/asm/spu.h2
-rw-r--r--arch/powerpc/include/asm/swab.h90
-rw-r--r--arch/powerpc/include/asm/systbl.h2
-rw-r--r--arch/powerpc/include/asm/topology.h13
-rw-r--r--arch/powerpc/include/asm/types.h7
-rw-r--r--arch/powerpc/kernel/Makefile2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c28
-rw-r--r--arch/powerpc/kernel/cacheinfo.c837
-rw-r--r--arch/powerpc/kernel/cacheinfo.h8
-rw-r--r--arch/powerpc/kernel/dma-iommu.c4
-rw-r--r--arch/powerpc/kernel/head_64.S9
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S8
-rw-r--r--arch/powerpc/kernel/init_task.c1
-rw-r--r--arch/powerpc/kernel/iommu.c12
-rw-r--r--arch/powerpc/kernel/irq.c2
-rw-r--r--arch/powerpc/kernel/kprobes.c9
-rw-r--r--arch/powerpc/kernel/lparcfg.c10
-rw-r--r--arch/powerpc/kernel/machine_kexec.c25
-rw-r--r--arch/powerpc/kernel/pci-common.c74
-rw-r--r--arch/powerpc/kernel/pci_64.c15
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c1
-rw-r--r--arch/powerpc/kernel/process.c1
-rw-r--r--arch/powerpc/kernel/prom.c19
-rw-r--r--arch/powerpc/kernel/prom_init.c2
-rw-r--r--arch/powerpc/kernel/prom_parse.c7
-rw-r--r--arch/powerpc/kernel/setup_64.c6
-rw-r--r--arch/powerpc/kernel/smp.c4
-rw-r--r--arch/powerpc/kernel/sysfs.c300
-rw-r--r--arch/powerpc/kernel/time.c20
-rw-r--r--arch/powerpc/kernel/vio.c7
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S4
-rw-r--r--arch/powerpc/kvm/44x.c228
-rw-r--r--arch/powerpc/kvm/44x_emulate.c371
-rw-r--r--arch/powerpc/kvm/44x_tlb.c463
-rw-r--r--arch/powerpc/kvm/44x_tlb.h26
-rw-r--r--arch/powerpc/kvm/Kconfig28
-rw-r--r--arch/powerpc/kvm/Makefile12
-rw-r--r--arch/powerpc/kvm/booke.c (renamed from arch/powerpc/kvm/booke_guest.c)418
-rw-r--r--arch/powerpc/kvm/booke.h60
-rw-r--r--arch/powerpc/kvm/booke_host.c83
-rw-r--r--arch/powerpc/kvm/booke_interrupts.S72
-rw-r--r--arch/powerpc/kvm/emulate.c447
-rw-r--r--arch/powerpc/kvm/powerpc.c130
-rw-r--r--arch/powerpc/kvm/timing.c239
-rw-r--r--arch/powerpc/kvm/timing.h102
-rw-r--r--arch/powerpc/mm/fsl_booke_mmu.c9
-rw-r--r--arch/powerpc/mm/hugetlbpage.c7
-rw-r--r--arch/powerpc/mm/mem.c2
-rw-r--r--arch/powerpc/mm/mmu_decl.h17
-rw-r--r--arch/powerpc/mm/numa.c62
-rw-r--r--arch/powerpc/mm/pgtable_32.c3
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c6
-rw-r--r--arch/powerpc/mm/slice.c11
-rw-r--r--arch/powerpc/mm/stab.c4
-rw-r--r--arch/powerpc/mm/tlb_nohash.c3
-rw-r--r--arch/powerpc/oprofile/cell/pr_util.h13
-rw-r--r--arch/powerpc/oprofile/cell/spu_profiler.c58
-rw-r--r--arch/powerpc/oprofile/cell/spu_task_sync.c2
-rw-r--r--arch/powerpc/oprofile/common.c22
-rw-r--r--arch/powerpc/oprofile/op_model_cell.c748
-rw-r--r--arch/powerpc/oprofile/op_model_pa6t.c6
-rw-r--r--arch/powerpc/platforms/44x/Makefile1
-rw-r--r--arch/powerpc/platforms/44x/warp-nand.c135
-rw-r--r--arch/powerpc/platforms/512x/clock.c4
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_common.c2
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_gpio.c3
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c24
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pic.c8
-rw-r--r--arch/powerpc/platforms/83xx/Makefile1
-rw-r--r--arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c (renamed from drivers/i2c/chips/mcu_mpc8349emitx.c)0
-rw-r--r--arch/powerpc/platforms/83xx/mpc831x_rdb.c3
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_mds.c9
-rw-r--r--arch/powerpc/platforms/83xx/mpc832x_rdb.c5
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_mds.c81
-rw-r--r--arch/powerpc/platforms/83xx/mpc836x_rdk.c6
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_mds.c1
-rw-r--r--arch/powerpc/platforms/83xx/mpc837x_rdb.c2
-rw-r--r--arch/powerpc/platforms/83xx/mpc83xx.h1
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c7
-rw-r--r--arch/powerpc/platforms/85xx/smp.c1
-rw-r--r--arch/powerpc/platforms/Kconfig22
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype2
-rw-r--r--arch/powerpc/platforms/cell/beat_htab.c21
-rw-r--r--arch/powerpc/platforms/cell/beat_interrupt.c2
-rw-r--r--arch/powerpc/platforms/cell/beat_udbg.c4
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c2
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c2
-rw-r--r--arch/powerpc/platforms/cell/celleb_scc_epci.c4
-rw-r--r--arch/powerpc/platforms/cell/cpufreq_spudemand.c4
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c2
-rw-r--r--arch/powerpc/platforms/cell/io-workarounds.c4
-rw-r--r--arch/powerpc/platforms/cell/iommu.c8
-rw-r--r--arch/powerpc/platforms/cell/ras.c8
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c4
-rw-r--r--arch/powerpc/platforms/cell/spu_callbacks.c2
-rw-r--r--arch/powerpc/platforms/cell/spu_priv1_mmio.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c2
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c6
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h2
-rw-r--r--arch/powerpc/platforms/fsl_uli1575.c1
-rw-r--r--arch/powerpc/platforms/iseries/Kconfig5
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c4
-rw-r--r--arch/powerpc/platforms/iseries/setup.c11
-rw-r--r--arch/powerpc/platforms/pasemi/cpufreq.c4
-rw-r--r--arch/powerpc/platforms/pasemi/dma_lib.c2
-rw-r--r--arch/powerpc/platforms/powermac/cpufreq_64.c2
-rw-r--r--arch/powerpc/platforms/powermac/pci.c2
-rw-r--r--arch/powerpc/platforms/powermac/smp.c2
-rw-r--r--arch/powerpc/platforms/powermac/time.c11
-rw-r--r--arch/powerpc/platforms/ps3/device-init.c63
-rw-r--r--arch/powerpc/platforms/ps3/htab.c2
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c28
-rw-r--r--arch/powerpc/platforms/ps3/mm.c97
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c2
-rw-r--r--arch/powerpc/platforms/ps3/repository.c22
-rw-r--r--arch/powerpc/platforms/ps3/setup.c2
-rw-r--r--arch/powerpc/platforms/ps3/spu.c12
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c14
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c35
-rw-r--r--arch/powerpc/platforms/pseries/phyp_dump.c26
-rw-r--r--arch/powerpc/platforms/pseries/xics.c4
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c114
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h5
-rw-r--r--arch/powerpc/sysdev/mpic.c6
-rw-r--r--arch/powerpc/sysdev/mpic.h2
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig3
-rw-r--r--arch/powerpc/sysdev/qe_lib/gpio.c195
-rw-r--r--arch/powerpc/sysdev/simple_gpio.c155
-rw-r--r--arch/powerpc/sysdev/simple_gpio.h12
-rw-r--r--arch/s390/Kconfig4
-rw-r--r--arch/s390/hypfs/inode.c1
-rw-r--r--arch/s390/include/asm/atomic.h7
-rw-r--r--arch/s390/include/asm/byteorder.h91
-rw-r--r--arch/s390/include/asm/chpid.h2
-rw-r--r--arch/s390/include/asm/chsc.h1
-rw-r--r--arch/s390/include/asm/cmb.h3
-rw-r--r--arch/s390/include/asm/cpu.h7
-rw-r--r--arch/s390/include/asm/cputime.h42
-rw-r--r--arch/s390/include/asm/dasd.h2
-rw-r--r--arch/s390/include/asm/elf.h16
-rw-r--r--arch/s390/include/asm/kvm.h2
-rw-r--r--arch/s390/include/asm/lowcore.h49
-rw-r--r--arch/s390/include/asm/posix_types.h4
-rw-r--r--arch/s390/include/asm/ptrace.h7
-rw-r--r--arch/s390/include/asm/qeth.h1
-rw-r--r--arch/s390/include/asm/s390_rdev.h15
-rw-r--r--arch/s390/include/asm/schid.h2
-rw-r--r--arch/s390/include/asm/swab.h91
-rw-r--r--arch/s390/include/asm/system.h4
-rw-r--r--arch/s390/include/asm/thread_info.h2
-rw-r--r--arch/s390/include/asm/timer.h16
-rw-r--r--arch/s390/include/asm/topology.h2
-rw-r--r--arch/s390/include/asm/types.h6
-rw-r--r--arch/s390/include/asm/vdso.h15
-rw-r--r--arch/s390/kernel/asm-offsets.c5
-rw-r--r--arch/s390/kernel/compat_wrapper.S42
-rw-r--r--arch/s390/kernel/entry.S5
-rw-r--r--arch/s390/kernel/entry.h18
-rw-r--r--arch/s390/kernel/entry64.S50
-rw-r--r--arch/s390/kernel/head64.S2
-rw-r--r--arch/s390/kernel/init_task.c1
-rw-r--r--arch/s390/kernel/kprobes.c9
-rw-r--r--arch/s390/kernel/process.c52
-rw-r--r--arch/s390/kernel/s390_ext.c2
-rw-r--r--arch/s390/kernel/setup.c2
-rw-r--r--arch/s390/kernel/signal.c19
-rw-r--r--arch/s390/kernel/smp.c41
-rw-r--r--arch/s390/kernel/sys_s390.c54
-rw-r--r--arch/s390/kernel/syscalls.S24
-rw-r--r--arch/s390/kernel/time.c8
-rw-r--r--arch/s390/kernel/topology.c5
-rw-r--r--arch/s390/kernel/vdso.c124
-rw-r--r--arch/s390/kernel/vdso32/gettimeofday.S4
-rw-r--r--arch/s390/kernel/vdso64/clock_getres.S5
-rw-r--r--arch/s390/kernel/vdso64/clock_gettime.S39
-rw-r--r--arch/s390/kernel/vtime.c490
-rw-r--r--arch/s390/kvm/diag.c2
-rw-r--r--arch/s390/kvm/interrupt.c6
-rw-r--r--arch/s390/kvm/kvm-s390.c41
-rw-r--r--arch/s390/kvm/priv.c2
-rw-r--r--arch/s390/mm/init.c2
-rw-r--r--arch/sh/Kconfig63
-rw-r--r--arch/sh/boards/board-ap325rxa.c53
-rw-r--r--arch/sh/boards/board-magicpanelr2.c23
-rw-r--r--arch/sh/boards/board-sh7785lcr.c1
-rw-r--r--arch/sh/boards/mach-highlander/setup.c1
-rw-r--r--arch/sh/boards/mach-hp6xx/setup.c2
-rw-r--r--arch/sh/boards/mach-migor/setup.c171
-rw-r--r--arch/sh/boards/mach-rsk/devices-rsk7203.c24
-rw-r--r--arch/sh/boards/mach-x3proto/setup.c1
-rw-r--r--arch/sh/configs/ap325rxa_defconfig355
-rw-r--r--arch/sh/configs/cayman_defconfig4
-rw-r--r--arch/sh/configs/dreamcast_defconfig60
-rw-r--r--arch/sh/configs/edosk7705_defconfig18
-rw-r--r--arch/sh/configs/edosk7760_defconfig87
-rw-r--r--arch/sh/configs/hp6xx_defconfig88
-rw-r--r--arch/sh/configs/landisk_defconfig76
-rw-r--r--arch/sh/configs/lboxre2_defconfig63
-rw-r--r--arch/sh/configs/magicpanelr2_defconfig119
-rw-r--r--arch/sh/configs/microdev_defconfig63
-rw-r--r--arch/sh/configs/migor_defconfig99
-rw-r--r--arch/sh/configs/r7780mp_defconfig89
-rw-r--r--arch/sh/configs/r7785rp_defconfig134
-rw-r--r--arch/sh/configs/rsk7201_defconfig26
-rw-r--r--arch/sh/configs/rsk7203_defconfig88
-rw-r--r--arch/sh/configs/rts7751r2d1_defconfig89
-rw-r--r--arch/sh/configs/rts7751r2dplus_defconfig89
-rw-r--r--arch/sh/configs/sdk7780_defconfig101
-rw-r--r--arch/sh/configs/se7206_defconfig75
-rw-r--r--arch/sh/configs/se7343_defconfig65
-rw-r--r--arch/sh/configs/se7619_defconfig47
-rw-r--r--arch/sh/configs/se7705_defconfig60
-rw-r--r--arch/sh/configs/se7712_defconfig79
-rw-r--r--arch/sh/configs/se7721_defconfig85
-rw-r--r--arch/sh/configs/se7722_defconfig61
-rw-r--r--arch/sh/configs/se7750_defconfig61
-rw-r--r--arch/sh/configs/se7751_defconfig56
-rw-r--r--arch/sh/configs/se7780_defconfig87
-rw-r--r--arch/sh/configs/sh03_defconfig82
-rw-r--r--arch/sh/configs/sh7710voipgw_defconfig55
-rw-r--r--arch/sh/configs/sh7763rdp_defconfig71
-rw-r--r--arch/sh/configs/sh7785lcr_defconfig96
-rw-r--r--arch/sh/configs/shmin_defconfig54
-rw-r--r--arch/sh/configs/shx3_defconfig83
-rw-r--r--arch/sh/configs/snapgear_defconfig53
-rw-r--r--arch/sh/configs/systemh_defconfig50
-rw-r--r--arch/sh/configs/titan_defconfig90
-rw-r--r--arch/sh/configs/ul2_defconfig69
-rw-r--r--arch/sh/drivers/pci/ops-cayman.c9
-rw-r--r--arch/sh/drivers/pci/pci.c22
-rw-r--r--arch/sh/include/asm/atomic.h7
-rw-r--r--arch/sh/include/asm/byteorder.h62
-rw-r--r--arch/sh/include/asm/mmu.h1
-rw-r--r--arch/sh/include/asm/posix_types_32.h8
-rw-r--r--arch/sh/include/asm/posix_types_64.h8
-rw-r--r--arch/sh/include/asm/smp.h2
-rw-r--r--arch/sh/include/asm/swab.h60
-rw-r--r--arch/sh/include/asm/syscalls_32.h6
-rw-r--r--arch/sh/include/asm/topology.h2
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7343.c31
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c2
-rw-r--r--arch/sh/kernel/init_task.c1
-rw-r--r--arch/sh/kernel/process_64.c2
-rw-r--r--arch/sh/kernel/smp.c10
-rw-r--r--arch/sh/kernel/sys_sh32.c2
-rw-r--r--arch/sh/kernel/syscalls_32.S4
-rw-r--r--arch/sh/kernel/syscalls_64.S2
-rw-r--r--arch/sh/kernel/timers/timer-broadcast.c2
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c2
-rw-r--r--arch/sh/kernel/traps_32.c10
-rw-r--r--arch/sh/mm/init.c3
-rw-r--r--arch/sh/mm/ioremap_64.c2
-rw-r--r--arch/sparc/Kconfig58
-rw-r--r--arch/sparc/configs/sparc32_defconfig290
-rw-r--r--arch/sparc/configs/sparc64_defconfig109
-rw-r--r--arch/sparc/include/asm/Kbuild20
-rw-r--r--arch/sparc/include/asm/atomic_32.h2
-rw-r--r--arch/sparc/include/asm/atomic_64.h3
-rw-r--r--arch/sparc/include/asm/byteorder.h47
-rw-r--r--arch/sparc/include/asm/cpudata_64.h2
-rw-r--r--arch/sparc/include/asm/ipcbuf.h38
-rw-r--r--arch/sparc/include/asm/ipcbuf_32.h31
-rw-r--r--arch/sparc/include/asm/ipcbuf_64.h28
-rw-r--r--arch/sparc/include/asm/irq_64.h4
-rw-r--r--arch/sparc/include/asm/jsflash.h2
-rw-r--r--arch/sparc/include/asm/kdebug_64.h2
-rw-r--r--arch/sparc/include/asm/nmi.h10
-rw-r--r--arch/sparc/include/asm/openprom.h277
-rw-r--r--arch/sparc/include/asm/openprom_32.h255
-rw-r--r--arch/sparc/include/asm/openprom_64.h280
-rw-r--r--arch/sparc/include/asm/oplib_32.h11
-rw-r--r--arch/sparc/include/asm/oplib_64.h10
-rw-r--r--arch/sparc/include/asm/pcr.h46
-rw-r--r--arch/sparc/include/asm/pil.h1
-rw-r--r--arch/sparc/include/asm/posix_types.h157
-rw-r--r--arch/sparc/include/asm/posix_types_32.h118
-rw-r--r--arch/sparc/include/asm/posix_types_64.h122
-rw-r--r--arch/sparc/include/asm/processor_32.h2
-rw-r--r--arch/sparc/include/asm/ptrace.h448
-rw-r--r--arch/sparc/include/asm/ptrace_32.h186
-rw-r--r--arch/sparc/include/asm/ptrace_64.h356
-rw-r--r--arch/sparc/include/asm/reg.h8
-rw-r--r--arch/sparc/include/asm/reg_32.h79
-rw-r--r--arch/sparc/include/asm/reg_64.h56
-rw-r--r--arch/sparc/include/asm/sigcontext.h102
-rw-r--r--arch/sparc/include/asm/sigcontext_32.h62
-rw-r--r--arch/sparc/include/asm/sigcontext_64.h87
-rw-r--r--arch/sparc/include/asm/siginfo.h43
-rw-r--r--arch/sparc/include/asm/siginfo_32.h17
-rw-r--r--arch/sparc/include/asm/siginfo_64.h32
-rw-r--r--arch/sparc/include/asm/signal.h216
-rw-r--r--arch/sparc/include/asm/signal_32.h207
-rw-r--r--arch/sparc/include/asm/signal_64.h194
-rw-r--r--arch/sparc/include/asm/smp_32.h5
-rw-r--r--arch/sparc/include/asm/stat.h111
-rw-r--r--arch/sparc/include/asm/stat_32.h76
-rw-r--r--arch/sparc/include/asm/stat_64.h47
-rw-r--r--arch/sparc/include/asm/swab.h45
-rw-r--r--arch/sparc/include/asm/thread_info_32.h2
-rw-r--r--arch/sparc/include/asm/timer_64.h2
-rw-r--r--arch/sparc/include/asm/topology_64.h17
-rw-r--r--arch/sparc/include/asm/traps.h11
-rw-r--r--arch/sparc/include/asm/types.h2
-rw-r--r--arch/sparc/kernel/Makefile2
-rw-r--r--arch/sparc/kernel/auxio_32.c3
-rw-r--r--arch/sparc/kernel/auxio_64.c2
-rw-r--r--arch/sparc/kernel/central.c2
-rw-r--r--arch/sparc/kernel/cpu.c53
-rw-r--r--arch/sparc/kernel/ds.c34
-rw-r--r--arch/sparc/kernel/entry.S4
-rw-r--r--arch/sparc/kernel/idprom.c3
-rw-r--r--arch/sparc/kernel/init_task.c1
-rw-r--r--arch/sparc/kernel/iommu.c2
-rw-r--r--arch/sparc/kernel/ioport.c15
-rw-r--r--arch/sparc/kernel/irq_32.c3
-rw-r--r--arch/sparc/kernel/irq_64.c79
-rw-r--r--arch/sparc/kernel/kernel.h1
-rw-r--r--arch/sparc/kernel/kgdb_32.c12
-rw-r--r--arch/sparc/kernel/kprobes.c2
-rw-r--r--arch/sparc/kernel/ldc.c23
-rw-r--r--arch/sparc/kernel/mdesc.c14
-rw-r--r--arch/sparc/kernel/muldiv.c8
-rw-r--r--arch/sparc/kernel/nmi.c224
-rw-r--r--arch/sparc/kernel/of_device_64.c6
-rw-r--r--arch/sparc/kernel/pci.c3
-rw-r--r--arch/sparc/kernel/pci_common.c2
-rw-r--r--arch/sparc/kernel/pci_msi.c8
-rw-r--r--arch/sparc/kernel/pci_psycho.c5
-rw-r--r--arch/sparc/kernel/pci_schizo.c2
-rw-r--r--arch/sparc/kernel/pci_sun4v.c2
-rw-r--r--arch/sparc/kernel/pcic.c6
-rw-r--r--arch/sparc/kernel/pcr.c153
-rw-r--r--arch/sparc/kernel/power.c2
-rw-r--r--arch/sparc/kernel/process_32.c18
-rw-r--r--arch/sparc/kernel/process_64.c7
-rw-r--r--arch/sparc/kernel/prom_common.c14
-rw-r--r--arch/sparc/kernel/prom_irqtrans.c2
-rw-r--r--arch/sparc/kernel/psycho_common.c74
-rw-r--r--arch/sparc/kernel/sbus.c1
-rw-r--r--arch/sparc/kernel/setup_32.c3
-rw-r--r--arch/sparc/kernel/setup_64.c5
-rw-r--r--arch/sparc/kernel/signal_32.c6
-rw-r--r--arch/sparc/kernel/smp_32.c6
-rw-r--r--arch/sparc/kernel/smp_64.c8
-rw-r--r--arch/sparc/kernel/sparc_ksyms_32.c229
-rw-r--r--arch/sparc/kernel/sparc_ksyms_64.c252
-rw-r--r--arch/sparc/kernel/sun4d_smp.c4
-rw-r--r--arch/sparc/kernel/sun4m_smp.c5
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c50
-rw-r--r--arch/sparc/kernel/syscalls.S4
-rw-r--r--arch/sparc/kernel/systbls.h3
-rw-r--r--arch/sparc/kernel/systbls_32.S4
-rw-r--r--arch/sparc/kernel/systbls_64.S20
-rw-r--r--arch/sparc/kernel/time_32.c2
-rw-r--r--arch/sparc/kernel/time_64.c16
-rw-r--r--arch/sparc/kernel/traps_32.c5
-rw-r--r--arch/sparc/kernel/traps_64.c39
-rw-r--r--arch/sparc/kernel/ttable.S3
-rw-r--r--arch/sparc/kernel/unaligned_32.c12
-rw-r--r--arch/sparc/kernel/unaligned_64.c16
-rw-r--r--arch/sparc/kernel/vio.c4
-rw-r--r--arch/sparc/kernel/viohs.c6
-rw-r--r--arch/sparc/kernel/windows.c6
-rw-r--r--arch/sparc/lib/Makefile4
-rw-r--r--arch/sparc/lib/PeeCeeI.c8
-rw-r--r--arch/sparc/lib/ksyms.c196
-rw-r--r--arch/sparc/lib/user_fixup.c5
-rw-r--r--arch/sparc/mm/fault_32.c3
-rw-r--r--arch/sparc/mm/fault_64.c44
-rw-r--r--arch/sparc/mm/generic_32.c1
-rw-r--r--arch/sparc/mm/generic_64.c1
-rw-r--r--arch/sparc/mm/highmem.c2
-rw-r--r--arch/sparc/mm/init_32.c6
-rw-r--r--arch/sparc/mm/init_64.c52
-rw-r--r--arch/sparc/oprofile/init.c232
-rw-r--r--arch/sparc/prom/init_32.c4
-rw-r--r--arch/sparc/prom/misc_32.c3
-rw-r--r--arch/sparc/prom/misc_64.c3
-rw-r--r--arch/sparc/prom/ranges.c3
-rw-r--r--arch/sparc/prom/tree_32.c17
-rw-r--r--arch/sparc/prom/tree_64.c18
-rw-r--r--arch/um/Makefile25
-rw-r--r--arch/um/include/asm/system.h14
-rw-r--r--arch/um/kernel/init_task.c1
-rw-r--r--arch/um/kernel/smp.c7
-rw-r--r--arch/um/kernel/time.c2
-rw-r--r--arch/um/kernel/trap.c24
-rw-r--r--arch/x86/Kconfig27
-rw-r--r--arch/x86/Kconfig.cpu2
-rw-r--r--arch/x86/boot/video-vesa.c11
-rw-r--r--arch/x86/configs/i386_defconfig4
-rw-r--r--arch/x86/configs/x86_64_defconfig4
-rw-r--r--arch/x86/ia32/ia32_signal.c3
-rw-r--r--arch/x86/ia32/ipc32.c1
-rw-r--r--arch/x86/ia32/sys_ia32.c2
-rw-r--r--arch/x86/include/asm/amd_iommu_types.h61
-rw-r--r--arch/x86/include/asm/apic.h3
-rw-r--r--arch/x86/include/asm/atomic_32.h10
-rw-r--r--arch/x86/include/asm/atomic_64.h18
-rw-r--r--arch/x86/include/asm/bigsmp/apic.h32
-rw-r--r--arch/x86/include/asm/bigsmp/ipi.h13
-rw-r--r--arch/x86/include/asm/bitops.h14
-rw-r--r--arch/x86/include/asm/byteorder.h61
-rw-r--r--arch/x86/include/asm/desc.h10
-rw-r--r--arch/x86/include/asm/dma-mapping.h4
-rw-r--r--arch/x86/include/asm/e820.h1
-rw-r--r--arch/x86/include/asm/efi.h1
-rw-r--r--arch/x86/include/asm/es7000/apic.h62
-rw-r--r--arch/x86/include/asm/es7000/ipi.h12
-rw-r--r--arch/x86/include/asm/es7000/mpparse.h3
-rw-r--r--arch/x86/include/asm/genapic_32.h21
-rw-r--r--arch/x86/include/asm/genapic_64.h14
-rw-r--r--arch/x86/include/asm/io.h1
-rw-r--r--arch/x86/include/asm/ipi.h23
-rw-r--r--arch/x86/include/asm/irq.h3
-rw-r--r--arch/x86/include/asm/kvm.h2
-rw-r--r--arch/x86/include/asm/kvm_host.h47
-rw-r--r--arch/x86/include/asm/kvm_x86_emulate.h11
-rw-r--r--arch/x86/include/asm/lguest.h2
-rw-r--r--arch/x86/include/asm/mach-default/mach_apic.h28
-rw-r--r--arch/x86/include/asm/mach-default/mach_ipi.h18
-rw-r--r--arch/x86/include/asm/mach-default/mach_mpparse.h4
-rw-r--r--arch/x86/include/asm/mach-default/mach_wakecpu.h6
-rw-r--r--arch/x86/include/asm/mach-generic/mach_apic.h1
-rw-r--r--arch/x86/include/asm/mach-generic/mach_mpparse.h5
-rw-r--r--arch/x86/include/asm/mach-generic/mach_mpspec.h4
-rw-r--r--arch/x86/include/asm/mce.h5
-rw-r--r--arch/x86/include/asm/mpspec.h2
-rw-r--r--arch/x86/include/asm/mpspec_def.h102
-rw-r--r--arch/x86/include/asm/msr-index.h29
-rw-r--r--arch/x86/include/asm/mtrr.h26
-rw-r--r--arch/x86/include/asm/numaq/apic.h16
-rw-r--r--arch/x86/include/asm/numaq/ipi.h13
-rw-r--r--arch/x86/include/asm/numaq/mpparse.h3
-rw-r--r--arch/x86/include/asm/pci.h10
-rw-r--r--arch/x86/include/asm/pci_x86.h (renamed from arch/x86/pci/pci.h)17
-rw-r--r--arch/x86/include/asm/pgalloc.h1
-rw-r--r--arch/x86/include/asm/pgtable.h19
-rw-r--r--arch/x86/include/asm/ptrace-abi.h2
-rw-r--r--arch/x86/include/asm/setup.h14
-rw-r--r--arch/x86/include/asm/sigcontext.h2
-rw-r--r--arch/x86/include/asm/sigcontext32.h2
-rw-r--r--arch/x86/include/asm/smp.h38
-rw-r--r--arch/x86/include/asm/summit/apic.h40
-rw-r--r--arch/x86/include/asm/summit/ipi.h9
-rw-r--r--arch/x86/include/asm/summit/mpparse.h2
-rw-r--r--arch/x86/include/asm/svm.h (renamed from arch/x86/kvm/svm.h)0
-rw-r--r--arch/x86/include/asm/swab.h61
-rw-r--r--arch/x86/include/asm/swiotlb.h38
-rw-r--r--arch/x86/include/asm/sys_ia32.h101
-rw-r--r--arch/x86/include/asm/syscalls.h2
-rw-r--r--arch/x86/include/asm/timex.h13
-rw-r--r--arch/x86/include/asm/topology.h38
-rw-r--r--arch/x86/include/asm/unwind.h13
-rw-r--r--arch/x86/include/asm/uv/uv_bau.h46
-rw-r--r--arch/x86/include/asm/virtext.h132
-rw-r--r--arch/x86/include/asm/vmx.h (renamed from arch/x86/kvm/vmx.h)27
-rw-r--r--arch/x86/kernel/acpi/boot.c48
-rw-r--r--arch/x86/kernel/acpi/cstate.c74
-rw-r--r--arch/x86/kernel/acpi/sleep.c2
-rw-r--r--arch/x86/kernel/amd_iommu.c666
-rw-r--r--arch/x86/kernel/amd_iommu_init.c19
-rw-r--r--arch/x86/kernel/apic.c68
-rw-r--r--arch/x86/kernel/apm_32.c4
-rw-r--r--arch/x86/kernel/bios_uv.c2
-rw-r--r--arch/x86/kernel/cpu/common.c28
-rw-r--r--arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c188
-rw-r--r--arch/x86/kernel/cpu/cpufreq/longhaul.c2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/p4-clockmod.c14
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k7.c9
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.c30
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.h2
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c72
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-ich.c18
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-lib.c9
-rw-r--r--arch/x86/kernel/cpu/intel.c13
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c60
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_32.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd_64.c108
-rw-r--r--arch/x86/kernel/cpu/mcheck/p5.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/p6.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/winchip.c2
-rw-r--r--arch/x86/kernel/cpu/mtrr/generic.c22
-rw-r--r--arch/x86/kernel/cpu/mtrr/main.c13
-rw-r--r--arch/x86/kernel/cpu/mtrr/mtrr.h18
-rw-r--r--arch/x86/kernel/cpuid.c8
-rw-r--r--arch/x86/kernel/crash.c18
-rw-r--r--arch/x86/kernel/ds.c31
-rw-r--r--arch/x86/kernel/e820.c21
-rw-r--r--arch/x86/kernel/early-quirks.c22
-rw-r--r--arch/x86/kernel/early_printk.c2
-rw-r--r--arch/x86/kernel/entry_32.S2
-rw-r--r--arch/x86/kernel/entry_64.S1
-rw-r--r--arch/x86/kernel/genapic_flat_64.c107
-rw-r--r--arch/x86/kernel/genx2apic_cluster.c81
-rw-r--r--arch/x86/kernel/genx2apic_phys.c78
-rw-r--r--arch/x86/kernel/genx2apic_uv_x.c61
-rw-r--r--arch/x86/kernel/head64.c2
-rw-r--r--arch/x86/kernel/head_64.S2
-rw-r--r--arch/x86/kernel/hpet.c11
-rw-r--r--arch/x86/kernel/i8253.c2
-rw-r--r--arch/x86/kernel/i8259.c8
-rw-r--r--arch/x86/kernel/init_task.c1
-rw-r--r--arch/x86/kernel/io_apic.c391
-rw-r--r--arch/x86/kernel/ioport.c4
-rw-r--r--arch/x86/kernel/ipi.c28
-rw-r--r--arch/x86/kernel/irq.c5
-rw-r--r--arch/x86/kernel/irq_32.c23
-rw-r--r--arch/x86/kernel/irq_64.c37
-rw-r--r--arch/x86/kernel/irqinit_32.c40
-rw-r--r--arch/x86/kernel/irqinit_64.c21
-rw-r--r--arch/x86/kernel/kprobes.c11
-rw-r--r--arch/x86/kernel/kvmclock.c10
-rw-r--r--arch/x86/kernel/ldt.c4
-rw-r--r--arch/x86/kernel/mfgpt_32.c4
-rw-r--r--arch/x86/kernel/mmconf-fam10h_64.c3
-rw-r--r--arch/x86/kernel/mpparse.c357
-rw-r--r--arch/x86/kernel/msr.c2
-rw-r--r--arch/x86/kernel/nmi.c2
-rw-r--r--arch/x86/kernel/numaq_32.c38
-rw-r--r--arch/x86/kernel/pci-dma.c2
-rw-r--r--arch/x86/kernel/pci-gart_64.c4
-rw-r--r--arch/x86/kernel/pci-swiotlb_64.c4
-rw-r--r--arch/x86/kernel/process_32.c19
-rw-r--r--arch/x86/kernel/reboot.c73
-rw-r--r--arch/x86/kernel/setup_percpu.c72
-rw-r--r--arch/x86/kernel/signal.c11
-rw-r--r--arch/x86/kernel/smp.c25
-rw-r--r--arch/x86/kernel/smpboot.c176
-rw-r--r--arch/x86/kernel/syscall_table_32.S2
-rw-r--r--arch/x86/kernel/time_32.c4
-rw-r--r--arch/x86/kernel/time_64.c2
-rw-r--r--arch/x86/kernel/tlb_32.c2
-rw-r--r--arch/x86/kernel/tlb_64.c2
-rw-r--r--arch/x86/kernel/tlb_uv.c10
-rw-r--r--arch/x86/kernel/traps.c50
-rw-r--r--arch/x86/kernel/visws_quirks.c32
-rw-r--r--arch/x86/kernel/vmi_32.c2
-rw-r--r--arch/x86/kernel/vmiclock_32.c2
-rw-r--r--arch/x86/kernel/xsave.c2
-rw-r--r--arch/x86/kvm/Makefile4
-rw-r--r--arch/x86/kvm/i8254.c19
-rw-r--r--arch/x86/kvm/i8259.c52
-rw-r--r--arch/x86/kvm/irq.h6
-rw-r--r--arch/x86/kvm/kvm_svm.h2
-rw-r--r--arch/x86/kvm/lapic.c58
-rw-r--r--arch/x86/kvm/mmu.c444
-rw-r--r--arch/x86/kvm/paging_tmpl.h44
-rw-r--r--arch/x86/kvm/svm.c48
-rw-r--r--arch/x86/kvm/vmx.c350
-rw-r--r--arch/x86/kvm/x86.c120
-rw-r--r--arch/x86/kvm/x86_emulate.c297
-rw-r--r--arch/x86/lguest/boot.c6
-rw-r--r--arch/x86/lib/usercopy_32.c4
-rw-r--r--arch/x86/lib/usercopy_64.c4
-rw-r--r--arch/x86/mach-default/setup.c27
-rw-r--r--arch/x86/mach-generic/bigsmp.c5
-rw-r--r--arch/x86/mach-generic/es7000.c15
-rw-r--r--arch/x86/mach-generic/numaq.c8
-rw-r--r--arch/x86/mach-generic/probe.c3
-rw-r--r--arch/x86/mach-generic/summit.c5
-rw-r--r--arch/x86/mach-voyager/setup.c12
-rw-r--r--arch/x86/mach-voyager/voyager_smp.c41
-rw-r--r--arch/x86/mm/fault.c26
-rw-r--r--arch/x86/mm/init_32.c60
-rw-r--r--arch/x86/mm/init_64.c6
-rw-r--r--arch/x86/mm/iomap_32.c10
-rw-r--r--arch/x86/mm/ioremap.c25
-rw-r--r--arch/x86/mm/k8topology_64.c20
-rw-r--r--arch/x86/mm/numa_32.c4
-rw-r--r--arch/x86/mm/numa_64.c4
-rw-r--r--arch/x86/mm/pageattr.c49
-rw-r--r--arch/x86/mm/pat.c88
-rw-r--r--arch/x86/mm/srat_64.c2
-rw-r--r--arch/x86/oprofile/op_model_amd.c149
-rw-r--r--arch/x86/pci/acpi.c9
-rw-r--r--arch/x86/pci/amd_bus.c2
-rw-r--r--arch/x86/pci/common.c15
-rw-r--r--arch/x86/pci/direct.c2
-rw-r--r--arch/x86/pci/early.c2
-rw-r--r--arch/x86/pci/fixup.c3
-rw-r--r--arch/x86/pci/i386.c18
-rw-r--r--arch/x86/pci/init.c5
-rw-r--r--arch/x86/pci/irq.c58
-rw-r--r--arch/x86/pci/legacy.c2
-rw-r--r--arch/x86/pci/mmconfig-shared.c3
-rw-r--r--arch/x86/pci/mmconfig_32.c2
-rw-r--r--arch/x86/pci/mmconfig_64.c3
-rw-r--r--arch/x86/pci/numaq_32.c2
-rw-r--r--arch/x86/pci/olpc.c2
-rw-r--r--arch/x86/pci/pcbios.c5
-rw-r--r--arch/x86/pci/visws.c23
-rw-r--r--arch/x86/scripts/strip-symbols1
-rw-r--r--arch/x86/xen/mmu.c20
-rw-r--r--arch/x86/xen/multicalls.h4
-rw-r--r--arch/x86/xen/smp.c27
-rw-r--r--arch/x86/xen/suspend.c3
-rw-r--r--arch/x86/xen/time.c12
-rw-r--r--arch/x86/xen/xen-ops.h2
-rw-r--r--arch/xtensa/Makefile28
-rw-r--r--arch/xtensa/boot/boot-elf/boot.lds.S2
-rw-r--r--arch/xtensa/boot/boot-redboot/bootstrap.S2
-rw-r--r--arch/xtensa/include/asm/Kbuild (renamed from arch/m68knommu/include/asm/Kbuild)0
-rw-r--r--arch/xtensa/include/asm/asmmacro.h (renamed from include/asm-xtensa/asmmacro.h)2
-rw-r--r--arch/xtensa/include/asm/atomic.h (renamed from include/asm-xtensa/atomic.h)3
-rw-r--r--arch/xtensa/include/asm/auxvec.h (renamed from include/asm-xtensa/auxvec.h)0
-rw-r--r--arch/xtensa/include/asm/bitops.h (renamed from include/asm-xtensa/bitops.h)11
-rw-r--r--arch/xtensa/include/asm/bootparam.h (renamed from include/asm-xtensa/bootparam.h)0
-rw-r--r--arch/xtensa/include/asm/bug.h (renamed from include/asm-xtensa/bug.h)0
-rw-r--r--arch/xtensa/include/asm/bugs.h (renamed from include/asm-xtensa/bugs.h)0
-rw-r--r--arch/xtensa/include/asm/byteorder.h12
-rw-r--r--arch/xtensa/include/asm/cache.h (renamed from include/asm-xtensa/cache.h)2
-rw-r--r--arch/xtensa/include/asm/cacheasm.h (renamed from include/asm-xtensa/cacheasm.h)0
-rw-r--r--arch/xtensa/include/asm/cacheflush.h (renamed from include/asm-xtensa/cacheflush.h)0
-rw-r--r--arch/xtensa/include/asm/checksum.h (renamed from include/asm-xtensa/checksum.h)2
-rw-r--r--arch/xtensa/include/asm/coprocessor.h (renamed from include/asm-xtensa/coprocessor.h)4
-rw-r--r--arch/xtensa/include/asm/cpumask.h (renamed from include/asm-xtensa/cpumask.h)0
-rw-r--r--arch/xtensa/include/asm/cputime.h (renamed from include/asm-xtensa/cputime.h)0
-rw-r--r--arch/xtensa/include/asm/current.h (renamed from include/asm-xtensa/current.h)0
-rw-r--r--arch/xtensa/include/asm/delay.h (renamed from include/asm-xtensa/delay.h)0
-rw-r--r--arch/xtensa/include/asm/device.h (renamed from include/asm-m68k/device.h)0
-rw-r--r--arch/xtensa/include/asm/div64.h (renamed from include/asm-xtensa/div64.h)0
-rw-r--r--arch/xtensa/include/asm/dma-mapping.h (renamed from include/asm-xtensa/dma-mapping.h)0
-rw-r--r--arch/xtensa/include/asm/dma.h (renamed from include/asm-xtensa/dma.h)0
-rw-r--r--arch/xtensa/include/asm/elf.h (renamed from include/asm-xtensa/elf.h)0
-rw-r--r--arch/xtensa/include/asm/emergency-restart.h (renamed from include/asm-m68k/emergency-restart.h)0
-rw-r--r--arch/xtensa/include/asm/errno.h (renamed from include/asm-xtensa/errno.h)0
-rw-r--r--arch/xtensa/include/asm/fb.h (renamed from include/asm-xtensa/fb.h)0
-rw-r--r--arch/xtensa/include/asm/fcntl.h (renamed from include/asm-xtensa/fcntl.h)0
-rw-r--r--arch/xtensa/include/asm/futex.h (renamed from include/asm-xtensa/futex.h)0
-rw-r--r--arch/xtensa/include/asm/hardirq.h (renamed from include/asm-xtensa/hardirq.h)0
-rw-r--r--arch/xtensa/include/asm/highmem.h (renamed from include/asm-xtensa/highmem.h)0
-rw-r--r--arch/xtensa/include/asm/hw_irq.h (renamed from include/asm-xtensa/hw_irq.h)0
-rw-r--r--arch/xtensa/include/asm/io.h (renamed from include/asm-xtensa/io.h)0
-rw-r--r--arch/xtensa/include/asm/ioctl.h (renamed from include/asm-m68k/ioctl.h)0
-rw-r--r--arch/xtensa/include/asm/ioctls.h (renamed from include/asm-xtensa/ioctls.h)0
-rw-r--r--arch/xtensa/include/asm/ipcbuf.h (renamed from include/asm-xtensa/ipcbuf.h)0
-rw-r--r--arch/xtensa/include/asm/irq.h (renamed from include/asm-xtensa/irq.h)4
-rw-r--r--arch/xtensa/include/asm/irq_regs.h (renamed from include/asm-m68k/irq_regs.h)0
-rw-r--r--arch/xtensa/include/asm/kdebug.h (renamed from include/asm-m68k/kdebug.h)0
-rw-r--r--arch/xtensa/include/asm/kmap_types.h (renamed from include/asm-xtensa/kmap_types.h)0
-rw-r--r--arch/xtensa/include/asm/linkage.h (renamed from include/asm-xtensa/linkage.h)0
-rw-r--r--arch/xtensa/include/asm/local.h (renamed from include/asm-xtensa/local.h)0
-rw-r--r--arch/xtensa/include/asm/mman.h (renamed from include/asm-xtensa/mman.h)0
-rw-r--r--arch/xtensa/include/asm/mmu.h (renamed from include/asm-xtensa/mmu.h)0
-rw-r--r--arch/xtensa/include/asm/mmu_context.h (renamed from include/asm-xtensa/mmu_context.h)0
-rw-r--r--arch/xtensa/include/asm/module.h (renamed from include/asm-xtensa/module.h)0
-rw-r--r--arch/xtensa/include/asm/msgbuf.h (renamed from include/asm-xtensa/msgbuf.h)0
-rw-r--r--arch/xtensa/include/asm/mutex.h (renamed from include/asm-m68k/mutex.h)0
-rw-r--r--arch/xtensa/include/asm/page.h (renamed from include/asm-xtensa/page.h)0
-rw-r--r--arch/xtensa/include/asm/param.h (renamed from include/asm-xtensa/param.h)0
-rw-r--r--arch/xtensa/include/asm/pci-bridge.h (renamed from include/asm-xtensa/pci-bridge.h)0
-rw-r--r--arch/xtensa/include/asm/pci.h (renamed from include/asm-xtensa/pci.h)0
-rw-r--r--arch/xtensa/include/asm/percpu.h (renamed from include/asm-xtensa/percpu.h)0
-rw-r--r--arch/xtensa/include/asm/pgalloc.h (renamed from include/asm-xtensa/pgalloc.h)0
-rw-r--r--arch/xtensa/include/asm/pgtable.h (renamed from include/asm-xtensa/pgtable.h)0
-rw-r--r--arch/xtensa/include/asm/platform.h (renamed from include/asm-xtensa/platform.h)2
-rw-r--r--arch/xtensa/include/asm/poll.h (renamed from include/asm-xtensa/poll.h)0
-rw-r--r--arch/xtensa/include/asm/posix_types.h (renamed from include/asm-xtensa/posix_types.h)0
-rw-r--r--arch/xtensa/include/asm/processor.h (renamed from include/asm-xtensa/processor.h)2
-rw-r--r--arch/xtensa/include/asm/ptrace.h (renamed from include/asm-xtensa/ptrace.h)2
-rw-r--r--arch/xtensa/include/asm/regs.h (renamed from include/asm-xtensa/regs.h)0
-rw-r--r--arch/xtensa/include/asm/resource.h (renamed from include/asm-xtensa/resource.h)0
-rw-r--r--arch/xtensa/include/asm/rmap.h (renamed from include/asm-xtensa/rmap.h)0
-rw-r--r--arch/xtensa/include/asm/rwsem.h (renamed from include/asm-xtensa/rwsem.h)0
-rw-r--r--arch/xtensa/include/asm/scatterlist.h (renamed from include/asm-xtensa/scatterlist.h)0
-rw-r--r--arch/xtensa/include/asm/sections.h (renamed from include/asm-xtensa/sections.h)0
-rw-r--r--arch/xtensa/include/asm/segment.h (renamed from include/asm-xtensa/segment.h)0
-rw-r--r--arch/xtensa/include/asm/sembuf.h (renamed from include/asm-xtensa/sembuf.h)0
-rw-r--r--arch/xtensa/include/asm/serial.h (renamed from include/asm-xtensa/serial.h)2
-rw-r--r--arch/xtensa/include/asm/setup.h (renamed from include/asm-xtensa/setup.h)0
-rw-r--r--arch/xtensa/include/asm/shmbuf.h (renamed from include/asm-xtensa/shmbuf.h)0
-rw-r--r--arch/xtensa/include/asm/shmparam.h (renamed from include/asm-xtensa/shmparam.h)0
-rw-r--r--arch/xtensa/include/asm/sigcontext.h (renamed from include/asm-xtensa/sigcontext.h)0
-rw-r--r--arch/xtensa/include/asm/siginfo.h (renamed from include/asm-xtensa/siginfo.h)0
-rw-r--r--arch/xtensa/include/asm/signal.h (renamed from include/asm-xtensa/signal.h)0
-rw-r--r--arch/xtensa/include/asm/smp.h (renamed from include/asm-xtensa/smp.h)0
-rw-r--r--arch/xtensa/include/asm/socket.h (renamed from include/asm-xtensa/socket.h)0
-rw-r--r--arch/xtensa/include/asm/sockios.h (renamed from include/asm-xtensa/sockios.h)0
-rw-r--r--arch/xtensa/include/asm/spinlock.h (renamed from include/asm-xtensa/spinlock.h)0
-rw-r--r--arch/xtensa/include/asm/stat.h (renamed from include/asm-xtensa/stat.h)0
-rw-r--r--arch/xtensa/include/asm/statfs.h (renamed from include/asm-xtensa/statfs.h)0
-rw-r--r--arch/xtensa/include/asm/string.h (renamed from include/asm-xtensa/string.h)0
-rw-r--r--arch/xtensa/include/asm/swab.h (renamed from include/asm-xtensa/byteorder.h)32
-rw-r--r--arch/xtensa/include/asm/syscall.h (renamed from include/asm-xtensa/syscall.h)0
-rw-r--r--arch/xtensa/include/asm/system.h (renamed from include/asm-xtensa/system.h)0
-rw-r--r--arch/xtensa/include/asm/termbits.h (renamed from include/asm-xtensa/termbits.h)0
-rw-r--r--arch/xtensa/include/asm/termios.h (renamed from include/asm-xtensa/termios.h)0
-rw-r--r--arch/xtensa/include/asm/thread_info.h (renamed from include/asm-xtensa/thread_info.h)0
-rw-r--r--arch/xtensa/include/asm/timex.h (renamed from include/asm-xtensa/timex.h)0
-rw-r--r--arch/xtensa/include/asm/tlb.h (renamed from include/asm-xtensa/tlb.h)0
-rw-r--r--arch/xtensa/include/asm/tlbflush.h (renamed from include/asm-xtensa/tlbflush.h)0
-rw-r--r--arch/xtensa/include/asm/topology.h (renamed from include/asm-xtensa/topology.h)0
-rw-r--r--arch/xtensa/include/asm/types.h (renamed from include/asm-xtensa/types.h)0
-rw-r--r--arch/xtensa/include/asm/uaccess.h (renamed from include/asm-xtensa/uaccess.h)0
-rw-r--r--arch/xtensa/include/asm/ucontext.h (renamed from include/asm-xtensa/ucontext.h)0
-rw-r--r--arch/xtensa/include/asm/unaligned.h (renamed from include/asm-xtensa/unaligned.h)12
-rw-r--r--arch/xtensa/include/asm/unistd.h (renamed from include/asm-xtensa/unistd.h)0
-rw-r--r--arch/xtensa/include/asm/user.h (renamed from include/asm-xtensa/user.h)0
-rw-r--r--arch/xtensa/include/asm/vga.h (renamed from include/asm-xtensa/vga.h)0
-rw-r--r--arch/xtensa/include/asm/xor.h (renamed from include/asm-xtensa/xor.h)0
-rw-r--r--arch/xtensa/kernel/entry.S2
-rw-r--r--arch/xtensa/kernel/init_task.c1
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S2
-rw-r--r--arch/xtensa/lib/checksum.S2
-rw-r--r--arch/xtensa/lib/memcopy.S2
-rw-r--r--arch/xtensa/lib/memset.S2
-rw-r--r--arch/xtensa/lib/strncpy_user.S2
-rw-r--r--arch/xtensa/lib/strnlen_user.S2
-rw-r--r--arch/xtensa/lib/usercopy.S2
-rw-r--r--arch/xtensa/platforms/iss/console.c4
-rw-r--r--arch/xtensa/platforms/iss/include/platform/hardware.h (renamed from include/asm-xtensa/platform-iss/hardware.h)0
-rw-r--r--arch/xtensa/platforms/iss/include/platform/simcall.h (renamed from include/asm-xtensa/platform-iss/simcall.h)0
-rw-r--r--arch/xtensa/platforms/iss/io.c2
-rw-r--r--arch/xtensa/platforms/iss/network.c4
-rw-r--r--arch/xtensa/platforms/xt2000/Makefile5
-rw-r--r--arch/xtensa/platforms/xt2000/include/platform/hardware.h55
-rw-r--r--arch/xtensa/platforms/xt2000/include/platform/serial.h28
-rw-r--r--arch/xtensa/platforms/xt2000/setup.c181
-rw-r--r--arch/xtensa/variants/dc232b/include/variant/core.h (renamed from include/asm-xtensa/variant-dc232b/core.h)0
-rw-r--r--arch/xtensa/variants/dc232b/include/variant/tie-asm.h (renamed from include/asm-xtensa/variant-dc232b/tie-asm.h)0
-rw-r--r--arch/xtensa/variants/dc232b/include/variant/tie.h (renamed from include/asm-xtensa/variant-dc232b/tie.h)0
-rw-r--r--arch/xtensa/variants/fsf/include/variant/core.h (renamed from include/asm-xtensa/variant-fsf/core.h)0
-rw-r--r--arch/xtensa/variants/fsf/include/variant/tie-asm.h (renamed from include/asm-xtensa/variant-fsf/tie-asm.h)0
-rw-r--r--arch/xtensa/variants/fsf/include/variant/tie.h (renamed from include/asm-xtensa/variant-fsf/tie.h)0
-rw-r--r--block/Kconfig6
-rw-r--r--block/blk-barrier.c2
-rw-r--r--block/blk-core.c100
-rw-r--r--block/blk-integrity.c25
-rw-r--r--block/blk-map.c19
-rw-r--r--block/blk-sysfs.c58
-rw-r--r--block/blk.h12
-rw-r--r--block/blktrace.c72
-rw-r--r--block/bsg.c6
-rw-r--r--block/cfq-iosched.c39
-rw-r--r--block/genhd.c2
-rw-r--r--crypto/async_tx/async_tx.c350
-rw-r--r--crypto/authenc.c24
-rw-r--r--crypto/blkcipher.c2
-rw-r--r--crypto/ccm.c2
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile6
-rw-r--r--drivers/acpi/Kconfig84
-rw-r--r--drivers/acpi/Makefile25
-rw-r--r--drivers/acpi/acpi_memhotplug.c2
-rw-r--r--drivers/acpi/acpica/Makefile44
-rw-r--r--drivers/acpi/acpica/accommon.h63
-rw-r--r--drivers/acpi/acpica/acconfig.h (renamed from include/acpi/acconfig.h)8
-rw-r--r--drivers/acpi/acpica/acdebug.h (renamed from include/acpi/acdebug.h)0
-rw-r--r--drivers/acpi/acpica/acdispat.h (renamed from include/acpi/acdispat.h)0
-rw-r--r--drivers/acpi/acpica/acevents.h (renamed from include/acpi/acevents.h)6
-rw-r--r--drivers/acpi/acpica/acglobal.h (renamed from include/acpi/acglobal.h)9
-rw-r--r--drivers/acpi/acpica/achware.h (renamed from include/acpi/achware.h)22
-rw-r--r--drivers/acpi/acpica/acinterp.h (renamed from include/acpi/acinterp.h)0
-rw-r--r--drivers/acpi/acpica/aclocal.h (renamed from include/acpi/aclocal.h)86
-rw-r--r--drivers/acpi/acpica/acmacros.h (renamed from include/acpi/acmacros.h)126
-rw-r--r--drivers/acpi/acpica/acnamesp.h (renamed from include/acpi/acnamesp.h)5
-rw-r--r--drivers/acpi/acpica/acobject.h (renamed from include/acpi/acobject.h)0
-rw-r--r--drivers/acpi/acpica/acopcode.h (renamed from include/acpi/acopcode.h)0
-rw-r--r--drivers/acpi/acpica/acparser.h (renamed from include/acpi/acparser.h)0
-rw-r--r--drivers/acpi/acpica/acpredef.h (renamed from include/acpi/acpredef.h)0
-rw-r--r--drivers/acpi/acpica/acresrc.h (renamed from include/acpi/acresrc.h)0
-rw-r--r--drivers/acpi/acpica/acstruct.h (renamed from include/acpi/acstruct.h)0
-rw-r--r--drivers/acpi/acpica/actables.h (renamed from include/acpi/actables.h)2
-rw-r--r--drivers/acpi/acpica/acutils.h (renamed from include/acpi/acutils.h)36
-rw-r--r--drivers/acpi/acpica/amlcode.h (renamed from include/acpi/amlcode.h)0
-rw-r--r--drivers/acpi/acpica/amlresrc.h (renamed from include/acpi/amlresrc.h)0
-rw-r--r--drivers/acpi/acpica/dsfield.c (renamed from drivers/acpi/dispatcher/dsfield.c)11
-rw-r--r--drivers/acpi/acpica/dsinit.c (renamed from drivers/acpi/dispatcher/dsinit.c)7
-rw-r--r--drivers/acpi/acpica/dsmethod.c (renamed from drivers/acpi/dispatcher/dsmethod.c)14
-rw-r--r--drivers/acpi/acpica/dsmthdat.c (renamed from drivers/acpi/dispatcher/dsmthdat.c)7
-rw-r--r--drivers/acpi/acpica/dsobject.c (renamed from drivers/acpi/dispatcher/dsobject.c)11
-rw-r--r--drivers/acpi/acpica/dsopcode.c (renamed from drivers/acpi/dispatcher/dsopcode.c)66
-rw-r--r--drivers/acpi/acpica/dsutils.c (renamed from drivers/acpi/dispatcher/dsutils.c)13
-rw-r--r--drivers/acpi/acpica/dswexec.c (renamed from drivers/acpi/dispatcher/dswexec.c)13
-rw-r--r--drivers/acpi/acpica/dswload.c (renamed from drivers/acpi/dispatcher/dswload.c)13
-rw-r--r--drivers/acpi/acpica/dswscope.c (renamed from drivers/acpi/dispatcher/dswscope.c)3
-rw-r--r--drivers/acpi/acpica/dswstate.c (renamed from drivers/acpi/dispatcher/dswstate.c)7
-rw-r--r--drivers/acpi/acpica/evevent.c (renamed from drivers/acpi/events/evevent.c)17
-rw-r--r--drivers/acpi/acpica/evgpe.c (renamed from drivers/acpi/events/evgpe.c)53
-rw-r--r--drivers/acpi/acpica/evgpeblk.c (renamed from drivers/acpi/events/evgpeblk.c)82
-rw-r--r--drivers/acpi/acpica/evmisc.c (renamed from drivers/acpi/events/evmisc.c)62
-rw-r--r--drivers/acpi/acpica/evregion.c (renamed from drivers/acpi/events/evregion.c)140
-rw-r--r--drivers/acpi/acpica/evrgnini.c (renamed from drivers/acpi/events/evrgnini.c)46
-rw-r--r--drivers/acpi/acpica/evsci.c (renamed from drivers/acpi/events/evsci.c)13
-rw-r--r--drivers/acpi/acpica/evxface.c (renamed from drivers/acpi/events/evxface.c)9
-rw-r--r--drivers/acpi/acpica/evxfevnt.c (renamed from drivers/acpi/events/evxfevnt.c)170
-rw-r--r--drivers/acpi/acpica/evxfregn.c (renamed from drivers/acpi/events/evxfregn.c)5
-rw-r--r--drivers/acpi/acpica/exconfig.c (renamed from drivers/acpi/executer/exconfig.c)9
-rw-r--r--drivers/acpi/acpica/exconvrt.c (renamed from drivers/acpi/executer/exconvrt.c)5
-rw-r--r--drivers/acpi/acpica/excreate.c (renamed from drivers/acpi/executer/excreate.c)7
-rw-r--r--drivers/acpi/acpica/exdump.c (renamed from drivers/acpi/executer/exdump.c)7
-rw-r--r--drivers/acpi/acpica/exfield.c (renamed from drivers/acpi/executer/exfield.c)5
-rw-r--r--drivers/acpi/acpica/exfldio.c (renamed from drivers/acpi/executer/exfldio.c)20
-rw-r--r--drivers/acpi/acpica/exmisc.c (renamed from drivers/acpi/executer/exmisc.c)7
-rw-r--r--drivers/acpi/acpica/exmutex.c (renamed from drivers/acpi/executer/exmutex.c)5
-rw-r--r--drivers/acpi/acpica/exnames.c (renamed from drivers/acpi/executer/exnames.c)5
-rw-r--r--drivers/acpi/acpica/exoparg1.c (renamed from drivers/acpi/executer/exoparg1.c)11
-rw-r--r--drivers/acpi/acpica/exoparg2.c (renamed from drivers/acpi/executer/exoparg2.c)9
-rw-r--r--drivers/acpi/acpica/exoparg3.c (renamed from drivers/acpi/executer/exoparg3.c)7
-rw-r--r--drivers/acpi/acpica/exoparg6.c (renamed from drivers/acpi/executer/exoparg6.c)7
-rw-r--r--drivers/acpi/acpica/exprep.c (renamed from drivers/acpi/executer/exprep.c)9
-rw-r--r--drivers/acpi/acpica/exregion.c (renamed from drivers/acpi/executer/exregion.c)3
-rw-r--r--drivers/acpi/acpica/exresnte.c (renamed from drivers/acpi/executer/exresnte.c)7
-rw-r--r--drivers/acpi/acpica/exresolv.c (renamed from drivers/acpi/executer/exresolv.c)11
-rw-r--r--drivers/acpi/acpica/exresop.c (renamed from drivers/acpi/executer/exresop.c)9
-rw-r--r--drivers/acpi/acpica/exstore.c (renamed from drivers/acpi/executer/exstore.c)11
-rw-r--r--drivers/acpi/acpica/exstoren.c (renamed from drivers/acpi/executer/exstoren.c)5
-rw-r--r--drivers/acpi/acpica/exstorob.c (renamed from drivers/acpi/executer/exstorob.c)3
-rw-r--r--drivers/acpi/acpica/exsystem.c (renamed from drivers/acpi/executer/exsystem.c)3
-rw-r--r--drivers/acpi/acpica/exutils.c (renamed from drivers/acpi/executer/exutils.c)5
-rw-r--r--drivers/acpi/acpica/hwacpi.c (renamed from drivers/acpi/hardware/hwacpi.c)1
-rw-r--r--drivers/acpi/acpica/hwgpe.c (renamed from drivers/acpi/hardware/hwgpe.c)78
-rw-r--r--drivers/acpi/acpica/hwregs.c353
-rw-r--r--drivers/acpi/acpica/hwsleep.c (renamed from drivers/acpi/hardware/hwsleep.c)76
-rw-r--r--drivers/acpi/acpica/hwtimer.c (renamed from drivers/acpi/hardware/hwtimer.c)1
-rw-r--r--drivers/acpi/acpica/hwxface.c (renamed from drivers/acpi/hardware/hwregs.c)744
-rw-r--r--drivers/acpi/acpica/nsaccess.c (renamed from drivers/acpi/namespace/nsaccess.c)18
-rw-r--r--drivers/acpi/acpica/nsalloc.c (renamed from drivers/acpi/namespace/nsalloc.c)3
-rw-r--r--drivers/acpi/acpica/nsdump.c (renamed from drivers/acpi/namespace/nsdump.c)3
-rw-r--r--drivers/acpi/acpica/nsdumpdv.c (renamed from drivers/acpi/namespace/nsdumpdv.c)3
-rw-r--r--drivers/acpi/acpica/nseval.c (renamed from drivers/acpi/namespace/nseval.c)77
-rw-r--r--drivers/acpi/acpica/nsinit.c (renamed from drivers/acpi/namespace/nsinit.c)7
-rw-r--r--drivers/acpi/acpica/nsload.c (renamed from drivers/acpi/namespace/nsload.c)7
-rw-r--r--drivers/acpi/acpica/nsnames.c (renamed from drivers/acpi/namespace/nsnames.c)5
-rw-r--r--drivers/acpi/acpica/nsobject.c (renamed from drivers/acpi/namespace/nsobject.c)3
-rw-r--r--drivers/acpi/acpica/nsparse.c (renamed from drivers/acpi/namespace/nsparse.c)9
-rw-r--r--drivers/acpi/acpica/nspredef.c (renamed from drivers/acpi/namespace/nspredef.c)261
-rw-r--r--drivers/acpi/acpica/nssearch.c (renamed from drivers/acpi/namespace/nssearch.c)3
-rw-r--r--drivers/acpi/acpica/nsutils.c (renamed from drivers/acpi/namespace/nsutils.c)15
-rw-r--r--drivers/acpi/acpica/nswalk.c (renamed from drivers/acpi/namespace/nswalk.c)3
-rw-r--r--drivers/acpi/acpica/nsxfeval.c (renamed from drivers/acpi/namespace/nsxfeval.c)5
-rw-r--r--drivers/acpi/acpica/nsxfname.c (renamed from drivers/acpi/namespace/nsxfname.c)3
-rw-r--r--drivers/acpi/acpica/nsxfobj.c (renamed from drivers/acpi/namespace/nsxfobj.c)3
-rw-r--r--drivers/acpi/acpica/psargs.c (renamed from drivers/acpi/parser/psargs.c)9
-rw-r--r--drivers/acpi/acpica/psloop.c (renamed from drivers/acpi/parser/psloop.c)7
-rw-r--r--drivers/acpi/acpica/psopcode.c (renamed from drivers/acpi/parser/psopcode.c)7
-rw-r--r--drivers/acpi/acpica/psparse.c (renamed from drivers/acpi/parser/psparse.c)23
-rw-r--r--drivers/acpi/acpica/psscope.c (renamed from drivers/acpi/parser/psscope.c)3
-rw-r--r--drivers/acpi/acpica/pstree.c (renamed from drivers/acpi/parser/pstree.c)5
-rw-r--r--drivers/acpi/acpica/psutils.c (renamed from drivers/acpi/parser/psutils.c)5
-rw-r--r--drivers/acpi/acpica/pswalk.c (renamed from drivers/acpi/parser/pswalk.c)3
-rw-r--r--drivers/acpi/acpica/psxface.c (renamed from drivers/acpi/parser/psxface.c)40
-rw-r--r--drivers/acpi/acpica/rsaddr.c (renamed from drivers/acpi/resources/rsaddr.c)3
-rw-r--r--drivers/acpi/acpica/rscalc.c (renamed from drivers/acpi/resources/rscalc.c)5
-rw-r--r--drivers/acpi/acpica/rscreate.c (renamed from drivers/acpi/resources/rscreate.c)7
-rw-r--r--drivers/acpi/acpica/rsdump.c (renamed from drivers/acpi/resources/rsdump.c)3
-rw-r--r--drivers/acpi/acpica/rsinfo.c (renamed from drivers/acpi/resources/rsinfo.c)3
-rw-r--r--drivers/acpi/acpica/rsio.c (renamed from drivers/acpi/resources/rsio.c)3
-rw-r--r--drivers/acpi/acpica/rsirq.c (renamed from drivers/acpi/resources/rsirq.c)3
-rw-r--r--drivers/acpi/acpica/rslist.c (renamed from drivers/acpi/resources/rslist.c)3
-rw-r--r--drivers/acpi/acpica/rsmemory.c (renamed from drivers/acpi/resources/rsmemory.c)3
-rw-r--r--drivers/acpi/acpica/rsmisc.c (renamed from drivers/acpi/resources/rsmisc.c)3
-rw-r--r--drivers/acpi/acpica/rsutils.c (renamed from drivers/acpi/resources/rsutils.c)5
-rw-r--r--drivers/acpi/acpica/rsxface.c (renamed from drivers/acpi/resources/rsxface.c)5
-rw-r--r--drivers/acpi/acpica/tbfadt.c (renamed from drivers/acpi/tables/tbfadt.c)252
-rw-r--r--drivers/acpi/acpica/tbfind.c (renamed from drivers/acpi/tables/tbfind.c)3
-rw-r--r--drivers/acpi/acpica/tbinstal.c (renamed from drivers/acpi/tables/tbinstal.c)5
-rw-r--r--drivers/acpi/acpica/tbutils.c (renamed from drivers/acpi/tables/tbutils.c)30
-rw-r--r--drivers/acpi/acpica/tbxface.c (renamed from drivers/acpi/tables/tbxface.c)5
-rw-r--r--drivers/acpi/acpica/tbxfroot.c (renamed from drivers/acpi/tables/tbxfroot.c)3
-rw-r--r--drivers/acpi/acpica/utalloc.c (renamed from drivers/acpi/utilities/utalloc.c)3
-rw-r--r--drivers/acpi/acpica/utcopy.c (renamed from drivers/acpi/utilities/utcopy.c)3
-rw-r--r--drivers/acpi/acpica/utdebug.c (renamed from drivers/acpi/utilities/utdebug.c)95
-rw-r--r--drivers/acpi/acpica/utdelete.c (renamed from drivers/acpi/utilities/utdelete.c)7
-rw-r--r--drivers/acpi/acpica/uteval.c (renamed from drivers/acpi/utilities/uteval.c)11
-rw-r--r--drivers/acpi/acpica/utglobal.c (renamed from drivers/acpi/utilities/utglobal.c)12
-rw-r--r--drivers/acpi/acpica/utinit.c (renamed from drivers/acpi/utilities/utinit.c)7
-rw-r--r--drivers/acpi/acpica/utmath.c (renamed from drivers/acpi/utilities/utmath.c)1
-rw-r--r--drivers/acpi/acpica/utmisc.c (renamed from drivers/acpi/utilities/utmisc.c)23
-rw-r--r--drivers/acpi/acpica/utmutex.c (renamed from drivers/acpi/utilities/utmutex.c)1
-rw-r--r--drivers/acpi/acpica/utobject.c (renamed from drivers/acpi/utilities/utobject.c)7
-rw-r--r--drivers/acpi/acpica/utresrc.c (renamed from drivers/acpi/utilities/utresrc.c)3
-rw-r--r--drivers/acpi/acpica/utstate.c (renamed from drivers/acpi/utilities/utstate.c)1
-rw-r--r--drivers/acpi/acpica/utxface.c (renamed from drivers/acpi/utilities/utxface.c)18
-rw-r--r--drivers/acpi/battery.c5
-rw-r--r--drivers/acpi/cm_sbs.c3
-rw-r--r--drivers/acpi/debug.c1
-rw-r--r--drivers/acpi/dispatcher/Makefile9
-rw-r--r--drivers/acpi/ec.c106
-rw-r--r--drivers/acpi/events/Makefile9
-rw-r--r--drivers/acpi/executer/Makefile10
-rw-r--r--drivers/acpi/hardware/Makefile9
-rw-r--r--drivers/acpi/namespace/Makefile12
-rw-r--r--drivers/acpi/numa.c1
-rw-r--r--drivers/acpi/osl.c4
-rw-r--r--drivers/acpi/parser/Makefile8
-rw-r--r--drivers/acpi/pci_bind.c90
-rw-r--r--drivers/acpi/pci_irq.c472
-rw-r--r--drivers/acpi/pci_link.c6
-rw-r--r--drivers/acpi/pci_root.c20
-rw-r--r--drivers/acpi/power.c6
-rw-r--r--drivers/acpi/proc.c (renamed from drivers/acpi/sleep/proc.c)65
-rw-r--r--drivers/acpi/processor_core.c14
-rw-r--r--drivers/acpi/processor_idle.c1
-rw-r--r--drivers/acpi/processor_perflib.c28
-rw-r--r--drivers/acpi/processor_throttling.c80
-rw-r--r--drivers/acpi/reboot.c2
-rw-r--r--drivers/acpi/resources/Makefile10
-rw-r--r--drivers/acpi/sbshc.c1
-rw-r--r--drivers/acpi/scan.c1
-rw-r--r--drivers/acpi/sleep.c (renamed from drivers/acpi/sleep/main.c)79
-rw-r--r--drivers/acpi/sleep.h (renamed from drivers/acpi/sleep/sleep.h)0
-rw-r--r--drivers/acpi/sleep/Makefile5
-rw-r--r--drivers/acpi/system.c63
-rw-r--r--drivers/acpi/tables/Makefile7
-rw-r--r--drivers/acpi/thermal.c16
-rw-r--r--drivers/acpi/utilities/Makefile9
-rw-r--r--drivers/acpi/utilities/utcache.c314
-rw-r--r--drivers/acpi/video.c20
-rw-r--r--drivers/acpi/video_detect.c4
-rw-r--r--drivers/acpi/wakeup.c (renamed from drivers/acpi/sleep/wakeup.c)6
-rw-r--r--drivers/amba/bus.c3
-rw-r--r--drivers/ata/Kconfig15
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ahci.c52
-rw-r--r--drivers/ata/ata_piix.c85
-rw-r--r--drivers/ata/libata-acpi.c6
-rw-r--r--drivers/ata/libata-core.c297
-rw-r--r--drivers/ata/libata-eh.c87
-rw-r--r--drivers/ata/libata-pmp.c2
-rw-r--r--drivers/ata/libata-scsi.c40
-rw-r--r--drivers/ata/libata-sff.c228
-rw-r--r--drivers/ata/libata.h4
-rw-r--r--drivers/ata/pata_acpi.c6
-rw-r--r--drivers/ata/pata_ali.c111
-rw-r--r--drivers/ata/pata_amd.c4
-rw-r--r--drivers/ata/pata_atiixp.c32
-rw-r--r--drivers/ata/pata_hpt366.c109
-rw-r--r--drivers/ata/pata_hpt3x3.c49
-rw-r--r--drivers/ata/pata_it821x.c17
-rw-r--r--drivers/ata/pata_mpiix.c3
-rw-r--r--drivers/ata/pata_octeon_cf.c965
-rw-r--r--drivers/ata/pata_platform.c2
-rw-r--r--drivers/ata/pata_qdi.c2
-rw-r--r--drivers/ata/pata_rb532_cf.c2
-rw-r--r--drivers/ata/pata_sil680.c4
-rw-r--r--drivers/ata/pata_via.c22
-rw-r--r--drivers/ata/sata_fsl.c2
-rw-r--r--drivers/ata/sata_mv.c60
-rw-r--r--drivers/ata/sata_nv.c77
-rw-r--r--drivers/ata/sata_sil.c39
-rw-r--r--drivers/ata/sata_sil24.c7
-rw-r--r--drivers/ata/sata_via.c2
-rw-r--r--drivers/atm/iphase.c6
-rw-r--r--drivers/base/Kconfig2
-rw-r--r--drivers/base/Makefile1
-rw-r--r--drivers/base/attribute_container.c2
-rw-r--r--drivers/base/bus.c12
-rw-r--r--drivers/base/core.c158
-rw-r--r--drivers/base/cpu.c46
-rw-r--r--drivers/base/dd.c13
-rw-r--r--drivers/base/firmware_class.c8
-rw-r--r--drivers/base/iommu.c100
-rw-r--r--drivers/base/isa.c7
-rw-r--r--drivers/base/memory.c19
-rw-r--r--drivers/base/node.c107
-rw-r--r--drivers/base/platform.c130
-rw-r--r--drivers/base/power/main.c21
-rw-r--r--drivers/base/power/trace.c4
-rw-r--r--drivers/base/topology.c5
-rw-r--r--drivers/block/amiflop.c40
-rw-r--r--drivers/block/nbd.c4
-rw-r--r--drivers/block/ps3disk.c18
-rw-r--r--drivers/block/sunvdc.c8
-rw-r--r--drivers/block/ub.c11
-rw-r--r--drivers/block/xsysace.c1
-rw-r--r--drivers/char/Kconfig18
-rw-r--r--drivers/char/amiserial.c70
-rw-r--r--drivers/char/bsr.c2
-rw-r--r--drivers/char/consolemap.c2
-rw-r--r--drivers/char/cyclades.c2
-rw-r--r--drivers/char/epca.c267
-rw-r--r--drivers/char/esp.c61
-rw-r--r--drivers/char/generic_serial.c76
-rw-r--r--drivers/char/hvc_beat.c4
-rw-r--r--drivers/char/hvc_console.c14
-rw-r--r--drivers/char/hvc_irq.c2
-rw-r--r--drivers/char/hvc_iucv.c420
-rw-r--r--drivers/char/hvsi.c12
-rw-r--r--drivers/char/hw_random/n2-drv.c2
-rw-r--r--drivers/char/hw_random/omap-rng.c2
-rw-r--r--drivers/char/i8k.c16
-rw-r--r--drivers/char/isicom.c166
-rw-r--r--drivers/char/istallion.c221
-rw-r--r--drivers/char/mem.c3
-rw-r--r--drivers/char/moxa.c26
-rw-r--r--drivers/char/mwave/mwavedd.c2
-rw-r--r--drivers/char/mxser.c150
-rw-r--r--drivers/char/n_r3964.c12
-rw-r--r--drivers/char/n_tty.c792
-rw-r--r--drivers/char/nozomi.c85
-rw-r--r--drivers/char/pcmcia/synclink_cs.c479
-rw-r--r--drivers/char/ps3flash.c18
-rw-r--r--drivers/char/pty.c57
-rw-r--r--drivers/char/random.c45
-rw-r--r--drivers/char/rio/rio_linux.c35
-rw-r--r--drivers/char/riscom8.c194
-rw-r--r--drivers/char/rocket.c320
-rw-r--r--drivers/char/rocket.h2
-rw-r--r--drivers/char/rocket_int.h5
-rw-r--r--drivers/char/rtc.c17
-rw-r--r--drivers/char/selection.c4
-rw-r--r--drivers/char/ser_a2232.c35
-rw-r--r--drivers/char/serial167.c32
-rw-r--r--drivers/char/specialix.c34
-rw-r--r--drivers/char/stallion.c169
-rw-r--r--drivers/char/sx.c39
-rw-r--r--drivers/char/synclink.c177
-rw-r--r--drivers/char/synclink_gt.c136
-rw-r--r--drivers/char/synclinkmp.c171
-rw-r--r--drivers/char/sysrq.c26
-rw-r--r--drivers/char/tpm/tpm_bios.c2
-rw-r--r--drivers/char/tpm/tpm_nsc.c35
-rw-r--r--drivers/char/tty_io.c43
-rw-r--r--drivers/char/tty_ioctl.c2
-rw-r--r--drivers/char/tty_ldisc.c30
-rw-r--r--drivers/char/tty_port.c225
-rw-r--r--drivers/char/vme_scc.c193
-rw-r--r--drivers/char/vt.c17
-rw-r--r--drivers/char/vt_ioctl.c2
-rw-r--r--drivers/clocksource/tcb_clksrc.c2
-rw-r--r--drivers/cpufreq/Kconfig4
-rw-r--r--drivers/cpufreq/cpufreq.c97
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c2
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c4
-rw-r--r--drivers/cpuidle/governors/menu.c10
-rw-r--r--drivers/dca/dca-core.c53
-rw-r--r--drivers/dio/dio-sysfs.c19
-rw-r--r--drivers/dio/dio.c18
-rw-r--r--drivers/dma/Kconfig21
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/dmaengine.c774
-rw-r--r--drivers/dma/dmatest.c164
-rw-r--r--drivers/dma/dw_dmac.c119
-rw-r--r--drivers/dma/fsldma.c11
-rw-r--r--drivers/dma/ioat.c92
-rw-r--r--drivers/dma/ioat_dma.c18
-rw-r--r--drivers/dma/iop-adma.c30
-rw-r--r--drivers/dma/ipu/Makefile1
-rw-r--r--drivers/dma/ipu/ipu_idmac.c1740
-rw-r--r--drivers/dma/ipu/ipu_intern.h176
-rw-r--r--drivers/dma/ipu/ipu_irq.c413
-rw-r--r--drivers/dma/mv_xor.c11
-rw-r--r--drivers/edac/Kconfig7
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/cell_edac.c8
-rw-r--r--drivers/edac/edac_device.c2
-rw-r--r--drivers/edac/edac_mc.c2
-rw-r--r--drivers/edac/edac_pci.c2
-rw-r--r--drivers/edac/edac_pci_sysfs.c6
-rw-r--r--drivers/edac/i5400_edac.c1476
-rw-r--r--drivers/edac/i82875p_edac.c4
-rw-r--r--drivers/edac/mpc85xx_edac.c74
-rw-r--r--drivers/firewire/fw-card.c37
-rw-r--r--drivers/firewire/fw-device.c154
-rw-r--r--drivers/firewire/fw-device.h3
-rw-r--r--drivers/firewire/fw-ohci.c6
-rw-r--r--drivers/firewire/fw-sbp2.c110
-rw-r--r--drivers/firewire/fw-topology.c24
-rw-r--r--drivers/firewire/fw-transaction.c2
-rw-r--r--drivers/firewire/fw-transaction.h22
-rw-r--r--drivers/firmware/dcdbas.c9
-rw-r--r--drivers/firmware/dcdbas.h2
-rw-r--r--drivers/firmware/dell_rbu.c4
-rw-r--r--drivers/firmware/dmi-id.c2
-rw-r--r--drivers/firmware/dmi_scan.c80
-rw-r--r--drivers/firmware/memmap.c6
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/gpiolib.c3
-rw-r--r--drivers/gpio/max7301.c6
-rw-r--r--drivers/gpio/max732x.c6
-rw-r--r--drivers/gpio/mcp23s08.c6
-rw-r--r--drivers/gpio/pca953x.c18
-rw-r--r--drivers/gpio/pcf857x.c12
-rw-r--r--drivers/gpio/twl4030-gpio.c54
-rw-r--r--drivers/gpu/drm/drm_agpsupport.c3
-rw-r--r--drivers/gpu/drm/drm_crtc.c14
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c175
-rw-r--r--drivers/gpu/drm/drm_drv.c10
-rw-r--r--drivers/gpu/drm/drm_edid.c2
-rw-r--r--drivers/gpu/drm/drm_fops.c4
-rw-r--r--drivers/gpu/drm/drm_gem.c2
-rw-r--r--drivers/gpu/drm/drm_irq.c173
-rw-r--r--drivers/gpu/drm/drm_stub.c8
-rw-r--r--drivers/gpu/drm/drm_sysfs.c2
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c63
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h25
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c208
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c6
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h25
-rw-r--r--drivers/gpu/drm/i915/intel_display.c75
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h5
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c280
-rw-r--r--drivers/gpu/drm/i915/intel_i2c.c4
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c22
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c8
-rw-r--r--drivers/hid/Kconfig70
-rw-r--r--drivers/hid/Makefile5
-rw-r--r--drivers/hid/hid-bright.c71
-rw-r--r--drivers/hid/hid-core.c124
-rw-r--r--drivers/hid/hid-dell.c76
-rw-r--r--drivers/hid/hid-dummy.c6
-rw-r--r--drivers/hid/hid-gaff.c185
-rw-r--r--drivers/hid/hid-ids.h23
-rw-r--r--drivers/hid/hid-lg.c7
-rw-r--r--drivers/hid/hid-microsoft.c13
-rw-r--r--drivers/hid/hid-ntrig.c82
-rw-r--r--drivers/hid/hid-sony.c2
-rw-r--r--drivers/hid/hid-topseed.c77
-rw-r--r--drivers/hid/hidraw.c32
-rw-r--r--drivers/hid/usbhid/Kconfig2
-rw-r--r--drivers/hid/usbhid/hid-core.c43
-rw-r--r--drivers/hid/usbhid/hid-quirks.c1
-rw-r--r--drivers/hid/usbhid/hiddev.c137
-rw-r--r--drivers/hid/usbhid/usbhid.h10
-rw-r--r--drivers/hwmon/Kconfig71
-rw-r--r--drivers/hwmon/Makefile5
-rw-r--r--drivers/hwmon/abituguru3.c24
-rw-r--r--drivers/hwmon/adt7462.c14
-rw-r--r--drivers/hwmon/adt7470.c227
-rw-r--r--drivers/hwmon/adt7473.c10
-rw-r--r--drivers/hwmon/adt7475.c1221
-rw-r--r--drivers/hwmon/applesmc.c45
-rw-r--r--drivers/hwmon/asb100.c5
-rw-r--r--drivers/hwmon/dme1737.c5
-rw-r--r--drivers/hwmon/f71805f.c5
-rw-r--r--drivers/hwmon/f71882fg.c1549
-rw-r--r--drivers/hwmon/fschmd.c450
-rw-r--r--drivers/hwmon/hp_accel.c339
-rw-r--r--drivers/hwmon/hwmon.c2
-rw-r--r--drivers/hwmon/i5k_amb.c7
-rw-r--r--drivers/hwmon/ibmpex.c2
-rw-r--r--drivers/hwmon/it87.c37
-rw-r--r--drivers/hwmon/k8temp.c55
-rw-r--r--drivers/hwmon/lis3lv02d.c273
-rw-r--r--drivers/hwmon/lis3lv02d.h35
-rw-r--r--drivers/hwmon/lm70.c91
-rw-r--r--drivers/hwmon/lm75.c2
-rw-r--r--drivers/hwmon/ltc4245.c567
-rw-r--r--drivers/hwmon/pc87360.c6
-rw-r--r--drivers/hwmon/pc87427.c5
-rw-r--r--drivers/hwmon/sis5595.c5
-rw-r--r--drivers/hwmon/smsc47b397.c5
-rw-r--r--drivers/hwmon/smsc47m1.c5
-rw-r--r--drivers/hwmon/via686a.c5
-rw-r--r--drivers/hwmon/vt1211.c5
-rw-r--r--drivers/hwmon/vt8231.c5
-rw-r--r--drivers/hwmon/w83627ehf.c8
-rw-r--r--drivers/hwmon/w83627hf.c5
-rw-r--r--drivers/hwmon/w83781d.c5
-rw-r--r--drivers/hwmon/w83791d.c5
-rw-r--r--drivers/hwmon/w83792d.c5
-rw-r--r--drivers/hwmon/w83793.c5
-rw-r--r--drivers/i2c/busses/i2c-acorn.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c5
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c1
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c4
-rw-r--r--drivers/i2c/busses/i2c-amd756.c6
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c1
-rw-r--r--drivers/i2c/busses/i2c-at91.c2
-rw-r--r--drivers/i2c/busses/i2c-au1550.c1
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c3
-rw-r--r--drivers/i2c/busses/i2c-elektor.c1
-rw-r--r--drivers/i2c/busses/i2c-hydra.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c51
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c1
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c1
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c1
-rw-r--r--drivers/i2c/busses/i2c-mpc.c1
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c1
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c1
-rw-r--r--drivers/i2c/busses/i2c-omap.c420
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c1
-rw-r--r--drivers/i2c/busses/i2c-parport.c1
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c1
-rw-r--r--drivers/i2c/busses/i2c-piix4.c1
-rw-r--r--drivers/i2c/busses/i2c-pxa.c4
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c187
-rw-r--r--drivers/i2c/busses/i2c-sh7760.c2
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c2
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c2
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c5
-rw-r--r--drivers/i2c/busses/i2c-sis630.c5
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c1
-rw-r--r--drivers/i2c/busses/i2c-via.c1
-rw-r--r--drivers/i2c/busses/i2c-viapro.c1
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c2
-rw-r--r--drivers/i2c/busses/scx200_acb.c1
-rw-r--r--drivers/i2c/busses/scx200_i2c.c1
-rw-r--r--drivers/i2c/chips/Kconfig83
-rw-r--r--drivers/i2c/chips/Makefile6
-rw-r--r--drivers/i2c/i2c-core.c8
-rw-r--r--drivers/ide/Kconfig40
-rw-r--r--drivers/ide/Makefile4
-rw-r--r--drivers/ide/aec62xx.c4
-rw-r--r--drivers/ide/alim15x3.c10
-rw-r--r--drivers/ide/amd74xx.c4
-rw-r--r--drivers/ide/au1xxx-ide.c11
-rw-r--r--drivers/ide/cmd640.c5
-rw-r--r--drivers/ide/cmd64x.c23
-rw-r--r--drivers/ide/cs5520.c2
-rw-r--r--drivers/ide/cs5536.c308
-rw-r--r--drivers/ide/cy82c693.c2
-rw-r--r--drivers/ide/falconide.c3
-rw-r--r--drivers/ide/hpt366.c23
-rw-r--r--drivers/ide/icside.c14
-rw-r--r--drivers/ide/ide-acpi.c30
-rw-r--r--drivers/ide/ide-atapi.c257
-rw-r--r--drivers/ide/ide-cd.c190
-rw-r--r--drivers/ide/ide-cd.h46
-rw-r--r--drivers/ide/ide-disk.c6
-rw-r--r--drivers/ide/ide-dma-sff.c63
-rw-r--r--drivers/ide/ide-dma.c2
-rw-r--r--drivers/ide/ide-floppy.c30
-rw-r--r--drivers/ide/ide-floppy_ioctl.c58
-rw-r--r--drivers/ide/ide-gd.c3
-rw-r--r--drivers/ide/ide-gd.h10
-rw-r--r--drivers/ide/ide-h8300.c1
-rw-r--r--drivers/ide/ide-io.c627
-rw-r--r--drivers/ide/ide-ioctls.c3
-rw-r--r--drivers/ide/ide-iops.c100
-rw-r--r--drivers/ide/ide-lib.c9
-rw-r--r--drivers/ide/ide-park.c25
-rw-r--r--drivers/ide/ide-pm.c20
-rw-r--r--drivers/ide/ide-probe.c715
-rw-r--r--drivers/ide/ide-proc.c23
-rw-r--r--drivers/ide/ide-sysfs.c125
-rw-r--r--drivers/ide/ide-tape.c22
-rw-r--r--drivers/ide/ide-taskfile.c14
-rw-r--r--drivers/ide/ide.c259
-rw-r--r--drivers/ide/it8172.c166
-rw-r--r--drivers/ide/it8213.c4
-rw-r--r--drivers/ide/it821x.c28
-rw-r--r--drivers/ide/ns87415.c14
-rw-r--r--drivers/ide/palm_bk3710.c14
-rw-r--r--drivers/ide/pdc202xx_new.c4
-rw-r--r--drivers/ide/pdc202xx_old.c14
-rw-r--r--drivers/ide/piix.c8
-rw-r--r--drivers/ide/pmac.c7
-rw-r--r--drivers/ide/q40ide.c1
-rw-r--r--drivers/ide/qd65xx.c9
-rw-r--r--drivers/ide/qd65xx.h6
-rw-r--r--drivers/ide/sc1200.c9
-rw-r--r--drivers/ide/scc_pata.c33
-rw-r--r--drivers/ide/serverworks.c2
-rw-r--r--drivers/ide/setup-pci.c12
-rw-r--r--drivers/ide/sgiioc4.c15
-rw-r--r--drivers/ide/siimage.c11
-rw-r--r--drivers/ide/sis5513.c2
-rw-r--r--drivers/ide/sl82c105.c9
-rw-r--r--drivers/ide/slc90e66.c4
-rw-r--r--drivers/ide/tc86c001.c17
-rw-r--r--drivers/ide/triflex.c2
-rw-r--r--drivers/ide/trm290.c10
-rw-r--r--drivers/ide/tx4938ide.c12
-rw-r--r--drivers/ide/tx4939ide.c70
-rw-r--r--drivers/ide/umc8672.c13
-rw-r--r--drivers/ide/via82cxxx.c9
-rw-r--r--drivers/idle/i7300_idle.c2
-rw-r--r--drivers/ieee1394/csr.c12
-rw-r--r--drivers/ieee1394/csr.h10
-rw-r--r--drivers/ieee1394/csr1212.c45
-rw-r--r--drivers/ieee1394/csr1212.h9
-rw-r--r--drivers/ieee1394/dv1394-private.h44
-rw-r--r--drivers/ieee1394/dv1394.c12
-rw-r--r--drivers/ieee1394/eth1394.c82
-rw-r--r--drivers/ieee1394/eth1394.h17
-rw-r--r--drivers/ieee1394/highlevel.c9
-rw-r--r--drivers/ieee1394/highlevel.h7
-rw-r--r--drivers/ieee1394/hosts.c6
-rw-r--r--drivers/ieee1394/hosts.h2
-rw-r--r--drivers/ieee1394/ieee1394.h7
-rw-r--r--drivers/ieee1394/ieee1394_core.c16
-rw-r--r--drivers/ieee1394/nodemgr.c20
-rw-r--r--drivers/ieee1394/nodemgr.h3
-rw-r--r--drivers/ieee1394/ohci1394.c26
-rw-r--r--drivers/ieee1394/ohci1394.h2
-rw-r--r--drivers/ieee1394/pcilynx.c3
-rw-r--r--drivers/ieee1394/pcilynx.h2
-rw-r--r--drivers/ieee1394/raw1394.c2
-rw-r--r--drivers/ieee1394/sbp2.c58
-rw-r--r--drivers/infiniband/core/sysfs.c2
-rw-r--r--drivers/infiniband/core/ucm.c3
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c16
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c35
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c8
-rw-r--r--drivers/infiniband/hw/ehca/ehca_mcast.c4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_mrmw.c144
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c32
-rw-r--r--drivers/infiniband/hw/ehca/ehca_reqs.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_sqp.c2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_tools.h2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_uverbs.c2
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.c56
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c8
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c3
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c2
-rw-r--r--drivers/infiniband/hw/mlx4/main.c13
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c28
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c14
-rw-r--r--drivers/infiniband/hw/nes/nes_utils.c4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c65
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c11
-rw-r--r--drivers/infiniband/ulp/iser/Kconfig2
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c3
-rw-r--r--drivers/input/Makefile2
-rw-r--r--drivers/input/evbug.c6
-rw-r--r--drivers/input/evdev.c199
-rw-r--r--drivers/input/gameport/gameport.c3
-rw-r--r--drivers/input/gameport/ns558.c2
-rw-r--r--drivers/input/input-compat.c135
-rw-r--r--drivers/input/input-compat.h94
-rw-r--r--drivers/input/input.c4
-rw-r--r--drivers/input/joydev.c2
-rw-r--r--drivers/input/joystick/Kconfig24
-rw-r--r--drivers/input/joystick/Makefile2
-rw-r--r--drivers/input/joystick/maplecontrol.c193
-rw-r--r--drivers/input/joystick/walkera0701.c292
-rw-r--r--drivers/input/keyboard/Kconfig9
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/atkbd.c62
-rw-r--r--drivers/input/keyboard/gpio_keys.c4
-rw-r--r--drivers/input/keyboard/hil_kbd.c1
-rw-r--r--drivers/input/keyboard/omap-keypad.c6
-rw-r--r--drivers/input/keyboard/pxa930_rotary.c212
-rw-r--r--drivers/input/misc/Kconfig7
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/apanel.c81
-rw-r--r--drivers/input/misc/pcf50633-input.c132
-rw-r--r--drivers/input/misc/pcspkr.c4
-rw-r--r--drivers/input/misc/uinput.c172
-rw-r--r--drivers/input/mouse/Kconfig6
-rw-r--r--drivers/input/mouse/Makefile27
-rw-r--r--drivers/input/mouse/appletouch.c274
-rw-r--r--drivers/input/mouse/gpio_mouse.c2
-rw-r--r--drivers/input/mouse/hgpk.c32
-rw-r--r--drivers/input/mouse/hil_ptr.c2
-rw-r--r--drivers/input/mouse/pxa930_trkball.c269
-rw-r--r--drivers/input/mouse/synaptics.c16
-rw-r--r--drivers/input/mousedev.c3
-rw-r--r--drivers/input/serio/hil_mlc.c1
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h15
-rw-r--r--drivers/input/serio/libps2.c20
-rw-r--r--drivers/input/serio/pcips2.c2
-rw-r--r--drivers/input/serio/serio.c4
-rw-r--r--drivers/input/serio/xilinx_ps2.c220
-rw-r--r--drivers/input/tablet/gtco.c2
-rw-r--r--drivers/input/tablet/wacom_wac.c2
-rw-r--r--drivers/input/touchscreen/Kconfig32
-rw-r--r--drivers/input/touchscreen/Makefile3
-rw-r--r--drivers/input/touchscreen/ads7846.c6
-rw-r--r--drivers/input/touchscreen/da9034-ts.c390
-rw-r--r--drivers/input/touchscreen/tsc2007.c381
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c5
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c325
-rw-r--r--drivers/isdn/capi/capidrv.c4
-rw-r--r--drivers/isdn/capi/capifs.c2
-rw-r--r--drivers/isdn/hardware/eicon/debuglib.h2
-rw-r--r--drivers/isdn/hardware/eicon/os_4bri.c2
-rw-r--r--drivers/isdn/hardware/eicon/os_bri.c2
-rw-r--r--drivers/isdn/hardware/eicon/os_pri.c2
-rw-r--r--drivers/isdn/hardware/mISDN/Kconfig7
-rw-r--r--drivers/isdn/hardware/mISDN/Makefile1
-rw-r--r--drivers/isdn/hardware/mISDN/hfc_multi.h10
-rw-r--r--drivers/isdn/hardware/mISDN/hfc_pci.h2
-rw-r--r--drivers/isdn/hardware/mISDN/hfcmulti.c209
-rw-r--r--drivers/isdn/hardware/mISDN/hfcpci.c241
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.c2196
-rw-r--r--drivers/isdn/hardware/mISDN/hfcsusb.h418
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c77
-rw-r--r--drivers/isdn/i4l/isdn_net.c70
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c2
-rw-r--r--drivers/isdn/mISDN/Makefile2
-rw-r--r--drivers/isdn/mISDN/clock.c216
-rw-r--r--drivers/isdn/mISDN/core.c280
-rw-r--r--drivers/isdn/mISDN/core.h2
-rw-r--r--drivers/isdn/mISDN/dsp.h2
-rw-r--r--drivers/isdn/mISDN/dsp_cmx.c149
-rw-r--r--drivers/isdn/mISDN/dsp_core.c55
-rw-r--r--drivers/isdn/mISDN/dsp_pipeline.c40
-rw-r--r--drivers/isdn/mISDN/hwchannel.c42
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c25
-rw-r--r--drivers/isdn/mISDN/layer1.c2
-rw-r--r--drivers/isdn/mISDN/socket.c41
-rw-r--r--drivers/isdn/mISDN/stack.c66
-rw-r--r--drivers/isdn/mISDN/tei.c6
-rw-r--r--drivers/leds/Kconfig22
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/led-class.c24
-rw-r--r--drivers/leds/leds-alix2.c181
-rw-r--r--drivers/leds/leds-ams-delta.c33
-rw-r--r--drivers/leds/leds-clevo-mail.c21
-rw-r--r--drivers/leds/leds-fsg.c37
-rw-r--r--drivers/leds/leds-gpio.c36
-rw-r--r--drivers/leds/leds-hp-disk.c155
-rw-r--r--drivers/leds/leds-hp6xx.c22
-rw-r--r--drivers/leds/leds-net48xx.c21
-rw-r--r--drivers/leds/leds-pca9532.c77
-rw-r--r--drivers/leds/leds-s3c24xx.c25
-rw-r--r--drivers/leds/leds-wm8350.c311
-rw-r--r--drivers/leds/leds-wrap.c27
-rw-r--r--drivers/leds/ledtrig-timer.c5
-rw-r--r--drivers/lguest/core.c2
-rw-r--r--drivers/lguest/interrupts_and_traps.c13
-rw-r--r--drivers/lguest/lguest_device.c10
-rw-r--r--drivers/lguest/lguest_user.c5
-rw-r--r--drivers/macintosh/Kconfig2
-rw-r--r--drivers/macintosh/macio_asic.c24
-rw-r--r--drivers/macintosh/therm_adt746x.c8
-rw-r--r--drivers/md/Makefile5
-rw-r--r--drivers/md/bitmap.c11
-rw-r--r--drivers/md/dm-crypt.c6
-rw-r--r--drivers/md/dm-delay.c6
-rw-r--r--drivers/md/dm-exception-store.c749
-rw-r--r--drivers/md/dm-exception-store.h148
-rw-r--r--drivers/md/dm-ioctl.c16
-rw-r--r--drivers/md/dm-linear.c6
-rw-r--r--drivers/md/dm-log.c40
-rw-r--r--drivers/md/dm-mpath.c14
-rw-r--r--drivers/md/dm-raid1.c24
-rw-r--r--drivers/md/dm-snap-persistent.c704
-rw-r--r--drivers/md/dm-snap-transient.c98
-rw-r--r--drivers/md/dm-snap.c48
-rw-r--r--drivers/md/dm-snap.h129
-rw-r--r--drivers/md/dm-stripe.c4
-rw-r--r--drivers/md/dm-sysfs.c99
-rw-r--r--drivers/md/dm-table.c47
-rw-r--r--drivers/md/dm-target.c15
-rw-r--r--drivers/md/dm-zero.c5
-rw-r--r--drivers/md/dm.c101
-rw-r--r--drivers/md/dm.h10
-rw-r--r--drivers/md/faulty.c3
-rw-r--r--drivers/md/linear.c3
-rw-r--r--drivers/md/md.c416
-rw-r--r--drivers/md/multipath.c3
-rw-r--r--drivers/md/raid0.c178
-rw-r--r--drivers/md/raid1.c11
-rw-r--r--drivers/md/raid10.c3
-rw-r--r--drivers/md/raid5.c8
-rw-r--r--drivers/media/common/saa7146_fops.c21
-rw-r--r--drivers/media/common/saa7146_video.c6
-rw-r--r--drivers/media/common/tuners/mxl5007t.c2
-rw-r--r--drivers/media/common/tuners/tda8290.c6
-rw-r--r--drivers/media/common/tuners/tuner-simple.c16
-rw-r--r--drivers/media/dvb/dm1105/Kconfig1
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c24
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.h6
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c26
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c57
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c8
-rw-r--r--drivers/media/dvb/dvb-usb/af9005-fe.c2
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c30
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c2
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c18
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h2
-rw-r--r--drivers/media/dvb/dvb-usb/gp8psk.c2
-rw-r--r--drivers/media/dvb/frontends/cx24116.c3
-rw-r--r--drivers/media/dvb/frontends/cx24116.h3
-rw-r--r--drivers/media/dvb/frontends/drx397xD.c2
-rw-r--r--drivers/media/dvb/frontends/lgdt3304.c10
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c7
-rw-r--r--drivers/media/dvb/frontends/s921_module.c2
-rw-r--r--drivers/media/dvb/frontends/stb0899_algo.c7
-rw-r--r--drivers/media/dvb/frontends/stb0899_drv.c7
-rw-r--r--drivers/media/dvb/frontends/zl10353.c7
-rw-r--r--drivers/media/dvb/siano/sms-cards.c19
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c2
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c4
-rw-r--r--drivers/media/dvb/ttpci/budget.c1
-rw-r--r--drivers/media/dvb/ttusb-budget/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-dec/Kconfig2
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c2
-rw-r--r--drivers/media/radio/Kconfig19
-rw-r--r--drivers/media/radio/Makefile1
-rw-r--r--drivers/media/radio/dsbr100.c14
-rw-r--r--drivers/media/radio/radio-aimslab.c10
-rw-r--r--drivers/media/radio/radio-aztech.c10
-rw-r--r--drivers/media/radio/radio-cadet.c10
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c10
-rw-r--r--drivers/media/radio/radio-gemtek.c10
-rw-r--r--drivers/media/radio/radio-maestro.c10
-rw-r--r--drivers/media/radio/radio-maxiradio.c10
-rw-r--r--drivers/media/radio/radio-mr800.c26
-rw-r--r--drivers/media/radio/radio-rtrack2.c10
-rw-r--r--drivers/media/radio/radio-sf16fmi.c10
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c10
-rw-r--r--drivers/media/radio/radio-si470x.c14
-rw-r--r--drivers/media/radio/radio-tea5764.c634
-rw-r--r--drivers/media/radio/radio-terratec.c10
-rw-r--r--drivers/media/radio/radio-trust.c10
-rw-r--r--drivers/media/radio/radio-typhoon.c10
-rw-r--r--drivers/media/radio/radio-zoltrix.c10
-rw-r--r--drivers/media/video/Makefile5
-rw-r--r--drivers/media/video/arv.c14
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c30
-rw-r--r--drivers/media/video/bw-qcam.c14
-rw-r--r--drivers/media/video/c-qcam.c14
-rw-r--r--drivers/media/video/cafe_ccic.c17
-rw-r--r--drivers/media/video/cpia.c14
-rw-r--r--drivers/media/video/cpia2/cpia2_v4l.c16
-rw-r--r--drivers/media/video/cs5345.c14
-rw-r--r--drivers/media/video/cs53l32a.c2
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c6
-rw-r--r--drivers/media/video/cx18/cx18-fileops.h4
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c28
-rw-r--r--drivers/media/video/cx18/cx18-i2c.h1
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c49
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.h2
-rw-r--r--drivers/media/video/cx18/cx18-streams.c13
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c18
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c27
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c21
-rw-r--r--drivers/media/video/cx88/Kconfig5
-rw-r--r--drivers/media/video/cx88/Makefile3
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c13
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c90
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c24
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c33
-rw-r--r--drivers/media/video/cx88/cx88-video.c27
-rw-r--r--drivers/media/video/cx88/cx88.h6
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c103
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c37
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c25
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c20
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c2
-rw-r--r--drivers/media/video/em28xx/em28xx-reg.h2
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c89
-rw-r--r--drivers/media/video/em28xx/em28xx.h25
-rw-r--r--drivers/media/video/et61x251/et61x251_core.c20
-rw-r--r--drivers/media/video/gspca/gspca.c16
-rw-r--r--drivers/media/video/gspca/m5602/m5602_s5k83a.c2
-rw-r--r--drivers/media/video/hexium_gemini.c2
-rw-r--r--drivers/media/video/hexium_orion.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c11
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c4
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.h4
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c25
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c8
-rw-r--r--drivers/media/video/m52790.c13
-rw-r--r--drivers/media/video/meye.c12
-rw-r--r--drivers/media/video/msp3400-driver.c4
-rw-r--r--drivers/media/video/mt9m001.c19
-rw-r--r--drivers/media/video/mt9m111.c19
-rw-r--r--drivers/media/video/mt9t031.c18
-rw-r--r--drivers/media/video/mt9v022.c19
-rw-r--r--drivers/media/video/mxb.c2
-rw-r--r--drivers/media/video/omap24xxcam.c9
-rw-r--r--drivers/media/video/ov511.c16
-rw-r--r--drivers/media/video/ov7670.c3
-rw-r--r--drivers/media/video/ov772x.c7
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c1
-rw-r--r--drivers/media/video/pms.c14
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c13
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h4
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c29
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c4
-rw-r--r--drivers/media/video/pwc/pwc-if.c21
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c2
-rw-r--r--drivers/media/video/pwc/pwc.h4
-rw-r--r--drivers/media/video/pxa_camera.c4
-rw-r--r--drivers/media/video/pxa_camera.h95
-rw-r--r--drivers/media/video/s2255drv.c12
-rw-r--r--drivers/media/video/saa5246a.c13
-rw-r--r--drivers/media/video/saa5249.c16
-rw-r--r--drivers/media/video/saa7115.c13
-rw-r--r--drivers/media/video/saa7127.c65
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c6
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c44
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c18
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c23
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c23
-rw-r--r--drivers/media/video/saa7134/saa7134.h1
-rw-r--r--drivers/media/video/saa717x.c10
-rw-r--r--drivers/media/video/se401.c14
-rw-r--r--drivers/media/video/sn9c102/sn9c102_core.c18
-rw-r--r--drivers/media/video/soc_camera.c13
-rw-r--r--drivers/media/video/stk-webcam.c10
-rw-r--r--drivers/media/video/stradis.c12
-rw-r--r--drivers/media/video/stv680.c14
-rw-r--r--drivers/media/video/tda9840.c2
-rw-r--r--drivers/media/video/tda9875.c2
-rw-r--r--drivers/media/video/tea6415c.c2
-rw-r--r--drivers/media/video/tea6420.c2
-rw-r--r--drivers/media/video/tuner-core.c2
-rw-r--r--drivers/media/video/tvaudio.c2
-rw-r--r--drivers/media/video/tveeprom.c3
-rw-r--r--drivers/media/video/tvp514x.c2
-rw-r--r--drivers/media/video/tvp5150.c13
-rw-r--r--drivers/media/video/tw9910.c6
-rw-r--r--drivers/media/video/upd64031a.c14
-rw-r--r--drivers/media/video/upd64083.c14
-rw-r--r--drivers/media/video/usbvideo/ibmcam.c2
-rw-r--r--drivers/media/video/usbvideo/konicawc.c2
-rw-r--r--drivers/media/video/usbvideo/ultracam.c2
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c20
-rw-r--r--drivers/media/video/usbvideo/vicam.c16
-rw-r--r--drivers/media/video/usbvision/usbvision-i2c.c2
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c40
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c7
-rw-r--r--drivers/media/video/uvc/uvc_driver.c55
-rw-r--r--drivers/media/video/uvc/uvc_isight.c2
-rw-r--r--drivers/media/video/uvc/uvc_queue.c31
-rw-r--r--drivers/media/video/uvc/uvc_status.c3
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c24
-rw-r--r--drivers/media/video/uvc/uvc_video.c31
-rw-r--r--drivers/media/video/uvc/uvcvideo.h234
-rw-r--r--drivers/media/video/v4l1-compat.c168
-rw-r--r--drivers/media/video/v4l2-common.c29
-rw-r--r--drivers/media/video/v4l2-compat-ioctl32.c27
-rw-r--r--drivers/media/video/v4l2-dev.c25
-rw-r--r--drivers/media/video/v4l2-device.c4
-rw-r--r--drivers/media/video/v4l2-ioctl.c36
-rw-r--r--drivers/media/video/v4l2-subdev.c6
-rw-r--r--drivers/media/video/videobuf-dma-sg.c3
-rw-r--r--drivers/media/video/vino.c13
-rw-r--r--drivers/media/video/vivi.c12
-rw-r--r--drivers/media/video/vp27smpx.c2
-rw-r--r--drivers/media/video/w9966.c16
-rw-r--r--drivers/media/video/w9968cf.c37
-rw-r--r--drivers/media/video/wm8739.c2
-rw-r--r--drivers/media/video/wm8775.c2
-rw-r--r--drivers/media/video/zc0301/zc0301_core.c18
-rw-r--r--drivers/media/video/zoran/zoran.h12
-rw-r--r--drivers/media/video/zoran/zoran_card.c620
-rw-r--r--drivers/media/video/zoran/zoran_card.h2
-rw-r--r--drivers/media/video/zoran/zoran_driver.c126
-rw-r--r--drivers/media/video/zr364xx.c8
-rw-r--r--drivers/memstick/core/memstick.c5
-rw-r--r--drivers/memstick/core/mspro_block.c57
-rw-r--r--drivers/memstick/host/tifm_ms.c4
-rw-r--r--drivers/message/fusion/lsi/mpi.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h47
-rw-r--r--drivers/message/fusion/lsi/mpi_fc.h2
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt86
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h2
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h22
-rw-r--r--drivers/message/fusion/lsi/mpi_lan.h2
-rw-r--r--drivers/message/fusion/lsi/mpi_log_fc.h2
-rw-r--r--drivers/message/fusion/lsi/mpi_log_sas.h37
-rw-r--r--drivers/message/fusion/lsi/mpi_raid.h11
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h18
-rw-r--r--drivers/message/fusion/lsi/mpi_targ.h2
-rw-r--r--drivers/message/fusion/lsi/mpi_tool.h2
-rw-r--r--drivers/message/fusion/lsi/mpi_type.h4
-rw-r--r--drivers/message/fusion/mptbase.c87
-rw-r--r--drivers/message/fusion/mptbase.h3
-rw-r--r--drivers/message/fusion/mptctl.c5
-rw-r--r--drivers/message/fusion/mptlan.c44
-rw-r--r--drivers/message/fusion/mptscsih.c3
-rw-r--r--drivers/message/i2o/device.c10
-rw-r--r--drivers/message/i2o/driver.c1
-rw-r--r--drivers/message/i2o/exec-osm.c2
-rw-r--r--drivers/message/i2o/i2o_config.c2
-rw-r--r--drivers/message/i2o/i2o_proc.c2
-rw-r--r--drivers/message/i2o/i2o_scsi.c2
-rw-r--r--drivers/message/i2o/iop.c4
-rw-r--r--drivers/message/i2o/pci.c2
-rw-r--r--drivers/mfd/Kconfig89
-rw-r--r--drivers/mfd/Makefile11
-rw-r--r--drivers/mfd/da903x.c16
-rw-r--r--drivers/mfd/dm355evm_msp.c430
-rw-r--r--drivers/mfd/menelaus.c (renamed from drivers/i2c/chips/menelaus.c)0
-rw-r--r--drivers/mfd/mfd-core.c1
-rw-r--r--drivers/mfd/pcf50633-adc.c277
-rw-r--r--drivers/mfd/pcf50633-core.c709
-rw-r--r--drivers/mfd/pcf50633-gpio.c118
-rw-r--r--drivers/mfd/sm501.c30
-rw-r--r--drivers/mfd/tps65010.c (renamed from drivers/i2c/chips/tps65010.c)0
-rw-r--r--drivers/mfd/twl4030-core.c483
-rw-r--r--drivers/mfd/twl4030-irq.c30
-rw-r--r--drivers/mfd/wm8350-core.c269
-rw-r--r--drivers/mfd/wm8350-i2c.c4
-rw-r--r--drivers/mfd/wm8350-regmap.c2100
-rw-r--r--drivers/mfd/wm8400-core.c31
-rw-r--r--drivers/misc/Kconfig306
-rw-r--r--drivers/misc/Makefile15
-rw-r--r--drivers/misc/atmel-ssc.c2
-rw-r--r--drivers/misc/eeprom/Kconfig59
-rw-r--r--drivers/misc/eeprom/Makefile4
-rw-r--r--drivers/misc/eeprom/at24.c (renamed from drivers/i2c/chips/at24.c)0
-rw-r--r--drivers/misc/eeprom/at25.c (renamed from drivers/spi/at25.c)0
-rw-r--r--drivers/misc/eeprom/eeprom.c (renamed from drivers/i2c/chips/eeprom.c)0
-rw-r--r--drivers/misc/eeprom/eeprom_93cx6.c (renamed from drivers/misc/eeprom_93cx6.c)0
-rw-r--r--drivers/misc/enclosure.c8
-rw-r--r--drivers/misc/hpilo.c8
-rw-r--r--drivers/misc/hpilo.h2
-rw-r--r--drivers/misc/ibmasm/event.c2
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c2
-rw-r--r--drivers/misc/ibmasm/module.c3
-rw-r--r--drivers/misc/ioc4.c36
-rw-r--r--drivers/misc/phantom.c2
-rw-r--r--drivers/misc/sgi-gru/grumain.c2
-rw-r--r--drivers/misc/sgi-xp/xp_main.c2
-rw-r--r--drivers/misc/sgi-xp/xpc.h5
-rw-r--r--drivers/misc/sgi-xp/xpc_channel.c3
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c8
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c36
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c13
-rw-r--r--drivers/misc/sgi-xp/xpnet.c73
-rw-r--r--drivers/misc/tifm_7xx1.c5
-rw-r--r--drivers/misc/tifm_core.c7
-rw-r--r--drivers/mmc/card/block.c122
-rw-r--r--drivers/mmc/core/core.c77
-rw-r--r--drivers/mmc/core/mmc.c18
-rw-r--r--drivers/mmc/host/Kconfig20
-rw-r--r--drivers/mmc/host/Makefile5
-rw-r--r--drivers/mmc/host/at91_mci.c4
-rw-r--r--drivers/mmc/host/atmel-mci.c105
-rw-r--r--drivers/mmc/host/mmc_spi.c4
-rw-r--r--drivers/mmc/host/mmci.c37
-rw-r--r--drivers/mmc/host/mmci.h28
-rw-r--r--drivers/mmc/host/mxcmmc.c880
-rw-r--r--drivers/mmc/host/of_mmc_spi.c149
-rw-r--r--drivers/mmc/host/omap_hsmmc.c1242
-rw-r--r--drivers/mmc/host/pxamci.c27
-rw-r--r--drivers/mmc/host/ricoh_mmc.c25
-rw-r--r--drivers/mmc/host/s3cmci.c2
-rw-r--r--drivers/mmc/host/sdhci-pci.c2
-rw-r--r--drivers/mmc/host/sdhci.c17
-rw-r--r--drivers/mmc/host/sdhci.h2
-rw-r--r--drivers/mmc/host/sdricoh_cs.c4
-rw-r--r--drivers/mmc/host/tmio_mmc.c3
-rw-r--r--drivers/mtd/Kconfig10
-rw-r--r--drivers/mtd/Makefile2
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c12
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c18
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0020.c14
-rw-r--r--drivers/mtd/chips/fwh_lock.h4
-rw-r--r--drivers/mtd/devices/Kconfig7
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/lart.c6
-rw-r--r--drivers/mtd/devices/m25p80.c53
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c52
-rw-r--r--drivers/mtd/devices/pmc551.c2
-rw-r--r--drivers/mtd/devices/ps3vram.c768
-rw-r--r--drivers/mtd/ftl.c100
-rw-r--r--drivers/mtd/inftlcore.c2
-rw-r--r--drivers/mtd/inftlmount.c4
-rw-r--r--drivers/mtd/lpddr/Kconfig22
-rw-r--r--drivers/mtd/lpddr/Makefile6
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c796
-rw-r--r--drivers/mtd/lpddr/qinfo_probe.c255
-rw-r--r--drivers/mtd/maps/Kconfig21
-rw-r--r--drivers/mtd/maps/alchemy-flash.c2
-rw-r--r--drivers/mtd/maps/amd76xrom.c4
-rw-r--r--drivers/mtd/maps/cfi_flagadm.c2
-rw-r--r--drivers/mtd/maps/ck804xrom.c4
-rw-r--r--drivers/mtd/maps/dbox2-flash.c2
-rw-r--r--drivers/mtd/maps/edb7312.c2
-rw-r--r--drivers/mtd/maps/esb2rom.c4
-rw-r--r--drivers/mtd/maps/fortunet.c2
-rw-r--r--drivers/mtd/maps/h720x-flash.c2
-rw-r--r--drivers/mtd/maps/ichxrom.c4
-rw-r--r--drivers/mtd/maps/impa7.c2
-rw-r--r--drivers/mtd/maps/integrator-flash.c2
-rw-r--r--drivers/mtd/maps/ipaq-flash.c2
-rw-r--r--drivers/mtd/maps/ixp2000.c4
-rw-r--r--drivers/mtd/maps/ixp4xx.c2
-rw-r--r--drivers/mtd/maps/mbx860.c2
-rw-r--r--drivers/mtd/maps/nettel.c9
-rw-r--r--drivers/mtd/maps/octagon-5066.c2
-rw-r--r--drivers/mtd/maps/omap_nor.c2
-rw-r--r--drivers/mtd/maps/physmap.c47
-rw-r--r--drivers/mtd/maps/physmap_of.c4
-rw-r--r--drivers/mtd/maps/pmcmsp-flash.c2
-rw-r--r--drivers/mtd/maps/redwood.c2
-rw-r--r--drivers/mtd/maps/rpxlite.c2
-rw-r--r--drivers/mtd/maps/sa1100-flash.c4
-rw-r--r--drivers/mtd/maps/sbc8240.c2
-rw-r--r--drivers/mtd/maps/scb2_flash.c8
-rw-r--r--drivers/mtd/maps/sharpsl-flash.c2
-rw-r--r--drivers/mtd/maps/tqm8xxl.c2
-rw-r--r--drivers/mtd/maps/uclinux.c4
-rw-r--r--drivers/mtd/maps/vmax301.c2
-rw-r--r--drivers/mtd/maps/wr_sbc82xx_flash.c2
-rw-r--r--drivers/mtd/mtdchar.c6
-rw-r--r--drivers/mtd/mtdconcat.c37
-rw-r--r--drivers/mtd/mtdcore.c16
-rw-r--r--drivers/mtd/mtdoops.c9
-rw-r--r--drivers/mtd/mtdpart.c34
-rw-r--r--drivers/mtd/nand/Kconfig7
-rw-r--r--drivers/mtd/nand/alauda.c6
-rw-r--r--drivers/mtd/nand/cafe_nand.c7
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c12
-rw-r--r--drivers/mtd/nand/fsl_upm.c2
-rw-r--r--drivers/mtd/nand/nand_base.c25
-rw-r--r--drivers/mtd/nand/nand_bbt.c31
-rw-r--r--drivers/mtd/nand/nandsim.c339
-rw-r--r--drivers/mtd/nand/ndfc.c269
-rw-r--r--drivers/mtd/nand/pasemi_nand.c4
-rw-r--r--drivers/mtd/nand/plat_nand.c2
-rw-r--r--drivers/mtd/nand/pxa3xx_nand.c6
-rw-r--r--drivers/mtd/nand/sharpsl.c247
-rw-r--r--drivers/mtd/nand/tmio_nand.c2
-rw-r--r--drivers/mtd/nftlcore.c2
-rw-r--r--drivers/mtd/nftlmount.c4
-rw-r--r--drivers/mtd/onenand/generic.c2
-rw-r--r--drivers/mtd/onenand/omap2.c8
-rw-r--r--drivers/mtd/onenand/onenand_base.c8
-rw-r--r--drivers/mtd/rfd_ftl.c29
-rw-r--r--drivers/mtd/ssfdc.c7
-rw-r--r--drivers/mtd/tests/Makefile7
-rw-r--r--drivers/mtd/tests/mtd_oobtest.c742
-rw-r--r--drivers/mtd/tests/mtd_pagetest.c632
-rw-r--r--drivers/mtd/tests/mtd_readtest.c253
-rw-r--r--drivers/mtd/tests/mtd_speedtest.c502
-rw-r--r--drivers/mtd/tests/mtd_stresstest.c330
-rw-r--r--drivers/mtd/tests/mtd_subpagetest.c525
-rw-r--r--drivers/mtd/tests/mtd_torturetest.c530
-rw-r--r--drivers/mtd/ubi/Kconfig.debug10
-rw-r--r--drivers/mtd/ubi/build.c30
-rw-r--r--drivers/mtd/ubi/cdev.c187
-rw-r--r--drivers/mtd/ubi/debug.h10
-rw-r--r--drivers/mtd/ubi/eba.c53
-rw-r--r--drivers/mtd/ubi/gluebi.c28
-rw-r--r--drivers/mtd/ubi/io.c30
-rw-r--r--drivers/mtd/ubi/kapi.c2
-rw-r--r--drivers/mtd/ubi/scan.c10
-rw-r--r--drivers/mtd/ubi/ubi-media.h4
-rw-r--r--drivers/mtd/ubi/ubi.h56
-rw-r--r--drivers/mtd/ubi/upd.c21
-rw-r--r--drivers/mtd/ubi/vmt.c21
-rw-r--r--drivers/mtd/ubi/vtbl.c2
-rw-r--r--drivers/mtd/ubi/wl.c493
-rw-r--r--drivers/net/3c503.c1
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139cp.c2
-rw-r--r--drivers/net/8139too.c2
-rw-r--r--drivers/net/8390.c1
-rw-r--r--drivers/net/8390p.c1
-rw-r--r--drivers/net/Kconfig8
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/acenic.c118
-rw-r--r--drivers/net/acenic.h4
-rw-r--r--drivers/net/acenic_firmware.h9456
-rw-r--r--drivers/net/amd8111e.c35
-rw-r--r--drivers/net/appletalk/ipddp.c25
-rw-r--r--drivers/net/arm/am79c961a.c20
-rw-r--r--drivers/net/arm/etherh.c1
-rw-r--r--drivers/net/arm/ks8695net.c1
-rw-r--r--drivers/net/atp.c32
-rw-r--r--drivers/net/ax88796.c27
-rw-r--r--drivers/net/b44.c46
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/bnx2x.h30
-rw-r--r--drivers/net/bnx2x_link.c66
-rw-r--r--drivers/net/bnx2x_main.c483
-rw-r--r--drivers/net/bnx2x_reg.h2
-rw-r--r--drivers/net/bonding/bond_main.c2
-rw-r--r--drivers/net/cassini.c33
-rw-r--r--drivers/net/cxgb3/adapter.h7
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c22
-rw-r--r--drivers/net/cxgb3/sge.c3
-rw-r--r--drivers/net/de600.c14
-rw-r--r--drivers/net/de620.c17
-rw-r--r--drivers/net/e100.c567
-rw-r--r--drivers/net/e1000/e1000_hw.c4
-rw-r--r--drivers/net/e1000/e1000_main.c6
-rw-r--r--drivers/net/e1000e/82571.c6
-rw-r--r--drivers/net/e1000e/hw.h1
-rw-r--r--drivers/net/e1000e/ich8lan.c19
-rw-r--r--drivers/net/e1000e/netdev.c2
-rw-r--r--drivers/net/e2100.c1
-rw-r--r--drivers/net/ehea/ehea.h3
-rw-r--r--drivers/net/ehea/ehea_main.c10
-rw-r--r--drivers/net/ehea/ehea_phyp.c16
-rw-r--r--drivers/net/ehea/ehea_qmr.c18
-rw-r--r--drivers/net/enc28j60.c22
-rw-r--r--drivers/net/enic/enic_main.c1
-rw-r--r--drivers/net/epic100.c21
-rw-r--r--drivers/net/fealnx.c21
-rw-r--r--drivers/net/fec.c2
-rw-r--r--drivers/net/forcedeth.c22
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c1
-rw-r--r--drivers/net/gianfar.c37
-rw-r--r--drivers/net/gianfar_mii.c2
-rw-r--r--drivers/net/hamachi.c1
-rw-r--r--drivers/net/hamradio/6pack.c3
-rw-r--r--drivers/net/hp-plus.c1
-rw-r--r--drivers/net/hp100.c32
-rw-r--r--drivers/net/hydra.c1
-rw-r--r--drivers/net/ibm_newemac/mal.c4
-rw-r--r--drivers/net/ibm_newemac/mal.h2
-rw-r--r--drivers/net/ibm_newemac/phy.c4
-rw-r--r--drivers/net/ibmveth.c20
-rw-r--r--drivers/net/ibmveth.h10
-rw-r--r--drivers/net/igb/e1000_82575.c11
-rw-r--r--drivers/net/igb/igb.h9
-rw-r--r--drivers/net/igb/igb_main.c28
-rw-r--r--drivers/net/ipg.c23
-rw-r--r--drivers/net/irda/ali-ircc.c45
-rw-r--r--drivers/net/irda/ali-ircc.h1
-rw-r--r--drivers/net/irda/au1000_ircc.h1
-rw-r--r--drivers/net/irda/au1k_ir.c11
-rw-r--r--drivers/net/irda/donauboe.c8
-rw-r--r--drivers/net/irda/donauboe.h1
-rw-r--r--drivers/net/irda/irda-usb.c30
-rw-r--r--drivers/net/irda/irda-usb.h1
-rw-r--r--drivers/net/irda/kingsun-sir.c20
-rw-r--r--drivers/net/irda/ks959-sir.c22
-rw-r--r--drivers/net/irda/ksdazzle-sir.c26
-rw-r--r--drivers/net/irda/mcs7780.c49
-rw-r--r--drivers/net/irda/mcs7780.h2
-rw-r--r--drivers/net/irda/nsc-ircc.c45
-rw-r--r--drivers/net/irda/nsc-ircc.h1
-rw-r--r--drivers/net/irda/pxaficp_ir.c52
-rw-r--r--drivers/net/irda/sa1100_ir.c46
-rw-r--r--drivers/net/irda/sir-dev.h1
-rw-r--r--drivers/net/irda/sir_dev.c26
-rw-r--r--drivers/net/irda/smsc-ircc2.c38
-rw-r--r--drivers/net/irda/stir4200.c44
-rw-r--r--drivers/net/irda/via-ircc.c47
-rw-r--r--drivers/net/irda/via-ircc.h1
-rw-r--r--drivers/net/irda/vlsi_ir.c78
-rw-r--r--drivers/net/irda/vlsi_ir.h1
-rw-r--r--drivers/net/irda/w83977af_ir.c35
-rw-r--r--drivers/net/irda/w83977af_ir.h1
-rw-r--r--drivers/net/iseries_veth.c2
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c62
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h3
-rw-r--r--drivers/net/korina.c173
-rw-r--r--drivers/net/mac8390.c1
-rw-r--r--drivers/net/macb.c8
-rw-r--r--drivers/net/mlx4/en_netdev.c1
-rw-r--r--drivers/net/mlx4/en_params.c6
-rw-r--r--drivers/net/mlx4/en_tx.c59
-rw-r--r--drivers/net/mlx4/main.c4
-rw-r--r--drivers/net/mlx4/mlx4_en.h5
-rw-r--r--drivers/net/mlx4/profile.c6
-rw-r--r--drivers/net/mv643xx_eth.c17
-rw-r--r--drivers/net/myri10ge/myri10ge.c19
-rw-r--r--drivers/net/natsemi.c29
-rw-r--r--drivers/net/ne-h8300.c1
-rw-r--r--drivers/net/ne2k-pci.c1
-rw-r--r--drivers/net/netxen/netxen_nic.h156
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c50
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c36
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c97
-rw-r--r--drivers/net/netxen/netxen_nic_init.c109
-rw-r--r--drivers/net/netxen/netxen_nic_main.c233
-rw-r--r--drivers/net/ns83820.c5
-rw-r--r--drivers/net/pasemi_mac.c6
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c2
-rw-r--r--drivers/net/pcnet32.c32
-rw-r--r--drivers/net/phy/mdio_bus.c8
-rw-r--r--drivers/net/phy/phy_device.c9
-rw-r--r--drivers/net/phy/smsc.c12
-rw-r--r--drivers/net/plip.c13
-rw-r--r--drivers/net/ppp_generic.c43
-rw-r--r--drivers/net/ps3_gelic_wireless.c2
-rw-r--r--drivers/net/qlge/qlge.h100
-rw-r--r--drivers/net/qlge/qlge_dbg.c75
-rw-r--r--drivers/net/qlge/qlge_ethtool.c8
-rw-r--r--drivers/net/qlge/qlge_main.c197
-rw-r--r--drivers/net/r6040.c63
-rw-r--r--drivers/net/sb1000.c16
-rw-r--r--drivers/net/sc92031.c1
-rw-r--r--drivers/net/sfc/efx.c59
-rw-r--r--drivers/net/sfc/efx.h9
-rw-r--r--drivers/net/sfc/ethtool.c3
-rw-r--r--drivers/net/sfc/falcon.c36
-rw-r--r--drivers/net/sfc/mdio_10g.c191
-rw-r--r--drivers/net/sfc/mdio_10g.h3
-rw-r--r--drivers/net/sfc/net_driver.h9
-rw-r--r--drivers/net/sfc/phy.h1
-rw-r--r--drivers/net/sfc/selftest.c7
-rw-r--r--drivers/net/sfc/sfe4001.c42
-rw-r--r--drivers/net/sfc/tenxpress.c218
-rw-r--r--drivers/net/sfc/workarounds.h12
-rw-r--r--drivers/net/sis190.c28
-rw-r--r--drivers/net/sis900.c9
-rw-r--r--drivers/net/skfp/skfddi.c4
-rw-r--r--drivers/net/sky2.c6
-rw-r--r--drivers/net/slip.c28
-rw-r--r--drivers/net/slip.h2
-rw-r--r--drivers/net/smc-mca.c1
-rw-r--r--drivers/net/smc-ultra.c1
-rw-r--r--drivers/net/smc911x.c4
-rw-r--r--drivers/net/smsc911x.c6
-rw-r--r--drivers/net/smsc9420.c16
-rw-r--r--drivers/net/starfire.c88
-rw-r--r--drivers/net/starfire_firmware.h346
-rw-r--r--drivers/net/starfire_firmware.pl31
-rw-r--r--drivers/net/sundance.c23
-rw-r--r--drivers/net/sungem.c24
-rw-r--r--drivers/net/sungem_phy.c2
-rw-r--r--drivers/net/sunhme.c26
-rw-r--r--drivers/net/sunqe.c2
-rw-r--r--drivers/net/sunvnet.c8
-rw-r--r--drivers/net/tehuti.c4
-rw-r--r--drivers/net/tg3.c811
-rw-r--r--drivers/net/tg3.h5
-rw-r--r--drivers/net/tlan.c26
-rw-r--r--drivers/net/tokenring/smctr.c2
-rw-r--r--drivers/net/tsi108_eth.c2
-rw-r--r--drivers/net/tulip/21142.c23
-rw-r--r--drivers/net/tulip/de2104x.c21
-rw-r--r--drivers/net/tulip/de4x5.c20
-rw-r--r--drivers/net/tulip/dmfe.c62
-rw-r--r--drivers/net/tulip/tulip_core.c27
-rw-r--r--drivers/net/tulip/uli526x.c63
-rw-r--r--drivers/net/tulip/winbond-840.c23
-rw-r--r--drivers/net/tulip/xircom_cb.c43
-rw-r--r--drivers/net/tun.c2
-rw-r--r--drivers/net/typhoon.c22
-rw-r--r--drivers/net/ucc_geth.c148
-rw-r--r--drivers/net/ucc_geth.h116
-rw-r--r--drivers/net/ucc_geth_mii.c12
-rw-r--r--drivers/net/ucc_geth_mii.h1
-rw-r--r--drivers/net/usb/dm9601.c29
-rw-r--r--drivers/net/usb/hso.c446
-rw-r--r--drivers/net/usb/kaweth.c29
-rw-r--r--drivers/net/usb/mcs7830.c20
-rw-r--r--drivers/net/usb/pegasus.c33
-rw-r--r--drivers/net/via-rhine.c1
-rw-r--r--drivers/net/via-velocity.c3
-rw-r--r--drivers/net/virtio_net.c29
-rw-r--r--drivers/net/wan/ixp4xx_hss.c6
-rw-r--r--drivers/net/wd.c1
-rw-r--r--drivers/net/wimax/Kconfig17
-rw-r--r--drivers/net/wimax/Makefile5
-rw-r--r--drivers/net/wimax/i2400m/Kconfig49
-rw-r--r--drivers/net/wimax/i2400m/Makefile29
-rw-r--r--drivers/net/wimax/i2400m/control.c1291
-rw-r--r--drivers/net/wimax/i2400m/debug-levels.h45
-rw-r--r--drivers/net/wimax/i2400m/debugfs.c378
-rw-r--r--drivers/net/wimax/i2400m/driver.c744
-rw-r--r--drivers/net/wimax/i2400m/fw.c1095
-rw-r--r--drivers/net/wimax/i2400m/i2400m-sdio.h132
-rw-r--r--drivers/net/wimax/i2400m/i2400m-usb.h264
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h755
-rw-r--r--drivers/net/wimax/i2400m/netdev.c524
-rw-r--r--drivers/net/wimax/i2400m/op-rfkill.c207
-rw-r--r--drivers/net/wimax/i2400m/rx.c534
-rw-r--r--drivers/net/wimax/i2400m/sdio-debug-levels.h22
-rw-r--r--drivers/net/wimax/i2400m/sdio-fw.c224
-rw-r--r--drivers/net/wimax/i2400m/sdio-rx.c255
-rw-r--r--drivers/net/wimax/i2400m/sdio-tx.c153
-rw-r--r--drivers/net/wimax/i2400m/sdio.c511
-rw-r--r--drivers/net/wimax/i2400m/tx.c817
-rw-r--r--drivers/net/wimax/i2400m/usb-debug-levels.h42
-rw-r--r--drivers/net/wimax/i2400m/usb-fw.c340
-rw-r--r--drivers/net/wimax/i2400m/usb-notif.c269
-rw-r--r--drivers/net/wimax/i2400m/usb-rx.c420
-rw-r--r--drivers/net/wimax/i2400m/usb-tx.c229
-rw-r--r--drivers/net/wimax/i2400m/usb.c597
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/ath5k/base.c18
-rw-r--r--drivers/net/wireless/ath5k/dma.c2
-rw-r--r--drivers/net/wireless/ath5k/pcu.c4
-rw-r--r--drivers/net/wireless/ath5k/reg.h2
-rw-r--r--drivers/net/wireless/ath9k/Kconfig1
-rw-r--r--drivers/net/wireless/ath9k/main.c4
-rw-r--r--drivers/net/wireless/ath9k/rc.c2
-rw-r--r--drivers/net/wireless/ath9k/regd_common.h2
-rw-r--r--drivers/net/wireless/ath9k/xmit.c48
-rw-r--r--drivers/net/wireless/atmel.c2
-rw-r--r--drivers/net/wireless/b43/main.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c2
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c4
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h91
-rw-r--r--drivers/net/wireless/libertas/main.c7
-rw-r--r--drivers/net/wireless/libertas_tf/main.c2
-rw-r--r--drivers/net/wireless/orinoco/orinoco.c60
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c1
-rw-r--r--drivers/net/wireless/p54/p54common.c60
-rw-r--r--drivers/net/wireless/p54/p54usb.c43
-rw-r--r--drivers/net/wireless/rndis_wlan.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c23
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00rfkill.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c6
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_rtl8225.c10
-rw-r--r--drivers/net/wireless/strip.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c1
-rw-r--r--drivers/net/xen-netfront.c17
-rw-r--r--drivers/net/yellowfin.c1
-rw-r--r--drivers/net/zorro8390.c1
-rw-r--r--drivers/of/of_i2c.c19
-rw-r--r--drivers/oprofile/buffer_sync.c190
-rw-r--r--drivers/oprofile/cpu_buffer.c321
-rw-r--r--drivers/oprofile/cpu_buffer.h96
-rw-r--r--drivers/oprofile/event_buffer.c4
-rw-r--r--drivers/oprofile/oprof.c4
-rw-r--r--drivers/oprofile/oprof.h8
-rw-r--r--drivers/oprofile/oprofile_files.c27
-rw-r--r--drivers/oprofile/oprofilefs.c3
-rw-r--r--drivers/parisc/asp.c3
-rw-r--r--drivers/parisc/ccio-dma.c4
-rw-r--r--drivers/parisc/dino.c8
-rw-r--r--drivers/parisc/hppb.c2
-rw-r--r--drivers/parisc/iosapic.c10
-rw-r--r--drivers/parisc/lasi.c5
-rw-r--r--drivers/parisc/lba_pci.c2
-rw-r--r--drivers/parisc/sba_iommu.c27
-rw-r--r--drivers/parisc/superio.c1
-rw-r--r--drivers/parisc/wax.c3
-rw-r--r--drivers/parport/ieee1284.c2
-rw-r--r--drivers/pci/Kconfig9
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/access.c226
-rw-r--r--drivers/pci/bus.c87
-rw-r--r--drivers/pci/dmar.c46
-rw-r--r--drivers/pci/hotplug/Makefile9
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c70
-rw-r--r--drivers/pci/hotplug/acpiphp.h2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c119
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c6
-rw-r--r--drivers/pci/hotplug/cpqphp_pci.c4
-rw-r--r--drivers/pci/hotplug/fakephp.c43
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c2
-rw-r--r--drivers/pci/hotplug/pciehp.h16
-rw-r--r--drivers/pci/hotplug/pciehp_acpi.c141
-rw-r--r--drivers/pci/hotplug/pciehp_core.c5
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c26
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c329
-rw-r--r--drivers/pci/intel-iommu.c945
-rw-r--r--drivers/pci/irq.c2
-rw-r--r--drivers/pci/msi.c60
-rw-r--r--drivers/pci/pci-acpi.c84
-rw-r--r--drivers/pci/pci-driver.c440
-rw-r--r--drivers/pci/pci-stub.c47
-rw-r--r--drivers/pci/pci-sysfs.c103
-rw-r--r--drivers/pci/pci.c568
-rw-r--r--drivers/pci/pci.h40
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c1
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c2
-rw-r--r--drivers/pci/pcie/aspm.c165
-rw-r--r--drivers/pci/pcie/portdrv_bus.c32
-rw-r--r--drivers/pci/pcie/portdrv_core.c240
-rw-r--r--drivers/pci/pcie/portdrv_pci.c21
-rw-r--r--drivers/pci/probe.c46
-rw-r--r--drivers/pci/proc.c18
-rw-r--r--drivers/pci/quirks.c112
-rw-r--r--drivers/pci/setup-bus.c5
-rw-r--r--drivers/pci/setup-res.c24
-rw-r--r--drivers/pci/syscall.c12
-rw-r--r--drivers/pcmcia/electra_cf.c2
-rw-r--r--drivers/platform/Kconfig5
-rw-r--r--drivers/platform/Makefile5
-rw-r--r--drivers/platform/x86/Kconfig398
-rw-r--r--drivers/platform/x86/Makefile20
-rw-r--r--drivers/platform/x86/acer-wmi.c (renamed from drivers/misc/acer-wmi.c)0
-rw-r--r--drivers/platform/x86/asus-laptop.c (renamed from drivers/misc/asus-laptop.c)0
-rw-r--r--drivers/platform/x86/asus_acpi.c (renamed from drivers/acpi/asus_acpi.c)0
-rw-r--r--drivers/platform/x86/compal-laptop.c (renamed from drivers/misc/compal-laptop.c)0
-rw-r--r--drivers/platform/x86/dell-laptop.c436
-rw-r--r--drivers/platform/x86/eeepc-laptop.c (renamed from drivers/misc/eeepc-laptop.c)4
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c (renamed from drivers/misc/fujitsu-laptop.c)419
-rw-r--r--drivers/platform/x86/hp-wmi.c (renamed from drivers/misc/hp-wmi.c)23
-rw-r--r--drivers/platform/x86/intel_menlow.c (renamed from drivers/misc/intel_menlow.c)0
-rw-r--r--drivers/platform/x86/msi-laptop.c (renamed from drivers/misc/msi-laptop.c)0
-rw-r--r--drivers/platform/x86/panasonic-laptop.c (renamed from drivers/misc/panasonic-laptop.c)22
-rw-r--r--drivers/platform/x86/sony-laptop.c (renamed from drivers/misc/sony-laptop.c)15
-rw-r--r--drivers/platform/x86/tc1100-wmi.c (renamed from drivers/misc/tc1100-wmi.c)1
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c (renamed from drivers/misc/thinkpad_acpi.c)911
-rw-r--r--drivers/platform/x86/toshiba_acpi.c (renamed from drivers/acpi/toshiba_acpi.c)0
-rw-r--r--drivers/platform/x86/wmi.c (renamed from drivers/acpi/wmi.c)0
-rw-r--r--drivers/pnp/card.c7
-rw-r--r--drivers/pnp/core.c5
-rw-r--r--drivers/pnp/pnpacpi/core.c1
-rw-r--r--drivers/pnp/pnpbios/bioscalls.c2
-rw-r--r--drivers/pnp/system.c2
-rw-r--r--drivers/power/Kconfig20
-rw-r--r--drivers/power/Makefile3
-rw-r--r--drivers/power/da9030_battery.c600
-rw-r--r--drivers/power/ds2760_battery.c4
-rw-r--r--drivers/power/pcf50633-charger.c358
-rw-r--r--drivers/power/pda_power.c2
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/power/wm8350_power.c532
-rw-r--r--drivers/ps3/ps3-lpm.c16
-rw-r--r--drivers/ps3/ps3-vuart.c32
-rw-r--r--drivers/ps3/ps3stor_lib.c14
-rw-r--r--drivers/rapidio/rio-driver.c1
-rw-r--r--drivers/regulator/Kconfig7
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/bq24022.c6
-rw-r--r--drivers/regulator/core.c474
-rw-r--r--drivers/regulator/da903x.c12
-rw-r--r--drivers/regulator/pcf50633-regulator.c329
-rw-r--r--drivers/regulator/wm8350-regulator.c98
-rw-r--r--drivers/regulator/wm8400-regulator.c2
-rw-r--r--drivers/rtc/Kconfig113
-rw-r--r--drivers/rtc/Makefile6
-rw-r--r--drivers/rtc/class.c16
-rw-r--r--drivers/rtc/interface.c70
-rw-r--r--drivers/rtc/rtc-at32ap700x.c4
-rw-r--r--drivers/rtc/rtc-au1xxx.c153
-rw-r--r--drivers/rtc/rtc-bfin.c2
-rw-r--r--drivers/rtc/rtc-cmos.c15
-rw-r--r--drivers/rtc/rtc-dev.c51
-rw-r--r--drivers/rtc/rtc-dm355evm.c175
-rw-r--r--drivers/rtc/rtc-ds1216.c30
-rw-r--r--drivers/rtc/rtc-ds1307.c154
-rw-r--r--drivers/rtc/rtc-ds1390.c73
-rw-r--r--drivers/rtc/rtc-ds1511.c21
-rw-r--r--drivers/rtc/rtc-ds1553.c15
-rw-r--r--drivers/rtc/rtc-ds1672.c22
-rw-r--r--drivers/rtc/rtc-ds3234.c172
-rw-r--r--drivers/rtc/rtc-ep93xx.c13
-rw-r--r--drivers/rtc/rtc-m48t59.c2
-rw-r--r--drivers/rtc/rtc-max6902.c176
-rw-r--r--drivers/rtc/rtc-mv.c163
-rw-r--r--drivers/rtc/rtc-parisc.c3
-rw-r--r--drivers/rtc/rtc-pcf50633.c344
-rw-r--r--drivers/rtc/rtc-pxa.c491
-rw-r--r--drivers/rtc/rtc-s3c.c3
-rw-r--r--drivers/rtc/rtc-sh.c13
-rw-r--r--drivers/rtc/rtc-stk17ta8.c17
-rw-r--r--drivers/rtc/rtc-test.c8
-rw-r--r--drivers/rtc/rtc-twl4030.c54
-rw-r--r--drivers/rtc/rtc-tx4939.c317
-rw-r--r--drivers/rtc/rtc-vr41xx.c11
-rw-r--r--drivers/s390/Makefile2
-rw-r--r--drivers/s390/block/dasd.c21
-rw-r--r--drivers/s390/block/dasd_3990_erp.c2
-rw-r--r--drivers/s390/block/dasd_devmap.c48
-rw-r--r--drivers/s390/block/dasd_diag.c3
-rw-r--r--drivers/s390/block/dasd_eckd.c3
-rw-r--r--drivers/s390/block/dasd_eer.c4
-rw-r--r--drivers/s390/block/dasd_fba.c3
-rw-r--r--drivers/s390/block/dasd_int.h2
-rw-r--r--drivers/s390/block/dcssblk.c11
-rw-r--r--drivers/s390/char/Kconfig2
-rw-r--r--drivers/s390/char/tape_3590.c2
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/cio/cio.c4
-rw-r--r--drivers/s390/cio/qdio_debug.c2
-rw-r--r--drivers/s390/cio/qdio_main.c2
-rw-r--r--drivers/s390/crypto/ap_bus.c7
-rw-r--r--drivers/s390/kvm/kvm_virtio.c5
-rw-r--r--drivers/s390/net/cu3088.c7
-rw-r--r--drivers/s390/net/lcs.c8
-rw-r--r--drivers/s390/net/qeth_core.h1
-rw-r--r--drivers/s390/net/qeth_core_main.c64
-rw-r--r--drivers/s390/net/qeth_l2_main.c37
-rw-r--r--drivers/s390/net/qeth_l3_main.c97
-rw-r--r--drivers/s390/s390_rdev.c51
-rw-r--r--drivers/s390/s390mach.c3
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/scsi/Kconfig9
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/NCR_D700.c2
-rw-r--r--drivers/scsi/a100u2w.c2
-rw-r--r--drivers/scsi/a2091.c18
-rw-r--r--drivers/scsi/advansys.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_tmf.c2
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.c1
-rw-r--r--drivers/scsi/gvp11.c8
-rw-r--r--drivers/scsi/hosts.c6
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c32
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h6
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c28
-rw-r--r--drivers/scsi/ide-scsi.c840
-rw-r--r--drivers/scsi/ipr.c4
-rw-r--r--drivers/scsi/ipr.h2
-rw-r--r--drivers/scsi/lasi700.c3
-rw-r--r--drivers/scsi/libiscsi.c1
-rw-r--r--drivers/scsi/libiscsi_tcp.c3
-rw-r--r--drivers/scsi/libsas/sas_discover.c2
-rw-r--r--drivers/scsi/libsas/sas_dump.c2
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c12
-rw-r--r--drivers/scsi/libsas/sas_port.c2
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c10
-rw-r--r--drivers/scsi/megaraid.c4
-rw-r--r--drivers/scsi/mvsas.c2
-rw-r--r--drivers/scsi/pcmcia/aha152x_stub.c2
-rw-r--r--drivers/scsi/ps3rom.c6
-rw-r--r--drivers/scsi/qla1280.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c32
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c462
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h40
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h33
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h294
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h11
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c9
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c406
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c87
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c57
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c166
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c284
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h6
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c10
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c2
-rw-r--r--drivers/scsi/raid_class.c3
-rw-r--r--drivers/scsi/scsi.c9
-rw-r--r--drivers/scsi/scsi_debug.c4
-rw-r--r--drivers/scsi/scsi_devinfo.c1
-rw-r--r--drivers/scsi/scsi_error.c26
-rw-r--r--drivers/scsi/scsi_ioctl.c9
-rw-r--r--drivers/scsi/scsi_lib.c119
-rw-r--r--drivers/scsi/scsi_scan.c10
-rw-r--r--drivers/scsi/scsi_sysfs.c12
-rw-r--r--drivers/scsi/scsi_transport_fc.c39
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c11
-rw-r--r--drivers/scsi/scsi_transport_sas.c42
-rw-r--r--drivers/scsi/scsi_transport_srp.c2
-rw-r--r--drivers/scsi/sd.c109
-rw-r--r--drivers/scsi/sd_dif.c17
-rw-r--r--drivers/scsi/ses.c2
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/sgiwd93.c3
-rw-r--r--drivers/scsi/sim710.c4
-rw-r--r--drivers/scsi/sni_53c710.c3
-rw-r--r--drivers/scsi/st.c492
-rw-r--r--drivers/scsi/st.h14
-rw-r--r--drivers/scsi/zalon.c4
-rw-r--r--drivers/serial/8250.c229
-rw-r--r--drivers/serial/8250_pci.c148
-rw-r--r--drivers/serial/8250_pnp.c2
-rw-r--r--drivers/serial/Kconfig23
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/atmel_serial.c2
-rw-r--r--drivers/serial/bfin_5xx.c239
-rw-r--r--drivers/serial/bfin_sport_uart.c60
-rw-r--r--drivers/serial/crisv10.c4
-rw-r--r--drivers/serial/jsm/jsm_driver.c2
-rw-r--r--drivers/serial/jsm/jsm_neo.c3
-rw-r--r--drivers/serial/jsm/jsm_tty.c8
-rw-r--r--drivers/serial/mcf.c11
-rw-r--r--drivers/serial/nwpserial.c475
-rw-r--r--drivers/serial/of_serial.c20
-rw-r--r--drivers/serial/pnx8xxx_uart.c23
-rw-r--r--drivers/serial/serial_core.c159
-rw-r--r--drivers/serial/sh-sci.h5
-rw-r--r--drivers/spi/Kconfig29
-rw-r--r--drivers/spi/Makefile2
-rw-r--r--drivers/spi/atmel_spi.c134
-rw-r--r--drivers/spi/pxa2xx_spi.c3
-rw-r--r--drivers/spi/spi.c20
-rw-r--r--drivers/spi/spi_bitbang.c2
-rw-r--r--drivers/spi/spi_butterfly.c2
-rw-r--r--drivers/spi/spi_gpio.c360
-rw-r--r--drivers/spi/spi_lm70llp.c35
-rw-r--r--drivers/spi/spi_s3c24xx.c38
-rw-r--r--drivers/spi/xilinx_spi.c137
-rw-r--r--drivers/staging/Kconfig32
-rw-r--r--drivers/staging/Makefile16
-rw-r--r--drivers/staging/agnx/Kconfig5
-rw-r--r--drivers/staging/agnx/Makefile8
-rw-r--r--drivers/staging/agnx/TODO22
-rw-r--r--drivers/staging/agnx/agnx.h156
-rw-r--r--drivers/staging/agnx/debug.h418
-rw-r--r--drivers/staging/agnx/pci.c644
-rw-r--r--drivers/staging/agnx/phy.c960
-rw-r--r--drivers/staging/agnx/phy.h409
-rw-r--r--drivers/staging/agnx/rf.c894
-rw-r--r--drivers/staging/agnx/sta.c219
-rw-r--r--drivers/staging/agnx/sta.h222
-rw-r--r--drivers/staging/agnx/table.c168
-rw-r--r--drivers/staging/agnx/table.h10
-rw-r--r--drivers/staging/agnx/xmit.c819
-rw-r--r--drivers/staging/agnx/xmit.h250
-rw-r--r--drivers/staging/altpciechdma/Kconfig10
-rw-r--r--drivers/staging/altpciechdma/Makefile2
-rw-r--r--drivers/staging/altpciechdma/TODO15
-rw-r--r--drivers/staging/altpciechdma/altpciechdma.c1184
-rw-r--r--drivers/staging/android/Kconfig86
-rw-r--r--drivers/staging/android/Makefile5
-rw-r--r--drivers/staging/android/TODO10
-rw-r--r--drivers/staging/android/binder.c3503
-rw-r--r--drivers/staging/android/binder.h330
-rw-r--r--drivers/staging/android/logger.c607
-rw-r--r--drivers/staging/android/logger.h48
-rw-r--r--drivers/staging/android/lowmemorykiller.c119
-rw-r--r--drivers/staging/android/lowmemorykiller.txt16
-rw-r--r--drivers/staging/android/ram_console.c395
-rw-r--r--drivers/staging/android/timed_gpio.c178
-rw-r--r--drivers/staging/android/timed_gpio.h31
-rw-r--r--drivers/staging/asus_oled/Kconfig6
-rw-r--r--drivers/staging/asus_oled/Makefile1
-rw-r--r--drivers/staging/asus_oled/README156
-rw-r--r--drivers/staging/asus_oled/TODO10
-rw-r--r--drivers/staging/asus_oled/asus_oled.c745
-rw-r--r--drivers/staging/asus_oled/linux.txt33
-rw-r--r--drivers/staging/asus_oled/linux_f.txt18
-rw-r--r--drivers/staging/asus_oled/linux_fr.txt33
-rw-r--r--drivers/staging/asus_oled/tux.txt33
-rw-r--r--drivers/staging/asus_oled/tux_r.txt33
-rw-r--r--drivers/staging/asus_oled/tux_r2.txt33
-rw-r--r--drivers/staging/asus_oled/zig.txt33
-rw-r--r--drivers/staging/at76_usb/Kconfig2
-rw-r--r--drivers/staging/at76_usb/at76_usb.c4640
-rw-r--r--drivers/staging/at76_usb/at76_usb.h227
-rw-r--r--drivers/staging/benet/Kconfig7
-rw-r--r--drivers/staging/benet/MAINTAINERS6
-rw-r--r--drivers/staging/benet/Makefile14
-rw-r--r--drivers/staging/benet/TODO6
-rw-r--r--drivers/staging/benet/asyncmesg.h82
-rw-r--r--drivers/staging/benet/be_cm.h134
-rw-r--r--drivers/staging/benet/be_common.h53
-rw-r--r--drivers/staging/benet/be_ethtool.c348
-rw-r--r--drivers/staging/benet/be_init.c1382
-rw-r--r--drivers/staging/benet/be_int.c863
-rw-r--r--drivers/staging/benet/be_netif.c705
-rw-r--r--drivers/staging/benet/benet.h429
-rw-r--r--drivers/staging/benet/bestatus.h103
-rw-r--r--drivers/staging/benet/cev.h243
-rw-r--r--drivers/staging/benet/cq.c211
-rw-r--r--drivers/staging/benet/descriptors.h71
-rw-r--r--drivers/staging/benet/doorbells.h179
-rw-r--r--drivers/staging/benet/ep.h66
-rw-r--r--drivers/staging/benet/eq.c299
-rw-r--r--drivers/staging/benet/eth.c1273
-rw-r--r--drivers/staging/benet/etx_context.h55
-rw-r--r--drivers/staging/benet/funcobj.c565
-rw-r--r--drivers/staging/benet/fwcmd_common.h222
-rw-r--r--drivers/staging/benet/fwcmd_common_bmap.h717
-rw-r--r--drivers/staging/benet/fwcmd_eth_bmap.h280
-rw-r--r--drivers/staging/benet/fwcmd_hdr_bmap.h54
-rw-r--r--drivers/staging/benet/fwcmd_mcc.h94
-rw-r--r--drivers/staging/benet/fwcmd_opcodes.h244
-rw-r--r--drivers/staging/benet/fwcmd_types_bmap.h29
-rw-r--r--drivers/staging/benet/host_struct.h182
-rw-r--r--drivers/staging/benet/hwlib.h830
-rw-r--r--drivers/staging/benet/mpu.c1364
-rw-r--r--drivers/staging/benet/mpu.h74
-rw-r--r--drivers/staging/benet/mpu_context.h46
-rw-r--r--drivers/staging/benet/pcicfg.h825
-rw-r--r--drivers/staging/benet/post_codes.h111
-rw-r--r--drivers/staging/benet/regmap.h68
-rw-r--r--drivers/staging/comedi/Kconfig28
-rw-r--r--drivers/staging/comedi/Makefile17
-rw-r--r--drivers/staging/comedi/TODO14
-rw-r--r--drivers/staging/comedi/comedi.h916
-rw-r--r--drivers/staging/comedi/comedi_compat32.c597
-rw-r--r--drivers/staging/comedi/comedi_compat32.h58
-rw-r--r--drivers/staging/comedi/comedi_fops.c2244
-rw-r--r--drivers/staging/comedi/comedi_fops.h8
-rw-r--r--drivers/staging/comedi/comedi_ksyms.c77
-rw-r--r--drivers/staging/comedi/comedi_rt.h150
-rw-r--r--drivers/staging/comedi/comedidev.h537
-rw-r--r--drivers/staging/comedi/comedilib.h192
-rw-r--r--drivers/staging/comedi/drivers.c846
-rw-r--r--drivers/staging/comedi/drivers/Makefile21
-rw-r--r--drivers/staging/comedi/drivers/comedi_bond.c535
-rw-r--r--drivers/staging/comedi/drivers/comedi_fc.c118
-rw-r--r--drivers/staging/comedi/drivers/comedi_fc.h76
-rw-r--r--drivers/staging/comedi/drivers/comedi_parport.c390
-rw-r--r--drivers/staging/comedi/drivers/comedi_pci.h60
-rw-r--r--drivers/staging/comedi/drivers/comedi_test.c527
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c1162
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c1085
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.h278
-rw-r--r--drivers/staging/comedi/drivers/me4000.c2362
-rw-r--r--drivers/staging/comedi/drivers/me4000.h446
-rw-r--r--drivers/staging/comedi/drivers/me_daq.c845
-rw-r--r--drivers/staging/comedi/drivers/mite.c809
-rw-r--r--drivers/staging/comedi/drivers/mite.h453
-rw-r--r--drivers/staging/comedi/drivers/plx9080.h429
-rw-r--r--drivers/staging/comedi/drivers/rtd520.c2283
-rw-r--r--drivers/staging/comedi/drivers/rtd520.h412
-rw-r--r--drivers/staging/comedi/drivers/s626.c3254
-rw-r--r--drivers/staging/comedi/drivers/s626.h802
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c2932
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c1778
-rw-r--r--drivers/staging/comedi/interrupt.h60
-rw-r--r--drivers/staging/comedi/kcomedilib/Makefile8
-rw-r--r--drivers/staging/comedi/kcomedilib/data.c89
-rw-r--r--drivers/staging/comedi/kcomedilib/dio.c95
-rw-r--r--drivers/staging/comedi/kcomedilib/get.c294
-rw-r--r--drivers/staging/comedi/kcomedilib/kcomedilib_main.c567
-rw-r--r--drivers/staging/comedi/kcomedilib/ksyms.c144
-rw-r--r--drivers/staging/comedi/pci_ids.h31
-rw-r--r--drivers/staging/comedi/proc.c102
-rw-r--r--drivers/staging/comedi/range.c161
-rw-r--r--drivers/staging/comedi/rt.c412
-rw-r--r--drivers/staging/comedi/rt_pend_tq.c113
-rw-r--r--drivers/staging/comedi/rt_pend_tq.h10
-rw-r--r--drivers/staging/comedi/wrapper.h25
-rw-r--r--drivers/staging/echo/TODO2
-rw-r--r--drivers/staging/echo/echo.h4
-rw-r--r--drivers/staging/echo/fir.h44
-rw-r--r--drivers/staging/echo/mmx.h8
-rw-r--r--drivers/staging/epl/Benchmark.h437
-rw-r--r--drivers/staging/epl/Debug.h734
-rw-r--r--drivers/staging/epl/Edrv8139.c1252
-rw-r--r--drivers/staging/epl/EdrvFec.h114
-rw-r--r--drivers/staging/epl/EdrvFec5282.h340
-rw-r--r--drivers/staging/epl/EdrvSim.h89
-rw-r--r--drivers/staging/epl/Epl.h273
-rw-r--r--drivers/staging/epl/EplAmi.h362
-rw-r--r--drivers/staging/epl/EplApiGeneric.c2060
-rw-r--r--drivers/staging/epl/EplApiLinux.h141
-rw-r--r--drivers/staging/epl/EplApiLinuxKernel.c1260
-rw-r--r--drivers/staging/epl/EplApiProcessImage.c347
-rw-r--r--drivers/staging/epl/EplCfg.h196
-rw-r--r--drivers/staging/epl/EplDef.h355
-rw-r--r--drivers/staging/epl/EplDll.h205
-rw-r--r--drivers/staging/epl/EplDllCal.h123
-rw-r--r--drivers/staging/epl/EplDllk.c4054
-rw-r--r--drivers/staging/epl/EplDllkCal.c1260
-rw-r--r--drivers/staging/epl/EplDlluCal.c529
-rw-r--r--drivers/staging/epl/EplErrDef.h294
-rw-r--r--drivers/staging/epl/EplErrorHandlerk.c810
-rw-r--r--drivers/staging/epl/EplEvent.h279
-rw-r--r--drivers/staging/epl/EplEventk.c853
-rw-r--r--drivers/staging/epl/EplEventu.c814
-rw-r--r--drivers/staging/epl/EplFrame.h344
-rw-r--r--drivers/staging/epl/EplIdentu.c488
-rw-r--r--drivers/staging/epl/EplInc.h385
-rw-r--r--drivers/staging/epl/EplInstDef.h377
-rw-r--r--drivers/staging/epl/EplLed.h92
-rw-r--r--drivers/staging/epl/EplNmt.h230
-rw-r--r--drivers/staging/epl/EplNmtCnu.c704
-rw-r--r--drivers/staging/epl/EplNmtMnu.c2835
-rw-r--r--drivers/staging/epl/EplNmtk.c1842
-rw-r--r--drivers/staging/epl/EplNmtkCal.c149
-rw-r--r--drivers/staging/epl/EplNmtu.c708
-rw-r--r--drivers/staging/epl/EplNmtuCal.c158
-rw-r--r--drivers/staging/epl/EplObd.c3262
-rw-r--r--drivers/staging/epl/EplObd.h464
-rw-r--r--drivers/staging/epl/EplObdMacro.h354
-rw-r--r--drivers/staging/epl/EplObdkCal.c147
-rw-r--r--drivers/staging/epl/EplObdu.c517
-rw-r--r--drivers/staging/epl/EplObduCal.c558
-rw-r--r--drivers/staging/epl/EplObjDef.h208
-rw-r--r--drivers/staging/epl/EplPdo.h117
-rw-r--r--drivers/staging/epl/EplPdok.c694
-rw-r--r--drivers/staging/epl/EplPdokCal.c266
-rw-r--r--drivers/staging/epl/EplPdou.c565
-rw-r--r--drivers/staging/epl/EplSdo.h245
-rw-r--r--drivers/staging/epl/EplSdoAc.h111
-rw-r--r--drivers/staging/epl/EplSdoAsndu.c483
-rw-r--r--drivers/staging/epl/EplSdoAsySequ.c2522
-rw-r--r--drivers/staging/epl/EplSdoComu.c3346
-rw-r--r--drivers/staging/epl/EplSdoUdpu.c790
-rw-r--r--drivers/staging/epl/EplStatusu.c380
-rw-r--r--drivers/staging/epl/EplTarget.h233
-rw-r--r--drivers/staging/epl/EplTimer.h117
-rw-r--r--drivers/staging/epl/EplTimeruLinuxKernel.c446
-rw-r--r--drivers/staging/epl/EplTimeruNull.c312
-rw-r--r--drivers/staging/epl/EplTimeruWin32.c513
-rw-r--r--drivers/staging/epl/EplVersion.h98
-rw-r--r--drivers/staging/epl/Kconfig6
-rw-r--r--drivers/staging/epl/Makefile41
-rw-r--r--drivers/staging/epl/SharedBuff.c1799
-rw-r--r--drivers/staging/epl/SharedBuff.h204
-rw-r--r--drivers/staging/epl/ShbIpc-LinuxKernel.c966
-rw-r--r--drivers/staging/epl/ShbIpc-Win32.c1202
-rw-r--r--drivers/staging/epl/ShbIpc.h125
-rw-r--r--drivers/staging/epl/ShbLinuxKernel.h68
-rw-r--r--drivers/staging/epl/SocketLinuxKernel.c197
-rw-r--r--drivers/staging/epl/SocketLinuxKernel.h105
-rw-r--r--drivers/staging/epl/TimerHighReskX86.c522
-rw-r--r--drivers/staging/epl/VirtualEthernetLinux.c342
-rw-r--r--drivers/staging/epl/amix86.c905
-rw-r--r--drivers/staging/epl/demo_main.c961
-rw-r--r--drivers/staging/epl/edrv.h167
-rw-r--r--drivers/staging/epl/global.h1391
-rw-r--r--drivers/staging/epl/kernel/EplDllk.h165
-rw-r--r--drivers/staging/epl/kernel/EplDllkCal.h141
-rw-r--r--drivers/staging/epl/kernel/EplErrorHandlerk.h100
-rw-r--r--drivers/staging/epl/kernel/EplEventk.h108
-rw-r--r--drivers/staging/epl/kernel/EplNmtk.h105
-rw-r--r--drivers/staging/epl/kernel/EplNmtkCal.h89
-rw-r--r--drivers/staging/epl/kernel/EplObdk.h196
-rw-r--r--drivers/staging/epl/kernel/EplObdkCal.h89
-rw-r--r--drivers/staging/epl/kernel/EplPdok.h110
-rw-r--r--drivers/staging/epl/kernel/EplPdokCal.h99
-rw-r--r--drivers/staging/epl/kernel/EplTimerHighResk.h109
-rw-r--r--drivers/staging/epl/kernel/EplTimerk.h118
-rw-r--r--drivers/staging/epl/kernel/VirtualEthernet.h96
-rw-r--r--drivers/staging/epl/proc_fs.c409
-rw-r--r--drivers/staging/epl/proc_fs.h89
-rw-r--r--drivers/staging/epl/user/EplCfgMau.h284
-rw-r--r--drivers/staging/epl/user/EplDllu.h108
-rw-r--r--drivers/staging/epl/user/EplDlluCal.h117
-rw-r--r--drivers/staging/epl/user/EplEventu.h108
-rw-r--r--drivers/staging/epl/user/EplIdentu.h108
-rw-r--r--drivers/staging/epl/user/EplLedu.h109
-rw-r--r--drivers/staging/epl/user/EplNmtCnu.h108
-rw-r--r--drivers/staging/epl/user/EplNmtMnu.h131
-rw-r--r--drivers/staging/epl/user/EplNmtu.h155
-rw-r--r--drivers/staging/epl/user/EplNmtuCal.h91
-rw-r--r--drivers/staging/epl/user/EplObdu.h192
-rw-r--r--drivers/staging/epl/user/EplObduCal.h148
-rw-r--r--drivers/staging/epl/user/EplPdou.h108
-rw-r--r--drivers/staging/epl/user/EplSdoAsndu.h107
-rw-r--r--drivers/staging/epl/user/EplSdoAsySequ.h111
-rw-r--r--drivers/staging/epl/user/EplSdoComu.h126
-rw-r--r--drivers/staging/epl/user/EplSdoUdpu.h109
-rw-r--r--drivers/staging/epl/user/EplStatusu.h104
-rw-r--r--drivers/staging/epl/user/EplTimeru.h107
-rw-r--r--drivers/staging/et131x/et1310_tx.c3
-rw-r--r--drivers/staging/et131x/et131x_debug.h160
-rw-r--r--drivers/staging/frontier/Kconfig6
-rw-r--r--drivers/staging/frontier/Makefile2
-rw-r--r--drivers/staging/frontier/README28
-rw-r--r--drivers/staging/frontier/TODO9
-rw-r--r--drivers/staging/frontier/alphatrack.c853
-rw-r--r--drivers/staging/frontier/alphatrack.h92
-rw-r--r--drivers/staging/frontier/frontier_compat.h63
-rw-r--r--drivers/staging/frontier/surface_sysfs.h100
-rw-r--r--drivers/staging/frontier/tranzport.c1006
-rw-r--r--drivers/staging/go7007/Kconfig10
-rw-r--r--drivers/staging/go7007/Makefile15
-rw-r--r--drivers/staging/go7007/go7007-driver.c5
-rw-r--r--drivers/staging/go7007/go7007-fw.c30
-rw-r--r--drivers/staging/go7007/go7007-priv.h2
-rw-r--r--drivers/staging/go7007/go7007-usb.c95
-rw-r--r--drivers/staging/go7007/go7007-v4l2.c1706
-rw-r--r--drivers/staging/go7007/go7007.txt481
-rw-r--r--drivers/staging/go7007/s2250-board.c630
-rw-r--r--drivers/staging/go7007/s2250-loader.c188
-rw-r--r--drivers/staging/go7007/saa7134-go7007.c52
-rw-r--r--drivers/staging/go7007/wis-i2c.h1
-rw-r--r--drivers/staging/go7007/wis-sony-tuner.c2
-rw-r--r--drivers/staging/me4000/me4000.c99
-rw-r--r--drivers/staging/meilhaus/Kconfig128
-rw-r--r--drivers/staging/meilhaus/Makefile43
-rw-r--r--drivers/staging/meilhaus/TODO10
-rw-r--r--drivers/staging/meilhaus/me0600_device.c215
-rw-r--r--drivers/staging/meilhaus/me0600_device.h97
-rw-r--r--drivers/staging/meilhaus/me0600_dio.c415
-rw-r--r--drivers/staging/meilhaus/me0600_dio.h68
-rw-r--r--drivers/staging/meilhaus/me0600_dio_reg.h41
-rw-r--r--drivers/staging/meilhaus/me0600_ext_irq.c478
-rw-r--r--drivers/staging/meilhaus/me0600_ext_irq.h58
-rw-r--r--drivers/staging/meilhaus/me0600_ext_irq_reg.h18
-rw-r--r--drivers/staging/meilhaus/me0600_optoi.c243
-rw-r--r--drivers/staging/meilhaus/me0600_optoi.h58
-rw-r--r--drivers/staging/meilhaus/me0600_optoi_reg.h35
-rw-r--r--drivers/staging/meilhaus/me0600_relay.c359
-rw-r--r--drivers/staging/meilhaus/me0600_relay.h63
-rw-r--r--drivers/staging/meilhaus/me0600_relay_reg.h36
-rw-r--r--drivers/staging/meilhaus/me0600_ttli.c238
-rw-r--r--drivers/staging/meilhaus/me0600_ttli.h58
-rw-r--r--drivers/staging/meilhaus/me0600_ttli_reg.h35
-rw-r--r--drivers/staging/meilhaus/me0900_device.c180
-rw-r--r--drivers/staging/meilhaus/me0900_device.h92
-rw-r--r--drivers/staging/meilhaus/me0900_di.c246
-rw-r--r--drivers/staging/meilhaus/me0900_di.h65
-rw-r--r--drivers/staging/meilhaus/me0900_do.c314
-rw-r--r--drivers/staging/meilhaus/me0900_do.h68
-rw-r--r--drivers/staging/meilhaus/me0900_reg.h40
-rw-r--r--drivers/staging/meilhaus/me1000_device.c208
-rw-r--r--drivers/staging/meilhaus/me1000_device.h59
-rw-r--r--drivers/staging/meilhaus/me1000_dio.c438
-rw-r--r--drivers/staging/meilhaus/me1000_dio.h71
-rw-r--r--drivers/staging/meilhaus/me1000_dio_reg.h50
-rw-r--r--drivers/staging/meilhaus/me1400_device.c256
-rw-r--r--drivers/staging/meilhaus/me1400_device.h108
-rw-r--r--drivers/staging/meilhaus/me1400_ext_irq.c517
-rw-r--r--drivers/staging/meilhaus/me1400_ext_irq.h62
-rw-r--r--drivers/staging/meilhaus/me1400_ext_irq_reg.h56
-rw-r--r--drivers/staging/meilhaus/me1600_ao.c1033
-rw-r--r--drivers/staging/meilhaus/me1600_ao.h132
-rw-r--r--drivers/staging/meilhaus/me1600_ao_reg.h66
-rw-r--r--drivers/staging/meilhaus/me1600_device.c261
-rw-r--r--drivers/staging/meilhaus/me1600_device.h101
-rw-r--r--drivers/staging/meilhaus/me4600_ai.c3434
-rw-r--r--drivers/staging/meilhaus/me4600_ai.h180
-rw-r--r--drivers/staging/meilhaus/me4600_ai_reg.h107
-rw-r--r--drivers/staging/meilhaus/me4600_ao.c6011
-rw-r--r--drivers/staging/meilhaus/me4600_ao.h263
-rw-r--r--drivers/staging/meilhaus/me4600_ao_reg.h113
-rw-r--r--drivers/staging/meilhaus/me4600_device.c373
-rw-r--r--drivers/staging/meilhaus/me4600_device.h151
-rw-r--r--drivers/staging/meilhaus/me4600_di.c256
-rw-r--r--drivers/staging/meilhaus/me4600_di.h64
-rw-r--r--drivers/staging/meilhaus/me4600_dio.c510
-rw-r--r--drivers/staging/meilhaus/me4600_dio.h69
-rw-r--r--drivers/staging/meilhaus/me4600_dio_reg.h63
-rw-r--r--drivers/staging/meilhaus/me4600_do.c433
-rw-r--r--drivers/staging/meilhaus/me4600_do.h65
-rw-r--r--drivers/staging/meilhaus/me4600_ext_irq.c467
-rw-r--r--drivers/staging/meilhaus/me4600_ext_irq.h78
-rw-r--r--drivers/staging/meilhaus/me4600_ext_irq_reg.h41
-rw-r--r--drivers/staging/meilhaus/me4600_reg.h46
-rw-r--r--drivers/staging/meilhaus/me6000_ao.c3739
-rw-r--r--drivers/staging/meilhaus/me6000_ao.h200
-rw-r--r--drivers/staging/meilhaus/me6000_ao_reg.h177
-rw-r--r--drivers/staging/meilhaus/me6000_device.c211
-rw-r--r--drivers/staging/meilhaus/me6000_device.h149
-rw-r--r--drivers/staging/meilhaus/me6000_dio.c415
-rw-r--r--drivers/staging/meilhaus/me6000_dio.h68
-rw-r--r--drivers/staging/meilhaus/me6000_dio_reg.h43
-rw-r--r--drivers/staging/meilhaus/me6000_reg.h35
-rw-r--r--drivers/staging/meilhaus/me8100_device.c187
-rw-r--r--drivers/staging/meilhaus/me8100_device.h97
-rw-r--r--drivers/staging/meilhaus/me8100_di.c693
-rw-r--r--drivers/staging/meilhaus/me8100_di.h89
-rw-r--r--drivers/staging/meilhaus/me8100_di_reg.h47
-rw-r--r--drivers/staging/meilhaus/me8100_do.c391
-rw-r--r--drivers/staging/meilhaus/me8100_do.h70
-rw-r--r--drivers/staging/meilhaus/me8100_do_reg.h36
-rw-r--r--drivers/staging/meilhaus/me8100_reg.h41
-rw-r--r--drivers/staging/meilhaus/me8200_device.c194
-rw-r--r--drivers/staging/meilhaus/me8200_device.h97
-rw-r--r--drivers/staging/meilhaus/me8200_di.c857
-rw-r--r--drivers/staging/meilhaus/me8200_di.h92
-rw-r--r--drivers/staging/meilhaus/me8200_di_reg.h75
-rw-r--r--drivers/staging/meilhaus/me8200_dio.c418
-rw-r--r--drivers/staging/meilhaus/me8200_dio.h68
-rw-r--r--drivers/staging/meilhaus/me8200_dio_reg.h43
-rw-r--r--drivers/staging/meilhaus/me8200_do.c600
-rw-r--r--drivers/staging/meilhaus/me8200_do.h75
-rw-r--r--drivers/staging/meilhaus/me8200_do_reg.h40
-rw-r--r--drivers/staging/meilhaus/me8200_reg.h46
-rw-r--r--drivers/staging/meilhaus/me8254.c1176
-rw-r--r--drivers/staging/meilhaus/me8254.h80
-rw-r--r--drivers/staging/meilhaus/me8254_reg.h172
-rw-r--r--drivers/staging/meilhaus/me8255.c462
-rw-r--r--drivers/staging/meilhaus/me8255.h59
-rw-r--r--drivers/staging/meilhaus/me8255_reg.h50
-rw-r--r--drivers/staging/meilhaus/mecirc_buf.h131
-rw-r--r--drivers/staging/meilhaus/mecommon.h26
-rw-r--r--drivers/staging/meilhaus/medebug.h125
-rw-r--r--drivers/staging/meilhaus/medefines.h449
-rw-r--r--drivers/staging/meilhaus/medevice.c1740
-rw-r--r--drivers/staging/meilhaus/medevice.h304
-rw-r--r--drivers/staging/meilhaus/medlist.c127
-rw-r--r--drivers/staging/meilhaus/medlist.h91
-rw-r--r--drivers/staging/meilhaus/medlock.c195
-rw-r--r--drivers/staging/meilhaus/medlock.h76
-rw-r--r--drivers/staging/meilhaus/medriver.h350
-rw-r--r--drivers/staging/meilhaus/medummy.c1266
-rw-r--r--drivers/staging/meilhaus/medummy.h40
-rw-r--r--drivers/staging/meilhaus/meerror.h100
-rw-r--r--drivers/staging/meilhaus/mefirmware.c137
-rw-r--r--drivers/staging/meilhaus/mefirmware.h57
-rw-r--r--drivers/staging/meilhaus/meids.h31
-rw-r--r--drivers/staging/meilhaus/meinternal.h363
-rw-r--r--drivers/staging/meilhaus/meioctl.h515
-rw-r--r--drivers/staging/meilhaus/memain.c2022
-rw-r--r--drivers/staging/meilhaus/memain.h460
-rw-r--r--drivers/staging/meilhaus/meplx_reg.h53
-rw-r--r--drivers/staging/meilhaus/meslist.c173
-rw-r--r--drivers/staging/meilhaus/meslist.h108
-rw-r--r--drivers/staging/meilhaus/meslock.c136
-rw-r--r--drivers/staging/meilhaus/meslock.h73
-rw-r--r--drivers/staging/meilhaus/mesubdevice.c317
-rw-r--r--drivers/staging/meilhaus/mesubdevice.h197
-rw-r--r--drivers/staging/meilhaus/metempl_device.c137
-rw-r--r--drivers/staging/meilhaus/metempl_device.h92
-rw-r--r--drivers/staging/meilhaus/metempl_sub.c149
-rw-r--r--drivers/staging/meilhaus/metempl_sub.h64
-rw-r--r--drivers/staging/meilhaus/metempl_sub_reg.h35
-rw-r--r--drivers/staging/meilhaus/metypes.h95
-rw-r--r--drivers/staging/mimio/Kconfig10
-rw-r--r--drivers/staging/mimio/Makefile1
-rw-r--r--drivers/staging/mimio/mimio.c914
-rw-r--r--drivers/staging/otus/80211core/amsdu.c134
-rw-r--r--drivers/staging/otus/80211core/cagg.c3611
-rw-r--r--drivers/staging/otus/80211core/cagg.h435
-rw-r--r--drivers/staging/otus/80211core/ccmd.c1861
-rw-r--r--drivers/staging/otus/80211core/cfunc.c1227
-rw-r--r--drivers/staging/otus/80211core/cfunc.h449
-rw-r--r--drivers/staging/otus/80211core/chb.c200
-rw-r--r--drivers/staging/otus/80211core/cic.c496
-rw-r--r--drivers/staging/otus/80211core/cinit.c1911
-rw-r--r--drivers/staging/otus/80211core/cmm.c2141
-rw-r--r--drivers/staging/otus/80211core/cmmap.c2402
-rw-r--r--drivers/staging/otus/80211core/cmmsta.c5782
-rw-r--r--drivers/staging/otus/80211core/coid.c2695
-rw-r--r--drivers/staging/otus/80211core/cprecomp.h32
-rw-r--r--drivers/staging/otus/80211core/cpsmgr.c731
-rw-r--r--drivers/staging/otus/80211core/cscanmgr.c535
-rw-r--r--drivers/staging/otus/80211core/ctkip.c598
-rw-r--r--drivers/staging/otus/80211core/ctxrx.c4096
-rw-r--r--drivers/staging/otus/80211core/cwep.c299
-rw-r--r--drivers/staging/otus/80211core/cwm.c131
-rw-r--r--drivers/staging/otus/80211core/cwm.h45
-rw-r--r--drivers/staging/otus/80211core/freqctrl.c259
-rw-r--r--drivers/staging/otus/80211core/ledmgr.c557
-rw-r--r--drivers/staging/otus/80211core/performance.c431
-rw-r--r--drivers/staging/otus/80211core/performance.h97
-rw-r--r--drivers/staging/otus/80211core/pub_usb.h102
-rw-r--r--drivers/staging/otus/80211core/pub_zfi.h821
-rw-r--r--drivers/staging/otus/80211core/pub_zfw.h93
-rw-r--r--drivers/staging/otus/80211core/queue.c303
-rw-r--r--drivers/staging/otus/80211core/queue.h37
-rw-r--r--drivers/staging/otus/80211core/ratectrl.c874
-rw-r--r--drivers/staging/otus/80211core/ratectrl.h37
-rw-r--r--drivers/staging/otus/80211core/struct.h1315
-rw-r--r--drivers/staging/otus/80211core/wlan.h595
-rw-r--r--drivers/staging/otus/Kconfig32
-rw-r--r--drivers/staging/otus/Makefile67
-rw-r--r--drivers/staging/otus/TODO9
-rw-r--r--drivers/staging/otus/apdbg.c457
-rw-r--r--drivers/staging/otus/athr_common.h141
-rw-r--r--drivers/staging/otus/hal/hpDKfwu.c832
-rw-r--r--drivers/staging/otus/hal/hpani.c732
-rw-r--r--drivers/staging/otus/hal/hpani.h420
-rw-r--r--drivers/staging/otus/hal/hpfw2.c1018
-rw-r--r--drivers/staging/otus/hal/hpfwbu.c5269
-rw-r--r--drivers/staging/otus/hal/hpfwspiu.c655
-rw-r--r--drivers/staging/otus/hal/hpfwu.c1017
-rw-r--r--drivers/staging/otus/hal/hpfwu.c.drv_ba_resend742
-rw-r--r--drivers/staging/otus/hal/hpfwu_2k.c1016
-rw-r--r--drivers/staging/otus/hal/hpfwu_BA.c874
-rw-r--r--drivers/staging/otus/hal/hpfwu_FB50_mdk.c721
-rw-r--r--drivers/staging/otus/hal/hpfwu_OTUS_RC.c715
-rw-r--r--drivers/staging/otus/hal/hpfwu_txstream.c1017
-rw-r--r--drivers/staging/otus/hal/hpfwuinit.c240
-rw-r--r--drivers/staging/otus/hal/hpmain.c4643
-rw-r--r--drivers/staging/otus/hal/hpreg.c2481
-rw-r--r--drivers/staging/otus/hal/hpreg.h524
-rw-r--r--drivers/staging/otus/hal/hprw.c1557
-rw-r--r--drivers/staging/otus/hal/hpusb.c1584
-rw-r--r--drivers/staging/otus/hal/hpusb.h437
-rw-r--r--drivers/staging/otus/hal/otus.ini414
-rw-r--r--drivers/staging/otus/ioctl.c2913
-rw-r--r--drivers/staging/otus/oal_dt.h60
-rw-r--r--drivers/staging/otus/oal_marc.h135
-rw-r--r--drivers/staging/otus/usbdrv.c1148
-rw-r--r--drivers/staging/otus/usbdrv.h252
-rw-r--r--drivers/staging/otus/wrap_buf.c114
-rw-r--r--drivers/staging/otus/wrap_dbg.c101
-rw-r--r--drivers/staging/otus/wrap_ev.c283
-rw-r--r--drivers/staging/otus/wrap_mem.c101
-rw-r--r--drivers/staging/otus/wrap_mis.c109
-rw-r--r--drivers/staging/otus/wrap_pkt.c173
-rw-r--r--drivers/staging/otus/wrap_sec.c127
-rw-r--r--drivers/staging/otus/wrap_usb.c191
-rw-r--r--drivers/staging/otus/wwrap.c1134
-rw-r--r--drivers/staging/otus/zdcompat.h62
-rw-r--r--drivers/staging/otus/zdusb.c239
-rw-r--r--drivers/staging/otus/zdusb.h43
-rw-r--r--drivers/staging/panel/Kconfig278
-rw-r--r--drivers/staging/panel/Makefile1
-rw-r--r--drivers/staging/panel/TODO9
-rw-r--r--drivers/staging/panel/lcd-panel-cgram.txt24
-rw-r--r--drivers/staging/panel/panel.c2193
-rw-r--r--drivers/staging/poch/README9
-rw-r--r--drivers/staging/poch/poch.c106
-rw-r--r--drivers/staging/rspiusb/Kconfig6
-rw-r--r--drivers/staging/rspiusb/Makefile1
-rw-r--r--drivers/staging/rspiusb/TODO22
-rw-r--r--drivers/staging/rspiusb/rspiusb.c887
-rw-r--r--drivers/staging/rspiusb/rspiusb.h25
-rw-r--r--drivers/staging/rt2860/2860_main_dev.c1377
-rw-r--r--drivers/staging/rt2860/Kconfig5
-rw-r--r--drivers/staging/rt2860/Makefile43
-rw-r--r--drivers/staging/rt2860/TODO17
-rw-r--r--drivers/staging/rt2860/aironet.h210
-rw-r--r--drivers/staging/rt2860/ap.h557
-rw-r--r--drivers/staging/rt2860/chlist.h1296
-rw-r--r--drivers/staging/rt2860/common/2860_rtmp_init.c922
-rw-r--r--drivers/staging/rt2860/common/action.c1031
-rw-r--r--drivers/staging/rt2860/common/action.h68
-rw-r--r--drivers/staging/rt2860/common/ba_action.c1802
-rw-r--r--drivers/staging/rt2860/common/cmm_data.c3466
-rw-r--r--drivers/staging/rt2860/common/cmm_data_2860.c1240
-rw-r--r--drivers/staging/rt2860/common/cmm_info.c3417
-rw-r--r--drivers/staging/rt2860/common/cmm_sanity.c1633
-rw-r--r--drivers/staging/rt2860/common/cmm_sync.c702
-rw-r--r--drivers/staging/rt2860/common/cmm_wpa.c1606
-rw-r--r--drivers/staging/rt2860/common/dfs.c453
-rw-r--r--drivers/staging/rt2860/common/eeprom.c244
-rw-r--r--drivers/staging/rt2860/common/firmware.h558
-rw-r--r--drivers/staging/rt2860/common/md5.c1427
-rw-r--r--drivers/staging/rt2860/common/mlme.c8667
-rw-r--r--drivers/staging/rt2860/common/netif_block.c144
-rw-r--r--drivers/staging/rt2860/common/netif_block.h58
-rw-r--r--drivers/staging/rt2860/common/rtmp_init.c3744
-rw-r--r--drivers/staging/rt2860/common/rtmp_tkip.c1607
-rw-r--r--drivers/staging/rt2860/common/rtmp_wep.c499
-rw-r--r--drivers/staging/rt2860/common/spectrum.c1877
-rw-r--r--drivers/staging/rt2860/config.mk245
-rw-r--r--drivers/staging/rt2860/dfs.h100
-rw-r--r--drivers/staging/rt2860/leap.h215
-rw-r--r--drivers/staging/rt2860/link_list.h134
-rw-r--r--drivers/staging/rt2860/md4.h42
-rw-r--r--drivers/staging/rt2860/md5.h107
-rw-r--r--drivers/staging/rt2860/mlme.h1447
-rw-r--r--drivers/staging/rt2860/oid.h995
-rw-r--r--drivers/staging/rt2860/rt2860.h349
-rw-r--r--drivers/staging/rt2860/rt28xx.h2714
-rw-r--r--drivers/staging/rt2860/rt_ate.c6025
-rw-r--r--drivers/staging/rt2860/rt_ate.h353
-rw-r--r--drivers/staging/rt2860/rt_config.h101
-rw-r--r--drivers/staging/rt2860/rt_linux.c1054
-rw-r--r--drivers/staging/rt2860/rt_linux.h926
-rw-r--r--drivers/staging/rt2860/rt_main_dev.c1686
-rw-r--r--drivers/staging/rt2860/rt_profile.c1981
-rw-r--r--drivers/staging/rt2860/rtmp.h7177
-rw-r--r--drivers/staging/rt2860/rtmp_ckipmic.h113
-rw-r--r--drivers/staging/rt2860/rtmp_def.h1588
-rw-r--r--drivers/staging/rt2860/rtmp_type.h94
-rw-r--r--drivers/staging/rt2860/spectrum.h322
-rw-r--r--drivers/staging/rt2860/spectrum_def.h95
-rw-r--r--drivers/staging/rt2860/sta/aironet.c1312
-rw-r--r--drivers/staging/rt2860/sta/assoc.c1826
-rw-r--r--drivers/staging/rt2860/sta/auth.c474
-rw-r--r--drivers/staging/rt2860/sta/auth_rsp.c167
-rw-r--r--drivers/staging/rt2860/sta/connect.c2751
-rw-r--r--drivers/staging/rt2860/sta/dls.c2201
-rw-r--r--drivers/staging/rt2860/sta/rtmp_data.c2614
-rw-r--r--drivers/staging/rt2860/sta/sanity.c420
-rw-r--r--drivers/staging/rt2860/sta/sync.c1959
-rw-r--r--drivers/staging/rt2860/sta/wpa.c2086
-rw-r--r--drivers/staging/rt2860/sta_ioctl.c6944
-rw-r--r--drivers/staging/rt2860/wpa.h356
-rw-r--r--drivers/staging/rt2870/2870_main_dev.c1612
-rw-r--r--drivers/staging/rt2870/Kconfig6
-rw-r--r--drivers/staging/rt2870/Makefile47
-rw-r--r--drivers/staging/rt2870/TODO10
-rw-r--r--drivers/staging/rt2870/aironet.h210
-rw-r--r--drivers/staging/rt2870/ap.h562
-rw-r--r--drivers/staging/rt2870/chlist.h1296
-rw-r--r--drivers/staging/rt2870/common/2870_rtmp_init.c1778
-rw-r--r--drivers/staging/rt2870/common/action.c1046
-rw-r--r--drivers/staging/rt2870/common/action.h68
-rw-r--r--drivers/staging/rt2870/common/ba_action.c1798
-rw-r--r--drivers/staging/rt2870/common/cmm_data.c2734
-rw-r--r--drivers/staging/rt2870/common/cmm_data_2870.c963
-rw-r--r--drivers/staging/rt2870/common/cmm_info.c3712
-rw-r--r--drivers/staging/rt2870/common/cmm_sanity.c1663
-rw-r--r--drivers/staging/rt2870/common/cmm_sync.c711
-rw-r--r--drivers/staging/rt2870/common/cmm_wpa.c1654
-rw-r--r--drivers/staging/rt2870/common/dfs.c453
-rw-r--r--drivers/staging/rt2870/common/eeprom.c254
-rw-r--r--drivers/staging/rt2870/common/firmware.h558
-rw-r--r--drivers/staging/rt2870/common/md5.c1427
-rw-r--r--drivers/staging/rt2870/common/mlme.c8609
-rw-r--r--drivers/staging/rt2870/common/netif_block.c144
-rw-r--r--drivers/staging/rt2870/common/rtmp_init.c4132
-rw-r--r--drivers/staging/rt2870/common/rtmp_tkip.c1613
-rw-r--r--drivers/staging/rt2870/common/rtmp_wep.c508
-rw-r--r--drivers/staging/rt2870/common/rtusb_bulk.c1981
-rw-r--r--drivers/staging/rt2870/common/rtusb_data.c229
-rw-r--r--drivers/staging/rt2870/common/rtusb_io.c2006
-rw-r--r--drivers/staging/rt2870/common/spectrum.c1876
-rw-r--r--drivers/staging/rt2870/dfs.h100
-rw-r--r--drivers/staging/rt2870/leap.h215
-rw-r--r--drivers/staging/rt2870/link_list.h134
-rw-r--r--drivers/staging/rt2870/md4.h42
-rw-r--r--drivers/staging/rt2870/md5.h107
-rw-r--r--drivers/staging/rt2870/mlme.h1471
-rw-r--r--drivers/staging/rt2870/netif_block.h58
-rw-r--r--drivers/staging/rt2870/oid.h1091
-rw-r--r--drivers/staging/rt2870/rt2870.h761
-rw-r--r--drivers/staging/rt2870/rt28xx.h2689
-rw-r--r--drivers/staging/rt2870/rt_ate.c6452
-rw-r--r--drivers/staging/rt2870/rt_ate.h315
-rw-r--r--drivers/staging/rt2870/rt_config.h104
-rw-r--r--drivers/staging/rt2870/rt_linux.c1095
-rw-r--r--drivers/staging/rt2870/rt_linux.h908
-rw-r--r--drivers/staging/rt2870/rt_main_dev.c1863
-rw-r--r--drivers/staging/rt2870/rt_profile.c2020
-rw-r--r--drivers/staging/rt2870/rtmp.h7586
-rw-r--r--drivers/staging/rt2870/rtmp_ckipmic.h113
-rw-r--r--drivers/staging/rt2870/rtmp_def.h1622
-rw-r--r--drivers/staging/rt2870/rtmp_type.h94
-rw-r--r--drivers/staging/rt2870/spectrum.h322
-rw-r--r--drivers/staging/rt2870/spectrum_def.h95
-rw-r--r--drivers/staging/rt2870/sta/aironet.c1312
-rw-r--r--drivers/staging/rt2870/sta/assoc.c2039
-rw-r--r--drivers/staging/rt2870/sta/auth.c474
-rw-r--r--drivers/staging/rt2870/sta/auth_rsp.c166
-rw-r--r--drivers/staging/rt2870/sta/connect.c2822
-rw-r--r--drivers/staging/rt2870/sta/dls.c2210
-rw-r--r--drivers/staging/rt2870/sta/rtmp_data.c2619
-rw-r--r--drivers/staging/rt2870/sta/sanity.c420
-rw-r--r--drivers/staging/rt2870/sta/sync.c1753
-rw-r--r--drivers/staging/rt2870/sta/wpa.c2107
-rw-r--r--drivers/staging/rt2870/sta_ioctl.c7068
-rw-r--r--drivers/staging/rt2870/sta_ioctl.c.patch18
-rw-r--r--drivers/staging/rt2870/tmp607037
-rw-r--r--drivers/staging/rt2870/tmp617037
-rw-r--r--drivers/staging/rt2870/wpa.h357
-rw-r--r--drivers/staging/rtl8187se/Kconfig5
-rw-r--r--drivers/staging/rtl8187se/Makefile55
-rw-r--r--drivers/staging/rtl8187se/dot11d.h101
-rw-r--r--drivers/staging/rtl8187se/ieee80211.h1755
-rw-r--r--drivers/staging/rtl8187se/ieee80211/dot11d.c246
-rw-r--r--drivers/staging/rtl8187se/ieee80211/dot11d.h102
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211.h1755
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c265
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h86
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c533
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c1001
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c394
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_module.c301
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c1971
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c4029
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c602
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c828
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c884
-rw-r--r--drivers/staging/rtl8187se/ieee80211/internal.h115
-rw-r--r--drivers/staging/rtl8187se/ieee80211/rtl_crypto.h399
-rw-r--r--drivers/staging/rtl8187se/ieee80211_crypt.h86
-rw-r--r--drivers/staging/rtl8187se/r8180.h761
-rw-r--r--drivers/staging/rtl8187se/r8180_93cx6.c146
-rw-r--r--drivers/staging/rtl8187se/r8180_93cx6.h59
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c6828
-rw-r--r--drivers/staging/rtl8187se/r8180_dm.c1725
-rw-r--r--drivers/staging/rtl8187se/r8180_dm.h41
-rw-r--r--drivers/staging/rtl8187se/r8180_gct.c296
-rw-r--r--drivers/staging/rtl8187se/r8180_gct.h25
-rw-r--r--drivers/staging/rtl8187se/r8180_hw.h956
-rw-r--r--drivers/staging/rtl8187se/r8180_max2820.c240
-rw-r--r--drivers/staging/rtl8187se/r8180_max2820.h21
-rw-r--r--drivers/staging/rtl8187se/r8180_pm.c90
-rw-r--r--drivers/staging/rtl8187se/r8180_pm.h28
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225.c933
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225.h44
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225z2.c1587
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8255.c1838
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8255.h19
-rw-r--r--drivers/staging/rtl8187se/r8180_sa2400.c233
-rw-r--r--drivers/staging/rtl8187se/r8180_sa2400.h26
-rw-r--r--drivers/staging/rtl8187se/r8180_wx.c1644
-rw-r--r--drivers/staging/rtl8187se/r8180_wx.h21
-rw-r--r--drivers/staging/rtl8187se/r8185b_init.c3342
-rw-r--r--drivers/staging/slicoss/slic.h34
-rw-r--r--drivers/staging/slicoss/slicoss.c84
-rw-r--r--drivers/staging/sxg/README2
-rw-r--r--drivers/staging/sxg/sxg.c316
-rw-r--r--drivers/staging/sxg/sxg.h121
-rw-r--r--drivers/staging/sxg/sxg_os.h24
-rw-r--r--drivers/staging/sxg/sxgdbg.h15
-rw-r--r--drivers/staging/sxg/sxghif.h139
-rw-r--r--drivers/staging/sxg/sxghw.h40
-rw-r--r--drivers/staging/sxg/sxgphycode.h2
-rw-r--r--drivers/staging/usbip/stub.h2
-rw-r--r--drivers/staging/usbip/stub_dev.c2
-rw-r--r--drivers/staging/usbip/stub_main.c21
-rw-r--r--drivers/staging/usbip/stub_rx.c9
-rw-r--r--drivers/staging/usbip/stub_tx.c1
-rw-r--r--drivers/staging/usbip/usbip_common.c16
-rw-r--r--drivers/staging/usbip/vhci_hcd.c2
-rw-r--r--drivers/staging/usbip/vhci_sysfs.c2
-rw-r--r--drivers/staging/winbond/Kconfig12
-rw-r--r--drivers/staging/winbond/Makefile17
-rw-r--r--drivers/staging/winbond/adapter.h23
-rw-r--r--drivers/staging/winbond/bss_f.h80
-rw-r--r--drivers/staging/winbond/bssdscpt.h20
-rw-r--r--drivers/staging/winbond/common.h27
-rw-r--r--drivers/staging/winbond/core.h42
-rw-r--r--drivers/staging/winbond/ds_tkip.h12
-rw-r--r--drivers/staging/winbond/gl_80211.h3
-rw-r--r--drivers/staging/winbond/linux/common.h128
-rw-r--r--drivers/staging/winbond/linux/wb35rx_f.h17
-rw-r--r--drivers/staging/winbond/linux/wb35tx_f.h20
-rw-r--r--drivers/staging/winbond/linux/wbusb.c391
-rw-r--r--drivers/staging/winbond/linux/wbusb_f.h34
-rw-r--r--drivers/staging/winbond/localpara.h11
-rw-r--r--drivers/staging/winbond/mac_structures.h7
-rw-r--r--drivers/staging/winbond/mds.c831
-rw-r--r--drivers/staging/winbond/mds_f.h42
-rw-r--r--drivers/staging/winbond/mds_s.h42
-rw-r--r--drivers/staging/winbond/mlme_mib.h20
-rw-r--r--drivers/staging/winbond/mlme_s.h11
-rw-r--r--drivers/staging/winbond/mlmetxrx.c113
-rw-r--r--drivers/staging/winbond/mlmetxrx_f.h25
-rw-r--r--drivers/staging/winbond/mto.c991
-rw-r--r--drivers/staging/winbond/mto.h27
-rw-r--r--drivers/staging/winbond/mto_f.h12
-rw-r--r--drivers/staging/winbond/os_common.h2
-rw-r--r--drivers/staging/winbond/phy_calibration.c40
-rw-r--r--drivers/staging/winbond/phy_calibration.h6
-rw-r--r--drivers/staging/winbond/reg.c349
-rw-r--r--drivers/staging/winbond/rxisr.c30
-rw-r--r--drivers/staging/winbond/scan_s.h22
-rw-r--r--drivers/staging/winbond/sme_api.c14
-rw-r--r--drivers/staging/winbond/sme_api.h7
-rw-r--r--drivers/staging/winbond/sme_s.h16
-rw-r--r--drivers/staging/winbond/sysdef.h (renamed from drivers/staging/winbond/linux/sysdef.h)33
-rw-r--r--drivers/staging/winbond/wb35reg.c (renamed from drivers/staging/winbond/linux/wb35reg.c)531
-rw-r--r--drivers/staging/winbond/wb35reg_f.h (renamed from drivers/staging/winbond/linux/wb35reg_f.h)9
-rw-r--r--drivers/staging/winbond/wb35reg_s.h (renamed from drivers/staging/winbond/linux/wb35reg_s.h)46
-rw-r--r--drivers/staging/winbond/wb35rx.c (renamed from drivers/staging/winbond/linux/wb35rx.c)421
-rw-r--r--drivers/staging/winbond/wb35rx_f.h15
-rw-r--r--drivers/staging/winbond/wb35rx_s.h (renamed from drivers/staging/winbond/linux/wb35rx_s.h)2
-rw-r--r--drivers/staging/winbond/wb35tx.c (renamed from drivers/staging/winbond/linux/wb35tx.c)248
-rw-r--r--drivers/staging/winbond/wb35tx_f.h21
-rw-r--r--drivers/staging/winbond/wb35tx_s.h (renamed from drivers/staging/winbond/linux/wb35tx_s.h)14
-rw-r--r--drivers/staging/winbond/wbhal.c830
-rw-r--r--drivers/staging/winbond/wbhal_f.h49
-rw-r--r--drivers/staging/winbond/wbhal_s.h33
-rw-r--r--drivers/staging/winbond/wblinux.c275
-rw-r--r--drivers/staging/winbond/wblinux_f.h21
-rw-r--r--drivers/staging/winbond/wblinux_s.h45
-rw-r--r--drivers/staging/winbond/wbusb.c438
-rw-r--r--drivers/staging/winbond/wbusb_s.h (renamed from drivers/staging/winbond/linux/wbusb_s.h)17
-rw-r--r--drivers/staging/wlan-ng/Kconfig6
-rw-r--r--drivers/staging/wlan-ng/Makefile3
-rw-r--r--drivers/staging/wlan-ng/README1
-rw-r--r--drivers/staging/wlan-ng/hfa384x.c4018
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h2491
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c655
-rw-r--r--drivers/staging/wlan-ng/p80211conv.c43
-rw-r--r--drivers/staging/wlan-ng/p80211conv.h76
-rw-r--r--drivers/staging/wlan-ng/p80211hdr.h90
-rw-r--r--drivers/staging/wlan-ng/p80211ioctl.h6
-rw-r--r--drivers/staging/wlan-ng/p80211meta.h46
-rw-r--r--drivers/staging/wlan-ng/p80211metadef.h1785
-rw-r--r--drivers/staging/wlan-ng/p80211metamib.h2
-rw-r--r--drivers/staging/wlan-ng/p80211metamsg.h2
-rw-r--r--drivers/staging/wlan-ng/p80211metastruct.h463
-rw-r--r--drivers/staging/wlan-ng/p80211mgmt.h194
-rw-r--r--drivers/staging/wlan-ng/p80211mod.c216
-rw-r--r--drivers/staging/wlan-ng/p80211msg.h14
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c357
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h180
-rw-r--r--drivers/staging/wlan-ng/p80211req.c39
-rw-r--r--drivers/staging/wlan-ng/p80211req.h2
-rw-r--r--drivers/staging/wlan-ng/p80211types.h208
-rw-r--r--drivers/staging/wlan-ng/p80211wep.c21
-rw-r--r--drivers/staging/wlan-ng/p80211wext.c353
-rw-r--r--drivers/staging/wlan-ng/prism2_cs.c1487
-rw-r--r--drivers/staging/wlan-ng/prism2_pci.c332
-rw-r--r--drivers/staging/wlan-ng/prism2_plx.c472
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.c1673
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.h59
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c2790
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c338
-rw-r--r--drivers/staging/wlan-ng/prism2usb.c (renamed from drivers/staging/wlan-ng/prism2_usb.c)77
-rw-r--r--drivers/staging/wlan-ng/version.h64
-rw-r--r--drivers/staging/wlan-ng/wlan_compat.h570
-rw-r--r--drivers/thermal/thermal_sys.c6
-rw-r--r--drivers/uio/uio.c159
-rw-r--r--drivers/uio/uio_cif.c3
-rw-r--r--drivers/uio/uio_pdrv_genirq.c5
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/class/cdc-acm.c11
-rw-r--r--drivers/usb/class/cdc-wdm.c3
-rw-r--r--drivers/usb/class/usblp.c1
-rw-r--r--drivers/usb/class/usbtmc.c9
-rw-r--r--drivers/usb/core/devio.c27
-rw-r--r--drivers/usb/core/driver.c183
-rw-r--r--drivers/usb/core/endpoint.c4
-rw-r--r--drivers/usb/core/generic.c10
-rw-r--r--drivers/usb/core/hcd-pci.c188
-rw-r--r--drivers/usb/core/hcd.c20
-rw-r--r--drivers/usb/core/hcd.h15
-rw-r--r--drivers/usb/core/hub.c148
-rw-r--r--drivers/usb/core/inode.c2
-rw-r--r--drivers/usb/core/message.c204
-rw-r--r--drivers/usb/core/sysfs.c49
-rw-r--r--drivers/usb/core/urb.c43
-rw-r--r--drivers/usb/core/usb.c83
-rw-r--r--drivers/usb/core/usb.h30
-rw-r--r--drivers/usb/gadget/Kconfig43
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/at91_udc.c2
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c2830
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.h195
-rw-r--r--drivers/usb/gadget/composite.c9
-rw-r--r--drivers/usb/gadget/epautoconf.c2
-rw-r--r--drivers/usb/gadget/f_phonet.c12
-rw-r--r--drivers/usb/gadget/file_storage.c195
-rw-r--r--drivers/usb/gadget/fsl_qe_udc.c14
-rw-r--r--drivers/usb/gadget/gadget_chips.h8
-rw-r--r--drivers/usb/gadget/goku_udc.c2
-rw-r--r--drivers/usb/gadget/imx_udc.c1516
-rw-r--r--drivers/usb/gadget/imx_udc.h344
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c2
-rw-r--r--drivers/usb/gadget/m66592-udc.c9
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c4
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c4
-rw-r--r--drivers/usb/gadget/pxa27x_udc.c4
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c36
-rw-r--r--drivers/usb/gadget/u_ether.c16
-rw-r--r--drivers/usb/host/Kconfig31
-rw-r--r--drivers/usb/host/Makefile7
-rw-r--r--drivers/usb/host/ehci-dbg.c8
-rw-r--r--drivers/usb/host/ehci-hub.c27
-rw-r--r--drivers/usb/host/ehci-pci.c13
-rw-r--r--drivers/usb/host/ehci-ppc-of.c45
-rw-r--r--drivers/usb/host/ehci.h34
-rw-r--r--drivers/usb/host/fhci-dbg.c139
-rw-r--r--drivers/usb/host/fhci-hcd.c836
-rw-r--r--drivers/usb/host/fhci-hub.c345
-rw-r--r--drivers/usb/host/fhci-mem.c113
-rw-r--r--drivers/usb/host/fhci-q.c284
-rw-r--r--drivers/usb/host/fhci-sched.c888
-rw-r--r--drivers/usb/host/fhci-tds.c626
-rw-r--r--drivers/usb/host/fhci.h607
-rw-r--r--drivers/usb/host/hwa-hc.c159
-rw-r--r--drivers/usb/host/isp1760-hcd.c13
-rw-r--r--drivers/usb/host/isp1760-hcd.h1
-rw-r--r--drivers/usb/host/isp1760-if.c116
-rw-r--r--drivers/usb/host/ohci-hcd.c14
-rw-r--r--drivers/usb/host/ohci-omap.c6
-rw-r--r--drivers/usb/host/ohci-pci.c5
-rw-r--r--drivers/usb/host/ohci-pnx4008.c85
-rw-r--r--drivers/usb/host/ohci-ppc-of.c25
-rw-r--r--drivers/usb/host/ohci-tmio.c2
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c3985
-rw-r--r--drivers/usb/host/oxu210hp.h447
-rw-r--r--drivers/usb/host/pci-quirks.c14
-rw-r--r--drivers/usb/host/r8a66597-hcd.c8
-rw-r--r--drivers/usb/host/uhci-hcd.c1
-rw-r--r--drivers/usb/host/whci/Kbuild1
-rw-r--r--drivers/usb/host/whci/asl.c51
-rw-r--r--drivers/usb/host/whci/debug.c189
-rw-r--r--drivers/usb/host/whci/hcd.c6
-rw-r--r--drivers/usb/host/whci/hw.c23
-rw-r--r--drivers/usb/host/whci/int.c1
-rw-r--r--drivers/usb/host/whci/pzl.c54
-rw-r--r--drivers/usb/host/whci/qset.c40
-rw-r--r--drivers/usb/host/whci/whcd.h12
-rw-r--r--drivers/usb/host/whci/whci-hc.h2
-rw-r--r--drivers/usb/host/whci/wusb.c43
-rw-r--r--drivers/usb/image/microtek.c11
-rw-r--r--drivers/usb/misc/berry_charge.c5
-rw-r--r--drivers/usb/misc/emi26.c2
-rw-r--r--drivers/usb/misc/ldusb.c2
-rw-r--r--drivers/usb/misc/usbtest.c2
-rw-r--r--drivers/usb/mon/Kconfig13
-rw-r--r--drivers/usb/mon/Makefile3
-rw-r--r--drivers/usb/mon/mon_bin.c105
-rw-r--r--drivers/usb/musb/Kconfig13
-rw-r--r--drivers/usb/musb/Makefile8
-rw-r--r--drivers/usb/musb/blackfin.c320
-rw-r--r--drivers/usb/musb/blackfin.h52
-rw-r--r--drivers/usb/musb/cppi_dma.c10
-rw-r--r--drivers/usb/musb/davinci.c13
-rw-r--r--drivers/usb/musb/musb_core.c85
-rw-r--r--drivers/usb/musb/musb_core.h73
-rw-r--r--drivers/usb/musb/musb_gadget.c8
-rw-r--r--drivers/usb/musb/musb_host.c49
-rw-r--r--drivers/usb/musb/musb_io.h26
-rw-r--r--drivers/usb/musb/musb_regs.h397
-rw-r--r--drivers/usb/musb/musbhsdma.c84
-rw-r--r--drivers/usb/musb/musbhsdma.h149
-rw-r--r--drivers/usb/musb/omap2430.c15
-rw-r--r--drivers/usb/musb/tusb6010.c7
-rw-r--r--drivers/usb/musb/tusb6010_omap.c4
-rw-r--r--drivers/usb/otg/Kconfig54
-rw-r--r--drivers/usb/otg/Makefile15
-rw-r--r--drivers/usb/otg/gpio_vbus.c335
-rw-r--r--drivers/usb/otg/isp1301_omap.c (renamed from drivers/i2c/chips/isp1301_omap.c)0
-rw-r--r--drivers/usb/otg/otg.c65
-rw-r--r--drivers/usb/otg/twl4030-usb.c721
-rw-r--r--drivers/usb/serial/Kconfig17
-rw-r--r--drivers/usb/serial/Makefile2
-rw-r--r--drivers/usb/serial/console.c13
-rw-r--r--drivers/usb/serial/cp2101.c2
-rw-r--r--drivers/usb/serial/digi_acceleport.c28
-rw-r--r--drivers/usb/serial/ftdi_sio.c13
-rw-r--r--drivers/usb/serial/ftdi_sio.h9
-rw-r--r--drivers/usb/serial/garmin_gps.c2
-rw-r--r--drivers/usb/serial/ipw.c4
-rw-r--r--drivers/usb/serial/iuu_phoenix.c38
-rw-r--r--drivers/usb/serial/kl5kusb105.c1
-rw-r--r--drivers/usb/serial/mct_u232.c2
-rw-r--r--drivers/usb/serial/mos7840.c41
-rw-r--r--drivers/usb/serial/opticon.c358
-rw-r--r--drivers/usb/serial/option.c25
-rw-r--r--drivers/usb/serial/siemens_mpi.c77
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/spcp8x5.c20
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c76
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h10
-rw-r--r--drivers/usb/serial/usb-serial.c29
-rw-r--r--drivers/usb/serial/usb_debug.c2
-rw-r--r--drivers/usb/storage/Kconfig11
-rw-r--r--drivers/usb/storage/Makefile3
-rw-r--r--drivers/usb/storage/dpcm.c86
-rw-r--r--drivers/usb/storage/dpcm.h32
-rw-r--r--drivers/usb/storage/libusual.c7
-rw-r--r--drivers/usb/storage/option_ms.c147
-rw-r--r--drivers/usb/storage/option_ms.h4
-rw-r--r--drivers/usb/storage/protocol.c24
-rw-r--r--drivers/usb/storage/protocol.h3
-rw-r--r--drivers/usb/storage/scsiglue.c43
-rw-r--r--drivers/usb/storage/sddr09.c43
-rw-r--r--drivers/usb/storage/sddr09.h5
-rw-r--r--drivers/usb/storage/transport.c219
-rw-r--r--drivers/usb/storage/transport.h2
-rw-r--r--drivers/usb/storage/unusual_devs.h390
-rw-r--r--drivers/usb/storage/usb.c106
-rw-r--r--drivers/usb/storage/usb.h5
-rw-r--r--drivers/usb/wusbcore/cbaf.c1
-rw-r--r--drivers/usb/wusbcore/crypto.c79
-rw-r--r--drivers/usb/wusbcore/dev-sysfs.c4
-rw-r--r--drivers/usb/wusbcore/devconnect.c234
-rw-r--r--drivers/usb/wusbcore/mmc.c118
-rw-r--r--drivers/usb/wusbcore/pal.c16
-rw-r--r--drivers/usb/wusbcore/reservation.c21
-rw-r--r--drivers/usb/wusbcore/rh.c109
-rw-r--r--drivers/usb/wusbcore/security.c78
-rw-r--r--drivers/usb/wusbcore/wa-nep.c16
-rw-r--r--drivers/usb/wusbcore/wa-rpipe.c68
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c180
-rw-r--r--drivers/usb/wusbcore/wusbhc.h36
-rw-r--r--drivers/uwb/Makefile3
-rw-r--r--drivers/uwb/address.c2
-rw-r--r--drivers/uwb/allocator.c385
-rw-r--r--drivers/uwb/beacon.c134
-rw-r--r--drivers/uwb/driver.c4
-rw-r--r--drivers/uwb/drp-avail.c4
-rw-r--r--drivers/uwb/drp-ie.c161
-rw-r--r--drivers/uwb/drp.c695
-rw-r--r--drivers/uwb/est.c14
-rw-r--r--drivers/uwb/hwa-rc.c53
-rw-r--r--drivers/uwb/i1480/dfu/dfu.c10
-rw-r--r--drivers/uwb/i1480/dfu/mac.c18
-rw-r--r--drivers/uwb/i1480/dfu/usb.c29
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/i1480u-wlp.h2
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/lc.c22
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/netdev.c62
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/rx.c33
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/sysfs.c3
-rw-r--r--drivers/uwb/i1480/i1480u-wlp/tx.c72
-rw-r--r--drivers/uwb/ie-rcv.c55
-rw-r--r--drivers/uwb/ie.c463
-rw-r--r--drivers/uwb/lc-dev.c23
-rw-r--r--drivers/uwb/lc-rc.c62
-rw-r--r--drivers/uwb/neh.c72
-rw-r--r--drivers/uwb/pal.c25
-rw-r--r--drivers/uwb/radio.c202
-rw-r--r--drivers/uwb/reset.c47
-rw-r--r--drivers/uwb/rsv.c578
-rw-r--r--drivers/uwb/umc-bus.c62
-rw-r--r--drivers/uwb/umc-dev.c11
-rw-r--r--drivers/uwb/uwb-debug.c151
-rw-r--r--drivers/uwb/uwb-internal.h126
-rw-r--r--drivers/uwb/uwbd.c176
-rw-r--r--drivers/uwb/whc-rc.c118
-rw-r--r--drivers/uwb/whci.c6
-rw-r--r--drivers/uwb/wlp/eda.c19
-rw-r--r--drivers/uwb/wlp/messages.c181
-rw-r--r--drivers/uwb/wlp/sysfs.c2
-rw-r--r--drivers/uwb/wlp/txrx.c37
-rw-r--r--drivers/uwb/wlp/wlp-internal.h4
-rw-r--r--drivers/uwb/wlp/wlp-lc.c80
-rw-r--r--drivers/uwb/wlp/wss-lc.c130
-rw-r--r--drivers/video/Kconfig14
-rw-r--r--drivers/video/Makefile5
-rw-r--r--drivers/video/amba-clcd.c1
-rw-r--r--drivers/video/amifb.c6
-rw-r--r--drivers/video/atafb.c112
-rw-r--r--drivers/video/aty/aty128fb.c10
-rw-r--r--drivers/video/aty/atyfb_base.c22
-rw-r--r--drivers/video/aty/mach64_ct.c11
-rw-r--r--drivers/video/aty/radeon_base.c10
-rw-r--r--drivers/video/aty/radeon_i2c.c1
-rw-r--r--drivers/video/aty/radeon_pm.c18
-rw-r--r--drivers/video/backlight/Kconfig15
-rw-r--r--drivers/video/backlight/Makefile4
-rw-r--r--drivers/video/backlight/backlight.c75
-rw-r--r--drivers/video/backlight/corgi_bl.c169
-rw-r--r--drivers/video/backlight/cr_bllcd.c18
-rw-r--r--drivers/video/backlight/da903x_bl.c (renamed from drivers/video/backlight/da903x.c)0
-rw-r--r--drivers/video/backlight/generic_bl.c147
-rw-r--r--drivers/video/backlight/hp680_bl.c20
-rw-r--r--drivers/video/backlight/lcd.c2
-rw-r--r--drivers/video/backlight/mbp_nvidia_bl.c1
-rw-r--r--drivers/video/backlight/progear_bl.c20
-rw-r--r--drivers/video/backlight/tdo24m.c94
-rw-r--r--drivers/video/backlight/tosa_lcd.c27
-rw-r--r--drivers/video/backlight/vgg2432a4.c2
-rw-r--r--drivers/video/bf54x-lq043fb.c15
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c21
-rw-r--r--drivers/video/c2p.c232
-rw-r--r--drivers/video/c2p.h11
-rw-r--r--drivers/video/c2p_core.h153
-rw-r--r--drivers/video/c2p_iplan2.c153
-rw-r--r--drivers/video/c2p_planar.c156
-rw-r--r--drivers/video/carminefb.c2
-rw-r--r--drivers/video/console/fbcon.c38
-rw-r--r--drivers/video/console/vgacon.c2
-rw-r--r--drivers/video/cyber2000fb.c3
-rw-r--r--drivers/video/fbcmap.c20
-rw-r--r--drivers/video/fbmem.c139
-rw-r--r--drivers/video/gbefb.c7
-rw-r--r--drivers/video/geode/gx1fb_core.c3
-rw-r--r--drivers/video/geode/gxfb_core.c8
-rw-r--r--drivers/video/geode/lxfb_core.c9
-rw-r--r--drivers/video/gxt4500.c4
-rw-r--r--drivers/video/i810/i810-i2c.c1
-rw-r--r--drivers/video/i810/i810_accel.c18
-rw-r--r--drivers/video/intelfb/intelfb_i2c.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c24
-rw-r--r--drivers/video/modedb.c2
-rw-r--r--drivers/video/mx3fb.c1555
-rw-r--r--drivers/video/neofb.c6
-rw-r--r--drivers/video/nvidia/nv_accel.c12
-rw-r--r--drivers/video/nvidia/nv_i2c.c1
-rw-r--r--drivers/video/omap/lcdc.c4
-rw-r--r--drivers/video/output.c2
-rw-r--r--drivers/video/pm3fb.c6
-rw-r--r--drivers/video/ps3fb.c4
-rw-r--r--drivers/video/savage/savagefb-i2c.c1
-rw-r--r--drivers/video/sm501fb.c6
-rw-r--r--drivers/video/via/viafbdev.c266
-rw-r--r--drivers/virtio/virtio_pci.c19
-rw-r--r--drivers/w1/masters/Kconfig6
-rw-r--r--drivers/w1/masters/Makefile2
-rw-r--r--drivers/w1/masters/mxc_w1.c211
-rw-r--r--drivers/w1/w1.c19
-rw-r--r--drivers/w1/w1.h1
-rw-r--r--drivers/w1/w1_int.c3
-rw-r--r--drivers/w1/w1_io.c26
-rw-r--r--drivers/w1/w1_netlink.c261
-rw-r--r--drivers/w1/w1_netlink.h16
-rw-r--r--drivers/watchdog/Kconfig39
-rw-r--r--drivers/watchdog/Makefile4
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c1
-rw-r--r--drivers/watchdog/gef_wdt.c330
-rw-r--r--drivers/watchdog/ib700wdt.c49
-rw-r--r--drivers/watchdog/pika_wdt.c301
-rw-r--r--drivers/watchdog/sch311x_wdt.c578
-rw-r--r--drivers/watchdog/wm8350_wdt.c329
-rw-r--r--drivers/xen/Kconfig24
-rw-r--r--drivers/xen/Makefile2
-rw-r--r--drivers/xen/balloon.c41
-rw-r--r--drivers/xen/events.c9
-rw-r--r--drivers/xen/xenbus/xenbus_client.c3
-rw-r--r--drivers/xen/xenbus/xenbus_probe.c55
-rw-r--r--drivers/xen/xenbus/xenbus_probe.h4
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c1
-rw-r--r--drivers/xen/xenfs/Makefile3
-rw-r--r--drivers/xen/xenfs/super.c64
-rw-r--r--drivers/xen/xenfs/xenbus.c592
-rw-r--r--drivers/xen/xenfs/xenfs.h6
-rw-r--r--drivers/zorro/.gitignore2
-rw-r--r--drivers/zorro/zorro-sysfs.c20
-rw-r--r--drivers/zorro/zorro.c23
-rw-r--r--drivers/zorro/zorro.h2
-rw-r--r--firmware/.gitignore1
-rw-r--r--firmware/Makefile26
-rw-r--r--firmware/WHENCE77
-rw-r--r--firmware/acenic/tg1.bin.ihex4573
-rw-r--r--firmware/acenic/tg2.bin.ihex4844
-rw-r--r--firmware/adaptec/starfire_rx.bin.ihex53
-rw-r--r--firmware/adaptec/starfire_tx.bin.ihex53
-rw-r--r--firmware/dsp56k/bootstrap.asm26
-rw-r--r--firmware/e100/d101m_ucode.bin.ihex38
-rw-r--r--firmware/e100/d101s_ucode.bin.ihex38
-rw-r--r--firmware/e100/d102e_ucode.bin.ihex38
-rw-r--r--firmware/mts_cdma.fw.ihex867
-rw-r--r--firmware/mts_edge.fw.ihex881
-rw-r--r--firmware/mts_gsm.fw.ihex867
-rw-r--r--firmware/tigon/tg3.bin.ihex175
-rw-r--r--firmware/tigon/tg3_tso.bin.ihex446
-rw-r--r--firmware/tigon/tg3_tso5.bin.ihex252
-rw-r--r--fs/9p/Kconfig10
-rw-r--r--fs/Kconfig1386
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--fs/Makefile8
-rw-r--r--fs/adfs/Kconfig27
-rw-r--r--fs/affs/Kconfig21
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/affs/inode.c3
-rw-r--r--fs/afs/Kconfig21
-rw-r--r--fs/afs/write.c2
-rw-r--r--fs/aio.c22
-rw-r--r--fs/anon_inodes.c7
-rw-r--r--fs/autofs/Kconfig21
-rw-r--r--fs/autofs/inode.c2
-rw-r--r--fs/autofs4/Kconfig20
-rw-r--r--fs/autofs4/autofs_i.h2
-rw-r--r--fs/autofs4/dev-ioctl.c75
-rw-r--r--fs/autofs4/expire.c4
-rw-r--r--fs/autofs4/inode.c18
-rw-r--r--fs/autofs4/waitq.c8
-rw-r--r--fs/bad_inode.c6
-rw-r--r--fs/befs/Kconfig26
-rw-r--r--fs/befs/linuxvfs.c5
-rw-r--r--fs/bfs/Kconfig19
-rw-r--r--fs/bfs/inode.c45
-rw-r--r--fs/binfmt_aout.c81
-rw-r--r--fs/binfmt_elf.c12
-rw-r--r--fs/binfmt_elf_fdpic.c35
-rw-r--r--fs/binfmt_flat.c34
-rw-r--r--fs/binfmt_misc.c5
-rw-r--r--fs/bio-integrity.c26
-rw-r--r--fs/bio.c36
-rw-r--r--fs/block_dev.c42
-rw-r--r--fs/btrfs/Kconfig18
-rw-r--r--fs/btrfs/Makefile25
-rw-r--r--fs/btrfs/acl.c351
-rw-r--r--fs/btrfs/async-thread.c419
-rw-r--r--fs/btrfs/async-thread.h101
-rw-r--r--fs/btrfs/btrfs_inode.h131
-rw-r--r--fs/btrfs/compat.h7
-rw-r--r--fs/btrfs/compression.c709
-rw-r--r--fs/btrfs/compression.h47
-rw-r--r--fs/btrfs/crc32c.h29
-rw-r--r--fs/btrfs/ctree.c3953
-rw-r--r--fs/btrfs/ctree.h2129
-rw-r--r--fs/btrfs/dir-item.c386
-rw-r--r--fs/btrfs/disk-io.c2343
-rw-r--r--fs/btrfs/disk-io.h102
-rw-r--r--fs/btrfs/export.c203
-rw-r--r--fs/btrfs/export.h19
-rw-r--r--fs/btrfs/extent-tree.c5986
-rw-r--r--fs/btrfs/extent_io.c3717
-rw-r--r--fs/btrfs/extent_io.h269
-rw-r--r--fs/btrfs/extent_map.c351
-rw-r--r--fs/btrfs/extent_map.h62
-rw-r--r--fs/btrfs/file-item.c831
-rw-r--r--fs/btrfs/file.c1288
-rw-r--r--fs/btrfs/free-space-cache.c495
-rw-r--r--fs/btrfs/hash.h27
-rw-r--r--fs/btrfs/inode-item.c206
-rw-r--r--fs/btrfs/inode-map.c144
-rw-r--r--fs/btrfs/inode.c5035
-rw-r--r--fs/btrfs/ioctl.c1132
-rw-r--r--fs/btrfs/ioctl.h69
-rw-r--r--fs/btrfs/locking.c88
-rw-r--r--fs/btrfs/locking.h27
-rw-r--r--fs/btrfs/ordered-data.c730
-rw-r--r--fs/btrfs/ordered-data.h158
-rw-r--r--fs/btrfs/orphan.c67
-rw-r--r--fs/btrfs/print-tree.c216
-rw-r--r--fs/btrfs/print-tree.h23
-rw-r--r--fs/btrfs/ref-cache.c230
-rw-r--r--fs/btrfs/ref-cache.h77
-rw-r--r--fs/btrfs/root-tree.c366
-rw-r--r--fs/btrfs/struct-funcs.c139
-rw-r--r--fs/btrfs/super.c723
-rw-r--r--fs/btrfs/sysfs.c269
-rw-r--r--fs/btrfs/transaction.c1097
-rw-r--r--fs/btrfs/transaction.h106
-rw-r--r--fs/btrfs/tree-defrag.c147
-rw-r--r--fs/btrfs/tree-log.c2898
-rw-r--r--fs/btrfs/tree-log.h41
-rw-r--r--fs/btrfs/version.h4
-rw-r--r--fs/btrfs/version.sh43
-rw-r--r--fs/btrfs/volumes.c3219
-rw-r--r--fs/btrfs/volumes.h162
-rw-r--r--fs/btrfs/xattr.c322
-rw-r--r--fs/btrfs/xattr.h39
-rw-r--r--fs/btrfs/zlib.c632
-rw-r--r--fs/buffer.c81
-rw-r--r--fs/char_dev.c2
-rw-r--r--fs/cifs/CHANGES4
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/cifsencrypt.c18
-rw-r--r--fs/cifs/cifsfs.c7
-rw-r--r--fs/cifs/cifsfs.h1
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/connect.c24
-rw-r--r--fs/cifs/dir.c56
-rw-r--r--fs/cifs/fcntl.c118
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c7
-rw-r--r--fs/cifs/md5.c38
-rw-r--r--fs/cifs/md5.h6
-rw-r--r--fs/cifs/transport.c127
-rw-r--r--fs/coda/Kconfig21
-rw-r--r--fs/coda/file.c12
-rw-r--r--fs/coda/sysctl.c5
-rw-r--r--fs/compat.c12
-rw-r--r--fs/compat_ioctl.c7
-rw-r--r--fs/configfs/Kconfig11
-rw-r--r--fs/configfs/dir.c59
-rw-r--r--fs/configfs/inode.c3
-rw-r--r--fs/cramfs/Kconfig19
-rw-r--r--fs/cramfs/inode.c2
-rw-r--r--fs/dcache.c39
-rw-r--r--fs/dcookies.c38
-rw-r--r--fs/debugfs/file.c32
-rw-r--r--fs/debugfs/inode.c3
-rw-r--r--fs/devpts/inode.c472
-rw-r--r--fs/direct-io.c13
-rw-r--r--fs/dlm/ast.c56
-rw-r--r--fs/dlm/ast.h4
-rw-r--r--fs/dlm/debug_fs.c700
-rw-r--r--fs/dlm/dir.c18
-rw-r--r--fs/dlm/dlm_internal.h6
-rw-r--r--fs/dlm/lock.c57
-rw-r--r--fs/dlm/lockspace.c2
-rw-r--r--fs/dlm/lowcomms.c8
-rw-r--r--fs/dlm/memory.c6
-rw-r--r--fs/dlm/midcomms.c2
-rw-r--r--fs/dlm/netlink.c1
-rw-r--r--fs/dlm/plock.c6
-rw-r--r--fs/dlm/recover.c10
-rw-r--r--fs/dlm/user.c4
-rw-r--r--fs/dlm/user.h2
-rw-r--r--fs/dquot.c594
-rw-r--r--fs/ecryptfs/Kconfig11
-rw-r--r--fs/ecryptfs/crypto.c514
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h105
-rw-r--r--fs/ecryptfs/file.c45
-rw-r--r--fs/ecryptfs/inode.c303
-rw-r--r--fs/ecryptfs/keystore.c651
-rw-r--r--fs/ecryptfs/main.c126
-rw-r--r--fs/ecryptfs/messaging.c4
-rw-r--r--fs/ecryptfs/miscdev.c18
-rw-r--r--fs/ecryptfs/mmap.c2
-rw-r--r--fs/efs/Kconfig14
-rw-r--r--fs/eventfd.c5
-rw-r--r--fs/eventpoll.c40
-rw-r--r--fs/exec.c80
-rw-r--r--fs/ext2/dir.c7
-rw-r--r--fs/ext2/ialloc.c14
-rw-r--r--fs/ext2/inode.c9
-rw-r--r--fs/ext2/ioctl.c3
-rw-r--r--fs/ext2/namei.c15
-rw-r--r--fs/ext2/super.c10
-rw-r--r--fs/ext3/hash.c77
-rw-r--r--fs/ext3/ialloc.c14
-rw-r--r--fs/ext3/inode.c9
-rw-r--r--fs/ext3/ioctl.c3
-rw-r--r--fs/ext3/namei.c53
-rw-r--r--fs/ext3/super.c104
-rw-r--r--fs/ext4/balloc.c297
-rw-r--r--fs/ext4/bitmap.c5
-rw-r--r--fs/ext4/dir.c10
-rw-r--r--fs/ext4/ext4.h165
-rw-r--r--fs/ext4/ext4_extents.h5
-rw-r--r--fs/ext4/ext4_i.h16
-rw-r--r--fs/ext4/ext4_jbd2.c83
-rw-r--r--fs/ext4/ext4_jbd2.h87
-rw-r--r--fs/ext4/ext4_sb.h12
-rw-r--r--fs/ext4/extents.c64
-rw-r--r--fs/ext4/file.c3
-rw-r--r--fs/ext4/hash.c77
-rw-r--r--fs/ext4/ialloc.c330
-rw-r--r--fs/ext4/inode.c325
-rw-r--r--fs/ext4/ioctl.c2
-rw-r--r--fs/ext4/mballoc.c631
-rw-r--r--fs/ext4/mballoc.h71
-rw-r--r--fs/ext4/migrate.c19
-rw-r--r--fs/ext4/namei.c134
-rw-r--r--fs/ext4/resize.c114
-rw-r--r--fs/ext4/super.c678
-rw-r--r--fs/ext4/xattr.c25
-rw-r--r--fs/fat/Kconfig97
-rw-r--r--fs/fat/dir.c1
-rw-r--r--fs/fat/inode.c2
-rw-r--r--fs/fat/namei_vfat.c2
-rw-r--r--fs/fcntl.c11
-rw-r--r--fs/file_table.c10
-rw-r--r--fs/filesystems.c25
-rw-r--r--fs/freevxfs/Kconfig16
-rw-r--r--fs/freevxfs/vxfs_inode.c4
-rw-r--r--fs/fs-writeback.c92
-rw-r--r--fs/fuse/Kconfig15
-rw-r--r--fs/fuse/control.c6
-rw-r--r--fs/fuse/dev.c121
-rw-r--r--fs/fuse/dir.c48
-rw-r--r--fs/fuse/file.c463
-rw-r--r--fs/fuse/fuse_i.h83
-rw-r--r--fs/fuse/inode.c185
-rw-r--r--fs/gfs2/Kconfig2
-rw-r--r--fs/gfs2/Makefile2
-rw-r--r--fs/gfs2/acl.c2
-rw-r--r--fs/gfs2/bmap.c77
-rw-r--r--fs/gfs2/bmap.h34
-rw-r--r--fs/gfs2/daemon.c136
-rw-r--r--fs/gfs2/daemon.h17
-rw-r--r--fs/gfs2/dir.c62
-rw-r--r--fs/gfs2/dir.h1
-rw-r--r--fs/gfs2/eattr.c40
-rw-r--r--fs/gfs2/glock.c303
-rw-r--r--fs/gfs2/glock.h2
-rw-r--r--fs/gfs2/glops.c56
-rw-r--r--fs/gfs2/incore.h55
-rw-r--r--fs/gfs2/inode.c53
-rw-r--r--fs/gfs2/inode.h13
-rw-r--r--fs/gfs2/locking/dlm/mount.c12
-rw-r--r--fs/gfs2/locking/dlm/sysfs.c16
-rw-r--r--fs/gfs2/main.c15
-rw-r--r--fs/gfs2/mount.c29
-rw-r--r--fs/gfs2/ops_address.c35
-rw-r--r--fs/gfs2/ops_dentry.c2
-rw-r--r--fs/gfs2/ops_dentry.h17
-rw-r--r--fs/gfs2/ops_export.c5
-rw-r--r--fs/gfs2/ops_file.c24
-rw-r--r--fs/gfs2/ops_fstype.c125
-rw-r--r--fs/gfs2/ops_fstype.h19
-rw-r--r--fs/gfs2/ops_inode.c75
-rw-r--r--fs/gfs2/ops_inode.h25
-rw-r--r--fs/gfs2/ops_super.c165
-rw-r--r--fs/gfs2/ops_super.h17
-rw-r--r--fs/gfs2/quota.c113
-rw-r--r--fs/gfs2/quota.h24
-rw-r--r--fs/gfs2/recovery.c48
-rw-r--r--fs/gfs2/recovery.h14
-rw-r--r--fs/gfs2/rgrp.c58
-rw-r--r--fs/gfs2/super.c246
-rw-r--r--fs/gfs2/super.h13
-rw-r--r--fs/gfs2/sys.c66
-rw-r--r--fs/gfs2/sys.h4
-rw-r--r--fs/gfs2/util.c1
-rw-r--r--fs/gfs2/util.h1
-rw-r--r--fs/hfs/Kconfig12
-rw-r--r--fs/hfsplus/Kconfig13
-rw-r--r--fs/hostfs/hostfs_kern.c2
-rw-r--r--fs/hpfs/Kconfig14
-rw-r--r--fs/hugetlbfs/inode.c13
-rw-r--r--fs/inode.c74
-rw-r--r--fs/ioctl.c92
-rw-r--r--fs/ioprio.c8
-rw-r--r--fs/isofs/Kconfig39
-rw-r--r--fs/isofs/inode.c6
-rw-r--r--fs/jbd/commit.c15
-rw-r--r--fs/jbd/transaction.c39
-rw-r--r--fs/jbd2/checkpoint.c24
-rw-r--r--fs/jbd2/commit.c67
-rw-r--r--fs/jbd2/journal.c143
-rw-r--r--fs/jbd2/transaction.c107
-rw-r--r--fs/jffs2/compr_rubin.c120
-rw-r--r--fs/jffs2/erase.c5
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/nodelist.h3
-rw-r--r--fs/jfs/Kconfig49
-rw-r--r--fs/jfs/jfs_imap.c10
-rw-r--r--fs/jfs/jfs_inode.c29
-rw-r--r--fs/jfs/namei.c24
-rw-r--r--fs/jfs/super.c10
-rw-r--r--fs/libfs.c7
-rw-r--r--fs/lockd/clntproc.c7
-rw-r--r--fs/lockd/host.c170
-rw-r--r--fs/lockd/mon.c569
-rw-r--r--fs/lockd/svc.c72
-rw-r--r--fs/lockd/svc4proc.c13
-rw-r--r--fs/lockd/svcproc.c13
-rw-r--r--fs/lockd/svcsubs.c1
-rw-r--r--fs/lockd/xdr.c5
-rw-r--r--fs/lockd/xdr4.c5
-rw-r--r--fs/locks.c2
-rw-r--r--fs/minix/Kconfig17
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/mpage.c6
-rw-r--r--fs/namei.c197
-rw-r--r--fs/namespace.c15
-rw-r--r--fs/ncpfs/Kconfig21
-rw-r--r--fs/ncpfs/getopt.c1
-rw-r--r--fs/ncpfs/ioctl.c2
-rw-r--r--fs/nfs/Kconfig86
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/nfsctl.c9
-rw-r--r--fs/nfsd/Kconfig80
-rw-r--r--fs/nfsd/auth.c7
-rw-r--r--fs/nfsd/nfs4callback.c3
-rw-r--r--fs/nfsd/nfs4proc.c5
-rw-r--r--fs/nfsd/nfs4recover.c2
-rw-r--r--fs/nfsd/nfs4state.c80
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c479
-rw-r--r--fs/nfsd/nfsfh.c36
-rw-r--r--fs/nfsd/nfsproc.c1
-rw-r--r--fs/nfsd/vfs.c9
-rw-r--r--fs/notify/Kconfig2
-rw-r--r--fs/notify/Makefile2
-rw-r--r--fs/notify/dnotify/Kconfig10
-rw-r--r--fs/notify/dnotify/Makefile1
-rw-r--r--fs/notify/dnotify/dnotify.c (renamed from fs/dnotify.c)3
-rw-r--r--fs/notify/inotify/Kconfig27
-rw-r--r--fs/notify/inotify/Makefile2
-rw-r--r--fs/notify/inotify/inotify.c (renamed from fs/inotify.c)0
-rw-r--r--fs/notify/inotify/inotify_user.c (renamed from fs/inotify_user.c)146
-rw-r--r--fs/ntfs/Kconfig78
-rw-r--r--fs/ntfs/inode.c3
-rw-r--r--fs/ocfs2/Kconfig85
-rw-r--r--fs/ocfs2/Makefile7
-rw-r--r--fs/ocfs2/acl.c479
-rw-r--r--fs/ocfs2/acl.h58
-rw-r--r--fs/ocfs2/alloc.c715
-rw-r--r--fs/ocfs2/alloc.h30
-rw-r--r--fs/ocfs2/aops.c59
-rw-r--r--fs/ocfs2/blockcheck.c477
-rw-r--r--fs/ocfs2/blockcheck.h82
-rw-r--r--fs/ocfs2/buffer_head_io.c32
-rw-r--r--fs/ocfs2/buffer_head_io.h27
-rw-r--r--fs/ocfs2/cluster/heartbeat.c2
-rw-r--r--fs/ocfs2/cluster/masklog.c1
-rw-r--r--fs/ocfs2/cluster/masklog.h1
-rw-r--r--fs/ocfs2/dcache.c42
-rw-r--r--fs/ocfs2/dcache.h9
-rw-r--r--fs/ocfs2/dir.c399
-rw-r--r--fs/ocfs2/dir.h2
-rw-r--r--fs/ocfs2/dlm/dlmast.c52
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h3
-rw-r--r--fs/ocfs2/dlm/dlmdebug.c53
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c1
-rw-r--r--fs/ocfs2/dlm/dlmfs.c2
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c42
-rw-r--r--fs/ocfs2/dlm/dlmthread.c3
-rw-r--r--fs/ocfs2/dlmglue.c176
-rw-r--r--fs/ocfs2/dlmglue.h19
-rw-r--r--fs/ocfs2/extent_map.c96
-rw-r--r--fs/ocfs2/extent_map.h24
-rw-r--r--fs/ocfs2/file.c211
-rw-r--r--fs/ocfs2/file.h3
-rw-r--r--fs/ocfs2/inode.c175
-rw-r--r--fs/ocfs2/inode.h18
-rw-r--r--fs/ocfs2/journal.c364
-rw-r--r--fs/ocfs2/journal.h128
-rw-r--r--fs/ocfs2/localalloc.c26
-rw-r--r--fs/ocfs2/namei.c318
-rw-r--r--fs/ocfs2/ocfs2.h52
-rw-r--r--fs/ocfs2/ocfs2_fs.h213
-rw-r--r--fs/ocfs2/ocfs2_jbd_compat.h82
-rw-r--r--fs/ocfs2/ocfs2_lockid.h5
-rw-r--r--fs/ocfs2/quota.h119
-rw-r--r--fs/ocfs2/quota_global.c862
-rw-r--r--fs/ocfs2/quota_local.c1253
-rw-r--r--fs/ocfs2/resize.c76
-rw-r--r--fs/ocfs2/slot_map.c4
-rw-r--r--fs/ocfs2/suballoc.c363
-rw-r--r--fs/ocfs2/suballoc.h18
-rw-r--r--fs/ocfs2/super.c331
-rw-r--r--fs/ocfs2/symlink.c2
-rw-r--r--fs/ocfs2/xattr.c2979
-rw-r--r--fs/ocfs2/xattr.h45
-rw-r--r--fs/omfs/Kconfig13
-rw-r--r--fs/omfs/inode.c1
-rw-r--r--fs/open.c89
-rw-r--r--fs/openpromfs/inode.c3
-rw-r--r--fs/partitions/check.c12
-rw-r--r--fs/pipe.c11
-rw-r--r--fs/proc/base.c235
-rw-r--r--fs/proc/generic.c8
-rw-r--r--fs/proc/inode.c3
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/meminfo.c6
-rw-r--r--fs/proc/nommu.c71
-rw-r--r--fs/proc/proc_net.c2
-rw-r--r--fs/proc/proc_sysctl.c1
-rw-r--r--fs/proc/root.c8
-rw-r--r--fs/proc/stat.c11
-rw-r--r--fs/proc/task_mmu.c8
-rw-r--r--fs/proc/task_nommu.c122
-rw-r--r--fs/proc/vmcore.c2
-rw-r--r--fs/qnx4/Kconfig25
-rw-r--r--fs/quota.c14
-rw-r--r--fs/quota_tree.c645
-rw-r--r--fs/quota_tree.h25
-rw-r--r--fs/quota_v1.c28
-rw-r--r--fs/quota_v2.c631
-rw-r--r--fs/quotaio_v1.h (renamed from include/linux/quotaio_v1.h)0
-rw-r--r--fs/quotaio_v2.h (renamed from include/linux/quotaio_v2.h)33
-rw-r--r--fs/ramfs/file-nommu.c21
-rw-r--r--fs/ramfs/inode.c1
-rw-r--r--fs/read_write.c62
-rw-r--r--fs/readdir.c9
-rw-r--r--fs/reiserfs/Kconfig85
-rw-r--r--fs/reiserfs/inode.c30
-rw-r--r--fs/reiserfs/namei.c8
-rw-r--r--fs/reiserfs/super.c20
-rw-r--r--fs/romfs/Kconfig16
-rw-r--r--fs/romfs/inode.c13
-rw-r--r--fs/select.c105
-rw-r--r--fs/seq_file.c128
-rw-r--r--fs/signalfd.c8
-rw-r--r--fs/smbfs/Kconfig55
-rw-r--r--fs/smbfs/file.c2
-rw-r--r--fs/splice.c13
-rw-r--r--fs/squashfs/Kconfig51
-rw-r--r--fs/squashfs/Makefile8
-rw-r--r--fs/squashfs/block.c274
-rw-r--r--fs/squashfs/cache.c412
-rw-r--r--fs/squashfs/dir.c235
-rw-r--r--fs/squashfs/export.c155
-rw-r--r--fs/squashfs/file.c502
-rw-r--r--fs/squashfs/fragment.c98
-rw-r--r--fs/squashfs/id.c94
-rw-r--r--fs/squashfs/inode.c346
-rw-r--r--fs/squashfs/namei.c242
-rw-r--r--fs/squashfs/squashfs.h90
-rw-r--r--fs/squashfs/squashfs_fs.h380
-rw-r--r--fs/squashfs/squashfs_fs_i.h45
-rw-r--r--fs/squashfs/squashfs_fs_sb.h76
-rw-r--r--fs/squashfs/super.c441
-rw-r--r--fs/squashfs/symlink.c118
-rw-r--r--fs/stat.c40
-rw-r--r--fs/super.c14
-rw-r--r--fs/sync.c82
-rw-r--r--fs/sysfs/Kconfig23
-rw-r--r--fs/sysfs/bin.c6
-rw-r--r--fs/sysfs/inode.c3
-rw-r--r--fs/sysv/Kconfig36
-rw-r--r--fs/sysv/inode.c6
-rw-r--r--fs/timerfd.c10
-rw-r--r--fs/ubifs/Kconfig2
-rw-r--r--fs/ubifs/budget.c243
-rw-r--r--fs/ubifs/commit.c25
-rw-r--r--fs/ubifs/compress.c18
-rw-r--r--fs/ubifs/debug.c327
-rw-r--r--fs/ubifs/debug.h127
-rw-r--r--fs/ubifs/dir.c96
-rw-r--r--fs/ubifs/file.c26
-rw-r--r--fs/ubifs/gc.c30
-rw-r--r--fs/ubifs/io.c22
-rw-r--r--fs/ubifs/ioctl.c2
-rw-r--r--fs/ubifs/journal.c8
-rw-r--r--fs/ubifs/key.h32
-rw-r--r--fs/ubifs/lprops.c26
-rw-r--r--fs/ubifs/lpt.c45
-rw-r--r--fs/ubifs/lpt_commit.c254
-rw-r--r--fs/ubifs/master.c2
-rw-r--r--fs/ubifs/orphan.c40
-rw-r--r--fs/ubifs/replay.c15
-rw-r--r--fs/ubifs/sb.c20
-rw-r--r--fs/ubifs/shrinker.c2
-rw-r--r--fs/ubifs/super.c383
-rw-r--r--fs/ubifs/tnc.c43
-rw-r--r--fs/ubifs/tnc_commit.c9
-rw-r--r--fs/ubifs/ubifs-media.h7
-rw-r--r--fs/ubifs/ubifs.h137
-rw-r--r--fs/udf/Kconfig18
-rw-r--r--fs/ufs/Kconfig43
-rw-r--r--fs/utimes.c11
-rw-r--r--fs/xattr.c55
-rw-r--r--fs/xfs/Kconfig1
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c79
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c23
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c320
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.h15
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c186
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c27
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c6
-rw-r--r--fs/xfs/quota/xfs_dquot.c38
-rw-r--r--fs/xfs/quota/xfs_dquot.h10
-rw-r--r--fs/xfs/quota/xfs_qm.c9
-rw-r--r--fs/xfs/xfs_acl.h1
-rw-r--r--fs/xfs/xfs_ag.h8
-rw-r--r--fs/xfs/xfs_alloc_btree.c2
-rw-r--r--fs/xfs/xfs_attr.c26
-rw-r--r--fs/xfs/xfs_attr_leaf.c72
-rw-r--r--fs/xfs/xfs_attr_leaf.h12
-rw-r--r--fs/xfs/xfs_bit.h10
-rw-r--r--fs/xfs/xfs_bmap.c166
-rw-r--r--fs/xfs/xfs_bmap.h2
-rw-r--r--fs/xfs/xfs_bmap_btree.c94
-rw-r--r--fs/xfs/xfs_bmap_btree.h4
-rw-r--r--fs/xfs/xfs_btree.c20
-rw-r--r--fs/xfs/xfs_da_btree.c8
-rw-r--r--fs/xfs/xfs_dfrag.c10
-rw-r--r--fs/xfs/xfs_dir2_block.c7
-rw-r--r--fs/xfs/xfs_dir2_leaf.c6
-rw-r--r--fs/xfs/xfs_dir2_sf.c15
-rw-r--r--fs/xfs/xfs_fs.h4
-rw-r--r--fs/xfs/xfs_fsops.c11
-rw-r--r--fs/xfs/xfs_fsops.h2
-rw-r--r--fs/xfs/xfs_ialloc.c6
-rw-r--r--fs/xfs/xfs_ialloc.h2
-rw-r--r--fs/xfs/xfs_ialloc_btree.h1
-rw-r--r--fs/xfs/xfs_inode.c19
-rw-r--r--fs/xfs/xfs_inode_item.h4
-rw-r--r--fs/xfs/xfs_iomap.c10
-rw-r--r--fs/xfs/xfs_itable.c6
-rw-r--r--fs/xfs/xfs_log_recover.c31
-rw-r--r--fs/xfs/xfs_mount.c26
-rw-r--r--fs/xfs/xfs_mount.h9
-rw-r--r--fs/xfs/xfs_rename.c2
-rw-r--r--fs/xfs/xfs_rtalloc.c2
-rw-r--r--fs/xfs/xfs_rw.h1
-rw-r--r--fs/xfs/xfs_sb.h2
-rw-r--r--fs/xfs/xfs_types.h4
-rw-r--r--fs/xfs/xfs_vnodeops.c20
-rw-r--r--include/acpi/acdisasm.h445
-rw-r--r--include/acpi/acexcep.h6
-rw-r--r--include/acpi/acoutput.h103
-rw-r--r--include/acpi/acpi.h31
-rw-r--r--include/acpi/acpiosxf.h13
-rw-r--r--include/acpi/acpixf.h100
-rw-r--r--include/acpi/acrestyp.h405
-rw-r--r--include/acpi/actbl.h27
-rw-r--r--include/acpi/actbl1.h2
-rw-r--r--include/acpi/actypes.h559
-rw-r--r--include/acpi/platform/acenv.h45
-rw-r--r--include/acpi/platform/aclinux.h4
-rw-r--r--include/acpi/processor.h4
-rw-r--r--include/asm-frv/atomic.h4
-rw-r--r--include/asm-frv/bitops.h13
-rw-r--r--include/asm-frv/byteorder.h7
-rw-r--r--include/asm-frv/mmu.h1
-rw-r--r--include/asm-frv/swab.h10
-rw-r--r--include/asm-generic/Kbuild.asm1
-rw-r--r--include/asm-generic/bitops/__ffs.h2
-rw-r--r--include/asm-generic/bitops/__fls.h2
-rw-r--r--include/asm-generic/bitops/fls.h2
-rw-r--r--include/asm-generic/bitops/fls64.h4
-rw-r--r--include/asm-generic/bug.h17
-rw-r--r--include/asm-generic/local.h1
-rw-r--r--include/asm-generic/memory_model.h7
-rw-r--r--include/asm-generic/pgtable.h4
-rw-r--r--include/asm-generic/rtc.h14
-rw-r--r--include/asm-generic/topology.h14
-rw-r--r--include/asm-m32r/atomic.h8
-rw-r--r--include/asm-m32r/bitops.h1
-rw-r--r--include/asm-m32r/byteorder.h7
-rw-r--r--include/asm-m32r/mmu.h1
-rw-r--r--include/asm-m32r/smp.h2
-rw-r--r--include/asm-m32r/swab.h10
-rw-r--r--include/asm-m68k/auxvec.h4
-rw-r--r--include/asm-m68k/futex.h6
-rw-r--r--include/asm-m68k/topology.h6
-rw-r--r--include/asm-mn10300/atomic.h9
-rw-r--r--include/asm-mn10300/bitops.h11
-rw-r--r--include/asm-mn10300/byteorder.h40
-rw-r--r--include/asm-mn10300/swab.h42
-rw-r--r--include/asm-xtensa/Kbuild1
-rw-r--r--include/asm-xtensa/device.h7
-rw-r--r--include/asm-xtensa/emergency-restart.h6
-rw-r--r--include/asm-xtensa/ioctl.h1
-rw-r--r--include/asm-xtensa/irq_regs.h1
-rw-r--r--include/asm-xtensa/kdebug.h1
-rw-r--r--include/asm-xtensa/mutex.h9
-rw-r--r--include/drm/drm.h2
-rw-r--r--include/drm/drmP.h9
-rw-r--r--include/drm/drm_crtc.h5
-rw-r--r--include/drm/drm_crtc_helper.h2
-rw-r--r--include/linux/8250_pci.h2
-rw-r--r--include/linux/Kbuild10
-rw-r--r--include/linux/acpi.h17
-rw-r--r--include/linux/agpgart.h1
-rw-r--r--include/linux/aio_abi.h1
-rw-r--r--include/linux/async.h25
-rw-r--r--include/linux/async_tx.h17
-rw-r--r--include/linux/ata.h15
-rw-r--r--include/linux/atalk.h1
-rw-r--r--include/linux/atm_idt77105.h2
-rw-r--r--include/linux/atmbr2684.h1
-rw-r--r--include/linux/atmel-mci.h (renamed from arch/avr32/include/asm/atmel-mci.h)12
-rw-r--r--include/linux/audit.h98
-rw-r--r--include/linux/auto_dev-ioctl.h75
-rw-r--r--include/linux/auto_fs4.h63
-rw-r--r--include/linux/auxvec.h6
-rw-r--r--include/linux/backlight.h16
-rw-r--r--include/linux/bfs_fs.h3
-rw-r--r--include/linux/binfmts.h3
-rw-r--r--include/linux/bio.h55
-rw-r--r--include/linux/bitmap.h35
-rw-r--r--include/linux/bitops.h13
-rw-r--r--include/linux/blkdev.h10
-rw-r--r--include/linux/blktrace_api.h1
-rw-r--r--include/linux/blockgroup_lock.h7
-rw-r--r--include/linux/buffer_head.h11
-rw-r--r--include/linux/byteorder.h372
-rw-r--r--include/linux/byteorder/Kbuild2
-rw-r--r--include/linux/byteorder/big_endian.h3
-rw-r--r--include/linux/byteorder/little_endian.h3
-rw-r--r--include/linux/byteorder/swab.h222
-rw-r--r--include/linux/byteorder/swabb.h135
-rw-r--r--include/linux/can/bcm.h2
-rw-r--r--include/linux/can/core.h2
-rw-r--r--include/linux/capability.h8
-rw-r--r--include/linux/capi.h2
-rw-r--r--include/linux/cdrom.h1
-rw-r--r--include/linux/cgroup.h76
-rw-r--r--include/linux/cgroupstats.h1
-rw-r--r--include/linux/clockchips.h5
-rw-r--r--include/linux/compat.h13
-rw-r--r--include/linux/compiler-gcc.h19
-rw-r--r--include/linux/compiler-gcc3.h5
-rw-r--r--include/linux/compiler-gcc4.h8
-rw-r--r--include/linux/compiler.h8
-rw-r--r--include/linux/connector.h2
-rw-r--r--include/linux/cpufreq.h5
-rw-r--r--include/linux/cpumask.h295
-rw-r--r--include/linux/cpuset.h16
-rw-r--r--include/linux/cyclades.h2
-rw-r--r--include/linux/dcache.h21
-rw-r--r--include/linux/debugfs.h9
-rw-r--r--include/linux/device-mapper.h28
-rw-r--r--include/linux/device.h32
-rw-r--r--include/linux/dio.h2
-rw-r--r--include/linux/dlm_plock.h2
-rw-r--r--include/linux/dma_remapping.h144
-rw-r--r--include/linux/dmaengine.h200
-rw-r--r--include/linux/dmar.h1
-rw-r--r--include/linux/dmi.h3
-rw-r--r--include/linux/dn.h2
-rw-r--r--include/linux/dqblk_qtree.h56
-rw-r--r--include/linux/dqblk_v1.h7
-rw-r--r--include/linux/dqblk_v2.h22
-rw-r--r--include/linux/dvb/audio.h5
-rw-r--r--include/linux/dvb/dmx.h2
-rw-r--r--include/linux/dvb/frontend.h30
-rw-r--r--include/linux/dvb/net.h3
-rw-r--r--include/linux/dvb/video.h7
-rw-r--r--include/linux/dw_dmac.h31
-rw-r--r--include/linux/edd.h2
-rw-r--r--include/linux/efs_fs_sb.h1
-rw-r--r--include/linux/elf-fdpic.h2
-rw-r--r--include/linux/elf.h3
-rw-r--r--include/linux/errqueue.h2
-rw-r--r--include/linux/ext2_fs.h24
-rw-r--r--include/linux/ext2_fs_sb.h8
-rw-r--r--include/linux/ext3_fs.h52
-rw-r--r--include/linux/ext3_fs_sb.h9
-rw-r--r--include/linux/fb.h17
-rw-r--r--include/linux/fdtable.h2
-rw-r--r--include/linux/fs.h53
-rw-r--r--include/linux/fs_struct.h6
-rw-r--r--include/linux/fuse.h79
-rw-r--r--include/linux/generic_serial.h1
-rw-r--r--include/linux/genetlink.h1
-rw-r--r--include/linux/gfp.h6
-rw-r--r--include/linux/gfs2_ondisk.h2
-rw-r--r--include/linux/gpio_keys.h1
-rw-r--r--include/linux/hid.h18
-rw-r--r--include/linux/hiddev.h2
-rw-r--r--include/linux/hidraw.h2
-rw-r--r--include/linux/hugetlb.h6
-rw-r--r--include/linux/i2c-id.h61
-rw-r--r--include/linux/i2c.h12
-rw-r--r--include/linux/i2c/dm355evm_msp.h79
-rw-r--r--include/linux/i2c/tsc2007.h17
-rw-r--r--include/linux/i2c/twl4030.h90
-rw-r--r--include/linux/icmpv6.h1
-rw-r--r--include/linux/ide.h250
-rw-r--r--include/linux/if_addr.h1
-rw-r--r--include/linux/if_addrlabel.h2
-rw-r--r--include/linux/if_fc.h1
-rw-r--r--include/linux/if_frad.h10
-rw-r--r--include/linux/if_hippi.h1
-rw-r--r--include/linux/if_link.h1
-rw-r--r--include/linux/if_ppp.h1
-rw-r--r--include/linux/if_pppol2tp.h2
-rw-r--r--include/linux/if_pppox.h2
-rw-r--r--include/linux/if_strip.h2
-rw-r--r--include/linux/if_tr.h1
-rw-r--r--include/linux/if_tunnel.h3
-rw-r--r--include/linux/if_vlan.h19
-rw-r--r--include/linux/igmp.h1
-rw-r--r--include/linux/inet_diag.h2
-rw-r--r--include/linux/init_task.h7
-rw-r--r--include/linux/input.h2
-rw-r--r--include/linux/intel-iommu.h25
-rw-r--r--include/linux/interrupt.h16
-rw-r--r--include/linux/iommu.h112
-rw-r--r--include/linux/ioport.h12
-rw-r--r--include/linux/ioprio.h2
-rw-r--r--include/linux/ip6_tunnel.h2
-rw-r--r--include/linux/ipv6.h1
-rw-r--r--include/linux/ipv6_route.h2
-rw-r--r--include/linux/ipx.h1
-rw-r--r--include/linux/irda.h2
-rw-r--r--include/linux/irq.h30
-rw-r--r--include/linux/irqnr.h30
-rw-r--r--include/linux/istallion.h2
-rw-r--r--include/linux/jbd.h17
-rw-r--r--include/linux/jbd2.h73
-rw-r--r--include/linux/journal-head.h8
-rw-r--r--include/linux/joystick.h2
-rw-r--r--include/linux/kernel.h21
-rw-r--r--include/linux/kernel_stat.h13
-rw-r--r--include/linux/klist.h4
-rw-r--r--include/linux/kprobes.h62
-rw-r--r--include/linux/kvm.h20
-rw-r--r--include/linux/kvm_host.h42
-rw-r--r--include/linux/leds-pca9532.h2
-rw-r--r--include/linux/leds.h5
-rw-r--r--include/linux/libata.h36
-rw-r--r--include/linux/libps2.h2
-rw-r--r--include/linux/lockd/lockd.h68
-rw-r--r--include/linux/lockd/sm_inter.h48
-rw-r--r--include/linux/lockd/xdr.h15
-rw-r--r--include/linux/loop.h2
-rw-r--r--include/linux/mISDNhw.h26
-rw-r--r--include/linux/mISDNif.h92
-rw-r--r--include/linux/magic.h3
-rw-r--r--include/linux/map_to_7segment.h2
-rw-r--r--include/linux/matroxfb.h2
-rw-r--r--include/linux/memcontrol.h154
-rw-r--r--include/linux/memory.h6
-rw-r--r--include/linux/memory_hotplug.h2
-rw-r--r--include/linux/memstick.h4
-rw-r--r--include/linux/mfd/da903x.h44
-rw-r--r--include/linux/mfd/pcf50633/adc.h72
-rw-r--r--include/linux/mfd/pcf50633/core.h218
-rw-r--r--include/linux/mfd/pcf50633/gpio.h52
-rw-r--r--include/linux/mfd/pcf50633/mbc.h134
-rw-r--r--include/linux/mfd/pcf50633/pmic.h67
-rw-r--r--include/linux/mfd/wm8350/comparator.h8
-rw-r--r--include/linux/mfd/wm8350/core.h52
-rw-r--r--include/linux/mfd/wm8350/pmic.h40
-rw-r--r--include/linux/mfd/wm8350/supply.h25
-rw-r--r--include/linux/migrate.h4
-rw-r--r--include/linux/minix_fs.h1
-rw-r--r--include/linux/miscdevice.h42
-rw-r--r--include/linux/mm.h24
-rw-r--r--include/linux/mm_inline.h22
-rw-r--r--include/linux/mm_types.h19
-rw-r--r--include/linux/mmc/core.h2
-rw-r--r--include/linux/mmc/host.h2
-rw-r--r--include/linux/mmzone.h24
-rw-r--r--include/linux/mod_devicetable.h7
-rw-r--r--include/linux/module.h40
-rw-r--r--include/linux/moduleloader.h3
-rw-r--r--include/linux/msdos_fs.h1
-rw-r--r--include/linux/mtd/cfi.h1
-rw-r--r--include/linux/mtd/concat.h2
-rw-r--r--include/linux/mtd/ftl.h38
-rw-r--r--include/linux/mtd/map.h1
-rw-r--r--include/linux/mtd/mtd.h77
-rw-r--r--include/linux/mtd/nand.h7
-rw-r--r--include/linux/mtd/partitions.h6
-rw-r--r--include/linux/mtd/pfow.h159
-rw-r--r--include/linux/mtd/physmap.h1
-rw-r--r--include/linux/mtd/qinfo.h91
-rw-r--r--include/linux/mtd/sharpsl.h20
-rw-r--r--include/linux/namei.h5
-rw-r--r--include/linux/ncp_fs.h2
-rw-r--r--include/linux/neighbour.h1
-rw-r--r--include/linux/netdevice.h30
-rw-r--r--include/linux/netfilter/x_tables.h2
-rw-r--r--include/linux/netfilter/xt_conntrack.h1
-rw-r--r--include/linux/nfs4.h2
-rw-r--r--include/linux/nfs_idmap.h2
-rw-r--r--include/linux/nfsd/export.h3
-rw-r--r--include/linux/nfsd/nfsd.h1
-rw-r--r--include/linux/nfsd/nfsfh.h7
-rw-r--r--include/linux/nfsd/syscall.h3
-rw-r--r--include/linux/node.h13
-rw-r--r--include/linux/nubus.h1
-rw-r--r--include/linux/nwpserial.h18
-rw-r--r--include/linux/of_i2c.h3
-rw-r--r--include/linux/oprofile.h18
-rw-r--r--include/linux/oxu210hp.h7
-rw-r--r--include/linux/page-flags.h26
-rw-r--r--include/linux/page_cgroup.h52
-rw-r--r--include/linux/pagemap.h3
-rw-r--r--include/linux/pagevec.h7
-rw-r--r--include/linux/pci-acpi.h23
-rw-r--r--include/linux/pci.h96
-rw-r--r--include/linux/pci_hotplug.h3
-rw-r--r--include/linux/pci_ids.h9
-rw-r--r--include/linux/pci_regs.h76
-rw-r--r--include/linux/percpu_counter.h22
-rw-r--r--include/linux/phantom.h2
-rw-r--r--include/linux/phonet.h2
-rw-r--r--include/linux/pid.h18
-rw-r--r--include/linux/pid_namespace.h6
-rw-r--r--include/linux/pkt_cls.h1
-rw-r--r--include/linux/pkt_sched.h2
-rw-r--r--include/linux/platform_device.h1
-rw-r--r--include/linux/pm.h88
-rw-r--r--include/linux/poll.h15
-rw-r--r--include/linux/power_supply.h1
-rw-r--r--include/linux/ppp_defs.h2
-rw-r--r--include/linux/qnx4_fs.h4
-rw-r--r--include/linux/qnxtypes.h5
-rw-r--r--include/linux/quota.h108
-rw-r--r--include/linux/quotaops.h94
-rw-r--r--include/linux/radeonfb.h2
-rw-r--r--include/linux/radix-tree.h2
-rw-r--r--include/linux/raid/md_k.h20
-rw-r--r--include/linux/raid/md_p.h4
-rw-r--r--include/linux/raid/raid0.h10
-rw-r--r--include/linux/random.h51
-rw-r--r--include/linux/rbtree.h8
-rw-r--r--include/linux/rcuclassic.h4
-rw-r--r--include/linux/rcupdate.h12
-rw-r--r--include/linux/regulator/consumer.h8
-rw-r--r--include/linux/regulator/driver.h37
-rw-r--r--include/linux/regulator/machine.h41
-rw-r--r--include/linux/res_counter.h10
-rw-r--r--include/linux/rio_drv.h1
-rw-r--r--include/linux/rmap.h5
-rw-r--r--include/linux/rtc.h8
-rw-r--r--include/linux/rtnetlink.h1
-rw-r--r--include/linux/sched.h137
-rw-r--r--include/linux/security.h137
-rw-r--r--include/linux/seq_file.h7
-rw-r--r--include/linux/serial.h3
-rw-r--r--include/linux/serial_8250.h3
-rw-r--r--include/linux/serial_core.h72
-rw-r--r--include/linux/serio.h1
-rw-r--r--include/linux/signalfd.h1
-rw-r--r--include/linux/slab_def.h10
-rw-r--r--include/linux/smp.h31
-rw-r--r--include/linux/sound.h2
-rw-r--r--include/linux/spi/mmc_spi.h15
-rw-r--r--include/linux/spi/spi.h6
-rw-r--r--include/linux/spi/spi_gpio.h60
-rw-r--r--include/linux/spi/spidev.h1
-rw-r--r--include/linux/spi/tdo24m.h13
-rw-r--r--include/linux/stop_machine.h28
-rw-r--r--include/linux/sunrpc/svc.h5
-rw-r--r--include/linux/suspend.h15
-rw-r--r--include/linux/swab.h54
-rw-r--r--include/linux/swap.h79
-rw-r--r--include/linux/swiotlb.h3
-rw-r--r--include/linux/synclink.h2
-rw-r--r--include/linux/syscalls.h176
-rw-r--r--include/linux/taskstats.h2
-rw-r--r--include/linux/tc_act/tc_gact.h1
-rw-r--r--include/linux/tc_act/tc_mirred.h1
-rw-r--r--include/linux/tc_act/tc_pedit.h1
-rw-r--r--include/linux/tc_ematch/tc_em_cmp.h1
-rw-r--r--include/linux/tc_ematch/tc_em_meta.h1
-rw-r--r--include/linux/tc_ematch/tc_em_nbyte.h1
-rw-r--r--include/linux/tc_ematch/tc_em_text.h1
-rw-r--r--include/linux/threads.h16
-rw-r--r--include/linux/tick.h4
-rw-r--r--include/linux/time.h1
-rw-r--r--include/linux/topology.h6
-rw-r--r--include/linux/tty.h27
-rw-r--r--include/linux/tty_driver.h6
-rw-r--r--include/linux/types.h13
-rw-r--r--include/linux/uio_driver.h30
-rw-r--r--include/linux/unwind.h68
-rw-r--r--include/linux/usb.h32
-rw-r--r--include/linux/usb/association.h22
-rw-r--r--include/linux/usb/cdc.h2
-rw-r--r--include/linux/usb/gadgetfs.h2
-rw-r--r--include/linux/usb/gpio_vbus.h30
-rw-r--r--include/linux/usb/musb.h5
-rw-r--r--include/linux/usb/otg.h1
-rw-r--r--include/linux/usb/usbnet.h4
-rw-r--r--include/linux/usb/wusb-wa.h1
-rw-r--r--include/linux/usb_usual.h7
-rw-r--r--include/linux/uwb.h123
-rw-r--r--include/linux/uwb/debug-cmd.h13
-rw-r--r--include/linux/uwb/debug.h82
-rw-r--r--include/linux/uwb/spec.h53
-rw-r--r--include/linux/uwb/umc.h2
-rw-r--r--include/linux/video_decoder.h2
-rw-r--r--include/linux/video_encoder.h2
-rw-r--r--include/linux/videodev.h1
-rw-r--r--include/linux/videodev2.h51
-rw-r--r--include/linux/virtio_blk.h1
-rw-r--r--include/linux/virtio_console.h1
-rw-r--r--include/linux/virtio_net.h1
-rw-r--r--include/linux/vmalloc.h4
-rw-r--r--include/linux/wait.h11
-rw-r--r--include/linux/wimax.h234
-rw-r--r--include/linux/wimax/Kbuild1
-rw-r--r--include/linux/wimax/debug.h453
-rw-r--r--include/linux/wimax/i2400m.h512
-rw-r--r--include/linux/wlp.h3
-rw-r--r--include/linux/workqueue.h12
-rw-r--r--include/linux/writeback.h16
-rw-r--r--include/media/saa7146_vv.h6
-rw-r--r--include/media/soc_camera.h6
-rw-r--r--include/media/v4l2-chip-ident.h4
-rw-r--r--include/media/v4l2-common.h6
-rw-r--r--include/media/v4l2-dev.h15
-rw-r--r--include/media/v4l2-device.h10
-rw-r--r--include/media/v4l2-int-device.h2
-rw-r--r--include/media/v4l2-ioctl.h31
-rw-r--r--include/media/v4l2-subdev.h8
-rw-r--r--include/media/videobuf-dma-sg.h2
-rw-r--r--include/mtd/inftl-user.h2
-rw-r--r--include/mtd/ubi-user.h134
-rw-r--r--include/net/inet_hashtables.h2
-rw-r--r--include/net/mac80211.h1
-rw-r--r--include/net/ndisc.h4
-rw-r--r--include/net/netdma.h11
-rw-r--r--include/net/protocol.h3
-rw-r--r--include/net/sctp/checksum.h2
-rw-r--r--include/net/wimax.h523
-rw-r--r--include/scsi/libiscsi_tcp.h1
-rw-r--r--include/scsi/scsi_transport_fc.h1
-rw-r--r--include/sound/hdsp.h2
-rw-r--r--include/sound/soc-dapm.h17
-rw-r--r--include/sound/soc.h17
-rw-r--r--include/sound/tea575x-tuner.h2
-rw-r--r--include/video/aty128.h4
-rw-r--r--include/video/mach64.h24
-rw-r--r--include/video/radeon.h18
-rw-r--r--include/video/sisfb.h2
-rw-r--r--include/video/uvesafb.h2
-rw-r--r--include/xen/xenbus.h2
-rw-r--r--init/Kconfig416
-rw-r--r--init/do_mounts.c6
-rw-r--r--init/do_mounts_md.c2
-rw-r--r--init/do_mounts_rd.c14
-rw-r--r--init/initramfs.c1
-rw-r--r--init/main.c48
-rw-r--r--ipc/ipc_sysctl.c46
-rw-r--r--ipc/mqueue.c129
-rw-r--r--ipc/msg.c12
-rw-r--r--ipc/sem.c21
-rw-r--r--ipc/shm.c47
-rw-r--r--ipc/util.c18
-rw-r--r--kernel/Makefile6
-rw-r--r--kernel/acct.c2
-rw-r--r--kernel/async.c350
-rw-r--r--kernel/audit.h5
-rw-r--r--kernel/audit_tree.c3
-rw-r--r--kernel/auditfilter.c325
-rw-r--r--kernel/auditsc.c739
-rw-r--r--kernel/capability.c8
-rw-r--r--kernel/cgroup.c324
-rw-r--r--kernel/compat.c54
-rw-r--r--kernel/cpu.c157
-rw-r--r--kernel/cpuset.c300
-rw-r--r--kernel/cred.c5
-rw-r--r--kernel/dma-coherent.c47
-rw-r--r--kernel/exec_domain.c3
-rw-r--r--kernel/exit.c38
-rw-r--r--kernel/fork.c45
-rw-r--r--kernel/futex.c89
-rw-r--r--kernel/hrtimer.c192
-rw-r--r--kernel/irq/autoprobe.c20
-rw-r--r--kernel/irq/chip.c4
-rw-r--r--kernel/irq/handle.c64
-rw-r--r--kernel/irq/manage.c27
-rw-r--r--kernel/irq/migration.c14
-rw-r--r--kernel/irq/numa_migrate.c14
-rw-r--r--kernel/irq/proc.c57
-rw-r--r--kernel/irq/spurious.c5
-rw-r--r--kernel/itimer.c7
-rw-r--r--kernel/kallsyms.c16
-rw-r--r--kernel/kexec.c7
-rw-r--r--kernel/kmod.c4
-rw-r--r--kernel/kprobes.c283
-rw-r--r--kernel/ksysfs.c4
-rw-r--r--kernel/module.c139
-rw-r--r--kernel/ns_cgroup.c2
-rw-r--r--kernel/panic.c2
-rw-r--r--kernel/pid.c8
-rw-r--r--kernel/posix-cpu-timers.c70
-rw-r--r--kernel/posix-timers.c43
-rw-r--r--kernel/power/Makefile3
-rw-r--r--kernel/power/disk.c16
-rw-r--r--kernel/power/main.c6
-rw-r--r--kernel/power/poweroff.c2
-rw-r--r--kernel/power/snapshot.c370
-rw-r--r--kernel/power/swsusp.c122
-rw-r--r--kernel/printk.c9
-rw-r--r--kernel/profile.c39
-rw-r--r--kernel/ptrace.c2
-rw-r--r--kernel/rcuclassic.c34
-rw-r--r--kernel/rcupdate.c11
-rw-r--r--kernel/rcupreempt.c30
-rw-r--r--kernel/rcutorture.c94
-rw-r--r--kernel/rcutree.c15
-rw-r--r--kernel/relay.c4
-rw-r--r--kernel/res_counter.c44
-rw-r--r--kernel/resource.c62
-rw-r--r--kernel/sched.c1175
-rw-r--r--kernel/sched_clock.c5
-rw-r--r--kernel/sched_cpupri.c39
-rw-r--r--kernel/sched_cpupri.h5
-rw-r--r--kernel/sched_debug.c21
-rw-r--r--kernel/sched_fair.c131
-rw-r--r--kernel/sched_rt.c78
-rw-r--r--kernel/sched_stats.h36
-rw-r--r--kernel/signal.c64
-rw-r--r--kernel/smp.c181
-rw-r--r--kernel/softirq.c22
-rw-r--r--kernel/softlockup.c19
-rw-r--r--kernel/stop_machine.c63
-rw-r--r--kernel/sys.c90
-rw-r--r--kernel/sys_ni.c1
-rw-r--r--kernel/sysctl.c56
-rw-r--r--kernel/taskstats.c41
-rw-r--r--kernel/test_kprobes.c210
-rw-r--r--kernel/time.c18
-rw-r--r--kernel/time/clockevents.c2
-rw-r--r--kernel/time/clocksource.c9
-rw-r--r--kernel/time/jiffies.c2
-rw-r--r--kernel/time/tick-broadcast.c113
-rw-r--r--kernel/time/tick-common.c40
-rw-r--r--kernel/time/tick-sched.c24
-rw-r--r--kernel/time/timekeeping.c7
-rw-r--r--kernel/timer.c33
-rw-r--r--kernel/trace/ftrace.c32
-rw-r--r--kernel/trace/ring_buffer.c65
-rw-r--r--kernel/trace/trace.c73
-rw-r--r--kernel/trace/trace.h2
-rw-r--r--kernel/trace/trace_boot.c2
-rw-r--r--kernel/trace/trace_functions_graph.c2
-rw-r--r--kernel/trace/trace_hw_branches.c6
-rw-r--r--kernel/trace/trace_irqsoff.c1
-rw-r--r--kernel/trace/trace_power.c2
-rw-r--r--kernel/trace/trace_sched_wakeup.c1
-rw-r--r--kernel/trace/trace_sysprof.c13
-rw-r--r--kernel/tsacct.c4
-rw-r--r--kernel/uid16.c39
-rw-r--r--kernel/up.c21
-rw-r--r--kernel/wait.c59
-rw-r--r--kernel/workqueue.c46
-rw-r--r--lib/Kconfig15
-rw-r--r--lib/Kconfig.debug43
-rw-r--r--lib/Makefile1
-rw-r--r--lib/bust_spinlocks.c2
-rw-r--r--lib/cpumask.c62
-rw-r--r--lib/dynamic_printk.c58
-rw-r--r--lib/fault-inject.c1
-rw-r--r--lib/find_last_bit.c45
-rw-r--r--lib/idr.c14
-rw-r--r--lib/klist.c43
-rw-r--r--lib/kobject_uevent.c8
-rw-r--r--lib/percpu_counter.c36
-rw-r--r--lib/prio_heap.c2
-rw-r--r--lib/proportions.c8
-rw-r--r--lib/radix-tree.c13
-rw-r--r--lib/rbtree.c12
-rw-r--r--lib/smp_processor_id.c2
-rw-r--r--lib/sort.c30
-rw-r--r--lib/swiotlb.c240
-rw-r--r--lib/vsprintf.c7
-rw-r--r--mm/Kconfig6
-rw-r--r--mm/Makefile4
-rw-r--r--mm/backing-dev.c8
-rw-r--r--mm/bootmem.c8
-rw-r--r--mm/fadvise.c18
-rw-r--r--mm/filemap.c56
-rw-r--r--mm/filemap_xip.c2
-rw-r--r--mm/fremap.c6
-rw-r--r--mm/hugetlb.c46
-rw-r--r--mm/internal.h2
-rw-r--r--mm/madvise.c2
-rw-r--r--mm/memcontrol.c1898
-rw-r--r--mm/memory.c234
-rw-r--r--mm/memory_hotplug.c20
-rw-r--r--mm/mempolicy.c24
-rw-r--r--mm/migrate.c139
-rw-r--r--mm/mincore.c4
-rw-r--r--mm/mlock.c64
-rw-r--r--mm/mmap.c117
-rw-r--r--mm/mprotect.c12
-rw-r--r--mm/mremap.c8
-rw-r--r--mm/msync.c4
-rw-r--r--mm/nommu.c1054
-rw-r--r--mm/oom_kill.c119
-rw-r--r--mm/page-writeback.c254
-rw-r--r--mm/page_alloc.c143
-rw-r--r--mm/page_cgroup.c209
-rw-r--r--mm/page_io.c6
-rw-r--r--mm/pdflush.c16
-rw-r--r--mm/rmap.c60
-rw-r--r--mm/shmem.c104
-rw-r--r--mm/slab.c2
-rw-r--r--mm/slub.c24
-rw-r--r--mm/swap.c77
-rw-r--r--mm/swap_state.c35
-rw-r--r--mm/swapfile.c607
-rw-r--r--mm/tiny-shmem.c134
-rw-r--r--mm/vmalloc.c57
-rw-r--r--mm/vmscan.c328
-rw-r--r--mm/vmstat.c4
-rw-r--r--net/8021q/vlan_core.c115
-rw-r--r--net/8021q/vlan_dev.c14
-rw-r--r--net/9p/Kconfig2
-rw-r--r--net/9p/client.c2
-rw-r--r--net/Kconfig10
-rw-r--r--net/Makefile1
-rw-r--r--net/appletalk/aarp.c5
-rw-r--r--net/bluetooth/bnep/bnep.h1
-rw-r--r--net/bluetooth/bnep/core.c12
-rw-r--r--net/bluetooth/bnep/netdev.c33
-rw-r--r--net/bridge/br_netfilter.c18
-rw-r--r--net/bridge/netfilter/ebtables.c5
-rw-r--r--net/can/af_can.c15
-rw-r--r--net/can/bcm.c201
-rw-r--r--net/can/raw.c15
-rw-r--r--net/core/dev.c346
-rw-r--r--net/core/net_namespace.c2
-rw-r--r--net/core/skbuff.c106
-rw-r--r--net/dcb/dcbnl.c14
-rw-r--r--net/dccp/Kconfig4
-rw-r--r--net/dccp/Makefile15
-rw-r--r--net/dccp/ackvec.h49
-rw-r--r--net/dccp/ccid.c254
-rw-r--r--net/dccp/ccid.h14
-rw-r--r--net/dccp/ccids/Kconfig79
-rw-r--r--net/dccp/ccids/Makefile9
-rw-r--r--net/dccp/ccids/ccid2.c22
-rw-r--r--net/dccp/ccids/ccid3.c23
-rw-r--r--net/dccp/ccids/lib/Makefile3
-rw-r--r--net/dccp/ccids/lib/loss_interval.c3
-rw-r--r--net/dccp/ccids/lib/packet_history.c9
-rw-r--r--net/dccp/ccids/lib/tfrc.c19
-rw-r--r--net/dccp/ccids/lib/tfrc.h11
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c4
-rw-r--r--net/dccp/dccp.h2
-rw-r--r--net/dccp/feat.c6
-rw-r--r--net/dccp/input.c2
-rw-r--r--net/dccp/proto.c7
-rw-r--r--net/dsa/slave.c51
-rw-r--r--net/ipv4/ipconfig.c6
-rw-r--r--net/ipv4/netfilter/iptable_filter.c7
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c6
-rw-r--r--net/ipv4/netfilter/iptable_raw.c6
-rw-r--r--net/ipv4/netfilter/iptable_security.c6
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c5
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c2
-rw-r--r--net/ipv4/tcp.c41
-rw-r--r--net/ipv4/tcp_input.c2
-rw-r--r--net/ipv4/tcp_ipv4.c2
-rw-r--r--net/ipv4/udp.c59
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/af_inet6.c114
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ip6_fib.c15
-rw-r--r--net/ipv6/ip6_input.c2
-rw-r--r--net/ipv6/ip6mr.c24
-rw-r--r--net/ipv6/ipv6_sockglue.c2
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c2
-rw-r--r--net/ipv6/route.c56
-rw-r--r--net/ipv6/sysctl_net_ipv6.c2
-rw-r--r--net/ipv6/tcp_ipv6.c47
-rw-r--r--net/irda/ircomm/ircomm_tty.c5
-rw-r--r--net/iucv/af_iucv.c28
-rw-r--r--net/iucv/iucv.c25
-rw-r--r--net/key/af_key.c1
-rw-r--r--net/mac80211/ht.c2
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/mesh_plink.c1
-rw-r--r--net/mac80211/mlme.c4
-rw-r--r--net/mac80211/rc80211_minstrel.c10
-rw-r--r--net/mac80211/sta_info.h1
-rw-r--r--net/mac80211/tx.c6
-rw-r--r--net/netfilter/nf_conntrack_core.c4
-rw-r--r--net/netfilter/nf_conntrack_netlink.c5
-rw-r--r--net/netfilter/x_tables.c8
-rw-r--r--net/netfilter/xt_time.c11
-rw-r--r--net/netlink/genetlink.c1
-rw-r--r--net/packet/af_packet.c17
-rw-r--r--net/phonet/pep-gprs.c12
-rw-r--r--net/rfkill/rfkill.c4
-rw-r--r--net/sched/cls_u32.c3
-rw-r--r--net/sched/sch_htb.c15
-rw-r--r--net/sched/sch_sfq.c2
-rw-r--r--net/sched/sch_teql.c20
-rw-r--r--net/sctp/auth.c6
-rw-r--r--net/sctp/input.c13
-rw-r--r--net/sctp/output.c7
-rw-r--r--net/sctp/outqueue.c3
-rw-r--r--net/sctp/sm_statefuns.c6
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/sctp/tsnmap.c2
-rw-r--r--net/socket.c76
-rw-r--r--net/sunrpc/Kconfig78
-rw-r--r--net/sunrpc/cache.c20
-rw-r--r--net/sunrpc/rpc_pipe.c2
-rw-r--r--net/sunrpc/stats.c6
-rw-r--r--net/sunrpc/svc.c14
-rw-r--r--net/sunrpc/svc_xprt.c58
-rw-r--r--net/sunrpc/svcauth.c14
-rw-r--r--net/sunrpc/svcauth_unix.c12
-rw-r--r--net/sunrpc/svcsock.c30
-rw-r--r--net/tipc/bcast.h2
-rw-r--r--net/unix/af_unix.c4
-rw-r--r--net/wimax/Kconfig52
-rw-r--r--net/wimax/Makefile13
-rw-r--r--net/wimax/debug-levels.h42
-rw-r--r--net/wimax/debugfs.c79
-rw-r--r--net/wimax/id-table.c144
-rw-r--r--net/wimax/op-msg.c421
-rw-r--r--net/wimax/op-reset.c143
-rw-r--r--net/wimax/op-rfkill.c532
-rw-r--r--net/wimax/stack.c612
-rw-r--r--net/wimax/wimax-internal.h91
-rw-r--r--net/wireless/reg.c142
-rw-r--r--net/wireless/wext.c4
-rw-r--r--net/xfrm/xfrm_ipcomp.c1
-rw-r--r--samples/firmware_class/firmware_sample_driver.c2
-rw-r--r--samples/kobject/kobject-example.c4
-rw-r--r--samples/kobject/kset-example.c4
-rw-r--r--samples/markers/marker-example.c4
-rw-r--r--samples/tracepoints/tracepoint-probe-sample.c4
-rw-r--r--samples/tracepoints/tracepoint-probe-sample2.c4
-rw-r--r--samples/tracepoints/tracepoint-sample.c4
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile3
-rw-r--r--scripts/Makefile.build55
-rw-r--r--scripts/Makefile.modinst3
-rw-r--r--scripts/bootgraph.pl56
-rwxr-xr-xscripts/checkpatch.pl184
-rwxr-xr-xscripts/config154
-rw-r--r--scripts/genksyms/genksyms.c21
-rw-r--r--scripts/genksyms/keywords.c_shipped189
-rw-r--r--scripts/genksyms/keywords.gperf2
-rw-r--r--scripts/headers_check.pl70
-rw-r--r--scripts/headers_install.pl3
-rw-r--r--scripts/ihex2fw.c (renamed from firmware/ihex2fw.c)0
-rw-r--r--scripts/kallsyms.c21
-rw-r--r--scripts/kconfig/expr.h82
-rw-r--r--scripts/kconfig/lex.zconf.c_shipped7
-rw-r--r--scripts/kconfig/zconf.l7
-rw-r--r--scripts/markup_oops.pl203
-rw-r--r--scripts/mksysmap7
-rw-r--r--scripts/mod/file2alias.c17
-rw-r--r--scripts/strip-symbols22
-rwxr-xr-xscripts/tags.sh19
-rw-r--r--security/Kconfig9
-rw-r--r--security/capability.c57
-rw-r--r--security/commoncap.c6
-rw-r--r--security/device_cgroup.c5
-rw-r--r--security/inode.c3
-rw-r--r--security/keys/keyctl.c23
-rw-r--r--security/security.c66
-rw-r--r--security/selinux/selinuxfs.c4
-rw-r--r--security/selinux/ss/services.c26
-rw-r--r--security/smack/smack_lsm.c6
-rw-r--r--security/smack/smackfs.c4
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c25
-rw-r--r--sound/core/oss/pcm_oss.c2
-rw-r--r--sound/core/sound.c4
-rw-r--r--sound/i2c/other/tea575x-tuner.c6
-rw-r--r--sound/oss/aedsp16.c2
-rw-r--r--sound/oss/dmasound/dmasound_atari.c5
-rw-r--r--sound/oss/dmasound/dmasound_q40.c16
-rw-r--r--sound/pci/Kconfig4
-rw-r--r--sound/pci/hda/hda_beep.c1
-rw-r--r--sound/pci/hda/hda_codec.c111
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_intel.c6
-rw-r--r--sound/pci/hda/hda_local.h3
-rw-r--r--sound/pci/hda/hda_proc.c3
-rw-r--r--sound/pci/hda/patch_analog.c5
-rw-r--r--sound/pci/hda/patch_conexant.c124
-rw-r--r--sound/pci/hda/patch_nvhdmi.c4
-rw-r--r--sound/pci/hda/patch_realtek.c26
-rw-r--r--sound/pci/hda/patch_sigmatel.c213
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/intel8x0.c2
-rw-r--r--sound/pci/oxygen/virtuoso.c20
-rw-r--r--sound/ppc/snd_ps3.c4
-rw-r--r--sound/soc/atmel/atmel-pcm.c2
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c2
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h2
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c4
-rw-r--r--sound/soc/au1x/dbdma2.c2
-rw-r--r--sound/soc/codecs/Kconfig20
-rw-r--r--sound/soc/codecs/twl4030.c417
-rw-r--r--sound/soc/codecs/twl4030.h7
-rw-r--r--sound/soc/codecs/wm8350.c2
-rw-r--r--sound/soc/codecs/wm8753.c9
-rw-r--r--sound/soc/codecs/wm8990.c3
-rw-r--r--sound/soc/davinci/davinci-evm.c19
-rw-r--r--sound/soc/davinci/davinci-pcm.c2
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c4
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c18
-rw-r--r--sound/soc/omap/Kconfig1
-rw-r--r--sound/soc/omap/omap-mcbsp.c4
-rw-r--r--sound/soc/omap/omap-pcm.c5
-rw-r--r--sound/soc/omap/omap3pandora.c13
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c4
-rw-r--r--sound/soc/soc-core.c120
-rw-r--r--sound/soc/soc-dapm.c140
-rw-r--r--sound/sparc/cs4231.c2
-rw-r--r--sound/usb/caiaq/caiaq-device.c6
-rw-r--r--sound/usb/caiaq/caiaq-device.h1
-rw-r--r--sound/usb/caiaq/caiaq-midi.c32
-rw-r--r--sound/usb/usbaudio.c8
-rw-r--r--sound/usb/usbmidi.c39
-rw-r--r--sound/usb/usbmixer.c5
-rw-r--r--sound/usb/usbquirks.h8
-rw-r--r--sound/usb/usx2y/us122l.c4
-rw-r--r--sound/usb/usx2y/usbusx2y.c6
-rw-r--r--virt/kvm/ioapic.c8
-rw-r--r--virt/kvm/ioapic.h2
-rw-r--r--virt/kvm/iommu.c (renamed from virt/kvm/vtd.c)135
-rw-r--r--virt/kvm/irq_comm.c19
-rw-r--r--virt/kvm/kvm_main.c470
-rw-r--r--virt/kvm/kvm_trace.c1
6302 files changed, 762144 insertions, 122652 deletions
diff --git a/.mailmap b/.mailmap
index 97f7b4fb6139..4e83e7b52d15 100644
--- a/.mailmap
+++ b/.mailmap
@@ -32,6 +32,7 @@ Christoph Hellwig <hch@lst.de>
Corey Minyard <minyard@acm.org>
David Brownell <david-b@pacbell.net>
David Woodhouse <dwmw2@shinybook.infradead.org>
+Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Domen Puncer <domen@coderock.org>
Douglas Gilbert <dougg@torque.net>
Ed L. Cashin <ecashin@coraid.com>
diff --git a/CREDITS b/CREDITS
index b50db1767554..2b39168c06aa 100644
--- a/CREDITS
+++ b/CREDITS
@@ -369,10 +369,10 @@ P: 1024/8462A731 4C 55 86 34 44 59 A7 99 2B 97 88 4A 88 9A 0D 97
D: sun4 port, Sparc hacker
N: Hugh Blemings
-E: hugh@misc.nu
-W: http://misc.nu/hugh/
-D: Author and maintainer of the Keyspan USB to Serial drivers
-S: Po Box 234
+E: hugh@blemings.org
+W: http://blemings.org/hugh
+D: Original author of the Keyspan USB to serial drivers, random PowerPC hacker
+S: PO Box 234
S: Belconnen ACT 2616
S: Australia
@@ -464,6 +464,11 @@ S: 1200 Goldenrod Dr.
S: Nampa, Idaho 83686
S: USA
+N: Dirk J. Brandewie
+E: dirk.j.brandewie@intel.com
+E: linux-wimax@intel.com
+D: Intel Wireless WiMAX Connection 2400 SDIO driver
+
N: Derrick J. Brashear
E: shadow@dementia.org
W: http://www.dementia.org/~shadow
@@ -1681,7 +1686,7 @@ E: ajoshi@shell.unixbox.com
D: fbdev hacking
N: Jesper Juhl
-E: jesper.juhl@gmail.com
+E: jj@chaosbits.net
D: Various fixes, cleanups and minor features all over the tree.
D: Wrote initial version of the hdaps driver (since passed on to others).
S: Lemnosvej 1, 3.tv
@@ -2119,6 +2124,11 @@ N: H.J. Lu
E: hjl@gnu.ai.mit.edu
D: GCC + libraries hacker
+N: Yanir Lubetkin
+E: yanirx.lubatkin@intel.com
+E: linux-wimax@intel.com
+D: Intel Wireless WiMAX Connection 2400 driver
+
N: Michal Ludvig
E: michal@logix.cz
E: michal.ludvig@asterisk.co.nz
@@ -2693,6 +2703,13 @@ S: RR #5, 497 Pole Line Road
S: Thunder Bay, Ontario
S: CANADA P7C 5M9
+N: Inaky Perez-Gonzalez
+E: inaky.perez-gonzalez@intel.com
+E: linux-wimax@intel.com
+E: inakypg@yahoo.com
+D: WiMAX stack
+D: Intel Wireless WiMAX Connection 2400 driver
+
N: Yuri Per
E: yuri@pts.mipt.ru
D: Some smbfs fixes
@@ -3769,14 +3786,11 @@ S: The Netherlands
N: David Woodhouse
E: dwmw2@infradead.org
-D: ARCnet stuff, Applicom board driver, SO_BINDTODEVICE,
-D: some Alpha platform porting from 2.0, Memory Technology Devices,
-D: Acquire watchdog timer, PC speaker driver maintenance,
+D: JFFS2 file system, Memory Technology Device subsystem,
D: various other stuff that annoyed me by not working.
-S: c/o Red Hat Engineering
-S: Rustat House
-S: 60 Clifton Road
-S: Cambridge. CB1 7EG
+S: c/o Intel Corporation
+S: Pipers Way
+S: Swindon. SN3 1RJ
S: England
N: Chris Wright
diff --git a/Documentation/ABI/testing/sysfs-class-regulator b/Documentation/ABI/testing/sysfs-class-regulator
index 3731f6f29bcb..873ef1fc1569 100644
--- a/Documentation/ABI/testing/sysfs-class-regulator
+++ b/Documentation/ABI/testing/sysfs-class-regulator
@@ -3,8 +3,9 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
- state. This holds the regulator output state.
+ Some regulator directories will contain a field called
+ state. This reports the regulator enable status, for
+ regulators which can report that value.
This will be one of the following strings:
@@ -18,7 +19,8 @@ Description:
'disabled' means the regulator output is OFF and is not
supplying power to the system..
- 'unknown' means software cannot determine the state.
+ 'unknown' means software cannot determine the state, or
+ the reported state is invalid.
NOTE: this field can be used in conjunction with microvolts
and microamps to determine regulator output levels.
@@ -53,9 +55,10 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
microvolts. This holds the regulator output voltage setting
- measured in microvolts (i.e. E-6 Volts).
+ measured in microvolts (i.e. E-6 Volts), for regulators
+ which can report that voltage.
NOTE: This value should not be used to determine the regulator
output voltage level as this value is the same regardless of
@@ -67,9 +70,10 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
microamps. This holds the regulator output current limit
- setting measured in microamps (i.e. E-6 Amps).
+ setting measured in microamps (i.e. E-6 Amps), for regulators
+ which can report that current.
NOTE: This value should not be used to determine the regulator
output current level as this value is the same regardless of
@@ -81,8 +85,9 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
- opmode. This holds the regulator operating mode setting.
+ Some regulator directories will contain a field called
+ opmode. This holds the current regulator operating mode,
+ for regulators which can report it.
The opmode value can be one of the following strings:
@@ -92,7 +97,7 @@ Description:
'standby'
'unknown'
- The modes are described in include/linux/regulator/regulator.h
+ The modes are described in include/linux/regulator/consumer.h
NOTE: This value should not be used to determine the regulator
output operating mode as this value is the same regardless of
@@ -104,9 +109,10 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
min_microvolts. This holds the minimum safe working regulator
- output voltage setting for this domain measured in microvolts.
+ output voltage setting for this domain measured in microvolts,
+ for regulators which support voltage constraints.
NOTE: this will return the string 'constraint not defined' if
the power domain has no min microvolts constraint defined by
@@ -118,9 +124,10 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
max_microvolts. This holds the maximum safe working regulator
- output voltage setting for this domain measured in microvolts.
+ output voltage setting for this domain measured in microvolts,
+ for regulators which support voltage constraints.
NOTE: this will return the string 'constraint not defined' if
the power domain has no max microvolts constraint defined by
@@ -132,10 +139,10 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
min_microamps. This holds the minimum safe working regulator
output current limit setting for this domain measured in
- microamps.
+ microamps, for regulators which support current constraints.
NOTE: this will return the string 'constraint not defined' if
the power domain has no min microamps constraint defined by
@@ -147,10 +154,10 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
max_microamps. This holds the maximum safe working regulator
output current limit setting for this domain measured in
- microamps.
+ microamps, for regulators which support current constraints.
NOTE: this will return the string 'constraint not defined' if
the power domain has no max microamps constraint defined by
@@ -185,7 +192,7 @@ Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
requested_microamps. This holds the total requested load
current in microamps for this regulator from all its consumer
devices.
@@ -204,125 +211,102 @@ Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_mem_microvolts. This holds the regulator output
voltage setting for this domain measured in microvolts when
- the system is suspended to memory.
-
- NOTE: this will return the string 'not defined' if
- the power domain has no suspend to memory voltage defined by
- platform code.
+ the system is suspended to memory, for voltage regulators
+ implementing suspend voltage configuration constraints.
What: /sys/class/regulator/.../suspend_disk_microvolts
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_disk_microvolts. This holds the regulator output
voltage setting for this domain measured in microvolts when
- the system is suspended to disk.
-
- NOTE: this will return the string 'not defined' if
- the power domain has no suspend to disk voltage defined by
- platform code.
+ the system is suspended to disk, for voltage regulators
+ implementing suspend voltage configuration constraints.
What: /sys/class/regulator/.../suspend_standby_microvolts
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_standby_microvolts. This holds the regulator output
voltage setting for this domain measured in microvolts when
- the system is suspended to standby.
-
- NOTE: this will return the string 'not defined' if
- the power domain has no suspend to standby voltage defined by
- platform code.
+ the system is suspended to standby, for voltage regulators
+ implementing suspend voltage configuration constraints.
What: /sys/class/regulator/.../suspend_mem_mode
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_mem_mode. This holds the regulator operating mode
setting for this domain when the system is suspended to
- memory.
-
- NOTE: this will return the string 'not defined' if
- the power domain has no suspend to memory mode defined by
- platform code.
+ memory, for regulators implementing suspend mode
+ configuration constraints.
What: /sys/class/regulator/.../suspend_disk_mode
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_disk_mode. This holds the regulator operating mode
- setting for this domain when the system is suspended to disk.
-
- NOTE: this will return the string 'not defined' if
- the power domain has no suspend to disk mode defined by
- platform code.
+ setting for this domain when the system is suspended to disk,
+ for regulators implementing suspend mode configuration
+ constraints.
What: /sys/class/regulator/.../suspend_standby_mode
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_standby_mode. This holds the regulator operating mode
setting for this domain when the system is suspended to
- standby.
-
- NOTE: this will return the string 'not defined' if
- the power domain has no suspend to standby mode defined by
- platform code.
+ standby, for regulators implementing suspend mode
+ configuration constraints.
What: /sys/class/regulator/.../suspend_mem_state
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_mem_state. This holds the regulator operating state
- when suspended to memory.
-
- This will be one of the following strings:
+ when suspended to memory, for regulators implementing suspend
+ configuration constraints.
- 'enabled'
- 'disabled'
- 'not defined'
+ This will be one of the same strings reported by
+ the "state" attribute.
What: /sys/class/regulator/.../suspend_disk_state
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_disk_state. This holds the regulator operating state
- when suspended to disk.
-
- This will be one of the following strings:
+ when suspended to disk, for regulators implementing
+ suspend configuration constraints.
- 'enabled'
- 'disabled'
- 'not defined'
+ This will be one of the same strings reported by
+ the "state" attribute.
What: /sys/class/regulator/.../suspend_standby_state
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lrg@slimlogic.co.uk>
Description:
- Each regulator directory will contain a field called
+ Some regulator directories will contain a field called
suspend_standby_state. This holds the regulator operating
- state when suspended to standby.
-
- This will be one of the following strings:
+ state when suspended to standby, for regulators implementing
+ suspend configuration constraints.
- 'enabled'
- 'disabled'
- 'not defined'
+ This will be one of the same strings reported by
+ the "state" attribute.
diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc b/Documentation/ABI/testing/sysfs-class-uwb_rc
index a0d18dbeb7a9..6a5fd072849d 100644
--- a/Documentation/ABI/testing/sysfs-class-uwb_rc
+++ b/Documentation/ABI/testing/sysfs-class-uwb_rc
@@ -32,14 +32,16 @@ Contact: linux-usb@vger.kernel.org
Description:
Write:
- <channel> [<bpst offset>]
+ <channel>
- to start beaconing on a specific channel, or stop
- beaconing if <channel> is -1. Valid channels depends
- on the radio controller's supported band groups.
+ to force a specific channel to be used when beaconing,
+ or, if <channel> is -1, to prohibit beaconing. If
+ <channel> is 0, then the default channel selection
+ algorithm will be used. Valid channels depends on the
+ radio controller's supported band groups.
- <bpst offset> may be used to try and join a specific
- beacon group if more than one was found during a scan.
+ Reading returns the currently active channel, or -1 if
+ the radio controller is not beaconing.
What: /sys/class/uwb_rc/uwbN/scan
Date: July 2008
diff --git a/Documentation/ABI/testing/sysfs-devices-memory b/Documentation/ABI/testing/sysfs-devices-memory
index 7a16fe1e2270..9fe91c02ee40 100644
--- a/Documentation/ABI/testing/sysfs-devices-memory
+++ b/Documentation/ABI/testing/sysfs-devices-memory
@@ -6,7 +6,6 @@ Description:
internal state of the kernel memory blocks. Files could be
added or removed dynamically to represent hot-add/remove
operations.
-
Users: hotplug memory add/remove tools
https://w3.opensource.ibm.com/projects/powerpc-utils/
@@ -19,6 +18,56 @@ Description:
This is useful for a user-level agent to determine
identify removable sections of the memory before attempting
potentially expensive hot-remove memory operation
+Users: hotplug memory remove tools
+ https://w3.opensource.ibm.com/projects/powerpc-utils/
+
+What: /sys/devices/system/memory/memoryX/phys_device
+Date: September 2008
+Contact: Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+ The file /sys/devices/system/memory/memoryX/phys_device
+ is read-only and is designed to show the name of physical
+ memory device. Implementation is currently incomplete.
+What: /sys/devices/system/memory/memoryX/phys_index
+Date: September 2008
+Contact: Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+ The file /sys/devices/system/memory/memoryX/phys_index
+ is read-only and contains the section ID in hexadecimal
+ which is equivalent to decimal X contained in the
+ memory section directory name.
+
+What: /sys/devices/system/memory/memoryX/state
+Date: September 2008
+Contact: Badari Pulavarty <pbadari@us.ibm.com>
+Description:
+ The file /sys/devices/system/memory/memoryX/state
+ is read-write. When read, it's contents show the
+ online/offline state of the memory section. When written,
+ root can toggle the the online/offline state of a removable
+ memory section (see removable file description above)
+ using the following commands.
+ # echo online > /sys/devices/system/memory/memoryX/state
+ # echo offline > /sys/devices/system/memory/memoryX/state
+
+ For example, if /sys/devices/system/memory/memory22/removable
+ contains a value of 1 and
+ /sys/devices/system/memory/memory22/state contains the
+ string "online" the following command can be executed by
+ by root to offline that section.
+ # echo offline > /sys/devices/system/memory/memory22/state
Users: hotplug memory remove tools
https://w3.opensource.ibm.com/projects/powerpc-utils/
+
+What: /sys/devices/system/node/nodeX/memoryY
+Date: September 2008
+Contact: Gary Hade <garyhade@us.ibm.com>
+Description:
+ When CONFIG_NUMA is enabled
+ /sys/devices/system/node/nodeX/memoryY is a symbolic link that
+ points to the corresponding /sys/devices/system/memory/memoryY
+ memory section directory. For example, the following symbolic
+ link is created for memory section 9 on node0.
+ /sys/devices/system/node/node0/memory9 -> ../../memory/memory9
+
diff --git a/Documentation/Changes b/Documentation/Changes
index cb2b141b1c3e..b95082be4d5e 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -33,10 +33,12 @@ o Gnu make 3.79.1 # make --version
o binutils 2.12 # ld -v
o util-linux 2.10o # fdformat --version
o module-init-tools 0.9.10 # depmod -V
-o e2fsprogs 1.29 # tune2fs
+o e2fsprogs 1.41.4 # e2fsck -V
o jfsutils 1.1.3 # fsck.jfs -V
o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs
o xfsprogs 2.6.0 # xfs_db -V
+o squashfs-tools 4.0 # mksquashfs -version
+o btrfs-progs 0.18 # btrfsck
o pcmciautils 004 # pccardctl -V
o quota-tools 3.09 # quota -V
o PPP 2.4.0 # pppd --version
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 1875e502f872..72968cd5eaf3 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -483,17 +483,25 @@ values. To do the latter, you can stick the following in your .emacs file:
(* (max steps 1)
c-basic-offset)))
+(add-hook 'c-mode-common-hook
+ (lambda ()
+ ;; Add kernel style
+ (c-add-style
+ "linux-tabs-only"
+ '("linux" (c-offsets-alist
+ (arglist-cont-nonempty
+ c-lineup-gcc-asm-reg
+ c-lineup-arglist-tabs-only))))))
+
(add-hook 'c-mode-hook
(lambda ()
(let ((filename (buffer-file-name)))
;; Enable kernel mode for the appropriate files
(when (and filename
- (string-match "~/src/linux-trees" filename))
+ (string-match (expand-file-name "~/src/linux-trees")
+ filename))
(setq indent-tabs-mode t)
- (c-set-style "linux")
- (c-set-offset 'arglist-cont-nonempty
- '(c-lineup-gcc-asm-reg
- c-lineup-arglist-tabs-only))))))
+ (c-set-style "linux-tabs-only")))))
This will make emacs go better with the kernel coding style for C
files below ~/src/linux-trees.
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index b462bb149543..2a3fcc55e981 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -5,7 +5,7 @@
This document describes the DMA API. For a more gentle introduction
phrased in terms of the pci_ equivalents (and actual examples) see
-DMA-mapping.txt
+Documentation/PCI/PCI-DMA-mapping.txt.
This API is split into two pieces. Part I describes the API and the
corresponding pci_ API. Part II describes the extensions to the API
@@ -170,16 +170,15 @@ Returns: 0 if successful and a negative error if not.
u64
dma_get_required_mask(struct device *dev)
-After setting the mask with dma_set_mask(), this API returns the
-actual mask (within that already set) that the platform actually
-requires to operate efficiently. Usually this means the returned mask
+This API returns the mask that the platform requires to
+operate efficiently. Usually this means the returned mask
is the minimum required to cover all of memory. Examining the
required mask gives drivers with variable descriptor sizes the
opportunity to use smaller descriptors as necessary.
Requesting the required mask does not alter the current mask. If you
-wish to take advantage of it, you should issue another dma_set_mask()
-call to lower the mask again.
+wish to take advantage of it, you should issue a dma_set_mask()
+call to set the mask to the value returned.
Part Id - Streaming DMA mappings
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index c74fec8c2351..b2a4d6d244d9 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -26,7 +26,7 @@ mapped only for the time they are actually used and unmapped after the DMA
transfer.
The following API will work of course even on platforms where no such
-hardware exists, see e.g. include/asm-i386/pci.h for how it is implemented on
+hardware exists, see e.g. arch/x86/include/asm/pci.h for how it is implemented on
top of the virt_to_bus interface.
First of all, you should make sure
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 0a08126d3094..dc3154e49279 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -12,7 +12,7 @@ DOCBOOKS := z8530book.xml mcabook.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
- mac80211.xml debugobjects.xml sh.xml
+ mac80211.xml debugobjects.xml sh.xml regulator.xml
###
# The build process is as follows (targets):
diff --git a/Documentation/DocBook/networking.tmpl b/Documentation/DocBook/networking.tmpl
index 627707a3cb9d..59ad69a9d777 100644
--- a/Documentation/DocBook/networking.tmpl
+++ b/Documentation/DocBook/networking.tmpl
@@ -74,6 +74,14 @@
!Enet/sunrpc/rpcb_clnt.c
!Enet/sunrpc/clnt.c
</sect1>
+ <sect1><title>WiMAX</title>
+!Enet/wimax/op-msg.c
+!Enet/wimax/op-reset.c
+!Enet/wimax/op-rfkill.c
+!Enet/wimax/stack.c
+!Iinclude/net/wimax.h
+!Iinclude/linux/wimax.h
+ </sect1>
</chapter>
<chapter id="netdev">
diff --git a/Documentation/DocBook/regulator.tmpl b/Documentation/DocBook/regulator.tmpl
new file mode 100644
index 000000000000..53f4f8d3b810
--- /dev/null
+++ b/Documentation/DocBook/regulator.tmpl
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="regulator-api">
+ <bookinfo>
+ <title>Voltage and current regulator API</title>
+
+ <authorgroup>
+ <author>
+ <firstname>Liam</firstname>
+ <surname>Girdwood</surname>
+ <affiliation>
+ <address>
+ <email>lrg@slimlogic.co.uk</email>
+ </address>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>Mark</firstname>
+ <surname>Brown</surname>
+ <affiliation>
+ <orgname>Wolfson Microelectronics</orgname>
+ <address>
+ <email>broonie@opensource.wolfsonmicro.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <copyright>
+ <year>2007-2008</year>
+ <holder>Wolfson Microelectronics</holder>
+ </copyright>
+ <copyright>
+ <year>2008</year>
+ <holder>Liam Girdwood</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>
+ This documentation 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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
+ </para>
+
+ <para>
+ For more details see the file COPYING in the source
+ distribution of Linux.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+ <chapter id="intro">
+ <title>Introduction</title>
+ <para>
+ This framework is designed to provide a standard kernel
+ interface to control voltage and current regulators.
+ </para>
+ <para>
+ The intention is to allow systems to dynamically control
+ regulator power output in order to save power and prolong
+ battery life. This applies to both voltage regulators (where
+ voltage output is controllable) and current sinks (where current
+ limit is controllable).
+ </para>
+ <para>
+ Note that additional (and currently more complete) documentation
+ is available in the Linux kernel source under
+ <filename>Documentation/power/regulator</filename>.
+ </para>
+
+ <sect1 id="glossary">
+ <title>Glossary</title>
+ <para>
+ The regulator API uses a number of terms which may not be
+ familiar:
+ </para>
+ <glossary>
+
+ <glossentry>
+ <glossterm>Regulator</glossterm>
+ <glossdef>
+ <para>
+ Electronic device that supplies power to other devices. Most
+ regulators can enable and disable their output and some can also
+ control their output voltage or current.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>Consumer</glossterm>
+ <glossdef>
+ <para>
+ Electronic device which consumes power provided by a regulator.
+ These may either be static, requiring only a fixed supply, or
+ dynamic, requiring active management of the regulator at
+ runtime.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>Power Domain</glossterm>
+ <glossdef>
+ <para>
+ The electronic circuit supplied by a given regulator, including
+ the regulator and all consumer devices. The configuration of
+ the regulator is shared between all the components in the
+ circuit.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>Power Management Integrated Circuit</glossterm>
+ <acronym>PMIC</acronym>
+ <glossdef>
+ <para>
+ An IC which contains numerous regulators and often also other
+ subsystems. In an embedded system the primary PMIC is often
+ equivalent to a combination of the PSU and southbridge in a
+ desktop system.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossary>
+ </sect1>
+ </chapter>
+
+ <chapter id="consumer">
+ <title>Consumer driver interface</title>
+ <para>
+ This offers a similar API to the kernel clock framework.
+ Consumer drivers use <link
+ linkend='API-regulator-get'>get</link> and <link
+ linkend='API-regulator-put'>put</link> operations to acquire and
+ release regulators. Functions are
+ provided to <link linkend='API-regulator-enable'>enable</link>
+ and <link linkend='API-regulator-disable'>disable</link> the
+ reguator and to get and set the runtime parameters of the
+ regulator.
+ </para>
+ <para>
+ When requesting regulators consumers use symbolic names for their
+ supplies, such as "Vcc", which are mapped into actual regulator
+ devices by the machine interface.
+ </para>
+ <para>
+ A stub version of this API is provided when the regulator
+ framework is not in use in order to minimise the need to use
+ ifdefs.
+ </para>
+
+ <sect1 id="consumer-enable">
+ <title>Enabling and disabling</title>
+ <para>
+ The regulator API provides reference counted enabling and
+ disabling of regulators. Consumer devices use the <function><link
+ linkend='API-regulator-enable'>regulator_enable</link></function>
+ and <function><link
+ linkend='API-regulator-disable'>regulator_disable</link>
+ </function> functions to enable and disable regulators. Calls
+ to the two functions must be balanced.
+ </para>
+ <para>
+ Note that since multiple consumers may be using a regulator and
+ machine constraints may not allow the regulator to be disabled
+ there is no guarantee that calling
+ <function>regulator_disable</function> will actually cause the
+ supply provided by the regulator to be disabled. Consumer
+ drivers should assume that the regulator may be enabled at all
+ times.
+ </para>
+ </sect1>
+
+ <sect1 id="consumer-config">
+ <title>Configuration</title>
+ <para>
+ Some consumer devices may need to be able to dynamically
+ configure their supplies. For example, MMC drivers may need to
+ select the correct operating voltage for their cards. This may
+ be done while the regulator is enabled or disabled.
+ </para>
+ <para>
+ The <function><link
+ linkend='API-regulator-set-voltage'>regulator_set_voltage</link>
+ </function> and <function><link
+ linkend='API-regulator-set-current-limit'
+ >regulator_set_current_limit</link>
+ </function> functions provide the primary interface for this.
+ Both take ranges of voltages and currents, supporting drivers
+ that do not require a specific value (eg, CPU frequency scaling
+ normally permits the CPU to use a wider range of supply
+ voltages at lower frequencies but does not require that the
+ supply voltage be lowered). Where an exact value is required
+ both minimum and maximum values should be identical.
+ </para>
+ </sect1>
+
+ <sect1 id="consumer-callback">
+ <title>Callbacks</title>
+ <para>
+ Callbacks may also be <link
+ linkend='API-regulator-register-notifier'>registered</link>
+ for events such as regulation failures.
+ </para>
+ </sect1>
+ </chapter>
+
+ <chapter id="driver">
+ <title>Regulator driver interface</title>
+ <para>
+ Drivers for regulator chips <link
+ linkend='API-regulator-register'>register</link> the regulators
+ with the regulator core, providing operations structures to the
+ core. A <link
+ linkend='API-regulator-notifier-call-chain'>notifier</link> interface
+ allows error conditions to be reported to the core.
+ </para>
+ <para>
+ Registration should be triggered by explicit setup done by the
+ platform, supplying a <link
+ linkend='API-struct-regulator-init-data'>struct
+ regulator_init_data</link> for the regulator containing
+ <link linkend='machine-constraint'>constraint</link> and
+ <link linkend='machine-supply'>supply</link> information.
+ </para>
+ </chapter>
+
+ <chapter id="machine">
+ <title>Machine interface</title>
+ <para>
+ This interface provides a way to define how regulators are
+ connected to consumers on a given system and what the valid
+ operating parameters are for the system.
+ </para>
+
+ <sect1 id="machine-supply">
+ <title>Supplies</title>
+ <para>
+ Regulator supplies are specified using <link
+ linkend='API-struct-regulator-consumer-supply'>struct
+ regulator_consumer_supply</link>. This is done at
+ <link linkend='driver'>driver registration
+ time</link> as part of the machine constraints.
+ </para>
+ </sect1>
+
+ <sect1 id="machine-constraint">
+ <title>Constraints</title>
+ <para>
+ As well as definining the connections the machine interface
+ also provides constraints definining the operations that
+ clients are allowed to perform and the parameters that may be
+ set. This is required since generally regulator devices will
+ offer more flexibility than it is safe to use on a given
+ system, for example supporting higher supply voltages than the
+ consumers are rated for.
+ </para>
+ <para>
+ This is done at <link linkend='driver'>driver
+ registration time</link> by providing a <link
+ linkend='API-struct-regulation-constraints'>struct
+ regulation_constraints</link>.
+ </para>
+ <para>
+ The constraints may also specify an initial configuration for the
+ regulator in the constraints, which is particularly useful for
+ use with static consumers.
+ </para>
+ </sect1>
+ </chapter>
+
+ <chapter id="api">
+ <title>API reference</title>
+ <para>
+ Due to limitations of the kernel documentation framework and the
+ existing layout of the source code the entire regulator API is
+ documented here.
+ </para>
+!Iinclude/linux/regulator/consumer.h
+!Iinclude/linux/regulator/machine.h
+!Iinclude/linux/regulator/driver.h
+!Edrivers/regulator/core.c
+ </chapter>
+</book>
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl
index df87d1b93605..52e1b79ce0e6 100644
--- a/Documentation/DocBook/uio-howto.tmpl
+++ b/Documentation/DocBook/uio-howto.tmpl
@@ -42,6 +42,18 @@ GPL version 2.
<revhistory>
<revision>
+ <revnumber>0.7</revnumber>
+ <date>2008-12-23</date>
+ <authorinitials>hjk</authorinitials>
+ <revremark>Added generic platform drivers and offset attribute.</revremark>
+ </revision>
+ <revision>
+ <revnumber>0.6</revnumber>
+ <date>2008-12-05</date>
+ <authorinitials>hjk</authorinitials>
+ <revremark>Added description of portio sysfs attributes.</revremark>
+ </revision>
+ <revision>
<revnumber>0.5</revnumber>
<date>2008-05-22</date>
<authorinitials>hjk</authorinitials>
@@ -306,6 +318,16 @@ interested in translating it, please email me
pointed to by addr.
</para>
</listitem>
+<listitem>
+ <para>
+ <filename>offset</filename>: The offset, in bytes, that has to be
+ added to the pointer returned by <function>mmap()</function> to get
+ to the actual device memory. This is important if the device's memory
+ is not page aligned. Remember that pointers returned by
+ <function>mmap()</function> are always page aligned, so it is good
+ style to always add this offset.
+ </para>
+</listitem>
</itemizedlist>
<para>
@@ -318,6 +340,54 @@ interested in translating it, please email me
offset = N * getpagesize();
</programlisting>
+<para>
+ Sometimes there is hardware with memory-like regions that can not be
+ mapped with the technique described here, but there are still ways to
+ access them from userspace. The most common example are x86 ioports.
+ On x86 systems, userspace can access these ioports using
+ <function>ioperm()</function>, <function>iopl()</function>,
+ <function>inb()</function>, <function>outb()</function>, and similar
+ functions.
+</para>
+<para>
+ Since these ioport regions can not be mapped, they will not appear under
+ <filename>/sys/class/uio/uioX/maps/</filename> like the normal memory
+ described above. Without information about the port regions a hardware
+ has to offer, it becomes difficult for the userspace part of the
+ driver to find out which ports belong to which UIO device.
+</para>
+<para>
+ To address this situation, the new directory
+ <filename>/sys/class/uio/uioX/portio/</filename> was added. It only
+ exists if the driver wants to pass information about one or more port
+ regions to userspace. If that is the case, subdirectories named
+ <filename>port0</filename>, <filename>port1</filename>, and so on,
+ will appear underneath
+ <filename>/sys/class/uio/uioX/portio/</filename>.
+</para>
+<para>
+ Each <filename>portX/</filename> directory contains three read-only
+ files that show start, size, and type of the port region:
+</para>
+<itemizedlist>
+<listitem>
+ <para>
+ <filename>start</filename>: The first port of this region.
+ </para>
+</listitem>
+<listitem>
+ <para>
+ <filename>size</filename>: The number of ports in this region.
+ </para>
+</listitem>
+<listitem>
+ <para>
+ <filename>porttype</filename>: A string describing the type of port.
+ </para>
+</listitem>
+</itemizedlist>
+
+
</sect1>
</chapter>
@@ -339,12 +409,12 @@ offset = N * getpagesize();
<itemizedlist>
<listitem><para>
-<varname>char *name</varname>: Required. The name of your driver as
+<varname>const char *name</varname>: Required. The name of your driver as
it will appear in sysfs. I recommend using the name of your module for this.
</para></listitem>
<listitem><para>
-<varname>char *version</varname>: Required. This string appears in
+<varname>const char *version</varname>: Required. This string appears in
<filename>/sys/class/uio/uioX/version</filename>.
</para></listitem>
@@ -356,6 +426,13 @@ See the description below for details.
</para></listitem>
<listitem><para>
+<varname>struct uio_port port[ MAX_UIO_PORTS_REGIONS ]</varname>: Required
+if you want to pass information about ioports to userspace. For each port
+region you need to fill one of the <varname>uio_port</varname> structures.
+See the description below for details.
+</para></listitem>
+
+<listitem><para>
<varname>long irq</varname>: Required. If your hardware generates an
interrupt, it's your modules task to determine the irq number during
initialization. If you don't have a hardware generated interrupt but
@@ -448,6 +525,42 @@ Please do not touch the <varname>kobj</varname> element of
<varname>struct uio_mem</varname>! It is used by the UIO framework
to set up sysfs files for this mapping. Simply leave it alone.
</para>
+
+<para>
+Sometimes, your device can have one or more port regions which can not be
+mapped to userspace. But if there are other possibilities for userspace to
+access these ports, it makes sense to make information about the ports
+available in sysfs. For each region, you have to set up a
+<varname>struct uio_port</varname> in the <varname>port[]</varname> array.
+Here's a description of the fields of <varname>struct uio_port</varname>:
+</para>
+
+<itemizedlist>
+<listitem><para>
+<varname>char *porttype</varname>: Required. Set this to one of the predefined
+constants. Use <varname>UIO_PORT_X86</varname> for the ioports found in x86
+architectures.
+</para></listitem>
+
+<listitem><para>
+<varname>unsigned long start</varname>: Required if the port region is used.
+Fill in the number of the first port of this region.
+</para></listitem>
+
+<listitem><para>
+<varname>unsigned long size</varname>: Fill in the number of ports in this
+region. If <varname>size</varname> is zero, the region is considered unused.
+Note that you <emphasis>must</emphasis> initialize <varname>size</varname>
+with zero for all unused regions.
+</para></listitem>
+</itemizedlist>
+
+<para>
+Please do not touch the <varname>portio</varname> element of
+<varname>struct uio_port</varname>! It is used internally by the UIO
+framework to set up sysfs files for this region. Simply leave it alone.
+</para>
+
</sect1>
<sect1 id="adding_irq_handler">
@@ -497,6 +610,78 @@ to set up sysfs files for this mapping. Simply leave it alone.
</para>
</sect1>
+<sect1 id="using_uio_pdrv">
+<title>Using uio_pdrv for platform devices</title>
+ <para>
+ In many cases, UIO drivers for platform devices can be handled in a
+ generic way. In the same place where you define your
+ <varname>struct platform_device</varname>, you simply also implement
+ your interrupt handler and fill your
+ <varname>struct uio_info</varname>. A pointer to this
+ <varname>struct uio_info</varname> is then used as
+ <varname>platform_data</varname> for your platform device.
+ </para>
+ <para>
+ You also need to set up an array of <varname>struct resource</varname>
+ containing addresses and sizes of your memory mappings. This
+ information is passed to the driver using the
+ <varname>.resource</varname> and <varname>.num_resources</varname>
+ elements of <varname>struct platform_device</varname>.
+ </para>
+ <para>
+ You now have to set the <varname>.name</varname> element of
+ <varname>struct platform_device</varname> to
+ <varname>"uio_pdrv"</varname> to use the generic UIO platform device
+ driver. This driver will fill the <varname>mem[]</varname> array
+ according to the resources given, and register the device.
+ </para>
+ <para>
+ The advantage of this approach is that you only have to edit a file
+ you need to edit anyway. You do not have to create an extra driver.
+ </para>
+</sect1>
+
+<sect1 id="using_uio_pdrv_genirq">
+<title>Using uio_pdrv_genirq for platform devices</title>
+ <para>
+ Especially in embedded devices, you frequently find chips where the
+ irq pin is tied to its own dedicated interrupt line. In such cases,
+ where you can be really sure the interrupt is not shared, we can take
+ the concept of <varname>uio_pdrv</varname> one step further and use a
+ generic interrupt handler. That's what
+ <varname>uio_pdrv_genirq</varname> does.
+ </para>
+ <para>
+ The setup for this driver is the same as described above for
+ <varname>uio_pdrv</varname>, except that you do not implement an
+ interrupt handler. The <varname>.handler</varname> element of
+ <varname>struct uio_info</varname> must remain
+ <varname>NULL</varname>. The <varname>.irq_flags</varname> element
+ must not contain <varname>IRQF_SHARED</varname>.
+ </para>
+ <para>
+ You will set the <varname>.name</varname> element of
+ <varname>struct platform_device</varname> to
+ <varname>"uio_pdrv_genirq"</varname> to use this driver.
+ </para>
+ <para>
+ The generic interrupt handler of <varname>uio_pdrv_genirq</varname>
+ will simply disable the interrupt line using
+ <function>disable_irq_nosync()</function>. After doing its work,
+ userspace can reenable the interrupt by writing 0x00000001 to the UIO
+ device file. The driver already implements an
+ <function>irq_control()</function> to make this possible, you must not
+ implement your own.
+ </para>
+ <para>
+ Using <varname>uio_pdrv_genirq</varname> not only saves a few lines of
+ interrupt handler code. You also do not need to know anything about
+ the chip's internal registers to create the kernel part of the driver.
+ All you need to know is the irq number of the pin the chip is
+ connected to.
+ </para>
+</sect1>
+
</chapter>
<chapter id="userspace_driver" xreflabel="Writing a driver in user space">
diff --git a/Documentation/IO-mapping.txt b/Documentation/IO-mapping.txt
index 86edb61bdee6..78a440695e11 100644
--- a/Documentation/IO-mapping.txt
+++ b/Documentation/IO-mapping.txt
@@ -1,6 +1,6 @@
[ NOTE: The virt_to_bus() and bus_to_virt() functions have been
- superseded by the functionality provided by the PCI DMA
- interface (see Documentation/DMA-mapping.txt). They continue
+ superseded by the functionality provided by the PCI DMA interface
+ (see Documentation/PCI/PCI-DMA-mapping.txt). They continue
to be documented below for historical purposes, but new code
must not use them. --davidm 00/12/12 ]
diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt
index fd4907a2968c..7f6de6ea5b47 100644
--- a/Documentation/PCI/pci.txt
+++ b/Documentation/PCI/pci.txt
@@ -294,7 +294,8 @@ NOTE: pci_enable_device() can fail! Check the return value.
pci_set_master() will enable DMA by setting the bus master bit
in the PCI_COMMAND register. It also fixes the latency timer value if
-it's set to something bogus by the BIOS.
+it's set to something bogus by the BIOS. pci_clear_master() will
+disable DMA by clearing the bus master bit.
If the PCI device can use the PCI Memory-Write-Invalidate transaction,
call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
diff --git a/Documentation/RCU/00-INDEX b/Documentation/RCU/00-INDEX
index 7dc0695a8f90..9bb62f7b89c3 100644
--- a/Documentation/RCU/00-INDEX
+++ b/Documentation/RCU/00-INDEX
@@ -12,6 +12,8 @@ rcuref.txt
- Reference-count design for elements of lists/arrays protected by RCU
rcu.txt
- RCU Concepts
+rcubarrier.txt
+ - Unloading modules that use RCU callbacks
RTFP.txt
- List of RCU papers (bibliography) going back to 1980.
torture.txt
diff --git a/Documentation/RCU/rcubarrier.txt b/Documentation/RCU/rcubarrier.txt
new file mode 100644
index 000000000000..909602d409bb
--- /dev/null
+++ b/Documentation/RCU/rcubarrier.txt
@@ -0,0 +1,304 @@
+RCU and Unloadable Modules
+
+[Originally published in LWN Jan. 14, 2007: http://lwn.net/Articles/217484/]
+
+RCU (read-copy update) is a synchronization mechanism that can be thought
+of as a replacement for read-writer locking (among other things), but with
+very low-overhead readers that are immune to deadlock, priority inversion,
+and unbounded latency. RCU read-side critical sections are delimited
+by rcu_read_lock() and rcu_read_unlock(), which, in non-CONFIG_PREEMPT
+kernels, generate no code whatsoever.
+
+This means that RCU writers are unaware of the presence of concurrent
+readers, so that RCU updates to shared data must be undertaken quite
+carefully, leaving an old version of the data structure in place until all
+pre-existing readers have finished. These old versions are needed because
+such readers might hold a reference to them. RCU updates can therefore be
+rather expensive, and RCU is thus best suited for read-mostly situations.
+
+How can an RCU writer possibly determine when all readers are finished,
+given that readers might well leave absolutely no trace of their
+presence? There is a synchronize_rcu() primitive that blocks until all
+pre-existing readers have completed. An updater wishing to delete an
+element p from a linked list might do the following, while holding an
+appropriate lock, of course:
+
+ list_del_rcu(p);
+ synchronize_rcu();
+ kfree(p);
+
+But the above code cannot be used in IRQ context -- the call_rcu()
+primitive must be used instead. This primitive takes a pointer to an
+rcu_head struct placed within the RCU-protected data structure and
+another pointer to a function that may be invoked later to free that
+structure. Code to delete an element p from the linked list from IRQ
+context might then be as follows:
+
+ list_del_rcu(p);
+ call_rcu(&p->rcu, p_callback);
+
+Since call_rcu() never blocks, this code can safely be used from within
+IRQ context. The function p_callback() might be defined as follows:
+
+ static void p_callback(struct rcu_head *rp)
+ {
+ struct pstruct *p = container_of(rp, struct pstruct, rcu);
+
+ kfree(p);
+ }
+
+
+Unloading Modules That Use call_rcu()
+
+But what if p_callback is defined in an unloadable module?
+
+If we unload the module while some RCU callbacks are pending,
+the CPUs executing these callbacks are going to be severely
+disappointed when they are later invoked, as fancifully depicted at
+http://lwn.net/images/ns/kernel/rcu-drop.jpg.
+
+We could try placing a synchronize_rcu() in the module-exit code path,
+but this is not sufficient. Although synchronize_rcu() does wait for a
+grace period to elapse, it does not wait for the callbacks to complete.
+
+One might be tempted to try several back-to-back synchronize_rcu()
+calls, but this is still not guaranteed to work. If there is a very
+heavy RCU-callback load, then some of the callbacks might be deferred
+in order to allow other processing to proceed. Such deferral is required
+in realtime kernels in order to avoid excessive scheduling latencies.
+
+
+rcu_barrier()
+
+We instead need the rcu_barrier() primitive. This primitive is similar
+to synchronize_rcu(), but instead of waiting solely for a grace
+period to elapse, it also waits for all outstanding RCU callbacks to
+complete. Pseudo-code using rcu_barrier() is as follows:
+
+ 1. Prevent any new RCU callbacks from being posted.
+ 2. Execute rcu_barrier().
+ 3. Allow the module to be unloaded.
+
+Quick Quiz #1: Why is there no srcu_barrier()?
+
+The rcutorture module makes use of rcu_barrier in its exit function
+as follows:
+
+ 1 static void
+ 2 rcu_torture_cleanup(void)
+ 3 {
+ 4 int i;
+ 5
+ 6 fullstop = 1;
+ 7 if (shuffler_task != NULL) {
+ 8 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task");
+ 9 kthread_stop(shuffler_task);
+10 }
+11 shuffler_task = NULL;
+12
+13 if (writer_task != NULL) {
+14 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task");
+15 kthread_stop(writer_task);
+16 }
+17 writer_task = NULL;
+18
+19 if (reader_tasks != NULL) {
+20 for (i = 0; i < nrealreaders; i++) {
+21 if (reader_tasks[i] != NULL) {
+22 VERBOSE_PRINTK_STRING(
+23 "Stopping rcu_torture_reader task");
+24 kthread_stop(reader_tasks[i]);
+25 }
+26 reader_tasks[i] = NULL;
+27 }
+28 kfree(reader_tasks);
+29 reader_tasks = NULL;
+30 }
+31 rcu_torture_current = NULL;
+32
+33 if (fakewriter_tasks != NULL) {
+34 for (i = 0; i < nfakewriters; i++) {
+35 if (fakewriter_tasks[i] != NULL) {
+36 VERBOSE_PRINTK_STRING(
+37 "Stopping rcu_torture_fakewriter task");
+38 kthread_stop(fakewriter_tasks[i]);
+39 }
+40 fakewriter_tasks[i] = NULL;
+41 }
+42 kfree(fakewriter_tasks);
+43 fakewriter_tasks = NULL;
+44 }
+45
+46 if (stats_task != NULL) {
+47 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task");
+48 kthread_stop(stats_task);
+49 }
+50 stats_task = NULL;
+51
+52 /* Wait for all RCU callbacks to fire. */
+53 rcu_barrier();
+54
+55 rcu_torture_stats_print(); /* -After- the stats thread is stopped! */
+56
+57 if (cur_ops->cleanup != NULL)
+58 cur_ops->cleanup();
+59 if (atomic_read(&n_rcu_torture_error))
+60 rcu_torture_print_module_parms("End of test: FAILURE");
+61 else
+62 rcu_torture_print_module_parms("End of test: SUCCESS");
+63 }
+
+Line 6 sets a global variable that prevents any RCU callbacks from
+re-posting themselves. This will not be necessary in most cases, since
+RCU callbacks rarely include calls to call_rcu(). However, the rcutorture
+module is an exception to this rule, and therefore needs to set this
+global variable.
+
+Lines 7-50 stop all the kernel tasks associated with the rcutorture
+module. Therefore, once execution reaches line 53, no more rcutorture
+RCU callbacks will be posted. The rcu_barrier() call on line 53 waits
+for any pre-existing callbacks to complete.
+
+Then lines 55-62 print status and do operation-specific cleanup, and
+then return, permitting the module-unload operation to be completed.
+
+Quick Quiz #2: Is there any other situation where rcu_barrier() might
+ be required?
+
+Your module might have additional complications. For example, if your
+module invokes call_rcu() from timers, you will need to first cancel all
+the timers, and only then invoke rcu_barrier() to wait for any remaining
+RCU callbacks to complete.
+
+
+Implementing rcu_barrier()
+
+Dipankar Sarma's implementation of rcu_barrier() makes use of the fact
+that RCU callbacks are never reordered once queued on one of the per-CPU
+queues. His implementation queues an RCU callback on each of the per-CPU
+callback queues, and then waits until they have all started executing, at
+which point, all earlier RCU callbacks are guaranteed to have completed.
+
+The original code for rcu_barrier() was as follows:
+
+ 1 void rcu_barrier(void)
+ 2 {
+ 3 BUG_ON(in_interrupt());
+ 4 /* Take cpucontrol mutex to protect against CPU hotplug */
+ 5 mutex_lock(&rcu_barrier_mutex);
+ 6 init_completion(&rcu_barrier_completion);
+ 7 atomic_set(&rcu_barrier_cpu_count, 0);
+ 8 on_each_cpu(rcu_barrier_func, NULL, 0, 1);
+ 9 wait_for_completion(&rcu_barrier_completion);
+10 mutex_unlock(&rcu_barrier_mutex);
+11 }
+
+Line 3 verifies that the caller is in process context, and lines 5 and 10
+use rcu_barrier_mutex to ensure that only one rcu_barrier() is using the
+global completion and counters at a time, which are initialized on lines
+6 and 7. Line 8 causes each CPU to invoke rcu_barrier_func(), which is
+shown below. Note that the final "1" in on_each_cpu()'s argument list
+ensures that all the calls to rcu_barrier_func() will have completed
+before on_each_cpu() returns. Line 9 then waits for the completion.
+
+This code was rewritten in 2008 to support rcu_barrier_bh() and
+rcu_barrier_sched() in addition to the original rcu_barrier().
+
+The rcu_barrier_func() runs on each CPU, where it invokes call_rcu()
+to post an RCU callback, as follows:
+
+ 1 static void rcu_barrier_func(void *notused)
+ 2 {
+ 3 int cpu = smp_processor_id();
+ 4 struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+ 5 struct rcu_head *head;
+ 6
+ 7 head = &rdp->barrier;
+ 8 atomic_inc(&rcu_barrier_cpu_count);
+ 9 call_rcu(head, rcu_barrier_callback);
+10 }
+
+Lines 3 and 4 locate RCU's internal per-CPU rcu_data structure,
+which contains the struct rcu_head that needed for the later call to
+call_rcu(). Line 7 picks up a pointer to this struct rcu_head, and line
+8 increments a global counter. This counter will later be decremented
+by the callback. Line 9 then registers the rcu_barrier_callback() on
+the current CPU's queue.
+
+The rcu_barrier_callback() function simply atomically decrements the
+rcu_barrier_cpu_count variable and finalizes the completion when it
+reaches zero, as follows:
+
+ 1 static void rcu_barrier_callback(struct rcu_head *notused)
+ 2 {
+ 3 if (atomic_dec_and_test(&rcu_barrier_cpu_count))
+ 4 complete(&rcu_barrier_completion);
+ 5 }
+
+Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
+ immediately (thus incrementing rcu_barrier_cpu_count to the
+ value one), but the other CPU's rcu_barrier_func() invocations
+ are delayed for a full grace period? Couldn't this result in
+ rcu_barrier() returning prematurely?
+
+
+rcu_barrier() Summary
+
+The rcu_barrier() primitive has seen relatively little use, since most
+code using RCU is in the core kernel rather than in modules. However, if
+you are using RCU from an unloadable module, you need to use rcu_barrier()
+so that your module may be safely unloaded.
+
+
+Answers to Quick Quizzes
+
+Quick Quiz #1: Why is there no srcu_barrier()?
+
+Answer: Since there is no call_srcu(), there can be no outstanding SRCU
+ callbacks. Therefore, there is no need to wait for them.
+
+Quick Quiz #2: Is there any other situation where rcu_barrier() might
+ be required?
+
+Answer: Interestingly enough, rcu_barrier() was not originally
+ implemented for module unloading. Nikita Danilov was using
+ RCU in a filesystem, which resulted in a similar situation at
+ filesystem-unmount time. Dipankar Sarma coded up rcu_barrier()
+ in response, so that Nikita could invoke it during the
+ filesystem-unmount process.
+
+ Much later, yours truly hit the RCU module-unload problem when
+ implementing rcutorture, and found that rcu_barrier() solves
+ this problem as well.
+
+Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
+ immediately (thus incrementing rcu_barrier_cpu_count to the
+ value one), but the other CPU's rcu_barrier_func() invocations
+ are delayed for a full grace period? Couldn't this result in
+ rcu_barrier() returning prematurely?
+
+Answer: This cannot happen. The reason is that on_each_cpu() has its last
+ argument, the wait flag, set to "1". This flag is passed through
+ to smp_call_function() and further to smp_call_function_on_cpu(),
+ causing this latter to spin until the cross-CPU invocation of
+ rcu_barrier_func() has completed. This by itself would prevent
+ a grace period from completing on non-CONFIG_PREEMPT kernels,
+ since each CPU must undergo a context switch (or other quiescent
+ state) before the grace period can complete. However, this is
+ of no use in CONFIG_PREEMPT kernels.
+
+ Therefore, on_each_cpu() disables preemption across its call
+ to smp_call_function() and also across the local call to
+ rcu_barrier_func(). This prevents the local CPU from context
+ switching, again preventing grace periods from completing. This
+ means that all CPUs have executed rcu_barrier_func() before
+ the first rcu_barrier_callback() can possibly execute, in turn
+ preventing rcu_barrier_cpu_count from prematurely reaching zero.
+
+ Currently, -rt implementations of RCU keep but a single global
+ queue for RCU callbacks, and thus do not suffer from this
+ problem. However, when the -rt RCU eventually does have per-CPU
+ callback queues, things will have to change. One simple change
+ is to add an rcu_read_lock() before line 8 of rcu_barrier()
+ and an rcu_read_unlock() after line 8 of this same function. If
+ you can think of a better change, please let me know!
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index cc49400b4af8..7ea231172c85 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -392,6 +392,10 @@ int main(int argc, char *argv[])
goto err;
}
}
+ if (!maskset && !tid && !containerset) {
+ usage();
+ goto err;
+ }
do {
int i;
diff --git a/Documentation/bad_memory.txt b/Documentation/bad_memory.txt
new file mode 100644
index 000000000000..df8416213202
--- /dev/null
+++ b/Documentation/bad_memory.txt
@@ -0,0 +1,45 @@
+March 2008
+Jan-Simon Moeller, dl9pf@gmx.de
+
+
+How to deal with bad memory e.g. reported by memtest86+ ?
+#########################################################
+
+There are three possibilities I know of:
+
+1) Reinsert/swap the memory modules
+
+2) Buy new modules (best!) or try to exchange the memory
+ if you have spare-parts
+
+3) Use BadRAM or memmap
+
+This Howto is about number 3) .
+
+
+BadRAM
+######
+BadRAM is the actively developed and available as kernel-patch
+here: http://rick.vanrein.org/linux/badram/
+
+For more details see the BadRAM documentation.
+
+memmap
+######
+
+memmap is already in the kernel and usable as kernel-parameter at
+boot-time. Its syntax is slightly strange and you may need to
+calculate the values by yourself!
+
+Syntax to exclude a memory area (see kernel-parameters.txt for details):
+memmap=<size>$<address>
+
+Example: memtest86+ reported here errors at address 0x18691458, 0x18698424 and
+ some others. All had 0x1869xxxx in common, so I chose a pattern of
+ 0x18690000,0xffff0000.
+
+With the numbers of the example above:
+memmap=64K$0x18690000
+ or
+memmap=0x10000$0x18690000
+
diff --git a/Documentation/blackfin/00-INDEX b/Documentation/blackfin/00-INDEX
index 7cb3b356b249..d6840a91e1e1 100644
--- a/Documentation/blackfin/00-INDEX
+++ b/Documentation/blackfin/00-INDEX
@@ -9,3 +9,6 @@ cachefeatures.txt
Filesystems
- Requirements for mounting the root file system.
+
+bfin-gpio-note.txt
+ - Notes in developing/using bfin-gpio driver.
diff --git a/Documentation/blackfin/bfin-gpio-notes.txt b/Documentation/blackfin/bfin-gpio-notes.txt
new file mode 100644
index 000000000000..9898c7ded7d3
--- /dev/null
+++ b/Documentation/blackfin/bfin-gpio-notes.txt
@@ -0,0 +1,71 @@
+/*
+ * File: Documentation/blackfin/bfin-gpio-note.txt
+ * Based on:
+ * Author:
+ *
+ * Created: $Id: bfin-gpio-note.txt 2008-11-24 16:42 grafyang $
+ * Description: This file contains the notes in developing/using bfin-gpio.
+ *
+ *
+ * Rev:
+ *
+ * Modified:
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ */
+
+
+1. Blackfin GPIO introduction
+
+ There are many GPIO pins on Blackfin. Most of these pins are muxed to
+ multi-functions. They can be configured as peripheral, or just as GPIO,
+ configured to input with interrupt enabled, or output.
+
+ For detailed information, please see "arch/blackfin/kernel/bfin_gpio.c",
+ or the relevant HRM.
+
+
+2. Avoiding resource conflict
+
+ Followed function groups are used to avoiding resource conflict,
+ - Use the pin as peripheral,
+ int peripheral_request(unsigned short per, const char *label);
+ int peripheral_request_list(const unsigned short per[], const char *label);
+ void peripheral_free(unsigned short per);
+ void peripheral_free_list(const unsigned short per[]);
+ - Use the pin as GPIO,
+ int bfin_gpio_request(unsigned gpio, const char *label);
+ void bfin_gpio_free(unsigned gpio);
+ - Use the pin as GPIO interrupt,
+ int bfin_gpio_irq_request(unsigned gpio, const char *label);
+ void bfin_gpio_irq_free(unsigned gpio);
+
+ The request functions will record the function state for a certain pin,
+ the free functions will clear it's function state.
+ Once a pin is requested, it can't be requested again before it is freed by
+ previous caller, otherwise kernel will dump stacks, and the request
+ function fail.
+ These functions are wrapped by other functions, most of the users need not
+ care.
+
+
+3. But there are some exceptions
+ - Kernel permit the identical GPIO be requested both as GPIO and GPIO
+ interrut.
+ Some drivers, like gpio-keys, need this behavior. Kernel only print out
+ warning messages like,
+ bfin-gpio: GPIO 24 is already reserved by gpio-keys: BTN0, and you are
+configuring it as IRQ!
+
+ Note: Consider the case that, if there are two drivers need the
+ identical GPIO, one of them use it as GPIO, the other use it as
+ GPIO interrupt. This will really cause resource conflict. So if
+ there is any abnormal driver behavior, please check the bfin-gpio
+ warning messages.
+
+ - Kernel permit the identical GPIO be requested from the same driver twice.
+
+
+
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 3c5434c83daf..ecad6ee75705 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -186,8 +186,9 @@ a virtual address mapping (unlike the earlier scheme of virtual address
do not have a corresponding kernel virtual address space mapping) and
low-memory pages.
-Note: Please refer to DMA-mapping.txt for a discussion on PCI high mem DMA
-aspects and mapping of scatter gather lists, and support for 64 bit PCI.
+Note: Please refer to Documentation/PCI/PCI-DMA-mapping.txt for a discussion
+on PCI high mem DMA aspects and mapping of scatter gather lists, and support
+for 64 bit PCI.
Special handling is required only for cases where i/o needs to happen on
pages at physical memory addresses beyond what the device can support. In these
@@ -953,14 +954,14 @@ elevator_allow_merge_fn called whenever the block layer determines
results in some sort of conflict internally,
this hook allows it to do that.
-elevator_dispatch_fn fills the dispatch queue with ready requests.
+elevator_dispatch_fn* fills the dispatch queue with ready requests.
I/O schedulers are free to postpone requests by
not filling the dispatch queue unless @force
is non-zero. Once dispatched, I/O schedulers
are not allowed to manipulate the requests -
they belong to generic dispatch queue.
-elevator_add_req_fn called to add a new request into the scheduler
+elevator_add_req_fn* called to add a new request into the scheduler
elevator_queue_empty_fn returns true if the merge queue is empty.
Drivers shouldn't use this, but rather check
@@ -990,7 +991,7 @@ elevator_activate_req_fn Called when device driver first sees a request.
elevator_deactivate_req_fn Called when device driver decides to delay
a request by requeueing it.
-elevator_init_fn
+elevator_init_fn*
elevator_exit_fn Allocate and free any elevator specific storage
for a queue.
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt
new file mode 100644
index 000000000000..e164403f60e1
--- /dev/null
+++ b/Documentation/block/queue-sysfs.txt
@@ -0,0 +1,63 @@
+Queue sysfs files
+=================
+
+This text file will detail the queue files that are located in the sysfs tree
+for each block device. Note that stacked devices typically do not export
+any settings, since their queue merely functions are a remapping target.
+These files are the ones found in the /sys/block/xxx/queue/ directory.
+
+Files denoted with a RO postfix are readonly and the RW postfix means
+read-write.
+
+hw_sector_size (RO)
+-------------------
+This is the hardware sector size of the device, in bytes.
+
+max_hw_sectors_kb (RO)
+----------------------
+This is the maximum number of kilobytes supported in a single data transfer.
+
+max_sectors_kb (RW)
+-------------------
+This is the maximum number of kilobytes that the block layer will allow
+for a filesystem request. Must be smaller than or equal to the maximum
+size allowed by the hardware.
+
+nomerges (RW)
+-------------
+This enables the user to disable the lookup logic involved with IO merging
+requests in the block layer. Merging may still occur through a direct
+1-hit cache, since that comes for (almost) free. The IO scheduler will not
+waste cycles doing tree/hash lookups for merges if nomerges is 1. Defaults
+to 0, enabling all merges.
+
+nr_requests (RW)
+----------------
+This controls how many requests may be allocated in the block layer for
+read or write requests. Note that the total allocated number may be twice
+this amount, since it applies only to reads or writes (not the accumulated
+sum).
+
+read_ahead_kb (RW)
+------------------
+Maximum number of kilobytes to read-ahead for filesystems on this block
+device.
+
+rq_affinity (RW)
+----------------
+If this option is enabled, the block layer will migrate request completions
+to the CPU that originally submitted the request. For some workloads
+this provides a significant reduction in CPU cycles due to caching effects.
+
+scheduler (RW)
+--------------
+When read, this file will display the current and available IO schedulers
+for this block device. The currently active IO scheduler will be enclosed
+in [] brackets. Writing an IO scheduler name to this file will switch
+control of this block device to that new IO scheduler. Note that writing
+an IO scheduler name to this file will attempt to load that IO scheduler
+module, if it isn't already present in the system.
+
+
+
+Jens Axboe <jens.axboe@oracle.com>, February 2009
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index d9014aa0eb68..d9e5d6f41b92 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -1,7 +1,8 @@
CGROUPS
-------
-Written by Paul Menage <menage@google.com> based on Documentation/cpusets.txt
+Written by Paul Menage <menage@google.com> based on
+Documentation/cgroups/cpusets.txt
Original copyright statements from cpusets.txt:
Portions Copyright (C) 2004 BULL SA.
@@ -68,7 +69,7 @@ On their own, the only use for cgroups is for simple job
tracking. The intention is that other subsystems hook into the generic
cgroup support to provide new attributes for cgroups, such as
accounting/limiting the resources which processes in a cgroup can
-access. For example, cpusets (see Documentation/cpusets.txt) allows
+access. For example, cpusets (see Documentation/cgroups/cpusets.txt) allows
you to associate a set of CPUs and a set of memory nodes with the
tasks in each cgroup.
@@ -227,7 +228,6 @@ Each cgroup is represented by a directory in the cgroup file system
containing the following files describing that cgroup:
- tasks: list of tasks (by pid) attached to that cgroup
- - releasable flag: cgroup currently removeable?
- notify_on_release flag: run the release agent on exit?
- release_agent: the path to use for release notifications (this file
exists in the top cgroup only)
@@ -360,7 +360,7 @@ Now you want to do something with this cgroup.
In this directory you can find several files:
# ls
-notify_on_release releasable tasks
+notify_on_release tasks
(plus whatever files added by the attached subsystems)
Now attach your shell to this cgroup:
@@ -479,7 +479,6 @@ newly-created cgroup if an error occurs after this subsystem's
create() method has been called for the new cgroup).
void pre_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp);
-(cgroup_mutex held by caller)
Called before checking the reference count on each subsystem. This may
be useful for subsystems which have some extra references even if
@@ -498,6 +497,7 @@ remain valid while the caller holds cgroup_mutex.
void attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct cgroup *old_cgrp, struct task_struct *task)
+(cgroup_mutex held by caller)
Called after the task has been attached to the cgroup, to allow any
post-attachment activity that requires memory allocations or blocking.
@@ -511,6 +511,7 @@ void exit(struct cgroup_subsys *ss, struct task_struct *task)
Called during task exit.
int populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
+(cgroup_mutex held by caller)
Called after creation of a cgroup to allow a subsystem to populate
the cgroup directory with file entries. The subsystem should make
@@ -520,6 +521,7 @@ method can return an error code, the error code is currently not
always handled well.
void post_clone(struct cgroup_subsys *ss, struct cgroup *cgrp)
+(cgroup_mutex held by caller)
Called at the end of cgroup_clone() to do any paramater
initialization which might be required before a task could attach. For
@@ -527,7 +529,7 @@ example in cpusets, no task may attach before 'cpus' and 'mems' are set
up.
void bind(struct cgroup_subsys *ss, struct cgroup *root)
-(cgroup_mutex held by caller)
+(cgroup_mutex and ss->hierarchy_mutex held by caller)
Called when a cgroup subsystem is rebound to a different hierarchy
and root cgroup. Currently this will only involve movement between
diff --git a/Documentation/controllers/cpuacct.txt b/Documentation/cgroups/cpuacct.txt
index bb775fbe43d7..bb775fbe43d7 100644
--- a/Documentation/controllers/cpuacct.txt
+++ b/Documentation/cgroups/cpuacct.txt
diff --git a/Documentation/cpusets.txt b/Documentation/cgroups/cpusets.txt
index 5c86c258c791..5c86c258c791 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
diff --git a/Documentation/controllers/devices.txt b/Documentation/cgroups/devices.txt
index 7cc6e6a60672..7cc6e6a60672 100644
--- a/Documentation/controllers/devices.txt
+++ b/Documentation/cgroups/devices.txt
diff --git a/Documentation/cgroups/memcg_test.txt b/Documentation/cgroups/memcg_test.txt
new file mode 100644
index 000000000000..523a9c16c400
--- /dev/null
+++ b/Documentation/cgroups/memcg_test.txt
@@ -0,0 +1,362 @@
+Memory Resource Controller(Memcg) Implementation Memo.
+Last Updated: 2009/1/19
+Base Kernel Version: based on 2.6.29-rc2.
+
+Because VM is getting complex (one of reasons is memcg...), memcg's behavior
+is complex. This is a document for memcg's internal behavior.
+Please note that implementation details can be changed.
+
+(*) Topics on API should be in Documentation/cgroups/memory.txt)
+
+0. How to record usage ?
+ 2 objects are used.
+
+ page_cgroup ....an object per page.
+ Allocated at boot or memory hotplug. Freed at memory hot removal.
+
+ swap_cgroup ... an entry per swp_entry.
+ Allocated at swapon(). Freed at swapoff().
+
+ The page_cgroup has USED bit and double count against a page_cgroup never
+ occurs. swap_cgroup is used only when a charged page is swapped-out.
+
+1. Charge
+
+ a page/swp_entry may be charged (usage += PAGE_SIZE) at
+
+ mem_cgroup_newpage_charge()
+ Called at new page fault and Copy-On-Write.
+
+ mem_cgroup_try_charge_swapin()
+ Called at do_swap_page() (page fault on swap entry) and swapoff.
+ Followed by charge-commit-cancel protocol. (With swap accounting)
+ At commit, a charge recorded in swap_cgroup is removed.
+
+ mem_cgroup_cache_charge()
+ Called at add_to_page_cache()
+
+ mem_cgroup_cache_charge_swapin()
+ Called at shmem's swapin.
+
+ mem_cgroup_prepare_migration()
+ Called before migration. "extra" charge is done and followed by
+ charge-commit-cancel protocol.
+ At commit, charge against oldpage or newpage will be committed.
+
+2. Uncharge
+ a page/swp_entry may be uncharged (usage -= PAGE_SIZE) by
+
+ mem_cgroup_uncharge_page()
+ Called when an anonymous page is fully unmapped. I.e., mapcount goes
+ to 0. If the page is SwapCache, uncharge is delayed until
+ mem_cgroup_uncharge_swapcache().
+
+ mem_cgroup_uncharge_cache_page()
+ Called when a page-cache is deleted from radix-tree. If the page is
+ SwapCache, uncharge is delayed until mem_cgroup_uncharge_swapcache().
+
+ mem_cgroup_uncharge_swapcache()
+ Called when SwapCache is removed from radix-tree. The charge itself
+ is moved to swap_cgroup. (If mem+swap controller is disabled, no
+ charge to swap occurs.)
+
+ mem_cgroup_uncharge_swap()
+ Called when swp_entry's refcnt goes down to 0. A charge against swap
+ disappears.
+
+ mem_cgroup_end_migration(old, new)
+ At success of migration old is uncharged (if necessary), a charge
+ to new page is committed. At failure, charge to old page is committed.
+
+3. charge-commit-cancel
+ In some case, we can't know this "charge" is valid or not at charging
+ (because of races).
+ To handle such case, there are charge-commit-cancel functions.
+ mem_cgroup_try_charge_XXX
+ mem_cgroup_commit_charge_XXX
+ mem_cgroup_cancel_charge_XXX
+ these are used in swap-in and migration.
+
+ At try_charge(), there are no flags to say "this page is charged".
+ at this point, usage += PAGE_SIZE.
+
+ At commit(), the function checks the page should be charged or not
+ and set flags or avoid charging.(usage -= PAGE_SIZE)
+
+ At cancel(), simply usage -= PAGE_SIZE.
+
+Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
+
+4. Anonymous
+ Anonymous page is newly allocated at
+ - page fault into MAP_ANONYMOUS mapping.
+ - Copy-On-Write.
+ It is charged right after it's allocated before doing any page table
+ related operations. Of course, it's uncharged when another page is used
+ for the fault address.
+
+ At freeing anonymous page (by exit() or munmap()), zap_pte() is called
+ and pages for ptes are freed one by one.(see mm/memory.c). Uncharges
+ are done at page_remove_rmap() when page_mapcount() goes down to 0.
+
+ Another page freeing is by page-reclaim (vmscan.c) and anonymous
+ pages are swapped out. In this case, the page is marked as
+ PageSwapCache(). uncharge() routine doesn't uncharge the page marked
+ as SwapCache(). It's delayed until __delete_from_swap_cache().
+
+ 4.1 Swap-in.
+ At swap-in, the page is taken from swap-cache. There are 2 cases.
+
+ (a) If the SwapCache is newly allocated and read, it has no charges.
+ (b) If the SwapCache has been mapped by processes, it has been
+ charged already.
+
+ This swap-in is one of the most complicated work. In do_swap_page(),
+ following events occur when pte is unchanged.
+
+ (1) the page (SwapCache) is looked up.
+ (2) lock_page()
+ (3) try_charge_swapin()
+ (4) reuse_swap_page() (may call delete_swap_cache())
+ (5) commit_charge_swapin()
+ (6) swap_free().
+
+ Considering following situation for example.
+
+ (A) The page has not been charged before (2) and reuse_swap_page()
+ doesn't call delete_from_swap_cache().
+ (B) The page has not been charged before (2) and reuse_swap_page()
+ calls delete_from_swap_cache().
+ (C) The page has been charged before (2) and reuse_swap_page() doesn't
+ call delete_from_swap_cache().
+ (D) The page has been charged before (2) and reuse_swap_page() calls
+ delete_from_swap_cache().
+
+ memory.usage/memsw.usage changes to this page/swp_entry will be
+ Case (A) (B) (C) (D)
+ Event
+ Before (2) 0/ 1 0/ 1 1/ 1 1/ 1
+ ===========================================
+ (3) +1/+1 +1/+1 +1/+1 +1/+1
+ (4) - 0/ 0 - -1/ 0
+ (5) 0/-1 0/ 0 -1/-1 0/ 0
+ (6) - 0/-1 - 0/-1
+ ===========================================
+ Result 1/ 1 1/ 1 1/ 1 1/ 1
+
+ In any cases, charges to this page should be 1/ 1.
+
+ 4.2 Swap-out.
+ At swap-out, typical state transition is below.
+
+ (a) add to swap cache. (marked as SwapCache)
+ swp_entry's refcnt += 1.
+ (b) fully unmapped.
+ swp_entry's refcnt += # of ptes.
+ (c) write back to swap.
+ (d) delete from swap cache. (remove from SwapCache)
+ swp_entry's refcnt -= 1.
+
+
+ At (b), the page is marked as SwapCache and not uncharged.
+ At (d), the page is removed from SwapCache and a charge in page_cgroup
+ is moved to swap_cgroup.
+
+ Finally, at task exit,
+ (e) zap_pte() is called and swp_entry's refcnt -=1 -> 0.
+ Here, a charge in swap_cgroup disappears.
+
+5. Page Cache
+ Page Cache is charged at
+ - add_to_page_cache_locked().
+
+ uncharged at
+ - __remove_from_page_cache().
+
+ The logic is very clear. (About migration, see below)
+ Note: __remove_from_page_cache() is called by remove_from_page_cache()
+ and __remove_mapping().
+
+6. Shmem(tmpfs) Page Cache
+ Memcg's charge/uncharge have special handlers of shmem. The best way
+ to understand shmem's page state transition is to read mm/shmem.c.
+ But brief explanation of the behavior of memcg around shmem will be
+ helpful to understand the logic.
+
+ Shmem's page (just leaf page, not direct/indirect block) can be on
+ - radix-tree of shmem's inode.
+ - SwapCache.
+ - Both on radix-tree and SwapCache. This happens at swap-in
+ and swap-out,
+
+ It's charged when...
+ - A new page is added to shmem's radix-tree.
+ - A swp page is read. (move a charge from swap_cgroup to page_cgroup)
+ It's uncharged when
+ - A page is removed from radix-tree and not SwapCache.
+ - When SwapCache is removed, a charge is moved to swap_cgroup.
+ - When swp_entry's refcnt goes down to 0, a charge in swap_cgroup
+ disappears.
+
+7. Page Migration
+ One of the most complicated functions is page-migration-handler.
+ Memcg has 2 routines. Assume that we are migrating a page's contents
+ from OLDPAGE to NEWPAGE.
+
+ Usual migration logic is..
+ (a) remove the page from LRU.
+ (b) allocate NEWPAGE (migration target)
+ (c) lock by lock_page().
+ (d) unmap all mappings.
+ (e-1) If necessary, replace entry in radix-tree.
+ (e-2) move contents of a page.
+ (f) map all mappings again.
+ (g) pushback the page to LRU.
+ (-) OLDPAGE will be freed.
+
+ Before (g), memcg should complete all necessary charge/uncharge to
+ NEWPAGE/OLDPAGE.
+
+ The point is....
+ - If OLDPAGE is anonymous, all charges will be dropped at (d) because
+ try_to_unmap() drops all mapcount and the page will not be
+ SwapCache.
+
+ - If OLDPAGE is SwapCache, charges will be kept at (g) because
+ __delete_from_swap_cache() isn't called at (e-1)
+
+ - If OLDPAGE is page-cache, charges will be kept at (g) because
+ remove_from_swap_cache() isn't called at (e-1)
+
+ memcg provides following hooks.
+
+ - mem_cgroup_prepare_migration(OLDPAGE)
+ Called after (b) to account a charge (usage += PAGE_SIZE) against
+ memcg which OLDPAGE belongs to.
+
+ - mem_cgroup_end_migration(OLDPAGE, NEWPAGE)
+ Called after (f) before (g).
+ If OLDPAGE is used, commit OLDPAGE again. If OLDPAGE is already
+ charged, a charge by prepare_migration() is automatically canceled.
+ If NEWPAGE is used, commit NEWPAGE and uncharge OLDPAGE.
+
+ But zap_pte() (by exit or munmap) can be called while migration,
+ we have to check if OLDPAGE/NEWPAGE is a valid page after commit().
+
+8. LRU
+ Each memcg has its own private LRU. Now, it's handling is under global
+ VM's control (means that it's handled under global zone->lru_lock).
+ Almost all routines around memcg's LRU is called by global LRU's
+ list management functions under zone->lru_lock().
+
+ A special function is mem_cgroup_isolate_pages(). This scans
+ memcg's private LRU and call __isolate_lru_page() to extract a page
+ from LRU.
+ (By __isolate_lru_page(), the page is removed from both of global and
+ private LRU.)
+
+
+9. Typical Tests.
+
+ Tests for racy cases.
+
+ 9.1 Small limit to memcg.
+ When you do test to do racy case, it's good test to set memcg's limit
+ to be very small rather than GB. Many races found in the test under
+ xKB or xxMB limits.
+ (Memory behavior under GB and Memory behavior under MB shows very
+ different situation.)
+
+ 9.2 Shmem
+ Historically, memcg's shmem handling was poor and we saw some amount
+ of troubles here. This is because shmem is page-cache but can be
+ SwapCache. Test with shmem/tmpfs is always good test.
+
+ 9.3 Migration
+ For NUMA, migration is an another special case. To do easy test, cpuset
+ is useful. Following is a sample script to do migration.
+
+ mount -t cgroup -o cpuset none /opt/cpuset
+
+ mkdir /opt/cpuset/01
+ echo 1 > /opt/cpuset/01/cpuset.cpus
+ echo 0 > /opt/cpuset/01/cpuset.mems
+ echo 1 > /opt/cpuset/01/cpuset.memory_migrate
+ mkdir /opt/cpuset/02
+ echo 1 > /opt/cpuset/02/cpuset.cpus
+ echo 1 > /opt/cpuset/02/cpuset.mems
+ echo 1 > /opt/cpuset/02/cpuset.memory_migrate
+
+ In above set, when you moves a task from 01 to 02, page migration to
+ node 0 to node 1 will occur. Following is a script to migrate all
+ under cpuset.
+ --
+ move_task()
+ {
+ for pid in $1
+ do
+ /bin/echo $pid >$2/tasks 2>/dev/null
+ echo -n $pid
+ echo -n " "
+ done
+ echo END
+ }
+
+ G1_TASK=`cat ${G1}/tasks`
+ G2_TASK=`cat ${G2}/tasks`
+ move_task "${G1_TASK}" ${G2} &
+ --
+ 9.4 Memory hotplug.
+ memory hotplug test is one of good test.
+ to offline memory, do following.
+ # echo offline > /sys/devices/system/memory/memoryXXX/state
+ (XXX is the place of memory)
+ This is an easy way to test page migration, too.
+
+ 9.5 mkdir/rmdir
+ When using hierarchy, mkdir/rmdir test should be done.
+ Use tests like the following.
+
+ echo 1 >/opt/cgroup/01/memory/use_hierarchy
+ mkdir /opt/cgroup/01/child_a
+ mkdir /opt/cgroup/01/child_b
+
+ set limit to 01.
+ add limit to 01/child_b
+ run jobs under child_a and child_b
+
+ create/delete following groups at random while jobs are running.
+ /opt/cgroup/01/child_a/child_aa
+ /opt/cgroup/01/child_b/child_bb
+ /opt/cgroup/01/child_c
+
+ running new jobs in new group is also good.
+
+ 9.6 Mount with other subsystems.
+ Mounting with other subsystems is a good test because there is a
+ race and lock dependency with other cgroup subsystems.
+
+ example)
+ # mount -t cgroup none /cgroup -t cpuset,memory,cpu,devices
+
+ and do task move, mkdir, rmdir etc...under this.
+
+ 9.7 swapoff.
+ Besides management of swap is one of complicated parts of memcg,
+ call path of swap-in at swapoff is not same as usual swap-in path..
+ It's worth to be tested explicitly.
+
+ For example, test like following is good.
+ (Shell-A)
+ # mount -t cgroup none /cgroup -t memory
+ # mkdir /cgroup/test
+ # echo 40M > /cgroup/test/memory.limit_in_bytes
+ # echo 0 > /cgroup/test/tasks
+ Run malloc(100M) program under this. You'll see 60M of swaps.
+ (Shell-B)
+ # move all tasks in /cgroup/test to /cgroup
+ # /sbin/swapoff -a
+ # rmdir /test/cgroup
+ # kill malloc task.
+
+ Of course, tmpfs v.s. swapoff test should be tested, too.
diff --git a/Documentation/controllers/memory.txt b/Documentation/cgroups/memory.txt
index 1c07547d3f81..e1501964df1e 100644
--- a/Documentation/controllers/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -137,7 +137,32 @@ behind this approach is that a cgroup that aggressively uses a shared
page will eventually get charged for it (once it is uncharged from
the cgroup that brought it in -- this will happen on memory pressure).
-2.4 Reclaim
+Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used..
+When you do swapoff and make swapped-out pages of shmem(tmpfs) to
+be backed into memory in force, charges for pages are accounted against the
+caller of swapoff rather than the users of shmem.
+
+
+2.4 Swap Extension (CONFIG_CGROUP_MEM_RES_CTLR_SWAP)
+Swap Extension allows you to record charge for swap. A swapped-in page is
+charged back to original page allocator if possible.
+
+When swap is accounted, following files are added.
+ - memory.memsw.usage_in_bytes.
+ - memory.memsw.limit_in_bytes.
+
+usage of mem+swap is limited by memsw.limit_in_bytes.
+
+Note: why 'mem+swap' rather than swap.
+The global LRU(kswapd) can swap out arbitrary pages. Swap-out means
+to move account from memory to swap...there is no change in usage of
+mem+swap.
+
+In other words, when we want to limit the usage of swap without affecting
+global LRU, mem+swap limit is better than just limiting swap from OS point
+of view.
+
+2.5 Reclaim
Each cgroup maintains a per cgroup LRU that consists of an active
and inactive list. When a cgroup goes over its limit, we first try
@@ -207,12 +232,6 @@ exceeded.
The memory.stat file gives accounting information. Now, the number of
caches, RSS and Active pages/Inactive pages are shown.
-The memory.force_empty gives an interface to drop *all* charges by force.
-
-# echo 1 > memory.force_empty
-
-will drop all charges in cgroup. Currently, this is maintained for test.
-
4. Testing
Balbir posted lmbench, AIM9, LTP and vmmstress results [10] and [11].
@@ -242,10 +261,106 @@ reclaimed.
A cgroup can be removed by rmdir, but as discussed in sections 4.1 and 4.2, a
cgroup might have some charge associated with it, even though all
-tasks have migrated away from it. Such charges are automatically dropped at
-rmdir() if there are no tasks.
+tasks have migrated away from it.
+Such charges are freed(at default) or moved to its parent. When moved,
+both of RSS and CACHES are moved to parent.
+If both of them are busy, rmdir() returns -EBUSY. See 5.1 Also.
+
+Charges recorded in swap information is not updated at removal of cgroup.
+Recorded information is discarded and a cgroup which uses swap (swapcache)
+will be charged as a new owner of it.
+
+
+5. Misc. interfaces.
+
+5.1 force_empty
+ memory.force_empty interface is provided to make cgroup's memory usage empty.
+ You can use this interface only when the cgroup has no tasks.
+ When writing anything to this
+
+ # echo 0 > memory.force_empty
+
+ Almost all pages tracked by this memcg will be unmapped and freed. Some of
+ pages cannot be freed because it's locked or in-use. Such pages are moved
+ to parent and this cgroup will be empty. But this may return -EBUSY in
+ some too busy case.
+
+ Typical use case of this interface is that calling this before rmdir().
+ Because rmdir() moves all pages to parent, some out-of-use page caches can be
+ moved to the parent. If you want to avoid that, force_empty will be useful.
+
+5.2 stat file
+ memory.stat file includes following statistics (now)
+ cache - # of pages from page-cache and shmem.
+ rss - # of pages from anonymous memory.
+ pgpgin - # of event of charging
+ pgpgout - # of event of uncharging
+ active_anon - # of pages on active lru of anon, shmem.
+ inactive_anon - # of pages on active lru of anon, shmem
+ active_file - # of pages on active lru of file-cache
+ inactive_file - # of pages on inactive lru of file cache
+ unevictable - # of pages cannot be reclaimed.(mlocked etc)
+
+ Below is depend on CONFIG_DEBUG_VM.
+ inactive_ratio - VM inernal parameter. (see mm/page_alloc.c)
+ recent_rotated_anon - VM internal parameter. (see mm/vmscan.c)
+ recent_rotated_file - VM internal parameter. (see mm/vmscan.c)
+ recent_scanned_anon - VM internal parameter. (see mm/vmscan.c)
+ recent_scanned_file - VM internal parameter. (see mm/vmscan.c)
+
+ Memo:
+ recent_rotated means recent frequency of lru rotation.
+ recent_scanned means recent # of scans to lru.
+ showing for better debug please see the code for meanings.
+
+
+5.3 swappiness
+ Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
+
+ Following cgroup's swapiness can't be changed.
+ - root cgroup (uses /proc/sys/vm/swappiness).
+ - a cgroup which uses hierarchy and it has child cgroup.
+ - a cgroup which uses hierarchy and not the root of hierarchy.
+
+
+6. Hierarchy support
+
+The memory controller supports a deep hierarchy and hierarchical accounting.
+The hierarchy is created by creating the appropriate cgroups in the
+cgroup filesystem. Consider for example, the following cgroup filesystem
+hierarchy
+
+ root
+ / | \
+ / | \
+ a b c
+ | \
+ | \
+ d e
+
+In the diagram above, with hierarchical accounting enabled, all memory
+usage of e, is accounted to its ancestors up until the root (i.e, c and root),
+that has memory.use_hierarchy enabled. If one of the ancestors goes over its
+limit, the reclaim algorithm reclaims from the tasks in the ancestor and the
+children of the ancestor.
+
+6.1 Enabling hierarchical accounting and reclaim
+
+The memory controller by default disables the hierarchy feature. Support
+can be enabled by writing 1 to memory.use_hierarchy file of the root cgroup
+
+# echo 1 > memory.use_hierarchy
+
+The feature can be disabled by
+
+# echo 0 > memory.use_hierarchy
+
+NOTE1: Enabling/disabling will fail if the cgroup already has other
+cgroups created below it.
+
+NOTE2: This feature can be enabled/disabled per subtree.
-5. TODO
+7. TODO
1. Add support for accounting huge pages (as a separate controller)
2. Make per-cgroup scanner reclaim not-shared pages first
diff --git a/Documentation/controllers/resource_counter.txt b/Documentation/cgroups/resource_counter.txt
index f196ac1d7d25..f196ac1d7d25 100644
--- a/Documentation/controllers/resource_counter.txt
+++ b/Documentation/cgroups/resource_counter.txt
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index 94bbc27ddd4f..9d620c153b04 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -50,16 +50,17 @@ additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets
cpu_possible_map = cpu_present_map + additional_cpus
(*) Option valid only for following architectures
-- x86_64, ia64
+- ia64
-ia64 and x86_64 use the number of disabled local apics in ACPI tables MADT
-to determine the number of potentially hot-pluggable cpus. The implementation
-should only rely on this to count the # of cpus, but *MUST* not rely on the
-apicid values in those tables for disabled apics. In the event BIOS doesn't
-mark such hot-pluggable cpus as disabled entries, one could use this
-parameter "additional_cpus=x" to represent those cpus in the cpu_possible_map.
+ia64 uses the number of disabled local apics in ACPI tables MADT to
+determine the number of potentially hot-pluggable cpus. The implementation
+should only rely on this to count the # of cpus, but *MUST* not rely
+on the apicid values in those tables for disabled apics. In the event
+BIOS doesn't mark such hot-pluggable cpus as disabled entries, one could
+use this parameter "additional_cpus=x" to represent those cpus in the
+cpu_possible_map.
-possible_cpus=n [s390 only] use this to set hotpluggable cpus.
+possible_cpus=n [s390,x86_64] use this to set hotpluggable cpus.
This option sets possible_cpus bits in
cpu_possible_map. Thus keeping the numbers of bits set
constant even if the machine gets rebooted.
diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt
index bd699da24666..45932ec21cee 100644
--- a/Documentation/cputopology.txt
+++ b/Documentation/cputopology.txt
@@ -31,3 +31,51 @@ not defined by include/asm-XXX/topology.h:
2) core_id: 0
3) thread_siblings: just the given CPU
4) core_siblings: just the given CPU
+
+Additionally, cpu topology information is provided under
+/sys/devices/system/cpu and includes these files. The internal
+source for the output is in brackets ("[]").
+
+ kernel_max: the maximum cpu index allowed by the kernel configuration.
+ [NR_CPUS-1]
+
+ offline: cpus that are not online because they have been
+ HOTPLUGGED off (see cpu-hotplug.txt) or exceed the limit
+ of cpus allowed by the kernel configuration (kernel_max
+ above). [~cpu_online_mask + cpus >= NR_CPUS]
+
+ online: cpus that are online and being scheduled [cpu_online_mask]
+
+ possible: cpus that have been allocated resources and can be
+ brought online if they are present. [cpu_possible_mask]
+
+ present: cpus that have been identified as being present in the
+ system. [cpu_present_mask]
+
+The format for the above output is compatible with cpulist_parse()
+[see <linux/cpumask.h>]. Some examples follow.
+
+In this example, there are 64 cpus in the system but cpus 32-63 exceed
+the kernel max which is limited to 0..31 by the NR_CPUS config option
+being 32. Note also that cpus 2 and 4-31 are not online but could be
+brought online as they are both present and possible.
+
+ kernel_max: 31
+ offline: 2,4-31,32-63
+ online: 0-1,3
+ possible: 0-31
+ present: 0-31
+
+In this example, the NR_CPUS config option is 128, but the kernel was
+started with possible_cpus=144. There are 4 cpus in the system and cpu2
+was manually taken offline (and is the only cpu that can be brought
+online.)
+
+ kernel_max: 127
+ offline: 2,4-127,128-143
+ online: 0-1,3
+ possible: 0-127
+ present: 0-3
+
+See cpu-hotplug.txt for the possible_cpus=NUM kernel start parameter
+as well as more information on the various cpumask's.
diff --git a/Documentation/crypto/async-tx-api.txt b/Documentation/crypto/async-tx-api.txt
index c1e9545c59bd..9f59fcbf5d82 100644
--- a/Documentation/crypto/async-tx-api.txt
+++ b/Documentation/crypto/async-tx-api.txt
@@ -13,9 +13,9 @@
3.6 Constraints
3.7 Example
-4 DRIVER DEVELOPER NOTES
+4 DMAENGINE DRIVER DEVELOPER NOTES
4.1 Conformance points
-4.2 "My application needs finer control of hardware channels"
+4.2 "My application needs exclusive control of hardware channels"
5 SOURCE
@@ -150,6 +150,7 @@ ops_run_* and ops_complete_* routines in drivers/md/raid5.c for more
implementation examples.
4 DRIVER DEVELOPMENT NOTES
+
4.1 Conformance points:
There are a few conformance points required in dmaengine drivers to
accommodate assumptions made by applications using the async_tx API:
@@ -158,58 +159,49 @@ accommodate assumptions made by applications using the async_tx API:
3/ Use async_tx_run_dependencies() in the descriptor clean up path to
handle submission of dependent operations
-4.2 "My application needs finer control of hardware channels"
-This requirement seems to arise from cases where a DMA engine driver is
-trying to support device-to-memory DMA. The dmaengine and async_tx
-implementations were designed for offloading memory-to-memory
-operations; however, there are some capabilities of the dmaengine layer
-that can be used for platform-specific channel management.
-Platform-specific constraints can be handled by registering the
-application as a 'dma_client' and implementing a 'dma_event_callback' to
-apply a filter to the available channels in the system. Before showing
-how to implement a custom dma_event callback some background of
-dmaengine's client support is required.
-
-The following routines in dmaengine support multiple clients requesting
-use of a channel:
-- dma_async_client_register(struct dma_client *client)
-- dma_async_client_chan_request(struct dma_client *client)
-
-dma_async_client_register takes a pointer to an initialized dma_client
-structure. It expects that the 'event_callback' and 'cap_mask' fields
-are already initialized.
-
-dma_async_client_chan_request triggers dmaengine to notify the client of
-all channels that satisfy the capability mask. It is up to the client's
-event_callback routine to track how many channels the client needs and
-how many it is currently using. The dma_event_callback routine returns a
-dma_state_client code to let dmaengine know the status of the
-allocation.
-
-Below is the example of how to extend this functionality for
-platform-specific filtering of the available channels beyond the
-standard capability mask:
-
-static enum dma_state_client
-my_dma_client_callback(struct dma_client *client,
- struct dma_chan *chan, enum dma_state state)
-{
- struct dma_device *dma_dev;
- struct my_platform_specific_dma *plat_dma_dev;
-
- dma_dev = chan->device;
- plat_dma_dev = container_of(dma_dev,
- struct my_platform_specific_dma,
- dma_dev);
-
- if (!plat_dma_dev->platform_specific_capability)
- return DMA_DUP;
-
- . . .
-}
+4.2 "My application needs exclusive control of hardware channels"
+Primarily this requirement arises from cases where a DMA engine driver
+is being used to support device-to-memory operations. A channel that is
+performing these operations cannot, for many platform specific reasons,
+be shared. For these cases the dma_request_channel() interface is
+provided.
+
+The interface is:
+struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
+ dma_filter_fn filter_fn,
+ void *filter_param);
+
+Where dma_filter_fn is defined as:
+typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);
+
+When the optional 'filter_fn' parameter is set to NULL
+dma_request_channel simply returns the first channel that satisfies the
+capability mask. Otherwise, when the mask parameter is insufficient for
+specifying the necessary channel, the filter_fn routine can be used to
+disposition the available channels in the system. The filter_fn routine
+is called once for each free channel in the system. Upon seeing a
+suitable channel filter_fn returns DMA_ACK which flags that channel to
+be the return value from dma_request_channel. A channel allocated via
+this interface is exclusive to the caller, until dma_release_channel()
+is called.
+
+The DMA_PRIVATE capability flag is used to tag dma devices that should
+not be used by the general-purpose allocator. It can be set at
+initialization time if it is known that a channel will always be
+private. Alternatively, it is set when dma_request_channel() finds an
+unused "public" channel.
+
+A couple caveats to note when implementing a driver and consumer:
+1/ Once a channel has been privately allocated it will no longer be
+ considered by the general-purpose allocator even after a call to
+ dma_release_channel().
+2/ Since capabilities are specified at the device level a dma_device
+ with multiple channels will either have all channels public, or all
+ channels private.
5 SOURCE
-include/linux/dmaengine.h: core header file for DMA drivers and clients
+
+include/linux/dmaengine.h: core header file for DMA drivers and api users
drivers/dma/dmaengine.c: offload engine channel management routines
drivers/dma/: location for offload engine drivers
include/linux/async_tx.h: core header file for the async_tx api
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt
index 2c0d631de0cf..c11b931f8f98 100644
--- a/Documentation/dell_rbu.txt
+++ b/Documentation/dell_rbu.txt
@@ -81,8 +81,8 @@ Until this step is completed the driver cannot be unloaded.
Also echoing either mono ,packet or init in to image_type will free up the
memory allocated by the driver.
-If an user by accident executes steps 1 and 3 above without executing step 2;
-it will make the /sys/class/firmware/dell_rbu/ entries to disappear.
+If a user by accident executes steps 1 and 3 above without executing step 2;
+it will make the /sys/class/firmware/dell_rbu/ entries disappear.
The entries can be recreated by doing the following
echo init > /sys/devices/platform/dell_rbu/image_type
NOTE: echoing init in image_type does not change it original value.
diff --git a/Documentation/development-process/4.Coding b/Documentation/development-process/4.Coding
index 014aca8f14e2..a5a3450faaa0 100644
--- a/Documentation/development-process/4.Coding
+++ b/Documentation/development-process/4.Coding
@@ -375,10 +375,10 @@ say, this can be a large job, so it is best to be sure that the
justification is solid.
When making an incompatible API change, one should, whenever possible,
-ensure that code which has not been updated is caught by the compiler.
+ensure that code which has not been updated is caught by the compiler.
This will help you to be sure that you have found all in-tree uses of that
interface. It will also alert developers of out-of-tree code that there is
a change that they need to respond to. Supporting out-of-tree code is not
something that kernel developers need to be worried about, but we also do
-not have to make life harder for out-of-tree developers than it it needs to
-be.
+not have to make life harder for out-of-tree developers than it needs to
+be.
diff --git a/Documentation/dmaengine.txt b/Documentation/dmaengine.txt
new file mode 100644
index 000000000000..0c1c2f63c0a9
--- /dev/null
+++ b/Documentation/dmaengine.txt
@@ -0,0 +1 @@
+See Documentation/crypto/async-tx-api.txt
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index a0ed3964a219..5ddbe350487a 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -310,15 +310,6 @@ Who: Krzysztof Piotr Oledzki <ole@ans.pl>
---------------------------
-What: ide-scsi (BLK_DEV_IDESCSI)
-When: 2.6.29
-Why: The 2.6 kernel supports direct writing to ide CD drives, which
- eliminates the need for ide-scsi. The new method is more
- efficient in every way.
-Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-
----------------------------
-
What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client()
When: 2.6.29 (ideally) or 2.6.30 (more likely)
Why: Deprecated by the new (standard) device driver binding model. Use
@@ -327,6 +318,14 @@ Who: Jean Delvare <khali@linux-fr.org>
---------------------------
+What: fscher and fscpos drivers
+When: June 2009
+Why: Deprecated by the new fschmd driver.
+Who: Hans de Goede <hdegoede@redhat.com>
+ Jean Delvare <khali@linux-fr.org>
+
+---------------------------
+
What: SELinux "compat_net" functionality
When: 2.6.30 at the earliest
Why: In 2.6.18 the Secmark concept was introduced to replace the "compat_net"
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 23d2f4460deb..ec6a9392a173 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -97,8 +97,8 @@ prototypes:
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*sync_fs)(struct super_block *sb, int wait);
- void (*write_super_lockfs) (struct super_block *);
- void (*unlockfs) (struct super_block *);
+ int (*freeze_fs) (struct super_block *);
+ int (*unfreeze_fs) (struct super_block *);
int (*statfs) (struct dentry *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
@@ -119,8 +119,8 @@ delete_inode: no
put_super: yes yes no
write_super: no yes read
sync_fs: no no read
-write_super_lockfs: ?
-unlockfs: ?
+freeze_fs: ?
+unfreeze_fs: ?
statfs: no no no
remount_fs: yes yes maybe (see below)
clear_inode: no
@@ -394,11 +394,10 @@ prototypes:
unsigned long (*get_unmapped_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
- int (*dir_notify)(struct file *, unsigned long);
};
locking rules:
- All except ->poll() may block.
+ All may block.
BKL
llseek: no (see below)
read: no
@@ -424,7 +423,6 @@ sendfile: no
sendpage: no
get_unmapped_area: no
check_flags: no
-dir_notify: no
->llseek() locking has moved from llseek to the individual llseek
implementations. If your fs is not using generic_file_llseek, you
diff --git a/Documentation/filesystems/btrfs.txt b/Documentation/filesystems/btrfs.txt
new file mode 100644
index 000000000000..64087c34327f
--- /dev/null
+++ b/Documentation/filesystems/btrfs.txt
@@ -0,0 +1,91 @@
+
+ BTRFS
+ =====
+
+Btrfs is a new copy on write filesystem for Linux aimed at
+implementing advanced features while focusing on fault tolerance,
+repair and easy administration. Initially developed by Oracle, Btrfs
+is licensed under the GPL and open for contribution from anyone.
+
+Linux has a wealth of filesystems to choose from, but we are facing a
+number of challenges with scaling to the large storage subsystems that
+are becoming common in today's data centers. Filesystems need to scale
+in their ability to address and manage large storage, and also in
+their ability to detect, repair and tolerate errors in the data stored
+on disk. Btrfs is under heavy development, and is not suitable for
+any uses other than benchmarking and review. The Btrfs disk format is
+not yet finalized.
+
+The main Btrfs features include:
+
+ * Extent based file storage (2^64 max file size)
+ * Space efficient packing of small files
+ * Space efficient indexed directories
+ * Dynamic inode allocation
+ * Writable snapshots
+ * Subvolumes (separate internal filesystem roots)
+ * Object level mirroring and striping
+ * Checksums on data and metadata (multiple algorithms available)
+ * Compression
+ * Integrated multiple device support, with several raid algorithms
+ * Online filesystem check (not yet implemented)
+ * Very fast offline filesystem check
+ * Efficient incremental backup and FS mirroring (not yet implemented)
+ * Online filesystem defragmentation
+
+
+
+ MAILING LIST
+ ============
+
+There is a Btrfs mailing list hosted on vger.kernel.org. You can
+find details on how to subscribe here:
+
+http://vger.kernel.org/vger-lists.html#linux-btrfs
+
+Mailing list archives are available from gmane:
+
+http://dir.gmane.org/gmane.comp.file-systems.btrfs
+
+
+
+ IRC
+ ===
+
+Discussion of Btrfs also occurs on the #btrfs channel of the Freenode
+IRC network.
+
+
+
+ UTILITIES
+ =========
+
+Userspace tools for creating and manipulating Btrfs file systems are
+available from the git repository at the following location:
+
+ http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs-unstable.git
+ git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git
+
+These include the following tools:
+
+mkfs.btrfs: create a filesystem
+
+btrfsctl: control program to create snapshots and subvolumes:
+
+ mount /dev/sda2 /mnt
+ btrfsctl -s new_subvol_name /mnt
+ btrfsctl -s snapshot_of_default /mnt/default
+ btrfsctl -s snapshot_of_new_subvol /mnt/new_subvol_name
+ btrfsctl -s snapshot_of_a_snapshot /mnt/snapshot_of_new_subvol
+ ls /mnt
+ default snapshot_of_a_snapshot snapshot_of_new_subvol
+ new_subvol_name snapshot_of_default
+
+ Snapshots and subvolumes cannot be deleted right now, but you can
+ rm -rf all the files and directories inside them.
+
+btrfsck: do a limited check of the FS extent trees.
+
+btrfs-debug-tree: print all of the FS metadata in text form. Example:
+
+ btrfs-debug-tree /dev/sda2 >& big_output_file
diff --git a/Documentation/filesystems/devpts.txt b/Documentation/filesystems/devpts.txt
new file mode 100644
index 000000000000..68dffd87f9b7
--- /dev/null
+++ b/Documentation/filesystems/devpts.txt
@@ -0,0 +1,132 @@
+
+To support containers, we now allow multiple instances of devpts filesystem,
+such that indices of ptys allocated in one instance are independent of indices
+allocated in other instances of devpts.
+
+To preserve backward compatibility, this support for multiple instances is
+enabled only if:
+
+ - CONFIG_DEVPTS_MULTIPLE_INSTANCES=y, and
+ - '-o newinstance' mount option is specified while mounting devpts
+
+IOW, devpts now supports both single-instance and multi-instance semantics.
+
+If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, there is no change in behavior and
+this referred to as the "legacy" mode. In this mode, the new mount options
+(-o newinstance and -o ptmxmode) will be ignored with a 'bogus option' message
+on console.
+
+If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and devpts is mounted without the
+'newinstance' option (as in current start-up scripts) the new mount binds
+to the initial kernel mount of devpts. This mode is referred to as the
+'single-instance' mode and the current, single-instance semantics are
+preserved, i.e PTYs are common across the system.
+
+The only difference between this single-instance mode and the legacy mode
+is the presence of new, '/dev/pts/ptmx' node with permissions 0000, which
+can safely be ignored.
+
+If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and 'newinstance' option is specified,
+the mount is considered to be in the multi-instance mode and a new instance
+of the devpts fs is created. Any ptys created in this instance are independent
+of ptys in other instances of devpts. Like in the single-instance mode, the
+/dev/pts/ptmx node is present. To effectively use the multi-instance mode,
+open of /dev/ptmx must be a redirected to '/dev/pts/ptmx' using a symlink or
+bind-mount.
+
+Eg: A container startup script could do the following:
+
+ $ chmod 0666 /dev/pts/ptmx
+ $ rm /dev/ptmx
+ $ ln -s pts/ptmx /dev/ptmx
+ $ ns_exec -cm /bin/bash
+
+ # We are now in new container
+
+ $ umount /dev/pts
+ $ mount -t devpts -o newinstance lxcpts /dev/pts
+ $ sshd -p 1234
+
+where 'ns_exec -cm /bin/bash' calls clone() with CLONE_NEWNS flag and execs
+/bin/bash in the child process. A pty created by the sshd is not visible in
+the original mount of /dev/pts.
+
+User-space changes
+------------------
+
+In multi-instance mode (i.e '-o newinstance' mount option is specified at least
+once), following user-space issues should be noted.
+
+1. If -o newinstance mount option is never used, /dev/pts/ptmx can be ignored
+ and no change is needed to system-startup scripts.
+
+2. To effectively use multi-instance mode (i.e -o newinstance is specified)
+ administrators or startup scripts should "redirect" open of /dev/ptmx to
+ /dev/pts/ptmx using either a bind mount or symlink.
+
+ $ mount -t devpts -o newinstance devpts /dev/pts
+
+ followed by either
+
+ $ rm /dev/ptmx
+ $ ln -s pts/ptmx /dev/ptmx
+ $ chmod 666 /dev/pts/ptmx
+ or
+ $ mount -o bind /dev/pts/ptmx /dev/ptmx
+
+3. The '/dev/ptmx -> pts/ptmx' symlink is the preferred method since it
+ enables better error-reporting and treats both single-instance and
+ multi-instance mounts similarly.
+
+ But this method requires that system-startup scripts set the mode of
+ /dev/pts/ptmx correctly (default mode is 0000). The scripts can set the
+ mode by, either
+
+ - adding ptmxmode mount option to devpts entry in /etc/fstab, or
+ - using 'chmod 0666 /dev/pts/ptmx'
+
+4. If multi-instance mode mount is needed for containers, but the system
+ startup scripts have not yet been updated, container-startup scripts
+ should bind mount /dev/ptmx to /dev/pts/ptmx to avoid breaking single-
+ instance mounts.
+
+ Or, in general, container-startup scripts should use:
+
+ mount -t devpts -o newinstance -o ptmxmode=0666 devpts /dev/pts
+ if [ ! -L /dev/ptmx ]; then
+ mount -o bind /dev/pts/ptmx /dev/ptmx
+ fi
+
+ When all devpts mounts are multi-instance, /dev/ptmx can permanently be
+ a symlink to pts/ptmx and the bind mount can be ignored.
+
+5. A multi-instance mount that is not accompanied by the /dev/ptmx to
+ /dev/pts/ptmx redirection would result in an unusable/unreachable pty.
+
+ mount -t devpts -o newinstance lxcpts /dev/pts
+
+ immediately followed by:
+
+ open("/dev/ptmx")
+
+ would create a pty, say /dev/pts/7, in the initial kernel mount.
+ But /dev/pts/7 would be invisible in the new mount.
+
+6. The permissions for /dev/pts/ptmx node should be specified when mounting
+ /dev/pts, using the '-o ptmxmode=%o' mount option (default is 0000).
+
+ mount -t devpts -o newinstance -o ptmxmode=0644 devpts /dev/pts
+
+ The permissions can be later be changed as usual with 'chmod'.
+
+ chmod 666 /dev/pts/ptmx
+
+7. A mount of devpts without the 'newinstance' option results in binding to
+ initial kernel mount. This behavior while preserving legacy semantics,
+ does not provide strict isolation in a container environment. i.e by
+ mounting devpts without the 'newinstance' option, a container could
+ get visibility into the 'host' or root container's devpts.
+
+ To workaround this and have strict isolation, all mounts of devpts,
+ including the mount in the root container, should use the newinstance
+ option.
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index 174eaff7ded9..cec829bc7291 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -58,13 +58,22 @@ Note: More extensive information for getting started with ext4 can be
# mount -t ext4 /dev/hda1 /wherever
- - When comparing performance with other filesystems, remember that
- ext3/4 by default offers higher data integrity guarantees than most.
- So when comparing with a metadata-only journalling filesystem, such
- as ext3, use `mount -o data=writeback'. And you might as well use
- `mount -o nobh' too along with it. Making the journal larger than
- the mke2fs default often helps performance with metadata-intensive
- workloads.
+ - When comparing performance with other filesystems, it's always
+ important to try multiple workloads; very often a subtle change in a
+ workload parameter can completely change the ranking of which
+ filesystems do well compared to others. When comparing versus ext3,
+ note that ext4 enables write barriers by default, while ext3 does
+ not enable write barriers by default. So it is useful to use
+ explicitly specify whether barriers are enabled or not when via the
+ '-o barriers=[0|1]' mount option for both ext3 and ext4 filesystems
+ for a fair comparison. When tuning ext3 for best benchmark numbers,
+ it is often worthwhile to try changing the data journaling mode; '-o
+ data=writeback,nobh' can be faster for some workloads. (Note
+ however that running mounted with data=writeback can potentially
+ leave stale data exposed in recently written files in case of an
+ unclean shutdown, which could be a security exposure in some
+ situations.) Configuring the filesystem with a large journal can
+ also be helpful for metadata-intensive workloads.
2. Features
===========
@@ -74,7 +83,7 @@ Note: More extensive information for getting started with ext4 can be
* ability to use filesystems > 16TB (e2fsprogs support not available yet)
* extent format reduces metadata overhead (RAM, IO for access, transactions)
* extent format more robust in face of on-disk corruption due to magics,
-* internal redunancy in tree
+* internal redundancy in tree
* improved file allocation (multi-block alloc)
* fix 32000 subdirectory limit
* nsec timestamps for mtime, atime, ctime, create time
@@ -116,10 +125,11 @@ grouping of bitmaps and inode tables. Some test results available here:
When mounting an ext4 filesystem, the following option are accepted:
(*) == default
-extents (*) ext4 will use extents to address file data. The
- file system will no longer be mountable by ext3.
-
-noextents ext4 will not use extents for newly created files
+ro Mount filesystem read only. Note that ext4 will
+ replay the journal (and thus write to the
+ partition) even when mounted "read only". The
+ mount options "ro,noload" can be used to prevent
+ writes to the filesystem.
journal_checksum Enable checksumming of the journal transactions.
This will allow the recovery code in e2fsck and the
@@ -134,17 +144,17 @@ journal_async_commit Commit block can be written to disk without waiting
journal=update Update the ext4 file system's journal to the current
format.
-journal=inum When a journal already exists, this option is ignored.
- Otherwise, it specifies the number of the inode which
- will represent the ext4 file system's journal file.
-
journal_dev=devnum When the external journal device's major/minor numbers
have changed, this option allows the user to specify
the new journal location. The journal device is
identified through its new major/minor numbers encoded
in devnum.
-noload Don't load the journal on mounting.
+noload Don't load the journal on mounting. Note that
+ if the filesystem was not unmounted cleanly,
+ skipping the journal replay will lead to the
+ filesystem containing inconsistencies that can
+ lead to any number of problems.
data=journal All data are committed into the journal prior to being
written into the main file system.
@@ -219,9 +229,12 @@ minixdf Make 'df' act like Minix.
debug Extra debugging information is sent to syslog.
-errors=remount-ro(*) Remount the filesystem read-only on an error.
+errors=remount-ro Remount the filesystem read-only on an error.
errors=continue Keep going on a filesystem error.
errors=panic Panic and halt the machine if an error occurs.
+ (These mount options override the errors behavior
+ specified in the superblock, which can be configured
+ using tune2fs)
data_err=ignore(*) Just print an error message if an error occurs
in a file data buffer in ordered mode.
@@ -261,6 +274,42 @@ delalloc (*) Deferring block allocation until write-out time.
nodelalloc Disable delayed allocation. Blocks are allocation
when data is copied from user to page cache.
+max_batch_time=usec Maximum amount of time ext4 should wait for
+ additional filesystem operations to be batch
+ together with a synchronous write operation.
+ Since a synchronous write operation is going to
+ force a commit and then a wait for the I/O
+ complete, it doesn't cost much, and can be a
+ huge throughput win, we wait for a small amount
+ of time to see if any other transactions can
+ piggyback on the synchronous write. The
+ algorithm used is designed to automatically tune
+ for the speed of the disk, by measuring the
+ amount of time (on average) that it takes to
+ finish committing a transaction. Call this time
+ the "commit time". If the time that the
+ transactoin has been running is less than the
+ commit time, ext4 will try sleeping for the
+ commit time to see if other operations will join
+ the transaction. The commit time is capped by
+ the max_batch_time, which defaults to 15000us
+ (15ms). This optimization can be turned off
+ entirely by setting max_batch_time to 0.
+
+min_batch_time=usec This parameter sets the commit time (as
+ described above) to be at least min_batch_time.
+ It defaults to zero microseconds. Increasing
+ this parameter may improve the throughput of
+ multi-threaded, synchronous workloads on very
+ fast disks, at the cost of increasing latency.
+
+journal_ioprio=prio The I/O priority (from 0 to 7, where 0 is the
+ highest priorty) which should be used for I/O
+ operations submitted by kjournald2 during a
+ commit operation. This defaults to 3, which is
+ a slightly higher priority than the default I/O
+ priority.
+
Data Mode
=========
There are 3 different data modes:
diff --git a/Documentation/filesystems/files.txt b/Documentation/filesystems/files.txt
index bb0142f61084..ac2facc50d2a 100644
--- a/Documentation/filesystems/files.txt
+++ b/Documentation/filesystems/files.txt
@@ -76,13 +76,13 @@ the fdtable structure -
5. Handling of the file structures is special. Since the look-up
of the fd (fget()/fget_light()) are lock-free, it is possible
that look-up may race with the last put() operation on the
- file structure. This is avoided using atomic_inc_not_zero()
+ file structure. This is avoided using atomic_long_inc_not_zero()
on ->f_count :
rcu_read_lock();
file = fcheck_files(files, fd);
if (file) {
- if (atomic_inc_not_zero(&file->f_count))
+ if (atomic_long_inc_not_zero(&file->f_count))
*fput_needed = 1;
else
/* Didn't get the reference, someone's freed */
@@ -92,7 +92,7 @@ the fdtable structure -
....
return file;
- atomic_inc_not_zero() detects if refcounts is already zero or
+ atomic_long_inc_not_zero() detects if refcounts is already zero or
goes to zero during increment. If it does, we fail
fget()/fget_light().
diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt
index 44bd766f2e5d..85eaeaddd27c 100644
--- a/Documentation/filesystems/nfs-rdma.txt
+++ b/Documentation/filesystems/nfs-rdma.txt
@@ -251,7 +251,7 @@ NFS/RDMA Setup
Instruct the server to listen on the RDMA transport:
- $ echo rdma 2050 > /proc/fs/nfsd/portlist
+ $ echo rdma 20049 > /proc/fs/nfsd/portlist
- On the client system
@@ -263,7 +263,7 @@ NFS/RDMA Setup
Regardless of how the client was built (module or built-in), use this
command to mount the NFS/RDMA server:
- $ mount -o rdma,port=2050 <IPoIB-server-name-or-address>:/<export> /mnt
+ $ mount -o rdma,port=20049 <IPoIB-server-name-or-address>:/<export> /mnt
To verify that the mount is using RDMA, run "cat /proc/mounts" and check
the "proto" field for the given mount.
diff --git a/Documentation/filesystems/ocfs2.txt b/Documentation/filesystems/ocfs2.txt
index 67310fbbb7df..c2a0871280a0 100644
--- a/Documentation/filesystems/ocfs2.txt
+++ b/Documentation/filesystems/ocfs2.txt
@@ -31,7 +31,6 @@ Features which OCFS2 does not support yet:
- quotas
- Directory change notification (F_NOTIFY)
- Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
- - POSIX ACLs
Mount options
=============
@@ -79,3 +78,5 @@ inode64 Indicates that Ocfs2 is allowed to create inodes at
bits of significance.
user_xattr (*) Enables Extended User Attributes.
nouser_xattr Disables Extended User Attributes.
+acl Enables POSIX Access Control Lists support.
+noacl (*) Disables POSIX Access Control Lists support.
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 71df353e367c..a87be42f8211 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -140,6 +140,7 @@ Table 1-1: Process specific entries in /proc
statm Process memory status information
status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
+ stack Report full stack trace, enable via CONFIG_STACKTRACE
smaps Extension based on maps, the rss size for each mapped file
..............................................................................
@@ -1370,268 +1371,8 @@ auto_msgmni default value is 1.
2.4 /proc/sys/vm - The virtual memory subsystem
-----------------------------------------------
-The files in this directory can be used to tune the operation of the virtual
-memory (VM) subsystem of the Linux kernel.
-
-vfs_cache_pressure
-------------------
-
-Controls the tendency of the kernel to reclaim the memory which is used for
-caching of directory and inode objects.
-
-At the default value of vfs_cache_pressure=100 the kernel will attempt to
-reclaim dentries and inodes at a "fair" rate with respect to pagecache and
-swapcache reclaim. Decreasing vfs_cache_pressure causes the kernel to prefer
-to retain dentry and inode caches. Increasing vfs_cache_pressure beyond 100
-causes the kernel to prefer to reclaim dentries and inodes.
-
-dirty_background_ratio
-----------------------
-
-Contains, as a percentage of the dirtyable system memory (free pages + mapped
-pages + file cache, not including locked pages and HugePages), the number of
-pages at which the pdflush background writeback daemon will start writing out
-dirty data.
-
-dirty_ratio
------------------
-
-Contains, as a percentage of the dirtyable system memory (free pages + mapped
-pages + file cache, not including locked pages and HugePages), the number of
-pages at which a process which is generating disk writes will itself start
-writing out dirty data.
-
-dirty_writeback_centisecs
--------------------------
-
-The pdflush writeback daemons will periodically wake up and write `old' data
-out to disk. This tunable expresses the interval between those wakeups, in
-100'ths of a second.
-
-Setting this to zero disables periodic writeback altogether.
-
-dirty_expire_centisecs
-----------------------
-
-This tunable is used to define when dirty data is old enough to be eligible
-for writeout by the pdflush daemons. It is expressed in 100'ths of a second.
-Data which has been dirty in-memory for longer than this interval will be
-written out next time a pdflush daemon wakes up.
-
-highmem_is_dirtyable
---------------------
-
-Only present if CONFIG_HIGHMEM is set.
-
-This defaults to 0 (false), meaning that the ratios set above are calculated
-as a percentage of lowmem only. This protects against excessive scanning
-in page reclaim, swapping and general VM distress.
-
-Setting this to 1 can be useful on 32 bit machines where you want to make
-random changes within an MMAPed file that is larger than your available
-lowmem without causing large quantities of random IO. Is is safe if the
-behavior of all programs running on the machine is known and memory will
-not be otherwise stressed.
-
-legacy_va_layout
-----------------
-
-If non-zero, this sysctl disables the new 32-bit mmap mmap layout - the kernel
-will use the legacy (2.4) layout for all processes.
-
-lowmem_reserve_ratio
----------------------
-
-For some specialised workloads on highmem machines it is dangerous for
-the kernel to allow process memory to be allocated from the "lowmem"
-zone. This is because that memory could then be pinned via the mlock()
-system call, or by unavailability of swapspace.
-
-And on large highmem machines this lack of reclaimable lowmem memory
-can be fatal.
-
-So the Linux page allocator has a mechanism which prevents allocations
-which _could_ use highmem from using too much lowmem. This means that
-a certain amount of lowmem is defended from the possibility of being
-captured into pinned user memory.
-
-(The same argument applies to the old 16 megabyte ISA DMA region. This
-mechanism will also defend that region from allocations which could use
-highmem or lowmem).
-
-The `lowmem_reserve_ratio' tunable determines how aggressive the kernel is
-in defending these lower zones.
-
-If you have a machine which uses highmem or ISA DMA and your
-applications are using mlock(), or if you are running with no swap then
-you probably should change the lowmem_reserve_ratio setting.
-
-The lowmem_reserve_ratio is an array. You can see them by reading this file.
--
-% cat /proc/sys/vm/lowmem_reserve_ratio
-256 256 32
--
-Note: # of this elements is one fewer than number of zones. Because the highest
- zone's value is not necessary for following calculation.
-
-But, these values are not used directly. The kernel calculates # of protection
-pages for each zones from them. These are shown as array of protection pages
-in /proc/zoneinfo like followings. (This is an example of x86-64 box).
-Each zone has an array of protection pages like this.
-
--
-Node 0, zone DMA
- pages free 1355
- min 3
- low 3
- high 4
- :
- :
- numa_other 0
- protection: (0, 2004, 2004, 2004)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- pagesets
- cpu: 0 pcp: 0
- :
--
-These protections are added to score to judge whether this zone should be used
-for page allocation or should be reclaimed.
-
-In this example, if normal pages (index=2) are required to this DMA zone and
-pages_high is used for watermark, the kernel judges this zone should not be
-used because pages_free(1355) is smaller than watermark + protection[2]
-(4 + 2004 = 2008). If this protection value is 0, this zone would be used for
-normal page requirement. If requirement is DMA zone(index=0), protection[0]
-(=0) is used.
-
-zone[i]'s protection[j] is calculated by following expression.
-
-(i < j):
- zone[i]->protection[j]
- = (total sums of present_pages from zone[i+1] to zone[j] on the node)
- / lowmem_reserve_ratio[i];
-(i = j):
- (should not be protected. = 0;
-(i > j):
- (not necessary, but looks 0)
-
-The default values of lowmem_reserve_ratio[i] are
- 256 (if zone[i] means DMA or DMA32 zone)
- 32 (others).
-As above expression, they are reciprocal number of ratio.
-256 means 1/256. # of protection pages becomes about "0.39%" of total present
-pages of higher zones on the node.
-
-If you would like to protect more pages, smaller values are effective.
-The minimum value is 1 (1/1 -> 100%).
-
-page-cluster
-------------
-
-page-cluster controls the number of pages which are written to swap in
-a single attempt. The swap I/O size.
-
-It is a logarithmic value - setting it to zero means "1 page", setting
-it to 1 means "2 pages", setting it to 2 means "4 pages", etc.
-
-The default value is three (eight pages at a time). There may be some
-small benefits in tuning this to a different value if your workload is
-swap-intensive.
-
-overcommit_memory
------------------
-
-Controls overcommit of system memory, possibly allowing processes
-to allocate (but not use) more memory than is actually available.
-
-
-0 - Heuristic overcommit handling. Obvious overcommits of
- address space are refused. Used for a typical system. It
- ensures a seriously wild allocation fails while allowing
- overcommit to reduce swap usage. root is allowed to
- allocate slightly more memory in this mode. This is the
- default.
-
-1 - Always overcommit. Appropriate for some scientific
- applications.
-
-2 - Don't overcommit. The total address space commit
- for the system is not permitted to exceed swap plus a
- configurable percentage (default is 50) of physical RAM.
- Depending on the percentage you use, in most situations
- this means a process will not be killed while attempting
- to use already-allocated memory but will receive errors
- on memory allocation as appropriate.
-
-overcommit_ratio
-----------------
-
-Percentage of physical memory size to include in overcommit calculations
-(see above.)
-
-Memory allocation limit = swapspace + physmem * (overcommit_ratio / 100)
-
- swapspace = total size of all swap areas
- physmem = size of physical memory in system
-
-nr_hugepages and hugetlb_shm_group
-----------------------------------
-
-nr_hugepages configures number of hugetlb page reserved for the system.
-
-hugetlb_shm_group contains group id that is allowed to create SysV shared
-memory segment using hugetlb page.
-
-hugepages_treat_as_movable
---------------------------
-
-This parameter is only useful when kernelcore= is specified at boot time to
-create ZONE_MOVABLE for pages that may be reclaimed or migrated. Huge pages
-are not movable so are not normally allocated from ZONE_MOVABLE. A non-zero
-value written to hugepages_treat_as_movable allows huge pages to be allocated
-from ZONE_MOVABLE.
-
-Once enabled, the ZONE_MOVABLE is treated as an area of memory the huge
-pages pool can easily grow or shrink within. Assuming that applications are
-not running that mlock() a lot of memory, it is likely the huge pages pool
-can grow to the size of ZONE_MOVABLE by repeatedly entering the desired value
-into nr_hugepages and triggering page reclaim.
-
-laptop_mode
------------
-
-laptop_mode is a knob that controls "laptop mode". All the things that are
-controlled by this knob are discussed in Documentation/laptops/laptop-mode.txt.
-
-block_dump
-----------
-
-block_dump enables block I/O debugging when set to a nonzero value. More
-information on block I/O debugging is in Documentation/laptops/laptop-mode.txt.
-
-swap_token_timeout
-------------------
-
-This file contains valid hold time of swap out protection token. The Linux
-VM has token based thrashing control mechanism and uses the token to prevent
-unnecessary page faults in thrashing situation. The unit of the value is
-second. The value would be useful to tune thrashing behavior.
-
-drop_caches
------------
-
-Writing to this will cause the kernel to drop clean caches, dentries and
-inodes from memory, causing that memory to become free.
-
-To free pagecache:
- echo 1 > /proc/sys/vm/drop_caches
-To free dentries and inodes:
- echo 2 > /proc/sys/vm/drop_caches
-To free pagecache, dentries and inodes:
- echo 3 > /proc/sys/vm/drop_caches
-
-As this is a non-destructive operation and dirty objects are not freeable, the
-user should run `sync' first.
+Please see: Documentation/sysctls/vm.txt for a description of these
+entries.
2.5 /proc/sys/dev - Device specific parameters
@@ -2286,6 +2027,34 @@ increase the likelihood of this process being killed by the oom-killer. Valid
values are in the range -16 to +15, plus the special value -17, which disables
oom-killing altogether for this process.
+The process to be killed in an out-of-memory situation is selected among all others
+based on its badness score. This value equals the original memory size of the process
+and is then updated according to its CPU time (utime + stime) and the
+run time (uptime - start time). The longer it runs the smaller is the score.
+Badness score is divided by the square root of the CPU time and then by
+the double square root of the run time.
+
+Swapped out tasks are killed first. Half of each child's memory size is added to
+the parent's score if they do not share the same memory. Thus forking servers
+are the prime candidates to be killed. Having only one 'hungry' child will make
+parent less preferable than the child.
+
+/proc/<pid>/oom_score shows process' current badness score.
+
+The following heuristics are then applied:
+ * if the task was reniced, its score doubles
+ * superuser or direct hardware access tasks (CAP_SYS_ADMIN, CAP_SYS_RESOURCE
+ or CAP_SYS_RAWIO) have their score divided by 4
+ * if oom condition happened in one cpuset and checked task does not belong
+ to it, its score is divided by 8
+ * the resulting score is multiplied by two to the power of oom_adj, i.e.
+ points <<= oom_adj when it is positive and
+ points >>= -(oom_adj) otherwise
+
+The task with the highest badness score is then selected and its children
+are killed, process itself will be killed in an OOM situation when it does
+not have children or some of them disabled oom like described above.
+
2.13 /proc/<pid>/oom_score - Display current oom-killer score
-------------------------------------------------------------
diff --git a/Documentation/filesystems/squashfs.txt b/Documentation/filesystems/squashfs.txt
new file mode 100644
index 000000000000..3e79e4a7a392
--- /dev/null
+++ b/Documentation/filesystems/squashfs.txt
@@ -0,0 +1,225 @@
+SQUASHFS 4.0 FILESYSTEM
+=======================
+
+Squashfs is a compressed read-only filesystem for Linux.
+It uses zlib compression to compress files, inodes and directories.
+Inodes in the system are very small and all blocks are packed to minimise
+data overhead. Block sizes greater than 4K are supported up to a maximum
+of 1Mbytes (default block size 128K).
+
+Squashfs is intended for general read-only filesystem use, for archival
+use (i.e. in cases where a .tar.gz file may be used), and in constrained
+block device/memory systems (e.g. embedded systems) where low overhead is
+needed.
+
+Mailing list: squashfs-devel@lists.sourceforge.net
+Web site: www.squashfs.org
+
+1. FILESYSTEM FEATURES
+----------------------
+
+Squashfs filesystem features versus Cramfs:
+
+ Squashfs Cramfs
+
+Max filesystem size: 2^64 16 MiB
+Max file size: ~ 2 TiB 16 MiB
+Max files: unlimited unlimited
+Max directories: unlimited unlimited
+Max entries per directory: unlimited unlimited
+Max block size: 1 MiB 4 KiB
+Metadata compression: yes no
+Directory indexes: yes no
+Sparse file support: yes no
+Tail-end packing (fragments): yes no
+Exportable (NFS etc.): yes no
+Hard link support: yes no
+"." and ".." in readdir: yes no
+Real inode numbers: yes no
+32-bit uids/gids: yes no
+File creation time: yes no
+Xattr and ACL support: no no
+
+Squashfs compresses data, inodes and directories. In addition, inode and
+directory data are highly compacted, and packed on byte boundaries. Each
+compressed inode is on average 8 bytes in length (the exact length varies on
+file type, i.e. regular file, directory, symbolic link, and block/char device
+inodes have different sizes).
+
+2. USING SQUASHFS
+-----------------
+
+As squashfs is a read-only filesystem, the mksquashfs program must be used to
+create populated squashfs filesystems. This and other squashfs utilities
+can be obtained from http://www.squashfs.org. Usage instructions can be
+obtained from this site also.
+
+
+3. SQUASHFS FILESYSTEM DESIGN
+-----------------------------
+
+A squashfs filesystem consists of seven parts, packed together on a byte
+alignment:
+
+ ---------------
+ | superblock |
+ |---------------|
+ | datablocks |
+ | & fragments |
+ |---------------|
+ | inode table |
+ |---------------|
+ | directory |
+ | table |
+ |---------------|
+ | fragment |
+ | table |
+ |---------------|
+ | export |
+ | table |
+ |---------------|
+ | uid/gid |
+ | lookup table |
+ ---------------
+
+Compressed data blocks are written to the filesystem as files are read from
+the source directory, and checked for duplicates. Once all file data has been
+written the completed inode, directory, fragment, export and uid/gid lookup
+tables are written.
+
+3.1 Inodes
+----------
+
+Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each
+compressed block is prefixed by a two byte length, the top bit is set if the
+block is uncompressed. A block will be uncompressed if the -noI option is set,
+or if the compressed block was larger than the uncompressed block.
+
+Inodes are packed into the metadata blocks, and are not aligned to block
+boundaries, therefore inodes overlap compressed blocks. Inodes are identified
+by a 48-bit number which encodes the location of the compressed metadata block
+containing the inode, and the byte offset into that block where the inode is
+placed (<block, offset>).
+
+To maximise compression there are different inodes for each file type
+(regular file, directory, device, etc.), the inode contents and length
+varying with the type.
+
+To further maximise compression, two types of regular file inode and
+directory inode are defined: inodes optimised for frequently occurring
+regular files and directories, and extended types where extra
+information has to be stored.
+
+3.2 Directories
+---------------
+
+Like inodes, directories are packed into compressed metadata blocks, stored
+in a directory table. Directories are accessed using the start address of
+the metablock containing the directory and the offset into the
+decompressed block (<block, offset>).
+
+Directories are organised in a slightly complex way, and are not simply
+a list of file names. The organisation takes advantage of the
+fact that (in most cases) the inodes of the files will be in the same
+compressed metadata block, and therefore, can share the start block.
+Directories are therefore organised in a two level list, a directory
+header containing the shared start block value, and a sequence of directory
+entries, each of which share the shared start block. A new directory header
+is written once/if the inode start block changes. The directory
+header/directory entry list is repeated as many times as necessary.
+
+Directories are sorted, and can contain a directory index to speed up
+file lookup. Directory indexes store one entry per metablock, each entry
+storing the index/filename mapping to the first directory header
+in each metadata block. Directories are sorted in alphabetical order,
+and at lookup the index is scanned linearly looking for the first filename
+alphabetically larger than the filename being looked up. At this point the
+location of the metadata block the filename is in has been found.
+The general idea of the index is ensure only one metadata block needs to be
+decompressed to do a lookup irrespective of the length of the directory.
+This scheme has the advantage that it doesn't require extra memory overhead
+and doesn't require much extra storage on disk.
+
+3.3 File data
+-------------
+
+Regular files consist of a sequence of contiguous compressed blocks, and/or a
+compressed fragment block (tail-end packed block). The compressed size
+of each datablock is stored in a block list contained within the
+file inode.
+
+To speed up access to datablocks when reading 'large' files (256 Mbytes or
+larger), the code implements an index cache that caches the mapping from
+block index to datablock location on disk.
+
+The index cache allows Squashfs to handle large files (up to 1.75 TiB) while
+retaining a simple and space-efficient block list on disk. The cache
+is split into slots, caching up to eight 224 GiB files (128 KiB blocks).
+Larger files use multiple slots, with 1.75 TiB files using all 8 slots.
+The index cache is designed to be memory efficient, and by default uses
+16 KiB.
+
+3.4 Fragment lookup table
+-------------------------
+
+Regular files can contain a fragment index which is mapped to a fragment
+location on disk and compressed size using a fragment lookup table. This
+fragment lookup table is itself stored compressed into metadata blocks.
+A second index table is used to locate these. This second index table for
+speed of access (and because it is small) is read at mount time and cached
+in memory.
+
+3.5 Uid/gid lookup table
+------------------------
+
+For space efficiency regular files store uid and gid indexes, which are
+converted to 32-bit uids/gids using an id look up table. This table is
+stored compressed into metadata blocks. A second index table is used to
+locate these. This second index table for speed of access (and because it
+is small) is read at mount time and cached in memory.
+
+3.6 Export table
+----------------
+
+To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems
+can optionally (disabled with the -no-exports Mksquashfs option) contain
+an inode number to inode disk location lookup table. This is required to
+enable Squashfs to map inode numbers passed in filehandles to the inode
+location on disk, which is necessary when the export code reinstantiates
+expired/flushed inodes.
+
+This table is stored compressed into metadata blocks. A second index table is
+used to locate these. This second index table for speed of access (and because
+it is small) is read at mount time and cached in memory.
+
+
+4. TODOS AND OUTSTANDING ISSUES
+-------------------------------
+
+4.1 Todo list
+-------------
+
+Implement Xattr and ACL support. The Squashfs 4.0 filesystem layout has hooks
+for these but the code has not been written. Once the code has been written
+the existing layout should not require modification.
+
+4.2 Squashfs internal cache
+---------------------------
+
+Blocks in Squashfs are compressed. To avoid repeatedly decompressing
+recently accessed data Squashfs uses two small metadata and fragment caches.
+
+The cache is not used for file datablocks, these are decompressed and cached in
+the page-cache in the normal way. The cache is used to temporarily cache
+fragment and metadata blocks which have been read as a result of a metadata
+(i.e. inode or directory) or fragment access. Because metadata and fragments
+are packed together into blocks (to gain greater compression) the read of a
+particular piece of metadata or fragment will retrieve other metadata/fragments
+which have been packed with it, these because of locality-of-reference may be
+read in the near future. Temporarily caching them ensures they are available
+for near future access without requiring an additional read and decompress.
+
+In the future this internal cache may be replaced with an implementation which
+uses the kernel page cache. Because the page cache operates on page sized
+units this may introduce additional complexity in terms of locking and
+associated race conditions.
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
index dd84ea3c10da..12fedb7834c6 100644
--- a/Documentation/filesystems/ubifs.txt
+++ b/Documentation/filesystems/ubifs.txt
@@ -79,13 +79,6 @@ Mount options
(*) == default.
-norm_unmount (*) commit on unmount; the journal is committed
- when the file-system is unmounted so that the
- next mount does not have to replay the journal
- and it becomes very fast;
-fast_unmount do not commit on unmount; this option makes
- unmount faster, but the next mount slower
- because of the need to replay the journal.
bulk_read read more in one go to take advantage of flash
media that read faster sequentially
no_bulk_read (*) do not bulk-read
@@ -95,6 +88,9 @@ no_chk_data_crc skip checking of CRCs on data nodes in order to
of this option is that corruption of the contents
of a file can go unnoticed.
chk_data_crc (*) do not skip checking CRCs on data nodes
+compr=none override default compressor and set it to "none"
+compr=lzo override default compressor and set it to "lzo"
+compr=zlib override default compressor and set it to "zlib"
Quick usage instructions
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 5579bda58a6d..deeeed0faa8f 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -210,8 +210,8 @@ struct super_operations {
void (*put_super) (struct super_block *);
void (*write_super) (struct super_block *);
int (*sync_fs)(struct super_block *sb, int wait);
- void (*write_super_lockfs) (struct super_block *);
- void (*unlockfs) (struct super_block *);
+ int (*freeze_fs) (struct super_block *);
+ int (*unfreeze_fs) (struct super_block *);
int (*statfs) (struct dentry *, struct kstatfs *);
int (*remount_fs) (struct super_block *, int *, char *);
void (*clear_inode) (struct inode *);
@@ -270,11 +270,11 @@ or bottom half).
a superblock. The second parameter indicates whether the method
should wait until the write out has been completed. Optional.
- write_super_lockfs: called when VFS is locking a filesystem and
+ freeze_fs: called when VFS is locking a filesystem and
forcing it into a consistent state. This method is currently
used by the Logical Volume Manager (LVM).
- unlockfs: called when VFS is unlocking a filesystem and making it writable
+ unfreeze_fs: called when VFS is unlocking a filesystem and making it writable
again.
statfs: called when the VFS needs to get filesystem statistics. This
@@ -733,7 +733,6 @@ struct file_operations {
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
- int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int);
@@ -800,8 +799,6 @@ otherwise noted.
check_flags: called by the fcntl(2) system call for F_SETFL command
- dir_notify: called by the fcntl(2) system call for F_NOTIFY command
-
flock: called by the flock(2) system call
splice_write: called by the VFS to splice data from a pipe to a file. This
@@ -931,7 +928,7 @@ manipulate dentries:
d_lookup: look up a dentry given its parent and path name component
It looks up the child of that given name from the dcache
hash table. If it is found, the reference count is incremented
- and the dentry is returned. The caller must use d_put()
+ and the dentry is returned. The caller must use dput()
to free the dentry when it finishes using it.
For further information on dentry locking, please refer to the document
diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet
index aef5a9b36846..d9251efdcec7 100644
--- a/Documentation/hwmon/abituguru-datasheet
+++ b/Documentation/hwmon/abituguru-datasheet
@@ -74,7 +74,7 @@ a sensor.
Notice that some banks have both a read and a write address this is how the
uGuru determines if a read from or a write to the bank is taking place, thus
when reading you should always use the read address and when writing the
-write address. The write address is always one (1) more then the read address.
+write address. The write address is always one (1) more than the read address.
uGuru ready
@@ -121,7 +121,7 @@ Once all bytes have been read data will hold 0x09, but there is no reason to
test for this. Notice that the number of bytes is bank address dependent see
above and below.
-After completing a successfull read it is advised to put the uGuru back in
+After completing a successful read it is advised to put the uGuru back in
ready mode, so that it is ready for the next read / write cycle. This way
if your program / driver is unloaded and later loaded again the detection
algorithm described above will still work.
@@ -141,7 +141,7 @@ don't ask why this is the way it is.
Once DATA holds 0x01 read CMD it should hold 0xAC now.
-After completing a successfull write it is advised to put the uGuru back in
+After completing a successful write it is advised to put the uGuru back in
ready mode, so that it is ready for the next read / write cycle. This way
if your program / driver is unloaded and later loaded again the detection
algorithm described above will still work.
@@ -224,7 +224,7 @@ Bit 3: Beep if alarm (RW)
Bit 4: 1 if alarm cause measured temp is over the warning threshold (R)
Bit 5: 1 if alarm cause measured volt is over the max threshold (R)
Bit 6: 1 if alarm cause measured volt is under the min threshold (R)
-Bit 7: Volt sensor: Shutdown if alarm persist for more then 4 seconds (RW)
+Bit 7: Volt sensor: Shutdown if alarm persist for more than 4 seconds (RW)
Temp sensor: Shutdown if temp is over the shutdown threshold (RW)
* This bit is only honored/used by the uGuru if a temp sensor is connected
@@ -293,7 +293,7 @@ Byte 0:
Alarm behaviour for the selected sensor. A 1 enables the described behaviour.
Bit 0: Give an alarm if measured rpm is under the min threshold (RW)
Bit 3: Beep if alarm (RW)
-Bit 7: Shutdown if alarm persist for more then 4 seconds (RW)
+Bit 7: Shutdown if alarm persist for more than 4 seconds (RW)
Byte 1:
min threshold (scale as bank 0x26)
diff --git a/Documentation/hwmon/adt7470 b/Documentation/hwmon/adt7470
index 75d13ca147cc..8ce4aa0a0f55 100644
--- a/Documentation/hwmon/adt7470
+++ b/Documentation/hwmon/adt7470
@@ -31,15 +31,11 @@ Each of the measured inputs (temperature, fan speed) has corresponding high/low
limit values. The ADT7470 will signal an ALARM if any measured value exceeds
either limit.
-The ADT7470 DOES NOT sample all inputs continuously. A single pin on the
-ADT7470 is connected to a multitude of thermal diodes, but the chip must be
-instructed explicitly to read the multitude of diodes. If you want to use
-automatic fan control mode, you must manually read any of the temperature
-sensors or the fan control algorithm will not run. The chip WILL NOT DO THIS
-AUTOMATICALLY; this must be done from userspace. This may be a bug in the chip
-design, given that many other AD chips take care of this. The driver will not
-read the registers more often than once every 5 seconds. Further,
-configuration data is only read once per minute.
+The ADT7470 samples all inputs continuously. A kernel thread is started up for
+the purpose of periodically querying the temperature sensors, thus allowing the
+automatic fan pwm control to set the fan speed. The driver will not read the
+registers more often than once every 5 seconds. Further, configuration data is
+only read once per minute.
Special Features
----------------
@@ -72,5 +68,6 @@ pwm#_auto_point2_temp.
Notes
-----
-As stated above, the temperature inputs must be read periodically from
-userspace in order for the automatic pwm algorithm to run.
+The temperature inputs no longer need to be read periodically from userspace in
+order for the automatic pwm algorithm to run. This was the case for earlier
+versions of the driver.
diff --git a/Documentation/hwmon/adt7475 b/Documentation/hwmon/adt7475
new file mode 100644
index 000000000000..a2b1abec850e
--- /dev/null
+++ b/Documentation/hwmon/adt7475
@@ -0,0 +1,87 @@
+This describes the interface for the ADT7475 driver:
+
+(there are 4 fans, numbered fan1 to fan4):
+
+fanX_input Read the current speed of the fan (in RPMs)
+fanX_min Read/write the minimum speed of the fan. Dropping
+ below this sets an alarm.
+
+(there are three PWMs, numbered pwm1 to pwm3):
+
+pwmX Read/write the current duty cycle of the PWM. Writes
+ only have effect when auto mode is turned off (see
+ below). Range is 0 - 255.
+
+pwmX_enable Fan speed control method:
+
+ 0 - No control (fan at full speed)
+ 1 - Manual fan speed control (using pwm[1-*])
+ 2 - Automatic fan speed control
+
+pwmX_auto_channels_temp Select which channels affect this PWM
+
+ 1 - TEMP1 controls PWM
+ 2 - TEMP2 controls PWM
+ 4 - TEMP3 controls PWM
+ 6 - TEMP2 and TEMP3 control PWM
+ 7 - All three inputs control PWM
+
+pwmX_freq Read/write the PWM frequency in Hz. The number
+ should be one of the following:
+
+ 11 Hz
+ 14 Hz
+ 22 Hz
+ 29 Hz
+ 35 Hz
+ 44 Hz
+ 58 Hz
+ 88 Hz
+
+pwmX_auto_point1_pwm Read/write the minimum PWM duty cycle in automatic mode
+
+pwmX_auto_point2_pwm Read/write the maximum PWM duty cycle in automatic mode
+
+(there are three temperature settings numbered temp1 to temp3):
+
+tempX_input Read the current temperature. The value is in milli
+ degrees of Celsius.
+
+tempX_max Read/write the upper temperature limit - exceeding this
+ will cause an alarm.
+
+tempX_min Read/write the lower temperature limit - exceeding this
+ will cause an alarm.
+
+tempX_offset Read/write the temperature adjustment offset
+
+tempX_crit Read/write the THERM limit for remote1.
+
+tempX_crit_hyst Set the temperature value below crit where the
+ fans will stay on - this helps drive the temperature
+ low enough so it doesn't stay near the edge and
+ cause THERM to keep tripping.
+
+tempX_auto_point1_temp Read/write the minimum temperature where the fans will
+ turn on in automatic mode.
+
+tempX_auto_point2_temp Read/write the maximum temperature over which the fans
+ will run in automatic mode. tempX_auto_point1_temp
+ and tempX_auto_point2_temp together define the
+ range of automatic control.
+
+tempX_alarm Read a 1 if the max/min alarm is set
+tempX_fault Read a 1 if either temp1 or temp3 diode has a fault
+
+(There are two voltage settings, in1 and in2):
+
+inX_input Read the current voltage on VCC. Value is in
+ millivolts.
+
+inX_min read/write the minimum voltage limit.
+ Dropping below this causes an alarm.
+
+inX_max read/write the maximum voltage limit.
+ Exceeding this causes an alarm.
+
+inX_alarm Read a 1 if the max/min alarm is set.
diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg
new file mode 100644
index 000000000000..a8321267b5b6
--- /dev/null
+++ b/Documentation/hwmon/f71882fg
@@ -0,0 +1,89 @@
+Kernel driver f71882fg
+======================
+
+Supported chips:
+ * Fintek F71882FG and F71883FG
+ Prefix: 'f71882fg'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: Available from the Fintek website
+ * Fintek F71862FG and F71863FG
+ Prefix: 'f71862fg'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: Available from the Fintek website
+ * Fintek F8000
+ Prefix: 'f8000'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: Not public
+
+Author: Hans de Goede <hdegoede@redhat.com>
+
+
+Description
+-----------
+
+Fintek F718xxFG/F8000 Super I/O chips include complete hardware monitoring
+capabilities. They can monitor up to 9 voltages (3 for the F8000), 4 fans and
+3 temperature sensors.
+
+These chips also have fan controlling features, using either DC or PWM, in
+three different modes (one manual, two automatic).
+
+The driver assumes that no more than one chip is present, which seems
+reasonable.
+
+
+Monitoring
+----------
+
+The Voltage, Fan and Temperature Monitoring uses the standard sysfs
+interface as documented in sysfs-interface, without any exceptions.
+
+
+Fan Control
+-----------
+
+Both PWM (pulse-width modulation) and DC fan speed control methods are
+supported. The right one to use depends on external circuitry on the
+motherboard, so the driver assumes that the BIOS set the method
+properly.
+
+There are 2 modes to specify the speed of the fan, PWM duty cycle (or DC
+voltage) mode, where 0-100% duty cycle (0-100% of 12V) is specified. And RPM
+mode where the actual RPM of the fan (as measured) is controlled and the speed
+gets specified as 0-100% of the fan#_full_speed file.
+
+Since both modes work in a 0-100% (mapped to 0-255) scale, there isn't a
+whole lot of a difference when modifying fan control settings. The only
+important difference is that in RPM mode the 0-100% controls the fan speed
+between 0-100% of fan#_full_speed. It is assumed that if the BIOS programs
+RPM mode, it will also set fan#_full_speed properly, if it does not then
+fan control will not work properly, unless you set a sane fan#_full_speed
+value yourself.
+
+Switching between these modes requires re-initializing a whole bunch of
+registers, so the mode which the BIOS has set is kept. The mode is
+printed when loading the driver.
+
+Three different fan control modes are supported; the mode number is written
+to the pwm#_enable file. Note that not all modes are supported on all
+chips, and some modes may only be available in RPM / PWM mode on the F8000.
+Writing an unsupported mode will result in an invalid parameter error.
+
+* 1: Manual mode
+ You ask for a specific PWM duty cycle / DC voltage or a specific % of
+ fan#_full_speed by writing to the pwm# file. This mode is only
+ available on the F8000 if the fan channel is in RPM mode.
+
+* 2: Normal auto mode
+ You can define a number of temperature/fan speed trip points, which % the
+ fan should run at at this temp and which temp a fan should follow using the
+ standard sysfs interface. The number and type of trip points is chip
+ depended, see which files are available in sysfs.
+ Fan/PWM channel 3 of the F8000 is always in this mode!
+
+* 3: Thermostat mode (Only available on the F8000 when in duty cycle mode)
+ The fan speed is regulated to keep the temp the fan is mapped to between
+ temp#_auto_point2_temp and temp#_auto_point3_temp.
+
+Both of the automatic modes require that pwm1 corresponds to fan1, pwm2 to
+fan2 and pwm3 to fan3.
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index 042c0415140b..659315d98e00 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -26,6 +26,10 @@ Supported chips:
Datasheet: Publicly available at the ITE website
http://www.ite.com.tw/product_info/file/pc/IT8718F_V0.2.zip
http://www.ite.com.tw/product_info/file/pc/IT8718F_V0%203_(for%20C%20version).zip
+ * IT8720F
+ Prefix: 'it8720'
+ Addresses scanned: from Super I/O config space (8 I/O ports)
+ Datasheet: Not yet publicly available.
* SiS950 [clone of IT8705F]
Prefix: 'it87'
Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -71,7 +75,7 @@ Description
-----------
This driver implements support for the IT8705F, IT8712F, IT8716F,
-IT8718F, IT8726F and SiS950 chips.
+IT8718F, IT8720F, IT8726F and SiS950 chips.
These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
joysticks and other miscellaneous stuff. For hardware monitoring, they
@@ -84,19 +88,19 @@ the IT8716F and late IT8712F have 6. They are shared with other functions
though, so the functionality may not be available on a given system.
The driver dumbly assume it is there.
-The IT8718F also features VID inputs (up to 8 pins) but the value is
-stored in the Super-I/O configuration space. Due to technical limitations,
+The IT8718F and IT8720F also features VID inputs (up to 8 pins) but the value
+is stored in the Super-I/O configuration space. Due to technical limitations,
this value can currently only be read once at initialization time, so
the driver won't notice and report changes in the VID value. The two
upper VID bits share their pins with voltage inputs (in5 and in6) so you
can't have both on a given board.
-The IT8716F, IT8718F and later IT8712F revisions have support for
+The IT8716F, IT8718F, IT8720F and later IT8712F revisions have support for
2 additional fans. The additional fans are supported by the driver.
-The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
-16-bit tachometer counters for fans 1 to 3. This is better (no more fan
-clock divider mess) but not compatible with the older chips and
+The IT8716F, IT8718F and IT8720F, and late IT8712F and IT8705F also have
+optional 16-bit tachometer counters for fans 1 to 3. This is better (no more
+fan clock divider mess) but not compatible with the older chips and
revisions. The 16-bit tachometer mode is enabled by the driver when one
of the above chips is detected.
@@ -122,7 +126,7 @@ zero'; this is important for negative voltage measurements. All voltage
inputs can measure voltages between 0 and 4.08 volts, with a resolution of
0.016 volt. The battery voltage in8 does not have limit registers.
-The VID lines (IT8712F/IT8716F/IT8718F) encode the core voltage value:
+The VID lines (IT8712F/IT8716F/IT8718F/IT8720F) encode the core voltage value:
the voltage level your processor should work with. This is hardcoded by
the mainboard and/or processor itself. It is a value in volts.
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d
index 65dfb0c0fd67..0fcfc4a7ccdc 100644
--- a/Documentation/hwmon/lis3lv02d
+++ b/Documentation/hwmon/lis3lv02d
@@ -13,18 +13,21 @@ Author:
Description
-----------
-This driver provides support for the accelerometer found in various HP laptops
-sporting the feature officially called "HP Mobile Data Protection System 3D" or
-"HP 3D DriveGuard". It detect automatically laptops with this sensor. Known models
-(for now the HP 2133, nc6420, nc2510, nc8510, nc84x0, nw9440 and nx9420) will
-have their axis automatically oriented on standard way (eg: you can directly
-play neverball). The accelerometer data is readable via
+This driver provides support for the accelerometer found in various HP
+laptops sporting the feature officially called "HP Mobile Data
+Protection System 3D" or "HP 3D DriveGuard". It detect automatically
+laptops with this sensor. Known models (for now the HP 2133, nc6420,
+nc2510, nc8510, nc84x0, nw9440 and nx9420) will have their axis
+automatically oriented on standard way (eg: you can directly play
+neverball). The accelerometer data is readable via
/sys/devices/platform/lis3lv02d.
Sysfs attributes under /sys/devices/platform/lis3lv02d/:
position - 3D position that the accelerometer reports. Format: "(x,y,z)"
-calibrate - read: values (x, y, z) that are used as the base for input class device operation.
- write: forces the base to be recalibrated with the current position.
+calibrate - read: values (x, y, z) that are used as the base for input
+ class device operation.
+ write: forces the base to be recalibrated with the current
+ position.
rate - reports the sampling rate of the accelerometer device in HZ
This driver also provides an absolute input class device, allowing
@@ -39,11 +42,12 @@ the accelerometer are converted into a "standard" organisation of the axes
* When the laptop is horizontal the position reported is about 0 for X and Y
and a positive value for Z
* If the left side is elevated, X increases (becomes positive)
- * If the front side (where the touchpad is) is elevated, Y decreases (becomes negative)
+ * If the front side (where the touchpad is) is elevated, Y decreases
+ (becomes negative)
* If the laptop is put upside-down, Z becomes negative
-If your laptop model is not recognized (cf "dmesg"), you can send an email to the
-authors to add it to the database. When reporting a new laptop, please include
-the output of "dmidecode" plus the value of /sys/devices/platform/lis3lv02d/position
-in these four cases.
+If your laptop model is not recognized (cf "dmesg"), you can send an
+email to the authors to add it to the database. When reporting a new
+laptop, please include the output of "dmidecode" plus the value of
+/sys/devices/platform/lis3lv02d/position in these four cases.
diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70
index 2bdd3feebf53..0d240291e3cc 100644
--- a/Documentation/hwmon/lm70
+++ b/Documentation/hwmon/lm70
@@ -1,9 +1,11 @@
Kernel driver lm70
==================
-Supported chip:
+Supported chips:
* National Semiconductor LM70
Datasheet: http://www.national.com/pf/LM/LM70.html
+ * Texas Instruments TMP121/TMP123
+ Information: http://focus.ti.com/docs/prod/folders/print/tmp121.html
Author:
Kaiwan N Billimoria <kaiwan@designergraphix.com>
@@ -25,6 +27,14 @@ complement digital temperature (sent via the SIO line), is available in the
driver for interpretation. This driver makes use of the kernel's in-core
SPI support.
+As a real (in-tree) example of this "SPI protocol driver" interfacing
+with a "SPI master controller driver", see drivers/spi/spi_lm70llp.c
+and its associated documentation.
+
+The TMP121/TMP123 are very similar; main differences are 4 wire SPI inter-
+face (read only) and 13-bit temperature data (0.0625 degrees celsius reso-
+lution).
+
Thanks to
---------
Jean Delvare <khali@linux-fr.org> for mentoring the hwmon-side driver
diff --git a/Documentation/hwmon/lm85 b/Documentation/hwmon/lm85
index 400620741290..a13680871bc7 100644
--- a/Documentation/hwmon/lm85
+++ b/Documentation/hwmon/lm85
@@ -164,7 +164,7 @@ configured individually according to the following options.
temperature. (PWM value from 0 to 255)
* pwm#_auto_pwm_minctl - this flags selects for temp#_auto_temp_off temperature
- the bahaviour of fans. Write 1 to let fans spinning at
+ the behaviour of fans. Write 1 to let fans spinning at
pwm#_auto_pwm_min or write 0 to let them off.
NOTE: It has been reported that there is a bug in the LM85 that causes the flag
diff --git a/Documentation/hwmon/ltc4245 b/Documentation/hwmon/ltc4245
new file mode 100644
index 000000000000..bae7a3adc5d8
--- /dev/null
+++ b/Documentation/hwmon/ltc4245
@@ -0,0 +1,81 @@
+Kernel driver ltc4245
+=====================
+
+Supported chips:
+ * Linear Technology LTC4245
+ Prefix: 'ltc4245'
+ Addresses scanned: 0x20-0x3f
+ Datasheet:
+ http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517
+
+Author: Ira W. Snyder <iws@ovro.caltech.edu>
+
+
+Description
+-----------
+
+The LTC4245 controller allows a board to be safely inserted and removed
+from a live backplane in multiple supply systems such as CompactPCI and
+PCI Express.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC4245 devices, due to the fact that some
+of the possible addresses are unfriendly to probing. You will need to use
+the "force" parameter to tell the driver where to find the device.
+
+Example: the following will load the driver for an LTC4245 at address 0x23
+on I2C bus #1:
+$ modprobe ltc4245 force=1,0x23
+
+
+Sysfs entries
+-------------
+
+The LTC4245 has built-in limits for over and under current warnings. This
+makes it very likely that the reference circuit will be used.
+
+This driver uses the values in the datasheet to change the register values
+into the values specified in the sysfs-interface document. The current readings
+rely on the sense resistors listed in Table 2: "Sense Resistor Values".
+
+in1_input 12v input voltage (mV)
+in2_input 5v input voltage (mV)
+in3_input 3v input voltage (mV)
+in4_input Vee (-12v) input voltage (mV)
+
+in1_min_alarm 12v input undervoltage alarm
+in2_min_alarm 5v input undervoltage alarm
+in3_min_alarm 3v input undervoltage alarm
+in4_min_alarm Vee (-12v) input undervoltage alarm
+
+curr1_input 12v current (mA)
+curr2_input 5v current (mA)
+curr3_input 3v current (mA)
+curr4_input Vee (-12v) current (mA)
+
+curr1_max_alarm 12v overcurrent alarm
+curr2_max_alarm 5v overcurrent alarm
+curr3_max_alarm 3v overcurrent alarm
+curr4_max_alarm Vee (-12v) overcurrent alarm
+
+in5_input 12v output voltage (mV)
+in6_input 5v output voltage (mV)
+in7_input 3v output voltage (mV)
+in8_input Vee (-12v) output voltage (mV)
+
+in5_min_alarm 12v output undervoltage alarm
+in6_min_alarm 5v output undervoltage alarm
+in7_min_alarm 3v output undervoltage alarm
+in8_min_alarm Vee (-12v) output undervoltage alarm
+
+in9_input GPIO #1 voltage data
+in10_input GPIO #2 voltage data
+in11_input GPIO #3 voltage data
+
+power1_input 12v power usage (mW)
+power2_input 5v power usage (mW)
+power3_input 3v power usage (mW)
+power4_input Vee (-12v) power usage (mW)
diff --git a/Documentation/ide/warm-plug-howto.txt b/Documentation/ide/warm-plug-howto.txt
index d5885468b072..98152bcd515a 100644
--- a/Documentation/ide/warm-plug-howto.txt
+++ b/Documentation/ide/warm-plug-howto.txt
@@ -11,3 +11,8 @@ unplug old device(s) and plug new device(s)
# echo -n "1" > /sys/class/ide_port/idex/scan
done
+
+NOTE: please make sure that partitions are unmounted and that there are
+no other active references to devices before doing "delete_devices" step,
+also do not attempt "scan" step on devices currently in use -- otherwise
+results may be unpredictable and lead to data loss if you're unlucky
diff --git a/Documentation/input/walkera0701.txt b/Documentation/input/walkera0701.txt
new file mode 100644
index 000000000000..8f4289efc5c4
--- /dev/null
+++ b/Documentation/input/walkera0701.txt
@@ -0,0 +1,109 @@
+
+Walkera WK-0701 transmitter is supplied with a ready to fly Walkera
+helicopters such as HM36, HM37, HM60. The walkera0701 module enables to use
+this transmitter as joystick
+
+Devel homepage and download:
+http://zub.fei.tuke.sk/walkera-wk0701/
+
+or use cogito:
+cg-clone http://zub.fei.tuke.sk/GIT/walkera0701-joystick
+
+
+Connecting to PC:
+
+At back side of transmitter S-video connector can be found. Modulation
+pulses from processor to HF part can be found at pin 2 of this connector,
+pin 3 is GND. Between pin 3 and CPU 5k6 resistor can be found. To get
+modulation pulses to PC, signal pulses must be amplified.
+
+Cable: (walkera TX to parport)
+
+Walkera WK-0701 TX S-VIDEO connector:
+ (back side of TX)
+ __ __ S-video: canon25
+ / |_| \ pin 2 (signal) NPN parport
+ / O 4 3 O \ pin 3 (GND) LED ________________ 10 ACK
+ ( O 2 1 O ) | C
+ \ ___ / 2 ________________________|\|_____|/
+ | [___] | |/| B |\
+ ------- 3 __________________________________|________________ 25 GND
+ E
+
+
+I use green LED and BC109 NPN transistor.
+
+Software:
+
+Build kernel with walkera0701 module. Module walkera0701 need exclusive
+access to parport, modules like lp must be unloaded before loading
+walkera0701 module, check dmesg for error messages. Connect TX to PC by
+cable and run jstest /dev/input/js0 to see values from TX. If no value can
+be changed by TX "joystick", check output from /proc/interrupts. Value for
+(usually irq7) parport must increase if TX is on.
+
+
+
+Technical details:
+
+Driver use interrupt from parport ACK input bit to measure pulse length
+using hrtimers.
+
+Frame format:
+Based on walkera WK-0701 PCM Format description by Shaul Eizikovich.
+(downloaded from http://www.smartpropoplus.com/Docs/Walkera_Wk-0701_PCM.pdf)
+
+Signal pulses:
+ (ANALOG)
+ SYNC BIN OCT
+ +---------+ +------+
+ | | | |
+--+ +------+ +---
+
+Frame:
+ SYNC , BIN1, OCT1, BIN2, OCT2 ... BIN24, OCT24, BIN25, next frame SYNC ..
+
+pulse length:
+ Binary values: Analog octal values:
+
+ 288 uS Binary 0 318 uS 000
+ 438 uS Binary 1 398 uS 001
+ 478 uS 010
+ 558 uS 011
+ 638 uS 100
+ 1306 uS SYNC 718 uS 101
+ 798 uS 110
+ 878 uS 111
+
+24 bin+oct values + 1 bin value = 24*4+1 bits = 97 bits
+
+(Warning, pulses on ACK ar inverted by transistor, irq is rised up on sync
+to bin change or octal value to bin change).
+
+Binary data representations:
+
+One binary and octal value can be grouped to nibble. 24 nibbles + one binary
+values can be sampled between sync pulses.
+
+Values for first four channels (analog joystick values) can be found in
+first 10 nibbles. Analog value is represented by one sign bit and 9 bit
+absolute binary value. (10 bits per channel). Next nibble is checksum for
+first ten nibbles.
+
+Next nibbles 12 .. 21 represents four channels (not all channels can be
+directly controlled from TX). Binary representations ar the same as in first
+four channels. In nibbles 22 and 23 is a special magic number. Nibble 24 is
+checksum for nibbles 12..23.
+
+After last octal value for nibble 24 and next sync pulse one additional
+binary value can be sampled. This bit and magic number is not used in
+software driver. Some details about this magic numbers can be found in
+Walkera_Wk-0701_PCM.pdf.
+
+Checksum calculation:
+
+Summary of octal values in nibbles must be same as octal value in checksum
+nibble (only first 3 bits are used). Binary value for checksum nibble is
+calculated by sum of binary values in checked nibbles + sum of octal values
+in checked nibbles divided by 8. Only bit 0 of this sum is used.
+
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index b880ce5dbd33..f1d639903325 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -84,7 +84,7 @@ Code Seq# Include File Comments
'B' C0-FF advanced bbus
<mailto:maassen@uni-freiburg.de>
'C' all linux/soundcard.h
-'D' all asm-s390/dasd.h
+'D' all arch/s390/include/asm/dasd.h
'E' all linux/input.h
'F' all linux/fb.h
'H' all linux/hiddev.h
@@ -97,6 +97,7 @@ Code Seq# Include File Comments
<http://linux01.gwdg.de/~alatham/ppdd.html>
'M' all linux/soundcard.h
'N' 00-1F drivers/usb/scanner.h
+'O' 00-02 include/mtd/ubi-user.h UBI
'P' all linux/soundcard.h
'Q' all linux/soundcard.h
'R' 00-1F linux/random.h
@@ -104,7 +105,7 @@ Code Seq# Include File Comments
'S' 80-81 scsi/scsi_ioctl.h conflict!
'S' 82-FF scsi/scsi.h conflict!
'T' all linux/soundcard.h conflict!
-'T' all asm-i386/ioctls.h conflict!
+'T' all arch/x86/include/asm/ioctls.h conflict!
'U' 00-EF linux/drivers/usb/usb.h
'V' all linux/vt.h
'W' 00-1F linux/watchdog.h conflict!
@@ -119,7 +120,7 @@ Code Seq# Include File Comments
<mailto:natalia@nikhefk.nikhef.nl>
'c' 00-7F linux/comstats.h conflict!
'c' 00-7F linux/coda.h conflict!
-'c' 80-9F asm-s390/chsc.h
+'c' 80-9F arch/s390/include/asm/chsc.h
'd' 00-FF linux/char/drm/drm/h conflict!
'd' 00-DF linux/video_decoder.h conflict!
'd' F0-FF linux/digi1.h
@@ -142,6 +143,9 @@ Code Seq# Include File Comments
'n' 00-7F linux/ncp_fs.h
'n' E0-FF video/matrox.h matroxfb
'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2
+'o' 00-03 include/mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps)
+'o' 40-41 include/mtd/ubi-user.h UBI
+'o' 01-A1 include/linux/dvb/*.h DVB
'p' 00-0F linux/phantom.h conflict! (OpenHaptics needs this)
'p' 00-3F linux/mc146818rtc.h conflict!
'p' 40-7F linux/nvram.h
@@ -166,7 +170,7 @@ Code Seq# Include File Comments
<mailto:oe@port.de>
0x80 00-1F linux/fb.h
0x81 00-1F linux/videotext.h
-0x89 00-06 asm-i386/sockios.h
+0x89 00-06 arch/x86/include/asm/sockios.h
0x89 0B-DF linux/sockios.h
0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range
0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range
diff --git a/Documentation/ja_JP/stable_kernel_rules.txt b/Documentation/ja_JP/stable_kernel_rules.txt
index b3ffe870de33..14265837c4ce 100644
--- a/Documentation/ja_JP/stable_kernel_rules.txt
+++ b/Documentation/ja_JP/stable_kernel_rules.txt
@@ -12,11 +12,11 @@ file at first.
==================================
これは、
-linux-2.6.24/Documentation/stable_kernel_rules.txt
+linux-2.6.29/Documentation/stable_kernel_rules.txt
の和訳です。
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日: 2007/12/30
+翻訳日: 2009/1/14
翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
校正者: 武井伸光さん、<takei at webmasters dot gr dot jp>
かねこさん (Seiji Kaneko) <skaneko at a2 dot mbn dot or dot jp>
@@ -38,12 +38,15 @@ linux-2.6.24/Documentation/stable_kernel_rules.txt
- ビルドエラー(CONFIG_BROKENになっているものを除く), oops, ハング、デー
タ破壊、現実のセキュリティ問題、その他 "ああ、これはダメだね"という
ようなものを修正しなければならない。短く言えば、重大な問題。
+ - 新しい device ID とクオークも受け入れられる。
- どのように競合状態が発生するかの説明も一緒に書かれていない限り、
"理論的には競合状態になる"ようなものは不可。
- いかなる些細な修正も含めることはできない。(スペルの修正、空白のクリー
ンアップなど)
- - 対応するサブシステムメンテナが受け入れたものでなければならない。
- Documentation/SubmittingPatches の規則に従ったものでなければならない。
+ - パッチ自体か同等の修正が Linus のツリーに既に存在しなければならない。
+  Linus のツリーでのコミットID を -stable へのパッチ投稿の際に引用す
+ ること。
-stable ツリーにパッチを送付する手続き-
@@ -52,8 +55,10 @@ linux-2.6.24/Documentation/stable_kernel_rules.txt
- 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合
には NAK を受け取る。この反応は開発者たちのスケジュールによって、数
日かかる場合がある。
- - もし受け取られたら、パッチは他の開発者たちのレビューのために
- -stable キューに追加される。
+ - もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの
+ メンテナーによるレビューのために -stable キューに追加される。
+ - パッチに stable@kernel.org のアドレスが付加されているときには、それ
+ が Linus のツリーに入る時に自動的に stable チームに email される。
- セキュリティパッチはこのエイリアス (stable@kernel.org) に送られるべ
きではなく、代わりに security@kernel.org のアドレスに送られる。
diff --git a/Documentation/kbuild/00-INDEX b/Documentation/kbuild/00-INDEX
index 114644285454..e8d2b6d83a3d 100644
--- a/Documentation/kbuild/00-INDEX
+++ b/Documentation/kbuild/00-INDEX
@@ -1,5 +1,9 @@
00-INDEX
- - this file: info on the kernel build process
+ - this file: info on the kernel build process
+kbuild.txt
+ - developer information on kbuild
+kconfig.txt
+ - usage help for make *config
kconfig-language.txt
- specification of Config Language, the language in Kconfig files
makefiles.txt
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
new file mode 100644
index 000000000000..f3355b6812df
--- /dev/null
+++ b/Documentation/kbuild/kbuild.txt
@@ -0,0 +1,134 @@
+Environment variables
+
+KCPPFLAGS
+--------------------------------------------------
+Additional options to pass when preprocessing. The preprocessing options
+will be used in all cases where kbuild does preprocessing including
+building C files and assembler files.
+
+KAFLAGS
+--------------------------------------------------
+Additional options to the assembler.
+
+KCFLAGS
+--------------------------------------------------
+Additional options to the C compiler.
+
+KBUILD_VERBOSE
+--------------------------------------------------
+Set the kbuild verbosity. Can be assigned same values as "V=...".
+See make help for the full list.
+Setting "V=..." takes precedence over KBUILD_VERBOSE.
+
+KBUILD_EXTMOD
+--------------------------------------------------
+Set the directory to look for the kernel source when building external
+modules.
+The directory can be specified in several ways:
+1) Use "M=..." on the command line
+2) Environmnet variable KBUILD_EXTMOD
+3) Environmnet variable SUBDIRS
+The possibilities are listed in the order they take precedence.
+Using "M=..." will always override the others.
+
+KBUILD_OUTPUT
+--------------------------------------------------
+Specify the output directory when building the kernel.
+The output directory can also be specificed using "O=...".
+Setting "O=..." takes precedence over KBUILD_OUTPUT.
+
+ARCH
+--------------------------------------------------
+Set ARCH to the architecture to be built.
+In most cases the name of the architecture is the same as the
+directory name found in the arch/ directory.
+But some architectures such as x86 and sparc have aliases.
+x86: i386 for 32 bit, x86_64 for 64 bit
+sparc: sparc for 32 bit, sparc64 for 64 bit
+
+CROSS_COMPILE
+--------------------------------------------------
+Specify an optional fixed part of the binutils filename.
+CROSS_COMPILE can be a part of the filename or the full path.
+
+CROSS_COMPILE is also used for ccache is some setups.
+
+CF
+--------------------------------------------------
+Additional options for sparse.
+CF is often used on the command-line like this:
+
+ make CF=-Wbitwise C=2
+
+INSTALL_PATH
+--------------------------------------------------
+INSTALL_PATH specifies where to place the updated kernel and system map
+images. Default is /boot, but you can set it to other values.
+
+
+MODLIB
+--------------------------------------------------
+Specify where to install modules.
+The default value is:
+
+ $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+
+The value can be overridden in which case the default value is ignored.
+
+INSTALL_MOD_PATH
+--------------------------------------------------
+INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
+relocations required by build roots. This is not defined in the
+makefile but the argument can be passed to make if needed.
+
+INSTALL_MOD_STRIP
+--------------------------------------------------
+INSTALL_MOD_STRIP, if defined, will cause modules to be
+stripped after they are installed. If INSTALL_MOD_STRIP is '1', then
+the default option --strip-debug will be used. Otherwise,
+INSTALL_MOD_STRIP will used as the options to the strip command.
+
+INSTALL_FW_PATH
+--------------------------------------------------
+INSTALL_FW_PATH specifies where to install the firmware blobs.
+The default value is:
+
+ $(INSTALL_MOD_PATH)/lib/firmware
+
+The value can be overridden in which case the default value is ignored.
+
+INSTALL_HDR_PATH
+--------------------------------------------------
+INSTALL_HDR_PATH specifies where to install user space headers when
+executing "make headers_*".
+The default value is:
+
+ $(objtree)/usr
+
+$(objtree) is the directory where output files are saved.
+The output directory is often set using "O=..." on the commandline.
+
+The value can be overridden in which case the default value is ignored.
+
+KBUILD_MODPOST_WARN
+--------------------------------------------------
+KBUILD_MODPOST_WARN can be set to avoid errors in case of undefined
+symbols in the final module linking stage. It changes such errors
+into warnings.
+
+KBUILD_MODPOST_NOFINAL
+--------------------------------------------------
+KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
+This is solely useful to speed up test compiles.
+
+KBUILD_EXTRA_SYMBOLS
+--------------------------------------------------
+For modules that use symbols from other modules.
+See more details in modules.txt.
+
+ALLSOURCE_ARCHS
+--------------------------------------------------
+For tags/TAGS/cscope targets, you can specify more than one arch
+to be included in the databases, separated by blank space. E.g.:
+
+ $ make ALLSOURCE_ARCHS="x86 mips arm" tags
diff --git a/Documentation/kbuild/kconfig.txt b/Documentation/kbuild/kconfig.txt
new file mode 100644
index 000000000000..26a7c0a93193
--- /dev/null
+++ b/Documentation/kbuild/kconfig.txt
@@ -0,0 +1,188 @@
+This file contains some assistance for using "make *config".
+
+Use "make help" to list all of the possible configuration targets.
+
+The xconfig ('qconf') and menuconfig ('mconf') programs also
+have embedded help text. Be sure to check it for navigation,
+search, and other general help text.
+
+======================================================================
+General
+--------------------------------------------------
+
+New kernel releases often introduce new config symbols. Often more
+important, new kernel releases may rename config symbols. When
+this happens, using a previously working .config file and running
+"make oldconfig" won't necessarily produce a working new kernel
+for you, so you may find that you need to see what NEW kernel
+symbols have been introduced.
+
+To see a list of new config symbols when using "make oldconfig", use
+
+ cp user/some/old.config .config
+ yes "" | make oldconfig >conf.new
+
+and the config program will list as (NEW) any new symbols that have
+unknown values. Of course, the .config file is also updated with
+new (default) values, so you can use:
+
+ grep "(NEW)" conf.new
+
+to see the new config symbols or you can 'diff' the previous and
+new .config files to see the differences:
+
+ diff .config.old .config | less
+
+(Yes, we need something better here.)
+
+
+======================================================================
+menuconfig
+--------------------------------------------------
+
+SEARCHING for CONFIG symbols
+
+Searching in menuconfig:
+
+ The Search function searches for kernel configuration symbol
+ names, so you have to know something close to what you are
+ looking for.
+
+ Example:
+ /hotplug
+ This lists all config symbols that contain "hotplug",
+ e.g., HOTPLUG, HOTPLUG_CPU, MEMORY_HOTPLUG.
+
+ For search help, enter / followed TAB-TAB-TAB (to highlight
+ <Help>) and Enter. This will tell you that you can also use
+ regular expressions (regexes) in the search string, so if you
+ are not interested in MEMORY_HOTPLUG, you could try
+
+ /^hotplug
+
+
+______________________________________________________________________
+Color Themes for 'menuconfig'
+
+It is possible to select different color themes using the variable
+MENUCONFIG_COLOR. To select a theme use:
+
+ make MENUCONFIG_COLOR=<theme> menuconfig
+
+Available themes are:
+ mono => selects colors suitable for monochrome displays
+ blackbg => selects a color scheme with black background
+ classic => theme with blue background. The classic look
+ bluetitle => a LCD friendly version of classic. (default)
+
+______________________________________________________________________
+Environment variables in 'menuconfig'
+
+KCONFIG_ALLCONFIG
+--------------------------------------------------
+(partially based on lkml email from/by Rob Landley, re: miniconfig)
+--------------------------------------------------
+The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
+also use the environment variable KCONFIG_ALLCONFIG as a flag or a
+filename that contains config symbols that the user requires to be
+set to a specific value. If KCONFIG_ALLCONFIG is used without a
+filename, "make *config" checks for a file named
+"all{yes/mod/no/random}.config" (corresponding to the *config command
+that was used) for symbol values that are to be forced. If this file
+is not found, it checks for a file named "all.config" to contain forced
+values.
+
+This enables you to create "miniature" config (miniconfig) or custom
+config files containing just the config symbols that you are interested
+in. Then the kernel config system generates the full .config file,
+including dependencies of your miniconfig file, based on the miniconfig
+file.
+
+This 'KCONFIG_ALLCONFIG' file is a config file which contains
+(usually a subset of all) preset config symbols. These variable
+settings are still subject to normal dependency checks.
+
+Examples:
+ KCONFIG_ALLCONFIG=custom-notebook.config make allnoconfig
+or
+ KCONFIG_ALLCONFIG=mini.config make allnoconfig
+or
+ make KCONFIG_ALLCONFIG=mini.config allnoconfig
+
+These examples will disable most options (allnoconfig) but enable or
+disable the options that are explicitly listed in the specified
+mini-config files.
+
+KCONFIG_NOSILENTUPDATE
+--------------------------------------------------
+If this variable has a non-blank value, it prevents silent kernel
+config udpates (requires explicit updates).
+
+KCONFIG_CONFIG
+--------------------------------------------------
+This environment variable can be used to specify a default kernel config
+file name to override the default name of ".config".
+
+KCONFIG_OVERWRITECONFIG
+--------------------------------------------------
+If you set KCONFIG_OVERWRITECONFIG in the environment, Kconfig will not
+break symlinks when .config is a symlink to somewhere else.
+
+KCONFIG_NOTIMESTAMP
+--------------------------------------------------
+If this environment variable exists and is non-null, the timestamp line
+in generated .config files is omitted.
+
+KCONFIG_AUTOCONFIG
+--------------------------------------------------
+This environment variable can be set to specify the path & name of the
+"auto.conf" file. Its default value is "include/config/auto.conf".
+
+KCONFIG_AUTOHEADER
+--------------------------------------------------
+This environment variable can be set to specify the path & name of the
+"autoconf.h" (header) file. Its default value is "include/linux/autoconf.h".
+
+______________________________________________________________________
+menuconfig User Interface Options
+----------------------------------------------------------------------
+MENUCONFIG_MODE
+--------------------------------------------------
+This mode shows all sub-menus in one large tree.
+
+Example:
+ MENUCONFIG_MODE=single_menu make menuconfig
+
+======================================================================
+xconfig
+--------------------------------------------------
+
+Searching in xconfig:
+
+ The Search function searches for kernel configuration symbol
+ names, so you have to know something close to what you are
+ looking for.
+
+ Example:
+ Ctrl-F hotplug
+ or
+ Menu: File, Search, hotplug
+
+ lists all config symbol entries that contain "hotplug" in
+ the symbol name. In this Search dialog, you may change the
+ config setting for any of the entries that are not grayed out.
+ You can also enter a different search string without having
+ to return to the main menu.
+
+
+======================================================================
+gconfig
+--------------------------------------------------
+
+Searching in gconfig:
+
+ None (gconfig isn't maintained as well as xconfig or menuconfig);
+ however, gconfig does have a few more viewing choices than
+ xconfig does.
+
+###
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt
index 1821c077b435..b1096da953c8 100644
--- a/Documentation/kbuild/modules.txt
+++ b/Documentation/kbuild/modules.txt
@@ -253,7 +253,7 @@ following files:
# Module specific targets
genbin:
- echo "X" > 8123_bin_shipped
+ echo "X" > 8123_bin.o_shipped
In example 2, we are down to two fairly simple files and for simple
@@ -279,7 +279,7 @@ following files:
# Module specific targets
genbin:
- echo "X" > 8123_bin_shipped
+ echo "X" > 8123_bin.o_shipped
endif
diff --git a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
index c6841eee9598..d73fbd2b2b45 100644
--- a/Documentation/kernel-doc-nano-HOWTO.txt
+++ b/Documentation/kernel-doc-nano-HOWTO.txt
@@ -71,6 +71,11 @@ The @argument descriptions must begin on the very next line following
this opening short function description line, with no intervening
empty comment lines.
+If a function parameter is "..." (varargs), it should be listed in
+kernel-doc notation as:
+ * @...: description
+
+
Example kernel-doc data structure comment.
/**
@@ -282,6 +287,32 @@ struct my_struct {
};
+Including documentation blocks in source files
+----------------------------------------------
+
+To facilitate having source code and comments close together, you can
+include kernel-doc documentation blocks that are free-form comments
+instead of being kernel-doc for functions, structures, unions,
+enums, or typedefs. This could be used for something like a
+theory of operation for a driver or library code, for example.
+
+This is done by using a DOC: section keyword with a section title. E.g.:
+
+/**
+ * DOC: Theory of Operation
+ *
+ * The whizbang foobar is a dilly of a gizmo. It can do whatever you
+ * want it to do, at any time. It reads your mind. Here's how it works.
+ *
+ * foo bar splat
+ *
+ * The only drawback to this gizmo is that is can sometimes damage
+ * hardware, software, or its subject(s).
+ */
+
+DOC: sections are used in SGML templates files as indicated below.
+
+
How to make new SGML template files
-----------------------------------
@@ -302,6 +333,9 @@ exported using EXPORT_SYMBOL.
!F<filename> <function [functions...]> is replaced by the
documentation, in <filename>, for the functions listed.
+!P<filename> <section title> is replaced by the contents of the DOC:
+section titled <section title> from <filename>.
+Spaces are allowed in <section title>; do not quote the <section title>.
Tim.
*/ <twaugh@redhat.com>
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 31e0c2c3c6e3..8cc40a1bee06 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -92,6 +92,7 @@ parameter is applicable:
SUSPEND System suspend states are enabled.
FTRACE Function tracing enabled.
TS Appropriate touchscreen support is enabled.
+ UMS USB Mass Storage support is enabled.
USB USB support is enabled.
USBHID USB Human Interface Device support is enabled.
V4L Video For Linux support is enabled.
@@ -141,6 +142,7 @@ and is between 256 and 4096 characters. It is defined in the file
ht -- run only enough ACPI to enable Hyper Threading
strict -- Be less tolerant of platforms that are not
strictly ACPI specification compliant.
+ rsdt -- prefer RSDT over (default) XSDT
See also Documentation/power/pm.txt, pci=noacpi
@@ -151,16 +153,20 @@ and is between 256 and 4096 characters. It is defined in the file
default: 0
acpi_sleep= [HW,ACPI] Sleep options
- Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig, old_ordering }
- See Documentation/power/video.txt for s3_bios and s3_mode.
+ Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
+ old_ordering, s4_nonvs }
+ See Documentation/power/video.txt for information on
+ s3_bios and s3_mode.
s3_beep is for debugging; it makes the PC's speaker beep
as soon as the kernel's real-mode entry point is called.
s4_nohwsig prevents ACPI hardware signature from being
used during resume from hibernation.
old_ordering causes the ACPI 1.0 ordering of the _PTS
- control method, wrt putting devices into low power
- states, to be enforced (the ACPI 2.0 ordering of _PTS is
- used by default).
+ control method, with respect to putting devices into
+ low power states, to be enforced (the ACPI 2.0 ordering
+ of _PTS is used by default).
+ s4_nonvs prevents the kernel from saving/restoring the
+ ACPI NVS memory during hibernation.
acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode
Format: { level | edge | high | low }
@@ -195,7 +201,7 @@ and is between 256 and 4096 characters. It is defined in the file
acpi_skip_timer_override [HW,ACPI]
Recognize and ignore IRQ0/pin2 Interrupt Override.
For broken nForce2 BIOS resulting in XT-PIC timer.
- acpi_use_timer_override [HW,ACPI}
+ acpi_use_timer_override [HW,ACPI]
Use timer override. For some broken Nvidia NF5 boards
that require a timer override, but don't have
HPET
@@ -470,8 +476,8 @@ and is between 256 and 4096 characters. It is defined in the file
clearcpuid=BITNUM [X86]
Disable CPUID feature X for the kernel. See
- include/asm-x86/cpufeature.h for the valid bit numbers.
- Note the Linux specific bits are not necessarily
+ arch/x86/include/asm/cpufeature.h for the valid bit
+ numbers. Note the Linux specific bits are not necessarily
stable over kernel options, but the vendor specific
ones should be.
Also note that user programs calling CPUID directly
@@ -552,6 +558,11 @@ and is between 256 and 4096 characters. It is defined in the file
not work reliably with all consoles, but is known
to work with serial and VGA consoles.
+ coredump_filter=
+ [KNL] Change the default value for
+ /proc/<pid>/coredump_filter.
+ See also Documentation/filesystems/proc.txt.
+
cpcihp_generic= [HW,PCI] Generic port I/O CompactPCI driver
Format:
<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
@@ -567,9 +578,6 @@ and is between 256 and 4096 characters. It is defined in the file
a memory unit (amount[KMG]). See also
Documentation/kdump/kdump.txt for a example.
- cs4232= [HW,OSS]
- Format: <io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>
-
cs89x0_dma= [HW,NET]
Format: <dma>
@@ -722,10 +730,6 @@ and is between 256 and 4096 characters. It is defined in the file
Default value is 0.
Value can be changed at runtime via /selinux/enforce.
- es1371= [HW,OSS]
- Format: <spdif>,[<nomix>,[<amplifier>]]
- See also header of sound/oss/es1371.c.
-
ether= [HW,NET] Ethernet cards parameters
This option is obsoleted by the "netdev=" option, which
has equivalent usage. See its documentation for details.
@@ -824,8 +828,8 @@ and is between 256 and 4096 characters. It is defined in the file
hlt [BUGS=ARM,SH]
- hvc_iucv= [S390] Number of z/VM IUCV Hypervisor console (HVC)
- back-ends. Valid parameters: 0..8
+ hvc_iucv= [S390] Number of z/VM IUCV hypervisor console (HVC)
+ terminal devices. Valid values: 0..8
i8042.debug [HW] Toggle i8042 debug mode
i8042.direct [HW] Put keyboard port into non-translated mode
@@ -873,17 +877,19 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/ide/ide.txt.
idle= [X86]
- Format: idle=poll or idle=mwait, idle=halt, idle=nomwait
- Poll forces a polling idle loop that can slightly improves the performance
- of waking up a idle CPU, but will use a lot of power and make the system
- run hot. Not recommended.
- idle=mwait. On systems which support MONITOR/MWAIT but the kernel chose
- to not use it because it doesn't save as much power as a normal idle
- loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
- as idle=poll.
- idle=halt. Halt is forced to be used for CPU idle.
+ Format: idle=poll, idle=mwait, idle=halt, idle=nomwait
+ Poll forces a polling idle loop that can slightly
+ improve the performance of waking up a idle CPU, but
+ will use a lot of power and make the system run hot.
+ Not recommended.
+ idle=mwait: On systems which support MONITOR/MWAIT but
+ the kernel chose to not use it because it doesn't save
+ as much power as a normal idle loop, use the
+ MONITOR/MWAIT idle loop anyways. Performance should be
+ the same as idle=poll.
+ idle=halt: Halt is forced to be used for CPU idle.
In such case C2/C3 won't be used again.
- idle=nomwait. Disable mwait for CPU C-states
+ idle=nomwait: Disable mwait for CPU C-states
ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
Claim all unknown PCI IDE storage controllers.
@@ -923,6 +929,10 @@ and is between 256 and 4096 characters. It is defined in the file
inttest= [IA64]
+ iomem= Disable strict checking of access to MMIO memory
+ strict regions from userspace.
+ relaxed
+
iommu= [x86]
off
force
@@ -1074,8 +1084,8 @@ and is between 256 and 4096 characters. It is defined in the file
lapic [X86-32,APIC] Enable the local APIC even if BIOS
disabled it.
- lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer in
- C2 power state.
+ lapic_timer_c2_ok [X86-32,x86-64,APIC] trust the local apic timer
+ in C2 power state.
libata.dma= [LIBATA] DMA control
libata.dma=0 Disable all PATA and SATA DMA
@@ -1127,6 +1137,8 @@ and is between 256 and 4096 characters. It is defined in the file
If there are multiple matching configurations changing
the same attribute, the last one is used.
+ lmb=debug [KNL] Enable lmb debug messages.
+
load_ramdisk= [RAM] List of ramdisks to load from floppy
See Documentation/blockdev/ramdisk.txt.
@@ -1560,6 +1572,9 @@ and is between 256 and 4096 characters. It is defined in the file
nosoftlockup [KNL] Disable the soft-lockup detector.
+ noswapaccount [KNL] Disable accounting of swap in memory resource
+ controller. (See Documentation/controllers/memory.txt)
+
nosync [HW,M68K] Disables sync negotiation for all devices.
notsc [BUGS=X86-32] Disable Time Stamp Counter
@@ -1579,6 +1594,10 @@ and is between 256 and 4096 characters. It is defined in the file
nr_uarts= [SERIAL] maximum number of UARTs to be registered.
+ ohci1394_dma=early [HW] enable debugging via the ohci1394 driver.
+ See Documentation/debugging-via-ohci1394.txt for more
+ info.
+
olpc_ec_timeout= [OLPC] ms delay when issuing EC commands
Rather than timing out after 20 ms if an EC
command is not properly ACKed, override the length
@@ -1803,10 +1822,10 @@ and is between 256 and 4096 characters. It is defined in the file
autoconfiguration.
Ranges are in pairs (memory base and size).
- dynamic_printk
- Enables pr_debug()/dev_dbg() calls if
- CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. These can also
- be switched on/off via <debugfs>/dynamic_printk/modules
+ dynamic_printk Enables pr_debug()/dev_dbg() calls if
+ CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled.
+ These can also be switched on/off via
+ <debugfs>/dynamic_printk/modules
print-fatal-signals=
[KNL] debug: print fatal signals
@@ -1894,7 +1913,7 @@ and is between 256 and 4096 characters. It is defined in the file
reboot= [BUGS=X86-32,BUGS=ARM,BUGS=IA-64] Rebooting mode
Format: <reboot_mode>[,<reboot_mode2>[,...]]
- See arch/*/kernel/reboot.c or arch/*/kernel/process.c
+ See arch/*/kernel/reboot.c or arch/*/kernel/process.c
relax_domain_level=
[KNL, SMP] Set scheduler's default relax_domain_level.
@@ -2294,7 +2313,8 @@ and is between 256 and 4096 characters. It is defined in the file
thermal.psv= [HW,ACPI]
-1: disable all passive trip points
- <degrees C>: override all passive trip points to this value
+ <degrees C>: override all passive trip points to this
+ value
thermal.tzp= [HW,ACPI]
Specify global default ACPI thermal zone polling rate
@@ -2382,6 +2402,41 @@ and is between 256 and 4096 characters. It is defined in the file
usbhid.mousepoll=
[USBHID] The interval which mice are to be polled at.
+ usb-storage.delay_use=
+ [UMS] The delay in seconds before a new device is
+ scanned for Logical Units (default 5).
+
+ usb-storage.quirks=
+ [UMS] A list of quirks entries to supplement or
+ override the built-in unusual_devs list. List
+ entries are separated by commas. Each entry has
+ the form VID:PID:Flags where VID and PID are Vendor
+ and Product ID values (4-digit hex numbers) and
+ Flags is a set of characters, each corresponding
+ to a common usb-storage quirk flag as follows:
+ a = SANE_SENSE (collect more than 18 bytes
+ of sense data);
+ c = FIX_CAPACITY (decrease the reported
+ device capacity by one sector);
+ h = CAPACITY_HEURISTICS (decrease the
+ reported device capacity by one
+ sector if the number is odd);
+ i = IGNORE_DEVICE (don't bind to this
+ device);
+ l = NOT_LOCKABLE (don't try to lock and
+ unlock ejectable media);
+ m = MAX_SECTORS_64 (don't transfer more
+ than 64 sectors = 32 KB at a time);
+ o = CAPACITY_OK (accept the capacity
+ reported by the device);
+ r = IGNORE_RESIDUE (the device reports
+ bogus residue values);
+ s = SINGLE_LUN (the device has only one
+ Logical Unit);
+ w = NO_WP_DETECT (don't test whether the
+ medium is write-protected).
+ Example: quirks=0419:aaf5:rl,0421:0433:rc
+
add_efi_memmap [EFI; x86-32,X86-64] Include EFI memory map in
kernel's map of available physical RAM.
@@ -2442,8 +2497,8 @@ and is between 256 and 4096 characters. It is defined in the file
Format:
<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
- norandmaps Don't use address space randomization
- Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space
+ norandmaps Don't use address space randomization. Equivalent to
+ echo 0 > /proc/sys/kernel/randomize_va_space
______________________________________________________________________
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index f5d2aad65a67..b2e374586bd8 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -118,8 +118,8 @@ the name of the kobject, call kobject_rename():
int kobject_rename(struct kobject *kobj, const char *new_name);
-Note kobject_rename does perform any locking or have a solid notion of
-what names are valid so the provide must provide their own sanity checking
+kobject_rename does not perform any locking or have a solid notion of
+what names are valid so the caller must provide their own sanity checking
and serialization.
There is a function called kobject_set_name() but that is legacy cruft and
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index a79633d702bf..48b3de90eb1e 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -497,7 +497,10 @@ The first column provides the kernel address where the probe is inserted.
The second column identifies the type of probe (k - kprobe, r - kretprobe
and j - jprobe), while the third column specifies the symbol+offset of
the probe. If the probed function belongs to a module, the module name
-is also specified.
+is also specified. Following columns show probe status. If the probe is on
+a virtual address that is no longer valid (module init sections, module
+virtual addresses that correspond to modules that've been unloaded),
+such probes are marked with [GONE].
/debug/kprobes/enabled: Turn kprobes ON/OFF
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 71f0fe1fc1b0..41bc99fa1884 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -1,7 +1,7 @@
ThinkPad ACPI Extras Driver
- Version 0.21
- May 29th, 2008
+ Version 0.22
+ November 23rd, 2008
Borislav Deianov <borislav@users.sf.net>
Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@ -16,7 +16,8 @@ supported by the generic Linux ACPI drivers.
This driver used to be named ibm-acpi until kernel 2.6.21 and release
0.13-20070314. It used to be in the drivers/acpi tree, but it was
moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel
-2.6.22, and release 0.14.
+2.6.22, and release 0.14. It was moved to drivers/platform/x86 for
+kernel 2.6.29 and release 0.22.
The driver is named "thinkpad-acpi". In some places, like module
names, "thinkpad_acpi" is used because of userspace issues.
@@ -1412,6 +1413,24 @@ Sysfs notes:
rfkill controller switch "tpacpi_wwan_sw": refer to
Documentation/rfkill.txt for details.
+EXPERIMENTAL: UWB
+-----------------
+
+This feature is marked EXPERIMENTAL because it has not been extensively
+tested and validated in various ThinkPad models yet. The feature may not
+work as expected. USE WITH CAUTION! To use this feature, you need to supply
+the experimental=1 parameter when loading the module.
+
+sysfs rfkill class: switch "tpacpi_uwb_sw"
+
+This feature exports an rfkill controller for the UWB device, if one is
+present and enabled in the BIOS.
+
+Sysfs notes:
+
+ rfkill controller switch "tpacpi_uwb_sw": refer to
+ Documentation/rfkill.txt for details.
+
Multiple Commands, Module Parameters
------------------------------------
@@ -1475,7 +1494,7 @@ Sysfs interface changelog:
0x020100: Marker for thinkpad-acpi with hot key NVRAM polling
support. If you must, use it to know you should not
- start an userspace NVRAM poller (allows to detect when
+ start a userspace NVRAM poller (allows to detect when
NVRAM is compiled out by the user because it is
unneeded/undesired in the first place).
0x020101: Marker for thinkpad-acpi with hot key NVRAM polling
diff --git a/Documentation/lguest/Makefile b/Documentation/lguest/Makefile
index 725eef81cd48..1f4f9e888bd1 100644
--- a/Documentation/lguest/Makefile
+++ b/Documentation/lguest/Makefile
@@ -1,5 +1,5 @@
# This creates the demonstration utility "lguest" which runs a Linux guest.
-CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include -I../../arch/x86/include
+CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 -I../../include -I../../arch/x86/include -U_FORTIFY_SOURCE
LDLIBS:=-lz
all: lguest
diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
index 95070028d15e..505f19607542 100644
--- a/Documentation/magic-number.txt
+++ b/Documentation/magic-number.txt
@@ -125,14 +125,14 @@ TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c
ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h
SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h
SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c
-GDA_MAGIC 0x58464552 gda include/asm-mips64/sn/gda.h
+GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h
RED_MAGIC1 0x5a2cf071 (any) mm/slab.c
STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h
EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c
HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h
EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h
PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h
-KV_MAGIC 0x5f4b565f kernel_vars_s include/asm-mips64/sn/klkernvars.h
+KV_MAGIC 0x5f4b565f kernel_vars_s arch/mips/include/asm/sn/klkernvars.h
I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c
TRIDENT_STATE_MAGIC 0x63657373 trient_state sound/oss/trident.c
M3_CARD_MAGIC 0x646e6f50 m3_card sound/oss/maestro3.c
@@ -158,7 +158,7 @@ CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c
QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c
QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry drivers/scsi/arm/queue.c
HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c
-NMI_MAGIC 0x48414d4d455201 nmi_s include/asm-mips64/sn/nmi.h
+NMI_MAGIC 0x48414d4d455201 nmi_s arch/mips/include/asm/sn/nmi.h
Note that there are also defined special per-driver magic numbers in sound
memory management. See include/sound/sndmagic.h for complete list of them. Many
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 168117bd6ee8..4c2ecf537a4a 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -124,7 +124,7 @@ config options.
This option can be kernel module too.
--------------------------------
-3 sysfs files for memory hotplug
+4 sysfs files for memory hotplug
--------------------------------
All sections have their device information under /sys/devices/system/memory as
@@ -138,11 +138,12 @@ For example, assume 1GiB section size. A device for a memory starting at
(0x100000000 / 1Gib = 4)
This device covers address range [0x100000000 ... 0x140000000)
-Under each section, you can see 3 files.
+Under each section, you can see 4 files.
/sys/devices/system/memory/memoryXXX/phys_index
/sys/devices/system/memory/memoryXXX/phys_device
/sys/devices/system/memory/memoryXXX/state
+/sys/devices/system/memory/memoryXXX/removable
'phys_index' : read-only and contains section id, same as XXX.
'state' : read-write
@@ -150,10 +151,20 @@ Under each section, you can see 3 files.
at write: user can specify "online", "offline" command
'phys_device': read-only: designed to show the name of physical memory device.
This is not well implemented now.
+'removable' : read-only: contains an integer value indicating
+ whether the memory section is removable or not
+ removable. A value of 1 indicates that the memory
+ section is removable and a value of 0 indicates that
+ it is not removable.
NOTE:
These directories/files appear after physical memory hotplug phase.
+If CONFIG_NUMA is enabled the
+/sys/devices/system/memory/memoryXXX memory section
+directories can also be accessed via symbolic links located in
+the /sys/devices/system/node/node* directories. For example:
+/sys/devices/system/node/node0/memory9 -> ../../memory/memory9
--------------------------------
4. Physical memory hot-add phase
@@ -365,7 +376,6 @@ node if necessary.
- allowing memory hot-add to ZONE_MOVABLE. maybe we need some switch like
sysctl or new control file.
- showing memory section and physical device relationship.
- - showing memory section and node relationship (maybe good for NUMA)
- showing memory section is under ZONE_MOVABLE or not
- test and make it better memory offlining.
- support HugeTLB page migration and offlining.
diff --git a/Documentation/mips/AU1xxx_IDE.README b/Documentation/mips/AU1xxx_IDE.README
index 25a6ed1aaa5b..8ace35ebdcd5 100644
--- a/Documentation/mips/AU1xxx_IDE.README
+++ b/Documentation/mips/AU1xxx_IDE.README
@@ -44,7 +44,7 @@ FILES, CONFIGS AND COMPATABILITY
Two files are introduced:
- a) 'include/asm-mips/mach-au1x00/au1xxx_ide.h'
+ a) 'arch/mips/include/asm/mach-au1x00/au1xxx_ide.h'
containes : struct _auide_hwif
timing parameters for PIO mode 0/1/2/3/4
timing parameters for MWDMA 0/1/2
@@ -52,14 +52,12 @@ Two files are introduced:
b) 'drivers/ide/mips/au1xxx-ide.c'
contains the functionality of the AU1XXX IDE driver
-Four configs variables are introduced:
+Following extra configs variables are introduced:
CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA - enable the PIO+DBDMA mode
CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - enable the MWDMA mode
CONFIG_BLK_DEV_IDE_AU1XXX_BURSTABLE_ON - set Burstable FIFO in DBDMA
controller
- CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - maximum transfer size
- per descriptor
SUPPORTED IDE MODES
@@ -87,7 +85,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_BLK_DEV_IDE_AU1XXX=y
CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y
-CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ=128
CONFIG_BLK_DEV_IDEDMA=y
CONFIG_IDEDMA_AUTO=y
@@ -105,7 +102,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
CONFIG_IDEDMA_PCI_AUTO=y
CONFIG_BLK_DEV_IDE_AU1XXX=y
CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA=y
-CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ=128
CONFIG_BLK_DEV_IDEDMA=y
CONFIG_IDEDMA_AUTO=y
diff --git a/Documentation/networking/alias.txt b/Documentation/networking/alias.txt
index cd12c2ff518a..85046f53fcfc 100644
--- a/Documentation/networking/alias.txt
+++ b/Documentation/networking/alias.txt
@@ -2,13 +2,13 @@
IP-Aliasing:
============
-IP-aliases are additional IP-addresses/masks hooked up to a base
-interface by adding a colon and a string when running ifconfig.
-This string is usually numeric, but this is not a must.
-
-IP-Aliases are avail if CONFIG_INET (`standard' IPv4 networking)
-is configured in the kernel.
+IP-aliases are an obsolete way to manage multiple IP-addresses/masks
+per interface. Newer tools such as iproute2 support multiple
+address/prefixes per interface, but aliases are still supported
+for backwards compatibility.
+An alias is formed by adding a colon and a string when running ifconfig.
+This string is usually numeric, but this is not a must.
o Alias creation.
Alias creation is done by 'magic' interface naming: eg. to create a
@@ -38,16 +38,3 @@ o Relationship with main device
If the base device is shut down the added aliases will be deleted
too.
-
-
-Contact
--------
-Please finger or e-mail me:
- Juan Jose Ciarlante <jjciarla@raiz.uncu.edu.ar>
-
-Updated by Erik Schoenfelder <schoenfr@gaertner.DE>
-
-; local variables:
-; mode: indented-text
-; mode: auto-fill
-; end:
diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
index 3c2f2b328638..8d022073e3ef 100644
--- a/Documentation/networking/netconsole.txt
+++ b/Documentation/networking/netconsole.txt
@@ -51,7 +51,8 @@ Built-in netconsole starts immediately after the TCP stack is
initialized and attempts to bring up the supplied dev at the supplied
address.
-The remote host can run either 'netcat -u -l -p <port>' or syslogd.
+The remote host can run either 'netcat -u -l -p <port>',
+'nc -l -u <port>' or syslogd.
Dynamic reconfiguration:
========================
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt
index c3669a3fb4af..60d05eb77c64 100644
--- a/Documentation/networking/rxrpc.txt
+++ b/Documentation/networking/rxrpc.txt
@@ -540,7 +540,7 @@ A client would issue an operation by:
MSG_MORE should be set in msghdr::msg_flags on all but the last part of
the request. Multiple requests may be made simultaneously.
- If a call is intended to go to a destination other then the default
+ If a call is intended to go to a destination other than the default
specified through connect(), then msghdr::msg_name should be set on the
first request message of that call.
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
index 839cbb71388b..c0aab985bad9 100644
--- a/Documentation/networking/tuntap.txt
+++ b/Documentation/networking/tuntap.txt
@@ -118,7 +118,7 @@ As mentioned above, main purpose of TUN/TAP driver is tunneling.
It is used by VTun (http://vtun.sourceforge.net).
Another interesting application using TUN/TAP is pipsecd
-(http://perso.enst.fr/~beyssac/pipsec/), an userspace IPSec
+(http://perso.enst.fr/~beyssac/pipsec/), a userspace IPSec
implementation that can use complete kernel routing (unlike FreeS/WAN).
3. How does Virtual network device actually work ?
diff --git a/Documentation/nommu-mmap.txt b/Documentation/nommu-mmap.txt
index 7714f57caad5..b565e8279d13 100644
--- a/Documentation/nommu-mmap.txt
+++ b/Documentation/nommu-mmap.txt
@@ -109,12 +109,18 @@ and it's also much more restricted in the latter case:
FURTHER NOTES ON NO-MMU MMAP
============================
- (*) A request for a private mapping of less than a page in size may not return
- a page-aligned buffer. This is because the kernel calls kmalloc() to
- allocate the buffer, not get_free_page().
+ (*) A request for a private mapping of a file may return a buffer that is not
+ page-aligned. This is because XIP may take place, and the data may not be
+ paged aligned in the backing store.
- (*) A list of all the mappings on the system is visible through /proc/maps in
- no-MMU mode.
+ (*) A request for an anonymous mapping will always be page aligned. If
+ possible the size of the request should be a power of two otherwise some
+ of the space may be wasted as the kernel must allocate a power-of-2
+ granule but will only discard the excess if appropriately configured as
+ this has an effect on fragmentation.
+
+ (*) A list of all the private copy and anonymous mappings on the system is
+ visible through /proc/maps in no-MMU mode.
(*) A list of all the mappings in use by a process is visible through
/proc/<pid>/maps in no-MMU mode.
@@ -242,3 +248,18 @@ PROVIDING SHAREABLE BLOCK DEVICE SUPPORT
Provision of shared mappings on block device files is exactly the same as for
character devices. If there isn't a real device underneath, then the driver
should allocate sufficient contiguous memory to honour any supported mapping.
+
+
+=================================
+ADJUSTING PAGE TRIMMING BEHAVIOUR
+=================================
+
+NOMMU mmap automatically rounds up to the nearest power-of-2 number of pages
+when performing an allocation. This can have adverse effects on memory
+fragmentation, and as such, is left configurable. The default behaviour is to
+aggressively trim allocations and discard any excess pages back in to the page
+allocator. In order to retain finer-grained control over fragmentation, this
+behaviour can either be disabled completely, or bumped up to a higher page
+watermark where trimming begins.
+
+Page trimming behaviour is configurable via the sysctl `vm.nr_trim_pages'.
diff --git a/Documentation/powerpc/cpu_features.txt b/Documentation/powerpc/cpu_features.txt
index 472739880e87..ffa4183fdb8b 100644
--- a/Documentation/powerpc/cpu_features.txt
+++ b/Documentation/powerpc/cpu_features.txt
@@ -31,7 +31,7 @@ anyways).
After detecting the processor type, the kernel patches out sections of code
that shouldn't be used by writing nop's over it. Using cpufeatures requires
-just 2 macros (found in include/asm-ppc/cputable.h), as seen in head.S
+just 2 macros (found in arch/powerpc/include/asm/cputable.h), as seen in head.S
transfer_to_handler:
#ifdef CONFIG_ALTIVEC
diff --git a/Documentation/powerpc/dts-bindings/4xx/ndfc.txt b/Documentation/powerpc/dts-bindings/4xx/ndfc.txt
new file mode 100644
index 000000000000..869f0b5f16e8
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/4xx/ndfc.txt
@@ -0,0 +1,39 @@
+AMCC NDFC (NanD Flash Controller)
+
+Required properties:
+- compatible : "ibm,ndfc".
+- reg : should specify chip select and size used for the chip (0x2000).
+
+Optional properties:
+- ccr : NDFC config and control register value (default 0).
+- bank-settings : NDFC bank configuration register value (default 0).
+
+Notes:
+- partition(s) - follows the OF MTD standard for partitions
+
+Example:
+
+ndfc@1,0 {
+ compatible = "ibm,ndfc";
+ reg = <0x00000001 0x00000000 0x00002000>;
+ ccr = <0x00001000>;
+ bank-settings = <0x80002222>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ nand {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00200000>;
+ };
+ partition@200000 {
+ label = "root";
+ reg = <0x00200000 0x03E00000>;
+ };
+ };
+};
+
+
diff --git a/Documentation/powerpc/dts-bindings/fsl/board.txt b/Documentation/powerpc/dts-bindings/fsl/board.txt
index 81a917ef96e9..6c974d28eeb4 100644
--- a/Documentation/powerpc/dts-bindings/fsl/board.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/board.txt
@@ -18,7 +18,7 @@ This is the memory-mapped registers for on board FPGA.
Required properities:
- compatible : should be "fsl,fpga-pixis".
-- reg : should contain the address and the lenght of the FPPGA register
+- reg : should contain the address and the length of the FPPGA register
set.
Example (MPC8610HPCD):
@@ -27,3 +27,33 @@ Example (MPC8610HPCD):
compatible = "fsl,fpga-pixis";
reg = <0xe8000000 32>;
};
+
+* Freescale BCSR GPIO banks
+
+Some BCSR registers act as simple GPIO controllers, each such
+register can be represented by the gpio-controller node.
+
+Required properities:
+- compatible : Should be "fsl,<board>-bcsr-gpio".
+- reg : Should contain the address and the length of the GPIO bank
+ register.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+ second cell is used to specify optional paramters (currently unused).
+- gpio-controller : Marks the port as GPIO controller.
+
+Example:
+
+ bcsr@1,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8360mds-bcsr";
+ reg = <1 0 0x8000>;
+ ranges = <0 1 0 0x8000>;
+
+ bcsr13: gpio-controller@d {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8360mds-bcsr-gpio";
+ reg = <0xd 1>;
+ gpio-controller;
+ };
+ };
diff --git a/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
new file mode 100644
index 000000000000..8447fd7090d0
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/fsl/mpc5200.txt
@@ -0,0 +1,180 @@
+MPC5200 Device Tree Bindings
+----------------------------
+
+(c) 2006-2009 Secret Lab Technologies Ltd
+Grant Likely <grant.likely@secretlab.ca>
+
+Naming conventions
+------------------
+For mpc5200 on-chip devices, the format for each compatible value is
+<chip>-<device>[-<mode>]. The OS should be able to match a device driver
+to the device based solely on the compatible value. If two drivers
+match on the compatible list; the 'most compatible' driver should be
+selected.
+
+The split between the MPC5200 and the MPC5200B leaves a bit of a
+conundrum. How should the compatible property be set up to provide
+maximum compatibility information; but still accurately describe the
+chip? For the MPC5200; the answer is easy. Most of the SoC devices
+originally appeared on the MPC5200. Since they didn't exist anywhere
+else; the 5200 compatible properties will contain only one item;
+"fsl,mpc5200-<device>".
+
+The 5200B is almost the same as the 5200, but not quite. It fixes
+silicon bugs and it adds a small number of enhancements. Most of the
+devices either provide exactly the same interface as on the 5200. A few
+devices have extra functions but still have a backwards compatible mode.
+To express this information as completely as possible, 5200B device trees
+should have two items in the compatible list:
+ compatible = "fsl,mpc5200b-<device>","fsl,mpc5200-<device>";
+
+It is *strongly* recommended that 5200B device trees follow this convention
+(instead of only listing the base mpc5200 item).
+
+ie. ethernet on mpc5200: compatible = "fsl,mpc5200-fec";
+ ethernet on mpc5200b: compatible = "fsl,mpc5200b-fec", "fsl,mpc5200-fec";
+
+Modal devices, like PSCs, also append the configured function to the
+end of the compatible field. ie. A PSC in i2s mode would specify
+"fsl,mpc5200-psc-i2s", not "fsl,mpc5200-i2s". This convention is chosen to
+avoid naming conflicts with non-psc devices providing the same
+function. For example, "fsl,mpc5200-spi" and "fsl,mpc5200-psc-spi" describe
+the mpc5200 simple spi device and a PSC spi mode respectively.
+
+At the time of writing, exact chip may be either 'fsl,mpc5200' or
+'fsl,mpc5200b'.
+
+The soc node
+------------
+This node describes the on chip SOC peripherals. Every mpc5200 based
+board will have this node, and as such there is a common naming
+convention for SOC devices.
+
+Required properties:
+name description
+---- -----------
+ranges Memory range of the internal memory mapped registers.
+ Should be <0 [baseaddr] 0xc000>
+reg Should be <[baseaddr] 0x100>
+compatible mpc5200: "fsl,mpc5200-immr"
+ mpc5200b: "fsl,mpc5200b-immr"
+system-frequency 'fsystem' frequency in Hz; XLB, IPB, USB and PCI
+ clocks are derived from the fsystem clock.
+bus-frequency IPB bus frequency in Hz. Clock rate
+ used by most of the soc devices.
+
+soc child nodes
+---------------
+Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
+
+Note: The tables below show the value for the mpc5200. A mpc5200b device
+tree should use the "fsl,mpc5200b-<device>","fsl,mpc5200-<device>" form.
+
+Required soc5200 child nodes:
+name compatible Description
+---- ---------- -----------
+cdm@<addr> fsl,mpc5200-cdm Clock Distribution
+interrupt-controller@<addr> fsl,mpc5200-pic need an interrupt
+ controller to boot
+bestcomm@<addr> fsl,mpc5200-bestcomm Bestcomm DMA controller
+
+Recommended soc5200 child nodes; populate as needed for your board
+name compatible Description
+---- ---------- -----------
+timer@<addr> fsl,mpc5200-gpt General purpose timers
+gpio@<addr> fsl,mpc5200-gpio MPC5200 simple gpio controller
+gpio@<addr> fsl,mpc5200-gpio-wkup MPC5200 wakeup gpio controller
+rtc@<addr> fsl,mpc5200-rtc Real time clock
+mscan@<addr> fsl,mpc5200-mscan CAN bus controller
+pci@<addr> fsl,mpc5200-pci PCI bridge
+serial@<addr> fsl,mpc5200-psc-uart PSC in serial mode
+i2s@<addr> fsl,mpc5200-psc-i2s PSC in i2s mode
+ac97@<addr> fsl,mpc5200-psc-ac97 PSC in ac97 mode
+spi@<addr> fsl,mpc5200-psc-spi PSC in spi mode
+irda@<addr> fsl,mpc5200-psc-irda PSC in IrDA mode
+spi@<addr> fsl,mpc5200-spi MPC5200 spi device
+ethernet@<addr> fsl,mpc5200-fec MPC5200 ethernet device
+ata@<addr> fsl,mpc5200-ata IDE ATA interface
+i2c@<addr> fsl,mpc5200-i2c I2C controller
+usb@<addr> fsl,mpc5200-ohci,ohci-be USB controller
+xlb@<addr> fsl,mpc5200-xlb XLB arbitrator
+
+fsl,mpc5200-gpt nodes
+---------------------
+On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board
+design supports the internal wdt, then the device node for GPT0 should
+include the empty property 'fsl,has-wdt'.
+
+An mpc5200-gpt can be used as a single line GPIO controller. To do so,
+add the following properties to the gpt node:
+ gpio-controller;
+ #gpio-cells = <2>;
+When referencing the GPIO line from another node, the first cell must always
+be zero and the second cell represents the gpio flags and described in the
+gpio device tree binding.
+
+An mpc5200-gpt can be used as a single line edge sensitive interrupt
+controller. To do so, add the following properties to the gpt node:
+ interrupt-controller;
+ #interrupt-cells = <1>;
+When referencing the IRQ line from another node, the cell represents the
+sense mode; 1 for edge rising, 2 for edge falling.
+
+fsl,mpc5200-psc nodes
+---------------------
+The PSCs should include a cell-index which is the index of the PSC in
+hardware. cell-index is used to determine which shared SoC registers to
+use when setting up PSC clocking. cell-index number starts at '0'. ie:
+ PSC1 has 'cell-index = <0>'
+ PSC4 has 'cell-index = <3>'
+
+PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in
+i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
+compatible field.
+
+
+fsl,mpc5200-gpio and fsl,mpc5200-gpio-wkup nodes
+------------------------------------------------
+Each GPIO controller node should have the empty property gpio-controller and
+#gpio-cells set to 2. First cell is the GPIO number which is interpreted
+according to the bit numbers in the GPIO control registers. The second cell
+is for flags which is currently unused.
+
+fsl,mpc5200-fec nodes
+---------------------
+The FEC node can specify one of the following properties to configure
+the MII link:
+- fsl,7-wire-mode - An empty property that specifies the link uses 7-wire
+ mode instead of MII
+- current-speed - Specifies that the MII should be configured for a fixed
+ speed. This property should contain two cells. The
+ first cell specifies the speed in Mbps and the second
+ should be '0' for half duplex and '1' for full duplex
+- phy-handle - Contains a phandle to an Ethernet PHY.
+
+Interrupt controller (fsl,mpc5200-pic) node
+-------------------------------------------
+The mpc5200 pic binding splits hardware IRQ numbers into two levels. The
+split reflects the layout of the PIC hardware itself, which groups
+interrupts into one of three groups; CRIT, MAIN or PERP. Also, the
+Bestcomm dma engine has it's own set of interrupt sources which are
+cascaded off of peripheral interrupt 0, which the driver interprets as a
+fourth group, SDMA.
+
+The interrupts property for device nodes using the mpc5200 pic consists
+of three cells; <L1 L2 level>
+
+ L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
+ L2 := interrupt number; directly mapped from the value in the
+ "ICTL PerStat, MainStat, CritStat Encoded Register"
+ level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]
+
+For external IRQs, use the following interrupt property values (how to
+specify external interrupts is a frequently asked question):
+External interrupts:
+ external irq0: interrupts = <0 0 n>;
+ external irq1: interrupts = <1 1 n>;
+ external irq2: interrupts = <1 2 n>;
+ external irq3: interrupts = <1 3 n>;
+'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low)
+
diff --git a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt b/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
deleted file mode 100644
index 6f12f1c79c0c..000000000000
--- a/Documentation/powerpc/mpc52xx-device-tree-bindings.txt
+++ /dev/null
@@ -1,277 +0,0 @@
-MPC5200 Device Tree Bindings
-----------------------------
-
-(c) 2006-2007 Secret Lab Technologies Ltd
-Grant Likely <grant.likely at secretlab.ca>
-
-********** DRAFT ***********
-* WARNING: Do not depend on the stability of these bindings just yet.
-* The MPC5200 device tree conventions are still in flux
-* Keep an eye on the linuxppc-dev mailing list for more details
-********** DRAFT ***********
-
-I - Introduction
-================
-Boards supported by the arch/powerpc architecture require device tree be
-passed by the boot loader to the kernel at boot time. The device tree
-describes what devices are present on the board and how they are
-connected. The device tree can either be passed as a binary blob (as
-described in Documentation/powerpc/booting-without-of.txt), or passed
-by Open Firmware (IEEE 1275) compatible firmware using an OF compatible
-client interface API.
-
-This document specifies the requirements on the device-tree for mpc5200
-based boards. These requirements are above and beyond the details
-specified in either the Open Firmware spec or booting-without-of.txt
-
-All new mpc5200-based boards are expected to match this document. In
-cases where this document is not sufficient to support a new board port,
-this document should be updated as part of adding the new board support.
-
-II - Philosophy
-===============
-The core of this document is naming convention. The whole point of
-defining this convention is to reduce or eliminate the number of
-special cases required to support a 5200 board. If all 5200 boards
-follow the same convention, then generic 5200 support code will work
-rather than coding special cases for each new board.
-
-This section tries to capture the thought process behind why the naming
-convention is what it is.
-
-1. names
----------
-There is strong convention/requirements already established for children
-of the root node. 'cpus' describes the processor cores, 'memory'
-describes memory, and 'chosen' provides boot configuration. Other nodes
-are added to describe devices attached to the processor local bus.
-
-Following convention already established with other system-on-chip
-processors, 5200 device trees should use the name 'soc5200' for the
-parent node of on chip devices, and the root node should be its parent.
-
-Child nodes are typically named after the configured function. ie.
-the FEC node is named 'ethernet', and a PSC in uart mode is named 'serial'.
-
-2. device_type property
------------------------
-similar to the node name convention above; the device_type reflects the
-configured function of a device. ie. 'serial' for a uart and 'spi' for
-an spi controller. However, while node names *should* reflect the
-configured function, device_type *must* match the configured function
-exactly.
-
-3. compatible property
-----------------------
-Since device_type isn't enough to match devices to drivers, there also
-needs to be a naming convention for the compatible property. Compatible
-is an list of device descriptions sorted from specific to generic. For
-the mpc5200, the required format for each compatible value is
-<chip>-<device>[-<mode>]. The OS should be able to match a device driver
-to the device based solely on the compatible value. If two drivers
-match on the compatible list; the 'most compatible' driver should be
-selected.
-
-The split between the MPC5200 and the MPC5200B leaves a bit of a
-conundrum. How should the compatible property be set up to provide
-maximum compatibility information; but still accurately describe the
-chip? For the MPC5200; the answer is easy. Most of the SoC devices
-originally appeared on the MPC5200. Since they didn't exist anywhere
-else; the 5200 compatible properties will contain only one item;
-"mpc5200-<device>".
-
-The 5200B is almost the same as the 5200, but not quite. It fixes
-silicon bugs and it adds a small number of enhancements. Most of the
-devices either provide exactly the same interface as on the 5200. A few
-devices have extra functions but still have a backwards compatible mode.
-To express this information as completely as possible, 5200B device trees
-should have two items in the compatible list;
-"mpc5200b-<device>\0mpc5200-<device>". It is *strongly* recommended
-that 5200B device trees follow this convention (instead of only listing
-the base mpc5200 item).
-
-If another chip appear on the market with one of the mpc5200 SoC
-devices, then the compatible list should include mpc5200-<device>.
-
-ie. ethernet on mpc5200: compatible = "mpc5200-ethernet"
- ethernet on mpc5200b: compatible = "mpc5200b-ethernet\0mpc5200-ethernet"
-
-Modal devices, like PSCs, also append the configured function to the
-end of the compatible field. ie. A PSC in i2s mode would specify
-"mpc5200-psc-i2s", not "mpc5200-i2s". This convention is chosen to
-avoid naming conflicts with non-psc devices providing the same
-function. For example, "mpc5200-spi" and "mpc5200-psc-spi" describe
-the mpc5200 simple spi device and a PSC spi mode respectively.
-
-If the soc device is more generic and present on other SOCs, the
-compatible property can specify the more generic device type also.
-
-ie. mscan: compatible = "mpc5200-mscan\0fsl,mscan";
-
-At the time of writing, exact chip may be either 'mpc5200' or
-'mpc5200b'.
-
-Device drivers should always try to match as generically as possible.
-
-III - Structure
-===============
-The device tree for an mpc5200 board follows the structure defined in
-booting-without-of.txt with the following additional notes:
-
-0) the root node
-----------------
-Typical root description node; see booting-without-of
-
-1) The cpus node
-----------------
-The cpus node follows the basic layout described in booting-without-of.
-The bus-frequency property holds the XLB bus frequency
-The clock-frequency property holds the core frequency
-
-2) The memory node
-------------------
-Typical memory description node; see booting-without-of.
-
-3) The soc5200 node
--------------------
-This node describes the on chip SOC peripherals. Every mpc5200 based
-board will have this node, and as such there is a common naming
-convention for SOC devices.
-
-Required properties:
-name type description
----- ---- -----------
-device_type string must be "soc"
-ranges int should be <0 baseaddr baseaddr+10000>
-reg int must be <baseaddr 10000>
-compatible string mpc5200: "mpc5200-soc"
- mpc5200b: "mpc5200b-soc\0mpc5200-soc"
-system-frequency int Fsystem frequency; source of all
- other clocks.
-bus-frequency int IPB bus frequency in HZ. Clock rate
- used by most of the soc devices.
-#interrupt-cells int must be <3>.
-
-Recommended properties:
-name type description
----- ---- -----------
-model string Exact model of the chip;
- ie: model="fsl,mpc5200"
-revision string Silicon revision of chip
- ie: revision="M08A"
-
-The 'model' and 'revision' properties are *strongly* recommended. Having
-them presence acts as a bit of a safety net for working around as yet
-undiscovered bugs on one version of silicon. For example, device drivers
-can use the model and revision properties to decide if a bug fix should
-be turned on.
-
-4) soc5200 child nodes
-----------------------
-Any on chip SOC devices available to Linux must appear as soc5200 child nodes.
-
-Note: The tables below show the value for the mpc5200. A mpc5200b device
-tree should use the "mpc5200b-<device>\0mpc5200-<device> form.
-
-Required soc5200 child nodes:
-name device_type compatible Description
----- ----------- ---------- -----------
-cdm@<addr> cdm mpc5200-cmd Clock Distribution
-pic@<addr> interrupt-controller mpc5200-pic need an interrupt
- controller to boot
-bestcomm@<addr> dma-controller mpc5200-bestcomm 5200 pic also requires
- the bestcomm device
-
-Recommended soc5200 child nodes; populate as needed for your board
-name device_type compatible Description
----- ----------- ---------- -----------
-gpt@<addr> gpt fsl,mpc5200-gpt General purpose timers
-gpt@<addr> gpt fsl,mpc5200-gpt-gpio General purpose
- timers in GPIO mode
-gpio@<addr> fsl,mpc5200-gpio MPC5200 simple gpio
- controller
-gpio@<addr> fsl,mpc5200-gpio-wkup MPC5200 wakeup gpio
- controller
-rtc@<addr> rtc mpc5200-rtc Real time clock
-mscan@<addr> mscan mpc5200-mscan CAN bus controller
-pci@<addr> pci mpc5200-pci PCI bridge
-serial@<addr> serial mpc5200-psc-uart PSC in serial mode
-i2s@<addr> sound mpc5200-psc-i2s PSC in i2s mode
-ac97@<addr> sound mpc5200-psc-ac97 PSC in ac97 mode
-spi@<addr> spi mpc5200-psc-spi PSC in spi mode
-irda@<addr> irda mpc5200-psc-irda PSC in IrDA mode
-spi@<addr> spi mpc5200-spi MPC5200 spi device
-ethernet@<addr> network mpc5200-fec MPC5200 ethernet device
-ata@<addr> ata mpc5200-ata IDE ATA interface
-i2c@<addr> i2c mpc5200-i2c I2C controller
-usb@<addr> usb-ohci-be mpc5200-ohci,ohci-be USB controller
-xlb@<addr> xlb mpc5200-xlb XLB arbitrator
-
-Important child node properties
-name type description
----- ---- -----------
-cell-index int When multiple devices are present, is the
- index of the device in the hardware (ie. There
- are 6 PSC on the 5200 numbered PSC1 to PSC6)
- PSC1 has 'cell-index = <0>'
- PSC4 has 'cell-index = <3>'
-
-5) General Purpose Timer nodes (child of soc5200 node)
-On the mpc5200 and 5200b, GPT0 has a watchdog timer function. If the board
-design supports the internal wdt, then the device node for GPT0 should
-include the empty property 'fsl,has-wdt'.
-
-6) PSC nodes (child of soc5200 node)
-PSC nodes can define the optional 'port-number' property to force assignment
-order of serial ports. For example, PSC5 might be physically connected to
-the port labeled 'COM1' and PSC1 wired to 'COM1'. In this case, PSC5 would
-have a "port-number = <0>" property, and PSC1 would have "port-number = <1>".
-
-PSC in i2s mode: The mpc5200 and mpc5200b PSCs are not compatible when in
-i2s mode. An 'mpc5200b-psc-i2s' node cannot include 'mpc5200-psc-i2s' in the
-compatible field.
-
-7) GPIO controller nodes
-Each GPIO controller node should have the empty property gpio-controller and
-#gpio-cells set to 2. First cell is the GPIO number which is interpreted
-according to the bit numbers in the GPIO control registers. The second cell
-is for flags which is currently unsused.
-
-8) FEC nodes
-The FEC node can specify one of the following properties to configure
-the MII link:
-"fsl,7-wire-mode" - An empty property that specifies the link uses 7-wire
- mode instead of MII
-"current-speed" - Specifies that the MII should be configured for a fixed
- speed. This property should contain two cells. The
- first cell specifies the speed in Mbps and the second
- should be '0' for half duplex and '1' for full duplex
-"phy-handle" - Contains a phandle to an Ethernet PHY.
-
-IV - Extra Notes
-================
-
-1. Interrupt mapping
---------------------
-The mpc5200 pic driver splits hardware IRQ numbers into two levels. The
-split reflects the layout of the PIC hardware itself, which groups
-interrupts into one of three groups; CRIT, MAIN or PERP. Also, the
-Bestcomm dma engine has it's own set of interrupt sources which are
-cascaded off of peripheral interrupt 0, which the driver interprets as a
-fourth group, SDMA.
-
-The interrupts property for device nodes using the mpc5200 pic consists
-of three cells; <L1 L2 level>
-
- L1 := [CRIT=0, MAIN=1, PERP=2, SDMA=3]
- L2 := interrupt number; directly mapped from the value in the
- "ICTL PerStat, MainStat, CritStat Encoded Register"
- level := [LEVEL_HIGH=0, EDGE_RISING=1, EDGE_FALLING=2, LEVEL_LOW=3]
-
-2. Shared registers
--------------------
-Some SoC devices share registers between them. ie. the i2c devices use
-a single clock control register, and almost all device are affected by
-the port_config register. Devices which need to manipulate shared regs
-should look to the parent SoC node. The soc node is responsible
-for arbitrating all shared register access.
diff --git a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt
index d30a281c570f..10711d9f0788 100644
--- a/Documentation/s390/Debugging390.txt
+++ b/Documentation/s390/Debugging390.txt
@@ -1402,7 +1402,7 @@ Syscalls are implemented on Linux for S390 by the Supervisor call instruction (S
possibilities of these as the instruction is made up of a 0xA opcode & the second byte being
the syscall number. They are traced using the simple command.
TR SVC <Optional value or range>
-the syscalls are defined in linux/include/asm-s390/unistd.h
+the syscalls are defined in linux/arch/s390/include/asm/unistd.h
e.g. to trace all file opens just do
TR SVC 5 ( as this is the syscall number of open )
diff --git a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt
index c4b7b2bd369a..480a78ef5a1e 100644
--- a/Documentation/s390/cds.txt
+++ b/Documentation/s390/cds.txt
@@ -98,7 +98,7 @@ platform. Some of the interface routines are specific to Linux/390 and some
of them can be found on other Linux platforms implementations too.
Miscellaneous function prototypes, data declarations, and macro definitions
can be found in the architecture specific C header file
-linux/include/asm-s390/irq.h.
+linux/arch/s390/include/asm/irq.h.
Overview of CDS interface concepts
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index e05420973698..2d10053dd97e 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -2,7 +2,7 @@ S390 Debug Feature
==================
files: arch/s390/kernel/debug.c
- include/asm-s390/debug.h
+ arch/s390/include/asm/debug.h
Description:
------------
diff --git a/Documentation/scheduler/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt
index 8398ca4ff4ed..6f33593e59e2 100644
--- a/Documentation/scheduler/sched-design-CFS.txt
+++ b/Documentation/scheduler/sched-design-CFS.txt
@@ -231,7 +231,7 @@ CPU bandwidth control purposes:
This options needs CONFIG_CGROUPS to be defined, and lets the administrator
create arbitrary groups of tasks, using the "cgroup" pseudo filesystem. See
- Documentation/cgroups.txt for more information about this filesystem.
+ Documentation/cgroups/cgroups.txt for more information about this filesystem.
Only one of these options to group tasks can be chosen and not both.
diff --git a/Documentation/scsi/ChangeLog.lpfc b/Documentation/scsi/ChangeLog.lpfc
index ae3f962a7cfc..ff19a52fe004 100644
--- a/Documentation/scsi/ChangeLog.lpfc
+++ b/Documentation/scsi/ChangeLog.lpfc
@@ -733,7 +733,7 @@ Changes from 20040920 to 20041018
I/O completion path a little more, especially taking care of
fast-pathing the non-error case. Also removes tons of dead
members and defines from lpfc_scsi.h - e.g. lpfc_target is down
- to nothing more then the lpfc_nodelist pointer.
+ to nothing more than the lpfc_nodelist pointer.
* Added binary sysfs file to issue mbox commands
* Replaced #if __BIG_ENDIAN with #if __BIG_ENDIAN_BITFIELD for
compatibility with the user space applications.
diff --git a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx
index a9f721aeb11c..8b278c10edfd 100644
--- a/Documentation/scsi/ChangeLog.ncr53c8xx
+++ b/Documentation/scsi/ChangeLog.ncr53c8xx
@@ -19,7 +19,7 @@ Sun Sep 24 21:30 2000 Gerard Roudier (groudier@club-internet.fr)
Wed Jul 26 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
* version ncr53c8xx-3.4.1
- - Provide OpenFirmare path through the proc FS on PPC.
+ - Provide OpenFirmware path through the proc FS on PPC.
- Remove trailing argument #2 from a couple of #undefs.
Sun Jul 09 16:30 2000 Gerard Roudier (groudier@club-internet.fr)
diff --git a/Documentation/scsi/ChangeLog.sym53c8xx b/Documentation/scsi/ChangeLog.sym53c8xx
index ef985ec348e6..02ffbc1e8a84 100644
--- a/Documentation/scsi/ChangeLog.sym53c8xx
+++ b/Documentation/scsi/ChangeLog.sym53c8xx
@@ -81,7 +81,7 @@ Sun Sep 24 21:30 2000 Gerard Roudier (groudier@club-internet.fr)
Wed Jul 26 23:30 2000 Gerard Roudier (groudier@club-internet.fr)
* version sym53c8xx-1.7.1
- - Provide OpenFirmare path through the proc FS on PPC.
+ - Provide OpenFirmware path through the proc FS on PPC.
- Download of on-chip SRAM using memcpy_toio() doesn't work
on PPC. Restore previous method (MEMORY MOVE from SCRIPTS).
- Remove trailing argument #2 from a couple of #undefs.
diff --git a/Documentation/scsi/scsi_fc_transport.txt b/Documentation/scsi/scsi_fc_transport.txt
index 38d324d62b25..e5b071d46619 100644
--- a/Documentation/scsi/scsi_fc_transport.txt
+++ b/Documentation/scsi/scsi_fc_transport.txt
@@ -191,7 +191,7 @@ Vport States:
This is equivalent to a driver "attach" on an adapter, which is
independent of the adapter's link state.
- Instantiation of the vport on the FC link via ELS traffic, etc.
- This is equivalent to a "link up" and successfull link initialization.
+ This is equivalent to a "link up" and successful link initialization.
Further information can be found in the interfaces section below for
Vport Creation.
@@ -320,7 +320,7 @@ Vport Creation:
This is equivalent to a driver "attach" on an adapter, which is
independent of the adapter's link state.
- Instantiation of the vport on the FC link via ELS traffic, etc.
- This is equivalent to a "link up" and successfull link initialization.
+ This is equivalent to a "link up" and successful link initialization.
The LLDD's vport_create() function will not synchronously wait for both
parts to be fully completed before returning. It must validate that the
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index 4b7ac21ea9eb..0f5d26bea80f 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -275,7 +275,8 @@ STAC9200
dell-m25 Dell Inspiron E1505n
dell-m26 Dell Inspiron 1501
dell-m27 Dell Inspiron E1705/9400
- gateway Gateway laptops with EAPD control
+ gateway-m4 Gateway laptops with EAPD control
+ gateway-m4-2 Gateway laptops with EAPD control
panasonic Panasonic CF-74
STAC9205/9254
@@ -302,6 +303,7 @@ STAC9220/9221
macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3)
imac-intel Intel iMac (eq. type 2)
imac-intel-20 Intel iMac (newer version) (eq. type 3)
+ ecs202 ECS/PC chips
dell-d81 Dell (unknown)
dell-d82 Dell (unknown)
dell-m81 Dell (unknown)
@@ -310,9 +312,13 @@ STAC9220/9221
STAC9202/9250/9251
==================
ref Reference board, base config
+ m1 Some Gateway MX series laptops (NX560XL)
+ m1-2 Some Gateway MX series laptops (MX6453)
+ m2 Some Gateway MX series laptops (M255)
m2-2 Some Gateway MX series laptops
+ m3 Some Gateway MX series laptops
+ m5 Some Gateway MX series laptops (MP6954)
m6 Some Gateway NX series laptops
- pa6 Gateway NX860 series
STAC9227/9228/9229/927x
=======================
@@ -329,6 +335,7 @@ STAC92HD71B*
dell-m4-1 Dell desktops
dell-m4-2 Dell desktops
dell-m4-3 Dell desktops
+ hp-m4 HP dv laptops
STAC92HD73*
===========
@@ -337,10 +344,12 @@ STAC92HD73*
dell-m6-amic Dell desktops/laptops with analog mics
dell-m6-dmic Dell desktops/laptops with digital mics
dell-m6 Dell desktops/laptops with both type of mics
+ dell-eq Dell desktops/laptops
STAC92HD83*
===========
ref Reference board
+ mic-ref Reference board with power managment for ports
STAC9872
========
diff --git a/Documentation/spi/spi-lm70llp b/Documentation/spi/spi-lm70llp
index 154bd02220b9..34a9cfd746bd 100644
--- a/Documentation/spi/spi-lm70llp
+++ b/Documentation/spi/spi-lm70llp
@@ -13,10 +13,20 @@ Description
This driver provides glue code connecting a National Semiconductor LM70 LLP
temperature sensor evaluation board to the kernel's SPI core subsystem.
+This is a SPI master controller driver. It can be used in conjunction with
+(layered under) the LM70 logical driver (a "SPI protocol driver").
In effect, this driver turns the parallel port interface on the eval board
into a SPI bus with a single device, which will be driven by the generic
LM70 driver (drivers/hwmon/lm70.c).
+
+Hardware Interfacing
+--------------------
+The schematic for this particular board (the LM70EVAL-LLP) is
+available (on page 4) here:
+
+ http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf
+
The hardware interfacing on the LM70 LLP eval board is as follows:
Parallel LM70 LLP
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index d79eeda7a699..3197fc83bc51 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -1,12 +1,13 @@
-Documentation for /proc/sys/vm/* kernel version 2.2.10
+Documentation for /proc/sys/vm/* kernel version 2.6.29
(c) 1998, 1999, Rik van Riel <riel@nl.linux.org>
+ (c) 2008 Peter W. Morreale <pmorreale@novell.com>
For general info and legal blurb, please look in README.
==============================================================
This file contains the documentation for the sysctl files in
-/proc/sys/vm and is valid for Linux kernel version 2.2.
+/proc/sys/vm and is valid for Linux kernel version 2.6.29.
The files in this directory can be used to tune the operation
of the virtual memory (VM) subsystem of the Linux kernel and
@@ -16,178 +17,274 @@ Default values and initialization routines for most of these
files can be found in mm/swap.c.
Currently, these files are in /proc/sys/vm:
-- overcommit_memory
-- page-cluster
-- dirty_ratio
+
+- block_dump
+- dirty_background_bytes
- dirty_background_ratio
+- dirty_bytes
- dirty_expire_centisecs
+- dirty_ratio
- dirty_writeback_centisecs
-- highmem_is_dirtyable (only if CONFIG_HIGHMEM set)
+- drop_caches
+- hugepages_treat_as_movable
+- hugetlb_shm_group
+- laptop_mode
+- legacy_va_layout
+- lowmem_reserve_ratio
- max_map_count
- min_free_kbytes
-- laptop_mode
-- block_dump
-- drop-caches
-- zone_reclaim_mode
-- min_unmapped_ratio
- min_slab_ratio
-- panic_on_oom
-- oom_dump_tasks
-- oom_kill_allocating_task
-- mmap_min_address
-- numa_zonelist_order
+- min_unmapped_ratio
+- mmap_min_addr
- nr_hugepages
- nr_overcommit_hugepages
+- nr_pdflush_threads
+- nr_trim_pages (only if CONFIG_MMU=n)
+- numa_zonelist_order
+- oom_dump_tasks
+- oom_kill_allocating_task
+- overcommit_memory
+- overcommit_ratio
+- page-cluster
+- panic_on_oom
+- percpu_pagelist_fraction
+- stat_interval
+- swappiness
+- vfs_cache_pressure
+- zone_reclaim_mode
+
==============================================================
-dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
-dirty_writeback_centisecs, highmem_is_dirtyable,
-vfs_cache_pressure, laptop_mode, block_dump, swap_token_timeout,
-drop-caches, hugepages_treat_as_movable:
+block_dump
-See Documentation/filesystems/proc.txt
+block_dump enables block I/O debugging when set to a nonzero value. More
+information on block I/O debugging is in Documentation/laptops/laptop-mode.txt.
==============================================================
-overcommit_memory:
+dirty_background_bytes
-This value contains a flag that enables memory overcommitment.
+Contains the amount of dirty memory at which the pdflush background writeback
+daemon will start writeback.
-When this flag is 0, the kernel attempts to estimate the amount
-of free memory left when userspace requests more memory.
+If dirty_background_bytes is written, dirty_background_ratio becomes a function
+of its value (dirty_background_bytes / the amount of dirtyable system memory).
-When this flag is 1, the kernel pretends there is always enough
-memory until it actually runs out.
+==============================================================
-When this flag is 2, the kernel uses a "never overcommit"
-policy that attempts to prevent any overcommit of memory.
+dirty_background_ratio
-This feature can be very useful because there are a lot of
-programs that malloc() huge amounts of memory "just-in-case"
-and don't use much of it.
+Contains, as a percentage of total system memory, the number of pages at which
+the pdflush background writeback daemon will start writing out dirty data.
-The default value is 0.
+==============================================================
-See Documentation/vm/overcommit-accounting and
-security/commoncap.c::cap_vm_enough_memory() for more information.
+dirty_bytes
+
+Contains the amount of dirty memory at which a process generating disk writes
+will itself start writeback.
+
+If dirty_bytes is written, dirty_ratio becomes a function of its value
+(dirty_bytes / the amount of dirtyable system memory).
==============================================================
-overcommit_ratio:
+dirty_expire_centisecs
-When overcommit_memory is set to 2, the committed address
-space is not permitted to exceed swap plus this percentage
-of physical RAM. See above.
+This tunable is used to define when dirty data is old enough to be eligible
+for writeout by the pdflush daemons. It is expressed in 100'ths of a second.
+Data which has been dirty in-memory for longer than this interval will be
+written out next time a pdflush daemon wakes up.
+
+==============================================================
+
+dirty_ratio
+
+Contains, as a percentage of total system memory, the number of pages at which
+a process which is generating disk writes will itself start writing out dirty
+data.
==============================================================
-page-cluster:
+dirty_writeback_centisecs
-The Linux VM subsystem avoids excessive disk seeks by reading
-multiple pages on a page fault. The number of pages it reads
-is dependent on the amount of memory in your machine.
+The pdflush writeback daemons will periodically wake up and write `old' data
+out to disk. This tunable expresses the interval between those wakeups, in
+100'ths of a second.
-The number of pages the kernel reads in at once is equal to
-2 ^ page-cluster. Values above 2 ^ 5 don't make much sense
-for swap because we only cluster swap data in 32-page groups.
+Setting this to zero disables periodic writeback altogether.
==============================================================
-max_map_count:
+drop_caches
-This file contains the maximum number of memory map areas a process
-may have. Memory map areas are used as a side-effect of calling
-malloc, directly by mmap and mprotect, and also when loading shared
-libraries.
+Writing to this will cause the kernel to drop clean caches, dentries and
+inodes from memory, causing that memory to become free.
-While most applications need less than a thousand maps, certain
-programs, particularly malloc debuggers, may consume lots of them,
-e.g., up to one or two maps per allocation.
+To free pagecache:
+ echo 1 > /proc/sys/vm/drop_caches
+To free dentries and inodes:
+ echo 2 > /proc/sys/vm/drop_caches
+To free pagecache, dentries and inodes:
+ echo 3 > /proc/sys/vm/drop_caches
-The default value is 65536.
+As this is a non-destructive operation and dirty objects are not freeable, the
+user should run `sync' first.
==============================================================
-min_free_kbytes:
+hugepages_treat_as_movable
-This is used to force the Linux VM to keep a minimum number
-of kilobytes free. The VM uses this number to compute a pages_min
-value for each lowmem zone in the system. Each lowmem zone gets
-a number of reserved free pages based proportionally on its size.
+This parameter is only useful when kernelcore= is specified at boot time to
+create ZONE_MOVABLE for pages that may be reclaimed or migrated. Huge pages
+are not movable so are not normally allocated from ZONE_MOVABLE. A non-zero
+value written to hugepages_treat_as_movable allows huge pages to be allocated
+from ZONE_MOVABLE.
-Some minimal amount of memory is needed to satisfy PF_MEMALLOC
-allocations; if you set this to lower than 1024KB, your system will
-become subtly broken, and prone to deadlock under high loads.
-
-Setting this too high will OOM your machine instantly.
+Once enabled, the ZONE_MOVABLE is treated as an area of memory the huge
+pages pool can easily grow or shrink within. Assuming that applications are
+not running that mlock() a lot of memory, it is likely the huge pages pool
+can grow to the size of ZONE_MOVABLE by repeatedly entering the desired value
+into nr_hugepages and triggering page reclaim.
==============================================================
-percpu_pagelist_fraction
+hugetlb_shm_group
-This is the fraction of pages at most (high mark pcp->high) in each zone that
-are allocated for each per cpu page list. The min value for this is 8. It
-means that we don't allow more than 1/8th of pages in each zone to be
-allocated in any single per_cpu_pagelist. This entry only changes the value
-of hot per cpu pagelists. User can specify a number like 100 to allocate
-1/100th of each zone to each per cpu page list.
+hugetlb_shm_group contains group id that is allowed to create SysV
+shared memory segment using hugetlb page.
-The batch value of each per cpu pagelist is also updated as a result. It is
-set to pcp->high/4. The upper limit of batch is (PAGE_SHIFT * 8)
+==============================================================
-The initial value is zero. Kernel does not use this value at boot time to set
-the high water marks for each per cpu page list.
+laptop_mode
-===============================================================
+laptop_mode is a knob that controls "laptop mode". All the things that are
+controlled by this knob are discussed in Documentation/laptops/laptop-mode.txt.
-zone_reclaim_mode:
+==============================================================
-Zone_reclaim_mode allows someone to set more or less aggressive approaches to
-reclaim memory when a zone runs out of memory. If it is set to zero then no
-zone reclaim occurs. Allocations will be satisfied from other zones / nodes
-in the system.
+legacy_va_layout
-This is value ORed together of
+If non-zero, this sysctl disables the new 32-bit mmap mmap layout - the kernel
+will use the legacy (2.4) layout for all processes.
-1 = Zone reclaim on
-2 = Zone reclaim writes dirty pages out
-4 = Zone reclaim swaps pages
+==============================================================
-zone_reclaim_mode is set during bootup to 1 if it is determined that pages
-from remote zones will cause a measurable performance reduction. The
-page allocator will then reclaim easily reusable pages (those page
-cache pages that are currently not used) before allocating off node pages.
+lowmem_reserve_ratio
+
+For some specialised workloads on highmem machines it is dangerous for
+the kernel to allow process memory to be allocated from the "lowmem"
+zone. This is because that memory could then be pinned via the mlock()
+system call, or by unavailability of swapspace.
+
+And on large highmem machines this lack of reclaimable lowmem memory
+can be fatal.
+
+So the Linux page allocator has a mechanism which prevents allocations
+which _could_ use highmem from using too much lowmem. This means that
+a certain amount of lowmem is defended from the possibility of being
+captured into pinned user memory.
+
+(The same argument applies to the old 16 megabyte ISA DMA region. This
+mechanism will also defend that region from allocations which could use
+highmem or lowmem).
+
+The `lowmem_reserve_ratio' tunable determines how aggressive the kernel is
+in defending these lower zones.
+
+If you have a machine which uses highmem or ISA DMA and your
+applications are using mlock(), or if you are running with no swap then
+you probably should change the lowmem_reserve_ratio setting.
+
+The lowmem_reserve_ratio is an array. You can see them by reading this file.
+-
+% cat /proc/sys/vm/lowmem_reserve_ratio
+256 256 32
+-
+Note: # of this elements is one fewer than number of zones. Because the highest
+ zone's value is not necessary for following calculation.
+
+But, these values are not used directly. The kernel calculates # of protection
+pages for each zones from them. These are shown as array of protection pages
+in /proc/zoneinfo like followings. (This is an example of x86-64 box).
+Each zone has an array of protection pages like this.
+
+-
+Node 0, zone DMA
+ pages free 1355
+ min 3
+ low 3
+ high 4
+ :
+ :
+ numa_other 0
+ protection: (0, 2004, 2004, 2004)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ pagesets
+ cpu: 0 pcp: 0
+ :
+-
+These protections are added to score to judge whether this zone should be used
+for page allocation or should be reclaimed.
+
+In this example, if normal pages (index=2) are required to this DMA zone and
+pages_high is used for watermark, the kernel judges this zone should not be
+used because pages_free(1355) is smaller than watermark + protection[2]
+(4 + 2004 = 2008). If this protection value is 0, this zone would be used for
+normal page requirement. If requirement is DMA zone(index=0), protection[0]
+(=0) is used.
+
+zone[i]'s protection[j] is calculated by following expression.
+
+(i < j):
+ zone[i]->protection[j]
+ = (total sums of present_pages from zone[i+1] to zone[j] on the node)
+ / lowmem_reserve_ratio[i];
+(i = j):
+ (should not be protected. = 0;
+(i > j):
+ (not necessary, but looks 0)
+
+The default values of lowmem_reserve_ratio[i] are
+ 256 (if zone[i] means DMA or DMA32 zone)
+ 32 (others).
+As above expression, they are reciprocal number of ratio.
+256 means 1/256. # of protection pages becomes about "0.39%" of total present
+pages of higher zones on the node.
+
+If you would like to protect more pages, smaller values are effective.
+The minimum value is 1 (1/1 -> 100%).
-It may be beneficial to switch off zone reclaim if the system is
-used for a file server and all of memory should be used for caching files
-from disk. In that case the caching effect is more important than
-data locality.
+==============================================================
-Allowing zone reclaim to write out pages stops processes that are
-writing large amounts of data from dirtying pages on other nodes. Zone
-reclaim will write out dirty pages if a zone fills up and so effectively
-throttle the process. This may decrease the performance of a single process
-since it cannot use all of system memory to buffer the outgoing writes
-anymore but it preserve the memory on other nodes so that the performance
-of other processes running on other nodes will not be affected.
+max_map_count:
-Allowing regular swap effectively restricts allocations to the local
-node unless explicitly overridden by memory policies or cpuset
-configurations.
+This file contains the maximum number of memory map areas a process
+may have. Memory map areas are used as a side-effect of calling
+malloc, directly by mmap and mprotect, and also when loading shared
+libraries.
-=============================================================
+While most applications need less than a thousand maps, certain
+programs, particularly malloc debuggers, may consume lots of them,
+e.g., up to one or two maps per allocation.
-min_unmapped_ratio:
+The default value is 65536.
-This is available only on NUMA kernels.
+==============================================================
-A percentage of the total pages in each zone. Zone reclaim will only
-occur if more than this percentage of pages are file backed and unmapped.
-This is to insure that a minimal amount of local pages is still available for
-file I/O even if the node is overallocated.
+min_free_kbytes:
-The default is 1 percent.
+This is used to force the Linux VM to keep a minimum number
+of kilobytes free. The VM uses this number to compute a pages_min
+value for each lowmem zone in the system. Each lowmem zone gets
+a number of reserved free pages based proportionally on its size.
+
+Some minimal amount of memory is needed to satisfy PF_MEMALLOC
+allocations; if you set this to lower than 1024KB, your system will
+become subtly broken, and prone to deadlock under high loads.
+
+Setting this too high will OOM your machine instantly.
=============================================================
@@ -209,82 +306,73 @@ and may not be fast.
=============================================================
-panic_on_oom
+min_unmapped_ratio:
-This enables or disables panic on out-of-memory feature.
+This is available only on NUMA kernels.
-If this is set to 0, the kernel will kill some rogue process,
-called oom_killer. Usually, oom_killer can kill rogue processes and
-system will survive.
+A percentage of the total pages in each zone. Zone reclaim will only
+occur if more than this percentage of pages are file backed and unmapped.
+This is to insure that a minimal amount of local pages is still available for
+file I/O even if the node is overallocated.
-If this is set to 1, the kernel panics when out-of-memory happens.
-However, if a process limits using nodes by mempolicy/cpusets,
-and those nodes become memory exhaustion status, one process
-may be killed by oom-killer. No panic occurs in this case.
-Because other nodes' memory may be free. This means system total status
-may be not fatal yet.
+The default is 1 percent.
-If this is set to 2, the kernel panics compulsorily even on the
-above-mentioned.
+==============================================================
-The default value is 0.
-1 and 2 are for failover of clustering. Please select either
-according to your policy of failover.
+mmap_min_addr
-=============================================================
+This file indicates the amount of address space which a user process will
+be restricted from mmaping. Since kernel null dereference bugs could
+accidentally operate based on the information in the first couple of pages
+of memory userspace processes should not be allowed to write to them. By
+default this value is set to 0 and no protections will be enforced by the
+security module. Setting this value to something like 64k will allow the
+vast majority of applications to work correctly and provide defense in depth
+against future potential kernel bugs.
-oom_dump_tasks
+==============================================================
-Enables a system-wide task dump (excluding kernel threads) to be
-produced when the kernel performs an OOM-killing and includes such
-information as pid, uid, tgid, vm size, rss, cpu, oom_adj score, and
-name. This is helpful to determine why the OOM killer was invoked
-and to identify the rogue task that caused it.
+nr_hugepages
-If this is set to zero, this information is suppressed. On very
-large systems with thousands of tasks it may not be feasible to dump
-the memory state information for each one. Such systems should not
-be forced to incur a performance penalty in OOM conditions when the
-information may not be desired.
+Change the minimum size of the hugepage pool.
-If this is set to non-zero, this information is shown whenever the
-OOM killer actually kills a memory-hogging task.
+See Documentation/vm/hugetlbpage.txt
-The default value is 0.
+==============================================================
-=============================================================
+nr_overcommit_hugepages
-oom_kill_allocating_task
+Change the maximum size of the hugepage pool. The maximum is
+nr_hugepages + nr_overcommit_hugepages.
-This enables or disables killing the OOM-triggering task in
-out-of-memory situations.
+See Documentation/vm/hugetlbpage.txt
-If this is set to zero, the OOM killer will scan through the entire
-tasklist and select a task based on heuristics to kill. This normally
-selects a rogue memory-hogging task that frees up a large amount of
-memory when killed.
+==============================================================
-If this is set to non-zero, the OOM killer simply kills the task that
-triggered the out-of-memory condition. This avoids the expensive
-tasklist scan.
+nr_pdflush_threads
-If panic_on_oom is selected, it takes precedence over whatever value
-is used in oom_kill_allocating_task.
+The current number of pdflush threads. This value is read-only.
+The value changes according to the number of dirty pages in the system.
-The default value is 0.
+When neccessary, additional pdflush threads are created, one per second, up to
+nr_pdflush_threads_max.
==============================================================
-mmap_min_addr
+nr_trim_pages
-This file indicates the amount of address space which a user process will
-be restricted from mmaping. Since kernel null dereference bugs could
-accidentally operate based on the information in the first couple of pages
-of memory userspace processes should not be allowed to write to them. By
-default this value is set to 0 and no protections will be enforced by the
-security module. Setting this value to something like 64k will allow the
-vast majority of applications to work correctly and provide defense in depth
-against future potential kernel bugs.
+This is available only on NOMMU kernels.
+
+This value adjusts the excess page trimming behaviour of power-of-2 aligned
+NOMMU mmap allocations.
+
+A value of 0 disables trimming of allocations entirely, while a value of 1
+trims excess pages aggressively. Any value >= 1 acts as the watermark where
+trimming of allocations is initiated.
+
+The default value is 1.
+
+See Documentation/nommu-mmap.txt for more information.
==============================================================
@@ -333,17 +421,199 @@ this is causing problems for your system/application.
==============================================================
-nr_hugepages
+oom_dump_tasks
-Change the minimum size of the hugepage pool.
+Enables a system-wide task dump (excluding kernel threads) to be
+produced when the kernel performs an OOM-killing and includes such
+information as pid, uid, tgid, vm size, rss, cpu, oom_adj score, and
+name. This is helpful to determine why the OOM killer was invoked
+and to identify the rogue task that caused it.
-See Documentation/vm/hugetlbpage.txt
+If this is set to zero, this information is suppressed. On very
+large systems with thousands of tasks it may not be feasible to dump
+the memory state information for each one. Such systems should not
+be forced to incur a performance penalty in OOM conditions when the
+information may not be desired.
+
+If this is set to non-zero, this information is shown whenever the
+OOM killer actually kills a memory-hogging task.
+
+The default value is 0.
==============================================================
-nr_overcommit_hugepages
+oom_kill_allocating_task
-Change the maximum size of the hugepage pool. The maximum is
-nr_hugepages + nr_overcommit_hugepages.
+This enables or disables killing the OOM-triggering task in
+out-of-memory situations.
-See Documentation/vm/hugetlbpage.txt
+If this is set to zero, the OOM killer will scan through the entire
+tasklist and select a task based on heuristics to kill. This normally
+selects a rogue memory-hogging task that frees up a large amount of
+memory when killed.
+
+If this is set to non-zero, the OOM killer simply kills the task that
+triggered the out-of-memory condition. This avoids the expensive
+tasklist scan.
+
+If panic_on_oom is selected, it takes precedence over whatever value
+is used in oom_kill_allocating_task.
+
+The default value is 0.
+
+==============================================================
+
+overcommit_memory:
+
+This value contains a flag that enables memory overcommitment.
+
+When this flag is 0, the kernel attempts to estimate the amount
+of free memory left when userspace requests more memory.
+
+When this flag is 1, the kernel pretends there is always enough
+memory until it actually runs out.
+
+When this flag is 2, the kernel uses a "never overcommit"
+policy that attempts to prevent any overcommit of memory.
+
+This feature can be very useful because there are a lot of
+programs that malloc() huge amounts of memory "just-in-case"
+and don't use much of it.
+
+The default value is 0.
+
+See Documentation/vm/overcommit-accounting and
+security/commoncap.c::cap_vm_enough_memory() for more information.
+
+==============================================================
+
+overcommit_ratio:
+
+When overcommit_memory is set to 2, the committed address
+space is not permitted to exceed swap plus this percentage
+of physical RAM. See above.
+
+==============================================================
+
+page-cluster
+
+page-cluster controls the number of pages which are written to swap in
+a single attempt. The swap I/O size.
+
+It is a logarithmic value - setting it to zero means "1 page", setting
+it to 1 means "2 pages", setting it to 2 means "4 pages", etc.
+
+The default value is three (eight pages at a time). There may be some
+small benefits in tuning this to a different value if your workload is
+swap-intensive.
+
+=============================================================
+
+panic_on_oom
+
+This enables or disables panic on out-of-memory feature.
+
+If this is set to 0, the kernel will kill some rogue process,
+called oom_killer. Usually, oom_killer can kill rogue processes and
+system will survive.
+
+If this is set to 1, the kernel panics when out-of-memory happens.
+However, if a process limits using nodes by mempolicy/cpusets,
+and those nodes become memory exhaustion status, one process
+may be killed by oom-killer. No panic occurs in this case.
+Because other nodes' memory may be free. This means system total status
+may be not fatal yet.
+
+If this is set to 2, the kernel panics compulsorily even on the
+above-mentioned.
+
+The default value is 0.
+1 and 2 are for failover of clustering. Please select either
+according to your policy of failover.
+
+=============================================================
+
+percpu_pagelist_fraction
+
+This is the fraction of pages at most (high mark pcp->high) in each zone that
+are allocated for each per cpu page list. The min value for this is 8. It
+means that we don't allow more than 1/8th of pages in each zone to be
+allocated in any single per_cpu_pagelist. This entry only changes the value
+of hot per cpu pagelists. User can specify a number like 100 to allocate
+1/100th of each zone to each per cpu page list.
+
+The batch value of each per cpu pagelist is also updated as a result. It is
+set to pcp->high/4. The upper limit of batch is (PAGE_SHIFT * 8)
+
+The initial value is zero. Kernel does not use this value at boot time to set
+the high water marks for each per cpu page list.
+
+==============================================================
+
+stat_interval
+
+The time interval between which vm statistics are updated. The default
+is 1 second.
+
+==============================================================
+
+swappiness
+
+This control is used to define how aggressive the kernel will swap
+memory pages. Higher values will increase agressiveness, lower values
+descrease the amount of swap.
+
+The default value is 60.
+
+==============================================================
+
+vfs_cache_pressure
+------------------
+
+Controls the tendency of the kernel to reclaim the memory which is used for
+caching of directory and inode objects.
+
+At the default value of vfs_cache_pressure=100 the kernel will attempt to
+reclaim dentries and inodes at a "fair" rate with respect to pagecache and
+swapcache reclaim. Decreasing vfs_cache_pressure causes the kernel to prefer
+to retain dentry and inode caches. Increasing vfs_cache_pressure beyond 100
+causes the kernel to prefer to reclaim dentries and inodes.
+
+==============================================================
+
+zone_reclaim_mode:
+
+Zone_reclaim_mode allows someone to set more or less aggressive approaches to
+reclaim memory when a zone runs out of memory. If it is set to zero then no
+zone reclaim occurs. Allocations will be satisfied from other zones / nodes
+in the system.
+
+This is value ORed together of
+
+1 = Zone reclaim on
+2 = Zone reclaim writes dirty pages out
+4 = Zone reclaim swaps pages
+
+zone_reclaim_mode is set during bootup to 1 if it is determined that pages
+from remote zones will cause a measurable performance reduction. The
+page allocator will then reclaim easily reusable pages (those page
+cache pages that are currently not used) before allocating off node pages.
+
+It may be beneficial to switch off zone reclaim if the system is
+used for a file server and all of memory should be used for caching files
+from disk. In that case the caching effect is more important than
+data locality.
+
+Allowing zone reclaim to write out pages stops processes that are
+writing large amounts of data from dirtying pages on other nodes. Zone
+reclaim will write out dirty pages if a zone fills up and so effectively
+throttle the process. This may decrease the performance of a single process
+since it cannot use all of system memory to buffer the outgoing writes
+anymore but it preserve the memory on other nodes so that the performance
+of other processes running on other nodes will not be affected.
+
+Allowing regular swap effectively restricts allocations to the local
+node unless explicitly overridden by memory policies or cpuset
+configurations.
+
+============ End of Document =================================
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 10a0263ebb3f..9e592c718afb 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -1,6 +1,5 @@
Linux Magic System Request Key Hacks
Documentation for sysrq.c
-Last update: 2007-AUG-04
* What is the magic SysRq key?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -211,6 +210,24 @@ within a function called by handle_sysrq, you must be aware that you are in
a lock (you are also in an interrupt handler, which means don't sleep!), so
you must call __handle_sysrq_nolock instead.
+* When I hit a SysRq key combination only the header appears on the console?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Sysrq output is subject to the same console loglevel control as all
+other console output. This means that if the kernel was booted 'quiet'
+as is common on distro kernels the output may not appear on the actual
+console, even though it will appear in the dmesg buffer, and be accessible
+via the dmesg command and to the consumers of /proc/kmsg. As a specific
+exception the header line from the sysrq command is passed to all console
+consumers as if the current loglevel was maximum. If only the header
+is emitted it is almost certain that the kernel loglevel is too low.
+Should you require the output on the console channel then you will need
+to temporarily up the console loglevel using alt-sysrq-8 or:
+
+ echo 8 > /proc/sysrq-trigger
+
+Remember to return the loglevel to normal after triggering the sysrq
+command you are interested in.
+
* I have more questions, who can I ask?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
And I'll answer any questions about the registration system you got, also
diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt
index e8b50b7de9d9..cfdcd16e3abf 100644
--- a/Documentation/usb/dma.txt
+++ b/Documentation/usb/dma.txt
@@ -6,8 +6,9 @@ in the kernel usb programming guide (kerneldoc, from the source code).
API OVERVIEW
The big picture is that USB drivers can continue to ignore most DMA issues,
-though they still must provide DMA-ready buffers (see DMA-mapping.txt).
-That's how they've worked through the 2.4 (and earlier) kernels.
+though they still must provide DMA-ready buffers (see
+Documentation/PCI/PCI-DMA-mapping.txt). That's how they've worked through
+the 2.4 (and earlier) kernels.
OR: they can now be DMA-aware.
@@ -62,8 +63,8 @@ and effects like cache-trashing can impose subtle penalties.
force a consistent memory access ordering by using memory barriers. It's
not using a streaming DMA mapping, so it's good for small transfers on
systems where the I/O would otherwise thrash an IOMMU mapping. (See
- Documentation/DMA-mapping.txt for definitions of "coherent" and "streaming"
- DMA mappings.)
+ Documentation/PCI/PCI-DMA-mapping.txt for definitions of "coherent" and
+ "streaming" DMA mappings.)
Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
space-efficient.
@@ -93,7 +94,7 @@ WORKING WITH EXISTING BUFFERS
Existing buffers aren't usable for DMA without first being mapped into the
DMA address space of the device. However, most buffers passed to your
driver can safely be used with such DMA mapping. (See the first section
-of DMA-mapping.txt, titled "What memory is DMA-able?")
+of Documentation/PCI/PCI-DMA-mapping.txt, titled "What memory is DMA-able?")
- When you're using scatterlists, you can map everything at once. On some
systems, this kicks in an IOMMU and turns the scatterlists into single
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index e48ea1d51010..ad642615ad4c 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -313,11 +313,13 @@ three of the methods listed above. In addition, a driver indicates
that it supports autosuspend by setting the .supports_autosuspend flag
in its usb_driver structure. It is then responsible for informing the
USB core whenever one of its interfaces becomes busy or idle. The
-driver does so by calling these three functions:
+driver does so by calling these five functions:
int usb_autopm_get_interface(struct usb_interface *intf);
void usb_autopm_put_interface(struct usb_interface *intf);
int usb_autopm_set_interface(struct usb_interface *intf);
+ int usb_autopm_get_interface_async(struct usb_interface *intf);
+ void usb_autopm_put_interface_async(struct usb_interface *intf);
The functions work by maintaining a counter in the usb_interface
structure. When intf->pm_usage_count is > 0 then the interface is
@@ -330,10 +332,12 @@ associated with the device itself rather than any of its interfaces.
This field is used only by the USB core.)
The driver owns intf->pm_usage_count; it can modify the value however
-and whenever it likes. A nice aspect of the usb_autopm_* routines is
-that the changes they make are protected by the usb_device structure's
-PM mutex (udev->pm_mutex); however drivers may change pm_usage_count
-without holding the mutex.
+and whenever it likes. A nice aspect of the non-async usb_autopm_*
+routines is that the changes they make are protected by the usb_device
+structure's PM mutex (udev->pm_mutex); however drivers may change
+pm_usage_count without holding the mutex. Drivers using the async
+routines are responsible for their own synchronization and mutual
+exclusion.
usb_autopm_get_interface() increments pm_usage_count and
attempts an autoresume if the new value is > 0 and the
@@ -348,6 +352,14 @@ without holding the mutex.
is suspended, and it attempts an autosuspend if the value is
<= 0 and the device isn't suspended.
+ usb_autopm_get_interface_async() and
+ usb_autopm_put_interface_async() do almost the same things as
+ their non-async counterparts. The differences are: they do
+ not acquire the PM mutex, and they use a workqueue to do their
+ jobs. As a result they can be called in an atomic context,
+ such as an URB's completion handler, but when they return the
+ device will not generally not yet be in the desired state.
+
There also are a couple of utility routines drivers can use:
usb_autopm_enable() sets pm_usage_cnt to 0 and then calls
diff --git a/Documentation/usb/wusb-cbaf b/Documentation/usb/wusb-cbaf
index 2e78b70f3adc..426ddaaef96f 100644
--- a/Documentation/usb/wusb-cbaf
+++ b/Documentation/usb/wusb-cbaf
@@ -80,12 +80,6 @@ case $1 in
start)
for dev in ${2:-$hdevs}
do
- uwb_rc=$(readlink -f $dev/uwb_rc)
- if cat $uwb_rc/beacon | grep -q -- "-1"
- then
- echo 13 0 > $uwb_rc/beacon
- echo I: started beaconing on ch 13 on $(basename $uwb_rc) >&2
- fi
echo $host_CHID > $dev/wusb_chid
echo I: started host $(basename $dev) >&2
done
@@ -95,9 +89,6 @@ case $1 in
do
echo 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > $dev/wusb_chid
echo I: stopped host $(basename $dev) >&2
- uwb_rc=$(readlink -f $dev/uwb_rc)
- echo -1 | cat > $uwb_rc/beacon
- echo I: stopped beaconing on $(basename $uwb_rc) >&2
done
;;
set-chid)
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 335aef4dcaeb..b8d470596b0c 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -152,3 +152,4 @@
151 -> ADS Tech Instant HDTV [1421:0380]
152 -> Asus Tiger Rev:1.00 [1043:4857]
153 -> Kworld Plus TV Analog Lite PCI [17de:7128]
+154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d]
diff --git a/Documentation/video4linux/si470x.txt b/Documentation/video4linux/si470x.txt
index 11c5fd22a332..49679e6aaa76 100644
--- a/Documentation/video4linux/si470x.txt
+++ b/Documentation/video4linux/si470x.txt
@@ -41,6 +41,7 @@ chips are known to work:
- 10c4:818a: Silicon Labs USB FM Radio Reference Design
- 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
- 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
+- 10c5:819a: DealExtreme USB Radio
Software
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index eeae76c22a93..ff124374e9ba 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -184,7 +184,7 @@ may be NULL if the subdev driver does not support anything from that category.
It looks like this:
struct v4l2_subdev_core_ops {
- int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip);
+ int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
int (*log_status)(struct v4l2_subdev *sd);
int (*init)(struct v4l2_subdev *sd, u32 val);
...
@@ -390,16 +390,18 @@ allocated memory.
You should also set these fields:
-- parent: set to the parent device (same device as was used to register
- v4l2_device).
+- v4l2_dev: set to the v4l2_device parent device.
- name: set to something descriptive and unique.
-- fops: set to the file_operations struct.
+- fops: set to the v4l2_file_operations struct.
- ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
(highly recommended to use this and it might become compulsory in the
future!), then set this to your v4l2_ioctl_ops struct.
-If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to
-__video_ioctl2 or .ioctl to video_ioctl2 in your file_operations struct.
+If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
+.ioctl to video_ioctl2 in your v4l2_file_operations struct.
+
+The v4l2_file_operations struct is a subset of file_operations. The main
+difference is that the inode argument is omitted since it is never used.
video_device registration
@@ -410,7 +412,7 @@ for you.
err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
if (err) {
- video_device_release(vdev); // or kfree(my_vdev);
+ video_device_release(vdev); /* or kfree(my_vdev); */
return err;
}
@@ -516,5 +518,4 @@ void *video_drvdata(struct file *file);
You can go from a video_device struct to the v4l2_device struct using:
-struct v4l2_device *v4l2_dev = dev_get_drvdata(vdev->parent);
-
+struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c
index 079b628481cf..d6e70bef8ad0 100644
--- a/Documentation/video4linux/v4lgrab.c
+++ b/Documentation/video4linux/v4lgrab.c
@@ -4,12 +4,21 @@
*
* Compile with:
* gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
- * Use as:
- * v4lgrab >image.ppm
+ * Use as:
+ * v4lgrab >image.ppm
*
* Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
- * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
- * with minor modifications (Dave Forrest, drf5n@virginia.edu).
+ * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
+ * with minor modifications (Dave Forrest, drf5n@virginia.edu).
+ *
+ *
+ * For some cameras you may need to pre-load libv4l to perform
+ * the necessary decompression, e.g.:
+ *
+ * export LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
+ * ./v4lgrab >image.ppm
+ *
+ * see http://hansdegoede.livejournal.com/3636.html for details.
*
*/
@@ -24,7 +33,7 @@
#include <linux/types.h>
#include <linux/videodev.h>
-#define FILE "/dev/video0"
+#define VIDEO_DEV "/dev/video0"
/* Stole this from tvset.c */
@@ -90,7 +99,7 @@ int get_brightness_adj(unsigned char *image, long size, int *brightness) {
int main(int argc, char ** argv)
{
- int fd = open(FILE, O_RDONLY), f;
+ int fd = open(VIDEO_DEV, O_RDONLY), f;
struct video_capability cap;
struct video_window win;
struct video_picture vpic;
@@ -100,13 +109,13 @@ int main(int argc, char ** argv)
unsigned int i, src_depth;
if (fd < 0) {
- perror(FILE);
+ perror(VIDEO_DEV);
exit(1);
}
if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
perror("VIDIOGCAP");
- fprintf(stderr, "(" FILE " not a video4linux device?)\n");
+ fprintf(stderr, "(" VIDEO_DEV " not a video4linux device?)\n");
close(fd);
exit(1);
}
diff --git a/Documentation/vm/unevictable-lru.txt b/Documentation/vm/unevictable-lru.txt
index 125eed560e5a..0706a7282a8c 100644
--- a/Documentation/vm/unevictable-lru.txt
+++ b/Documentation/vm/unevictable-lru.txt
@@ -137,13 +137,6 @@ shrink_page_list() where they will be detected when vmscan walks the reverse
map in try_to_unmap(). If try_to_unmap() returns SWAP_MLOCK, shrink_page_list()
will cull the page at that point.
-Note that for anonymous pages, shrink_page_list() attempts to add the page to
-the swap cache before it tries to unmap the page. To avoid this unnecessary
-consumption of swap space, shrink_page_list() calls try_to_munlock() to check
-whether any VM_LOCKED vmas map the page without attempting to unmap the page.
-If try_to_munlock() returns SWAP_MLOCK, shrink_page_list() will cull the page
-without consuming swap space. try_to_munlock() will be described below.
-
To "cull" an unevictable page, vmscan simply puts the page back on the lru
list using putback_lru_page()--the inverse operation to isolate_lru_page()--
after dropping the page lock. Because the condition which makes the page
@@ -190,8 +183,8 @@ several places:
in the VM_LOCKED flag being set for the vma.
3) in the fault path, if mlocked pages are "culled" in the fault path,
and when a VM_LOCKED stack segment is expanded.
-4) as mentioned above, in vmscan:shrink_page_list() with attempting to
- reclaim a page in a VM_LOCKED vma--via try_to_unmap() or try_to_munlock().
+4) as mentioned above, in vmscan:shrink_page_list() when attempting to
+ reclaim a page in a VM_LOCKED vma via try_to_unmap().
Mlocked pages become unlocked and rescued from the unevictable list when:
@@ -260,9 +253,9 @@ mlock_fixup() filters several classes of "special" vmas:
2) vmas mapping hugetlbfs page are already effectively pinned into memory.
We don't need nor want to mlock() these pages. However, to preserve the
- prior behavior of mlock()--before the unevictable/mlock changes--mlock_fixup()
- will call make_pages_present() in the hugetlbfs vma range to allocate the
- huge pages and populate the ptes.
+ prior behavior of mlock()--before the unevictable/mlock changes--
+ mlock_fixup() will call make_pages_present() in the hugetlbfs vma range
+ to allocate the huge pages and populate the ptes.
3) vmas with VM_DONTEXPAND|VM_RESERVED are generally user space mappings of
kernel pages, such as the vdso page, relay channel pages, etc. These pages
@@ -322,7 +315,7 @@ __mlock_vma_pages_range()--the same function used to mlock a vma range--
passing a flag to indicate that munlock() is being performed.
Because the vma access protections could have been changed to PROT_NONE after
-faulting in and mlocking some pages, get_user_pages() was unreliable for visiting
+faulting in and mlocking pages, get_user_pages() was unreliable for visiting
these pages for munlocking. Because we don't want to leave pages mlocked(),
get_user_pages() was enhanced to accept a flag to ignore the permissions when
fetching the pages--all of which should be resident as a result of previous
@@ -416,8 +409,8 @@ Mlocked Pages: munmap()/exit()/exec() System Call Handling
When unmapping an mlocked region of memory, whether by an explicit call to
munmap() or via an internal unmap from exit() or exec() processing, we must
munlock the pages if we're removing the last VM_LOCKED vma that maps the pages.
-Before the unevictable/mlock changes, mlocking did not mark the pages in any way,
-so unmapping them required no processing.
+Before the unevictable/mlock changes, mlocking did not mark the pages in any
+way, so unmapping them required no processing.
To munlock a range of memory under the unevictable/mlock infrastructure, the
munmap() hander and task address space tear down function call
@@ -517,12 +510,10 @@ couldn't be mlocked.
Mlocked pages: try_to_munlock() Reverse Map Scan
TODO/FIXME: a better name might be page_mlocked()--analogous to the
-page_referenced() reverse map walker--especially if we continue to call this
-from shrink_page_list(). See related TODO/FIXME below.
+page_referenced() reverse map walker.
-When munlock_vma_page()--see "Mlocked Pages: munlock()/munlockall() System
-Call Handling" above--tries to munlock a page, or when shrink_page_list()
-encounters an anonymous page that is not yet in the swap cache, they need to
+When munlock_vma_page()--see "Mlocked Pages: munlock()/munlockall()
+System Call Handling" above--tries to munlock a page, it needs to
determine whether or not the page is mapped by any VM_LOCKED vma, without
actually attempting to unmap all ptes from the page. For this purpose, the
unevictable/mlock infrastructure introduced a variant of try_to_unmap() called
@@ -535,10 +526,7 @@ for VM_LOCKED vmas. When such a vma is found for anonymous pages and file
pages mapped in linear VMAs, as in the try_to_unmap() case, the functions
attempt to acquire the associated mmap semphore, mlock the page via
mlock_vma_page() and return SWAP_MLOCK. This effectively undoes the
-pre-clearing of the page's PG_mlocked done by munlock_vma_page() and informs
-shrink_page_list() that the anonymous page should be culled rather than added
-to the swap cache in preparation for a try_to_unmap() that will almost
-certainly fail.
+pre-clearing of the page's PG_mlocked done by munlock_vma_page.
If try_to_unmap() is unable to acquire a VM_LOCKED vma's associated mmap
semaphore, it will return SWAP_AGAIN. This will allow shrink_page_list()
@@ -557,10 +545,7 @@ However, the scan can terminate when it encounters a VM_LOCKED vma and can
successfully acquire the vma's mmap semphore for read and mlock the page.
Although try_to_munlock() can be called many [very many!] times when
munlock()ing a large region or tearing down a large address space that has been
-mlocked via mlockall(), overall this is a fairly rare event. In addition,
-although shrink_page_list() calls try_to_munlock() for every anonymous page that
-it handles that is not yet in the swap cache, on average anonymous pages will
-have very short reverse map lists.
+mlocked via mlockall(), overall this is a fairly rare event.
Mlocked Page: Page Reclaim in shrink_*_list()
@@ -588,8 +573,8 @@ Some examples of these unevictable pages on the LRU lists are:
munlock_vma_page() was forced to let the page back on to the normal
LRU list for vmscan to handle.
-shrink_inactive_list() also culls any unevictable pages that it finds
-on the inactive lists, again diverting them to the appropriate zone's unevictable
+shrink_inactive_list() also culls any unevictable pages that it finds on
+the inactive lists, again diverting them to the appropriate zone's unevictable
lru list. shrink_inactive_list() should only see SHM_LOCKed pages that became
SHM_LOCKed after shrink_active_list() had moved them to the inactive list, or
pages mapped into VM_LOCKED vmas that munlock_vma_page() couldn't isolate from
@@ -597,19 +582,7 @@ the lru to recheck via try_to_munlock(). shrink_inactive_list() won't notice
the latter, but will pass on to shrink_page_list().
shrink_page_list() again culls obviously unevictable pages that it could
-encounter for similar reason to shrink_inactive_list(). As already discussed,
-shrink_page_list() proactively looks for anonymous pages that should have
-PG_mlocked set but don't--these would not be detected by page_evictable()--to
-avoid adding them to the swap cache unnecessarily. File pages mapped into
+encounter for similar reason to shrink_inactive_list(). Pages mapped into
VM_LOCKED vmas but without PG_mlocked set will make it all the way to
-try_to_unmap(). shrink_page_list() will divert them to the unevictable list when
-try_to_unmap() returns SWAP_MLOCK, as discussed above.
-
-TODO/FIXME: If we can enhance the swap cache to reliably remove entries
-with page_count(page) > 2, as long as all ptes are mapped to the page and
-not the swap entry, we can probably remove the call to try_to_munlock() in
-shrink_page_list() and just remove the page from the swap cache when
-try_to_unmap() returns SWAP_MLOCK. Currently, remove_exclusive_swap_page()
-doesn't seem to allow that.
-
-
+try_to_unmap(). shrink_page_list() will divert them to the unevictable list
+when try_to_unmap() returns SWAP_MLOCK, as discussed above.
diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX
index 7b0ceaaad7af..d63fa024ac05 100644
--- a/Documentation/w1/masters/00-INDEX
+++ b/Documentation/w1/masters/00-INDEX
@@ -4,5 +4,7 @@ ds2482
- The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses.
ds2490
- The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges.
+mxc_w1
+ - W1 master controller driver found on Freescale MX2/MX3 SoCs
w1-gpio
- GPIO 1-wire bus master driver.
diff --git a/Documentation/w1/masters/mxc-w1 b/Documentation/w1/masters/mxc-w1
new file mode 100644
index 000000000000..97f6199a7f39
--- /dev/null
+++ b/Documentation/w1/masters/mxc-w1
@@ -0,0 +1,11 @@
+Kernel driver mxc_w1
+====================
+
+Supported chips:
+ * Freescale MX27, MX31 and probably other i.MX SoCs
+ Datasheets:
+ http://www.freescale.com/files/32bit/doc/data_sheet/MCIMX31.pdf?fpsp=1
+ http://www.freescale.com/files/dsp/MCIMX27.pdf?fpsp=1
+
+Author: Originally based on Freescale code, prepared for mainline by
+ Sascha Hauer <s.hauer@pengutronix.de>
diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink
index 3640c7c87d45..804445f745ed 100644
--- a/Documentation/w1/w1.netlink
+++ b/Documentation/w1/w1.netlink
@@ -5,69 +5,157 @@ Message types.
=============
There are three types of messages between w1 core and userspace:
-1. Events. They are generated each time new master or slave device found
- either due to automatic or requested search.
-2. Userspace commands. Includes read/write and search/alarm search comamnds.
+1. Events. They are generated each time new master or slave device
+ found either due to automatic or requested search.
+2. Userspace commands.
3. Replies to userspace commands.
Protocol.
========
-[struct cn_msg] - connector header. It's length field is equal to size of the attached data.
+[struct cn_msg] - connector header.
+ Its length field is equal to size of the attached data
[struct w1_netlink_msg] - w1 netlink header.
__u8 type - message type.
- W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events.
- W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events.
- W1_MASTER_CMD - userspace command for bus master device (search/alarm search).
- W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search
- for bus master device where given slave device found).
+ W1_LIST_MASTERS
+ list current bus masters
+ W1_SLAVE_ADD/W1_SLAVE_REMOVE
+ slave add/remove events
+ W1_MASTER_ADD/W1_MASTER_REMOVE
+ master add/remove events
+ W1_MASTER_CMD
+ userspace command for bus master
+ device (search/alarm search)
+ W1_SLAVE_CMD
+ userspace command for slave device
+ (read/write/touch)
__u8 res - reserved
- __u16 len - size of attached to this header data.
+ __u16 len - size of data attached to this header data
union {
- __u8 id; - slave unique device id
+ __u8 id[8]; - slave unique device id
struct w1_mst {
- __u32 id; - master's id.
+ __u32 id; - master's id
__u32 res; - reserved
} mst;
} id;
-[strucrt w1_netlink_cmd] - command for gived master or slave device.
+[struct w1_netlink_cmd] - command for given master or slave device.
__u8 cmd - command opcode.
- W1_CMD_READ - read command.
- W1_CMD_WRITE - write command.
- W1_CMD_SEARCH - search command.
- W1_CMD_ALARM_SEARCH - alarm search command.
+ W1_CMD_READ - read command
+ W1_CMD_WRITE - write command
+ W1_CMD_TOUCH - touch command
+ (write and sample data back to userspace)
+ W1_CMD_SEARCH - search command
+ W1_CMD_ALARM_SEARCH - alarm search command
__u8 res - reserved
- __u16 len - length of data for this command.
- For read command data must be allocated like for write command.
- __u8 data[0] - data for this command.
+ __u16 len - length of data for this command
+ For read command data must be allocated like for write command
+ __u8 data[0] - data for this command
-Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages.
+Each connector message can include one or more w1_netlink_msg with
+zero or more attached w1_netlink_cmd messages.
-For event messages there are no w1_netlink_cmd embedded structures, only connector header
-and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types)
-and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned
-to bus master device when it is added to w1 core.
+For event messages there are no w1_netlink_cmd embedded structures,
+only connector header and w1_netlink_msg strucutre with "len" field
+being zero and filled type (one of event types) and id:
+either 8 bytes of slave unique id in host order,
+or master's id, which is assigned to bus master device
+when it is added to w1 core.
+
+Currently replies to userspace commands are only generated for read
+command request. One reply is generated exactly for one w1_netlink_cmd
+read request. Replies are not combined when sent - i.e. typical reply
+messages looks like the following:
-Currently replies to userspace commands are only generated for read command request.
-One reply is generated exactly for one w1_netlink_cmd read request.
-Replies are not combined when sent - i.e. typical reply messages looks like the following:
[cn_msg][w1_netlink_msg][w1_netlink_cmd]
-cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
+cn_msg.len = sizeof(struct w1_netlink_msg) +
+ sizeof(struct w1_netlink_cmd) +
+ cmd->len;
w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len;
w1_netlink_cmd.len = cmd->len;
+Replies to W1_LIST_MASTERS should send a message back to the userspace
+which will contain list of all registered master ids in the following
+format:
+
+ cn_msg (CN_W1_IDX.CN_W1_VAL as id, len is equal to sizeof(struct
+ w1_netlink_msg) plus number of masters multipled by 4)
+ w1_netlink_msg (type: W1_LIST_MASTERS, len is equal to
+ number of masters multiplied by 4 (u32 size))
+ id0 ... idN
+
+ Each message is at most 4k in size, so if number of master devices
+ exceeds this, it will be split into several messages,
+ cn.seq will be increased for each one.
+
+W1 search and alarm search commands.
+request:
+[cn_msg]
+ [w1_netlink_msg type = W1_MASTER_CMD
+ id is equal to the bus master id to use for searching]
+ [w1_netlink_cmd cmd = W1_CMD_SEARCH or W1_CMD_ALARM_SEARCH]
+
+reply:
+ [cn_msg, ack = 1 and increasing, 0 means the last message,
+ seq is equal to the request seq]
+ [w1_netlink_msg type = W1_MASTER_CMD]
+ [w1_netlink_cmd cmd = W1_CMD_SEARCH or W1_CMD_ALARM_SEARCH
+ len is equal to number of IDs multiplied by 8]
+ [64bit-id0 ... 64bit-idN]
+Length in each header corresponds to the size of the data behind it, so
+w1_netlink_cmd->len = N * 8; where N is number of IDs in this message.
+ Can be zero.
+w1_netlink_msg->len = sizeof(struct w1_netlink_cmd) + N * 8;
+cn_msg->len = sizeof(struct w1_netlink_msg) +
+ sizeof(struct w1_netlink_cmd) +
+ N*8;
+
+W1 reset command.
+[cn_msg]
+ [w1_netlink_msg type = W1_MASTER_CMD
+ id is equal to the bus master id to use for searching]
+ [w1_netlink_cmd cmd = W1_CMD_RESET]
+
+
+Command status replies.
+======================
+
+Each command (either root, master or slave with or without w1_netlink_cmd
+structure) will be 'acked' by the w1 core. Format of the reply is the same
+as request message except that length parameters do not account for data
+requested by the user, i.e. read/write/touch IO requests will not contain
+data, so w1_netlink_cmd.len will be 0, w1_netlink_msg.len will be size
+of the w1_netlink_cmd structure and cn_msg.len will be equal to the sum
+of the sizeof(struct w1_netlink_msg) and sizeof(struct w1_netlink_cmd).
+If reply is generated for master or root command (which do not have
+w1_netlink_cmd attached), reply will contain only cn_msg and w1_netlink_msg
+structires.
+
+w1_netlink_msg.status field will carry positive error value
+(EINVAL for example) or zero in case of success.
+
+All other fields in every structure will mirror the same parameters in the
+request message (except lengths as described above).
+
+Status reply is generated for every w1_netlink_cmd embedded in the
+w1_netlink_msg, if there are no w1_netlink_cmd structures,
+reply will be generated for the w1_netlink_msg.
+
+All w1_netlink_cmd command structures are handled in every w1_netlink_msg,
+even if there were errors, only length mismatch interrupts message processing.
+
Operation steps in w1 core when new command is received.
=======================================================
-When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request,
-according to w1_netlink_msg.type field.
+When new message (w1_netlink_msg) is received w1 core detects if it is
+master or slave request, according to w1_netlink_msg.type field.
Then master or slave device is searched for.
-When found, master device (requested or those one on where slave device is found) is locked.
-If slave command is requested, then reset/select procedure is started to select given device.
+When found, master device (requested or those one on where slave device
+is found) is locked. If slave command is requested, then reset/select
+procedure is started to select given device.
Then all requested in w1_netlink_msg operations are performed one by one.
If command requires reply (like read command) it is sent on command completion.
@@ -82,8 +170,8 @@ Connector [1] specific documentation.
Each connector message includes two u32 fields as "address".
w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header.
Each message also includes sequence and acknowledge numbers.
-Sequence number for event messages is appropriate bus master sequence number increased with
-each event message sent "through" this master.
+Sequence number for event messages is appropriate bus master sequence number
+increased with each event message sent "through" this master.
Sequence number for userspace requests is set by userspace application.
Sequence number for reply is the same as was in request, and
acknowledge number is set to seq+1.
@@ -93,6 +181,6 @@ Additional documantion, source code examples.
============================================
1. Documentation/connector
-2. http://tservice.net.ru/~s0mbre/archive/w1
-This archive includes userspace application w1d.c which
-uses read/write/search commands for all master/slave devices found on the bus.
+2. http://www.ioremap.net/archive/w1
+This archive includes userspace application w1d.c which uses
+read/write/search commands for all master/slave devices found on the bus.
diff --git a/Documentation/wimax/README.i2400m b/Documentation/wimax/README.i2400m
new file mode 100644
index 000000000000..7dffd8919cb0
--- /dev/null
+++ b/Documentation/wimax/README.i2400m
@@ -0,0 +1,260 @@
+
+ Driver for the Intel Wireless Wimax Connection 2400m
+
+ (C) 2008 Intel Corporation < linux-wimax@intel.com >
+
+ This provides a driver for the Intel Wireless WiMAX Connection 2400m
+ and a basic Linux kernel WiMAX stack.
+
+1. Requirements
+
+ * Linux installation with Linux kernel 2.6.22 or newer (if building
+ from a separate tree)
+ * Intel i2400m Echo Peak or Baxter Peak; this includes the Intel
+ Wireless WiMAX/WiFi Link 5x50 series.
+ * build tools:
+ + Linux kernel development package for the target kernel; to
+ build against your currently running kernel, you need to have
+ the kernel development package corresponding to the running
+ image installed (usually if your kernel is named
+ linux-VERSION, the development package is called
+ linux-dev-VERSION or linux-headers-VERSION).
+ + GNU C Compiler, make
+
+2. Compilation and installation
+
+2.1. Compilation of the drivers included in the kernel
+
+ Configure the kernel; to enable the WiMAX drivers select Drivers >
+ Networking Drivers > WiMAX device support. Enable all of them as
+ modules (easier).
+
+ If USB or SDIO are not enabled in the kernel configuration, the options
+ to build the i2400m USB or SDIO drivers will not show. Enable said
+ subsystems and go back to the WiMAX menu to enable the drivers.
+
+ Compile and install your kernel as usual.
+
+2.2. Compilation of the drivers distributed as an standalone module
+
+ To compile
+
+$ cd source/directory
+$ make
+
+ Once built you can load and unload using the provided load.sh script;
+ load.sh will load the modules, load.sh u will unload them.
+
+ To install in the default kernel directories (and enable auto loading
+ when the device is plugged):
+
+$ make install
+$ depmod -a
+
+ If your kernel development files are located in a non standard
+ directory or if you want to build for a kernel that is not the
+ currently running one, set KDIR to the right location:
+
+$ make KDIR=/path/to/kernel/dev/tree
+
+ For more information, please contact linux-wimax@intel.com.
+
+3. Installing the firmware
+
+ The firmware can be obtained from http://linuxwimax.org or might have
+ been supplied with your hardware.
+
+ It has to be installed in the target system:
+ *
+$ cp FIRMWAREFILE.sbcf /lib/firmware/i2400m-fw-BUSTYPE-1.3.sbcf
+
+ * NOTE: if your firmware came in an .rpm or .deb file, just install
+ it as normal, with the rpm (rpm -i FIRMWARE.rpm) or dpkg
+ (dpkg -i FIRMWARE.deb) commands. No further action is needed.
+ * BUSTYPE will be usb or sdio, depending on the hardware you have.
+ Each hardware type comes with its own firmware and will not work
+ with other types.
+
+4. Design
+
+ This package contains two major parts: a WiMAX kernel stack and a
+ driver for the Intel i2400m.
+
+ The WiMAX stack is designed to provide for common WiMAX control
+ services to current and future WiMAX devices from any vendor; please
+ see README.wimax for details.
+
+ The i2400m kernel driver is broken up in two main parts: the bus
+ generic driver and the bus-specific drivers. The bus generic driver
+ forms the drivercore and contain no knowledge of the actual method we
+ use to connect to the device. The bus specific drivers are just the
+ glue to connect the bus-generic driver and the device. Currently only
+ USB and SDIO are supported. See drivers/net/wimax/i2400m/i2400m.h for
+ more information.
+
+ The bus generic driver is logically broken up in two parts: OS-glue and
+ hardware-glue. The OS-glue interfaces with Linux. The hardware-glue
+ interfaces with the device on using an interface provided by the
+ bus-specific driver. The reason for this breakup is to be able to
+ easily reuse the hardware-glue to write drivers for other OSes; note
+ the hardware glue part is written as a native Linux driver; no
+ abstraction layers are used, so to port to another OS, the Linux kernel
+ API calls should be replaced with the target OS's.
+
+5. Usage
+
+ To load the driver, follow the instructions in the install section;
+ once the driver is loaded, plug in the device (unless it is permanently
+ plugged in). The driver will enumerate the device, upload the firmware
+ and output messages in the kernel log (dmesg, /var/log/messages or
+ /var/log/kern.log) such as:
+
+...
+i2400m_usb 5-4:1.0: firmware interface version 8.0.0
+i2400m_usb 5-4:1.0: WiMAX interface wmx0 (00:1d:e1:01:94:2c) ready
+
+ At this point the device is ready to work.
+
+ Current versions require the Intel WiMAX Network Service in userspace
+ to make things work. See the network service's README for instructions
+ on how to scan, connect and disconnect.
+
+5.1. Module parameters
+
+ Module parameters can be set at kernel or module load time or by
+ echoing values:
+
+$ echo VALUE > /sys/module/MODULENAME/parameters/PARAMETERNAME
+
+ To make changes permanent, for example, for the i2400m module, you can
+ also create a file named /etc/modprobe.d/i2400m containing:
+
+options i2400m idle_mode_disabled=1
+
+ To find which parameters are supported by a module, run:
+
+$ modinfo path/to/module.ko
+
+ During kernel bootup (if the driver is linked in the kernel), specify
+ the following to the kernel command line:
+
+i2400m.PARAMETER=VALUE
+
+5.1.1. i2400m: idle_mode_disabled
+
+ The i2400m module supports a parameter to disable idle mode. This
+ parameter, once set, will take effect only when the device is
+ reinitialized by the driver (eg: following a reset or a reconnect).
+
+5.2. Debug operations: debugfs entries
+
+ The driver will register debugfs entries that allow the user to tweak
+ debug settings. There are three main container directories where
+ entries are placed, which correspond to the three blocks a i2400m WiMAX
+ driver has:
+ * /sys/kernel/debug/wimax:DEVNAME/ for the generic WiMAX stack
+ controls
+ * /sys/kernel/debug/wimax:DEVNAME/i2400m for the i2400m generic
+ driver controls
+ * /sys/kernel/debug/wimax:DEVNAME/i2400m-usb (or -sdio) for the
+ bus-specific i2400m-usb or i2400m-sdio controls).
+
+ Of course, if debugfs is mounted in a directory other than
+ /sys/kernel/debug, those paths will change.
+
+5.2.1. Increasing debug output
+
+ The files named *dl_* indicate knobs for controlling the debug output
+ of different submodules:
+ *
+# find /sys/kernel/debug/wimax\:wmx0 -name \*dl_\*
+/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_tx
+/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_rx
+/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_notif
+/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_fw
+/sys/kernel/debug/wimax:wmx0/i2400m-usb/dl_usb
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_tx
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_rx
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_rfkill
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_netdev
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_fw
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_debugfs
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_driver
+/sys/kernel/debug/wimax:wmx0/i2400m/dl_control
+/sys/kernel/debug/wimax:wmx0/wimax_dl_stack
+/sys/kernel/debug/wimax:wmx0/wimax_dl_op_rfkill
+/sys/kernel/debug/wimax:wmx0/wimax_dl_op_reset
+/sys/kernel/debug/wimax:wmx0/wimax_dl_op_msg
+/sys/kernel/debug/wimax:wmx0/wimax_dl_id_table
+/sys/kernel/debug/wimax:wmx0/wimax_dl_debugfs
+
+ By reading the file you can obtain the current value of said debug
+ level; by writing to it, you can set it.
+
+ To increase the debug level of, for example, the i2400m's generic TX
+ engine, just write:
+
+$ echo 3 > /sys/kernel/debug/wimax:wmx0/i2400m/dl_tx
+
+ Increasing numbers yield increasing debug information; for details of
+ what is printed and the available levels, check the source. The code
+ uses 0 for disabled and increasing values until 8.
+
+5.2.2. RX and TX statistics
+
+ The i2400m/rx_stats and i2400m/tx_stats provide statistics about the
+ data reception/delivery from the device:
+
+$ cat /sys/kernel/debug/wimax:wmx0/i2400m/rx_stats
+45 1 3 34 3104 48 480
+
+ The numbers reported are
+ * packets/RX-buffer: total, min, max
+ * RX-buffers: total RX buffers received, accumulated RX buffer size
+ in bytes, min size received, max size received
+
+ Thus, to find the average buffer size received, divide accumulated
+ RX-buffer / total RX-buffers.
+
+ To clear the statistics back to 0, write anything to the rx_stats file:
+
+$ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m_rx_stats
+
+ Likewise for TX.
+
+ Note the packets this debug file refers to are not network packet, but
+ packets in the sense of the device-specific protocol for communication
+ to the host. See drivers/net/wimax/i2400m/tx.c.
+
+5.2.3. Tracing messages received from user space
+
+ To echo messages received from user space into the trace pipe that the
+ i2400m driver creates, set the debug file i2400m/trace_msg_from_user to
+ 1:
+ *
+$ echo 1 > /sys/kernel/debug/wimax:wmx0/i2400m/trace_msg_from_user
+
+5.2.4. Performing a device reset
+
+ By writing a 0, a 1 or a 2 to the file
+ /sys/kernel/debug/wimax:wmx0/reset, the driver performs a warm (without
+ disconnecting from the bus), cold (disconnecting from the bus) or bus
+ (bus specific) reset on the device.
+
+5.2.5. Asking the device to enter power saving mode
+
+ By writing any value to the /sys/kernel/debug/wimax:wmx0 file, the
+ device will attempt to enter power saving mode.
+
+6. Troubleshooting
+
+6.1. Driver complains about 'i2400m-fw-usb-1.2.sbcf: request failed'
+
+ If upon connecting the device, the following is output in the kernel
+ log:
+
+i2400m_usb 5-4:1.0: fw i2400m-fw-usb-1.3.sbcf: request failed: -2
+
+ This means that the driver cannot locate the firmware file named
+ /lib/firmware/i2400m-fw-usb-1.2.sbcf. Check that the file is present in
+ the right location.
diff --git a/Documentation/wimax/README.wimax b/Documentation/wimax/README.wimax
new file mode 100644
index 000000000000..b78c4378084e
--- /dev/null
+++ b/Documentation/wimax/README.wimax
@@ -0,0 +1,81 @@
+
+ Linux kernel WiMAX stack
+
+ (C) 2008 Intel Corporation < linux-wimax@intel.com >
+
+ This provides a basic Linux kernel WiMAX stack to provide a common
+ control API for WiMAX devices, usable from kernel and user space.
+
+1. Design
+
+ The WiMAX stack is designed to provide for common WiMAX control
+ services to current and future WiMAX devices from any vendor.
+
+ Because currently there is only one and we don't know what would be the
+ common services, the APIs it currently provides are very minimal.
+ However, it is done in such a way that it is easily extensible to
+ accommodate future requirements.
+
+ The stack works by embedding a struct wimax_dev in your device's
+ control structures. This provides a set of callbacks that the WiMAX
+ stack will call in order to implement control operations requested by
+ the user. As well, the stack provides API functions that the driver
+ calls to notify about changes of state in the device.
+
+ The stack exports the API calls needed to control the device to user
+ space using generic netlink as a marshalling mechanism. You can access
+ them using your own code or use the wrappers provided for your
+ convenience in libwimax (in the wimax-tools package).
+
+ For detailed information on the stack, please see
+ include/linux/wimax.h.
+
+2. Usage
+
+ For usage in a driver (registration, API, etc) please refer to the
+ instructions in the header file include/linux/wimax.h.
+
+ When a device is registered with the WiMAX stack, a set of debugfs
+ files will appear in /sys/kernel/debug/wimax:wmxX can tweak for
+ control.
+
+2.1. Obtaining debug information: debugfs entries
+
+ The WiMAX stack is compiled, by default, with debug messages that can
+ be used to diagnose issues. By default, said messages are disabled.
+
+ The drivers will register debugfs entries that allow the user to tweak
+ debug settings.
+
+ Each driver, when registering with the stack, will cause a debugfs
+ directory named wimax:DEVICENAME to be created; optionally, it might
+ create more subentries below it.
+
+2.1.1. Increasing debug output
+
+ The files named *dl_* indicate knobs for controlling the debug output
+ of different submodules of the WiMAX stack:
+ *
+# find /sys/kernel/debug/wimax\:wmx0 -name \*dl_\*
+/sys/kernel/debug/wimax:wmx0/wimax_dl_stack
+/sys/kernel/debug/wimax:wmx0/wimax_dl_op_rfkill
+/sys/kernel/debug/wimax:wmx0/wimax_dl_op_reset
+/sys/kernel/debug/wimax:wmx0/wimax_dl_op_msg
+/sys/kernel/debug/wimax:wmx0/wimax_dl_id_table
+/sys/kernel/debug/wimax:wmx0/wimax_dl_debugfs
+/sys/kernel/debug/wimax:wmx0/.... # other driver specific files
+
+ NOTE: Of course, if debugfs is mounted in a directory other than
+ /sys/kernel/debug, those paths will change.
+
+ By reading the file you can obtain the current value of said debug
+ level; by writing to it, you can set it.
+
+ To increase the debug level of, for example, the id-table submodule,
+ just write:
+
+$ echo 3 > /sys/kernel/debug/wimax:wmx0/wimax_dl_id_table
+
+ Increasing numbers yield increasing debug information; for details of
+ what is printed and the available levels, check the source. The code
+ uses 0 for disabled and increasing values until 8.
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index fcdc62b3c3d8..7b4596ac4120 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -44,7 +44,7 @@ Protocol 2.07: (Kernel 2.6.24) Added paravirtualised boot protocol.
and KEEP_SEGMENTS flag in load_flags.
Protocol 2.08: (Kernel 2.6.26) Added crc32 checksum and ELF format
- payload. Introduced payload_offset and payload length
+ payload. Introduced payload_offset and payload_length
fields to aid in locating the payload.
Protocol 2.09: (Kernel 2.6.26) Added a field of 64-bit physical
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
index 169ad423a3d1..4f913857b8a2 100644
--- a/Documentation/x86/zero-page.txt
+++ b/Documentation/x86/zero-page.txt
@@ -3,7 +3,7 @@ protocol of kernel. These should be filled by bootloader or 16-bit
real-mode setup code of the kernel. References/settings to it mainly
are in:
- include/asm-x86/bootparam.h
+ arch/x86/include/asm/bootparam.h
Offset Proto Name Meaning
diff --git a/MAINTAINERS b/MAINTAINERS
index 12fc2805ab41..a781f2ec0829 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -616,7 +616,7 @@ M: mkpetch@internode.on.net
S: Maintained
ARM/TOSA MACHINE SUPPORT
-P: Dmitry Baryshkov
+P: Dmitry Eremin-Solenikov
M: dbaryshkov@gmail.com
P: Dirk Opfer
M: dirk@opfer-online.de
@@ -911,7 +911,7 @@ S: Maintained
BLACKFIN ARCHITECTURE
P: Bryan Wu
M: cooloney@kernel.org
-L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+L: uclinux-dist-devel@blackfin.uclinux.org
W: http://blackfin.uclinux.org
S: Supported
@@ -1024,16 +1024,17 @@ S: Maintained
BTTV VIDEO4LINUX DRIVER
P: Mauro Carvalho Chehab
M: mchehab@infradead.org
-M: v4l-dvb-maintainer@linuxtv.org
+L: linux-media@vger.kernel.org
L: video4linux-list@redhat.com
W: http://linuxtv.org
-T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
P: Jonathan Corbet
M: corbet@lwn.net
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
CALGARY x86-64 IOMMU
@@ -1092,11 +1093,8 @@ S: Maintained
CHECKPATCH
P: Andy Whitcroft
-M: apw@shadowen.org
-P: Randy Dunlap
-M: rdunlap@xenotime.net
-P: Joel Schopp
-M: jschopp@austin.ibm.com
+M: apw@canonical.com
+L: linux-kernel@vger.kernel.org
S: Supported
CISCO 10G ETHERNET DRIVER
@@ -1264,7 +1262,8 @@ P: Hans Verkuil, Andy Walls
M: hverkuil@xs4all.nl, awalls@radix.net
L: ivtv-devel@ivtvdriver.org
L: ivtv-users@ivtvdriver.org
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://linuxtv.org
S: Maintained
@@ -1361,6 +1360,11 @@ P: Maciej W. Rozycki
M: macro@linux-mips.org
S: Maintained
+DELL LAPTOP DRIVER
+P: Matthew Garrett
+M: mjg59@srcf.ucam.org
+S: Maintained
+
DELL LAPTOP SMM DRIVER
P: Massimo Dal Zotto
M: dz@debian.org
@@ -1490,10 +1494,10 @@ S: Maintained
DVB SUBSYSTEM AND DRIVERS
P: LinuxTV.org Project
-M: v4l-dvb-maintainer@linuxtv.org
+M: linux-media@vger.kernel.org
L: linux-dvb@linuxtv.org (subscription required)
W: http://linuxtv.org/
-T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
DZ DECSTATION DZ11 SERIAL DRIVER
@@ -1577,6 +1581,13 @@ L: bluesmoke-devel@lists.sourceforge.net
W: bluesmoke.sourceforge.net
S: Maintained
+EDAC-I5400
+P: Mauro Carvalho Chehab
+M: mchehab@redhat.com
+L: bluesmoke-devel@lists.sourceforge.net
+W: bluesmoke.sourceforge.net
+S: Maintained
+
EDAC-I82975X
P: Ranganathan Desikan
P: Arvind R.
@@ -1810,6 +1821,14 @@ M: hch@infradead.org
W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
S: Maintained
+FREEZER
+P: Pavel Machek
+M: pavel@suse.cz
+P: Rafael J. Wysocki
+M: rjw@sisk.pl
+L: linux-pm@lists.linux-foundation.org
+S: Supported
+
FTRACE
P: Steven Rostedt
M: rostedt@goodmis.org
@@ -1885,32 +1904,37 @@ S: Maintained
GSPCA FINEPIX SUBDRIVER
P: Frank Zago
M: frank@zago.net
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
GSPCA M5602 SUBDRIVER
P: Erik Andren
M: erik.andren@gmail.com
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
GSPCA PAC207 SONIXB SUBDRIVER
P: Hans de Goede
M: hdegoede@redhat.com
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
GSPCA T613 SUBDRIVER
P: Leandro Costantino
M: lcostantino@gmail.com
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
GSPCA USB WEBCAM DRIVER
P: Jean-Francois Moine
M: moinejf@free.fr
W: http://moinejf.free.fr
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
HARDWARE MONITORING
@@ -2049,6 +2073,12 @@ M: mikulas@artax.karlin.mff.cuni.cz
W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
S: Maintained
+HSO 3G Modem Driver (hso.c)
+P: Denis Joseph Barrow
+M: d.barow@option.com
+W: http://www.pharscape.org
+S: Maintained
+
HTCPEN TOUCHSCREEN DRIVER
P: Pau Oliva Fora
M: pof@eslack.org
@@ -2072,7 +2102,8 @@ M: khali@linux-fr.org
P: Ben Dooks (embedded platforms)
M: ben-linux@fluff.org
L: linux-i2c@vger.kernel.org
-T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
+W: http://i2c.wiki.kernel.org/
+T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
S: Maintained
I2C-TINY-USB DRIVER
@@ -2146,11 +2177,6 @@ M: Gadi Oxman <gadio@netvision.net.il>
L: linux-kernel@vger.kernel.org
S: Maintained
-IDE-SCSI DRIVER
-L: linux-ide@vger.kernel.org
-L: linux-scsi@vger.kernel.org
-S: Orphan
-
IDLE-I7300
P: Andy Henroid
M: andrew.d.henroid@intel.com
@@ -2191,7 +2217,7 @@ P: Sean Hefty
M: sean.hefty@intel.com
P: Hal Rosenstock
M: hal.rosenstock@gmail.com
-L: general@lists.openfabrics.org
+L: general@lists.openfabrics.org (moderated for non-subscribers)
W: http://www.openib.org/
T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
S: Supported
@@ -2312,6 +2338,14 @@ W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
W: http://ipw2200.sourceforge.net
S: Supported
+INTEL WIRELESS WIMAX CONNECTION 2400
+P: Inaky Perez-Gonzalez
+M: inaky.perez-gonzalez@intel.com
+M: linux-wimax@intel.com
+L: wimax@linuxwimax.org
+S: Supported
+W: http://linuxwimax.org
+
INTEL WIRELESS WIFI LINK (iwlwifi)
P: Zhu Yi
M: yi.zhu@intel.com
@@ -2436,7 +2470,8 @@ P: Hans Verkuil
M: hverkuil@xs4all.nl
L: ivtv-devel@ivtvdriver.org
L: ivtv-users@ivtvdriver.org
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.ivtvdriver.org
S: Maintained
@@ -2546,8 +2581,6 @@ W: http://kvm.qumranet.com
S: Supported
KERNEL VIRTUAL MACHINE For Itanium (KVM/IA64)
-P: Anthony Xu
-M: anthony.xu@intel.com
P: Xiantao Zhang
M: xiantao.zhang@intel.com
L: kvm-ia64@vger.kernel.org
@@ -2640,13 +2673,13 @@ W: http://www.hansenpartnership.com/voyager
S: Maintained
LINUX FOR POWERPC (32-BIT AND 64-BIT)
-P: Paul Mackerras
-M: paulus@samba.org
P: Benjamin Herrenschmidt
M: benh@kernel.crashing.org
+P: Paul Mackerras
+M: paulus@samba.org
W: http://www.penguinppc.org/
L: linuxppc-dev@ozlabs.org
-T: git kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc.git
+T: git kernel.org:/pub/scm/linux/kernel/git/benh/powerpc.git
S: Supported
LINUX FOR POWER MACINTOSH
@@ -2808,8 +2841,6 @@ S: Maintained
MAC80211
P: Johannes Berg
M: johannes@sipsolutions.net
-P: Michael Wu
-M: flamingice@sourmilk.net
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
@@ -2991,6 +3022,7 @@ MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
P: Felipe Balbi
M: felipe.balbi@nokia.com
L: linux-usb@vger.kernel.org
+T: git gitorious.org:/musb/mainline.git
S: Maintained
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
@@ -3197,7 +3229,8 @@ S: Maintained
OMNIVISION OV7670 SENSOR DRIVER
P: Jonathan Corbet
M: corbet@lwn.net
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
ONENAND FLASH DRIVER
@@ -3475,12 +3508,19 @@ L: linuxppc-dev@ozlabs.org
L: cbe-oss-dev@ozlabs.org
S: Supported
+PS3VRAM DRIVER
+P: Jim Paris
+M: jim@jtan.com
+L: cbe-oss-dev@ozlabs.org
+S: Maintained
+
PVRUSB2 VIDEO4LINUX DRIVER
P: Mike Isely
M: isely@pobox.com
L: pvrusb2@isely.net (subscribers-only)
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
W: http://www.isely.net/pvrusb2/
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
PXA2xx/PXA3xx SUPPORT
@@ -3700,6 +3740,8 @@ S: Supported
SAA7146 VIDEO4LINUX-2 DRIVER
P: Michael Hunold
M: michael@mihu.de
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.mihu.de/linux/saa7146
S: Maintained
@@ -3964,7 +4006,8 @@ S: Maintained
SOC-CAMERA V4L2 SUBSYSTEM
P: Guennadi Liakhovetski
M: g.liakhovetski@gmx.de
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
SOEKRIS NET48XX LED SUPPORT
@@ -4022,10 +4065,12 @@ L: alsa-devel@alsa-project.org (subscribers-only)
W: http://alsa-project.org/main/index.php/ASoC
S: Supported
-SPARC (sparc32)
-P: William L. Irwin
-M: wli@holomorphy.com
+SPARC + UltraSPARC (sparc/sparc64)
+P: David S. Miller
+M: davem@davemloft.net
L: sparclinux@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
S: Maintained
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
@@ -4056,6 +4101,13 @@ L: cbe-oss-dev@ozlabs.org
W: http://www.ibm.com/developerworks/power/cell/
S: Supported
+SQUASHFS FILE SYSTEM
+P: Phillip Lougher
+M: phillip@lougher.demon.co.uk
+L: squashfs-devel@lists.sourceforge.net (subscribers-only)
+W: http://squashfs.org.uk
+S: Maintained
+
SRM (Alpha) environment access
P: Jan-Benedict Glaw
M: jbglaw@lug-owl.de
@@ -4237,9 +4289,10 @@ L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
S: Maintained
TRIVIAL PATCHES
-P: Jesper Juhl
+P: Jiri Kosina
M: trivial@kernel.org
L: linux-kernel@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/jikos/trivial.git
S: Maintained
TTY LAYER
@@ -4309,13 +4362,6 @@ M: dushistov@mail.ru
L: linux-kernel@vger.kernel.org
S: Maintained
-UltraSPARC (sparc64)
-P: David S. Miller
-M: davem@davemloft.net
-L: sparclinux@vger.kernel.org
-T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
-S: Maintained
-
ULTRA-WIDEBAND (UWB) SUBSYSTEM:
P: David Vrabel
M: david.vrabel@csr.com
@@ -4387,7 +4433,8 @@ USB ET61X[12]51 DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb@vger.kernel.org
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.linux-projects.org
S: Maintained
@@ -4536,7 +4583,8 @@ USB SN9C1xx DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb@vger.kernel.org
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.linux-projects.org
S: Maintained
@@ -4565,7 +4613,8 @@ USB VIDEO CLASS
P: Laurent Pinchart
M: laurent.pinchart@skynet.be
L: linux-uvc-devel@lists.berlios.de (subscribers-only)
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://linux-uvc.berlios.de
S: Maintained
@@ -4573,7 +4622,8 @@ USB W996[87]CF DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb@vger.kernel.org
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.linux-projects.org
S: Maintained
@@ -4587,7 +4637,8 @@ USB ZC0301 DRIVER
P: Luca Risolia
M: luca.risolia@studio.unibo.it
L: linux-usb@vger.kernel.org
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.linux-projects.org
S: Maintained
@@ -4602,7 +4653,8 @@ USB ZR364XX DRIVER
P: Antoine Jacquet
M: royale@zerezo.com
L: linux-usb@vger.kernel.org
-L: video4linux-list@redhat.com
+L: linux-media@vger.kernel.org
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://royale.zerezo.com/zr364xx/
S: Maintained
@@ -4671,10 +4723,10 @@ S: Maintained
VIDEO FOR LINUX (V4L)
P: Mauro Carvalho Chehab
M: mchehab@infradead.org
-M: v4l-dvb-maintainer@linuxtv.org
+L: linux-media@vger.kernel.org
L: video4linux-list@redhat.com
W: http://linuxtv.org
-T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
+T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
VLAN (802.1Q)
@@ -4747,6 +4799,14 @@ M: zaga@fly.cc.fer.hr
L: linux-scsi@vger.kernel.org
S: Maintained
+WIMAX STACK
+P: Inaky Perez-Gonzalez
+M: inaky.perez-gonzalez@intel.com
+M: linux-wimax@intel.com
+L: wimax@linuxwimax.org
+S: Supported
+W: http://linuxwimax.org
+
WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
P: David Vrabel
M: david.vrabel@csr.com
@@ -4787,6 +4847,7 @@ P: Ingo Molnar
M: mingo@redhat.com
P: H. Peter Anvin
M: hpa@zytor.com
+M: x86@kernel.org
L: linux-kernel@vger.kernel.org
T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
S: Maintained
@@ -4802,11 +4863,11 @@ S: Supported
XFS FILESYSTEM
P: Silicon Graphics Inc
-P: Tim Shimmin
+P: Bill O'Donnell
M: xfs-masters@oss.sgi.com
L: xfs@oss.sgi.com
W: http://oss.sgi.com/projects/xfs
-T: git git://oss.sgi.com:8090/xfs/xfs-2.6.git
+T: git://oss.sgi.com/xfs/xfs.git
S: Supported
XILINX SYSTEMACE DRIVER
diff --git a/Makefile b/Makefile
index d13a9694e159..7715b2c14fb4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 28
-EXTRAVERSION =
+SUBLEVEL = 29
+EXTRAVERSION = -rc3
NAME = Erotic Pickled Herring
# *DOCUMENTATION*
@@ -213,6 +213,10 @@ endif
# Where to locate arch specific headers
hdr-arch := $(SRCARCH)
+ifeq ($(ARCH),m68knommu)
+ hdr-arch := m68k
+endif
+
KCONFIG_CONFIG ?= .config
# SHELL used by kbuild
@@ -321,7 +325,8 @@ KALLSYMS = scripts/kallsyms
PERL = perl
CHECK = sparse
-CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
+CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
+ -Wbitwise -Wno-return-void $(CF)
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE = $(MODFLAGS)
@@ -605,25 +610,20 @@ export INSTALL_PATH ?= /boot
MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
export MODLIB
-strip-symbols := $(srctree)/scripts/strip-symbols \
- $(wildcard $(srctree)/arch/$(ARCH)/scripts/strip-symbols)
-
#
-# INSTALL_MOD_STRIP, if defined, will cause modules to be stripped while
-# they get installed. If INSTALL_MOD_STRIP is '1', then the default
-# options (see below) will be used. Otherwise, INSTALL_MOD_STRIP will
-# be used as the option(s) to the objcopy command.
+# INSTALL_MOD_STRIP, if defined, will cause modules to be
+# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then
+# the default option --strip-debug will be used. Otherwise,
+# INSTALL_MOD_STRIP will used as the options to the strip command.
+
ifdef INSTALL_MOD_STRIP
ifeq ($(INSTALL_MOD_STRIP),1)
-mod_strip_cmd = $(OBJCOPY) --strip-debug
-ifeq ($(CONFIG_KALLSYMS_ALL),$(CONFIG_KALLSYMS_STRIP_GENERATED))
-mod_strip_cmd += --wildcard $(addprefix --strip-symbols ,$(strip-symbols))
-endif
+mod_strip_cmd = $(STRIP) --strip-debug
else
-mod_strip_cmd = $(OBJCOPY) $(INSTALL_MOD_STRIP)
+mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
endif # INSTALL_MOD_STRIP=1
else
-mod_strip_cmd = false
+mod_strip_cmd = true
endif # INSTALL_MOD_STRIP
export mod_strip_cmd
@@ -753,7 +753,6 @@ last_kallsyms := 2
endif
kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
-kallsyms.h := $(wildcard include/config/kallsyms/*.h) $(wildcard include/config/kallsyms/*/*.h)
define verify_kallsyms
$(Q)$(if $($(quiet)cmd_sysmap), \
@@ -778,41 +777,24 @@ endef
# Generate .S file with all kernel symbols
quiet_cmd_kallsyms = KSYM $@
- cmd_kallsyms = { test $* -eq 0 || $(NM) -n $<; } \
- | $(KALLSYMS) $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) >$@
+ cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
+ $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
-quiet_cmd_kstrip = STRIP $@
- cmd_kstrip = $(OBJCOPY) --wildcard $(addprefix --strip$(if $(CONFIG_RELOCATABLE),-unneeded)-symbols ,$(filter %/scripts/strip-symbols,$^)) $< $@
-
-$(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): KBUILD_AFLAGS += -Wa,--strip-local-absolute
-$(foreach n,0 1 2 3,.tmp_kallsyms$(n).o): %.o: %.S scripts FORCE
+.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
$(call if_changed_dep,as_o_S)
-ifeq ($(CONFIG_KALLSYMS_STRIP_GENERATED),y)
-strip-ext := .stripped
-endif
-
-.tmp_kallsyms%.S: .tmp_vmlinux%$(strip-ext) $(KALLSYMS) $(kallsyms.h)
+.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
$(call cmd,kallsyms)
-# make -jN seems to have problems with intermediate files, see bug #3330.
-.SECONDARY: $(foreach n,1 2 3,.tmp_vmlinux$(n).stripped)
-.tmp_vmlinux%.stripped: .tmp_vmlinux% $(strip-symbols) $(kallsyms.h)
- $(call cmd,kstrip)
-
-ifneq ($(CONFIG_DEBUG_INFO),y)
-.tmp_vmlinux%: LDFLAGS_vmlinux += -S
-endif
# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
-.tmp_vmlinux%: $(vmlinux-lds) $(vmlinux-all) FORCE
- $(if $(filter 1,$*),$(call if_changed_rule,ksym_ld),$(call if_changed,vmlinux__))
+.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
+ $(call if_changed_rule,ksym_ld)
-.tmp_vmlinux0$(strip-ext):
- $(Q)echo "placeholder" >$@
+.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
+ $(call if_changed,vmlinux__)
-.tmp_vmlinux1: .tmp_kallsyms0.o
-.tmp_vmlinux2: .tmp_kallsyms1.o
-.tmp_vmlinux3: .tmp_kallsyms2.o
+.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
+ $(call if_changed,vmlinux__)
# Needs to visit scripts/ before $(KALLSYMS) can be used.
$(KALLSYMS): scripts ;
@@ -964,6 +946,7 @@ ifneq ($(KBUILD_SRC),)
mkdir -p include2; \
ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \
fi
+ ln -fsn $(srctree) source
endif
# prepare2 creates a makefile if using a separate output directory
@@ -1007,7 +990,7 @@ define check-symlink
endef
# We create the target directory of the symlink if it does
-# not exist so the test in chack-symlink works and we have a
+# not exist so the test in check-symlink works and we have a
# directory for generated filesas used by some architectures.
define create-symlink
if [ ! -L include/asm ]; then \
diff --git a/README b/README
index 159912cf5155..90a07658ede1 100644
--- a/README
+++ b/README
@@ -52,11 +52,11 @@ DOCUMENTATION:
- The Documentation/DocBook/ subdirectory contains several guides for
kernel developers and users. These guides can be rendered in a
- number of formats: PostScript (.ps), PDF, and HTML, among others.
- After installation, "make psdocs", "make pdfdocs", or "make htmldocs"
- will render the documentation in the requested format.
+ number of formats: PostScript (.ps), PDF, HTML, & man-pages, among others.
+ After installation, "make psdocs", "make pdfdocs", "make htmldocs",
+ or "make mandocs" will render the documentation in the requested format.
-INSTALLING the kernel:
+INSTALLING the kernel source:
- If you install the full sources, put the kernel tarball in a
directory where you have permissions (eg. your home directory) and
@@ -187,14 +187,9 @@ CONFIGURING the kernel:
"make randconfig" Create a ./.config file by setting symbol
values to random values.
- The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
- also use the environment variable KCONFIG_ALLCONFIG to specify a
- filename that contains config options that the user requires to be
- set to a specific value. If KCONFIG_ALLCONFIG=filename is not used,
- "make *config" checks for a file named "all{yes/mod/no/random}.config"
- for symbol values that are to be forced. If this file is not found,
- it checks for a file named "all.config" to contain forced values.
-
+ You can find more information on using the Linux kernel config tools
+ in Documentation/kbuild/make-configs.txt.
+
NOTES on "make config":
- having unnecessary drivers will make the kernel bigger, and can
under some circumstances lead to problems: probing for a
@@ -231,6 +226,19 @@ COMPILING the kernel:
- If you configured any of the parts of the kernel as `modules', you
will also have to do "make modules_install".
+ - Verbose kernel compile/build output:
+
+ Normally the kernel build system runs in a fairly quiet mode (but not
+ totally silent). However, sometimes you or other kernel developers need
+ to see compile, link, or other commands exactly as they are executed.
+ For this, use "verbose" build mode. This is done by inserting
+ "V=1" in the "make" command. E.g.:
+
+ make V=1 all
+
+ To have the build system also tell the reason for the rebuild of each
+ target, use "V=2". The default is "V=0".
+
- Keep a backup kernel handy in case something goes wrong. This is
especially true for the development releases, since each new release
contains new code which has not been debugged. Make sure you keep a
diff --git a/arch/Kconfig b/arch/Kconfig
index 2e13aa261929..550dab22daa1 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -62,6 +62,9 @@ config HAVE_EFFICIENT_UNALIGNED_ACCESS
See Documentation/unaligned-memory-access.txt for more
information on the topic of unaligned memory accesses.
+config HAVE_SYSCALL_WRAPPERS
+ bool
+
config KRETPROBES
def_bool y
depends on KPROBES && HAVE_KRETPROBES
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 6110197757a3..9fb8aae5c391 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -8,6 +8,7 @@ config ALPHA
select HAVE_AOUT
select HAVE_IDE
select HAVE_OPROFILE
+ select HAVE_SYSCALL_WRAPPERS
help
The Alpha is a 64-bit general-purpose processor designed and
marketed by the Digital Equipment Corporation of blessed memory,
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index ca88e54dec93..62b363584b2b 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -1,6 +1,7 @@
#ifndef _ALPHA_ATOMIC_H
#define _ALPHA_ATOMIC_H
+#include <linux/types.h>
#include <asm/barrier.h>
#include <asm/system.h>
@@ -13,14 +14,6 @@
*/
-/*
- * Counter is volatile to make sure gcc doesn't try to be clever
- * and move things around on us. We need to use _exactly_ the address
- * the user gave us, not some alias that contains the same information.
- */
-typedef struct { volatile int counter; } atomic_t;
-typedef struct { volatile long counter; } atomic64_t;
-
#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
#define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } )
diff --git a/arch/alpha/include/asm/bug.h b/arch/alpha/include/asm/bug.h
index 695a5ee4b5d3..1720c8ad86fe 100644
--- a/arch/alpha/include/asm/bug.h
+++ b/arch/alpha/include/asm/bug.h
@@ -8,17 +8,12 @@
/* ??? Would be nice to use .gprel32 here, but we can't be sure that the
function loaded the GP, so this could fail in modules. */
-static inline void ATTRIB_NORET __BUG(const char *file, int line)
-{
- __asm__ __volatile__(
- "call_pal %0 # bugchk\n\t"
- ".long %1\n\t.8byte %2"
- : : "i" (PAL_bugchk), "i"(line), "i"(file));
- for ( ; ; )
- ;
-}
-
-#define BUG() __BUG(__FILE__, __LINE__)
+#define BUG() do { \
+ __asm__ __volatile__( \
+ "call_pal %0 # bugchk\n\t" \
+ ".long %1\n\t.8byte %2" \
+ : : "i"(PAL_bugchk), "i"(__LINE__), "i"(__FILE__)); \
+ for ( ; ; ); } while (0)
#define HAVE_ARCH_BUG
#endif
diff --git a/arch/alpha/include/asm/byteorder.h b/arch/alpha/include/asm/byteorder.h
index 58e958fc7f1b..73683093202d 100644
--- a/arch/alpha/include/asm/byteorder.h
+++ b/arch/alpha/include/asm/byteorder.h
@@ -1,47 +1,6 @@
#ifndef _ALPHA_BYTEORDER_H
#define _ALPHA_BYTEORDER_H
-#include <asm/types.h>
-#include <linux/compiler.h>
-#include <asm/compiler.h>
-
-#ifdef __GNUC__
-
-static inline __attribute_const__ __u32 __arch__swab32(__u32 x)
-{
- /*
- * Unfortunately, we can't use the 6 instruction sequence
- * on ev6 since the latency of the UNPKBW is 3, which is
- * pretty hard to hide. Just in case a future implementation
- * has a lower latency, here's the sequence (also by Mike Burrows)
- *
- * UNPKBW a0, v0 v0: 00AA00BB00CC00DD
- * SLL v0, 24, a0 a0: BB00CC00DD000000
- * BIS v0, a0, a0 a0: BBAACCBBDDCC00DD
- * EXTWL a0, 6, v0 v0: 000000000000BBAA
- * ZAP a0, 0xf3, a0 a0: 00000000DDCC0000
- * ADDL a0, v0, v0 v0: ssssssssDDCCBBAA
- */
-
- __u64 t0, t1, t2, t3;
-
- t0 = __kernel_inslh(x, 7); /* t0 : 0000000000AABBCC */
- t1 = __kernel_inswl(x, 3); /* t1 : 000000CCDD000000 */
- t1 |= t0; /* t1 : 000000CCDDAABBCC */
- t2 = t1 >> 16; /* t2 : 0000000000CCDDAA */
- t0 = t1 & 0xFF00FF00; /* t0 : 00000000DD00BB00 */
- t3 = t2 & 0x00FF00FF; /* t3 : 0000000000CC00AA */
- t1 = t0 + t3; /* t1 : ssssssssDDCCBBAA */
-
- return t1;
-}
-
-#define __arch__swab32 __arch__swab32
-
-#endif /* __GNUC__ */
-
-#define __BYTEORDER_HAS_U64__
-
#include <linux/byteorder/little_endian.h>
#endif /* _ALPHA_BYTEORDER_H */
diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h
index a5801ae02e4b..04eb5681448c 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -29,6 +29,8 @@
#else /* no PCI - no IOMMU. */
+#include <asm/io.h> /* for virt_to_phys() */
+
struct scatterlist;
void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
diff --git a/arch/alpha/include/asm/machvec.h b/arch/alpha/include/asm/machvec.h
index a86c083cdf7f..fea4ea75b79d 100644
--- a/arch/alpha/include/asm/machvec.h
+++ b/arch/alpha/include/asm/machvec.h
@@ -21,6 +21,7 @@ struct pci_dev;
struct pci_ops;
struct pci_controller;
struct _alpha_agp_info;
+struct rtc_time;
struct alpha_machine_vector
{
@@ -94,6 +95,9 @@ struct alpha_machine_vector
struct _alpha_agp_info *(*agp_info)(void);
+ unsigned int (*rtc_get_time)(struct rtc_time *);
+ int (*rtc_set_time)(struct rtc_time *);
+
const char *vector_name;
/* NUMA information */
diff --git a/arch/alpha/include/asm/pgalloc.h b/arch/alpha/include/asm/pgalloc.h
index fd090155dccd..bc2a0daf2d92 100644
--- a/arch/alpha/include/asm/pgalloc.h
+++ b/arch/alpha/include/asm/pgalloc.h
@@ -50,7 +50,12 @@ pmd_free(struct mm_struct *mm, pmd_t *pmd)
free_page((unsigned long)pmd);
}
-extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+static inline pte_t *
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+ return pte;
+}
static inline void
pte_free_kernel(struct mm_struct *mm, pte_t *pte)
diff --git a/arch/alpha/include/asm/rtc.h b/arch/alpha/include/asm/rtc.h
index 4e854b1333eb..1f7fba671ae6 100644
--- a/arch/alpha/include/asm/rtc.h
+++ b/arch/alpha/include/asm/rtc.h
@@ -1,9 +1,15 @@
#ifndef _ALPHA_RTC_H
#define _ALPHA_RTC_H
-/*
- * Alpha uses the default access methods for the RTC.
- */
+#if defined(CONFIG_ALPHA_GENERIC)
+# define get_rtc_time alpha_mv.rtc_get_time
+# define set_rtc_time alpha_mv.rtc_set_time
+#else
+# if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP)
+# define get_rtc_time marvel_get_rtc_time
+# define set_rtc_time marvel_set_rtc_time
+# endif
+#endif
#include <asm-generic/rtc.h>
diff --git a/arch/alpha/include/asm/smp.h b/arch/alpha/include/asm/smp.h
index 544c69af8168..547e90951cec 100644
--- a/arch/alpha/include/asm/smp.h
+++ b/arch/alpha/include/asm/smp.h
@@ -45,7 +45,6 @@ extern struct cpuinfo_alpha cpu_data[NR_CPUS];
#define raw_smp_processor_id() (current_thread_info()->cpu)
extern int smp_num_cpus;
-#define cpu_possible_map cpu_present_map
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi(cpumask_t mask);
diff --git a/arch/alpha/include/asm/swab.h b/arch/alpha/include/asm/swab.h
new file mode 100644
index 000000000000..68e7089e02d5
--- /dev/null
+++ b/arch/alpha/include/asm/swab.h
@@ -0,0 +1,42 @@
+#ifndef _ALPHA_SWAB_H
+#define _ALPHA_SWAB_H
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+#include <asm/compiler.h>
+
+#ifdef __GNUC__
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+ /*
+ * Unfortunately, we can't use the 6 instruction sequence
+ * on ev6 since the latency of the UNPKBW is 3, which is
+ * pretty hard to hide. Just in case a future implementation
+ * has a lower latency, here's the sequence (also by Mike Burrows)
+ *
+ * UNPKBW a0, v0 v0: 00AA00BB00CC00DD
+ * SLL v0, 24, a0 a0: BB00CC00DD000000
+ * BIS v0, a0, a0 a0: BBAACCBBDDCC00DD
+ * EXTWL a0, 6, v0 v0: 000000000000BBAA
+ * ZAP a0, 0xf3, a0 a0: 00000000DDCC0000
+ * ADDL a0, v0, v0 v0: ssssssssDDCCBBAA
+ */
+
+ __u64 t0, t1, t2, t3;
+
+ t0 = __kernel_inslh(x, 7); /* t0 : 0000000000AABBCC */
+ t1 = __kernel_inswl(x, 3); /* t1 : 000000CCDD000000 */
+ t1 |= t0; /* t1 : 000000CCDDAABBCC */
+ t2 = t1 >> 16; /* t2 : 0000000000CCDDAA */
+ t0 = t1 & 0xFF00FF00; /* t0 : 00000000DD00BB00 */
+ t3 = t2 & 0x00FF00FF; /* t3 : 0000000000CC00AA */
+ t1 = t0 + t3; /* t1 : ssssssssDDCCBBAA */
+
+ return t1;
+}
+#define __arch_swab32 __arch_swab32
+
+#endif /* __GNUC__ */
+
+#endif /* _ALPHA_SWAB_H */
diff --git a/arch/alpha/include/asm/topology.h b/arch/alpha/include/asm/topology.h
index 149532e162c4..b4f284c72ff3 100644
--- a/arch/alpha/include/asm/topology.h
+++ b/arch/alpha/include/asm/topology.h
@@ -39,7 +39,24 @@ static inline cpumask_t node_to_cpumask(int node)
return node_cpu_mask;
}
+extern struct cpumask node_to_cpumask_map[];
+/* FIXME: This is dumb, recalculating every time. But simple. */
+static const struct cpumask *cpumask_of_node(int node)
+{
+ int cpu;
+
+ cpumask_clear(&node_to_cpumask_map[node]);
+
+ for_each_online_cpu(cpu) {
+ if (cpu_to_node(cpu) == node)
+ cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
+ }
+
+ return &node_to_cpumask_map[node];
+}
+
#define pcibus_to_cpumask(bus) (cpu_online_map)
+#define cpumask_of_pcibus(bus) (cpu_online_mask)
#endif /* !CONFIG_NUMA */
# include <asm-generic/topology.h>
diff --git a/arch/alpha/kernel/.gitignore b/arch/alpha/kernel/.gitignore
new file mode 100644
index 000000000000..c5f676c3c224
--- /dev/null
+++ b/arch/alpha/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index ac706c1d7ada..b4697759a123 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror -Wno-sign-compare
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o \
- alpha_ksyms.o systbls.o err_common.o io.o
+ alpha_ksyms.o systbls.o err_common.o io.o binfmt_loader.o
obj-$(CONFIG_VGA_HOSE) += console.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/alpha/kernel/binfmt_loader.c b/arch/alpha/kernel/binfmt_loader.c
new file mode 100644
index 000000000000..4a0af906b00a
--- /dev/null
+++ b/arch/alpha/kernel/binfmt_loader.c
@@ -0,0 +1,51 @@
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mm_types.h>
+#include <linux/binfmts.h>
+#include <linux/a.out.h>
+
+static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+{
+ struct exec *eh = (struct exec *)bprm->buf;
+ unsigned long loader;
+ struct file *file;
+ int retval;
+
+ if (eh->fh.f_magic != 0x183 || (eh->fh.f_flags & 0x3000) != 0x3000)
+ return -ENOEXEC;
+
+ if (bprm->loader)
+ return -ENOEXEC;
+
+ allow_write_access(bprm->file);
+ fput(bprm->file);
+ bprm->file = NULL;
+
+ loader = bprm->vma->vm_end - sizeof(void *);
+
+ file = open_exec("/sbin/loader");
+ retval = PTR_ERR(file);
+ if (IS_ERR(file))
+ return retval;
+
+ /* Remember if the application is TASO. */
+ bprm->taso = eh->ah.entry < 0x100000000UL;
+
+ bprm->file = file;
+ bprm->loader = loader;
+ retval = prepare_binprm(bprm);
+ if (retval < 0)
+ return retval;
+ return search_binary_handler(bprm,regs);
+}
+
+static struct linux_binfmt loader_format = {
+ .load_binary = load_binary,
+};
+
+static int __init init_loader_binfmt(void)
+{
+ return register_binfmt(&loader_format);
+}
+arch_initcall(init_loader_binfmt);
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index 9cd8dca742a7..e302daecbe56 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -658,16 +658,8 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write)
rtc_access.data = bcd2bin(b);
rtc_access.function = 0x48 + !write; /* GET/PUT_TOY */
-#ifdef CONFIG_SMP
- if (smp_processor_id() != boot_cpuid)
- smp_call_function_single(boot_cpuid,
- __marvel_access_rtc,
- &rtc_access, 1);
- else
- __marvel_access_rtc(&rtc_access);
-#else
__marvel_access_rtc(&rtc_access);
-#endif
+
ret = bin2bcd(rtc_access.data);
break;
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index f77345bc66a9..e4a54b615894 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -896,9 +896,9 @@ sys_getxpid:
.end sys_getxpid
.align 4
- .globl sys_pipe
- .ent sys_pipe
-sys_pipe:
+ .globl sys_alpha_pipe
+ .ent sys_alpha_pipe
+sys_alpha_pipe:
lda $sp, -16($sp)
stq $26, 0($sp)
.prologue 0
@@ -916,7 +916,7 @@ sys_pipe:
stq $1, 80+16($sp)
1: lda $sp, 16($sp)
ret
-.end sys_pipe
+.end sys_alpha_pipe
.align 4
.globl sys_execve
@@ -933,7 +933,7 @@ sys_execve:
osf_sigprocmask:
.prologue 0
mov $sp, $18
- jmp $31, do_osf_sigprocmask
+ jmp $31, sys_osf_sigprocmask
.end osf_sigprocmask
.align 4
diff --git a/arch/alpha/kernel/init_task.c b/arch/alpha/kernel/init_task.c
index 1f762189fa64..c2938e574a40 100644
--- a/arch/alpha/kernel/init_task.c
+++ b/arch/alpha/kernel/init_task.c
@@ -8,7 +8,6 @@
#include <asm/uaccess.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index c626a821cdcb..703731accda6 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -50,12 +50,13 @@ int irq_select_affinity(unsigned int irq)
if (!irq_desc[irq].chip->set_affinity || irq_user_affinity[irq])
return 1;
- while (!cpu_possible(cpu) || !cpu_isset(cpu, irq_default_affinity))
+ while (!cpu_possible(cpu) ||
+ !cpumask_test_cpu(cpu, irq_default_affinity))
cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
last_cpu = cpu;
irq_desc[irq].affinity = cpumask_of_cpu(cpu);
- irq_desc[irq].chip->set_affinity(irq, cpumask_of_cpu(cpu));
+ irq_desc[irq].chip->set_affinity(irq, cpumask_of(cpu));
return 0;
}
#endif /* CONFIG_SMP */
diff --git a/arch/alpha/kernel/irq_srm.c b/arch/alpha/kernel/irq_srm.c
index 32212014fbe9..a03fbca4940e 100644
--- a/arch/alpha/kernel/irq_srm.c
+++ b/arch/alpha/kernel/irq_srm.c
@@ -63,6 +63,8 @@ init_srm_irqs(long max, unsigned long ignore_mask)
{
long i;
+ if (NR_IRQS <= 16)
+ return;
for (i = 16; i < max; ++i) {
if (i < 64 && ((ignore_mask >> i) & 1))
continue;
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index 466c9dff8181..512685f78097 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -40,7 +40,10 @@
#define CAT1(x,y) x##y
#define CAT(x,y) CAT1(x,y)
-#define DO_DEFAULT_RTC .rtc_port = 0x70
+#define DO_DEFAULT_RTC \
+ .rtc_port = 0x70, \
+ .rtc_get_time = common_get_rtc_time, \
+ .rtc_set_time = common_set_rtc_time
#define DO_EV4_MMU \
.max_asn = EV4_MAX_ASN, \
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 18a3ea1aac51..ae41f097864b 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -54,8 +54,7 @@ extern int do_pipe(int *);
* identical to OSF as we don't return 0 on success, but doing otherwise
* would require changes to libc. Hopefully this is good enough.
*/
-asmlinkage unsigned long
-osf_brk(unsigned long brk)
+SYSCALL_DEFINE1(osf_brk, unsigned long, brk)
{
unsigned long retval = sys_brk(brk);
if (brk && brk != retval)
@@ -66,9 +65,9 @@ osf_brk(unsigned long brk)
/*
* This is pure guess-work..
*/
-asmlinkage int
-osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
- unsigned long bss_start, unsigned long bss_len)
+SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start,
+ unsigned long, text_len, unsigned long, bss_start,
+ unsigned long, bss_len)
{
struct mm_struct *mm;
@@ -146,9 +145,9 @@ Efault:
return -EFAULT;
}
-asmlinkage int
-osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
- unsigned int count, long __user *basep)
+SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
+ struct osf_dirent __user *, dirent, unsigned int, count,
+ long __user *, basep)
{
int error;
struct file *file;
@@ -177,9 +176,9 @@ osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
#undef NAME_OFFSET
-asmlinkage unsigned long
-osf_mmap(unsigned long addr, unsigned long len, unsigned long prot,
- unsigned long flags, unsigned long fd, unsigned long off)
+SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len,
+ unsigned long, prot, unsigned long, flags, unsigned long, fd,
+ unsigned long, off)
{
struct file *file = NULL;
unsigned long ret = -EBADF;
@@ -254,8 +253,8 @@ do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
return error;
}
-asmlinkage int
-osf_statfs(char __user *pathname, struct osf_statfs __user *buffer, unsigned long bufsiz)
+SYSCALL_DEFINE3(osf_statfs, char __user *, pathname,
+ struct osf_statfs __user *, buffer, unsigned long, bufsiz)
{
struct path path;
int retval;
@@ -268,8 +267,8 @@ osf_statfs(char __user *pathname, struct osf_statfs __user *buffer, unsigned lon
return retval;
}
-asmlinkage int
-osf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bufsiz)
+SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd,
+ struct osf_statfs __user *, buffer, unsigned long, bufsiz)
{
struct file *file;
int retval;
@@ -368,8 +367,8 @@ osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
return do_mount("", dirname, "proc", flags, NULL);
}
-asmlinkage int
-osf_mount(unsigned long typenr, char __user *path, int flag, void __user *data)
+SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, char __user *, path,
+ int, flag, void __user *, data)
{
int retval = -EINVAL;
char *name;
@@ -399,8 +398,7 @@ osf_mount(unsigned long typenr, char __user *path, int flag, void __user *data)
return retval;
}
-asmlinkage int
-osf_utsname(char __user *name)
+SYSCALL_DEFINE1(osf_utsname, char __user *, name)
{
int error;
@@ -423,14 +421,12 @@ osf_utsname(char __user *name)
return error;
}
-asmlinkage unsigned long
-sys_getpagesize(void)
+SYSCALL_DEFINE0(getpagesize)
{
return PAGE_SIZE;
}
-asmlinkage unsigned long
-sys_getdtablesize(void)
+SYSCALL_DEFINE0(getdtablesize)
{
return sysctl_nr_open;
}
@@ -438,8 +434,7 @@ sys_getdtablesize(void)
/*
* For compatibility with OSF/1 only. Use utsname(2) instead.
*/
-asmlinkage int
-osf_getdomainname(char __user *name, int namelen)
+SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
{
unsigned len;
int i;
@@ -527,8 +522,8 @@ enum pl_code {
PL_DEL = 5, PL_FDEL = 6
};
-asmlinkage long
-osf_proplist_syscall(enum pl_code code, union pl_args __user *args)
+SYSCALL_DEFINE2(osf_proplist_syscall, enum pl_code, code,
+ union pl_args __user *, args)
{
long error;
int __user *min_buf_size_ptr;
@@ -567,8 +562,8 @@ osf_proplist_syscall(enum pl_code code, union pl_args __user *args)
return error;
}
-asmlinkage int
-osf_sigstack(struct sigstack __user *uss, struct sigstack __user *uoss)
+SYSCALL_DEFINE2(osf_sigstack, struct sigstack __user *, uss,
+ struct sigstack __user *, uoss)
{
unsigned long usp = rdusp();
unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size;
@@ -608,8 +603,7 @@ osf_sigstack(struct sigstack __user *uss, struct sigstack __user *uoss)
return error;
}
-asmlinkage long
-osf_sysinfo(int command, char __user *buf, long count)
+SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
{
char *sysinfo_table[] = {
utsname()->sysname,
@@ -647,9 +641,8 @@ osf_sysinfo(int command, char __user *buf, long count)
return err;
}
-asmlinkage unsigned long
-osf_getsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
- int __user *start, void __user *arg)
+SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
+ unsigned long, nbytes, int __user *, start, void __user *, arg)
{
unsigned long w;
struct percpu_struct *cpu;
@@ -705,9 +698,8 @@ osf_getsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
return -EOPNOTSUPP;
}
-asmlinkage unsigned long
-osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
- int __user *start, void __user *arg)
+SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
+ unsigned long, nbytes, int __user *, start, void __user *, arg)
{
switch (op) {
case SSI_IEEE_FP_CONTROL: {
@@ -880,8 +872,8 @@ jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value)
value->tv_sec = jiffies / HZ;
}
-asmlinkage int
-osf_gettimeofday(struct timeval32 __user *tv, struct timezone __user *tz)
+SYSCALL_DEFINE2(osf_gettimeofday, struct timeval32 __user *, tv,
+ struct timezone __user *, tz)
{
if (tv) {
struct timeval ktv;
@@ -896,8 +888,8 @@ osf_gettimeofday(struct timeval32 __user *tv, struct timezone __user *tz)
return 0;
}
-asmlinkage int
-osf_settimeofday(struct timeval32 __user *tv, struct timezone __user *tz)
+SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv,
+ struct timezone __user *, tz)
{
struct timespec kts;
struct timezone ktz;
@@ -916,8 +908,7 @@ osf_settimeofday(struct timeval32 __user *tv, struct timezone __user *tz)
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
-asmlinkage int
-osf_getitimer(int which, struct itimerval32 __user *it)
+SYSCALL_DEFINE2(osf_getitimer, int, which, struct itimerval32 __user *, it)
{
struct itimerval kit;
int error;
@@ -929,8 +920,8 @@ osf_getitimer(int which, struct itimerval32 __user *it)
return error;
}
-asmlinkage int
-osf_setitimer(int which, struct itimerval32 __user *in, struct itimerval32 __user *out)
+SYSCALL_DEFINE3(osf_setitimer, int, which, struct itimerval32 __user *, in,
+ struct itimerval32 __user *, out)
{
struct itimerval kin, kout;
int error;
@@ -952,8 +943,8 @@ osf_setitimer(int which, struct itimerval32 __user *in, struct itimerval32 __use
}
-asmlinkage int
-osf_utimes(char __user *filename, struct timeval32 __user *tvs)
+SYSCALL_DEFINE2(osf_utimes, char __user *, filename,
+ struct timeval32 __user *, tvs)
{
struct timespec tv[2];
@@ -979,9 +970,8 @@ osf_utimes(char __user *filename, struct timeval32 __user *tvs)
#define MAX_SELECT_SECONDS \
((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-asmlinkage int
-osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
- struct timeval32 __user *tvp)
+SYSCALL_DEFINE5(osf_select, int, n, fd_set __user *, inp, fd_set __user *, outp,
+ fd_set __user *, exp, struct timeval32 __user *, tvp)
{
struct timespec end_time, *to = NULL;
if (tvp) {
@@ -1026,8 +1016,7 @@ struct rusage32 {
long ru_nivcsw; /* involuntary " */
};
-asmlinkage int
-osf_getrusage(int who, struct rusage32 __user *ru)
+SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
{
struct rusage32 r;
@@ -1053,9 +1042,8 @@ osf_getrusage(int who, struct rusage32 __user *ru)
return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
}
-asmlinkage long
-osf_wait4(pid_t pid, int __user *ustatus, int options,
- struct rusage32 __user *ur)
+SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
+ struct rusage32 __user *, ur)
{
struct rusage r;
long ret, err;
@@ -1101,8 +1089,8 @@ osf_wait4(pid_t pid, int __user *ustatus, int options,
* seems to be a timeval pointer, and I suspect the second
* one is the time remaining.. Ho humm.. No documentation.
*/
-asmlinkage int
-osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remain)
+SYSCALL_DEFINE2(osf_usleep_thread, struct timeval32 __user *, sleep,
+ struct timeval32 __user *, remain)
{
struct timeval tmp;
unsigned long ticks;
@@ -1155,8 +1143,7 @@ struct timex32 {
int :32; int :32; int :32; int :32;
};
-asmlinkage int
-sys_old_adjtimex(struct timex32 __user *txc_p)
+SYSCALL_DEFINE1(old_adjtimex, struct timex32 __user *, txc_p)
{
struct timex txc;
int ret;
@@ -1267,8 +1254,8 @@ osf_fix_iov_len(const struct iovec __user *iov, unsigned long count)
return 0;
}
-asmlinkage ssize_t
-osf_readv(unsigned long fd, const struct iovec __user * vector, unsigned long count)
+SYSCALL_DEFINE3(osf_readv, unsigned long, fd,
+ const struct iovec __user *, vector, unsigned long, count)
{
if (unlikely(personality(current->personality) == PER_OSF4))
if (osf_fix_iov_len(vector, count))
@@ -1276,8 +1263,8 @@ osf_readv(unsigned long fd, const struct iovec __user * vector, unsigned long co
return sys_readv(fd, vector, count);
}
-asmlinkage ssize_t
-osf_writev(unsigned long fd, const struct iovec __user * vector, unsigned long count)
+SYSCALL_DEFINE3(osf_writev, unsigned long, fd,
+ const struct iovec __user *, vector, unsigned long, count)
{
if (unlikely(personality(current->personality) == PER_OSF4))
if (osf_fix_iov_len(vector, count))
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 8ac08311f5a5..c19a376520f4 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -109,7 +109,8 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
/* Stubs for the routines in pci_iommu.c: */
void *
-pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
+__pci_alloc_consistent(struct pci_dev *pdev, size_t size,
+ dma_addr_t *dma_addrp, gfp_t gfp)
{
return NULL;
}
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index ff8cb638472e..a3b938811400 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -320,24 +320,6 @@ pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
-/* Most Alphas have straight-forward swizzling needs. */
-
-u8 __init
-common_swizzle(struct pci_dev *dev, u8 *pinp)
-{
- u8 pin = *pinp;
-
- while (dev->bus->parent) {
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
- /* Move up the chain of bridges. */
- dev = dev->bus->self;
- }
- *pinp = pin;
-
- /* The slot is the slot of the last bridge. */
- return PCI_SLOT(dev->devfn);
-}
-
void
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
index f8b74995a002..00edd04b585e 100644
--- a/arch/alpha/kernel/pci_impl.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -106,16 +106,11 @@ struct pci_iommu_arena;
* Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
* Thus, each swizzle is ((pin-1) + (device#-4)) % 4
*
- * The following code swizzles for exactly one bridge. The routine
- * common_swizzle below handles multiple bridges. But there are a
- * couple boards that do strange things, so we define this here.
+ * pci_swizzle_interrupt_pin() swizzles for exactly one bridge. The routine
+ * pci_common_swizzle() handles multiple bridges. But there are a
+ * couple boards that do strange things.
*/
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
- return (((pin-1) + slot) % 4) + 1;
-}
-
/* The following macro is used to implement the table-based irq mapping
function for all single-bus Alphas. */
@@ -184,7 +179,7 @@ extern int pci_probe_only;
extern unsigned long alpha_agpgart_size;
extern void common_init_pci(void);
-extern u8 common_swizzle(struct pci_dev *, u8 *);
+#define common_swizzle pci_common_swizzle
extern struct pci_controller *alloc_pci_controller(void);
extern struct resource *alloc_resource(void);
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 351407e07e71..f238370c907d 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -94,6 +94,7 @@ common_shutdown_1(void *generic_ptr)
flags |= 0x00040000UL; /* "remain halted" */
*pflags = flags;
cpu_clear(cpuid, cpu_present_map);
+ cpu_clear(cpuid, cpu_possible_map);
halt();
}
#endif
@@ -120,6 +121,7 @@ common_shutdown_1(void *generic_ptr)
#ifdef CONFIG_SMP
/* Wait for the secondaries to halt. */
cpu_clear(boot_cpuid, cpu_present_map);
+ cpu_clear(boot_cpuid, cpu_possible_map);
while (cpus_weight(cpu_present_map))
barrier();
#endif
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 708d5ca87782..fe14c6747cd6 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -145,6 +145,8 @@ extern void smp_percpu_timer_interrupt(struct pt_regs *);
extern irqreturn_t timer_interrupt(int irq, void *dev);
extern void common_init_rtc(void);
extern unsigned long est_cycle_freq;
+extern unsigned int common_get_rtc_time(struct rtc_time *time);
+extern int common_set_rtc_time(struct rtc_time *time);
/* smc37c93x.c */
extern void SMC93x_Init(void);
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index a449e999027c..02bee6983ce2 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -79,6 +79,11 @@ int alpha_l3_cacheshape;
unsigned long alpha_verbose_mcheck = CONFIG_VERBOSE_MCHECK_ON;
#endif
+#ifdef CONFIG_NUMA
+struct cpumask node_to_cpumask_map[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL(node_to_cpumask_map);
+#endif
+
/* Which processor we booted from. */
int boot_cpuid;
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 410af4f3140e..df65eaa84c4c 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -19,6 +19,7 @@
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/bitops.h>
+#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/sigcontext.h>
@@ -51,8 +52,8 @@ static void do_signal(struct pt_regs *, struct switch_stack *,
* Note that we don't need to acquire the kernel lock for SMP
* operation, as all of this is local to this thread.
*/
-asmlinkage unsigned long
-do_osf_sigprocmask(int how, unsigned long newmask, struct pt_regs *regs)
+SYSCALL_DEFINE3(osf_sigprocmask, int, how, unsigned long, newmask,
+ struct pt_regs *, regs)
{
unsigned long oldmask = -EINVAL;
@@ -81,9 +82,9 @@ do_osf_sigprocmask(int how, unsigned long newmask, struct pt_regs *regs)
return oldmask;
}
-asmlinkage int
-osf_sigaction(int sig, const struct osf_sigaction __user *act,
- struct osf_sigaction __user *oact)
+SYSCALL_DEFINE3(osf_sigaction, int, sig,
+ const struct osf_sigaction __user *, act,
+ struct osf_sigaction __user *, oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
@@ -112,10 +113,9 @@ osf_sigaction(int sig, const struct osf_sigaction __user *act,
return ret;
}
-asmlinkage long
-sys_rt_sigaction(int sig, const struct sigaction __user *act,
- struct sigaction __user *oact,
- size_t sigsetsize, void __user *restorer)
+SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
+ struct sigaction __user *, oact,
+ size_t, sigsetsize, void __user *, restorer)
{
struct k_sigaction new_ka, old_ka;
int ret;
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index cf7da10097bb..00f1dc3dfd5f 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -70,11 +70,6 @@ enum ipi_message_type {
/* Set to a secondary's cpuid when it comes online. */
static int smp_secondary_alive __devinitdata = 0;
-/* Which cpus ids came online. */
-cpumask_t cpu_online_map;
-
-EXPORT_SYMBOL(cpu_online_map);
-
int smp_num_probed; /* Internal processor count */
int smp_num_cpus = 1; /* Number that came online. */
EXPORT_SYMBOL(smp_num_cpus);
@@ -125,8 +120,9 @@ void __cpuinit
smp_callin(void)
{
int cpuid = hard_smp_processor_id();
+ cpumask_t mask = cpu_online_map;
- if (cpu_test_and_set(cpuid, cpu_online_map)) {
+ if (cpu_test_and_set(cpuid, mask)) {
printk("??, cpu 0x%x already present??\n", cpuid);
BUG();
}
@@ -440,6 +436,7 @@ setup_smp(void)
((char *)cpubase + i*hwrpb->processor_size);
if ((cpu->flags & 0x1cc) == 0x1cc) {
smp_num_probed++;
+ cpu_set(i, cpu_possible_map);
cpu_set(i, cpu_present_map);
cpu->pal_revision = boot_cpu_palrev;
}
@@ -473,6 +470,7 @@ smp_prepare_cpus(unsigned int max_cpus)
/* Nothing to do on a UP box, or when told not to. */
if (smp_num_probed == 1 || max_cpus == 0) {
+ cpu_possible_map = cpumask_of_cpu(boot_cpuid);
cpu_present_map = cpumask_of_cpu(boot_cpuid);
printk(KERN_INFO "SMP mode deactivated.\n");
return;
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index c71b0fd7a61f..9c9d1fd4155f 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -177,19 +177,19 @@ cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
}
static void
-dp264_set_affinity(unsigned int irq, cpumask_t affinity)
+dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
{
spin_lock(&dp264_irq_lock);
- cpu_set_irq_affinity(irq, affinity);
+ cpu_set_irq_affinity(irq, *affinity);
tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
static void
-clipper_set_affinity(unsigned int irq, cpumask_t affinity)
+clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
{
spin_lock(&dp264_irq_lock);
- cpu_set_irq_affinity(irq - 16, affinity);
+ cpu_set_irq_affinity(irq - 16, *affinity);
tsunami_update_irq_hw(cached_irq_mask);
spin_unlock(&dp264_irq_lock);
}
@@ -481,7 +481,7 @@ monet_swizzle(struct pci_dev *dev, u8 *pinp)
slot = PCI_SLOT(dev->devfn);
break;
}
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+ pin = pci_swizzle_interrupt_pin(dev, pin);
/* Move up the chain of bridges. */
dev = dev->bus->self;
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
index 7ef3b6fb3700..baf60f36cbd7 100644
--- a/arch/alpha/kernel/sys_eiger.c
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -204,7 +204,7 @@ eiger_swizzle(struct pci_dev *dev, u8 *pinp)
break;
}
/* Must be a card-based bridge. */
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ pin = pci_swizzle_interrupt_pin(dev, pin);
/* Move up the chain of bridges. */
dev = dev->bus->self;
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
index 2c3de97de46c..e2516f9a8967 100644
--- a/arch/alpha/kernel/sys_jensen.c
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -261,6 +261,8 @@ struct alpha_machine_vector jensen_mv __initmv = {
.machine_check = jensen_machine_check,
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
.rtc_port = 0x170,
+ .rtc_get_time = common_get_rtc_time,
+ .rtc_set_time = common_set_rtc_time,
.nr_irqs = 16,
.device_interrupt = jensen_device_interrupt,
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 828449cd2636..c5a1a2438c67 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -23,6 +23,7 @@
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>
#include <asm/vga.h>
+#include <asm/rtc.h>
#include "proto.h"
#include "err_impl.h"
@@ -426,6 +427,57 @@ marvel_init_rtc(void)
init_rtc_irq();
}
+struct marvel_rtc_time {
+ struct rtc_time *time;
+ int retval;
+};
+
+#ifdef CONFIG_SMP
+static void
+smp_get_rtc_time(void *data)
+{
+ struct marvel_rtc_time *mrt = data;
+ mrt->retval = __get_rtc_time(mrt->time);
+}
+
+static void
+smp_set_rtc_time(void *data)
+{
+ struct marvel_rtc_time *mrt = data;
+ mrt->retval = __set_rtc_time(mrt->time);
+}
+#endif
+
+static unsigned int
+marvel_get_rtc_time(struct rtc_time *time)
+{
+#ifdef CONFIG_SMP
+ struct marvel_rtc_time mrt;
+
+ if (smp_processor_id() != boot_cpuid) {
+ mrt.time = time;
+ smp_call_function_single(boot_cpuid, smp_get_rtc_time, &mrt, 1);
+ return mrt.retval;
+ }
+#endif
+ return __get_rtc_time(time);
+}
+
+static int
+marvel_set_rtc_time(struct rtc_time *time)
+{
+#ifdef CONFIG_SMP
+ struct marvel_rtc_time mrt;
+
+ if (smp_processor_id() != boot_cpuid) {
+ mrt.time = time;
+ smp_call_function_single(boot_cpuid, smp_set_rtc_time, &mrt, 1);
+ return mrt.retval;
+ }
+#endif
+ return __set_rtc_time(time);
+}
+
static void
marvel_smp_callin(void)
{
@@ -466,7 +518,9 @@ marvel_smp_callin(void)
struct alpha_machine_vector marvel_ev7_mv __initmv = {
.vector_name = "MARVEL/EV7",
DO_EV7_MMU,
- DO_DEFAULT_RTC,
+ .rtc_port = 0x70,
+ .rtc_get_time = marvel_get_rtc_time,
+ .rtc_set_time = marvel_set_rtc_time,
DO_MARVEL_IO,
.machine_check = marvel_machine_check,
.max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index 910b43cd63e8..61ccd95579ec 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -219,7 +219,7 @@ miata_swizzle(struct pci_dev *dev, u8 *pinp)
slot = PCI_SLOT(dev->devfn) + 9;
break;
}
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ pin = pci_swizzle_interrupt_pin(dev, pin);
/* Move up the chain of bridges. */
dev = dev->bus->self;
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index a7f23b5ab814..99c0f46f6b9c 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -245,6 +245,10 @@ nautilus_init_pci(void)
IRONGATE0->pci_mem = pci_mem;
pci_bus_assign_resources(bus);
+
+ /* pci_common_swizzle() relies on bus->self being NULL
+ for the root bus, so just clear it. */
+ bus->self = NULL;
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
}
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index eb2a1d63f484..538876b62449 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -257,7 +257,7 @@ noritake_swizzle(struct pci_dev *dev, u8 *pinp)
slot = PCI_SLOT(dev->devfn) + 15;
break;
}
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+ pin = pci_swizzle_interrupt_pin(dev, pin);
/* Move up the chain of bridges. */
dev = dev->bus->self;
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 5b99cf3cd69c..f15a329b6011 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -160,7 +160,7 @@ ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
slot = PCI_SLOT(dev->devfn) + 10;
break;
}
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ pin = pci_swizzle_interrupt_pin(dev, pin);
/* Move up the chain of bridges. */
dev = dev->bus->self;
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
index a4555f497639..d232e42be018 100644
--- a/arch/alpha/kernel/sys_sable.c
+++ b/arch/alpha/kernel/sys_sable.c
@@ -425,7 +425,7 @@ lynx_swizzle(struct pci_dev *dev, u8 *pinp)
slot = PCI_SLOT(dev->devfn) + 11;
break;
}
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+ pin = pci_swizzle_interrupt_pin(dev, pin);
/* Move up the chain of bridges. */
dev = dev->bus->self;
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
index 52c91ccc1648..27f840a4ad3d 100644
--- a/arch/alpha/kernel/sys_titan.c
+++ b/arch/alpha/kernel/sys_titan.c
@@ -158,10 +158,10 @@ titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
}
static void
-titan_set_irq_affinity(unsigned int irq, cpumask_t affinity)
+titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
{
spin_lock(&titan_irq_lock);
- titan_cpu_set_irq_affinity(irq - 16, affinity);
+ titan_cpu_set_irq_affinity(irq - 16, *affinity);
titan_update_irq_hw(titan_cached_irq_mask);
spin_unlock(&titan_irq_lock);
}
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index ba914af18c4f..95c9aef1c106 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -17,7 +17,7 @@ sys_call_table:
.quad sys_write
.quad alpha_ni_syscall /* 5 */
.quad sys_close
- .quad osf_wait4
+ .quad sys_osf_wait4
.quad alpha_ni_syscall
.quad sys_link
.quad sys_unlink /* 10 */
@@ -27,11 +27,11 @@ sys_call_table:
.quad sys_mknod
.quad sys_chmod /* 15 */
.quad sys_chown
- .quad osf_brk
+ .quad sys_osf_brk
.quad alpha_ni_syscall
.quad sys_lseek
.quad sys_getxpid /* 20 */
- .quad osf_mount
+ .quad sys_osf_mount
.quad sys_umount
.quad sys_setuid
.quad sys_getxuid
@@ -52,8 +52,8 @@ sys_call_table:
.quad sys_setpgid
.quad alpha_ni_syscall /* 40 */
.quad sys_dup
- .quad sys_pipe
- .quad osf_set_program_attributes
+ .quad sys_alpha_pipe
+ .quad sys_osf_set_program_attributes
.quad alpha_ni_syscall
.quad sys_open /* 45 */
.quad alpha_ni_syscall
@@ -81,7 +81,7 @@ sys_call_table:
.quad sys_newlstat
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 70 */
- .quad osf_mmap
+ .quad sys_osf_mmap
.quad alpha_ni_syscall
.quad sys_munmap
.quad sys_mprotect
@@ -94,17 +94,17 @@ sys_call_table:
.quad sys_setgroups /* 80 */
.quad alpha_ni_syscall
.quad sys_setpgid
- .quad osf_setitimer
+ .quad sys_osf_setitimer
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 85 */
- .quad osf_getitimer
+ .quad sys_osf_getitimer
.quad sys_gethostname
.quad sys_sethostname
.quad sys_getdtablesize
.quad sys_dup2 /* 90 */
.quad sys_newfstat
.quad sys_fcntl
- .quad osf_select
+ .quad sys_osf_select
.quad sys_poll
.quad sys_fsync /* 95 */
.quad sys_setpriority
@@ -123,22 +123,22 @@ sys_call_table:
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 110 */
.quad sys_sigsuspend
- .quad osf_sigstack
+ .quad sys_osf_sigstack
.quad sys_recvmsg
.quad sys_sendmsg
.quad alpha_ni_syscall /* 115 */
- .quad osf_gettimeofday
- .quad osf_getrusage
+ .quad sys_osf_gettimeofday
+ .quad sys_osf_getrusage
.quad sys_getsockopt
.quad alpha_ni_syscall
#ifdef CONFIG_OSF4_COMPAT
- .quad osf_readv /* 120 */
- .quad osf_writev
+ .quad sys_osf_readv /* 120 */
+ .quad sys_osf_writev
#else
.quad sys_readv /* 120 */
.quad sys_writev
#endif
- .quad osf_settimeofday
+ .quad sys_osf_settimeofday
.quad sys_fchown
.quad sys_fchmod
.quad sys_recvfrom /* 125 */
@@ -154,7 +154,7 @@ sys_call_table:
.quad sys_socketpair /* 135 */
.quad sys_mkdir
.quad sys_rmdir
- .quad osf_utimes
+ .quad sys_osf_utimes
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 140 */
.quad sys_getpeername
@@ -172,16 +172,16 @@ sys_call_table:
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 155 */
- .quad osf_sigaction
+ .quad sys_osf_sigaction
.quad alpha_ni_syscall
.quad alpha_ni_syscall
- .quad osf_getdirentries
- .quad osf_statfs /* 160 */
- .quad osf_fstatfs
+ .quad sys_osf_getdirentries
+ .quad sys_osf_statfs /* 160 */
+ .quad sys_osf_fstatfs
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
- .quad osf_getdomainname /* 165 */
+ .quad sys_osf_getdomainname /* 165 */
.quad sys_setdomainname
.quad alpha_ni_syscall
.quad alpha_ni_syscall
@@ -224,7 +224,7 @@ sys_call_table:
.quad sys_semctl
.quad sys_semget /* 205 */
.quad sys_semop
- .quad osf_utsname
+ .quad sys_osf_utsname
.quad sys_lchown
.quad sys_shmat
.quad sys_shmctl /* 210 */
@@ -258,23 +258,23 @@ sys_call_table:
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 240 */
- .quad osf_sysinfo
+ .quad sys_osf_sysinfo
.quad alpha_ni_syscall
.quad alpha_ni_syscall
- .quad osf_proplist_syscall
+ .quad sys_osf_proplist_syscall
.quad alpha_ni_syscall /* 245 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 250 */
- .quad osf_usleep_thread
+ .quad sys_osf_usleep_thread
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad sys_sysfs
.quad alpha_ni_syscall /* 255 */
- .quad osf_getsysinfo
- .quad osf_setsysinfo
+ .quad sys_osf_getsysinfo
+ .quad sys_osf_setsysinfo
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 260 */
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index e6a231435cba..b04e2cbf23a4 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -46,6 +46,7 @@
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/8253pit.h>
+#include <asm/rtc.h>
#include <linux/mc146818rtc.h>
#include <linux/time.h>
@@ -180,6 +181,15 @@ common_init_rtc(void)
init_rtc_irq();
}
+unsigned int common_get_rtc_time(struct rtc_time *time)
+{
+ return __get_rtc_time(time);
+}
+
+int common_set_rtc_time(struct rtc_time *time)
+{
+ return __set_rtc_time(time);
+}
/* Validate a computed cycle counter result against the known bounds for
the given processor core. There's too much brokenness in the way of
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 234e42b8ee74..5d7a16eab312 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -59,13 +59,6 @@ pgd_alloc(struct mm_struct *mm)
return ret;
}
-pte_t *
-pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
- return pte;
-}
-
/*
* BAD_PAGE is the page that is used for page faults when linux
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d6ebe39934b5..dbfdf87f993f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1325,6 +1325,8 @@ source "drivers/regulator/Kconfig"
source "drivers/uio/Kconfig"
+source "drivers/staging/Kconfig"
+
endmenu
source "fs/Kconfig"
diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c
index 17a17b49a45b..1037bba18329 100644
--- a/arch/arm/common/clkdev.c
+++ b/arch/arm/common/clkdev.c
@@ -24,6 +24,15 @@
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
+/*
+ * Find the correct struct clk for the device and connection ID.
+ * We do slightly fuzzy matching here:
+ * An entry with a NULL ID is assumed to be a wildcard.
+ * If an entry has a device ID, it must match
+ * If an entry has a connection ID, it must match
+ * Then we take the most specific entry - with the following
+ * order of precidence: dev+con > dev only > con only.
+ */
static struct clk *clk_find(const char *dev_id, const char *con_id)
{
struct clk_lookup *p;
@@ -31,13 +40,17 @@ static struct clk *clk_find(const char *dev_id, const char *con_id)
int match, best = 0;
list_for_each_entry(p, &clocks, node) {
- if ((p->dev_id && !dev_id) || (p->con_id && !con_id))
- continue;
match = 0;
- if (p->dev_id)
- match += 2 * (strcmp(p->dev_id, dev_id) == 0);
- if (p->con_id)
- match += 1 * (strcmp(p->con_id, con_id) == 0);
+ if (p->dev_id) {
+ if (!dev_id || strcmp(p->dev_id, dev_id))
+ continue;
+ match += 2;
+ }
+ if (p->con_id) {
+ if (!con_id || strcmp(p->con_id, con_id))
+ continue;
+ match += 1;
+ }
if (match == 0)
continue;
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 7fc9860a97d7..c6884ba1d5ed 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -109,11 +109,11 @@ static void gic_unmask_irq(unsigned int irq)
}
#ifdef CONFIG_SMP
-static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
+static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
{
void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
unsigned int shift = (irq % 4) * 8;
- unsigned int cpu = first_cpu(mask_val);
+ unsigned int cpu = cpumask_first(mask_val);
u32 val;
spin_lock(&irq_controller_lock);
diff --git a/arch/arm/configs/afeb9260_defconfig b/arch/arm/configs/afeb9260_defconfig
index ce909586a34f..f7a272cb3da0 100644
--- a/arch/arm/configs/afeb9260_defconfig
+++ b/arch/arm/configs/afeb9260_defconfig
@@ -719,8 +719,8 @@ CONFIG_I2C_GPIO=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_AT24=y
-# CONFIG_SENSORS_EEPROM is not set
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -744,7 +744,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/ams_delta_defconfig b/arch/arm/configs/ams_delta_defconfig
index 2c4aa11f0b0d..764732529ea3 100644
--- a/arch/arm/configs/ams_delta_defconfig
+++ b/arch/arm/configs/ams_delta_defconfig
@@ -767,7 +767,7 @@ CONFIG_I2C_OMAP=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/at91cap9adk_defconfig b/arch/arm/configs/at91cap9adk_defconfig
index bf97801a1068..bc6bd9f6174d 100644
--- a/arch/arm/configs/at91cap9adk_defconfig
+++ b/arch/arm/configs/at91cap9adk_defconfig
@@ -676,7 +676,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -703,7 +703,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig
index 868fb7b9530b..238b218394e3 100644
--- a/arch/arm/configs/at91rm9200dk_defconfig
+++ b/arch/arm/configs/at91rm9200dk_defconfig
@@ -636,7 +636,7 @@ CONFIG_I2C_GPIO=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig
index de43fc675616..9f7a99ace514 100644
--- a/arch/arm/configs/at91rm9200ek_defconfig
+++ b/arch/arm/configs/at91rm9200ek_defconfig
@@ -610,7 +610,7 @@ CONFIG_I2C_GPIO=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
index 38e6a0abeb4e..e0ee7060f9aa 100644
--- a/arch/arm/configs/at91sam9260ek_defconfig
+++ b/arch/arm/configs/at91sam9260ek_defconfig
@@ -582,7 +582,7 @@ CONFIG_I2C_GPIO=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
index 93b779f94b41..01d1ef97d8be 100644
--- a/arch/arm/configs/at91sam9261ek_defconfig
+++ b/arch/arm/configs/at91sam9261ek_defconfig
@@ -660,7 +660,7 @@ CONFIG_I2C_GPIO=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -687,7 +687,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
index a7ddd94363ca..036a126725c1 100644
--- a/arch/arm/configs/at91sam9263ek_defconfig
+++ b/arch/arm/configs/at91sam9263ek_defconfig
@@ -670,7 +670,7 @@ CONFIG_I2C_GPIO=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -697,7 +697,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig
index df0d6ee672b3..7e018a04c31b 100644
--- a/arch/arm/configs/at91sam9g20ek_defconfig
+++ b/arch/arm/configs/at91sam9g20ek_defconfig
@@ -665,7 +665,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig
index 811bebbdc784..237a2a6a8517 100644
--- a/arch/arm/configs/at91sam9rlek_defconfig
+++ b/arch/arm/configs/at91sam9rlek_defconfig
@@ -566,7 +566,7 @@ CONFIG_I2C_GPIO=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -593,7 +593,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
index 85c80f723d8e..a19e824cf7f8 100644
--- a/arch/arm/configs/ateb9200_defconfig
+++ b/arch/arm/configs/ateb9200_defconfig
@@ -723,7 +723,7 @@ CONFIG_I2C_GPIO=m
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
index b2bbf217c707..80222feb7dad 100644
--- a/arch/arm/configs/badge4_defconfig
+++ b/arch/arm/configs/badge4_defconfig
@@ -750,7 +750,7 @@ CONFIG_I2C_ELEKTOR=m
# Other I2C Chip support
#
# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
diff --git a/arch/arm/configs/cam60_defconfig b/arch/arm/configs/cam60_defconfig
index f945105d6cd6..8448108347cf 100644
--- a/arch/arm/configs/cam60_defconfig
+++ b/arch/arm/configs/cam60_defconfig
@@ -722,7 +722,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -749,7 +749,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/clps7500_defconfig b/arch/arm/configs/clps7500_defconfig
deleted file mode 100644
index 49e9f9d8b3d1..000000000000
--- a/arch/arm/configs/clps7500_defconfig
+++ /dev/null
@@ -1,801 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 17:20:48 2005
-#
-CONFIG_ARM=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# System Type
-#
-CONFIG_ARCH_CLPS7500=y
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_IOP3XX is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_ARM710=y
-CONFIG_CPU_32v3=y
-CONFIG_CPU_CACHE_V3=y
-CONFIG_CPU_CACHE_VIVT=y
-CONFIG_CPU_COPY_V3=y
-CONFIG_CPU_TLB_V3=y
-
-#
-# Processor Features
-#
-CONFIG_TIMER_ACORN=y
-
-#
-# Bus support
-#
-CONFIG_ISA=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-# CONFIG_PREEMPT is not set
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=16M root=nfs"
-# CONFIG_XIP_KERNEL is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-# CONFIG_FPE_NWFPE is not set
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_ARTHUR is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_PARTITIONS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-# CONFIG_MTD_BLOCK is not set
-# CONFIG_MTD_BLOCK_RO is not set
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# Parallel port support
-#
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_ARC is not set
-# CONFIG_PARPORT_GSC is not set
-CONFIG_PARPORT_1284=y
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_SMC91X is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-CONFIG_NET_PCI=y
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
-CONFIG_CS89x0=y
-# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_PLIP is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-# CONFIG_PPPOE is not set
-CONFIG_SLIP=y
-CONFIG_SLIP_COMPRESSED=y
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_PARKBD is not set
-CONFIG_SERIO_RPCKBD=y
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=y
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-CONFIG_I2C=y
-# CONFIG_I2C_CHARDEV is not set
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ELEKTOR is not set
-# CONFIG_I2C_PARPORT is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-
-#
-# Other I2C Chip support
-#
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 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
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-CONFIG_FB_SOFT_CURSOR=y
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-CONFIG_FB_ACORN=y
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
-# CONFIG_XFS_FS is not set
-CONFIG_MINIX_FS=y
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_DEBUG_USER is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index 46f1c9dc350c..227da0843ead 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -763,8 +763,8 @@ CONFIG_I2C_PXA=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/colibri_defconfig b/arch/arm/configs/colibri_defconfig
index c3e3418ed4fe..744086fff414 100644
--- a/arch/arm/configs/colibri_defconfig
+++ b/arch/arm/configs/colibri_defconfig
@@ -801,7 +801,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 98765438048d..d6cd165e9310 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -982,8 +982,8 @@ CONFIG_I2C_PXA=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -1008,7 +1008,7 @@ CONFIG_SPI_PXA2XX=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
index 67e65e4f0cdc..29f68c2effe6 100644
--- a/arch/arm/configs/csb337_defconfig
+++ b/arch/arm/configs/csb337_defconfig
@@ -679,7 +679,7 @@ CONFIG_I2C_GPIO=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
index 99702146c9fc..f7b60ceed6c7 100644
--- a/arch/arm/configs/csb637_defconfig
+++ b/arch/arm/configs/csb637_defconfig
@@ -704,7 +704,7 @@ CONFIG_I2C_CHARDEV=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/ecbat91_defconfig b/arch/arm/configs/ecbat91_defconfig
index cfeb817ad21a..ca520733bdb0 100644
--- a/arch/arm/configs/ecbat91_defconfig
+++ b/arch/arm/configs/ecbat91_defconfig
@@ -721,7 +721,7 @@ CONFIG_I2C_GPIO=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -747,7 +747,7 @@ CONFIG_SPI_AT91=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
#
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 21aa013793c6..3f89d5f25bce 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -681,7 +681,7 @@ CONFIG_I2C_ALGOBIT=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/ezx_defconfig b/arch/arm/configs/ezx_defconfig
index 2a84d557adc2..d5ee16e6abf3 100644
--- a/arch/arm/configs/ezx_defconfig
+++ b/arch/arm/configs/ezx_defconfig
@@ -877,7 +877,7 @@ CONFIG_I2C_PXA=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -900,7 +900,7 @@ CONFIG_SPI_PXA2XX=m
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_HAVE_GPIO_LIB=y
diff --git a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig
index 299dc22294a0..6ace512fa101 100644
--- a/arch/arm/configs/footbridge_defconfig
+++ b/arch/arm/configs/footbridge_defconfig
@@ -801,7 +801,7 @@ CONFIG_I2C=m
#
# Other I2C Chip support
#
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
diff --git a/arch/arm/configs/iop13xx_defconfig b/arch/arm/configs/iop13xx_defconfig
index 482e57061053..89c17761726b 100644
--- a/arch/arm/configs/iop13xx_defconfig
+++ b/arch/arm/configs/iop13xx_defconfig
@@ -744,7 +744,7 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/iop32x_defconfig b/arch/arm/configs/iop32x_defconfig
index 8612f58e1056..d70177b38f5f 100644
--- a/arch/arm/configs/iop32x_defconfig
+++ b/arch/arm/configs/iop32x_defconfig
@@ -847,7 +847,7 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/iop33x_defconfig b/arch/arm/configs/iop33x_defconfig
index 8b0098d19d08..eec488298267 100644
--- a/arch/arm/configs/iop33x_defconfig
+++ b/arch/arm/configs/iop33x_defconfig
@@ -746,7 +746,7 @@ CONFIG_I2C_IOP3XX=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/ixp2000_defconfig b/arch/arm/configs/ixp2000_defconfig
index 84680db6c615..57526c15e854 100644
--- a/arch/arm/configs/ixp2000_defconfig
+++ b/arch/arm/configs/ixp2000_defconfig
@@ -768,7 +768,7 @@ CONFIG_I2C_IXP2000=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig
index 4a2f7b2372db..ef97561ed75b 100644
--- a/arch/arm/configs/ixp23xx_defconfig
+++ b/arch/arm/configs/ixp23xx_defconfig
@@ -900,7 +900,7 @@ CONFIG_I2C_ALGOBIT=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index fc14932e3abd..95cd8dfb5f1e 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -1083,7 +1083,7 @@ CONFIG_I2C_IXP4XX=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
index 6dd95a2c8d5d..9f92fc527f59 100644
--- a/arch/arm/configs/kafa_defconfig
+++ b/arch/arm/configs/kafa_defconfig
@@ -603,7 +603,7 @@ CONFIG_I2C_GPIO=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index ab8b1e0d0dac..4bc38078d580 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -905,8 +905,8 @@ CONFIG_I2C_MV64XXX=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -930,7 +930,7 @@ CONFIG_SPI_ORION=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/loki_defconfig b/arch/arm/configs/loki_defconfig
index 17da7c3b3d53..b720fcffbcd4 100644
--- a/arch/arm/configs/loki_defconfig
+++ b/arch/arm/configs/loki_defconfig
@@ -654,7 +654,7 @@ CONFIG_I2C_MV64XXX=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -675,7 +675,7 @@ CONFIG_SPI_MASTER=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/magician_defconfig b/arch/arm/configs/magician_defconfig
index 4d11678584db..73ba62b71063 100644
--- a/arch/arm/configs/magician_defconfig
+++ b/arch/arm/configs/magician_defconfig
@@ -678,7 +678,7 @@ CONFIG_I2C_PXA=m
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/msm_defconfig b/arch/arm/configs/msm_defconfig
index 3b4ecf2a90dd..cc3b06ee24f9 100644
--- a/arch/arm/configs/msm_defconfig
+++ b/arch/arm/configs/msm_defconfig
@@ -580,7 +580,7 @@ CONFIG_I2C_MSM=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
CONFIG_SENSORS_PCA9633=y
diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig
index d38ebf8721a4..83c817f31bcc 100644
--- a/arch/arm/configs/mv78xx0_defconfig
+++ b/arch/arm/configs/mv78xx0_defconfig
@@ -832,7 +832,7 @@ CONFIG_I2C_MV64XXX=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/n770_defconfig b/arch/arm/configs/n770_defconfig
index 568ef1770d5f..672f6db06a52 100644
--- a/arch/arm/configs/n770_defconfig
+++ b/arch/arm/configs/n770_defconfig
@@ -767,7 +767,7 @@ CONFIG_I2C_OMAP=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -798,7 +798,7 @@ CONFIG_SPI_OMAP_UWIRE=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_TSC2101 is not set
# CONFIG_SPI_TSC2102 is not set
# CONFIG_SPI_TSC210X is not set
diff --git a/arch/arm/configs/neocore926_defconfig b/arch/arm/configs/neocore926_defconfig
index 325f1e105f69..e0e4e98b5aa2 100644
--- a/arch/arm/configs/neocore926_defconfig
+++ b/arch/arm/configs/neocore926_defconfig
@@ -774,8 +774,8 @@ CONFIG_I2C_CHARDEV=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -798,7 +798,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
index 92ccdc6492f7..d81ea219c934 100644
--- a/arch/arm/configs/neponset_defconfig
+++ b/arch/arm/configs/neponset_defconfig
@@ -737,7 +737,7 @@ CONFIG_I2C_ALGOBIT=y
#
# Other I2C Chip support
#
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
diff --git a/arch/arm/configs/omap3_beagle_defconfig b/arch/arm/configs/omap3_beagle_defconfig
index e042d27eae16..4c6fb7e959df 100644
--- a/arch/arm/configs/omap3_beagle_defconfig
+++ b/arch/arm/configs/omap3_beagle_defconfig
@@ -687,8 +687,8 @@ CONFIG_I2C_OMAP=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/arm/configs/omap3_pandora_defconfig b/arch/arm/configs/omap3_pandora_defconfig
index 09543f4de5bc..b54ad2e2da36 100644
--- a/arch/arm/configs/omap3_pandora_defconfig
+++ b/arch/arm/configs/omap3_pandora_defconfig
@@ -713,8 +713,8 @@ CONFIG_I2C_OMAP=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -740,7 +740,7 @@ CONFIG_SPI_OMAP24XX=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/arm/configs/omap_2430sdp_defconfig b/arch/arm/configs/omap_2430sdp_defconfig
index b0617c0da2a1..640e9afc4630 100644
--- a/arch/arm/configs/omap_2430sdp_defconfig
+++ b/arch/arm/configs/omap_2430sdp_defconfig
@@ -710,7 +710,7 @@ CONFIG_I2C_OMAP=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -743,7 +743,7 @@ CONFIG_SPI_MASTER=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_TSC2101 is not set
# CONFIG_SPI_TSC2102 is not set
# CONFIG_SPI_TSC210X is not set
diff --git a/arch/arm/configs/omap_apollon_2420_defconfig b/arch/arm/configs/omap_apollon_2420_defconfig
index bb39dfc72d69..ac7adf34c54a 100644
--- a/arch/arm/configs/omap_apollon_2420_defconfig
+++ b/arch/arm/configs/omap_apollon_2420_defconfig
@@ -612,7 +612,7 @@ CONFIG_SPI_OMAP24XX=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_TSC2101 is not set
# CONFIG_SPI_TSC2102 is not set
# CONFIG_SPI_TSC210X is not set
diff --git a/arch/arm/configs/omap_generic_1510_defconfig b/arch/arm/configs/omap_generic_1510_defconfig
index 4b1c252f2091..ccdc661b5856 100644
--- a/arch/arm/configs/omap_generic_1510_defconfig
+++ b/arch/arm/configs/omap_generic_1510_defconfig
@@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/omap_generic_1610_defconfig b/arch/arm/configs/omap_generic_1610_defconfig
index fc66f019d56c..0c42c8955047 100644
--- a/arch/arm/configs/omap_generic_1610_defconfig
+++ b/arch/arm/configs/omap_generic_1610_defconfig
@@ -641,7 +641,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/omap_h2_1610_defconfig b/arch/arm/configs/omap_h2_1610_defconfig
index c03507202f3c..74dbdc644d32 100644
--- a/arch/arm/configs/omap_h2_1610_defconfig
+++ b/arch/arm/configs/omap_h2_1610_defconfig
@@ -700,7 +700,7 @@ CONFIG_I2C_OMAP=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -731,7 +731,7 @@ CONFIG_SPI_OMAP_UWIRE=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_TSC2101=y
# CONFIG_SPI_TSC2102 is not set
# CONFIG_SPI_TSC210X is not set
diff --git a/arch/arm/configs/omap_h4_2420_defconfig b/arch/arm/configs/omap_h4_2420_defconfig
index 5bc89185a64f..a4aab8e4c29b 100644
--- a/arch/arm/configs/omap_h4_2420_defconfig
+++ b/arch/arm/configs/omap_h4_2420_defconfig
@@ -681,7 +681,7 @@ CONFIG_I2C_OMAP=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/omap_innovator_1510_defconfig b/arch/arm/configs/omap_innovator_1510_defconfig
index 55b2611bd90a..0cfe363e3365 100644
--- a/arch/arm/configs/omap_innovator_1510_defconfig
+++ b/arch/arm/configs/omap_innovator_1510_defconfig
@@ -631,7 +631,7 @@ CONFIG_I2C_BOARDINFO=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/omap_ldp_defconfig b/arch/arm/configs/omap_ldp_defconfig
index b77d054169ee..aa9d34feddc6 100644
--- a/arch/arm/configs/omap_ldp_defconfig
+++ b/arch/arm/configs/omap_ldp_defconfig
@@ -629,8 +629,8 @@ CONFIG_I2C_OMAP=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -656,7 +656,7 @@ CONFIG_SPI_OMAP24XX=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/arm/configs/omap_osk_5912_defconfig b/arch/arm/configs/omap_osk_5912_defconfig
index b68e0144cab5..6b3b5c610da0 100644
--- a/arch/arm/configs/omap_osk_5912_defconfig
+++ b/arch/arm/configs/omap_osk_5912_defconfig
@@ -711,7 +711,7 @@ CONFIG_I2C_OMAP=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig
index 418ca2febbe3..f8701fadb600 100644
--- a/arch/arm/configs/onearm_defconfig
+++ b/arch/arm/configs/onearm_defconfig
@@ -698,7 +698,7 @@ CONFIG_I2C_CHARDEV=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
index b2456ca544c9..a8ee6984a09e 100644
--- a/arch/arm/configs/orion5x_defconfig
+++ b/arch/arm/configs/orion5x_defconfig
@@ -886,8 +886,8 @@ CONFIG_I2C_MV64XXX=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/arm/configs/overo_defconfig b/arch/arm/configs/overo_defconfig
index 49200967a153..a57f9e4124fa 100644
--- a/arch/arm/configs/overo_defconfig
+++ b/arch/arm/configs/overo_defconfig
@@ -858,8 +858,8 @@ CONFIG_I2C_OMAP=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -885,7 +885,7 @@ CONFIG_SPI_OMAP24XX=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/arm/configs/palmz71_defconfig b/arch/arm/configs/palmz71_defconfig
index 6361922e71c1..08e14068fff7 100644
--- a/arch/arm/configs/palmz71_defconfig
+++ b/arch/arm/configs/palmz71_defconfig
@@ -554,7 +554,7 @@ CONFIG_SPI_OMAP_UWIRE=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_TSC2101 is not set
# CONFIG_SPI_TSC2102 is not set
# CONFIG_SPI_TSC210X is not set
diff --git a/arch/arm/configs/palmz72_defconfig b/arch/arm/configs/palmz72_defconfig
index 3245f8f33e0a..a0dc37c05dea 100644
--- a/arch/arm/configs/palmz72_defconfig
+++ b/arch/arm/configs/palmz72_defconfig
@@ -527,8 +527,8 @@ CONFIG_I2C_PXA=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -552,7 +552,7 @@ CONFIG_SPI_MASTER=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 17b9b2469570..05ad96a43b1d 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -606,7 +606,7 @@ CONFIG_I2C_PXA=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/pcm038_defconfig b/arch/arm/configs/pcm038_defconfig
index 6b798c215ca8..41429a00f58c 100644
--- a/arch/arm/configs/pcm038_defconfig
+++ b/arch/arm/configs/pcm038_defconfig
@@ -604,7 +604,7 @@ CONFIG_I2C_BOARDINFO=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -626,7 +626,7 @@ CONFIG_SPI_BITBANG=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_HAVE_GPIO_LIB=y
diff --git a/arch/arm/configs/picotux200_defconfig b/arch/arm/configs/picotux200_defconfig
index 59e4463c2da2..9018f0f298aa 100644
--- a/arch/arm/configs/picotux200_defconfig
+++ b/arch/arm/configs/picotux200_defconfig
@@ -744,7 +744,7 @@ CONFIG_I2C_GPIO=m
#
CONFIG_SENSORS_DS1337=m
CONFIG_SENSORS_DS1374=m
-CONFIG_SENSORS_EEPROM=m
+CONFIG_EEPROM_LEGACY=m
CONFIG_SENSORS_PCF8574=m
CONFIG_SENSORS_PCA9539=m
CONFIG_SENSORS_PCF8591=m
diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig
index 811b8f60d19d..67b5f1e15f4a 100644
--- a/arch/arm/configs/pnx4008_defconfig
+++ b/arch/arm/configs/pnx4008_defconfig
@@ -915,7 +915,7 @@ CONFIG_I2C_ALGOPCA=m
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=m
+CONFIG_EEPROM_LEGACY=m
CONFIG_SENSORS_PCF8574=m
# CONFIG_SENSORS_PCA9539 is not set
CONFIG_SENSORS_PCF8591=m
diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig
index 5cbd81589647..cd1d717903ac 100644
--- a/arch/arm/configs/qil-a9260_defconfig
+++ b/arch/arm/configs/qil-a9260_defconfig
@@ -687,7 +687,7 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -714,7 +714,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/rpc_defconfig b/arch/arm/configs/rpc_defconfig
index f62d1817d2c6..a29d61fe4c6a 100644
--- a/arch/arm/configs/rpc_defconfig
+++ b/arch/arm/configs/rpc_defconfig
@@ -590,7 +590,7 @@ CONFIG_I2C_ACORN=y
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 35faaea8623e..65a583ee5df8 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -923,7 +923,7 @@ CONFIG_I2C_SIMTEC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_SENSORS_EEPROM=m
+CONFIG_EEPROM_LEGACY=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -950,7 +950,7 @@ CONFIG_SPI_S3C24XX_GPIO=m
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_HAVE_GPIO_LIB=y
diff --git a/arch/arm/configs/s3c6400_defconfig b/arch/arm/configs/s3c6400_defconfig
index cf3c1b5d7048..2e8fa50e9a09 100644
--- a/arch/arm/configs/s3c6400_defconfig
+++ b/arch/arm/configs/s3c6400_defconfig
@@ -465,8 +465,8 @@ CONFIG_I2C_S3C2410=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_AT24=y
-# CONFIG_SENSORS_EEPROM is not set
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 4df5b4db2aa0..745c68ffb885 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -977,8 +977,8 @@ CONFIG_I2C_PXA=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -1003,7 +1003,7 @@ CONFIG_SPI_PXA2XX=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/arm/configs/sx1_defconfig b/arch/arm/configs/sx1_defconfig
index 853dcdd9f2e0..25b007ff8bab 100644
--- a/arch/arm/configs/sx1_defconfig
+++ b/arch/arm/configs/sx1_defconfig
@@ -610,7 +610,7 @@ CONFIG_I2C_OMAP=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 9033d147f052..b6f838197816 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -948,7 +948,7 @@ CONFIG_I2C_PXA_SLAVE=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/usb-a9260_defconfig b/arch/arm/configs/usb-a9260_defconfig
index fcb4aaabd439..fd7774033d64 100644
--- a/arch/arm/configs/usb-a9260_defconfig
+++ b/arch/arm/configs/usb-a9260_defconfig
@@ -676,7 +676,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/usb-a9263_defconfig b/arch/arm/configs/usb-a9263_defconfig
index b786e0407e8e..e7c19dd92557 100644
--- a/arch/arm/configs/usb-a9263_defconfig
+++ b/arch/arm/configs/usb-a9263_defconfig
@@ -668,7 +668,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig
index 8355f88f7292..b11c5da3996c 100644
--- a/arch/arm/configs/versatile_defconfig
+++ b/arch/arm/configs/versatile_defconfig
@@ -611,7 +611,7 @@ CONFIG_I2C_ALGOBIT=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_EEPROM=m
+CONFIG_EEPROM_LEGACY=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d01fecb8673e..30f463d2fa8a 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -860,8 +860,8 @@ CONFIG_I2C_PXA=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/arm/configs/xm_x2xx_defconfig b/arch/arm/configs/xm_x2xx_defconfig
index f891364deceb..1039f366bf8d 100644
--- a/arch/arm/configs/xm_x2xx_defconfig
+++ b/arch/arm/configs/xm_x2xx_defconfig
@@ -1009,8 +1009,8 @@ CONFIG_I2C_PXA=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/arm/configs/yl9200_defconfig b/arch/arm/configs/yl9200_defconfig
index a9f41c24c9dc..9192e5977674 100644
--- a/arch/arm/configs/yl9200_defconfig
+++ b/arch/arm/configs/yl9200_defconfig
@@ -682,7 +682,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h
index 325f881ccb50..ee99723b3a6c 100644
--- a/arch/arm/include/asm/atomic.h
+++ b/arch/arm/include/asm/atomic.h
@@ -12,10 +12,9 @@
#define __ASM_ARM_ATOMIC_H
#include <linux/compiler.h>
+#include <linux/types.h>
#include <asm/system.h>
-typedef struct { volatile int counter; } atomic_t;
-
#define ATOMIC_INIT(i) { (i) }
#ifdef __KERNEL__
diff --git a/arch/arm/include/asm/byteorder.h b/arch/arm/include/asm/byteorder.h
index 4fbfb22f65a0..77379748b171 100644
--- a/arch/arm/include/asm/byteorder.h
+++ b/arch/arm/include/asm/byteorder.h
@@ -15,39 +15,6 @@
#ifndef __ASM_ARM_BYTEORDER_H
#define __ASM_ARM_BYTEORDER_H
-#include <linux/compiler.h>
-#include <asm/types.h>
-
-static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
-{
- __u32 t;
-
-#ifndef __thumb__
- if (!__builtin_constant_p(x)) {
- /*
- * The compiler needs a bit of a hint here to always do the
- * right thing and not screw it up to different degrees
- * depending on the gcc version.
- */
- asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
- } else
-#endif
- t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */
-
- x = (x << 24) | (x >> 8); /* mov r0,r0,ror #8 */
- t &= ~0x00FF0000; /* bic r1,r1,#0x00FF0000 */
- x ^= (t >> 8); /* eor r0,r0,r1,lsr #8 */
-
- return x;
-}
-
-#define __arch__swab32(x) ___arch__swab32(x)
-
-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
-
#ifdef __ARMEB__
#include <linux/byteorder/big_endian.h>
#else
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 32da1ae17e06..a38bdc7afa34 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -42,7 +42,7 @@ struct pci_sys_data {
/*
* This is the standard PCI-PCI bridge swizzling algorithm.
*/
-u8 pci_std_swizzle(struct pci_dev *dev, u8 *pinp);
+#define pci_std_swizzle pci_common_swizzle
/*
* Call this with your hw_pci struct to initialise the PCI system.
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index 53099d4ee421..b561584d04a1 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -24,7 +24,6 @@ typedef struct {
* modified for 2.6 by Hyok S. Choi <hyok.choi@samsung.com>
*/
typedef struct {
- struct vm_list_struct *vmlist;
unsigned long end_brk;
} mm_context_t;
diff --git a/arch/arm/include/asm/swab.h b/arch/arm/include/asm/swab.h
new file mode 100644
index 000000000000..27a689be0856
--- /dev/null
+++ b/arch/arm/include/asm/swab.h
@@ -0,0 +1,50 @@
+/*
+ * arch/arm/include/asm/byteorder.h
+ *
+ * ARM Endian-ness. In little endian mode, the data bus is connected such
+ * that byte accesses appear as:
+ * 0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
+ * and word accesses (data or instruction) appear as:
+ * d0...d31
+ *
+ * When in big endian mode, byte accesses appear as:
+ * 0 = d24...d31, 1 = d16...d23, 2 = d8...d15, 3 = d0...d7
+ * and word accesses (data or instruction) appear as:
+ * d0...d31
+ */
+#ifndef __ASM_ARM_SWAB_H
+#define __ASM_ARM_SWAB_H
+
+#include <linux/compiler.h>
+#include <asm/types.h>
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __SWAB_64_THRU_32__
+#endif
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+ __u32 t;
+
+#ifndef __thumb__
+ if (!__builtin_constant_p(x)) {
+ /*
+ * The compiler needs a bit of a hint here to always do the
+ * right thing and not screw it up to different degrees
+ * depending on the gcc version.
+ */
+ asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
+ } else
+#endif
+ t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */
+
+ x = (x << 24) | (x >> 8); /* mov r0,r0,ror #8 */
+ t &= ~0x00FF0000; /* bic r1,r1,#0x00FF0000 */
+ x ^= (t >> 8); /* eor r0,r0,r1,lsr #8 */
+
+ return x;
+}
+#define __arch_swab32 __arch_swab32
+
+#endif
+
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 17a59b6e521f..809681900ec8 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -480,33 +480,6 @@ EXPORT_SYMBOL(pcibios_bus_to_resource);
#endif
/*
- * This is the standard PCI-PCI bridge swizzling algorithm:
- *
- * Dev: 0 1 2 3
- * A A B C D
- * B B C D A
- * C C D A B
- * D D A B C
- * ^^^^^^^^^^ irq pin on bridge
- */
-u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp)
-{
- int pin = *pinp - 1;
-
- while (dev->bus->self) {
- pin = (pin + PCI_SLOT(dev->devfn)) & 3;
- /*
- * move up the chain of bridges,
- * swizzling as we go.
- */
- dev = dev->bus->self;
- }
- *pinp = pin + 1;
-
- return PCI_SLOT(dev->devfn);
-}
-
-/*
* Swizzle the device pin each time we cross a bridge.
* This might update pin and returns the slot number.
*/
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 09a061cb7838..9ca8d13f05f7 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -98,7 +98,7 @@
CALL(sys_uselib)
CALL(sys_swapon)
CALL(sys_reboot)
- CALL(OBSOLETE(old_readdir)) /* used by libc4 */
+ CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */
/* 90 */ CALL(OBSOLETE(old_mmap)) /* used by libc4 */
CALL(sys_munmap)
CALL(sys_truncate)
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 60c079d85355..eed2f795e1b3 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -817,7 +817,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
ec->dma = NO_DMA;
ec->ops = &ecard_default_ops;
- snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
+ dev_set_name(&ec->dev, "ecard%d", slot);
ec->dev.parent = NULL;
ec->dev.bus = &ecard_bus_type;
ec->dev.dma_mask = &ec->dma_mask;
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 77b047475539..85040cfeb5e5 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -650,6 +650,7 @@ ENTRY(fp_enter)
no_fp: mov pc, lr
__und_usr_unknown:
+ enable_irq
mov r0, sp
adr lr, ret_from_exception
b do_undefinstr
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 06269ea375c5..49a6ba926c2b 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -136,7 +136,7 @@ ENTRY(mcount)
ldmia sp!, {r0-r3, pc}
trace:
- ldr r1, [fp, #-4]
+ ldr r1, [fp, #-4] @ lr of instrumented routine
mov r0, lr
sub r0, r0, #MCOUNT_INSN_SIZE
mov lr, pc
diff --git a/arch/arm/kernel/init_task.c b/arch/arm/kernel/init_task.c
index 0bbf80625395..e859af349467 100644
--- a/arch/arm/kernel/init_task.c
+++ b/arch/arm/kernel/init_task.c
@@ -12,7 +12,6 @@
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 2f3eb795fa6e..363db186cb93 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -101,7 +101,7 @@ unlock:
/* Handle bad interrupts */
static struct irq_desc bad_irq_desc = {
.handle_irq = handle_bad_irq,
- .lock = SPIN_LOCK_UNLOCKED
+ .lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock),
};
/*
@@ -174,7 +174,7 @@ static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu);
spin_lock_irq(&desc->lock);
- desc->chip->set_affinity(irq, cpumask_of_cpu(cpu));
+ desc->chip->set_affinity(irq, cpumask_of(cpu));
spin_unlock_irq(&desc->lock);
}
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index 50a30bc91872..8ac9b8424007 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/sysctl.h>
#include <linux/init.h>
+#include <linux/io.h>
static unsigned int isa_membase, isa_portbase, isa_portshift;
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index 3f9abe0e9aff..f692efddd449 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -92,9 +92,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
if (p->ainsn.insn) {
- mutex_lock(&kprobe_mutex);
free_insn_slot(p->ainsn.insn, 0);
- mutex_unlock(&kprobe_mutex);
p->ainsn.insn = NULL;
}
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 019237d21622..55fa7ff96a3e 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -34,16 +34,6 @@
#include <asm/ptrace.h>
/*
- * bitmask of present and online CPUs.
- * The present bitmask indicates that the CPU is physically present.
- * The online bitmask indicates that the CPU is up and running.
- */
-cpumask_t cpu_possible_map;
-EXPORT_SYMBOL(cpu_possible_map);
-cpumask_t cpu_online_map;
-EXPORT_SYMBOL(cpu_online_map);
-
-/*
* as from 2.5, kernels no longer have an init_tasks structure
* so we need some other way of telling a new secondary core
* where to place its SVC stack
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
index 50e13965dfed..b5c5fc6ba3a9 100644
--- a/arch/arm/mach-aaec2000/core.c
+++ b/arch/arm/mach-aaec2000/core.c
@@ -212,7 +212,7 @@ static struct clcd_board clcd_plat_data = {
static struct amba_device clcd_device = {
.dev = {
- .bus_id = "mb:16",
+ .init_name = "mb:16",
.coherent_dma_mask = ~0,
.platform_data = &clcd_plat_data,
},
diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
index 0a38c69fdbc4..73376170fb91 100644
--- a/arch/arm/mach-at91/at91cap9.c
+++ b/arch/arm/mach-at91/at91cap9.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/pm.h>
+#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 28594fcc88e3..2e9ecad97f3d 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
+#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/at91rm9200.h>
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index d140eae53ded..1ff1bda0a894 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -178,7 +178,6 @@ static struct clock_event_device clkevt = {
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.shift = 32,
.rating = 150,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = clkevt32k_next_event,
.set_mode = clkevt32k_mode,
};
@@ -206,7 +205,7 @@ void __init at91rm9200_timer_init(void)
clkevt.mult = div_sc(AT91_SLOW_CLOCK, NSEC_PER_SEC, clkevt.shift);
clkevt.max_delta_ns = clockevent_delta2ns(AT91_ST_ALMV, &clkevt);
clkevt.min_delta_ns = clockevent_delta2ns(2, &clkevt) + 1;
- clkevt.cpumask = cpumask_of_cpu(0);
+ clkevt.cpumask = cpumask_of(0);
clockevents_register_device(&clkevt);
/* register clocksource */
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index accb69ec478e..0894f1077be7 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/pm.h>
+#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/cpu.h>
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 7b51a59ae8b3..3acd7d7e6a42 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/pm.h>
+#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/at91sam9261.h>
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index ada4b6769107..942792d630d8 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/pm.h>
+#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/at91sam9263.h>
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 122fd77ed580..b63e1d5f1bad 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -91,7 +91,6 @@ static struct clock_event_device pit_clkevt = {
.features = CLOCK_EVT_FEAT_PERIODIC,
.shift = 32,
.rating = 100,
- .cpumask = CPU_MASK_CPU0,
.set_mode = pit_clkevt_mode,
};
@@ -173,6 +172,7 @@ static void __init at91sam926x_pit_init(void)
/* Set up and register clockevents */
pit_clkevt.mult = div_sc(pit_rate, NSEC_PER_SEC, pit_clkevt.shift);
+ pit_clkevt.cpumask = cpumask_of(0);
clockevents_register_device(&pit_clkevt);
}
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 252e954b49fd..211c5c14a1e6 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/pm.h>
+#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/cpu.h>
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 9b937ee4815a..35e12a49d1a6 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -29,6 +29,7 @@
#include <mach/hardware.h>
#include <mach/board.h>
#include <mach/gpio.h>
+#include <mach/at91sam9_smc.h>
#include <mach/at91_shdwc.h>
#include "sam9_smc.h"
diff --git a/arch/arm/mach-clps711x/edb7211-mm.c b/arch/arm/mach-clps711x/edb7211-mm.c
index c58e32ec4c5d..0bea1454ae03 100644
--- a/arch/arm/mach-clps711x/edb7211-mm.c
+++ b/arch/arm/mach-clps711x/edb7211-mm.c
@@ -24,7 +24,6 @@
#include <mach/hardware.h>
#include <asm/page.h>
-#include <asm/pgtable.h>
#include <asm/sizes.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-clps711x/fortunet.c b/arch/arm/mach-clps711x/fortunet.c
index 7122b3d21043..7430e4049d87 100644
--- a/arch/arm/mach-clps711x/fortunet.c
+++ b/arch/arm/mach-clps711x/fortunet.c
@@ -24,7 +24,6 @@
#include <linux/initrd.h>
#include <mach/hardware.h>
-#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
index 3d4b1de8f898..808633f9f03c 100644
--- a/arch/arm/mach-davinci/devices.c
+++ b/arch/arm/mach-davinci/devices.c
@@ -20,6 +20,7 @@
#include <mach/hardware.h>
#include <mach/i2c.h>
+#include <mach/irqs.h>
static struct resource i2c_resources[] = {
{
diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h
index b3a2961f0f46..b456f079f43f 100644
--- a/arch/arm/mach-davinci/include/mach/gpio.h
+++ b/arch/arm/mach-davinci/include/mach/gpio.h
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <asm-generic/gpio.h>
#include <mach/hardware.h>
+#include <mach/irqs.h>
/*
* basic gpio routines
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 3b9a296b5c4b..f8bcd29d17a6 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -322,7 +322,7 @@ static void __init davinci_timer_init(void)
clockevent_davinci.min_delta_ns =
clockevent_delta2ns(1, &clockevent_davinci);
- clockevent_davinci.cpumask = cpumask_of_cpu(0);
+ clockevent_davinci.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_davinci);
}
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index fe182a85159c..867ead2559ad 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -12,6 +12,7 @@
#include <mach/common.h>
#include <mach/hardware.h>
+#include <mach/irqs.h>
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
static struct musb_hdrc_eps_bits musb_eps[] = {
@@ -76,29 +77,6 @@ static struct platform_device usb_dev = {
.num_resources = ARRAY_SIZE(usb_resources),
};
-#ifdef CONFIG_USB_MUSB_OTG
-
-static struct otg_transceiver *xceiv;
-
-struct otg_transceiver *otg_get_transceiver(void)
-{
- if (xceiv)
- get_device(xceiv->dev);
- return xceiv;
-}
-EXPORT_SYMBOL(otg_get_transceiver);
-
-int otg_set_transceiver(struct otg_transceiver *x)
-{
- if (xceiv && x)
- return -EBUSY;
- xceiv = x;
- return 0;
-}
-EXPORT_SYMBOL(otg_set_transceiver);
-
-#endif
-
void __init setup_usb(unsigned mA, unsigned potpgt_msec)
{
usb_data.power = mA / 2;
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 4781f323703b..6d9152de6074 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -409,7 +409,7 @@ static struct amba_pl010_data ep93xx_uart_data = {
static struct amba_device uart1_device = {
.dev = {
- .bus_id = "apb:uart1",
+ .init_name = "apb:uart1",
.platform_data = &ep93xx_uart_data,
},
.res = {
@@ -423,7 +423,7 @@ static struct amba_device uart1_device = {
static struct amba_device uart2_device = {
.dev = {
- .bus_id = "apb:uart2",
+ .init_name = "apb:uart2",
.platform_data = &ep93xx_uart_data,
},
.res = {
@@ -437,7 +437,7 @@ static struct amba_device uart2_device = {
static struct amba_device uart3_device = {
.dev = {
- .bus_id = "apb:uart3",
+ .init_name = "apb:uart3",
.platform_data = &ep93xx_uart_data,
},
.res = {
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c
index 36ff06d4df15..b97f529e58e8 100644
--- a/arch/arm/mach-footbridge/common.c
+++ b/arch/arm/mach-footbridge/common.c
@@ -28,12 +28,17 @@
#include "common.h"
-extern void __init isa_init_irq(unsigned int irq);
-
unsigned int mem_fclk_21285 = 50000000;
EXPORT_SYMBOL(mem_fclk_21285);
+static void __init early_fclk(char **arg)
+{
+ mem_fclk_21285 = simple_strtoul(*arg, arg, 0);
+}
+
+__early_param("mem_fclk_21285=", early_fclk);
+
static int __init parse_tag_memclk(const struct tag *tag)
{
mem_fclk_21285 = tag->u.memclk.fmemclk;
diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h
index 580e31bbc711..b05e662d21ad 100644
--- a/arch/arm/mach-footbridge/common.h
+++ b/arch/arm/mach-footbridge/common.h
@@ -7,3 +7,4 @@ extern void isa_rtc_init(void);
extern void footbridge_map_io(void);
extern void footbridge_init_irq(void);
+extern void isa_init_irq(unsigned int irq);
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 133086019e3e..3ffa54841ec5 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -287,6 +287,9 @@ struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys)
return pci_scan_bus(0, &dc21285_ops, sys);
}
+#define dc21285_request_irq(_a, _b, _c, _d, _e) \
+ WARN_ON(request_irq(_a, _b, _c, _d, _e) < 0)
+
void __init dc21285_preinit(void)
{
unsigned int mem_size, mem_mask;
@@ -335,16 +338,16 @@ void __init dc21285_preinit(void)
/*
* We don't care if these fail.
*/
- request_irq(IRQ_PCI_SERR, dc21285_serr_irq, IRQF_DISABLED,
- "PCI system error", &serr_timer);
- request_irq(IRQ_PCI_PERR, dc21285_parity_irq, IRQF_DISABLED,
- "PCI parity error", &perr_timer);
- request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, IRQF_DISABLED,
- "PCI abort", NULL);
- request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, IRQF_DISABLED,
- "Discard timer", NULL);
- request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, IRQF_DISABLED,
- "PCI data parity", NULL);
+ dc21285_request_irq(IRQ_PCI_SERR, dc21285_serr_irq, IRQF_DISABLED,
+ "PCI system error", &serr_timer);
+ dc21285_request_irq(IRQ_PCI_PERR, dc21285_parity_irq, IRQF_DISABLED,
+ "PCI parity error", &perr_timer);
+ dc21285_request_irq(IRQ_PCI_ABORT, dc21285_abort_irq, IRQF_DISABLED,
+ "PCI abort", NULL);
+ dc21285_request_irq(IRQ_DISCARD_TIMER, dc21285_discard_irq, IRQF_DISABLED,
+ "Discard timer", NULL);
+ dc21285_request_irq(IRQ_PCI_DPERR, dc21285_dparity_irq, IRQF_DISABLED,
+ "PCI data parity", NULL);
if (cfn_mode) {
static struct resource csrio;
diff --git a/arch/arm/mach-footbridge/isa-irq.c b/arch/arm/mach-footbridge/isa-irq.c
index 9ee80a211d3c..8bfd06aeb64d 100644
--- a/arch/arm/mach-footbridge/isa-irq.c
+++ b/arch/arm/mach-footbridge/isa-irq.c
@@ -28,6 +28,8 @@
#include <asm/irq.h>
#include <asm/mach-types.h>
+#include "common.h"
+
static void isa_mask_pic_lo_irq(unsigned int irq)
{
unsigned int mask = 1 << (irq & 7);
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index 56161d55cf47..8c0ba99d683f 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -25,6 +25,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/mach/arch.h>
+#include <mach/irqs.h>
#include <mach/hardware.h>
#include "common.h"
diff --git a/arch/arm/mach-imx/clock.c b/arch/arm/mach-imx/clock.c
index 7ec60fc91565..cf332aeb942e 100644
--- a/arch/arm/mach-imx/clock.c
+++ b/arch/arm/mach-imx/clock.c
@@ -23,7 +23,7 @@
#include <linux/err.h>
#include <linux/io.h>
-#include <mach/imx-regs.h>
+#include <mach/hardware.h>
/*
* Very simple approach: We can't disable clocks, so we do
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index fa72174dd95c..887cb21f75b0 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -245,11 +245,11 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
imx_mmc_device.dev.platform_data = info;
}
-static struct imxfb_mach_info imx_fb_info;
+static struct imx_fb_platform_data imx_fb_info;
-void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
+void __init set_imx_fb_info(struct imx_fb_platform_data *hard_imx_fb_info)
{
- memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imxfb_mach_info));
+ memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imx_fb_platform_data));
}
static struct resource imxfb_resources[] = {
diff --git a/arch/arm/mach-imx/include/mach/imx-regs.h b/arch/arm/mach-imx/include/mach/imx-regs.h
index fb9de2733879..490297fc0e38 100644
--- a/arch/arm/mach-imx/include/mach/imx-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx-regs.h
@@ -373,110 +373,4 @@
#define TSTAT_CAPT (1<<1)
#define TSTAT_COMP (1<<0)
-/*
- * LCD Controller
- */
-
-#define LCDC_SSA __REG(IMX_LCDC_BASE+0x00)
-
-#define LCDC_SIZE __REG(IMX_LCDC_BASE+0x04)
-#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20)
-#define SIZE_YMAX(y) ( (y) & 0x1ff )
-
-#define LCDC_VPW __REG(IMX_LCDC_BASE+0x08)
-#define VPW_VPW(x) ( (x) & 0x3ff )
-
-#define LCDC_CPOS __REG(IMX_LCDC_BASE+0x0C)
-#define CPOS_CC1 (1<<31)
-#define CPOS_CC0 (1<<30)
-#define CPOS_OP (1<<28)
-#define CPOS_CXP(x) (((x) & 3ff) << 16)
-#define CPOS_CYP(y) ((y) & 0x1ff)
-
-#define LCDC_LCWHB __REG(IMX_LCDC_BASE+0x10)
-#define LCWHB_BK_EN (1<<31)
-#define LCWHB_CW(w) (((w) & 0x1f) << 24)
-#define LCWHB_CH(h) (((h) & 0x1f) << 16)
-#define LCWHB_BD(x) ((x) & 0xff)
-
-#define LCDC_LCHCC __REG(IMX_LCDC_BASE+0x14)
-#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
-#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
-#define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
-
-#define LCDC_PCR __REG(IMX_LCDC_BASE+0x18)
-#define PCR_TFT (1<<31)
-#define PCR_COLOR (1<<30)
-#define PCR_PBSIZ_1 (0<<28)
-#define PCR_PBSIZ_2 (1<<28)
-#define PCR_PBSIZ_4 (2<<28)
-#define PCR_PBSIZ_8 (3<<28)
-#define PCR_BPIX_1 (0<<25)
-#define PCR_BPIX_2 (1<<25)
-#define PCR_BPIX_4 (2<<25)
-#define PCR_BPIX_8 (3<<25)
-#define PCR_BPIX_12 (4<<25)
-#define PCR_BPIX_16 (4<<25)
-#define PCR_PIXPOL (1<<24)
-#define PCR_FLMPOL (1<<23)
-#define PCR_LPPOL (1<<22)
-#define PCR_CLKPOL (1<<21)
-#define PCR_OEPOL (1<<20)
-#define PCR_SCLKIDLE (1<<19)
-#define PCR_END_SEL (1<<18)
-#define PCR_END_BYTE_SWAP (1<<17)
-#define PCR_REV_VS (1<<16)
-#define PCR_ACD_SEL (1<<15)
-#define PCR_ACD(x) (((x) & 0x7f) << 8)
-#define PCR_SCLK_SEL (1<<7)
-#define PCR_SHARP (1<<6)
-#define PCR_PCD(x) ((x) & 0x3f)
-
-#define LCDC_HCR __REG(IMX_LCDC_BASE+0x1C)
-#define HCR_H_WIDTH(x) (((x) & 0x3f) << 26)
-#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8)
-#define HCR_H_WAIT_2(x) ((x) & 0xff)
-
-#define LCDC_VCR __REG(IMX_LCDC_BASE+0x20)
-#define VCR_V_WIDTH(x) (((x) & 0x3f) << 26)
-#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8)
-#define VCR_V_WAIT_2(x) ((x) & 0xff)
-
-#define LCDC_POS __REG(IMX_LCDC_BASE+0x24)
-#define POS_POS(x) ((x) & 1f)
-
-#define LCDC_LSCR1 __REG(IMX_LCDC_BASE+0x28)
-#define LSCR1_PS_RISE_DELAY(x) (((x) & 0x7f) << 26)
-#define LSCR1_CLS_RISE_DELAY(x) (((x) & 0x3f) << 16)
-#define LSCR1_REV_TOGGLE_DELAY(x) (((x) & 0xf) << 8)
-#define LSCR1_GRAY2(x) (((x) & 0xf) << 4)
-#define LSCR1_GRAY1(x) (((x) & 0xf))
-
-#define LCDC_PWMR __REG(IMX_LCDC_BASE+0x2C)
-#define PWMR_CLS(x) (((x) & 0x1ff) << 16)
-#define PWMR_LDMSK (1<<15)
-#define PWMR_SCR1 (1<<10)
-#define PWMR_SCR0 (1<<9)
-#define PWMR_CC_EN (1<<8)
-#define PWMR_PW(x) ((x) & 0xff)
-
-#define LCDC_DMACR __REG(IMX_LCDC_BASE+0x30)
-#define DMACR_BURST (1<<31)
-#define DMACR_HM(x) (((x) & 0xf) << 16)
-#define DMACR_TM(x) ((x) &0xf)
-
-#define LCDC_RMCR __REG(IMX_LCDC_BASE+0x34)
-#define RMCR_LCDC_EN (1<<1)
-#define RMCR_SELF_REF (1<<0)
-
-#define LCDC_LCDICR __REG(IMX_LCDC_BASE+0x38)
-#define LCDICR_INT_SYN (1<<2)
-#define LCDICR_INT_CON (1)
-
-#define LCDC_LCDISR __REG(IMX_LCDC_BASE+0x40)
-#define LCDISR_UDR_ERR (1<<3)
-#define LCDISR_ERR_RES (1<<2)
-#define LCDISR_EOF (1<<1)
-#define LCDISR_BOF (1<<0)
-
#endif // _IMX_REGS_H
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index a11765f5f23b..aff0ebcfa847 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -184,7 +184,7 @@ static int __init imx_clockevent_init(unsigned long rate)
clockevent_imx.min_delta_ns =
clockevent_delta2ns(0xf, &clockevent_imx);
- clockevent_imx.cpumask = cpumask_of_cpu(0);
+ clockevent_imx.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_imx);
diff --git a/arch/arm/mach-integrator/clock.h b/arch/arm/mach-integrator/clock.h
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/arch/arm/mach-integrator/clock.h
+++ /dev/null
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index c89c949b4d45..6f8872913073 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -37,7 +37,7 @@ static struct amba_pl010_data integrator_uart_data;
static struct amba_device rtc_device = {
.dev = {
- .bus_id = "mb:15",
+ .init_name = "mb:15",
},
.res = {
.start = INTEGRATOR_RTC_BASE,
@@ -50,7 +50,7 @@ static struct amba_device rtc_device = {
static struct amba_device uart0_device = {
.dev = {
- .bus_id = "mb:16",
+ .init_name = "mb:16",
.platform_data = &integrator_uart_data,
},
.res = {
@@ -64,7 +64,7 @@ static struct amba_device uart0_device = {
static struct amba_device uart1_device = {
.dev = {
- .bus_id = "mb:17",
+ .init_name = "mb:17",
.platform_data = &integrator_uart_data,
},
.res = {
@@ -78,7 +78,7 @@ static struct amba_device uart1_device = {
static struct amba_device kmi0_device = {
.dev = {
- .bus_id = "mb:18",
+ .init_name = "mb:18",
},
.res = {
.start = KMI0_BASE,
@@ -91,7 +91,7 @@ static struct amba_device kmi0_device = {
static struct amba_device kmi1_device = {
.dev = {
- .bus_id = "mb:19",
+ .init_name = "mb:19",
},
.res = {
.start = KMI1_BASE,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 427c2d8dc123..4ac04055c2ea 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -407,7 +407,7 @@ static struct mmc_platform_data mmc_data = {
static struct amba_device mmc_device = {
.dev = {
- .bus_id = "mb:1c",
+ .init_name = "mb:1c",
.platform_data = &mmc_data,
},
.res = {
@@ -421,7 +421,7 @@ static struct amba_device mmc_device = {
static struct amba_device aaci_device = {
.dev = {
- .bus_id = "mb:1d",
+ .init_name = "mb:1d",
},
.res = {
.start = INTCP_PA_AACI_BASE,
@@ -532,7 +532,7 @@ static struct clcd_board clcd_data = {
static struct amba_device clcd_device = {
.dev = {
- .bus_id = "mb:c0",
+ .init_name = "mb:c0",
.coherent_dma_mask = ~0,
.platform_data = &clcd_data,
},
diff --git a/arch/arm/mach-integrator/pci.c b/arch/arm/mach-integrator/pci.c
index af7d3ff013ec..2fdb95433f0a 100644
--- a/arch/arm/mach-integrator/pci.c
+++ b/arch/arm/mach-integrator/pci.c
@@ -63,13 +63,7 @@
*
* Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
* Thus, each swizzle is ((pin-1) + (device#-4)) % 4
- *
- * The following code swizzles for exactly one bridge.
*/
-static inline int bridge_swizzle(int pin, unsigned int slot)
-{
- return (pin + slot) & 3;
-}
/*
* This routine handles multiple bridges.
@@ -81,15 +75,14 @@ static u8 __init integrator_swizzle(struct pci_dev *dev, u8 *pinp)
if (pin == 0)
pin = 1;
- pin -= 1;
while (dev->bus->self) {
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ pin = pci_swizzle_interrupt_pin(dev, pin);
/*
* move up the chain of bridges, swizzling as we go.
*/
dev = dev->bus->self;
}
- *pinp = pin + 1;
+ *pinp = pin;
return PCI_SLOT(dev->devfn);
}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 7766f469456b..f4656d2ac8a8 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -487,7 +487,7 @@ static int __init ixp4xx_clockevent_init(void)
clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx);
clockevent_ixp4xx.min_delta_ns =
clockevent_delta2ns(0xf, &clockevent_ixp4xx);
- clockevent_ixp4xx.cpumask = cpumask_of_cpu(0);
+ clockevent_ixp4xx.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_ixp4xx);
return 0;
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 7b8ef97fb501..b3404b7775b3 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -698,6 +698,7 @@ void __init kirkwood_init(void)
printk(KERN_INFO "Kirkwood: %s, TCLK=%d.\n",
kirkwood_id(), kirkwood_tclk);
kirkwood_ge00_shared_data.t_clk = kirkwood_tclk;
+ kirkwood_ge01_shared_data.t_clk = kirkwood_tclk;
kirkwood_spi_plat_data.tclk = kirkwood_tclk;
kirkwood_uart0_data[0].uartclk = kirkwood_tclk;
kirkwood_uart1_data[0].uartclk = kirkwood_tclk;
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index f6b08f207c89..73fccacd1a73 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/mbus.h>
+#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <plat/pcie.h>
#include "common.h"
diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c
index 36ab0fd3d9b6..b89fb6d46ccc 100644
--- a/arch/arm/mach-ks8695/devices.c
+++ b/arch/arm/mach-ks8695/devices.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
+#include <mach/irqs.h>
#include <mach/regs-wan.h>
#include <mach/regs-lan.h>
#include <mach/regs-hpna.h>
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
index a2a543258fc3..c472b9e8b37c 100644
--- a/arch/arm/mach-lh7a40x/clcd.c
+++ b/arch/arm/mach-lh7a40x/clcd.c
@@ -207,7 +207,7 @@ static struct clcd_board clcd_platform_data = {
static struct amba_device name##_device = { \
.dev = { \
.coherent_dma_mask = ~0, \
- .bus_id = busid, \
+ .init_name = busid, \
.platform_data = plat, \
}, \
.res = { \
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index c2a96e3965a6..e61967dde9a1 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -27,6 +27,7 @@
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
+#include <mach/irqs.h>
#include <mach/board.h>
#include <mach/msm_iomap.h>
diff --git a/arch/arm/mach-msm/devices.c b/arch/arm/mach-msm/devices.c
index f2a74b92a97f..31b6b30e98bf 100644
--- a/arch/arm/mach-msm/devices.c
+++ b/arch/arm/mach-msm/devices.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <mach/irqs.h>
#include <mach/msm_iomap.h>
#include "devices.h"
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 345a14cb73c3..444d9c0f5ca6 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -182,7 +182,7 @@ static void __init msm_timer_init(void)
clockevent_delta2ns(0xf0000000 >> clock->shift, ce);
/* 4 gets rounded down to 3 */
ce->min_delta_ns = clockevent_delta2ns(4, ce);
- ce->cpumask = cpumask_of_cpu(0);
+ ce->cpumask = cpumask_of(0);
cs->mult = clocksource_hz2mult(clock->freq, cs->shift);
res = clocksource_register(cs);
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index 430ea84d587d..aad3a7a2f830 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/mbus.h>
+#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <plat/pcie.h>
#include "common.h"
diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c
index af121f5ab710..2f9240be1c76 100644
--- a/arch/arm/mach-mx2/devices.c
+++ b/arch/arm/mach-mx2/devices.c
@@ -32,6 +32,7 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
+#include <mach/irqs.h>
#include <mach/hardware.h>
/*
diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c
index 1d46cb4adf96..f8428800f286 100644
--- a/arch/arm/mach-mx3/devices.c
+++ b/arch/arm/mach-mx3/devices.c
@@ -22,6 +22,7 @@
#include <linux/serial.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
+#include <mach/irqs.h>
#include <mach/imx-uart.h>
static struct resource uart0[] = {
diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c
index 8f1f992f002e..1d844e228ea9 100644
--- a/arch/arm/mach-netx/fb.c
+++ b/arch/arm/mach-netx/fb.c
@@ -24,6 +24,8 @@
#include <linux/amba/clcd.h>
#include <linux/err.h>
+#include <asm/irq.h>
+
#include <mach/netx-regs.h>
#include <mach/hardware.h>
@@ -91,7 +93,7 @@ void clk_put(struct clk *clk)
static struct amba_device fb_device = {
.dev = {
- .bus_id = "fb",
+ .init_name = "fb",
.coherent_dma_mask = ~0,
},
.res = {
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index d51d627ce7cf..f201fddb594f 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -163,7 +163,7 @@ static void __init netx_timer_init(void)
* Adding some safety ... */
netx_clockevent.min_delta_ns =
clockevent_delta2ns(0xa00, &netx_clockevent);
- netx_clockevent.cpumask = cpumask_of_cpu(0);
+ netx_clockevent.cpumask = cpumask_of(0);
clockevents_register_device(&netx_clockevent);
}
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
index 8fc6205dc3a5..181a78ba8165 100644
--- a/arch/arm/mach-netx/xc.c
+++ b/arch/arm/mach-netx/xc.c
@@ -24,6 +24,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
+#include <mach/irqs.h>
#include <mach/netx-regs.h>
#include <mach/xc.h>
diff --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c
index a63424d083d9..41df69721769 100644
--- a/arch/arm/mach-ns9xxx/time-ns9360.c
+++ b/arch/arm/mach-ns9xxx/time-ns9360.c
@@ -173,7 +173,7 @@ static void __init ns9360_timer_init(void)
ns9360_clockevent_device.min_delta_ns =
clockevent_delta2ns(1, &ns9360_clockevent_device);
- ns9360_clockevent_device.cpumask = cpumask_of_cpu(0);
+ ns9360_clockevent_device.cpumask = cpumask_of(0);
clockevents_register_device(&ns9360_clockevent_device);
setup_irq(IRQ_NS9360_TIMER0 + TIMER_CLOCKEVENT,
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index b240c5f861da..0d784a795092 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -37,16 +37,14 @@
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
-#include <mach/gpio-switch.h>
#include <mach/mux.h>
+#include <mach/dma.h>
#include <mach/tc.h>
#include <mach/nand.h>
#include <mach/irda.h>
#include <mach/usb.h>
#include <mach/keypad.h>
#include <mach/common.h>
-#include <mach/mcbsp.h>
-#include <mach/omap-alsa.h>
static int h2_keymap[] = {
KEY(0, 0, KEY_LEFT),
@@ -292,41 +290,6 @@ static struct platform_device h2_lcd_device = {
.id = -1,
};
-static struct omap_mcbsp_reg_cfg mcbsp_regs = {
- .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
- .spcr1 = RINTM(3) | RRST,
- .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
- RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
- .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
- .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
- XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
- .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
- .srgr1 = FWID(15),
- .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
-
- .pcr0 = CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
- /*.pcr0 = CLKXP | CLKRP,*/ /* mcbsp: slave */
-};
-
-static struct omap_alsa_codec_config alsa_config = {
- .name = "H2 TSC2101",
- .mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, /* tsc2101_configure, */
- .codec_set_samplerate = NULL, /* tsc2101_set_samplerate, */
- .codec_clock_setup = NULL, /* tsc2101_clock_setup, */
- .codec_clock_on = NULL, /* tsc2101_clock_on, */
- .codec_clock_off = NULL, /* tsc2101_clock_off, */
- .get_default_samplerate = NULL, /* tsc2101_get_default_samplerate, */
-};
-
-static struct platform_device h2_mcbsp1_device = {
- .name = "omap_alsa_mcbsp",
- .id = 1,
- .dev = {
- .platform_data = &alsa_config,
- },
-};
-
static struct platform_device *h2_devices[] __initdata = {
&h2_nor_device,
&h2_nand_device,
@@ -334,7 +297,6 @@ static struct platform_device *h2_devices[] __initdata = {
&h2_irda_device,
&h2_kp_device,
&h2_lcd_device,
- &h2_mcbsp1_device,
};
static void __init h2_init_smc91x(void)
@@ -409,11 +371,6 @@ static struct omap_board_config_kernel h2_config[] __initdata = {
#define H2_NAND_RB_GPIO_PIN 62
-static int h2_nand_dev_ready(struct omap_nand_platform_data *data)
-{
- return gpio_get_value(H2_NAND_RB_GPIO_PIN);
-}
-
static void __init h2_init(void)
{
/* Here we assume the NOR boot config: NOR on CS3 (possibly swapped
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 5157eea9be35..bf08b6ad22ee 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -49,8 +49,6 @@
#include <mach/keypad.h>
#include <mach/dma.h>
#include <mach/common.h>
-#include <mach/mcbsp.h>
-#include <mach/omap-alsa.h>
#define H3_TS_GPIO 48
@@ -387,41 +385,6 @@ static struct spi_board_info h3_spi_board_info[] __initdata = {
},
};
-static struct omap_mcbsp_reg_cfg mcbsp_regs = {
- .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
- .spcr1 = RINTM(3) | RRST,
- .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
- RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(1),
- .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
- .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
- XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
- .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
- .srgr1 = FWID(15),
- .srgr2 = GSYNC | CLKSP | FSGM | FPER(31),
-
- .pcr0 = CLKRM | SCLKME | FSXP | FSRP | CLKXP | CLKRP,
- /*.pcr0 = CLKXP | CLKRP,*/ /* mcbsp: slave */
-};
-
-static struct omap_alsa_codec_config alsa_config = {
- .name = "H3 TSC2101",
- .mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, /* tsc2101_configure, */
- .codec_set_samplerate = NULL, /* tsc2101_set_samplerate, */
- .codec_clock_setup = NULL, /* tsc2101_clock_setup, */
- .codec_clock_on = NULL, /* tsc2101_clock_on, */
- .codec_clock_off = NULL, /* tsc2101_clock_off, */
- .get_default_samplerate = NULL, /* tsc2101_get_default_samplerate, */
-};
-
-static struct platform_device h3_mcbsp1_device = {
- .name = "omap_alsa_mcbsp",
- .id = 1,
- .dev = {
- .platform_data = &alsa_config,
- },
-};
-
static struct platform_device *devices[] __initdata = {
&nor_device,
&nand_device,
@@ -430,7 +393,6 @@ static struct platform_device *devices[] __initdata = {
&h3_irda_device,
&h3_kp_device,
&h3_lcd_device,
- &h3_mcbsp1_device,
};
static struct omap_usb_config h3_usb_config __initdata = {
@@ -472,18 +434,6 @@ static struct i2c_board_info __initdata h3_i2c_board_info[] = {
},
};
-static struct omap_gpio_switch h3_gpio_switches[] __initdata = {
- {
- .name = "mmc_slot",
- .gpio = OMAP_MPUIO(1),
- .type = OMAP_GPIO_SWITCH_TYPE_COVER,
- .debounce_rising = 100,
- .debounce_falling = 0,
- .notify = h3_mmc_slot_cover_handler,
- .notify_data = NULL,
- },
-};
-
#define H3_NAND_RB_GPIO_PIN 10
static int nand_dev_ready(struct omap_nand_platform_data *data)
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index af2fb9070083..071cd02a734e 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -37,8 +37,6 @@
#include <mach/usb.h>
#include <mach/keypad.h>
#include <mach/common.h>
-#include <mach/mcbsp.h>
-#include <mach/omap-alsa.h>
#include <mach/mmc.h>
static int innovator_keymap[] = {
@@ -115,42 +113,6 @@ static struct platform_device innovator_flash_device = {
.resource = &innovator_flash_resource,
};
-#define DEFAULT_BITPERSAMPLE 16
-
-static struct omap_mcbsp_reg_cfg mcbsp_regs = {
- .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
- .spcr1 = RINTM(3) | RRST,
- .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
- RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
- .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
- .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
- XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
- .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
- .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
- .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
- /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
- .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
-};
-
-static struct omap_alsa_codec_config alsa_config = {
- .name = "OMAP Innovator AIC23",
- .mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, /* aic23_configure, */
- .codec_set_samplerate = NULL, /* aic23_set_samplerate, */
- .codec_clock_setup = NULL, /* aic23_clock_setup, */
- .codec_clock_on = NULL, /* aic23_clock_on, */
- .codec_clock_off = NULL, /* aic23_clock_off, */
- .get_default_samplerate = NULL, /* aic23_get_default_samplerate, */
-};
-
-static struct platform_device innovator_mcbsp1_device = {
- .name = "omap_alsa_mcbsp",
- .id = 1,
- .dev = {
- .platform_data = &alsa_config,
- },
-};
-
static struct resource innovator_kp_resources[] = {
[0] = {
.start = INT_KEYBOARD,
@@ -227,7 +189,6 @@ static struct platform_device innovator1510_spi_device = {
static struct platform_device *innovator1510_devices[] __initdata = {
&innovator_flash_device,
&innovator1510_smc91x_device,
- &innovator_mcbsp1_device,
&innovator_kp_device,
&innovator1510_lcd_device,
&innovator1510_spi_device,
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 4970c402a594..af51e0b180f2 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -32,7 +32,6 @@
#include <mach/keypad.h>
#include <mach/common.h>
#include <mach/dsp_common.h>
-#include <mach/aic23.h>
#include <mach/omapfb.h>
#include <mach/lcd_mipid.h>
#include <mach/mmc.h>
@@ -261,6 +260,13 @@ static DEFINE_MUTEX(audio_pwr_lock);
*/
static int audio_pwr_state = -1;
+static inline void aic23_power_up(void)
+{
+}
+static inline void aic23_power_down(void)
+{
+}
+
/*
* audio_pwr_up / down should be called under audio_pwr_lock
*/
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index ff9e67baa5c9..1a16ecb2ccc8 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -51,8 +51,6 @@
#include <mach/mux.h>
#include <mach/tc.h>
#include <mach/common.h>
-#include <mach/mcbsp.h>
-#include <mach/omap-alsa.h>
static struct mtd_partition osk_partitions[] = {
/* bootloader (U-Boot, etc) in first sector */
@@ -141,47 +139,10 @@ static struct platform_device osk5912_cf_device = {
.resource = osk5912_cf_resources,
};
-#define DEFAULT_BITPERSAMPLE 16
-
-static struct omap_mcbsp_reg_cfg mcbsp_regs = {
- .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
- .spcr1 = RINTM(3) | RRST,
- .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
- RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
- .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
- .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
- XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
- .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
- .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
- .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
- /*.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,*/ /* mcbsp: master */
- .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
-};
-
-static struct omap_alsa_codec_config alsa_config = {
- .name = "OSK AIC23",
- .mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, /* aic23_configure, */
- .codec_set_samplerate = NULL, /* aic23_set_samplerate, */
- .codec_clock_setup = NULL, /* aic23_clock_setup, */
- .codec_clock_on = NULL, /* aic23_clock_on, */
- .codec_clock_off = NULL, /* aic23_clock_off, */
- .get_default_samplerate = NULL, /* aic23_get_default_samplerate, */
-};
-
-static struct platform_device osk5912_mcbsp1_device = {
- .name = "omap_alsa_mcbsp",
- .id = 1,
- .dev = {
- .platform_data = &alsa_config,
- },
-};
-
static struct platform_device *osk5912_devices[] __initdata = {
&osk5912_flash_device,
&osk5912_smc91x_device,
&osk5912_cf_device,
- &osk5912_mcbsp1_device,
};
static struct gpio_led tps_leds[] = {
@@ -259,8 +220,10 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
.platform_data = &tps_board,
},
+ {
+ I2C_BOARD_INFO("tlv320aic23", 0x1B),
+ },
/* TODO when driver support is ready:
- * - aic23 audio chip at 0x1a
* - optionally on Mistral, ov9640 camera sensor at 0x30
*/
};
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 75e32d35afd9..99f2b43f2541 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -42,8 +42,6 @@
#include <mach/irda.h>
#include <mach/keypad.h>
#include <mach/common.h>
-#include <mach/mcbsp.h>
-#include <mach/omap-alsa.h>
static void __init omap_palmte_init_irq(void)
{
@@ -195,15 +193,6 @@ static struct omap_usb_config palmte_usb_config __initdata = {
.pins[0] = 2,
};
-static struct omap_mmc_config palmte_mmc_config __initdata = {
- .mmc[0] = {
- .enabled = 1,
- .wp_pin = PALMTE_MMC_WP_GPIO,
- .power_pin = PALMTE_MMC_POWER_GPIO,
- .switch_pin = PALMTE_MMC_SWITCH_GPIO,
- },
-};
-
static struct omap_lcd_config palmte_lcd_config __initdata = {
.ctrl_name = "internal",
};
@@ -212,24 +201,6 @@ static struct omap_uart_config palmte_uart_config __initdata = {
.enabled_uarts = (1 << 0) | (1 << 1) | (0 << 2),
};
-static struct omap_mcbsp_reg_cfg palmte_mcbsp1_regs = {
- .spcr2 = FRST | GRST | XRST | XINTM(3),
- .xcr2 = XDATDLY(1) | XFIG,
- .xcr1 = XWDLEN1(OMAP_MCBSP_WORD_32),
- .pcr0 = SCLKME | FSXP | CLKXP,
-};
-
-static struct omap_alsa_codec_config palmte_alsa_config = {
- .name = "TSC2102 audio",
- .mcbsp_regs_alsa = &palmte_mcbsp1_regs,
- .codec_configure_dev = NULL, /* tsc2102_configure, */
- .codec_set_samplerate = NULL, /* tsc2102_set_samplerate, */
- .codec_clock_setup = NULL, /* tsc2102_clock_setup, */
- .codec_clock_on = NULL, /* tsc2102_clock_on, */
- .codec_clock_off = NULL, /* tsc2102_clock_off, */
- .get_default_samplerate = NULL, /* tsc2102_get_default_samplerate, */
-};
-
#ifdef CONFIG_APM
/*
* Values measured in 10 minute intervals averaged over 10 samples.
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 5c001afe8062..1cbc1275c95f 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -30,7 +30,6 @@
#include <asm/mach/flash.h>
#include <mach/led.h>
-#include <mach/mcbsp.h>
#include <mach/gpio.h>
#include <mach/mux.h>
#include <mach/usb.h>
@@ -40,7 +39,6 @@
#include <mach/irda.h>
#include <mach/keypad.h>
#include <mach/common.h>
-#include <mach/omap-alsa.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
@@ -122,44 +120,6 @@ static struct platform_device palmtt_flash_device = {
.resource = &palmtt_flash_resource,
};
-#define DEFAULT_BITPERSAMPLE 16
-
-static struct omap_mcbsp_reg_cfg mcbsp_regs = {
- .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
- .spcr1 = RINTM(3) | RRST,
- .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
- RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
- .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) |
- RWDLEN1(OMAP_MCBSP_WORD_16),
- .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
- XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
- .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) |
- XWDLEN1(OMAP_MCBSP_WORD_16),
- .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
- .srgr2 = GSYNC | CLKSP | FSGM |
- FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
- .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
-};
-
-static struct omap_alsa_codec_config alsa_config = {
- .name = "PalmTT AIC23",
- .mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, /* aic23_configure, */
- .codec_set_samplerate = NULL, /* aic23_set_samplerate, */
- .codec_clock_setup = NULL, /* aic23_clock_setup, */
- .codec_clock_on = NULL, /* aic23_clock_on, */
- .codec_clock_off = NULL, /* aic23_clock_off, */
- .get_default_samplerate = NULL, /* aic23_get_default_samplerate, */
-};
-
-static struct platform_device palmtt_mcbsp1_device = {
- .name = "omap_alsa_mcbsp",
- .id = 1,
- .dev = {
- .platform_data = &alsa_config,
- },
-};
-
static struct resource palmtt_kp_resources[] = {
[0] = {
.start = INT_KEYBOARD,
@@ -257,7 +217,6 @@ static struct platform_device palmtt_led_device = {
static struct platform_device *palmtt_devices[] __initdata = {
&palmtt_flash_device,
- &palmtt_mcbsp1_device,
&palmtt_kp_device,
&palmtt_lcd_device,
&palmtt_irda_device,
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index cc05257eb1cd..baf5efbfe3e8 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -32,7 +32,6 @@
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
-#include <mach/mcbsp.h>
#include <mach/gpio.h>
#include <mach/mux.h>
#include <mach/usb.h>
@@ -179,41 +178,6 @@ static struct platform_device palmz71_spi_device = {
.id = -1,
};
-#define DEFAULT_BITPERSAMPLE 16
-
-static struct omap_mcbsp_reg_cfg mcbsp_regs = {
- .spcr2 = FREE | FRST | GRST | XRST | XINTM(3),
- .spcr1 = RINTM(3) | RRST,
- .rcr2 = RPHASE | RFRLEN2(OMAP_MCBSP_WORD_8) |
- RWDLEN2(OMAP_MCBSP_WORD_16) | RDATDLY(0),
- .rcr1 = RFRLEN1(OMAP_MCBSP_WORD_8) | RWDLEN1(OMAP_MCBSP_WORD_16),
- .xcr2 = XPHASE | XFRLEN2(OMAP_MCBSP_WORD_8) |
- XWDLEN2(OMAP_MCBSP_WORD_16) | XDATDLY(0) | XFIG,
- .xcr1 = XFRLEN1(OMAP_MCBSP_WORD_8) | XWDLEN1(OMAP_MCBSP_WORD_16),
- .srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
- .srgr2 = GSYNC | CLKSP | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
- .pcr0 = CLKXP | CLKRP, /* mcbsp: slave */
-};
-
-static struct omap_alsa_codec_config alsa_config = {
- .name = "PalmZ71 AIC23",
- .mcbsp_regs_alsa = &mcbsp_regs,
- .codec_configure_dev = NULL, /* aic23_configure */
- .codec_set_samplerate = NULL, /* aic23_set_samplerate */
- .codec_clock_setup = NULL, /* aic23_clock_setup */
- .codec_clock_on = NULL, /* aic23_clock_on */
- .codec_clock_off = NULL, /* aic23_clock_off */
- .get_default_samplerate = NULL, /* aic23_get_default_samplerate */
-};
-
-static struct platform_device palmz71_mcbsp1_device = {
- .name = "omap_alsa_mcbsp",
- .id = 1,
- .dev = {
- .platform_data = &alsa_config,
- },
-};
-
static struct omap_backlight_config palmz71_backlight_config = {
.default_intensity = 0xa0,
};
@@ -229,7 +193,6 @@ static struct platform_device palmz71_backlight_device = {
static struct platform_device *devices[] __initdata = {
&palmz71_rom_device,
&palmz71_kp_device,
- &palmz71_mcbsp1_device,
&palmz71_lcd_device,
&palmz71_irda_device,
&palmz71_spi_device,
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 8171fe0ca082..28c76a1e71c0 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -34,13 +34,12 @@
#include <mach/gpio.h>
#include <mach/mux.h>
+#include <mach/dma.h>
#include <mach/irda.h>
#include <mach/usb.h>
#include <mach/tc.h>
#include <mach/board.h>
#include <mach/common.h>
-#include <mach/mcbsp.h>
-#include <mach/omap-alsa.h>
#include <mach/keypad.h>
/* Write to I2C device */
@@ -254,35 +253,6 @@ static struct platform_device sx1_irda_device = {
.resource = sx1_irda_resources,
};
-/*----------- McBSP & Sound -------------------------*/
-
-/* Playback interface - McBSP1 */
-static struct omap_mcbsp_reg_cfg mcbsp1_regs = {
- .spcr2 = XINTM(3), /* SPCR2=30 */
- .spcr1 = RINTM(3), /* SPCR1=30 */
- .rcr2 = 0, /* RCR2 =00 */
- .rcr1 = RFRLEN1(1) | RWDLEN1(OMAP_MCBSP_WORD_16), /* RCR1=140 */
- .xcr2 = 0, /* XCR2 = 0 */
- .xcr1 = XFRLEN1(1) | XWDLEN1(OMAP_MCBSP_WORD_16), /* XCR1 = 140 */
- .srgr1 = FWID(15) | CLKGDV(12), /* SRGR1=0f0c */
- .srgr2 = FSGM | FPER(31), /* SRGR2=101f */
- .pcr0 = FSXM | FSRM | CLKXM | CLKRM | FSXP | FSRP | CLKXP | CLKRP,
- /* PCR0 =0f0f */
-};
-
-static struct omap_alsa_codec_config sx1_alsa_config = {
- .name = "SX1 EGold",
- .mcbsp_regs_alsa = &mcbsp1_regs,
-};
-
-static struct platform_device sx1_mcbsp1_device = {
- .name = "omap_alsa_mcbsp",
- .id = 1,
- .dev = {
- .platform_data = &sx1_alsa_config,
- },
-};
-
/*----------- MTD -------------------------*/
static struct mtd_partition sx1_partitions[] = {
@@ -394,7 +364,6 @@ static struct platform_device *sx1_devices[] __initdata = {
&sx1_flash_device,
&sx1_kp_device,
&sx1_lcd_device,
- &sx1_mcbsp1_device,
&sx1_irda_device,
};
/*-----------------------------------------*/
@@ -423,9 +392,9 @@ static void __init omap_sx1_init(void)
/* turn on USB power */
/* sx1_setusbpower(1); cant do it here because i2c is not ready */
- omap_request_gpio(1); /* A_IRDA_OFF */
- omap_request_gpio(11); /* A_SWITCH */
- omap_request_gpio(15); /* A_USB_ON */
+ gpio_request(1, "A_IRDA_OFF");
+ gpio_request(11, "A_SWITCH");
+ gpio_request(15, "A_USB_ON");
gpio_direction_output(1, 1); /*A_IRDA_OFF = 1 */
gpio_direction_output(11, 0); /*A_SWITCH = 0 */
gpio_direction_output(15, 0); /*A_USB_ON = 0 */
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index c224f3c64235..a7653542a2b0 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -22,7 +22,6 @@
#include <linux/reboot.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
-#include <linux/irq.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index 77382d8b6b2f..ba5d7c08dc17 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -181,7 +181,7 @@ void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
}
size = OMAP1_MMC_SIZE;
- omap_mmc_add(i, base, size, irq, mmc_data[i]);
+ omap_mmc_add("mmci-omap", i, base, size, irq, mmc_data[i]);
};
}
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 7de7c6915584..575ba31295cf 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -17,7 +17,9 @@
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <mach/irqs.h>
#include <mach/dma.h>
+#include <mach/irqs.h>
#include <mach/mux.h>
#include <mach/cpu.h>
#include <mach/mcbsp.h>
@@ -26,81 +28,8 @@
#define DPS_RSTCT2_PER_EN (1 << 0)
#define DSP_RSTCT2_WD_PER_EN (1 << 1)
-struct mcbsp_internal_clk {
- struct clk clk;
- struct clk **childs;
- int n_childs;
-};
-
#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
-static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
-{
- const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" };
- int i;
-
- mclk->n_childs = ARRAY_SIZE(clk_names);
- mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
- GFP_KERNEL);
-
- for (i = 0; i < mclk->n_childs; i++) {
- /* We fake a platform device to get correct device id */
- struct platform_device pdev;
-
- pdev.dev.bus = &platform_bus_type;
- pdev.id = mclk->clk.id;
- mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
- if (IS_ERR(mclk->childs[i]))
- printk(KERN_ERR "Could not get clock %s (%d).\n",
- clk_names[i], mclk->clk.id);
- }
-}
-
-static int omap_mcbsp_clk_enable(struct clk *clk)
-{
- struct mcbsp_internal_clk *mclk = container_of(clk,
- struct mcbsp_internal_clk, clk);
- int i;
-
- for (i = 0; i < mclk->n_childs; i++)
- clk_enable(mclk->childs[i]);
- return 0;
-}
-
-static void omap_mcbsp_clk_disable(struct clk *clk)
-{
- struct mcbsp_internal_clk *mclk = container_of(clk,
- struct mcbsp_internal_clk, clk);
- int i;
-
- for (i = 0; i < mclk->n_childs; i++)
- clk_disable(mclk->childs[i]);
-}
-
-static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
- {
- .clk = {
- .name = "mcbsp_clk",
- .id = 1,
- .enable = omap_mcbsp_clk_enable,
- .disable = omap_mcbsp_clk_disable,
- },
- },
- {
- .clk = {
- .name = "mcbsp_clk",
- .id = 3,
- .enable = omap_mcbsp_clk_enable,
- .disable = omap_mcbsp_clk_disable,
- },
- },
-};
-
-#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks)
-#else
-#define omap_mcbsp_clks_size 0
-static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
-static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
-{ }
+const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" };
#endif
static void omap1_mcbsp_request(unsigned int id)
@@ -165,8 +94,9 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
.rx_irq = INT_McBSP1RX,
.tx_irq = INT_McBSP1TX,
.ops = &omap1_mcbsp_ops,
- .clk_name = "mcbsp_clk",
- },
+ .clk_names = clk_names,
+ .num_clks = 3,
+ },
{
.phys_base = OMAP1510_MCBSP2_BASE,
.dma_rx_sync = OMAP_DMA_MCBSP2_RX,
@@ -182,7 +112,8 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
.rx_irq = INT_McBSP3RX,
.tx_irq = INT_McBSP3TX,
.ops = &omap1_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 3,
},
};
#define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata)
@@ -200,7 +131,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
.rx_irq = INT_McBSP1RX,
.tx_irq = INT_McBSP1TX,
.ops = &omap1_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 3,
},
{
.phys_base = OMAP1610_MCBSP2_BASE,
@@ -217,7 +149,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
.rx_irq = INT_McBSP3RX,
.tx_irq = INT_McBSP3TX,
.ops = &omap1_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 3,
},
};
#define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata)
@@ -228,15 +161,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
int __init omap1_mcbsp_init(void)
{
- int i;
-
- for (i = 0; i < omap_mcbsp_clks_size; i++) {
- if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
- omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
- clk_register(&omap_mcbsp_clks[i].clk);
- }
- }
-
if (cpu_is_omap730())
omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ;
if (cpu_is_omap15xx())
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 2cf7e32bd293..495a32c287b4 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -173,7 +173,7 @@ static __init void omap_init_mpu_timer(unsigned long rate)
clockevent_mpu_timer1.min_delta_ns =
clockevent_delta2ns(1, &clockevent_mpu_timer1);
- clockevent_mpu_timer1.cpumask = cpumask_of_cpu(0);
+ clockevent_mpu_timer1.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_mpu_timer1);
}
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index 705367ece174..fd3f7396e162 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -187,7 +187,7 @@ static __init void omap_init_32k_timer(void)
clockevent_32k_timer.min_delta_ns =
clockevent_delta2ns(1, &clockevent_32k_timer);
- clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
+ clockevent_32k_timer.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_32k_timer);
}
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index bf1e5d32c2a3..0a7b24ba1652 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -22,8 +22,6 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/onenand.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/leds.h>
#include <linux/err.h>
@@ -282,65 +280,16 @@ static void __init apollon_led_init(void)
{
/* LED0 - AA10 */
omap_cfg_reg(AA10_242X_GPIO13);
- omap_request_gpio(LED0_GPIO13);
- omap_set_gpio_direction(LED0_GPIO13, 0);
- omap_set_gpio_dataout(LED0_GPIO13, 0);
+ gpio_request(LED0_GPIO13, "LED0");
+ gpio_direction_output(LED0_GPIO13, 0);
/* LED1 - AA6 */
omap_cfg_reg(AA6_242X_GPIO14);
- omap_request_gpio(LED1_GPIO14);
- omap_set_gpio_direction(LED1_GPIO14, 0);
- omap_set_gpio_dataout(LED1_GPIO14, 0);
+ gpio_request(LED1_GPIO14, "LED1");
+ gpio_direction_output(LED1_GPIO14, 0);
/* LED2 - AA4 */
omap_cfg_reg(AA4_242X_GPIO15);
- omap_request_gpio(LED2_GPIO15);
- omap_set_gpio_direction(LED2_GPIO15, 0);
- omap_set_gpio_dataout(LED2_GPIO15, 0);
-}
-
-static irqreturn_t apollon_sw_interrupt(int irq, void *ignored)
-{
- static unsigned int led0, led1, led2;
-
- if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16))
- omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1);
- else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17))
- omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1);
- else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58))
- omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1);
-
- return IRQ_HANDLED;
-}
-
-static void __init apollon_sw_init(void)
-{
- /* Enter SW - Y11 */
- omap_cfg_reg(Y11_242X_GPIO16);
- omap_request_gpio(SW_ENTER_GPIO16);
- gpio_direction_input(SW_ENTER_GPIO16);
- /* Up SW - AA12 */
- omap_cfg_reg(AA12_242X_GPIO17);
- omap_request_gpio(SW_UP_GPIO17);
- gpio_direction_input(SW_UP_GPIO17);
- /* Down SW - AA8 */
- omap_cfg_reg(AA8_242X_GPIO58);
- omap_request_gpio(SW_DOWN_GPIO58);
- gpio_direction_input(SW_DOWN_GPIO58);
-
- set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQ_TYPE_EDGE_RISING);
- if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt,
- IRQF_SHARED, "enter sw",
- &apollon_sw_interrupt))
- return;
- set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQ_TYPE_EDGE_RISING);
- if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt,
- IRQF_SHARED, "up sw",
- &apollon_sw_interrupt))
- return;
- set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQ_TYPE_EDGE_RISING);
- if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt,
- IRQF_SHARED, "down sw",
- &apollon_sw_interrupt))
- return;
+ gpio_request(LED2_GPIO15, "LED2");
+ gpio_direction_output(LED2_GPIO15, 0);
}
static void __init apollon_usb_init(void)
@@ -357,7 +306,6 @@ static void __init omap_apollon_init(void)
u32 v;
apollon_led_init();
- apollon_sw_init();
apollon_flash_init();
apollon_usb_init();
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index aa6972781e4a..f6a13451d1fd 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -88,7 +88,7 @@ static inline void __init ldp_init_smc911x(void)
ldp_smc911x_resources[1].start = OMAP_GPIO_IRQ(eth_gpio);
- if (omap_request_gpio(eth_gpio) < 0) {
+ if (gpio_request(eth_gpio, "smc911x irq") < 0) {
printk(KERN_ERR "Failed to request GPIO%d for smc911x IRQ\n",
eth_gpio);
return;
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 9e5ada01b5fa..38c88fbe658d 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -28,6 +28,8 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
+#include <linux/i2c/twl4030.h>
+
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -120,6 +122,9 @@ static int beagle_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
+ omap_cfg_reg(AH8_34XX_GPIO29);
+ mmc[0].gpio_cd = gpio + 0;
+ twl4030_mmc_init(mmc);
/* REVISIT: need ehci-omap hooks for external VBUS
* power switch and overcurrent detect
@@ -304,10 +309,6 @@ static void __init omap3_beagle_init(void)
omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
omap_serial_init();
- omap_cfg_reg(AH8_34XX_GPIO29);
- mmc[0].gpio_cd = gpio + 0;
- twl4030_mmc_init(mmc);
-
omap_cfg_reg(J25_34XX_GPIO170);
gpio_request(170, "DVI_nPD");
/* REVISIT leave DVI powered down until it's needed ... */
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h
index ff6cd14d254d..ad6d98d177c5 100644
--- a/arch/arm/mach-omap2/clock24xx.h
+++ b/arch/arm/mach-omap2/clock24xx.h
@@ -2321,7 +2321,7 @@ static struct clk i2c2_fck = {
};
static struct clk i2chs2_fck = {
- .name = "i2chs_fck",
+ .name = "i2c_fck",
.id = 2,
.parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X,
@@ -2354,7 +2354,7 @@ static struct clk i2c1_fck = {
};
static struct clk i2chs1_fck = {
- .name = "i2chs_fck",
+ .name = "i2c_fck",
.id = 1,
.parent = &func_96m_ck,
.flags = CLOCK_IN_OMAP243X,
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 9d7216ff6c9f..ce03fa750775 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -421,6 +421,7 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
int nr_controllers)
{
int i;
+ char *name;
for (i = 0; i < nr_controllers; i++) {
unsigned long base, size;
@@ -450,12 +451,14 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
continue;
}
- if (cpu_is_omap2420())
+ if (cpu_is_omap2420()) {
size = OMAP2420_MMC_SIZE;
- else
+ name = "mmci-omap";
+ } else {
size = HSMMC_SIZE;
-
- omap_mmc_add(i, base, size, irq, mmc_data[i]);
+ name = "mmci-omap-hs";
+ }
+ omap_mmc_add(name, i, base, size, irq, mmc_data[i]);
};
}
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index b0f8e7d62798..b52a02fc7cd6 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -172,9 +172,13 @@ void __init omap34xx_check_revision(void)
omap_revision = OMAP3430_REV_ES3_0;
rev_name = "ES3.0";
break;
+ case 4:
+ omap_revision = OMAP3430_REV_ES3_1;
+ rev_name = "ES3.1";
+ break;
default:
/* Use the latest known revision as default */
- omap_revision = OMAP3430_REV_ES3_0;
+ omap_revision = OMAP3430_REV_ES3_1;
rev_name = "Unknown revision\n";
}
}
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 636e2821af7d..9ba20d985dda 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -134,6 +134,7 @@ static struct irq_chip omap_irq_chip = {
.ack = omap_mask_ack_irq,
.mask = omap_mask_irq,
.unmask = omap_unmask_irq,
+ .disable = omap_mask_irq,
};
static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index cae3ebe249b3..a9e631fc1134 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -17,111 +17,14 @@
#include <linux/io.h>
#include <linux/platform_device.h>
+#include <mach/irqs.h>
#include <mach/dma.h>
+#include <mach/irqs.h>
#include <mach/mux.h>
#include <mach/cpu.h>
#include <mach/mcbsp.h>
-struct mcbsp_internal_clk {
- struct clk clk;
- struct clk **childs;
- int n_childs;
-};
-
-#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
-static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
-{
- const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
- int i;
-
- mclk->n_childs = ARRAY_SIZE(clk_names);
- mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
- GFP_KERNEL);
-
- for (i = 0; i < mclk->n_childs; i++) {
- /* We fake a platform device to get correct device id */
- struct platform_device pdev;
-
- pdev.dev.bus = &platform_bus_type;
- pdev.id = mclk->clk.id;
- mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
- if (IS_ERR(mclk->childs[i]))
- printk(KERN_ERR "Could not get clock %s (%d).\n",
- clk_names[i], mclk->clk.id);
- }
-}
-
-static int omap_mcbsp_clk_enable(struct clk *clk)
-{
- struct mcbsp_internal_clk *mclk = container_of(clk,
- struct mcbsp_internal_clk, clk);
- int i;
-
- for (i = 0; i < mclk->n_childs; i++)
- clk_enable(mclk->childs[i]);
- return 0;
-}
-
-static void omap_mcbsp_clk_disable(struct clk *clk)
-{
- struct mcbsp_internal_clk *mclk = container_of(clk,
- struct mcbsp_internal_clk, clk);
- int i;
-
- for (i = 0; i < mclk->n_childs; i++)
- clk_disable(mclk->childs[i]);
-}
-
-static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
- {
- .clk = {
- .name = "mcbsp_clk",
- .id = 1,
- .enable = omap_mcbsp_clk_enable,
- .disable = omap_mcbsp_clk_disable,
- },
- },
- {
- .clk = {
- .name = "mcbsp_clk",
- .id = 2,
- .enable = omap_mcbsp_clk_enable,
- .disable = omap_mcbsp_clk_disable,
- },
- },
- {
- .clk = {
- .name = "mcbsp_clk",
- .id = 3,
- .enable = omap_mcbsp_clk_enable,
- .disable = omap_mcbsp_clk_disable,
- },
- },
- {
- .clk = {
- .name = "mcbsp_clk",
- .id = 4,
- .enable = omap_mcbsp_clk_enable,
- .disable = omap_mcbsp_clk_disable,
- },
- },
- {
- .clk = {
- .name = "mcbsp_clk",
- .id = 5,
- .enable = omap_mcbsp_clk_enable,
- .disable = omap_mcbsp_clk_disable,
- },
- },
-};
-
-#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks)
-#else
-#define omap_mcbsp_clks_size 0
-static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
-static inline void omap_mcbsp_clk_init(struct clk *clk)
-{ }
-#endif
+const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
static void omap2_mcbsp2_mux_setup(void)
{
@@ -154,7 +57,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP24XX_MCBSP2_BASE,
@@ -163,7 +67,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
};
#define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata)
@@ -181,7 +86,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP24XX_MCBSP2_BASE,
@@ -190,7 +96,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP2430_MCBSP3_BASE,
@@ -199,7 +106,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP3_IRQ_RX,
.tx_irq = INT_24XX_MCBSP3_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP2430_MCBSP4_BASE,
@@ -208,7 +116,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP4_IRQ_RX,
.tx_irq = INT_24XX_MCBSP4_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP2430_MCBSP5_BASE,
@@ -217,7 +126,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP5_IRQ_RX,
.tx_irq = INT_24XX_MCBSP5_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
};
#define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata)
@@ -235,7 +145,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP34XX_MCBSP2_BASE,
@@ -244,7 +155,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP34XX_MCBSP3_BASE,
@@ -253,7 +165,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP3_IRQ_RX,
.tx_irq = INT_24XX_MCBSP3_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP34XX_MCBSP4_BASE,
@@ -262,7 +175,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP4_IRQ_RX,
.tx_irq = INT_24XX_MCBSP4_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
{
.phys_base = OMAP34XX_MCBSP5_BASE,
@@ -271,7 +185,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
.rx_irq = INT_24XX_MCBSP5_IRQ_RX,
.tx_irq = INT_24XX_MCBSP5_IRQ_TX,
.ops = &omap2_mcbsp_ops,
- .clk_name = "mcbsp_clk",
+ .clk_names = clk_names,
+ .num_clks = 2,
},
};
#define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata)
@@ -282,14 +197,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
static int __init omap2_mcbsp_init(void)
{
- int i;
-
- for (i = 0; i < omap_mcbsp_clks_size; i++) {
- /* Once we call clk_get inside init, we do not register it */
- omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
- clk_register(&omap_mcbsp_clks[i].clk);
- }
-
if (cpu_is_omap2420())
omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
if (cpu_is_omap2430())
diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S
index 43336b93b21c..bf9e96105e11 100644
--- a/arch/arm/mach-omap2/sleep24xx.S
+++ b/arch/arm/mach-omap2/sleep24xx.S
@@ -93,9 +93,8 @@ ENTRY(omap24xx_cpu_suspend)
orr r4, r4, #0x40 @ enable self refresh on idle req
mov r5, #0x2000 @ set delay (DPLL relock + DLL relock)
str r4, [r2] @ make it so
- mov r2, #0
nop
- mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt
+ mcr p15, 0, r3, c7, c0, 4 @ wait for interrupt
nop
loop:
subs r5, r5, #0x1 @ awake, wait just a bit
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 589393bedade..9fc13a2cc3f4 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -118,9 +118,10 @@ static void __init omap2_gp_clockevent_init(void)
clockevent_gpt.max_delta_ns =
clockevent_delta2ns(0xffffffff, &clockevent_gpt);
clockevent_gpt.min_delta_ns =
- clockevent_delta2ns(1, &clockevent_gpt);
+ clockevent_delta2ns(3, &clockevent_gpt);
+ /* Timer internal resynch latency. */
- clockevent_gpt.cpumask = cpumask_of_cpu(0);
+ clockevent_gpt.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_gpt);
}
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index a7b7d77b1b09..d0a785a3b880 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/mbus.h>
+#include <asm/irq.h>
#include <asm/mach/pci.h>
#include <plat/pcie.h>
#include "common.h"
diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
index 015cc21d5f55..f219914f5b29 100644
--- a/arch/arm/mach-pnx4008/gpio.c
+++ b/arch/arm/mach-pnx4008/gpio.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <mach/hardware.h>
#include <mach/platform.h>
#include <mach/gpio.h>
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c
index 87c093286ff9..f3fea29c00d3 100644
--- a/arch/arm/mach-pnx4008/i2c.c
+++ b/arch/arm/mach-pnx4008/i2c.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/err.h>
#include <mach/platform.h>
+#include <mach/irqs.h>
#include <mach/i2c.h>
static int set_clock_run(struct platform_device *pdev)
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index c5e28a46b292..a8d91b6c136b 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -27,6 +27,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/spi/corgi_lcd.h>
+#include <linux/mtd/sharpsl.h>
#include <video/w100fb.h>
#include <asm/setup.h>
@@ -542,6 +543,55 @@ err_free_1:
static inline void corgi_init_spi(void) {}
#endif
+static struct mtd_partition sharpsl_nand_partitions[] = {
+ {
+ .name = "System Area",
+ .offset = 0,
+ .size = 7 * 1024 * 1024,
+ },
+ {
+ .name = "Root Filesystem",
+ .offset = 7 * 1024 * 1024,
+ .size = 25 * 1024 * 1024,
+ },
+ {
+ .name = "Home Filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr sharpsl_bbt = {
+ .options = 0,
+ .offs = 4,
+ .len = 2,
+ .pattern = scan_ff_pattern
+};
+
+static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = {
+ .badblock_pattern = &sharpsl_bbt,
+ .partitions = sharpsl_nand_partitions,
+ .nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions),
+};
+
+static struct resource sharpsl_nand_resources[] = {
+ {
+ .start = 0x0C000000,
+ .end = 0x0C000FFF,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device sharpsl_nand_device = {
+ .name = "sharpsl-nand",
+ .id = -1,
+ .resource = sharpsl_nand_resources,
+ .num_resources = ARRAY_SIZE(sharpsl_nand_resources),
+ .dev.platform_data = &sharpsl_nand_platform_data,
+};
+
static struct mtd_partition sharpsl_rom_parts[] = {
{
.name ="Boot PROM Filesystem",
@@ -577,6 +627,7 @@ static struct platform_device *devices[] __initdata = {
&corgifb_device,
&corgikbd_device,
&corgiled_device,
+ &sharpsl_nand_device,
&sharpsl_rom_device,
};
@@ -617,6 +668,9 @@ static void __init corgi_init(void)
platform_scoop_config = &corgi_pcmcia_config;
+ if (machine_is_husky())
+ sharpsl_nand_partitions[1].size = 53 * 1024 * 1024;
+
platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-pxa/e350.c b/arch/arm/mach-pxa/e350.c
index 251129391d7d..edcd9d5ce545 100644
--- a/arch/arm/mach-pxa/e350.c
+++ b/arch/arm/mach-pxa/e350.c
@@ -20,6 +20,7 @@
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
+#include <mach/irqs.h>
#include <mach/mfp-pxa25x.h>
#include <mach/pxa-regs.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-pxa/e400.c b/arch/arm/mach-pxa/e400.c
index bed0336aca3d..77bb8e2c48c0 100644
--- a/arch/arm/mach-pxa/e400.c
+++ b/arch/arm/mach-pxa/e400.c
@@ -28,6 +28,7 @@
#include <mach/eseries-gpio.h>
#include <mach/pxafb.h>
#include <mach/udc.h>
+#include <mach/irqs.h>
#include "generic.h"
#include "eseries.h"
diff --git a/arch/arm/mach-pxa/e740.c b/arch/arm/mach-pxa/e740.c
index b00d670b2ea6..6d48e00f4f0b 100644
--- a/arch/arm/mach-pxa/e740.c
+++ b/arch/arm/mach-pxa/e740.c
@@ -30,6 +30,7 @@
#include <mach/eseries-gpio.h>
#include <mach/udc.h>
#include <mach/irda.h>
+#include <mach/irqs.h>
#include "generic.h"
#include "eseries.h"
diff --git a/arch/arm/mach-pxa/e750.c b/arch/arm/mach-pxa/e750.c
index 84d7c1aac58d..be1ab8edb973 100644
--- a/arch/arm/mach-pxa/e750.c
+++ b/arch/arm/mach-pxa/e750.c
@@ -29,6 +29,7 @@
#include <mach/eseries-gpio.h>
#include <mach/udc.h>
#include <mach/irda.h>
+#include <mach/irqs.h>
#include "generic.h"
#include "eseries.h"
@@ -105,6 +106,57 @@ static struct platform_device e750_fb_device = {
.resource = e750_fb_resources,
};
+/* -------------------- e750 MFP parameters -------------------- */
+
+static unsigned long e750_pin_config[] __initdata = {
+ /* Chip selects */
+ GPIO15_nCS_1, /* CS1 - Flash */
+ GPIO79_nCS_3, /* CS3 - IMAGEON */
+ GPIO80_nCS_4, /* CS4 - TMIO */
+
+ /* Clocks */
+ GPIO11_3_6MHz,
+
+ /* BTUART */
+ GPIO42_BTUART_RXD,
+ GPIO43_BTUART_TXD,
+ GPIO44_BTUART_CTS,
+
+ /* TMIO controller */
+ GPIO19_GPIO, /* t7l66xb #PCLR */
+ GPIO45_GPIO, /* t7l66xb #SUSPEND (NOT BTUART!) */
+
+ /* UDC */
+ GPIO13_GPIO,
+ GPIO3_GPIO,
+
+ /* IrDA */
+ GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
+
+ /* PC Card */
+ GPIO8_GPIO, /* CD0 */
+ GPIO44_GPIO, /* CD1 */
+ GPIO11_GPIO, /* IRQ0 */
+ GPIO6_GPIO, /* IRQ1 */
+ GPIO27_GPIO, /* RST0 */
+ GPIO24_GPIO, /* RST1 */
+ GPIO20_GPIO, /* PWR0 */
+ GPIO23_GPIO, /* PWR1 */
+ GPIO48_nPOE,
+ GPIO49_nPWE,
+ GPIO50_nPIOR,
+ GPIO51_nPIOW,
+ GPIO52_nPCE_1,
+ GPIO53_nPCE_2,
+ GPIO54_nPSKTSEL,
+ GPIO55_nPREG,
+ GPIO56_nPWAIT,
+ GPIO57_nIOIS16,
+
+ /* wakeup */
+ GPIO0_GPIO | WAKEUP_ON_EDGE_RISE,
+};
+
/* ----------------- e750 tc6393xb parameters ------------------ */
static struct tc6393xb_platform_data e750_tc6393xb_info = {
@@ -137,6 +189,7 @@ static struct platform_device *devices[] __initdata = {
static void __init e750_init(void)
{
+ pxa2xx_mfp_config(ARRAY_AND_SIZE(e750_pin_config));
clk_add_alias("CLK_CK3P6MI", &e750_tc6393xb_device.dev,
"GPIO11_CLK", NULL),
eseries_get_tmio_gpios();
diff --git a/arch/arm/mach-pxa/e800.c b/arch/arm/mach-pxa/e800.c
index 9a86a426f924..cc9b1293e866 100644
--- a/arch/arm/mach-pxa/e800.c
+++ b/arch/arm/mach-pxa/e800.c
@@ -28,6 +28,7 @@
#include <mach/hardware.h>
#include <mach/eseries-gpio.h>
#include <mach/udc.h>
+#include <mach/irqs.h>
#include "generic.h"
#include "eseries.h"
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
index b1fcd10ab6c6..bcf3fb2c4b3a 100644
--- a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
@@ -193,10 +193,8 @@
#define CKEN_MINI_IM 48 /* < Mini-IM */
#define CKEN_MINI_LCD 49 /* < Mini LCD */
-#if defined(CONFIG_CPU_PXA310)
#define CKEN_MMC3 5 /* < MMC3 Clock Enable */
#define CKEN_MVED 43 /* < MVED clock enable */
-#endif
/* Note: GCU clock enable bit differs on PXA300/PXA310 and PXA320 */
#define PXA300_CKEN_GRAPHICS 42 /* Graphics controller clock enable */
diff --git a/arch/arm/mach-pxa/include/mach/pxa930_rotary.h b/arch/arm/mach-pxa/include/mach/pxa930_rotary.h
new file mode 100644
index 000000000000..053587caffdd
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa930_rotary.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_ARCH_PXA930_ROTARY_H
+#define __ASM_ARCH_PXA930_ROTARY_H
+
+/* NOTE:
+ *
+ * rotary can be either interpreted as a ralative input event (e.g.
+ * REL_WHEEL or REL_HWHEEL) or a specific key event (e.g. UP/DOWN
+ * or LEFT/RIGHT), depending on if up_key & down_key are assigned
+ * or rel_code is assigned a non-zero value. When all are non-zero,
+ * up_key and down_key will be preferred.
+ */
+struct pxa930_rotary_platform_data {
+ int up_key;
+ int down_key;
+ int rel_code;
+};
+
+void __init pxa930_set_rotarykey_info(struct pxa930_rotary_platform_data *info);
+
+#endif /* __ASM_ARCH_PXA930_ROTARY_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa930_trkball.h b/arch/arm/mach-pxa/include/mach/pxa930_trkball.h
new file mode 100644
index 000000000000..5e0789bc4729
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/pxa930_trkball.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_ARCH_PXA930_TRKBALL_H
+#define __ASM_ARCH_PXA930_TRKBALL_H
+
+struct pxa930_trkball_platform_data {
+ int x_filter;
+ int y_filter;
+};
+
+#endif /* __ASM_ARCH_PXA930_TRKBALL_H */
+
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index ae88855bf974..f9093beba752 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -24,6 +24,7 @@
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
+#include <linux/mtd/sharpsl.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -414,6 +415,55 @@ static struct pxafb_mach_info poodle_fb_info = {
.lcd_conn = LCD_COLOR_TFT_16BPP,
};
+static struct mtd_partition sharpsl_nand_partitions[] = {
+ {
+ .name = "System Area",
+ .offset = 0,
+ .size = 7 * 1024 * 1024,
+ },
+ {
+ .name = "Root Filesystem",
+ .offset = 7 * 1024 * 1024,
+ .size = 22 * 1024 * 1024,
+ },
+ {
+ .name = "Home Filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr sharpsl_bbt = {
+ .options = 0,
+ .offs = 4,
+ .len = 2,
+ .pattern = scan_ff_pattern
+};
+
+static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = {
+ .badblock_pattern = &sharpsl_bbt,
+ .partitions = sharpsl_nand_partitions,
+ .nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions),
+};
+
+static struct resource sharpsl_nand_resources[] = {
+ {
+ .start = 0x0C000000,
+ .end = 0x0C000FFF,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device sharpsl_nand_device = {
+ .name = "sharpsl-nand",
+ .id = -1,
+ .resource = sharpsl_nand_resources,
+ .num_resources = ARRAY_SIZE(sharpsl_nand_resources),
+ .dev.platform_data = &sharpsl_nand_platform_data,
+};
+
static struct mtd_partition sharpsl_rom_parts[] = {
{
.name ="Boot PROM Filesystem",
@@ -447,6 +497,7 @@ static struct platform_device sharpsl_rom_device = {
static struct platform_device *devices[] __initdata = {
&poodle_locomo_device,
&poodle_scoop_device,
+ &sharpsl_nand_device,
&sharpsl_rom_device,
};
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 7299d87a1cb3..6d447c9ce8ab 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -31,6 +31,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/spi/corgi_lcd.h>
+#include <linux/mtd/sharpsl.h>
#include <asm/setup.h>
#include <asm/memory.h>
@@ -613,6 +614,54 @@ static struct pxafb_mach_info spitz_pxafb_info = {
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_ALTERNATE_MAPPING,
};
+static struct mtd_partition sharpsl_nand_partitions[] = {
+ {
+ .name = "System Area",
+ .offset = 0,
+ .size = 7 * 1024 * 1024,
+ },
+ {
+ .name = "Root Filesystem",
+ .offset = 7 * 1024 * 1024,
+ },
+ {
+ .name = "Home Filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr sharpsl_bbt = {
+ .options = 0,
+ .offs = 4,
+ .len = 2,
+ .pattern = scan_ff_pattern
+};
+
+static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = {
+ .badblock_pattern = &sharpsl_bbt,
+ .partitions = sharpsl_nand_partitions,
+ .nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions),
+};
+
+static struct resource sharpsl_nand_resources[] = {
+ {
+ .start = 0x0C000000,
+ .end = 0x0C000FFF,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device sharpsl_nand_device = {
+ .name = "sharpsl-nand",
+ .id = -1,
+ .resource = sharpsl_nand_resources,
+ .num_resources = ARRAY_SIZE(sharpsl_nand_resources),
+ .dev.platform_data = &sharpsl_nand_platform_data,
+};
+
static struct mtd_partition sharpsl_rom_parts[] = {
{
@@ -648,6 +697,7 @@ static struct platform_device *devices[] __initdata = {
&spitzscoop_device,
&spitzkbd_device,
&spitzled_device,
+ &sharpsl_nand_device,
&sharpsl_rom_device,
};
@@ -671,6 +721,14 @@ static void __init common_init(void)
pm_power_off = spitz_poweroff;
arm_pm_restart = spitz_restart;
+ if (machine_is_spitz()) {
+ sharpsl_nand_partitions[1].size = 5 * 1024 * 1024;
+ } else if (machine_is_akita()) {
+ sharpsl_nand_partitions[1].size = 58 * 1024 * 1024;
+ } else if (machine_is_borzoi()) {
+ sharpsl_nand_partitions[1].size = 32 * 1024 * 1024;
+ }
+
PMCR = 0x00;
/* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
@@ -715,10 +773,29 @@ static struct i2c_board_info akita_i2c_board_info[] = {
},
};
+static struct nand_bbt_descr sharpsl_akita_bbt = {
+ .options = 0,
+ .offs = 4,
+ .len = 1,
+ .pattern = scan_ff_pattern
+};
+
+static struct nand_ecclayout akita_oobinfo = {
+ .eccbytes = 24,
+ .eccpos = {
+ 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
+ 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
+ 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
+ .oobfree = {{0x08, 0x09}}
+};
+
static void __init akita_init(void)
{
spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode;
+ sharpsl_nand_platform_data.badblock_pattern = &sharpsl_akita_bbt;
+ sharpsl_nand_platform_data.ecc_layout = &akita_oobinfo;
+
/* We just pretend the second element of the array doesn't exist */
spitz_pcmcia_config.num_devs = 1;
platform_scoop_config = &spitz_pcmcia_config;
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 001624158519..95656a72268d 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -122,7 +122,6 @@ static struct clock_event_device ckevt_pxa_osmr0 = {
.features = CLOCK_EVT_FEAT_ONESHOT,
.shift = 32,
.rating = 200,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = pxa_osmr0_set_next_event,
.set_mode = pxa_osmr0_set_mode,
};
@@ -163,6 +162,7 @@ static void __init pxa_timer_init(void)
clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
ckevt_pxa_osmr0.min_delta_ns =
clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1;
+ ckevt_pxa_osmr0.cpumask = cpumask_of(0);
cksrc_pxa_oscr0.mult =
clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift);
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 5f1d55963ced..bd2aa4f16141 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -624,7 +624,7 @@ static struct clock_event_device timer0_clockevent = {
.set_mode = timer_set_mode,
.set_next_event = timer_set_next_event,
.rating = 300,
- .cpumask = CPU_MASK_ALL,
+ .cpumask = cpu_all_mask,
};
static void __init realview_clockevents_init(unsigned int timer_irq)
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index 63be2abdc19c..44269b162d49 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -31,7 +31,7 @@
static struct amba_device name##_device = { \
.dev = { \
.coherent_dma_mask = ~0, \
- .bus_id = busid, \
+ .init_name = busid, \
.platform_data = plat, \
}, \
.res = { \
diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c
index 9019ef2e5611..67d6d9cc68b2 100644
--- a/arch/arm/mach-realview/localtimer.c
+++ b/arch/arm/mach-realview/localtimer.c
@@ -154,7 +154,7 @@ void __cpuinit local_timer_setup(void)
clk->set_mode = local_timer_set_mode;
clk->set_next_event = local_timer_set_next_event;
clk->irq = IRQ_LOCALTIMER;
- clk->cpumask = cpumask_of_cpu(cpu);
+ clk->cpumask = cpumask_of(cpu);
clk->shift = 20;
clk->mult = div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift);
clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
@@ -193,7 +193,7 @@ void __cpuinit local_timer_setup(void)
clk->rating = 200;
clk->set_mode = dummy_timer_set_mode;
clk->broadcast = smp_timer_broadcast;
- clk->cpumask = cpumask_of_cpu(cpu);
+ clk->cpumask = cpumask_of(cpu);
clockevents_register_device(clk);
}
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 8fce85f33033..ea3c75595fa9 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/jiffies.h>
#include <linux/smp.h>
#include <linux/io.h>
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h
index e0349af8a483..00476a573bbe 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio.h
@@ -14,6 +14,7 @@
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
+#define gpio_to_irq __gpio_to_irq
/* some boards require extra gpio capacity to support external
* devices that need GPIO.
diff --git a/arch/arm/mach-s3c2410/include/mach/irqs.h b/arch/arm/mach-s3c2410/include/mach/irqs.h
index 9565903d490b..49efce8cd4a7 100644
--- a/arch/arm/mach-s3c2410/include/mach/irqs.h
+++ b/arch/arm/mach-s3c2410/include/mach/irqs.h
@@ -12,10 +12,6 @@
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H __FILE__
-#ifndef __ASM_ARM_IRQ_H
-#error "Do not include this directly, instead #include <asm/irq.h>"
-#endif
-
/* we keep the first set of CPU IRQs out of the range of
* the ISA space, so that the PC104 has them to itself
* and we don't end up having to do horrible things to the
diff --git a/arch/arm/mach-s3c2410/include/mach/spi.h b/arch/arm/mach-s3c2410/include/mach/spi.h
index 774f3adfe8ad..1d300fb112b1 100644
--- a/arch/arm/mach-s3c2410/include/mach/spi.h
+++ b/arch/arm/mach-s3c2410/include/mach/spi.h
@@ -14,7 +14,7 @@
#define __ASM_ARCH_SPI_H __FILE__
struct s3c2410_spi_info {
- unsigned long pin_cs; /* simple gpio cs */
+ int pin_cs; /* simple gpio cs */
unsigned int num_cs; /* total chipselects */
int bus_num; /* bus number to use. */
diff --git a/arch/arm/mach-s3c2440/mach-at2440evb.c b/arch/arm/mach-s3c2440/mach-at2440evb.c
index 0a6d0a5d961b..315c42e31278 100644
--- a/arch/arm/mach-s3c2440/mach-at2440evb.c
+++ b/arch/arm/mach-s3c2440/mach-at2440evb.c
@@ -47,7 +47,7 @@
#include <plat/clock.h>
#include <plat/devs.h>
#include <plat/cpu.h>
-#include <asm/plat-s3c24xx/mci.h>
+#include <plat/mci.h>
static struct map_desc at2440evb_iodesc[] __initdata = {
/* Nothing here */
diff --git a/arch/arm/mach-s3c6400/include/mach/irqs.h b/arch/arm/mach-s3c6400/include/mach/irqs.h
index b38c47cffc28..4c97f9a4370b 100644
--- a/arch/arm/mach-s3c6400/include/mach/irqs.h
+++ b/arch/arm/mach-s3c6400/include/mach/irqs.h
@@ -11,10 +11,6 @@
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H __FILE__
-#ifndef __ASM_ARM_IRQ_H
-#error "Do not include this directly, instead #include <asm/irq.h>"
-#endif
-
#include <plat/irqs.h>
#endif /* __ASM_ARCH_IRQ_H */
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index c1fbd5b5f9c4..23cfdd593954 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -289,7 +289,7 @@ static struct platform_device sa11x0pcmcia_device = {
};
static struct platform_device sa11x0mtd_device = {
- .name = "flash",
+ .name = "sa1100-mtd",
.id = -1,
};
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 8c5e727f3b75..711c0295c66f 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -73,7 +73,6 @@ static struct clock_event_device ckevt_sa1100_osmr0 = {
.features = CLOCK_EVT_FEAT_ONESHOT,
.shift = 32,
.rating = 200,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = sa1100_osmr0_set_next_event,
.set_mode = sa1100_osmr0_set_mode,
};
@@ -110,6 +109,7 @@ static void __init sa1100_timer_init(void)
clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0);
ckevt_sa1100_osmr0.min_delta_ns =
clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1;
+ ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
cksrc_sa1100_oscr.mult =
clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_sa1100_oscr.shift);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index df25aa138509..1c43494f5c42 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -1005,7 +1005,7 @@ static void __init versatile_timer_init(void)
timer0_clockevent.min_delta_ns =
clockevent_delta2ns(0xf, &timer0_clockevent);
- timer0_clockevent.cpumask = cpumask_of_cpu(0);
+ timer0_clockevent.cpumask = cpumask_of(0);
clockevents_register_device(&timer0_clockevent);
}
diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h
index afcaa858eb1f..9d39886a8351 100644
--- a/arch/arm/mach-versatile/core.h
+++ b/arch/arm/mach-versatile/core.h
@@ -34,7 +34,7 @@ extern unsigned int mmc_status(struct device *dev);
static struct amba_device name##_device = { \
.dev = { \
.coherent_dma_mask = ~0, \
- .bus_id = busid, \
+ .init_name = busid, \
.platform_data = plat, \
}, \
.res = { \
diff --git a/arch/arm/mach-w90x900/mach-w90p910evb.c b/arch/arm/mach-w90x900/mach-w90p910evb.c
index 9307a2475438..9ebc93f48530 100644
--- a/arch/arm/mach-w90x900/mach-w90p910evb.c
+++ b/arch/arm/mach-w90x900/mach-w90p910evb.c
@@ -29,6 +29,7 @@
#include <asm/mach-types.h>
#include <mach/regs-serial.h>
+#include <mach/map.h>
#include "cpu.h"
diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c
index 3a69e381f316..bcc838f6b393 100644
--- a/arch/arm/mach-w90x900/time.c
+++ b/arch/arm/mach-w90x900/time.c
@@ -28,7 +28,6 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
-#include <mach/system.h>
#include <mach/map.h>
#include <mach/regs-timer.h>
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index bdb5fd983b15..1601698b9800 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -68,7 +68,7 @@ mc_copy_user_page(void *from, void *to)
: "r" (from), "r" (to), "I" (PAGE_SIZE / 64));
}
-void v4_mc_copy_user_highpage(struct page *from, struct page *to,
+void v4_mc_copy_user_highpage(struct page *to, struct page *from,
unsigned long vaddr)
{
void *kto = kmap_atomic(to, KM_USER1);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 67960017dc8f..310e479309ef 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -71,7 +71,7 @@ static DEFINE_SPINLOCK(consistent_lock);
* the amount of RAM found at boot time.) I would imagine that get_vm_area()
* would have to initialise this each time prior to calling vm_region_alloc().
*/
-struct vm_region {
+struct arm_vm_region {
struct list_head vm_list;
unsigned long vm_start;
unsigned long vm_end;
@@ -79,20 +79,20 @@ struct vm_region {
int vm_active;
};
-static struct vm_region consistent_head = {
+static struct arm_vm_region consistent_head = {
.vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
.vm_start = CONSISTENT_BASE,
.vm_end = CONSISTENT_END,
};
-static struct vm_region *
-vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
+static struct arm_vm_region *
+arm_vm_region_alloc(struct arm_vm_region *head, size_t size, gfp_t gfp)
{
unsigned long addr = head->vm_start, end = head->vm_end - size;
unsigned long flags;
- struct vm_region *c, *new;
+ struct arm_vm_region *c, *new;
- new = kmalloc(sizeof(struct vm_region), gfp);
+ new = kmalloc(sizeof(struct arm_vm_region), gfp);
if (!new)
goto out;
@@ -127,9 +127,9 @@ vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
return NULL;
}
-static struct vm_region *vm_region_find(struct vm_region *head, unsigned long addr)
+static struct arm_vm_region *arm_vm_region_find(struct arm_vm_region *head, unsigned long addr)
{
- struct vm_region *c;
+ struct arm_vm_region *c;
list_for_each_entry(c, &head->vm_list, vm_list) {
if (c->vm_active && c->vm_start == addr)
@@ -149,7 +149,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
pgprot_t prot)
{
struct page *page;
- struct vm_region *c;
+ struct arm_vm_region *c;
unsigned long order;
u64 mask = ISA_DMA_THRESHOLD, limit;
@@ -214,7 +214,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
/*
* Allocate a virtual address in the consistent mapping region.
*/
- c = vm_region_alloc(&consistent_head, size,
+ c = arm_vm_region_alloc(&consistent_head, size,
gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
if (c) {
pte_t *pte;
@@ -311,13 +311,13 @@ static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size)
{
unsigned long flags, user_size, kern_size;
- struct vm_region *c;
+ struct arm_vm_region *c;
int ret = -ENXIO;
user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
spin_lock_irqsave(&consistent_lock, flags);
- c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
+ c = arm_vm_region_find(&consistent_head, (unsigned long)cpu_addr);
spin_unlock_irqrestore(&consistent_lock, flags);
if (c) {
@@ -359,7 +359,7 @@ EXPORT_SYMBOL(dma_mmap_writecombine);
*/
void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
{
- struct vm_region *c;
+ struct arm_vm_region *c;
unsigned long flags, addr;
pte_t *ptep;
int idx;
@@ -378,7 +378,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
size = PAGE_ALIGN(size);
spin_lock_irqsave(&consistent_lock, flags);
- c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
+ c = arm_vm_region_find(&consistent_head, (unsigned long)cpu_addr);
if (!c)
goto no_area;
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 81d0b8772de3..bc0099d5ae85 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -66,7 +66,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
* fault (ie, is old), we can safely ignore any issues.
*/
if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) {
- flush_cache_page(vma, address, pte_pfn(entry));
+ unsigned long pfn = pte_pfn(entry);
+ flush_cache_page(vma, address, pfn);
+ outer_flush_range((pfn << PAGE_SHIFT),
+ (pfn << PAGE_SHIFT) + PAGE_SIZE);
pte_val(entry) &= ~L_PTE_MT_MASK;
pte_val(entry) |= shared_pte_mask;
set_pte_at(vma->vm_mm, address, pte, entry);
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 18373f73f2fc..9f88dd3be601 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -138,7 +138,7 @@ void __check_kvm_seq(struct mm_struct *mm)
*/
static void unmap_area_sections(unsigned long virt, unsigned long size)
{
- unsigned long addr = virt, end = virt + (size & ~SZ_1M);
+ unsigned long addr = virt, end = virt + (size & ~(SZ_1M - 1));
pgd_t *pgd;
flush_cache_vunmap(addr, end);
@@ -337,10 +337,7 @@ void __iounmap(volatile void __iomem *io_addr)
void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
#ifndef CONFIG_SMP
struct vm_struct **p, *tmp;
-#endif
- unsigned int section_mapping = 0;
-#ifndef CONFIG_SMP
/*
* If this is a section based mapping we need to handle it
* specially as the VM subsystem does not know how to handle
@@ -352,11 +349,8 @@ void __iounmap(volatile void __iomem *io_addr)
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
if (tmp->flags & VM_ARM_SECTION_MAPPING) {
- *p = tmp->next;
unmap_area_sections((unsigned long)tmp->addr,
tmp->size);
- kfree(tmp);
- section_mapping = 1;
}
break;
}
@@ -364,7 +358,6 @@ void __iounmap(volatile void __iomem *io_addr)
write_unlock(&vmlist_lock);
#endif
- if (!section_mapping)
- vunmap(addr);
+ vunmap(addr);
}
EXPORT_SYMBOL(__iounmap);
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 4ad3bf291ad3..195e48edd8c2 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all);
EXPORT_SYMBOL(__cpuc_flush_user_all);
EXPORT_SYMBOL(__cpuc_flush_user_range);
EXPORT_SYMBOL(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL(dmac_inv_range); /* because of flush_ioremap_region() */
#else
EXPORT_SYMBOL(cpu_cache);
#endif
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
index 4de366e8b4c5..6d6bd5899240 100644
--- a/arch/arm/oprofile/op_model_mpcore.c
+++ b/arch/arm/oprofile/op_model_mpcore.c
@@ -260,10 +260,10 @@ static void em_stop(void)
static void em_route_irq(int irq, unsigned int cpu)
{
struct irq_desc *desc = irq_desc + irq;
- cpumask_t mask = cpumask_of_cpu(cpu);
+ const struct cpumask *mask = cpumask_of(cpu);
spin_lock_irq(&desc->lock);
- desc->affinity = mask;
+ desc->affinity = *mask;
desc->chip->set_affinity(irq, mask);
spin_unlock_irq(&desc->lock);
}
diff --git a/arch/arm/plat-mxc/include/mach/ipu.h b/arch/arm/plat-mxc/include/mach/ipu.h
new file mode 100644
index 000000000000..a9221f1cc1a0
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/ipu.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * Copyright (C) 2005-2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _IPU_H_
+#define _IPU_H_
+
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+
+/* IPU DMA Controller channel definitions. */
+enum ipu_channel {
+ IDMAC_IC_0 = 0, /* IC (encoding task) to memory */
+ IDMAC_IC_1 = 1, /* IC (viewfinder task) to memory */
+ IDMAC_ADC_0 = 1,
+ IDMAC_IC_2 = 2,
+ IDMAC_ADC_1 = 2,
+ IDMAC_IC_3 = 3,
+ IDMAC_IC_4 = 4,
+ IDMAC_IC_5 = 5,
+ IDMAC_IC_6 = 6,
+ IDMAC_IC_7 = 7, /* IC (sensor data) to memory */
+ IDMAC_IC_8 = 8,
+ IDMAC_IC_9 = 9,
+ IDMAC_IC_10 = 10,
+ IDMAC_IC_11 = 11,
+ IDMAC_IC_12 = 12,
+ IDMAC_IC_13 = 13,
+ IDMAC_SDC_0 = 14, /* Background synchronous display data */
+ IDMAC_SDC_1 = 15, /* Foreground data (overlay) */
+ IDMAC_SDC_2 = 16,
+ IDMAC_SDC_3 = 17,
+ IDMAC_ADC_2 = 18,
+ IDMAC_ADC_3 = 19,
+ IDMAC_ADC_4 = 20,
+ IDMAC_ADC_5 = 21,
+ IDMAC_ADC_6 = 22,
+ IDMAC_ADC_7 = 23,
+ IDMAC_PF_0 = 24,
+ IDMAC_PF_1 = 25,
+ IDMAC_PF_2 = 26,
+ IDMAC_PF_3 = 27,
+ IDMAC_PF_4 = 28,
+ IDMAC_PF_5 = 29,
+ IDMAC_PF_6 = 30,
+ IDMAC_PF_7 = 31,
+};
+
+/* Order significant! */
+enum ipu_channel_status {
+ IPU_CHANNEL_FREE,
+ IPU_CHANNEL_INITIALIZED,
+ IPU_CHANNEL_READY,
+ IPU_CHANNEL_ENABLED,
+};
+
+#define IPU_CHANNELS_NUM 32
+
+enum pixel_fmt {
+ /* 1 byte */
+ IPU_PIX_FMT_GENERIC,
+ IPU_PIX_FMT_RGB332,
+ IPU_PIX_FMT_YUV420P,
+ IPU_PIX_FMT_YUV422P,
+ IPU_PIX_FMT_YUV420P2,
+ IPU_PIX_FMT_YVU422P,
+ /* 2 bytes */
+ IPU_PIX_FMT_RGB565,
+ IPU_PIX_FMT_RGB666,
+ IPU_PIX_FMT_BGR666,
+ IPU_PIX_FMT_YUYV,
+ IPU_PIX_FMT_UYVY,
+ /* 3 bytes */
+ IPU_PIX_FMT_RGB24,
+ IPU_PIX_FMT_BGR24,
+ /* 4 bytes */
+ IPU_PIX_FMT_GENERIC_32,
+ IPU_PIX_FMT_RGB32,
+ IPU_PIX_FMT_BGR32,
+ IPU_PIX_FMT_ABGR32,
+ IPU_PIX_FMT_BGRA32,
+ IPU_PIX_FMT_RGBA32,
+};
+
+enum ipu_color_space {
+ IPU_COLORSPACE_RGB,
+ IPU_COLORSPACE_YCBCR,
+ IPU_COLORSPACE_YUV
+};
+
+/*
+ * Enumeration of IPU rotation modes
+ */
+enum ipu_rotate_mode {
+ /* Note the enum values correspond to BAM value */
+ IPU_ROTATE_NONE = 0,
+ IPU_ROTATE_VERT_FLIP = 1,
+ IPU_ROTATE_HORIZ_FLIP = 2,
+ IPU_ROTATE_180 = 3,
+ IPU_ROTATE_90_RIGHT = 4,
+ IPU_ROTATE_90_RIGHT_VFLIP = 5,
+ IPU_ROTATE_90_RIGHT_HFLIP = 6,
+ IPU_ROTATE_90_LEFT = 7,
+};
+
+struct ipu_platform_data {
+ unsigned int irq_base;
+};
+
+/*
+ * Enumeration of DI ports for ADC.
+ */
+enum display_port {
+ DISP0,
+ DISP1,
+ DISP2,
+ DISP3
+};
+
+struct idmac_video_param {
+ unsigned short in_width;
+ unsigned short in_height;
+ uint32_t in_pixel_fmt;
+ unsigned short out_width;
+ unsigned short out_height;
+ uint32_t out_pixel_fmt;
+ unsigned short out_stride;
+ bool graphics_combine_en;
+ bool global_alpha_en;
+ bool key_color_en;
+ enum display_port disp;
+ unsigned short out_left;
+ unsigned short out_top;
+};
+
+/*
+ * Union of initialization parameters for a logical channel. So far only video
+ * parameters are used.
+ */
+union ipu_channel_param {
+ struct idmac_video_param video;
+};
+
+struct idmac_tx_desc {
+ struct dma_async_tx_descriptor txd;
+ struct scatterlist *sg; /* scatterlist for this */
+ unsigned int sg_len; /* tx-descriptor. */
+ struct list_head list;
+};
+
+struct idmac_channel {
+ struct dma_chan dma_chan;
+ dma_cookie_t completed; /* last completed cookie */
+ union ipu_channel_param params;
+ enum ipu_channel link; /* input channel, linked to the output */
+ enum ipu_channel_status status;
+ void *client; /* Only one client per channel */
+ unsigned int n_tx_desc;
+ struct idmac_tx_desc *desc; /* allocated tx-descriptors */
+ struct scatterlist *sg[2]; /* scatterlist elements in buffer-0 and -1 */
+ struct list_head free_list; /* free tx-descriptors */
+ struct list_head queue; /* queued tx-descriptors */
+ spinlock_t lock; /* protects sg[0,1], queue */
+ struct mutex chan_mutex; /* protects status, cookie, free_list */
+ bool sec_chan_en;
+ int active_buffer;
+ unsigned int eof_irq;
+ char eof_name[16]; /* EOF IRQ name for request_irq() */
+};
+
+#define to_tx_desc(tx) container_of(tx, struct idmac_tx_desc, txd)
+#define to_idmac_chan(c) container_of(c, struct idmac_channel, dma_chan)
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index e06d3cb0ee11..c02b8fc2d821 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -35,7 +35,15 @@
#define MXC_BOARD_IRQ_START (MXC_INTERNAL_IRQS + MXC_GPIO_IRQS)
#define MXC_BOARD_IRQS 16
-#define NR_IRQS (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS)
+#define MXC_IPU_IRQ_START (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS)
+
+#ifdef CONFIG_MX3_IPU_IRQS
+#define MX3_IPU_IRQS CONFIG_MX3_IPU_IRQS
+#else
+#define MX3_IPU_IRQS 0
+#endif
+
+#define NR_IRQS (MXC_IPU_IRQ_START + MX3_IPU_IRQS)
extern void imx_irq_set_priority(unsigned char irq, unsigned char prio);
diff --git a/arch/arm/plat-mxc/include/mach/mmc.h b/arch/arm/plat-mxc/include/mach/mmc.h
new file mode 100644
index 000000000000..de2128dada5c
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mmc.h
@@ -0,0 +1,36 @@
+#ifndef ASMARM_ARCH_MMC_H
+#define ASMARM_ARCH_MMC_H
+
+#include <linux/mmc/host.h>
+
+struct device;
+
+/* board specific SDHC data, optional.
+ * If not present, a writable card with 3,3V is assumed.
+ */
+struct imxmmc_platform_data {
+ /* Return values for the get_ro callback should be:
+ * 0 for a read/write card
+ * 1 for a read-only card
+ * -ENOSYS when not supported (equal to NULL callback)
+ * or a negative errno value when something bad happened
+ */
+ int (*get_ro)(struct device *);
+
+ /* board specific hook to (de)initialize the SD slot.
+ * The board code can call 'handler' on a card detection
+ * change giving data as argument.
+ */
+ int (*init)(struct device *dev, irq_handler_t handler, void *data);
+ void (*exit)(struct device *dev, void *data);
+
+ /* available voltages. If not given, assume
+ * MMC_VDD_32_33 | MMC_VDD_33_34
+ */
+ unsigned int ocr_avail;
+
+ /* adjust slot voltage */
+ void (*setpower)(struct device *, unsigned int vdd);
+};
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/mx3fb.h b/arch/arm/plat-mxc/include/mach/mx3fb.h
new file mode 100644
index 000000000000..e391a76ca87d
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/mx3fb.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_MX3FB_H__
+#define __ASM_ARCH_MX3FB_H__
+
+#include <linux/device.h>
+#include <linux/fb.h>
+
+/* Proprietary FB_SYNC_ flags */
+#define FB_SYNC_OE_ACT_HIGH 0x80000000
+#define FB_SYNC_CLK_INVERT 0x40000000
+#define FB_SYNC_DATA_INVERT 0x20000000
+#define FB_SYNC_CLK_IDLE_EN 0x10000000
+#define FB_SYNC_SHARP_MODE 0x08000000
+#define FB_SYNC_SWAP_RGB 0x04000000
+#define FB_SYNC_CLK_SEL_EN 0x02000000
+
+/**
+ * struct mx3fb_platform_data - mx3fb platform data
+ *
+ * @dma_dev: pointer to the dma-device, used for dma-slave connection
+ * @mode: pointer to a platform-provided per mxc_register_fb() videomode
+ */
+struct mx3fb_platform_data {
+ struct device *dma_dev;
+ const char *name;
+ const struct fb_videomode *mode;
+ int num_modes;
+};
+
+#endif
diff --git a/arch/arm/plat-mxc/include/mach/usb.h b/arch/arm/plat-mxc/include/mach/usb.h
new file mode 100644
index 000000000000..2dacb3086f1c
--- /dev/null
+++ b/arch/arm/plat-mxc/include/mach/usb.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.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.
+ */
+
+#ifndef __ASM_ARCH_MXC_USB
+#define __ASM_ARCH_MXC_USB
+
+struct imxusb_platform_data {
+ int (*init)(struct device *);
+ int (*exit)(struct device *);
+};
+
+#endif /* __ASM_ARCH_MXC_USB */
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c
index fd28f5194f71..758a1293bcfa 100644
--- a/arch/arm/plat-mxc/time.c
+++ b/arch/arm/plat-mxc/time.c
@@ -190,7 +190,7 @@ static int __init mxc_clockevent_init(void)
clockevent_mxc.min_delta_ns =
clockevent_delta2ns(0xff, &clockevent_mxc);
- clockevent_mxc.cpumask = cpumask_of_cpu(0);
+ clockevent_mxc.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_mxc);
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index ac15c23fd5da..208dbb121f47 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -200,14 +200,15 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
/*
* Register MMC devices. Called from mach-omap1 and mach-omap2 device init.
*/
-int __init omap_mmc_add(int id, unsigned long base, unsigned long size,
- unsigned int irq, struct omap_mmc_platform_data *data)
+int __init omap_mmc_add(const char *name, int id, unsigned long base,
+ unsigned long size, unsigned int irq,
+ struct omap_mmc_platform_data *data)
{
struct platform_device *pdev;
struct resource res[OMAP_MMC_NR_RES];
int ret;
- pdev = platform_device_alloc("mmci-omap", id);
+ pdev = platform_device_alloc(name, id);
if (!pdev)
return -ENOMEM;
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 692d2b495af3..47ec77af4ccb 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -278,14 +278,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
u32 val;
val = dma_read(CCR(lch));
- val &= ~(3 << 19);
- if (dma_trigger > 63)
- val |= 1 << 20;
- if (dma_trigger > 31)
- val |= 1 << 19;
- val &= ~(0x1f);
- val |= (dma_trigger & 0x1f);
+ /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */
+ val &= ~((3 << 19) | 0x1f);
+ val |= (dma_trigger & ~0x1f) << 14;
+ val |= dma_trigger & 0x1f;
if (sync_mode & OMAP_DMA_SYNC_FRAME)
val |= 1 << 5;
@@ -712,6 +709,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
chan->dev_name = dev_name;
chan->callback = callback;
chan->data = data;
+ chan->flags = 0;
#ifndef CONFIG_ARCH_OMAP1
if (cpu_class_is_omap2()) {
@@ -1891,11 +1889,11 @@ static int omap2_dma_handle_ch(int ch)
status = dma_read(CSR(ch));
}
+ dma_write(status, CSR(ch));
+
if (likely(dma_chan[ch].callback != NULL))
dma_chan[ch].callback(ch, status, dma_chan[ch].data);
- dma_write(status, CSR(ch));
-
return 0;
}
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index 07b6968a7d16..f856a90b264e 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -1789,6 +1789,8 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
/* FIXME for at least omap2, show pullup/pulldown state */
irqstat = irq_desc[irq].status;
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \
+ defined(CONFIG_ARCH_OMAP34XX)
if (is_in && ((bank->suspend_wakeup & mask)
|| irqstat & IRQ_TYPE_SENSE_MASK)) {
char *trigger = NULL;
@@ -1818,6 +1820,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
(bank->suspend_wakeup & mask)
? " wakeup" : "");
}
+#endif
seq_printf(s, "\n");
}
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 89a6ab0b7db8..467531edefd3 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -26,6 +26,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
+#include <mach/irqs.h>
#include <mach/mux.h>
#define OMAP_I2C_SIZE 0x3f
diff --git a/arch/arm/plat-omap/include/mach/aic23.h b/arch/arm/plat-omap/include/mach/aic23.h
deleted file mode 100644
index 5ccedac77526..000000000000
--- a/arch/arm/plat-omap/include/mach/aic23.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/aic23.h
- *
- * Hardware definitions for TI TLV320AIC23 audio codec
- *
- * Copyright (C) 2002 RidgeRun, Inc.
- * Author: Steve Johnson
- *
- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_AIC23_H
-#define __ASM_ARCH_AIC23_H
-
-// Codec TLV320AIC23
-#define LEFT_LINE_VOLUME_ADDR 0x00
-#define RIGHT_LINE_VOLUME_ADDR 0x01
-#define LEFT_CHANNEL_VOLUME_ADDR 0x02
-#define RIGHT_CHANNEL_VOLUME_ADDR 0x03
-#define ANALOG_AUDIO_CONTROL_ADDR 0x04
-#define DIGITAL_AUDIO_CONTROL_ADDR 0x05
-#define POWER_DOWN_CONTROL_ADDR 0x06
-#define DIGITAL_AUDIO_FORMAT_ADDR 0x07
-#define SAMPLE_RATE_CONTROL_ADDR 0x08
-#define DIGITAL_INTERFACE_ACT_ADDR 0x09
-#define RESET_CONTROL_ADDR 0x0F
-
-// Left (right) line input volume control register
-#define LRS_ENABLED 0x0100
-#define LIM_MUTED 0x0080
-#define LIV_DEFAULT 0x0017
-#define LIV_MAX 0x001f
-#define LIV_MIN 0x0000
-
-// Left (right) channel headphone volume control register
-#define LZC_ON 0x0080
-#define LHV_DEFAULT 0x0079
-#define LHV_MAX 0x007f
-#define LHV_MIN 0x0000
-
-// Analog audio path control register
-#define STA_REG(x) ((x)<<6)
-#define STE_ENABLED 0x0020
-#define DAC_SELECTED 0x0010
-#define BYPASS_ON 0x0008
-#define INSEL_MIC 0x0004
-#define MICM_MUTED 0x0002
-#define MICB_20DB 0x0001
-
-// Digital audio path control register
-#define DACM_MUTE 0x0008
-#define DEEMP_32K 0x0002
-#define DEEMP_44K 0x0004
-#define DEEMP_48K 0x0006
-#define ADCHP_ON 0x0001
-
-// Power control down register
-#define DEVICE_POWER_OFF 0x0080
-#define CLK_OFF 0x0040
-#define OSC_OFF 0x0020
-#define OUT_OFF 0x0010
-#define DAC_OFF 0x0008
-#define ADC_OFF 0x0004
-#define MIC_OFF 0x0002
-#define LINE_OFF 0x0001
-
-// Digital audio interface register
-#define MS_MASTER 0x0040
-#define LRSWAP_ON 0x0020
-#define LRP_ON 0x0010
-#define IWL_16 0x0000
-#define IWL_20 0x0004
-#define IWL_24 0x0008
-#define IWL_32 0x000C
-#define FOR_I2S 0x0002
-#define FOR_DSP 0x0003
-
-// Sample rate control register
-#define CLKOUT_HALF 0x0080
-#define CLKIN_HALF 0x0040
-#define BOSR_384fs 0x0002 // BOSR_272fs when in USB mode
-#define USB_CLK_ON 0x0001
-#define SR_MASK 0xf
-#define CLKOUT_SHIFT 7
-#define CLKIN_SHIFT 6
-#define SR_SHIFT 2
-#define BOSR_SHIFT 1
-
-// Digital interface register
-#define ACT_ON 0x0001
-
-#define TLV320AIC23ID1 (0x1a) // cs low
-#define TLV320AIC23ID2 (0x1b) // cs high
-
-void aic23_power_up(void);
-void aic23_power_down(void);
-
-#endif /* __ASM_ARCH_AIC23_H */
diff --git a/arch/arm/plat-omap/include/mach/board-h3.h b/arch/arm/plat-omap/include/mach/board-h3.h
index 14909dc7858a..1888326da7ea 100644
--- a/arch/arm/plat-omap/include/mach/board-h3.h
+++ b/arch/arm/plat-omap/include/mach/board-h3.h
@@ -30,7 +30,9 @@
/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
#define OMAP1710_ETHR_START 0x04000300
+#define H3_TPS_GPIO_BASE (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
+# define H3_TPS_GPIO_MMC_PWR_EN (H3_TPS_GPIO_BASE + 4)
+
extern void h3_mmc_init(void);
-extern void h3_mmc_slot_cover_handler(void *arg, int state);
#endif /* __ASM_ARCH_OMAP_H3_H */
diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h
index b2062f1175de..a8e1178a9468 100644
--- a/arch/arm/plat-omap/include/mach/cpu.h
+++ b/arch/arm/plat-omap/include/mach/cpu.h
@@ -339,6 +339,7 @@ IS_OMAP_TYPE(3430, 0x3430)
#define OMAP3430_REV_ES2_0 0x34301034
#define OMAP3430_REV_ES2_1 0x34302034
#define OMAP3430_REV_ES3_0 0x34303034
+#define OMAP3430_REV_ES3_1 0x34304034
/*
* omap_chip bits
diff --git a/arch/arm/plat-omap/include/mach/gpio.h b/arch/arm/plat-omap/include/mach/gpio.h
index 04e68e88f134..8d9dfe314387 100644
--- a/arch/arm/plat-omap/include/mach/gpio.h
+++ b/arch/arm/plat-omap/include/mach/gpio.h
@@ -87,16 +87,6 @@ extern void omap_set_gpio_debounce_time(int gpio, int enable);
#include <linux/errno.h>
#include <asm-generic/gpio.h>
-static inline int omap_request_gpio(int gpio)
-{
- return gpio_request(gpio, "FIXME");
-}
-
-static inline void omap_free_gpio(int gpio)
-{
- gpio_free(gpio);
-}
-
static inline int gpio_get_value(unsigned gpio)
{
return __gpio_get_value(gpio);
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h
index 6a0d1a0a24a7..113c2466c86a 100644
--- a/arch/arm/plat-omap/include/mach/mcbsp.h
+++ b/arch/arm/plat-omap/include/mach/mcbsp.h
@@ -87,6 +87,10 @@
#define OMAP_MCBSP_REG_XCERG 0x3A
#define OMAP_MCBSP_REG_XCERH 0x3C
+/* Dummy defines, these are not available on omap1 */
+#define OMAP_MCBSP_REG_XCCR 0x00
+#define OMAP_MCBSP_REG_RCCR 0x00
+
#define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
#define AUDIO_MCBSP_DATAREAD (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
@@ -231,11 +235,16 @@
#define XPBBLK(value) ((value)<<7) /* Bits 7:8 */
/*********************** McBSP XCCR bit definitions *************************/
+#define EXTCLKGATE 0x8000
+#define PPCONNECT 0x4000
+#define DXENDLY(value) ((value)<<12) /* Bits 12:13 */
+#define XFULL_CYCLE 0x0800
#define DILB 0x0020
#define XDMAEN 0x0008
#define XDISABLE 0x0001
/********************** McBSP RCCR bit definitions *************************/
+#define RFULL_CYCLE 0x0800
#define RDMAEN 0x0008
#define RDISABLE 0x0001
@@ -267,6 +276,8 @@ struct omap_mcbsp_reg_cfg {
u16 rcerh;
u16 xcerg;
u16 xcerh;
+ u16 xccr;
+ u16 rccr;
};
typedef enum {
@@ -333,7 +344,8 @@ struct omap_mcbsp_platform_data {
u8 dma_rx_sync, dma_tx_sync;
u16 rx_irq, tx_irq;
struct omap_mcbsp_ops *ops;
- char const *clk_name;
+ char const **clk_names;
+ int num_clks;
};
struct omap_mcbsp {
@@ -365,7 +377,8 @@ struct omap_mcbsp {
/* Protect the field .free, while checking if the mcbsp is in use */
spinlock_t lock;
struct omap_mcbsp_platform_data *pdata;
- struct clk *clk;
+ struct clk **clks;
+ int num_clks;
};
extern struct omap_mcbsp **mcbsp_ptr;
extern int omap_mcbsp_count;
diff --git a/arch/arm/plat-omap/include/mach/memory.h b/arch/arm/plat-omap/include/mach/memory.h
index 211c9f6619e9..d6b5ca6c7da2 100644
--- a/arch/arm/plat-omap/include/mach/memory.h
+++ b/arch/arm/plat-omap/include/mach/memory.h
@@ -59,7 +59,7 @@
#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev->bus_id, "ohci", 4) == 0))
+#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
#define __arch_page_to_dma(dev, page) ({is_lbus_device(dev) ? \
(dma_addr_t)virt_to_lbus(page_address(page)) : \
diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h
index 031250f02805..73a9e15031b1 100644
--- a/arch/arm/plat-omap/include/mach/mmc.h
+++ b/arch/arm/plat-omap/include/mach/mmc.h
@@ -115,8 +115,9 @@ void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
int nr_controllers);
void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
int nr_controllers);
-int omap_mmc_add(int id, unsigned long base, unsigned long size,
- unsigned int irq, struct omap_mmc_platform_data *data);
+int omap_mmc_add(const char *name, int id, unsigned long base,
+ unsigned long size, unsigned int irq,
+ struct omap_mmc_platform_data *data);
#else
static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
int nr_controllers)
@@ -126,8 +127,9 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
int nr_controllers)
{
}
-static inline int omap_mmc_add(int id, unsigned long base, unsigned long size,
- unsigned int irq, struct omap_mmc_platform_data *data)
+static inline int omap_mmc_add(const char *name, int id, unsigned long base,
+ unsigned long size, unsigned int irq,
+ struct omap_mmc_platform_data *data)
{
return 0;
}
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index af33fc713e1a..e5842e30e534 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -173,6 +173,10 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ OMAP_MCBSP_WRITE(io_base, XCCR, config->xccr);
+ OMAP_MCBSP_WRITE(io_base, RCCR, config->rccr);
+ }
}
EXPORT_SYMBOL(omap_mcbsp_config);
@@ -210,6 +214,7 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type);
int omap_mcbsp_request(unsigned int id)
{
struct omap_mcbsp *mcbsp;
+ int i;
int err;
if (!omap_mcbsp_check_valid_id(id)) {
@@ -221,7 +226,8 @@ int omap_mcbsp_request(unsigned int id)
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
mcbsp->pdata->ops->request(id);
- clk_enable(mcbsp->clk);
+ for (i = 0; i < mcbsp->num_clks; i++)
+ clk_enable(mcbsp->clks[i]);
spin_lock(&mcbsp->lock);
if (!mcbsp->free) {
@@ -272,6 +278,7 @@ EXPORT_SYMBOL(omap_mcbsp_request);
void omap_mcbsp_free(unsigned int id)
{
struct omap_mcbsp *mcbsp;
+ int i;
if (!omap_mcbsp_check_valid_id(id)) {
printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
@@ -282,7 +289,8 @@ void omap_mcbsp_free(unsigned int id)
if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
mcbsp->pdata->ops->free(id);
- clk_disable(mcbsp->clk);
+ for (i = mcbsp->num_clks - 1; i >= 0; i--)
+ clk_disable(mcbsp->clks[i]);
spin_lock(&mcbsp->lock);
if (mcbsp->free) {
@@ -868,6 +876,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
struct omap_mcbsp *mcbsp;
int id = pdev->id - 1;
+ int i;
int ret = 0;
if (!pdata) {
@@ -912,14 +921,25 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
mcbsp->dma_rx_sync = pdata->dma_rx_sync;
mcbsp->dma_tx_sync = pdata->dma_tx_sync;
- if (pdata->clk_name)
- mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name);
- if (IS_ERR(mcbsp->clk)) {
- dev_err(&pdev->dev,
- "Invalid clock configuration for McBSP%d.\n",
- mcbsp->id);
- ret = PTR_ERR(mcbsp->clk);
- goto err_clk;
+ if (pdata->num_clks) {
+ mcbsp->num_clks = pdata->num_clks;
+ mcbsp->clks = kzalloc(mcbsp->num_clks * sizeof(struct clk *),
+ GFP_KERNEL);
+ if (!mcbsp->clks) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+ for (i = 0; i < mcbsp->num_clks; i++) {
+ mcbsp->clks[i] = clk_get(&pdev->dev, pdata->clk_names[i]);
+ if (IS_ERR(mcbsp->clks[i])) {
+ dev_err(&pdev->dev,
+ "Invalid %s configuration for McBSP%d.\n",
+ pdata->clk_names[i], mcbsp->id);
+ ret = PTR_ERR(mcbsp->clks[i]);
+ goto err_clk;
+ }
+ }
+
}
mcbsp->pdata = pdata;
@@ -928,6 +948,9 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
return 0;
err_clk:
+ while (i--)
+ clk_put(mcbsp->clks[i]);
+ kfree(mcbsp->clks);
iounmap(mcbsp->io_base);
err_ioremap:
mcbsp->free = 0;
@@ -938,6 +961,7 @@ exit:
static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
{
struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+ int i;
platform_set_drvdata(pdev, NULL);
if (mcbsp) {
@@ -946,12 +970,18 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
mcbsp->pdata->ops->free)
mcbsp->pdata->ops->free(mcbsp->id);
- clk_disable(mcbsp->clk);
- clk_put(mcbsp->clk);
+ for (i = mcbsp->num_clks - 1; i >= 0; i--) {
+ clk_disable(mcbsp->clks[i]);
+ clk_put(mcbsp->clks[i]);
+ }
iounmap(mcbsp->io_base);
- mcbsp->clk = NULL;
+ if (mcbsp->num_clks) {
+ kfree(mcbsp->clks);
+ mcbsp->clks = NULL;
+ mcbsp->num_clks = 0;
+ }
mcbsp->free = 0;
mcbsp->dev = NULL;
}
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
index 67ca1e216df7..e278de6862ae 100644
--- a/arch/arm/plat-omap/usb.c
+++ b/arch/arm/plat-omap/usb.c
@@ -77,38 +77,6 @@
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_USB_MUSB_OTG)
-
-static struct otg_transceiver *xceiv;
-
-/**
- * otg_get_transceiver - find the (single) OTG transceiver driver
- *
- * Returns the transceiver driver, after getting a refcount to it; or
- * null if there is no such transceiver. The caller is responsible for
- * releasing that count.
- */
-struct otg_transceiver *otg_get_transceiver(void)
-{
- if (xceiv)
- get_device(xceiv->dev);
- return xceiv;
-}
-EXPORT_SYMBOL(otg_get_transceiver);
-
-int otg_set_transceiver(struct otg_transceiver *x)
-{
- if (xceiv && x)
- return -EBUSY;
- xceiv = x;
- return 0;
-}
-EXPORT_SYMBOL(otg_set_transceiver);
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP15XX)
static void omap2_usb_devconf_clear(u8 port, u32 mask)
@@ -463,15 +431,6 @@ bad:
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_USB_GADGET_OMAP) || \
- defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) || \
- (defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG))
-static void usb_release(struct device *dev)
-{
- /* normally not freed */
-}
-#endif
-
#ifdef CONFIG_USB_GADGET_OMAP
static struct resource udc_resources[] = {
@@ -498,7 +457,6 @@ static struct platform_device udc_device = {
.name = "omap_udc",
.id = -1,
.dev = {
- .release = usb_release,
.dma_mask = &udc_dmamask,
.coherent_dma_mask = 0xffffffff,
},
@@ -529,7 +487,6 @@ static struct platform_device ohci_device = {
.name = "ohci",
.id = -1,
.dev = {
- .release = usb_release,
.dma_mask = &ohci_dmamask,
.coherent_dma_mask = 0xffffffff,
},
@@ -556,9 +513,6 @@ static struct resource otg_resources[] = {
static struct platform_device otg_device = {
.name = "omap_otg",
.id = -1,
- .dev = {
- .release = usb_release,
- },
.num_resources = ARRAY_SIZE(otg_resources),
.resource = otg_resources,
};
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index 544d6b327f3a..6fa2923e6dca 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -149,7 +149,6 @@ static struct clock_event_device orion_clkevt = {
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
.shift = 32,
.rating = 300,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = orion_clkevt_next_event,
.set_mode = orion_clkevt_mode,
};
@@ -199,5 +198,6 @@ void __init orion_time_init(unsigned int irq, unsigned int tclk)
orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt);
orion_clkevt.min_delta_ns = clockevent_delta2ns(1, &orion_clkevt);
+ orion_clkevt.cpumask = cpumask_of(0);
clockevents_register_device(&orion_clkevt);
}
diff --git a/arch/arm/plat-s3c/dev-fb.c b/arch/arm/plat-s3c/dev-fb.c
index 0454b8ec02e2..a90198fc4b0f 100644
--- a/arch/arm/plat-s3c/dev-fb.c
+++ b/arch/arm/plat-s3c/dev-fb.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/fb.h>
+#include <mach/irqs.h>
#include <mach/map.h>
#include <mach/regs-fb.h>
diff --git a/arch/arm/plat-s3c/dev-i2c0.c b/arch/arm/plat-s3c/dev-i2c0.c
index 2c0128c77c6e..fe327074037e 100644
--- a/arch/arm/plat-s3c/dev-i2c0.c
+++ b/arch/arm/plat-s3c/dev-i2c0.c
@@ -15,6 +15,7 @@
#include <linux/string.h>
#include <linux/platform_device.h>
+#include <mach/irqs.h>
#include <mach/map.h>
#include <plat/regs-iic.h>
diff --git a/arch/arm/plat-s3c/dev-i2c1.c b/arch/arm/plat-s3c/dev-i2c1.c
index 9658fb0aec95..2387fbf57af6 100644
--- a/arch/arm/plat-s3c/dev-i2c1.c
+++ b/arch/arm/plat-s3c/dev-i2c1.c
@@ -15,6 +15,7 @@
#include <linux/string.h>
#include <linux/platform_device.h>
+#include <mach/irqs.h>
#include <mach/map.h>
#include <plat/regs-iic.h>
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index f95c6c9d9f1a..94a341aaa4e4 100644
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ b/arch/arm/plat-s3c24xx/gpiolib.c
@@ -59,6 +59,22 @@ static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
return 0;
}
+static int s3c24xx_gpiolib_bankf_toirq(struct gpio_chip *chip, unsigned offset)
+{
+ if (offset < 4)
+ return IRQ_EINT0 + offset;
+
+ if (offset < 8)
+ return IRQ_EINT4 + offset - 4;
+
+ return -EINVAL;
+}
+
+static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset)
+{
+ return IRQ_EINT8 + offset;
+}
+
struct s3c_gpio_chip s3c24xx_gpios[] = {
[0] = {
.base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
@@ -114,6 +130,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
.owner = THIS_MODULE,
.label = "GPIOF",
.ngpio = 8,
+ .to_irq = s3c24xx_gpiolib_bankf_toirq,
},
},
[6] = {
@@ -123,6 +140,7 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
.owner = THIS_MODULE,
.label = "GPIOG",
.ngpio = 10,
+ .to_irq = s3c24xx_gpiolib_bankg_toirq,
},
},
};
diff --git a/arch/arm/plat-s3c24xx/pwm.c b/arch/arm/plat-s3c24xx/pwm.c
index ec56b88866c4..0120b760315b 100644
--- a/arch/arm/plat-s3c24xx/pwm.c
+++ b/arch/arm/plat-s3c24xx/pwm.c
@@ -19,6 +19,8 @@
#include <linux/io.h>
#include <linux/pwm.h>
+#include <mach/irqs.h>
+
#include <plat/devs.h>
#include <plat/regs-timer.h>
diff --git a/arch/arm/plat-s3c64xx/include/plat/irqs.h b/arch/arm/plat-s3c64xx/include/plat/irqs.h
index 02e8dd4c97d5..2846f550b727 100644
--- a/arch/arm/plat-s3c64xx/include/plat/irqs.h
+++ b/arch/arm/plat-s3c64xx/include/plat/irqs.h
@@ -191,7 +191,7 @@
#define IRQ_EINT_GROUP8_BASE (IRQ_EINT_GROUP7_BASE + IRQ_EINT_GROUP7_NR)
#define IRQ_EINT_GROUP9_BASE (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR)
-#define IRQ_EINT_GROUP(group, no) (IRQ_EINT_GROUP##group##__BASE + (x))
+#define IRQ_EINT_GROUP(group, no) (IRQ_EINT_GROUP##group##_BASE + (no))
/* Set the default NR_IRQS */
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 26eca87f6735..b189680d18b0 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -122,6 +122,24 @@ config BOARD_ATNGW100
bool "ATNGW100 Network Gateway"
select CPU_AT32AP7000
+config BOARD_HAMMERHEAD
+ bool "Hammerhead board"
+ select CPU_AT32AP7000
+ select USB_ARCH_HAS_HCD
+ help
+ The Hammerhead platform is built around a AVR32 32-bit microcontroller from Atmel.
+ It offers versatile peripherals, such as ethernet, usb device, usb host etc.
+
+ The board also incooperates a power supply and is a Power over Ethernet (PoE) Powered
+ Device (PD).
+
+ Additonally, a Cyclone III FPGA from Altera is integrated on the board. The FPGA is
+ mapped into the 32-bit AVR memory bus. The FPGA offers two DDR2 SDRAM interfaces, which
+ will cover even the most exceptional need of memory bandwidth. Together with the onboard
+ video decoder the board is ready for video processing.
+
+ For more information see: http://www.miromico.com/hammerhead
+
config BOARD_FAVR_32
bool "Favr-32 LCD-board"
select CPU_AT32AP7000
@@ -133,6 +151,7 @@ endchoice
source "arch/avr32/boards/atstk1000/Kconfig"
source "arch/avr32/boards/atngw100/Kconfig"
+source "arch/avr32/boards/hammerhead/Kconfig"
source "arch/avr32/boards/favr-32/Kconfig"
choice
diff --git a/arch/avr32/Makefile b/arch/avr32/Makefile
index b088e103e753..f3ef3bbf797c 100644
--- a/arch/avr32/Makefile
+++ b/arch/avr32/Makefile
@@ -33,6 +33,7 @@ head-y += arch/avr32/kernel/head.o
core-y += $(machdirs)
core-$(CONFIG_BOARD_ATSTK1000) += arch/avr32/boards/atstk1000/
core-$(CONFIG_BOARD_ATNGW100) += arch/avr32/boards/atngw100/
+core-$(CONFIG_BOARD_HAMMERHEAD) += arch/avr32/boards/hammerhead/
core-$(CONFIG_BOARD_FAVR_32) += arch/avr32/boards/favr-32/
core-$(CONFIG_BOARD_MIMC200) += arch/avr32/boards/mimc200/
core-$(CONFIG_LOADER_U_BOOT) += arch/avr32/boot/u-boot/
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
index 32fb9ba0fbdf..05d3722fff18 100644
--- a/arch/avr32/boards/atngw100/setup.c
+++ b/arch/avr32/boards/atngw100/setup.c
@@ -19,8 +19,8 @@
#include <linux/types.h>
#include <linux/leds.h>
#include <linux/spi/spi.h>
+#include <linux/atmel-mci.h>
-#include <asm/atmel-mci.h>
#include <asm/io.h>
#include <asm/setup.h>
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index 5c5cdf3b464f..1f33a106905c 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -16,12 +16,12 @@
#include <linux/types.h>
#include <linux/spi/spi.h>
#include <linux/spi/at73c213.h>
+#include <linux/atmel-mci.h>
#include <video/atmel_lcdc.h>
#include <asm/io.h>
#include <asm/setup.h>
-#include <asm/atmel-mci.h>
#include <mach/at32ap700x.h>
#include <mach/board.h>
@@ -287,23 +287,7 @@ static int __init atstk1002_init(void)
* ATSTK1000 uses 32-bit SDRAM interface. Reserve the
* SDRAM-specific pins so that nobody messes with them.
*/
- at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */
- at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */
- at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */
- at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */
- at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */
- at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */
- at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */
- at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */
- at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */
- at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */
- at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */
- at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */
- at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */
- at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */
- at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */
- at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
- at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
+ at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
#ifdef CONFIG_BOARD_ATSTK1006
smc_set_timing(&nand_config, &nand_timing);
diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c
index 134b566630b0..b3a23c88bcfe 100644
--- a/arch/avr32/boards/atstk1000/atstk1003.c
+++ b/arch/avr32/boards/atstk1000/atstk1003.c
@@ -17,9 +17,9 @@
#include <linux/spi/at73c213.h>
#include <linux/spi/spi.h>
+#include <linux/atmel-mci.h>
#include <asm/setup.h>
-#include <asm/atmel-mci.h>
#include <mach/at32ap700x.h>
#include <mach/board.h>
@@ -131,23 +131,7 @@ static int __init atstk1003_init(void)
* ATSTK1000 uses 32-bit SDRAM interface. Reserve the
* SDRAM-specific pins so that nobody messes with them.
*/
- at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */
- at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */
- at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */
- at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */
- at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */
- at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */
- at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */
- at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */
- at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */
- at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */
- at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */
- at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */
- at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */
- at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */
- at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */
- at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
- at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
+ at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
#ifdef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM
at32_add_device_usart(1);
diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c
index cb32eb844aa7..29b35aca96cd 100644
--- a/arch/avr32/boards/atstk1000/atstk1004.c
+++ b/arch/avr32/boards/atstk1000/atstk1004.c
@@ -17,11 +17,11 @@
#include <linux/spi/at73c213.h>
#include <linux/spi/spi.h>
+#include <linux/atmel-mci.h>
#include <video/atmel_lcdc.h>
#include <asm/setup.h>
-#include <asm/atmel-mci.h>
#include <mach/at32ap700x.h>
#include <mach/board.h>
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c
index 1ee4faf0742d..745c408c2ac5 100644
--- a/arch/avr32/boards/favr-32/setup.c
+++ b/arch/avr32/boards/favr-32/setup.c
@@ -17,6 +17,7 @@
#include <linux/linkage.h>
#include <linux/gpio.h>
#include <linux/leds.h>
+#include <linux/atmel-mci.h>
#include <linux/atmel-pwm-bl.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
@@ -79,6 +80,14 @@ static struct spi_board_info __initdata spi1_board_info[] = {
},
};
+static struct mci_platform_data __initdata mci0_data = {
+ .slot[0] = {
+ .bus_width = 4,
+ .detect_pin = -ENODEV,
+ .wp_pin = -ENODEV,
+ },
+};
+
static struct fb_videomode __initdata lb104v03_modes[] = {
{
.name = "640x480 @ 50",
@@ -307,28 +316,10 @@ static int __init favr32_init(void)
* Favr-32 uses 32-bit SDRAM interface. Reserve the SDRAM-specific
* pins so that nobody messes with them.
*/
- at32_reserve_pin(GPIO_PIN_PE(0)); /* DATA[16] */
- at32_reserve_pin(GPIO_PIN_PE(1)); /* DATA[17] */
- at32_reserve_pin(GPIO_PIN_PE(2)); /* DATA[18] */
- at32_reserve_pin(GPIO_PIN_PE(3)); /* DATA[19] */
- at32_reserve_pin(GPIO_PIN_PE(4)); /* DATA[20] */
- at32_reserve_pin(GPIO_PIN_PE(5)); /* DATA[21] */
- at32_reserve_pin(GPIO_PIN_PE(6)); /* DATA[22] */
- at32_reserve_pin(GPIO_PIN_PE(7)); /* DATA[23] */
- at32_reserve_pin(GPIO_PIN_PE(8)); /* DATA[24] */
- at32_reserve_pin(GPIO_PIN_PE(9)); /* DATA[25] */
- at32_reserve_pin(GPIO_PIN_PE(10)); /* DATA[26] */
- at32_reserve_pin(GPIO_PIN_PE(11)); /* DATA[27] */
- at32_reserve_pin(GPIO_PIN_PE(12)); /* DATA[28] */
- at32_reserve_pin(GPIO_PIN_PE(13)); /* DATA[29] */
- at32_reserve_pin(GPIO_PIN_PE(14)); /* DATA[30] */
- at32_reserve_pin(GPIO_PIN_PE(15)); /* DATA[31] */
- at32_reserve_pin(GPIO_PIN_PE(26)); /* SDCS */
+ at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
at32_select_gpio(GPIO_PIN_PB(3), 0); /* IRQ from ADS7843 */
- at32_add_system_devices();
-
at32_add_device_usart(0);
set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
@@ -339,7 +330,7 @@ static int __init favr32_init(void)
at32_add_device_pwm(1 << atmel_pwm_bl_pdata.pwm_channel);
at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info));
- at32_add_device_mci(0, NULL);
+ at32_add_device_mci(0, &mci0_data);
at32_add_device_usba(0, NULL);
at32_add_device_lcdc(0, &favr32_lcdc_data, fbmem_start, fbmem_size, 0);
diff --git a/arch/avr32/boards/hammerhead/Kconfig b/arch/avr32/boards/hammerhead/Kconfig
new file mode 100644
index 000000000000..fda2331f9789
--- /dev/null
+++ b/arch/avr32/boards/hammerhead/Kconfig
@@ -0,0 +1,43 @@
+# Hammerhead customization
+
+if BOARD_HAMMERHEAD
+
+config BOARD_HAMMERHEAD_USB
+ bool "Philips ISP116x-hcd USB support"
+ help
+ This enables USB support for Hammerheads internal ISP116x
+ controller from Philips.
+
+ Choose 'Y' here if you want to have your board USB driven.
+
+config BOARD_HAMMERHEAD_LCD
+ bool "Atmel AT91/AT32 LCD support"
+ help
+ This enables LCD support for the Hammerhead board. You may
+ also add support for framebuffer devices (AT91/AT32 LCD Controller)
+ and framebuffer console support to get the most out of your LCD.
+
+ Choose 'Y' here if you have ordered a Corona daugther board and
+ want to have support for your Hantronix HDA-351T-LV LCD.
+
+config BOARD_HAMMERHEAD_SND
+ bool "Atmel AC97 Sound support"
+ help
+ This enables Sound support for the Hammerhead board. You may
+ also go trough the ALSA settings to get it working.
+
+ Choose 'Y' here if you have ordered a Corona daugther board and
+ want to make your board funky.
+
+config BOARD_HAMMERHEAD_FPGA
+ bool "Hammerhead FPGA Support"
+ default y
+ help
+ This adds support for the Cyclone III FPGA from Altera
+ found on Miromico's Hammerhead board.
+
+ Choose 'Y' here if you want to have FPGA support enabled.
+ You will have to choose the "Hammerhead FPGA Device Support" in
+ Device Drivers->Misc to be able to use FPGA functionality.
+
+endif # BOARD_ATNGW100
diff --git a/arch/avr32/boards/hammerhead/Makefile b/arch/avr32/boards/hammerhead/Makefile
new file mode 100644
index 000000000000..c740aa116755
--- /dev/null
+++ b/arch/avr32/boards/hammerhead/Makefile
@@ -0,0 +1 @@
+obj-y += setup.o flash.o
diff --git a/arch/avr32/boards/hammerhead/flash.c b/arch/avr32/boards/hammerhead/flash.c
new file mode 100644
index 000000000000..a98c6dd3a028
--- /dev/null
+++ b/arch/avr32/boards/hammerhead/flash.c
@@ -0,0 +1,377 @@
+/*
+ * Hammerhead board-specific flash initialization
+ *
+ * Copyright (C) 2008 Miromico AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/usb/isp116x.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/portmux.h>
+#include <mach/at32ap700x.h>
+#include <mach/smc.h>
+
+#include "../../mach-at32ap/clock.h"
+#include "flash.h"
+
+
+#define HAMMERHEAD_USB_PERIPH_GCLK0 0x40000000
+#define HAMMERHEAD_USB_PERIPH_CS2 0x02000000
+#define HAMMERHEAD_USB_PERIPH_EXTINT0 0x02000000
+
+#define HAMMERHEAD_FPGA_PERIPH_MOSI 0x00000002
+#define HAMMERHEAD_FPGA_PERIPH_SCK 0x00000020
+#define HAMMERHEAD_FPGA_PERIPH_EXTINT3 0x10000000
+
+static struct smc_timing flash_timing __initdata = {
+ .ncs_read_setup = 0,
+ .nrd_setup = 40,
+ .ncs_write_setup = 0,
+ .nwe_setup = 10,
+
+ .ncs_read_pulse = 80,
+ .nrd_pulse = 40,
+ .ncs_write_pulse = 65,
+ .nwe_pulse = 55,
+
+ .read_cycle = 120,
+ .write_cycle = 120,
+};
+
+static struct smc_config flash_config __initdata = {
+ .bus_width = 2,
+ .nrd_controlled = 1,
+ .nwe_controlled = 1,
+ .byte_write = 1,
+};
+
+static struct mtd_partition flash_parts[] = {
+ {
+ .name = "u-boot",
+ .offset = 0x00000000,
+ .size = 0x00020000, /* 128 KiB */
+ .mask_flags = MTD_WRITEABLE,
+ },
+ {
+ .name = "root",
+ .offset = 0x00020000,
+ .size = 0x007d0000,
+ },
+ {
+ .name = "env",
+ .offset = 0x007f0000,
+ .size = 0x00010000,
+ .mask_flags = MTD_WRITEABLE,
+ },
+};
+
+static struct physmap_flash_data flash_data = {
+ .width = 2,
+ .nr_parts = ARRAY_SIZE(flash_parts),
+ .parts = flash_parts,
+};
+
+static struct resource flash_resource = {
+ .start = 0x00000000,
+ .end = 0x007fffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .resource = &flash_resource,
+ .num_resources = 1,
+ .dev = { .platform_data = &flash_data, },
+};
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_USB
+
+static struct smc_timing isp1160_timing __initdata = {
+ .ncs_read_setup = 75,
+ .nrd_setup = 75,
+ .ncs_write_setup = 75,
+ .nwe_setup = 75,
+
+
+ /* We use conservative timing settings, as the minimal settings aren't
+ stable. There may be room for tweaking. */
+ .ncs_read_pulse = 75, /* min. 33ns */
+ .nrd_pulse = 75, /* min. 33ns */
+ .ncs_write_pulse = 75, /* min. 26ns */
+ .nwe_pulse = 75, /* min. 26ns */
+
+ .read_cycle = 225, /* min. 143ns */
+ .write_cycle = 225, /* min. 136ns */
+};
+
+static struct smc_config isp1160_config __initdata = {
+ .bus_width = 2,
+ .nrd_controlled = 1,
+ .nwe_controlled = 1,
+ .byte_write = 0,
+};
+
+/*
+ * The platform delay function is only used to enforce the strange
+ * read to write delay. This can not be configured in the SMC. All other
+ * timings are controlled by the SMC (see timings obove)
+ * So in isp116x-hcd.c we should comment out USE_PLATFORM_DELAY
+ */
+void isp116x_delay(struct device *dev, int delay)
+{
+ if (delay > 150)
+ ndelay(delay - 150);
+}
+
+static struct isp116x_platform_data isp1160_data = {
+ .sel15Kres = 1, /* use internal downstream resistors */
+ .oc_enable = 0, /* external overcurrent detection */
+ .int_edge_triggered = 0, /* interrupt is level triggered */
+ .int_act_high = 0, /* interrupt is active low */
+ .delay = isp116x_delay, /* platform delay function */
+};
+
+static struct resource isp1160_resource[] = {
+ {
+ .start = 0x08000000,
+ .end = 0x08000001,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x08000002,
+ .end = 0x08000003,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 64,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device isp1160_device = {
+ .name = "isp116x-hcd",
+ .id = 0,
+ .resource = isp1160_resource,
+ .num_resources = 3,
+ .dev = {
+ .platform_data = &isp1160_data,
+ },
+};
+#endif
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_USB
+static int __init hammerhead_usbh_init(void)
+{
+ struct clk *gclk;
+ struct clk *osc;
+
+ int ret;
+
+ /* setup smc for usbh */
+ smc_set_timing(&isp1160_config, &isp1160_timing);
+ ret = smc_set_configuration(2, &isp1160_config);
+
+ if (ret < 0) {
+ printk(KERN_ERR
+ "hammerhead: failed to set ISP1160 USBH timing\n");
+ return ret;
+ }
+
+ /* setup gclk0 to run from osc1 */
+ gclk = clk_get(NULL, "gclk0");
+ if (IS_ERR(gclk))
+ goto err_gclk;
+
+ osc = clk_get(NULL, "osc1");
+ if (IS_ERR(osc))
+ goto err_osc;
+
+ if (clk_set_parent(gclk, osc)) {
+ pr_debug("hammerhead: failed to set osc1 for USBH clock\n");
+ goto err_set_clk;
+ }
+
+ /* set clock to 6MHz */
+ clk_set_rate(gclk, 6000000);
+
+ /* and enable */
+ clk_enable(gclk);
+
+ /* select GCLK0 peripheral function */
+ at32_select_periph(GPIO_PIOA_BASE, HAMMERHEAD_USB_PERIPH_GCLK0,
+ GPIO_PERIPH_A, 0);
+
+ /* enable CS2 peripheral function */
+ at32_select_periph(GPIO_PIOE_BASE, HAMMERHEAD_USB_PERIPH_CS2,
+ GPIO_PERIPH_A, 0);
+
+ /* H_WAKEUP must be driven low */
+ at32_select_gpio(GPIO_PIN_PA(8), AT32_GPIOF_OUTPUT);
+
+ /* Select EXTINT0 for PB25 */
+ at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_USB_PERIPH_EXTINT0,
+ GPIO_PERIPH_A, 0);
+
+ /* register usbh device driver */
+ platform_device_register(&isp1160_device);
+
+ err_set_clk:
+ clk_put(osc);
+ err_osc:
+ clk_put(gclk);
+ err_gclk:
+ return ret;
+}
+#endif
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
+static struct smc_timing fpga_timing __initdata = {
+ .ncs_read_setup = 16,
+ .nrd_setup = 32,
+ .ncs_read_pulse = 48,
+ .nrd_pulse = 32,
+ .read_cycle = 64,
+
+ .ncs_write_setup = 16,
+ .nwe_setup = 16,
+ .ncs_write_pulse = 32,
+ .nwe_pulse = 32,
+ .write_cycle = 64,
+};
+
+static struct smc_config fpga_config __initdata = {
+ .bus_width = 4,
+ .nrd_controlled = 1,
+ .nwe_controlled = 1,
+ .byte_write = 0,
+};
+
+static struct resource hh_fpga0_resource[] = {
+ {
+ .start = 0xffe00400,
+ .end = 0xffe00400 + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 4,
+ .end = 4,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = 0x0c000000,
+ .end = 0x0c000100,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 67,
+ .end = 67,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 hh_fpga0_dma_mask = DMA_32BIT_MASK;
+static struct platform_device hh_fpga0_device = {
+ .name = "hh_fpga",
+ .id = 0,
+ .dev = {
+ .dma_mask = &hh_fpga0_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ },
+ .resource = hh_fpga0_resource,
+ .num_resources = ARRAY_SIZE(hh_fpga0_resource),
+};
+
+static struct clk hh_fpga0_spi_clk = {
+ .name = "spi_clk",
+ .dev = &hh_fpga0_device.dev,
+ .mode = pba_clk_mode,
+ .get_rate = pba_clk_get_rate,
+ .index = 1,
+};
+
+struct platform_device *__init at32_add_device_hh_fpga(void)
+{
+ /* Select peripheral functionallity for SPI SCK and MOSI */
+ at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_SCK,
+ GPIO_PERIPH_B, 0);
+ at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_MOSI,
+ GPIO_PERIPH_B, 0);
+
+ /* reserve all other needed gpio
+ * We have on board pull ups, so there is no need
+ * to enable gpio pull ups */
+ /* INIT_DONE (input) */
+ at32_select_gpio(GPIO_PIN_PB(0), 0);
+
+ /* nSTATUS (input) */
+ at32_select_gpio(GPIO_PIN_PB(2), 0);
+
+ /* nCONFIG (output, low) */
+ at32_select_gpio(GPIO_PIN_PB(3), AT32_GPIOF_OUTPUT);
+
+ /* CONF_DONE (input) */
+ at32_select_gpio(GPIO_PIN_PB(4), 0);
+
+ /* Select EXTINT3 for PB28 (Interrupt from FPGA) */
+ at32_select_periph(GPIO_PIOB_BASE, HAMMERHEAD_FPGA_PERIPH_EXTINT3,
+ GPIO_PERIPH_A, 0);
+
+ /* Get our parent clock */
+ hh_fpga0_spi_clk.parent = clk_get(NULL, "pba");
+ clk_put(hh_fpga0_spi_clk.parent);
+
+ /* Register clock in at32 clock tree */
+ at32_clk_register(&hh_fpga0_spi_clk);
+
+ platform_device_register(&hh_fpga0_device);
+ return &hh_fpga0_device;
+}
+#endif
+
+/* This needs to be called after the SMC has been initialized */
+static int __init hammerhead_flash_init(void)
+{
+ int ret;
+
+ smc_set_timing(&flash_config, &flash_timing);
+ ret = smc_set_configuration(0, &flash_config);
+
+ if (ret < 0) {
+ printk(KERN_ERR "hammerhead: failed to set NOR flash timing\n");
+ return ret;
+ }
+
+ platform_device_register(&flash_device);
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_USB
+ hammerhead_usbh_init();
+#endif
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
+ /* Setup SMC for FPGA interface */
+ smc_set_timing(&fpga_config, &fpga_timing);
+ ret = smc_set_configuration(3, &fpga_config);
+#endif
+
+
+ if (ret < 0) {
+ printk(KERN_ERR "hammerhead: failed to set FPGA timing\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+device_initcall(hammerhead_flash_init);
diff --git a/arch/avr32/boards/hammerhead/flash.h b/arch/avr32/boards/hammerhead/flash.h
new file mode 100644
index 000000000000..ea70c626587b
--- /dev/null
+++ b/arch/avr32/boards/hammerhead/flash.h
@@ -0,0 +1,6 @@
+#ifndef __BOARDS_HAMMERHEAD_FLASH_H
+#define __BOARDS_HAMMERHEAD_FLASH_H
+
+struct platform_device *at32_add_device_hh_fpga(void);
+
+#endif /* __BOARDS_HAMMERHEAD_FLASH_H */
diff --git a/arch/avr32/boards/hammerhead/setup.c b/arch/avr32/boards/hammerhead/setup.c
new file mode 100644
index 000000000000..4d2fe82b2029
--- /dev/null
+++ b/arch/avr32/boards/hammerhead/setup.c
@@ -0,0 +1,245 @@
+/*
+ * Board-specific setup code for the Miromico Hammerhead board
+ *
+ * Copyright (C) 2008 Miromico AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/atmel-mci.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/etherdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/spi/spi.h>
+
+#include <video/atmel_lcdc.h>
+
+#include <linux/io.h>
+#include <asm/setup.h>
+
+#include <mach/at32ap700x.h>
+#include <mach/board.h>
+#include <mach/init.h>
+#include <mach/portmux.h>
+
+#include "../../mach-at32ap/clock.h"
+#include "flash.h"
+
+/* Oscillator frequencies. These are board-specific */
+unsigned long at32_board_osc_rates[3] = {
+ [0] = 32768, /* 32.768 kHz on RTC osc */
+ [1] = 25000000, /* 25MHz on osc0 */
+ [2] = 12000000, /* 12 MHz on osc1 */
+};
+
+/* Initialized by bootloader-specific startup code. */
+struct tag *bootloader_tags __initdata;
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_LCD
+static struct fb_videomode __initdata hda350tlv_modes[] = {
+ {
+ .name = "320x240 @ 75",
+ .refresh = 75,
+ .xres = 320,
+ .yres = 240,
+ .pixclock = KHZ2PICOS(6891),
+
+ .left_margin = 48,
+ .right_margin = 18,
+ .upper_margin = 18,
+ .lower_margin = 4,
+ .hsync_len = 20,
+ .vsync_len = 2,
+
+ .sync = 0,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+};
+
+static struct fb_monspecs __initdata hammerhead_hda350t_monspecs = {
+ .manufacturer = "HAN",
+ .monitor = "HDA350T-LV",
+ .modedb = hda350tlv_modes,
+ .modedb_len = ARRAY_SIZE(hda350tlv_modes),
+ .hfmin = 14900,
+ .hfmax = 22350,
+ .vfmin = 60,
+ .vfmax = 90,
+ .dclkmax = 10000000,
+};
+
+struct atmel_lcdfb_info __initdata hammerhead_lcdc_data = {
+ .default_bpp = 24,
+ .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN,
+ .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT
+ | ATMEL_LCDC_INVCLK
+ | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE
+ | ATMEL_LCDC_MEMOR_BIG),
+ .default_monspecs = &hammerhead_hda350t_monspecs,
+ .guard_time = 2,
+};
+#endif
+
+static struct mci_platform_data __initdata mci0_data = {
+ .slot[0] = {
+ .bus_width = 4,
+ .detect_pin = -ENODEV,
+ .wp_pin = -ENODEV,
+ },
+};
+
+struct eth_addr {
+ u8 addr[6];
+};
+
+static struct eth_addr __initdata hw_addr[1];
+static struct eth_platform_data __initdata eth_data[1];
+
+/*
+ * The next two functions should go away as the boot loader is
+ * supposed to initialize the macb address registers with a valid
+ * ethernet address. But we need to keep it around for a while until
+ * we can be reasonably sure the boot loader does this.
+ *
+ * The phy_id is ignored as the driver will probe for it.
+ */
+static int __init parse_tag_ethernet(struct tag *tag)
+{
+ int i = tag->u.ethernet.mac_index;
+
+ if (i < ARRAY_SIZE(hw_addr))
+ memcpy(hw_addr[i].addr, tag->u.ethernet.hw_address,
+ sizeof(hw_addr[i].addr));
+
+ return 0;
+}
+__tagtable(ATAG_ETHERNET, parse_tag_ethernet);
+
+static void __init set_hw_addr(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ const u8 *addr;
+ void __iomem *regs;
+ struct clk *pclk;
+
+ if (!res)
+ return;
+
+ if (pdev->id >= ARRAY_SIZE(hw_addr))
+ return;
+
+ addr = hw_addr[pdev->id].addr;
+
+ if (!is_valid_ether_addr(addr))
+ return;
+
+ /*
+ * Since this is board-specific code, we'll cheat and use the
+ * physical address directly as we happen to know that it's
+ * the same as the virtual address.
+ */
+ regs = (void __iomem __force *)res->start;
+ pclk = clk_get(&pdev->dev, "pclk");
+
+ if (!pclk)
+ return;
+
+ clk_enable(pclk);
+
+ __raw_writel((addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) |
+ addr[0], regs + 0x98);
+ __raw_writel((addr[5] << 8) | addr[4], regs + 0x9c);
+
+ clk_disable(pclk);
+ clk_put(pclk);
+}
+
+void __init setup_board(void)
+{
+ at32_map_usart(1, 0); /* USART 1: /dev/ttyS0, DB9 */
+ at32_setup_serial_console(0);
+}
+
+static struct i2c_gpio_platform_data i2c_gpio_data = {
+ .sda_pin = GPIO_PIN_PA(6),
+ .scl_pin = GPIO_PIN_PA(7),
+ .sda_is_open_drain = 1,
+ .scl_is_open_drain = 1,
+ .udelay = 2, /* close to 100 kHz */
+};
+
+static struct platform_device i2c_gpio_device = {
+ .name = "i2c-gpio",
+ .id = 0,
+ .dev = { .platform_data = &i2c_gpio_data, },
+};
+
+static struct i2c_board_info __initdata i2c_info[] = {};
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_SND
+static struct ac97c_platform_data ac97c_data = {
+ .reset_pin = GPIO_PIN_PA(16),
+};
+#endif
+
+static int __init hammerhead_init(void)
+{
+ /*
+ * Hammerhead uses 32-bit SDRAM interface. Reserve the
+ * SDRAM-specific pins so that nobody messes with them.
+ */
+ at32_reserve_pin(GPIO_PIOE_BASE, ATMEL_EBI_PE_DATA_ALL);
+
+ at32_add_device_usart(0);
+
+ /* Reserve PB29 (GCLK3). This pin is used as clock source
+ * for ETH PHY (25MHz). GCLK3 setup is done by U-Boot.
+ */
+ at32_reserve_pin(GPIO_PIOB_BASE, (1<<29));
+
+ /*
+ * Hammerhead uses only one ethernet port, so we don't set
+ * address of second port
+ */
+ set_hw_addr(at32_add_device_eth(0, &eth_data[0]));
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_FPGA
+ at32_add_device_hh_fpga();
+#endif
+ at32_add_device_mci(0, &mci0_data);
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_USB
+ at32_add_device_usba(0, NULL);
+#endif
+#ifdef CONFIG_BOARD_HAMMERHEAD_LCD
+ at32_add_device_lcdc(0, &hammerhead_lcdc_data, fbmem_start,
+ fbmem_size, ATMEL_LCDC_PRI_24BIT);
+#endif
+
+ at32_select_gpio(i2c_gpio_data.sda_pin,
+ AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT |
+ AT32_GPIOF_HIGH);
+ at32_select_gpio(i2c_gpio_data.scl_pin,
+ AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT |
+ AT32_GPIOF_HIGH);
+ platform_device_register(&i2c_gpio_device);
+ i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info));
+
+#ifdef CONFIG_BOARD_HAMMERHEAD_SND
+ at32_add_device_ac97c(0, &ac97c_data);
+#endif
+
+ /* Select the Touchscreen interrupt pin mode */
+ at32_select_periph(GPIO_PIOB_BASE, 0x08000000, GPIO_PERIPH_A, 0);
+
+ return 0;
+}
+
+postcore_initcall(hammerhead_init);
diff --git a/arch/avr32/boards/mimc200/setup.c b/arch/avr32/boards/mimc200/setup.c
index 397cbb8f44c8..2b58d61f0afc 100644
--- a/arch/avr32/boards/mimc200/setup.c
+++ b/arch/avr32/boards/mimc200/setup.c
@@ -24,7 +24,7 @@ extern struct atmel_lcdfb_info mimc200_lcdc_data;
#include <video/atmel_lcdc.h>
#include <linux/fb.h>
-#include <asm/atmel-mci.h>
+#include <linux/atmel-mci.h>
#include <linux/io.h>
#include <asm/setup.h>
@@ -207,8 +207,6 @@ static int __init mimc200_init(void)
* reserve any pins for it.
*/
- at32_add_system_devices();
-
at32_add_device_usart(0);
at32_add_device_usart(1);
at32_add_device_usart(2);
diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig
index 541520912c55..574aca975334 100644
--- a/arch/avr32/configs/atngw100_defconfig
+++ b/arch/avr32/configs/atngw100_defconfig
@@ -644,8 +644,8 @@ CONFIG_I2C_GPIO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_AT24=m
-# CONFIG_SENSORS_EEPROM is not set
+CONFIG_EEPROM_AT24=m
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -670,7 +670,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
@@ -892,7 +892,7 @@ CONFIG_DMA_ENGINE=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
-CONFIG_DMATEST=m
+# CONFIG_DMATEST is not set
# CONFIG_UIO is not set
#
diff --git a/arch/avr32/configs/atngw100_evklcd100_defconfig b/arch/avr32/configs/atngw100_evklcd100_defconfig
index b0572d213826..86a45b5c9d0d 100644
--- a/arch/avr32/configs/atngw100_evklcd100_defconfig
+++ b/arch/avr32/configs/atngw100_evklcd100_defconfig
@@ -671,7 +671,7 @@ CONFIG_I2C_GPIO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -699,7 +699,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
CONFIG_HAVE_GPIO_LIB=y
diff --git a/arch/avr32/configs/atngw100_evklcd101_defconfig b/arch/avr32/configs/atngw100_evklcd101_defconfig
index c5b898d21075..a96b68ea5e83 100644
--- a/arch/avr32/configs/atngw100_evklcd101_defconfig
+++ b/arch/avr32/configs/atngw100_evklcd101_defconfig
@@ -671,7 +671,7 @@ CONFIG_I2C_GPIO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -699,7 +699,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
CONFIG_HAVE_GPIO_LIB=y
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index 69fce6b6a783..0abe90adb1a4 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -663,8 +663,8 @@ CONFIG_I2C_GPIO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_AT24=m
-# CONFIG_SENSORS_EEPROM is not set
+CONFIG_EEPROM_AT24=m
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -689,7 +689,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
@@ -964,7 +964,7 @@ CONFIG_DMA_ENGINE=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
-CONFIG_DMATEST=m
+# CONFIG_DMATEST is not set
# CONFIG_UIO is not set
#
diff --git a/arch/avr32/configs/atstk1003_defconfig b/arch/avr32/configs/atstk1003_defconfig
index 5477ed3183b4..101972f40f07 100644
--- a/arch/avr32/configs/atstk1003_defconfig
+++ b/arch/avr32/configs/atstk1003_defconfig
@@ -611,8 +611,8 @@ CONFIG_I2C_GPIO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_AT24=m
-# CONFIG_SENSORS_EEPROM is not set
+CONFIG_EEPROM_AT24=m
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -637,7 +637,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
@@ -882,7 +882,7 @@ CONFIG_DMA_ENGINE=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
-CONFIG_DMATEST=m
+# CONFIG_DMATEST is not set
# CONFIG_UIO is not set
#
diff --git a/arch/avr32/configs/atstk1004_defconfig b/arch/avr32/configs/atstk1004_defconfig
index 69e6c0d08ce8..518f7898df75 100644
--- a/arch/avr32/configs/atstk1004_defconfig
+++ b/arch/avr32/configs/atstk1004_defconfig
@@ -394,7 +394,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig
index 6c45a3b77aa3..c1603c4860e0 100644
--- a/arch/avr32/configs/atstk1006_defconfig
+++ b/arch/avr32/configs/atstk1006_defconfig
@@ -684,8 +684,8 @@ CONFIG_I2C_GPIO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -710,7 +710,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
@@ -1014,7 +1014,7 @@ CONFIG_DMA_ENGINE=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
-CONFIG_DMATEST=m
+# CONFIG_DMATEST is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
CONFIG_STAGING_EXCLUDE_BUILD=y
diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig
index e2bd9982e2af..4c3ac0643e4a 100644
--- a/arch/avr32/configs/favr-32_defconfig
+++ b/arch/avr32/configs/favr-32_defconfig
@@ -633,8 +633,8 @@ CONFIG_I2C_GPIO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -659,7 +659,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig
new file mode 100644
index 000000000000..3970fcc4d76e
--- /dev/null
+++ b/arch/avr32/configs/hammerhead_defconfig
@@ -0,0 +1,1467 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27
+# Tue Dec 9 15:37:30 2008
+#
+CONFIG_AVR32=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_BASE_FULL is not set
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=1
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
+
+#
+# System Type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SUBARCH_AVR32B=y
+CONFIG_MMU=y
+CONFIG_PERFORMANCE_COUNTERS=y
+CONFIG_PLATFORM_AT32AP=y
+CONFIG_CPU_AT32AP700X=y
+CONFIG_CPU_AT32AP7000=y
+# CONFIG_BOARD_ATSTK1000 is not set
+# CONFIG_BOARD_ATNGW100 is not set
+CONFIG_BOARD_HAMMERHEAD=y
+# CONFIG_BOARD_FAVR_32 is not set
+# CONFIG_BOARD_MIMC200 is not set
+CONFIG_BOARD_HAMMERHEAD_USB=y
+CONFIG_BOARD_HAMMERHEAD_LCD=y
+CONFIG_BOARD_HAMMERHEAD_SND=y
+# CONFIG_BOARD_HAMMERHEAD_FPGA is not set
+CONFIG_LOADER_U_BOOT=y
+
+#
+# Atmel AVR32 AP options
+#
+# CONFIG_AP700X_32_BIT_SMC is not set
+CONFIG_AP700X_16_BIT_SMC=y
+# CONFIG_AP700X_8_BIT_SMC is not set
+CONFIG_LOAD_ADDRESS=0x10000000
+CONFIG_ENTRY_ADDRESS=0x90000000
+CONFIG_PHYS_OFFSET=0x10000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_QUICKLIST=y
+# CONFIG_HAVE_ARCH_BOOTMEM_NODE is not set
+# CONFIG_ARCH_HAVE_MEMORY_PRESENT is not set
+# CONFIG_NEED_NODE_MEMMAP_SIZE is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+# CONFIG_ARCH_SPARSEMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+# CONFIG_OWNERSHIP_TRACE is not set
+# CONFIG_NMI_DEBUGGING is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_CMDLINE=""
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+# CONFIG_CPU_FREQ_STAT is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_AT32AP=y
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+# CONFIG_IP_PIMSM_V2 is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_ADVANCED is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x80000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_DATAFLASH=y
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+# CONFIG_MTD_DATAFLASH_OTP is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ATMEL_PWM is not set
+CONFIG_ATMEL_TCLIB=y
+CONFIG_ATMEL_TCB_CLKSRC=y
+CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ATMEL_SSC is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_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 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 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 is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MACB=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AT32PSIF is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_ATMEL_PDC=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_GPIO=m
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 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=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_ATMEL=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_EEPROM_AT25 is not set
+CONFIG_SPI_SPIDEV=m
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT32AP700X_WDT=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_ATMEL=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_ISP116X_HCD=m
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_USB_ATMEL_USBA=y
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_ATMELMCI=m
+# CONFIG_MMC_SPI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_AT32AP700X=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP 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_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/avr32/configs/mimc200_defconfig b/arch/avr32/configs/mimc200_defconfig
index 981e4f8b8aeb..1a58ffbc752d 100644
--- a/arch/avr32/configs/mimc200_defconfig
+++ b/arch/avr32/configs/mimc200_defconfig
@@ -565,8 +565,8 @@ CONFIG_I2C_GPIO=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_AT24=y
-# CONFIG_SENSORS_EEPROM is not set
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -592,7 +592,7 @@ CONFIG_SPI_ATMEL=y
#
# SPI Protocol Masters
#
-CONFIG_SPI_AT25=y
+CONFIG_EEPROM_AT25=y
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_REQUIRE_GPIOLIB=y
diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h
index 7ef3862a73d0..318815107748 100644
--- a/arch/avr32/include/asm/atomic.h
+++ b/arch/avr32/include/asm/atomic.h
@@ -14,9 +14,9 @@
#ifndef __ASM_AVR32_ATOMIC_H
#define __ASM_AVR32_ATOMIC_H
+#include <linux/types.h>
#include <asm/system.h>
-typedef struct { volatile int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
diff --git a/arch/avr32/include/asm/bitops.h b/arch/avr32/include/asm/bitops.h
index 1a50b69b1a19..f7dd5f71edf7 100644
--- a/arch/avr32/include/asm/bitops.h
+++ b/arch/avr32/include/asm/bitops.h
@@ -263,6 +263,11 @@ static inline int fls(unsigned long word)
return 32 - result;
}
+static inline int __fls(unsigned long word)
+{
+ return fls(word) - 1;
+}
+
unsigned long find_first_zero_bit(const unsigned long *addr,
unsigned long size);
unsigned long find_next_zero_bit(const unsigned long *addr,
diff --git a/arch/avr32/include/asm/byteorder.h b/arch/avr32/include/asm/byteorder.h
index 8e3af02076dd..50abc21619a8 100644
--- a/arch/avr32/include/asm/byteorder.h
+++ b/arch/avr32/include/asm/byteorder.h
@@ -4,34 +4,6 @@
#ifndef __ASM_AVR32_BYTEORDER_H
#define __ASM_AVR32_BYTEORDER_H
-#include <asm/types.h>
-#include <linux/compiler.h>
+#include <linux/byteorder/big_endian.h>
-#define __BIG_ENDIAN
-#define __SWAB_64_THRU_32__
-
-#ifdef __CHECKER__
-extern unsigned long __builtin_bswap_32(unsigned long x);
-extern unsigned short __builtin_bswap_16(unsigned short x);
-#endif
-
-/*
- * avr32-linux-gcc versions earlier than 4.2 improperly sign-extends
- * the result.
- */
-#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2)
-static inline __attribute_const__ __u16 __arch_swab16(__u16 val)
-{
- return __builtin_bswap_16(val);
-}
-#define __arch_swab16 __arch_swab16
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
- return __builtin_bswap_32(val);
-}
-#define __arch_swab32 __arch_swab32
-#endif
-
-#include <linux/byteorder.h>
#endif /* __ASM_AVR32_BYTEORDER_H */
diff --git a/arch/avr32/include/asm/kdebug.h b/arch/avr32/include/asm/kdebug.h
index ca4f9542365a..f930ce286803 100644
--- a/arch/avr32/include/asm/kdebug.h
+++ b/arch/avr32/include/asm/kdebug.h
@@ -6,6 +6,7 @@ enum die_val {
DIE_BREAKPOINT,
DIE_SSTEP,
DIE_NMI,
+ DIE_OOPS,
};
#endif /* __ASM_AVR32_KDEBUG_H */
diff --git a/arch/avr32/include/asm/swab.h b/arch/avr32/include/asm/swab.h
new file mode 100644
index 000000000000..a14aa5b46d98
--- /dev/null
+++ b/arch/avr32/include/asm/swab.h
@@ -0,0 +1,35 @@
+/*
+ * AVR32 byteswapping functions.
+ */
+#ifndef __ASM_AVR32_SWAB_H
+#define __ASM_AVR32_SWAB_H
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+
+#define __SWAB_64_THRU_32__
+
+#ifdef __CHECKER__
+extern unsigned long __builtin_bswap_32(unsigned long x);
+extern unsigned short __builtin_bswap_16(unsigned short x);
+#endif
+
+/*
+ * avr32-linux-gcc versions earlier than 4.2 improperly sign-extends
+ * the result.
+ */
+#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2)
+static inline __attribute_const__ __u16 __arch_swab16(__u16 val)
+{
+ return __builtin_bswap_16(val);
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+ return __builtin_bswap_32(val);
+}
+#define __arch_swab32 __arch_swab32
+#endif
+
+#endif /* __ASM_AVR32_SWAB_H */
diff --git a/arch/avr32/include/asm/syscalls.h b/arch/avr32/include/asm/syscalls.h
new file mode 100644
index 000000000000..483d666c27c0
--- /dev/null
+++ b/arch/avr32/include/asm/syscalls.h
@@ -0,0 +1,39 @@
+/*
+ * syscalls.h - Linux syscall interfaces (arch-specific)
+ *
+ * Copyright (c) 2008 Jaswinder Singh
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#ifndef _ASM_AVR32_SYSCALLS_H
+#define _ASM_AVR32_SYSCALLS_H
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/signal.h>
+
+/* kernel/process.c */
+asmlinkage int sys_fork(struct pt_regs *);
+asmlinkage int sys_clone(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ struct pt_regs *);
+asmlinkage int sys_vfork(struct pt_regs *);
+asmlinkage int sys_execve(char __user *, char __user *__user *,
+ char __user *__user *, struct pt_regs *);
+
+/* kernel/signal.c */
+asmlinkage int sys_sigaltstack(const stack_t __user *, stack_t __user *,
+ struct pt_regs *);
+asmlinkage int sys_rt_sigreturn(struct pt_regs *);
+
+/* kernel/sys_avr32.c */
+asmlinkage long sys_mmap2(unsigned long, unsigned long, unsigned long,
+ unsigned long, unsigned long, off_t);
+
+/* mm/cache.c */
+asmlinkage int sys_cacheflush(int, void __user *, size_t);
+
+#endif /* _ASM_AVR32_SYSCALLS_H */
diff --git a/arch/avr32/kernel/init_task.c b/arch/avr32/kernel/init_task.c
index 44058469c6ec..993d56ee3cf3 100644
--- a/arch/avr32/kernel/init_task.c
+++ b/arch/avr32/kernel/init_task.c
@@ -13,7 +13,6 @@
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 134d5302b6dd..43ae555ecb33 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -18,6 +18,7 @@
#include <asm/sysreg.h>
#include <asm/ocd.h>
+#include <asm/syscalls.h>
#include <mach/pm.h>
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index c5b11f9067f1..803d7be0938f 100644
--- a/arch/avr32/kernel/signal.c
+++ b/arch/avr32/kernel/signal.c
@@ -19,6 +19,7 @@
#include <asm/uaccess.h>
#include <asm/ucontext.h>
+#include <asm/syscalls.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c
index 8e8911e55c8f..5d2daeaf356f 100644
--- a/arch/avr32/kernel/sys_avr32.c
+++ b/arch/avr32/kernel/sys_avr32.c
@@ -13,6 +13,7 @@
#include <asm/mman.h>
#include <asm/uaccess.h>
+#include <asm/syscalls.h>
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index 283481d74a5b..0ff46bf873b0 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -106,7 +106,6 @@ static struct clock_event_device comparator = {
.features = CLOCK_EVT_FEAT_ONESHOT,
.shift = 16,
.rating = 50,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = comparator_next_event,
.set_mode = comparator_mode,
};
@@ -134,6 +133,7 @@ void __init time_init(void)
comparator.mult = div_sc(counter_hz, NSEC_PER_SEC, comparator.shift);
comparator.max_delta_ns = clockevent_delta2ns((u32)~0, &comparator);
comparator.min_delta_ns = clockevent_delta2ns(50, &comparator) + 1;
+ comparator.cpumask = cpumask_of(0);
sysreg_write(COMPARE, 0);
timer_irqaction.dev_id = &comparator;
diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
index 0d987373bc01..d547c8df157d 100644
--- a/arch/avr32/kernel/traps.c
+++ b/arch/avr32/kernel/traps.c
@@ -7,6 +7,7 @@
*/
#include <linux/bug.h>
+#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/kdebug.h>
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index 066252eebf61..3fbfd1e32a9e 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -15,8 +15,8 @@
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/usb/atmel_usba_udc.h>
+#include <linux/atmel-mci.h>
-#include <asm/atmel-mci.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -421,7 +421,7 @@ static unsigned long hsb_clk_get_rate(struct clk *clk)
return bus_clk_get_rate(clk, shift);
}
-static void pba_clk_mode(struct clk *clk, int enabled)
+void pba_clk_mode(struct clk *clk, int enabled)
{
unsigned long flags;
u32 mask;
@@ -436,7 +436,7 @@ static void pba_clk_mode(struct clk *clk, int enabled)
spin_unlock_irqrestore(&pm_lock, flags);
}
-static unsigned long pba_clk_get_rate(struct clk *clk)
+unsigned long pba_clk_get_rate(struct clk *clk)
{
unsigned long cksel, shift = 0;
@@ -1305,7 +1305,7 @@ struct platform_device *__init
at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
{
struct platform_device *pdev;
- struct dw_dma_slave *dws;
+ struct dw_dma_slave *dws = &data->dma_slave;
u32 pioa_mask;
u32 piob_mask;
@@ -1324,22 +1324,13 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
ARRAY_SIZE(atmel_mci0_resource)))
goto fail;
- if (data->dma_slave)
- dws = kmemdup(to_dw_dma_slave(data->dma_slave),
- sizeof(struct dw_dma_slave), GFP_KERNEL);
- else
- dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL);
-
- dws->slave.dev = &pdev->dev;
- dws->slave.dma_dev = &dw_dmac0_device.dev;
- dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT;
+ dws->dma_dev = &dw_dmac0_device.dev;
+ dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
dws->cfg_hi = (DWC_CFGH_SRC_PER(0)
| DWC_CFGH_DST_PER(1));
dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL
| DWC_CFGL_HS_SRC_POL);
- data->dma_slave = &dws->slave;
-
if (platform_device_add_data(pdev, data,
sizeof(struct mci_platform_data)))
goto fail;
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 138a00a2a2d0..442f08c5e641 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -198,7 +198,7 @@ dump_clock(struct clk *parent, struct clkinf *r)
unsigned i;
/* skip clocks coupled to devices that aren't registered */
- if (parent->dev && !parent->dev->bus_id[0] && !parent->users)
+ if (parent->dev && !dev_name(parent->dev) && !parent->users)
return;
/* <nest spaces> name <pad to end> */
@@ -214,7 +214,7 @@ dump_clock(struct clk *parent, struct clkinf *r)
parent->users ? "on" : "off", /* NOTE: not-paranoid!! */
clk_get_rate(parent));
if (parent->dev)
- seq_printf(r->s, ", for %s", parent->dev->bus_id);
+ seq_printf(r->s, ", for %s", dev_name(parent->dev));
seq_printf(r->s, "\n");
/* cost of this scan is small, but not linear... */
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
index 623bf0e9a1e7..4c7ebbdc6dfa 100644
--- a/arch/avr32/mach-at32ap/clock.h
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -30,3 +30,6 @@ struct clk {
u16 users; /* Enabled if non-zero */
u16 index; /* Sibling index */
};
+
+unsigned long pba_clk_get_rate(struct clk *clk);
+void pba_clk_mode(struct clk *clk, int enabled);
diff --git a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h
index a77d372f6f3e..5c4c971eed8e 100644
--- a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h
+++ b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h
@@ -211,4 +211,7 @@
#define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA)
+/* Bitmask for all EBI data (D16..D31) pins on port E */
+#define ATMEL_EBI_PE_DATA_ALL (0x0000FFFF)
+
#endif /* __ASM_ARCH_AT32AP700X_H__ */
diff --git a/arch/avr32/mach-at32ap/include/mach/portmux.h b/arch/avr32/mach-at32ap/include/mach/portmux.h
index 21c79373b53f..4873024e3b96 100644
--- a/arch/avr32/mach-at32ap/include/mach/portmux.h
+++ b/arch/avr32/mach-at32ap/include/mach/portmux.h
@@ -25,6 +25,6 @@ void at32_select_periph(unsigned int port, unsigned int pin,
unsigned int periph, unsigned long flags);
void at32_select_gpio(unsigned int pin, unsigned long flags);
void at32_deselect_pin(unsigned int pin);
-void at32_reserve_pin(unsigned int pin);
+void at32_reserve_pin(unsigned int port, u32 pin_mask);
#endif /* __ASM_ARCH_PORTMUX_H__ */
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
index ed81a8bcb22d..09a274c9d0b7 100644
--- a/arch/avr32/mach-at32ap/pio.c
+++ b/arch/avr32/mach-at32ap/pio.c
@@ -167,22 +167,29 @@ void at32_deselect_pin(unsigned int pin)
}
/* Reserve a pin, preventing anyone else from changing its configuration. */
-void __init at32_reserve_pin(unsigned int pin)
+void __init at32_reserve_pin(unsigned int port, u32 pin_mask)
{
struct pio_device *pio;
- unsigned int pin_index = pin & 0x1f;
- pio = gpio_to_pio(pin);
+ /* assign and verify pio */
+ pio = gpio_to_pio(port);
if (unlikely(!pio)) {
- printk("pio: invalid pin %u\n", pin);
+ printk(KERN_WARNING "pio: invalid port %u\n", port);
goto fail;
}
- if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
- printk("%s: pin %u is busy\n", pio->name, pin_index);
+ /* Test if any of the requested pins is already muxed */
+ spin_lock(&pio_lock);
+ if (unlikely(pio->pinmux_mask & pin_mask)) {
+ printk(KERN_WARNING "%s: pin(s) busy (req. 0x%x, busy 0x%x)\n",
+ pio->name, pin_mask, pio->pinmux_mask & pin_mask);
+ spin_unlock(&pio_lock);
goto fail;
}
+ /* Reserve pins */
+ pio->pinmux_mask |= pin_mask;
+ spin_unlock(&pio_lock);
return;
fail:
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
index 15a4e5e142c1..24a74d1ca7d9 100644
--- a/arch/avr32/mm/cache.c
+++ b/arch/avr32/mm/cache.c
@@ -13,6 +13,7 @@
#include <asm/cachectl.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
+#include <asm/syscalls.h>
/*
* If you attempt to flush anything more than this, you need superuser
diff --git a/arch/avr32/mm/init.c b/arch/avr32/mm/init.c
index fa92ff6d95f7..e819fa69a90e 100644
--- a/arch/avr32/mm/init.c
+++ b/arch/avr32/mm/init.c
@@ -97,7 +97,6 @@ void __init paging_init(void)
mem_map = NODE_DATA(0)->node_mem_map;
- memset(zero_page, 0, PAGE_SIZE);
empty_zero_page = virt_to_page(zero_page);
flush_dcache_page(empty_zero_page);
}
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 29e71ed6b8a7..8f1f97d56e1e 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -26,6 +26,7 @@ config BLACKFIN
default y
select HAVE_IDE
select HAVE_OPROFILE
+ select ARCH_WANT_OPTIONAL_GPIOLIB
config ZONE_DMA
bool
@@ -59,10 +60,6 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
-config HARDWARE_PM
- def_bool y
- depends on OPROFILE
-
source "init/Kconfig"
source "kernel/Kconfig.preempt"
@@ -77,6 +74,26 @@ choice
prompt "CPU"
default BF533
+config BF512
+ bool "BF512"
+ help
+ BF512 Processor Support.
+
+config BF514
+ bool "BF514"
+ help
+ BF514 Processor Support.
+
+config BF516
+ bool "BF516"
+ help
+ BF516 Processor Support.
+
+config BF518
+ bool "BF518"
+ help
+ BF518 Processor Support.
+
config BF522
bool "BF522"
help
@@ -137,31 +154,66 @@ config BF537
help
BF537 Processor Support.
+config BF538
+ bool "BF538"
+ help
+ BF538 Processor Support.
+
+config BF539
+ bool "BF539"
+ help
+ BF539 Processor Support.
+
config BF542
bool "BF542"
help
BF542 Processor Support.
+config BF542M
+ bool "BF542m"
+ help
+ BF542 Processor Support.
+
config BF544
bool "BF544"
help
BF544 Processor Support.
+config BF544M
+ bool "BF544m"
+ help
+ BF544 Processor Support.
+
config BF547
bool "BF547"
help
BF547 Processor Support.
+config BF547M
+ bool "BF547m"
+ help
+ BF547 Processor Support.
+
config BF548
bool "BF548"
help
BF548 Processor Support.
+config BF548M
+ bool "BF548m"
+ help
+ BF548 Processor Support.
+
config BF549
bool "BF549"
help
BF549 Processor Support.
+config BF549M
+ bool "BF549m"
+ help
+ BF549 Processor Support.
+
config BF561
bool "BF561"
help
@@ -169,48 +221,75 @@ config BF561
endchoice
+config SMP
+ depends on BF561
+ bool "Symmetric multi-processing support"
+ ---help---
+ This enables support for systems with more than one CPU,
+ like the dual core BF561. If you have a system with only one
+ CPU, say N. If you have a system with more than one CPU, say Y.
+
+ If you don't know what to do here, say N.
+
+config NR_CPUS
+ int
+ depends on SMP
+ default 2 if BF561
+
+config IRQ_PER_CPU
+ bool
+ depends on SMP
+ default y
+
+config TICK_SOURCE_SYSTMR0
+ bool
+ select BFIN_GPTIMERS
+ depends on SMP
+ default y
+
config BF_REV_MIN
int
- default 0 if (BF52x || BF54x)
+ default 0 if (BF51x || BF52x || (BF54x && !BF54xM))
default 2 if (BF537 || BF536 || BF534)
- default 3 if (BF561 ||BF533 || BF532 || BF531)
+ default 3 if (BF561 || BF533 || BF532 || BF531 || BF54xM)
+ default 4 if (BF538 || BF539)
config BF_REV_MAX
int
- default 2 if (BF52x || BF54x)
- default 3 if (BF537 || BF536 || BF534)
- default 5 if (BF561)
+ default 2 if (BF51x || BF52x || (BF54x && !BF54xM))
+ default 3 if (BF537 || BF536 || BF534 || BF54xM)
+ default 5 if (BF561 || BF538 || BF539)
default 6 if (BF533 || BF532 || BF531)
choice
prompt "Silicon Rev"
- default BF_REV_0_1 if (BF52x || BF54x)
+ default BF_REV_0_1 if (BF51x || BF52x || (BF54x && !BF54xM))
default BF_REV_0_2 if (BF534 || BF536 || BF537)
- default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF561)
+ default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF54xM || BF561)
config BF_REV_0_0
bool "0.0"
- depends on (BF52x || BF54x)
+ depends on (BF51x || BF52x || (BF54x && !BF54xM))
config BF_REV_0_1
bool "0.1"
- depends on (BF52x || BF54x)
+ depends on (BF52x || (BF54x && !BF54xM))
config BF_REV_0_2
bool "0.2"
- depends on (BF52x || BF537 || BF536 || BF534 || BF54x)
+ depends on (BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM))
config BF_REV_0_3
bool "0.3"
- depends on (BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531)
+ depends on (BF54xM || BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531)
config BF_REV_0_4
bool "0.4"
- depends on (BF561 || BF533 || BF532 || BF531)
+ depends on (BF561 || BF533 || BF532 || BF531 || BF538 || BF539)
config BF_REV_0_5
bool "0.5"
- depends on (BF561 || BF533 || BF532 || BF531)
+ depends on (BF561 || BF533 || BF532 || BF531 || BF538 || BF539)
config BF_REV_0_6
bool "0.6"
@@ -224,6 +303,11 @@ config BF_REV_NONE
endchoice
+config BF51x
+ bool
+ depends on (BF512 || BF514 || BF516 || BF518)
+ default y
+
config BF52x
bool
depends on (BF522 || BF523 || BF524 || BF525 || BF526 || BF527)
@@ -234,9 +318,14 @@ config BF53x
depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
default y
+config BF54xM
+ bool
+ depends on (BF542M || BF544M || BF547M || BF548M || BF549M)
+ default y
+
config BF54x
bool
- depends on (BF542 || BF544 || BF547 || BF548 || BF549)
+ depends on (BF542 || BF544 || BF547 || BF548 || BF549 || BF54xM)
default y
config MEM_GENERIC_BOARD
@@ -258,7 +347,7 @@ config MEM_MT48LC16M16A2TG_75
config MEM_MT48LC32M8A2_75
bool
- depends on (BFIN537_STAMP || PNAV10)
+ depends on (BFIN537_STAMP || PNAV10 || BFIN538_EZKIT)
default y
config MEM_MT48LC8M32B2B5_7
@@ -271,10 +360,17 @@ config MEM_MT48LC32M16A2TG_75
depends on (BFIN527_EZKIT || BFIN532_IP0X || BLACKSTAMP || BFIN526_EZBRD)
default y
+config MEM_MT48LC32M8A2_75
+ bool
+ depends on (BFIN518F_EZBRD)
+ default y
+
+source "arch/blackfin/mach-bf518/Kconfig"
source "arch/blackfin/mach-bf527/Kconfig"
source "arch/blackfin/mach-bf533/Kconfig"
source "arch/blackfin/mach-bf561/Kconfig"
source "arch/blackfin/mach-bf537/Kconfig"
+source "arch/blackfin/mach-bf538/Kconfig"
source "arch/blackfin/mach-bf548/Kconfig"
menu "Board customizations"
@@ -307,6 +403,7 @@ config BOOT_LOAD
config ROM_BASE
hex "Kernel ROM Base"
+ depends on ROMKERNEL
default "0x20040000"
range 0x20000000 0x20400000 if !(BF54x || BF561)
range 0x20000000 0x30000000 if (BF54x || BF561)
@@ -318,7 +415,7 @@ config CLKIN_HZ
int "Frequency of the crystal on the board in Hz"
default "11059200" if BFIN533_STAMP
default "27000000" if BFIN533_EZKIT
- default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD)
+ default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT || H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN538_EZKIT || BFIN518F-EZBRD)
default "30000000" if BFIN561_EZKIT
default "24576000" if PNAV10
default "10000000" if BFIN532_IP0X
@@ -354,11 +451,11 @@ config VCO_MULT
range 1 64
default "22" if BFIN533_EZKIT
default "45" if BFIN533_STAMP
- default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM)
+ default "20" if (BFIN537_STAMP || BFIN527_EZKIT || BFIN548_EZKIT || BFIN548_BLUETECHNIX_CM || BFIN538_EZKIT)
default "22" if BFIN533_BLUETECHNIX_CM
default "20" if (BFIN537_BLUETECHNIX_CM || BFIN527_BLUETECHNIX_CM || BFIN561_BLUETECHNIX_CM)
default "20" if BFIN561_EZKIT
- default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD)
+ default "16" if (H8606_HVSISTEMAS || BLACKSTAMP || BFIN526_EZBRD || BFIN518F_EZBRD)
help
This controls the frequency of the on-chip PLL. This can be between 1 and 64.
PLL Frequency = (Crystal Frequency) * (this setting)
@@ -407,19 +504,70 @@ config MEM_MT46V32M16_5B
bool "MT46V32M16_5B"
endchoice
-config MAX_MEM_SIZE
- int "Max SDRAM Memory Size in MBytes"
- depends on !MPU
- default 512
+choice
+ prompt "DDR/SDRAM Timing"
+ depends on BFIN_KERNEL_CLOCK
+ default BFIN_KERNEL_CLOCK_MEMINIT_CALC
help
- This is the max memory size that the kernel will create CPLB
- tables for. Your system will not be able to handle any more.
+ This option allows you to specify Blackfin SDRAM/DDR Timing parameters
+ The calculated SDRAM timing parameters may not be 100%
+ accurate - This option is therefore marked experimental.
+
+config BFIN_KERNEL_CLOCK_MEMINIT_CALC
+ bool "Calculate Timings (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+
+config BFIN_KERNEL_CLOCK_MEMINIT_SPEC
+ bool "Provide accurate Timings based on target SCLK"
+ help
+ Please consult the Blackfin Hardware Reference Manuals as well
+ as the memory device datasheet.
+ http://docs.blackfin.uclinux.org/doku.php?id=bfin:sdram
+endchoice
+
+menu "Memory Init Control"
+ depends on BFIN_KERNEL_CLOCK_MEMINIT_SPEC
+
+config MEM_DDRCTL0
+ depends on BF54x
+ hex "DDRCTL0"
+ default 0x0
+
+config MEM_DDRCTL1
+ depends on BF54x
+ hex "DDRCTL1"
+ default 0x0
+
+config MEM_DDRCTL2
+ depends on BF54x
+ hex "DDRCTL2"
+ default 0x0
+
+config MEM_EBIU_DDRQUE
+ depends on BF54x
+ hex "DDRQUE"
+ default 0x0
+
+config MEM_SDRRC
+ depends on !BF54x
+ hex "SDRRC"
+ default 0x0
+
+config MEM_SDGCTL
+ depends on !BF54x
+ hex "SDGCTL"
+ default 0x0
+endmenu
#
# Max & Min Speeds for various Chips
#
config MAX_VCO_HZ
int
+ default 400000000 if BF512
+ default 400000000 if BF514
+ default 400000000 if BF516
+ default 400000000 if BF518
default 600000000 if BF522
default 400000000 if BF523
default 400000000 if BF524
@@ -459,6 +607,7 @@ source kernel/Kconfig.hz
config GENERIC_TIME
bool "Generic time"
+ depends on !SMP
default y
config GENERIC_CLOCKEVENTS
@@ -533,6 +682,7 @@ endmenu
menu "Blackfin Kernel Optimizations"
+ depends on !SMP
comment "Memory Optimizations"
@@ -655,6 +805,17 @@ config APP_STACK_L1
Currently only works with FLAT binaries.
+config EXCEPTION_L1_SCRATCH
+ bool "Locate exception stack in L1 Scratch Memory"
+ default n
+ depends on !APP_STACK_L1 && !SYSCALL_TAB_L1
+ help
+ Whenever an exception occurs, use the L1 Scratch memory for
+ stack storage. You cannot place the stacks of FLAT binaries
+ in L1 when using this option.
+
+ If you don't use L1 Scratch, then you should say Y here.
+
comment "Speed Optimizations"
config BFIN_INS_LOWOVERHEAD
bool "ins[bwl] low overhead, higher interrupt latency"
@@ -684,7 +845,6 @@ config BFIN_INS_LOWOVERHEAD
endmenu
-
choice
prompt "Kernel executes from"
help
@@ -714,17 +874,9 @@ config BFIN_GPTIMERS
To compile this driver as a module, choose M here: the module
will be called gptimers.ko.
-config BFIN_DMA_5XX
- bool "Enable DMA Support"
- depends on (BF52x || BF53x || BF561 || BF54x)
- default y
- help
- DMA driver for BF5xx.
-
choice
- prompt "Uncached SDRAM region"
+ prompt "Uncached DMA region"
default DMA_UNCACHED_1M
- depends on BFIN_DMA_5XX
config DMA_UNCACHED_4M
bool "Enable 4M DMA region"
config DMA_UNCACHED_2M
@@ -751,9 +903,11 @@ config BFIN_ICACHE_LOCK
choice
prompt "Policy"
depends on BFIN_DCACHE
- default BFIN_WB
+ default BFIN_WB if !SMP
+ default BFIN_WT if SMP
config BFIN_WB
bool "Write back"
+ depends on !SMP
help
Write Back Policy:
Cached data will be written back to SDRAM only when needed.
@@ -790,7 +944,7 @@ endchoice
config BFIN_L2_CACHEABLE
bool "Cache L2 SRAM"
- depends on (BFIN_DCACHE || BFIN_ICACHE) && (BF54x || BF561)
+ depends on (BFIN_DCACHE || BFIN_ICACHE) && (BF54x || (BF561 && !SMP))
default n
help
Select to make L2 SRAM cacheable in L1 data and instruction cache.
@@ -980,7 +1134,7 @@ config PM_WAKEUP_GPIO_NUMBER
int "GPIO number"
range 0 47
depends on PM_WAKEUP_BY_GPIO
- default 2 if BFIN537_STAMP
+ default 2
choice
prompt "GPIO Polarity"
@@ -1003,7 +1157,7 @@ comment "Possible Suspend Mem / Hibernate Wake-Up Sources"
config PM_BFIN_WAKE_PH6
bool "Allow Wake-Up from on-chip PHY or PH6 GP"
- depends on PM && (BF52x || BF534 || BF536 || BF537)
+ depends on PM && (BF51x || BF52x || BF534 || BF536 || BF537)
default n
help
Enable PHY and PH6 GP Wake-Up (Voltage Regulator Power-Up)
@@ -1020,15 +1174,21 @@ menu "CPU Frequency scaling"
source "drivers/cpufreq/Kconfig"
+config BFIN_CPU_FREQ
+ bool
+ depends on CPU_FREQ
+ select CPU_FREQ_TABLE
+ default y
+
config CPU_VOLTAGE
bool "CPU Voltage scaling"
- depends on EXPERIMENTAL
+ depends on EXPERIMENTAL
depends on CPU_FREQ
default n
help
Say Y here if you want CPU voltage scaling according to the CPU frequency.
This option violates the PLL BYPASS recommendation in the Blackfin Processor
- manuals. There is a theoretical risk that during VDDINT transitions
+ manuals. There is a theoretical risk that during VDDINT transitions
the PLL may unlock.
endmenu
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug
index 3ad25983ec97..5f981d9ca625 100644
--- a/arch/blackfin/Kconfig.debug
+++ b/arch/blackfin/Kconfig.debug
@@ -2,8 +2,30 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
+config DEBUG_STACKOVERFLOW
+ bool "Check for stack overflows"
+ depends on DEBUG_KERNEL
+ help
+ This option will cause messages to be printed if free stack space
+ drops below a certain limit.
+
+config DEBUG_STACK_USAGE
+ bool "Enable stack utilization instrumentation"
+ depends on DEBUG_KERNEL
+ help
+ Enables the display of the minimum amount of free stack which each
+ task has ever had available in the sysrq-T output.
+
+ This option will slow down process creation somewhat.
+
config HAVE_ARCH_KGDB
- def_bool y
+ def_bool y
+
+config KGDB_TESTCASE
+ tristate "KGDB: for test case in expect"
+ default n
+ help
+ This is a kgdb test case for automated testing.
config DEBUG_VERBOSE
bool "Verbose fault messages"
@@ -182,11 +204,11 @@ config DEBUG_BFIN_HWTRACE_EXPAND_LEN
4 for (2^4) 16k, or 4096 entries
config DEBUG_BFIN_NO_KERN_HWTRACE
- bool "Trace user apps (turn off hwtrace in kernel)"
+ bool "Turn off hwtrace in CPLB handlers"
depends on DEBUG_BFIN_HWTRACE_ON
- default n
+ default y
help
- Some pieces of the kernel contain a lot of flow changes which can
+ The CPLB error handler contains a lot of flow changes which can
quickly fill up the hardware trace buffer. When debugging crashes,
the hardware trace may indicate that the problem lies in kernel
space when in reality an application is buggy.
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 6bf50977850c..d54c8283825c 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -21,45 +21,67 @@ KALLSYMS += --symbol-prefix=_
KBUILD_DEFCONFIG := BF537-STAMP_defconfig
# setup the machine name and the machine dependent settings
-machine-$(CONFIG_BF522) := bf527
-machine-$(CONFIG_BF523) := bf527
-machine-$(CONFIG_BF524) := bf527
-machine-$(CONFIG_BF525) := bf527
-machine-$(CONFIG_BF526) := bf527
-machine-$(CONFIG_BF527) := bf527
-machine-$(CONFIG_BF531) := bf533
-machine-$(CONFIG_BF532) := bf533
-machine-$(CONFIG_BF533) := bf533
-machine-$(CONFIG_BF534) := bf537
-machine-$(CONFIG_BF536) := bf537
-machine-$(CONFIG_BF537) := bf537
-machine-$(CONFIG_BF542) := bf548
-machine-$(CONFIG_BF544) := bf548
-machine-$(CONFIG_BF547) := bf548
-machine-$(CONFIG_BF548) := bf548
-machine-$(CONFIG_BF549) := bf548
-machine-$(CONFIG_BF561) := bf561
+machine-$(CONFIG_BF512) := bf518
+machine-$(CONFIG_BF514) := bf518
+machine-$(CONFIG_BF516) := bf518
+machine-$(CONFIG_BF518) := bf518
+machine-$(CONFIG_BF522) := bf527
+machine-$(CONFIG_BF523) := bf527
+machine-$(CONFIG_BF524) := bf527
+machine-$(CONFIG_BF525) := bf527
+machine-$(CONFIG_BF526) := bf527
+machine-$(CONFIG_BF527) := bf527
+machine-$(CONFIG_BF531) := bf533
+machine-$(CONFIG_BF532) := bf533
+machine-$(CONFIG_BF533) := bf533
+machine-$(CONFIG_BF534) := bf537
+machine-$(CONFIG_BF536) := bf537
+machine-$(CONFIG_BF537) := bf537
+machine-$(CONFIG_BF538) := bf538
+machine-$(CONFIG_BF539) := bf538
+machine-$(CONFIG_BF542) := bf548
+machine-$(CONFIG_BF542M) := bf548
+machine-$(CONFIG_BF544) := bf548
+machine-$(CONFIG_BF544M) := bf548
+machine-$(CONFIG_BF547) := bf548
+machine-$(CONFIG_BF547M) := bf548
+machine-$(CONFIG_BF548) := bf548
+machine-$(CONFIG_BF548M) := bf548
+machine-$(CONFIG_BF549) := bf548
+machine-$(CONFIG_BF549M) := bf548
+machine-$(CONFIG_BF561) := bf561
MACHINE := $(machine-y)
export MACHINE
-cpu-$(CONFIG_BF522) := bf522
-cpu-$(CONFIG_BF523) := bf523
-cpu-$(CONFIG_BF524) := bf524
-cpu-$(CONFIG_BF525) := bf525
-cpu-$(CONFIG_BF526) := bf526
-cpu-$(CONFIG_BF527) := bf527
-cpu-$(CONFIG_BF531) := bf531
-cpu-$(CONFIG_BF532) := bf532
-cpu-$(CONFIG_BF533) := bf533
-cpu-$(CONFIG_BF534) := bf534
-cpu-$(CONFIG_BF536) := bf536
-cpu-$(CONFIG_BF537) := bf537
-cpu-$(CONFIG_BF542) := bf542
-cpu-$(CONFIG_BF544) := bf544
-cpu-$(CONFIG_BF547) := bf547
-cpu-$(CONFIG_BF548) := bf548
-cpu-$(CONFIG_BF549) := bf549
-cpu-$(CONFIG_BF561) := bf561
+cpu-$(CONFIG_BF512) := bf512
+cpu-$(CONFIG_BF514) := bf514
+cpu-$(CONFIG_BF516) := bf516
+cpu-$(CONFIG_BF518) := bf518
+cpu-$(CONFIG_BF522) := bf522
+cpu-$(CONFIG_BF523) := bf523
+cpu-$(CONFIG_BF524) := bf524
+cpu-$(CONFIG_BF525) := bf525
+cpu-$(CONFIG_BF526) := bf526
+cpu-$(CONFIG_BF527) := bf527
+cpu-$(CONFIG_BF531) := bf531
+cpu-$(CONFIG_BF532) := bf532
+cpu-$(CONFIG_BF533) := bf533
+cpu-$(CONFIG_BF534) := bf534
+cpu-$(CONFIG_BF536) := bf536
+cpu-$(CONFIG_BF537) := bf537
+cpu-$(CONFIG_BF538) := bf538
+cpu-$(CONFIG_BF539) := bf539
+cpu-$(CONFIG_BF542) := bf542
+cpu-$(CONFIG_BF542M) := bf542m
+cpu-$(CONFIG_BF544) := bf544
+cpu-$(CONFIG_BF544M) := bf544m
+cpu-$(CONFIG_BF547) := bf547
+cpu-$(CONFIG_BF547M) := bf547m
+cpu-$(CONFIG_BF548) := bf548
+cpu-$(CONFIG_BF548M) := bf548m
+cpu-$(CONFIG_BF549) := bf549
+cpu-$(CONFIG_BF549M) := bf549m
+cpu-$(CONFIG_BF561) := bf561
rev-$(CONFIG_BF_REV_0_0) := 0.0
rev-$(CONFIG_BF_REV_0_1) := 0.1
@@ -79,7 +101,7 @@ KBUILD_AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
CHECKFLAGS_SILICON = $(shell echo "" | $(CPP) $(KBUILD_CFLAGS) -dD - 2>/dev/null | awk '$$2 == "__SILICON_REVISION__" { print $$3 }')
CHECKFLAGS += -D__SILICON_REVISION__=$(CHECKFLAGS_SILICON) -Dl1_text=__used__
-head-y := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
+head-y := arch/$(ARCH)/kernel/init_task.o
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ arch/$(ARCH)/mach-common/
@@ -95,10 +117,10 @@ else
core-y += arch/$(ARCH)/kernel/cplb-nompu/
endif
-libs-y += arch/$(ARCH)/lib/
-
drivers-$(CONFIG_OPROFILE) += arch/$(ARCH)/oprofile/
+libs-y += arch/$(ARCH)/lib/
+
machdirs := $(patsubst %,arch/blackfin/mach-%/, $(machine-y))
KBUILD_CFLAGS += -Iarch/$(ARCH)/include/
diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig
new file mode 100644
index 000000000000..4fdb9e04759f
--- /dev/null
+++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig
@@ -0,0 +1,1196 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-rc2
+# Fri Jan 9 17:58:41 2009
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+CONFIG_BF518=y
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=0
+CONFIG_BF_REV_MAX=2
+CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF51x=y
+CONFIG_MEM_MT48LC32M8A2_75=y
+CONFIG_BFIN518F_EZBRD=y
+
+#
+# BF518 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF518_SPORT0_PORTF is not set
+CONFIG_BF518_SPORT0_PORTG=y
+CONFIG_BF518_SPORT0_TSCLK_PG10=y
+# CONFIG_BF518_SPORT0_TSCLK_PG14 is not set
+CONFIG_BF518_UART1_PORTF=y
+# CONFIG_BF518_UART1_PORTG is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_DMA0_ERROR=7
+CONFIG_IRQ_DMAR0_BLK=7
+CONFIG_IRQ_DMAR1_BLK=7
+CONFIG_IRQ_DMAR0_OVR=7
+CONFIG_IRQ_DMAR1_OVR=7
+CONFIG_IRQ_PPI_ERROR=7
+CONFIG_IRQ_MAC_ERROR=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_PTP_ERROR=7
+CONFIG_IRQ_UART0_ERROR=7
+CONFIG_IRQ_UART1_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI0=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_OPTSEC=11
+CONFIG_IRQ_CNT=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_PORTH_INTA=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_PORTH_INTB=11
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
+CONFIG_IRQ_PORTG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_PORTF_INTA=13
+CONFIG_IRQ_PORTF_INTB=13
+CONFIG_IRQ_SPI0_ERROR=7
+CONFIG_IRQ_SPI1_ERROR=7
+CONFIG_IRQ_RSI_INT0=7
+CONFIG_IRQ_RSI_INT1=7
+CONFIG_IRQ_PWM_TRIP=10
+CONFIG_IRQ_PWM_SYNC=10
+CONFIG_IRQ_PTP_STAT=10
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=400000000
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Misc
+#
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+# CONFIG_SCHEDULE_L1 is not set
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+# CONFIG_MEMSET_L1 is not set
+# CONFIG_MEMCPY_L1 is not set
+# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_BFIN_GPTIMERS=y
+# CONFIG_DMA_UNCACHED_4M is not set
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+CONFIG_BFIN_WB=y
+# CONFIG_BFIN_WT is not set
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x5554
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0xFFC0
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_GPIO_ADDR is not set
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+# CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMC91X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_CONFIG_INPUT_PCF8574 is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+# CONFIG_BFIN_SPORT is not set
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_TWI_LCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+CONFIG_SIMPLE_GPIO=m
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART1 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_SENSORS_AD5252 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 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
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_BFIN=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# 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_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_YAFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
+CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
index 4443a47e516f..8e2b855b8db7 100644
--- a/arch/blackfin/configs/BF526-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF526-EZBRD_defconfig
@@ -1,7 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26.3
-# Thu Aug 28 16:49:53 2008
+# Linux kernel version: 2.6.28-rc2
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -37,8 +36,7 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED 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=y
@@ -48,13 +46,13 @@ CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
@@ -63,6 +61,7 @@ CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
@@ -70,9 +69,7 @@ CONFIG_SLAB=y
# CONFIG_PROFILING is not set
# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
@@ -89,6 +86,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -106,6 +104,7 @@ CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
#
# Blackfin Processor Options
@@ -114,6 +113,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -126,49 +129,27 @@ CONFIG_BF526=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=0
+CONFIG_BF_REV_MAX=2
CONFIG_BF_REV_0_0=y
# CONFIG_BF_REV_0_1 is not set
# CONFIG_BF_REV_0_2 is not set
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF52x=y
CONFIG_MEM_MT48LC32M16A2TG_75=y
-# CONFIG_BFIN527_EZKIT is not set
-# CONFIG_BFIN527_BLUETECHNIX_CM is not set
-CONFIG_BFIN526_EZBRD=y
-
-#
-# BF527 Specific Configuration
-#
-
-#
-# Alternative Multiplexing Scheme
-#
-# CONFIG_BF527_SPORT0_PORTF is not set
-CONFIG_BF527_SPORT0_PORTG=y
-CONFIG_BF527_SPORT0_TSCLK_PG10=y
-# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
-CONFIG_BF527_UART1_PORTF=y
-# CONFIG_BF527_UART1_PORTG is not set
-# CONFIG_BF527_NAND_D_PORTF is not set
-CONFIG_BF527_NAND_D_PORTH=y
-
-#
-# Interrupt Priority Assignment
-#
-
-#
-# Priority
-#
CONFIG_IRQ_PLL_WAKEUP=7
CONFIG_IRQ_DMA0_ERROR=7
CONFIG_IRQ_DMAR0_BLK=7
@@ -188,7 +169,6 @@ CONFIG_IRQ_SPORT0_TX=9
CONFIG_IRQ_SPORT1_RX=9
CONFIG_IRQ_SPORT1_TX=9
CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
CONFIG_IRQ_UART0_RX=10
CONFIG_IRQ_UART0_TX=10
CONFIG_IRQ_UART1_RX=10
@@ -199,14 +179,14 @@ CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_PORTH_INTA=11
CONFIG_IRQ_MAC_TX=11
CONFIG_IRQ_PORTH_INTB=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTA=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
@@ -214,6 +194,34 @@ CONFIG_IRQ_MEM_DMA1=13
CONFIG_IRQ_WATCH=13
CONFIG_IRQ_PORTF_INTA=13
CONFIG_IRQ_PORTF_INTB=13
+# CONFIG_BFIN527_EZKIT is not set
+# CONFIG_BFIN527_BLUETECHNIX_CM is not set
+CONFIG_BFIN526_EZBRD=y
+
+#
+# BF527 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF527_SPORT0_PORTF is not set
+CONFIG_BF527_SPORT0_PORTG=y
+CONFIG_BF527_SPORT0_TSCLK_PG10=y
+# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
+CONFIG_BF527_UART1_PORTF=y
+# CONFIG_BF527_UART1_PORTG is not set
+# CONFIG_BF527_NAND_D_PORTF is not set
+CONFIG_BF527_NAND_D_PORTH=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_SPI=10
CONFIG_IRQ_SPI_ERROR=7
CONFIG_IRQ_NFC_ERROR=7
CONFIG_IRQ_HDMA_ERROR=7
@@ -235,7 +243,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=400000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -253,16 +260,11 @@ CONFIG_HZ=250
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
#
-# Memory Setup
-#
-
-#
# Misc
#
CONFIG_BFIN_SCRATCH_REG_RETN=y
@@ -291,6 +293,7 @@ CONFIG_ACCESS_OK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
#
# Speed Optimizations
@@ -304,15 +307,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
CONFIG_BFIN_GPTIMERS=y
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -365,6 +366,7 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
@@ -378,10 +380,6 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -432,6 +430,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -452,11 +451,10 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -474,6 +472,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -534,7 +534,8 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
# Self-contained MTD device drivers
#
# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
+CONFIG_MTD_M25P80=y
+CONFIG_M25PXX_USE_FAST_READ=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
@@ -579,6 +580,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
@@ -595,7 +597,6 @@ CONFIG_HAVE_IDE=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -633,9 +634,10 @@ CONFIG_BFIN_MAC_RMII=y
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
-# CONFIG_E1000E_ENABLED is not set
# CONFIG_AX88180 is not set
CONFIG_NETDEV_10000=y
@@ -667,7 +669,7 @@ CONFIG_NETDEV_10000=y
# Input device support
#
CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_POLLDEV is not set
#
@@ -692,8 +694,9 @@ CONFIG_INPUT_MISC=y
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
# CONFIG_INPUT_UINPUT is not set
-# CONFIG_TWI_KEYPAD is not set
+# CONFIG_CONFIG_INPUT_PCF8574 is not set
#
# Hardware I/O ports
@@ -712,12 +715,15 @@ CONFIG_INPUT_MISC=y
# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_TWI_LCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
-CONFIG_DEVKMEM=y
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -760,25 +766,39 @@ CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
CONFIG_I2C_BLACKFIN_TWI=y
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
@@ -787,25 +807,31 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -834,6 +860,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -871,16 +898,14 @@ CONFIG_BFIN_WDT=y
# CONFIG_USBPCWATCHDOG is not set
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
#
# Multimedia devices
@@ -915,15 +940,8 @@ CONFIG_SSB_POSSIBLE=y
# Console display driver support
#
CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
@@ -937,56 +955,40 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-
-#
-# SPI devices
-#
+CONFIG_SND_SPI=y
#
# ALSA Blackfin devices
#
# CONFIG_SND_BLACKFIN_AD1836 is not set
-# CONFIG_SND_BFIN_AD73311 is not set
# CONFIG_SND_BFIN_AD73322 is not set
-
-#
-# USB devices
-#
+CONFIG_SND_USB=y
# CONFIG_SND_USB_AUDIO is not set
# CONFIG_SND_USB_CAIAQ is not set
-
-#
-# System on Chip audio support
-#
CONFIG_SND_SOC=m
+CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_BF5XX_I2S=m
CONFIG_SND_BF5XX_SOC_SSM2602=m
-# CONFIG_SND_BF5XX_AC97 is not set
+# CONFIG_SND_BF5XX_SOC_AD73311 is not set
+CONFIG_SND_BF5XX_AC97=m
+CONFIG_SND_BF5XX_MMAP_SUPPORT=y
+# CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set
CONFIG_SND_BF5XX_SOC_SPORT=m
CONFIG_SND_BF5XX_SOC_I2S=m
+CONFIG_SND_BF5XX_SOC_AC97=m
+CONFIG_SND_BF5XX_SOC_AD1980=m
CONFIG_SND_BF5XX_SPORT_NUM=0
-
-#
-# ALSA SoC audio for Freescale SOCs
-#
-
-#
-# SoC Audio for the Texas Instruments OMAP
-#
+# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_AD1980=m
CONFIG_SND_SOC_SSM2602=m
-
-#
-# Open Sound System
-#
# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
@@ -996,9 +998,36 @@ CONFIG_HID=y
# USB Input Devices
#
CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -1016,6 +1045,9 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1026,6 +1058,7 @@ CONFIG_USB_OTG_BLACKLIST_HUB=y
# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_SOC=y
@@ -1037,7 +1070,7 @@ CONFIG_USB_MUSB_HOST=y
# CONFIG_USB_MUSB_OTG is not set
CONFIG_USB_MUSB_HDRC_HCD=y
CONFIG_MUSB_PIO_ONLY=y
-CONFIG_USB_MUSB_LOGLEVEL=0
+# CONFIG_USB_MUSB_DEBUG is not set
#
# USB Device Class drivers
@@ -1045,6 +1078,7 @@ CONFIG_USB_MUSB_LOGLEVEL=0
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1059,7 +1093,6 @@ CONFIG_USB_MUSB_LOGLEVEL=0
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
-CONFIG_USB_MON=y
#
# USB port drivers
@@ -1072,7 +1105,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -1089,6 +1122,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1128,36 +1162,45 @@ CONFIG_RTC_INTF_DEV=y
#
# SPI RTC drivers
#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_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_OCFS2_FS is not set
# CONFIG_DNOTIFY is not set
@@ -1225,6 +1268,7 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -1240,7 +1284,7 @@ CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1308,10 +1352,48 @@ CONFIG_FRAME_WARN=1024
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1329,8 +1411,9 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_SECURITY_ROOTPLUG is not set
CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
CONFIG_CRYPTO=y
@@ -1338,6 +1421,7 @@ CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
@@ -1376,6 +1460,10 @@ CONFIG_CRYPTO=y
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
@@ -1406,15 +1494,20 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index 4a2a660a6b35..833128b39724 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
+# Linux kernel version: 2.6.28-rc2
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -31,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -51,26 +48,35 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -81,6 +87,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -94,9 +101,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
#
# Blackfin Processor Options
@@ -105,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -117,47 +130,27 @@ CONFIG_BF527=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=0
+CONFIG_BF_REV_MAX=2
CONFIG_BF_REV_0_0=y
# CONFIG_BF_REV_0_1 is not set
# CONFIG_BF_REV_0_2 is not set
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF52x=y
CONFIG_MEM_MT48LC32M16A2TG_75=y
-CONFIG_BFIN527_EZKIT=y
-
-#
-# BF527 Specific Configuration
-#
-
-#
-# Alternative Multiplexing Scheme
-#
-# CONFIG_BF527_SPORT0_PORTF is not set
-CONFIG_BF527_SPORT0_PORTG=y
-CONFIG_BF527_SPORT0_TSCLK_PG10=y
-# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
-CONFIG_BF527_UART1_PORTF=y
-# CONFIG_BF527_UART1_PORTG is not set
-# CONFIG_BF527_NAND_D_PORTF is not set
-CONFIG_BF527_NAND_D_PORTH=y
-
-#
-# Interrupt Priority Assignment
-#
-
-#
-# Priority
-#
CONFIG_IRQ_PLL_WAKEUP=7
CONFIG_IRQ_DMA0_ERROR=7
CONFIG_IRQ_DMAR0_BLK=7
@@ -177,7 +170,6 @@ CONFIG_IRQ_SPORT0_TX=9
CONFIG_IRQ_SPORT1_RX=9
CONFIG_IRQ_SPORT1_TX=9
CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
CONFIG_IRQ_UART0_RX=10
CONFIG_IRQ_UART0_TX=10
CONFIG_IRQ_UART1_RX=10
@@ -188,14 +180,14 @@ CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_PORTH_INTA=11
CONFIG_IRQ_MAC_TX=11
CONFIG_IRQ_PORTH_INTB=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=8
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTA=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
@@ -203,6 +195,34 @@ CONFIG_IRQ_MEM_DMA1=13
CONFIG_IRQ_WATCH=13
CONFIG_IRQ_PORTF_INTA=13
CONFIG_IRQ_PORTF_INTB=13
+CONFIG_BFIN527_EZKIT=y
+# CONFIG_BFIN527_BLUETECHNIX_CM is not set
+# CONFIG_BFIN526_EZBRD is not set
+
+#
+# BF527 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF527_SPORT0_PORTF is not set
+CONFIG_BF527_SPORT0_PORTG=y
+CONFIG_BF527_SPORT0_TSCLK_PG10=y
+# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
+CONFIG_BF527_UART1_PORTF=y
+# CONFIG_BF527_UART1_PORTG is not set
+# CONFIG_BF527_NAND_D_PORTF is not set
+CONFIG_BF527_NAND_D_PORTH=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_SPI=10
CONFIG_IRQ_SPI_ERROR=7
CONFIG_IRQ_NFC_ERROR=7
CONFIG_IRQ_HDMA_ERROR=7
@@ -224,7 +244,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -238,10 +257,10 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -275,6 +294,12 @@ CONFIG_ACCESS_OK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -283,14 +308,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
CONFIG_BFIN_GPTIMERS=y
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -305,7 +329,6 @@ CONFIG_BFIN_DCACHE=y
# CONFIG_BFIN_ICACHE_LOCK is not set
# CONFIG_BFIN_WB is not set
CONFIG_BFIN_WT=y
-CONFIG_L1_MAX_PIECE=16
# CONFIG_MPU is not set
#
@@ -334,7 +357,6 @@ CONFIG_BANK_3=0xFFC0
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -345,23 +367,20 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -374,6 +393,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -403,8 +423,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -413,6 +431,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -429,6 +448,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
CONFIG_IRDA=m
#
@@ -467,15 +487,6 @@ CONFIG_SIR_BFIN_DMA=y
# CONFIG_KS959_DONGLE is not set
#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
# FIR device drivers
#
# CONFIG_USB_IRDA is not set
@@ -483,11 +494,10 @@ CONFIG_SIR_BFIN_DMA=y
# CONFIG_MCS_FIR is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -505,6 +515,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -513,6 +525,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -556,6 +569,7 @@ CONFIG_MTD_ROM=m
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
@@ -563,7 +577,8 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
# Self-contained MTD device drivers
#
# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
+CONFIG_MTD_M25P80=y
+CONFIG_M25PXX_USE_FAST_READ=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
@@ -605,11 +620,14 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -622,7 +640,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -643,6 +660,7 @@ CONFIG_PHYLIB=y
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -655,11 +673,14 @@ CONFIG_BFIN_MAC_RMII=y
# CONFIG_SMC91X is not set
# CONFIG_SMSC911X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
# CONFIG_AX88180 is not set
CONFIG_NETDEV_10000=y
@@ -669,6 +690,7 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
@@ -681,7 +703,6 @@ CONFIG_NETDEV_10000=y
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -692,7 +713,7 @@ CONFIG_NETDEV_10000=y
# Input device support
#
CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_POLLDEV is not set
#
@@ -717,8 +738,9 @@ CONFIG_INPUT_MISC=y
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
# CONFIG_INPUT_UINPUT is not set
-# CONFIG_TWI_KEYPAD is not set
+# CONFIG_CONFIG_INPUT_PCF8574 is not set
#
# Hardware I/O ports
@@ -734,16 +756,18 @@ CONFIG_INPUT_MISC=y
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BFIN_SIMPLE_TIMER is not set
# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_OTP=y
-# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_TWI_LCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -766,6 +790,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_BFIN_SPORT is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
#
# CAN, the car bus and industrial fieldbus
@@ -773,44 +799,49 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_CAN4LINUX is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_BLACKFIN_TWI=m
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
@@ -819,30 +850,32 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -850,6 +883,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -870,6 +904,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -878,6 +913,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
@@ -885,9 +921,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -903,21 +942,29 @@ CONFIG_BFIN_WDT=y
# CONFIG_USBPCWATCHDOG is not set
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -928,6 +975,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -935,8 +983,8 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -947,12 +995,18 @@ CONFIG_FB_DEFERRED_IO=y
# Frame buffer hardware drivers
#
CONFIG_FB_BFIN_T350MCQB=y
+# CONFIG_FB_BFIN_LQ035Q1 is not set
# CONFIG_FB_BFIN_7393 is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=m
CONFIG_LCD_LTV350QV=m
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=m
# CONFIG_BACKLIGHT_CORGI is not set
@@ -977,15 +1031,8 @@ CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_CLUT224 is not set
# CONFIG_LOGO_BLACKFIN_VGA16 is not set
CONFIG_LOGO_BLACKFIN_CLUT224=y
-
-#
-# Sound
-#
CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
+# CONFIG_SOUND_OSS_CORE is not set
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
@@ -997,62 +1044,38 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-
-#
-# SPI devices
-#
+CONFIG_SND_SPI=y
#
# ALSA Blackfin devices
#
# CONFIG_SND_BLACKFIN_AD1836 is not set
-# CONFIG_SND_BLACKFIN_AD1836_TDM is not set
-# CONFIG_SND_BLACKFIN_AD1836_I2S is not set
-# CONFIG_SND_BLACKFIN_AD1836_MULSUB is not set
-# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
-# CONFIG_SND_BFIN_AD73311 is not set
# CONFIG_SND_BFIN_AD73322 is not set
-
-#
-# USB devices
-#
+CONFIG_SND_USB=y
# CONFIG_SND_USB_AUDIO is not set
# CONFIG_SND_USB_CAIAQ is not set
-
-#
-# System on Chip audio support
-#
-CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC=m
-CONFIG_SND_BF5XX_SOC=m
-CONFIG_SND_MMAP_SUPPORT=y
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_BF5XX_I2S=m
+CONFIG_SND_BF5XX_SOC_SSM2602=m
+# CONFIG_SND_BF5XX_SOC_AD73311 is not set
+CONFIG_SND_BF5XX_AC97=m
+CONFIG_SND_BF5XX_MMAP_SUPPORT=y
+# CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set
+CONFIG_SND_BF5XX_SOC_SPORT=m
CONFIG_SND_BF5XX_SOC_I2S=m
CONFIG_SND_BF5XX_SOC_AC97=m
-# CONFIG_SND_BF5XX_SOC_WM8750 is not set
-# CONFIG_SND_BF5XX_SOC_WM8731 is not set
-CONFIG_SND_BF5XX_SOC_SSM2602=m
-CONFIG_SND_BF5XX_SOC_BF5xx=m
+CONFIG_SND_BF5XX_SOC_AD1980=m
CONFIG_SND_BF5XX_SPORT_NUM=0
# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
-
-#
-# SoC Audio support for SuperH
-#
-CONFIG_SND_SOC_SSM2602=m
-# CONFIG_SND_SOC_SSM2602_SPI is not set
+# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_AD1980=m
-
-#
-# Open Sound System
-#
+CONFIG_SND_SOC_SSM2602=m
# CONFIG_SOUND_PRIME is not set
CONFIG_AC97_BUS=m
CONFIG_HID_SUPPORT=y
@@ -1064,15 +1087,43 @@ CONFIG_HID=y
# USB Input Devices
#
CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
@@ -1083,15 +1134,20 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_SOC=y
@@ -1103,13 +1159,15 @@ CONFIG_USB_MUSB_HOST=y
# CONFIG_USB_MUSB_OTG is not set
CONFIG_USB_MUSB_HDRC_HCD=y
CONFIG_MUSB_PIO_ONLY=y
-CONFIG_USB_MUSB_LOGLEVEL=0
+# CONFIG_USB_MUSB_DEBUG is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1124,15 +1182,10 @@ CONFIG_USB_MUSB_LOGLEVEL=0
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
-CONFIG_USB_MON=y
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
@@ -1141,7 +1194,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -1157,17 +1210,13 @@ CONFIG_USB_MON=y
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1196,51 +1245,57 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
#
# SPI RTC drivers
#
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1280,11 +1335,11 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
CONFIG_YAFFS_FS=m
CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
@@ -1301,8 +1356,11 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -1310,13 +1368,12 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1372,9 +1429,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -1382,14 +1436,53 @@ CONFIG_INSTRUMENTATION=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1407,10 +1500,95 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_SECURITY_ROOTPLUG is not set
-# CONFIG_CRYPTO is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1418,6 +1596,7 @@ CONFIG_SECURITY=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index deeb5e45effb..334c94b51c40 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
+# Linux kernel version: 2.6.28-rc2
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -31,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -51,26 +48,35 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -81,6 +87,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -94,9 +101,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+CONFIG_FREEZER=y
#
# Blackfin Processor Options
@@ -105,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -117,24 +130,30 @@ CONFIG_BF533=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=3
+CONFIG_BF_REV_MAX=6
# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_1 is not set
# CONFIG_BF_REV_0_2 is not set
CONFIG_BF_REV_0_3=y
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF53x=y
CONFIG_MEM_MT48LC16M16A2TG_75=y
CONFIG_BFIN533_EZKIT=y
# CONFIG_BFIN533_STAMP is not set
+# CONFIG_BLACKSTAMP is not set
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_H8606_HVSISTEMAS is not set
# CONFIG_BFIN532_IP0X is not set
@@ -187,7 +206,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=27000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=750000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -201,6 +219,7 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
@@ -238,6 +257,12 @@ CONFIG_SYS_BFIN_SPINLOCK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -246,14 +271,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -268,7 +292,6 @@ CONFIG_BFIN_DCACHE=y
# CONFIG_BFIN_ICACHE_LOCK is not set
# CONFIG_BFIN_WB is not set
CONFIG_BFIN_WT=y
-CONFIG_L1_MAX_PIECE=16
# CONFIG_MPU is not set
#
@@ -297,7 +320,6 @@ CONFIG_BANK_3=0xAAC2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -308,29 +330,30 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_UP_POSSIBLE=y
CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_PM_BFIN_SLEEP_DEEPER=y
# CONFIG_PM_BFIN_SLEEP is not set
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
-# CPU Frequency scaling
+# Possible Suspend Mem / Hibernate Wake-Up Sources
#
-# CONFIG_CPU_FREQ is not set
#
-# Networking
+# CPU Frequency scaling
#
+# CONFIG_CPU_FREQ is not set
CONFIG_NET=y
#
@@ -343,6 +366,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -372,8 +396,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -382,6 +404,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -398,6 +421,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
CONFIG_IRDA=m
#
@@ -430,24 +454,14 @@ CONFIG_IRTTY_SIR=m
# CONFIG_DONGLE is not set
#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
# FIR device drivers
#
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -465,6 +479,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -473,6 +489,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -516,6 +533,7 @@ CONFIG_MTD_ROM=m
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
@@ -550,11 +568,14 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -567,7 +588,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -580,11 +600,14 @@ CONFIG_MII=y
CONFIG_SMC91X=y
# CONFIG_SMSC911X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
# CONFIG_AX88180 is not set
CONFIG_NETDEV_10000=y
@@ -594,10 +617,10 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -645,8 +668,11 @@ CONFIG_INPUT_EVDEV=m
# CONFIG_BF5xx_PPI is not set
CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -675,38 +701,39 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_CAN4LINUX is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -715,6 +742,8 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -725,21 +754,28 @@ CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -754,18 +790,22 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -784,47 +824,51 @@ CONFIG_RTC_INTF_DEV=y
#
# SPI RTC drivers
#
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -864,11 +908,11 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
CONFIG_YAFFS_FS=m
CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
@@ -885,8 +929,11 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -894,13 +941,12 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -956,9 +1002,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -966,14 +1009,53 @@ CONFIG_INSTRUMENTATION=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -991,9 +1073,94 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1001,6 +1168,7 @@ CONFIG_SECURITY=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index c23267ed880b..9d733436e300 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
+# Linux kernel version: 2.6.28-rc2
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -31,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -51,26 +48,35 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -81,6 +87,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -94,9 +101,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+CONFIG_FREEZER=y
#
# Blackfin Processor Options
@@ -105,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -117,24 +130,30 @@ CONFIG_BF533=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=3
+CONFIG_BF_REV_MAX=6
# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_1 is not set
# CONFIG_BF_REV_0_2 is not set
CONFIG_BF_REV_0_3=y
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF53x=y
CONFIG_MEM_MT48LC64M4A2FB_7E=y
# CONFIG_BFIN533_EZKIT is not set
CONFIG_BFIN533_STAMP=y
+# CONFIG_BLACKSTAMP is not set
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_H8606_HVSISTEMAS is not set
# CONFIG_BFIN532_IP0X is not set
@@ -187,7 +206,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=11059200
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=750000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -201,6 +219,7 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
@@ -238,6 +257,12 @@ CONFIG_SYS_BFIN_SPINLOCK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -246,14 +271,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -268,7 +292,6 @@ CONFIG_BFIN_DCACHE=y
# CONFIG_BFIN_ICACHE_LOCK is not set
# CONFIG_BFIN_WB is not set
CONFIG_BFIN_WT=y
-CONFIG_L1_MAX_PIECE=16
# CONFIG_MPU is not set
#
@@ -297,7 +320,6 @@ CONFIG_BANK_3=0xAAC2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -308,29 +330,30 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_UP_POSSIBLE=y
CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_PM_BFIN_SLEEP_DEEPER=y
# CONFIG_PM_BFIN_SLEEP is not set
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
-# CPU Frequency scaling
+# Possible Suspend Mem / Hibernate Wake-Up Sources
#
-# CONFIG_CPU_FREQ is not set
#
-# Networking
+# CPU Frequency scaling
#
+# CONFIG_CPU_FREQ is not set
CONFIG_NET=y
#
@@ -343,6 +366,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -372,8 +396,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -382,6 +404,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -398,6 +421,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
CONFIG_IRDA=m
#
@@ -432,24 +456,14 @@ CONFIG_SIR_BFIN_DMA=y
# CONFIG_DONGLE is not set
#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
# FIR device drivers
#
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -467,6 +481,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -475,6 +491,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -520,6 +537,7 @@ CONFIG_MTD_ROM=m
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
CONFIG_MTD_BFIN_ASYNC=m
+# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
@@ -554,11 +572,14 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -571,7 +592,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -584,11 +604,14 @@ CONFIG_MII=y
CONFIG_SMC91X=y
# CONFIG_SMSC911X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
# CONFIG_AX88180 is not set
CONFIG_NETDEV_10000=y
@@ -598,10 +621,10 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -633,7 +656,7 @@ CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_UINPUT is not set
-CONFIG_TWI_KEYPAD=m
+CONFIG_CONFIG_INPUT_PCF8574=m
#
# Hardware I/O ports
@@ -652,8 +675,11 @@ CONFIG_TWI_KEYPAD=m
CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
CONFIG_TWI_LCD=m
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -682,41 +708,46 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_CAN4LINUX is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-CONFIG_I2C_ALGOBIT=m
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# I2C system bus drivers (mostly embedded / system-on-chip)
#
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
@@ -725,30 +756,32 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -756,6 +789,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -776,6 +810,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -784,6 +819,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
@@ -791,9 +827,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -804,21 +843,29 @@ CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -829,6 +876,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=m
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=m
CONFIG_FB_CFB_COPYAREA=m
CONFIG_FB_CFB_IMAGEBLIT=m
@@ -836,8 +884,8 @@ CONFIG_FB_CFB_IMAGEBLIT=m
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -848,6 +896,7 @@ CONFIG_FB_DEFERRED_IO=y
# Frame buffer hardware drivers
#
# CONFIG_FB_BFIN_T350MCQB is not set
+# CONFIG_FB_BFIN_LQ035Q1 is not set
CONFIG_FB_BFIN_7393=m
CONFIG_NTSC=y
# CONFIG_PAL is not set
@@ -859,6 +908,7 @@ CONFIG_ADV7393_1XMEM=y
# CONFIG_ADV7393_2XMEM is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -866,15 +916,8 @@ CONFIG_ADV7393_1XMEM=y
#
# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_LOGO is not set
-
-#
-# Sound
-#
CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
@@ -888,18 +931,12 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-
-#
-# SPI devices
-#
+CONFIG_SND_SPI=y
#
# ALSA Blackfin devices
@@ -911,46 +948,46 @@ CONFIG_SND_BLACKFIN_AD1836_MULSUB=y
# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
CONFIG_SND_BLACKFIN_SPORT=0
CONFIG_SND_BLACKFIN_SPI_PFBIT=4
-CONFIG_SND_BFIN_AD73311=m
CONFIG_SND_BFIN_SPORT=0
-CONFIG_SND_BFIN_AD73311_SE=4
CONFIG_SND_BFIN_AD73322=m
CONFIG_SND_BFIN_AD73322_SPORT0_SE=10
CONFIG_SND_BFIN_AD73322_SPORT1_SE=14
CONFIG_SND_BFIN_AD73322_RESET=12
-
-#
-# System on Chip audio support
-#
-CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC=m
-CONFIG_SND_BF5XX_SOC=m
-CONFIG_SND_MMAP_SUPPORT=y
-CONFIG_SND_BF5XX_SOC_AC97=m
-# CONFIG_SND_BF5XX_SOC_WM8750 is not set
-# CONFIG_SND_BF5XX_SOC_WM8731 is not set
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_BF5XX_I2S=m
# CONFIG_SND_BF5XX_SOC_SSM2602 is not set
-CONFIG_SND_BF5XX_SOC_BF5xx=m
+CONFIG_SND_BF5XX_SOC_AD73311=m
+CONFIG_SND_BFIN_AD73311_SE=4
+CONFIG_SND_BF5XX_AC97=m
+CONFIG_SND_BF5XX_MMAP_SUPPORT=y
+# CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set
+CONFIG_SND_BF5XX_SOC_SPORT=m
+CONFIG_SND_BF5XX_SOC_I2S=m
+CONFIG_SND_BF5XX_SOC_AC97=m
+CONFIG_SND_BF5XX_SOC_AD1980=m
CONFIG_SND_BF5XX_SPORT_NUM=0
# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
-
-#
-# SoC Audio support for SuperH
-#
+# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_AD1980=m
-
-#
-# Open Sound System
-#
+CONFIG_SND_SOC_AD73311=m
# CONFIG_SOUND_PRIME is not set
CONFIG_AC97_BUS=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -979,51 +1016,57 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
#
# SPI RTC drivers
#
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1063,11 +1106,11 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
CONFIG_YAFFS_FS=m
CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
@@ -1084,8 +1127,11 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -1093,13 +1139,12 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1155,9 +1200,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -1165,14 +1207,53 @@ CONFIG_INSTRUMENTATION=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1190,9 +1271,94 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1200,6 +1366,7 @@ CONFIG_SECURITY=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index 63a0f854745c..4fb4108d3103 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -1,6 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
+# Linux kernel version: 2.6.28-rc2
+# Tue Dec 30 17:24:37 2008
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -8,7 +9,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -31,18 +31,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -51,26 +49,35 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -81,6 +88,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -94,9 +102,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+CONFIG_FREEZER=y
#
# Blackfin Processor Options
@@ -105,6 +115,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -117,18 +131,23 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
CONFIG_BF537=y
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=2
+CONFIG_BF_REV_MAX=3
# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_1 is not set
CONFIG_BF_REV_0_2=y
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF53x=y
@@ -141,27 +160,28 @@ CONFIG_IRQ_SPORT0_TX=9
CONFIG_IRQ_SPORT1_RX=9
CONFIG_IRQ_SPORT1_TX=9
CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
CONFIG_IRQ_UART0_RX=10
CONFIG_IRQ_UART0_TX=10
CONFIG_IRQ_UART1_RX=10
CONFIG_IRQ_UART1_TX=10
CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=8
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
CONFIG_IRQ_MEM_DMA1=13
CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_SPI=10
CONFIG_BFIN537_STAMP=y
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_TCM is not set
# CONFIG_PNAV10 is not set
# CONFIG_CAMSIG_MINOTAUR is not set
# CONFIG_GENERIC_BF537_BOARD is not set
@@ -194,7 +214,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -208,6 +227,7 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
@@ -245,6 +265,12 @@ CONFIG_SYS_BFIN_SPINLOCK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -253,14 +279,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
-# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
+CONFIG_BFIN_GPTIMERS=m
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -275,7 +300,6 @@ CONFIG_BFIN_DCACHE=y
# CONFIG_BFIN_ICACHE_LOCK is not set
# CONFIG_BFIN_WB is not set
CONFIG_BFIN_WT=y
-CONFIG_L1_MAX_PIECE=16
# CONFIG_MPU is not set
#
@@ -304,7 +328,6 @@ CONFIG_BANK_3=0x99B2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -315,29 +338,31 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_UP_POSSIBLE=y
CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_PM_BFIN_SLEEP_DEEPER=y
# CONFIG_PM_BFIN_SLEEP is not set
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
-# CPU Frequency scaling
+# Possible Suspend Mem / Hibernate Wake-Up Sources
#
-# CONFIG_CPU_FREQ is not set
+# CONFIG_PM_BFIN_WAKE_PH6 is not set
#
-# Networking
+# CPU Frequency scaling
#
+# CONFIG_CPU_FREQ is not set
CONFIG_NET=y
#
@@ -350,6 +375,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -379,8 +405,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -389,6 +413,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -405,6 +430,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
CONFIG_IRDA=m
#
@@ -440,24 +466,14 @@ CONFIG_SIR_BFIN_DMA=y
# CONFIG_DONGLE is not set
#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
# FIR device drivers
#
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -475,6 +491,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -483,6 +501,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -553,15 +572,11 @@ CONFIG_MTD_NAND=m
# CONFIG_MTD_NAND_VERIFY_WRITE is not set
# CONFIG_MTD_NAND_ECC_SMC is not set
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
-CONFIG_MTD_NAND_BFIN=m
-CONFIG_BFIN_NAND_BASE=0x20212000
-CONFIG_BFIN_NAND_CLE=2
-CONFIG_BFIN_NAND_ALE=1
-CONFIG_BFIN_NAND_READY=3
+# CONFIG_MTD_NAND_BFIN is not set
CONFIG_MTD_NAND_IDS=m
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_NANDSIM is not set
-# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_PLATFORM=m
# CONFIG_MTD_ONENAND is not set
#
@@ -576,11 +591,14 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -593,7 +611,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -614,6 +631,7 @@ CONFIG_PHYLIB=y
CONFIG_SMSC_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -626,11 +644,14 @@ CONFIG_BFIN_RX_DESC_NUM=20
# CONFIG_SMC91X is not set
# CONFIG_SMSC911X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
# CONFIG_AX88180 is not set
CONFIG_NETDEV_10000=y
@@ -640,10 +661,10 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -675,12 +696,15 @@ CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_UINPUT is not set
-CONFIG_TWI_KEYPAD=m
+CONFIG_CONFIG_INPUT_PCF8574=m
#
# Hardware I/O ports
#
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
#
@@ -691,11 +715,14 @@ CONFIG_TWI_KEYPAD=m
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BFIN_SIMPLE_TIMER is not set
# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_SPORT=y
+CONFIG_BFIN_SPORT=m
# CONFIG_BFIN_TIMER_LATENCY is not set
CONFIG_TWI_LCD=m
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -727,48 +754,51 @@ CONFIG_CAN4LINUX=y
#
# linux embedded drivers
#
-# CONFIG_CAN_MCF5282 is not set
-# CONFIG_CAN_UNCTWINCAN is not set
CONFIG_CAN_BLACKFIN=m
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_BLACKFIN_TWI=m
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
CONFIG_SENSORS_AD5252=m
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
@@ -777,30 +807,32 @@ CONFIG_SENSORS_AD5252=m
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -808,6 +840,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -828,6 +861,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -836,6 +870,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
@@ -843,9 +878,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -856,21 +894,29 @@ CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -881,6 +927,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=m
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=m
CONFIG_FB_CFB_COPYAREA=m
CONFIG_FB_CFB_IMAGEBLIT=m
@@ -888,8 +935,8 @@ CONFIG_FB_CFB_IMAGEBLIT=m
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -899,8 +946,12 @@ CONFIG_FB_DEFERRED_IO=y
#
# Frame buffer hardware drivers
#
-# CONFIG_FB_HITACHI_TX09 is not set
# CONFIG_FB_BFIN_T350MCQB is not set
+# CONFIG_FB_BFIN_LQ035Q1 is not set
+CONFIG_FB_BF537_LQ035=m
+CONFIG_LQ035_SLAVE_ADDR=0x58
+# CONFIG_FB_BFIN_LANDSCAPE is not set
+# CONFIG_FB_BFIN_BGR is not set
CONFIG_FB_BFIN_7393=m
CONFIG_NTSC=y
# CONFIG_PAL is not set
@@ -910,15 +961,17 @@ CONFIG_NTSC=y
# CONFIG_PAL_YCBCR is not set
CONFIG_ADV7393_1XMEM=y
# CONFIG_ADV7393_2XMEM is not set
-CONFIG_FB_BF537_LQ035=m
-CONFIG_LQ035_SLAVE_ADDR=0x58
-# CONFIG_FB_BFIN_LANDSCAPE is not set
-# CONFIG_FB_BFIN_BGR is not set
+# CONFIG_FB_HITACHI_TX09 is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=m
# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=m
CONFIG_BACKLIGHT_CORGI=m
@@ -927,15 +980,8 @@ CONFIG_BACKLIGHT_CORGI=m
#
# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_LOGO is not set
-
-#
-# Sound
-#
CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=m
CONFIG_SND_TIMER=m
CONFIG_SND_PCM=m
@@ -949,18 +995,12 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-
-#
-# SPI devices
-#
+CONFIG_SND_SPI=y
#
# ALSA Blackfin devices
@@ -972,51 +1012,46 @@ CONFIG_SND_BLACKFIN_AD1836_MULSUB=y
# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
CONFIG_SND_BLACKFIN_SPORT=0
CONFIG_SND_BLACKFIN_SPI_PFBIT=4
-CONFIG_SND_BFIN_AD73311=m
CONFIG_SND_BFIN_SPORT=0
-CONFIG_SND_BFIN_AD73311_SE=4
CONFIG_SND_BFIN_AD73322=m
CONFIG_SND_BFIN_AD73322_SPORT0_SE=10
CONFIG_SND_BFIN_AD73322_SPORT1_SE=14
CONFIG_SND_BFIN_AD73322_RESET=12
-
-#
-# System on Chip audio support
-#
-CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC=m
-CONFIG_SND_BF5XX_SOC=m
-CONFIG_SND_MMAP_SUPPORT=y
-CONFIG_SND_BF5XX_SOC_AC97=m
-# CONFIG_SND_BF5XX_SOC_WM8750 is not set
-# CONFIG_SND_BF5XX_SOC_WM8731 is not set
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_BF5XX_I2S=m
# CONFIG_SND_BF5XX_SOC_SSM2602 is not set
-CONFIG_SND_BF5XX_SOC_BF5xx=m
+CONFIG_SND_BF5XX_SOC_AD73311=m
+CONFIG_SND_BFIN_AD73311_SE=4
+CONFIG_SND_BF5XX_AC97=m
+CONFIG_SND_BF5XX_MMAP_SUPPORT=y
+# CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set
+CONFIG_SND_BF5XX_SOC_SPORT=m
+CONFIG_SND_BF5XX_SOC_I2S=m
+CONFIG_SND_BF5XX_SOC_AC97=m
+CONFIG_SND_BF5XX_SOC_AD1980=m
CONFIG_SND_BF5XX_SPORT_NUM=0
# CONFIG_SND_BF5XX_HAVE_COLD_RESET is not set
-
-#
-# SoC Audio support for SuperH
-#
+# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_AD1980=m
-
-#
-# Open Sound System
-#
+CONFIG_SND_SOC_AD73311=m
# CONFIG_SOUND_PRIME is not set
CONFIG_AC97_BUS=m
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
-# CONFIG_NO_DUMMY_DELAY is not set
-# CONFIG_DUMMY_DELAY_BANK0 is not set
-# CONFIG_DUMMY_DELAY_BANK1 is not set
-# CONFIG_DUMMY_DELAY_BANK2 is not set
-# CONFIG_DUMMY_DELAY_BANK3 is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1045,51 +1080,57 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
#
# SPI RTC drivers
#
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1129,11 +1170,11 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
CONFIG_YAFFS_FS=m
CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
@@ -1150,8 +1191,11 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -1159,13 +1203,12 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1221,9 +1264,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -1231,14 +1271,53 @@ CONFIG_INSTRUMENTATION=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1256,9 +1335,94 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1266,6 +1430,7 @@ CONFIG_SECURITY=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig
new file mode 100644
index 000000000000..cb32f5624a1b
--- /dev/null
+++ b/arch/blackfin/configs/BF538-EZKIT_defconfig
@@ -0,0 +1,1368 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-rc2
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
+# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
+# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
+# CONFIG_BF527 is not set
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF536 is not set
+# CONFIG_BF537 is not set
+CONFIG_BF538=y
+# CONFIG_BF539 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF547 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=4
+CONFIG_BF_REV_MAX=5
+# CONFIG_BF_REV_0_0 is not set
+# CONFIG_BF_REV_0_1 is not set
+# CONFIG_BF_REV_0_2 is not set
+# CONFIG_BF_REV_0_3 is not set
+CONFIG_BF_REV_0_4=y
+# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_MEM_MT48LC32M8A2_75=y
+CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_DMA0_ERROR=7
+CONFIG_IRQ_PPI_ERROR=7
+CONFIG_IRQ_SPORT0_ERROR=7
+CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_UART0_ERROR=7
+CONFIG_IRQ_UART1_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_SPI0=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_PORTF_INTA=12
+CONFIG_IRQ_PORTF_INTB=12
+CONFIG_IRQ_SPI0_ERROR=7
+CONFIG_IRQ_SPI1_ERROR=7
+CONFIG_IRQ_DMA1_ERROR=7
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_BFIN538_EZKIT=y
+
+#
+# BF538 Specific Configuration
+#
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_MEM0_DMA0=13
+CONFIG_IRQ_MEM0_DMA1=13
+CONFIG_IRQ_SPORT2_ERROR=7
+CONFIG_IRQ_SPORT3_ERROR=7
+CONFIG_IRQ_SPI2_ERROR=7
+CONFIG_IRQ_UART2_ERROR=7
+CONFIG_IRQ_CAN_ERROR=7
+CONFIG_IRQ_SPORT2_RX=9
+CONFIG_IRQ_SPORT2_TX=9
+CONFIG_IRQ_SPORT3_RX=9
+CONFIG_IRQ_SPORT3_TX=9
+CONFIG_IRQ_SPI1=10
+CONFIG_IRQ_SPI2=10
+CONFIG_IRQ_UART2_RX=10
+CONFIG_IRQ_UART2_TX=10
+CONFIG_IRQ_TWI0=11
+CONFIG_IRQ_TWI1=11
+CONFIG_IRQ_MEM1_DMA0=13
+CONFIG_IRQ_MEM1_DMA1=13
+
+#
+# Board customizations
+#
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Clock/PLL Setup
+#
+CONFIG_CLKIN_HZ=25000000
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+CONFIG_MAX_VCO_HZ=533333333
+CONFIG_MIN_VCO_HZ=50000000
+CONFIG_MAX_SCLK_HZ=133333333
+CONFIG_MIN_SCLK_HZ=27000000
+
+#
+# Kernel Timer/Scheduler
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# Misc
+#
+CONFIG_BFIN_SCRATCH_REG_RETN=y
+# CONFIG_BFIN_SCRATCH_REG_RETE is not set
+# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_EXCPT_IRQ_SYSC_L1=y
+CONFIG_DO_IRQ_L1=y
+CONFIG_CORE_TIMER_IRQ_L1=y
+CONFIG_IDLE_L1=y
+CONFIG_SCHEDULE_L1=y
+CONFIG_ARITHMETIC_OPS_L1=y
+CONFIG_ACCESS_OK_L1=y
+CONFIG_MEMSET_L1=y
+CONFIG_MEMCPY_L1=y
+CONFIG_SYS_BFIN_SPINLOCK_L1=y
+# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
+# CONFIG_SYSCALL_TAB_L1 is not set
+# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_BFIN_GPTIMERS=y
+# CONFIG_DMA_UNCACHED_4M is not set
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BFIN_ICACHE=y
+CONFIG_BFIN_DCACHE=y
+# CONFIG_BFIN_DCACHE_BANKA is not set
+# CONFIG_BFIN_ICACHE_LOCK is not set
+# CONFIG_BFIN_WB is not set
+CONFIG_BFIN_WT=y
+# CONFIG_MPU is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMGCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B2
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+CONFIG_BFIN_SIR=m
+CONFIG_SIR_BFIN_DMA=y
+# CONFIG_SIR_BFIN_PIO is not set
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x20000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_UCLINUX is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_BFIN=m
+CONFIG_BFIN_NAND_BASE=0x20212000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=3
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+CONFIG_TOUCHSCREEN_AD7879_SPI=y
+CONFIG_TOUCHSCREEN_AD7879=m
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_CONFIG_INPUT_PCF8574 is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BFIN_SIMPLE_TIMER is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_TWI_LCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+CONFIG_SIMPLE_GPIO=m
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+CONFIG_SERIAL_BFIN_UART2=y
+# CONFIG_BFIN_UART2_CTSRTS is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+# CONFIG_CAN4LINUX is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_SENSORS_AD5252 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 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=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_BFIN_T350MCQB is not set
+CONFIG_FB_BFIN_LQ035Q1=m
+# CONFIG_FB_BFIN_7393 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_BFIN=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# 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_OCFS2_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
+CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+CONFIG_DEBUG_BFIN_HWTRACE_ON=y
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set
+# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set
+CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
+# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_CPLB_INFO=y
+CONFIG_ACCESS_CHECK=y
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index bf63660815b9..0f8697618aa5 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
+# Linux kernel version: 2.6.28-rc2
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -31,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -51,26 +48,35 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -81,6 +87,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -94,9 +101,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
#
# Blackfin Processor Options
@@ -105,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -117,18 +130,23 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
CONFIG_BF548=y
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=0
+CONFIG_BF_REV_MAX=2
CONFIG_BF_REV_0_0=y
# CONFIG_BF_REV_0_1 is not set
# CONFIG_BF_REV_0_2 is not set
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF54x=y
@@ -138,15 +156,12 @@ CONFIG_IRQ_SPORT0_RX=9
CONFIG_IRQ_SPORT0_TX=9
CONFIG_IRQ_SPORT1_RX=9
CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_SPI0=10
CONFIG_IRQ_UART0_RX=10
CONFIG_IRQ_UART0_TX=10
CONFIG_IRQ_UART1_RX=10
CONFIG_IRQ_UART1_TX=10
CONFIG_IRQ_CNT=8
-CONFIG_IRQ_USB_INT0=11
-CONFIG_IRQ_USB_INT1=11
-CONFIG_IRQ_USB_INT2=11
-CONFIG_IRQ_USB_DMA=11
CONFIG_IRQ_TIMER0=11
CONFIG_IRQ_TIMER1=11
CONFIG_IRQ_TIMER2=11
@@ -155,9 +170,21 @@ CONFIG_IRQ_TIMER4=11
CONFIG_IRQ_TIMER5=11
CONFIG_IRQ_TIMER6=11
CONFIG_IRQ_TIMER7=11
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
CONFIG_IRQ_TIMER8=11
CONFIG_IRQ_TIMER9=11
CONFIG_IRQ_TIMER10=11
+CONFIG_IRQ_SPORT2_RX=9
+CONFIG_IRQ_SPORT2_TX=9
+CONFIG_IRQ_SPORT3_RX=9
+CONFIG_IRQ_SPORT3_TX=9
+CONFIG_IRQ_SPI1=10
+CONFIG_IRQ_SPI2=10
+CONFIG_IRQ_TWI0=11
+CONFIG_IRQ_TWI1=11
CONFIG_BFIN548_EZKIT=y
# CONFIG_BFIN548_BLUETECHNIX_CM is not set
@@ -180,7 +207,6 @@ CONFIG_IRQ_SPORT1_ERR=7
CONFIG_IRQ_SPI0_ERR=7
CONFIG_IRQ_UART0_ERR=7
CONFIG_IRQ_EPPI0=8
-CONFIG_IRQ_SPI0=10
CONFIG_IRQ_PINT0=12
CONFIG_IRQ_PINT1=12
CONFIG_IRQ_MDMAS0=13
@@ -195,18 +221,10 @@ CONFIG_IRQ_SPI2_ERR=7
CONFIG_IRQ_UART1_ERR=7
CONFIG_IRQ_UART2_ERR=7
CONFIG_IRQ_CAN0_ERR=7
-CONFIG_IRQ_SPORT2_RX=9
-CONFIG_IRQ_SPORT2_TX=9
-CONFIG_IRQ_SPORT3_RX=9
-CONFIG_IRQ_SPORT3_TX=9
CONFIG_IRQ_EPPI1=9
CONFIG_IRQ_EPPI2=9
-CONFIG_IRQ_SPI1=10
-CONFIG_IRQ_SPI2=10
CONFIG_IRQ_ATAPI_RX=10
CONFIG_IRQ_ATAPI_TX=10
-CONFIG_IRQ_TWI0=11
-CONFIG_IRQ_TWI1=11
CONFIG_IRQ_CAN0_RX=11
CONFIG_IRQ_CAN0_TX=11
CONFIG_IRQ_MDMAS2=13
@@ -260,7 +278,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -274,10 +291,10 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -311,6 +328,12 @@ CONFIG_ACCESS_OK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -319,14 +342,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
CONFIG_DMA_UNCACHED_2M=y
# CONFIG_DMA_UNCACHED_1M is not set
@@ -341,7 +363,7 @@ CONFIG_BFIN_DCACHE=y
# CONFIG_BFIN_ICACHE_LOCK is not set
# CONFIG_BFIN_WB is not set
CONFIG_BFIN_WT=y
-CONFIG_L1_MAX_PIECE=16
+# CONFIG_BFIN_L2_CACHEABLE is not set
# CONFIG_MPU is not set
#
@@ -373,7 +395,6 @@ CONFIG_EBIU_FCTLVAL=0x6
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -384,23 +405,20 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -413,6 +431,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -442,8 +461,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -452,6 +469,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -468,6 +486,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
CONFIG_IRDA=m
#
@@ -493,9 +512,9 @@ CONFIG_IRCOMM=m
#
CONFIG_IRTTY_SIR=m
CONFIG_BFIN_SIR=m
+CONFIG_BFIN_SIR3=y
# CONFIG_BFIN_SIR0 is not set
# CONFIG_BFIN_SIR2 is not set
-CONFIG_BFIN_SIR3=y
CONFIG_SIR_BFIN_DMA=y
# CONFIG_SIR_BFIN_PIO is not set
@@ -508,15 +527,6 @@ CONFIG_SIR_BFIN_DMA=y
# CONFIG_KS959_DONGLE is not set
#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
# FIR device drivers
#
# CONFIG_USB_IRDA is not set
@@ -524,11 +534,10 @@ CONFIG_SIR_BFIN_DMA=y
# CONFIG_MCS_FIR is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -546,6 +555,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -554,6 +565,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -601,6 +613,7 @@ CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0x20000000
CONFIG_MTD_PHYSMAP_LEN=0
CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
@@ -608,7 +621,8 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# Self-contained MTD device drivers
#
# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
+CONFIG_MTD_M25P80=y
+CONFIG_M25PXX_USE_FAST_READ=y
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
@@ -648,11 +662,14 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -696,13 +713,16 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_MV is not set
# CONFIG_PATA_PLATFORM is not set
CONFIG_PATA_BF54X=y
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -715,11 +735,14 @@ CONFIG_MII=y
# CONFIG_SMC91X is not set
CONFIG_SMSC911X=y
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
# CONFIG_AX88180 is not set
CONFIG_NETDEV_10000=y
@@ -729,6 +752,7 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
@@ -741,7 +765,6 @@ CONFIG_NETDEV_10000=y
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -752,7 +775,7 @@ CONFIG_NETDEV_10000=y
# Input device support
#
CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
+CONFIG_INPUT_FF_MEMLESS=m
# CONFIG_INPUT_POLLDEV is not set
#
@@ -776,30 +799,37 @@ CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_GPIO is not set
CONFIG_KEYBOARD_BFIN=y
# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_ADP5588 is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_ADS7846 is not set
CONFIG_TOUCHSCREEN_AD7877=m
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_ELO is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
# CONFIG_TOUCHSCREEN_MK712 is not set
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
-# CONFIG_TOUCHSCREEN_UCB1400 is not set
+# CONFIG_TOUCHSCREEN_WM97XX is not set
# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_ATI_REMOTE is not set
# CONFIG_INPUT_ATI_REMOTE2 is not set
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
# CONFIG_INPUT_UINPUT is not set
-# CONFIG_TWI_KEYPAD is not set
+# CONFIG_CONFIG_INPUT_PCF8574 is not set
#
# Hardware I/O ports
@@ -815,16 +845,18 @@ CONFIG_INPUT_MISC=y
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BFIN_SIMPLE_TIMER is not set
# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_OTP=y
-# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_TWI_LCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -849,6 +881,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_BFIN_SPORT is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
#
# CAN, the car bus and industrial fieldbus
@@ -856,44 +890,49 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_CAN4LINUX is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_BLACKFIN_TWI=y
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
@@ -902,30 +941,32 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -933,6 +974,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -953,6 +995,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -961,6 +1004,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
@@ -968,9 +1012,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -986,23 +1033,30 @@ CONFIG_BFIN_WDT=y
# CONFIG_USBPCWATCHDOG is not set
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
-# CONFIG_USB_DABUSB is not set
#
# Graphics support
@@ -1012,6 +1066,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
@@ -1019,8 +1074,8 @@ CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -1032,9 +1087,11 @@ CONFIG_FB_DEFERRED_IO=y
#
CONFIG_FB_BF54X_LQ043=y
# CONFIG_FB_BFIN_T350MCQB is not set
+# CONFIG_FB_BFIN_LQ035Q1 is not set
# CONFIG_FB_BFIN_7393 is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1066,15 +1123,8 @@ CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_CLUT224 is not set
# CONFIG_LOGO_BLACKFIN_VGA16 is not set
CONFIG_LOGO_BLACKFIN_CLUT224=y
-
-#
-# Sound
-#
CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
@@ -1088,56 +1138,35 @@ CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
-
-#
-# SPI devices
-#
+CONFIG_SND_SPI=y
#
# ALSA Blackfin devices
#
# CONFIG_SND_BLACKFIN_AD1836 is not set
-# CONFIG_SND_BFIN_AD73311 is not set
# CONFIG_SND_BFIN_AD73322 is not set
-
-#
-# USB devices
-#
+CONFIG_SND_USB=y
# CONFIG_SND_USB_AUDIO is not set
# CONFIG_SND_USB_CAIAQ is not set
-
-#
-# System on Chip audio support
-#
-CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC=y
-CONFIG_SND_BF5XX_SOC=y
-CONFIG_SND_MMAP_SUPPORT=y
+CONFIG_SND_SOC_AC97_BUS=y
+# CONFIG_SND_BF5XX_I2S is not set
+CONFIG_SND_BF5XX_AC97=y
+CONFIG_SND_BF5XX_MMAP_SUPPORT=y
+# CONFIG_SND_BF5XX_MULTICHAN_SUPPORT is not set
+CONFIG_SND_BF5XX_SOC_SPORT=y
CONFIG_SND_BF5XX_SOC_AC97=y
-CONFIG_SND_BF5XX_SOC_BF548_EZKIT=y
-# CONFIG_SND_BF5XX_SOC_WM8750 is not set
-# CONFIG_SND_BF5XX_SOC_WM8731 is not set
-# CONFIG_SND_BF5XX_SOC_SSM2602 is not set
+CONFIG_SND_BF5XX_SOC_AD1980=y
CONFIG_SND_BF5XX_SPORT_NUM=0
CONFIG_SND_BF5XX_HAVE_COLD_RESET=y
CONFIG_SND_BF5XX_RESET_GPIO_NUM=19
-
-#
-# SoC Audio support for SuperH
-#
+# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_AD1980=y
-
-#
-# Open Sound System
-#
# CONFIG_SOUND_PRIME is not set
CONFIG_AC97_BUS=y
CONFIG_HID_SUPPORT=y
@@ -1149,15 +1178,43 @@ CONFIG_HID=y
# USB Input Devices
#
CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_BRIGHT=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_DELL=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
@@ -1168,15 +1225,20 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_SOC=y
@@ -1190,13 +1252,15 @@ CONFIG_USB_MUSB_HDRC_HCD=y
# CONFIG_MUSB_PIO_ONLY is not set
CONFIG_USB_INVENTRA_DMA=y
# CONFIG_USB_TI_CPPI_DMA is not set
-CONFIG_USB_MUSB_LOGLEVEL=0
+# CONFIG_USB_MUSB_DEBUG is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1218,6 +1282,7 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_ONETOUCH is not set
# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -1225,15 +1290,10 @@ CONFIG_USB_STORAGE=m
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-CONFIG_USB_MON=y
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
@@ -1242,7 +1302,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -1258,34 +1318,31 @@ CONFIG_USB_MON=y
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
CONFIG_MMC=m
# CONFIG_MMC_DEBUG is not set
# CONFIG_MMC_UNSAFE_RESUME is not set
#
-# MMC/SD Card Drivers
+# MMC/SD/SDIO Card Drivers
#
CONFIG_MMC_BLOCK=m
CONFIG_MMC_BLOCK_BOUNCE=y
# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
#
-# MMC/SD Host Controller Drivers
+# MMC/SD/SDIO Host Controller Drivers
#
+# CONFIG_MMC_SDHCI is not set
CONFIG_SDH_BFIN=m
# CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND is not set
# CONFIG_MMC_SPI is not set
-# CONFIG_SPI_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1314,32 +1371,40 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
#
# SPI RTC drivers
#
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -1352,22 +1417,20 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_POSIX_ACL is not set
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# 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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1414,11 +1477,11 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
CONFIG_YAFFS_FS=m
CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
@@ -1435,8 +1498,11 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -1444,18 +1510,16 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=m
CONFIG_NFSD_V3=y
# CONFIG_NFSD_V3_ACL is not set
# CONFIG_NFSD_V4 is not set
-CONFIG_NFSD_TCP=y
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1533,9 +1597,6 @@ CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -1543,14 +1604,53 @@ CONFIG_INSTRUMENTATION=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1568,10 +1668,95 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_SECURITY_ROOTPLUG is not set
-# CONFIG_CRYPTO is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1579,6 +1764,7 @@ CONFIG_SECURITY=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 3c70d6230a12..042c7adfccfa 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
+# Linux kernel version: 2.6.28-rc2
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -8,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -31,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -51,26 +48,35 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -81,6 +87,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -94,9 +101,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
#
# Blackfin Processor Options
@@ -105,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -117,24 +130,38 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
CONFIG_BF561=y
+# CONFIG_SMP is not set
+CONFIG_BF_REV_MIN=3
+CONFIG_BF_REV_MAX=5
# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_1 is not set
# CONFIG_BF_REV_0_2 is not set
CONFIG_BF_REV_0_3=y
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_MEM_MT48LC16M16A2TG_75=y
CONFIG_IRQ_PLL_WAKEUP=7
CONFIG_IRQ_SPORT0_ERROR=7
CONFIG_IRQ_SPORT1_ERROR=7
+CONFIG_IRQ_TIMER0=10
+CONFIG_IRQ_TIMER1=10
+CONFIG_IRQ_TIMER2=10
+CONFIG_IRQ_TIMER3=10
+CONFIG_IRQ_TIMER4=10
+CONFIG_IRQ_TIMER5=10
+CONFIG_IRQ_TIMER6=10
+CONFIG_IRQ_TIMER7=10
CONFIG_IRQ_SPI_ERROR=7
CONFIG_BFIN561_EZKIT=y
# CONFIG_BFIN561_TEPLA is not set
@@ -148,10 +175,6 @@ CONFIG_BFIN561_EZKIT=y
#
# Core B Support
#
-
-#
-# Core B Support
-#
CONFIG_BF561_COREB=y
CONFIG_BF561_COREB_RESET=y
@@ -193,14 +216,6 @@ CONFIG_IRQ_DMA2_8=9
CONFIG_IRQ_DMA2_9=9
CONFIG_IRQ_DMA2_10=9
CONFIG_IRQ_DMA2_11=9
-CONFIG_IRQ_TIMER0=10
-CONFIG_IRQ_TIMER1=10
-CONFIG_IRQ_TIMER2=10
-CONFIG_IRQ_TIMER3=10
-CONFIG_IRQ_TIMER4=10
-CONFIG_IRQ_TIMER5=10
-CONFIG_IRQ_TIMER6=10
-CONFIG_IRQ_TIMER7=10
CONFIG_IRQ_TIMER8=10
CONFIG_IRQ_TIMER9=10
CONFIG_IRQ_TIMER10=10
@@ -230,7 +245,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=30000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -244,6 +258,7 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
@@ -281,6 +296,12 @@ CONFIG_SYS_BFIN_SPINLOCK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -289,14 +310,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -311,7 +331,7 @@ CONFIG_BFIN_DCACHE=y
# CONFIG_BFIN_ICACHE_LOCK is not set
# CONFIG_BFIN_WB is not set
CONFIG_BFIN_WT=y
-CONFIG_L1_MAX_PIECE=16
+# CONFIG_BFIN_L2_CACHEABLE is not set
# CONFIG_MPU is not set
#
@@ -344,7 +364,6 @@ CONFIG_BANK_3=0xAAC2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -355,23 +374,20 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -384,6 +400,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -413,8 +430,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -423,6 +438,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -439,6 +455,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
CONFIG_IRDA=m
#
@@ -471,24 +488,14 @@ CONFIG_IRTTY_SIR=m
# CONFIG_DONGLE is not set
#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
# FIR device drivers
#
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -506,6 +513,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -514,6 +523,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -595,11 +605,14 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -612,7 +625,6 @@ CONFIG_MISC_DEVICES=y
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -625,11 +637,14 @@ CONFIG_MII=y
CONFIG_SMC91X=y
# CONFIG_SMSC911X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
# CONFIG_AX88180 is not set
CONFIG_NETDEV_10000=y
@@ -639,10 +654,10 @@ CONFIG_NETDEV_10000=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -690,8 +705,11 @@ CONFIG_INPUT_EVDEV=m
# CONFIG_BF5xx_PPI is not set
# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_BFIN_JTAG_COMM=m
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -720,38 +738,39 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_CAN4LINUX is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -760,6 +779,8 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -770,21 +791,28 @@ CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -799,43 +827,43 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -875,11 +903,11 @@ CONFIG_SYSFS=y
# CONFIG_EFS_FS is not set
CONFIG_YAFFS_FS=m
CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
@@ -896,8 +924,11 @@ CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -905,13 +936,12 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -967,9 +997,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
#
# Kernel hacking
@@ -977,14 +1004,53 @@ CONFIG_INSTRUMENTATION=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -994,7 +1060,6 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
CONFIG_EARLY_PRINTK=y
-# CONFIG_DUAL_CORE_TEST_MODULE is not set
CONFIG_CPLB_INFO=y
CONFIG_ACCESS_CHECK=y
@@ -1003,9 +1068,94 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1013,6 +1163,7 @@ CONFIG_SECURITY=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/BlackStamp_defconfig b/arch/blackfin/configs/BlackStamp_defconfig
index 2921f9952d5f..3a20e281d23c 100644
--- a/arch/blackfin/configs/BlackStamp_defconfig
+++ b/arch/blackfin/configs/BlackStamp_defconfig
@@ -53,7 +53,7 @@ CONFIG_KALLSYMS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
@@ -276,7 +276,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
CONFIG_BFIN_GPTIMERS=y
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -692,7 +691,7 @@ CONFIG_I2C_GPIO=m
#
# CONFIG_DS1682 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -714,7 +713,7 @@ CONFIG_SPI_BFIN=y
#
# SPI Protocol Masters
#
-CONFIG_SPI_AT25=y
+CONFIG_EEPROM_AT25=y
CONFIG_SPI_SPIDEV=m
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index b6a14635fb91..865ed85a5760 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -1,7 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
-# Fri Jul 18 18:00:41 2008
+# Linux kernel version: 2.6.28
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -9,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -32,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
+# CONFIG_GROUP_SCHED is not set
CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -52,26 +48,35 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -82,6 +87,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -95,9 +101,11 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
#
# Blackfin Processor Options
@@ -106,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -118,48 +130,32 @@ CONFIG_BF527=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
+# CONFIG_BF542M is not set
# CONFIG_BF544 is not set
+# CONFIG_BF544M is not set
# CONFIG_BF547 is not set
+# CONFIG_BF547M is not set
# CONFIG_BF548 is not set
+# CONFIG_BF548M is not set
# CONFIG_BF549 is not set
+# CONFIG_BF549M is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=0
+CONFIG_BF_REV_MAX=2
# CONFIG_BF_REV_0_0 is not set
CONFIG_BF_REV_0_1=y
# CONFIG_BF_REV_0_2 is not set
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF52x=y
CONFIG_MEM_MT48LC16M16A2TG_75=y
-# CONFIG_BFIN527_EZKIT is not set
-CONFIG_BFIN527_BLUETECHNIX_CM=y
-
-#
-# BF527 Specific Configuration
-#
-
-#
-# Alternative Multiplexing Scheme
-#
-# CONFIG_BF527_SPORT0_PORTF is not set
-CONFIG_BF527_SPORT0_PORTG=y
-CONFIG_BF527_SPORT0_TSCLK_PG10=y
-# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
-CONFIG_BF527_UART1_PORTF=y
-# CONFIG_BF527_UART1_PORTG is not set
-# CONFIG_BF527_NAND_D_PORTF is not set
-CONFIG_BF527_NAND_D_PORTH=y
-
-#
-# Interrupt Priority Assignment
-#
-
-#
-# Priority
-#
CONFIG_IRQ_PLL_WAKEUP=7
CONFIG_IRQ_DMA0_ERROR=7
CONFIG_IRQ_DMAR0_BLK=7
@@ -179,7 +175,6 @@ CONFIG_IRQ_SPORT0_TX=9
CONFIG_IRQ_SPORT1_RX=9
CONFIG_IRQ_SPORT1_TX=9
CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
CONFIG_IRQ_UART0_RX=10
CONFIG_IRQ_UART0_TX=10
CONFIG_IRQ_UART1_RX=10
@@ -190,14 +185,14 @@ CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_PORTH_INTA=11
CONFIG_IRQ_MAC_TX=11
CONFIG_IRQ_PORTH_INTB=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTA=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
@@ -205,6 +200,34 @@ CONFIG_IRQ_MEM_DMA1=13
CONFIG_IRQ_WATCH=13
CONFIG_IRQ_PORTF_INTA=13
CONFIG_IRQ_PORTF_INTB=13
+# CONFIG_BFIN527_EZKIT is not set
+CONFIG_BFIN527_BLUETECHNIX_CM=y
+# CONFIG_BFIN526_EZBRD is not set
+
+#
+# BF527 Specific Configuration
+#
+
+#
+# Alternative Multiplexing Scheme
+#
+# CONFIG_BF527_SPORT0_PORTF is not set
+CONFIG_BF527_SPORT0_PORTG=y
+CONFIG_BF527_SPORT0_TSCLK_PG10=y
+# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set
+CONFIG_BF527_UART1_PORTF=y
+# CONFIG_BF527_UART1_PORTG is not set
+# CONFIG_BF527_NAND_D_PORTF is not set
+CONFIG_BF527_NAND_D_PORTH=y
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_SPI=10
CONFIG_IRQ_SPI_ERROR=7
CONFIG_IRQ_NFC_ERROR=7
CONFIG_IRQ_HDMA_ERROR=7
@@ -226,7 +249,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=512
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -240,10 +262,10 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -277,6 +299,12 @@ CONFIG_ACCESS_OK_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -285,14 +313,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
CONFIG_BFIN_GPTIMERS=y
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -335,7 +362,6 @@ CONFIG_BANK_3=0xFFC0
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -346,25 +372,20 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
-# CONFIG_PM_BFIN_SLEEP_DEEPER is not set
-# CONFIG_PM_BFIN_SLEEP is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -377,6 +398,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -406,8 +428,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -416,6 +436,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -432,14 +453,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
@@ -457,6 +478,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
@@ -465,6 +488,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -508,6 +532,7 @@ CONFIG_MTD_ROM=m
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
@@ -543,10 +568,12 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -559,7 +586,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -580,6 +606,7 @@ CONFIG_PHYLIB=y
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -592,11 +619,14 @@ CONFIG_BFIN_MAC_RMII=y
# CONFIG_SMC91X is not set
# CONFIG_SMSC911X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
@@ -605,6 +635,7 @@ CONFIG_BFIN_MAC_RMII=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
@@ -617,7 +648,6 @@ CONFIG_BFIN_MAC_RMII=y
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -643,13 +673,15 @@ CONFIG_BFIN_MAC_RMII=y
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BFIN_SIMPLE_TIMER is not set
# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_OTP=y
-# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
+# CONFIG_BF5xx_EPPI is not set
# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_TWI_LCD is not set
+CONFIG_BFIN_DMA_INTERFACE=m
CONFIG_SIMPLE_GPIO=m
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -673,6 +705,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_BFIN_SPORT is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_BFIN_OTP=y
+# CONFIG_BFIN_OTP_WRITE_ENABLE is not set
#
# CAN, the car bus and industrial fieldbus
@@ -680,44 +714,49 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_CAN4LINUX is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_BLACKFIN_TWI=m
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
# CONFIG_I2C_TINY_USB is not set
#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
# CONFIG_SENSORS_AD5252 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
@@ -726,17 +765,15 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
@@ -745,18 +782,24 @@ CONFIG_SPI_BFIN=y
# CONFIG_SPI_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -777,6 +820,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -785,6 +829,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
@@ -792,9 +837,12 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -810,21 +858,31 @@ CONFIG_BFIN_WDT=y
# CONFIG_USBPCWATCHDOG is not set
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -839,10 +897,6 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
@@ -850,6 +904,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_EHCI is not set
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
@@ -860,40 +915,48 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_SOC=y
#
-# Blackfin high speed USB support
+# Blackfin high speed USB Support
#
CONFIG_USB_MUSB_HOST=y
# CONFIG_USB_MUSB_PERIPHERAL is not set
# CONFIG_USB_MUSB_OTG is not set
CONFIG_USB_MUSB_HDRC_HCD=y
CONFIG_MUSB_PIO_ONLY=y
-CONFIG_USB_MUSB_LOGLEVEL=0
+CONFIG_MUSB_DMA_POLL=y
+# CONFIG_USB_MUSB_DEBUG is not set
#
# USB Device Class drivers
#
# CONFIG_USB_ACM is not set
# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
# CONFIG_USB_LIBUSUAL is not set
@@ -901,15 +964,10 @@ CONFIG_USB_MUSB_LOGLEVEL=0
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
-CONFIG_USB_MON=y
#
# USB port drivers
#
-
-#
-# USB Serial Converter support
-#
# CONFIG_USB_SERIAL is not set
#
@@ -918,7 +976,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
@@ -934,17 +992,13 @@ CONFIG_USB_MON=y
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -973,51 +1027,59 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
#
# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1059,8 +1121,11 @@ CONFIG_SYSFS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
@@ -1068,13 +1133,12 @@ CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1130,7 +1194,6 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
# CONFIG_DLM is not set
-# CONFIG_INSTRUMENTATION is not set
#
# Kernel hacking
@@ -1138,14 +1201,61 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB_TESTCASE is not set
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_HWERR is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1154,7 +1264,7 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set
# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK is not set
# CONFIG_CPLB_INFO is not set
CONFIG_ACCESS_CHECK=y
@@ -1163,10 +1273,96 @@ CONFIG_ACCESS_CHECK=y
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_CAPABILITIES is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_SECURITY_ROOTPLUG is not set
-# CONFIG_CRYPTO is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1174,6 +1370,7 @@ CONFIG_SECURITY=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/configs/CM-BF533_defconfig b/arch/blackfin/configs/CM-BF533_defconfig
index c3ba9066b935..085211b9e4e4 100644
--- a/arch/blackfin/configs/CM-BF533_defconfig
+++ b/arch/blackfin/configs/CM-BF533_defconfig
@@ -42,7 +42,7 @@ CONFIG_SYSVIPC_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -55,7 +55,7 @@ CONFIG_KALLSYMS=y
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -254,7 +254,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -598,6 +597,7 @@ CONFIG_NETDEV_10000=y
CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
diff --git a/arch/blackfin/configs/CM-BF537E_defconfig b/arch/blackfin/configs/CM-BF537E_defconfig
index cdc6b7feb59e..750203e27a46 100644
--- a/arch/blackfin/configs/CM-BF537E_defconfig
+++ b/arch/blackfin/configs/CM-BF537E_defconfig
@@ -42,7 +42,7 @@ CONFIG_SYSVIPC_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -55,7 +55,7 @@ CONFIG_KALLSYMS=y
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -157,14 +157,14 @@ CONFIG_IRQ_UART1_RX=10
CONFIG_IRQ_UART1_TX=10
CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
CONFIG_IRQ_MEM_DMA1=13
@@ -262,7 +262,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -627,6 +626,7 @@ CONFIG_NETDEV_10000=y
CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
diff --git a/arch/blackfin/configs/CM-BF537U_defconfig b/arch/blackfin/configs/CM-BF537U_defconfig
index f074bdcd1ce5..dec8a7d5cc0e 100644
--- a/arch/blackfin/configs/CM-BF537U_defconfig
+++ b/arch/blackfin/configs/CM-BF537U_defconfig
@@ -42,7 +42,7 @@ CONFIG_SYSVIPC_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -55,7 +55,7 @@ CONFIG_KALLSYMS=y
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -157,14 +157,14 @@ CONFIG_IRQ_UART1_RX=10
CONFIG_IRQ_UART1_TX=10
CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
CONFIG_IRQ_MEM_DMA1=13
@@ -262,7 +262,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -607,6 +606,7 @@ CONFIG_NETDEV_10000=y
CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index 5c44fdb8e6e3..efe9741b1f14 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -41,7 +41,7 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_FAIR_USER_SCHED=y
# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
@@ -55,7 +55,7 @@ CONFIG_KALLSYMS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -325,7 +325,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -544,7 +543,7 @@ CONFIG_MTD_RAM=y
CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_START=0x20000000
-CONFIG_MTD_PHYSMAP_LEN=0x800000
+CONFIG_MTD_PHYSMAP_LEN=0
CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_UCLINUX is not set
# CONFIG_MTD_PLATRAM is not set
@@ -732,6 +731,7 @@ CONFIG_BFIN_OTP=y
# CONFIG_TWI_LCD is not set
# CONFIG_SIMPLE_GPIO is not set
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -782,7 +782,7 @@ CONFIG_I2C_CHARDEV=y
# I2C Hardware Bus support
#
CONFIG_I2C_BLACKFIN_TWI=y
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
@@ -798,7 +798,7 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8575 is not set
# CONFIG_SENSORS_PCA9543 is not set
@@ -826,7 +826,7 @@ CONFIG_SPI_BFIN=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
diff --git a/arch/blackfin/configs/CM-BF561_defconfig b/arch/blackfin/configs/CM-BF561_defconfig
index 086fe5dda495..346bc7af8f42 100644
--- a/arch/blackfin/configs/CM-BF561_defconfig
+++ b/arch/blackfin/configs/CM-BF561_defconfig
@@ -42,7 +42,7 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_FAIR_USER_SCHED=y
# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -55,7 +55,7 @@ CONFIG_KALLSYMS=y
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -300,7 +300,6 @@ CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
CONFIG_LARGE_ALLOCS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -612,6 +611,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_BFIN_TIMER_LATENCY is not set
# CONFIG_SIMPLE_GPIO is not set
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
diff --git a/arch/blackfin/configs/H8606_defconfig b/arch/blackfin/configs/H8606_defconfig
index 1fc31f1b762b..bd553da15db8 100644
--- a/arch/blackfin/configs/H8606_defconfig
+++ b/arch/blackfin/configs/H8606_defconfig
@@ -54,7 +54,7 @@ CONFIG_KALLSYMS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -250,7 +250,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
CONFIG_BFIN_GPTIMERS=y
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -751,7 +750,7 @@ CONFIG_SPI_BFIN=y
#
# SPI Protocol Masters
#
-CONFIG_SPI_AT25=y
+CONFIG_EEPROM_AT25=y
CONFIG_SPI_SPIDEV=y
#
diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
index 285d2241df26..eae83b5de92f 100644
--- a/arch/blackfin/configs/IP0X_defconfig
+++ b/arch/blackfin/configs/IP0X_defconfig
@@ -55,7 +55,7 @@ CONFIG_KALLSYMS=y
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -262,7 +262,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -804,7 +803,7 @@ CONFIG_SPI_BFIN=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
#
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
index bffca7de65d4..ad096702ac16 100644
--- a/arch/blackfin/configs/PNAV-10_defconfig
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22.12
+# Linux kernel version: 2.6.28-rc2
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -8,41 +8,37 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_GPIO=y
CONFIG_FORCE_MAX_ZONEORDER=14
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
-# Code maturity level options
+# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -54,40 +50,41 @@ CONFIG_KALLSYMS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=9
-# CONFIG_NP2 is not set
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
-
-#
-# Block layer
-#
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -101,9 +98,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
# CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
#
# Blackfin Processor Options
@@ -112,8 +111,15 @@ CONFIG_PREEMPT_VOLUNTARY=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
+# CONFIG_BF523 is not set
+# CONFIG_BF524 is not set
# CONFIG_BF525 is not set
+# CONFIG_BF526 is not set
# CONFIG_BF527 is not set
# CONFIG_BF531 is not set
# CONFIG_BF532 is not set
@@ -121,22 +127,26 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
CONFIG_BF537=y
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=2
+CONFIG_BF_REV_MAX=3
# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_1 is not set
CONFIG_BF_REV_0_2=y
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF53x=y
-CONFIG_BFIN_SINGLE_CORE=y
CONFIG_MEM_MT48LC32M8A2_75=y
CONFIG_IRQ_PLL_WAKEUP=7
CONFIG_IRQ_RTC=8
@@ -146,28 +156,30 @@ CONFIG_IRQ_SPORT0_TX=9
CONFIG_IRQ_SPORT1_RX=9
CONFIG_IRQ_SPORT1_TX=9
CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
CONFIG_IRQ_UART0_RX=10
CONFIG_IRQ_UART0_TX=10
CONFIG_IRQ_UART1_RX=10
CONFIG_IRQ_UART1_TX=10
CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
CONFIG_IRQ_MEM_DMA1=13
CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_SPI=10
# CONFIG_BFIN537_STAMP is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_TCM is not set
CONFIG_PNAV10=y
+# CONFIG_CAMSIG_MINOTAUR is not set
# CONFIG_GENERIC_BF537_BOARD is not set
#
@@ -191,6 +203,7 @@ CONFIG_IRQ_PROG_INTA=12
# Board customizations
#
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_BOOT_LOAD=0x1000
#
# Clock/PLL Setup
@@ -199,7 +212,7 @@ CONFIG_CLKIN_HZ=24576000
# CONFIG_BFIN_KERNEL_CLOCK is not set
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
-CONFIG_MAX_SCLK_HZ=133000000
+CONFIG_MAX_SCLK_HZ=133333333
CONFIG_MIN_SCLK_HZ=27000000
#
@@ -210,13 +223,17 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_CYCLES_CLOCKSOURCE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
#
-# Memory Setup
+# Misc
#
-CONFIG_MAX_MEM_SIZE=64
-CONFIG_MEM_ADD_WIDTH=10
-CONFIG_BOOT_LOAD=0x1000
CONFIG_BFIN_SCRATCH_REG_RETN=y
# CONFIG_BFIN_SCRATCH_REG_RETE is not set
# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set
@@ -243,6 +260,12 @@ CONFIG_IP_CHECKSUM_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
CONFIG_SYSCALL_TAB_L1=y
CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -251,13 +274,14 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
-CONFIG_LARGE_ALLOCS=y
-# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_BFIN_GPTIMERS=y
+# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -271,7 +295,7 @@ CONFIG_BFIN_DCACHE=y
# CONFIG_BFIN_ICACHE_LOCK is not set
CONFIG_BFIN_WB=y
# CONFIG_BFIN_WT is not set
-CONFIG_L1_MAX_PIECE=16
+# CONFIG_MPU is not set
#
# Asynchonous Memory Configuration
@@ -299,12 +323,7 @@ CONFIG_BANK_3=0x99B2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
# CONFIG_PCCARD is not set
#
@@ -314,21 +333,20 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
CONFIG_NET=y
#
@@ -341,6 +359,7 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -362,6 +381,7 @@ CONFIG_SYN_COOKIES=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
@@ -369,8 +389,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
@@ -379,6 +397,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -388,10 +407,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
# CONFIG_NET_SCHED is not set
#
@@ -399,18 +414,19 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
#
# Device Drivers
@@ -419,14 +435,11 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# Generic Driver Options
#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
@@ -434,6 +447,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -446,6 +460,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -470,7 +485,7 @@ CONFIG_MTD_RAM=y
# Mapping drivers for chip access
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
-# CONFIG_MTD_BF5xx is not set
+# CONFIG_MTD_GPIO_ADDR is not set
CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_PLATRAM is not set
@@ -509,33 +524,22 @@ CONFIG_MTD_NAND_IDS=y
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
-
-#
-# Parallel port support
-#
# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -543,22 +547,17 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
# CONFIG_MD is not set
-
-#
-# Network device support
-#
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
+# CONFIG_VETH is not set
CONFIG_PHYLIB=y
#
@@ -572,46 +571,45 @@ CONFIG_PHYLIB=y
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-# CONFIG_SMC91X is not set
CONFIG_BFIN_MAC=y
# CONFIG_BFIN_MAC_USE_L1 is not set
CONFIG_BFIN_TX_DESC_NUM=100
CONFIG_BFIN_RX_DESC_NUM=100
CONFIG_BFIN_MAC_RMII=y
+# CONFIG_SMC91X is not set
# CONFIG_SMSC911X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NETDEV_1000=y
-CONFIG_NETDEV_10000=y
# CONFIG_AX88180 is not set
+CONFIG_NETDEV_10000=y
#
# Wireless LAN
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
# CONFIG_PHONE is not set
#
@@ -626,9 +624,6 @@ CONFIG_INPUT=y
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
-CONFIG_INPUT_TSDEV=y
-CONFIG_INPUT_TSDEV_SCREEN_X=240
-CONFIG_INPUT_TSDEV_SCREEN_Y=320
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
@@ -642,24 +637,29 @@ CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_ADS7846 is not set
CONFIG_TOUCHSCREEN_AD7877=y
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_ELO is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
# CONFIG_TOUCHSCREEN_MK712 is not set
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
-# CONFIG_TOUCHSCREEN_UCB1400 is not set
# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_ATI_REMOTE is not set
# CONFIG_INPUT_ATI_REMOTE2 is not set
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
CONFIG_INPUT_UINPUT=y
-# CONFIG_BF53X_PFBUTTONS is not set
-# CONFIG_TWI_KEYPAD is not set
+# CONFIG_CONFIG_INPUT_PCF8574 is not set
#
# Hardware I/O ports
@@ -672,18 +672,17 @@ CONFIG_INPUT_UINPUT=y
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BFIN_SIMPLE_TIMER is not set
# CONFIG_BF5xx_PPI is not set
CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
CONFIG_TWI_LCD=m
-CONFIG_TWI_LCD_SLAVE_ADDR=34
-# CONFIG_AD5304 is not set
-# CONFIG_BF5xx_TEA5764 is not set
-# CONFIG_BF5xx_FBDMA is not set
+CONFIG_BFIN_DMA_INTERFACE=m
+# CONFIG_SIMPLE_GPIO is not set
# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_BFIN_JTAG_COMM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -716,68 +715,59 @@ CONFIG_CAN4LINUX=y
#
# linux embedded drivers
#
-# CONFIG_CAN_MCF5282 is not set
-# CONFIG_CAN_UNCTWINCAN is not set
CONFIG_CAN_BLACKFIN=m
-
-#
-# IPMI
-#
# CONFIG_IPMI_HANDLER is not set
-# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
# CONFIG_TCG_TPM is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
-# I2C Algorithms
+# I2C Hardware Bus support
#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
#
-# I2C Hardware Bus support
+# I2C system bus drivers (mostly embedded / system-on-chip)
#
-# CONFIG_I2C_BLACKFIN_GPIO is not set
CONFIG_I2C_BLACKFIN_TWI=y
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_EEPROM_AT24 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
CONFIG_SENSORS_PCF8574=m
-CONFIG_SENSORS_PCF8575=y
-# CONFIG_SENSORS_PCA9543 is not set
+# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 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
-
-#
-# SPI support
-#
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
@@ -785,34 +775,37 @@ CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
-
-#
-# Dallas's 1-wire bus
-#
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
@@ -827,58 +820,76 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
-CONFIG_DAB=y
+# CONFIG_VIDEO_MEDIA is not set
#
-# Graphics support
+# Multimedia drivers
#
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_DAB=y
#
-# Display device support
+# Graphics support
#
-# CONFIG_DISPLAY_SUPPORT is not set
# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
# CONFIG_FB_SYS_FILLRECT is not set
# CONFIG_FB_SYS_COPYAREA is not set
# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
# CONFIG_FB_SYS_FOPS is not set
-CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -888,25 +899,34 @@ CONFIG_FB_DEFERRED_IO=y
#
# Frame buffer hardware drivers
#
-# CONFIG_FB_BFIN_7171 is not set
-# CONFIG_FB_BFIN_7393 is not set
+# CONFIG_FB_BFIN_T350MCQB is not set
+# CONFIG_FB_BFIN_LQ035Q1 is not set
CONFIG_FB_BF537_LQ035=y
CONFIG_LQ035_SLAVE_ADDR=0x58
CONFIG_FB_BFIN_LANDSCAPE=y
# CONFIG_FB_BFIN_BGR is not set
-# CONFIG_FB_BFIN_T350MCQB is not set
+# CONFIG_FB_BFIN_7393 is not set
+# CONFIG_FB_HITACHI_TX09 is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
-# CONFIG_LOGO is not set
+# CONFIG_FB_METRONOME is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_ILI9320 is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+# CONFIG_LCD_PLATFORM is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_CORGI is not set
#
-# Sound
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_LOGO is not set
CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
+CONFIG_SOUND_OSS_CORE=y
CONFIG_SND=m
# CONFIG_SND_SEQUENCER is not set
# CONFIG_SND_MIXER_OSS is not set
@@ -916,46 +936,30 @@ CONFIG_SND=m
# CONFIG_SND_VERBOSE_PROCFS is not set
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
+CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_MTPAV is not set
# CONFIG_SND_SERIAL_U16550 is not set
# CONFIG_SND_MPU401 is not set
+CONFIG_SND_SPI=y
#
# ALSA Blackfin devices
#
# CONFIG_SND_BLACKFIN_AD1836 is not set
-# CONFIG_SND_BFIN_AD73311 is not set
-
-#
-# System on Chip audio support
-#
+# CONFIG_SND_BFIN_AD73322 is not set
# CONFIG_SND_SOC is not set
-
-#
-# Open Sound System
-#
CONFIG_SOUND_PRIME=y
-# CONFIG_OSS_OBSOLETE is not set
-# CONFIG_SOUND_MSNDCLAS is not set
-# CONFIG_SOUND_MSNDPIN is not set
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
# CONFIG_HID is not set
-
-#
-# USB support
-#
+# CONFIG_HID_PID is not set
+CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
# CONFIG_USB_ARCH_HAS_EHCI is not set
# CONFIG_USB is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
#
# Enable Host or Gadget support to see Inventra options
@@ -964,37 +968,11 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
-
-#
-# USB Gadget Support
-#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
-
-#
-# LED devices
-#
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
+# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
@@ -1014,6 +992,7 @@ CONFIG_RTC_INTF_DEV=y
# I2C RTC drivers
#
# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_MAX6900 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
@@ -1021,43 +1000,41 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
#
# SPI RTC drivers
#
-# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_BFIN=y
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# PBX support
-#
-# CONFIG_PBX is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -1067,20 +1044,18 @@ CONFIG_EXT2_FS_XATTR=y
# CONFIG_EXT2_FS_POSIX_ACL is not set
# CONFIG_EXT2_FS_SECURITY is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_FS_MBCACHE=y
# 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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1106,7 +1081,6 @@ CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
#
@@ -1121,36 +1095,35 @@ CONFIG_RAMFS=y
# CONFIG_EFS_FS is not set
CONFIG_YAFFS_FS=y
CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
# CONFIG_YAFFS_DOES_ECC is not set
CONFIG_YAFFS_YAFFS2=y
CONFIG_YAFFS_AUTO_YAFFS2=y
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=m
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1159,17 +1132,12 @@ CONFIG_SMB_FS=m
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
CONFIG_NLS=m
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
@@ -1210,29 +1178,30 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
# CONFIG_NLS_UTF8 is not set
-
-#
-# Distributed Lock Manager
-#
# CONFIG_DLM is not set
#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_DEBUG_VERBOSE=y
# CONFIG_DEBUG_MMRS is not set
+# CONFIG_DEBUG_DOUBLEFAULT is not set
# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -1250,13 +1219,94 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0
#
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
#
-# Cryptographic options
+# Random Number Generation
#
-# CONFIG_CRYPTO is not set
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
#
# Library routines
@@ -1264,8 +1314,10 @@ CONFIG_SECURITY_CAPABILITIES=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
diff --git a/arch/blackfin/configs/SRV1_defconfig b/arch/blackfin/configs/SRV1_defconfig
index b1309f878fcd..fa580affc9d6 100644
--- a/arch/blackfin/configs/SRV1_defconfig
+++ b/arch/blackfin/configs/SRV1_defconfig
@@ -59,7 +59,7 @@ CONFIG_KALLSYMS_ALL=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
@@ -172,14 +172,14 @@ CONFIG_IRQ_UART1_RX=10
CONFIG_IRQ_UART1_TX=10
CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
CONFIG_IRQ_MEM_DMA1=13
@@ -271,7 +271,6 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
-CONFIG_BFIN_DMA_5XX=y
CONFIG_DMA_UNCACHED_2M=y
# CONFIG_DMA_UNCACHED_1M is not set
# CONFIG_DMA_UNCACHED_NONE is not set
@@ -786,7 +785,7 @@ CONFIG_I2C_CHARDEV=y
#
# CONFIG_I2C_BLACKFIN_GPIO is not set
CONFIG_I2C_BLACKFIN_TWI=y
-CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100
# CONFIG_I2C_GPIO is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
@@ -799,7 +798,7 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_SENSORS_AD5252 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8575 is not set
# CONFIG_SENSORS_PCA9543 is not set
@@ -827,7 +826,7 @@ CONFIG_SPI_BFIN=y
#
# SPI Protocol Masters
#
-CONFIG_SPI_AT25=m
+CONFIG_EEPROM_AT25=m
# CONFIG_SPI_SPIDEV is not set
#
diff --git a/arch/blackfin/configs/TCM-BF537_defconfig b/arch/blackfin/configs/TCM-BF537_defconfig
index c482ee171f9e..97a1f1d20dcf 100644
--- a/arch/blackfin/configs/TCM-BF537_defconfig
+++ b/arch/blackfin/configs/TCM-BF537_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24.7
-# Thu Jul 31 00:53:15 2008
+# Linux kernel version: 2.6.28-rc2
+# Tue Jan 6 09:22:17 2009
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
@@ -9,7 +9,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
CONFIG_ZONE_DMA=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
@@ -30,17 +29,14 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_USER_NS is not set
-# CONFIG_PID_NS is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CGROUPS is not set
-CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_FAIR_USER_SCHED=y
-# CONFIG_FAIR_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -52,22 +48,30 @@ CONFIG_KALLSYMS=y
# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
-CONFIG_ELF_CORE=y
+# CONFIG_ELF_CORE is not set
+CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
@@ -78,6 +82,7 @@ CONFIG_BLOCK=y
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -91,9 +96,11 @@ CONFIG_IOSCHED_CFQ=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
+CONFIG_CLASSIC_RCU=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
+# CONFIG_FREEZER is not set
#
# Blackfin Processor Options
@@ -102,6 +109,10 @@ CONFIG_PREEMPT_NONE=y
#
# Processor and Board Settings
#
+# CONFIG_BF512 is not set
+# CONFIG_BF514 is not set
+# CONFIG_BF516 is not set
+# CONFIG_BF518 is not set
# CONFIG_BF522 is not set
# CONFIG_BF523 is not set
# CONFIG_BF524 is not set
@@ -114,18 +125,23 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
CONFIG_BF537=y
+# CONFIG_BF538 is not set
+# CONFIG_BF539 is not set
# CONFIG_BF542 is not set
# CONFIG_BF544 is not set
# CONFIG_BF547 is not set
# CONFIG_BF548 is not set
# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+CONFIG_BF_REV_MIN=2
+CONFIG_BF_REV_MAX=3
# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_1 is not set
CONFIG_BF_REV_0_2=y
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_0_6 is not set
# CONFIG_BF_REV_ANY is not set
# CONFIG_BF_REV_NONE is not set
CONFIG_BF53x=y
@@ -137,25 +153,25 @@ CONFIG_IRQ_SPORT0_TX=9
CONFIG_IRQ_SPORT1_RX=9
CONFIG_IRQ_SPORT1_TX=9
CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
CONFIG_IRQ_UART0_RX=10
CONFIG_IRQ_UART0_TX=10
CONFIG_IRQ_UART1_RX=10
CONFIG_IRQ_UART1_TX=10
CONFIG_IRQ_MAC_RX=11
CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_TIMER0=12
+CONFIG_IRQ_TIMER1=12
+CONFIG_IRQ_TIMER2=12
+CONFIG_IRQ_TIMER3=12
+CONFIG_IRQ_TIMER4=12
+CONFIG_IRQ_TIMER5=12
+CONFIG_IRQ_TIMER6=12
+CONFIG_IRQ_TIMER7=12
CONFIG_IRQ_PORTG_INTB=12
CONFIG_IRQ_MEM_DMA0=13
CONFIG_IRQ_MEM_DMA1=13
CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_SPI=10
# CONFIG_BFIN537_STAMP is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
CONFIG_BFIN537_BLUETECHNIX_TCM=y
@@ -191,7 +207,6 @@ CONFIG_BOOT_LOAD=0x1000
#
CONFIG_CLKIN_HZ=25000000
# CONFIG_BFIN_KERNEL_CLOCK is not set
-CONFIG_MAX_MEM_SIZE=32
CONFIG_MAX_VCO_HZ=600000000
CONFIG_MIN_VCO_HZ=50000000
CONFIG_MAX_SCLK_HZ=133333333
@@ -205,10 +220,10 @@ CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_CYCLES_CLOCKSOURCE is not set
-# CONFIG_TICK_ONESHOT is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
@@ -242,6 +257,12 @@ CONFIG_IP_CHECKSUM_L1=y
CONFIG_CACHELINE_ALIGNED_L1=y
CONFIG_SYSCALL_TAB_L1=y
CONFIG_CPLB_SWITCH_TAB_L1=y
+CONFIG_APP_STACK_L1=y
+
+#
+# Speed Optimizations
+#
+CONFIG_BFIN_INS_LOWOVERHEAD=y
CONFIG_RAMKERNEL=y
# CONFIG_ROMKERNEL is not set
CONFIG_SELECT_MEMORY_MODEL=y
@@ -250,14 +271,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_VIRT_TO_BUS=y
# CONFIG_BFIN_GPTIMERS is not set
-CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_4M is not set
# CONFIG_DMA_UNCACHED_2M is not set
CONFIG_DMA_UNCACHED_1M=y
@@ -300,7 +320,6 @@ CONFIG_BANK_3=0xFFC2
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
#
@@ -310,23 +329,20 @@ CONFIG_BINFMT_ELF_FDPIC=y
CONFIG_BINFMT_FLAT=y
CONFIG_BINFMT_ZFLAT=y
CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
# CONFIG_PM is not set
-CONFIG_SUSPEND_UP_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_PM_WAKEUP_BY_GPIO is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
-
-#
-# Networking
-#
# CONFIG_NET is not set
#
@@ -345,6 +361,7 @@ CONFIG_MTD=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
@@ -362,8 +379,10 @@ CONFIG_MTD_BLOCK=y
#
# RAM/ROM/Flash chip drivers
#
-# CONFIG_MTD_CFI is not set
+CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -374,6 +393,10 @@ CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
@@ -381,8 +404,9 @@ CONFIG_MTD_RAM=y
#
# Mapping drivers for chip access
#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_GPIO_ADDR is not set
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_GPIO_ADDR=y
CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_PLATRAM is not set
@@ -416,10 +440,13 @@ CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
#
@@ -454,8 +481,11 @@ CONFIG_MISC_DEVICES=y
# CONFIG_BF5xx_PPI is not set
CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_BFIN_DMA_INTERFACE=m
# CONFIG_SIMPLE_GPIO is not set
# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_BFIN_JTAG_COMM is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -486,15 +516,10 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_CAN4LINUX is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
-
-#
-# SPI support
-#
CONFIG_SPI=y
CONFIG_SPI_MASTER=y
@@ -502,17 +527,22 @@ CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
#
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BFIN_LOCK is not set
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -523,20 +553,27 @@ CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y
#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -551,20 +588,16 @@ CONFIG_SSB_POSSIBLE=y
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
-
-#
-# Userspace I/O
-#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
@@ -574,19 +607,17 @@ CONFIG_EXT2_FS_XATTR=y
# CONFIG_EXT2_FS_POSIX_ACL is not set
# CONFIG_EXT2_FS_SECURITY is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_FS_MBCACHE=y
# 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_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -628,8 +659,11 @@ CONFIG_SYSFS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
@@ -639,7 +673,6 @@ CONFIG_SYSFS=y
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
-# CONFIG_INSTRUMENTATION is not set
#
# Kernel hacking
@@ -647,14 +680,22 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_DEBUG_VERBOSE=y
CONFIG_DEBUG_MMRS=y
+# CONFIG_DEBUG_DOUBLEFAULT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
CONFIG_DEBUG_BFIN_HWTRACE_ON=y
CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y
@@ -671,9 +712,8 @@ CONFIG_ACCESS_CHECK=y
# Security options
#
# CONFIG_KEYS is not set
-CONFIG_SECURITY=y
-# CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
# CONFIG_CRYPTO is not set
@@ -682,6 +722,7 @@ CONFIG_SECURITY_CAPABILITIES=y
#
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
# CONFIG_CRC32 is not set
# CONFIG_CRC7 is not set
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h
index 7cf508718605..94b2a9b19451 100644
--- a/arch/blackfin/include/asm/atomic.h
+++ b/arch/blackfin/include/asm/atomic.h
@@ -1,6 +1,7 @@
#ifndef __ARCH_BLACKFIN_ATOMIC__
#define __ARCH_BLACKFIN_ATOMIC__
+#include <linux/types.h>
#include <asm/system.h> /* local_irq_XXX() */
/*
@@ -13,108 +14,160 @@
* Tony Kou (tonyko@lineo.ca) Lineo Inc. 2001
*/
-typedef struct {
- int counter;
-} atomic_t;
#define ATOMIC_INIT(i) { (i) }
-
-#define atomic_read(v) ((v)->counter)
#define atomic_set(v, i) (((v)->counter) = i)
-static __inline__ void atomic_add(int i, atomic_t * v)
+#ifdef CONFIG_SMP
+
+#define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter)
+
+asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr);
+
+asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value);
+
+asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value);
+
+asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value);
+
+asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value);
+
+asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value);
+
+static inline void atomic_add(int i, atomic_t *v)
+{
+ __raw_atomic_update_asm(&v->counter, i);
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+ __raw_atomic_update_asm(&v->counter, -i);
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+ return __raw_atomic_update_asm(&v->counter, i);
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+ return __raw_atomic_update_asm(&v->counter, -i);
+}
+
+static inline void atomic_inc(volatile atomic_t *v)
+{
+ __raw_atomic_update_asm(&v->counter, 1);
+}
+
+static inline void atomic_dec(volatile atomic_t *v)
+{
+ __raw_atomic_update_asm(&v->counter, -1);
+}
+
+static inline void atomic_clear_mask(int mask, atomic_t *v)
+{
+ __raw_atomic_clear_asm(&v->counter, mask);
+}
+
+static inline void atomic_set_mask(int mask, atomic_t *v)
+{
+ __raw_atomic_set_asm(&v->counter, mask);
+}
+
+static inline int atomic_test_mask(int mask, atomic_t *v)
+{
+ return __raw_atomic_test_asm(&v->counter, mask);
+}
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#else /* !CONFIG_SMP */
+
+#define atomic_read(v) ((v)->counter)
+
+static inline void atomic_add(int i, atomic_t *v)
{
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter += i;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
-static __inline__ void atomic_sub(int i, atomic_t * v)
+static inline void atomic_sub(int i, atomic_t *v)
{
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter -= i;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
-static inline int atomic_add_return(int i, atomic_t * v)
+static inline int atomic_add_return(int i, atomic_t *v)
{
int __temp = 0;
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter += i;
__temp = v->counter;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return __temp;
}
-#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
-static inline int atomic_sub_return(int i, atomic_t * v)
+static inline int atomic_sub_return(int i, atomic_t *v)
{
int __temp = 0;
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter -= i;
__temp = v->counter;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return __temp;
}
-static __inline__ void atomic_inc(volatile atomic_t * v)
+static inline void atomic_inc(volatile atomic_t *v)
{
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter++;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
-#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-#define atomic_add_unless(v, a, u) \
-({ \
- int c, old; \
- c = atomic_read(v); \
- while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
- c = old; \
- c != (u); \
-})
-#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
-
-static __inline__ void atomic_dec(volatile atomic_t * v)
+static inline void atomic_dec(volatile atomic_t *v)
{
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter--;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
-static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t * v)
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
{
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter &= ~mask;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
-static __inline__ void atomic_set_mask(unsigned int mask, atomic_t * v)
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
{
long flags;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
v->counter |= mask;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
/* Atomic operations are already serializing */
@@ -123,9 +176,25 @@ static __inline__ void atomic_set_mask(unsigned int mask, atomic_t * v)
#define smp_mb__before_atomic_inc() barrier()
#define smp_mb__after_atomic_inc() barrier()
+#endif /* !CONFIG_SMP */
+
+#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
#define atomic_dec_return(v) atomic_sub_return(1,(v))
#define atomic_inc_return(v) atomic_add_return(1,(v))
+#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#define atomic_add_unless(v, a, u) \
+({ \
+ int c, old; \
+ c = atomic_read(v); \
+ while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
+ c = old; \
+ c != (u); \
+})
+#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+
/*
* atomic_inc_and_test - increment and test
* @v: pointer of type atomic_t
diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h
index 77295666c34b..daffc0684e75 100644
--- a/arch/blackfin/include/asm/bfin-global.h
+++ b/arch/blackfin/include/asm/bfin-global.h
@@ -47,6 +47,9 @@
# define DMA_UNCACHED_REGION (0)
#endif
+extern void bfin_setup_caches(unsigned int cpu);
+extern void bfin_setup_cpudata(unsigned int cpu);
+
extern unsigned long get_cclk(void);
extern unsigned long get_sclk(void);
extern unsigned long sclk_to_usecs(unsigned long sclk);
@@ -58,8 +61,6 @@ extern void dump_bfin_trace_buffer(void);
/* init functions only */
extern int init_arch_irq(void);
-extern void bfin_icache_init(void);
-extern void bfin_dcache_init(void);
extern void init_exception_vectors(void);
extern void program_IAR(void);
@@ -110,7 +111,7 @@ extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size;
#ifdef CONFIG_BFIN_ICACHE_LOCK
extern void cache_grab_lock(int way);
-extern void cache_lock(int way);
+extern void bfin_cache_lock(int way);
#endif
#endif
diff --git a/arch/blackfin/include/asm/bfin5xx_spi.h b/arch/blackfin/include/asm/bfin5xx_spi.h
index 9fa19158e38d..1306e6b22946 100644
--- a/arch/blackfin/include/asm/bfin5xx_spi.h
+++ b/arch/blackfin/include/asm/bfin5xx_spi.h
@@ -1,22 +1,12 @@
-/************************************************************
-
-* Copyright (C) 2006-2008, Analog Devices. All Rights Reserved
-*
-* FILE bfin5xx_spi.h
-* PROGRAMMER(S): Luke Yang (Analog Devices Inc.)
-*
-*
-* DATE OF CREATION: March. 10th 2006
-*
-* SYNOPSIS:
-*
-* DESCRIPTION: header file for SPI controller driver for Blackfin5xx.
-**************************************************************
-
-* MODIFICATION HISTORY:
-* March 10, 2006 bfin5xx_spi.h Created. (Luke Yang)
-
-************************************************************/
+/*
+ * Blackfin On-Chip SPI Driver
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef _SPI_CHANNEL_H_
#define _SPI_CHANNEL_H_
diff --git a/arch/blackfin/include/asm/bfin_sdh.h b/arch/blackfin/include/asm/bfin_sdh.h
new file mode 100644
index 000000000000..d61d5497c590
--- /dev/null
+++ b/arch/blackfin/include/asm/bfin_sdh.h
@@ -0,0 +1,19 @@
+/*
+ * bfin_sdh.h - Blackfin SDH definitions
+ *
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __BFIN_SDH_H__
+#define __BFIN_SDH_H__
+
+struct bfin_sd_host {
+ int dma_chan;
+ int irq_int0;
+ int irq_int1;
+ u16 pin_req[7];
+};
+
+#endif
diff --git a/arch/blackfin/include/asm/bfin_sport.h b/arch/blackfin/include/asm/bfin_sport.h
index c76ed8def302..fe88a2c19213 100644
--- a/arch/blackfin/include/asm/bfin_sport.h
+++ b/arch/blackfin/include/asm/bfin_sport.h
@@ -120,9 +120,6 @@ struct sport_register {
#define SPORT_IOC_MAGIC 'P'
#define SPORT_IOC_CONFIG _IOWR('P', 0x01, struct sport_config)
-/* Test purpose */
-#define ENABLE_AD73311 _IOWR('P', 0x02, int)
-
struct sport_dev {
struct cdev cdev; /* Char device structure */
diff --git a/arch/blackfin/include/asm/bfrom.h b/arch/blackfin/include/asm/bfrom.h
index cfe8024c3b2f..9e4be5e5e767 100644
--- a/arch/blackfin/include/asm/bfrom.h
+++ b/arch/blackfin/include/asm/bfrom.h
@@ -43,6 +43,11 @@ __attribute__((__noreturn__))
static inline void bfrom_SoftReset(void *new_stack)
{
while (1)
+ /*
+ * We don't declare the SP as clobbered on purpose, since
+ * it confuses the heck out of the compiler, and this function
+ * never returns
+ */
__asm__ __volatile__(
"sp = %[stack];"
"jump (%[bfrom_syscontrol]);"
diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h
index b39a175c79c1..21b036eadab1 100644
--- a/arch/blackfin/include/asm/bitops.h
+++ b/arch/blackfin/include/asm/bitops.h
@@ -7,7 +7,6 @@
#include <linux/compiler.h>
#include <asm/byteorder.h> /* swab32 */
-#include <asm/system.h> /* save_flags */
#ifdef __KERNEL__
@@ -20,80 +19,107 @@
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffz.h>
-static __inline__ void set_bit(int nr, volatile unsigned long *addr)
+#ifdef CONFIG_SMP
+
+#include <linux/linkage.h>
+
+asmlinkage int __raw_bit_set_asm(volatile unsigned long *addr, int nr);
+
+asmlinkage int __raw_bit_clear_asm(volatile unsigned long *addr, int nr);
+
+asmlinkage int __raw_bit_toggle_asm(volatile unsigned long *addr, int nr);
+
+asmlinkage int __raw_bit_test_set_asm(volatile unsigned long *addr, int nr);
+
+asmlinkage int __raw_bit_test_clear_asm(volatile unsigned long *addr, int nr);
+
+asmlinkage int __raw_bit_test_toggle_asm(volatile unsigned long *addr, int nr);
+
+asmlinkage int __raw_bit_test_asm(const volatile unsigned long *addr, int nr);
+
+static inline void set_bit(int nr, volatile unsigned long *addr)
{
- int *a = (int *)addr;
- int mask;
- unsigned long flags;
+ volatile unsigned long *a = addr + (nr >> 5);
+ __raw_bit_set_asm(a, nr & 0x1f);
+}
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- local_irq_save(flags);
- *a |= mask;
- local_irq_restore(flags);
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+ volatile unsigned long *a = addr + (nr >> 5);
+ __raw_bit_clear_asm(a, nr & 0x1f);
}
-static __inline__ void __set_bit(int nr, volatile unsigned long *addr)
+static inline void change_bit(int nr, volatile unsigned long *addr)
{
- int *a = (int *)addr;
- int mask;
+ volatile unsigned long *a = addr + (nr >> 5);
+ __raw_bit_toggle_asm(a, nr & 0x1f);
+}
- a += nr >> 5;
- mask = 1 << (nr & 0x1f);
- *a |= mask;
+static inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+ volatile const unsigned long *a = addr + (nr >> 5);
+ return __raw_bit_test_asm(a, nr & 0x1f) != 0;
}
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit() barrier()
-#define smp_mb__after_clear_bit() barrier()
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+ volatile unsigned long *a = addr + (nr >> 5);
+ return __raw_bit_test_set_asm(a, nr & 0x1f);
+}
+
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+ volatile unsigned long *a = addr + (nr >> 5);
+ return __raw_bit_test_clear_asm(a, nr & 0x1f);
+}
+
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+ volatile unsigned long *a = addr + (nr >> 5);
+ return __raw_bit_test_toggle_asm(a, nr & 0x1f);
+}
+
+#else /* !CONFIG_SMP */
+
+#include <asm/system.h> /* save_flags */
-static __inline__ void clear_bit(int nr, volatile unsigned long *addr)
+static inline void set_bit(int nr, volatile unsigned long *addr)
{
int *a = (int *)addr;
int mask;
unsigned long flags;
a += nr >> 5;
mask = 1 << (nr & 0x1f);
- local_irq_save(flags);
- *a &= ~mask;
- local_irq_restore(flags);
+ local_irq_save_hw(flags);
+ *a |= mask;
+ local_irq_restore_hw(flags);
}
-static __inline__ void __clear_bit(int nr, volatile unsigned long *addr)
+static inline void clear_bit(int nr, volatile unsigned long *addr)
{
int *a = (int *)addr;
int mask;
-
+ unsigned long flags;
a += nr >> 5;
mask = 1 << (nr & 0x1f);
+ local_irq_save_hw(flags);
*a &= ~mask;
+ local_irq_restore_hw(flags);
}
-static __inline__ void change_bit(int nr, volatile unsigned long *addr)
+static inline void change_bit(int nr, volatile unsigned long *addr)
{
int mask, flags;
unsigned long *ADDR = (unsigned long *)addr;
ADDR += nr >> 5;
mask = 1 << (nr & 31);
- local_irq_save(flags);
- *ADDR ^= mask;
- local_irq_restore(flags);
-}
-
-static __inline__ void __change_bit(int nr, volatile unsigned long *addr)
-{
- int mask;
- unsigned long *ADDR = (unsigned long *)addr;
-
- ADDR += nr >> 5;
- mask = 1 << (nr & 31);
+ local_irq_save_hw(flags);
*ADDR ^= mask;
+ local_irq_restore_hw(flags);
}
-static __inline__ int test_and_set_bit(int nr, void *addr)
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
int mask, retval;
volatile unsigned int *a = (volatile unsigned int *)addr;
@@ -101,27 +127,31 @@ static __inline__ int test_and_set_bit(int nr, void *addr)
a += nr >> 5;
mask = 1 << (nr & 0x1f);
- local_irq_save(flags);
+ local_irq_save_hw(flags);
retval = (mask & *a) != 0;
*a |= mask;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return retval;
}
-static __inline__ int __test_and_set_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
{
int mask, retval;
volatile unsigned int *a = (volatile unsigned int *)addr;
+ unsigned long flags;
a += nr >> 5;
mask = 1 << (nr & 0x1f);
+ local_irq_save_hw(flags);
retval = (mask & *a) != 0;
- *a |= mask;
+ *a &= ~mask;
+ local_irq_restore_hw(flags);
+
return retval;
}
-static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
{
int mask, retval;
volatile unsigned int *a = (volatile unsigned int *)addr;
@@ -129,15 +159,52 @@ static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr)
a += nr >> 5;
mask = 1 << (nr & 0x1f);
- local_irq_save(flags);
+ local_irq_save_hw(flags);
retval = (mask & *a) != 0;
+ *a ^= mask;
+ local_irq_restore_hw(flags);
+ return retval;
+}
+
+#endif /* CONFIG_SMP */
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit() barrier()
+#define smp_mb__after_clear_bit() barrier()
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+ int *a = (int *)addr;
+ int mask;
+
+ a += nr >> 5;
+ mask = 1 << (nr & 0x1f);
+ *a |= mask;
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+ int *a = (int *)addr;
+ int mask;
+
+ a += nr >> 5;
+ mask = 1 << (nr & 0x1f);
*a &= ~mask;
- local_irq_restore(flags);
+}
- return retval;
+static inline void __change_bit(int nr, volatile unsigned long *addr)
+{
+ int mask;
+ unsigned long *ADDR = (unsigned long *)addr;
+
+ ADDR += nr >> 5;
+ mask = 1 << (nr & 31);
+ *ADDR ^= mask;
}
-static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
{
int mask, retval;
volatile unsigned int *a = (volatile unsigned int *)addr;
@@ -145,26 +212,23 @@ static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr)
a += nr >> 5;
mask = 1 << (nr & 0x1f);
retval = (mask & *a) != 0;
- *a &= ~mask;
+ *a |= mask;
return retval;
}
-static __inline__ int test_and_change_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
{
int mask, retval;
volatile unsigned int *a = (volatile unsigned int *)addr;
- unsigned long flags;
a += nr >> 5;
mask = 1 << (nr & 0x1f);
- local_irq_save(flags);
retval = (mask & *a) != 0;
- *a ^= mask;
- local_irq_restore(flags);
+ *a &= ~mask;
return retval;
}
-static __inline__ int __test_and_change_bit(int nr,
+static inline int __test_and_change_bit(int nr,
volatile unsigned long *addr)
{
int mask, retval;
@@ -177,16 +241,7 @@ static __inline__ int __test_and_change_bit(int nr,
return retval;
}
-/*
- * This routine doesn't need to be atomic.
- */
-static __inline__ int __constant_test_bit(int nr, const void *addr)
-{
- return ((1UL << (nr & 31)) &
- (((const volatile unsigned int *)addr)[nr >> 5])) != 0;
-}
-
-static __inline__ int __test_bit(int nr, const void *addr)
+static inline int __test_bit(int nr, const void *addr)
{
int *a = (int *)addr;
int mask;
@@ -196,10 +251,16 @@ static __inline__ int __test_bit(int nr, const void *addr)
return ((mask & *a) != 0);
}
-#define test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- __constant_test_bit((nr),(addr)) : \
- __test_bit((nr),(addr)))
+#ifndef CONFIG_SMP
+/*
+ * This routine doesn't need irq save and restore ops in UP
+ * context.
+ */
+static inline int test_bit(int nr, const void *addr)
+{
+ return __test_bit(nr, addr);
+}
+#endif
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/hweight.h>
@@ -213,6 +274,7 @@ static __inline__ int __test_bit(int nr, const void *addr)
#endif /* __KERNEL__ */
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#endif /* _BLACKFIN_BITOPS_H */
diff --git a/arch/blackfin/include/asm/blackfin.h b/arch/blackfin/include/asm/blackfin.h
index 8749b0e321ab..8bb2cb139756 100644
--- a/arch/blackfin/include/asm/blackfin.h
+++ b/arch/blackfin/include/asm/blackfin.h
@@ -6,11 +6,6 @@
#ifndef _BLACKFIN_H_
#define _BLACKFIN_H_
-#define LO(con32) ((con32) & 0xFFFF)
-#define lo(con32) ((con32) & 0xFFFF)
-#define HI(con32) (((con32) >> 16) & 0xFFFF)
-#define hi(con32) (((con32) >> 16) & 0xFFFF)
-
#include <mach/anomaly.h>
#ifndef __ASSEMBLY__
@@ -65,6 +60,11 @@ static inline void CSYNC(void)
#else /* __ASSEMBLY__ */
+#define LO(con32) ((con32) & 0xFFFF)
+#define lo(con32) ((con32) & 0xFFFF)
+#define HI(con32) (((con32) >> 16) & 0xFFFF)
+#define hi(con32) (((con32) >> 16) & 0xFFFF)
+
/* SSYNC & CSYNC implementations for assembly files */
#define ssync(x) SSYNC(x)
diff --git a/arch/blackfin/include/asm/byteorder.h b/arch/blackfin/include/asm/byteorder.h
index 6a673d42da18..3e69106a4d37 100644
--- a/arch/blackfin/include/asm/byteorder.h
+++ b/arch/blackfin/include/asm/byteorder.h
@@ -1,48 +1,6 @@
#ifndef _BLACKFIN_BYTEORDER_H
#define _BLACKFIN_BYTEORDER_H
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#ifdef __GNUC__
-
-static __inline__ __attribute_const__ __u32 ___arch__swahb32(__u32 xx)
-{
- __u32 tmp;
- __asm__("%1 = %0 >> 8 (V);\n\t"
- "%0 = %0 << 8 (V);\n\t"
- "%0 = %0 | %1;\n\t"
- : "+d"(xx), "=&d"(tmp));
- return xx;
-}
-
-static __inline__ __attribute_const__ __u32 ___arch__swahw32(__u32 xx)
-{
- __u32 rv;
- __asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
- return rv;
-}
-
-#define __arch__swahb32(x) ___arch__swahb32(x)
-#define __arch__swahw32(x) ___arch__swahw32(x)
-#define __arch__swab32(x) ___arch__swahb32(___arch__swahw32(x))
-
-static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 xx)
-{
- __u32 xw = xx;
- __asm__("%0 <<= 8;\n %0.L = %0.L + %0.H (NS);\n": "+d"(xw));
- return (__u16)xw;
-}
-
-#define __arch__swab16(x) ___arch__swab16(x)
-
-#endif
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
-
#include <linux/byteorder/little_endian.h>
#endif /* _BLACKFIN_BYTEORDER_H */
diff --git a/arch/blackfin/include/asm/cache.h b/arch/blackfin/include/asm/cache.h
index 023d72133b5a..86637814cf25 100644
--- a/arch/blackfin/include/asm/cache.h
+++ b/arch/blackfin/include/asm/cache.h
@@ -12,6 +12,11 @@
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#define SMP_CACHE_BYTES L1_CACHE_BYTES
+#ifdef CONFIG_SMP
+#define __cacheline_aligned
+#else
+#define ____cacheline_aligned
+
/*
* Put cacheline_aliged data to L1 data memory
*/
@@ -21,9 +26,33 @@
__section__(".data_l1.cacheline_aligned")))
#endif
+#endif
+
/*
* largest L1 which this arch supports
*/
#define L1_CACHE_SHIFT_MAX 5
+#if defined(CONFIG_SMP) && \
+ !defined(CONFIG_BFIN_CACHE_COHERENT) && \
+ defined(CONFIG_BFIN_DCACHE)
+#define __ARCH_SYNC_CORE_DCACHE
+#ifndef __ASSEMBLY__
+asmlinkage void __raw_smp_mark_barrier_asm(void);
+asmlinkage void __raw_smp_check_barrier_asm(void);
+
+static inline void smp_mark_barrier(void)
+{
+ __raw_smp_mark_barrier_asm();
+}
+static inline void smp_check_barrier(void)
+{
+ __raw_smp_check_barrier_asm();
+}
+
+void resync_core_dcache(void);
+#endif
+#endif
+
+
#endif
diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h
index 4403415583fa..1b040f5b4feb 100644
--- a/arch/blackfin/include/asm/cacheflush.h
+++ b/arch/blackfin/include/asm/cacheflush.h
@@ -35,6 +35,7 @@ extern void blackfin_icache_flush_range(unsigned long start_address, unsigned lo
extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address);
extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address);
extern void blackfin_dflush_page(void *page);
+extern void blackfin_invalidate_entire_dcache(void);
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
@@ -44,12 +45,20 @@ extern void blackfin_dflush_page(void *page);
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
+#ifdef CONFIG_SMP
+#define flush_icache_range_others(start, end) \
+ smp_icache_flush_range_others((start), (end))
+#else
+#define flush_icache_range_others(start, end) do { } while (0)
+#endif
+
static inline void flush_icache_range(unsigned start, unsigned end)
{
#if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE)
# if defined(CONFIG_BFIN_WT)
blackfin_icache_flush_range((start), (end));
+ flush_icache_range_others(start, end);
# else
blackfin_icache_dcache_flush_range((start), (end));
# endif
@@ -58,6 +67,7 @@ static inline void flush_icache_range(unsigned start, unsigned end)
# if defined(CONFIG_BFIN_ICACHE)
blackfin_icache_flush_range((start), (end));
+ flush_icache_range_others(start, end);
# endif
# if defined(CONFIG_BFIN_DCACHE)
blackfin_dcache_flush_range((start), (end));
@@ -66,10 +76,12 @@ static inline void flush_icache_range(unsigned start, unsigned end)
#endif
}
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
- flush_icache_range ((unsigned) (dst), (unsigned) (dst) + (len)); \
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+do { memcpy(dst, src, len); \
+ flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
+ flush_icache_range_others((unsigned long) (dst), (unsigned long) (dst) + (len));\
} while (0)
+
#define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len)
#if defined(CONFIG_BFIN_DCACHE)
@@ -82,7 +94,7 @@ do { memcpy(dst, src, len); \
# define flush_dcache_page(page) blackfin_dflush_page(page_address(page))
#else
# define flush_dcache_range(start,end) do { } while (0)
-# define flush_dcache_page(page) do { } while (0)
+# define flush_dcache_page(page) do { } while (0)
#endif
extern unsigned long reserved_mem_dcache_on;
diff --git a/arch/blackfin/include/asm/checksum.h b/arch/blackfin/include/asm/checksum.h
index 6f6af2b8e9e0..793581fc9556 100644
--- a/arch/blackfin/include/asm/checksum.h
+++ b/arch/blackfin/include/asm/checksum.h
@@ -63,22 +63,23 @@ static inline __wsum
csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
unsigned short proto, __wsum sum)
{
-
- __asm__ ("%0 = %0 + %1;\n\t"
- "CC = AC0;\n\t"
- "if !CC jump 4;\n\t"
- "%0 = %0 + %4;\n\t"
- "%0 = %0 + %2;\n\t"
- "CC = AC0;\n\t"
- "if !CC jump 4;\n\t"
- "%0 = %0 + %4;\n\t"
- "%0 = %0 + %3;\n\t"
- "CC = AC0;\n\t"
- "if !CC jump 4;\n\t"
- "%0 = %0 + %4;\n\t"
- "NOP;\n\t"
- : "=d" (sum)
- : "d" (daddr), "d" (saddr), "d" ((ntohs(len)<<16)+proto*256), "d" (1), "0"(sum));
+ unsigned int carry;
+
+ __asm__ ("%0 = %0 + %2;\n\t"
+ "CC = AC0;\n\t"
+ "%1 = CC;\n\t"
+ "%0 = %0 + %1;\n\t"
+ "%0 = %0 + %3;\n\t"
+ "CC = AC0;\n\t"
+ "%1 = CC;\n\t"
+ "%0 = %0 + %1;\n\t"
+ "%0 = %0 + %4;\n\t"
+ "CC = AC0;\n\t"
+ "%1 = CC;\n\t"
+ "%0 = %0 + %1;\n\t"
+ : "=d" (sum), "=&d" (carry)
+ : "d" (daddr), "d" (saddr), "d" ((len + proto) << 8), "0"(sum)
+ : "CC");
return (sum);
}
diff --git a/arch/blackfin/include/asm/context.S b/arch/blackfin/include/asm/context.S
index c0e630edfb9a..16561ab18b38 100644
--- a/arch/blackfin/include/asm/context.S
+++ b/arch/blackfin/include/asm/context.S
@@ -303,9 +303,14 @@
RETI = [sp++];
RETS = [sp++];
- p0.h = _irq_flags;
- p0.l = _irq_flags;
+#ifdef CONFIG_SMP
+ GET_PDA(p0, r0);
+ r0 = [p0 + PDA_IRQFLAGS];
+#else
+ p0.h = _bfin_irq_flags;
+ p0.l = _bfin_irq_flags;
r0 = [p0];
+#endif
sti r0;
sp += 4; /* Skip Reserved */
@@ -353,3 +358,41 @@
csync;
.endm
+.macro save_context_cplb
+ [--sp] = (R7:0, P5:0);
+ [--sp] = fp;
+
+ [--sp] = a0.x;
+ [--sp] = a0.w;
+ [--sp] = a1.x;
+ [--sp] = a1.w;
+
+ [--sp] = LC0;
+ [--sp] = LC1;
+ [--sp] = LT0;
+ [--sp] = LT1;
+ [--sp] = LB0;
+ [--sp] = LB1;
+
+ [--sp] = RETS;
+.endm
+
+.macro restore_context_cplb
+ RETS = [sp++];
+
+ LB1 = [sp++];
+ LB0 = [sp++];
+ LT1 = [sp++];
+ LT0 = [sp++];
+ LC1 = [sp++];
+ LC0 = [sp++];
+
+ a1.w = [sp++];
+ a1.x = [sp++];
+ a0.w = [sp++];
+ a0.x = [sp++];
+
+ fp = [sp++];
+
+ (R7:0, P5:0) = [SP++];
+.endm
diff --git a/arch/blackfin/include/asm/cplb-mpu.h b/arch/blackfin/include/asm/cplb-mpu.h
deleted file mode 100644
index 75c67b99d607..000000000000
--- a/arch/blackfin/include/asm/cplb-mpu.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * File: include/asm-blackfin/cplbinit.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#ifndef __ASM_BFIN_CPLB_MPU_H
-#define __ASM_BFIN_CPLB_MPU_H
-
-struct cplb_entry {
- unsigned long data, addr;
-};
-
-struct mem_region {
- unsigned long start, end;
- unsigned long dcplb_data;
- unsigned long icplb_data;
-};
-
-extern struct cplb_entry dcplb_tbl[MAX_CPLBS];
-extern struct cplb_entry icplb_tbl[MAX_CPLBS];
-extern int first_switched_icplb;
-extern int first_mask_dcplb;
-extern int first_switched_dcplb;
-
-extern int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot;
-extern int nr_cplb_flush;
-
-extern int page_mask_order;
-extern int page_mask_nelts;
-
-extern unsigned long *current_rwx_mask;
-
-extern void flush_switched_cplbs(void);
-extern void set_mask_dcplbs(unsigned long *);
-
-extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *);
-
-#endif /* __ASM_BFIN_CPLB_MPU_H */
diff --git a/arch/blackfin/include/asm/cplb.h b/arch/blackfin/include/asm/cplb.h
index 9e8b4035fcec..ad566ff9ad16 100644
--- a/arch/blackfin/include/asm/cplb.h
+++ b/arch/blackfin/include/asm/cplb.h
@@ -30,7 +30,6 @@
#ifndef _CPLB_H
#define _CPLB_H
-#include <asm/blackfin.h>
#include <mach/anomaly.h>
#define SDRAM_IGENERIC (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
@@ -55,13 +54,24 @@
#endif
#define L1_DMEMORY (CPLB_LOCK | CPLB_COMMON)
+
+#ifdef CONFIG_SMP
+#define L2_ATTR (INITIAL_T | I_CPLB | D_CPLB)
+#define L2_IMEMORY (CPLB_COMMON | CPLB_LOCK)
+#define L2_DMEMORY (CPLB_COMMON | CPLB_LOCK)
+
+#else
#ifdef CONFIG_BFIN_L2_CACHEABLE
#define L2_IMEMORY (SDRAM_IGENERIC)
#define L2_DMEMORY (SDRAM_DGENERIC)
#else
#define L2_IMEMORY (CPLB_COMMON)
#define L2_DMEMORY (CPLB_COMMON)
-#endif
+#endif /* CONFIG_BFIN_L2_CACHEABLE */
+
+#define L2_ATTR (INITIAL_T | SWITCH_T | I_CPLB | D_CPLB)
+#endif /* CONFIG_SMP */
+
#define SDRAM_DNON_CHBL (CPLB_COMMON)
#define SDRAM_EBIU (CPLB_COMMON)
#define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY)
@@ -71,14 +81,7 @@
#define SIZE_1M 0x00100000 /* 1M */
#define SIZE_4M 0x00400000 /* 4M */
-#ifdef CONFIG_MPU
#define MAX_CPLBS 16
-#else
-#define MAX_CPLBS (16 * 2)
-#endif
-
-#define ASYNC_MEMORY_CPLB_COVERAGE ((ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
- ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE) / SIZE_4M)
#define CPLB_ENABLE_ICACHE_P 0
#define CPLB_ENABLE_DCACHE_P 1
@@ -113,4 +116,8 @@
#define CPLB_INOCACHE CPLB_USER_RD | CPLB_VALID
#define CPLB_IDOCACHE CPLB_INOCACHE | CPLB_L1_CHBL
+#define FAULT_RW (1 << 16)
+#define FAULT_USERSUPV (1 << 17)
+#define FAULT_CPLBBITS 0x0000ffff
+
#endif /* _CPLB_H */
diff --git a/arch/blackfin/include/asm/cplbinit.h b/arch/blackfin/include/asm/cplbinit.h
index f845b41147ba..05b14a631d0c 100644
--- a/arch/blackfin/include/asm/cplbinit.h
+++ b/arch/blackfin/include/asm/cplbinit.h
@@ -32,61 +32,56 @@
#include <asm/blackfin.h>
#include <asm/cplb.h>
+#include <linux/threads.h>
-#ifdef CONFIG_MPU
-
-#include <asm/cplb-mpu.h>
-
+#ifdef CONFIG_CPLB_SWITCH_TAB_L1
+# define PDT_ATTR __attribute__((l1_data))
#else
+# define PDT_ATTR
+#endif
-#define INITIAL_T 0x1
-#define SWITCH_T 0x2
-#define I_CPLB 0x4
-#define D_CPLB 0x8
-
-#define IN_KERNEL 1
-
-enum
-{ZERO_P, L1I_MEM, L1D_MEM, SDRAM_KERN , SDRAM_RAM_MTD, SDRAM_DMAZ, RES_MEM, ASYNC_MEM, L2_MEM};
-
-struct cplb_desc {
- u32 start; /* start address */
- u32 end; /* end address */
- u32 psize; /* prefered size if any otherwise 1MB or 4MB*/
- u16 attr;/* attributes */
- u16 i_conf;/* I-CPLB DATA */
- u16 d_conf;/* D-CPLB DATA */
- u16 valid;/* valid */
- const s8 name[30];/* name */
+struct cplb_entry {
+ unsigned long data, addr;
};
-struct cplb_tab {
- u_long *tab;
- u16 pos;
- u16 size;
+struct cplb_boundary {
+ unsigned long eaddr; /* End of this region. */
+ unsigned long data; /* CPLB data value. */
};
-extern u_long icplb_table[];
-extern u_long dcplb_table[];
+extern struct cplb_boundary dcplb_bounds[];
+extern struct cplb_boundary icplb_bounds[];
+extern int dcplb_nr_bounds, icplb_nr_bounds;
-/* Till here we are discussing about the static memory management model.
- * However, the operating envoronments commonly define more CPLB
- * descriptors to cover the entire addressable memory than will fit into
- * the available on-chip 16 CPLB MMRs. When this happens, the below table
- * will be used which will hold all the potentially required CPLB descriptors
- *
- * This is how Page descriptor Table is implemented in uClinux/Blackfin.
- */
+extern struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS];
+extern struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS];
+extern int first_switched_icplb;
+extern int first_switched_dcplb;
-extern u_long ipdt_table[];
-extern u_long dpdt_table[];
-#ifdef CONFIG_CPLB_INFO
-extern u_long ipdt_swapcount_table[];
-extern u_long dpdt_swapcount_table[];
-#endif
+extern int nr_dcplb_miss[], nr_icplb_miss[], nr_icplb_supv_miss[];
+extern int nr_dcplb_prot[], nr_cplb_flush[];
+
+#ifdef CONFIG_MPU
+
+extern int first_mask_dcplb;
+
+extern int page_mask_order;
+extern int page_mask_nelts;
+
+extern unsigned long *current_rwx_mask[NR_CPUS];
+
+extern void flush_switched_cplbs(unsigned int);
+extern void set_mask_dcplbs(unsigned long *, unsigned int);
+
+extern void __noreturn panic_cplb_error(int seqstat, struct pt_regs *);
#endif /* CONFIG_MPU */
-extern void generate_cplb_tables(void);
+extern void bfin_icache_init(struct cplb_entry *icplb_tbl);
+extern void bfin_dcache_init(struct cplb_entry *icplb_tbl);
+#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
+extern void generate_cplb_tables_all(void);
+extern void generate_cplb_tables_cpu(unsigned int cpu);
+#endif
#endif
diff --git a/arch/blackfin/include/asm/cpu.h b/arch/blackfin/include/asm/cpu.h
new file mode 100644
index 000000000000..c2594ef877f6
--- /dev/null
+++ b/arch/blackfin/include/asm/cpu.h
@@ -0,0 +1,41 @@
+/*
+ * File: arch/blackfin/include/asm/cpu.h.
+ * Author: Philippe Gerum <rpm@xenomai.org>
+ *
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __ASM_BLACKFIN_CPU_H
+#define __ASM_BLACKFIN_CPU_H
+
+#include <linux/percpu.h>
+
+struct task_struct;
+
+struct blackfin_cpudata {
+ struct cpu cpu;
+ struct task_struct *idle;
+ unsigned int imemctl;
+ unsigned int dmemctl;
+ unsigned long loops_per_jiffy;
+ unsigned long dcache_invld_count;
+};
+
+DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data);
+
+#endif
diff --git a/arch/blackfin/include/asm/delay.h b/arch/blackfin/include/asm/delay.h
index 0889c3abb593..c31f91cc1d5d 100644
--- a/arch/blackfin/include/asm/delay.h
+++ b/arch/blackfin/include/asm/delay.h
@@ -13,29 +13,7 @@
static inline void __delay(unsigned long loops)
{
- if (ANOMALY_05000312) {
- /* Interrupted loads to loop registers -> bad */
- unsigned long tmp;
- __asm__ __volatile__(
- "[--SP] = LC0;"
- "[--SP] = LT0;"
- "[--SP] = LB0;"
- "LSETUP (1f,1f) LC0 = %1;"
- "1: NOP;"
- /* We take advantage of the fact that LC0 is 0 at
- * the end of the loop. Otherwise we'd need some
- * NOPs after the CLI here.
- */
- "CLI %0;"
- "LB0 = [SP++];"
- "LT0 = [SP++];"
- "LC0 = [SP++];"
- "STI %0;"
- : "=d" (tmp)
- : "a" (loops)
- );
- } else
- __asm__ __volatile__ (
+__asm__ __volatile__ (
"LSETUP(1f, 1f) LC0 = %0;"
"1: NOP;"
:
@@ -47,16 +25,15 @@ static inline void __delay(unsigned long loops)
#include <linux/param.h> /* needed for HZ */
/*
- * Use only for very small delays ( < 1 msec). Should probably use a
- * lookup table, really, as the multiplications take much too long with
- * short delays. This is a "reasonable" implementation, though (and the
- * first constant multiplications gets optimized away if the delay is
- * a constant)
+ * close approximation borrowed from m68knommu to avoid 64-bit math
*/
+
+#define HZSCALE (268435456 / (1000000/HZ))
+
static inline void udelay(unsigned long usecs)
{
extern unsigned long loops_per_jiffy;
- __delay(usecs * loops_per_jiffy / (1000000 / HZ));
+ __delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6);
}
#endif
diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h
index 6509733bb0f6..e4f7b8043f02 100644
--- a/arch/blackfin/include/asm/dma.h
+++ b/arch/blackfin/include/asm/dma.h
@@ -1,44 +1,17 @@
/*
- * File: include/asm-blackfin/simple_bf533_dma.h
- * Based on: none - original work
- * Author: LG Soft India
- * Copyright (C) 2004-2005 Analog Devices Inc.
- * Created: Tue Sep 21 2004
- * Description: This file contains the major Data structures and constants
- * used for DMA Implementation in BF533
- * Modified:
+ * dma.h - Blackfin DMA defines/structures/etc...
*
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
*/
#ifndef _BLACKFIN_DMA_H_
#define _BLACKFIN_DMA_H_
-#include <asm/io.h>
-#include <linux/slab.h>
-#include <asm/irq.h>
-#include <asm/signal.h>
-
-#include <linux/kernel.h>
-#include <mach/dma.h>
-#include <linux/mm.h>
#include <linux/interrupt.h>
+#include <mach/dma.h>
#include <asm/blackfin.h>
+#include <asm/page.h>
#define MAX_DMA_ADDRESS PAGE_OFFSET
@@ -79,7 +52,7 @@ enum dma_chan_status {
#define DMA_SYNC_RESTART 1
struct dmasg {
- unsigned long next_desc_addr;
+ void *next_desc_addr;
unsigned long start_addr;
unsigned short cfg;
unsigned short x_count;
@@ -89,7 +62,7 @@ struct dmasg {
} __attribute__((packed));
struct dma_register {
- unsigned long next_desc_ptr; /* DMA Next Descriptor Pointer register */
+ void *next_desc_ptr; /* DMA Next Descriptor Pointer register */
unsigned long start_addr; /* DMA Start address register */
unsigned short cfg; /* DMA Configuration register */
@@ -109,7 +82,7 @@ struct dma_register {
short y_modify; /* DMA y_modify register */
unsigned short dummy5;
- unsigned long curr_desc_ptr; /* DMA Current Descriptor Pointer
+ void *curr_desc_ptr; /* DMA Current Descriptor Pointer
register */
unsigned long curr_addr_ptr; /* DMA Current Address Pointer
register */
@@ -131,19 +104,15 @@ struct dma_register {
};
-typedef irqreturn_t(*dma_interrupt_t) (int irq, void *dev_id);
-
+struct mutex;
struct dma_channel {
struct mutex dmalock;
- char *device_id;
+ const char *device_id;
enum dma_chan_status chan_status;
- struct dma_register *regs;
+ volatile struct dma_register *regs;
struct dmasg *sg; /* large mode descriptor */
- unsigned int ctrl_num; /* controller number */
- dma_interrupt_t irq_callback;
+ unsigned int irq;
void *data;
- unsigned int dma_enable_flag;
- unsigned int loopback_flag;
#ifdef CONFIG_PM
unsigned short saved_peripheral_map;
#endif
@@ -157,49 +126,132 @@ void blackfin_dma_resume(void);
/*******************************************************************************
* DMA API's
*******************************************************************************/
-/* functions to set register mode */
-void set_dma_start_addr(unsigned int channel, unsigned long addr);
-void set_dma_next_desc_addr(unsigned int channel, unsigned long addr);
-void set_dma_curr_desc_addr(unsigned int channel, unsigned long addr);
-void set_dma_x_count(unsigned int channel, unsigned short x_count);
-void set_dma_x_modify(unsigned int channel, short x_modify);
-void set_dma_y_count(unsigned int channel, unsigned short y_count);
-void set_dma_y_modify(unsigned int channel, short y_modify);
-void set_dma_config(unsigned int channel, unsigned short config);
-unsigned short set_bfin_dma_config(char direction, char flow_mode,
- char intr_mode, char dma_mode, char width,
- char syncmode);
-void set_dma_curr_addr(unsigned int channel, unsigned long addr);
-
-/* get curr status for polling */
-unsigned short get_dma_curr_irqstat(unsigned int channel);
-unsigned short get_dma_curr_xcount(unsigned int channel);
-unsigned short get_dma_curr_ycount(unsigned int channel);
-unsigned long get_dma_next_desc_ptr(unsigned int channel);
-unsigned long get_dma_curr_desc_ptr(unsigned int channel);
-unsigned long get_dma_curr_addr(unsigned int channel);
-
-/* set large DMA mode descriptor */
-void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg);
-
-/* check if current channel is in use */
-int dma_channel_active(unsigned int channel);
-
-/* common functions must be called in any mode */
+extern struct dma_channel dma_ch[MAX_DMA_CHANNELS];
+extern struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS];
+extern int channel2irq(unsigned int channel);
+
+static inline void set_dma_start_addr(unsigned int channel, unsigned long addr)
+{
+ dma_ch[channel].regs->start_addr = addr;
+}
+static inline void set_dma_next_desc_addr(unsigned int channel, void *addr)
+{
+ dma_ch[channel].regs->next_desc_ptr = addr;
+}
+static inline void set_dma_curr_desc_addr(unsigned int channel, void *addr)
+{
+ dma_ch[channel].regs->curr_desc_ptr = addr;
+}
+static inline void set_dma_x_count(unsigned int channel, unsigned short x_count)
+{
+ dma_ch[channel].regs->x_count = x_count;
+}
+static inline void set_dma_y_count(unsigned int channel, unsigned short y_count)
+{
+ dma_ch[channel].regs->y_count = y_count;
+}
+static inline void set_dma_x_modify(unsigned int channel, short x_modify)
+{
+ dma_ch[channel].regs->x_modify = x_modify;
+}
+static inline void set_dma_y_modify(unsigned int channel, short y_modify)
+{
+ dma_ch[channel].regs->y_modify = y_modify;
+}
+static inline void set_dma_config(unsigned int channel, unsigned short config)
+{
+ dma_ch[channel].regs->cfg = config;
+}
+static inline void set_dma_curr_addr(unsigned int channel, unsigned long addr)
+{
+ dma_ch[channel].regs->curr_addr_ptr = addr;
+}
+
+static inline unsigned short
+set_bfin_dma_config(char direction, char flow_mode,
+ char intr_mode, char dma_mode, char width, char syncmode)
+{
+ return (direction << 1) | (width << 2) | (dma_mode << 4) |
+ (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5);
+}
+
+static inline unsigned short get_dma_curr_irqstat(unsigned int channel)
+{
+ return dma_ch[channel].regs->irq_status;
+}
+static inline unsigned short get_dma_curr_xcount(unsigned int channel)
+{
+ return dma_ch[channel].regs->curr_x_count;
+}
+static inline unsigned short get_dma_curr_ycount(unsigned int channel)
+{
+ return dma_ch[channel].regs->curr_y_count;
+}
+static inline void *get_dma_next_desc_ptr(unsigned int channel)
+{
+ return dma_ch[channel].regs->next_desc_ptr;
+}
+static inline void *get_dma_curr_desc_ptr(unsigned int channel)
+{
+ return dma_ch[channel].regs->curr_desc_ptr;
+}
+static inline unsigned short get_dma_config(unsigned int channel)
+{
+ return dma_ch[channel].regs->cfg;
+}
+static inline unsigned long get_dma_curr_addr(unsigned int channel)
+{
+ return dma_ch[channel].regs->curr_addr_ptr;
+}
+
+static inline void set_dma_sg(unsigned int channel, struct dmasg *sg, int ndsize)
+{
+ dma_ch[channel].regs->cfg =
+ (dma_ch[channel].regs->cfg & ~(0xf << 8)) |
+ ((ndsize & 0xf) << 8);
+ dma_ch[channel].regs->next_desc_ptr = sg;
+}
+
+static inline int dma_channel_active(unsigned int channel)
+{
+ if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE)
+ return 0;
+ else
+ return 1;
+}
+
+static inline void disable_dma(unsigned int channel)
+{
+ dma_ch[channel].regs->cfg &= ~DMAEN;
+ SSYNC();
+ dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
+}
+static inline void enable_dma(unsigned int channel)
+{
+ dma_ch[channel].regs->curr_x_count = 0;
+ dma_ch[channel].regs->curr_y_count = 0;
+ dma_ch[channel].regs->cfg |= DMAEN;
+ dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
+}
void free_dma(unsigned int channel);
-int dma_channel_active(unsigned int channel); /* check if a channel is in use */
-void disable_dma(unsigned int channel);
-void enable_dma(unsigned int channel);
-int request_dma(unsigned int channel, char *device_id);
-int set_dma_callback(unsigned int channel, dma_interrupt_t callback,
- void *data);
-void dma_disable_irq(unsigned int channel);
-void dma_enable_irq(unsigned int channel);
-void clear_dma_irqstat(unsigned int channel);
+int request_dma(unsigned int channel, const char *device_id);
+int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data);
+
+static inline void dma_disable_irq(unsigned int channel)
+{
+ disable_irq(dma_ch[channel].irq);
+}
+static inline void dma_enable_irq(unsigned int channel)
+{
+ enable_irq(dma_ch[channel].irq);
+}
+static inline void clear_dma_irqstat(unsigned int channel)
+{
+ dma_ch[channel].regs->irq_status = DMA_DONE | DMA_ERR;
+}
+
void *dma_memcpy(void *dest, const void *src, size_t count);
void *safe_dma_memcpy(void *dest, const void *src, size_t count);
-
-extern int channel2irq(unsigned int channel);
-extern struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL];
+void blackfin_dma_early_init(void);
#endif
diff --git a/arch/blackfin/include/asm/entry.h b/arch/blackfin/include/asm/entry.h
index c4f721e0d00d..b30a2968e274 100644
--- a/arch/blackfin/include/asm/entry.h
+++ b/arch/blackfin/include/asm/entry.h
@@ -27,6 +27,14 @@
#define SAVE_ALL_SYS save_context_no_interrupts
/* This is used for all normal interrupts. It saves a minimum of registers
to the stack, loads the IRQ number, and jumps to common code. */
+#ifdef CONFIG_IPIPE
+# define LOAD_IPIPE_IPEND \
+ P0.l = lo(IPEND); \
+ P0.h = hi(IPEND); \
+ R1 = [P0];
+#else
+# define LOAD_IPIPE_IPEND
+#endif
#define INTERRUPT_ENTRY(N) \
[--sp] = SYSCFG; \
\
@@ -34,6 +42,7 @@
[--sp] = R0; /*orig_r0*/ \
[--sp] = (R7:0,P5:0); \
R0 = (N); \
+ LOAD_IPIPE_IPEND \
jump __common_int_entry;
/* For timer interrupts, we need to save IPEND, since the user_mode
@@ -53,9 +62,11 @@
/* This one pushes RETI without using CLI. Interrupts are enabled. */
#define SAVE_CONTEXT_SYSCALL save_context_syscall
#define SAVE_CONTEXT save_context_with_interrupts
+#define SAVE_CONTEXT_CPLB save_context_cplb
#define RESTORE_ALL_SYS restore_context_no_interrupts
#define RESTORE_CONTEXT restore_context_with_interrupts
+#define RESTORE_CONTEXT_CPLB restore_context_cplb
#endif /* __ASSEMBLY__ */
#endif /* __BFIN_ENTRY_H */
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index ad33ac271fd9..d4a082ef75b4 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -27,68 +27,17 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/*
-* Number BF537/6/4 BF561 BF533/2/1
-* BF527/5/2
-*
-* GPIO_0 PF0 PF0 PF0
-* GPIO_1 PF1 PF1 PF1
-* GPIO_2 PF2 PF2 PF2
-* GPIO_3 PF3 PF3 PF3
-* GPIO_4 PF4 PF4 PF4
-* GPIO_5 PF5 PF5 PF5
-* GPIO_6 PF6 PF6 PF6
-* GPIO_7 PF7 PF7 PF7
-* GPIO_8 PF8 PF8 PF8
-* GPIO_9 PF9 PF9 PF9
-* GPIO_10 PF10 PF10 PF10
-* GPIO_11 PF11 PF11 PF11
-* GPIO_12 PF12 PF12 PF12
-* GPIO_13 PF13 PF13 PF13
-* GPIO_14 PF14 PF14 PF14
-* GPIO_15 PF15 PF15 PF15
-* GPIO_16 PG0 PF16
-* GPIO_17 PG1 PF17
-* GPIO_18 PG2 PF18
-* GPIO_19 PG3 PF19
-* GPIO_20 PG4 PF20
-* GPIO_21 PG5 PF21
-* GPIO_22 PG6 PF22
-* GPIO_23 PG7 PF23
-* GPIO_24 PG8 PF24
-* GPIO_25 PG9 PF25
-* GPIO_26 PG10 PF26
-* GPIO_27 PG11 PF27
-* GPIO_28 PG12 PF28
-* GPIO_29 PG13 PF29
-* GPIO_30 PG14 PF30
-* GPIO_31 PG15 PF31
-* GPIO_32 PH0 PF32
-* GPIO_33 PH1 PF33
-* GPIO_34 PH2 PF34
-* GPIO_35 PH3 PF35
-* GPIO_36 PH4 PF36
-* GPIO_37 PH5 PF37
-* GPIO_38 PH6 PF38
-* GPIO_39 PH7 PF39
-* GPIO_40 PH8 PF40
-* GPIO_41 PH9 PF41
-* GPIO_42 PH10 PF42
-* GPIO_43 PH11 PF43
-* GPIO_44 PH12 PF44
-* GPIO_45 PH13 PF45
-* GPIO_46 PH14 PF46
-* GPIO_47 PH15 PF47
-*/
-
#ifndef __ARCH_BLACKFIN_GPIO_H__
#define __ARCH_BLACKFIN_GPIO_H__
-#define gpio_bank(x) ((x) >> 4)
-#define gpio_bit(x) (1<<((x) & 0xF))
-#define gpio_sub_n(x) ((x) & 0xF)
+#define gpio_bank(x) ((x) >> 4)
+#define gpio_bit(x) (1<<((x) & 0xF))
+#define gpio_sub_n(x) ((x) & 0xF)
-#define GPIO_BANKSIZE 16
+#define GPIO_BANKSIZE 16
+#define GPIO_BANK_NUM DIV_ROUND_UP(MAX_BLACKFIN_GPIOS, GPIO_BANKSIZE)
+
+#include <mach/gpio.h>
#define GPIO_0 0
#define GPIO_1 1
@@ -139,151 +88,9 @@
#define GPIO_46 46
#define GPIO_47 47
-
#define PERIPHERAL_USAGE 1
#define GPIO_USAGE 0
-#ifdef BF533_FAMILY
-#define MAX_BLACKFIN_GPIOS 16
-
-#define GPIO_PF0 0
-#define GPIO_PF1 1
-#define GPIO_PF2 2
-#define GPIO_PF3 3
-#define GPIO_PF4 4
-#define GPIO_PF5 5
-#define GPIO_PF6 6
-#define GPIO_PF7 7
-#define GPIO_PF8 8
-#define GPIO_PF9 9
-#define GPIO_PF10 10
-#define GPIO_PF11 11
-#define GPIO_PF12 12
-#define GPIO_PF13 13
-#define GPIO_PF14 14
-#define GPIO_PF15 15
-
-#endif
-
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
-#define MAX_BLACKFIN_GPIOS 48
-
-#define GPIO_PF0 0
-#define GPIO_PF1 1
-#define GPIO_PF2 2
-#define GPIO_PF3 3
-#define GPIO_PF4 4
-#define GPIO_PF5 5
-#define GPIO_PF6 6
-#define GPIO_PF7 7
-#define GPIO_PF8 8
-#define GPIO_PF9 9
-#define GPIO_PF10 10
-#define GPIO_PF11 11
-#define GPIO_PF12 12
-#define GPIO_PF13 13
-#define GPIO_PF14 14
-#define GPIO_PF15 15
-#define GPIO_PG0 16
-#define GPIO_PG1 17
-#define GPIO_PG2 18
-#define GPIO_PG3 19
-#define GPIO_PG4 20
-#define GPIO_PG5 21
-#define GPIO_PG6 22
-#define GPIO_PG7 23
-#define GPIO_PG8 24
-#define GPIO_PG9 25
-#define GPIO_PG10 26
-#define GPIO_PG11 27
-#define GPIO_PG12 28
-#define GPIO_PG13 29
-#define GPIO_PG14 30
-#define GPIO_PG15 31
-#define GPIO_PH0 32
-#define GPIO_PH1 33
-#define GPIO_PH2 34
-#define GPIO_PH3 35
-#define GPIO_PH4 36
-#define GPIO_PH5 37
-#define GPIO_PH6 38
-#define GPIO_PH7 39
-#define GPIO_PH8 40
-#define GPIO_PH9 41
-#define GPIO_PH10 42
-#define GPIO_PH11 43
-#define GPIO_PH12 44
-#define GPIO_PH13 45
-#define GPIO_PH14 46
-#define GPIO_PH15 47
-
-#define PORT_F GPIO_PF0
-#define PORT_G GPIO_PG0
-#define PORT_H GPIO_PH0
-
-#endif
-
-#ifdef BF548_FAMILY
-#include <mach/gpio.h>
-#endif
-
-#ifdef BF561_FAMILY
-#define MAX_BLACKFIN_GPIOS 48
-
-#define GPIO_PF0 0
-#define GPIO_PF1 1
-#define GPIO_PF2 2
-#define GPIO_PF3 3
-#define GPIO_PF4 4
-#define GPIO_PF5 5
-#define GPIO_PF6 6
-#define GPIO_PF7 7
-#define GPIO_PF8 8
-#define GPIO_PF9 9
-#define GPIO_PF10 10
-#define GPIO_PF11 11
-#define GPIO_PF12 12
-#define GPIO_PF13 13
-#define GPIO_PF14 14
-#define GPIO_PF15 15
-#define GPIO_PF16 16
-#define GPIO_PF17 17
-#define GPIO_PF18 18
-#define GPIO_PF19 19
-#define GPIO_PF20 20
-#define GPIO_PF21 21
-#define GPIO_PF22 22
-#define GPIO_PF23 23
-#define GPIO_PF24 24
-#define GPIO_PF25 25
-#define GPIO_PF26 26
-#define GPIO_PF27 27
-#define GPIO_PF28 28
-#define GPIO_PF29 29
-#define GPIO_PF30 30
-#define GPIO_PF31 31
-#define GPIO_PF32 32
-#define GPIO_PF33 33
-#define GPIO_PF34 34
-#define GPIO_PF35 35
-#define GPIO_PF36 36
-#define GPIO_PF37 37
-#define GPIO_PF38 38
-#define GPIO_PF39 39
-#define GPIO_PF40 40
-#define GPIO_PF41 41
-#define GPIO_PF42 42
-#define GPIO_PF43 43
-#define GPIO_PF44 44
-#define GPIO_PF45 45
-#define GPIO_PF46 46
-#define GPIO_PF47 47
-
-#define PORT_FIO0 GPIO_0
-#define PORT_FIO1 GPIO_16
-#define PORT_FIO2 GPIO_32
-#endif
-
#ifndef __ASSEMBLY__
/***********************************************************
@@ -425,20 +232,73 @@ struct gpio_port_s {
* MODIFICATION HISTORY :
**************************************************************/
-int gpio_request(unsigned, const char *);
-void gpio_free(unsigned);
+int bfin_gpio_request(unsigned gpio, const char *label);
+void bfin_gpio_free(unsigned gpio);
+int bfin_gpio_irq_request(unsigned gpio, const char *label);
+void bfin_gpio_irq_free(unsigned gpio);
+int bfin_gpio_direction_input(unsigned gpio);
+int bfin_gpio_direction_output(unsigned gpio, int value);
+int bfin_gpio_get_value(unsigned gpio);
+void bfin_gpio_set_value(unsigned gpio, int value);
-void gpio_set_value(unsigned gpio, int arg);
-int gpio_get_value(unsigned gpio);
+#ifdef CONFIG_GPIOLIB
+#include <asm-generic/gpio.h> /* cansleep wrappers */
-#ifndef BF548_FAMILY
-#define gpio_set_value(gpio, value) set_gpio_data(gpio, value)
-#endif
+static inline int gpio_get_value(unsigned int gpio)
+{
+ if (gpio < MAX_BLACKFIN_GPIOS)
+ return bfin_gpio_get_value(gpio);
+ else
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+ if (gpio < MAX_BLACKFIN_GPIOS)
+ bfin_gpio_set_value(gpio, value);
+ else
+ __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+#else /* !CONFIG_GPIOLIB */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+ return bfin_gpio_request(gpio, label);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+ return bfin_gpio_free(gpio);
+}
-int gpio_direction_input(unsigned gpio);
-int gpio_direction_output(unsigned gpio, int value);
+static inline int gpio_direction_input(unsigned gpio)
+{
+ return bfin_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ return bfin_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return bfin_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ return bfin_gpio_set_value(gpio, value);
+}
#include <asm-generic/gpio.h> /* cansleep wrappers */
+#endif /* !CONFIG_GPIOLIB */
#include <asm/irq.h>
static inline int gpio_to_irq(unsigned gpio)
diff --git a/arch/blackfin/include/asm/hardirq.h b/arch/blackfin/include/asm/hardirq.h
index b6b19f1b9dab..717181a1749b 100644
--- a/arch/blackfin/include/asm/hardirq.h
+++ b/arch/blackfin/include/asm/hardirq.h
@@ -42,4 +42,6 @@ typedef struct {
#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1
+extern void ack_bad_irq(unsigned int irq);
+
#endif
diff --git a/arch/blackfin/include/asm/io.h b/arch/blackfin/include/asm/io.h
index 7dc77a21fdf3..63b2d8c78570 100644
--- a/arch/blackfin/include/asm/io.h
+++ b/arch/blackfin/include/asm/io.h
@@ -94,12 +94,12 @@ static inline unsigned int readl(const volatile void __iomem *addr)
#define outw_p(x,addr) outw(x,addr)
#define outl_p(x,addr) outl(x,addr)
-#define ioread8_rep(a,d,c) insb(a,d,c)
-#define ioread16_rep(a,d,c) insw(a,d,c)
-#define ioread32_rep(a,d,c) insl(a,d,c)
-#define iowrite8_rep(a,s,c) outsb(a,s,c)
-#define iowrite16_rep(a,s,c) outsw(a,s,c)
-#define iowrite32_rep(a,s,c) outsl(a,s,c)
+#define ioread8_rep(a,d,c) readsb(a,d,c)
+#define ioread16_rep(a,d,c) readsw(a,d,c)
+#define ioread32_rep(a,d,c) readsl(a,d,c)
+#define iowrite8_rep(a,s,c) writesb(a,s,c)
+#define iowrite16_rep(a,s,c) writesw(a,s,c)
+#define iowrite32_rep(a,s,c) writesl(a,s,c)
#define ioread8(X) readb(X)
#define ioread16(X) readw(X)
@@ -108,6 +108,8 @@ static inline unsigned int readl(const volatile void __iomem *addr)
#define iowrite16(val,X) writew(val,X)
#define iowrite32(val,X) writel(val,X)
+#define mmiowb() wmb()
+
#define IO_SPACE_LIMIT 0xffffffff
/* Values for nocacheflag and cmode */
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
new file mode 100644
index 000000000000..76f53d8b9a0d
--- /dev/null
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -0,0 +1,278 @@
+/* -*- linux-c -*-
+ * include/asm-blackfin/ipipe.h
+ *
+ * Copyright (C) 2002-2007 Philippe Gerum.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; 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.
+ */
+
+#ifndef __ASM_BLACKFIN_IPIPE_H
+#define __ASM_BLACKFIN_IPIPE_H
+
+#ifdef CONFIG_IPIPE
+
+#include <linux/cpumask.h>
+#include <linux/list.h>
+#include <linux/threads.h>
+#include <linux/irq.h>
+#include <linux/ipipe_percpu.h>
+#include <asm/ptrace.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/atomic.h>
+#include <asm/traps.h>
+
+#define IPIPE_ARCH_STRING "1.8-00"
+#define IPIPE_MAJOR_NUMBER 1
+#define IPIPE_MINOR_NUMBER 8
+#define IPIPE_PATCH_NUMBER 0
+
+#ifdef CONFIG_SMP
+#error "I-pipe/blackfin: SMP not implemented"
+#else /* !CONFIG_SMP */
+#define ipipe_processor_id() 0
+#endif /* CONFIG_SMP */
+
+#define prepare_arch_switch(next) \
+do { \
+ ipipe_schedule_notify(current, next); \
+ local_irq_disable_hw(); \
+} while (0)
+
+#define task_hijacked(p) \
+ ({ \
+ int __x__ = ipipe_current_domain != ipipe_root_domain; \
+ /* We would need to clear the SYNC flag for the root domain */ \
+ /* over the current processor in SMP mode. */ \
+ local_irq_enable_hw(); __x__; \
+ })
+
+struct ipipe_domain;
+
+struct ipipe_sysinfo {
+
+ int ncpus; /* Number of CPUs on board */
+ u64 cpufreq; /* CPU frequency (in Hz) */
+
+ /* Arch-dependent block */
+
+ struct {
+ unsigned tmirq; /* Timer tick IRQ */
+ u64 tmfreq; /* Timer frequency */
+ } archdep;
+};
+
+#define ipipe_read_tsc(t) \
+ ({ \
+ unsigned long __cy2; \
+ __asm__ __volatile__ ("1: %0 = CYCLES2\n" \
+ "%1 = CYCLES\n" \
+ "%2 = CYCLES2\n" \
+ "CC = %2 == %0\n" \
+ "if ! CC jump 1b\n" \
+ : "=r" (((unsigned long *)&t)[1]), \
+ "=r" (((unsigned long *)&t)[0]), \
+ "=r" (__cy2) \
+ : /*no input*/ : "CC"); \
+ t; \
+ })
+
+#define ipipe_cpu_freq() __ipipe_core_clock
+#define ipipe_tsc2ns(_t) (((unsigned long)(_t)) * __ipipe_freq_scale)
+#define ipipe_tsc2us(_t) (ipipe_tsc2ns(_t) / 1000 + 1)
+
+/* Private interface -- Internal use only */
+
+#define __ipipe_check_platform() do { } while (0)
+
+#define __ipipe_init_platform() do { } while (0)
+
+extern atomic_t __ipipe_irq_lvdepth[IVG15 + 1];
+
+extern unsigned long __ipipe_irq_lvmask;
+
+extern struct ipipe_domain ipipe_root;
+
+/* enable/disable_irqdesc _must_ be used in pairs. */
+
+void __ipipe_enable_irqdesc(struct ipipe_domain *ipd,
+ unsigned irq);
+
+void __ipipe_disable_irqdesc(struct ipipe_domain *ipd,
+ unsigned irq);
+
+#define __ipipe_enable_irq(irq) (irq_desc[irq].chip->unmask(irq))
+
+#define __ipipe_disable_irq(irq) (irq_desc[irq].chip->mask(irq))
+
+#define __ipipe_lock_root() \
+ set_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)
+
+#define __ipipe_unlock_root() \
+ clear_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags)
+
+void __ipipe_enable_pipeline(void);
+
+#define __ipipe_hook_critical_ipi(ipd) do { } while (0)
+
+#define __ipipe_sync_pipeline(syncmask) \
+ do { \
+ struct ipipe_domain *ipd = ipipe_current_domain; \
+ if (likely(ipd != ipipe_root_domain || !test_bit(IPIPE_ROOTLOCK_FLAG, &ipd->flags))) \
+ __ipipe_sync_stage(syncmask); \
+ } while (0)
+
+void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
+
+int __ipipe_get_irq_priority(unsigned irq);
+
+int __ipipe_get_irqthread_priority(unsigned irq);
+
+void __ipipe_stall_root_raw(void);
+
+void __ipipe_unstall_root_raw(void);
+
+void __ipipe_serial_debug(const char *fmt, ...);
+
+DECLARE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
+
+extern unsigned long __ipipe_core_clock;
+
+extern unsigned long __ipipe_freq_scale;
+
+extern unsigned long __ipipe_irq_tail_hook;
+
+static inline unsigned long __ipipe_ffnz(unsigned long ul)
+{
+ return ffs(ul) - 1;
+}
+
+#define __ipipe_run_irqtail() /* Must be a macro */ \
+ do { \
+ asmlinkage void __ipipe_call_irqtail(void); \
+ unsigned long __pending; \
+ CSYNC(); \
+ __pending = bfin_read_IPEND(); \
+ if (__pending & 0x8000) { \
+ __pending &= ~0x8010; \
+ if (__pending && (__pending & (__pending - 1)) == 0) \
+ __ipipe_call_irqtail(); \
+ } \
+ } while (0)
+
+#define __ipipe_run_isr(ipd, irq) \
+ do { \
+ if (ipd == ipipe_root_domain) { \
+ /* \
+ * Note: the I-pipe implements a threaded interrupt model on \
+ * this arch for Linux external IRQs. The interrupt handler we \
+ * call here only wakes up the associated IRQ thread. \
+ */ \
+ if (ipipe_virtual_irq_p(irq)) { \
+ /* No irqtail here; virtual interrupts have no effect \
+ on IPEND so there is no need for processing \
+ deferral. */ \
+ local_irq_enable_nohead(ipd); \
+ ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
+ local_irq_disable_nohead(ipd); \
+ } else \
+ /* \
+ * No need to run the irqtail here either; \
+ * we can't be preempted by hw IRQs, so \
+ * non-Linux IRQs cannot stack over the short \
+ * thread wakeup code. Which in turn means \
+ * that no irqtail condition could be pending \
+ * for domains above Linux in the pipeline. \
+ */ \
+ ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
+ } else { \
+ __clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
+ local_irq_enable_nohead(ipd); \
+ ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
+ /* Attempt to exit the outer interrupt level before \
+ * starting the deferred IRQ processing. */ \
+ local_irq_disable_nohead(ipd); \
+ __ipipe_run_irqtail(); \
+ __set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
+ } \
+ } while (0)
+
+#define __ipipe_syscall_watched_p(p, sc) \
+ (((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls)
+
+void ipipe_init_irq_threads(void);
+
+int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
+
+#define IS_SYSIRQ(irq) ((irq) > IRQ_CORETMR && (irq) <= SYS_IRQS)
+#define IS_GPIOIRQ(irq) ((irq) >= GPIO_IRQ_BASE && (irq) < NR_IRQS)
+
+#define IRQ_SYSTMR IRQ_TIMER0
+#define IRQ_PRIOTMR CONFIG_IRQ_TIMER0
+
+#if defined(CONFIG_BF531) || defined(CONFIG_BF532) || defined(CONFIG_BF533)
+#define PRIO_GPIODEMUX(irq) CONFIG_PFA
+#elif defined(CONFIG_BF534) || defined(CONFIG_BF536) || defined(CONFIG_BF537)
+#define PRIO_GPIODEMUX(irq) CONFIG_IRQ_PROG_INTA
+#elif defined(CONFIG_BF52x)
+#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PORTF_INTA ? CONFIG_IRQ_PORTF_INTA : \
+ (irq) == IRQ_PORTG_INTA ? CONFIG_IRQ_PORTG_INTA : \
+ (irq) == IRQ_PORTH_INTA ? CONFIG_IRQ_PORTH_INTA : \
+ -1)
+#elif defined(CONFIG_BF561)
+#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PROG0_INTA ? CONFIG_IRQ_PROG0_INTA : \
+ (irq) == IRQ_PROG1_INTA ? CONFIG_IRQ_PROG1_INTA : \
+ (irq) == IRQ_PROG2_INTA ? CONFIG_IRQ_PROG2_INTA : \
+ -1)
+#define bfin_write_TIMER_DISABLE(val) bfin_write_TMRS8_DISABLE(val)
+#define bfin_write_TIMER_ENABLE(val) bfin_write_TMRS8_ENABLE(val)
+#define bfin_write_TIMER_STATUS(val) bfin_write_TMRS8_STATUS(val)
+#define bfin_read_TIMER_STATUS() bfin_read_TMRS8_STATUS()
+#elif defined(CONFIG_BF54x)
+#define PRIO_GPIODEMUX(irq) ((irq) == IRQ_PINT0 ? CONFIG_IRQ_PINT0 : \
+ (irq) == IRQ_PINT1 ? CONFIG_IRQ_PINT1 : \
+ (irq) == IRQ_PINT2 ? CONFIG_IRQ_PINT2 : \
+ (irq) == IRQ_PINT3 ? CONFIG_IRQ_PINT3 : \
+ -1)
+#define bfin_write_TIMER_DISABLE(val) bfin_write_TIMER_DISABLE0(val)
+#define bfin_write_TIMER_ENABLE(val) bfin_write_TIMER_ENABLE0(val)
+#define bfin_write_TIMER_STATUS(val) bfin_write_TIMER_STATUS0(val)
+#define bfin_read_TIMER_STATUS(val) bfin_read_TIMER_STATUS0(val)
+#else
+# error "no PRIO_GPIODEMUX() for this part"
+#endif
+
+#define __ipipe_root_tick_p(regs) ((regs->ipend & 0x10) != 0)
+
+#else /* !CONFIG_IPIPE */
+
+#define task_hijacked(p) 0
+#define ipipe_trap_notify(t, r) 0
+
+#define __ipipe_stall_root_raw() do { } while (0)
+#define __ipipe_unstall_root_raw() do { } while (0)
+
+#define ipipe_init_irq_threads() do { } while (0)
+#define ipipe_start_irq_thread(irq, desc) 0
+
+#define IRQ_SYSTMR IRQ_CORETMR
+#define IRQ_PRIOTMR IRQ_CORETMR
+
+#define __ipipe_root_tick_p(regs) 1
+
+#endif /* !CONFIG_IPIPE */
+
+#endif /* !__ASM_BLACKFIN_IPIPE_H */
diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h
new file mode 100644
index 000000000000..cb1025aeabcf
--- /dev/null
+++ b/arch/blackfin/include/asm/ipipe_base.h
@@ -0,0 +1,80 @@
+/* -*- linux-c -*-
+ * include/asm-blackfin/_baseipipe.h
+ *
+ * Copyright (C) 2007 Philippe Gerum.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; 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.
+ */
+
+#ifndef __ASM_BLACKFIN_IPIPE_BASE_H
+#define __ASM_BLACKFIN_IPIPE_BASE_H
+
+#ifdef CONFIG_IPIPE
+
+#define IPIPE_NR_XIRQS NR_IRQS
+#define IPIPE_IRQ_ISHIFT 5 /* 2^5 for 32bits arch. */
+
+/* Blackfin-specific, global domain flags */
+#define IPIPE_ROOTLOCK_FLAG 1 /* Lock pipeline for root */
+
+ /* Blackfin traps -- i.e. exception vector numbers */
+#define IPIPE_NR_FAULTS 52 /* We leave a gap after VEC_ILL_RES. */
+/* Pseudo-vectors used for kernel events */
+#define IPIPE_FIRST_EVENT IPIPE_NR_FAULTS
+#define IPIPE_EVENT_SYSCALL (IPIPE_FIRST_EVENT)
+#define IPIPE_EVENT_SCHEDULE (IPIPE_FIRST_EVENT + 1)
+#define IPIPE_EVENT_SIGWAKE (IPIPE_FIRST_EVENT + 2)
+#define IPIPE_EVENT_SETSCHED (IPIPE_FIRST_EVENT + 3)
+#define IPIPE_EVENT_INIT (IPIPE_FIRST_EVENT + 4)
+#define IPIPE_EVENT_EXIT (IPIPE_FIRST_EVENT + 5)
+#define IPIPE_EVENT_CLEANUP (IPIPE_FIRST_EVENT + 6)
+#define IPIPE_LAST_EVENT IPIPE_EVENT_CLEANUP
+#define IPIPE_NR_EVENTS (IPIPE_LAST_EVENT + 1)
+
+#define IPIPE_TIMER_IRQ IRQ_CORETMR
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bitops.h>
+
+extern int test_bit(int nr, const void *addr);
+
+
+extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
+
+static inline void __ipipe_stall_root(void)
+{
+ volatile unsigned long *p = &__ipipe_root_status;
+ set_bit(0, p);
+}
+
+static inline unsigned long __ipipe_test_and_stall_root(void)
+{
+ volatile unsigned long *p = &__ipipe_root_status;
+ return test_and_set_bit(0, p);
+}
+
+static inline unsigned long __ipipe_test_root(void)
+{
+ const unsigned long *p = &__ipipe_root_status;
+ return test_bit(0, p);
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* CONFIG_IPIPE */
+
+#endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */
diff --git a/arch/blackfin/include/asm/irq.h b/arch/blackfin/include/asm/irq.h
index 89f59e18af93..3d977909ce7d 100644
--- a/arch/blackfin/include/asm/irq.h
+++ b/arch/blackfin/include/asm/irq.h
@@ -17,56 +17,272 @@
#ifndef _BFIN_IRQ_H_
#define _BFIN_IRQ_H_
+/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h>*/
#include <mach/irq.h>
-#include <asm/ptrace.h>
-
-/*******************************************************************************
- ***** INTRODUCTION ***********
- * On the Blackfin, the interrupt structure allows remmapping of the hardware
- * levels.
- * - I'm going to assume that the H/W level is going to stay at the default
- * settings. If someone wants to go through and abstart this out, feel free
- * to mod the interrupt numbering scheme.
- * - I'm abstracting the interrupts so that uClinux does not know anything
- * about the H/W levels. If you want to change the H/W AND keep the abstracted
- * levels that uClinux sees, you should be able to do most of it here.
- * - I've left the "abstract" numbering sparce in case someone wants to pull the
- * interrupts apart (just the TX/RX for the various devices)
- *******************************************************************************/
+#include <asm/pda.h>
+#include <asm/processor.h>
-/* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h>*/
+#ifdef CONFIG_SMP
+/* Forward decl needed due to cdef inter dependencies */
+static inline uint32_t __pure bfin_dspid(void);
+# define blackfin_core_id() (bfin_dspid() & 0xff)
+# define bfin_irq_flags cpu_pda[blackfin_core_id()].imask
+#else
+extern unsigned long bfin_irq_flags;
+#endif
-/*
- * Machine specific interrupt sources.
- *
- * Adding an interrupt service routine for a source with this bit
- * set indicates a special machine specific interrupt source.
- * The machine specific files define these sources.
- *
- * The IRQ_MACHSPEC bit is now gone - the only thing it did was to
- * introduce unnecessary overhead.
- *
- * All interrupt handling is actually machine specific so it is better
- * to use function pointers, as used by the Sparc port, and select the
- * interrupt handling functions when initializing the kernel. This way
- * we save some unnecessary overhead at run-time.
- * 01/11/97 - Jes
- */
+#ifdef CONFIG_IPIPE
+
+#include <linux/ipipe_trace.h>
+
+void __ipipe_unstall_root(void);
+
+void __ipipe_restore_root(unsigned long flags);
+
+#ifdef CONFIG_DEBUG_HWERR
+# define __all_masked_irq_flags 0x3f
+# define __save_and_cli_hw(x) \
+ __asm__ __volatile__( \
+ "cli %0;" \
+ "sti %1;" \
+ : "=&d"(x) \
+ : "d" (0x3F) \
+ )
+#else
+# define __all_masked_irq_flags 0x1f
+# define __save_and_cli_hw(x) \
+ __asm__ __volatile__( \
+ "cli %0;" \
+ : "=&d"(x) \
+ )
+#endif
+
+#define irqs_enabled_from_flags_hw(x) ((x) != __all_masked_irq_flags)
+#define raw_irqs_disabled_flags(flags) (!irqs_enabled_from_flags_hw(flags))
+#define local_test_iflag_hw(x) irqs_enabled_from_flags_hw(x)
-extern void ack_bad_irq(unsigned int irq);
+#define local_save_flags(x) \
+ do { \
+ (x) = __ipipe_test_root() ? \
+ __all_masked_irq_flags : bfin_irq_flags; \
+ } while (0)
-static __inline__ int irq_canonicalize(int irq)
+#define local_irq_save(x) \
+ do { \
+ (x) = __ipipe_test_and_stall_root(); \
+ } while (0)
+
+#define local_irq_restore(x) __ipipe_restore_root(x)
+#define local_irq_disable() __ipipe_stall_root()
+#define local_irq_enable() __ipipe_unstall_root()
+#define irqs_disabled() __ipipe_test_root()
+
+#define local_save_flags_hw(x) \
+ __asm__ __volatile__( \
+ "cli %0;" \
+ "sti %0;" \
+ : "=d"(x) \
+ )
+
+#define irqs_disabled_hw() \
+ ({ \
+ unsigned long flags; \
+ local_save_flags_hw(flags); \
+ !irqs_enabled_from_flags_hw(flags); \
+ })
+
+static inline unsigned long raw_mangle_irq_bits(int virt, unsigned long real)
{
- return irq;
+ /* Merge virtual and real interrupt mask bits into a single
+ 32bit word. */
+ return (real & ~(1 << 31)) | ((virt != 0) << 31);
+}
+
+static inline int raw_demangle_irq_bits(unsigned long *x)
+{
+ int virt = (*x & (1 << 31)) != 0;
+ *x &= ~(1L << 31);
+ return virt;
}
-/* count of spurious interrupts */
-/* extern volatile unsigned int num_spurious; */
+#ifdef CONFIG_IPIPE_TRACE_IRQSOFF
+
+#define local_irq_disable_hw() \
+ do { \
+ int _tmp_dummy; \
+ if (!irqs_disabled_hw()) \
+ ipipe_trace_begin(0x80000000); \
+ __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \
+ } while (0)
+
+#define local_irq_enable_hw() \
+ do { \
+ if (irqs_disabled_hw()) \
+ ipipe_trace_end(0x80000000); \
+ __asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags)); \
+ } while (0)
+
+#define local_irq_save_hw(x) \
+ do { \
+ __save_and_cli_hw(x); \
+ if (local_test_iflag_hw(x)) \
+ ipipe_trace_begin(0x80000001); \
+ } while (0)
+
+#define local_irq_restore_hw(x) \
+ do { \
+ if (local_test_iflag_hw(x)) { \
+ ipipe_trace_end(0x80000001); \
+ local_irq_enable_hw_notrace(); \
+ } \
+ } while (0)
+
+#define local_irq_disable_hw_notrace() \
+ do { \
+ int _tmp_dummy; \
+ __asm__ __volatile__ ("cli %0;" : "=d" (_tmp_dummy) : ); \
+ } while (0)
+
+#define local_irq_enable_hw_notrace() \
+ __asm__ __volatile__( \
+ "sti %0;" \
+ : \
+ : "d"(bfin_irq_flags) \
+ )
-#ifndef NO_IRQ
-#define NO_IRQ ((unsigned int)(-1))
+#define local_irq_save_hw_notrace(x) __save_and_cli_hw(x)
+
+#define local_irq_restore_hw_notrace(x) \
+ do { \
+ if (local_test_iflag_hw(x)) \
+ local_irq_enable_hw_notrace(); \
+ } while (0)
+
+#else /* CONFIG_IPIPE_TRACE_IRQSOFF */
+
+#define local_irq_enable_hw() \
+ __asm__ __volatile__( \
+ "sti %0;" \
+ : \
+ : "d"(bfin_irq_flags) \
+ )
+
+#define local_irq_disable_hw() \
+ do { \
+ int _tmp_dummy; \
+ __asm__ __volatile__ ( \
+ "cli %0;" \
+ : "=d" (_tmp_dummy)); \
+ } while (0)
+
+#define local_irq_restore_hw(x) \
+ do { \
+ if (irqs_enabled_from_flags_hw(x)) \
+ local_irq_enable_hw(); \
+ } while (0)
+
+#define local_irq_save_hw(x) __save_and_cli_hw(x)
+
+#define local_irq_disable_hw_notrace() local_irq_disable_hw()
+#define local_irq_enable_hw_notrace() local_irq_enable_hw()
+#define local_irq_save_hw_notrace(x) local_irq_save_hw(x)
+#define local_irq_restore_hw_notrace(x) local_irq_restore_hw(x)
+
+#endif /* CONFIG_IPIPE_TRACE_IRQSOFF */
+
+#else /* !CONFIG_IPIPE */
+
+/*
+ * Interrupt configuring macros.
+ */
+#define local_irq_disable() \
+ do { \
+ int __tmp_dummy; \
+ __asm__ __volatile__( \
+ "cli %0;" \
+ : "=d" (__tmp_dummy) \
+ ); \
+ } while (0)
+
+#define local_irq_enable() \
+ __asm__ __volatile__( \
+ "sti %0;" \
+ : \
+ : "d" (bfin_irq_flags) \
+ )
+
+#ifdef CONFIG_DEBUG_HWERR
+# define __save_and_cli(x) \
+ __asm__ __volatile__( \
+ "cli %0;" \
+ "sti %1;" \
+ : "=&d" (x) \
+ : "d" (0x3F) \
+ )
+#else
+# define __save_and_cli(x) \
+ __asm__ __volatile__( \
+ "cli %0;" \
+ : "=&d" (x) \
+ )
#endif
-#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
+#define local_save_flags(x) \
+ __asm__ __volatile__( \
+ "cli %0;" \
+ "sti %0;" \
+ : "=d" (x) \
+ )
+
+#ifdef CONFIG_DEBUG_HWERR
+#define irqs_enabled_from_flags(x) (((x) & ~0x3f) != 0)
+#else
+#define irqs_enabled_from_flags(x) ((x) != 0x1f)
+#endif
+
+#define local_irq_restore(x) \
+ do { \
+ if (irqs_enabled_from_flags(x)) \
+ local_irq_enable(); \
+ } while (0)
+
+/* For spinlocks etc */
+#define local_irq_save(x) __save_and_cli(x)
+
+#define irqs_disabled() \
+({ \
+ unsigned long flags; \
+ local_save_flags(flags); \
+ !irqs_enabled_from_flags(flags); \
+})
+
+#define local_irq_save_hw(x) local_irq_save(x)
+#define local_irq_restore_hw(x) local_irq_restore(x)
+#define local_irq_enable_hw() local_irq_enable()
+#define local_irq_disable_hw() local_irq_disable()
+#define irqs_disabled_hw() irqs_disabled()
+
+#endif /* !CONFIG_IPIPE */
+
+#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
+# define NOP_PAD_ANOMALY_05000244 "nop; nop;"
+#else
+# define NOP_PAD_ANOMALY_05000244
+#endif
+
+#define idle_with_irq_disabled() \
+ __asm__ __volatile__( \
+ NOP_PAD_ANOMALY_05000244 \
+ ".align 8;" \
+ "sti %0;" \
+ "idle;" \
+ : \
+ : "d" (bfin_irq_flags) \
+ )
+
+static inline int irq_canonicalize(int irq)
+{
+ return irq;
+}
#endif /* _BFIN_IRQ_H_ */
diff --git a/arch/blackfin/include/asm/kgdb.h b/arch/blackfin/include/asm/kgdb.h
index 26ebac6646d8..c8b256d2ea30 100644
--- a/arch/blackfin/include/asm/kgdb.h
+++ b/arch/blackfin/include/asm/kgdb.h
@@ -1,32 +1,8 @@
-/*
- * File: include/asm-blackfin/kgdb.h
- * Based on:
- * Author: Sonic Zhang
- *
- * Created:
- * Description:
- *
- * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
- *
- * Modified:
- * Copyright 2005-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
+/* Blackfin KGDB header
*
- * 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.
+ * Copyright 2005-2009 Analog Devices Inc.
*
- * 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, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Licensed under the GPL-2 or later.
*/
#ifndef __ASM_BLACKFIN_KGDB_H__
@@ -37,17 +13,18 @@
/* gdb locks */
#define KGDB_MAX_NO_CPUS 8
-/************************************************************************/
-/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
-/* at least NUMREGBYTES*2 are needed for register packets */
-/* Longer buffer is needed to list all threads */
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers.
+ * At least NUMREGBYTES*2 are needed for register packets.
+ * Longer buffer is needed to list all threads.
+ */
#define BUFMAX 2048
/*
- * Note that this register image is different from
- * the register image that Linux produces at interrupt time.
- *
- * Linux's register image is defined by struct pt_regs in ptrace.h.
+ * Note that this register image is different from
+ * the register image that Linux produces at interrupt time.
+ *
+ * Linux's register image is defined by struct pt_regs in ptrace.h.
*/
enum regnames {
/* Core Registers */
@@ -104,14 +81,14 @@ enum regnames {
BFIN_RETX,
BFIN_RETN,
BFIN_RETE,
-
+
/* Pseudo Registers */
BFIN_PC,
BFIN_CC,
BFIN_EXTRA1, /* Address of .text section. */
BFIN_EXTRA2, /* Address of .data section. */
BFIN_EXTRA3, /* Address of .bss section. */
- BFIN_FDPIC_EXEC,
+ BFIN_FDPIC_EXEC,
BFIN_FDPIC_INTERP,
/* MMRs */
@@ -126,7 +103,7 @@ enum regnames {
static inline void arch_kgdb_breakpoint(void)
{
- asm(" EXCPT 2;");
+ asm("EXCPT 2;");
}
#define BREAK_INSTR_SIZE 2
#define CACHE_FLUSH_IS_SAFE 1
diff --git a/arch/blackfin/include/asm/l1layout.h b/arch/blackfin/include/asm/l1layout.h
index c13ded777828..79dbefaa5bef 100644
--- a/arch/blackfin/include/asm/l1layout.h
+++ b/arch/blackfin/include/asm/l1layout.h
@@ -8,6 +8,7 @@
#include <asm/blackfin.h>
+#ifndef CONFIG_SMP
#ifndef __ASSEMBLY__
/* Data that is "mapped" into the process VM at the start of the L1 scratch
@@ -24,8 +25,10 @@ struct l1_scratch_task_info
};
/* A pointer to the structure in memory. */
-#define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)L1_SCRATCH_START)
+#define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)\
+ get_l1_scratch_start())
#endif
+#endif
#endif
diff --git a/arch/blackfin/mach-bf527/include/mach/mem_init.h b/arch/blackfin/include/asm/mem_init.h
index cbe03f4a5698..61f7487fbf12 100644
--- a/arch/blackfin/mach-bf527/include/mach/mem_init.h
+++ b/arch/blackfin/include/asm/mem_init.h
@@ -1,35 +1,20 @@
/*
- * File: include/asm-blackfin/mach-bf527/mem_init.h
- * Based on:
- * Author:
+ * arch/blackfin/include/asm/mem_init.h - reprogram clocks / memory
*
- * Created:
- * Description:
+ * Copyright 2004-2008 Analog Devices Inc.
*
- * Rev:
- *
- * Modified:
- * Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
*/
-#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_MT48LC16M8A2TG_75 || CONFIG_MEM_GENERIC_BOARD || CONFIG_MEM_MT48LC32M8A2_75 || CONFIG_MEM_MT48LC32M16A2TG_75)
+#if defined(EBIU_SDGCTL)
+#if defined(CONFIG_MEM_MT48LC16M16A2TG_75) || \
+ defined(CONFIG_MEM_MT48LC64M4A2FB_7E) || \
+ defined(CONFIG_MEM_MT48LC16M8A2TG_75) || \
+ defined(CONFIG_MEM_GENERIC_BOARD) || \
+ defined(CONFIG_MEM_MT48LC32M8A2_75) || \
+ defined(CONFIG_MEM_MT48LC8M32B2B5_7) || \
+ defined(CONFIG_MEM_MT48LC32M16A2TG_75) || \
+ defined(CONFIG_MEM_MT48LC32M8A2_75)
#if (CONFIG_SCLK_HZ > 119402985)
#define SDRAM_tRP TRP_2
#define SDRAM_tRP_num 2
@@ -104,53 +89,114 @@
#endif
#endif
-#if (CONFIG_MEM_MT48LC16M16A2TG_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC16M8A2TG_75)
+#if defined(CONFIG_MEM_MT48LC16M8A2TG_75) || \
+ defined(CONFIG_MEM_MT48LC8M32B2B5_7)
/*SDRAM INFORMATION: */
#define SDRAM_Tref 64 /* Refresh period in milliseconds */
#define SDRAM_NRA 4096 /* Number of row addresses in SDRAM */
#define SDRAM_CL CL_3
#endif
-#if (CONFIG_MEM_MT48LC32M8A2_75)
+#if defined(CONFIG_MEM_MT48LC32M8A2_75) || \
+ defined(CONFIG_MEM_MT48LC64M4A2FB_7E) || \
+ defined(CONFIG_MEM_GENERIC_BOARD) || \
+ defined(CONFIG_MEM_MT48LC32M16A2TG_75) || \
+ defined(CONFIG_MEM_MT48LC16M16A2TG_75) || \
+ defined(CONFIG_MEM_MT48LC32M8A2_75)
/*SDRAM INFORMATION: */
#define SDRAM_Tref 64 /* Refresh period in milliseconds */
#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
#define SDRAM_CL CL_3
#endif
-#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
+
+#ifdef CONFIG_BFIN_KERNEL_CLOCK_MEMINIT_CALC
+/* Equation from section 17 (p17-46) of BF533 HRM */
+#define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
+
+/* Enable SCLK Out */
+#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
+#else
+#define mem_SDRRC CONFIG_MEM_SDRRC
+#define mem_SDGCTL CONFIG_MEM_SDGCTL
+#endif
#endif
-#if (CONFIG_MEM_GENERIC_BOARD)
- /*SDRAM INFORMATION: Modify this for your board */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
+
+#if defined(EBIU_DDRCTL0)
+#define MIN_DDR_SCLK(x) (x*(CONFIG_SCLK_HZ/1000/1000)/1000 + 1)
+#define MAX_DDR_SCLK(x) (x*(CONFIG_SCLK_HZ/1000/1000)/1000)
+#define DDR_CLK_HZ(x) (1000*1000*1000/x)
+
+#if defined(CONFIG_MEM_MT46V32M16_6T)
+#define DDR_SIZE DEVSZ_512
+#define DDR_WIDTH DEVWD_16
+#define DDR_MAX_tCK 13
+
+#define DDR_tRC DDR_TRC(MIN_DDR_SCLK(60))
+#define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(42))
+#define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15))
+#define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(72))
+#define DDR_tREFI DDR_TREFI(MAX_DDR_SCLK(7800))
+
+#define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15))
+#define DDR_tWTR DDR_TWTR(1)
+#define DDR_tMRD DDR_TMRD(MIN_DDR_SCLK(12))
+#define DDR_tWR DDR_TWR(MIN_DDR_SCLK(15))
#endif
-#if (CONFIG_MEM_MT48LC32M16A2TG_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
+#if defined(CONFIG_MEM_MT46V32M16_5B)
+#define DDR_SIZE DEVSZ_512
+#define DDR_WIDTH DEVWD_16
+#define DDR_MAX_tCK 13
+
+#define DDR_tRC DDR_TRC(MIN_DDR_SCLK(55))
+#define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(40))
+#define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15))
+#define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(70))
+#define DDR_tREFI DDR_TREFI(MAX_DDR_SCLK(7800))
+
+#define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15))
+#define DDR_tWTR DDR_TWTR(2)
+#define DDR_tMRD DDR_TMRD(MIN_DDR_SCLK(10))
+#define DDR_tWR DDR_TWR(MIN_DDR_SCLK(15))
#endif
-/* Equation from section 17 (p17-46) of BF533 HRM */
-#define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
+#if defined(CONFIG_MEM_GENERIC_BOARD)
+#define DDR_SIZE DEVSZ_512
+#define DDR_WIDTH DEVWD_16
+#define DDR_MAX_tCK 13
-/* Enable SCLK Out */
-#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
+#define DDR_tRCD DDR_TRCD(3)
+#define DDR_tWTR DDR_TWTR(2)
+#define DDR_tWR DDR_TWR(2)
+#define DDR_tMRD DDR_TMRD(2)
+#define DDR_tRP DDR_TRP(3)
+#define DDR_tRAS DDR_TRAS(7)
+#define DDR_tRC DDR_TRC(10)
+#define DDR_tRFC DDR_TRFC(12)
+#define DDR_tREFI DDR_TREFI(1288)
+#endif
+
+#if (CONFIG_SCLK_HZ < DDR_CLK_HZ(DDR_MAX_tCK))
+# error "CONFIG_SCLK_HZ is too small (<DDR_CLK_HZ(DDR_MAX_tCK) Hz)."
+#elif(CONFIG_SCLK_HZ <= 133333333)
+# define DDR_CL CL_2
+#else
+# error "CONFIG_SCLK_HZ is too large (>133333333 Hz)."
+#endif
+
+#ifdef CONFIG_BFIN_KERNEL_CLOCK_MEMINIT_CALC
+#define mem_DDRCTL0 (DDR_tRP | DDR_tRAS | DDR_tRC | DDR_tRFC | DDR_tREFI)
+#define mem_DDRCTL1 (DDR_DATWIDTH | EXTBANK_1 | DDR_SIZE | DDR_WIDTH | DDR_tWTR \
+ | DDR_tMRD | DDR_tWR | DDR_tRCD)
+#define mem_DDRCTL2 DDR_CL
+#else
+#define mem_DDRCTL0 CONFIG_MEM_DDRCTL0
+#define mem_DDRCTL1 CONFIG_MEM_DDRCTL1
+#define mem_DDRCTL2 CONFIG_MEM_DDRCTL2
+#endif
+#endif
#if defined CONFIG_CLKIN_HALF
#define CLKIN_HALF 1
@@ -165,6 +211,13 @@
#endif
/***************************************Currently Not Being Used *********************************/
+
+#if defined(CONFIG_FLASH_SPEED_BWAT) && \
+defined(CONFIG_FLASH_SPEED_BRAT) && \
+defined(CONFIG_FLASH_SPEED_BHT) && \
+defined(CONFIG_FLASH_SPEED_BST) && \
+defined(CONFIG_FLASH_SPEED_BTT)
+
#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ))
@@ -308,3 +361,4 @@
#define flash_EBIU_AMBCTL0 \
(flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
+#endif
diff --git a/arch/blackfin/include/asm/mem_map.h b/arch/blackfin/include/asm/mem_map.h
index 88d04a707708..e92b31051bb7 100644
--- a/arch/blackfin/include/asm/mem_map.h
+++ b/arch/blackfin/include/asm/mem_map.h
@@ -9,4 +9,79 @@
#include <mach/mem_map.h>
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_SMP
+static inline ulong get_l1_scratch_start_cpu(int cpu)
+{
+ return (cpu) ? COREB_L1_SCRATCH_START : COREA_L1_SCRATCH_START;
+}
+static inline ulong get_l1_code_start_cpu(int cpu)
+{
+ return (cpu) ? COREB_L1_CODE_START : COREA_L1_CODE_START;
+}
+static inline ulong get_l1_data_a_start_cpu(int cpu)
+{
+ return (cpu) ? COREB_L1_DATA_A_START : COREA_L1_DATA_A_START;
+}
+static inline ulong get_l1_data_b_start_cpu(int cpu)
+{
+ return (cpu) ? COREB_L1_DATA_B_START : COREA_L1_DATA_B_START;
+}
+
+static inline ulong get_l1_scratch_start(void)
+{
+ return get_l1_scratch_start_cpu(blackfin_core_id());
+}
+static inline ulong get_l1_code_start(void)
+{
+ return get_l1_code_start_cpu(blackfin_core_id());
+}
+static inline ulong get_l1_data_a_start(void)
+{
+ return get_l1_data_a_start_cpu(blackfin_core_id());
+}
+static inline ulong get_l1_data_b_start(void)
+{
+ return get_l1_data_b_start_cpu(blackfin_core_id());
+}
+
+#else /* !CONFIG_SMP */
+
+static inline ulong get_l1_scratch_start_cpu(int cpu)
+{
+ return L1_SCRATCH_START;
+}
+static inline ulong get_l1_code_start_cpu(int cpu)
+{
+ return L1_CODE_START;
+}
+static inline ulong get_l1_data_a_start_cpu(int cpu)
+{
+ return L1_DATA_A_START;
+}
+static inline ulong get_l1_data_b_start_cpu(int cpu)
+{
+ return L1_DATA_B_START;
+}
+static inline ulong get_l1_scratch_start(void)
+{
+ return get_l1_scratch_start_cpu(0);
+}
+static inline ulong get_l1_code_start(void)
+{
+ return get_l1_code_start_cpu(0);
+}
+static inline ulong get_l1_data_a_start(void)
+{
+ return get_l1_data_a_start_cpu(0);
+}
+static inline ulong get_l1_data_b_start(void)
+{
+ return get_l1_data_b_start_cpu(0);
+}
+
+#endif /* CONFIG_SMP */
+#endif /* __ASSEMBLY__ */
+
#endif /* _MEM_MAP_H_ */
diff --git a/arch/blackfin/include/asm/mmu.h b/arch/blackfin/include/asm/mmu.h
index 757e43906ed4..dbfd686360e6 100644
--- a/arch/blackfin/include/asm/mmu.h
+++ b/arch/blackfin/include/asm/mmu.h
@@ -10,7 +10,6 @@ struct sram_list_struct {
};
typedef struct {
- struct vm_list_struct *vmlist;
unsigned long end_brk;
unsigned long stack_start;
diff --git a/arch/blackfin/include/asm/mmu_context.h b/arch/blackfin/include/asm/mmu_context.h
index 35593dda2a4d..944e29faae48 100644
--- a/arch/blackfin/include/asm/mmu_context.h
+++ b/arch/blackfin/include/asm/mmu_context.h
@@ -37,6 +37,10 @@
#include <asm/pgalloc.h>
#include <asm/cplbinit.h>
+/* Note: L1 stacks are CPU-private things, so we bluntly disable this
+ feature in SMP mode, and use the per-CPU scratch SRAM bank only to
+ store the PDA instead. */
+
extern void *current_l1_stack_save;
extern int nr_l1stack_tasks;
extern void *l1_stack_base;
@@ -88,12 +92,15 @@ activate_l1stack(struct mm_struct *mm, unsigned long sp_base)
static inline void switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
struct task_struct *tsk)
{
+#ifdef CONFIG_MPU
+ unsigned int cpu = smp_processor_id();
+#endif
if (prev_mm == next_mm)
return;
#ifdef CONFIG_MPU
- if (prev_mm->context.page_rwx_mask == current_rwx_mask) {
- flush_switched_cplbs();
- set_mask_dcplbs(next_mm->context.page_rwx_mask);
+ if (prev_mm->context.page_rwx_mask == current_rwx_mask[cpu]) {
+ flush_switched_cplbs(cpu);
+ set_mask_dcplbs(next_mm->context.page_rwx_mask, cpu);
}
#endif
@@ -138,9 +145,10 @@ static inline void protect_page(struct mm_struct *mm, unsigned long addr,
static inline void update_protections(struct mm_struct *mm)
{
- if (mm->context.page_rwx_mask == current_rwx_mask) {
- flush_switched_cplbs();
- set_mask_dcplbs(mm->context.page_rwx_mask);
+ unsigned int cpu = smp_processor_id();
+ if (mm->context.page_rwx_mask == current_rwx_mask[cpu]) {
+ flush_switched_cplbs(cpu);
+ set_mask_dcplbs(mm->context.page_rwx_mask, cpu);
}
}
#endif
@@ -165,6 +173,9 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
static inline void destroy_context(struct mm_struct *mm)
{
struct sram_list_struct *tmp;
+#ifdef CONFIG_MPU
+ unsigned int cpu = smp_processor_id();
+#endif
#ifdef CONFIG_APP_STACK_L1
if (current_l1_stack_save == mm->context.l1_stack_save)
@@ -179,8 +190,8 @@ static inline void destroy_context(struct mm_struct *mm)
kfree(tmp);
}
#ifdef CONFIG_MPU
- if (current_rwx_mask == mm->context.page_rwx_mask)
- current_rwx_mask = NULL;
+ if (current_rwx_mask[cpu] == mm->context.page_rwx_mask)
+ current_rwx_mask[cpu] = NULL;
free_pages((unsigned long)mm->context.page_rwx_mask, page_mask_order);
#endif
}
diff --git a/arch/blackfin/include/asm/mutex-dec.h b/arch/blackfin/include/asm/mutex-dec.h
new file mode 100644
index 000000000000..0134151656af
--- /dev/null
+++ b/arch/blackfin/include/asm/mutex-dec.h
@@ -0,0 +1,112 @@
+/*
+ * include/asm-generic/mutex-dec.h
+ *
+ * Generic implementation of the mutex fastpath, based on atomic
+ * decrement/increment.
+ */
+#ifndef _ASM_GENERIC_MUTEX_DEC_H
+#define _ASM_GENERIC_MUTEX_DEC_H
+
+/**
+ * __mutex_fastpath_lock - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function MUST leave the value lower than
+ * 1 even when the "1" assertion wasn't true.
+ */
+static inline void
+__mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ fail_fn(count);
+ else
+ smp_mb();
+}
+
+/**
+ * __mutex_fastpath_lock_retval - try to take the lock by moving the count
+ * from 1 to a 0 value
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns.
+ */
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ return fail_fn(count);
+ else {
+ smp_mb();
+ return 0;
+ }
+}
+
+/**
+ * __mutex_fastpath_unlock - try to promote the count from 0 to 1
+ * @count: pointer of type atomic_t
+ * @fail_fn: function to call if the original value was not 0
+ *
+ * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
+ * In the failure case, this function is allowed to either set the value to
+ * 1, or to set it to a value lower than 1.
+ *
+ * If the implementation sets it to a value of lower than 1, then the
+ * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
+ * to return 0 otherwise.
+ */
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *))
+{
+ smp_mb();
+ if (unlikely(atomic_inc_return(count) <= 0))
+ fail_fn(count);
+}
+
+#define __mutex_slowpath_needs_to_unlock() 1
+
+/**
+ * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
+ *
+ * @count: pointer of type atomic_t
+ * @fail_fn: fallback function
+ *
+ * Change the count from 1 to a value lower than 1, and return 0 (failure)
+ * if it wasn't 1 originally, or return 1 (success) otherwise. This function
+ * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
+ * Additionally, if the value was < 0 originally, this function must not leave
+ * it to 0 on failure.
+ *
+ * If the architecture has no effective trylock variant, it should call the
+ * <fail_fn> spinlock-based trylock variant unconditionally.
+ */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ /*
+ * We have two variants here. The cmpxchg based one is the best one
+ * because it never induce a false contention state. It is included
+ * here because architectures using the inc/dec algorithms over the
+ * xchg ones are much more likely to support cmpxchg natively.
+ *
+ * If not we fall back to the spinlock based variant - that is
+ * just as efficient (and simpler) as a 'destructive' probing of
+ * the mutex state would be.
+ */
+#ifdef __HAVE_ARCH_CMPXCHG
+ if (likely(atomic_cmpxchg(count, 1, 0) == 1)) {
+ smp_mb();
+ return 1;
+ }
+ return 0;
+#else
+ return fail_fn(count);
+#endif
+}
+
+#endif
diff --git a/arch/blackfin/include/asm/mutex.h b/arch/blackfin/include/asm/mutex.h
index 458c1f7fbc18..5d399256bf06 100644
--- a/arch/blackfin/include/asm/mutex.h
+++ b/arch/blackfin/include/asm/mutex.h
@@ -6,4 +6,67 @@
* implementation. (see asm-generic/mutex-xchg.h for details)
*/
+#ifndef _ASM_MUTEX_H
+#define _ASM_MUTEX_H
+
+#ifndef CONFIG_SMP
#include <asm-generic/mutex-dec.h>
+#else
+
+static inline void
+__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ fail_fn(count);
+ else
+ smp_mb();
+}
+
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ if (unlikely(atomic_dec_return(count) < 0))
+ return fail_fn(count);
+ else {
+ smp_mb();
+ return 0;
+ }
+}
+
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
+{
+ smp_mb();
+ if (unlikely(atomic_inc_return(count) <= 0))
+ fail_fn(count);
+}
+
+#define __mutex_slowpath_needs_to_unlock() 1
+
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+ /*
+ * We have two variants here. The cmpxchg based one is the best one
+ * because it never induce a false contention state. It is included
+ * here because architectures using the inc/dec algorithms over the
+ * xchg ones are much more likely to support cmpxchg natively.
+ *
+ * If not we fall back to the spinlock based variant - that is
+ * just as efficient (and simpler) as a 'destructive' probing of
+ * the mutex state would be.
+ */
+#ifdef __HAVE_ARCH_CMPXCHG
+ if (likely(atomic_cmpxchg(count, 1, 0) == 1)) {
+ smp_mb();
+ return 1;
+ }
+ return 0;
+#else
+ return fail_fn(count);
+#endif
+}
+
+#endif
+
+#endif
diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h
new file mode 100644
index 000000000000..a67142740df0
--- /dev/null
+++ b/arch/blackfin/include/asm/pda.h
@@ -0,0 +1,71 @@
+/*
+ * File: arch/blackfin/include/asm/pda.h
+ * Author: Philippe Gerum <rpm@xenomai.org>
+ *
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _ASM_BLACKFIN_PDA_H
+#define _ASM_BLACKFIN_PDA_H
+
+#include <mach/anomaly.h>
+
+#ifndef __ASSEMBLY__
+
+struct blackfin_pda { /* Per-processor Data Area */
+ struct blackfin_pda *next;
+
+ unsigned long syscfg;
+#ifdef CONFIG_SMP
+ unsigned long imask; /* Current IMASK value */
+#endif
+
+ unsigned long *ipdt; /* Start of switchable I-CPLB table */
+ unsigned long *ipdt_swapcount; /* Number of swaps in ipdt */
+ unsigned long *dpdt; /* Start of switchable D-CPLB table */
+ unsigned long *dpdt_swapcount; /* Number of swaps in dpdt */
+
+ /*
+ * Single instructions can have multiple faults, which
+ * need to be handled by traps.c, in irq5. We store
+ * the exception cause to ensure we don't miss a
+ * double fault condition
+ */
+ unsigned long ex_iptr;
+ unsigned long ex_optr;
+ unsigned long ex_buf[4];
+ unsigned long ex_imask; /* Saved imask from exception */
+ unsigned long *ex_stack; /* Exception stack space */
+
+#ifdef ANOMALY_05000261
+ unsigned long last_cplb_fault_retx;
+#endif
+ unsigned long dcplb_fault_addr;
+ unsigned long icplb_fault_addr;
+ unsigned long retx;
+ unsigned long seqstat;
+ unsigned int __nmi_count; /* number of times NMI asserted on this CPU */
+};
+
+extern struct blackfin_pda cpu_pda[];
+
+void reserve_pda(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_BLACKFIN_PDA_H */
diff --git a/arch/blackfin/include/asm/percpu.h b/arch/blackfin/include/asm/percpu.h
index 78dd61f6b39f..797c0c165069 100644
--- a/arch/blackfin/include/asm/percpu.h
+++ b/arch/blackfin/include/asm/percpu.h
@@ -3,4 +3,14 @@
#include <asm-generic/percpu.h>
-#endif /* __ARCH_BLACKFIN_PERCPU__ */
+#ifdef CONFIG_MODULES
+#define PERCPU_MODULE_RESERVE 8192
+#else
+#define PERCPU_MODULE_RESERVE 0
+#endif
+
+#define PERCPU_ENOUGH_ROOM \
+ (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \
+ PERCPU_MODULE_RESERVE)
+
+#endif /* __ARCH_BLACKFIN_PERCPU__ */
diff --git a/arch/blackfin/include/asm/pgtable.h b/arch/blackfin/include/asm/pgtable.h
index f11684e4ade7..783c8f7f8f8c 100644
--- a/arch/blackfin/include/asm/pgtable.h
+++ b/arch/blackfin/include/asm/pgtable.h
@@ -29,6 +29,7 @@ typedef pte_t *pte_addr_t;
#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
+#define pgprot_noncached(prot) (prot)
extern void paging_init(void);
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index e3e9b41fa8db..0eece23b41c7 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -24,6 +24,14 @@ static inline void wrusp(unsigned long usp)
__asm__ __volatile__("usp = %0;\n\t"::"da"(usp));
}
+static inline unsigned long __get_SP(void)
+{
+ unsigned long sp;
+
+ __asm__ __volatile__("%0 = sp;\n\t" : "=da"(sp));
+ return sp;
+}
+
/*
* User space process size: 1st byte beyond user address space.
* Fairly meaningless on nommu. Parts of user programs can be scattered
@@ -57,6 +65,7 @@ struct thread_struct {
* pass the data segment into user programs if it exists,
* it can't hurt anything as far as I can tell
*/
+#ifndef CONFIG_SMP
#define start_thread(_regs, _pc, _usp) \
do { \
set_fs(USER_DS); \
@@ -70,6 +79,16 @@ do { \
sizeof(*L1_SCRATCH_TASK_INFO)); \
wrusp(_usp); \
} while(0)
+#else
+#define start_thread(_regs, _pc, _usp) \
+do { \
+ set_fs(USER_DS); \
+ (_regs)->pc = (_pc); \
+ if (current->mm) \
+ (_regs)->p5 = current->mm->start_data; \
+ wrusp(_usp); \
+} while (0)
+#endif
/* Forward declaration, a strange C thing */
struct task_struct;
@@ -106,7 +125,8 @@ unsigned long get_wchan(struct task_struct *p);
eip; })
#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
-#define cpu_relax() barrier()
+#define cpu_relax() smp_mb()
+
/* Get the Silicon Revision of the chip */
static inline uint32_t __pure bfin_revid(void)
@@ -137,7 +157,11 @@ static inline uint32_t __pure bfin_revid(void)
static inline uint16_t __pure bfin_cpuid(void)
{
return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12;
+}
+static inline uint32_t __pure bfin_dspid(void)
+{
+ return bfin_read_DSPID();
}
static inline uint32_t __pure bfin_compiled_revid(void)
@@ -154,6 +178,8 @@ static inline uint32_t __pure bfin_compiled_revid(void)
return 4;
#elif defined(CONFIG_BF_REV_0_5)
return 5;
+#elif defined(CONFIG_BF_REV_0_6)
+ return 6;
#elif defined(CONFIG_BF_REV_ANY)
return 0xffff;
#else
diff --git a/arch/blackfin/include/asm/reboot.h b/arch/blackfin/include/asm/reboot.h
index 6d448b5f5985..ae1e36329bec 100644
--- a/arch/blackfin/include/asm/reboot.h
+++ b/arch/blackfin/include/asm/reboot.h
@@ -1,7 +1,7 @@
/*
- * include/asm-blackfin/reboot.h - shutdown/reboot header
+ * reboot.h - shutdown/reboot header
*
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2008 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
@@ -15,6 +15,6 @@ extern void native_machine_halt(void);
extern void native_machine_power_off(void);
/* common reboot workarounds */
-extern void bfin_gpio_reset_spi0_ssel1(void);
+extern void bfin_reset_boot_spi_cs(unsigned short pin);
#endif
diff --git a/arch/blackfin/include/asm/rwlock.h b/arch/blackfin/include/asm/rwlock.h
new file mode 100644
index 000000000000..4a724b378971
--- /dev/null
+++ b/arch/blackfin/include/asm/rwlock.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_BLACKFIN_RWLOCK_H
+#define _ASM_BLACKFIN_RWLOCK_H
+
+#define RW_LOCK_BIAS 0x01000000
+
+#endif
diff --git a/arch/blackfin/include/asm/serial.h b/arch/blackfin/include/asm/serial.h
index 994dd869558c..3a47606c858b 100644
--- a/arch/blackfin/include/asm/serial.h
+++ b/arch/blackfin/include/asm/serial.h
@@ -3,3 +3,4 @@
*/
#define SERIAL_EXTRA_IRQ_FLAGS IRQF_TRIGGER_HIGH
+#define BASE_BAUD (1843200 / 16)
diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h
new file mode 100644
index 000000000000..118deeeae7c0
--- /dev/null
+++ b/arch/blackfin/include/asm/smp.h
@@ -0,0 +1,44 @@
+/*
+ * File: arch/blackfin/include/asm/smp.h
+ * Author: Philippe Gerum <rpm@xenomai.org>
+ *
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __ASM_BLACKFIN_SMP_H
+#define __ASM_BLACKFIN_SMP_H
+
+#include <linux/kernel.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/cache.h>
+#include <asm/blackfin.h>
+#include <mach/smp.h>
+
+#define raw_smp_processor_id() blackfin_core_id()
+
+extern char coreb_trampoline_start, coreb_trampoline_end;
+
+struct corelock_slot {
+ int lock;
+};
+
+void smp_icache_flush_range_others(unsigned long start,
+ unsigned long end);
+
+#endif /* !__ASM_BLACKFIN_SMP_H */
diff --git a/arch/blackfin/include/asm/spinlock.h b/arch/blackfin/include/asm/spinlock.h
index 64e908a50646..0249ac319476 100644
--- a/arch/blackfin/include/asm/spinlock.h
+++ b/arch/blackfin/include/asm/spinlock.h
@@ -1,6 +1,89 @@
#ifndef __BFIN_SPINLOCK_H
#define __BFIN_SPINLOCK_H
-#error blackfin architecture does not support SMP spin lock yet
+#include <asm/atomic.h>
-#endif
+asmlinkage int __raw_spin_is_locked_asm(volatile int *ptr);
+asmlinkage void __raw_spin_lock_asm(volatile int *ptr);
+asmlinkage int __raw_spin_trylock_asm(volatile int *ptr);
+asmlinkage void __raw_spin_unlock_asm(volatile int *ptr);
+asmlinkage void __raw_read_lock_asm(volatile int *ptr);
+asmlinkage int __raw_read_trylock_asm(volatile int *ptr);
+asmlinkage void __raw_read_unlock_asm(volatile int *ptr);
+asmlinkage void __raw_write_lock_asm(volatile int *ptr);
+asmlinkage int __raw_write_trylock_asm(volatile int *ptr);
+asmlinkage void __raw_write_unlock_asm(volatile int *ptr);
+
+static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+{
+ return __raw_spin_is_locked_asm(&lock->lock);
+}
+
+static inline void __raw_spin_lock(raw_spinlock_t *lock)
+{
+ __raw_spin_lock_asm(&lock->lock);
+}
+
+#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
+
+static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+{
+ return __raw_spin_trylock_asm(&lock->lock);
+}
+
+static inline void __raw_spin_unlock(raw_spinlock_t *lock)
+{
+ __raw_spin_unlock_asm(&lock->lock);
+}
+
+static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
+{
+ while (__raw_spin_is_locked(lock))
+ cpu_relax();
+}
+
+static inline int __raw_read_can_lock(raw_rwlock_t *rw)
+{
+ return __raw_uncached_fetch_asm(&rw->lock) > 0;
+}
+
+static inline int __raw_write_can_lock(raw_rwlock_t *rw)
+{
+ return __raw_uncached_fetch_asm(&rw->lock) == RW_LOCK_BIAS;
+}
+
+static inline void __raw_read_lock(raw_rwlock_t *rw)
+{
+ __raw_read_lock_asm(&rw->lock);
+}
+
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
+{
+ return __raw_read_trylock_asm(&rw->lock);
+}
+
+static inline void __raw_read_unlock(raw_rwlock_t *rw)
+{
+ __raw_read_unlock_asm(&rw->lock);
+}
+
+static inline void __raw_write_lock(raw_rwlock_t *rw)
+{
+ __raw_write_lock_asm(&rw->lock);
+}
+
+static inline int __raw_write_trylock(raw_rwlock_t *rw)
+{
+ return __raw_write_trylock_asm(&rw->lock);
+}
+
+static inline void __raw_write_unlock(raw_rwlock_t *rw)
+{
+ __raw_write_unlock_asm(&rw->lock);
+}
+
+#define _raw_spin_relax(lock) cpu_relax()
+#define _raw_read_relax(lock) cpu_relax()
+#define _raw_write_relax(lock) cpu_relax()
+
+#endif /* !__BFIN_SPINLOCK_H */
diff --git a/arch/blackfin/include/asm/spinlock_types.h b/arch/blackfin/include/asm/spinlock_types.h
new file mode 100644
index 000000000000..b1e3c4c7b382
--- /dev/null
+++ b/arch/blackfin/include/asm/spinlock_types.h
@@ -0,0 +1,22 @@
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+#include <asm/rwlock.h>
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_spinlock_t;
+
+#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
+
+typedef struct {
+ volatile unsigned int lock;
+} raw_rwlock_t;
+
+#define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS }
+
+#endif
diff --git a/arch/blackfin/include/asm/swab.h b/arch/blackfin/include/asm/swab.h
new file mode 100644
index 000000000000..69a051b612bd
--- /dev/null
+++ b/arch/blackfin/include/asm/swab.h
@@ -0,0 +1,48 @@
+#ifndef _BLACKFIN_SWAB_H
+#define _BLACKFIN_SWAB_H
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __GNUC__
+
+static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
+{
+ __u32 tmp;
+ __asm__("%1 = %0 >> 8 (V);\n\t"
+ "%0 = %0 << 8 (V);\n\t"
+ "%0 = %0 | %1;\n\t"
+ : "+d"(xx), "=&d"(tmp));
+ return xx;
+}
+#define __arch_swahb32 __arch_swahb32
+
+static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
+{
+ __u32 rv;
+ __asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
+ return rv;
+}
+#define __arch_swahw32 __arch_swahw32
+
+static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 xx)
+{
+ return __arch_swahb32(__arch_swahw32(xx));
+}
+#define __arch_swab32 __arch_swab32
+
+static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 xx)
+{
+ __u32 xw = xx;
+ __asm__("%0 <<= 8;\n %0.L = %0.L + %0.H (NS);\n": "+d"(xw));
+ return (__u16)xw;
+}
+#define __arch_swab16 __arch_swab16
+
+#endif /* __GNUC__ */
+
+#endif /* _BLACKFIN_SWAB_H */
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h
index 8f1627d8bf09..a4c8254bec55 100644
--- a/arch/blackfin/include/asm/system.h
+++ b/arch/blackfin/include/asm/system.h
@@ -37,114 +37,98 @@
#include <linux/linkage.h>
#include <linux/compiler.h>
#include <mach/anomaly.h>
+#include <asm/pda.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
/*
- * Interrupt configuring macros.
+ * Force strict CPU ordering.
*/
+#define nop() __asm__ __volatile__ ("nop;\n\t" : : )
+#define mb() __asm__ __volatile__ ("" : : : "memory")
+#define rmb() __asm__ __volatile__ ("" : : : "memory")
+#define wmb() __asm__ __volatile__ ("" : : : "memory")
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+#define read_barrier_depends() do { } while(0)
-extern unsigned long irq_flags;
-
-#define local_irq_enable() \
- __asm__ __volatile__( \
- "sti %0;" \
- : \
- : "d" (irq_flags) \
- )
-
-#define local_irq_disable() \
- do { \
- int __tmp_dummy; \
- __asm__ __volatile__( \
- "cli %0;" \
- : "=d" (__tmp_dummy) \
- ); \
- } while (0)
-
-#if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
-# define NOP_PAD_ANOMALY_05000244 "nop; nop;"
-#else
-# define NOP_PAD_ANOMALY_05000244
-#endif
-
-#define idle_with_irq_disabled() \
- __asm__ __volatile__( \
- NOP_PAD_ANOMALY_05000244 \
- ".align 8;" \
- "sti %0;" \
- "idle;" \
- : \
- : "d" (irq_flags) \
- )
-
-#ifdef CONFIG_DEBUG_HWERR
-# define __save_and_cli(x) \
- __asm__ __volatile__( \
- "cli %0;" \
- "sti %1;" \
- : "=&d" (x) \
- : "d" (0x3F) \
- )
-#else
-# define __save_and_cli(x) \
- __asm__ __volatile__( \
- "cli %0;" \
- : "=&d" (x) \
- )
-#endif
-
-#define local_save_flags(x) \
- __asm__ __volatile__( \
- "cli %0;" \
- "sti %0;" \
- : "=d" (x) \
- )
+#ifdef CONFIG_SMP
+asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value);
+asmlinkage unsigned long __raw_xchg_2_asm(volatile void *ptr, unsigned long value);
+asmlinkage unsigned long __raw_xchg_4_asm(volatile void *ptr, unsigned long value);
+asmlinkage unsigned long __raw_cmpxchg_1_asm(volatile void *ptr,
+ unsigned long new, unsigned long old);
+asmlinkage unsigned long __raw_cmpxchg_2_asm(volatile void *ptr,
+ unsigned long new, unsigned long old);
+asmlinkage unsigned long __raw_cmpxchg_4_asm(volatile void *ptr,
+ unsigned long new, unsigned long old);
+
+#ifdef __ARCH_SYNC_CORE_DCACHE
+# define smp_mb() do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0)
+# define smp_rmb() do { barrier(); smp_check_barrier(); } while (0)
+# define smp_wmb() do { barrier(); smp_mark_barrier(); } while (0)
+#define smp_read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0)
-#ifdef CONFIG_DEBUG_HWERR
-#define irqs_enabled_from_flags(x) (((x) & ~0x3f) != 0)
#else
-#define irqs_enabled_from_flags(x) ((x) != 0x1f)
+# define smp_mb() barrier()
+# define smp_rmb() barrier()
+# define smp_wmb() barrier()
+#define smp_read_barrier_depends() barrier()
#endif
-#define local_irq_restore(x) \
- do { \
- if (irqs_enabled_from_flags(x)) \
- local_irq_enable(); \
- } while (0)
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+ int size)
+{
+ unsigned long tmp;
-/* For spinlocks etc */
-#define local_irq_save(x) __save_and_cli(x)
+ switch (size) {
+ case 1:
+ tmp = __raw_xchg_1_asm(ptr, x);
+ break;
+ case 2:
+ tmp = __raw_xchg_2_asm(ptr, x);
+ break;
+ case 4:
+ tmp = __raw_xchg_4_asm(ptr, x);
+ break;
+ }
-#define irqs_disabled() \
-({ \
- unsigned long flags; \
- local_save_flags(flags); \
- !irqs_enabled_from_flags(flags); \
-})
+ return tmp;
+}
/*
- * Force strict CPU ordering.
+ * Atomic compare and exchange. Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
*/
-#define nop() asm volatile ("nop;\n\t"::)
-#define mb() asm volatile ("" : : :"memory")
-#define rmb() asm volatile ("" : : :"memory")
-#define wmb() asm volatile ("" : : :"memory")
-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ unsigned long new, int size)
+{
+ unsigned long tmp;
-#define read_barrier_depends() do { } while(0)
+ switch (size) {
+ case 1:
+ tmp = __raw_cmpxchg_1_asm(ptr, new, old);
+ break;
+ case 2:
+ tmp = __raw_cmpxchg_2_asm(ptr, new, old);
+ break;
+ case 4:
+ tmp = __raw_cmpxchg_4_asm(ptr, new, old);
+ break;
+ }
+
+ return tmp;
+}
+#define cmpxchg(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \
+ (unsigned long)(n), sizeof(*(ptr))))
+
+#else /* !CONFIG_SMP */
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#define smp_rmb() rmb()
-#define smp_wmb() wmb()
-#define smp_read_barrier_depends() read_barrier_depends()
-#else
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
#define smp_read_barrier_depends() do { } while(0)
-#endif
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
struct __xchg_dummy {
unsigned long a[100];
@@ -157,7 +141,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
unsigned long tmp = 0;
unsigned long flags = 0;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
switch (size) {
case 1:
@@ -179,7 +163,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
: "=&d" (tmp) : "d" (x), "m" (*__xg(ptr)) : "memory");
break;
}
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return tmp;
}
@@ -194,9 +178,12 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
(unsigned long)(n), sizeof(*(ptr))))
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#ifndef CONFIG_SMP
#include <asm-generic/cmpxchg.h>
-#endif
+
+#endif /* !CONFIG_SMP */
+
+#define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+#define tas(ptr) ((void)xchg((ptr), 1))
#define prepare_to_switch() do { } while(0)
@@ -205,10 +192,12 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
* ptr isn't the current task, in which case it does nothing.
*/
-#include <asm/blackfin.h>
+#include <asm/l1layout.h>
+#include <asm/mem_map.h>
asmlinkage struct task_struct *resume(struct task_struct *prev, struct task_struct *next);
+#ifndef CONFIG_SMP
#define switch_to(prev,next,last) \
do { \
memcpy (&task_thread_info(prev)->l1_task_info, L1_SCRATCH_TASK_INFO, \
@@ -217,5 +206,11 @@ do { \
sizeof *L1_SCRATCH_TASK_INFO); \
(last) = resume (prev, next); \
} while (0)
+#else
+#define switch_to(prev, next, last) \
+do { \
+ (last) = resume(prev, next); \
+} while (0)
+#endif
-#endif /* _BLACKFIN_SYSTEM_H */
+#endif /* _BLACKFIN_SYSTEM_H */
diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h
index 642769329d12..e721ce55956c 100644
--- a/arch/blackfin/include/asm/thread_info.h
+++ b/arch/blackfin/include/asm/thread_info.h
@@ -44,6 +44,7 @@
*/
#define THREAD_SIZE_ORDER 1
#define THREAD_SIZE 8192 /* 2 pages */
+#define STACK_WARN (THREAD_SIZE/8)
#ifndef __ASSEMBLY__
@@ -62,7 +63,9 @@ struct thread_info {
int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* address limit */
struct restart_block restart_block;
+#ifndef CONFIG_SMP
struct l1_scratch_task_info l1_task_info;
+#endif
};
/*
@@ -90,7 +93,7 @@ __attribute_const__
static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
- __asm__("%0 = sp;": "=&d"(ti):
+ __asm__("%0 = sp;" : "=da"(ti) :
);
return (struct thread_info *)((long)ti & ~((long)THREAD_SIZE-1));
}
diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h
index d928b8099056..3248033531e6 100644
--- a/arch/blackfin/include/asm/uaccess.h
+++ b/arch/blackfin/include/asm/uaccess.h
@@ -149,54 +149,42 @@ static inline int bad_user_access_length(void)
: /* no outputs */ \
:"d" (x),"a" (__ptr(p)) : "memory")
-#define get_user(x,p) \
- ({ \
- int _err = 0; \
- typeof(*(p)) *_p = (p); \
- if (!access_ok(VERIFY_READ, _p, sizeof(*(_p)))) { \
- _err = -EFAULT; \
- } \
- else { \
- switch (sizeof(*(_p))) { \
- case 1: \
- __get_user_asm(x, _p, B,(Z)); \
- break; \
- case 2: \
- __get_user_asm(x, _p, W,(Z)); \
- break; \
- case 4: \
- __get_user_asm(x, _p, , ); \
- break; \
- case 8: { \
- unsigned long _xl, _xh; \
- __get_user_asm(_xl, ((unsigned long *)_p)+0, , ); \
- __get_user_asm(_xh, ((unsigned long *)_p)+1, , ); \
- ((unsigned long *)&x)[0] = _xl; \
- ((unsigned long *)&x)[1] = _xh; \
- } break; \
- default: \
- x = 0; \
- printk(KERN_INFO "get_user_bad: %s:%d %s\n", \
- __FILE__, __LINE__, __func__); \
- _err = __get_user_bad(); \
- break; \
- } \
- } \
- _err; \
- })
+#define get_user(x, ptr) \
+({ \
+ int _err = 0; \
+ unsigned long _val = 0; \
+ const typeof(*(ptr)) __user *_p = (ptr); \
+ const size_t ptr_size = sizeof(*(_p)); \
+ if (likely(access_ok(VERIFY_READ, _p, ptr_size))) { \
+ BUILD_BUG_ON(ptr_size >= 8); \
+ switch (ptr_size) { \
+ case 1: \
+ __get_user_asm(_val, _p, B,(Z)); \
+ break; \
+ case 2: \
+ __get_user_asm(_val, _p, W,(Z)); \
+ break; \
+ case 4: \
+ __get_user_asm(_val, _p, , ); \
+ break; \
+ } \
+ } else \
+ _err = -EFAULT; \
+ x = (typeof(*(ptr)))_val; \
+ _err; \
+})
#define __get_user(x,p) get_user(x,p)
#define __get_user_bad() (bad_user_access_length(), (-EFAULT))
-#define __get_user_asm(x,p,bhw,option) \
- { \
- unsigned long _tmp; \
- __asm__ ("%0 =" #bhw "[%1]"#option";\n\t" \
- : "=d" (_tmp) \
- : "a" (__ptr(p))); \
- (x) = (__typeof__(*(p))) _tmp; \
- }
+#define __get_user_asm(x, ptr, bhw, option) \
+({ \
+ __asm__ __volatile__ ( \
+ "%0 =" #bhw "[%1]" #option ";" \
+ : "=d" (x) \
+ : "a" (__ptr(ptr))); \
+})
#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
@@ -209,8 +197,8 @@ static inline int bad_user_access_length(void)
#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n))\
return retval; })
-static inline long copy_from_user(void *to,
- const void __user * from, unsigned long n)
+static inline unsigned long __must_check
+copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
memcpy(to, from, n);
@@ -219,8 +207,8 @@ static inline long copy_from_user(void *to,
return 0;
}
-static inline long copy_to_user(void *to,
- const void __user * from, unsigned long n)
+static inline unsigned long __must_check
+copy_to_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
memcpy(to, from, n);
@@ -233,8 +221,8 @@ static inline long copy_to_user(void *to,
* Copy a null terminated string from userspace.
*/
-static inline long strncpy_from_user(char *dst,
- const char *src, long count)
+static inline long __must_check
+strncpy_from_user(char *dst, const char *src, long count)
{
char *tmp;
if (!access_ok(VERIFY_READ, src, 1))
@@ -260,7 +248,8 @@ static inline long strnlen_user(const char *src, long n)
* Zero Userspace
*/
-static inline unsigned long __clear_user(void *to, unsigned long n)
+static inline unsigned long __must_check
+__clear_user(void *to, unsigned long n)
{
memset(to, 0, n);
return 0;
diff --git a/include/asm-m68k/xor.h b/arch/blackfin/include/asm/xor.h
index c82eb12a5b18..c82eb12a5b18 100644
--- a/include/asm-m68k/xor.h
+++ b/arch/blackfin/include/asm/xor.h
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 606adc78aa85..4a92a86824b7 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := init_task.o vmlinux.lds
obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
sys_bfin.o traps.o irqchip.o dma-mapping.o flat.o \
- fixed_code.o reboot.o bfin_gpio.o
+ fixed_code.o reboot.o bfin_gpio.o bfin_dma_5xx.o
ifeq ($(CONFIG_GENERIC_CLOCKEVENTS),y)
obj-y += time-ts.o
@@ -15,8 +15,13 @@ else
obj-y += time.o
endif
+CFLAGS_kgdb_test.o := -mlong-calls -O0
+
+obj-$(CONFIG_IPIPE) += ipipe.o
+obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o
obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o
+obj-$(CONFIG_CPLB_INFO) += cplbinfo.o
obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
obj-$(CONFIG_KGDB) += kgdb.o
+obj-$(CONFIG_KGDB_TESTCASE) += kgdb_test.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index 9bb85dd5ccb3..b5df9459d6d5 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -56,6 +56,9 @@ int main(void)
/* offsets into the thread struct */
DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+ DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat));
+ DEFINE(PT_SR, offsetof(struct thread_struct, seqstat));
+ DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
DEFINE(THREAD_PC, offsetof(struct thread_struct, pc));
DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE);
@@ -128,5 +131,31 @@ int main(void)
DEFINE(SIGSEGV, SIGSEGV);
DEFINE(SIGTRAP, SIGTRAP);
+ /* PDA management (in L1 scratchpad) */
+ DEFINE(PDA_SYSCFG, offsetof(struct blackfin_pda, syscfg));
+#ifdef CONFIG_SMP
+ DEFINE(PDA_IRQFLAGS, offsetof(struct blackfin_pda, imask));
+#endif
+ DEFINE(PDA_IPDT, offsetof(struct blackfin_pda, ipdt));
+ DEFINE(PDA_IPDT_SWAPCOUNT, offsetof(struct blackfin_pda, ipdt_swapcount));
+ DEFINE(PDA_DPDT, offsetof(struct blackfin_pda, dpdt));
+ DEFINE(PDA_DPDT_SWAPCOUNT, offsetof(struct blackfin_pda, dpdt_swapcount));
+ DEFINE(PDA_EXIPTR, offsetof(struct blackfin_pda, ex_iptr));
+ DEFINE(PDA_EXOPTR, offsetof(struct blackfin_pda, ex_optr));
+ DEFINE(PDA_EXBUF, offsetof(struct blackfin_pda, ex_buf));
+ DEFINE(PDA_EXIMASK, offsetof(struct blackfin_pda, ex_imask));
+ DEFINE(PDA_EXSTACK, offsetof(struct blackfin_pda, ex_stack));
+#ifdef ANOMALY_05000261
+ DEFINE(PDA_LFRETX, offsetof(struct blackfin_pda, last_cplb_fault_retx));
+#endif
+ DEFINE(PDA_DCPLB, offsetof(struct blackfin_pda, dcplb_fault_addr));
+ DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
+ DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
+ DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat));
+#ifdef CONFIG_SMP
+ /* Inter-core lock (in L2 SRAM) */
+ DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
+#endif
+
return 0;
}
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 339293d677cc..8531693fb48d 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -1,63 +1,27 @@
/*
- * File: arch/blackfin/kernel/bfin_dma_5xx.c
- * Based on:
- * Author:
+ * bfin_dma_5xx.c - Blackfin DMA implementation
*
- * Created:
- * Description: This file contains the simple DMA Implementation for Blackfin
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
*/
#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/param.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
#include <asm/blackfin.h>
-#include <asm/dma.h>
#include <asm/cacheflush.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
-/* Remove unused code not exported by symbol or internally called */
-#define REMOVE_DEAD_CODE
-
-/**************************************************************************
- * Global Variables
-***************************************************************************/
-
-static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
-
-/*------------------------------------------------------------------------------
- * Set the Buffer Clear bit in the Configuration register of specific DMA
- * channel. This will stop the descriptor based DMA operation.
- *-----------------------------------------------------------------------------*/
-static void clear_dma_buffer(unsigned int channel)
-{
- dma_ch[channel].regs->cfg |= RESTART;
- SSYNC();
- dma_ch[channel].regs->cfg &= ~RESTART;
- SSYNC();
-}
+struct dma_channel dma_ch[MAX_DMA_CHANNELS];
+EXPORT_SYMBOL(dma_ch);
static int __init blackfin_dma_init(void)
{
@@ -65,32 +29,67 @@ static int __init blackfin_dma_init(void)
printk(KERN_INFO "Blackfin DMA Controller\n");
- for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
+ for (i = 0; i < MAX_DMA_CHANNELS; i++) {
dma_ch[i].chan_status = DMA_CHANNEL_FREE;
dma_ch[i].regs = dma_io_base_addr[i];
mutex_init(&(dma_ch[i].dmalock));
}
/* Mark MEMDMA Channel 0 as requested since we're using it internally */
- dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED;
- dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED;
+ request_dma(CH_MEM_STREAM0_DEST, "Blackfin dma_memcpy");
+ request_dma(CH_MEM_STREAM0_SRC, "Blackfin dma_memcpy");
#if defined(CONFIG_DEB_DMA_URGENT)
bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE()
| DEB1_URGENT | DEB2_URGENT | DEB3_URGENT);
#endif
+
return 0;
}
-
arch_initcall(blackfin_dma_init);
-/*------------------------------------------------------------------------------
- * Request the specific DMA channel from the system.
- *-----------------------------------------------------------------------------*/
-int request_dma(unsigned int channel, char *device_id)
+#ifdef CONFIG_PROC_FS
+static int proc_dma_show(struct seq_file *m, void *v)
{
+ int i;
+
+ for (i = 0; i < MAX_DMA_CHANNELS; ++i)
+ if (dma_ch[i].chan_status != DMA_CHANNEL_FREE)
+ seq_printf(m, "%2d: %s\n", i, dma_ch[i].device_id);
+
+ return 0;
+}
+static int proc_dma_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_dma_show, NULL);
+}
+
+static const struct file_operations proc_dma_operations = {
+ .open = proc_dma_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init proc_dma_init(void)
+{
+ return proc_create("dma", 0, NULL, &proc_dma_operations) != NULL;
+}
+late_initcall(proc_dma_init);
+#endif
+
+/**
+ * request_dma - request a DMA channel
+ *
+ * Request the specific DMA channel from the system if it's available.
+ */
+int request_dma(unsigned int channel, const char *device_id)
+{
pr_debug("request_dma() : BEGIN \n");
+ if (device_id == NULL)
+ printk(KERN_WARNING "request_dma(%u): no device_id given\n", channel);
+
#if defined(CONFIG_BF561) && ANOMALY_05000182
if (channel >= CH_IMEM_STREAM0_DEST && channel <= CH_IMEM_STREAM1_DEST) {
if (get_cclk() > 500000000) {
@@ -129,60 +128,63 @@ int request_dma(unsigned int channel, char *device_id)
#endif
dma_ch[channel].device_id = device_id;
- dma_ch[channel].irq_callback = NULL;
+ dma_ch[channel].irq = 0;
/* This is to be enabled by putting a restriction -
* you have to request DMA, before doing any operations on
* descriptor/channel
*/
pr_debug("request_dma() : END \n");
- return channel;
+ return 0;
}
EXPORT_SYMBOL(request_dma);
-int set_dma_callback(unsigned int channel, dma_interrupt_t callback, void *data)
+int set_dma_callback(unsigned int channel, irq_handler_t callback, void *data)
{
- int ret_irq = 0;
-
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
+ && channel < MAX_DMA_CHANNELS));
if (callback != NULL) {
- int ret_val;
- ret_irq = channel2irq(channel);
+ int ret;
+ unsigned int irq = channel2irq(channel);
- dma_ch[channel].data = data;
+ ret = request_irq(irq, callback, IRQF_DISABLED,
+ dma_ch[channel].device_id, data);
+ if (ret)
+ return ret;
- ret_val =
- request_irq(ret_irq, (void *)callback, IRQF_DISABLED,
- dma_ch[channel].device_id, data);
- if (ret_val) {
- printk(KERN_NOTICE
- "Request irq in DMA engine failed.\n");
- return -EPERM;
- }
- dma_ch[channel].irq_callback = callback;
+ dma_ch[channel].irq = irq;
+ dma_ch[channel].data = data;
}
return 0;
}
EXPORT_SYMBOL(set_dma_callback);
-void free_dma(unsigned int channel)
+/**
+ * clear_dma_buffer - clear DMA fifos for specified channel
+ *
+ * Set the Buffer Clear bit in the Configuration register of specific DMA
+ * channel. This will stop the descriptor based DMA operation.
+ */
+static void clear_dma_buffer(unsigned int channel)
{
- int ret_irq;
+ dma_ch[channel].regs->cfg |= RESTART;
+ SSYNC();
+ dma_ch[channel].regs->cfg &= ~RESTART;
+}
+void free_dma(unsigned int channel)
+{
pr_debug("freedma() : BEGIN \n");
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
+ && channel < MAX_DMA_CHANNELS));
/* Halt the DMA */
disable_dma(channel);
clear_dma_buffer(channel);
- if (dma_ch[channel].irq_callback != NULL) {
- ret_irq = channel2irq(channel);
- free_irq(ret_irq, dma_ch[channel].data);
- }
+ if (dma_ch[channel].irq)
+ free_irq(dma_ch[channel].irq, dma_ch[channel].data);
/* Clear the DMA Variable in the Channel */
mutex_lock(&(dma_ch[channel].dmalock));
@@ -193,294 +195,15 @@ void free_dma(unsigned int channel)
}
EXPORT_SYMBOL(free_dma);
-void dma_enable_irq(unsigned int channel)
-{
- int ret_irq;
-
- pr_debug("dma_enable_irq() : BEGIN \n");
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- ret_irq = channel2irq(channel);
- enable_irq(ret_irq);
-}
-EXPORT_SYMBOL(dma_enable_irq);
-
-void dma_disable_irq(unsigned int channel)
-{
- int ret_irq;
-
- pr_debug("dma_disable_irq() : BEGIN \n");
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- ret_irq = channel2irq(channel);
- disable_irq(ret_irq);
-}
-EXPORT_SYMBOL(dma_disable_irq);
-
-int dma_channel_active(unsigned int channel)
-{
- if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE) {
- return 0;
- } else {
- return 1;
- }
-}
-EXPORT_SYMBOL(dma_channel_active);
-
-/*------------------------------------------------------------------------------
-* stop the specific DMA channel.
-*-----------------------------------------------------------------------------*/
-void disable_dma(unsigned int channel)
-{
- pr_debug("stop_dma() : BEGIN \n");
-
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->cfg &= ~DMAEN; /* Clean the enable bit */
- SSYNC();
- dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
- /* Needs to be enabled Later */
- pr_debug("stop_dma() : END \n");
- return;
-}
-EXPORT_SYMBOL(disable_dma);
-
-void enable_dma(unsigned int channel)
-{
- pr_debug("enable_dma() : BEGIN \n");
-
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
- dma_ch[channel].regs->curr_x_count = 0;
- dma_ch[channel].regs->curr_y_count = 0;
-
- dma_ch[channel].regs->cfg |= DMAEN; /* Set the enable bit */
- SSYNC();
- pr_debug("enable_dma() : END \n");
- return;
-}
-EXPORT_SYMBOL(enable_dma);
-
-/*------------------------------------------------------------------------------
-* Set the Start Address register for the specific DMA channel
-* This function can be used for register based DMA,
-* to setup the start address
-* addr: Starting address of the DMA Data to be transferred.
-*-----------------------------------------------------------------------------*/
-void set_dma_start_addr(unsigned int channel, unsigned long addr)
-{
- pr_debug("set_dma_start_addr() : BEGIN \n");
-
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->start_addr = addr;
- SSYNC();
- pr_debug("set_dma_start_addr() : END\n");
-}
-EXPORT_SYMBOL(set_dma_start_addr);
-
-void set_dma_next_desc_addr(unsigned int channel, unsigned long addr)
-{
- pr_debug("set_dma_next_desc_addr() : BEGIN \n");
-
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->next_desc_ptr = addr;
- SSYNC();
- pr_debug("set_dma_next_desc_addr() : END\n");
-}
-EXPORT_SYMBOL(set_dma_next_desc_addr);
-
-void set_dma_curr_desc_addr(unsigned int channel, unsigned long addr)
-{
- pr_debug("set_dma_curr_desc_addr() : BEGIN \n");
-
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->curr_desc_ptr = addr;
- SSYNC();
- pr_debug("set_dma_curr_desc_addr() : END\n");
-}
-EXPORT_SYMBOL(set_dma_curr_desc_addr);
-
-void set_dma_x_count(unsigned int channel, unsigned short x_count)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->x_count = x_count;
- SSYNC();
-}
-EXPORT_SYMBOL(set_dma_x_count);
-
-void set_dma_y_count(unsigned int channel, unsigned short y_count)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->y_count = y_count;
- SSYNC();
-}
-EXPORT_SYMBOL(set_dma_y_count);
-
-void set_dma_x_modify(unsigned int channel, short x_modify)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->x_modify = x_modify;
- SSYNC();
-}
-EXPORT_SYMBOL(set_dma_x_modify);
-
-void set_dma_y_modify(unsigned int channel, short y_modify)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->y_modify = y_modify;
- SSYNC();
-}
-EXPORT_SYMBOL(set_dma_y_modify);
-
-void set_dma_config(unsigned int channel, unsigned short config)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->cfg = config;
- SSYNC();
-}
-EXPORT_SYMBOL(set_dma_config);
-
-unsigned short
-set_bfin_dma_config(char direction, char flow_mode,
- char intr_mode, char dma_mode, char width, char syncmode)
-{
- unsigned short config;
-
- config =
- ((direction << 1) | (width << 2) | (dma_mode << 4) |
- (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5));
- return config;
-}
-EXPORT_SYMBOL(set_bfin_dma_config);
-
-void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->cfg |= ((nr_sg & 0x0F) << 8);
-
- dma_ch[channel].regs->next_desc_ptr = (unsigned int)sg;
-
- SSYNC();
-}
-EXPORT_SYMBOL(set_dma_sg);
-
-void set_dma_curr_addr(unsigned int channel, unsigned long addr)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- dma_ch[channel].regs->curr_addr_ptr = addr;
- SSYNC();
-}
-EXPORT_SYMBOL(set_dma_curr_addr);
-
-/*------------------------------------------------------------------------------
- * Get the DMA status of a specific DMA channel from the system.
- *-----------------------------------------------------------------------------*/
-unsigned short get_dma_curr_irqstat(unsigned int channel)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- return dma_ch[channel].regs->irq_status;
-}
-EXPORT_SYMBOL(get_dma_curr_irqstat);
-
-/*------------------------------------------------------------------------------
- * Clear the DMA_DONE bit in DMA status. Stop the DMA completion interrupt.
- *-----------------------------------------------------------------------------*/
-void clear_dma_irqstat(unsigned int channel)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
- dma_ch[channel].regs->irq_status |= 3;
-}
-EXPORT_SYMBOL(clear_dma_irqstat);
-
-/*------------------------------------------------------------------------------
- * Get current DMA xcount of a specific DMA channel from the system.
- *-----------------------------------------------------------------------------*/
-unsigned short get_dma_curr_xcount(unsigned int channel)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- return dma_ch[channel].regs->curr_x_count;
-}
-EXPORT_SYMBOL(get_dma_curr_xcount);
-
-/*------------------------------------------------------------------------------
- * Get current DMA ycount of a specific DMA channel from the system.
- *-----------------------------------------------------------------------------*/
-unsigned short get_dma_curr_ycount(unsigned int channel)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- return dma_ch[channel].regs->curr_y_count;
-}
-EXPORT_SYMBOL(get_dma_curr_ycount);
-
-unsigned long get_dma_next_desc_ptr(unsigned int channel)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- return dma_ch[channel].regs->next_desc_ptr;
-}
-EXPORT_SYMBOL(get_dma_next_desc_ptr);
-
-unsigned long get_dma_curr_desc_ptr(unsigned int channel)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- return dma_ch[channel].regs->curr_desc_ptr;
-}
-EXPORT_SYMBOL(get_dma_curr_desc_ptr);
-
-unsigned long get_dma_curr_addr(unsigned int channel)
-{
- BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
- && channel < MAX_BLACKFIN_DMA_CHANNEL));
-
- return dma_ch[channel].regs->curr_addr_ptr;
-}
-EXPORT_SYMBOL(get_dma_curr_addr);
-
#ifdef CONFIG_PM
+# ifndef MAX_DMA_SUSPEND_CHANNELS
+# define MAX_DMA_SUSPEND_CHANNELS MAX_DMA_CHANNELS
+# endif
int blackfin_dma_suspend(void)
{
int i;
-#ifdef CONFIG_BF561 /* IMDMA channels doesn't have a PERIPHERAL_MAP */
- for (i = 0; i <= CH_MEM_STREAM3_SRC; i++) {
-#else
- for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
-#endif
+ for (i = 0; i < MAX_DMA_SUSPEND_CHANNELS; ++i) {
if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
return -EBUSY;
@@ -495,388 +218,208 @@ int blackfin_dma_suspend(void)
void blackfin_dma_resume(void)
{
int i;
-
-#ifdef CONFIG_BF561 /* IMDMA channels doesn't have a PERIPHERAL_MAP */
- for (i = 0; i <= CH_MEM_STREAM3_SRC; i++)
-#else
- for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++)
-#endif
+ for (i = 0; i < MAX_DMA_SUSPEND_CHANNELS; ++i)
dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
}
#endif
-static void *__dma_memcpy(void *dest, const void *src, size_t size)
+/**
+ * blackfin_dma_early_init - minimal DMA init
+ *
+ * Setup a few DMA registers so we can safely do DMA transfers early on in
+ * the kernel booting process. Really this just means using dma_memcpy().
+ */
+void __init blackfin_dma_early_init(void)
{
- int direction; /* 1 - address decrease, 0 - address increase */
- int flag_align; /* 1 - address aligned, 0 - address unaligned */
- int flag_2D; /* 1 - 2D DMA needed, 0 - 1D DMA needed */
- unsigned long flags;
-
- if (size <= 0)
- return NULL;
-
- local_irq_save(flags);
-
- if ((unsigned long)src < memory_end)
- blackfin_dcache_flush_range((unsigned int)src,
- (unsigned int)(src + size));
-
- if ((unsigned long)dest < memory_end)
- blackfin_dcache_invalidate_range((unsigned int)dest,
- (unsigned int)(dest + size));
-
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- if ((unsigned long)src < (unsigned long)dest)
- direction = 1;
- else
- direction = 0;
-
- if ((((unsigned long)dest % 2) == 0) && (((unsigned long)src % 2) == 0)
- && ((size % 2) == 0))
- flag_align = 1;
- else
- flag_align = 0;
-
- if (size > 0x10000) /* size > 64K */
- flag_2D = 1;
- else
- flag_2D = 0;
-
- /* Setup destination and source start address */
- if (direction) {
- if (flag_align) {
- bfin_write_MDMA_D0_START_ADDR(dest + size - 2);
- bfin_write_MDMA_S0_START_ADDR(src + size - 2);
- } else {
- bfin_write_MDMA_D0_START_ADDR(dest + size - 1);
- bfin_write_MDMA_S0_START_ADDR(src + size - 1);
- }
- } else {
- bfin_write_MDMA_D0_START_ADDR(dest);
- bfin_write_MDMA_S0_START_ADDR(src);
- }
-
- /* Setup destination and source xcount */
- if (flag_2D) {
- if (flag_align) {
- bfin_write_MDMA_D0_X_COUNT(1024 / 2);
- bfin_write_MDMA_S0_X_COUNT(1024 / 2);
- } else {
- bfin_write_MDMA_D0_X_COUNT(1024);
- bfin_write_MDMA_S0_X_COUNT(1024);
- }
- bfin_write_MDMA_D0_Y_COUNT(size >> 10);
- bfin_write_MDMA_S0_Y_COUNT(size >> 10);
- } else {
- if (flag_align) {
- bfin_write_MDMA_D0_X_COUNT(size / 2);
- bfin_write_MDMA_S0_X_COUNT(size / 2);
- } else {
- bfin_write_MDMA_D0_X_COUNT(size);
- bfin_write_MDMA_S0_X_COUNT(size);
- }
- }
-
- /* Setup destination and source xmodify and ymodify */
- if (direction) {
- if (flag_align) {
- bfin_write_MDMA_D0_X_MODIFY(-2);
- bfin_write_MDMA_S0_X_MODIFY(-2);
- if (flag_2D) {
- bfin_write_MDMA_D0_Y_MODIFY(-2);
- bfin_write_MDMA_S0_Y_MODIFY(-2);
- }
- } else {
- bfin_write_MDMA_D0_X_MODIFY(-1);
- bfin_write_MDMA_S0_X_MODIFY(-1);
- if (flag_2D) {
- bfin_write_MDMA_D0_Y_MODIFY(-1);
- bfin_write_MDMA_S0_Y_MODIFY(-1);
- }
- }
- } else {
- if (flag_align) {
- bfin_write_MDMA_D0_X_MODIFY(2);
- bfin_write_MDMA_S0_X_MODIFY(2);
- if (flag_2D) {
- bfin_write_MDMA_D0_Y_MODIFY(2);
- bfin_write_MDMA_S0_Y_MODIFY(2);
- }
- } else {
- bfin_write_MDMA_D0_X_MODIFY(1);
- bfin_write_MDMA_S0_X_MODIFY(1);
- if (flag_2D) {
- bfin_write_MDMA_D0_Y_MODIFY(1);
- bfin_write_MDMA_S0_Y_MODIFY(1);
- }
- }
- }
-
- /* Enable source DMA */
- if (flag_2D) {
- if (flag_align) {
- bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D | WDSIZE_16);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D | WDSIZE_16);
- } else {
- bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D);
- }
- } else {
- if (flag_align) {
- bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
- } else {
- bfin_write_MDMA_S0_CONFIG(DMAEN);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN);
- }
- }
-
- SSYNC();
-
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
- ;
-
- bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() |
- (DMA_DONE | DMA_ERR));
-
bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
-
- local_irq_restore(flags);
-
- return dest;
}
-void *dma_memcpy(void *dest, const void *src, size_t size)
-{
- size_t bulk;
- size_t rest;
- void * addr;
-
- bulk = (size >> 16) << 16;
- rest = size - bulk;
- if (bulk)
- __dma_memcpy(dest, src, bulk);
- addr = __dma_memcpy(dest+bulk, src+bulk, rest);
- return addr;
-}
-EXPORT_SYMBOL(dma_memcpy);
-
-void *safe_dma_memcpy(void *dest, const void *src, size_t size)
-{
- void *addr;
- addr = dma_memcpy(dest, src, size);
- return addr;
-}
-EXPORT_SYMBOL(safe_dma_memcpy);
-
-void dma_outsb(unsigned long addr, const void *buf, unsigned short len)
+/**
+ * __dma_memcpy - program the MDMA registers
+ *
+ * Actually program MDMA0 and wait for the transfer to finish. Disable IRQs
+ * while programming registers so that everything is fully configured. Wait
+ * for DMA to finish with IRQs enabled. If interrupted, the initial DMA_DONE
+ * check will make sure we don't clobber any existing transfer.
+ */
+static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u32 conf)
{
+ static DEFINE_SPINLOCK(mdma_lock);
unsigned long flags;
- local_irq_save(flags);
+ spin_lock_irqsave(&mdma_lock, flags);
- blackfin_dcache_flush_range((unsigned int)buf,
- (unsigned int)(buf) + len);
+ /* Force a sync in case a previous config reset on this channel
+ * occurred. This is needed so subsequent writes to DMA registers
+ * are not spuriously lost/corrupted. Do it under irq lock and
+ * without the anomaly version (because we are atomic already).
+ */
+ __builtin_bfin_ssync();
+
+ if (bfin_read_MDMA_S0_CONFIG())
+ while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+ continue;
+
+ if (conf & DMA2D) {
+ /* For larger bit sizes, we've already divided down cnt so it
+ * is no longer a multiple of 64k. So we have to break down
+ * the limit here so it is a multiple of the incoming size.
+ * There is no limitation here in terms of total size other
+ * than the hardware though as the bits lost in the shift are
+ * made up by MODIFY (== we can hit the whole address space).
+ * X: (2^(16 - 0)) * 1 == (2^(16 - 1)) * 2 == (2^(16 - 2)) * 4
+ */
+ u32 shift = abs(dmod) >> 1;
+ size_t ycnt = cnt >> (16 - shift);
+ cnt = 1 << (16 - shift);
+ bfin_write_MDMA_D0_Y_COUNT(ycnt);
+ bfin_write_MDMA_S0_Y_COUNT(ycnt);
+ bfin_write_MDMA_D0_Y_MODIFY(dmod);
+ bfin_write_MDMA_S0_Y_MODIFY(smod);
+ }
- bfin_write_MDMA_D0_START_ADDR(addr);
- bfin_write_MDMA_D0_X_COUNT(len);
- bfin_write_MDMA_D0_X_MODIFY(0);
+ bfin_write_MDMA_D0_START_ADDR(daddr);
+ bfin_write_MDMA_D0_X_COUNT(cnt);
+ bfin_write_MDMA_D0_X_MODIFY(dmod);
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
- bfin_write_MDMA_S0_START_ADDR(buf);
- bfin_write_MDMA_S0_X_COUNT(len);
- bfin_write_MDMA_S0_X_MODIFY(1);
+ bfin_write_MDMA_S0_START_ADDR(saddr);
+ bfin_write_MDMA_S0_X_COUNT(cnt);
+ bfin_write_MDMA_S0_X_MODIFY(smod);
bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
- bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
+ bfin_write_MDMA_S0_CONFIG(DMAEN | conf);
+ bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | conf);
+
+ spin_unlock_irqrestore(&mdma_lock, flags);
SSYNC();
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+ while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+ if (bfin_read_MDMA_S0_CONFIG())
+ continue;
+ else
+ return;
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
bfin_write_MDMA_S0_CONFIG(0);
bfin_write_MDMA_D0_CONFIG(0);
- local_irq_restore(flags);
-
}
-EXPORT_SYMBOL(dma_outsb);
-
-void dma_insb(unsigned long addr, void *buf, unsigned short len)
+/**
+ * _dma_memcpy - translate C memcpy settings into MDMA settings
+ *
+ * Handle all the high level steps before we touch the MDMA registers. So
+ * handle direction, tweaking of sizes, and formatting of addresses.
+ */
+static void *_dma_memcpy(void *pdst, const void *psrc, size_t size)
{
- unsigned long flags;
-
- blackfin_dcache_invalidate_range((unsigned int)buf,
- (unsigned int)(buf) + len);
-
- local_irq_save(flags);
- bfin_write_MDMA_D0_START_ADDR(buf);
- bfin_write_MDMA_D0_X_COUNT(len);
- bfin_write_MDMA_D0_X_MODIFY(1);
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_START_ADDR(addr);
- bfin_write_MDMA_S0_X_COUNT(len);
- bfin_write_MDMA_S0_X_MODIFY(0);
- bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+ u32 conf, shift;
+ s16 mod;
+ unsigned long dst = (unsigned long)pdst;
+ unsigned long src = (unsigned long)psrc;
- bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
+ if (size == 0)
+ return NULL;
- SSYNC();
+ if (dst % 4 == 0 && src % 4 == 0 && size % 4 == 0) {
+ conf = WDSIZE_32;
+ shift = 2;
+ } else if (dst % 2 == 0 && src % 2 == 0 && size % 2 == 0) {
+ conf = WDSIZE_16;
+ shift = 1;
+ } else {
+ conf = WDSIZE_8;
+ shift = 0;
+ }
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
+ /* If the two memory regions have a chance of overlapping, make
+ * sure the memcpy still works as expected. Do this by having the
+ * copy run backwards instead.
+ */
+ mod = 1 << shift;
+ if (src < dst) {
+ mod *= -1;
+ dst += size + mod;
+ src += size + mod;
+ }
+ size >>= shift;
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+ if (size > 0x10000)
+ conf |= DMA2D;
- bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
- local_irq_restore(flags);
+ __dma_memcpy(dst, mod, src, mod, size, conf);
+ return pdst;
}
-EXPORT_SYMBOL(dma_insb);
-void dma_outsw(unsigned long addr, const void *buf, unsigned short len)
+/**
+ * dma_memcpy - DMA memcpy under mutex lock
+ *
+ * Do not check arguments before starting the DMA memcpy. Break the transfer
+ * up into two pieces. The first transfer is in multiples of 64k and the
+ * second transfer is the piece smaller than 64k.
+ */
+void *dma_memcpy(void *pdst, const void *psrc, size_t size)
{
- unsigned long flags;
-
- local_irq_save(flags);
+ unsigned long dst = (unsigned long)pdst;
+ unsigned long src = (unsigned long)psrc;
+ size_t bulk, rest;
- blackfin_dcache_flush_range((unsigned int)buf,
- (unsigned int)(buf) + len * sizeof(short));
+ if (bfin_addr_dcachable(src))
+ blackfin_dcache_flush_range(src, src + size);
- bfin_write_MDMA_D0_START_ADDR(addr);
- bfin_write_MDMA_D0_X_COUNT(len);
- bfin_write_MDMA_D0_X_MODIFY(0);
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_START_ADDR(buf);
- bfin_write_MDMA_S0_X_COUNT(len);
- bfin_write_MDMA_S0_X_MODIFY(2);
- bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
-
- SSYNC();
-
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
-
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
- local_irq_restore(flags);
+ if (bfin_addr_dcachable(dst))
+ blackfin_dcache_invalidate_range(dst, dst + size);
+ bulk = size & ~0xffff;
+ rest = size - bulk;
+ if (bulk)
+ _dma_memcpy(pdst, psrc, bulk);
+ _dma_memcpy(pdst + bulk, psrc + bulk, rest);
+ return pdst;
}
-EXPORT_SYMBOL(dma_outsw);
+EXPORT_SYMBOL(dma_memcpy);
-void dma_insw(unsigned long addr, void *buf, unsigned short len)
+/**
+ * safe_dma_memcpy - DMA memcpy w/argument checking
+ *
+ * Verify arguments are safe before heading to dma_memcpy().
+ */
+void *safe_dma_memcpy(void *dst, const void *src, size_t size)
{
- unsigned long flags;
-
- blackfin_dcache_invalidate_range((unsigned int)buf,
- (unsigned int)(buf) + len * sizeof(short));
-
- local_irq_save(flags);
-
- bfin_write_MDMA_D0_START_ADDR(buf);
- bfin_write_MDMA_D0_X_COUNT(len);
- bfin_write_MDMA_D0_X_MODIFY(2);
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_START_ADDR(addr);
- bfin_write_MDMA_S0_X_COUNT(len);
- bfin_write_MDMA_S0_X_MODIFY(0);
- bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
-
- SSYNC();
-
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
-
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
- local_irq_restore(flags);
-
+ if (!access_ok(VERIFY_WRITE, dst, size))
+ return NULL;
+ if (!access_ok(VERIFY_READ, src, size))
+ return NULL;
+ return dma_memcpy(dst, src, size);
}
-EXPORT_SYMBOL(dma_insw);
+EXPORT_SYMBOL(safe_dma_memcpy);
-void dma_outsl(unsigned long addr, const void *buf, unsigned short len)
+static void _dma_out(unsigned long addr, unsigned long buf, unsigned short len,
+ u16 size, u16 dma_size)
{
- unsigned long flags;
-
- local_irq_save(flags);
-
- blackfin_dcache_flush_range((unsigned int)buf,
- (unsigned int)(buf) + len * sizeof(long));
-
- bfin_write_MDMA_D0_START_ADDR(addr);
- bfin_write_MDMA_D0_X_COUNT(len);
- bfin_write_MDMA_D0_X_MODIFY(0);
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_START_ADDR(buf);
- bfin_write_MDMA_S0_X_COUNT(len);
- bfin_write_MDMA_S0_X_MODIFY(4);
- bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
-
- SSYNC();
-
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
-
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
- local_irq_restore(flags);
-
+ blackfin_dcache_flush_range(buf, buf + len * size);
+ __dma_memcpy(addr, 0, buf, size, len, dma_size);
}
-EXPORT_SYMBOL(dma_outsl);
-void dma_insl(unsigned long addr, void *buf, unsigned short len)
+static void _dma_in(unsigned long addr, unsigned long buf, unsigned short len,
+ u16 size, u16 dma_size)
{
- unsigned long flags;
-
- blackfin_dcache_invalidate_range((unsigned int)buf,
- (unsigned int)(buf) + len * sizeof(long));
-
- local_irq_save(flags);
-
- bfin_write_MDMA_D0_START_ADDR(buf);
- bfin_write_MDMA_D0_X_COUNT(len);
- bfin_write_MDMA_D0_X_MODIFY(4);
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_START_ADDR(addr);
- bfin_write_MDMA_S0_X_COUNT(len);
- bfin_write_MDMA_S0_X_MODIFY(0);
- bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
- bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
-
- SSYNC();
-
- while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
-
- bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
-
- bfin_write_MDMA_S0_CONFIG(0);
- bfin_write_MDMA_D0_CONFIG(0);
- local_irq_restore(flags);
-
+ blackfin_dcache_invalidate_range(buf, buf + len * size);
+ __dma_memcpy(buf, size, addr, 0, len, dma_size);
}
-EXPORT_SYMBOL(dma_insl);
+
+#define MAKE_DMA_IO(io, bwl, isize, dmasize, cnst) \
+void dma_##io##s##bwl(unsigned long addr, cnst void *buf, unsigned short len) \
+{ \
+ _dma_##io(addr, (unsigned long)buf, len, isize, WDSIZE_##dmasize); \
+} \
+EXPORT_SYMBOL(dma_##io##s##bwl)
+MAKE_DMA_IO(out, b, 1, 8, const);
+MAKE_DMA_IO(in, b, 1, 8, );
+MAKE_DMA_IO(out, w, 2, 16, const);
+MAKE_DMA_IO(in, w, 2, 16, );
+MAKE_DMA_IO(out, l, 4, 32, const);
+MAKE_DMA_IO(in, l, 4, 32, );
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 5c0800adb4dd..51dac55c524a 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -27,59 +27,6 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/*
-* Number BF537/6/4 BF561 BF533/2/1 BF549/8/4/2
-*
-* GPIO_0 PF0 PF0 PF0 PA0...PJ13
-* GPIO_1 PF1 PF1 PF1
-* GPIO_2 PF2 PF2 PF2
-* GPIO_3 PF3 PF3 PF3
-* GPIO_4 PF4 PF4 PF4
-* GPIO_5 PF5 PF5 PF5
-* GPIO_6 PF6 PF6 PF6
-* GPIO_7 PF7 PF7 PF7
-* GPIO_8 PF8 PF8 PF8
-* GPIO_9 PF9 PF9 PF9
-* GPIO_10 PF10 PF10 PF10
-* GPIO_11 PF11 PF11 PF11
-* GPIO_12 PF12 PF12 PF12
-* GPIO_13 PF13 PF13 PF13
-* GPIO_14 PF14 PF14 PF14
-* GPIO_15 PF15 PF15 PF15
-* GPIO_16 PG0 PF16
-* GPIO_17 PG1 PF17
-* GPIO_18 PG2 PF18
-* GPIO_19 PG3 PF19
-* GPIO_20 PG4 PF20
-* GPIO_21 PG5 PF21
-* GPIO_22 PG6 PF22
-* GPIO_23 PG7 PF23
-* GPIO_24 PG8 PF24
-* GPIO_25 PG9 PF25
-* GPIO_26 PG10 PF26
-* GPIO_27 PG11 PF27
-* GPIO_28 PG12 PF28
-* GPIO_29 PG13 PF29
-* GPIO_30 PG14 PF30
-* GPIO_31 PG15 PF31
-* GPIO_32 PH0 PF32
-* GPIO_33 PH1 PF33
-* GPIO_34 PH2 PF34
-* GPIO_35 PH3 PF35
-* GPIO_36 PH4 PF36
-* GPIO_37 PH5 PF37
-* GPIO_38 PH6 PF38
-* GPIO_39 PH7 PF39
-* GPIO_40 PH8 PF40
-* GPIO_41 PH9 PF41
-* GPIO_42 PH10 PF42
-* GPIO_43 PH11 PF43
-* GPIO_44 PH12 PF44
-* GPIO_45 PH13 PF45
-* GPIO_46 PH14 PF46
-* GPIO_47 PH15 PF47
-*/
-
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/err.h>
@@ -119,66 +66,66 @@ enum {
#define AWA_DUMMY_READ(...) do { } while (0)
#endif
-#ifdef BF533_FAMILY
-static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+static struct gpio_port_t * const gpio_array[] = {
+#if defined(BF533_FAMILY) || defined(BF538_FAMILY)
(struct gpio_port_t *) FIO_FLAG_D,
-};
-#endif
-
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
-static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+#elif defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
(struct gpio_port_t *) PORTFIO,
(struct gpio_port_t *) PORTGIO,
(struct gpio_port_t *) PORTHIO,
+#elif defined(BF561_FAMILY)
+ (struct gpio_port_t *) FIO0_FLAG_D,
+ (struct gpio_port_t *) FIO1_FLAG_D,
+ (struct gpio_port_t *) FIO2_FLAG_D,
+#elif defined(BF548_FAMILY)
+ (struct gpio_port_t *)PORTA_FER,
+ (struct gpio_port_t *)PORTB_FER,
+ (struct gpio_port_t *)PORTC_FER,
+ (struct gpio_port_t *)PORTD_FER,
+ (struct gpio_port_t *)PORTE_FER,
+ (struct gpio_port_t *)PORTF_FER,
+ (struct gpio_port_t *)PORTG_FER,
+ (struct gpio_port_t *)PORTH_FER,
+ (struct gpio_port_t *)PORTI_FER,
+ (struct gpio_port_t *)PORTJ_FER,
+#else
+# error no gpio arrays defined
+#endif
};
-static unsigned short *port_fer[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+static unsigned short * const port_fer[] = {
(unsigned short *) PORTF_FER,
(unsigned short *) PORTG_FER,
(unsigned short *) PORTH_FER,
};
-#endif
-#ifdef BF527_FAMILY
-static unsigned short *port_mux[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+# if !defined(BF537_FAMILY)
+static unsigned short * const port_mux[] = {
(unsigned short *) PORTF_MUX,
(unsigned short *) PORTG_MUX,
(unsigned short *) PORTH_MUX,
};
static const
-u8 pmux_offset[][16] =
- {{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
- { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
- { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
- };
-#endif
-
-#ifdef BF561_FAMILY
-static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
- (struct gpio_port_t *) FIO0_FLAG_D,
- (struct gpio_port_t *) FIO1_FLAG_D,
- (struct gpio_port_t *) FIO2_FLAG_D,
+u8 pmux_offset[][16] = {
+# if defined(BF527_FAMILY)
+ { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */
+ { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */
+# elif defined(BF518_FAMILY)
+ { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */
+ { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */
+ { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */
+# endif
};
-#endif
+# endif
-#ifdef BF548_FAMILY
-static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
- (struct gpio_port_t *)PORTA_FER,
- (struct gpio_port_t *)PORTB_FER,
- (struct gpio_port_t *)PORTC_FER,
- (struct gpio_port_t *)PORTD_FER,
- (struct gpio_port_t *)PORTE_FER,
- (struct gpio_port_t *)PORTF_FER,
- (struct gpio_port_t *)PORTG_FER,
- (struct gpio_port_t *)PORTH_FER,
- (struct gpio_port_t *)PORTI_FER,
- (struct gpio_port_t *)PORTJ_FER,
-};
#endif
-static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short reserved_gpio_map[GPIO_BANK_NUM];
static unsigned short reserved_peri_map[gpio_bank(MAX_RESOURCES)];
+static unsigned short reserved_gpio_irq_map[GPIO_BANK_NUM];
#define RESOURCE_LABEL_SIZE 16
@@ -187,49 +134,21 @@ static struct str_ident {
} str_ident[MAX_RESOURCES];
#if defined(CONFIG_PM)
-#if defined(CONFIG_BF54x)
-static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
-#else
-static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
-static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
-static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
-
-#ifdef BF533_FAMILY
-static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB};
-#endif
-
-#ifdef BF537_FAMILY
-static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX};
-#endif
-
-#ifdef BF527_FAMILY
-static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB};
+static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM];
#endif
-#ifdef BF561_FAMILY
-static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
-#endif
-#endif
-#endif /* CONFIG_PM */
-
-#if defined(BF548_FAMILY)
inline int check_gpio(unsigned gpio)
{
+#if defined(BF548_FAMILY)
if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
|| gpio == GPIO_PH14 || gpio == GPIO_PH15
- || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
- || gpio >= MAX_BLACKFIN_GPIOS)
+ || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
return -EINVAL;
- return 0;
-}
-#else
-inline int check_gpio(unsigned gpio)
-{
+#endif
if (gpio >= MAX_BLACKFIN_GPIOS)
return -EINVAL;
return 0;
}
-#endif
static void gpio_error(unsigned gpio)
{
@@ -258,35 +177,30 @@ static int cmp_label(unsigned short ident, const char *label)
}
if (label)
- return strncmp(str_ident[ident].name,
- label, strlen(label));
+ return strcmp(str_ident[ident].name, label);
else
return -EINVAL;
}
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
static void port_setup(unsigned gpio, unsigned short usage)
{
- if (!check_gpio(gpio)) {
- if (usage == GPIO_USAGE)
- *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
- else
- *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
- SSYNC();
- }
-}
+ if (check_gpio(gpio))
+ return;
+
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+ if (usage == GPIO_USAGE)
+ *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+ else
+ *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
+ SSYNC();
#elif defined(BF548_FAMILY)
-static void port_setup(unsigned gpio, unsigned short usage)
-{
if (usage == GPIO_USAGE)
gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
else
gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
SSYNC();
-}
-#else
-# define port_setup(...) do { } while (0)
#endif
+}
#ifdef BF537_FAMILY
static struct {
@@ -336,9 +250,10 @@ static struct {
{.res = P_SPI0_SSEL3, .offset = 0},
};
-static void portmux_setup(unsigned short per, unsigned short function)
+static void portmux_setup(unsigned short per)
{
u16 y, offset, muxreg;
+ u16 function = P_FUNCT2MUX(per);
for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) {
if (port_mux_lut[y].res == per) {
@@ -359,30 +274,33 @@ static void portmux_setup(unsigned short per, unsigned short function)
}
}
#elif defined(BF548_FAMILY)
-inline void portmux_setup(unsigned short portno, unsigned short function)
+inline void portmux_setup(unsigned short per)
{
u32 pmux;
+ u16 ident = P_IDENT(per);
+ u16 function = P_FUNCT2MUX(per);
- pmux = gpio_array[gpio_bank(portno)]->port_mux;
+ pmux = gpio_array[gpio_bank(ident)]->port_mux;
- pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
- pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
+ pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
+ pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
- gpio_array[gpio_bank(portno)]->port_mux = pmux;
+ gpio_array[gpio_bank(ident)]->port_mux = pmux;
}
-inline u16 get_portmux(unsigned short portno)
+inline u16 get_portmux(unsigned short per)
{
u32 pmux;
+ u16 ident = P_IDENT(per);
- pmux = gpio_array[gpio_bank(portno)]->port_mux;
+ pmux = gpio_array[gpio_bank(ident)]->port_mux;
- return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
+ return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
}
-#elif defined(BF527_FAMILY)
-inline void portmux_setup(unsigned short portno, unsigned short function)
+#elif defined(BF527_FAMILY) || defined(BF518_FAMILY)
+inline void portmux_setup(unsigned short per)
{
- u16 pmux, ident = P_IDENT(portno);
+ u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per);
u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)];
pmux = *port_mux[gpio_bank(ident)];
@@ -428,92 +346,73 @@ arch_initcall(bfin_gpio_init);
void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
{ \
unsigned long flags; \
- local_irq_save(flags); \
+ local_irq_save_hw(flags); \
if (arg) \
- gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
+ gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
else \
- gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
+ gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
AWA_DUMMY_READ(name); \
- local_irq_restore(flags); \
+ local_irq_restore_hw(flags); \
} \
EXPORT_SYMBOL(set_gpio_ ## name);
-SET_GPIO(dir)
-SET_GPIO(inen)
-SET_GPIO(polar)
-SET_GPIO(edge)
-SET_GPIO(both)
+SET_GPIO(dir) /* set_gpio_dir() */
+SET_GPIO(inen) /* set_gpio_inen() */
+SET_GPIO(polar) /* set_gpio_polar() */
+SET_GPIO(edge) /* set_gpio_edge() */
+SET_GPIO(both) /* set_gpio_both() */
-#if ANOMALY_05000311 || ANOMALY_05000323
#define SET_GPIO_SC(name) \
void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
{ \
unsigned long flags; \
- local_irq_save(flags); \
+ if (ANOMALY_05000311 || ANOMALY_05000323) \
+ local_irq_save_hw(flags); \
if (arg) \
- gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
+ gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
else \
- gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
- AWA_DUMMY_READ(name); \
- local_irq_restore(flags); \
+ gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
+ if (ANOMALY_05000311 || ANOMALY_05000323) { \
+ AWA_DUMMY_READ(name); \
+ local_irq_restore_hw(flags); \
+ } \
} \
EXPORT_SYMBOL(set_gpio_ ## name);
-#else
-#define SET_GPIO_SC(name) \
-void set_gpio_ ## name(unsigned gpio, unsigned short arg) \
-{ \
- if (arg) \
- gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
- else \
- gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
-} \
-EXPORT_SYMBOL(set_gpio_ ## name);
-#endif
SET_GPIO_SC(maska)
SET_GPIO_SC(maskb)
SET_GPIO_SC(data)
-#if ANOMALY_05000311 || ANOMALY_05000323
void set_gpio_toggle(unsigned gpio)
{
unsigned long flags;
- local_irq_save(flags);
- gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
- AWA_DUMMY_READ(toggle);
- local_irq_restore(flags);
-}
-#else
-void set_gpio_toggle(unsigned gpio)
-{
- gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+ if (ANOMALY_05000311 || ANOMALY_05000323)
+ local_irq_save_hw(flags);
+ gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+ if (ANOMALY_05000311 || ANOMALY_05000323) {
+ AWA_DUMMY_READ(toggle);
+ local_irq_restore_hw(flags);
+ }
}
-#endif
EXPORT_SYMBOL(set_gpio_toggle);
/*Set current PORT date (16-bit word)*/
-#if ANOMALY_05000311 || ANOMALY_05000323
#define SET_GPIO_P(name) \
void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
{ \
unsigned long flags; \
- local_irq_save(flags); \
- gpio_bankb[gpio_bank(gpio)]->name = arg; \
- AWA_DUMMY_READ(name); \
- local_irq_restore(flags); \
-} \
-EXPORT_SYMBOL(set_gpiop_ ## name);
-#else
-#define SET_GPIO_P(name) \
-void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \
-{ \
- gpio_bankb[gpio_bank(gpio)]->name = arg; \
+ if (ANOMALY_05000311 || ANOMALY_05000323) \
+ local_irq_save_hw(flags); \
+ gpio_array[gpio_bank(gpio)]->name = arg; \
+ if (ANOMALY_05000311 || ANOMALY_05000323) { \
+ AWA_DUMMY_READ(name); \
+ local_irq_restore_hw(flags); \
+ } \
} \
EXPORT_SYMBOL(set_gpiop_ ## name);
-#endif
SET_GPIO_P(data)
SET_GPIO_P(dir)
@@ -525,27 +424,21 @@ SET_GPIO_P(maska)
SET_GPIO_P(maskb)
/* Get a specific bit */
-#if ANOMALY_05000311 || ANOMALY_05000323
#define GET_GPIO(name) \
unsigned short get_gpio_ ## name(unsigned gpio) \
{ \
unsigned long flags; \
unsigned short ret; \
- local_irq_save(flags); \
- ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
- AWA_DUMMY_READ(name); \
- local_irq_restore(flags); \
+ if (ANOMALY_05000311 || ANOMALY_05000323) \
+ local_irq_save_hw(flags); \
+ ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \
+ if (ANOMALY_05000311 || ANOMALY_05000323) { \
+ AWA_DUMMY_READ(name); \
+ local_irq_restore_hw(flags); \
+ } \
return ret; \
} \
EXPORT_SYMBOL(get_gpio_ ## name);
-#else
-#define GET_GPIO(name) \
-unsigned short get_gpio_ ## name(unsigned gpio) \
-{ \
- return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \
-} \
-EXPORT_SYMBOL(get_gpio_ ## name);
-#endif
GET_GPIO(data)
GET_GPIO(dir)
@@ -558,27 +451,21 @@ GET_GPIO(maskb)
/*Get current PORT date (16-bit word)*/
-#if ANOMALY_05000311 || ANOMALY_05000323
#define GET_GPIO_P(name) \
unsigned short get_gpiop_ ## name(unsigned gpio) \
{ \
unsigned long flags; \
unsigned short ret; \
- local_irq_save(flags); \
- ret = (gpio_bankb[gpio_bank(gpio)]->name); \
- AWA_DUMMY_READ(name); \
- local_irq_restore(flags); \
+ if (ANOMALY_05000311 || ANOMALY_05000323) \
+ local_irq_save_hw(flags); \
+ ret = (gpio_array[gpio_bank(gpio)]->name); \
+ if (ANOMALY_05000311 || ANOMALY_05000323) { \
+ AWA_DUMMY_READ(name); \
+ local_irq_restore_hw(flags); \
+ } \
return ret; \
} \
EXPORT_SYMBOL(get_gpiop_ ## name);
-#else
-#define GET_GPIO_P(name) \
-unsigned short get_gpiop_ ## name(unsigned gpio) \
-{ \
- return (gpio_bankb[gpio_bank(gpio)]->name);\
-} \
-EXPORT_SYMBOL(get_gpiop_ ## name);
-#endif
GET_GPIO_P(data)
GET_GPIO_P(dir)
@@ -591,6 +478,26 @@ GET_GPIO_P(maskb)
#ifdef CONFIG_PM
+
+static unsigned short wakeup_map[GPIO_BANK_NUM];
+static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
+
+static const unsigned int sic_iwr_irqs[] = {
+#if defined(BF533_FAMILY)
+ IRQ_PROG_INTB
+#elif defined(BF537_FAMILY)
+ IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX
+#elif defined(BF538_FAMILY)
+ IRQ_PORTF_INTB
+#elif defined(BF527_FAMILY) || defined(BF518_FAMILY)
+ IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB
+#elif defined(BF561_FAMILY)
+ IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB
+#else
+# error no SIC_IWR defined
+#endif
+};
+
/***********************************************************
*
* FUNCTIONS: Blackfin PM Setup API
@@ -617,10 +524,10 @@ int gpio_pm_wakeup_request(unsigned gpio, unsigned char type)
if ((check_gpio(gpio) < 0) || !type)
return -EINVAL;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);
wakeup_flags_map[gpio] = type;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return 0;
}
@@ -633,11 +540,11 @@ void gpio_pm_wakeup_free(unsigned gpio)
if (check_gpio(gpio) < 0)
return;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
EXPORT_SYMBOL(gpio_pm_wakeup_free);
@@ -675,18 +582,18 @@ u32 bfin_pm_standby_setup(void)
mask = wakeup_map[gpio_bank(i)];
bank = gpio_bank(i);
- gpio_bank_saved[bank].maskb = gpio_bankb[bank]->maskb;
- gpio_bankb[bank]->maskb = 0;
+ gpio_bank_saved[bank].maskb = gpio_array[bank]->maskb;
+ gpio_array[bank]->maskb = 0;
if (mask) {
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
gpio_bank_saved[bank].fer = *port_fer[bank];
#endif
- gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
- gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
- gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
- gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
- gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
+ gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
+ gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
+ gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
+ gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
+ gpio_bank_saved[bank].both = gpio_array[bank]->both;
gpio_bank_saved[bank].reserved =
reserved_gpio_map[bank];
@@ -706,7 +613,7 @@ u32 bfin_pm_standby_setup(void)
}
bfin_internal_set_wake(sic_iwr_irqs[bank], 1);
- gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
+ gpio_array[bank]->maskb_set = wakeup_map[gpio_bank(i)];
}
}
@@ -724,21 +631,21 @@ void bfin_pm_standby_restore(void)
bank = gpio_bank(i);
if (mask) {
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
*port_fer[bank] = gpio_bank_saved[bank].fer;
#endif
- gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
- gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir;
- gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
- gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
- gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
+ gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
+ gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
+ gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
+ gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
+ gpio_array[bank]->both = gpio_bank_saved[bank].both;
reserved_gpio_map[bank] =
gpio_bank_saved[bank].reserved;
bfin_internal_set_wake(sic_iwr_irqs[bank], 0);
}
- gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
+ gpio_array[bank]->maskb = gpio_bank_saved[bank].maskb;
}
AWA_DUMMY_READ(maskb);
}
@@ -750,22 +657,22 @@ void bfin_gpio_pm_hibernate_suspend(void)
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
- gpio_bank_saved[bank].fer = *port_fer[bank];
-#ifdef BF527_FAMILY
- gpio_bank_saved[bank].mux = *port_mux[bank];
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+ gpio_bank_saved[bank].fer = *port_fer[bank];
+#if defined(BF527_FAMILY) || defined(BF518_FAMILY)
+ gpio_bank_saved[bank].mux = *port_mux[bank];
#else
- if (bank == 0)
- gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
+ if (bank == 0)
+ gpio_bank_saved[bank].mux = bfin_read_PORT_MUX();
#endif
#endif
- gpio_bank_saved[bank].data = gpio_bankb[bank]->data;
- gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
- gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
- gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
- gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
- gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
- gpio_bank_saved[bank].maska = gpio_bankb[bank]->maska;
+ gpio_bank_saved[bank].data = gpio_array[bank]->data;
+ gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
+ gpio_bank_saved[bank].polar = gpio_array[bank]->polar;
+ gpio_bank_saved[bank].dir = gpio_array[bank]->dir;
+ gpio_bank_saved[bank].edge = gpio_array[bank]->edge;
+ gpio_bank_saved[bank].both = gpio_array[bank]->both;
+ gpio_bank_saved[bank].maska = gpio_array[bank]->maska;
}
AWA_DUMMY_READ(maska);
@@ -776,27 +683,27 @@ void bfin_gpio_pm_hibernate_restore(void)
int i, bank;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
- bank = gpio_bank(i);
+ bank = gpio_bank(i);
-#if defined(BF527_FAMILY) || defined(BF537_FAMILY)
-#ifdef BF527_FAMILY
- *port_mux[bank] = gpio_bank_saved[bank].mux;
+#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY)
+#if defined(BF527_FAMILY) || defined(BF518_FAMILY)
+ *port_mux[bank] = gpio_bank_saved[bank].mux;
#else
- if (bank == 0)
- bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
+ if (bank == 0)
+ bfin_write_PORT_MUX(gpio_bank_saved[bank].mux);
#endif
- *port_fer[bank] = gpio_bank_saved[bank].fer;
+ *port_fer[bank] = gpio_bank_saved[bank].fer;
#endif
- gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
- gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir;
- gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
- gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
- gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
+ gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
+ gpio_array[bank]->dir = gpio_bank_saved[bank].dir;
+ gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
+ gpio_array[bank]->edge = gpio_bank_saved[bank].edge;
+ gpio_array[bank]->both = gpio_bank_saved[bank].both;
- gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data
- | gpio_bank_saved[bank].dir;
+ gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+ | gpio_bank_saved[bank].dir;
- gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska;
+ gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
}
AWA_DUMMY_READ(maska);
}
@@ -823,12 +730,12 @@ void bfin_gpio_pm_hibernate_suspend(void)
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
bank = gpio_bank(i);
- gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
- gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
- gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
- gpio_bank_saved[bank].data = gpio_array[bank]->port_data;
- gpio_bank_saved[bank].inen = gpio_array[bank]->port_inen;
- gpio_bank_saved[bank].dir = gpio_array[bank]->port_dir_set;
+ gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer;
+ gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux;
+ gpio_bank_saved[bank].data = gpio_array[bank]->data;
+ gpio_bank_saved[bank].data = gpio_array[bank]->data;
+ gpio_bank_saved[bank].inen = gpio_array[bank]->inen;
+ gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set;
}
}
@@ -837,21 +744,21 @@ void bfin_gpio_pm_hibernate_restore(void)
int i, bank;
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
- bank = gpio_bank(i);
-
- gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
- gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
- gpio_array[bank]->port_inen = gpio_bank_saved[bank].inen;
- gpio_array[bank]->port_dir_set = gpio_bank_saved[bank].dir;
- gpio_array[bank]->port_set = gpio_bank_saved[bank].data
- | gpio_bank_saved[bank].dir;
+ bank = gpio_bank(i);
+
+ gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux;
+ gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer;
+ gpio_array[bank]->inen = gpio_bank_saved[bank].inen;
+ gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir;
+ gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+ | gpio_bank_saved[bank].dir;
}
}
#endif
unsigned short get_gpio_dir(unsigned gpio)
{
- return (0x01 & (gpio_array[gpio_bank(gpio)]->port_dir_clear >> gpio_sub_n(gpio)));
+ return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
}
EXPORT_SYMBOL(get_gpio_dir);
@@ -873,7 +780,6 @@ EXPORT_SYMBOL(get_gpio_dir);
* MODIFICATION HISTORY :
**************************************************************/
-#ifdef BF548_FAMILY
int peripheral_request(unsigned short per, const char *label)
{
unsigned long flags;
@@ -889,31 +795,33 @@ int peripheral_request(unsigned short per, const char *label)
if (!(per & P_DEFINED))
return -ENODEV;
- if (check_gpio(ident) < 0)
- return -EINVAL;
-
- local_irq_save(flags);
+ local_irq_save_hw(flags);
- if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+ /* If a pin can be muxed as either GPIO or peripheral, make
+ * sure it is not already a GPIO pin when we request it.
+ */
+ if (unlikely(!check_gpio(ident) &&
+ reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
dump_stack();
printk(KERN_ERR
- "%s: Peripheral %d is already reserved as GPIO by %s !\n",
+ "%s: Peripheral %d is already reserved as GPIO by %s !\n",
__func__, ident, get_label(ident));
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return -EBUSY;
}
if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
- u16 funct = get_portmux(ident);
-
/*
* Pin functions like AMC address strobes my
* be requested and used by several drivers
*/
- if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
-
+#ifdef BF548_FAMILY
+ if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
+#else
+ if (!(per & P_MAYSHARE)) {
+#endif
/*
* Allow that the identical pin function can
* be requested from the same driver twice
@@ -926,7 +834,7 @@ int peripheral_request(unsigned short per, const char *label)
printk(KERN_ERR
"%s: Peripheral %d function %d is already reserved by %s !\n",
__func__, ident, P_FUNCT2MUX(per), get_label(ident));
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return -EBUSY;
}
}
@@ -934,89 +842,15 @@ int peripheral_request(unsigned short per, const char *label)
anyway:
reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
- portmux_setup(ident, P_FUNCT2MUX(per));
- port_setup(ident, PERIPHERAL_USAGE);
-
- local_irq_restore(flags);
- set_label(ident, label);
-
- return 0;
-}
-EXPORT_SYMBOL(peripheral_request);
-#else
-
-int peripheral_request(unsigned short per, const char *label)
-{
- unsigned long flags;
- unsigned short ident = P_IDENT(per);
-
- /*
- * Don't cares are pins with only one dedicated function
- */
-
- if (per & P_DONTCARE)
- return 0;
-
- if (!(per & P_DEFINED))
- return -ENODEV;
-
- local_irq_save(flags);
-
- if (!check_gpio(ident)) {
-
- if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
- dump_stack();
- printk(KERN_ERR
- "%s: Peripheral %d is already reserved as GPIO by %s !\n",
- __func__, ident, get_label(ident));
- local_irq_restore(flags);
- return -EBUSY;
- }
-
- }
-
- if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
-
- /*
- * Pin functions like AMC address strobes my
- * be requested and used by several drivers
- */
-
- if (!(per & P_MAYSHARE)) {
-
- /*
- * Allow that the identical pin function can
- * be requested from the same driver twice
- */
-
- if (cmp_label(ident, label) == 0)
- goto anyway;
-
- dump_stack();
- printk(KERN_ERR
- "%s: Peripheral %d function %d is already"
- " reserved by %s !\n",
- __func__, ident, P_FUNCT2MUX(per),
- get_label(ident));
- local_irq_restore(flags);
- return -EBUSY;
- }
-
- }
-
- anyway:
- portmux_setup(per, P_FUNCT2MUX(per));
-
+ portmux_setup(per);
port_setup(ident, PERIPHERAL_USAGE);
- reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
set_label(ident, label);
return 0;
}
EXPORT_SYMBOL(peripheral_request);
-#endif
int peripheral_request_list(const unsigned short per[], const char *label)
{
@@ -1050,13 +884,10 @@ void peripheral_free(unsigned short per)
if (!(per & P_DEFINED))
return;
- if (check_gpio(ident) < 0)
- return;
-
- local_irq_save(flags);
+ local_irq_save_hw(flags);
if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return;
}
@@ -1067,7 +898,7 @@ void peripheral_free(unsigned short per)
set_label(ident, "free");
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
EXPORT_SYMBOL(peripheral_free);
@@ -1094,14 +925,14 @@ EXPORT_SYMBOL(peripheral_free_list);
* MODIFICATION HISTORY :
**************************************************************/
-int gpio_request(unsigned gpio, const char *label)
+int bfin_gpio_request(unsigned gpio, const char *label)
{
unsigned long flags;
if (check_gpio(gpio) < 0)
return -EINVAL;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
/*
* Allow that the identical GPIO can
@@ -1110,15 +941,15 @@ int gpio_request(unsigned gpio, const char *label)
*/
if (cmp_label(gpio, label) == 0) {
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return 0;
}
if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
dump_stack();
printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved by %s !\n",
- gpio, get_label(gpio));
- local_irq_restore(flags);
+ gpio, get_label(gpio));
+ local_irq_restore_hw(flags);
return -EBUSY;
}
if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
@@ -1126,34 +957,45 @@ int gpio_request(unsigned gpio, const char *label)
printk(KERN_ERR
"bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
gpio, get_label(gpio));
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return -EBUSY;
}
+ if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!"
+ " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio);
+ }
+#ifndef BF548_FAMILY
+ else { /* Reset POLAR setting when acquiring a gpio for the first time */
+ set_gpio_polar(gpio, 0);
+ }
+#endif
reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+ set_label(gpio, label);
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
port_setup(gpio, GPIO_USAGE);
- set_label(gpio, label);
return 0;
}
-EXPORT_SYMBOL(gpio_request);
+EXPORT_SYMBOL(bfin_gpio_request);
-void gpio_free(unsigned gpio)
+void bfin_gpio_free(unsigned gpio)
{
unsigned long flags;
if (check_gpio(gpio) < 0)
return;
- local_irq_save(flags);
+ might_sleep();
+
+ local_irq_save_hw(flags);
if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
dump_stack();
gpio_error(gpio);
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return;
}
@@ -1161,117 +1003,126 @@ void gpio_free(unsigned gpio)
set_label(gpio, "free");
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
-EXPORT_SYMBOL(gpio_free);
-
+EXPORT_SYMBOL(bfin_gpio_free);
-#ifdef BF548_FAMILY
-int gpio_direction_input(unsigned gpio)
+int bfin_gpio_irq_request(unsigned gpio, const char *label)
{
unsigned long flags;
- if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
- gpio_error(gpio);
+ if (check_gpio(gpio) < 0)
return -EINVAL;
+
+ local_irq_save_hw(flags);
+
+ if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ dump_stack();
+ printk(KERN_ERR
+ "bfin-gpio: GPIO %d is already reserved as gpio-irq !\n",
+ gpio);
+ local_irq_restore_hw(flags);
+ return -EBUSY;
+ }
+ if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ dump_stack();
+ printk(KERN_ERR
+ "bfin-gpio: GPIO %d is already reserved as Peripheral by %s !\n",
+ gpio, get_label(gpio));
+ local_irq_restore_hw(flags);
+ return -EBUSY;
}
+ if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))
+ printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved by %s! "
+ "(Documentation/blackfin/bfin-gpio-notes.txt)\n",
+ gpio, get_label(gpio));
- local_irq_save(flags);
- gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
- gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
- local_irq_restore(flags);
+ reserved_gpio_irq_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+ set_label(gpio, label);
+
+ local_irq_restore_hw(flags);
+
+ port_setup(gpio, GPIO_USAGE);
return 0;
}
-EXPORT_SYMBOL(gpio_direction_input);
-int gpio_direction_output(unsigned gpio, int value)
+void bfin_gpio_irq_free(unsigned gpio)
{
unsigned long flags;
- if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ if (check_gpio(gpio) < 0)
+ return;
+
+ local_irq_save_hw(flags);
+
+ if (unlikely(!(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+ dump_stack();
gpio_error(gpio);
- return -EINVAL;
+ local_irq_restore_hw(flags);
+ return;
}
- local_irq_save(flags);
- gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
- gpio_set_value(gpio, value);
- gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
- local_irq_restore(flags);
+ reserved_gpio_irq_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
+ set_label(gpio, "free");
-void gpio_set_value(unsigned gpio, int arg)
-{
- if (arg)
- gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
- else
- gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
+ local_irq_restore_hw(flags);
}
-EXPORT_SYMBOL(gpio_set_value);
-int gpio_get_value(unsigned gpio)
+static inline void __bfin_gpio_direction_input(unsigned gpio)
{
- return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
+#ifdef BF548_FAMILY
+ gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
+#else
+ gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
+#endif
+ gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
}
-EXPORT_SYMBOL(gpio_get_value);
-void bfin_gpio_irq_prepare(unsigned gpio)
+int bfin_gpio_direction_input(unsigned gpio)
{
unsigned long flags;
- port_setup(gpio, GPIO_USAGE);
+ if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ gpio_error(gpio);
+ return -EINVAL;
+ }
- local_irq_save(flags);
- gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
- gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
- local_irq_restore(flags);
-}
+ local_irq_save_hw(flags);
+ __bfin_gpio_direction_input(gpio);
+ AWA_DUMMY_READ(inen);
+ local_irq_restore_hw(flags);
-#else
+ return 0;
+}
+EXPORT_SYMBOL(bfin_gpio_direction_input);
-int gpio_get_value(unsigned gpio)
+void bfin_gpio_irq_prepare(unsigned gpio)
{
+#ifdef BF548_FAMILY
unsigned long flags;
- int ret;
+#endif
- if (unlikely(get_gpio_edge(gpio))) {
- local_irq_save(flags);
- set_gpio_edge(gpio, 0);
- ret = get_gpio_data(gpio);
- set_gpio_edge(gpio, 1);
- local_irq_restore(flags);
+ port_setup(gpio, GPIO_USAGE);
- return ret;
- } else
- return get_gpio_data(gpio);
+#ifdef BF548_FAMILY
+ local_irq_save_hw(flags);
+ __bfin_gpio_direction_input(gpio);
+ local_irq_restore_hw(flags);
+#endif
}
-EXPORT_SYMBOL(gpio_get_value);
-
-int gpio_direction_input(unsigned gpio)
+void bfin_gpio_set_value(unsigned gpio, int arg)
{
- unsigned long flags;
-
- if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
- gpio_error(gpio);
- return -EINVAL;
- }
-
- local_irq_save(flags);
- gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
- gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
- AWA_DUMMY_READ(inen);
- local_irq_restore(flags);
-
- return 0;
+ if (arg)
+ gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
+ else
+ gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
}
-EXPORT_SYMBOL(gpio_direction_input);
+EXPORT_SYMBOL(bfin_gpio_set_value);
-int gpio_direction_output(unsigned gpio, int value)
+int bfin_gpio_direction_output(unsigned gpio, int value)
{
unsigned long flags;
@@ -1280,21 +1131,43 @@ int gpio_direction_output(unsigned gpio, int value)
return -EINVAL;
}
- local_irq_save(flags);
- gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
+ local_irq_save_hw(flags);
- if (value)
- gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
- else
- gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
+ gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
+ gpio_set_value(gpio, value);
+#ifdef BF548_FAMILY
+ gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
+#else
+ gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
+#endif
- gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
AWA_DUMMY_READ(dir);
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return 0;
}
-EXPORT_SYMBOL(gpio_direction_output);
+EXPORT_SYMBOL(bfin_gpio_direction_output);
+
+int bfin_gpio_get_value(unsigned gpio)
+{
+#ifdef BF548_FAMILY
+ return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
+#else
+ unsigned long flags;
+
+ if (unlikely(get_gpio_edge(gpio))) {
+ int ret;
+ local_irq_save_hw(flags);
+ set_gpio_edge(gpio, 0);
+ ret = get_gpio_data(gpio);
+ set_gpio_edge(gpio, 1);
+ local_irq_restore_hw(flags);
+ return ret;
+ } else
+ return get_gpio_data(gpio);
+#endif
+}
+EXPORT_SYMBOL(bfin_gpio_get_value);
/* If we are booting from SPI and our board lacks a strong enough pull up,
* the core can reset and execute the bootrom faster than the resistor can
@@ -1306,35 +1179,30 @@ EXPORT_SYMBOL(gpio_direction_output);
* lives here as we need to force all the GPIO states w/out going through
* BUG() checks and such.
*/
-void bfin_gpio_reset_spi0_ssel1(void)
+void bfin_reset_boot_spi_cs(unsigned short pin)
{
- u16 gpio = P_IDENT(P_SPI0_SSEL1);
-
+ unsigned short gpio = P_IDENT(pin);
port_setup(gpio, GPIO_USAGE);
- gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
+ gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
AWA_DUMMY_READ(data_set);
udelay(1);
}
-void bfin_gpio_irq_prepare(unsigned gpio)
-{
- port_setup(gpio, GPIO_USAGE);
-}
-
-#endif /*BF548_FAMILY */
-
#if defined(CONFIG_PROC_FS)
static int gpio_proc_read(char *buf, char **start, off_t offset,
int len, int *unused_i, void *unused_v)
{
- int c, outlen = 0;
+ int c, irq, gpio, outlen = 0;
for (c = 0; c < MAX_RESOURCES; c++) {
- if (!check_gpio(c) && (reserved_gpio_map[gpio_bank(c)] & gpio_bit(c)))
- len = sprintf(buf, "GPIO_%d: %s \t\tGPIO %s\n", c,
- get_label(c), get_gpio_dir(c) ? "OUTPUT" : "INPUT");
+ irq = reserved_gpio_irq_map[gpio_bank(c)] & gpio_bit(c);
+ gpio = reserved_gpio_map[gpio_bank(c)] & gpio_bit(c);
+ if (!check_gpio(c) && (gpio || irq))
+ len = sprintf(buf, "GPIO_%d: \t%s%s \t\tGPIO %s\n", c,
+ get_label(c), (gpio && irq) ? " *" : "",
+ get_gpio_dir(c) ? "OUTPUT" : "INPUT");
else if (reserved_peri_map[gpio_bank(c)] & gpio_bit(c))
- len = sprintf(buf, "GPIO_%d: %s \t\tPeripheral\n", c, get_label(c));
+ len = sprintf(buf, "GPIO_%d: \t%s \t\tPeripheral\n", c, get_label(c));
else
continue;
buf += len;
@@ -1354,3 +1222,53 @@ static __init int gpio_register_proc(void)
}
__initcall(gpio_register_proc);
#endif
+
+#ifdef CONFIG_GPIOLIB
+int bfin_gpiolib_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+ return bfin_gpio_direction_input(gpio);
+}
+
+int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
+{
+ return bfin_gpio_direction_output(gpio, level);
+}
+
+int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio)
+{
+ return bfin_gpio_get_value(gpio);
+}
+
+void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value)
+{
+ return bfin_gpio_set_value(gpio, value);
+}
+
+int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio)
+{
+ return bfin_gpio_request(gpio, chip->label);
+}
+
+void bfin_gpiolib_gpio_free(struct gpio_chip *chip, unsigned gpio)
+{
+ return bfin_gpio_free(gpio);
+}
+
+static struct gpio_chip bfin_chip = {
+ .label = "Blackfin-GPIOlib",
+ .direction_input = bfin_gpiolib_direction_input,
+ .get = bfin_gpiolib_get_value,
+ .direction_output = bfin_gpiolib_direction_output,
+ .set = bfin_gpiolib_set_value,
+ .request = bfin_gpiolib_gpio_request,
+ .free = bfin_gpiolib_gpio_free,
+ .base = 0,
+ .ngpio = MAX_BLACKFIN_GPIOS,
+};
+
+static int __init bfin_gpiolib_setup(void)
+{
+ return gpiochip_add(&bfin_chip);
+}
+arch_initcall(bfin_gpiolib_setup);
+#endif
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
index 4367330909b2..01f917d58b59 100644
--- a/arch/blackfin/kernel/bfin_ksyms.c
+++ b/arch/blackfin/kernel/bfin_ksyms.c
@@ -1,52 +1,25 @@
/*
- * File: arch/blackfin/kernel/bfin_ksyms.c
- * Based on: none - original work
- * Author:
+ * arch/blackfin/kernel/bfin_ksyms.c - exports for random symbols
*
- * Created:
- * Description:
+ * Copyright 2004-2008 Analog Devices Inc.
*
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
-#include <linux/irq.h>
#include <linux/uaccess.h>
-#include <asm/checksum.h>
#include <asm/cacheflush.h>
-/* platform dependent support */
-
-EXPORT_SYMBOL(__ioremap);
-
-EXPORT_SYMBOL(ip_fast_csum);
-
-EXPORT_SYMBOL(kernel_thread);
-
-EXPORT_SYMBOL(is_in_rom);
+/* Allow people to have their own Blackfin exception handler in a module */
EXPORT_SYMBOL(bfin_return_from_exception);
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
+/* All the Blackfin cache functions: mach-common/cache.S */
+EXPORT_SYMBOL(blackfin_dcache_invalidate_range);
+EXPORT_SYMBOL(blackfin_icache_dcache_flush_range);
+EXPORT_SYMBOL(blackfin_icache_flush_range);
+EXPORT_SYMBOL(blackfin_dcache_flush_range);
+EXPORT_SYMBOL(blackfin_dflush_page);
/* The following are special because they're not called
* explicitly (the C compiler generates them). Fortunately,
@@ -74,8 +47,6 @@ extern void __modsi3(void);
extern void __muldi3(void);
extern void __udivsi3(void);
extern void __umodsi3(void);
-
-/* gcc lib functions */
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__umulsi3_highpart);
@@ -87,6 +58,7 @@ EXPORT_SYMBOL(__muldi3);
EXPORT_SYMBOL(__udivsi3);
EXPORT_SYMBOL(__umodsi3);
+/* Input/output symbols: lib/{in,out}s.S */
EXPORT_SYMBOL(outsb);
EXPORT_SYMBOL(insb);
EXPORT_SYMBOL(outsw);
@@ -96,20 +68,39 @@ EXPORT_SYMBOL(insw_8);
EXPORT_SYMBOL(outsl);
EXPORT_SYMBOL(insl);
EXPORT_SYMBOL(insl_16);
-EXPORT_SYMBOL(irq_flags);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(blackfin_dcache_invalidate_range);
-EXPORT_SYMBOL(blackfin_icache_dcache_flush_range);
-EXPORT_SYMBOL(blackfin_icache_flush_range);
-EXPORT_SYMBOL(blackfin_dcache_flush_range);
-EXPORT_SYMBOL(blackfin_dflush_page);
-EXPORT_SYMBOL(csum_partial);
-EXPORT_SYMBOL(__init_begin);
-EXPORT_SYMBOL(__init_end);
-EXPORT_SYMBOL(_ebss_l1);
-EXPORT_SYMBOL(_stext_l1);
-EXPORT_SYMBOL(_etext_l1);
-EXPORT_SYMBOL(_sdata_l1);
-EXPORT_SYMBOL(_ebss_b_l1);
-EXPORT_SYMBOL(_sdata_b_l1);
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(__raw_atomic_update_asm);
+EXPORT_SYMBOL(__raw_atomic_clear_asm);
+EXPORT_SYMBOL(__raw_atomic_set_asm);
+EXPORT_SYMBOL(__raw_atomic_xor_asm);
+EXPORT_SYMBOL(__raw_atomic_test_asm);
+EXPORT_SYMBOL(__raw_xchg_1_asm);
+EXPORT_SYMBOL(__raw_xchg_2_asm);
+EXPORT_SYMBOL(__raw_xchg_4_asm);
+EXPORT_SYMBOL(__raw_cmpxchg_1_asm);
+EXPORT_SYMBOL(__raw_cmpxchg_2_asm);
+EXPORT_SYMBOL(__raw_cmpxchg_4_asm);
+EXPORT_SYMBOL(__raw_spin_is_locked_asm);
+EXPORT_SYMBOL(__raw_spin_lock_asm);
+EXPORT_SYMBOL(__raw_spin_trylock_asm);
+EXPORT_SYMBOL(__raw_spin_unlock_asm);
+EXPORT_SYMBOL(__raw_read_lock_asm);
+EXPORT_SYMBOL(__raw_read_trylock_asm);
+EXPORT_SYMBOL(__raw_read_unlock_asm);
+EXPORT_SYMBOL(__raw_write_lock_asm);
+EXPORT_SYMBOL(__raw_write_trylock_asm);
+EXPORT_SYMBOL(__raw_write_unlock_asm);
+EXPORT_SYMBOL(__raw_bit_set_asm);
+EXPORT_SYMBOL(__raw_bit_clear_asm);
+EXPORT_SYMBOL(__raw_bit_toggle_asm);
+EXPORT_SYMBOL(__raw_bit_test_asm);
+EXPORT_SYMBOL(__raw_bit_test_set_asm);
+EXPORT_SYMBOL(__raw_bit_test_clear_asm);
+EXPORT_SYMBOL(__raw_bit_test_toggle_asm);
+EXPORT_SYMBOL(__raw_uncached_fetch_asm);
+#ifdef __ARCH_SYNC_CORE_DCACHE
+EXPORT_SYMBOL(__raw_smp_mark_barrier_asm);
+EXPORT_SYMBOL(__raw_smp_check_barrier_asm);
+#endif
+#endif
diff --git a/arch/blackfin/kernel/cplb-mpu/Makefile b/arch/blackfin/kernel/cplb-mpu/Makefile
index 286b69357f97..7d70d3bf3212 100644
--- a/arch/blackfin/kernel/cplb-mpu/Makefile
+++ b/arch/blackfin/kernel/cplb-mpu/Makefile
@@ -4,5 +4,7 @@
obj-y := cplbinit.o cacheinit.o cplbmgr.o
-obj-$(CONFIG_CPLB_INFO) += cplbinfo.o
-
+CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
+ -ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
+ -ffixed-M0 -ffixed-M1 -ffixed-M2 -ffixed-M3 \
+ -ffixed-B0 -ffixed-B1 -ffixed-B2 -ffixed-B3
diff --git a/arch/blackfin/kernel/cplb-mpu/cacheinit.c b/arch/blackfin/kernel/cplb-mpu/cacheinit.c
index a8b712a24c59..c6ff947f9d37 100644
--- a/arch/blackfin/kernel/cplb-mpu/cacheinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cacheinit.c
@@ -25,7 +25,7 @@
#include <asm/cplbinit.h>
#if defined(CONFIG_BFIN_ICACHE)
-void __init bfin_icache_init(void)
+void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
{
unsigned long ctrl;
int i;
@@ -43,7 +43,7 @@ void __init bfin_icache_init(void)
#endif
#if defined(CONFIG_BFIN_DCACHE)
-void __init bfin_dcache_init(void)
+void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
{
unsigned long ctrl;
int i;
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c b/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
deleted file mode 100644
index 822beefa3a4b..000000000000
--- a/arch/blackfin/kernel/cplb-mpu/cplbinfo.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * File: arch/blackfin/mach-common/cplbinfo.c
- * Based on:
- * Author: Sonic Zhang <sonic.zhang@analog.com>
- *
- * Created: Jan. 2005
- * Description: Display CPLB status
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/uaccess.h>
-
-#include <asm/current.h>
-#include <asm/system.h>
-#include <asm/cplb.h>
-#include <asm/cplbinit.h>
-#include <asm/blackfin.h>
-
-static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };
-
-static char *cplb_print_entry(char *buf, struct cplb_entry *tbl, int switched)
-{
- int i;
- buf += sprintf(buf, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n");
- for (i = 0; i < MAX_CPLBS; i++) {
- unsigned long data = tbl[i].data;
- unsigned long addr = tbl[i].addr;
- if (!(data & CPLB_VALID))
- continue;
-
- buf +=
- sprintf(buf,
- "%d\t0x%08lx\t%06lx\t%s\t%c\t%c\t%c\t%c\n",
- i, addr, data,
- page_size_string_table[(data & 0x30000) >> 16],
- (data & CPLB_USER_RD) ? 'Y' : 'N',
- (data & CPLB_USER_WR) ? 'Y' : 'N',
- (data & CPLB_SUPV_WR) ? 'Y' : 'N',
- i < switched ? 'N' : 'Y');
- }
- buf += sprintf(buf, "\n");
-
- return buf;
-}
-
-int cplbinfo_proc_output(char *buf)
-{
- char *p;
-
- p = buf;
-
- p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
-
- if (bfin_read_IMEM_CONTROL() & ENICPLB) {
- p += sprintf(p, "Instruction CPLB entry:\n");
- p = cplb_print_entry(p, icplb_tbl, first_switched_icplb);
- } else
- p += sprintf(p, "Instruction CPLB is disabled.\n\n");
-
- if (1 || bfin_read_DMEM_CONTROL() & ENDCPLB) {
- p += sprintf(p, "Data CPLB entry:\n");
- p = cplb_print_entry(p, dcplb_tbl, first_switched_dcplb);
- } else
- p += sprintf(p, "Data CPLB is disabled.\n");
-
- p += sprintf(p, "ICPLB miss: %d\nICPLB supervisor miss: %d\n",
- nr_icplb_miss, nr_icplb_supv_miss);
- p += sprintf(p, "DCPLB miss: %d\nDCPLB protection fault:%d\n",
- nr_dcplb_miss, nr_dcplb_prot);
- p += sprintf(p, "CPLB flushes: %d\n",
- nr_cplb_flush);
-
- return p - buf;
-}
-
-static int cplbinfo_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
-
- len = cplbinfo_proc_output(page);
- if (len <= off + count)
- *eof = 1;
- *start = page + off;
- len -= off;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
- return len;
-}
-
-static int __init cplbinfo_init(void)
-{
- struct proc_dir_entry *entry;
-
- entry = create_proc_entry("cplbinfo", 0, NULL);
- if (!entry)
- return -ENOMEM;
-
- entry->read_proc = cplbinfo_read_proc;
- entry->data = NULL;
-
- return 0;
-}
-
-static void __exit cplbinfo_exit(void)
-{
- remove_proc_entry("cplbinfo", NULL);
-}
-
-module_init(cplbinfo_init);
-module_exit(cplbinfo_exit);
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
index 55af729f8495..3e329a6ce041 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c
@@ -25,18 +25,19 @@
#include <asm/blackfin.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>
+#include <asm/mem_map.h>
#if ANOMALY_05000263
# error the MPU will not function safely while Anomaly 05000263 applies
#endif
-struct cplb_entry icplb_tbl[MAX_CPLBS];
-struct cplb_entry dcplb_tbl[MAX_CPLBS];
+struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS];
+struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS];
int first_switched_icplb, first_switched_dcplb;
int first_mask_dcplb;
-void __init generate_cplb_tables(void)
+void __init generate_cplb_tables_cpu(unsigned int cpu)
{
int i_d, i_i;
unsigned long addr;
@@ -55,16 +56,15 @@ void __init generate_cplb_tables(void)
d_cache |= CPLB_L1_AOW | CPLB_WT;
#endif
#endif
+
i_d = i_i = 0;
/* Set up the zero page. */
- dcplb_tbl[i_d].addr = 0;
- dcplb_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
+ dcplb_tbl[cpu][i_d].addr = 0;
+ dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
-#if 0
- icplb_tbl[i_i].addr = 0;
- icplb_tbl[i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB;
-#endif
+ icplb_tbl[cpu][i_i].addr = 0;
+ icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_1KB;
/* Cover kernel memory with 4M pages. */
addr = 0;
@@ -72,28 +72,28 @@ void __init generate_cplb_tables(void)
i_data = i_cache | CPLB_VALID | CPLB_PORTPRIO | PAGE_SIZE_4MB;
for (; addr < memory_start; addr += 4 * 1024 * 1024) {
- dcplb_tbl[i_d].addr = addr;
- dcplb_tbl[i_d++].data = d_data;
- icplb_tbl[i_i].addr = addr;
- icplb_tbl[i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0);
+ dcplb_tbl[cpu][i_d].addr = addr;
+ dcplb_tbl[cpu][i_d++].data = d_data;
+ icplb_tbl[cpu][i_i].addr = addr;
+ icplb_tbl[cpu][i_i++].data = i_data | (addr == 0 ? CPLB_USER_RD : 0);
}
/* Cover L1 memory. One 4M area for code and data each is enough. */
#if L1_DATA_A_LENGTH > 0 || L1_DATA_B_LENGTH > 0
- dcplb_tbl[i_d].addr = L1_DATA_A_START;
- dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+ dcplb_tbl[cpu][i_d].addr = get_l1_data_a_start_cpu(cpu);
+ dcplb_tbl[cpu][i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
#endif
#if L1_CODE_LENGTH > 0
- icplb_tbl[i_i].addr = L1_CODE_START;
- icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
+ icplb_tbl[cpu][i_i].addr = get_l1_code_start_cpu(cpu);
+ icplb_tbl[cpu][i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
#endif
/* Cover L2 memory */
#if L2_LENGTH > 0
- dcplb_tbl[i_d].addr = L2_START;
- dcplb_tbl[i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
- icplb_tbl[i_i].addr = L2_START;
- icplb_tbl[i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
+ dcplb_tbl[cpu][i_d].addr = L2_START;
+ dcplb_tbl[cpu][i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB;
+ icplb_tbl[cpu][i_i].addr = L2_START;
+ icplb_tbl[cpu][i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB;
#endif
first_mask_dcplb = i_d;
@@ -101,7 +101,11 @@ void __init generate_cplb_tables(void)
first_switched_icplb = i_i;
while (i_d < MAX_CPLBS)
- dcplb_tbl[i_d++].data = 0;
+ dcplb_tbl[cpu][i_d++].data = 0;
while (i_i < MAX_CPLBS)
- icplb_tbl[i_i++].data = 0;
+ icplb_tbl[cpu][i_i++].data = 0;
+}
+
+void generate_cplb_tables_all(void)
+{
}
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index baa52e261f0d..87463ce87f5a 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -25,15 +25,21 @@
#include <asm/cplbinit.h>
#include <asm/mmu_context.h>
-#define FAULT_RW (1 << 16)
-#define FAULT_USERSUPV (1 << 17)
+/*
+ * WARNING
+ *
+ * This file is compiled with certain -ffixed-reg options. We have to
+ * make sure not to call any functions here that could clobber these
+ * registers.
+ */
int page_mask_nelts;
int page_mask_order;
-unsigned long *current_rwx_mask;
+unsigned long *current_rwx_mask[NR_CPUS];
-int nr_dcplb_miss, nr_icplb_miss, nr_icplb_supv_miss, nr_dcplb_prot;
-int nr_cplb_flush;
+int nr_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS];
+int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
+int nr_cplb_flush[NR_CPUS];
static inline void disable_dcplb(void)
{
@@ -98,42 +104,42 @@ static inline int write_permitted(int status, unsigned long data)
}
/* Counters to implement round-robin replacement. */
-static int icplb_rr_index, dcplb_rr_index;
+static int icplb_rr_index[NR_CPUS], dcplb_rr_index[NR_CPUS];
/*
* Find an ICPLB entry to be evicted and return its index.
*/
-static int evict_one_icplb(void)
+static int evict_one_icplb(unsigned int cpu)
{
int i;
for (i = first_switched_icplb; i < MAX_CPLBS; i++)
- if ((icplb_tbl[i].data & CPLB_VALID) == 0)
+ if ((icplb_tbl[cpu][i].data & CPLB_VALID) == 0)
return i;
- i = first_switched_icplb + icplb_rr_index;
+ i = first_switched_icplb + icplb_rr_index[cpu];
if (i >= MAX_CPLBS) {
i -= MAX_CPLBS - first_switched_icplb;
- icplb_rr_index -= MAX_CPLBS - first_switched_icplb;
+ icplb_rr_index[cpu] -= MAX_CPLBS - first_switched_icplb;
}
- icplb_rr_index++;
+ icplb_rr_index[cpu]++;
return i;
}
-static int evict_one_dcplb(void)
+static int evict_one_dcplb(unsigned int cpu)
{
int i;
for (i = first_switched_dcplb; i < MAX_CPLBS; i++)
- if ((dcplb_tbl[i].data & CPLB_VALID) == 0)
+ if ((dcplb_tbl[cpu][i].data & CPLB_VALID) == 0)
return i;
- i = first_switched_dcplb + dcplb_rr_index;
+ i = first_switched_dcplb + dcplb_rr_index[cpu];
if (i >= MAX_CPLBS) {
i -= MAX_CPLBS - first_switched_dcplb;
- dcplb_rr_index -= MAX_CPLBS - first_switched_dcplb;
+ dcplb_rr_index[cpu] -= MAX_CPLBS - first_switched_dcplb;
}
- dcplb_rr_index++;
+ dcplb_rr_index[cpu]++;
return i;
}
-static noinline int dcplb_miss(void)
+static noinline int dcplb_miss(unsigned int cpu)
{
unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
int status = bfin_read_DCPLB_STATUS();
@@ -141,7 +147,7 @@ static noinline int dcplb_miss(void)
int idx;
unsigned long d_data;
- nr_dcplb_miss++;
+ nr_dcplb_miss[cpu]++;
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE
@@ -168,25 +174,25 @@ static noinline int dcplb_miss(void)
} else if (addr >= _ramend) {
d_data |= CPLB_USER_RD | CPLB_USER_WR;
} else {
- mask = current_rwx_mask;
+ mask = current_rwx_mask[cpu];
if (mask) {
int page = addr >> PAGE_SHIFT;
- int offs = page >> 5;
+ int idx = page >> 5;
int bit = 1 << (page & 31);
- if (mask[offs] & bit)
+ if (mask[idx] & bit)
d_data |= CPLB_USER_RD;
mask += page_mask_nelts;
- if (mask[offs] & bit)
+ if (mask[idx] & bit)
d_data |= CPLB_USER_WR;
}
}
- idx = evict_one_dcplb();
+ idx = evict_one_dcplb(cpu);
addr &= PAGE_MASK;
- dcplb_tbl[idx].addr = addr;
- dcplb_tbl[idx].data = d_data;
+ dcplb_tbl[cpu][idx].addr = addr;
+ dcplb_tbl[cpu][idx].data = d_data;
disable_dcplb();
bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
@@ -196,21 +202,21 @@ static noinline int dcplb_miss(void)
return 0;
}
-static noinline int icplb_miss(void)
+static noinline int icplb_miss(unsigned int cpu)
{
unsigned long addr = bfin_read_ICPLB_FAULT_ADDR();
int status = bfin_read_ICPLB_STATUS();
int idx;
unsigned long i_data;
- nr_icplb_miss++;
+ nr_icplb_miss[cpu]++;
/* If inside the uncached DMA region, fault. */
if (addr >= _ramend - DMA_UNCACHED_REGION && addr < _ramend)
return CPLB_PROT_VIOL;
if (status & FAULT_USERSUPV)
- nr_icplb_supv_miss++;
+ nr_icplb_supv_miss[cpu]++;
/*
* First, try to find a CPLB that matches this address. If we
@@ -218,8 +224,8 @@ static noinline int icplb_miss(void)
* that the instruction crosses a page boundary.
*/
for (idx = first_switched_icplb; idx < MAX_CPLBS; idx++) {
- if (icplb_tbl[idx].data & CPLB_VALID) {
- unsigned long this_addr = icplb_tbl[idx].addr;
+ if (icplb_tbl[cpu][idx].data & CPLB_VALID) {
+ unsigned long this_addr = icplb_tbl[cpu][idx].addr;
if (this_addr <= addr && this_addr + PAGE_SIZE > addr) {
addr += PAGE_SIZE;
break;
@@ -257,23 +263,23 @@ static noinline int icplb_miss(void)
* Otherwise, check the x bitmap of the current process.
*/
if (!(status & FAULT_USERSUPV)) {
- unsigned long *mask = current_rwx_mask;
+ unsigned long *mask = current_rwx_mask[cpu];
if (mask) {
int page = addr >> PAGE_SHIFT;
- int offs = page >> 5;
+ int idx = page >> 5;
int bit = 1 << (page & 31);
mask += 2 * page_mask_nelts;
- if (mask[offs] & bit)
+ if (mask[idx] & bit)
i_data |= CPLB_USER_RD;
}
}
}
- idx = evict_one_icplb();
+ idx = evict_one_icplb(cpu);
addr &= PAGE_MASK;
- icplb_tbl[idx].addr = addr;
- icplb_tbl[idx].data = i_data;
+ icplb_tbl[cpu][idx].addr = addr;
+ icplb_tbl[cpu][idx].data = i_data;
disable_icplb();
bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
@@ -283,19 +289,19 @@ static noinline int icplb_miss(void)
return 0;
}
-static noinline int dcplb_protection_fault(void)
+static noinline int dcplb_protection_fault(unsigned int cpu)
{
int status = bfin_read_DCPLB_STATUS();
- nr_dcplb_prot++;
+ nr_dcplb_prot[cpu]++;
if (status & FAULT_RW) {
int idx = faulting_cplb_index(status);
- unsigned long data = dcplb_tbl[idx].data;
+ unsigned long data = dcplb_tbl[cpu][idx].data;
if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
write_permitted(status, data)) {
data |= CPLB_DIRTY;
- dcplb_tbl[idx].data = data;
+ dcplb_tbl[cpu][idx].data = data;
bfin_write32(DCPLB_DATA0 + idx * 4, data);
return 0;
}
@@ -306,44 +312,45 @@ static noinline int dcplb_protection_fault(void)
int cplb_hdr(int seqstat, struct pt_regs *regs)
{
int cause = seqstat & 0x3f;
+ unsigned int cpu = smp_processor_id();
switch (cause) {
case 0x23:
- return dcplb_protection_fault();
+ return dcplb_protection_fault(cpu);
case 0x2C:
- return icplb_miss();
+ return icplb_miss(cpu);
case 0x26:
- return dcplb_miss();
+ return dcplb_miss(cpu);
default:
return 1;
}
}
-void flush_switched_cplbs(void)
+void flush_switched_cplbs(unsigned int cpu)
{
int i;
unsigned long flags;
- nr_cplb_flush++;
+ nr_cplb_flush[cpu]++;
- local_irq_save(flags);
+ local_irq_save_hw(flags);
disable_icplb();
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
- icplb_tbl[i].data = 0;
+ icplb_tbl[cpu][i].data = 0;
bfin_write32(ICPLB_DATA0 + i * 4, 0);
}
enable_icplb();
disable_dcplb();
for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
- dcplb_tbl[i].data = 0;
+ dcplb_tbl[cpu][i].data = 0;
bfin_write32(DCPLB_DATA0 + i * 4, 0);
}
enable_dcplb();
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
-void set_mask_dcplbs(unsigned long *masks)
+void set_mask_dcplbs(unsigned long *masks, unsigned int cpu)
{
int i;
unsigned long addr = (unsigned long)masks;
@@ -351,12 +358,12 @@ void set_mask_dcplbs(unsigned long *masks)
unsigned long flags;
if (!masks) {
- current_rwx_mask = masks;
+ current_rwx_mask[cpu] = masks;
return;
}
- local_irq_save(flags);
- current_rwx_mask = masks;
+ local_irq_save_hw(flags);
+ current_rwx_mask[cpu] = masks;
d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB;
#ifdef CONFIG_BFIN_DCACHE
@@ -368,12 +375,12 @@ void set_mask_dcplbs(unsigned long *masks)
disable_dcplb();
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
- dcplb_tbl[i].addr = addr;
- dcplb_tbl[i].data = d_data;
+ dcplb_tbl[cpu][i].addr = addr;
+ dcplb_tbl[cpu][i].data = d_data;
bfin_write32(DCPLB_DATA0 + i * 4, d_data);
bfin_write32(DCPLB_ADDR0 + i * 4, addr);
addr += PAGE_SIZE;
}
enable_dcplb();
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
diff --git a/arch/blackfin/kernel/cplb-nompu/Makefile b/arch/blackfin/kernel/cplb-nompu/Makefile
index d36ea9b5382e..7d70d3bf3212 100644
--- a/arch/blackfin/kernel/cplb-nompu/Makefile
+++ b/arch/blackfin/kernel/cplb-nompu/Makefile
@@ -2,7 +2,9 @@
# arch/blackfin/kernel/cplb-nompu/Makefile
#
-obj-y := cplbinit.o cacheinit.o cplbhdlr.o cplbmgr.o
-
-obj-$(CONFIG_CPLB_INFO) += cplbinfo.o
+obj-y := cplbinit.o cacheinit.o cplbmgr.o
+CFLAGS_cplbmgr.o := -ffixed-I0 -ffixed-I1 -ffixed-I2 -ffixed-I3 \
+ -ffixed-L0 -ffixed-L1 -ffixed-L2 -ffixed-L3 \
+ -ffixed-M0 -ffixed-M1 -ffixed-M2 -ffixed-M3 \
+ -ffixed-B0 -ffixed-B1 -ffixed-B2 -ffixed-B3
diff --git a/arch/blackfin/kernel/cplb-nompu/cacheinit.c b/arch/blackfin/kernel/cplb-nompu/cacheinit.c
index bd0831592c2c..c6ff947f9d37 100644
--- a/arch/blackfin/kernel/cplb-nompu/cacheinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cacheinit.c
@@ -25,19 +25,15 @@
#include <asm/cplbinit.h>
#if defined(CONFIG_BFIN_ICACHE)
-void __init bfin_icache_init(void)
+void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl)
{
- unsigned long *table = icplb_table;
unsigned long ctrl;
int i;
+ SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
- unsigned long addr = *table++;
- unsigned long data = *table++;
- if (addr == (unsigned long)-1)
- break;
- bfin_write32(ICPLB_ADDR0 + i * 4, addr);
- bfin_write32(ICPLB_DATA0 + i * 4, data);
+ bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr);
+ bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data);
}
ctrl = bfin_read_IMEM_CONTROL();
ctrl |= IMC | ENICPLB;
@@ -47,20 +43,17 @@ void __init bfin_icache_init(void)
#endif
#if defined(CONFIG_BFIN_DCACHE)
-void __init bfin_dcache_init(void)
+void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl)
{
- unsigned long *table = dcplb_table;
unsigned long ctrl;
int i;
+ SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
- unsigned long addr = *table++;
- unsigned long data = *table++;
- if (addr == (unsigned long)-1)
- break;
- bfin_write32(DCPLB_ADDR0 + i * 4, addr);
- bfin_write32(DCPLB_DATA0 + i * 4, data);
+ bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr);
+ bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data);
}
+
ctrl = bfin_read_DMEM_CONTROL();
ctrl |= DMEM_CNTR;
bfin_write_DMEM_CONTROL(ctrl);
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S b/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S
deleted file mode 100644
index ecbabc0a1fed..000000000000
--- a/arch/blackfin/kernel/cplb-nompu/cplbhdlr.S
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * File: arch/blackfin/mach-common/cplbhdlr.S
- * Based on:
- * Author: LG Soft India
- *
- * Created: ?
- * Description: CPLB exception handler
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/linkage.h>
-#include <asm/cplb.h>
-#include <asm/entry.h>
-
-#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
-.section .l1.text
-#else
-.text
-#endif
-
-.type _cplb_mgr, STT_FUNC;
-.type _panic_cplb_error, STT_FUNC;
-
-.align 2
-
-ENTRY(__cplb_hdr)
- R2 = SEQSTAT;
-
- /* Mask the contents of SEQSTAT and leave only EXCAUSE in R2 */
- R2 <<= 26;
- R2 >>= 26;
-
- R1 = 0x23; /* Data access CPLB protection violation */
- CC = R2 == R1;
- IF !CC JUMP .Lnot_data_write;
- R0 = 2; /* is a write to data space*/
- JUMP .Lis_icplb_miss;
-
-.Lnot_data_write:
- R1 = 0x2C; /* CPLB miss on an instruction fetch */
- CC = R2 == R1;
- R0 = 0; /* is_data_miss == False*/
- IF CC JUMP .Lis_icplb_miss;
-
- R1 = 0x26;
- CC = R2 == R1;
- IF !CC JUMP .Lunknown;
-
- R0 = 1; /* is_data_miss == True*/
-
-.Lis_icplb_miss:
-
-#if defined(CONFIG_BFIN_ICACHE) || defined(CONFIG_BFIN_DCACHE)
-# if defined(CONFIG_BFIN_ICACHE) && !defined(CONFIG_BFIN_DCACHE)
- R1 = CPLB_ENABLE_ICACHE;
-# endif
-# if !defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE)
- R1 = CPLB_ENABLE_DCACHE;
-# endif
-# if defined(CONFIG_BFIN_ICACHE) && defined(CONFIG_BFIN_DCACHE)
- R1 = CPLB_ENABLE_DCACHE | CPLB_ENABLE_ICACHE;
-# endif
-#else
- R1 = 0;
-#endif
-
- [--SP] = RETS;
- CALL _cplb_mgr;
- RETS = [SP++];
- CC = R0 == 0;
- IF !CC JUMP .Lnot_replaced;
- RTS;
-
-/*
- * Diagnostic exception handlers
- */
-.Lunknown:
- R0 = CPLB_UNKNOWN_ERR;
- JUMP .Lcplb_error;
-
-.Lnot_replaced:
- CC = R0 == CPLB_NO_UNLOCKED;
- IF !CC JUMP .Lnext_check;
- R0 = CPLB_NO_UNLOCKED;
- JUMP .Lcplb_error;
-
-.Lnext_check:
- CC = R0 == CPLB_NO_ADDR_MATCH;
- IF !CC JUMP .Lnext_check2;
- R0 = CPLB_NO_ADDR_MATCH;
- JUMP .Lcplb_error;
-
-.Lnext_check2:
- CC = R0 == CPLB_PROT_VIOL;
- IF !CC JUMP .Lstrange_return_from_cplb_mgr;
- R0 = CPLB_PROT_VIOL;
- JUMP .Lcplb_error;
-
-.Lstrange_return_from_cplb_mgr:
- IDLE;
- CSYNC;
- JUMP .Lstrange_return_from_cplb_mgr;
-
-.Lcplb_error:
- R1 = sp;
- SP += -12;
- call _panic_cplb_error;
- SP += 12;
- JUMP.L _handle_bad_cplb;
-
-ENDPROC(__cplb_hdr)
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c b/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
deleted file mode 100644
index 1e74f0b97996..000000000000
--- a/arch/blackfin/kernel/cplb-nompu/cplbinfo.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * File: arch/blackfin/mach-common/cplbinfo.c
- * Based on:
- * Author: Sonic Zhang <sonic.zhang@analog.com>
- *
- * Created: Jan. 2005
- * Description: Display CPLB status
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/uaccess.h>
-
-#include <asm/cplbinit.h>
-#include <asm/blackfin.h>
-
-#define CPLB_I 1
-#define CPLB_D 2
-
-#define SYNC_SYS SSYNC()
-#define SYNC_CORE CSYNC()
-
-#define CPLB_BIT_PAGESIZE 0x30000
-
-static int page_size_table[4] = {
- 0x00000400, /* 1K */
- 0x00001000, /* 4K */
- 0x00100000, /* 1M */
- 0x00400000 /* 4M */
-};
-
-static char page_size_string_table[][4] = { "1K", "4K", "1M", "4M" };
-
-static int cplb_find_entry(unsigned long *cplb_addr,
- unsigned long *cplb_data, unsigned long addr,
- unsigned long data)
-{
- int ii;
-
- for (ii = 0; ii < 16; ii++)
- if (addr >= cplb_addr[ii] && addr < cplb_addr[ii] +
- page_size_table[(cplb_data[ii] & CPLB_BIT_PAGESIZE) >> 16]
- && (cplb_data[ii] == data))
- return ii;
-
- return -1;
-}
-
-static char *cplb_print_entry(char *buf, int type)
-{
- unsigned long *p_addr = dpdt_table;
- unsigned long *p_data = dpdt_table + 1;
- unsigned long *p_icount = dpdt_swapcount_table;
- unsigned long *p_ocount = dpdt_swapcount_table + 1;
- unsigned long *cplb_addr = (unsigned long *)DCPLB_ADDR0;
- unsigned long *cplb_data = (unsigned long *)DCPLB_DATA0;
- int entry = 0, used_cplb = 0;
-
- if (type == CPLB_I) {
- buf += sprintf(buf, "Instruction CPLB entry:\n");
- p_addr = ipdt_table;
- p_data = ipdt_table + 1;
- p_icount = ipdt_swapcount_table;
- p_ocount = ipdt_swapcount_table + 1;
- cplb_addr = (unsigned long *)ICPLB_ADDR0;
- cplb_data = (unsigned long *)ICPLB_DATA0;
- } else
- buf += sprintf(buf, "Data CPLB entry:\n");
-
- buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\tiCount\toCount\n");
-
- while (*p_addr != 0xffffffff) {
- entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data);
- if (entry >= 0)
- used_cplb |= 1 << entry;
-
- buf +=
- sprintf(buf,
- "0x%08lx\t0x%05lx\t%s\t%c\t%c\t%2d\t%ld\t%ld\n",
- *p_addr, *p_data,
- page_size_string_table[(*p_data & 0x30000) >> 16],
- (*p_data & CPLB_VALID) ? 'Y' : 'N',
- (*p_data & CPLB_LOCK) ? 'Y' : 'N', entry, *p_icount,
- *p_ocount);
-
- p_addr += 2;
- p_data += 2;
- p_icount += 2;
- p_ocount += 2;
- }
-
- if (used_cplb != 0xffff) {
- buf += sprintf(buf, "Unused/mismatched CPLBs:\n");
-
- for (entry = 0; entry < 16; entry++)
- if (0 == ((1 << entry) & used_cplb)) {
- int flags = cplb_data[entry];
- buf +=
- sprintf(buf,
- "%2d: 0x%08lx\t0x%05x\t%s\t%c\t%c\n",
- entry, cplb_addr[entry], flags,
- page_size_string_table[(flags &
- 0x30000) >>
- 16],
- (flags & CPLB_VALID) ? 'Y' : 'N',
- (flags & CPLB_LOCK) ? 'Y' : 'N');
- }
- }
-
- buf += sprintf(buf, "\n");
-
- return buf;
-}
-
-static int cplbinfo_proc_output(char *buf)
-{
- char *p;
-
- p = buf;
-
- p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
-
- if (bfin_read_IMEM_CONTROL() & ENICPLB)
- p = cplb_print_entry(p, CPLB_I);
- else
- p += sprintf(p, "Instruction CPLB is disabled.\n\n");
-
- if (bfin_read_DMEM_CONTROL() & ENDCPLB)
- p = cplb_print_entry(p, CPLB_D);
- else
- p += sprintf(p, "Data CPLB is disabled.\n");
-
- return p - buf;
-}
-
-static int cplbinfo_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
-
- len = cplbinfo_proc_output(page);
- if (len <= off + count)
- *eof = 1;
- *start = page + off;
- len -= off;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
- return len;
-}
-
-static int __init cplbinfo_init(void)
-{
- struct proc_dir_entry *entry;
-
- entry = create_proc_entry("cplbinfo", 0, NULL);
- if (!entry)
- return -ENOMEM;
-
- entry->read_proc = cplbinfo_read_proc;
- entry->data = NULL;
-
- return 0;
-}
-
-static void __exit cplbinfo_exit(void)
-{
- remove_proc_entry("cplbinfo", NULL);
-}
-
-module_init(cplbinfo_init);
-module_exit(cplbinfo_exit);
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
index 2debc900e246..0e28f7595733 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c
@@ -20,445 +20,152 @@
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
#include <linux/module.h>
#include <asm/blackfin.h>
#include <asm/cacheflush.h>
#include <asm/cplb.h>
#include <asm/cplbinit.h>
+#include <asm/mem_map.h>
-#define CPLB_MEM CONFIG_MAX_MEM_SIZE
-
-/*
-* Number of required data CPLB switchtable entries
-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
-* approx 16 for smaller 1MB page size CPLBs for allignment purposes
-* 1 for L1 Data Memory
-* possibly 1 for L2 Data Memory
-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
-* 1 for ASYNC Memory
-*/
-#define MAX_SWITCH_D_CPLBS (((CPLB_MEM / 4) + 16 + 1 + 1 + 1 \
- + ASYNC_MEMORY_CPLB_COVERAGE) * 2)
-
-/*
-* Number of required instruction CPLB switchtable entries
-* MEMSIZE / 4 (we mostly install 4M page size CPLBs
-* approx 12 for smaller 1MB page size CPLBs for allignment purposes
-* 1 for L1 Instruction Memory
-* possibly 1 for L2 Instruction Memory
-* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
-*/
-#define MAX_SWITCH_I_CPLBS (((CPLB_MEM / 4) + 12 + 1 + 1 + 1) * 2)
-
-
-u_long icplb_table[MAX_CPLBS + 1];
-u_long dcplb_table[MAX_CPLBS + 1];
-
-#ifdef CONFIG_CPLB_SWITCH_TAB_L1
-# define PDT_ATTR __attribute__((l1_data))
-#else
-# define PDT_ATTR
-#endif
-
-u_long ipdt_table[MAX_SWITCH_I_CPLBS + 1] PDT_ATTR;
-u_long dpdt_table[MAX_SWITCH_D_CPLBS + 1] PDT_ATTR;
+struct cplb_entry icplb_tbl[NR_CPUS][MAX_CPLBS] PDT_ATTR;
+struct cplb_entry dcplb_tbl[NR_CPUS][MAX_CPLBS] PDT_ATTR;
-#ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS] PDT_ATTR;
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS] PDT_ATTR;
-#endif
+int first_switched_icplb PDT_ATTR;
+int first_switched_dcplb PDT_ATTR;
-struct s_cplb {
- struct cplb_tab init_i;
- struct cplb_tab init_d;
- struct cplb_tab switch_i;
- struct cplb_tab switch_d;
-};
+struct cplb_boundary dcplb_bounds[9] PDT_ATTR;
+struct cplb_boundary icplb_bounds[7] PDT_ATTR;
-#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
-static struct cplb_desc cplb_data[] = {
- {
- .start = 0,
- .end = SIZE_1K,
- .psize = SIZE_1K,
- .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
- .i_conf = SDRAM_OOPS,
- .d_conf = SDRAM_OOPS,
-#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
- .valid = 1,
-#else
- .valid = 0,
-#endif
- .name = "Zero Pointer Guard Page",
- },
- {
- .start = L1_CODE_START,
- .end = L1_CODE_START + L1_CODE_LENGTH,
- .psize = SIZE_4M,
- .attr = INITIAL_T | SWITCH_T | I_CPLB,
- .i_conf = L1_IMEMORY,
- .d_conf = 0,
- .valid = 1,
- .name = "L1 I-Memory",
- },
- {
- .start = L1_DATA_A_START,
- .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
- .psize = SIZE_4M,
- .attr = INITIAL_T | SWITCH_T | D_CPLB,
- .i_conf = 0,
- .d_conf = L1_DMEMORY,
-#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
- .valid = 1,
-#else
- .valid = 0,
-#endif
- .name = "L1 D-Memory",
- },
- {
- .start = 0,
- .end = 0, /* dynamic */
- .psize = 0,
- .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
- .i_conf = SDRAM_IGENERIC,
- .d_conf = SDRAM_DGENERIC,
- .valid = 1,
- .name = "Kernel Memory",
- },
- {
- .start = 0, /* dynamic */
- .end = 0, /* dynamic */
- .psize = 0,
- .attr = INITIAL_T | SWITCH_T | D_CPLB,
- .i_conf = SDRAM_IGENERIC,
- .d_conf = SDRAM_DNON_CHBL,
- .valid = 1,
- .name = "uClinux MTD Memory",
- },
- {
- .start = 0, /* dynamic */
- .end = 0, /* dynamic */
- .psize = SIZE_1M,
- .attr = INITIAL_T | SWITCH_T | D_CPLB,
- .d_conf = SDRAM_DNON_CHBL,
- .valid = 1,
- .name = "Uncached DMA Zone",
- },
- {
- .start = 0, /* dynamic */
- .end = 0, /* dynamic */
- .psize = 0,
- .attr = SWITCH_T | D_CPLB,
- .i_conf = 0, /* dynamic */
- .d_conf = 0, /* dynamic */
- .valid = 1,
- .name = "Reserved Memory",
- },
- {
- .start = ASYNC_BANK0_BASE,
- .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
- .psize = 0,
- .attr = SWITCH_T | D_CPLB,
- .d_conf = SDRAM_EBIU,
- .valid = 1,
- .name = "Asynchronous Memory Banks",
- },
- {
- .start = L2_START,
- .end = L2_START + L2_LENGTH,
- .psize = SIZE_1M,
- .attr = SWITCH_T | I_CPLB | D_CPLB,
- .i_conf = L2_IMEMORY,
- .d_conf = L2_DMEMORY,
- .valid = (L2_LENGTH > 0),
- .name = "L2 Memory",
- },
- {
- .start = BOOT_ROM_START,
- .end = BOOT_ROM_START + BOOT_ROM_LENGTH,
- .psize = SIZE_1M,
- .attr = SWITCH_T | I_CPLB | D_CPLB,
- .i_conf = SDRAM_IGENERIC,
- .d_conf = SDRAM_DGENERIC,
- .valid = 1,
- .name = "On-Chip BootROM",
- },
-};
+int icplb_nr_bounds PDT_ATTR;
+int dcplb_nr_bounds PDT_ATTR;
-static u16 __init lock_kernel_check(u32 start, u32 end)
+void __init generate_cplb_tables_cpu(unsigned int cpu)
{
- if (start >= (u32)_end || end <= (u32)_stext)
- return 0;
+ int i_d, i_i;
+ unsigned long addr;
- /* This cplb block overlapped with kernel area. */
- return IN_KERNEL;
-}
+ struct cplb_entry *d_tbl = dcplb_tbl[cpu];
+ struct cplb_entry *i_tbl = icplb_tbl[cpu];
-static unsigned short __init
-fill_cplbtab(struct cplb_tab *table,
- unsigned long start, unsigned long end,
- unsigned long block_size, unsigned long cplb_data)
-{
- int i;
+ printk(KERN_INFO "NOMPU: setting up cplb tables\n");
- switch (block_size) {
- case SIZE_4M:
- i = 3;
- break;
- case SIZE_1M:
- i = 2;
- break;
- case SIZE_4K:
- i = 1;
- break;
- case SIZE_1K:
- default:
- i = 0;
- break;
- }
-
- cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
-
- while ((start < end) && (table->pos < table->size)) {
+ i_d = i_i = 0;
- table->tab[table->pos++] = start;
+ /* Set up the zero page. */
+ d_tbl[i_d].addr = 0;
+ d_tbl[i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB;
- if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
- table->tab[table->pos++] =
- cplb_data | CPLB_LOCK | CPLB_DIRTY;
- else
- table->tab[table->pos++] = cplb_data;
+ /* Cover kernel memory with 4M pages. */
+ addr = 0;
- start += block_size;
+ for (; addr < memory_start; addr += 4 * 1024 * 1024) {
+ d_tbl[i_d].addr = addr;
+ d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_4MB;
+ i_tbl[i_i].addr = addr;
+ i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_4MB;
}
- return 0;
-}
-static unsigned short __init
-close_cplbtab(struct cplb_tab *table)
-{
-
- while (table->pos < table->size) {
-
- table->tab[table->pos++] = 0;
- table->tab[table->pos++] = 0; /* !CPLB_VALID */
+ /* Cover L1 memory. One 4M area for code and data each is enough. */
+ if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
+ d_tbl[i_d].addr = L1_DATA_A_START;
+ d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
}
- return 0;
-}
+ i_tbl[i_i].addr = L1_CODE_START;
+ i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
-/* helper function */
-static void __init
-__fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
-{
- if (cplb_data[i].psize) {
- fill_cplbtab(t,
- cplb_data[i].start,
- cplb_data[i].end,
- cplb_data[i].psize,
- cplb_data[i].i_conf);
- } else {
-#if defined(CONFIG_BFIN_ICACHE)
- if (ANOMALY_05000263 && i == SDRAM_KERN) {
- fill_cplbtab(t,
- cplb_data[i].start,
- cplb_data[i].end,
- SIZE_4M,
- cplb_data[i].i_conf);
- } else
-#endif
- {
- fill_cplbtab(t,
- cplb_data[i].start,
- a_start,
- SIZE_1M,
- cplb_data[i].i_conf);
- fill_cplbtab(t,
- a_start,
- a_end,
- SIZE_4M,
- cplb_data[i].i_conf);
- fill_cplbtab(t, a_end,
- cplb_data[i].end,
- SIZE_1M,
- cplb_data[i].i_conf);
- }
- }
-}
+ first_switched_dcplb = i_d;
+ first_switched_icplb = i_i;
-static void __init
-__fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
-{
- if (cplb_data[i].psize) {
- fill_cplbtab(t,
- cplb_data[i].start,
- cplb_data[i].end,
- cplb_data[i].psize,
- cplb_data[i].d_conf);
- } else {
- fill_cplbtab(t,
- cplb_data[i].start,
- a_start, SIZE_1M,
- cplb_data[i].d_conf);
- fill_cplbtab(t, a_start,
- a_end, SIZE_4M,
- cplb_data[i].d_conf);
- fill_cplbtab(t, a_end,
- cplb_data[i].end,
- SIZE_1M,
- cplb_data[i].d_conf);
- }
+ BUG_ON(first_switched_dcplb > MAX_CPLBS);
+ BUG_ON(first_switched_icplb > MAX_CPLBS);
+
+ while (i_d < MAX_CPLBS)
+ d_tbl[i_d++].data = 0;
+ while (i_i < MAX_CPLBS)
+ i_tbl[i_i++].data = 0;
}
-void __init generate_cplb_tables(void)
+void __init generate_cplb_tables_all(void)
{
+ int i_d, i_i;
- u16 i, j, process;
- u32 a_start, a_end, as, ae, as_1m;
-
- struct cplb_tab *t_i = NULL;
- struct cplb_tab *t_d = NULL;
- struct s_cplb cplb;
-
- printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n");
-
- cplb.init_i.size = MAX_CPLBS;
- cplb.init_d.size = MAX_CPLBS;
- cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
- cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
-
- cplb.init_i.pos = 0;
- cplb.init_d.pos = 0;
- cplb.switch_i.pos = 0;
- cplb.switch_d.pos = 0;
-
- cplb.init_i.tab = icplb_table;
- cplb.init_d.tab = dcplb_table;
- cplb.switch_i.tab = ipdt_table;
- cplb.switch_d.tab = dpdt_table;
-
- cplb_data[SDRAM_KERN].end = memory_end;
-
+ i_d = 0;
+ /* Normal RAM, including MTD FS. */
#ifdef CONFIG_MTD_UCLINUX
- cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
- cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
- cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
-# if defined(CONFIG_ROMFS_FS)
- cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
-
- /*
- * The ROMFS_FS size is often not multiple of 1MB.
- * This can cause multiple CPLB sets covering the same memory area.
- * This will then cause multiple CPLB hit exceptions.
- * Workaround: We ensure a contiguous memory area by extending the kernel
- * memory section over the mtd section.
- * For ROMFS_FS memory must be covered with ICPLBs anyways.
- * So there is no difference between kernel and mtd memory setup.
- */
-
- cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
- cplb_data[SDRAM_RAM_MTD].valid = 0;
-
-# endif
+ dcplb_bounds[i_d].eaddr = memory_mtd_start + mtd_size;
#else
- cplb_data[SDRAM_RAM_MTD].valid = 0;
+ dcplb_bounds[i_d].eaddr = memory_end;
#endif
+ dcplb_bounds[i_d++].data = SDRAM_DGENERIC;
+ /* DMA uncached region. */
+ if (DMA_UNCACHED_REGION) {
+ dcplb_bounds[i_d].eaddr = _ramend;
+ dcplb_bounds[i_d++].data = SDRAM_DNON_CHBL;
+ }
+ if (_ramend != physical_mem_end) {
+ /* Reserved memory. */
+ dcplb_bounds[i_d].eaddr = physical_mem_end;
+ dcplb_bounds[i_d++].data = (reserved_mem_dcache_on ?
+ SDRAM_DGENERIC : SDRAM_DNON_CHBL);
+ }
+ /* Addressing hole up to the async bank. */
+ dcplb_bounds[i_d].eaddr = ASYNC_BANK0_BASE;
+ dcplb_bounds[i_d++].data = 0;
+ /* ASYNC banks. */
+ dcplb_bounds[i_d].eaddr = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE;
+ dcplb_bounds[i_d++].data = SDRAM_EBIU;
+ /* Addressing hole up to BootROM. */
+ dcplb_bounds[i_d].eaddr = BOOT_ROM_START;
+ dcplb_bounds[i_d++].data = 0;
+ /* BootROM -- largest one should be less than 1 meg. */
+ dcplb_bounds[i_d].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
+ dcplb_bounds[i_d++].data = SDRAM_DGENERIC;
+ if (L2_LENGTH) {
+ /* Addressing hole up to L2 SRAM. */
+ dcplb_bounds[i_d].eaddr = L2_START;
+ dcplb_bounds[i_d++].data = 0;
+ /* L2 SRAM. */
+ dcplb_bounds[i_d].eaddr = L2_START + L2_LENGTH;
+ dcplb_bounds[i_d++].data = L2_DMEMORY;
+ }
+ dcplb_nr_bounds = i_d;
+ BUG_ON(dcplb_nr_bounds > ARRAY_SIZE(dcplb_bounds));
- cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
- cplb_data[SDRAM_DMAZ].end = _ramend;
-
- cplb_data[RES_MEM].start = _ramend;
- cplb_data[RES_MEM].end = physical_mem_end;
-
- if (reserved_mem_dcache_on)
- cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
- else
- cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
-
- if (reserved_mem_icache_on)
- cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
- else
- cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
-
- for (i = ZERO_P; i < ARRAY_SIZE(cplb_data); ++i) {
- if (!cplb_data[i].valid)
- continue;
-
- as_1m = cplb_data[i].start % SIZE_1M;
-
- /* We need to make sure all sections are properly 1M aligned
- * However between Kernel Memory and the Kernel mtd section, depending on the
- * rootfs size, there can be overlapping memory areas.
- */
-
- if (as_1m && i != L1I_MEM && i != L1D_MEM) {
+ i_i = 0;
+ /* Normal RAM, including MTD FS. */
#ifdef CONFIG_MTD_UCLINUX
- if (i == SDRAM_RAM_MTD) {
- if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
- cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
- else
- cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
- } else
+ icplb_bounds[i_i].eaddr = memory_mtd_start + mtd_size;
+#else
+ icplb_bounds[i_i].eaddr = memory_end;
#endif
- printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
- cplb_data[i].name, cplb_data[i].start);
- }
-
- as = cplb_data[i].start % SIZE_4M;
- ae = cplb_data[i].end % SIZE_4M;
-
- if (as)
- a_start = cplb_data[i].start + (SIZE_4M - (as));
- else
- a_start = cplb_data[i].start;
-
- a_end = cplb_data[i].end - ae;
-
- for (j = INITIAL_T; j <= SWITCH_T; j++) {
-
- switch (j) {
- case INITIAL_T:
- if (cplb_data[i].attr & INITIAL_T) {
- t_i = &cplb.init_i;
- t_d = &cplb.init_d;
- process = 1;
- } else
- process = 0;
- break;
- case SWITCH_T:
- if (cplb_data[i].attr & SWITCH_T) {
- t_i = &cplb.switch_i;
- t_d = &cplb.switch_d;
- process = 1;
- } else
- process = 0;
- break;
- default:
- process = 0;
- break;
- }
-
- if (!process)
- continue;
- if (cplb_data[i].attr & I_CPLB)
- __fill_code_cplbtab(t_i, i, a_start, a_end);
-
- if (cplb_data[i].attr & D_CPLB)
- __fill_data_cplbtab(t_d, i, a_start, a_end);
- }
+ icplb_bounds[i_i++].data = SDRAM_IGENERIC;
+ /* DMA uncached region. */
+ if (DMA_UNCACHED_REGION) {
+ icplb_bounds[i_i].eaddr = _ramend;
+ icplb_bounds[i_i++].data = 0;
}
-
-/* close tables */
-
- close_cplbtab(&cplb.init_i);
- close_cplbtab(&cplb.init_d);
-
- cplb.init_i.tab[cplb.init_i.pos] = -1;
- cplb.init_d.tab[cplb.init_d.pos] = -1;
- cplb.switch_i.tab[cplb.switch_i.pos] = -1;
- cplb.switch_d.tab[cplb.switch_d.pos] = -1;
-
+ if (_ramend != physical_mem_end) {
+ /* Reserved memory. */
+ icplb_bounds[i_i].eaddr = physical_mem_end;
+ icplb_bounds[i_i++].data = (reserved_mem_icache_on ?
+ SDRAM_IGENERIC : SDRAM_INON_CHBL);
+ }
+ /* Addressing hole up to BootROM. */
+ icplb_bounds[i_i].eaddr = BOOT_ROM_START;
+ icplb_bounds[i_i++].data = 0;
+ /* BootROM -- largest one should be less than 1 meg. */
+ icplb_bounds[i_i].eaddr = BOOT_ROM_START + (1 * 1024 * 1024);
+ icplb_bounds[i_i++].data = SDRAM_IGENERIC;
+ if (L2_LENGTH) {
+ /* Addressing hole up to L2 SRAM, including the async bank. */
+ icplb_bounds[i_i].eaddr = L2_START;
+ icplb_bounds[i_i++].data = 0;
+ /* L2 SRAM. */
+ icplb_bounds[i_i].eaddr = L2_START + L2_LENGTH;
+ icplb_bounds[i_i++].data = L2_IMEMORY;
+ }
+ icplb_nr_bounds = i_i;
+ BUG_ON(icplb_nr_bounds > ARRAY_SIZE(icplb_bounds));
}
-
-#endif
-
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.S b/arch/blackfin/kernel/cplb-nompu/cplbmgr.S
deleted file mode 100644
index f5cf3accef37..000000000000
--- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.S
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * File: arch/blackfin/mach-common/cplbmgtr.S
- * Based on:
- * Author: LG Soft India
- *
- * Created: ?
- * Description: CPLB replacement routine for CPLB mismatch
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/* Usage: int _cplb_mgr(is_data_miss,int enable_cache)
- * is_data_miss==2 => Mark as Dirty, write to the clean data page
- * is_data_miss==1 => Replace a data CPLB.
- * is_data_miss==0 => Replace an instruction CPLB.
- *
- * Returns:
- * CPLB_RELOADED => Successfully updated CPLB table.
- * CPLB_NO_UNLOCKED => All CPLBs are locked, so cannot be evicted.
- * This indicates that the CPLBs in the configuration
- * tablei are badly configured, as this should never
- * occur.
- * CPLB_NO_ADDR_MATCH => The address being accessed, that triggered the
- * exception, is not covered by any of the CPLBs in
- * the configuration table. The application is
- * presumably misbehaving.
- * CPLB_PROT_VIOL => The address being accessed, that triggered the
- * exception, was not a first-write to a clean Write
- * Back Data page, and so presumably is a genuine
- * violation of the page's protection attributes.
- * The application is misbehaving.
- */
-
-#include <linux/linkage.h>
-#include <asm/blackfin.h>
-#include <asm/cplb.h>
-
-#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
-.section .l1.text
-#else
-.text
-#endif
-
-.align 2;
-ENTRY(_cplb_mgr)
-
- [--SP]=( R7:4,P5:3 );
-
- CC = R0 == 2;
- IF CC JUMP .Ldcplb_write;
-
- CC = R0 == 0;
- IF !CC JUMP .Ldcplb_miss_compare;
-
- /* ICPLB Miss Exception. We need to choose one of the
- * currently-installed CPLBs, and replace it with one
- * from the configuration table.
- */
-
- /* A multi-word instruction can cross a page boundary. This means the
- * first part of the instruction can be in a valid page, but the
- * second part is not, and hence generates the instruction miss.
- * However, the fault address is for the start of the instruction,
- * not the part that's in the bad page. Therefore, we have to check
- * whether the fault address applies to a page that is already present
- * in the table.
- */
-
- P4.L = LO(ICPLB_FAULT_ADDR);
- P4.H = HI(ICPLB_FAULT_ADDR);
-
- P1 = 16;
- P5.L = _page_size_table;
- P5.H = _page_size_table;
-
- P0.L = LO(ICPLB_DATA0);
- P0.H = HI(ICPLB_DATA0);
- R4 = [P4]; /* Get faulting address*/
- R6 = 64; /* Advance past the fault address, which*/
- R6 = R6 + R4; /* we'll use if we find a match*/
- R3 = ((16 << 8) | 2); /* Extract mask, two bits at posn 16 */
-
- R5 = 0;
-.Lisearch:
-
- R1 = [P0-0x100]; /* Address for this CPLB */
-
- R0 = [P0++]; /* Info for this CPLB*/
- CC = BITTST(R0,0); /* Is the CPLB valid?*/
- IF !CC JUMP .Lnomatch; /* Skip it, if not.*/
- CC = R4 < R1(IU); /* If fault address less than page start*/
- IF CC JUMP .Lnomatch; /* then skip this one.*/
- R2 = EXTRACT(R0,R3.L) (Z); /* Get page size*/
- P1 = R2;
- P1 = P5 + (P1<<2); /* index into page-size table*/
- R2 = [P1]; /* Get the page size*/
- R1 = R1 + R2; /* and add to page start, to get page end*/
- CC = R4 < R1(IU); /* and see whether fault addr is in page.*/
- IF !CC R4 = R6; /* If so, advance the address and finish loop.*/
- IF !CC JUMP .Lisearch_done;
-.Lnomatch:
- /* Go around again*/
- R5 += 1;
- CC = BITTST(R5, 4); /* i.e CC = R5 >= 16*/
- IF !CC JUMP .Lisearch;
-
-.Lisearch_done:
- I0 = R4; /* Fault address we'll search for*/
-
- /* set up pointers */
- P0.L = LO(ICPLB_DATA0);
- P0.H = HI(ICPLB_DATA0);
-
- /* The replacement procedure for ICPLBs */
-
- P4.L = LO(IMEM_CONTROL);
- P4.H = HI(IMEM_CONTROL);
-
- /* Turn off CPLBs while we work, necessary according to HRM before
- * modifying CPLB descriptors
- */
- R5 = [P4]; /* Control Register*/
- BITCLR(R5,ENICPLB_P);
- CLI R1;
- SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
- .align 8;
- [P4] = R5;
- SSYNC;
- STI R1;
-
- R1 = -1; /* end point comparison */
- R3 = 16; /* counter */
-
- /* Search through CPLBs for first non-locked entry */
- /* Overwrite it by moving everyone else up by 1 */
-.Licheck_lock:
- R0 = [P0++];
- R3 = R3 + R1;
- CC = R3 == R1;
- IF CC JUMP .Lall_locked;
- CC = BITTST(R0, 0); /* an invalid entry is good */
- IF !CC JUMP .Lifound_victim;
- CC = BITTST(R0,1); /* but a locked entry isn't */
- IF CC JUMP .Licheck_lock;
-
-.Lifound_victim:
-#ifdef CONFIG_CPLB_INFO
- R7 = [P0 - 0x104];
- P2.L = _ipdt_table;
- P2.H = _ipdt_table;
- P3.L = _ipdt_swapcount_table;
- P3.H = _ipdt_swapcount_table;
- P3 += -4;
-.Licount:
- R2 = [P2]; /* address from config table */
- P2 += 8;
- P3 += 8;
- CC = R2==-1;
- IF CC JUMP .Licount_done;
- CC = R7==R2;
- IF !CC JUMP .Licount;
- R7 = [P3];
- R7 += 1;
- [P3] = R7;
- CSYNC;
-.Licount_done:
-#endif
- LC0=R3;
- LSETUP(.Lis_move,.Lie_move) LC0;
-.Lis_move:
- R0 = [P0];
- [P0 - 4] = R0;
- R0 = [P0 - 0x100];
- [P0-0x104] = R0;
-.Lie_move:
- P0+=4;
-
- /* Clear ICPLB_DATA15, in case we don't find a replacement
- * otherwise, we would have a duplicate entry, and will crash
- */
- R0 = 0;
- [P0 - 4] = R0;
-
- /* We've made space in the ICPLB table, so that ICPLB15
- * is now free to be overwritten. Next, we have to determine
- * which CPLB we need to install, from the configuration
- * table. This is a matter of getting the start-of-page
- * addresses and page-lengths from the config table, and
- * determining whether the fault address falls within that
- * range.
- */
-
- P2.L = _ipdt_table;
- P2.H = _ipdt_table;
-#ifdef CONFIG_CPLB_INFO
- P3.L = _ipdt_swapcount_table;
- P3.H = _ipdt_swapcount_table;
- P3 += -8;
-#endif
- P0.L = _page_size_table;
- P0.H = _page_size_table;
-
- /* Retrieve our fault address (which may have been advanced
- * because the faulting instruction crossed a page boundary).
- */
-
- R0 = I0;
-
- /* An extraction pattern, to get the page-size bits from
- * the CPLB data entry. Bits 16-17, so two bits at posn 16.
- */
-
- R1 = ((16<<8)|2);
-.Linext: R4 = [P2++]; /* address from config table */
- R2 = [P2++]; /* data from config table */
-#ifdef CONFIG_CPLB_INFO
- P3 += 8;
-#endif
-
- CC = R4 == -1; /* End of config table*/
- IF CC JUMP .Lno_page_in_table;
-
- /* See if failed address > start address */
- CC = R4 <= R0(IU);
- IF !CC JUMP .Linext;
-
- /* extract page size (17:16)*/
- R3 = EXTRACT(R2, R1.L) (Z);
-
- /* add page size to addr to get range */
-
- P5 = R3;
- P5 = P0 + (P5 << 2); /* scaled, for int access*/
- R3 = [P5];
- R3 = R3 + R4;
-
- /* See if failed address < (start address + page size) */
- CC = R0 < R3(IU);
- IF !CC JUMP .Linext;
-
- /* We've found a CPLB in the config table that covers
- * the faulting address, so install this CPLB into the
- * last entry of the table.
- */
-
- P1.L = LO(ICPLB_DATA15); /* ICPLB_DATA15 */
- P1.H = HI(ICPLB_DATA15);
- [P1] = R2;
- [P1-0x100] = R4;
-#ifdef CONFIG_CPLB_INFO
- R3 = [P3];
- R3 += 1;
- [P3] = R3;
-#endif
-
- /* P4 points to IMEM_CONTROL, and R5 contains its old
- * value, after we disabled ICPLBS. Re-enable them.
- */
-
- BITSET(R5,ENICPLB_P);
- CLI R2;
- SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
- .align 8;
- [P4] = R5;
- SSYNC;
- STI R2;
-
- ( R7:4,P5:3 ) = [SP++];
- R0 = CPLB_RELOADED;
- RTS;
-
-/* FAILED CASES*/
-.Lno_page_in_table:
- R0 = CPLB_NO_ADDR_MATCH;
- JUMP .Lfail_ret;
-
-.Lall_locked:
- R0 = CPLB_NO_UNLOCKED;
- JUMP .Lfail_ret;
-
-.Lprot_violation:
- R0 = CPLB_PROT_VIOL;
-
-.Lfail_ret:
- /* Make sure we turn protection/cache back on, even in the failing case */
- BITSET(R5,ENICPLB_P);
- CLI R2;
- SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
- .align 8;
- [P4] = R5;
- SSYNC;
- STI R2;
-
- ( R7:4,P5:3 ) = [SP++];
- RTS;
-
-.Ldcplb_write:
-
- /* if a DCPLB is marked as write-back (CPLB_WT==0), and
- * it is clean (CPLB_DIRTY==0), then a write to the
- * CPLB's page triggers a protection violation. We have to
- * mark the CPLB as dirty, to indicate that there are
- * pending writes associated with the CPLB.
- */
-
- P4.L = LO(DCPLB_STATUS);
- P4.H = HI(DCPLB_STATUS);
- P3.L = LO(DCPLB_DATA0);
- P3.H = HI(DCPLB_DATA0);
- R5 = [P4];
-
- /* A protection violation can be caused by more than just writes
- * to a clean WB page, so we have to ensure that:
- * - It's a write
- * - to a clean WB page
- * - and is allowed in the mode the access occurred.
- */
-
- CC = BITTST(R5, 16); /* ensure it was a write*/
- IF !CC JUMP .Lprot_violation;
-
- /* to check the rest, we have to retrieve the DCPLB.*/
-
- /* The low half of DCPLB_STATUS is a bit mask*/
-
- R2 = R5.L (Z); /* indicating which CPLB triggered the event.*/
- R3 = 30; /* so we can use this to determine the offset*/
- R2.L = SIGNBITS R2;
- R2 = R2.L (Z); /* into the DCPLB table.*/
- R3 = R3 - R2;
- P4 = R3;
- P3 = P3 + (P4<<2);
- R3 = [P3]; /* Retrieve the CPLB*/
-
- /* Now we can check whether it's a clean WB page*/
-
- CC = BITTST(R3, 14); /* 0==WB, 1==WT*/
- IF CC JUMP .Lprot_violation;
- CC = BITTST(R3, 7); /* 0 == clean, 1 == dirty*/
- IF CC JUMP .Lprot_violation;
-
- /* Check whether the write is allowed in the mode that was active.*/
-
- R2 = 1<<3; /* checking write in user mode*/
- CC = BITTST(R5, 17); /* 0==was user, 1==was super*/
- R5 = CC;
- R2 <<= R5; /* if was super, check write in super mode*/
- R2 = R3 & R2;
- CC = R2 == 0;
- IF CC JUMP .Lprot_violation;
-
- /* It's a genuine write-to-clean-page.*/
-
- BITSET(R3, 7); /* mark as dirty*/
- [P3] = R3; /* and write back.*/
- NOP;
- CSYNC;
- ( R7:4,P5:3 ) = [SP++];
- R0 = CPLB_RELOADED;
- RTS;
-
-.Ldcplb_miss_compare:
-
- /* Data CPLB Miss event. We need to choose a CPLB to
- * evict, and then locate a new CPLB to install from the
- * config table, that covers the faulting address.
- */
-
- P1.L = LO(DCPLB_DATA15);
- P1.H = HI(DCPLB_DATA15);
-
- P4.L = LO(DCPLB_FAULT_ADDR);
- P4.H = HI(DCPLB_FAULT_ADDR);
- R4 = [P4];
- I0 = R4;
-
- /* The replacement procedure for DCPLBs*/
-
- R6 = R1; /* Save for later*/
-
- /* Turn off CPLBs while we work.*/
- P4.L = LO(DMEM_CONTROL);
- P4.H = HI(DMEM_CONTROL);
- R5 = [P4];
- BITCLR(R5,ENDCPLB_P);
- CLI R0;
- SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
- .align 8;
- [P4] = R5;
- SSYNC;
- STI R0;
-
- /* Start looking for a CPLB to evict. Our order of preference
- * is: invalid CPLBs, clean CPLBs, dirty CPLBs. Locked CPLBs
- * are no good.
- */
-
- I1.L = LO(DCPLB_DATA0);
- I1.H = HI(DCPLB_DATA0);
- P1 = 2;
- P2 = 16;
- I2.L = _dcplb_preference;
- I2.H = _dcplb_preference;
- LSETUP(.Lsdsearch1, .Ledsearch1) LC0 = P1;
-.Lsdsearch1:
- R0 = [I2++]; /* Get the bits we're interested in*/
- P0 = I1; /* Go back to start of table*/
- LSETUP (.Lsdsearch2, .Ledsearch2) LC1 = P2;
-.Lsdsearch2:
- R1 = [P0++]; /* Fetch each installed CPLB in turn*/
- R2 = R1 & R0; /* and test for interesting bits.*/
- CC = R2 == 0; /* If none are set, it'll do.*/
- IF !CC JUMP .Lskip_stack_check;
-
- R2 = [P0 - 0x104]; /* R2 - PageStart */
- P3.L = _page_size_table; /* retrieve end address */
- P3.H = _page_size_table; /* retrieve end address */
- R3 = 0x1002; /* 16th - position, 2 bits -length */
-#if ANOMALY_05000209
- nop; /* Anomaly 05000209 */
-#endif
- R7 = EXTRACT(R1,R3.l);
- R7 = R7 << 2; /* Page size index offset */
- P5 = R7;
- P3 = P3 + P5;
- R7 = [P3]; /* page size in bytes */
-
- R7 = R2 + R7; /* R7 - PageEnd */
- R4 = SP; /* Test SP is in range */
-
- CC = R7 < R4; /* if PageEnd < SP */
- IF CC JUMP .Ldfound_victim;
- R3 = 0x284; /* stack length from start of trap till
- * the point.
- * 20 stack locations for future modifications
- */
- R4 = R4 + R3;
- CC = R4 < R2; /* if SP + stacklen < PageStart */
- IF CC JUMP .Ldfound_victim;
-.Lskip_stack_check:
-
-.Ledsearch2: NOP;
-.Ledsearch1: NOP;
-
- /* If we got here, we didn't find a DCPLB we considered
- * replacable, which means all of them were locked.
- */
-
- JUMP .Lall_locked;
-.Ldfound_victim:
-
-#ifdef CONFIG_CPLB_INFO
- R7 = [P0 - 0x104];
- P2.L = _dpdt_table;
- P2.H = _dpdt_table;
- P3.L = _dpdt_swapcount_table;
- P3.H = _dpdt_swapcount_table;
- P3 += -4;
-.Ldicount:
- R2 = [P2];
- P2 += 8;
- P3 += 8;
- CC = R2==-1;
- IF CC JUMP .Ldicount_done;
- CC = R7==R2;
- IF !CC JUMP .Ldicount;
- R7 = [P3];
- R7 += 1;
- [P3] = R7;
-.Ldicount_done:
-#endif
-
- /* Clean down the hardware loops*/
- R2 = 0;
- LC1 = R2;
- LC0 = R2;
-
- /* There's a suitable victim in [P0-4] (because we've
- * advanced already).
- */
-
-.LDdoverwrite:
-
- /* [P0-4] is a suitable victim CPLB, so we want to
- * overwrite it by moving all the following CPLBs
- * one space closer to the start.
- */
-
- R1.L = LO(DCPLB_DATA16); /* DCPLB_DATA15 + 4 */
- R1.H = HI(DCPLB_DATA16);
- R0 = P0;
-
- /* If the victim happens to be in DCPLB15,
- * we don't need to move anything.
- */
-
- CC = R1 == R0;
- IF CC JUMP .Lde_moved;
- R1 = R1 - R0;
- R1 >>= 2;
- P1 = R1;
- LSETUP(.Lds_move, .Lde_move) LC0=P1;
-.Lds_move:
- R0 = [P0++]; /* move data */
- [P0 - 8] = R0;
- R0 = [P0-0x104] /* move address */
-.Lde_move:
- [P0-0x108] = R0;
-
-.Lde_moved:
- NOP;
-
- /* Clear DCPLB_DATA15, in case we don't find a replacement
- * otherwise, we would have a duplicate entry, and will crash
- */
- R0 = 0;
- [P0 - 0x4] = R0;
-
- /* We've now made space in DCPLB15 for the new CPLB to be
- * installed. The next stage is to locate a CPLB in the
- * config table that covers the faulting address.
- */
-
- R0 = I0; /* Our faulting address */
-
- P2.L = _dpdt_table;
- P2.H = _dpdt_table;
-#ifdef CONFIG_CPLB_INFO
- P3.L = _dpdt_swapcount_table;
- P3.H = _dpdt_swapcount_table;
- P3 += -8;
-#endif
-
- P1.L = _page_size_table;
- P1.H = _page_size_table;
-
- /* An extraction pattern, to retrieve bits 17:16.*/
-
- R1 = (16<<8)|2;
-.Ldnext: R4 = [P2++]; /* address */
- R2 = [P2++]; /* data */
-#ifdef CONFIG_CPLB_INFO
- P3 += 8;
-#endif
-
- CC = R4 == -1;
- IF CC JUMP .Lno_page_in_table;
-
- /* See if failed address > start address */
- CC = R4 <= R0(IU);
- IF !CC JUMP .Ldnext;
-
- /* extract page size (17:16)*/
- R3 = EXTRACT(R2, R1.L) (Z);
-
- /* add page size to addr to get range */
-
- P5 = R3;
- P5 = P1 + (P5 << 2);
- R3 = [P5];
- R3 = R3 + R4;
-
- /* See if failed address < (start address + page size) */
- CC = R0 < R3(IU);
- IF !CC JUMP .Ldnext;
-
- /* We've found the CPLB that should be installed, so
- * write it into CPLB15, masking off any caching bits
- * if necessary.
- */
-
- P1.L = LO(DCPLB_DATA15);
- P1.H = HI(DCPLB_DATA15);
-
- /* If the DCPLB has cache bits set, but caching hasn't
- * been enabled, then we want to mask off the cache-in-L1
- * bit before installing. Moreover, if caching is off, we
- * also want to ensure that the DCPLB has WT mode set, rather
- * than WB, since WB pages still trigger first-write exceptions
- * even when not caching is off, and the page isn't marked as
- * cachable. Finally, we could mark the page as clean, not dirty,
- * but we choose to leave that decision to the user; if the user
- * chooses to have a CPLB pre-defined as dirty, then they always
- * pay the cost of flushing during eviction, but don't pay the
- * cost of first-write exceptions to mark the page as dirty.
- */
-
-#ifdef CONFIG_BFIN_WT
- BITSET(R6, 14); /* Set WT*/
-#endif
-
- [P1] = R2;
- [P1-0x100] = R4;
-#ifdef CONFIG_CPLB_INFO
- R3 = [P3];
- R3 += 1;
- [P3] = R3;
-#endif
-
- /* We've installed the CPLB, so re-enable CPLBs. P4
- * points to DMEM_CONTROL, and R5 is the value we
- * last wrote to it, when we were disabling CPLBs.
- */
-
- BITSET(R5,ENDCPLB_P);
- CLI R2;
- .align 8;
- [P4] = R5;
- SSYNC;
- STI R2;
-
- ( R7:4,P5:3 ) = [SP++];
- R0 = CPLB_RELOADED;
- RTS;
-ENDPROC(_cplb_mgr)
-
-.data
-.align 4;
-_page_size_table:
-.byte4 0x00000400; /* 1K */
-.byte4 0x00001000; /* 4K */
-.byte4 0x00100000; /* 1M */
-.byte4 0x00400000; /* 4M */
-
-.align 4;
-_dcplb_preference:
-.byte4 0x00000001; /* valid bit */
-.byte4 0x00000002; /* lock bit */
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
new file mode 100644
index 000000000000..8cbb47c7b663
--- /dev/null
+++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
@@ -0,0 +1,287 @@
+/*
+ * File: arch/blackfin/kernel/cplb-nompu-c/cplbmgr.c
+ * Based on: arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+ * Author: Michael McTernan <mmcternan@airvana.com>
+ *
+ * Created: 01Nov2008
+ * Description: CPLB miss handler.
+ *
+ * Modified:
+ * Copyright 2008 Airvana Inc.
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+#include <asm/cplb.h>
+#include <asm/mmu_context.h>
+
+/*
+ * WARNING
+ *
+ * This file is compiled with certain -ffixed-reg options. We have to
+ * make sure not to call any functions here that could clobber these
+ * registers.
+ */
+
+int nr_dcplb_miss[NR_CPUS], nr_icplb_miss[NR_CPUS];
+int nr_dcplb_supv_miss[NR_CPUS], nr_icplb_supv_miss[NR_CPUS];
+int nr_cplb_flush[NR_CPUS], nr_dcplb_prot[NR_CPUS];
+
+#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+#define MGR_ATTR __attribute__((l1_text))
+#else
+#define MGR_ATTR
+#endif
+
+/*
+ * We're in an exception handler. The normal cli nop nop workaround
+ * isn't going to do very much, as the only thing that can interrupt
+ * us is an NMI, and the cli isn't going to stop that.
+ */
+#define NOWA_SSYNC __asm__ __volatile__ ("ssync;")
+
+/* Anomaly handlers provide SSYNCs, so avoid extra if anomaly is present */
+#if ANOMALY_05000125
+
+#define bfin_write_DMEM_CONTROL_SSYNC(v) bfin_write_DMEM_CONTROL(v)
+#define bfin_write_IMEM_CONTROL_SSYNC(v) bfin_write_IMEM_CONTROL(v)
+
+#else
+
+#define bfin_write_DMEM_CONTROL_SSYNC(v) \
+ do { NOWA_SSYNC; bfin_write_DMEM_CONTROL(v); NOWA_SSYNC; } while (0)
+#define bfin_write_IMEM_CONTROL_SSYNC(v) \
+ do { NOWA_SSYNC; bfin_write_IMEM_CONTROL(v); NOWA_SSYNC; } while (0)
+
+#endif
+
+static inline void write_dcplb_data(int cpu, int idx, unsigned long data,
+ unsigned long addr)
+{
+ unsigned long ctrl = bfin_read_DMEM_CONTROL();
+ bfin_write_DMEM_CONTROL_SSYNC(ctrl & ~ENDCPLB);
+ bfin_write32(DCPLB_DATA0 + idx * 4, data);
+ bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
+ bfin_write_DMEM_CONTROL_SSYNC(ctrl);
+
+#ifdef CONFIG_CPLB_INFO
+ dcplb_tbl[cpu][idx].addr = addr;
+ dcplb_tbl[cpu][idx].data = data;
+#endif
+}
+
+static inline void write_icplb_data(int cpu, int idx, unsigned long data,
+ unsigned long addr)
+{
+ unsigned long ctrl = bfin_read_IMEM_CONTROL();
+
+ bfin_write_IMEM_CONTROL_SSYNC(ctrl & ~ENICPLB);
+ bfin_write32(ICPLB_DATA0 + idx * 4, data);
+ bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
+ bfin_write_IMEM_CONTROL_SSYNC(ctrl);
+
+#ifdef CONFIG_CPLB_INFO
+ icplb_tbl[cpu][idx].addr = addr;
+ icplb_tbl[cpu][idx].data = data;
+#endif
+}
+
+/*
+ * Given the contents of the status register, return the index of the
+ * CPLB that caused the fault.
+ */
+static inline int faulting_cplb_index(int status)
+{
+ int signbits = __builtin_bfin_norm_fr1x32(status & 0xFFFF);
+ return 30 - signbits;
+}
+
+/*
+ * Given the contents of the status register and the DCPLB_DATA contents,
+ * return true if a write access should be permitted.
+ */
+static inline int write_permitted(int status, unsigned long data)
+{
+ if (status & FAULT_USERSUPV)
+ return !!(data & CPLB_SUPV_WR);
+ else
+ return !!(data & CPLB_USER_WR);
+}
+
+/* Counters to implement round-robin replacement. */
+static int icplb_rr_index[NR_CPUS] PDT_ATTR;
+static int dcplb_rr_index[NR_CPUS] PDT_ATTR;
+
+/*
+ * Find an ICPLB entry to be evicted and return its index.
+ */
+static int evict_one_icplb(int cpu)
+{
+ int i = first_switched_icplb + icplb_rr_index[cpu];
+ if (i >= MAX_CPLBS) {
+ i -= MAX_CPLBS - first_switched_icplb;
+ icplb_rr_index[cpu] -= MAX_CPLBS - first_switched_icplb;
+ }
+ icplb_rr_index[cpu]++;
+ return i;
+}
+
+static int evict_one_dcplb(int cpu)
+{
+ int i = first_switched_dcplb + dcplb_rr_index[cpu];
+ if (i >= MAX_CPLBS) {
+ i -= MAX_CPLBS - first_switched_dcplb;
+ dcplb_rr_index[cpu] -= MAX_CPLBS - first_switched_dcplb;
+ }
+ dcplb_rr_index[cpu]++;
+ return i;
+}
+
+MGR_ATTR static int icplb_miss(int cpu)
+{
+ unsigned long addr = bfin_read_ICPLB_FAULT_ADDR();
+ int status = bfin_read_ICPLB_STATUS();
+ int idx;
+ unsigned long i_data, base, addr1, eaddr;
+
+ nr_icplb_miss[cpu]++;
+ if (unlikely(status & FAULT_USERSUPV))
+ nr_icplb_supv_miss[cpu]++;
+
+ base = 0;
+ idx = 0;
+ do {
+ eaddr = icplb_bounds[idx].eaddr;
+ if (addr < eaddr)
+ break;
+ base = eaddr;
+ } while (++idx < icplb_nr_bounds);
+
+ if (unlikely(idx == icplb_nr_bounds))
+ return CPLB_NO_ADDR_MATCH;
+
+ i_data = icplb_bounds[idx].data;
+ if (unlikely(i_data == 0))
+ return CPLB_NO_ADDR_MATCH;
+
+ addr1 = addr & ~(SIZE_4M - 1);
+ addr &= ~(SIZE_1M - 1);
+ i_data |= PAGE_SIZE_1MB;
+ if (addr1 >= base && (addr1 + SIZE_4M) <= eaddr) {
+ /*
+ * This works because
+ * (PAGE_SIZE_4MB & PAGE_SIZE_1MB) == PAGE_SIZE_1MB.
+ */
+ i_data |= PAGE_SIZE_4MB;
+ addr = addr1;
+ }
+
+ /* Pick entry to evict */
+ idx = evict_one_icplb(cpu);
+
+ write_icplb_data(cpu, idx, i_data, addr);
+
+ return CPLB_RELOADED;
+}
+
+MGR_ATTR static int dcplb_miss(int cpu)
+{
+ unsigned long addr = bfin_read_DCPLB_FAULT_ADDR();
+ int status = bfin_read_DCPLB_STATUS();
+ int idx;
+ unsigned long d_data, base, addr1, eaddr;
+
+ nr_dcplb_miss[cpu]++;
+ if (unlikely(status & FAULT_USERSUPV))
+ nr_dcplb_supv_miss[cpu]++;
+
+ base = 0;
+ idx = 0;
+ do {
+ eaddr = dcplb_bounds[idx].eaddr;
+ if (addr < eaddr)
+ break;
+ base = eaddr;
+ } while (++idx < dcplb_nr_bounds);
+
+ if (unlikely(idx == dcplb_nr_bounds))
+ return CPLB_NO_ADDR_MATCH;
+
+ d_data = dcplb_bounds[idx].data;
+ if (unlikely(d_data == 0))
+ return CPLB_NO_ADDR_MATCH;
+
+ addr1 = addr & ~(SIZE_4M - 1);
+ addr &= ~(SIZE_1M - 1);
+ d_data |= PAGE_SIZE_1MB;
+ if (addr1 >= base && (addr1 + SIZE_4M) <= eaddr) {
+ /*
+ * This works because
+ * (PAGE_SIZE_4MB & PAGE_SIZE_1MB) == PAGE_SIZE_1MB.
+ */
+ d_data |= PAGE_SIZE_4MB;
+ addr = addr1;
+ }
+
+ /* Pick entry to evict */
+ idx = evict_one_dcplb(cpu);
+
+ write_dcplb_data(cpu, idx, d_data, addr);
+
+ return CPLB_RELOADED;
+}
+
+MGR_ATTR static noinline int dcplb_protection_fault(int cpu)
+{
+ int status = bfin_read_DCPLB_STATUS();
+
+ nr_dcplb_prot[cpu]++;
+
+ if (likely(status & FAULT_RW)) {
+ int idx = faulting_cplb_index(status);
+ unsigned long regaddr = DCPLB_DATA0 + idx * 4;
+ unsigned long data = bfin_read32(regaddr);
+
+ /* Check if fault is to dirty a clean page */
+ if (!(data & CPLB_WT) && !(data & CPLB_DIRTY) &&
+ write_permitted(status, data)) {
+
+ dcplb_tbl[cpu][idx].data = data;
+ bfin_write32(regaddr, data);
+ return CPLB_RELOADED;
+ }
+ }
+
+ return CPLB_PROT_VIOL;
+}
+
+MGR_ATTR int cplb_hdr(int seqstat, struct pt_regs *regs)
+{
+ int cause = seqstat & 0x3f;
+ unsigned int cpu = smp_processor_id();
+ switch (cause) {
+ case 0x2C:
+ return icplb_miss(cpu);
+ case 0x26:
+ return dcplb_miss(cpu);
+ default:
+ if (unlikely(cause == 0x23))
+ return dcplb_protection_fault(cpu);
+
+ return CPLB_UNKNOWN_ERR;
+ }
+}
diff --git a/arch/blackfin/kernel/cplbinfo.c b/arch/blackfin/kernel/cplbinfo.c
new file mode 100644
index 000000000000..64d78300dd08
--- /dev/null
+++ b/arch/blackfin/kernel/cplbinfo.c
@@ -0,0 +1,177 @@
+/*
+ * arch/blackfin/kernel/cplbinfo.c - display CPLB status
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+
+#include <asm/cplbinit.h>
+#include <asm/blackfin.h>
+
+static char const page_strtbl[][3] = { "1K", "4K", "1M", "4M" };
+#define page(flags) (((flags) & 0x30000) >> 16)
+#define strpage(flags) page_strtbl[page(flags)]
+
+struct cplbinfo_data {
+ loff_t pos;
+ char cplb_type;
+ u32 mem_control;
+ struct cplb_entry *tbl;
+ int switched;
+};
+
+static void cplbinfo_print_header(struct seq_file *m)
+{
+ seq_printf(m, "Index\tAddress\t\tData\tSize\tU/RD\tU/WR\tS/WR\tSwitch\n");
+}
+
+static int cplbinfo_nomore(struct cplbinfo_data *cdata)
+{
+ return cdata->pos >= MAX_CPLBS;
+}
+
+static int cplbinfo_show(struct seq_file *m, void *p)
+{
+ struct cplbinfo_data *cdata;
+ unsigned long data, addr;
+ loff_t pos;
+
+ cdata = p;
+ pos = cdata->pos;
+ addr = cdata->tbl[pos].addr;
+ data = cdata->tbl[pos].data;
+
+ seq_printf(m,
+ "%d\t0x%08lx\t%05lx\t%s\t%c\t%c\t%c\t%c\n",
+ (int)pos, addr, data, strpage(data),
+ (data & CPLB_USER_RD) ? 'Y' : 'N',
+ (data & CPLB_USER_WR) ? 'Y' : 'N',
+ (data & CPLB_SUPV_WR) ? 'Y' : 'N',
+ pos < cdata->switched ? 'N' : 'Y');
+
+ return 0;
+}
+
+static void cplbinfo_seq_init(struct cplbinfo_data *cdata, unsigned int cpu)
+{
+ if (cdata->cplb_type == 'I') {
+ cdata->mem_control = bfin_read_IMEM_CONTROL();
+ cdata->tbl = icplb_tbl[cpu];
+ cdata->switched = first_switched_icplb;
+ } else {
+ cdata->mem_control = bfin_read_DMEM_CONTROL();
+ cdata->tbl = dcplb_tbl[cpu];
+ cdata->switched = first_switched_dcplb;
+ }
+}
+
+static void *cplbinfo_start(struct seq_file *m, loff_t *pos)
+{
+ struct cplbinfo_data *cdata = m->private;
+
+ if (!*pos) {
+ seq_printf(m, "%cCPLBs are %sabled: 0x%x\n", cdata->cplb_type,
+ (cdata->mem_control & ENDCPLB ? "en" : "dis"),
+ cdata->mem_control);
+ cplbinfo_print_header(m);
+ } else if (cplbinfo_nomore(cdata))
+ return NULL;
+
+ get_cpu();
+ return cdata;
+}
+
+static void *cplbinfo_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ struct cplbinfo_data *cdata = p;
+ cdata->pos = ++(*pos);
+ if (cplbinfo_nomore(cdata))
+ return NULL;
+ else
+ return cdata;
+}
+
+static void cplbinfo_stop(struct seq_file *m, void *p)
+{
+ put_cpu();
+}
+
+static const struct seq_operations cplbinfo_sops = {
+ .start = cplbinfo_start,
+ .next = cplbinfo_next,
+ .stop = cplbinfo_stop,
+ .show = cplbinfo_show,
+};
+
+static int cplbinfo_open(struct inode *inode, struct file *file)
+{
+ char buf[256], *path, *p;
+ unsigned int cpu;
+ char *s_cpu, *s_cplb;
+ int ret;
+ struct seq_file *m;
+ struct cplbinfo_data *cdata;
+
+ path = d_path(&file->f_path, buf, sizeof(buf));
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+ s_cpu = strstr(path, "/cpu");
+ s_cplb = strrchr(path, '/');
+ if (!s_cpu || !s_cplb)
+ return -EINVAL;
+
+ cpu = simple_strtoul(s_cpu + 4, &p, 10);
+ if (!cpu_online(cpu))
+ return -ENODEV;
+
+ ret = seq_open_private(file, &cplbinfo_sops, sizeof(*cdata));
+ if (ret)
+ return ret;
+ m = file->private_data;
+ cdata = m->private;
+
+ cdata->pos = 0;
+ cdata->cplb_type = toupper(s_cplb[1]);
+ cplbinfo_seq_init(cdata, cpu);
+
+ return 0;
+}
+
+static const struct file_operations cplbinfo_fops = {
+ .open = cplbinfo_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+static int __init cplbinfo_init(void)
+{
+ struct proc_dir_entry *cplb_dir, *cpu_dir;
+ char buf[10];
+ unsigned int cpu;
+
+ cplb_dir = proc_mkdir("cplbinfo", NULL);
+ if (!cplb_dir)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ sprintf(buf, "cpu%i", cpu);
+ cpu_dir = proc_mkdir(buf, cplb_dir);
+ if (!cpu_dir)
+ return -ENOMEM;
+
+ proc_create("icplb", S_IRUGO, cpu_dir, &cplbinfo_fops);
+ proc_create("dcplb", S_IRUGO, cpu_dir, &cplbinfo_fops);
+ }
+
+ return 0;
+}
+late_initcall(cplbinfo_init);
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c
index 1f4e3d2e0901..c8ad051742e2 100644
--- a/arch/blackfin/kernel/early_printk.c
+++ b/arch/blackfin/kernel/early_printk.c
@@ -105,10 +105,10 @@ static struct console * __init earlyserial_init(char *buf)
cflag |= CS5;
break;
case 6:
- cflag |= CS5;
+ cflag |= CS6;
break;
case 7:
- cflag |= CS5;
+ cflag |= CS7;
break;
default:
cflag |= CS8;
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index faea88ebb2ef..a9cfba9946b5 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -30,6 +30,7 @@
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
+#include <asm/blackfin.h>
#include <asm/asm-offsets.h>
#include <asm/context.S>
@@ -41,6 +42,10 @@
#endif
ENTRY(_ret_from_fork)
+#ifdef CONFIG_IPIPE
+ [--sp] = reti; /* IRQs on. */
+ SP += 4;
+#endif /* CONFIG_IPIPE */
SP += -12;
call _schedule_tail;
SP += 12;
diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S
index 4b03ba025488..0d2d9e0968c8 100644
--- a/arch/blackfin/kernel/fixed_code.S
+++ b/arch/blackfin/kernel/fixed_code.S
@@ -8,10 +8,12 @@
* BF561 SMP).
*/
#include <linux/linkage.h>
+#include <linux/init.h>
#include <linux/unistd.h>
#include <asm/entry.h>
-.text
+__INIT
+
ENTRY(_fixed_code_start)
.align 16
@@ -144,3 +146,5 @@ ENTRY(_safe_user_instruction)
ENDPROC(_safe_user_instruction)
ENTRY(_fixed_code_end)
+
+__FINIT
diff --git a/arch/blackfin/kernel/init_task.c b/arch/blackfin/kernel/init_task.c
index 6bdba7b21109..2c228c020978 100644
--- a/arch/blackfin/kernel/init_task.c
+++ b/arch/blackfin/kernel/init_task.c
@@ -33,7 +33,6 @@
#include <linux/mqueue.h>
#include <linux/fs.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
new file mode 100644
index 000000000000..339be5a3ae6a
--- /dev/null
+++ b/arch/blackfin/kernel/ipipe.c
@@ -0,0 +1,428 @@
+/* -*- linux-c -*-
+ * linux/arch/blackfin/kernel/ipipe.c
+ *
+ * Copyright (C) 2005-2007 Philippe Gerum.
+ *
+ * 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, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; 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.
+ *
+ * Architecture-dependent I-pipe support for the Blackfin.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/kthread.h>
+#include <asm/unistd.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+
+static int create_irq_threads;
+
+DEFINE_PER_CPU(struct pt_regs, __ipipe_tick_regs);
+
+static DEFINE_PER_CPU(unsigned long, pending_irqthread_mask);
+
+static DEFINE_PER_CPU(int [IVG13 + 1], pending_irq_count);
+
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
+
+static void __ipipe_no_irqtail(void);
+
+unsigned long __ipipe_irq_tail_hook = (unsigned long)&__ipipe_no_irqtail;
+EXPORT_SYMBOL(__ipipe_irq_tail_hook);
+
+unsigned long __ipipe_core_clock;
+EXPORT_SYMBOL(__ipipe_core_clock);
+
+unsigned long __ipipe_freq_scale;
+EXPORT_SYMBOL(__ipipe_freq_scale);
+
+atomic_t __ipipe_irq_lvdepth[IVG15 + 1];
+
+unsigned long __ipipe_irq_lvmask = __all_masked_irq_flags;
+EXPORT_SYMBOL(__ipipe_irq_lvmask);
+
+static void __ipipe_ack_irq(unsigned irq, struct irq_desc *desc)
+{
+ desc->ipipe_ack(irq, desc);
+}
+
+/*
+ * __ipipe_enable_pipeline() -- We are running on the boot CPU, hw
+ * interrupts are off, and secondary CPUs are still lost in space.
+ */
+void __ipipe_enable_pipeline(void)
+{
+ unsigned irq;
+
+ __ipipe_core_clock = get_cclk(); /* Fetch this once. */
+ __ipipe_freq_scale = 1000000000UL / __ipipe_core_clock;
+
+ for (irq = 0; irq < NR_IRQS; ++irq)
+ ipipe_virtualize_irq(ipipe_root_domain,
+ irq,
+ (ipipe_irq_handler_t)&asm_do_IRQ,
+ NULL,
+ &__ipipe_ack_irq,
+ IPIPE_HANDLE_MASK | IPIPE_PASS_MASK);
+}
+
+/*
+ * __ipipe_handle_irq() -- IPIPE's generic IRQ handler. An optimistic
+ * interrupt protection log is maintained here for each domain. Hw
+ * interrupts are masked on entry.
+ */
+void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
+{
+ struct ipipe_domain *this_domain, *next_domain;
+ struct list_head *head, *pos;
+ int m_ack, s = -1;
+
+ /*
+ * Software-triggered IRQs do not need any ack. The contents
+ * of the register frame should only be used when processing
+ * the timer interrupt, but not for handling any other
+ * interrupt.
+ */
+ m_ack = (regs == NULL || irq == IRQ_SYSTMR || irq == IRQ_CORETMR);
+
+ this_domain = ipipe_current_domain;
+
+ if (unlikely(test_bit(IPIPE_STICKY_FLAG, &this_domain->irqs[irq].control)))
+ head = &this_domain->p_link;
+ else {
+ head = __ipipe_pipeline.next;
+ next_domain = list_entry(head, struct ipipe_domain, p_link);
+ if (likely(test_bit(IPIPE_WIRED_FLAG, &next_domain->irqs[irq].control))) {
+ if (!m_ack && next_domain->irqs[irq].acknowledge != NULL)
+ next_domain->irqs[irq].acknowledge(irq, irq_desc + irq);
+ if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags))
+ s = __test_and_set_bit(IPIPE_STALL_FLAG,
+ &ipipe_root_cpudom_var(status));
+ __ipipe_dispatch_wired(next_domain, irq);
+ goto finalize;
+ return;
+ }
+ }
+
+ /* Ack the interrupt. */
+
+ pos = head;
+
+ while (pos != &__ipipe_pipeline) {
+ next_domain = list_entry(pos, struct ipipe_domain, p_link);
+ /*
+ * For each domain handling the incoming IRQ, mark it
+ * as pending in its log.
+ */
+ if (test_bit(IPIPE_HANDLE_FLAG, &next_domain->irqs[irq].control)) {
+ /*
+ * Domains that handle this IRQ are polled for
+ * acknowledging it by decreasing priority
+ * order. The interrupt must be made pending
+ * _first_ in the domain's status flags before
+ * the PIC is unlocked.
+ */
+ __ipipe_set_irq_pending(next_domain, irq);
+
+ if (!m_ack && next_domain->irqs[irq].acknowledge != NULL) {
+ next_domain->irqs[irq].acknowledge(irq, irq_desc + irq);
+ m_ack = 1;
+ }
+ }
+
+ /*
+ * If the domain does not want the IRQ to be passed
+ * down the interrupt pipe, exit the loop now.
+ */
+ if (!test_bit(IPIPE_PASS_FLAG, &next_domain->irqs[irq].control))
+ break;
+
+ pos = next_domain->p_link.next;
+ }
+
+ /*
+ * Now walk the pipeline, yielding control to the highest
+ * priority domain that has pending interrupt(s) or
+ * immediately to the current domain if the interrupt has been
+ * marked as 'sticky'. This search does not go beyond the
+ * current domain in the pipeline. We also enforce the
+ * additional root stage lock (blackfin-specific). */
+
+ if (test_bit(IPIPE_ROOTLOCK_FLAG, &ipipe_root_domain->flags))
+ s = __test_and_set_bit(IPIPE_STALL_FLAG,
+ &ipipe_root_cpudom_var(status));
+finalize:
+
+ __ipipe_walk_pipeline(head);
+
+ if (!s)
+ __clear_bit(IPIPE_STALL_FLAG,
+ &ipipe_root_cpudom_var(status));
+}
+
+int __ipipe_check_root(void)
+{
+ return ipipe_root_domain_p;
+}
+
+void __ipipe_enable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
+{
+ struct irq_desc *desc = irq_desc + irq;
+ int prio = desc->ic_prio;
+
+ desc->depth = 0;
+ if (ipd != &ipipe_root &&
+ atomic_inc_return(&__ipipe_irq_lvdepth[prio]) == 1)
+ __set_bit(prio, &__ipipe_irq_lvmask);
+}
+EXPORT_SYMBOL(__ipipe_enable_irqdesc);
+
+void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
+{
+ struct irq_desc *desc = irq_desc + irq;
+ int prio = desc->ic_prio;
+
+ if (ipd != &ipipe_root &&
+ atomic_dec_and_test(&__ipipe_irq_lvdepth[prio]))
+ __clear_bit(prio, &__ipipe_irq_lvmask);
+}
+EXPORT_SYMBOL(__ipipe_disable_irqdesc);
+
+void __ipipe_stall_root_raw(void)
+{
+ /*
+ * This code is called by the ins{bwl} routines (see
+ * arch/blackfin/lib/ins.S), which are heavily used by the
+ * network stack. It masks all interrupts but those handled by
+ * non-root domains, so that we keep decent network transfer
+ * rates for Linux without inducing pathological jitter for
+ * the real-time domain.
+ */
+ __asm__ __volatile__ ("sti %0;" : : "d"(__ipipe_irq_lvmask));
+
+ __set_bit(IPIPE_STALL_FLAG,
+ &ipipe_root_cpudom_var(status));
+}
+
+void __ipipe_unstall_root_raw(void)
+{
+ __clear_bit(IPIPE_STALL_FLAG,
+ &ipipe_root_cpudom_var(status));
+
+ __asm__ __volatile__ ("sti %0;" : : "d"(bfin_irq_flags));
+}
+
+int __ipipe_syscall_root(struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ /* We need to run the IRQ tail hook whenever we don't
+ * propagate a syscall to higher domains, because we know that
+ * important operations might be pending there (e.g. Xenomai
+ * deferred rescheduling). */
+
+ if (!__ipipe_syscall_watched_p(current, regs->orig_p0)) {
+ void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
+ hook();
+ return 0;
+ }
+
+ /*
+ * This routine either returns:
+ * 0 -- if the syscall is to be passed to Linux;
+ * 1 -- if the syscall should not be passed to Linux, and no
+ * tail work should be performed;
+ * -1 -- if the syscall should not be passed to Linux but the
+ * tail work has to be performed (for handling signals etc).
+ */
+
+ if (__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL) &&
+ __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs) > 0) {
+ if (ipipe_root_domain_p && !in_atomic()) {
+ /*
+ * Sync pending VIRQs before _TIF_NEED_RESCHED
+ * is tested.
+ */
+ local_irq_save_hw(flags);
+ if ((ipipe_root_cpudom_var(irqpend_himask) & IPIPE_IRQMASK_VIRT) != 0)
+ __ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
+ local_irq_restore_hw(flags);
+ return -1;
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned long ipipe_critical_enter(void (*syncfn) (void))
+{
+ unsigned long flags;
+
+ local_irq_save_hw(flags);
+
+ return flags;
+}
+
+void ipipe_critical_exit(unsigned long flags)
+{
+ local_irq_restore_hw(flags);
+}
+
+static void __ipipe_no_irqtail(void)
+{
+}
+
+int ipipe_get_sysinfo(struct ipipe_sysinfo *info)
+{
+ info->ncpus = num_online_cpus();
+ info->cpufreq = ipipe_cpu_freq();
+ info->archdep.tmirq = IPIPE_TIMER_IRQ;
+ info->archdep.tmfreq = info->cpufreq;
+
+ return 0;
+}
+
+/*
+ * ipipe_trigger_irq() -- Push the interrupt at front of the pipeline
+ * just like if it has been actually received from a hw source. Also
+ * works for virtual interrupts.
+ */
+int ipipe_trigger_irq(unsigned irq)
+{
+ unsigned long flags;
+
+ if (irq >= IPIPE_NR_IRQS ||
+ (ipipe_virtual_irq_p(irq)
+ && !test_bit(irq - IPIPE_VIRQ_BASE, &__ipipe_virtual_irq_map)))
+ return -EINVAL;
+
+ local_irq_save_hw(flags);
+
+ __ipipe_handle_irq(irq, NULL);
+
+ local_irq_restore_hw(flags);
+
+ return 1;
+}
+
+/* Move Linux IRQ to threads. */
+
+static int do_irqd(void *__desc)
+{
+ struct irq_desc *desc = __desc;
+ unsigned irq = desc - irq_desc;
+ int thrprio = desc->thr_prio;
+ int thrmask = 1 << thrprio;
+ int cpu = smp_processor_id();
+ cpumask_t cpumask;
+
+ sigfillset(&current->blocked);
+ current->flags |= PF_NOFREEZE;
+ cpumask = cpumask_of_cpu(cpu);
+ set_cpus_allowed(current, cpumask);
+ ipipe_setscheduler_root(current, SCHED_FIFO, 50 + thrprio);
+
+ while (!kthread_should_stop()) {
+ local_irq_disable();
+ if (!(desc->status & IRQ_SCHEDULED)) {
+ set_current_state(TASK_INTERRUPTIBLE);
+resched:
+ local_irq_enable();
+ schedule();
+ local_irq_disable();
+ }
+ __set_current_state(TASK_RUNNING);
+ /*
+ * If higher priority interrupt servers are ready to
+ * run, reschedule immediately. We need this for the
+ * GPIO demux IRQ handler to unmask the interrupt line
+ * _last_, after all GPIO IRQs have run.
+ */
+ if (per_cpu(pending_irqthread_mask, cpu) & ~(thrmask|(thrmask-1)))
+ goto resched;
+ if (--per_cpu(pending_irq_count[thrprio], cpu) == 0)
+ per_cpu(pending_irqthread_mask, cpu) &= ~thrmask;
+ desc->status &= ~IRQ_SCHEDULED;
+ desc->thr_handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs));
+ local_irq_enable();
+ }
+ __set_current_state(TASK_RUNNING);
+ return 0;
+}
+
+static void kick_irqd(unsigned irq, void *cookie)
+{
+ struct irq_desc *desc = irq_desc + irq;
+ int thrprio = desc->thr_prio;
+ int thrmask = 1 << thrprio;
+ int cpu = smp_processor_id();
+
+ if (!(desc->status & IRQ_SCHEDULED)) {
+ desc->status |= IRQ_SCHEDULED;
+ per_cpu(pending_irqthread_mask, cpu) |= thrmask;
+ ++per_cpu(pending_irq_count[thrprio], cpu);
+ wake_up_process(desc->thread);
+ }
+}
+
+int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc)
+{
+ if (desc->thread || !create_irq_threads)
+ return 0;
+
+ desc->thread = kthread_create(do_irqd, desc, "IRQ %d", irq);
+ if (desc->thread == NULL) {
+ printk(KERN_ERR "irqd: could not create IRQ thread %d!\n", irq);
+ return -ENOMEM;
+ }
+
+ wake_up_process(desc->thread);
+
+ desc->thr_handler = ipipe_root_domain->irqs[irq].handler;
+ ipipe_root_domain->irqs[irq].handler = &kick_irqd;
+
+ return 0;
+}
+
+void __init ipipe_init_irq_threads(void)
+{
+ unsigned irq;
+ struct irq_desc *desc;
+
+ create_irq_threads = 1;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ desc = irq_desc + irq;
+ if (desc->action != NULL ||
+ (desc->status & IRQ_NOREQUEST) != 0)
+ ipipe_start_irq_thread(irq, desc);
+ }
+}
+
+EXPORT_SYMBOL(show_stack);
+
+#ifdef CONFIG_IPIPE_TRACE_MCOUNT
+void notrace _mcount(void);
+EXPORT_SYMBOL(_mcount);
+#endif /* CONFIG_IPIPE_TRACE_MCOUNT */
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index 07402f57c9de..75724eee6494 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -35,8 +35,9 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/trace.h>
+#include <asm/pda.h>
-static unsigned long irq_err_count;
+static atomic_t irq_err_count;
static spinlock_t irq_controller_lock;
/*
@@ -48,10 +49,9 @@ void dummy_mask_unmask_irq(unsigned int irq)
void ack_bad_irq(unsigned int irq)
{
- irq_err_count += 1;
+ atomic_inc(&irq_err_count);
printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
}
-EXPORT_SYMBOL(ack_bad_irq);
static struct irq_chip bad_chip = {
.ack = dummy_mask_unmask_irq,
@@ -72,7 +72,7 @@ static struct irq_desc bad_irq_desc = {
int show_interrupts(struct seq_file *p, void *v)
{
- int i = *(loff_t *) v;
+ int i = *(loff_t *) v, j;
struct irqaction *action;
unsigned long flags;
@@ -80,18 +80,24 @@ int show_interrupts(struct seq_file *p, void *v)
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
- goto unlock;
-
- seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
+ goto skip;
+ seq_printf(p, "%3d: ", i);
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+ seq_printf(p, " %8s", irq_desc[i].chip->name);
seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next)
- seq_printf(p, ", %s", action->name);
+ seq_printf(p, " %s", action->name);
seq_putc(p, '\n');
- unlock:
+ skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
} else if (i == NR_IRQS) {
- seq_printf(p, "Err: %10lu\n", irq_err_count);
+ seq_printf(p, "NMI: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_pda[j].__nmi_count);
+ seq_printf(p, " CORE Non Maskable Interrupt\n");
+ seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
}
return 0;
}
@@ -101,7 +107,6 @@ int show_interrupts(struct seq_file *p, void *v)
* come via this function. Instead, they should provide their
* own 'handler'
*/
-
#ifdef CONFIG_DO_IRQ_L1
__attribute__((l1_text))
#endif
@@ -109,8 +114,9 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs;
struct irq_desc *desc = irq_desc + irq;
+#ifndef CONFIG_IPIPE
unsigned short pending, other_ints;
-
+#endif
old_regs = set_irq_regs(regs);
/*
@@ -121,9 +127,24 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
desc = &bad_irq_desc;
irq_enter();
-
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /* Debugging check for stack overflow: is there less than STACK_WARN free? */
+ {
+ long sp;
+
+ sp = __get_SP() & (THREAD_SIZE-1);
+
+ if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
+ dump_stack();
+ printk(KERN_EMERG "%s: possible stack overflow while handling irq %i "
+ " only %ld bytes free\n",
+ __func__, irq, sp - sizeof(struct thread_info));
+ }
+ }
+#endif
generic_handle_irq(irq);
+#ifndef CONFIG_IPIPE /* Useless and bugous over the I-pipe: IRQs are threaded. */
/* If we're the only interrupt running (ignoring IRQ15 which is for
syscalls), lower our priority to IRQ14 so that softirqs run at
that level. If there's another, lower-level interrupt, irq_exit
@@ -133,6 +154,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
other_ints = pending & (pending - 1);
if (other_ints == 0)
lower_to_irq14();
+#endif /* !CONFIG_IPIPE */
irq_exit();
set_irq_regs(old_regs);
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
index b795a207742c..b163f6d3330d 100644
--- a/arch/blackfin/kernel/kgdb.c
+++ b/arch/blackfin/kernel/kgdb.c
@@ -34,9 +34,14 @@ int gdb_bfin_vector = -1;
#error change the definition of slavecpulocks
#endif
-#ifdef CONFIG_BFIN_WDT
-# error "Please unselect blackfin watchdog driver before build KGDB."
-#endif
+#define IN_MEM(addr, size, l1_addr, l1_size) \
+({ \
+ unsigned long __addr = (unsigned long)(addr); \
+ (l1_size && __addr >= l1_addr && __addr + (size) <= l1_addr + l1_size); \
+})
+#define ASYNC_BANK_SIZE \
+ (ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
+ ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE)
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
@@ -105,7 +110,7 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
* Extracts ebp, esp and eip values understandable by gdb from the values
* saved by switch_to.
* thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
- * prior to entering switch_to is 8 greater then the value that is saved.
+ * prior to entering switch_to is 8 greater than the value that is saved.
* If switch_to changes, change following code appropriately.
*/
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
@@ -219,6 +224,7 @@ int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
if (bfin_type == breakinfo[breakno].type
&& !breakinfo[breakno].occupied) {
breakinfo[breakno].occupied = 1;
+ breakinfo[breakno].skip = 0;
breakinfo[breakno].enabled = 1;
breakinfo[breakno].addr = addr;
breakinfo[breakno].dataacc = dataacc;
@@ -363,12 +369,12 @@ void kgdb_passive_cpu_callback(void *info)
void kgdb_roundup_cpus(unsigned long flags)
{
- smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0);
+ smp_call_function(kgdb_passive_cpu_callback, NULL, 0);
}
void kgdb_roundup_cpu(int cpu, unsigned long flags)
{
- smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0);
+ smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0);
}
#endif
@@ -385,10 +391,8 @@ int kgdb_arch_handle_exception(int vector, int signo,
struct pt_regs *regs)
{
long addr;
- long breakno;
char *ptr;
int newPC;
- int wp_status;
int i;
switch (remcom_in_buffer[0]) {
@@ -426,17 +430,6 @@ int kgdb_arch_handle_exception(int vector, int signo,
kgdb_single_step = i + 1;
}
- if (vector == VEC_WATCH) {
- wp_status = bfin_read_WPSTAT();
- for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) {
- if (wp_status & (1 << breakno)) {
- breakinfo->skip = 1;
- break;
- }
- }
- bfin_write_WPSTAT(0);
- }
-
bfin_correct_hw_break();
return 0;
@@ -478,57 +471,32 @@ static int validate_memory_access_address(unsigned long addr, int size)
return 0;
if (addr >= SYSMMR_BASE)
return 0;
- if (addr >= ASYNC_BANK0_BASE
- && addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)
+ if (IN_MEM(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK_SIZE))
return 0;
if (cpu == 0) {
- if (addr >= L1_SCRATCH_START
- && (addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH))
+ if (IN_MEM(addr, size, L1_SCRATCH_START, L1_SCRATCH_LENGTH))
return 0;
-#if L1_CODE_LENGTH != 0
- if (addr >= L1_CODE_START
- && (addr + size <= L1_CODE_START + L1_CODE_LENGTH))
+ if (IN_MEM(addr, size, L1_CODE_START, L1_CODE_LENGTH))
return 0;
-#endif
-#if L1_DATA_A_LENGTH != 0
- if (addr >= L1_DATA_A_START
- && (addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH))
+ if (IN_MEM(addr, size, L1_DATA_A_START, L1_DATA_A_LENGTH))
return 0;
-#endif
-#if L1_DATA_B_LENGTH != 0
- if (addr >= L1_DATA_B_START
- && (addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH))
+ if (IN_MEM(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH))
return 0;
-#endif
#ifdef CONFIG_SMP
} else if (cpu == 1) {
- if (addr >= COREB_L1_SCRATCH_START
- && (addr + size <= COREB_L1_SCRATCH_START
- + L1_SCRATCH_LENGTH))
+ if (IN_MEM(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
return 0;
-# if L1_CODE_LENGTH != 0
- if (addr >= COREB_L1_CODE_START
- && (addr + size <= COREB_L1_CODE_START + L1_CODE_LENGTH))
+ if (IN_MEM(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
return 0;
-# endif
-# if L1_DATA_A_LENGTH != 0
- if (addr >= COREB_L1_DATA_A_START
- && (addr + size <= COREB_L1_DATA_A_START + L1_DATA_A_LENGTH))
+ if (IN_MEM(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
return 0;
-# endif
-# if L1_DATA_B_LENGTH != 0
- if (addr >= COREB_L1_DATA_B_START
- && (addr + size <= COREB_L1_DATA_B_START + L1_DATA_B_LENGTH))
+ if (IN_MEM(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
return 0;
-# endif
#endif
}
-#if L2_LENGTH != 0
- if (addr >= L2_START
- && addr + size <= L2_START + L2_LENGTH)
+ if (IN_MEM(addr, size, L2_START, L2_LENGTH))
return 0;
-#endif
return EFAULT;
}
@@ -582,12 +550,9 @@ int kgdb_mem2hex(char *mem, char *buf, int count)
default:
err = EFAULT;
}
- } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
- (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH
+ } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH))
#ifdef CONFIG_SMP
- || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
- (unsigned int)(mem + count) <=
- COREB_L1_CODE_START + L1_CODE_LENGTH
+ || (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH))
#endif
) {
/* access L1 instruction SRAM*/
@@ -658,12 +623,9 @@ int kgdb_ebin2mem(char *buf, char *mem, int count)
default:
return EFAULT;
}
- } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
- (unsigned int)(mem + count) < L1_CODE_START + L1_CODE_LENGTH
+ } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH))
#ifdef CONFIG_SMP
- || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
- (unsigned int)(mem + count) <=
- COREB_L1_CODE_START + L1_CODE_LENGTH
+ || (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH))
#endif
) {
/* access L1 instruction SRAM */
@@ -723,12 +685,9 @@ int kgdb_hex2mem(char *buf, char *mem, int count)
default:
return EFAULT;
}
- } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
- (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH
+ } else if ((cpu == 0 && IN_MEM(mem, count, L1_CODE_START, L1_CODE_LENGTH))
#ifdef CONFIG_SMP
- || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
- (unsigned int)(mem + count) <=
- COREB_L1_CODE_START + L1_CODE_LENGTH
+ || (cpu == 1 && IN_MEM(mem, count, COREB_L1_CODE_START, L1_CODE_LENGTH))
#endif
) {
/* access L1 instruction SRAM */
@@ -745,24 +704,16 @@ int kgdb_validate_break_address(unsigned long addr)
if (addr >= 0x1000 && (addr + BREAK_INSTR_SIZE) <= physical_mem_end)
return 0;
- if (addr >= ASYNC_BANK0_BASE
- && addr + BREAK_INSTR_SIZE <= ASYNC_BANK3_BASE + ASYNC_BANK3_BASE)
+ if (IN_MEM(addr, BREAK_INSTR_SIZE, ASYNC_BANK0_BASE, ASYNC_BANK_SIZE))
return 0;
-#if L1_CODE_LENGTH != 0
- if (cpu == 0 && addr >= L1_CODE_START
- && addr + BREAK_INSTR_SIZE <= L1_CODE_START + L1_CODE_LENGTH)
+ if (cpu == 0 && IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH))
return 0;
-# ifdef CONFIG_SMP
- else if (cpu == 1 && addr >= COREB_L1_CODE_START
- && addr + BREAK_INSTR_SIZE <= COREB_L1_CODE_START + L1_CODE_LENGTH)
+#ifdef CONFIG_SMP
+ else if (cpu == 1 && IN_MEM(addr, BREAK_INSTR_SIZE, COREB_L1_CODE_START, L1_CODE_LENGTH))
return 0;
-# endif
#endif
-#if L2_LENGTH != 0
- if (addr >= L2_START
- && addr + BREAK_INSTR_SIZE <= L2_START + L2_LENGTH)
+ if (IN_MEM(addr, BREAK_INSTR_SIZE, L2_START, L2_LENGTH))
return 0;
-#endif
return EFAULT;
}
@@ -772,13 +723,9 @@ int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
int err;
int cpu = raw_smp_processor_id();
- if ((cpu == 0 && (unsigned int)addr >= L1_CODE_START
- && (unsigned int)(addr + BREAK_INSTR_SIZE)
- < L1_CODE_START + L1_CODE_LENGTH)
+ if ((cpu == 0 && IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH))
#ifdef CONFIG_SMP
- || (cpu == 1 && (unsigned int)addr >= COREB_L1_CODE_START
- && (unsigned int)(addr + BREAK_INSTR_SIZE)
- < COREB_L1_CODE_START + L1_CODE_LENGTH)
+ || (cpu == 1 && IN_MEM(addr, BREAK_INSTR_SIZE, COREB_L1_CODE_START, L1_CODE_LENGTH))
#endif
) {
/* access L1 instruction SRAM */
@@ -804,9 +751,7 @@ int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
{
- if ((unsigned int)addr >= L1_CODE_START &&
- (unsigned int)(addr + BREAK_INSTR_SIZE) <
- L1_CODE_START + L1_CODE_LENGTH) {
+ if (IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH)) {
/* access L1 instruction SRAM */
if (dma_memcpy((void *)addr, bundle, BREAK_INSTR_SIZE) == NULL)
return -EFAULT;
diff --git a/arch/blackfin/kernel/kgdb_test.c b/arch/blackfin/kernel/kgdb_test.c
new file mode 100644
index 000000000000..3dba9c17304a
--- /dev/null
+++ b/arch/blackfin/kernel/kgdb_test.c
@@ -0,0 +1,123 @@
+/*
+ * arch/blackfin/kernel/kgdb_test.c - Blackfin kgdb tests
+ *
+ * Copyright 2005-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+
+#include <asm/current.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <asm/blackfin.h>
+
+static char cmdline[256];
+static unsigned long len;
+
+static int num1 __attribute__((l1_data));
+
+void kgdb_l1_test(void) __attribute__((l1_text));
+
+void kgdb_l1_test(void)
+{
+ printk(KERN_ALERT "L1(before change) : data variable addr = 0x%p, data value is %d\n", &num1, num1);
+ printk(KERN_ALERT "L1 : code function addr = 0x%p\n", kgdb_l1_test);
+ num1 = num1 + 10 ;
+ printk(KERN_ALERT "L1(after change) : data variable addr = 0x%p, data value is %d\n", &num1, num1);
+ return ;
+}
+#if L2_LENGTH
+
+static int num2 __attribute__((l2));
+void kgdb_l2_test(void) __attribute__((l2));
+
+void kgdb_l2_test(void)
+{
+ printk(KERN_ALERT "L2(before change) : data variable addr = 0x%p, data value is %d\n", &num2, num2);
+ printk(KERN_ALERT "L2 : code function addr = 0x%p\n", kgdb_l2_test);
+ num2 = num2 + 20 ;
+ printk(KERN_ALERT "L2(after change) : data variable addr = 0x%p, data value is %d\n", &num2, num2);
+ return ;
+}
+
+#endif
+
+
+int kgdb_test(char *name, int len, int count, int z)
+{
+ printk(KERN_DEBUG "kgdb name(%d): %s, %d, %d\n", len, name, count, z);
+ count = z;
+ return count;
+}
+
+static int test_proc_output(char *buf)
+{
+ kgdb_test("hello world!", 12, 0x55, 0x10);
+ kgdb_l1_test();
+ #if L2_LENGTH
+ kgdb_l2_test();
+ #endif
+
+ return 0;
+}
+
+static int test_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+
+ len = test_proc_output(page);
+ if (len <= off+count)
+ *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
+ return len;
+}
+
+static int test_write_proc(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ if (count >= 256)
+ len = 255;
+ else
+ len = count;
+
+ memcpy(cmdline, buffer, count);
+ cmdline[len] = 0;
+
+ return len;
+}
+
+static int __init kgdbtest_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_entry("kgdbtest", 0, NULL);
+ if (entry == NULL)
+ return -ENOMEM;
+
+ entry->read_proc = test_read_proc;
+ entry->write_proc = test_write_proc;
+ entry->data = NULL;
+
+ return 0;
+}
+
+static void __exit kgdbtest_exit(void)
+{
+ remove_proc_entry("kgdbtest", NULL);
+}
+
+module_init(kgdbtest_init);
+module_exit(kgdbtest_exit);
+MODULE_LICENSE("GPL");
diff --git a/arch/blackfin/kernel/mcount.S b/arch/blackfin/kernel/mcount.S
new file mode 100644
index 000000000000..edcfb3865f46
--- /dev/null
+++ b/arch/blackfin/kernel/mcount.S
@@ -0,0 +1,70 @@
+/*
+ * linux/arch/blackfin/mcount.S
+ *
+ * Copyright (C) 2006 Analog Devices Inc.
+ *
+ * 2007/04/12 Save index, length, modify and base registers. --rpm
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+
+.text
+
+.align 4 /* just in case */
+
+ENTRY(__mcount)
+ [--sp] = i0;
+ [--sp] = i1;
+ [--sp] = i2;
+ [--sp] = i3;
+ [--sp] = l0;
+ [--sp] = l1;
+ [--sp] = l2;
+ [--sp] = l3;
+ [--sp] = m0;
+ [--sp] = m1;
+ [--sp] = m2;
+ [--sp] = m3;
+ [--sp] = b0;
+ [--sp] = b1;
+ [--sp] = b2;
+ [--sp] = b3;
+ [--sp] = ( r7:0, p5:0 );
+ [--sp] = ASTAT;
+
+ p1.L = _ipipe_trace_enable;
+ p1.H = _ipipe_trace_enable;
+ r7 = [p1];
+ CC = r7 == 0;
+ if CC jump out;
+ link 0x10;
+ r0 = 0x0;
+ [sp + 0xc] = r0; /* v */
+ r0 = 0x0; /* type: IPIPE_TRACE_FN */
+ r1 = rets;
+ p0 = [fp]; /* p0: Prior FP */
+ r2 = [p0 + 4]; /* r2: Prior RETS */
+ call ___ipipe_trace;
+ unlink;
+out:
+ ASTAT = [sp++];
+ ( r7:0, p5:0 ) = [sp++];
+ b3 = [sp++];
+ b2 = [sp++];
+ b1 = [sp++];
+ b0 = [sp++];
+ m3 = [sp++];
+ m2 = [sp++];
+ m1 = [sp++];
+ m0 = [sp++];
+ l3 = [sp++];
+ l2 = [sp++];
+ l1 = [sp++];
+ l0 = [sp++];
+ i3 = [sp++];
+ i2 = [sp++];
+ i1 = [sp++];
+ i0 = [sp++];
+ rts;
+ENDPROC(__mcount)
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index e1bebc80a5bf..1bd7f2d018a8 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -37,111 +37,6 @@
#include <asm/dma.h>
#include <asm/cacheflush.h>
-/*
- * handle arithmetic relocations.
- * See binutils/bfd/elf32-bfin.c for more details
- */
-#define RELOC_STACK_SIZE 100
-static uint32_t reloc_stack[RELOC_STACK_SIZE];
-static unsigned int reloc_stack_tos;
-
-#define is_reloc_stack_empty() ((reloc_stack_tos > 0)?0:1)
-
-static void reloc_stack_push(uint32_t value)
-{
- reloc_stack[reloc_stack_tos++] = value;
-}
-
-static uint32_t reloc_stack_pop(void)
-{
- return reloc_stack[--reloc_stack_tos];
-}
-
-static uint32_t reloc_stack_operate(unsigned int oper, struct module *mod)
-{
- uint32_t value;
-
- switch (oper) {
- case R_add:
- value = reloc_stack[reloc_stack_tos - 2] +
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_sub:
- value = reloc_stack[reloc_stack_tos - 2] -
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_mult:
- value = reloc_stack[reloc_stack_tos - 2] *
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_div:
- value = reloc_stack[reloc_stack_tos - 2] /
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_mod:
- value = reloc_stack[reloc_stack_tos - 2] %
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_lshift:
- value = reloc_stack[reloc_stack_tos - 2] <<
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_rshift:
- value = reloc_stack[reloc_stack_tos - 2] >>
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_and:
- value = reloc_stack[reloc_stack_tos - 2] &
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_or:
- value = reloc_stack[reloc_stack_tos - 2] |
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_xor:
- value = reloc_stack[reloc_stack_tos - 2] ^
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_land:
- value = reloc_stack[reloc_stack_tos - 2] &&
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_lor:
- value = reloc_stack[reloc_stack_tos - 2] ||
- reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 2;
- break;
- case R_neg:
- value = -reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos--;
- break;
- case R_comp:
- value = ~reloc_stack[reloc_stack_tos - 1];
- reloc_stack_tos -= 1;
- break;
- default:
- printk(KERN_WARNING "module %s: unhandled reloction\n",
- mod->name);
- return 0;
- }
-
- /* now push the new value back on stack */
- reloc_stack_push(value);
-
- return value;
-}
-
void *module_alloc(unsigned long size)
{
if (size == 0)
@@ -334,16 +229,18 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
undefined symbols have been resolved. */
sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rel[i].r_info);
- if (is_reloc_stack_empty()) {
- value = sym->st_value;
- } else {
- value = reloc_stack_pop();
- }
+ value = sym->st_value;
value += rel[i].r_addend;
pr_debug("location is %x, value is %x type is %d \n",
(unsigned int) location32, value,
ELF32_R_TYPE(rel[i].r_info));
-
+#ifdef CONFIG_SMP
+ if ((unsigned long)location16 >= COREB_L1_DATA_A_START) {
+ printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)",
+ mod->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+#endif
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_pcrel24:
@@ -355,6 +252,12 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
location32 = (uint32_t *) location16;
value -= (uint32_t) location32;
value >>= 1;
+ if ((value & 0xFF000000) != 0 &&
+ (value & 0xFF000000) != 0xFF000000) {
+ printk(KERN_ERR "module %s: relocation overflow\n",
+ mod->name);
+ return -ENOEXEC;
+ }
pr_debug("value is %x, before %x-%x after %x-%x\n", value,
*location16, *(location16 + 1),
(*location16 & 0xff00) | (value >> 16 & 0x00ff),
@@ -399,28 +302,6 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
pr_debug("before %x after %x\n", *location32, value);
*location32 = value;
break;
- case R_push:
- reloc_stack_push(value);
- break;
- case R_const:
- reloc_stack_push(rel[i].r_addend);
- break;
- case R_add:
- case R_sub:
- case R_mult:
- case R_div:
- case R_mod:
- case R_lshift:
- case R_rshift:
- case R_and:
- case R_or:
- case R_xor:
- case R_land:
- case R_lor:
- case R_neg:
- case R_comp:
- reloc_stack_operate(ELF32_R_TYPE(rel[i].r_info), mod);
- break;
default:
printk(KERN_ERR "module %s: Unknown relocation: %u\n",
mod->name, ELF32_R_TYPE(rel[i].r_info));
@@ -436,6 +317,7 @@ module_finalize(const Elf_Ehdr * hdr,
{
unsigned int i, strindex = 0, symindex = 0;
char *secstrings;
+ long err = 0;
secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
@@ -460,8 +342,10 @@ module_finalize(const Elf_Ehdr * hdr,
(strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
(hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
- apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
+ err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
symindex, i, mod);
+ if (err < 0)
+ return -ENOEXEC;
}
}
return 0;
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 0c3ea118b657..33e2e8993f7f 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -39,6 +39,7 @@
#include <asm/blackfin.h>
#include <asm/fixed_code.h>
+#include <asm/mem_map.h>
asmlinkage void ret_from_fork(void);
@@ -81,11 +82,14 @@ void cpu_idle(void)__attribute__((l1_text));
*/
static void default_idle(void)
{
- local_irq_disable();
+#ifdef CONFIG_IPIPE
+ ipipe_suspend_domain();
+#endif
+ local_irq_disable_hw();
if (!need_resched())
idle_with_irq_disabled();
- local_irq_enable();
+ local_irq_enable_hw();
}
/*
@@ -154,6 +158,7 @@ pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
NULL);
}
+EXPORT_SYMBOL(kernel_thread);
void flush_thread(void)
{
@@ -170,6 +175,13 @@ asmlinkage int bfin_clone(struct pt_regs *regs)
unsigned long clone_flags;
unsigned long newsp;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ if (current->rt.nr_cpus_allowed == num_possible_cpus()) {
+ current->cpus_allowed = cpumask_of_cpu(smp_processor_id());
+ current->rt.nr_cpus_allowed = 1;
+ }
+#endif
+
/* syscall2 puts clone_flags in r0 and usp in r1 */
clone_flags = regs->r0;
newsp = regs->r1;
@@ -337,22 +349,22 @@ int _access_ok(unsigned long addr, unsigned long size)
if (addr >= (unsigned long)__init_begin &&
addr + size <= (unsigned long)__init_end)
return 1;
- if (addr >= L1_SCRATCH_START
- && addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH)
+ if (addr >= get_l1_scratch_start()
+ && addr + size <= get_l1_scratch_start() + L1_SCRATCH_LENGTH)
return 1;
#if L1_CODE_LENGTH != 0
- if (addr >= L1_CODE_START + (_etext_l1 - _stext_l1)
- && addr + size <= L1_CODE_START + L1_CODE_LENGTH)
+ if (addr >= get_l1_code_start() + (_etext_l1 - _stext_l1)
+ && addr + size <= get_l1_code_start() + L1_CODE_LENGTH)
return 1;
#endif
#if L1_DATA_A_LENGTH != 0
- if (addr >= L1_DATA_A_START + (_ebss_l1 - _sdata_l1)
- && addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH)
+ if (addr >= get_l1_data_a_start() + (_ebss_l1 - _sdata_l1)
+ && addr + size <= get_l1_data_a_start() + L1_DATA_A_LENGTH)
return 1;
#endif
#if L1_DATA_B_LENGTH != 0
- if (addr >= L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1)
- && addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)
+ if (addr >= get_l1_data_b_start() + (_ebss_b_l1 - _sdata_b_l1)
+ && addr + size <= get_l1_data_b_start() + L1_DATA_B_LENGTH)
return 1;
#endif
#if L2_LENGTH != 0
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index 140bf00e9974..594e325b40e4 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -45,6 +45,7 @@
#include <asm/asm-offsets.h>
#include <asm/dma.h>
#include <asm/fixed_code.h>
+#include <asm/mem_map.h>
#define TEXT_OFFSET 0
/*
@@ -80,10 +81,12 @@ static inline struct pt_regs *get_user_regs(struct task_struct *task)
/*
* Get all user integer registers.
*/
-static inline int ptrace_getregs(struct task_struct *tsk, void __user * uregs)
+static inline int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
{
- struct pt_regs *regs = get_user_regs(tsk);
- return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
+ struct pt_regs regs;
+ memcpy(&regs, get_user_regs(tsk), sizeof(regs));
+ regs.usp = tsk->thread.usp;
+ return copy_to_user(uregs, &regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
}
/* Mapping from PT_xxx to the stack offset at which the register is
@@ -157,15 +160,15 @@ put_reg(struct task_struct *task, int regno, unsigned long data)
static inline int is_user_addr_valid(struct task_struct *child,
unsigned long start, unsigned long len)
{
- struct vm_list_struct *vml;
+ struct vm_area_struct *vma;
struct sram_list_struct *sraml;
/* overflow */
if (start + len < start)
return -EIO;
- for (vml = child->mm->context.vmlist; vml; vml = vml->next)
- if (start >= vml->vma->vm_start && start + len < vml->vma->vm_end)
+ vma = find_vma(child->mm, start);
+ if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
return 0;
for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
@@ -220,8 +223,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
pr_debug("ptrace: user address is valid\n");
- if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START
- && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) {
+ if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
+ && addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) {
safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp));
copied = sizeof(tmp);
@@ -300,8 +303,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
pr_debug("ptrace: user address is valid\n");
- if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START
- && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) {
+ if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start()
+ && addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) {
safe_dma_memcpy ((void *)(addr), &data, sizeof(data));
copied = sizeof(data);
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
index ae97ca407b0d..53d08dee8531 100644
--- a/arch/blackfin/kernel/reboot.c
+++ b/arch/blackfin/kernel/reboot.c
@@ -20,7 +20,7 @@
* reset while the Core B bit (on dual core parts) is cleared by
* the core reset.
*/
-__attribute__((l1_text))
+__attribute__ ((__l1_text__, __noreturn__))
static void bfin_reset(void)
{
/* Wait for completion of "system" events such as cache line
@@ -30,7 +30,11 @@ static void bfin_reset(void)
*/
__builtin_bfin_ssync();
- while (1) {
+ /* The bootrom checks to see how it was reset and will
+ * automatically perform a software reset for us when
+ * it starts executing after the core reset.
+ */
+ if (ANOMALY_05000353 || ANOMALY_05000386) {
/* Initiate System software reset. */
bfin_write_SWRST(0x7);
@@ -50,6 +54,11 @@ static void bfin_reset(void)
/* Clear System software reset */
bfin_write_SWRST(0);
+ /* The BF526 ROM will crash during reset */
+#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
+ bfin_read_SWRST();
+#endif
+
/* Wait for the SWRST write to complete. Cannot rely on SSYNC
* though as the System state is all reset now.
*/
@@ -60,10 +69,11 @@ static void bfin_reset(void)
: "a" (15 * 1)
: "LC1", "LB1", "LT1"
);
+ }
+ while (1)
/* Issue core reset */
asm("raise 1");
- }
}
__attribute__((weak))
@@ -75,14 +85,10 @@ void machine_restart(char *cmd)
{
native_machine_restart(cmd);
local_irq_disable();
- if (ANOMALY_05000353 || ANOMALY_05000386)
- bfin_reset();
+ if (smp_processor_id())
+ smp_call_function((void *)bfin_reset, 0, 1);
else
- /* the bootrom checks to see how it was reset and will
- * automatically perform a software reset for us when
- * it starts executing boot
- */
- asm("raise 1;");
+ bfin_reset();
}
__attribute__((weak))
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 71a9a8c53cea..e5c116230800 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -13,6 +13,7 @@
#include <linux/bootmem.h>
#include <linux/seq_file.h>
#include <linux/cpu.h>
+#include <linux/mm.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/pfn.h>
@@ -26,11 +27,10 @@
#include <asm/blackfin.h>
#include <asm/cplbinit.h>
#include <asm/div64.h>
+#include <asm/cpu.h>
#include <asm/fixed_code.h>
#include <asm/early_printk.h>
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
u16 _bfin_swrst;
EXPORT_SYMBOL(_bfin_swrst);
@@ -60,7 +60,7 @@ void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat,
#define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */
#define BFIN_MEMMAP_RAM 1
#define BFIN_MEMMAP_RESERVED 2
-struct bfin_memmap {
+static struct bfin_memmap {
int nr_map;
struct bfin_memmap_entry {
unsigned long long addr; /* start of memory segment */
@@ -79,29 +79,70 @@ static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata;
static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata;
static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata;
-void __init bfin_cache_init(void)
-{
+DEFINE_PER_CPU(struct blackfin_cpudata, cpu_data);
+
+static int early_init_clkin_hz(char *buf);
+
#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
- generate_cplb_tables();
+void __init generate_cplb_tables(void)
+{
+ unsigned int cpu;
+
+ generate_cplb_tables_all();
+ /* Generate per-CPU I&D CPLB tables */
+ for (cpu = 0; cpu < num_possible_cpus(); ++cpu)
+ generate_cplb_tables_cpu(cpu);
+}
#endif
+void __cpuinit bfin_setup_caches(unsigned int cpu)
+{
#ifdef CONFIG_BFIN_ICACHE
- bfin_icache_init();
- printk(KERN_INFO "Instruction Cache Enabled\n");
+ bfin_icache_init(icplb_tbl[cpu]);
#endif
#ifdef CONFIG_BFIN_DCACHE
- bfin_dcache_init();
- printk(KERN_INFO "Data Cache Enabled"
+ bfin_dcache_init(dcplb_tbl[cpu]);
+#endif
+
+ /*
+ * In cache coherence emulation mode, we need to have the
+ * D-cache enabled before running any atomic operation which
+ * might invove cache invalidation (i.e. spinlock, rwlock).
+ * So printk's are deferred until then.
+ */
+#ifdef CONFIG_BFIN_ICACHE
+ printk(KERN_INFO "Instruction Cache Enabled for CPU%u\n", cpu);
+#endif
+#ifdef CONFIG_BFIN_DCACHE
+ printk(KERN_INFO "Data Cache Enabled for CPU%u"
# if defined CONFIG_BFIN_WB
" (write-back)"
# elif defined CONFIG_BFIN_WT
" (write-through)"
# endif
- "\n");
+ "\n", cpu);
#endif
}
+void __cpuinit bfin_setup_cpudata(unsigned int cpu)
+{
+ struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu);
+
+ cpudata->idle = current;
+ cpudata->loops_per_jiffy = loops_per_jiffy;
+ cpudata->imemctl = bfin_read_IMEM_CONTROL();
+ cpudata->dmemctl = bfin_read_DMEM_CONTROL();
+}
+
+void __init bfin_cache_init(void)
+{
+#if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE)
+ generate_cplb_tables();
+#endif
+ bfin_setup_caches(0);
+}
+
void __init bfin_relocate_l1_mem(void)
{
unsigned long l1_code_length;
@@ -109,6 +150,8 @@ void __init bfin_relocate_l1_mem(void)
unsigned long l1_data_b_length;
unsigned long l2_length;
+ blackfin_dma_early_init();
+
l1_code_length = _etext_l1 - _stext_l1;
if (l1_code_length > L1_CODE_LENGTH)
panic("L1 Instruction SRAM Overflow\n");
@@ -230,7 +273,7 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
/* record all known change-points (starting and ending addresses),
omitting those that are for empty memory regions */
chgidx = 0;
- for (i = 0; i < old_nr; i++) {
+ for (i = 0; i < old_nr; i++) {
if (map[i].size != 0) {
change_point[chgidx]->addr = map[i].addr;
change_point[chgidx++]->pentry = &map[i];
@@ -238,13 +281,13 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
change_point[chgidx++]->pentry = &map[i];
}
}
- chg_nr = chgidx; /* true number of change-points */
+ chg_nr = chgidx; /* true number of change-points */
/* sort change-point list by memory addresses (low -> high) */
still_changing = 1;
- while (still_changing) {
+ while (still_changing) {
still_changing = 0;
- for (i = 1; i < chg_nr; i++) {
+ for (i = 1; i < chg_nr; i++) {
/* if <current_addr> > <last_addr>, swap */
/* or, if current=<start_addr> & last=<end_addr>, swap */
if ((change_point[i]->addr < change_point[i-1]->addr) ||
@@ -261,10 +304,10 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
}
/* create a new memmap, removing overlaps */
- overlap_entries = 0; /* number of entries in the overlap table */
- new_entry = 0; /* index for creating new memmap entries */
- last_type = 0; /* start with undefined memory type */
- last_addr = 0; /* start with 0 as last starting address */
+ overlap_entries = 0; /* number of entries in the overlap table */
+ new_entry = 0; /* index for creating new memmap entries */
+ last_type = 0; /* start with undefined memory type */
+ last_addr = 0; /* start with 0 as last starting address */
/* loop through change-points, determining affect on the new memmap */
for (chgidx = 0; chgidx < chg_nr; chgidx++) {
/* keep track of all overlapping memmap entries */
@@ -286,14 +329,14 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
if (overlap_list[i]->type > current_type)
current_type = overlap_list[i]->type;
/* continue building up new memmap based on this information */
- if (current_type != last_type) {
+ if (current_type != last_type) {
if (last_type != 0) {
new_map[new_entry].size =
change_point[chgidx]->addr - last_addr;
/* move forward only if the new size was non-zero */
if (new_map[new_entry].size != 0)
if (++new_entry >= BFIN_MEMMAP_MAX)
- break; /* no more space left for new entries */
+ break; /* no more space left for new entries */
}
if (current_type != 0) {
new_map[new_entry].addr = change_point[chgidx]->addr;
@@ -303,9 +346,9 @@ static int __init sanitize_memmap(struct bfin_memmap_entry *map, int *pnr_map)
last_type = current_type;
}
}
- new_nr = new_entry; /* retain count for new entries */
+ new_nr = new_entry; /* retain count for new entries */
- /* copy new mapping into original location */
+ /* copy new mapping into original location */
memcpy(map, new_map, new_nr*sizeof(struct bfin_memmap_entry));
*pnr_map = new_nr;
@@ -361,7 +404,6 @@ static __init int parse_memmap(char *arg)
* - "memmap=XXX[KkmM][@][$]XXX[KkmM]" defines a memory region
* @ from <start> to <start>+<mem>, type RAM
* $ from <start> to <start>+<mem>, type RESERVED
- *
*/
static __init void parse_cmdline_early(char *cmdline_p)
{
@@ -383,14 +425,15 @@ static __init void parse_cmdline_early(char *cmdline_p)
if (*to != ' ') {
if (*to == '$'
|| *(to + 1) == '$')
- reserved_mem_dcache_on =
- 1;
+ reserved_mem_dcache_on = 1;
if (*to == '#'
|| *(to + 1) == '#')
- reserved_mem_icache_on =
- 1;
+ reserved_mem_icache_on = 1;
}
}
+ } else if (!memcmp(to, "clkin_hz=", 9)) {
+ to += 9;
+ early_init_clkin_hz(to);
} else if (!memcmp(to, "earlyprintk=", 12)) {
to += 12;
setup_early_printk(to);
@@ -417,9 +460,8 @@ static __init void parse_cmdline_early(char *cmdline_p)
* [_ramend - DMA_UNCACHED_REGION,
* _ramend]: uncached DMA region
* [_ramend, physical_mem_end]: memory not managed by kernel
- *
*/
-static __init void memory_setup(void)
+static __init void memory_setup(void)
{
#ifdef CONFIG_MTD_UCLINUX
unsigned long mtd_phys = 0;
@@ -436,7 +478,7 @@ static __init void memory_setup(void)
memory_end = _ramend - DMA_UNCACHED_REGION;
#ifdef CONFIG_MPU
- /* Round up to multiple of 4MB. */
+ /* Round up to multiple of 4MB */
memory_start = (_ramstart + 0x3fffff) & ~0x3fffff;
#else
memory_start = PAGE_ALIGN(_ramstart);
@@ -616,7 +658,7 @@ static __init void setup_bootmem_allocator(void)
end_pfn = memory_end >> PAGE_SHIFT;
/*
- * give all the memory to the bootmap allocator, tell it to put the
+ * give all the memory to the bootmap allocator, tell it to put the
* boot mem_map at the start of memory.
*/
bootmap_size = init_bootmem_node(NODE_DATA(0),
@@ -782,7 +824,15 @@ void __init setup_arch(char **cmdline_p)
flash_probe();
#endif
+ printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF);
+
+ /* Newer parts mirror SWRST bits in SYSCR */
+#if defined(CONFIG_BF53x) || defined(CONFIG_BF561) || \
+ defined(CONFIG_BF538) || defined(CONFIG_BF539)
_bfin_swrst = bfin_read_SWRST();
+#else
+ _bfin_swrst = bfin_read_SYSCR();
+#endif
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT);
@@ -791,7 +841,11 @@ void __init setup_arch(char **cmdline_p)
bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT);
#endif
+#ifdef CONFIG_SMP
+ if (_bfin_swrst & SWRST_DBL_FAULT_A) {
+#else
if (_bfin_swrst & RESET_DOUBLE) {
+#endif
printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n");
#ifdef CONFIG_DEBUG_DOUBLEFAULT
/* We assume the crashing kernel, and the current symbol table match */
@@ -807,7 +861,7 @@ void __init setup_arch(char **cmdline_p)
else if (_bfin_swrst & RESET_SOFTWARE)
printk(KERN_NOTICE "Reset caused by Software reset\n");
- printk(KERN_INFO "Blackfin support (C) 2004-2008 Analog Devices, Inc.\n");
+ printk(KERN_INFO "Blackfin support (C) 2004-2009 Analog Devices, Inc.\n");
if (bfin_compiled_revid() == 0xffff)
printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
else if (bfin_compiled_revid() == -1)
@@ -823,9 +877,12 @@ void __init setup_arch(char **cmdline_p)
if (bfin_compiled_revid() == -1)
printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n",
bfin_revid());
- else if (bfin_compiled_revid() != 0xffff)
+ else if (bfin_compiled_revid() != 0xffff) {
printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
bfin_compiled_revid(), bfin_revid());
+ if (bfin_compiled_revid() > bfin_revid())
+ panic("Error: you are missing anomaly workarounds for this rev\n");
+ }
}
if (bfin_revid() < CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX)
printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
@@ -835,7 +892,7 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
- cclk / 1000000, sclk / 1000000);
+ cclk / 1000000, sclk / 1000000);
if (ANOMALY_05000273 && (cclk >> 1) <= sclk)
printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n");
@@ -867,18 +924,21 @@ void __init setup_arch(char **cmdline_p)
BUG_ON((char *)&safe_user_instruction - (char *)&fixed_code_start
!= SAFE_USER_INSTRUCTION - FIXED_CODE_START);
+#ifdef CONFIG_SMP
+ platform_init_cpus();
+#endif
init_exception_vectors();
- bfin_cache_init();
+ bfin_cache_init(); /* Initialize caches for the boot CPU */
}
static int __init topology_init(void)
{
- int cpu;
+ unsigned int cpu;
+ /* Record CPU-private information for the boot processor. */
+ bfin_setup_cpudata(0);
for_each_possible_cpu(cpu) {
- struct cpu *c = &per_cpu(cpu_devices, cpu);
-
- register_cpu(c, cpu);
+ register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu);
}
return 0;
@@ -886,36 +946,54 @@ static int __init topology_init(void)
subsys_initcall(topology_init);
+/* Get the input clock frequency */
+static u_long cached_clkin_hz = CONFIG_CLKIN_HZ;
+static u_long get_clkin_hz(void)
+{
+ return cached_clkin_hz;
+}
+static int __init early_init_clkin_hz(char *buf)
+{
+ cached_clkin_hz = simple_strtoul(buf, NULL, 0);
+#ifdef BFIN_KERNEL_CLOCK
+ if (cached_clkin_hz != CONFIG_CLKIN_HZ)
+ panic("cannot change clkin_hz when reprogramming clocks");
+#endif
+ return 1;
+}
+early_param("clkin_hz=", early_init_clkin_hz);
+
/* Get the voltage input multiplier */
-static u_long cached_vco_pll_ctl, cached_vco;
static u_long get_vco(void)
{
- u_long msel;
+ static u_long cached_vco;
+ u_long msel, pll_ctl;
- u_long pll_ctl = bfin_read_PLL_CTL();
- if (pll_ctl == cached_vco_pll_ctl)
+ /* The assumption here is that VCO never changes at runtime.
+ * If, someday, we support that, then we'll have to change this.
+ */
+ if (cached_vco)
return cached_vco;
- else
- cached_vco_pll_ctl = pll_ctl;
+ pll_ctl = bfin_read_PLL_CTL();
msel = (pll_ctl >> 9) & 0x3F;
if (0 == msel)
msel = 64;
- cached_vco = CONFIG_CLKIN_HZ;
+ cached_vco = get_clkin_hz();
cached_vco >>= (1 & pll_ctl); /* DF bit */
cached_vco *= msel;
return cached_vco;
}
/* Get the Core clock */
-static u_long cached_cclk_pll_div, cached_cclk;
u_long get_cclk(void)
{
+ static u_long cached_cclk_pll_div, cached_cclk;
u_long csel, ssel;
if (bfin_read_PLL_STAT() & 0x1)
- return CONFIG_CLKIN_HZ;
+ return get_clkin_hz();
ssel = bfin_read_PLL_DIV();
if (ssel == cached_cclk_pll_div)
@@ -934,21 +1012,21 @@ u_long get_cclk(void)
EXPORT_SYMBOL(get_cclk);
/* Get the System clock */
-static u_long cached_sclk_pll_div, cached_sclk;
u_long get_sclk(void)
{
+ static u_long cached_sclk;
u_long ssel;
- if (bfin_read_PLL_STAT() & 0x1)
- return CONFIG_CLKIN_HZ;
-
- ssel = bfin_read_PLL_DIV();
- if (ssel == cached_sclk_pll_div)
+ /* The assumption here is that SCLK never changes at runtime.
+ * If, someday, we support that, then we'll have to change this.
+ */
+ if (cached_sclk)
return cached_sclk;
- else
- cached_sclk_pll_div = ssel;
- ssel &= 0xf;
+ if (bfin_read_PLL_STAT() & 0x1)
+ return get_clkin_hz();
+
+ ssel = bfin_read_PLL_DIV() & 0xf;
if (0 == ssel) {
printk(KERN_WARNING "Invalid System Clock\n");
ssel = 1;
@@ -982,17 +1060,18 @@ static int show_cpuinfo(struct seq_file *m, void *v)
{
char *cpu, *mmu, *fpu, *vendor, *cache;
uint32_t revid;
-
- u_long cclk = 0, sclk = 0;
+ int cpu_num = *(unsigned int *)v;
+ u_long sclk, cclk;
u_int icache_size = BFIN_ICACHESIZE / 1024, dcache_size = 0, dsup_banks = 0;
+ struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu_num);
cpu = CPU;
mmu = "none";
fpu = "none";
revid = bfin_revid();
- cclk = get_cclk();
sclk = get_sclk();
+ cclk = get_cclk();
switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) {
case 0xca:
@@ -1003,10 +1082,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
break;
}
- seq_printf(m, "processor\t: %d\n"
- "vendor_id\t: %s\n",
- *(unsigned int *)v,
- vendor);
+ seq_printf(m, "processor\t: %d\n" "vendor_id\t: %s\n", cpu_num, vendor);
if (CPUID == bfin_cpuid())
seq_printf(m, "cpu family\t: 0x%04x\n", CPUID);
@@ -1029,12 +1105,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
sclk/1000000, sclk%1000000);
seq_printf(m, "bogomips\t: %lu.%02lu\n"
"Calibration\t: %lu loops\n",
- (loops_per_jiffy * HZ) / 500000,
- ((loops_per_jiffy * HZ) / 5000) % 100,
- (loops_per_jiffy * HZ));
+ (cpudata->loops_per_jiffy * HZ) / 500000,
+ ((cpudata->loops_per_jiffy * HZ) / 5000) % 100,
+ (cpudata->loops_per_jiffy * HZ));
/* Check Cache configutation */
- switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
+ switch (cpudata->dmemctl & (1 << DMC0_P | 1 << DMC1_P)) {
case ACACHE_BSRAM:
cache = "dbank-A/B\t: cache/sram";
dcache_size = 16;
@@ -1058,10 +1134,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
}
/* Is it turned on? */
- if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE))
+ if ((cpudata->dmemctl & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE))
dcache_size = 0;
- if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) != (IMC | ENICPLB))
+ if ((cpudata->imemctl & (IMC | ENICPLB)) != (IMC | ENICPLB))
icache_size = 0;
seq_printf(m, "cache size\t: %d KB(L1 icache) "
@@ -1086,8 +1162,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS,
BFIN_DLINES);
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ seq_printf(m, "SMP Dcache Flushes\t: %lu\n\n", cpudata->dcache_invld_count);
+#endif
#ifdef CONFIG_BFIN_ICACHE_LOCK
- switch ((bfin_read_IMEM_CONTROL() >> 3) & WAYALL_L) {
+ switch ((cpudata->imemctl >> 3) & WAYALL_L) {
case WAY0_L:
seq_printf(m, "Way0 Locked-Down\n");
break;
@@ -1137,6 +1216,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "No Ways are locked\n");
}
#endif
+
+ if (cpu_num != num_possible_cpus() - 1)
+ return 0;
+
+ if (L2_LENGTH)
+ seq_printf(m, "L2 SRAM\t\t: %dKB\n", L2_LENGTH/0x400);
seq_printf(m, "board name\t: %s\n", bfin_board_name);
seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n",
physical_mem_end >> 10, (void *)0, (void *)physical_mem_end);
@@ -1144,6 +1229,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
((int)memory_end - (int)_stext) >> 10,
_stext,
(void *)memory_end);
+ seq_printf(m, "\n");
return 0;
}
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c
index e887efc86c29..0ed2badfd746 100644
--- a/arch/blackfin/kernel/time-ts.c
+++ b/arch/blackfin/kernel/time-ts.c
@@ -162,7 +162,6 @@ static struct clock_event_device clockevent_bfin = {
.name = "bfin_core_timer",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.shift = 32,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = bfin_timer_set_next_event,
.set_mode = bfin_timer_set_mode,
};
@@ -193,6 +192,7 @@ static int __init bfin_clockevent_init(void)
clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift);
clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
+ clockevent_bfin.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_bfin);
return 0;
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index eb2352320454..172b4c588467 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -1,32 +1,11 @@
/*
- * File: arch/blackfin/kernel/time.c
- * Based on: none - original work
- * Author:
+ * arch/blackfin/kernel/time.c
*
- * Created:
- * Description: This file contains the bfin-specific time handling details.
- * Most of the stuff is located in the machine specific files.
- * FIXME: (This file is subject for removal)
+ * This file contains the Blackfin-specific time handling details.
+ * Most of the stuff is located in the machine specific files.
*
- * Modified:
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
@@ -34,23 +13,43 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/irq.h>
+#include <linux/delay.h>
#include <asm/blackfin.h>
#include <asm/time.h>
+#include <asm/gptimers.h>
/* This is an NTP setting */
#define TICK_SIZE (tick_nsec / 1000)
-static void time_sched_init(irq_handler_t timer_routine);
-static unsigned long gettimeoffset(void);
-
static struct irqaction bfin_timer_irq = {
- .name = "BFIN Timer Tick",
+ .name = "Blackfin Timer Tick",
+#ifdef CONFIG_IRQ_PER_CPU
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+#else
.flags = IRQF_DISABLED
+#endif
};
-static void
-time_sched_init(irq_handler_t timer_routine)
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+void __init setup_system_timer0(void)
+{
+ /* Power down the core timer, just to play safe. */
+ bfin_write_TCNTL(0);
+
+ disable_gptimers(TIMER0bit);
+ set_gptimer_status(0, TIMER_STATUS_TRUN0);
+ while (get_gptimer_status(0) & TIMER_STATUS_TRUN0)
+ udelay(10);
+
+ set_gptimer_config(0, 0x59); /* IRQ enable, periodic, PWM_OUT, SCLKed, OUT PAD disabled */
+ set_gptimer_period(TIMER0_id, get_sclk() / HZ);
+ set_gptimer_pwidth(TIMER0_id, 1);
+ SSYNC();
+ enable_gptimers(TIMER0bit);
+}
+#else
+void __init setup_core_timer(void)
{
u32 tcount;
@@ -58,10 +57,8 @@ time_sched_init(irq_handler_t timer_routine)
bfin_write_TCNTL(1);
CSYNC();
- /*
- * the TSCALE prescaler counter.
- */
- bfin_write_TSCALE((TIME_SCALE - 1));
+ /* the TSCALE prescaler counter */
+ bfin_write_TSCALE(TIME_SCALE - 1);
tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
bfin_write_TPERIOD(tcount);
@@ -71,35 +68,52 @@ time_sched_init(irq_handler_t timer_routine)
CSYNC();
bfin_write_TCNTL(7);
+}
+#endif
- bfin_timer_irq.handler = (irq_handler_t)timer_routine;
- /* call setup_irq instead of request_irq because request_irq calls
- * kmalloc which has not been initialized yet
- */
+static void __init
+time_sched_init(irqreturn_t(*timer_routine) (int, void *))
+{
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+ setup_system_timer0();
+ bfin_timer_irq.handler = timer_routine;
+ setup_irq(IRQ_TIMER0, &bfin_timer_irq);
+#else
+ setup_core_timer();
+ bfin_timer_irq.handler = timer_routine;
setup_irq(IRQ_CORETMR, &bfin_timer_irq);
+#endif
}
/*
* Should return useconds since last timer tick
*/
+#ifndef CONFIG_GENERIC_TIME
static unsigned long gettimeoffset(void)
{
unsigned long offset;
unsigned long clocks_per_jiffy;
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+ clocks_per_jiffy = bfin_read_TIMER0_PERIOD();
+ offset = bfin_read_TIMER0_COUNTER() / \
+ (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
+
+ if ((get_gptimer_status(0) & TIMER_STATUS_TIMIL0) && offset < (100000 / HZ / 2))
+ offset += (USEC_PER_SEC / HZ);
+#else
clocks_per_jiffy = bfin_read_TPERIOD();
- offset =
- (clocks_per_jiffy -
- bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) /
- USEC_PER_SEC);
+ offset = (clocks_per_jiffy - bfin_read_TCOUNT()) / \
+ (((clocks_per_jiffy + 1) * HZ) / USEC_PER_SEC);
/* Check if we just wrapped the counters and maybe missed a tick */
if ((bfin_read_ILAT() & (1 << IRQ_CORETMR))
- && (offset < (100000 / HZ / 2)))
+ && (offset < (100000 / HZ / 2)))
offset += (USEC_PER_SEC / HZ);
-
+#endif
return offset;
}
+#endif
static inline int set_rtc_mmss(unsigned long nowtime)
{
@@ -111,43 +125,49 @@ static inline int set_rtc_mmss(unsigned long nowtime)
* as well as call the "do_timer()" routine every clocktick
*/
#ifdef CONFIG_CORE_TIMER_IRQ_L1
-irqreturn_t timer_interrupt(int irq, void *dummy)__attribute__((l1_text));
+__attribute__((l1_text))
#endif
-
irqreturn_t timer_interrupt(int irq, void *dummy)
{
/* last time the cmos clock got updated */
static long last_rtc_update;
write_seqlock(&xtime_lock);
-
- do_timer(1);
-
- profile_tick(CPU_PROFILING);
-
- /*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
-
- if (ntp_synced() &&
- xtime.tv_sec > last_rtc_update + 660 &&
- (xtime.tv_nsec / NSEC_PER_USEC) >=
- 500000 - ((unsigned)TICK_SIZE) / 2
- && (xtime.tv_nsec / NSEC_PER_USEC) <=
- 500000 + ((unsigned)TICK_SIZE) / 2) {
- if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- /* Do it again in 60s. */
- last_rtc_update = xtime.tv_sec - 600;
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
+/* FIXME: Here TIMIL0 is not set when IPIPE enabled, why? */
+ if (get_gptimer_status(0) & TIMER_STATUS_TIMIL0) {
+#endif
+ do_timer(1);
+
+ /*
+ * If we have an externally synchronized Linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if (ntp_synced() &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ (xtime.tv_nsec / NSEC_PER_USEC) >=
+ 500000 - ((unsigned)TICK_SIZE) / 2
+ && (xtime.tv_nsec / NSEC_PER_USEC) <=
+ 500000 + ((unsigned)TICK_SIZE) / 2) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ /* Do it again in 60s. */
+ last_rtc_update = xtime.tv_sec - 600;
+ }
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) && !defined(CONFIG_IPIPE)
+ set_gptimer_status(0, TIMER_STATUS_TIMIL0);
}
+#endif
write_sequnlock(&xtime_lock);
-#ifndef CONFIG_SMP
+#ifdef CONFIG_IPIPE
+ update_root_process_times(get_irq_regs());
+#else
update_process_times(user_mode(get_irq_regs()));
#endif
+ profile_tick(CPU_PROFILING);
return IRQ_HANDLED;
}
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index bef025b07443..ffe7fb53eccb 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/fs.h>
+#include <linux/rbtree.h>
#include <asm/traps.h>
#include <asm/cacheflush.h>
#include <asm/cplb.h>
@@ -75,16 +76,6 @@ void __init trap_init(void)
CSYNC();
}
-/*
- * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR
- * values across the transition from exception to IRQ5.
- * We put these in L1, so they are going to be in a valid
- * location during exception context
- */
-__attribute__((l1_data))
-unsigned long saved_retx, saved_seqstat,
- saved_icplb_fault_addr, saved_dcplb_fault_addr;
-
static void decode_address(char *buf, unsigned long address)
{
#ifdef CONFIG_DEBUG_VERBOSE
@@ -93,6 +84,7 @@ static void decode_address(char *buf, unsigned long address)
struct mm_struct *mm;
unsigned long flags, offset;
unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
+ struct rb_node *n;
#ifdef CONFIG_KALLSYMS
unsigned long symsize;
@@ -138,9 +130,10 @@ static void decode_address(char *buf, unsigned long address)
if (!mm)
continue;
- vml = mm->context.vmlist;
- while (vml) {
- struct vm_area_struct *vma = vml->vma;
+ for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) {
+ struct vm_area_struct *vma;
+
+ vma = rb_entry(n, struct vm_area_struct, vm_rb);
if (address >= vma->vm_start && address < vma->vm_end) {
char _tmpbuf[256];
@@ -186,8 +179,6 @@ static void decode_address(char *buf, unsigned long address)
goto done;
}
-
- vml = vml->next;
}
if (!in_atomic)
mmput(mm);
@@ -211,18 +202,18 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
+ unsigned int cpu = smp_processor_id();
char buf[150];
- decode_address(buf, saved_retx);
+ decode_address(buf, cpu_pda[cpu].retx);
printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
- (int)saved_seqstat & SEQSTAT_EXCAUSE, buf);
- decode_address(buf, saved_dcplb_fault_addr);
+ (unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf);
+ decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
- decode_address(buf, saved_icplb_fault_addr);
+ decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
decode_address(buf, fp->retx);
- printk(KERN_NOTICE "The instruction at %s caused a double exception\n",
- buf);
+ printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf);
} else
#endif
{
@@ -240,6 +231,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
int j;
#endif
+#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
+ unsigned int cpu = smp_processor_id();
+#endif
int sig = 0;
siginfo_t info;
unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
@@ -417,7 +411,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
info.si_code = ILL_CPLB_MULHIT;
sig = SIGSEGV;
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
- if (saved_dcplb_fault_addr < FIXED_CODE_START)
+ if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START)
verbose_printk(KERN_NOTICE "NULL pointer access\n");
else
#endif
@@ -471,7 +465,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
info.si_code = ILL_CPLB_MULHIT;
sig = SIGSEGV;
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
- if (saved_icplb_fault_addr < FIXED_CODE_START)
+ if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START)
verbose_printk(KERN_NOTICE "Jump to NULL address\n");
else
#endif
@@ -584,10 +578,15 @@ asmlinkage void trap_c(struct pt_regs *fp)
}
}
- info.si_signo = sig;
- info.si_errno = 0;
- info.si_addr = (void __user *)fp->pc;
- force_sig_info(sig, &info, current);
+#ifdef CONFIG_IPIPE
+ if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp))
+#endif
+ {
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_addr = (void __user *)fp->pc;
+ force_sig_info(sig, &info, current);
+ }
trace_buffer_restore(j);
return;
@@ -656,13 +655,13 @@ static bool get_instruction(unsigned short *val, unsigned short *address)
return false;
}
-/*
+/*
* decode the instruction if we are printing out the trace, as it
* makes things easier to follow, without running it through objdump
* These are the normal instructions which cause change of flow, which
* would be at the source of the trace buffer
*/
-#ifdef CONFIG_DEBUG_VERBOSE
+#if defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_BFIN_HWTRACE_ON)
static void decode_instruction(unsigned short *address)
{
unsigned short opcode;
@@ -674,6 +673,14 @@ static void decode_instruction(unsigned short *address)
verbose_printk("RTI");
else if (opcode == 0x0012)
verbose_printk("RTX");
+ else if (opcode == 0x0013)
+ verbose_printk("RTN");
+ else if (opcode == 0x0014)
+ verbose_printk("RTE");
+ else if (opcode == 0x0025)
+ verbose_printk("EMUEXCPT");
+ else if (opcode == 0x0040 && opcode <= 0x0047)
+ verbose_printk("STI R%i", opcode & 7);
else if (opcode >= 0x0050 && opcode <= 0x0057)
verbose_printk("JUMP (P%i)", opcode & 7);
else if (opcode >= 0x0060 && opcode <= 0x0067)
@@ -682,6 +689,10 @@ static void decode_instruction(unsigned short *address)
verbose_printk("CALL (PC+P%i)", opcode & 7);
else if (opcode >= 0x0080 && opcode <= 0x0087)
verbose_printk("JUMP (PC+P%i)", opcode & 7);
+ else if (opcode >= 0x0090 && opcode <= 0x009F)
+ verbose_printk("RAISE 0x%x", opcode & 0xF);
+ else if (opcode >= 0x00A0 && opcode <= 0x00AF)
+ verbose_printk("EXCPT 0x%x", opcode & 0xF);
else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF))
verbose_printk("IF !CC JUMP");
else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff))
@@ -821,11 +832,8 @@ void show_stack(struct task_struct *task, unsigned long *stack)
decode_address(buf, (unsigned int)stack);
printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
- addr = (unsigned int *)((unsigned int)stack & ~0x3F);
-
/* First thing is to look for a frame pointer */
- for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
- addr < endstack; addr++, i++) {
+ for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
if (*addr & 0x1)
continue;
ins_addr = (unsigned short *)*addr;
@@ -835,7 +843,8 @@ void show_stack(struct task_struct *task, unsigned long *stack)
if (fp) {
/* Let's check to see if it is a frame pointer */
- while (fp >= (addr - 1) && fp < endstack && fp)
+ while (fp >= (addr - 1) && fp < endstack
+ && fp && ((unsigned int) fp & 0x3) == 0)
fp = (unsigned int *)*fp;
if (fp == 0 || fp == endstack) {
fp = addr - 1;
@@ -846,7 +855,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
}
if (fp) {
frame = fp;
- printk(" FP: (0x%p)\n", fp);
+ printk(KERN_NOTICE " FP: (0x%p)\n", fp);
} else
frame = 0;
@@ -960,6 +969,7 @@ void dump_bfin_process(struct pt_regs *fp)
else
verbose_printk(KERN_NOTICE "COMM= invalid\n");
+ printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
@@ -1052,7 +1062,9 @@ void show_regs(struct pt_regs *fp)
char buf [150];
struct irqaction *action;
unsigned int i;
- unsigned long flags;
+ unsigned long flags = 0;
+ unsigned int cpu = smp_processor_id();
+ unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
@@ -1072,17 +1084,22 @@ void show_regs(struct pt_regs *fp)
}
verbose_printk(KERN_NOTICE " EXCAUSE : 0x%lx\n",
fp->seqstat & SEQSTAT_EXCAUSE);
- for (i = 6; i <= 15 ; i++) {
+ for (i = 2; i <= 15 ; i++) {
if (fp->ipend & (1 << i)) {
- decode_address(buf, bfin_read32(EVT0 + 4*i));
- verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf);
+ if (i != 4) {
+ decode_address(buf, bfin_read32(EVT0 + 4*i));
+ verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf);
+ } else
+ verbose_printk(KERN_NOTICE " interrupts disabled\n");
}
}
/* if no interrupts are going off, don't print this out */
if (fp->ipend & ~0x3F) {
for (i = 0; i < (NR_IRQS - 1); i++) {
- spin_lock_irqsave(&irq_desc[i].lock, flags);
+ if (!in_atomic)
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+
action = irq_desc[i].action;
if (!action)
goto unlock;
@@ -1095,7 +1112,8 @@ void show_regs(struct pt_regs *fp)
}
verbose_printk("\n");
unlock:
- spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ if (!in_atomic)
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
}
@@ -1112,9 +1130,9 @@ unlock:
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
(((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
- decode_address(buf, saved_dcplb_fault_addr);
+ decode_address(buf, cpu_pda[cpu].dcplb_fault_addr);
verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
- decode_address(buf, saved_icplb_fault_addr);
+ decode_address(buf, cpu_pda[cpu].icplb_fault_addr);
verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
}
@@ -1153,20 +1171,21 @@ unlock:
asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));
#endif
-asmlinkage int sys_bfin_spinlock(int *spinlock)
+static DEFINE_SPINLOCK(bfin_spinlock_lock);
+
+asmlinkage int sys_bfin_spinlock(int *p)
{
- int ret = 0;
- int tmp = 0;
+ int ret, tmp = 0;
- local_irq_disable();
- ret = get_user(tmp, spinlock);
- if (ret == 0) {
- if (tmp)
+ spin_lock(&bfin_spinlock_lock); /* This would also hold kernel preemption. */
+ ret = get_user(tmp, p);
+ if (likely(ret == 0)) {
+ if (unlikely(tmp))
ret = 1;
- tmp = 1;
- put_user(tmp, spinlock);
+ else
+ put_user(1, p);
}
- local_irq_enable();
+ spin_unlock(&bfin_spinlock_lock);
return ret;
}
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 7d12c6692a65..4b4341da0585 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -68,6 +68,8 @@ SECTIONS
__etext = .;
}
+ NOTES
+
/* Just in case the first read only is a 32-bit access */
RO_DATA(4)
@@ -109,7 +111,6 @@ SECTIONS
#endif
DATA_DATA
- *(.data.*)
CONSTRUCTORS
/* make sure the init_task is aligned to the
@@ -161,12 +162,14 @@ SECTIONS
*(.con_initcall.init)
___con_initcall_end = .;
}
+ PERCPU(4)
SECURITY_INIT
.init.ramfs :
{
. = ALIGN(4);
___initramfs_start = .;
*(.init.ramfs)
+ . = ALIGN(4);
___initramfs_end = .;
}
@@ -212,7 +215,7 @@ SECTIONS
__ebss_b_l1 = .;
}
- __l2_lma_start = .;
+ __l2_lma_start = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
.text_data_l2 L2_START : AT(LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1))
{
@@ -240,7 +243,7 @@ SECTIONS
/* Force trailing alignment of our init section so that when we
* free our init memory, we don't leave behind a partial page.
*/
- . = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
+ . = LOADADDR(.text_data_l2) + SIZEOF(.text_data_l2);
. = ALIGN(PAGE_SIZE);
___init_end = .;
diff --git a/arch/blackfin/lib/checksum.c b/arch/blackfin/lib/checksum.c
index 5c87505165d3..762a7f02970a 100644
--- a/arch/blackfin/lib/checksum.c
+++ b/arch/blackfin/lib/checksum.c
@@ -29,6 +29,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <linux/module.h>
#include <net/checksum.h>
#include <asm/checksum.h>
@@ -76,6 +77,7 @@ __sum16 ip_fast_csum(unsigned char *iph, unsigned int ihl)
{
return (__force __sum16)~do_csum(iph, ihl * 4);
}
+EXPORT_SYMBOL(ip_fast_csum);
/*
* computes the checksum of a memory block at buff, length len,
@@ -104,6 +106,7 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
return sum;
}
+EXPORT_SYMBOL(csum_partial);
/*
* this routine is used for miscellaneous IP-like checksums, mainly
@@ -137,3 +140,4 @@ __wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
memcpy(dst, src, len);
return csum_partial(dst, len, sum);
}
+EXPORT_SYMBOL(csum_partial_copy);
diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S
index d60554dce87b..1863a6ba507c 100644
--- a/arch/blackfin/lib/ins.S
+++ b/arch/blackfin/lib/ins.S
@@ -1,31 +1,9 @@
/*
- * File: arch/blackfin/lib/ins.S
- * Based on:
- * Author: Bas Vermeulen <bas@buyways.nl>
+ * arch/blackfin/lib/ins.S - ins{bwl} using hardware loops
*
- * Created: Tue Mar 22 15:27:24 CEST 2005
- * Description: Implementation of ins{bwl} for BlackFin processors using zero overhead loops.
- *
- * Modified:
- * Copyright 2004-2008 Analog Devices Inc.
- * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Copyright (C) 2005 Bas Vermeulen, BuyWays BV <bas@buyways.nl>
+ * Licensed under the GPL-2 or later.
*/
#include <linux/linkage.h>
@@ -33,6 +11,46 @@
.align 2
+#ifdef CONFIG_IPIPE
+# define DO_CLI \
+ [--sp] = rets; \
+ [--sp] = (P5:0); \
+ sp += -12; \
+ call ___ipipe_stall_root_raw; \
+ sp += 12; \
+ (P5:0) = [sp++];
+# define CLI_INNER_NOP
+#else
+# define DO_CLI cli R3;
+# define CLI_INNER_NOP nop; nop; nop;
+#endif
+
+#ifdef CONFIG_IPIPE
+# define DO_STI \
+ sp += -12; \
+ call ___ipipe_unstall_root_raw; \
+ sp += 12; \
+2: rets = [sp++];
+#else
+# define DO_STI 2: sti R3;
+#endif
+
+#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
+# define CLI_OUTER DO_CLI;
+# define STI_OUTER DO_STI;
+# define CLI_INNER 1:
+# if ANOMALY_05000416
+# define STI_INNER nop; 2: nop;
+# else
+# define STI_INNER 2:
+# endif
+#else
+# define CLI_OUTER
+# define STI_OUTER
+# define CLI_INNER 1: DO_CLI; CLI_INNER_NOP;
+# define STI_INNER DO_STI;
+#endif
+
/*
* Reads on the Blackfin are speculative. In Blackfin terms, this means they
* can be interrupted at any time (even after they have been issued on to the
@@ -53,170 +71,48 @@
* buffers in/out of FIFOs.
*/
-ENTRY(_insl)
-#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
- P0 = R0; /* P0 = port */
- cli R3;
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
-.Llong_loop_s: R0 = [P0];
- [P1++] = R0;
- NOP;
-.Llong_loop_e: NOP;
- sti R3;
- RTS;
-#else
- P0 = R0; /* P0 = port */
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Llong_loop_s, .Llong_loop_e) LC0 = P2;
-.Llong_loop_s:
- CLI R3;
- NOP; NOP; NOP;
- R0 = [P0];
- [P1++] = R0;
-.Llong_loop_e:
- STI R3;
+#define COMMON_INS(func, ops) \
+ENTRY(_ins##func) \
+ P0 = R0; /* P0 = port */ \
+ CLI_OUTER; /* 3 instructions before first read access */ \
+ P1 = R1; /* P1 = address */ \
+ P2 = R2; /* P2 = count */ \
+ SSYNC; \
+ \
+ LSETUP(1f, 2f) LC0 = P2; \
+ CLI_INNER; \
+ ops; \
+ STI_INNER; \
+ \
+ STI_OUTER; \
+ RTS; \
+ENDPROC(_ins##func)
- RTS;
-#endif
-ENDPROC(_insl)
-
-ENTRY(_insw)
-#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
- P0 = R0; /* P0 = port */
- cli R3;
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
-.Lword_loop_s: R0 = W[P0];
- W[P1++] = R0;
- NOP;
-.Lword_loop_e: NOP;
- sti R3;
- RTS;
-#else
- P0 = R0; /* P0 = port */
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Lword_loop_s, .Lword_loop_e) LC0 = P2;
-.Lword_loop_s:
- CLI R3;
- NOP; NOP; NOP;
- R0 = W[P0];
- W[P1++] = R0;
-.Lword_loop_e:
- STI R3;
- RTS;
-
-#endif
-ENDPROC(_insw)
-
-ENTRY(_insw_8)
-#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
- P0 = R0; /* P0 = port */
- cli R3;
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
-.Lword8_loop_s: R0 = W[P0];
- B[P1++] = R0;
- R0 = R0 >> 8;
- B[P1++] = R0;
- NOP;
-.Lword8_loop_e: NOP;
- sti R3;
- RTS;
-#else
- P0 = R0; /* P0 = port */
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Lword8_loop_s, .Lword8_loop_e) LC0 = P2;
-.Lword8_loop_s:
- CLI R3;
- NOP; NOP; NOP;
- R0 = W[P0];
- B[P1++] = R0;
- R0 = R0 >> 8;
- B[P1++] = R0;
- NOP;
-.Lword8_loop_e:
- STI R3;
+COMMON_INS(l, \
+ R0 = [P0]; \
+ [P1++] = R0; \
+)
- RTS;
-#endif
-ENDPROC(_insw_8)
+COMMON_INS(w, \
+ R0 = W[P0]; \
+ W[P1++] = R0; \
+)
-ENTRY(_insb)
-#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
- P0 = R0; /* P0 = port */
- cli R3;
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
-.Lbyte_loop_s: R0 = B[P0];
- B[P1++] = R0;
- NOP;
-.Lbyte_loop_e: NOP;
- sti R3;
- RTS;
-#else
- P0 = R0; /* P0 = port */
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Lbyte_loop_s, .Lbyte_loop_e) LC0 = P2;
-.Lbyte_loop_s:
- CLI R3;
- NOP; NOP; NOP;
- R0 = B[P0];
- B[P1++] = R0;
-.Lbyte_loop_e:
- STI R3;
+COMMON_INS(w_8, \
+ R0 = W[P0]; \
+ B[P1++] = R0; \
+ R0 = R0 >> 8; \
+ B[P1++] = R0; \
+)
- RTS;
-#endif
-ENDPROC(_insb)
+COMMON_INS(b, \
+ R0 = B[P0]; \
+ B[P1++] = R0; \
+)
-ENTRY(_insl_16)
-#ifdef CONFIG_BFIN_INS_LOWOVERHEAD
- P0 = R0; /* P0 = port */
- cli R3;
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
-.Llong16_loop_s: R0 = [P0];
- W[P1++] = R0;
- R0 = R0 >> 16;
- W[P1++] = R0;
- NOP;
-.Llong16_loop_e: NOP;
- sti R3;
- RTS;
-#else
- P0 = R0; /* P0 = port */
- P1 = R1; /* P1 = address */
- P2 = R2; /* P2 = count */
- SSYNC;
- LSETUP( .Llong16_loop_s, .Llong16_loop_e) LC0 = P2;
-.Llong16_loop_s:
- CLI R3;
- NOP; NOP; NOP;
- R0 = [P0];
- W[P1++] = R0;
- R0 = R0 >> 16;
- W[P1++] = R0;
-.Llong16_loop_e:
- STI R3;
- RTS;
-#endif
-ENDPROC(_insl_16)
+COMMON_INS(l_16, \
+ R0 = [P0]; \
+ W[P1++] = R0; \
+ R0 = R0 >> 16; \
+ W[P1++] = R0; \
+)
diff --git a/arch/blackfin/lib/muldi3.S b/arch/blackfin/lib/muldi3.S
new file mode 100644
index 000000000000..abde120ee230
--- /dev/null
+++ b/arch/blackfin/lib/muldi3.S
@@ -0,0 +1,68 @@
+.align 2
+.global ___muldi3;
+.type ___muldi3, STT_FUNC;
+
+#ifdef CONFIG_ARITHMETIC_OPS_L1
+.section .l1.text
+#else
+.text
+#endif
+
+/*
+ R1:R0 * R3:R2
+ = R1.h:R1.l:R0.h:R0.l * R3.h:R3.l:R2.h:R2.l
+[X] = (R1.h * R3.h) * 2^96
+[X] + (R1.h * R3.l + R1.l * R3.h) * 2^80
+[X] + (R1.h * R2.h + R1.l * R3.l + R3.h * R0.h) * 2^64
+[T1] + (R1.h * R2.l + R3.h * R0.l + R1.l * R2.h + R3.l * R0.h) * 2^48
+[T2] + (R1.l * R2.l + R3.l * R0.l + R0.h * R2.h) * 2^32
+[T3] + (R0.l * R2.h + R2.l * R0.h) * 2^16
+[T4] + (R0.l * R2.l)
+
+ We can discard the first three lines marked "X" since we produce
+ only a 64 bit result. So, we need ten 16-bit multiplies.
+
+ Individual mul-acc results:
+[E1] = R1.h * R2.l + R3.h * R0.l + R1.l * R2.h + R3.l * R0.h
+[E2] = R1.l * R2.l + R3.l * R0.l + R0.h * R2.h
+[E3] = R0.l * R2.h + R2.l * R0.h
+[E4] = R0.l * R2.l
+
+ We also need to add high parts from lower-level results to higher ones:
+ E[n]c = E[n] + (E[n+1]c >> 16), where E4c := E4
+
+ One interesting property is that all parts of the result that depend
+ on the sign of the multiplication are discarded. Those would be the
+ multiplications involving R1.h and R3.h, but only the top 16 bit of
+ the 32 bit result depend on the sign, and since R1.h and R3.h only
+ occur in E1, the top half of these results is cut off.
+ So, we can just use FU mode for all of the 16-bit multiplies, and
+ ignore questions of when to use mixed mode. */
+
+___muldi3:
+ /* [SP] technically is part of the caller's frame, but we can
+ use it as scratch space. */
+ A0 = R2.H * R1.L, A1 = R2.L * R1.H (FU) || R3 = [SP + 12]; /* E1 */
+ A0 += R3.H * R0.L, A1 += R3.L * R0.H (FU) || [SP] = R4; /* E1 */
+ A0 += A1; /* E1 */
+ R4 = A0.w;
+ A0 = R0.l * R3.l (FU); /* E2 */
+ A0 += R2.l * R1.l (FU); /* E2 */
+
+ A1 = R2.L * R0.L (FU); /* E4 */
+ R3 = A1.w;
+ A1 = A1 >> 16; /* E3c */
+ A0 += R2.H * R0.H, A1 += R2.L * R0.H (FU); /* E2, E3c */
+ A1 += R0.L * R2.H (FU); /* E3c */
+ R0 = A1.w;
+ A1 = A1 >> 16; /* E2c */
+ A0 += A1; /* E2c */
+ R1 = A0.w;
+
+ /* low(result) = low(E3c):low(E4) */
+ R0 = PACK (R0.l, R3.l);
+ /* high(result) = E2c + (E1 << 16) */
+ R1.h = R1.h + R4.l (NS) || R4 = [SP];
+ RTS;
+
+.size ___muldi3, .-___muldi3
diff --git a/arch/blackfin/lib/muldi3.c b/arch/blackfin/lib/muldi3.c
deleted file mode 100644
index 303d0c6a6dba..000000000000
--- a/arch/blackfin/lib/muldi3.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * File: arch/blackfin/lib/muldi3.c
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef SI_TYPE_SIZE
-#define SI_TYPE_SIZE 32
-#endif
-#define __ll_b (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((usitype) (t) % __ll_b)
-#define __ll_highpart(t) ((usitype) (t) / __ll_b)
-#define BITS_PER_UNIT 8
-
-#if !defined(umul_ppmm)
-#define umul_ppmm(w1, w0, u, v) \
- do { \
- usitype __x0, __x1, __x2, __x3; \
- usitype __ul, __vl, __uh, __vh; \
- \
- __ul = __ll_lowpart (u); \
- __uh = __ll_highpart (u); \
- __vl = __ll_lowpart (v); \
- __vh = __ll_highpart (v); \
- \
- __x0 = (usitype) __ul * __vl; \
- __x1 = (usitype) __ul * __vh; \
- __x2 = (usitype) __uh * __vl; \
- __x3 = (usitype) __uh * __vh; \
- \
- __x1 += __ll_highpart (__x0);/* this can't give carry */ \
- __x1 += __x2; /* but this indeed can */ \
- if (__x1 < __x2) /* did we get it? */ \
- __x3 += __ll_b; /* yes, add it in the proper pos. */ \
- \
- (w1) = __x3 + __ll_highpart (__x1); \
- (w0) = __ll_lowpart (__x1) * __ll_b + __ll_lowpart (__x0); \
- } while (0)
-#endif
-
-#if !defined(__umulsidi3)
-#define __umulsidi3(u, v) \
- ({diunion __w; \
- umul_ppmm (__w.s.high, __w.s.low, u, v); \
- __w.ll; })
-#endif
-
-typedef unsigned int usitype __attribute__ ((mode(SI)));
-typedef int sitype __attribute__ ((mode(SI)));
-typedef int ditype __attribute__ ((mode(DI)));
-typedef int word_type __attribute__ ((mode(__word__)));
-
-struct distruct {
- sitype low, high;
-};
-typedef union {
- struct distruct s;
- ditype ll;
-} diunion;
-
-#ifdef CONFIG_ARITHMETIC_OPS_L1
-ditype __muldi3(ditype u, ditype v)__attribute__((l1_text));
-#endif
-
-ditype __muldi3(ditype u, ditype v)
-{
- diunion w;
- diunion uu, vv;
-
- uu.ll = u, vv.ll = v;
- w.ll = __umulsidi3(uu.s.low, vv.s.low);
- w.s.high += ((usitype) uu.s.low * (usitype) vv.s.high
- + (usitype) uu.s.high * (usitype) vv.s.low);
-
- return w.ll;
-}
diff --git a/arch/blackfin/mach-bf518/Kconfig b/arch/blackfin/mach-bf518/Kconfig
new file mode 100644
index 000000000000..f397ede006bf
--- /dev/null
+++ b/arch/blackfin/mach-bf518/Kconfig
@@ -0,0 +1,233 @@
+if (BF51x)
+
+source "arch/blackfin/mach-bf518/boards/Kconfig"
+
+menu "BF518 Specific Configuration"
+
+comment "Alternative Multiplexing Scheme"
+
+choice
+ prompt "SPORT0"
+ default BF518_SPORT0_PORTG
+ help
+ Select PORT used for SPORT0. See Hardware Reference Manual
+
+config BF518_SPORT0_PORTF
+ bool "PORT F"
+ help
+ PORT F
+
+config BF518_SPORT0_PORTG
+ bool "PORT G"
+ help
+ PORT G
+endchoice
+
+choice
+ prompt "SPORT0 TSCLK Location"
+ depends on BF518_SPORT0_PORTG
+ default BF518_SPORT0_TSCLK_PG10
+ help
+ Select PIN used for SPORT0_TSCLK. See Hardware Reference Manual
+
+config BF518_SPORT0_TSCLK_PG10
+ bool "PORT PG10"
+ help
+ PORT PG10
+
+config BF518_SPORT0_TSCLK_PG14
+ bool "PORT PG14"
+ help
+ PORT PG14
+endchoice
+
+choice
+ prompt "UART1"
+ default BF518_UART1_PORTF
+ help
+ Select PORT used for UART1. See Hardware Reference Manual
+
+config BF518_UART1_PORTF
+ bool "PORT F"
+ help
+ PORT F
+
+config BF518_UART1_PORTG
+ bool "PORT G"
+ help
+ PORT G
+endchoice
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+ int "IRQ_PLL_WAKEUP"
+ default 7
+config IRQ_DMA0_ERROR
+ int "IRQ_DMA0_ERROR"
+ default 7
+config IRQ_DMAR0_BLK
+ int "IRQ_DMAR0_BLK"
+ default 7
+config IRQ_DMAR1_BLK
+ int "IRQ_DMAR1_BLK"
+ default 7
+config IRQ_DMAR0_OVR
+ int "IRQ_DMAR0_OVR"
+ default 7
+config IRQ_DMAR1_OVR
+ int "IRQ_DMAR1_OVR"
+ default 7
+config IRQ_PPI_ERROR
+ int "IRQ_PPI_ERROR"
+ default 7
+config IRQ_MAC_ERROR
+ int "IRQ_MAC_ERROR"
+ default 7
+config IRQ_SPORT0_ERROR
+ int "IRQ_SPORT0_ERROR"
+ default 7
+config IRQ_SPORT1_ERROR
+ int "IRQ_SPORT1_ERROR"
+ default 7
+config IRQ_PTP_ERROR
+ int "IRQ_PTP_ERROR"
+ default 7
+config IRQ_UART0_ERROR
+ int "IRQ_UART0_ERROR"
+ default 7
+config IRQ_UART1_ERROR
+ int "IRQ_UART1_ERROR"
+ default 7
+config IRQ_RTC
+ int "IRQ_RTC"
+ default 8
+config IRQ_PPI
+ int "IRQ_PPI"
+ default 8
+config IRQ_SPORT0_RX
+ int "IRQ_SPORT0_RX"
+ default 9
+config IRQ_SPORT0_TX
+ int "IRQ_SPORT0_TX"
+ default 9
+config IRQ_SPORT1_RX
+ int "IRQ_SPORT1_RX"
+ default 9
+config IRQ_SPORT1_TX
+ int "IRQ_SPORT1_TX"
+ default 9
+config IRQ_TWI
+ int "IRQ_TWI"
+ default 10
+config IRQ_SPI0
+ int "IRQ_SPI"
+ default 10
+config IRQ_UART0_RX
+ int "IRQ_UART0_RX"
+ default 10
+config IRQ_UART0_TX
+ int "IRQ_UART0_TX"
+ default 10
+config IRQ_UART1_RX
+ int "IRQ_UART1_RX"
+ default 10
+config IRQ_UART1_TX
+ int "IRQ_UART1_TX"
+ default 10
+config IRQ_OPTSEC
+ int "IRQ_OPTSEC"
+ default 11
+config IRQ_CNT
+ int "IRQ_CNT"
+ default 11
+config IRQ_MAC_RX
+ int "IRQ_MAC_RX"
+ default 11
+config IRQ_PORTH_INTA
+ int "IRQ_PORTH_INTA"
+ default 11
+config IRQ_MAC_TX
+ int "IRQ_MAC_TX/NFC"
+ default 11
+config IRQ_PORTH_INTB
+ int "IRQ_PORTH_INTB"
+ default 11
+config IRQ_TIMER0
+ int "IRQ_TIMER0"
+ default 8
+config IRQ_TIMER1
+ int "IRQ_TIMER1"
+ default 12
+config IRQ_TIMER2
+ int "IRQ_TIMER2"
+ default 12
+config IRQ_TIMER3
+ int "IRQ_TIMER3"
+ default 12
+config IRQ_TIMER4
+ int "IRQ_TIMER4"
+ default 12
+config IRQ_TIMER5
+ int "IRQ_TIMER5"
+ default 12
+config IRQ_TIMER6
+ int "IRQ_TIMER6"
+ default 12
+config IRQ_TIMER7
+ int "IRQ_TIMER7"
+ default 12
+config IRQ_PORTG_INTA
+ int "IRQ_PORTG_INTA"
+ default 12
+config IRQ_PORTG_INTB
+ int "IRQ_PORTG_INTB"
+ default 12
+config IRQ_MEM_DMA0
+ int "IRQ_MEM_DMA0"
+ default 13
+config IRQ_MEM_DMA1
+ int "IRQ_MEM_DMA1"
+ default 13
+config IRQ_WATCH
+ int "IRQ_WATCH"
+ default 13
+config IRQ_PORTF_INTA
+ int "IRQ_PORTF_INTA"
+ default 13
+config IRQ_PORTF_INTB
+ int "IRQ_PORTF_INTB"
+ default 13
+config IRQ_SPI0_ERROR
+ int "IRQ_SPI0_ERROR"
+ default 7
+config IRQ_SPI1_ERROR
+ int "IRQ_SPI1_ERROR"
+ default 7
+config IRQ_RSI_INT0
+ int "IRQ_RSI_INT0"
+ default 7
+config IRQ_RSI_INT1
+ int "IRQ_RSI_INT1"
+ default 7
+config IRQ_PWM_TRIP
+ int "IRQ_PWM_TRIP"
+ default 10
+config IRQ_PWM_SYNC
+ int "IRQ_PWM_SYNC"
+ default 10
+config IRQ_PTP_STAT
+ int "IRQ_PTP_STAT"
+ default 10
+
+ help
+ Enter the priority numbers between 7-13 ONLY. Others are Reserved.
+ This applies to all the above. It is not recommended to assign the
+ highest priority number 7 to UART or any other device.
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf518/Makefile b/arch/blackfin/mach-bf518/Makefile
new file mode 100644
index 000000000000..168a193f9f9a
--- /dev/null
+++ b/arch/blackfin/mach-bf518/Makefile
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf518/Makefile
+#
+
+obj-y := ints-priority.o dma.o
diff --git a/arch/blackfin/mach-bf518/boards/Kconfig b/arch/blackfin/mach-bf518/boards/Kconfig
new file mode 100644
index 000000000000..96163514ed22
--- /dev/null
+++ b/arch/blackfin/mach-bf518/boards/Kconfig
@@ -0,0 +1,12 @@
+choice
+ prompt "System type"
+ default BFIN518F_EZBRD
+ help
+ Select your board!
+
+config BFIN518F_EZBRD
+ bool "BF518F-EZBRD"
+ help
+ BF518-EZBRD board support.
+
+endchoice
diff --git a/arch/blackfin/mach-bf518/boards/Makefile b/arch/blackfin/mach-bf518/boards/Makefile
new file mode 100644
index 000000000000..172e859c3a7f
--- /dev/null
+++ b/arch/blackfin/mach-bf518/boards/Makefile
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf518/boards/Makefile
+#
+
+obj-$(CONFIG_BFIN518F_EZBRD) += ezbrd.o
diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c
new file mode 100644
index 000000000000..0e175342112e
--- /dev/null
+++ b/arch/blackfin/mach-bf518/boards/ezbrd.c
@@ -0,0 +1,714 @@
+/*
+ * File: arch/blackfin/mach-bf518/boards/ezbrd.c
+ * Based on: arch/blackfin/mach-bf527/boards/ezbrd.c
+ * Author: Bryan Wu <cooloney@kernel.org>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2005 National ICT Australia (NICTA)
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/dma.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/reboot.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+#include <asm/bfin_sdh.h>
+#include <linux/spi/ad7877.h>
+#include <net/dsa.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "ADI BF518F-EZBRD";
+
+/*
+ * Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition ezbrd_partitions[] = {
+ {
+ .name = "bootloader(nor)",
+ .size = 0x40000,
+ .offset = 0,
+ }, {
+ .name = "linux kernel(nor)",
+ .size = 0x1C0000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "file system(nor)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct physmap_flash_data ezbrd_flash_data = {
+ .width = 2,
+ .parts = ezbrd_partitions,
+ .nr_parts = ARRAY_SIZE(ezbrd_partitions),
+};
+
+static struct resource ezbrd_flash_resource = {
+ .start = 0x20000000,
+ .end = 0x203fffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ezbrd_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &ezbrd_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &ezbrd_flash_resource,
+};
+#endif
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
+static struct platform_device bfin_mac_device = {
+ .name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
+};
+#endif
+
+#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+static struct dsa_platform_data ksz8893m_switch_data = {
+ .mii_bus = &bfin_mii_bus.dev,
+ .netdev = &bfin_mac_device.dev,
+ .port_names[0] = NULL,
+ .port_names[1] = "eth%d",
+ .port_names[2] = "eth%d",
+ .port_names[3] = "cpu",
+};
+
+static struct platform_device ksz8893m_switch_device = {
+ .name = "dsa",
+ .id = 0,
+ .num_resources = 0,
+ .dev.platform_data = &ksz8893m_switch_data,
+};
+#endif
+
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader(spi)",
+ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+ .name = "linux kernel(spi)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+ .name = "m25p80",
+ .parts = bfin_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+ .type = "m25p16",
+};
+
+/* SPI flash chip (m25p64) */
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+ || defined(CONFIG_SPI_ADC_BF533_MODULE)
+/* SPI ADC chip */
+static struct bfin5xx_spi_chip spi_adc_chip_info = {
+ .enable_dma = 1, /* use dma transfer with this chip*/
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_NET_DSA_KSZ8893M) \
+ || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+/* SPI SWITCH CHIP */
+static struct bfin5xx_spi_chip spi_switch_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+static struct bfin5xx_spi_chip spi_mmc_chip_info = {
+ .enable_dma = 1,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_PBX)
+static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
+ .ctl_reg = 0x4, /* send zero */
+ .enable_dma = 0,
+ .bits_per_word = 8,
+ .cs_change_per_word = 1,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+
+static const struct ad7877_platform_data bfin_ad7877_ts_info = {
+ .model = 7877,
+ .vref_delay_usecs = 50, /* internal, no capacitor */
+ .x_plate_ohms = 419,
+ .y_plate_ohms = 486,
+ .pressure_max = 1000,
+ .pressure_min = 0,
+ .stopacq_polarity = 1,
+ .first_conversion_delay = 3,
+ .acquisition_time = 1,
+ .averaging = 1,
+ .pen_down_acc_interval = 1,
+};
+#endif
+
+#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
+ && defined(CONFIG_SND_SOC_WM8731_SPI)
+static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bfin_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+ {
+ /* the modalias must be the same as spi device driver name */
+ .modalias = "m25p80", /* Name of spi_driver for this device */
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/
+ .platform_data = &bfin_spi_flash_data,
+ .controller_data = &spi_flash_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_SPI_ADC_BF533) \
+ || defined(CONFIG_SPI_ADC_BF533_MODULE)
+ {
+ .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
+ .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* Framework chip select. */
+ .platform_data = NULL, /* No spi_driver specific config */
+ .controller_data = &spi_adc_chip_info,
+ },
+#endif
+
+#if defined(CONFIG_NET_DSA_KSZ8893M) \
+ || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+ {
+ .modalias = "ksz8893m",
+ .max_speed_hz = 5000000,
+ .bus_num = 0,
+ .chip_select = 1,
+ .platform_data = NULL,
+ .controller_data = &spi_switch_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+
+#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+ {
+ .modalias = "spi_mmc_dummy",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 0,
+ .platform_data = NULL,
+ .controller_data = &spi_mmc_chip_info,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "spi_mmc",
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = CONFIG_SPI_MMC_CS_CHAN,
+ .platform_data = NULL,
+ .controller_data = &spi_mmc_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_PBX)
+ {
+ .modalias = "fxs-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 8 - CONFIG_J11_JUMPER,
+ .controller_data = &spi_si3xxx_chip_info,
+ .mode = SPI_MODE_3,
+ },
+ {
+ .modalias = "fxo-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 8 - CONFIG_J19_JUMPER,
+ .controller_data = &spi_si3xxx_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
+ {
+ .modalias = "ad7877",
+ .platform_data = &bfin_ad7877_ts_info,
+ .irq = IRQ_PF8,
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 2,
+ .controller_data = &spi_ad7877_chip_info,
+ },
+#endif
+#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
+ && defined(CONFIG_SND_SOC_WM8731_SPI)
+ {
+ .modalias = "wm8731",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5,
+ .controller_data = &spi_wm8731_chip_info,
+ .mode = SPI_MODE_0,
+ },
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+ {
+ .modalias = "bfin-lq035q1-spi",
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &lq035q1_spi_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
+};
+
+/* SPI controller data */
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* SPI (0) */
+static struct bfin5xx_spi_master bfin_spi0_info = {
+ .num_chipselect = 5,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+ .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+static struct resource bfin_spi0_resource[] = {
+ [0] = {
+ .start = SPI0_REGBASE,
+ .end = SPI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI0,
+ .end = CH_SPI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_spi0_device = {
+ .name = "bfin-spi",
+ .id = 0, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+ .resource = bfin_spi0_resource,
+ .dev = {
+ .platform_data = &bfin_spi0_info, /* Passed to driver */
+ },
+};
+
+/* SPI (1) */
+static struct bfin5xx_spi_master bfin_spi1_info = {
+ .num_chipselect = 5,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+ .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
+};
+
+static struct resource bfin_spi1_resource[] = {
+ [0] = {
+ .start = SPI1_REGBASE,
+ .end = SPI1_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI1,
+ .end = CH_SPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_spi1_device = {
+ .name = "bfin-spi",
+ .id = 1, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi1_resource),
+ .resource = bfin_spi1_resource,
+ .dev = {
+ .platform_data = &bfin_spi1_info, /* Passed to driver */
+ },
+};
+#endif /* spi master and devices */
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart_resources),
+ .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir1_device = {
+ .name = "bfin_sir",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
+};
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+ [0] = {
+ .start = TWI0_REGBASE,
+ .end = TWI0_REGBASE,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI,
+ .end = IRQ_TWI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi_device = {
+ .name = "i2c-bfin-twi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+ .resource = bfin_twi0_resource,
+};
+#endif
+
+static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
+#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_lcd", 0x22),
+ },
+#endif
+#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
+ {
+ I2C_BOARD_INFO("pcf8574_keypad", 0x27),
+ .irq = IRQ_PF8,
+ },
+#endif
+};
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+static struct platform_device bfin_sport0_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 0,
+};
+
+static struct platform_device bfin_sport1_uart_device = {
+ .name = "bfin-sport-uart",
+ .id = 1,
+};
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button bfin_gpio_keys_table[] = {
+ {BTN_0, GPIO_PG0, 1, "gpio-keys: BTN0"},
+ {BTN_1, GPIO_PG13, 1, "gpio-keys: BTN1"},
+};
+
+static struct gpio_keys_platform_data bfin_gpio_keys_data = {
+ .buttons = bfin_gpio_keys_table,
+ .nbuttons = ARRAY_SIZE(bfin_gpio_keys_table),
+};
+
+static struct platform_device bfin_device_gpiokeys = {
+ .name = "gpio-keys",
+ .dev = {
+ .platform_data = &bfin_gpio_keys_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+
+static struct bfin_sd_host bfin_sdh_data = {
+ .dma_chan = CH_RSI,
+ .irq_int0 = IRQ_RSI_INT0,
+ .pin_req = {P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3, P_RSI_CMD, P_RSI_CLK, 0},
+};
+
+static struct platform_device bf51x_sdh_device = {
+ .name = "bfin-sdh",
+ .id = 0,
+ .dev = {
+ .platform_data = &bfin_sdh_data,
+ },
+};
+#endif
+
+static struct resource bfin_gpios_resources = {
+ .start = 0,
+ .end = MAX_BLACKFIN_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+ .name = "simple-gpio",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &bfin_gpios_resources,
+};
+
+static const unsigned int cclk_vlev_datasheet[] =
+{
+ VRPAIR(VLEV_100, 400000000),
+ VRPAIR(VLEV_105, 426000000),
+ VRPAIR(VLEV_110, 500000000),
+ VRPAIR(VLEV_115, 533000000),
+ VRPAIR(VLEV_120, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+ .tuple_tab = cclk_vlev_datasheet,
+ .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+ .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+ .name = "bfin dpmc",
+ .dev = {
+ .platform_data = &bfin_dmpc_vreg_data,
+ },
+};
+
+static struct platform_device *stamp_devices[] __initdata = {
+
+ &bfin_dpmc,
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
+ &bfin_mac_device,
+#endif
+
+#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
+ &ksz8893m_switch_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ &bfin_spi0_device,
+ &bfin_spi1_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+ &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
+ &bfin_sport0_uart_device,
+ &bfin_sport1_uart_device,
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+ &bfin_device_gpiokeys,
+#endif
+
+#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+ &bf51x_sdh_device,
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ &ezbrd_flash_device,
+#endif
+
+ &bfin_gpios_device,
+};
+
+static int __init ezbrd_init(void)
+{
+ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ i2c_register_board_info(0, bfin_i2c_board_info,
+ ARRAY_SIZE(bfin_i2c_board_info));
+ platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
+ spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
+ return 0;
+}
+
+arch_initcall(ezbrd_init);
+
+void native_machine_restart(char *cmd)
+{
+ /* workaround reboot hang when booting from SPI */
+ if ((bfin_read_SYSCR() & 0x7) == 0x3)
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
+}
+
+void bfin_get_ether_addr(char *addr)
+{
+ /* the MAC is stored in OTP memory page 0xDF */
+ u32 ret;
+ u64 otp_mac;
+ u32 (*otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)0xEF00001A;
+
+ ret = otp_read(0xDF, 0x00, &otp_mac);
+ if (!(ret & 0x1)) {
+ char *otp_mac_p = (char *)&otp_mac;
+ for (ret = 0; ret < 6; ++ret)
+ addr[ret] = otp_mac_p[5 - ret];
+ }
+}
+EXPORT_SYMBOL(bfin_get_ether_addr);
diff --git a/arch/blackfin/mach-bf518/dma.c b/arch/blackfin/mach-bf518/dma.c
new file mode 100644
index 000000000000..698e88ca5104
--- /dev/null
+++ b/arch/blackfin/mach-bf518/dma.c
@@ -0,0 +1,118 @@
+/*
+ * File: arch/blackfin/mach-bf518/dma.c
+ * Based on:
+ * Author: Bryan Wu <cooloney@kernel.org>
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/module.h>
+
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA11_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+};
+EXPORT_SYMBOL(dma_io_base_addr);
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI:
+ ret_irq = IRQ_PPI;
+ break;
+
+ case CH_EMAC_RX:
+ ret_irq = IRQ_MAC_RX;
+ break;
+
+ case CH_EMAC_TX:
+ ret_irq = IRQ_MAC_TX;
+ break;
+
+ case CH_UART1_RX:
+ ret_irq = IRQ_UART1_RX;
+ break;
+
+ case CH_UART1_TX:
+ ret_irq = IRQ_UART1_TX;
+ break;
+
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+
+ case CH_SPI0:
+ ret_irq = IRQ_SPI0;
+ break;
+
+ case CH_UART0_RX:
+ ret_irq = IRQ_UART0_RX;
+ break;
+
+ case CH_UART0_TX:
+ ret_irq = IRQ_UART0_TX;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM_DMA0;
+ break;
+
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM_DMA1;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf518/include/mach/anomaly.h b/arch/blackfin/mach-bf518/include/mach/anomaly.h
new file mode 100644
index 000000000000..e5b4bef0edae
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/anomaly.h
@@ -0,0 +1,79 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/anomaly.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+/* This file shoule be up to date with:
+ * - ????
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
+#define ANOMALY_05000074 (1)
+/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
+#define ANOMALY_05000122 (1)
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
+#define ANOMALY_05000245 (1)
+/* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
+#define ANOMALY_05000265 (1)
+/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
+#define ANOMALY_05000310 (1)
+/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+#define ANOMALY_05000366 (1)
+/* Lockbox SESR Firmware Does Not Save/Restore Full Context */
+#define ANOMALY_05000405 (1)
+/* Lockbox Firmware Memory Cleanup Routine Does not Clear Registers */
+#define ANOMALY_05000408 (1)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
+/* TWI Fall Time (Tof) May Violate the Minimum I2C Specification */
+#define ANOMALY_05000421 (1)
+/* TWI Input Capacitance (Ci) May Violate the Maximum I2C Specification */
+#define ANOMALY_05000422 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* Software System Reset Corrupts PLL_LOCKCNT Register */
+#define ANOMALY_05000430 (1)
+/* Incorrect Use of Stack in Lockbox Firmware During Authentication */
+#define ANOMALY_05000431 (1)
+/* Certain SIC Registers are not Reset After Soft or Core Double Fault Reset */
+#define ANOMALY_05000435 (1)
+/* PORTx_DRIVE and PORTx_HYSTERESIS Registers Read Back Incorrect Values */
+#define ANOMALY_05000438 (1)
+/* Preboot Cannot be Used to Program the PLL_DIV Register */
+#define ANOMALY_05000439 (1)
+/* bfrom_SysControl() Cannot be Used to Write the PLL_DIV Register */
+#define ANOMALY_05000440 (1)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
+/* Incorrect L1 Instruction Bank B Memory Map Location */
+#define ANOMALY_05000444 (1)
+
+/* Anomalies that don't exist on this proc */
+#define ANOMALY_05000125 (0)
+#define ANOMALY_05000158 (0)
+#define ANOMALY_05000183 (0)
+#define ANOMALY_05000198 (0)
+#define ANOMALY_05000230 (0)
+#define ANOMALY_05000244 (0)
+#define ANOMALY_05000261 (0)
+#define ANOMALY_05000263 (0)
+#define ANOMALY_05000266 (0)
+#define ANOMALY_05000273 (0)
+#define ANOMALY_05000285 (0)
+#define ANOMALY_05000307 (0)
+#define ANOMALY_05000311 (0)
+#define ANOMALY_05000312 (0)
+#define ANOMALY_05000323 (0)
+#define ANOMALY_05000353 (0)
+#define ANOMALY_05000363 (0)
+#define ANOMALY_05000386 (0)
+#define ANOMALY_05000412 (0)
+#define ANOMALY_05000432 (0)
+
+#endif
diff --git a/arch/blackfin/mach-bf518/include/mach/bf518.h b/arch/blackfin/mach-bf518/include/mach/bf518.h
new file mode 100644
index 000000000000..78da1a07ee73
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/bf518.h
@@ -0,0 +1,132 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/bf518.h
+ * Based on: include/asm-blackfin/mach-bf527/bf527.h
+ * Author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * Created:
+ * Description: SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF518
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __MACH_BF518_H__
+#define __MACH_BF518_H__
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15 0x8000
+#define IMASK_IVG14 0x4000
+#define IMASK_IVG13 0x2000
+#define IMASK_IVG12 0x1000
+
+#define IMASK_IVG11 0x0800
+#define IMASK_IVG10 0x0400
+#define IMASK_IVG9 0x0200
+#define IMASK_IVG8 0x0100
+
+#define IMASK_IVG7 0x0080
+#define IMASK_IVGTMR 0x0040
+#define IMASK_IVGHW 0x0020
+
+/***************************/
+
+#define BFIN_DSUBBANKS 4
+#define BFIN_DWAYS 2
+#define BFIN_DLINES 64
+#define BFIN_ISUBBANKS 4
+#define BFIN_IWAYS 4
+#define BFIN_ILINES 32
+
+#define WAY0_L 0x1
+#define WAY1_L 0x2
+#define WAY01_L 0x3
+#define WAY2_L 0x4
+#define WAY02_L 0x5
+#define WAY12_L 0x6
+#define WAY012_L 0x7
+
+#define WAY3_L 0x8
+#define WAY03_L 0x9
+#define WAY13_L 0xA
+#define WAY013_L 0xB
+
+#define WAY32_L 0xC
+#define WAY320_L 0xD
+#define WAY321_L 0xE
+#define WAYALL_L 0xF
+
+#define DMC_ENABLE (2<<2) /*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+#ifdef CONFIG_C_CDPRIO
+#define V_CDPRIO 0x100
+#else
+#define V_CDPRIO 0x0
+#endif
+
+#define AMGCTLVAL (V_AMBEN | V_AMCKEN | V_CDPRIO)
+
+#ifdef CONFIG_BF518
+#define CPU "BF518"
+#define CPUID 0x27e8
+#endif
+#ifdef CONFIG_BF516
+#define CPU "BF516"
+#define CPUID 0x27e8
+#endif
+#ifdef CONFIG_BF514
+#define CPU "BF514"
+#define CPUID 0x27e8
+#endif
+#ifdef CONFIG_BF512
+#define CPU "BF512"
+#define CPUID 0x27e8
+#endif
+
+#ifndef CPU
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
+#endif
+
+#endif /* __MACH_BF518_H__ */
diff --git a/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
new file mode 100644
index 000000000000..b50a63b975a2
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
@@ -0,0 +1,169 @@
+/*
+ * file: include/asm-blackfin/mach-bf518/bfin_serial_5xx.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ * blackfin serial driver head file
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER))
+#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR))
+#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_THR), v)
+#define UART_PUT_DLL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLL), v)
+#define UART_PUT_IER(uart, v) bfin_write16(((uart)->port.membase + OFFSET_IER), v)
+#define UART_SET_IER(uart, v) UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
+#define UART_CLEAR_IER(uart, v) UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
+#define UART_PUT_DLH(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLH), v)
+#define UART_PUT_LCR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_LCR), v)
+#define UART_PUT_GCTL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_GCTL), v)
+
+#define UART_SET_DLAB(uart) do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
+#define UART_CLEAR_DLAB(uart) do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
+
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
+#define UART_SET_RTS(x) gpio_set_value(x->rts_pin, 1)
+#define UART_CLEAR_RTS(x) gpio_set_value(x->rts_pin, 0)
+#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
+#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+# define CONFIG_SERIAL_BFIN_CTSRTS
+
+# ifndef CONFIG_UART0_CTS_PIN
+# define CONFIG_UART0_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART0_RTS_PIN
+# define CONFIG_UART0_RTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_CTS_PIN
+# define CONFIG_UART1_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_RTS_PIN
+# define CONFIG_UART1_RTS_PIN -1
+# endif
+#endif
+
+#define BFIN_UART_TX_FIFO_SIZE 2
+
+/*
+ * The pin configuration is different from schematic
+ */
+struct bfin_serial_port {
+ struct uart_port port;
+ unsigned int old_status;
+ unsigned int lsr;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ int tx_done;
+ int tx_count;
+ struct circ_buf rx_dma_buf;
+ struct timer_list rx_dma_timer;
+ int rx_dma_nrows;
+ unsigned int tx_dma_channel;
+ unsigned int rx_dma_channel;
+ struct work_struct tx_dma_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ struct timer_list cts_timer;
+ int cts_pin;
+ int rts_pin;
+#endif
+};
+
+/* The hardware clears the LSR bits upon read, so we need to cache
+ * some of the more fun bits in software so they don't get lost
+ * when checking the LSR in other code paths (TX).
+ */
+static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
+{
+ unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
+ uart->lsr |= (lsr & (BI|FE|PE|OE));
+ return lsr | uart->lsr;
+}
+
+static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+{
+ uart->lsr = 0;
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+}
+
+struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ unsigned int uart_tx_dma_channel;
+ unsigned int uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ int uart_cts_pin;
+ int uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ 0xFFC00400,
+ IRQ_UART0_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART0_TX,
+ CH_UART0_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+ CONFIG_UART0_CTS_PIN,
+ CONFIG_UART0_RTS_PIN,
+#endif
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ 0xFFC02000,
+ IRQ_UART1_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART1_TX,
+ CH_UART1_RX,
+#endif
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ CONFIG_UART1_CTS_PIN,
+ CONFIG_UART1_RTS_PIN,
+#endif
+ },
+#endif
+};
+
+#define DRIVER_NAME "bfin-uart"
diff --git a/arch/blackfin/mach-bf518/include/mach/blackfin.h b/arch/blackfin/mach-bf518/include/mach/blackfin.h
new file mode 100644
index 000000000000..d1a2b9ca6227
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/blackfin.h
@@ -0,0 +1,105 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF518_FAMILY
+
+#include "bf518.h"
+#include "mem_map.h"
+#include "defBF512.h"
+#include "anomaly.h"
+
+#if defined(CONFIG_BF518)
+#include "defBF518.h"
+#endif
+
+#if defined(CONFIG_BF516)
+#include "defBF516.h"
+#endif
+
+#if defined(CONFIG_BF514)
+#include "defBF514.h"
+#endif
+
+#if defined(CONFIG_BF512)
+#include "defBF512.h"
+#endif
+
+#if !defined(__ASSEMBLY__)
+#include "cdefBF512.h"
+
+#if defined(CONFIG_BF518)
+#include "cdefBF518.h"
+#endif
+
+#if defined(CONFIG_BF516)
+#include "cdefBF516.h"
+#endif
+
+#if defined(CONFIG_BF514)
+#include "cdefBF514.h"
+#endif
+#endif
+
+/* UART_IIR Register */
+#define STATUS(x) ((x << 1) & 0x06)
+#define STATUS_P1 0x02
+#define STATUS_P0 0x01
+
+#define BFIN_UART_NR_PORTS 2
+
+#define OFFSET_THR 0x00 /* Transmit Holding register */
+#define OFFSET_RBR 0x00 /* Receive Buffer register */
+#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+#define OFFSET_IER 0x04 /* Interrupt Enable Register */
+#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
+#define OFFSET_LCR 0x0C /* Line Control Register */
+#define OFFSET_MCR 0x10 /* Modem Control Register */
+#define OFFSET_LSR 0x14 /* Line Status Register */
+#define OFFSET_MSR 0x18 /* Modem Status Register */
+#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+#define OFFSET_GCTL 0x24 /* Global Control Register */
+
+/* DPMC*/
+#define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+#define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
+#define STOPCK_OFF STOPCK
+
+/* PLL_DIV Masks */
+#define CCLK_DIV1 CSEL_DIV1 /* CCLK = VCO / 1 */
+#define CCLK_DIV2 CSEL_DIV2 /* CCLK = VCO / 2 */
+#define CCLK_DIV4 CSEL_DIV4 /* CCLK = VCO / 4 */
+#define CCLK_DIV8 CSEL_DIV8 /* CCLK = VCO / 8 */
+
+#endif
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF512.h b/arch/blackfin/mach-bf518/include/mach/cdefBF512.h
new file mode 100644
index 000000000000..820c13c4daaa
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF512.h
@@ -0,0 +1,46 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/cdefbf512.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF512_H
+#define _CDEF_BF512_H
+
+/* include all Core registers and bit definitions */
+#include "defBF512.h"
+
+/* include core specific register pointer definitions */
+#include <asm/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF512 */
+
+/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "cdefBF51x_base.h"
+
+#endif /* _CDEF_BF512_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF514.h b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
new file mode 100644
index 000000000000..9521e178fb28
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF514.h
@@ -0,0 +1,48 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/cdefbf514.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF514_H
+#define _CDEF_BF514_H
+
+/* include all Core registers and bit definitions */
+#include "defBF514.h"
+
+/* include core specific register pointer definitions */
+#include <asm/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF514 */
+
+/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "cdefBF51x_base.h"
+
+/* The following are the #defines needed by ADSP-BF514 that are not in the common header */
+
+#endif /* _CDEF_BF514_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF516.h b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
new file mode 100644
index 000000000000..4e26ccfcef97
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF516.h
@@ -0,0 +1,213 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/cdefbf516.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF516_H
+#define _CDEF_BF516_H
+
+/* include all Core registers and bit definitions */
+#include "defBF516.h"
+
+/* include core specific register pointer definitions */
+#include <asm/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF516 */
+
+/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "cdefBF51x_base.h"
+
+/* The following are the #defines needed by ADSP-BF516 that are not in the common header */
+
+/* 10/100 Ethernet Controller (0xFFC03000 - 0xFFC031FF) */
+
+#define bfin_read_EMAC_OPMODE() bfin_read32(EMAC_OPMODE)
+#define bfin_write_EMAC_OPMODE(val) bfin_write32(EMAC_OPMODE, val)
+#define bfin_read_EMAC_ADDRLO() bfin_read32(EMAC_ADDRLO)
+#define bfin_write_EMAC_ADDRLO(val) bfin_write32(EMAC_ADDRLO, val)
+#define bfin_read_EMAC_ADDRHI() bfin_read32(EMAC_ADDRHI)
+#define bfin_write_EMAC_ADDRHI(val) bfin_write32(EMAC_ADDRHI, val)
+#define bfin_read_EMAC_HASHLO() bfin_read32(EMAC_HASHLO)
+#define bfin_write_EMAC_HASHLO(val) bfin_write32(EMAC_HASHLO, val)
+#define bfin_read_EMAC_HASHHI() bfin_read32(EMAC_HASHHI)
+#define bfin_write_EMAC_HASHHI(val) bfin_write32(EMAC_HASHHI, val)
+#define bfin_read_EMAC_STAADD() bfin_read32(EMAC_STAADD)
+#define bfin_write_EMAC_STAADD(val) bfin_write32(EMAC_STAADD, val)
+#define bfin_read_EMAC_STADAT() bfin_read32(EMAC_STADAT)
+#define bfin_write_EMAC_STADAT(val) bfin_write32(EMAC_STADAT, val)
+#define bfin_read_EMAC_FLC() bfin_read32(EMAC_FLC)
+#define bfin_write_EMAC_FLC(val) bfin_write32(EMAC_FLC, val)
+#define bfin_read_EMAC_VLAN1() bfin_read32(EMAC_VLAN1)
+#define bfin_write_EMAC_VLAN1(val) bfin_write32(EMAC_VLAN1, val)
+#define bfin_read_EMAC_VLAN2() bfin_read32(EMAC_VLAN2)
+#define bfin_write_EMAC_VLAN2(val) bfin_write32(EMAC_VLAN2, val)
+#define bfin_read_EMAC_WKUP_CTL() bfin_read32(EMAC_WKUP_CTL)
+#define bfin_write_EMAC_WKUP_CTL(val) bfin_write32(EMAC_WKUP_CTL, val)
+#define bfin_read_EMAC_WKUP_FFMSK0() bfin_read32(EMAC_WKUP_FFMSK0)
+#define bfin_write_EMAC_WKUP_FFMSK0(val) bfin_write32(EMAC_WKUP_FFMSK0, val)
+#define bfin_read_EMAC_WKUP_FFMSK1() bfin_read32(EMAC_WKUP_FFMSK1)
+#define bfin_write_EMAC_WKUP_FFMSK1(val) bfin_write32(EMAC_WKUP_FFMSK1, val)
+#define bfin_read_EMAC_WKUP_FFMSK2() bfin_read32(EMAC_WKUP_FFMSK2)
+#define bfin_write_EMAC_WKUP_FFMSK2(val) bfin_write32(EMAC_WKUP_FFMSK2, val)
+#define bfin_read_EMAC_WKUP_FFMSK3() bfin_read32(EMAC_WKUP_FFMSK3)
+#define bfin_write_EMAC_WKUP_FFMSK3(val) bfin_write32(EMAC_WKUP_FFMSK3, val)
+#define bfin_read_EMAC_WKUP_FFCMD() bfin_read32(EMAC_WKUP_FFCMD)
+#define bfin_write_EMAC_WKUP_FFCMD(val) bfin_write32(EMAC_WKUP_FFCMD, val)
+#define bfin_read_EMAC_WKUP_FFOFF() bfin_read32(EMAC_WKUP_FFOFF)
+#define bfin_write_EMAC_WKUP_FFOFF(val) bfin_write32(EMAC_WKUP_FFOFF, val)
+#define bfin_read_EMAC_WKUP_FFCRC0() bfin_read32(EMAC_WKUP_FFCRC0)
+#define bfin_write_EMAC_WKUP_FFCRC0(val) bfin_write32(EMAC_WKUP_FFCRC0, val)
+#define bfin_read_EMAC_WKUP_FFCRC1() bfin_read32(EMAC_WKUP_FFCRC1)
+#define bfin_write_EMAC_WKUP_FFCRC1(val) bfin_write32(EMAC_WKUP_FFCRC1, val)
+
+#define bfin_read_EMAC_SYSCTL() bfin_read32(EMAC_SYSCTL)
+#define bfin_write_EMAC_SYSCTL(val) bfin_write32(EMAC_SYSCTL, val)
+#define bfin_read_EMAC_SYSTAT() bfin_read32(EMAC_SYSTAT)
+#define bfin_write_EMAC_SYSTAT(val) bfin_write32(EMAC_SYSTAT, val)
+#define bfin_read_EMAC_RX_STAT() bfin_read32(EMAC_RX_STAT)
+#define bfin_write_EMAC_RX_STAT(val) bfin_write32(EMAC_RX_STAT, val)
+#define bfin_read_EMAC_RX_STKY() bfin_read32(EMAC_RX_STKY)
+#define bfin_write_EMAC_RX_STKY(val) bfin_write32(EMAC_RX_STKY, val)
+#define bfin_read_EMAC_RX_IRQE() bfin_read32(EMAC_RX_IRQE)
+#define bfin_write_EMAC_RX_IRQE(val) bfin_write32(EMAC_RX_IRQE, val)
+#define bfin_read_EMAC_TX_STAT() bfin_read32(EMAC_TX_STAT)
+#define bfin_write_EMAC_TX_STAT(val) bfin_write32(EMAC_TX_STAT, val)
+#define bfin_read_EMAC_TX_STKY() bfin_read32(EMAC_TX_STKY)
+#define bfin_write_EMAC_TX_STKY(val) bfin_write32(EMAC_TX_STKY, val)
+#define bfin_read_EMAC_TX_IRQE() bfin_read32(EMAC_TX_IRQE)
+#define bfin_write_EMAC_TX_IRQE(val) bfin_write32(EMAC_TX_IRQE, val)
+
+#define bfin_read_EMAC_MMC_CTL() bfin_read32(EMAC_MMC_CTL)
+#define bfin_write_EMAC_MMC_CTL(val) bfin_write32(EMAC_MMC_CTL, val)
+#define bfin_read_EMAC_MMC_RIRQS() bfin_read32(EMAC_MMC_RIRQS)
+#define bfin_write_EMAC_MMC_RIRQS(val) bfin_write32(EMAC_MMC_RIRQS, val)
+#define bfin_read_EMAC_MMC_RIRQE() bfin_read32(EMAC_MMC_RIRQE)
+#define bfin_write_EMAC_MMC_RIRQE(val) bfin_write32(EMAC_MMC_RIRQE, val)
+#define bfin_read_EMAC_MMC_TIRQS() bfin_read32(EMAC_MMC_TIRQS)
+#define bfin_write_EMAC_MMC_TIRQS(val) bfin_write32(EMAC_MMC_TIRQS, val)
+#define bfin_read_EMAC_MMC_TIRQE() bfin_read32(EMAC_MMC_TIRQE)
+#define bfin_write_EMAC_MMC_TIRQE(val) bfin_write32(EMAC_MMC_TIRQE, val)
+
+#define bfin_read_EMAC_RXC_OK() bfin_read32(EMAC_RXC_OK)
+#define bfin_write_EMAC_RXC_OK(val) bfin_write32(EMAC_RXC_OK, val)
+#define bfin_read_EMAC_RXC_FCS() bfin_read32(EMAC_RXC_FCS)
+#define bfin_write_EMAC_RXC_FCS(val) bfin_write32(EMAC_RXC_FCS, val)
+#define bfin_read_EMAC_RXC_ALIGN() bfin_read32(EMAC_RXC_ALIGN)
+#define bfin_write_EMAC_RXC_ALIGN(val) bfin_write32(EMAC_RXC_ALIGN, val)
+#define bfin_read_EMAC_RXC_OCTET() bfin_read32(EMAC_RXC_OCTET)
+#define bfin_write_EMAC_RXC_OCTET(val) bfin_write32(EMAC_RXC_OCTET, val)
+#define bfin_read_EMAC_RXC_DMAOVF() bfin_read32(EMAC_RXC_DMAOVF)
+#define bfin_write_EMAC_RXC_DMAOVF(val) bfin_write32(EMAC_RXC_DMAOVF, val)
+#define bfin_read_EMAC_RXC_UNICST() bfin_read32(EMAC_RXC_UNICST)
+#define bfin_write_EMAC_RXC_UNICST(val) bfin_write32(EMAC_RXC_UNICST, val)
+#define bfin_read_EMAC_RXC_MULTI() bfin_read32(EMAC_RXC_MULTI)
+#define bfin_write_EMAC_RXC_MULTI(val) bfin_write32(EMAC_RXC_MULTI, val)
+#define bfin_read_EMAC_RXC_BROAD() bfin_read32(EMAC_RXC_BROAD)
+#define bfin_write_EMAC_RXC_BROAD(val) bfin_write32(EMAC_RXC_BROAD, val)
+#define bfin_read_EMAC_RXC_LNERRI() bfin_read32(EMAC_RXC_LNERRI)
+#define bfin_write_EMAC_RXC_LNERRI(val) bfin_write32(EMAC_RXC_LNERRI, val)
+#define bfin_read_EMAC_RXC_LNERRO() bfin_read32(EMAC_RXC_LNERRO)
+#define bfin_write_EMAC_RXC_LNERRO(val) bfin_write32(EMAC_RXC_LNERRO, val)
+#define bfin_read_EMAC_RXC_LONG() bfin_read32(EMAC_RXC_LONG)
+#define bfin_write_EMAC_RXC_LONG(val) bfin_write32(EMAC_RXC_LONG, val)
+#define bfin_read_EMAC_RXC_MACCTL() bfin_read32(EMAC_RXC_MACCTL)
+#define bfin_write_EMAC_RXC_MACCTL(val) bfin_write32(EMAC_RXC_MACCTL, val)
+#define bfin_read_EMAC_RXC_OPCODE() bfin_read32(EMAC_RXC_OPCODE)
+#define bfin_write_EMAC_RXC_OPCODE(val) bfin_write32(EMAC_RXC_OPCODE, val)
+#define bfin_read_EMAC_RXC_PAUSE() bfin_read32(EMAC_RXC_PAUSE)
+#define bfin_write_EMAC_RXC_PAUSE(val) bfin_write32(EMAC_RXC_PAUSE, val)
+#define bfin_read_EMAC_RXC_ALLFRM() bfin_read32(EMAC_RXC_ALLFRM)
+#define bfin_write_EMAC_RXC_ALLFRM(val) bfin_write32(EMAC_RXC_ALLFRM, val)
+#define bfin_read_EMAC_RXC_ALLOCT() bfin_read32(EMAC_RXC_ALLOCT)
+#define bfin_write_EMAC_RXC_ALLOCT(val) bfin_write32(EMAC_RXC_ALLOCT, val)
+#define bfin_read_EMAC_RXC_TYPED() bfin_read32(EMAC_RXC_TYPED)
+#define bfin_write_EMAC_RXC_TYPED(val) bfin_write32(EMAC_RXC_TYPED, val)
+#define bfin_read_EMAC_RXC_SHORT() bfin_read32(EMAC_RXC_SHORT)
+#define bfin_write_EMAC_RXC_SHORT(val) bfin_write32(EMAC_RXC_SHORT, val)
+#define bfin_read_EMAC_RXC_EQ64() bfin_read32(EMAC_RXC_EQ64)
+#define bfin_write_EMAC_RXC_EQ64(val) bfin_write32(EMAC_RXC_EQ64, val)
+#define bfin_read_EMAC_RXC_LT128() bfin_read32(EMAC_RXC_LT128)
+#define bfin_write_EMAC_RXC_LT128(val) bfin_write32(EMAC_RXC_LT128, val)
+#define bfin_read_EMAC_RXC_LT256() bfin_read32(EMAC_RXC_LT256)
+#define bfin_write_EMAC_RXC_LT256(val) bfin_write32(EMAC_RXC_LT256, val)
+#define bfin_read_EMAC_RXC_LT512() bfin_read32(EMAC_RXC_LT512)
+#define bfin_write_EMAC_RXC_LT512(val) bfin_write32(EMAC_RXC_LT512, val)
+#define bfin_read_EMAC_RXC_LT1024() bfin_read32(EMAC_RXC_LT1024)
+#define bfin_write_EMAC_RXC_LT1024(val) bfin_write32(EMAC_RXC_LT1024, val)
+#define bfin_read_EMAC_RXC_GE1024() bfin_read32(EMAC_RXC_GE1024)
+#define bfin_write_EMAC_RXC_GE1024(val) bfin_write32(EMAC_RXC_GE1024, val)
+
+#define bfin_read_EMAC_TXC_OK() bfin_read32(EMAC_TXC_OK)
+#define bfin_write_EMAC_TXC_OK(val) bfin_write32(EMAC_TXC_OK, val)
+#define bfin_read_EMAC_TXC_1COL() bfin_read32(EMAC_TXC_1COL)
+#define bfin_write_EMAC_TXC_1COL(val) bfin_write32(EMAC_TXC_1COL, val)
+#define bfin_read_EMAC_TXC_GT1COL() bfin_read32(EMAC_TXC_GT1COL)
+#define bfin_write_EMAC_TXC_GT1COL(val) bfin_write32(EMAC_TXC_GT1COL, val)
+#define bfin_read_EMAC_TXC_OCTET() bfin_read32(EMAC_TXC_OCTET)
+#define bfin_write_EMAC_TXC_OCTET(val) bfin_write32(EMAC_TXC_OCTET, val)
+#define bfin_read_EMAC_TXC_DEFER() bfin_read32(EMAC_TXC_DEFER)
+#define bfin_write_EMAC_TXC_DEFER(val) bfin_write32(EMAC_TXC_DEFER, val)
+#define bfin_read_EMAC_TXC_LATECL() bfin_read32(EMAC_TXC_LATECL)
+#define bfin_write_EMAC_TXC_LATECL(val) bfin_write32(EMAC_TXC_LATECL, val)
+#define bfin_read_EMAC_TXC_XS_COL() bfin_read32(EMAC_TXC_XS_COL)
+#define bfin_write_EMAC_TXC_XS_COL(val) bfin_write32(EMAC_TXC_XS_COL, val)
+#define bfin_read_EMAC_TXC_DMAUND() bfin_read32(EMAC_TXC_DMAUND)
+#define bfin_write_EMAC_TXC_DMAUND(val) bfin_write32(EMAC_TXC_DMAUND, val)
+#define bfin_read_EMAC_TXC_CRSERR() bfin_read32(EMAC_TXC_CRSERR)
+#define bfin_write_EMAC_TXC_CRSERR(val) bfin_write32(EMAC_TXC_CRSERR, val)
+#define bfin_read_EMAC_TXC_UNICST() bfin_read32(EMAC_TXC_UNICST)
+#define bfin_write_EMAC_TXC_UNICST(val) bfin_write32(EMAC_TXC_UNICST, val)
+#define bfin_read_EMAC_TXC_MULTI() bfin_read32(EMAC_TXC_MULTI)
+#define bfin_write_EMAC_TXC_MULTI(val) bfin_write32(EMAC_TXC_MULTI, val)
+#define bfin_read_EMAC_TXC_BROAD() bfin_read32(EMAC_TXC_BROAD)
+#define bfin_write_EMAC_TXC_BROAD(val) bfin_write32(EMAC_TXC_BROAD, val)
+#define bfin_read_EMAC_TXC_XS_DFR() bfin_read32(EMAC_TXC_XS_DFR)
+#define bfin_write_EMAC_TXC_XS_DFR(val) bfin_write32(EMAC_TXC_XS_DFR, val)
+#define bfin_read_EMAC_TXC_MACCTL() bfin_read32(EMAC_TXC_MACCTL)
+#define bfin_write_EMAC_TXC_MACCTL(val) bfin_write32(EMAC_TXC_MACCTL, val)
+#define bfin_read_EMAC_TXC_ALLFRM() bfin_read32(EMAC_TXC_ALLFRM)
+#define bfin_write_EMAC_TXC_ALLFRM(val) bfin_write32(EMAC_TXC_ALLFRM, val)
+#define bfin_read_EMAC_TXC_ALLOCT() bfin_read32(EMAC_TXC_ALLOCT)
+#define bfin_write_EMAC_TXC_ALLOCT(val) bfin_write32(EMAC_TXC_ALLOCT, val)
+#define bfin_read_EMAC_TXC_EQ64() bfin_read32(EMAC_TXC_EQ64)
+#define bfin_write_EMAC_TXC_EQ64(val) bfin_write32(EMAC_TXC_EQ64, val)
+#define bfin_read_EMAC_TXC_LT128() bfin_read32(EMAC_TXC_LT128)
+#define bfin_write_EMAC_TXC_LT128(val) bfin_write32(EMAC_TXC_LT128, val)
+#define bfin_read_EMAC_TXC_LT256() bfin_read32(EMAC_TXC_LT256)
+#define bfin_write_EMAC_TXC_LT256(val) bfin_write32(EMAC_TXC_LT256, val)
+#define bfin_read_EMAC_TXC_LT512() bfin_read32(EMAC_TXC_LT512)
+#define bfin_write_EMAC_TXC_LT512(val) bfin_write32(EMAC_TXC_LT512, val)
+#define bfin_read_EMAC_TXC_LT1024() bfin_read32(EMAC_TXC_LT1024)
+#define bfin_write_EMAC_TXC_LT1024(val) bfin_write32(EMAC_TXC_LT1024, val)
+#define bfin_read_EMAC_TXC_GE1024() bfin_read32(EMAC_TXC_GE1024)
+#define bfin_write_EMAC_TXC_GE1024(val) bfin_write32(EMAC_TXC_GE1024, val)
+#define bfin_read_EMAC_TXC_ABORT() bfin_read32(EMAC_TXC_ABORT)
+#define bfin_write_EMAC_TXC_ABORT(val) bfin_write32(EMAC_TXC_ABORT, val)
+
+#endif /* _CDEF_BF516_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF518.h b/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
new file mode 100644
index 000000000000..bafb370cfb3c
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF518.h
@@ -0,0 +1,282 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/cdefbf518.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: system mmr register map
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF518_H
+#define _CDEF_BF518_H
+
+/* include all Core registers and bit definitions */
+#include "defBF518.h"
+
+/* include core specific register pointer definitions */
+#include <asm/cdef_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF518 */
+
+/* include cdefBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "cdefBF51x_base.h"
+
+/* The following are the #defines needed by ADSP-BF518 that are not in the common header */
+
+
+/* 10/100 Ethernet Controller (0xFFC03000 - 0xFFC031FF) */
+
+#define bfin_read_EMAC_OPMODE() bfin_read32(EMAC_OPMODE)
+#define bfin_write_EMAC_OPMODE(val) bfin_write32(EMAC_OPMODE, val)
+#define bfin_read_EMAC_ADDRLO() bfin_read32(EMAC_ADDRLO)
+#define bfin_write_EMAC_ADDRLO(val) bfin_write32(EMAC_ADDRLO, val)
+#define bfin_read_EMAC_ADDRHI() bfin_read32(EMAC_ADDRHI)
+#define bfin_write_EMAC_ADDRHI(val) bfin_write32(EMAC_ADDRHI, val)
+#define bfin_read_EMAC_HASHLO() bfin_read32(EMAC_HASHLO)
+#define bfin_write_EMAC_HASHLO(val) bfin_write32(EMAC_HASHLO, val)
+#define bfin_read_EMAC_HASHHI() bfin_read32(EMAC_HASHHI)
+#define bfin_write_EMAC_HASHHI(val) bfin_write32(EMAC_HASHHI, val)
+#define bfin_read_EMAC_STAADD() bfin_read32(EMAC_STAADD)
+#define bfin_write_EMAC_STAADD(val) bfin_write32(EMAC_STAADD, val)
+#define bfin_read_EMAC_STADAT() bfin_read32(EMAC_STADAT)
+#define bfin_write_EMAC_STADAT(val) bfin_write32(EMAC_STADAT, val)
+#define bfin_read_EMAC_FLC() bfin_read32(EMAC_FLC)
+#define bfin_write_EMAC_FLC(val) bfin_write32(EMAC_FLC, val)
+#define bfin_read_EMAC_VLAN1() bfin_read32(EMAC_VLAN1)
+#define bfin_write_EMAC_VLAN1(val) bfin_write32(EMAC_VLAN1, val)
+#define bfin_read_EMAC_VLAN2() bfin_read32(EMAC_VLAN2)
+#define bfin_write_EMAC_VLAN2(val) bfin_write32(EMAC_VLAN2, val)
+#define bfin_read_EMAC_WKUP_CTL() bfin_read32(EMAC_WKUP_CTL)
+#define bfin_write_EMAC_WKUP_CTL(val) bfin_write32(EMAC_WKUP_CTL, val)
+#define bfin_read_EMAC_WKUP_FFMSK0() bfin_read32(EMAC_WKUP_FFMSK0)
+#define bfin_write_EMAC_WKUP_FFMSK0(val) bfin_write32(EMAC_WKUP_FFMSK0, val)
+#define bfin_read_EMAC_WKUP_FFMSK1() bfin_read32(EMAC_WKUP_FFMSK1)
+#define bfin_write_EMAC_WKUP_FFMSK1(val) bfin_write32(EMAC_WKUP_FFMSK1, val)
+#define bfin_read_EMAC_WKUP_FFMSK2() bfin_read32(EMAC_WKUP_FFMSK2)
+#define bfin_write_EMAC_WKUP_FFMSK2(val) bfin_write32(EMAC_WKUP_FFMSK2, val)
+#define bfin_read_EMAC_WKUP_FFMSK3() bfin_read32(EMAC_WKUP_FFMSK3)
+#define bfin_write_EMAC_WKUP_FFMSK3(val) bfin_write32(EMAC_WKUP_FFMSK3, val)
+#define bfin_read_EMAC_WKUP_FFCMD() bfin_read32(EMAC_WKUP_FFCMD)
+#define bfin_write_EMAC_WKUP_FFCMD(val) bfin_write32(EMAC_WKUP_FFCMD, val)
+#define bfin_read_EMAC_WKUP_FFOFF() bfin_read32(EMAC_WKUP_FFOFF)
+#define bfin_write_EMAC_WKUP_FFOFF(val) bfin_write32(EMAC_WKUP_FFOFF, val)
+#define bfin_read_EMAC_WKUP_FFCRC0() bfin_read32(EMAC_WKUP_FFCRC0)
+#define bfin_write_EMAC_WKUP_FFCRC0(val) bfin_write32(EMAC_WKUP_FFCRC0, val)
+#define bfin_read_EMAC_WKUP_FFCRC1() bfin_read32(EMAC_WKUP_FFCRC1)
+#define bfin_write_EMAC_WKUP_FFCRC1(val) bfin_write32(EMAC_WKUP_FFCRC1, val)
+
+#define bfin_read_EMAC_SYSCTL() bfin_read32(EMAC_SYSCTL)
+#define bfin_write_EMAC_SYSCTL(val) bfin_write32(EMAC_SYSCTL, val)
+#define bfin_read_EMAC_SYSTAT() bfin_read32(EMAC_SYSTAT)
+#define bfin_write_EMAC_SYSTAT(val) bfin_write32(EMAC_SYSTAT, val)
+#define bfin_read_EMAC_RX_STAT() bfin_read32(EMAC_RX_STAT)
+#define bfin_write_EMAC_RX_STAT(val) bfin_write32(EMAC_RX_STAT, val)
+#define bfin_read_EMAC_RX_STKY() bfin_read32(EMAC_RX_STKY)
+#define bfin_write_EMAC_RX_STKY(val) bfin_write32(EMAC_RX_STKY, val)
+#define bfin_read_EMAC_RX_IRQE() bfin_read32(EMAC_RX_IRQE)
+#define bfin_write_EMAC_RX_IRQE(val) bfin_write32(EMAC_RX_IRQE, val)
+#define bfin_read_EMAC_TX_STAT() bfin_read32(EMAC_TX_STAT)
+#define bfin_write_EMAC_TX_STAT(val) bfin_write32(EMAC_TX_STAT, val)
+#define bfin_read_EMAC_TX_STKY() bfin_read32(EMAC_TX_STKY)
+#define bfin_write_EMAC_TX_STKY(val) bfin_write32(EMAC_TX_STKY, val)
+#define bfin_read_EMAC_TX_IRQE() bfin_read32(EMAC_TX_IRQE)
+#define bfin_write_EMAC_TX_IRQE(val) bfin_write32(EMAC_TX_IRQE, val)
+
+#define bfin_read_EMAC_MMC_CTL() bfin_read32(EMAC_MMC_CTL)
+#define bfin_write_EMAC_MMC_CTL(val) bfin_write32(EMAC_MMC_CTL, val)
+#define bfin_read_EMAC_MMC_RIRQS() bfin_read32(EMAC_MMC_RIRQS)
+#define bfin_write_EMAC_MMC_RIRQS(val) bfin_write32(EMAC_MMC_RIRQS, val)
+#define bfin_read_EMAC_MMC_RIRQE() bfin_read32(EMAC_MMC_RIRQE)
+#define bfin_write_EMAC_MMC_RIRQE(val) bfin_write32(EMAC_MMC_RIRQE, val)
+#define bfin_read_EMAC_MMC_TIRQS() bfin_read32(EMAC_MMC_TIRQS)
+#define bfin_write_EMAC_MMC_TIRQS(val) bfin_write32(EMAC_MMC_TIRQS, val)
+#define bfin_read_EMAC_MMC_TIRQE() bfin_read32(EMAC_MMC_TIRQE)
+#define bfin_write_EMAC_MMC_TIRQE(val) bfin_write32(EMAC_MMC_TIRQE, val)
+
+#define bfin_read_EMAC_RXC_OK() bfin_read32(EMAC_RXC_OK)
+#define bfin_write_EMAC_RXC_OK(val) bfin_write32(EMAC_RXC_OK, val)
+#define bfin_read_EMAC_RXC_FCS() bfin_read32(EMAC_RXC_FCS)
+#define bfin_write_EMAC_RXC_FCS(val) bfin_write32(EMAC_RXC_FCS, val)
+#define bfin_read_EMAC_RXC_ALIGN() bfin_read32(EMAC_RXC_ALIGN)
+#define bfin_write_EMAC_RXC_ALIGN(val) bfin_write32(EMAC_RXC_ALIGN, val)
+#define bfin_read_EMAC_RXC_OCTET() bfin_read32(EMAC_RXC_OCTET)
+#define bfin_write_EMAC_RXC_OCTET(val) bfin_write32(EMAC_RXC_OCTET, val)
+#define bfin_read_EMAC_RXC_DMAOVF() bfin_read32(EMAC_RXC_DMAOVF)
+#define bfin_write_EMAC_RXC_DMAOVF(val) bfin_write32(EMAC_RXC_DMAOVF, val)
+#define bfin_read_EMAC_RXC_UNICST() bfin_read32(EMAC_RXC_UNICST)
+#define bfin_write_EMAC_RXC_UNICST(val) bfin_write32(EMAC_RXC_UNICST, val)
+#define bfin_read_EMAC_RXC_MULTI() bfin_read32(EMAC_RXC_MULTI)
+#define bfin_write_EMAC_RXC_MULTI(val) bfin_write32(EMAC_RXC_MULTI, val)
+#define bfin_read_EMAC_RXC_BROAD() bfin_read32(EMAC_RXC_BROAD)
+#define bfin_write_EMAC_RXC_BROAD(val) bfin_write32(EMAC_RXC_BROAD, val)
+#define bfin_read_EMAC_RXC_LNERRI() bfin_read32(EMAC_RXC_LNERRI)
+#define bfin_write_EMAC_RXC_LNERRI(val) bfin_write32(EMAC_RXC_LNERRI, val)
+#define bfin_read_EMAC_RXC_LNERRO() bfin_read32(EMAC_RXC_LNERRO)
+#define bfin_write_EMAC_RXC_LNERRO(val) bfin_write32(EMAC_RXC_LNERRO, val)
+#define bfin_read_EMAC_RXC_LONG() bfin_read32(EMAC_RXC_LONG)
+#define bfin_write_EMAC_RXC_LONG(val) bfin_write32(EMAC_RXC_LONG, val)
+#define bfin_read_EMAC_RXC_MACCTL() bfin_read32(EMAC_RXC_MACCTL)
+#define bfin_write_EMAC_RXC_MACCTL(val) bfin_write32(EMAC_RXC_MACCTL, val)
+#define bfin_read_EMAC_RXC_OPCODE() bfin_read32(EMAC_RXC_OPCODE)
+#define bfin_write_EMAC_RXC_OPCODE(val) bfin_write32(EMAC_RXC_OPCODE, val)
+#define bfin_read_EMAC_RXC_PAUSE() bfin_read32(EMAC_RXC_PAUSE)
+#define bfin_write_EMAC_RXC_PAUSE(val) bfin_write32(EMAC_RXC_PAUSE, val)
+#define bfin_read_EMAC_RXC_ALLFRM() bfin_read32(EMAC_RXC_ALLFRM)
+#define bfin_write_EMAC_RXC_ALLFRM(val) bfin_write32(EMAC_RXC_ALLFRM, val)
+#define bfin_read_EMAC_RXC_ALLOCT() bfin_read32(EMAC_RXC_ALLOCT)
+#define bfin_write_EMAC_RXC_ALLOCT(val) bfin_write32(EMAC_RXC_ALLOCT, val)
+#define bfin_read_EMAC_RXC_TYPED() bfin_read32(EMAC_RXC_TYPED)
+#define bfin_write_EMAC_RXC_TYPED(val) bfin_write32(EMAC_RXC_TYPED, val)
+#define bfin_read_EMAC_RXC_SHORT() bfin_read32(EMAC_RXC_SHORT)
+#define bfin_write_EMAC_RXC_SHORT(val) bfin_write32(EMAC_RXC_SHORT, val)
+#define bfin_read_EMAC_RXC_EQ64() bfin_read32(EMAC_RXC_EQ64)
+#define bfin_write_EMAC_RXC_EQ64(val) bfin_write32(EMAC_RXC_EQ64, val)
+#define bfin_read_EMAC_RXC_LT128() bfin_read32(EMAC_RXC_LT128)
+#define bfin_write_EMAC_RXC_LT128(val) bfin_write32(EMAC_RXC_LT128, val)
+#define bfin_read_EMAC_RXC_LT256() bfin_read32(EMAC_RXC_LT256)
+#define bfin_write_EMAC_RXC_LT256(val) bfin_write32(EMAC_RXC_LT256, val)
+#define bfin_read_EMAC_RXC_LT512() bfin_read32(EMAC_RXC_LT512)
+#define bfin_write_EMAC_RXC_LT512(val) bfin_write32(EMAC_RXC_LT512, val)
+#define bfin_read_EMAC_RXC_LT1024() bfin_read32(EMAC_RXC_LT1024)
+#define bfin_write_EMAC_RXC_LT1024(val) bfin_write32(EMAC_RXC_LT1024, val)
+#define bfin_read_EMAC_RXC_GE1024() bfin_read32(EMAC_RXC_GE1024)
+#define bfin_write_EMAC_RXC_GE1024(val) bfin_write32(EMAC_RXC_GE1024, val)
+
+#define bfin_read_EMAC_TXC_OK() bfin_read32(EMAC_TXC_OK)
+#define bfin_write_EMAC_TXC_OK(val) bfin_write32(EMAC_TXC_OK, val)
+#define bfin_read_EMAC_TXC_1COL() bfin_read32(EMAC_TXC_1COL)
+#define bfin_write_EMAC_TXC_1COL(val) bfin_write32(EMAC_TXC_1COL, val)
+#define bfin_read_EMAC_TXC_GT1COL() bfin_read32(EMAC_TXC_GT1COL)
+#define bfin_write_EMAC_TXC_GT1COL(val) bfin_write32(EMAC_TXC_GT1COL, val)
+#define bfin_read_EMAC_TXC_OCTET() bfin_read32(EMAC_TXC_OCTET)
+#define bfin_write_EMAC_TXC_OCTET(val) bfin_write32(EMAC_TXC_OCTET, val)
+#define bfin_read_EMAC_TXC_DEFER() bfin_read32(EMAC_TXC_DEFER)
+#define bfin_write_EMAC_TXC_DEFER(val) bfin_write32(EMAC_TXC_DEFER, val)
+#define bfin_read_EMAC_TXC_LATECL() bfin_read32(EMAC_TXC_LATECL)
+#define bfin_write_EMAC_TXC_LATECL(val) bfin_write32(EMAC_TXC_LATECL, val)
+#define bfin_read_EMAC_TXC_XS_COL() bfin_read32(EMAC_TXC_XS_COL)
+#define bfin_write_EMAC_TXC_XS_COL(val) bfin_write32(EMAC_TXC_XS_COL, val)
+#define bfin_read_EMAC_TXC_DMAUND() bfin_read32(EMAC_TXC_DMAUND)
+#define bfin_write_EMAC_TXC_DMAUND(val) bfin_write32(EMAC_TXC_DMAUND, val)
+#define bfin_read_EMAC_TXC_CRSERR() bfin_read32(EMAC_TXC_CRSERR)
+#define bfin_write_EMAC_TXC_CRSERR(val) bfin_write32(EMAC_TXC_CRSERR, val)
+#define bfin_read_EMAC_TXC_UNICST() bfin_read32(EMAC_TXC_UNICST)
+#define bfin_write_EMAC_TXC_UNICST(val) bfin_write32(EMAC_TXC_UNICST, val)
+#define bfin_read_EMAC_TXC_MULTI() bfin_read32(EMAC_TXC_MULTI)
+#define bfin_write_EMAC_TXC_MULTI(val) bfin_write32(EMAC_TXC_MULTI, val)
+#define bfin_read_EMAC_TXC_BROAD() bfin_read32(EMAC_TXC_BROAD)
+#define bfin_write_EMAC_TXC_BROAD(val) bfin_write32(EMAC_TXC_BROAD, val)
+#define bfin_read_EMAC_TXC_XS_DFR() bfin_read32(EMAC_TXC_XS_DFR)
+#define bfin_write_EMAC_TXC_XS_DFR(val) bfin_write32(EMAC_TXC_XS_DFR, val)
+#define bfin_read_EMAC_TXC_MACCTL() bfin_read32(EMAC_TXC_MACCTL)
+#define bfin_write_EMAC_TXC_MACCTL(val) bfin_write32(EMAC_TXC_MACCTL, val)
+#define bfin_read_EMAC_TXC_ALLFRM() bfin_read32(EMAC_TXC_ALLFRM)
+#define bfin_write_EMAC_TXC_ALLFRM(val) bfin_write32(EMAC_TXC_ALLFRM, val)
+#define bfin_read_EMAC_TXC_ALLOCT() bfin_read32(EMAC_TXC_ALLOCT)
+#define bfin_write_EMAC_TXC_ALLOCT(val) bfin_write32(EMAC_TXC_ALLOCT, val)
+#define bfin_read_EMAC_TXC_EQ64() bfin_read32(EMAC_TXC_EQ64)
+#define bfin_write_EMAC_TXC_EQ64(val) bfin_write32(EMAC_TXC_EQ64, val)
+#define bfin_read_EMAC_TXC_LT128() bfin_read32(EMAC_TXC_LT128)
+#define bfin_write_EMAC_TXC_LT128(val) bfin_write32(EMAC_TXC_LT128, val)
+#define bfin_read_EMAC_TXC_LT256() bfin_read32(EMAC_TXC_LT256)
+#define bfin_write_EMAC_TXC_LT256(val) bfin_write32(EMAC_TXC_LT256, val)
+#define bfin_read_EMAC_TXC_LT512() bfin_read32(EMAC_TXC_LT512)
+#define bfin_write_EMAC_TXC_LT512(val) bfin_write32(EMAC_TXC_LT512, val)
+#define bfin_read_EMAC_TXC_LT1024() bfin_read32(EMAC_TXC_LT1024)
+#define bfin_write_EMAC_TXC_LT1024(val) bfin_write32(EMAC_TXC_LT1024, val)
+#define bfin_read_EMAC_TXC_GE1024() bfin_read32(EMAC_TXC_GE1024)
+#define bfin_write_EMAC_TXC_GE1024(val) bfin_write32(EMAC_TXC_GE1024, val)
+#define bfin_read_EMAC_TXC_ABORT() bfin_read32(EMAC_TXC_ABORT)
+#define bfin_write_EMAC_TXC_ABORT(val) bfin_write32(EMAC_TXC_ABORT, val)
+
+/* Removable Storage Interface Registers */
+
+#define bfin_read_RSI_PWR_CTL() bfin_read16(RSI_PWR_CONTROL)
+#define bfin_write_RSI_PWR_CTL(val) bfin_write16(RSI_PWR_CONTROL, val)
+#define bfin_read_RSI_CLK_CTL() bfin_read16(RSI_CLK_CONTROL)
+#define bfin_write_RSI_CLK_CTL(val) bfin_write16(RSI_CLK_CONTROL, val)
+#define bfin_read_RSI_ARGUMENT() bfin_read32(RSI_ARGUMENT)
+#define bfin_write_RSI_ARGUMENT(val) bfin_write32(RSI_ARGUMENT, val)
+#define bfin_read_RSI_COMMAND() bfin_read16(RSI_COMMAND)
+#define bfin_write_RSI_COMMAND(val) bfin_write16(RSI_COMMAND, val)
+#define bfin_read_RSI_RESP_CMD() bfin_read16(RSI_RESP_CMD)
+#define bfin_write_RSI_RESP_CMD(val) bfin_write16(RSI_RESP_CMD, val)
+#define bfin_read_RSI_RESPONSE0() bfin_read32(RSI_RESPONSE0)
+#define bfin_write_RSI_RESPONSE0(val) bfin_write32(RSI_RESPONSE0, val)
+#define bfin_read_RSI_RESPONSE1() bfin_read32(RSI_RESPONSE1)
+#define bfin_write_RSI_RESPONSE1(val) bfin_write32(RSI_RESPONSE1, val)
+#define bfin_read_RSI_RESPONSE2() bfin_read32(RSI_RESPONSE2)
+#define bfin_write_RSI_RESPONSE2(val) bfin_write32(RSI_RESPONSE2, val)
+#define bfin_read_RSI_RESPONSE3() bfin_read32(RSI_RESPONSE3)
+#define bfin_write_RSI_RESPONSE3(val) bfin_write32(RSI_RESPONSE3, val)
+#define bfin_read_RSI_DATA_TIMER() bfin_read32(RSI_DATA_TIMER)
+#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val)
+#define bfin_read_RSI_DATA_LGTH() bfin_read16(RSI_DATA_LGTH)
+#define bfin_write_RSI_DATA_LGTH(val) bfin_write16(RSI_DATA_LGTH, val)
+#define bfin_read_RSI_DATA_CTL() bfin_read16(RSI_DATA_CONTROL)
+#define bfin_write_RSI_DATA_CTL(val) bfin_write16(RSI_DATA_CONTROL, val)
+#define bfin_read_RSI_DATA_CNT() bfin_read16(RSI_DATA_CNT)
+#define bfin_write_RSI_DATA_CNT(val) bfin_write16(RSI_DATA_CNT, val)
+#define bfin_read_RSI_STATUS() bfin_read32(RSI_STATUS)
+#define bfin_write_RSI_STATUS(val) bfin_write32(RSI_STATUS, val)
+#define bfin_read_RSI_STATUS_CLR() bfin_read16(RSI_STATUSCL)
+#define bfin_write_RSI_STATUS_CLR(val) bfin_write16(RSI_STATUSCL, val)
+#define bfin_read_RSI_MASK0() bfin_read32(RSI_MASK0)
+#define bfin_write_RSI_MASK0(val) bfin_write32(RSI_MASK0, val)
+#define bfin_read_RSI_MASK1() bfin_read32(RSI_MASK1)
+#define bfin_write_RSI_MASK1(val) bfin_write32(RSI_MASK1, val)
+#define bfin_read_RSI_FIFO_CNT() bfin_read16(RSI_FIFO_CNT)
+#define bfin_write_RSI_FIFO_CNT(val) bfin_write16(RSI_FIFO_CNT, val)
+#define bfin_read_RSI_CEATA_CTL() bfin_read16(RSI_CEATA_CONTROL)
+#define bfin_write_RSI_CEATA_CTL(val) bfin_write16(RSI_CEATA_CONTROL, val)
+#define bfin_read_RSI_FIFO() bfin_read32(RSI_FIFO)
+#define bfin_write_RSI_FIFO(val) bfin_write32(RSI_FIFO, val)
+#define bfin_read_RSI_E_STATUS() bfin_read16(RSI_ESTAT)
+#define bfin_write_RSI_E_STATUS(val) bfin_write16(RSI_ESTAT, val)
+#define bfin_read_RSI_E_MASK() bfin_read16(RSI_EMASK)
+#define bfin_write_RSI_E_MASK(val) bfin_write16(RSI_EMASK, val)
+#define bfin_read_RSI_CFG() bfin_read16(RSI_CONFIG)
+#define bfin_write_RSI_CFG(val) bfin_write16(RSI_CONFIG, val)
+#define bfin_read_RSI_RD_WAIT_EN() bfin_read16(RSI_RD_WAIT_EN)
+#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val)
+#define bfin_read_RSI_PID0() bfin_read16(RSI_PID0)
+#define bfin_write_RSI_PID0(val) bfin_write16(RSI_PID0, val)
+#define bfin_read_RSI_PID1() bfin_read16(RSI_PID1)
+#define bfin_write_RSI_PID1(val) bfin_write16(RSI_PID1, val)
+#define bfin_read_RSI_PID2() bfin_read16(RSI_PID2)
+#define bfin_write_RSI_PID2(val) bfin_write16(RSI_PID2, val)
+#define bfin_read_RSI_PID3() bfin_read16(RSI_PID3)
+#define bfin_write_RSI_PID3(val) bfin_write16(RSI_PID3, val)
+#define bfin_read_RSI_PID4() bfin_read16(RSI_PID4)
+#define bfin_write_RSI_PID4(val) bfin_write16(RSI_PID4, val)
+#define bfin_read_RSI_PID5() bfin_read16(RSI_PID5)
+#define bfin_write_RSI_PID5(val) bfin_write16(RSI_PID5, val)
+#define bfin_read_RSI_PID6() bfin_read16(RSI_PID6)
+#define bfin_write_RSI_PID6(val) bfin_write16(RSI_PID6, val)
+#define bfin_read_RSI_PID7() bfin_read16(RSI_PID7)
+#define bfin_write_RSI_PID7(val) bfin_write16(RSI_PID7, val)
+
+
+#endif /* _CDEF_BF518_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
new file mode 100644
index 000000000000..ee3d4733369c
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/cdefBF51x_base.h
@@ -0,0 +1,1208 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/cdefBF51x_base.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF52X_H
+#define _CDEF_BF52X_H
+
+#include <asm/blackfin.h>
+
+#include "defBF51x_base.h"
+
+/* Include core specific register pointer definitions */
+#include <asm/cdef_LPBlackfin.h>
+
+/* ==== begin from cdefBF534.h ==== */
+
+/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
+#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
+#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
+#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
+#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val) bfin_write16(PLL_LOCKCNT, val)
+#define bfin_read_CHIPID() bfin_read32(CHIPID)
+#define bfin_write_CHIPID(val) bfin_write32(CHIPID, val)
+
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
+#define bfin_read_SWRST() bfin_read16(SWRST)
+#define bfin_write_SWRST(val) bfin_write16(SWRST, val)
+#define bfin_read_SYSCR() bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val) bfin_write16(SYSCR, val)
+
+#define bfin_read_SIC_RVECT() bfin_read32(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val) bfin_write32(SIC_RVECT, val)
+#define bfin_read_SIC_IMASK0() bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val) bfin_write32(SIC_IMASK0, val)
+#define bfin_read_SIC_IMASK(x) bfin_read32(SIC_IMASK0 + (x << 6))
+#define bfin_write_SIC_IMASK(x, val) bfin_write32((SIC_IMASK0 + (x << 6)), val)
+
+#define bfin_read_SIC_IAR0() bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val) bfin_write32(SIC_IAR0, val)
+#define bfin_read_SIC_IAR1() bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val) bfin_write32(SIC_IAR1, val)
+#define bfin_read_SIC_IAR2() bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val) bfin_write32(SIC_IAR2, val)
+#define bfin_read_SIC_IAR3() bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val) bfin_write32(SIC_IAR3, val)
+
+#define bfin_read_SIC_ISR0() bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val) bfin_write32(SIC_ISR0, val)
+#define bfin_read_SIC_ISR(x) bfin_read32(SIC_ISR0 + (x << 6))
+#define bfin_write_SIC_ISR(x, val) bfin_write32((SIC_ISR0 + (x << 6)), val)
+
+#define bfin_read_SIC_IWR0() bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val) bfin_write32(SIC_IWR0, val)
+#define bfin_read_SIC_IWR(x) bfin_read32(SIC_IWR0 + (x << 6))
+#define bfin_write_SIC_IWR(x, val) bfin_write32((SIC_IWR0 + (x << 6)), val)
+
+/* SIC Additions to ADSP-BF51x (0xFFC0014C - 0xFFC00162) */
+
+#define bfin_read_SIC_IMASK1() bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val) bfin_write32(SIC_IMASK1, val)
+#define bfin_read_SIC_IAR4() bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val) bfin_write32(SIC_IAR4, val)
+#define bfin_read_SIC_IAR5() bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val) bfin_write32(SIC_IAR5, val)
+#define bfin_read_SIC_IAR6() bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val) bfin_write32(SIC_IAR6, val)
+#define bfin_read_SIC_IAR7() bfin_read32(SIC_IAR7)
+#define bfin_write_SIC_IAR7(val) bfin_write32(SIC_IAR7, val)
+#define bfin_read_SIC_ISR1() bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val) bfin_write32(SIC_ISR1, val)
+#define bfin_read_SIC_IWR1() bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val) bfin_write32(SIC_IWR1, val)
+
+/* Watchdog Timer (0xFFC00200 - 0xFFC002FF) */
+#define bfin_read_WDOG_CTL() bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val) bfin_write16(WDOG_CTL, val)
+#define bfin_read_WDOG_CNT() bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val) bfin_write32(WDOG_CNT, val)
+#define bfin_read_WDOG_STAT() bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val) bfin_write32(WDOG_STAT, val)
+
+
+/* Real Time Clock (0xFFC00300 - 0xFFC003FF) */
+#define bfin_read_RTC_STAT() bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val) bfin_write32(RTC_STAT, val)
+#define bfin_read_RTC_ICTL() bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val) bfin_write16(RTC_ICTL, val)
+#define bfin_read_RTC_ISTAT() bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val) bfin_write16(RTC_ISTAT, val)
+#define bfin_read_RTC_SWCNT() bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val) bfin_write16(RTC_SWCNT, val)
+#define bfin_read_RTC_ALARM() bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val) bfin_write32(RTC_ALARM, val)
+#define bfin_read_RTC_FAST() bfin_read16(RTC_FAST)
+#define bfin_write_RTC_FAST(val) bfin_write16(RTC_FAST, val)
+#define bfin_read_RTC_PREN() bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val) bfin_write16(RTC_PREN, val)
+
+
+/* UART0 Controller (0xFFC00400 - 0xFFC004FF) */
+#define bfin_read_UART0_THR() bfin_read16(UART0_THR)
+#define bfin_write_UART0_THR(val) bfin_write16(UART0_THR, val)
+#define bfin_read_UART0_RBR() bfin_read16(UART0_RBR)
+#define bfin_write_UART0_RBR(val) bfin_write16(UART0_RBR, val)
+#define bfin_read_UART0_DLL() bfin_read16(UART0_DLL)
+#define bfin_write_UART0_DLL(val) bfin_write16(UART0_DLL, val)
+#define bfin_read_UART0_IER() bfin_read16(UART0_IER)
+#define bfin_write_UART0_IER(val) bfin_write16(UART0_IER, val)
+#define bfin_read_UART0_DLH() bfin_read16(UART0_DLH)
+#define bfin_write_UART0_DLH(val) bfin_write16(UART0_DLH, val)
+#define bfin_read_UART0_IIR() bfin_read16(UART0_IIR)
+#define bfin_write_UART0_IIR(val) bfin_write16(UART0_IIR, val)
+#define bfin_read_UART0_LCR() bfin_read16(UART0_LCR)
+#define bfin_write_UART0_LCR(val) bfin_write16(UART0_LCR, val)
+#define bfin_read_UART0_MCR() bfin_read16(UART0_MCR)
+#define bfin_write_UART0_MCR(val) bfin_write16(UART0_MCR, val)
+#define bfin_read_UART0_LSR() bfin_read16(UART0_LSR)
+#define bfin_write_UART0_LSR(val) bfin_write16(UART0_LSR, val)
+#define bfin_read_UART0_MSR() bfin_read16(UART0_MSR)
+#define bfin_write_UART0_MSR(val) bfin_write16(UART0_MSR, val)
+#define bfin_read_UART0_SCR() bfin_read16(UART0_SCR)
+#define bfin_write_UART0_SCR(val) bfin_write16(UART0_SCR, val)
+#define bfin_read_UART0_GCTL() bfin_read16(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val) bfin_write16(UART0_GCTL, val)
+
+
+/* SPI Controller (0xFFC00500 - 0xFFC005FF) */
+#define bfin_read_SPI_CTL() bfin_read16(SPI_CTL)
+#define bfin_write_SPI_CTL(val) bfin_write16(SPI_CTL, val)
+#define bfin_read_SPI_FLG() bfin_read16(SPI_FLG)
+#define bfin_write_SPI_FLG(val) bfin_write16(SPI_FLG, val)
+#define bfin_read_SPI_STAT() bfin_read16(SPI_STAT)
+#define bfin_write_SPI_STAT(val) bfin_write16(SPI_STAT, val)
+#define bfin_read_SPI_TDBR() bfin_read16(SPI_TDBR)
+#define bfin_write_SPI_TDBR(val) bfin_write16(SPI_TDBR, val)
+#define bfin_read_SPI_RDBR() bfin_read16(SPI_RDBR)
+#define bfin_write_SPI_RDBR(val) bfin_write16(SPI_RDBR, val)
+#define bfin_read_SPI_BAUD() bfin_read16(SPI_BAUD)
+#define bfin_write_SPI_BAUD(val) bfin_write16(SPI_BAUD, val)
+#define bfin_read_SPI_SHADOW() bfin_read16(SPI_SHADOW)
+#define bfin_write_SPI_SHADOW(val) bfin_write16(SPI_SHADOW, val)
+
+
+/* TIMER0-7 Registers (0xFFC00600 - 0xFFC006FF) */
+#define bfin_read_TIMER0_CONFIG() bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val) bfin_write16(TIMER0_CONFIG, val)
+#define bfin_read_TIMER0_COUNTER() bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val) bfin_write32(TIMER0_COUNTER, val)
+#define bfin_read_TIMER0_PERIOD() bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val) bfin_write32(TIMER0_PERIOD, val)
+#define bfin_read_TIMER0_WIDTH() bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val) bfin_write32(TIMER0_WIDTH, val)
+
+#define bfin_read_TIMER1_CONFIG() bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val) bfin_write16(TIMER1_CONFIG, val)
+#define bfin_read_TIMER1_COUNTER() bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val) bfin_write32(TIMER1_COUNTER, val)
+#define bfin_read_TIMER1_PERIOD() bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val) bfin_write32(TIMER1_PERIOD, val)
+#define bfin_read_TIMER1_WIDTH() bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val) bfin_write32(TIMER1_WIDTH, val)
+
+#define bfin_read_TIMER2_CONFIG() bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val) bfin_write16(TIMER2_CONFIG, val)
+#define bfin_read_TIMER2_COUNTER() bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val) bfin_write32(TIMER2_COUNTER, val)
+#define bfin_read_TIMER2_PERIOD() bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val) bfin_write32(TIMER2_PERIOD, val)
+#define bfin_read_TIMER2_WIDTH() bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val) bfin_write32(TIMER2_WIDTH, val)
+
+#define bfin_read_TIMER3_CONFIG() bfin_read16(TIMER3_CONFIG)
+#define bfin_write_TIMER3_CONFIG(val) bfin_write16(TIMER3_CONFIG, val)
+#define bfin_read_TIMER3_COUNTER() bfin_read32(TIMER3_COUNTER)
+#define bfin_write_TIMER3_COUNTER(val) bfin_write32(TIMER3_COUNTER, val)
+#define bfin_read_TIMER3_PERIOD() bfin_read32(TIMER3_PERIOD)
+#define bfin_write_TIMER3_PERIOD(val) bfin_write32(TIMER3_PERIOD, val)
+#define bfin_read_TIMER3_WIDTH() bfin_read32(TIMER3_WIDTH)
+#define bfin_write_TIMER3_WIDTH(val) bfin_write32(TIMER3_WIDTH, val)
+
+#define bfin_read_TIMER4_CONFIG() bfin_read16(TIMER4_CONFIG)
+#define bfin_write_TIMER4_CONFIG(val) bfin_write16(TIMER4_CONFIG, val)
+#define bfin_read_TIMER4_COUNTER() bfin_read32(TIMER4_COUNTER)
+#define bfin_write_TIMER4_COUNTER(val) bfin_write32(TIMER4_COUNTER, val)
+#define bfin_read_TIMER4_PERIOD() bfin_read32(TIMER4_PERIOD)
+#define bfin_write_TIMER4_PERIOD(val) bfin_write32(TIMER4_PERIOD, val)
+#define bfin_read_TIMER4_WIDTH() bfin_read32(TIMER4_WIDTH)
+#define bfin_write_TIMER4_WIDTH(val) bfin_write32(TIMER4_WIDTH, val)
+
+#define bfin_read_TIMER5_CONFIG() bfin_read16(TIMER5_CONFIG)
+#define bfin_write_TIMER5_CONFIG(val) bfin_write16(TIMER5_CONFIG, val)
+#define bfin_read_TIMER5_COUNTER() bfin_read32(TIMER5_COUNTER)
+#define bfin_write_TIMER5_COUNTER(val) bfin_write32(TIMER5_COUNTER, val)
+#define bfin_read_TIMER5_PERIOD() bfin_read32(TIMER5_PERIOD)
+#define bfin_write_TIMER5_PERIOD(val) bfin_write32(TIMER5_PERIOD, val)
+#define bfin_read_TIMER5_WIDTH() bfin_read32(TIMER5_WIDTH)
+#define bfin_write_TIMER5_WIDTH(val) bfin_write32(TIMER5_WIDTH, val)
+
+#define bfin_read_TIMER6_CONFIG() bfin_read16(TIMER6_CONFIG)
+#define bfin_write_TIMER6_CONFIG(val) bfin_write16(TIMER6_CONFIG, val)
+#define bfin_read_TIMER6_COUNTER() bfin_read32(TIMER6_COUNTER)
+#define bfin_write_TIMER6_COUNTER(val) bfin_write32(TIMER6_COUNTER, val)
+#define bfin_read_TIMER6_PERIOD() bfin_read32(TIMER6_PERIOD)
+#define bfin_write_TIMER6_PERIOD(val) bfin_write32(TIMER6_PERIOD, val)
+#define bfin_read_TIMER6_WIDTH() bfin_read32(TIMER6_WIDTH)
+#define bfin_write_TIMER6_WIDTH(val) bfin_write32(TIMER6_WIDTH, val)
+
+#define bfin_read_TIMER7_CONFIG() bfin_read16(TIMER7_CONFIG)
+#define bfin_write_TIMER7_CONFIG(val) bfin_write16(TIMER7_CONFIG, val)
+#define bfin_read_TIMER7_COUNTER() bfin_read32(TIMER7_COUNTER)
+#define bfin_write_TIMER7_COUNTER(val) bfin_write32(TIMER7_COUNTER, val)
+#define bfin_read_TIMER7_PERIOD() bfin_read32(TIMER7_PERIOD)
+#define bfin_write_TIMER7_PERIOD(val) bfin_write32(TIMER7_PERIOD, val)
+#define bfin_read_TIMER7_WIDTH() bfin_read32(TIMER7_WIDTH)
+#define bfin_write_TIMER7_WIDTH(val) bfin_write32(TIMER7_WIDTH, val)
+
+#define bfin_read_TIMER_ENABLE() bfin_read16(TIMER_ENABLE)
+#define bfin_write_TIMER_ENABLE(val) bfin_write16(TIMER_ENABLE, val)
+#define bfin_read_TIMER_DISABLE() bfin_read16(TIMER_DISABLE)
+#define bfin_write_TIMER_DISABLE(val) bfin_write16(TIMER_DISABLE, val)
+#define bfin_read_TIMER_STATUS() bfin_read32(TIMER_STATUS)
+#define bfin_write_TIMER_STATUS(val) bfin_write32(TIMER_STATUS, val)
+
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF) */
+#define bfin_read_PORTFIO() bfin_read16(PORTFIO)
+#define bfin_write_PORTFIO(val) bfin_write16(PORTFIO, val)
+#define bfin_read_PORTFIO_CLEAR() bfin_read16(PORTFIO_CLEAR)
+#define bfin_write_PORTFIO_CLEAR(val) bfin_write16(PORTFIO_CLEAR, val)
+#define bfin_read_PORTFIO_SET() bfin_read16(PORTFIO_SET)
+#define bfin_write_PORTFIO_SET(val) bfin_write16(PORTFIO_SET, val)
+#define bfin_read_PORTFIO_TOGGLE() bfin_read16(PORTFIO_TOGGLE)
+#define bfin_write_PORTFIO_TOGGLE(val) bfin_write16(PORTFIO_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKA() bfin_read16(PORTFIO_MASKA)
+#define bfin_write_PORTFIO_MASKA(val) bfin_write16(PORTFIO_MASKA, val)
+#define bfin_read_PORTFIO_MASKA_CLEAR() bfin_read16(PORTFIO_MASKA_CLEAR)
+#define bfin_write_PORTFIO_MASKA_CLEAR(val) bfin_write16(PORTFIO_MASKA_CLEAR, val)
+#define bfin_read_PORTFIO_MASKA_SET() bfin_read16(PORTFIO_MASKA_SET)
+#define bfin_write_PORTFIO_MASKA_SET(val) bfin_write16(PORTFIO_MASKA_SET, val)
+#define bfin_read_PORTFIO_MASKA_TOGGLE() bfin_read16(PORTFIO_MASKA_TOGGLE)
+#define bfin_write_PORTFIO_MASKA_TOGGLE(val) bfin_write16(PORTFIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKB() bfin_read16(PORTFIO_MASKB)
+#define bfin_write_PORTFIO_MASKB(val) bfin_write16(PORTFIO_MASKB, val)
+#define bfin_read_PORTFIO_MASKB_CLEAR() bfin_read16(PORTFIO_MASKB_CLEAR)
+#define bfin_write_PORTFIO_MASKB_CLEAR(val) bfin_write16(PORTFIO_MASKB_CLEAR, val)
+#define bfin_read_PORTFIO_MASKB_SET() bfin_read16(PORTFIO_MASKB_SET)
+#define bfin_write_PORTFIO_MASKB_SET(val) bfin_write16(PORTFIO_MASKB_SET, val)
+#define bfin_read_PORTFIO_MASKB_TOGGLE() bfin_read16(PORTFIO_MASKB_TOGGLE)
+#define bfin_write_PORTFIO_MASKB_TOGGLE(val) bfin_write16(PORTFIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTFIO_DIR() bfin_read16(PORTFIO_DIR)
+#define bfin_write_PORTFIO_DIR(val) bfin_write16(PORTFIO_DIR, val)
+#define bfin_read_PORTFIO_POLAR() bfin_read16(PORTFIO_POLAR)
+#define bfin_write_PORTFIO_POLAR(val) bfin_write16(PORTFIO_POLAR, val)
+#define bfin_read_PORTFIO_EDGE() bfin_read16(PORTFIO_EDGE)
+#define bfin_write_PORTFIO_EDGE(val) bfin_write16(PORTFIO_EDGE, val)
+#define bfin_read_PORTFIO_BOTH() bfin_read16(PORTFIO_BOTH)
+#define bfin_write_PORTFIO_BOTH(val) bfin_write16(PORTFIO_BOTH, val)
+#define bfin_read_PORTFIO_INEN() bfin_read16(PORTFIO_INEN)
+#define bfin_write_PORTFIO_INEN(val) bfin_write16(PORTFIO_INEN, val)
+
+
+/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
+#define bfin_read_SPORT0_TCR1() bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val) bfin_write16(SPORT0_TCR1, val)
+#define bfin_read_SPORT0_TCR2() bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val) bfin_write16(SPORT0_TCR2, val)
+#define bfin_read_SPORT0_TCLKDIV() bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val) bfin_write16(SPORT0_TCLKDIV, val)
+#define bfin_read_SPORT0_TFSDIV() bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val) bfin_write16(SPORT0_TFSDIV, val)
+#define bfin_read_SPORT0_TX() bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val) bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX() bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val) bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_TX32() bfin_read32(SPORT0_TX32)
+#define bfin_write_SPORT0_TX32(val) bfin_write32(SPORT0_TX32, val)
+#define bfin_read_SPORT0_RX32() bfin_read32(SPORT0_RX32)
+#define bfin_write_SPORT0_RX32(val) bfin_write32(SPORT0_RX32, val)
+#define bfin_read_SPORT0_TX16() bfin_read16(SPORT0_TX16)
+#define bfin_write_SPORT0_TX16(val) bfin_write16(SPORT0_TX16, val)
+#define bfin_read_SPORT0_RX16() bfin_read16(SPORT0_RX16)
+#define bfin_write_SPORT0_RX16(val) bfin_write16(SPORT0_RX16, val)
+#define bfin_read_SPORT0_RCR1() bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val) bfin_write16(SPORT0_RCR1, val)
+#define bfin_read_SPORT0_RCR2() bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val) bfin_write16(SPORT0_RCR2, val)
+#define bfin_read_SPORT0_RCLKDIV() bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val) bfin_write16(SPORT0_RCLKDIV, val)
+#define bfin_read_SPORT0_RFSDIV() bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val) bfin_write16(SPORT0_RFSDIV, val)
+#define bfin_read_SPORT0_STAT() bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val) bfin_write16(SPORT0_STAT, val)
+#define bfin_read_SPORT0_CHNL() bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val) bfin_write16(SPORT0_CHNL, val)
+#define bfin_read_SPORT0_MCMC1() bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val) bfin_write16(SPORT0_MCMC1, val)
+#define bfin_read_SPORT0_MCMC2() bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val) bfin_write16(SPORT0_MCMC2, val)
+#define bfin_read_SPORT0_MTCS0() bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val) bfin_write32(SPORT0_MTCS0, val)
+#define bfin_read_SPORT0_MTCS1() bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val) bfin_write32(SPORT0_MTCS1, val)
+#define bfin_read_SPORT0_MTCS2() bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val) bfin_write32(SPORT0_MTCS2, val)
+#define bfin_read_SPORT0_MTCS3() bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val) bfin_write32(SPORT0_MTCS3, val)
+#define bfin_read_SPORT0_MRCS0() bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val) bfin_write32(SPORT0_MRCS0, val)
+#define bfin_read_SPORT0_MRCS1() bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val) bfin_write32(SPORT0_MRCS1, val)
+#define bfin_read_SPORT0_MRCS2() bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val) bfin_write32(SPORT0_MRCS2, val)
+#define bfin_read_SPORT0_MRCS3() bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val) bfin_write32(SPORT0_MRCS3, val)
+
+
+/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
+#define bfin_read_SPORT1_TCR1() bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val) bfin_write16(SPORT1_TCR1, val)
+#define bfin_read_SPORT1_TCR2() bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val) bfin_write16(SPORT1_TCR2, val)
+#define bfin_read_SPORT1_TCLKDIV() bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val) bfin_write16(SPORT1_TCLKDIV, val)
+#define bfin_read_SPORT1_TFSDIV() bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val) bfin_write16(SPORT1_TFSDIV, val)
+#define bfin_read_SPORT1_TX() bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val) bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX() bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val) bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_TX32() bfin_read32(SPORT1_TX32)
+#define bfin_write_SPORT1_TX32(val) bfin_write32(SPORT1_TX32, val)
+#define bfin_read_SPORT1_RX32() bfin_read32(SPORT1_RX32)
+#define bfin_write_SPORT1_RX32(val) bfin_write32(SPORT1_RX32, val)
+#define bfin_read_SPORT1_TX16() bfin_read16(SPORT1_TX16)
+#define bfin_write_SPORT1_TX16(val) bfin_write16(SPORT1_TX16, val)
+#define bfin_read_SPORT1_RX16() bfin_read16(SPORT1_RX16)
+#define bfin_write_SPORT1_RX16(val) bfin_write16(SPORT1_RX16, val)
+#define bfin_read_SPORT1_RCR1() bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val) bfin_write16(SPORT1_RCR1, val)
+#define bfin_read_SPORT1_RCR2() bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val) bfin_write16(SPORT1_RCR2, val)
+#define bfin_read_SPORT1_RCLKDIV() bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val) bfin_write16(SPORT1_RCLKDIV, val)
+#define bfin_read_SPORT1_RFSDIV() bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val) bfin_write16(SPORT1_RFSDIV, val)
+#define bfin_read_SPORT1_STAT() bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val) bfin_write16(SPORT1_STAT, val)
+#define bfin_read_SPORT1_CHNL() bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val) bfin_write16(SPORT1_CHNL, val)
+#define bfin_read_SPORT1_MCMC1() bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val) bfin_write16(SPORT1_MCMC1, val)
+#define bfin_read_SPORT1_MCMC2() bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val) bfin_write16(SPORT1_MCMC2, val)
+#define bfin_read_SPORT1_MTCS0() bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val) bfin_write32(SPORT1_MTCS0, val)
+#define bfin_read_SPORT1_MTCS1() bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val) bfin_write32(SPORT1_MTCS1, val)
+#define bfin_read_SPORT1_MTCS2() bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val) bfin_write32(SPORT1_MTCS2, val)
+#define bfin_read_SPORT1_MTCS3() bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val) bfin_write32(SPORT1_MTCS3, val)
+#define bfin_read_SPORT1_MRCS0() bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val) bfin_write32(SPORT1_MRCS0, val)
+#define bfin_read_SPORT1_MRCS1() bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val) bfin_write32(SPORT1_MRCS1, val)
+#define bfin_read_SPORT1_MRCS2() bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val) bfin_write32(SPORT1_MRCS2, val)
+#define bfin_read_SPORT1_MRCS3() bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val) bfin_write32(SPORT1_MRCS3, val)
+
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
+#define bfin_read_EBIU_AMGCTL() bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val) bfin_write16(EBIU_AMGCTL, val)
+#define bfin_read_EBIU_AMBCTL0() bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val) bfin_write32(EBIU_AMBCTL0, val)
+#define bfin_read_EBIU_AMBCTL1() bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val) bfin_write32(EBIU_AMBCTL1, val)
+#define bfin_read_EBIU_SDGCTL() bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val) bfin_write32(EBIU_SDGCTL, val)
+#define bfin_read_EBIU_SDBCTL() bfin_read16(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val) bfin_write16(EBIU_SDBCTL, val)
+#define bfin_read_EBIU_SDRRC() bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val) bfin_write16(EBIU_SDRRC, val)
+#define bfin_read_EBIU_SDSTAT() bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val) bfin_write16(EBIU_SDSTAT, val)
+
+
+/* DMA Traffic Control Registers */
+#define bfin_read_DMA_TC_PER() bfin_read16(DMA_TC_PER)
+#define bfin_write_DMA_TC_PER(val) bfin_write16(DMA_TC_PER, val)
+#define bfin_read_DMA_TC_CNT() bfin_read16(DMA_TC_CNT)
+#define bfin_write_DMA_TC_CNT(val) bfin_write16(DMA_TC_CNT, val)
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define bfin_read_DMA_TCPER() bfin_read16(DMA_TCPER)
+#define bfin_write_DMA_TCPER(val) bfin_write16(DMA_TCPER, val)
+#define bfin_read_DMA_TCCNT() bfin_read16(DMA_TCCNT)
+#define bfin_write_DMA_TCCNT(val) bfin_write16(DMA_TCCNT, val)
+
+/* DMA Controller */
+#define bfin_read_DMA0_CONFIG() bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val) bfin_write16(DMA0_CONFIG, val)
+#define bfin_read_DMA0_NEXT_DESC_PTR() bfin_read32(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val) bfin_write32(DMA0_NEXT_DESC_PTR, val)
+#define bfin_read_DMA0_START_ADDR() bfin_read32(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val) bfin_write32(DMA0_START_ADDR, val)
+#define bfin_read_DMA0_X_COUNT() bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val) bfin_write16(DMA0_X_COUNT, val)
+#define bfin_read_DMA0_Y_COUNT() bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val) bfin_write16(DMA0_Y_COUNT, val)
+#define bfin_read_DMA0_X_MODIFY() bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val) bfin_write16(DMA0_X_MODIFY, val)
+#define bfin_read_DMA0_Y_MODIFY() bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val) bfin_write16(DMA0_Y_MODIFY, val)
+#define bfin_read_DMA0_CURR_DESC_PTR() bfin_read32(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val) bfin_write32(DMA0_CURR_DESC_PTR, val)
+#define bfin_read_DMA0_CURR_ADDR() bfin_read32(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val) bfin_write32(DMA0_CURR_ADDR, val)
+#define bfin_read_DMA0_CURR_X_COUNT() bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val) bfin_write16(DMA0_CURR_X_COUNT, val)
+#define bfin_read_DMA0_CURR_Y_COUNT() bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val) bfin_write16(DMA0_CURR_Y_COUNT, val)
+#define bfin_read_DMA0_IRQ_STATUS() bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val) bfin_write16(DMA0_IRQ_STATUS, val)
+#define bfin_read_DMA0_PERIPHERAL_MAP() bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val) bfin_write16(DMA0_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA1_CONFIG() bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val) bfin_write16(DMA1_CONFIG, val)
+#define bfin_read_DMA1_NEXT_DESC_PTR() bfin_read32(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val) bfin_write32(DMA1_NEXT_DESC_PTR, val)
+#define bfin_read_DMA1_START_ADDR() bfin_read32(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val) bfin_write32(DMA1_START_ADDR, val)
+#define bfin_read_DMA1_X_COUNT() bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val) bfin_write16(DMA1_X_COUNT, val)
+#define bfin_read_DMA1_Y_COUNT() bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val) bfin_write16(DMA1_Y_COUNT, val)
+#define bfin_read_DMA1_X_MODIFY() bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val) bfin_write16(DMA1_X_MODIFY, val)
+#define bfin_read_DMA1_Y_MODIFY() bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val) bfin_write16(DMA1_Y_MODIFY, val)
+#define bfin_read_DMA1_CURR_DESC_PTR() bfin_read32(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val) bfin_write32(DMA1_CURR_DESC_PTR, val)
+#define bfin_read_DMA1_CURR_ADDR() bfin_read32(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val) bfin_write32(DMA1_CURR_ADDR, val)
+#define bfin_read_DMA1_CURR_X_COUNT() bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val) bfin_write16(DMA1_CURR_X_COUNT, val)
+#define bfin_read_DMA1_CURR_Y_COUNT() bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val) bfin_write16(DMA1_CURR_Y_COUNT, val)
+#define bfin_read_DMA1_IRQ_STATUS() bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val) bfin_write16(DMA1_IRQ_STATUS, val)
+#define bfin_read_DMA1_PERIPHERAL_MAP() bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val) bfin_write16(DMA1_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA2_CONFIG() bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val) bfin_write16(DMA2_CONFIG, val)
+#define bfin_read_DMA2_NEXT_DESC_PTR() bfin_read32(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val) bfin_write32(DMA2_NEXT_DESC_PTR, val)
+#define bfin_read_DMA2_START_ADDR() bfin_read32(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val) bfin_write32(DMA2_START_ADDR, val)
+#define bfin_read_DMA2_X_COUNT() bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val) bfin_write16(DMA2_X_COUNT, val)
+#define bfin_read_DMA2_Y_COUNT() bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val) bfin_write16(DMA2_Y_COUNT, val)
+#define bfin_read_DMA2_X_MODIFY() bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val) bfin_write16(DMA2_X_MODIFY, val)
+#define bfin_read_DMA2_Y_MODIFY() bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val) bfin_write16(DMA2_Y_MODIFY, val)
+#define bfin_read_DMA2_CURR_DESC_PTR() bfin_read32(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val) bfin_write32(DMA2_CURR_DESC_PTR, val)
+#define bfin_read_DMA2_CURR_ADDR() bfin_read32(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val) bfin_write32(DMA2_CURR_ADDR, val)
+#define bfin_read_DMA2_CURR_X_COUNT() bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val) bfin_write16(DMA2_CURR_X_COUNT, val)
+#define bfin_read_DMA2_CURR_Y_COUNT() bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val) bfin_write16(DMA2_CURR_Y_COUNT, val)
+#define bfin_read_DMA2_IRQ_STATUS() bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val) bfin_write16(DMA2_IRQ_STATUS, val)
+#define bfin_read_DMA2_PERIPHERAL_MAP() bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val) bfin_write16(DMA2_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA3_CONFIG() bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val) bfin_write16(DMA3_CONFIG, val)
+#define bfin_read_DMA3_NEXT_DESC_PTR() bfin_read32(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val) bfin_write32(DMA3_NEXT_DESC_PTR, val)
+#define bfin_read_DMA3_START_ADDR() bfin_read32(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val) bfin_write32(DMA3_START_ADDR, val)
+#define bfin_read_DMA3_X_COUNT() bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val) bfin_write16(DMA3_X_COUNT, val)
+#define bfin_read_DMA3_Y_COUNT() bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val) bfin_write16(DMA3_Y_COUNT, val)
+#define bfin_read_DMA3_X_MODIFY() bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val) bfin_write16(DMA3_X_MODIFY, val)
+#define bfin_read_DMA3_Y_MODIFY() bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val) bfin_write16(DMA3_Y_MODIFY, val)
+#define bfin_read_DMA3_CURR_DESC_PTR() bfin_read32(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val) bfin_write32(DMA3_CURR_DESC_PTR, val)
+#define bfin_read_DMA3_CURR_ADDR() bfin_read32(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val) bfin_write32(DMA3_CURR_ADDR, val)
+#define bfin_read_DMA3_CURR_X_COUNT() bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val) bfin_write16(DMA3_CURR_X_COUNT, val)
+#define bfin_read_DMA3_CURR_Y_COUNT() bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val) bfin_write16(DMA3_CURR_Y_COUNT, val)
+#define bfin_read_DMA3_IRQ_STATUS() bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val) bfin_write16(DMA3_IRQ_STATUS, val)
+#define bfin_read_DMA3_PERIPHERAL_MAP() bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val) bfin_write16(DMA3_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA4_CONFIG() bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val) bfin_write16(DMA4_CONFIG, val)
+#define bfin_read_DMA4_NEXT_DESC_PTR() bfin_read32(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val) bfin_write32(DMA4_NEXT_DESC_PTR, val)
+#define bfin_read_DMA4_START_ADDR() bfin_read32(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val) bfin_write32(DMA4_START_ADDR, val)
+#define bfin_read_DMA4_X_COUNT() bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val) bfin_write16(DMA4_X_COUNT, val)
+#define bfin_read_DMA4_Y_COUNT() bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val) bfin_write16(DMA4_Y_COUNT, val)
+#define bfin_read_DMA4_X_MODIFY() bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val) bfin_write16(DMA4_X_MODIFY, val)
+#define bfin_read_DMA4_Y_MODIFY() bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val) bfin_write16(DMA4_Y_MODIFY, val)
+#define bfin_read_DMA4_CURR_DESC_PTR() bfin_read32(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val) bfin_write32(DMA4_CURR_DESC_PTR, val)
+#define bfin_read_DMA4_CURR_ADDR() bfin_read32(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val) bfin_write32(DMA4_CURR_ADDR, val)
+#define bfin_read_DMA4_CURR_X_COUNT() bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val) bfin_write16(DMA4_CURR_X_COUNT, val)
+#define bfin_read_DMA4_CURR_Y_COUNT() bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val) bfin_write16(DMA4_CURR_Y_COUNT, val)
+#define bfin_read_DMA4_IRQ_STATUS() bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val) bfin_write16(DMA4_IRQ_STATUS, val)
+#define bfin_read_DMA4_PERIPHERAL_MAP() bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val) bfin_write16(DMA4_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA5_CONFIG() bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val) bfin_write16(DMA5_CONFIG, val)
+#define bfin_read_DMA5_NEXT_DESC_PTR() bfin_read32(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val) bfin_write32(DMA5_NEXT_DESC_PTR, val)
+#define bfin_read_DMA5_START_ADDR() bfin_read32(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val) bfin_write32(DMA5_START_ADDR, val)
+#define bfin_read_DMA5_X_COUNT() bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val) bfin_write16(DMA5_X_COUNT, val)
+#define bfin_read_DMA5_Y_COUNT() bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val) bfin_write16(DMA5_Y_COUNT, val)
+#define bfin_read_DMA5_X_MODIFY() bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val) bfin_write16(DMA5_X_MODIFY, val)
+#define bfin_read_DMA5_Y_MODIFY() bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val) bfin_write16(DMA5_Y_MODIFY, val)
+#define bfin_read_DMA5_CURR_DESC_PTR() bfin_read32(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val) bfin_write32(DMA5_CURR_DESC_PTR, val)
+#define bfin_read_DMA5_CURR_ADDR() bfin_read32(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val) bfin_write32(DMA5_CURR_ADDR, val)
+#define bfin_read_DMA5_CURR_X_COUNT() bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val) bfin_write16(DMA5_CURR_X_COUNT, val)
+#define bfin_read_DMA5_CURR_Y_COUNT() bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val) bfin_write16(DMA5_CURR_Y_COUNT, val)
+#define bfin_read_DMA5_IRQ_STATUS() bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val) bfin_write16(DMA5_IRQ_STATUS, val)
+#define bfin_read_DMA5_PERIPHERAL_MAP() bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val) bfin_write16(DMA5_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA6_CONFIG() bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val) bfin_write16(DMA6_CONFIG, val)
+#define bfin_read_DMA6_NEXT_DESC_PTR() bfin_read32(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val) bfin_write32(DMA6_NEXT_DESC_PTR, val)
+#define bfin_read_DMA6_START_ADDR() bfin_read32(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val) bfin_write32(DMA6_START_ADDR, val)
+#define bfin_read_DMA6_X_COUNT() bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val) bfin_write16(DMA6_X_COUNT, val)
+#define bfin_read_DMA6_Y_COUNT() bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val) bfin_write16(DMA6_Y_COUNT, val)
+#define bfin_read_DMA6_X_MODIFY() bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val) bfin_write16(DMA6_X_MODIFY, val)
+#define bfin_read_DMA6_Y_MODIFY() bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val) bfin_write16(DMA6_Y_MODIFY, val)
+#define bfin_read_DMA6_CURR_DESC_PTR() bfin_read32(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val) bfin_write32(DMA6_CURR_DESC_PTR, val)
+#define bfin_read_DMA6_CURR_ADDR() bfin_read32(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val) bfin_write32(DMA6_CURR_ADDR, val)
+#define bfin_read_DMA6_CURR_X_COUNT() bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val) bfin_write16(DMA6_CURR_X_COUNT, val)
+#define bfin_read_DMA6_CURR_Y_COUNT() bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val) bfin_write16(DMA6_CURR_Y_COUNT, val)
+#define bfin_read_DMA6_IRQ_STATUS() bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val) bfin_write16(DMA6_IRQ_STATUS, val)
+#define bfin_read_DMA6_PERIPHERAL_MAP() bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val) bfin_write16(DMA6_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA7_CONFIG() bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val) bfin_write16(DMA7_CONFIG, val)
+#define bfin_read_DMA7_NEXT_DESC_PTR() bfin_read32(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val) bfin_write32(DMA7_NEXT_DESC_PTR, val)
+#define bfin_read_DMA7_START_ADDR() bfin_read32(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val) bfin_write32(DMA7_START_ADDR, val)
+#define bfin_read_DMA7_X_COUNT() bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val) bfin_write16(DMA7_X_COUNT, val)
+#define bfin_read_DMA7_Y_COUNT() bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val) bfin_write16(DMA7_Y_COUNT, val)
+#define bfin_read_DMA7_X_MODIFY() bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val) bfin_write16(DMA7_X_MODIFY, val)
+#define bfin_read_DMA7_Y_MODIFY() bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val) bfin_write16(DMA7_Y_MODIFY, val)
+#define bfin_read_DMA7_CURR_DESC_PTR() bfin_read32(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val) bfin_write32(DMA7_CURR_DESC_PTR, val)
+#define bfin_read_DMA7_CURR_ADDR() bfin_read32(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val) bfin_write32(DMA7_CURR_ADDR, val)
+#define bfin_read_DMA7_CURR_X_COUNT() bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val) bfin_write16(DMA7_CURR_X_COUNT, val)
+#define bfin_read_DMA7_CURR_Y_COUNT() bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val) bfin_write16(DMA7_CURR_Y_COUNT, val)
+#define bfin_read_DMA7_IRQ_STATUS() bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val) bfin_write16(DMA7_IRQ_STATUS, val)
+#define bfin_read_DMA7_PERIPHERAL_MAP() bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val) bfin_write16(DMA7_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA8_CONFIG() bfin_read16(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val) bfin_write16(DMA8_CONFIG, val)
+#define bfin_read_DMA8_NEXT_DESC_PTR() bfin_read32(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val) bfin_write32(DMA8_NEXT_DESC_PTR, val)
+#define bfin_read_DMA8_START_ADDR() bfin_read32(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val) bfin_write32(DMA8_START_ADDR, val)
+#define bfin_read_DMA8_X_COUNT() bfin_read16(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val) bfin_write16(DMA8_X_COUNT, val)
+#define bfin_read_DMA8_Y_COUNT() bfin_read16(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val) bfin_write16(DMA8_Y_COUNT, val)
+#define bfin_read_DMA8_X_MODIFY() bfin_read16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val) bfin_write16(DMA8_X_MODIFY, val)
+#define bfin_read_DMA8_Y_MODIFY() bfin_read16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val) bfin_write16(DMA8_Y_MODIFY, val)
+#define bfin_read_DMA8_CURR_DESC_PTR() bfin_read32(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val) bfin_write32(DMA8_CURR_DESC_PTR, val)
+#define bfin_read_DMA8_CURR_ADDR() bfin_read32(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val) bfin_write32(DMA8_CURR_ADDR, val)
+#define bfin_read_DMA8_CURR_X_COUNT() bfin_read16(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val) bfin_write16(DMA8_CURR_X_COUNT, val)
+#define bfin_read_DMA8_CURR_Y_COUNT() bfin_read16(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val) bfin_write16(DMA8_CURR_Y_COUNT, val)
+#define bfin_read_DMA8_IRQ_STATUS() bfin_read16(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val) bfin_write16(DMA8_IRQ_STATUS, val)
+#define bfin_read_DMA8_PERIPHERAL_MAP() bfin_read16(DMA8_PERIPHERAL_MAP)
+#define bfin_write_DMA8_PERIPHERAL_MAP(val) bfin_write16(DMA8_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA9_CONFIG() bfin_read16(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val) bfin_write16(DMA9_CONFIG, val)
+#define bfin_read_DMA9_NEXT_DESC_PTR() bfin_read32(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val) bfin_write32(DMA9_NEXT_DESC_PTR, val)
+#define bfin_read_DMA9_START_ADDR() bfin_read32(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val) bfin_write32(DMA9_START_ADDR, val)
+#define bfin_read_DMA9_X_COUNT() bfin_read16(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val) bfin_write16(DMA9_X_COUNT, val)
+#define bfin_read_DMA9_Y_COUNT() bfin_read16(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val) bfin_write16(DMA9_Y_COUNT, val)
+#define bfin_read_DMA9_X_MODIFY() bfin_read16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val) bfin_write16(DMA9_X_MODIFY, val)
+#define bfin_read_DMA9_Y_MODIFY() bfin_read16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val) bfin_write16(DMA9_Y_MODIFY, val)
+#define bfin_read_DMA9_CURR_DESC_PTR() bfin_read32(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val) bfin_write32(DMA9_CURR_DESC_PTR, val)
+#define bfin_read_DMA9_CURR_ADDR() bfin_read32(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val) bfin_write32(DMA9_CURR_ADDR, val)
+#define bfin_read_DMA9_CURR_X_COUNT() bfin_read16(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val) bfin_write16(DMA9_CURR_X_COUNT, val)
+#define bfin_read_DMA9_CURR_Y_COUNT() bfin_read16(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val) bfin_write16(DMA9_CURR_Y_COUNT, val)
+#define bfin_read_DMA9_IRQ_STATUS() bfin_read16(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val) bfin_write16(DMA9_IRQ_STATUS, val)
+#define bfin_read_DMA9_PERIPHERAL_MAP() bfin_read16(DMA9_PERIPHERAL_MAP)
+#define bfin_write_DMA9_PERIPHERAL_MAP(val) bfin_write16(DMA9_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA10_CONFIG() bfin_read16(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val) bfin_write16(DMA10_CONFIG, val)
+#define bfin_read_DMA10_NEXT_DESC_PTR() bfin_read32(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val) bfin_write32(DMA10_NEXT_DESC_PTR, val)
+#define bfin_read_DMA10_START_ADDR() bfin_read32(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val) bfin_write32(DMA10_START_ADDR, val)
+#define bfin_read_DMA10_X_COUNT() bfin_read16(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val) bfin_write16(DMA10_X_COUNT, val)
+#define bfin_read_DMA10_Y_COUNT() bfin_read16(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val) bfin_write16(DMA10_Y_COUNT, val)
+#define bfin_read_DMA10_X_MODIFY() bfin_read16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val) bfin_write16(DMA10_X_MODIFY, val)
+#define bfin_read_DMA10_Y_MODIFY() bfin_read16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val) bfin_write16(DMA10_Y_MODIFY, val)
+#define bfin_read_DMA10_CURR_DESC_PTR() bfin_read32(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val) bfin_write32(DMA10_CURR_DESC_PTR, val)
+#define bfin_read_DMA10_CURR_ADDR() bfin_read32(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val) bfin_write32(DMA10_CURR_ADDR, val)
+#define bfin_read_DMA10_CURR_X_COUNT() bfin_read16(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val) bfin_write16(DMA10_CURR_X_COUNT, val)
+#define bfin_read_DMA10_CURR_Y_COUNT() bfin_read16(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val) bfin_write16(DMA10_CURR_Y_COUNT, val)
+#define bfin_read_DMA10_IRQ_STATUS() bfin_read16(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val) bfin_write16(DMA10_IRQ_STATUS, val)
+#define bfin_read_DMA10_PERIPHERAL_MAP() bfin_read16(DMA10_PERIPHERAL_MAP)
+#define bfin_write_DMA10_PERIPHERAL_MAP(val) bfin_write16(DMA10_PERIPHERAL_MAP, val)
+
+#define bfin_read_DMA11_CONFIG() bfin_read16(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val) bfin_write16(DMA11_CONFIG, val)
+#define bfin_read_DMA11_NEXT_DESC_PTR() bfin_read32(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val) bfin_write32(DMA11_NEXT_DESC_PTR, val)
+#define bfin_read_DMA11_START_ADDR() bfin_read32(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val) bfin_write32(DMA11_START_ADDR, val)
+#define bfin_read_DMA11_X_COUNT() bfin_read16(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val) bfin_write16(DMA11_X_COUNT, val)
+#define bfin_read_DMA11_Y_COUNT() bfin_read16(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val) bfin_write16(DMA11_Y_COUNT, val)
+#define bfin_read_DMA11_X_MODIFY() bfin_read16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val) bfin_write16(DMA11_X_MODIFY, val)
+#define bfin_read_DMA11_Y_MODIFY() bfin_read16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val) bfin_write16(DMA11_Y_MODIFY, val)
+#define bfin_read_DMA11_CURR_DESC_PTR() bfin_read32(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val) bfin_write32(DMA11_CURR_DESC_PTR, val)
+#define bfin_read_DMA11_CURR_ADDR() bfin_read32(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val) bfin_write32(DMA11_CURR_ADDR, val)
+#define bfin_read_DMA11_CURR_X_COUNT() bfin_read16(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val) bfin_write16(DMA11_CURR_X_COUNT, val)
+#define bfin_read_DMA11_CURR_Y_COUNT() bfin_read16(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val) bfin_write16(DMA11_CURR_Y_COUNT, val)
+#define bfin_read_DMA11_IRQ_STATUS() bfin_read16(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val) bfin_write16(DMA11_IRQ_STATUS, val)
+#define bfin_read_DMA11_PERIPHERAL_MAP() bfin_read16(DMA11_PERIPHERAL_MAP)
+#define bfin_write_DMA11_PERIPHERAL_MAP(val) bfin_write16(DMA11_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D0_CONFIG() bfin_read16(MDMA_D0_CONFIG)
+#define bfin_write_MDMA_D0_CONFIG(val) bfin_write16(MDMA_D0_CONFIG, val)
+#define bfin_read_MDMA_D0_NEXT_DESC_PTR() bfin_read32(MDMA_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA_D0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D0_START_ADDR() bfin_read32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write32(MDMA_D0_START_ADDR, val)
+#define bfin_read_MDMA_D0_X_COUNT() bfin_read16(MDMA_D0_X_COUNT)
+#define bfin_write_MDMA_D0_X_COUNT(val) bfin_write16(MDMA_D0_X_COUNT, val)
+#define bfin_read_MDMA_D0_Y_COUNT() bfin_read16(MDMA_D0_Y_COUNT)
+#define bfin_write_MDMA_D0_Y_COUNT(val) bfin_write16(MDMA_D0_Y_COUNT, val)
+#define bfin_read_MDMA_D0_X_MODIFY() bfin_read16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write16(MDMA_D0_X_MODIFY, val)
+#define bfin_read_MDMA_D0_Y_MODIFY() bfin_read16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write16(MDMA_D0_Y_MODIFY, val)
+#define bfin_read_MDMA_D0_CURR_DESC_PTR() bfin_read32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D0_CURR_ADDR() bfin_read32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val) bfin_write32(MDMA_D0_CURR_ADDR, val)
+#define bfin_read_MDMA_D0_CURR_X_COUNT() bfin_read16(MDMA_D0_CURR_X_COUNT)
+#define bfin_write_MDMA_D0_CURR_X_COUNT(val) bfin_write16(MDMA_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D0_CURR_Y_COUNT() bfin_read16(MDMA_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA_D0_CURR_Y_COUNT(val) bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D0_IRQ_STATUS() bfin_read16(MDMA_D0_IRQ_STATUS)
+#define bfin_write_MDMA_D0_IRQ_STATUS(val) bfin_write16(MDMA_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA_D0_PERIPHERAL_MAP() bfin_read16(MDMA_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA_D0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S0_CONFIG() bfin_read16(MDMA_S0_CONFIG)
+#define bfin_write_MDMA_S0_CONFIG(val) bfin_write16(MDMA_S0_CONFIG, val)
+#define bfin_read_MDMA_S0_NEXT_DESC_PTR() bfin_read32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S0_START_ADDR() bfin_read32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val) bfin_write32(MDMA_S0_START_ADDR, val)
+#define bfin_read_MDMA_S0_X_COUNT() bfin_read16(MDMA_S0_X_COUNT)
+#define bfin_write_MDMA_S0_X_COUNT(val) bfin_write16(MDMA_S0_X_COUNT, val)
+#define bfin_read_MDMA_S0_Y_COUNT() bfin_read16(MDMA_S0_Y_COUNT)
+#define bfin_write_MDMA_S0_Y_COUNT(val) bfin_write16(MDMA_S0_Y_COUNT, val)
+#define bfin_read_MDMA_S0_X_MODIFY() bfin_read16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write16(MDMA_S0_X_MODIFY, val)
+#define bfin_read_MDMA_S0_Y_MODIFY() bfin_read16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write16(MDMA_S0_Y_MODIFY, val)
+#define bfin_read_MDMA_S0_CURR_DESC_PTR() bfin_read32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S0_CURR_ADDR() bfin_read32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val) bfin_write32(MDMA_S0_CURR_ADDR, val)
+#define bfin_read_MDMA_S0_CURR_X_COUNT() bfin_read16(MDMA_S0_CURR_X_COUNT)
+#define bfin_write_MDMA_S0_CURR_X_COUNT(val) bfin_write16(MDMA_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S0_CURR_Y_COUNT() bfin_read16(MDMA_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA_S0_CURR_Y_COUNT(val) bfin_write16(MDMA_S0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S0_IRQ_STATUS() bfin_read16(MDMA_S0_IRQ_STATUS)
+#define bfin_write_MDMA_S0_IRQ_STATUS(val) bfin_write16(MDMA_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA_S0_PERIPHERAL_MAP() bfin_read16(MDMA_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA_S0_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_D1_CONFIG() bfin_read16(MDMA_D1_CONFIG)
+#define bfin_write_MDMA_D1_CONFIG(val) bfin_write16(MDMA_D1_CONFIG, val)
+#define bfin_read_MDMA_D1_NEXT_DESC_PTR() bfin_read32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_D1_START_ADDR() bfin_read32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val) bfin_write32(MDMA_D1_START_ADDR, val)
+#define bfin_read_MDMA_D1_X_COUNT() bfin_read16(MDMA_D1_X_COUNT)
+#define bfin_write_MDMA_D1_X_COUNT(val) bfin_write16(MDMA_D1_X_COUNT, val)
+#define bfin_read_MDMA_D1_Y_COUNT() bfin_read16(MDMA_D1_Y_COUNT)
+#define bfin_write_MDMA_D1_Y_COUNT(val) bfin_write16(MDMA_D1_Y_COUNT, val)
+#define bfin_read_MDMA_D1_X_MODIFY() bfin_read16(MDMA_D1_X_MODIFY)
+#define bfin_write_MDMA_D1_X_MODIFY(val) bfin_write16(MDMA_D1_X_MODIFY, val)
+#define bfin_read_MDMA_D1_Y_MODIFY() bfin_read16(MDMA_D1_Y_MODIFY)
+#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write16(MDMA_D1_Y_MODIFY, val)
+#define bfin_read_MDMA_D1_CURR_DESC_PTR() bfin_read32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_D1_CURR_ADDR() bfin_read32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val) bfin_write32(MDMA_D1_CURR_ADDR, val)
+#define bfin_read_MDMA_D1_CURR_X_COUNT() bfin_read16(MDMA_D1_CURR_X_COUNT)
+#define bfin_write_MDMA_D1_CURR_X_COUNT(val) bfin_write16(MDMA_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_D1_CURR_Y_COUNT() bfin_read16(MDMA_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA_D1_CURR_Y_COUNT(val) bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_D1_IRQ_STATUS() bfin_read16(MDMA_D1_IRQ_STATUS)
+#define bfin_write_MDMA_D1_IRQ_STATUS(val) bfin_write16(MDMA_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA_D1_PERIPHERAL_MAP() bfin_read16(MDMA_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA_D1_PERIPHERAL_MAP, val)
+
+#define bfin_read_MDMA_S1_CONFIG() bfin_read16(MDMA_S1_CONFIG)
+#define bfin_write_MDMA_S1_CONFIG(val) bfin_write16(MDMA_S1_CONFIG, val)
+#define bfin_read_MDMA_S1_NEXT_DESC_PTR() bfin_read32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA_S1_START_ADDR() bfin_read32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val) bfin_write32(MDMA_S1_START_ADDR, val)
+#define bfin_read_MDMA_S1_X_COUNT() bfin_read16(MDMA_S1_X_COUNT)
+#define bfin_write_MDMA_S1_X_COUNT(val) bfin_write16(MDMA_S1_X_COUNT, val)
+#define bfin_read_MDMA_S1_Y_COUNT() bfin_read16(MDMA_S1_Y_COUNT)
+#define bfin_write_MDMA_S1_Y_COUNT(val) bfin_write16(MDMA_S1_Y_COUNT, val)
+#define bfin_read_MDMA_S1_X_MODIFY() bfin_read16(MDMA_S1_X_MODIFY)
+#define bfin_write_MDMA_S1_X_MODIFY(val) bfin_write16(MDMA_S1_X_MODIFY, val)
+#define bfin_read_MDMA_S1_Y_MODIFY() bfin_read16(MDMA_S1_Y_MODIFY)
+#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write16(MDMA_S1_Y_MODIFY, val)
+#define bfin_read_MDMA_S1_CURR_DESC_PTR() bfin_read32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA_S1_CURR_ADDR() bfin_read32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val) bfin_write32(MDMA_S1_CURR_ADDR, val)
+#define bfin_read_MDMA_S1_CURR_X_COUNT() bfin_read16(MDMA_S1_CURR_X_COUNT)
+#define bfin_write_MDMA_S1_CURR_X_COUNT(val) bfin_write16(MDMA_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA_S1_CURR_Y_COUNT() bfin_read16(MDMA_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA_S1_CURR_Y_COUNT(val) bfin_write16(MDMA_S1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA_S1_IRQ_STATUS() bfin_read16(MDMA_S1_IRQ_STATUS)
+#define bfin_write_MDMA_S1_IRQ_STATUS(val) bfin_write16(MDMA_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA_S1_PERIPHERAL_MAP() bfin_read16(MDMA_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA_S1_PERIPHERAL_MAP, val)
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF) */
+#define bfin_read_PPI_CONTROL() bfin_read16(PPI_CONTROL)
+#define bfin_write_PPI_CONTROL(val) bfin_write16(PPI_CONTROL, val)
+#define bfin_read_PPI_STATUS() bfin_read16(PPI_STATUS)
+#define bfin_write_PPI_STATUS(val) bfin_write16(PPI_STATUS, val)
+#define bfin_read_PPI_DELAY() bfin_read16(PPI_DELAY)
+#define bfin_write_PPI_DELAY(val) bfin_write16(PPI_DELAY, val)
+#define bfin_read_PPI_COUNT() bfin_read16(PPI_COUNT)
+#define bfin_write_PPI_COUNT(val) bfin_write16(PPI_COUNT, val)
+#define bfin_read_PPI_FRAME() bfin_read16(PPI_FRAME)
+#define bfin_write_PPI_FRAME(val) bfin_write16(PPI_FRAME, val)
+
+
+/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF) */
+#define bfin_read_PORTGIO() bfin_read16(PORTGIO)
+#define bfin_write_PORTGIO(val) bfin_write16(PORTGIO, val)
+#define bfin_read_PORTGIO_CLEAR() bfin_read16(PORTGIO_CLEAR)
+#define bfin_write_PORTGIO_CLEAR(val) bfin_write16(PORTGIO_CLEAR, val)
+#define bfin_read_PORTGIO_SET() bfin_read16(PORTGIO_SET)
+#define bfin_write_PORTGIO_SET(val) bfin_write16(PORTGIO_SET, val)
+#define bfin_read_PORTGIO_TOGGLE() bfin_read16(PORTGIO_TOGGLE)
+#define bfin_write_PORTGIO_TOGGLE(val) bfin_write16(PORTGIO_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKA() bfin_read16(PORTGIO_MASKA)
+#define bfin_write_PORTGIO_MASKA(val) bfin_write16(PORTGIO_MASKA, val)
+#define bfin_read_PORTGIO_MASKA_CLEAR() bfin_read16(PORTGIO_MASKA_CLEAR)
+#define bfin_write_PORTGIO_MASKA_CLEAR(val) bfin_write16(PORTGIO_MASKA_CLEAR, val)
+#define bfin_read_PORTGIO_MASKA_SET() bfin_read16(PORTGIO_MASKA_SET)
+#define bfin_write_PORTGIO_MASKA_SET(val) bfin_write16(PORTGIO_MASKA_SET, val)
+#define bfin_read_PORTGIO_MASKA_TOGGLE() bfin_read16(PORTGIO_MASKA_TOGGLE)
+#define bfin_write_PORTGIO_MASKA_TOGGLE(val) bfin_write16(PORTGIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTGIO_MASKB() bfin_read16(PORTGIO_MASKB)
+#define bfin_write_PORTGIO_MASKB(val) bfin_write16(PORTGIO_MASKB, val)
+#define bfin_read_PORTGIO_MASKB_CLEAR() bfin_read16(PORTGIO_MASKB_CLEAR)
+#define bfin_write_PORTGIO_MASKB_CLEAR(val) bfin_write16(PORTGIO_MASKB_CLEAR, val)
+#define bfin_read_PORTGIO_MASKB_SET() bfin_read16(PORTGIO_MASKB_SET)
+#define bfin_write_PORTGIO_MASKB_SET(val) bfin_write16(PORTGIO_MASKB_SET, val)
+#define bfin_read_PORTGIO_MASKB_TOGGLE() bfin_read16(PORTGIO_MASKB_TOGGLE)
+#define bfin_write_PORTGIO_MASKB_TOGGLE(val) bfin_write16(PORTGIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTGIO_DIR() bfin_read16(PORTGIO_DIR)
+#define bfin_write_PORTGIO_DIR(val) bfin_write16(PORTGIO_DIR, val)
+#define bfin_read_PORTGIO_POLAR() bfin_read16(PORTGIO_POLAR)
+#define bfin_write_PORTGIO_POLAR(val) bfin_write16(PORTGIO_POLAR, val)
+#define bfin_read_PORTGIO_EDGE() bfin_read16(PORTGIO_EDGE)
+#define bfin_write_PORTGIO_EDGE(val) bfin_write16(PORTGIO_EDGE, val)
+#define bfin_read_PORTGIO_BOTH() bfin_read16(PORTGIO_BOTH)
+#define bfin_write_PORTGIO_BOTH(val) bfin_write16(PORTGIO_BOTH, val)
+#define bfin_read_PORTGIO_INEN() bfin_read16(PORTGIO_INEN)
+#define bfin_write_PORTGIO_INEN(val) bfin_write16(PORTGIO_INEN, val)
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF) */
+#define bfin_read_PORTHIO() bfin_read16(PORTHIO)
+#define bfin_write_PORTHIO(val) bfin_write16(PORTHIO, val)
+#define bfin_read_PORTHIO_CLEAR() bfin_read16(PORTHIO_CLEAR)
+#define bfin_write_PORTHIO_CLEAR(val) bfin_write16(PORTHIO_CLEAR, val)
+#define bfin_read_PORTHIO_SET() bfin_read16(PORTHIO_SET)
+#define bfin_write_PORTHIO_SET(val) bfin_write16(PORTHIO_SET, val)
+#define bfin_read_PORTHIO_TOGGLE() bfin_read16(PORTHIO_TOGGLE)
+#define bfin_write_PORTHIO_TOGGLE(val) bfin_write16(PORTHIO_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKA() bfin_read16(PORTHIO_MASKA)
+#define bfin_write_PORTHIO_MASKA(val) bfin_write16(PORTHIO_MASKA, val)
+#define bfin_read_PORTHIO_MASKA_CLEAR() bfin_read16(PORTHIO_MASKA_CLEAR)
+#define bfin_write_PORTHIO_MASKA_CLEAR(val) bfin_write16(PORTHIO_MASKA_CLEAR, val)
+#define bfin_read_PORTHIO_MASKA_SET() bfin_read16(PORTHIO_MASKA_SET)
+#define bfin_write_PORTHIO_MASKA_SET(val) bfin_write16(PORTHIO_MASKA_SET, val)
+#define bfin_read_PORTHIO_MASKA_TOGGLE() bfin_read16(PORTHIO_MASKA_TOGGLE)
+#define bfin_write_PORTHIO_MASKA_TOGGLE(val) bfin_write16(PORTHIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTHIO_MASKB() bfin_read16(PORTHIO_MASKB)
+#define bfin_write_PORTHIO_MASKB(val) bfin_write16(PORTHIO_MASKB, val)
+#define bfin_read_PORTHIO_MASKB_CLEAR() bfin_read16(PORTHIO_MASKB_CLEAR)
+#define bfin_write_PORTHIO_MASKB_CLEAR(val) bfin_write16(PORTHIO_MASKB_CLEAR, val)
+#define bfin_read_PORTHIO_MASKB_SET() bfin_read16(PORTHIO_MASKB_SET)
+#define bfin_write_PORTHIO_MASKB_SET(val) bfin_write16(PORTHIO_MASKB_SET, val)
+#define bfin_read_PORTHIO_MASKB_TOGGLE() bfin_read16(PORTHIO_MASKB_TOGGLE)
+#define bfin_write_PORTHIO_MASKB_TOGGLE(val) bfin_write16(PORTHIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTHIO_DIR() bfin_read16(PORTHIO_DIR)
+#define bfin_write_PORTHIO_DIR(val) bfin_write16(PORTHIO_DIR, val)
+#define bfin_read_PORTHIO_POLAR() bfin_read16(PORTHIO_POLAR)
+#define bfin_write_PORTHIO_POLAR(val) bfin_write16(PORTHIO_POLAR, val)
+#define bfin_read_PORTHIO_EDGE() bfin_read16(PORTHIO_EDGE)
+#define bfin_write_PORTHIO_EDGE(val) bfin_write16(PORTHIO_EDGE, val)
+#define bfin_read_PORTHIO_BOTH() bfin_read16(PORTHIO_BOTH)
+#define bfin_write_PORTHIO_BOTH(val) bfin_write16(PORTHIO_BOTH, val)
+#define bfin_read_PORTHIO_INEN() bfin_read16(PORTHIO_INEN)
+#define bfin_write_PORTHIO_INEN(val) bfin_write16(PORTHIO_INEN, val)
+
+
+/* UART1 Controller (0xFFC02000 - 0xFFC020FF) */
+#define bfin_read_UART1_THR() bfin_read16(UART1_THR)
+#define bfin_write_UART1_THR(val) bfin_write16(UART1_THR, val)
+#define bfin_read_UART1_RBR() bfin_read16(UART1_RBR)
+#define bfin_write_UART1_RBR(val) bfin_write16(UART1_RBR, val)
+#define bfin_read_UART1_DLL() bfin_read16(UART1_DLL)
+#define bfin_write_UART1_DLL(val) bfin_write16(UART1_DLL, val)
+#define bfin_read_UART1_IER() bfin_read16(UART1_IER)
+#define bfin_write_UART1_IER(val) bfin_write16(UART1_IER, val)
+#define bfin_read_UART1_DLH() bfin_read16(UART1_DLH)
+#define bfin_write_UART1_DLH(val) bfin_write16(UART1_DLH, val)
+#define bfin_read_UART1_IIR() bfin_read16(UART1_IIR)
+#define bfin_write_UART1_IIR(val) bfin_write16(UART1_IIR, val)
+#define bfin_read_UART1_LCR() bfin_read16(UART1_LCR)
+#define bfin_write_UART1_LCR(val) bfin_write16(UART1_LCR, val)
+#define bfin_read_UART1_MCR() bfin_read16(UART1_MCR)
+#define bfin_write_UART1_MCR(val) bfin_write16(UART1_MCR, val)
+#define bfin_read_UART1_LSR() bfin_read16(UART1_LSR)
+#define bfin_write_UART1_LSR(val) bfin_write16(UART1_LSR, val)
+#define bfin_read_UART1_MSR() bfin_read16(UART1_MSR)
+#define bfin_write_UART1_MSR(val) bfin_write16(UART1_MSR, val)
+#define bfin_read_UART1_SCR() bfin_read16(UART1_SCR)
+#define bfin_write_UART1_SCR(val) bfin_write16(UART1_SCR, val)
+#define bfin_read_UART1_GCTL() bfin_read16(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val) bfin_write16(UART1_GCTL, val)
+
+/* Omit CAN register sets from the cdefBF534.h (CAN is not in the ADSP-BF51x processor) */
+
+/* Pin Control Registers (0xFFC03200 - 0xFFC032FF) */
+#define bfin_read_PORTF_FER() bfin_read16(PORTF_FER)
+#define bfin_write_PORTF_FER(val) bfin_write16(PORTF_FER, val)
+#define bfin_read_PORTG_FER() bfin_read16(PORTG_FER)
+#define bfin_write_PORTG_FER(val) bfin_write16(PORTG_FER, val)
+#define bfin_read_PORTH_FER() bfin_read16(PORTH_FER)
+#define bfin_write_PORTH_FER(val) bfin_write16(PORTH_FER, val)
+#define bfin_read_PORT_MUX() bfin_read16(PORT_MUX)
+#define bfin_write_PORT_MUX(val) bfin_write16(PORT_MUX, val)
+
+
+/* Handshake MDMA Registers (0xFFC03300 - 0xFFC033FF) */
+#define bfin_read_HMDMA0_CONTROL() bfin_read16(HMDMA0_CONTROL)
+#define bfin_write_HMDMA0_CONTROL(val) bfin_write16(HMDMA0_CONTROL, val)
+#define bfin_read_HMDMA0_ECINIT() bfin_read16(HMDMA0_ECINIT)
+#define bfin_write_HMDMA0_ECINIT(val) bfin_write16(HMDMA0_ECINIT, val)
+#define bfin_read_HMDMA0_BCINIT() bfin_read16(HMDMA0_BCINIT)
+#define bfin_write_HMDMA0_BCINIT(val) bfin_write16(HMDMA0_BCINIT, val)
+#define bfin_read_HMDMA0_ECURGENT() bfin_read16(HMDMA0_ECURGENT)
+#define bfin_write_HMDMA0_ECURGENT(val) bfin_write16(HMDMA0_ECURGENT, val)
+#define bfin_read_HMDMA0_ECOVERFLOW() bfin_read16(HMDMA0_ECOVERFLOW)
+#define bfin_write_HMDMA0_ECOVERFLOW(val) bfin_write16(HMDMA0_ECOVERFLOW, val)
+#define bfin_read_HMDMA0_ECOUNT() bfin_read16(HMDMA0_ECOUNT)
+#define bfin_write_HMDMA0_ECOUNT(val) bfin_write16(HMDMA0_ECOUNT, val)
+#define bfin_read_HMDMA0_BCOUNT() bfin_read16(HMDMA0_BCOUNT)
+#define bfin_write_HMDMA0_BCOUNT(val) bfin_write16(HMDMA0_BCOUNT, val)
+
+#define bfin_read_HMDMA1_CONTROL() bfin_read16(HMDMA1_CONTROL)
+#define bfin_write_HMDMA1_CONTROL(val) bfin_write16(HMDMA1_CONTROL, val)
+#define bfin_read_HMDMA1_ECINIT() bfin_read16(HMDMA1_ECINIT)
+#define bfin_write_HMDMA1_ECINIT(val) bfin_write16(HMDMA1_ECINIT, val)
+#define bfin_read_HMDMA1_BCINIT() bfin_read16(HMDMA1_BCINIT)
+#define bfin_write_HMDMA1_BCINIT(val) bfin_write16(HMDMA1_BCINIT, val)
+#define bfin_read_HMDMA1_ECURGENT() bfin_read16(HMDMA1_ECURGENT)
+#define bfin_write_HMDMA1_ECURGENT(val) bfin_write16(HMDMA1_ECURGENT, val)
+#define bfin_read_HMDMA1_ECOVERFLOW() bfin_read16(HMDMA1_ECOVERFLOW)
+#define bfin_write_HMDMA1_ECOVERFLOW(val) bfin_write16(HMDMA1_ECOVERFLOW, val)
+#define bfin_read_HMDMA1_ECOUNT() bfin_read16(HMDMA1_ECOUNT)
+#define bfin_write_HMDMA1_ECOUNT(val) bfin_write16(HMDMA1_ECOUNT, val)
+#define bfin_read_HMDMA1_BCOUNT() bfin_read16(HMDMA1_BCOUNT)
+#define bfin_write_HMDMA1_BCOUNT(val) bfin_write16(HMDMA1_BCOUNT, val)
+
+/* ==== end from cdefBF534.h ==== */
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+
+#define bfin_read_PORTF_MUX() bfin_read16(PORTF_MUX)
+#define bfin_write_PORTF_MUX(val) bfin_write16(PORTF_MUX, val)
+#define bfin_read_PORTG_MUX() bfin_read16(PORTG_MUX)
+#define bfin_write_PORTG_MUX(val) bfin_write16(PORTG_MUX, val)
+#define bfin_read_PORTH_MUX() bfin_read16(PORTH_MUX)
+#define bfin_write_PORTH_MUX(val) bfin_write16(PORTH_MUX, val)
+
+#define bfin_read_PORTF_DRIVE() bfin_read16(PORTF_DRIVE)
+#define bfin_write_PORTF_DRIVE(val) bfin_write16(PORTF_DRIVE, val)
+#define bfin_read_PORTG_DRIVE() bfin_read16(PORTG_DRIVE)
+#define bfin_write_PORTG_DRIVE(val) bfin_write16(PORTG_DRIVE, val)
+#define bfin_read_PORTH_DRIVE() bfin_read16(PORTH_DRIVE)
+#define bfin_write_PORTH_DRIVE(val) bfin_write16(PORTH_DRIVE, val)
+#define bfin_read_PORTF_SLEW() bfin_read16(PORTF_SLEW)
+#define bfin_write_PORTF_SLEW(val) bfin_write16(PORTF_SLEW, val)
+#define bfin_read_PORTG_SLEW() bfin_read16(PORTG_SLEW)
+#define bfin_write_PORTG_SLEW(val) bfin_write16(PORTG_SLEW, val)
+#define bfin_read_PORTH_SLEW() bfin_read16(PORTH_SLEW)
+#define bfin_write_PORTH_SLEW(val) bfin_write16(PORTH_SLEW, val)
+#define bfin_read_PORTF_HYSTERISIS() bfin_read16(PORTF_HYSTERISIS)
+#define bfin_write_PORTF_HYSTERISIS(val) bfin_write16(PORTF_HYSTERISIS, val)
+#define bfin_read_PORTG_HYSTERISIS() bfin_read16(PORTG_HYSTERISIS)
+#define bfin_write_PORTG_HYSTERISIS(val) bfin_write16(PORTG_HYSTERISIS, val)
+#define bfin_read_PORTH_HYSTERISIS() bfin_read16(PORTH_HYSTERISIS)
+#define bfin_write_PORTH_HYSTERISIS(val) bfin_write16(PORTH_HYSTERISIS, val)
+#define bfin_read_MISCPORT_DRIVE() bfin_read16(MISCPORT_DRIVE)
+#define bfin_write_MISCPORT_DRIVE(val) bfin_write16(MISCPORT_DRIVE, val)
+#define bfin_read_MISCPORT_SLEW() bfin_read16(MISCPORT_SLEW)
+#define bfin_write_MISCPORT_SLEW(val) bfin_write16(MISCPORT_SLEW, val)
+#define bfin_read_MISCPORT_HYSTERISIS() bfin_read16(MISCPORT_HYSTERISIS)
+#define bfin_write_MISCPORT_HYSTERISIS(val) bfin_write16(MISCPORT_HYSTERISIS, val)
+
+/* HOST Port Registers */
+
+#define bfin_read_HOST_CONTROL() bfin_read16(HOST_CONTROL)
+#define bfin_write_HOST_CONTROL(val) bfin_write16(HOST_CONTROL, val)
+#define bfin_read_HOST_STATUS() bfin_read16(HOST_STATUS)
+#define bfin_write_HOST_STATUS(val) bfin_write16(HOST_STATUS, val)
+#define bfin_read_HOST_TIMEOUT() bfin_read16(HOST_TIMEOUT)
+#define bfin_write_HOST_TIMEOUT(val) bfin_write16(HOST_TIMEOUT, val)
+
+/* Counter Registers */
+
+#define bfin_read_CNT_CONFIG() bfin_read16(CNT_CONFIG)
+#define bfin_write_CNT_CONFIG(val) bfin_write16(CNT_CONFIG, val)
+#define bfin_read_CNT_IMASK() bfin_read16(CNT_IMASK)
+#define bfin_write_CNT_IMASK(val) bfin_write16(CNT_IMASK, val)
+#define bfin_read_CNT_STATUS() bfin_read16(CNT_STATUS)
+#define bfin_write_CNT_STATUS(val) bfin_write16(CNT_STATUS, val)
+#define bfin_read_CNT_COMMAND() bfin_read16(CNT_COMMAND)
+#define bfin_write_CNT_COMMAND(val) bfin_write16(CNT_COMMAND, val)
+#define bfin_read_CNT_DEBOUNCE() bfin_read16(CNT_DEBOUNCE)
+#define bfin_write_CNT_DEBOUNCE(val) bfin_write16(CNT_DEBOUNCE, val)
+#define bfin_read_CNT_COUNTER() bfin_read32(CNT_COUNTER)
+#define bfin_write_CNT_COUNTER(val) bfin_write32(CNT_COUNTER, val)
+#define bfin_read_CNT_MAX() bfin_read32(CNT_MAX)
+#define bfin_write_CNT_MAX(val) bfin_write32(CNT_MAX, val)
+#define bfin_read_CNT_MIN() bfin_read32(CNT_MIN)
+#define bfin_write_CNT_MIN(val) bfin_write32(CNT_MIN, val)
+
+/* OTP/FUSE Registers */
+
+#define bfin_read_OTP_CONTROL() bfin_read16(OTP_CONTROL)
+#define bfin_write_OTP_CONTROL(val) bfin_write16(OTP_CONTROL, val)
+#define bfin_read_OTP_BEN() bfin_read16(OTP_BEN)
+#define bfin_write_OTP_BEN(val) bfin_write16(OTP_BEN, val)
+#define bfin_read_OTP_STATUS() bfin_read16(OTP_STATUS)
+#define bfin_write_OTP_STATUS(val) bfin_write16(OTP_STATUS, val)
+#define bfin_read_OTP_TIMING() bfin_read32(OTP_TIMING)
+#define bfin_write_OTP_TIMING(val) bfin_write32(OTP_TIMING, val)
+
+/* Security Registers */
+
+#define bfin_read_SECURE_SYSSWT() bfin_read32(SECURE_SYSSWT)
+#define bfin_write_SECURE_SYSSWT(val) bfin_write32(SECURE_SYSSWT, val)
+#define bfin_read_SECURE_CONTROL() bfin_read16(SECURE_CONTROL)
+#define bfin_write_SECURE_CONTROL(val) bfin_write16(SECURE_CONTROL, val)
+#define bfin_read_SECURE_STATUS() bfin_read16(SECURE_STATUS)
+#define bfin_write_SECURE_STATUS(val) bfin_write16(SECURE_STATUS, val)
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define bfin_read_OTP_DATA0() bfin_read32(OTP_DATA0)
+#define bfin_write_OTP_DATA0(val) bfin_write32(OTP_DATA0, val)
+#define bfin_read_OTP_DATA1() bfin_read32(OTP_DATA1)
+#define bfin_write_OTP_DATA1(val) bfin_write32(OTP_DATA1, val)
+#define bfin_read_OTP_DATA2() bfin_read32(OTP_DATA2)
+#define bfin_write_OTP_DATA2(val) bfin_write32(OTP_DATA2, val)
+#define bfin_read_OTP_DATA3() bfin_read32(OTP_DATA3)
+#define bfin_write_OTP_DATA3(val) bfin_write32(OTP_DATA3, val)
+
+/* NFC Registers */
+
+#define bfin_read_NFC_CTL() bfin_read16(NFC_CTL)
+#define bfin_write_NFC_CTL(val) bfin_write16(NFC_CTL, val)
+#define bfin_read_NFC_STAT() bfin_read16(NFC_STAT)
+#define bfin_write_NFC_STAT(val) bfin_write16(NFC_STAT, val)
+#define bfin_read_NFC_IRQSTAT() bfin_read16(NFC_IRQSTAT)
+#define bfin_write_NFC_IRQSTAT(val) bfin_write16(NFC_IRQSTAT, val)
+#define bfin_read_NFC_IRQMASK() bfin_read16(NFC_IRQMASK)
+#define bfin_write_NFC_IRQMASK(val) bfin_write16(NFC_IRQMASK, val)
+#define bfin_read_NFC_ECC0() bfin_read16(NFC_ECC0)
+#define bfin_write_NFC_ECC0(val) bfin_write16(NFC_ECC0, val)
+#define bfin_read_NFC_ECC1() bfin_read16(NFC_ECC1)
+#define bfin_write_NFC_ECC1(val) bfin_write16(NFC_ECC1, val)
+#define bfin_read_NFC_ECC2() bfin_read16(NFC_ECC2)
+#define bfin_write_NFC_ECC2(val) bfin_write16(NFC_ECC2, val)
+#define bfin_read_NFC_ECC3() bfin_read16(NFC_ECC3)
+#define bfin_write_NFC_ECC3(val) bfin_write16(NFC_ECC3, val)
+#define bfin_read_NFC_COUNT() bfin_read16(NFC_COUNT)
+#define bfin_write_NFC_COUNT(val) bfin_write16(NFC_COUNT, val)
+#define bfin_read_NFC_RST() bfin_read16(NFC_RST)
+#define bfin_write_NFC_RST(val) bfin_write16(NFC_RST, val)
+#define bfin_read_NFC_PGCTL() bfin_read16(NFC_PGCTL)
+#define bfin_write_NFC_PGCTL(val) bfin_write16(NFC_PGCTL, val)
+#define bfin_read_NFC_READ() bfin_read16(NFC_READ)
+#define bfin_write_NFC_READ(val) bfin_write16(NFC_READ, val)
+#define bfin_read_NFC_ADDR() bfin_read16(NFC_ADDR)
+#define bfin_write_NFC_ADDR(val) bfin_write16(NFC_ADDR, val)
+#define bfin_read_NFC_CMD() bfin_read16(NFC_CMD)
+#define bfin_write_NFC_CMD(val) bfin_write16(NFC_CMD, val)
+#define bfin_read_NFC_DATA_WR() bfin_read16(NFC_DATA_WR)
+#define bfin_write_NFC_DATA_WR(val) bfin_write16(NFC_DATA_WR, val)
+#define bfin_read_NFC_DATA_RD() bfin_read16(NFC_DATA_RD)
+#define bfin_write_NFC_DATA_RD(val) bfin_write16(NFC_DATA_RD, val)
+
+/* These need to be last due to the cdef/linux inter-dependencies */
+#include <asm/irq.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
+#endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF512.h b/arch/blackfin/mach-bf518/include/mach/defBF512.h
new file mode 100644
index 000000000000..a96ca90154dd
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/defBF512.h
@@ -0,0 +1,42 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/defBF512.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF512_H
+#define _DEF_BF512_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF512 */
+
+/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "defBF51x_base.h"
+
+#endif /* _DEF_BF512_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF514.h b/arch/blackfin/mach-bf518/include/mach/defBF514.h
new file mode 100644
index 000000000000..543f2913b3f5
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/defBF514.h
@@ -0,0 +1,113 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/defBF514.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF514_H
+#define _DEF_BF514_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF514 */
+
+/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "defBF51x_base.h"
+
+/* The following are the #defines needed by ADSP-BF514 that are not in the common header */
+
+/* SDH Registers */
+
+#define SDH_PWR_CTL 0xFFC03900 /* SDH Power Control */
+#define SDH_CLK_CTL 0xFFC03904 /* SDH Clock Control */
+#define SDH_ARGUMENT 0xFFC03908 /* SDH Argument */
+#define SDH_COMMAND 0xFFC0390C /* SDH Command */
+#define SDH_RESP_CMD 0xFFC03910 /* SDH Response Command */
+#define SDH_RESPONSE0 0xFFC03914 /* SDH Response0 */
+#define SDH_RESPONSE1 0xFFC03918 /* SDH Response1 */
+#define SDH_RESPONSE2 0xFFC0391C /* SDH Response2 */
+#define SDH_RESPONSE3 0xFFC03920 /* SDH Response3 */
+#define SDH_DATA_TIMER 0xFFC03924 /* SDH Data Timer */
+#define SDH_DATA_LGTH 0xFFC03928 /* SDH Data Length */
+#define SDH_DATA_CTL 0xFFC0392C /* SDH Data Control */
+#define SDH_DATA_CNT 0xFFC03930 /* SDH Data Counter */
+#define SDH_STATUS 0xFFC03934 /* SDH Status */
+#define SDH_STATUS_CLR 0xFFC03938 /* SDH Status Clear */
+#define SDH_MASK0 0xFFC0393C /* SDH Interrupt0 Mask */
+#define SDH_MASK1 0xFFC03940 /* SDH Interrupt1 Mask */
+#define SDH_FIFO_CNT 0xFFC03948 /* SDH FIFO Counter */
+#define SDH_FIFO 0xFFC03980 /* SDH Data FIFO */
+#define SDH_E_STATUS 0xFFC039C0 /* SDH Exception Status */
+#define SDH_E_MASK 0xFFC039C4 /* SDH Exception Mask */
+#define SDH_CFG 0xFFC039C8 /* SDH Configuration */
+#define SDH_RD_WAIT_EN 0xFFC039CC /* SDH Read Wait Enable */
+#define SDH_PID0 0xFFC039D0 /* SDH Peripheral Identification0 */
+#define SDH_PID1 0xFFC039D4 /* SDH Peripheral Identification1 */
+#define SDH_PID2 0xFFC039D8 /* SDH Peripheral Identification2 */
+#define SDH_PID3 0xFFC039DC /* SDH Peripheral Identification3 */
+#define SDH_PID4 0xFFC039E0 /* SDH Peripheral Identification4 */
+#define SDH_PID5 0xFFC039E4 /* SDH Peripheral Identification5 */
+#define SDH_PID6 0xFFC039E8 /* SDH Peripheral Identification6 */
+#define SDH_PID7 0xFFC039EC /* SDH Peripheral Identification7 */
+
+/* Removable Storage Interface Registers */
+
+#define RSI_PWR_CONTROL 0xFFC03800 /* RSI Power Control Register */
+#define RSI_CLK_CONTROL 0xFFC03804 /* RSI Clock Control Register */
+#define RSI_ARGUMENT 0xFFC03808 /* RSI Argument Register */
+#define RSI_COMMAND 0xFFC0380C /* RSI Command Register */
+#define RSI_RESP_CMD 0xFFC03810 /* RSI Response Command Register */
+#define RSI_RESPONSE0 0xFFC03814 /* RSI Response Register */
+#define RSI_RESPONSE1 0xFFC03818 /* RSI Response Register */
+#define RSI_RESPONSE2 0xFFC0381C /* RSI Response Register */
+#define RSI_RESPONSE3 0xFFC03820 /* RSI Response Register */
+#define RSI_DATA_TIMER 0xFFC03824 /* RSI Data Timer Register */
+#define RSI_DATA_LGTH 0xFFC03828 /* RSI Data Length Register */
+#define RSI_DATA_CONTROL 0xFFC0382C /* RSI Data Control Register */
+#define RSI_DATA_CNT 0xFFC03830 /* RSI Data Counter Register */
+#define RSI_STATUS 0xFFC03834 /* RSI Status Register */
+#define RSI_STATUSCL 0xFFC03838 /* RSI Status Clear Register */
+#define RSI_MASK0 0xFFC0383C /* RSI Interrupt 0 Mask Register */
+#define RSI_MASK1 0xFFC03840 /* RSI Interrupt 1 Mask Register */
+#define RSI_FIFO_CNT 0xFFC03848 /* RSI FIFO Counter Register */
+#define RSI_CEATA_CONTROL 0xFFC0384C /* RSI CEATA Register */
+#define RSI_FIFO 0xFFC03880 /* RSI Data FIFO Register */
+#define RSI_ESTAT 0xFFC038C0 /* RSI Exception Status Register */
+#define RSI_EMASK 0xFFC038C4 /* RSI Exception Mask Register */
+#define RSI_CONFIG 0xFFC038C8 /* RSI Configuration Register */
+#define RSI_RD_WAIT_EN 0xFFC038CC /* RSI Read Wait Enable Register */
+#define RSI_PID0 0xFFC03FE0 /* RSI Peripheral ID Register 0 */
+#define RSI_PID1 0xFFC03FE4 /* RSI Peripheral ID Register 1 */
+#define RSI_PID2 0xFFC03FE8 /* RSI Peripheral ID Register 2 */
+#define RSI_PID3 0xFFC03FEC /* RSI Peripheral ID Register 3 */
+#define RSI_PID4 0xFFC03FF0 /* RSI Peripheral ID Register 4 */
+#define RSI_PID5 0xFFC03FF4 /* RSI Peripheral ID Register 5 */
+#define RSI_PID6 0xFFC03FF8 /* RSI Peripheral ID Register 6 */
+#define RSI_PID7 0xFFC03FFC /* RSI Peripheral ID Register 7 */
+
+#endif /* _DEF_BF514_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF516.h b/arch/blackfin/mach-bf518/include/mach/defBF516.h
new file mode 100644
index 000000000000..149a269306c5
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/defBF516.h
@@ -0,0 +1,490 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/defBF516.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF516_H
+#define _DEF_BF516_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF516 */
+
+/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "defBF51x_base.h"
+
+/* The following are the #defines needed by ADSP-BF516 that are not in the common header */
+/* 10/100 Ethernet Controller (0xFFC03000 - 0xFFC031FF) */
+
+#define EMAC_OPMODE 0xFFC03000 /* Operating Mode Register */
+#define EMAC_ADDRLO 0xFFC03004 /* Address Low (32 LSBs) Register */
+#define EMAC_ADDRHI 0xFFC03008 /* Address High (16 MSBs) Register */
+#define EMAC_HASHLO 0xFFC0300C /* Multicast Hash Table Low (Bins 31-0) Register */
+#define EMAC_HASHHI 0xFFC03010 /* Multicast Hash Table High (Bins 63-32) Register */
+#define EMAC_STAADD 0xFFC03014 /* Station Management Address Register */
+#define EMAC_STADAT 0xFFC03018 /* Station Management Data Register */
+#define EMAC_FLC 0xFFC0301C /* Flow Control Register */
+#define EMAC_VLAN1 0xFFC03020 /* VLAN1 Tag Register */
+#define EMAC_VLAN2 0xFFC03024 /* VLAN2 Tag Register */
+#define EMAC_WKUP_CTL 0xFFC0302C /* Wake-Up Control/Status Register */
+#define EMAC_WKUP_FFMSK0 0xFFC03030 /* Wake-Up Frame Filter 0 Byte Mask Register */
+#define EMAC_WKUP_FFMSK1 0xFFC03034 /* Wake-Up Frame Filter 1 Byte Mask Register */
+#define EMAC_WKUP_FFMSK2 0xFFC03038 /* Wake-Up Frame Filter 2 Byte Mask Register */
+#define EMAC_WKUP_FFMSK3 0xFFC0303C /* Wake-Up Frame Filter 3 Byte Mask Register */
+#define EMAC_WKUP_FFCMD 0xFFC03040 /* Wake-Up Frame Filter Commands Register */
+#define EMAC_WKUP_FFOFF 0xFFC03044 /* Wake-Up Frame Filter Offsets Register */
+#define EMAC_WKUP_FFCRC0 0xFFC03048 /* Wake-Up Frame Filter 0,1 CRC-16 Register */
+#define EMAC_WKUP_FFCRC1 0xFFC0304C /* Wake-Up Frame Filter 2,3 CRC-16 Register */
+
+#define EMAC_SYSCTL 0xFFC03060 /* EMAC System Control Register */
+#define EMAC_SYSTAT 0xFFC03064 /* EMAC System Status Register */
+#define EMAC_RX_STAT 0xFFC03068 /* RX Current Frame Status Register */
+#define EMAC_RX_STKY 0xFFC0306C /* RX Sticky Frame Status Register */
+#define EMAC_RX_IRQE 0xFFC03070 /* RX Frame Status Interrupt Enables Register */
+#define EMAC_TX_STAT 0xFFC03074 /* TX Current Frame Status Register */
+#define EMAC_TX_STKY 0xFFC03078 /* TX Sticky Frame Status Register */
+#define EMAC_TX_IRQE 0xFFC0307C /* TX Frame Status Interrupt Enables Register */
+
+#define EMAC_MMC_CTL 0xFFC03080 /* MMC Counter Control Register */
+#define EMAC_MMC_RIRQS 0xFFC03084 /* MMC RX Interrupt Status Register */
+#define EMAC_MMC_RIRQE 0xFFC03088 /* MMC RX Interrupt Enables Register */
+#define EMAC_MMC_TIRQS 0xFFC0308C /* MMC TX Interrupt Status Register */
+#define EMAC_MMC_TIRQE 0xFFC03090 /* MMC TX Interrupt Enables Register */
+
+#define EMAC_RXC_OK 0xFFC03100 /* RX Frame Successful Count */
+#define EMAC_RXC_FCS 0xFFC03104 /* RX Frame FCS Failure Count */
+#define EMAC_RXC_ALIGN 0xFFC03108 /* RX Alignment Error Count */
+#define EMAC_RXC_OCTET 0xFFC0310C /* RX Octets Successfully Received Count */
+#define EMAC_RXC_DMAOVF 0xFFC03110 /* Internal MAC Sublayer Error RX Frame Count */
+#define EMAC_RXC_UNICST 0xFFC03114 /* Unicast RX Frame Count */
+#define EMAC_RXC_MULTI 0xFFC03118 /* Multicast RX Frame Count */
+#define EMAC_RXC_BROAD 0xFFC0311C /* Broadcast RX Frame Count */
+#define EMAC_RXC_LNERRI 0xFFC03120 /* RX Frame In Range Error Count */
+#define EMAC_RXC_LNERRO 0xFFC03124 /* RX Frame Out Of Range Error Count */
+#define EMAC_RXC_LONG 0xFFC03128 /* RX Frame Too Long Count */
+#define EMAC_RXC_MACCTL 0xFFC0312C /* MAC Control RX Frame Count */
+#define EMAC_RXC_OPCODE 0xFFC03130 /* Unsupported Op-Code RX Frame Count */
+#define EMAC_RXC_PAUSE 0xFFC03134 /* MAC Control Pause RX Frame Count */
+#define EMAC_RXC_ALLFRM 0xFFC03138 /* Overall RX Frame Count */
+#define EMAC_RXC_ALLOCT 0xFFC0313C /* Overall RX Octet Count */
+#define EMAC_RXC_TYPED 0xFFC03140 /* Type/Length Consistent RX Frame Count */
+#define EMAC_RXC_SHORT 0xFFC03144 /* RX Frame Fragment Count - Byte Count x < 64 */
+#define EMAC_RXC_EQ64 0xFFC03148 /* Good RX Frame Count - Byte Count x = 64 */
+#define EMAC_RXC_LT128 0xFFC0314C /* Good RX Frame Count - Byte Count 64 < x < 128 */
+#define EMAC_RXC_LT256 0xFFC03150 /* Good RX Frame Count - Byte Count 128 <= x < 256 */
+#define EMAC_RXC_LT512 0xFFC03154 /* Good RX Frame Count - Byte Count 256 <= x < 512 */
+#define EMAC_RXC_LT1024 0xFFC03158 /* Good RX Frame Count - Byte Count 512 <= x < 1024 */
+#define EMAC_RXC_GE1024 0xFFC0315C /* Good RX Frame Count - Byte Count x >= 1024 */
+
+#define EMAC_TXC_OK 0xFFC03180 /* TX Frame Successful Count */
+#define EMAC_TXC_1COL 0xFFC03184 /* TX Frames Successful After Single Collision Count */
+#define EMAC_TXC_GT1COL 0xFFC03188 /* TX Frames Successful After Multiple Collisions Count */
+#define EMAC_TXC_OCTET 0xFFC0318C /* TX Octets Successfully Received Count */
+#define EMAC_TXC_DEFER 0xFFC03190 /* TX Frame Delayed Due To Busy Count */
+#define EMAC_TXC_LATECL 0xFFC03194 /* Late TX Collisions Count */
+#define EMAC_TXC_XS_COL 0xFFC03198 /* TX Frame Failed Due To Excessive Collisions Count */
+#define EMAC_TXC_DMAUND 0xFFC0319C /* Internal MAC Sublayer Error TX Frame Count */
+#define EMAC_TXC_CRSERR 0xFFC031A0 /* Carrier Sense Deasserted During TX Frame Count */
+#define EMAC_TXC_UNICST 0xFFC031A4 /* Unicast TX Frame Count */
+#define EMAC_TXC_MULTI 0xFFC031A8 /* Multicast TX Frame Count */
+#define EMAC_TXC_BROAD 0xFFC031AC /* Broadcast TX Frame Count */
+#define EMAC_TXC_XS_DFR 0xFFC031B0 /* TX Frames With Excessive Deferral Count */
+#define EMAC_TXC_MACCTL 0xFFC031B4 /* MAC Control TX Frame Count */
+#define EMAC_TXC_ALLFRM 0xFFC031B8 /* Overall TX Frame Count */
+#define EMAC_TXC_ALLOCT 0xFFC031BC /* Overall TX Octet Count */
+#define EMAC_TXC_EQ64 0xFFC031C0 /* Good TX Frame Count - Byte Count x = 64 */
+#define EMAC_TXC_LT128 0xFFC031C4 /* Good TX Frame Count - Byte Count 64 < x < 128 */
+#define EMAC_TXC_LT256 0xFFC031C8 /* Good TX Frame Count - Byte Count 128 <= x < 256 */
+#define EMAC_TXC_LT512 0xFFC031CC /* Good TX Frame Count - Byte Count 256 <= x < 512 */
+#define EMAC_TXC_LT1024 0xFFC031D0 /* Good TX Frame Count - Byte Count 512 <= x < 1024 */
+#define EMAC_TXC_GE1024 0xFFC031D4 /* Good TX Frame Count - Byte Count x >= 1024 */
+#define EMAC_TXC_ABORT 0xFFC031D8 /* Total TX Frames Aborted Count */
+
+/* Listing for IEEE-Supported Count Registers */
+
+#define FramesReceivedOK EMAC_RXC_OK /* RX Frame Successful Count */
+#define FrameCheckSequenceErrors EMAC_RXC_FCS /* RX Frame FCS Failure Count */
+#define AlignmentErrors EMAC_RXC_ALIGN /* RX Alignment Error Count */
+#define OctetsReceivedOK EMAC_RXC_OCTET /* RX Octets Successfully Received Count */
+#define FramesLostDueToIntMACRcvError EMAC_RXC_DMAOVF /* Internal MAC Sublayer Error RX Frame Count */
+#define UnicastFramesReceivedOK EMAC_RXC_UNICST /* Unicast RX Frame Count */
+#define MulticastFramesReceivedOK EMAC_RXC_MULTI /* Multicast RX Frame Count */
+#define BroadcastFramesReceivedOK EMAC_RXC_BROAD /* Broadcast RX Frame Count */
+#define InRangeLengthErrors EMAC_RXC_LNERRI /* RX Frame In Range Error Count */
+#define OutOfRangeLengthField EMAC_RXC_LNERRO /* RX Frame Out Of Range Error Count */
+#define FrameTooLongErrors EMAC_RXC_LONG /* RX Frame Too Long Count */
+#define MACControlFramesReceived EMAC_RXC_MACCTL /* MAC Control RX Frame Count */
+#define UnsupportedOpcodesReceived EMAC_RXC_OPCODE /* Unsupported Op-Code RX Frame Count */
+#define PAUSEMACCtrlFramesReceived EMAC_RXC_PAUSE /* MAC Control Pause RX Frame Count */
+#define FramesReceivedAll EMAC_RXC_ALLFRM /* Overall RX Frame Count */
+#define OctetsReceivedAll EMAC_RXC_ALLOCT /* Overall RX Octet Count */
+#define TypedFramesReceived EMAC_RXC_TYPED /* Type/Length Consistent RX Frame Count */
+#define FramesLenLt64Received EMAC_RXC_SHORT /* RX Frame Fragment Count - Byte Count x < 64 */
+#define FramesLenEq64Received EMAC_RXC_EQ64 /* Good RX Frame Count - Byte Count x = 64 */
+#define FramesLen65_127Received EMAC_RXC_LT128 /* Good RX Frame Count - Byte Count 64 < x < 128 */
+#define FramesLen128_255Received EMAC_RXC_LT256 /* Good RX Frame Count - Byte Count 128 <= x < 256 */
+#define FramesLen256_511Received EMAC_RXC_LT512 /* Good RX Frame Count - Byte Count 256 <= x < 512 */
+#define FramesLen512_1023Received EMAC_RXC_LT1024 /* Good RX Frame Count - Byte Count 512 <= x < 1024 */
+#define FramesLen1024_MaxReceived EMAC_RXC_GE1024 /* Good RX Frame Count - Byte Count x >= 1024 */
+
+#define FramesTransmittedOK EMAC_TXC_OK /* TX Frame Successful Count */
+#define SingleCollisionFrames EMAC_TXC_1COL /* TX Frames Successful After Single Collision Count */
+#define MultipleCollisionFrames EMAC_TXC_GT1COL /* TX Frames Successful After Multiple Collisions Count */
+#define OctetsTransmittedOK EMAC_TXC_OCTET /* TX Octets Successfully Received Count */
+#define FramesWithDeferredXmissions EMAC_TXC_DEFER /* TX Frame Delayed Due To Busy Count */
+#define LateCollisions EMAC_TXC_LATECL /* Late TX Collisions Count */
+#define FramesAbortedDueToXSColls EMAC_TXC_XS_COL /* TX Frame Failed Due To Excessive Collisions Count */
+#define FramesLostDueToIntMacXmitError EMAC_TXC_DMAUND /* Internal MAC Sublayer Error TX Frame Count */
+#define CarrierSenseErrors EMAC_TXC_CRSERR /* Carrier Sense Deasserted During TX Frame Count */
+#define UnicastFramesXmittedOK EMAC_TXC_UNICST /* Unicast TX Frame Count */
+#define MulticastFramesXmittedOK EMAC_TXC_MULTI /* Multicast TX Frame Count */
+#define BroadcastFramesXmittedOK EMAC_TXC_BROAD /* Broadcast TX Frame Count */
+#define FramesWithExcessiveDeferral EMAC_TXC_XS_DFR /* TX Frames With Excessive Deferral Count */
+#define MACControlFramesTransmitted EMAC_TXC_MACCTL /* MAC Control TX Frame Count */
+#define FramesTransmittedAll EMAC_TXC_ALLFRM /* Overall TX Frame Count */
+#define OctetsTransmittedAll EMAC_TXC_ALLOCT /* Overall TX Octet Count */
+#define FramesLenEq64Transmitted EMAC_TXC_EQ64 /* Good TX Frame Count - Byte Count x = 64 */
+#define FramesLen65_127Transmitted EMAC_TXC_LT128 /* Good TX Frame Count - Byte Count 64 < x < 128 */
+#define FramesLen128_255Transmitted EMAC_TXC_LT256 /* Good TX Frame Count - Byte Count 128 <= x < 256 */
+#define FramesLen256_511Transmitted EMAC_TXC_LT512 /* Good TX Frame Count - Byte Count 256 <= x < 512 */
+#define FramesLen512_1023Transmitted EMAC_TXC_LT1024 /* Good TX Frame Count - Byte Count 512 <= x < 1024 */
+#define FramesLen1024_MaxTransmitted EMAC_TXC_GE1024 /* Good TX Frame Count - Byte Count x >= 1024 */
+#define TxAbortedFrames EMAC_TXC_ABORT /* Total TX Frames Aborted Count */
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer: All macros are intended to make C and Assembly code more readable.
+** Use these macros carefully, as any that do left shifts for field
+** depositing will result in the lower order bits being destroyed. Any
+** macro that shifts left to properly position the bit-field should be
+** used as part of an OR to initialize a register and NOT as a dynamic
+** modifier UNLESS the lower order bits are saved and ORed back in when
+** the macro is used.
+*************************************************************************************/
+
+/************************ ETHERNET 10/100 CONTROLLER MASKS ************************/
+
+/* EMAC_OPMODE Masks */
+
+#define RE 0x00000001 /* Receiver Enable */
+#define ASTP 0x00000002 /* Enable Automatic Pad Stripping On RX Frames */
+#define HU 0x00000010 /* Hash Filter Unicast Address */
+#define HM 0x00000020 /* Hash Filter Multicast Address */
+#define PAM 0x00000040 /* Pass-All-Multicast Mode Enable */
+#define PR 0x00000080 /* Promiscuous Mode Enable */
+#define IFE 0x00000100 /* Inverse Filtering Enable */
+#define DBF 0x00000200 /* Disable Broadcast Frame Reception */
+#define PBF 0x00000400 /* Pass Bad Frames Enable */
+#define PSF 0x00000800 /* Pass Short Frames Enable */
+#define RAF 0x00001000 /* Receive-All Mode */
+#define TE 0x00010000 /* Transmitter Enable */
+#define DTXPAD 0x00020000 /* Disable Automatic TX Padding */
+#define DTXCRC 0x00040000 /* Disable Automatic TX CRC Generation */
+#define DC 0x00080000 /* Deferral Check */
+#define BOLMT 0x00300000 /* Back-Off Limit */
+#define BOLMT_10 0x00000000 /* 10-bit range */
+#define BOLMT_8 0x00100000 /* 8-bit range */
+#define BOLMT_4 0x00200000 /* 4-bit range */
+#define BOLMT_1 0x00300000 /* 1-bit range */
+#define DRTY 0x00400000 /* Disable TX Retry On Collision */
+#define LCTRE 0x00800000 /* Enable TX Retry On Late Collision */
+#define RMII 0x01000000 /* RMII/MII* Mode */
+#define RMII_10 0x02000000 /* Speed Select for RMII Port (10MBit/100MBit*) */
+#define FDMODE 0x04000000 /* Duplex Mode Enable (Full/Half*) */
+#define LB 0x08000000 /* Internal Loopback Enable */
+#define DRO 0x10000000 /* Disable Receive Own Frames (Half-Duplex Mode) */
+
+/* EMAC_STAADD Masks */
+
+#define STABUSY 0x00000001 /* Initiate Station Mgt Reg Access / STA Busy Stat */
+#define STAOP 0x00000002 /* Station Management Operation Code (Write/Read*) */
+#define STADISPRE 0x00000004 /* Disable Preamble Generation */
+#define STAIE 0x00000008 /* Station Mgt. Transfer Done Interrupt Enable */
+#define REGAD 0x000007C0 /* STA Register Address */
+#define PHYAD 0x0000F800 /* PHY Device Address */
+
+#define SET_REGAD(x) (((x)&0x1F)<< 6 ) /* Set STA Register Address */
+#define SET_PHYAD(x) (((x)&0x1F)<< 11 ) /* Set PHY Device Address */
+
+/* EMAC_STADAT Mask */
+
+#define STADATA 0x0000FFFF /* Station Management Data */
+
+/* EMAC_FLC Masks */
+
+#define FLCBUSY 0x00000001 /* Send Flow Ctrl Frame / Flow Ctrl Busy Status */
+#define FLCE 0x00000002 /* Flow Control Enable */
+#define PCF 0x00000004 /* Pass Control Frames */
+#define BKPRSEN 0x00000008 /* Enable Backpressure */
+#define FLCPAUSE 0xFFFF0000 /* Pause Time */
+
+#define SET_FLCPAUSE(x) (((x)&0xFFFF)<< 16) /* Set Pause Time */
+
+/* EMAC_WKUP_CTL Masks */
+
+#define CAPWKFRM 0x00000001 /* Capture Wake-Up Frames */
+#define MPKE 0x00000002 /* Magic Packet Enable */
+#define RWKE 0x00000004 /* Remote Wake-Up Frame Enable */
+#define GUWKE 0x00000008 /* Global Unicast Wake Enable */
+#define MPKS 0x00000020 /* Magic Packet Received Status */
+#define RWKS 0x00000F00 /* Wake-Up Frame Received Status, Filters 3:0 */
+
+/* EMAC_WKUP_FFCMD Masks */
+
+#define WF0_E 0x00000001 /* Enable Wake-Up Filter 0 */
+#define WF0_T 0x00000008 /* Wake-Up Filter 0 Addr Type (Multicast/Unicast*) */
+#define WF1_E 0x00000100 /* Enable Wake-Up Filter 1 */
+#define WF1_T 0x00000800 /* Wake-Up Filter 1 Addr Type (Multicast/Unicast*) */
+#define WF2_E 0x00010000 /* Enable Wake-Up Filter 2 */
+#define WF2_T 0x00080000 /* Wake-Up Filter 2 Addr Type (Multicast/Unicast*) */
+#define WF3_E 0x01000000 /* Enable Wake-Up Filter 3 */
+#define WF3_T 0x08000000 /* Wake-Up Filter 3 Addr Type (Multicast/Unicast*) */
+
+/* EMAC_WKUP_FFOFF Masks */
+
+#define WF0_OFF 0x000000FF /* Wake-Up Filter 0 Pattern Offset */
+#define WF1_OFF 0x0000FF00 /* Wake-Up Filter 1 Pattern Offset */
+#define WF2_OFF 0x00FF0000 /* Wake-Up Filter 2 Pattern Offset */
+#define WF3_OFF 0xFF000000 /* Wake-Up Filter 3 Pattern Offset */
+
+#define SET_WF0_OFF(x) (((x)&0xFF)<< 0 ) /* Set Wake-Up Filter 0 Byte Offset */
+#define SET_WF1_OFF(x) (((x)&0xFF)<< 8 ) /* Set Wake-Up Filter 1 Byte Offset */
+#define SET_WF2_OFF(x) (((x)&0xFF)<< 16 ) /* Set Wake-Up Filter 2 Byte Offset */
+#define SET_WF3_OFF(x) (((x)&0xFF)<< 24 ) /* Set Wake-Up Filter 3 Byte Offset */
+/* Set ALL Offsets */
+#define SET_WF_OFFS(x0,x1,x2,x3) (SET_WF0_OFF((x0))|SET_WF1_OFF((x1))|SET_WF2_OFF((x2))|SET_WF3_OFF((x3)))
+
+/* EMAC_WKUP_FFCRC0 Masks */
+
+#define WF0_CRC 0x0000FFFF /* Wake-Up Filter 0 Pattern CRC */
+#define WF1_CRC 0xFFFF0000 /* Wake-Up Filter 1 Pattern CRC */
+
+#define SET_WF0_CRC(x) (((x)&0xFFFF)<< 0 ) /* Set Wake-Up Filter 0 Target CRC */
+#define SET_WF1_CRC(x) (((x)&0xFFFF)<< 16 ) /* Set Wake-Up Filter 1 Target CRC */
+
+/* EMAC_WKUP_FFCRC1 Masks */
+
+#define WF2_CRC 0x0000FFFF /* Wake-Up Filter 2 Pattern CRC */
+#define WF3_CRC 0xFFFF0000 /* Wake-Up Filter 3 Pattern CRC */
+
+#define SET_WF2_CRC(x) (((x)&0xFFFF)<< 0 ) /* Set Wake-Up Filter 2 Target CRC */
+#define SET_WF3_CRC(x) (((x)&0xFFFF)<< 16 ) /* Set Wake-Up Filter 3 Target CRC */
+
+/* EMAC_SYSCTL Masks */
+
+#define PHYIE 0x00000001 /* PHY_INT Interrupt Enable */
+#define RXDWA 0x00000002 /* Receive Frame DMA Word Alignment (Odd/Even*) */
+#define RXCKS 0x00000004 /* Enable RX Frame TCP/UDP Checksum Computation */
+#define TXDWA 0x00000010 /* Transmit Frame DMA Word Alignment (Odd/Even*) */
+#define MDCDIV 0x00003F00 /* SCLK:MDC Clock Divisor [MDC=SCLK/(2*(N+1))] */
+
+#define SET_MDCDIV(x) (((x)&0x3F)<< 8) /* Set MDC Clock Divisor */
+
+/* EMAC_SYSTAT Masks */
+
+#define PHYINT 0x00000001 /* PHY_INT Interrupt Status */
+#define MMCINT 0x00000002 /* MMC Counter Interrupt Status */
+#define RXFSINT 0x00000004 /* RX Frame-Status Interrupt Status */
+#define TXFSINT 0x00000008 /* TX Frame-Status Interrupt Status */
+#define WAKEDET 0x00000010 /* Wake-Up Detected Status */
+#define RXDMAERR 0x00000020 /* RX DMA Direction Error Status */
+#define TXDMAERR 0x00000040 /* TX DMA Direction Error Status */
+#define STMDONE 0x00000080 /* Station Mgt. Transfer Done Interrupt Status */
+
+/* EMAC_RX_STAT, EMAC_RX_STKY, and EMAC_RX_IRQE Masks */
+
+#define RX_FRLEN 0x000007FF /* Frame Length In Bytes */
+#define RX_COMP 0x00001000 /* RX Frame Complete */
+#define RX_OK 0x00002000 /* RX Frame Received With No Errors */
+#define RX_LONG 0x00004000 /* RX Frame Too Long Error */
+#define RX_ALIGN 0x00008000 /* RX Frame Alignment Error */
+#define RX_CRC 0x00010000 /* RX Frame CRC Error */
+#define RX_LEN 0x00020000 /* RX Frame Length Error */
+#define RX_FRAG 0x00040000 /* RX Frame Fragment Error */
+#define RX_ADDR 0x00080000 /* RX Frame Address Filter Failed Error */
+#define RX_DMAO 0x00100000 /* RX Frame DMA Overrun Error */
+#define RX_PHY 0x00200000 /* RX Frame PHY Error */
+#define RX_LATE 0x00400000 /* RX Frame Late Collision Error */
+#define RX_RANGE 0x00800000 /* RX Frame Length Field Out of Range Error */
+#define RX_MULTI 0x01000000 /* RX Multicast Frame Indicator */
+#define RX_BROAD 0x02000000 /* RX Broadcast Frame Indicator */
+#define RX_CTL 0x04000000 /* RX Control Frame Indicator */
+#define RX_UCTL 0x08000000 /* Unsupported RX Control Frame Indicator */
+#define RX_TYPE 0x10000000 /* RX Typed Frame Indicator */
+#define RX_VLAN1 0x20000000 /* RX VLAN1 Frame Indicator */
+#define RX_VLAN2 0x40000000 /* RX VLAN2 Frame Indicator */
+#define RX_ACCEPT 0x80000000 /* RX Frame Accepted Indicator */
+
+/* EMAC_TX_STAT, EMAC_TX_STKY, and EMAC_TX_IRQE Masks */
+
+#define TX_COMP 0x00000001 /* TX Frame Complete */
+#define TX_OK 0x00000002 /* TX Frame Sent With No Errors */
+#define TX_ECOLL 0x00000004 /* TX Frame Excessive Collision Error */
+#define TX_LATE 0x00000008 /* TX Frame Late Collision Error */
+#define TX_DMAU 0x00000010 /* TX Frame DMA Underrun Error (STAT) */
+#define TX_MACE 0x00000010 /* Internal MAC Error Detected (STKY and IRQE) */
+#define TX_EDEFER 0x00000020 /* TX Frame Excessive Deferral Error */
+#define TX_BROAD 0x00000040 /* TX Broadcast Frame Indicator */
+#define TX_MULTI 0x00000080 /* TX Multicast Frame Indicator */
+#define TX_CCNT 0x00000F00 /* TX Frame Collision Count */
+#define TX_DEFER 0x00001000 /* TX Frame Deferred Indicator */
+#define TX_CRS 0x00002000 /* TX Frame Carrier Sense Not Asserted Error */
+#define TX_LOSS 0x00004000 /* TX Frame Carrier Lost During TX Error */
+#define TX_RETRY 0x00008000 /* TX Frame Successful After Retry */
+#define TX_FRLEN 0x07FF0000 /* TX Frame Length (Bytes) */
+
+/* EMAC_MMC_CTL Masks */
+#define RSTC 0x00000001 /* Reset All Counters */
+#define CROLL 0x00000002 /* Counter Roll-Over Enable */
+#define CCOR 0x00000004 /* Counter Clear-On-Read Mode Enable */
+#define MMCE 0x00000008 /* Enable MMC Counter Operation */
+
+/* EMAC_MMC_RIRQS and EMAC_MMC_RIRQE Masks */
+#define RX_OK_CNT 0x00000001 /* RX Frames Received With No Errors */
+#define RX_FCS_CNT 0x00000002 /* RX Frames W/Frame Check Sequence Errors */
+#define RX_ALIGN_CNT 0x00000004 /* RX Frames With Alignment Errors */
+#define RX_OCTET_CNT 0x00000008 /* RX Octets Received OK */
+#define RX_LOST_CNT 0x00000010 /* RX Frames Lost Due To Internal MAC RX Error */
+#define RX_UNI_CNT 0x00000020 /* Unicast RX Frames Received OK */
+#define RX_MULTI_CNT 0x00000040 /* Multicast RX Frames Received OK */
+#define RX_BROAD_CNT 0x00000080 /* Broadcast RX Frames Received OK */
+#define RX_IRL_CNT 0x00000100 /* RX Frames With In-Range Length Errors */
+#define RX_ORL_CNT 0x00000200 /* RX Frames With Out-Of-Range Length Errors */
+#define RX_LONG_CNT 0x00000400 /* RX Frames With Frame Too Long Errors */
+#define RX_MACCTL_CNT 0x00000800 /* MAC Control RX Frames Received */
+#define RX_OPCODE_CTL 0x00001000 /* Unsupported Op-Code RX Frames Received */
+#define RX_PAUSE_CNT 0x00002000 /* PAUSEMAC Control RX Frames Received */
+#define RX_ALLF_CNT 0x00004000 /* All RX Frames Received */
+#define RX_ALLO_CNT 0x00008000 /* All RX Octets Received */
+#define RX_TYPED_CNT 0x00010000 /* Typed RX Frames Received */
+#define RX_SHORT_CNT 0x00020000 /* RX Frame Fragments (< 64 Bytes) Received */
+#define RX_EQ64_CNT 0x00040000 /* 64-Byte RX Frames Received */
+#define RX_LT128_CNT 0x00080000 /* 65-127-Byte RX Frames Received */
+#define RX_LT256_CNT 0x00100000 /* 128-255-Byte RX Frames Received */
+#define RX_LT512_CNT 0x00200000 /* 256-511-Byte RX Frames Received */
+#define RX_LT1024_CNT 0x00400000 /* 512-1023-Byte RX Frames Received */
+#define RX_GE1024_CNT 0x00800000 /* 1024-Max-Byte RX Frames Received */
+
+/* EMAC_MMC_TIRQS and EMAC_MMC_TIRQE Masks */
+
+#define TX_OK_CNT 0x00000001 /* TX Frames Sent OK */
+#define TX_SCOLL_CNT 0x00000002 /* TX Frames With Single Collisions */
+#define TX_MCOLL_CNT 0x00000004 /* TX Frames With Multiple Collisions */
+#define TX_OCTET_CNT 0x00000008 /* TX Octets Sent OK */
+#define TX_DEFER_CNT 0x00000010 /* TX Frames With Deferred Transmission */
+#define TX_LATE_CNT 0x00000020 /* TX Frames With Late Collisions */
+#define TX_ABORTC_CNT 0x00000040 /* TX Frames Aborted Due To Excess Collisions */
+#define TX_LOST_CNT 0x00000080 /* TX Frames Lost Due To Internal MAC TX Error */
+#define TX_CRS_CNT 0x00000100 /* TX Frames With Carrier Sense Errors */
+#define TX_UNI_CNT 0x00000200 /* Unicast TX Frames Sent */
+#define TX_MULTI_CNT 0x00000400 /* Multicast TX Frames Sent */
+#define TX_BROAD_CNT 0x00000800 /* Broadcast TX Frames Sent */
+#define TX_EXDEF_CTL 0x00001000 /* TX Frames With Excessive Deferral */
+#define TX_MACCTL_CNT 0x00002000 /* MAC Control TX Frames Sent */
+#define TX_ALLF_CNT 0x00004000 /* All TX Frames Sent */
+#define TX_ALLO_CNT 0x00008000 /* All TX Octets Sent */
+#define TX_EQ64_CNT 0x00010000 /* 64-Byte TX Frames Sent */
+#define TX_LT128_CNT 0x00020000 /* 65-127-Byte TX Frames Sent */
+#define TX_LT256_CNT 0x00040000 /* 128-255-Byte TX Frames Sent */
+#define TX_LT512_CNT 0x00080000 /* 256-511-Byte TX Frames Sent */
+#define TX_LT1024_CNT 0x00100000 /* 512-1023-Byte TX Frames Sent */
+#define TX_GE1024_CNT 0x00200000 /* 1024-Max-Byte TX Frames Sent */
+#define TX_ABORT_CNT 0x00400000 /* TX Frames Aborted */
+
+/* SDH Registers */
+
+#define SDH_PWR_CTL 0xFFC03900 /* SDH Power Control */
+#define SDH_CLK_CTL 0xFFC03904 /* SDH Clock Control */
+#define SDH_ARGUMENT 0xFFC03908 /* SDH Argument */
+#define SDH_COMMAND 0xFFC0390C /* SDH Command */
+#define SDH_RESP_CMD 0xFFC03910 /* SDH Response Command */
+#define SDH_RESPONSE0 0xFFC03914 /* SDH Response0 */
+#define SDH_RESPONSE1 0xFFC03918 /* SDH Response1 */
+#define SDH_RESPONSE2 0xFFC0391C /* SDH Response2 */
+#define SDH_RESPONSE3 0xFFC03920 /* SDH Response3 */
+#define SDH_DATA_TIMER 0xFFC03924 /* SDH Data Timer */
+#define SDH_DATA_LGTH 0xFFC03928 /* SDH Data Length */
+#define SDH_DATA_CTL 0xFFC0392C /* SDH Data Control */
+#define SDH_DATA_CNT 0xFFC03930 /* SDH Data Counter */
+#define SDH_STATUS 0xFFC03934 /* SDH Status */
+#define SDH_STATUS_CLR 0xFFC03938 /* SDH Status Clear */
+#define SDH_MASK0 0xFFC0393C /* SDH Interrupt0 Mask */
+#define SDH_MASK1 0xFFC03940 /* SDH Interrupt1 Mask */
+#define SDH_FIFO_CNT 0xFFC03948 /* SDH FIFO Counter */
+#define SDH_FIFO 0xFFC03980 /* SDH Data FIFO */
+#define SDH_E_STATUS 0xFFC039C0 /* SDH Exception Status */
+#define SDH_E_MASK 0xFFC039C4 /* SDH Exception Mask */
+#define SDH_CFG 0xFFC039C8 /* SDH Configuration */
+#define SDH_RD_WAIT_EN 0xFFC039CC /* SDH Read Wait Enable */
+#define SDH_PID0 0xFFC039D0 /* SDH Peripheral Identification0 */
+#define SDH_PID1 0xFFC039D4 /* SDH Peripheral Identification1 */
+#define SDH_PID2 0xFFC039D8 /* SDH Peripheral Identification2 */
+#define SDH_PID3 0xFFC039DC /* SDH Peripheral Identification3 */
+#define SDH_PID4 0xFFC039E0 /* SDH Peripheral Identification4 */
+#define SDH_PID5 0xFFC039E4 /* SDH Peripheral Identification5 */
+#define SDH_PID6 0xFFC039E8 /* SDH Peripheral Identification6 */
+#define SDH_PID7 0xFFC039EC /* SDH Peripheral Identification7 */
+
+/* Removable Storage Interface Registers */
+
+#define RSI_PWR_CONTROL 0xFFC03800 /* RSI Power Control Register */
+#define RSI_CLK_CONTROL 0xFFC03804 /* RSI Clock Control Register */
+#define RSI_ARGUMENT 0xFFC03808 /* RSI Argument Register */
+#define RSI_COMMAND 0xFFC0380C /* RSI Command Register */
+#define RSI_RESP_CMD 0xFFC03810 /* RSI Response Command Register */
+#define RSI_RESPONSE0 0xFFC03814 /* RSI Response Register */
+#define RSI_RESPONSE1 0xFFC03818 /* RSI Response Register */
+#define RSI_RESPONSE2 0xFFC0381C /* RSI Response Register */
+#define RSI_RESPONSE3 0xFFC03820 /* RSI Response Register */
+#define RSI_DATA_TIMER 0xFFC03824 /* RSI Data Timer Register */
+#define RSI_DATA_LGTH 0xFFC03828 /* RSI Data Length Register */
+#define RSI_DATA_CONTROL 0xFFC0382C /* RSI Data Control Register */
+#define RSI_DATA_CNT 0xFFC03830 /* RSI Data Counter Register */
+#define RSI_STATUS 0xFFC03834 /* RSI Status Register */
+#define RSI_STATUSCL 0xFFC03838 /* RSI Status Clear Register */
+#define RSI_MASK0 0xFFC0383C /* RSI Interrupt 0 Mask Register */
+#define RSI_MASK1 0xFFC03840 /* RSI Interrupt 1 Mask Register */
+#define RSI_FIFO_CNT 0xFFC03848 /* RSI FIFO Counter Register */
+#define RSI_CEATA_CONTROL 0xFFC0384C /* RSI CEATA Register */
+#define RSI_FIFO 0xFFC03880 /* RSI Data FIFO Register */
+#define RSI_ESTAT 0xFFC038C0 /* RSI Exception Status Register */
+#define RSI_EMASK 0xFFC038C4 /* RSI Exception Mask Register */
+#define RSI_CONFIG 0xFFC038C8 /* RSI Configuration Register */
+#define RSI_RD_WAIT_EN 0xFFC038CC /* RSI Read Wait Enable Register */
+#define RSI_PID0 0xFFC03FE0 /* RSI Peripheral ID Register 0 */
+#define RSI_PID1 0xFFC03FE4 /* RSI Peripheral ID Register 1 */
+#define RSI_PID2 0xFFC03FE8 /* RSI Peripheral ID Register 2 */
+#define RSI_PID3 0xFFC03FEC /* RSI Peripheral ID Register 3 */
+#define RSI_PID4 0xFFC03FF0 /* RSI Peripheral ID Register 4 */
+#define RSI_PID5 0xFFC03FF4 /* RSI Peripheral ID Register 5 */
+#define RSI_PID6 0xFFC03FF8 /* RSI Peripheral ID Register 6 */
+#define RSI_PID7 0xFFC03FFC /* RSI Peripheral ID Register 7 */
+
+#endif /* _DEF_BF516_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF518.h b/arch/blackfin/mach-bf518/include/mach/defBF518.h
new file mode 100644
index 000000000000..6e982abf4ede
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/defBF518.h
@@ -0,0 +1,651 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/defBF518.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF518_H
+#define _DEF_BF518_H
+
+/* Include all Core registers and bit definitions */
+#include <asm/def_LPBlackfin.h>
+
+/* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF518 */
+
+/* Include defBF51x_base.h for the set of #defines that are common to all ADSP-BF51x processors */
+#include "defBF51x_base.h"
+
+/* The following are the #defines needed by ADSP-BF518 that are not in the common header */
+/* 10/100 Ethernet Controller (0xFFC03000 - 0xFFC031FF) */
+
+#define EMAC_OPMODE 0xFFC03000 /* Operating Mode Register */
+#define EMAC_ADDRLO 0xFFC03004 /* Address Low (32 LSBs) Register */
+#define EMAC_ADDRHI 0xFFC03008 /* Address High (16 MSBs) Register */
+#define EMAC_HASHLO 0xFFC0300C /* Multicast Hash Table Low (Bins 31-0) Register */
+#define EMAC_HASHHI 0xFFC03010 /* Multicast Hash Table High (Bins 63-32) Register */
+#define EMAC_STAADD 0xFFC03014 /* Station Management Address Register */
+#define EMAC_STADAT 0xFFC03018 /* Station Management Data Register */
+#define EMAC_FLC 0xFFC0301C /* Flow Control Register */
+#define EMAC_VLAN1 0xFFC03020 /* VLAN1 Tag Register */
+#define EMAC_VLAN2 0xFFC03024 /* VLAN2 Tag Register */
+#define EMAC_WKUP_CTL 0xFFC0302C /* Wake-Up Control/Status Register */
+#define EMAC_WKUP_FFMSK0 0xFFC03030 /* Wake-Up Frame Filter 0 Byte Mask Register */
+#define EMAC_WKUP_FFMSK1 0xFFC03034 /* Wake-Up Frame Filter 1 Byte Mask Register */
+#define EMAC_WKUP_FFMSK2 0xFFC03038 /* Wake-Up Frame Filter 2 Byte Mask Register */
+#define EMAC_WKUP_FFMSK3 0xFFC0303C /* Wake-Up Frame Filter 3 Byte Mask Register */
+#define EMAC_WKUP_FFCMD 0xFFC03040 /* Wake-Up Frame Filter Commands Register */
+#define EMAC_WKUP_FFOFF 0xFFC03044 /* Wake-Up Frame Filter Offsets Register */
+#define EMAC_WKUP_FFCRC0 0xFFC03048 /* Wake-Up Frame Filter 0,1 CRC-16 Register */
+#define EMAC_WKUP_FFCRC1 0xFFC0304C /* Wake-Up Frame Filter 2,3 CRC-16 Register */
+
+#define EMAC_SYSCTL 0xFFC03060 /* EMAC System Control Register */
+#define EMAC_SYSTAT 0xFFC03064 /* EMAC System Status Register */
+#define EMAC_RX_STAT 0xFFC03068 /* RX Current Frame Status Register */
+#define EMAC_RX_STKY 0xFFC0306C /* RX Sticky Frame Status Register */
+#define EMAC_RX_IRQE 0xFFC03070 /* RX Frame Status Interrupt Enables Register */
+#define EMAC_TX_STAT 0xFFC03074 /* TX Current Frame Status Register */
+#define EMAC_TX_STKY 0xFFC03078 /* TX Sticky Frame Status Register */
+#define EMAC_TX_IRQE 0xFFC0307C /* TX Frame Status Interrupt Enables Register */
+
+#define EMAC_MMC_CTL 0xFFC03080 /* MMC Counter Control Register */
+#define EMAC_MMC_RIRQS 0xFFC03084 /* MMC RX Interrupt Status Register */
+#define EMAC_MMC_RIRQE 0xFFC03088 /* MMC RX Interrupt Enables Register */
+#define EMAC_MMC_TIRQS 0xFFC0308C /* MMC TX Interrupt Status Register */
+#define EMAC_MMC_TIRQE 0xFFC03090 /* MMC TX Interrupt Enables Register */
+
+#define EMAC_RXC_OK 0xFFC03100 /* RX Frame Successful Count */
+#define EMAC_RXC_FCS 0xFFC03104 /* RX Frame FCS Failure Count */
+#define EMAC_RXC_ALIGN 0xFFC03108 /* RX Alignment Error Count */
+#define EMAC_RXC_OCTET 0xFFC0310C /* RX Octets Successfully Received Count */
+#define EMAC_RXC_DMAOVF 0xFFC03110 /* Internal MAC Sublayer Error RX Frame Count */
+#define EMAC_RXC_UNICST 0xFFC03114 /* Unicast RX Frame Count */
+#define EMAC_RXC_MULTI 0xFFC03118 /* Multicast RX Frame Count */
+#define EMAC_RXC_BROAD 0xFFC0311C /* Broadcast RX Frame Count */
+#define EMAC_RXC_LNERRI 0xFFC03120 /* RX Frame In Range Error Count */
+#define EMAC_RXC_LNERRO 0xFFC03124 /* RX Frame Out Of Range Error Count */
+#define EMAC_RXC_LONG 0xFFC03128 /* RX Frame Too Long Count */
+#define EMAC_RXC_MACCTL 0xFFC0312C /* MAC Control RX Frame Count */
+#define EMAC_RXC_OPCODE 0xFFC03130 /* Unsupported Op-Code RX Frame Count */
+#define EMAC_RXC_PAUSE 0xFFC03134 /* MAC Control Pause RX Frame Count */
+#define EMAC_RXC_ALLFRM 0xFFC03138 /* Overall RX Frame Count */
+#define EMAC_RXC_ALLOCT 0xFFC0313C /* Overall RX Octet Count */
+#define EMAC_RXC_TYPED 0xFFC03140 /* Type/Length Consistent RX Frame Count */
+#define EMAC_RXC_SHORT 0xFFC03144 /* RX Frame Fragment Count - Byte Count x < 64 */
+#define EMAC_RXC_EQ64 0xFFC03148 /* Good RX Frame Count - Byte Count x = 64 */
+#define EMAC_RXC_LT128 0xFFC0314C /* Good RX Frame Count - Byte Count 64 < x < 128 */
+#define EMAC_RXC_LT256 0xFFC03150 /* Good RX Frame Count - Byte Count 128 <= x < 256 */
+#define EMAC_RXC_LT512 0xFFC03154 /* Good RX Frame Count - Byte Count 256 <= x < 512 */
+#define EMAC_RXC_LT1024 0xFFC03158 /* Good RX Frame Count - Byte Count 512 <= x < 1024 */
+#define EMAC_RXC_GE1024 0xFFC0315C /* Good RX Frame Count - Byte Count x >= 1024 */
+
+#define EMAC_TXC_OK 0xFFC03180 /* TX Frame Successful Count */
+#define EMAC_TXC_1COL 0xFFC03184 /* TX Frames Successful After Single Collision Count */
+#define EMAC_TXC_GT1COL 0xFFC03188 /* TX Frames Successful After Multiple Collisions Count */
+#define EMAC_TXC_OCTET 0xFFC0318C /* TX Octets Successfully Received Count */
+#define EMAC_TXC_DEFER 0xFFC03190 /* TX Frame Delayed Due To Busy Count */
+#define EMAC_TXC_LATECL 0xFFC03194 /* Late TX Collisions Count */
+#define EMAC_TXC_XS_COL 0xFFC03198 /* TX Frame Failed Due To Excessive Collisions Count */
+#define EMAC_TXC_DMAUND 0xFFC0319C /* Internal MAC Sublayer Error TX Frame Count */
+#define EMAC_TXC_CRSERR 0xFFC031A0 /* Carrier Sense Deasserted During TX Frame Count */
+#define EMAC_TXC_UNICST 0xFFC031A4 /* Unicast TX Frame Count */
+#define EMAC_TXC_MULTI 0xFFC031A8 /* Multicast TX Frame Count */
+#define EMAC_TXC_BROAD 0xFFC031AC /* Broadcast TX Frame Count */
+#define EMAC_TXC_XS_DFR 0xFFC031B0 /* TX Frames With Excessive Deferral Count */
+#define EMAC_TXC_MACCTL 0xFFC031B4 /* MAC Control TX Frame Count */
+#define EMAC_TXC_ALLFRM 0xFFC031B8 /* Overall TX Frame Count */
+#define EMAC_TXC_ALLOCT 0xFFC031BC /* Overall TX Octet Count */
+#define EMAC_TXC_EQ64 0xFFC031C0 /* Good TX Frame Count - Byte Count x = 64 */
+#define EMAC_TXC_LT128 0xFFC031C4 /* Good TX Frame Count - Byte Count 64 < x < 128 */
+#define EMAC_TXC_LT256 0xFFC031C8 /* Good TX Frame Count - Byte Count 128 <= x < 256 */
+#define EMAC_TXC_LT512 0xFFC031CC /* Good TX Frame Count - Byte Count 256 <= x < 512 */
+#define EMAC_TXC_LT1024 0xFFC031D0 /* Good TX Frame Count - Byte Count 512 <= x < 1024 */
+#define EMAC_TXC_GE1024 0xFFC031D4 /* Good TX Frame Count - Byte Count x >= 1024 */
+#define EMAC_TXC_ABORT 0xFFC031D8 /* Total TX Frames Aborted Count */
+
+/* Listing for IEEE-Supported Count Registers */
+
+#define FramesReceivedOK EMAC_RXC_OK /* RX Frame Successful Count */
+#define FrameCheckSequenceErrors EMAC_RXC_FCS /* RX Frame FCS Failure Count */
+#define AlignmentErrors EMAC_RXC_ALIGN /* RX Alignment Error Count */
+#define OctetsReceivedOK EMAC_RXC_OCTET /* RX Octets Successfully Received Count */
+#define FramesLostDueToIntMACRcvError EMAC_RXC_DMAOVF /* Internal MAC Sublayer Error RX Frame Count */
+#define UnicastFramesReceivedOK EMAC_RXC_UNICST /* Unicast RX Frame Count */
+#define MulticastFramesReceivedOK EMAC_RXC_MULTI /* Multicast RX Frame Count */
+#define BroadcastFramesReceivedOK EMAC_RXC_BROAD /* Broadcast RX Frame Count */
+#define InRangeLengthErrors EMAC_RXC_LNERRI /* RX Frame In Range Error Count */
+#define OutOfRangeLengthField EMAC_RXC_LNERRO /* RX Frame Out Of Range Error Count */
+#define FrameTooLongErrors EMAC_RXC_LONG /* RX Frame Too Long Count */
+#define MACControlFramesReceived EMAC_RXC_MACCTL /* MAC Control RX Frame Count */
+#define UnsupportedOpcodesReceived EMAC_RXC_OPCODE /* Unsupported Op-Code RX Frame Count */
+#define PAUSEMACCtrlFramesReceived EMAC_RXC_PAUSE /* MAC Control Pause RX Frame Count */
+#define FramesReceivedAll EMAC_RXC_ALLFRM /* Overall RX Frame Count */
+#define OctetsReceivedAll EMAC_RXC_ALLOCT /* Overall RX Octet Count */
+#define TypedFramesReceived EMAC_RXC_TYPED /* Type/Length Consistent RX Frame Count */
+#define FramesLenLt64Received EMAC_RXC_SHORT /* RX Frame Fragment Count - Byte Count x < 64 */
+#define FramesLenEq64Received EMAC_RXC_EQ64 /* Good RX Frame Count - Byte Count x = 64 */
+#define FramesLen65_127Received EMAC_RXC_LT128 /* Good RX Frame Count - Byte Count 64 < x < 128 */
+#define FramesLen128_255Received EMAC_RXC_LT256 /* Good RX Frame Count - Byte Count 128 <= x < 256 */
+#define FramesLen256_511Received EMAC_RXC_LT512 /* Good RX Frame Count - Byte Count 256 <= x < 512 */
+#define FramesLen512_1023Received EMAC_RXC_LT1024 /* Good RX Frame Count - Byte Count 512 <= x < 1024 */
+#define FramesLen1024_MaxReceived EMAC_RXC_GE1024 /* Good RX Frame Count - Byte Count x >= 1024 */
+
+#define FramesTransmittedOK EMAC_TXC_OK /* TX Frame Successful Count */
+#define SingleCollisionFrames EMAC_TXC_1COL /* TX Frames Successful After Single Collision Count */
+#define MultipleCollisionFrames EMAC_TXC_GT1COL /* TX Frames Successful After Multiple Collisions Count */
+#define OctetsTransmittedOK EMAC_TXC_OCTET /* TX Octets Successfully Received Count */
+#define FramesWithDeferredXmissions EMAC_TXC_DEFER /* TX Frame Delayed Due To Busy Count */
+#define LateCollisions EMAC_TXC_LATECL /* Late TX Collisions Count */
+#define FramesAbortedDueToXSColls EMAC_TXC_XS_COL /* TX Frame Failed Due To Excessive Collisions Count */
+#define FramesLostDueToIntMacXmitError EMAC_TXC_DMAUND /* Internal MAC Sublayer Error TX Frame Count */
+#define CarrierSenseErrors EMAC_TXC_CRSERR /* Carrier Sense Deasserted During TX Frame Count */
+#define UnicastFramesXmittedOK EMAC_TXC_UNICST /* Unicast TX Frame Count */
+#define MulticastFramesXmittedOK EMAC_TXC_MULTI /* Multicast TX Frame Count */
+#define BroadcastFramesXmittedOK EMAC_TXC_BROAD /* Broadcast TX Frame Count */
+#define FramesWithExcessiveDeferral EMAC_TXC_XS_DFR /* TX Frames With Excessive Deferral Count */
+#define MACControlFramesTransmitted EMAC_TXC_MACCTL /* MAC Control TX Frame Count */
+#define FramesTransmittedAll EMAC_TXC_ALLFRM /* Overall TX Frame Count */
+#define OctetsTransmittedAll EMAC_TXC_ALLOCT /* Overall TX Octet Count */
+#define FramesLenEq64Transmitted EMAC_TXC_EQ64 /* Good TX Frame Count - Byte Count x = 64 */
+#define FramesLen65_127Transmitted EMAC_TXC_LT128 /* Good TX Frame Count - Byte Count 64 < x < 128 */
+#define FramesLen128_255Transmitted EMAC_TXC_LT256 /* Good TX Frame Count - Byte Count 128 <= x < 256 */
+#define FramesLen256_511Transmitted EMAC_TXC_LT512 /* Good TX Frame Count - Byte Count 256 <= x < 512 */
+#define FramesLen512_1023Transmitted EMAC_TXC_LT1024 /* Good TX Frame Count - Byte Count 512 <= x < 1024 */
+#define FramesLen1024_MaxTransmitted EMAC_TXC_GE1024 /* Good TX Frame Count - Byte Count x >= 1024 */
+#define TxAbortedFrames EMAC_TXC_ABORT /* Total TX Frames Aborted Count */
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer: All macros are intended to make C and Assembly code more readable.
+** Use these macros carefully, as any that do left shifts for field
+** depositing will result in the lower order bits being destroyed. Any
+** macro that shifts left to properly position the bit-field should be
+** used as part of an OR to initialize a register and NOT as a dynamic
+** modifier UNLESS the lower order bits are saved and ORed back in when
+** the macro is used.
+*************************************************************************************/
+
+/************************ ETHERNET 10/100 CONTROLLER MASKS ************************/
+
+/* EMAC_OPMODE Masks */
+
+#define RE 0x00000001 /* Receiver Enable */
+#define ASTP 0x00000002 /* Enable Automatic Pad Stripping On RX Frames */
+#define HU 0x00000010 /* Hash Filter Unicast Address */
+#define HM 0x00000020 /* Hash Filter Multicast Address */
+#define PAM 0x00000040 /* Pass-All-Multicast Mode Enable */
+#define PR 0x00000080 /* Promiscuous Mode Enable */
+#define IFE 0x00000100 /* Inverse Filtering Enable */
+#define DBF 0x00000200 /* Disable Broadcast Frame Reception */
+#define PBF 0x00000400 /* Pass Bad Frames Enable */
+#define PSF 0x00000800 /* Pass Short Frames Enable */
+#define RAF 0x00001000 /* Receive-All Mode */
+#define TE 0x00010000 /* Transmitter Enable */
+#define DTXPAD 0x00020000 /* Disable Automatic TX Padding */
+#define DTXCRC 0x00040000 /* Disable Automatic TX CRC Generation */
+#define DC 0x00080000 /* Deferral Check */
+#define BOLMT 0x00300000 /* Back-Off Limit */
+#define BOLMT_10 0x00000000 /* 10-bit range */
+#define BOLMT_8 0x00100000 /* 8-bit range */
+#define BOLMT_4 0x00200000 /* 4-bit range */
+#define BOLMT_1 0x00300000 /* 1-bit range */
+#define DRTY 0x00400000 /* Disable TX Retry On Collision */
+#define LCTRE 0x00800000 /* Enable TX Retry On Late Collision */
+#define RMII 0x01000000 /* RMII/MII* Mode */
+#define RMII_10 0x02000000 /* Speed Select for RMII Port (10MBit/100MBit*) */
+#define FDMODE 0x04000000 /* Duplex Mode Enable (Full/Half*) */
+#define LB 0x08000000 /* Internal Loopback Enable */
+#define DRO 0x10000000 /* Disable Receive Own Frames (Half-Duplex Mode) */
+
+/* EMAC_STAADD Masks */
+
+#define STABUSY 0x00000001 /* Initiate Station Mgt Reg Access / STA Busy Stat */
+#define STAOP 0x00000002 /* Station Management Operation Code (Write/Read*) */
+#define STADISPRE 0x00000004 /* Disable Preamble Generation */
+#define STAIE 0x00000008 /* Station Mgt. Transfer Done Interrupt Enable */
+#define REGAD 0x000007C0 /* STA Register Address */
+#define PHYAD 0x0000F800 /* PHY Device Address */
+
+#define SET_REGAD(x) (((x)&0x1F)<< 6 ) /* Set STA Register Address */
+#define SET_PHYAD(x) (((x)&0x1F)<< 11 ) /* Set PHY Device Address */
+
+/* EMAC_STADAT Mask */
+
+#define STADATA 0x0000FFFF /* Station Management Data */
+
+/* EMAC_FLC Masks */
+
+#define FLCBUSY 0x00000001 /* Send Flow Ctrl Frame / Flow Ctrl Busy Status */
+#define FLCE 0x00000002 /* Flow Control Enable */
+#define PCF 0x00000004 /* Pass Control Frames */
+#define BKPRSEN 0x00000008 /* Enable Backpressure */
+#define FLCPAUSE 0xFFFF0000 /* Pause Time */
+
+#define SET_FLCPAUSE(x) (((x)&0xFFFF)<< 16) /* Set Pause Time */
+
+/* EMAC_WKUP_CTL Masks */
+
+#define CAPWKFRM 0x00000001 /* Capture Wake-Up Frames */
+#define MPKE 0x00000002 /* Magic Packet Enable */
+#define RWKE 0x00000004 /* Remote Wake-Up Frame Enable */
+#define GUWKE 0x00000008 /* Global Unicast Wake Enable */
+#define MPKS 0x00000020 /* Magic Packet Received Status */
+#define RWKS 0x00000F00 /* Wake-Up Frame Received Status, Filters 3:0 */
+
+/* EMAC_WKUP_FFCMD Masks */
+
+#define WF0_E 0x00000001 /* Enable Wake-Up Filter 0 */
+#define WF0_T 0x00000008 /* Wake-Up Filter 0 Addr Type (Multicast/Unicast*) */
+#define WF1_E 0x00000100 /* Enable Wake-Up Filter 1 */
+#define WF1_T 0x00000800 /* Wake-Up Filter 1 Addr Type (Multicast/Unicast*) */
+#define WF2_E 0x00010000 /* Enable Wake-Up Filter 2 */
+#define WF2_T 0x00080000 /* Wake-Up Filter 2 Addr Type (Multicast/Unicast*) */
+#define WF3_E 0x01000000 /* Enable Wake-Up Filter 3 */
+#define WF3_T 0x08000000 /* Wake-Up Filter 3 Addr Type (Multicast/Unicast*) */
+
+/* EMAC_WKUP_FFOFF Masks */
+
+#define WF0_OFF 0x000000FF /* Wake-Up Filter 0 Pattern Offset */
+#define WF1_OFF 0x0000FF00 /* Wake-Up Filter 1 Pattern Offset */
+#define WF2_OFF 0x00FF0000 /* Wake-Up Filter 2 Pattern Offset */
+#define WF3_OFF 0xFF000000 /* Wake-Up Filter 3 Pattern Offset */
+
+#define SET_WF0_OFF(x) (((x)&0xFF)<< 0 ) /* Set Wake-Up Filter 0 Byte Offset */
+#define SET_WF1_OFF(x) (((x)&0xFF)<< 8 ) /* Set Wake-Up Filter 1 Byte Offset */
+#define SET_WF2_OFF(x) (((x)&0xFF)<< 16 ) /* Set Wake-Up Filter 2 Byte Offset */
+#define SET_WF3_OFF(x) (((x)&0xFF)<< 24 ) /* Set Wake-Up Filter 3 Byte Offset */
+/* Set ALL Offsets */
+#define SET_WF_OFFS(x0,x1,x2,x3) (SET_WF0_OFF((x0))|SET_WF1_OFF((x1))|SET_WF2_OFF((x2))|SET_WF3_OFF((x3)))
+
+/* EMAC_WKUP_FFCRC0 Masks */
+
+#define WF0_CRC 0x0000FFFF /* Wake-Up Filter 0 Pattern CRC */
+#define WF1_CRC 0xFFFF0000 /* Wake-Up Filter 1 Pattern CRC */
+
+#define SET_WF0_CRC(x) (((x)&0xFFFF)<< 0 ) /* Set Wake-Up Filter 0 Target CRC */
+#define SET_WF1_CRC(x) (((x)&0xFFFF)<< 16 ) /* Set Wake-Up Filter 1 Target CRC */
+
+/* EMAC_WKUP_FFCRC1 Masks */
+
+#define WF2_CRC 0x0000FFFF /* Wake-Up Filter 2 Pattern CRC */
+#define WF3_CRC 0xFFFF0000 /* Wake-Up Filter 3 Pattern CRC */
+
+#define SET_WF2_CRC(x) (((x)&0xFFFF)<< 0 ) /* Set Wake-Up Filter 2 Target CRC */
+#define SET_WF3_CRC(x) (((x)&0xFFFF)<< 16 ) /* Set Wake-Up Filter 3 Target CRC */
+
+/* EMAC_SYSCTL Masks */
+
+#define PHYIE 0x00000001 /* PHY_INT Interrupt Enable */
+#define RXDWA 0x00000002 /* Receive Frame DMA Word Alignment (Odd/Even*) */
+#define RXCKS 0x00000004 /* Enable RX Frame TCP/UDP Checksum Computation */
+#define TXDWA 0x00000010 /* Transmit Frame DMA Word Alignment (Odd/Even*) */
+#define MDCDIV 0x00003F00 /* SCLK:MDC Clock Divisor [MDC=SCLK/(2*(N+1))] */
+
+#define SET_MDCDIV(x) (((x)&0x3F)<< 8) /* Set MDC Clock Divisor */
+
+/* EMAC_SYSTAT Masks */
+
+#define PHYINT 0x00000001 /* PHY_INT Interrupt Status */
+#define MMCINT 0x00000002 /* MMC Counter Interrupt Status */
+#define RXFSINT 0x00000004 /* RX Frame-Status Interrupt Status */
+#define TXFSINT 0x00000008 /* TX Frame-Status Interrupt Status */
+#define WAKEDET 0x00000010 /* Wake-Up Detected Status */
+#define RXDMAERR 0x00000020 /* RX DMA Direction Error Status */
+#define TXDMAERR 0x00000040 /* TX DMA Direction Error Status */
+#define STMDONE 0x00000080 /* Station Mgt. Transfer Done Interrupt Status */
+
+/* EMAC_RX_STAT, EMAC_RX_STKY, and EMAC_RX_IRQE Masks */
+
+#define RX_FRLEN 0x000007FF /* Frame Length In Bytes */
+#define RX_COMP 0x00001000 /* RX Frame Complete */
+#define RX_OK 0x00002000 /* RX Frame Received With No Errors */
+#define RX_LONG 0x00004000 /* RX Frame Too Long Error */
+#define RX_ALIGN 0x00008000 /* RX Frame Alignment Error */
+#define RX_CRC 0x00010000 /* RX Frame CRC Error */
+#define RX_LEN 0x00020000 /* RX Frame Length Error */
+#define RX_FRAG 0x00040000 /* RX Frame Fragment Error */
+#define RX_ADDR 0x00080000 /* RX Frame Address Filter Failed Error */
+#define RX_DMAO 0x00100000 /* RX Frame DMA Overrun Error */
+#define RX_PHY 0x00200000 /* RX Frame PHY Error */
+#define RX_LATE 0x00400000 /* RX Frame Late Collision Error */
+#define RX_RANGE 0x00800000 /* RX Frame Length Field Out of Range Error */
+#define RX_MULTI 0x01000000 /* RX Multicast Frame Indicator */
+#define RX_BROAD 0x02000000 /* RX Broadcast Frame Indicator */
+#define RX_CTL 0x04000000 /* RX Control Frame Indicator */
+#define RX_UCTL 0x08000000 /* Unsupported RX Control Frame Indicator */
+#define RX_TYPE 0x10000000 /* RX Typed Frame Indicator */
+#define RX_VLAN1 0x20000000 /* RX VLAN1 Frame Indicator */
+#define RX_VLAN2 0x40000000 /* RX VLAN2 Frame Indicator */
+#define RX_ACCEPT 0x80000000 /* RX Frame Accepted Indicator */
+
+/* EMAC_TX_STAT, EMAC_TX_STKY, and EMAC_TX_IRQE Masks */
+
+#define TX_COMP 0x00000001 /* TX Frame Complete */
+#define TX_OK 0x00000002 /* TX Frame Sent With No Errors */
+#define TX_ECOLL 0x00000004 /* TX Frame Excessive Collision Error */
+#define TX_LATE 0x00000008 /* TX Frame Late Collision Error */
+#define TX_DMAU 0x00000010 /* TX Frame DMA Underrun Error (STAT) */
+#define TX_MACE 0x00000010 /* Internal MAC Error Detected (STKY and IRQE) */
+#define TX_EDEFER 0x00000020 /* TX Frame Excessive Deferral Error */
+#define TX_BROAD 0x00000040 /* TX Broadcast Frame Indicator */
+#define TX_MULTI 0x00000080 /* TX Multicast Frame Indicator */
+#define TX_CCNT 0x00000F00 /* TX Frame Collision Count */
+#define TX_DEFER 0x00001000 /* TX Frame Deferred Indicator */
+#define TX_CRS 0x00002000 /* TX Frame Carrier Sense Not Asserted Error */
+#define TX_LOSS 0x00004000 /* TX Frame Carrier Lost During TX Error */
+#define TX_RETRY 0x00008000 /* TX Frame Successful After Retry */
+#define TX_FRLEN 0x07FF0000 /* TX Frame Length (Bytes) */
+
+/* EMAC_MMC_CTL Masks */
+#define RSTC 0x00000001 /* Reset All Counters */
+#define CROLL 0x00000002 /* Counter Roll-Over Enable */
+#define CCOR 0x00000004 /* Counter Clear-On-Read Mode Enable */
+#define MMCE 0x00000008 /* Enable MMC Counter Operation */
+
+/* EMAC_MMC_RIRQS and EMAC_MMC_RIRQE Masks */
+#define RX_OK_CNT 0x00000001 /* RX Frames Received With No Errors */
+#define RX_FCS_CNT 0x00000002 /* RX Frames W/Frame Check Sequence Errors */
+#define RX_ALIGN_CNT 0x00000004 /* RX Frames With Alignment Errors */
+#define RX_OCTET_CNT 0x00000008 /* RX Octets Received OK */
+#define RX_LOST_CNT 0x00000010 /* RX Frames Lost Due To Internal MAC RX Error */
+#define RX_UNI_CNT 0x00000020 /* Unicast RX Frames Received OK */
+#define RX_MULTI_CNT 0x00000040 /* Multicast RX Frames Received OK */
+#define RX_BROAD_CNT 0x00000080 /* Broadcast RX Frames Received OK */
+#define RX_IRL_CNT 0x00000100 /* RX Frames With In-Range Length Errors */
+#define RX_ORL_CNT 0x00000200 /* RX Frames With Out-Of-Range Length Errors */
+#define RX_LONG_CNT 0x00000400 /* RX Frames With Frame Too Long Errors */
+#define RX_MACCTL_CNT 0x00000800 /* MAC Control RX Frames Received */
+#define RX_OPCODE_CTL 0x00001000 /* Unsupported Op-Code RX Frames Received */
+#define RX_PAUSE_CNT 0x00002000 /* PAUSEMAC Control RX Frames Received */
+#define RX_ALLF_CNT 0x00004000 /* All RX Frames Received */
+#define RX_ALLO_CNT 0x00008000 /* All RX Octets Received */
+#define RX_TYPED_CNT 0x00010000 /* Typed RX Frames Received */
+#define RX_SHORT_CNT 0x00020000 /* RX Frame Fragments (< 64 Bytes) Received */
+#define RX_EQ64_CNT 0x00040000 /* 64-Byte RX Frames Received */
+#define RX_LT128_CNT 0x00080000 /* 65-127-Byte RX Frames Received */
+#define RX_LT256_CNT 0x00100000 /* 128-255-Byte RX Frames Received */
+#define RX_LT512_CNT 0x00200000 /* 256-511-Byte RX Frames Received */
+#define RX_LT1024_CNT 0x00400000 /* 512-1023-Byte RX Frames Received */
+#define RX_GE1024_CNT 0x00800000 /* 1024-Max-Byte RX Frames Received */
+
+/* EMAC_MMC_TIRQS and EMAC_MMC_TIRQE Masks */
+
+#define TX_OK_CNT 0x00000001 /* TX Frames Sent OK */
+#define TX_SCOLL_CNT 0x00000002 /* TX Frames With Single Collisions */
+#define TX_MCOLL_CNT 0x00000004 /* TX Frames With Multiple Collisions */
+#define TX_OCTET_CNT 0x00000008 /* TX Octets Sent OK */
+#define TX_DEFER_CNT 0x00000010 /* TX Frames With Deferred Transmission */
+#define TX_LATE_CNT 0x00000020 /* TX Frames With Late Collisions */
+#define TX_ABORTC_CNT 0x00000040 /* TX Frames Aborted Due To Excess Collisions */
+#define TX_LOST_CNT 0x00000080 /* TX Frames Lost Due To Internal MAC TX Error */
+#define TX_CRS_CNT 0x00000100 /* TX Frames With Carrier Sense Errors */
+#define TX_UNI_CNT 0x00000200 /* Unicast TX Frames Sent */
+#define TX_MULTI_CNT 0x00000400 /* Multicast TX Frames Sent */
+#define TX_BROAD_CNT 0x00000800 /* Broadcast TX Frames Sent */
+#define TX_EXDEF_CTL 0x00001000 /* TX Frames With Excessive Deferral */
+#define TX_MACCTL_CNT 0x00002000 /* MAC Control TX Frames Sent */
+#define TX_ALLF_CNT 0x00004000 /* All TX Frames Sent */
+#define TX_ALLO_CNT 0x00008000 /* All TX Octets Sent */
+#define TX_EQ64_CNT 0x00010000 /* 64-Byte TX Frames Sent */
+#define TX_LT128_CNT 0x00020000 /* 65-127-Byte TX Frames Sent */
+#define TX_LT256_CNT 0x00040000 /* 128-255-Byte TX Frames Sent */
+#define TX_LT512_CNT 0x00080000 /* 256-511-Byte TX Frames Sent */
+#define TX_LT1024_CNT 0x00100000 /* 512-1023-Byte TX Frames Sent */
+#define TX_GE1024_CNT 0x00200000 /* 1024-Max-Byte TX Frames Sent */
+#define TX_ABORT_CNT 0x00400000 /* TX Frames Aborted */
+
+/* SDH Registers */
+
+#define SDH_PWR_CTL 0xFFC03900 /* SDH Power Control */
+#define SDH_CLK_CTL 0xFFC03904 /* SDH Clock Control */
+#define SDH_ARGUMENT 0xFFC03908 /* SDH Argument */
+#define SDH_COMMAND 0xFFC0390C /* SDH Command */
+#define SDH_RESP_CMD 0xFFC03910 /* SDH Response Command */
+#define SDH_RESPONSE0 0xFFC03914 /* SDH Response0 */
+#define SDH_RESPONSE1 0xFFC03918 /* SDH Response1 */
+#define SDH_RESPONSE2 0xFFC0391C /* SDH Response2 */
+#define SDH_RESPONSE3 0xFFC03920 /* SDH Response3 */
+#define SDH_DATA_TIMER 0xFFC03924 /* SDH Data Timer */
+#define SDH_DATA_LGTH 0xFFC03928 /* SDH Data Length */
+#define SDH_DATA_CTL 0xFFC0392C /* SDH Data Control */
+#define SDH_DATA_CNT 0xFFC03930 /* SDH Data Counter */
+#define SDH_STATUS 0xFFC03934 /* SDH Status */
+#define SDH_STATUS_CLR 0xFFC03938 /* SDH Status Clear */
+#define SDH_MASK0 0xFFC0393C /* SDH Interrupt0 Mask */
+#define SDH_MASK1 0xFFC03940 /* SDH Interrupt1 Mask */
+#define SDH_FIFO_CNT 0xFFC03948 /* SDH FIFO Counter */
+#define SDH_FIFO 0xFFC03980 /* SDH Data FIFO */
+#define SDH_E_STATUS 0xFFC039C0 /* SDH Exception Status */
+#define SDH_E_MASK 0xFFC039C4 /* SDH Exception Mask */
+#define SDH_CFG 0xFFC039C8 /* SDH Configuration */
+#define SDH_RD_WAIT_EN 0xFFC039CC /* SDH Read Wait Enable */
+#define SDH_PID0 0xFFC039D0 /* SDH Peripheral Identification0 */
+#define SDH_PID1 0xFFC039D4 /* SDH Peripheral Identification1 */
+#define SDH_PID2 0xFFC039D8 /* SDH Peripheral Identification2 */
+#define SDH_PID3 0xFFC039DC /* SDH Peripheral Identification3 */
+#define SDH_PID4 0xFFC039E0 /* SDH Peripheral Identification4 */
+#define SDH_PID5 0xFFC039E4 /* SDH Peripheral Identification5 */
+#define SDH_PID6 0xFFC039E8 /* SDH Peripheral Identification6 */
+#define SDH_PID7 0xFFC039EC /* SDH Peripheral Identification7 */
+
+/* Removable Storage Interface Registers */
+
+#define RSI_PWR_CONTROL 0xFFC03800 /* RSI Power Control Register */
+#define RSI_CLK_CONTROL 0xFFC03804 /* RSI Clock Control Register */
+#define RSI_ARGUMENT 0xFFC03808 /* RSI Argument Register */
+#define RSI_COMMAND 0xFFC0380C /* RSI Command Register */
+#define RSI_RESP_CMD 0xFFC03810 /* RSI Response Command Register */
+#define RSI_RESPONSE0 0xFFC03814 /* RSI Response Register */
+#define RSI_RESPONSE1 0xFFC03818 /* RSI Response Register */
+#define RSI_RESPONSE2 0xFFC0381C /* RSI Response Register */
+#define RSI_RESPONSE3 0xFFC03820 /* RSI Response Register */
+#define RSI_DATA_TIMER 0xFFC03824 /* RSI Data Timer Register */
+#define RSI_DATA_LGTH 0xFFC03828 /* RSI Data Length Register */
+#define RSI_DATA_CONTROL 0xFFC0382C /* RSI Data Control Register */
+#define RSI_DATA_CNT 0xFFC03830 /* RSI Data Counter Register */
+#define RSI_STATUS 0xFFC03834 /* RSI Status Register */
+#define RSI_STATUSCL 0xFFC03838 /* RSI Status Clear Register */
+#define RSI_MASK0 0xFFC0383C /* RSI Interrupt 0 Mask Register */
+#define RSI_MASK1 0xFFC03840 /* RSI Interrupt 1 Mask Register */
+#define RSI_FIFO_CNT 0xFFC03848 /* RSI FIFO Counter Register */
+#define RSI_CEATA_CONTROL 0xFFC0384C /* RSI CEATA Register */
+#define RSI_FIFO 0xFFC03880 /* RSI Data FIFO Register */
+#define RSI_ESTAT 0xFFC038C0 /* RSI Exception Status Register */
+#define RSI_EMASK 0xFFC038C4 /* RSI Exception Mask Register */
+#define RSI_CONFIG 0xFFC038C8 /* RSI Configuration Register */
+#define RSI_RD_WAIT_EN 0xFFC038CC /* RSI Read Wait Enable Register */
+#define RSI_PID0 0xFFC03FE0 /* RSI Peripheral ID Register 0 */
+#define RSI_PID1 0xFFC03FE4 /* RSI Peripheral ID Register 1 */
+#define RSI_PID2 0xFFC03FE8 /* RSI Peripheral ID Register 2 */
+#define RSI_PID3 0xFFC03FEC /* RSI Peripheral ID Register 3 */
+#define RSI_PID4 0xFFC03FF0 /* RSI Peripheral ID Register 4 */
+#define RSI_PID5 0xFFC03FF4 /* RSI Peripheral ID Register 5 */
+#define RSI_PID6 0xFFC03FF8 /* RSI Peripheral ID Register 6 */
+#define RSI_PID7 0xFFC03FFC /* RSI Peripheral ID Register 7 */
+
+/* PTP TSYNC Registers */
+
+#define EMAC_PTP_CTL 0xFFC030A0 /* PTP Block Control */
+#define EMAC_PTP_IE 0xFFC030A4 /* PTP Block Interrupt Enable */
+#define EMAC_PTP_ISTAT 0xFFC030A8 /* PTP Block Interrupt Status */
+#define EMAC_PTP_FOFF 0xFFC030AC /* PTP Filter offset Register */
+#define EMAC_PTP_FV1 0xFFC030B0 /* PTP Filter Value Register 1 */
+#define EMAC_PTP_FV2 0xFFC030B4 /* PTP Filter Value Register 2 */
+#define EMAC_PTP_FV3 0xFFC030B8 /* PTP Filter Value Register 3 */
+#define EMAC_PTP_ADDEND 0xFFC030BC /* PTP Addend for Frequency Compensation */
+#define EMAC_PTP_ACCR 0xFFC030C0 /* PTP Accumulator for Frequency Compensation */
+#define EMAC_PTP_OFFSET 0xFFC030C4 /* PTP Time Offset Register */
+#define EMAC_PTP_TIMELO 0xFFC030C8 /* PTP Precision Clock Time Low */
+#define EMAC_PTP_TIMEHI 0xFFC030CC /* PTP Precision Clock Time High */
+#define EMAC_PTP_RXSNAPLO 0xFFC030D0 /* PTP Receive Snapshot Register Low */
+#define EMAC_PTP_RXSNAPHI 0xFFC030D4 /* PTP Receive Snapshot Register High */
+#define EMAC_PTP_TXSNAPLO 0xFFC030D8 /* PTP Transmit Snapshot Register Low */
+#define EMAC_PTP_TXSNAPHI 0xFFC030DC /* PTP Transmit Snapshot Register High */
+#define EMAC_PTP_ALARMLO 0xFFC030E0 /* PTP Alarm time Low */
+#define EMAC_PTP_ALARMHI 0xFFC030E4 /* PTP Alarm time High */
+#define EMAC_PTP_ID_OFF 0xFFC030E8 /* PTP Capture ID offset register */
+#define EMAC_PTP_ID_SNAP 0xFFC030EC /* PTP Capture ID register */
+#define EMAC_PTP_PPS_STARTLO 0xFFC030F0 /* PPS Start Time Low */
+#define EMAC_PTP_PPS_STARTHI 0xFFC030F4 /* PPS Start Time High */
+#define EMAC_PTP_PPS_PERIOD 0xFFC030F8 /* PPS Count Register */
+
+/* ********************************************************** */
+/* SINGLE BIT MACRO PAIRS (bit mask and negated one) */
+/* and MULTI BIT READ MACROS */
+/* ********************************************************** */
+
+/* Bit masks for SDH_COMMAND */
+
+#define CMD_IDX 0x3f /* Command Index */
+#define CMD_RSP 0x40 /* Response */
+#define CMD_L_RSP 0x80 /* Long Response */
+#define CMD_INT_E 0x100 /* Command Interrupt */
+#define CMD_PEND_E 0x200 /* Command Pending */
+#define CMD_E 0x400 /* Command Enable */
+
+/* Bit masks for SDH_PWR_CTL */
+
+#define PWR_ON 0x3 /* Power On */
+#if 0
+#define TBD 0x3c /* TBD */
+#endif
+#define SD_CMD_OD 0x40 /* Open Drain Output */
+#define ROD_CTL 0x80 /* Rod Control */
+
+/* Bit masks for SDH_CLK_CTL */
+
+#define CLKDIV 0xff /* MC_CLK Divisor */
+#define CLK_E 0x100 /* MC_CLK Bus Clock Enable */
+#define PWR_SV_E 0x200 /* Power Save Enable */
+#define CLKDIV_BYPASS 0x400 /* Bypass Divisor */
+#define WIDE_BUS 0x800 /* Wide Bus Mode Enable */
+
+/* Bit masks for SDH_RESP_CMD */
+
+#define RESP_CMD 0x3f /* Response Command */
+
+/* Bit masks for SDH_DATA_CTL */
+
+#define DTX_E 0x1 /* Data Transfer Enable */
+#define DTX_DIR 0x2 /* Data Transfer Direction */
+#define DTX_MODE 0x4 /* Data Transfer Mode */
+#define DTX_DMA_E 0x8 /* Data Transfer DMA Enable */
+#define DTX_BLK_LGTH 0xf0 /* Data Transfer Block Length */
+
+/* Bit masks for SDH_STATUS */
+
+#define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */
+#define DAT_CRC_FAIL 0x2 /* Data CRC Fail */
+#define CMD_TIME_OUT 0x4 /* CMD Time Out */
+#define DAT_TIME_OUT 0x8 /* Data Time Out */
+#define TX_UNDERRUN 0x10 /* Transmit Underrun */
+#define RX_OVERRUN 0x20 /* Receive Overrun */
+#define CMD_RESP_END 0x40 /* CMD Response End */
+#define CMD_SENT 0x80 /* CMD Sent */
+#define DAT_END 0x100 /* Data End */
+#define START_BIT_ERR 0x200 /* Start Bit Error */
+#define DAT_BLK_END 0x400 /* Data Block End */
+#define CMD_ACT 0x800 /* CMD Active */
+#define TX_ACT 0x1000 /* Transmit Active */
+#define RX_ACT 0x2000 /* Receive Active */
+#define TX_FIFO_STAT 0x4000 /* Transmit FIFO Status */
+#define RX_FIFO_STAT 0x8000 /* Receive FIFO Status */
+#define TX_FIFO_FULL 0x10000 /* Transmit FIFO Full */
+#define RX_FIFO_FULL 0x20000 /* Receive FIFO Full */
+#define TX_FIFO_ZERO 0x40000 /* Transmit FIFO Empty */
+#define RX_DAT_ZERO 0x80000 /* Receive FIFO Empty */
+#define TX_DAT_RDY 0x100000 /* Transmit Data Available */
+#define RX_FIFO_RDY 0x200000 /* Receive Data Available */
+
+/* Bit masks for SDH_STATUS_CLR */
+
+#define CMD_CRC_FAIL_STAT 0x1 /* CMD CRC Fail Status */
+#define DAT_CRC_FAIL_STAT 0x2 /* Data CRC Fail Status */
+#define CMD_TIMEOUT_STAT 0x4 /* CMD Time Out Status */
+#define DAT_TIMEOUT_STAT 0x8 /* Data Time Out status */
+#define TX_UNDERRUN_STAT 0x10 /* Transmit Underrun Status */
+#define RX_OVERRUN_STAT 0x20 /* Receive Overrun Status */
+#define CMD_RESP_END_STAT 0x40 /* CMD Response End Status */
+#define CMD_SENT_STAT 0x80 /* CMD Sent Status */
+#define DAT_END_STAT 0x100 /* Data End Status */
+#define START_BIT_ERR_STAT 0x200 /* Start Bit Error Status */
+#define DAT_BLK_END_STAT 0x400 /* Data Block End Status */
+
+/* Bit masks for SDH_MASK0 */
+
+#define CMD_CRC_FAIL_MASK 0x1 /* CMD CRC Fail Mask */
+#define DAT_CRC_FAIL_MASK 0x2 /* Data CRC Fail Mask */
+#define CMD_TIMEOUT_MASK 0x4 /* CMD Time Out Mask */
+#define DAT_TIMEOUT_MASK 0x8 /* Data Time Out Mask */
+#define TX_UNDERRUN_MASK 0x10 /* Transmit Underrun Mask */
+#define RX_OVERRUN_MASK 0x20 /* Receive Overrun Mask */
+#define CMD_RESP_END_MASK 0x40 /* CMD Response End Mask */
+#define CMD_SENT_MASK 0x80 /* CMD Sent Mask */
+#define DAT_END_MASK 0x100 /* Data End Mask */
+#define START_BIT_ERR_MASK 0x200 /* Start Bit Error Mask */
+#define DAT_BLK_END_MASK 0x400 /* Data Block End Mask */
+#define CMD_ACT_MASK 0x800 /* CMD Active Mask */
+#define TX_ACT_MASK 0x1000 /* Transmit Active Mask */
+#define RX_ACT_MASK 0x2000 /* Receive Active Mask */
+#define TX_FIFO_STAT_MASK 0x4000 /* Transmit FIFO Status Mask */
+#define RX_FIFO_STAT_MASK 0x8000 /* Receive FIFO Status Mask */
+#define TX_FIFO_FULL_MASK 0x10000 /* Transmit FIFO Full Mask */
+#define RX_FIFO_FULL_MASK 0x20000 /* Receive FIFO Full Mask */
+#define TX_FIFO_ZERO_MASK 0x40000 /* Transmit FIFO Empty Mask */
+#define RX_DAT_ZERO_MASK 0x80000 /* Receive FIFO Empty Mask */
+#define TX_DAT_RDY_MASK 0x100000 /* Transmit Data Available Mask */
+#define RX_FIFO_RDY_MASK 0x200000 /* Receive Data Available Mask */
+
+/* Bit masks for SDH_FIFO_CNT */
+
+#define FIFO_COUNT 0x7fff /* FIFO Count */
+
+/* Bit masks for SDH_E_STATUS */
+
+#define SDIO_INT_DET 0x2 /* SDIO Int Detected */
+#define SD_CARD_DET 0x10 /* SD Card Detect */
+
+/* Bit masks for SDH_E_MASK */
+
+#define SDIO_MSK 0x2 /* Mask SDIO Int Detected */
+#define SCD_MSK 0x40 /* Mask Card Detect */
+
+/* Bit masks for SDH_CFG */
+
+#define CLKS_EN 0x1 /* Clocks Enable */
+#define SD4E 0x4 /* SDIO 4-Bit Enable */
+#define MWE 0x8 /* Moving Window Enable */
+#define SD_RST 0x10 /* SDMMC Reset */
+#define PUP_SDDAT 0x20 /* Pull-up SD_DAT */
+#define PUP_SDDAT3 0x40 /* Pull-up SD_DAT3 */
+#define PD_SDDAT3 0x80 /* Pull-down SD_DAT3 */
+
+/* Bit masks for SDH_RD_WAIT_EN */
+
+#define RWR 0x1 /* Read Wait Request */
+
+#endif /* _DEF_BF518_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
new file mode 100644
index 000000000000..1bec8d1c2a73
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/defBF51x_base.h
@@ -0,0 +1,1940 @@
+/*
+ * File: include/asm-blackfin/mach-bf518/defBF51x_base.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DEF_BF51X_H
+#define _DEF_BF51X_H
+
+
+/* ************************************************************** */
+/* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF51x */
+/* ************************************************************** */
+
+/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
+#define PLL_CTL 0xFFC00000 /* PLL Control Register */
+#define PLL_DIV 0xFFC00004 /* PLL Divide Register */
+#define VR_CTL 0xFFC00008 /* Voltage Regulator Control Register */
+#define PLL_STAT 0xFFC0000C /* PLL Status Register */
+#define PLL_LOCKCNT 0xFFC00010 /* PLL Lock Count Register */
+#define CHIPID 0xFFC00014 /* Device ID Register */
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
+#define SWRST 0xFFC00100 /* Software Reset Register */
+#define SYSCR 0xFFC00104 /* System Configuration Register */
+#define SIC_RVECT 0xFFC00108 /* Interrupt Reset Vector Address Register */
+
+#define SIC_IMASK0 0xFFC0010C /* Interrupt Mask Register */
+#define SIC_IAR0 0xFFC00110 /* Interrupt Assignment Register 0 */
+#define SIC_IAR1 0xFFC00114 /* Interrupt Assignment Register 1 */
+#define SIC_IAR2 0xFFC00118 /* Interrupt Assignment Register 2 */
+#define SIC_IAR3 0xFFC0011C /* Interrupt Assignment Register 3 */
+#define SIC_ISR0 0xFFC00120 /* Interrupt Status Register */
+#define SIC_IWR0 0xFFC00124 /* Interrupt Wakeup Register */
+
+/* SIC Additions to ADSP-BF51x (0xFFC0014C - 0xFFC00162) */
+#define SIC_IMASK1 0xFFC0014C /* Interrupt Mask register of SIC2 */
+#define SIC_IAR4 0xFFC00150 /* Interrupt Assignment register4 */
+#define SIC_IAR5 0xFFC00154 /* Interrupt Assignment register5 */
+#define SIC_IAR6 0xFFC00158 /* Interrupt Assignment register6 */
+#define SIC_IAR7 0xFFC0015C /* Interrupt Assignment register7 */
+#define SIC_ISR1 0xFFC00160 /* Interrupt Statur register */
+#define SIC_IWR1 0xFFC00164 /* Interrupt Wakeup register */
+
+
+/* Watchdog Timer (0xFFC00200 - 0xFFC002FF) */
+#define WDOG_CTL 0xFFC00200 /* Watchdog Control Register */
+#define WDOG_CNT 0xFFC00204 /* Watchdog Count Register */
+#define WDOG_STAT 0xFFC00208 /* Watchdog Status Register */
+
+
+/* Real Time Clock (0xFFC00300 - 0xFFC003FF) */
+#define RTC_STAT 0xFFC00300 /* RTC Status Register */
+#define RTC_ICTL 0xFFC00304 /* RTC Interrupt Control Register */
+#define RTC_ISTAT 0xFFC00308 /* RTC Interrupt Status Register */
+#define RTC_SWCNT 0xFFC0030C /* RTC Stopwatch Count Register */
+#define RTC_ALARM 0xFFC00310 /* RTC Alarm Time Register */
+#define RTC_FAST 0xFFC00314 /* RTC Prescaler Enable Register */
+#define RTC_PREN 0xFFC00314 /* RTC Prescaler Enable Alternate Macro */
+
+
+/* UART0 Controller (0xFFC00400 - 0xFFC004FF) */
+#define UART0_THR 0xFFC00400 /* Transmit Holding register */
+#define UART0_RBR 0xFFC00400 /* Receive Buffer register */
+#define UART0_DLL 0xFFC00400 /* Divisor Latch (Low-Byte) */
+#define UART0_IER 0xFFC00404 /* Interrupt Enable Register */
+#define UART0_DLH 0xFFC00404 /* Divisor Latch (High-Byte) */
+#define UART0_IIR 0xFFC00408 /* Interrupt Identification Register */
+#define UART0_LCR 0xFFC0040C /* Line Control Register */
+#define UART0_MCR 0xFFC00410 /* Modem Control Register */
+#define UART0_LSR 0xFFC00414 /* Line Status Register */
+#define UART0_MSR 0xFFC00418 /* Modem Status Register */
+#define UART0_SCR 0xFFC0041C /* SCR Scratch Register */
+#define UART0_GCTL 0xFFC00424 /* Global Control Register */
+
+/* SPI0 Controller (0xFFC00500 - 0xFFC005FF) */
+#define SPI0_REGBASE 0xFFC00500
+#define SPI0_CTL 0xFFC00500 /* SPI Control Register */
+#define SPI0_FLG 0xFFC00504 /* SPI Flag register */
+#define SPI0_STAT 0xFFC00508 /* SPI Status register */
+#define SPI0_TDBR 0xFFC0050C /* SPI Transmit Data Buffer Register */
+#define SPI0_RDBR 0xFFC00510 /* SPI Receive Data Buffer Register */
+#define SPI0_BAUD 0xFFC00514 /* SPI Baud rate Register */
+#define SPI0_SHADOW 0xFFC00518 /* SPI_RDBR Shadow Register */
+
+/* SPI1 Controller (0xFFC03400 - 0xFFC034FF) */
+#define SPI1_REGBASE 0xFFC03400
+#define SPI1_CTL 0xFFC03400 /* SPI Control Register */
+#define SPI1_FLG 0xFFC03404 /* SPI Flag register */
+#define SPI1_STAT 0xFFC03408 /* SPI Status register */
+#define SPI1_TDBR 0xFFC0340C /* SPI Transmit Data Buffer Register */
+#define SPI1_RDBR 0xFFC03410 /* SPI Receive Data Buffer Register */
+#define SPI1_BAUD 0xFFC03414 /* SPI Baud rate Register */
+#define SPI1_SHADOW 0xFFC03418 /* SPI_RDBR Shadow Register */
+
+/* TIMER0-7 Registers (0xFFC00600 - 0xFFC006FF) */
+#define TIMER0_CONFIG 0xFFC00600 /* Timer 0 Configuration Register */
+#define TIMER0_COUNTER 0xFFC00604 /* Timer 0 Counter Register */
+#define TIMER0_PERIOD 0xFFC00608 /* Timer 0 Period Register */
+#define TIMER0_WIDTH 0xFFC0060C /* Timer 0 Width Register */
+
+#define TIMER1_CONFIG 0xFFC00610 /* Timer 1 Configuration Register */
+#define TIMER1_COUNTER 0xFFC00614 /* Timer 1 Counter Register */
+#define TIMER1_PERIOD 0xFFC00618 /* Timer 1 Period Register */
+#define TIMER1_WIDTH 0xFFC0061C /* Timer 1 Width Register */
+
+#define TIMER2_CONFIG 0xFFC00620 /* Timer 2 Configuration Register */
+#define TIMER2_COUNTER 0xFFC00624 /* Timer 2 Counter Register */
+#define TIMER2_PERIOD 0xFFC00628 /* Timer 2 Period Register */
+#define TIMER2_WIDTH 0xFFC0062C /* Timer 2 Width Register */
+
+#define TIMER3_CONFIG 0xFFC00630 /* Timer 3 Configuration Register */
+#define TIMER3_COUNTER 0xFFC00634 /* Timer 3 Counter Register */
+#define TIMER3_PERIOD 0xFFC00638 /* Timer 3 Period Register */
+#define TIMER3_WIDTH 0xFFC0063C /* Timer 3 Width Register */
+
+#define TIMER4_CONFIG 0xFFC00640 /* Timer 4 Configuration Register */
+#define TIMER4_COUNTER 0xFFC00644 /* Timer 4 Counter Register */
+#define TIMER4_PERIOD 0xFFC00648 /* Timer 4 Period Register */
+#define TIMER4_WIDTH 0xFFC0064C /* Timer 4 Width Register */
+
+#define TIMER5_CONFIG 0xFFC00650 /* Timer 5 Configuration Register */
+#define TIMER5_COUNTER 0xFFC00654 /* Timer 5 Counter Register */
+#define TIMER5_PERIOD 0xFFC00658 /* Timer 5 Period Register */
+#define TIMER5_WIDTH 0xFFC0065C /* Timer 5 Width Register */
+
+#define TIMER6_CONFIG 0xFFC00660 /* Timer 6 Configuration Register */
+#define TIMER6_COUNTER 0xFFC00664 /* Timer 6 Counter Register */
+#define TIMER6_PERIOD 0xFFC00668 /* Timer 6 Period Register */
+#define TIMER6_WIDTH 0xFFC0066C /* Timer 6 Width Register */
+
+#define TIMER7_CONFIG 0xFFC00670 /* Timer 7 Configuration Register */
+#define TIMER7_COUNTER 0xFFC00674 /* Timer 7 Counter Register */
+#define TIMER7_PERIOD 0xFFC00678 /* Timer 7 Period Register */
+#define TIMER7_WIDTH 0xFFC0067C /* Timer 7 Width Register */
+
+#define TIMER_ENABLE 0xFFC00680 /* Timer Enable Register */
+#define TIMER_DISABLE 0xFFC00684 /* Timer Disable Register */
+#define TIMER_STATUS 0xFFC00688 /* Timer Status Register */
+
+/* General Purpose I/O Port F (0xFFC00700 - 0xFFC007FF) */
+#define PORTFIO 0xFFC00700 /* Port F I/O Pin State Specify Register */
+#define PORTFIO_CLEAR 0xFFC00704 /* Port F I/O Peripheral Interrupt Clear Register */
+#define PORTFIO_SET 0xFFC00708 /* Port F I/O Peripheral Interrupt Set Register */
+#define PORTFIO_TOGGLE 0xFFC0070C /* Port F I/O Pin State Toggle Register */
+#define PORTFIO_MASKA 0xFFC00710 /* Port F I/O Mask State Specify Interrupt A Register */
+#define PORTFIO_MASKA_CLEAR 0xFFC00714 /* Port F I/O Mask Disable Interrupt A Register */
+#define PORTFIO_MASKA_SET 0xFFC00718 /* Port F I/O Mask Enable Interrupt A Register */
+#define PORTFIO_MASKA_TOGGLE 0xFFC0071C /* Port F I/O Mask Toggle Enable Interrupt A Register */
+#define PORTFIO_MASKB 0xFFC00720 /* Port F I/O Mask State Specify Interrupt B Register */
+#define PORTFIO_MASKB_CLEAR 0xFFC00724 /* Port F I/O Mask Disable Interrupt B Register */
+#define PORTFIO_MASKB_SET 0xFFC00728 /* Port F I/O Mask Enable Interrupt B Register */
+#define PORTFIO_MASKB_TOGGLE 0xFFC0072C /* Port F I/O Mask Toggle Enable Interrupt B Register */
+#define PORTFIO_DIR 0xFFC00730 /* Port F I/O Direction Register */
+#define PORTFIO_POLAR 0xFFC00734 /* Port F I/O Source Polarity Register */
+#define PORTFIO_EDGE 0xFFC00738 /* Port F I/O Source Sensitivity Register */
+#define PORTFIO_BOTH 0xFFC0073C /* Port F I/O Set on BOTH Edges Register */
+#define PORTFIO_INEN 0xFFC00740 /* Port F I/O Input Enable Register */
+
+/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
+#define SPORT0_TCR1 0xFFC00800 /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_TCR2 0xFFC00804 /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_TCLKDIV 0xFFC00808 /* SPORT0 Transmit Clock Divider */
+#define SPORT0_TFSDIV 0xFFC0080C /* SPORT0 Transmit Frame Sync Divider */
+#define SPORT0_TX 0xFFC00810 /* SPORT0 TX Data Register */
+#define SPORT0_RX 0xFFC00818 /* SPORT0 RX Data Register */
+#define SPORT0_RCR1 0xFFC00820 /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_RCR2 0xFFC00824 /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_RCLKDIV 0xFFC00828 /* SPORT0 Receive Clock Divider */
+#define SPORT0_RFSDIV 0xFFC0082C /* SPORT0 Receive Frame Sync Divider */
+#define SPORT0_STAT 0xFFC00830 /* SPORT0 Status Register */
+#define SPORT0_CHNL 0xFFC00834 /* SPORT0 Current Channel Register */
+#define SPORT0_MCMC1 0xFFC00838 /* SPORT0 Multi-Channel Configuration Register 1 */
+#define SPORT0_MCMC2 0xFFC0083C /* SPORT0 Multi-Channel Configuration Register 2 */
+#define SPORT0_MTCS0 0xFFC00840 /* SPORT0 Multi-Channel Transmit Select Register 0 */
+#define SPORT0_MTCS1 0xFFC00844 /* SPORT0 Multi-Channel Transmit Select Register 1 */
+#define SPORT0_MTCS2 0xFFC00848 /* SPORT0 Multi-Channel Transmit Select Register 2 */
+#define SPORT0_MTCS3 0xFFC0084C /* SPORT0 Multi-Channel Transmit Select Register 3 */
+#define SPORT0_MRCS0 0xFFC00850 /* SPORT0 Multi-Channel Receive Select Register 0 */
+#define SPORT0_MRCS1 0xFFC00854 /* SPORT0 Multi-Channel Receive Select Register 1 */
+#define SPORT0_MRCS2 0xFFC00858 /* SPORT0 Multi-Channel Receive Select Register 2 */
+#define SPORT0_MRCS3 0xFFC0085C /* SPORT0 Multi-Channel Receive Select Register 3 */
+
+/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
+#define SPORT1_TCR1 0xFFC00900 /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_TCR2 0xFFC00904 /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_TCLKDIV 0xFFC00908 /* SPORT1 Transmit Clock Divider */
+#define SPORT1_TFSDIV 0xFFC0090C /* SPORT1 Transmit Frame Sync Divider */
+#define SPORT1_TX 0xFFC00910 /* SPORT1 TX Data Register */
+#define SPORT1_RX 0xFFC00918 /* SPORT1 RX Data Register */
+#define SPORT1_RCR1 0xFFC00920 /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_RCR2 0xFFC00924 /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_RCLKDIV 0xFFC00928 /* SPORT1 Receive Clock Divider */
+#define SPORT1_RFSDIV 0xFFC0092C /* SPORT1 Receive Frame Sync Divider */
+#define SPORT1_STAT 0xFFC00930 /* SPORT1 Status Register */
+#define SPORT1_CHNL 0xFFC00934 /* SPORT1 Current Channel Register */
+#define SPORT1_MCMC1 0xFFC00938 /* SPORT1 Multi-Channel Configuration Register 1 */
+#define SPORT1_MCMC2 0xFFC0093C /* SPORT1 Multi-Channel Configuration Register 2 */
+#define SPORT1_MTCS0 0xFFC00940 /* SPORT1 Multi-Channel Transmit Select Register 0 */
+#define SPORT1_MTCS1 0xFFC00944 /* SPORT1 Multi-Channel Transmit Select Register 1 */
+#define SPORT1_MTCS2 0xFFC00948 /* SPORT1 Multi-Channel Transmit Select Register 2 */
+#define SPORT1_MTCS3 0xFFC0094C /* SPORT1 Multi-Channel Transmit Select Register 3 */
+#define SPORT1_MRCS0 0xFFC00950 /* SPORT1 Multi-Channel Receive Select Register 0 */
+#define SPORT1_MRCS1 0xFFC00954 /* SPORT1 Multi-Channel Receive Select Register 1 */
+#define SPORT1_MRCS2 0xFFC00958 /* SPORT1 Multi-Channel Receive Select Register 2 */
+#define SPORT1_MRCS3 0xFFC0095C /* SPORT1 Multi-Channel Receive Select Register 3 */
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
+#define EBIU_AMGCTL 0xFFC00A00 /* Asynchronous Memory Global Control Register */
+#define EBIU_AMBCTL0 0xFFC00A04 /* Asynchronous Memory Bank Control Register 0 */
+#define EBIU_AMBCTL1 0xFFC00A08 /* Asynchronous Memory Bank Control Register 1 */
+#define EBIU_SDGCTL 0xFFC00A10 /* SDRAM Global Control Register */
+#define EBIU_SDBCTL 0xFFC00A14 /* SDRAM Bank Control Register */
+#define EBIU_SDRRC 0xFFC00A18 /* SDRAM Refresh Rate Control Register */
+#define EBIU_SDSTAT 0xFFC00A1C /* SDRAM Status Register */
+
+/* DMA Traffic Control Registers */
+#define DMA_TC_PER 0xFFC00B0C /* Traffic Control Periods Register */
+#define DMA_TC_CNT 0xFFC00B10 /* Traffic Control Current Counts Register */
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define DMA_TCPER 0xFFC00B0C /* Traffic Control Periods Register */
+#define DMA_TCCNT 0xFFC00B10 /* Traffic Control Current Counts Register */
+
+/* DMA Controller (0xFFC00C00 - 0xFFC00FFF) */
+#define DMA0_NEXT_DESC_PTR 0xFFC00C00 /* DMA Channel 0 Next Descriptor Pointer Register */
+#define DMA0_START_ADDR 0xFFC00C04 /* DMA Channel 0 Start Address Register */
+#define DMA0_CONFIG 0xFFC00C08 /* DMA Channel 0 Configuration Register */
+#define DMA0_X_COUNT 0xFFC00C10 /* DMA Channel 0 X Count Register */
+#define DMA0_X_MODIFY 0xFFC00C14 /* DMA Channel 0 X Modify Register */
+#define DMA0_Y_COUNT 0xFFC00C18 /* DMA Channel 0 Y Count Register */
+#define DMA0_Y_MODIFY 0xFFC00C1C /* DMA Channel 0 Y Modify Register */
+#define DMA0_CURR_DESC_PTR 0xFFC00C20 /* DMA Channel 0 Current Descriptor Pointer Register */
+#define DMA0_CURR_ADDR 0xFFC00C24 /* DMA Channel 0 Current Address Register */
+#define DMA0_IRQ_STATUS 0xFFC00C28 /* DMA Channel 0 Interrupt/Status Register */
+#define DMA0_PERIPHERAL_MAP 0xFFC00C2C /* DMA Channel 0 Peripheral Map Register */
+#define DMA0_CURR_X_COUNT 0xFFC00C30 /* DMA Channel 0 Current X Count Register */
+#define DMA0_CURR_Y_COUNT 0xFFC00C38 /* DMA Channel 0 Current Y Count Register */
+
+#define DMA1_NEXT_DESC_PTR 0xFFC00C40 /* DMA Channel 1 Next Descriptor Pointer Register */
+#define DMA1_START_ADDR 0xFFC00C44 /* DMA Channel 1 Start Address Register */
+#define DMA1_CONFIG 0xFFC00C48 /* DMA Channel 1 Configuration Register */
+#define DMA1_X_COUNT 0xFFC00C50 /* DMA Channel 1 X Count Register */
+#define DMA1_X_MODIFY 0xFFC00C54 /* DMA Channel 1 X Modify Register */
+#define DMA1_Y_COUNT 0xFFC00C58 /* DMA Channel 1 Y Count Register */
+#define DMA1_Y_MODIFY 0xFFC00C5C /* DMA Channel 1 Y Modify Register */
+#define DMA1_CURR_DESC_PTR 0xFFC00C60 /* DMA Channel 1 Current Descriptor Pointer Register */
+#define DMA1_CURR_ADDR 0xFFC00C64 /* DMA Channel 1 Current Address Register */
+#define DMA1_IRQ_STATUS 0xFFC00C68 /* DMA Channel 1 Interrupt/Status Register */
+#define DMA1_PERIPHERAL_MAP 0xFFC00C6C /* DMA Channel 1 Peripheral Map Register */
+#define DMA1_CURR_X_COUNT 0xFFC00C70 /* DMA Channel 1 Current X Count Register */
+#define DMA1_CURR_Y_COUNT 0xFFC00C78 /* DMA Channel 1 Current Y Count Register */
+
+#define DMA2_NEXT_DESC_PTR 0xFFC00C80 /* DMA Channel 2 Next Descriptor Pointer Register */
+#define DMA2_START_ADDR 0xFFC00C84 /* DMA Channel 2 Start Address Register */
+#define DMA2_CONFIG 0xFFC00C88 /* DMA Channel 2 Configuration Register */
+#define DMA2_X_COUNT 0xFFC00C90 /* DMA Channel 2 X Count Register */
+#define DMA2_X_MODIFY 0xFFC00C94 /* DMA Channel 2 X Modify Register */
+#define DMA2_Y_COUNT 0xFFC00C98 /* DMA Channel 2 Y Count Register */
+#define DMA2_Y_MODIFY 0xFFC00C9C /* DMA Channel 2 Y Modify Register */
+#define DMA2_CURR_DESC_PTR 0xFFC00CA0 /* DMA Channel 2 Current Descriptor Pointer Register */
+#define DMA2_CURR_ADDR 0xFFC00CA4 /* DMA Channel 2 Current Address Register */
+#define DMA2_IRQ_STATUS 0xFFC00CA8 /* DMA Channel 2 Interrupt/Status Register */
+#define DMA2_PERIPHERAL_MAP 0xFFC00CAC /* DMA Channel 2 Peripheral Map Register */
+#define DMA2_CURR_X_COUNT 0xFFC00CB0 /* DMA Channel 2 Current X Count Register */
+#define DMA2_CURR_Y_COUNT 0xFFC00CB8 /* DMA Channel 2 Current Y Count Register */
+
+#define DMA3_NEXT_DESC_PTR 0xFFC00CC0 /* DMA Channel 3 Next Descriptor Pointer Register */
+#define DMA3_START_ADDR 0xFFC00CC4 /* DMA Channel 3 Start Address Register */
+#define DMA3_CONFIG 0xFFC00CC8 /* DMA Channel 3 Configuration Register */
+#define DMA3_X_COUNT 0xFFC00CD0 /* DMA Channel 3 X Count Register */
+#define DMA3_X_MODIFY 0xFFC00CD4 /* DMA Channel 3 X Modify Register */
+#define DMA3_Y_COUNT 0xFFC00CD8 /* DMA Channel 3 Y Count Register */
+#define DMA3_Y_MODIFY 0xFFC00CDC /* DMA Channel 3 Y Modify Register */
+#define DMA3_CURR_DESC_PTR 0xFFC00CE0 /* DMA Channel 3 Current Descriptor Pointer Register */
+#define DMA3_CURR_ADDR 0xFFC00CE4 /* DMA Channel 3 Current Address Register */
+#define DMA3_IRQ_STATUS 0xFFC00CE8 /* DMA Channel 3 Interrupt/Status Register */
+#define DMA3_PERIPHERAL_MAP 0xFFC00CEC /* DMA Channel 3 Peripheral Map Register */
+#define DMA3_CURR_X_COUNT 0xFFC00CF0 /* DMA Channel 3 Current X Count Register */
+#define DMA3_CURR_Y_COUNT 0xFFC00CF8 /* DMA Channel 3 Current Y Count Register */
+
+#define DMA4_NEXT_DESC_PTR 0xFFC00D00 /* DMA Channel 4 Next Descriptor Pointer Register */
+#define DMA4_START_ADDR 0xFFC00D04 /* DMA Channel 4 Start Address Register */
+#define DMA4_CONFIG 0xFFC00D08 /* DMA Channel 4 Configuration Register */
+#define DMA4_X_COUNT 0xFFC00D10 /* DMA Channel 4 X Count Register */
+#define DMA4_X_MODIFY 0xFFC00D14 /* DMA Channel 4 X Modify Register */
+#define DMA4_Y_COUNT 0xFFC00D18 /* DMA Channel 4 Y Count Register */
+#define DMA4_Y_MODIFY 0xFFC00D1C /* DMA Channel 4 Y Modify Register */
+#define DMA4_CURR_DESC_PTR 0xFFC00D20 /* DMA Channel 4 Current Descriptor Pointer Register */
+#define DMA4_CURR_ADDR 0xFFC00D24 /* DMA Channel 4 Current Address Register */
+#define DMA4_IRQ_STATUS 0xFFC00D28 /* DMA Channel 4 Interrupt/Status Register */
+#define DMA4_PERIPHERAL_MAP 0xFFC00D2C /* DMA Channel 4 Peripheral Map Register */
+#define DMA4_CURR_X_COUNT 0xFFC00D30 /* DMA Channel 4 Current X Count Register */
+#define DMA4_CURR_Y_COUNT 0xFFC00D38 /* DMA Channel 4 Current Y Count Register */
+
+#define DMA5_NEXT_DESC_PTR 0xFFC00D40 /* DMA Channel 5 Next Descriptor Pointer Register */
+#define DMA5_START_ADDR 0xFFC00D44 /* DMA Channel 5 Start Address Register */
+#define DMA5_CONFIG 0xFFC00D48 /* DMA Channel 5 Configuration Register */
+#define DMA5_X_COUNT 0xFFC00D50 /* DMA Channel 5 X Count Register */
+#define DMA5_X_MODIFY 0xFFC00D54 /* DMA Channel 5 X Modify Register */
+#define DMA5_Y_COUNT 0xFFC00D58 /* DMA Channel 5 Y Count Register */
+#define DMA5_Y_MODIFY 0xFFC00D5C /* DMA Channel 5 Y Modify Register */
+#define DMA5_CURR_DESC_PTR 0xFFC00D60 /* DMA Channel 5 Current Descriptor Pointer Register */
+#define DMA5_CURR_ADDR 0xFFC00D64 /* DMA Channel 5 Current Address Register */
+#define DMA5_IRQ_STATUS 0xFFC00D68 /* DMA Channel 5 Interrupt/Status Register */
+#define DMA5_PERIPHERAL_MAP 0xFFC00D6C /* DMA Channel 5 Peripheral Map Register */
+#define DMA5_CURR_X_COUNT 0xFFC00D70 /* DMA Channel 5 Current X Count Register */
+#define DMA5_CURR_Y_COUNT 0xFFC00D78 /* DMA Channel 5 Current Y Count Register */
+
+#define DMA6_NEXT_DESC_PTR 0xFFC00D80 /* DMA Channel 6 Next Descriptor Pointer Register */
+#define DMA6_START_ADDR 0xFFC00D84 /* DMA Channel 6 Start Address Register */
+#define DMA6_CONFIG 0xFFC00D88 /* DMA Channel 6 Configuration Register */
+#define DMA6_X_COUNT 0xFFC00D90 /* DMA Channel 6 X Count Register */
+#define DMA6_X_MODIFY 0xFFC00D94 /* DMA Channel 6 X Modify Register */
+#define DMA6_Y_COUNT 0xFFC00D98 /* DMA Channel 6 Y Count Register */
+#define DMA6_Y_MODIFY 0xFFC00D9C /* DMA Channel 6 Y Modify Register */
+#define DMA6_CURR_DESC_PTR 0xFFC00DA0 /* DMA Channel 6 Current Descriptor Pointer Register */
+#define DMA6_CURR_ADDR 0xFFC00DA4 /* DMA Channel 6 Current Address Register */
+#define DMA6_IRQ_STATUS 0xFFC00DA8 /* DMA Channel 6 Interrupt/Status Register */
+#define DMA6_PERIPHERAL_MAP 0xFFC00DAC /* DMA Channel 6 Peripheral Map Register */
+#define DMA6_CURR_X_COUNT 0xFFC00DB0 /* DMA Channel 6 Current X Count Register */
+#define DMA6_CURR_Y_COUNT 0xFFC00DB8 /* DMA Channel 6 Current Y Count Register */
+
+#define DMA7_NEXT_DESC_PTR 0xFFC00DC0 /* DMA Channel 7 Next Descriptor Pointer Register */
+#define DMA7_START_ADDR 0xFFC00DC4 /* DMA Channel 7 Start Address Register */
+#define DMA7_CONFIG 0xFFC00DC8 /* DMA Channel 7 Configuration Register */
+#define DMA7_X_COUNT 0xFFC00DD0 /* DMA Channel 7 X Count Register */
+#define DMA7_X_MODIFY 0xFFC00DD4 /* DMA Channel 7 X Modify Register */
+#define DMA7_Y_COUNT 0xFFC00DD8 /* DMA Channel 7 Y Count Register */
+#define DMA7_Y_MODIFY 0xFFC00DDC /* DMA Channel 7 Y Modify Register */
+#define DMA7_CURR_DESC_PTR 0xFFC00DE0 /* DMA Channel 7 Current Descriptor Pointer Register */
+#define DMA7_CURR_ADDR 0xFFC00DE4 /* DMA Channel 7 Current Address Register */
+#define DMA7_IRQ_STATUS 0xFFC00DE8 /* DMA Channel 7 Interrupt/Status Register */
+#define DMA7_PERIPHERAL_MAP 0xFFC00DEC /* DMA Channel 7 Peripheral Map Register */
+#define DMA7_CURR_X_COUNT 0xFFC00DF0 /* DMA Channel 7 Current X Count Register */
+#define DMA7_CURR_Y_COUNT 0xFFC00DF8 /* DMA Channel 7 Current Y Count Register */
+
+#define DMA8_NEXT_DESC_PTR 0xFFC00E00 /* DMA Channel 8 Next Descriptor Pointer Register */
+#define DMA8_START_ADDR 0xFFC00E04 /* DMA Channel 8 Start Address Register */
+#define DMA8_CONFIG 0xFFC00E08 /* DMA Channel 8 Configuration Register */
+#define DMA8_X_COUNT 0xFFC00E10 /* DMA Channel 8 X Count Register */
+#define DMA8_X_MODIFY 0xFFC00E14 /* DMA Channel 8 X Modify Register */
+#define DMA8_Y_COUNT 0xFFC00E18 /* DMA Channel 8 Y Count Register */
+#define DMA8_Y_MODIFY 0xFFC00E1C /* DMA Channel 8 Y Modify Register */
+#define DMA8_CURR_DESC_PTR 0xFFC00E20 /* DMA Channel 8 Current Descriptor Pointer Register */
+#define DMA8_CURR_ADDR 0xFFC00E24 /* DMA Channel 8 Current Address Register */
+#define DMA8_IRQ_STATUS 0xFFC00E28 /* DMA Channel 8 Interrupt/Status Register */
+#define DMA8_PERIPHERAL_MAP 0xFFC00E2C /* DMA Channel 8 Peripheral Map Register */
+#define DMA8_CURR_X_COUNT 0xFFC00E30 /* DMA Channel 8 Current X Count Register */
+#define DMA8_CURR_Y_COUNT 0xFFC00E38 /* DMA Channel 8 Current Y Count Register */
+
+#define DMA9_NEXT_DESC_PTR 0xFFC00E40 /* DMA Channel 9 Next Descriptor Pointer Register */
+#define DMA9_START_ADDR 0xFFC00E44 /* DMA Channel 9 Start Address Register */
+#define DMA9_CONFIG 0xFFC00E48 /* DMA Channel 9 Configuration Register */
+#define DMA9_X_COUNT 0xFFC00E50 /* DMA Channel 9 X Count Register */
+#define DMA9_X_MODIFY 0xFFC00E54 /* DMA Channel 9 X Modify Register */
+#define DMA9_Y_COUNT 0xFFC00E58 /* DMA Channel 9 Y Count Register */
+#define DMA9_Y_MODIFY 0xFFC00E5C /* DMA Channel 9 Y Modify Register */
+#define DMA9_CURR_DESC_PTR 0xFFC00E60 /* DMA Channel 9 Current Descriptor Pointer Register */
+#define DMA9_CURR_ADDR 0xFFC00E64 /* DMA Channel 9 Current Address Register */
+#define DMA9_IRQ_STATUS 0xFFC00E68 /* DMA Channel 9 Interrupt/Status Register */
+#define DMA9_PERIPHERAL_MAP 0xFFC00E6C /* DMA Channel 9 Peripheral Map Register */
+#define DMA9_CURR_X_COUNT 0xFFC00E70 /* DMA Channel 9 Current X Count Register */
+#define DMA9_CURR_Y_COUNT 0xFFC00E78 /* DMA Channel 9 Current Y Count Register */
+
+#define DMA10_NEXT_DESC_PTR 0xFFC00E80 /* DMA Channel 10 Next Descriptor Pointer Register */
+#define DMA10_START_ADDR 0xFFC00E84 /* DMA Channel 10 Start Address Register */
+#define DMA10_CONFIG 0xFFC00E88 /* DMA Channel 10 Configuration Register */
+#define DMA10_X_COUNT 0xFFC00E90 /* DMA Channel 10 X Count Register */
+#define DMA10_X_MODIFY 0xFFC00E94 /* DMA Channel 10 X Modify Register */
+#define DMA10_Y_COUNT 0xFFC00E98 /* DMA Channel 10 Y Count Register */
+#define DMA10_Y_MODIFY 0xFFC00E9C /* DMA Channel 10 Y Modify Register */
+#define DMA10_CURR_DESC_PTR 0xFFC00EA0 /* DMA Channel 10 Current Descriptor Pointer Register */
+#define DMA10_CURR_ADDR 0xFFC00EA4 /* DMA Channel 10 Current Address Register */
+#define DMA10_IRQ_STATUS 0xFFC00EA8 /* DMA Channel 10 Interrupt/Status Register */
+#define DMA10_PERIPHERAL_MAP 0xFFC00EAC /* DMA Channel 10 Peripheral Map Register */
+#define DMA10_CURR_X_COUNT 0xFFC00EB0 /* DMA Channel 10 Current X Count Register */
+#define DMA10_CURR_Y_COUNT 0xFFC00EB8 /* DMA Channel 10 Current Y Count Register */
+
+#define DMA11_NEXT_DESC_PTR 0xFFC00EC0 /* DMA Channel 11 Next Descriptor Pointer Register */
+#define DMA11_START_ADDR 0xFFC00EC4 /* DMA Channel 11 Start Address Register */
+#define DMA11_CONFIG 0xFFC00EC8 /* DMA Channel 11 Configuration Register */
+#define DMA11_X_COUNT 0xFFC00ED0 /* DMA Channel 11 X Count Register */
+#define DMA11_X_MODIFY 0xFFC00ED4 /* DMA Channel 11 X Modify Register */
+#define DMA11_Y_COUNT 0xFFC00ED8 /* DMA Channel 11 Y Count Register */
+#define DMA11_Y_MODIFY 0xFFC00EDC /* DMA Channel 11 Y Modify Register */
+#define DMA11_CURR_DESC_PTR 0xFFC00EE0 /* DMA Channel 11 Current Descriptor Pointer Register */
+#define DMA11_CURR_ADDR 0xFFC00EE4 /* DMA Channel 11 Current Address Register */
+#define DMA11_IRQ_STATUS 0xFFC00EE8 /* DMA Channel 11 Interrupt/Status Register */
+#define DMA11_PERIPHERAL_MAP 0xFFC00EEC /* DMA Channel 11 Peripheral Map Register */
+#define DMA11_CURR_X_COUNT 0xFFC00EF0 /* DMA Channel 11 Current X Count Register */
+#define DMA11_CURR_Y_COUNT 0xFFC00EF8 /* DMA Channel 11 Current Y Count Register */
+
+#define MDMA_D0_NEXT_DESC_PTR 0xFFC00F00 /* MemDMA Stream 0 Destination Next Descriptor Pointer Register */
+#define MDMA_D0_START_ADDR 0xFFC00F04 /* MemDMA Stream 0 Destination Start Address Register */
+#define MDMA_D0_CONFIG 0xFFC00F08 /* MemDMA Stream 0 Destination Configuration Register */
+#define MDMA_D0_X_COUNT 0xFFC00F10 /* MemDMA Stream 0 Destination X Count Register */
+#define MDMA_D0_X_MODIFY 0xFFC00F14 /* MemDMA Stream 0 Destination X Modify Register */
+#define MDMA_D0_Y_COUNT 0xFFC00F18 /* MemDMA Stream 0 Destination Y Count Register */
+#define MDMA_D0_Y_MODIFY 0xFFC00F1C /* MemDMA Stream 0 Destination Y Modify Register */
+#define MDMA_D0_CURR_DESC_PTR 0xFFC00F20 /* MemDMA Stream 0 Destination Current Descriptor Pointer Register */
+#define MDMA_D0_CURR_ADDR 0xFFC00F24 /* MemDMA Stream 0 Destination Current Address Register */
+#define MDMA_D0_IRQ_STATUS 0xFFC00F28 /* MemDMA Stream 0 Destination Interrupt/Status Register */
+#define MDMA_D0_PERIPHERAL_MAP 0xFFC00F2C /* MemDMA Stream 0 Destination Peripheral Map Register */
+#define MDMA_D0_CURR_X_COUNT 0xFFC00F30 /* MemDMA Stream 0 Destination Current X Count Register */
+#define MDMA_D0_CURR_Y_COUNT 0xFFC00F38 /* MemDMA Stream 0 Destination Current Y Count Register */
+
+#define MDMA_S0_NEXT_DESC_PTR 0xFFC00F40 /* MemDMA Stream 0 Source Next Descriptor Pointer Register */
+#define MDMA_S0_START_ADDR 0xFFC00F44 /* MemDMA Stream 0 Source Start Address Register */
+#define MDMA_S0_CONFIG 0xFFC00F48 /* MemDMA Stream 0 Source Configuration Register */
+#define MDMA_S0_X_COUNT 0xFFC00F50 /* MemDMA Stream 0 Source X Count Register */
+#define MDMA_S0_X_MODIFY 0xFFC00F54 /* MemDMA Stream 0 Source X Modify Register */
+#define MDMA_S0_Y_COUNT 0xFFC00F58 /* MemDMA Stream 0 Source Y Count Register */
+#define MDMA_S0_Y_MODIFY 0xFFC00F5C /* MemDMA Stream 0 Source Y Modify Register */
+#define MDMA_S0_CURR_DESC_PTR 0xFFC00F60 /* MemDMA Stream 0 Source Current Descriptor Pointer Register */
+#define MDMA_S0_CURR_ADDR 0xFFC00F64 /* MemDMA Stream 0 Source Current Address Register */
+#define MDMA_S0_IRQ_STATUS 0xFFC00F68 /* MemDMA Stream 0 Source Interrupt/Status Register */
+#define MDMA_S0_PERIPHERAL_MAP 0xFFC00F6C /* MemDMA Stream 0 Source Peripheral Map Register */
+#define MDMA_S0_CURR_X_COUNT 0xFFC00F70 /* MemDMA Stream 0 Source Current X Count Register */
+#define MDMA_S0_CURR_Y_COUNT 0xFFC00F78 /* MemDMA Stream 0 Source Current Y Count Register */
+
+#define MDMA_D1_NEXT_DESC_PTR 0xFFC00F80 /* MemDMA Stream 1 Destination Next Descriptor Pointer Register */
+#define MDMA_D1_START_ADDR 0xFFC00F84 /* MemDMA Stream 1 Destination Start Address Register */
+#define MDMA_D1_CONFIG 0xFFC00F88 /* MemDMA Stream 1 Destination Configuration Register */
+#define MDMA_D1_X_COUNT 0xFFC00F90 /* MemDMA Stream 1 Destination X Count Register */
+#define MDMA_D1_X_MODIFY 0xFFC00F94 /* MemDMA Stream 1 Destination X Modify Register */
+#define MDMA_D1_Y_COUNT 0xFFC00F98 /* MemDMA Stream 1 Destination Y Count Register */
+#define MDMA_D1_Y_MODIFY 0xFFC00F9C /* MemDMA Stream 1 Destination Y Modify Register */
+#define MDMA_D1_CURR_DESC_PTR 0xFFC00FA0 /* MemDMA Stream 1 Destination Current Descriptor Pointer Register */
+#define MDMA_D1_CURR_ADDR 0xFFC00FA4 /* MemDMA Stream 1 Destination Current Address Register */
+#define MDMA_D1_IRQ_STATUS 0xFFC00FA8 /* MemDMA Stream 1 Destination Interrupt/Status Register */
+#define MDMA_D1_PERIPHERAL_MAP 0xFFC00FAC /* MemDMA Stream 1 Destination Peripheral Map Register */
+#define MDMA_D1_CURR_X_COUNT 0xFFC00FB0 /* MemDMA Stream 1 Destination Current X Count Register */
+#define MDMA_D1_CURR_Y_COUNT 0xFFC00FB8 /* MemDMA Stream 1 Destination Current Y Count Register */
+
+#define MDMA_S1_NEXT_DESC_PTR 0xFFC00FC0 /* MemDMA Stream 1 Source Next Descriptor Pointer Register */
+#define MDMA_S1_START_ADDR 0xFFC00FC4 /* MemDMA Stream 1 Source Start Address Register */
+#define MDMA_S1_CONFIG 0xFFC00FC8 /* MemDMA Stream 1 Source Configuration Register */
+#define MDMA_S1_X_COUNT 0xFFC00FD0 /* MemDMA Stream 1 Source X Count Register */
+#define MDMA_S1_X_MODIFY 0xFFC00FD4 /* MemDMA Stream 1 Source X Modify Register */
+#define MDMA_S1_Y_COUNT 0xFFC00FD8 /* MemDMA Stream 1 Source Y Count Register */
+#define MDMA_S1_Y_MODIFY 0xFFC00FDC /* MemDMA Stream 1 Source Y Modify Register */
+#define MDMA_S1_CURR_DESC_PTR 0xFFC00FE0 /* MemDMA Stream 1 Source Current Descriptor Pointer Register */
+#define MDMA_S1_CURR_ADDR 0xFFC00FE4 /* MemDMA Stream 1 Source Current Address Register */
+#define MDMA_S1_IRQ_STATUS 0xFFC00FE8 /* MemDMA Stream 1 Source Interrupt/Status Register */
+#define MDMA_S1_PERIPHERAL_MAP 0xFFC00FEC /* MemDMA Stream 1 Source Peripheral Map Register */
+#define MDMA_S1_CURR_X_COUNT 0xFFC00FF0 /* MemDMA Stream 1 Source Current X Count Register */
+#define MDMA_S1_CURR_Y_COUNT 0xFFC00FF8 /* MemDMA Stream 1 Source Current Y Count Register */
+
+
+/* Parallel Peripheral Interface (0xFFC01000 - 0xFFC010FF) */
+#define PPI_CONTROL 0xFFC01000 /* PPI Control Register */
+#define PPI_STATUS 0xFFC01004 /* PPI Status Register */
+#define PPI_COUNT 0xFFC01008 /* PPI Transfer Count Register */
+#define PPI_DELAY 0xFFC0100C /* PPI Delay Count Register */
+#define PPI_FRAME 0xFFC01010 /* PPI Frame Length Register */
+
+
+/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
+#define TWI0_REGBASE 0xFFC01400
+#define TWI_CLKDIV 0xFFC01400 /* Serial Clock Divider Register */
+#define TWI_CONTROL 0xFFC01404 /* TWI Control Register */
+#define TWI_SLAVE_CTL 0xFFC01408 /* Slave Mode Control Register */
+#define TWI_SLAVE_STAT 0xFFC0140C /* Slave Mode Status Register */
+#define TWI_SLAVE_ADDR 0xFFC01410 /* Slave Mode Address Register */
+#define TWI_MASTER_CTL 0xFFC01414 /* Master Mode Control Register */
+#define TWI_MASTER_STAT 0xFFC01418 /* Master Mode Status Register */
+#define TWI_MASTER_ADDR 0xFFC0141C /* Master Mode Address Register */
+#define TWI_INT_STAT 0xFFC01420 /* TWI Interrupt Status Register */
+#define TWI_INT_MASK 0xFFC01424 /* TWI Master Interrupt Mask Register */
+#define TWI_FIFO_CTL 0xFFC01428 /* FIFO Control Register */
+#define TWI_FIFO_STAT 0xFFC0142C /* FIFO Status Register */
+#define TWI_XMT_DATA8 0xFFC01480 /* FIFO Transmit Data Single Byte Register */
+#define TWI_XMT_DATA16 0xFFC01484 /* FIFO Transmit Data Double Byte Register */
+#define TWI_RCV_DATA8 0xFFC01488 /* FIFO Receive Data Single Byte Register */
+#define TWI_RCV_DATA16 0xFFC0148C /* FIFO Receive Data Double Byte Register */
+
+
+/* General Purpose I/O Port G (0xFFC01500 - 0xFFC015FF) */
+#define PORTGIO 0xFFC01500 /* Port G I/O Pin State Specify Register */
+#define PORTGIO_CLEAR 0xFFC01504 /* Port G I/O Peripheral Interrupt Clear Register */
+#define PORTGIO_SET 0xFFC01508 /* Port G I/O Peripheral Interrupt Set Register */
+#define PORTGIO_TOGGLE 0xFFC0150C /* Port G I/O Pin State Toggle Register */
+#define PORTGIO_MASKA 0xFFC01510 /* Port G I/O Mask State Specify Interrupt A Register */
+#define PORTGIO_MASKA_CLEAR 0xFFC01514 /* Port G I/O Mask Disable Interrupt A Register */
+#define PORTGIO_MASKA_SET 0xFFC01518 /* Port G I/O Mask Enable Interrupt A Register */
+#define PORTGIO_MASKA_TOGGLE 0xFFC0151C /* Port G I/O Mask Toggle Enable Interrupt A Register */
+#define PORTGIO_MASKB 0xFFC01520 /* Port G I/O Mask State Specify Interrupt B Register */
+#define PORTGIO_MASKB_CLEAR 0xFFC01524 /* Port G I/O Mask Disable Interrupt B Register */
+#define PORTGIO_MASKB_SET 0xFFC01528 /* Port G I/O Mask Enable Interrupt B Register */
+#define PORTGIO_MASKB_TOGGLE 0xFFC0152C /* Port G I/O Mask Toggle Enable Interrupt B Register */
+#define PORTGIO_DIR 0xFFC01530 /* Port G I/O Direction Register */
+#define PORTGIO_POLAR 0xFFC01534 /* Port G I/O Source Polarity Register */
+#define PORTGIO_EDGE 0xFFC01538 /* Port G I/O Source Sensitivity Register */
+#define PORTGIO_BOTH 0xFFC0153C /* Port G I/O Set on BOTH Edges Register */
+#define PORTGIO_INEN 0xFFC01540 /* Port G I/O Input Enable Register */
+
+
+/* General Purpose I/O Port H (0xFFC01700 - 0xFFC017FF) */
+#define PORTHIO 0xFFC01700 /* Port H I/O Pin State Specify Register */
+#define PORTHIO_CLEAR 0xFFC01704 /* Port H I/O Peripheral Interrupt Clear Register */
+#define PORTHIO_SET 0xFFC01708 /* Port H I/O Peripheral Interrupt Set Register */
+#define PORTHIO_TOGGLE 0xFFC0170C /* Port H I/O Pin State Toggle Register */
+#define PORTHIO_MASKA 0xFFC01710 /* Port H I/O Mask State Specify Interrupt A Register */
+#define PORTHIO_MASKA_CLEAR 0xFFC01714 /* Port H I/O Mask Disable Interrupt A Register */
+#define PORTHIO_MASKA_SET 0xFFC01718 /* Port H I/O Mask Enable Interrupt A Register */
+#define PORTHIO_MASKA_TOGGLE 0xFFC0171C /* Port H I/O Mask Toggle Enable Interrupt A Register */
+#define PORTHIO_MASKB 0xFFC01720 /* Port H I/O Mask State Specify Interrupt B Register */
+#define PORTHIO_MASKB_CLEAR 0xFFC01724 /* Port H I/O Mask Disable Interrupt B Register */
+#define PORTHIO_MASKB_SET 0xFFC01728 /* Port H I/O Mask Enable Interrupt B Register */
+#define PORTHIO_MASKB_TOGGLE 0xFFC0172C /* Port H I/O Mask Toggle Enable Interrupt B Register */
+#define PORTHIO_DIR 0xFFC01730 /* Port H I/O Direction Register */
+#define PORTHIO_POLAR 0xFFC01734 /* Port H I/O Source Polarity Register */
+#define PORTHIO_EDGE 0xFFC01738 /* Port H I/O Source Sensitivity Register */
+#define PORTHIO_BOTH 0xFFC0173C /* Port H I/O Set on BOTH Edges Register */
+#define PORTHIO_INEN 0xFFC01740 /* Port H I/O Input Enable Register */
+
+
+/* UART1 Controller (0xFFC02000 - 0xFFC020FF) */
+#define UART1_THR 0xFFC02000 /* Transmit Holding register */
+#define UART1_RBR 0xFFC02000 /* Receive Buffer register */
+#define UART1_DLL 0xFFC02000 /* Divisor Latch (Low-Byte) */
+#define UART1_IER 0xFFC02004 /* Interrupt Enable Register */
+#define UART1_DLH 0xFFC02004 /* Divisor Latch (High-Byte) */
+#define UART1_IIR 0xFFC02008 /* Interrupt Identification Register */
+#define UART1_LCR 0xFFC0200C /* Line Control Register */
+#define UART1_MCR 0xFFC02010 /* Modem Control Register */
+#define UART1_LSR 0xFFC02014 /* Line Status Register */
+#define UART1_MSR 0xFFC02018 /* Modem Status Register */
+#define UART1_SCR 0xFFC0201C /* SCR Scratch Register */
+#define UART1_GCTL 0xFFC02024 /* Global Control Register */
+
+
+/* Pin Control Registers (0xFFC03200 - 0xFFC032FF) */
+#define PORTF_FER 0xFFC03200 /* Port F Function Enable Register (Alternate/Flag*) */
+#define PORTG_FER 0xFFC03204 /* Port G Function Enable Register (Alternate/Flag*) */
+#define PORTH_FER 0xFFC03208 /* Port H Function Enable Register (Alternate/Flag*) */
+#define BFIN_PORT_MUX 0xFFC0320C /* Port Multiplexer Control Register */
+
+
+/* Handshake MDMA Registers (0xFFC03300 - 0xFFC033FF) */
+#define HMDMA0_CONTROL 0xFFC03300 /* Handshake MDMA0 Control Register */
+#define HMDMA0_ECINIT 0xFFC03304 /* HMDMA0 Initial Edge Count Register */
+#define HMDMA0_BCINIT 0xFFC03308 /* HMDMA0 Initial Block Count Register */
+#define HMDMA0_ECURGENT 0xFFC0330C /* HMDMA0 Urgent Edge Count Threshhold Register */
+#define HMDMA0_ECOVERFLOW 0xFFC03310 /* HMDMA0 Edge Count Overflow Interrupt Register */
+#define HMDMA0_ECOUNT 0xFFC03314 /* HMDMA0 Current Edge Count Register */
+#define HMDMA0_BCOUNT 0xFFC03318 /* HMDMA0 Current Block Count Register */
+
+#define HMDMA1_CONTROL 0xFFC03340 /* Handshake MDMA1 Control Register */
+#define HMDMA1_ECINIT 0xFFC03344 /* HMDMA1 Initial Edge Count Register */
+#define HMDMA1_BCINIT 0xFFC03348 /* HMDMA1 Initial Block Count Register */
+#define HMDMA1_ECURGENT 0xFFC0334C /* HMDMA1 Urgent Edge Count Threshhold Register */
+#define HMDMA1_ECOVERFLOW 0xFFC03350 /* HMDMA1 Edge Count Overflow Interrupt Register */
+#define HMDMA1_ECOUNT 0xFFC03354 /* HMDMA1 Current Edge Count Register */
+#define HMDMA1_BCOUNT 0xFFC03358 /* HMDMA1 Current Block Count Register */
+
+
+/* GPIO PIN mux (0xFFC03210 - OxFFC03288) */
+#define PORTF_MUX 0xFFC03210 /* Port F mux control */
+#define PORTG_MUX 0xFFC03214 /* Port G mux control */
+#define PORTH_MUX 0xFFC03218 /* Port H mux control */
+#define PORTF_DRIVE 0xFFC03220 /* Port F drive strength control */
+#define PORTG_DRIVE 0xFFC03224 /* Port G drive strength control */
+#define PORTH_DRIVE 0xFFC03228 /* Port H drive strength control */
+#define PORTF_SLEW 0xFFC03230 /* Port F slew control */
+#define PORTG_SLEW 0xFFC03234 /* Port G slew control */
+#define PORTH_SLEW 0xFFC03238 /* Port H slew control */
+#define PORTF_HYSTERISIS 0xFFC03240 /* Port F Schmitt trigger control */
+#define PORTG_HYSTERISIS 0xFFC03244 /* Port G Schmitt trigger control */
+#define PORTH_HYSTERISIS 0xFFC03248 /* Port H Schmitt trigger control */
+#define MISCPORT_DRIVE 0xFFC03280 /* Misc Port drive strength control */
+#define MISCPORT_SLEW 0xFFC03284 /* Misc Port slew control */
+#define MISCPORT_HYSTERISIS 0xFFC03288 /* Misc Port Schmitt trigger control */
+
+
+/***********************************************************************************
+** System MMR Register Bits And Macros
+**
+** Disclaimer: All macros are intended to make C and Assembly code more readable.
+** Use these macros carefully, as any that do left shifts for field
+** depositing will result in the lower order bits being destroyed. Any
+** macro that shifts left to properly position the bit-field should be
+** used as part of an OR to initialize a register and NOT as a dynamic
+** modifier UNLESS the lower order bits are saved and ORed back in when
+** the macro is used.
+*************************************************************************************/
+/*
+** ********************* PLL AND RESET MASKS ****************************************/
+/* PLL_CTL Masks */
+#define DF 0x0001 /* 0: PLL = CLKIN, 1: PLL = CLKIN/2 */
+#define PLL_OFF 0x0002 /* PLL Not Powered */
+#define STOPCK 0x0008 /* Core Clock Off */
+#define PDWN 0x0020 /* Enter Deep Sleep Mode */
+#define IN_DELAY 0x0040 /* Add 200ps Delay To EBIU Input Latches */
+#define OUT_DELAY 0x0080 /* Add 200ps Delay To EBIU Output Signals */
+#define BYPASS 0x0100 /* Bypass the PLL */
+#define MSEL 0x7E00 /* Multiplier Select For CCLK/VCO Factors */
+/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits) */
+#define SET_MSEL(x) (((x)&0x3F) << 0x9) /* Set MSEL = 0-63 --> VCO = CLKIN*MSEL */
+
+/* PLL_DIV Masks */
+#define SSEL 0x000F /* System Select */
+#define CSEL 0x0030 /* Core Select */
+#define CSEL_DIV1 0x0000 /* CCLK = VCO / 1 */
+#define CSEL_DIV2 0x0010 /* CCLK = VCO / 2 */
+#define CSEL_DIV4 0x0020 /* CCLK = VCO / 4 */
+#define CSEL_DIV8 0x0030 /* CCLK = VCO / 8 */
+/* PLL_DIV Macros */
+#define SET_SSEL(x) ((x)&0xF) /* Set SSEL = 0-15 --> SCLK = VCO/SSEL */
+
+/* VR_CTL Masks */
+#define FREQ 0x3000 /* Switching Oscillator Frequency For Regulator */
+#define HIBERNATE 0x0000 /* Powerdown/Bypass On-Board Regulation */
+
+#define VLEV 0x00F0 /* Internal Voltage Level */
+#define VLEV_085 0x0060 /* VLEV = 0.85 V (-5% - +10% Accuracy) */
+#define VLEV_090 0x0070 /* VLEV = 0.90 V (-5% - +10% Accuracy) */
+#define VLEV_095 0x0080 /* VLEV = 0.95 V (-5% - +10% Accuracy) */
+#define VLEV_100 0x0090 /* VLEV = 1.00 V (-5% - +10% Accuracy) */
+#define VLEV_105 0x00A0 /* VLEV = 1.05 V (-5% - +10% Accuracy) */
+#define VLEV_110 0x00B0 /* VLEV = 1.10 V (-5% - +10% Accuracy) */
+#define VLEV_115 0x00C0 /* VLEV = 1.15 V (-5% - +10% Accuracy) */
+#define VLEV_120 0x00D0 /* VLEV = 1.20 V (-5% - +10% Accuracy) */
+#define VLEV_125 0x00E0 /* VLEV = 1.25 V (-5% - +10% Accuracy) */
+#define VLEV_130 0x00F0 /* VLEV = 1.30 V (-5% - +10% Accuracy) */
+
+#define WAKE 0x0100 /* Enable RTC/Reset Wakeup From Hibernate */
+#define USBWE 0x0200 /* Enable USB Wakeup From Hibernate */
+#define PHYWE 0x0400 /* Enable PHY Wakeup From Hibernate */
+#define CLKBUFOE 0x4000 /* CLKIN Buffer Output Enable */
+#define PHYCLKOE CLKBUFOE /* Alternative legacy name for the above */
+#define SCKELOW 0x8000 /* Enable Drive CKE Low During Reset */
+
+/* PLL_STAT Masks */
+#define ACTIVE_PLLENABLED 0x0001 /* Processor In Active Mode With PLL Enabled */
+#define FULL_ON 0x0002 /* Processor In Full On Mode */
+#define ACTIVE_PLLDISABLED 0x0004 /* Processor In Active Mode With PLL Disabled */
+#define PLL_LOCKED 0x0020 /* PLL_LOCKCNT Has Been Reached */
+
+/* CHIPID Masks */
+#define CHIPID_VERSION 0xF0000000
+#define CHIPID_FAMILY 0x0FFFF000
+#define CHIPID_MANUFACTURE 0x00000FFE
+
+/* SWRST Masks */
+#define SYSTEM_RESET 0x0007 /* Initiates A System Software Reset */
+#define DOUBLE_FAULT 0x0008 /* Core Double Fault Causes Reset */
+#define RESET_DOUBLE 0x2000 /* SW Reset Generated By Core Double-Fault */
+#define RESET_WDOG 0x4000 /* SW Reset Generated By Watchdog Timer */
+#define RESET_SOFTWARE 0x8000 /* SW Reset Occurred Since Last Read Of SWRST */
+
+/* SYSCR Masks */
+#define BMODE 0x0007 /* Boot Mode - Latched During HW Reset From Mode Pins */
+#define NOBOOT 0x0010 /* Execute From L1 or ASYNC Bank 0 When BMODE = 0 */
+
+
+/* ************* SYSTEM INTERRUPT CONTROLLER MASKS *************************************/
+/* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK */
+
+#if 0
+#define IRQ_PLL_WAKEUP 0x00000001 /* PLL Wakeup Interrupt */
+
+#define IRQ_ERROR1 0x00000002 /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */
+#define IRQ_ERROR2 0x00000004 /* Error Interrupt (CAN, Ethernet, SPORTx, PPI, SPI, UARTx) */
+#define IRQ_RTC 0x00000008 /* Real Time Clock Interrupt */
+#define IRQ_DMA0 0x00000010 /* DMA Channel 0 (PPI) Interrupt */
+#define IRQ_DMA3 0x00000020 /* DMA Channel 3 (SPORT0 RX) Interrupt */
+#define IRQ_DMA4 0x00000040 /* DMA Channel 4 (SPORT0 TX) Interrupt */
+#define IRQ_DMA5 0x00000080 /* DMA Channel 5 (SPORT1 RX) Interrupt */
+
+#define IRQ_DMA6 0x00000100 /* DMA Channel 6 (SPORT1 TX) Interrupt */
+#define IRQ_TWI 0x00000200 /* TWI Interrupt */
+#define IRQ_DMA7 0x00000400 /* DMA Channel 7 (SPI) Interrupt */
+#define IRQ_DMA8 0x00000800 /* DMA Channel 8 (UART0 RX) Interrupt */
+#define IRQ_DMA9 0x00001000 /* DMA Channel 9 (UART0 TX) Interrupt */
+#define IRQ_DMA10 0x00002000 /* DMA Channel 10 (UART1 RX) Interrupt */
+#define IRQ_DMA11 0x00004000 /* DMA Channel 11 (UART1 TX) Interrupt */
+#define IRQ_CAN_RX 0x00008000 /* CAN Receive Interrupt */
+
+#define IRQ_CAN_TX 0x00010000 /* CAN Transmit Interrupt */
+#define IRQ_DMA1 0x00020000 /* DMA Channel 1 (Ethernet RX) Interrupt */
+#define IRQ_PFA_PORTH 0x00020000 /* PF Port H (PF47:32) Interrupt A */
+#define IRQ_DMA2 0x00040000 /* DMA Channel 2 (Ethernet TX) Interrupt */
+#define IRQ_PFB_PORTH 0x00040000 /* PF Port H (PF47:32) Interrupt B */
+#define IRQ_TIMER0 0x00080000 /* Timer 0 Interrupt */
+#define IRQ_TIMER1 0x00100000 /* Timer 1 Interrupt */
+#define IRQ_TIMER2 0x00200000 /* Timer 2 Interrupt */
+#define IRQ_TIMER3 0x00400000 /* Timer 3 Interrupt */
+#define IRQ_TIMER4 0x00800000 /* Timer 4 Interrupt */
+
+#define IRQ_TIMER5 0x01000000 /* Timer 5 Interrupt */
+#define IRQ_TIMER6 0x02000000 /* Timer 6 Interrupt */
+#define IRQ_TIMER7 0x04000000 /* Timer 7 Interrupt */
+#define IRQ_PFA_PORTFG 0x08000000 /* PF Ports F&G (PF31:0) Interrupt A */
+#define IRQ_PFB_PORTF 0x80000000 /* PF Port F (PF15:0) Interrupt B */
+#define IRQ_DMA12 0x20000000 /* DMA Channels 12 (MDMA1 Source) RX Interrupt */
+#define IRQ_DMA13 0x20000000 /* DMA Channels 13 (MDMA1 Destination) TX Interrupt */
+#define IRQ_DMA14 0x40000000 /* DMA Channels 14 (MDMA0 Source) RX Interrupt */
+#define IRQ_DMA15 0x40000000 /* DMA Channels 15 (MDMA0 Destination) TX Interrupt */
+#define IRQ_WDOG 0x80000000 /* Software Watchdog Timer Interrupt */
+#define IRQ_PFB_PORTG 0x10000000 /* PF Port G (PF31:16) Interrupt B */
+#endif
+
+/* SIC_IAR0 Macros */
+#define P0_IVG(x) (((x)&0xF)-7) /* Peripheral #0 assigned IVG #x */
+#define P1_IVG(x) (((x)&0xF)-7) << 0x4 /* Peripheral #1 assigned IVG #x */
+#define P2_IVG(x) (((x)&0xF)-7) << 0x8 /* Peripheral #2 assigned IVG #x */
+#define P3_IVG(x) (((x)&0xF)-7) << 0xC /* Peripheral #3 assigned IVG #x */
+#define P4_IVG(x) (((x)&0xF)-7) << 0x10 /* Peripheral #4 assigned IVG #x */
+#define P5_IVG(x) (((x)&0xF)-7) << 0x14 /* Peripheral #5 assigned IVG #x */
+#define P6_IVG(x) (((x)&0xF)-7) << 0x18 /* Peripheral #6 assigned IVG #x */
+#define P7_IVG(x) (((x)&0xF)-7) << 0x1C /* Peripheral #7 assigned IVG #x */
+
+/* SIC_IAR1 Macros */
+#define P8_IVG(x) (((x)&0xF)-7) /* Peripheral #8 assigned IVG #x */
+#define P9_IVG(x) (((x)&0xF)-7) << 0x4 /* Peripheral #9 assigned IVG #x */
+#define P10_IVG(x) (((x)&0xF)-7) << 0x8 /* Peripheral #10 assigned IVG #x */
+#define P11_IVG(x) (((x)&0xF)-7) << 0xC /* Peripheral #11 assigned IVG #x */
+#define P12_IVG(x) (((x)&0xF)-7) << 0x10 /* Peripheral #12 assigned IVG #x */
+#define P13_IVG(x) (((x)&0xF)-7) << 0x14 /* Peripheral #13 assigned IVG #x */
+#define P14_IVG(x) (((x)&0xF)-7) << 0x18 /* Peripheral #14 assigned IVG #x */
+#define P15_IVG(x) (((x)&0xF)-7) << 0x1C /* Peripheral #15 assigned IVG #x */
+
+/* SIC_IAR2 Macros */
+#define P16_IVG(x) (((x)&0xF)-7) /* Peripheral #16 assigned IVG #x */
+#define P17_IVG(x) (((x)&0xF)-7) << 0x4 /* Peripheral #17 assigned IVG #x */
+#define P18_IVG(x) (((x)&0xF)-7) << 0x8 /* Peripheral #18 assigned IVG #x */
+#define P19_IVG(x) (((x)&0xF)-7) << 0xC /* Peripheral #19 assigned IVG #x */
+#define P20_IVG(x) (((x)&0xF)-7) << 0x10 /* Peripheral #20 assigned IVG #x */
+#define P21_IVG(x) (((x)&0xF)-7) << 0x14 /* Peripheral #21 assigned IVG #x */
+#define P22_IVG(x) (((x)&0xF)-7) << 0x18 /* Peripheral #22 assigned IVG #x */
+#define P23_IVG(x) (((x)&0xF)-7) << 0x1C /* Peripheral #23 assigned IVG #x */
+
+/* SIC_IAR3 Macros */
+#define P24_IVG(x) (((x)&0xF)-7) /* Peripheral #24 assigned IVG #x */
+#define P25_IVG(x) (((x)&0xF)-7) << 0x4 /* Peripheral #25 assigned IVG #x */
+#define P26_IVG(x) (((x)&0xF)-7) << 0x8 /* Peripheral #26 assigned IVG #x */
+#define P27_IVG(x) (((x)&0xF)-7) << 0xC /* Peripheral #27 assigned IVG #x */
+#define P28_IVG(x) (((x)&0xF)-7) << 0x10 /* Peripheral #28 assigned IVG #x */
+#define P29_IVG(x) (((x)&0xF)-7) << 0x14 /* Peripheral #29 assigned IVG #x */
+#define P30_IVG(x) (((x)&0xF)-7) << 0x18 /* Peripheral #30 assigned IVG #x */
+#define P31_IVG(x) (((x)&0xF)-7) << 0x1C /* Peripheral #31 assigned IVG #x */
+
+
+/* SIC_IMASK Masks */
+#define SIC_UNMASK_ALL 0x00000000 /* Unmask all peripheral interrupts */
+#define SIC_MASK_ALL 0xFFFFFFFF /* Mask all peripheral interrupts */
+#define SIC_MASK(x) (1 << ((x)&0x1F)) /* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFF ^ (1 << ((x)&0x1F))) /* Unmask Peripheral #x interrupt */
+
+/* SIC_IWR Masks */
+#define IWR_DISABLE_ALL 0x00000000 /* Wakeup Disable all peripherals */
+#define IWR_ENABLE_ALL 0xFFFFFFFF /* Wakeup Enable all peripherals */
+#define IWR_ENABLE(x) (1 << ((x)&0x1F)) /* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << ((x)&0x1F))) /* Wakeup Disable Peripheral #x */
+
+
+/* ********* WATCHDOG TIMER MASKS ******************** */
+
+/* Watchdog Timer WDOG_CTL Register Masks */
+
+#define WDEV(x) (((x)<<1) & 0x0006) /* event generated on roll over */
+#define WDEV_RESET 0x0000 /* generate reset event on roll over */
+#define WDEV_NMI 0x0002 /* generate NMI event on roll over */
+#define WDEV_GPI 0x0004 /* generate GP IRQ on roll over */
+#define WDEV_NONE 0x0006 /* no event on roll over */
+#define WDEN 0x0FF0 /* enable watchdog */
+#define WDDIS 0x0AD0 /* disable watchdog */
+#define WDRO 0x8000 /* watchdog rolled over latch */
+
+/* depreciated WDOG_CTL Register Masks for legacy code */
+
+
+#define ICTL WDEV
+#define ENABLE_RESET WDEV_RESET
+#define WDOG_RESET WDEV_RESET
+#define ENABLE_NMI WDEV_NMI
+#define WDOG_NMI WDEV_NMI
+#define ENABLE_GPI WDEV_GPI
+#define WDOG_GPI WDEV_GPI
+#define DISABLE_EVT WDEV_NONE
+#define WDOG_NONE WDEV_NONE
+
+#define TMR_EN WDEN
+#define TMR_DIS WDDIS
+#define TRO WDRO
+#define ICTL_P0 0x01
+ #define ICTL_P1 0x02
+#define TRO_P 0x0F
+
+
+
+/* *************** REAL TIME CLOCK MASKS **************************/
+/* RTC_STAT and RTC_ALARM Masks */
+#define RTC_SEC 0x0000003F /* Real-Time Clock Seconds */
+#define RTC_MIN 0x00000FC0 /* Real-Time Clock Minutes */
+#define RTC_HR 0x0001F000 /* Real-Time Clock Hours */
+#define RTC_DAY 0xFFFE0000 /* Real-Time Clock Days */
+
+/* RTC_ALARM Macro z=day y=hr x=min w=sec */
+#define SET_ALARM(z,y,x,w) ((((z)&0x7FFF)<<0x11)|(((y)&0x1F)<<0xC)|(((x)&0x3F)<<0x6)|((w)&0x3F))
+
+/* RTC_ICTL and RTC_ISTAT Masks */
+#define STOPWATCH 0x0001 /* Stopwatch Interrupt Enable */
+#define ALARM 0x0002 /* Alarm Interrupt Enable */
+#define SECOND 0x0004 /* Seconds (1 Hz) Interrupt Enable */
+#define MINUTE 0x0008 /* Minutes Interrupt Enable */
+#define HOUR 0x0010 /* Hours Interrupt Enable */
+#define DAY 0x0020 /* 24 Hours (Days) Interrupt Enable */
+#define DAY_ALARM 0x0040 /* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable */
+#define WRITE_PENDING 0x4000 /* Write Pending Status */
+#define WRITE_COMPLETE 0x8000 /* Write Complete Interrupt Enable */
+
+/* RTC_FAST / RTC_PREN Mask */
+#define PREN 0x0001 /* Enable Prescaler, RTC Runs @1 Hz */
+
+
+/* ************** UART CONTROLLER MASKS *************************/
+/* UARTx_LCR Masks */
+#define WLS(x) (((x)-5) & 0x03) /* Word Length Select */
+#define STB 0x04 /* Stop Bits */
+#define PEN 0x08 /* Parity Enable */
+#define EPS 0x10 /* Even Parity Select */
+#define STP 0x20 /* Stick Parity */
+#define SB 0x40 /* Set Break */
+#define DLAB 0x80 /* Divisor Latch Access */
+
+/* UARTx_MCR Mask */
+#define LOOP_ENA 0x10 /* Loopback Mode Enable */
+#define LOOP_ENA_P 0x04
+
+/* UARTx_LSR Masks */
+#define DR 0x01 /* Data Ready */
+#define OE 0x02 /* Overrun Error */
+#define PE 0x04 /* Parity Error */
+#define FE 0x08 /* Framing Error */
+#define BI 0x10 /* Break Interrupt */
+#define THRE 0x20 /* THR Empty */
+#define TEMT 0x40 /* TSR and UART_THR Empty */
+
+/* UARTx_IER Masks */
+#define ERBFI 0x01 /* Enable Receive Buffer Full Interrupt */
+#define ETBEI 0x02 /* Enable Transmit Buffer Empty Interrupt */
+#define ELSI 0x04 /* Enable RX Status Interrupt */
+
+/* UARTx_IIR Masks */
+#define NINT 0x01 /* Pending Interrupt */
+#define IIR_TX_READY 0x02 /* UART_THR empty */
+#define IIR_RX_READY 0x04 /* Receive data ready */
+#define IIR_LINE_CHANGE 0x06 /* Receive line status */
+#define IIR_STATUS 0x06 /* Highest Priority Pending Interrupt */
+
+/* UARTx_GCTL Masks */
+#define UCEN 0x01 /* Enable UARTx Clocks */
+#define IREN 0x02 /* Enable IrDA Mode */
+#define TPOLC 0x04 /* IrDA TX Polarity Change */
+#define RPOLC 0x08 /* IrDA RX Polarity Change */
+#define FPE 0x10 /* Force Parity Error On Transmit */
+#define FFE 0x20 /* Force Framing Error On Transmit */
+
+
+/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS ****************************/
+/* SPI_CTL Masks */
+#define TIMOD 0x0003 /* Transfer Initiate Mode */
+#define RDBR_CORE 0x0000 /* RDBR Read Initiates, IRQ When RDBR Full */
+#define TDBR_CORE 0x0001 /* TDBR Write Initiates, IRQ When TDBR Empty */
+#define RDBR_DMA 0x0002 /* DMA Read, DMA Until FIFO Empty */
+#define TDBR_DMA 0x0003 /* DMA Write, DMA Until FIFO Full */
+#define SZ 0x0004 /* Send Zero (When TDBR Empty, Send Zero/Last*) */
+#define GM 0x0008 /* Get More (When RDBR Full, Overwrite/Discard*) */
+#define PSSE 0x0010 /* Slave-Select Input Enable */
+#define EMISO 0x0020 /* Enable MISO As Output */
+#define SIZE 0x0100 /* Size of Words (16/8* Bits) */
+#define LSBF 0x0200 /* LSB First */
+#define CPHA 0x0400 /* Clock Phase */
+#define CPOL 0x0800 /* Clock Polarity */
+#define MSTR 0x1000 /* Master/Slave* */
+#define WOM 0x2000 /* Write Open Drain Master */
+#define SPE 0x4000 /* SPI Enable */
+
+/* SPI_FLG Masks */
+#define FLS1 0x0002 /* Enables SPI_FLOUT1 as SPI Slave-Select Output */
+#define FLS2 0x0004 /* Enables SPI_FLOUT2 as SPI Slave-Select Output */
+#define FLS3 0x0008 /* Enables SPI_FLOUT3 as SPI Slave-Select Output */
+#define FLS4 0x0010 /* Enables SPI_FLOUT4 as SPI Slave-Select Output */
+#define FLS5 0x0020 /* Enables SPI_FLOUT5 as SPI Slave-Select Output */
+#define FLS6 0x0040 /* Enables SPI_FLOUT6 as SPI Slave-Select Output */
+#define FLS7 0x0080 /* Enables SPI_FLOUT7 as SPI Slave-Select Output */
+#define FLG1 0xFDFF /* Activates SPI_FLOUT1 */
+#define FLG2 0xFBFF /* Activates SPI_FLOUT2 */
+#define FLG3 0xF7FF /* Activates SPI_FLOUT3 */
+#define FLG4 0xEFFF /* Activates SPI_FLOUT4 */
+#define FLG5 0xDFFF /* Activates SPI_FLOUT5 */
+#define FLG6 0xBFFF /* Activates SPI_FLOUT6 */
+#define FLG7 0x7FFF /* Activates SPI_FLOUT7 */
+
+/* SPI_STAT Masks */
+#define SPIF 0x0001 /* SPI Finished (Single-Word Transfer Complete) */
+#define MODF 0x0002 /* Mode Fault Error (Another Device Tried To Become Master) */
+#define TXE 0x0004 /* Transmission Error (Data Sent With No New Data In TDBR) */
+#define TXS 0x0008 /* SPI_TDBR Data Buffer Status (Full/Empty*) */
+#define RBSY 0x0010 /* Receive Error (Data Received With RDBR Full) */
+#define RXS 0x0020 /* SPI_RDBR Data Buffer Status (Full/Empty*) */
+#define TXCOL 0x0040 /* Transmit Collision Error (Corrupt Data May Have Been Sent) */
+
+
+/* **************** GENERAL PURPOSE TIMER MASKS **********************/
+/* TIMER_ENABLE Masks */
+#define TIMEN0 0x0001 /* Enable Timer 0 */
+#define TIMEN1 0x0002 /* Enable Timer 1 */
+#define TIMEN2 0x0004 /* Enable Timer 2 */
+#define TIMEN3 0x0008 /* Enable Timer 3 */
+#define TIMEN4 0x0010 /* Enable Timer 4 */
+#define TIMEN5 0x0020 /* Enable Timer 5 */
+#define TIMEN6 0x0040 /* Enable Timer 6 */
+#define TIMEN7 0x0080 /* Enable Timer 7 */
+
+/* TIMER_DISABLE Masks */
+#define TIMDIS0 TIMEN0 /* Disable Timer 0 */
+#define TIMDIS1 TIMEN1 /* Disable Timer 1 */
+#define TIMDIS2 TIMEN2 /* Disable Timer 2 */
+#define TIMDIS3 TIMEN3 /* Disable Timer 3 */
+#define TIMDIS4 TIMEN4 /* Disable Timer 4 */
+#define TIMDIS5 TIMEN5 /* Disable Timer 5 */
+#define TIMDIS6 TIMEN6 /* Disable Timer 6 */
+#define TIMDIS7 TIMEN7 /* Disable Timer 7 */
+
+/* TIMER_STATUS Masks */
+#define TIMIL0 0x00000001 /* Timer 0 Interrupt */
+#define TIMIL1 0x00000002 /* Timer 1 Interrupt */
+#define TIMIL2 0x00000004 /* Timer 2 Interrupt */
+#define TIMIL3 0x00000008 /* Timer 3 Interrupt */
+#define TOVF_ERR0 0x00000010 /* Timer 0 Counter Overflow */
+#define TOVF_ERR1 0x00000020 /* Timer 1 Counter Overflow */
+#define TOVF_ERR2 0x00000040 /* Timer 2 Counter Overflow */
+#define TOVF_ERR3 0x00000080 /* Timer 3 Counter Overflow */
+#define TRUN0 0x00001000 /* Timer 0 Slave Enable Status */
+#define TRUN1 0x00002000 /* Timer 1 Slave Enable Status */
+#define TRUN2 0x00004000 /* Timer 2 Slave Enable Status */
+#define TRUN3 0x00008000 /* Timer 3 Slave Enable Status */
+#define TIMIL4 0x00010000 /* Timer 4 Interrupt */
+#define TIMIL5 0x00020000 /* Timer 5 Interrupt */
+#define TIMIL6 0x00040000 /* Timer 6 Interrupt */
+#define TIMIL7 0x00080000 /* Timer 7 Interrupt */
+#define TOVF_ERR4 0x00100000 /* Timer 4 Counter Overflow */
+#define TOVF_ERR5 0x00200000 /* Timer 5 Counter Overflow */
+#define TOVF_ERR6 0x00400000 /* Timer 6 Counter Overflow */
+#define TOVF_ERR7 0x00800000 /* Timer 7 Counter Overflow */
+#define TRUN4 0x10000000 /* Timer 4 Slave Enable Status */
+#define TRUN5 0x20000000 /* Timer 5 Slave Enable Status */
+#define TRUN6 0x40000000 /* Timer 6 Slave Enable Status */
+#define TRUN7 0x80000000 /* Timer 7 Slave Enable Status */
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 TOVF_ERR0
+#define TOVL_ERR1 TOVF_ERR1
+#define TOVL_ERR2 TOVF_ERR2
+#define TOVL_ERR3 TOVF_ERR3
+#define TOVL_ERR4 TOVF_ERR4
+#define TOVL_ERR5 TOVF_ERR5
+#define TOVL_ERR6 TOVF_ERR6
+#define TOVL_ERR7 TOVF_ERR7
+
+/* TIMERx_CONFIG Masks */
+#define PWM_OUT 0x0001 /* Pulse-Width Modulation Output Mode */
+#define WDTH_CAP 0x0002 /* Width Capture Input Mode */
+#define EXT_CLK 0x0003 /* External Clock Mode */
+#define PULSE_HI 0x0004 /* Action Pulse (Positive/Negative*) */
+#define PERIOD_CNT 0x0008 /* Period Count */
+#define IRQ_ENA 0x0010 /* Interrupt Request Enable */
+#define TIN_SEL 0x0020 /* Timer Input Select */
+#define OUT_DIS 0x0040 /* Output Pad Disable */
+#define CLK_SEL 0x0080 /* Timer Clock Select */
+#define TOGGLE_HI 0x0100 /* PWM_OUT PULSE_HI Toggle Mode */
+#define EMU_RUN 0x0200 /* Emulation Behavior Select */
+#define ERR_TYP 0xC000 /* Error Type */
+
+
+/* ****************** GPIO PORTS F, G, H MASKS ***********************/
+/* General Purpose IO (0xFFC00700 - 0xFFC007FF) Masks */
+/* Port F Masks */
+#define PF0 0x0001
+#define PF1 0x0002
+#define PF2 0x0004
+#define PF3 0x0008
+#define PF4 0x0010
+#define PF5 0x0020
+#define PF6 0x0040
+#define PF7 0x0080
+#define PF8 0x0100
+#define PF9 0x0200
+#define PF10 0x0400
+#define PF11 0x0800
+#define PF12 0x1000
+#define PF13 0x2000
+#define PF14 0x4000
+#define PF15 0x8000
+
+/* Port G Masks */
+#define PG0 0x0001
+#define PG1 0x0002
+#define PG2 0x0004
+#define PG3 0x0008
+#define PG4 0x0010
+#define PG5 0x0020
+#define PG6 0x0040
+#define PG7 0x0080
+#define PG8 0x0100
+#define PG9 0x0200
+#define PG10 0x0400
+#define PG11 0x0800
+#define PG12 0x1000
+#define PG13 0x2000
+#define PG14 0x4000
+#define PG15 0x8000
+
+/* Port H Masks */
+#define PH0 0x0001
+#define PH1 0x0002
+#define PH2 0x0004
+#define PH3 0x0008
+#define PH4 0x0010
+#define PH5 0x0020
+#define PH6 0x0040
+#define PH7 0x0080
+
+
+/* ******************* SERIAL PORT MASKS **************************************/
+/* SPORTx_TCR1 Masks */
+#define TSPEN 0x0001 /* Transmit Enable */
+#define ITCLK 0x0002 /* Internal Transmit Clock Select */
+#define DTYPE_NORM 0x0004 /* Data Format Normal */
+#define DTYPE_ULAW 0x0008 /* Compand Using u-Law */
+#define DTYPE_ALAW 0x000C /* Compand Using A-Law */
+#define TLSBIT 0x0010 /* Transmit Bit Order */
+#define ITFS 0x0200 /* Internal Transmit Frame Sync Select */
+#define TFSR 0x0400 /* Transmit Frame Sync Required Select */
+#define DITFS 0x0800 /* Data-Independent Transmit Frame Sync Select */
+#define LTFS 0x1000 /* Low Transmit Frame Sync Select */
+#define LATFS 0x2000 /* Late Transmit Frame Sync Select */
+#define TCKFE 0x4000 /* Clock Falling Edge Select */
+
+/* SPORTx_TCR2 Masks and Macro */
+#define SLEN(x) ((x)&0x1F) /* SPORT TX Word Length (2 - 31) */
+#define TXSE 0x0100 /* TX Secondary Enable */
+#define TSFSE 0x0200 /* Transmit Stereo Frame Sync Enable */
+#define TRFST 0x0400 /* Left/Right Order (1 = Right Channel 1st) */
+
+/* SPORTx_RCR1 Masks */
+#define RSPEN 0x0001 /* Receive Enable */
+#define IRCLK 0x0002 /* Internal Receive Clock Select */
+#define DTYPE_NORM 0x0004 /* Data Format Normal */
+#define DTYPE_ULAW 0x0008 /* Compand Using u-Law */
+#define DTYPE_ALAW 0x000C /* Compand Using A-Law */
+#define RLSBIT 0x0010 /* Receive Bit Order */
+#define IRFS 0x0200 /* Internal Receive Frame Sync Select */
+#define RFSR 0x0400 /* Receive Frame Sync Required Select */
+#define LRFS 0x1000 /* Low Receive Frame Sync Select */
+#define LARFS 0x2000 /* Late Receive Frame Sync Select */
+#define RCKFE 0x4000 /* Clock Falling Edge Select */
+
+/* SPORTx_RCR2 Masks */
+#define SLEN(x) ((x)&0x1F) /* SPORT RX Word Length (2 - 31) */
+#define RXSE 0x0100 /* RX Secondary Enable */
+#define RSFSE 0x0200 /* RX Stereo Frame Sync Enable */
+#define RRFST 0x0400 /* Right-First Data Order */
+
+/* SPORTx_STAT Masks */
+#define RXNE 0x0001 /* Receive FIFO Not Empty Status */
+#define RUVF 0x0002 /* Sticky Receive Underflow Status */
+#define ROVF 0x0004 /* Sticky Receive Overflow Status */
+#define TXF 0x0008 /* Transmit FIFO Full Status */
+#define TUVF 0x0010 /* Sticky Transmit Underflow Status */
+#define TOVF 0x0020 /* Sticky Transmit Overflow Status */
+#define TXHRE 0x0040 /* Transmit Hold Register Empty */
+
+/* SPORTx_MCMC1 Macros */
+#define SP_WOFF(x) ((x) & 0x3FF) /* Multichannel Window Offset Field */
+
+/* Only use WSIZE Macro With Logic OR While Setting Lower Order Bits */
+#define SP_WSIZE(x) (((((x)>>0x3)-1)&0xF) << 0xC) /* Multichannel Window Size = (x/8)-1 */
+
+/* SPORTx_MCMC2 Masks */
+#define REC_BYPASS 0x0000 /* Bypass Mode (No Clock Recovery) */
+#define REC_2FROM4 0x0002 /* Recover 2 MHz Clock from 4 MHz Clock */
+#define REC_8FROM16 0x0003 /* Recover 8 MHz Clock from 16 MHz Clock */
+#define MCDTXPE 0x0004 /* Multichannel DMA Transmit Packing */
+#define MCDRXPE 0x0008 /* Multichannel DMA Receive Packing */
+#define MCMEN 0x0010 /* Multichannel Frame Mode Enable */
+#define FSDR 0x0080 /* Multichannel Frame Sync to Data Relationship */
+#define MFD_0 0x0000 /* Multichannel Frame Delay = 0 */
+#define MFD_1 0x1000 /* Multichannel Frame Delay = 1 */
+#define MFD_2 0x2000 /* Multichannel Frame Delay = 2 */
+#define MFD_3 0x3000 /* Multichannel Frame Delay = 3 */
+#define MFD_4 0x4000 /* Multichannel Frame Delay = 4 */
+#define MFD_5 0x5000 /* Multichannel Frame Delay = 5 */
+#define MFD_6 0x6000 /* Multichannel Frame Delay = 6 */
+#define MFD_7 0x7000 /* Multichannel Frame Delay = 7 */
+#define MFD_8 0x8000 /* Multichannel Frame Delay = 8 */
+#define MFD_9 0x9000 /* Multichannel Frame Delay = 9 */
+#define MFD_10 0xA000 /* Multichannel Frame Delay = 10 */
+#define MFD_11 0xB000 /* Multichannel Frame Delay = 11 */
+#define MFD_12 0xC000 /* Multichannel Frame Delay = 12 */
+#define MFD_13 0xD000 /* Multichannel Frame Delay = 13 */
+#define MFD_14 0xE000 /* Multichannel Frame Delay = 14 */
+#define MFD_15 0xF000 /* Multichannel Frame Delay = 15 */
+
+
+/* ********************* ASYNCHRONOUS MEMORY CONTROLLER MASKS *************************/
+/* EBIU_AMGCTL Masks */
+#define AMCKEN 0x0001 /* Enable CLKOUT */
+#define AMBEN_NONE 0x0000 /* All Banks Disabled */
+#define AMBEN_B0 0x0002 /* Enable Async Memory Bank 0 only */
+#define AMBEN_B0_B1 0x0004 /* Enable Async Memory Banks 0 & 1 only */
+#define AMBEN_B0_B1_B2 0x0006 /* Enable Async Memory Banks 0, 1, and 2 */
+#define AMBEN_ALL 0x0008 /* Enable Async Memory Banks (all) 0, 1, 2, and 3 */
+
+/* EBIU_AMBCTL0 Masks */
+#define B0RDYEN 0x00000001 /* Bank 0 (B0) RDY Enable */
+#define B0RDYPOL 0x00000002 /* B0 RDY Active High */
+#define B0TT_1 0x00000004 /* B0 Transition Time (Read to Write) = 1 cycle */
+#define B0TT_2 0x00000008 /* B0 Transition Time (Read to Write) = 2 cycles */
+#define B0TT_3 0x0000000C /* B0 Transition Time (Read to Write) = 3 cycles */
+#define B0TT_4 0x00000000 /* B0 Transition Time (Read to Write) = 4 cycles */
+#define B0ST_1 0x00000010 /* B0 Setup Time (AOE to Read/Write) = 1 cycle */
+#define B0ST_2 0x00000020 /* B0 Setup Time (AOE to Read/Write) = 2 cycles */
+#define B0ST_3 0x00000030 /* B0 Setup Time (AOE to Read/Write) = 3 cycles */
+#define B0ST_4 0x00000000 /* B0 Setup Time (AOE to Read/Write) = 4 cycles */
+#define B0HT_1 0x00000040 /* B0 Hold Time (~Read/Write to ~AOE) = 1 cycle */
+#define B0HT_2 0x00000080 /* B0 Hold Time (~Read/Write to ~AOE) = 2 cycles */
+#define B0HT_3 0x000000C0 /* B0 Hold Time (~Read/Write to ~AOE) = 3 cycles */
+#define B0HT_0 0x00000000 /* B0 Hold Time (~Read/Write to ~AOE) = 0 cycles */
+#define B0RAT_1 0x00000100 /* B0 Read Access Time = 1 cycle */
+#define B0RAT_2 0x00000200 /* B0 Read Access Time = 2 cycles */
+#define B0RAT_3 0x00000300 /* B0 Read Access Time = 3 cycles */
+#define B0RAT_4 0x00000400 /* B0 Read Access Time = 4 cycles */
+#define B0RAT_5 0x00000500 /* B0 Read Access Time = 5 cycles */
+#define B0RAT_6 0x00000600 /* B0 Read Access Time = 6 cycles */
+#define B0RAT_7 0x00000700 /* B0 Read Access Time = 7 cycles */
+#define B0RAT_8 0x00000800 /* B0 Read Access Time = 8 cycles */
+#define B0RAT_9 0x00000900 /* B0 Read Access Time = 9 cycles */
+#define B0RAT_10 0x00000A00 /* B0 Read Access Time = 10 cycles */
+#define B0RAT_11 0x00000B00 /* B0 Read Access Time = 11 cycles */
+#define B0RAT_12 0x00000C00 /* B0 Read Access Time = 12 cycles */
+#define B0RAT_13 0x00000D00 /* B0 Read Access Time = 13 cycles */
+#define B0RAT_14 0x00000E00 /* B0 Read Access Time = 14 cycles */
+#define B0RAT_15 0x00000F00 /* B0 Read Access Time = 15 cycles */
+#define B0WAT_1 0x00001000 /* B0 Write Access Time = 1 cycle */
+#define B0WAT_2 0x00002000 /* B0 Write Access Time = 2 cycles */
+#define B0WAT_3 0x00003000 /* B0 Write Access Time = 3 cycles */
+#define B0WAT_4 0x00004000 /* B0 Write Access Time = 4 cycles */
+#define B0WAT_5 0x00005000 /* B0 Write Access Time = 5 cycles */
+#define B0WAT_6 0x00006000 /* B0 Write Access Time = 6 cycles */
+#define B0WAT_7 0x00007000 /* B0 Write Access Time = 7 cycles */
+#define B0WAT_8 0x00008000 /* B0 Write Access Time = 8 cycles */
+#define B0WAT_9 0x00009000 /* B0 Write Access Time = 9 cycles */
+#define B0WAT_10 0x0000A000 /* B0 Write Access Time = 10 cycles */
+#define B0WAT_11 0x0000B000 /* B0 Write Access Time = 11 cycles */
+#define B0WAT_12 0x0000C000 /* B0 Write Access Time = 12 cycles */
+#define B0WAT_13 0x0000D000 /* B0 Write Access Time = 13 cycles */
+#define B0WAT_14 0x0000E000 /* B0 Write Access Time = 14 cycles */
+#define B0WAT_15 0x0000F000 /* B0 Write Access Time = 15 cycles */
+
+#define B1RDYEN 0x00010000 /* Bank 1 (B1) RDY Enable */
+#define B1RDYPOL 0x00020000 /* B1 RDY Active High */
+#define B1TT_1 0x00040000 /* B1 Transition Time (Read to Write) = 1 cycle */
+#define B1TT_2 0x00080000 /* B1 Transition Time (Read to Write) = 2 cycles */
+#define B1TT_3 0x000C0000 /* B1 Transition Time (Read to Write) = 3 cycles */
+#define B1TT_4 0x00000000 /* B1 Transition Time (Read to Write) = 4 cycles */
+#define B1ST_1 0x00100000 /* B1 Setup Time (AOE to Read/Write) = 1 cycle */
+#define B1ST_2 0x00200000 /* B1 Setup Time (AOE to Read/Write) = 2 cycles */
+#define B1ST_3 0x00300000 /* B1 Setup Time (AOE to Read/Write) = 3 cycles */
+#define B1ST_4 0x00000000 /* B1 Setup Time (AOE to Read/Write) = 4 cycles */
+#define B1HT_1 0x00400000 /* B1 Hold Time (~Read/Write to ~AOE) = 1 cycle */
+#define B1HT_2 0x00800000 /* B1 Hold Time (~Read/Write to ~AOE) = 2 cycles */
+#define B1HT_3 0x00C00000 /* B1 Hold Time (~Read/Write to ~AOE) = 3 cycles */
+#define B1HT_0 0x00000000 /* B1 Hold Time (~Read/Write to ~AOE) = 0 cycles */
+#define B1RAT_1 0x01000000 /* B1 Read Access Time = 1 cycle */
+#define B1RAT_2 0x02000000 /* B1 Read Access Time = 2 cycles */
+#define B1RAT_3 0x03000000 /* B1 Read Access Time = 3 cycles */
+#define B1RAT_4 0x04000000 /* B1 Read Access Time = 4 cycles */
+#define B1RAT_5 0x05000000 /* B1 Read Access Time = 5 cycles */
+#define B1RAT_6 0x06000000 /* B1 Read Access Time = 6 cycles */
+#define B1RAT_7 0x07000000 /* B1 Read Access Time = 7 cycles */
+#define B1RAT_8 0x08000000 /* B1 Read Access Time = 8 cycles */
+#define B1RAT_9 0x09000000 /* B1 Read Access Time = 9 cycles */
+#define B1RAT_10 0x0A000000 /* B1 Read Access Time = 10 cycles */
+#define B1RAT_11 0x0B000000 /* B1 Read Access Time = 11 cycles */
+#define B1RAT_12 0x0C000000 /* B1 Read Access Time = 12 cycles */
+#define B1RAT_13 0x0D000000 /* B1 Read Access Time = 13 cycles */
+#define B1RAT_14 0x0E000000 /* B1 Read Access Time = 14 cycles */
+#define B1RAT_15 0x0F000000 /* B1 Read Access Time = 15 cycles */
+#define B1WAT_1 0x10000000 /* B1 Write Access Time = 1 cycle */
+#define B1WAT_2 0x20000000 /* B1 Write Access Time = 2 cycles */
+#define B1WAT_3 0x30000000 /* B1 Write Access Time = 3 cycles */
+#define B1WAT_4 0x40000000 /* B1 Write Access Time = 4 cycles */
+#define B1WAT_5 0x50000000 /* B1 Write Access Time = 5 cycles */
+#define B1WAT_6 0x60000000 /* B1 Write Access Time = 6 cycles */
+#define B1WAT_7 0x70000000 /* B1 Write Access Time = 7 cycles */
+#define B1WAT_8 0x80000000 /* B1 Write Access Time = 8 cycles */
+#define B1WAT_9 0x90000000 /* B1 Write Access Time = 9 cycles */
+#define B1WAT_10 0xA0000000 /* B1 Write Access Time = 10 cycles */
+#define B1WAT_11 0xB0000000 /* B1 Write Access Time = 11 cycles */
+#define B1WAT_12 0xC0000000 /* B1 Write Access Time = 12 cycles */
+#define B1WAT_13 0xD0000000 /* B1 Write Access Time = 13 cycles */
+#define B1WAT_14 0xE0000000 /* B1 Write Access Time = 14 cycles */
+#define B1WAT_15 0xF0000000 /* B1 Write Access Time = 15 cycles */
+
+/* EBIU_AMBCTL1 Masks */
+#define B2RDYEN 0x00000001 /* Bank 2 (B2) RDY Enable */
+#define B2RDYPOL 0x00000002 /* B2 RDY Active High */
+#define B2TT_1 0x00000004 /* B2 Transition Time (Read to Write) = 1 cycle */
+#define B2TT_2 0x00000008 /* B2 Transition Time (Read to Write) = 2 cycles */
+#define B2TT_3 0x0000000C /* B2 Transition Time (Read to Write) = 3 cycles */
+#define B2TT_4 0x00000000 /* B2 Transition Time (Read to Write) = 4 cycles */
+#define B2ST_1 0x00000010 /* B2 Setup Time (AOE to Read/Write) = 1 cycle */
+#define B2ST_2 0x00000020 /* B2 Setup Time (AOE to Read/Write) = 2 cycles */
+#define B2ST_3 0x00000030 /* B2 Setup Time (AOE to Read/Write) = 3 cycles */
+#define B2ST_4 0x00000000 /* B2 Setup Time (AOE to Read/Write) = 4 cycles */
+#define B2HT_1 0x00000040 /* B2 Hold Time (~Read/Write to ~AOE) = 1 cycle */
+#define B2HT_2 0x00000080 /* B2 Hold Time (~Read/Write to ~AOE) = 2 cycles */
+#define B2HT_3 0x000000C0 /* B2 Hold Time (~Read/Write to ~AOE) = 3 cycles */
+#define B2HT_0 0x00000000 /* B2 Hold Time (~Read/Write to ~AOE) = 0 cycles */
+#define B2RAT_1 0x00000100 /* B2 Read Access Time = 1 cycle */
+#define B2RAT_2 0x00000200 /* B2 Read Access Time = 2 cycles */
+#define B2RAT_3 0x00000300 /* B2 Read Access Time = 3 cycles */
+#define B2RAT_4 0x00000400 /* B2 Read Access Time = 4 cycles */
+#define B2RAT_5 0x00000500 /* B2 Read Access Time = 5 cycles */
+#define B2RAT_6 0x00000600 /* B2 Read Access Time = 6 cycles */
+#define B2RAT_7 0x00000700 /* B2 Read Access Time = 7 cycles */
+#define B2RAT_8 0x00000800 /* B2 Read Access Time = 8 cycles */
+#define B2RAT_9 0x00000900 /* B2 Read Access Time = 9 cycles */
+#define B2RAT_10 0x00000A00 /* B2 Read Access Time = 10 cycles */
+#define B2RAT_11 0x00000B00 /* B2 Read Access Time = 11 cycles */
+#define B2RAT_12 0x00000C00 /* B2 Read Access Time = 12 cycles */
+#define B2RAT_13 0x00000D00 /* B2 Read Access Time = 13 cycles */
+#define B2RAT_14 0x00000E00 /* B2 Read Access Time = 14 cycles */
+#define B2RAT_15 0x00000F00 /* B2 Read Access Time = 15 cycles */
+#define B2WAT_1 0x00001000 /* B2 Write Access Time = 1 cycle */
+#define B2WAT_2 0x00002000 /* B2 Write Access Time = 2 cycles */
+#define B2WAT_3 0x00003000 /* B2 Write Access Time = 3 cycles */
+#define B2WAT_4 0x00004000 /* B2 Write Access Time = 4 cycles */
+#define B2WAT_5 0x00005000 /* B2 Write Access Time = 5 cycles */
+#define B2WAT_6 0x00006000 /* B2 Write Access Time = 6 cycles */
+#define B2WAT_7 0x00007000 /* B2 Write Access Time = 7 cycles */
+#define B2WAT_8 0x00008000 /* B2 Write Access Time = 8 cycles */
+#define B2WAT_9 0x00009000 /* B2 Write Access Time = 9 cycles */
+#define B2WAT_10 0x0000A000 /* B2 Write Access Time = 10 cycles */
+#define B2WAT_11 0x0000B000 /* B2 Write Access Time = 11 cycles */
+#define B2WAT_12 0x0000C000 /* B2 Write Access Time = 12 cycles */
+#define B2WAT_13 0x0000D000 /* B2 Write Access Time = 13 cycles */
+#define B2WAT_14 0x0000E000 /* B2 Write Access Time = 14 cycles */
+#define B2WAT_15 0x0000F000 /* B2 Write Access Time = 15 cycles */
+
+#define B3RDYEN 0x00010000 /* Bank 3 (B3) RDY Enable */
+#define B3RDYPOL 0x00020000 /* B3 RDY Active High */
+#define B3TT_1 0x00040000 /* B3 Transition Time (Read to Write) = 1 cycle */
+#define B3TT_2 0x00080000 /* B3 Transition Time (Read to Write) = 2 cycles */
+#define B3TT_3 0x000C0000 /* B3 Transition Time (Read to Write) = 3 cycles */
+#define B3TT_4 0x00000000 /* B3 Transition Time (Read to Write) = 4 cycles */
+#define B3ST_1 0x00100000 /* B3 Setup Time (AOE to Read/Write) = 1 cycle */
+#define B3ST_2 0x00200000 /* B3 Setup Time (AOE to Read/Write) = 2 cycles */
+#define B3ST_3 0x00300000 /* B3 Setup Time (AOE to Read/Write) = 3 cycles */
+#define B3ST_4 0x00000000 /* B3 Setup Time (AOE to Read/Write) = 4 cycles */
+#define B3HT_1 0x00400000 /* B3 Hold Time (~Read/Write to ~AOE) = 1 cycle */
+#define B3HT_2 0x00800000 /* B3 Hold Time (~Read/Write to ~AOE) = 2 cycles */
+#define B3HT_3 0x00C00000 /* B3 Hold Time (~Read/Write to ~AOE) = 3 cycles */
+#define B3HT_0 0x00000000 /* B3 Hold Time (~Read/Write to ~AOE) = 0 cycles */
+#define B3RAT_1 0x01000000 /* B3 Read Access Time = 1 cycle */
+#define B3RAT_2 0x02000000 /* B3 Read Access Time = 2 cycles */
+#define B3RAT_3 0x03000000 /* B3 Read Access Time = 3 cycles */
+#define B3RAT_4 0x04000000 /* B3 Read Access Time = 4 cycles */
+#define B3RAT_5 0x05000000 /* B3 Read Access Time = 5 cycles */
+#define B3RAT_6 0x06000000 /* B3 Read Access Time = 6 cycles */
+#define B3RAT_7 0x07000000 /* B3 Read Access Time = 7 cycles */
+#define B3RAT_8 0x08000000 /* B3 Read Access Time = 8 cycles */
+#define B3RAT_9 0x09000000 /* B3 Read Access Time = 9 cycles */
+#define B3RAT_10 0x0A000000 /* B3 Read Access Time = 10 cycles */
+#define B3RAT_11 0x0B000000 /* B3 Read Access Time = 11 cycles */
+#define B3RAT_12 0x0C000000 /* B3 Read Access Time = 12 cycles */
+#define B3RAT_13 0x0D000000 /* B3 Read Access Time = 13 cycles */
+#define B3RAT_14 0x0E000000 /* B3 Read Access Time = 14 cycles */
+#define B3RAT_15 0x0F000000 /* B3 Read Access Time = 15 cycles */
+#define B3WAT_1 0x10000000 /* B3 Write Access Time = 1 cycle */
+#define B3WAT_2 0x20000000 /* B3 Write Access Time = 2 cycles */
+#define B3WAT_3 0x30000000 /* B3 Write Access Time = 3 cycles */
+#define B3WAT_4 0x40000000 /* B3 Write Access Time = 4 cycles */
+#define B3WAT_5 0x50000000 /* B3 Write Access Time = 5 cycles */
+#define B3WAT_6 0x60000000 /* B3 Write Access Time = 6 cycles */
+#define B3WAT_7 0x70000000 /* B3 Write Access Time = 7 cycles */
+#define B3WAT_8 0x80000000 /* B3 Write Access Time = 8 cycles */
+#define B3WAT_9 0x90000000 /* B3 Write Access Time = 9 cycles */
+#define B3WAT_10 0xA0000000 /* B3 Write Access Time = 10 cycles */
+#define B3WAT_11 0xB0000000 /* B3 Write Access Time = 11 cycles */
+#define B3WAT_12 0xC0000000 /* B3 Write Access Time = 12 cycles */
+#define B3WAT_13 0xD0000000 /* B3 Write Access Time = 13 cycles */
+#define B3WAT_14 0xE0000000 /* B3 Write Access Time = 14 cycles */
+#define B3WAT_15 0xF0000000 /* B3 Write Access Time = 15 cycles */
+
+
+/* ********************** SDRAM CONTROLLER MASKS **********************************************/
+/* EBIU_SDGCTL Masks */
+#define SCTLE 0x00000001 /* Enable SDRAM Signals */
+#define CL_2 0x00000008 /* SDRAM CAS Latency = 2 cycles */
+#define CL_3 0x0000000C /* SDRAM CAS Latency = 3 cycles */
+#define PASR_ALL 0x00000000 /* All 4 SDRAM Banks Refreshed In Self-Refresh */
+#define PASR_B0_B1 0x00000010 /* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh */
+#define PASR_B0 0x00000020 /* Only SDRAM Bank 0 Is Refreshed In Self-Refresh */
+#define TRAS_1 0x00000040 /* SDRAM tRAS = 1 cycle */
+#define TRAS_2 0x00000080 /* SDRAM tRAS = 2 cycles */
+#define TRAS_3 0x000000C0 /* SDRAM tRAS = 3 cycles */
+#define TRAS_4 0x00000100 /* SDRAM tRAS = 4 cycles */
+#define TRAS_5 0x00000140 /* SDRAM tRAS = 5 cycles */
+#define TRAS_6 0x00000180 /* SDRAM tRAS = 6 cycles */
+#define TRAS_7 0x000001C0 /* SDRAM tRAS = 7 cycles */
+#define TRAS_8 0x00000200 /* SDRAM tRAS = 8 cycles */
+#define TRAS_9 0x00000240 /* SDRAM tRAS = 9 cycles */
+#define TRAS_10 0x00000280 /* SDRAM tRAS = 10 cycles */
+#define TRAS_11 0x000002C0 /* SDRAM tRAS = 11 cycles */
+#define TRAS_12 0x00000300 /* SDRAM tRAS = 12 cycles */
+#define TRAS_13 0x00000340 /* SDRAM tRAS = 13 cycles */
+#define TRAS_14 0x00000380 /* SDRAM tRAS = 14 cycles */
+#define TRAS_15 0x000003C0 /* SDRAM tRAS = 15 cycles */
+#define TRP_1 0x00000800 /* SDRAM tRP = 1 cycle */
+#define TRP_2 0x00001000 /* SDRAM tRP = 2 cycles */
+#define TRP_3 0x00001800 /* SDRAM tRP = 3 cycles */
+#define TRP_4 0x00002000 /* SDRAM tRP = 4 cycles */
+#define TRP_5 0x00002800 /* SDRAM tRP = 5 cycles */
+#define TRP_6 0x00003000 /* SDRAM tRP = 6 cycles */
+#define TRP_7 0x00003800 /* SDRAM tRP = 7 cycles */
+#define TRCD_1 0x00008000 /* SDRAM tRCD = 1 cycle */
+#define TRCD_2 0x00010000 /* SDRAM tRCD = 2 cycles */
+#define TRCD_3 0x00018000 /* SDRAM tRCD = 3 cycles */
+#define TRCD_4 0x00020000 /* SDRAM tRCD = 4 cycles */
+#define TRCD_5 0x00028000 /* SDRAM tRCD = 5 cycles */
+#define TRCD_6 0x00030000 /* SDRAM tRCD = 6 cycles */
+#define TRCD_7 0x00038000 /* SDRAM tRCD = 7 cycles */
+#define TWR_1 0x00080000 /* SDRAM tWR = 1 cycle */
+#define TWR_2 0x00100000 /* SDRAM tWR = 2 cycles */
+#define TWR_3 0x00180000 /* SDRAM tWR = 3 cycles */
+#define PUPSD 0x00200000 /* Power-Up Start Delay (15 SCLK Cycles Delay) */
+#define PSM 0x00400000 /* Power-Up Sequence (Mode Register Before/After* Refresh) */
+#define PSS 0x00800000 /* Enable Power-Up Sequence on Next SDRAM Access */
+#define SRFS 0x01000000 /* Enable SDRAM Self-Refresh Mode */
+#define EBUFE 0x02000000 /* Enable External Buffering Timing */
+#define FBBRW 0x04000000 /* Enable Fast Back-To-Back Read To Write */
+#define EMREN 0x10000000 /* Extended Mode Register Enable */
+#define TCSR 0x20000000 /* Temp-Compensated Self-Refresh Value (85/45* Deg C) */
+#define CDDBG 0x40000000 /* Tristate SDRAM Controls During Bus Grant */
+
+/* EBIU_SDBCTL Masks */
+#define EBE 0x0001 /* Enable SDRAM External Bank */
+#define EBSZ_16 0x0000 /* SDRAM External Bank Size = 16MB */
+#define EBSZ_32 0x0002 /* SDRAM External Bank Size = 32MB */
+#define EBSZ_64 0x0004 /* SDRAM External Bank Size = 64MB */
+#define EBSZ_128 0x0006 /* SDRAM External Bank Size = 128MB */
+#define EBSZ_256 0x0008 /* SDRAM External Bank Size = 256MB */
+#define EBSZ_512 0x000A /* SDRAM External Bank Size = 512MB */
+#define EBCAW_8 0x0000 /* SDRAM External Bank Column Address Width = 8 Bits */
+#define EBCAW_9 0x0010 /* SDRAM External Bank Column Address Width = 9 Bits */
+#define EBCAW_10 0x0020 /* SDRAM External Bank Column Address Width = 10 Bits */
+#define EBCAW_11 0x0030 /* SDRAM External Bank Column Address Width = 11 Bits */
+
+/* EBIU_SDSTAT Masks */
+#define SDCI 0x0001 /* SDRAM Controller Idle */
+#define SDSRA 0x0002 /* SDRAM Self-Refresh Active */
+#define SDPUA 0x0004 /* SDRAM Power-Up Active */
+#define SDRS 0x0008 /* SDRAM Will Power-Up On Next Access */
+#define SDEASE 0x0010 /* SDRAM EAB Sticky Error Status */
+#define BGSTAT 0x0020 /* Bus Grant Status */
+
+
+/* ************************** DMA CONTROLLER MASKS ********************************/
+/* DMAx_CONFIG, MDMA_yy_CONFIG Masks */
+#define DMAEN 0x0001 /* DMA Channel Enable */
+#define WNR 0x0002 /* Channel Direction (W/R*) */
+#define WDSIZE_8 0x0000 /* Transfer Word Size = 8 */
+#define WDSIZE_16 0x0004 /* Transfer Word Size = 16 */
+#define WDSIZE_32 0x0008 /* Transfer Word Size = 32 */
+#define DMA2D 0x0010 /* DMA Mode (2D/1D*) */
+#define RESTART 0x0020 /* DMA Buffer Clear */
+#define DI_SEL 0x0040 /* Data Interrupt Timing Select */
+#define DI_EN 0x0080 /* Data Interrupt Enable */
+#define NDSIZE_0 0x0000 /* Next Descriptor Size = 0 (Stop/Autobuffer) */
+#define NDSIZE_1 0x0100 /* Next Descriptor Size = 1 */
+#define NDSIZE_2 0x0200 /* Next Descriptor Size = 2 */
+#define NDSIZE_3 0x0300 /* Next Descriptor Size = 3 */
+#define NDSIZE_4 0x0400 /* Next Descriptor Size = 4 */
+#define NDSIZE_5 0x0500 /* Next Descriptor Size = 5 */
+#define NDSIZE_6 0x0600 /* Next Descriptor Size = 6 */
+#define NDSIZE_7 0x0700 /* Next Descriptor Size = 7 */
+#define NDSIZE_8 0x0800 /* Next Descriptor Size = 8 */
+#define NDSIZE_9 0x0900 /* Next Descriptor Size = 9 */
+#define NDSIZE 0x0900 /* Next Descriptor Size */
+#define DMAFLOW 0x7000 /* Flow Control */
+#define DMAFLOW_STOP 0x0000 /* Stop Mode */
+#define DMAFLOW_AUTO 0x1000 /* Autobuffer Mode */
+#define DMAFLOW_ARRAY 0x4000 /* Descriptor Array Mode */
+#define DMAFLOW_SMALL 0x6000 /* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE 0x7000 /* Large Model Descriptor List Mode */
+
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks */
+#define CTYPE 0x0040 /* DMA Channel Type Indicator (Memory/Peripheral*) */
+#define PMAP 0xF000 /* Peripheral Mapped To This Channel */
+#define PMAP_PPI 0x0000 /* PPI Port DMA */
+#define PMAP_EMACRX 0x1000 /* Ethernet Receive DMA */
+#define PMAP_EMACTX 0x2000 /* Ethernet Transmit DMA */
+#define PMAP_SPORT0RX 0x3000 /* SPORT0 Receive DMA */
+#define PMAP_SPORT0TX 0x4000 /* SPORT0 Transmit DMA */
+#define PMAP_SPORT1RX 0x5000 /* SPORT1 Receive DMA */
+#define PMAP_SPORT1TX 0x6000 /* SPORT1 Transmit DMA */
+#define PMAP_SPI 0x7000 /* SPI Port DMA */
+#define PMAP_UART0RX 0x8000 /* UART0 Port Receive DMA */
+#define PMAP_UART0TX 0x9000 /* UART0 Port Transmit DMA */
+#define PMAP_UART1RX 0xA000 /* UART1 Port Receive DMA */
+#define PMAP_UART1TX 0xB000 /* UART1 Port Transmit DMA */
+
+/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks */
+#define DMA_DONE 0x0001 /* DMA Completion Interrupt Status */
+#define DMA_ERR 0x0002 /* DMA Error Interrupt Status */
+#define DFETCH 0x0004 /* DMA Descriptor Fetch Indicator */
+#define DMA_RUN 0x0008 /* DMA Channel Running Indicator */
+
+
+/* ************ PARALLEL PERIPHERAL INTERFACE (PPI) MASKS *************/
+/* PPI_CONTROL Masks */
+#define PORT_EN 0x0001 /* PPI Port Enable */
+#define PORT_DIR 0x0002 /* PPI Port Direction */
+#define XFR_TYPE 0x000C /* PPI Transfer Type */
+#define PORT_CFG 0x0030 /* PPI Port Configuration */
+#define FLD_SEL 0x0040 /* PPI Active Field Select */
+#define PACK_EN 0x0080 /* PPI Packing Mode */
+#define DMA32 0x0100 /* PPI 32-bit DMA Enable */
+#define SKIP_EN 0x0200 /* PPI Skip Element Enable */
+#define SKIP_EO 0x0400 /* PPI Skip Even/Odd Elements */
+#define DLEN_8 0x0000 /* Data Length = 8 Bits */
+#define DLEN_10 0x0800 /* Data Length = 10 Bits */
+#define DLEN_11 0x1000 /* Data Length = 11 Bits */
+#define DLEN_12 0x1800 /* Data Length = 12 Bits */
+#define DLEN_13 0x2000 /* Data Length = 13 Bits */
+#define DLEN_14 0x2800 /* Data Length = 14 Bits */
+#define DLEN_15 0x3000 /* Data Length = 15 Bits */
+#define DLEN_16 0x3800 /* Data Length = 16 Bits */
+#define DLENGTH 0x3800 /* PPI Data Length */
+#define POLC 0x4000 /* PPI Clock Polarity */
+#define POLS 0x8000 /* PPI Frame Sync Polarity */
+
+/* PPI_STATUS Masks */
+#define FLD 0x0400 /* Field Indicator */
+#define FT_ERR 0x0800 /* Frame Track Error */
+#define OVR 0x1000 /* FIFO Overflow Error */
+#define UNDR 0x2000 /* FIFO Underrun Error */
+#define ERR_DET 0x4000 /* Error Detected Indicator */
+#define ERR_NCOR 0x8000 /* Error Not Corrected Indicator */
+
+
+/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ***********************/
+/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
+#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
+#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
+
+/* TWI_PRESCALE Masks */
+#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
+#define TWI_ENA 0x0080 /* TWI Enable */
+#define SCCB 0x0200 /* SCCB Compatibility Enable */
+
+/* TWI_SLAVE_CTRL Masks */
+#define SEN 0x0001 /* Slave Enable */
+#define SADD_LEN 0x0002 /* Slave Address Length */
+#define STDVAL 0x0004 /* Slave Transmit Data Valid */
+#define NAK 0x0008 /* NAK/ACK* Generated At Conclusion Of Transfer */
+#define GEN 0x0010 /* General Call Adrress Matching Enabled */
+
+/* TWI_SLAVE_STAT Masks */
+#define SDIR 0x0001 /* Slave Transfer Direction (Transmit/Receive*) */
+#define GCALL 0x0002 /* General Call Indicator */
+
+/* TWI_MASTER_CTRL Masks */
+#define MEN 0x0001 /* Master Mode Enable */
+#define MADD_LEN 0x0002 /* Master Address Length */
+#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
+#define FAST 0x0008 /* Use Fast Mode Timing Specs */
+#define STOP 0x0010 /* Issue Stop Condition */
+#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
+#define DCNT 0x3FC0 /* Data Bytes To Transfer */
+#define SDAOVR 0x4000 /* Serial Data Override */
+#define SCLOVR 0x8000 /* Serial Clock Override */
+
+/* TWI_MASTER_STAT Masks */
+#define MPROG 0x0001 /* Master Transfer In Progress */
+#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
+#define ANAK 0x0004 /* Address Not Acknowledged */
+#define DNAK 0x0008 /* Data Not Acknowledged */
+#define BUFRDERR 0x0010 /* Buffer Read Error */
+#define BUFWRERR 0x0020 /* Buffer Write Error */
+#define SDASEN 0x0040 /* Serial Data Sense */
+#define SCLSEN 0x0080 /* Serial Clock Sense */
+#define BUSBUSY 0x0100 /* Bus Busy Indicator */
+
+/* TWI_INT_SRC and TWI_INT_ENABLE Masks */
+#define SINIT 0x0001 /* Slave Transfer Initiated */
+#define SCOMP 0x0002 /* Slave Transfer Complete */
+#define SERR 0x0004 /* Slave Transfer Error */
+#define SOVF 0x0008 /* Slave Overflow */
+#define MCOMP 0x0010 /* Master Transfer Complete */
+#define MERR 0x0020 /* Master Transfer Error */
+#define XMTSERV 0x0040 /* Transmit FIFO Service */
+#define RCVSERV 0x0080 /* Receive FIFO Service */
+
+/* TWI_FIFO_CTRL Masks */
+#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
+#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
+#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
+#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
+
+/* TWI_FIFO_STAT Masks */
+#define XMTSTAT 0x0003 /* Transmit FIFO Status */
+#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
+#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
+#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
+
+#define RCVSTAT 0x000C /* Receive FIFO Status */
+#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
+#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
+#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
+
+
+/* ******************* PIN CONTROL REGISTER MASKS ************************/
+/* PORT_MUX Masks */
+#define PJSE 0x0001 /* Port J SPI/SPORT Enable */
+#define PJSE_SPORT 0x0000 /* Enable TFS0/DT0PRI */
+#define PJSE_SPI 0x0001 /* Enable SPI_SSEL3:2 */
+
+#define PJCE(x) (((x)&0x3)<<1) /* Port J CAN/SPI/SPORT Enable */
+#define PJCE_SPORT 0x0000 /* Enable DR0SEC/DT0SEC */
+#define PJCE_CAN 0x0002 /* Enable CAN RX/TX */
+#define PJCE_SPI 0x0004 /* Enable SPI_SSEL7 */
+
+#define PFDE 0x0008 /* Port F DMA Request Enable */
+#define PFDE_UART 0x0000 /* Enable UART0 RX/TX */
+#define PFDE_DMA 0x0008 /* Enable DMAR1:0 */
+
+#define PFTE 0x0010 /* Port F Timer Enable */
+#define PFTE_UART 0x0000 /* Enable UART1 RX/TX */
+#define PFTE_TIMER 0x0010 /* Enable TMR7:6 */
+
+#define PFS6E 0x0020 /* Port F SPI SSEL 6 Enable */
+#define PFS6E_TIMER 0x0000 /* Enable TMR5 */
+#define PFS6E_SPI 0x0020 /* Enable SPI_SSEL6 */
+
+#define PFS5E 0x0040 /* Port F SPI SSEL 5 Enable */
+#define PFS5E_TIMER 0x0000 /* Enable TMR4 */
+#define PFS5E_SPI 0x0040 /* Enable SPI_SSEL5 */
+
+#define PFS4E 0x0080 /* Port F SPI SSEL 4 Enable */
+#define PFS4E_TIMER 0x0000 /* Enable TMR3 */
+#define PFS4E_SPI 0x0080 /* Enable SPI_SSEL4 */
+
+#define PFFE 0x0100 /* Port F PPI Frame Sync Enable */
+#define PFFE_TIMER 0x0000 /* Enable TMR2 */
+#define PFFE_PPI 0x0100 /* Enable PPI FS3 */
+
+#define PGSE 0x0200 /* Port G SPORT1 Secondary Enable */
+#define PGSE_PPI 0x0000 /* Enable PPI D9:8 */
+#define PGSE_SPORT 0x0200 /* Enable DR1SEC/DT1SEC */
+
+#define PGRE 0x0400 /* Port G SPORT1 Receive Enable */
+#define PGRE_PPI 0x0000 /* Enable PPI D12:10 */
+#define PGRE_SPORT 0x0400 /* Enable DR1PRI/RFS1/RSCLK1 */
+
+#define PGTE 0x0800 /* Port G SPORT1 Transmit Enable */
+#define PGTE_PPI 0x0000 /* Enable PPI D15:13 */
+#define PGTE_SPORT 0x0800 /* Enable DT1PRI/TFS1/TSCLK1 */
+
+
+/* ****************** HANDSHAKE DMA (HDMA) MASKS *********************/
+/* HDMAx_CTL Masks */
+#define HMDMAEN 0x0001 /* Enable Handshake DMA 0/1 */
+#define REP 0x0002 /* HDMA Request Polarity */
+#define UTE 0x0004 /* Urgency Threshold Enable */
+#define OIE 0x0010 /* Overflow Interrupt Enable */
+#define BDIE 0x0020 /* Block Done Interrupt Enable */
+#define MBDI 0x0040 /* Mask Block Done IRQ If Pending ECNT */
+#define DRQ 0x0300 /* HDMA Request Type */
+#define DRQ_NONE 0x0000 /* No Request */
+#define DRQ_SINGLE 0x0100 /* Channels Request Single */
+#define DRQ_MULTI 0x0200 /* Channels Request Multi (Default) */
+#define DRQ_URGENT 0x0300 /* Channels Request Multi Urgent */
+#define RBC 0x1000 /* Reload BCNT With IBCNT */
+#define PS 0x2000 /* HDMA Pin Status */
+#define OI 0x4000 /* Overflow Interrupt Generated */
+#define BDI 0x8000 /* Block Done Interrupt Generated */
+
+/* entry addresses of the user-callable Boot ROM functions */
+
+#define _BOOTROM_RESET 0xEF000000
+#define _BOOTROM_FINAL_INIT 0xEF000002
+#define _BOOTROM_DO_MEMORY_DMA 0xEF000006
+#define _BOOTROM_BOOT_DXE_FLASH 0xEF000008
+#define _BOOTROM_BOOT_DXE_SPI 0xEF00000A
+#define _BOOTROM_BOOT_DXE_TWI 0xEF00000C
+#define _BOOTROM_GET_DXE_ADDRESS_FLASH 0xEF000010
+#define _BOOTROM_GET_DXE_ADDRESS_SPI 0xEF000012
+#define _BOOTROM_GET_DXE_ADDRESS_TWI 0xEF000014
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define PGDE_UART PFDE_UART
+#define PGDE_DMA PFDE_DMA
+#define CKELOW SCKELOW
+
+/* HOST Port Registers */
+
+#define HOST_CONTROL 0xffc03400 /* HOST Control Register */
+#define HOST_STATUS 0xffc03404 /* HOST Status Register */
+#define HOST_TIMEOUT 0xffc03408 /* HOST Acknowledge Mode Timeout Register */
+
+/* Counter Registers */
+
+#define CNT_CONFIG 0xffc03500 /* Configuration Register */
+#define CNT_IMASK 0xffc03504 /* Interrupt Mask Register */
+#define CNT_STATUS 0xffc03508 /* Status Register */
+#define CNT_COMMAND 0xffc0350c /* Command Register */
+#define CNT_DEBOUNCE 0xffc03510 /* Debounce Register */
+#define CNT_COUNTER 0xffc03514 /* Counter Register */
+#define CNT_MAX 0xffc03518 /* Maximal Count Register */
+#define CNT_MIN 0xffc0351c /* Minimal Count Register */
+
+/* OTP/FUSE Registers */
+
+#define OTP_CONTROL 0xffc03600 /* OTP/Fuse Control Register */
+#define OTP_BEN 0xffc03604 /* OTP/Fuse Byte Enable */
+#define OTP_STATUS 0xffc03608 /* OTP/Fuse Status */
+#define OTP_TIMING 0xffc0360c /* OTP/Fuse Access Timing */
+
+/* Security Registers */
+
+#define SECURE_SYSSWT 0xffc03620 /* Secure System Switches */
+#define SECURE_CONTROL 0xffc03624 /* Secure Control */
+#define SECURE_STATUS 0xffc03628 /* Secure Status */
+
+/* OTP Read/Write Data Buffer Registers */
+
+#define OTP_DATA0 0xffc03680 /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define OTP_DATA1 0xffc03684 /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define OTP_DATA2 0xffc03688 /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+#define OTP_DATA3 0xffc0368c /* OTP/Fuse Data (OTP_DATA0-3) accesses the fuse read write buffer */
+
+/* Motor Control PWM Registers */
+
+#define PWM_CTRL 0xffc03700 /* PWM Control Register */
+#define PWM_STAT 0xffc03704 /* PWM Status Register */
+#define PWM_TM 0xffc03708 /* PWM Period Register */
+#define PWM_DT 0xffc0370c /* PWM Dead Time Register */
+#define PWM_GATE 0xffc03710 /* PWM Chopping Control */
+#define PWM_CHA 0xffc03714 /* PWM Channel A Duty Control */
+#define PWM_CHB 0xffc03718 /* PWM Channel B Duty Control */
+#define PWM_CHC 0xffc0371c /* PWM Channel C Duty Control */
+#define PWM_SEG 0xffc03720 /* PWM Crossover and Output Enable */
+#define PWM_SYNCWT 0xffc03724 /* PWM Sync Pluse Width Control */
+#define PWM_CHAL 0xffc03728 /* PWM Channel AL Duty Control (SR mode only) */
+#define PWM_CHBL 0xffc0372c /* PWM Channel BL Duty Control (SR mode only) */
+#define PWM_CHCL 0xffc03730 /* PWM Channel CL Duty Control (SR mode only) */
+#define PWM_LSI 0xffc03734 /* PWM Low Side Invert (SR mode only) */
+#define PWM_STAT2 0xffc03738 /* PWM Status Register 2 */
+
+
+/* ********************************************************** */
+/* SINGLE BIT MACRO PAIRS (bit mask and negated one) */
+/* and MULTI BIT READ MACROS */
+/* ********************************************************** */
+
+/* Bit masks for HOST_CONTROL */
+
+#define HOST_CNTR_HOST_EN 0x1 /* Host Enable */
+#define HOST_CNTR_nHOST_EN 0x0
+#define HOST_CNTR_HOST_END 0x2 /* Host Endianess */
+#define HOST_CNTR_nHOST_END 0x0
+#define HOST_CNTR_DATA_SIZE 0x4 /* Data Size */
+#define HOST_CNTR_nDATA_SIZE 0x0
+#define HOST_CNTR_HOST_RST 0x8 /* Host Reset */
+#define HOST_CNTR_nHOST_RST 0x0
+#define HOST_CNTR_HRDY_OVR 0x20 /* Host Ready Override */
+#define HOST_CNTR_nHRDY_OVR 0x0
+#define HOST_CNTR_INT_MODE 0x40 /* Interrupt Mode */
+#define HOST_CNTR_nINT_MODE 0x0
+#define HOST_CNTR_BT_EN 0x80 /* Bus Timeout Enable */
+#define HOST_CNTR_ nBT_EN 0x0
+#define HOST_CNTR_EHW 0x100 /* Enable Host Write */
+#define HOST_CNTR_nEHW 0x0
+#define HOST_CNTR_EHR 0x200 /* Enable Host Read */
+#define HOST_CNTR_nEHR 0x0
+#define HOST_CNTR_BDR 0x400 /* Burst DMA Requests */
+#define HOST_CNTR_nBDR 0x0
+
+/* Bit masks for HOST_STATUS */
+
+#define HOST_STAT_READY 0x1 /* DMA Ready */
+#define HOST_STAT_nREADY 0x0
+#define HOST_STAT_FIFOFULL 0x2 /* FIFO Full */
+#define HOST_STAT_nFIFOFULL 0x0
+#define HOST_STAT_FIFOEMPTY 0x4 /* FIFO Empty */
+#define HOST_STAT_nFIFOEMPTY 0x0
+#define HOST_STAT_COMPLETE 0x8 /* DMA Complete */
+#define HOST_STAT_nCOMPLETE 0x0
+#define HOST_STAT_HSHK 0x10 /* Host Handshake */
+#define HOST_STAT_nHSHK 0x0
+#define HOST_STAT_TIMEOUT 0x20 /* Host Timeout */
+#define HOST_STAT_nTIMEOUT 0x0
+#define HOST_STAT_HIRQ 0x40 /* Host Interrupt Request */
+#define HOST_STAT_nHIRQ 0x0
+#define HOST_STAT_ALLOW_CNFG 0x80 /* Allow New Configuration */
+#define HOST_STAT_nALLOW_CNFG 0x0
+#define HOST_STAT_DMA_DIR 0x100 /* DMA Direction */
+#define HOST_STAT_nDMA_DIR 0x0
+#define HOST_STAT_BTE 0x200 /* Bus Timeout Enabled */
+#define HOST_STAT_nBTE 0x0
+#define HOST_STAT_HOSTRD_DONE 0x8000 /* Host Read Completion Interrupt */
+#define HOST_STAT_nHOSTRD_DONE 0x0
+
+/* Bit masks for HOST_TIMEOUT */
+
+#define HOST_COUNT_TIMEOUT 0x7ff /* Host Timeout count */
+
+/* Bit masks for CNT_CONFIG */
+
+#define CNTE 0x1 /* Counter Enable */
+#define nCNTE 0x0
+#define DEBE 0x2 /* Debounce Enable */
+#define nDEBE 0x0
+#define CDGINV 0x10 /* CDG Pin Polarity Invert */
+#define nCDGINV 0x0
+#define CUDINV 0x20 /* CUD Pin Polarity Invert */
+#define nCUDINV 0x0
+#define CZMINV 0x40 /* CZM Pin Polarity Invert */
+#define nCZMINV 0x0
+#define CNTMODE 0x700 /* Counter Operating Mode */
+#define ZMZC 0x800 /* CZM Zeroes Counter Enable */
+#define nZMZC 0x0
+#define BNDMODE 0x3000 /* Boundary register Mode */
+#define INPDIS 0x8000 /* CUG and CDG Input Disable */
+#define nINPDIS 0x0
+
+/* Bit masks for CNT_IMASK */
+
+#define ICIE 0x1 /* Illegal Gray/Binary Code Interrupt Enable */
+#define nICIE 0x0
+#define UCIE 0x2 /* Up count Interrupt Enable */
+#define nUCIE 0x0
+#define DCIE 0x4 /* Down count Interrupt Enable */
+#define nDCIE 0x0
+#define MINCIE 0x8 /* Min Count Interrupt Enable */
+#define nMINCIE 0x0
+#define MAXCIE 0x10 /* Max Count Interrupt Enable */
+#define nMAXCIE 0x0
+#define COV31IE 0x20 /* Bit 31 Overflow Interrupt Enable */
+#define nCOV31IE 0x0
+#define COV15IE 0x40 /* Bit 15 Overflow Interrupt Enable */
+#define nCOV15IE 0x0
+#define CZEROIE 0x80 /* Count to Zero Interrupt Enable */
+#define nCZEROIE 0x0
+#define CZMIE 0x100 /* CZM Pin Interrupt Enable */
+#define nCZMIE 0x0
+#define CZMEIE 0x200 /* CZM Error Interrupt Enable */
+#define nCZMEIE 0x0
+#define CZMZIE 0x400 /* CZM Zeroes Counter Interrupt Enable */
+#define nCZMZIE 0x0
+
+/* Bit masks for CNT_STATUS */
+
+#define ICII 0x1 /* Illegal Gray/Binary Code Interrupt Identifier */
+#define nICII 0x0
+#define UCII 0x2 /* Up count Interrupt Identifier */
+#define nUCII 0x0
+#define DCII 0x4 /* Down count Interrupt Identifier */
+#define nDCII 0x0
+#define MINCII 0x8 /* Min Count Interrupt Identifier */
+#define nMINCII 0x0
+#define MAXCII 0x10 /* Max Count Interrupt Identifier */
+#define nMAXCII 0x0
+#define COV31II 0x20 /* Bit 31 Overflow Interrupt Identifier */
+#define nCOV31II 0x0
+#define COV15II 0x40 /* Bit 15 Overflow Interrupt Identifier */
+#define nCOV15II 0x0
+#define CZEROII 0x80 /* Count to Zero Interrupt Identifier */
+#define nCZEROII 0x0
+#define CZMII 0x100 /* CZM Pin Interrupt Identifier */
+#define nCZMII 0x0
+#define CZMEII 0x200 /* CZM Error Interrupt Identifier */
+#define nCZMEII 0x0
+#define CZMZII 0x400 /* CZM Zeroes Counter Interrupt Identifier */
+#define nCZMZII 0x0
+
+/* Bit masks for CNT_COMMAND */
+
+#define W1LCNT 0xf /* Load Counter Register */
+#define W1LMIN 0xf0 /* Load Min Register */
+#define W1LMAX 0xf00 /* Load Max Register */
+#define W1ZMONCE 0x1000 /* Enable CZM Clear Counter Once */
+#define nW1ZMONCE 0x0
+
+/* Bit masks for CNT_DEBOUNCE */
+
+#define DPRESCALE 0xf /* Load Counter Register */
+
+/* CNT_COMMAND bit field options */
+
+#define W1LCNT_ZERO 0x0001 /* write 1 to load CNT_COUNTER with zero */
+#define W1LCNT_MIN 0x0004 /* write 1 to load CNT_COUNTER from CNT_MIN */
+#define W1LCNT_MAX 0x0008 /* write 1 to load CNT_COUNTER from CNT_MAX */
+
+#define W1LMIN_ZERO 0x0010 /* write 1 to load CNT_MIN with zero */
+#define W1LMIN_CNT 0x0020 /* write 1 to load CNT_MIN from CNT_COUNTER */
+#define W1LMIN_MAX 0x0080 /* write 1 to load CNT_MIN from CNT_MAX */
+
+#define W1LMAX_ZERO 0x0100 /* write 1 to load CNT_MAX with zero */
+#define W1LMAX_CNT 0x0200 /* write 1 to load CNT_MAX from CNT_COUNTER */
+#define W1LMAX_MIN 0x0400 /* write 1 to load CNT_MAX from CNT_MIN */
+
+/* CNT_CONFIG bit field options */
+
+#define CNTMODE_QUADENC 0x0000 /* quadrature encoder mode */
+#define CNTMODE_BINENC 0x0100 /* binary encoder mode */
+#define CNTMODE_UDCNT 0x0200 /* up/down counter mode */
+#define CNTMODE_DIRCNT 0x0400 /* direction counter mode */
+#define CNTMODE_DIRTMR 0x0500 /* direction timer mode */
+
+#define BNDMODE_COMP 0x0000 /* boundary compare mode */
+#define BNDMODE_ZERO 0x1000 /* boundary compare and zero mode */
+#define BNDMODE_CAPT 0x2000 /* boundary capture mode */
+#define BNDMODE_AEXT 0x3000 /* boundary auto-extend mode */
+
+/* Bit masks for OTP_CONTROL */
+
+#define FUSE_FADDR 0x1ff /* OTP/Fuse Address */
+#define FIEN 0x800 /* OTP/Fuse Interrupt Enable */
+#define nFIEN 0x0
+#define FTESTDEC 0x1000 /* OTP/Fuse Test Decoder */
+#define nFTESTDEC 0x0
+#define FWRTEST 0x2000 /* OTP/Fuse Write Test */
+#define nFWRTEST 0x0
+#define FRDEN 0x4000 /* OTP/Fuse Read Enable */
+#define nFRDEN 0x0
+#define FWREN 0x8000 /* OTP/Fuse Write Enable */
+#define nFWREN 0x0
+
+/* Bit masks for OTP_BEN */
+
+#define FBEN 0xffff /* OTP/Fuse Byte Enable */
+
+/* Bit masks for OTP_STATUS */
+
+#define FCOMP 0x1 /* OTP/Fuse Access Complete */
+#define nFCOMP 0x0
+#define FERROR 0x2 /* OTP/Fuse Access Error */
+#define nFERROR 0x0
+#define MMRGLOAD 0x10 /* Memory Mapped Register Gasket Load */
+#define nMMRGLOAD 0x0
+#define MMRGLOCK 0x20 /* Memory Mapped Register Gasket Lock */
+#define nMMRGLOCK 0x0
+#define FPGMEN 0x40 /* OTP/Fuse Program Enable */
+#define nFPGMEN 0x0
+
+/* Bit masks for OTP_TIMING */
+
+#define USECDIV 0xff /* Micro Second Divider */
+#define READACC 0x7f00 /* Read Access Time */
+#define CPUMPRL 0x38000 /* Charge Pump Release Time */
+#define CPUMPSU 0xc0000 /* Charge Pump Setup Time */
+#define CPUMPHD 0xf00000 /* Charge Pump Hold Time */
+#define PGMTIME 0xff000000 /* Program Time */
+
+/* Bit masks for SECURE_SYSSWT */
+
+#define EMUDABL 0x1 /* Emulation Disable. */
+#define nEMUDABL 0x0
+#define RSTDABL 0x2 /* Reset Disable */
+#define nRSTDABL 0x0
+#define L1IDABL 0x1c /* L1 Instruction Memory Disable. */
+#define L1DADABL 0xe0 /* L1 Data Bank A Memory Disable. */
+#define L1DBDABL 0x700 /* L1 Data Bank B Memory Disable. */
+#define DMA0OVR 0x800 /* DMA0 Memory Access Override */
+#define nDMA0OVR 0x0
+#define DMA1OVR 0x1000 /* DMA1 Memory Access Override */
+#define nDMA1OVR 0x0
+#define EMUOVR 0x4000 /* Emulation Override */
+#define nEMUOVR 0x0
+#define OTPSEN 0x8000 /* OTP Secrets Enable. */
+#define nOTPSEN 0x0
+#define L2DABL 0x70000 /* L2 Memory Disable. */
+
+/* Bit masks for SECURE_CONTROL */
+
+#define SECURE0 0x1 /* SECURE 0 */
+#define nSECURE0 0x0
+#define SECURE1 0x2 /* SECURE 1 */
+#define nSECURE1 0x0
+#define SECURE2 0x4 /* SECURE 2 */
+#define nSECURE2 0x0
+#define SECURE3 0x8 /* SECURE 3 */
+#define nSECURE3 0x0
+
+/* Bit masks for SECURE_STATUS */
+
+#define SECMODE 0x3 /* Secured Mode Control State */
+#define NMI 0x4 /* Non Maskable Interrupt */
+#define nNMI 0x0
+#define AFVALID 0x8 /* Authentication Firmware Valid */
+#define nAFVALID 0x0
+#define AFEXIT 0x10 /* Authentication Firmware Exit */
+#define nAFEXIT 0x0
+#define SECSTAT 0xe0 /* Secure Status */
+
+
+
+#endif /* _DEF_BF51X_H */
diff --git a/arch/blackfin/mach-bf518/include/mach/dma.h b/arch/blackfin/mach-bf518/include/mach/dma.h
new file mode 100644
index 000000000000..bbd33c1706e2
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/dma.h
@@ -0,0 +1,33 @@
+/* mach/dma.h - arch-specific DMA defines
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define MAX_DMA_CHANNELS 16
+
+#define CH_PPI 0 /* PPI receive/transmit */
+#define CH_EMAC_RX 1 /* Ethernet MAC receive */
+#define CH_EMAC_TX 2 /* Ethernet MAC transmit */
+#define CH_SPORT0_RX 3 /* SPORT0 receive */
+#define CH_SPORT0_TX 4 /* SPORT0 transmit */
+#define CH_RSI 4 /* RSI */
+#define CH_SPORT1_RX 5 /* SPORT1 receive */
+#define CH_SPI1 5 /* SPI1 transmit/receive */
+#define CH_SPORT1_TX 6 /* SPORT1 transmit */
+#define CH_SPI0 7 /* SPI0 transmit/receive */
+#define CH_UART0_RX 8 /* UART0 receive */
+#define CH_UART0_TX 9 /* UART0 transmit */
+#define CH_UART1_RX 10 /* UART1 receive */
+#define CH_UART1_TX 11 /* UART1 transmit */
+
+#define CH_MEM_STREAM0_SRC 12 /* RX */
+#define CH_MEM_STREAM0_DEST 13 /* TX */
+#define CH_MEM_STREAM1_SRC 14 /* RX */
+#define CH_MEM_STREAM1_DEST 15 /* TX */
+
+#endif
diff --git a/arch/blackfin/mach-bf518/include/mach/gpio.h b/arch/blackfin/mach-bf518/include/mach/gpio.h
new file mode 100644
index 000000000000..9757683c3948
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/gpio.h
@@ -0,0 +1,60 @@
+/*
+ * File: arch/blackfin/mach-bf518/include/mach/gpio.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+
+#ifndef _MACH_GPIO_H_
+#define _MACH_GPIO_H_
+
+#define MAX_BLACKFIN_GPIOS 40
+
+#define GPIO_PF0 0
+#define GPIO_PF1 1
+#define GPIO_PF2 2
+#define GPIO_PF3 3
+#define GPIO_PF4 4
+#define GPIO_PF5 5
+#define GPIO_PF6 6
+#define GPIO_PF7 7
+#define GPIO_PF8 8
+#define GPIO_PF9 9
+#define GPIO_PF10 10
+#define GPIO_PF11 11
+#define GPIO_PF12 12
+#define GPIO_PF13 13
+#define GPIO_PF14 14
+#define GPIO_PF15 15
+#define GPIO_PG0 16
+#define GPIO_PG1 17
+#define GPIO_PG2 18
+#define GPIO_PG3 19
+#define GPIO_PG4 20
+#define GPIO_PG5 21
+#define GPIO_PG6 22
+#define GPIO_PG7 23
+#define GPIO_PG8 24
+#define GPIO_PG9 25
+#define GPIO_PG10 26
+#define GPIO_PG11 27
+#define GPIO_PG12 28
+#define GPIO_PG13 29
+#define GPIO_PG14 30
+#define GPIO_PG15 31
+#define GPIO_PH0 32
+#define GPIO_PH1 33
+#define GPIO_PH2 34
+#define GPIO_PH3 35
+#define GPIO_PH4 36
+#define GPIO_PH5 37
+#define GPIO_PH6 38
+#define GPIO_PH7 39
+
+#define PORT_F GPIO_PF0
+#define PORT_G GPIO_PG0
+#define PORT_H GPIO_PH0
+
+#endif /* _MACH_GPIO_H_ */
diff --git a/arch/blackfin/mach-bf518/include/mach/irq.h b/arch/blackfin/mach-bf518/include/mach/irq.h
new file mode 100644
index 000000000000..3ff0f093313d
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/irq.h
@@ -0,0 +1,260 @@
+/*
+ * file: include/asm-blackfin/mach-bf518/irq.h
+ * based on: include/asm-blackfin/mach-bf527/irq.h
+ * author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * created:
+ * description:
+ * system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _BF518_IRQ_H_
+#define _BF518_IRQ_H_
+
+/*
+ * Interrupt source definitions
+ Event Source Core Event Name
+ Core Emulation **
+ Events (highest priority) EMU 0
+ Reset RST 1
+ NMI NMI 2
+ Exception EVX 3
+ Reserved -- 4
+ Hardware Error IVHW 5
+ Core Timer IVTMR 6 *
+
+ .....
+
+ Software Interrupt 1 IVG14 31
+ Software Interrupt 2 --
+ (lowest priority) IVG15 32 *
+*/
+
+#define NR_PERI_INTS (2 * 32)
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define IRQ_EMU 0 /* Emulation */
+#define IRQ_RST 1 /* reset */
+#define IRQ_NMI 2 /* Non Maskable */
+#define IRQ_EVX 3 /* Exception */
+#define IRQ_UNUSED 4 /* - unused interrupt */
+#define IRQ_HWERR 5 /* Hardware Error */
+#define IRQ_CORETMR 6 /* Core timer */
+
+#define BFIN_IRQ(x) ((x) + 7)
+
+#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */
+#define IRQ_DMA0_ERROR BFIN_IRQ(1) /* DMA Error 0 (generic) */
+#define IRQ_DMAR0_BLK BFIN_IRQ(2) /* DMAR0 Block Interrupt */
+#define IRQ_DMAR1_BLK BFIN_IRQ(3) /* DMAR1 Block Interrupt */
+#define IRQ_DMAR0_OVR BFIN_IRQ(4) /* DMAR0 Overflow Error */
+#define IRQ_DMAR1_OVR BFIN_IRQ(5) /* DMAR1 Overflow Error */
+#define IRQ_PPI_ERROR BFIN_IRQ(6) /* PPI Error */
+#define IRQ_MAC_ERROR BFIN_IRQ(7) /* MAC Status */
+#define IRQ_SPORT0_ERROR BFIN_IRQ(8) /* SPORT0 Status */
+#define IRQ_SPORT1_ERROR BFIN_IRQ(9) /* SPORT1 Status */
+#define IRQ_PTP_ERROR BFIN_IRQ(10) /* PTP Error Interrupt */
+#define IRQ_UART0_ERROR BFIN_IRQ(12) /* UART0 Status */
+#define IRQ_UART1_ERROR BFIN_IRQ(13) /* UART1 Status */
+#define IRQ_RTC BFIN_IRQ(14) /* RTC */
+#define IRQ_PPI BFIN_IRQ(15) /* DMA Channel 0 (PPI) */
+#define IRQ_SPORT0_RX BFIN_IRQ(16) /* DMA 3 Channel (SPORT0 RX) */
+#define IRQ_SPORT0_TX BFIN_IRQ(17) /* DMA 4 Channel (SPORT0 TX) */
+#define IRQ_RSI BFIN_IRQ(17) /* DMA 4 Channel (RSI) */
+#define IRQ_SPORT1_RX BFIN_IRQ(18) /* DMA 5 Channel (SPORT1 RX/SPI) */
+#define IRQ_SPI1 BFIN_IRQ(18) /* DMA 5 Channel (SPI1) */
+#define IRQ_SPORT1_TX BFIN_IRQ(19) /* DMA 6 Channel (SPORT1 TX) */
+#define IRQ_TWI BFIN_IRQ(20) /* TWI */
+#define IRQ_SPI0 BFIN_IRQ(21) /* DMA 7 Channel (SPI0) */
+#define IRQ_UART0_RX BFIN_IRQ(22) /* DMA8 Channel (UART0 RX) */
+#define IRQ_UART0_TX BFIN_IRQ(23) /* DMA9 Channel (UART0 TX) */
+#define IRQ_UART1_RX BFIN_IRQ(24) /* DMA10 Channel (UART1 RX) */
+#define IRQ_UART1_TX BFIN_IRQ(25) /* DMA11 Channel (UART1 TX) */
+#define IRQ_OPTSEC BFIN_IRQ(26) /* OTPSEC Interrupt */
+#define IRQ_CNT BFIN_IRQ(27) /* GP Counter */
+#define IRQ_MAC_RX BFIN_IRQ(28) /* DMA1 Channel (MAC RX) */
+#define IRQ_PORTH_INTA BFIN_IRQ(29) /* Port H Interrupt A */
+#define IRQ_MAC_TX BFIN_IRQ(30) /* DMA2 Channel (MAC TX) */
+#define IRQ_PORTH_INTB BFIN_IRQ(31) /* Port H Interrupt B */
+#define IRQ_TIMER0 BFIN_IRQ(32) /* Timer 0 */
+#define IRQ_TIMER1 BFIN_IRQ(33) /* Timer 1 */
+#define IRQ_TIMER2 BFIN_IRQ(34) /* Timer 2 */
+#define IRQ_TIMER3 BFIN_IRQ(35) /* Timer 3 */
+#define IRQ_TIMER4 BFIN_IRQ(36) /* Timer 4 */
+#define IRQ_TIMER5 BFIN_IRQ(37) /* Timer 5 */
+#define IRQ_TIMER6 BFIN_IRQ(38) /* Timer 6 */
+#define IRQ_TIMER7 BFIN_IRQ(39) /* Timer 7 */
+#define IRQ_PORTG_INTA BFIN_IRQ(40) /* Port G Interrupt A */
+#define IRQ_PORTG_INTB BFIN_IRQ(41) /* Port G Interrupt B */
+#define IRQ_MEM_DMA0 BFIN_IRQ(42) /* MDMA Stream 0 */
+#define IRQ_MEM_DMA1 BFIN_IRQ(43) /* MDMA Stream 1 */
+#define IRQ_WATCH BFIN_IRQ(44) /* Software Watchdog Timer */
+#define IRQ_PORTF_INTA BFIN_IRQ(45) /* Port F Interrupt A */
+#define IRQ_PORTF_INTB BFIN_IRQ(46) /* Port F Interrupt B */
+#define IRQ_SPI0_ERROR BFIN_IRQ(47) /* SPI0 Status */
+#define IRQ_SPI1_ERROR BFIN_IRQ(48) /* SPI1 Error */
+#define IRQ_RSI_INT0 BFIN_IRQ(51) /* RSI Interrupt0 */
+#define IRQ_RSI_INT1 BFIN_IRQ(52) /* RSI Interrupt1 */
+#define IRQ_PWM_TRIP BFIN_IRQ(53) /* PWM Trip Interrupt */
+#define IRQ_PWM_SYNC BFIN_IRQ(54) /* PWM Sync Interrupt */
+#define IRQ_PTP_STAT BFIN_IRQ(55) /* PTP Stat Interrupt */
+
+#define SYS_IRQS BFIN_IRQ(63) /* 70 */
+
+#define IRQ_PF0 71
+#define IRQ_PF1 72
+#define IRQ_PF2 73
+#define IRQ_PF3 74
+#define IRQ_PF4 75
+#define IRQ_PF5 76
+#define IRQ_PF6 77
+#define IRQ_PF7 78
+#define IRQ_PF8 79
+#define IRQ_PF9 80
+#define IRQ_PF10 81
+#define IRQ_PF11 82
+#define IRQ_PF12 83
+#define IRQ_PF13 84
+#define IRQ_PF14 85
+#define IRQ_PF15 86
+
+#define IRQ_PG0 87
+#define IRQ_PG1 88
+#define IRQ_PG2 89
+#define IRQ_PG3 90
+#define IRQ_PG4 91
+#define IRQ_PG5 92
+#define IRQ_PG6 93
+#define IRQ_PG7 94
+#define IRQ_PG8 95
+#define IRQ_PG9 96
+#define IRQ_PG10 97
+#define IRQ_PG11 98
+#define IRQ_PG12 99
+#define IRQ_PG13 100
+#define IRQ_PG14 101
+#define IRQ_PG15 102
+
+#define IRQ_PH0 103
+#define IRQ_PH1 104
+#define IRQ_PH2 105
+#define IRQ_PH3 106
+#define IRQ_PH4 107
+#define IRQ_PH5 108
+#define IRQ_PH6 109
+#define IRQ_PH7 110
+#define IRQ_PH8 111
+#define IRQ_PH9 112
+#define IRQ_PH10 113
+#define IRQ_PH11 114
+#define IRQ_PH12 115
+#define IRQ_PH13 116
+#define IRQ_PH14 117
+#define IRQ_PH15 118
+
+#define GPIO_IRQ_BASE IRQ_PF0
+
+#define NR_IRQS (IRQ_PH15 + 1)
+
+#define IVG7 7
+#define IVG8 8
+#define IVG9 9
+#define IVG10 10
+#define IVG11 11
+#define IVG12 12
+#define IVG13 13
+#define IVG14 14
+#define IVG15 15
+
+/* IAR0 BIT FIELDS */
+#define IRQ_PLL_WAKEUP_POS 0
+#define IRQ_DMA0_ERROR_POS 4
+#define IRQ_DMAR0_BLK_POS 8
+#define IRQ_DMAR1_BLK_POS 12
+#define IRQ_DMAR0_OVR_POS 16
+#define IRQ_DMAR1_OVR_POS 20
+#define IRQ_PPI_ERROR_POS 24
+#define IRQ_MAC_ERROR_POS 28
+
+/* IAR1 BIT FIELDS */
+#define IRQ_SPORT0_ERROR_POS 0
+#define IRQ_SPORT1_ERROR_POS 4
+#define IRQ_PTP_ERROR_POS 8
+#define IRQ_UART0_ERROR_POS 16
+#define IRQ_UART1_ERROR_POS 20
+#define IRQ_RTC_POS 24
+#define IRQ_PPI_POS 28
+
+/* IAR2 BIT FIELDS */
+#define IRQ_SPORT0_RX_POS 0
+#define IRQ_SPORT0_TX_POS 4
+#define IRQ_RSI_POS 4
+#define IRQ_SPORT1_RX_POS 8
+#define IRQ_SPI1_POS 8
+#define IRQ_SPORT1_TX_POS 12
+#define IRQ_TWI_POS 16
+#define IRQ_SPI0_POS 20
+#define IRQ_UART0_RX_POS 24
+#define IRQ_UART0_TX_POS 28
+
+/* IAR3 BIT FIELDS */
+#define IRQ_UART1_RX_POS 0
+#define IRQ_UART1_TX_POS 4
+#define IRQ_OPTSEC_POS 8
+#define IRQ_CNT_POS 12
+#define IRQ_MAC_RX_POS 16
+#define IRQ_PORTH_INTA_POS 20
+#define IRQ_MAC_TX_POS 24
+#define IRQ_PORTH_INTB_POS 28
+
+/* IAR4 BIT FIELDS */
+#define IRQ_TIMER0_POS 0
+#define IRQ_TIMER1_POS 4
+#define IRQ_TIMER2_POS 8
+#define IRQ_TIMER3_POS 12
+#define IRQ_TIMER4_POS 16
+#define IRQ_TIMER5_POS 20
+#define IRQ_TIMER6_POS 24
+#define IRQ_TIMER7_POS 28
+
+/* IAR5 BIT FIELDS */
+#define IRQ_PORTG_INTA_POS 0
+#define IRQ_PORTG_INTB_POS 4
+#define IRQ_MEM_DMA0_POS 8
+#define IRQ_MEM_DMA1_POS 12
+#define IRQ_WATCH_POS 16
+#define IRQ_PORTF_INTA_POS 20
+#define IRQ_PORTF_INTB_POS 24
+#define IRQ_SPI0_ERROR_POS 28
+
+/* IAR6 BIT FIELDS */
+#define IRQ_SPI1_ERROR_POS 0
+#define IRQ_RSI_INT0_POS 12
+#define IRQ_RSI_INT1_POS 16
+#define IRQ_PWM_TRIP_POS 20
+#define IRQ_PWM_SYNC_POS 24
+#define IRQ_PTP_STAT_POS 28
+
+#endif /* _BF518_IRQ_H_ */
diff --git a/arch/blackfin/mach-bf518/include/mach/mem_map.h b/arch/blackfin/mach-bf518/include/mach/mem_map.h
new file mode 100644
index 000000000000..62bcc781bfaa
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/mem_map.h
@@ -0,0 +1,108 @@
+/*
+ * file: include/asm-blackfin/mach-bf518/mem_map.h
+ * based on: include/asm-blackfin/mach-bf527/mem_map.h
+ * author: Bryan Wu <cooloney@kernel.org>
+ *
+ * created:
+ * description:
+ * Memory MAP Common header file for blackfin BF518/6/4/2 of processors.
+ * rev:
+ *
+ * modified:
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MEM_MAP_518_H_
+#define _MEM_MAP_518_H_
+
+#define COREMMR_BASE 0xFFE00000 /* Core MMRs */
+#define SYSMMR_BASE 0xFFC00000 /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE 0x20300000 /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK2_BASE 0x20200000 /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK1_BASE 0x20100000 /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK0_BASE 0x20000000 /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE 0x00100000 /* 1M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START 0xEF000000
+#define BOOT_ROM_LENGTH 0x8000
+
+/* Level 1 Memory */
+
+/* Memory Map for ADSP-BF518/6/4/2 processors */
+
+#ifdef CONFIG_BFIN_ICACHE
+#define BFIN_ICACHESIZE (16 * 1024)
+#else
+#define BFIN_ICACHESIZE (0)
+#endif
+
+#define L1_CODE_START 0xFFA00000
+#define L1_DATA_A_START 0xFF800000
+#define L1_DATA_B_START 0xFF900000
+
+#define L1_CODE_LENGTH 0xC000
+
+#ifdef CONFIG_BFIN_DCACHE
+
+#ifdef CONFIG_BFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE (16 * 1024)
+#define BFIN_DSUPBANKS 1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH (0x8000 - 0x4000)
+#define BFIN_DCACHESIZE (32 * 1024)
+#define BFIN_DSUPBANKS 2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH 0x8000
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE 0
+#define BFIN_DSUPBANKS 0
+#endif /*CONFIG_BFIN_DCACHE */
+
+/* Level 2 Memory - none */
+
+#define L2_START 0
+#define L2_LENGTH 0
+
+/* Scratch Pad Memory */
+
+#define L1_SCRATCH_START 0xFFB00000
+#define L1_SCRATCH_LENGTH 0x1000
+
+#define GET_PDA_SAFE(preg) \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda;
+
+#define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+
+#endif /* _MEM_MAP_518_H_ */
diff --git a/arch/blackfin/mach-bf518/include/mach/portmux.h b/arch/blackfin/mach-bf518/include/mach/portmux.h
new file mode 100644
index 000000000000..f618b487b2b0
--- /dev/null
+++ b/arch/blackfin/mach-bf518/include/mach/portmux.h
@@ -0,0 +1,190 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define MAX_RESOURCES MAX_BLACKFIN_GPIOS
+
+/* EMAC MII/RMII Port Mux */
+#define P_MII0_ETxD2 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_MII0_ERxD2 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_MII0_ETxD3 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_MII0_ERxD3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_MII0_ERxCLK (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_MII0_ERxDV (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_MII0_COL (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+
+#define P_MII0_MDC (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_MII0_MDIO (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_MII0_ETxD0 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_MII0_ERxD0 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_MII0_ETxD1 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_MII0_ERxD1 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_MII0_ETxEN (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_MII0_PHYINT (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+#define P_MII0_CRS (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_MII0_ERxER (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_MII0_TxCLK (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+
+#define P_MII0 {\
+ P_MII0_ETxD0, \
+ P_MII0_ETxD1, \
+ P_MII0_ETxD2, \
+ P_MII0_ETxD3, \
+ P_MII0_ETxEN, \
+ P_MII0_TxCLK, \
+ P_MII0_PHYINT, \
+ P_MII0_COL, \
+ P_MII0_ERxD0, \
+ P_MII0_ERxD1, \
+ P_MII0_ERxD2, \
+ P_MII0_ERxD3, \
+ P_MII0_ERxDV, \
+ P_MII0_ERxCLK, \
+ P_MII0_ERxER, \
+ P_MII0_CRS, \
+ P_MII0_MDC, \
+ P_MII0_MDIO, 0}
+
+#define P_RMII0 {\
+ P_MII0_ETxD0, \
+ P_MII0_ETxD1, \
+ P_MII0_ETxEN, \
+ P_MII0_ERxD0, \
+ P_MII0_ERxD1, \
+ P_MII0_ERxER, \
+ P_MII0_TxCLK, \
+ P_MII0_PHYINT, \
+ P_MII0_CRS, \
+ P_MII0_MDC, \
+ P_MII0_MDIO, 0}
+
+/* PPI Port Mux */
+#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_PPI0_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_PPI0_CLK (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
+#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
+#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
+
+/* SPI Port Mux */
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(2))
+#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(2))
+#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(2))
+
+#define P_SPI1_SS (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1))
+#define P_SPI1_SCK (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(1))
+#define P_SPI1_MISO (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(1))
+#define P_SPI1_MOSI (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(1))
+
+#define P_SPI1_SSEL1 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(2))
+#define P_SPI1_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(2))
+#define P_SPI1_SSEL3 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(2))
+#define P_SPI1_SSEL4 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(2))
+#define P_SPI1_SSEL5 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(2))
+
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
+
+/* SPORT Port Mux */
+#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_SPORT0_RFS (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_SPORT0_TFS (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+
+#define P_SPORT1_DRPRI (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_SPORT1_RFS (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_SPORT1_TFS (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+
+/* UART Port Mux */
+#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1))
+#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(1))
+
+#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(1))
+
+/* Timer */
+#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(2))
+#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2))
+#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(2))
+#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(2))
+#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(2))
+#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(2))
+#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(2))
+#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(2))
+
+/* DMA */
+#define P_DMAR1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(1))
+#define P_DMAR0 (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(1))
+
+/* TWI */
+#define P_TWI0_SCL (P_DONTCARE)
+#define P_TWI0_SDA (P_DONTCARE)
+
+/* PWM */
+#define P_PWM0_AH (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2))
+#define P_PWM0_AL (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2))
+#define P_PWM0_BH (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2))
+#define P_PWM0_BL (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2))
+#define P_PWM0_CH (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2))
+#define P_PWM0_CL (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2))
+#define P_PWM0_SYNC (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2))
+
+#define P_PWM1_AH (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(2))
+#define P_PWM1_AL (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2))
+#define P_PWM1_BH (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2))
+#define P_PWM1_BL (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2))
+#define P_PWM1_CH (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
+#define P_PWM1_CL (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
+#define P_PWM1_SYNC (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2))
+
+#define P_PWM_TRIPB (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(2))
+
+/* RSI */
+#define P_RSI_DATA0 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
+#define P_RSI_DATA1 (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#define P_RSI_DATA2 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
+#define P_RSI_DATA3 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+#define P_RSI_DATA4 (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(2))
+#define P_RSI_DATA5 (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(2))
+#define P_RSI_DATA6 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(2))
+#define P_RSI_DATA7 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(2))
+#define P_RSI_CMD (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#define P_RSI_CLK (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1))
+
+/* PTP */
+#define P_PTP_PPS (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(2))
+#define P_PTP_CLKOUT (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(2))
+
+#define P_HWAIT (P_DEFINED | P_IDENT(GPIO_PG000000000) | P_FUNCT(1))
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/arch/blackfin/mach-bf518/ints-priority.c b/arch/blackfin/mach-bf518/ints-priority.c
new file mode 100644
index 000000000000..3151fd5501ca
--- /dev/null
+++ b/arch/blackfin/mach-bf518/ints-priority.c
@@ -0,0 +1,99 @@
+/*
+ * File: arch/blackfin/mach-bf518/ints-priority.c
+ * Based on: arch/blackfin/mach-bf527/ints-priority.c
+ * Author: Bryan Wu <cooloney@kernel.org>
+ *
+ * Created:
+ * Description: Set up the interrupt priorities
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <asm/blackfin.h>
+
+void __init program_IAR(void)
+{
+ /* Program the IAR0 Register with the configured priority */
+ bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+ ((CONFIG_IRQ_DMA0_ERROR - 7) << IRQ_DMA0_ERROR_POS) |
+ ((CONFIG_IRQ_DMAR0_BLK - 7) << IRQ_DMAR0_BLK_POS) |
+ ((CONFIG_IRQ_DMAR1_BLK - 7) << IRQ_DMAR1_BLK_POS) |
+ ((CONFIG_IRQ_DMAR0_OVR - 7) << IRQ_DMAR0_OVR_POS) |
+ ((CONFIG_IRQ_DMAR1_OVR - 7) << IRQ_DMAR1_OVR_POS) |
+ ((CONFIG_IRQ_PPI_ERROR - 7) << IRQ_PPI_ERROR_POS) |
+ ((CONFIG_IRQ_MAC_ERROR - 7) << IRQ_MAC_ERROR_POS));
+
+
+ bfin_write_SIC_IAR1(((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) |
+ ((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS) |
+ ((CONFIG_IRQ_PTP_ERROR - 7) << IRQ_PTP_ERROR_POS) |
+ ((CONFIG_IRQ_UART0_ERROR - 7) << IRQ_UART0_ERROR_POS) |
+ ((CONFIG_IRQ_UART1_ERROR - 7) << IRQ_UART1_ERROR_POS) |
+ ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS) |
+ ((CONFIG_IRQ_PPI - 7) << IRQ_PPI_POS));
+
+ bfin_write_SIC_IAR2(((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) |
+ ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) |
+ ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS) |
+ ((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) |
+ ((CONFIG_IRQ_TWI - 7) << IRQ_TWI_POS) |
+ ((CONFIG_IRQ_SPI0 - 7) << IRQ_SPI0_POS) |
+ ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
+ ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS));
+
+ bfin_write_SIC_IAR3(((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) |
+ ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) |
+ ((CONFIG_IRQ_OPTSEC - 7) << IRQ_OPTSEC_POS) |
+ ((CONFIG_IRQ_CNT - 7) << IRQ_CNT_POS) |
+ ((CONFIG_IRQ_MAC_RX - 7) << IRQ_MAC_RX_POS) |
+ ((CONFIG_IRQ_PORTH_INTA - 7) << IRQ_PORTH_INTA_POS) |
+ ((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
+ ((CONFIG_IRQ_PORTH_INTB - 7) << IRQ_PORTH_INTB_POS));
+
+ bfin_write_SIC_IAR4(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+ ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+ ((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+ ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+ ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS) |
+ ((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+ ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+ ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS));
+
+ bfin_write_SIC_IAR5(((CONFIG_IRQ_PORTG_INTA - 7) << IRQ_PORTG_INTA_POS) |
+ ((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
+ ((CONFIG_IRQ_MEM_DMA0 - 7) << IRQ_MEM_DMA0_POS) |
+ ((CONFIG_IRQ_MEM_DMA1 - 7) << IRQ_MEM_DMA1_POS) |
+ ((CONFIG_IRQ_WATCH - 7) << IRQ_WATCH_POS) |
+ ((CONFIG_IRQ_PORTF_INTA - 7) << IRQ_PORTF_INTA_POS) |
+ ((CONFIG_IRQ_PORTF_INTB - 7) << IRQ_PORTF_INTB_POS) |
+ ((CONFIG_IRQ_SPI0_ERROR - 7) << IRQ_SPI0_ERROR_POS));
+
+ bfin_write_SIC_IAR6(((CONFIG_IRQ_SPI1_ERROR - 7) << IRQ_SPI1_ERROR_POS) |
+ ((CONFIG_IRQ_RSI_INT0 - 7) << IRQ_RSI_INT0_POS) |
+ ((CONFIG_IRQ_RSI_INT1 - 7) << IRQ_RSI_INT1_POS) |
+ ((CONFIG_IRQ_PWM_TRIP - 7) << IRQ_PWM_TRIP_POS) |
+ ((CONFIG_IRQ_PWM_SYNC - 7) << IRQ_PWM_SYNC_POS) |
+ ((CONFIG_IRQ_PTP_STAT - 7) << IRQ_PTP_STAT_POS));
+
+ SSYNC();
+}
diff --git a/arch/blackfin/mach-bf527/Kconfig b/arch/blackfin/mach-bf527/Kconfig
index 3cde4beeb214..8438ec6d6679 100644
--- a/arch/blackfin/mach-bf527/Kconfig
+++ b/arch/blackfin/mach-bf527/Kconfig
@@ -168,29 +168,29 @@ config IRQ_MAC_TX
config IRQ_PORTH_INTB
int "IRQ_PORTH_INTB"
default 11
-config IRQ_TMR0
- int "IRQ_TMR0"
- default 12
-config IRQ_TMR1
- int "IRQ_TMR1"
+config IRQ_TIMER0
+ int "IRQ_TIMER0"
+ default 8
+config IRQ_TIMER1
+ int "IRQ_TIMER1"
default 12
-config IRQ_TMR2
- int "IRQ_TMR2"
+config IRQ_TIMER2
+ int "IRQ_TIMER2"
default 12
-config IRQ_TMR3
- int "IRQ_TMR3"
+config IRQ_TIMER3
+ int "IRQ_TIMER3"
default 12
-config IRQ_TMR4
- int "IRQ_TMR4"
+config IRQ_TIMER4
+ int "IRQ_TIMER4"
default 12
-config IRQ_TMR5
- int "IRQ_TMR5"
+config IRQ_TIMER5
+ int "IRQ_TIMER5"
default 12
-config IRQ_TMR6
- int "IRQ_TMR6"
+config IRQ_TIMER6
+ int "IRQ_TIMER6"
default 12
-config IRQ_TMR7
- int "IRQ_TMR7"
+config IRQ_TIMER7
+ int "IRQ_TIMER7"
default 12
config IRQ_PORTG_INTA
int "IRQ_PORTG_INTA"
diff --git a/arch/blackfin/mach-bf527/Makefile b/arch/blackfin/mach-bf527/Makefile
index 4eddb580319c..4a6cdafab8ce 100644
--- a/arch/blackfin/mach-bf527/Makefile
+++ b/arch/blackfin/mach-bf527/Makefile
@@ -2,6 +2,4 @@
# arch/blackfin/mach-bf527/Makefile
#
-extra-y := head.o
-
obj-y := ints-priority.o dma.o
diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c
index 9ea440bbb13d..856c097b5317 100644
--- a/arch/blackfin/mach-bf527/boards/cm_bf527.c
+++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c
@@ -61,51 +61,40 @@ const char bfin_board_name[] = "Bluetechnix CM-BF527";
* Driver needs to know address, irq and flag pin.
*/
-#define ISP1761_BASE 0x203C0000
-#define ISP1761_IRQ IRQ_PF7
-
#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-static struct resource bfin_isp1761_resources[] = {
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
[0] = {
- .name = "isp1761-regs",
- .start = ISP1761_BASE + 0x00000000,
- .end = ISP1761_BASE + 0x000fffff,
+ .start = 0x203C0000,
+ .end = 0x203C0000 + 0x000fffff,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = ISP1761_IRQ,
- .end = ISP1761_IRQ,
+ .start = IRQ_PF7,
+ .end = IRQ_PF7,
.flags = IORESOURCE_IRQ,
},
};
-static struct platform_device bfin_isp1761_device = {
- .name = "isp1761",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_isp1761_resources),
- .resource = bfin_isp1761_resources,
+static struct isp1760_platform_data isp1760_priv = {
+ .is_isp1761 = 0,
+ .port1_disable = 0,
+ .bus_width_16 = 1,
+ .port1_otg = 0,
+ .analog_oc = 0,
+ .dack_polarity_high = 0,
+ .dreq_polarity_high = 0,
};
-static struct platform_device *bfin_isp1761_devices[] = {
- &bfin_isp1761_device,
+static struct platform_device bfin_isp1760_device = {
+ .name = "isp1760-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1760_priv,
+ },
+ .num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+ .resource = bfin_isp1760_resources,
};
-
-int __init bfin_isp1761_init(void)
-{
- unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
-
- printk(KERN_INFO "%s(): registering device resources\n", __func__);
- set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
-
- return platform_add_devices(bfin_isp1761_devices, num_devices);
-}
-
-void __exit bfin_isp1761_exit(void)
-{
- platform_device_unregister(&bfin_isp1761_device);
-}
-
-arch_initcall(bfin_isp1761_init);
#endif
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
@@ -132,8 +121,8 @@ static struct musb_hdrc_config musb_config = {
.dyn_fifo = 0,
.soft_con = 1,
.dma = 1,
- .num_eps = 7,
- .dma_channels = 7,
+ .num_eps = 8,
+ .dma_channels = 8,
.gpio_vrsel = GPIO_PF11,
};
@@ -414,8 +403,13 @@ static struct platform_device isp1362_hcd_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -728,30 +722,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -775,7 +798,6 @@ static struct platform_device i2c_bfin_twi_device = {
};
#endif
-#ifdef CONFIG_I2C_BOARDINFO
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
{
@@ -791,7 +813,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
},
#endif
};
-#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
@@ -885,6 +906,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&isp1362_hcd_device,
#endif
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+ &bfin_isp1760_device,
+#endif
+
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
&musb_device,
#endif
@@ -898,6 +923,7 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -918,7 +944,12 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -941,27 +972,23 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_gpios_device,
};
-static int __init stamp_init(void)
+static int __init cm_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
return 0;
}
-arch_initcall(stamp_init);
+arch_initcall(cm_init);
void native_machine_restart(char *cmd)
{
/* workaround reboot hang when booting from SPI */
if ((bfin_read_SYSCR() & 0x7) == 0x3)
- bfin_gpio_reset_spi0_ssel1();
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
}
void bfin_get_ether_addr(char *addr)
diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c
index 36c87b6fbdec..83606fcdde27 100644
--- a/arch/blackfin/mach-bf527/boards/ezbrd.c
+++ b/arch/blackfin/mach-bf527/boards/ezbrd.c
@@ -51,7 +51,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "BF526-EZBRD";
+const char bfin_board_name[] = "ADI BF526-EZBRD";
/*
* Driver needs to know address, irq and flag pin.
@@ -81,8 +81,8 @@ static struct musb_hdrc_config musb_config = {
.dyn_fifo = 0,
.soft_con = 1,
.dma = 1,
- .num_eps = 7,
- .dma_channels = 7,
+ .num_eps = 8,
+ .dma_channels = 8,
.gpio_vrsel = GPIO_PG13,
};
@@ -208,8 +208,13 @@ static struct platform_device rtc_device = {
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -288,6 +293,30 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879) || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+#include <linux/spi/ad7879.h>
+static const struct ad7879_platform_data bfin_ad7879_ts_info = {
+ .model = 7879, /* Model = AD7879 */
+ .x_plate_ohms = 620, /* 620 Ohm from the touch datasheet */
+ .pressure_max = 10000,
+ .pressure_min = 0,
+ .first_conversion_delay = 3, /* wait 512us before do a first conversion */
+ .acquisition_time = 1, /* 4us acquisition time per sample */
+ .median = 2, /* do 8 measurements */
+ .averaging = 1, /* take the average of 4 middle samples */
+ .pen_down_acc_interval = 255, /* 9.4 ms */
+ .gpio_output = 1, /* configure AUX/VBAT/GPIO as GPIO output */
+ .gpio_default = 1, /* During initialization set GPIO = HIGH */
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
&& defined(CONFIG_SND_SOC_WM8731_SPI)
static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
@@ -386,6 +415,18 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &spi_ad7877_chip_info,
},
#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+ {
+ .modalias = "ad7879",
+ .platform_data = &bfin_ad7879_ts_info,
+ .irq = IRQ_PG0,
+ .max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 5,
+ .controller_data = &spi_ad7879_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
&& defined(CONFIG_SND_SOC_WM8731_SPI)
{
@@ -478,30 +519,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -525,7 +595,6 @@ static struct platform_device i2c_bfin_twi_device = {
};
#endif
-#ifdef CONFIG_I2C_BOARDINFO
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
{
@@ -539,7 +608,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
},
#endif
};
-#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
@@ -655,6 +723,7 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -671,7 +740,12 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -694,27 +768,23 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_gpios_device,
};
-static int __init stamp_init(void)
+static int __init ezbrd_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
return 0;
}
-arch_initcall(stamp_init);
+arch_initcall(ezbrd_init);
void native_machine_restart(char *cmd)
{
/* workaround reboot hang when booting from SPI */
if ((bfin_read_SYSCR() & 0x7) == 0x3)
- bfin_gpio_reset_spi0_ssel1();
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
}
void bfin_get_ether_addr(char *addr)
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 8ee2b744e234..d0864111ef59 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -54,57 +54,46 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "ADDS-BF527-EZKIT";
+const char bfin_board_name[] = "ADI BF527-EZKIT";
/*
* Driver needs to know address, irq and flag pin.
*/
-#define ISP1761_BASE 0x203C0000
-#define ISP1761_IRQ IRQ_PF7
-
#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-static struct resource bfin_isp1761_resources[] = {
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
[0] = {
- .name = "isp1761-regs",
- .start = ISP1761_BASE + 0x00000000,
- .end = ISP1761_BASE + 0x000fffff,
+ .start = 0x203C0000,
+ .end = 0x203C0000 + 0x000fffff,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = ISP1761_IRQ,
- .end = ISP1761_IRQ,
+ .start = IRQ_PF7,
+ .end = IRQ_PF7,
.flags = IORESOURCE_IRQ,
},
};
-static struct platform_device bfin_isp1761_device = {
- .name = "isp1761",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_isp1761_resources),
- .resource = bfin_isp1761_resources,
+static struct isp1760_platform_data isp1760_priv = {
+ .is_isp1761 = 0,
+ .port1_disable = 0,
+ .bus_width_16 = 1,
+ .port1_otg = 0,
+ .analog_oc = 0,
+ .dack_polarity_high = 0,
+ .dreq_polarity_high = 0,
};
-static struct platform_device *bfin_isp1761_devices[] = {
- &bfin_isp1761_device,
+static struct platform_device bfin_isp1760_device = {
+ .name = "isp1760-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1760_priv,
+ },
+ .num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+ .resource = bfin_isp1760_resources,
};
-
-int __init bfin_isp1761_init(void)
-{
- unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
-
- printk(KERN_INFO "%s(): registering device resources\n", __func__);
- set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
-
- return platform_add_devices(bfin_isp1761_devices, num_devices);
-}
-
-void __exit bfin_isp1761_exit(void)
-{
- platform_device_unregister(&bfin_isp1761_device);
-}
-
-arch_initcall(bfin_isp1761_init);
#endif
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
@@ -131,8 +120,8 @@ static struct musb_hdrc_config musb_config = {
.dyn_fifo = 0,
.soft_con = 1,
.dma = 1,
- .num_eps = 7,
- .dma_channels = 7,
+ .num_eps = 8,
+ .dma_channels = 8,
.gpio_vrsel = GPIO_PG13,
};
@@ -436,8 +425,13 @@ static struct platform_device isp1362_hcd_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -515,13 +509,6 @@ static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
};
#endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
- .enable_dma = 1,
- .bits_per_word = 8,
-};
-#endif
-
#if defined(CONFIG_PBX)
static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
.ctl_reg = 0x4, /* send zero */
@@ -552,6 +539,30 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
};
#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879) || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+#include <linux/spi/ad7879.h>
+static const struct ad7879_platform_data bfin_ad7879_ts_info = {
+ .model = 7879, /* Model = AD7879 */
+ .x_plate_ohms = 620, /* 620 Ohm from the touch datasheet */
+ .pressure_max = 10000,
+ .pressure_min = 0,
+ .first_conversion_delay = 3, /* wait 512us before do a first conversion */
+ .acquisition_time = 1, /* 4us acquisition time per sample */
+ .median = 2, /* do 8 measurements */
+ .averaging = 1, /* take the average of 4 middle samples */
+ .pen_down_acc_interval = 255, /* 9.4 ms */
+ .gpio_output = 1, /* configure AUX/VBAT/GPIO as GPIO output */
+ .gpio_default = 1, /* During initialization set GPIO = HIGH */
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
&& defined(CONFIG_SND_SOC_WM8731_SPI)
static struct bfin5xx_spi_chip spi_wm8731_chip_info = {
@@ -613,26 +624,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &ad9960_spi_chip_info,
},
#endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
- {
- .modalias = "spi_mmc_dummy",
- .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0,
- .chip_select = 0,
- .platform_data = NULL,
- .controller_data = &spi_mmc_chip_info,
- .mode = SPI_MODE_3,
- },
- {
- .modalias = "spi_mmc",
- .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0,
- .chip_select = CONFIG_SPI_MMC_CS_CHAN,
- .platform_data = NULL,
- .controller_data = &spi_mmc_chip_info,
- .mode = SPI_MODE_3,
- },
-#endif
#if defined(CONFIG_PBX)
{
.modalias = "fxs-spi",
@@ -662,6 +653,18 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &spi_ad7877_chip_info,
},
#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+ {
+ .modalias = "ad7879",
+ .platform_data = &bfin_ad7879_ts_info,
+ .irq = IRQ_PF8,
+ .max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 3,
+ .controller_data = &spi_ad7879_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
#if defined(CONFIG_SND_SOC_WM8731) || defined(CONFIG_SND_SOC_WM8731_MODULE) \
&& defined(CONFIG_SND_SOC_WM8731_SPI)
{
@@ -756,30 +759,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -803,7 +835,6 @@ static struct platform_device i2c_bfin_twi_device = {
};
#endif
-#ifdef CONFIG_I2C_BOARDINFO
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
{
@@ -817,7 +848,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
},
#endif
};
-#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
@@ -944,6 +974,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&isp1362_hcd_device,
#endif
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+ &bfin_isp1760_device,
+#endif
+
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
&musb_device,
#endif
@@ -957,6 +991,7 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -985,7 +1020,12 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -1012,27 +1052,23 @@ static struct platform_device *stamp_devices[] __initdata = {
&bfin_gpios_device,
};
-static int __init stamp_init(void)
+static int __init ezkit_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
return 0;
}
-arch_initcall(stamp_init);
+arch_initcall(ezkit_init);
void native_machine_restart(char *cmd)
{
/* workaround reboot hang when booting from SPI */
if ((bfin_read_SYSCR() & 0x7) == 0x3)
- bfin_gpio_reset_spi0_ssel1();
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
}
void bfin_get_ether_addr(char *addr)
diff --git a/arch/blackfin/mach-bf527/dma.c b/arch/blackfin/mach-bf527/dma.c
index dfd080cda787..231877578243 100644
--- a/arch/blackfin/mach-bf527/dma.c
+++ b/arch/blackfin/mach-bf527/dma.c
@@ -31,7 +31,7 @@
#include <asm/blackfin.h>
#include <asm/dma.h>
-struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
(struct dma_register *) DMA0_NEXT_DESC_PTR,
(struct dma_register *) DMA1_NEXT_DESC_PTR,
(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff --git a/arch/blackfin/mach-bf527/head.S b/arch/blackfin/mach-bf527/head.S
deleted file mode 100644
index 0eb1da85db73..000000000000
--- a/arch/blackfin/mach-bf527/head.S
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * File: arch/blackfin/mach-bf527/head.S
- * Based on: arch/blackfin/mach-bf533/head.S
- * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
- *
- * Created: 1998
- * Description: Startup code for Blackfin BF537
- *
- * Modified:
- * Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/blackfin.h>
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-#include <asm/clocks.h>
-#include <mach/mem_init.h>
-#endif
-
-.section .l1.text
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-ENTRY(_start_dma_code)
-
- /* Enable PHY CLK buffer output */
- p0.h = hi(VR_CTL);
- p0.l = lo(VR_CTL);
- r0.l = w[p0];
- bitset(r0, 14);
- w[p0] = r0.l;
- ssync;
-
- p0.h = hi(SIC_IWR0);
- p0.l = lo(SIC_IWR0);
- r0.l = 0x1;
- r0.h = 0x0;
- [p0] = r0;
- SSYNC;
-
- /*
- * Set PLL_CTL
- * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
- * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
- * - [7] = output delay (add 200ps of delay to mem signals)
- * - [6] = input delay (add 200ps of input delay to mem signals)
- * - [5] = PDWN : 1=All Clocks off
- * - [3] = STOPCK : 1=Core Clock off
- * - [1] = PLL_OFF : 1=Disable Power to PLL
- * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
- * all other bits set to zero
- */
-
- p0.h = hi(PLL_LOCKCNT);
- p0.l = lo(PLL_LOCKCNT);
- r0 = 0x300(Z);
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITSET (R0, 24);
- [P2] = R0;
- SSYNC;
-
- r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
- r0 = r0 << 9; /* Shift it over, */
- r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
- r0 = r1 | r0;
- r1 = PLL_BYPASS; /* Bypass the PLL? */
- r1 = r1 << 8; /* Shift it over */
- r0 = r1 | r0; /* add them all together */
-#ifdef ANOMALY_05000265
- BITSET(r0, 15); /* Add 250 mV of hysteresis to SPORT input pins */
-#endif
-
- p0.h = hi(PLL_CTL);
- p0.l = lo(PLL_CTL); /* Load the address */
- cli r2; /* Disable interrupts */
- ssync;
- w[p0] = r0.l; /* Set the value */
- idle; /* Wait for the PLL to stablize */
- sti r2; /* Enable interrupts */
-
-.Lcheck_again:
- p0.h = hi(PLL_STAT);
- p0.l = lo(PLL_STAT);
- R0 = W[P0](Z);
- CC = BITTST(R0,5);
- if ! CC jump .Lcheck_again;
-
- /* Configure SCLK & CCLK Dividers */
- r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
- p0.h = hi(PLL_DIV);
- p0.l = lo(PLL_DIV);
- w[p0] = r0.l;
- ssync;
-
- p0.l = lo(EBIU_SDRRC);
- p0.h = hi(EBIU_SDRRC);
- r0 = mem_SDRRC;
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITCLR (R0, 24);
- p0.h = hi(EBIU_SDSTAT);
- p0.l = lo(EBIU_SDSTAT);
- r2.l = w[p0];
- cc = bittst(r2,3);
- if !cc jump .Lskip;
- NOP;
- BITSET (R0, 23);
-.Lskip:
- [P2] = R0;
- SSYNC;
-
- R0.L = lo(mem_SDGCTL);
- R0.H = hi(mem_SDGCTL);
- R1 = [p2];
- R1 = R1 | R0;
- [P2] = R1;
- SSYNC;
-
- RTS;
-ENDPROC(_start_dma_code)
-#endif /* CONFIG_BFIN_KERNEL_CLOCK */
diff --git a/arch/blackfin/mach-bf527/include/mach/anomaly.h b/arch/blackfin/mach-bf527/include/mach/anomaly.h
index 62373e61c585..035e8d835058 100644
--- a/arch/blackfin/mach-bf527/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf527/include/mach/anomaly.h
@@ -28,7 +28,7 @@
/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
#define ANOMALY_05000074 (1)
/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
-#define ANOMALY_05000119 (1)
+#define ANOMALY_05000119 (1) /* note: brokenness is noted in documentation, not anomaly sheet */
/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
#define ANOMALY_05000122 (1)
/* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
@@ -37,8 +37,6 @@
#define ANOMALY_05000265 (1)
/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
#define ANOMALY_05000310 (1)
-/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
-#define ANOMALY_05000312 (ANOMALY_BF527)
/* PPI Is Level-Sensitive on First Transfer In Single Frame Sync Modes */
#define ANOMALY_05000313 (__SILICON_REVISION__ < 2)
/* Incorrect Access of OTP_STATUS During otp_write() Function */
@@ -153,6 +151,10 @@
#define ANOMALY_05000430 (ANOMALY_BF527 && __SILICON_REVISION__ > 1)
/* bfrom_SysControl() Does Not Clear SIC_IWR1 Before Executing PLL Programming Sequence */
#define ANOMALY_05000432 (ANOMALY_BF526)
+/* Certain SIC Registers are not Reset After Soft or Core Double Fault Reset */
+#define ANOMALY_05000435 ((ANOMALY_BF526 && __SILICON_REVISION__ < 1) || ANOMALY_BF527)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000125 (0)
@@ -168,7 +170,9 @@
#define ANOMALY_05000285 (0)
#define ANOMALY_05000307 (0)
#define ANOMALY_05000311 (0)
+#define ANOMALY_05000312 (0)
#define ANOMALY_05000323 (0)
#define ANOMALY_05000363 (0)
+#define ANOMALY_05000412 (0)
#endif
diff --git a/arch/blackfin/mach-bf527/include/mach/bf527.h b/arch/blackfin/mach-bf527/include/mach/bf527.h
index 144f08d3f8ea..3832aab11e9a 100644
--- a/arch/blackfin/mach-bf527/include/mach/bf527.h
+++ b/arch/blackfin/mach-bf527/include/mach/bf527.h
@@ -110,7 +110,7 @@
#ifdef CONFIG_BF527
#define CPU "BF527"
-#define CPUID 0x27e4
+#define CPUID 0x27e0
#endif
#ifdef CONFIG_BF526
#define CPU "BF526"
@@ -118,7 +118,7 @@
#endif
#ifdef CONFIG_BF525
#define CPU "BF525"
-#define CPUID 0x27e4
+#define CPUID 0x27e0
#endif
#ifdef CONFIG_BF524
#define CPU "BF524"
@@ -126,7 +126,7 @@
#endif
#ifdef CONFIG_BF523
#define CPU "BF523"
-#define CPUID 0x27e4
+#define CPUID 0x27e0
#endif
#ifdef CONFIG_BF522
#define CPU "BF522"
@@ -134,7 +134,7 @@
#endif
#ifndef CPU
-#error Unknown CPU type - This kernel doesn't seem to be configured properly
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
#endif
#endif /* __MACH_BF527_H__ */
diff --git a/arch/blackfin/mach-bf527/include/mach/bfin_sir.h b/arch/blackfin/mach-bf527/include/mach/bfin_sir.h
deleted file mode 100644
index cfd8ad4f1f2c..000000000000
--- a/arch/blackfin/mach-bf527/include/mach/bfin_sir.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Blackfin Infra-red Driver
- *
- * Copyright 2006-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- *
- */
-
-#include <linux/serial.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-
-#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
-#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
-#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
-#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
-#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
-#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
-#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
-
-#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
-#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
-#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
-#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
-#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
-#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
-
-#ifdef CONFIG_SIR_BFIN_DMA
-struct dma_rx_buf {
- char *buf;
- int head;
- int tail;
- };
-#endif /* CONFIG_SIR_BFIN_DMA */
-
-struct bfin_sir_port {
- unsigned char __iomem *membase;
- unsigned int irq;
- unsigned int lsr;
- unsigned long clk;
- struct net_device *dev;
-#ifdef CONFIG_SIR_BFIN_DMA
- int tx_done;
- struct dma_rx_buf rx_dma_buf;
- struct timer_list rx_dma_timer;
- int rx_dma_nrows;
-#endif /* CONFIG_SIR_BFIN_DMA */
- unsigned int tx_dma_channel;
- unsigned int rx_dma_channel;
-};
-
-struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
-
-struct bfin_sir_port_res {
- unsigned long base_addr;
- int irq;
- unsigned int rx_dma_channel;
- unsigned int tx_dma_channel;
-};
-
-struct bfin_sir_port_res bfin_sir_port_resource[] = {
-#ifdef CONFIG_BFIN_SIR0
- {
- 0xFFC00400,
- IRQ_UART0_RX,
- CH_UART0_RX,
- CH_UART0_TX,
- },
-#endif
-#ifdef CONFIG_BFIN_SIR1
- {
- 0xFFC02000,
- IRQ_UART1_RX,
- CH_UART1_RX,
- CH_UART1_TX,
- },
-#endif
-};
-
-int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
-
-struct bfin_sir_self {
- struct bfin_sir_port *sir_port;
- spinlock_t lock;
- unsigned int open;
- int speed;
- int newspeed;
-
- struct sk_buff *txskb;
- struct sk_buff *rxskb;
- struct net_device_stats stats;
- struct device *dev;
- struct irlap_cb *irlap;
- struct qos_info qos;
-
- iobuff_t tx_buff;
- iobuff_t rx_buff;
-
- struct work_struct work;
- int mtt;
-};
-
-static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
-{
- unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
- port->lsr |= (lsr & (BI|FE|PE|OE));
- return lsr | port->lsr;
-}
-
-static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
-{
- port->lsr = 0;
- bfin_read16(port->membase + OFFSET_LSR);
-}
-
-#define DRIVER_NAME "bfin_sir"
-
-static int bfin_sir_hw_init(void)
-{
- int ret = -ENODEV;
-#ifdef CONFIG_BFIN_SIR0
- ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
-
-#ifdef CONFIG_BFIN_SIR1
- ret = peripheral_request(P_UART1_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART1_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
- return ret;
-}
diff --git a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
index 9a814b9a12b9..1fe76d8e0403 100644
--- a/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
+++ b/arch/blackfin/mach-bf527/include/mach/cdefBF52x_base.h
@@ -31,7 +31,6 @@
#ifndef _CDEF_BF52X_H
#define _CDEF_BF52X_H
-#include <asm/system.h>
#include <asm/blackfin.h>
#include "defBF52x_base.h"
@@ -43,57 +42,9 @@
/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
@@ -1201,4 +1152,57 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
#define bfin_read_NFC_DATA_RD() bfin_read16(NFC_DATA_RD)
#define bfin_write_NFC_DATA_RD(val) bfin_write16(NFC_DATA_RD, val)
+/* These need to be last due to the cdef/linux inter-dependencies */
+#include <asm/irq.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
#endif /* _CDEF_BF52X_H */
diff --git a/arch/blackfin/mach-bf527/include/mach/dma.h b/arch/blackfin/mach-bf527/include/mach/dma.h
index 49dd693223e8..eb287da101a2 100644
--- a/arch/blackfin/mach-bf527/include/mach/dma.h
+++ b/arch/blackfin/mach-bf527/include/mach/dma.h
@@ -1,38 +1,14 @@
-/*
- * file: include/asm-blackfin/mach-bf527/dma.h
- * based on: include/asm-blackfin/mach-bf537/dma.h
- * author: Michael Hennerich (michael.hennerich@analog.com)
+/* mach/dma.h - arch-specific DMA defines
*
- * created:
- * description:
- * system DMA map
- * rev:
+ * Copyright 2004-2008 Analog Devices Inc.
*
- * modified:
- *
- *
- * bugs: enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, 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; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
*/
#ifndef _MACH_DMA_H_
#define _MACH_DMA_H_
-#define MAX_BLACKFIN_DMA_CHANNEL 16
+#define MAX_DMA_CHANNELS 16
#define CH_PPI 0 /* PPI receive/transmit or NFC */
#define CH_EMAC_RX 1 /* Ethernet MAC receive or HOSTDP */
diff --git a/arch/blackfin/mach-bf527/include/mach/gpio.h b/arch/blackfin/mach-bf527/include/mach/gpio.h
new file mode 100644
index 000000000000..06b6eebf0d49
--- /dev/null
+++ b/arch/blackfin/mach-bf527/include/mach/gpio.h
@@ -0,0 +1,68 @@
+/*
+ * File: arch/blackfin/mach-bf527/include/mach/gpio.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+
+#ifndef _MACH_GPIO_H_
+#define _MACH_GPIO_H_
+
+#define MAX_BLACKFIN_GPIOS 48
+
+#define GPIO_PF0 0
+#define GPIO_PF1 1
+#define GPIO_PF2 2
+#define GPIO_PF3 3
+#define GPIO_PF4 4
+#define GPIO_PF5 5
+#define GPIO_PF6 6
+#define GPIO_PF7 7
+#define GPIO_PF8 8
+#define GPIO_PF9 9
+#define GPIO_PF10 10
+#define GPIO_PF11 11
+#define GPIO_PF12 12
+#define GPIO_PF13 13
+#define GPIO_PF14 14
+#define GPIO_PF15 15
+#define GPIO_PG0 16
+#define GPIO_PG1 17
+#define GPIO_PG2 18
+#define GPIO_PG3 19
+#define GPIO_PG4 20
+#define GPIO_PG5 21
+#define GPIO_PG6 22
+#define GPIO_PG7 23
+#define GPIO_PG8 24
+#define GPIO_PG9 25
+#define GPIO_PG10 26
+#define GPIO_PG11 27
+#define GPIO_PG12 28
+#define GPIO_PG13 29
+#define GPIO_PG14 30
+#define GPIO_PG15 31
+#define GPIO_PH0 32
+#define GPIO_PH1 33
+#define GPIO_PH2 34
+#define GPIO_PH3 35
+#define GPIO_PH4 36
+#define GPIO_PH5 37
+#define GPIO_PH6 38
+#define GPIO_PH7 39
+#define GPIO_PH8 40
+#define GPIO_PH9 41
+#define GPIO_PH10 42
+#define GPIO_PH11 43
+#define GPIO_PH12 44
+#define GPIO_PH13 45
+#define GPIO_PH14 46
+#define GPIO_PH15 47
+
+#define PORT_F GPIO_PF0
+#define PORT_G GPIO_PG0
+#define PORT_H GPIO_PH0
+
+#endif /* _MACH_GPIO_H_ */
diff --git a/arch/blackfin/mach-bf527/include/mach/irq.h b/arch/blackfin/mach-bf527/include/mach/irq.h
index 4e2b3f2020e5..8ea660d8151f 100644
--- a/arch/blackfin/mach-bf527/include/mach/irq.h
+++ b/arch/blackfin/mach-bf527/include/mach/irq.h
@@ -96,14 +96,14 @@
#define IRQ_MAC_TX BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */
#define IRQ_NFC BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */
#define IRQ_PORTH_INTB BFIN_IRQ(31) /* Port H Interrupt B */
-#define IRQ_TMR0 BFIN_IRQ(32) /* Timer 0 */
-#define IRQ_TMR1 BFIN_IRQ(33) /* Timer 1 */
-#define IRQ_TMR2 BFIN_IRQ(34) /* Timer 2 */
-#define IRQ_TMR3 BFIN_IRQ(35) /* Timer 3 */
-#define IRQ_TMR4 BFIN_IRQ(36) /* Timer 4 */
-#define IRQ_TMR5 BFIN_IRQ(37) /* Timer 5 */
-#define IRQ_TMR6 BFIN_IRQ(38) /* Timer 6 */
-#define IRQ_TMR7 BFIN_IRQ(39) /* Timer 7 */
+#define IRQ_TIMER0 BFIN_IRQ(32) /* Timer 0 */
+#define IRQ_TIMER1 BFIN_IRQ(33) /* Timer 1 */
+#define IRQ_TIMER2 BFIN_IRQ(34) /* Timer 2 */
+#define IRQ_TIMER3 BFIN_IRQ(35) /* Timer 3 */
+#define IRQ_TIMER4 BFIN_IRQ(36) /* Timer 4 */
+#define IRQ_TIMER5 BFIN_IRQ(37) /* Timer 5 */
+#define IRQ_TIMER6 BFIN_IRQ(38) /* Timer 6 */
+#define IRQ_TIMER7 BFIN_IRQ(39) /* Timer 7 */
#define IRQ_PORTG_INTA BFIN_IRQ(40) /* Port G Interrupt A */
#define IRQ_PORTG_INTB BFIN_IRQ(41) /* Port G Interrupt B */
#define IRQ_MEM_DMA0 BFIN_IRQ(42) /* MDMA Stream 0 */
@@ -227,14 +227,14 @@
#define IRQ_PORTH_INTB_POS 28
/* IAR4 BIT FIELDS */
-#define IRQ_TMR0_POS 0
-#define IRQ_TMR1_POS 4
-#define IRQ_TMR2_POS 8
-#define IRQ_TMR3_POS 12
-#define IRQ_TMR4_POS 16
-#define IRQ_TMR5_POS 20
-#define IRQ_TMR6_POS 24
-#define IRQ_TMR7_POS 28
+#define IRQ_TIMER0_POS 0
+#define IRQ_TIMER1_POS 4
+#define IRQ_TIMER2_POS 8
+#define IRQ_TIMER3_POS 12
+#define IRQ_TIMER4_POS 16
+#define IRQ_TIMER5_POS 20
+#define IRQ_TIMER6_POS 24
+#define IRQ_TIMER7_POS 28
/* IAR5 BIT FIELDS */
#define IRQ_PORTG_INTA_POS 0
diff --git a/arch/blackfin/mach-bf527/include/mach/mem_map.h b/arch/blackfin/mach-bf527/include/mach/mem_map.h
index ef46dc991cd4..019e0017ad81 100644
--- a/arch/blackfin/mach-bf527/include/mach/mem_map.h
+++ b/arch/blackfin/mach-bf527/include/mach/mem_map.h
@@ -99,4 +99,10 @@
#define L1_SCRATCH_START 0xFFB00000
#define L1_SCRATCH_LENGTH 0x1000
+#define GET_PDA_SAFE(preg) \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda;
+
+#define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+
#endif /* _MEM_MAP_527_H_ */
diff --git a/arch/blackfin/mach-bf527/include/mach/portmux.h b/arch/blackfin/mach-bf527/include/mach/portmux.h
index 7f6da2c386bb..72b1652be4da 100644
--- a/arch/blackfin/mach-bf527/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf527/include/mach/portmux.h
@@ -73,6 +73,8 @@
#define P_HWAIT (P_DONTCARE)
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1
+
#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2))
#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2))
diff --git a/arch/blackfin/mach-bf527/ints-priority.c b/arch/blackfin/mach-bf527/ints-priority.c
index 8a2367403d2b..f8c8acd73e30 100644
--- a/arch/blackfin/mach-bf527/ints-priority.c
+++ b/arch/blackfin/mach-bf527/ints-priority.c
@@ -69,14 +69,14 @@ void __init program_IAR(void)
((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
((CONFIG_IRQ_PORTH_INTB - 7) << IRQ_PORTH_INTB_POS));
- bfin_write_SIC_IAR4(((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
- ((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
- ((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
- ((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) |
- ((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS) |
- ((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) |
- ((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) |
- ((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS));
+ bfin_write_SIC_IAR4(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+ ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+ ((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+ ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+ ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS) |
+ ((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+ ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+ ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS));
bfin_write_SIC_IAR5(((CONFIG_IRQ_PORTG_INTA - 7) << IRQ_PORTG_INTA_POS) |
((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
diff --git a/arch/blackfin/mach-bf533/Kconfig b/arch/blackfin/mach-bf533/Kconfig
index 76beb75f12da..14427de7d77f 100644
--- a/arch/blackfin/mach-bf533/Kconfig
+++ b/arch/blackfin/mach-bf533/Kconfig
@@ -59,7 +59,7 @@ config DMA7_UARTTX
default 10
config TIMER0
int "TIMER0"
- default 11
+ default 8
config TIMER1
int "TIMER1"
default 11
diff --git a/arch/blackfin/mach-bf533/Makefile b/arch/blackfin/mach-bf533/Makefile
index aa9f2647ee0c..874840f76028 100644
--- a/arch/blackfin/mach-bf533/Makefile
+++ b/arch/blackfin/mach-bf533/Makefile
@@ -2,6 +2,4 @@
# arch/blackfin/mach-bf533/Makefile
#
-extra-y := head.o
-
obj-y := ints-priority.o dma.o
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index 72ac3ac8ef76..0c66bf44cfab 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -313,23 +313,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
@@ -431,7 +441,9 @@ static struct platform_device *h8606_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_KEYBOARD_OPENCORES) || defined(CONFIG_KEYBOARD_OPENCORES_MODULE)
diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c
index d064ded87719..015c18f85e7f 100644
--- a/arch/blackfin/mach-bf533/boards/blackstamp.c
+++ b/arch/blackfin/mach-bf533/boards/blackstamp.c
@@ -212,23 +212,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
@@ -299,10 +309,8 @@ static struct platform_device i2c_gpio_device = {
};
#endif
-#ifdef CONFIG_I2C_BOARDINFO
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
};
-#endif
static const unsigned int cclk_vlev_datasheet[] =
{
@@ -353,7 +361,9 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -378,10 +388,8 @@ static int __init blackstamp_init(void)
printk(KERN_INFO "%s(): registering device resources\n", __func__);
-#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info));
-#endif
ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
if (ret < 0)
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 575843f6d9ef..e7061c7e8c42 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -219,6 +219,19 @@ static struct platform_device smc91x_device = {
};
#endif
+static struct resource bfin_gpios_resources = {
+ .start = 0,
+ .end = MAX_BLACKFIN_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+ .name = "simple-gpio",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &bfin_gpios_resources,
+};
+
#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
static struct resource bfin_uart_resources[] = {
{
@@ -237,23 +250,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
@@ -342,7 +365,9 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -365,6 +390,8 @@ static struct platform_device *cm_bf533_devices[] __initdata = {
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
&bfin_spi0_device,
#endif
+
+ &bfin_gpios_device,
};
static int __init cm_bf533_init(void)
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index cc2e7eeb1d5a..08cd0969de47 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -46,7 +46,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "ADDS-BF533-EZKIT";
+const char bfin_board_name[] = "ADI BF533-EZKIT";
#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
static struct platform_device rtc_device = {
@@ -236,23 +236,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
#include <linux/input.h>
@@ -363,7 +373,9 @@ static struct platform_device *ezkit_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
index 82b1f6a60e3f..986eeec53b1f 100644
--- a/arch/blackfin/mach-bf533/boards/generic_board.c
+++ b/arch/blackfin/mach-bf533/boards/generic_board.c
@@ -72,6 +72,35 @@ static struct platform_device smc91x_device = {
};
#endif
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#endif
+
static struct platform_device *generic_board_devices[] __initdata = {
#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
&rtc_device,
@@ -80,6 +109,12 @@ static struct platform_device *generic_board_devices[] __initdata = {
#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
&smc91x_device,
#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#endif
};
static int __init generic_board_init(void)
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index 5864892de314..e30b1b7d1442 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -197,23 +197,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
static struct resource isp1362_hcd_resources[] = {
@@ -272,7 +282,9 @@ static struct platform_device *ip0x_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 050ffca53530..db96f33f72e2 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -49,7 +49,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "ADDS-BF533-STAMP";
+const char bfin_board_name[] = "ADI BF533-STAMP";
#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
static struct platform_device rtc_device = {
@@ -118,7 +118,7 @@ static struct mtd_partition stamp_partitions[] = {
.offset = 0,
}, {
.name = "linux kernel(nor)",
- .size = 0xE0000,
+ .size = 0x180000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "file system(nor)",
@@ -169,7 +169,7 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.mask_flags = MTD_CAP_ROM
}, {
.name = "linux kernel(spi)",
- .size = 0xe0000,
+ .size = 0x180000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "file system(spi)",
@@ -216,13 +216,6 @@ static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
};
#endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
- .enable_dma = 1,
- .bits_per_word = 8,
-};
-#endif
-
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
static struct bfin5xx_spi_chip spidev_chip_info = {
.enable_dma = 0,
@@ -265,27 +258,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
},
#endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
- {
- .modalias = "spi_mmc_dummy",
- .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0,
- .chip_select = 0,
- .platform_data = NULL,
- .controller_data = &spi_mmc_chip_info,
- .mode = SPI_MODE_3,
- },
- {
- .modalias = "spi_mmc",
- .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0,
- .chip_select = CONFIG_SPI_MMC_CS_CHAN,
- .platform_data = NULL,
- .controller_data = &spi_mmc_chip_info,
- .mode = SPI_MODE_3,
- },
-#endif
-
#if defined(CONFIG_PBX)
{
.modalias = "fxs-spi",
@@ -373,23 +345,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
@@ -459,7 +441,6 @@ static struct platform_device i2c_gpio_device = {
};
#endif
-#ifdef CONFIG_I2C_BOARDINFO
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
{
@@ -479,7 +460,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
},
#endif
};
-#endif
static const unsigned int cclk_vlev_datasheet[] =
{
@@ -537,7 +517,9 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
@@ -566,10 +548,8 @@ static int __init stamp_init(void)
printk(KERN_INFO "%s(): registering device resources\n", __func__);
-#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info));
-#endif
ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
if (ret < 0)
diff --git a/arch/blackfin/mach-bf533/dma.c b/arch/blackfin/mach-bf533/dma.c
index 28655c1cb7dc..0a6eb8f24d98 100644
--- a/arch/blackfin/mach-bf533/dma.c
+++ b/arch/blackfin/mach-bf533/dma.c
@@ -31,7 +31,7 @@
#include <asm/blackfin.h>
#include <asm/dma.h>
-struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
(struct dma_register *) DMA0_NEXT_DESC_PTR,
(struct dma_register *) DMA1_NEXT_DESC_PTR,
(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff --git a/arch/blackfin/mach-bf533/head.S b/arch/blackfin/mach-bf533/head.S
deleted file mode 100644
index 9fc95aaca439..000000000000
--- a/arch/blackfin/mach-bf533/head.S
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * File: arch/blackfin/mach-bf533/head.S
- * Based on:
- * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
- *
- * Created: 1998
- * Description: bf533 startup file
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/blackfin.h>
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-#include <asm/clocks.h>
-#include <mach/mem_init.h>
-#endif
-
-.section .l1.text
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-ENTRY(_start_dma_code)
- p0.h = hi(SIC_IWR);
- p0.l = lo(SIC_IWR);
- r0.l = 0x1;
- r0.h = 0x0;
- [p0] = r0;
- SSYNC;
-
- /*
- * Set PLL_CTL
- * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
- * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
- * - [7] = output delay (add 200ps of delay to mem signals)
- * - [6] = input delay (add 200ps of input delay to mem signals)
- * - [5] = PDWN : 1=All Clocks off
- * - [3] = STOPCK : 1=Core Clock off
- * - [1] = PLL_OFF : 1=Disable Power to PLL
- * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
- * all other bits set to zero
- */
-
- p0.h = hi(PLL_LOCKCNT);
- p0.l = lo(PLL_LOCKCNT);
- r0 = 0x300(Z);
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITSET (R0, 24);
- [P2] = R0;
- SSYNC;
-
- r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
- r0 = r0 << 9; /* Shift it over, */
- r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
- r0 = r1 | r0;
- r1 = PLL_BYPASS; /* Bypass the PLL? */
- r1 = r1 << 8; /* Shift it over */
- r0 = r1 | r0; /* add them all together */
-#ifdef ANOMALY_05000265
- BITSET(r0, 15); /* Add 250 mV of hysteresis to SPORT input pins */
-#endif
-
- p0.h = hi(PLL_CTL);
- p0.l = lo(PLL_CTL); /* Load the address */
- cli r2; /* Disable interrupts */
- ssync;
- w[p0] = r0.l; /* Set the value */
- idle; /* Wait for the PLL to stablize */
- sti r2; /* Enable interrupts */
-
-.Lcheck_again:
- p0.h = hi(PLL_STAT);
- p0.l = lo(PLL_STAT);
- R0 = W[P0](Z);
- CC = BITTST(R0,5);
- if ! CC jump .Lcheck_again;
-
- /* Configure SCLK & CCLK Dividers */
- r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
- p0.h = hi(PLL_DIV);
- p0.l = lo(PLL_DIV);
- w[p0] = r0.l;
- ssync;
-
- p0.l = lo(EBIU_SDRRC);
- p0.h = hi(EBIU_SDRRC);
- r0 = mem_SDRRC;
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITCLR (R0, 24);
- p0.h = hi(EBIU_SDSTAT);
- p0.l = lo(EBIU_SDSTAT);
- r2.l = w[p0];
- cc = bittst(r2,3);
- if !cc jump .Lskip;
- NOP;
- BITSET (R0, 23);
-.Lskip:
- [P2] = R0;
- SSYNC;
-
- R0.L = lo(mem_SDGCTL);
- R0.H = hi(mem_SDGCTL);
- R1 = [p2];
- R1 = R1 | R0;
- [P2] = R1;
- SSYNC;
-
- RTS;
-ENDPROC(_start_dma_code)
-#endif /* CONFIG_BFIN_KERNEL_CLOCK */
diff --git a/arch/blackfin/mach-bf533/include/mach/anomaly.h b/arch/blackfin/mach-bf533/include/mach/anomaly.h
index f544fc56959a..0d3a03429fb9 100644
--- a/arch/blackfin/mach-bf533/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf533/include/mach/anomaly.h
@@ -7,7 +7,7 @@
*/
/* This file shoule be up to date with:
- * - Revision D, 06/18/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
+ * - Revision E, 09/18/2008; ADSP-BF531/BF532/BF533 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -194,6 +194,12 @@
#define ANOMALY_05000403 (1)
/* Speculative Fetches Can Cause Undesired External FIFO Operations */
#define ANOMALY_05000416 (1)
+/* Multichannel SPORT Channel Misalignment Under Specific Configuration */
+#define ANOMALY_05000425 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
/* These anomalies have been "phased" out of analog.com anomaly sheets and are
* here to show running on older silicon just isn't feasible.
@@ -273,5 +279,8 @@
#define ANOMALY_05000323 (0)
#define ANOMALY_05000353 (1)
#define ANOMALY_05000386 (1)
+#define ANOMALY_05000412 (0)
+#define ANOMALY_05000432 (0)
+#define ANOMALY_05000435 (0)
#endif
diff --git a/arch/blackfin/mach-bf533/include/mach/bf533.h b/arch/blackfin/mach-bf533/include/mach/bf533.h
index dfc8c1ad2d7a..cf4427cd3f72 100644
--- a/arch/blackfin/mach-bf533/include/mach/bf533.h
+++ b/arch/blackfin/mach-bf533/include/mach/bf533.h
@@ -145,7 +145,7 @@
#endif
#ifdef CONFIG_BF532
#define CPU "BF532"
-#define CPUID 0x275A
+#define CPUID 0x27a5
#endif
#ifdef CONFIG_BF531
#define CPU "BF531"
@@ -153,7 +153,7 @@
#endif
#ifndef CPU
-#error Unknown CPU type - This kernel doesn't seem to be configured properly
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
#endif
#endif /* __MACH_BF533_H__ */
diff --git a/arch/blackfin/mach-bf533/include/mach/bfin_sir.h b/arch/blackfin/mach-bf533/include/mach/bfin_sir.h
deleted file mode 100644
index 9bb87e9e2e9b..000000000000
--- a/arch/blackfin/mach-bf533/include/mach/bfin_sir.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Blackfin Infra-red Driver
- *
- * Copyright 2006-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- *
- */
-
-#include <linux/serial.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-
-#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
-#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
-#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
-#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
-#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
-#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
-#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
-
-#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
-#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
-#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
-#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
-#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
-#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
-
-#ifdef CONFIG_SIR_BFIN_DMA
-struct dma_rx_buf {
- char *buf;
- int head;
- int tail;
- };
-#endif /* CONFIG_SIR_BFIN_DMA */
-
-struct bfin_sir_port {
- unsigned char __iomem *membase;
- unsigned int irq;
- unsigned int lsr;
- unsigned long clk;
- struct net_device *dev;
-#ifdef CONFIG_SIR_BFIN_DMA
- int tx_done;
- struct dma_rx_buf rx_dma_buf;
- struct timer_list rx_dma_timer;
- int rx_dma_nrows;
-#endif /* CONFIG_SIR_BFIN_DMA */
- unsigned int tx_dma_channel;
- unsigned int rx_dma_channel;
-};
-
-struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
-
-struct bfin_sir_port_res {
- unsigned long base_addr;
- int irq;
- unsigned int rx_dma_channel;
- unsigned int tx_dma_channel;
-};
-
-struct bfin_sir_port_res bfin_sir_port_resource[] = {
-#ifdef CONFIG_BFIN_SIR0
- {
- 0xFFC00400,
- IRQ_UART_RX,
- CH_UART_RX,
- CH_UART_TX,
- },
-#endif
-};
-
-int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
-
-struct bfin_sir_self {
- struct bfin_sir_port *sir_port;
- spinlock_t lock;
- unsigned int open;
- int speed;
- int newspeed;
-
- struct sk_buff *txskb;
- struct sk_buff *rxskb;
- struct net_device_stats stats;
- struct device *dev;
- struct irlap_cb *irlap;
- struct qos_info qos;
-
- iobuff_t tx_buff;
- iobuff_t rx_buff;
-
- struct work_struct work;
- int mtt;
-};
-
-static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
-{
- unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
- port->lsr |= (lsr & (BI|FE|PE|OE));
- return lsr | port->lsr;
-}
-
-static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
-{
- port->lsr = 0;
- bfin_read16(port->membase + OFFSET_LSR);
-}
-
-#define DRIVER_NAME "bfin_sir"
-
-static int bfin_sir_hw_init(void)
-{
- int ret = -ENODEV;
-#ifdef CONFIG_BFIN_SIR0
- ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
- return ret;
-}
diff --git a/arch/blackfin/mach-bf533/include/mach/blackfin.h b/arch/blackfin/mach-bf533/include/mach/blackfin.h
index d80971b4e3aa..045184f81a29 100644
--- a/arch/blackfin/mach-bf533/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf533/include/mach/blackfin.h
@@ -44,6 +44,13 @@
#define BFIN_UART_NR_PORTS 1
+#define CH_UART_RX CH_UART0_RX
+#define CH_UART_TX CH_UART0_TX
+
+#define IRQ_UART_ERROR IRQ_UART0_ERROR
+#define IRQ_UART_RX IRQ_UART0_RX
+#define IRQ_UART_TX IRQ_UART0_TX
+
#define OFFSET_THR 0x00 /* Transmit Holding register */
#define OFFSET_RBR 0x00 /* Receive Buffer register */
#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
diff --git a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
index 3d8978a52c17..bbc3c8386d48 100644
--- a/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
+++ b/arch/blackfin/mach-bf533/include/mach/cdefBF532.h
@@ -39,31 +39,8 @@
/*include core specific register pointer definitions*/
#include <asm/cdef_LPBlackfin.h>
-#include <asm/system.h>
-
/* Clock and System Control (0xFFC0 0400-0xFFC0 07FF) */
#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT,val)
#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
@@ -72,27 +49,6 @@ static __inline__ void bfin_write_PLL_CTL(unsigned int val)
#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV,val)
#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore(flags);
-}
/* System Interrupt Controller (0xFFC0 0C00-0xFFC0 0FFF) */
#define bfin_read_SWRST() bfin_read16(SWRST)
@@ -178,50 +134,6 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
#define bfin_read_FIO_MASKB_T() bfin_read16(FIO_MASKB_T)
#define bfin_write_FIO_MASKB_T(val) bfin_write16(FIO_MASKB_T,val)
-
-#if ANOMALY_05000311
-#define BFIN_WRITE_FIO_FLAG(name) \
-static __inline__ void bfin_write_FIO_FLAG_ ## name (unsigned short val)\
-{\
- unsigned long flags;\
- local_irq_save(flags);\
- bfin_write16(FIO_FLAG_ ## name,val);\
- bfin_read_CHIPID();\
- local_irq_restore(flags);\
-}
-BFIN_WRITE_FIO_FLAG(D)
-BFIN_WRITE_FIO_FLAG(C)
-BFIN_WRITE_FIO_FLAG(S)
-BFIN_WRITE_FIO_FLAG(T)
-
-#define BFIN_READ_FIO_FLAG(name) \
-static __inline__ unsigned short bfin_read_FIO_FLAG_ ## name (void)\
-{\
- unsigned long flags;\
- unsigned short ret;\
- local_irq_save(flags);\
- ret = bfin_read16(FIO_FLAG_ ## name);\
- bfin_read_CHIPID();\
- local_irq_restore(flags);\
- return ret;\
-}
-BFIN_READ_FIO_FLAG(D)
-BFIN_READ_FIO_FLAG(C)
-BFIN_READ_FIO_FLAG(S)
-BFIN_READ_FIO_FLAG(T)
-
-#else
-#define bfin_write_FIO_FLAG_D(val) bfin_write16(FIO_FLAG_D,val)
-#define bfin_write_FIO_FLAG_C(val) bfin_write16(FIO_FLAG_C,val)
-#define bfin_write_FIO_FLAG_S(val) bfin_write16(FIO_FLAG_S,val)
-#define bfin_write_FIO_FLAG_T(val) bfin_write16(FIO_FLAG_T,val)
-#define bfin_read_FIO_FLAG_T() bfin_read16(FIO_FLAG_T)
-#define bfin_read_FIO_FLAG_C() bfin_read16(FIO_FLAG_C)
-#define bfin_read_FIO_FLAG_S() bfin_read16(FIO_FLAG_S)
-#define bfin_read_FIO_FLAG_D() bfin_read16(FIO_FLAG_D)
-#endif
-
-
/* DMA Controller */
#define bfin_read_DMA0_CONFIG() bfin_read16(DMA0_CONFIG)
#define bfin_write_DMA0_CONFIG(val) bfin_write16(DMA0_CONFIG,val)
@@ -764,4 +676,93 @@ BFIN_READ_FIO_FLAG(T)
#define bfin_read_PPI_FRAME() bfin_read16(PPI_FRAME)
#define bfin_write_PPI_FRAME(val) bfin_write16(PPI_FRAME,val)
+/* These need to be last due to the cdef/linux inter-dependencies */
+#include <asm/irq.h>
+
+#if ANOMALY_05000311
+#define BFIN_WRITE_FIO_FLAG(name) \
+static inline void bfin_write_FIO_FLAG_##name(unsigned short val) \
+{ \
+ unsigned long flags; \
+ local_irq_save_hw(flags); \
+ bfin_write16(FIO_FLAG_##name, val); \
+ bfin_read_CHIPID(); \
+ local_irq_restore_hw(flags); \
+}
+BFIN_WRITE_FIO_FLAG(D)
+BFIN_WRITE_FIO_FLAG(C)
+BFIN_WRITE_FIO_FLAG(S)
+BFIN_WRITE_FIO_FLAG(T)
+
+#define BFIN_READ_FIO_FLAG(name) \
+static inline u16 bfin_read_FIO_FLAG_##name(void) \
+{ \
+ unsigned long flags; \
+ u16 ret; \
+ local_irq_save_hw(flags); \
+ ret = bfin_read16(FIO_FLAG_##name); \
+ bfin_read_CHIPID(); \
+ local_irq_restore_hw(flags); \
+ return ret; \
+}
+BFIN_READ_FIO_FLAG(D)
+BFIN_READ_FIO_FLAG(C)
+BFIN_READ_FIO_FLAG(S)
+BFIN_READ_FIO_FLAG(T)
+
+#else
+#define bfin_write_FIO_FLAG_D(val) bfin_write16(FIO_FLAG_D, val)
+#define bfin_write_FIO_FLAG_C(val) bfin_write16(FIO_FLAG_C, val)
+#define bfin_write_FIO_FLAG_S(val) bfin_write16(FIO_FLAG_S, val)
+#define bfin_write_FIO_FLAG_T(val) bfin_write16(FIO_FLAG_T, val)
+#define bfin_read_FIO_FLAG_T() bfin_read16(FIO_FLAG_T)
+#define bfin_read_FIO_FLAG_C() bfin_read16(FIO_FLAG_C)
+#define bfin_read_FIO_FLAG_S() bfin_read16(FIO_FLAG_S)
+#define bfin_read_FIO_FLAG_D() bfin_read16(FIO_FLAG_D)
+#endif
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ local_irq_restore_hw(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ local_irq_restore_hw(flags);
+}
+
#endif /* _CDEF_BF532_H */
diff --git a/arch/blackfin/mach-bf533/include/mach/dma.h b/arch/blackfin/mach-bf533/include/mach/dma.h
index bd9d5e94307d..fb34934c5ba8 100644
--- a/arch/blackfin/mach-bf533/include/mach/dma.h
+++ b/arch/blackfin/mach-bf533/include/mach/dma.h
@@ -1,42 +1,14 @@
-/*****************************************************************************
-*
-* BF-533/2/1 Specific Declarations
-*
-****************************************************************************/
-/*
- * File: include/asm-blackfin/mach-bf533/dma.h
- * Based on:
- * Author:
+/* mach/dma.h - arch-specific DMA defines
*
- * Created:
- * Description:
+ * Copyright 2004-2008 Analog Devices Inc.
*
- * Rev:
- *
- * Modified:
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
*/
#ifndef _MACH_DMA_H_
#define _MACH_DMA_H_
-#define MAX_BLACKFIN_DMA_CHANNEL 12
+#define MAX_DMA_CHANNELS 12
#define CH_PPI 0
#define CH_SPORT0_RX 1
@@ -44,8 +16,8 @@
#define CH_SPORT1_RX 3
#define CH_SPORT1_TX 4
#define CH_SPI 5
-#define CH_UART_RX 6
-#define CH_UART_TX 7
+#define CH_UART0_RX 6
+#define CH_UART0_TX 7
#define CH_MEM_STREAM0_DEST 8 /* TX */
#define CH_MEM_STREAM0_SRC 9 /* RX */
#define CH_MEM_STREAM1_DEST 10 /* TX */
diff --git a/arch/blackfin/mach-bf533/include/mach/gpio.h b/arch/blackfin/mach-bf533/include/mach/gpio.h
new file mode 100644
index 000000000000..e45c17077aff
--- /dev/null
+++ b/arch/blackfin/mach-bf533/include/mach/gpio.h
@@ -0,0 +1,34 @@
+/*
+ * File: arch/blackfin/mach-bf533/include/mach/gpio.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+
+#ifndef _MACH_GPIO_H_
+#define _MACH_GPIO_H_
+
+#define MAX_BLACKFIN_GPIOS 16
+
+#define GPIO_PF0 0
+#define GPIO_PF1 1
+#define GPIO_PF2 2
+#define GPIO_PF3 3
+#define GPIO_PF4 4
+#define GPIO_PF5 5
+#define GPIO_PF6 6
+#define GPIO_PF7 7
+#define GPIO_PF8 8
+#define GPIO_PF9 9
+#define GPIO_PF10 10
+#define GPIO_PF11 11
+#define GPIO_PF12 12
+#define GPIO_PF13 13
+#define GPIO_PF14 14
+#define GPIO_PF15 15
+
+#define PORT_F GPIO_PF0
+
+#endif /* _MACH_GPIO_H_ */
diff --git a/arch/blackfin/mach-bf533/include/mach/irq.h b/arch/blackfin/mach-bf533/include/mach/irq.h
index 5aa38e5da6b7..db1e346cd1aa 100644
--- a/arch/blackfin/mach-bf533/include/mach/irq.h
+++ b/arch/blackfin/mach-bf533/include/mach/irq.h
@@ -90,19 +90,19 @@ Core Emulation **
#define IRQ_SPORT0_ERROR 10 /*SPORT0 Error Interrupt */
#define IRQ_SPORT1_ERROR 11 /*SPORT1 Error Interrupt */
#define IRQ_SPI_ERROR 12 /*SPI Error Interrupt */
-#define IRQ_UART_ERROR 13 /*UART Error Interrupt */
+#define IRQ_UART0_ERROR 13 /*UART Error Interrupt */
#define IRQ_RTC 14 /*RTC Interrupt */
#define IRQ_PPI 15 /*DMA0 Interrupt (PPI) */
#define IRQ_SPORT0_RX 16 /*DMA1 Interrupt (SPORT0 RX) */
#define IRQ_SPORT0_TX 17 /*DMA2 Interrupt (SPORT0 TX) */
#define IRQ_SPORT1_RX 18 /*DMA3 Interrupt (SPORT1 RX) */
#define IRQ_SPORT1_TX 19 /*DMA4 Interrupt (SPORT1 TX) */
-#define IRQ_SPI 20 /*DMA5 Interrupt (SPI) */
-#define IRQ_UART_RX 21 /*DMA6 Interrupt (UART RX) */
-#define IRQ_UART_TX 22 /*DMA7 Interrupt (UART TX) */
-#define IRQ_TMR0 23 /*Timer 0 */
-#define IRQ_TMR1 24 /*Timer 1 */
-#define IRQ_TMR2 25 /*Timer 2 */
+#define IRQ_SPI 20 /*DMA5 Interrupt (SPI) */
+#define IRQ_UART0_RX 21 /*DMA6 Interrupt (UART RX) */
+#define IRQ_UART0_TX 22 /*DMA7 Interrupt (UART TX) */
+#define IRQ_TIMER0 23 /*Timer 0 */
+#define IRQ_TIMER1 24 /*Timer 1 */
+#define IRQ_TIMER2 25 /*Timer 2 */
#define IRQ_PROG_INTA 26 /*Programmable Flags A (8) */
#define IRQ_PROG_INTB 27 /*Programmable Flags B (8) */
#define IRQ_MEM_DMA0 28 /*DMA8/9 Interrupt (Memory DMA Stream 0) */
diff --git a/arch/blackfin/mach-bf533/include/mach/mem_init.h b/arch/blackfin/mach-bf533/include/mach/mem_init.h
deleted file mode 100644
index ed2034bf10ec..000000000000
--- a/arch/blackfin/mach-bf533/include/mach/mem_init.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * File: include/asm-blackfin/mach-bf533/mem_init.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || \
- CONFIG_MEM_MT48LC32M16A2TG_75 || CONFIG_MEM_GENERIC_BOARD)
-#if (CONFIG_SCLK_HZ > 119402985)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_7
-#define SDRAM_tRAS_num 7
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_6
-#define SDRAM_tRAS_num 6
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_5
-#define SDRAM_tRAS_num 5
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_4
-#define SDRAM_tRAS_num 4
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_3
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_4
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_3
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_2
-#define SDRAM_tRAS_num 2
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ <= 29850746)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_1
-#define SDRAM_tRAS_num 1
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#endif
-
-#if (CONFIG_MEM_MT48LC16M16A2TG_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC32M16A2TG_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_GENERIC_BOARD)
- /*SDRAM INFORMATION: Modify this for your board */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-/* Equation from section 17 (p17-46) of BF533 HRM */
-#define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
-
-/* Enable SCLK Out */
-#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
-
-#if defined CONFIG_CLKIN_HALF
-#define CLKIN_HALF 1
-#else
-#define CLKIN_HALF 0
-#endif
-
-#if defined CONFIG_PLL_BYPASS
-#define PLL_BYPASS 1
-#else
-#define PLL_BYPASS 0
-#endif
-
-/***************************************Currently Not Being Used *********************************/
-#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ))
-#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-
-#if (flash_EBIU_AMBCTL_TT > 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_4
-#endif
-#if (flash_EBIU_AMBCTL_TT == 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_3
-#endif
-#if (flash_EBIU_AMBCTL_TT == 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_2
-#endif
-#if (flash_EBIU_AMBCTL_TT < 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_ST > 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_4
-#endif
-#if (flash_EBIU_AMBCTL_ST == 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_3
-#endif
-#if (flash_EBIU_AMBCTL_ST == 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_2
-#endif
-#if (flash_EBIU_AMBCTL_ST < 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_1
-#endif
-
-#if (flash_EBIU_AMBCTL_HT > 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_3
-#endif
-#if (flash_EBIU_AMBCTL_HT == 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_2
-#endif
-#if (flash_EBIU_AMBCTL_HT == 1)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_0
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_WAT > 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_15
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_14
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 13)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_13
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 12)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_12
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 11)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_11
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 10)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_10
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 9)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_9
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 8)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_8
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 7)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_7
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 6)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_6
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 5)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_5
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 4)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_4
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 3)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_3
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 2)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_2
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 1)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_RAT > 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_15
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_14
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 13)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_13
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 12)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_12
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 11)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_11
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 10)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_10
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 9)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_9
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 8)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_8
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 7)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_7
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 6)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_6
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 5)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_5
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 4)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_4
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 3)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_3
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 2)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_2
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 1)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_1
-#endif
-
-#define flash_EBIU_AMBCTL0 \
- (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
- flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/arch/blackfin/mach-bf533/include/mach/mem_map.h b/arch/blackfin/mach-bf533/include/mach/mem_map.h
index 581fc6eea789..fc33b7cb9937 100644
--- a/arch/blackfin/mach-bf533/include/mach/mem_map.h
+++ b/arch/blackfin/mach-bf533/include/mach/mem_map.h
@@ -168,4 +168,10 @@
#define L1_SCRATCH_START 0xFFB00000
#define L1_SCRATCH_LENGTH 0x1000
+#define GET_PDA_SAFE(preg) \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda;
+
+#define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+
#endif /* _MEM_MAP_533_H_ */
diff --git a/arch/blackfin/mach-bf533/include/mach/portmux.h b/arch/blackfin/mach-bf533/include/mach/portmux.h
index 685a2651dcda..2f59ce0b0cb5 100644
--- a/arch/blackfin/mach-bf533/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf533/include/mach/portmux.h
@@ -54,14 +54,11 @@
#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2))
#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1))
#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
#define P_TMR2 (P_DONTCARE)
#define P_TMR1 (P_DONTCARE)
#define P_TMR0 (P_DONTCARE)
#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF1))
-
-
-
-
#endif /* _MACH_PORTMUX_H_ */
diff --git a/arch/blackfin/mach-bf537/Kconfig b/arch/blackfin/mach-bf537/Kconfig
index 8255374c04aa..bbc08fd4f122 100644
--- a/arch/blackfin/mach-bf537/Kconfig
+++ b/arch/blackfin/mach-bf537/Kconfig
@@ -64,29 +64,29 @@ config IRQ_MAC_RX
config IRQ_MAC_TX
int "IRQ_MAC_TX"
default 11
-config IRQ_TMR0
- int "IRQ_TMR0"
- default 12
-config IRQ_TMR1
- int "IRQ_TMR1"
+config IRQ_TIMER0
+ int "IRQ_TIMER0"
+ default 8
+config IRQ_TIMER1
+ int "IRQ_TIMER1"
default 12
-config IRQ_TMR2
- int "IRQ_TMR2"
+config IRQ_TIMER2
+ int "IRQ_TIMER2"
default 12
-config IRQ_TMR3
- int "IRQ_TMR3"
+config IRQ_TIMER3
+ int "IRQ_TIMER3"
default 12
-config IRQ_TMR4
- int "IRQ_TMR4"
+config IRQ_TIMER4
+ int "IRQ_TIMER4"
default 12
-config IRQ_TMR5
- int "IRQ_TMR5"
+config IRQ_TIMER5
+ int "IRQ_TIMER5"
default 12
-config IRQ_TMR6
- int "IRQ_TMR6"
+config IRQ_TIMER6
+ int "IRQ_TIMER6"
default 12
-config IRQ_TMR7
- int "IRQ_TMR7"
+config IRQ_TIMER7
+ int "IRQ_TIMER7"
default 12
config IRQ_PROG_INTA
int "IRQ_PROG_INTA"
diff --git a/arch/blackfin/mach-bf537/Makefile b/arch/blackfin/mach-bf537/Makefile
index 68e5478e95a9..56994b675f9c 100644
--- a/arch/blackfin/mach-bf537/Makefile
+++ b/arch/blackfin/mach-bf537/Makefile
@@ -2,6 +2,4 @@
# arch/blackfin/mach-bf537/Makefile
#
-extra-y := head.o
-
obj-y := ints-priority.o dma.o
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index dde14720b0ea..9cd8fb2a30d3 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -308,6 +308,19 @@ static struct platform_device net2272_bfin_device = {
};
#endif
+static struct resource bfin_gpios_resources = {
+ .start = 0,
+ .end = MAX_BLACKFIN_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+ .name = "simple-gpio",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &bfin_gpios_resources,
+};
+
#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
static struct mtd_partition cm_partitions[] = {
{
@@ -379,30 +392,57 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -439,8 +479,13 @@ static struct platform_device bfin_sport1_uart_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -525,7 +570,12 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -546,6 +596,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -564,6 +615,8 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
&cm_flash_device,
#endif
+
+ &bfin_gpios_device,
};
static int __init cm_bf537_init(void)
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 78a13d5bfd55..da710fdc4569 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -50,57 +50,46 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "GENERIC Board";
+const char bfin_board_name[] = "UNKNOWN BOARD";
/*
* Driver needs to know address, irq and flag pin.
*/
-#define ISP1761_BASE 0x203C0000
-#define ISP1761_IRQ IRQ_PF7
-
#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-static struct resource bfin_isp1761_resources[] = {
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
[0] = {
- .name = "isp1761-regs",
- .start = ISP1761_BASE + 0x00000000,
- .end = ISP1761_BASE + 0x000fffff,
+ .start = 0x203C0000,
+ .end = 0x203C0000 + 0x000fffff,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = ISP1761_IRQ,
- .end = ISP1761_IRQ,
+ .start = IRQ_PF7,
+ .end = IRQ_PF7,
.flags = IORESOURCE_IRQ,
},
};
-static struct platform_device bfin_isp1761_device = {
- .name = "isp1761",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_isp1761_resources),
- .resource = bfin_isp1761_resources,
+static struct isp1760_platform_data isp1760_priv = {
+ .is_isp1761 = 0,
+ .port1_disable = 0,
+ .bus_width_16 = 1,
+ .port1_otg = 0,
+ .analog_oc = 0,
+ .dack_polarity_high = 0,
+ .dreq_polarity_high = 0,
};
-static struct platform_device *bfin_isp1761_devices[] = {
- &bfin_isp1761_device,
+static struct platform_device bfin_isp1760_device = {
+ .name = "isp1760-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1760_priv,
+ },
+ .num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+ .resource = bfin_isp1760_resources,
};
-
-int __init bfin_isp1761_init(void)
-{
- unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
-
- printk(KERN_INFO "%s(): registering device resources\n", __func__);
- set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
-
- return platform_add_devices(bfin_isp1761_devices, num_devices);
-}
-
-void __exit bfin_isp1761_exit(void)
-{
- platform_device_unregister(&bfin_isp1761_device);
-}
-
-arch_initcall(bfin_isp1761_init);
#endif
#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
@@ -273,8 +262,13 @@ static struct platform_device isp1362_hcd_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -559,30 +553,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -644,6 +667,7 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -651,6 +675,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&net2272_bfin_device,
#endif
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+ &bfin_isp1760_device,
+#endif
+
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
&bfin_spi0_device,
#endif
@@ -668,7 +696,12 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -681,7 +714,7 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
};
-static int __init stamp_init(void)
+static int __init generic_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
@@ -693,13 +726,13 @@ static int __init stamp_init(void)
return 0;
}
-arch_initcall(stamp_init);
+arch_initcall(generic_init);
void native_machine_restart(char *cmd)
{
/* workaround reboot hang when booting from SPI */
if ((bfin_read_SYSCR() & 0x7) == 0x3)
- bfin_gpio_reset_spi0_ssel1();
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
}
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index 48c4cd2d1be6..db7d3a385e4b 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -61,8 +61,13 @@ static struct platform_device rtc_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -226,30 +231,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -295,6 +329,7 @@ static struct platform_device *minotaur_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -311,7 +346,12 @@ static struct platform_device *minotaur_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -343,5 +383,5 @@ void native_machine_restart(char *cmd)
{
/* workaround reboot hang when booting from SPI */
if ((bfin_read_SYSCR() & 0x7) == 0x3)
- bfin_gpio_reset_spi0_ssel1();
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
}
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index f9174c11cbd4..590eb3a139b7 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -49,7 +49,7 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "PNAV-1.0";
+const char bfin_board_name[] = "ADI PNAV-1.0";
/*
* Driver needs to know address, irq and flag pin.
@@ -198,8 +198,13 @@ static struct platform_device isp1362_hcd_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -453,30 +458,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
static struct platform_device *stamp_devices[] __initdata = {
#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE)
@@ -500,6 +534,7 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -520,11 +555,16 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
};
-static int __init stamp_init(void)
+static int __init pnav_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
@@ -535,7 +575,7 @@ static int __init stamp_init(void)
return 0;
}
-arch_initcall(stamp_init);
+arch_initcall(pnav_init);
void bfin_get_ether_addr(char *addr)
{
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 8d394393201f..cd04c5e44878 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -46,6 +46,7 @@
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/usb/sl811.h>
+#include <linux/spi/mmc_spi.h>
#include <asm/dma.h>
#include <asm/bfin5xx_spi.h>
#include <asm/reboot.h>
@@ -55,57 +56,46 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "ADDS-BF537-STAMP";
+const char bfin_board_name[] = "ADI BF537-STAMP";
/*
* Driver needs to know address, irq and flag pin.
*/
-#define ISP1761_BASE 0x203C0000
-#define ISP1761_IRQ IRQ_PF7
-
#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-static struct resource bfin_isp1761_resources[] = {
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
[0] = {
- .name = "isp1761-regs",
- .start = ISP1761_BASE + 0x00000000,
- .end = ISP1761_BASE + 0x000fffff,
+ .start = 0x203C0000,
+ .end = 0x203C0000 + 0x000fffff,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = ISP1761_IRQ,
- .end = ISP1761_IRQ,
- .flags = IORESOURCE_IRQ,
+ .start = IRQ_PF7,
+ .end = IRQ_PF7,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
},
};
-static struct platform_device bfin_isp1761_device = {
- .name = "isp1761",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_isp1761_resources),
- .resource = bfin_isp1761_resources,
+static struct isp1760_platform_data isp1760_priv = {
+ .is_isp1761 = 0,
+ .port1_disable = 0,
+ .bus_width_16 = 1,
+ .port1_otg = 0,
+ .analog_oc = 0,
+ .dack_polarity_high = 0,
+ .dreq_polarity_high = 0,
};
-static struct platform_device *bfin_isp1761_devices[] = {
- &bfin_isp1761_device,
+static struct platform_device bfin_isp1760_device = {
+ .name = "isp1760-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1760_priv,
+ },
+ .num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+ .resource = bfin_isp1760_resources,
};
-
-int __init bfin_isp1761_init(void)
-{
- unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
-
- printk(KERN_INFO "%s(): registering device resources\n", __func__);
- set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
-
- return platform_add_devices(bfin_isp1761_devices, num_devices);
-}
-
-void __exit bfin_isp1761_exit(void)
-{
- platform_device_unregister(&bfin_isp1761_device);
-}
-
-arch_initcall(bfin_isp1761_init);
#endif
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
@@ -331,8 +321,13 @@ static struct platform_device isp1362_hcd_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -443,11 +438,11 @@ static struct mtd_partition stamp_partitions[] = {
.offset = 0,
}, {
.name = "linux kernel(nor)",
- .size = 0xE0000,
+ .size = 0x180000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "file system(nor)",
- .size = 0x400000 - 0x40000 - 0xE0000 - 0x10000,
+ .size = 0x400000 - 0x40000 - 0x180000 - 0x10000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "MAC Address(nor)",
@@ -490,7 +485,7 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.mask_flags = MTD_CAP_ROM
}, {
.name = "linux kernel(spi)",
- .size = 0xe0000,
+ .size = 0x180000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "file system(spi)",
@@ -503,7 +498,7 @@ static struct flash_platform_data bfin_spi_flash_data = {
.name = "m25p80",
.parts = bfin_spi_flash_partitions,
.nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
- .type = "m25p64",
+ /* .type = "m25p64", */
};
/* SPI flash chip (m25p64) */
@@ -537,9 +532,29 @@ static struct bfin5xx_spi_chip ad9960_spi_chip_info = {
};
#endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
-static struct bfin5xx_spi_chip spi_mmc_chip_info = {
- .enable_dma = 1,
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
+#define MMC_SPI_CARD_DETECT_INT IRQ_PF5
+
+static int bfin_mmc_spi_init(struct device *dev,
+ irqreturn_t (*detect_int)(int, void *), void *data)
+{
+ return request_irq(MMC_SPI_CARD_DETECT_INT, detect_int,
+ IRQF_TRIGGER_FALLING, "mmc-spi-detect", data);
+}
+
+static void bfin_mmc_spi_exit(struct device *dev, void *data)
+{
+ free_irq(MMC_SPI_CARD_DETECT_INT, data);
+}
+
+static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
+ .init = bfin_mmc_spi_init,
+ .exit = bfin_mmc_spi_exit,
+ .detect_delay = 100, /* msecs */
+};
+
+static struct bfin5xx_spi_chip mmc_spi_chip_info = {
+ .enable_dma = 0,
.bits_per_word = 8,
};
#endif
@@ -613,6 +628,14 @@ static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
};
#endif
+#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
+static struct bfin5xx_spi_chip enc28j60_spi_chip_info = {
+ .enable_dma = 1,
+ .bits_per_word = 8,
+ .cs_gpio = GPIO_PF10,
+};
+#endif
+
#if defined(CONFIG_MTD_DATAFLASH) \
|| defined(CONFIG_MTD_DATAFLASH_MODULE)
@@ -624,7 +647,7 @@ static struct mtd_partition bfin_spi_dataflash_partitions[] = {
.mask_flags = MTD_CAP_ROM
}, {
.name = "linux kernel(spi)",
- .size = 0xe0000,
+ .size = 0x180000,
.offset = MTDPART_OFS_APPEND,
}, {
.name = "file system(spi)",
@@ -703,23 +726,14 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.controller_data = &ad9960_spi_chip_info,
},
#endif
-#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE)
+#if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
{
- .modalias = "spi_mmc_dummy",
+ .modalias = "mmc_spi",
.max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
- .chip_select = 0,
- .platform_data = NULL,
- .controller_data = &spi_mmc_chip_info,
- .mode = SPI_MODE_3,
- },
- {
- .modalias = "spi_mmc",
- .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 0,
- .chip_select = CONFIG_SPI_MMC_CS_CHAN,
- .platform_data = NULL,
- .controller_data = &spi_mmc_chip_info,
+ .chip_select = 4,
+ .platform_data = &bfin_mmc_spi_pdata,
+ .controller_data = &mmc_spi_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -783,6 +797,17 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_CPHA | SPI_CPOL,
},
#endif
+#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
+ {
+ .modalias = "enc28j60",
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
+ .irq = IRQ_PF6,
+ .bus_num = 0,
+ .chip_select = 0, /* GPIO controlled SSEL */
+ .controller_data = &enc28j60_spi_chip_info,
+ .mode = SPI_MODE_0,
+ },
+#endif
};
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
@@ -885,30 +910,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -932,7 +986,93 @@ static struct platform_device i2c_bfin_twi_device = {
};
#endif
-#ifdef CONFIG_I2C_BOARDINFO
+#if defined(CONFIG_KEYBOARD_ADP5588) || defined(CONFIG_KEYBOARD_ADP5588_MODULE)
+#include <linux/input.h>
+#include <linux/i2c/adp5588_keys.h>
+static const unsigned short adp5588_keymap[ADP5588_KEYMAPSIZE] = {
+ [0] = KEY_GRAVE,
+ [1] = KEY_1,
+ [2] = KEY_2,
+ [3] = KEY_3,
+ [4] = KEY_4,
+ [5] = KEY_5,
+ [6] = KEY_6,
+ [7] = KEY_7,
+ [8] = KEY_8,
+ [9] = KEY_9,
+ [10] = KEY_0,
+ [11] = KEY_MINUS,
+ [12] = KEY_EQUAL,
+ [13] = KEY_BACKSLASH,
+ [15] = KEY_KP0,
+ [16] = KEY_Q,
+ [17] = KEY_W,
+ [18] = KEY_E,
+ [19] = KEY_R,
+ [20] = KEY_T,
+ [21] = KEY_Y,
+ [22] = KEY_U,
+ [23] = KEY_I,
+ [24] = KEY_O,
+ [25] = KEY_P,
+ [26] = KEY_LEFTBRACE,
+ [27] = KEY_RIGHTBRACE,
+ [29] = KEY_KP1,
+ [30] = KEY_KP2,
+ [31] = KEY_KP3,
+ [32] = KEY_A,
+ [33] = KEY_S,
+ [34] = KEY_D,
+ [35] = KEY_F,
+ [36] = KEY_G,
+ [37] = KEY_H,
+ [38] = KEY_J,
+ [39] = KEY_K,
+ [40] = KEY_L,
+ [41] = KEY_SEMICOLON,
+ [42] = KEY_APOSTROPHE,
+ [43] = KEY_BACKSLASH,
+ [45] = KEY_KP4,
+ [46] = KEY_KP5,
+ [47] = KEY_KP6,
+ [48] = KEY_102ND,
+ [49] = KEY_Z,
+ [50] = KEY_X,
+ [51] = KEY_C,
+ [52] = KEY_V,
+ [53] = KEY_B,
+ [54] = KEY_N,
+ [55] = KEY_M,
+ [56] = KEY_COMMA,
+ [57] = KEY_DOT,
+ [58] = KEY_SLASH,
+ [60] = KEY_KPDOT,
+ [61] = KEY_KP7,
+ [62] = KEY_KP8,
+ [63] = KEY_KP9,
+ [64] = KEY_SPACE,
+ [65] = KEY_BACKSPACE,
+ [66] = KEY_TAB,
+ [67] = KEY_KPENTER,
+ [68] = KEY_ENTER,
+ [69] = KEY_ESC,
+ [70] = KEY_DELETE,
+ [74] = KEY_KPMINUS,
+ [76] = KEY_UP,
+ [77] = KEY_DOWN,
+ [78] = KEY_RIGHT,
+ [79] = KEY_LEFT,
+};
+
+static struct adp5588_kpad_platform_data adp5588_kpad_data = {
+ .rows = 8,
+ .cols = 10,
+ .keymap = adp5588_keymap,
+ .keymapsize = ARRAY_SIZE(adp5588_keymap),
+ .repeat = 0,
+};
+#endif
+
static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
{
@@ -958,8 +1098,14 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
.platform_data = (void *)&bfin_ad7879_ts_info,
},
#endif
-};
+#if defined(CONFIG_KEYBOARD_ADP5588) || defined(CONFIG_KEYBOARD_ADP5588_MODULE)
+ {
+ I2C_BOARD_INFO("adp5588-keys", 0x34),
+ .irq = IRQ_PG0,
+ .platform_data = (void *)&adp5588_kpad_data,
+ },
#endif
+};
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
static struct platform_device bfin_sport0_uart_device = {
@@ -1057,6 +1203,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&isp1362_hcd_device,
#endif
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+ &bfin_isp1760_device,
+#endif
+
#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
&smc91x_device,
#endif
@@ -1070,6 +1220,7 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -1098,7 +1249,12 @@ static struct platform_device *stamp_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -1132,12 +1288,8 @@ static struct platform_device *stamp_devices[] __initdata = {
static int __init stamp_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
-
-#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(0, bfin_i2c_board_info,
ARRAY_SIZE(bfin_i2c_board_info));
-#endif
-
bfin_plat_nand_init();
platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices));
spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info));
@@ -1155,7 +1307,7 @@ void native_machine_restart(char *cmd)
{
/* workaround reboot hang when booting from SPI */
if ((bfin_read_SYSCR() & 0x7) == 0x3)
- bfin_gpio_reset_spi0_ssel1();
+ bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS);
}
/*
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index d5ff705a5129..3f4f203a06ec 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -308,6 +308,19 @@ static struct platform_device net2272_bfin_device = {
};
#endif
+static struct resource bfin_gpios_resources = {
+ .start = 0,
+ .end = MAX_BLACKFIN_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+ .name = "simple-gpio",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &bfin_gpios_resources,
+};
+
#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
static struct mtd_partition cm_partitions[] = {
{
@@ -379,30 +392,59 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir1_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
};
#endif
+#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
@@ -439,8 +481,13 @@ static struct platform_device bfin_sport1_uart_device = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+static struct platform_device bfin_mii_bus = {
+ .name = "bfin_mii_bus",
+};
+
static struct platform_device bfin_mac_device = {
.name = "bfin_mac",
+ .dev.platform_data = &bfin_mii_bus,
};
#endif
@@ -525,7 +572,12 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
@@ -546,6 +598,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+ &bfin_mii_bus,
&bfin_mac_device,
#endif
@@ -564,9 +617,11 @@ static struct platform_device *cm_bf537_devices[] __initdata = {
#if defined(CONFIG_MTD_GPIO_ADDR) || defined(CONFIG_MTD_GPIO_ADDR_MODULE)
&cm_flash_device,
#endif
+
+ &bfin_gpios_device,
};
-static int __init cm_bf537_init(void)
+static int __init tcm_bf537_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices));
@@ -580,7 +635,7 @@ static int __init cm_bf537_init(void)
return 0;
}
-arch_initcall(cm_bf537_init);
+arch_initcall(tcm_bf537_init);
void bfin_get_ether_addr(char *addr)
{
diff --git a/arch/blackfin/mach-bf537/dma.c b/arch/blackfin/mach-bf537/dma.c
index 4edb363ff99c..81185051de91 100644
--- a/arch/blackfin/mach-bf537/dma.c
+++ b/arch/blackfin/mach-bf537/dma.c
@@ -31,7 +31,7 @@
#include <asm/blackfin.h>
#include <asm/dma.h>
-struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
(struct dma_register *) DMA0_NEXT_DESC_PTR,
(struct dma_register *) DMA1_NEXT_DESC_PTR,
(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S
deleted file mode 100644
index f5c94bf80e3b..000000000000
--- a/arch/blackfin/mach-bf537/head.S
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * File: arch/blackfin/mach-bf537/head.S
- * Based on: arch/blackfin/mach-bf533/head.S
- * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
- *
- * Created: 1998
- * Description: Startup code for Blackfin BF537
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/blackfin.h>
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-#include <asm/clocks.h>
-#include <mach/mem_init.h>
-#endif
-
-.section .l1.text
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-ENTRY(_start_dma_code)
-
- /* Enable PHY CLK buffer output */
- p0.h = hi(VR_CTL);
- p0.l = lo(VR_CTL);
- r0.l = w[p0];
- bitset(r0, 14);
- w[p0] = r0.l;
- ssync;
-
- p0.h = hi(SIC_IWR);
- p0.l = lo(SIC_IWR);
- r0.l = 0x1;
- r0.h = 0x0;
- [p0] = r0;
- SSYNC;
-
- /*
- * Set PLL_CTL
- * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
- * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
- * - [7] = output delay (add 200ps of delay to mem signals)
- * - [6] = input delay (add 200ps of input delay to mem signals)
- * - [5] = PDWN : 1=All Clocks off
- * - [3] = STOPCK : 1=Core Clock off
- * - [1] = PLL_OFF : 1=Disable Power to PLL
- * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
- * all other bits set to zero
- */
-
- p0.h = hi(PLL_LOCKCNT);
- p0.l = lo(PLL_LOCKCNT);
- r0 = 0x300(Z);
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITSET (R0, 24);
- [P2] = R0;
- SSYNC;
-
- r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
- r0 = r0 << 9; /* Shift it over, */
- r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
- r0 = r1 | r0;
- r1 = PLL_BYPASS; /* Bypass the PLL? */
- r1 = r1 << 8; /* Shift it over */
- r0 = r1 | r0; /* add them all together */
-#ifdef ANOMALY_05000265
- BITSET(r0, 15); /* Add 250 mV of hysteresis to SPORT input pins */
-#endif
-
- p0.h = hi(PLL_CTL);
- p0.l = lo(PLL_CTL); /* Load the address */
- cli r2; /* Disable interrupts */
- ssync;
- w[p0] = r0.l; /* Set the value */
- idle; /* Wait for the PLL to stablize */
- sti r2; /* Enable interrupts */
-
-.Lcheck_again:
- p0.h = hi(PLL_STAT);
- p0.l = lo(PLL_STAT);
- R0 = W[P0](Z);
- CC = BITTST(R0,5);
- if ! CC jump .Lcheck_again;
-
- /* Configure SCLK & CCLK Dividers */
- r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
- p0.h = hi(PLL_DIV);
- p0.l = lo(PLL_DIV);
- w[p0] = r0.l;
- ssync;
-
- p0.l = lo(EBIU_SDRRC);
- p0.h = hi(EBIU_SDRRC);
- r0 = mem_SDRRC;
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITCLR (R0, 24);
- p0.h = hi(EBIU_SDSTAT);
- p0.l = lo(EBIU_SDSTAT);
- r2.l = w[p0];
- cc = bittst(r2,3);
- if !cc jump .Lskip;
- NOP;
- BITSET (R0, 23);
-.Lskip:
- [P2] = R0;
- SSYNC;
-
- R0.L = lo(mem_SDGCTL);
- R0.H = hi(mem_SDGCTL);
- R1 = [p2];
- R1 = R1 | R0;
- [P2] = R1;
- SSYNC;
-
- RTS;
-ENDPROC(_start_dma_code)
-#endif /* CONFIG_BFIN_KERNEL_CLOCK */
diff --git a/arch/blackfin/mach-bf537/include/mach/anomaly.h b/arch/blackfin/mach-bf537/include/mach/anomaly.h
index c68992494f9e..9cb39121d1cb 100644
--- a/arch/blackfin/mach-bf537/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf537/include/mach/anomaly.h
@@ -7,7 +7,7 @@
*/
/* This file shoule be up to date with:
- * - Revision C, 02/08/2008; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
+ * - Revision D, 09/18/2008; ADSP-BF534/ADSP-BF536/ADSP-BF537 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -148,6 +148,14 @@
#define ANOMALY_05000402 (__SILICON_REVISION__ >= 5)
/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
#define ANOMALY_05000403 (1)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
+/* Multichannel SPORT Channel Misalignment Under Specific Configuration */
+#define ANOMALY_05000425 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000125 (0)
@@ -161,5 +169,8 @@
#define ANOMALY_05000353 (1)
#define ANOMALY_05000363 (0)
#define ANOMALY_05000386 (1)
+#define ANOMALY_05000412 (0)
+#define ANOMALY_05000432 (0)
+#define ANOMALY_05000435 (0)
#endif
diff --git a/arch/blackfin/mach-bf537/include/mach/bf537.h b/arch/blackfin/mach-bf537/include/mach/bf537.h
index 24d5c9d42323..f194a848ae8e 100644
--- a/arch/blackfin/mach-bf537/include/mach/bf537.h
+++ b/arch/blackfin/mach-bf537/include/mach/bf537.h
@@ -133,7 +133,7 @@
#endif
#ifndef CPU
-#error Unknown CPU type - This kernel doesn't seem to be configured properly
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
#endif
#endif /* __MACH_BF537_H__ */
diff --git a/arch/blackfin/mach-bf537/include/mach/bfin_sir.h b/arch/blackfin/mach-bf537/include/mach/bfin_sir.h
deleted file mode 100644
index cfd8ad4f1f2c..000000000000
--- a/arch/blackfin/mach-bf537/include/mach/bfin_sir.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Blackfin Infra-red Driver
- *
- * Copyright 2006-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- *
- */
-
-#include <linux/serial.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-
-#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
-#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
-#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
-#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
-#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
-#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
-#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
-
-#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
-#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
-#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
-#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
-#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
-#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
-
-#ifdef CONFIG_SIR_BFIN_DMA
-struct dma_rx_buf {
- char *buf;
- int head;
- int tail;
- };
-#endif /* CONFIG_SIR_BFIN_DMA */
-
-struct bfin_sir_port {
- unsigned char __iomem *membase;
- unsigned int irq;
- unsigned int lsr;
- unsigned long clk;
- struct net_device *dev;
-#ifdef CONFIG_SIR_BFIN_DMA
- int tx_done;
- struct dma_rx_buf rx_dma_buf;
- struct timer_list rx_dma_timer;
- int rx_dma_nrows;
-#endif /* CONFIG_SIR_BFIN_DMA */
- unsigned int tx_dma_channel;
- unsigned int rx_dma_channel;
-};
-
-struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
-
-struct bfin_sir_port_res {
- unsigned long base_addr;
- int irq;
- unsigned int rx_dma_channel;
- unsigned int tx_dma_channel;
-};
-
-struct bfin_sir_port_res bfin_sir_port_resource[] = {
-#ifdef CONFIG_BFIN_SIR0
- {
- 0xFFC00400,
- IRQ_UART0_RX,
- CH_UART0_RX,
- CH_UART0_TX,
- },
-#endif
-#ifdef CONFIG_BFIN_SIR1
- {
- 0xFFC02000,
- IRQ_UART1_RX,
- CH_UART1_RX,
- CH_UART1_TX,
- },
-#endif
-};
-
-int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
-
-struct bfin_sir_self {
- struct bfin_sir_port *sir_port;
- spinlock_t lock;
- unsigned int open;
- int speed;
- int newspeed;
-
- struct sk_buff *txskb;
- struct sk_buff *rxskb;
- struct net_device_stats stats;
- struct device *dev;
- struct irlap_cb *irlap;
- struct qos_info qos;
-
- iobuff_t tx_buff;
- iobuff_t rx_buff;
-
- struct work_struct work;
- int mtt;
-};
-
-static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
-{
- unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
- port->lsr |= (lsr & (BI|FE|PE|OE));
- return lsr | port->lsr;
-}
-
-static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
-{
- port->lsr = 0;
- bfin_read16(port->membase + OFFSET_LSR);
-}
-
-#define DRIVER_NAME "bfin_sir"
-
-static int bfin_sir_hw_init(void)
-{
- int ret = -ENODEV;
-#ifdef CONFIG_BFIN_SIR0
- ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
-
-#ifdef CONFIG_BFIN_SIR1
- ret = peripheral_request(P_UART1_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART1_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
- return ret;
-}
diff --git a/arch/blackfin/mach-bf537/include/mach/blackfin.h b/arch/blackfin/mach-bf537/include/mach/blackfin.h
index cffc786b2a2b..7d6069c886f1 100644
--- a/arch/blackfin/mach-bf537/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf537/include/mach/blackfin.h
@@ -82,7 +82,7 @@
#define STATUS_P1 0x02
#define STATUS_P0 0x01
-/* DMA Channnel */
+/* DMA Channel */
#define bfin_read_CH_UART_RX() bfin_read_CH_UART0_RX()
#define bfin_write_CH_UART_RX(val) bfin_write_CH_UART0_RX(val)
#define CH_UART_RX CH_UART0_RX
diff --git a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
index 88d491cd9f36..5f8b5f845be6 100644
--- a/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/cdefBF534.h
@@ -40,55 +40,11 @@
/* Include core specific register pointer definitions */
#include <asm/cdef_LPBlackfin.h>
-#include <asm/system.h>
-
/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV,val)
#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SIC_IWR);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR, IWR_ENABLE(0));
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR, iwr);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT,val)
#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
@@ -1816,4 +1772,51 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
#define bfin_read_HMDMA1_BCOUNT() bfin_read16(HMDMA1_BCOUNT)
#define bfin_write_HMDMA1_BCOUNT(val) bfin_write16(HMDMA1_BCOUNT,val)
+/* These need to be last due to the cdef/linux inter-dependencies */
+#include <asm/irq.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ local_irq_restore_hw(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr = bfin_read32(SIC_IWR);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR, IWR_ENABLE(0));
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR, iwr);
+ local_irq_restore_hw(flags);
+}
+
#endif /* _CDEF_BF534_H */
diff --git a/arch/blackfin/mach-bf537/include/mach/dma.h b/arch/blackfin/mach-bf537/include/mach/dma.h
index 7a964040870a..5ae83b1183a1 100644
--- a/arch/blackfin/mach-bf537/include/mach/dma.h
+++ b/arch/blackfin/mach-bf537/include/mach/dma.h
@@ -1,38 +1,14 @@
-/*
- * file: include/asm-blackfin/mach-bf537/dma.h
- * based on:
- * author:
+/* mach/dma.h - arch-specific DMA defines
*
- * created:
- * description:
- * system mmr register map
- * rev:
+ * Copyright 2004-2008 Analog Devices Inc.
*
- * modified:
- *
- *
- * bugs: enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, 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; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
*/
#ifndef _MACH_DMA_H_
#define _MACH_DMA_H_
-#define MAX_BLACKFIN_DMA_CHANNEL 16
+#define MAX_DMA_CHANNELS 16
#define CH_PPI 0
#define CH_EMAC_RX 1
diff --git a/arch/blackfin/mach-bf537/include/mach/gpio.h b/arch/blackfin/mach-bf537/include/mach/gpio.h
new file mode 100644
index 000000000000..d77a31e45a30
--- /dev/null
+++ b/arch/blackfin/mach-bf537/include/mach/gpio.h
@@ -0,0 +1,68 @@
+/*
+ * File: arch/blackfin/mach-bf537/include/mach/gpio.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+
+#ifndef _MACH_GPIO_H_
+#define _MACH_GPIO_H_
+
+#define MAX_BLACKFIN_GPIOS 48
+
+#define GPIO_PF0 0
+#define GPIO_PF1 1
+#define GPIO_PF2 2
+#define GPIO_PF3 3
+#define GPIO_PF4 4
+#define GPIO_PF5 5
+#define GPIO_PF6 6
+#define GPIO_PF7 7
+#define GPIO_PF8 8
+#define GPIO_PF9 9
+#define GPIO_PF10 10
+#define GPIO_PF11 11
+#define GPIO_PF12 12
+#define GPIO_PF13 13
+#define GPIO_PF14 14
+#define GPIO_PF15 15
+#define GPIO_PG0 16
+#define GPIO_PG1 17
+#define GPIO_PG2 18
+#define GPIO_PG3 19
+#define GPIO_PG4 20
+#define GPIO_PG5 21
+#define GPIO_PG6 22
+#define GPIO_PG7 23
+#define GPIO_PG8 24
+#define GPIO_PG9 25
+#define GPIO_PG10 26
+#define GPIO_PG11 27
+#define GPIO_PG12 28
+#define GPIO_PG13 29
+#define GPIO_PG14 30
+#define GPIO_PG15 31
+#define GPIO_PH0 32
+#define GPIO_PH1 33
+#define GPIO_PH2 34
+#define GPIO_PH3 35
+#define GPIO_PH4 36
+#define GPIO_PH5 37
+#define GPIO_PH6 38
+#define GPIO_PH7 39
+#define GPIO_PH8 40
+#define GPIO_PH9 41
+#define GPIO_PH10 42
+#define GPIO_PH11 43
+#define GPIO_PH12 44
+#define GPIO_PH13 45
+#define GPIO_PH14 46
+#define GPIO_PH15 47
+
+#define PORT_F GPIO_PF0
+#define PORT_G GPIO_PG0
+#define PORT_H GPIO_PH0
+
+#endif /* _MACH_GPIO_H_ */
diff --git a/arch/blackfin/mach-bf537/include/mach/irq.h b/arch/blackfin/mach-bf537/include/mach/irq.h
index 2e68a8a1e730..b2a71d5d4e5f 100644
--- a/arch/blackfin/mach-bf537/include/mach/irq.h
+++ b/arch/blackfin/mach-bf537/include/mach/irq.h
@@ -82,14 +82,14 @@
#define IRQ_CAN_TX 23 /*CAN Transmit Interrupt */
#define IRQ_MAC_RX 24 /*DMA1 (Ethernet RX) Interrupt */
#define IRQ_MAC_TX 25 /*DMA2 (Ethernet TX) Interrupt */
-#define IRQ_TMR0 26 /*Timer 0 */
-#define IRQ_TMR1 27 /*Timer 1 */
-#define IRQ_TMR2 28 /*Timer 2 */
-#define IRQ_TMR3 29 /*Timer 3 */
-#define IRQ_TMR4 30 /*Timer 4 */
-#define IRQ_TMR5 31 /*Timer 5 */
-#define IRQ_TMR6 32 /*Timer 6 */
-#define IRQ_TMR7 33 /*Timer 7 */
+#define IRQ_TIMER0 26 /*Timer 0 */
+#define IRQ_TIMER1 27 /*Timer 1 */
+#define IRQ_TIMER2 28 /*Timer 2 */
+#define IRQ_TIMER3 29 /*Timer 3 */
+#define IRQ_TIMER4 30 /*Timer 4 */
+#define IRQ_TIMER5 31 /*Timer 5 */
+#define IRQ_TIMER6 32 /*Timer 6 */
+#define IRQ_TIMER7 33 /*Timer 7 */
#define IRQ_PROG_INTA 34 /* PF Ports F&G (PF15:0) Interrupt A */
#define IRQ_PORTG_INTB 35 /* PF Port G (PF15:0) Interrupt B */
#define IRQ_MEM_DMA0 36 /*(Memory DMA Stream 0) */
@@ -195,16 +195,16 @@
#define IRQ_CAN_TX_POS 0
#define IRQ_MAC_RX_POS 4
#define IRQ_MAC_TX_POS 8
-#define IRQ_TMR0_POS 12
-#define IRQ_TMR1_POS 16
-#define IRQ_TMR2_POS 20
-#define IRQ_TMR3_POS 24
-#define IRQ_TMR4_POS 28
+#define IRQ_TIMER0_POS 12
+#define IRQ_TIMER1_POS 16
+#define IRQ_TIMER2_POS 20
+#define IRQ_TIMER3_POS 24
+#define IRQ_TIMER4_POS 28
/* IAR3 BIT FIELDS*/
-#define IRQ_TMR5_POS 0
-#define IRQ_TMR6_POS 4
-#define IRQ_TMR7_POS 8
+#define IRQ_TIMER5_POS 0
+#define IRQ_TIMER6_POS 4
+#define IRQ_TIMER7_POS 8
#define IRQ_PROG_INTA_POS 12
#define IRQ_PORTG_INTB_POS 16
#define IRQ_MEM_DMA0_POS 20
diff --git a/arch/blackfin/mach-bf537/include/mach/mem_init.h b/arch/blackfin/mach-bf537/include/mach/mem_init.h
deleted file mode 100644
index f67698f670ca..000000000000
--- a/arch/blackfin/mach-bf537/include/mach/mem_init.h
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * File: include/asm-blackfin/mach-bf537/mem_init.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_MT48LC16M8A2TG_75 || CONFIG_MEM_GENERIC_BOARD || CONFIG_MEM_MT48LC32M8A2_75)
-#if (CONFIG_SCLK_HZ > 119402985)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_7
-#define SDRAM_tRAS_num 7
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_6
-#define SDRAM_tRAS_num 6
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_5
-#define SDRAM_tRAS_num 5
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_4
-#define SDRAM_tRAS_num 4
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_3
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_4
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_3
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_2
-#define SDRAM_tRAS_num 2
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ <= 29850746)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_1
-#define SDRAM_tRAS_num 1
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#endif
-
-#if (CONFIG_MEM_MT48LC16M16A2TG_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC16M8A2TG_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 4096 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC32M8A2_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_GENERIC_BOARD)
- /*SDRAM INFORMATION: Modify this for your board */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-/* Equation from section 17 (p17-46) of BF533 HRM */
-#define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
-
-/* Enable SCLK Out */
-#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
-
-#if defined CONFIG_CLKIN_HALF
-#define CLKIN_HALF 1
-#else
-#define CLKIN_HALF 0
-#endif
-
-#if defined CONFIG_PLL_BYPASS
-#define PLL_BYPASS 1
-#else
-#define PLL_BYPASS 0
-#endif
-
-/***************************************Currently Not Being Used *********************************/
-#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ))
-#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-
-#if (flash_EBIU_AMBCTL_TT > 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_4
-#endif
-#if (flash_EBIU_AMBCTL_TT == 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_3
-#endif
-#if (flash_EBIU_AMBCTL_TT == 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_2
-#endif
-#if (flash_EBIU_AMBCTL_TT < 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_ST > 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_4
-#endif
-#if (flash_EBIU_AMBCTL_ST == 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_3
-#endif
-#if (flash_EBIU_AMBCTL_ST == 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_2
-#endif
-#if (flash_EBIU_AMBCTL_ST < 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_1
-#endif
-
-#if (flash_EBIU_AMBCTL_HT > 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_3
-#endif
-#if (flash_EBIU_AMBCTL_HT == 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_2
-#endif
-#if (flash_EBIU_AMBCTL_HT == 1)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_0
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_WAT > 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_15
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_14
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 13)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_13
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 12)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_12
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 11)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_11
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 10)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_10
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 9)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_9
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 8)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_8
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 7)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_7
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 6)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_6
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 5)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_5
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 4)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_4
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 3)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_3
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 2)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_2
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 1)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_RAT > 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_15
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_14
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 13)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_13
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 12)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_12
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 11)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_11
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 10)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_10
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 9)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_9
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 8)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_8
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 7)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_7
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 6)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_6
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 5)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_5
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 4)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_4
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 3)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_3
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 2)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_2
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 1)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_1
-#endif
-
-#define flash_EBIU_AMBCTL0 \
- (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
- flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/arch/blackfin/mach-bf537/include/mach/mem_map.h b/arch/blackfin/mach-bf537/include/mach/mem_map.h
index 5078b669431f..f9010c4b4bf3 100644
--- a/arch/blackfin/mach-bf537/include/mach/mem_map.h
+++ b/arch/blackfin/mach-bf537/include/mach/mem_map.h
@@ -176,4 +176,10 @@
#define L1_SCRATCH_START 0xFFB00000
#define L1_SCRATCH_LENGTH 0x1000
+#define GET_PDA_SAFE(preg) \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda;
+
+#define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+
#endif /* _MEM_MAP_537_H_ */
diff --git a/arch/blackfin/mach-bf537/include/mach/portmux.h b/arch/blackfin/mach-bf537/include/mach/portmux.h
index 78fee6e0f237..87285e75e903 100644
--- a/arch/blackfin/mach-bf537/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf537/include/mach/portmux.h
@@ -31,6 +31,7 @@
#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
#define P_TACLK0 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1
#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
diff --git a/arch/blackfin/mach-bf537/ints-priority.c b/arch/blackfin/mach-bf537/ints-priority.c
index b1300b3f1812..51c48087e03b 100644
--- a/arch/blackfin/mach-bf537/ints-priority.c
+++ b/arch/blackfin/mach-bf537/ints-priority.c
@@ -55,15 +55,15 @@ void __init program_IAR(void)
bfin_write_SIC_IAR2(((CONFIG_IRQ_CAN_TX - 7) << IRQ_CAN_TX_POS) |
((CONFIG_IRQ_MAC_RX - 7) << IRQ_MAC_RX_POS) |
((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) |
- ((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) |
- ((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) |
- ((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) |
- ((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) |
- ((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS));
+ ((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+ ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+ ((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+ ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+ ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS));
- bfin_write_SIC_IAR3(((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) |
- ((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) |
- ((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS) |
+ bfin_write_SIC_IAR3(((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+ ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+ ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
((CONFIG_IRQ_PROG_INTA - 7) << IRQ_PROG_INTA_POS) |
((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) |
((CONFIG_IRQ_MEM_DMA0 - 7) << IRQ_MEM_DMA0_POS) |
diff --git a/arch/blackfin/mach-bf538/Kconfig b/arch/blackfin/mach-bf538/Kconfig
new file mode 100644
index 000000000000..f068c3523cdc
--- /dev/null
+++ b/arch/blackfin/mach-bf538/Kconfig
@@ -0,0 +1,164 @@
+if (BF538 || BF539)
+
+source "arch/blackfin/mach-bf538/boards/Kconfig"
+
+menu "BF538 Specific Configuration"
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+ int "IRQ_PLL_WAKEUP"
+ default 7
+config IRQ_DMA0_ERROR
+ int "IRQ_DMA0_ERROR"
+ default 7
+config IRQ_PPI_ERROR
+ int "IRQ_PPI_ERROR"
+ default 7
+config IRQ_SPORT0_ERROR
+ int "IRQ_SPORT0_ERROR"
+ default 7
+config IRQ_SPORT1_ERROR
+ int "IRQ_SPORT1_ERROR"
+ default 7
+config IRQ_SPI0_ERROR
+ int "IRQ_SPI0_ERROR"
+ default 7
+config IRQ_UART0_ERROR
+ int "IRQ_UART0_ERROR"
+ default 7
+config IRQ_RTC
+ int "IRQ_RTC"
+ default 8
+config IRQ_PPI
+ int "IRQ_PPI"
+ default 8
+config IRQ_SPORT0_RX
+ int "IRQ_SPORT0_RX"
+ default 9
+config IRQ_SPORT0_TX
+ int "IRQ_SPORT0_TX"
+ default 9
+config IRQ_SPORT1_RX
+ int "IRQ_SPORT1_RX"
+ default 9
+config IRQ_SPORT1_TX
+ int "IRQ_SPORT1_TX"
+ default 9
+config IRQ_SPI0
+ int "IRQ_SPI0"
+ default 10
+config IRQ_UART0_RX
+ int "IRQ_UART0_RX"
+ default 10
+config IRQ_UART0_TX
+ int "IRQ_UART0_TX"
+ default 10
+config IRQ_TIMER0
+ int "IRQ_TIMER0"
+ default 8
+config IRQ_TIMER1
+ int "IRQ_TIMER1"
+ default 11
+config IRQ_TIMER2
+ int "IRQ_TIMER2"
+ default 11
+config IRQ_PORTF_INTA
+ int "IRQ_PORTF_INTA"
+ default 12
+config IRQ_PORTF_INTB
+ int "IRQ_PORTF_INTB"
+ default 12
+config IRQ_MEM0_DMA0
+ int "IRQ_MEM0_DMA0"
+ default 13
+config IRQ_MEM0_DMA1
+ int "IRQ_MEM0_DMA1"
+ default 13
+config IRQ_WATCH
+ int "IRQ_WATCH"
+ default 13
+config IRQ_DMA1_ERROR
+ int "IRQ_DMA1_ERROR"
+ default 7
+config IRQ_SPORT2_ERROR
+ int "IRQ_SPORT2_ERROR"
+ default 7
+config IRQ_SPORT3_ERROR
+ int "IRQ_SPORT3_ERROR"
+ default 7
+config IRQ_SPI1_ERROR
+ int "IRQ_SPI1_ERROR"
+ default 7
+config IRQ_SPI2_ERROR
+ int "IRQ_SPI2_ERROR"
+ default 7
+config IRQ_UART1_ERROR
+ int "IRQ_UART1_ERROR"
+ default 7
+config IRQ_UART2_ERROR
+ int "IRQ_UART2_ERROR"
+ default 7
+config IRQ_CAN_ERROR
+ int "IRQ_CAN_ERROR"
+ default 7
+config IRQ_SPORT2_RX
+ int "IRQ_SPORT2_RX"
+ default 9
+config IRQ_SPORT2_TX
+ int "IRQ_SPORT2_TX"
+ default 9
+config IRQ_SPORT3_RX
+ int "IRQ_SPORT3_RX"
+ default 9
+config IRQ_SPORT3_TX
+ int "IRQ_SPORT3_TX"
+ default 9
+config IRQ_SPI1
+ int "IRQ_SPI1"
+ default 10
+config IRQ_SPI2
+ int "IRQ_SPI2"
+ default 10
+config IRQ_UART1_RX
+ int "IRQ_UART1_RX"
+ default 10
+config IRQ_UART1_TX
+ int "IRQ_UART1_TX"
+ default 10
+config IRQ_UART2_RX
+ int "IRQ_UART2_RX"
+ default 10
+config IRQ_UART2_TX
+ int "IRQ_UART2_TX"
+ default 10
+config IRQ_TWI0
+ int "IRQ_TWI0"
+ default 11
+config IRQ_TWI1
+ int "IRQ_TWI1"
+ default 11
+config IRQ_CAN_RX
+ int "IRQ_CAN_RX"
+ default 11
+config IRQ_CAN_TX
+ int "IRQ_CAN_TX"
+ default 11
+config IRQ_MEM1_DMA0
+ int "IRQ_MEM1_DMA0"
+ default 13
+config IRQ_MEM1_DMA1
+ int "IRQ_MEM1_DMA1"
+ default 13
+
+ help
+ Enter the priority numbers between 7-13 ONLY. Others are Reserved.
+ This applies to all the above. It is not recommended to assign the
+ highest priority number 7 to UART or any other device.
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf538/Makefile b/arch/blackfin/mach-bf538/Makefile
new file mode 100644
index 000000000000..8cd2719684db
--- /dev/null
+++ b/arch/blackfin/mach-bf538/Makefile
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf538/Makefile
+#
+
+obj-y := ints-priority.o dma.o
diff --git a/arch/blackfin/mach-bf538/boards/Kconfig b/arch/blackfin/mach-bf538/boards/Kconfig
new file mode 100644
index 000000000000..215249ba58bb
--- /dev/null
+++ b/arch/blackfin/mach-bf538/boards/Kconfig
@@ -0,0 +1,12 @@
+choice
+ prompt "System type"
+ default BFIN538_EZKIT
+ help
+ Select your board!
+
+config BFIN538_EZKIT
+ bool "BF538-EZKIT"
+ help
+ BF538-EZKIT-LITE board support.
+
+endchoice
diff --git a/arch/blackfin/mach-bf538/boards/Makefile b/arch/blackfin/mach-bf538/boards/Makefile
new file mode 100644
index 000000000000..6143b320d585
--- /dev/null
+++ b/arch/blackfin/mach-bf538/boards/Makefile
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf538/boards/Makefile
+#
+
+obj-$(CONFIG_BFIN538_EZKIT) += ezkit.o
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
new file mode 100644
index 000000000000..e37cb9378884
--- /dev/null
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -0,0 +1,606 @@
+/*
+ * File: arch/blackfin/mach-bf538/boards/ezkit.c
+ * Based on: arch/blackfin/mach-bf537/boards/ezkit.c
+ * Author: Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2005 National ICT Australia (NICTA)
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/bfin5xx_spi.h>
+#include <asm/dma.h>
+#include <asm/gpio.h>
+#include <asm/nand.h>
+#include <asm/portmux.h>
+#include <asm/dpmc.h>
+#include <linux/input.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+const char bfin_board_name[] = "ADI BF538-EZKIT";
+
+/*
+ * Driver needs to know address, irq and flag pin.
+ */
+
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+ {
+ .start = 0xFFC02100,
+ .end = 0xFFC021FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart_resources),
+ .resource = bfin_uart_resources,
+};
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir1_device = {
+ .name = "bfin_sir",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
+};
+#endif
+#ifdef CONFIG_BFIN_SIR2
+static struct resource bfin_sir2_resources[] = {
+ {
+ .start = 0xFFC02100,
+ .end = 0xFFC021FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART2_RX,
+ .end = IRQ_UART2_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART2_RX,
+ .end = CH_UART2_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir2_device = {
+ .name = "bfin_sir",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(bfin_sir2_resources),
+ .resource = bfin_sir2_resources,
+};
+#endif
+#endif
+
+/*
+ * USB-LAN EzExtender board
+ * Driver needs to know address, irq and flag pin.
+ */
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+static struct resource smc91x_resources[] = {
+ {
+ .name = "smc91x-regs",
+ .start = 0x20310300,
+ .end = 0x20310300 + 16,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PF0,
+ .end = IRQ_PF0,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+ },
+};
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+/* all SPI peripherals info goes here */
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+/* SPI flash chip (m25p16) */
+static struct mtd_partition bfin_spi_flash_partitions[] = {
+ {
+ .name = "bootloader(spi)",
+ .size = 0x00040000,
+ .offset = 0,
+ .mask_flags = MTD_CAP_ROM
+ }, {
+ .name = "linux kernel(spi)",
+ .size = 0x1c0000,
+ .offset = 0x40000
+ }
+};
+
+static struct flash_platform_data bfin_spi_flash_data = {
+ .name = "m25p80",
+ .parts = bfin_spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions),
+ .type = "m25p16",
+};
+
+static struct bfin5xx_spi_chip spi_flash_chip_info = {
+ .enable_dma = 0, /* use dma transfer with this chip*/
+ .bits_per_word = 8,
+ .cs_change_per_word = 0,
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879) || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
+#include <linux/spi/ad7879.h>
+static const struct ad7879_platform_data bfin_ad7879_ts_info = {
+ .model = 7879, /* Model = AD7879 */
+ .x_plate_ohms = 620, /* 620 Ohm from the touch datasheet */
+ .pressure_max = 10000,
+ .pressure_min = 0,
+ .first_conversion_delay = 3, /* wait 512us before do a first conversion */
+ .acquisition_time = 1, /* 4us acquisition time per sample */
+ .median = 2, /* do 8 measurements */
+ .averaging = 1, /* take the average of 4 middle samples */
+ .pen_down_acc_interval = 255, /* 9.4 ms */
+ .gpio_output = 1, /* configure AUX/VBAT/GPIO as GPIO output */
+ .gpio_default = 1, /* During initialization set GPIO = HIGH */
+};
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+static struct bfin5xx_spi_chip spi_ad7879_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 16,
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+#include <asm/bfin-lq035q1.h>
+
+static struct bfin_lq035q1fb_disp_info bfin_lq035q1_data = {
+ .mode = LQ035_NORM | LQ035_RGB | LQ035_RL | LQ035_TB,
+ .use_bl = 0, /* let something else control the LCD Blacklight */
+ .gpio_bl = GPIO_PF7,
+};
+
+static struct resource bfin_lq035q1_resources[] = {
+ {
+ .start = IRQ_PPI_ERROR,
+ .end = IRQ_PPI_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device bfin_lq035q1_device = {
+ .name = "bfin-lq035q1",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(bfin_lq035q1_resources),
+ .resource = bfin_lq035q1_resources,
+ .dev = {
+ .platform_data = &bfin_lq035q1_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+static struct bfin5xx_spi_chip spidev_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+static struct bfin5xx_spi_chip lq035q1_spi_chip_info = {
+ .enable_dma = 0,
+ .bits_per_word = 8,
+};
+#endif
+
+static struct spi_board_info bf538_spi_board_info[] __initdata = {
+#if defined(CONFIG_MTD_M25P80) \
+ || defined(CONFIG_MTD_M25P80_MODULE)
+ {
+ /* the modalias must be the same as spi device driver name */
+ .modalias = "m25p80", /* Name of spi_driver for this device */
+ .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0, /* Framework bus number */
+ .chip_select = 1, /* SPI_SSEL1*/
+ .platform_data = &bfin_spi_flash_data,
+ .controller_data = &spi_flash_chip_info,
+ .mode = SPI_MODE_3,
+ },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
+ {
+ .modalias = "ad7879",
+ .platform_data = &bfin_ad7879_ts_info,
+ .irq = IRQ_PF3,
+ .max_speed_hz = 5000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spi_ad7879_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+ {
+ .modalias = "bfin-lq035q1-spi",
+ .max_speed_hz = 20000000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 2,
+ .controller_data = &lq035q1_spi_chip_info,
+ .mode = SPI_CPHA | SPI_CPOL,
+ },
+#endif
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 0,
+ .chip_select = 1,
+ .controller_data = &spidev_chip_info,
+ },
+#endif
+};
+
+/* SPI (0) */
+static struct resource bfin_spi0_resource[] = {
+ [0] = {
+ .start = SPI0_REGBASE,
+ .end = SPI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI0,
+ .end = CH_SPI0,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+/* SPI (1) */
+static struct resource bfin_spi1_resource[] = {
+ [0] = {
+ .start = SPI1_REGBASE,
+ .end = SPI1_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI1,
+ .end = CH_SPI1,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+/* SPI (2) */
+static struct resource bfin_spi2_resource[] = {
+ [0] = {
+ .start = SPI2_REGBASE,
+ .end = SPI2_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = CH_SPI2,
+ .end = CH_SPI2,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+/* SPI controller data */
+static struct bfin5xx_spi_master bf538_spi_master_info0 = {
+ .num_chipselect = 8,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+ .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
+};
+
+static struct platform_device bf538_spi_master0 = {
+ .name = "bfin-spi",
+ .id = 0, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi0_resource),
+ .resource = bfin_spi0_resource,
+ .dev = {
+ .platform_data = &bf538_spi_master_info0, /* Passed to driver */
+ },
+};
+
+static struct bfin5xx_spi_master bf538_spi_master_info1 = {
+ .num_chipselect = 8,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+ .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
+};
+
+static struct platform_device bf538_spi_master1 = {
+ .name = "bfin-spi",
+ .id = 1, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi1_resource),
+ .resource = bfin_spi1_resource,
+ .dev = {
+ .platform_data = &bf538_spi_master_info1, /* Passed to driver */
+ },
+};
+
+static struct bfin5xx_spi_master bf538_spi_master_info2 = {
+ .num_chipselect = 8,
+ .enable_dma = 1, /* master has the ability to do dma transfer */
+ .pin_req = {P_SPI2_SCK, P_SPI2_MISO, P_SPI2_MOSI, 0},
+};
+
+static struct platform_device bf538_spi_master2 = {
+ .name = "bfin-spi",
+ .id = 2, /* Bus number */
+ .num_resources = ARRAY_SIZE(bfin_spi2_resource),
+ .resource = bfin_spi2_resource,
+ .dev = {
+ .platform_data = &bf538_spi_master_info2, /* Passed to driver */
+ },
+};
+
+#endif /* spi master and devices */
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+static struct resource bfin_twi0_resource[] = {
+ [0] = {
+ .start = TWI0_REGBASE,
+ .end = TWI0_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI0,
+ .end = IRQ_TWI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi0_device = {
+ .name = "i2c-bfin-twi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_twi0_resource),
+ .resource = bfin_twi0_resource,
+};
+
+#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
+static struct resource bfin_twi1_resource[] = {
+ [0] = {
+ .start = TWI1_REGBASE,
+ .end = TWI1_REGBASE + 0xFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_TWI1,
+ .end = IRQ_TWI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c_bfin_twi1_device = {
+ .name = "i2c-bfin-twi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_twi1_resource),
+ .resource = bfin_twi1_resource,
+};
+#endif
+#endif
+
+static struct resource bfin_gpios_resources = {
+ .start = 0,
+ .end = MAX_BLACKFIN_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+ .name = "simple-gpio",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &bfin_gpios_resources,
+};
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button bfin_gpio_keys_table[] = {
+ {BTN_0, GPIO_PC7, 1, "gpio-keys: BTN0"},
+};
+
+static struct gpio_keys_platform_data bfin_gpio_keys_data = {
+ .buttons = bfin_gpio_keys_table,
+ .nbuttons = ARRAY_SIZE(bfin_gpio_keys_table),
+};
+
+static struct platform_device bfin_device_gpiokeys = {
+ .name = "gpio-keys",
+ .dev = {
+ .platform_data = &bfin_gpio_keys_data,
+ },
+};
+#endif
+
+static const unsigned int cclk_vlev_datasheet[] =
+{
+/*
+ * Internal VLEV BF538SBBC1533
+ ****temporarily using these values until data sheet is updated
+ */
+ VRPAIR(VLEV_100, 150000000),
+ VRPAIR(VLEV_100, 250000000),
+ VRPAIR(VLEV_110, 276000000),
+ VRPAIR(VLEV_115, 301000000),
+ VRPAIR(VLEV_120, 525000000),
+ VRPAIR(VLEV_125, 550000000),
+ VRPAIR(VLEV_130, 600000000),
+};
+
+static struct bfin_dpmc_platform_data bfin_dmpc_vreg_data = {
+ .tuple_tab = cclk_vlev_datasheet,
+ .tabsize = ARRAY_SIZE(cclk_vlev_datasheet),
+ .vr_settling_time = 25 /* us */,
+};
+
+static struct platform_device bfin_dpmc = {
+ .name = "bfin dpmc",
+ .dev = {
+ .platform_data = &bfin_dmpc_vreg_data,
+ },
+};
+
+static struct platform_device *cm_bf538_devices[] __initdata = {
+
+ &bfin_dpmc,
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+ &bfin_uart_device,
+#endif
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ &bf538_spi_master0,
+ &bf538_spi_master1,
+ &bf538_spi_master2,
+#endif
+
+#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
+ &i2c_bfin_twi0_device,
+ &i2c_bfin_twi1_device,
+#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
+#ifdef CONFIG_BFIN_SIR2
+ &bfin_sir2_device,
+#endif
+#endif
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+ &smc91x_device,
+#endif
+
+#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
+ &bfin_lq035q1_device,
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+ &bfin_device_gpiokeys,
+#endif
+
+ &bfin_gpios_device,
+};
+
+static int __init ezkit_init(void)
+{
+ printk(KERN_INFO "%s(): registering device resources\n", __func__);
+ platform_add_devices(cm_bf538_devices, ARRAY_SIZE(cm_bf538_devices));
+
+#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
+ spi_register_board_info(bf538_spi_board_info,
+ ARRAY_SIZE(bf538_spi_board_info));
+#endif
+
+ return 0;
+}
+
+arch_initcall(ezkit_init);
diff --git a/arch/blackfin/mach-bf538/dma.c b/arch/blackfin/mach-bf538/dma.c
new file mode 100644
index 000000000000..d6837fbf94ea
--- /dev/null
+++ b/arch/blackfin/mach-bf538/dma.c
@@ -0,0 +1,161 @@
+/*
+ * File: arch/blackfin/mach-bf538/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/module.h>
+
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA11_NEXT_DESC_PTR,
+ (struct dma_register *) DMA12_NEXT_DESC_PTR,
+ (struct dma_register *) DMA13_NEXT_DESC_PTR,
+ (struct dma_register *) DMA14_NEXT_DESC_PTR,
+ (struct dma_register *) DMA15_NEXT_DESC_PTR,
+ (struct dma_register *) DMA16_NEXT_DESC_PTR,
+ (struct dma_register *) DMA17_NEXT_DESC_PTR,
+ (struct dma_register *) DMA18_NEXT_DESC_PTR,
+ (struct dma_register *) DMA19_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA0_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA0_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA0_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA0_S1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
+};
+EXPORT_SYMBOL(dma_io_base_addr);
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI:
+ ret_irq = IRQ_PPI;
+ break;
+
+ case CH_UART0_RX:
+ ret_irq = IRQ_UART0_RX;
+ break;
+
+ case CH_UART0_TX:
+ ret_irq = IRQ_UART0_TX;
+ break;
+
+ case CH_UART1_RX:
+ ret_irq = IRQ_UART1_RX;
+ break;
+
+ case CH_UART1_TX:
+ ret_irq = IRQ_UART1_TX;
+ break;
+
+ case CH_UART2_RX:
+ ret_irq = IRQ_UART2_RX;
+ break;
+
+ case CH_UART2_TX:
+ ret_irq = IRQ_UART2_TX;
+ break;
+
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+
+ case CH_SPORT2_RX:
+ ret_irq = IRQ_SPORT2_RX;
+ break;
+
+ case CH_SPORT2_TX:
+ ret_irq = IRQ_SPORT2_TX;
+ break;
+
+ case CH_SPORT3_RX:
+ ret_irq = IRQ_SPORT3_RX;
+ break;
+
+ case CH_SPORT3_TX:
+ ret_irq = IRQ_SPORT3_TX;
+ break;
+
+ case CH_SPI0:
+ ret_irq = IRQ_SPI0;
+ break;
+
+ case CH_SPI1:
+ ret_irq = IRQ_SPI1;
+ break;
+
+ case CH_SPI2:
+ ret_irq = IRQ_SPI2;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM0_DMA0;
+ break;
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM0_DMA1;
+ break;
+ case CH_MEM_STREAM2_SRC:
+ case CH_MEM_STREAM2_DEST:
+ ret_irq = IRQ_MEM1_DMA0;
+ break;
+ case CH_MEM_STREAM3_SRC:
+ case CH_MEM_STREAM3_DEST:
+ ret_irq = IRQ_MEM1_DMA1;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf538/include/mach/anomaly.h b/arch/blackfin/mach-bf538/include/mach/anomaly.h
new file mode 100644
index 000000000000..e130b4f8a05d
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/anomaly.h
@@ -0,0 +1,132 @@
+/*
+ * File: include/asm-blackfin/mach-bf538/anomaly.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+/* This file shoule be up to date with:
+ * - Revision G, 09/18/2008; ADSP-BF538/BF538F Blackfin Processor Anomaly List
+ * - Revision L, 09/18/2008; ADSP-BF539/BF539F Blackfin Processor Anomaly List
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+
+#if __SILICON_REVISION__ < 4
+# error will not work on BF538 silicon version 0.0, 0.1, 0.2, or 0.3
+#endif
+
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
+#define ANOMALY_05000074 (1)
+/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
+#define ANOMALY_05000119 (1)
+/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
+#define ANOMALY_05000122 (1)
+/* PPI Data Lengths between 8 and 16 Do Not Zero Out Upper Bits */
+#define ANOMALY_05000166 (1)
+/* PPI_COUNT Cannot Be Programmed to 0 in General Purpose TX or RX Modes */
+#define ANOMALY_05000179 (1)
+/* PPI_DELAY Not Functional in PPI Modes with 0 Frame Syncs */
+#define ANOMALY_05000180 (1)
+/* False I/O Pin Interrupts on Edge-Sensitive Inputs When Polarity Setting Is Changed */
+#define ANOMALY_05000193 (1)
+/* Current DMA Address Shows Wrong Value During Carry Fix */
+#define ANOMALY_05000199 (__SILICON_REVISION__ < 4)
+/* NMI Event at Boot Time Results in Unpredictable State */
+#define ANOMALY_05000219 (1)
+/* SPI Slave Boot Mode Modifies Registers from Reset Value */
+#define ANOMALY_05000229 (1)
+/* PPI_FS3 Is Not Driven in 2 or 3 Internal Frame Sync Transmit Modes */
+#define ANOMALY_05000233 (1)
+/* If i-cache is on, CSYNC/SSYNC/IDLE around Change of Control causes failures */
+#define ANOMALY_05000244 (__SILICON_REVISION__ < 3)
+/* Spurious Hardware Error from an Access in the Shadow of a Conditional Branch */
+#define ANOMALY_05000245 (1)
+/* Maximum External Clock Speed for Timers */
+#define ANOMALY_05000253 (1)
+/* DCPLB_FAULT_ADDR MMR register may be corrupted */
+#define ANOMALY_05000261 (__SILICON_REVISION__ < 3)
+/* High I/O Activity Causes Output Voltage of Internal Voltage Regulator (Vddint) to Decrease */
+#define ANOMALY_05000270 (__SILICON_REVISION__ < 4)
+/* Certain Data Cache Writethrough Modes Fail for Vddint <= 0.9V */
+#define ANOMALY_05000272 (1)
+/* Writes to Synchronous SDRAM Memory May Be Lost */
+#define ANOMALY_05000273 (__SILICON_REVISION__ < 4)
+/* Writes to an I/O Data Register One SCLK Cycle after an Edge Is Detected May Clear Interrupt */
+#define ANOMALY_05000277 (__SILICON_REVISION__ < 4)
+/* Disabling Peripherals with DMA Running May Cause DMA System Instability */
+#define ANOMALY_05000278 (__SILICON_REVISION__ < 4)
+/* False Hardware Error Exception when ISR Context Is Not Restored */
+#define ANOMALY_05000281 (__SILICON_REVISION__ < 4)
+/* Memory DMA Corruption with 32-Bit Data and Traffic Control */
+#define ANOMALY_05000282 (__SILICON_REVISION__ < 4)
+/* System MMR Write Is Stalled Indefinitely when Killed in a Particular Stage */
+#define ANOMALY_05000283 (__SILICON_REVISION__ < 4)
+/* SPORTs May Receive Bad Data If FIFOs Fill Up */
+#define ANOMALY_05000288 (__SILICON_REVISION__ < 4)
+/* Reads from CAN Mailbox and Acceptance Mask Area Can Fail */
+#define ANOMALY_05000291 (__SILICON_REVISION__ < 4)
+/* Hibernate Leakage Current Is Higher Than Specified */
+#define ANOMALY_05000293 (__SILICON_REVISION__ < 4)
+/* Timer Pin Limitations for PPI TX Modes with External Frame Syncs */
+#define ANOMALY_05000294 (1)
+/* Memory-To-Memory DMA Source/Destination Descriptors Must Be in Same Memory Space */
+#define ANOMALY_05000301 (__SILICON_REVISION__ < 4)
+/* SSYNCs After Writes To CAN/DMA MMR Registers Are Not Always Handled Correctly */
+#define ANOMALY_05000304 (__SILICON_REVISION__ < 4)
+/* SCKELOW Bit Does Not Maintain State Through Hibernate */
+#define ANOMALY_05000307 (__SILICON_REVISION__ < 4)
+/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
+#define ANOMALY_05000310 (1)
+/* Errors when SSYNC, CSYNC, or Loads to LT, LB and LC Registers Are Interrupted */
+#define ANOMALY_05000312 (__SILICON_REVISION__ < 5)
+/* PPI Is Level-Sensitive on First Transfer */
+#define ANOMALY_05000313 (__SILICON_REVISION__ < 4)
+/* Killed System MMR Write Completes Erroneously on Next System MMR Access */
+#define ANOMALY_05000315 (__SILICON_REVISION__ < 4)
+/* PFx Glitch on Write to FIO_FLAG_D or FIO_FLAG_T */
+#define ANOMALY_05000318 (__SILICON_REVISION__ < 4)
+/* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
+#define ANOMALY_05000355 (__SILICON_REVISION__ < 5)
+/* Serial Port (SPORT) Multichannel Transmit Failure when Channel 0 Is Disabled */
+#define ANOMALY_05000357 (__SILICON_REVISION__ < 5)
+/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
+#define ANOMALY_05000366 (1)
+/* Possible RETS Register Corruption when Subroutine Is under 5 Cycles in Duration */
+#define ANOMALY_05000371 (__SILICON_REVISION__ < 5)
+/* Entering Hibernate State with Peripheral Wakeups Enabled Draws Excess Current */
+#define ANOMALY_05000374 (__SILICON_REVISION__ == 4)
+/* New Feature: Open-Drain GPIO Outputs on PC1 and PC4 (Not Available on Older Silicon) */
+#define ANOMALY_05000375 (__SILICON_REVISION__ < 4)
+/* SSYNC Stalls Processor when Executed from Non-Cacheable Memory */
+#define ANOMALY_05000402 (__SILICON_REVISION__ < 4)
+/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
+#define ANOMALY_05000403 (1)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
+/* Multichannel SPORT Channel Misalignment Under Specific Configuration */
+#define ANOMALY_05000425 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* Specific GPIO Pins May Change State when Entering Hibernate */
+#define ANOMALY_05000436 (__SILICON_REVISION__ > 3)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
+
+/* Anomalies that don't exist on this proc */
+#define ANOMALY_05000158 (0)
+#define ANOMALY_05000198 (0)
+#define ANOMALY_05000230 (0)
+#define ANOMALY_05000263 (0)
+#define ANOMALY_05000311 (0)
+#define ANOMALY_05000323 (0)
+#define ANOMALY_05000353 (1)
+#define ANOMALY_05000363 (0)
+#define ANOMALY_05000386 (1)
+#define ANOMALY_05000412 (0)
+#define ANOMALY_05000432 (0)
+#define ANOMALY_05000435 (0)
+
+#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/bf538.h b/arch/blackfin/mach-bf538/include/mach/bf538.h
new file mode 100644
index 000000000000..9c8abb307908
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/bf538.h
@@ -0,0 +1,124 @@
+/*
+ * File: include/asm-blackfin/mach-bf538/bf538.h
+ * Based on: include/asm-blackfin/mach-bf537/bf537.h
+ * Author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * Created:
+ * Description: SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF527
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __MACH_BF538_H__
+#define __MACH_BF538_H__
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15 0x8000
+#define IMASK_IVG14 0x4000
+#define IMASK_IVG13 0x2000
+#define IMASK_IVG12 0x1000
+
+#define IMASK_IVG11 0x0800
+#define IMASK_IVG10 0x0400
+#define IMASK_IVG9 0x0200
+#define IMASK_IVG8 0x0100
+
+#define IMASK_IVG7 0x0080
+#define IMASK_IVGTMR 0x0040
+#define IMASK_IVGHW 0x0020
+
+/***************************/
+
+#define BFIN_DSUBBANKS 4
+#define BFIN_DWAYS 2
+#define BFIN_DLINES 64
+#define BFIN_ISUBBANKS 4
+#define BFIN_IWAYS 4
+#define BFIN_ILINES 32
+
+#define WAY0_L 0x1
+#define WAY1_L 0x2
+#define WAY01_L 0x3
+#define WAY2_L 0x4
+#define WAY02_L 0x5
+#define WAY12_L 0x6
+#define WAY012_L 0x7
+
+#define WAY3_L 0x8
+#define WAY03_L 0x9
+#define WAY13_L 0xA
+#define WAY013_L 0xB
+
+#define WAY32_L 0xC
+#define WAY320_L 0xD
+#define WAY321_L 0xE
+#define WAYALL_L 0xF
+
+#define DMC_ENABLE (2<<2) /*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+#ifdef CONFIG_C_CDPRIO
+#define V_CDPRIO 0x100
+#else
+#define V_CDPRIO 0x0
+#endif
+
+#define AMGCTLVAL (V_AMBEN | V_AMCKEN | V_CDPRIO)
+
+#ifdef CONFIG_BF538
+#define CPU "BF538"
+#define CPUID 0x27C4
+#endif
+#ifdef CONFIG_BF539
+#define CPU "BF539"
+#define CPUID 0x27C4 /* FXIME:? */
+#endif
+
+#ifndef CPU
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
+#endif
+
+#endif /* __MACH_BF538_H__ */
diff --git a/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
new file mode 100644
index 000000000000..40503b6b89a3
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
@@ -0,0 +1,183 @@
+/*
+ * file: include/asm-blackfin/mach-bf538/bfin_serial_5xx.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ * blackfin serial driver header files
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#include <linux/serial.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER))
+#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR))
+#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_THR), v)
+#define UART_PUT_DLL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLL), v)
+#define UART_PUT_IER(uart, v) bfin_write16(((uart)->port.membase + OFFSET_IER), v)
+#define UART_SET_IER(uart, v) UART_PUT_IER(uart, UART_GET_IER(uart) | (v))
+#define UART_CLEAR_IER(uart, v) UART_PUT_IER(uart, UART_GET_IER(uart) & ~(v))
+#define UART_PUT_DLH(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLH), v)
+#define UART_PUT_LCR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_LCR), v)
+#define UART_PUT_GCTL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_GCTL), v)
+
+#define UART_SET_DLAB(uart) do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
+#define UART_CLEAR_DLAB(uart) do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
+
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
+#define UART_SET_RTS(x) gpio_set_value(x->rts_pin, 1)
+#define UART_CLEAR_RTS(x) gpio_set_value(x->rts_pin, 0)
+#define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
+#define UART_DISABLE_INTS(x) UART_PUT_IER(x, 0)
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+# define CONFIG_SERIAL_BFIN_CTSRTS
+
+# ifndef CONFIG_UART0_CTS_PIN
+# define CONFIG_UART0_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART0_RTS_PIN
+# define CONFIG_UART0_RTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_CTS_PIN
+# define CONFIG_UART1_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_RTS_PIN
+# define CONFIG_UART1_RTS_PIN -1
+# endif
+#endif
+
+#define BFIN_UART_TX_FIFO_SIZE 2
+
+/*
+ * The pin configuration is different from schematic
+ */
+struct bfin_serial_port {
+ struct uart_port port;
+ unsigned int old_status;
+ unsigned int lsr;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ int tx_done;
+ int tx_count;
+ struct circ_buf rx_dma_buf;
+ struct timer_list rx_dma_timer;
+ int rx_dma_nrows;
+ unsigned int tx_dma_channel;
+ unsigned int rx_dma_channel;
+ struct work_struct tx_dma_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ struct timer_list cts_timer;
+ int cts_pin;
+ int rts_pin;
+#endif
+};
+
+/* The hardware clears the LSR bits upon read, so we need to cache
+ * some of the more fun bits in software so they don't get lost
+ * when checking the LSR in other code paths (TX).
+ */
+static inline unsigned int UART_GET_LSR(struct bfin_serial_port *uart)
+{
+ unsigned int lsr = bfin_read16(uart->port.membase + OFFSET_LSR);
+ uart->lsr |= (lsr & (BI|FE|PE|OE));
+ return lsr | uart->lsr;
+}
+
+static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart)
+{
+ uart->lsr = 0;
+ bfin_write16(uart->port.membase + OFFSET_LSR, -1);
+}
+
+struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ unsigned int uart_tx_dma_channel;
+ unsigned int uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ int uart_cts_pin;
+ int uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ 0xFFC00400,
+ IRQ_UART0_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART0_TX,
+ CH_UART0_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+ CONFIG_UART0_CTS_PIN,
+ CONFIG_UART0_RTS_PIN,
+#endif
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ 0xFFC02000,
+ IRQ_UART1_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART1_TX,
+ CH_UART1_RX,
+#endif
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ CONFIG_UART1_CTS_PIN,
+ CONFIG_UART1_RTS_PIN,
+#endif
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+ {
+ 0xFFC02100,
+ IRQ_UART2_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART2_TX,
+ CH_UART2_RX,
+#endif
+#ifdef CONFIG_BFIN_UART2_CTSRTS
+ CONFIG_UART2_CTS_PIN,
+ CONFIG_UART2_RTS_PIN,
+#endif
+ },
+#endif
+};
+
+#define DRIVER_NAME "bfin-uart"
diff --git a/arch/blackfin/mach-bf538/include/mach/blackfin.h b/arch/blackfin/mach-bf538/include/mach/blackfin.h
new file mode 100644
index 000000000000..ea25371a922b
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/blackfin.h
@@ -0,0 +1,101 @@
+/*
+ * File: include/asm-blackfin/mach-bf538/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF538_FAMILY
+
+#include "bf538.h"
+#include "mem_map.h"
+#include "defBF539.h"
+#include "anomaly.h"
+
+
+#if !defined(__ASSEMBLY__)
+#include "cdefBF538.h"
+
+#if defined(CONFIG_BF539)
+#include "cdefBF539.h"
+#endif
+#endif
+
+/* UART_IIR Register */
+#define STATUS(x) ((x << 1) & 0x06)
+#define STATUS_P1 0x02
+#define STATUS_P0 0x01
+
+#define BFIN_UART_NR_PORTS 3
+
+#define OFFSET_THR 0x00 /* Transmit Holding register */
+#define OFFSET_RBR 0x00 /* Receive Buffer register */
+#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+#define OFFSET_IER 0x04 /* Interrupt Enable Register */
+#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+#define OFFSET_IIR 0x08 /* Interrupt Identification Register */
+#define OFFSET_LCR 0x0C /* Line Control Register */
+#define OFFSET_MCR 0x10 /* Modem Control Register */
+#define OFFSET_LSR 0x14 /* Line Status Register */
+#define OFFSET_MSR 0x18 /* Modem Status Register */
+#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+#define OFFSET_GCTL 0x24 /* Global Control Register */
+
+
+#define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA0_D0_IRQ_STATUS
+#define bfin_write_MDMA_D0_START_ADDR bfin_write_MDMA0_D0_START_ADDR
+#define bfin_write_MDMA_S0_START_ADDR bfin_write_MDMA0_S0_START_ADDR
+#define bfin_write_MDMA_D0_X_COUNT bfin_write_MDMA0_D0_X_COUNT
+#define bfin_write_MDMA_S0_X_COUNT bfin_write_MDMA0_S0_X_COUNT
+#define bfin_write_MDMA_D0_Y_COUNT bfin_write_MDMA0_D0_Y_COUNT
+#define bfin_write_MDMA_S0_Y_COUNT bfin_write_MDMA0_S0_Y_COUNT
+#define bfin_write_MDMA_D0_X_MODIFY bfin_write_MDMA0_D0_X_MODIFY
+#define bfin_write_MDMA_S0_X_MODIFY bfin_write_MDMA0_S0_X_MODIFY
+#define bfin_write_MDMA_D0_Y_MODIFY bfin_write_MDMA0_D0_Y_MODIFY
+#define bfin_write_MDMA_S0_Y_MODIFY bfin_write_MDMA0_S0_Y_MODIFY
+#define bfin_write_MDMA_S0_CONFIG bfin_write_MDMA0_S0_CONFIG
+#define bfin_write_MDMA_D0_CONFIG bfin_write_MDMA0_D0_CONFIG
+#define bfin_read_MDMA_S0_CONFIG bfin_read_MDMA0_S0_CONFIG
+#define bfin_read_MDMA_D0_IRQ_STATUS bfin_read_MDMA0_D0_IRQ_STATUS
+#define bfin_write_MDMA_S0_IRQ_STATUS bfin_write_MDMA0_S0_IRQ_STATUS
+
+
+/* DPMC*/
+#define bfin_read_STOPCK_OFF() bfin_read_STOPCK()
+#define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val)
+#define STOPCK_OFF STOPCK
+
+/* PLL_DIV Masks */
+#define CCLK_DIV1 CSEL_DIV1 /* CCLK = VCO / 1 */
+#define CCLK_DIV2 CSEL_DIV2 /* CCLK = VCO / 2 */
+#define CCLK_DIV4 CSEL_DIV4 /* CCLK = VCO / 4 */
+#define CCLK_DIV8 CSEL_DIV8 /* CCLK = VCO / 8 */
+
+#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/cdefBF538.h b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
new file mode 100644
index 000000000000..241725bc6988
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/cdefBF538.h
@@ -0,0 +1,2108 @@
+/*
+ * File: include/asm-blackfin/mach-bf538/cdefBF538.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _CDEF_BF538_H
+#define _CDEF_BF538_H
+
+#include <asm/blackfin.h>
+
+/*include all Core registers and bit definitions*/
+#include "defBF539.h"
+
+/*include core specific register pointer definitions*/
+#include <asm/cdef_LPBlackfin.h>
+
+#define bfin_writePTR(addr, val) bfin_write32(addr, val)
+
+#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
+#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
+#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
+#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
+#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
+#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
+#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
+#define bfin_write_PLL_LOCKCNT(val) bfin_write16(PLL_LOCKCNT, val)
+#define bfin_read_CHIPID() bfin_read32(CHIPID)
+#define bfin_write_CHIPID(val) bfin_write32(CHIPID, val)
+#define bfin_read_SWRST() bfin_read16(SWRST)
+#define bfin_write_SWRST(val) bfin_write16(SWRST, val)
+#define bfin_read_SYSCR() bfin_read16(SYSCR)
+#define bfin_write_SYSCR(val) bfin_write16(SYSCR, val)
+#define bfin_read_SIC_RVECT() bfin_readPTR(SIC_RVECT)
+#define bfin_write_SIC_RVECT(val) bfin_writePTR(SIC_RVECT, val)
+#define bfin_read_SIC_IMASK0() bfin_read32(SIC_IMASK0)
+#define bfin_write_SIC_IMASK0(val) bfin_write32(SIC_IMASK0, val)
+#define bfin_read_SIC_IMASK1() bfin_read32(SIC_IMASK1)
+#define bfin_write_SIC_IMASK1(val) bfin_write32(SIC_IMASK1, val)
+#define bfin_read_SIC_IMASK(x) bfin_read32(SIC_IMASK0 + x * (SIC_IMASK1 - SIC_IMASK0))
+#define bfin_write_SIC_IMASK(x, val) bfin_write32(SIC_IMASK0 + x * (SIC_IMASK1 - SIC_IMASK0), val)
+#define bfin_read_SIC_ISR0() bfin_read32(SIC_ISR0)
+#define bfin_write_SIC_ISR0(val) bfin_write32(SIC_ISR0, val)
+#define bfin_read_SIC_ISR1() bfin_read32(SIC_ISR1)
+#define bfin_write_SIC_ISR1(val) bfin_write32(SIC_ISR1, val)
+#define bfin_read_SIC_ISR(x) bfin_read32(SIC_ISR0 + x * (SIC_ISR1 - SIC_ISR0))
+#define bfin_write_SIC_ISR(x, val) bfin_write32(SIC_ISR0 + x * (SIC_ISR1 - SIC_ISR0), val)
+#define bfin_read_SIC_IWR0() bfin_read32(SIC_IWR0)
+#define bfin_write_SIC_IWR0(val) bfin_write32(SIC_IWR0, val)
+#define bfin_read_SIC_IWR1() bfin_read32(SIC_IWR1)
+#define bfin_write_SIC_IWR1(val) bfin_write32(SIC_IWR1, val)
+#define bfin_read_SIC_IWR(x) bfin_read32(SIC_IWR0 + x * (SIC_IWR1 - SIC_IWR0))
+#define bfin_write_SIC_IWR(x, val) bfin_write32((SIC_IWR0 + x * (SIC_IWR1 - SIC_IWR0), val)
+#define bfin_read_SIC_IAR0() bfin_read32(SIC_IAR0)
+#define bfin_write_SIC_IAR0(val) bfin_write32(SIC_IAR0, val)
+#define bfin_read_SIC_IAR1() bfin_read32(SIC_IAR1)
+#define bfin_write_SIC_IAR1(val) bfin_write32(SIC_IAR1, val)
+#define bfin_read_SIC_IAR2() bfin_read32(SIC_IAR2)
+#define bfin_write_SIC_IAR2(val) bfin_write32(SIC_IAR2, val)
+#define bfin_read_SIC_IAR3() bfin_read32(SIC_IAR3)
+#define bfin_write_SIC_IAR3(val) bfin_write32(SIC_IAR3, val)
+#define bfin_read_SIC_IAR4() bfin_read32(SIC_IAR4)
+#define bfin_write_SIC_IAR4(val) bfin_write32(SIC_IAR4, val)
+#define bfin_read_SIC_IAR5() bfin_read32(SIC_IAR5)
+#define bfin_write_SIC_IAR5(val) bfin_write32(SIC_IAR5, val)
+#define bfin_read_SIC_IAR6() bfin_read32(SIC_IAR6)
+#define bfin_write_SIC_IAR6(val) bfin_write32(SIC_IAR6, val)
+#define bfin_read_WDOG_CTL() bfin_read16(WDOG_CTL)
+#define bfin_write_WDOG_CTL(val) bfin_write16(WDOG_CTL, val)
+#define bfin_read_WDOG_CNT() bfin_read32(WDOG_CNT)
+#define bfin_write_WDOG_CNT(val) bfin_write32(WDOG_CNT, val)
+#define bfin_read_WDOG_STAT() bfin_read32(WDOG_STAT)
+#define bfin_write_WDOG_STAT(val) bfin_write32(WDOG_STAT, val)
+#define bfin_read_RTC_STAT() bfin_read32(RTC_STAT)
+#define bfin_write_RTC_STAT(val) bfin_write32(RTC_STAT, val)
+#define bfin_read_RTC_ICTL() bfin_read16(RTC_ICTL)
+#define bfin_write_RTC_ICTL(val) bfin_write16(RTC_ICTL, val)
+#define bfin_read_RTC_ISTAT() bfin_read16(RTC_ISTAT)
+#define bfin_write_RTC_ISTAT(val) bfin_write16(RTC_ISTAT, val)
+#define bfin_read_RTC_SWCNT() bfin_read16(RTC_SWCNT)
+#define bfin_write_RTC_SWCNT(val) bfin_write16(RTC_SWCNT, val)
+#define bfin_read_RTC_ALARM() bfin_read32(RTC_ALARM)
+#define bfin_write_RTC_ALARM(val) bfin_write32(RTC_ALARM, val)
+#define bfin_read_RTC_PREN() bfin_read16(RTC_PREN)
+#define bfin_write_RTC_PREN(val) bfin_write16(RTC_PREN, val)
+#define bfin_read_UART0_THR() bfin_read16(UART0_THR)
+#define bfin_write_UART0_THR(val) bfin_write16(UART0_THR, val)
+#define bfin_read_UART0_RBR() bfin_read16(UART0_RBR)
+#define bfin_write_UART0_RBR(val) bfin_write16(UART0_RBR, val)
+#define bfin_read_UART0_DLL() bfin_read16(UART0_DLL)
+#define bfin_write_UART0_DLL(val) bfin_write16(UART0_DLL, val)
+#define bfin_read_UART0_DLH() bfin_read16(UART0_DLH)
+#define bfin_write_UART0_DLH(val) bfin_write16(UART0_DLH, val)
+#define bfin_read_UART0_IER() bfin_read16(UART0_IER)
+#define bfin_write_UART0_IER(val) bfin_write16(UART0_IER, val)
+#define bfin_read_UART0_IIR() bfin_read16(UART0_IIR)
+#define bfin_write_UART0_IIR(val) bfin_write16(UART0_IIR, val)
+#define bfin_read_UART0_LCR() bfin_read16(UART0_LCR)
+#define bfin_write_UART0_LCR(val) bfin_write16(UART0_LCR, val)
+#define bfin_read_UART0_MCR() bfin_read16(UART0_MCR)
+#define bfin_write_UART0_MCR(val) bfin_write16(UART0_MCR, val)
+#define bfin_read_UART0_LSR() bfin_read16(UART0_LSR)
+#define bfin_write_UART0_LSR(val) bfin_write16(UART0_LSR, val)
+#define bfin_read_UART0_SCR() bfin_read16(UART0_SCR)
+#define bfin_write_UART0_SCR(val) bfin_write16(UART0_SCR, val)
+#define bfin_read_UART0_GCTL() bfin_read16(UART0_GCTL)
+#define bfin_write_UART0_GCTL(val) bfin_write16(UART0_GCTL, val)
+#define bfin_read_UART1_THR() bfin_read16(UART1_THR)
+#define bfin_write_UART1_THR(val) bfin_write16(UART1_THR, val)
+#define bfin_read_UART1_RBR() bfin_read16(UART1_RBR)
+#define bfin_write_UART1_RBR(val) bfin_write16(UART1_RBR, val)
+#define bfin_read_UART1_DLL() bfin_read16(UART1_DLL)
+#define bfin_write_UART1_DLL(val) bfin_write16(UART1_DLL, val)
+#define bfin_read_UART1_DLH() bfin_read16(UART1_DLH)
+#define bfin_write_UART1_DLH(val) bfin_write16(UART1_DLH, val)
+#define bfin_read_UART1_IER() bfin_read16(UART1_IER)
+#define bfin_write_UART1_IER(val) bfin_write16(UART1_IER, val)
+#define bfin_read_UART1_IIR() bfin_read16(UART1_IIR)
+#define bfin_write_UART1_IIR(val) bfin_write16(UART1_IIR, val)
+#define bfin_read_UART1_LCR() bfin_read16(UART1_LCR)
+#define bfin_write_UART1_LCR(val) bfin_write16(UART1_LCR, val)
+#define bfin_read_UART1_MCR() bfin_read16(UART1_MCR)
+#define bfin_write_UART1_MCR(val) bfin_write16(UART1_MCR, val)
+#define bfin_read_UART1_LSR() bfin_read16(UART1_LSR)
+#define bfin_write_UART1_LSR(val) bfin_write16(UART1_LSR, val)
+#define bfin_read_UART1_SCR() bfin_read16(UART1_SCR)
+#define bfin_write_UART1_SCR(val) bfin_write16(UART1_SCR, val)
+#define bfin_read_UART1_GCTL() bfin_read16(UART1_GCTL)
+#define bfin_write_UART1_GCTL(val) bfin_write16(UART1_GCTL, val)
+#define bfin_read_UART2_THR() bfin_read16(UART2_THR)
+#define bfin_write_UART2_THR(val) bfin_write16(UART2_THR, val)
+#define bfin_read_UART2_RBR() bfin_read16(UART2_RBR)
+#define bfin_write_UART2_RBR(val) bfin_write16(UART2_RBR, val)
+#define bfin_read_UART2_DLL() bfin_read16(UART2_DLL)
+#define bfin_write_UART2_DLL(val) bfin_write16(UART2_DLL, val)
+#define bfin_read_UART2_DLH() bfin_read16(UART2_DLH)
+#define bfin_write_UART2_DLH(val) bfin_write16(UART2_DLH, val)
+#define bfin_read_UART2_IER() bfin_read16(UART2_IER)
+#define bfin_write_UART2_IER(val) bfin_write16(UART2_IER, val)
+#define bfin_read_UART2_IIR() bfin_read16(UART2_IIR)
+#define bfin_write_UART2_IIR(val) bfin_write16(UART2_IIR, val)
+#define bfin_read_UART2_LCR() bfin_read16(UART2_LCR)
+#define bfin_write_UART2_LCR(val) bfin_write16(UART2_LCR, val)
+#define bfin_read_UART2_MCR() bfin_read16(UART2_MCR)
+#define bfin_write_UART2_MCR(val) bfin_write16(UART2_MCR, val)
+#define bfin_read_UART2_LSR() bfin_read16(UART2_LSR)
+#define bfin_write_UART2_LSR(val) bfin_write16(UART2_LSR, val)
+#define bfin_read_UART2_SCR() bfin_read16(UART2_SCR)
+#define bfin_write_UART2_SCR(val) bfin_write16(UART2_SCR, val)
+#define bfin_read_UART2_GCTL() bfin_read16(UART2_GCTL)
+#define bfin_write_UART2_GCTL(val) bfin_write16(UART2_GCTL, val)
+#define bfin_read_SPI0_CTL() bfin_read16(SPI0_CTL)
+#define bfin_write_SPI0_CTL(val) bfin_write16(SPI0_CTL, val)
+#define bfin_read_SPI0_FLG() bfin_read16(SPI0_FLG)
+#define bfin_write_SPI0_FLG(val) bfin_write16(SPI0_FLG, val)
+#define bfin_read_SPI0_STAT() bfin_read16(SPI0_STAT)
+#define bfin_write_SPI0_STAT(val) bfin_write16(SPI0_STAT, val)
+#define bfin_read_SPI0_TDBR() bfin_read16(SPI0_TDBR)
+#define bfin_write_SPI0_TDBR(val) bfin_write16(SPI0_TDBR, val)
+#define bfin_read_SPI0_RDBR() bfin_read16(SPI0_RDBR)
+#define bfin_write_SPI0_RDBR(val) bfin_write16(SPI0_RDBR, val)
+#define bfin_read_SPI0_BAUD() bfin_read16(SPI0_BAUD)
+#define bfin_write_SPI0_BAUD(val) bfin_write16(SPI0_BAUD, val)
+#define bfin_read_SPI0_SHADOW() bfin_read16(SPI0_SHADOW)
+#define bfin_write_SPI0_SHADOW(val) bfin_write16(SPI0_SHADOW, val)
+#define bfin_read_SPI1_CTL() bfin_read16(SPI1_CTL)
+#define bfin_write_SPI1_CTL(val) bfin_write16(SPI1_CTL, val)
+#define bfin_read_SPI1_FLG() bfin_read16(SPI1_FLG)
+#define bfin_write_SPI1_FLG(val) bfin_write16(SPI1_FLG, val)
+#define bfin_read_SPI1_STAT() bfin_read16(SPI1_STAT)
+#define bfin_write_SPI1_STAT(val) bfin_write16(SPI1_STAT, val)
+#define bfin_read_SPI1_TDBR() bfin_read16(SPI1_TDBR)
+#define bfin_write_SPI1_TDBR(val) bfin_write16(SPI1_TDBR, val)
+#define bfin_read_SPI1_RDBR() bfin_read16(SPI1_RDBR)
+#define bfin_write_SPI1_RDBR(val) bfin_write16(SPI1_RDBR, val)
+#define bfin_read_SPI1_BAUD() bfin_read16(SPI1_BAUD)
+#define bfin_write_SPI1_BAUD(val) bfin_write16(SPI1_BAUD, val)
+#define bfin_read_SPI1_SHADOW() bfin_read16(SPI1_SHADOW)
+#define bfin_write_SPI1_SHADOW(val) bfin_write16(SPI1_SHADOW, val)
+#define bfin_read_SPI2_CTL() bfin_read16(SPI2_CTL)
+#define bfin_write_SPI2_CTL(val) bfin_write16(SPI2_CTL, val)
+#define bfin_read_SPI2_FLG() bfin_read16(SPI2_FLG)
+#define bfin_write_SPI2_FLG(val) bfin_write16(SPI2_FLG, val)
+#define bfin_read_SPI2_STAT() bfin_read16(SPI2_STAT)
+#define bfin_write_SPI2_STAT(val) bfin_write16(SPI2_STAT, val)
+#define bfin_read_SPI2_TDBR() bfin_read16(SPI2_TDBR)
+#define bfin_write_SPI2_TDBR(val) bfin_write16(SPI2_TDBR, val)
+#define bfin_read_SPI2_RDBR() bfin_read16(SPI2_RDBR)
+#define bfin_write_SPI2_RDBR(val) bfin_write16(SPI2_RDBR, val)
+#define bfin_read_SPI2_BAUD() bfin_read16(SPI2_BAUD)
+#define bfin_write_SPI2_BAUD(val) bfin_write16(SPI2_BAUD, val)
+#define bfin_read_SPI2_SHADOW() bfin_read16(SPI2_SHADOW)
+#define bfin_write_SPI2_SHADOW(val) bfin_write16(SPI2_SHADOW, val)
+#define bfin_read_TIMER0_CONFIG() bfin_read16(TIMER0_CONFIG)
+#define bfin_write_TIMER0_CONFIG(val) bfin_write16(TIMER0_CONFIG, val)
+#define bfin_read_TIMER0_COUNTER() bfin_read32(TIMER0_COUNTER)
+#define bfin_write_TIMER0_COUNTER(val) bfin_write32(TIMER0_COUNTER, val)
+#define bfin_read_TIMER0_PERIOD() bfin_read32(TIMER0_PERIOD)
+#define bfin_write_TIMER0_PERIOD(val) bfin_write32(TIMER0_PERIOD, val)
+#define bfin_read_TIMER0_WIDTH() bfin_read32(TIMER0_WIDTH)
+#define bfin_write_TIMER0_WIDTH(val) bfin_write32(TIMER0_WIDTH, val)
+#define bfin_read_TIMER1_CONFIG() bfin_read16(TIMER1_CONFIG)
+#define bfin_write_TIMER1_CONFIG(val) bfin_write16(TIMER1_CONFIG, val)
+#define bfin_read_TIMER1_COUNTER() bfin_read32(TIMER1_COUNTER)
+#define bfin_write_TIMER1_COUNTER(val) bfin_write32(TIMER1_COUNTER, val)
+#define bfin_read_TIMER1_PERIOD() bfin_read32(TIMER1_PERIOD)
+#define bfin_write_TIMER1_PERIOD(val) bfin_write32(TIMER1_PERIOD, val)
+#define bfin_read_TIMER1_WIDTH() bfin_read32(TIMER1_WIDTH)
+#define bfin_write_TIMER1_WIDTH(val) bfin_write32(TIMER1_WIDTH, val)
+#define bfin_read_TIMER2_CONFIG() bfin_read16(TIMER2_CONFIG)
+#define bfin_write_TIMER2_CONFIG(val) bfin_write16(TIMER2_CONFIG, val)
+#define bfin_read_TIMER2_COUNTER() bfin_read32(TIMER2_COUNTER)
+#define bfin_write_TIMER2_COUNTER(val) bfin_write32(TIMER2_COUNTER, val)
+#define bfin_read_TIMER2_PERIOD() bfin_read32(TIMER2_PERIOD)
+#define bfin_write_TIMER2_PERIOD(val) bfin_write32(TIMER2_PERIOD, val)
+#define bfin_read_TIMER2_WIDTH() bfin_read32(TIMER2_WIDTH)
+#define bfin_write_TIMER2_WIDTH(val) bfin_write32(TIMER2_WIDTH, val)
+#define bfin_read_TIMER_ENABLE() bfin_read16(TIMER_ENABLE)
+#define bfin_write_TIMER_ENABLE(val) bfin_write16(TIMER_ENABLE, val)
+#define bfin_read_TIMER_DISABLE() bfin_read16(TIMER_DISABLE)
+#define bfin_write_TIMER_DISABLE(val) bfin_write16(TIMER_DISABLE, val)
+#define bfin_read_TIMER_STATUS() bfin_read16(TIMER_STATUS)
+#define bfin_write_TIMER_STATUS(val) bfin_write16(TIMER_STATUS, val)
+#define bfin_read_SPORT0_TCR1() bfin_read16(SPORT0_TCR1)
+#define bfin_write_SPORT0_TCR1(val) bfin_write16(SPORT0_TCR1, val)
+#define bfin_read_SPORT0_TCR2() bfin_read16(SPORT0_TCR2)
+#define bfin_write_SPORT0_TCR2(val) bfin_write16(SPORT0_TCR2, val)
+#define bfin_read_SPORT0_TCLKDIV() bfin_read16(SPORT0_TCLKDIV)
+#define bfin_write_SPORT0_TCLKDIV(val) bfin_write16(SPORT0_TCLKDIV, val)
+#define bfin_read_SPORT0_TFSDIV() bfin_read16(SPORT0_TFSDIV)
+#define bfin_write_SPORT0_TFSDIV(val) bfin_write16(SPORT0_TFSDIV, val)
+#define bfin_read_SPORT0_TX() bfin_read32(SPORT0_TX)
+#define bfin_write_SPORT0_TX(val) bfin_write32(SPORT0_TX, val)
+#define bfin_read_SPORT0_RX() bfin_read32(SPORT0_RX)
+#define bfin_write_SPORT0_RX(val) bfin_write32(SPORT0_RX, val)
+#define bfin_read_SPORT0_RCR1() bfin_read16(SPORT0_RCR1)
+#define bfin_write_SPORT0_RCR1(val) bfin_write16(SPORT0_RCR1, val)
+#define bfin_read_SPORT0_RCR2() bfin_read16(SPORT0_RCR2)
+#define bfin_write_SPORT0_RCR2(val) bfin_write16(SPORT0_RCR2, val)
+#define bfin_read_SPORT0_RCLKDIV() bfin_read16(SPORT0_RCLKDIV)
+#define bfin_write_SPORT0_RCLKDIV(val) bfin_write16(SPORT0_RCLKDIV, val)
+#define bfin_read_SPORT0_RFSDIV() bfin_read16(SPORT0_RFSDIV)
+#define bfin_write_SPORT0_RFSDIV(val) bfin_write16(SPORT0_RFSDIV, val)
+#define bfin_read_SPORT0_STAT() bfin_read16(SPORT0_STAT)
+#define bfin_write_SPORT0_STAT(val) bfin_write16(SPORT0_STAT, val)
+#define bfin_read_SPORT0_CHNL() bfin_read16(SPORT0_CHNL)
+#define bfin_write_SPORT0_CHNL(val) bfin_write16(SPORT0_CHNL, val)
+#define bfin_read_SPORT0_MCMC1() bfin_read16(SPORT0_MCMC1)
+#define bfin_write_SPORT0_MCMC1(val) bfin_write16(SPORT0_MCMC1, val)
+#define bfin_read_SPORT0_MCMC2() bfin_read16(SPORT0_MCMC2)
+#define bfin_write_SPORT0_MCMC2(val) bfin_write16(SPORT0_MCMC2, val)
+#define bfin_read_SPORT0_MTCS0() bfin_read32(SPORT0_MTCS0)
+#define bfin_write_SPORT0_MTCS0(val) bfin_write32(SPORT0_MTCS0, val)
+#define bfin_read_SPORT0_MTCS1() bfin_read32(SPORT0_MTCS1)
+#define bfin_write_SPORT0_MTCS1(val) bfin_write32(SPORT0_MTCS1, val)
+#define bfin_read_SPORT0_MTCS2() bfin_read32(SPORT0_MTCS2)
+#define bfin_write_SPORT0_MTCS2(val) bfin_write32(SPORT0_MTCS2, val)
+#define bfin_read_SPORT0_MTCS3() bfin_read32(SPORT0_MTCS3)
+#define bfin_write_SPORT0_MTCS3(val) bfin_write32(SPORT0_MTCS3, val)
+#define bfin_read_SPORT0_MRCS0() bfin_read32(SPORT0_MRCS0)
+#define bfin_write_SPORT0_MRCS0(val) bfin_write32(SPORT0_MRCS0, val)
+#define bfin_read_SPORT0_MRCS1() bfin_read32(SPORT0_MRCS1)
+#define bfin_write_SPORT0_MRCS1(val) bfin_write32(SPORT0_MRCS1, val)
+#define bfin_read_SPORT0_MRCS2() bfin_read32(SPORT0_MRCS2)
+#define bfin_write_SPORT0_MRCS2(val) bfin_write32(SPORT0_MRCS2, val)
+#define bfin_read_SPORT0_MRCS3() bfin_read32(SPORT0_MRCS3)
+#define bfin_write_SPORT0_MRCS3(val) bfin_write32(SPORT0_MRCS3, val)
+#define bfin_read_SPORT1_TCR1() bfin_read16(SPORT1_TCR1)
+#define bfin_write_SPORT1_TCR1(val) bfin_write16(SPORT1_TCR1, val)
+#define bfin_read_SPORT1_TCR2() bfin_read16(SPORT1_TCR2)
+#define bfin_write_SPORT1_TCR2(val) bfin_write16(SPORT1_TCR2, val)
+#define bfin_read_SPORT1_TCLKDIV() bfin_read16(SPORT1_TCLKDIV)
+#define bfin_write_SPORT1_TCLKDIV(val) bfin_write16(SPORT1_TCLKDIV, val)
+#define bfin_read_SPORT1_TFSDIV() bfin_read16(SPORT1_TFSDIV)
+#define bfin_write_SPORT1_TFSDIV(val) bfin_write16(SPORT1_TFSDIV, val)
+#define bfin_read_SPORT1_TX() bfin_read32(SPORT1_TX)
+#define bfin_write_SPORT1_TX(val) bfin_write32(SPORT1_TX, val)
+#define bfin_read_SPORT1_RX() bfin_read32(SPORT1_RX)
+#define bfin_write_SPORT1_RX(val) bfin_write32(SPORT1_RX, val)
+#define bfin_read_SPORT1_RCR1() bfin_read16(SPORT1_RCR1)
+#define bfin_write_SPORT1_RCR1(val) bfin_write16(SPORT1_RCR1, val)
+#define bfin_read_SPORT1_RCR2() bfin_read16(SPORT1_RCR2)
+#define bfin_write_SPORT1_RCR2(val) bfin_write16(SPORT1_RCR2, val)
+#define bfin_read_SPORT1_RCLKDIV() bfin_read16(SPORT1_RCLKDIV)
+#define bfin_write_SPORT1_RCLKDIV(val) bfin_write16(SPORT1_RCLKDIV, val)
+#define bfin_read_SPORT1_RFSDIV() bfin_read16(SPORT1_RFSDIV)
+#define bfin_write_SPORT1_RFSDIV(val) bfin_write16(SPORT1_RFSDIV, val)
+#define bfin_read_SPORT1_STAT() bfin_read16(SPORT1_STAT)
+#define bfin_write_SPORT1_STAT(val) bfin_write16(SPORT1_STAT, val)
+#define bfin_read_SPORT1_CHNL() bfin_read16(SPORT1_CHNL)
+#define bfin_write_SPORT1_CHNL(val) bfin_write16(SPORT1_CHNL, val)
+#define bfin_read_SPORT1_MCMC1() bfin_read16(SPORT1_MCMC1)
+#define bfin_write_SPORT1_MCMC1(val) bfin_write16(SPORT1_MCMC1, val)
+#define bfin_read_SPORT1_MCMC2() bfin_read16(SPORT1_MCMC2)
+#define bfin_write_SPORT1_MCMC2(val) bfin_write16(SPORT1_MCMC2, val)
+#define bfin_read_SPORT1_MTCS0() bfin_read32(SPORT1_MTCS0)
+#define bfin_write_SPORT1_MTCS0(val) bfin_write32(SPORT1_MTCS0, val)
+#define bfin_read_SPORT1_MTCS1() bfin_read32(SPORT1_MTCS1)
+#define bfin_write_SPORT1_MTCS1(val) bfin_write32(SPORT1_MTCS1, val)
+#define bfin_read_SPORT1_MTCS2() bfin_read32(SPORT1_MTCS2)
+#define bfin_write_SPORT1_MTCS2(val) bfin_write32(SPORT1_MTCS2, val)
+#define bfin_read_SPORT1_MTCS3() bfin_read32(SPORT1_MTCS3)
+#define bfin_write_SPORT1_MTCS3(val) bfin_write32(SPORT1_MTCS3, val)
+#define bfin_read_SPORT1_MRCS0() bfin_read32(SPORT1_MRCS0)
+#define bfin_write_SPORT1_MRCS0(val) bfin_write32(SPORT1_MRCS0, val)
+#define bfin_read_SPORT1_MRCS1() bfin_read32(SPORT1_MRCS1)
+#define bfin_write_SPORT1_MRCS1(val) bfin_write32(SPORT1_MRCS1, val)
+#define bfin_read_SPORT1_MRCS2() bfin_read32(SPORT1_MRCS2)
+#define bfin_write_SPORT1_MRCS2(val) bfin_write32(SPORT1_MRCS2, val)
+#define bfin_read_SPORT1_MRCS3() bfin_read32(SPORT1_MRCS3)
+#define bfin_write_SPORT1_MRCS3(val) bfin_write32(SPORT1_MRCS3, val)
+#define bfin_read_SPORT2_TCR1() bfin_read16(SPORT2_TCR1)
+#define bfin_write_SPORT2_TCR1(val) bfin_write16(SPORT2_TCR1, val)
+#define bfin_read_SPORT2_TCR2() bfin_read16(SPORT2_TCR2)
+#define bfin_write_SPORT2_TCR2(val) bfin_write16(SPORT2_TCR2, val)
+#define bfin_read_SPORT2_TCLKDIV() bfin_read16(SPORT2_TCLKDIV)
+#define bfin_write_SPORT2_TCLKDIV(val) bfin_write16(SPORT2_TCLKDIV, val)
+#define bfin_read_SPORT2_TFSDIV() bfin_read16(SPORT2_TFSDIV)
+#define bfin_write_SPORT2_TFSDIV(val) bfin_write16(SPORT2_TFSDIV, val)
+#define bfin_read_SPORT2_TX() bfin_read32(SPORT2_TX)
+#define bfin_write_SPORT2_TX(val) bfin_write32(SPORT2_TX, val)
+#define bfin_read_SPORT2_RX() bfin_read32(SPORT2_RX)
+#define bfin_write_SPORT2_RX(val) bfin_write32(SPORT2_RX, val)
+#define bfin_read_SPORT2_RCR1() bfin_read16(SPORT2_RCR1)
+#define bfin_write_SPORT2_RCR1(val) bfin_write16(SPORT2_RCR1, val)
+#define bfin_read_SPORT2_RCR2() bfin_read16(SPORT2_RCR2)
+#define bfin_write_SPORT2_RCR2(val) bfin_write16(SPORT2_RCR2, val)
+#define bfin_read_SPORT2_RCLKDIV() bfin_read16(SPORT2_RCLKDIV)
+#define bfin_write_SPORT2_RCLKDIV(val) bfin_write16(SPORT2_RCLKDIV, val)
+#define bfin_read_SPORT2_RFSDIV() bfin_read16(SPORT2_RFSDIV)
+#define bfin_write_SPORT2_RFSDIV(val) bfin_write16(SPORT2_RFSDIV, val)
+#define bfin_read_SPORT2_STAT() bfin_read16(SPORT2_STAT)
+#define bfin_write_SPORT2_STAT(val) bfin_write16(SPORT2_STAT, val)
+#define bfin_read_SPORT2_CHNL() bfin_read16(SPORT2_CHNL)
+#define bfin_write_SPORT2_CHNL(val) bfin_write16(SPORT2_CHNL, val)
+#define bfin_read_SPORT2_MCMC1() bfin_read16(SPORT2_MCMC1)
+#define bfin_write_SPORT2_MCMC1(val) bfin_write16(SPORT2_MCMC1, val)
+#define bfin_read_SPORT2_MCMC2() bfin_read16(SPORT2_MCMC2)
+#define bfin_write_SPORT2_MCMC2(val) bfin_write16(SPORT2_MCMC2, val)
+#define bfin_read_SPORT2_MTCS0() bfin_read32(SPORT2_MTCS0)
+#define bfin_write_SPORT2_MTCS0(val) bfin_write32(SPORT2_MTCS0, val)
+#define bfin_read_SPORT2_MTCS1() bfin_read32(SPORT2_MTCS1)
+#define bfin_write_SPORT2_MTCS1(val) bfin_write32(SPORT2_MTCS1, val)
+#define bfin_read_SPORT2_MTCS2() bfin_read32(SPORT2_MTCS2)
+#define bfin_write_SPORT2_MTCS2(val) bfin_write32(SPORT2_MTCS2, val)
+#define bfin_read_SPORT2_MTCS3() bfin_read32(SPORT2_MTCS3)
+#define bfin_write_SPORT2_MTCS3(val) bfin_write32(SPORT2_MTCS3, val)
+#define bfin_read_SPORT2_MRCS0() bfin_read32(SPORT2_MRCS0)
+#define bfin_write_SPORT2_MRCS0(val) bfin_write32(SPORT2_MRCS0, val)
+#define bfin_read_SPORT2_MRCS1() bfin_read32(SPORT2_MRCS1)
+#define bfin_write_SPORT2_MRCS1(val) bfin_write32(SPORT2_MRCS1, val)
+#define bfin_read_SPORT2_MRCS2() bfin_read32(SPORT2_MRCS2)
+#define bfin_write_SPORT2_MRCS2(val) bfin_write32(SPORT2_MRCS2, val)
+#define bfin_read_SPORT2_MRCS3() bfin_read32(SPORT2_MRCS3)
+#define bfin_write_SPORT2_MRCS3(val) bfin_write32(SPORT2_MRCS3, val)
+#define bfin_read_SPORT3_TCR1() bfin_read16(SPORT3_TCR1)
+#define bfin_write_SPORT3_TCR1(val) bfin_write16(SPORT3_TCR1, val)
+#define bfin_read_SPORT3_TCR2() bfin_read16(SPORT3_TCR2)
+#define bfin_write_SPORT3_TCR2(val) bfin_write16(SPORT3_TCR2, val)
+#define bfin_read_SPORT3_TCLKDIV() bfin_read16(SPORT3_TCLKDIV)
+#define bfin_write_SPORT3_TCLKDIV(val) bfin_write16(SPORT3_TCLKDIV, val)
+#define bfin_read_SPORT3_TFSDIV() bfin_read16(SPORT3_TFSDIV)
+#define bfin_write_SPORT3_TFSDIV(val) bfin_write16(SPORT3_TFSDIV, val)
+#define bfin_read_SPORT3_TX() bfin_read32(SPORT3_TX)
+#define bfin_write_SPORT3_TX(val) bfin_write32(SPORT3_TX, val)
+#define bfin_read_SPORT3_RX() bfin_read32(SPORT3_RX)
+#define bfin_write_SPORT3_RX(val) bfin_write32(SPORT3_RX, val)
+#define bfin_read_SPORT3_RCR1() bfin_read16(SPORT3_RCR1)
+#define bfin_write_SPORT3_RCR1(val) bfin_write16(SPORT3_RCR1, val)
+#define bfin_read_SPORT3_RCR2() bfin_read16(SPORT3_RCR2)
+#define bfin_write_SPORT3_RCR2(val) bfin_write16(SPORT3_RCR2, val)
+#define bfin_read_SPORT3_RCLKDIV() bfin_read16(SPORT3_RCLKDIV)
+#define bfin_write_SPORT3_RCLKDIV(val) bfin_write16(SPORT3_RCLKDIV, val)
+#define bfin_read_SPORT3_RFSDIV() bfin_read16(SPORT3_RFSDIV)
+#define bfin_write_SPORT3_RFSDIV(val) bfin_write16(SPORT3_RFSDIV, val)
+#define bfin_read_SPORT3_STAT() bfin_read16(SPORT3_STAT)
+#define bfin_write_SPORT3_STAT(val) bfin_write16(SPORT3_STAT, val)
+#define bfin_read_SPORT3_CHNL() bfin_read16(SPORT3_CHNL)
+#define bfin_write_SPORT3_CHNL(val) bfin_write16(SPORT3_CHNL, val)
+#define bfin_read_SPORT3_MCMC1() bfin_read16(SPORT3_MCMC1)
+#define bfin_write_SPORT3_MCMC1(val) bfin_write16(SPORT3_MCMC1, val)
+#define bfin_read_SPORT3_MCMC2() bfin_read16(SPORT3_MCMC2)
+#define bfin_write_SPORT3_MCMC2(val) bfin_write16(SPORT3_MCMC2, val)
+#define bfin_read_SPORT3_MTCS0() bfin_read32(SPORT3_MTCS0)
+#define bfin_write_SPORT3_MTCS0(val) bfin_write32(SPORT3_MTCS0, val)
+#define bfin_read_SPORT3_MTCS1() bfin_read32(SPORT3_MTCS1)
+#define bfin_write_SPORT3_MTCS1(val) bfin_write32(SPORT3_MTCS1, val)
+#define bfin_read_SPORT3_MTCS2() bfin_read32(SPORT3_MTCS2)
+#define bfin_write_SPORT3_MTCS2(val) bfin_write32(SPORT3_MTCS2, val)
+#define bfin_read_SPORT3_MTCS3() bfin_read32(SPORT3_MTCS3)
+#define bfin_write_SPORT3_MTCS3(val) bfin_write32(SPORT3_MTCS3, val)
+#define bfin_read_SPORT3_MRCS0() bfin_read32(SPORT3_MRCS0)
+#define bfin_write_SPORT3_MRCS0(val) bfin_write32(SPORT3_MRCS0, val)
+#define bfin_read_SPORT3_MRCS1() bfin_read32(SPORT3_MRCS1)
+#define bfin_write_SPORT3_MRCS1(val) bfin_write32(SPORT3_MRCS1, val)
+#define bfin_read_SPORT3_MRCS2() bfin_read32(SPORT3_MRCS2)
+#define bfin_write_SPORT3_MRCS2(val) bfin_write32(SPORT3_MRCS2, val)
+#define bfin_read_SPORT3_MRCS3() bfin_read32(SPORT3_MRCS3)
+#define bfin_write_SPORT3_MRCS3(val) bfin_write32(SPORT3_MRCS3, val)
+#define bfin_read_PORTFIO() bfin_read16(PORTFIO)
+#define bfin_write_PORTFIO(val) bfin_write16(PORTFIO, val)
+#define bfin_read_PORTFIO_CLEAR() bfin_read16(PORTFIO_CLEAR)
+#define bfin_write_PORTFIO_CLEAR(val) bfin_write16(PORTFIO_CLEAR, val)
+#define bfin_read_PORTFIO_SET() bfin_read16(PORTFIO_SET)
+#define bfin_write_PORTFIO_SET(val) bfin_write16(PORTFIO_SET, val)
+#define bfin_read_PORTFIO_TOGGLE() bfin_read16(PORTFIO_TOGGLE)
+#define bfin_write_PORTFIO_TOGGLE(val) bfin_write16(PORTFIO_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKA() bfin_read16(PORTFIO_MASKA)
+#define bfin_write_PORTFIO_MASKA(val) bfin_write16(PORTFIO_MASKA, val)
+#define bfin_read_PORTFIO_MASKA_CLEAR() bfin_read16(PORTFIO_MASKA_CLEAR)
+#define bfin_write_PORTFIO_MASKA_CLEAR(val) bfin_write16(PORTFIO_MASKA_CLEAR, val)
+#define bfin_read_PORTFIO_MASKA_SET() bfin_read16(PORTFIO_MASKA_SET)
+#define bfin_write_PORTFIO_MASKA_SET(val) bfin_write16(PORTFIO_MASKA_SET, val)
+#define bfin_read_PORTFIO_MASKA_TOGGLE() bfin_read16(PORTFIO_MASKA_TOGGLE)
+#define bfin_write_PORTFIO_MASKA_TOGGLE(val) bfin_write16(PORTFIO_MASKA_TOGGLE, val)
+#define bfin_read_PORTFIO_MASKB() bfin_read16(PORTFIO_MASKB)
+#define bfin_write_PORTFIO_MASKB(val) bfin_write16(PORTFIO_MASKB, val)
+#define bfin_read_PORTFIO_MASKB_CLEAR() bfin_read16(PORTFIO_MASKB_CLEAR)
+#define bfin_write_PORTFIO_MASKB_CLEAR(val) bfin_write16(PORTFIO_MASKB_CLEAR, val)
+#define bfin_read_PORTFIO_MASKB_SET() bfin_read16(PORTFIO_MASKB_SET)
+#define bfin_write_PORTFIO_MASKB_SET(val) bfin_write16(PORTFIO_MASKB_SET, val)
+#define bfin_read_PORTFIO_MASKB_TOGGLE() bfin_read16(PORTFIO_MASKB_TOGGLE)
+#define bfin_write_PORTFIO_MASKB_TOGGLE(val) bfin_write16(PORTFIO_MASKB_TOGGLE, val)
+#define bfin_read_PORTFIO_DIR() bfin_read16(PORTFIO_DIR)
+#define bfin_write_PORTFIO_DIR(val) bfin_write16(PORTFIO_DIR, val)
+#define bfin_read_PORTFIO_POLAR() bfin_read16(PORTFIO_POLAR)
+#define bfin_write_PORTFIO_POLAR(val) bfin_write16(PORTFIO_POLAR, val)
+#define bfin_read_PORTFIO_EDGE() bfin_read16(PORTFIO_EDGE)
+#define bfin_write_PORTFIO_EDGE(val) bfin_write16(PORTFIO_EDGE, val)
+#define bfin_read_PORTFIO_BOTH() bfin_read16(PORTFIO_BOTH)
+#define bfin_write_PORTFIO_BOTH(val) bfin_write16(PORTFIO_BOTH, val)
+#define bfin_read_PORTFIO_INEN() bfin_read16(PORTFIO_INEN)
+#define bfin_write_PORTFIO_INEN(val) bfin_write16(PORTFIO_INEN, val)
+#define bfin_read_PORTCIO_FER() bfin_read16(PORTCIO_FER)
+#define bfin_write_PORTCIO_FER(val) bfin_write16(PORTCIO_FER, val)
+#define bfin_read_PORTCIO() bfin_read16(PORTCIO)
+#define bfin_write_PORTCIO(val) bfin_write16(PORTCIO, val)
+#define bfin_read_PORTCIO_CLEAR() bfin_read16(PORTCIO_CLEAR)
+#define bfin_write_PORTCIO_CLEAR(val) bfin_write16(PORTCIO_CLEAR, val)
+#define bfin_read_PORTCIO_SET() bfin_read16(PORTCIO_SET)
+#define bfin_write_PORTCIO_SET(val) bfin_write16(PORTCIO_SET, val)
+#define bfin_read_PORTCIO_TOGGLE() bfin_read16(PORTCIO_TOGGLE)
+#define bfin_write_PORTCIO_TOGGLE(val) bfin_write16(PORTCIO_TOGGLE, val)
+#define bfin_read_PORTCIO_DIR() bfin_read16(PORTCIO_DIR)
+#define bfin_write_PORTCIO_DIR(val) bfin_write16(PORTCIO_DIR, val)
+#define bfin_read_PORTCIO_INEN() bfin_read16(PORTCIO_INEN)
+#define bfin_write_PORTCIO_INEN(val) bfin_write16(PORTCIO_INEN, val)
+#define bfin_read_PORTDIO_FER() bfin_read16(PORTDIO_FER)
+#define bfin_write_PORTDIO_FER(val) bfin_write16(PORTDIO_FER, val)
+#define bfin_read_PORTDIO() bfin_read16(PORTDIO)
+#define bfin_write_PORTDIO(val) bfin_write16(PORTDIO, val)
+#define bfin_read_PORTDIO_CLEAR() bfin_read16(PORTDIO_CLEAR)
+#define bfin_write_PORTDIO_CLEAR(val) bfin_write16(PORTDIO_CLEAR, val)
+#define bfin_read_PORTDIO_SET() bfin_read16(PORTDIO_SET)
+#define bfin_write_PORTDIO_SET(val) bfin_write16(PORTDIO_SET, val)
+#define bfin_read_PORTDIO_TOGGLE() bfin_read16(PORTDIO_TOGGLE)
+#define bfin_write_PORTDIO_TOGGLE(val) bfin_write16(PORTDIO_TOGGLE, val)
+#define bfin_read_PORTDIO_DIR() bfin_read16(PORTDIO_DIR)
+#define bfin_write_PORTDIO_DIR(val) bfin_write16(PORTDIO_DIR, val)
+#define bfin_read_PORTDIO_INEN() bfin_read16(PORTDIO_INEN)
+#define bfin_write_PORTDIO_INEN(val) bfin_write16(PORTDIO_INEN, val)
+#define bfin_read_PORTEIO_FER() bfin_read16(PORTEIO_FER)
+#define bfin_write_PORTEIO_FER(val) bfin_write16(PORTEIO_FER, val)
+#define bfin_read_PORTEIO() bfin_read16(PORTEIO)
+#define bfin_write_PORTEIO(val) bfin_write16(PORTEIO, val)
+#define bfin_read_PORTEIO_CLEAR() bfin_read16(PORTEIO_CLEAR)
+#define bfin_write_PORTEIO_CLEAR(val) bfin_write16(PORTEIO_CLEAR, val)
+#define bfin_read_PORTEIO_SET() bfin_read16(PORTEIO_SET)
+#define bfin_write_PORTEIO_SET(val) bfin_write16(PORTEIO_SET, val)
+#define bfin_read_PORTEIO_TOGGLE() bfin_read16(PORTEIO_TOGGLE)
+#define bfin_write_PORTEIO_TOGGLE(val) bfin_write16(PORTEIO_TOGGLE, val)
+#define bfin_read_PORTEIO_DIR() bfin_read16(PORTEIO_DIR)
+#define bfin_write_PORTEIO_DIR(val) bfin_write16(PORTEIO_DIR, val)
+#define bfin_read_PORTEIO_INEN() bfin_read16(PORTEIO_INEN)
+#define bfin_write_PORTEIO_INEN(val) bfin_write16(PORTEIO_INEN, val)
+#define bfin_read_EBIU_AMGCTL() bfin_read16(EBIU_AMGCTL)
+#define bfin_write_EBIU_AMGCTL(val) bfin_write16(EBIU_AMGCTL, val)
+#define bfin_read_EBIU_AMBCTL0() bfin_read32(EBIU_AMBCTL0)
+#define bfin_write_EBIU_AMBCTL0(val) bfin_write32(EBIU_AMBCTL0, val)
+#define bfin_read_EBIU_AMBCTL1() bfin_read32(EBIU_AMBCTL1)
+#define bfin_write_EBIU_AMBCTL1(val) bfin_write32(EBIU_AMBCTL1, val)
+#define bfin_read_EBIU_SDGCTL() bfin_read32(EBIU_SDGCTL)
+#define bfin_write_EBIU_SDGCTL(val) bfin_write32(EBIU_SDGCTL, val)
+#define bfin_read_EBIU_SDBCTL() bfin_read16(EBIU_SDBCTL)
+#define bfin_write_EBIU_SDBCTL(val) bfin_write16(EBIU_SDBCTL, val)
+#define bfin_read_EBIU_SDRRC() bfin_read16(EBIU_SDRRC)
+#define bfin_write_EBIU_SDRRC(val) bfin_write16(EBIU_SDRRC, val)
+#define bfin_read_EBIU_SDSTAT() bfin_read16(EBIU_SDSTAT)
+#define bfin_write_EBIU_SDSTAT(val) bfin_write16(EBIU_SDSTAT, val)
+#define bfin_read_DMA0_TC_PER() bfin_read16(DMA0_TC_PER)
+#define bfin_write_DMA0_TC_PER(val) bfin_write16(DMA0_TC_PER, val)
+#define bfin_read_DMA0_TC_CNT() bfin_read16(DMA0_TC_CNT)
+#define bfin_write_DMA0_TC_CNT(val) bfin_write16(DMA0_TC_CNT, val)
+#define bfin_read_DMA0_NEXT_DESC_PTR() bfin_readPTR(DMA0_NEXT_DESC_PTR)
+#define bfin_write_DMA0_NEXT_DESC_PTR(val) bfin_writePTR(DMA0_NEXT_DESC_PTR, val)
+#define bfin_read_DMA0_START_ADDR() bfin_readPTR(DMA0_START_ADDR)
+#define bfin_write_DMA0_START_ADDR(val) bfin_writePTR(DMA0_START_ADDR, val)
+#define bfin_read_DMA0_CONFIG() bfin_read16(DMA0_CONFIG)
+#define bfin_write_DMA0_CONFIG(val) bfin_write16(DMA0_CONFIG, val)
+#define bfin_read_DMA0_X_COUNT() bfin_read16(DMA0_X_COUNT)
+#define bfin_write_DMA0_X_COUNT(val) bfin_write16(DMA0_X_COUNT, val)
+#define bfin_read_DMA0_X_MODIFY() bfin_read16(DMA0_X_MODIFY)
+#define bfin_write_DMA0_X_MODIFY(val) bfin_write16(DMA0_X_MODIFY, val)
+#define bfin_read_DMA0_Y_COUNT() bfin_read16(DMA0_Y_COUNT)
+#define bfin_write_DMA0_Y_COUNT(val) bfin_write16(DMA0_Y_COUNT, val)
+#define bfin_read_DMA0_Y_MODIFY() bfin_read16(DMA0_Y_MODIFY)
+#define bfin_write_DMA0_Y_MODIFY(val) bfin_write16(DMA0_Y_MODIFY, val)
+#define bfin_read_DMA0_CURR_DESC_PTR() bfin_readPTR(DMA0_CURR_DESC_PTR)
+#define bfin_write_DMA0_CURR_DESC_PTR(val) bfin_writePTR(DMA0_CURR_DESC_PTR, val)
+#define bfin_read_DMA0_CURR_ADDR() bfin_readPTR(DMA0_CURR_ADDR)
+#define bfin_write_DMA0_CURR_ADDR(val) bfin_writePTR(DMA0_CURR_ADDR, val)
+#define bfin_read_DMA0_IRQ_STATUS() bfin_read16(DMA0_IRQ_STATUS)
+#define bfin_write_DMA0_IRQ_STATUS(val) bfin_write16(DMA0_IRQ_STATUS, val)
+#define bfin_read_DMA0_PERIPHERAL_MAP() bfin_read16(DMA0_PERIPHERAL_MAP)
+#define bfin_write_DMA0_PERIPHERAL_MAP(val) bfin_write16(DMA0_PERIPHERAL_MAP, val)
+#define bfin_read_DMA0_CURR_X_COUNT() bfin_read16(DMA0_CURR_X_COUNT)
+#define bfin_write_DMA0_CURR_X_COUNT(val) bfin_write16(DMA0_CURR_X_COUNT, val)
+#define bfin_read_DMA0_CURR_Y_COUNT() bfin_read16(DMA0_CURR_Y_COUNT)
+#define bfin_write_DMA0_CURR_Y_COUNT(val) bfin_write16(DMA0_CURR_Y_COUNT, val)
+#define bfin_read_DMA1_NEXT_DESC_PTR() bfin_readPTR(DMA1_NEXT_DESC_PTR)
+#define bfin_write_DMA1_NEXT_DESC_PTR(val) bfin_writePTR(DMA1_NEXT_DESC_PTR, val)
+#define bfin_read_DMA1_START_ADDR() bfin_readPTR(DMA1_START_ADDR)
+#define bfin_write_DMA1_START_ADDR(val) bfin_writePTR(DMA1_START_ADDR, val)
+#define bfin_read_DMA1_CONFIG() bfin_read16(DMA1_CONFIG)
+#define bfin_write_DMA1_CONFIG(val) bfin_write16(DMA1_CONFIG, val)
+#define bfin_read_DMA1_X_COUNT() bfin_read16(DMA1_X_COUNT)
+#define bfin_write_DMA1_X_COUNT(val) bfin_write16(DMA1_X_COUNT, val)
+#define bfin_read_DMA1_X_MODIFY() bfin_read16(DMA1_X_MODIFY)
+#define bfin_write_DMA1_X_MODIFY(val) bfin_write16(DMA1_X_MODIFY, val)
+#define bfin_read_DMA1_Y_COUNT() bfin_read16(DMA1_Y_COUNT)
+#define bfin_write_DMA1_Y_COUNT(val) bfin_write16(DMA1_Y_COUNT, val)
+#define bfin_read_DMA1_Y_MODIFY() bfin_read16(DMA1_Y_MODIFY)
+#define bfin_write_DMA1_Y_MODIFY(val) bfin_write16(DMA1_Y_MODIFY, val)
+#define bfin_read_DMA1_CURR_DESC_PTR() bfin_readPTR(DMA1_CURR_DESC_PTR)
+#define bfin_write_DMA1_CURR_DESC_PTR(val) bfin_writePTR(DMA1_CURR_DESC_PTR, val)
+#define bfin_read_DMA1_CURR_ADDR() bfin_readPTR(DMA1_CURR_ADDR)
+#define bfin_write_DMA1_CURR_ADDR(val) bfin_writePTR(DMA1_CURR_ADDR, val)
+#define bfin_read_DMA1_IRQ_STATUS() bfin_read16(DMA1_IRQ_STATUS)
+#define bfin_write_DMA1_IRQ_STATUS(val) bfin_write16(DMA1_IRQ_STATUS, val)
+#define bfin_read_DMA1_PERIPHERAL_MAP() bfin_read16(DMA1_PERIPHERAL_MAP)
+#define bfin_write_DMA1_PERIPHERAL_MAP(val) bfin_write16(DMA1_PERIPHERAL_MAP, val)
+#define bfin_read_DMA1_CURR_X_COUNT() bfin_read16(DMA1_CURR_X_COUNT)
+#define bfin_write_DMA1_CURR_X_COUNT(val) bfin_write16(DMA1_CURR_X_COUNT, val)
+#define bfin_read_DMA1_CURR_Y_COUNT() bfin_read16(DMA1_CURR_Y_COUNT)
+#define bfin_write_DMA1_CURR_Y_COUNT(val) bfin_write16(DMA1_CURR_Y_COUNT, val)
+#define bfin_read_DMA2_NEXT_DESC_PTR() bfin_readPTR(DMA2_NEXT_DESC_PTR)
+#define bfin_write_DMA2_NEXT_DESC_PTR(val) bfin_writePTR(DMA2_NEXT_DESC_PTR, val)
+#define bfin_read_DMA2_START_ADDR() bfin_readPTR(DMA2_START_ADDR)
+#define bfin_write_DMA2_START_ADDR(val) bfin_writePTR(DMA2_START_ADDR, val)
+#define bfin_read_DMA2_CONFIG() bfin_read16(DMA2_CONFIG)
+#define bfin_write_DMA2_CONFIG(val) bfin_write16(DMA2_CONFIG, val)
+#define bfin_read_DMA2_X_COUNT() bfin_read16(DMA2_X_COUNT)
+#define bfin_write_DMA2_X_COUNT(val) bfin_write16(DMA2_X_COUNT, val)
+#define bfin_read_DMA2_X_MODIFY() bfin_read16(DMA2_X_MODIFY)
+#define bfin_write_DMA2_X_MODIFY(val) bfin_write16(DMA2_X_MODIFY, val)
+#define bfin_read_DMA2_Y_COUNT() bfin_read16(DMA2_Y_COUNT)
+#define bfin_write_DMA2_Y_COUNT(val) bfin_write16(DMA2_Y_COUNT, val)
+#define bfin_read_DMA2_Y_MODIFY() bfin_read16(DMA2_Y_MODIFY)
+#define bfin_write_DMA2_Y_MODIFY(val) bfin_write16(DMA2_Y_MODIFY, val)
+#define bfin_read_DMA2_CURR_DESC_PTR() bfin_readPTR(DMA2_CURR_DESC_PTR)
+#define bfin_write_DMA2_CURR_DESC_PTR(val) bfin_writePTR(DMA2_CURR_DESC_PTR, val)
+#define bfin_read_DMA2_CURR_ADDR() bfin_readPTR(DMA2_CURR_ADDR)
+#define bfin_write_DMA2_CURR_ADDR(val) bfin_writePTR(DMA2_CURR_ADDR, val)
+#define bfin_read_DMA2_IRQ_STATUS() bfin_read16(DMA2_IRQ_STATUS)
+#define bfin_write_DMA2_IRQ_STATUS(val) bfin_write16(DMA2_IRQ_STATUS, val)
+#define bfin_read_DMA2_PERIPHERAL_MAP() bfin_read16(DMA2_PERIPHERAL_MAP)
+#define bfin_write_DMA2_PERIPHERAL_MAP(val) bfin_write16(DMA2_PERIPHERAL_MAP, val)
+#define bfin_read_DMA2_CURR_X_COUNT() bfin_read16(DMA2_CURR_X_COUNT)
+#define bfin_write_DMA2_CURR_X_COUNT(val) bfin_write16(DMA2_CURR_X_COUNT, val)
+#define bfin_read_DMA2_CURR_Y_COUNT() bfin_read16(DMA2_CURR_Y_COUNT)
+#define bfin_write_DMA2_CURR_Y_COUNT(val) bfin_write16(DMA2_CURR_Y_COUNT, val)
+#define bfin_read_DMA3_NEXT_DESC_PTR() bfin_readPTR(DMA3_NEXT_DESC_PTR)
+#define bfin_write_DMA3_NEXT_DESC_PTR(val) bfin_writePTR(DMA3_NEXT_DESC_PTR, val)
+#define bfin_read_DMA3_START_ADDR() bfin_readPTR(DMA3_START_ADDR)
+#define bfin_write_DMA3_START_ADDR(val) bfin_writePTR(DMA3_START_ADDR, val)
+#define bfin_read_DMA3_CONFIG() bfin_read16(DMA3_CONFIG)
+#define bfin_write_DMA3_CONFIG(val) bfin_write16(DMA3_CONFIG, val)
+#define bfin_read_DMA3_X_COUNT() bfin_read16(DMA3_X_COUNT)
+#define bfin_write_DMA3_X_COUNT(val) bfin_write16(DMA3_X_COUNT, val)
+#define bfin_read_DMA3_X_MODIFY() bfin_read16(DMA3_X_MODIFY)
+#define bfin_write_DMA3_X_MODIFY(val) bfin_write16(DMA3_X_MODIFY, val)
+#define bfin_read_DMA3_Y_COUNT() bfin_read16(DMA3_Y_COUNT)
+#define bfin_write_DMA3_Y_COUNT(val) bfin_write16(DMA3_Y_COUNT, val)
+#define bfin_read_DMA3_Y_MODIFY() bfin_read16(DMA3_Y_MODIFY)
+#define bfin_write_DMA3_Y_MODIFY(val) bfin_write16(DMA3_Y_MODIFY, val)
+#define bfin_read_DMA3_CURR_DESC_PTR() bfin_readPTR(DMA3_CURR_DESC_PTR)
+#define bfin_write_DMA3_CURR_DESC_PTR(val) bfin_writePTR(DMA3_CURR_DESC_PTR, val)
+#define bfin_read_DMA3_CURR_ADDR() bfin_readPTR(DMA3_CURR_ADDR)
+#define bfin_write_DMA3_CURR_ADDR(val) bfin_writePTR(DMA3_CURR_ADDR, val)
+#define bfin_read_DMA3_IRQ_STATUS() bfin_read16(DMA3_IRQ_STATUS)
+#define bfin_write_DMA3_IRQ_STATUS(val) bfin_write16(DMA3_IRQ_STATUS, val)
+#define bfin_read_DMA3_PERIPHERAL_MAP() bfin_read16(DMA3_PERIPHERAL_MAP)
+#define bfin_write_DMA3_PERIPHERAL_MAP(val) bfin_write16(DMA3_PERIPHERAL_MAP, val)
+#define bfin_read_DMA3_CURR_X_COUNT() bfin_read16(DMA3_CURR_X_COUNT)
+#define bfin_write_DMA3_CURR_X_COUNT(val) bfin_write16(DMA3_CURR_X_COUNT, val)
+#define bfin_read_DMA3_CURR_Y_COUNT() bfin_read16(DMA3_CURR_Y_COUNT)
+#define bfin_write_DMA3_CURR_Y_COUNT(val) bfin_write16(DMA3_CURR_Y_COUNT, val)
+#define bfin_read_DMA4_NEXT_DESC_PTR() bfin_readPTR(DMA4_NEXT_DESC_PTR)
+#define bfin_write_DMA4_NEXT_DESC_PTR(val) bfin_writePTR(DMA4_NEXT_DESC_PTR, val)
+#define bfin_read_DMA4_START_ADDR() bfin_readPTR(DMA4_START_ADDR)
+#define bfin_write_DMA4_START_ADDR(val) bfin_writePTR(DMA4_START_ADDR, val)
+#define bfin_read_DMA4_CONFIG() bfin_read16(DMA4_CONFIG)
+#define bfin_write_DMA4_CONFIG(val) bfin_write16(DMA4_CONFIG, val)
+#define bfin_read_DMA4_X_COUNT() bfin_read16(DMA4_X_COUNT)
+#define bfin_write_DMA4_X_COUNT(val) bfin_write16(DMA4_X_COUNT, val)
+#define bfin_read_DMA4_X_MODIFY() bfin_read16(DMA4_X_MODIFY)
+#define bfin_write_DMA4_X_MODIFY(val) bfin_write16(DMA4_X_MODIFY, val)
+#define bfin_read_DMA4_Y_COUNT() bfin_read16(DMA4_Y_COUNT)
+#define bfin_write_DMA4_Y_COUNT(val) bfin_write16(DMA4_Y_COUNT, val)
+#define bfin_read_DMA4_Y_MODIFY() bfin_read16(DMA4_Y_MODIFY)
+#define bfin_write_DMA4_Y_MODIFY(val) bfin_write16(DMA4_Y_MODIFY, val)
+#define bfin_read_DMA4_CURR_DESC_PTR() bfin_readPTR(DMA4_CURR_DESC_PTR)
+#define bfin_write_DMA4_CURR_DESC_PTR(val) bfin_writePTR(DMA4_CURR_DESC_PTR, val)
+#define bfin_read_DMA4_CURR_ADDR() bfin_readPTR(DMA4_CURR_ADDR)
+#define bfin_write_DMA4_CURR_ADDR(val) bfin_writePTR(DMA4_CURR_ADDR, val)
+#define bfin_read_DMA4_IRQ_STATUS() bfin_read16(DMA4_IRQ_STATUS)
+#define bfin_write_DMA4_IRQ_STATUS(val) bfin_write16(DMA4_IRQ_STATUS, val)
+#define bfin_read_DMA4_PERIPHERAL_MAP() bfin_read16(DMA4_PERIPHERAL_MAP)
+#define bfin_write_DMA4_PERIPHERAL_MAP(val) bfin_write16(DMA4_PERIPHERAL_MAP, val)
+#define bfin_read_DMA4_CURR_X_COUNT() bfin_read16(DMA4_CURR_X_COUNT)
+#define bfin_write_DMA4_CURR_X_COUNT(val) bfin_write16(DMA4_CURR_X_COUNT, val)
+#define bfin_read_DMA4_CURR_Y_COUNT() bfin_read16(DMA4_CURR_Y_COUNT)
+#define bfin_write_DMA4_CURR_Y_COUNT(val) bfin_write16(DMA4_CURR_Y_COUNT, val)
+#define bfin_read_DMA5_NEXT_DESC_PTR() bfin_readPTR(DMA5_NEXT_DESC_PTR)
+#define bfin_write_DMA5_NEXT_DESC_PTR(val) bfin_writePTR(DMA5_NEXT_DESC_PTR, val)
+#define bfin_read_DMA5_START_ADDR() bfin_readPTR(DMA5_START_ADDR)
+#define bfin_write_DMA5_START_ADDR(val) bfin_writePTR(DMA5_START_ADDR, val)
+#define bfin_read_DMA5_CONFIG() bfin_read16(DMA5_CONFIG)
+#define bfin_write_DMA5_CONFIG(val) bfin_write16(DMA5_CONFIG, val)
+#define bfin_read_DMA5_X_COUNT() bfin_read16(DMA5_X_COUNT)
+#define bfin_write_DMA5_X_COUNT(val) bfin_write16(DMA5_X_COUNT, val)
+#define bfin_read_DMA5_X_MODIFY() bfin_read16(DMA5_X_MODIFY)
+#define bfin_write_DMA5_X_MODIFY(val) bfin_write16(DMA5_X_MODIFY, val)
+#define bfin_read_DMA5_Y_COUNT() bfin_read16(DMA5_Y_COUNT)
+#define bfin_write_DMA5_Y_COUNT(val) bfin_write16(DMA5_Y_COUNT, val)
+#define bfin_read_DMA5_Y_MODIFY() bfin_read16(DMA5_Y_MODIFY)
+#define bfin_write_DMA5_Y_MODIFY(val) bfin_write16(DMA5_Y_MODIFY, val)
+#define bfin_read_DMA5_CURR_DESC_PTR() bfin_readPTR(DMA5_CURR_DESC_PTR)
+#define bfin_write_DMA5_CURR_DESC_PTR(val) bfin_writePTR(DMA5_CURR_DESC_PTR, val)
+#define bfin_read_DMA5_CURR_ADDR() bfin_readPTR(DMA5_CURR_ADDR)
+#define bfin_write_DMA5_CURR_ADDR(val) bfin_writePTR(DMA5_CURR_ADDR, val)
+#define bfin_read_DMA5_IRQ_STATUS() bfin_read16(DMA5_IRQ_STATUS)
+#define bfin_write_DMA5_IRQ_STATUS(val) bfin_write16(DMA5_IRQ_STATUS, val)
+#define bfin_read_DMA5_PERIPHERAL_MAP() bfin_read16(DMA5_PERIPHERAL_MAP)
+#define bfin_write_DMA5_PERIPHERAL_MAP(val) bfin_write16(DMA5_PERIPHERAL_MAP, val)
+#define bfin_read_DMA5_CURR_X_COUNT() bfin_read16(DMA5_CURR_X_COUNT)
+#define bfin_write_DMA5_CURR_X_COUNT(val) bfin_write16(DMA5_CURR_X_COUNT, val)
+#define bfin_read_DMA5_CURR_Y_COUNT() bfin_read16(DMA5_CURR_Y_COUNT)
+#define bfin_write_DMA5_CURR_Y_COUNT(val) bfin_write16(DMA5_CURR_Y_COUNT, val)
+#define bfin_read_DMA6_NEXT_DESC_PTR() bfin_readPTR(DMA6_NEXT_DESC_PTR)
+#define bfin_write_DMA6_NEXT_DESC_PTR(val) bfin_writePTR(DMA6_NEXT_DESC_PTR, val)
+#define bfin_read_DMA6_START_ADDR() bfin_readPTR(DMA6_START_ADDR)
+#define bfin_write_DMA6_START_ADDR(val) bfin_writePTR(DMA6_START_ADDR, val)
+#define bfin_read_DMA6_CONFIG() bfin_read16(DMA6_CONFIG)
+#define bfin_write_DMA6_CONFIG(val) bfin_write16(DMA6_CONFIG, val)
+#define bfin_read_DMA6_X_COUNT() bfin_read16(DMA6_X_COUNT)
+#define bfin_write_DMA6_X_COUNT(val) bfin_write16(DMA6_X_COUNT, val)
+#define bfin_read_DMA6_X_MODIFY() bfin_read16(DMA6_X_MODIFY)
+#define bfin_write_DMA6_X_MODIFY(val) bfin_write16(DMA6_X_MODIFY, val)
+#define bfin_read_DMA6_Y_COUNT() bfin_read16(DMA6_Y_COUNT)
+#define bfin_write_DMA6_Y_COUNT(val) bfin_write16(DMA6_Y_COUNT, val)
+#define bfin_read_DMA6_Y_MODIFY() bfin_read16(DMA6_Y_MODIFY)
+#define bfin_write_DMA6_Y_MODIFY(val) bfin_write16(DMA6_Y_MODIFY, val)
+#define bfin_read_DMA6_CURR_DESC_PTR() bfin_readPTR(DMA6_CURR_DESC_PTR)
+#define bfin_write_DMA6_CURR_DESC_PTR(val) bfin_writePTR(DMA6_CURR_DESC_PTR, val)
+#define bfin_read_DMA6_CURR_ADDR() bfin_readPTR(DMA6_CURR_ADDR)
+#define bfin_write_DMA6_CURR_ADDR(val) bfin_writePTR(DMA6_CURR_ADDR, val)
+#define bfin_read_DMA6_IRQ_STATUS() bfin_read16(DMA6_IRQ_STATUS)
+#define bfin_write_DMA6_IRQ_STATUS(val) bfin_write16(DMA6_IRQ_STATUS, val)
+#define bfin_read_DMA6_PERIPHERAL_MAP() bfin_read16(DMA6_PERIPHERAL_MAP)
+#define bfin_write_DMA6_PERIPHERAL_MAP(val) bfin_write16(DMA6_PERIPHERAL_MAP, val)
+#define bfin_read_DMA6_CURR_X_COUNT() bfin_read16(DMA6_CURR_X_COUNT)
+#define bfin_write_DMA6_CURR_X_COUNT(val) bfin_write16(DMA6_CURR_X_COUNT, val)
+#define bfin_read_DMA6_CURR_Y_COUNT() bfin_read16(DMA6_CURR_Y_COUNT)
+#define bfin_write_DMA6_CURR_Y_COUNT(val) bfin_write16(DMA6_CURR_Y_COUNT, val)
+#define bfin_read_DMA7_NEXT_DESC_PTR() bfin_readPTR(DMA7_NEXT_DESC_PTR)
+#define bfin_write_DMA7_NEXT_DESC_PTR(val) bfin_writePTR(DMA7_NEXT_DESC_PTR, val)
+#define bfin_read_DMA7_START_ADDR() bfin_readPTR(DMA7_START_ADDR)
+#define bfin_write_DMA7_START_ADDR(val) bfin_writePTR(DMA7_START_ADDR, val)
+#define bfin_read_DMA7_CONFIG() bfin_read16(DMA7_CONFIG)
+#define bfin_write_DMA7_CONFIG(val) bfin_write16(DMA7_CONFIG, val)
+#define bfin_read_DMA7_X_COUNT() bfin_read16(DMA7_X_COUNT)
+#define bfin_write_DMA7_X_COUNT(val) bfin_write16(DMA7_X_COUNT, val)
+#define bfin_read_DMA7_X_MODIFY() bfin_read16(DMA7_X_MODIFY)
+#define bfin_write_DMA7_X_MODIFY(val) bfin_write16(DMA7_X_MODIFY, val)
+#define bfin_read_DMA7_Y_COUNT() bfin_read16(DMA7_Y_COUNT)
+#define bfin_write_DMA7_Y_COUNT(val) bfin_write16(DMA7_Y_COUNT, val)
+#define bfin_read_DMA7_Y_MODIFY() bfin_read16(DMA7_Y_MODIFY)
+#define bfin_write_DMA7_Y_MODIFY(val) bfin_write16(DMA7_Y_MODIFY, val)
+#define bfin_read_DMA7_CURR_DESC_PTR() bfin_readPTR(DMA7_CURR_DESC_PTR)
+#define bfin_write_DMA7_CURR_DESC_PTR(val) bfin_writePTR(DMA7_CURR_DESC_PTR, val)
+#define bfin_read_DMA7_CURR_ADDR() bfin_readPTR(DMA7_CURR_ADDR)
+#define bfin_write_DMA7_CURR_ADDR(val) bfin_writePTR(DMA7_CURR_ADDR, val)
+#define bfin_read_DMA7_IRQ_STATUS() bfin_read16(DMA7_IRQ_STATUS)
+#define bfin_write_DMA7_IRQ_STATUS(val) bfin_write16(DMA7_IRQ_STATUS, val)
+#define bfin_read_DMA7_PERIPHERAL_MAP() bfin_read16(DMA7_PERIPHERAL_MAP)
+#define bfin_write_DMA7_PERIPHERAL_MAP(val) bfin_write16(DMA7_PERIPHERAL_MAP, val)
+#define bfin_read_DMA7_CURR_X_COUNT() bfin_read16(DMA7_CURR_X_COUNT)
+#define bfin_write_DMA7_CURR_X_COUNT(val) bfin_write16(DMA7_CURR_X_COUNT, val)
+#define bfin_read_DMA7_CURR_Y_COUNT() bfin_read16(DMA7_CURR_Y_COUNT)
+#define bfin_write_DMA7_CURR_Y_COUNT(val) bfin_write16(DMA7_CURR_Y_COUNT, val)
+#define bfin_read_DMA1_TC_PER() bfin_read16(DMA1_TC_PER)
+#define bfin_write_DMA1_TC_PER(val) bfin_write16(DMA1_TC_PER, val)
+#define bfin_read_DMA1_TC_CNT() bfin_read16(DMA1_TC_CNT)
+#define bfin_write_DMA1_TC_CNT(val) bfin_write16(DMA1_TC_CNT, val)
+#define bfin_read_DMA8_NEXT_DESC_PTR() bfin_readPTR(DMA8_NEXT_DESC_PTR)
+#define bfin_write_DMA8_NEXT_DESC_PTR(val) bfin_writePTR(DMA8_NEXT_DESC_PTR, val)
+#define bfin_read_DMA8_START_ADDR() bfin_readPTR(DMA8_START_ADDR)
+#define bfin_write_DMA8_START_ADDR(val) bfin_writePTR(DMA8_START_ADDR, val)
+#define bfin_read_DMA8_CONFIG() bfin_read16(DMA8_CONFIG)
+#define bfin_write_DMA8_CONFIG(val) bfin_write16(DMA8_CONFIG, val)
+#define bfin_read_DMA8_X_COUNT() bfin_read16(DMA8_X_COUNT)
+#define bfin_write_DMA8_X_COUNT(val) bfin_write16(DMA8_X_COUNT, val)
+#define bfin_read_DMA8_X_MODIFY() bfin_read16(DMA8_X_MODIFY)
+#define bfin_write_DMA8_X_MODIFY(val) bfin_write16(DMA8_X_MODIFY, val)
+#define bfin_read_DMA8_Y_COUNT() bfin_read16(DMA8_Y_COUNT)
+#define bfin_write_DMA8_Y_COUNT(val) bfin_write16(DMA8_Y_COUNT, val)
+#define bfin_read_DMA8_Y_MODIFY() bfin_read16(DMA8_Y_MODIFY)
+#define bfin_write_DMA8_Y_MODIFY(val) bfin_write16(DMA8_Y_MODIFY, val)
+#define bfin_read_DMA8_CURR_DESC_PTR() bfin_readPTR(DMA8_CURR_DESC_PTR)
+#define bfin_write_DMA8_CURR_DESC_PTR(val) bfin_writePTR(DMA8_CURR_DESC_PTR, val)
+#define bfin_read_DMA8_CURR_ADDR() bfin_readPTR(DMA8_CURR_ADDR)
+#define bfin_write_DMA8_CURR_ADDR(val) bfin_writePTR(DMA8_CURR_ADDR, val)
+#define bfin_read_DMA8_IRQ_STATUS() bfin_read16(DMA8_IRQ_STATUS)
+#define bfin_write_DMA8_IRQ_STATUS(val) bfin_write16(DMA8_IRQ_STATUS, val)
+#define bfin_read_DMA8_PERIPHERAL_MAP() bfin_read16(DMA8_PERIPHERAL_MAP)
+#define bfin_write_DMA8_PERIPHERAL_MAP(val) bfin_write16(DMA8_PERIPHERAL_MAP, val)
+#define bfin_read_DMA8_CURR_X_COUNT() bfin_read16(DMA8_CURR_X_COUNT)
+#define bfin_write_DMA8_CURR_X_COUNT(val) bfin_write16(DMA8_CURR_X_COUNT, val)
+#define bfin_read_DMA8_CURR_Y_COUNT() bfin_read16(DMA8_CURR_Y_COUNT)
+#define bfin_write_DMA8_CURR_Y_COUNT(val) bfin_write16(DMA8_CURR_Y_COUNT, val)
+#define bfin_read_DMA9_NEXT_DESC_PTR() bfin_readPTR(DMA9_NEXT_DESC_PTR)
+#define bfin_write_DMA9_NEXT_DESC_PTR(val) bfin_writePTR(DMA9_NEXT_DESC_PTR, val)
+#define bfin_read_DMA9_START_ADDR() bfin_readPTR(DMA9_START_ADDR)
+#define bfin_write_DMA9_START_ADDR(val) bfin_writePTR(DMA9_START_ADDR, val)
+#define bfin_read_DMA9_CONFIG() bfin_read16(DMA9_CONFIG)
+#define bfin_write_DMA9_CONFIG(val) bfin_write16(DMA9_CONFIG, val)
+#define bfin_read_DMA9_X_COUNT() bfin_read16(DMA9_X_COUNT)
+#define bfin_write_DMA9_X_COUNT(val) bfin_write16(DMA9_X_COUNT, val)
+#define bfin_read_DMA9_X_MODIFY() bfin_read16(DMA9_X_MODIFY)
+#define bfin_write_DMA9_X_MODIFY(val) bfin_write16(DMA9_X_MODIFY, val)
+#define bfin_read_DMA9_Y_COUNT() bfin_read16(DMA9_Y_COUNT)
+#define bfin_write_DMA9_Y_COUNT(val) bfin_write16(DMA9_Y_COUNT, val)
+#define bfin_read_DMA9_Y_MODIFY() bfin_read16(DMA9_Y_MODIFY)
+#define bfin_write_DMA9_Y_MODIFY(val) bfin_write16(DMA9_Y_MODIFY, val)
+#define bfin_read_DMA9_CURR_DESC_PTR() bfin_readPTR(DMA9_CURR_DESC_PTR)
+#define bfin_write_DMA9_CURR_DESC_PTR(val) bfin_writePTR(DMA9_CURR_DESC_PTR, val)
+#define bfin_read_DMA9_CURR_ADDR() bfin_readPTR(DMA9_CURR_ADDR)
+#define bfin_write_DMA9_CURR_ADDR(val) bfin_writePTR(DMA9_CURR_ADDR, val)
+#define bfin_read_DMA9_IRQ_STATUS() bfin_read16(DMA9_IRQ_STATUS)
+#define bfin_write_DMA9_IRQ_STATUS(val) bfin_write16(DMA9_IRQ_STATUS, val)
+#define bfin_read_DMA9_PERIPHERAL_MAP() bfin_read16(DMA9_PERIPHERAL_MAP)
+#define bfin_write_DMA9_PERIPHERAL_MAP(val) bfin_write16(DMA9_PERIPHERAL_MAP, val)
+#define bfin_read_DMA9_CURR_X_COUNT() bfin_read16(DMA9_CURR_X_COUNT)
+#define bfin_write_DMA9_CURR_X_COUNT(val) bfin_write16(DMA9_CURR_X_COUNT, val)
+#define bfin_read_DMA9_CURR_Y_COUNT() bfin_read16(DMA9_CURR_Y_COUNT)
+#define bfin_write_DMA9_CURR_Y_COUNT(val) bfin_write16(DMA9_CURR_Y_COUNT, val)
+#define bfin_read_DMA10_NEXT_DESC_PTR() bfin_readPTR(DMA10_NEXT_DESC_PTR)
+#define bfin_write_DMA10_NEXT_DESC_PTR(val) bfin_writePTR(DMA10_NEXT_DESC_PTR, val)
+#define bfin_read_DMA10_START_ADDR() bfin_readPTR(DMA10_START_ADDR)
+#define bfin_write_DMA10_START_ADDR(val) bfin_writePTR(DMA10_START_ADDR, val)
+#define bfin_read_DMA10_CONFIG() bfin_read16(DMA10_CONFIG)
+#define bfin_write_DMA10_CONFIG(val) bfin_write16(DMA10_CONFIG, val)
+#define bfin_read_DMA10_X_COUNT() bfin_read16(DMA10_X_COUNT)
+#define bfin_write_DMA10_X_COUNT(val) bfin_write16(DMA10_X_COUNT, val)
+#define bfin_read_DMA10_X_MODIFY() bfin_read16(DMA10_X_MODIFY)
+#define bfin_write_DMA10_X_MODIFY(val) bfin_write16(DMA10_X_MODIFY, val)
+#define bfin_read_DMA10_Y_COUNT() bfin_read16(DMA10_Y_COUNT)
+#define bfin_write_DMA10_Y_COUNT(val) bfin_write16(DMA10_Y_COUNT, val)
+#define bfin_read_DMA10_Y_MODIFY() bfin_read16(DMA10_Y_MODIFY)
+#define bfin_write_DMA10_Y_MODIFY(val) bfin_write16(DMA10_Y_MODIFY, val)
+#define bfin_read_DMA10_CURR_DESC_PTR() bfin_readPTR(DMA10_CURR_DESC_PTR)
+#define bfin_write_DMA10_CURR_DESC_PTR(val) bfin_writePTR(DMA10_CURR_DESC_PTR, val)
+#define bfin_read_DMA10_CURR_ADDR() bfin_readPTR(DMA10_CURR_ADDR)
+#define bfin_write_DMA10_CURR_ADDR(val) bfin_writePTR(DMA10_CURR_ADDR, val)
+#define bfin_read_DMA10_IRQ_STATUS() bfin_read16(DMA10_IRQ_STATUS)
+#define bfin_write_DMA10_IRQ_STATUS(val) bfin_write16(DMA10_IRQ_STATUS, val)
+#define bfin_read_DMA10_PERIPHERAL_MAP() bfin_read16(DMA10_PERIPHERAL_MAP)
+#define bfin_write_DMA10_PERIPHERAL_MAP(val) bfin_write16(DMA10_PERIPHERAL_MAP, val)
+#define bfin_read_DMA10_CURR_X_COUNT() bfin_read16(DMA10_CURR_X_COUNT)
+#define bfin_write_DMA10_CURR_X_COUNT(val) bfin_write16(DMA10_CURR_X_COUNT, val)
+#define bfin_read_DMA10_CURR_Y_COUNT() bfin_read16(DMA10_CURR_Y_COUNT)
+#define bfin_write_DMA10_CURR_Y_COUNT(val) bfin_write16(DMA10_CURR_Y_COUNT, val)
+#define bfin_read_DMA11_NEXT_DESC_PTR() bfin_readPTR(DMA11_NEXT_DESC_PTR)
+#define bfin_write_DMA11_NEXT_DESC_PTR(val) bfin_writePTR(DMA11_NEXT_DESC_PTR, val)
+#define bfin_read_DMA11_START_ADDR() bfin_readPTR(DMA11_START_ADDR)
+#define bfin_write_DMA11_START_ADDR(val) bfin_writePTR(DMA11_START_ADDR, val)
+#define bfin_read_DMA11_CONFIG() bfin_read16(DMA11_CONFIG)
+#define bfin_write_DMA11_CONFIG(val) bfin_write16(DMA11_CONFIG, val)
+#define bfin_read_DMA11_X_COUNT() bfin_read16(DMA11_X_COUNT)
+#define bfin_write_DMA11_X_COUNT(val) bfin_write16(DMA11_X_COUNT, val)
+#define bfin_read_DMA11_X_MODIFY() bfin_read16(DMA11_X_MODIFY)
+#define bfin_write_DMA11_X_MODIFY(val) bfin_write16(DMA11_X_MODIFY, val)
+#define bfin_read_DMA11_Y_COUNT() bfin_read16(DMA11_Y_COUNT)
+#define bfin_write_DMA11_Y_COUNT(val) bfin_write16(DMA11_Y_COUNT, val)
+#define bfin_read_DMA11_Y_MODIFY() bfin_read16(DMA11_Y_MODIFY)
+#define bfin_write_DMA11_Y_MODIFY(val) bfin_write16(DMA11_Y_MODIFY, val)
+#define bfin_read_DMA11_CURR_DESC_PTR() bfin_readPTR(DMA11_CURR_DESC_PTR)
+#define bfin_write_DMA11_CURR_DESC_PTR(val) bfin_writePTR(DMA11_CURR_DESC_PTR, val)
+#define bfin_read_DMA11_CURR_ADDR() bfin_readPTR(DMA11_CURR_ADDR)
+#define bfin_write_DMA11_CURR_ADDR(val) bfin_writePTR(DMA11_CURR_ADDR, val)
+#define bfin_read_DMA11_IRQ_STATUS() bfin_read16(DMA11_IRQ_STATUS)
+#define bfin_write_DMA11_IRQ_STATUS(val) bfin_write16(DMA11_IRQ_STATUS, val)
+#define bfin_read_DMA11_PERIPHERAL_MAP() bfin_read16(DMA11_PERIPHERAL_MAP)
+#define bfin_write_DMA11_PERIPHERAL_MAP(val) bfin_write16(DMA11_PERIPHERAL_MAP, val)
+#define bfin_read_DMA11_CURR_X_COUNT() bfin_read16(DMA11_CURR_X_COUNT)
+#define bfin_write_DMA11_CURR_X_COUNT(val) bfin_write16(DMA11_CURR_X_COUNT, val)
+#define bfin_read_DMA11_CURR_Y_COUNT() bfin_read16(DMA11_CURR_Y_COUNT)
+#define bfin_write_DMA11_CURR_Y_COUNT(val) bfin_write16(DMA11_CURR_Y_COUNT, val)
+#define bfin_read_DMA12_NEXT_DESC_PTR() bfin_readPTR(DMA12_NEXT_DESC_PTR)
+#define bfin_write_DMA12_NEXT_DESC_PTR(val) bfin_writePTR(DMA12_NEXT_DESC_PTR, val)
+#define bfin_read_DMA12_START_ADDR() bfin_readPTR(DMA12_START_ADDR)
+#define bfin_write_DMA12_START_ADDR(val) bfin_writePTR(DMA12_START_ADDR, val)
+#define bfin_read_DMA12_CONFIG() bfin_read16(DMA12_CONFIG)
+#define bfin_write_DMA12_CONFIG(val) bfin_write16(DMA12_CONFIG, val)
+#define bfin_read_DMA12_X_COUNT() bfin_read16(DMA12_X_COUNT)
+#define bfin_write_DMA12_X_COUNT(val) bfin_write16(DMA12_X_COUNT, val)
+#define bfin_read_DMA12_X_MODIFY() bfin_read16(DMA12_X_MODIFY)
+#define bfin_write_DMA12_X_MODIFY(val) bfin_write16(DMA12_X_MODIFY, val)
+#define bfin_read_DMA12_Y_COUNT() bfin_read16(DMA12_Y_COUNT)
+#define bfin_write_DMA12_Y_COUNT(val) bfin_write16(DMA12_Y_COUNT, val)
+#define bfin_read_DMA12_Y_MODIFY() bfin_read16(DMA12_Y_MODIFY)
+#define bfin_write_DMA12_Y_MODIFY(val) bfin_write16(DMA12_Y_MODIFY, val)
+#define bfin_read_DMA12_CURR_DESC_PTR() bfin_readPTR(DMA12_CURR_DESC_PTR)
+#define bfin_write_DMA12_CURR_DESC_PTR(val) bfin_writePTR(DMA12_CURR_DESC_PTR, val)
+#define bfin_read_DMA12_CURR_ADDR() bfin_readPTR(DMA12_CURR_ADDR)
+#define bfin_write_DMA12_CURR_ADDR(val) bfin_writePTR(DMA12_CURR_ADDR, val)
+#define bfin_read_DMA12_IRQ_STATUS() bfin_read16(DMA12_IRQ_STATUS)
+#define bfin_write_DMA12_IRQ_STATUS(val) bfin_write16(DMA12_IRQ_STATUS, val)
+#define bfin_read_DMA12_PERIPHERAL_MAP() bfin_read16(DMA12_PERIPHERAL_MAP)
+#define bfin_write_DMA12_PERIPHERAL_MAP(val) bfin_write16(DMA12_PERIPHERAL_MAP, val)
+#define bfin_read_DMA12_CURR_X_COUNT() bfin_read16(DMA12_CURR_X_COUNT)
+#define bfin_write_DMA12_CURR_X_COUNT(val) bfin_write16(DMA12_CURR_X_COUNT, val)
+#define bfin_read_DMA12_CURR_Y_COUNT() bfin_read16(DMA12_CURR_Y_COUNT)
+#define bfin_write_DMA12_CURR_Y_COUNT(val) bfin_write16(DMA12_CURR_Y_COUNT, val)
+#define bfin_read_DMA13_NEXT_DESC_PTR() bfin_readPTR(DMA13_NEXT_DESC_PTR)
+#define bfin_write_DMA13_NEXT_DESC_PTR(val) bfin_writePTR(DMA13_NEXT_DESC_PTR, val)
+#define bfin_read_DMA13_START_ADDR() bfin_readPTR(DMA13_START_ADDR)
+#define bfin_write_DMA13_START_ADDR(val) bfin_writePTR(DMA13_START_ADDR, val)
+#define bfin_read_DMA13_CONFIG() bfin_read16(DMA13_CONFIG)
+#define bfin_write_DMA13_CONFIG(val) bfin_write16(DMA13_CONFIG, val)
+#define bfin_read_DMA13_X_COUNT() bfin_read16(DMA13_X_COUNT)
+#define bfin_write_DMA13_X_COUNT(val) bfin_write16(DMA13_X_COUNT, val)
+#define bfin_read_DMA13_X_MODIFY() bfin_read16(DMA13_X_MODIFY)
+#define bfin_write_DMA13_X_MODIFY(val) bfin_write16(DMA13_X_MODIFY, val)
+#define bfin_read_DMA13_Y_COUNT() bfin_read16(DMA13_Y_COUNT)
+#define bfin_write_DMA13_Y_COUNT(val) bfin_write16(DMA13_Y_COUNT, val)
+#define bfin_read_DMA13_Y_MODIFY() bfin_read16(DMA13_Y_MODIFY)
+#define bfin_write_DMA13_Y_MODIFY(val) bfin_write16(DMA13_Y_MODIFY, val)
+#define bfin_read_DMA13_CURR_DESC_PTR() bfin_readPTR(DMA13_CURR_DESC_PTR)
+#define bfin_write_DMA13_CURR_DESC_PTR(val) bfin_writePTR(DMA13_CURR_DESC_PTR, val)
+#define bfin_read_DMA13_CURR_ADDR() bfin_readPTR(DMA13_CURR_ADDR)
+#define bfin_write_DMA13_CURR_ADDR(val) bfin_writePTR(DMA13_CURR_ADDR, val)
+#define bfin_read_DMA13_IRQ_STATUS() bfin_read16(DMA13_IRQ_STATUS)
+#define bfin_write_DMA13_IRQ_STATUS(val) bfin_write16(DMA13_IRQ_STATUS, val)
+#define bfin_read_DMA13_PERIPHERAL_MAP() bfin_read16(DMA13_PERIPHERAL_MAP)
+#define bfin_write_DMA13_PERIPHERAL_MAP(val) bfin_write16(DMA13_PERIPHERAL_MAP, val)
+#define bfin_read_DMA13_CURR_X_COUNT() bfin_read16(DMA13_CURR_X_COUNT)
+#define bfin_write_DMA13_CURR_X_COUNT(val) bfin_write16(DMA13_CURR_X_COUNT, val)
+#define bfin_read_DMA13_CURR_Y_COUNT() bfin_read16(DMA13_CURR_Y_COUNT)
+#define bfin_write_DMA13_CURR_Y_COUNT(val) bfin_write16(DMA13_CURR_Y_COUNT, val)
+#define bfin_read_DMA14_NEXT_DESC_PTR() bfin_readPTR(DMA14_NEXT_DESC_PTR)
+#define bfin_write_DMA14_NEXT_DESC_PTR(val) bfin_writePTR(DMA14_NEXT_DESC_PTR, val)
+#define bfin_read_DMA14_START_ADDR() bfin_readPTR(DMA14_START_ADDR)
+#define bfin_write_DMA14_START_ADDR(val) bfin_writePTR(DMA14_START_ADDR, val)
+#define bfin_read_DMA14_CONFIG() bfin_read16(DMA14_CONFIG)
+#define bfin_write_DMA14_CONFIG(val) bfin_write16(DMA14_CONFIG, val)
+#define bfin_read_DMA14_X_COUNT() bfin_read16(DMA14_X_COUNT)
+#define bfin_write_DMA14_X_COUNT(val) bfin_write16(DMA14_X_COUNT, val)
+#define bfin_read_DMA14_X_MODIFY() bfin_read16(DMA14_X_MODIFY)
+#define bfin_write_DMA14_X_MODIFY(val) bfin_write16(DMA14_X_MODIFY, val)
+#define bfin_read_DMA14_Y_COUNT() bfin_read16(DMA14_Y_COUNT)
+#define bfin_write_DMA14_Y_COUNT(val) bfin_write16(DMA14_Y_COUNT, val)
+#define bfin_read_DMA14_Y_MODIFY() bfin_read16(DMA14_Y_MODIFY)
+#define bfin_write_DMA14_Y_MODIFY(val) bfin_write16(DMA14_Y_MODIFY, val)
+#define bfin_read_DMA14_CURR_DESC_PTR() bfin_readPTR(DMA14_CURR_DESC_PTR)
+#define bfin_write_DMA14_CURR_DESC_PTR(val) bfin_writePTR(DMA14_CURR_DESC_PTR, val)
+#define bfin_read_DMA14_CURR_ADDR() bfin_readPTR(DMA14_CURR_ADDR)
+#define bfin_write_DMA14_CURR_ADDR(val) bfin_writePTR(DMA14_CURR_ADDR, val)
+#define bfin_read_DMA14_IRQ_STATUS() bfin_read16(DMA14_IRQ_STATUS)
+#define bfin_write_DMA14_IRQ_STATUS(val) bfin_write16(DMA14_IRQ_STATUS, val)
+#define bfin_read_DMA14_PERIPHERAL_MAP() bfin_read16(DMA14_PERIPHERAL_MAP)
+#define bfin_write_DMA14_PERIPHERAL_MAP(val) bfin_write16(DMA14_PERIPHERAL_MAP, val)
+#define bfin_read_DMA14_CURR_X_COUNT() bfin_read16(DMA14_CURR_X_COUNT)
+#define bfin_write_DMA14_CURR_X_COUNT(val) bfin_write16(DMA14_CURR_X_COUNT, val)
+#define bfin_read_DMA14_CURR_Y_COUNT() bfin_read16(DMA14_CURR_Y_COUNT)
+#define bfin_write_DMA14_CURR_Y_COUNT(val) bfin_write16(DMA14_CURR_Y_COUNT, val)
+#define bfin_read_DMA15_NEXT_DESC_PTR() bfin_readPTR(DMA15_NEXT_DESC_PTR)
+#define bfin_write_DMA15_NEXT_DESC_PTR(val) bfin_writePTR(DMA15_NEXT_DESC_PTR, val)
+#define bfin_read_DMA15_START_ADDR() bfin_readPTR(DMA15_START_ADDR)
+#define bfin_write_DMA15_START_ADDR(val) bfin_writePTR(DMA15_START_ADDR, val)
+#define bfin_read_DMA15_CONFIG() bfin_read16(DMA15_CONFIG)
+#define bfin_write_DMA15_CONFIG(val) bfin_write16(DMA15_CONFIG, val)
+#define bfin_read_DMA15_X_COUNT() bfin_read16(DMA15_X_COUNT)
+#define bfin_write_DMA15_X_COUNT(val) bfin_write16(DMA15_X_COUNT, val)
+#define bfin_read_DMA15_X_MODIFY() bfin_read16(DMA15_X_MODIFY)
+#define bfin_write_DMA15_X_MODIFY(val) bfin_write16(DMA15_X_MODIFY, val)
+#define bfin_read_DMA15_Y_COUNT() bfin_read16(DMA15_Y_COUNT)
+#define bfin_write_DMA15_Y_COUNT(val) bfin_write16(DMA15_Y_COUNT, val)
+#define bfin_read_DMA15_Y_MODIFY() bfin_read16(DMA15_Y_MODIFY)
+#define bfin_write_DMA15_Y_MODIFY(val) bfin_write16(DMA15_Y_MODIFY, val)
+#define bfin_read_DMA15_CURR_DESC_PTR() bfin_readPTR(DMA15_CURR_DESC_PTR)
+#define bfin_write_DMA15_CURR_DESC_PTR(val) bfin_writePTR(DMA15_CURR_DESC_PTR, val)
+#define bfin_read_DMA15_CURR_ADDR() bfin_readPTR(DMA15_CURR_ADDR)
+#define bfin_write_DMA15_CURR_ADDR(val) bfin_writePTR(DMA15_CURR_ADDR, val)
+#define bfin_read_DMA15_IRQ_STATUS() bfin_read16(DMA15_IRQ_STATUS)
+#define bfin_write_DMA15_IRQ_STATUS(val) bfin_write16(DMA15_IRQ_STATUS, val)
+#define bfin_read_DMA15_PERIPHERAL_MAP() bfin_read16(DMA15_PERIPHERAL_MAP)
+#define bfin_write_DMA15_PERIPHERAL_MAP(val) bfin_write16(DMA15_PERIPHERAL_MAP, val)
+#define bfin_read_DMA15_CURR_X_COUNT() bfin_read16(DMA15_CURR_X_COUNT)
+#define bfin_write_DMA15_CURR_X_COUNT(val) bfin_write16(DMA15_CURR_X_COUNT, val)
+#define bfin_read_DMA15_CURR_Y_COUNT() bfin_read16(DMA15_CURR_Y_COUNT)
+#define bfin_write_DMA15_CURR_Y_COUNT(val) bfin_write16(DMA15_CURR_Y_COUNT, val)
+#define bfin_read_DMA16_NEXT_DESC_PTR() bfin_readPTR(DMA16_NEXT_DESC_PTR)
+#define bfin_write_DMA16_NEXT_DESC_PTR(val) bfin_writePTR(DMA16_NEXT_DESC_PTR, val)
+#define bfin_read_DMA16_START_ADDR() bfin_readPTR(DMA16_START_ADDR)
+#define bfin_write_DMA16_START_ADDR(val) bfin_writePTR(DMA16_START_ADDR, val)
+#define bfin_read_DMA16_CONFIG() bfin_read16(DMA16_CONFIG)
+#define bfin_write_DMA16_CONFIG(val) bfin_write16(DMA16_CONFIG, val)
+#define bfin_read_DMA16_X_COUNT() bfin_read16(DMA16_X_COUNT)
+#define bfin_write_DMA16_X_COUNT(val) bfin_write16(DMA16_X_COUNT, val)
+#define bfin_read_DMA16_X_MODIFY() bfin_read16(DMA16_X_MODIFY)
+#define bfin_write_DMA16_X_MODIFY(val) bfin_write16(DMA16_X_MODIFY, val)
+#define bfin_read_DMA16_Y_COUNT() bfin_read16(DMA16_Y_COUNT)
+#define bfin_write_DMA16_Y_COUNT(val) bfin_write16(DMA16_Y_COUNT, val)
+#define bfin_read_DMA16_Y_MODIFY() bfin_read16(DMA16_Y_MODIFY)
+#define bfin_write_DMA16_Y_MODIFY(val) bfin_write16(DMA16_Y_MODIFY, val)
+#define bfin_read_DMA16_CURR_DESC_PTR() bfin_readPTR(DMA16_CURR_DESC_PTR)
+#define bfin_write_DMA16_CURR_DESC_PTR(val) bfin_writePTR(DMA16_CURR_DESC_PTR, val)
+#define bfin_read_DMA16_CURR_ADDR() bfin_readPTR(DMA16_CURR_ADDR)
+#define bfin_write_DMA16_CURR_ADDR(val) bfin_writePTR(DMA16_CURR_ADDR, val)
+#define bfin_read_DMA16_IRQ_STATUS() bfin_read16(DMA16_IRQ_STATUS)
+#define bfin_write_DMA16_IRQ_STATUS(val) bfin_write16(DMA16_IRQ_STATUS, val)
+#define bfin_read_DMA16_PERIPHERAL_MAP() bfin_read16(DMA16_PERIPHERAL_MAP)
+#define bfin_write_DMA16_PERIPHERAL_MAP(val) bfin_write16(DMA16_PERIPHERAL_MAP, val)
+#define bfin_read_DMA16_CURR_X_COUNT() bfin_read16(DMA16_CURR_X_COUNT)
+#define bfin_write_DMA16_CURR_X_COUNT(val) bfin_write16(DMA16_CURR_X_COUNT, val)
+#define bfin_read_DMA16_CURR_Y_COUNT() bfin_read16(DMA16_CURR_Y_COUNT)
+#define bfin_write_DMA16_CURR_Y_COUNT(val) bfin_write16(DMA16_CURR_Y_COUNT, val)
+#define bfin_read_DMA17_NEXT_DESC_PTR() bfin_readPTR(DMA17_NEXT_DESC_PTR)
+#define bfin_write_DMA17_NEXT_DESC_PTR(val) bfin_writePTR(DMA17_NEXT_DESC_PTR, val)
+#define bfin_read_DMA17_START_ADDR() bfin_readPTR(DMA17_START_ADDR)
+#define bfin_write_DMA17_START_ADDR(val) bfin_writePTR(DMA17_START_ADDR, val)
+#define bfin_read_DMA17_CONFIG() bfin_read16(DMA17_CONFIG)
+#define bfin_write_DMA17_CONFIG(val) bfin_write16(DMA17_CONFIG, val)
+#define bfin_read_DMA17_X_COUNT() bfin_read16(DMA17_X_COUNT)
+#define bfin_write_DMA17_X_COUNT(val) bfin_write16(DMA17_X_COUNT, val)
+#define bfin_read_DMA17_X_MODIFY() bfin_read16(DMA17_X_MODIFY)
+#define bfin_write_DMA17_X_MODIFY(val) bfin_write16(DMA17_X_MODIFY, val)
+#define bfin_read_DMA17_Y_COUNT() bfin_read16(DMA17_Y_COUNT)
+#define bfin_write_DMA17_Y_COUNT(val) bfin_write16(DMA17_Y_COUNT, val)
+#define bfin_read_DMA17_Y_MODIFY() bfin_read16(DMA17_Y_MODIFY)
+#define bfin_write_DMA17_Y_MODIFY(val) bfin_write16(DMA17_Y_MODIFY, val)
+#define bfin_read_DMA17_CURR_DESC_PTR() bfin_readPTR(DMA17_CURR_DESC_PTR)
+#define bfin_write_DMA17_CURR_DESC_PTR(val) bfin_writePTR(DMA17_CURR_DESC_PTR, val)
+#define bfin_read_DMA17_CURR_ADDR() bfin_readPTR(DMA17_CURR_ADDR)
+#define bfin_write_DMA17_CURR_ADDR(val) bfin_writePTR(DMA17_CURR_ADDR, val)
+#define bfin_read_DMA17_IRQ_STATUS() bfin_read16(DMA17_IRQ_STATUS)
+#define bfin_write_DMA17_IRQ_STATUS(val) bfin_write16(DMA17_IRQ_STATUS, val)
+#define bfin_read_DMA17_PERIPHERAL_MAP() bfin_read16(DMA17_PERIPHERAL_MAP)
+#define bfin_write_DMA17_PERIPHERAL_MAP(val) bfin_write16(DMA17_PERIPHERAL_MAP, val)
+#define bfin_read_DMA17_CURR_X_COUNT() bfin_read16(DMA17_CURR_X_COUNT)
+#define bfin_write_DMA17_CURR_X_COUNT(val) bfin_write16(DMA17_CURR_X_COUNT, val)
+#define bfin_read_DMA17_CURR_Y_COUNT() bfin_read16(DMA17_CURR_Y_COUNT)
+#define bfin_write_DMA17_CURR_Y_COUNT(val) bfin_write16(DMA17_CURR_Y_COUNT, val)
+#define bfin_read_DMA18_NEXT_DESC_PTR() bfin_readPTR(DMA18_NEXT_DESC_PTR)
+#define bfin_write_DMA18_NEXT_DESC_PTR(val) bfin_writePTR(DMA18_NEXT_DESC_PTR, val)
+#define bfin_read_DMA18_START_ADDR() bfin_readPTR(DMA18_START_ADDR)
+#define bfin_write_DMA18_START_ADDR(val) bfin_writePTR(DMA18_START_ADDR, val)
+#define bfin_read_DMA18_CONFIG() bfin_read16(DMA18_CONFIG)
+#define bfin_write_DMA18_CONFIG(val) bfin_write16(DMA18_CONFIG, val)
+#define bfin_read_DMA18_X_COUNT() bfin_read16(DMA18_X_COUNT)
+#define bfin_write_DMA18_X_COUNT(val) bfin_write16(DMA18_X_COUNT, val)
+#define bfin_read_DMA18_X_MODIFY() bfin_read16(DMA18_X_MODIFY)
+#define bfin_write_DMA18_X_MODIFY(val) bfin_write16(DMA18_X_MODIFY, val)
+#define bfin_read_DMA18_Y_COUNT() bfin_read16(DMA18_Y_COUNT)
+#define bfin_write_DMA18_Y_COUNT(val) bfin_write16(DMA18_Y_COUNT, val)
+#define bfin_read_DMA18_Y_MODIFY() bfin_read16(DMA18_Y_MODIFY)
+#define bfin_write_DMA18_Y_MODIFY(val) bfin_write16(DMA18_Y_MODIFY, val)
+#define bfin_read_DMA18_CURR_DESC_PTR() bfin_readPTR(DMA18_CURR_DESC_PTR)
+#define bfin_write_DMA18_CURR_DESC_PTR(val) bfin_writePTR(DMA18_CURR_DESC_PTR, val)
+#define bfin_read_DMA18_CURR_ADDR() bfin_readPTR(DMA18_CURR_ADDR)
+#define bfin_write_DMA18_CURR_ADDR(val) bfin_writePTR(DMA18_CURR_ADDR, val)
+#define bfin_read_DMA18_IRQ_STATUS() bfin_read16(DMA18_IRQ_STATUS)
+#define bfin_write_DMA18_IRQ_STATUS(val) bfin_write16(DMA18_IRQ_STATUS, val)
+#define bfin_read_DMA18_PERIPHERAL_MAP() bfin_read16(DMA18_PERIPHERAL_MAP)
+#define bfin_write_DMA18_PERIPHERAL_MAP(val) bfin_write16(DMA18_PERIPHERAL_MAP, val)
+#define bfin_read_DMA18_CURR_X_COUNT() bfin_read16(DMA18_CURR_X_COUNT)
+#define bfin_write_DMA18_CURR_X_COUNT(val) bfin_write16(DMA18_CURR_X_COUNT, val)
+#define bfin_read_DMA18_CURR_Y_COUNT() bfin_read16(DMA18_CURR_Y_COUNT)
+#define bfin_write_DMA18_CURR_Y_COUNT(val) bfin_write16(DMA18_CURR_Y_COUNT, val)
+#define bfin_read_DMA19_NEXT_DESC_PTR() bfin_readPTR(DMA19_NEXT_DESC_PTR)
+#define bfin_write_DMA19_NEXT_DESC_PTR(val) bfin_writePTR(DMA19_NEXT_DESC_PTR, val)
+#define bfin_read_DMA19_START_ADDR() bfin_readPTR(DMA19_START_ADDR)
+#define bfin_write_DMA19_START_ADDR(val) bfin_writePTR(DMA19_START_ADDR, val)
+#define bfin_read_DMA19_CONFIG() bfin_read16(DMA19_CONFIG)
+#define bfin_write_DMA19_CONFIG(val) bfin_write16(DMA19_CONFIG, val)
+#define bfin_read_DMA19_X_COUNT() bfin_read16(DMA19_X_COUNT)
+#define bfin_write_DMA19_X_COUNT(val) bfin_write16(DMA19_X_COUNT, val)
+#define bfin_read_DMA19_X_MODIFY() bfin_read16(DMA19_X_MODIFY)
+#define bfin_write_DMA19_X_MODIFY(val) bfin_write16(DMA19_X_MODIFY, val)
+#define bfin_read_DMA19_Y_COUNT() bfin_read16(DMA19_Y_COUNT)
+#define bfin_write_DMA19_Y_COUNT(val) bfin_write16(DMA19_Y_COUNT, val)
+#define bfin_read_DMA19_Y_MODIFY() bfin_read16(DMA19_Y_MODIFY)
+#define bfin_write_DMA19_Y_MODIFY(val) bfin_write16(DMA19_Y_MODIFY, val)
+#define bfin_read_DMA19_CURR_DESC_PTR() bfin_readPTR(DMA19_CURR_DESC_PTR)
+#define bfin_write_DMA19_CURR_DESC_PTR(val) bfin_writePTR(DMA19_CURR_DESC_PTR, val)
+#define bfin_read_DMA19_CURR_ADDR() bfin_readPTR(DMA19_CURR_ADDR)
+#define bfin_write_DMA19_CURR_ADDR(val) bfin_writePTR(DMA19_CURR_ADDR, val)
+#define bfin_read_DMA19_IRQ_STATUS() bfin_read16(DMA19_IRQ_STATUS)
+#define bfin_write_DMA19_IRQ_STATUS(val) bfin_write16(DMA19_IRQ_STATUS, val)
+#define bfin_read_DMA19_PERIPHERAL_MAP() bfin_read16(DMA19_PERIPHERAL_MAP)
+#define bfin_write_DMA19_PERIPHERAL_MAP(val) bfin_write16(DMA19_PERIPHERAL_MAP, val)
+#define bfin_read_DMA19_CURR_X_COUNT() bfin_read16(DMA19_CURR_X_COUNT)
+#define bfin_write_DMA19_CURR_X_COUNT(val) bfin_write16(DMA19_CURR_X_COUNT, val)
+#define bfin_read_DMA19_CURR_Y_COUNT() bfin_read16(DMA19_CURR_Y_COUNT)
+#define bfin_write_DMA19_CURR_Y_COUNT(val) bfin_write16(DMA19_CURR_Y_COUNT, val)
+#define bfin_read_MDMA0_D0_NEXT_DESC_PTR() bfin_readPTR(MDMA0_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA0_D0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_D0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA0_D0_START_ADDR() bfin_readPTR(MDMA0_D0_START_ADDR)
+#define bfin_write_MDMA0_D0_START_ADDR(val) bfin_writePTR(MDMA0_D0_START_ADDR, val)
+#define bfin_read_MDMA0_D0_CONFIG() bfin_read16(MDMA0_D0_CONFIG)
+#define bfin_write_MDMA0_D0_CONFIG(val) bfin_write16(MDMA0_D0_CONFIG, val)
+#define bfin_read_MDMA0_D0_X_COUNT() bfin_read16(MDMA0_D0_X_COUNT)
+#define bfin_write_MDMA0_D0_X_COUNT(val) bfin_write16(MDMA0_D0_X_COUNT, val)
+#define bfin_read_MDMA0_D0_X_MODIFY() bfin_read16(MDMA0_D0_X_MODIFY)
+#define bfin_write_MDMA0_D0_X_MODIFY(val) bfin_write16(MDMA0_D0_X_MODIFY, val)
+#define bfin_read_MDMA0_D0_Y_COUNT() bfin_read16(MDMA0_D0_Y_COUNT)
+#define bfin_write_MDMA0_D0_Y_COUNT(val) bfin_write16(MDMA0_D0_Y_COUNT, val)
+#define bfin_read_MDMA0_D0_Y_MODIFY() bfin_read16(MDMA0_D0_Y_MODIFY)
+#define bfin_write_MDMA0_D0_Y_MODIFY(val) bfin_write16(MDMA0_D0_Y_MODIFY, val)
+#define bfin_read_MDMA0_D0_CURR_DESC_PTR() bfin_readPTR(MDMA0_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA0_D0_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA0_D0_CURR_ADDR() bfin_readPTR(MDMA0_D0_CURR_ADDR)
+#define bfin_write_MDMA0_D0_CURR_ADDR(val) bfin_writePTR(MDMA0_D0_CURR_ADDR, val)
+#define bfin_read_MDMA0_D0_IRQ_STATUS() bfin_read16(MDMA0_D0_IRQ_STATUS)
+#define bfin_write_MDMA0_D0_IRQ_STATUS(val) bfin_write16(MDMA0_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA0_D0_PERIPHERAL_MAP() bfin_read16(MDMA0_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA0_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA0_D0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA0_D0_CURR_X_COUNT() bfin_read16(MDMA0_D0_CURR_X_COUNT)
+#define bfin_write_MDMA0_D0_CURR_X_COUNT(val) bfin_write16(MDMA0_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA0_D0_CURR_Y_COUNT() bfin_read16(MDMA0_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA0_D0_CURR_Y_COUNT(val) bfin_write16(MDMA0_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA0_S0_NEXT_DESC_PTR() bfin_readPTR(MDMA0_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA0_S0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA0_S0_START_ADDR() bfin_readPTR(MDMA0_S0_START_ADDR)
+#define bfin_write_MDMA0_S0_START_ADDR(val) bfin_writePTR(MDMA0_S0_START_ADDR, val)
+#define bfin_read_MDMA0_S0_CONFIG() bfin_read16(MDMA0_S0_CONFIG)
+#define bfin_write_MDMA0_S0_CONFIG(val) bfin_write16(MDMA0_S0_CONFIG, val)
+#define bfin_read_MDMA0_S0_X_COUNT() bfin_read16(MDMA0_S0_X_COUNT)
+#define bfin_write_MDMA0_S0_X_COUNT(val) bfin_write16(MDMA0_S0_X_COUNT, val)
+#define bfin_read_MDMA0_S0_X_MODIFY() bfin_read16(MDMA0_S0_X_MODIFY)
+#define bfin_write_MDMA0_S0_X_MODIFY(val) bfin_write16(MDMA0_S0_X_MODIFY, val)
+#define bfin_read_MDMA0_S0_Y_COUNT() bfin_read16(MDMA0_S0_Y_COUNT)
+#define bfin_write_MDMA0_S0_Y_COUNT(val) bfin_write16(MDMA0_S0_Y_COUNT, val)
+#define bfin_read_MDMA0_S0_Y_MODIFY() bfin_read16(MDMA0_S0_Y_MODIFY)
+#define bfin_write_MDMA0_S0_Y_MODIFY(val) bfin_write16(MDMA0_S0_Y_MODIFY, val)
+#define bfin_read_MDMA0_S0_CURR_DESC_PTR() bfin_readPTR(MDMA0_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA0_S0_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA0_S0_CURR_ADDR() bfin_readPTR(MDMA0_S0_CURR_ADDR)
+#define bfin_write_MDMA0_S0_CURR_ADDR(val) bfin_writePTR(MDMA0_S0_CURR_ADDR, val)
+#define bfin_read_MDMA0_S0_IRQ_STATUS() bfin_read16(MDMA0_S0_IRQ_STATUS)
+#define bfin_write_MDMA0_S0_IRQ_STATUS(val) bfin_write16(MDMA0_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA0_S0_PERIPHERAL_MAP() bfin_read16(MDMA0_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA0_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA0_S0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA0_S0_CURR_X_COUNT() bfin_read16(MDMA0_S0_CURR_X_COUNT)
+#define bfin_write_MDMA0_S0_CURR_X_COUNT(val) bfin_write16(MDMA0_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA0_S0_CURR_Y_COUNT() bfin_read16(MDMA0_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA0_S0_CURR_Y_COUNT(val) bfin_write16(MDMA0_S0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA0_D1_NEXT_DESC_PTR() bfin_readPTR(MDMA0_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA0_D1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA0_D1_START_ADDR() bfin_readPTR(MDMA0_D1_START_ADDR)
+#define bfin_write_MDMA0_D1_START_ADDR(val) bfin_writePTR(MDMA0_D1_START_ADDR, val)
+#define bfin_read_MDMA0_D1_CONFIG() bfin_read16(MDMA0_D1_CONFIG)
+#define bfin_write_MDMA0_D1_CONFIG(val) bfin_write16(MDMA0_D1_CONFIG, val)
+#define bfin_read_MDMA0_D1_X_COUNT() bfin_read16(MDMA0_D1_X_COUNT)
+#define bfin_write_MDMA0_D1_X_COUNT(val) bfin_write16(MDMA0_D1_X_COUNT, val)
+#define bfin_read_MDMA0_D1_X_MODIFY() bfin_read16(MDMA0_D1_X_MODIFY)
+#define bfin_write_MDMA0_D1_X_MODIFY(val) bfin_write16(MDMA0_D1_X_MODIFY, val)
+#define bfin_read_MDMA0_D1_Y_COUNT() bfin_read16(MDMA0_D1_Y_COUNT)
+#define bfin_write_MDMA0_D1_Y_COUNT(val) bfin_write16(MDMA0_D1_Y_COUNT, val)
+#define bfin_read_MDMA0_D1_Y_MODIFY() bfin_read16(MDMA0_D1_Y_MODIFY)
+#define bfin_write_MDMA0_D1_Y_MODIFY(val) bfin_write16(MDMA0_D1_Y_MODIFY, val)
+#define bfin_read_MDMA0_D1_CURR_DESC_PTR() bfin_readPTR(MDMA0_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA0_D1_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA0_D1_CURR_ADDR() bfin_readPTR(MDMA0_D1_CURR_ADDR)
+#define bfin_write_MDMA0_D1_CURR_ADDR(val) bfin_writePTR(MDMA0_D1_CURR_ADDR, val)
+#define bfin_read_MDMA0_D1_IRQ_STATUS() bfin_read16(MDMA0_D1_IRQ_STATUS)
+#define bfin_write_MDMA0_D1_IRQ_STATUS(val) bfin_write16(MDMA0_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA0_D1_PERIPHERAL_MAP() bfin_read16(MDMA0_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA0_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA0_D1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA0_D1_CURR_X_COUNT() bfin_read16(MDMA0_D1_CURR_X_COUNT)
+#define bfin_write_MDMA0_D1_CURR_X_COUNT(val) bfin_write16(MDMA0_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA0_D1_CURR_Y_COUNT() bfin_read16(MDMA0_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA0_D1_CURR_Y_COUNT(val) bfin_write16(MDMA0_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA0_S1_NEXT_DESC_PTR() bfin_readPTR(MDMA0_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA0_S1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA0_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA0_S1_START_ADDR() bfin_readPTR(MDMA0_S1_START_ADDR)
+#define bfin_write_MDMA0_S1_START_ADDR(val) bfin_writePTR(MDMA0_S1_START_ADDR, val)
+#define bfin_read_MDMA0_S1_CONFIG() bfin_read16(MDMA0_S1_CONFIG)
+#define bfin_write_MDMA0_S1_CONFIG(val) bfin_write16(MDMA0_S1_CONFIG, val)
+#define bfin_read_MDMA0_S1_X_COUNT() bfin_read16(MDMA0_S1_X_COUNT)
+#define bfin_write_MDMA0_S1_X_COUNT(val) bfin_write16(MDMA0_S1_X_COUNT, val)
+#define bfin_read_MDMA0_S1_X_MODIFY() bfin_read16(MDMA0_S1_X_MODIFY)
+#define bfin_write_MDMA0_S1_X_MODIFY(val) bfin_write16(MDMA0_S1_X_MODIFY, val)
+#define bfin_read_MDMA0_S1_Y_COUNT() bfin_read16(MDMA0_S1_Y_COUNT)
+#define bfin_write_MDMA0_S1_Y_COUNT(val) bfin_write16(MDMA0_S1_Y_COUNT, val)
+#define bfin_read_MDMA0_S1_Y_MODIFY() bfin_read16(MDMA0_S1_Y_MODIFY)
+#define bfin_write_MDMA0_S1_Y_MODIFY(val) bfin_write16(MDMA0_S1_Y_MODIFY, val)
+#define bfin_read_MDMA0_S1_CURR_DESC_PTR() bfin_readPTR(MDMA0_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA0_S1_CURR_DESC_PTR(val) bfin_writePTR(MDMA0_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA0_S1_CURR_ADDR() bfin_readPTR(MDMA0_S1_CURR_ADDR)
+#define bfin_write_MDMA0_S1_CURR_ADDR(val) bfin_writePTR(MDMA0_S1_CURR_ADDR, val)
+#define bfin_read_MDMA0_S1_IRQ_STATUS() bfin_read16(MDMA0_S1_IRQ_STATUS)
+#define bfin_write_MDMA0_S1_IRQ_STATUS(val) bfin_write16(MDMA0_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA0_S1_PERIPHERAL_MAP() bfin_read16(MDMA0_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA0_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA0_S1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA0_S1_CURR_X_COUNT() bfin_read16(MDMA0_S1_CURR_X_COUNT)
+#define bfin_write_MDMA0_S1_CURR_X_COUNT(val) bfin_write16(MDMA0_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA0_S1_CURR_Y_COUNT() bfin_read16(MDMA0_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA0_S1_CURR_Y_COUNT(val) bfin_write16(MDMA0_S1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA1_D0_NEXT_DESC_PTR() bfin_readPTR(MDMA1_D0_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_D0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_D0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA1_D0_START_ADDR() bfin_readPTR(MDMA1_D0_START_ADDR)
+#define bfin_write_MDMA1_D0_START_ADDR(val) bfin_writePTR(MDMA1_D0_START_ADDR, val)
+#define bfin_read_MDMA1_D0_CONFIG() bfin_read16(MDMA1_D0_CONFIG)
+#define bfin_write_MDMA1_D0_CONFIG(val) bfin_write16(MDMA1_D0_CONFIG, val)
+#define bfin_read_MDMA1_D0_X_COUNT() bfin_read16(MDMA1_D0_X_COUNT)
+#define bfin_write_MDMA1_D0_X_COUNT(val) bfin_write16(MDMA1_D0_X_COUNT, val)
+#define bfin_read_MDMA1_D0_X_MODIFY() bfin_read16(MDMA1_D0_X_MODIFY)
+#define bfin_write_MDMA1_D0_X_MODIFY(val) bfin_write16(MDMA1_D0_X_MODIFY, val)
+#define bfin_read_MDMA1_D0_Y_COUNT() bfin_read16(MDMA1_D0_Y_COUNT)
+#define bfin_write_MDMA1_D0_Y_COUNT(val) bfin_write16(MDMA1_D0_Y_COUNT, val)
+#define bfin_read_MDMA1_D0_Y_MODIFY() bfin_read16(MDMA1_D0_Y_MODIFY)
+#define bfin_write_MDMA1_D0_Y_MODIFY(val) bfin_write16(MDMA1_D0_Y_MODIFY, val)
+#define bfin_read_MDMA1_D0_CURR_DESC_PTR() bfin_readPTR(MDMA1_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA1_D0_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_D0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA1_D0_CURR_ADDR() bfin_readPTR(MDMA1_D0_CURR_ADDR)
+#define bfin_write_MDMA1_D0_CURR_ADDR(val) bfin_writePTR(MDMA1_D0_CURR_ADDR, val)
+#define bfin_read_MDMA1_D0_IRQ_STATUS() bfin_read16(MDMA1_D0_IRQ_STATUS)
+#define bfin_write_MDMA1_D0_IRQ_STATUS(val) bfin_write16(MDMA1_D0_IRQ_STATUS, val)
+#define bfin_read_MDMA1_D0_PERIPHERAL_MAP() bfin_read16(MDMA1_D0_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_D0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA1_D0_CURR_X_COUNT() bfin_read16(MDMA1_D0_CURR_X_COUNT)
+#define bfin_write_MDMA1_D0_CURR_X_COUNT(val) bfin_write16(MDMA1_D0_CURR_X_COUNT, val)
+#define bfin_read_MDMA1_D0_CURR_Y_COUNT() bfin_read16(MDMA1_D0_CURR_Y_COUNT)
+#define bfin_write_MDMA1_D0_CURR_Y_COUNT(val) bfin_write16(MDMA1_D0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA1_S0_NEXT_DESC_PTR() bfin_readPTR(MDMA1_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_S0_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_S0_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA1_S0_START_ADDR() bfin_readPTR(MDMA1_S0_START_ADDR)
+#define bfin_write_MDMA1_S0_START_ADDR(val) bfin_writePTR(MDMA1_S0_START_ADDR, val)
+#define bfin_read_MDMA1_S0_CONFIG() bfin_read16(MDMA1_S0_CONFIG)
+#define bfin_write_MDMA1_S0_CONFIG(val) bfin_write16(MDMA1_S0_CONFIG, val)
+#define bfin_read_MDMA1_S0_X_COUNT() bfin_read16(MDMA1_S0_X_COUNT)
+#define bfin_write_MDMA1_S0_X_COUNT(val) bfin_write16(MDMA1_S0_X_COUNT, val)
+#define bfin_read_MDMA1_S0_X_MODIFY() bfin_read16(MDMA1_S0_X_MODIFY)
+#define bfin_write_MDMA1_S0_X_MODIFY(val) bfin_write16(MDMA1_S0_X_MODIFY, val)
+#define bfin_read_MDMA1_S0_Y_COUNT() bfin_read16(MDMA1_S0_Y_COUNT)
+#define bfin_write_MDMA1_S0_Y_COUNT(val) bfin_write16(MDMA1_S0_Y_COUNT, val)
+#define bfin_read_MDMA1_S0_Y_MODIFY() bfin_read16(MDMA1_S0_Y_MODIFY)
+#define bfin_write_MDMA1_S0_Y_MODIFY(val) bfin_write16(MDMA1_S0_Y_MODIFY, val)
+#define bfin_read_MDMA1_S0_CURR_DESC_PTR() bfin_readPTR(MDMA1_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA1_S0_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_S0_CURR_DESC_PTR, val)
+#define bfin_read_MDMA1_S0_CURR_ADDR() bfin_readPTR(MDMA1_S0_CURR_ADDR)
+#define bfin_write_MDMA1_S0_CURR_ADDR(val) bfin_writePTR(MDMA1_S0_CURR_ADDR, val)
+#define bfin_read_MDMA1_S0_IRQ_STATUS() bfin_read16(MDMA1_S0_IRQ_STATUS)
+#define bfin_write_MDMA1_S0_IRQ_STATUS(val) bfin_write16(MDMA1_S0_IRQ_STATUS, val)
+#define bfin_read_MDMA1_S0_PERIPHERAL_MAP() bfin_read16(MDMA1_S0_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_S0_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S0_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA1_S0_CURR_X_COUNT() bfin_read16(MDMA1_S0_CURR_X_COUNT)
+#define bfin_write_MDMA1_S0_CURR_X_COUNT(val) bfin_write16(MDMA1_S0_CURR_X_COUNT, val)
+#define bfin_read_MDMA1_S0_CURR_Y_COUNT() bfin_read16(MDMA1_S0_CURR_Y_COUNT)
+#define bfin_write_MDMA1_S0_CURR_Y_COUNT(val) bfin_write16(MDMA1_S0_CURR_Y_COUNT, val)
+#define bfin_read_MDMA1_D1_NEXT_DESC_PTR() bfin_readPTR(MDMA1_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_D1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_D1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA1_D1_START_ADDR() bfin_readPTR(MDMA1_D1_START_ADDR)
+#define bfin_write_MDMA1_D1_START_ADDR(val) bfin_writePTR(MDMA1_D1_START_ADDR, val)
+#define bfin_read_MDMA1_D1_CONFIG() bfin_read16(MDMA1_D1_CONFIG)
+#define bfin_write_MDMA1_D1_CONFIG(val) bfin_write16(MDMA1_D1_CONFIG, val)
+#define bfin_read_MDMA1_D1_X_COUNT() bfin_read16(MDMA1_D1_X_COUNT)
+#define bfin_write_MDMA1_D1_X_COUNT(val) bfin_write16(MDMA1_D1_X_COUNT, val)
+#define bfin_read_MDMA1_D1_X_MODIFY() bfin_read16(MDMA1_D1_X_MODIFY)
+#define bfin_write_MDMA1_D1_X_MODIFY(val) bfin_write16(MDMA1_D1_X_MODIFY, val)
+#define bfin_read_MDMA1_D1_Y_COUNT() bfin_read16(MDMA1_D1_Y_COUNT)
+#define bfin_write_MDMA1_D1_Y_COUNT(val) bfin_write16(MDMA1_D1_Y_COUNT, val)
+#define bfin_read_MDMA1_D1_Y_MODIFY() bfin_read16(MDMA1_D1_Y_MODIFY)
+#define bfin_write_MDMA1_D1_Y_MODIFY(val) bfin_write16(MDMA1_D1_Y_MODIFY, val)
+#define bfin_read_MDMA1_D1_CURR_DESC_PTR() bfin_readPTR(MDMA1_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA1_D1_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_D1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA1_D1_CURR_ADDR() bfin_readPTR(MDMA1_D1_CURR_ADDR)
+#define bfin_write_MDMA1_D1_CURR_ADDR(val) bfin_writePTR(MDMA1_D1_CURR_ADDR, val)
+#define bfin_read_MDMA1_D1_IRQ_STATUS() bfin_read16(MDMA1_D1_IRQ_STATUS)
+#define bfin_write_MDMA1_D1_IRQ_STATUS(val) bfin_write16(MDMA1_D1_IRQ_STATUS, val)
+#define bfin_read_MDMA1_D1_PERIPHERAL_MAP() bfin_read16(MDMA1_D1_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_D1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_D1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA1_D1_CURR_X_COUNT() bfin_read16(MDMA1_D1_CURR_X_COUNT)
+#define bfin_write_MDMA1_D1_CURR_X_COUNT(val) bfin_write16(MDMA1_D1_CURR_X_COUNT, val)
+#define bfin_read_MDMA1_D1_CURR_Y_COUNT() bfin_read16(MDMA1_D1_CURR_Y_COUNT)
+#define bfin_write_MDMA1_D1_CURR_Y_COUNT(val) bfin_write16(MDMA1_D1_CURR_Y_COUNT, val)
+#define bfin_read_MDMA1_S1_NEXT_DESC_PTR() bfin_readPTR(MDMA1_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA1_S1_NEXT_DESC_PTR(val) bfin_writePTR(MDMA1_S1_NEXT_DESC_PTR, val)
+#define bfin_read_MDMA1_S1_START_ADDR() bfin_readPTR(MDMA1_S1_START_ADDR)
+#define bfin_write_MDMA1_S1_START_ADDR(val) bfin_writePTR(MDMA1_S1_START_ADDR, val)
+#define bfin_read_MDMA1_S1_CONFIG() bfin_read16(MDMA1_S1_CONFIG)
+#define bfin_write_MDMA1_S1_CONFIG(val) bfin_write16(MDMA1_S1_CONFIG, val)
+#define bfin_read_MDMA1_S1_X_COUNT() bfin_read16(MDMA1_S1_X_COUNT)
+#define bfin_write_MDMA1_S1_X_COUNT(val) bfin_write16(MDMA1_S1_X_COUNT, val)
+#define bfin_read_MDMA1_S1_X_MODIFY() bfin_read16(MDMA1_S1_X_MODIFY)
+#define bfin_write_MDMA1_S1_X_MODIFY(val) bfin_write16(MDMA1_S1_X_MODIFY, val)
+#define bfin_read_MDMA1_S1_Y_COUNT() bfin_read16(MDMA1_S1_Y_COUNT)
+#define bfin_write_MDMA1_S1_Y_COUNT(val) bfin_write16(MDMA1_S1_Y_COUNT, val)
+#define bfin_read_MDMA1_S1_Y_MODIFY() bfin_read16(MDMA1_S1_Y_MODIFY)
+#define bfin_write_MDMA1_S1_Y_MODIFY(val) bfin_write16(MDMA1_S1_Y_MODIFY, val)
+#define bfin_read_MDMA1_S1_CURR_DESC_PTR() bfin_readPTR(MDMA1_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA1_S1_CURR_DESC_PTR(val) bfin_writePTR(MDMA1_S1_CURR_DESC_PTR, val)
+#define bfin_read_MDMA1_S1_CURR_ADDR() bfin_readPTR(MDMA1_S1_CURR_ADDR)
+#define bfin_write_MDMA1_S1_CURR_ADDR(val) bfin_writePTR(MDMA1_S1_CURR_ADDR, val)
+#define bfin_read_MDMA1_S1_IRQ_STATUS() bfin_read16(MDMA1_S1_IRQ_STATUS)
+#define bfin_write_MDMA1_S1_IRQ_STATUS(val) bfin_write16(MDMA1_S1_IRQ_STATUS, val)
+#define bfin_read_MDMA1_S1_PERIPHERAL_MAP() bfin_read16(MDMA1_S1_PERIPHERAL_MAP)
+#define bfin_write_MDMA1_S1_PERIPHERAL_MAP(val) bfin_write16(MDMA1_S1_PERIPHERAL_MAP, val)
+#define bfin_read_MDMA1_S1_CURR_X_COUNT() bfin_read16(MDMA1_S1_CURR_X_COUNT)
+#define bfin_write_MDMA1_S1_CURR_X_COUNT(val) bfin_write16(MDMA1_S1_CURR_X_COUNT, val)
+#define bfin_read_MDMA1_S1_CURR_Y_COUNT() bfin_read16(MDMA1_S1_CURR_Y_COUNT)
+#define bfin_write_MDMA1_S1_CURR_Y_COUNT(val) bfin_write16(MDMA1_S1_CURR_Y_COUNT, val)
+#define bfin_read_PPI_CONTROL() bfin_read16(PPI_CONTROL)
+#define bfin_write_PPI_CONTROL(val) bfin_write16(PPI_CONTROL, val)
+#define bfin_read_PPI_STATUS() bfin_read16(PPI_STATUS)
+#define bfin_write_PPI_STATUS(val) bfin_write16(PPI_STATUS, val)
+#define bfin_read_PPI_DELAY() bfin_read16(PPI_DELAY)
+#define bfin_write_PPI_DELAY(val) bfin_write16(PPI_DELAY, val)
+#define bfin_read_PPI_COUNT() bfin_read16(PPI_COUNT)
+#define bfin_write_PPI_COUNT(val) bfin_write16(PPI_COUNT, val)
+#define bfin_read_PPI_FRAME() bfin_read16(PPI_FRAME)
+#define bfin_write_PPI_FRAME(val) bfin_write16(PPI_FRAME, val)
+#define bfin_read_TWI0_CLKDIV() bfin_read16(TWI0_CLKDIV)
+#define bfin_write_TWI0_CLKDIV(val) bfin_write16(TWI0_CLKDIV, val)
+#define bfin_read_TWI0_CONTROL() bfin_read16(TWI0_CONTROL)
+#define bfin_write_TWI0_CONTROL(val) bfin_write16(TWI0_CONTROL, val)
+#define bfin_read_TWI0_SLAVE_CTRL() bfin_read16(TWI0_SLAVE_CTRL)
+#define bfin_write_TWI0_SLAVE_CTRL(val) bfin_write16(TWI0_SLAVE_CTRL, val)
+#define bfin_read_TWI0_SLAVE_STAT() bfin_read16(TWI0_SLAVE_STAT)
+#define bfin_write_TWI0_SLAVE_STAT(val) bfin_write16(TWI0_SLAVE_STAT, val)
+#define bfin_read_TWI0_SLAVE_ADDR() bfin_read16(TWI0_SLAVE_ADDR)
+#define bfin_write_TWI0_SLAVE_ADDR(val) bfin_write16(TWI0_SLAVE_ADDR, val)
+#define bfin_read_TWI0_MASTER_CTL() bfin_read16(TWI0_MASTER_CTL)
+#define bfin_write_TWI0_MASTER_CTL(val) bfin_write16(TWI0_MASTER_CTL, val)
+#define bfin_read_TWI0_MASTER_STAT() bfin_read16(TWI0_MASTER_STAT)
+#define bfin_write_TWI0_MASTER_STAT(val) bfin_write16(TWI0_MASTER_STAT, val)
+#define bfin_read_TWI0_MASTER_ADDR() bfin_read16(TWI0_MASTER_ADDR)
+#define bfin_write_TWI0_MASTER_ADDR(val) bfin_write16(TWI0_MASTER_ADDR, val)
+#define bfin_read_TWI0_INT_STAT() bfin_read16(TWI0_INT_STAT)
+#define bfin_write_TWI0_INT_STAT(val) bfin_write16(TWI0_INT_STAT, val)
+#define bfin_read_TWI0_INT_MASK() bfin_read16(TWI0_INT_MASK)
+#define bfin_write_TWI0_INT_MASK(val) bfin_write16(TWI0_INT_MASK, val)
+#define bfin_read_TWI0_FIFO_CTL() bfin_read16(TWI0_FIFO_CTL)
+#define bfin_write_TWI0_FIFO_CTL(val) bfin_write16(TWI0_FIFO_CTL, val)
+#define bfin_read_TWI0_FIFO_STAT() bfin_read16(TWI0_FIFO_STAT)
+#define bfin_write_TWI0_FIFO_STAT(val) bfin_write16(TWI0_FIFO_STAT, val)
+#define bfin_read_TWI0_XMT_DATA8() bfin_read16(TWI0_XMT_DATA8)
+#define bfin_write_TWI0_XMT_DATA8(val) bfin_write16(TWI0_XMT_DATA8, val)
+#define bfin_read_TWI0_XMT_DATA16() bfin_read16(TWI0_XMT_DATA16)
+#define bfin_write_TWI0_XMT_DATA16(val) bfin_write16(TWI0_XMT_DATA16, val)
+#define bfin_read_TWI0_RCV_DATA8() bfin_read16(TWI0_RCV_DATA8)
+#define bfin_write_TWI0_RCV_DATA8(val) bfin_write16(TWI0_RCV_DATA8, val)
+#define bfin_read_TWI0_RCV_DATA16() bfin_read16(TWI0_RCV_DATA16)
+#define bfin_write_TWI0_RCV_DATA16(val) bfin_write16(TWI0_RCV_DATA16, val)
+#define bfin_read_TWI1_CLKDIV() bfin_read16(TWI1_CLKDIV)
+#define bfin_write_TWI1_CLKDIV(val) bfin_write16(TWI1_CLKDIV, val)
+#define bfin_read_TWI1_CONTROL() bfin_read16(TWI1_CONTROL)
+#define bfin_write_TWI1_CONTROL(val) bfin_write16(TWI1_CONTROL, val)
+#define bfin_read_TWI1_SLAVE_CTRL() bfin_read16(TWI1_SLAVE_CTRL)
+#define bfin_write_TWI1_SLAVE_CTRL(val) bfin_write16(TWI1_SLAVE_CTRL, val)
+#define bfin_read_TWI1_SLAVE_STAT() bfin_read16(TWI1_SLAVE_STAT)
+#define bfin_write_TWI1_SLAVE_STAT(val) bfin_write16(TWI1_SLAVE_STAT, val)
+#define bfin_read_TWI1_SLAVE_ADDR() bfin_read16(TWI1_SLAVE_ADDR)
+#define bfin_write_TWI1_SLAVE_ADDR(val) bfin_write16(TWI1_SLAVE_ADDR, val)
+#define bfin_read_TWI1_MASTER_CTL() bfin_read16(TWI1_MASTER_CTL)
+#define bfin_write_TWI1_MASTER_CTL(val) bfin_write16(TWI1_MASTER_CTL, val)
+#define bfin_read_TWI1_MASTER_STAT() bfin_read16(TWI1_MASTER_STAT)
+#define bfin_write_TWI1_MASTER_STAT(val) bfin_write16(TWI1_MASTER_STAT, val)
+#define bfin_read_TWI1_MASTER_ADDR() bfin_read16(TWI1_MASTER_ADDR)
+#define bfin_write_TWI1_MASTER_ADDR(val) bfin_write16(TWI1_MASTER_ADDR, val)
+#define bfin_read_TWI1_INT_STAT() bfin_read16(TWI1_INT_STAT)
+#define bfin_write_TWI1_INT_STAT(val) bfin_write16(TWI1_INT_STAT, val)
+#define bfin_read_TWI1_INT_MASK() bfin_read16(TWI1_INT_MASK)
+#define bfin_write_TWI1_INT_MASK(val) bfin_write16(TWI1_INT_MASK, val)
+#define bfin_read_TWI1_FIFO_CTL() bfin_read16(TWI1_FIFO_CTL)
+#define bfin_write_TWI1_FIFO_CTL(val) bfin_write16(TWI1_FIFO_CTL, val)
+#define bfin_read_TWI1_FIFO_STAT() bfin_read16(TWI1_FIFO_STAT)
+#define bfin_write_TWI1_FIFO_STAT(val) bfin_write16(TWI1_FIFO_STAT, val)
+#define bfin_read_TWI1_XMT_DATA8() bfin_read16(TWI1_XMT_DATA8)
+#define bfin_write_TWI1_XMT_DATA8(val) bfin_write16(TWI1_XMT_DATA8, val)
+#define bfin_read_TWI1_XMT_DATA16() bfin_read16(TWI1_XMT_DATA16)
+#define bfin_write_TWI1_XMT_DATA16(val) bfin_write16(TWI1_XMT_DATA16, val)
+#define bfin_read_TWI1_RCV_DATA8() bfin_read16(TWI1_RCV_DATA8)
+#define bfin_write_TWI1_RCV_DATA8(val) bfin_write16(TWI1_RCV_DATA8, val)
+#define bfin_read_TWI1_RCV_DATA16() bfin_read16(TWI1_RCV_DATA16)
+#define bfin_write_TWI1_RCV_DATA16(val) bfin_write16(TWI1_RCV_DATA16, val)
+#define bfin_read_CAN_MC1() bfin_read16(CAN_MC1)
+#define bfin_write_CAN_MC1(val) bfin_write16(CAN_MC1, val)
+#define bfin_read_CAN_MD1() bfin_read16(CAN_MD1)
+#define bfin_write_CAN_MD1(val) bfin_write16(CAN_MD1, val)
+#define bfin_read_CAN_TRS1() bfin_read16(CAN_TRS1)
+#define bfin_write_CAN_TRS1(val) bfin_write16(CAN_TRS1, val)
+#define bfin_read_CAN_TRR1() bfin_read16(CAN_TRR1)
+#define bfin_write_CAN_TRR1(val) bfin_write16(CAN_TRR1, val)
+#define bfin_read_CAN_TA1() bfin_read16(CAN_TA1)
+#define bfin_write_CAN_TA1(val) bfin_write16(CAN_TA1, val)
+#define bfin_read_CAN_AA1() bfin_read16(CAN_AA1)
+#define bfin_write_CAN_AA1(val) bfin_write16(CAN_AA1, val)
+#define bfin_read_CAN_RMP1() bfin_read16(CAN_RMP1)
+#define bfin_write_CAN_RMP1(val) bfin_write16(CAN_RMP1, val)
+#define bfin_read_CAN_RML1() bfin_read16(CAN_RML1)
+#define bfin_write_CAN_RML1(val) bfin_write16(CAN_RML1, val)
+#define bfin_read_CAN_MBTIF1() bfin_read16(CAN_MBTIF1)
+#define bfin_write_CAN_MBTIF1(val) bfin_write16(CAN_MBTIF1, val)
+#define bfin_read_CAN_MBRIF1() bfin_read16(CAN_MBRIF1)
+#define bfin_write_CAN_MBRIF1(val) bfin_write16(CAN_MBRIF1, val)
+#define bfin_read_CAN_MBIM1() bfin_read16(CAN_MBIM1)
+#define bfin_write_CAN_MBIM1(val) bfin_write16(CAN_MBIM1, val)
+#define bfin_read_CAN_RFH1() bfin_read16(CAN_RFH1)
+#define bfin_write_CAN_RFH1(val) bfin_write16(CAN_RFH1, val)
+#define bfin_read_CAN_OPSS1() bfin_read16(CAN_OPSS1)
+#define bfin_write_CAN_OPSS1(val) bfin_write16(CAN_OPSS1, val)
+#define bfin_read_CAN_MC2() bfin_read16(CAN_MC2)
+#define bfin_write_CAN_MC2(val) bfin_write16(CAN_MC2, val)
+#define bfin_read_CAN_MD2() bfin_read16(CAN_MD2)
+#define bfin_write_CAN_MD2(val) bfin_write16(CAN_MD2, val)
+#define bfin_read_CAN_TRS2() bfin_read16(CAN_TRS2)
+#define bfin_write_CAN_TRS2(val) bfin_write16(CAN_TRS2, val)
+#define bfin_read_CAN_TRR2() bfin_read16(CAN_TRR2)
+#define bfin_write_CAN_TRR2(val) bfin_write16(CAN_TRR2, val)
+#define bfin_read_CAN_TA2() bfin_read16(CAN_TA2)
+#define bfin_write_CAN_TA2(val) bfin_write16(CAN_TA2, val)
+#define bfin_read_CAN_AA2() bfin_read16(CAN_AA2)
+#define bfin_write_CAN_AA2(val) bfin_write16(CAN_AA2, val)
+#define bfin_read_CAN_RMP2() bfin_read16(CAN_RMP2)
+#define bfin_write_CAN_RMP2(val) bfin_write16(CAN_RMP2, val)
+#define bfin_read_CAN_RML2() bfin_read16(CAN_RML2)
+#define bfin_write_CAN_RML2(val) bfin_write16(CAN_RML2, val)
+#define bfin_read_CAN_MBTIF2() bfin_read16(CAN_MBTIF2)
+#define bfin_write_CAN_MBTIF2(val) bfin_write16(CAN_MBTIF2, val)
+#define bfin_read_CAN_MBRIF2() bfin_read16(CAN_MBRIF2)
+#define bfin_write_CAN_MBRIF2(val) bfin_write16(CAN_MBRIF2, val)
+#define bfin_read_CAN_MBIM2() bfin_read16(CAN_MBIM2)
+#define bfin_write_CAN_MBIM2(val) bfin_write16(CAN_MBIM2, val)
+#define bfin_read_CAN_RFH2() bfin_read16(CAN_RFH2)
+#define bfin_write_CAN_RFH2(val) bfin_write16(CAN_RFH2, val)
+#define bfin_read_CAN_OPSS2() bfin_read16(CAN_OPSS2)
+#define bfin_write_CAN_OPSS2(val) bfin_write16(CAN_OPSS2, val)
+#define bfin_read_CAN_CLOCK() bfin_read16(CAN_CLOCK)
+#define bfin_write_CAN_CLOCK(val) bfin_write16(CAN_CLOCK, val)
+#define bfin_read_CAN_TIMING() bfin_read16(CAN_TIMING)
+#define bfin_write_CAN_TIMING(val) bfin_write16(CAN_TIMING, val)
+#define bfin_read_CAN_DEBUG() bfin_read16(CAN_DEBUG)
+#define bfin_write_CAN_DEBUG(val) bfin_write16(CAN_DEBUG, val)
+#define bfin_read_CAN_STATUS() bfin_read16(CAN_STATUS)
+#define bfin_write_CAN_STATUS(val) bfin_write16(CAN_STATUS, val)
+#define bfin_read_CAN_CEC() bfin_read16(CAN_CEC)
+#define bfin_write_CAN_CEC(val) bfin_write16(CAN_CEC, val)
+#define bfin_read_CAN_GIS() bfin_read16(CAN_GIS)
+#define bfin_write_CAN_GIS(val) bfin_write16(CAN_GIS, val)
+#define bfin_read_CAN_GIM() bfin_read16(CAN_GIM)
+#define bfin_write_CAN_GIM(val) bfin_write16(CAN_GIM, val)
+#define bfin_read_CAN_GIF() bfin_read16(CAN_GIF)
+#define bfin_write_CAN_GIF(val) bfin_write16(CAN_GIF, val)
+#define bfin_read_CAN_CONTROL() bfin_read16(CAN_CONTROL)
+#define bfin_write_CAN_CONTROL(val) bfin_write16(CAN_CONTROL, val)
+#define bfin_read_CAN_INTR() bfin_read16(CAN_INTR)
+#define bfin_write_CAN_INTR(val) bfin_write16(CAN_INTR, val)
+#define bfin_read_CAN_VERSION() bfin_read16(CAN_VERSION)
+#define bfin_write_CAN_VERSION(val) bfin_write16(CAN_VERSION, val)
+#define bfin_read_CAN_MBTD() bfin_read16(CAN_MBTD)
+#define bfin_write_CAN_MBTD(val) bfin_write16(CAN_MBTD, val)
+#define bfin_read_CAN_EWR() bfin_read16(CAN_EWR)
+#define bfin_write_CAN_EWR(val) bfin_write16(CAN_EWR, val)
+#define bfin_read_CAN_ESR() bfin_read16(CAN_ESR)
+#define bfin_write_CAN_ESR(val) bfin_write16(CAN_ESR, val)
+#define bfin_read_CAN_UCREG() bfin_read16(CAN_UCREG)
+#define bfin_write_CAN_UCREG(val) bfin_write16(CAN_UCREG, val)
+#define bfin_read_CAN_UCCNT() bfin_read16(CAN_UCCNT)
+#define bfin_write_CAN_UCCNT(val) bfin_write16(CAN_UCCNT, val)
+#define bfin_read_CAN_UCRC() bfin_read16(CAN_UCRC)
+#define bfin_write_CAN_UCRC(val) bfin_write16(CAN_UCRC, val)
+#define bfin_read_CAN_UCCNF() bfin_read16(CAN_UCCNF)
+#define bfin_write_CAN_UCCNF(val) bfin_write16(CAN_UCCNF, val)
+#define bfin_read_CAN_VERSION2() bfin_read16(CAN_VERSION2)
+#define bfin_write_CAN_VERSION2(val) bfin_write16(CAN_VERSION2, val)
+#define bfin_read_CAN_AM00L() bfin_read16(CAN_AM00L)
+#define bfin_write_CAN_AM00L(val) bfin_write16(CAN_AM00L, val)
+#define bfin_read_CAN_AM00H() bfin_read16(CAN_AM00H)
+#define bfin_write_CAN_AM00H(val) bfin_write16(CAN_AM00H, val)
+#define bfin_read_CAN_AM01L() bfin_read16(CAN_AM01L)
+#define bfin_write_CAN_AM01L(val) bfin_write16(CAN_AM01L, val)
+#define bfin_read_CAN_AM01H() bfin_read16(CAN_AM01H)
+#define bfin_write_CAN_AM01H(val) bfin_write16(CAN_AM01H, val)
+#define bfin_read_CAN_AM02L() bfin_read16(CAN_AM02L)
+#define bfin_write_CAN_AM02L(val) bfin_write16(CAN_AM02L, val)
+#define bfin_read_CAN_AM02H() bfin_read16(CAN_AM02H)
+#define bfin_write_CAN_AM02H(val) bfin_write16(CAN_AM02H, val)
+#define bfin_read_CAN_AM03L() bfin_read16(CAN_AM03L)
+#define bfin_write_CAN_AM03L(val) bfin_write16(CAN_AM03L, val)
+#define bfin_read_CAN_AM03H() bfin_read16(CAN_AM03H)
+#define bfin_write_CAN_AM03H(val) bfin_write16(CAN_AM03H, val)
+#define bfin_read_CAN_AM04L() bfin_read16(CAN_AM04L)
+#define bfin_write_CAN_AM04L(val) bfin_write16(CAN_AM04L, val)
+#define bfin_read_CAN_AM04H() bfin_read16(CAN_AM04H)
+#define bfin_write_CAN_AM04H(val) bfin_write16(CAN_AM04H, val)
+#define bfin_read_CAN_AM05L() bfin_read16(CAN_AM05L)
+#define bfin_write_CAN_AM05L(val) bfin_write16(CAN_AM05L, val)
+#define bfin_read_CAN_AM05H() bfin_read16(CAN_AM05H)
+#define bfin_write_CAN_AM05H(val) bfin_write16(CAN_AM05H, val)
+#define bfin_read_CAN_AM06L() bfin_read16(CAN_AM06L)
+#define bfin_write_CAN_AM06L(val) bfin_write16(CAN_AM06L, val)
+#define bfin_read_CAN_AM06H() bfin_read16(CAN_AM06H)
+#define bfin_write_CAN_AM06H(val) bfin_write16(CAN_AM06H, val)
+#define bfin_read_CAN_AM07L() bfin_read16(CAN_AM07L)
+#define bfin_write_CAN_AM07L(val) bfin_write16(CAN_AM07L, val)
+#define bfin_read_CAN_AM07H() bfin_read16(CAN_AM07H)
+#define bfin_write_CAN_AM07H(val) bfin_write16(CAN_AM07H, val)
+#define bfin_read_CAN_AM08L() bfin_read16(CAN_AM08L)
+#define bfin_write_CAN_AM08L(val) bfin_write16(CAN_AM08L, val)
+#define bfin_read_CAN_AM08H() bfin_read16(CAN_AM08H)
+#define bfin_write_CAN_AM08H(val) bfin_write16(CAN_AM08H, val)
+#define bfin_read_CAN_AM09L() bfin_read16(CAN_AM09L)
+#define bfin_write_CAN_AM09L(val) bfin_write16(CAN_AM09L, val)
+#define bfin_read_CAN_AM09H() bfin_read16(CAN_AM09H)
+#define bfin_write_CAN_AM09H(val) bfin_write16(CAN_AM09H, val)
+#define bfin_read_CAN_AM10L() bfin_read16(CAN_AM10L)
+#define bfin_write_CAN_AM10L(val) bfin_write16(CAN_AM10L, val)
+#define bfin_read_CAN_AM10H() bfin_read16(CAN_AM10H)
+#define bfin_write_CAN_AM10H(val) bfin_write16(CAN_AM10H, val)
+#define bfin_read_CAN_AM11L() bfin_read16(CAN_AM11L)
+#define bfin_write_CAN_AM11L(val) bfin_write16(CAN_AM11L, val)
+#define bfin_read_CAN_AM11H() bfin_read16(CAN_AM11H)
+#define bfin_write_CAN_AM11H(val) bfin_write16(CAN_AM11H, val)
+#define bfin_read_CAN_AM12L() bfin_read16(CAN_AM12L)
+#define bfin_write_CAN_AM12L(val) bfin_write16(CAN_AM12L, val)
+#define bfin_read_CAN_AM12H() bfin_read16(CAN_AM12H)
+#define bfin_write_CAN_AM12H(val) bfin_write16(CAN_AM12H, val)
+#define bfin_read_CAN_AM13L() bfin_read16(CAN_AM13L)
+#define bfin_write_CAN_AM13L(val) bfin_write16(CAN_AM13L, val)
+#define bfin_read_CAN_AM13H() bfin_read16(CAN_AM13H)
+#define bfin_write_CAN_AM13H(val) bfin_write16(CAN_AM13H, val)
+#define bfin_read_CAN_AM14L() bfin_read16(CAN_AM14L)
+#define bfin_write_CAN_AM14L(val) bfin_write16(CAN_AM14L, val)
+#define bfin_read_CAN_AM14H() bfin_read16(CAN_AM14H)
+#define bfin_write_CAN_AM14H(val) bfin_write16(CAN_AM14H, val)
+#define bfin_read_CAN_AM15L() bfin_read16(CAN_AM15L)
+#define bfin_write_CAN_AM15L(val) bfin_write16(CAN_AM15L, val)
+#define bfin_read_CAN_AM15H() bfin_read16(CAN_AM15H)
+#define bfin_write_CAN_AM15H(val) bfin_write16(CAN_AM15H, val)
+#define bfin_read_CAN_AM16L() bfin_read16(CAN_AM16L)
+#define bfin_write_CAN_AM16L(val) bfin_write16(CAN_AM16L, val)
+#define bfin_read_CAN_AM16H() bfin_read16(CAN_AM16H)
+#define bfin_write_CAN_AM16H(val) bfin_write16(CAN_AM16H, val)
+#define bfin_read_CAN_AM17L() bfin_read16(CAN_AM17L)
+#define bfin_write_CAN_AM17L(val) bfin_write16(CAN_AM17L, val)
+#define bfin_read_CAN_AM17H() bfin_read16(CAN_AM17H)
+#define bfin_write_CAN_AM17H(val) bfin_write16(CAN_AM17H, val)
+#define bfin_read_CAN_AM18L() bfin_read16(CAN_AM18L)
+#define bfin_write_CAN_AM18L(val) bfin_write16(CAN_AM18L, val)
+#define bfin_read_CAN_AM18H() bfin_read16(CAN_AM18H)
+#define bfin_write_CAN_AM18H(val) bfin_write16(CAN_AM18H, val)
+#define bfin_read_CAN_AM19L() bfin_read16(CAN_AM19L)
+#define bfin_write_CAN_AM19L(val) bfin_write16(CAN_AM19L, val)
+#define bfin_read_CAN_AM19H() bfin_read16(CAN_AM19H)
+#define bfin_write_CAN_AM19H(val) bfin_write16(CAN_AM19H, val)
+#define bfin_read_CAN_AM20L() bfin_read16(CAN_AM20L)
+#define bfin_write_CAN_AM20L(val) bfin_write16(CAN_AM20L, val)
+#define bfin_read_CAN_AM20H() bfin_read16(CAN_AM20H)
+#define bfin_write_CAN_AM20H(val) bfin_write16(CAN_AM20H, val)
+#define bfin_read_CAN_AM21L() bfin_read16(CAN_AM21L)
+#define bfin_write_CAN_AM21L(val) bfin_write16(CAN_AM21L, val)
+#define bfin_read_CAN_AM21H() bfin_read16(CAN_AM21H)
+#define bfin_write_CAN_AM21H(val) bfin_write16(CAN_AM21H, val)
+#define bfin_read_CAN_AM22L() bfin_read16(CAN_AM22L)
+#define bfin_write_CAN_AM22L(val) bfin_write16(CAN_AM22L, val)
+#define bfin_read_CAN_AM22H() bfin_read16(CAN_AM22H)
+#define bfin_write_CAN_AM22H(val) bfin_write16(CAN_AM22H, val)
+#define bfin_read_CAN_AM23L() bfin_read16(CAN_AM23L)
+#define bfin_write_CAN_AM23L(val) bfin_write16(CAN_AM23L, val)
+#define bfin_read_CAN_AM23H() bfin_read16(CAN_AM23H)
+#define bfin_write_CAN_AM23H(val) bfin_write16(CAN_AM23H, val)
+#define bfin_read_CAN_AM24L() bfin_read16(CAN_AM24L)
+#define bfin_write_CAN_AM24L(val) bfin_write16(CAN_AM24L, val)
+#define bfin_read_CAN_AM24H() bfin_read16(CAN_AM24H)
+#define bfin_write_CAN_AM24H(val) bfin_write16(CAN_AM24H, val)
+#define bfin_read_CAN_AM25L() bfin_read16(CAN_AM25L)
+#define bfin_write_CAN_AM25L(val) bfin_write16(CAN_AM25L, val)
+#define bfin_read_CAN_AM25H() bfin_read16(CAN_AM25H)
+#define bfin_write_CAN_AM25H(val) bfin_write16(CAN_AM25H, val)
+#define bfin_read_CAN_AM26L() bfin_read16(CAN_AM26L)
+#define bfin_write_CAN_AM26L(val) bfin_write16(CAN_AM26L, val)
+#define bfin_read_CAN_AM26H() bfin_read16(CAN_AM26H)
+#define bfin_write_CAN_AM26H(val) bfin_write16(CAN_AM26H, val)
+#define bfin_read_CAN_AM27L() bfin_read16(CAN_AM27L)
+#define bfin_write_CAN_AM27L(val) bfin_write16(CAN_AM27L, val)
+#define bfin_read_CAN_AM27H() bfin_read16(CAN_AM27H)
+#define bfin_write_CAN_AM27H(val) bfin_write16(CAN_AM27H, val)
+#define bfin_read_CAN_AM28L() bfin_read16(CAN_AM28L)
+#define bfin_write_CAN_AM28L(val) bfin_write16(CAN_AM28L, val)
+#define bfin_read_CAN_AM28H() bfin_read16(CAN_AM28H)
+#define bfin_write_CAN_AM28H(val) bfin_write16(CAN_AM28H, val)
+#define bfin_read_CAN_AM29L() bfin_read16(CAN_AM29L)
+#define bfin_write_CAN_AM29L(val) bfin_write16(CAN_AM29L, val)
+#define bfin_read_CAN_AM29H() bfin_read16(CAN_AM29H)
+#define bfin_write_CAN_AM29H(val) bfin_write16(CAN_AM29H, val)
+#define bfin_read_CAN_AM30L() bfin_read16(CAN_AM30L)
+#define bfin_write_CAN_AM30L(val) bfin_write16(CAN_AM30L, val)
+#define bfin_read_CAN_AM30H() bfin_read16(CAN_AM30H)
+#define bfin_write_CAN_AM30H(val) bfin_write16(CAN_AM30H, val)
+#define bfin_read_CAN_AM31L() bfin_read16(CAN_AM31L)
+#define bfin_write_CAN_AM31L(val) bfin_write16(CAN_AM31L, val)
+#define bfin_read_CAN_AM31H() bfin_read16(CAN_AM31H)
+#define bfin_write_CAN_AM31H(val) bfin_write16(CAN_AM31H, val)
+#define bfin_read_CAN_MB00_DATA0() bfin_read16(CAN_MB00_DATA0)
+#define bfin_write_CAN_MB00_DATA0(val) bfin_write16(CAN_MB00_DATA0, val)
+#define bfin_read_CAN_MB00_DATA1() bfin_read16(CAN_MB00_DATA1)
+#define bfin_write_CAN_MB00_DATA1(val) bfin_write16(CAN_MB00_DATA1, val)
+#define bfin_read_CAN_MB00_DATA2() bfin_read16(CAN_MB00_DATA2)
+#define bfin_write_CAN_MB00_DATA2(val) bfin_write16(CAN_MB00_DATA2, val)
+#define bfin_read_CAN_MB00_DATA3() bfin_read16(CAN_MB00_DATA3)
+#define bfin_write_CAN_MB00_DATA3(val) bfin_write16(CAN_MB00_DATA3, val)
+#define bfin_read_CAN_MB00_LENGTH() bfin_read16(CAN_MB00_LENGTH)
+#define bfin_write_CAN_MB00_LENGTH(val) bfin_write16(CAN_MB00_LENGTH, val)
+#define bfin_read_CAN_MB00_TIMESTAMP() bfin_read16(CAN_MB00_TIMESTAMP)
+#define bfin_write_CAN_MB00_TIMESTAMP(val) bfin_write16(CAN_MB00_TIMESTAMP, val)
+#define bfin_read_CAN_MB00_ID0() bfin_read16(CAN_MB00_ID0)
+#define bfin_write_CAN_MB00_ID0(val) bfin_write16(CAN_MB00_ID0, val)
+#define bfin_read_CAN_MB00_ID1() bfin_read16(CAN_MB00_ID1)
+#define bfin_write_CAN_MB00_ID1(val) bfin_write16(CAN_MB00_ID1, val)
+#define bfin_read_CAN_MB01_DATA0() bfin_read16(CAN_MB01_DATA0)
+#define bfin_write_CAN_MB01_DATA0(val) bfin_write16(CAN_MB01_DATA0, val)
+#define bfin_read_CAN_MB01_DATA1() bfin_read16(CAN_MB01_DATA1)
+#define bfin_write_CAN_MB01_DATA1(val) bfin_write16(CAN_MB01_DATA1, val)
+#define bfin_read_CAN_MB01_DATA2() bfin_read16(CAN_MB01_DATA2)
+#define bfin_write_CAN_MB01_DATA2(val) bfin_write16(CAN_MB01_DATA2, val)
+#define bfin_read_CAN_MB01_DATA3() bfin_read16(CAN_MB01_DATA3)
+#define bfin_write_CAN_MB01_DATA3(val) bfin_write16(CAN_MB01_DATA3, val)
+#define bfin_read_CAN_MB01_LENGTH() bfin_read16(CAN_MB01_LENGTH)
+#define bfin_write_CAN_MB01_LENGTH(val) bfin_write16(CAN_MB01_LENGTH, val)
+#define bfin_read_CAN_MB01_TIMESTAMP() bfin_read16(CAN_MB01_TIMESTAMP)
+#define bfin_write_CAN_MB01_TIMESTAMP(val) bfin_write16(CAN_MB01_TIMESTAMP, val)
+#define bfin_read_CAN_MB01_ID0() bfin_read16(CAN_MB01_ID0)
+#define bfin_write_CAN_MB01_ID0(val) bfin_write16(CAN_MB01_ID0, val)
+#define bfin_read_CAN_MB01_ID1() bfin_read16(CAN_MB01_ID1)
+#define bfin_write_CAN_MB01_ID1(val) bfin_write16(CAN_MB01_ID1, val)
+#define bfin_read_CAN_MB02_DATA0() bfin_read16(CAN_MB02_DATA0)
+#define bfin_write_CAN_MB02_DATA0(val) bfin_write16(CAN_MB02_DATA0, val)
+#define bfin_read_CAN_MB02_DATA1() bfin_read16(CAN_MB02_DATA1)
+#define bfin_write_CAN_MB02_DATA1(val) bfin_write16(CAN_MB02_DATA1, val)
+#define bfin_read_CAN_MB02_DATA2() bfin_read16(CAN_MB02_DATA2)
+#define bfin_write_CAN_MB02_DATA2(val) bfin_write16(CAN_MB02_DATA2, val)
+#define bfin_read_CAN_MB02_DATA3() bfin_read16(CAN_MB02_DATA3)
+#define bfin_write_CAN_MB02_DATA3(val) bfin_write16(CAN_MB02_DATA3, val)
+#define bfin_read_CAN_MB02_LENGTH() bfin_read16(CAN_MB02_LENGTH)
+#define bfin_write_CAN_MB02_LENGTH(val) bfin_write16(CAN_MB02_LENGTH, val)
+#define bfin_read_CAN_MB02_TIMESTAMP() bfin_read16(CAN_MB02_TIMESTAMP)
+#define bfin_write_CAN_MB02_TIMESTAMP(val) bfin_write16(CAN_MB02_TIMESTAMP, val)
+#define bfin_read_CAN_MB02_ID0() bfin_read16(CAN_MB02_ID0)
+#define bfin_write_CAN_MB02_ID0(val) bfin_write16(CAN_MB02_ID0, val)
+#define bfin_read_CAN_MB02_ID1() bfin_read16(CAN_MB02_ID1)
+#define bfin_write_CAN_MB02_ID1(val) bfin_write16(CAN_MB02_ID1, val)
+#define bfin_read_CAN_MB03_DATA0() bfin_read16(CAN_MB03_DATA0)
+#define bfin_write_CAN_MB03_DATA0(val) bfin_write16(CAN_MB03_DATA0, val)
+#define bfin_read_CAN_MB03_DATA1() bfin_read16(CAN_MB03_DATA1)
+#define bfin_write_CAN_MB03_DATA1(val) bfin_write16(CAN_MB03_DATA1, val)
+#define bfin_read_CAN_MB03_DATA2() bfin_read16(CAN_MB03_DATA2)
+#define bfin_write_CAN_MB03_DATA2(val) bfin_write16(CAN_MB03_DATA2, val)
+#define bfin_read_CAN_MB03_DATA3() bfin_read16(CAN_MB03_DATA3)
+#define bfin_write_CAN_MB03_DATA3(val) bfin_write16(CAN_MB03_DATA3, val)
+#define bfin_read_CAN_MB03_LENGTH() bfin_read16(CAN_MB03_LENGTH)
+#define bfin_write_CAN_MB03_LENGTH(val) bfin_write16(CAN_MB03_LENGTH, val)
+#define bfin_read_CAN_MB03_TIMESTAMP() bfin_read16(CAN_MB03_TIMESTAMP)
+#define bfin_write_CAN_MB03_TIMESTAMP(val) bfin_write16(CAN_MB03_TIMESTAMP, val)
+#define bfin_read_CAN_MB03_ID0() bfin_read16(CAN_MB03_ID0)
+#define bfin_write_CAN_MB03_ID0(val) bfin_write16(CAN_MB03_ID0, val)
+#define bfin_read_CAN_MB03_ID1() bfin_read16(CAN_MB03_ID1)
+#define bfin_write_CAN_MB03_ID1(val) bfin_write16(CAN_MB03_ID1, val)
+#define bfin_read_CAN_MB04_DATA0() bfin_read16(CAN_MB04_DATA0)
+#define bfin_write_CAN_MB04_DATA0(val) bfin_write16(CAN_MB04_DATA0, val)
+#define bfin_read_CAN_MB04_DATA1() bfin_read16(CAN_MB04_DATA1)
+#define bfin_write_CAN_MB04_DATA1(val) bfin_write16(CAN_MB04_DATA1, val)
+#define bfin_read_CAN_MB04_DATA2() bfin_read16(CAN_MB04_DATA2)
+#define bfin_write_CAN_MB04_DATA2(val) bfin_write16(CAN_MB04_DATA2, val)
+#define bfin_read_CAN_MB04_DATA3() bfin_read16(CAN_MB04_DATA3)
+#define bfin_write_CAN_MB04_DATA3(val) bfin_write16(CAN_MB04_DATA3, val)
+#define bfin_read_CAN_MB04_LENGTH() bfin_read16(CAN_MB04_LENGTH)
+#define bfin_write_CAN_MB04_LENGTH(val) bfin_write16(CAN_MB04_LENGTH, val)
+#define bfin_read_CAN_MB04_TIMESTAMP() bfin_read16(CAN_MB04_TIMESTAMP)
+#define bfin_write_CAN_MB04_TIMESTAMP(val) bfin_write16(CAN_MB04_TIMESTAMP, val)
+#define bfin_read_CAN_MB04_ID0() bfin_read16(CAN_MB04_ID0)
+#define bfin_write_CAN_MB04_ID0(val) bfin_write16(CAN_MB04_ID0, val)
+#define bfin_read_CAN_MB04_ID1() bfin_read16(CAN_MB04_ID1)
+#define bfin_write_CAN_MB04_ID1(val) bfin_write16(CAN_MB04_ID1, val)
+#define bfin_read_CAN_MB05_DATA0() bfin_read16(CAN_MB05_DATA0)
+#define bfin_write_CAN_MB05_DATA0(val) bfin_write16(CAN_MB05_DATA0, val)
+#define bfin_read_CAN_MB05_DATA1() bfin_read16(CAN_MB05_DATA1)
+#define bfin_write_CAN_MB05_DATA1(val) bfin_write16(CAN_MB05_DATA1, val)
+#define bfin_read_CAN_MB05_DATA2() bfin_read16(CAN_MB05_DATA2)
+#define bfin_write_CAN_MB05_DATA2(val) bfin_write16(CAN_MB05_DATA2, val)
+#define bfin_read_CAN_MB05_DATA3() bfin_read16(CAN_MB05_DATA3)
+#define bfin_write_CAN_MB05_DATA3(val) bfin_write16(CAN_MB05_DATA3, val)
+#define bfin_read_CAN_MB05_LENGTH() bfin_read16(CAN_MB05_LENGTH)
+#define bfin_write_CAN_MB05_LENGTH(val) bfin_write16(CAN_MB05_LENGTH, val)
+#define bfin_read_CAN_MB05_TIMESTAMP() bfin_read16(CAN_MB05_TIMESTAMP)
+#define bfin_write_CAN_MB05_TIMESTAMP(val) bfin_write16(CAN_MB05_TIMESTAMP, val)
+#define bfin_read_CAN_MB05_ID0() bfin_read16(CAN_MB05_ID0)
+#define bfin_write_CAN_MB05_ID0(val) bfin_write16(CAN_MB05_ID0, val)
+#define bfin_read_CAN_MB05_ID1() bfin_read16(CAN_MB05_ID1)
+#define bfin_write_CAN_MB05_ID1(val) bfin_write16(CAN_MB05_ID1, val)
+#define bfin_read_CAN_MB06_DATA0() bfin_read16(CAN_MB06_DATA0)
+#define bfin_write_CAN_MB06_DATA0(val) bfin_write16(CAN_MB06_DATA0, val)
+#define bfin_read_CAN_MB06_DATA1() bfin_read16(CAN_MB06_DATA1)
+#define bfin_write_CAN_MB06_DATA1(val) bfin_write16(CAN_MB06_DATA1, val)
+#define bfin_read_CAN_MB06_DATA2() bfin_read16(CAN_MB06_DATA2)
+#define bfin_write_CAN_MB06_DATA2(val) bfin_write16(CAN_MB06_DATA2, val)
+#define bfin_read_CAN_MB06_DATA3() bfin_read16(CAN_MB06_DATA3)
+#define bfin_write_CAN_MB06_DATA3(val) bfin_write16(CAN_MB06_DATA3, val)
+#define bfin_read_CAN_MB06_LENGTH() bfin_read16(CAN_MB06_LENGTH)
+#define bfin_write_CAN_MB06_LENGTH(val) bfin_write16(CAN_MB06_LENGTH, val)
+#define bfin_read_CAN_MB06_TIMESTAMP() bfin_read16(CAN_MB06_TIMESTAMP)
+#define bfin_write_CAN_MB06_TIMESTAMP(val) bfin_write16(CAN_MB06_TIMESTAMP, val)
+#define bfin_read_CAN_MB06_ID0() bfin_read16(CAN_MB06_ID0)
+#define bfin_write_CAN_MB06_ID0(val) bfin_write16(CAN_MB06_ID0, val)
+#define bfin_read_CAN_MB06_ID1() bfin_read16(CAN_MB06_ID1)
+#define bfin_write_CAN_MB06_ID1(val) bfin_write16(CAN_MB06_ID1, val)
+#define bfin_read_CAN_MB07_DATA0() bfin_read16(CAN_MB07_DATA0)
+#define bfin_write_CAN_MB07_DATA0(val) bfin_write16(CAN_MB07_DATA0, val)
+#define bfin_read_CAN_MB07_DATA1() bfin_read16(CAN_MB07_DATA1)
+#define bfin_write_CAN_MB07_DATA1(val) bfin_write16(CAN_MB07_DATA1, val)
+#define bfin_read_CAN_MB07_DATA2() bfin_read16(CAN_MB07_DATA2)
+#define bfin_write_CAN_MB07_DATA2(val) bfin_write16(CAN_MB07_DATA2, val)
+#define bfin_read_CAN_MB07_DATA3() bfin_read16(CAN_MB07_DATA3)
+#define bfin_write_CAN_MB07_DATA3(val) bfin_write16(CAN_MB07_DATA3, val)
+#define bfin_read_CAN_MB07_LENGTH() bfin_read16(CAN_MB07_LENGTH)
+#define bfin_write_CAN_MB07_LENGTH(val) bfin_write16(CAN_MB07_LENGTH, val)
+#define bfin_read_CAN_MB07_TIMESTAMP() bfin_read16(CAN_MB07_TIMESTAMP)
+#define bfin_write_CAN_MB07_TIMESTAMP(val) bfin_write16(CAN_MB07_TIMESTAMP, val)
+#define bfin_read_CAN_MB07_ID0() bfin_read16(CAN_MB07_ID0)
+#define bfin_write_CAN_MB07_ID0(val) bfin_write16(CAN_MB07_ID0, val)
+#define bfin_read_CAN_MB07_ID1() bfin_read16(CAN_MB07_ID1)
+#define bfin_write_CAN_MB07_ID1(val) bfin_write16(CAN_MB07_ID1, val)
+#define bfin_read_CAN_MB08_DATA0() bfin_read16(CAN_MB08_DATA0)
+#define bfin_write_CAN_MB08_DATA0(val) bfin_write16(CAN_MB08_DATA0, val)
+#define bfin_read_CAN_MB08_DATA1() bfin_read16(CAN_MB08_DATA1)
+#define bfin_write_CAN_MB08_DATA1(val) bfin_write16(CAN_MB08_DATA1, val)
+#define bfin_read_CAN_MB08_DATA2() bfin_read16(CAN_MB08_DATA2)
+#define bfin_write_CAN_MB08_DATA2(val) bfin_write16(CAN_MB08_DATA2, val)
+#define bfin_read_CAN_MB08_DATA3() bfin_read16(CAN_MB08_DATA3)
+#define bfin_write_CAN_MB08_DATA3(val) bfin_write16(CAN_MB08_DATA3, val)
+#define bfin_read_CAN_MB08_LENGTH() bfin_read16(CAN_MB08_LENGTH)
+#define bfin_write_CAN_MB08_LENGTH(val) bfin_write16(CAN_MB08_LENGTH, val)
+#define bfin_read_CAN_MB08_TIMESTAMP() bfin_read16(CAN_MB08_TIMESTAMP)
+#define bfin_write_CAN_MB08_TIMESTAMP(val) bfin_write16(CAN_MB08_TIMESTAMP, val)
+#define bfin_read_CAN_MB08_ID0() bfin_read16(CAN_MB08_ID0)
+#define bfin_write_CAN_MB08_ID0(val) bfin_write16(CAN_MB08_ID0, val)
+#define bfin_read_CAN_MB08_ID1() bfin_read16(CAN_MB08_ID1)
+#define bfin_write_CAN_MB08_ID1(val) bfin_write16(CAN_MB08_ID1, val)
+#define bfin_read_CAN_MB09_DATA0() bfin_read16(CAN_MB09_DATA0)
+#define bfin_write_CAN_MB09_DATA0(val) bfin_write16(CAN_MB09_DATA0, val)
+#define bfin_read_CAN_MB09_DATA1() bfin_read16(CAN_MB09_DATA1)
+#define bfin_write_CAN_MB09_DATA1(val) bfin_write16(CAN_MB09_DATA1, val)
+#define bfin_read_CAN_MB09_DATA2() bfin_read16(CAN_MB09_DATA2)
+#define bfin_write_CAN_MB09_DATA2(val) bfin_write16(CAN_MB09_DATA2, val)
+#define bfin_read_CAN_MB09_DATA3() bfin_read16(CAN_MB09_DATA3)
+#define bfin_write_CAN_MB09_DATA3(val) bfin_write16(CAN_MB09_DATA3, val)
+#define bfin_read_CAN_MB09_LENGTH() bfin_read16(CAN_MB09_LENGTH)
+#define bfin_write_CAN_MB09_LENGTH(val) bfin_write16(CAN_MB09_LENGTH, val)
+#define bfin_read_CAN_MB09_TIMESTAMP() bfin_read16(CAN_MB09_TIMESTAMP)
+#define bfin_write_CAN_MB09_TIMESTAMP(val) bfin_write16(CAN_MB09_TIMESTAMP, val)
+#define bfin_read_CAN_MB09_ID0() bfin_read16(CAN_MB09_ID0)
+#define bfin_write_CAN_MB09_ID0(val) bfin_write16(CAN_MB09_ID0, val)
+#define bfin_read_CAN_MB09_ID1() bfin_read16(CAN_MB09_ID1)
+#define bfin_write_CAN_MB09_ID1(val) bfin_write16(CAN_MB09_ID1, val)
+#define bfin_read_CAN_MB10_DATA0() bfin_read16(CAN_MB10_DATA0)
+#define bfin_write_CAN_MB10_DATA0(val) bfin_write16(CAN_MB10_DATA0, val)
+#define bfin_read_CAN_MB10_DATA1() bfin_read16(CAN_MB10_DATA1)
+#define bfin_write_CAN_MB10_DATA1(val) bfin_write16(CAN_MB10_DATA1, val)
+#define bfin_read_CAN_MB10_DATA2() bfin_read16(CAN_MB10_DATA2)
+#define bfin_write_CAN_MB10_DATA2(val) bfin_write16(CAN_MB10_DATA2, val)
+#define bfin_read_CAN_MB10_DATA3() bfin_read16(CAN_MB10_DATA3)
+#define bfin_write_CAN_MB10_DATA3(val) bfin_write16(CAN_MB10_DATA3, val)
+#define bfin_read_CAN_MB10_LENGTH() bfin_read16(CAN_MB10_LENGTH)
+#define bfin_write_CAN_MB10_LENGTH(val) bfin_write16(CAN_MB10_LENGTH, val)
+#define bfin_read_CAN_MB10_TIMESTAMP() bfin_read16(CAN_MB10_TIMESTAMP)
+#define bfin_write_CAN_MB10_TIMESTAMP(val) bfin_write16(CAN_MB10_TIMESTAMP, val)
+#define bfin_read_CAN_MB10_ID0() bfin_read16(CAN_MB10_ID0)
+#define bfin_write_CAN_MB10_ID0(val) bfin_write16(CAN_MB10_ID0, val)
+#define bfin_read_CAN_MB10_ID1() bfin_read16(CAN_MB10_ID1)
+#define bfin_write_CAN_MB10_ID1(val) bfin_write16(CAN_MB10_ID1, val)
+#define bfin_read_CAN_MB11_DATA0() bfin_read16(CAN_MB11_DATA0)
+#define bfin_write_CAN_MB11_DATA0(val) bfin_write16(CAN_MB11_DATA0, val)
+#define bfin_read_CAN_MB11_DATA1() bfin_read16(CAN_MB11_DATA1)
+#define bfin_write_CAN_MB11_DATA1(val) bfin_write16(CAN_MB11_DATA1, val)
+#define bfin_read_CAN_MB11_DATA2() bfin_read16(CAN_MB11_DATA2)
+#define bfin_write_CAN_MB11_DATA2(val) bfin_write16(CAN_MB11_DATA2, val)
+#define bfin_read_CAN_MB11_DATA3() bfin_read16(CAN_MB11_DATA3)
+#define bfin_write_CAN_MB11_DATA3(val) bfin_write16(CAN_MB11_DATA3, val)
+#define bfin_read_CAN_MB11_LENGTH() bfin_read16(CAN_MB11_LENGTH)
+#define bfin_write_CAN_MB11_LENGTH(val) bfin_write16(CAN_MB11_LENGTH, val)
+#define bfin_read_CAN_MB11_TIMESTAMP() bfin_read16(CAN_MB11_TIMESTAMP)
+#define bfin_write_CAN_MB11_TIMESTAMP(val) bfin_write16(CAN_MB11_TIMESTAMP, val)
+#define bfin_read_CAN_MB11_ID0() bfin_read16(CAN_MB11_ID0)
+#define bfin_write_CAN_MB11_ID0(val) bfin_write16(CAN_MB11_ID0, val)
+#define bfin_read_CAN_MB11_ID1() bfin_read16(CAN_MB11_ID1)
+#define bfin_write_CAN_MB11_ID1(val) bfin_write16(CAN_MB11_ID1, val)
+#define bfin_read_CAN_MB12_DATA0() bfin_read16(CAN_MB12_DATA0)
+#define bfin_write_CAN_MB12_DATA0(val) bfin_write16(CAN_MB12_DATA0, val)
+#define bfin_read_CAN_MB12_DATA1() bfin_read16(CAN_MB12_DATA1)
+#define bfin_write_CAN_MB12_DATA1(val) bfin_write16(CAN_MB12_DATA1, val)
+#define bfin_read_CAN_MB12_DATA2() bfin_read16(CAN_MB12_DATA2)
+#define bfin_write_CAN_MB12_DATA2(val) bfin_write16(CAN_MB12_DATA2, val)
+#define bfin_read_CAN_MB12_DATA3() bfin_read16(CAN_MB12_DATA3)
+#define bfin_write_CAN_MB12_DATA3(val) bfin_write16(CAN_MB12_DATA3, val)
+#define bfin_read_CAN_MB12_LENGTH() bfin_read16(CAN_MB12_LENGTH)
+#define bfin_write_CAN_MB12_LENGTH(val) bfin_write16(CAN_MB12_LENGTH, val)
+#define bfin_read_CAN_MB12_TIMESTAMP() bfin_read16(CAN_MB12_TIMESTAMP)
+#define bfin_write_CAN_MB12_TIMESTAMP(val) bfin_write16(CAN_MB12_TIMESTAMP, val)
+#define bfin_read_CAN_MB12_ID0() bfin_read16(CAN_MB12_ID0)
+#define bfin_write_CAN_MB12_ID0(val) bfin_write16(CAN_MB12_ID0, val)
+#define bfin_read_CAN_MB12_ID1() bfin_read16(CAN_MB12_ID1)
+#define bfin_write_CAN_MB12_ID1(val) bfin_write16(CAN_MB12_ID1, val)
+#define bfin_read_CAN_MB13_DATA0() bfin_read16(CAN_MB13_DATA0)
+#define bfin_write_CAN_MB13_DATA0(val) bfin_write16(CAN_MB13_DATA0, val)
+#define bfin_read_CAN_MB13_DATA1() bfin_read16(CAN_MB13_DATA1)
+#define bfin_write_CAN_MB13_DATA1(val) bfin_write16(CAN_MB13_DATA1, val)
+#define bfin_read_CAN_MB13_DATA2() bfin_read16(CAN_MB13_DATA2)
+#define bfin_write_CAN_MB13_DATA2(val) bfin_write16(CAN_MB13_DATA2, val)
+#define bfin_read_CAN_MB13_DATA3() bfin_read16(CAN_MB13_DATA3)
+#define bfin_write_CAN_MB13_DATA3(val) bfin_write16(CAN_MB13_DATA3, val)
+#define bfin_read_CAN_MB13_LENGTH() bfin_read16(CAN_MB13_LENGTH)
+#define bfin_write_CAN_MB13_LENGTH(val) bfin_write16(CAN_MB13_LENGTH, val)
+#define bfin_read_CAN_MB13_TIMESTAMP() bfin_read16(CAN_MB13_TIMESTAMP)
+#define bfin_write_CAN_MB13_TIMESTAMP(val) bfin_write16(CAN_MB13_TIMESTAMP, val)
+#define bfin_read_CAN_MB13_ID0() bfin_read16(CAN_MB13_ID0)
+#define bfin_write_CAN_MB13_ID0(val) bfin_write16(CAN_MB13_ID0, val)
+#define bfin_read_CAN_MB13_ID1() bfin_read16(CAN_MB13_ID1)
+#define bfin_write_CAN_MB13_ID1(val) bfin_write16(CAN_MB13_ID1, val)
+#define bfin_read_CAN_MB14_DATA0() bfin_read16(CAN_MB14_DATA0)
+#define bfin_write_CAN_MB14_DATA0(val) bfin_write16(CAN_MB14_DATA0, val)
+#define bfin_read_CAN_MB14_DATA1() bfin_read16(CAN_MB14_DATA1)
+#define bfin_write_CAN_MB14_DATA1(val) bfin_write16(CAN_MB14_DATA1, val)
+#define bfin_read_CAN_MB14_DATA2() bfin_read16(CAN_MB14_DATA2)
+#define bfin_write_CAN_MB14_DATA2(val) bfin_write16(CAN_MB14_DATA2, val)
+#define bfin_read_CAN_MB14_DATA3() bfin_read16(CAN_MB14_DATA3)
+#define bfin_write_CAN_MB14_DATA3(val) bfin_write16(CAN_MB14_DATA3, val)
+#define bfin_read_CAN_MB14_LENGTH() bfin_read16(CAN_MB14_LENGTH)
+#define bfin_write_CAN_MB14_LENGTH(val) bfin_write16(CAN_MB14_LENGTH, val)
+#define bfin_read_CAN_MB14_TIMESTAMP() bfin_read16(CAN_MB14_TIMESTAMP)
+#define bfin_write_CAN_MB14_TIMESTAMP(val) bfin_write16(CAN_MB14_TIMESTAMP, val)
+#define bfin_read_CAN_MB14_ID0() bfin_read16(CAN_MB14_ID0)
+#define bfin_write_CAN_MB14_ID0(val) bfin_write16(CAN_MB14_ID0, val)
+#define bfin_read_CAN_MB14_ID1() bfin_read16(CAN_MB14_ID1)
+#define bfin_write_CAN_MB14_ID1(val) bfin_write16(CAN_MB14_ID1, val)
+#define bfin_read_CAN_MB15_DATA0() bfin_read16(CAN_MB15_DATA0)
+#define bfin_write_CAN_MB15_DATA0(val) bfin_write16(CAN_MB15_DATA0, val)
+#define bfin_read_CAN_MB15_DATA1() bfin_read16(CAN_MB15_DATA1)
+#define bfin_write_CAN_MB15_DATA1(val) bfin_write16(CAN_MB15_DATA1, val)
+#define bfin_read_CAN_MB15_DATA2() bfin_read16(CAN_MB15_DATA2)
+#define bfin_write_CAN_MB15_DATA2(val) bfin_write16(CAN_MB15_DATA2, val)
+#define bfin_read_CAN_MB15_DATA3() bfin_read16(CAN_MB15_DATA3)
+#define bfin_write_CAN_MB15_DATA3(val) bfin_write16(CAN_MB15_DATA3, val)
+#define bfin_read_CAN_MB15_LENGTH() bfin_read16(CAN_MB15_LENGTH)
+#define bfin_write_CAN_MB15_LENGTH(val) bfin_write16(CAN_MB15_LENGTH, val)
+#define bfin_read_CAN_MB15_TIMESTAMP() bfin_read16(CAN_MB15_TIMESTAMP)
+#define bfin_write_CAN_MB15_TIMESTAMP(val) bfin_write16(CAN_MB15_TIMESTAMP, val)
+#define bfin_read_CAN_MB15_ID0() bfin_read16(CAN_MB15_ID0)
+#define bfin_write_CAN_MB15_ID0(val) bfin_write16(CAN_MB15_ID0, val)
+#define bfin_read_CAN_MB15_ID1() bfin_read16(CAN_MB15_ID1)
+#define bfin_write_CAN_MB15_ID1(val) bfin_write16(CAN_MB15_ID1, val)
+#define bfin_read_CAN_MB16_DATA0() bfin_read16(CAN_MB16_DATA0)
+#define bfin_write_CAN_MB16_DATA0(val) bfin_write16(CAN_MB16_DATA0, val)
+#define bfin_read_CAN_MB16_DATA1() bfin_read16(CAN_MB16_DATA1)
+#define bfin_write_CAN_MB16_DATA1(val) bfin_write16(CAN_MB16_DATA1, val)
+#define bfin_read_CAN_MB16_DATA2() bfin_read16(CAN_MB16_DATA2)
+#define bfin_write_CAN_MB16_DATA2(val) bfin_write16(CAN_MB16_DATA2, val)
+#define bfin_read_CAN_MB16_DATA3() bfin_read16(CAN_MB16_DATA3)
+#define bfin_write_CAN_MB16_DATA3(val) bfin_write16(CAN_MB16_DATA3, val)
+#define bfin_read_CAN_MB16_LENGTH() bfin_read16(CAN_MB16_LENGTH)
+#define bfin_write_CAN_MB16_LENGTH(val) bfin_write16(CAN_MB16_LENGTH, val)
+#define bfin_read_CAN_MB16_TIMESTAMP() bfin_read16(CAN_MB16_TIMESTAMP)
+#define bfin_write_CAN_MB16_TIMESTAMP(val) bfin_write16(CAN_MB16_TIMESTAMP, val)
+#define bfin_read_CAN_MB16_ID0() bfin_read16(CAN_MB16_ID0)
+#define bfin_write_CAN_MB16_ID0(val) bfin_write16(CAN_MB16_ID0, val)
+#define bfin_read_CAN_MB16_ID1() bfin_read16(CAN_MB16_ID1)
+#define bfin_write_CAN_MB16_ID1(val) bfin_write16(CAN_MB16_ID1, val)
+#define bfin_read_CAN_MB17_DATA0() bfin_read16(CAN_MB17_DATA0)
+#define bfin_write_CAN_MB17_DATA0(val) bfin_write16(CAN_MB17_DATA0, val)
+#define bfin_read_CAN_MB17_DATA1() bfin_read16(CAN_MB17_DATA1)
+#define bfin_write_CAN_MB17_DATA1(val) bfin_write16(CAN_MB17_DATA1, val)
+#define bfin_read_CAN_MB17_DATA2() bfin_read16(CAN_MB17_DATA2)
+#define bfin_write_CAN_MB17_DATA2(val) bfin_write16(CAN_MB17_DATA2, val)
+#define bfin_read_CAN_MB17_DATA3() bfin_read16(CAN_MB17_DATA3)
+#define bfin_write_CAN_MB17_DATA3(val) bfin_write16(CAN_MB17_DATA3, val)
+#define bfin_read_CAN_MB17_LENGTH() bfin_read16(CAN_MB17_LENGTH)
+#define bfin_write_CAN_MB17_LENGTH(val) bfin_write16(CAN_MB17_LENGTH, val)
+#define bfin_read_CAN_MB17_TIMESTAMP() bfin_read16(CAN_MB17_TIMESTAMP)
+#define bfin_write_CAN_MB17_TIMESTAMP(val) bfin_write16(CAN_MB17_TIMESTAMP, val)
+#define bfin_read_CAN_MB17_ID0() bfin_read16(CAN_MB17_ID0)
+#define bfin_write_CAN_MB17_ID0(val) bfin_write16(CAN_MB17_ID0, val)
+#define bfin_read_CAN_MB17_ID1() bfin_read16(CAN_MB17_ID1)
+#define bfin_write_CAN_MB17_ID1(val) bfin_write16(CAN_MB17_ID1, val)
+#define bfin_read_CAN_MB18_DATA0() bfin_read16(CAN_MB18_DATA0)
+#define bfin_write_CAN_MB18_DATA0(val) bfin_write16(CAN_MB18_DATA0, val)
+#define bfin_read_CAN_MB18_DATA1() bfin_read16(CAN_MB18_DATA1)
+#define bfin_write_CAN_MB18_DATA1(val) bfin_write16(CAN_MB18_DATA1, val)
+#define bfin_read_CAN_MB18_DATA2() bfin_read16(CAN_MB18_DATA2)
+#define bfin_write_CAN_MB18_DATA2(val) bfin_write16(CAN_MB18_DATA2, val)
+#define bfin_read_CAN_MB18_DATA3() bfin_read16(CAN_MB18_DATA3)
+#define bfin_write_CAN_MB18_DATA3(val) bfin_write16(CAN_MB18_DATA3, val)
+#define bfin_read_CAN_MB18_LENGTH() bfin_read16(CAN_MB18_LENGTH)
+#define bfin_write_CAN_MB18_LENGTH(val) bfin_write16(CAN_MB18_LENGTH, val)
+#define bfin_read_CAN_MB18_TIMESTAMP() bfin_read16(CAN_MB18_TIMESTAMP)
+#define bfin_write_CAN_MB18_TIMESTAMP(val) bfin_write16(CAN_MB18_TIMESTAMP, val)
+#define bfin_read_CAN_MB18_ID0() bfin_read16(CAN_MB18_ID0)
+#define bfin_write_CAN_MB18_ID0(val) bfin_write16(CAN_MB18_ID0, val)
+#define bfin_read_CAN_MB18_ID1() bfin_read16(CAN_MB18_ID1)
+#define bfin_write_CAN_MB18_ID1(val) bfin_write16(CAN_MB18_ID1, val)
+#define bfin_read_CAN_MB19_DATA0() bfin_read16(CAN_MB19_DATA0)
+#define bfin_write_CAN_MB19_DATA0(val) bfin_write16(CAN_MB19_DATA0, val)
+#define bfin_read_CAN_MB19_DATA1() bfin_read16(CAN_MB19_DATA1)
+#define bfin_write_CAN_MB19_DATA1(val) bfin_write16(CAN_MB19_DATA1, val)
+#define bfin_read_CAN_MB19_DATA2() bfin_read16(CAN_MB19_DATA2)
+#define bfin_write_CAN_MB19_DATA2(val) bfin_write16(CAN_MB19_DATA2, val)
+#define bfin_read_CAN_MB19_DATA3() bfin_read16(CAN_MB19_DATA3)
+#define bfin_write_CAN_MB19_DATA3(val) bfin_write16(CAN_MB19_DATA3, val)
+#define bfin_read_CAN_MB19_LENGTH() bfin_read16(CAN_MB19_LENGTH)
+#define bfin_write_CAN_MB19_LENGTH(val) bfin_write16(CAN_MB19_LENGTH, val)
+#define bfin_read_CAN_MB19_TIMESTAMP() bfin_read16(CAN_MB19_TIMESTAMP)
+#define bfin_write_CAN_MB19_TIMESTAMP(val) bfin_write16(CAN_MB19_TIMESTAMP, val)
+#define bfin_read_CAN_MB19_ID0() bfin_read16(CAN_MB19_ID0)
+#define bfin_write_CAN_MB19_ID0(val) bfin_write16(CAN_MB19_ID0, val)
+#define bfin_read_CAN_MB19_ID1() bfin_read16(CAN_MB19_ID1)
+#define bfin_write_CAN_MB19_ID1(val) bfin_write16(CAN_MB19_ID1, val)
+#define bfin_read_CAN_MB20_DATA0() bfin_read16(CAN_MB20_DATA0)
+#define bfin_write_CAN_MB20_DATA0(val) bfin_write16(CAN_MB20_DATA0, val)
+#define bfin_read_CAN_MB20_DATA1() bfin_read16(CAN_MB20_DATA1)
+#define bfin_write_CAN_MB20_DATA1(val) bfin_write16(CAN_MB20_DATA1, val)
+#define bfin_read_CAN_MB20_DATA2() bfin_read16(CAN_MB20_DATA2)
+#define bfin_write_CAN_MB20_DATA2(val) bfin_write16(CAN_MB20_DATA2, val)
+#define bfin_read_CAN_MB20_DATA3() bfin_read16(CAN_MB20_DATA3)
+#define bfin_write_CAN_MB20_DATA3(val) bfin_write16(CAN_MB20_DATA3, val)
+#define bfin_read_CAN_MB20_LENGTH() bfin_read16(CAN_MB20_LENGTH)
+#define bfin_write_CAN_MB20_LENGTH(val) bfin_write16(CAN_MB20_LENGTH, val)
+#define bfin_read_CAN_MB20_TIMESTAMP() bfin_read16(CAN_MB20_TIMESTAMP)
+#define bfin_write_CAN_MB20_TIMESTAMP(val) bfin_write16(CAN_MB20_TIMESTAMP, val)
+#define bfin_read_CAN_MB20_ID0() bfin_read16(CAN_MB20_ID0)
+#define bfin_write_CAN_MB20_ID0(val) bfin_write16(CAN_MB20_ID0, val)
+#define bfin_read_CAN_MB20_ID1() bfin_read16(CAN_MB20_ID1)
+#define bfin_write_CAN_MB20_ID1(val) bfin_write16(CAN_MB20_ID1, val)
+#define bfin_read_CAN_MB21_DATA0() bfin_read16(CAN_MB21_DATA0)
+#define bfin_write_CAN_MB21_DATA0(val) bfin_write16(CAN_MB21_DATA0, val)
+#define bfin_read_CAN_MB21_DATA1() bfin_read16(CAN_MB21_DATA1)
+#define bfin_write_CAN_MB21_DATA1(val) bfin_write16(CAN_MB21_DATA1, val)
+#define bfin_read_CAN_MB21_DATA2() bfin_read16(CAN_MB21_DATA2)
+#define bfin_write_CAN_MB21_DATA2(val) bfin_write16(CAN_MB21_DATA2, val)
+#define bfin_read_CAN_MB21_DATA3() bfin_read16(CAN_MB21_DATA3)
+#define bfin_write_CAN_MB21_DATA3(val) bfin_write16(CAN_MB21_DATA3, val)
+#define bfin_read_CAN_MB21_LENGTH() bfin_read16(CAN_MB21_LENGTH)
+#define bfin_write_CAN_MB21_LENGTH(val) bfin_write16(CAN_MB21_LENGTH, val)
+#define bfin_read_CAN_MB21_TIMESTAMP() bfin_read16(CAN_MB21_TIMESTAMP)
+#define bfin_write_CAN_MB21_TIMESTAMP(val) bfin_write16(CAN_MB21_TIMESTAMP, val)
+#define bfin_read_CAN_MB21_ID0() bfin_read16(CAN_MB21_ID0)
+#define bfin_write_CAN_MB21_ID0(val) bfin_write16(CAN_MB21_ID0, val)
+#define bfin_read_CAN_MB21_ID1() bfin_read16(CAN_MB21_ID1)
+#define bfin_write_CAN_MB21_ID1(val) bfin_write16(CAN_MB21_ID1, val)
+#define bfin_read_CAN_MB22_DATA0() bfin_read16(CAN_MB22_DATA0)
+#define bfin_write_CAN_MB22_DATA0(val) bfin_write16(CAN_MB22_DATA0, val)
+#define bfin_read_CAN_MB22_DATA1() bfin_read16(CAN_MB22_DATA1)
+#define bfin_write_CAN_MB22_DATA1(val) bfin_write16(CAN_MB22_DATA1, val)
+#define bfin_read_CAN_MB22_DATA2() bfin_read16(CAN_MB22_DATA2)
+#define bfin_write_CAN_MB22_DATA2(val) bfin_write16(CAN_MB22_DATA2, val)
+#define bfin_read_CAN_MB22_DATA3() bfin_read16(CAN_MB22_DATA3)
+#define bfin_write_CAN_MB22_DATA3(val) bfin_write16(CAN_MB22_DATA3, val)
+#define bfin_read_CAN_MB22_LENGTH() bfin_read16(CAN_MB22_LENGTH)
+#define bfin_write_CAN_MB22_LENGTH(val) bfin_write16(CAN_MB22_LENGTH, val)
+#define bfin_read_CAN_MB22_TIMESTAMP() bfin_read16(CAN_MB22_TIMESTAMP)
+#define bfin_write_CAN_MB22_TIMESTAMP(val) bfin_write16(CAN_MB22_TIMESTAMP, val)
+#define bfin_read_CAN_MB22_ID0() bfin_read16(CAN_MB22_ID0)
+#define bfin_write_CAN_MB22_ID0(val) bfin_write16(CAN_MB22_ID0, val)
+#define bfin_read_CAN_MB22_ID1() bfin_read16(CAN_MB22_ID1)
+#define bfin_write_CAN_MB22_ID1(val) bfin_write16(CAN_MB22_ID1, val)
+#define bfin_read_CAN_MB23_DATA0() bfin_read16(CAN_MB23_DATA0)
+#define bfin_write_CAN_MB23_DATA0(val) bfin_write16(CAN_MB23_DATA0, val)
+#define bfin_read_CAN_MB23_DATA1() bfin_read16(CAN_MB23_DATA1)
+#define bfin_write_CAN_MB23_DATA1(val) bfin_write16(CAN_MB23_DATA1, val)
+#define bfin_read_CAN_MB23_DATA2() bfin_read16(CAN_MB23_DATA2)
+#define bfin_write_CAN_MB23_DATA2(val) bfin_write16(CAN_MB23_DATA2, val)
+#define bfin_read_CAN_MB23_DATA3() bfin_read16(CAN_MB23_DATA3)
+#define bfin_write_CAN_MB23_DATA3(val) bfin_write16(CAN_MB23_DATA3, val)
+#define bfin_read_CAN_MB23_LENGTH() bfin_read16(CAN_MB23_LENGTH)
+#define bfin_write_CAN_MB23_LENGTH(val) bfin_write16(CAN_MB23_LENGTH, val)
+#define bfin_read_CAN_MB23_TIMESTAMP() bfin_read16(CAN_MB23_TIMESTAMP)
+#define bfin_write_CAN_MB23_TIMESTAMP(val) bfin_write16(CAN_MB23_TIMESTAMP, val)
+#define bfin_read_CAN_MB23_ID0() bfin_read16(CAN_MB23_ID0)
+#define bfin_write_CAN_MB23_ID0(val) bfin_write16(CAN_MB23_ID0, val)
+#define bfin_read_CAN_MB23_ID1() bfin_read16(CAN_MB23_ID1)
+#define bfin_write_CAN_MB23_ID1(val) bfin_write16(CAN_MB23_ID1, val)
+#define bfin_read_CAN_MB24_DATA0() bfin_read16(CAN_MB24_DATA0)
+#define bfin_write_CAN_MB24_DATA0(val) bfin_write16(CAN_MB24_DATA0, val)
+#define bfin_read_CAN_MB24_DATA1() bfin_read16(CAN_MB24_DATA1)
+#define bfin_write_CAN_MB24_DATA1(val) bfin_write16(CAN_MB24_DATA1, val)
+#define bfin_read_CAN_MB24_DATA2() bfin_read16(CAN_MB24_DATA2)
+#define bfin_write_CAN_MB24_DATA2(val) bfin_write16(CAN_MB24_DATA2, val)
+#define bfin_read_CAN_MB24_DATA3() bfin_read16(CAN_MB24_DATA3)
+#define bfin_write_CAN_MB24_DATA3(val) bfin_write16(CAN_MB24_DATA3, val)
+#define bfin_read_CAN_MB24_LENGTH() bfin_read16(CAN_MB24_LENGTH)
+#define bfin_write_CAN_MB24_LENGTH(val) bfin_write16(CAN_MB24_LENGTH, val)
+#define bfin_read_CAN_MB24_TIMESTAMP() bfin_read16(CAN_MB24_TIMESTAMP)
+#define bfin_write_CAN_MB24_TIMESTAMP(val) bfin_write16(CAN_MB24_TIMESTAMP, val)
+#define bfin_read_CAN_MB24_ID0() bfin_read16(CAN_MB24_ID0)
+#define bfin_write_CAN_MB24_ID0(val) bfin_write16(CAN_MB24_ID0, val)
+#define bfin_read_CAN_MB24_ID1() bfin_read16(CAN_MB24_ID1)
+#define bfin_write_CAN_MB24_ID1(val) bfin_write16(CAN_MB24_ID1, val)
+#define bfin_read_CAN_MB25_DATA0() bfin_read16(CAN_MB25_DATA0)
+#define bfin_write_CAN_MB25_DATA0(val) bfin_write16(CAN_MB25_DATA0, val)
+#define bfin_read_CAN_MB25_DATA1() bfin_read16(CAN_MB25_DATA1)
+#define bfin_write_CAN_MB25_DATA1(val) bfin_write16(CAN_MB25_DATA1, val)
+#define bfin_read_CAN_MB25_DATA2() bfin_read16(CAN_MB25_DATA2)
+#define bfin_write_CAN_MB25_DATA2(val) bfin_write16(CAN_MB25_DATA2, val)
+#define bfin_read_CAN_MB25_DATA3() bfin_read16(CAN_MB25_DATA3)
+#define bfin_write_CAN_MB25_DATA3(val) bfin_write16(CAN_MB25_DATA3, val)
+#define bfin_read_CAN_MB25_LENGTH() bfin_read16(CAN_MB25_LENGTH)
+#define bfin_write_CAN_MB25_LENGTH(val) bfin_write16(CAN_MB25_LENGTH, val)
+#define bfin_read_CAN_MB25_TIMESTAMP() bfin_read16(CAN_MB25_TIMESTAMP)
+#define bfin_write_CAN_MB25_TIMESTAMP(val) bfin_write16(CAN_MB25_TIMESTAMP, val)
+#define bfin_read_CAN_MB25_ID0() bfin_read16(CAN_MB25_ID0)
+#define bfin_write_CAN_MB25_ID0(val) bfin_write16(CAN_MB25_ID0, val)
+#define bfin_read_CAN_MB25_ID1() bfin_read16(CAN_MB25_ID1)
+#define bfin_write_CAN_MB25_ID1(val) bfin_write16(CAN_MB25_ID1, val)
+#define bfin_read_CAN_MB26_DATA0() bfin_read16(CAN_MB26_DATA0)
+#define bfin_write_CAN_MB26_DATA0(val) bfin_write16(CAN_MB26_DATA0, val)
+#define bfin_read_CAN_MB26_DATA1() bfin_read16(CAN_MB26_DATA1)
+#define bfin_write_CAN_MB26_DATA1(val) bfin_write16(CAN_MB26_DATA1, val)
+#define bfin_read_CAN_MB26_DATA2() bfin_read16(CAN_MB26_DATA2)
+#define bfin_write_CAN_MB26_DATA2(val) bfin_write16(CAN_MB26_DATA2, val)
+#define bfin_read_CAN_MB26_DATA3() bfin_read16(CAN_MB26_DATA3)
+#define bfin_write_CAN_MB26_DATA3(val) bfin_write16(CAN_MB26_DATA3, val)
+#define bfin_read_CAN_MB26_LENGTH() bfin_read16(CAN_MB26_LENGTH)
+#define bfin_write_CAN_MB26_LENGTH(val) bfin_write16(CAN_MB26_LENGTH, val)
+#define bfin_read_CAN_MB26_TIMESTAMP() bfin_read16(CAN_MB26_TIMESTAMP)
+#define bfin_write_CAN_MB26_TIMESTAMP(val) bfin_write16(CAN_MB26_TIMESTAMP, val)
+#define bfin_read_CAN_MB26_ID0() bfin_read16(CAN_MB26_ID0)
+#define bfin_write_CAN_MB26_ID0(val) bfin_write16(CAN_MB26_ID0, val)
+#define bfin_read_CAN_MB26_ID1() bfin_read16(CAN_MB26_ID1)
+#define bfin_write_CAN_MB26_ID1(val) bfin_write16(CAN_MB26_ID1, val)
+#define bfin_read_CAN_MB27_DATA0() bfin_read16(CAN_MB27_DATA0)
+#define bfin_write_CAN_MB27_DATA0(val) bfin_write16(CAN_MB27_DATA0, val)
+#define bfin_read_CAN_MB27_DATA1() bfin_read16(CAN_MB27_DATA1)
+#define bfin_write_CAN_MB27_DATA1(val) bfin_write16(CAN_MB27_DATA1, val)
+#define bfin_read_CAN_MB27_DATA2() bfin_read16(CAN_MB27_DATA2)
+#define bfin_write_CAN_MB27_DATA2(val) bfin_write16(CAN_MB27_DATA2, val)
+#define bfin_read_CAN_MB27_DATA3() bfin_read16(CAN_MB27_DATA3)
+#define bfin_write_CAN_MB27_DATA3(val) bfin_write16(CAN_MB27_DATA3, val)
+#define bfin_read_CAN_MB27_LENGTH() bfin_read16(CAN_MB27_LENGTH)
+#define bfin_write_CAN_MB27_LENGTH(val) bfin_write16(CAN_MB27_LENGTH, val)
+#define bfin_read_CAN_MB27_TIMESTAMP() bfin_read16(CAN_MB27_TIMESTAMP)
+#define bfin_write_CAN_MB27_TIMESTAMP(val) bfin_write16(CAN_MB27_TIMESTAMP, val)
+#define bfin_read_CAN_MB27_ID0() bfin_read16(CAN_MB27_ID0)
+#define bfin_write_CAN_MB27_ID0(val) bfin_write16(CAN_MB27_ID0, val)
+#define bfin_read_CAN_MB27_ID1() bfin_read16(CAN_MB27_ID1)
+#define bfin_write_CAN_MB27_ID1(val) bfin_write16(CAN_MB27_ID1, val)
+#define bfin_read_CAN_MB28_DATA0() bfin_read16(CAN_MB28_DATA0)
+#define bfin_write_CAN_MB28_DATA0(val) bfin_write16(CAN_MB28_DATA0, val)
+#define bfin_read_CAN_MB28_DATA1() bfin_read16(CAN_MB28_DATA1)
+#define bfin_write_CAN_MB28_DATA1(val) bfin_write16(CAN_MB28_DATA1, val)
+#define bfin_read_CAN_MB28_DATA2() bfin_read16(CAN_MB28_DATA2)
+#define bfin_write_CAN_MB28_DATA2(val) bfin_write16(CAN_MB28_DATA2, val)
+#define bfin_read_CAN_MB28_DATA3() bfin_read16(CAN_MB28_DATA3)
+#define bfin_write_CAN_MB28_DATA3(val) bfin_write16(CAN_MB28_DATA3, val)
+#define bfin_read_CAN_MB28_LENGTH() bfin_read16(CAN_MB28_LENGTH)
+#define bfin_write_CAN_MB28_LENGTH(val) bfin_write16(CAN_MB28_LENGTH, val)
+#define bfin_read_CAN_MB28_TIMESTAMP() bfin_read16(CAN_MB28_TIMESTAMP)
+#define bfin_write_CAN_MB28_TIMESTAMP(val) bfin_write16(CAN_MB28_TIMESTAMP, val)
+#define bfin_read_CAN_MB28_ID0() bfin_read16(CAN_MB28_ID0)
+#define bfin_write_CAN_MB28_ID0(val) bfin_write16(CAN_MB28_ID0, val)
+#define bfin_read_CAN_MB28_ID1() bfin_read16(CAN_MB28_ID1)
+#define bfin_write_CAN_MB28_ID1(val) bfin_write16(CAN_MB28_ID1, val)
+#define bfin_read_CAN_MB29_DATA0() bfin_read16(CAN_MB29_DATA0)
+#define bfin_write_CAN_MB29_DATA0(val) bfin_write16(CAN_MB29_DATA0, val)
+#define bfin_read_CAN_MB29_DATA1() bfin_read16(CAN_MB29_DATA1)
+#define bfin_write_CAN_MB29_DATA1(val) bfin_write16(CAN_MB29_DATA1, val)
+#define bfin_read_CAN_MB29_DATA2() bfin_read16(CAN_MB29_DATA2)
+#define bfin_write_CAN_MB29_DATA2(val) bfin_write16(CAN_MB29_DATA2, val)
+#define bfin_read_CAN_MB29_DATA3() bfin_read16(CAN_MB29_DATA3)
+#define bfin_write_CAN_MB29_DATA3(val) bfin_write16(CAN_MB29_DATA3, val)
+#define bfin_read_CAN_MB29_LENGTH() bfin_read16(CAN_MB29_LENGTH)
+#define bfin_write_CAN_MB29_LENGTH(val) bfin_write16(CAN_MB29_LENGTH, val)
+#define bfin_read_CAN_MB29_TIMESTAMP() bfin_read16(CAN_MB29_TIMESTAMP)
+#define bfin_write_CAN_MB29_TIMESTAMP(val) bfin_write16(CAN_MB29_TIMESTAMP, val)
+#define bfin_read_CAN_MB29_ID0() bfin_read16(CAN_MB29_ID0)
+#define bfin_write_CAN_MB29_ID0(val) bfin_write16(CAN_MB29_ID0, val)
+#define bfin_read_CAN_MB29_ID1() bfin_read16(CAN_MB29_ID1)
+#define bfin_write_CAN_MB29_ID1(val) bfin_write16(CAN_MB29_ID1, val)
+#define bfin_read_CAN_MB30_DATA0() bfin_read16(CAN_MB30_DATA0)
+#define bfin_write_CAN_MB30_DATA0(val) bfin_write16(CAN_MB30_DATA0, val)
+#define bfin_read_CAN_MB30_DATA1() bfin_read16(CAN_MB30_DATA1)
+#define bfin_write_CAN_MB30_DATA1(val) bfin_write16(CAN_MB30_DATA1, val)
+#define bfin_read_CAN_MB30_DATA2() bfin_read16(CAN_MB30_DATA2)
+#define bfin_write_CAN_MB30_DATA2(val) bfin_write16(CAN_MB30_DATA2, val)
+#define bfin_read_CAN_MB30_DATA3() bfin_read16(CAN_MB30_DATA3)
+#define bfin_write_CAN_MB30_DATA3(val) bfin_write16(CAN_MB30_DATA3, val)
+#define bfin_read_CAN_MB30_LENGTH() bfin_read16(CAN_MB30_LENGTH)
+#define bfin_write_CAN_MB30_LENGTH(val) bfin_write16(CAN_MB30_LENGTH, val)
+#define bfin_read_CAN_MB30_TIMESTAMP() bfin_read16(CAN_MB30_TIMESTAMP)
+#define bfin_write_CAN_MB30_TIMESTAMP(val) bfin_write16(CAN_MB30_TIMESTAMP, val)
+#define bfin_read_CAN_MB30_ID0() bfin_read16(CAN_MB30_ID0)
+#define bfin_write_CAN_MB30_ID0(val) bfin_write16(CAN_MB30_ID0, val)
+#define bfin_read_CAN_MB30_ID1() bfin_read16(CAN_MB30_ID1)
+#define bfin_write_CAN_MB30_ID1(val) bfin_write16(CAN_MB30_ID1, val)
+#define bfin_read_CAN_MB31_DATA0() bfin_read16(CAN_MB31_DATA0)
+#define bfin_write_CAN_MB31_DATA0(val) bfin_write16(CAN_MB31_DATA0, val)
+#define bfin_read_CAN_MB31_DATA1() bfin_read16(CAN_MB31_DATA1)
+#define bfin_write_CAN_MB31_DATA1(val) bfin_write16(CAN_MB31_DATA1, val)
+#define bfin_read_CAN_MB31_DATA2() bfin_read16(CAN_MB31_DATA2)
+#define bfin_write_CAN_MB31_DATA2(val) bfin_write16(CAN_MB31_DATA2, val)
+#define bfin_read_CAN_MB31_DATA3() bfin_read16(CAN_MB31_DATA3)
+#define bfin_write_CAN_MB31_DATA3(val) bfin_write16(CAN_MB31_DATA3, val)
+#define bfin_read_CAN_MB31_LENGTH() bfin_read16(CAN_MB31_LENGTH)
+#define bfin_write_CAN_MB31_LENGTH(val) bfin_write16(CAN_MB31_LENGTH, val)
+#define bfin_read_CAN_MB31_TIMESTAMP() bfin_read16(CAN_MB31_TIMESTAMP)
+#define bfin_write_CAN_MB31_TIMESTAMP(val) bfin_write16(CAN_MB31_TIMESTAMP, val)
+#define bfin_read_CAN_MB31_ID0() bfin_read16(CAN_MB31_ID0)
+#define bfin_write_CAN_MB31_ID0(val) bfin_write16(CAN_MB31_ID0, val)
+#define bfin_read_CAN_MB31_ID1() bfin_read16(CAN_MB31_ID1)
+#define bfin_write_CAN_MB31_ID1(val) bfin_write16(CAN_MB31_ID1, val)
+
+/* These need to be last due to the cdef/linux inter-dependencies */
+#include <asm/irq.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
+#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/cdefBF539.h b/arch/blackfin/mach-bf538/include/mach/cdefBF539.h
new file mode 100644
index 000000000000..198c4bbc8e5d
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/cdefBF539.h
@@ -0,0 +1,240 @@
+/* DO NOT EDIT THIS FILE
+ * Automatically generated by generate-cdef-headers.xsl
+ * DO NOT EDIT THIS FILE
+ */
+
+#ifndef _CDEF_BF539_H
+#define _CDEF_BF539_H
+
+/* Include MMRs Common to BF538 */
+#include "cdefBF538.h"
+
+
+#define bfin_read_MXVR_CONFIG() bfin_read16(MXVR_CONFIG)
+#define bfin_write_MXVR_CONFIG(val) bfin_write16(MXVR_CONFIG, val)
+#define bfin_read_MXVR_PLL_CTL_0() bfin_read32(MXVR_PLL_CTL_0)
+#define bfin_write_MXVR_PLL_CTL_0(val) bfin_write32(MXVR_PLL_CTL_0, val)
+#define bfin_read_MXVR_STATE_0() bfin_read32(MXVR_STATE_0)
+#define bfin_write_MXVR_STATE_0(val) bfin_write32(MXVR_STATE_0, val)
+#define bfin_read_MXVR_STATE_1() bfin_read32(MXVR_STATE_1)
+#define bfin_write_MXVR_STATE_1(val) bfin_write32(MXVR_STATE_1, val)
+#define bfin_read_MXVR_INT_STAT_0() bfin_read32(MXVR_INT_STAT_0)
+#define bfin_write_MXVR_INT_STAT_0(val) bfin_write32(MXVR_INT_STAT_0, val)
+#define bfin_read_MXVR_INT_STAT_1() bfin_read32(MXVR_INT_STAT_1)
+#define bfin_write_MXVR_INT_STAT_1(val) bfin_write32(MXVR_INT_STAT_1, val)
+#define bfin_read_MXVR_INT_EN_0() bfin_read32(MXVR_INT_EN_0)
+#define bfin_write_MXVR_INT_EN_0(val) bfin_write32(MXVR_INT_EN_0, val)
+#define bfin_read_MXVR_INT_EN_1() bfin_read32(MXVR_INT_EN_1)
+#define bfin_write_MXVR_INT_EN_1(val) bfin_write32(MXVR_INT_EN_1, val)
+#define bfin_read_MXVR_POSITION() bfin_read16(MXVR_POSITION)
+#define bfin_write_MXVR_POSITION(val) bfin_write16(MXVR_POSITION, val)
+#define bfin_read_MXVR_MAX_POSITION() bfin_read16(MXVR_MAX_POSITION)
+#define bfin_write_MXVR_MAX_POSITION(val) bfin_write16(MXVR_MAX_POSITION, val)
+#define bfin_read_MXVR_DELAY() bfin_read16(MXVR_DELAY)
+#define bfin_write_MXVR_DELAY(val) bfin_write16(MXVR_DELAY, val)
+#define bfin_read_MXVR_MAX_DELAY() bfin_read16(MXVR_MAX_DELAY)
+#define bfin_write_MXVR_MAX_DELAY(val) bfin_write16(MXVR_MAX_DELAY, val)
+#define bfin_read_MXVR_LADDR() bfin_read32(MXVR_LADDR)
+#define bfin_write_MXVR_LADDR(val) bfin_write32(MXVR_LADDR, val)
+#define bfin_read_MXVR_GADDR() bfin_read16(MXVR_GADDR)
+#define bfin_write_MXVR_GADDR(val) bfin_write16(MXVR_GADDR, val)
+#define bfin_read_MXVR_AADDR() bfin_read32(MXVR_AADDR)
+#define bfin_write_MXVR_AADDR(val) bfin_write32(MXVR_AADDR, val)
+#define bfin_read_MXVR_ALLOC_0() bfin_read32(MXVR_ALLOC_0)
+#define bfin_write_MXVR_ALLOC_0(val) bfin_write32(MXVR_ALLOC_0, val)
+#define bfin_read_MXVR_ALLOC_1() bfin_read32(MXVR_ALLOC_1)
+#define bfin_write_MXVR_ALLOC_1(val) bfin_write32(MXVR_ALLOC_1, val)
+#define bfin_read_MXVR_ALLOC_2() bfin_read32(MXVR_ALLOC_2)
+#define bfin_write_MXVR_ALLOC_2(val) bfin_write32(MXVR_ALLOC_2, val)
+#define bfin_read_MXVR_ALLOC_3() bfin_read32(MXVR_ALLOC_3)
+#define bfin_write_MXVR_ALLOC_3(val) bfin_write32(MXVR_ALLOC_3, val)
+#define bfin_read_MXVR_ALLOC_4() bfin_read32(MXVR_ALLOC_4)
+#define bfin_write_MXVR_ALLOC_4(val) bfin_write32(MXVR_ALLOC_4, val)
+#define bfin_read_MXVR_ALLOC_5() bfin_read32(MXVR_ALLOC_5)
+#define bfin_write_MXVR_ALLOC_5(val) bfin_write32(MXVR_ALLOC_5, val)
+#define bfin_read_MXVR_ALLOC_6() bfin_read32(MXVR_ALLOC_6)
+#define bfin_write_MXVR_ALLOC_6(val) bfin_write32(MXVR_ALLOC_6, val)
+#define bfin_read_MXVR_ALLOC_7() bfin_read32(MXVR_ALLOC_7)
+#define bfin_write_MXVR_ALLOC_7(val) bfin_write32(MXVR_ALLOC_7, val)
+#define bfin_read_MXVR_ALLOC_8() bfin_read32(MXVR_ALLOC_8)
+#define bfin_write_MXVR_ALLOC_8(val) bfin_write32(MXVR_ALLOC_8, val)
+#define bfin_read_MXVR_ALLOC_9() bfin_read32(MXVR_ALLOC_9)
+#define bfin_write_MXVR_ALLOC_9(val) bfin_write32(MXVR_ALLOC_9, val)
+#define bfin_read_MXVR_ALLOC_10() bfin_read32(MXVR_ALLOC_10)
+#define bfin_write_MXVR_ALLOC_10(val) bfin_write32(MXVR_ALLOC_10, val)
+#define bfin_read_MXVR_ALLOC_11() bfin_read32(MXVR_ALLOC_11)
+#define bfin_write_MXVR_ALLOC_11(val) bfin_write32(MXVR_ALLOC_11, val)
+#define bfin_read_MXVR_ALLOC_12() bfin_read32(MXVR_ALLOC_12)
+#define bfin_write_MXVR_ALLOC_12(val) bfin_write32(MXVR_ALLOC_12, val)
+#define bfin_read_MXVR_ALLOC_13() bfin_read32(MXVR_ALLOC_13)
+#define bfin_write_MXVR_ALLOC_13(val) bfin_write32(MXVR_ALLOC_13, val)
+#define bfin_read_MXVR_ALLOC_14() bfin_read32(MXVR_ALLOC_14)
+#define bfin_write_MXVR_ALLOC_14(val) bfin_write32(MXVR_ALLOC_14, val)
+#define bfin_read_MXVR_SYNC_LCHAN_0() bfin_read32(MXVR_SYNC_LCHAN_0)
+#define bfin_write_MXVR_SYNC_LCHAN_0(val) bfin_write32(MXVR_SYNC_LCHAN_0, val)
+#define bfin_read_MXVR_SYNC_LCHAN_1() bfin_read32(MXVR_SYNC_LCHAN_1)
+#define bfin_write_MXVR_SYNC_LCHAN_1(val) bfin_write32(MXVR_SYNC_LCHAN_1, val)
+#define bfin_read_MXVR_SYNC_LCHAN_2() bfin_read32(MXVR_SYNC_LCHAN_2)
+#define bfin_write_MXVR_SYNC_LCHAN_2(val) bfin_write32(MXVR_SYNC_LCHAN_2, val)
+#define bfin_read_MXVR_SYNC_LCHAN_3() bfin_read32(MXVR_SYNC_LCHAN_3)
+#define bfin_write_MXVR_SYNC_LCHAN_3(val) bfin_write32(MXVR_SYNC_LCHAN_3, val)
+#define bfin_read_MXVR_SYNC_LCHAN_4() bfin_read32(MXVR_SYNC_LCHAN_4)
+#define bfin_write_MXVR_SYNC_LCHAN_4(val) bfin_write32(MXVR_SYNC_LCHAN_4, val)
+#define bfin_read_MXVR_SYNC_LCHAN_5() bfin_read32(MXVR_SYNC_LCHAN_5)
+#define bfin_write_MXVR_SYNC_LCHAN_5(val) bfin_write32(MXVR_SYNC_LCHAN_5, val)
+#define bfin_read_MXVR_SYNC_LCHAN_6() bfin_read32(MXVR_SYNC_LCHAN_6)
+#define bfin_write_MXVR_SYNC_LCHAN_6(val) bfin_write32(MXVR_SYNC_LCHAN_6, val)
+#define bfin_read_MXVR_SYNC_LCHAN_7() bfin_read32(MXVR_SYNC_LCHAN_7)
+#define bfin_write_MXVR_SYNC_LCHAN_7(val) bfin_write32(MXVR_SYNC_LCHAN_7, val)
+#define bfin_read_MXVR_DMA0_CONFIG() bfin_read32(MXVR_DMA0_CONFIG)
+#define bfin_write_MXVR_DMA0_CONFIG(val) bfin_write32(MXVR_DMA0_CONFIG, val)
+#define bfin_read_MXVR_DMA0_START_ADDR() bfin_readPTR(MXVR_DMA0_START_ADDR)
+#define bfin_write_MXVR_DMA0_START_ADDR(val) bfin_writePTR(MXVR_DMA0_START_ADDR, val)
+#define bfin_read_MXVR_DMA0_COUNT() bfin_read16(MXVR_DMA0_COUNT)
+#define bfin_write_MXVR_DMA0_COUNT(val) bfin_write16(MXVR_DMA0_COUNT, val)
+#define bfin_read_MXVR_DMA0_CURR_ADDR() bfin_readPTR(MXVR_DMA0_CURR_ADDR)
+#define bfin_write_MXVR_DMA0_CURR_ADDR(val) bfin_writePTR(MXVR_DMA0_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA0_CURR_COUNT() bfin_read16(MXVR_DMA0_CURR_COUNT)
+#define bfin_write_MXVR_DMA0_CURR_COUNT(val) bfin_write16(MXVR_DMA0_CURR_COUNT, val)
+#define bfin_read_MXVR_DMA1_CONFIG() bfin_read32(MXVR_DMA1_CONFIG)
+#define bfin_write_MXVR_DMA1_CONFIG(val) bfin_write32(MXVR_DMA1_CONFIG, val)
+#define bfin_read_MXVR_DMA1_START_ADDR() bfin_readPTR(MXVR_DMA1_START_ADDR)
+#define bfin_write_MXVR_DMA1_START_ADDR(val) bfin_writePTR(MXVR_DMA1_START_ADDR, val)
+#define bfin_read_MXVR_DMA1_COUNT() bfin_read16(MXVR_DMA1_COUNT)
+#define bfin_write_MXVR_DMA1_COUNT(val) bfin_write16(MXVR_DMA1_COUNT, val)
+#define bfin_read_MXVR_DMA1_CURR_ADDR() bfin_readPTR(MXVR_DMA1_CURR_ADDR)
+#define bfin_write_MXVR_DMA1_CURR_ADDR(val) bfin_writePTR(MXVR_DMA1_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA1_CURR_COUNT() bfin_read16(MXVR_DMA1_CURR_COUNT)
+#define bfin_write_MXVR_DMA1_CURR_COUNT(val) bfin_write16(MXVR_DMA1_CURR_COUNT, val)
+#define bfin_read_MXVR_DMA2_CONFIG() bfin_read32(MXVR_DMA2_CONFIG)
+#define bfin_write_MXVR_DMA2_CONFIG(val) bfin_write32(MXVR_DMA2_CONFIG, val)
+#define bfin_read_MXVR_DMA2_START_ADDR() bfin_readPTR(MXVR_DMA2_START_ADDR)
+#define bfin_write_MXVR_DMA2_START_ADDR(val) bfin_writePTR(MXVR_DMA2_START_ADDR, val)
+#define bfin_read_MXVR_DMA2_COUNT() bfin_read16(MXVR_DMA2_COUNT)
+#define bfin_write_MXVR_DMA2_COUNT(val) bfin_write16(MXVR_DMA2_COUNT, val)
+#define bfin_read_MXVR_DMA2_CURR_ADDR() bfin_readPTR(MXVR_DMA2_CURR_ADDR)
+#define bfin_write_MXVR_DMA2_CURR_ADDR(val) bfin_writePTR(MXVR_DMA2_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA2_CURR_COUNT() bfin_read16(MXVR_DMA2_CURR_COUNT)
+#define bfin_write_MXVR_DMA2_CURR_COUNT(val) bfin_write16(MXVR_DMA2_CURR_COUNT, val)
+#define bfin_read_MXVR_DMA3_CONFIG() bfin_read32(MXVR_DMA3_CONFIG)
+#define bfin_write_MXVR_DMA3_CONFIG(val) bfin_write32(MXVR_DMA3_CONFIG, val)
+#define bfin_read_MXVR_DMA3_START_ADDR() bfin_readPTR(MXVR_DMA3_START_ADDR)
+#define bfin_write_MXVR_DMA3_START_ADDR(val) bfin_writePTR(MXVR_DMA3_START_ADDR, val)
+#define bfin_read_MXVR_DMA3_COUNT() bfin_read16(MXVR_DMA3_COUNT)
+#define bfin_write_MXVR_DMA3_COUNT(val) bfin_write16(MXVR_DMA3_COUNT, val)
+#define bfin_read_MXVR_DMA3_CURR_ADDR() bfin_readPTR(MXVR_DMA3_CURR_ADDR)
+#define bfin_write_MXVR_DMA3_CURR_ADDR(val) bfin_writePTR(MXVR_DMA3_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA3_CURR_COUNT() bfin_read16(MXVR_DMA3_CURR_COUNT)
+#define bfin_write_MXVR_DMA3_CURR_COUNT(val) bfin_write16(MXVR_DMA3_CURR_COUNT, val)
+#define bfin_read_MXVR_DMA4_CONFIG() bfin_read32(MXVR_DMA4_CONFIG)
+#define bfin_write_MXVR_DMA4_CONFIG(val) bfin_write32(MXVR_DMA4_CONFIG, val)
+#define bfin_read_MXVR_DMA4_START_ADDR() bfin_readPTR(MXVR_DMA4_START_ADDR)
+#define bfin_write_MXVR_DMA4_START_ADDR(val) bfin_writePTR(MXVR_DMA4_START_ADDR, val)
+#define bfin_read_MXVR_DMA4_COUNT() bfin_read16(MXVR_DMA4_COUNT)
+#define bfin_write_MXVR_DMA4_COUNT(val) bfin_write16(MXVR_DMA4_COUNT, val)
+#define bfin_read_MXVR_DMA4_CURR_ADDR() bfin_readPTR(MXVR_DMA4_CURR_ADDR)
+#define bfin_write_MXVR_DMA4_CURR_ADDR(val) bfin_writePTR(MXVR_DMA4_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA4_CURR_COUNT() bfin_read16(MXVR_DMA4_CURR_COUNT)
+#define bfin_write_MXVR_DMA4_CURR_COUNT(val) bfin_write16(MXVR_DMA4_CURR_COUNT, val)
+#define bfin_read_MXVR_DMA5_CONFIG() bfin_read32(MXVR_DMA5_CONFIG)
+#define bfin_write_MXVR_DMA5_CONFIG(val) bfin_write32(MXVR_DMA5_CONFIG, val)
+#define bfin_read_MXVR_DMA5_START_ADDR() bfin_readPTR(MXVR_DMA5_START_ADDR)
+#define bfin_write_MXVR_DMA5_START_ADDR(val) bfin_writePTR(MXVR_DMA5_START_ADDR, val)
+#define bfin_read_MXVR_DMA5_COUNT() bfin_read16(MXVR_DMA5_COUNT)
+#define bfin_write_MXVR_DMA5_COUNT(val) bfin_write16(MXVR_DMA5_COUNT, val)
+#define bfin_read_MXVR_DMA5_CURR_ADDR() bfin_readPTR(MXVR_DMA5_CURR_ADDR)
+#define bfin_write_MXVR_DMA5_CURR_ADDR(val) bfin_writePTR(MXVR_DMA5_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA5_CURR_COUNT() bfin_read16(MXVR_DMA5_CURR_COUNT)
+#define bfin_write_MXVR_DMA5_CURR_COUNT(val) bfin_write16(MXVR_DMA5_CURR_COUNT, val)
+#define bfin_read_MXVR_DMA6_CONFIG() bfin_read32(MXVR_DMA6_CONFIG)
+#define bfin_write_MXVR_DMA6_CONFIG(val) bfin_write32(MXVR_DMA6_CONFIG, val)
+#define bfin_read_MXVR_DMA6_START_ADDR() bfin_readPTR(MXVR_DMA6_START_ADDR)
+#define bfin_write_MXVR_DMA6_START_ADDR(val) bfin_writePTR(MXVR_DMA6_START_ADDR, val)
+#define bfin_read_MXVR_DMA6_COUNT() bfin_read16(MXVR_DMA6_COUNT)
+#define bfin_write_MXVR_DMA6_COUNT(val) bfin_write16(MXVR_DMA6_COUNT, val)
+#define bfin_read_MXVR_DMA6_CURR_ADDR() bfin_readPTR(MXVR_DMA6_CURR_ADDR)
+#define bfin_write_MXVR_DMA6_CURR_ADDR(val) bfin_writePTR(MXVR_DMA6_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA6_CURR_COUNT() bfin_read16(MXVR_DMA6_CURR_COUNT)
+#define bfin_write_MXVR_DMA6_CURR_COUNT(val) bfin_write16(MXVR_DMA6_CURR_COUNT, val)
+#define bfin_read_MXVR_DMA7_CONFIG() bfin_read32(MXVR_DMA7_CONFIG)
+#define bfin_write_MXVR_DMA7_CONFIG(val) bfin_write32(MXVR_DMA7_CONFIG, val)
+#define bfin_read_MXVR_DMA7_START_ADDR() bfin_readPTR(MXVR_DMA7_START_ADDR)
+#define bfin_write_MXVR_DMA7_START_ADDR(val) bfin_writePTR(MXVR_DMA7_START_ADDR, val)
+#define bfin_read_MXVR_DMA7_COUNT() bfin_read16(MXVR_DMA7_COUNT)
+#define bfin_write_MXVR_DMA7_COUNT(val) bfin_write16(MXVR_DMA7_COUNT, val)
+#define bfin_read_MXVR_DMA7_CURR_ADDR() bfin_readPTR(MXVR_DMA7_CURR_ADDR)
+#define bfin_write_MXVR_DMA7_CURR_ADDR(val) bfin_writePTR(MXVR_DMA7_CURR_ADDR, val)
+#define bfin_read_MXVR_DMA7_CURR_COUNT() bfin_read16(MXVR_DMA7_CURR_COUNT)
+#define bfin_write_MXVR_DMA7_CURR_COUNT(val) bfin_write16(MXVR_DMA7_CURR_COUNT, val)
+#define bfin_read_MXVR_AP_CTL() bfin_read16(MXVR_AP_CTL)
+#define bfin_write_MXVR_AP_CTL(val) bfin_write16(MXVR_AP_CTL, val)
+#define bfin_read_MXVR_APRB_START_ADDR() bfin_readPTR(MXVR_APRB_START_ADDR)
+#define bfin_write_MXVR_APRB_START_ADDR(val) bfin_writePTR(MXVR_APRB_START_ADDR, val)
+#define bfin_read_MXVR_APRB_CURR_ADDR() bfin_readPTR(MXVR_APRB_CURR_ADDR)
+#define bfin_write_MXVR_APRB_CURR_ADDR(val) bfin_writePTR(MXVR_APRB_CURR_ADDR, val)
+#define bfin_read_MXVR_APTB_START_ADDR() bfin_readPTR(MXVR_APTB_START_ADDR)
+#define bfin_write_MXVR_APTB_START_ADDR(val) bfin_writePTR(MXVR_APTB_START_ADDR, val)
+#define bfin_read_MXVR_APTB_CURR_ADDR() bfin_readPTR(MXVR_APTB_CURR_ADDR)
+#define bfin_write_MXVR_APTB_CURR_ADDR(val) bfin_writePTR(MXVR_APTB_CURR_ADDR, val)
+#define bfin_read_MXVR_CM_CTL() bfin_read32(MXVR_CM_CTL)
+#define bfin_write_MXVR_CM_CTL(val) bfin_write32(MXVR_CM_CTL, val)
+#define bfin_read_MXVR_CMRB_START_ADDR() bfin_readPTR(MXVR_CMRB_START_ADDR)
+#define bfin_write_MXVR_CMRB_START_ADDR(val) bfin_writePTR(MXVR_CMRB_START_ADDR, val)
+#define bfin_read_MXVR_CMRB_CURR_ADDR() bfin_readPTR(MXVR_CMRB_CURR_ADDR)
+#define bfin_write_MXVR_CMRB_CURR_ADDR(val) bfin_writePTR(MXVR_CMRB_CURR_ADDR, val)
+#define bfin_read_MXVR_CMTB_START_ADDR() bfin_readPTR(MXVR_CMTB_START_ADDR)
+#define bfin_write_MXVR_CMTB_START_ADDR(val) bfin_writePTR(MXVR_CMTB_START_ADDR, val)
+#define bfin_read_MXVR_CMTB_CURR_ADDR() bfin_readPTR(MXVR_CMTB_CURR_ADDR)
+#define bfin_write_MXVR_CMTB_CURR_ADDR(val) bfin_writePTR(MXVR_CMTB_CURR_ADDR, val)
+#define bfin_read_MXVR_RRDB_START_ADDR() bfin_readPTR(MXVR_RRDB_START_ADDR)
+#define bfin_write_MXVR_RRDB_START_ADDR(val) bfin_writePTR(MXVR_RRDB_START_ADDR, val)
+#define bfin_read_MXVR_RRDB_CURR_ADDR() bfin_readPTR(MXVR_RRDB_CURR_ADDR)
+#define bfin_write_MXVR_RRDB_CURR_ADDR(val) bfin_writePTR(MXVR_RRDB_CURR_ADDR, val)
+#define bfin_read_MXVR_PAT_DATA_0() bfin_read32(MXVR_PAT_DATA_0)
+#define bfin_write_MXVR_PAT_DATA_0(val) bfin_write32(MXVR_PAT_DATA_0, val)
+#define bfin_read_MXVR_PAT_EN_0() bfin_read32(MXVR_PAT_EN_0)
+#define bfin_write_MXVR_PAT_EN_0(val) bfin_write32(MXVR_PAT_EN_0, val)
+#define bfin_read_MXVR_PAT_DATA_1() bfin_read32(MXVR_PAT_DATA_1)
+#define bfin_write_MXVR_PAT_DATA_1(val) bfin_write32(MXVR_PAT_DATA_1, val)
+#define bfin_read_MXVR_PAT_EN_1() bfin_read32(MXVR_PAT_EN_1)
+#define bfin_write_MXVR_PAT_EN_1(val) bfin_write32(MXVR_PAT_EN_1, val)
+#define bfin_read_MXVR_FRAME_CNT_0() bfin_read16(MXVR_FRAME_CNT_0)
+#define bfin_write_MXVR_FRAME_CNT_0(val) bfin_write16(MXVR_FRAME_CNT_0, val)
+#define bfin_read_MXVR_FRAME_CNT_1() bfin_read16(MXVR_FRAME_CNT_1)
+#define bfin_write_MXVR_FRAME_CNT_1(val) bfin_write16(MXVR_FRAME_CNT_1, val)
+#define bfin_read_MXVR_ROUTING_0() bfin_read32(MXVR_ROUTING_0)
+#define bfin_write_MXVR_ROUTING_0(val) bfin_write32(MXVR_ROUTING_0, val)
+#define bfin_read_MXVR_ROUTING_1() bfin_read32(MXVR_ROUTING_1)
+#define bfin_write_MXVR_ROUTING_1(val) bfin_write32(MXVR_ROUTING_1, val)
+#define bfin_read_MXVR_ROUTING_2() bfin_read32(MXVR_ROUTING_2)
+#define bfin_write_MXVR_ROUTING_2(val) bfin_write32(MXVR_ROUTING_2, val)
+#define bfin_read_MXVR_ROUTING_3() bfin_read32(MXVR_ROUTING_3)
+#define bfin_write_MXVR_ROUTING_3(val) bfin_write32(MXVR_ROUTING_3, val)
+#define bfin_read_MXVR_ROUTING_4() bfin_read32(MXVR_ROUTING_4)
+#define bfin_write_MXVR_ROUTING_4(val) bfin_write32(MXVR_ROUTING_4, val)
+#define bfin_read_MXVR_ROUTING_5() bfin_read32(MXVR_ROUTING_5)
+#define bfin_write_MXVR_ROUTING_5(val) bfin_write32(MXVR_ROUTING_5, val)
+#define bfin_read_MXVR_ROUTING_6() bfin_read32(MXVR_ROUTING_6)
+#define bfin_write_MXVR_ROUTING_6(val) bfin_write32(MXVR_ROUTING_6, val)
+#define bfin_read_MXVR_ROUTING_7() bfin_read32(MXVR_ROUTING_7)
+#define bfin_write_MXVR_ROUTING_7(val) bfin_write32(MXVR_ROUTING_7, val)
+#define bfin_read_MXVR_ROUTING_8() bfin_read32(MXVR_ROUTING_8)
+#define bfin_write_MXVR_ROUTING_8(val) bfin_write32(MXVR_ROUTING_8, val)
+#define bfin_read_MXVR_ROUTING_9() bfin_read32(MXVR_ROUTING_9)
+#define bfin_write_MXVR_ROUTING_9(val) bfin_write32(MXVR_ROUTING_9, val)
+#define bfin_read_MXVR_ROUTING_10() bfin_read32(MXVR_ROUTING_10)
+#define bfin_write_MXVR_ROUTING_10(val) bfin_write32(MXVR_ROUTING_10, val)
+#define bfin_read_MXVR_ROUTING_11() bfin_read32(MXVR_ROUTING_11)
+#define bfin_write_MXVR_ROUTING_11(val) bfin_write32(MXVR_ROUTING_11, val)
+#define bfin_read_MXVR_ROUTING_12() bfin_read32(MXVR_ROUTING_12)
+#define bfin_write_MXVR_ROUTING_12(val) bfin_write32(MXVR_ROUTING_12, val)
+#define bfin_read_MXVR_ROUTING_13() bfin_read32(MXVR_ROUTING_13)
+#define bfin_write_MXVR_ROUTING_13(val) bfin_write32(MXVR_ROUTING_13, val)
+#define bfin_read_MXVR_ROUTING_14() bfin_read32(MXVR_ROUTING_14)
+#define bfin_write_MXVR_ROUTING_14(val) bfin_write32(MXVR_ROUTING_14, val)
+#define bfin_read_MXVR_PLL_CTL_1() bfin_read32(MXVR_PLL_CTL_1)
+#define bfin_write_MXVR_PLL_CTL_1(val) bfin_write32(MXVR_PLL_CTL_1, val)
+#define bfin_read_MXVR_BLOCK_CNT() bfin_read16(MXVR_BLOCK_CNT)
+#define bfin_write_MXVR_BLOCK_CNT(val) bfin_write16(MXVR_BLOCK_CNT, val)
+
+#endif /* _CDEF_BF539_H */
diff --git a/arch/blackfin/mach-bf538/include/mach/defBF539.h b/arch/blackfin/mach-bf538/include/mach/defBF539.h
new file mode 100644
index 000000000000..6adbfcc65a35
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/defBF539.h
@@ -0,0 +1,4243 @@
+/************************************************************************
+ *
+ * This file is subject to the terms and conditions of the GNU Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Non-GPL License also available as part of VisualDSP++
+ * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html
+ *
+ * (c) Copyright 2001-2005 Analog Devices, Inc. All rights reserved
+ *
+ * This file under source code control, please send bugs or changes to:
+ * dsptools.support@analog.com
+ *
+ ************************************************************************/
+/*
+ * File: include/asm-blackfin/mach-bf538/defBF539.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* SYSTEM & MM REGISTER BIT & ADDRESS DEFINITIONS FOR ADSP-BF538/9 */
+
+#ifndef _DEF_BF539_H
+#define _DEF_BF539_H
+
+/* include all Core registers and bit definitions */
+#include <asm/def_LPBlackfin.h>
+
+
+/*********************************************************************************** */
+/* System MMR Register Map */
+/*********************************************************************************** */
+/* Clock/Regulator Control (0xFFC00000 - 0xFFC000FF) */
+#define PLL_CTL 0xFFC00000 /* PLL Control register (16-bit) */
+#define PLL_DIV 0xFFC00004 /* PLL Divide Register (16-bit) */
+#define VR_CTL 0xFFC00008 /* Voltage Regulator Control Register (16-bit) */
+#define PLL_STAT 0xFFC0000C /* PLL Status register (16-bit) */
+#define PLL_LOCKCNT 0xFFC00010 /* PLL Lock Count register (16-bit) */
+#define CHIPID 0xFFC00014 /* Chip ID Register */
+
+/* CHIPID Masks */
+#define CHIPID_VERSION 0xF0000000
+#define CHIPID_FAMILY 0x0FFFF000
+#define CHIPID_MANUFACTURE 0x00000FFE
+
+/* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */
+#define SWRST 0xFFC00100 /* Software Reset Register (16-bit) */
+#define SYSCR 0xFFC00104 /* System Configuration registe */
+#define SIC_IMASK0 0xFFC0010C /* Interrupt Mask Register */
+#define SIC_IAR0 0xFFC00110 /* Interrupt Assignment Register 0 */
+#define SIC_IAR1 0xFFC00114 /* Interrupt Assignment Register 1 */
+#define SIC_IAR2 0xFFC00118 /* Interrupt Assignment Register 2 */
+#define SIC_IAR3 0xFFC0011C /* Interrupt Assignment Register 3 */
+#define SIC_ISR0 0xFFC00120 /* Interrupt Status Register */
+#define SIC_IWR0 0xFFC00124 /* Interrupt Wakeup Register */
+#define SIC_IMASK1 0xFFC00128 /* Interrupt Mask Register 1 */
+#define SIC_ISR1 0xFFC0012C /* Interrupt Status Register 1 */
+#define SIC_IWR1 0xFFC00130 /* Interrupt Wakeup Register 1 */
+#define SIC_IAR4 0xFFC00134 /* Interrupt Assignment Register 4 */
+#define SIC_IAR5 0xFFC00138 /* Interrupt Assignment Register 5 */
+#define SIC_IAR6 0xFFC0013C /* Interrupt Assignment Register 6 */
+
+
+/* Watchdog Timer (0xFFC00200 - 0xFFC002FF) */
+#define WDOG_CTL 0xFFC00200 /* Watchdog Control Register */
+#define WDOG_CNT 0xFFC00204 /* Watchdog Count Register */
+#define WDOG_STAT 0xFFC00208 /* Watchdog Status Register */
+
+
+/* Real Time Clock (0xFFC00300 - 0xFFC003FF) */
+#define RTC_STAT 0xFFC00300 /* RTC Status Register */
+#define RTC_ICTL 0xFFC00304 /* RTC Interrupt Control Register */
+#define RTC_ISTAT 0xFFC00308 /* RTC Interrupt Status Register */
+#define RTC_SWCNT 0xFFC0030C /* RTC Stopwatch Count Register */
+#define RTC_ALARM 0xFFC00310 /* RTC Alarm Time Register */
+#define RTC_FAST 0xFFC00314 /* RTC Prescaler Enable Register */
+#define RTC_PREN 0xFFC00314 /* RTC Prescaler Enable Register (alternate macro) */
+
+
+/* UART0 Controller (0xFFC00400 - 0xFFC004FF) */
+#define UART0_THR 0xFFC00400 /* Transmit Holding register */
+#define UART0_RBR 0xFFC00400 /* Receive Buffer register */
+#define UART0_DLL 0xFFC00400 /* Divisor Latch (Low-Byte) */
+#define UART0_IER 0xFFC00404 /* Interrupt Enable Register */
+#define UART0_DLH 0xFFC00404 /* Divisor Latch (High-Byte) */
+#define UART0_IIR 0xFFC00408 /* Interrupt Identification Register */
+#define UART0_LCR 0xFFC0040C /* Line Control Register */
+#define UART0_MCR 0xFFC00410 /* Modem Control Register */
+#define UART0_LSR 0xFFC00414 /* Line Status Register */
+#define UART0_SCR 0xFFC0041C /* SCR Scratch Register */
+#define UART0_GCTL 0xFFC00424 /* Global Control Register */
+
+
+/* SPI0 Controller (0xFFC00500 - 0xFFC005FF) */
+
+#define SPI0_CTL 0xFFC00500 /* SPI0 Control Register */
+#define SPI0_FLG 0xFFC00504 /* SPI0 Flag register */
+#define SPI0_STAT 0xFFC00508 /* SPI0 Status register */
+#define SPI0_TDBR 0xFFC0050C /* SPI0 Transmit Data Buffer Register */
+#define SPI0_RDBR 0xFFC00510 /* SPI0 Receive Data Buffer Register */
+#define SPI0_BAUD 0xFFC00514 /* SPI0 Baud rate Register */
+#define SPI0_SHADOW 0xFFC00518 /* SPI0_RDBR Shadow Register */
+#define SPI0_REGBASE SPI0_CTL
+
+
+/* TIMER 0, 1, 2 Registers (0xFFC00600 - 0xFFC006FF) */
+#define TIMER0_CONFIG 0xFFC00600 /* Timer 0 Configuration Register */
+#define TIMER0_COUNTER 0xFFC00604 /* Timer 0 Counter Register */
+#define TIMER0_PERIOD 0xFFC00608 /* Timer 0 Period Register */
+#define TIMER0_WIDTH 0xFFC0060C /* Timer 0 Width Register */
+
+#define TIMER1_CONFIG 0xFFC00610 /* Timer 1 Configuration Register */
+#define TIMER1_COUNTER 0xFFC00614 /* Timer 1 Counter Register */
+#define TIMER1_PERIOD 0xFFC00618 /* Timer 1 Period Register */
+#define TIMER1_WIDTH 0xFFC0061C /* Timer 1 Width Register */
+
+#define TIMER2_CONFIG 0xFFC00620 /* Timer 2 Configuration Register */
+#define TIMER2_COUNTER 0xFFC00624 /* Timer 2 Counter Register */
+#define TIMER2_PERIOD 0xFFC00628 /* Timer 2 Period Register */
+#define TIMER2_WIDTH 0xFFC0062C /* Timer 2 Width Register */
+
+#define TIMER_ENABLE 0xFFC00640 /* Timer Enable Register */
+#define TIMER_DISABLE 0xFFC00644 /* Timer Disable Register */
+#define TIMER_STATUS 0xFFC00648 /* Timer Status Register */
+
+
+/* Programmable Flags (0xFFC00700 - 0xFFC007FF) */
+#define FIO_FLAG_D 0xFFC00700 /* Flag Mask to directly specify state of pins */
+#define FIO_FLAG_C 0xFFC00704 /* Peripheral Interrupt Flag Register (clear) */
+#define FIO_FLAG_S 0xFFC00708 /* Peripheral Interrupt Flag Register (set) */
+#define FIO_FLAG_T 0xFFC0070C /* Flag Mask to directly toggle state of pins */
+#define FIO_MASKA_D 0xFFC00710 /* Flag Mask Interrupt A Register (set directly) */
+#define FIO_MASKA_C 0xFFC00714 /* Flag Mask Interrupt A Register (clear) */
+#define FIO_MASKA_S 0xFFC00718 /* Flag Mask Interrupt A Register (set) */
+#define FIO_MASKA_T 0xFFC0071C /* Flag Mask Interrupt A Register (toggle) */
+#define FIO_MASKB_D 0xFFC00720 /* Flag Mask Interrupt B Register (set directly) */
+#define FIO_MASKB_C 0xFFC00724 /* Flag Mask Interrupt B Register (clear) */
+#define FIO_MASKB_S 0xFFC00728 /* Flag Mask Interrupt B Register (set) */
+#define FIO_MASKB_T 0xFFC0072C /* Flag Mask Interrupt B Register (toggle) */
+#define FIO_DIR 0xFFC00730 /* Peripheral Flag Direction Register */
+#define FIO_POLAR 0xFFC00734 /* Flag Source Polarity Register */
+#define FIO_EDGE 0xFFC00738 /* Flag Source Sensitivity Register */
+#define FIO_BOTH 0xFFC0073C /* Flag Set on BOTH Edges Register */
+#define FIO_INEN 0xFFC00740 /* Flag Input Enable Register */
+
+
+/* SPORT0 Controller (0xFFC00800 - 0xFFC008FF) */
+#define SPORT0_TCR1 0xFFC00800 /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_TCR2 0xFFC00804 /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_TCLKDIV 0xFFC00808 /* SPORT0 Transmit Clock Divider */
+#define SPORT0_TFSDIV 0xFFC0080C /* SPORT0 Transmit Frame Sync Divider */
+#define SPORT0_TX 0xFFC00810 /* SPORT0 TX Data Register */
+#define SPORT0_RX 0xFFC00818 /* SPORT0 RX Data Register */
+#define SPORT0_RCR1 0xFFC00820 /* SPORT0 Transmit Configuration 1 Register */
+#define SPORT0_RCR2 0xFFC00824 /* SPORT0 Transmit Configuration 2 Register */
+#define SPORT0_RCLKDIV 0xFFC00828 /* SPORT0 Receive Clock Divider */
+#define SPORT0_RFSDIV 0xFFC0082C /* SPORT0 Receive Frame Sync Divider */
+#define SPORT0_STAT 0xFFC00830 /* SPORT0 Status Register */
+#define SPORT0_CHNL 0xFFC00834 /* SPORT0 Current Channel Register */
+#define SPORT0_MCMC1 0xFFC00838 /* SPORT0 Multi-Channel Configuration Register 1 */
+#define SPORT0_MCMC2 0xFFC0083C /* SPORT0 Multi-Channel Configuration Register 2 */
+#define SPORT0_MTCS0 0xFFC00840 /* SPORT0 Multi-Channel Transmit Select Register 0 */
+#define SPORT0_MTCS1 0xFFC00844 /* SPORT0 Multi-Channel Transmit Select Register 1 */
+#define SPORT0_MTCS2 0xFFC00848 /* SPORT0 Multi-Channel Transmit Select Register 2 */
+#define SPORT0_MTCS3 0xFFC0084C /* SPORT0 Multi-Channel Transmit Select Register 3 */
+#define SPORT0_MRCS0 0xFFC00850 /* SPORT0 Multi-Channel Receive Select Register 0 */
+#define SPORT0_MRCS1 0xFFC00854 /* SPORT0 Multi-Channel Receive Select Register 1 */
+#define SPORT0_MRCS2 0xFFC00858 /* SPORT0 Multi-Channel Receive Select Register 2 */
+#define SPORT0_MRCS3 0xFFC0085C /* SPORT0 Multi-Channel Receive Select Register 3 */
+
+
+/* SPORT1 Controller (0xFFC00900 - 0xFFC009FF) */
+#define SPORT1_TCR1 0xFFC00900 /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_TCR2 0xFFC00904 /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_TCLKDIV 0xFFC00908 /* SPORT1 Transmit Clock Divider */
+#define SPORT1_TFSDIV 0xFFC0090C /* SPORT1 Transmit Frame Sync Divider */
+#define SPORT1_TX 0xFFC00910 /* SPORT1 TX Data Register */
+#define SPORT1_RX 0xFFC00918 /* SPORT1 RX Data Register */
+#define SPORT1_RCR1 0xFFC00920 /* SPORT1 Transmit Configuration 1 Register */
+#define SPORT1_RCR2 0xFFC00924 /* SPORT1 Transmit Configuration 2 Register */
+#define SPORT1_RCLKDIV 0xFFC00928 /* SPORT1 Receive Clock Divider */
+#define SPORT1_RFSDIV 0xFFC0092C /* SPORT1 Receive Frame Sync Divider */
+#define SPORT1_STAT 0xFFC00930 /* SPORT1 Status Register */
+#define SPORT1_CHNL 0xFFC00934 /* SPORT1 Current Channel Register */
+#define SPORT1_MCMC1 0xFFC00938 /* SPORT1 Multi-Channel Configuration Register 1 */
+#define SPORT1_MCMC2 0xFFC0093C /* SPORT1 Multi-Channel Configuration Register 2 */
+#define SPORT1_MTCS0 0xFFC00940 /* SPORT1 Multi-Channel Transmit Select Register 0 */
+#define SPORT1_MTCS1 0xFFC00944 /* SPORT1 Multi-Channel Transmit Select Register 1 */
+#define SPORT1_MTCS2 0xFFC00948 /* SPORT1 Multi-Channel Transmit Select Register 2 */
+#define SPORT1_MTCS3 0xFFC0094C /* SPORT1 Multi-Channel Transmit Select Register 3 */
+#define SPORT1_MRCS0 0xFFC00950 /* SPORT1 Multi-Channel Receive Select Register 0 */
+#define SPORT1_MRCS1 0xFFC00954 /* SPORT1 Multi-Channel Receive Select Register 1 */
+#define SPORT1_MRCS2 0xFFC00958 /* SPORT1 Multi-Channel Receive Select Register 2 */
+#define SPORT1_MRCS3 0xFFC0095C /* SPORT1 Multi-Channel Receive Select Register 3 */
+
+
+/* External Bus Interface Unit (0xFFC00A00 - 0xFFC00AFF) */
+/* Asynchronous Memory Controller */
+#define EBIU_AMGCTL 0xFFC00A00 /* Asynchronous Memory Global Control Register */
+#define EBIU_AMBCTL0 0xFFC00A04 /* Asynchronous Memory Bank Control Register 0 */
+#define EBIU_AMBCTL1 0xFFC00A08 /* Asynchronous Memory Bank Control Register 1 */
+
+/* SDRAM Controller */
+#define EBIU_SDGCTL 0xFFC00A10 /* SDRAM Global Control Register */
+#define EBIU_SDBCTL 0xFFC00A14 /* SDRAM Bank Control Register */
+#define EBIU_SDRRC 0xFFC00A18 /* SDRAM Refresh Rate Control Register */
+#define EBIU_SDSTAT 0xFFC00A1C /* SDRAM Status Register */
+
+
+
+/* DMA Controller 0 Traffic Control Registers (0xFFC00B00 - 0xFFC00BFF) */
+
+#define DMAC0_TC_PER 0xFFC00B0C /* DMA Controller 0 Traffic Control Periods Register */
+#define DMAC0_TC_CNT 0xFFC00B10 /* DMA Controller 0 Traffic Control Current Counts Register */
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define DMA0_TCPER DMAC0_TC_PER
+#define DMA0_TCCNT DMAC0_TC_CNT
+
+
+/* DMA Controller 0 (0xFFC00C00 - 0xFFC00FFF) */
+
+#define DMA0_NEXT_DESC_PTR 0xFFC00C00 /* DMA Channel 0 Next Descriptor Pointer Register */
+#define DMA0_START_ADDR 0xFFC00C04 /* DMA Channel 0 Start Address Register */
+#define DMA0_CONFIG 0xFFC00C08 /* DMA Channel 0 Configuration Register */
+#define DMA0_X_COUNT 0xFFC00C10 /* DMA Channel 0 X Count Register */
+#define DMA0_X_MODIFY 0xFFC00C14 /* DMA Channel 0 X Modify Register */
+#define DMA0_Y_COUNT 0xFFC00C18 /* DMA Channel 0 Y Count Register */
+#define DMA0_Y_MODIFY 0xFFC00C1C /* DMA Channel 0 Y Modify Register */
+#define DMA0_CURR_DESC_PTR 0xFFC00C20 /* DMA Channel 0 Current Descriptor Pointer Register */
+#define DMA0_CURR_ADDR 0xFFC00C24 /* DMA Channel 0 Current Address Register */
+#define DMA0_IRQ_STATUS 0xFFC00C28 /* DMA Channel 0 Interrupt/Status Register */
+#define DMA0_PERIPHERAL_MAP 0xFFC00C2C /* DMA Channel 0 Peripheral Map Register */
+#define DMA0_CURR_X_COUNT 0xFFC00C30 /* DMA Channel 0 Current X Count Register */
+#define DMA0_CURR_Y_COUNT 0xFFC00C38 /* DMA Channel 0 Current Y Count Register */
+
+#define DMA1_NEXT_DESC_PTR 0xFFC00C40 /* DMA Channel 1 Next Descriptor Pointer Register */
+#define DMA1_START_ADDR 0xFFC00C44 /* DMA Channel 1 Start Address Register */
+#define DMA1_CONFIG 0xFFC00C48 /* DMA Channel 1 Configuration Register */
+#define DMA1_X_COUNT 0xFFC00C50 /* DMA Channel 1 X Count Register */
+#define DMA1_X_MODIFY 0xFFC00C54 /* DMA Channel 1 X Modify Register */
+#define DMA1_Y_COUNT 0xFFC00C58 /* DMA Channel 1 Y Count Register */
+#define DMA1_Y_MODIFY 0xFFC00C5C /* DMA Channel 1 Y Modify Register */
+#define DMA1_CURR_DESC_PTR 0xFFC00C60 /* DMA Channel 1 Current Descriptor Pointer Register */
+#define DMA1_CURR_ADDR 0xFFC00C64 /* DMA Channel 1 Current Address Register */
+#define DMA1_IRQ_STATUS 0xFFC00C68 /* DMA Channel 1 Interrupt/Status Register */
+#define DMA1_PERIPHERAL_MAP 0xFFC00C6C /* DMA Channel 1 Peripheral Map Register */
+#define DMA1_CURR_X_COUNT 0xFFC00C70 /* DMA Channel 1 Current X Count Register */
+#define DMA1_CURR_Y_COUNT 0xFFC00C78 /* DMA Channel 1 Current Y Count Register */
+
+#define DMA2_NEXT_DESC_PTR 0xFFC00C80 /* DMA Channel 2 Next Descriptor Pointer Register */
+#define DMA2_START_ADDR 0xFFC00C84 /* DMA Channel 2 Start Address Register */
+#define DMA2_CONFIG 0xFFC00C88 /* DMA Channel 2 Configuration Register */
+#define DMA2_X_COUNT 0xFFC00C90 /* DMA Channel 2 X Count Register */
+#define DMA2_X_MODIFY 0xFFC00C94 /* DMA Channel 2 X Modify Register */
+#define DMA2_Y_COUNT 0xFFC00C98 /* DMA Channel 2 Y Count Register */
+#define DMA2_Y_MODIFY 0xFFC00C9C /* DMA Channel 2 Y Modify Register */
+#define DMA2_CURR_DESC_PTR 0xFFC00CA0 /* DMA Channel 2 Current Descriptor Pointer Register */
+#define DMA2_CURR_ADDR 0xFFC00CA4 /* DMA Channel 2 Current Address Register */
+#define DMA2_IRQ_STATUS 0xFFC00CA8 /* DMA Channel 2 Interrupt/Status Register */
+#define DMA2_PERIPHERAL_MAP 0xFFC00CAC /* DMA Channel 2 Peripheral Map Register */
+#define DMA2_CURR_X_COUNT 0xFFC00CB0 /* DMA Channel 2 Current X Count Register */
+#define DMA2_CURR_Y_COUNT 0xFFC00CB8 /* DMA Channel 2 Current Y Count Register */
+
+#define DMA3_NEXT_DESC_PTR 0xFFC00CC0 /* DMA Channel 3 Next Descriptor Pointer Register */
+#define DMA3_START_ADDR 0xFFC00CC4 /* DMA Channel 3 Start Address Register */
+#define DMA3_CONFIG 0xFFC00CC8 /* DMA Channel 3 Configuration Register */
+#define DMA3_X_COUNT 0xFFC00CD0 /* DMA Channel 3 X Count Register */
+#define DMA3_X_MODIFY 0xFFC00CD4 /* DMA Channel 3 X Modify Register */
+#define DMA3_Y_COUNT 0xFFC00CD8 /* DMA Channel 3 Y Count Register */
+#define DMA3_Y_MODIFY 0xFFC00CDC /* DMA Channel 3 Y Modify Register */
+#define DMA3_CURR_DESC_PTR 0xFFC00CE0 /* DMA Channel 3 Current Descriptor Pointer Register */
+#define DMA3_CURR_ADDR 0xFFC00CE4 /* DMA Channel 3 Current Address Register */
+#define DMA3_IRQ_STATUS 0xFFC00CE8 /* DMA Channel 3 Interrupt/Status Register */
+#define DMA3_PERIPHERAL_MAP 0xFFC00CEC /* DMA Channel 3 Peripheral Map Register */
+#define DMA3_CURR_X_COUNT 0xFFC00CF0 /* DMA Channel 3 Current X Count Register */
+#define DMA3_CURR_Y_COUNT 0xFFC00CF8 /* DMA Channel 3 Current Y Count Register */
+
+#define DMA4_NEXT_DESC_PTR 0xFFC00D00 /* DMA Channel 4 Next Descriptor Pointer Register */
+#define DMA4_START_ADDR 0xFFC00D04 /* DMA Channel 4 Start Address Register */
+#define DMA4_CONFIG 0xFFC00D08 /* DMA Channel 4 Configuration Register */
+#define DMA4_X_COUNT 0xFFC00D10 /* DMA Channel 4 X Count Register */
+#define DMA4_X_MODIFY 0xFFC00D14 /* DMA Channel 4 X Modify Register */
+#define DMA4_Y_COUNT 0xFFC00D18 /* DMA Channel 4 Y Count Register */
+#define DMA4_Y_MODIFY 0xFFC00D1C /* DMA Channel 4 Y Modify Register */
+#define DMA4_CURR_DESC_PTR 0xFFC00D20 /* DMA Channel 4 Current Descriptor Pointer Register */
+#define DMA4_CURR_ADDR 0xFFC00D24 /* DMA Channel 4 Current Address Register */
+#define DMA4_IRQ_STATUS 0xFFC00D28 /* DMA Channel 4 Interrupt/Status Register */
+#define DMA4_PERIPHERAL_MAP 0xFFC00D2C /* DMA Channel 4 Peripheral Map Register */
+#define DMA4_CURR_X_COUNT 0xFFC00D30 /* DMA Channel 4 Current X Count Register */
+#define DMA4_CURR_Y_COUNT 0xFFC00D38 /* DMA Channel 4 Current Y Count Register */
+
+#define DMA5_NEXT_DESC_PTR 0xFFC00D40 /* DMA Channel 5 Next Descriptor Pointer Register */
+#define DMA5_START_ADDR 0xFFC00D44 /* DMA Channel 5 Start Address Register */
+#define DMA5_CONFIG 0xFFC00D48 /* DMA Channel 5 Configuration Register */
+#define DMA5_X_COUNT 0xFFC00D50 /* DMA Channel 5 X Count Register */
+#define DMA5_X_MODIFY 0xFFC00D54 /* DMA Channel 5 X Modify Register */
+#define DMA5_Y_COUNT 0xFFC00D58 /* DMA Channel 5 Y Count Register */
+#define DMA5_Y_MODIFY 0xFFC00D5C /* DMA Channel 5 Y Modify Register */
+#define DMA5_CURR_DESC_PTR 0xFFC00D60 /* DMA Channel 5 Current Descriptor Pointer Register */
+#define DMA5_CURR_ADDR 0xFFC00D64 /* DMA Channel 5 Current Address Register */
+#define DMA5_IRQ_STATUS 0xFFC00D68 /* DMA Channel 5 Interrupt/Status Register */
+#define DMA5_PERIPHERAL_MAP 0xFFC00D6C /* DMA Channel 5 Peripheral Map Register */
+#define DMA5_CURR_X_COUNT 0xFFC00D70 /* DMA Channel 5 Current X Count Register */
+#define DMA5_CURR_Y_COUNT 0xFFC00D78 /* DMA Channel 5 Current Y Count Register */
+
+#define DMA6_NEXT_DESC_PTR 0xFFC00D80 /* DMA Channel 6 Next Descriptor Pointer Register */
+#define DMA6_START_ADDR 0xFFC00D84 /* DMA Channel 6 Start Address Register */
+#define DMA6_CONFIG 0xFFC00D88 /* DMA Channel 6 Configuration Register */
+#define DMA6_X_COUNT 0xFFC00D90 /* DMA Channel 6 X Count Register */
+#define DMA6_X_MODIFY 0xFFC00D94 /* DMA Channel 6 X Modify Register */
+#define DMA6_Y_COUNT 0xFFC00D98 /* DMA Channel 6 Y Count Register */
+#define DMA6_Y_MODIFY 0xFFC00D9C /* DMA Channel 6 Y Modify Register */
+#define DMA6_CURR_DESC_PTR 0xFFC00DA0 /* DMA Channel 6 Current Descriptor Pointer Register */
+#define DMA6_CURR_ADDR 0xFFC00DA4 /* DMA Channel 6 Current Address Register */
+#define DMA6_IRQ_STATUS 0xFFC00DA8 /* DMA Channel 6 Interrupt/Status Register */
+#define DMA6_PERIPHERAL_MAP 0xFFC00DAC /* DMA Channel 6 Peripheral Map Register */
+#define DMA6_CURR_X_COUNT 0xFFC00DB0 /* DMA Channel 6 Current X Count Register */
+#define DMA6_CURR_Y_COUNT 0xFFC00DB8 /* DMA Channel 6 Current Y Count Register */
+
+#define DMA7_NEXT_DESC_PTR 0xFFC00DC0 /* DMA Channel 7 Next Descriptor Pointer Register */
+#define DMA7_START_ADDR 0xFFC00DC4 /* DMA Channel 7 Start Address Register */
+#define DMA7_CONFIG 0xFFC00DC8 /* DMA Channel 7 Configuration Register */
+#define DMA7_X_COUNT 0xFFC00DD0 /* DMA Channel 7 X Count Register */
+#define DMA7_X_MODIFY 0xFFC00DD4 /* DMA Channel 7 X Modify Register */
+#define DMA7_Y_COUNT 0xFFC00DD8 /* DMA Channel 7 Y Count Register */
+#define DMA7_Y_MODIFY 0xFFC00DDC /* DMA Channel 7 Y Modify Register */
+#define DMA7_CURR_DESC_PTR 0xFFC00DE0 /* DMA Channel 7 Current Descriptor Pointer Register */
+#define DMA7_CURR_ADDR 0xFFC00DE4 /* DMA Channel 7 Current Address Register */
+#define DMA7_IRQ_STATUS 0xFFC00DE8 /* DMA Channel 7 Interrupt/Status Register */
+#define DMA7_PERIPHERAL_MAP 0xFFC00DEC /* DMA Channel 7 Peripheral Map Register */
+#define DMA7_CURR_X_COUNT 0xFFC00DF0 /* DMA Channel 7 Current X Count Register */
+#define DMA7_CURR_Y_COUNT 0xFFC00DF8 /* DMA Channel 7 Current Y Count Register */
+
+#define MDMA0_D0_NEXT_DESC_PTR 0xFFC00E00 /* MemDMA0 Stream 0 Destination Next Descriptor Pointer Register */
+#define MDMA0_D0_START_ADDR 0xFFC00E04 /* MemDMA0 Stream 0 Destination Start Address Register */
+#define MDMA0_D0_CONFIG 0xFFC00E08 /* MemDMA0 Stream 0 Destination Configuration Register */
+#define MDMA0_D0_X_COUNT 0xFFC00E10 /* MemDMA0 Stream 0 Destination X Count Register */
+#define MDMA0_D0_X_MODIFY 0xFFC00E14 /* MemDMA0 Stream 0 Destination X Modify Register */
+#define MDMA0_D0_Y_COUNT 0xFFC00E18 /* MemDMA0 Stream 0 Destination Y Count Register */
+#define MDMA0_D0_Y_MODIFY 0xFFC00E1C /* MemDMA0 Stream 0 Destination Y Modify Register */
+#define MDMA0_D0_CURR_DESC_PTR 0xFFC00E20 /* MemDMA0 Stream 0 Destination Current Descriptor Pointer Register */
+#define MDMA0_D0_CURR_ADDR 0xFFC00E24 /* MemDMA0 Stream 0 Destination Current Address Register */
+#define MDMA0_D0_IRQ_STATUS 0xFFC00E28 /* MemDMA0 Stream 0 Destination Interrupt/Status Register */
+#define MDMA0_D0_PERIPHERAL_MAP 0xFFC00E2C /* MemDMA0 Stream 0 Destination Peripheral Map Register */
+#define MDMA0_D0_CURR_X_COUNT 0xFFC00E30 /* MemDMA0 Stream 0 Destination Current X Count Register */
+#define MDMA0_D0_CURR_Y_COUNT 0xFFC00E38 /* MemDMA0 Stream 0 Destination Current Y Count Register */
+
+#define MDMA0_S0_NEXT_DESC_PTR 0xFFC00E40 /* MemDMA0 Stream 0 Source Next Descriptor Pointer Register */
+#define MDMA0_S0_START_ADDR 0xFFC00E44 /* MemDMA0 Stream 0 Source Start Address Register */
+#define MDMA0_S0_CONFIG 0xFFC00E48 /* MemDMA0 Stream 0 Source Configuration Register */
+#define MDMA0_S0_X_COUNT 0xFFC00E50 /* MemDMA0 Stream 0 Source X Count Register */
+#define MDMA0_S0_X_MODIFY 0xFFC00E54 /* MemDMA0 Stream 0 Source X Modify Register */
+#define MDMA0_S0_Y_COUNT 0xFFC00E58 /* MemDMA0 Stream 0 Source Y Count Register */
+#define MDMA0_S0_Y_MODIFY 0xFFC00E5C /* MemDMA0 Stream 0 Source Y Modify Register */
+#define MDMA0_S0_CURR_DESC_PTR 0xFFC00E60 /* MemDMA0 Stream 0 Source Current Descriptor Pointer Register */
+#define MDMA0_S0_CURR_ADDR 0xFFC00E64 /* MemDMA0 Stream 0 Source Current Address Register */
+#define MDMA0_S0_IRQ_STATUS 0xFFC00E68 /* MemDMA0 Stream 0 Source Interrupt/Status Register */
+#define MDMA0_S0_PERIPHERAL_MAP 0xFFC00E6C /* MemDMA0 Stream 0 Source Peripheral Map Register */
+#define MDMA0_S0_CURR_X_COUNT 0xFFC00E70 /* MemDMA0 Stream 0 Source Current X Count Register */
+#define MDMA0_S0_CURR_Y_COUNT 0xFFC00E78 /* MemDMA0 Stream 0 Source Current Y Count Register */
+
+#define MDMA0_D1_NEXT_DESC_PTR 0xFFC00E80 /* MemDMA0 Stream 1 Destination Next Descriptor Pointer Register */
+#define MDMA0_D1_START_ADDR 0xFFC00E84 /* MemDMA0 Stream 1 Destination Start Address Register */
+#define MDMA0_D1_CONFIG 0xFFC00E88 /* MemDMA0 Stream 1 Destination Configuration Register */
+#define MDMA0_D1_X_COUNT 0xFFC00E90 /* MemDMA0 Stream 1 Destination X Count Register */
+#define MDMA0_D1_X_MODIFY 0xFFC00E94 /* MemDMA0 Stream 1 Destination X Modify Register */
+#define MDMA0_D1_Y_COUNT 0xFFC00E98 /* MemDMA0 Stream 1 Destination Y Count Register */
+#define MDMA0_D1_Y_MODIFY 0xFFC00E9C /* MemDMA0 Stream 1 Destination Y Modify Register */
+#define MDMA0_D1_CURR_DESC_PTR 0xFFC00EA0 /* MemDMA0 Stream 1 Destination Current Descriptor Pointer Register */
+#define MDMA0_D1_CURR_ADDR 0xFFC00EA4 /* MemDMA0 Stream 1 Destination Current Address Register */
+#define MDMA0_D1_IRQ_STATUS 0xFFC00EA8 /* MemDMA0 Stream 1 Destination Interrupt/Status Register */
+#define MDMA0_D1_PERIPHERAL_MAP 0xFFC00EAC /* MemDMA0 Stream 1 Destination Peripheral Map Register */
+#define MDMA0_D1_CURR_X_COUNT 0xFFC00EB0 /* MemDMA0 Stream 1 Destination Current X Count Register */
+#define MDMA0_D1_CURR_Y_COUNT 0xFFC00EB8 /* MemDMA0 Stream 1 Destination Current Y Count Register */
+
+#define MDMA0_S1_NEXT_DESC_PTR 0xFFC00EC0 /* MemDMA0 Stream 1 Source Next Descriptor Pointer Register */
+#define MDMA0_S1_START_ADDR 0xFFC00EC4 /* MemDMA0 Stream 1 Source Start Address Register */
+#define MDMA0_S1_CONFIG 0xFFC00EC8 /* MemDMA0 Stream 1 Source Configuration Register */
+#define MDMA0_S1_X_COUNT 0xFFC00ED0 /* MemDMA0 Stream 1 Source X Count Register */
+#define MDMA0_S1_X_MODIFY 0xFFC00ED4 /* MemDMA0 Stream 1 Source X Modify Register */
+#define MDMA0_S1_Y_COUNT 0xFFC00ED8 /* MemDMA0 Stream 1 Source Y Count Register */
+#define MDMA0_S1_Y_MODIFY 0xFFC00EDC /* MemDMA0 Stream 1 Source Y Modify Register */
+#define MDMA0_S1_CURR_DESC_PTR 0xFFC00EE0 /* MemDMA0 Stream 1 Source Current Descriptor Pointer Register */
+#define MDMA0_S1_CURR_ADDR 0xFFC00EE4 /* MemDMA0 Stream 1 Source Current Address Register */
+#define MDMA0_S1_IRQ_STATUS 0xFFC00EE8 /* MemDMA0 Stream 1 Source Interrupt/Status Register */
+#define MDMA0_S1_PERIPHERAL_MAP 0xFFC00EEC /* MemDMA0 Stream 1 Source Peripheral Map Register */
+#define MDMA0_S1_CURR_X_COUNT 0xFFC00EF0 /* MemDMA0 Stream 1 Source Current X Count Register */
+#define MDMA0_S1_CURR_Y_COUNT 0xFFC00EF8 /* MemDMA0 Stream 1 Source Current Y Count Register */
+
+
+/* Parallel Peripheral Interface (PPI) (0xFFC01000 - 0xFFC010FF) */
+#define PPI_CONTROL 0xFFC01000 /* PPI Control Register */
+#define PPI_STATUS 0xFFC01004 /* PPI Status Register */
+#define PPI_COUNT 0xFFC01008 /* PPI Transfer Count Register */
+#define PPI_DELAY 0xFFC0100C /* PPI Delay Count Register */
+#define PPI_FRAME 0xFFC01010 /* PPI Frame Length Register */
+
+
+/* Two-Wire Interface 0 (0xFFC01400 - 0xFFC014FF) */
+#define TWI0_CLKDIV 0xFFC01400 /* Serial Clock Divider Register */
+#define TWI0_CONTROL 0xFFC01404 /* TWI0 Master Internal Time Reference Register */
+#define TWI0_SLAVE_CTRL 0xFFC01408 /* Slave Mode Control Register */
+#define TWI0_SLAVE_STAT 0xFFC0140C /* Slave Mode Status Register */
+#define TWI0_SLAVE_ADDR 0xFFC01410 /* Slave Mode Address Register */
+#define TWI0_MASTER_CTRL 0xFFC01414 /* Master Mode Control Register */
+#define TWI0_MASTER_STAT 0xFFC01418 /* Master Mode Status Register */
+#define TWI0_MASTER_ADDR 0xFFC0141C /* Master Mode Address Register */
+#define TWI0_INT_STAT 0xFFC01420 /* TWI0 Master Interrupt Register */
+#define TWI0_INT_MASK 0xFFC01424 /* TWI0 Master Interrupt Mask Register */
+#define TWI0_FIFO_CTRL 0xFFC01428 /* FIFO Control Register */
+#define TWI0_FIFO_STAT 0xFFC0142C /* FIFO Status Register */
+#define TWI0_XMT_DATA8 0xFFC01480 /* FIFO Transmit Data Single Byte Register */
+#define TWI0_XMT_DATA16 0xFFC01484 /* FIFO Transmit Data Double Byte Register */
+#define TWI0_RCV_DATA8 0xFFC01488 /* FIFO Receive Data Single Byte Register */
+#define TWI0_RCV_DATA16 0xFFC0148C /* FIFO Receive Data Double Byte Register */
+
+#define TWI0_REGBASE TWI0_CLKDIV
+
+/* the following are for backwards compatibility */
+#define TWI0_PRESCALE TWI0_CONTROL
+#define TWI0_INT_SRC TWI0_INT_STAT
+#define TWI0_INT_ENABLE TWI0_INT_MASK
+
+
+/* General-Purpose Ports (0xFFC01500 - 0xFFC015FF) */
+
+/* GPIO Port C Register Names */
+#define GPIO_C_CNFG 0xFFC01500 /* GPIO Pin Port C Configuration Register */
+#define GPIO_C_D 0xFFC01510 /* GPIO Pin Port C Data Register */
+#define GPIO_C_C 0xFFC01520 /* Clear GPIO Pin Port C Register */
+#define GPIO_C_S 0xFFC01530 /* Set GPIO Pin Port C Register */
+#define GPIO_C_T 0xFFC01540 /* Toggle GPIO Pin Port C Register */
+#define GPIO_C_DIR 0xFFC01550 /* GPIO Pin Port C Direction Register */
+#define GPIO_C_INEN 0xFFC01560 /* GPIO Pin Port C Input Enable Register */
+
+/* GPIO Port D Register Names */
+#define GPIO_D_CNFG 0xFFC01504 /* GPIO Pin Port D Configuration Register */
+#define GPIO_D_D 0xFFC01514 /* GPIO Pin Port D Data Register */
+#define GPIO_D_C 0xFFC01524 /* Clear GPIO Pin Port D Register */
+#define GPIO_D_S 0xFFC01534 /* Set GPIO Pin Port D Register */
+#define GPIO_D_T 0xFFC01544 /* Toggle GPIO Pin Port D Register */
+#define GPIO_D_DIR 0xFFC01554 /* GPIO Pin Port D Direction Register */
+#define GPIO_D_INEN 0xFFC01564 /* GPIO Pin Port D Input Enable Register */
+
+/* GPIO Port E Register Names */
+#define GPIO_E_CNFG 0xFFC01508 /* GPIO Pin Port E Configuration Register */
+#define GPIO_E_D 0xFFC01518 /* GPIO Pin Port E Data Register */
+#define GPIO_E_C 0xFFC01528 /* Clear GPIO Pin Port E Register */
+#define GPIO_E_S 0xFFC01538 /* Set GPIO Pin Port E Register */
+#define GPIO_E_T 0xFFC01548 /* Toggle GPIO Pin Port E Register */
+#define GPIO_E_DIR 0xFFC01558 /* GPIO Pin Port E Direction Register */
+#define GPIO_E_INEN 0xFFC01568 /* GPIO Pin Port E Input Enable Register */
+
+/* DMA Controller 1 Traffic Control Registers (0xFFC01B00 - 0xFFC01BFF) */
+
+#define DMAC1_TC_PER 0xFFC01B0C /* DMA Controller 1 Traffic Control Periods Register */
+#define DMAC1_TC_CNT 0xFFC01B10 /* DMA Controller 1 Traffic Control Current Counts Register */
+
+/* Alternate deprecated register names (below) provided for backwards code compatibility */
+#define DMA1_TCPER DMAC1_TC_PER
+#define DMA1_TCCNT DMAC1_TC_CNT
+
+
+/* DMA Controller 1 (0xFFC01C00 - 0xFFC01FFF) */
+#define DMA8_NEXT_DESC_PTR 0xFFC01C00 /* DMA Channel 8 Next Descriptor Pointer Register */
+#define DMA8_START_ADDR 0xFFC01C04 /* DMA Channel 8 Start Address Register */
+#define DMA8_CONFIG 0xFFC01C08 /* DMA Channel 8 Configuration Register */
+#define DMA8_X_COUNT 0xFFC01C10 /* DMA Channel 8 X Count Register */
+#define DMA8_X_MODIFY 0xFFC01C14 /* DMA Channel 8 X Modify Register */
+#define DMA8_Y_COUNT 0xFFC01C18 /* DMA Channel 8 Y Count Register */
+#define DMA8_Y_MODIFY 0xFFC01C1C /* DMA Channel 8 Y Modify Register */
+#define DMA8_CURR_DESC_PTR 0xFFC01C20 /* DMA Channel 8 Current Descriptor Pointer Register */
+#define DMA8_CURR_ADDR 0xFFC01C24 /* DMA Channel 8 Current Address Register */
+#define DMA8_IRQ_STATUS 0xFFC01C28 /* DMA Channel 8 Interrupt/Status Register */
+#define DMA8_PERIPHERAL_MAP 0xFFC01C2C /* DMA Channel 8 Peripheral Map Register */
+#define DMA8_CURR_X_COUNT 0xFFC01C30 /* DMA Channel 8 Current X Count Register */
+#define DMA8_CURR_Y_COUNT 0xFFC01C38 /* DMA Channel 8 Current Y Count Register */
+
+#define DMA9_NEXT_DESC_PTR 0xFFC01C40 /* DMA Channel 9 Next Descriptor Pointer Register */
+#define DMA9_START_ADDR 0xFFC01C44 /* DMA Channel 9 Start Address Register */
+#define DMA9_CONFIG 0xFFC01C48 /* DMA Channel 9 Configuration Register */
+#define DMA9_X_COUNT 0xFFC01C50 /* DMA Channel 9 X Count Register */
+#define DMA9_X_MODIFY 0xFFC01C54 /* DMA Channel 9 X Modify Register */
+#define DMA9_Y_COUNT 0xFFC01C58 /* DMA Channel 9 Y Count Register */
+#define DMA9_Y_MODIFY 0xFFC01C5C /* DMA Channel 9 Y Modify Register */
+#define DMA9_CURR_DESC_PTR 0xFFC01C60 /* DMA Channel 9 Current Descriptor Pointer Register */
+#define DMA9_CURR_ADDR 0xFFC01C64 /* DMA Channel 9 Current Address Register */
+#define DMA9_IRQ_STATUS 0xFFC01C68 /* DMA Channel 9 Interrupt/Status Register */
+#define DMA9_PERIPHERAL_MAP 0xFFC01C6C /* DMA Channel 9 Peripheral Map Register */
+#define DMA9_CURR_X_COUNT 0xFFC01C70 /* DMA Channel 9 Current X Count Register */
+#define DMA9_CURR_Y_COUNT 0xFFC01C78 /* DMA Channel 9 Current Y Count Register */
+
+#define DMA10_NEXT_DESC_PTR 0xFFC01C80 /* DMA Channel 10 Next Descriptor Pointer Register */
+#define DMA10_START_ADDR 0xFFC01C84 /* DMA Channel 10 Start Address Register */
+#define DMA10_CONFIG 0xFFC01C88 /* DMA Channel 10 Configuration Register */
+#define DMA10_X_COUNT 0xFFC01C90 /* DMA Channel 10 X Count Register */
+#define DMA10_X_MODIFY 0xFFC01C94 /* DMA Channel 10 X Modify Register */
+#define DMA10_Y_COUNT 0xFFC01C98 /* DMA Channel 10 Y Count Register */
+#define DMA10_Y_MODIFY 0xFFC01C9C /* DMA Channel 10 Y Modify Register */
+#define DMA10_CURR_DESC_PTR 0xFFC01CA0 /* DMA Channel 10 Current Descriptor Pointer Register */
+#define DMA10_CURR_ADDR 0xFFC01CA4 /* DMA Channel 10 Current Address Register */
+#define DMA10_IRQ_STATUS 0xFFC01CA8 /* DMA Channel 10 Interrupt/Status Register */
+#define DMA10_PERIPHERAL_MAP 0xFFC01CAC /* DMA Channel 10 Peripheral Map Register */
+#define DMA10_CURR_X_COUNT 0xFFC01CB0 /* DMA Channel 10 Current X Count Register */
+#define DMA10_CURR_Y_COUNT 0xFFC01CB8 /* DMA Channel 10 Current Y Count Register */
+
+#define DMA11_NEXT_DESC_PTR 0xFFC01CC0 /* DMA Channel 11 Next Descriptor Pointer Register */
+#define DMA11_START_ADDR 0xFFC01CC4 /* DMA Channel 11 Start Address Register */
+#define DMA11_CONFIG 0xFFC01CC8 /* DMA Channel 11 Configuration Register */
+#define DMA11_X_COUNT 0xFFC01CD0 /* DMA Channel 11 X Count Register */
+#define DMA11_X_MODIFY 0xFFC01CD4 /* DMA Channel 11 X Modify Register */
+#define DMA11_Y_COUNT 0xFFC01CD8 /* DMA Channel 11 Y Count Register */
+#define DMA11_Y_MODIFY 0xFFC01CDC /* DMA Channel 11 Y Modify Register */
+#define DMA11_CURR_DESC_PTR 0xFFC01CE0 /* DMA Channel 11 Current Descriptor Pointer Register */
+#define DMA11_CURR_ADDR 0xFFC01CE4 /* DMA Channel 11 Current Address Register */
+#define DMA11_IRQ_STATUS 0xFFC01CE8 /* DMA Channel 11 Interrupt/Status Register */
+#define DMA11_PERIPHERAL_MAP 0xFFC01CEC /* DMA Channel 11 Peripheral Map Register */
+#define DMA11_CURR_X_COUNT 0xFFC01CF0 /* DMA Channel 11 Current X Count Register */
+#define DMA11_CURR_Y_COUNT 0xFFC01CF8 /* DMA Channel 11 Current Y Count Register */
+
+#define DMA12_NEXT_DESC_PTR 0xFFC01D00 /* DMA Channel 12 Next Descriptor Pointer Register */
+#define DMA12_START_ADDR 0xFFC01D04 /* DMA Channel 12 Start Address Register */
+#define DMA12_CONFIG 0xFFC01D08 /* DMA Channel 12 Configuration Register */
+#define DMA12_X_COUNT 0xFFC01D10 /* DMA Channel 12 X Count Register */
+#define DMA12_X_MODIFY 0xFFC01D14 /* DMA Channel 12 X Modify Register */
+#define DMA12_Y_COUNT 0xFFC01D18 /* DMA Channel 12 Y Count Register */
+#define DMA12_Y_MODIFY 0xFFC01D1C /* DMA Channel 12 Y Modify Register */
+#define DMA12_CURR_DESC_PTR 0xFFC01D20 /* DMA Channel 12 Current Descriptor Pointer Register */
+#define DMA12_CURR_ADDR 0xFFC01D24 /* DMA Channel 12 Current Address Register */
+#define DMA12_IRQ_STATUS 0xFFC01D28 /* DMA Channel 12 Interrupt/Status Register */
+#define DMA12_PERIPHERAL_MAP 0xFFC01D2C /* DMA Channel 12 Peripheral Map Register */
+#define DMA12_CURR_X_COUNT 0xFFC01D30 /* DMA Channel 12 Current X Count Register */
+#define DMA12_CURR_Y_COUNT 0xFFC01D38 /* DMA Channel 12 Current Y Count Register */
+
+#define DMA13_NEXT_DESC_PTR 0xFFC01D40 /* DMA Channel 13 Next Descriptor Pointer Register */
+#define DMA13_START_ADDR 0xFFC01D44 /* DMA Channel 13 Start Address Register */
+#define DMA13_CONFIG 0xFFC01D48 /* DMA Channel 13 Configuration Register */
+#define DMA13_X_COUNT 0xFFC01D50 /* DMA Channel 13 X Count Register */
+#define DMA13_X_MODIFY 0xFFC01D54 /* DMA Channel 13 X Modify Register */
+#define DMA13_Y_COUNT 0xFFC01D58 /* DMA Channel 13 Y Count Register */
+#define DMA13_Y_MODIFY 0xFFC01D5C /* DMA Channel 13 Y Modify Register */
+#define DMA13_CURR_DESC_PTR 0xFFC01D60 /* DMA Channel 13 Current Descriptor Pointer Register */
+#define DMA13_CURR_ADDR 0xFFC01D64 /* DMA Channel 13 Current Address Register */
+#define DMA13_IRQ_STATUS 0xFFC01D68 /* DMA Channel 13 Interrupt/Status Register */
+#define DMA13_PERIPHERAL_MAP 0xFFC01D6C /* DMA Channel 13 Peripheral Map Register */
+#define DMA13_CURR_X_COUNT 0xFFC01D70 /* DMA Channel 13 Current X Count Register */
+#define DMA13_CURR_Y_COUNT 0xFFC01D78 /* DMA Channel 13 Current Y Count Register */
+
+#define DMA14_NEXT_DESC_PTR 0xFFC01D80 /* DMA Channel 14 Next Descriptor Pointer Register */
+#define DMA14_START_ADDR 0xFFC01D84 /* DMA Channel 14 Start Address Register */
+#define DMA14_CONFIG 0xFFC01D88 /* DMA Channel 14 Configuration Register */
+#define DMA14_X_COUNT 0xFFC01D90 /* DMA Channel 14 X Count Register */
+#define DMA14_X_MODIFY 0xFFC01D94 /* DMA Channel 14 X Modify Register */
+#define DMA14_Y_COUNT 0xFFC01D98 /* DMA Channel 14 Y Count Register */
+#define DMA14_Y_MODIFY 0xFFC01D9C /* DMA Channel 14 Y Modify Register */
+#define DMA14_CURR_DESC_PTR 0xFFC01DA0 /* DMA Channel 14 Current Descriptor Pointer Register */
+#define DMA14_CURR_ADDR 0xFFC01DA4 /* DMA Channel 14 Current Address Register */
+#define DMA14_IRQ_STATUS 0xFFC01DA8 /* DMA Channel 14 Interrupt/Status Register */
+#define DMA14_PERIPHERAL_MAP 0xFFC01DAC /* DMA Channel 14 Peripheral Map Register */
+#define DMA14_CURR_X_COUNT 0xFFC01DB0 /* DMA Channel 14 Current X Count Register */
+#define DMA14_CURR_Y_COUNT 0xFFC01DB8 /* DMA Channel 14 Current Y Count Register */
+
+#define DMA15_NEXT_DESC_PTR 0xFFC01DC0 /* DMA Channel 15 Next Descriptor Pointer Register */
+#define DMA15_START_ADDR 0xFFC01DC4 /* DMA Channel 15 Start Address Register */
+#define DMA15_CONFIG 0xFFC01DC8 /* DMA Channel 15 Configuration Register */
+#define DMA15_X_COUNT 0xFFC01DD0 /* DMA Channel 15 X Count Register */
+#define DMA15_X_MODIFY 0xFFC01DD4 /* DMA Channel 15 X Modify Register */
+#define DMA15_Y_COUNT 0xFFC01DD8 /* DMA Channel 15 Y Count Register */
+#define DMA15_Y_MODIFY 0xFFC01DDC /* DMA Channel 15 Y Modify Register */
+#define DMA15_CURR_DESC_PTR 0xFFC01DE0 /* DMA Channel 15 Current Descriptor Pointer Register */
+#define DMA15_CURR_ADDR 0xFFC01DE4 /* DMA Channel 15 Current Address Register */
+#define DMA15_IRQ_STATUS 0xFFC01DE8 /* DMA Channel 15 Interrupt/Status Register */
+#define DMA15_PERIPHERAL_MAP 0xFFC01DEC /* DMA Channel 15 Peripheral Map Register */
+#define DMA15_CURR_X_COUNT 0xFFC01DF0 /* DMA Channel 15 Current X Count Register */
+#define DMA15_CURR_Y_COUNT 0xFFC01DF8 /* DMA Channel 15 Current Y Count Register */
+
+#define DMA16_NEXT_DESC_PTR 0xFFC01E00 /* DMA Channel 16 Next Descriptor Pointer Register */
+#define DMA16_START_ADDR 0xFFC01E04 /* DMA Channel 16 Start Address Register */
+#define DMA16_CONFIG 0xFFC01E08 /* DMA Channel 16 Configuration Register */
+#define DMA16_X_COUNT 0xFFC01E10 /* DMA Channel 16 X Count Register */
+#define DMA16_X_MODIFY 0xFFC01E14 /* DMA Channel 16 X Modify Register */
+#define DMA16_Y_COUNT 0xFFC01E18 /* DMA Channel 16 Y Count Register */
+#define DMA16_Y_MODIFY 0xFFC01E1C /* DMA Channel 16 Y Modify Register */
+#define DMA16_CURR_DESC_PTR 0xFFC01E20 /* DMA Channel 16 Current Descriptor Pointer Register */
+#define DMA16_CURR_ADDR 0xFFC01E24 /* DMA Channel 16 Current Address Register */
+#define DMA16_IRQ_STATUS 0xFFC01E28 /* DMA Channel 16 Interrupt/Status Register */
+#define DMA16_PERIPHERAL_MAP 0xFFC01E2C /* DMA Channel 16 Peripheral Map Register */
+#define DMA16_CURR_X_COUNT 0xFFC01E30 /* DMA Channel 16 Current X Count Register */
+#define DMA16_CURR_Y_COUNT 0xFFC01E38 /* DMA Channel 16 Current Y Count Register */
+
+#define DMA17_NEXT_DESC_PTR 0xFFC01E40 /* DMA Channel 17 Next Descriptor Pointer Register */
+#define DMA17_START_ADDR 0xFFC01E44 /* DMA Channel 17 Start Address Register */
+#define DMA17_CONFIG 0xFFC01E48 /* DMA Channel 17 Configuration Register */
+#define DMA17_X_COUNT 0xFFC01E50 /* DMA Channel 17 X Count Register */
+#define DMA17_X_MODIFY 0xFFC01E54 /* DMA Channel 17 X Modify Register */
+#define DMA17_Y_COUNT 0xFFC01E58 /* DMA Channel 17 Y Count Register */
+#define DMA17_Y_MODIFY 0xFFC01E5C /* DMA Channel 17 Y Modify Register */
+#define DMA17_CURR_DESC_PTR 0xFFC01E60 /* DMA Channel 17 Current Descriptor Pointer Register */
+#define DMA17_CURR_ADDR 0xFFC01E64 /* DMA Channel 17 Current Address Register */
+#define DMA17_IRQ_STATUS 0xFFC01E68 /* DMA Channel 17 Interrupt/Status Register */
+#define DMA17_PERIPHERAL_MAP 0xFFC01E6C /* DMA Channel 17 Peripheral Map Register */
+#define DMA17_CURR_X_COUNT 0xFFC01E70 /* DMA Channel 17 Current X Count Register */
+#define DMA17_CURR_Y_COUNT 0xFFC01E78 /* DMA Channel 17 Current Y Count Register */
+
+#define DMA18_NEXT_DESC_PTR 0xFFC01E80 /* DMA Channel 18 Next Descriptor Pointer Register */
+#define DMA18_START_ADDR 0xFFC01E84 /* DMA Channel 18 Start Address Register */
+#define DMA18_CONFIG 0xFFC01E88 /* DMA Channel 18 Configuration Register */
+#define DMA18_X_COUNT 0xFFC01E90 /* DMA Channel 18 X Count Register */
+#define DMA18_X_MODIFY 0xFFC01E94 /* DMA Channel 18 X Modify Register */
+#define DMA18_Y_COUNT 0xFFC01E98 /* DMA Channel 18 Y Count Register */
+#define DMA18_Y_MODIFY 0xFFC01E9C /* DMA Channel 18 Y Modify Register */
+#define DMA18_CURR_DESC_PTR 0xFFC01EA0 /* DMA Channel 18 Current Descriptor Pointer Register */
+#define DMA18_CURR_ADDR 0xFFC01EA4 /* DMA Channel 18 Current Address Register */
+#define DMA18_IRQ_STATUS 0xFFC01EA8 /* DMA Channel 18 Interrupt/Status Register */
+#define DMA18_PERIPHERAL_MAP 0xFFC01EAC /* DMA Channel 18 Peripheral Map Register */
+#define DMA18_CURR_X_COUNT 0xFFC01EB0 /* DMA Channel 18 Current X Count Register */
+#define DMA18_CURR_Y_COUNT 0xFFC01EB8 /* DMA Channel 18 Current Y Count Register */
+
+#define DMA19_NEXT_DESC_PTR 0xFFC01EC0 /* DMA Channel 19 Next Descriptor Pointer Register */
+#define DMA19_START_ADDR 0xFFC01EC4 /* DMA Channel 19 Start Address Register */
+#define DMA19_CONFIG 0xFFC01EC8 /* DMA Channel 19 Configuration Register */
+#define DMA19_X_COUNT 0xFFC01ED0 /* DMA Channel 19 X Count Register */
+#define DMA19_X_MODIFY 0xFFC01ED4 /* DMA Channel 19 X Modify Register */
+#define DMA19_Y_COUNT 0xFFC01ED8 /* DMA Channel 19 Y Count Register */
+#define DMA19_Y_MODIFY 0xFFC01EDC /* DMA Channel 19 Y Modify Register */
+#define DMA19_CURR_DESC_PTR 0xFFC01EE0 /* DMA Channel 19 Current Descriptor Pointer Register */
+#define DMA19_CURR_ADDR 0xFFC01EE4 /* DMA Channel 19 Current Address Register */
+#define DMA19_IRQ_STATUS 0xFFC01EE8 /* DMA Channel 19 Interrupt/Status Register */
+#define DMA19_PERIPHERAL_MAP 0xFFC01EEC /* DMA Channel 19 Peripheral Map Register */
+#define DMA19_CURR_X_COUNT 0xFFC01EF0 /* DMA Channel 19 Current X Count Register */
+#define DMA19_CURR_Y_COUNT 0xFFC01EF8 /* DMA Channel 19 Current Y Count Register */
+
+#define MDMA1_D0_NEXT_DESC_PTR 0xFFC01F00 /* MemDMA1 Stream 0 Destination Next Descriptor Pointer Register */
+#define MDMA1_D0_START_ADDR 0xFFC01F04 /* MemDMA1 Stream 0 Destination Start Address Register */
+#define MDMA1_D0_CONFIG 0xFFC01F08 /* MemDMA1 Stream 0 Destination Configuration Register */
+#define MDMA1_D0_X_COUNT 0xFFC01F10 /* MemDMA1 Stream 0 Destination X Count Register */
+#define MDMA1_D0_X_MODIFY 0xFFC01F14 /* MemDMA1 Stream 0 Destination X Modify Register */
+#define MDMA1_D0_Y_COUNT 0xFFC01F18 /* MemDMA1 Stream 0 Destination Y Count Register */
+#define MDMA1_D0_Y_MODIFY 0xFFC01F1C /* MemDMA1 Stream 0 Destination Y Modify Register */
+#define MDMA1_D0_CURR_DESC_PTR 0xFFC01F20 /* MemDMA1 Stream 0 Destination Current Descriptor Pointer Register */
+#define MDMA1_D0_CURR_ADDR 0xFFC01F24 /* MemDMA1 Stream 0 Destination Current Address Register */
+#define MDMA1_D0_IRQ_STATUS 0xFFC01F28 /* MemDMA1 Stream 0 Destination Interrupt/Status Register */
+#define MDMA1_D0_PERIPHERAL_MAP 0xFFC01F2C /* MemDMA1 Stream 0 Destination Peripheral Map Register */
+#define MDMA1_D0_CURR_X_COUNT 0xFFC01F30 /* MemDMA1 Stream 0 Destination Current X Count Register */
+#define MDMA1_D0_CURR_Y_COUNT 0xFFC01F38 /* MemDMA1 Stream 0 Destination Current Y Count Register */
+
+#define MDMA1_S0_NEXT_DESC_PTR 0xFFC01F40 /* MemDMA1 Stream 0 Source Next Descriptor Pointer Register */
+#define MDMA1_S0_START_ADDR 0xFFC01F44 /* MemDMA1 Stream 0 Source Start Address Register */
+#define MDMA1_S0_CONFIG 0xFFC01F48 /* MemDMA1 Stream 0 Source Configuration Register */
+#define MDMA1_S0_X_COUNT 0xFFC01F50 /* MemDMA1 Stream 0 Source X Count Register */
+#define MDMA1_S0_X_MODIFY 0xFFC01F54 /* MemDMA1 Stream 0 Source X Modify Register */
+#define MDMA1_S0_Y_COUNT 0xFFC01F58 /* MemDMA1 Stream 0 Source Y Count Register */
+#define MDMA1_S0_Y_MODIFY 0xFFC01F5C /* MemDMA1 Stream 0 Source Y Modify Register */
+#define MDMA1_S0_CURR_DESC_PTR 0xFFC01F60 /* MemDMA1 Stream 0 Source Current Descriptor Pointer Register */
+#define MDMA1_S0_CURR_ADDR 0xFFC01F64 /* MemDMA1 Stream 0 Source Current Address Register */
+#define MDMA1_S0_IRQ_STATUS 0xFFC01F68 /* MemDMA1 Stream 0 Source Interrupt/Status Register */
+#define MDMA1_S0_PERIPHERAL_MAP 0xFFC01F6C /* MemDMA1 Stream 0 Source Peripheral Map Register */
+#define MDMA1_S0_CURR_X_COUNT 0xFFC01F70 /* MemDMA1 Stream 0 Source Current X Count Register */
+#define MDMA1_S0_CURR_Y_COUNT 0xFFC01F78 /* MemDMA1 Stream 0 Source Current Y Count Register */
+
+#define MDMA1_D1_NEXT_DESC_PTR 0xFFC01F80 /* MemDMA1 Stream 1 Destination Next Descriptor Pointer Register */
+#define MDMA1_D1_START_ADDR 0xFFC01F84 /* MemDMA1 Stream 1 Destination Start Address Register */
+#define MDMA1_D1_CONFIG 0xFFC01F88 /* MemDMA1 Stream 1 Destination Configuration Register */
+#define MDMA1_D1_X_COUNT 0xFFC01F90 /* MemDMA1 Stream 1 Destination X Count Register */
+#define MDMA1_D1_X_MODIFY 0xFFC01F94 /* MemDMA1 Stream 1 Destination X Modify Register */
+#define MDMA1_D1_Y_COUNT 0xFFC01F98 /* MemDMA1 Stream 1 Destination Y Count Register */
+#define MDMA1_D1_Y_MODIFY 0xFFC01F9C /* MemDMA1 Stream 1 Destination Y Modify Register */
+#define MDMA1_D1_CURR_DESC_PTR 0xFFC01FA0 /* MemDMA1 Stream 1 Destination Current Descriptor Pointer Register */
+#define MDMA1_D1_CURR_ADDR 0xFFC01FA4 /* MemDMA1 Stream 1 Destination Current Address Register */
+#define MDMA1_D1_IRQ_STATUS 0xFFC01FA8 /* MemDMA1 Stream 1 Destination Interrupt/Status Register */
+#define MDMA1_D1_PERIPHERAL_MAP 0xFFC01FAC /* MemDMA1 Stream 1 Destination Peripheral Map Register */
+#define MDMA1_D1_CURR_X_COUNT 0xFFC01FB0 /* MemDMA1 Stream 1 Destination Current X Count Register */
+#define MDMA1_D1_CURR_Y_COUNT 0xFFC01FB8 /* MemDMA1 Stream 1 Destination Current Y Count Register */
+
+#define MDMA1_S1_NEXT_DESC_PTR 0xFFC01FC0 /* MemDMA1 Stream 1 Source Next Descriptor Pointer Register */
+#define MDMA1_S1_START_ADDR 0xFFC01FC4 /* MemDMA1 Stream 1 Source Start Address Register */
+#define MDMA1_S1_CONFIG 0xFFC01FC8 /* MemDMA1 Stream 1 Source Configuration Register */
+#define MDMA1_S1_X_COUNT 0xFFC01FD0 /* MemDMA1 Stream 1 Source X Count Register */
+#define MDMA1_S1_X_MODIFY 0xFFC01FD4 /* MemDMA1 Stream 1 Source X Modify Register */
+#define MDMA1_S1_Y_COUNT 0xFFC01FD8 /* MemDMA1 Stream 1 Source Y Count Register */
+#define MDMA1_S1_Y_MODIFY 0xFFC01FDC /* MemDMA1 Stream 1 Source Y Modify Register */
+#define MDMA1_S1_CURR_DESC_PTR 0xFFC01FE0 /* MemDMA1 Stream 1 Source Current Descriptor Pointer Register */
+#define MDMA1_S1_CURR_ADDR 0xFFC01FE4 /* MemDMA1 Stream 1 Source Current Address Register */
+#define MDMA1_S1_IRQ_STATUS 0xFFC01FE8 /* MemDMA1 Stream 1 Source Interrupt/Status Register */
+#define MDMA1_S1_PERIPHERAL_MAP 0xFFC01FEC /* MemDMA1 Stream 1 Source Peripheral Map Register */
+#define MDMA1_S1_CURR_X_COUNT 0xFFC01FF0 /* MemDMA1 Stream 1 Source Current X Count Register */
+#define MDMA1_S1_CURR_Y_COUNT 0xFFC01FF8 /* MemDMA1 Stream 1 Source Current Y Count Register */
+
+
+/* UART1 Controller (0xFFC02000 - 0xFFC020FF) */
+#define UART1_THR 0xFFC02000 /* Transmit Holding register */
+#define UART1_RBR 0xFFC02000 /* Receive Buffer register */
+#define UART1_DLL 0xFFC02000 /* Divisor Latch (Low-Byte) */
+#define UART1_IER 0xFFC02004 /* Interrupt Enable Register */
+#define UART1_DLH 0xFFC02004 /* Divisor Latch (High-Byte) */
+#define UART1_IIR 0xFFC02008 /* Interrupt Identification Register */
+#define UART1_LCR 0xFFC0200C /* Line Control Register */
+#define UART1_MCR 0xFFC02010 /* Modem Control Register */
+#define UART1_LSR 0xFFC02014 /* Line Status Register */
+#define UART1_SCR 0xFFC0201C /* SCR Scratch Register */
+#define UART1_GCTL 0xFFC02024 /* Global Control Register */
+
+
+/* UART2 Controller (0xFFC02100 - 0xFFC021FF) */
+#define UART2_THR 0xFFC02100 /* Transmit Holding register */
+#define UART2_RBR 0xFFC02100 /* Receive Buffer register */
+#define UART2_DLL 0xFFC02100 /* Divisor Latch (Low-Byte) */
+#define UART2_IER 0xFFC02104 /* Interrupt Enable Register */
+#define UART2_DLH 0xFFC02104 /* Divisor Latch (High-Byte) */
+#define UART2_IIR 0xFFC02108 /* Interrupt Identification Register */
+#define UART2_LCR 0xFFC0210C /* Line Control Register */
+#define UART2_MCR 0xFFC02110 /* Modem Control Register */
+#define UART2_LSR 0xFFC02114 /* Line Status Register */
+#define UART2_SCR 0xFFC0211C /* SCR Scratch Register */
+#define UART2_GCTL 0xFFC02124 /* Global Control Register */
+
+
+/* Two-Wire Interface 1 (0xFFC02200 - 0xFFC022FF) */
+#define TWI1_CLKDIV 0xFFC02200 /* Serial Clock Divider Register */
+#define TWI1_CONTROL 0xFFC02204 /* TWI1 Master Internal Time Reference Register */
+#define TWI1_SLAVE_CTRL 0xFFC02208 /* Slave Mode Control Register */
+#define TWI1_SLAVE_STAT 0xFFC0220C /* Slave Mode Status Register */
+#define TWI1_SLAVE_ADDR 0xFFC02210 /* Slave Mode Address Register */
+#define TWI1_MASTER_CTRL 0xFFC02214 /* Master Mode Control Register */
+#define TWI1_MASTER_STAT 0xFFC02218 /* Master Mode Status Register */
+#define TWI1_MASTER_ADDR 0xFFC0221C /* Master Mode Address Register */
+#define TWI1_INT_STAT 0xFFC02220 /* TWI1 Master Interrupt Register */
+#define TWI1_INT_MASK 0xFFC02224 /* TWI1 Master Interrupt Mask Register */
+#define TWI1_FIFO_CTRL 0xFFC02228 /* FIFO Control Register */
+#define TWI1_FIFO_STAT 0xFFC0222C /* FIFO Status Register */
+#define TWI1_XMT_DATA8 0xFFC02280 /* FIFO Transmit Data Single Byte Register */
+#define TWI1_XMT_DATA16 0xFFC02284 /* FIFO Transmit Data Double Byte Register */
+#define TWI1_RCV_DATA8 0xFFC02288 /* FIFO Receive Data Single Byte Register */
+#define TWI1_RCV_DATA16 0xFFC0228C /* FIFO Receive Data Double Byte Register */
+#define TWI1_REGBASE TWI1_CLKDIV
+
+
+/* the following are for backwards compatibility */
+#define TWI1_PRESCALE TWI1_CONTROL
+#define TWI1_INT_SRC TWI1_INT_STAT
+#define TWI1_INT_ENABLE TWI1_INT_MASK
+
+
+/* SPI1 Controller (0xFFC02300 - 0xFFC023FF) */
+#define SPI1_CTL 0xFFC02300 /* SPI1 Control Register */
+#define SPI1_FLG 0xFFC02304 /* SPI1 Flag register */
+#define SPI1_STAT 0xFFC02308 /* SPI1 Status register */
+#define SPI1_TDBR 0xFFC0230C /* SPI1 Transmit Data Buffer Register */
+#define SPI1_RDBR 0xFFC02310 /* SPI1 Receive Data Buffer Register */
+#define SPI1_BAUD 0xFFC02314 /* SPI1 Baud rate Register */
+#define SPI1_SHADOW 0xFFC02318 /* SPI1_RDBR Shadow Register */
+#define SPI1_REGBASE SPI1_CTL
+
+/* SPI2 Controller (0xFFC02400 - 0xFFC024FF) */
+#define SPI2_CTL 0xFFC02400 /* SPI2 Control Register */
+#define SPI2_FLG 0xFFC02404 /* SPI2 Flag register */
+#define SPI2_STAT 0xFFC02408 /* SPI2 Status register */
+#define SPI2_TDBR 0xFFC0240C /* SPI2 Transmit Data Buffer Register */
+#define SPI2_RDBR 0xFFC02410 /* SPI2 Receive Data Buffer Register */
+#define SPI2_BAUD 0xFFC02414 /* SPI2 Baud rate Register */
+#define SPI2_SHADOW 0xFFC02418 /* SPI2_RDBR Shadow Register */
+#define SPI2_REGBASE SPI2_CTL
+
+/* SPORT2 Controller (0xFFC02500 - 0xFFC025FF) */
+#define SPORT2_TCR1 0xFFC02500 /* SPORT2 Transmit Configuration 1 Register */
+#define SPORT2_TCR2 0xFFC02504 /* SPORT2 Transmit Configuration 2 Register */
+#define SPORT2_TCLKDIV 0xFFC02508 /* SPORT2 Transmit Clock Divider */
+#define SPORT2_TFSDIV 0xFFC0250C /* SPORT2 Transmit Frame Sync Divider */
+#define SPORT2_TX 0xFFC02510 /* SPORT2 TX Data Register */
+#define SPORT2_RX 0xFFC02518 /* SPORT2 RX Data Register */
+#define SPORT2_RCR1 0xFFC02520 /* SPORT2 Transmit Configuration 1 Register */
+#define SPORT2_RCR2 0xFFC02524 /* SPORT2 Transmit Configuration 2 Register */
+#define SPORT2_RCLKDIV 0xFFC02528 /* SPORT2 Receive Clock Divider */
+#define SPORT2_RFSDIV 0xFFC0252C /* SPORT2 Receive Frame Sync Divider */
+#define SPORT2_STAT 0xFFC02530 /* SPORT2 Status Register */
+#define SPORT2_CHNL 0xFFC02534 /* SPORT2 Current Channel Register */
+#define SPORT2_MCMC1 0xFFC02538 /* SPORT2 Multi-Channel Configuration Register 1 */
+#define SPORT2_MCMC2 0xFFC0253C /* SPORT2 Multi-Channel Configuration Register 2 */
+#define SPORT2_MTCS0 0xFFC02540 /* SPORT2 Multi-Channel Transmit Select Register 0 */
+#define SPORT2_MTCS1 0xFFC02544 /* SPORT2 Multi-Channel Transmit Select Register 1 */
+#define SPORT2_MTCS2 0xFFC02548 /* SPORT2 Multi-Channel Transmit Select Register 2 */
+#define SPORT2_MTCS3 0xFFC0254C /* SPORT2 Multi-Channel Transmit Select Register 3 */
+#define SPORT2_MRCS0 0xFFC02550 /* SPORT2 Multi-Channel Receive Select Register 0 */
+#define SPORT2_MRCS1 0xFFC02554 /* SPORT2 Multi-Channel Receive Select Register 1 */
+#define SPORT2_MRCS2 0xFFC02558 /* SPORT2 Multi-Channel Receive Select Register 2 */
+#define SPORT2_MRCS3 0xFFC0255C /* SPORT2 Multi-Channel Receive Select Register 3 */
+
+
+/* SPORT3 Controller (0xFFC02600 - 0xFFC026FF) */
+#define SPORT3_TCR1 0xFFC02600 /* SPORT3 Transmit Configuration 1 Register */
+#define SPORT3_TCR2 0xFFC02604 /* SPORT3 Transmit Configuration 2 Register */
+#define SPORT3_TCLKDIV 0xFFC02608 /* SPORT3 Transmit Clock Divider */
+#define SPORT3_TFSDIV 0xFFC0260C /* SPORT3 Transmit Frame Sync Divider */
+#define SPORT3_TX 0xFFC02610 /* SPORT3 TX Data Register */
+#define SPORT3_RX 0xFFC02618 /* SPORT3 RX Data Register */
+#define SPORT3_RCR1 0xFFC02620 /* SPORT3 Transmit Configuration 1 Register */
+#define SPORT3_RCR2 0xFFC02624 /* SPORT3 Transmit Configuration 2 Register */
+#define SPORT3_RCLKDIV 0xFFC02628 /* SPORT3 Receive Clock Divider */
+#define SPORT3_RFSDIV 0xFFC0262C /* SPORT3 Receive Frame Sync Divider */
+#define SPORT3_STAT 0xFFC02630 /* SPORT3 Status Register */
+#define SPORT3_CHNL 0xFFC02634 /* SPORT3 Current Channel Register */
+#define SPORT3_MCMC1 0xFFC02638 /* SPORT3 Multi-Channel Configuration Register 1 */
+#define SPORT3_MCMC2 0xFFC0263C /* SPORT3 Multi-Channel Configuration Register 2 */
+#define SPORT3_MTCS0 0xFFC02640 /* SPORT3 Multi-Channel Transmit Select Register 0 */
+#define SPORT3_MTCS1 0xFFC02644 /* SPORT3 Multi-Channel Transmit Select Register 1 */
+#define SPORT3_MTCS2 0xFFC02648 /* SPORT3 Multi-Channel Transmit Select Register 2 */
+#define SPORT3_MTCS3 0xFFC0264C /* SPORT3 Multi-Channel Transmit Select Register 3 */
+#define SPORT3_MRCS0 0xFFC02650 /* SPORT3 Multi-Channel Receive Select Register 0 */
+#define SPORT3_MRCS1 0xFFC02654 /* SPORT3 Multi-Channel Receive Select Register 1 */
+#define SPORT3_MRCS2 0xFFC02658 /* SPORT3 Multi-Channel Receive Select Register 2 */
+#define SPORT3_MRCS3 0xFFC0265C /* SPORT3 Multi-Channel Receive Select Register 3 */
+
+
+/* Media Transceiver (MXVR) (0xFFC02700 - 0xFFC028FF) */
+
+#define MXVR_CONFIG 0xFFC02700 /* MXVR Configuration Register */
+#define MXVR_PLL_CTL_0 0xFFC02704 /* MXVR Phase Lock Loop Control Register 0 */
+
+#define MXVR_STATE_0 0xFFC02708 /* MXVR State Register 0 */
+#define MXVR_STATE_1 0xFFC0270C /* MXVR State Register 1 */
+
+#define MXVR_INT_STAT_0 0xFFC02710 /* MXVR Interrupt Status Register 0 */
+#define MXVR_INT_STAT_1 0xFFC02714 /* MXVR Interrupt Status Register 1 */
+
+#define MXVR_INT_EN_0 0xFFC02718 /* MXVR Interrupt Enable Register 0 */
+#define MXVR_INT_EN_1 0xFFC0271C /* MXVR Interrupt Enable Register 1 */
+
+#define MXVR_POSITION 0xFFC02720 /* MXVR Node Position Register */
+#define MXVR_MAX_POSITION 0xFFC02724 /* MXVR Maximum Node Position Register */
+
+#define MXVR_DELAY 0xFFC02728 /* MXVR Node Frame Delay Register */
+#define MXVR_MAX_DELAY 0xFFC0272C /* MXVR Maximum Node Frame Delay Register */
+
+#define MXVR_LADDR 0xFFC02730 /* MXVR Logical Address Register */
+#define MXVR_GADDR 0xFFC02734 /* MXVR Group Address Register */
+#define MXVR_AADDR 0xFFC02738 /* MXVR Alternate Address Register */
+
+#define MXVR_ALLOC_0 0xFFC0273C /* MXVR Allocation Table Register 0 */
+#define MXVR_ALLOC_1 0xFFC02740 /* MXVR Allocation Table Register 1 */
+#define MXVR_ALLOC_2 0xFFC02744 /* MXVR Allocation Table Register 2 */
+#define MXVR_ALLOC_3 0xFFC02748 /* MXVR Allocation Table Register 3 */
+#define MXVR_ALLOC_4 0xFFC0274C /* MXVR Allocation Table Register 4 */
+#define MXVR_ALLOC_5 0xFFC02750 /* MXVR Allocation Table Register 5 */
+#define MXVR_ALLOC_6 0xFFC02754 /* MXVR Allocation Table Register 6 */
+#define MXVR_ALLOC_7 0xFFC02758 /* MXVR Allocation Table Register 7 */
+#define MXVR_ALLOC_8 0xFFC0275C /* MXVR Allocation Table Register 8 */
+#define MXVR_ALLOC_9 0xFFC02760 /* MXVR Allocation Table Register 9 */
+#define MXVR_ALLOC_10 0xFFC02764 /* MXVR Allocation Table Register 10 */
+#define MXVR_ALLOC_11 0xFFC02768 /* MXVR Allocation Table Register 11 */
+#define MXVR_ALLOC_12 0xFFC0276C /* MXVR Allocation Table Register 12 */
+#define MXVR_ALLOC_13 0xFFC02770 /* MXVR Allocation Table Register 13 */
+#define MXVR_ALLOC_14 0xFFC02774 /* MXVR Allocation Table Register 14 */
+
+#define MXVR_SYNC_LCHAN_0 0xFFC02778 /* MXVR Sync Data Logical Channel Assign Register 0 */
+#define MXVR_SYNC_LCHAN_1 0xFFC0277C /* MXVR Sync Data Logical Channel Assign Register 1 */
+#define MXVR_SYNC_LCHAN_2 0xFFC02780 /* MXVR Sync Data Logical Channel Assign Register 2 */
+#define MXVR_SYNC_LCHAN_3 0xFFC02784 /* MXVR Sync Data Logical Channel Assign Register 3 */
+#define MXVR_SYNC_LCHAN_4 0xFFC02788 /* MXVR Sync Data Logical Channel Assign Register 4 */
+#define MXVR_SYNC_LCHAN_5 0xFFC0278C /* MXVR Sync Data Logical Channel Assign Register 5 */
+#define MXVR_SYNC_LCHAN_6 0xFFC02790 /* MXVR Sync Data Logical Channel Assign Register 6 */
+#define MXVR_SYNC_LCHAN_7 0xFFC02794 /* MXVR Sync Data Logical Channel Assign Register 7 */
+
+#define MXVR_DMA0_CONFIG 0xFFC02798 /* MXVR Sync Data DMA0 Config Register */
+#define MXVR_DMA0_START_ADDR 0xFFC0279C /* MXVR Sync Data DMA0 Start Address Register */
+#define MXVR_DMA0_COUNT 0xFFC027A0 /* MXVR Sync Data DMA0 Loop Count Register */
+#define MXVR_DMA0_CURR_ADDR 0xFFC027A4 /* MXVR Sync Data DMA0 Current Address Register */
+#define MXVR_DMA0_CURR_COUNT 0xFFC027A8 /* MXVR Sync Data DMA0 Current Loop Count Register */
+
+#define MXVR_DMA1_CONFIG 0xFFC027AC /* MXVR Sync Data DMA1 Config Register */
+#define MXVR_DMA1_START_ADDR 0xFFC027B0 /* MXVR Sync Data DMA1 Start Address Register */
+#define MXVR_DMA1_COUNT 0xFFC027B4 /* MXVR Sync Data DMA1 Loop Count Register */
+#define MXVR_DMA1_CURR_ADDR 0xFFC027B8 /* MXVR Sync Data DMA1 Current Address Register */
+#define MXVR_DMA1_CURR_COUNT 0xFFC027BC /* MXVR Sync Data DMA1 Current Loop Count Register */
+
+#define MXVR_DMA2_CONFIG 0xFFC027C0 /* MXVR Sync Data DMA2 Config Register */
+#define MXVR_DMA2_START_ADDR 0xFFC027C4 /* MXVR Sync Data DMA2 Start Address Register */
+#define MXVR_DMA2_COUNT 0xFFC027C8 /* MXVR Sync Data DMA2 Loop Count Register */
+#define MXVR_DMA2_CURR_ADDR 0xFFC027CC /* MXVR Sync Data DMA2 Current Address Register */
+#define MXVR_DMA2_CURR_COUNT 0xFFC027D0 /* MXVR Sync Data DMA2 Current Loop Count Register */
+
+#define MXVR_DMA3_CONFIG 0xFFC027D4 /* MXVR Sync Data DMA3 Config Register */
+#define MXVR_DMA3_START_ADDR 0xFFC027D8 /* MXVR Sync Data DMA3 Start Address Register */
+#define MXVR_DMA3_COUNT 0xFFC027DC /* MXVR Sync Data DMA3 Loop Count Register */
+#define MXVR_DMA3_CURR_ADDR 0xFFC027E0 /* MXVR Sync Data DMA3 Current Address Register */
+#define MXVR_DMA3_CURR_COUNT 0xFFC027E4 /* MXVR Sync Data DMA3 Current Loop Count Register */
+
+#define MXVR_DMA4_CONFIG 0xFFC027E8 /* MXVR Sync Data DMA4 Config Register */
+#define MXVR_DMA4_START_ADDR 0xFFC027EC /* MXVR Sync Data DMA4 Start Address Register */
+#define MXVR_DMA4_COUNT 0xFFC027F0 /* MXVR Sync Data DMA4 Loop Count Register */
+#define MXVR_DMA4_CURR_ADDR 0xFFC027F4 /* MXVR Sync Data DMA4 Current Address Register */
+#define MXVR_DMA4_CURR_COUNT 0xFFC027F8 /* MXVR Sync Data DMA4 Current Loop Count Register */
+
+#define MXVR_DMA5_CONFIG 0xFFC027FC /* MXVR Sync Data DMA5 Config Register */
+#define MXVR_DMA5_START_ADDR 0xFFC02800 /* MXVR Sync Data DMA5 Start Address Register */
+#define MXVR_DMA5_COUNT 0xFFC02804 /* MXVR Sync Data DMA5 Loop Count Register */
+#define MXVR_DMA5_CURR_ADDR 0xFFC02808 /* MXVR Sync Data DMA5 Current Address Register */
+#define MXVR_DMA5_CURR_COUNT 0xFFC0280C /* MXVR Sync Data DMA5 Current Loop Count Register */
+
+#define MXVR_DMA6_CONFIG 0xFFC02810 /* MXVR Sync Data DMA6 Config Register */
+#define MXVR_DMA6_START_ADDR 0xFFC02814 /* MXVR Sync Data DMA6 Start Address Register */
+#define MXVR_DMA6_COUNT 0xFFC02818 /* MXVR Sync Data DMA6 Loop Count Register */
+#define MXVR_DMA6_CURR_ADDR 0xFFC0281C /* MXVR Sync Data DMA6 Current Address Register */
+#define MXVR_DMA6_CURR_COUNT 0xFFC02820 /* MXVR Sync Data DMA6 Current Loop Count Register */
+
+#define MXVR_DMA7_CONFIG 0xFFC02824 /* MXVR Sync Data DMA7 Config Register */
+#define MXVR_DMA7_START_ADDR 0xFFC02828 /* MXVR Sync Data DMA7 Start Address Register */
+#define MXVR_DMA7_COUNT 0xFFC0282C /* MXVR Sync Data DMA7 Loop Count Register */
+#define MXVR_DMA7_CURR_ADDR 0xFFC02830 /* MXVR Sync Data DMA7 Current Address Register */
+#define MXVR_DMA7_CURR_COUNT 0xFFC02834 /* MXVR Sync Data DMA7 Current Loop Count Register */
+
+#define MXVR_AP_CTL 0xFFC02838 /* MXVR Async Packet Control Register */
+#define MXVR_APRB_START_ADDR 0xFFC0283C /* MXVR Async Packet RX Buffer Start Addr Register */
+#define MXVR_APRB_CURR_ADDR 0xFFC02840 /* MXVR Async Packet RX Buffer Current Addr Register */
+#define MXVR_APTB_START_ADDR 0xFFC02844 /* MXVR Async Packet TX Buffer Start Addr Register */
+#define MXVR_APTB_CURR_ADDR 0xFFC02848 /* MXVR Async Packet TX Buffer Current Addr Register */
+
+#define MXVR_CM_CTL 0xFFC0284C /* MXVR Control Message Control Register */
+#define MXVR_CMRB_START_ADDR 0xFFC02850 /* MXVR Control Message RX Buffer Start Addr Register */
+#define MXVR_CMRB_CURR_ADDR 0xFFC02854 /* MXVR Control Message RX Buffer Current Address */
+#define MXVR_CMTB_START_ADDR 0xFFC02858 /* MXVR Control Message TX Buffer Start Addr Register */
+#define MXVR_CMTB_CURR_ADDR 0xFFC0285C /* MXVR Control Message TX Buffer Current Address */
+
+#define MXVR_RRDB_START_ADDR 0xFFC02860 /* MXVR Remote Read Buffer Start Addr Register */
+#define MXVR_RRDB_CURR_ADDR 0xFFC02864 /* MXVR Remote Read Buffer Current Addr Register */
+
+#define MXVR_PAT_DATA_0 0xFFC02868 /* MXVR Pattern Data Register 0 */
+#define MXVR_PAT_EN_0 0xFFC0286C /* MXVR Pattern Enable Register 0 */
+#define MXVR_PAT_DATA_1 0xFFC02870 /* MXVR Pattern Data Register 1 */
+#define MXVR_PAT_EN_1 0xFFC02874 /* MXVR Pattern Enable Register 1 */
+
+#define MXVR_FRAME_CNT_0 0xFFC02878 /* MXVR Frame Counter 0 */
+#define MXVR_FRAME_CNT_1 0xFFC0287C /* MXVR Frame Counter 1 */
+
+#define MXVR_ROUTING_0 0xFFC02880 /* MXVR Routing Table Register 0 */
+#define MXVR_ROUTING_1 0xFFC02884 /* MXVR Routing Table Register 1 */
+#define MXVR_ROUTING_2 0xFFC02888 /* MXVR Routing Table Register 2 */
+#define MXVR_ROUTING_3 0xFFC0288C /* MXVR Routing Table Register 3 */
+#define MXVR_ROUTING_4 0xFFC02890 /* MXVR Routing Table Register 4 */
+#define MXVR_ROUTING_5 0xFFC02894 /* MXVR Routing Table Register 5 */
+#define MXVR_ROUTING_6 0xFFC02898 /* MXVR Routing Table Register 6 */
+#define MXVR_ROUTING_7 0xFFC0289C /* MXVR Routing Table Register 7 */
+#define MXVR_ROUTING_8 0xFFC028A0 /* MXVR Routing Table Register 8 */
+#define MXVR_ROUTING_9 0xFFC028A4 /* MXVR Routing Table Register 9 */
+#define MXVR_ROUTING_10 0xFFC028A8 /* MXVR Routing Table Register 10 */
+#define MXVR_ROUTING_11 0xFFC028AC /* MXVR Routing Table Register 11 */
+#define MXVR_ROUTING_12 0xFFC028B0 /* MXVR Routing Table Register 12 */
+#define MXVR_ROUTING_13 0xFFC028B4 /* MXVR Routing Table Register 13 */
+#define MXVR_ROUTING_14 0xFFC028B8 /* MXVR Routing Table Register 14 */
+
+#define MXVR_PLL_CTL_1 0xFFC028BC /* MXVR Phase Lock Loop Control Register 1 */
+#define MXVR_BLOCK_CNT 0xFFC028C0 /* MXVR Block Counter */
+#define MXVR_PLL_CTL_2 0xFFC028C4 /* MXVR Phase Lock Loop Control Register 2 */
+
+
+/* CAN Controller (0xFFC02A00 - 0xFFC02FFF) */
+/* For Mailboxes 0-15 */
+#define CAN_MC1 0xFFC02A00 /* Mailbox config reg 1 */
+#define CAN_MD1 0xFFC02A04 /* Mailbox direction reg 1 */
+#define CAN_TRS1 0xFFC02A08 /* Transmit Request Set reg 1 */
+#define CAN_TRR1 0xFFC02A0C /* Transmit Request Reset reg 1 */
+#define CAN_TA1 0xFFC02A10 /* Transmit Acknowledge reg 1 */
+#define CAN_AA1 0xFFC02A14 /* Transmit Abort Acknowledge reg 1 */
+#define CAN_RMP1 0xFFC02A18 /* Receive Message Pending reg 1 */
+#define CAN_RML1 0xFFC02A1C /* Receive Message Lost reg 1 */
+#define CAN_MBTIF1 0xFFC02A20 /* Mailbox Transmit Interrupt Flag reg 1 */
+#define CAN_MBRIF1 0xFFC02A24 /* Mailbox Receive Interrupt Flag reg 1 */
+#define CAN_MBIM1 0xFFC02A28 /* Mailbox Interrupt Mask reg 1 */
+#define CAN_RFH1 0xFFC02A2C /* Remote Frame Handling reg 1 */
+#define CAN_OPSS1 0xFFC02A30 /* Overwrite Protection Single Shot Xmission reg 1 */
+
+/* For Mailboxes 16-31 */
+#define CAN_MC2 0xFFC02A40 /* Mailbox config reg 2 */
+#define CAN_MD2 0xFFC02A44 /* Mailbox direction reg 2 */
+#define CAN_TRS2 0xFFC02A48 /* Transmit Request Set reg 2 */
+#define CAN_TRR2 0xFFC02A4C /* Transmit Request Reset reg 2 */
+#define CAN_TA2 0xFFC02A50 /* Transmit Acknowledge reg 2 */
+#define CAN_AA2 0xFFC02A54 /* Transmit Abort Acknowledge reg 2 */
+#define CAN_RMP2 0xFFC02A58 /* Receive Message Pending reg 2 */
+#define CAN_RML2 0xFFC02A5C /* Receive Message Lost reg 2 */
+#define CAN_MBTIF2 0xFFC02A60 /* Mailbox Transmit Interrupt Flag reg 2 */
+#define CAN_MBRIF2 0xFFC02A64 /* Mailbox Receive Interrupt Flag reg 2 */
+#define CAN_MBIM2 0xFFC02A68 /* Mailbox Interrupt Mask reg 2 */
+#define CAN_RFH2 0xFFC02A6C /* Remote Frame Handling reg 2 */
+#define CAN_OPSS2 0xFFC02A70 /* Overwrite Protection Single Shot Xmission reg 2 */
+
+#define CAN_CLOCK 0xFFC02A80 /* Bit Timing Configuration register 0 */
+#define CAN_TIMING 0xFFC02A84 /* Bit Timing Configuration register 1 */
+
+#define CAN_DEBUG 0xFFC02A88 /* Debug Register */
+/* the following is for backwards compatibility */
+#define CAN_CNF CAN_DEBUG
+
+#define CAN_STATUS 0xFFC02A8C /* Global Status Register */
+#define CAN_CEC 0xFFC02A90 /* Error Counter Register */
+#define CAN_GIS 0xFFC02A94 /* Global Interrupt Status Register */
+#define CAN_GIM 0xFFC02A98 /* Global Interrupt Mask Register */
+#define CAN_GIF 0xFFC02A9C /* Global Interrupt Flag Register */
+#define CAN_CONTROL 0xFFC02AA0 /* Master Control Register */
+#define CAN_INTR 0xFFC02AA4 /* Interrupt Pending Register */
+#define CAN_MBTD 0xFFC02AAC /* Mailbox Temporary Disable Feature */
+#define CAN_EWR 0xFFC02AB0 /* Programmable Warning Level */
+#define CAN_ESR 0xFFC02AB4 /* Error Status Register */
+#define CAN_UCCNT 0xFFC02AC4 /* Universal Counter */
+#define CAN_UCRC 0xFFC02AC8 /* Universal Counter Reload/Capture Register */
+#define CAN_UCCNF 0xFFC02ACC /* Universal Counter Configuration Register */
+
+/* Mailbox Acceptance Masks */
+#define CAN_AM00L 0xFFC02B00 /* Mailbox 0 Low Acceptance Mask */
+#define CAN_AM00H 0xFFC02B04 /* Mailbox 0 High Acceptance Mask */
+#define CAN_AM01L 0xFFC02B08 /* Mailbox 1 Low Acceptance Mask */
+#define CAN_AM01H 0xFFC02B0C /* Mailbox 1 High Acceptance Mask */
+#define CAN_AM02L 0xFFC02B10 /* Mailbox 2 Low Acceptance Mask */
+#define CAN_AM02H 0xFFC02B14 /* Mailbox 2 High Acceptance Mask */
+#define CAN_AM03L 0xFFC02B18 /* Mailbox 3 Low Acceptance Mask */
+#define CAN_AM03H 0xFFC02B1C /* Mailbox 3 High Acceptance Mask */
+#define CAN_AM04L 0xFFC02B20 /* Mailbox 4 Low Acceptance Mask */
+#define CAN_AM04H 0xFFC02B24 /* Mailbox 4 High Acceptance Mask */
+#define CAN_AM05L 0xFFC02B28 /* Mailbox 5 Low Acceptance Mask */
+#define CAN_AM05H 0xFFC02B2C /* Mailbox 5 High Acceptance Mask */
+#define CAN_AM06L 0xFFC02B30 /* Mailbox 6 Low Acceptance Mask */
+#define CAN_AM06H 0xFFC02B34 /* Mailbox 6 High Acceptance Mask */
+#define CAN_AM07L 0xFFC02B38 /* Mailbox 7 Low Acceptance Mask */
+#define CAN_AM07H 0xFFC02B3C /* Mailbox 7 High Acceptance Mask */
+#define CAN_AM08L 0xFFC02B40 /* Mailbox 8 Low Acceptance Mask */
+#define CAN_AM08H 0xFFC02B44 /* Mailbox 8 High Acceptance Mask */
+#define CAN_AM09L 0xFFC02B48 /* Mailbox 9 Low Acceptance Mask */
+#define CAN_AM09H 0xFFC02B4C /* Mailbox 9 High Acceptance Mask */
+#define CAN_AM10L 0xFFC02B50 /* Mailbox 10 Low Acceptance Mask */
+#define CAN_AM10H 0xFFC02B54 /* Mailbox 10 High Acceptance Mask */
+#define CAN_AM11L 0xFFC02B58 /* Mailbox 11 Low Acceptance Mask */
+#define CAN_AM11H 0xFFC02B5C /* Mailbox 11 High Acceptance Mask */
+#define CAN_AM12L 0xFFC02B60 /* Mailbox 12 Low Acceptance Mask */
+#define CAN_AM12H 0xFFC02B64 /* Mailbox 12 High Acceptance Mask */
+#define CAN_AM13L 0xFFC02B68 /* Mailbox 13 Low Acceptance Mask */
+#define CAN_AM13H 0xFFC02B6C /* Mailbox 13 High Acceptance Mask */
+#define CAN_AM14L 0xFFC02B70 /* Mailbox 14 Low Acceptance Mask */
+#define CAN_AM14H 0xFFC02B74 /* Mailbox 14 High Acceptance Mask */
+#define CAN_AM15L 0xFFC02B78 /* Mailbox 15 Low Acceptance Mask */
+#define CAN_AM15H 0xFFC02B7C /* Mailbox 15 High Acceptance Mask */
+
+#define CAN_AM16L 0xFFC02B80 /* Mailbox 16 Low Acceptance Mask */
+#define CAN_AM16H 0xFFC02B84 /* Mailbox 16 High Acceptance Mask */
+#define CAN_AM17L 0xFFC02B88 /* Mailbox 17 Low Acceptance Mask */
+#define CAN_AM17H 0xFFC02B8C /* Mailbox 17 High Acceptance Mask */
+#define CAN_AM18L 0xFFC02B90 /* Mailbox 18 Low Acceptance Mask */
+#define CAN_AM18H 0xFFC02B94 /* Mailbox 18 High Acceptance Mask */
+#define CAN_AM19L 0xFFC02B98 /* Mailbox 19 Low Acceptance Mask */
+#define CAN_AM19H 0xFFC02B9C /* Mailbox 19 High Acceptance Mask */
+#define CAN_AM20L 0xFFC02BA0 /* Mailbox 20 Low Acceptance Mask */
+#define CAN_AM20H 0xFFC02BA4 /* Mailbox 20 High Acceptance Mask */
+#define CAN_AM21L 0xFFC02BA8 /* Mailbox 21 Low Acceptance Mask */
+#define CAN_AM21H 0xFFC02BAC /* Mailbox 21 High Acceptance Mask */
+#define CAN_AM22L 0xFFC02BB0 /* Mailbox 22 Low Acceptance Mask */
+#define CAN_AM22H 0xFFC02BB4 /* Mailbox 22 High Acceptance Mask */
+#define CAN_AM23L 0xFFC02BB8 /* Mailbox 23 Low Acceptance Mask */
+#define CAN_AM23H 0xFFC02BBC /* Mailbox 23 High Acceptance Mask */
+#define CAN_AM24L 0xFFC02BC0 /* Mailbox 24 Low Acceptance Mask */
+#define CAN_AM24H 0xFFC02BC4 /* Mailbox 24 High Acceptance Mask */
+#define CAN_AM25L 0xFFC02BC8 /* Mailbox 25 Low Acceptance Mask */
+#define CAN_AM25H 0xFFC02BCC /* Mailbox 25 High Acceptance Mask */
+#define CAN_AM26L 0xFFC02BD0 /* Mailbox 26 Low Acceptance Mask */
+#define CAN_AM26H 0xFFC02BD4 /* Mailbox 26 High Acceptance Mask */
+#define CAN_AM27L 0xFFC02BD8 /* Mailbox 27 Low Acceptance Mask */
+#define CAN_AM27H 0xFFC02BDC /* Mailbox 27 High Acceptance Mask */
+#define CAN_AM28L 0xFFC02BE0 /* Mailbox 28 Low Acceptance Mask */
+#define CAN_AM28H 0xFFC02BE4 /* Mailbox 28 High Acceptance Mask */
+#define CAN_AM29L 0xFFC02BE8 /* Mailbox 29 Low Acceptance Mask */
+#define CAN_AM29H 0xFFC02BEC /* Mailbox 29 High Acceptance Mask */
+#define CAN_AM30L 0xFFC02BF0 /* Mailbox 30 Low Acceptance Mask */
+#define CAN_AM30H 0xFFC02BF4 /* Mailbox 30 High Acceptance Mask */
+#define CAN_AM31L 0xFFC02BF8 /* Mailbox 31 Low Acceptance Mask */
+#define CAN_AM31H 0xFFC02BFC /* Mailbox 31 High Acceptance Mask */
+
+/* CAN Acceptance Mask Macros */
+#define CAN_AM_L(x) (CAN_AM00L+((x)*0x8))
+#define CAN_AM_H(x) (CAN_AM00H+((x)*0x8))
+
+/* Mailbox Registers */
+#define CAN_MB00_DATA0 0xFFC02C00 /* Mailbox 0 Data Word 0 [15:0] Register */
+#define CAN_MB00_DATA1 0xFFC02C04 /* Mailbox 0 Data Word 1 [31:16] Register */
+#define CAN_MB00_DATA2 0xFFC02C08 /* Mailbox 0 Data Word 2 [47:32] Register */
+#define CAN_MB00_DATA3 0xFFC02C0C /* Mailbox 0 Data Word 3 [63:48] Register */
+#define CAN_MB00_LENGTH 0xFFC02C10 /* Mailbox 0 Data Length Code Register */
+#define CAN_MB00_TIMESTAMP 0xFFC02C14 /* Mailbox 0 Time Stamp Value Register */
+#define CAN_MB00_ID0 0xFFC02C18 /* Mailbox 0 Identifier Low Register */
+#define CAN_MB00_ID1 0xFFC02C1C /* Mailbox 0 Identifier High Register */
+
+#define CAN_MB01_DATA0 0xFFC02C20 /* Mailbox 1 Data Word 0 [15:0] Register */
+#define CAN_MB01_DATA1 0xFFC02C24 /* Mailbox 1 Data Word 1 [31:16] Register */
+#define CAN_MB01_DATA2 0xFFC02C28 /* Mailbox 1 Data Word 2 [47:32] Register */
+#define CAN_MB01_DATA3 0xFFC02C2C /* Mailbox 1 Data Word 3 [63:48] Register */
+#define CAN_MB01_LENGTH 0xFFC02C30 /* Mailbox 1 Data Length Code Register */
+#define CAN_MB01_TIMESTAMP 0xFFC02C34 /* Mailbox 1 Time Stamp Value Register */
+#define CAN_MB01_ID0 0xFFC02C38 /* Mailbox 1 Identifier Low Register */
+#define CAN_MB01_ID1 0xFFC02C3C /* Mailbox 1 Identifier High Register */
+
+#define CAN_MB02_DATA0 0xFFC02C40 /* Mailbox 2 Data Word 0 [15:0] Register */
+#define CAN_MB02_DATA1 0xFFC02C44 /* Mailbox 2 Data Word 1 [31:16] Register */
+#define CAN_MB02_DATA2 0xFFC02C48 /* Mailbox 2 Data Word 2 [47:32] Register */
+#define CAN_MB02_DATA3 0xFFC02C4C /* Mailbox 2 Data Word 3 [63:48] Register */
+#define CAN_MB02_LENGTH 0xFFC02C50 /* Mailbox 2 Data Length Code Register */
+#define CAN_MB02_TIMESTAMP 0xFFC02C54 /* Mailbox 2 Time Stamp Value Register */
+#define CAN_MB02_ID0 0xFFC02C58 /* Mailbox 2 Identifier Low Register */
+#define CAN_MB02_ID1 0xFFC02C5C /* Mailbox 2 Identifier High Register */
+
+#define CAN_MB03_DATA0 0xFFC02C60 /* Mailbox 3 Data Word 0 [15:0] Register */
+#define CAN_MB03_DATA1 0xFFC02C64 /* Mailbox 3 Data Word 1 [31:16] Register */
+#define CAN_MB03_DATA2 0xFFC02C68 /* Mailbox 3 Data Word 2 [47:32] Register */
+#define CAN_MB03_DATA3 0xFFC02C6C /* Mailbox 3 Data Word 3 [63:48] Register */
+#define CAN_MB03_LENGTH 0xFFC02C70 /* Mailbox 3 Data Length Code Register */
+#define CAN_MB03_TIMESTAMP 0xFFC02C74 /* Mailbox 3 Time Stamp Value Register */
+#define CAN_MB03_ID0 0xFFC02C78 /* Mailbox 3 Identifier Low Register */
+#define CAN_MB03_ID1 0xFFC02C7C /* Mailbox 3 Identifier High Register */
+
+#define CAN_MB04_DATA0 0xFFC02C80 /* Mailbox 4 Data Word 0 [15:0] Register */
+#define CAN_MB04_DATA1 0xFFC02C84 /* Mailbox 4 Data Word 1 [31:16] Register */
+#define CAN_MB04_DATA2 0xFFC02C88 /* Mailbox 4 Data Word 2 [47:32] Register */
+#define CAN_MB04_DATA3 0xFFC02C8C /* Mailbox 4 Data Word 3 [63:48] Register */
+#define CAN_MB04_LENGTH 0xFFC02C90 /* Mailbox 4 Data Length Code Register */
+#define CAN_MB04_TIMESTAMP 0xFFC02C94 /* Mailbox 4 Time Stamp Value Register */
+#define CAN_MB04_ID0 0xFFC02C98 /* Mailbox 4 Identifier Low Register */
+#define CAN_MB04_ID1 0xFFC02C9C /* Mailbox 4 Identifier High Register */
+
+#define CAN_MB05_DATA0 0xFFC02CA0 /* Mailbox 5 Data Word 0 [15:0] Register */
+#define CAN_MB05_DATA1 0xFFC02CA4 /* Mailbox 5 Data Word 1 [31:16] Register */
+#define CAN_MB05_DATA2 0xFFC02CA8 /* Mailbox 5 Data Word 2 [47:32] Register */
+#define CAN_MB05_DATA3 0xFFC02CAC /* Mailbox 5 Data Word 3 [63:48] Register */
+#define CAN_MB05_LENGTH 0xFFC02CB0 /* Mailbox 5 Data Length Code Register */
+#define CAN_MB05_TIMESTAMP 0xFFC02CB4 /* Mailbox 5 Time Stamp Value Register */
+#define CAN_MB05_ID0 0xFFC02CB8 /* Mailbox 5 Identifier Low Register */
+#define CAN_MB05_ID1 0xFFC02CBC /* Mailbox 5 Identifier High Register */
+
+#define CAN_MB06_DATA0 0xFFC02CC0 /* Mailbox 6 Data Word 0 [15:0] Register */
+#define CAN_MB06_DATA1 0xFFC02CC4 /* Mailbox 6 Data Word 1 [31:16] Register */
+#define CAN_MB06_DATA2 0xFFC02CC8 /* Mailbox 6 Data Word 2 [47:32] Register */
+#define CAN_MB06_DATA3 0xFFC02CCC /* Mailbox 6 Data Word 3 [63:48] Register */
+#define CAN_MB06_LENGTH 0xFFC02CD0 /* Mailbox 6 Data Length Code Register */
+#define CAN_MB06_TIMESTAMP 0xFFC02CD4 /* Mailbox 6 Time Stamp Value Register */
+#define CAN_MB06_ID0 0xFFC02CD8 /* Mailbox 6 Identifier Low Register */
+#define CAN_MB06_ID1 0xFFC02CDC /* Mailbox 6 Identifier High Register */
+
+#define CAN_MB07_DATA0 0xFFC02CE0 /* Mailbox 7 Data Word 0 [15:0] Register */
+#define CAN_MB07_DATA1 0xFFC02CE4 /* Mailbox 7 Data Word 1 [31:16] Register */
+#define CAN_MB07_DATA2 0xFFC02CE8 /* Mailbox 7 Data Word 2 [47:32] Register */
+#define CAN_MB07_DATA3 0xFFC02CEC /* Mailbox 7 Data Word 3 [63:48] Register */
+#define CAN_MB07_LENGTH 0xFFC02CF0 /* Mailbox 7 Data Length Code Register */
+#define CAN_MB07_TIMESTAMP 0xFFC02CF4 /* Mailbox 7 Time Stamp Value Register */
+#define CAN_MB07_ID0 0xFFC02CF8 /* Mailbox 7 Identifier Low Register */
+#define CAN_MB07_ID1 0xFFC02CFC /* Mailbox 7 Identifier High Register */
+
+#define CAN_MB08_DATA0 0xFFC02D00 /* Mailbox 8 Data Word 0 [15:0] Register */
+#define CAN_MB08_DATA1 0xFFC02D04 /* Mailbox 8 Data Word 1 [31:16] Register */
+#define CAN_MB08_DATA2 0xFFC02D08 /* Mailbox 8 Data Word 2 [47:32] Register */
+#define CAN_MB08_DATA3 0xFFC02D0C /* Mailbox 8 Data Word 3 [63:48] Register */
+#define CAN_MB08_LENGTH 0xFFC02D10 /* Mailbox 8 Data Length Code Register */
+#define CAN_MB08_TIMESTAMP 0xFFC02D14 /* Mailbox 8 Time Stamp Value Register */
+#define CAN_MB08_ID0 0xFFC02D18 /* Mailbox 8 Identifier Low Register */
+#define CAN_MB08_ID1 0xFFC02D1C /* Mailbox 8 Identifier High Register */
+
+#define CAN_MB09_DATA0 0xFFC02D20 /* Mailbox 9 Data Word 0 [15:0] Register */
+#define CAN_MB09_DATA1 0xFFC02D24 /* Mailbox 9 Data Word 1 [31:16] Register */
+#define CAN_MB09_DATA2 0xFFC02D28 /* Mailbox 9 Data Word 2 [47:32] Register */
+#define CAN_MB09_DATA3 0xFFC02D2C /* Mailbox 9 Data Word 3 [63:48] Register */
+#define CAN_MB09_LENGTH 0xFFC02D30 /* Mailbox 9 Data Length Code Register */
+#define CAN_MB09_TIMESTAMP 0xFFC02D34 /* Mailbox 9 Time Stamp Value Register */
+#define CAN_MB09_ID0 0xFFC02D38 /* Mailbox 9 Identifier Low Register */
+#define CAN_MB09_ID1 0xFFC02D3C /* Mailbox 9 Identifier High Register */
+
+#define CAN_MB10_DATA0 0xFFC02D40 /* Mailbox 10 Data Word 0 [15:0] Register */
+#define CAN_MB10_DATA1 0xFFC02D44 /* Mailbox 10 Data Word 1 [31:16] Register */
+#define CAN_MB10_DATA2 0xFFC02D48 /* Mailbox 10 Data Word 2 [47:32] Register */
+#define CAN_MB10_DATA3 0xFFC02D4C /* Mailbox 10 Data Word 3 [63:48] Register */
+#define CAN_MB10_LENGTH 0xFFC02D50 /* Mailbox 10 Data Length Code Register */
+#define CAN_MB10_TIMESTAMP 0xFFC02D54 /* Mailbox 10 Time Stamp Value Register */
+#define CAN_MB10_ID0 0xFFC02D58 /* Mailbox 10 Identifier Low Register */
+#define CAN_MB10_ID1 0xFFC02D5C /* Mailbox 10 Identifier High Register */
+
+#define CAN_MB11_DATA0 0xFFC02D60 /* Mailbox 11 Data Word 0 [15:0] Register */
+#define CAN_MB11_DATA1 0xFFC02D64 /* Mailbox 11 Data Word 1 [31:16] Register */
+#define CAN_MB11_DATA2 0xFFC02D68 /* Mailbox 11 Data Word 2 [47:32] Register */
+#define CAN_MB11_DATA3 0xFFC02D6C /* Mailbox 11 Data Word 3 [63:48] Register */
+#define CAN_MB11_LENGTH 0xFFC02D70 /* Mailbox 11 Data Length Code Register */
+#define CAN_MB11_TIMESTAMP 0xFFC02D74 /* Mailbox 11 Time Stamp Value Register */
+#define CAN_MB11_ID0 0xFFC02D78 /* Mailbox 11 Identifier Low Register */
+#define CAN_MB11_ID1 0xFFC02D7C /* Mailbox 11 Identifier High Register */
+
+#define CAN_MB12_DATA0 0xFFC02D80 /* Mailbox 12 Data Word 0 [15:0] Register */
+#define CAN_MB12_DATA1 0xFFC02D84 /* Mailbox 12 Data Word 1 [31:16] Register */
+#define CAN_MB12_DATA2 0xFFC02D88 /* Mailbox 12 Data Word 2 [47:32] Register */
+#define CAN_MB12_DATA3 0xFFC02D8C /* Mailbox 12 Data Word 3 [63:48] Register */
+#define CAN_MB12_LENGTH 0xFFC02D90 /* Mailbox 12 Data Length Code Register */
+#define CAN_MB12_TIMESTAMP 0xFFC02D94 /* Mailbox 12 Time Stamp Value Register */
+#define CAN_MB12_ID0 0xFFC02D98 /* Mailbox 12 Identifier Low Register */
+#define CAN_MB12_ID1 0xFFC02D9C /* Mailbox 12 Identifier High Register */
+
+#define CAN_MB13_DATA0 0xFFC02DA0 /* Mailbox 13 Data Word 0 [15:0] Register */
+#define CAN_MB13_DATA1 0xFFC02DA4 /* Mailbox 13 Data Word 1 [31:16] Register */
+#define CAN_MB13_DATA2 0xFFC02DA8 /* Mailbox 13 Data Word 2 [47:32] Register */
+#define CAN_MB13_DATA3 0xFFC02DAC /* Mailbox 13 Data Word 3 [63:48] Register */
+#define CAN_MB13_LENGTH 0xFFC02DB0 /* Mailbox 13 Data Length Code Register */
+#define CAN_MB13_TIMESTAMP 0xFFC02DB4 /* Mailbox 13 Time Stamp Value Register */
+#define CAN_MB13_ID0 0xFFC02DB8 /* Mailbox 13 Identifier Low Register */
+#define CAN_MB13_ID1 0xFFC02DBC /* Mailbox 13 Identifier High Register */
+
+#define CAN_MB14_DATA0 0xFFC02DC0 /* Mailbox 14 Data Word 0 [15:0] Register */
+#define CAN_MB14_DATA1 0xFFC02DC4 /* Mailbox 14 Data Word 1 [31:16] Register */
+#define CAN_MB14_DATA2 0xFFC02DC8 /* Mailbox 14 Data Word 2 [47:32] Register */
+#define CAN_MB14_DATA3 0xFFC02DCC /* Mailbox 14 Data Word 3 [63:48] Register */
+#define CAN_MB14_LENGTH 0xFFC02DD0 /* Mailbox 14 Data Length Code Register */
+#define CAN_MB14_TIMESTAMP 0xFFC02DD4 /* Mailbox 14 Time Stamp Value Register */
+#define CAN_MB14_ID0 0xFFC02DD8 /* Mailbox 14 Identifier Low Register */
+#define CAN_MB14_ID1 0xFFC02DDC /* Mailbox 14 Identifier High Register */
+
+#define CAN_MB15_DATA0 0xFFC02DE0 /* Mailbox 15 Data Word 0 [15:0] Register */
+#define CAN_MB15_DATA1 0xFFC02DE4 /* Mailbox 15 Data Word 1 [31:16] Register */
+#define CAN_MB15_DATA2 0xFFC02DE8 /* Mailbox 15 Data Word 2 [47:32] Register */
+#define CAN_MB15_DATA3 0xFFC02DEC /* Mailbox 15 Data Word 3 [63:48] Register */
+#define CAN_MB15_LENGTH 0xFFC02DF0 /* Mailbox 15 Data Length Code Register */
+#define CAN_MB15_TIMESTAMP 0xFFC02DF4 /* Mailbox 15 Time Stamp Value Register */
+#define CAN_MB15_ID0 0xFFC02DF8 /* Mailbox 15 Identifier Low Register */
+#define CAN_MB15_ID1 0xFFC02DFC /* Mailbox 15 Identifier High Register */
+
+#define CAN_MB16_DATA0 0xFFC02E00 /* Mailbox 16 Data Word 0 [15:0] Register */
+#define CAN_MB16_DATA1 0xFFC02E04 /* Mailbox 16 Data Word 1 [31:16] Register */
+#define CAN_MB16_DATA2 0xFFC02E08 /* Mailbox 16 Data Word 2 [47:32] Register */
+#define CAN_MB16_DATA3 0xFFC02E0C /* Mailbox 16 Data Word 3 [63:48] Register */
+#define CAN_MB16_LENGTH 0xFFC02E10 /* Mailbox 16 Data Length Code Register */
+#define CAN_MB16_TIMESTAMP 0xFFC02E14 /* Mailbox 16 Time Stamp Value Register */
+#define CAN_MB16_ID0 0xFFC02E18 /* Mailbox 16 Identifier Low Register */
+#define CAN_MB16_ID1 0xFFC02E1C /* Mailbox 16 Identifier High Register */
+
+#define CAN_MB17_DATA0 0xFFC02E20 /* Mailbox 17 Data Word 0 [15:0] Register */
+#define CAN_MB17_DATA1 0xFFC02E24 /* Mailbox 17 Data Word 1 [31:16] Register */
+#define CAN_MB17_DATA2 0xFFC02E28 /* Mailbox 17 Data Word 2 [47:32] Register */
+#define CAN_MB17_DATA3 0xFFC02E2C /* Mailbox 17 Data Word 3 [63:48] Register */
+#define CAN_MB17_LENGTH 0xFFC02E30 /* Mailbox 17 Data Length Code Register */
+#define CAN_MB17_TIMESTAMP 0xFFC02E34 /* Mailbox 17 Time Stamp Value Register */
+#define CAN_MB17_ID0 0xFFC02E38 /* Mailbox 17 Identifier Low Register */
+#define CAN_MB17_ID1 0xFFC02E3C /* Mailbox 17 Identifier High Register */
+
+#define CAN_MB18_DATA0 0xFFC02E40 /* Mailbox 18 Data Word 0 [15:0] Register */
+#define CAN_MB18_DATA1 0xFFC02E44 /* Mailbox 18 Data Word 1 [31:16] Register */
+#define CAN_MB18_DATA2 0xFFC02E48 /* Mailbox 18 Data Word 2 [47:32] Register */
+#define CAN_MB18_DATA3 0xFFC02E4C /* Mailbox 18 Data Word 3 [63:48] Register */
+#define CAN_MB18_LENGTH 0xFFC02E50 /* Mailbox 18 Data Length Code Register */
+#define CAN_MB18_TIMESTAMP 0xFFC02E54 /* Mailbox 18 Time Stamp Value Register */
+#define CAN_MB18_ID0 0xFFC02E58 /* Mailbox 18 Identifier Low Register */
+#define CAN_MB18_ID1 0xFFC02E5C /* Mailbox 18 Identifier High Register */
+
+#define CAN_MB19_DATA0 0xFFC02E60 /* Mailbox 19 Data Word 0 [15:0] Register */
+#define CAN_MB19_DATA1 0xFFC02E64 /* Mailbox 19 Data Word 1 [31:16] Register */
+#define CAN_MB19_DATA2 0xFFC02E68 /* Mailbox 19 Data Word 2 [47:32] Register */
+#define CAN_MB19_DATA3 0xFFC02E6C /* Mailbox 19 Data Word 3 [63:48] Register */
+#define CAN_MB19_LENGTH 0xFFC02E70 /* Mailbox 19 Data Length Code Register */
+#define CAN_MB19_TIMESTAMP 0xFFC02E74 /* Mailbox 19 Time Stamp Value Register */
+#define CAN_MB19_ID0 0xFFC02E78 /* Mailbox 19 Identifier Low Register */
+#define CAN_MB19_ID1 0xFFC02E7C /* Mailbox 19 Identifier High Register */
+
+#define CAN_MB20_DATA0 0xFFC02E80 /* Mailbox 20 Data Word 0 [15:0] Register */
+#define CAN_MB20_DATA1 0xFFC02E84 /* Mailbox 20 Data Word 1 [31:16] Register */
+#define CAN_MB20_DATA2 0xFFC02E88 /* Mailbox 20 Data Word 2 [47:32] Register */
+#define CAN_MB20_DATA3 0xFFC02E8C /* Mailbox 20 Data Word 3 [63:48] Register */
+#define CAN_MB20_LENGTH 0xFFC02E90 /* Mailbox 20 Data Length Code Register */
+#define CAN_MB20_TIMESTAMP 0xFFC02E94 /* Mailbox 20 Time Stamp Value Register */
+#define CAN_MB20_ID0 0xFFC02E98 /* Mailbox 20 Identifier Low Register */
+#define CAN_MB20_ID1 0xFFC02E9C /* Mailbox 20 Identifier High Register */
+
+#define CAN_MB21_DATA0 0xFFC02EA0 /* Mailbox 21 Data Word 0 [15:0] Register */
+#define CAN_MB21_DATA1 0xFFC02EA4 /* Mailbox 21 Data Word 1 [31:16] Register */
+#define CAN_MB21_DATA2 0xFFC02EA8 /* Mailbox 21 Data Word 2 [47:32] Register */
+#define CAN_MB21_DATA3 0xFFC02EAC /* Mailbox 21 Data Word 3 [63:48] Register */
+#define CAN_MB21_LENGTH 0xFFC02EB0 /* Mailbox 21 Data Length Code Register */
+#define CAN_MB21_TIMESTAMP 0xFFC02EB4 /* Mailbox 21 Time Stamp Value Register */
+#define CAN_MB21_ID0 0xFFC02EB8 /* Mailbox 21 Identifier Low Register */
+#define CAN_MB21_ID1 0xFFC02EBC /* Mailbox 21 Identifier High Register */
+
+#define CAN_MB22_DATA0 0xFFC02EC0 /* Mailbox 22 Data Word 0 [15:0] Register */
+#define CAN_MB22_DATA1 0xFFC02EC4 /* Mailbox 22 Data Word 1 [31:16] Register */
+#define CAN_MB22_DATA2 0xFFC02EC8 /* Mailbox 22 Data Word 2 [47:32] Register */
+#define CAN_MB22_DATA3 0xFFC02ECC /* Mailbox 22 Data Word 3 [63:48] Register */
+#define CAN_MB22_LENGTH 0xFFC02ED0 /* Mailbox 22 Data Length Code Register */
+#define CAN_MB22_TIMESTAMP 0xFFC02ED4 /* Mailbox 22 Time Stamp Value Register */
+#define CAN_MB22_ID0 0xFFC02ED8 /* Mailbox 22 Identifier Low Register */
+#define CAN_MB22_ID1 0xFFC02EDC /* Mailbox 22 Identifier High Register */
+
+#define CAN_MB23_DATA0 0xFFC02EE0 /* Mailbox 23 Data Word 0 [15:0] Register */
+#define CAN_MB23_DATA1 0xFFC02EE4 /* Mailbox 23 Data Word 1 [31:16] Register */
+#define CAN_MB23_DATA2 0xFFC02EE8 /* Mailbox 23 Data Word 2 [47:32] Register */
+#define CAN_MB23_DATA3 0xFFC02EEC /* Mailbox 23 Data Word 3 [63:48] Register */
+#define CAN_MB23_LENGTH 0xFFC02EF0 /* Mailbox 23 Data Length Code Register */
+#define CAN_MB23_TIMESTAMP 0xFFC02EF4 /* Mailbox 23 Time Stamp Value Register */
+#define CAN_MB23_ID0 0xFFC02EF8 /* Mailbox 23 Identifier Low Register */
+#define CAN_MB23_ID1 0xFFC02EFC /* Mailbox 23 Identifier High Register */
+
+#define CAN_MB24_DATA0 0xFFC02F00 /* Mailbox 24 Data Word 0 [15:0] Register */
+#define CAN_MB24_DATA1 0xFFC02F04 /* Mailbox 24 Data Word 1 [31:16] Register */
+#define CAN_MB24_DATA2 0xFFC02F08 /* Mailbox 24 Data Word 2 [47:32] Register */
+#define CAN_MB24_DATA3 0xFFC02F0C /* Mailbox 24 Data Word 3 [63:48] Register */
+#define CAN_MB24_LENGTH 0xFFC02F10 /* Mailbox 24 Data Length Code Register */
+#define CAN_MB24_TIMESTAMP 0xFFC02F14 /* Mailbox 24 Time Stamp Value Register */
+#define CAN_MB24_ID0 0xFFC02F18 /* Mailbox 24 Identifier Low Register */
+#define CAN_MB24_ID1 0xFFC02F1C /* Mailbox 24 Identifier High Register */
+
+#define CAN_MB25_DATA0 0xFFC02F20 /* Mailbox 25 Data Word 0 [15:0] Register */
+#define CAN_MB25_DATA1 0xFFC02F24 /* Mailbox 25 Data Word 1 [31:16] Register */
+#define CAN_MB25_DATA2 0xFFC02F28 /* Mailbox 25 Data Word 2 [47:32] Register */
+#define CAN_MB25_DATA3 0xFFC02F2C /* Mailbox 25 Data Word 3 [63:48] Register */
+#define CAN_MB25_LENGTH 0xFFC02F30 /* Mailbox 25 Data Length Code Register */
+#define CAN_MB25_TIMESTAMP 0xFFC02F34 /* Mailbox 25 Time Stamp Value Register */
+#define CAN_MB25_ID0 0xFFC02F38 /* Mailbox 25 Identifier Low Register */
+#define CAN_MB25_ID1 0xFFC02F3C /* Mailbox 25 Identifier High Register */
+
+#define CAN_MB26_DATA0 0xFFC02F40 /* Mailbox 26 Data Word 0 [15:0] Register */
+#define CAN_MB26_DATA1 0xFFC02F44 /* Mailbox 26 Data Word 1 [31:16] Register */
+#define CAN_MB26_DATA2 0xFFC02F48 /* Mailbox 26 Data Word 2 [47:32] Register */
+#define CAN_MB26_DATA3 0xFFC02F4C /* Mailbox 26 Data Word 3 [63:48] Register */
+#define CAN_MB26_LENGTH 0xFFC02F50 /* Mailbox 26 Data Length Code Register */
+#define CAN_MB26_TIMESTAMP 0xFFC02F54 /* Mailbox 26 Time Stamp Value Register */
+#define CAN_MB26_ID0 0xFFC02F58 /* Mailbox 26 Identifier Low Register */
+#define CAN_MB26_ID1 0xFFC02F5C /* Mailbox 26 Identifier High Register */
+
+#define CAN_MB27_DATA0 0xFFC02F60 /* Mailbox 27 Data Word 0 [15:0] Register */
+#define CAN_MB27_DATA1 0xFFC02F64 /* Mailbox 27 Data Word 1 [31:16] Register */
+#define CAN_MB27_DATA2 0xFFC02F68 /* Mailbox 27 Data Word 2 [47:32] Register */
+#define CAN_MB27_DATA3 0xFFC02F6C /* Mailbox 27 Data Word 3 [63:48] Register */
+#define CAN_MB27_LENGTH 0xFFC02F70 /* Mailbox 27 Data Length Code Register */
+#define CAN_MB27_TIMESTAMP 0xFFC02F74 /* Mailbox 27 Time Stamp Value Register */
+#define CAN_MB27_ID0 0xFFC02F78 /* Mailbox 27 Identifier Low Register */
+#define CAN_MB27_ID1 0xFFC02F7C /* Mailbox 27 Identifier High Register */
+
+#define CAN_MB28_DATA0 0xFFC02F80 /* Mailbox 28 Data Word 0 [15:0] Register */
+#define CAN_MB28_DATA1 0xFFC02F84 /* Mailbox 28 Data Word 1 [31:16] Register */
+#define CAN_MB28_DATA2 0xFFC02F88 /* Mailbox 28 Data Word 2 [47:32] Register */
+#define CAN_MB28_DATA3 0xFFC02F8C /* Mailbox 28 Data Word 3 [63:48] Register */
+#define CAN_MB28_LENGTH 0xFFC02F90 /* Mailbox 28 Data Length Code Register */
+#define CAN_MB28_TIMESTAMP 0xFFC02F94 /* Mailbox 28 Time Stamp Value Register */
+#define CAN_MB28_ID0 0xFFC02F98 /* Mailbox 28 Identifier Low Register */
+#define CAN_MB28_ID1 0xFFC02F9C /* Mailbox 28 Identifier High Register */
+
+#define CAN_MB29_DATA0 0xFFC02FA0 /* Mailbox 29 Data Word 0 [15:0] Register */
+#define CAN_MB29_DATA1 0xFFC02FA4 /* Mailbox 29 Data Word 1 [31:16] Register */
+#define CAN_MB29_DATA2 0xFFC02FA8 /* Mailbox 29 Data Word 2 [47:32] Register */
+#define CAN_MB29_DATA3 0xFFC02FAC /* Mailbox 29 Data Word 3 [63:48] Register */
+#define CAN_MB29_LENGTH 0xFFC02FB0 /* Mailbox 29 Data Length Code Register */
+#define CAN_MB29_TIMESTAMP 0xFFC02FB4 /* Mailbox 29 Time Stamp Value Register */
+#define CAN_MB29_ID0 0xFFC02FB8 /* Mailbox 29 Identifier Low Register */
+#define CAN_MB29_ID1 0xFFC02FBC /* Mailbox 29 Identifier High Register */
+
+#define CAN_MB30_DATA0 0xFFC02FC0 /* Mailbox 30 Data Word 0 [15:0] Register */
+#define CAN_MB30_DATA1 0xFFC02FC4 /* Mailbox 30 Data Word 1 [31:16] Register */
+#define CAN_MB30_DATA2 0xFFC02FC8 /* Mailbox 30 Data Word 2 [47:32] Register */
+#define CAN_MB30_DATA3 0xFFC02FCC /* Mailbox 30 Data Word 3 [63:48] Register */
+#define CAN_MB30_LENGTH 0xFFC02FD0 /* Mailbox 30 Data Length Code Register */
+#define CAN_MB30_TIMESTAMP 0xFFC02FD4 /* Mailbox 30 Time Stamp Value Register */
+#define CAN_MB30_ID0 0xFFC02FD8 /* Mailbox 30 Identifier Low Register */
+#define CAN_MB30_ID1 0xFFC02FDC /* Mailbox 30 Identifier High Register */
+
+#define CAN_MB31_DATA0 0xFFC02FE0 /* Mailbox 31 Data Word 0 [15:0] Register */
+#define CAN_MB31_DATA1 0xFFC02FE4 /* Mailbox 31 Data Word 1 [31:16] Register */
+#define CAN_MB31_DATA2 0xFFC02FE8 /* Mailbox 31 Data Word 2 [47:32] Register */
+#define CAN_MB31_DATA3 0xFFC02FEC /* Mailbox 31 Data Word 3 [63:48] Register */
+#define CAN_MB31_LENGTH 0xFFC02FF0 /* Mailbox 31 Data Length Code Register */
+#define CAN_MB31_TIMESTAMP 0xFFC02FF4 /* Mailbox 31 Time Stamp Value Register */
+#define CAN_MB31_ID0 0xFFC02FF8 /* Mailbox 31 Identifier Low Register */
+#define CAN_MB31_ID1 0xFFC02FFC /* Mailbox 31 Identifier High Register */
+
+/* CAN Mailbox Area Macros */
+#define CAN_MB_ID1(x) (CAN_MB00_ID1+((x)*0x20))
+#define CAN_MB_ID0(x) (CAN_MB00_ID0+((x)*0x20))
+#define CAN_MB_TIMESTAMP(x) (CAN_MB00_TIMESTAMP+((x)*0x20))
+#define CAN_MB_LENGTH(x) (CAN_MB00_LENGTH+((x)*0x20))
+#define CAN_MB_DATA3(x) (CAN_MB00_DATA3+((x)*0x20))
+#define CAN_MB_DATA2(x) (CAN_MB00_DATA2+((x)*0x20))
+#define CAN_MB_DATA1(x) (CAN_MB00_DATA1+((x)*0x20))
+#define CAN_MB_DATA0(x) (CAN_MB00_DATA0+((x)*0x20))
+
+
+/*********************************************************************************** */
+/* System MMR Register Bits and Macros */
+/******************************************************************************* */
+
+/* ********************* PLL AND RESET MASKS ************************ */
+/* PLL_CTL Masks */
+#define PLL_CLKIN 0x0000 /* Pass CLKIN to PLL */
+#define PLL_CLKIN_DIV2 0x0001 /* Pass CLKIN/2 to PLL */
+#define DF 0x0001 /* 0: PLL = CLKIN, 1: PLL = CLKIN/2 */
+#define PLL_OFF 0x0002 /* Shut off PLL clocks */
+
+#define STOPCK 0x0008 /* Core Clock Off */
+#define PDWN 0x0020 /* Put the PLL in a Deep Sleep state */
+#define IN_DELAY 0x0014 /* EBIU Input Delay Select */
+#define OUT_DELAY 0x00C0 /* EBIU Output Delay Select */
+#define BYPASS 0x0100 /* Bypass the PLL */
+#define MSEL 0x7E00 /* Multiplier Select For CCLK/VCO Factors */
+
+/* PLL_CTL Macros */
+#ifdef _MISRA_RULES
+#define SET_MSEL(x) (((x)&0x3Fu) << 0x9) /* Set MSEL = 0-63 --> VCO = CLKIN*MSEL */
+#define SET_OUT_DELAY(x) (((x)&0x03u) << 0x6)
+#define SET_IN_DELAY(x) ((((x)&0x02u) << 0x3) | (((x)&0x01u) << 0x2))
+#else
+#define SET_MSEL(x) (((x)&0x3F) << 0x9) /* Set MSEL = 0-63 --> VCO = CLKIN*MSEL */
+#define SET_OUT_DELAY(x) (((x)&0x03) << 0x6)
+#define SET_IN_DELAY(x) ((((x)&0x02) << 0x3) | (((x)&0x01) << 0x2))
+#endif /* _MISRA_RULES */
+
+/* PLL_DIV Masks */
+#define SSEL 0x000F /* System Select */
+#define CSEL 0x0030 /* Core Select */
+#define CSEL_DIV1 0x0000 /* CCLK = VCO / 1 */
+#define CSEL_DIV2 0x0010 /* CCLK = VCO / 2 */
+#define CSEL_DIV4 0x0020 /* CCLK = VCO / 4 */
+#define CSEL_DIV8 0x0030 /* CCLK = VCO / 8 */
+
+#define SCLK_DIV(x) (x) /* SCLK = VCO / x */
+
+/* PLL_DIV Macros */
+#ifdef _MISRA_RULES
+#define SET_SSEL(x) ((x)&0xFu) /* Set SSEL = 0-15 --> SCLK = VCO/SSEL */
+#else
+#define SET_SSEL(x) ((x)&0xF) /* Set SSEL = 0-15 --> SCLK = VCO/SSEL */
+#endif /* _MISRA_RULES */
+
+/* PLL_STAT Masks */
+#define ACTIVE_PLLENABLED 0x0001 /* Processor In Active Mode With PLL Enabled */
+#define FULL_ON 0x0002 /* Processor In Full On Mode */
+#define ACTIVE_PLLDISABLED 0x0004 /* Processor In Active Mode With PLL Disabled */
+#define PLL_LOCKED 0x0020 /* PLL_LOCKCNT Has Been Reached */
+
+/* VR_CTL Masks */
+#define FREQ 0x0003 /* Switching Oscillator Frequency For Regulator */
+#define HIBERNATE 0x0000 /* Powerdown/Bypass On-Board Regulation */
+#define FREQ_333 0x0001 /* Switching Frequency Is 333 kHz */
+#define FREQ_667 0x0002 /* Switching Frequency Is 667 kHz */
+#define FREQ_1000 0x0003 /* Switching Frequency Is 1 MHz */
+
+#define GAIN 0x000C /* Voltage Level Gain */
+#define GAIN_5 0x0000 /* GAIN = 5 */
+#define GAIN_10 0x0004 /* GAIN = 10 */
+#define GAIN_20 0x0008 /* GAIN = 20 */
+#define GAIN_50 0x000C /* GAIN = 50 */
+
+#define VLEV 0x00F0 /* Internal Voltage Level - Only Program Values Within Specifications */
+#define VLEV_100 0x0090 /* VLEV = 1.00 V (See Datasheet for Regulator Tolerance) */
+#define VLEV_105 0x00A0 /* VLEV = 1.05 V (See Datasheet for Regulator Tolerance) */
+#define VLEV_110 0x00B0 /* VLEV = 1.10 V (See Datasheet for Regulator Tolerance) */
+#define VLEV_115 0x00C0 /* VLEV = 1.15 V (See Datasheet for Regulator Tolerance) */
+#define VLEV_120 0x00D0 /* VLEV = 1.20 V (See Datasheet for Regulator Tolerance) */
+#define VLEV_125 0x00E0 /* VLEV = 1.25 V (See Datasheet for Regulator Tolerance) */
+#define VLEV_130 0x00F0 /* VLEV = 1.30 V (See Datasheet for Regulator Tolerance) */
+
+#define WAKE 0x0100 /* Enable RTC/Reset Wakeup From Hibernate */
+#define CANWE 0x0200 /* Enable CAN Wakeup From Hibernate */
+#define MXVRWE 0x0400 /* Enable MXVR Wakeup From Hibernate */
+#define SCKELOW 0x8000 /* Do Not Drive SCKE High During Reset After Hibernate */
+
+/* SWRST Mask */
+#define SYSTEM_RESET 0x0007 /* Initiates A System Software Reset */
+#define DOUBLE_FAULT 0x0008 /* Core Double Fault Causes Reset */
+#define RESET_DOUBLE 0x2000 /* SW Reset Generated By Core Double-Fault */
+#define RESET_WDOG 0x4000 /* SW Reset Generated By Watchdog Timer */
+#define RESET_SOFTWARE 0x8000 /* SW Reset Occurred Since Last Read Of SWRST */
+
+/* SYSCR Masks */
+#define BMODE 0x0006 /* Boot Mode - Latched During HW Reset From Mode Pins */
+#define NOBOOT 0x0010 /* Execute From L1 or ASYNC Bank 0 When BMODE = 0 */
+
+
+/* ************* SYSTEM INTERRUPT CONTROLLER MASKS ***************** */
+
+/* Peripheral Masks For SIC0_ISR, SIC0_IWR, SIC0_IMASK */
+#define PLL_WAKEUP_IRQ 0x00000001 /* PLL Wakeup Interrupt Request */
+#define DMAC0_ERR_IRQ 0x00000002 /* DMA Controller 0 Error Interrupt Request */
+#define PPI_ERR_IRQ 0x00000004 /* PPI Error Interrupt Request */
+#define SPORT0_ERR_IRQ 0x00000008 /* SPORT0 Error Interrupt Request */
+#define SPORT1_ERR_IRQ 0x00000010 /* SPORT1 Error Interrupt Request */
+#define SPI0_ERR_IRQ 0x00000020 /* SPI0 Error Interrupt Request */
+#define UART0_ERR_IRQ 0x00000040 /* UART0 Error Interrupt Request */
+#define RTC_IRQ 0x00000080 /* Real-Time Clock Interrupt Request */
+#define DMA0_IRQ 0x00000100 /* DMA Channel 0 (PPI) Interrupt Request */
+#define DMA1_IRQ 0x00000200 /* DMA Channel 1 (SPORT0 RX) Interrupt Request */
+#define DMA2_IRQ 0x00000400 /* DMA Channel 2 (SPORT0 TX) Interrupt Request */
+#define DMA3_IRQ 0x00000800 /* DMA Channel 3 (SPORT1 RX) Interrupt Request */
+#define DMA4_IRQ 0x00001000 /* DMA Channel 4 (SPORT1 TX) Interrupt Request */
+#define DMA5_IRQ 0x00002000 /* DMA Channel 5 (SPI) Interrupt Request */
+#define DMA6_IRQ 0x00004000 /* DMA Channel 6 (UART RX) Interrupt Request */
+#define DMA7_IRQ 0x00008000 /* DMA Channel 7 (UART TX) Interrupt Request */
+#define TIMER0_IRQ 0x00010000 /* Timer 0 Interrupt Request */
+#define TIMER1_IRQ 0x00020000 /* Timer 1 Interrupt Request */
+#define TIMER2_IRQ 0x00040000 /* Timer 2 Interrupt Request */
+#define PFA_IRQ 0x00080000 /* Programmable Flag Interrupt Request A */
+#define PFB_IRQ 0x00100000 /* Programmable Flag Interrupt Request B */
+#define MDMA0_0_IRQ 0x00200000 /* MemDMA0 Stream 0 Interrupt Request */
+#define MDMA0_1_IRQ 0x00400000 /* MemDMA0 Stream 1 Interrupt Request */
+#define WDOG_IRQ 0x00800000 /* Software Watchdog Timer Interrupt Request */
+#define DMAC1_ERR_IRQ 0x01000000 /* DMA Controller 1 Error Interrupt Request */
+#define SPORT2_ERR_IRQ 0x02000000 /* SPORT2 Error Interrupt Request */
+#define SPORT3_ERR_IRQ 0x04000000 /* SPORT3 Error Interrupt Request */
+#define MXVR_SD_IRQ 0x08000000 /* MXVR Synchronous Data Interrupt Request */
+#define SPI1_ERR_IRQ 0x10000000 /* SPI1 Error Interrupt Request */
+#define SPI2_ERR_IRQ 0x20000000 /* SPI2 Error Interrupt Request */
+#define UART1_ERR_IRQ 0x40000000 /* UART1 Error Interrupt Request */
+#define UART2_ERR_IRQ 0x80000000 /* UART2 Error Interrupt Request */
+
+/* the following are for backwards compatibility */
+#define DMA0_ERR_IRQ DMAC0_ERR_IRQ
+#define DMA1_ERR_IRQ DMAC1_ERR_IRQ
+
+
+/* Peripheral Masks For SIC_ISR1, SIC_IWR1, SIC_IMASK1 */
+#define CAN_ERR_IRQ 0x00000001 /* CAN Error Interrupt Request */
+#define DMA8_IRQ 0x00000002 /* DMA Channel 8 (SPORT2 RX) Interrupt Request */
+#define DMA9_IRQ 0x00000004 /* DMA Channel 9 (SPORT2 TX) Interrupt Request */
+#define DMA10_IRQ 0x00000008 /* DMA Channel 10 (SPORT3 RX) Interrupt Request */
+#define DMA11_IRQ 0x00000010 /* DMA Channel 11 (SPORT3 TX) Interrupt Request */
+#define DMA12_IRQ 0x00000020 /* DMA Channel 12 Interrupt Request */
+#define DMA13_IRQ 0x00000040 /* DMA Channel 13 Interrupt Request */
+#define DMA14_IRQ 0x00000080 /* DMA Channel 14 (SPI1) Interrupt Request */
+#define DMA15_IRQ 0x00000100 /* DMA Channel 15 (SPI2) Interrupt Request */
+#define DMA16_IRQ 0x00000200 /* DMA Channel 16 (UART1 RX) Interrupt Request */
+#define DMA17_IRQ 0x00000400 /* DMA Channel 17 (UART1 TX) Interrupt Request */
+#define DMA18_IRQ 0x00000800 /* DMA Channel 18 (UART2 RX) Interrupt Request */
+#define DMA19_IRQ 0x00001000 /* DMA Channel 19 (UART2 TX) Interrupt Request */
+#define TWI0_IRQ 0x00002000 /* TWI0 Interrupt Request */
+#define TWI1_IRQ 0x00004000 /* TWI1 Interrupt Request */
+#define CAN_RX_IRQ 0x00008000 /* CAN Receive Interrupt Request */
+#define CAN_TX_IRQ 0x00010000 /* CAN Transmit Interrupt Request */
+#define MDMA1_0_IRQ 0x00020000 /* MemDMA1 Stream 0 Interrupt Request */
+#define MDMA1_1_IRQ 0x00040000 /* MemDMA1 Stream 1 Interrupt Request */
+#define MXVR_STAT_IRQ 0x00080000 /* MXVR Status Interrupt Request */
+#define MXVR_CM_IRQ 0x00100000 /* MXVR Control Message Interrupt Request */
+#define MXVR_AP_IRQ 0x00200000 /* MXVR Asynchronous Packet Interrupt */
+
+/* the following are for backwards compatibility */
+#define MDMA0_IRQ MDMA1_0_IRQ
+#define MDMA1_IRQ MDMA1_1_IRQ
+
+#ifdef _MISRA_RULES
+#define _MF15 0xFu
+#define _MF7 7u
+#else
+#define _MF15 0xF
+#define _MF7 7
+#endif /* _MISRA_RULES */
+
+/* SIC_IMASKx Masks */
+#define SIC_UNMASK_ALL 0x00000000 /* Unmask all peripheral interrupts */
+#define SIC_MASK_ALL 0xFFFFFFFF /* Mask all peripheral interrupts */
+#ifdef _MISRA_RULES
+#define SIC_MASK(x) (1 << ((x)&0x1Fu)) /* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFFu ^ (1 << ((x)&0x1Fu))) /* Unmask Peripheral #x interrupt */
+#else
+#define SIC_MASK(x) (1 << ((x)&0x1F)) /* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFF ^ (1 << ((x)&0x1F))) /* Unmask Peripheral #x interrupt */
+#endif /* _MISRA_RULES */
+
+/* SIC_IWRx Masks */
+#define IWR_DISABLE_ALL 0x00000000 /* Wakeup Disable all peripherals */
+#define IWR_ENABLE_ALL 0xFFFFFFFF /* Wakeup Enable all peripherals */
+#ifdef _MISRA_RULES
+#define IWR_ENABLE(x) (1 << ((x)&0x1Fu)) /* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFFu ^ (1 << ((x)&0x1Fu))) /* Wakeup Disable Peripheral #x */
+#else
+#define IWR_ENABLE(x) (1 << ((x)&0x1F)) /* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << ((x)&0x1F))) /* Wakeup Disable Peripheral #x */
+#endif /* _MISRA_RULES */
+
+
+/* ********* WATCHDOG TIMER MASKS ******************** */
+/* Watchdog Timer WDOG_CTL Register Masks */
+#ifdef _MISRA_RULES
+#define WDEV(x) (((x)<<1) & 0x0006u) /* event generated on roll over */
+#else
+#define WDEV(x) (((x)<<1) & 0x0006) /* event generated on roll over */
+#endif /* _MISRA_RULES */
+#define WDEV_RESET 0x0000 /* generate reset event on roll over */
+#define WDEV_NMI 0x0002 /* generate NMI event on roll over */
+#define WDEV_GPI 0x0004 /* generate GP IRQ on roll over */
+#define WDEV_NONE 0x0006 /* no event on roll over */
+#define WDEN 0x0FF0 /* enable watchdog */
+#define WDDIS 0x0AD0 /* disable watchdog */
+#define WDRO 0x8000 /* watchdog rolled over latch */
+
+/* deprecated WDOG_CTL Register Masks for legacy code */
+#define ICTL WDEV
+#define ENABLE_RESET WDEV_RESET
+#define WDOG_RESET WDEV_RESET
+#define ENABLE_NMI WDEV_NMI
+#define WDOG_NMI WDEV_NMI
+#define ENABLE_GPI WDEV_GPI
+#define WDOG_GPI WDEV_GPI
+#define DISABLE_EVT WDEV_NONE
+#define WDOG_NONE WDEV_NONE
+
+#define TMR_EN WDEN
+#define WDOG_DISABLE WDDIS
+#define TRO WDRO
+
+#define ICTL_P0 0x01
+#define ICTL_P1 0x02
+#define TRO_P 0x0F
+
+
+/* *************** REAL TIME CLOCK MASKS **************************/
+/* RTC_STAT and RTC_ALARM register */
+#define RTSEC 0x0000003F /* Real-Time Clock Seconds */
+#define RTMIN 0x00000FC0 /* Real-Time Clock Minutes */
+#define RTHR 0x0001F000 /* Real-Time Clock Hours */
+#define RTDAY 0xFFFE0000 /* Real-Time Clock Days */
+
+/* RTC_ICTL register */
+#define SWIE 0x0001 /* Stopwatch Interrupt Enable */
+#define AIE 0x0002 /* Alarm Interrupt Enable */
+#define SIE 0x0004 /* Seconds (1 Hz) Interrupt Enable */
+#define MIE 0x0008 /* Minutes Interrupt Enable */
+#define HIE 0x0010 /* Hours Interrupt Enable */
+#define DIE 0x0020 /* 24 Hours (Days) Interrupt Enable */
+#define DAIE 0x0040 /* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable */
+#define WCIE 0x8000 /* Write Complete Interrupt Enable */
+
+/* RTC_ISTAT register */
+#define SWEF 0x0001 /* Stopwatch Event Flag */
+#define AEF 0x0002 /* Alarm Event Flag */
+#define SEF 0x0004 /* Seconds (1 Hz) Event Flag */
+#define MEF 0x0008 /* Minutes Event Flag */
+#define HEF 0x0010 /* Hours Event Flag */
+#define DEF 0x0020 /* 24 Hours (Days) Event Flag */
+#define DAEF 0x0040 /* Day Alarm (Day, Hour, Minute, Second) Event Flag */
+#define WPS 0x4000 /* Write Pending Status (RO) */
+#define WCOM 0x8000 /* Write Complete */
+
+/* RTC_FAST Mask (RTC_PREN Mask) */
+#define ENABLE_PRESCALE 0x00000001 /* Enable prescaler so RTC runs at 1 Hz */
+#define PREN 0x00000001
+ /* ** Must be set after power-up for proper operation of RTC */
+
+/* Deprecated RTC_STAT and RTC_ALARM Masks */
+#define RTC_SEC RTSEC /* Real-Time Clock Seconds */
+#define RTC_MIN RTMIN /* Real-Time Clock Minutes */
+#define RTC_HR RTHR /* Real-Time Clock Hours */
+#define RTC_DAY RTDAY /* Real-Time Clock Days */
+
+/* Deprecated RTC_ICTL/RTC_ISTAT Masks */
+#define STOPWATCH SWIE /* Stopwatch Interrupt Enable */
+#define ALARM AIE /* Alarm Interrupt Enable */
+#define SECOND SIE /* Seconds (1 Hz) Interrupt Enable */
+#define MINUTE MIE /* Minutes Interrupt Enable */
+#define HOUR HIE /* Hours Interrupt Enable */
+#define DAY DIE /* 24 Hours (Days) Interrupt Enable */
+#define DAY_ALARM DAIE /* Day Alarm (Day, Hour, Minute, Second) Interrupt Enable */
+#define WRITE_COMPLETE WCIE /* Write Complete Interrupt Enable */
+
+
+/* ***************************** UART CONTROLLER MASKS ********************** */
+/* UARTx_LCR Register */
+#ifdef _MISRA_RULES
+#define WLS(x) (((x)-5u) & 0x03u) /* Word Length Select */
+#else
+#define WLS(x) (((x)-5) & 0x03) /* Word Length Select */
+#endif /* _MISRA_RULES */
+#define STB 0x04 /* Stop Bits */
+#define PEN 0x08 /* Parity Enable */
+#define EPS 0x10 /* Even Parity Select */
+#define STP 0x20 /* Stick Parity */
+#define SB 0x40 /* Set Break */
+#define DLAB 0x80 /* Divisor Latch Access */
+
+#define DLAB_P 0x07
+#define SB_P 0x06
+#define STP_P 0x05
+#define EPS_P 0x04
+#define PEN_P 0x03
+#define STB_P 0x02
+#define WLS_P1 0x01
+#define WLS_P0 0x00
+
+/* UARTx_MCR Register */
+#define LOOP_ENA 0x10 /* Loopback Mode Enable */
+#define LOOP_ENA_P 0x04
+/* Deprecated UARTx_MCR Mask */
+
+/* UARTx_LSR Register */
+#define DR 0x01 /* Data Ready */
+#define OE 0x02 /* Overrun Error */
+#define PE 0x04 /* Parity Error */
+#define FE 0x08 /* Framing Error */
+#define BI 0x10 /* Break Interrupt */
+#define THRE 0x20 /* THR Empty */
+#define TEMT 0x40 /* TSR and UART_THR Empty */
+
+#define TEMP_P 0x06
+#define THRE_P 0x05
+#define BI_P 0x04
+#define FE_P 0x03
+#define PE_P 0x02
+#define OE_P 0x01
+#define DR_P 0x00
+
+/* UARTx_IER Register */
+#define ERBFI 0x01 /* Enable Receive Buffer Full Interrupt */
+#define ETBEI 0x02 /* Enable Transmit Buffer Empty Interrupt */
+#define ELSI 0x04 /* Enable RX Status Interrupt */
+
+#define ELSI_P 0x02
+#define ETBEI_P 0x01
+#define ERBFI_P 0x00
+
+/* UARTx_IIR Register */
+#define NINT 0x01
+#define STATUS_P1 0x02
+#define STATUS_P0 0x01
+#define NINT_P 0x00
+
+/* UARTx_GCTL Register */
+#define UCEN 0x01 /* Enable UARTx Clocks */
+#define IREN 0x02 /* Enable IrDA Mode */
+#define TPOLC 0x04 /* IrDA TX Polarity Change */
+#define RPOLC 0x08 /* IrDA RX Polarity Change */
+#define FPE 0x10 /* Force Parity Error On Transmit */
+#define FFE 0x20 /* Force Framing Error On Transmit */
+
+#define FFE_P 0x05
+#define FPE_P 0x04
+#define RPOLC_P 0x03
+#define TPOLC_P 0x02
+#define IREN_P 0x01
+#define UCEN_P 0x00
+
+
+/* ********** SERIAL PORT MASKS ********************** */
+/* SPORTx_TCR1 Masks */
+#define TSPEN 0x0001 /* TX enable */
+#define ITCLK 0x0002 /* Internal TX Clock Select */
+#define TDTYPE 0x000C /* TX Data Formatting Select */
+#define DTYPE_NORM 0x0000 /* Data Format Normal */
+#define DTYPE_ULAW 0x0008 /* Compand Using u-Law */
+#define DTYPE_ALAW 0x000C /* Compand Using A-Law */
+#define TLSBIT 0x0010 /* TX Bit Order */
+#define ITFS 0x0200 /* Internal TX Frame Sync Select */
+#define TFSR 0x0400 /* TX Frame Sync Required Select */
+#define DITFS 0x0800 /* Data Independent TX Frame Sync Select */
+#define LTFS 0x1000 /* Low TX Frame Sync Select */
+#define LATFS 0x2000 /* Late TX Frame Sync Select */
+#define TCKFE 0x4000 /* TX Clock Falling Edge Select */
+/* SPORTx_RCR1 Deprecated Masks */
+#define TULAW DTYPE_ULAW /* Compand Using u-Law */
+#define TALAW DTYPE_ALAW /* Compand Using A-Law */
+
+/* SPORTx_TCR2 Masks */
+#ifdef _MISRA_RULES
+#define SLEN(x) ((x)&0x1Fu) /* SPORT TX Word Length (2 - 31) */
+#else
+#define SLEN(x) ((x)&0x1F) /* SPORT TX Word Length (2 - 31) */
+#endif /* _MISRA_RULES */
+#define TXSE 0x0100 /*TX Secondary Enable */
+#define TSFSE 0x0200 /*TX Stereo Frame Sync Enable */
+#define TRFST 0x0400 /*TX Right-First Data Order */
+
+/* SPORTx_RCR1 Masks */
+#define RSPEN 0x0001 /* RX enable */
+#define IRCLK 0x0002 /* Internal RX Clock Select */
+#define RDTYPE 0x000C /* RX Data Formatting Select */
+#define DTYPE_NORM 0x0000 /* no companding */
+#define DTYPE_ULAW 0x0008 /* Compand Using u-Law */
+#define DTYPE_ALAW 0x000C /* Compand Using A-Law */
+#define RLSBIT 0x0010 /* RX Bit Order */
+#define IRFS 0x0200 /* Internal RX Frame Sync Select */
+#define RFSR 0x0400 /* RX Frame Sync Required Select */
+#define LRFS 0x1000 /* Low RX Frame Sync Select */
+#define LARFS 0x2000 /* Late RX Frame Sync Select */
+#define RCKFE 0x4000 /* RX Clock Falling Edge Select */
+/* SPORTx_RCR1 Deprecated Masks */
+#define RULAW DTYPE_ULAW /* Compand Using u-Law */
+#define RALAW DTYPE_ALAW /* Compand Using A-Law */
+
+/* SPORTx_RCR2 Masks */
+#ifdef _MISRA_RULES
+#define SLEN(x) ((x)&0x1Fu) /* SPORT RX Word Length (2 - 31) */
+#else
+#define SLEN(x) ((x)&0x1F) /* SPORT RX Word Length (2 - 31) */
+#endif /* _MISRA_RULES */
+#define RXSE 0x0100 /*RX Secondary Enable */
+#define RSFSE 0x0200 /*RX Stereo Frame Sync Enable */
+#define RRFST 0x0400 /*Right-First Data Order */
+
+/*SPORTx_STAT Masks */
+#define RXNE 0x0001 /*RX FIFO Not Empty Status */
+#define RUVF 0x0002 /*RX Underflow Status */
+#define ROVF 0x0004 /*RX Overflow Status */
+#define TXF 0x0008 /*TX FIFO Full Status */
+#define TUVF 0x0010 /*TX Underflow Status */
+#define TOVF 0x0020 /*TX Overflow Status */
+#define TXHRE 0x0040 /*TX Hold Register Empty */
+
+/*SPORTx_MCMC1 Masks */
+#define WOFF 0x000003FF /*Multichannel Window Offset Field */
+/* SPORTx_MCMC1 Macros */
+#ifdef _MISRA_RULES
+#define SET_WOFF(x) ((x) & 0x3FFu) /* Multichannel Window Offset Field */
+/* Only use SET_WSIZE Macro With Logic OR While Setting Lower Order Bits */
+#define SET_WSIZE(x) (((((x)>>0x3)-1u)&0xFu) << 0xC) /* Multichannel Window Size = (x/8)-1 */
+#else
+#define SET_WOFF(x) ((x) & 0x3FF) /* Multichannel Window Offset Field */
+/* Only use SET_WSIZE Macro With Logic OR While Setting Lower Order Bits */
+#define SET_WSIZE(x) (((((x)>>0x3)-1)&0xF) << 0xC) /* Multichannel Window Size = (x/8)-1 */
+#endif /* _MISRA_RULES */
+
+
+/*SPORTx_MCMC2 Masks */
+#define MCCRM 0x0003 /*Multichannel Clock Recovery Mode */
+#define REC_BYPASS 0x0000 /* Bypass Mode (No Clock Recovery) */
+#define REC_2FROM4 0x0002 /* Recover 2 MHz Clock from 4 MHz Clock */
+#define REC_8FROM16 0x0003 /* Recover 8 MHz Clock from 16 MHz Clock */
+#define MCDTXPE 0x0004 /*Multichannel DMA Transmit Packing */
+#define MCDRXPE 0x0008 /*Multichannel DMA Receive Packing */
+#define MCMEN 0x0010 /*Multichannel Frame Mode Enable */
+#define FSDR 0x0080 /*Multichannel Frame Sync to Data Relationship */
+#define MFD 0xF000 /*Multichannel Frame Delay */
+#define MFD_0 0x0000 /* Multichannel Frame Delay = 0 */
+#define MFD_1 0x1000 /* Multichannel Frame Delay = 1 */
+#define MFD_2 0x2000 /* Multichannel Frame Delay = 2 */
+#define MFD_3 0x3000 /* Multichannel Frame Delay = 3 */
+#define MFD_4 0x4000 /* Multichannel Frame Delay = 4 */
+#define MFD_5 0x5000 /* Multichannel Frame Delay = 5 */
+#define MFD_6 0x6000 /* Multichannel Frame Delay = 6 */
+#define MFD_7 0x7000 /* Multichannel Frame Delay = 7 */
+#define MFD_8 0x8000 /* Multichannel Frame Delay = 8 */
+#define MFD_9 0x9000 /* Multichannel Frame Delay = 9 */
+#define MFD_10 0xA000 /* Multichannel Frame Delay = 10 */
+#define MFD_11 0xB000 /* Multichannel Frame Delay = 11 */
+#define MFD_12 0xC000 /* Multichannel Frame Delay = 12 */
+#define MFD_13 0xD000 /* Multichannel Frame Delay = 13 */
+#define MFD_14 0xE000 /* Multichannel Frame Delay = 14 */
+#define MFD_15 0xF000 /* Multichannel Frame Delay = 15 */
+
+
+/* ********* PARALLEL PERIPHERAL INTERFACE (PPI) MASKS **************** */
+/* PPI_CONTROL Masks */
+#define PORT_EN 0x0001 /* PPI Port Enable */
+#define PORT_DIR 0x0002 /* PPI Port Direction */
+#define XFR_TYPE 0x000C /* PPI Transfer Type */
+#define PORT_CFG 0x0030 /* PPI Port Configuration */
+#define FLD_SEL 0x0040 /* PPI Active Field Select */
+#define PACK_EN 0x0080 /* PPI Packing Mode */
+/* previous versions of defBF539.h erroneously included DMA32 (PPI 32-bit DMA Enable) */
+#define SKIP_EN 0x0200 /* PPI Skip Element Enable */
+#define SKIP_EO 0x0400 /* PPI Skip Even/Odd Elements */
+#define DLENGTH 0x3800 /* PPI Data Length */
+#define DLEN_8 0x0 /* PPI Data Length mask for DLEN=8 */
+#define DLEN_10 0x0800 /* Data Length = 10 Bits */
+#define DLEN_11 0x1000 /* Data Length = 11 Bits */
+#define DLEN_12 0x1800 /* Data Length = 12 Bits */
+#define DLEN_13 0x2000 /* Data Length = 13 Bits */
+#define DLEN_14 0x2800 /* Data Length = 14 Bits */
+#define DLEN_15 0x3000 /* Data Length = 15 Bits */
+#define DLEN_16 0x3800 /* Data Length = 16 Bits */
+#ifdef _MISRA_RULES
+#define DLEN(x) ((((x)-9u) & 0x07u) << 11) /* PPI Data Length (only works for x=10-->x=16) */
+#else
+#define DLEN(x) ((((x)-9) & 0x07) << 11) /* PPI Data Length (only works for x=10-->x=16) */
+#endif /* _MISRA_RULES */
+#define POL 0xC000 /* PPI Signal Polarities */
+#define POLC 0x4000 /* PPI Clock Polarity */
+#define POLS 0x8000 /* PPI Frame Sync Polarity */
+
+
+/* PPI_STATUS Masks */
+#define FLD 0x0400 /* Field Indicator */
+#define FT_ERR 0x0800 /* Frame Track Error */
+#define OVR 0x1000 /* FIFO Overflow Error */
+#define UNDR 0x2000 /* FIFO Underrun Error */
+#define ERR_DET 0x4000 /* Error Detected Indicator */
+#define ERR_NCOR 0x8000 /* Error Not Corrected Indicator */
+
+
+/* ********** DMA CONTROLLER MASKS ***********************/
+/* DMAx_CONFIG, MDMA_yy_CONFIG Masks */
+#define DMAEN 0x0001 /* Channel Enable */
+#define WNR 0x0002 /* Channel Direction (W/R*) */
+#define WDSIZE_8 0x0000 /* Word Size 8 bits */
+#define WDSIZE_16 0x0004 /* Word Size 16 bits */
+#define WDSIZE_32 0x0008 /* Word Size 32 bits */
+#define DMA2D 0x0010 /* 2D/1D* Mode */
+#define RESTART 0x0020 /* Restart */
+#define DI_SEL 0x0040 /* Data Interrupt Select */
+#define DI_EN 0x0080 /* Data Interrupt Enable */
+#define NDSIZE 0x0900 /* Next Descriptor Size */
+#define NDSIZE_0 0x0000 /* Next Descriptor Size = 0 (Stop/Autobuffer) */
+#define NDSIZE_1 0x0100 /* Next Descriptor Size = 1 */
+#define NDSIZE_2 0x0200 /* Next Descriptor Size = 2 */
+#define NDSIZE_3 0x0300 /* Next Descriptor Size = 3 */
+#define NDSIZE_4 0x0400 /* Next Descriptor Size = 4 */
+#define NDSIZE_5 0x0500 /* Next Descriptor Size = 5 */
+#define NDSIZE_6 0x0600 /* Next Descriptor Size = 6 */
+#define NDSIZE_7 0x0700 /* Next Descriptor Size = 7 */
+#define NDSIZE_8 0x0800 /* Next Descriptor Size = 8 */
+#define NDSIZE_9 0x0900 /* Next Descriptor Size = 9 */
+
+#define DMAFLOW 0x7000 /* Flow Control */
+#define DMAFLOW_STOP 0x0000 /* Stop Mode */
+#define DMAFLOW_AUTO 0x1000 /* Autobuffer Mode */
+#define DMAFLOW_ARRAY 0x4000 /* Descriptor Array Mode */
+#define DMAFLOW_SMALL 0x6000 /* Small Model Descriptor List Mode */
+#define DMAFLOW_LARGE 0x7000 /* Large Model Descriptor List Mode */
+
+#define DMAEN_P 0x0 /* Channel Enable */
+#define WNR_P 0x1 /* Channel Direction (W/R*) */
+#define DMA2D_P 0x4 /* 2D/1D* Mode */
+#define RESTART_P 0x5 /* Restart */
+#define DI_SEL_P 0x6 /* Data Interrupt Select */
+#define DI_EN_P 0x7 /* Data Interrupt Enable */
+
+/* DMAx_IRQ_STATUS, MDMA_yy_IRQ_STATUS Masks */
+#define DMA_DONE 0x0001 /* DMA Done Indicator */
+#define DMA_ERR 0x0002 /* DMA Error Indicator */
+#define DFETCH 0x0004 /* Descriptor Fetch Indicator */
+#define DMA_RUN 0x0008 /* DMA Running Indicator */
+
+#define DMA_DONE_P 0x0 /* DMA Done Indicator */
+#define DMA_ERR_P 0x1 /* DMA Error Indicator */
+#define DFETCH_P 0x2 /* Descriptor Fetch Indicator */
+#define DMA_RUN_P 0x3 /* DMA Running Indicator */
+
+/* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks */
+
+#define CTYPE 0x0040 /* DMA Channel Type Indicator */
+#define CTYPE_P 0x6 /* DMA Channel Type Indicator BIT POSITION */
+#define PCAP8 0x0080 /* DMA 8-bit Operation Indicator */
+#define PCAP16 0x0100 /* DMA 16-bit Operation Indicator */
+#define PCAP32 0x0200 /* DMA 32-bit Operation Indicator */
+#define PCAPWR 0x0400 /* DMA Write Operation Indicator */
+#define PCAPRD 0x0800 /* DMA Read Operation Indicator */
+#define PMAP 0xF000 /* DMA Peripheral Map Field */
+
+/* PMAP Encodings For DMA Controller 0 */
+#define PMAP_PPI 0x0000 /* PMAP PPI Port DMA */
+#define PMAP_SPORT0RX 0x1000 /* PMAP SPORT0 Receive DMA */
+#define PMAP_SPORT0TX 0x2000 /* PMAP SPORT0 Transmit DMA */
+#define PMAP_SPORT1RX 0x3000 /* PMAP SPORT1 Receive DMA */
+#define PMAP_SPORT1TX 0x4000 /* PMAP SPORT1 Transmit DMA */
+#define PMAP_SPI0 0x5000 /* PMAP SPI DMA */
+#define PMAP_UART0RX 0x6000 /* PMAP UART Receive DMA */
+#define PMAP_UART0TX 0x7000 /* PMAP UART Transmit DMA */
+
+/* PMAP Encodings For DMA Controller 1 */
+#define PMAP_SPORT2RX 0x0000 /* PMAP SPORT2 Receive DMA */
+#define PMAP_SPORT2TX 0x1000 /* PMAP SPORT2 Transmit DMA */
+#define PMAP_SPORT3RX 0x2000 /* PMAP SPORT3 Receive DMA */
+#define PMAP_SPORT3TX 0x3000 /* PMAP SPORT3 Transmit DMA */
+#define PMAP_SPI1 0x6000 /* PMAP SPI1 DMA */
+#define PMAP_SPI2 0x7000 /* PMAP SPI2 DMA */
+#define PMAP_UART1RX 0x8000 /* PMAP UART1 Receive DMA */
+#define PMAP_UART1TX 0x9000 /* PMAP UART1 Transmit DMA */
+#define PMAP_UART2RX 0xA000 /* PMAP UART2 Receive DMA */
+#define PMAP_UART2TX 0xB000 /* PMAP UART2 Transmit DMA */
+
+
+/* ************* GENERAL PURPOSE TIMER MASKS ******************** */
+/* PWM Timer bit definitions */
+/* TIMER_ENABLE Register */
+#define TIMEN0 0x0001 /* Enable Timer 0 */
+#define TIMEN1 0x0002 /* Enable Timer 1 */
+#define TIMEN2 0x0004 /* Enable Timer 2 */
+
+#define TIMEN0_P 0x00
+#define TIMEN1_P 0x01
+#define TIMEN2_P 0x02
+
+/* TIMER_DISABLE Register */
+#define TIMDIS0 0x0001 /* Disable Timer 0 */
+#define TIMDIS1 0x0002 /* Disable Timer 1 */
+#define TIMDIS2 0x0004 /* Disable Timer 2 */
+
+#define TIMDIS0_P 0x00
+#define TIMDIS1_P 0x01
+#define TIMDIS2_P 0x02
+
+/* TIMER_STATUS Register */
+#define TIMIL0 0x0001 /* Timer 0 Interrupt */
+#define TIMIL1 0x0002 /* Timer 1 Interrupt */
+#define TIMIL2 0x0004 /* Timer 2 Interrupt */
+#define TOVF_ERR0 0x0010 /* Timer 0 Counter Overflow */
+#define TOVF_ERR1 0x0020 /* Timer 1 Counter Overflow */
+#define TOVF_ERR2 0x0040 /* Timer 2 Counter Overflow */
+#define TRUN0 0x1000 /* Timer 0 Slave Enable Status */
+#define TRUN1 0x2000 /* Timer 1 Slave Enable Status */
+#define TRUN2 0x4000 /* Timer 2 Slave Enable Status */
+
+#define TIMIL0_P 0x00
+#define TIMIL1_P 0x01
+#define TIMIL2_P 0x02
+#define TOVF_ERR0_P 0x04
+#define TOVF_ERR1_P 0x05
+#define TOVF_ERR2_P 0x06
+#define TRUN0_P 0x0C
+#define TRUN1_P 0x0D
+#define TRUN2_P 0x0E
+
+/* Alternate Deprecated Macros Provided For Backwards Code Compatibility */
+#define TOVL_ERR0 TOVF_ERR0
+#define TOVL_ERR1 TOVF_ERR1
+#define TOVL_ERR2 TOVF_ERR2
+#define TOVL_ERR0_P TOVF_ERR0_P
+#define TOVL_ERR1_P TOVF_ERR1_P
+#define TOVL_ERR2_P TOVF_ERR2_P
+
+/* TIMERx_CONFIG Registers */
+#define PWM_OUT 0x0001
+#define WDTH_CAP 0x0002
+#define EXT_CLK 0x0003
+#define PULSE_HI 0x0004
+#define PERIOD_CNT 0x0008
+#define IRQ_ENA 0x0010
+#define TIN_SEL 0x0020
+#define OUT_DIS 0x0040
+#define CLK_SEL 0x0080
+#define TOGGLE_HI 0x0100
+#define EMU_RUN 0x0200
+#ifdef _MISRA_RULES
+#define ERR_TYP(x) (((x) & 0x03u) << 14)
+#else
+#define ERR_TYP(x) (((x) & 0x03) << 14)
+#endif /* _MISRA_RULES */
+
+#define TMODE_P0 0x00
+#define TMODE_P1 0x01
+#define PULSE_HI_P 0x02
+#define PERIOD_CNT_P 0x03
+#define IRQ_ENA_P 0x04
+#define TIN_SEL_P 0x05
+#define OUT_DIS_P 0x06
+#define CLK_SEL_P 0x07
+#define TOGGLE_HI_P 0x08
+#define EMU_RUN_P 0x09
+#define ERR_TYP_P0 0x0E
+#define ERR_TYP_P1 0x0F
+
+
+/*/ ****************** GENERAL-PURPOSE I/O ********************* */
+/* Flag I/O (FIO_) Masks */
+#define PF0 0x0001
+#define PF1 0x0002
+#define PF2 0x0004
+#define PF3 0x0008
+#define PF4 0x0010
+#define PF5 0x0020
+#define PF6 0x0040
+#define PF7 0x0080
+#define PF8 0x0100
+#define PF9 0x0200
+#define PF10 0x0400
+#define PF11 0x0800
+#define PF12 0x1000
+#define PF13 0x2000
+#define PF14 0x4000
+#define PF15 0x8000
+
+/* PORT F BIT POSITIONS */
+#define PF0_P 0x0
+#define PF1_P 0x1
+#define PF2_P 0x2
+#define PF3_P 0x3
+#define PF4_P 0x4
+#define PF5_P 0x5
+#define PF6_P 0x6
+#define PF7_P 0x7
+#define PF8_P 0x8
+#define PF9_P 0x9
+#define PF10_P 0xA
+#define PF11_P 0xB
+#define PF12_P 0xC
+#define PF13_P 0xD
+#define PF14_P 0xE
+#define PF15_P 0xF
+
+
+/******************* GPIO MASKS *********************/
+/* Port C Masks */
+#define PC0 0x0001
+#define PC1 0x0002
+#define PC4 0x0010
+#define PC5 0x0020
+#define PC6 0x0040
+#define PC7 0x0080
+#define PC8 0x0100
+#define PC9 0x0200
+/* Port C Bit Positions */
+#define PC0_P 0x0
+#define PC1_P 0x1
+#define PC4_P 0x4
+#define PC5_P 0x5
+#define PC6_P 0x6
+#define PC7_P 0x7
+#define PC8_P 0x8
+#define PC9_P 0x9
+
+/* Port D */
+#define PD0 0x0001
+#define PD1 0x0002
+#define PD2 0x0004
+#define PD3 0x0008
+#define PD4 0x0010
+#define PD5 0x0020
+#define PD6 0x0040
+#define PD7 0x0080
+#define PD8 0x0100
+#define PD9 0x0200
+#define PD10 0x0400
+#define PD11 0x0800
+#define PD12 0x1000
+#define PD13 0x2000
+#define PD14 0x4000
+#define PD15 0x8000
+/* Port D Bit Positions */
+#define PD0_P 0x0
+#define PD1_P 0x1
+#define PD2_P 0x2
+#define PD3_P 0x3
+#define PD4_P 0x4
+#define PD5_P 0x5
+#define PD6_P 0x6
+#define PD7_P 0x7
+#define PD8_P 0x8
+#define PD9_P 0x9
+#define PD10_P 0xA
+#define PD11_P 0xB
+#define PD12_P 0xC
+#define PD13_P 0xD
+#define PD14_P 0xE
+#define PD15_P 0xF
+
+/* Port E */
+#define PE0 0x0001
+#define PE1 0x0002
+#define PE2 0x0004
+#define PE3 0x0008
+#define PE4 0x0010
+#define PE5 0x0020
+#define PE6 0x0040
+#define PE7 0x0080
+#define PE8 0x0100
+#define PE9 0x0200
+#define PE10 0x0400
+#define PE11 0x0800
+#define PE12 0x1000
+#define PE13 0x2000
+#define PE14 0x4000
+#define PE15 0x8000
+/* Port E Bit Positions */
+#define PE0_P 0x0
+#define PE1_P 0x1
+#define PE2_P 0x2
+#define PE3_P 0x3
+#define PE4_P 0x4
+#define PE5_P 0x5
+#define PE6_P 0x6
+#define PE7_P 0x7
+#define PE8_P 0x8
+#define PE9_P 0x9
+#define PE10_P 0xA
+#define PE11_P 0xB
+#define PE12_P 0xC
+#define PE13_P 0xD
+#define PE14_P 0xE
+#define PE15_P 0xF
+
+
+/* *********** SERIAL PERIPHERAL INTERFACE (SPI) MASKS **************** */
+/* SPIx_CTL Masks */
+#define TIMOD 0x0003 /* Transfer Initiate Mode */
+#define RDBR_CORE 0x0000 /* RDBR Read Initiates, IRQ When RDBR Full */
+#define TDBR_CORE 0x0001 /* TDBR Write Initiates, IRQ When TDBR Empty */
+#define RDBR_DMA 0x0002 /* DMA Read, DMA Until FIFO Empty */
+#define TDBR_DMA 0x0003 /* DMA Write, DMA Until FIFO Full */
+#define SZ 0x0004 /* Send Zero (When TDBR Empty, Send Zero/Last*) */
+#define GM 0x0008 /* Get More (When RDBR Full, Overwrite/Discard*) */
+#define PSSE 0x0010 /* Slave-Select Input Enable */
+#define EMISO 0x0020 /* Enable MISO As Output */
+#define SIZE 0x0100 /* Size of Words (16/8* Bits) */
+#define LSBF 0x0200 /* LSB First */
+#define CPHA 0x0400 /* Clock Phase */
+#define CPOL 0x0800 /* Clock Polarity */
+#define MSTR 0x1000 /* Master/Slave* */
+#define WOM 0x2000 /* Write Open Drain Master */
+#define SPE 0x4000 /* SPI Enable */
+
+/* SPIx_FLG Masks */
+#define FLS1 0x0002 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLS2 0x0004 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLS3 0x0008 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLS4 0x0010 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLS5 0x0020 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLS6 0x0040 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLS7 0x0080 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
+
+#define FLG1 0x0200 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLG2 0x0400 /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLG3 0x0800 /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLG4 0x1000 /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLG5 0x2000 /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLG6 0x4000 /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLG7 0x8000 /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
+
+/* SPIx_FLG Bit Positions */
+#define FLS1_P 0x0001 /* Enables (=1) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLS2_P 0x0002 /* Enables (=1) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLS3_P 0x0003 /* Enables (=1) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLS4_P 0x0004 /* Enables (=1) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLS5_P 0x0005 /* Enables (=1) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLS6_P 0x0006 /* Enables (=1) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLS7_P 0x0007 /* Enables (=1) SPI_FLOUT7 as flag output for SPI Slave-select */
+#define FLG1_P 0x0009 /* Activates (=0) SPI_FLOUT1 as flag output for SPI Slave-select */
+#define FLG2_P 0x000A /* Activates (=0) SPI_FLOUT2 as flag output for SPI Slave-select */
+#define FLG3_P 0x000B /* Activates (=0) SPI_FLOUT3 as flag output for SPI Slave-select */
+#define FLG4_P 0x000C /* Activates (=0) SPI_FLOUT4 as flag output for SPI Slave-select */
+#define FLG5_P 0x000D /* Activates (=0) SPI_FLOUT5 as flag output for SPI Slave-select */
+#define FLG6_P 0x000E /* Activates (=0) SPI_FLOUT6 as flag output for SPI Slave-select */
+#define FLG7_P 0x000F /* Activates (=0) SPI_FLOUT7 as flag output for SPI Slave-select */
+
+/* SPIx_STAT Masks */
+#define SPIF 0x0001 /* Set (=1) when SPI single-word transfer complete */
+#define MODF 0x0002 /* Set (=1) in a master device when some other device tries to become master */
+#define TXE 0x0004 /* Set (=1) when transmission occurs with no new data in SPI_TDBR */
+#define TXS 0x0008 /* SPI_TDBR Data Buffer Status (0=Empty, 1=Full) */
+#define RBSY 0x0010 /* Set (=1) when data is received with RDBR full */
+#define RXS 0x0020 /* SPI_RDBR Data Buffer Status (0=Empty, 1=Full) */
+#define TXCOL 0x0040 /* When set (=1), corrupt data may have been transmitted */
+
+/* SPIx_FLG Masks */
+#define FLG1E 0xFDFF /* Activates SPI_FLOUT1 */
+#define FLG2E 0xFBFF /* Activates SPI_FLOUT2 */
+#define FLG3E 0xF7FF /* Activates SPI_FLOUT3 */
+#define FLG4E 0xEFFF /* Activates SPI_FLOUT4 */
+#define FLG5E 0xDFFF /* Activates SPI_FLOUT5 */
+#define FLG6E 0xBFFF /* Activates SPI_FLOUT6 */
+#define FLG7E 0x7FFF /* Activates SPI_FLOUT7 */
+
+
+/* ********************* ASYNCHRONOUS MEMORY CONTROLLER MASKS ************* */
+/* EBIU_AMGCTL Masks */
+#define AMCKEN 0x0001 /* Enable CLKOUT */
+#define AMBEN_NONE 0x0000 /* All Banks Disabled */
+#define AMBEN_B0 0x0002 /* Enable Asynchronous Memory Bank 0 only */
+#define AMBEN_B0_B1 0x0004 /* Enable Asynchronous Memory Banks 0 & 1 only */
+#define AMBEN_B0_B1_B2 0x0006 /* Enable Asynchronous Memory Banks 0, 1, and 2 */
+#define AMBEN_ALL 0x0008 /* Enable Asynchronous Memory Banks (all) 0, 1, 2, and 3 */
+#define CDPRIO 0x0100 /* DMA has priority over core for for external accesses */
+
+/* EBIU_AMGCTL Bit Positions */
+#define AMCKEN_P 0x0000 /* Enable CLKOUT */
+#define AMBEN_P0 0x0001 /* Asynchronous Memory Enable, 000 - banks 0-3 disabled, 001 - Bank 0 enabled */
+#define AMBEN_P1 0x0002 /* Asynchronous Memory Enable, 010 - banks 0&1 enabled, 011 - banks 0-3 enabled */
+#define AMBEN_P2 0x0003 /* Asynchronous Memory Enable, 1xx - All banks (bank 0, 1, 2, and 3) enabled */
+
+/* EBIU_AMBCTL0 Masks */
+#define B0RDYEN 0x00000001 /* Bank 0 RDY Enable, 0=disable, 1=enable */
+#define B0RDYPOL 0x00000002 /* Bank 0 RDY Active high, 0=active low, 1=active high */
+#define B0TT_1 0x00000004 /* Bank 0 Transition Time from Read to Write = 1 cycle */
+#define B0TT_2 0x00000008 /* Bank 0 Transition Time from Read to Write = 2 cycles */
+#define B0TT_3 0x0000000C /* Bank 0 Transition Time from Read to Write = 3 cycles */
+#define B0TT_4 0x00000000 /* Bank 0 Transition Time from Read to Write = 4 cycles */
+#define B0ST_1 0x00000010 /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=1 cycle */
+#define B0ST_2 0x00000020 /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=2 cycles */
+#define B0ST_3 0x00000030 /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=3 cycles */
+#define B0ST_4 0x00000000 /* Bank 0 Setup Time from AOE asserted to Read/Write asserted=4 cycles */
+#define B0HT_1 0x00000040 /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 1 cycle */
+#define B0HT_2 0x00000080 /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 2 cycles */
+#define B0HT_3 0x000000C0 /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 3 cycles */
+#define B0HT_0 0x00000000 /* Bank 0 Hold Time from Read/Write deasserted to AOE deasserted = 0 cycles */
+#define B0RAT_1 0x00000100 /* Bank 0 Read Access Time = 1 cycle */
+#define B0RAT_2 0x00000200 /* Bank 0 Read Access Time = 2 cycles */
+#define B0RAT_3 0x00000300 /* Bank 0 Read Access Time = 3 cycles */
+#define B0RAT_4 0x00000400 /* Bank 0 Read Access Time = 4 cycles */
+#define B0RAT_5 0x00000500 /* Bank 0 Read Access Time = 5 cycles */
+#define B0RAT_6 0x00000600 /* Bank 0 Read Access Time = 6 cycles */
+#define B0RAT_7 0x00000700 /* Bank 0 Read Access Time = 7 cycles */
+#define B0RAT_8 0x00000800 /* Bank 0 Read Access Time = 8 cycles */
+#define B0RAT_9 0x00000900 /* Bank 0 Read Access Time = 9 cycles */
+#define B0RAT_10 0x00000A00 /* Bank 0 Read Access Time = 10 cycles */
+#define B0RAT_11 0x00000B00 /* Bank 0 Read Access Time = 11 cycles */
+#define B0RAT_12 0x00000C00 /* Bank 0 Read Access Time = 12 cycles */
+#define B0RAT_13 0x00000D00 /* Bank 0 Read Access Time = 13 cycles */
+#define B0RAT_14 0x00000E00 /* Bank 0 Read Access Time = 14 cycles */
+#define B0RAT_15 0x00000F00 /* Bank 0 Read Access Time = 15 cycles */
+#define B0WAT_1 0x00001000 /* Bank 0 Write Access Time = 1 cycle */
+#define B0WAT_2 0x00002000 /* Bank 0 Write Access Time = 2 cycles */
+#define B0WAT_3 0x00003000 /* Bank 0 Write Access Time = 3 cycles */
+#define B0WAT_4 0x00004000 /* Bank 0 Write Access Time = 4 cycles */
+#define B0WAT_5 0x00005000 /* Bank 0 Write Access Time = 5 cycles */
+#define B0WAT_6 0x00006000 /* Bank 0 Write Access Time = 6 cycles */
+#define B0WAT_7 0x00007000 /* Bank 0 Write Access Time = 7 cycles */
+#define B0WAT_8 0x00008000 /* Bank 0 Write Access Time = 8 cycles */
+#define B0WAT_9 0x00009000 /* Bank 0 Write Access Time = 9 cycles */
+#define B0WAT_10 0x0000A000 /* Bank 0 Write Access Time = 10 cycles */
+#define B0WAT_11 0x0000B000 /* Bank 0 Write Access Time = 11 cycles */
+#define B0WAT_12 0x0000C000 /* Bank 0 Write Access Time = 12 cycles */
+#define B0WAT_13 0x0000D000 /* Bank 0 Write Access Time = 13 cycles */
+#define B0WAT_14 0x0000E000 /* Bank 0 Write Access Time = 14 cycles */
+#define B0WAT_15 0x0000F000 /* Bank 0 Write Access Time = 15 cycles */
+#define B1RDYEN 0x00010000 /* Bank 1 RDY enable, 0=disable, 1=enable */
+#define B1RDYPOL 0x00020000 /* Bank 1 RDY Active high, 0=active low, 1=active high */
+#define B1TT_1 0x00040000 /* Bank 1 Transition Time from Read to Write = 1 cycle */
+#define B1TT_2 0x00080000 /* Bank 1 Transition Time from Read to Write = 2 cycles */
+#define B1TT_3 0x000C0000 /* Bank 1 Transition Time from Read to Write = 3 cycles */
+#define B1TT_4 0x00000000 /* Bank 1 Transition Time from Read to Write = 4 cycles */
+#define B1ST_1 0x00100000 /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B1ST_2 0x00200000 /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B1ST_3 0x00300000 /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B1ST_4 0x00000000 /* Bank 1 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B1HT_1 0x00400000 /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B1HT_2 0x00800000 /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B1HT_3 0x00C00000 /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B1HT_0 0x00000000 /* Bank 1 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B1RAT_1 0x01000000 /* Bank 1 Read Access Time = 1 cycle */
+#define B1RAT_2 0x02000000 /* Bank 1 Read Access Time = 2 cycles */
+#define B1RAT_3 0x03000000 /* Bank 1 Read Access Time = 3 cycles */
+#define B1RAT_4 0x04000000 /* Bank 1 Read Access Time = 4 cycles */
+#define B1RAT_5 0x05000000 /* Bank 1 Read Access Time = 5 cycles */
+#define B1RAT_6 0x06000000 /* Bank 1 Read Access Time = 6 cycles */
+#define B1RAT_7 0x07000000 /* Bank 1 Read Access Time = 7 cycles */
+#define B1RAT_8 0x08000000 /* Bank 1 Read Access Time = 8 cycles */
+#define B1RAT_9 0x09000000 /* Bank 1 Read Access Time = 9 cycles */
+#define B1RAT_10 0x0A000000 /* Bank 1 Read Access Time = 10 cycles */
+#define B1RAT_11 0x0B000000 /* Bank 1 Read Access Time = 11 cycles */
+#define B1RAT_12 0x0C000000 /* Bank 1 Read Access Time = 12 cycles */
+#define B1RAT_13 0x0D000000 /* Bank 1 Read Access Time = 13 cycles */
+#define B1RAT_14 0x0E000000 /* Bank 1 Read Access Time = 14 cycles */
+#define B1RAT_15 0x0F000000 /* Bank 1 Read Access Time = 15 cycles */
+#define B1WAT_1 0x10000000 /* Bank 1 Write Access Time = 1 cycle */
+#define B1WAT_2 0x20000000 /* Bank 1 Write Access Time = 2 cycles */
+#define B1WAT_3 0x30000000 /* Bank 1 Write Access Time = 3 cycles */
+#define B1WAT_4 0x40000000 /* Bank 1 Write Access Time = 4 cycles */
+#define B1WAT_5 0x50000000 /* Bank 1 Write Access Time = 5 cycles */
+#define B1WAT_6 0x60000000 /* Bank 1 Write Access Time = 6 cycles */
+#define B1WAT_7 0x70000000 /* Bank 1 Write Access Time = 7 cycles */
+#define B1WAT_8 0x80000000 /* Bank 1 Write Access Time = 8 cycles */
+#define B1WAT_9 0x90000000 /* Bank 1 Write Access Time = 9 cycles */
+#define B1WAT_10 0xA0000000 /* Bank 1 Write Access Time = 10 cycles */
+#define B1WAT_11 0xB0000000 /* Bank 1 Write Access Time = 11 cycles */
+#define B1WAT_12 0xC0000000 /* Bank 1 Write Access Time = 12 cycles */
+#define B1WAT_13 0xD0000000 /* Bank 1 Write Access Time = 13 cycles */
+#define B1WAT_14 0xE0000000 /* Bank 1 Write Access Time = 14 cycles */
+#define B1WAT_15 0xF0000000 /* Bank 1 Write Access Time = 15 cycles */
+
+/* EBIU_AMBCTL1 Masks */
+#define B2RDYEN 0x00000001 /* Bank 2 RDY Enable, 0=disable, 1=enable */
+#define B2RDYPOL 0x00000002 /* Bank 2 RDY Active high, 0=active low, 1=active high */
+#define B2TT_1 0x00000004 /* Bank 2 Transition Time from Read to Write = 1 cycle */
+#define B2TT_2 0x00000008 /* Bank 2 Transition Time from Read to Write = 2 cycles */
+#define B2TT_3 0x0000000C /* Bank 2 Transition Time from Read to Write = 3 cycles */
+#define B2TT_4 0x00000000 /* Bank 2 Transition Time from Read to Write = 4 cycles */
+#define B2ST_1 0x00000010 /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B2ST_2 0x00000020 /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B2ST_3 0x00000030 /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B2ST_4 0x00000000 /* Bank 2 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B2HT_1 0x00000040 /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B2HT_2 0x00000080 /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B2HT_3 0x000000C0 /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B2HT_0 0x00000000 /* Bank 2 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B2RAT_1 0x00000100 /* Bank 2 Read Access Time = 1 cycle */
+#define B2RAT_2 0x00000200 /* Bank 2 Read Access Time = 2 cycles */
+#define B2RAT_3 0x00000300 /* Bank 2 Read Access Time = 3 cycles */
+#define B2RAT_4 0x00000400 /* Bank 2 Read Access Time = 4 cycles */
+#define B2RAT_5 0x00000500 /* Bank 2 Read Access Time = 5 cycles */
+#define B2RAT_6 0x00000600 /* Bank 2 Read Access Time = 6 cycles */
+#define B2RAT_7 0x00000700 /* Bank 2 Read Access Time = 7 cycles */
+#define B2RAT_8 0x00000800 /* Bank 2 Read Access Time = 8 cycles */
+#define B2RAT_9 0x00000900 /* Bank 2 Read Access Time = 9 cycles */
+#define B2RAT_10 0x00000A00 /* Bank 2 Read Access Time = 10 cycles */
+#define B2RAT_11 0x00000B00 /* Bank 2 Read Access Time = 11 cycles */
+#define B2RAT_12 0x00000C00 /* Bank 2 Read Access Time = 12 cycles */
+#define B2RAT_13 0x00000D00 /* Bank 2 Read Access Time = 13 cycles */
+#define B2RAT_14 0x00000E00 /* Bank 2 Read Access Time = 14 cycles */
+#define B2RAT_15 0x00000F00 /* Bank 2 Read Access Time = 15 cycles */
+#define B2WAT_1 0x00001000 /* Bank 2 Write Access Time = 1 cycle */
+#define B2WAT_2 0x00002000 /* Bank 2 Write Access Time = 2 cycles */
+#define B2WAT_3 0x00003000 /* Bank 2 Write Access Time = 3 cycles */
+#define B2WAT_4 0x00004000 /* Bank 2 Write Access Time = 4 cycles */
+#define B2WAT_5 0x00005000 /* Bank 2 Write Access Time = 5 cycles */
+#define B2WAT_6 0x00006000 /* Bank 2 Write Access Time = 6 cycles */
+#define B2WAT_7 0x00007000 /* Bank 2 Write Access Time = 7 cycles */
+#define B2WAT_8 0x00008000 /* Bank 2 Write Access Time = 8 cycles */
+#define B2WAT_9 0x00009000 /* Bank 2 Write Access Time = 9 cycles */
+#define B2WAT_10 0x0000A000 /* Bank 2 Write Access Time = 10 cycles */
+#define B2WAT_11 0x0000B000 /* Bank 2 Write Access Time = 11 cycles */
+#define B2WAT_12 0x0000C000 /* Bank 2 Write Access Time = 12 cycles */
+#define B2WAT_13 0x0000D000 /* Bank 2 Write Access Time = 13 cycles */
+#define B2WAT_14 0x0000E000 /* Bank 2 Write Access Time = 14 cycles */
+#define B2WAT_15 0x0000F000 /* Bank 2 Write Access Time = 15 cycles */
+#define B3RDYEN 0x00010000 /* Bank 3 RDY enable, 0=disable, 1=enable */
+#define B3RDYPOL 0x00020000 /* Bank 3 RDY Active high, 0=active low, 1=active high */
+#define B3TT_1 0x00040000 /* Bank 3 Transition Time from Read to Write = 1 cycle */
+#define B3TT_2 0x00080000 /* Bank 3 Transition Time from Read to Write = 2 cycles */
+#define B3TT_3 0x000C0000 /* Bank 3 Transition Time from Read to Write = 3 cycles */
+#define B3TT_4 0x00000000 /* Bank 3 Transition Time from Read to Write = 4 cycles */
+#define B3ST_1 0x00100000 /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 1 cycle */
+#define B3ST_2 0x00200000 /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 2 cycles */
+#define B3ST_3 0x00300000 /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 3 cycles */
+#define B3ST_4 0x00000000 /* Bank 3 Setup Time from AOE asserted to Read or Write asserted = 4 cycles */
+#define B3HT_1 0x00400000 /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 1 cycle */
+#define B3HT_2 0x00800000 /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 2 cycles */
+#define B3HT_3 0x00C00000 /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 3 cycles */
+#define B3HT_0 0x00000000 /* Bank 3 Hold Time from Read or Write deasserted to AOE deasserted = 0 cycles */
+#define B3RAT_1 0x01000000 /* Bank 3 Read Access Time = 1 cycle */
+#define B3RAT_2 0x02000000 /* Bank 3 Read Access Time = 2 cycles */
+#define B3RAT_3 0x03000000 /* Bank 3 Read Access Time = 3 cycles */
+#define B3RAT_4 0x04000000 /* Bank 3 Read Access Time = 4 cycles */
+#define B3RAT_5 0x05000000 /* Bank 3 Read Access Time = 5 cycles */
+#define B3RAT_6 0x06000000 /* Bank 3 Read Access Time = 6 cycles */
+#define B3RAT_7 0x07000000 /* Bank 3 Read Access Time = 7 cycles */
+#define B3RAT_8 0x08000000 /* Bank 3 Read Access Time = 8 cycles */
+#define B3RAT_9 0x09000000 /* Bank 3 Read Access Time = 9 cycles */
+#define B3RAT_10 0x0A000000 /* Bank 3 Read Access Time = 10 cycles */
+#define B3RAT_11 0x0B000000 /* Bank 3 Read Access Time = 11 cycles */
+#define B3RAT_12 0x0C000000 /* Bank 3 Read Access Time = 12 cycles */
+#define B3RAT_13 0x0D000000 /* Bank 3 Read Access Time = 13 cycles */
+#define B3RAT_14 0x0E000000 /* Bank 3 Read Access Time = 14 cycles */
+#define B3RAT_15 0x0F000000 /* Bank 3 Read Access Time = 15 cycles */
+#define B3WAT_1 0x10000000 /* Bank 3 Write Access Time = 1 cycle */
+#define B3WAT_2 0x20000000 /* Bank 3 Write Access Time = 2 cycles */
+#define B3WAT_3 0x30000000 /* Bank 3 Write Access Time = 3 cycles */
+#define B3WAT_4 0x40000000 /* Bank 3 Write Access Time = 4 cycles */
+#define B3WAT_5 0x50000000 /* Bank 3 Write Access Time = 5 cycles */
+#define B3WAT_6 0x60000000 /* Bank 3 Write Access Time = 6 cycles */
+#define B3WAT_7 0x70000000 /* Bank 3 Write Access Time = 7 cycles */
+#define B3WAT_8 0x80000000 /* Bank 3 Write Access Time = 8 cycles */
+#define B3WAT_9 0x90000000 /* Bank 3 Write Access Time = 9 cycles */
+#define B3WAT_10 0xA0000000 /* Bank 3 Write Access Time = 10 cycles */
+#define B3WAT_11 0xB0000000 /* Bank 3 Write Access Time = 11 cycles */
+#define B3WAT_12 0xC0000000 /* Bank 3 Write Access Time = 12 cycles */
+#define B3WAT_13 0xD0000000 /* Bank 3 Write Access Time = 13 cycles */
+#define B3WAT_14 0xE0000000 /* Bank 3 Write Access Time = 14 cycles */
+#define B3WAT_15 0xF0000000 /* Bank 3 Write Access Time = 15 cycles */
+
+/* ********************** SDRAM CONTROLLER MASKS *************************** */
+/* EBIU_SDGCTL Masks */
+#define SCTLE 0x00000001 /* Enable SCLK[0], /SRAS, /SCAS, /SWE, SDQM[3:0] */
+#define CL_2 0x00000008 /* SDRAM CAS latency = 2 cycles */
+#define CL_3 0x0000000C /* SDRAM CAS latency = 3 cycles */
+#define PFE 0x00000010 /* Enable SDRAM prefetch */
+#define PFP 0x00000020 /* Prefetch has priority over AMC requests */
+#define PASR_ALL 0x00000000 /* All 4 SDRAM Banks Refreshed In Self-Refresh */
+#define PASR_B0_B1 0x00000010 /* SDRAM Banks 0 and 1 Are Refreshed In Self-Refresh */
+#define PASR_B0 0x00000020 /* Only SDRAM Bank 0 Is Refreshed In Self-Refresh */
+#define TRAS_1 0x00000040 /* SDRAM tRAS = 1 cycle */
+#define TRAS_2 0x00000080 /* SDRAM tRAS = 2 cycles */
+#define TRAS_3 0x000000C0 /* SDRAM tRAS = 3 cycles */
+#define TRAS_4 0x00000100 /* SDRAM tRAS = 4 cycles */
+#define TRAS_5 0x00000140 /* SDRAM tRAS = 5 cycles */
+#define TRAS_6 0x00000180 /* SDRAM tRAS = 6 cycles */
+#define TRAS_7 0x000001C0 /* SDRAM tRAS = 7 cycles */
+#define TRAS_8 0x00000200 /* SDRAM tRAS = 8 cycles */
+#define TRAS_9 0x00000240 /* SDRAM tRAS = 9 cycles */
+#define TRAS_10 0x00000280 /* SDRAM tRAS = 10 cycles */
+#define TRAS_11 0x000002C0 /* SDRAM tRAS = 11 cycles */
+#define TRAS_12 0x00000300 /* SDRAM tRAS = 12 cycles */
+#define TRAS_13 0x00000340 /* SDRAM tRAS = 13 cycles */
+#define TRAS_14 0x00000380 /* SDRAM tRAS = 14 cycles */
+#define TRAS_15 0x000003C0 /* SDRAM tRAS = 15 cycles */
+#define TRP_1 0x00000800 /* SDRAM tRP = 1 cycle */
+#define TRP_2 0x00001000 /* SDRAM tRP = 2 cycles */
+#define TRP_3 0x00001800 /* SDRAM tRP = 3 cycles */
+#define TRP_4 0x00002000 /* SDRAM tRP = 4 cycles */
+#define TRP_5 0x00002800 /* SDRAM tRP = 5 cycles */
+#define TRP_6 0x00003000 /* SDRAM tRP = 6 cycles */
+#define TRP_7 0x00003800 /* SDRAM tRP = 7 cycles */
+#define TRCD_1 0x00008000 /* SDRAM tRCD = 1 cycle */
+#define TRCD_2 0x00010000 /* SDRAM tRCD = 2 cycles */
+#define TRCD_3 0x00018000 /* SDRAM tRCD = 3 cycles */
+#define TRCD_4 0x00020000 /* SDRAM tRCD = 4 cycles */
+#define TRCD_5 0x00028000 /* SDRAM tRCD = 5 cycles */
+#define TRCD_6 0x00030000 /* SDRAM tRCD = 6 cycles */
+#define TRCD_7 0x00038000 /* SDRAM tRCD = 7 cycles */
+#define TWR_1 0x00080000 /* SDRAM tWR = 1 cycle */
+#define TWR_2 0x00100000 /* SDRAM tWR = 2 cycles */
+#define TWR_3 0x00180000 /* SDRAM tWR = 3 cycles */
+#define PUPSD 0x00200000 /*Power-up start delay */
+#define PSM 0x00400000 /* SDRAM power-up sequence = Precharge, mode register set, 8 CBR refresh cycles */
+#define PSS 0x00800000 /* enable SDRAM power-up sequence on next SDRAM access */
+#define SRFS 0x01000000 /* Start SDRAM self-refresh mode */
+#define EBUFE 0x02000000 /* Enable external buffering timing */
+#define FBBRW 0x04000000 /* Fast back-to-back read write enable */
+#define EMREN 0x10000000 /* Extended mode register enable */
+#define TCSR 0x20000000 /* Temp compensated self refresh value 85 deg C */
+#define CDDBG 0x40000000 /* Tristate SDRAM controls during bus grant */
+
+/* EBIU_SDBCTL Masks */
+#define EBE 0x00000001 /* Enable SDRAM external bank */
+#define EBSZ_16 0x00000000 /* SDRAM external bank size = 16MB */
+#define EBSZ_32 0x00000002 /* SDRAM external bank size = 32MB */
+#define EBSZ_64 0x00000004 /* SDRAM external bank size = 64MB */
+#define EBSZ_128 0x00000006 /* SDRAM external bank size = 128MB */
+#define EBSZ_256 0x00000008 /* SDRAM External Bank Size = 256MB */
+#define EBSZ_512 0x0000000A /* SDRAM External Bank Size = 512MB */
+#define EBCAW_8 0x00000000 /* SDRAM external bank column address width = 8 bits */
+#define EBCAW_9 0x00000010 /* SDRAM external bank column address width = 9 bits */
+#define EBCAW_10 0x00000020 /* SDRAM external bank column address width = 9 bits */
+#define EBCAW_11 0x00000030 /* SDRAM external bank column address width = 9 bits */
+
+/* EBIU_SDSTAT Masks */
+#define SDCI 0x00000001 /* SDRAM controller is idle */
+#define SDSRA 0x00000002 /* SDRAM SDRAM self refresh is active */
+#define SDPUA 0x00000004 /* SDRAM power up active */
+#define SDRS 0x00000008 /* SDRAM is in reset state */
+#define SDEASE 0x00000010 /* SDRAM EAB sticky error status - W1C */
+#define BGSTAT 0x00000020 /* Bus granted */
+
+
+/* ******************** TWO-WIRE INTERFACE (TWIx) MASKS ***********************/
+/* TWIx_CLKDIV Macros (Use: *pTWIx_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
+#ifdef _MISRA_RULES
+#define CLKLOW(x) ((x) & 0xFFu) /* Periods Clock Is Held Low */
+#define CLKHI(y) (((y)&0xFFu)<<0x8) /* Periods Before New Clock Low */
+#else
+#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
+#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
+#endif /* _MISRA_RULES */
+
+/* TWIx_PRESCALE Masks */
+#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
+#define TWI_ENA 0x0080 /* TWI Enable */
+#define SCCB 0x0200 /* SCCB Compatibility Enable */
+
+/* TWIx_SLAVE_CTRL Masks */
+#define SEN 0x0001 /* Slave Enable */
+#define SADD_LEN 0x0002 /* Slave Address Length */
+#define STDVAL 0x0004 /* Slave Transmit Data Valid */
+#define NAK 0x0008 /* NAK/ACK* Generated At Conclusion Of Transfer */
+#define GEN 0x0010 /* General Call Adrress Matching Enabled */
+
+/* TWIx_SLAVE_STAT Masks */
+#define SDIR 0x0001 /* Slave Transfer Direction (Transmit/Receive*) */
+#define GCALL 0x0002 /* General Call Indicator */
+
+/* TWIx_MASTER_CTRL Masks */
+#define MEN 0x0001 /* Master Mode Enable */
+#define MADD_LEN 0x0002 /* Master Address Length */
+#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
+#define FAST 0x0008 /* Use Fast Mode Timing Specs */
+#define STOP 0x0010 /* Issue Stop Condition */
+#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
+#define DCNT 0x3FC0 /* Data Bytes To Transfer */
+#define SDAOVR 0x4000 /* Serial Data Override */
+#define SCLOVR 0x8000 /* Serial Clock Override */
+
+/* TWIx_MASTER_STAT Masks */
+#define MPROG 0x0001 /* Master Transfer In Progress */
+#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
+#define ANAK 0x0004 /* Address Not Acknowledged */
+#define DNAK 0x0008 /* Data Not Acknowledged */
+#define BUFRDERR 0x0010 /* Buffer Read Error */
+#define BUFWRERR 0x0020 /* Buffer Write Error */
+#define SDASEN 0x0040 /* Serial Data Sense */
+#define SCLSEN 0x0080 /* Serial Clock Sense */
+#define BUSBUSY 0x0100 /* Bus Busy Indicator */
+
+/* TWIx_INT_SRC and TWIx_INT_ENABLE Masks */
+#define SINIT 0x0001 /* Slave Transfer Initiated */
+#define SCOMP 0x0002 /* Slave Transfer Complete */
+#define SERR 0x0004 /* Slave Transfer Error */
+#define SOVF 0x0008 /* Slave Overflow */
+#define MCOMP 0x0010 /* Master Transfer Complete */
+#define MERR 0x0020 /* Master Transfer Error */
+#define XMTSERV 0x0040 /* Transmit FIFO Service */
+#define RCVSERV 0x0080 /* Receive FIFO Service */
+
+/* TWIx_FIFO_CTRL Masks */
+#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
+#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
+#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
+#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
+
+/* TWIx_FIFO_STAT Masks */
+#define XMTSTAT 0x0003 /* Transmit FIFO Status */
+#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
+#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
+#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
+
+#define RCVSTAT 0x000C /* Receive FIFO Status */
+#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
+#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
+#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
+
+
+/********************************* MXVR MASKS ****************************************/
+
+/* MXVR_CONFIG Masks */
+
+#define MXVREN 0x00000001lu
+#define MMSM 0x00000002lu
+#define ACTIVE 0x00000004lu
+#define SDELAY 0x00000008lu
+#define NCMRXEN 0x00000010lu
+#define RWRRXEN 0x00000020lu
+#define MTXEN 0x00000040lu
+#define MTXON 0x00000080lu /*legacy*/
+#define MTXONB 0x00000080lu
+#define EPARITY 0x00000100lu
+#define MSB 0x00001E00lu
+#define APRXEN 0x00002000lu
+#define WAKEUP 0x00004000lu
+#define LMECH 0x00008000lu
+
+#ifdef _MISRA_RULES
+#define SET_MSB(x) (((x)&0xFu) << 0x9)
+#else
+#define SET_MSB(x) (((x)&0xF) << 0x9)
+#endif /* _MISRA_RULES */
+
+
+/* MXVR_PLL_CTL_0 Masks */
+
+#define MXTALCEN 0x00000001lu
+#define MXTALFEN 0x00000002lu
+#define MPLLMS 0x00000008lu
+#define MXTALMUL 0x00000030lu
+#define MPLLEN 0x00000040lu
+#define MPLLEN0 0x00000040lu /* legacy */
+#define MPLLEN1 0x00000080lu /* legacy */
+#define MMCLKEN 0x00000100lu
+#define MMCLKMUL 0x00001E00lu
+#define MPLLRSTB 0x00002000lu
+#define MPLLRSTB0 0x00002000lu /* legacy */
+#define MPLLRSTB1 0x00004000lu /* legacy */
+#define MBCLKEN 0x00010000lu
+#define MBCLKDIV 0x001E0000lu
+#define MPLLCDR 0x00200000lu
+#define MPLLCDR0 0x00200000lu /* legacy */
+#define MPLLCDR1 0x00400000lu /* legacy */
+#define INVRX 0x00800000lu
+#define MFSEN 0x01000000lu
+#define MFSDIV 0x1E000000lu
+#define MFSSEL 0x60000000lu
+#define MFSSYNC 0x80000000lu
+
+#define MXTALMUL_256FS 0x00000000lu /* legacy */
+#define MXTALMUL_384FS 0x00000010lu /* legacy */
+#define MXTALMUL_512FS 0x00000020lu /* legacy */
+#define MXTALMUL_1024FS 0x00000030lu
+
+#define MMCLKMUL_1024FS 0x00000000lu
+#define MMCLKMUL_512FS 0x00000200lu
+#define MMCLKMUL_256FS 0x00000400lu
+#define MMCLKMUL_128FS 0x00000600lu
+#define MMCLKMUL_64FS 0x00000800lu
+#define MMCLKMUL_32FS 0x00000A00lu
+#define MMCLKMUL_16FS 0x00000C00lu
+#define MMCLKMUL_8FS 0x00000E00lu
+#define MMCLKMUL_4FS 0x00001000lu
+#define MMCLKMUL_2FS 0x00001200lu
+#define MMCLKMUL_1FS 0x00001400lu
+#define MMCLKMUL_1536FS 0x00001A00lu
+#define MMCLKMUL_768FS 0x00001C00lu
+#define MMCLKMUL_384FS 0x00001E00lu
+
+#define MBCLKDIV_DIV2 0x00020000lu
+#define MBCLKDIV_DIV4 0x00040000lu
+#define MBCLKDIV_DIV8 0x00060000lu
+#define MBCLKDIV_DIV16 0x00080000lu
+#define MBCLKDIV_DIV32 0x000A0000lu
+#define MBCLKDIV_DIV64 0x000C0000lu
+#define MBCLKDIV_DIV128 0x000E0000lu
+#define MBCLKDIV_DIV256 0x00100000lu
+#define MBCLKDIV_DIV512 0x00120000lu
+#define MBCLKDIV_DIV1024 0x00140000lu
+
+#define MFSDIV_DIV2 0x02000000lu
+#define MFSDIV_DIV4 0x04000000lu
+#define MFSDIV_DIV8 0x06000000lu
+#define MFSDIV_DIV16 0x08000000lu
+#define MFSDIV_DIV32 0x0A000000lu
+#define MFSDIV_DIV64 0x0C000000lu
+#define MFSDIV_DIV128 0x0E000000lu
+#define MFSDIV_DIV256 0x10000000lu
+#define MFSDIV_DIV512 0x12000000lu
+#define MFSDIV_DIV1024 0x14000000lu
+
+#define MFSSEL_CLOCK 0x00000000lu
+#define MFSSEL_PULSE_HI 0x20000000lu
+#define MFSSEL_PULSE_LO 0x40000000lu
+
+
+/* MXVR_PLL_CTL_1 Masks */
+
+#define MSTO 0x00000001lu
+#define MSTO0 0x00000001lu /* legacy */
+#define MHOGGD 0x00000004lu
+#define MHOGGD0 0x00000004lu /* legacy */
+#define MHOGGD1 0x00000008lu /* legacy */
+#define MSHAPEREN 0x00000010lu
+#define MSHAPEREN0 0x00000010lu /* legacy */
+#define MSHAPEREN1 0x00000020lu /* legacy */
+#define MPLLCNTEN 0x00008000lu
+#define MPLLCNT 0xFFFF0000lu
+
+#ifdef _MISRA_RULES
+#define SET_MPLLCNT(x) (((x)&0xFFFFu) << 0x10)
+#else
+#define SET_MPLLCNT(x) (((x)&0xFFFF) << 0x10)
+#endif /* _MISRA_RULES */
+
+
+/* MXVR_PLL_CTL_2 Masks */
+
+#define MSHAPERSEL 0x00000007lu
+#define MCPSEL 0x000000E0lu
+
+/* MXVR_INT_STAT_0 Masks */
+
+#define NI2A 0x00000001lu
+#define NA2I 0x00000002lu
+#define SBU2L 0x00000004lu
+#define SBL2U 0x00000008lu
+#define PRU 0x00000010lu
+#define MPRU 0x00000020lu
+#define DRU 0x00000040lu
+#define MDRU 0x00000080lu
+#define SBU 0x00000100lu
+#define ATU 0x00000200lu
+#define FCZ0 0x00000400lu
+#define FCZ1 0x00000800lu
+#define PERR 0x00001000lu
+#define MH2L 0x00002000lu
+#define ML2H 0x00004000lu
+#define WUP 0x00008000lu
+#define FU2L 0x00010000lu
+#define FL2U 0x00020000lu
+#define BU2L 0x00040000lu
+#define BL2U 0x00080000lu
+#define PCZ 0x00400000lu
+#define FERR 0x00800000lu
+#define CMR 0x01000000lu
+#define CMROF 0x02000000lu
+#define CMTS 0x04000000lu
+#define CMTC 0x08000000lu
+#define RWRC 0x10000000lu
+#define BCZ 0x20000000lu
+#define BMERR 0x40000000lu
+#define DERR 0x80000000lu
+
+
+/* MXVR_INT_EN_0 Masks */
+
+#define NI2AEN NI2A
+#define NA2IEN NA2I
+#define SBU2LEN SBU2L
+#define SBL2UEN SBL2U
+#define PRUEN PRU
+#define MPRUEN MPRU
+#define DRUEN DRU
+#define MDRUEN MDRU
+#define SBUEN SBU
+#define ATUEN ATU
+#define FCZ0EN FCZ0
+#define FCZ1EN FCZ1
+#define PERREN PERR
+#define MH2LEN MH2L
+#define ML2HEN ML2H
+#define WUPEN WUP
+#define FU2LEN FU2L
+#define FL2UEN FL2U
+#define BU2LEN BU2L
+#define BL2UEN BL2U
+#define PCZEN PCZ
+#define FERREN FERR
+#define CMREN CMR
+#define CMROFEN CMROF
+#define CMTSEN CMTS
+#define CMTCEN CMTC
+#define RWRCEN RWRC
+#define BCZEN BCZ
+#define BMERREN BMERR
+#define DERREN DERR
+
+
+/* MXVR_INT_STAT_1 Masks */
+
+#define APR 0x00000004lu
+#define APROF 0x00000008lu
+#define APTS 0x00000040lu
+#define APTC 0x00000080lu
+#define APRCE 0x00000400lu
+#define APRPE 0x00000800lu
+
+#define HDONE0 0x00000001lu
+#define DONE0 0x00000002lu
+#define HDONE1 0x00000010lu
+#define DONE1 0x00000020lu
+#define HDONE2 0x00000100lu
+#define DONE2 0x00000200lu
+#define HDONE3 0x00001000lu
+#define DONE3 0x00002000lu
+#define HDONE4 0x00010000lu
+#define DONE4 0x00020000lu
+#define HDONE5 0x00100000lu
+#define DONE5 0x00200000lu
+#define HDONE6 0x01000000lu
+#define DONE6 0x02000000lu
+#define HDONE7 0x10000000lu
+#define DONE7 0x20000000lu
+
+#define DONEX(x) (0x00000002 << (4 * (x)))
+#define HDONEX(x) (0x00000001 << (4 * (x)))
+
+
+/* MXVR_INT_EN_1 Masks */
+
+#define APREN APR
+#define APROFEN APROF
+#define APTSEN APTS
+#define APTCEN APTC
+#define APRCEEN APRCE
+#define APRPEEN APRPE
+
+#define HDONEEN0 HDONE0
+#define DONEEN0 DONE0
+#define HDONEEN1 HDONE1
+#define DONEEN1 DONE1
+#define HDONEEN2 HDONE2
+#define DONEEN2 DONE2
+#define HDONEEN3 HDONE3
+#define DONEEN3 DONE3
+#define HDONEEN4 HDONE4
+#define DONEEN4 DONE4
+#define HDONEEN5 HDONE5
+#define DONEEN5 DONE5
+#define HDONEEN6 HDONE6
+#define DONEEN6 DONE6
+#define HDONEEN7 HDONE7
+#define DONEEN7 DONE7
+
+#define DONEENX(x) (0x00000002 << (4 * (x)))
+#define HDONEENX(x) (0x00000001 << (4 * (x)))
+
+
+/* MXVR_STATE_0 Masks */
+
+#define NACT 0x00000001lu
+#define SBLOCK 0x00000002lu
+#define PFDLOCK 0x00000004lu
+#define PFDLOCK0 0x00000004lu /* legacy */
+#define PDD 0x00000008lu
+#define PDD0 0x00000008lu /* legacy */
+#define PVCO 0x00000010lu
+#define PVCO0 0x00000010lu /* legacy */
+#define PFDLOCK1 0x00000020lu /* legacy */
+#define PDD1 0x00000040lu /* legacy */
+#define PVCO1 0x00000080lu /* legacy */
+#define APBSY 0x00000100lu
+#define APARB 0x00000200lu
+#define APTX 0x00000400lu
+#define APRX 0x00000800lu
+#define CMBSY 0x00001000lu
+#define CMARB 0x00002000lu
+#define CMTX 0x00004000lu
+#define CMRX 0x00008000lu
+#define MRXONB 0x00010000lu
+#define RGSIP 0x00020000lu
+#define DALIP 0x00040000lu
+#define ALIP 0x00080000lu
+#define RRDIP 0x00100000lu
+#define RWRIP 0x00200000lu
+#define FLOCK 0x00400000lu
+#define BLOCK 0x00800000lu
+#define RSB 0x0F000000lu
+#define DERRNUM 0xF0000000lu
+
+
+/* MXVR_STATE_1 Masks */
+
+#define STXNUMB 0x0000000Flu
+#define SRXNUMB 0x000000F0lu
+#define APCONT 0x00000100lu
+#define DMAACTIVEX 0x00FF0000lu
+#define DMAACTIVE0 0x00010000lu
+#define DMAACTIVE1 0x00020000lu
+#define DMAACTIVE2 0x00040000lu
+#define DMAACTIVE3 0x00080000lu
+#define DMAACTIVE4 0x00100000lu
+#define DMAACTIVE5 0x00200000lu
+#define DMAACTIVE6 0x00400000lu
+#define DMAACTIVE7 0x00800000lu
+#define DMAPMENX 0xFF000000lu
+#define DMAPMEN0 0x01000000lu
+#define DMAPMEN1 0x02000000lu
+#define DMAPMEN2 0x04000000lu
+#define DMAPMEN3 0x08000000lu
+#define DMAPMEN4 0x10000000lu
+#define DMAPMEN5 0x20000000lu
+#define DMAPMEN6 0x40000000lu
+#define DMAPMEN7 0x80000000lu
+
+
+/* MXVR_POSITION Masks */
+
+#define PVALID 0x8000
+#define POSITION 0x003F
+
+
+/* MXVR_MAX_POSITION Masks */
+
+#define MPVALID 0x8000
+#define MPOSITION 0x003F
+
+
+/* MXVR_DELAY Masks */
+
+#define DVALID 0x8000
+#define DELAY 0x003F
+
+
+/* MXVR_MAX_DELAY Masks */
+
+#define MDVALID 0x8000
+#define MDELAY 0x003F
+
+
+/* MXVR_LADDR Masks */
+
+#define LVALID 0x80000000lu
+#define LADDR 0x0000FFFFlu
+
+
+/* MXVR_GADDR Masks */
+
+#define GVALID 0x8000
+#define GADDRL 0x00FF
+
+
+/* MXVR_AADDR Masks */
+
+#define AVALID 0x80000000lu
+#define AADDR 0x0000FFFFlu
+
+
+/* MXVR_ALLOC_0 Masks */
+
+#define CIU0 0x00000080lu
+#define CIU1 0x00008000lu
+#define CIU2 0x00800000lu
+#define CIU3 0x80000000lu
+
+#define CL0 0x0000007Flu
+#define CL1 0x00007F00lu
+#define CL2 0x007F0000lu
+#define CL3 0x7F000000lu
+
+
+/* MXVR_ALLOC_1 Masks */
+
+#define CIU4 0x00000080lu
+#define CIU5 0x00008000lu
+#define CIU6 0x00800000lu
+#define CIU7 0x80000000lu
+
+#define CL4 0x0000007Flu
+#define CL5 0x00007F00lu
+#define CL6 0x007F0000lu
+#define CL7 0x7F000000lu
+
+
+/* MXVR_ALLOC_2 Masks */
+
+#define CIU8 0x00000080lu
+#define CIU9 0x00008000lu
+#define CIU10 0x00800000lu
+#define CIU11 0x80000000lu
+
+#define CL8 0x0000007Flu
+#define CL9 0x00007F00lu
+#define CL10 0x007F0000lu
+#define CL11 0x7F000000lu
+
+
+/* MXVR_ALLOC_3 Masks */
+
+#define CIU12 0x00000080lu
+#define CIU13 0x00008000lu
+#define CIU14 0x00800000lu
+#define CIU15 0x80000000lu
+
+#define CL12 0x0000007Flu
+#define CL13 0x00007F00lu
+#define CL14 0x007F0000lu
+#define CL15 0x7F000000lu
+
+
+/* MXVR_ALLOC_4 Masks */
+
+#define CIU16 0x00000080lu
+#define CIU17 0x00008000lu
+#define CIU18 0x00800000lu
+#define CIU19 0x80000000lu
+
+#define CL16 0x0000007Flu
+#define CL17 0x00007F00lu
+#define CL18 0x007F0000lu
+#define CL19 0x7F000000lu
+
+
+/* MXVR_ALLOC_5 Masks */
+
+#define CIU20 0x00000080lu
+#define CIU21 0x00008000lu
+#define CIU22 0x00800000lu
+#define CIU23 0x80000000lu
+
+#define CL20 0x0000007Flu
+#define CL21 0x00007F00lu
+#define CL22 0x007F0000lu
+#define CL23 0x7F000000lu
+
+
+/* MXVR_ALLOC_6 Masks */
+
+#define CIU24 0x00000080lu
+#define CIU25 0x00008000lu
+#define CIU26 0x00800000lu
+#define CIU27 0x80000000lu
+
+#define CL24 0x0000007Flu
+#define CL25 0x00007F00lu
+#define CL26 0x007F0000lu
+#define CL27 0x7F000000lu
+
+
+/* MXVR_ALLOC_7 Masks */
+
+#define CIU28 0x00000080lu
+#define CIU29 0x00008000lu
+#define CIU30 0x00800000lu
+#define CIU31 0x80000000lu
+
+#define CL28 0x0000007Flu
+#define CL29 0x00007F00lu
+#define CL30 0x007F0000lu
+#define CL31 0x7F000000lu
+
+
+/* MXVR_ALLOC_8 Masks */
+
+#define CIU32 0x00000080lu
+#define CIU33 0x00008000lu
+#define CIU34 0x00800000lu
+#define CIU35 0x80000000lu
+
+#define CL32 0x0000007Flu
+#define CL33 0x00007F00lu
+#define CL34 0x007F0000lu
+#define CL35 0x7F000000lu
+
+
+/* MXVR_ALLOC_9 Masks */
+
+#define CIU36 0x00000080lu
+#define CIU37 0x00008000lu
+#define CIU38 0x00800000lu
+#define CIU39 0x80000000lu
+
+#define CL36 0x0000007Flu
+#define CL37 0x00007F00lu
+#define CL38 0x007F0000lu
+#define CL39 0x7F000000lu
+
+
+/* MXVR_ALLOC_10 Masks */
+
+#define CIU40 0x00000080lu
+#define CIU41 0x00008000lu
+#define CIU42 0x00800000lu
+#define CIU43 0x80000000lu
+
+#define CL40 0x0000007Flu
+#define CL41 0x00007F00lu
+#define CL42 0x007F0000lu
+#define CL43 0x7F000000lu
+
+
+/* MXVR_ALLOC_11 Masks */
+
+#define CIU44 0x00000080lu
+#define CIU45 0x00008000lu
+#define CIU46 0x00800000lu
+#define CIU47 0x80000000lu
+
+#define CL44 0x0000007Flu
+#define CL45 0x00007F00lu
+#define CL46 0x007F0000lu
+#define CL47 0x7F000000lu
+
+
+/* MXVR_ALLOC_12 Masks */
+
+#define CIU48 0x00000080lu
+#define CIU49 0x00008000lu
+#define CIU50 0x00800000lu
+#define CIU51 0x80000000lu
+
+#define CL48 0x0000007Flu
+#define CL49 0x00007F00lu
+#define CL50 0x007F0000lu
+#define CL51 0x7F000000lu
+
+
+/* MXVR_ALLOC_13 Masks */
+
+#define CIU52 0x00000080lu
+#define CIU53 0x00008000lu
+#define CIU54 0x00800000lu
+#define CIU55 0x80000000lu
+
+#define CL52 0x0000007Flu
+#define CL53 0x00007F00lu
+#define CL54 0x007F0000lu
+#define CL55 0x7F000000lu
+
+
+/* MXVR_ALLOC_14 Masks */
+
+#define CIU56 0x00000080lu
+#define CIU57 0x00008000lu
+#define CIU58 0x00800000lu
+#define CIU59 0x80000000lu
+
+#define CL56 0x0000007Flu
+#define CL57 0x00007F00lu
+#define CL58 0x007F0000lu
+#define CL59 0x7F000000lu
+
+
+/* MXVR_SYNC_LCHAN_0 Masks */
+
+#define LCHANPC0 0x0000000Flu
+#define LCHANPC1 0x000000F0lu
+#define LCHANPC2 0x00000F00lu
+#define LCHANPC3 0x0000F000lu
+#define LCHANPC4 0x000F0000lu
+#define LCHANPC5 0x00F00000lu
+#define LCHANPC6 0x0F000000lu
+#define LCHANPC7 0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_1 Masks */
+
+#define LCHANPC8 0x0000000Flu
+#define LCHANPC9 0x000000F0lu
+#define LCHANPC10 0x00000F00lu
+#define LCHANPC11 0x0000F000lu
+#define LCHANPC12 0x000F0000lu
+#define LCHANPC13 0x00F00000lu
+#define LCHANPC14 0x0F000000lu
+#define LCHANPC15 0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_2 Masks */
+
+#define LCHANPC16 0x0000000Flu
+#define LCHANPC17 0x000000F0lu
+#define LCHANPC18 0x00000F00lu
+#define LCHANPC19 0x0000F000lu
+#define LCHANPC20 0x000F0000lu
+#define LCHANPC21 0x00F00000lu
+#define LCHANPC22 0x0F000000lu
+#define LCHANPC23 0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_3 Masks */
+
+#define LCHANPC24 0x0000000Flu
+#define LCHANPC25 0x000000F0lu
+#define LCHANPC26 0x00000F00lu
+#define LCHANPC27 0x0000F000lu
+#define LCHANPC28 0x000F0000lu
+#define LCHANPC29 0x00F00000lu
+#define LCHANPC30 0x0F000000lu
+#define LCHANPC31 0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_4 Masks */
+
+#define LCHANPC32 0x0000000Flu
+#define LCHANPC33 0x000000F0lu
+#define LCHANPC34 0x00000F00lu
+#define LCHANPC35 0x0000F000lu
+#define LCHANPC36 0x000F0000lu
+#define LCHANPC37 0x00F00000lu
+#define LCHANPC38 0x0F000000lu
+#define LCHANPC39 0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_5 Masks */
+
+#define LCHANPC40 0x0000000Flu
+#define LCHANPC41 0x000000F0lu
+#define LCHANPC42 0x00000F00lu
+#define LCHANPC43 0x0000F000lu
+#define LCHANPC44 0x000F0000lu
+#define LCHANPC45 0x00F00000lu
+#define LCHANPC46 0x0F000000lu
+#define LCHANPC47 0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_6 Masks */
+
+#define LCHANPC48 0x0000000Flu
+#define LCHANPC49 0x000000F0lu
+#define LCHANPC50 0x00000F00lu
+#define LCHANPC51 0x0000F000lu
+#define LCHANPC52 0x000F0000lu
+#define LCHANPC53 0x00F00000lu
+#define LCHANPC54 0x0F000000lu
+#define LCHANPC55 0xF0000000lu
+
+
+/* MXVR_SYNC_LCHAN_7 Masks */
+
+#define LCHANPC56 0x0000000Flu
+#define LCHANPC57 0x000000F0lu
+#define LCHANPC58 0x00000F00lu
+#define LCHANPC59 0x0000F000lu
+
+
+/* MXVR_DMAx_CONFIG Masks */
+
+#define MDMAEN 0x00000001lu
+#define DD 0x00000002lu
+#define LCHAN 0x000003C0lu
+#define BITSWAPEN 0x00000400lu
+#define BYSWAPEN 0x00000800lu
+#define MFLOW 0x00007000lu
+#define FIXEDPM 0x00080000lu
+#define STARTPAT 0x00300000lu
+#define STOPPAT 0x00C00000lu
+#define COUNTPOS 0x1C000000lu
+
+#define DD_TX 0x00000000lu
+#define DD_RX 0x00000002lu
+
+#define LCHAN_0 0x00000000lu
+#define LCHAN_1 0x00000040lu
+#define LCHAN_2 0x00000080lu
+#define LCHAN_3 0x000000C0lu
+#define LCHAN_4 0x00000100lu
+#define LCHAN_5 0x00000140lu
+#define LCHAN_6 0x00000180lu
+#define LCHAN_7 0x000001C0lu
+
+#define MFLOW_STOP 0x00000000lu
+#define MFLOW_AUTO 0x00001000lu
+#define MFLOW_PVC 0x00002000lu
+#define MFLOW_PSS 0x00003000lu
+#define MFLOW_PFC 0x00004000lu
+
+#define STARTPAT_0 0x00000000lu
+#define STARTPAT_1 0x00100000lu
+
+#define STOPPAT_0 0x00000000lu
+#define STOPPAT_1 0x00400000lu
+
+#define COUNTPOS_0 0x00000000lu
+#define COUNTPOS_1 0x04000000lu
+#define COUNTPOS_2 0x08000000lu
+#define COUNTPOS_3 0x0C000000lu
+#define COUNTPOS_4 0x10000000lu
+#define COUNTPOS_5 0x14000000lu
+#define COUNTPOS_6 0x18000000lu
+#define COUNTPOS_7 0x1C000000lu
+
+
+/* MXVR_AP_CTL Masks */
+
+#define STARTAP 0x00000001lu
+#define CANCELAP 0x00000002lu
+#define RESETAP 0x00000004lu
+#define APRBE0 0x00004000lu
+#define APRBE1 0x00008000lu
+#define APRBEX 0x0000C000lu
+
+
+/* MXVR_CM_CTL Masks */
+
+#define STARTCM 0x00000001lu
+#define CANCELCM 0x00000002lu
+#define CMRBEX 0xFFFF0000lu
+#define CMRBE0 0x00010000lu
+#define CMRBE1 0x00020000lu
+#define CMRBE2 0x00040000lu
+#define CMRBE3 0x00080000lu
+#define CMRBE4 0x00100000lu
+#define CMRBE5 0x00200000lu
+#define CMRBE6 0x00400000lu
+#define CMRBE7 0x00800000lu
+#define CMRBE8 0x01000000lu
+#define CMRBE9 0x02000000lu
+#define CMRBE10 0x04000000lu
+#define CMRBE11 0x08000000lu
+#define CMRBE12 0x10000000lu
+#define CMRBE13 0x20000000lu
+#define CMRBE14 0x40000000lu
+#define CMRBE15 0x80000000lu
+
+
+/* MXVR_PAT_DATA_x Masks */
+
+#define MATCH_DATA_0 0x000000FFlu
+#define MATCH_DATA_1 0x0000FF00lu
+#define MATCH_DATA_2 0x00FF0000lu
+#define MATCH_DATA_3 0xFF000000lu
+
+
+
+/* MXVR_PAT_EN_x Masks */
+
+#define MATCH_EN_0_0 0x00000001lu
+#define MATCH_EN_0_1 0x00000002lu
+#define MATCH_EN_0_2 0x00000004lu
+#define MATCH_EN_0_3 0x00000008lu
+#define MATCH_EN_0_4 0x00000010lu
+#define MATCH_EN_0_5 0x00000020lu
+#define MATCH_EN_0_6 0x00000040lu
+#define MATCH_EN_0_7 0x00000080lu
+
+#define MATCH_EN_1_0 0x00000100lu
+#define MATCH_EN_1_1 0x00000200lu
+#define MATCH_EN_1_2 0x00000400lu
+#define MATCH_EN_1_3 0x00000800lu
+#define MATCH_EN_1_4 0x00001000lu
+#define MATCH_EN_1_5 0x00002000lu
+#define MATCH_EN_1_6 0x00004000lu
+#define MATCH_EN_1_7 0x00008000lu
+
+#define MATCH_EN_2_0 0x00010000lu
+#define MATCH_EN_2_1 0x00020000lu
+#define MATCH_EN_2_2 0x00040000lu
+#define MATCH_EN_2_3 0x00080000lu
+#define MATCH_EN_2_4 0x00100000lu
+#define MATCH_EN_2_5 0x00200000lu
+#define MATCH_EN_2_6 0x00400000lu
+#define MATCH_EN_2_7 0x00800000lu
+
+#define MATCH_EN_3_0 0x01000000lu
+#define MATCH_EN_3_1 0x02000000lu
+#define MATCH_EN_3_2 0x04000000lu
+#define MATCH_EN_3_3 0x08000000lu
+#define MATCH_EN_3_4 0x10000000lu
+#define MATCH_EN_3_5 0x20000000lu
+#define MATCH_EN_3_6 0x40000000lu
+#define MATCH_EN_3_7 0x80000000lu
+
+
+/* MXVR_ROUTING_0 Masks */
+
+#define MUTE_CH0 0x00000080lu
+#define MUTE_CH1 0x00008000lu
+#define MUTE_CH2 0x00800000lu
+#define MUTE_CH3 0x80000000lu
+
+#define TX_CH0 0x0000007Flu
+#define TX_CH1 0x00007F00lu
+#define TX_CH2 0x007F0000lu
+#define TX_CH3 0x7F000000lu
+
+
+/* MXVR_ROUTING_1 Masks */
+
+#define MUTE_CH4 0x00000080lu
+#define MUTE_CH5 0x00008000lu
+#define MUTE_CH6 0x00800000lu
+#define MUTE_CH7 0x80000000lu
+
+#define TX_CH4 0x0000007Flu
+#define TX_CH5 0x00007F00lu
+#define TX_CH6 0x007F0000lu
+#define TX_CH7 0x7F000000lu
+
+
+/* MXVR_ROUTING_2 Masks */
+
+#define MUTE_CH8 0x00000080lu
+#define MUTE_CH9 0x00008000lu
+#define MUTE_CH10 0x00800000lu
+#define MUTE_CH11 0x80000000lu
+
+#define TX_CH8 0x0000007Flu
+#define TX_CH9 0x00007F00lu
+#define TX_CH10 0x007F0000lu
+#define TX_CH11 0x7F000000lu
+
+/* MXVR_ROUTING_3 Masks */
+
+#define MUTE_CH12 0x00000080lu
+#define MUTE_CH13 0x00008000lu
+#define MUTE_CH14 0x00800000lu
+#define MUTE_CH15 0x80000000lu
+
+#define TX_CH12 0x0000007Flu
+#define TX_CH13 0x00007F00lu
+#define TX_CH14 0x007F0000lu
+#define TX_CH15 0x7F000000lu
+
+
+/* MXVR_ROUTING_4 Masks */
+
+#define MUTE_CH16 0x00000080lu
+#define MUTE_CH17 0x00008000lu
+#define MUTE_CH18 0x00800000lu
+#define MUTE_CH19 0x80000000lu
+
+#define TX_CH16 0x0000007Flu
+#define TX_CH17 0x00007F00lu
+#define TX_CH18 0x007F0000lu
+#define TX_CH19 0x7F000000lu
+
+
+/* MXVR_ROUTING_5 Masks */
+
+#define MUTE_CH20 0x00000080lu
+#define MUTE_CH21 0x00008000lu
+#define MUTE_CH22 0x00800000lu
+#define MUTE_CH23 0x80000000lu
+
+#define TX_CH20 0x0000007Flu
+#define TX_CH21 0x00007F00lu
+#define TX_CH22 0x007F0000lu
+#define TX_CH23 0x7F000000lu
+
+
+/* MXVR_ROUTING_6 Masks */
+
+#define MUTE_CH24 0x00000080lu
+#define MUTE_CH25 0x00008000lu
+#define MUTE_CH26 0x00800000lu
+#define MUTE_CH27 0x80000000lu
+
+#define TX_CH24 0x0000007Flu
+#define TX_CH25 0x00007F00lu
+#define TX_CH26 0x007F0000lu
+#define TX_CH27 0x7F000000lu
+
+
+/* MXVR_ROUTING_7 Masks */
+
+#define MUTE_CH28 0x00000080lu
+#define MUTE_CH29 0x00008000lu
+#define MUTE_CH30 0x00800000lu
+#define MUTE_CH31 0x80000000lu
+
+#define TX_CH28 0x0000007Flu
+#define TX_CH29 0x00007F00lu
+#define TX_CH30 0x007F0000lu
+#define TX_CH31 0x7F000000lu
+
+
+/* MXVR_ROUTING_8 Masks */
+
+#define MUTE_CH32 0x00000080lu
+#define MUTE_CH33 0x00008000lu
+#define MUTE_CH34 0x00800000lu
+#define MUTE_CH35 0x80000000lu
+
+#define TX_CH32 0x0000007Flu
+#define TX_CH33 0x00007F00lu
+#define TX_CH34 0x007F0000lu
+#define TX_CH35 0x7F000000lu
+
+
+/* MXVR_ROUTING_9 Masks */
+
+#define MUTE_CH36 0x00000080lu
+#define MUTE_CH37 0x00008000lu
+#define MUTE_CH38 0x00800000lu
+#define MUTE_CH39 0x80000000lu
+
+#define TX_CH36 0x0000007Flu
+#define TX_CH37 0x00007F00lu
+#define TX_CH38 0x007F0000lu
+#define TX_CH39 0x7F000000lu
+
+
+/* MXVR_ROUTING_10 Masks */
+
+#define MUTE_CH40 0x00000080lu
+#define MUTE_CH41 0x00008000lu
+#define MUTE_CH42 0x00800000lu
+#define MUTE_CH43 0x80000000lu
+
+#define TX_CH40 0x0000007Flu
+#define TX_CH41 0x00007F00lu
+#define TX_CH42 0x007F0000lu
+#define TX_CH43 0x7F000000lu
+
+
+/* MXVR_ROUTING_11 Masks */
+
+#define MUTE_CH44 0x00000080lu
+#define MUTE_CH45 0x00008000lu
+#define MUTE_CH46 0x00800000lu
+#define MUTE_CH47 0x80000000lu
+
+#define TX_CH44 0x0000007Flu
+#define TX_CH45 0x00007F00lu
+#define TX_CH46 0x007F0000lu
+#define TX_CH47 0x7F000000lu
+
+
+/* MXVR_ROUTING_12 Masks */
+
+#define MUTE_CH48 0x00000080lu
+#define MUTE_CH49 0x00008000lu
+#define MUTE_CH50 0x00800000lu
+#define MUTE_CH51 0x80000000lu
+
+#define TX_CH48 0x0000007Flu
+#define TX_CH49 0x00007F00lu
+#define TX_CH50 0x007F0000lu
+#define TX_CH51 0x7F000000lu
+
+
+/* MXVR_ROUTING_13 Masks */
+
+#define MUTE_CH52 0x00000080lu
+#define MUTE_CH53 0x00008000lu
+#define MUTE_CH54 0x00800000lu
+#define MUTE_CH55 0x80000000lu
+
+#define TX_CH52 0x0000007Flu
+#define TX_CH53 0x00007F00lu
+#define TX_CH54 0x007F0000lu
+#define TX_CH55 0x7F000000lu
+
+
+/* MXVR_ROUTING_14 Masks */
+
+#define MUTE_CH56 0x00000080lu
+#define MUTE_CH57 0x00008000lu
+#define MUTE_CH58 0x00800000lu
+#define MUTE_CH59 0x80000000lu
+
+#define TX_CH56 0x0000007Flu
+#define TX_CH57 0x00007F00lu
+#define TX_CH58 0x007F0000lu
+#define TX_CH59 0x7F000000lu
+
+
+/* Control Message Receive Buffer (CMRB) Address Offsets */
+
+#define CMRB_STRIDE 0x00000016lu
+
+#define CMRB_DST_OFFSET 0x00000000lu
+#define CMRB_SRC_OFFSET 0x00000002lu
+#define CMRB_DATA_OFFSET 0x00000005lu
+
+
+/* Control Message Transmit Buffer (CMTB) Address Offsets */
+
+#define CMTB_PRIO_OFFSET 0x00000000lu
+#define CMTB_DST_OFFSET 0x00000002lu
+#define CMTB_SRC_OFFSET 0x00000004lu
+#define CMTB_TYPE_OFFSET 0x00000006lu
+#define CMTB_DATA_OFFSET 0x00000007lu
+
+#define CMTB_ANSWER_OFFSET 0x0000000Alu
+
+#define CMTB_STAT_N_OFFSET 0x00000018lu
+#define CMTB_STAT_A_OFFSET 0x00000016lu
+#define CMTB_STAT_D_OFFSET 0x0000000Elu
+#define CMTB_STAT_R_OFFSET 0x00000014lu
+#define CMTB_STAT_W_OFFSET 0x00000014lu
+#define CMTB_STAT_G_OFFSET 0x00000014lu
+
+
+/* Asynchronous Packet Receive Buffer (APRB) Address Offsets */
+
+#define APRB_STRIDE 0x00000400lu
+
+#define APRB_DST_OFFSET 0x00000000lu
+#define APRB_LEN_OFFSET 0x00000002lu
+#define APRB_SRC_OFFSET 0x00000004lu
+#define APRB_DATA_OFFSET 0x00000006lu
+
+
+/* Asynchronous Packet Transmit Buffer (APTB) Address Offsets */
+
+#define APTB_PRIO_OFFSET 0x00000000lu
+#define APTB_DST_OFFSET 0x00000002lu
+#define APTB_LEN_OFFSET 0x00000004lu
+#define APTB_SRC_OFFSET 0x00000006lu
+#define APTB_DATA_OFFSET 0x00000008lu
+
+
+/* Remote Read Buffer (RRDB) Address Offsets */
+
+#define RRDB_WADDR_OFFSET 0x00000100lu
+#define RRDB_WLEN_OFFSET 0x00000101lu
+
+
+
+/* ************ CONTROLLER AREA NETWORK (CAN) MASKS ***************/
+/* CAN_CONTROL Masks */
+#define SRS 0x0001 /* Software Reset */
+#define DNM 0x0002 /* Device Net Mode */
+#define ABO 0x0004 /* Auto-Bus On Enable */
+#define WBA 0x0010 /* Wake-Up On CAN Bus Activity Enable */
+#define SMR 0x0020 /* Sleep Mode Request */
+#define CSR 0x0040 /* CAN Suspend Mode Request */
+#define CCR 0x0080 /* CAN Configuration Mode Request */
+
+/* CAN_STATUS Masks */
+#define WT 0x0001 /* TX Warning Flag */
+#define WR 0x0002 /* RX Warning Flag */
+#define EP 0x0004 /* Error Passive Mode */
+#define EBO 0x0008 /* Error Bus Off Mode */
+#define CSA 0x0040 /* Suspend Mode Acknowledge */
+#define CCA 0x0080 /* Configuration Mode Acknowledge */
+#define MBPTR 0x1F00 /* Mailbox Pointer */
+#define TRM 0x4000 /* Transmit Mode */
+#define REC 0x8000 /* Receive Mode */
+
+/* CAN_CLOCK Masks */
+#define BRP 0x03FF /* Bit-Rate Pre-Scaler */
+
+/* CAN_TIMING Masks */
+#define TSEG1 0x000F /* Time Segment 1 */
+#define TSEG2 0x0070 /* Time Segment 2 */
+#define SAM 0x0080 /* Sampling */
+#define SJW 0x0300 /* Synchronization Jump Width */
+
+/* CAN_DEBUG Masks */
+#define DEC 0x0001 /* Disable CAN Error Counters */
+#define DRI 0x0002 /* Disable CAN RX Input */
+#define DTO 0x0004 /* Disable CAN TX Output */
+#define DIL 0x0008 /* Disable CAN Internal Loop */
+#define MAA 0x0010 /* Mode Auto-Acknowledge Enable */
+#define MRB 0x0020 /* Mode Read Back Enable */
+#define CDE 0x8000 /* CAN Debug Enable */
+
+/* CAN_CEC Masks */
+#define RXECNT 0x00FF /* Receive Error Counter */
+#define TXECNT 0xFF00 /* Transmit Error Counter */
+
+/* CAN_INTR Masks */
+#define MBRIRQ 0x0001 /* Mailbox Receive Interrupt */
+#define MBRIF MBRIRQ /* legacy */
+#define MBTIRQ 0x0002 /* Mailbox Transmit Interrupt */
+#define MBTIF MBTIRQ /* legacy */
+#define GIRQ 0x0004 /* Global Interrupt */
+#define SMACK 0x0008 /* Sleep Mode Acknowledge */
+#define CANTX 0x0040 /* CAN TX Bus Value */
+#define CANRX 0x0080 /* CAN RX Bus Value */
+
+/* CAN_MBxx_ID1 and CAN_MBxx_ID0 Masks */
+#define DFC 0xFFFF /* Data Filtering Code (If Enabled) (ID0) */
+#define EXTID_LO 0xFFFF /* Lower 16 Bits of Extended Identifier (ID0) */
+#define EXTID_HI 0x0003 /* Upper 2 Bits of Extended Identifier (ID1) */
+#define BASEID 0x1FFC /* Base Identifier */
+#define IDE 0x2000 /* Identifier Extension */
+#define RTR 0x4000 /* Remote Frame Transmission Request */
+#define AME 0x8000 /* Acceptance Mask Enable */
+
+/* CAN_MBxx_TIMESTAMP Masks */
+#define TSV 0xFFFF /* Timestamp */
+
+/* CAN_MBxx_LENGTH Masks */
+#define DLC 0x000F /* Data Length Code */
+
+/* CAN_AMxxH and CAN_AMxxL Masks */
+#define DFM 0xFFFF /* Data Field Mask (If Enabled) (CAN_AMxxL) */
+#define EXTID_LO 0xFFFF /* Lower 16 Bits of Extended Identifier (CAN_AMxxL) */
+#define EXTID_HI 0x0003 /* Upper 2 Bits of Extended Identifier (CAN_AMxxH) */
+#define BASEID 0x1FFC /* Base Identifier */
+#define AMIDE 0x2000 /* Acceptance Mask ID Extension Enable */
+#define FMD 0x4000 /* Full Mask Data Field Enable */
+#define FDF 0x8000 /* Filter On Data Field Enable */
+
+/* CAN_MC1 Masks */
+#define MC0 0x0001 /* Enable Mailbox 0 */
+#define MC1 0x0002 /* Enable Mailbox 1 */
+#define MC2 0x0004 /* Enable Mailbox 2 */
+#define MC3 0x0008 /* Enable Mailbox 3 */
+#define MC4 0x0010 /* Enable Mailbox 4 */
+#define MC5 0x0020 /* Enable Mailbox 5 */
+#define MC6 0x0040 /* Enable Mailbox 6 */
+#define MC7 0x0080 /* Enable Mailbox 7 */
+#define MC8 0x0100 /* Enable Mailbox 8 */
+#define MC9 0x0200 /* Enable Mailbox 9 */
+#define MC10 0x0400 /* Enable Mailbox 10 */
+#define MC11 0x0800 /* Enable Mailbox 11 */
+#define MC12 0x1000 /* Enable Mailbox 12 */
+#define MC13 0x2000 /* Enable Mailbox 13 */
+#define MC14 0x4000 /* Enable Mailbox 14 */
+#define MC15 0x8000 /* Enable Mailbox 15 */
+
+/* CAN_MC2 Masks */
+#define MC16 0x0001 /* Enable Mailbox 16 */
+#define MC17 0x0002 /* Enable Mailbox 17 */
+#define MC18 0x0004 /* Enable Mailbox 18 */
+#define MC19 0x0008 /* Enable Mailbox 19 */
+#define MC20 0x0010 /* Enable Mailbox 20 */
+#define MC21 0x0020 /* Enable Mailbox 21 */
+#define MC22 0x0040 /* Enable Mailbox 22 */
+#define MC23 0x0080 /* Enable Mailbox 23 */
+#define MC24 0x0100 /* Enable Mailbox 24 */
+#define MC25 0x0200 /* Enable Mailbox 25 */
+#define MC26 0x0400 /* Enable Mailbox 26 */
+#define MC27 0x0800 /* Enable Mailbox 27 */
+#define MC28 0x1000 /* Enable Mailbox 28 */
+#define MC29 0x2000 /* Enable Mailbox 29 */
+#define MC30 0x4000 /* Enable Mailbox 30 */
+#define MC31 0x8000 /* Enable Mailbox 31 */
+
+/* CAN_MD1 Masks */
+#define MD0 0x0001 /* Enable Mailbox 0 For Receive */
+#define MD1 0x0002 /* Enable Mailbox 1 For Receive */
+#define MD2 0x0004 /* Enable Mailbox 2 For Receive */
+#define MD3 0x0008 /* Enable Mailbox 3 For Receive */
+#define MD4 0x0010 /* Enable Mailbox 4 For Receive */
+#define MD5 0x0020 /* Enable Mailbox 5 For Receive */
+#define MD6 0x0040 /* Enable Mailbox 6 For Receive */
+#define MD7 0x0080 /* Enable Mailbox 7 For Receive */
+#define MD8 0x0100 /* Enable Mailbox 8 For Receive */
+#define MD9 0x0200 /* Enable Mailbox 9 For Receive */
+#define MD10 0x0400 /* Enable Mailbox 10 For Receive */
+#define MD11 0x0800 /* Enable Mailbox 11 For Receive */
+#define MD12 0x1000 /* Enable Mailbox 12 For Receive */
+#define MD13 0x2000 /* Enable Mailbox 13 For Receive */
+#define MD14 0x4000 /* Enable Mailbox 14 For Receive */
+#define MD15 0x8000 /* Enable Mailbox 15 For Receive */
+
+/* CAN_MD2 Masks */
+#define MD16 0x0001 /* Enable Mailbox 16 For Receive */
+#define MD17 0x0002 /* Enable Mailbox 17 For Receive */
+#define MD18 0x0004 /* Enable Mailbox 18 For Receive */
+#define MD19 0x0008 /* Enable Mailbox 19 For Receive */
+#define MD20 0x0010 /* Enable Mailbox 20 For Receive */
+#define MD21 0x0020 /* Enable Mailbox 21 For Receive */
+#define MD22 0x0040 /* Enable Mailbox 22 For Receive */
+#define MD23 0x0080 /* Enable Mailbox 23 For Receive */
+#define MD24 0x0100 /* Enable Mailbox 24 For Receive */
+#define MD25 0x0200 /* Enable Mailbox 25 For Receive */
+#define MD26 0x0400 /* Enable Mailbox 26 For Receive */
+#define MD27 0x0800 /* Enable Mailbox 27 For Receive */
+#define MD28 0x1000 /* Enable Mailbox 28 For Receive */
+#define MD29 0x2000 /* Enable Mailbox 29 For Receive */
+#define MD30 0x4000 /* Enable Mailbox 30 For Receive */
+#define MD31 0x8000 /* Enable Mailbox 31 For Receive */
+
+/* CAN_RMP1 Masks */
+#define RMP0 0x0001 /* RX Message Pending In Mailbox 0 */
+#define RMP1 0x0002 /* RX Message Pending In Mailbox 1 */
+#define RMP2 0x0004 /* RX Message Pending In Mailbox 2 */
+#define RMP3 0x0008 /* RX Message Pending In Mailbox 3 */
+#define RMP4 0x0010 /* RX Message Pending In Mailbox 4 */
+#define RMP5 0x0020 /* RX Message Pending In Mailbox 5 */
+#define RMP6 0x0040 /* RX Message Pending In Mailbox 6 */
+#define RMP7 0x0080 /* RX Message Pending In Mailbox 7 */
+#define RMP8 0x0100 /* RX Message Pending In Mailbox 8 */
+#define RMP9 0x0200 /* RX Message Pending In Mailbox 9 */
+#define RMP10 0x0400 /* RX Message Pending In Mailbox 10 */
+#define RMP11 0x0800 /* RX Message Pending In Mailbox 11 */
+#define RMP12 0x1000 /* RX Message Pending In Mailbox 12 */
+#define RMP13 0x2000 /* RX Message Pending In Mailbox 13 */
+#define RMP14 0x4000 /* RX Message Pending In Mailbox 14 */
+#define RMP15 0x8000 /* RX Message Pending In Mailbox 15 */
+
+/* CAN_RMP2 Masks */
+#define RMP16 0x0001 /* RX Message Pending In Mailbox 16 */
+#define RMP17 0x0002 /* RX Message Pending In Mailbox 17 */
+#define RMP18 0x0004 /* RX Message Pending In Mailbox 18 */
+#define RMP19 0x0008 /* RX Message Pending In Mailbox 19 */
+#define RMP20 0x0010 /* RX Message Pending In Mailbox 20 */
+#define RMP21 0x0020 /* RX Message Pending In Mailbox 21 */
+#define RMP22 0x0040 /* RX Message Pending In Mailbox 22 */
+#define RMP23 0x0080 /* RX Message Pending In Mailbox 23 */
+#define RMP24 0x0100 /* RX Message Pending In Mailbox 24 */
+#define RMP25 0x0200 /* RX Message Pending In Mailbox 25 */
+#define RMP26 0x0400 /* RX Message Pending In Mailbox 26 */
+#define RMP27 0x0800 /* RX Message Pending In Mailbox 27 */
+#define RMP28 0x1000 /* RX Message Pending In Mailbox 28 */
+#define RMP29 0x2000 /* RX Message Pending In Mailbox 29 */
+#define RMP30 0x4000 /* RX Message Pending In Mailbox 30 */
+#define RMP31 0x8000 /* RX Message Pending In Mailbox 31 */
+
+/* CAN_RML1 Masks */
+#define RML0 0x0001 /* RX Message Lost In Mailbox 0 */
+#define RML1 0x0002 /* RX Message Lost In Mailbox 1 */
+#define RML2 0x0004 /* RX Message Lost In Mailbox 2 */
+#define RML3 0x0008 /* RX Message Lost In Mailbox 3 */
+#define RML4 0x0010 /* RX Message Lost In Mailbox 4 */
+#define RML5 0x0020 /* RX Message Lost In Mailbox 5 */
+#define RML6 0x0040 /* RX Message Lost In Mailbox 6 */
+#define RML7 0x0080 /* RX Message Lost In Mailbox 7 */
+#define RML8 0x0100 /* RX Message Lost In Mailbox 8 */
+#define RML9 0x0200 /* RX Message Lost In Mailbox 9 */
+#define RML10 0x0400 /* RX Message Lost In Mailbox 10 */
+#define RML11 0x0800 /* RX Message Lost In Mailbox 11 */
+#define RML12 0x1000 /* RX Message Lost In Mailbox 12 */
+#define RML13 0x2000 /* RX Message Lost In Mailbox 13 */
+#define RML14 0x4000 /* RX Message Lost In Mailbox 14 */
+#define RML15 0x8000 /* RX Message Lost In Mailbox 15 */
+
+/* CAN_RML2 Masks */
+#define RML16 0x0001 /* RX Message Lost In Mailbox 16 */
+#define RML17 0x0002 /* RX Message Lost In Mailbox 17 */
+#define RML18 0x0004 /* RX Message Lost In Mailbox 18 */
+#define RML19 0x0008 /* RX Message Lost In Mailbox 19 */
+#define RML20 0x0010 /* RX Message Lost In Mailbox 20 */
+#define RML21 0x0020 /* RX Message Lost In Mailbox 21 */
+#define RML22 0x0040 /* RX Message Lost In Mailbox 22 */
+#define RML23 0x0080 /* RX Message Lost In Mailbox 23 */
+#define RML24 0x0100 /* RX Message Lost In Mailbox 24 */
+#define RML25 0x0200 /* RX Message Lost In Mailbox 25 */
+#define RML26 0x0400 /* RX Message Lost In Mailbox 26 */
+#define RML27 0x0800 /* RX Message Lost In Mailbox 27 */
+#define RML28 0x1000 /* RX Message Lost In Mailbox 28 */
+#define RML29 0x2000 /* RX Message Lost In Mailbox 29 */
+#define RML30 0x4000 /* RX Message Lost In Mailbox 30 */
+#define RML31 0x8000 /* RX Message Lost In Mailbox 31 */
+
+/* CAN_OPSS1 Masks */
+#define OPSS0 0x0001 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 0 */
+#define OPSS1 0x0002 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 1 */
+#define OPSS2 0x0004 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 2 */
+#define OPSS3 0x0008 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 3 */
+#define OPSS4 0x0010 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 4 */
+#define OPSS5 0x0020 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 5 */
+#define OPSS6 0x0040 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 6 */
+#define OPSS7 0x0080 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 7 */
+#define OPSS8 0x0100 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 8 */
+#define OPSS9 0x0200 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 9 */
+#define OPSS10 0x0400 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 10 */
+#define OPSS11 0x0800 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 11 */
+#define OPSS12 0x1000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 12 */
+#define OPSS13 0x2000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 13 */
+#define OPSS14 0x4000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 14 */
+#define OPSS15 0x8000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 15 */
+
+/* CAN_OPSS2 Masks */
+#define OPSS16 0x0001 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 16 */
+#define OPSS17 0x0002 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 17 */
+#define OPSS18 0x0004 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 18 */
+#define OPSS19 0x0008 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 19 */
+#define OPSS20 0x0010 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 20 */
+#define OPSS21 0x0020 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 21 */
+#define OPSS22 0x0040 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 22 */
+#define OPSS23 0x0080 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 23 */
+#define OPSS24 0x0100 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 24 */
+#define OPSS25 0x0200 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 25 */
+#define OPSS26 0x0400 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 26 */
+#define OPSS27 0x0800 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 27 */
+#define OPSS28 0x1000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 28 */
+#define OPSS29 0x2000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 29 */
+#define OPSS30 0x4000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 30 */
+#define OPSS31 0x8000 /* Enable RX Overwrite Protection or TX Single-Shot For Mailbox 31 */
+
+/* CAN_TRR1 Masks */
+#define TRR0 0x0001 /* Deny But Don't Lock Access To Mailbox 0 */
+#define TRR1 0x0002 /* Deny But Don't Lock Access To Mailbox 1 */
+#define TRR2 0x0004 /* Deny But Don't Lock Access To Mailbox 2 */
+#define TRR3 0x0008 /* Deny But Don't Lock Access To Mailbox 3 */
+#define TRR4 0x0010 /* Deny But Don't Lock Access To Mailbox 4 */
+#define TRR5 0x0020 /* Deny But Don't Lock Access To Mailbox 5 */
+#define TRR6 0x0040 /* Deny But Don't Lock Access To Mailbox 6 */
+#define TRR7 0x0080 /* Deny But Don't Lock Access To Mailbox 7 */
+#define TRR8 0x0100 /* Deny But Don't Lock Access To Mailbox 8 */
+#define TRR9 0x0200 /* Deny But Don't Lock Access To Mailbox 9 */
+#define TRR10 0x0400 /* Deny But Don't Lock Access To Mailbox 10 */
+#define TRR11 0x0800 /* Deny But Don't Lock Access To Mailbox 11 */
+#define TRR12 0x1000 /* Deny But Don't Lock Access To Mailbox 12 */
+#define TRR13 0x2000 /* Deny But Don't Lock Access To Mailbox 13 */
+#define TRR14 0x4000 /* Deny But Don't Lock Access To Mailbox 14 */
+#define TRR15 0x8000 /* Deny But Don't Lock Access To Mailbox 15 */
+
+/* CAN_TRR2 Masks */
+#define TRR16 0x0001 /* Deny But Don't Lock Access To Mailbox 16 */
+#define TRR17 0x0002 /* Deny But Don't Lock Access To Mailbox 17 */
+#define TRR18 0x0004 /* Deny But Don't Lock Access To Mailbox 18 */
+#define TRR19 0x0008 /* Deny But Don't Lock Access To Mailbox 19 */
+#define TRR20 0x0010 /* Deny But Don't Lock Access To Mailbox 20 */
+#define TRR21 0x0020 /* Deny But Don't Lock Access To Mailbox 21 */
+#define TRR22 0x0040 /* Deny But Don't Lock Access To Mailbox 22 */
+#define TRR23 0x0080 /* Deny But Don't Lock Access To Mailbox 23 */
+#define TRR24 0x0100 /* Deny But Don't Lock Access To Mailbox 24 */
+#define TRR25 0x0200 /* Deny But Don't Lock Access To Mailbox 25 */
+#define TRR26 0x0400 /* Deny But Don't Lock Access To Mailbox 26 */
+#define TRR27 0x0800 /* Deny But Don't Lock Access To Mailbox 27 */
+#define TRR28 0x1000 /* Deny But Don't Lock Access To Mailbox 28 */
+#define TRR29 0x2000 /* Deny But Don't Lock Access To Mailbox 29 */
+#define TRR30 0x4000 /* Deny But Don't Lock Access To Mailbox 30 */
+#define TRR31 0x8000 /* Deny But Don't Lock Access To Mailbox 31 */
+
+/* CAN_TRS1 Masks */
+#define TRS0 0x0001 /* Remote Frame Request For Mailbox 0 */
+#define TRS1 0x0002 /* Remote Frame Request For Mailbox 1 */
+#define TRS2 0x0004 /* Remote Frame Request For Mailbox 2 */
+#define TRS3 0x0008 /* Remote Frame Request For Mailbox 3 */
+#define TRS4 0x0010 /* Remote Frame Request For Mailbox 4 */
+#define TRS5 0x0020 /* Remote Frame Request For Mailbox 5 */
+#define TRS6 0x0040 /* Remote Frame Request For Mailbox 6 */
+#define TRS7 0x0080 /* Remote Frame Request For Mailbox 7 */
+#define TRS8 0x0100 /* Remote Frame Request For Mailbox 8 */
+#define TRS9 0x0200 /* Remote Frame Request For Mailbox 9 */
+#define TRS10 0x0400 /* Remote Frame Request For Mailbox 10 */
+#define TRS11 0x0800 /* Remote Frame Request For Mailbox 11 */
+#define TRS12 0x1000 /* Remote Frame Request For Mailbox 12 */
+#define TRS13 0x2000 /* Remote Frame Request For Mailbox 13 */
+#define TRS14 0x4000 /* Remote Frame Request For Mailbox 14 */
+#define TRS15 0x8000 /* Remote Frame Request For Mailbox 15 */
+
+/* CAN_TRS2 Masks */
+#define TRS16 0x0001 /* Remote Frame Request For Mailbox 16 */
+#define TRS17 0x0002 /* Remote Frame Request For Mailbox 17 */
+#define TRS18 0x0004 /* Remote Frame Request For Mailbox 18 */
+#define TRS19 0x0008 /* Remote Frame Request For Mailbox 19 */
+#define TRS20 0x0010 /* Remote Frame Request For Mailbox 20 */
+#define TRS21 0x0020 /* Remote Frame Request For Mailbox 21 */
+#define TRS22 0x0040 /* Remote Frame Request For Mailbox 22 */
+#define TRS23 0x0080 /* Remote Frame Request For Mailbox 23 */
+#define TRS24 0x0100 /* Remote Frame Request For Mailbox 24 */
+#define TRS25 0x0200 /* Remote Frame Request For Mailbox 25 */
+#define TRS26 0x0400 /* Remote Frame Request For Mailbox 26 */
+#define TRS27 0x0800 /* Remote Frame Request For Mailbox 27 */
+#define TRS28 0x1000 /* Remote Frame Request For Mailbox 28 */
+#define TRS29 0x2000 /* Remote Frame Request For Mailbox 29 */
+#define TRS30 0x4000 /* Remote Frame Request For Mailbox 30 */
+#define TRS31 0x8000 /* Remote Frame Request For Mailbox 31 */
+
+/* CAN_AA1 Masks */
+#define AA0 0x0001 /* Aborted Message In Mailbox 0 */
+#define AA1 0x0002 /* Aborted Message In Mailbox 1 */
+#define AA2 0x0004 /* Aborted Message In Mailbox 2 */
+#define AA3 0x0008 /* Aborted Message In Mailbox 3 */
+#define AA4 0x0010 /* Aborted Message In Mailbox 4 */
+#define AA5 0x0020 /* Aborted Message In Mailbox 5 */
+#define AA6 0x0040 /* Aborted Message In Mailbox 6 */
+#define AA7 0x0080 /* Aborted Message In Mailbox 7 */
+#define AA8 0x0100 /* Aborted Message In Mailbox 8 */
+#define AA9 0x0200 /* Aborted Message In Mailbox 9 */
+#define AA10 0x0400 /* Aborted Message In Mailbox 10 */
+#define AA11 0x0800 /* Aborted Message In Mailbox 11 */
+#define AA12 0x1000 /* Aborted Message In Mailbox 12 */
+#define AA13 0x2000 /* Aborted Message In Mailbox 13 */
+#define AA14 0x4000 /* Aborted Message In Mailbox 14 */
+#define AA15 0x8000 /* Aborted Message In Mailbox 15 */
+
+/* CAN_AA2 Masks */
+#define AA16 0x0001 /* Aborted Message In Mailbox 16 */
+#define AA17 0x0002 /* Aborted Message In Mailbox 17 */
+#define AA18 0x0004 /* Aborted Message In Mailbox 18 */
+#define AA19 0x0008 /* Aborted Message In Mailbox 19 */
+#define AA20 0x0010 /* Aborted Message In Mailbox 20 */
+#define AA21 0x0020 /* Aborted Message In Mailbox 21 */
+#define AA22 0x0040 /* Aborted Message In Mailbox 22 */
+#define AA23 0x0080 /* Aborted Message In Mailbox 23 */
+#define AA24 0x0100 /* Aborted Message In Mailbox 24 */
+#define AA25 0x0200 /* Aborted Message In Mailbox 25 */
+#define AA26 0x0400 /* Aborted Message In Mailbox 26 */
+#define AA27 0x0800 /* Aborted Message In Mailbox 27 */
+#define AA28 0x1000 /* Aborted Message In Mailbox 28 */
+#define AA29 0x2000 /* Aborted Message In Mailbox 29 */
+#define AA30 0x4000 /* Aborted Message In Mailbox 30 */
+#define AA31 0x8000 /* Aborted Message In Mailbox 31 */
+
+/* CAN_TA1 Masks */
+#define TA0 0x0001 /* Transmit Successful From Mailbox 0 */
+#define TA1 0x0002 /* Transmit Successful From Mailbox 1 */
+#define TA2 0x0004 /* Transmit Successful From Mailbox 2 */
+#define TA3 0x0008 /* Transmit Successful From Mailbox 3 */
+#define TA4 0x0010 /* Transmit Successful From Mailbox 4 */
+#define TA5 0x0020 /* Transmit Successful From Mailbox 5 */
+#define TA6 0x0040 /* Transmit Successful From Mailbox 6 */
+#define TA7 0x0080 /* Transmit Successful From Mailbox 7 */
+#define TA8 0x0100 /* Transmit Successful From Mailbox 8 */
+#define TA9 0x0200 /* Transmit Successful From Mailbox 9 */
+#define TA10 0x0400 /* Transmit Successful From Mailbox 10 */
+#define TA11 0x0800 /* Transmit Successful From Mailbox 11 */
+#define TA12 0x1000 /* Transmit Successful From Mailbox 12 */
+#define TA13 0x2000 /* Transmit Successful From Mailbox 13 */
+#define TA14 0x4000 /* Transmit Successful From Mailbox 14 */
+#define TA15 0x8000 /* Transmit Successful From Mailbox 15 */
+
+/* CAN_TA2 Masks */
+#define TA16 0x0001 /* Transmit Successful From Mailbox 16 */
+#define TA17 0x0002 /* Transmit Successful From Mailbox 17 */
+#define TA18 0x0004 /* Transmit Successful From Mailbox 18 */
+#define TA19 0x0008 /* Transmit Successful From Mailbox 19 */
+#define TA20 0x0010 /* Transmit Successful From Mailbox 20 */
+#define TA21 0x0020 /* Transmit Successful From Mailbox 21 */
+#define TA22 0x0040 /* Transmit Successful From Mailbox 22 */
+#define TA23 0x0080 /* Transmit Successful From Mailbox 23 */
+#define TA24 0x0100 /* Transmit Successful From Mailbox 24 */
+#define TA25 0x0200 /* Transmit Successful From Mailbox 25 */
+#define TA26 0x0400 /* Transmit Successful From Mailbox 26 */
+#define TA27 0x0800 /* Transmit Successful From Mailbox 27 */
+#define TA28 0x1000 /* Transmit Successful From Mailbox 28 */
+#define TA29 0x2000 /* Transmit Successful From Mailbox 29 */
+#define TA30 0x4000 /* Transmit Successful From Mailbox 30 */
+#define TA31 0x8000 /* Transmit Successful From Mailbox 31 */
+
+/* CAN_MBTD Masks */
+#define TDPTR 0x001F /* Mailbox To Temporarily Disable */
+#define TDA 0x0040 /* Temporary Disable Acknowledge */
+#define TDR 0x0080 /* Temporary Disable Request */
+
+/* CAN_RFH1 Masks */
+#define RFH0 0x0001 /* Enable Automatic Remote Frame Handling For Mailbox 0 */
+#define RFH1 0x0002 /* Enable Automatic Remote Frame Handling For Mailbox 1 */
+#define RFH2 0x0004 /* Enable Automatic Remote Frame Handling For Mailbox 2 */
+#define RFH3 0x0008 /* Enable Automatic Remote Frame Handling For Mailbox 3 */
+#define RFH4 0x0010 /* Enable Automatic Remote Frame Handling For Mailbox 4 */
+#define RFH5 0x0020 /* Enable Automatic Remote Frame Handling For Mailbox 5 */
+#define RFH6 0x0040 /* Enable Automatic Remote Frame Handling For Mailbox 6 */
+#define RFH7 0x0080 /* Enable Automatic Remote Frame Handling For Mailbox 7 */
+#define RFH8 0x0100 /* Enable Automatic Remote Frame Handling For Mailbox 8 */
+#define RFH9 0x0200 /* Enable Automatic Remote Frame Handling For Mailbox 9 */
+#define RFH10 0x0400 /* Enable Automatic Remote Frame Handling For Mailbox 10 */
+#define RFH11 0x0800 /* Enable Automatic Remote Frame Handling For Mailbox 11 */
+#define RFH12 0x1000 /* Enable Automatic Remote Frame Handling For Mailbox 12 */
+#define RFH13 0x2000 /* Enable Automatic Remote Frame Handling For Mailbox 13 */
+#define RFH14 0x4000 /* Enable Automatic Remote Frame Handling For Mailbox 14 */
+#define RFH15 0x8000 /* Enable Automatic Remote Frame Handling For Mailbox 15 */
+
+/* CAN_RFH2 Masks */
+#define RFH16 0x0001 /* Enable Automatic Remote Frame Handling For Mailbox 16 */
+#define RFH17 0x0002 /* Enable Automatic Remote Frame Handling For Mailbox 17 */
+#define RFH18 0x0004 /* Enable Automatic Remote Frame Handling For Mailbox 18 */
+#define RFH19 0x0008 /* Enable Automatic Remote Frame Handling For Mailbox 19 */
+#define RFH20 0x0010 /* Enable Automatic Remote Frame Handling For Mailbox 20 */
+#define RFH21 0x0020 /* Enable Automatic Remote Frame Handling For Mailbox 21 */
+#define RFH22 0x0040 /* Enable Automatic Remote Frame Handling For Mailbox 22 */
+#define RFH23 0x0080 /* Enable Automatic Remote Frame Handling For Mailbox 23 */
+#define RFH24 0x0100 /* Enable Automatic Remote Frame Handling For Mailbox 24 */
+#define RFH25 0x0200 /* Enable Automatic Remote Frame Handling For Mailbox 25 */
+#define RFH26 0x0400 /* Enable Automatic Remote Frame Handling For Mailbox 26 */
+#define RFH27 0x0800 /* Enable Automatic Remote Frame Handling For Mailbox 27 */
+#define RFH28 0x1000 /* Enable Automatic Remote Frame Handling For Mailbox 28 */
+#define RFH29 0x2000 /* Enable Automatic Remote Frame Handling For Mailbox 29 */
+#define RFH30 0x4000 /* Enable Automatic Remote Frame Handling For Mailbox 30 */
+#define RFH31 0x8000 /* Enable Automatic Remote Frame Handling For Mailbox 31 */
+
+/* CAN_MBTIF1 Masks */
+#define MBTIF0 0x0001 /* TX Interrupt Active In Mailbox 0 */
+#define MBTIF1 0x0002 /* TX Interrupt Active In Mailbox 1 */
+#define MBTIF2 0x0004 /* TX Interrupt Active In Mailbox 2 */
+#define MBTIF3 0x0008 /* TX Interrupt Active In Mailbox 3 */
+#define MBTIF4 0x0010 /* TX Interrupt Active In Mailbox 4 */
+#define MBTIF5 0x0020 /* TX Interrupt Active In Mailbox 5 */
+#define MBTIF6 0x0040 /* TX Interrupt Active In Mailbox 6 */
+#define MBTIF7 0x0080 /* TX Interrupt Active In Mailbox 7 */
+#define MBTIF8 0x0100 /* TX Interrupt Active In Mailbox 8 */
+#define MBTIF9 0x0200 /* TX Interrupt Active In Mailbox 9 */
+#define MBTIF10 0x0400 /* TX Interrupt Active In Mailbox 10 */
+#define MBTIF11 0x0800 /* TX Interrupt Active In Mailbox 11 */
+#define MBTIF12 0x1000 /* TX Interrupt Active In Mailbox 12 */
+#define MBTIF13 0x2000 /* TX Interrupt Active In Mailbox 13 */
+#define MBTIF14 0x4000 /* TX Interrupt Active In Mailbox 14 */
+#define MBTIF15 0x8000 /* TX Interrupt Active In Mailbox 15 */
+
+/* CAN_MBTIF2 Masks */
+#define MBTIF16 0x0001 /* TX Interrupt Active In Mailbox 16 */
+#define MBTIF17 0x0002 /* TX Interrupt Active In Mailbox 17 */
+#define MBTIF18 0x0004 /* TX Interrupt Active In Mailbox 18 */
+#define MBTIF19 0x0008 /* TX Interrupt Active In Mailbox 19 */
+#define MBTIF20 0x0010 /* TX Interrupt Active In Mailbox 20 */
+#define MBTIF21 0x0020 /* TX Interrupt Active In Mailbox 21 */
+#define MBTIF22 0x0040 /* TX Interrupt Active In Mailbox 22 */
+#define MBTIF23 0x0080 /* TX Interrupt Active In Mailbox 23 */
+#define MBTIF24 0x0100 /* TX Interrupt Active In Mailbox 24 */
+#define MBTIF25 0x0200 /* TX Interrupt Active In Mailbox 25 */
+#define MBTIF26 0x0400 /* TX Interrupt Active In Mailbox 26 */
+#define MBTIF27 0x0800 /* TX Interrupt Active In Mailbox 27 */
+#define MBTIF28 0x1000 /* TX Interrupt Active In Mailbox 28 */
+#define MBTIF29 0x2000 /* TX Interrupt Active In Mailbox 29 */
+#define MBTIF30 0x4000 /* TX Interrupt Active In Mailbox 30 */
+#define MBTIF31 0x8000 /* TX Interrupt Active In Mailbox 31 */
+
+/* CAN_MBRIF1 Masks */
+#define MBRIF0 0x0001 /* RX Interrupt Active In Mailbox 0 */
+#define MBRIF1 0x0002 /* RX Interrupt Active In Mailbox 1 */
+#define MBRIF2 0x0004 /* RX Interrupt Active In Mailbox 2 */
+#define MBRIF3 0x0008 /* RX Interrupt Active In Mailbox 3 */
+#define MBRIF4 0x0010 /* RX Interrupt Active In Mailbox 4 */
+#define MBRIF5 0x0020 /* RX Interrupt Active In Mailbox 5 */
+#define MBRIF6 0x0040 /* RX Interrupt Active In Mailbox 6 */
+#define MBRIF7 0x0080 /* RX Interrupt Active In Mailbox 7 */
+#define MBRIF8 0x0100 /* RX Interrupt Active In Mailbox 8 */
+#define MBRIF9 0x0200 /* RX Interrupt Active In Mailbox 9 */
+#define MBRIF10 0x0400 /* RX Interrupt Active In Mailbox 10 */
+#define MBRIF11 0x0800 /* RX Interrupt Active In Mailbox 11 */
+#define MBRIF12 0x1000 /* RX Interrupt Active In Mailbox 12 */
+#define MBRIF13 0x2000 /* RX Interrupt Active In Mailbox 13 */
+#define MBRIF14 0x4000 /* RX Interrupt Active In Mailbox 14 */
+#define MBRIF15 0x8000 /* RX Interrupt Active In Mailbox 15 */
+
+/* CAN_MBRIF2 Masks */
+#define MBRIF16 0x0001 /* RX Interrupt Active In Mailbox 16 */
+#define MBRIF17 0x0002 /* RX Interrupt Active In Mailbox 17 */
+#define MBRIF18 0x0004 /* RX Interrupt Active In Mailbox 18 */
+#define MBRIF19 0x0008 /* RX Interrupt Active In Mailbox 19 */
+#define MBRIF20 0x0010 /* RX Interrupt Active In Mailbox 20 */
+#define MBRIF21 0x0020 /* RX Interrupt Active In Mailbox 21 */
+#define MBRIF22 0x0040 /* RX Interrupt Active In Mailbox 22 */
+#define MBRIF23 0x0080 /* RX Interrupt Active In Mailbox 23 */
+#define MBRIF24 0x0100 /* RX Interrupt Active In Mailbox 24 */
+#define MBRIF25 0x0200 /* RX Interrupt Active In Mailbox 25 */
+#define MBRIF26 0x0400 /* RX Interrupt Active In Mailbox 26 */
+#define MBRIF27 0x0800 /* RX Interrupt Active In Mailbox 27 */
+#define MBRIF28 0x1000 /* RX Interrupt Active In Mailbox 28 */
+#define MBRIF29 0x2000 /* RX Interrupt Active In Mailbox 29 */
+#define MBRIF30 0x4000 /* RX Interrupt Active In Mailbox 30 */
+#define MBRIF31 0x8000 /* RX Interrupt Active In Mailbox 31 */
+
+/* CAN_MBIM1 Masks */
+#define MBIM0 0x0001 /* Enable Interrupt For Mailbox 0 */
+#define MBIM1 0x0002 /* Enable Interrupt For Mailbox 1 */
+#define MBIM2 0x0004 /* Enable Interrupt For Mailbox 2 */
+#define MBIM3 0x0008 /* Enable Interrupt For Mailbox 3 */
+#define MBIM4 0x0010 /* Enable Interrupt For Mailbox 4 */
+#define MBIM5 0x0020 /* Enable Interrupt For Mailbox 5 */
+#define MBIM6 0x0040 /* Enable Interrupt For Mailbox 6 */
+#define MBIM7 0x0080 /* Enable Interrupt For Mailbox 7 */
+#define MBIM8 0x0100 /* Enable Interrupt For Mailbox 8 */
+#define MBIM9 0x0200 /* Enable Interrupt For Mailbox 9 */
+#define MBIM10 0x0400 /* Enable Interrupt For Mailbox 10 */
+#define MBIM11 0x0800 /* Enable Interrupt For Mailbox 11 */
+#define MBIM12 0x1000 /* Enable Interrupt For Mailbox 12 */
+#define MBIM13 0x2000 /* Enable Interrupt For Mailbox 13 */
+#define MBIM14 0x4000 /* Enable Interrupt For Mailbox 14 */
+#define MBIM15 0x8000 /* Enable Interrupt For Mailbox 15 */
+
+/* CAN_MBIM2 Masks */
+#define MBIM16 0x0001 /* Enable Interrupt For Mailbox 16 */
+#define MBIM17 0x0002 /* Enable Interrupt For Mailbox 17 */
+#define MBIM18 0x0004 /* Enable Interrupt For Mailbox 18 */
+#define MBIM19 0x0008 /* Enable Interrupt For Mailbox 19 */
+#define MBIM20 0x0010 /* Enable Interrupt For Mailbox 20 */
+#define MBIM21 0x0020 /* Enable Interrupt For Mailbox 21 */
+#define MBIM22 0x0040 /* Enable Interrupt For Mailbox 22 */
+#define MBIM23 0x0080 /* Enable Interrupt For Mailbox 23 */
+#define MBIM24 0x0100 /* Enable Interrupt For Mailbox 24 */
+#define MBIM25 0x0200 /* Enable Interrupt For Mailbox 25 */
+#define MBIM26 0x0400 /* Enable Interrupt For Mailbox 26 */
+#define MBIM27 0x0800 /* Enable Interrupt For Mailbox 27 */
+#define MBIM28 0x1000 /* Enable Interrupt For Mailbox 28 */
+#define MBIM29 0x2000 /* Enable Interrupt For Mailbox 29 */
+#define MBIM30 0x4000 /* Enable Interrupt For Mailbox 30 */
+#define MBIM31 0x8000 /* Enable Interrupt For Mailbox 31 */
+
+/* CAN_GIM Masks */
+#define EWTIM 0x0001 /* Enable TX Error Count Interrupt */
+#define EWRIM 0x0002 /* Enable RX Error Count Interrupt */
+#define EPIM 0x0004 /* Enable Error-Passive Mode Interrupt */
+#define BOIM 0x0008 /* Enable Bus Off Interrupt */
+#define WUIM 0x0010 /* Enable Wake-Up Interrupt */
+#define UIAIM 0x0020 /* Enable Access To Unimplemented Address Interrupt */
+#define AAIM 0x0040 /* Enable Abort Acknowledge Interrupt */
+#define RMLIM 0x0080 /* Enable RX Message Lost Interrupt */
+#define UCEIM 0x0100 /* Enable Universal Counter Overflow Interrupt */
+#define EXTIM 0x0200 /* Enable External Trigger Output Interrupt */
+#define ADIM 0x0400 /* Enable Access Denied Interrupt */
+
+/* CAN_GIS Masks */
+#define EWTIS 0x0001 /* TX Error Count IRQ Status */
+#define EWRIS 0x0002 /* RX Error Count IRQ Status */
+#define EPIS 0x0004 /* Error-Passive Mode IRQ Status */
+#define BOIS 0x0008 /* Bus Off IRQ Status */
+#define WUIS 0x0010 /* Wake-Up IRQ Status */
+#define UIAIS 0x0020 /* Access To Unimplemented Address IRQ Status */
+#define AAIS 0x0040 /* Abort Acknowledge IRQ Status */
+#define RMLIS 0x0080 /* RX Message Lost IRQ Status */
+#define UCEIS 0x0100 /* Universal Counter Overflow IRQ Status */
+#define EXTIS 0x0200 /* External Trigger Output IRQ Status */
+#define ADIS 0x0400 /* Access Denied IRQ Status */
+
+/* CAN_GIF Masks */
+#define EWTIF 0x0001 /* TX Error Count IRQ Flag */
+#define EWRIF 0x0002 /* RX Error Count IRQ Flag */
+#define EPIF 0x0004 /* Error-Passive Mode IRQ Flag */
+#define BOIF 0x0008 /* Bus Off IRQ Flag */
+#define WUIF 0x0010 /* Wake-Up IRQ Flag */
+#define UIAIF 0x0020 /* Access To Unimplemented Address IRQ Flag */
+#define AAIF 0x0040 /* Abort Acknowledge IRQ Flag */
+#define RMLIF 0x0080 /* RX Message Lost IRQ Flag */
+#define UCEIF 0x0100 /* Universal Counter Overflow IRQ Flag */
+#define EXTIF 0x0200 /* External Trigger Output IRQ Flag */
+#define ADIF 0x0400 /* Access Denied IRQ Flag */
+
+/* CAN_UCCNF Masks */
+#define UCCNF 0x000F /* Universal Counter Mode */
+#define UC_STAMP 0x0001 /* Timestamp Mode */
+#define UC_WDOG 0x0002 /* Watchdog Mode */
+#define UC_AUTOTX 0x0003 /* Auto-Transmit Mode */
+#define UC_ERROR 0x0006 /* CAN Error Frame Count */
+#define UC_OVER 0x0007 /* CAN Overload Frame Count */
+#define UC_LOST 0x0008 /* Arbitration Lost During TX Count */
+#define UC_AA 0x0009 /* TX Abort Count */
+#define UC_TA 0x000A /* TX Successful Count */
+#define UC_REJECT 0x000B /* RX Message Rejected Count */
+#define UC_RML 0x000C /* RX Message Lost Count */
+#define UC_RX 0x000D /* Total Successful RX Messages Count */
+#define UC_RMP 0x000E /* Successful RX W/Matching ID Count */
+#define UC_ALL 0x000F /* Correct Message On CAN Bus Line Count */
+#define UCRC 0x0020 /* Universal Counter Reload/Clear */
+#define UCCT 0x0040 /* Universal Counter CAN Trigger */
+#define UCE 0x0080 /* Universal Counter Enable */
+
+/* CAN_ESR Masks */
+#define ACKE 0x0004 /* Acknowledge Error */
+#define SER 0x0008 /* Stuff Error */
+#define CRCE 0x0010 /* CRC Error */
+#define SA0 0x0020 /* Stuck At Dominant Error */
+#define BEF 0x0040 /* Bit Error Flag */
+#define FER 0x0080 /* Form Error Flag */
+
+/* CAN_EWR Masks */
+#define EWLREC 0x00FF /* RX Error Count Limit (For EWRIS) */
+#define EWLTEC 0xFF00 /* TX Error Count Limit (For EWTIS) */
+
+#endif /* _DEF_BF539_H */
diff --git a/arch/blackfin/mach-bf538/include/mach/dma.h b/arch/blackfin/mach-bf538/include/mach/dma.h
new file mode 100644
index 000000000000..eb05cacbf4d3
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/dma.h
@@ -0,0 +1,41 @@
+/* mach/dma.h - arch-specific DMA defines
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define CH_PPI 0
+#define CH_SPORT0_RX 1
+#define CH_SPORT0_TX 2
+#define CH_SPORT1_RX 3
+#define CH_SPORT1_TX 4
+#define CH_SPI0 5
+#define CH_UART0_RX 6
+#define CH_UART0_TX 7
+#define CH_SPORT2_RX 8
+#define CH_SPORT2_TX 9
+#define CH_SPORT3_RX 10
+#define CH_SPORT3_TX 11
+#define CH_SPI1 14
+#define CH_SPI2 15
+#define CH_UART1_RX 16
+#define CH_UART1_TX 17
+#define CH_UART2_RX 18
+#define CH_UART2_TX 19
+
+#define CH_MEM_STREAM0_DEST 20
+#define CH_MEM_STREAM0_SRC 21
+#define CH_MEM_STREAM1_DEST 22
+#define CH_MEM_STREAM1_SRC 23
+#define CH_MEM_STREAM2_DEST 24
+#define CH_MEM_STREAM2_SRC 25
+#define CH_MEM_STREAM3_DEST 26
+#define CH_MEM_STREAM3_SRC 27
+
+#define MAX_DMA_CHANNELS 28
+
+#endif
diff --git a/arch/blackfin/mach-bf538/include/mach/gpio.h b/arch/blackfin/mach-bf538/include/mach/gpio.h
new file mode 100644
index 000000000000..30f4f723f7cc
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/gpio.h
@@ -0,0 +1,79 @@
+/*
+ * File: arch/blackfin/mach-bf538/include/mach/gpio.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+
+#ifndef _MACH_GPIO_H_
+#define _MACH_GPIO_H_
+
+ /* FIXME:
+ * For now only support PORTF GPIOs.
+ * PORT C,D and E are for peripheral usage only
+ */
+#define MAX_BLACKFIN_GPIOS 16
+
+#define GPIO_PF0 0 /* PF */
+#define GPIO_PF1 1
+#define GPIO_PF2 2
+#define GPIO_PF3 3
+#define GPIO_PF4 4
+#define GPIO_PF5 5
+#define GPIO_PF6 6
+#define GPIO_PF7 7
+#define GPIO_PF8 8
+#define GPIO_PF9 9
+#define GPIO_PF10 10
+#define GPIO_PF11 11
+#define GPIO_PF12 12
+#define GPIO_PF13 13
+#define GPIO_PF14 14
+#define GPIO_PF15 15
+#define GPIO_PC0 16 /* PC */
+#define GPIO_PC1 17
+#define GPIO_PC4 20
+#define GPIO_PC5 21
+#define GPIO_PC6 22
+#define GPIO_PC7 23
+#define GPIO_PC8 24
+#define GPIO_PC9 25
+#define GPIO_PD0 32 /* PD */
+#define GPIO_PD1 33
+#define GPIO_PD2 34
+#define GPIO_PD3 35
+#define GPIO_PD4 36
+#define GPIO_PD5 37
+#define GPIO_PD6 38
+#define GPIO_PD7 39
+#define GPIO_PD8 40
+#define GPIO_PD9 41
+#define GPIO_PD10 42
+#define GPIO_PD11 43
+#define GPIO_PD12 44
+#define GPIO_PD13 45
+#define GPIO_PE0 48 /* PE */
+#define GPIO_PE1 49
+#define GPIO_PE2 50
+#define GPIO_PE3 51
+#define GPIO_PE4 52
+#define GPIO_PE5 53
+#define GPIO_PE6 54
+#define GPIO_PE7 55
+#define GPIO_PE8 56
+#define GPIO_PE9 57
+#define GPIO_PE10 58
+#define GPIO_PE11 59
+#define GPIO_PE12 60
+#define GPIO_PE13 61
+#define GPIO_PE14 62
+#define GPIO_PE15 63
+
+#define PORT_F GPIO_PF0
+#define PORT_C GPIO_PC0
+#define PORT_D GPIO_PD0
+#define PORT_E GPIO_PE0
+
+#endif /* _MACH_GPIO_H_ */
diff --git a/arch/blackfin/mach-bf538/include/mach/irq.h b/arch/blackfin/mach-bf538/include/mach/irq.h
new file mode 100644
index 000000000000..fdc87fe2c174
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/irq.h
@@ -0,0 +1,211 @@
+/*
+ * file: include/asm-blackfin/mach-bf538/irq.h
+ * based on: include/asm-blackfin/mach-bf537/irq.h
+ * author: Michael Hennerich (michael.hennerich@analog.com)
+ *
+ * created:
+ * description:
+ * system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.org/
+ *
+ * this program is free software; you can redistribute it and/or modify
+ * it under the terms of the gnu general public license as published by
+ * the free software foundation; either version 2, 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; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _BF538_IRQ_H_
+#define _BF538_IRQ_H_
+
+/*
+ * Interrupt source definitions
+ Event Source Core Event Name
+ Core Emulation **
+ Events (highest priority) EMU 0
+ Reset RST 1
+ NMI NMI 2
+ Exception EVX 3
+ Reserved -- 4
+ Hardware Error IVHW 5
+ Core Timer IVTMR 6 *
+
+ .....
+
+ Software Interrupt 1 IVG14 31
+ Software Interrupt 2 --
+ (lowest priority) IVG15 32 *
+*/
+
+#define NR_PERI_INTS (2 * 32)
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define IRQ_EMU 0 /* Emulation */
+#define IRQ_RST 1 /* reset */
+#define IRQ_NMI 2 /* Non Maskable */
+#define IRQ_EVX 3 /* Exception */
+#define IRQ_UNUSED 4 /* - unused interrupt */
+#define IRQ_HWERR 5 /* Hardware Error */
+#define IRQ_CORETMR 6 /* Core timer */
+
+#define BFIN_IRQ(x) ((x) + 7)
+
+#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */
+#define IRQ_DMA0_ERROR BFIN_IRQ(1) /* DMA Error 0 (generic) */
+#define IRQ_PPI_ERROR BFIN_IRQ(2) /* PPI Error */
+#define IRQ_SPORT0_ERROR BFIN_IRQ(3) /* SPORT0 Status */
+#define IRQ_SPORT1_ERROR BFIN_IRQ(4) /* SPORT1 Status */
+#define IRQ_SPI0_ERROR BFIN_IRQ(5) /* SPI0 Status */
+#define IRQ_UART0_ERROR BFIN_IRQ(6) /* UART0 Status */
+#define IRQ_RTC BFIN_IRQ(7) /* RTC */
+#define IRQ_PPI BFIN_IRQ(8) /* DMA Channel 0 (PPI) */
+#define IRQ_SPORT0_RX BFIN_IRQ(9) /* DMA 1 Channel (SPORT0 RX) */
+#define IRQ_SPORT0_TX BFIN_IRQ(10) /* DMA 2 Channel (SPORT0 TX) */
+#define IRQ_SPORT1_RX BFIN_IRQ(11) /* DMA 3 Channel (SPORT1 RX) */
+#define IRQ_SPORT1_TX BFIN_IRQ(12) /* DMA 4 Channel (SPORT1 TX) */
+#define IRQ_SPI0 BFIN_IRQ(13) /* DMA 5 Channel (SPI0) */
+#define IRQ_UART0_RX BFIN_IRQ(14) /* DMA 6 Channel (UART0 RX) */
+#define IRQ_UART0_TX BFIN_IRQ(15) /* DMA 7 Channel (UART0 TX) */
+#define IRQ_TIMER0 BFIN_IRQ(16) /* Timer 0 */
+#define IRQ_TIMER1 BFIN_IRQ(17) /* Timer 1 */
+#define IRQ_TIMER2 BFIN_IRQ(18) /* Timer 2 */
+#define IRQ_PORTF_INTA BFIN_IRQ(19) /* Port F Interrupt A */
+#define IRQ_PORTF_INTB BFIN_IRQ(20) /* Port F Interrupt B */
+#define IRQ_MEM0_DMA0 BFIN_IRQ(21) /* MDMA0 Stream 0 */
+#define IRQ_MEM0_DMA1 BFIN_IRQ(22) /* MDMA0 Stream 1 */
+#define IRQ_WATCH BFIN_IRQ(23) /* Software Watchdog Timer */
+#define IRQ_DMA1_ERROR BFIN_IRQ(24) /* DMA Error 1 (generic) */
+#define IRQ_SPORT2_ERROR BFIN_IRQ(25) /* SPORT2 Status */
+#define IRQ_SPORT3_ERROR BFIN_IRQ(26) /* SPORT3 Status */
+#define IRQ_SPI1_ERROR BFIN_IRQ(28) /* SPI1 Status */
+#define IRQ_SPI2_ERROR BFIN_IRQ(29) /* SPI2 Status */
+#define IRQ_UART1_ERROR BFIN_IRQ(30) /* UART1 Status */
+#define IRQ_UART2_ERROR BFIN_IRQ(31) /* UART2 Status */
+#define IRQ_CAN_ERROR BFIN_IRQ(32) /* CAN Status (Error) Interrupt */
+#define IRQ_SPORT2_RX BFIN_IRQ(33) /* DMA 8 Channel (SPORT2 RX) */
+#define IRQ_SPORT2_TX BFIN_IRQ(34) /* DMA 9 Channel (SPORT2 TX) */
+#define IRQ_SPORT3_RX BFIN_IRQ(35) /* DMA 10 Channel (SPORT3 RX) */
+#define IRQ_SPORT3_TX BFIN_IRQ(36) /* DMA 11 Channel (SPORT3 TX) */
+#define IRQ_SPI1 BFIN_IRQ(39) /* DMA 14 Channel (SPI1) */
+#define IRQ_SPI2 BFIN_IRQ(40) /* DMA 15 Channel (SPI2) */
+#define IRQ_UART1_RX BFIN_IRQ(41) /* DMA 16 Channel (UART1 RX) */
+#define IRQ_UART1_TX BFIN_IRQ(42) /* DMA 17 Channel (UART1 TX) */
+#define IRQ_UART2_RX BFIN_IRQ(43) /* DMA 18 Channel (UART2 RX) */
+#define IRQ_UART2_TX BFIN_IRQ(44) /* DMA 19 Channel (UART2 TX) */
+#define IRQ_TWI0 BFIN_IRQ(45) /* TWI0 */
+#define IRQ_TWI1 BFIN_IRQ(46) /* TWI1 */
+#define IRQ_CAN_RX BFIN_IRQ(47) /* CAN Receive Interrupt */
+#define IRQ_CAN_TX BFIN_IRQ(48) /* CAN Transmit Interrupt */
+#define IRQ_MEM1_DMA0 BFIN_IRQ(49) /* MDMA1 Stream 0 */
+#define IRQ_MEM1_DMA1 BFIN_IRQ(50) /* MDMA1 Stream 1 */
+
+#define SYS_IRQS BFIN_IRQ(63) /* 70 */
+
+#define IRQ_PF0 71
+#define IRQ_PF1 72
+#define IRQ_PF2 73
+#define IRQ_PF3 74
+#define IRQ_PF4 75
+#define IRQ_PF5 76
+#define IRQ_PF6 77
+#define IRQ_PF7 78
+#define IRQ_PF8 79
+#define IRQ_PF9 80
+#define IRQ_PF10 81
+#define IRQ_PF11 82
+#define IRQ_PF12 83
+#define IRQ_PF13 84
+#define IRQ_PF14 85
+#define IRQ_PF15 86
+
+#define GPIO_IRQ_BASE IRQ_PF0
+
+#define NR_IRQS (IRQ_PF15+1)
+
+#define IVG7 7
+#define IVG8 8
+#define IVG9 9
+#define IVG10 10
+#define IVG11 11
+#define IVG12 12
+#define IVG13 13
+#define IVG14 14
+#define IVG15 15
+
+/* IAR0 BIT FIELDS */
+#define IRQ_PLL_WAKEUP_POS 0
+#define IRQ_DMA0_ERROR_POS 4
+#define IRQ_PPI_ERROR_POS 8
+#define IRQ_SPORT0_ERROR_POS 12
+#define IRQ_SPORT1_ERROR_POS 16
+#define IRQ_SPI0_ERROR_POS 20
+#define IRQ_UART0_ERROR_POS 24
+#define IRQ_RTC_POS 28
+
+/* IAR1 BIT FIELDS */
+#define IRQ_PPI_POS 0
+#define IRQ_SPORT0_RX_POS 4
+#define IRQ_SPORT0_TX_POS 8
+#define IRQ_SPORT1_RX_POS 12
+#define IRQ_SPORT1_TX_POS 16
+#define IRQ_SPI0_POS 20
+#define IRQ_UART0_RX_POS 24
+#define IRQ_UART0_TX_POS 28
+
+/* IAR2 BIT FIELDS */
+#define IRQ_TIMER0_POS 0
+#define IRQ_TIMER1_POS 4
+#define IRQ_TIMER2_POS 8
+#define IRQ_PORTF_INTA_POS 12
+#define IRQ_PORTF_INTB_POS 16
+#define IRQ_MEM0_DMA0_POS 20
+#define IRQ_MEM0_DMA1_POS 24
+#define IRQ_WATCH_POS 28
+
+/* IAR3 BIT FIELDS */
+#define IRQ_DMA1_ERROR_POS 0
+#define IRQ_SPORT2_ERROR_POS 4
+#define IRQ_SPORT3_ERROR_POS 8
+#define IRQ_SPI1_ERROR_POS 16
+#define IRQ_SPI2_ERROR_POS 20
+#define IRQ_UART1_ERROR_POS 24
+#define IRQ_UART2_ERROR_POS 28
+
+/* IAR4 BIT FIELDS */
+#define IRQ_CAN_ERROR_POS 0
+#define IRQ_SPORT2_RX_POS 4
+#define IRQ_SPORT2_TX_POS 8
+#define IRQ_SPORT3_RX_POS 12
+#define IRQ_SPORT3_TX_POS 16
+#define IRQ_SPI1_POS 28
+
+/* IAR5 BIT FIELDS */
+#define IRQ_SPI2_POS 0
+#define IRQ_UART1_RX_POS 4
+#define IRQ_UART1_TX_POS 8
+#define IRQ_UART2_RX_POS 12
+#define IRQ_UART2_TX_POS 16
+#define IRQ_TWI0_POS 20
+#define IRQ_TWI1_POS 24
+#define IRQ_CAN_RX_POS 28
+
+/* IAR6 BIT FIELDS */
+#define IRQ_CAN_TX_POS 0
+#define IRQ_MEM1_DMA0_POS 4
+#define IRQ_MEM1_DMA1_POS 8
+#endif /* _BF538_IRQ_H_ */
diff --git a/arch/blackfin/mach-bf538/include/mach/mem_map.h b/arch/blackfin/mach-bf538/include/mach/mem_map.h
new file mode 100644
index 000000000000..76811966690e
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/mem_map.h
@@ -0,0 +1,113 @@
+/*
+ * File: include/asm-blackfin/mach-bf538/mem_map.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MEM_MAP_538_H_
+#define _MEM_MAP_538_H_
+
+#define COREMMR_BASE 0xFFE00000 /* Core MMRs */
+#define SYSMMR_BASE 0xFFC00000 /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE 0x20300000 /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK2_BASE 0x20200000 /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK1_BASE 0x20100000 /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE 0x00100000 /* 1M */
+#define ASYNC_BANK0_BASE 0x20000000 /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE 0x00100000 /* 1M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START 0xEF000000
+#define BOOT_ROM_LENGTH 0x400
+
+/* Level 1 Memory */
+
+#ifdef CONFIG_BFIN_ICACHE
+#define BFIN_ICACHESIZE (16*1024)
+#else
+#define BFIN_ICACHESIZE (0*1024)
+#endif
+
+/* Memory Map for ADSP-BF538/9 processors */
+
+#define L1_CODE_START 0xFFA00000
+#define L1_DATA_A_START 0xFF800000
+#define L1_DATA_B_START 0xFF900000
+
+#ifdef CONFIG_BFIN_ICACHE
+#define L1_CODE_LENGTH (0x14000 - 0x4000)
+#else
+#define L1_CODE_LENGTH 0x14000
+#endif
+
+#ifdef CONFIG_BFIN_DCACHE
+
+#ifdef CONFIG_BFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE (16*1024)
+#define BFIN_DSUPBANKS 1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH (0x8000 - 0x4000)
+#define BFIN_DCACHESIZE (32*1024)
+#define BFIN_DSUPBANKS 2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH 0x8000
+#define L1_DATA_B_LENGTH 0x8000
+#define BFIN_DCACHESIZE (0*1024)
+#define BFIN_DSUPBANKS 0
+#endif /*CONFIG_BFIN_DCACHE*/
+
+
+/* Level 2 Memory - none */
+
+#define L2_START 0
+#define L2_LENGTH 0
+
+/* Scratch Pad Memory */
+
+#define L1_SCRATCH_START 0xFFB00000
+#define L1_SCRATCH_LENGTH 0x1000
+
+#define GET_PDA_SAFE(preg) \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda;
+
+#define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+
+#endif /* _MEM_MAP_538_H_ */
diff --git a/arch/blackfin/mach-bf538/include/mach/portmux.h b/arch/blackfin/mach-bf538/include/mach/portmux.h
new file mode 100644
index 000000000000..c8db264e3e4d
--- /dev/null
+++ b/arch/blackfin/mach-bf538/include/mach/portmux.h
@@ -0,0 +1,107 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define MAX_RESOURCES MAX_BLACKFIN_GPIOS
+
+#define P_TMR2 (P_DONTCARE)
+#define P_TMR1 (P_DONTCARE)
+#define P_TMR0 (P_DONTCARE)
+#define P_TMRCLK (P_DONTCARE)
+#define P_PPI0_CLK (P_DONTCARE)
+#define P_PPI0_FS1 (P_DONTCARE)
+#define P_PPI0_FS2 (P_DONTCARE)
+
+#define P_TWI0_SCL (P_DONTCARE)
+#define P_TWI0_SDA (P_DONTCARE)
+#define P_TWI1_SCL (P_DONTCARE)
+#define P_TWI1_SDA (P_DONTCARE)
+
+#define P_SPORT1_TSCLK (P_DONTCARE)
+#define P_SPORT1_RSCLK (P_DONTCARE)
+#define P_SPORT0_TSCLK (P_DONTCARE)
+#define P_SPORT0_RSCLK (P_DONTCARE)
+#define P_SPORT1_DRSEC (P_DONTCARE)
+#define P_SPORT1_RFS (P_DONTCARE)
+#define P_SPORT1_DTPRI (P_DONTCARE)
+#define P_SPORT1_DTSEC (P_DONTCARE)
+#define P_SPORT1_TFS (P_DONTCARE)
+#define P_SPORT1_DRPRI (P_DONTCARE)
+#define P_SPORT0_DRSEC (P_DONTCARE)
+#define P_SPORT0_RFS (P_DONTCARE)
+#define P_SPORT0_DTPRI (P_DONTCARE)
+#define P_SPORT0_DTSEC (P_DONTCARE)
+#define P_SPORT0_TFS (P_DONTCARE)
+#define P_SPORT0_DRPRI (P_DONTCARE)
+
+#define P_UART0_RX (P_DONTCARE)
+#define P_UART0_TX (P_DONTCARE)
+
+#define P_SPI0_MOSI (P_DONTCARE)
+#define P_SPI0_MISO (P_DONTCARE)
+#define P_SPI0_SCK (P_DONTCARE)
+
+#define P_PPI0_D0 (P_DONTCARE)
+#define P_PPI0_D1 (P_DONTCARE)
+#define P_PPI0_D2 (P_DONTCARE)
+#define P_PPI0_D3 (P_DONTCARE)
+
+#define P_CAN0_TX (P_DEFINED | P_IDENT(GPIO_PC0))
+#define P_CAN0_RX (P_DEFINED | P_IDENT(GPIO_PC1))
+
+#define P_SPI1_MOSI (P_DEFINED | P_IDENT(GPIO_PD0))
+#define P_SPI1_MISO (P_DEFINED | P_IDENT(GPIO_PD1))
+#define P_SPI1_SCK (P_DEFINED | P_IDENT(GPIO_PD2))
+#define P_SPI1_SS (P_DEFINED | P_IDENT(GPIO_PD3))
+#define P_SPI1_SSEL1 (P_DEFINED | P_IDENT(GPIO_PD4))
+#define P_SPI2_MOSI (P_DEFINED | P_IDENT(GPIO_PD5))
+#define P_SPI2_MISO (P_DEFINED | P_IDENT(GPIO_PD6))
+#define P_SPI2_SCK (P_DEFINED | P_IDENT(GPIO_PD7))
+#define P_SPI2_SS (P_DEFINED | P_IDENT(GPIO_PD8))
+#define P_SPI2_SSEL1 (P_DEFINED | P_IDENT(GPIO_PD9))
+#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PD10))
+#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PD11))
+#define P_UART2_RX (P_DEFINED | P_IDENT(GPIO_PD12))
+#define P_UART2_TX (P_DEFINED | P_IDENT(GPIO_PD13))
+
+#define P_SPORT2_RSCLK (P_DEFINED | P_IDENT(GPIO_PE0))
+#define P_SPORT2_RFS (P_DEFINED | P_IDENT(GPIO_PE1))
+#define P_SPORT2_DRPRI (P_DEFINED | P_IDENT(GPIO_PE2))
+#define P_SPORT2_DRSEC (P_DEFINED | P_IDENT(GPIO_PE3))
+#define P_SPORT2_TSCLK (P_DEFINED | P_IDENT(GPIO_PE4))
+#define P_SPORT2_TFS (P_DEFINED | P_IDENT(GPIO_PE5))
+#define P_SPORT2_DTPRI (P_DEFINED | P_IDENT(GPIO_PE6))
+#define P_SPORT2_DTSEC (P_DEFINED | P_IDENT(GPIO_PE7))
+#define P_SPORT3_RSCLK (P_DEFINED | P_IDENT(GPIO_PE8))
+#define P_SPORT3_RFS (P_DEFINED | P_IDENT(GPIO_PE9))
+#define P_SPORT3_DRPRI (P_DEFINED | P_IDENT(GPIO_PE10))
+#define P_SPORT3_DRSEC (P_DEFINED | P_IDENT(GPIO_PE11))
+#define P_SPORT3_TSCLK (P_DEFINED | P_IDENT(GPIO_PE12))
+#define P_SPORT3_TFS (P_DEFINED | P_IDENT(GPIO_PE13))
+#define P_SPORT3_DTPRI (P_DEFINED | P_IDENT(GPIO_PE14))
+#define P_SPORT3_DTSEC (P_DEFINED | P_IDENT(GPIO_PE15))
+
+#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF8))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF9))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF10))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF11))
+
+#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF15))
+#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF14))
+#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF13))
+#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF12))
+#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/arch/blackfin/mach-bf538/ints-priority.c b/arch/blackfin/mach-bf538/ints-priority.c
new file mode 100644
index 000000000000..70d17e550e05
--- /dev/null
+++ b/arch/blackfin/mach-bf538/ints-priority.c
@@ -0,0 +1,94 @@
+/*
+ * File: arch/blackfin/mach-bf538/ints-priority.c
+ * Based on: arch/blackfin/mach-bf533/ints-priority.c
+ * Author: Michael Hennerich
+ *
+ * Created:
+ * Description: Set up the interrupt priorities
+ *
+ * Modified:
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <asm/blackfin.h>
+
+void __init program_IAR(void)
+{
+
+ /* Program the IAR0 Register with the configured priority */
+ bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+ ((CONFIG_IRQ_DMA0_ERROR - 7) << IRQ_DMA0_ERROR_POS) |
+ ((CONFIG_IRQ_PPI_ERROR - 7) << IRQ_PPI_ERROR_POS) |
+ ((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) |
+ ((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS) |
+ ((CONFIG_IRQ_SPI0_ERROR - 7) << IRQ_SPI0_ERROR_POS) |
+ ((CONFIG_IRQ_UART0_ERROR - 7) << IRQ_UART0_ERROR_POS) |
+ ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS));
+
+ bfin_write_SIC_IAR1(((CONFIG_IRQ_PPI - 7) << IRQ_PPI_POS) |
+ ((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) |
+ ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) |
+ ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS) |
+ ((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) |
+ ((CONFIG_IRQ_SPI0 - 7) << IRQ_SPI0_POS) |
+ ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
+ ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS));
+
+ bfin_write_SIC_IAR2(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+ ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS) |
+ ((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+ ((CONFIG_IRQ_PORTF_INTA - 7) << IRQ_PORTF_INTA_POS) |
+ ((CONFIG_IRQ_PORTF_INTB - 7) << IRQ_PORTF_INTB_POS) |
+ ((CONFIG_IRQ_MEM0_DMA0 - 7) << IRQ_MEM0_DMA0_POS) |
+ ((CONFIG_IRQ_MEM0_DMA1 - 7) << IRQ_MEM0_DMA1_POS) |
+ ((CONFIG_IRQ_WATCH - 7) << IRQ_WATCH_POS));
+
+ bfin_write_SIC_IAR3(((CONFIG_IRQ_DMA1_ERROR - 7) << IRQ_DMA1_ERROR_POS) |
+ ((CONFIG_IRQ_SPORT2_ERROR - 7) << IRQ_SPORT2_ERROR_POS) |
+ ((CONFIG_IRQ_SPORT3_ERROR - 7) << IRQ_SPORT3_ERROR_POS) |
+ ((CONFIG_IRQ_SPI1_ERROR - 7) << IRQ_SPI1_ERROR_POS) |
+ ((CONFIG_IRQ_SPI2_ERROR - 7) << IRQ_SPI2_ERROR_POS) |
+ ((CONFIG_IRQ_UART1_ERROR - 7) << IRQ_UART1_ERROR_POS) |
+ ((CONFIG_IRQ_UART2_ERROR - 7) << IRQ_UART2_ERROR_POS));
+
+ bfin_write_SIC_IAR4(((CONFIG_IRQ_CAN_ERROR - 7) << IRQ_CAN_ERROR_POS) |
+ ((CONFIG_IRQ_SPORT2_RX - 7) << IRQ_SPORT2_RX_POS) |
+ ((CONFIG_IRQ_SPORT2_TX - 7) << IRQ_SPORT2_TX_POS) |
+ ((CONFIG_IRQ_SPORT3_RX - 7) << IRQ_SPORT3_RX_POS) |
+ ((CONFIG_IRQ_SPORT3_TX - 7) << IRQ_SPORT3_TX_POS) |
+ ((CONFIG_IRQ_SPI1 - 7) << IRQ_SPI1_POS));
+
+ bfin_write_SIC_IAR5(((CONFIG_IRQ_SPI2 - 7) << IRQ_SPI2_POS) |
+ ((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) |
+ ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) |
+ ((CONFIG_IRQ_UART2_RX - 7) << IRQ_UART2_RX_POS) |
+ ((CONFIG_IRQ_UART2_TX - 7) << IRQ_UART2_TX_POS) |
+ ((CONFIG_IRQ_TWI0 - 7) << IRQ_TWI0_POS) |
+ ((CONFIG_IRQ_TWI1 - 7) << IRQ_TWI1_POS) |
+ ((CONFIG_IRQ_CAN_RX - 7) << IRQ_CAN_RX_POS));
+
+ bfin_write_SIC_IAR6(((CONFIG_IRQ_CAN_TX - 7) << IRQ_CAN_TX_POS) |
+ ((CONFIG_IRQ_MEM1_DMA0 - 7) << IRQ_MEM1_DMA0_POS) |
+ ((CONFIG_IRQ_MEM1_DMA1 - 7) << IRQ_MEM1_DMA1_POS));
+
+ SSYNC();
+}
diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig
index 1bfcd8f646ab..dcf657159051 100644
--- a/arch/blackfin/mach-bf548/Kconfig
+++ b/arch/blackfin/mach-bf548/Kconfig
@@ -250,7 +250,7 @@ config IRQ_OTPSEC
default 11
config IRQ_TIMER0
int "IRQ_TIMER0"
- default 11
+ default 8
config IRQ_TIMER1
int "IRQ_TIMER1"
default 11
diff --git a/arch/blackfin/mach-bf548/Makefile b/arch/blackfin/mach-bf548/Makefile
index 68e5478e95a9..56994b675f9c 100644
--- a/arch/blackfin/mach-bf548/Makefile
+++ b/arch/blackfin/mach-bf548/Makefile
@@ -2,6 +2,4 @@
# arch/blackfin/mach-bf537/Makefile
#
-extra-y := head.o
-
obj-y := ints-priority.o dma.o
diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c
index 24192aaa9275..f53ad682530b 100644
--- a/arch/blackfin/mach-bf548/boards/cm_bf548.c
+++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c
@@ -32,6 +32,7 @@
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/irq.h>
@@ -42,6 +43,7 @@
#include <asm/gpio.h>
#include <asm/nand.h>
#include <asm/portmux.h>
+#include <asm/bfin_sdh.h>
#include <mach/bf54x_keys.h>
#include <asm/dpmc.h>
#include <linux/input.h>
@@ -186,44 +188,107 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir1_device = {
+ .name = "bfin_sir",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR2
+static struct resource bfin_sir2_resources[] = {
{
.start = 0xFFC02100,
.end = 0xFFC021FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART2_RX,
+ .end = IRQ_UART2_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART2_RX,
+ .end = CH_UART2_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir2_device = {
+ .name = "bfin_sir",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(bfin_sir2_resources),
+ .resource = bfin_sir2_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR3
+static struct resource bfin_sir3_resources[] = {
{
.start = 0xFFC03100,
.end = 0xFFC031FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART3_RX,
+ .end = IRQ_UART3_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART3_RX,
+ .end = CH_UART3_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir3_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 3,
+ .num_resources = ARRAY_SIZE(bfin_sir3_resources),
+ .resource = bfin_sir3_resources,
};
#endif
+#endif
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
static struct resource smsc911x_resources[] = {
@@ -271,8 +336,8 @@ static struct musb_hdrc_config musb_config = {
.dyn_fifo = 0,
.soft_con = 1,
.dma = 1,
- .num_eps = 7,
- .dma_channels = 7,
+ .num_eps = 8,
+ .dma_channels = 8,
.gpio_vrsel = GPIO_PH6,
};
@@ -302,6 +367,19 @@ static struct platform_device musb_device = {
};
#endif
+static struct resource bfin_gpios_resources = {
+ .start = 0,
+ .end = MAX_BLACKFIN_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+ .name = "simple-gpio",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &bfin_gpios_resources,
+};
+
#if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
static struct resource bfin_atapi_resources[] = {
{
@@ -372,9 +450,58 @@ static struct platform_device bf5xx_nand_device = {
#endif
#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+static struct bfin_sd_host bfin_sdh_data = {
+ .dma_chan = CH_SDH,
+ .irq_int0 = IRQ_SDH_MASK0,
+ .pin_req = {P_SD_D0, P_SD_D1, P_SD_D2, P_SD_D3, P_SD_CLK, P_SD_CMD, 0},
+};
+
static struct platform_device bf54x_sdh_device = {
.name = "bfin-sdh",
.id = 0,
+ .dev = {
+ .platform_data = &bfin_sdh_data,
+ },
+};
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static struct mtd_partition para_partitions[] = {
+ {
+ .name = "bootloader(nor)",
+ .size = 0x40000,
+ .offset = 0,
+ }, {
+ .name = "linux kernel(nor)",
+ .size = 0x400000,
+ .offset = MTDPART_OFS_APPEND,
+ }, {
+ .name = "file system(nor)",
+ .size = MTDPART_SIZ_FULL,
+ .offset = MTDPART_OFS_APPEND,
+ }
+};
+
+static struct physmap_flash_data para_flash_data = {
+ .width = 2,
+ .parts = para_partitions,
+ .nr_parts = ARRAY_SIZE(para_partitions),
+};
+
+static struct resource para_flash_resource = {
+ .start = 0x20000000,
+ .end = 0x207fffff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device para_flash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &para_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &para_flash_resource,
};
#endif
@@ -642,7 +769,18 @@ static struct platform_device *cm_bf548_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
+#ifdef CONFIG_BFIN_SIR2
+ &bfin_sir2_device,
+#endif
+#ifdef CONFIG_BFIN_SIR3
+ &bfin_sir3_device,
+#endif
#endif
#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
@@ -679,7 +817,7 @@ static struct platform_device *cm_bf548_devices[] __initdata = {
#endif
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
-/* &i2c_bfin_twi0_device, */
+ &i2c_bfin_twi0_device,
#if !defined(CONFIG_BF542)
&i2c_bfin_twi1_device,
#endif
@@ -688,6 +826,12 @@ static struct platform_device *cm_bf548_devices[] __initdata = {
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
&bfin_device_gpiokeys,
#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+ &para_flash_device,
+#endif
+
+ &bfin_gpios_device,
};
static int __init cm_bf548_init(void)
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index 5288187a3ace..096e661700a7 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -45,6 +45,7 @@
#include <asm/nand.h>
#include <asm/dpmc.h>
#include <asm/portmux.h>
+#include <asm/bfin_sdh.h>
#include <mach/bf54x_keys.h>
#include <linux/input.h>
#include <linux/spi/ad7877.h>
@@ -52,16 +53,16 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "ADSP-BF548-EZKIT";
+const char bfin_board_name[] = "ADI BF548-EZKIT";
/*
* Driver needs to know address, irq and flag pin.
*/
#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-static struct resource bfin_isp1761_resources[] = {
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
[0] = {
- .name = "isp1761-regs",
.start = 0x2C0C0000,
.end = 0x2C0C0000 + 0xfffff,
.flags = IORESOURCE_MEM,
@@ -73,32 +74,25 @@ static struct resource bfin_isp1761_resources[] = {
},
};
-static struct platform_device bfin_isp1761_device = {
- .name = "isp1761",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_isp1761_resources),
- .resource = bfin_isp1761_resources,
+static struct isp1760_platform_data isp1760_priv = {
+ .is_isp1761 = 0,
+ .port1_disable = 0,
+ .bus_width_16 = 1,
+ .port1_otg = 0,
+ .analog_oc = 0,
+ .dack_polarity_high = 0,
+ .dreq_polarity_high = 0,
};
-static struct platform_device *bfin_isp1761_devices[] = {
- &bfin_isp1761_device,
+static struct platform_device bfin_isp1760_device = {
+ .name = "isp1760-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1760_priv,
+ },
+ .num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+ .resource = bfin_isp1760_resources,
};
-
-int __init bfin_isp1761_init(void)
-{
- unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
-
- printk(KERN_INFO "%s(): registering device resources\n", __func__);
- set_irq_type(bfin_isp1761_resources[1].start, IRQF_TRIGGER_FALLING);
-
- return platform_add_devices(bfin_isp1761_devices, num_devices);
-}
-
-void __exit bfin_isp1761_exit(void)
-{
- platform_device_unregister(&bfin_isp1761_device);
-}
-arch_initcall(bfin_isp1761_init);
#endif
#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
@@ -262,44 +256,107 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR1
+static struct resource bfin_sir1_resources[] = {
{
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART1_RX,
+ .end = IRQ_UART1_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART1_RX,
+ .end = CH_UART1_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir1_device = {
+ .name = "bfin_sir",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_sir1_resources),
+ .resource = bfin_sir1_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR2
+static struct resource bfin_sir2_resources[] = {
{
.start = 0xFFC02100,
.end = 0xFFC021FF,
.flags = IORESOURCE_MEM,
},
+ {
+ .start = IRQ_UART2_RX,
+ .end = IRQ_UART2_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART2_RX,
+ .end = CH_UART2_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+static struct platform_device bfin_sir2_device = {
+ .name = "bfin_sir",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(bfin_sir2_resources),
+ .resource = bfin_sir2_resources,
+};
#endif
#ifdef CONFIG_BFIN_SIR3
+static struct resource bfin_sir3_resources[] = {
{
.start = 0xFFC03100,
.end = 0xFFC031FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART3_RX,
+ .end = IRQ_UART3_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART3_RX,
+ .end = CH_UART3_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir3_device = {
.name = "bfin_sir",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .id = 3,
+ .num_resources = ARRAY_SIZE(bfin_sir3_resources),
+ .resource = bfin_sir3_resources,
};
#endif
+#endif
#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
static struct resource smsc911x_resources[] = {
@@ -347,8 +404,8 @@ static struct musb_hdrc_config musb_config = {
.dyn_fifo = 0,
.soft_con = 1,
.dma = 1,
- .num_eps = 7,
- .dma_channels = 7,
+ .num_eps = 8,
+ .dma_channels = 8,
.gpio_vrsel = GPIO_PE7,
};
@@ -448,9 +505,19 @@ static struct platform_device bf5xx_nand_device = {
#endif
#if defined(CONFIG_SDH_BFIN) || defined(CONFIG_SDH_BFIN_MODULE)
+
+static struct bfin_sd_host bfin_sdh_data = {
+ .dma_chan = CH_SDH,
+ .irq_int0 = IRQ_SDH_MASK0,
+ .pin_req = {P_SD_D0, P_SD_D1, P_SD_D2, P_SD_D3, P_SD_CLK, P_SD_CMD, 0},
+};
+
static struct platform_device bf54x_sdh_device = {
.name = "bfin-sdh",
.id = 0,
+ .dev = {
+ .platform_data = &bfin_sdh_data,
+ },
};
#endif
@@ -589,7 +656,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
{
.modalias = "ad7877",
.platform_data = &bfin_ad7877_ts_info,
- .irq = IRQ_PJ11, /* newer boards (Rev 1.4+) use IRQ_PB4 */
+ .irq = IRQ_PB4, /* old boards (<=Rev 1.3) use IRQ_PJ11 */
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = 2,
@@ -714,7 +781,6 @@ static struct platform_device i2c_bfin_twi1_device = {
#endif
#endif
-#ifdef CONFIG_I2C_BOARDINFO
static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
};
@@ -733,7 +799,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
#endif
};
#endif
-#endif
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
#include <linux/gpio_keys.h>
@@ -812,7 +877,18 @@ static struct platform_device *ezkit_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#ifdef CONFIG_BFIN_SIR1
+ &bfin_sir1_device,
+#endif
+#ifdef CONFIG_BFIN_SIR2
+ &bfin_sir2_device,
+#endif
+#ifdef CONFIG_BFIN_SIR3
+ &bfin_sir3_device,
+#endif
#endif
#if defined(CONFIG_FB_BF54X_LQ043) || defined(CONFIG_FB_BF54X_LQ043_MODULE)
@@ -827,6 +903,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
&musb_device,
#endif
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+ &bfin_isp1760_device,
+#endif
+
#if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
&bfin_atapi_device,
#endif
@@ -874,14 +954,12 @@ static int __init ezkit_init(void)
{
printk(KERN_INFO "%s(): registering device resources\n", __func__);
-#ifdef CONFIG_I2C_BOARDINFO
i2c_register_board_info(0, bfin_i2c_board_info0,
ARRAY_SIZE(bfin_i2c_board_info0));
#if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */
i2c_register_board_info(1, bfin_i2c_board_info1,
ARRAY_SIZE(bfin_i2c_board_info1));
#endif
-#endif
platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
index 74730eb8ae1b..535980652bf6 100644
--- a/arch/blackfin/mach-bf548/dma.c
+++ b/arch/blackfin/mach-bf548/dma.c
@@ -32,7 +32,7 @@
#include <asm/blackfin.h>
#include <asm/dma.h>
-struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
(struct dma_register *) DMA0_NEXT_DESC_PTR,
(struct dma_register *) DMA1_NEXT_DESC_PTR,
(struct dma_register *) DMA2_NEXT_DESC_PTR,
diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S
deleted file mode 100644
index 93b361dff27b..000000000000
--- a/arch/blackfin/mach-bf548/head.S
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * File: arch/blackfin/mach-bf548/head.S
- * Based on: arch/blackfin/mach-bf537/head.S
- * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
- *
- * Created: 1998
- * Description: Startup code for Blackfin BF548
- *
- * Modified:
- * Copyright 2004-2007 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/blackfin.h>
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-#include <asm/clocks.h>
-#include <mach/mem_init.h>
-#endif
-
-.section .l1.text
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-ENTRY(_start_dma_code)
-
- /* Enable PHY CLK buffer output */
- p0.h = hi(VR_CTL);
- p0.l = lo(VR_CTL);
- r0.l = w[p0];
- bitset(r0, 14);
- w[p0] = r0.l;
- ssync;
-
- p0.h = hi(SIC_IWR0);
- p0.l = lo(SIC_IWR0);
- r0.l = 0x1;
- r0.h = 0x0;
- [p0] = r0;
- SSYNC;
-
- /*
- * Set PLL_CTL
- * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
- * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
- * - [7] = output delay (add 200ps of delay to mem signals)
- * - [6] = input delay (add 200ps of input delay to mem signals)
- * - [5] = PDWN : 1=All Clocks off
- * - [3] = STOPCK : 1=Core Clock off
- * - [1] = PLL_OFF : 1=Disable Power to PLL
- * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
- * all other bits set to zero
- */
-
- p0.h = hi(PLL_LOCKCNT);
- p0.l = lo(PLL_LOCKCNT);
- r0 = 0x300(Z);
- w[p0] = r0.l;
- ssync;
-
- /* enable self refresh via SRREQ */
- P2.H = hi(EBIU_RSTCTL);
- P2.L = lo(EBIU_RSTCTL);
- R0 = [P2];
- BITSET (R0, 3);
- [P2] = R0;
- SSYNC;
-
- /* wait for SRACK bit to be set */
-.LSRR_MODE:
- R0 = [P2];
- CC = BITTST(R0, 4);
- if !CC JUMP .LSRR_MODE;
-
- r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
- r0 = r0 << 9; /* Shift it over, */
- r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
- r0 = r1 | r0;
- r1 = PLL_BYPASS; /* Bypass the PLL? */
- r1 = r1 << 8; /* Shift it over */
- r0 = r1 | r0; /* add them all together */
-#ifdef ANOMALY_05000265
- BITSET(r0, 15); /* Add 250 mV of hysteresis to SPORT input pins */
-#endif
-
- p0.h = hi(PLL_CTL);
- p0.l = lo(PLL_CTL); /* Load the address */
- cli r2; /* Disable interrupts */
- ssync;
- w[p0] = r0.l; /* Set the value */
- idle; /* Wait for the PLL to stablize */
- sti r2; /* Enable interrupts */
-
-.Lcheck_again:
- p0.h = hi(PLL_STAT);
- p0.l = lo(PLL_STAT);
- R0 = W[P0](Z);
- CC = BITTST(R0,5);
- if ! CC jump .Lcheck_again;
-
- /* Configure SCLK & CCLK Dividers */
- r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
- p0.h = hi(PLL_DIV);
- p0.l = lo(PLL_DIV);
- w[p0] = r0.l;
- ssync;
-
- /* disable self refresh by clearing SRREQ */
- P2.H = hi(EBIU_RSTCTL);
- P2.L = lo(EBIU_RSTCTL);
- R0 = [P2];
- CC = BITTST(R0, 0);
- if CC jump .Lskipddrrst;
- BITSET (R0, 0);
-.Lskipddrrst:
- BITCLR (R0, 3);
- [P2] = R0;
- SSYNC;
-
- p0.l = lo(EBIU_DDRCTL0);
- p0.h = hi(EBIU_DDRCTL0);
- r0.l = lo(mem_DDRCTL0);
- r0.h = hi(mem_DDRCTL0);
- [p0] = r0;
- ssync;
-
- p0.l = lo(EBIU_DDRCTL1);
- p0.h = hi(EBIU_DDRCTL1);
- r0.l = lo(mem_DDRCTL1);
- r0.h = hi(mem_DDRCTL1);
- [p0] = r0;
- ssync;
-
- p0.l = lo(EBIU_DDRCTL2);
- p0.h = hi(EBIU_DDRCTL2);
- r0.l = lo(mem_DDRCTL2);
- r0.h = hi(mem_DDRCTL2);
- [p0] = r0;
- ssync;
-
- RTS;
-ENDPROC(_start_dma_code)
-#endif /* CONFIG_BFIN_KERNEL_CLOCK */
diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h
index 816b09278f62..23d03c52f4b4 100644
--- a/arch/blackfin/mach-bf548/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h
@@ -157,6 +157,8 @@
#define ANOMALY_05000429 (__SILICON_REVISION__ < 2)
/* Software System Reset Corrupts PLL_LOCKCNT Register */
#define ANOMALY_05000430 (__SILICON_REVISION__ >= 2)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000125 (0)
@@ -173,5 +175,9 @@
#define ANOMALY_05000311 (0)
#define ANOMALY_05000323 (0)
#define ANOMALY_05000363 (0)
+#define ANOMALY_05000380 (0)
+#define ANOMALY_05000412 (0)
+#define ANOMALY_05000432 (0)
+#define ANOMALY_05000435 (0)
#endif
diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h
index 49f9b403d458..cd31f72bdd82 100644
--- a/arch/blackfin/mach-bf548/include/mach/bf548.h
+++ b/arch/blackfin/mach-bf548/include/mach/bf548.h
@@ -104,6 +104,18 @@
#define AMGCTLVAL (V_AMBEN | V_AMCKEN)
+#if defined(CONFIG_BF542M)
+# define CONFIG_BF542
+#elif defined(CONFIG_BF544M)
+# define CONFIG_BF544
+#elif defined(CONFIG_BF547M)
+# define CONFIG_BF547
+#elif defined(CONFIG_BF548M)
+# define CONFIG_BF548
+#elif defined(CONFIG_BF549M)
+# define CONFIG_BF549
+#endif
+
#if defined(CONFIG_BF542)
# define CPU "BF542"
# define CPUID 0x27de
@@ -122,7 +134,7 @@
#endif
#ifndef CPU
-#error Unknown CPU type - This kernel doesn't seem to be configured properly
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
#endif
#endif /* __MACH_BF48_H__ */
diff --git a/arch/blackfin/mach-bf548/include/mach/bfin_sir.h b/arch/blackfin/mach-bf548/include/mach/bfin_sir.h
deleted file mode 100644
index c41f9cf00268..000000000000
--- a/arch/blackfin/mach-bf548/include/mach/bfin_sir.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Blackfin Infra-red Driver
- *
- * Copyright 2006-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- *
- */
-
-#include <linux/serial.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-
-#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
-#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
-#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER_SET)
-#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
-#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
-#define SIR_UART_GET_LSR(port) bfin_read16((port)->membase + OFFSET_LSR)
-#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
-
-#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
-#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
-#define SIR_UART_SET_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_SET), v)
-#define SIR_UART_CLEAR_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER_CLEAR), v)
-#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
-#define SIR_UART_PUT_LSR(port, v) bfin_write16(((port)->membase + OFFSET_LSR), v)
-#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
-#define SIR_UART_CLEAR_LSR(port) bfin_write16(((port)->membase + OFFSET_LSR), -1)
-#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
-
-#ifdef CONFIG_SIR_BFIN_DMA
-struct dma_rx_buf {
- char *buf;
- int head;
- int tail;
- };
-#endif /* CONFIG_SIR_BFIN_DMA */
-
-struct bfin_sir_port {
- unsigned char __iomem *membase;
- unsigned int irq;
- unsigned int lsr;
- unsigned long clk;
- struct net_device *dev;
-#ifdef CONFIG_SIR_BFIN_DMA
- int tx_done;
- struct dma_rx_buf rx_dma_buf;
- struct timer_list rx_dma_timer;
- int rx_dma_nrows;
-#endif /* CONFIG_SIR_BFIN_DMA */
- unsigned int tx_dma_channel;
- unsigned int rx_dma_channel;
-};
-
-struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
-
-struct bfin_sir_port_res {
- unsigned long base_addr;
- int irq;
- unsigned int rx_dma_channel;
- unsigned int tx_dma_channel;
-};
-
-struct bfin_sir_port_res bfin_sir_port_resource[] = {
-#ifdef CONFIG_BFIN_SIR0
- {
- 0xFFC00400,
- IRQ_UART0_RX,
- CH_UART0_RX,
- CH_UART0_TX,
- },
-#endif
-#ifdef CONFIG_BFIN_SIR1
- {
- 0xFFC02000,
- IRQ_UART1_RX,
- CH_UART1_RX,
- CH_UART1_TX,
- },
-#endif
-#ifdef CONFIG_BFIN_SIR2
- {
- 0xFFC02100,
- IRQ_UART2_RX,
- CH_UART2_RX,
- CH_UART2_TX,
- },
-#endif
-#ifdef CONFIG_BFIN_SIR3
- {
- 0xFFC03100,
- IRQ_UART3_RX,
- CH_UART3_RX,
- CH_UART3_TX,
- },
-#endif
-};
-
-int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
-
-struct bfin_sir_self {
- struct bfin_sir_port *sir_port;
- spinlock_t lock;
- unsigned int open;
- int speed;
- int newspeed;
-
- struct sk_buff *txskb;
- struct sk_buff *rxskb;
- struct net_device_stats stats;
- struct device *dev;
- struct irlap_cb *irlap;
- struct qos_info qos;
-
- iobuff_t tx_buff;
- iobuff_t rx_buff;
-
- struct work_struct work;
- int mtt;
-};
-
-#define DRIVER_NAME "bfin_sir"
-
-static int bfin_sir_hw_init(void)
-{
- int ret = -ENODEV;
-#ifdef CONFIG_BFIN_SIR0
- ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
-
-#ifdef CONFIG_BFIN_SIR1
- ret = peripheral_request(P_UART1_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART1_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
-
-#ifdef CONFIG_BFIN_SIR2
- ret = peripheral_request(P_UART2_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART2_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
-
-#ifdef CONFIG_BFIN_SIR3
- ret = peripheral_request(P_UART3_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART3_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
- return ret;
-}
diff --git a/arch/blackfin/mach-bf548/include/mach/blackfin.h b/arch/blackfin/mach-bf548/include/mach/blackfin.h
index d6ee74ac0460..0c0e3e2c3c21 100644
--- a/arch/blackfin/mach-bf548/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf548/include/mach/blackfin.h
@@ -111,7 +111,7 @@
/* UART 0*/
-/* DMA Channnel */
+/* DMA Channel */
#define bfin_read_CH_UART_RX() bfin_read_CH_UART1_RX()
#define bfin_write_CH_UART_RX(val) bfin_write_CH_UART1_RX(val)
#define bfin_read_CH_UART_TX() bfin_read_CH_UART1_TX()
diff --git a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
index 57ac8cb9b1f6..6e636c418cb0 100644
--- a/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
+++ b/arch/blackfin/mach-bf548/include/mach/cdefBF54x_base.h
@@ -34,7 +34,6 @@
#include <asm/blackfin.h>
#include "defBF54x_base.h"
-#include <asm/system.h>
/* ************************************************************** */
/* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF54x */
@@ -43,63 +42,9 @@
/* PLL Registers */
#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1, iwr2;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- iwr2 = bfin_read32(SIC_IWR2);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
- bfin_write32(SIC_IWR2, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- bfin_write32(SIC_IWR2, iwr2);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1, iwr2;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SIC_IWR0);
- iwr1 = bfin_read32(SIC_IWR1);
- iwr2 = bfin_read32(SIC_IWR2);
- /* Only allow PPL Wakeup) */
- bfin_write32(SIC_IWR0, IWR_ENABLE(0));
- bfin_write32(SIC_IWR1, 0);
- bfin_write32(SIC_IWR2, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SIC_IWR0, iwr0);
- bfin_write32(SIC_IWR1, iwr1);
- bfin_write32(SIC_IWR2, iwr2);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
@@ -2746,5 +2691,64 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
#define bfin_read_PINT3_IRQ bfin_read_PINT3_REQUEST
#define bfin_write_PINT3_IRQ bfin_write_PINT3_REQUEST
+/* These need to be last due to the cdef/linux inter-dependencies */
+#include <asm/irq.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1, iwr2;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ iwr2 = bfin_read32(SIC_IWR2);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+ bfin_write32(SIC_IWR2, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ bfin_write32(SIC_IWR2, iwr2);
+ local_irq_restore_hw(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1, iwr2;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ iwr2 = bfin_read32(SIC_IWR2);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+ bfin_write32(SIC_IWR2, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ bfin_write32(SIC_IWR2, iwr2);
+ local_irq_restore_hw(flags);
+}
+
#endif /* _CDEF_BF54X_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/dma.h b/arch/blackfin/mach-bf548/include/mach/dma.h
index 36a2ef7e7849..a30d242c7398 100644
--- a/arch/blackfin/mach-bf548/include/mach/dma.h
+++ b/arch/blackfin/mach-bf548/include/mach/dma.h
@@ -1,32 +1,8 @@
-/*
- * file: include/asm-blackfin/mach-bf548/dma.h
- * based on:
- * author:
+/* mach/dma.h - arch-specific DMA defines
*
- * created:
- * description:
- * system mmr register map
- * rev:
+ * Copyright 2004-2008 Analog Devices Inc.
*
- * modified:
- *
- *
- * bugs: enter bugs at http://blackfin.uclinux.org/
- *
- * this program is free software; you can redistribute it and/or modify
- * it under the terms of the gnu general public license as published by
- * the free software foundation; either version 2, 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; see the file copying.
- * if not, write to the free software foundation,
- * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ * Licensed under the GPL-2 or later.
*/
#ifndef _MACH_DMA_H_
@@ -71,6 +47,6 @@
#define CH_MEM_STREAM3_DEST 30
#define CH_MEM_STREAM3_SRC 31
-#define MAX_BLACKFIN_DMA_CHANNEL 32
+#define MAX_DMA_CHANNELS 32
#endif
diff --git a/arch/blackfin/mach-bf548/include/mach/gpio.h b/arch/blackfin/mach-bf548/include/mach/gpio.h
index bba82dc75f16..3a2051709787 100644
--- a/arch/blackfin/mach-bf548/include/mach/gpio.h
+++ b/arch/blackfin/mach-bf548/include/mach/gpio.h
@@ -195,17 +195,17 @@
struct gpio_port_t {
unsigned short port_fer;
unsigned short dummy1;
- unsigned short port_data;
+ unsigned short data;
unsigned short dummy2;
- unsigned short port_set;
+ unsigned short data_set;
unsigned short dummy3;
- unsigned short port_clear;
+ unsigned short data_clear;
unsigned short dummy4;
- unsigned short port_dir_set;
+ unsigned short dir_set;
unsigned short dummy5;
- unsigned short port_dir_clear;
+ unsigned short dir_clear;
unsigned short dummy6;
- unsigned short port_inen;
+ unsigned short inen;
unsigned short dummy7;
unsigned int port_mux;
};
diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h
index ad380d1f5872..60299a71e090 100644
--- a/arch/blackfin/mach-bf548/include/mach/irq.h
+++ b/arch/blackfin/mach-bf548/include/mach/irq.h
@@ -158,7 +158,7 @@ Events (highest priority) EMU 0
#define IRQ_PINT2 BFIN_IRQ(94) /* PINT2 Interrupt */
#define IRQ_PINT3 BFIN_IRQ(95) /* PINT3 Interrupt */
-#define SYS_IRQS IRQ_PINT3
+#define SYS_IRQS IRQ_PINT3
#define BFIN_PA_IRQ(x) ((x) + SYS_IRQS + 1)
#define IRQ_PA0 BFIN_PA_IRQ(0)
diff --git a/arch/blackfin/mach-bf548/include/mach/mem_init.h b/arch/blackfin/mach-bf548/include/mach/mem_init.h
deleted file mode 100644
index ab0b863eee66..000000000000
--- a/arch/blackfin/mach-bf548/include/mach/mem_init.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * File: include/asm-blackfin/mach-bf548/mem_init.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-#define MIN_DDR_SCLK(x) (x*(CONFIG_SCLK_HZ/1000/1000)/1000 + 1)
-#define MAX_DDR_SCLK(x) (x*(CONFIG_SCLK_HZ/1000/1000)/1000)
-#define DDR_CLK_HZ(x) (1000*1000*1000/x)
-
-#if (CONFIG_MEM_MT46V32M16_6T)
-#define DDR_SIZE DEVSZ_512
-#define DDR_WIDTH DEVWD_16
-#define DDR_MAX_tCK 13
-
-#define DDR_tRC DDR_TRC(MIN_DDR_SCLK(60))
-#define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(42))
-#define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15))
-#define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(72))
-#define DDR_tREFI DDR_TREFI(MAX_DDR_SCLK(7800))
-
-#define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15))
-#define DDR_tWTR DDR_TWTR(1)
-#define DDR_tMRD DDR_TMRD(MIN_DDR_SCLK(12))
-#define DDR_tWR DDR_TWR(MIN_DDR_SCLK(15))
-#endif
-
-#if (CONFIG_MEM_MT46V32M16_5B)
-#define DDR_SIZE DEVSZ_512
-#define DDR_WIDTH DEVWD_16
-#define DDR_MAX_tCK 13
-
-#define DDR_tRC DDR_TRC(MIN_DDR_SCLK(55))
-#define DDR_tRAS DDR_TRAS(MIN_DDR_SCLK(40))
-#define DDR_tRP DDR_TRP(MIN_DDR_SCLK(15))
-#define DDR_tRFC DDR_TRFC(MIN_DDR_SCLK(70))
-#define DDR_tREFI DDR_TREFI(MAX_DDR_SCLK(7800))
-
-#define DDR_tRCD DDR_TRCD(MIN_DDR_SCLK(15))
-#define DDR_tWTR DDR_TWTR(2)
-#define DDR_tMRD DDR_TMRD(MIN_DDR_SCLK(10))
-#define DDR_tWR DDR_TWR(MIN_DDR_SCLK(15))
-#endif
-
-#if (CONFIG_MEM_GENERIC_BOARD)
-#define DDR_SIZE DEVSZ_512
-#define DDR_WIDTH DEVWD_16
-#define DDR_MAX_tCK 13
-
-#define DDR_tRCD DDR_TRCD(3)
-#define DDR_tWTR DDR_TWTR(2)
-#define DDR_tWR DDR_TWR(2)
-#define DDR_tMRD DDR_TMRD(2)
-#define DDR_tRP DDR_TRP(3)
-#define DDR_tRAS DDR_TRAS(7)
-#define DDR_tRC DDR_TRC(10)
-#define DDR_tRFC DDR_TRFC(12)
-#define DDR_tREFI DDR_TREFI(1288)
-#endif
-
-#if (CONFIG_SCLK_HZ < DDR_CLK_HZ(DDR_MAX_tCK))
-# error "CONFIG_SCLK_HZ is too small (<DDR_CLK_HZ(DDR_MAX_tCK) Hz)."
-#elif(CONFIG_SCLK_HZ <= 133333333)
-# define DDR_CL CL_2
-#else
-# error "CONFIG_SCLK_HZ is too large (>133333333 Hz)."
-#endif
-
-
-#define mem_DDRCTL0 (DDR_tRP | DDR_tRAS | DDR_tRC | DDR_tRFC | DDR_tREFI)
-#define mem_DDRCTL1 (DDR_DATWIDTH | EXTBANK_1 | DDR_SIZE | DDR_WIDTH | DDR_tWTR \
- | DDR_tMRD | DDR_tWR | DDR_tRCD)
-#define mem_DDRCTL2 DDR_CL
-
-
-#if defined CONFIG_CLKIN_HALF
-#define CLKIN_HALF 1
-#else
-#define CLKIN_HALF 0
-#endif
-
-#if defined CONFIG_PLL_BYPASS
-#define PLL_BYPASS 1
-#else
-#define PLL_BYPASS 0
-#endif
-
-/***************************************Currently Not Being Used *********************************/
-#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ))
-#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-
-#if (flash_EBIU_AMBCTL_TT > 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_4
-#endif
-#if (flash_EBIU_AMBCTL_TT == 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_3
-#endif
-#if (flash_EBIU_AMBCTL_TT == 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_2
-#endif
-#if (flash_EBIU_AMBCTL_TT < 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_ST > 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_4
-#endif
-#if (flash_EBIU_AMBCTL_ST == 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_3
-#endif
-#if (flash_EBIU_AMBCTL_ST == 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_2
-#endif
-#if (flash_EBIU_AMBCTL_ST < 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_1
-#endif
-
-#if (flash_EBIU_AMBCTL_HT > 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_3
-#endif
-#if (flash_EBIU_AMBCTL_HT == 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_2
-#endif
-#if (flash_EBIU_AMBCTL_HT == 1)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_0
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_WAT > 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_15
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_14
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 13)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_13
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 12)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_12
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 11)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_11
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 10)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_10
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 9)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_9
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 8)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_8
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 7)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_7
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 6)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_6
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 5)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_5
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 4)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_4
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 3)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_3
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 2)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_2
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 1)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_RAT > 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_15
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_14
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 13)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_13
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 12)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_12
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 11)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_11
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 10)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_10
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 9)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_9
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 8)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_8
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 7)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_7
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 6)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_6
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 5)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_5
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 4)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_4
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 3)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_3
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 2)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_2
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 1)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_1
-#endif
-
-#define flash_EBIU_AMBCTL0 \
- (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
- flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/arch/blackfin/mach-bf548/include/mach/mem_map.h b/arch/blackfin/mach-bf548/include/mach/mem_map.h
index a2228428dc06..70b9c1194024 100644
--- a/arch/blackfin/mach-bf548/include/mach/mem_map.h
+++ b/arch/blackfin/mach-bf548/include/mach/mem_map.h
@@ -108,4 +108,10 @@
#define L1_SCRATCH_START 0xFFB00000
#define L1_SCRATCH_LENGTH 0x1000
+#define GET_PDA_SAFE(preg) \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda;
+
+#define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+
#endif/* _MEM_MAP_548_H_ */
diff --git a/arch/blackfin/mach-bf548/include/mach/portmux.h b/arch/blackfin/mach-bf548/include/mach/portmux.h
index 8177a567dcdb..ffb1d0a44b4d 100644
--- a/arch/blackfin/mach-bf548/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf548/include/mach/portmux.h
@@ -125,6 +125,7 @@
#define P_KEY_COL2 (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(3))
#define P_KEY_COL3 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(3))
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1
#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0))
#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0))
#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0))
diff --git a/arch/blackfin/mach-bf561/Kconfig b/arch/blackfin/mach-bf561/Kconfig
index 3f4895450bea..638ec38ca470 100644
--- a/arch/blackfin/mach-bf561/Kconfig
+++ b/arch/blackfin/mach-bf561/Kconfig
@@ -4,9 +4,9 @@ source "arch/blackfin/mach-bf561/boards/Kconfig"
menu "BF561 Specific Configuration"
-comment "Core B Support"
+if (!SMP)
-menu "Core B Support"
+comment "Core B Support"
config BF561_COREB
bool "Enable Core B support"
@@ -25,7 +25,7 @@ config BF561_COREB_RESET
0 is set, and will reset PC to 0xff600000 when
COREB_SRAM_INIT is cleared.
-endmenu
+endif
comment "Interrupt Priority Assignment"
@@ -138,7 +138,7 @@ config IRQ_DMA2_11
default 9
config IRQ_TIMER0
int "TIMER 0 Interrupt"
- default 10
+ default 8
config IRQ_TIMER1
int "TIMER 1 Interrupt"
default 10
diff --git a/arch/blackfin/mach-bf561/Makefile b/arch/blackfin/mach-bf561/Makefile
index f39235a55783..59e18afe28c6 100644
--- a/arch/blackfin/mach-bf561/Makefile
+++ b/arch/blackfin/mach-bf561/Makefile
@@ -2,8 +2,7 @@
# arch/blackfin/mach-bf561/Makefile
#
-extra-y := head.o
-
obj-y := ints-priority.o dma.o
obj-$(CONFIG_BF561_COREB) += coreb.o
+obj-$(CONFIG_SMP) += smp.o secondary.o atomic.o
diff --git a/arch/blackfin/mach-bf561/atomic.S b/arch/blackfin/mach-bf561/atomic.S
new file mode 100644
index 000000000000..9439bc6bd01f
--- /dev/null
+++ b/arch/blackfin/mach-bf561/atomic.S
@@ -0,0 +1,919 @@
+/*
+ * File: arch/blackfin/mach-bf561/atomic.S
+ * Author: Philippe Gerum <rpm@xenomai.org>
+ *
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/cache.h>
+#include <asm/asm-offsets.h>
+#include <asm/rwlock.h>
+#include <asm/cplb.h>
+
+.text
+
+.macro coreslot_loadaddr reg:req
+ \reg\().l = _corelock;
+ \reg\().h = _corelock;
+.endm
+
+/*
+ * r0 = address of atomic data to flush and invalidate (32bit).
+ *
+ * Clear interrupts and return the old mask.
+ * We assume that no atomic data can span cachelines.
+ *
+ * Clobbers: r2:0, p0
+ */
+ENTRY(_get_core_lock)
+ r1 = -L1_CACHE_BYTES;
+ r1 = r0 & r1;
+ cli r0;
+ coreslot_loadaddr p0;
+.Lretry_corelock:
+ testset (p0);
+ if cc jump .Ldone_corelock;
+ SSYNC(r2);
+ jump .Lretry_corelock
+.Ldone_corelock:
+ p0 = r1;
+ CSYNC(r2);
+ flushinv[p0];
+ SSYNC(r2);
+ rts;
+ENDPROC(_get_core_lock)
+
+/*
+ * r0 = address of atomic data in uncacheable memory region (32bit).
+ *
+ * Clear interrupts and return the old mask.
+ *
+ * Clobbers: r0, p0
+ */
+ENTRY(_get_core_lock_noflush)
+ cli r0;
+ coreslot_loadaddr p0;
+.Lretry_corelock_noflush:
+ testset (p0);
+ if cc jump .Ldone_corelock_noflush;
+ SSYNC(r2);
+ jump .Lretry_corelock_noflush
+.Ldone_corelock_noflush:
+ rts;
+ENDPROC(_get_core_lock_noflush)
+
+/*
+ * r0 = interrupt mask to restore.
+ * r1 = address of atomic data to flush and invalidate (32bit).
+ *
+ * Interrupts are masked on entry (see _get_core_lock).
+ * Clobbers: r2:0, p0
+ */
+ENTRY(_put_core_lock)
+ /* Write-through cache assumed, so no flush needed here. */
+ coreslot_loadaddr p0;
+ r1 = 0;
+ [p0] = r1;
+ SSYNC(r2);
+ sti r0;
+ rts;
+ENDPROC(_put_core_lock)
+
+#ifdef __ARCH_SYNC_CORE_DCACHE
+
+ENTRY(___raw_smp_mark_barrier_asm)
+ [--sp] = rets;
+ [--sp] = ( r7:5 );
+ [--sp] = r0;
+ [--sp] = p1;
+ [--sp] = p0;
+ call _get_core_lock_noflush;
+
+ /*
+ * Calculate current core mask
+ */
+ GET_CPUID(p1, r7);
+ r6 = 1;
+ r6 <<= r7;
+
+ /*
+ * Set bit of other cores in barrier mask. Don't change current core bit.
+ */
+ p1.l = _barrier_mask;
+ p1.h = _barrier_mask;
+ r7 = [p1];
+ r5 = r7 & r6;
+ r7 = ~r6;
+ cc = r5 == 0;
+ if cc jump 1f;
+ r7 = r7 | r6;
+1:
+ [p1] = r7;
+ SSYNC(r2);
+
+ call _put_core_lock;
+ p0 = [sp++];
+ p1 = [sp++];
+ r0 = [sp++];
+ ( r7:5 ) = [sp++];
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_smp_mark_barrier_asm)
+
+ENTRY(___raw_smp_check_barrier_asm)
+ [--sp] = rets;
+ [--sp] = ( r7:5 );
+ [--sp] = r0;
+ [--sp] = p1;
+ [--sp] = p0;
+ call _get_core_lock_noflush;
+
+ /*
+ * Calculate current core mask
+ */
+ GET_CPUID(p1, r7);
+ r6 = 1;
+ r6 <<= r7;
+
+ /*
+ * Clear current core bit in barrier mask if it is set.
+ */
+ p1.l = _barrier_mask;
+ p1.h = _barrier_mask;
+ r7 = [p1];
+ r5 = r7 & r6;
+ cc = r5 == 0;
+ if cc jump 1f;
+ r6 = ~r6;
+ r7 = r7 & r6;
+ [p1] = r7;
+ SSYNC(r2);
+
+ call _put_core_lock;
+
+ /*
+ * Invalidate the entire D-cache of current core.
+ */
+ sp += -12;
+ call _resync_core_dcache
+ sp += 12;
+ jump 2f;
+1:
+ call _put_core_lock;
+2:
+ p0 = [sp++];
+ p1 = [sp++];
+ r0 = [sp++];
+ ( r7:5 ) = [sp++];
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_smp_check_barrier_asm)
+
+/*
+ * r0 = irqflags
+ * r1 = address of atomic data
+ *
+ * Clobbers: r2:0, p1:0
+ */
+_start_lock_coherent:
+
+ [--sp] = rets;
+ [--sp] = ( r7:6 );
+ r7 = r0;
+ p1 = r1;
+
+ /*
+ * Determine whether the atomic data was previously
+ * owned by another CPU (=r6).
+ */
+ GET_CPUID(p0, r2);
+ r1 = 1;
+ r1 <<= r2;
+ r2 = ~r1;
+
+ r1 = [p1];
+ r1 >>= 28; /* CPU fingerprints are stored in the high nibble. */
+ r6 = r1 & r2;
+ r1 = [p1];
+ r1 <<= 4;
+ r1 >>= 4;
+ [p1] = r1;
+
+ /*
+ * Release the core lock now, but keep IRQs disabled while we are
+ * performing the remaining housekeeping chores for the current CPU.
+ */
+ coreslot_loadaddr p0;
+ r1 = 0;
+ [p0] = r1;
+
+ /*
+ * If another CPU has owned the same atomic section before us,
+ * then our D-cached copy of the shared data protected by the
+ * current spin/write_lock may be obsolete.
+ */
+ cc = r6 == 0;
+ if cc jump .Lcache_synced
+
+ /*
+ * Invalidate the entire D-cache of the current core.
+ */
+ sp += -12;
+ call _resync_core_dcache
+ sp += 12;
+
+.Lcache_synced:
+ SSYNC(r2);
+ sti r7;
+ ( r7:6 ) = [sp++];
+ rets = [sp++];
+ rts
+
+/*
+ * r0 = irqflags
+ * r1 = address of atomic data
+ *
+ * Clobbers: r2:0, p1:0
+ */
+_end_lock_coherent:
+
+ p1 = r1;
+ GET_CPUID(p0, r2);
+ r2 += 28;
+ r1 = 1;
+ r1 <<= r2;
+ r2 = [p1];
+ r2 = r1 | r2;
+ [p1] = r2;
+ r1 = p1;
+ jump _put_core_lock;
+
+#endif /* __ARCH_SYNC_CORE_DCACHE */
+
+/*
+ * r0 = &spinlock->lock
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_spin_is_locked_asm)
+ p1 = r0;
+ [--sp] = rets;
+ call _get_core_lock;
+ r3 = [p1];
+ cc = bittst( r3, 0 );
+ r3 = cc;
+ r1 = p1;
+ call _put_core_lock;
+ rets = [sp++];
+ r0 = r3;
+ rts;
+ENDPROC(___raw_spin_is_locked_asm)
+
+/*
+ * r0 = &spinlock->lock
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_spin_lock_asm)
+ p1 = r0;
+ [--sp] = rets;
+.Lretry_spinlock:
+ call _get_core_lock;
+ r1 = p1;
+ r2 = [p1];
+ cc = bittst( r2, 0 );
+ if cc jump .Lbusy_spinlock
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ r3 = p1;
+ bitset ( r2, 0 ); /* Raise the lock bit. */
+ [p1] = r2;
+ call _start_lock_coherent
+#else
+ r2 = 1;
+ [p1] = r2;
+ call _put_core_lock;
+#endif
+ rets = [sp++];
+ rts;
+
+.Lbusy_spinlock:
+ /* We don't touch the atomic area if busy, so that flush
+ will behave like nop in _put_core_lock. */
+ call _put_core_lock;
+ SSYNC(r2);
+ r0 = p1;
+ jump .Lretry_spinlock
+ENDPROC(___raw_spin_lock_asm)
+
+/*
+ * r0 = &spinlock->lock
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_spin_trylock_asm)
+ p1 = r0;
+ [--sp] = rets;
+ call _get_core_lock;
+ r1 = p1;
+ r3 = [p1];
+ cc = bittst( r3, 0 );
+ if cc jump .Lfailed_trylock
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ bitset ( r3, 0 ); /* Raise the lock bit. */
+ [p1] = r3;
+ call _start_lock_coherent
+#else
+ r2 = 1;
+ [p1] = r2;
+ call _put_core_lock;
+#endif
+ r0 = 1;
+ rets = [sp++];
+ rts;
+.Lfailed_trylock:
+ call _put_core_lock;
+ r0 = 0;
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_spin_trylock_asm)
+
+/*
+ * r0 = &spinlock->lock
+ *
+ * Clobbers: r2:0, p1:0
+ */
+ENTRY(___raw_spin_unlock_asm)
+ p1 = r0;
+ [--sp] = rets;
+ call _get_core_lock;
+ r2 = [p1];
+ bitclr ( r2, 0 );
+ [p1] = r2;
+ r1 = p1;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ call _end_lock_coherent
+#else
+ call _put_core_lock;
+#endif
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_spin_unlock_asm)
+
+/*
+ * r0 = &rwlock->lock
+ *
+ * Clobbers: r2:0, p1:0
+ */
+ENTRY(___raw_read_lock_asm)
+ p1 = r0;
+ [--sp] = rets;
+ call _get_core_lock;
+.Lrdlock_try:
+ r1 = [p1];
+ r1 += -1;
+ [p1] = r1;
+ cc = r1 < 0;
+ if cc jump .Lrdlock_failed
+ r1 = p1;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ call _start_lock_coherent
+#else
+ call _put_core_lock;
+#endif
+ rets = [sp++];
+ rts;
+
+.Lrdlock_failed:
+ r1 += 1;
+ [p1] = r1;
+.Lrdlock_wait:
+ r1 = p1;
+ call _put_core_lock;
+ SSYNC(r2);
+ r0 = p1;
+ call _get_core_lock;
+ r1 = [p1];
+ cc = r1 < 2;
+ if cc jump .Lrdlock_wait;
+ jump .Lrdlock_try
+ENDPROC(___raw_read_lock_asm)
+
+/*
+ * r0 = &rwlock->lock
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_read_trylock_asm)
+ p1 = r0;
+ [--sp] = rets;
+ call _get_core_lock;
+ r1 = [p1];
+ cc = r1 <= 0;
+ if cc jump .Lfailed_tryrdlock;
+ r1 += -1;
+ [p1] = r1;
+ r1 = p1;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ call _start_lock_coherent
+#else
+ call _put_core_lock;
+#endif
+ rets = [sp++];
+ r0 = 1;
+ rts;
+.Lfailed_tryrdlock:
+ r1 = p1;
+ call _put_core_lock;
+ rets = [sp++];
+ r0 = 0;
+ rts;
+ENDPROC(___raw_read_trylock_asm)
+
+/*
+ * r0 = &rwlock->lock
+ *
+ * Note: Processing controlled by a reader lock should not have
+ * any side-effect on cache issues with the other core, so we
+ * just release the core lock and exit (no _end_lock_coherent).
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_read_unlock_asm)
+ p1 = r0;
+ [--sp] = rets;
+ call _get_core_lock;
+ r1 = [p1];
+ r1 += 1;
+ [p1] = r1;
+ r1 = p1;
+ call _put_core_lock;
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_read_unlock_asm)
+
+/*
+ * r0 = &rwlock->lock
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_write_lock_asm)
+ p1 = r0;
+ r3.l = lo(RW_LOCK_BIAS);
+ r3.h = hi(RW_LOCK_BIAS);
+ [--sp] = rets;
+ call _get_core_lock;
+.Lwrlock_try:
+ r1 = [p1];
+ r1 = r1 - r3;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ r2 = r1;
+ r2 <<= 4;
+ r2 >>= 4;
+ cc = r2 == 0;
+#else
+ cc = r1 == 0;
+#endif
+ if !cc jump .Lwrlock_wait
+ [p1] = r1;
+ r1 = p1;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ call _start_lock_coherent
+#else
+ call _put_core_lock;
+#endif
+ rets = [sp++];
+ rts;
+
+.Lwrlock_wait:
+ r1 = p1;
+ call _put_core_lock;
+ SSYNC(r2);
+ r0 = p1;
+ call _get_core_lock;
+ r1 = [p1];
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ r1 <<= 4;
+ r1 >>= 4;
+#endif
+ cc = r1 == r3;
+ if !cc jump .Lwrlock_wait;
+ jump .Lwrlock_try
+ENDPROC(___raw_write_lock_asm)
+
+/*
+ * r0 = &rwlock->lock
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_write_trylock_asm)
+ p1 = r0;
+ [--sp] = rets;
+ call _get_core_lock;
+ r1 = [p1];
+ r2.l = lo(RW_LOCK_BIAS);
+ r2.h = hi(RW_LOCK_BIAS);
+ cc = r1 == r2;
+ if !cc jump .Lfailed_trywrlock;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ r1 >>= 28;
+ r1 <<= 28;
+#else
+ r1 = 0;
+#endif
+ [p1] = r1;
+ r1 = p1;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ call _start_lock_coherent
+#else
+ call _put_core_lock;
+#endif
+ rets = [sp++];
+ r0 = 1;
+ rts;
+
+.Lfailed_trywrlock:
+ r1 = p1;
+ call _put_core_lock;
+ rets = [sp++];
+ r0 = 0;
+ rts;
+ENDPROC(___raw_write_trylock_asm)
+
+/*
+ * r0 = &rwlock->lock
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_write_unlock_asm)
+ p1 = r0;
+ r3.l = lo(RW_LOCK_BIAS);
+ r3.h = hi(RW_LOCK_BIAS);
+ [--sp] = rets;
+ call _get_core_lock;
+ r1 = [p1];
+ r1 = r1 + r3;
+ [p1] = r1;
+ r1 = p1;
+#ifdef __ARCH_SYNC_CORE_DCACHE
+ call _end_lock_coherent
+#else
+ call _put_core_lock;
+#endif
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_write_unlock_asm)
+
+/*
+ * r0 = ptr
+ * r1 = value
+ *
+ * Add a signed value to a 32bit word and return the new value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_atomic_update_asm)
+ p1 = r0;
+ r3 = r1;
+ [--sp] = rets;
+ call _get_core_lock;
+ r2 = [p1];
+ r3 = r3 + r2;
+ [p1] = r3;
+ r1 = p1;
+ call _put_core_lock;
+ r0 = r3;
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_atomic_update_asm)
+
+/*
+ * r0 = ptr
+ * r1 = mask
+ *
+ * Clear the mask bits from a 32bit word and return the old 32bit value
+ * atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_atomic_clear_asm)
+ p1 = r0;
+ r3 = ~r1;
+ [--sp] = rets;
+ call _get_core_lock;
+ r2 = [p1];
+ r3 = r2 & r3;
+ [p1] = r3;
+ r3 = r2;
+ r1 = p1;
+ call _put_core_lock;
+ r0 = r3;
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_atomic_clear_asm)
+
+/*
+ * r0 = ptr
+ * r1 = mask
+ *
+ * Set the mask bits into a 32bit word and return the old 32bit value
+ * atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_atomic_set_asm)
+ p1 = r0;
+ r3 = r1;
+ [--sp] = rets;
+ call _get_core_lock;
+ r2 = [p1];
+ r3 = r2 | r3;
+ [p1] = r3;
+ r3 = r2;
+ r1 = p1;
+ call _put_core_lock;
+ r0 = r3;
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_atomic_set_asm)
+
+/*
+ * r0 = ptr
+ * r1 = mask
+ *
+ * XOR the mask bits with a 32bit word and return the old 32bit value
+ * atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_atomic_xor_asm)
+ p1 = r0;
+ r3 = r1;
+ [--sp] = rets;
+ call _get_core_lock;
+ r2 = [p1];
+ r3 = r2 ^ r3;
+ [p1] = r3;
+ r3 = r2;
+ r1 = p1;
+ call _put_core_lock;
+ r0 = r3;
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_atomic_xor_asm)
+
+/*
+ * r0 = ptr
+ * r1 = mask
+ *
+ * Perform a logical AND between the mask bits and a 32bit word, and
+ * return the masked value. We need this on this architecture in
+ * order to invalidate the local cache before testing.
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_atomic_test_asm)
+ p1 = r0;
+ r3 = r1;
+ r1 = -L1_CACHE_BYTES;
+ r1 = r0 & r1;
+ p0 = r1;
+ flushinv[p0];
+ SSYNC(r2);
+ r0 = [p1];
+ r0 = r0 & r3;
+ rts;
+ENDPROC(___raw_atomic_test_asm)
+
+/*
+ * r0 = ptr
+ * r1 = value
+ *
+ * Swap *ptr with value and return the old 32bit value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+#define __do_xchg(src, dst) \
+ p1 = r0; \
+ r3 = r1; \
+ [--sp] = rets; \
+ call _get_core_lock; \
+ r2 = src; \
+ dst = r3; \
+ r3 = r2; \
+ r1 = p1; \
+ call _put_core_lock; \
+ r0 = r3; \
+ rets = [sp++]; \
+ rts;
+
+ENTRY(___raw_xchg_1_asm)
+ __do_xchg(b[p1] (z), b[p1])
+ENDPROC(___raw_xchg_1_asm)
+
+ENTRY(___raw_xchg_2_asm)
+ __do_xchg(w[p1] (z), w[p1])
+ENDPROC(___raw_xchg_2_asm)
+
+ENTRY(___raw_xchg_4_asm)
+ __do_xchg([p1], [p1])
+ENDPROC(___raw_xchg_4_asm)
+
+/*
+ * r0 = ptr
+ * r1 = new
+ * r2 = old
+ *
+ * Swap *ptr with new if *ptr == old and return the previous *ptr
+ * value atomically.
+ *
+ * Clobbers: r3:0, p1:0
+ */
+#define __do_cmpxchg(src, dst) \
+ [--sp] = rets; \
+ [--sp] = r4; \
+ p1 = r0; \
+ r3 = r1; \
+ r4 = r2; \
+ call _get_core_lock; \
+ r2 = src; \
+ cc = r2 == r4; \
+ if !cc jump 1f; \
+ dst = r3; \
+ 1: r3 = r2; \
+ r1 = p1; \
+ call _put_core_lock; \
+ r0 = r3; \
+ r4 = [sp++]; \
+ rets = [sp++]; \
+ rts;
+
+ENTRY(___raw_cmpxchg_1_asm)
+ __do_cmpxchg(b[p1] (z), b[p1])
+ENDPROC(___raw_cmpxchg_1_asm)
+
+ENTRY(___raw_cmpxchg_2_asm)
+ __do_cmpxchg(w[p1] (z), w[p1])
+ENDPROC(___raw_cmpxchg_2_asm)
+
+ENTRY(___raw_cmpxchg_4_asm)
+ __do_cmpxchg([p1], [p1])
+ENDPROC(___raw_cmpxchg_4_asm)
+
+/*
+ * r0 = ptr
+ * r1 = bitnr
+ *
+ * Set a bit in a 32bit word and return the old 32bit value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_bit_set_asm)
+ r2 = r1;
+ r1 = 1;
+ r1 <<= r2;
+ jump ___raw_atomic_set_asm
+ENDPROC(___raw_bit_set_asm)
+
+/*
+ * r0 = ptr
+ * r1 = bitnr
+ *
+ * Clear a bit in a 32bit word and return the old 32bit value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_bit_clear_asm)
+ r2 = r1;
+ r1 = 1;
+ r1 <<= r2;
+ jump ___raw_atomic_clear_asm
+ENDPROC(___raw_bit_clear_asm)
+
+/*
+ * r0 = ptr
+ * r1 = bitnr
+ *
+ * Toggle a bit in a 32bit word and return the old 32bit value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_bit_toggle_asm)
+ r2 = r1;
+ r1 = 1;
+ r1 <<= r2;
+ jump ___raw_atomic_xor_asm
+ENDPROC(___raw_bit_toggle_asm)
+
+/*
+ * r0 = ptr
+ * r1 = bitnr
+ *
+ * Test-and-set a bit in a 32bit word and return the old bit value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_bit_test_set_asm)
+ [--sp] = rets;
+ [--sp] = r1;
+ call ___raw_bit_set_asm
+ r1 = [sp++];
+ r2 = 1;
+ r2 <<= r1;
+ r0 = r0 & r2;
+ cc = r0 == 0;
+ if cc jump 1f
+ r0 = 1;
+1:
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_bit_test_set_asm)
+
+/*
+ * r0 = ptr
+ * r1 = bitnr
+ *
+ * Test-and-clear a bit in a 32bit word and return the old bit value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_bit_test_clear_asm)
+ [--sp] = rets;
+ [--sp] = r1;
+ call ___raw_bit_clear_asm
+ r1 = [sp++];
+ r2 = 1;
+ r2 <<= r1;
+ r0 = r0 & r2;
+ cc = r0 == 0;
+ if cc jump 1f
+ r0 = 1;
+1:
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_bit_test_clear_asm)
+
+/*
+ * r0 = ptr
+ * r1 = bitnr
+ *
+ * Test-and-toggle a bit in a 32bit word,
+ * and return the old bit value atomically.
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_bit_test_toggle_asm)
+ [--sp] = rets;
+ [--sp] = r1;
+ call ___raw_bit_toggle_asm
+ r1 = [sp++];
+ r2 = 1;
+ r2 <<= r1;
+ r0 = r0 & r2;
+ cc = r0 == 0;
+ if cc jump 1f
+ r0 = 1;
+1:
+ rets = [sp++];
+ rts;
+ENDPROC(___raw_bit_test_toggle_asm)
+
+/*
+ * r0 = ptr
+ * r1 = bitnr
+ *
+ * Test a bit in a 32bit word and return its value.
+ * We need this on this architecture in order to invalidate
+ * the local cache before testing.
+ *
+ * Clobbers: r3:0, p1:0
+ */
+ENTRY(___raw_bit_test_asm)
+ r2 = r1;
+ r1 = 1;
+ r1 <<= r2;
+ jump ___raw_atomic_test_asm
+ENDPROC(___raw_bit_test_asm)
+
+/*
+ * r0 = ptr
+ *
+ * Fetch and return an uncached 32bit value.
+ *
+ * Clobbers: r2:0, p1:0
+ */
+ENTRY(___raw_uncached_fetch_asm)
+ p1 = r0;
+ r1 = -L1_CACHE_BYTES;
+ r1 = r0 & r1;
+ p0 = r1;
+ flushinv[p0];
+ SSYNC(r2);
+ r0 = [p1];
+ rts;
+ENDPROC(___raw_uncached_fetch_asm)
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 8f40990eea2f..6880d1ebfe60 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -230,6 +230,19 @@ static struct platform_device smc91x_device = {
};
#endif
+static struct resource bfin_gpios_resources = {
+ .start = 0,
+ .end = MAX_BLACKFIN_GPIOS - 1,
+ .flags = IORESOURCE_IRQ,
+};
+
+static struct platform_device bfin_gpios_device = {
+ .name = "simple-gpio",
+ .id = -1,
+ .num_resources = 1,
+ .resource = &bfin_gpios_resources,
+};
+
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
static struct resource isp1362_hcd_resources[] = {
{
@@ -287,23 +300,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
#define PATA_INT IRQ_PF46
@@ -382,7 +405,9 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
@@ -400,6 +425,8 @@ static struct platform_device *cm_bf561_devices[] __initdata = {
#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
&bfin_pata_device,
#endif
+
+ &bfin_gpios_device,
};
static int __init cm_bf561_init(void)
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 50b4cdceccfe..0e2178a1aec5 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -43,53 +43,42 @@
/*
* Name the Board for the /proc/cpuinfo
*/
-const char bfin_board_name[] = "ADDS-BF561-EZKIT";
-
-#define ISP1761_BASE 0x2C0F0000
-#define ISP1761_IRQ IRQ_PF10
+const char bfin_board_name[] = "ADI BF561-EZKIT";
#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
-static struct resource bfin_isp1761_resources[] = {
- {
- .name = "isp1761-regs",
- .start = ISP1761_BASE + 0x00000000,
- .end = ISP1761_BASE + 0x000fffff,
+#include <linux/usb/isp1760.h>
+static struct resource bfin_isp1760_resources[] = {
+ [0] = {
+ .start = 0x2C0F0000,
+ .end = 0x203C0000 + 0xfffff,
.flags = IORESOURCE_MEM,
},
- {
- .start = ISP1761_IRQ,
- .end = ISP1761_IRQ,
+ [1] = {
+ .start = IRQ_PF10,
+ .end = IRQ_PF10,
.flags = IORESOURCE_IRQ,
},
};
-static struct platform_device bfin_isp1761_device = {
- .name = "isp1761",
- .id = 0,
- .num_resources = ARRAY_SIZE(bfin_isp1761_resources),
- .resource = bfin_isp1761_resources,
+static struct isp1760_platform_data isp1760_priv = {
+ .is_isp1761 = 0,
+ .port1_disable = 0,
+ .bus_width_16 = 1,
+ .port1_otg = 0,
+ .analog_oc = 0,
+ .dack_polarity_high = 0,
+ .dreq_polarity_high = 0,
};
-static struct platform_device *bfin_isp1761_devices[] = {
- &bfin_isp1761_device,
+static struct platform_device bfin_isp1760_device = {
+ .name = "isp1760-hcd",
+ .id = 0,
+ .dev = {
+ .platform_data = &isp1760_priv,
+ },
+ .num_resources = ARRAY_SIZE(bfin_isp1760_resources),
+ .resource = bfin_isp1760_resources,
};
-
-int __init bfin_isp1761_init(void)
-{
- unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
-
- printk(KERN_INFO "%s(): registering device resources\n", __func__);
- set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
-
- return platform_add_devices(bfin_isp1761_devices, num_devices);
-}
-
-void __exit bfin_isp1761_exit(void)
-{
- platform_device_unregister(&bfin_isp1761_device);
-}
-
-arch_initcall(bfin_isp1761_init);
#endif
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
@@ -221,23 +210,33 @@ static struct platform_device bfin_uart_device = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
-static struct resource bfin_sir_resources[] = {
#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
{
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
},
-#endif
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
};
-static struct platform_device bfin_sir_device = {
+static struct platform_device bfin_sir0_device = {
.name = "bfin_sir",
.id = 0,
- .num_resources = ARRAY_SIZE(bfin_sir_resources),
- .resource = bfin_sir_resources,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
};
#endif
+#endif
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
static struct mtd_partition ezkit_partitions[] = {
@@ -449,6 +448,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
&net2272_bfin_device,
#endif
+#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
+ &bfin_isp1760_device,
+#endif
+
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
&bfin_spi0_device,
#endif
@@ -458,7 +461,9 @@ static struct platform_device *ezkit_devices[] __initdata = {
#endif
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
- &bfin_sir_device,
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
#endif
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
index 2faa0072d614..0ba366a0e696 100644
--- a/arch/blackfin/mach-bf561/boards/generic_board.c
+++ b/arch/blackfin/mach-bf561/boards/generic_board.c
@@ -62,10 +62,45 @@ static struct platform_device smc91x_device = {
};
#endif
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#endif
+
static struct platform_device *generic_board_devices[] __initdata = {
#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
&smc91x_device,
#endif
+
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#endif
};
static int __init generic_board_init(void)
diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c
index c9174b39f98d..6f77dbe952f5 100644
--- a/arch/blackfin/mach-bf561/boards/tepla.c
+++ b/arch/blackfin/mach-bf561/boards/tepla.c
@@ -44,8 +44,42 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+static struct resource bfin_sir0_resources[] = {
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_UART0_RX,
+ .end = IRQ_UART0_RX+1,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = CH_UART0_RX,
+ .end = CH_UART0_RX+1,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device bfin_sir0_device = {
+ .name = "bfin_sir",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bfin_sir0_resources),
+ .resource = bfin_sir0_resources,
+};
+#endif
+#endif
+
static struct platform_device *tepla_devices[] __initdata = {
&smc91x_device,
+#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
+#ifdef CONFIG_BFIN_SIR0
+ &bfin_sir0_device,
+#endif
+#endif
};
static int __init tepla_init(void)
diff --git a/arch/blackfin/mach-bf561/dma.c b/arch/blackfin/mach-bf561/dma.c
index 24415eb82698..42b0037afe61 100644
--- a/arch/blackfin/mach-bf561/dma.c
+++ b/arch/blackfin/mach-bf561/dma.c
@@ -31,7 +31,7 @@
#include <asm/blackfin.h>
#include <asm/dma.h>
-struct dma_register *dma_io_base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+struct dma_register *dma_io_base_addr[MAX_DMA_CHANNELS] = {
(struct dma_register *) DMA1_0_NEXT_DESC_PTR,
(struct dma_register *) DMA1_1_NEXT_DESC_PTR,
(struct dma_register *) DMA1_2_NEXT_DESC_PTR,
diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S
deleted file mode 100644
index 31a777a9e699..000000000000
--- a/arch/blackfin/mach-bf561/head.S
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * File: arch/blackfin/mach-bf561/head.S
- * Based on: arch/blackfin/mach-bf533/head.S
- * Author:
- *
- * Created:
- * Description: BF561 startup file
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/blackfin.h>
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-#include <asm/clocks.h>
-#include <mach/mem_init.h>
-#endif
-
-.section .l1.text
-#ifdef CONFIG_BFIN_KERNEL_CLOCK
-ENTRY(_start_dma_code)
- p0.h = hi(SICA_IWR0);
- p0.l = lo(SICA_IWR0);
- r0.l = 0x1;
- [p0] = r0;
- SSYNC;
-
- /*
- * Set PLL_CTL
- * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
- * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
- * - [7] = output delay (add 200ps of delay to mem signals)
- * - [6] = input delay (add 200ps of input delay to mem signals)
- * - [5] = PDWN : 1=All Clocks off
- * - [3] = STOPCK : 1=Core Clock off
- * - [1] = PLL_OFF : 1=Disable Power to PLL
- * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
- * all other bits set to zero
- */
-
- p0.h = hi(PLL_LOCKCNT);
- p0.l = lo(PLL_LOCKCNT);
- r0 = 0x300(Z);
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITSET (R0, 24);
- [P2] = R0;
- SSYNC;
-
- r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
- r0 = r0 << 9; /* Shift it over, */
- r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
- r0 = r1 | r0;
- r1 = PLL_BYPASS; /* Bypass the PLL? */
- r1 = r1 << 8; /* Shift it over */
- r0 = r1 | r0; /* add them all together */
-#ifdef ANOMALY_05000265
- BITSET(r0, 15); /* Add 250 mV of hysteresis to SPORT input pins */
-#endif
-
- p0.h = hi(PLL_CTL);
- p0.l = lo(PLL_CTL); /* Load the address */
- cli r2; /* Disable interrupts */
- ssync;
- w[p0] = r0.l; /* Set the value */
- idle; /* Wait for the PLL to stablize */
- sti r2; /* Enable interrupts */
-
-.Lcheck_again:
- p0.h = hi(PLL_STAT);
- p0.l = lo(PLL_STAT);
- R0 = W[P0](Z);
- CC = BITTST(R0,5);
- if ! CC jump .Lcheck_again;
-
- /* Configure SCLK & CCLK Dividers */
- r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
- p0.h = hi(PLL_DIV);
- p0.l = lo(PLL_DIV);
- w[p0] = r0.l;
- ssync;
-
- p0.l = lo(EBIU_SDRRC);
- p0.h = hi(EBIU_SDRRC);
- r0 = mem_SDRRC;
- w[p0] = r0.l;
- ssync;
-
- P2.H = hi(EBIU_SDGCTL);
- P2.L = lo(EBIU_SDGCTL);
- R0 = [P2];
- BITCLR (R0, 24);
- p0.h = hi(EBIU_SDSTAT);
- p0.l = lo(EBIU_SDSTAT);
- r2.l = w[p0];
- cc = bittst(r2,3);
- if !cc jump .Lskip;
- NOP;
- BITSET (R0, 23);
-.Lskip:
- [P2] = R0;
- SSYNC;
-
- R0.L = lo(mem_SDGCTL);
- R0.H = hi(mem_SDGCTL);
- R1 = [p2];
- R1 = R1 | R0;
- [P2] = R1;
- SSYNC;
-
- RTS;
-ENDPROC(_start_dma_code)
-#endif /* CONFIG_BFIN_KERNEL_CLOCK */
diff --git a/arch/blackfin/mach-bf561/include/mach/anomaly.h b/arch/blackfin/mach-bf561/include/mach/anomaly.h
index 22990df04ae1..1a9e17562821 100644
--- a/arch/blackfin/mach-bf561/include/mach/anomaly.h
+++ b/arch/blackfin/mach-bf561/include/mach/anomaly.h
@@ -7,7 +7,7 @@
*/
/* This file shoule be up to date with:
- * - Revision P, 02/08/2008; ADSP-BF561 Blackfin Processor Anomaly List
+ * - Revision Q, 11/07/2008; ADSP-BF561 Blackfin Processor Anomaly List
*/
#ifndef _MACH_ANOMALY_H_
@@ -264,6 +264,18 @@
#define ANOMALY_05000371 (1)
/* Level-Sensitive External GPIO Wakeups May Cause Indefinite Stall */
#define ANOMALY_05000403 (1)
+/* TESTSET Instruction Causes Data Corruption with Writeback Data Cache Enabled */
+#define ANOMALY_05000412 (1)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_05000416 (1)
+/* Multichannel SPORT Channel Misalignment Under Specific Configuration */
+#define ANOMALY_05000425 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
+#define ANOMALY_05000426 (1)
+/* Lost/Corrupted L2/L3 Memory Write after Speculative L2 Memory Read by Core B */
+#define ANOMALY_05000428 (__SILICON_REVISION__ > 3)
+/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
+#define ANOMALY_05000443 (1)
/* Anomalies that don't exist on this proc */
#define ANOMALY_05000158 (0)
@@ -272,5 +284,7 @@
#define ANOMALY_05000311 (0)
#define ANOMALY_05000353 (1)
#define ANOMALY_05000386 (1)
+#define ANOMALY_05000432 (0)
+#define ANOMALY_05000435 (0)
#endif
diff --git a/arch/blackfin/mach-bf561/include/mach/bf561.h b/arch/blackfin/mach-bf561/include/mach/bf561.h
index 18b1b3a223ab..9968362a2ee4 100644
--- a/arch/blackfin/mach-bf561/include/mach/bf561.h
+++ b/arch/blackfin/mach-bf561/include/mach/bf561.h
@@ -215,7 +215,7 @@
#endif
#ifndef CPU
-#error Unknown CPU type - This kernel doesn't seem to be configured properly
+#error "Unknown CPU type - This kernel doesn't seem to be configured properly"
#endif
#endif /* __MACH_BF561_H__ */
diff --git a/arch/blackfin/mach-bf561/include/mach/bfin_sir.h b/arch/blackfin/mach-bf561/include/mach/bfin_sir.h
deleted file mode 100644
index 9bb87e9e2e9b..000000000000
--- a/arch/blackfin/mach-bf561/include/mach/bfin_sir.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Blackfin Infra-red Driver
- *
- * Copyright 2006-2008 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- *
- */
-
-#include <linux/serial.h>
-#include <asm/dma.h>
-#include <asm/portmux.h>
-
-#define SIR_UART_GET_CHAR(port) bfin_read16((port)->membase + OFFSET_RBR)
-#define SIR_UART_GET_DLL(port) bfin_read16((port)->membase + OFFSET_DLL)
-#define SIR_UART_GET_IER(port) bfin_read16((port)->membase + OFFSET_IER)
-#define SIR_UART_GET_DLH(port) bfin_read16((port)->membase + OFFSET_DLH)
-#define SIR_UART_GET_IIR(port) bfin_read16((port)->membase + OFFSET_IIR)
-#define SIR_UART_GET_LCR(port) bfin_read16((port)->membase + OFFSET_LCR)
-#define SIR_UART_GET_GCTL(port) bfin_read16((port)->membase + OFFSET_GCTL)
-
-#define SIR_UART_PUT_CHAR(port, v) bfin_write16(((port)->membase + OFFSET_THR), v)
-#define SIR_UART_PUT_DLL(port, v) bfin_write16(((port)->membase + OFFSET_DLL), v)
-#define SIR_UART_PUT_IER(port, v) bfin_write16(((port)->membase + OFFSET_IER), v)
-#define SIR_UART_PUT_DLH(port, v) bfin_write16(((port)->membase + OFFSET_DLH), v)
-#define SIR_UART_PUT_LCR(port, v) bfin_write16(((port)->membase + OFFSET_LCR), v)
-#define SIR_UART_PUT_GCTL(port, v) bfin_write16(((port)->membase + OFFSET_GCTL), v)
-
-#ifdef CONFIG_SIR_BFIN_DMA
-struct dma_rx_buf {
- char *buf;
- int head;
- int tail;
- };
-#endif /* CONFIG_SIR_BFIN_DMA */
-
-struct bfin_sir_port {
- unsigned char __iomem *membase;
- unsigned int irq;
- unsigned int lsr;
- unsigned long clk;
- struct net_device *dev;
-#ifdef CONFIG_SIR_BFIN_DMA
- int tx_done;
- struct dma_rx_buf rx_dma_buf;
- struct timer_list rx_dma_timer;
- int rx_dma_nrows;
-#endif /* CONFIG_SIR_BFIN_DMA */
- unsigned int tx_dma_channel;
- unsigned int rx_dma_channel;
-};
-
-struct bfin_sir_port sir_ports[BFIN_UART_NR_PORTS];
-
-struct bfin_sir_port_res {
- unsigned long base_addr;
- int irq;
- unsigned int rx_dma_channel;
- unsigned int tx_dma_channel;
-};
-
-struct bfin_sir_port_res bfin_sir_port_resource[] = {
-#ifdef CONFIG_BFIN_SIR0
- {
- 0xFFC00400,
- IRQ_UART_RX,
- CH_UART_RX,
- CH_UART_TX,
- },
-#endif
-};
-
-int nr_sirs = ARRAY_SIZE(bfin_sir_port_resource);
-
-struct bfin_sir_self {
- struct bfin_sir_port *sir_port;
- spinlock_t lock;
- unsigned int open;
- int speed;
- int newspeed;
-
- struct sk_buff *txskb;
- struct sk_buff *rxskb;
- struct net_device_stats stats;
- struct device *dev;
- struct irlap_cb *irlap;
- struct qos_info qos;
-
- iobuff_t tx_buff;
- iobuff_t rx_buff;
-
- struct work_struct work;
- int mtt;
-};
-
-static inline unsigned int SIR_UART_GET_LSR(struct bfin_sir_port *port)
-{
- unsigned int lsr = bfin_read16(port->membase + OFFSET_LSR);
- port->lsr |= (lsr & (BI|FE|PE|OE));
- return lsr | port->lsr;
-}
-
-static inline void SIR_UART_CLEAR_LSR(struct bfin_sir_port *port)
-{
- port->lsr = 0;
- bfin_read16(port->membase + OFFSET_LSR);
-}
-
-#define DRIVER_NAME "bfin_sir"
-
-static int bfin_sir_hw_init(void)
-{
- int ret = -ENODEV;
-#ifdef CONFIG_BFIN_SIR0
- ret = peripheral_request(P_UART0_TX, DRIVER_NAME);
- if (ret)
- return ret;
- ret = peripheral_request(P_UART0_RX, DRIVER_NAME);
- if (ret)
- return ret;
-#endif
- return ret;
-}
diff --git a/arch/blackfin/mach-bf561/include/mach/blackfin.h b/arch/blackfin/mach-bf561/include/mach/blackfin.h
index 0ea8666e6764..f79f6626b7ec 100644
--- a/arch/blackfin/mach-bf561/include/mach/blackfin.h
+++ b/arch/blackfin/mach-bf561/include/mach/blackfin.h
@@ -66,8 +66,12 @@
#define bfin_read_SIC_IMASK(x) bfin_read32(SICA_IMASK0 + (x << 2))
#define bfin_write_SIC_IMASK(x, val) bfin_write32((SICA_IMASK0 + (x << 2)), val)
+#define bfin_read_SICB_IMASK(x) bfin_read32(SICB_IMASK0 + (x << 2))
+#define bfin_write_SICB_IMASK(x, val) bfin_write32((SICB_IMASK0 + (x << 2)), val)
#define bfin_read_SIC_ISR(x) bfin_read32(SICA_ISR0 + (x << 2))
#define bfin_write_SIC_ISR(x, val) bfin_write32((SICA_ISR0 + (x << 2)), val)
+#define bfin_read_SICB_ISR(x) bfin_read32(SICB_ISR0 + (x << 2))
+#define bfin_write_SICB_ISR(x, val) bfin_write32((SICB_ISR0 + (x << 2)), val)
#define BFIN_UART_NR_PORTS 1
diff --git a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
index c14d63402e70..95d609f11c97 100644
--- a/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/cdefBF561.h
@@ -39,65 +39,15 @@
/*include core specific register pointer definitions*/
#include <asm/cdef_LPBlackfin.h>
-#include <asm/system.h>
-
/*********************************************************************************** */
/* System MMR Register Map */
/*********************************************************************************** */
/* Clock and System Control (0xFFC00000 - 0xFFC000FF) */
#define bfin_read_PLL_CTL() bfin_read16(PLL_CTL)
-/* Writing to PLL_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_PLL_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_PLL_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SICA_IWR0);
- iwr1 = bfin_read32(SICA_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SICA_IWR0, IWR_ENABLE(0));
- bfin_write32(SICA_IWR1, 0);
-
- bfin_write16(PLL_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SICA_IWR0, iwr0);
- bfin_write32(SICA_IWR1, iwr1);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV,val)
#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
-/* Writing to VR_CTL initiates a PLL relock sequence. */
-static __inline__ void bfin_write_VR_CTL(unsigned int val)
-{
- unsigned long flags, iwr0, iwr1;
-
- if (val == bfin_read_VR_CTL())
- return;
-
- local_irq_save(flags);
- /* Enable the PLL Wakeup bit in SIC IWR */
- iwr0 = bfin_read32(SICA_IWR0);
- iwr1 = bfin_read32(SICA_IWR1);
- /* Only allow PPL Wakeup) */
- bfin_write32(SICA_IWR0, IWR_ENABLE(0));
- bfin_write32(SICA_IWR1, 0);
-
- bfin_write16(VR_CTL, val);
- SSYNC();
- asm("IDLE;");
-
- bfin_write32(SICA_IWR0, iwr0);
- bfin_write32(SICA_IWR1, iwr1);
- local_irq_restore(flags);
-}
#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT,val)
#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
@@ -1576,4 +1526,57 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
#define bfin_read_MDMA_D0_START_ADDR() bfin_read_MDMA1_D0_START_ADDR()
#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write_MDMA1_D0_START_ADDR(val)
+/* These need to be last due to the cdef/linux inter-dependencies */
+#include <asm/irq.h>
+
+/* Writing to PLL_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_PLL_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_PLL_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SICA_IWR0);
+ iwr1 = bfin_read32(SICA_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+ bfin_write32(SICA_IWR1, 0);
+
+ bfin_write16(PLL_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SICA_IWR0, iwr0);
+ bfin_write32(SICA_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1;
+
+ if (val == bfin_read_VR_CTL())
+ return;
+
+ local_irq_save_hw(flags);
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SICA_IWR0);
+ iwr1 = bfin_read32(SICA_IWR1);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+ bfin_write32(SICA_IWR1, 0);
+
+ bfin_write16(VR_CTL, val);
+ SSYNC();
+ asm("IDLE;");
+
+ bfin_write32(SICA_IWR0, iwr0);
+ bfin_write32(SICA_IWR1, iwr1);
+ local_irq_restore_hw(flags);
+}
+
#endif /* _CDEF_BF561_H */
diff --git a/arch/blackfin/mach-bf561/include/mach/defBF561.h b/arch/blackfin/mach-bf561/include/mach/defBF561.h
index 4eca2026bb92..cf922295f4ce 100644
--- a/arch/blackfin/mach-bf561/include/mach/defBF561.h
+++ b/arch/blackfin/mach-bf561/include/mach/defBF561.h
@@ -912,6 +912,9 @@
#define ACTIVE_PLLDISABLED 0x0004 /* Processor In Active Mode With PLL Disabled */
#define PLL_LOCKED 0x0020 /* PLL_LOCKCNT Has Been Reached */
+/* SICA_SYSCR Masks */
+#define COREB_SRAM_INIT 0x0020
+
/* SWRST Mask */
#define SYSTEM_RESET 0x0007 /* Initiates a system software reset */
#define DOUBLE_FAULT_A 0x0008 /* Core A Double Fault Causes Reset */
@@ -1103,6 +1106,8 @@
#define DLEN_8 0x0 /* PPI Data Length mask for DLEN=8 */
#define DLEN(x) (((x-9) & 0x07) << 11) /* PPI Data Length (only works for x=10-->x=16) */
#define POL 0x0000C000 /* PPI Signal Polarities */
+#define POLC 0x4000 /* PPI Clock Polarity */
+#define POLS 0x8000 /* PPI Frame Sync Polarity */
/* PPI_STATUS Masks */
#define FLD 0x00000400 /* Field Indicator */
diff --git a/arch/blackfin/mach-bf561/include/mach/dma.h b/arch/blackfin/mach-bf561/include/mach/dma.h
index 8bc46cd89a02..13647c71f1c7 100644
--- a/arch/blackfin/mach-bf561/include/mach/dma.h
+++ b/arch/blackfin/mach-bf561/include/mach/dma.h
@@ -1,13 +1,17 @@
-/*****************************************************************************
-*
-* BF-533/2/1 Specific Declarations
-*
-****************************************************************************/
+/* mach/dma.h - arch-specific DMA defines
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
#ifndef _MACH_DMA_H_
#define _MACH_DMA_H_
-#define MAX_BLACKFIN_DMA_CHANNEL 36
+#define MAX_DMA_CHANNELS 36
+
+/* [#4267] IMDMA channels have no PERIPHERAL_MAP MMR */
+#define MAX_DMA_SUSPEND_CHANNELS 32
#define CH_PPI0 0
#define CH_PPI (CH_PPI0)
diff --git a/arch/blackfin/mach-bf561/include/mach/gpio.h b/arch/blackfin/mach-bf561/include/mach/gpio.h
new file mode 100644
index 000000000000..7882f79e1ade
--- /dev/null
+++ b/arch/blackfin/mach-bf561/include/mach/gpio.h
@@ -0,0 +1,68 @@
+/*
+ * File: arch/blackfin/mach-bf561/include/mach/gpio.h
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Copyright (C) 2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+
+#ifndef _MACH_GPIO_H_
+#define _MACH_GPIO_H_
+
+#define MAX_BLACKFIN_GPIOS 48
+
+#define GPIO_PF0 0
+#define GPIO_PF1 1
+#define GPIO_PF2 2
+#define GPIO_PF3 3
+#define GPIO_PF4 4
+#define GPIO_PF5 5
+#define GPIO_PF6 6
+#define GPIO_PF7 7
+#define GPIO_PF8 8
+#define GPIO_PF9 9
+#define GPIO_PF10 10
+#define GPIO_PF11 11
+#define GPIO_PF12 12
+#define GPIO_PF13 13
+#define GPIO_PF14 14
+#define GPIO_PF15 15
+#define GPIO_PF16 16
+#define GPIO_PF17 17
+#define GPIO_PF18 18
+#define GPIO_PF19 19
+#define GPIO_PF20 20
+#define GPIO_PF21 21
+#define GPIO_PF22 22
+#define GPIO_PF23 23
+#define GPIO_PF24 24
+#define GPIO_PF25 25
+#define GPIO_PF26 26
+#define GPIO_PF27 27
+#define GPIO_PF28 28
+#define GPIO_PF29 29
+#define GPIO_PF30 30
+#define GPIO_PF31 31
+#define GPIO_PF32 32
+#define GPIO_PF33 33
+#define GPIO_PF34 34
+#define GPIO_PF35 35
+#define GPIO_PF36 36
+#define GPIO_PF37 37
+#define GPIO_PF38 38
+#define GPIO_PF39 39
+#define GPIO_PF40 40
+#define GPIO_PF41 41
+#define GPIO_PF42 42
+#define GPIO_PF43 43
+#define GPIO_PF44 44
+#define GPIO_PF45 45
+#define GPIO_PF46 46
+#define GPIO_PF47 47
+
+#define PORT_FIO0 GPIO_0
+#define PORT_FIO1 GPIO_16
+#define PORT_FIO2 GPIO_32
+
+#endif /* _MACH_GPIO_H_ */
diff --git a/arch/blackfin/mach-bf561/include/mach/mem_init.h b/arch/blackfin/mach-bf561/include/mach/mem_init.h
deleted file mode 100644
index e163260bca18..000000000000
--- a/arch/blackfin/mach-bf561/include/mach/mem_init.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * File: include/asm-blackfin/mach-bf561/mem_init.h
- * Based on:
- * Author:
- *
- * Created:
- * Description:
- *
- * Rev:
- *
- * Modified:
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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; see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_GENERIC_BOARD || CONFIG_MEM_MT48LC8M32B2B5_7)
-#if (CONFIG_SCLK_HZ > 119402985)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_7
-#define SDRAM_tRAS_num 7
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_6
-#define SDRAM_tRAS_num 6
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_5
-#define SDRAM_tRAS_num 5
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_4
-#define SDRAM_tRAS_num 4
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866)
-#define SDRAM_tRP TRP_2
-#define SDRAM_tRP_num 2
-#define SDRAM_tRAS TRAS_3
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_2
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_4
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_3
-#define SDRAM_tRAS_num 3
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_2
-#define SDRAM_tRAS_num 2
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#if (CONFIG_SCLK_HZ <= 29850746)
-#define SDRAM_tRP TRP_1
-#define SDRAM_tRP_num 1
-#define SDRAM_tRAS TRAS_1
-#define SDRAM_tRAS_num 1
-#define SDRAM_tRCD TRCD_1
-#define SDRAM_tWR TWR_2
-#endif
-#endif
-
-#if (CONFIG_MEM_MT48LC16M16A2TG_75)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC64M4A2FB_7E)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_MT48LC8M32B2B5_7)
- /*SDRAM INFORMATION: */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 4096 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-#if (CONFIG_MEM_GENERIC_BOARD)
- /*SDRAM INFORMATION: Modify this for your board */
-#define SDRAM_Tref 64 /* Refresh period in milliseconds */
-#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */
-#define SDRAM_CL CL_3
-#endif
-
-/* Equation from section 17 (p17-46) of BF533 HRM */
-#define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num)
-
-/* Enable SCLK Out */
-#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS)
-
-#if defined CONFIG_CLKIN_HALF
-#define CLKIN_HALF 1
-#else
-#define CLKIN_HALF 0
-#endif
-
-#if defined CONFIG_PLL_BYPASS
-#define PLL_BYPASS 1
-#else
-#define PLL_BYPASS 0
-#endif
-
-/***************************************Currently Not Being Used *********************************/
-#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ))
-#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
-
-#if (flash_EBIU_AMBCTL_TT > 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_4
-#endif
-#if (flash_EBIU_AMBCTL_TT == 3)
-#define flash_EBIU_AMBCTL0_TT B0TT_3
-#endif
-#if (flash_EBIU_AMBCTL_TT == 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_2
-#endif
-#if (flash_EBIU_AMBCTL_TT < 2)
-#define flash_EBIU_AMBCTL0_TT B0TT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_ST > 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_4
-#endif
-#if (flash_EBIU_AMBCTL_ST == 3)
-#define flash_EBIU_AMBCTL0_ST B0ST_3
-#endif
-#if (flash_EBIU_AMBCTL_ST == 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_2
-#endif
-#if (flash_EBIU_AMBCTL_ST < 2)
-#define flash_EBIU_AMBCTL0_ST B0ST_1
-#endif
-
-#if (flash_EBIU_AMBCTL_HT > 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_3
-#endif
-#if (flash_EBIU_AMBCTL_HT == 2)
-#define flash_EBIU_AMBCTL0_HT B0HT_2
-#endif
-#if (flash_EBIU_AMBCTL_HT == 1)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_0
-#endif
-#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
-#define flash_EBIU_AMBCTL0_HT B0HT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_WAT > 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_15
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 14)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_14
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 13)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_13
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 12)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_12
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 11)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_11
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 10)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_10
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 9)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_9
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 8)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_8
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 7)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_7
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 6)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_6
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 5)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_5
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 4)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_4
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 3)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_3
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 2)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_2
-#endif
-#if (flash_EBIU_AMBCTL_WAT == 1)
-#define flash_EBIU_AMBCTL0_WAT B0WAT_1
-#endif
-
-#if (flash_EBIU_AMBCTL_RAT > 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_15
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 14)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_14
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 13)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_13
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 12)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_12
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 11)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_11
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 10)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_10
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 9)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_9
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 8)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_8
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 7)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_7
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 6)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_6
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 5)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_5
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 4)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_4
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 3)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_3
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 2)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_2
-#endif
-#if (flash_EBIU_AMBCTL_RAT == 1)
-#define flash_EBIU_AMBCTL0_RAT B0RAT_1
-#endif
-
-#define flash_EBIU_AMBCTL0 \
- (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
- flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/arch/blackfin/mach-bf561/include/mach/mem_map.h b/arch/blackfin/mach-bf561/include/mach/mem_map.h
index f1d4c0637bd2..419dffdc96eb 100644
--- a/arch/blackfin/mach-bf561/include/mach/mem_map.h
+++ b/arch/blackfin/mach-bf561/include/mach/mem_map.h
@@ -85,4 +85,84 @@
#define L1_SCRATCH_START COREA_L1_SCRATCH_START
#define L1_SCRATCH_LENGTH 0x1000
+#ifdef __ASSEMBLY__
+
+/*
+ * The following macros both return the address of the PDA for the
+ * current core.
+ *
+ * In its first safe (and hairy) form, the macro neither clobbers any
+ * register aside of the output Preg, nor uses the stack, since it
+ * could be called with an invalid stack pointer, or the current stack
+ * space being uncovered by any CPLB (e.g. early exception handling).
+ *
+ * The constraints on the second form are a bit relaxed, and the code
+ * is allowed to use the specified Dreg for determining the PDA
+ * address to be returned into Preg.
+ */
+#ifdef CONFIG_SMP
+#define GET_PDA_SAFE(preg) \
+ preg.l = lo(DSPID); \
+ preg.h = hi(DSPID); \
+ preg = [preg]; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ preg = preg << 2; \
+ if cc jump 2f; \
+ cc = preg == 0x0; \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda; \
+ if !cc jump 3f; \
+1: \
+ /* preg = 0x0; */ \
+ cc = !cc; /* restore cc to 0 */ \
+ jump 4f; \
+2: \
+ cc = preg == 0x0; \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda; \
+ if cc jump 4f; \
+ /* preg = 0x1000000; */ \
+ cc = !cc; /* restore cc to 1 */ \
+3: \
+ preg = [preg]; \
+4:
+
+#define GET_PDA(preg, dreg) \
+ preg.l = lo(DSPID); \
+ preg.h = hi(DSPID); \
+ dreg = [preg]; \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda; \
+ cc = bittst(dreg, 0); \
+ if !cc jump 1f; \
+ preg = [preg]; \
+1: \
+
+#define GET_CPUID(preg, dreg) \
+ preg.l = lo(DSPID); \
+ preg.h = hi(DSPID); \
+ dreg = [preg]; \
+ dreg = ROT dreg BY -1; \
+ dreg = CC;
+
+#else
+#define GET_PDA_SAFE(preg) \
+ preg.l = _cpu_pda; \
+ preg.h = _cpu_pda;
+
+#define GET_PDA(preg, dreg) GET_PDA_SAFE(preg)
+#endif /* CONFIG_SMP */
+
+#endif /* __ASSEMBLY__ */
+
#endif /* _MEM_MAP_533_H_ */
diff --git a/arch/blackfin/mach-bf561/include/mach/portmux.h b/arch/blackfin/mach-bf561/include/mach/portmux.h
index a6ee8206efb6..2e5ad6347dea 100644
--- a/arch/blackfin/mach-bf561/include/mach/portmux.h
+++ b/arch/blackfin/mach-bf561/include/mach/portmux.h
@@ -85,5 +85,6 @@
#define P_SPI0_MOSI (P_DONTCARE)
#define P_SPI0_MISO (P_DONTCARE)
#define P_SPI0_SCK (P_DONTCARE)
+#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2
#endif /* _MACH_PORTMUX_H_ */
diff --git a/arch/blackfin/mach-bf561/include/mach/smp.h b/arch/blackfin/mach-bf561/include/mach/smp.h
new file mode 100644
index 000000000000..f9e65ebe81b2
--- /dev/null
+++ b/arch/blackfin/mach-bf561/include/mach/smp.h
@@ -0,0 +1,22 @@
+#ifndef _MACH_BF561_SMP
+#define _MACH_BF561_SMP
+
+struct task_struct;
+
+void platform_init_cpus(void);
+
+void platform_prepare_cpus(unsigned int max_cpus);
+
+int platform_boot_secondary(unsigned int cpu, struct task_struct *idle);
+
+void platform_secondary_init(unsigned int cpu);
+
+void platform_request_ipi(int (*handler)(int, void *));
+
+void platform_send_ipi(cpumask_t callmap);
+
+void platform_send_ipi_cpu(unsigned int cpu);
+
+void platform_clear_ipi(unsigned int cpu);
+
+#endif /* !_MACH_BF561_SMP */
diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S
new file mode 100644
index 000000000000..35280f06b7b6
--- /dev/null
+++ b/arch/blackfin/mach-bf561/secondary.S
@@ -0,0 +1,215 @@
+/*
+ * File: arch/blackfin/mach-bf561/secondary.S
+ * Based on: arch/blackfin/mach-bf561/head.S
+ * Author: Philippe Gerum <rpm@xenomai.org>
+ *
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * Description: BF561 coreB bootstrap file
+ *
+ * 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/blackfin.h>
+#include <asm/asm-offsets.h>
+
+__INIT
+
+/* Lay the initial stack into the L1 scratch area of Core B */
+#define INITIAL_STACK (COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
+
+ENTRY(_coreb_trampoline_start)
+ /* Set the SYSCFG register */
+ R0 = 0x36;
+ SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+ R0 = 0;
+
+ /*Clear Out All the data and pointer Registers*/
+ R1 = R0;
+ R2 = R0;
+ R3 = R0;
+ R4 = R0;
+ R5 = R0;
+ R6 = R0;
+ R7 = R0;
+
+ P0 = R0;
+ P1 = R0;
+ P2 = R0;
+ P3 = R0;
+ P4 = R0;
+ P5 = R0;
+
+ LC0 = r0;
+ LC1 = r0;
+ L0 = r0;
+ L1 = r0;
+ L2 = r0;
+ L3 = r0;
+
+ /* Clear Out All the DAG Registers*/
+ B0 = r0;
+ B1 = r0;
+ B2 = r0;
+ B3 = r0;
+
+ I0 = r0;
+ I1 = r0;
+ I2 = r0;
+ I3 = r0;
+
+ M0 = r0;
+ M1 = r0;
+ M2 = r0;
+ M3 = r0;
+
+ /* Turn off the icache */
+ p0.l = LO(IMEM_CONTROL);
+ p0.h = HI(IMEM_CONTROL);
+ R1 = [p0];
+ R0 = ~ENICPLB;
+ R0 = R0 & R1;
+
+ /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+ CLI R2;
+ SSYNC;
+#endif
+ [p0] = R0;
+ SSYNC;
+#ifdef ANOMALY_05000125
+ STI R2;
+#endif
+
+ /* Turn off the dcache */
+ p0.l = LO(DMEM_CONTROL);
+ p0.h = HI(DMEM_CONTROL);
+ R1 = [p0];
+ R0 = ~ENDCPLB;
+ R0 = R0 & R1;
+
+ /* Anomaly 05000125 */
+#ifdef ANOMALY_05000125
+ CLI R2;
+ SSYNC;
+#endif
+ [p0] = R0;
+ SSYNC;
+#ifdef ANOMALY_05000125
+ STI R2;
+#endif
+
+ /* in case of double faults, save a few things */
+ p0.l = _init_retx_coreb;
+ p0.h = _init_retx_coreb;
+ R0 = RETX;
+ [P0] = R0;
+
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+ /* Only save these if we are storing them,
+ * This happens here, since L1 gets clobbered
+ * below
+ */
+ GET_PDA(p0, r0);
+ r7 = [p0 + PDA_RETX];
+ p1.l = _init_saved_retx_coreb;
+ p1.h = _init_saved_retx_coreb;
+ [p1] = r7;
+
+ r7 = [p0 + PDA_DCPLB];
+ p1.l = _init_saved_dcplb_fault_addr_coreb;
+ p1.h = _init_saved_dcplb_fault_addr_coreb;
+ [p1] = r7;
+
+ r7 = [p0 + PDA_ICPLB];
+ p1.l = _init_saved_icplb_fault_addr_coreb;
+ p1.h = _init_saved_icplb_fault_addr_coreb;
+ [p1] = r7;
+
+ r7 = [p0 + PDA_SEQSTAT];
+ p1.l = _init_saved_seqstat_coreb;
+ p1.h = _init_saved_seqstat_coreb;
+ [p1] = r7;
+#endif
+
+ /* Initialize stack pointer */
+ sp.l = lo(INITIAL_STACK);
+ sp.h = hi(INITIAL_STACK);
+ fp = sp;
+ usp = sp;
+
+ /* This section keeps the processor in supervisor mode
+ * during core B startup. Branches to the idle task.
+ */
+
+ /* EVT15 = _real_start */
+
+ p0.l = lo(EVT15);
+ p0.h = hi(EVT15);
+ p1.l = _coreb_start;
+ p1.h = _coreb_start;
+ [p0] = p1;
+ csync;
+
+ p0.l = lo(IMASK);
+ p0.h = hi(IMASK);
+ p1.l = IMASK_IVG15;
+ p1.h = 0x0;
+ [p0] = p1;
+ csync;
+
+ raise 15;
+ p0.l = .LWAIT_HERE;
+ p0.h = .LWAIT_HERE;
+ reti = p0;
+#if defined(ANOMALY_05000281)
+ nop; nop; nop;
+#endif
+ rti;
+
+.LWAIT_HERE:
+ jump .LWAIT_HERE;
+ENDPROC(_coreb_trampoline_start)
+ENTRY(_coreb_trampoline_end)
+
+ENTRY(_coreb_start)
+ [--sp] = reti;
+
+ p0.l = lo(WDOGB_CTL);
+ p0.h = hi(WDOGB_CTL);
+ r0 = 0xAD6(z);
+ w[p0] = r0; /* Clear the watchdog. */
+ ssync;
+
+ /*
+ * switch to IDLE stack.
+ */
+ p0.l = _secondary_stack;
+ p0.h = _secondary_stack;
+ sp = [p0];
+ usp = sp;
+ fp = sp;
+ sp += -12;
+ call _init_pda
+ sp += 12;
+ call _secondary_start_kernel;
+.L_exit:
+ jump.s .L_exit;
+ENDPROC(_coreb_start)
+
+__FINIT
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c
new file mode 100644
index 000000000000..9b27e698c0b2
--- /dev/null
+++ b/arch/blackfin/mach-bf561/smp.c
@@ -0,0 +1,167 @@
+/*
+ * File: arch/blackfin/mach-bf561/smp.c
+ * Author: Philippe Gerum <rpm@xenomai.org>
+ *
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <asm/smp.h>
+#include <asm/dma.h>
+
+static DEFINE_SPINLOCK(boot_lock);
+
+static cpumask_t cpu_callin_map;
+
+/*
+ * platform_init_cpus() - Tell the world about how many cores we
+ * have. This is called while setting up the architecture support
+ * (setup_arch()), so don't be too demanding here with respect to
+ * available kernel services.
+ */
+
+void __init platform_init_cpus(void)
+{
+ cpu_set(0, cpu_possible_map); /* CoreA */
+ cpu_set(1, cpu_possible_map); /* CoreB */
+}
+
+void __init platform_prepare_cpus(unsigned int max_cpus)
+{
+ int len;
+
+ len = &coreb_trampoline_end - &coreb_trampoline_start + 1;
+ BUG_ON(len > L1_CODE_LENGTH);
+
+ dma_memcpy((void *)COREB_L1_CODE_START, &coreb_trampoline_start, len);
+
+ /* Both cores ought to be present on a bf561! */
+ cpu_set(0, cpu_present_map); /* CoreA */
+ cpu_set(1, cpu_present_map); /* CoreB */
+
+ printk(KERN_INFO "CoreB bootstrap code to SRAM %p via DMA.\n", (void *)COREB_L1_CODE_START);
+}
+
+int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
+{
+ return -EINVAL;
+}
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+ local_irq_disable();
+
+ /* Clone setup for peripheral interrupt sources from CoreA. */
+ bfin_write_SICB_IMASK0(bfin_read_SICA_IMASK0());
+ bfin_write_SICB_IMASK1(bfin_read_SICA_IMASK1());
+ SSYNC();
+
+ /* Clone setup for IARs from CoreA. */
+ bfin_write_SICB_IAR0(bfin_read_SICA_IAR0());
+ bfin_write_SICB_IAR1(bfin_read_SICA_IAR1());
+ bfin_write_SICB_IAR2(bfin_read_SICA_IAR2());
+ bfin_write_SICB_IAR3(bfin_read_SICA_IAR3());
+ bfin_write_SICB_IAR4(bfin_read_SICA_IAR4());
+ bfin_write_SICB_IAR5(bfin_read_SICA_IAR5());
+ bfin_write_SICB_IAR6(bfin_read_SICA_IAR6());
+ bfin_write_SICB_IAR7(bfin_read_SICA_IAR7());
+ SSYNC();
+
+ local_irq_enable();
+
+ /* Calibrate loops per jiffy value. */
+ calibrate_delay();
+
+ /* Store CPU-private information to the cpu_data array. */
+ bfin_setup_cpudata(cpu);
+
+ /* We are done with local CPU inits, unblock the boot CPU. */
+ cpu_set(cpu, cpu_callin_map);
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long timeout;
+
+ /* CoreB already running?! */
+ BUG_ON((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0);
+
+ printk(KERN_INFO "Booting Core B.\n");
+
+ spin_lock(&boot_lock);
+
+ /* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
+ SSYNC();
+ bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
+ SSYNC();
+
+ timeout = jiffies + 1 * HZ;
+ while (time_before(jiffies, timeout)) {
+ if (cpu_isset(cpu, cpu_callin_map))
+ break;
+ udelay(100);
+ barrier();
+ }
+
+ spin_unlock(&boot_lock);
+
+ return cpu_isset(cpu, cpu_callin_map) ? 0 : -ENOSYS;
+}
+
+void __init platform_request_ipi(irq_handler_t handler)
+{
+ int ret;
+
+ ret = request_irq(IRQ_SUPPLE_0, handler, IRQF_DISABLED,
+ "SMP interrupt", handler);
+ if (ret)
+ panic("Cannot request supplemental interrupt 0 for IPI service\n");
+}
+
+void platform_send_ipi(cpumask_t callmap)
+{
+ unsigned int cpu;
+
+ for_each_cpu_mask(cpu, callmap) {
+ BUG_ON(cpu >= 2);
+ SSYNC();
+ bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (6 + cpu)));
+ SSYNC();
+ }
+}
+
+void platform_send_ipi_cpu(unsigned int cpu)
+{
+ BUG_ON(cpu >= 2);
+ SSYNC();
+ bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (6 + cpu)));
+ SSYNC();
+}
+
+void platform_clear_ipi(unsigned int cpu)
+{
+ BUG_ON(cpu >= 2);
+ SSYNC();
+ bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + cpu)));
+ SSYNC();
+}
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
index e6ed57c56d4b..1f3228ed713f 100644
--- a/arch/blackfin/mach-common/Makefile
+++ b/arch/blackfin/mach-common/Makefile
@@ -3,10 +3,12 @@
#
obj-y := \
- cache.o entry.o head.o \
+ cache.o cache-c.o entry.o head.o \
interrupt.o irqpanic.o arch_checks.o ints-priority.o
obj-$(CONFIG_BFIN_ICACHE_LOCK) += lock.o
obj-$(CONFIG_PM) += pm.o dpmc_modes.o
obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o
diff --git a/arch/blackfin/mach-common/cache-c.c b/arch/blackfin/mach-common/cache-c.c
new file mode 100644
index 000000000000..e6ab1f815123
--- /dev/null
+++ b/arch/blackfin/mach-common/cache-c.c
@@ -0,0 +1,24 @@
+/*
+ * Blackfin cache control code (simpler control-style functions)
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <asm/blackfin.h>
+
+/* Invalidate the Entire Data cache by
+ * clearing DMC[1:0] bits
+ */
+void blackfin_invalidate_entire_dcache(void)
+{
+ u32 dmem = bfin_read_DMEM_CONTROL();
+ SSYNC();
+ bfin_write_DMEM_CONTROL(dmem & ~0xc);
+ SSYNC();
+ bfin_write_DMEM_CONTROL(dmem);
+ SSYNC();
+}
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
index a028e9450419..3c98dacbf289 100644
--- a/arch/blackfin/mach-common/cache.S
+++ b/arch/blackfin/mach-common/cache.S
@@ -49,13 +49,17 @@
.ifnb \optflushins
\optflushins [P0];
.endif
+#if ANOMALY_05000443
.ifb \optnopins
2:
.endif
\flushins [P0++];
.ifnb \optnopins
-2: \optnopins;
+2: \optnopins;
.endif
+#else
+2: \flushins [P0++];
+#endif
RTS;
.endm
diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c
new file mode 100644
index 000000000000..9dddb6f8cc85
--- /dev/null
+++ b/arch/blackfin/mach-common/clocks-init.c
@@ -0,0 +1,94 @@
+/*
+ * arch/blackfin/mach-common/clocks-init.c - reprogram clocks / memory
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/blackfin.h>
+
+#include <asm/dma.h>
+#include <asm/clocks.h>
+#include <asm/mem_init.h>
+
+#define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */
+#define PLL_CTL_VAL \
+ (((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \
+ (PLL_BYPASS << 8) | (ANOMALY_05000265 ? 0x8000 : 0))
+
+__attribute__((l1_text))
+static void do_sync(void)
+{
+ __builtin_bfin_ssync();
+}
+
+__attribute__((l1_text))
+void init_clocks(void)
+{
+ /* Kill any active DMAs as they may trigger external memory accesses
+ * in the middle of reprogramming things, and that'll screw us up.
+ * For example, any automatic DMAs left by U-Boot for splash screens.
+ */
+ size_t i;
+ for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
+ struct dma_register *dma = dma_io_base_addr[i];
+ dma->cfg = 0;
+ }
+
+ do_sync();
+
+#ifdef SIC_IWR0
+ bfin_write_SIC_IWR0(IWR_ENABLE(0));
+# ifdef SIC_IWR1
+ /* BF52x system reset does not properly reset SIC_IWR1 which
+ * will screw up the bootrom as it relies on MDMA0/1 waking it
+ * up from IDLE instructions. See this report for more info:
+ * http://blackfin.uclinux.org/gf/tracker/4323
+ */
+ if (ANOMALY_05000435)
+ bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
+ else
+ bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
+# endif
+# ifdef SIC_IWR2
+ bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
+# endif
+#else
+ bfin_write_SIC_IWR(IWR_ENABLE(0));
+#endif
+ do_sync();
+#ifdef EBIU_SDGCTL
+ bfin_write_EBIU_SDGCTL(bfin_read_EBIU_SDGCTL() | SRFS);
+ do_sync();
+#endif
+
+#ifdef CLKBUFOE
+ bfin_write16(VR_CTL, bfin_read_VR_CTL() | CLKBUFOE);
+ do_sync();
+ __asm__ __volatile__("IDLE;");
+#endif
+ bfin_write_PLL_LOCKCNT(0x300);
+ do_sync();
+ bfin_write16(PLL_CTL, PLL_CTL_VAL);
+ __asm__ __volatile__("IDLE;");
+ bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+#ifdef EBIU_SDGCTL
+ bfin_write_EBIU_SDRRC(mem_SDRRC);
+ bfin_write_EBIU_SDGCTL((bfin_read_EBIU_SDGCTL() & SDGCTL_WIDTH) | mem_SDGCTL);
+#else
+ bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ));
+ do_sync();
+ bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() | 0x1);
+ bfin_write_EBIU_DDRCTL0(mem_DDRCTL0);
+ bfin_write_EBIU_DDRCTL1(mem_DDRCTL1);
+ bfin_write_EBIU_DDRCTL2(mem_DDRCTL2);
+#ifdef CONFIG_MEM_EBIU_DDRQUE
+ bfin_write_EBIU_DDRQUE(CONFIG_MEM_EBIU_DDRQUE);
+#endif
+#endif
+ do_sync();
+ bfin_read16(0);
+}
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index dda5443b37ed..72e16605ca09 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -104,7 +104,7 @@ static int bfin_target(struct cpufreq_policy *policy,
cclk_hz, target_freq, freqs.old);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- local_irq_save(flags);
+ local_irq_save_hw(flags);
plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
tscale = dpm_state_table[index].tscale;
bfin_write_PLL_DIV(plldiv);
@@ -112,10 +112,10 @@ static int bfin_target(struct cpufreq_policy *policy,
bfin_write_TSCALE(tscale);
cycles = get_cycles();
SSYNC();
- cycles += 10; /* ~10 cycles we loose after get_cycles() */
+ cycles += 10; /* ~10 cycles we lose after get_cycles() */
__bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index);
__bfin_cycles_mod = index;
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
/* TODO: just test case for cycles clock source, remove later */
pr_debug("cpufreq: done\n");
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
diff --git a/arch/blackfin/mach-common/dpmc_modes.S b/arch/blackfin/mach-common/dpmc_modes.S
index ad5431e2cd05..4da50bcd9300 100644
--- a/arch/blackfin/mach-common/dpmc_modes.S
+++ b/arch/blackfin/mach-common/dpmc_modes.S
@@ -247,7 +247,8 @@ ENTRY(_unset_dram_srfs)
ENDPROC(_unset_dram_srfs)
ENTRY(_set_sic_iwr)
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \
+ defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x)
P0.H = hi(SIC_IWR0);
P0.L = lo(SIC_IWR0);
P1.H = hi(SIC_IWR1);
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index bde6dc4e2614..88de053bbe8e 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -36,6 +36,7 @@
#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/unistd.h>
+#include <linux/threads.h>
#include <asm/blackfin.h>
#include <asm/errno.h>
#include <asm/fixed_code.h>
@@ -75,11 +76,11 @@ ENTRY(_ex_workaround_261)
* handle it.
*/
P4 = R7; /* Store EXCAUSE */
- p5.l = _last_cplb_fault_retx;
- p5.h = _last_cplb_fault_retx;
- r7 = [p5];
+
+ GET_PDA(p5, r7);
+ r7 = [p5 + PDA_LFRETX];
r6 = retx;
- [p5] = r6;
+ [p5 + PDA_LFRETX] = r6;
cc = r6 == r7;
if !cc jump _bfin_return_from_exception;
/* fall through */
@@ -111,24 +112,21 @@ ENTRY(_ex_dcplb_viol)
ENTRY(_ex_dcplb_miss)
ENTRY(_ex_icplb_miss)
(R7:6,P5:4) = [sp++];
- ASTAT = [sp++];
- SAVE_ALL_SYS
-#ifdef CONFIG_MPU
+ /* We leave the previously pushed ASTAT on the stack. */
+ SAVE_CONTEXT_CPLB
+
/* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that
* will change the stack pointer. */
R0 = SEQSTAT;
R1 = SP;
-#endif
+
DEBUG_HWTRACE_SAVE(p5, r7)
-#ifdef CONFIG_MPU
+
sp += -12;
call _cplb_hdr;
sp += 12;
CC = R0 == 0;
IF !CC JUMP _handle_bad_cplb;
-#else
- call __cplb_hdr;
-#endif
#ifdef CONFIG_DEBUG_DOUBLEFAULT
/* While we were processing this, did we double fault? */
@@ -142,7 +140,8 @@ ENTRY(_ex_icplb_miss)
#endif
DEBUG_HWTRACE_RESTORE(p5, r7)
- RESTORE_ALL_SYS
+ RESTORE_CONTEXT_CPLB
+ ASTAT = [SP++];
SP = EX_SCRATCH_REG;
rtx;
ENDPROC(_ex_icplb_miss)
@@ -152,13 +151,6 @@ ENTRY(_ex_syscall)
jump.s _bfin_return_from_exception;
ENDPROC(_ex_syscall)
-ENTRY(_ex_soft_bp)
- r7 = retx;
- r7 += -2;
- retx = r7;
- jump.s _ex_trap_c;
-ENDPROC(_ex_soft_bp)
-
ENTRY(_ex_single_step)
/* If we just returned from an interrupt, the single step event is
for the RTI instruction. */
@@ -297,9 +289,8 @@ ENTRY(_handle_bad_cplb)
* the stack to get ready so, we can fall through - we
* need to make a CPLB exception look like a normal exception
*/
-
- RESTORE_ALL_SYS
- [--sp] = ASTAT;
+ RESTORE_CONTEXT_CPLB
+ /* ASTAT is still on the stack, where it is needed. */
[--sp] = (R7:6,P5:4);
ENTRY(_ex_replaceable)
@@ -324,7 +315,9 @@ ENTRY(_ex_trap_c)
[p4] = p5;
csync;
+ GET_PDA(p5, r6);
#ifndef CONFIG_DEBUG_DOUBLEFAULT
+
/*
* Save these registers, as they are only valid in exception context
* (where we are now - as soon as we defer to IRQ5, they can change)
@@ -335,29 +328,25 @@ ENTRY(_ex_trap_c)
p4.l = lo(DCPLB_FAULT_ADDR);
p4.h = hi(DCPLB_FAULT_ADDR);
r7 = [p4];
- p5.h = _saved_dcplb_fault_addr;
- p5.l = _saved_dcplb_fault_addr;
- [p5] = r7;
+ [p5 + PDA_DCPLB] = r7;
- r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
- p5.h = _saved_icplb_fault_addr;
- p5.l = _saved_icplb_fault_addr;
- [p5] = r7;
+ p4.l = lo(ICPLB_FAULT_ADDR);
+ p4.h = hi(ICPLB_FAULT_ADDR);
+ r6 = [p4];
+ [p5 + PDA_ICPLB] = r6;
r6 = retx;
- p4.l = _saved_retx;
- p4.h = _saved_retx;
- [p4] = r6;
+ [p5 + PDA_RETX] = r6;
#endif
r6 = SYSCFG;
- [p4 + 4] = r6;
+ [p5 + PDA_SYSCFG] = r6;
BITCLR(r6, 0);
SYSCFG = r6;
/* Disable all interrupts, but make sure level 5 is enabled so
* we can switch to that level. Save the old mask. */
cli r6;
- [p4 + 8] = r6;
+ [p5 + PDA_EXIMASK] = r6;
p4.l = lo(SAFE_USER_INSTRUCTION);
p4.h = hi(SAFE_USER_INSTRUCTION);
@@ -371,9 +360,10 @@ ENTRY(_ex_trap_c)
ENDPROC(_ex_trap_c)
/* We just realized we got an exception, while we were processing a different
- * exception. This is a unrecoverable event, so crash
+ * exception. This is a unrecoverable event, so crash.
+ * Note: this cannot be ENTRY() as we jump here with "if cc jump" ...
*/
-ENTRY(_double_fault)
+_double_fault:
/* Turn caches & protection off, to ensure we don't get any more
* double exceptions
*/
@@ -424,17 +414,16 @@ ENDPROC(_double_fault)
ENTRY(_exception_to_level5)
SAVE_ALL_SYS
- p4.l = _saved_retx;
- p4.h = _saved_retx;
- r6 = [p4];
+ GET_PDA(p4, r7); /* Fetch current PDA */
+ r6 = [p4 + PDA_RETX];
[sp + PT_PC] = r6;
- r6 = [p4 + 4];
+ r6 = [p4 + PDA_SYSCFG];
[sp + PT_SYSCFG] = r6;
/* Restore interrupt mask. We haven't pushed RETI, so this
* doesn't enable interrupts until we return from this handler. */
- r6 = [p4 + 8];
+ r6 = [p4 + PDA_EXIMASK];
sti r6;
/* Restore the hardware error vector. */
@@ -478,8 +467,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
* scratch register (for want of a better option).
*/
EX_SCRATCH_REG = sp;
- sp.l = _exception_stack_top;
- sp.h = _exception_stack_top;
+ GET_PDA_SAFE(sp);
+ sp = [sp + PDA_EXSTACK]
/* Try to deal with syscalls quickly. */
[--sp] = ASTAT;
[--sp] = (R7:6,P5:4);
@@ -501,27 +490,22 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
* but they are not very interesting, so don't save them
*/
+ GET_PDA(p5, r7);
p4.l = lo(DCPLB_FAULT_ADDR);
p4.h = hi(DCPLB_FAULT_ADDR);
r7 = [p4];
- p5.h = _saved_dcplb_fault_addr;
- p5.l = _saved_dcplb_fault_addr;
- [p5] = r7;
+ [p5 + PDA_DCPLB] = r7;
- r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
- p5.h = _saved_icplb_fault_addr;
- p5.l = _saved_icplb_fault_addr;
- [p5] = r7;
+ p4.l = lo(ICPLB_FAULT_ADDR);
+ p4.h = hi(ICPLB_FAULT_ADDR);
+ r7 = [p4];
+ [p5 + PDA_ICPLB] = r7;
- p4.l = _saved_retx;
- p4.h = _saved_retx;
r6 = retx;
- [p4] = r6;
+ [p5 + PDA_RETX] = r6;
r7 = SEQSTAT; /* reason code is in bit 5:0 */
- p4.l = _saved_seqstat;
- p4.h = _saved_seqstat;
- [p4] = r7;
+ [p5 + PDA_SEQSTAT] = r7;
#else
r7 = SEQSTAT; /* reason code is in bit 5:0 */
#endif
@@ -546,11 +530,11 @@ ENTRY(_kernel_execve)
p0 = sp;
r3 = SIZEOF_PTREGS / 4;
r4 = 0(x);
-0:
+.Lclear_regs:
[p0++] = r4;
r3 += -1;
cc = r3 == 0;
- if !cc jump 0b (bp);
+ if !cc jump .Lclear_regs (bp);
p0 = sp;
sp += -16;
@@ -558,7 +542,7 @@ ENTRY(_kernel_execve)
call _do_execve;
SP += 16;
cc = r0 == 0;
- if ! cc jump 1f;
+ if ! cc jump .Lexecve_failed;
/* Success. Copy our temporary pt_regs to the top of the kernel
* stack and do a normal exception return.
*/
@@ -574,12 +558,12 @@ ENTRY(_kernel_execve)
p0 = fp;
r4 = [p0--];
r3 = SIZEOF_PTREGS / 4;
-0:
+.Lcopy_regs:
r4 = [p0--];
[p1--] = r4;
r3 += -1;
cc = r3 == 0;
- if ! cc jump 0b (bp);
+ if ! cc jump .Lcopy_regs (bp);
r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z);
p1 = r0;
@@ -591,7 +575,7 @@ ENTRY(_kernel_execve)
RESTORE_CONTEXT;
rti;
-1:
+.Lexecve_failed:
unlink;
rts;
ENDPROC(_kernel_execve)
@@ -925,9 +909,14 @@ _schedule_and_signal_from_int:
p1 = rets;
[sp + PT_RESERVED] = p1;
- p0.l = _irq_flags;
- p0.h = _irq_flags;
+#ifdef CONFIG_SMP
+ GET_PDA(p0, r0); /* Fetch current PDA (can't migrate to other CPU here) */
+ r0 = [p0 + PDA_IRQFLAGS];
+#else
+ p0.l = _bfin_irq_flags;
+ p0.h = _bfin_irq_flags;
r0 = [p0];
+#endif
sti r0;
r0 = sp;
@@ -1091,7 +1080,7 @@ ENTRY(_ex_table)
* EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
*/
.long _ex_syscall /* 0x00 - User Defined - Linux Syscall */
- .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */
+ .long _ex_trap_c /* 0x01 - User Defined - Software breakpoint */
#ifdef CONFIG_KGDB
.long _ex_trap_c /* 0x02 - User Defined - KGDB initial connection
and break signal trap */
@@ -1539,14 +1528,18 @@ ENTRY(_sys_call_table)
.endr
END(_sys_call_table)
-_exception_stack:
- .rept 1024
- .long 0;
+#ifdef CONFIG_EXCEPTION_L1_SCRATCH
+/* .section .l1.bss.scratch */
+.set _exception_stack_top, L1_SCRATCH_START + L1_SCRATCH_LENGTH
+#else
+#ifdef CONFIG_SYSCALL_TAB_L1
+.section .l1.bss
+#else
+.bss
+#endif
+ENTRY(_exception_stack)
+ .rept 1024 * NR_CPUS
+ .long 0
.endr
_exception_stack_top:
-
-#if ANOMALY_05000261
-/* Used by the assembly entry point to work around an anomaly. */
-_last_cplb_fault_retx:
- .long 0;
#endif
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S
index f123a62e2451..698d4c05947e 100644
--- a/arch/blackfin/mach-common/head.S
+++ b/arch/blackfin/mach-common/head.S
@@ -13,9 +13,23 @@
#include <asm/blackfin.h>
#include <asm/thread_info.h>
#include <asm/trace.h>
+#include <asm/asm-offsets.h>
__INIT
+ENTRY(__init_clear_bss)
+ r2 = r2 - r1;
+ cc = r2 == 0;
+ if cc jump .L_bss_done;
+ r2 >>= 2;
+ p1 = r1;
+ p2 = r2;
+ lsetup (1f, 1f) lc0 = p2;
+1: [p1++] = r0;
+.L_bss_done:
+ rts;
+ENDPROC(__init_clear_bss)
+
#define INITIAL_STACK (L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
ENTRY(__start)
@@ -111,33 +125,26 @@ ENTRY(__start)
* This happens here, since L1 gets clobbered
* below
*/
- p0.l = _saved_retx;
- p0.h = _saved_retx;
+ GET_PDA(p0, r0);
+ r7 = [p0 + PDA_RETX];
p1.l = _init_saved_retx;
p1.h = _init_saved_retx;
- r0 = [p0];
- [p1] = r0;
+ [p1] = r7;
- p0.l = _saved_dcplb_fault_addr;
- p0.h = _saved_dcplb_fault_addr;
+ r7 = [p0 + PDA_DCPLB];
p1.l = _init_saved_dcplb_fault_addr;
p1.h = _init_saved_dcplb_fault_addr;
- r0 = [p0];
- [p1] = r0;
+ [p1] = r7;
- p0.l = _saved_icplb_fault_addr;
- p0.h = _saved_icplb_fault_addr;
+ r7 = [p0 + PDA_ICPLB];
p1.l = _init_saved_icplb_fault_addr;
p1.h = _init_saved_icplb_fault_addr;
- r0 = [p0];
- [p1] = r0;
+ [p1] = r7;
- p0.l = _saved_seqstat;
- p0.h = _saved_seqstat;
+ r7 = [p0 + PDA_SEQSTAT];
p1.l = _init_saved_seqstat;
p1.h = _init_saved_seqstat;
- r0 = [p0];
- [p1] = r0;
+ [p1] = r7;
#endif
/* Initialize stack pointer */
@@ -150,10 +157,39 @@ ENTRY(__start)
call _init_early_exception_vectors;
#endif
+ r0 = 0 (x);
+ /* Zero out all of the fun bss regions */
+#if L1_DATA_A_LENGTH > 0
+ r1.l = __sbss_l1;
+ r1.h = __sbss_l1;
+ r2.l = __ebss_l1;
+ r2.h = __ebss_l1;
+ call __init_clear_bss
+#endif
+#if L1_DATA_B_LENGTH > 0
+ r1.l = __sbss_b_l1;
+ r1.h = __sbss_b_l1;
+ r2.l = __ebss_b_l1;
+ r2.h = __ebss_b_l1;
+ call __init_clear_bss
+#endif
+#if L2_LENGTH > 0
+ r1.l = __sbss_l2;
+ r1.h = __sbss_l2;
+ r2.l = __ebss_l2;
+ r2.h = __ebss_l2;
+ call __init_clear_bss
+#endif
+ r1.l = ___bss_start;
+ r1.h = ___bss_start;
+ r2.l = ___bss_stop;
+ r2.h = ___bss_stop;
+ call __init_clear_bss
+
/* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
call _bfin_relocate_l1_mem;
#ifdef CONFIG_BFIN_KERNEL_CLOCK
- call _start_dma_code;
+ call _init_clocks;
#endif
/* This section keeps the processor in supervisor mode
@@ -170,12 +206,8 @@ ENTRY(__start)
[p0] = p1;
csync;
- p0.l = lo(IMASK);
- p0.h = hi(IMASK);
- p1.l = IMASK_IVG15;
- p1.h = 0x0;
- [p0] = p1;
- csync;
+ r0 = EVT_IVG15 (z);
+ sti r0;
raise 15;
p0.l = .LWAIT_HERE;
@@ -206,88 +238,6 @@ ENTRY(_real_start)
w[p0] = r0;
ssync;
-#if L1_DATA_A_LENGTH > 0
- r1.l = __sbss_l1;
- r1.h = __sbss_l1;
- r2.l = __ebss_l1;
- r2.h = __ebss_l1;
- r0 = 0 (z);
- r2 = r2 - r1;
- cc = r2 == 0;
- if cc jump .L_a_l1_done;
- r2 >>= 2;
- p1 = r1;
- p2 = r2;
- lsetup (.L_clear_a_l1, .L_clear_a_l1 ) lc0 = p2;
-.L_clear_a_l1:
- [p1++] = r0;
-.L_a_l1_done:
-#endif
-
-#if L1_DATA_B_LENGTH > 0
- r1.l = __sbss_b_l1;
- r1.h = __sbss_b_l1;
- r2.l = __ebss_b_l1;
- r2.h = __ebss_b_l1;
- r0 = 0 (z);
- r2 = r2 - r1;
- cc = r2 == 0;
- if cc jump .L_b_l1_done;
- r2 >>= 2;
- p1 = r1;
- p2 = r2;
- lsetup (.L_clear_b_l1, .L_clear_b_l1 ) lc0 = p2;
-.L_clear_b_l1:
- [p1++] = r0;
-.L_b_l1_done:
-#endif
-
-#if L2_LENGTH > 0
- r1.l = __sbss_l2;
- r1.h = __sbss_l2;
- r2.l = __ebss_l2;
- r2.h = __ebss_l2;
- r0 = 0 (z);
- r2 = r2 - r1;
- cc = r2 == 0;
- if cc jump .L_l2_done;
- r2 >>= 2;
- p1 = r1;
- p2 = r2;
- lsetup (.L_clear_l2, .L_clear_l2 ) lc0 = p2;
-.L_clear_l2:
- [p1++] = r0;
-.L_l2_done:
-#endif
-
- /* Zero out the bss region
- * Note: this will fail if bss is 0 bytes ...
- */
- r0 = 0 (z);
- r1.l = ___bss_start;
- r1.h = ___bss_start;
- r2.l = ___bss_stop;
- r2.h = ___bss_stop;
- r2 = r2 - r1;
- r2 >>= 2;
- p1 = r1;
- p2 = r2;
- lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
-.L_clear_bss:
- [p1++] = r0;
-
- /* In case there is a NULL pointer reference,
- * zero out region before stext
- */
- p1 = r0;
- r2.l = __stext;
- r2.h = __stext;
- r2 >>= 2;
- p2 = r2;
- lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
-.L_clear_zero:
- [p1++] = r0;
-
/* Pass the u-boot arguments to the global value command line */
R0 = R7;
call _cmdline_init;
@@ -299,6 +249,9 @@ ENTRY(_real_start)
sp = sp + p1;
usp = sp;
fp = sp;
+ sp += -12;
+ call _init_pda
+ sp += 12;
jump.l _start_kernel;
ENDPROC(_real_start)
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index 4a2ec7a9675a..43c4eb9acb65 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -129,8 +129,15 @@ __common_int_entry:
#endif
r1 = sp;
SP += -12;
+#ifdef CONFIG_IPIPE
+ call ___ipipe_grab_irq
+ SP += 12;
+ cc = r0 == 0;
+ if cc jump .Lcommon_restore_context;
+#else /* CONFIG_IPIPE */
call _do_irq;
SP += 12;
+#endif /* CONFIG_IPIPE */
call _return_from_int;
.Lcommon_restore_context:
RESTORE_CONTEXT
@@ -152,15 +159,6 @@ ENTRY(_evt_ivhw)
1:
#endif
-#ifdef CONFIG_HARDWARE_PM
- r7 = [sp + PT_SEQSTAT];
- r7 = r7 >>> 0xe;
- r6 = 0x1F;
- r7 = r7 & r6;
- r5 = 0x12;
- cc = r7 == r5;
- if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */
-#endif
# We are going to dump something out, so make sure we print IPEND properly
p2.l = lo(IPEND);
p2.h = hi(IPEND);
@@ -192,23 +190,12 @@ ENTRY(_evt_ivhw)
.Lcommon_restore_all_sys:
RESTORE_ALL_SYS
rti;
-
-#ifdef CONFIG_HARDWARE_PM
-.Lcall_do_ovf:
-
- SP += -12;
- call _pm_overflow;
- SP += 12;
-
- jump .Lcommon_restore_all_sys;
-#endif
-
ENDPROC(_evt_ivhw)
/* Interrupt routine for evt2 (NMI).
* We don't actually use this, so just return.
* For inner circle type details, please see:
- * http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi
+ * http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:nmi
*/
ENTRY(_evt_nmi)
.weak _evt_nmi
@@ -245,3 +232,56 @@ ENTRY(_evt_system_call)
call _system_call;
jump .Lcommon_restore_context;
ENDPROC(_evt_system_call)
+
+#ifdef CONFIG_IPIPE
+ENTRY(___ipipe_call_irqtail)
+ r0.l = 1f;
+ r0.h = 1f;
+ reti = r0;
+ rti;
+1:
+ [--sp] = rets;
+ [--sp] = ( r7:4, p5:3 );
+ p0.l = ___ipipe_irq_tail_hook;
+ p0.h = ___ipipe_irq_tail_hook;
+ p0 = [p0];
+ sp += -12;
+ call (p0);
+ sp += 12;
+ ( r7:4, p5:3 ) = [sp++];
+ rets = [sp++];
+
+ [--sp] = reti;
+ reti = [sp++]; /* IRQs are off. */
+ r0.h = 3f;
+ r0.l = 3f;
+ p0.l = lo(EVT14);
+ p0.h = hi(EVT14);
+ [p0] = r0;
+ csync;
+ r0 = 0x401f;
+ sti r0;
+ raise 14;
+ [--sp] = reti; /* IRQs on. */
+2:
+ jump 2b; /* Likely paranoid. */
+3:
+ sp += 4; /* Discard saved RETI */
+ r0.h = _evt14_softirq;
+ r0.l = _evt14_softirq;
+ p0.l = lo(EVT14);
+ p0.h = hi(EVT14);
+ [p0] = r0;
+ csync;
+ p0.l = _bfin_irq_flags;
+ p0.h = _bfin_irq_flags;
+ r0 = [p0];
+ sti r0;
+#if 0 /* FIXME: this actually raises scheduling latencies */
+ /* Reenable interrupts */
+ [--sp] = reti;
+ r0 = [sp++];
+#endif
+ rts;
+ENDPROC(___ipipe_call_irqtail)
+#endif /* CONFIG_IPIPE */
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 34e8a726ffda..202494568c6c 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -1,9 +1,6 @@
/*
* File: arch/blackfin/mach-common/ints-priority.c
- * Based on:
- * Author:
*
- * Created: ?
* Description: Set up the interrupt priorities
*
* Modified:
@@ -37,6 +34,9 @@
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/irq.h>
+#ifdef CONFIG_IPIPE
+#include <linux/ipipe.h>
+#endif
#ifdef CONFIG_KGDB
#include <linux/kgdb.h>
#endif
@@ -45,6 +45,8 @@
#include <asm/gpio.h>
#include <asm/irq_handler.h>
+#define SIC_SYSIRQ(irq) (irq - (IRQ_CORETMR + 1))
+
#ifdef BF537_FAMILY
# define BF537_GENERIC_ERROR_INT_DEMUX
#else
@@ -58,13 +60,16 @@
* -
*/
+#ifndef CONFIG_SMP
/* Initialize this to an actual value to force it into the .data
* section so that we know it is properly initialized at entry into
* the kernel but before bss is initialized to zero (which is where
* it would live otherwise). The 0x1f magic represents the IRQs we
* cannot actually mask out in hardware.
*/
-unsigned long irq_flags = 0x1f;
+unsigned long bfin_irq_flags = 0x1f;
+EXPORT_SYMBOL(bfin_irq_flags);
+#endif
/* The number of spurious interrupts */
atomic_t num_spurious;
@@ -103,12 +108,14 @@ static void __init search_IAR(void)
for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
int iar_shift = (irqn & 7) * 4;
if (ivg == (0xf &
-#ifndef CONFIG_BF52x
+#if defined(CONFIG_BF52x) || defined(CONFIG_BF538) \
+ || defined(CONFIG_BF539) || defined(CONFIG_BF51x)
bfin_read32((unsigned long *)SIC_IAR0 +
- (irqn >> 3)) >> iar_shift)) {
+ ((irqn % 32) >> 3) + ((irqn / 32) *
+ ((SIC_IAR4 - SIC_IAR0) / 4))) >> iar_shift)) {
#else
bfin_read32((unsigned long *)SIC_IAR0 +
- ((irqn%32) >> 3) + ((irqn / 32) * 16)) >> iar_shift)) {
+ (irqn >> 3)) >> iar_shift)) {
#endif
ivg_table[irq_pos].irqno = IVG7 + irqn;
ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
@@ -130,25 +137,25 @@ static void bfin_ack_noop(unsigned int irq)
static void bfin_core_mask_irq(unsigned int irq)
{
- irq_flags &= ~(1 << irq);
- if (!irqs_disabled())
- local_irq_enable();
+ bfin_irq_flags &= ~(1 << irq);
+ if (!irqs_disabled_hw())
+ local_irq_enable_hw();
}
static void bfin_core_unmask_irq(unsigned int irq)
{
- irq_flags |= 1 << irq;
+ bfin_irq_flags |= 1 << irq;
/*
* If interrupts are enabled, IMASK must contain the same value
- * as irq_flags. Make sure that invariant holds. If interrupts
+ * as bfin_irq_flags. Make sure that invariant holds. If interrupts
* are currently disabled we need not do anything; one of the
* callers will take care of setting IMASK to the proper value
* when reenabling interrupts.
- * local_irq_enable just does "STI irq_flags", so it's exactly
+ * local_irq_enable just does "STI bfin_irq_flags", so it's exactly
* what we need.
*/
- if (!irqs_disabled())
- local_irq_enable();
+ if (!irqs_disabled_hw())
+ local_irq_enable_hw();
return;
}
@@ -163,8 +170,11 @@ static void bfin_internal_mask_irq(unsigned int irq)
mask_bit = SIC_SYSIRQ(irq) % 32;
bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
~(1 << mask_bit));
+#ifdef CONFIG_SMP
+ bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) &
+ ~(1 << mask_bit));
+#endif
#endif
- SSYNC();
}
static void bfin_internal_unmask_irq(unsigned int irq)
@@ -178,14 +188,17 @@ static void bfin_internal_unmask_irq(unsigned int irq)
mask_bit = SIC_SYSIRQ(irq) % 32;
bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
(1 << mask_bit));
+#ifdef CONFIG_SMP
+ bfin_write_SICB_IMASK(mask_bank, bfin_read_SICB_IMASK(mask_bank) |
+ (1 << mask_bit));
+#endif
#endif
- SSYNC();
}
#ifdef CONFIG_PM
int bfin_internal_set_wake(unsigned int irq, unsigned int state)
{
- unsigned bank, bit, wakeup = 0;
+ u32 bank, bit, wakeup = 0;
unsigned long flags;
bank = SIC_SYSIRQ(irq) / 32;
bit = SIC_SYSIRQ(irq) % 32;
@@ -225,7 +238,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
break;
}
- local_irq_save(flags);
+ local_irq_save_hw(flags);
if (state) {
bfin_sic_iwr[bank] |= (1 << bit);
@@ -236,7 +249,7 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
vr_wakeup &= ~wakeup;
}
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
return 0;
}
@@ -262,6 +275,19 @@ static struct irq_chip bfin_internal_irqchip = {
#endif
};
+static void bfin_handle_irq(unsigned irq)
+{
+#ifdef CONFIG_IPIPE
+ struct pt_regs regs; /* Contents not used. */
+ ipipe_trace_irq_entry(irq);
+ __ipipe_handle_irq(irq, &regs);
+ ipipe_trace_irq_exit(irq);
+#else /* !CONFIG_IPIPE */
+ struct irq_desc *desc = irq_desc + irq;
+ desc->handle_irq(irq, desc);
+#endif /* !CONFIG_IPIPE */
+}
+
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
static int error_int_mask;
@@ -292,8 +318,6 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
{
int irq = 0;
- SSYNC();
-
#if (defined(CONFIG_BF537) || defined(CONFIG_BF536))
if (bfin_read_EMAC_SYSTAT() & EMAC_ERR_MASK)
irq = IRQ_MAC_ERROR;
@@ -317,10 +341,9 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
irq = IRQ_UART1_ERROR;
if (irq) {
- if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR))) {
- struct irq_desc *desc = irq_desc + irq;
- desc->handle_irq(irq, desc);
- } else {
+ if (error_int_mask & (1L << (irq - IRQ_PPI_ERROR)))
+ bfin_handle_irq(irq);
+ else {
switch (irq) {
case IRQ_PPI_ERROR:
@@ -366,62 +389,57 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
{
+#ifdef CONFIG_IPIPE
+ _set_irq_handler(irq, handle_edge_irq);
+#else
struct irq_desc *desc = irq_desc + irq;
/* May not call generic set_irq_handler() due to spinlock
recursion. */
desc->handle_irq = handle;
+#endif
}
-#if !defined(CONFIG_BF54x)
-
-static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
-static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
-
+static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
extern void bfin_gpio_irq_prepare(unsigned gpio);
+#if !defined(CONFIG_BF54x)
+
static void bfin_gpio_ack_irq(unsigned int irq)
{
- u16 gpionr = irq - IRQ_PF0;
-
- if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
- set_gpio_data(gpionr, 0);
- SSYNC();
- }
+ /* AFAIK ack_irq in case mask_ack is provided
+ * get's only called for edge sense irqs
+ */
+ set_gpio_data(irq_to_gpio(irq), 0);
}
static void bfin_gpio_mask_ack_irq(unsigned int irq)
{
- u16 gpionr = irq - IRQ_PF0;
+ struct irq_desc *desc = irq_desc + irq;
+ u32 gpionr = irq_to_gpio(irq);
- if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+ if (desc->handle_irq == handle_edge_irq)
set_gpio_data(gpionr, 0);
- SSYNC();
- }
set_gpio_maska(gpionr, 0);
- SSYNC();
}
static void bfin_gpio_mask_irq(unsigned int irq)
{
- set_gpio_maska(irq - IRQ_PF0, 0);
- SSYNC();
+ set_gpio_maska(irq_to_gpio(irq), 0);
}
static void bfin_gpio_unmask_irq(unsigned int irq)
{
- set_gpio_maska(irq - IRQ_PF0, 1);
- SSYNC();
+ set_gpio_maska(irq_to_gpio(irq), 1);
}
static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{
- u16 gpionr = irq - IRQ_PF0;
+ u32 gpionr = irq_to_gpio(irq);
- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+ if (__test_and_set_bit(gpionr, gpio_enabled))
bfin_gpio_irq_prepare(gpionr);
- gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
bfin_gpio_unmask_irq(irq);
return 0;
@@ -429,29 +447,39 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
static void bfin_gpio_irq_shutdown(unsigned int irq)
{
+ u32 gpionr = irq_to_gpio(irq);
+
bfin_gpio_mask_irq(irq);
- gpio_enabled[gpio_bank(irq - IRQ_PF0)] &= ~gpio_bit(irq - IRQ_PF0);
+ __clear_bit(gpionr, gpio_enabled);
+ bfin_gpio_irq_free(gpionr);
}
static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{
- u16 gpionr = irq - IRQ_PF0;
+ int ret;
+ char buf[16];
+ u32 gpionr = irq_to_gpio(irq);
if (type == IRQ_TYPE_PROBE) {
/* only probe unenabled GPIO interrupt lines */
- if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
+ if (__test_bit(gpionr, gpio_enabled))
return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
}
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+
+ snprintf(buf, 16, "gpio-irq%d", irq);
+ ret = bfin_gpio_irq_request(gpionr, buf);
+ if (ret)
+ return ret;
+
+ if (__test_and_set_bit(gpionr, gpio_enabled))
bfin_gpio_irq_prepare(gpionr);
- gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
} else {
- gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+ __clear_bit(gpionr, gpio_enabled);
return 0;
}
@@ -472,17 +500,13 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
set_gpio_edge(gpionr, 1);
set_gpio_inen(gpionr, 1);
- gpio_edge_triggered[gpio_bank(gpionr)] |= gpio_bit(gpionr);
set_gpio_data(gpionr, 0);
} else {
set_gpio_edge(gpionr, 0);
- gpio_edge_triggered[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
set_gpio_inen(gpionr, 1);
}
- SSYNC();
-
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
bfin_set_irq_handler(irq, handle_edge_irq);
else
@@ -505,22 +529,6 @@ int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
}
#endif
-static struct irq_chip bfin_gpio_irqchip = {
- .name = "GPIO",
- .ack = bfin_gpio_ack_irq,
- .mask = bfin_gpio_mask_irq,
- .mask_ack = bfin_gpio_mask_ack_irq,
- .unmask = bfin_gpio_unmask_irq,
- .disable = bfin_gpio_mask_irq,
- .enable = bfin_gpio_unmask_irq,
- .set_type = bfin_gpio_irq_type,
- .startup = bfin_gpio_irq_startup,
- .shutdown = bfin_gpio_irq_shutdown,
-#ifdef CONFIG_PM
- .set_wake = bfin_gpio_set_wake,
-#endif
-};
-
static void bfin_demux_gpio_irq(unsigned int inta_irq,
struct irq_desc *desc)
{
@@ -537,7 +545,11 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
irq = IRQ_PH0;
break;
# endif
-#elif defined(CONFIG_BF52x)
+#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
+ case IRQ_PORTF_INTA:
+ irq = IRQ_PF0;
+ break;
+#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
case IRQ_PORTF_INTA:
irq = IRQ_PF0;
break;
@@ -567,30 +579,22 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
irq += i;
- mask = get_gpiop_data(i) &
- (gpio_enabled[gpio_bank(i)] &
- get_gpiop_maska(i));
+ mask = get_gpiop_data(i) & get_gpiop_maska(i);
while (mask) {
- if (mask & 1) {
- desc = irq_desc + irq;
- desc->handle_irq(irq, desc);
- }
+ if (mask & 1)
+ bfin_handle_irq(irq);
irq++;
mask >>= 1;
}
}
} else {
gpio = irq_to_gpio(irq);
- mask = get_gpiop_data(gpio) &
- (gpio_enabled[gpio_bank(gpio)] &
- get_gpiop_maska(gpio));
+ mask = get_gpiop_data(gpio) & get_gpiop_maska(gpio);
do {
- if (mask & 1) {
- desc = irq_desc + irq;
- desc->handle_irq(irq, desc);
- }
+ if (mask & 1)
+ bfin_handle_irq(irq);
irq++;
mask >>= 1;
} while (mask);
@@ -612,10 +616,6 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
static unsigned char irq2pint_lut[NR_PINTS];
static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
-static unsigned int gpio_both_edge_triggered[NR_PINT_SYS_IRQS];
-static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
-
-
struct pin_int_t {
unsigned int mask_set;
unsigned int mask_clear;
@@ -636,12 +636,9 @@ static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
(struct pin_int_t *)PINT3_MASK_SET,
};
-extern void bfin_gpio_irq_prepare(unsigned gpio);
-
-inline unsigned short get_irq_base(u8 bank, u8 bmap)
+inline unsigned int get_irq_base(u32 bank, u8 bmap)
{
-
- u16 irq_base;
+ unsigned int irq_base;
if (bank < 2) { /*PA-PB */
irq_base = IRQ_PA0 + bmap * 16;
@@ -650,7 +647,6 @@ inline unsigned short get_irq_base(u8 bank, u8 bmap)
}
return irq_base;
-
}
/* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
@@ -677,20 +673,18 @@ void init_pint_lut(void)
pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;
irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;
-
}
-
}
-
}
static void bfin_gpio_ack_irq(unsigned int irq)
{
- u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ struct irq_desc *desc = irq_desc + irq;
+ u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
u32 pintbit = PINT_BIT(pint_val);
- u8 bank = PINT_2_BANK(pint_val);
+ u32 bank = PINT_2_BANK(pint_val);
- if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) {
+ if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
if (pint[bank]->invert_set & pintbit)
pint[bank]->invert_clear = pintbit;
else
@@ -698,16 +692,16 @@ static void bfin_gpio_ack_irq(unsigned int irq)
}
pint[bank]->request = pintbit;
- SSYNC();
}
static void bfin_gpio_mask_ack_irq(unsigned int irq)
{
- u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ struct irq_desc *desc = irq_desc + irq;
+ u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
u32 pintbit = PINT_BIT(pint_val);
- u8 bank = PINT_2_BANK(pint_val);
+ u32 bank = PINT_2_BANK(pint_val);
- if (unlikely(gpio_both_edge_triggered[bank] & pintbit)) {
+ if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
if (pint[bank]->invert_set & pintbit)
pint[bank]->invert_clear = pintbit;
else
@@ -716,32 +710,29 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq)
pint[bank]->request = pintbit;
pint[bank]->mask_clear = pintbit;
- SSYNC();
}
static void bfin_gpio_mask_irq(unsigned int irq)
{
- u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
- SSYNC();
}
static void bfin_gpio_unmask_irq(unsigned int irq)
{
- u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
u32 pintbit = PINT_BIT(pint_val);
- u8 bank = PINT_2_BANK(pint_val);
+ u32 bank = PINT_2_BANK(pint_val);
pint[bank]->request = pintbit;
pint[bank]->mask_set = pintbit;
- SSYNC();
}
static unsigned int bfin_gpio_irq_startup(unsigned int irq)
{
- u16 gpionr = irq_to_gpio(irq);
- u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 gpionr = irq_to_gpio(irq);
+ u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
if (pint_val == IRQ_NOT_AVAIL) {
printk(KERN_ERR
@@ -750,10 +741,9 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
return -ENODEV;
}
- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+ if (__test_and_set_bit(gpionr, gpio_enabled))
bfin_gpio_irq_prepare(gpionr);
- gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
bfin_gpio_unmask_irq(irq);
return 0;
@@ -761,38 +751,45 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
static void bfin_gpio_irq_shutdown(unsigned int irq)
{
- u16 gpionr = irq_to_gpio(irq);
+ u32 gpionr = irq_to_gpio(irq);
bfin_gpio_mask_irq(irq);
- gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+ __clear_bit(gpionr, gpio_enabled);
+ bfin_gpio_irq_free(gpionr);
}
static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
{
-
- u16 gpionr = irq_to_gpio(irq);
- u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ int ret;
+ char buf[16];
+ u32 gpionr = irq_to_gpio(irq);
+ u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
u32 pintbit = PINT_BIT(pint_val);
- u8 bank = PINT_2_BANK(pint_val);
+ u32 bank = PINT_2_BANK(pint_val);
if (pint_val == IRQ_NOT_AVAIL)
return -ENODEV;
if (type == IRQ_TYPE_PROBE) {
/* only probe unenabled GPIO interrupt lines */
- if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
+ if (__test_bit(gpionr, gpio_enabled))
return 0;
type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
}
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
- if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr)))
+
+ snprintf(buf, 16, "gpio-irq%d", irq);
+ ret = bfin_gpio_irq_request(gpionr, buf);
+ if (ret)
+ return ret;
+
+ if (__test_and_set_bit(gpionr, gpio_enabled))
bfin_gpio_irq_prepare(gpionr);
- gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
} else {
- gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+ __clear_bit(gpionr, gpio_enabled);
return 0;
}
@@ -803,15 +800,10 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
== (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-
- gpio_both_edge_triggered[bank] |= pintbit;
-
if (gpio_get_value(gpionr))
pint[bank]->invert_set = pintbit;
else
pint[bank]->invert_clear = pintbit;
- } else {
- gpio_both_edge_triggered[bank] &= ~pintbit;
}
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
@@ -822,8 +814,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
bfin_set_irq_handler(irq, handle_level_irq);
}
- SSYNC();
-
return 0;
}
@@ -834,7 +824,7 @@ u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
{
u32 pint_irq;
- u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
u32 bank = PINT_2_BANK(pint_val);
u32 pintbit = PINT_BIT(pint_val);
@@ -895,26 +885,10 @@ void bfin_pm_restore(void)
}
#endif
-static struct irq_chip bfin_gpio_irqchip = {
- .name = "GPIO",
- .ack = bfin_gpio_ack_irq,
- .mask = bfin_gpio_mask_irq,
- .mask_ack = bfin_gpio_mask_ack_irq,
- .unmask = bfin_gpio_unmask_irq,
- .disable = bfin_gpio_mask_irq,
- .enable = bfin_gpio_unmask_irq,
- .set_type = bfin_gpio_irq_type,
- .startup = bfin_gpio_irq_startup,
- .shutdown = bfin_gpio_irq_shutdown,
-#ifdef CONFIG_PM
- .set_wake = bfin_gpio_set_wake,
-#endif
-};
-
static void bfin_demux_gpio_irq(unsigned int inta_irq,
struct irq_desc *desc)
{
- u8 bank, pint_val;
+ u32 bank, pint_val;
u32 request, irq;
switch (inta_irq) {
@@ -941,8 +915,7 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
while (request) {
if (request & 1) {
irq = pint2irq_lut[pint_val] + SYS_IRQS;
- desc = irq_desc + irq;
- desc->handle_irq(irq, desc);
+ bfin_handle_irq(irq);
}
pint_val++;
request >>= 1;
@@ -951,10 +924,24 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
}
#endif
-void __init init_exception_vectors(void)
-{
- SSYNC();
+static struct irq_chip bfin_gpio_irqchip = {
+ .name = "GPIO",
+ .ack = bfin_gpio_ack_irq,
+ .mask = bfin_gpio_mask_irq,
+ .mask_ack = bfin_gpio_mask_ack_irq,
+ .unmask = bfin_gpio_unmask_irq,
+ .disable = bfin_gpio_mask_irq,
+ .enable = bfin_gpio_unmask_irq,
+ .set_type = bfin_gpio_irq_type,
+ .startup = bfin_gpio_irq_startup,
+ .shutdown = bfin_gpio_irq_shutdown,
+#ifdef CONFIG_PM
+ .set_wake = bfin_gpio_set_wake,
+#endif
+};
+void __cpuinit init_exception_vectors(void)
+{
/* cannot program in software:
* evt0 - emulation (jtag)
* evt1 - reset
@@ -979,17 +966,23 @@ void __init init_exception_vectors(void)
* This function should be called during kernel startup to initialize
* the BFin IRQ handling routines.
*/
+
int __init init_arch_irq(void)
{
int irq;
unsigned long ilat = 0;
/* Disable all the peripheral intrs - page 4-29 HW Ref manual */
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
+ || defined(BF538_FAMILY) || defined(CONFIG_BF51x)
bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
# ifdef CONFIG_BF54x
bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
# endif
+# ifdef CONFIG_SMP
+ bfin_write_SICB_IMASK0(SIC_UNMASK_ALL);
+ bfin_write_SICB_IMASK1(SIC_UNMASK_ALL);
+# endif
#else
bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
#endif
@@ -1029,7 +1022,7 @@ int __init init_arch_irq(void)
case IRQ_PINT1:
case IRQ_PINT2:
case IRQ_PINT3:
-#elif defined(CONFIG_BF52x)
+#elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
case IRQ_PORTF_INTA:
case IRQ_PORTG_INTA:
case IRQ_PORTH_INTA:
@@ -1037,18 +1030,41 @@ int __init init_arch_irq(void)
case IRQ_PROG0_INTA:
case IRQ_PROG1_INTA:
case IRQ_PROG2_INTA:
+#elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
+ case IRQ_PORTF_INTA:
#endif
+
set_irq_chained_handler(irq,
bfin_demux_gpio_irq);
break;
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
case IRQ_GENERIC_ERROR:
- set_irq_handler(irq, bfin_demux_error_irq);
-
+ set_irq_chained_handler(irq, bfin_demux_error_irq);
+ break;
+#endif
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+ case IRQ_TIMER0:
+ set_irq_handler(irq, handle_percpu_irq);
+ break;
+#endif
+#ifdef CONFIG_SMP
+ case IRQ_SUPPLE_0:
+ case IRQ_SUPPLE_1:
+ set_irq_handler(irq, handle_percpu_irq);
break;
#endif
default:
+#ifdef CONFIG_IPIPE
+ /*
+ * We want internal interrupt sources to be masked, because
+ * ISRs may trigger interrupts recursively (e.g. DMA), but
+ * interrupts are _not_ masked at CPU level. So let's handle
+ * them as level interrupts.
+ */
+ set_irq_handler(irq, handle_level_irq);
+#else /* !CONFIG_IPIPE */
set_irq_handler(irq, handle_simple_irq);
+#endif /* !CONFIG_IPIPE */
break;
}
}
@@ -1073,7 +1089,7 @@ int __init init_arch_irq(void)
CSYNC();
printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
- /* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
+ /* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx,
* local_irq_enable()
*/
program_IAR();
@@ -1081,29 +1097,38 @@ int __init init_arch_irq(void)
search_IAR();
/* Enable interrupts IVG7-15 */
- irq_flags = irq_flags | IMASK_IVG15 |
+ bfin_irq_flags |= IMASK_IVG15 |
IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
+#ifdef SIC_IWR0
bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
-#if defined(CONFIG_BF52x)
- /* BF52x system reset does not properly reset SIC_IWR1 which
+# ifdef SIC_IWR1
+ /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which
* will screw up the bootrom as it relies on MDMA0/1 waking it
* up from IDLE instructions. See this report for more info:
* http://blackfin.uclinux.org/gf/tracker/4323
*/
- bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
-#else
- bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
-#endif
-# ifdef CONFIG_BF54x
+ if (ANOMALY_05000435)
+ bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
+ else
+ bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
+# endif
+# ifdef SIC_IWR2
bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
# endif
#else
bfin_write_SIC_IWR(IWR_DISABLE_ALL);
#endif
+#ifdef CONFIG_IPIPE
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ struct irq_desc *desc = irq_desc + irq;
+ desc->ic_prio = __ipipe_get_irq_priority(irq);
+ desc->thr_prio = __ipipe_get_irqthread_priority(irq);
+ }
+#endif /* CONFIG_IPIPE */
+
return 0;
}
@@ -1117,11 +1142,20 @@ void do_irq(int vec, struct pt_regs *fp)
} else {
struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \
+ || defined(BF538_FAMILY) || defined(CONFIG_BF51x)
unsigned long sic_status[3];
- sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
- sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
+ if (smp_processor_id()) {
+#ifdef CONFIG_SMP
+ /* This will be optimized out in UP mode. */
+ sic_status[0] = bfin_read_SICB_ISR0() & bfin_read_SICB_IMASK0();
+ sic_status[1] = bfin_read_SICB_ISR1() & bfin_read_SICB_IMASK1();
+#endif
+ } else {
+ sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
+ sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
+ }
#ifdef CONFIG_BF54x
sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
#endif
@@ -1150,3 +1184,161 @@ void do_irq(int vec, struct pt_regs *fp)
}
asm_do_IRQ(vec, fp);
}
+
+#ifdef CONFIG_IPIPE
+
+int __ipipe_get_irq_priority(unsigned irq)
+{
+ int ient, prio;
+
+ if (irq <= IRQ_CORETMR)
+ return irq;
+
+ for (ient = 0; ient < NR_PERI_INTS; ient++) {
+ struct ivgx *ivg = ivg_table + ient;
+ if (ivg->irqno == irq) {
+ for (prio = 0; prio <= IVG13-IVG7; prio++) {
+ if (ivg7_13[prio].ifirst <= ivg &&
+ ivg7_13[prio].istop > ivg)
+ return IVG7 + prio;
+ }
+ }
+ }
+
+ return IVG15;
+}
+
+int __ipipe_get_irqthread_priority(unsigned irq)
+{
+ int ient, prio;
+ int demux_irq;
+
+ /* The returned priority value is rescaled to [0..IVG13+1]
+ * with 0 being the lowest effective priority level. */
+
+ if (irq <= IRQ_CORETMR)
+ return IVG13 - irq + 1;
+
+ /* GPIO IRQs are given the priority of the demux
+ * interrupt. */
+ if (IS_GPIOIRQ(irq)) {
+#if defined(CONFIG_BF54x)
+ u32 bank = PINT_2_BANK(irq2pint_lut[irq - SYS_IRQS]);
+ demux_irq = (bank == 0 ? IRQ_PINT0 :
+ bank == 1 ? IRQ_PINT1 :
+ bank == 2 ? IRQ_PINT2 :
+ IRQ_PINT3);
+#elif defined(CONFIG_BF561)
+ demux_irq = (irq >= IRQ_PF32 ? IRQ_PROG2_INTA :
+ irq >= IRQ_PF16 ? IRQ_PROG1_INTA :
+ IRQ_PROG0_INTA);
+#elif defined(CONFIG_BF52x)
+ demux_irq = (irq >= IRQ_PH0 ? IRQ_PORTH_INTA :
+ irq >= IRQ_PG0 ? IRQ_PORTG_INTA :
+ IRQ_PORTF_INTA);
+#else
+ demux_irq = irq;
+#endif
+ return IVG13 - PRIO_GPIODEMUX(demux_irq) + 1;
+ }
+
+ /* The GPIO demux interrupt is given a lower priority
+ * than the GPIO IRQs, so that its threaded handler
+ * unmasks the interrupt line after the decoded IRQs
+ * have been processed. */
+ prio = PRIO_GPIODEMUX(irq);
+ /* demux irq? */
+ if (prio != -1)
+ return IVG13 - prio;
+
+ for (ient = 0; ient < NR_PERI_INTS; ient++) {
+ struct ivgx *ivg = ivg_table + ient;
+ if (ivg->irqno == irq) {
+ for (prio = 0; prio <= IVG13-IVG7; prio++) {
+ if (ivg7_13[prio].ifirst <= ivg &&
+ ivg7_13[prio].istop > ivg)
+ return IVG7 - prio;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Hw interrupts are disabled on entry (check SAVE_CONTEXT). */
+#ifdef CONFIG_DO_IRQ_L1
+__attribute__((l1_text))
+#endif
+asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
+{
+ struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
+ struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
+ int irq;
+
+ if (likely(vec == EVT_IVTMR_P)) {
+ irq = IRQ_CORETMR;
+ goto handle_irq;
+ }
+
+ SSYNC();
+
+#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
+ {
+ unsigned long sic_status[3];
+
+ sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0();
+ sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1();
+#ifdef CONFIG_BF54x
+ sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2();
+#endif
+ for (;; ivg++) {
+ if (ivg >= ivg_stop) {
+ atomic_inc(&num_spurious);
+ return 0;
+ }
+ if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
+ break;
+ }
+ }
+#else
+ {
+ unsigned long sic_status;
+
+ sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
+
+ for (;; ivg++) {
+ if (ivg >= ivg_stop) {
+ atomic_inc(&num_spurious);
+ return 0;
+ } else if (sic_status & ivg->isrflag)
+ break;
+ }
+ }
+#endif
+
+ irq = ivg->irqno;
+
+ if (irq == IRQ_SYSTMR) {
+ bfin_write_TIMER_STATUS(1); /* Latch TIMIL0 */
+ /* This is basically what we need from the register frame. */
+ __raw_get_cpu_var(__ipipe_tick_regs).ipend = regs->ipend;
+ __raw_get_cpu_var(__ipipe_tick_regs).pc = regs->pc;
+ if (!ipipe_root_domain_p)
+ __raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
+ else
+ __raw_get_cpu_var(__ipipe_tick_regs).ipend &= ~0x10;
+ }
+
+handle_irq:
+
+ ipipe_trace_irq_entry(irq);
+ __ipipe_handle_irq(irq, regs);
+ ipipe_trace_irq_exit(irq);
+
+ if (ipipe_root_domain_p)
+ return !test_bit(IPIPE_STALL_FLAG, &ipipe_root_cpudom_var(status));
+
+ return 0;
+}
+
+#endif /* CONFIG_IPIPE */
diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c
index 606ded9ff4e1..05004df0f78b 100644
--- a/arch/blackfin/mach-common/irqpanic.c
+++ b/arch/blackfin/mach-common/irqpanic.c
@@ -33,8 +33,6 @@
#include <asm/traps.h>
#include <asm/blackfin.h>
-#include "../oprofile/op_blackfin.h"
-
#ifdef CONFIG_DEBUG_ICACHE_CHECK
#define L1_ICACHE_START 0xffa10000
#define L1_ICACHE_END 0xffa13fff
@@ -134,13 +132,3 @@ asmlinkage void irq_panic(int reason, struct pt_regs *regs)
#endif
}
-
-#ifdef CONFIG_HARDWARE_PM
-/*
- * call the handler of Performance overflow
- */
-asmlinkage void pm_overflow(int irq, struct pt_regs *regs)
-{
- pm_overflow_handler(irq, regs);
-}
-#endif
diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S
index 9daf01201e9f..6c5f5f0ea7fe 100644
--- a/arch/blackfin/mach-common/lock.S
+++ b/arch/blackfin/mach-common/lock.S
@@ -160,7 +160,7 @@ ENDPROC(_cache_grab_lock)
* R0 - Which way to be locked
*/
-ENTRY(_cache_lock)
+ENTRY(_bfin_cache_lock)
[--SP]=( R7:0,P5:0 );
@@ -184,7 +184,7 @@ ENTRY(_cache_lock)
( R7:0,P5:0 ) = [SP++];
RTS;
-ENDPROC(_cache_lock)
+ENDPROC(_bfin_cache_lock)
/* Invalidate the Entire Instruction cache by
* disabling IMC bit
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index e28c6af1f415..f48a6aebb49b 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -71,7 +71,7 @@ void bfin_pm_suspend_standby_enter(void)
gpio_pm_wakeup_request(CONFIG_PM_WAKEUP_GPIO_NUMBER, WAKEUP_TYPE);
#endif
- local_irq_save(flags);
+ local_irq_save_hw(flags);
bfin_pm_standby_setup();
#ifdef CONFIG_PM_BFIN_SLEEP_DEEPER
@@ -82,26 +82,27 @@ void bfin_pm_suspend_standby_enter(void)
bfin_pm_standby_restore();
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561)
+#ifdef SIC_IWR0
bfin_write_SIC_IWR0(IWR_DISABLE_ALL);
-#if defined(CONFIG_BF52x)
+# ifdef SIC_IWR1
/* BF52x system reset does not properly reset SIC_IWR1 which
* will screw up the bootrom as it relies on MDMA0/1 waking it
* up from IDLE instructions. See this report for more info:
* http://blackfin.uclinux.org/gf/tracker/4323
*/
- bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
-#else
- bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
-#endif
-# ifdef CONFIG_BF54x
+ if (ANOMALY_05000435)
+ bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11));
+ else
+ bfin_write_SIC_IWR1(IWR_DISABLE_ALL);
+# endif
+# ifdef SIC_IWR2
bfin_write_SIC_IWR2(IWR_DISABLE_ALL);
# endif
#else
bfin_write_SIC_IWR(IWR_DISABLE_ALL);
#endif
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
}
int bf53x_suspend_l1_mem(unsigned char *memptr)
@@ -245,12 +246,12 @@ int bfin_pm_suspend_mem_enter(void)
wakeup |= GPWE;
#endif
- local_irq_save(flags);
+ local_irq_save_hw(flags);
ret = blackfin_dma_suspend();
if (ret) {
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
kfree(memptr);
return ret;
}
@@ -271,7 +272,7 @@ int bfin_pm_suspend_mem_enter(void)
bfin_gpio_pm_hibernate_restore();
blackfin_dma_resume();
- local_irq_restore(flags);
+ local_irq_restore_hw(flags);
kfree(memptr);
return 0;
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
new file mode 100644
index 000000000000..77c992847094
--- /dev/null
+++ b/arch/blackfin/mach-common/smp.c
@@ -0,0 +1,476 @@
+/*
+ * File: arch/blackfin/kernel/smp.c
+ * Author: Philippe Gerum <rpm@xenomai.org>
+ * IPI management based on arch/arm/kernel/smp.c.
+ *
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/cache.h>
+#include <linux/profile.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+#include <asm/atomic.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/cpu.h>
+#include <linux/err.h>
+
+struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
+
+void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
+ *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
+ *init_saved_dcplb_fault_addr_coreb;
+
+cpumask_t cpu_possible_map;
+EXPORT_SYMBOL(cpu_possible_map);
+
+cpumask_t cpu_online_map;
+EXPORT_SYMBOL(cpu_online_map);
+
+#define BFIN_IPI_RESCHEDULE 0
+#define BFIN_IPI_CALL_FUNC 1
+#define BFIN_IPI_CPU_STOP 2
+
+struct blackfin_flush_data {
+ unsigned long start;
+ unsigned long end;
+};
+
+void *secondary_stack;
+
+
+struct smp_call_struct {
+ void (*func)(void *info);
+ void *info;
+ int wait;
+ cpumask_t pending;
+ cpumask_t waitmask;
+};
+
+static struct blackfin_flush_data smp_flush_data;
+
+static DEFINE_SPINLOCK(stop_lock);
+
+struct ipi_message {
+ struct list_head list;
+ unsigned long type;
+ struct smp_call_struct call_struct;
+};
+
+struct ipi_message_queue {
+ struct list_head head;
+ spinlock_t lock;
+ unsigned long count;
+};
+
+static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue);
+
+static void ipi_cpu_stop(unsigned int cpu)
+{
+ spin_lock(&stop_lock);
+ printk(KERN_CRIT "CPU%u: stopping\n", cpu);
+ dump_stack();
+ spin_unlock(&stop_lock);
+
+ cpu_clear(cpu, cpu_online_map);
+
+ local_irq_disable();
+
+ while (1)
+ SSYNC();
+}
+
+static void ipi_flush_icache(void *info)
+{
+ struct blackfin_flush_data *fdata = info;
+
+ /* Invalidate the memory holding the bounds of the flushed region. */
+ blackfin_dcache_invalidate_range((unsigned long)fdata,
+ (unsigned long)fdata + sizeof(*fdata));
+
+ blackfin_icache_flush_range(fdata->start, fdata->end);
+}
+
+static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
+{
+ int wait;
+ void (*func)(void *info);
+ void *info;
+ func = msg->call_struct.func;
+ info = msg->call_struct.info;
+ wait = msg->call_struct.wait;
+ cpu_clear(cpu, msg->call_struct.pending);
+ func(info);
+ if (wait)
+ cpu_clear(cpu, msg->call_struct.waitmask);
+ else
+ kfree(msg);
+}
+
+static irqreturn_t ipi_handler(int irq, void *dev_instance)
+{
+ struct ipi_message *msg, *mg;
+ struct ipi_message_queue *msg_queue;
+ unsigned int cpu = smp_processor_id();
+
+ platform_clear_ipi(cpu);
+
+ msg_queue = &__get_cpu_var(ipi_msg_queue);
+ msg_queue->count++;
+
+ spin_lock(&msg_queue->lock);
+ list_for_each_entry_safe(msg, mg, &msg_queue->head, list) {
+ list_del(&msg->list);
+ switch (msg->type) {
+ case BFIN_IPI_RESCHEDULE:
+ /* That's the easiest one; leave it to
+ * return_from_int. */
+ kfree(msg);
+ break;
+ case BFIN_IPI_CALL_FUNC:
+ ipi_call_function(cpu, msg);
+ break;
+ case BFIN_IPI_CPU_STOP:
+ ipi_cpu_stop(cpu);
+ kfree(msg);
+ break;
+ default:
+ printk(KERN_CRIT "CPU%u: Unknown IPI message \
+ 0x%lx\n", cpu, msg->type);
+ kfree(msg);
+ break;
+ }
+ }
+ spin_unlock(&msg_queue->lock);
+ return IRQ_HANDLED;
+}
+
+static void ipi_queue_init(void)
+{
+ unsigned int cpu;
+ struct ipi_message_queue *msg_queue;
+ for_each_possible_cpu(cpu) {
+ msg_queue = &per_cpu(ipi_msg_queue, cpu);
+ INIT_LIST_HEAD(&msg_queue->head);
+ spin_lock_init(&msg_queue->lock);
+ msg_queue->count = 0;
+ }
+}
+
+int smp_call_function(void (*func)(void *info), void *info, int wait)
+{
+ unsigned int cpu;
+ cpumask_t callmap;
+ unsigned long flags;
+ struct ipi_message_queue *msg_queue;
+ struct ipi_message *msg;
+
+ callmap = cpu_online_map;
+ cpu_clear(smp_processor_id(), callmap);
+ if (cpus_empty(callmap))
+ return 0;
+
+ msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+ INIT_LIST_HEAD(&msg->list);
+ msg->call_struct.func = func;
+ msg->call_struct.info = info;
+ msg->call_struct.wait = wait;
+ msg->call_struct.pending = callmap;
+ msg->call_struct.waitmask = callmap;
+ msg->type = BFIN_IPI_CALL_FUNC;
+
+ for_each_cpu_mask(cpu, callmap) {
+ msg_queue = &per_cpu(ipi_msg_queue, cpu);
+ spin_lock_irqsave(&msg_queue->lock, flags);
+ list_add(&msg->list, &msg_queue->head);
+ spin_unlock_irqrestore(&msg_queue->lock, flags);
+ platform_send_ipi_cpu(cpu);
+ }
+ if (wait) {
+ while (!cpus_empty(msg->call_struct.waitmask))
+ blackfin_dcache_invalidate_range(
+ (unsigned long)(&msg->call_struct.waitmask),
+ (unsigned long)(&msg->call_struct.waitmask));
+ kfree(msg);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(smp_call_function);
+
+int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
+ int wait)
+{
+ unsigned int cpu = cpuid;
+ cpumask_t callmap;
+ unsigned long flags;
+ struct ipi_message_queue *msg_queue;
+ struct ipi_message *msg;
+
+ if (cpu_is_offline(cpu))
+ return 0;
+ cpus_clear(callmap);
+ cpu_set(cpu, callmap);
+
+ msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+ INIT_LIST_HEAD(&msg->list);
+ msg->call_struct.func = func;
+ msg->call_struct.info = info;
+ msg->call_struct.wait = wait;
+ msg->call_struct.pending = callmap;
+ msg->call_struct.waitmask = callmap;
+ msg->type = BFIN_IPI_CALL_FUNC;
+
+ msg_queue = &per_cpu(ipi_msg_queue, cpu);
+ spin_lock_irqsave(&msg_queue->lock, flags);
+ list_add(&msg->list, &msg_queue->head);
+ spin_unlock_irqrestore(&msg_queue->lock, flags);
+ platform_send_ipi_cpu(cpu);
+
+ if (wait) {
+ while (!cpus_empty(msg->call_struct.waitmask))
+ blackfin_dcache_invalidate_range(
+ (unsigned long)(&msg->call_struct.waitmask),
+ (unsigned long)(&msg->call_struct.waitmask));
+ kfree(msg);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(smp_call_function_single);
+
+void smp_send_reschedule(int cpu)
+{
+ unsigned long flags;
+ struct ipi_message_queue *msg_queue;
+ struct ipi_message *msg;
+
+ if (cpu_is_offline(cpu))
+ return;
+
+ msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+ memset(msg, 0, sizeof(msg));
+ INIT_LIST_HEAD(&msg->list);
+ msg->type = BFIN_IPI_RESCHEDULE;
+
+ msg_queue = &per_cpu(ipi_msg_queue, cpu);
+ spin_lock_irqsave(&msg_queue->lock, flags);
+ list_add(&msg->list, &msg_queue->head);
+ spin_unlock_irqrestore(&msg_queue->lock, flags);
+ platform_send_ipi_cpu(cpu);
+
+ return;
+}
+
+void smp_send_stop(void)
+{
+ unsigned int cpu;
+ cpumask_t callmap;
+ unsigned long flags;
+ struct ipi_message_queue *msg_queue;
+ struct ipi_message *msg;
+
+ callmap = cpu_online_map;
+ cpu_clear(smp_processor_id(), callmap);
+ if (cpus_empty(callmap))
+ return;
+
+ msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+ memset(msg, 0, sizeof(msg));
+ INIT_LIST_HEAD(&msg->list);
+ msg->type = BFIN_IPI_CPU_STOP;
+
+ for_each_cpu_mask(cpu, callmap) {
+ msg_queue = &per_cpu(ipi_msg_queue, cpu);
+ spin_lock_irqsave(&msg_queue->lock, flags);
+ list_add(&msg->list, &msg_queue->head);
+ spin_unlock_irqrestore(&msg_queue->lock, flags);
+ platform_send_ipi_cpu(cpu);
+ }
+ return;
+}
+
+int __cpuinit __cpu_up(unsigned int cpu)
+{
+ struct task_struct *idle;
+ int ret;
+
+ idle = fork_idle(cpu);
+ if (IS_ERR(idle)) {
+ printk(KERN_ERR "CPU%u: fork() failed\n", cpu);
+ return PTR_ERR(idle);
+ }
+
+ secondary_stack = task_stack_page(idle) + THREAD_SIZE;
+ smp_wmb();
+
+ ret = platform_boot_secondary(cpu, idle);
+
+ if (ret) {
+ cpu_clear(cpu, cpu_present_map);
+ printk(KERN_CRIT "CPU%u: processor failed to boot (%d)\n", cpu, ret);
+ free_task(idle);
+ } else
+ cpu_set(cpu, cpu_online_map);
+
+ secondary_stack = NULL;
+
+ return ret;
+}
+
+static void __cpuinit setup_secondary(unsigned int cpu)
+{
+#if !(defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE))
+ struct irq_desc *timer_desc;
+#endif
+ unsigned long ilat;
+
+ bfin_write_IMASK(0);
+ CSYNC();
+ ilat = bfin_read_ILAT();
+ CSYNC();
+ bfin_write_ILAT(ilat);
+ CSYNC();
+
+ /* Reserve the PDA space for the secondary CPU. */
+ reserve_pda();
+
+ /* Enable interrupt levels IVG7-15. IARs have been already
+ * programmed by the boot CPU. */
+ bfin_irq_flags |= IMASK_IVG15 |
+ IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
+ IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
+
+#if defined(CONFIG_TICK_SOURCE_SYSTMR0) || defined(CONFIG_IPIPE)
+ /* Power down the core timer, just to play safe. */
+ bfin_write_TCNTL(0);
+
+ /* system timer0 has been setup by CoreA. */
+#else
+ timer_desc = irq_desc + IRQ_CORETMR;
+ setup_core_timer();
+ timer_desc->chip->enable(IRQ_CORETMR);
+#endif
+}
+
+void __cpuinit secondary_start_kernel(void)
+{
+ unsigned int cpu = smp_processor_id();
+ struct mm_struct *mm = &init_mm;
+
+ if (_bfin_swrst & SWRST_DBL_FAULT_B) {
+ printk(KERN_EMERG "CoreB Recovering from DOUBLE FAULT event\n");
+#ifdef CONFIG_DEBUG_DOUBLEFAULT
+ printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n",
+ (int)init_saved_seqstat_coreb & SEQSTAT_EXCAUSE, init_saved_retx_coreb);
+ printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr_coreb);
+ printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr_coreb);
+#endif
+ printk(KERN_NOTICE " The instruction at %pF caused a double exception\n",
+ init_retx_coreb);
+ }
+
+ /*
+ * We want the D-cache to be enabled early, in case the atomic
+ * support code emulates cache coherence (see
+ * __ARCH_SYNC_CORE_DCACHE).
+ */
+ init_exception_vectors();
+
+ bfin_setup_caches(cpu);
+
+ local_irq_disable();
+
+ /* Attach the new idle task to the global mm. */
+ atomic_inc(&mm->mm_users);
+ atomic_inc(&mm->mm_count);
+ current->active_mm = mm;
+ BUG_ON(current->mm); /* Can't be, but better be safe than sorry. */
+
+ preempt_disable();
+
+ setup_secondary(cpu);
+
+ local_irq_enable();
+
+ platform_secondary_init(cpu);
+
+ cpu_idle();
+}
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ platform_prepare_cpus(max_cpus);
+ ipi_queue_init();
+ platform_request_ipi(&ipi_handler);
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+ unsigned long bogosum = 0;
+ unsigned int cpu;
+
+ for_each_online_cpu(cpu)
+ bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy;
+
+ printk(KERN_INFO "SMP: Total of %d processors activated "
+ "(%lu.%02lu BogoMIPS).\n",
+ num_online_cpus(),
+ bogosum / (500000/HZ),
+ (bogosum / (5000/HZ)) % 100);
+}
+
+void smp_icache_flush_range_others(unsigned long start, unsigned long end)
+{
+ smp_flush_data.start = start;
+ smp_flush_data.end = end;
+
+ if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 1))
+ printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs\n");
+}
+EXPORT_SYMBOL_GPL(smp_icache_flush_range_others);
+
+#ifdef __ARCH_SYNC_CORE_DCACHE
+unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));
+
+void resync_core_dcache(void)
+{
+ unsigned int cpu = get_cpu();
+ blackfin_invalidate_entire_dcache();
+ ++per_cpu(cpu_data, cpu).dcache_invld_count;
+ put_cpu();
+}
+EXPORT_SYMBOL(resync_core_dcache);
+#endif
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index bc240abb8745..d0532b72bba5 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -31,7 +31,8 @@
#include <linux/bootmem.h>
#include <linux/uaccess.h>
#include <asm/bfin-global.h>
-#include <asm/l1layout.h>
+#include <asm/pda.h>
+#include <asm/cplbinit.h>
#include "blackfin_sram.h"
/*
@@ -53,6 +54,11 @@ static unsigned long empty_bad_page;
unsigned long empty_zero_page;
+extern unsigned long exception_stack[NR_CPUS][1024];
+
+struct blackfin_pda cpu_pda[NR_CPUS];
+EXPORT_SYMBOL(cpu_pda);
+
/*
* paging_init() continues the virtual memory environment setup which
* was begun by the code in arch/head.S.
@@ -98,6 +104,32 @@ void __init paging_init(void)
}
}
+asmlinkage void init_pda(void)
+{
+ unsigned int cpu = raw_smp_processor_id();
+
+ /* Initialize the PDA fields holding references to other parts
+ of the memory. The content of such memory is still
+ undefined at the time of the call, we are only setting up
+ valid pointers to it. */
+ memset(&cpu_pda[cpu], 0, sizeof(cpu_pda[cpu]));
+
+ cpu_pda[0].next = &cpu_pda[1];
+ cpu_pda[1].next = &cpu_pda[0];
+
+ cpu_pda[cpu].ex_stack = exception_stack[cpu + 1];
+
+#ifdef CONFIG_SMP
+ cpu_pda[cpu].imask = 0x1f;
+#endif
+}
+
+void __cpuinit reserve_pda(void)
+{
+ printk(KERN_INFO "PDA for CPU%u reserved at %p\n", smp_processor_id(),
+ &cpu_pda[smp_processor_id()]);
+}
+
void __init mem_init(void)
{
unsigned int codek = 0, datak = 0, initk = 0;
@@ -141,21 +173,13 @@ void __init mem_init(void)
static int __init sram_init(void)
{
- unsigned long tmp;
-
/* Initialize the blackfin L1 Memory. */
bfin_sram_init();
- /* Allocate this once; never free it. We assume this gives us a
- pointer to the start of L1 scratchpad memory; panic if it
- doesn't. */
- tmp = (unsigned long)l1sram_alloc(sizeof(struct l1_scratch_task_info));
- if (tmp != (unsigned long)L1_SCRATCH_TASK_INFO) {
- printk(KERN_EMERG "mem_init(): Did not get the right address from l1sram_alloc: %08lx != %08lx\n",
- tmp, (unsigned long)L1_SCRATCH_TASK_INFO);
- panic("No L1, time to give up\n");
- }
-
+ /* Reserve the PDA space for the boot CPU right after we
+ * initialized the scratch memory allocator.
+ */
+ reserve_pda();
return 0;
}
pure_initcall(sram_init);
diff --git a/arch/blackfin/mm/sram-alloc.c b/arch/blackfin/mm/sram-alloc.c
index cc6f336e7313..834cab7438a8 100644
--- a/arch/blackfin/mm/sram-alloc.c
+++ b/arch/blackfin/mm/sram-alloc.c
@@ -39,10 +39,13 @@
#include <linux/spinlock.h>
#include <linux/rtc.h>
#include <asm/blackfin.h>
+#include <asm/mem_map.h>
#include "blackfin_sram.h"
-static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock;
-static spinlock_t l2_sram_lock;
+static DEFINE_PER_CPU(spinlock_t, l1sram_lock) ____cacheline_aligned_in_smp;
+static DEFINE_PER_CPU(spinlock_t, l1_data_sram_lock) ____cacheline_aligned_in_smp;
+static DEFINE_PER_CPU(spinlock_t, l1_inst_sram_lock) ____cacheline_aligned_in_smp;
+static spinlock_t l2_sram_lock ____cacheline_aligned_in_smp;
/* the data structure for L1 scratchpad and DATA SRAM */
struct sram_piece {
@@ -52,18 +55,22 @@ struct sram_piece {
struct sram_piece *next;
};
-static struct sram_piece free_l1_ssram_head, used_l1_ssram_head;
+static DEFINE_PER_CPU(struct sram_piece, free_l1_ssram_head);
+static DEFINE_PER_CPU(struct sram_piece, used_l1_ssram_head);
#if L1_DATA_A_LENGTH != 0
-static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head;
+static DEFINE_PER_CPU(struct sram_piece, free_l1_data_A_sram_head);
+static DEFINE_PER_CPU(struct sram_piece, used_l1_data_A_sram_head);
#endif
#if L1_DATA_B_LENGTH != 0
-static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head;
+static DEFINE_PER_CPU(struct sram_piece, free_l1_data_B_sram_head);
+static DEFINE_PER_CPU(struct sram_piece, used_l1_data_B_sram_head);
#endif
#if L1_CODE_LENGTH != 0
-static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head;
+static DEFINE_PER_CPU(struct sram_piece, free_l1_inst_sram_head);
+static DEFINE_PER_CPU(struct sram_piece, used_l1_inst_sram_head);
#endif
#if L2_LENGTH != 0
@@ -75,102 +82,117 @@ static struct kmem_cache *sram_piece_cache;
/* L1 Scratchpad SRAM initialization function */
static void __init l1sram_init(void)
{
- free_l1_ssram_head.next =
- kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
- if (!free_l1_ssram_head.next) {
- printk(KERN_INFO "Failed to initialize Scratchpad data SRAM\n");
- return;
+ unsigned int cpu;
+ for (cpu = 0; cpu < num_possible_cpus(); ++cpu) {
+ per_cpu(free_l1_ssram_head, cpu).next =
+ kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+ if (!per_cpu(free_l1_ssram_head, cpu).next) {
+ printk(KERN_INFO "Fail to initialize Scratchpad data SRAM.\n");
+ return;
+ }
+
+ per_cpu(free_l1_ssram_head, cpu).next->paddr = (void *)get_l1_scratch_start_cpu(cpu);
+ per_cpu(free_l1_ssram_head, cpu).next->size = L1_SCRATCH_LENGTH;
+ per_cpu(free_l1_ssram_head, cpu).next->pid = 0;
+ per_cpu(free_l1_ssram_head, cpu).next->next = NULL;
+
+ per_cpu(used_l1_ssram_head, cpu).next = NULL;
+
+ /* mutex initialize */
+ spin_lock_init(&per_cpu(l1sram_lock, cpu));
+ printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
+ L1_SCRATCH_LENGTH >> 10);
}
-
- free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START;
- free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH;
- free_l1_ssram_head.next->pid = 0;
- free_l1_ssram_head.next->next = NULL;
-
- used_l1_ssram_head.next = NULL;
-
- /* mutex initialize */
- spin_lock_init(&l1sram_lock);
-
- printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
- L1_SCRATCH_LENGTH >> 10);
}
static void __init l1_data_sram_init(void)
{
+#if L1_DATA_A_LENGTH != 0 || L1_DATA_B_LENGTH != 0
+ unsigned int cpu;
+#endif
#if L1_DATA_A_LENGTH != 0
- free_l1_data_A_sram_head.next =
- kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
- if (!free_l1_data_A_sram_head.next) {
- printk(KERN_INFO "Failed to initialize L1 Data A SRAM\n");
- return;
+ for (cpu = 0; cpu < num_possible_cpus(); ++cpu) {
+ per_cpu(free_l1_data_A_sram_head, cpu).next =
+ kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+ if (!per_cpu(free_l1_data_A_sram_head, cpu).next) {
+ printk(KERN_INFO "Fail to initialize L1 Data A SRAM.\n");
+ return;
+ }
+
+ per_cpu(free_l1_data_A_sram_head, cpu).next->paddr =
+ (void *)get_l1_data_a_start_cpu(cpu) + (_ebss_l1 - _sdata_l1);
+ per_cpu(free_l1_data_A_sram_head, cpu).next->size =
+ L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
+ per_cpu(free_l1_data_A_sram_head, cpu).next->pid = 0;
+ per_cpu(free_l1_data_A_sram_head, cpu).next->next = NULL;
+
+ per_cpu(used_l1_data_A_sram_head, cpu).next = NULL;
+
+ printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n",
+ L1_DATA_A_LENGTH >> 10,
+ per_cpu(free_l1_data_A_sram_head, cpu).next->size >> 10);
}
-
- free_l1_data_A_sram_head.next->paddr =
- (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1);
- free_l1_data_A_sram_head.next->size =
- L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
- free_l1_data_A_sram_head.next->pid = 0;
- free_l1_data_A_sram_head.next->next = NULL;
-
- used_l1_data_A_sram_head.next = NULL;
-
- printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n",
- L1_DATA_A_LENGTH >> 10,
- free_l1_data_A_sram_head.next->size >> 10);
#endif
#if L1_DATA_B_LENGTH != 0
- free_l1_data_B_sram_head.next =
- kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
- if (!free_l1_data_B_sram_head.next) {
- printk(KERN_INFO "Failed to initialize L1 Data B SRAM\n");
- return;
+ for (cpu = 0; cpu < num_possible_cpus(); ++cpu) {
+ per_cpu(free_l1_data_B_sram_head, cpu).next =
+ kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+ if (!per_cpu(free_l1_data_B_sram_head, cpu).next) {
+ printk(KERN_INFO "Fail to initialize L1 Data B SRAM.\n");
+ return;
+ }
+
+ per_cpu(free_l1_data_B_sram_head, cpu).next->paddr =
+ (void *)get_l1_data_b_start_cpu(cpu) + (_ebss_b_l1 - _sdata_b_l1);
+ per_cpu(free_l1_data_B_sram_head, cpu).next->size =
+ L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
+ per_cpu(free_l1_data_B_sram_head, cpu).next->pid = 0;
+ per_cpu(free_l1_data_B_sram_head, cpu).next->next = NULL;
+
+ per_cpu(used_l1_data_B_sram_head, cpu).next = NULL;
+
+ printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n",
+ L1_DATA_B_LENGTH >> 10,
+ per_cpu(free_l1_data_B_sram_head, cpu).next->size >> 10);
+ /* mutex initialize */
}
-
- free_l1_data_B_sram_head.next->paddr =
- (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1);
- free_l1_data_B_sram_head.next->size =
- L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
- free_l1_data_B_sram_head.next->pid = 0;
- free_l1_data_B_sram_head.next->next = NULL;
-
- used_l1_data_B_sram_head.next = NULL;
-
- printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n",
- L1_DATA_B_LENGTH >> 10,
- free_l1_data_B_sram_head.next->size >> 10);
#endif
- /* mutex initialize */
- spin_lock_init(&l1_data_sram_lock);
+#if L1_DATA_A_LENGTH != 0 || L1_DATA_B_LENGTH != 0
+ for (cpu = 0; cpu < num_possible_cpus(); ++cpu)
+ spin_lock_init(&per_cpu(l1_data_sram_lock, cpu));
+#endif
}
static void __init l1_inst_sram_init(void)
{
#if L1_CODE_LENGTH != 0
- free_l1_inst_sram_head.next =
- kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
- if (!free_l1_inst_sram_head.next) {
- printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n");
- return;
+ unsigned int cpu;
+ for (cpu = 0; cpu < num_possible_cpus(); ++cpu) {
+ per_cpu(free_l1_inst_sram_head, cpu).next =
+ kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
+ if (!per_cpu(free_l1_inst_sram_head, cpu).next) {
+ printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n");
+ return;
+ }
+
+ per_cpu(free_l1_inst_sram_head, cpu).next->paddr =
+ (void *)get_l1_code_start_cpu(cpu) + (_etext_l1 - _stext_l1);
+ per_cpu(free_l1_inst_sram_head, cpu).next->size =
+ L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
+ per_cpu(free_l1_inst_sram_head, cpu).next->pid = 0;
+ per_cpu(free_l1_inst_sram_head, cpu).next->next = NULL;
+
+ per_cpu(used_l1_inst_sram_head, cpu).next = NULL;
+
+ printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n",
+ L1_CODE_LENGTH >> 10,
+ per_cpu(free_l1_inst_sram_head, cpu).next->size >> 10);
+
+ /* mutex initialize */
+ spin_lock_init(&per_cpu(l1_inst_sram_lock, cpu));
}
-
- free_l1_inst_sram_head.next->paddr =
- (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
- free_l1_inst_sram_head.next->size =
- L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
- free_l1_inst_sram_head.next->pid = 0;
- free_l1_inst_sram_head.next->next = NULL;
-
- used_l1_inst_sram_head.next = NULL;
-
- printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n",
- L1_CODE_LENGTH >> 10,
- free_l1_inst_sram_head.next->size >> 10);
#endif
-
- /* mutex initialize */
- spin_lock_init(&l1_inst_sram_lock);
}
static void __init l2_sram_init(void)
@@ -179,7 +201,7 @@ static void __init l2_sram_init(void)
free_l2_sram_head.next =
kmem_cache_alloc(sram_piece_cache, GFP_KERNEL);
if (!free_l2_sram_head.next) {
- printk(KERN_INFO "Failed to initialize L2 SRAM\n");
+ printk(KERN_INFO "Fail to initialize L2 SRAM.\n");
return;
}
@@ -200,6 +222,7 @@ static void __init l2_sram_init(void)
/* mutex initialize */
spin_lock_init(&l2_sram_lock);
}
+
void __init bfin_sram_init(void)
{
sram_piece_cache = kmem_cache_create("sram_piece_cache",
@@ -353,20 +376,20 @@ int sram_free(const void *addr)
{
#if L1_CODE_LENGTH != 0
- if (addr >= (void *)L1_CODE_START
- && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
+ if (addr >= (void *)get_l1_code_start()
+ && addr < (void *)(get_l1_code_start() + L1_CODE_LENGTH))
return l1_inst_sram_free(addr);
else
#endif
#if L1_DATA_A_LENGTH != 0
- if (addr >= (void *)L1_DATA_A_START
- && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH))
+ if (addr >= (void *)get_l1_data_a_start()
+ && addr < (void *)(get_l1_data_a_start() + L1_DATA_A_LENGTH))
return l1_data_A_sram_free(addr);
else
#endif
#if L1_DATA_B_LENGTH != 0
- if (addr >= (void *)L1_DATA_B_START
- && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH))
+ if (addr >= (void *)get_l1_data_b_start()
+ && addr < (void *)(get_l1_data_b_start() + L1_DATA_B_LENGTH))
return l1_data_B_sram_free(addr);
else
#endif
@@ -384,17 +407,20 @@ void *l1_data_A_sram_alloc(size_t size)
{
unsigned long flags;
void *addr = NULL;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1_data_sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags);
#if L1_DATA_A_LENGTH != 0
- addr = _sram_alloc(size, &free_l1_data_A_sram_head,
- &used_l1_data_A_sram_head);
+ addr = _sram_alloc(size, &per_cpu(free_l1_data_A_sram_head, cpu),
+ &per_cpu(used_l1_data_A_sram_head, cpu));
#endif
/* add mutex operation */
- spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags);
+ put_cpu();
pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n",
(long unsigned int)addr, size);
@@ -407,19 +433,22 @@ int l1_data_A_sram_free(const void *addr)
{
unsigned long flags;
int ret;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1_data_sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags);
#if L1_DATA_A_LENGTH != 0
- ret = _sram_free(addr, &free_l1_data_A_sram_head,
- &used_l1_data_A_sram_head);
+ ret = _sram_free(addr, &per_cpu(free_l1_data_A_sram_head, cpu),
+ &per_cpu(used_l1_data_A_sram_head, cpu));
#else
ret = -1;
#endif
/* add mutex operation */
- spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags);
+ put_cpu();
return ret;
}
@@ -430,15 +459,18 @@ void *l1_data_B_sram_alloc(size_t size)
#if L1_DATA_B_LENGTH != 0
unsigned long flags;
void *addr;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1_data_sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags);
- addr = _sram_alloc(size, &free_l1_data_B_sram_head,
- &used_l1_data_B_sram_head);
+ addr = _sram_alloc(size, &per_cpu(free_l1_data_B_sram_head, cpu),
+ &per_cpu(used_l1_data_B_sram_head, cpu));
/* add mutex operation */
- spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags);
+ put_cpu();
pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n",
(long unsigned int)addr, size);
@@ -455,15 +487,18 @@ int l1_data_B_sram_free(const void *addr)
#if L1_DATA_B_LENGTH != 0
unsigned long flags;
int ret;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1_data_sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1_data_sram_lock, cpu), flags);
- ret = _sram_free(addr, &free_l1_data_B_sram_head,
- &used_l1_data_B_sram_head);
+ ret = _sram_free(addr, &per_cpu(free_l1_data_B_sram_head, cpu),
+ &per_cpu(used_l1_data_B_sram_head, cpu));
/* add mutex operation */
- spin_unlock_irqrestore(&l1_data_sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1_data_sram_lock, cpu), flags);
+ put_cpu();
return ret;
#else
@@ -509,15 +544,18 @@ void *l1_inst_sram_alloc(size_t size)
#if L1_CODE_LENGTH != 0
unsigned long flags;
void *addr;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1_inst_sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1_inst_sram_lock, cpu), flags);
- addr = _sram_alloc(size, &free_l1_inst_sram_head,
- &used_l1_inst_sram_head);
+ addr = _sram_alloc(size, &per_cpu(free_l1_inst_sram_head, cpu),
+ &per_cpu(used_l1_inst_sram_head, cpu));
/* add mutex operation */
- spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1_inst_sram_lock, cpu), flags);
+ put_cpu();
pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n",
(long unsigned int)addr, size);
@@ -534,15 +572,18 @@ int l1_inst_sram_free(const void *addr)
#if L1_CODE_LENGTH != 0
unsigned long flags;
int ret;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1_inst_sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1_inst_sram_lock, cpu), flags);
- ret = _sram_free(addr, &free_l1_inst_sram_head,
- &used_l1_inst_sram_head);
+ ret = _sram_free(addr, &per_cpu(free_l1_inst_sram_head, cpu),
+ &per_cpu(used_l1_inst_sram_head, cpu));
/* add mutex operation */
- spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1_inst_sram_lock, cpu), flags);
+ put_cpu();
return ret;
#else
@@ -556,15 +597,18 @@ void *l1sram_alloc(size_t size)
{
unsigned long flags;
void *addr;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags);
- addr = _sram_alloc(size, &free_l1_ssram_head,
- &used_l1_ssram_head);
+ addr = _sram_alloc(size, &per_cpu(free_l1_ssram_head, cpu),
+ &per_cpu(used_l1_ssram_head, cpu));
/* add mutex operation */
- spin_unlock_irqrestore(&l1sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags);
+ put_cpu();
return addr;
}
@@ -574,15 +618,18 @@ void *l1sram_alloc_max(size_t *psize)
{
unsigned long flags;
void *addr;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags);
- addr = _sram_alloc_max(&free_l1_ssram_head,
- &used_l1_ssram_head, psize);
+ addr = _sram_alloc_max(&per_cpu(free_l1_ssram_head, cpu),
+ &per_cpu(used_l1_ssram_head, cpu), psize);
/* add mutex operation */
- spin_unlock_irqrestore(&l1sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags);
+ put_cpu();
return addr;
}
@@ -592,15 +639,18 @@ int l1sram_free(const void *addr)
{
unsigned long flags;
int ret;
+ unsigned int cpu;
+ cpu = get_cpu();
/* add mutex operation */
- spin_lock_irqsave(&l1sram_lock, flags);
+ spin_lock_irqsave(&per_cpu(l1sram_lock, cpu), flags);
- ret = _sram_free(addr, &free_l1_ssram_head,
- &used_l1_ssram_head);
+ ret = _sram_free(addr, &per_cpu(free_l1_ssram_head, cpu),
+ &per_cpu(used_l1_ssram_head, cpu));
/* add mutex operation */
- spin_unlock_irqrestore(&l1sram_lock, flags);
+ spin_unlock_irqrestore(&per_cpu(l1sram_lock, cpu), flags);
+ put_cpu();
return ret;
}
@@ -761,33 +811,36 @@ static int sram_proc_read(char *buf, char **start, off_t offset, int count,
int *eof, void *data)
{
int len = 0;
+ unsigned int cpu;
- if (_sram_proc_read(buf, &len, count, "Scratchpad",
- &free_l1_ssram_head, &used_l1_ssram_head))
- goto not_done;
+ for (cpu = 0; cpu < num_possible_cpus(); ++cpu) {
+ if (_sram_proc_read(buf, &len, count, "Scratchpad",
+ &per_cpu(free_l1_ssram_head, cpu), &per_cpu(used_l1_ssram_head, cpu)))
+ goto not_done;
#if L1_DATA_A_LENGTH != 0
- if (_sram_proc_read(buf, &len, count, "L1 Data A",
- &free_l1_data_A_sram_head,
- &used_l1_data_A_sram_head))
- goto not_done;
+ if (_sram_proc_read(buf, &len, count, "L1 Data A",
+ &per_cpu(free_l1_data_A_sram_head, cpu),
+ &per_cpu(used_l1_data_A_sram_head, cpu)))
+ goto not_done;
#endif
#if L1_DATA_B_LENGTH != 0
- if (_sram_proc_read(buf, &len, count, "L1 Data B",
- &free_l1_data_B_sram_head,
- &used_l1_data_B_sram_head))
- goto not_done;
+ if (_sram_proc_read(buf, &len, count, "L1 Data B",
+ &per_cpu(free_l1_data_B_sram_head, cpu),
+ &per_cpu(used_l1_data_B_sram_head, cpu)))
+ goto not_done;
#endif
#if L1_CODE_LENGTH != 0
- if (_sram_proc_read(buf, &len, count, "L1 Instruction",
- &free_l1_inst_sram_head, &used_l1_inst_sram_head))
- goto not_done;
+ if (_sram_proc_read(buf, &len, count, "L1 Instruction",
+ &per_cpu(free_l1_inst_sram_head, cpu),
+ &per_cpu(used_l1_inst_sram_head, cpu)))
+ goto not_done;
#endif
+ }
#if L2_LENGTH != 0
- if (_sram_proc_read(buf, &len, count, "L2",
- &free_l2_sram_head, &used_l2_sram_head))
+ if (_sram_proc_read(buf, &len, count, "L2", &free_l2_sram_head,
+ &used_l2_sram_head))
goto not_done;
#endif
-
*eof = 1;
not_done:
return len;
diff --git a/arch/blackfin/oprofile/Makefile b/arch/blackfin/oprofile/Makefile
index 634e300d67e2..c70af3a01297 100644
--- a/arch/blackfin/oprofile/Makefile
+++ b/arch/blackfin/oprofile/Makefile
@@ -10,5 +10,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )
-oprofile-y := $(DRIVER_OBJS) common.o
-oprofile-$(CONFIG_HARDWARE_PM) += op_model_bf533.o
+oprofile-y := $(DRIVER_OBJS) bfin_oprofile.o
diff --git a/arch/blackfin/oprofile/bfin_oprofile.c b/arch/blackfin/oprofile/bfin_oprofile.c
new file mode 100644
index 000000000000..c3b9713b23f8
--- /dev/null
+++ b/arch/blackfin/oprofile/bfin_oprofile.c
@@ -0,0 +1,18 @@
+/*
+ * bfin_oprofile.c - Blackfin oprofile code
+ *
+ * Copyright 2004-2008 Analog Devices Inc.
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/oprofile.h>
+#include <linux/init.h>
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
+{
+ return -1;
+}
+
+void oprofile_arch_exit(void)
+{
+}
diff --git a/arch/blackfin/oprofile/common.c b/arch/blackfin/oprofile/common.c
deleted file mode 100644
index 0f6d303a8891..000000000000
--- a/arch/blackfin/oprofile/common.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * File: arch/blackfin/oprofile/common.c
- * Based on: arch/alpha/oprofile/common.c
- * Author: Anton Blanchard <anton@au.ibm.com>
- *
- * Created:
- * Description:
- *
- * Modified:
- * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/oprofile.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/ptrace.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/blackfin.h>
-
-#include "op_blackfin.h"
-
-#define BFIN_533_ID 0xE5040003
-#define BFIN_537_ID 0xE5040002
-
-static int pfmon_enabled;
-static struct mutex pfmon_lock;
-
-struct op_bfin533_model *model;
-
-struct op_counter_config ctr[OP_MAX_COUNTER];
-
-static int op_bfin_setup(void)
-{
- int ret;
-
- /* Pre-compute the values to stuff in the hardware registers. */
- spin_lock(&oprofilefs_lock);
- ret = model->reg_setup(ctr);
- spin_unlock(&oprofilefs_lock);
-
- return ret;
-}
-
-static void op_bfin_shutdown(void)
-{
-#if 0
- /* what is the difference between shutdown and stop? */
-#endif
-}
-
-static int op_bfin_start(void)
-{
- int ret = -EBUSY;
-
- printk(KERN_INFO "KSDBG:in %s\n", __func__);
- mutex_lock(&pfmon_lock);
- if (!pfmon_enabled) {
- ret = model->start(ctr);
- pfmon_enabled = !ret;
- }
- mutex_unlock(&pfmon_lock);
-
- return ret;
-}
-
-static void op_bfin_stop(void)
-{
- mutex_lock(&pfmon_lock);
- if (pfmon_enabled) {
- model->stop();
- pfmon_enabled = 0;
- }
- mutex_unlock(&pfmon_lock);
-}
-
-static int op_bfin_create_files(struct super_block *sb, struct dentry *root)
-{
- int i;
-
- for (i = 0; i < model->num_counters; ++i) {
- struct dentry *dir;
- char buf[3];
- printk(KERN_INFO "Oprofile: creating files... \n");
-
- snprintf(buf, sizeof buf, "%d", i);
- dir = oprofilefs_mkdir(sb, root, buf);
-
- oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
- oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
- oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
- /*
- * We dont support per counter user/kernel selection, but
- * we leave the entries because userspace expects them
- */
- oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
- oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
- oprofilefs_create_ulong(sb, dir, "unit_mask",
- &ctr[i].unit_mask);
- }
-
- return 0;
-}
-int __init oprofile_arch_init(struct oprofile_operations *ops)
-{
-#ifdef CONFIG_HARDWARE_PM
- unsigned int dspid;
-
- mutex_init(&pfmon_lock);
-
- dspid = bfin_read_DSPID();
-
- printk(KERN_INFO "Oprofile got the cpu id is 0x%x. \n", dspid);
-
- switch (dspid) {
- case BFIN_533_ID:
- model = &op_model_bfin533;
- model->num_counters = 2;
- break;
- case BFIN_537_ID:
- model = &op_model_bfin533;
- model->num_counters = 2;
- break;
- default:
- return -ENODEV;
- }
-
- ops->cpu_type = model->name;
- ops->create_files = op_bfin_create_files;
- ops->setup = op_bfin_setup;
- ops->shutdown = op_bfin_shutdown;
- ops->start = op_bfin_start;
- ops->stop = op_bfin_stop;
-
- printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
- ops->cpu_type);
-
- return 0;
-#else
- return -1;
-#endif
-}
-
-void oprofile_arch_exit(void)
-{
-}
diff --git a/arch/blackfin/oprofile/op_blackfin.h b/arch/blackfin/oprofile/op_blackfin.h
deleted file mode 100644
index 05dd08c9d154..000000000000
--- a/arch/blackfin/oprofile/op_blackfin.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * File: arch/blackfin/oprofile/op_blackfin.h
- * Based on:
- * Author: Anton Blanchard <anton@au.ibm.com>
- *
- * Created:
- * Description:
- *
- * Modified:
- * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef OP_BLACKFIN_H
-#define OP_BLACKFIN_H 1
-
-#define OP_MAX_COUNTER 2
-
-#include <asm/blackfin.h>
-
-/* Per-counter configuration as set via oprofilefs. */
-struct op_counter_config {
- unsigned long valid;
- unsigned long enabled;
- unsigned long event;
- unsigned long count;
- unsigned long kernel;
- unsigned long user;
- unsigned long unit_mask;
-};
-
-/* System-wide configuration as set via oprofilefs. */
-struct op_system_config {
- unsigned long enable_kernel;
- unsigned long enable_user;
-};
-
-/* Per-arch configuration */
-struct op_bfin533_model {
- int (*reg_setup) (struct op_counter_config *);
- int (*start) (struct op_counter_config *);
- void (*stop) (void);
- int num_counters;
- char *name;
-};
-
-extern struct op_bfin533_model op_model_bfin533;
-
-static inline unsigned int ctr_read(void)
-{
- unsigned int tmp;
-
- tmp = bfin_read_PFCTL();
- CSYNC();
-
- return tmp;
-}
-
-static inline void ctr_write(unsigned int val)
-{
- bfin_write_PFCTL(val);
- CSYNC();
-}
-
-static inline void count_read(unsigned int *count)
-{
- count[0] = bfin_read_PFCNTR0();
- count[1] = bfin_read_PFCNTR1();
- CSYNC();
-}
-
-static inline void count_write(unsigned int *count)
-{
- bfin_write_PFCNTR0(count[0]);
- bfin_write_PFCNTR1(count[1]);
- CSYNC();
-}
-
-extern int pm_overflow_handler(int irq, struct pt_regs *regs);
-
-#endif
diff --git a/arch/blackfin/oprofile/op_model_bf533.c b/arch/blackfin/oprofile/op_model_bf533.c
deleted file mode 100644
index d1c698bb9ee5..000000000000
--- a/arch/blackfin/oprofile/op_model_bf533.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * File: arch/blackfin/oprofile/op_model_bf533.c
- * Based on:
- * Author: Anton Blanchard <anton@au.ibm.com>
- *
- * Created:
- * Description:
- *
- * Modified:
- * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/oprofile.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/system.h>
-#include <asm/processor.h>
-#include <asm/blackfin.h>
-
-#include "op_blackfin.h"
-
-#define PM_ENABLE 0x01;
-#define PM_CTL1_ENABLE 0x18
-#define PM_CTL0_ENABLE 0xC000
-#define COUNT_EDGE_ONLY 0x3000000
-
-static int oprofile_running;
-
-static unsigned curr_pfctl, curr_count[2];
-
-static int bfin533_reg_setup(struct op_counter_config *ctr)
-{
- unsigned int pfctl = ctr_read();
- unsigned int count[2];
-
- /* set Blackfin perf monitor regs with ctr */
- if (ctr[0].enabled) {
- pfctl |= (PM_CTL0_ENABLE | ((char)ctr[0].event << 5));
- count[0] = 0xFFFFFFFF - ctr[0].count;
- curr_count[0] = count[0];
- }
- if (ctr[1].enabled) {
- pfctl |= (PM_CTL1_ENABLE | ((char)ctr[1].event << 16));
- count[1] = 0xFFFFFFFF - ctr[1].count;
- curr_count[1] = count[1];
- }
-
- pr_debug("ctr[0].enabled=%d,ctr[1].enabled=%d,ctr[0].event<<5=0x%x,ctr[1].event<<16=0x%x\n", ctr[0].enabled, ctr[1].enabled, ctr[0].event << 5, ctr[1].event << 16);
- pfctl |= COUNT_EDGE_ONLY;
- curr_pfctl = pfctl;
-
- pr_debug("write 0x%x to pfctl\n", pfctl);
- ctr_write(pfctl);
- count_write(count);
-
- return 0;
-}
-
-static int bfin533_start(struct op_counter_config *ctr)
-{
- unsigned int pfctl = ctr_read();
-
- pfctl |= PM_ENABLE;
- curr_pfctl = pfctl;
-
- ctr_write(pfctl);
-
- oprofile_running = 1;
- pr_debug("start oprofile counter \n");
-
- return 0;
-}
-
-static void bfin533_stop(void)
-{
- int pfctl;
-
- pfctl = ctr_read();
- pfctl &= ~PM_ENABLE;
- /* freeze counters */
- ctr_write(pfctl);
-
- oprofile_running = 0;
- pr_debug("stop oprofile counter \n");
-}
-
-static int get_kernel(void)
-{
- int ipend, is_kernel;
-
- ipend = bfin_read_IPEND();
-
- /* test bit 15 */
- is_kernel = ((ipend & 0x8000) != 0);
-
- return is_kernel;
-}
-
-int pm_overflow_handler(int irq, struct pt_regs *regs)
-{
- int is_kernel;
- int i, cpu;
- unsigned int pc, pfctl;
- unsigned int count[2];
-
- pr_debug("get interrupt in %s\n", __func__);
- if (oprofile_running == 0) {
- pr_debug("error: entering interrupt when oprofile is stopped.\n\r");
- return -1;
- }
-
- is_kernel = get_kernel();
- cpu = smp_processor_id();
- pc = regs->pc;
- pfctl = ctr_read();
-
- /* read the two event counter regs */
- count_read(count);
-
- /* if the counter overflows, add sample to oprofile buffer */
- for (i = 0; i < 2; ++i) {
- if (oprofile_running) {
- oprofile_add_sample(regs, i);
- }
- }
-
- /* reset the perfmon counter */
- ctr_write(curr_pfctl);
- count_write(curr_count);
- return 0;
-}
-
-struct op_bfin533_model op_model_bfin533 = {
- .reg_setup = bfin533_reg_setup,
- .start = bfin533_start,
- .stop = bfin533_stop,
- .num_counters = 2,
- .name = "blackfin/bf533"
-};
diff --git a/arch/blackfin/oprofile/timer_int.c b/arch/blackfin/oprofile/timer_int.c
deleted file mode 100644
index 6c6f8606af4c..000000000000
--- a/arch/blackfin/oprofile/timer_int.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * File: arch/blackfin/oprofile/timer_int.c
- * Based on:
- * Author: Michael Kang
- *
- * Created:
- * Description:
- *
- * Modified:
- * Copyright 2004-2006 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/irq.h>
-#include <linux/oprofile.h>
-#include <linux/ptrace.h>
-
-static void enable_sys_timer0()
-{
-}
-static void disable_sys_timer0()
-{
-}
-
-static irqreturn_t sys_timer0_int_handler(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- oprofile_add_sample(regs, 0);
- return IRQ_HANDLED;
-}
-
-static int sys_timer0_start(void)
-{
- enable_sys_timer0();
- return request_irq(IVG11, sys_timer0_int_handler, 0, "sys_timer0", NULL);
-}
-
-static void sys_timer0_stop(void)
-{
- disable_sys_timer();
-}
-
-int __init sys_timer0_init(struct oprofile_operations *ops)
-{
- extern int nmi_active;
-
- if (nmi_active <= 0)
- return -ENODEV;
-
- ops->start = timer_start;
- ops->stop = timer_stop;
- ops->cpu_type = "timer";
- printk(KERN_INFO "oprofile: using NMI timer interrupt.\n");
- return 0;
-}
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index b17aeea8d620..3462245fe9fb 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -681,6 +681,8 @@ source "drivers/usb/Kconfig"
source "drivers/uwb/Kconfig"
+source "drivers/staging/Kconfig"
+
source "arch/cris/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index ed171d389e65..72f5cd319b97 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -691,7 +691,7 @@ sys_call_table:
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/cris/arch-v32/drivers/iop_fw_load.c b/arch/cris/arch-v32/drivers/iop_fw_load.c
index 3b3857ec1f15..2f8ea0f7a63c 100644
--- a/arch/cris/arch-v32/drivers/iop_fw_load.c
+++ b/arch/cris/arch-v32/drivers/iop_fw_load.c
@@ -24,12 +24,12 @@
#error "Please contact <greg@kroah.com> for details on how to fix it properly."
static struct device iop_spu_device[2] = {
- { .bus_id = "iop-spu0", },
- { .bus_id = "iop-spu1", },
+ { .init_name = "iop-spu0", },
+ { .init_name = "iop-spu1", },
};
static struct device iop_mpu_device = {
- .bus_id = "iop-mpu",
+ .init_name = "iop-mpu",
};
static int wait_mpu_idle(void)
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S
index 7f6f93e6b70e..5e674c8f7c51 100644
--- a/arch/cris/arch-v32/kernel/entry.S
+++ b/arch/cris/arch-v32/kernel/entry.S
@@ -614,7 +614,7 @@ sys_call_table:
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index 173c141ac9ba..295131fee710 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -325,11 +325,11 @@ static void end_crisv32_irq(unsigned int irq)
{
}
-void set_affinity_crisv32_irq(unsigned int irq, cpumask_t dest)
+void set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
{
unsigned long flags;
spin_lock_irqsave(&irq_lock, flags);
- irq_allocations[irq - FIRST_IRQ].mask = dest;
+ irq_allocations[irq - FIRST_IRQ].mask = *dest;
spin_unlock_irqrestore(&irq_lock, flags);
}
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index da7d2be000ba..372d0ca6efbc 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -456,7 +456,7 @@ give_sigsegv:
return -EFAULT;
}
-/* Invoke a singal handler to, well, handle the signal. */
+/* Invoke a signal handler to, well, handle the signal. */
static inline int
handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka,
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 52e16c6436f9..9dac17334640 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -29,11 +29,7 @@
spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED};
/* CPU masks */
-cpumask_t cpu_online_map = CPU_MASK_NONE;
-EXPORT_SYMBOL(cpu_online_map);
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
-cpumask_t cpu_possible_map;
-EXPORT_SYMBOL(cpu_possible_map);
EXPORT_SYMBOL(phys_cpu_present_map);
/* Variables used during SMP boot */
diff --git a/arch/cris/include/arch-v10/arch/byteorder.h b/arch/cris/include/arch-v10/arch/swab.h
index 255b646b7fa8..e4e847d8a05e 100644
--- a/arch/cris/include/arch-v10/arch/byteorder.h
+++ b/arch/cris/include/arch-v10/arch/swab.h
@@ -1,26 +1,30 @@
-#ifndef _CRIS_ARCH_BYTEORDER_H
-#define _CRIS_ARCH_BYTEORDER_H
+#ifndef _CRIS_ARCH_SWAB_H
+#define _CRIS_ARCH_SWAB_H
#include <asm/types.h>
#include <linux/compiler.h>
+#define __SWAB_64_THRU_32__
+
/* we just define these two (as we can do the swap in a single
* asm instruction in CRIS) and the arch-independent files will put
* them together into ntohl etc.
*/
-static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
{
__asm__ ("swapwb %0" : "=r" (x) : "0" (x));
-
+
return(x);
}
+#define __arch_swab32 __arch_swab32
-static inline __attribute_const__ __u16 ___arch__swab16(__u16 x)
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
{
__asm__ ("swapb %0" : "=r" (x) : "0" (x));
-
+
return(x);
}
+#define __arch_swab16 __arch_swab16
#endif
diff --git a/arch/cris/include/arch-v32/arch/byteorder.h b/arch/cris/include/arch-v32/arch/byteorder.h
deleted file mode 100644
index 6ef8fb4a35f2..000000000000
--- a/arch/cris/include/arch-v32/arch/byteorder.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASM_CRIS_ARCH_BYTEORDER_H
-#define _ASM_CRIS_ARCH_BYTEORDER_H
-
-#include <asm/types.h>
-
-static inline __const__ __u32
-___arch__swab32(__u32 x)
-{
- __asm__ __volatile__ ("swapwb %0" : "=r" (x) : "0" (x));
- return (x);
-}
-
-static inline __const__ __u16
-___arch__swab16(__u16 x)
-{
- __asm__ __volatile__ ("swapb %0" : "=r" (x) : "0" (x));
- return (x);
-}
-
-#endif /* _ASM_CRIS_ARCH_BYTEORDER_H */
diff --git a/arch/cris/include/arch-v32/arch/swab.h b/arch/cris/include/arch-v32/arch/swab.h
new file mode 100644
index 000000000000..9a4ea5e209c2
--- /dev/null
+++ b/arch/cris/include/arch-v32/arch/swab.h
@@ -0,0 +1,24 @@
+#ifndef _ASM_CRIS_ARCH_SWAB_H
+#define _ASM_CRIS_ARCH_SWAB_H
+
+#include <asm/types.h>
+
+#define __SWAB_64_THRU_32__
+
+static inline __const__ __u32
+__arch_swab32(__u32 x)
+{
+ __asm__ __volatile__ ("swapwb %0" : "=r" (x) : "0" (x));
+ return (x);
+}
+#define __arch_swab32 __arch_swab32
+
+static inline __const__ __u16
+__arch_swab16(__u16 x)
+{
+ __asm__ __volatile__ ("swapb %0" : "=r" (x) : "0" (x));
+ return (x);
+}
+#define __arch_swab16 __arch_swab16
+
+#endif /* _ASM_CRIS_ARCH_SWAB_H */
diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h
index f71ea686a2ea..5718dd8902a1 100644
--- a/arch/cris/include/asm/atomic.h
+++ b/arch/cris/include/asm/atomic.h
@@ -4,7 +4,7 @@
#define __ASM_CRIS_ATOMIC__
#include <linux/compiler.h>
-
+#include <linux/types.h>
#include <asm/system.h>
#include <arch/atomic.h>
@@ -13,8 +13,6 @@
* resource counting etc..
*/
-typedef struct { volatile int counter; } atomic_t;
-
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
diff --git a/arch/cris/include/asm/bitops.h b/arch/cris/include/asm/bitops.h
index c0e62f811e09..9e69cfb7f134 100644
--- a/arch/cris/include/asm/bitops.h
+++ b/arch/cris/include/asm/bitops.h
@@ -148,6 +148,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
#define ffs kernel_ffs
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/find.h>
diff --git a/arch/cris/include/asm/byteorder.h b/arch/cris/include/asm/byteorder.h
index cc8e418cfd14..bcd189798e26 100644
--- a/arch/cris/include/asm/byteorder.h
+++ b/arch/cris/include/asm/byteorder.h
@@ -1,25 +1,6 @@
#ifndef _CRIS_BYTEORDER_H
#define _CRIS_BYTEORDER_H
-#ifdef __GNUC__
-
-#ifdef __KERNEL__
-#include <arch/byteorder.h>
-
-/* defines are necessary because the other files detect the presence
- * of a defined __arch_swab32, not an inline
- */
-#define __arch__swab32(x) ___arch__swab32(x)
-#define __arch__swab16(x) ___arch__swab16(x)
-#endif /* __KERNEL__ */
-
-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
-
-#endif /* __GNUC__ */
-
#include <linux/byteorder/little_endian.h>
#endif
diff --git a/arch/cris/include/asm/smp.h b/arch/cris/include/asm/smp.h
index dba33aba3e95..c615a06dd757 100644
--- a/arch/cris/include/asm/smp.h
+++ b/arch/cris/include/asm/smp.h
@@ -4,7 +4,6 @@
#include <linux/cpumask.h>
extern cpumask_t phys_cpu_present_map;
-extern cpumask_t cpu_possible_map;
#define raw_smp_processor_id() (current_thread_info()->cpu)
diff --git a/arch/cris/include/asm/swab.h b/arch/cris/include/asm/swab.h
new file mode 100644
index 000000000000..80668e88419c
--- /dev/null
+++ b/arch/cris/include/asm/swab.h
@@ -0,0 +1,8 @@
+#ifndef _CRIS_SWAB_H
+#define _CRIS_SWAB_H
+
+#ifdef __KERNEL__
+#include <arch/swab.h>
+#endif /* __KERNEL__ */
+
+#endif /* _CRIS_SWAB_H */
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 5933656db5a2..60816e876455 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -37,7 +37,6 @@
* setup.
*/
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/frv/kernel/init_task.c b/arch/frv/kernel/init_task.c
index e2198815b630..29429a8b7f6a 100644
--- a/arch/frv/kernel/init_task.c
+++ b/arch/frv/kernel/init_task.c
@@ -10,7 +10,6 @@
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index 709e9bdc6126..5e7d401d21e7 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -69,7 +69,8 @@ static inline int put_reg(struct task_struct *task, int regno,
}
/*
- * check that an address falls within the bounds of the target process's memory mappings
+ * check that an address falls within the bounds of the target process's memory
+ * mappings
*/
static inline int is_user_addr_valid(struct task_struct *child,
unsigned long start, unsigned long len)
@@ -79,11 +80,11 @@ static inline int is_user_addr_valid(struct task_struct *child,
return -EIO;
return 0;
#else
- struct vm_list_struct *vml;
+ struct vm_area_struct *vma;
- for (vml = child->mm->context.vmlist; vml; vml = vml->next)
- if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end)
- return 0;
+ vma = find_vma(child->mm, start);
+ if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
+ return 0;
return -EIO;
#endif
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 28f06fd9b7b7..9420648352b8 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -220,6 +220,8 @@ source "drivers/uwb/Kconfig"
endmenu
+source "drivers/staging/Kconfig"
+
source "fs/Kconfig"
source "arch/h8300/Kconfig.debug"
diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h
index b4cf0ea97ede..833186c8dc3b 100644
--- a/arch/h8300/include/asm/atomic.h
+++ b/arch/h8300/include/asm/atomic.h
@@ -1,12 +1,13 @@
#ifndef __ARCH_H8300_ATOMIC__
#define __ARCH_H8300_ATOMIC__
+#include <linux/types.h>
+
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
*/
-typedef struct { int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h
index cb18e3b0aa94..cb9ddf5fc54f 100644
--- a/arch/h8300/include/asm/bitops.h
+++ b/arch/h8300/include/asm/bitops.h
@@ -207,6 +207,7 @@ static __inline__ unsigned long __ffs(unsigned long word)
#endif /* __KERNEL__ */
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#endif /* _H8300_BITOPS_H */
diff --git a/arch/h8300/include/asm/byteorder.h b/arch/h8300/include/asm/byteorder.h
index 36e597d61619..13539da99efd 100644
--- a/arch/h8300/include/asm/byteorder.h
+++ b/arch/h8300/include/asm/byteorder.h
@@ -1,13 +1,6 @@
#ifndef _H8300_BYTEORDER_H
#define _H8300_BYTEORDER_H
-#include <asm/types.h>
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
-
#include <linux/byteorder/big_endian.h>
#endif /* _H8300_BYTEORDER_H */
diff --git a/arch/h8300/include/asm/mmu.h b/arch/h8300/include/asm/mmu.h
index 2ce06ea46104..31309969df70 100644
--- a/arch/h8300/include/asm/mmu.h
+++ b/arch/h8300/include/asm/mmu.h
@@ -4,7 +4,6 @@
/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
typedef struct {
- struct vm_list_struct *vmlist;
unsigned long end_brk;
} mm_context_t;
diff --git a/arch/h8300/include/asm/swab.h b/arch/h8300/include/asm/swab.h
new file mode 100644
index 000000000000..c108f39b8bc4
--- /dev/null
+++ b/arch/h8300/include/asm/swab.h
@@ -0,0 +1,10 @@
+#ifndef _H8300_SWAB_H
+#define _H8300_SWAB_H
+
+#include <asm/types.h>
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __SWAB_64_THRU_32__
+#endif
+
+#endif /* _H8300_SWAB_H */
diff --git a/arch/h8300/kernel/init_task.c b/arch/h8300/kernel/init_task.c
index 93a4899e46c2..cb5dc552da97 100644
--- a/arch/h8300/kernel/init_task.c
+++ b/arch/h8300/kernel/init_task.c
@@ -12,7 +12,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
index 54e21c3f2057..4eb67faac633 100644
--- a/arch/h8300/kernel/syscalls.S
+++ b/arch/h8300/kernel/syscalls.S
@@ -103,7 +103,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
.long SYMBOL_NAME(sys_uselib)
.long SYMBOL_NAME(sys_swapon)
.long SYMBOL_NAME(sys_reboot)
- .long SYMBOL_NAME(old_readdir)
+ .long SYMBOL_NAME(sys_old_readdir)
.long SYMBOL_NAME(old_mmap) /* 90 */
.long SYMBOL_NAME(sys_munmap)
.long SYMBOL_NAME(sys_truncate)
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 7fa8f615ba6e..6183aeccecf1 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -17,6 +17,7 @@ config IA64
select ACPI if (!IA64_HP_SIM)
select PM if (!IA64_HP_SIM)
select ARCH_SUPPORTS_MSI
+ select HAVE_UNSTABLE_SCHED_CLOCK
select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
@@ -687,3 +688,6 @@ config IRQ_PER_CPU
config IOMMU_HELPER
def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
+
+config IOMMU_API
+ def_bool (DMAR)
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
index 6dd8655664f3..ace41096b47b 100644
--- a/arch/ia64/configs/bigsur_defconfig
+++ b/arch/ia64/configs/bigsur_defconfig
@@ -752,7 +752,7 @@ CONFIG_I2C_ALGOBIT=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index 27eb67604c53..a109db30ce55 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -578,7 +578,7 @@ CONFIG_ATA_PIIX=y
# 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_VITESSE=y
# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ACPI is not set
# CONFIG_PATA_ALI is not set
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index 0a06b1333c95..514f0635dafe 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -841,7 +841,7 @@ CONFIG_I2C_ALGOPCF=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index d98f0f4ff83f..6d5e6c5630e3 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -906,7 +906,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
dma_addr_t
sba_map_single_attrs(struct device *dev, void *addr, size_t size, int dir,
@@ -1024,7 +1024,7 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
int dir, struct dma_attrs *attrs)
@@ -1102,7 +1102,7 @@ EXPORT_SYMBOL(sba_unmap_single_attrs);
* @size: number of bytes mapped in driver buffer.
* @dma_handle: IOVA of new buffer.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
void *
sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
@@ -1165,7 +1165,7 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp
* @vaddr: virtual address IOVA of "consistent" buffer.
* @dma_handler: IO virtual address of "consistent" buffer.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
void sba_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle)
{
@@ -1420,7 +1420,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
int dir, struct dma_attrs *attrs)
@@ -1512,7 +1512,7 @@ EXPORT_SYMBOL(sba_map_sg_attrs);
* @dir: R/W or both.
* @attrs: optional dma attributes
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
int nents, int dir, struct dma_attrs *attrs)
diff --git a/arch/ia64/hp/sim/hpsim_irq.c b/arch/ia64/hp/sim/hpsim_irq.c
index c2f58ff364e7..cc0a3182db3c 100644
--- a/arch/ia64/hp/sim/hpsim_irq.c
+++ b/arch/ia64/hp/sim/hpsim_irq.c
@@ -22,7 +22,7 @@ hpsim_irq_noop (unsigned int irq)
}
static void
-hpsim_set_affinity_noop (unsigned int a, cpumask_t b)
+hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
{
}
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index a8cf19958850..a46f8395e9a5 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -220,7 +220,7 @@ ia32_syscall_table:
data8 sys_mkdir
data8 sys_rmdir /* 40 */
data8 sys_dup
- data8 sys_pipe
+ data8 sys_ia64_pipe
data8 compat_sys_times
data8 sys_ni_syscall /* old prof syscall holder */
data8 sys32_brk /* 45 */
diff --git a/arch/ia64/include/asm/acpi-ext.h b/arch/ia64/include/asm/acpi-ext.h
index 734d137dda6e..7f8362b379eb 100644
--- a/arch/ia64/include/asm/acpi-ext.h
+++ b/arch/ia64/include/asm/acpi-ext.h
@@ -14,7 +14,6 @@
#define _ASM_IA64_ACPI_EXT_H
#include <linux/types.h>
-#include <acpi/actypes.h>
extern acpi_status hp_acpi_csr_space (acpi_handle, u64 *base, u64 *length);
diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h
index 50c2b83fd5a0..d37292bd9875 100644
--- a/arch/ia64/include/asm/atomic.h
+++ b/arch/ia64/include/asm/atomic.h
@@ -17,12 +17,6 @@
#include <asm/intrinsics.h>
#include <asm/system.h>
-/*
- * On IA-64, counter must always be volatile to ensure that that the
- * memory accesses are ordered.
- */
-typedef struct { volatile __s32 counter; } atomic_t;
-typedef struct { volatile __s64 counter; } atomic64_t;
#define ATOMIC_INIT(i) ((atomic_t) { (i) })
#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
diff --git a/arch/ia64/include/asm/byteorder.h b/arch/ia64/include/asm/byteorder.h
index 69bd41d7c26e..a8dd73558150 100644
--- a/arch/ia64/include/asm/byteorder.h
+++ b/arch/ia64/include/asm/byteorder.h
@@ -1,42 +1,6 @@
#ifndef _ASM_IA64_BYTEORDER_H
#define _ASM_IA64_BYTEORDER_H
-/*
- * Modified 1998, 1999
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
- */
-
-#include <asm/types.h>
-#include <asm/intrinsics.h>
-#include <linux/compiler.h>
-
-static __inline__ __attribute_const__ __u64
-__ia64_swab64 (__u64 x)
-{
- __u64 result;
-
- result = ia64_mux1(x, ia64_mux1_rev);
- return result;
-}
-
-static __inline__ __attribute_const__ __u32
-__ia64_swab32 (__u32 x)
-{
- return __ia64_swab64(x) >> 32;
-}
-
-static __inline__ __attribute_const__ __u16
-__ia64_swab16(__u16 x)
-{
- return __ia64_swab64(x) >> 48;
-}
-
-#define __arch__swab64(x) __ia64_swab64(x)
-#define __arch__swab32(x) __ia64_swab32(x)
-#define __arch__swab16(x) __ia64_swab16(x)
-
-#define __BYTEORDER_HAS_U64__
-
#include <linux/byteorder/little_endian.h>
#endif /* _ASM_IA64_BYTEORDER_H */
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index bbab7e2b0fc9..1f912d927585 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -9,6 +9,8 @@
#include <linux/scatterlist.h>
#include <asm/swiotlb.h>
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
struct dma_mapping_ops {
int (*mapping_error)(struct device *dev,
dma_addr_t dma_addr);
diff --git a/arch/ia64/include/asm/irq.h b/arch/ia64/include/asm/irq.h
index 3627116fb0e2..5282546cdf82 100644
--- a/arch/ia64/include/asm/irq.h
+++ b/arch/ia64/include/asm/irq.h
@@ -27,7 +27,7 @@ irq_canonicalize (int irq)
}
extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
-bool is_affinity_mask_valid(cpumask_t cpumask);
+bool is_affinity_mask_valid(const struct cpumask *cpumask);
#define is_affinity_mask_valid is_affinity_mask_valid
diff --git a/arch/ia64/include/asm/kvm.h b/arch/ia64/include/asm/kvm.h
index f38472ac2267..68aa6da807c1 100644
--- a/arch/ia64/include/asm/kvm.h
+++ b/arch/ia64/include/asm/kvm.h
@@ -166,8 +166,6 @@ struct saved_vpd {
};
struct kvm_regs {
- char *saved_guest;
- char *saved_stack;
struct saved_vpd vpd;
/*Arch-regs*/
int mp_state;
@@ -200,6 +198,10 @@ struct kvm_regs {
unsigned long fp_psr; /*used for lazy float register */
unsigned long saved_gp;
/*for phycial emulation */
+
+ union context saved_guest;
+
+ unsigned long reserved[64]; /* for future use */
};
struct kvm_sregs {
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h
index c60d324da540..348663661659 100644
--- a/arch/ia64/include/asm/kvm_host.h
+++ b/arch/ia64/include/asm/kvm_host.h
@@ -23,17 +23,6 @@
#ifndef __ASM_KVM_HOST_H
#define __ASM_KVM_HOST_H
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/kvm.h>
-#include <linux/kvm_para.h>
-#include <linux/kvm_types.h>
-
-#include <asm/pal.h>
-#include <asm/sal.h>
-
-#define KVM_MAX_VCPUS 4
#define KVM_MEMORY_SLOTS 32
/* memory slots that does not exposed to userspace */
#define KVM_PRIVATE_MEM_SLOTS 4
@@ -50,70 +39,132 @@
#define EXIT_REASON_EXTERNAL_INTERRUPT 6
#define EXIT_REASON_IPI 7
#define EXIT_REASON_PTC_G 8
+#define EXIT_REASON_DEBUG 20
/*Define vmm address space and vm data space.*/
-#define KVM_VMM_SIZE (16UL<<20)
+#define KVM_VMM_SIZE (__IA64_UL_CONST(16)<<20)
#define KVM_VMM_SHIFT 24
-#define KVM_VMM_BASE 0xD000000000000000UL
-#define VMM_SIZE (8UL<<20)
+#define KVM_VMM_BASE 0xD000000000000000
+#define VMM_SIZE (__IA64_UL_CONST(8)<<20)
/*
* Define vm_buffer, used by PAL Services, base address.
- * Note: vmbuffer is in the VMM-BLOCK, the size must be < 8M
+ * Note: vm_buffer is in the VMM-BLOCK, the size must be < 8M
*/
#define KVM_VM_BUFFER_BASE (KVM_VMM_BASE + VMM_SIZE)
-#define KVM_VM_BUFFER_SIZE (8UL<<20)
-
-/*Define Virtual machine data layout.*/
-#define KVM_VM_DATA_SHIFT 24
-#define KVM_VM_DATA_SIZE (1UL << KVM_VM_DATA_SHIFT)
-#define KVM_VM_DATA_BASE (KVM_VMM_BASE + KVM_VMM_SIZE)
-
-
-#define KVM_P2M_BASE KVM_VM_DATA_BASE
-#define KVM_P2M_OFS 0
-#define KVM_P2M_SIZE (8UL << 20)
-
-#define KVM_VHPT_BASE (KVM_P2M_BASE + KVM_P2M_SIZE)
-#define KVM_VHPT_OFS KVM_P2M_SIZE
-#define KVM_VHPT_BLOCK_SIZE (2UL << 20)
-#define VHPT_SHIFT 18
-#define VHPT_SIZE (1UL << VHPT_SHIFT)
-#define VHPT_NUM_ENTRIES (1<<(VHPT_SHIFT-5))
-
-#define KVM_VTLB_BASE (KVM_VHPT_BASE+KVM_VHPT_BLOCK_SIZE)
-#define KVM_VTLB_OFS (KVM_VHPT_OFS+KVM_VHPT_BLOCK_SIZE)
-#define KVM_VTLB_BLOCK_SIZE (1UL<<20)
-#define VTLB_SHIFT 17
-#define VTLB_SIZE (1UL<<VTLB_SHIFT)
-#define VTLB_NUM_ENTRIES (1<<(VTLB_SHIFT-5))
-
-#define KVM_VPD_BASE (KVM_VTLB_BASE+KVM_VTLB_BLOCK_SIZE)
-#define KVM_VPD_OFS (KVM_VTLB_OFS+KVM_VTLB_BLOCK_SIZE)
-#define KVM_VPD_BLOCK_SIZE (2UL<<20)
-#define VPD_SHIFT 16
-#define VPD_SIZE (1UL<<VPD_SHIFT)
-
-#define KVM_VCPU_BASE (KVM_VPD_BASE+KVM_VPD_BLOCK_SIZE)
-#define KVM_VCPU_OFS (KVM_VPD_OFS+KVM_VPD_BLOCK_SIZE)
-#define KVM_VCPU_BLOCK_SIZE (2UL<<20)
-#define VCPU_SHIFT 18
-#define VCPU_SIZE (1UL<<VCPU_SHIFT)
-#define MAX_VCPU_NUM KVM_VCPU_BLOCK_SIZE/VCPU_SIZE
-
-#define KVM_VM_BASE (KVM_VCPU_BASE+KVM_VCPU_BLOCK_SIZE)
-#define KVM_VM_OFS (KVM_VCPU_OFS+KVM_VCPU_BLOCK_SIZE)
-#define KVM_VM_BLOCK_SIZE (1UL<<19)
-
-#define KVM_MEM_DIRTY_LOG_BASE (KVM_VM_BASE+KVM_VM_BLOCK_SIZE)
-#define KVM_MEM_DIRTY_LOG_OFS (KVM_VM_OFS+KVM_VM_BLOCK_SIZE)
-#define KVM_MEM_DIRTY_LOG_SIZE (1UL<<19)
-
-/* Get vpd, vhpt, tlb, vcpu, base*/
-#define VPD_ADDR(n) (KVM_VPD_BASE+n*VPD_SIZE)
-#define VHPT_ADDR(n) (KVM_VHPT_BASE+n*VHPT_SIZE)
-#define VTLB_ADDR(n) (KVM_VTLB_BASE+n*VTLB_SIZE)
-#define VCPU_ADDR(n) (KVM_VCPU_BASE+n*VCPU_SIZE)
+#define KVM_VM_BUFFER_SIZE (__IA64_UL_CONST(8)<<20)
+
+/*
+ * kvm guest's data area looks as follow:
+ *
+ * +----------------------+ ------- KVM_VM_DATA_SIZE
+ * | vcpu[n]'s data | | ___________________KVM_STK_OFFSET
+ * | | | / |
+ * | .......... | | /vcpu's struct&stack |
+ * | .......... | | /---------------------|---- 0
+ * | vcpu[5]'s data | | / vpd |
+ * | vcpu[4]'s data | |/-----------------------|
+ * | vcpu[3]'s data | / vtlb |
+ * | vcpu[2]'s data | /|------------------------|
+ * | vcpu[1]'s data |/ | vhpt |
+ * | vcpu[0]'s data |____________________________|
+ * +----------------------+ |
+ * | memory dirty log | |
+ * +----------------------+ |
+ * | vm's data struct | |
+ * +----------------------+ |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | vm's p2m table | |
+ * | | |
+ * | | |
+ * | | | |
+ * vm's data->| | | |
+ * +----------------------+ ------- 0
+ * To support large memory, needs to increase the size of p2m.
+ * To support more vcpus, needs to ensure it has enough space to
+ * hold vcpus' data.
+ */
+
+#define KVM_VM_DATA_SHIFT 26
+#define KVM_VM_DATA_SIZE (__IA64_UL_CONST(1) << KVM_VM_DATA_SHIFT)
+#define KVM_VM_DATA_BASE (KVM_VMM_BASE + KVM_VM_DATA_SIZE)
+
+#define KVM_P2M_BASE KVM_VM_DATA_BASE
+#define KVM_P2M_SIZE (__IA64_UL_CONST(24) << 20)
+
+#define VHPT_SHIFT 16
+#define VHPT_SIZE (__IA64_UL_CONST(1) << VHPT_SHIFT)
+#define VHPT_NUM_ENTRIES (__IA64_UL_CONST(1) << (VHPT_SHIFT-5))
+
+#define VTLB_SHIFT 16
+#define VTLB_SIZE (__IA64_UL_CONST(1) << VTLB_SHIFT)
+#define VTLB_NUM_ENTRIES (1UL << (VHPT_SHIFT-5))
+
+#define VPD_SHIFT 16
+#define VPD_SIZE (__IA64_UL_CONST(1) << VPD_SHIFT)
+
+#define VCPU_STRUCT_SHIFT 16
+#define VCPU_STRUCT_SIZE (__IA64_UL_CONST(1) << VCPU_STRUCT_SHIFT)
+
+#define KVM_STK_OFFSET VCPU_STRUCT_SIZE
+
+#define KVM_VM_STRUCT_SHIFT 19
+#define KVM_VM_STRUCT_SIZE (__IA64_UL_CONST(1) << KVM_VM_STRUCT_SHIFT)
+
+#define KVM_MEM_DIRY_LOG_SHIFT 19
+#define KVM_MEM_DIRTY_LOG_SIZE (__IA64_UL_CONST(1) << KVM_MEM_DIRY_LOG_SHIFT)
+
+#ifndef __ASSEMBLY__
+
+/*Define the max vcpus and memory for Guests.*/
+#define KVM_MAX_VCPUS (KVM_VM_DATA_SIZE - KVM_P2M_SIZE - KVM_VM_STRUCT_SIZE -\
+ KVM_MEM_DIRTY_LOG_SIZE) / sizeof(struct kvm_vcpu_data)
+#define KVM_MAX_MEM_SIZE (KVM_P2M_SIZE >> 3 << PAGE_SHIFT)
+
+#define VMM_LOG_LEN 256
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/kvm.h>
+#include <linux/kvm_para.h>
+#include <linux/kvm_types.h>
+
+#include <asm/pal.h>
+#include <asm/sal.h>
+#include <asm/page.h>
+
+struct kvm_vcpu_data {
+ char vcpu_vhpt[VHPT_SIZE];
+ char vcpu_vtlb[VTLB_SIZE];
+ char vcpu_vpd[VPD_SIZE];
+ char vcpu_struct[VCPU_STRUCT_SIZE];
+};
+
+struct kvm_vm_data {
+ char kvm_p2m[KVM_P2M_SIZE];
+ char kvm_vm_struct[KVM_VM_STRUCT_SIZE];
+ char kvm_mem_dirty_log[KVM_MEM_DIRTY_LOG_SIZE];
+ struct kvm_vcpu_data vcpu_data[KVM_MAX_VCPUS];
+};
+
+#define VCPU_BASE(n) KVM_VM_DATA_BASE + \
+ offsetof(struct kvm_vm_data, vcpu_data[n])
+#define VM_BASE KVM_VM_DATA_BASE + \
+ offsetof(struct kvm_vm_data, kvm_vm_struct)
+#define KVM_MEM_DIRTY_LOG_BASE KVM_VM_DATA_BASE + \
+ offsetof(struct kvm_vm_data, kvm_mem_dirty_log)
+
+#define VHPT_BASE(n) (VCPU_BASE(n) + offsetof(struct kvm_vcpu_data, vcpu_vhpt))
+#define VTLB_BASE(n) (VCPU_BASE(n) + offsetof(struct kvm_vcpu_data, vcpu_vtlb))
+#define VPD_BASE(n) (VCPU_BASE(n) + offsetof(struct kvm_vcpu_data, vcpu_vpd))
+#define VCPU_STRUCT_BASE(n) (VCPU_BASE(n) + \
+ offsetof(struct kvm_vcpu_data, vcpu_struct))
/*IO section definitions*/
#define IOREQ_READ 1
@@ -389,6 +440,7 @@ struct kvm_vcpu_arch {
unsigned long opcode;
unsigned long cause;
+ char log_buf[VMM_LOG_LEN];
union context host;
union context guest;
};
@@ -403,20 +455,19 @@ struct kvm_sal_data {
};
struct kvm_arch {
+ spinlock_t dirty_log_lock;
+
unsigned long vm_base;
unsigned long metaphysical_rr0;
unsigned long metaphysical_rr4;
unsigned long vmm_init_rr;
- unsigned long vhpt_base;
- unsigned long vtlb_base;
- unsigned long vpd_base;
- spinlock_t dirty_log_lock;
+
struct kvm_ioapic *vioapic;
struct kvm_vm_stat stat;
struct kvm_sal_data rdv_sal_data;
struct list_head assigned_dev_head;
- struct dmar_domain *intel_iommu_domain;
+ struct iommu_domain *iommu_domain;
struct hlist_head irq_ack_notifier_list;
unsigned long irq_sources_bitmap;
@@ -512,7 +563,7 @@ struct kvm_pt_regs {
static inline struct kvm_pt_regs *vcpu_regs(struct kvm_vcpu *v)
{
- return (struct kvm_pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1;
+ return (struct kvm_pt_regs *) ((unsigned long) v + KVM_STK_OFFSET) - 1;
}
typedef int kvm_vmm_entry(void);
@@ -531,5 +582,6 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run);
void kvm_sal_emul(struct kvm_vcpu *vcpu);
static inline void kvm_inject_nmi(struct kvm_vcpu *vcpu) {}
+#endif /* __ASSEMBLY__*/
#endif
diff --git a/arch/ia64/include/asm/machvec.h b/arch/ia64/include/asm/machvec.h
index 59c17e446683..fe87b2121707 100644
--- a/arch/ia64/include/asm/machvec.h
+++ b/arch/ia64/include/asm/machvec.h
@@ -62,6 +62,7 @@ typedef dma_addr_t ia64_mv_dma_map_single_attrs (struct device *, void *, size_t
typedef void ia64_mv_dma_unmap_single_attrs (struct device *, dma_addr_t, size_t, int, struct dma_attrs *);
typedef int ia64_mv_dma_map_sg_attrs (struct device *, struct scatterlist *, int, int, struct dma_attrs *);
typedef void ia64_mv_dma_unmap_sg_attrs (struct device *, struct scatterlist *, int, int, struct dma_attrs *);
+typedef u64 ia64_mv_dma_get_required_mask (struct device *);
/*
* WARNING: The legacy I/O space is _architected_. Platforms are
@@ -159,6 +160,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
# define platform_dma_sync_sg_for_device ia64_mv.dma_sync_sg_for_device
# define platform_dma_mapping_error ia64_mv.dma_mapping_error
# define platform_dma_supported ia64_mv.dma_supported
+# define platform_dma_get_required_mask ia64_mv.dma_get_required_mask
# define platform_irq_to_vector ia64_mv.irq_to_vector
# define platform_local_vector_to_irq ia64_mv.local_vector_to_irq
# define platform_pci_get_legacy_mem ia64_mv.pci_get_legacy_mem
@@ -213,6 +215,7 @@ struct ia64_machine_vector {
ia64_mv_dma_sync_sg_for_device *dma_sync_sg_for_device;
ia64_mv_dma_mapping_error *dma_mapping_error;
ia64_mv_dma_supported *dma_supported;
+ ia64_mv_dma_get_required_mask *dma_get_required_mask;
ia64_mv_irq_to_vector *irq_to_vector;
ia64_mv_local_vector_to_irq *local_vector_to_irq;
ia64_mv_pci_get_legacy_mem_t *pci_get_legacy_mem;
@@ -263,6 +266,7 @@ struct ia64_machine_vector {
platform_dma_sync_sg_for_device, \
platform_dma_mapping_error, \
platform_dma_supported, \
+ platform_dma_get_required_mask, \
platform_irq_to_vector, \
platform_local_vector_to_irq, \
platform_pci_get_legacy_mem, \
@@ -366,6 +370,9 @@ extern void machvec_init_from_cmdline(const char *cmdline);
#ifndef platform_dma_supported
# define platform_dma_supported swiotlb_dma_supported
#endif
+#ifndef platform_dma_get_required_mask
+# define platform_dma_get_required_mask ia64_dma_get_required_mask
+#endif
#ifndef platform_irq_to_vector
# define platform_irq_to_vector __ia64_irq_to_vector
#endif
diff --git a/arch/ia64/include/asm/machvec_init.h b/arch/ia64/include/asm/machvec_init.h
index ef964b286842..37a469849ab9 100644
--- a/arch/ia64/include/asm/machvec_init.h
+++ b/arch/ia64/include/asm/machvec_init.h
@@ -3,6 +3,7 @@
extern ia64_mv_send_ipi_t ia64_send_ipi;
extern ia64_mv_global_tlb_purge_t ia64_global_tlb_purge;
+extern ia64_mv_dma_get_required_mask ia64_dma_get_required_mask;
extern ia64_mv_irq_to_vector __ia64_irq_to_vector;
extern ia64_mv_local_vector_to_irq __ia64_local_vector_to_irq;
extern ia64_mv_pci_get_legacy_mem_t ia64_pci_get_legacy_mem;
diff --git a/arch/ia64/include/asm/machvec_sn2.h b/arch/ia64/include/asm/machvec_sn2.h
index 781308ea7b88..f1a6e0d6dfa5 100644
--- a/arch/ia64/include/asm/machvec_sn2.h
+++ b/arch/ia64/include/asm/machvec_sn2.h
@@ -67,6 +67,7 @@ extern ia64_mv_dma_sync_single_for_device sn_dma_sync_single_for_device;
extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device;
extern ia64_mv_dma_mapping_error sn_dma_mapping_error;
extern ia64_mv_dma_supported sn_dma_supported;
+extern ia64_mv_dma_get_required_mask sn_dma_get_required_mask;
extern ia64_mv_migrate_t sn_migrate;
extern ia64_mv_kernel_launch_event_t sn_kernel_launch_event;
extern ia64_mv_setup_msi_irq_t sn_setup_msi_irq;
@@ -123,6 +124,7 @@ extern ia64_mv_pci_fixup_bus_t sn_pci_fixup_bus;
#define platform_dma_sync_sg_for_device sn_dma_sync_sg_for_device
#define platform_dma_mapping_error sn_dma_mapping_error
#define platform_dma_supported sn_dma_supported
+#define platform_dma_get_required_mask sn_dma_get_required_mask
#define platform_migrate sn_migrate
#define platform_kernel_launch_event sn_kernel_launch_event
#ifdef CONFIG_PCI_MSI
diff --git a/arch/ia64/include/asm/smp.h b/arch/ia64/include/asm/smp.h
index 12d96e0cd513..21c402365d0e 100644
--- a/arch/ia64/include/asm/smp.h
+++ b/arch/ia64/include/asm/smp.h
@@ -57,7 +57,6 @@ extern struct smp_boot_data {
extern char no_int_routing __devinitdata;
-extern cpumask_t cpu_online_map;
extern cpumask_t cpu_core_map[NR_CPUS];
DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
extern int smp_num_siblings;
diff --git a/arch/ia64/include/asm/sn/acpi.h b/arch/ia64/include/asm/sn/acpi.h
index 9ce2801cbd57..fd480db25565 100644
--- a/arch/ia64/include/asm/sn/acpi.h
+++ b/arch/ia64/include/asm/sn/acpi.h
@@ -9,8 +9,6 @@
#ifndef _ASM_IA64_SN_ACPI_H
#define _ASM_IA64_SN_ACPI_H
-#include "acpi/acglobal.h"
-
extern int sn_acpi_rev;
#define SN_ACPI_BASE_SUPPORT() (sn_acpi_rev >= 0x20101)
diff --git a/arch/ia64/include/asm/swab.h b/arch/ia64/include/asm/swab.h
new file mode 100644
index 000000000000..6aa58b699eea
--- /dev/null
+++ b/arch/ia64/include/asm/swab.h
@@ -0,0 +1,34 @@
+#ifndef _ASM_IA64_SWAB_H
+#define _ASM_IA64_SWAB_H
+
+/*
+ * Modified 1998, 1999
+ * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co.
+ */
+
+#include <asm/types.h>
+#include <asm/intrinsics.h>
+#include <linux/compiler.h>
+
+static __inline__ __attribute_const__ __u64 __arch_swab64(__u64 x)
+{
+ __u64 result;
+
+ result = ia64_mux1(x, ia64_mux1_rev);
+ return result;
+}
+#define __arch_swab64 __arch_swab64
+
+static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+ return __arch_swab64(x) >> 32;
+}
+#define __arch_swab32 __arch_swab32
+
+static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 x)
+{
+ return __arch_swab64(x) >> 48;
+}
+#define __arch_swab16 __arch_swab16
+
+#endif /* _ASM_IA64_SWAB_H */
diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
index fb79423834d0..dcbaea7ce128 100644
--- a/arch/ia64/include/asm/swiotlb.h
+++ b/arch/ia64/include/asm/swiotlb.h
@@ -2,44 +2,7 @@
#define ASM_IA64__SWIOTLB_H
#include <linux/dma-mapping.h>
-
-/* SWIOTLB interface */
-
-extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
- size_t size, int dir);
-extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags);
-extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
- size_t size, int dir);
-extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
- dma_addr_t dev_addr,
- size_t size, int dir);
-extern void swiotlb_sync_single_for_device(struct device *hwdev,
- dma_addr_t dev_addr,
- size_t size, int dir);
-extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev,
- dma_addr_t dev_addr,
- unsigned long offset,
- size_t size, int dir);
-extern void swiotlb_sync_single_range_for_device(struct device *hwdev,
- dma_addr_t dev_addr,
- unsigned long offset,
- size_t size, int dir);
-extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- int dir);
-extern void swiotlb_sync_sg_for_device(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- int dir);
-extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction);
-extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction);
-extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
-extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
-extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
-extern void swiotlb_init(void);
+#include <linux/swiotlb.h>
extern int swiotlb_force;
diff --git a/arch/ia64/include/asm/topology.h b/arch/ia64/include/asm/topology.h
index 35bcb641c9e5..32f3af1641c5 100644
--- a/arch/ia64/include/asm/topology.h
+++ b/arch/ia64/include/asm/topology.h
@@ -34,6 +34,7 @@
* Returns a bitmask of CPUs on Node 'node'.
*/
#define node_to_cpumask(node) (node_to_cpu_mask[node])
+#define cpumask_of_node(node) (&node_to_cpu_mask[node])
/*
* Returns the number of the node containing Node 'nid'.
@@ -45,7 +46,7 @@
/*
* Returns the number of the first CPU on Node 'node'.
*/
-#define node_to_first_cpu(node) (first_cpu(node_to_cpumask(node)))
+#define node_to_first_cpu(node) (cpumask_first(cpumask_of_node(node)))
/*
* Determines the node for a given pci bus
@@ -55,7 +56,6 @@
void build_cpu_to_node_map(void);
#define SD_CPU_INIT (struct sched_domain) { \
- .span = CPU_MASK_NONE, \
.parent = NULL, \
.child = NULL, \
.groups = NULL, \
@@ -80,7 +80,6 @@ void build_cpu_to_node_map(void);
/* sched_domains SD_NODE_INIT for IA64 NUMA machines */
#define SD_NODE_INIT (struct sched_domain) { \
- .span = CPU_MASK_NONE, \
.parent = NULL, \
.child = NULL, \
.groups = NULL, \
@@ -111,6 +110,8 @@ void build_cpu_to_node_map(void);
#define topology_core_id(cpu) (cpu_data(cpu)->core_id)
#define topology_core_siblings(cpu) (cpu_core_map[cpu])
#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
+#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
#define smt_capable() (smp_num_siblings > 1)
#endif
@@ -121,6 +122,10 @@ extern void arch_fix_phys_package_id(int num, u32 slot);
node_to_cpumask(pcibus_to_node(bus)) \
)
+#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \
+ cpu_all_mask : \
+ cpumask_of_node(pcibus_to_node(bus)))
+
#include <asm-generic/topology.h>
#endif /* _ASM_IA64_TOPOLOGY_H */
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index f791576355ad..9015979ebe0f 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -364,7 +364,7 @@ struct pt_regs;
struct sigaction;
long sys_execve(char __user *filename, char __user * __user *argv,
char __user * __user *envp, struct pt_regs *regs);
-asmlinkage long sys_pipe(void);
+asmlinkage long sys_ia64_pipe(void);
asmlinkage long sys_rt_sigaction(int sig,
const struct sigaction __user *act,
struct sigaction __user *oact,
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index bd7acc71e8a9..d541671caf4a 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -65,6 +65,7 @@ EXPORT_SYMBOL(pm_idle);
void (*pm_power_off) (void);
EXPORT_SYMBOL(pm_power_off);
+u32 acpi_rsdt_forced;
unsigned int acpi_cpei_override;
unsigned int acpi_cpei_phys_cpuid;
@@ -202,7 +203,6 @@ char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size)
Boot-time Table Parsing
-------------------------------------------------------------------------- */
-static int total_cpus __initdata;
static int available_cpus __initdata;
struct acpi_table_madt *acpi_madt __initdata;
static u8 has_8259;
@@ -1001,7 +1001,7 @@ acpi_map_iosapic(acpi_handle handle, u32 depth, void *context, void **ret)
node = pxm_to_node(pxm);
if (node >= MAX_NUMNODES || !node_online(node) ||
- cpus_empty(node_to_cpumask(node)))
+ cpumask_empty(cpumask_of_node(node)))
return AE_OK;
/* We know a gsi to node mapping! */
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index d435f4a7a96c..e5341e2c1175 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1442,7 +1442,7 @@ sys_call_table:
data8 sys_mkdir // 1055
data8 sys_rmdir
data8 sys_dup
- data8 sys_pipe
+ data8 sys_ia64_pipe
data8 sys_times
data8 ia64_brk // 1060
data8 sys_setgid
diff --git a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
index 9d7e1c66faf4..5b0e830c6f33 100644
--- a/arch/ia64/kernel/init_task.c
+++ b/arch/ia64/kernel/init_task.c
@@ -17,7 +17,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 5c4674ae8aea..5cfd3d91001a 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -330,25 +330,25 @@ unmask_irq (unsigned int irq)
static void
-iosapic_set_affinity (unsigned int irq, cpumask_t mask)
+iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
{
#ifdef CONFIG_SMP
u32 high32, low32;
- int dest, rte_index;
+ int cpu, dest, rte_index;
int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
struct iosapic_rte_info *rte;
struct iosapic *iosapic;
irq &= (~IA64_IRQ_REDIRECTED);
- cpus_and(mask, mask, cpu_online_map);
- if (cpus_empty(mask))
+ cpu = cpumask_first_and(cpu_online_mask, mask);
+ if (cpu >= nr_cpu_ids)
return;
- if (irq_prepare_move(irq, first_cpu(mask)))
+ if (irq_prepare_move(irq, cpu))
return;
- dest = cpu_physical_id(first_cpu(mask));
+ dest = cpu_physical_id(cpu);
if (!iosapic_intr_info[irq].count)
return; /* not an IOSAPIC interrupt */
@@ -695,32 +695,31 @@ get_target_cpu (unsigned int gsi, int irq)
#ifdef CONFIG_NUMA
{
int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
- cpumask_t cpu_mask;
+ const struct cpumask *cpu_mask;
iosapic_index = find_iosapic(gsi);
if (iosapic_index < 0 ||
iosapic_lists[iosapic_index].node == MAX_NUMNODES)
goto skip_numa_setup;
- cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node);
- cpus_and(cpu_mask, cpu_mask, domain);
- for_each_cpu_mask(numa_cpu, cpu_mask) {
- if (!cpu_online(numa_cpu))
- cpu_clear(numa_cpu, cpu_mask);
+ cpu_mask = cpumask_of_node(iosapic_lists[iosapic_index].node);
+ num_cpus = 0;
+ for_each_cpu_and(numa_cpu, cpu_mask, &domain) {
+ if (cpu_online(numa_cpu))
+ num_cpus++;
}
- num_cpus = cpus_weight(cpu_mask);
-
if (!num_cpus)
goto skip_numa_setup;
/* Use irq assignment to distribute across cpus in node */
cpu_index = irq % num_cpus;
- for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
- numa_cpu = next_cpu(numa_cpu, cpu_mask);
+ for_each_cpu_and(numa_cpu, cpu_mask, &domain)
+ if (cpu_online(numa_cpu) && i++ >= cpu_index)
+ break;
- if (numa_cpu != NR_CPUS)
+ if (numa_cpu < nr_cpu_ids)
return cpu_physical_id(numa_cpu);
}
skip_numa_setup:
@@ -731,7 +730,7 @@ skip_numa_setup:
* case of NUMA.)
*/
do {
- if (++cpu >= NR_CPUS)
+ if (++cpu >= nr_cpu_ids)
cpu = 0;
} while (!cpu_online(cpu) || !cpu_isset(cpu, domain));
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 7fd18f54c056..a58f64ca9f0e 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -102,21 +102,18 @@ static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
{
- cpumask_t mask = CPU_MASK_NONE;
-
- cpu_set(cpu_logical_id(hwid), mask);
-
if (irq < NR_IRQS) {
- irq_desc[irq].affinity = mask;
+ cpumask_copy(&irq_desc[irq].affinity,
+ cpumask_of(cpu_logical_id(hwid)));
irq_redir[irq] = (char) (redir & 0xff);
}
}
-bool is_affinity_mask_valid(cpumask_t cpumask)
+bool is_affinity_mask_valid(const struct cpumask *cpumask)
{
if (ia64_platform_is("sn2")) {
/* Only allow one CPU to be specified in the smp_affinity mask */
- if (cpus_weight(cpumask) != 1)
+ if (cpumask_weight(cpumask) != 1)
return false;
}
return true;
@@ -128,12 +125,11 @@ bool is_affinity_mask_valid(cpumask_t cpumask)
unsigned int vectors_in_migration[NR_IRQS];
/*
- * Since cpu_online_map is already updated, we just need to check for
+ * Since cpu_online_mask is already updated, we just need to check for
* affinity that has zeros
*/
static void migrate_irqs(void)
{
- cpumask_t mask;
irq_desc_t *desc;
int irq, new_cpu;
@@ -152,15 +148,14 @@ static void migrate_irqs(void)
if (desc->status == IRQ_PER_CPU)
continue;
- cpus_and(mask, irq_desc[irq].affinity, cpu_online_map);
- if (any_online_cpu(mask) == NR_CPUS) {
+ if (cpumask_any_and(&irq_desc[irq].affinity, cpu_online_mask)
+ >= nr_cpu_ids) {
/*
* Save it for phase 2 processing
*/
vectors_in_migration[irq] = irq;
- new_cpu = any_online_cpu(cpu_online_map);
- mask = cpumask_of_cpu(new_cpu);
+ new_cpu = cpumask_any(cpu_online_mask);
/*
* Al three are essential, currently WARN_ON.. maybe panic?
@@ -168,7 +163,8 @@ static void migrate_irqs(void)
if (desc->chip && desc->chip->disable &&
desc->chip->enable && desc->chip->set_affinity) {
desc->chip->disable(irq);
- desc->chip->set_affinity(irq, mask);
+ desc->chip->set_affinity(irq,
+ cpumask_of(new_cpu));
desc->chip->enable(irq);
} else {
WARN_ON((!(desc->chip) || !(desc->chip->disable) ||
@@ -192,7 +188,7 @@ void fixup_irqs(void)
* Find a new timesync master
*/
if (smp_processor_id() == time_keeper_id) {
- time_keeper_id = first_cpu(cpu_online_map);
+ time_keeper_id = cpumask_first(cpu_online_mask);
printk ("CPU %d is now promoted to time-keeper master\n", time_keeper_id);
}
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index f07688da947c..9adac441ac9b 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -434,7 +434,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
/*
* It is possible to have multiple instances associated with a given
* task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
+ * have a return probe installed on them, and/or more than one return
* return probe was registered for a target function.
*
* We can handle this because:
@@ -670,9 +670,11 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
- mutex_lock(&kprobe_mutex);
- free_insn_slot(p->ainsn.insn, p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
- mutex_unlock(&kprobe_mutex);
+ if (p->ainsn.insn) {
+ free_insn_slot(p->ainsn.insn,
+ p->ainsn.inst_flag & INST_FLAG_BOOSTABLE);
+ p->ainsn.insn = NULL;
+ }
}
/*
* We are resuming execution after a single step fault, so the pt_regs
@@ -868,7 +870,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
return 1;
ss_probe:
-#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
+#if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER)
if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
/* Boost up -- we can execute copied instructions directly */
ia64_psr(regs)->ri = p->ainsn.slot;
diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c
index 702a09c13238..890339339035 100644
--- a/arch/ia64/kernel/msi_ia64.c
+++ b/arch/ia64/kernel/msi_ia64.c
@@ -49,11 +49,12 @@
static struct irq_chip ia64_msi_chip;
#ifdef CONFIG_SMP
-static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
+static void ia64_set_msi_irq_affinity(unsigned int irq,
+ const cpumask_t *cpu_mask)
{
struct msi_msg msg;
u32 addr, data;
- int cpu = first_cpu(cpu_mask);
+ int cpu = first_cpu(*cpu_mask);
if (!cpu_online(cpu))
return;
@@ -166,12 +167,11 @@ void arch_teardown_msi_irq(unsigned int irq)
#ifdef CONFIG_DMAR
#ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
+static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_cfg *cfg = irq_cfg + irq;
struct msi_msg msg;
- int cpu = first_cpu(mask);
-
+ int cpu = cpumask_first(mask);
if (!cpu_online(cpu))
return;
@@ -187,7 +187,7 @@ static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu));
dmar_msi_write(irq, &msg);
- irq_desc[irq].affinity = mask;
+ irq_desc[irq].affinity = *mask;
}
#endif /* CONFIG_SMP */
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index 2a92f637431d..d0ada067a4af 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -39,7 +39,7 @@ int iommu_detected __read_mostly;
be probably a smaller DMA mask, but this is bug-to-bug compatible
to i386. */
struct device fallback_dev = {
- .bus_id = "fallback device",
+ .init_name = "fallback device",
.coherent_dma_mask = DMA_32BIT_MASK,
.dma_mask = &fallback_dev.coherent_dma_mask,
};
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 1dcbb85fc4ee..11463994a7d5 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -131,12 +131,6 @@ struct task_struct *task_for_booting_cpu;
*/
DEFINE_PER_CPU(int, cpu_state);
-/* Bitmasks of currently online, and possible CPUs */
-cpumask_t cpu_online_map;
-EXPORT_SYMBOL(cpu_online_map);
-cpumask_t cpu_possible_map = CPU_MASK_NONE;
-EXPORT_SYMBOL(cpu_possible_map);
-
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
EXPORT_SYMBOL(cpu_core_map);
DEFINE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
@@ -688,7 +682,7 @@ int migrate_platform_irqs(unsigned int cpu)
{
int new_cpei_cpu;
irq_desc_t *desc = NULL;
- cpumask_t mask;
+ const struct cpumask *mask;
int retval = 0;
/*
@@ -701,7 +695,7 @@ int migrate_platform_irqs(unsigned int cpu)
* Now re-target the CPEI to a different processor
*/
new_cpei_cpu = any_online_cpu(cpu_online_map);
- mask = cpumask_of_cpu(new_cpei_cpu);
+ mask = cpumask_of(new_cpei_cpu);
set_cpei_target_cpu(new_cpei_cpu);
desc = irq_desc + ia64_cpe_irq;
/*
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index bcbb6d8792d3..92ed83f34036 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -154,7 +154,7 @@ out:
* and r9) as this is faster than doing a copy_to_user().
*/
asmlinkage long
-sys_pipe (void)
+sys_ia64_pipe (void)
{
struct pt_regs *regs = task_pt_regs(current);
int fd[2];
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 65c10a42c88f..f0ebb342409d 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -93,13 +93,14 @@ void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
now = ia64_get_itc();
delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
- account_system_time(prev, 0, delta_stime);
- account_system_time_scaled(prev, delta_stime);
+ if (idle_task(smp_processor_id()) != prev)
+ account_system_time(prev, 0, delta_stime, delta_stime);
+ else
+ account_idle_time(delta_stime);
if (pi->ac_utime) {
delta_utime = cycle_to_cputime(pi->ac_utime);
- account_user_time(prev, delta_utime);
- account_user_time_scaled(prev, delta_utime);
+ account_user_time(prev, delta_utime, delta_utime);
}
pi->ac_stamp = ni->ac_stamp = now;
@@ -122,8 +123,10 @@ void account_system_vtime(struct task_struct *tsk)
now = ia64_get_itc();
delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
- account_system_time(tsk, 0, delta_stime);
- account_system_time_scaled(tsk, delta_stime);
+ if (irq_count() || idle_task(smp_processor_id()) != tsk)
+ account_system_time(tsk, 0, delta_stime, delta_stime);
+ else
+ account_idle_time(delta_stime);
ti->ac_stime = 0;
ti->ac_stamp = now;
@@ -143,8 +146,7 @@ void account_process_tick(struct task_struct *p, int user_tick)
if (ti->ac_utime) {
delta_utime = cycle_to_cputime(ti->ac_utime);
- account_user_time(p, delta_utime);
- account_user_time_scaled(p, delta_utime);
+ account_user_time(p, delta_utime, delta_utime);
ti->ac_utime = 0;
}
}
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index c75b914f2d6b..a8d61a3e9a94 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -219,7 +219,7 @@ static ssize_t show_shared_cpu_map(struct cache_info *this_leaf, char *buf)
cpumask_t shared_cpu_map;
cpus_and(shared_cpu_map, this_leaf->shared_cpu_map, cpu_online_map);
- len = cpumask_scnprintf(buf, NR_CPUS+1, shared_cpu_map);
+ len = cpumask_scnprintf(buf, NR_CPUS+1, &shared_cpu_map);
len += sprintf(buf+len, "\n");
return len;
}
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index ff0e7c10faa7..6db08599ebbc 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -59,6 +59,7 @@ dump (const char *str, void *vp, size_t len)
* (i.e. don't allow attacker to fill up logs with unaligned accesses).
*/
int no_unaligned_warning;
+int unaligned_dump_stack;
static int noprint_warning;
/*
@@ -1371,9 +1372,12 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
}
}
} else {
- if (within_logging_rate_limit())
+ if (within_logging_rate_limit()) {
printk(KERN_WARNING "kernel unaligned access to 0x%016lx, ip=0x%016lx\n",
ifa, regs->cr_iip + ipsr->ri);
+ if (unaligned_dump_stack)
+ dump_stack();
+ }
set_fs(KERNEL_DS);
}
diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile
index 92cef66ca268..0bb99b732908 100644
--- a/arch/ia64/kvm/Makefile
+++ b/arch/ia64/kvm/Makefile
@@ -51,8 +51,8 @@ EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
coalesced_mmio.o irq_comm.o)
-ifeq ($(CONFIG_DMAR),y)
-common-objs += $(addprefix ../../../virt/kvm/, vtd.o)
+ifeq ($(CONFIG_IOMMU_API),y)
+common-objs += $(addprefix ../../../virt/kvm/, iommu.o)
endif
kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
@@ -60,7 +60,7 @@ obj-$(CONFIG_KVM) += kvm.o
CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127
kvm-intel-objs = vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o mmio.o \
- vtlb.o process.o
+ vtlb.o process.o kvm_lib.o
#Add link memcpy and memset to avoid possible structure assignment error
kvm-intel-objs += memcpy.o memset.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
diff --git a/arch/ia64/kvm/asm-offsets.c b/arch/ia64/kvm/asm-offsets.c
index 4e3dc13a619c..0c3564a7a033 100644
--- a/arch/ia64/kvm/asm-offsets.c
+++ b/arch/ia64/kvm/asm-offsets.c
@@ -24,19 +24,10 @@
#include <linux/autoconf.h>
#include <linux/kvm_host.h>
+#include <linux/kbuild.h>
#include "vcpu.h"
-#define task_struct kvm_vcpu
-
-#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " (%0) " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : :)
-
-#define OFFSET(_sym, _str, _mem) \
- DEFINE(_sym, offsetof(_str, _mem));
-
void foo(void)
{
DEFINE(VMM_TASK_SIZE, sizeof(struct kvm_vcpu));
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index af1464f7a6ad..4e586f6110aa 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -31,6 +31,7 @@
#include <linux/bitops.h>
#include <linux/hrtimer.h>
#include <linux/uaccess.h>
+#include <linux/iommu.h>
#include <linux/intel-iommu.h>
#include <asm/pgtable.h>
@@ -180,7 +181,6 @@ int kvm_dev_ioctl_check_extension(long ext)
switch (ext) {
case KVM_CAP_IRQCHIP:
- case KVM_CAP_USER_MEMORY:
case KVM_CAP_MP_STATE:
r = 1;
@@ -189,7 +189,7 @@ int kvm_dev_ioctl_check_extension(long ext)
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
break;
case KVM_CAP_IOMMU:
- r = intel_iommu_found();
+ r = iommu_found();
break;
default:
r = 0;
@@ -439,7 +439,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
expires = div64_u64(itc_diff, cyc_per_usec);
kt = ktime_set(0, 1000 * expires);
- down_read(&vcpu->kvm->slots_lock);
vcpu->arch.ht_active = 1;
hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS);
@@ -452,7 +451,6 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
vcpu->arch.mp_state =
KVM_MP_STATE_RUNNABLE;
- up_read(&vcpu->kvm->slots_lock);
if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
return -EINTR;
@@ -476,6 +474,13 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu,
return 1;
}
+static int handle_vcpu_debug(struct kvm_vcpu *vcpu,
+ struct kvm_run *kvm_run)
+{
+ printk("VMM: %s", vcpu->arch.log_buf);
+ return 1;
+}
+
static int (*kvm_vti_exit_handlers[])(struct kvm_vcpu *vcpu,
struct kvm_run *kvm_run) = {
[EXIT_REASON_VM_PANIC] = handle_vm_error,
@@ -487,6 +492,7 @@ static int (*kvm_vti_exit_handlers[])(struct kvm_vcpu *vcpu,
[EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt,
[EXIT_REASON_IPI] = handle_ipi,
[EXIT_REASON_PTC_G] = handle_global_purge,
+ [EXIT_REASON_DEBUG] = handle_vcpu_debug,
};
@@ -698,27 +704,24 @@ out:
return r;
}
-/*
- * Allocate 16M memory for every vm to hold its specific data.
- * Its memory map is defined in kvm_host.h.
- */
static struct kvm *kvm_alloc_kvm(void)
{
struct kvm *kvm;
uint64_t vm_base;
+ BUG_ON(sizeof(struct kvm) > KVM_VM_STRUCT_SIZE);
+
vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE));
if (!vm_base)
return ERR_PTR(-ENOMEM);
- printk(KERN_DEBUG"kvm: VM data's base Address:0x%lx\n", vm_base);
- /* Zero all pages before use! */
memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
-
- kvm = (struct kvm *)(vm_base + KVM_VM_OFS);
+ kvm = (struct kvm *)(vm_base +
+ offsetof(struct kvm_vm_data, kvm_vm_struct));
kvm->arch.vm_base = vm_base;
+ printk(KERN_DEBUG"kvm: vm's data area:0x%lx\n", vm_base);
return kvm;
}
@@ -760,21 +763,12 @@ static void kvm_build_io_pmt(struct kvm *kvm)
static void kvm_init_vm(struct kvm *kvm)
{
- long vm_base;
-
BUG_ON(!kvm);
kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4;
kvm->arch.vmm_init_rr = VMM_INIT_RR;
- vm_base = kvm->arch.vm_base;
- if (vm_base) {
- kvm->arch.vhpt_base = vm_base + KVM_VHPT_OFS;
- kvm->arch.vtlb_base = vm_base + KVM_VTLB_OFS;
- kvm->arch.vpd_base = vm_base + KVM_VPD_OFS;
- }
-
/*
*Fill P2M entries for MMIO/IO ranges
*/
@@ -838,9 +832,8 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
- int i;
struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
- int r;
+ int i;
vcpu_load(vcpu);
@@ -857,18 +850,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
vpd->vpr = regs->vpd.vpr;
- r = -EFAULT;
- r = copy_from_user(&vcpu->arch.guest, regs->saved_guest,
- sizeof(union context));
- if (r)
- goto out;
- r = copy_from_user(vcpu + 1, regs->saved_stack +
- sizeof(struct kvm_vcpu),
- IA64_STK_OFFSET - sizeof(struct kvm_vcpu));
- if (r)
- goto out;
- vcpu->arch.exit_data =
- ((struct kvm_vcpu *)(regs->saved_stack))->arch.exit_data;
+ memcpy(&vcpu->arch.guest, &regs->saved_guest, sizeof(union context));
RESTORE_REGS(mp_state);
RESTORE_REGS(vmm_rr);
@@ -902,9 +884,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
set_bit(KVM_REQ_RESUME, &vcpu->requests);
vcpu_put(vcpu);
- r = 0;
-out:
- return r;
+
+ return 0;
}
long kvm_arch_vm_ioctl(struct file *filp,
@@ -1166,10 +1147,11 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
/*Set entry address for first run.*/
regs->cr_iip = PALE_RESET_ENTRY;
- /*Initilize itc offset for vcpus*/
+ /*Initialize itc offset for vcpus*/
itc_offset = 0UL - ia64_getreg(_IA64_REG_AR_ITC);
- for (i = 0; i < MAX_VCPU_NUM; i++) {
- v = (struct kvm_vcpu *)((char *)vcpu + VCPU_SIZE * i);
+ for (i = 0; i < KVM_MAX_VCPUS; i++) {
+ v = (struct kvm_vcpu *)((char *)vcpu +
+ sizeof(struct kvm_vcpu_data) * i);
v->arch.itc_offset = itc_offset;
v->arch.last_itc = 0;
}
@@ -1183,7 +1165,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
vcpu->arch.apic->vcpu = vcpu;
p_ctx->gr[1] = 0;
- p_ctx->gr[12] = (unsigned long)((char *)vmm_vcpu + IA64_STK_OFFSET);
+ p_ctx->gr[12] = (unsigned long)((char *)vmm_vcpu + KVM_STK_OFFSET);
p_ctx->gr[13] = (unsigned long)vmm_vcpu;
p_ctx->psr = 0x1008522000UL;
p_ctx->ar[40] = FPSR_DEFAULT; /*fpsr*/
@@ -1218,12 +1200,12 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
vcpu->arch.hlt_timer.function = hlt_timer_fn;
vcpu->arch.last_run_cpu = -1;
- vcpu->arch.vpd = (struct vpd *)VPD_ADDR(vcpu->vcpu_id);
+ vcpu->arch.vpd = (struct vpd *)VPD_BASE(vcpu->vcpu_id);
vcpu->arch.vsa_base = kvm_vsa_base;
vcpu->arch.__gp = kvm_vmm_gp;
vcpu->arch.dirty_log_lock_pa = __pa(&kvm->arch.dirty_log_lock);
- vcpu->arch.vhpt.hash = (struct thash_data *)VHPT_ADDR(vcpu->vcpu_id);
- vcpu->arch.vtlb.hash = (struct thash_data *)VTLB_ADDR(vcpu->vcpu_id);
+ vcpu->arch.vhpt.hash = (struct thash_data *)VHPT_BASE(vcpu->vcpu_id);
+ vcpu->arch.vtlb.hash = (struct thash_data *)VTLB_BASE(vcpu->vcpu_id);
init_ptce_info(vcpu);
r = 0;
@@ -1273,12 +1255,22 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
int r;
int cpu;
+ BUG_ON(sizeof(struct kvm_vcpu) > VCPU_STRUCT_SIZE/2);
+
+ r = -EINVAL;
+ if (id >= KVM_MAX_VCPUS) {
+ printk(KERN_ERR"kvm: Can't configure vcpus > %ld",
+ KVM_MAX_VCPUS);
+ goto fail;
+ }
+
r = -ENOMEM;
if (!vm_base) {
printk(KERN_ERR"kvm: Create vcpu[%d] error!\n", id);
goto fail;
}
- vcpu = (struct kvm_vcpu *)(vm_base + KVM_VCPU_OFS + VCPU_SIZE * id);
+ vcpu = (struct kvm_vcpu *)(vm_base + offsetof(struct kvm_vm_data,
+ vcpu_data[id].vcpu_struct));
vcpu->kvm = kvm;
cpu = get_cpu();
@@ -1374,9 +1366,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
- int i;
- int r;
struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);
+ int i;
+
vcpu_load(vcpu);
for (i = 0; i < 16; i++) {
@@ -1391,14 +1383,8 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->vpd.vpsr = vpd->vpsr;
regs->vpd.vpr = vpd->vpr;
- r = -EFAULT;
- r = copy_to_user(regs->saved_guest, &vcpu->arch.guest,
- sizeof(union context));
- if (r)
- goto out;
- r = copy_to_user(regs->saved_stack, (void *)vcpu, IA64_STK_OFFSET);
- if (r)
- goto out;
+ memcpy(&regs->saved_guest, &vcpu->arch.guest, sizeof(union context));
+
SAVE_REGS(mp_state);
SAVE_REGS(vmm_rr);
memcpy(regs->itrs, vcpu->arch.itrs, sizeof(struct thash_data) * NITRS);
@@ -1426,10 +1412,9 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
SAVE_REGS(metaphysical_saved_rr4);
SAVE_REGS(fp_psr);
SAVE_REGS(saved_gp);
+
vcpu_put(vcpu);
- r = 0;
-out:
- return r;
+ return 0;
}
void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
@@ -1457,6 +1442,9 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot];
unsigned long base_gfn = memslot->base_gfn;
+ if (base_gfn + npages > (KVM_MAX_MEM_SIZE >> PAGE_SHIFT))
+ return -ENOMEM;
+
for (i = 0; i < npages; i++) {
pfn = gfn_to_pfn(kvm, base_gfn + i);
if (!kvm_is_mmio_pfn(pfn)) {
@@ -1631,8 +1619,8 @@ static int kvm_ia64_sync_dirty_log(struct kvm *kvm,
struct kvm_memory_slot *memslot;
int r, i;
long n, base;
- unsigned long *dirty_bitmap = (unsigned long *)((void *)kvm - KVM_VM_OFS
- + KVM_MEM_DIRTY_LOG_OFS);
+ unsigned long *dirty_bitmap = (unsigned long *)(kvm->arch.vm_base +
+ offsetof(struct kvm_vm_data, kvm_mem_dirty_log));
r = -EINVAL;
if (log->slot >= KVM_MEMORY_SLOTS)
diff --git a/arch/ia64/kvm/kvm_lib.c b/arch/ia64/kvm/kvm_lib.c
new file mode 100644
index 000000000000..a85cb611ecd7
--- /dev/null
+++ b/arch/ia64/kvm/kvm_lib.c
@@ -0,0 +1,15 @@
+/*
+ * kvm_lib.c: Compile some libraries for kvm-intel module.
+ *
+ * Just include kernel's library, and disable symbols export.
+ * Copyright (C) 2008, Intel Corporation.
+ * Xiantao Zhang (xiantao.zhang@intel.com)
+ *
+ * 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.
+ *
+ */
+#undef CONFIG_MODULES
+#include "../../../lib/vsprintf.c"
+#include "../../../lib/ctype.c"
diff --git a/arch/ia64/kvm/kvm_minstate.h b/arch/ia64/kvm/kvm_minstate.h
index 2cc41d17cf99..b2bcaa2787aa 100644
--- a/arch/ia64/kvm/kvm_minstate.h
+++ b/arch/ia64/kvm/kvm_minstate.h
@@ -24,6 +24,8 @@
#include <asm/asmmacro.h>
#include <asm/types.h>
#include <asm/kregs.h>
+#include <asm/kvm_host.h>
+
#include "asm-offsets.h"
#define KVM_MINSTATE_START_SAVE_MIN \
@@ -33,7 +35,7 @@
addl r22 = VMM_RBS_OFFSET,r1; /* compute base of RBS */ \
;; \
lfetch.fault.excl.nt1 [r22]; \
- addl r1 = IA64_STK_OFFSET-VMM_PT_REGS_SIZE,r1; /* compute base of memory stack */ \
+ addl r1 = KVM_STK_OFFSET-VMM_PT_REGS_SIZE, r1; \
mov r23 = ar.bspstore; /* save ar.bspstore */ \
;; \
mov ar.bspstore = r22; /* switch to kernel RBS */\
diff --git a/arch/ia64/kvm/misc.h b/arch/ia64/kvm/misc.h
index e585c4607344..dd979e00b574 100644
--- a/arch/ia64/kvm/misc.h
+++ b/arch/ia64/kvm/misc.h
@@ -27,7 +27,8 @@
*/
static inline uint64_t *kvm_host_get_pmt(struct kvm *kvm)
{
- return (uint64_t *)(kvm->arch.vm_base + KVM_P2M_OFS);
+ return (uint64_t *)(kvm->arch.vm_base +
+ offsetof(struct kvm_vm_data, kvm_p2m));
}
static inline void kvm_set_pmt_entry(struct kvm *kvm, gfn_t gfn,
diff --git a/arch/ia64/kvm/mmio.c b/arch/ia64/kvm/mmio.c
index 7f1a858bc69f..21f63fffc379 100644
--- a/arch/ia64/kvm/mmio.c
+++ b/arch/ia64/kvm/mmio.c
@@ -66,31 +66,25 @@ void lsapic_write(struct kvm_vcpu *v, unsigned long addr,
switch (addr) {
case PIB_OFST_INTA:
- /*panic_domain(NULL, "Undefined write on PIB INTA\n");*/
- panic_vm(v);
+ panic_vm(v, "Undefined write on PIB INTA\n");
break;
case PIB_OFST_XTP:
if (length == 1) {
vlsapic_write_xtp(v, val);
} else {
- /*panic_domain(NULL,
- "Undefined write on PIB XTP\n");*/
- panic_vm(v);
+ panic_vm(v, "Undefined write on PIB XTP\n");
}
break;
default:
if (PIB_LOW_HALF(addr)) {
- /*lower half */
+ /*Lower half */
if (length != 8)
- /*panic_domain(NULL,
- "Can't LHF write with size %ld!\n",
- length);*/
- panic_vm(v);
+ panic_vm(v, "Can't LHF write with size %ld!\n",
+ length);
else
vlsapic_write_ipi(v, addr, val);
- } else { /* upper half
- printk("IPI-UHF write %lx\n",addr);*/
- panic_vm(v);
+ } else { /*Upper half */
+ panic_vm(v, "IPI-UHF write %lx\n", addr);
}
break;
}
@@ -108,22 +102,18 @@ unsigned long lsapic_read(struct kvm_vcpu *v, unsigned long addr,
if (length == 1) /* 1 byte load */
; /* There is no i8259, there is no INTA access*/
else
- /*panic_domain(NULL,"Undefined read on PIB INTA\n"); */
- panic_vm(v);
+ panic_vm(v, "Undefined read on PIB INTA\n");
break;
case PIB_OFST_XTP:
if (length == 1) {
result = VLSAPIC_XTP(v);
- /* printk("read xtp %lx\n", result); */
} else {
- /*panic_domain(NULL,
- "Undefined read on PIB XTP\n");*/
- panic_vm(v);
+ panic_vm(v, "Undefined read on PIB XTP\n");
}
break;
default:
- panic_vm(v);
+ panic_vm(v, "Undefined addr access for lsapic!\n");
break;
}
return result;
@@ -162,7 +152,7 @@ static void mmio_access(struct kvm_vcpu *vcpu, u64 src_pa, u64 *dest,
/* it's necessary to ensure zero extending */
*dest = p->u.ioreq.data & (~0UL >> (64-(s*8)));
} else
- panic_vm(vcpu);
+ panic_vm(vcpu, "Unhandled mmio access returned!\n");
out:
local_irq_restore(psr);
return ;
@@ -324,7 +314,9 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
return;
} else {
inst_type = -1;
- panic_vm(vcpu);
+ panic_vm(vcpu, "Unsupported MMIO access instruction! \
+ Bunld[0]=0x%lx, Bundle[1]=0x%lx\n",
+ bundle.i64[0], bundle.i64[1]);
}
size = 1 << size;
@@ -335,7 +327,7 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
if (inst_type == SL_INTEGER)
vcpu_set_gr(vcpu, inst.M1.r1, data, 0);
else
- panic_vm(vcpu);
+ panic_vm(vcpu, "Unsupported instruction type!\n");
}
vcpu_increment_iip(vcpu);
diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c
index 800817307b7b..552d07724207 100644
--- a/arch/ia64/kvm/process.c
+++ b/arch/ia64/kvm/process.c
@@ -527,7 +527,8 @@ void reflect_interruption(u64 ifa, u64 isr, u64 iim,
vector = vec2off[vec];
if (!(vpsr & IA64_PSR_IC) && (vector != IA64_DATA_NESTED_TLB_VECTOR)) {
- panic_vm(vcpu);
+ panic_vm(vcpu, "Interruption with vector :0x%lx occurs "
+ "with psr.ic = 0\n", vector);
return;
}
@@ -586,7 +587,7 @@ static void set_pal_call_result(struct kvm_vcpu *vcpu)
vcpu_set_gr(vcpu, 10, p->u.pal_data.ret.v1, 0);
vcpu_set_gr(vcpu, 11, p->u.pal_data.ret.v2, 0);
} else
- panic_vm(vcpu);
+ panic_vm(vcpu, "Mis-set for exit reason!\n");
}
static void set_sal_call_data(struct kvm_vcpu *vcpu)
@@ -614,7 +615,7 @@ static void set_sal_call_result(struct kvm_vcpu *vcpu)
vcpu_set_gr(vcpu, 10, p->u.sal_data.ret.r10, 0);
vcpu_set_gr(vcpu, 11, p->u.sal_data.ret.r11, 0);
} else
- panic_vm(vcpu);
+ panic_vm(vcpu, "Mis-set for exit reason!\n");
}
void kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs,
@@ -680,7 +681,7 @@ static void generate_exirq(struct kvm_vcpu *vcpu)
vpsr = VCPU(vcpu, vpsr);
isr = vpsr & IA64_PSR_RI;
if (!(vpsr & IA64_PSR_IC))
- panic_vm(vcpu);
+ panic_vm(vcpu, "Trying to inject one IRQ with psr.ic=0\n");
reflect_interruption(0, isr, 0, 12, regs); /* EXT IRQ */
}
@@ -941,8 +942,20 @@ static void vcpu_do_resume(struct kvm_vcpu *vcpu)
ia64_set_pta(vcpu->arch.vhpt.pta.val);
}
+static void vmm_sanity_check(struct kvm_vcpu *vcpu)
+{
+ struct exit_ctl_data *p = &vcpu->arch.exit_data;
+
+ if (!vmm_sanity && p->exit_reason != EXIT_REASON_DEBUG) {
+ panic_vm(vcpu, "Failed to do vmm sanity check,"
+ "it maybe caused by crashed vmm!!\n\n");
+ }
+}
+
static void kvm_do_resume_op(struct kvm_vcpu *vcpu)
{
+ vmm_sanity_check(vcpu); /*Guarantee vcpu runing on healthy vmm!*/
+
if (test_and_clear_bit(KVM_REQ_RESUME, &vcpu->requests)) {
vcpu_do_resume(vcpu);
return;
@@ -968,3 +981,11 @@ void vmm_transition(struct kvm_vcpu *vcpu)
1, 0, 0, 0, 0, 0);
kvm_do_resume_op(vcpu);
}
+
+void vmm_panic_handler(u64 vec)
+{
+ struct kvm_vcpu *vcpu = current_vcpu;
+ vmm_sanity = 0;
+ panic_vm(vcpu, "Unexpected interruption occurs in VMM, vector:0x%lx\n",
+ vec2off[vec]);
+}
diff --git a/arch/ia64/kvm/vcpu.c b/arch/ia64/kvm/vcpu.c
index e44027ce5667..ecd526b55323 100644
--- a/arch/ia64/kvm/vcpu.c
+++ b/arch/ia64/kvm/vcpu.c
@@ -816,8 +816,9 @@ static void vcpu_set_itc(struct kvm_vcpu *vcpu, u64 val)
unsigned long vitv = VCPU(vcpu, itv);
if (vcpu->vcpu_id == 0) {
- for (i = 0; i < MAX_VCPU_NUM; i++) {
- v = (struct kvm_vcpu *)((char *)vcpu + VCPU_SIZE * i);
+ for (i = 0; i < KVM_MAX_VCPUS; i++) {
+ v = (struct kvm_vcpu *)((char *)vcpu +
+ sizeof(struct kvm_vcpu_data) * i);
VMX(v, itc_offset) = itc_offset;
VMX(v, last_itc) = 0;
}
@@ -1650,7 +1651,8 @@ void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val)
* Otherwise panic
*/
if (val & (IA64_PSR_PK | IA64_PSR_IS | IA64_PSR_VM))
- panic_vm(vcpu);
+ panic_vm(vcpu, "Only support guests with vpsr.pk =0 \
+ & vpsr.is=0\n");
/*
* For those IA64_PSR bits: id/da/dd/ss/ed/ia
@@ -2103,7 +2105,7 @@ void kvm_init_all_rr(struct kvm_vcpu *vcpu)
if (is_physical_mode(vcpu)) {
if (vcpu->arch.mode_flags & GUEST_PHY_EMUL)
- panic_vm(vcpu);
+ panic_vm(vcpu, "Machine Status conflicts!\n");
ia64_set_rr((VRN0 << VRN_SHIFT), vcpu->arch.metaphysical_rr0);
ia64_dv_serialize_data();
@@ -2152,10 +2154,70 @@ int vmm_entry(void)
return 0;
}
-void panic_vm(struct kvm_vcpu *v)
-{
+static void kvm_show_registers(struct kvm_pt_regs *regs)
+{
+ unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
+
+ struct kvm_vcpu *vcpu = current_vcpu;
+ if (vcpu != NULL)
+ printk("vcpu 0x%p vcpu %d\n",
+ vcpu, vcpu->vcpu_id);
+
+ printk("psr : %016lx ifs : %016lx ip : [<%016lx>]\n",
+ regs->cr_ipsr, regs->cr_ifs, ip);
+
+ printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
+ regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
+ printk("rnat: %016lx bspstore: %016lx pr : %016lx\n",
+ regs->ar_rnat, regs->ar_bspstore, regs->pr);
+ printk("ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
+ regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
+ printk("csd : %016lx ssd : %016lx\n", regs->ar_csd, regs->ar_ssd);
+ printk("b0 : %016lx b6 : %016lx b7 : %016lx\n", regs->b0,
+ regs->b6, regs->b7);
+ printk("f6 : %05lx%016lx f7 : %05lx%016lx\n",
+ regs->f6.u.bits[1], regs->f6.u.bits[0],
+ regs->f7.u.bits[1], regs->f7.u.bits[0]);
+ printk("f8 : %05lx%016lx f9 : %05lx%016lx\n",
+ regs->f8.u.bits[1], regs->f8.u.bits[0],
+ regs->f9.u.bits[1], regs->f9.u.bits[0]);
+ printk("f10 : %05lx%016lx f11 : %05lx%016lx\n",
+ regs->f10.u.bits[1], regs->f10.u.bits[0],
+ regs->f11.u.bits[1], regs->f11.u.bits[0]);
+
+ printk("r1 : %016lx r2 : %016lx r3 : %016lx\n", regs->r1,
+ regs->r2, regs->r3);
+ printk("r8 : %016lx r9 : %016lx r10 : %016lx\n", regs->r8,
+ regs->r9, regs->r10);
+ printk("r11 : %016lx r12 : %016lx r13 : %016lx\n", regs->r11,
+ regs->r12, regs->r13);
+ printk("r14 : %016lx r15 : %016lx r16 : %016lx\n", regs->r14,
+ regs->r15, regs->r16);
+ printk("r17 : %016lx r18 : %016lx r19 : %016lx\n", regs->r17,
+ regs->r18, regs->r19);
+ printk("r20 : %016lx r21 : %016lx r22 : %016lx\n", regs->r20,
+ regs->r21, regs->r22);
+ printk("r23 : %016lx r24 : %016lx r25 : %016lx\n", regs->r23,
+ regs->r24, regs->r25);
+ printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26,
+ regs->r27, regs->r28);
+ printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29,
+ regs->r30, regs->r31);
+
+}
+
+void panic_vm(struct kvm_vcpu *v, const char *fmt, ...)
+{
+ va_list args;
+ char buf[256];
+
+ struct kvm_pt_regs *regs = vcpu_regs(v);
struct exit_ctl_data *p = &v->arch.exit_data;
-
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ printk(buf);
+ kvm_show_registers(regs);
p->exit_reason = EXIT_REASON_VM_PANIC;
vmm_transition(v);
/*Never to return*/
diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h
index e9b2a4e121c0..b2f12a562bdf 100644
--- a/arch/ia64/kvm/vcpu.h
+++ b/arch/ia64/kvm/vcpu.h
@@ -737,9 +737,12 @@ void kvm_init_vtlb(struct kvm_vcpu *v);
void kvm_init_vhpt(struct kvm_vcpu *v);
void thash_init(struct thash_cb *hcb, u64 sz);
-void panic_vm(struct kvm_vcpu *v);
+void panic_vm(struct kvm_vcpu *v, const char *fmt, ...);
extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2, u64 arg3,
u64 arg4, u64 arg5, u64 arg6, u64 arg7);
+
+extern long vmm_sanity;
+
#endif
#endif /* __VCPU_H__ */
diff --git a/arch/ia64/kvm/vmm.c b/arch/ia64/kvm/vmm.c
index 2275bf4e681a..9eee5c04bacc 100644
--- a/arch/ia64/kvm/vmm.c
+++ b/arch/ia64/kvm/vmm.c
@@ -20,6 +20,7 @@
*/
+#include<linux/kernel.h>
#include<linux/module.h>
#include<asm/fpswa.h>
@@ -31,6 +32,8 @@ MODULE_LICENSE("GPL");
extern char kvm_ia64_ivt;
extern fpswa_interface_t *vmm_fpswa_interface;
+long vmm_sanity = 1;
+
struct kvm_vmm_info vmm_info = {
.module = THIS_MODULE,
.vmm_entry = vmm_entry,
@@ -62,5 +65,31 @@ void vmm_spin_unlock(spinlock_t *lock)
{
_vmm_raw_spin_unlock(lock);
}
+
+static void vcpu_debug_exit(struct kvm_vcpu *vcpu)
+{
+ struct exit_ctl_data *p = &vcpu->arch.exit_data;
+ long psr;
+
+ local_irq_save(psr);
+ p->exit_reason = EXIT_REASON_DEBUG;
+ vmm_transition(vcpu);
+ local_irq_restore(psr);
+}
+
+asmlinkage int printk(const char *fmt, ...)
+{
+ struct kvm_vcpu *vcpu = current_vcpu;
+ va_list args;
+ int r;
+
+ memset(vcpu->arch.log_buf, 0, VMM_LOG_LEN);
+ va_start(args, fmt);
+ r = vsnprintf(vcpu->arch.log_buf, VMM_LOG_LEN, fmt, args);
+ va_end(args);
+ vcpu_debug_exit(vcpu);
+ return r;
+}
+
module_init(kvm_vmm_init)
module_exit(kvm_vmm_exit)
diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S
index c1d7251a1480..3ef1a017a318 100644
--- a/arch/ia64/kvm/vmm_ivt.S
+++ b/arch/ia64/kvm/vmm_ivt.S
@@ -1,5 +1,5 @@
/*
- * /ia64/kvm_ivt.S
+ * arch/ia64/kvm/vmm_ivt.S
*
* Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
@@ -70,32 +70,39 @@
# define PSR_DEFAULT_BITS 0
#endif
-
#define KVM_FAULT(n) \
- kvm_fault_##n:; \
- mov r19=n;; \
- br.sptk.many kvm_fault_##n; \
- ;; \
-
+ kvm_fault_##n:; \
+ mov r19=n;; \
+ br.sptk.many kvm_vmm_panic; \
+ ;; \
#define KVM_REFLECT(n) \
- mov r31=pr; \
- mov r19=n; /* prepare to save predicates */ \
- mov r29=cr.ipsr; \
- ;; \
- tbit.z p6,p7=r29,IA64_PSR_VM_BIT; \
-(p7)br.sptk.many kvm_dispatch_reflection; \
- br.sptk.many kvm_panic; \
-
-
-GLOBAL_ENTRY(kvm_panic)
- br.sptk.many kvm_panic
- ;;
-END(kvm_panic)
-
-
-
-
+ mov r31=pr; \
+ mov r19=n; /* prepare to save predicates */ \
+ mov r29=cr.ipsr; \
+ ;; \
+ tbit.z p6,p7=r29,IA64_PSR_VM_BIT; \
+(p7) br.sptk.many kvm_dispatch_reflection; \
+ br.sptk.many kvm_vmm_panic; \
+
+GLOBAL_ENTRY(kvm_vmm_panic)
+ KVM_SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,1,0
+ mov out0=r15
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+ //(p15) ssm psr.i // restore psr.i
+ addl r14=@gprel(ia64_leave_hypervisor),gp
+ ;;
+ KVM_SAVE_REST
+ mov rp=r14
+ ;;
+ br.call.sptk.many b6=vmm_panic_handler;
+END(kvm_vmm_panic)
.section .text.ivt,"ax"
@@ -105,308 +112,307 @@ kvm_ia64_ivt:
///////////////////////////////////////////////////////////////
// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47)
ENTRY(kvm_vhpt_miss)
- KVM_FAULT(0)
+ KVM_FAULT(0)
END(kvm_vhpt_miss)
-
.org kvm_ia64_ivt+0x400
////////////////////////////////////////////////////////////////
// 0x0400 Entry 1 (size 64 bundles) ITLB (21)
ENTRY(kvm_itlb_miss)
- mov r31 = pr
- mov r29=cr.ipsr;
- ;;
- tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
- (p6) br.sptk kvm_alt_itlb_miss
- mov r19 = 1
- br.sptk kvm_itlb_miss_dispatch
- KVM_FAULT(1);
+ mov r31 = pr
+ mov r29=cr.ipsr;
+ ;;
+ tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
+(p6) br.sptk kvm_alt_itlb_miss
+ mov r19 = 1
+ br.sptk kvm_itlb_miss_dispatch
+ KVM_FAULT(1);
END(kvm_itlb_miss)
.org kvm_ia64_ivt+0x0800
//////////////////////////////////////////////////////////////////
// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48)
ENTRY(kvm_dtlb_miss)
- mov r31 = pr
- mov r29=cr.ipsr;
- ;;
- tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
-(p6)br.sptk kvm_alt_dtlb_miss
- br.sptk kvm_dtlb_miss_dispatch
+ mov r31 = pr
+ mov r29=cr.ipsr;
+ ;;
+ tbit.z p6,p7=r29,IA64_PSR_VM_BIT;
+(p6) br.sptk kvm_alt_dtlb_miss
+ br.sptk kvm_dtlb_miss_dispatch
END(kvm_dtlb_miss)
.org kvm_ia64_ivt+0x0c00
////////////////////////////////////////////////////////////////////
// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19)
ENTRY(kvm_alt_itlb_miss)
- mov r16=cr.ifa // get address that caused the TLB miss
- ;;
- movl r17=PAGE_KERNEL
- mov r24=cr.ipsr
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- ;;
- and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
- ;;
- or r19=r17,r19 // insert PTE control bits into r19
- ;;
- movl r20=IA64_GRANULE_SHIFT<<2
- ;;
- mov cr.itir=r20
- ;;
- itc.i r19 // insert the TLB entry
- mov pr=r31,-1
- rfi
+ mov r16=cr.ifa // get address that caused the TLB miss
+ ;;
+ movl r17=PAGE_KERNEL
+ mov r24=cr.ipsr
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ ;;
+ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
+ ;;
+ or r19=r17,r19 // insert PTE control bits into r19
+ ;;
+ movl r20=IA64_GRANULE_SHIFT<<2
+ ;;
+ mov cr.itir=r20
+ ;;
+ itc.i r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
END(kvm_alt_itlb_miss)
.org kvm_ia64_ivt+0x1000
/////////////////////////////////////////////////////////////////////
// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46)
ENTRY(kvm_alt_dtlb_miss)
- mov r16=cr.ifa // get address that caused the TLB miss
- ;;
- movl r17=PAGE_KERNEL
- movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
- mov r24=cr.ipsr
- ;;
- and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
- ;;
- or r19=r19,r17 // insert PTE control bits into r19
- ;;
- movl r20=IA64_GRANULE_SHIFT<<2
- ;;
- mov cr.itir=r20
- ;;
- itc.d r19 // insert the TLB entry
- mov pr=r31,-1
- rfi
+ mov r16=cr.ifa // get address that caused the TLB miss
+ ;;
+ movl r17=PAGE_KERNEL
+ movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff)
+ mov r24=cr.ipsr
+ ;;
+ and r19=r19,r16 // clear ed, reserved bits, and PTE control bits
+ ;;
+ or r19=r19,r17 // insert PTE control bits into r19
+ ;;
+ movl r20=IA64_GRANULE_SHIFT<<2
+ ;;
+ mov cr.itir=r20
+ ;;
+ itc.d r19 // insert the TLB entry
+ mov pr=r31,-1
+ rfi
END(kvm_alt_dtlb_miss)
.org kvm_ia64_ivt+0x1400
//////////////////////////////////////////////////////////////////////
// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
ENTRY(kvm_nested_dtlb_miss)
- KVM_FAULT(5)
+ KVM_FAULT(5)
END(kvm_nested_dtlb_miss)
.org kvm_ia64_ivt+0x1800
/////////////////////////////////////////////////////////////////////
// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
ENTRY(kvm_ikey_miss)
- KVM_REFLECT(6)
+ KVM_REFLECT(6)
END(kvm_ikey_miss)
.org kvm_ia64_ivt+0x1c00
/////////////////////////////////////////////////////////////////////
// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
ENTRY(kvm_dkey_miss)
- KVM_REFLECT(7)
+ KVM_REFLECT(7)
END(kvm_dkey_miss)
.org kvm_ia64_ivt+0x2000
////////////////////////////////////////////////////////////////////
// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
ENTRY(kvm_dirty_bit)
- KVM_REFLECT(8)
+ KVM_REFLECT(8)
END(kvm_dirty_bit)
.org kvm_ia64_ivt+0x2400
////////////////////////////////////////////////////////////////////
// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
ENTRY(kvm_iaccess_bit)
- KVM_REFLECT(9)
+ KVM_REFLECT(9)
END(kvm_iaccess_bit)
.org kvm_ia64_ivt+0x2800
///////////////////////////////////////////////////////////////////
// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
ENTRY(kvm_daccess_bit)
- KVM_REFLECT(10)
+ KVM_REFLECT(10)
END(kvm_daccess_bit)
.org kvm_ia64_ivt+0x2c00
/////////////////////////////////////////////////////////////////
// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
ENTRY(kvm_break_fault)
- mov r31=pr
- mov r19=11
- mov r29=cr.ipsr
- ;;
- KVM_SAVE_MIN_WITH_COVER_R19
- ;;
- alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in insn group!)
- mov out0=cr.ifa
- mov out2=cr.isr // FIXME: pity to make this slow access twice
- mov out3=cr.iim // FIXME: pity to make this slow access twice
- adds r3=8,r2 // set up second base pointer
- ;;
- ssm psr.ic
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
- //(p15)ssm psr.i // restore psr.i
- addl r14=@gprel(ia64_leave_hypervisor),gp
- ;;
- KVM_SAVE_REST
- mov rp=r14
- ;;
- adds out1=16,sp
- br.call.sptk.many b6=kvm_ia64_handle_break
- ;;
+ mov r31=pr
+ mov r19=11
+ mov r29=cr.ipsr
+ ;;
+ KVM_SAVE_MIN_WITH_COVER_R19
+ ;;
+ alloc r14=ar.pfs,0,0,4,0 //(must be first in insn group!)
+ mov out0=cr.ifa
+ mov out2=cr.isr // FIXME: pity to make this slow access twice
+ mov out3=cr.iim // FIXME: pity to make this slow access twice
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+ //(p15)ssm psr.i // restore psr.i
+ addl r14=@gprel(ia64_leave_hypervisor),gp
+ ;;
+ KVM_SAVE_REST
+ mov rp=r14
+ ;;
+ adds out1=16,sp
+ br.call.sptk.many b6=kvm_ia64_handle_break
+ ;;
END(kvm_break_fault)
.org kvm_ia64_ivt+0x3000
/////////////////////////////////////////////////////////////////
// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4)
ENTRY(kvm_interrupt)
- mov r31=pr // prepare to save predicates
- mov r19=12
- mov r29=cr.ipsr
- ;;
- tbit.z p6,p7=r29,IA64_PSR_VM_BIT
- tbit.z p0,p15=r29,IA64_PSR_I_BIT
- ;;
-(p7) br.sptk kvm_dispatch_interrupt
- ;;
- mov r27=ar.rsc /* M */
- mov r20=r1 /* A */
- mov r25=ar.unat /* M */
- mov r26=ar.pfs /* I */
- mov r28=cr.iip /* M */
- cover /* B (or nothing) */
- ;;
- mov r1=sp
- ;;
- invala /* M */
- mov r30=cr.ifs
- ;;
- addl r1=-VMM_PT_REGS_SIZE,r1
- ;;
- adds r17=2*L1_CACHE_BYTES,r1 /* really: biggest cache-line size */
- adds r16=PT(CR_IPSR),r1
- ;;
- lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES
- st8 [r16]=r29 /* save cr.ipsr */
- ;;
- lfetch.fault.excl.nt1 [r17]
- mov r29=b0
- ;;
- adds r16=PT(R8),r1 /* initialize first base pointer */
- adds r17=PT(R9),r1 /* initialize second base pointer */
- mov r18=r0 /* make sure r18 isn't NaT */
- ;;
+ mov r31=pr // prepare to save predicates
+ mov r19=12
+ mov r29=cr.ipsr
+ ;;
+ tbit.z p6,p7=r29,IA64_PSR_VM_BIT
+ tbit.z p0,p15=r29,IA64_PSR_I_BIT
+ ;;
+(p7) br.sptk kvm_dispatch_interrupt
+ ;;
+ mov r27=ar.rsc /* M */
+ mov r20=r1 /* A */
+ mov r25=ar.unat /* M */
+ mov r26=ar.pfs /* I */
+ mov r28=cr.iip /* M */
+ cover /* B (or nothing) */
+ ;;
+ mov r1=sp
+ ;;
+ invala /* M */
+ mov r30=cr.ifs
+ ;;
+ addl r1=-VMM_PT_REGS_SIZE,r1
+ ;;
+ adds r17=2*L1_CACHE_BYTES,r1 /* really: biggest cache-line size */
+ adds r16=PT(CR_IPSR),r1
+ ;;
+ lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES
+ st8 [r16]=r29 /* save cr.ipsr */
+ ;;
+ lfetch.fault.excl.nt1 [r17]
+ mov r29=b0
+ ;;
+ adds r16=PT(R8),r1 /* initialize first base pointer */
+ adds r17=PT(R9),r1 /* initialize second base pointer */
+ mov r18=r0 /* make sure r18 isn't NaT */
+ ;;
.mem.offset 0,0; st8.spill [r16]=r8,16
.mem.offset 8,0; st8.spill [r17]=r9,16
;;
.mem.offset 0,0; st8.spill [r16]=r10,24
.mem.offset 8,0; st8.spill [r17]=r11,24
;;
- st8 [r16]=r28,16 /* save cr.iip */
- st8 [r17]=r30,16 /* save cr.ifs */
- mov r8=ar.fpsr /* M */
- mov r9=ar.csd
- mov r10=ar.ssd
- movl r11=FPSR_DEFAULT /* L-unit */
- ;;
- st8 [r16]=r25,16 /* save ar.unat */
- st8 [r17]=r26,16 /* save ar.pfs */
- shl r18=r18,16 /* compute ar.rsc to be used for "loadrs" */
- ;;
- st8 [r16]=r27,16 /* save ar.rsc */
- adds r17=16,r17 /* skip over ar_rnat field */
- ;;
- st8 [r17]=r31,16 /* save predicates */
- adds r16=16,r16 /* skip over ar_bspstore field */
- ;;
- st8 [r16]=r29,16 /* save b0 */
- st8 [r17]=r18,16 /* save ar.rsc value for "loadrs" */
- ;;
+ st8 [r16]=r28,16 /* save cr.iip */
+ st8 [r17]=r30,16 /* save cr.ifs */
+ mov r8=ar.fpsr /* M */
+ mov r9=ar.csd
+ mov r10=ar.ssd
+ movl r11=FPSR_DEFAULT /* L-unit */
+ ;;
+ st8 [r16]=r25,16 /* save ar.unat */
+ st8 [r17]=r26,16 /* save ar.pfs */
+ shl r18=r18,16 /* compute ar.rsc to be used for "loadrs" */
+ ;;
+ st8 [r16]=r27,16 /* save ar.rsc */
+ adds r17=16,r17 /* skip over ar_rnat field */
+ ;;
+ st8 [r17]=r31,16 /* save predicates */
+ adds r16=16,r16 /* skip over ar_bspstore field */
+ ;;
+ st8 [r16]=r29,16 /* save b0 */
+ st8 [r17]=r18,16 /* save ar.rsc value for "loadrs" */
+ ;;
.mem.offset 0,0; st8.spill [r16]=r20,16 /* save original r1 */
.mem.offset 8,0; st8.spill [r17]=r12,16
- adds r12=-16,r1
- /* switch to kernel memory stack (with 16 bytes of scratch) */
- ;;
+ adds r12=-16,r1
+ /* switch to kernel memory stack (with 16 bytes of scratch) */
+ ;;
.mem.offset 0,0; st8.spill [r16]=r13,16
.mem.offset 8,0; st8.spill [r17]=r8,16 /* save ar.fpsr */
- ;;
+ ;;
.mem.offset 0,0; st8.spill [r16]=r15,16
.mem.offset 8,0; st8.spill [r17]=r14,16
- dep r14=-1,r0,60,4
- ;;
+ dep r14=-1,r0,60,4
+ ;;
.mem.offset 0,0; st8.spill [r16]=r2,16
.mem.offset 8,0; st8.spill [r17]=r3,16
- adds r2=VMM_PT_REGS_R16_OFFSET,r1
- adds r14 = VMM_VCPU_GP_OFFSET,r13
- ;;
- mov r8=ar.ccv
- ld8 r14 = [r14]
- ;;
- mov r1=r14 /* establish kernel global pointer */
- ;; \
- bsw.1
- ;;
- alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
- mov out0=r13
- ;;
- ssm psr.ic
- ;;
- srlz.i
- ;;
- //(p15) ssm psr.i
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- srlz.i // ensure everybody knows psr.ic is back on
- ;;
+ adds r2=VMM_PT_REGS_R16_OFFSET,r1
+ adds r14 = VMM_VCPU_GP_OFFSET,r13
+ ;;
+ mov r8=ar.ccv
+ ld8 r14 = [r14]
+ ;;
+ mov r1=r14 /* establish kernel global pointer */
+ ;; \
+ bsw.1
+ ;;
+ alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
+ mov out0=r13
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i
+ ;;
+ //(p15) ssm psr.i
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ srlz.i // ensure everybody knows psr.ic is back on
+ ;;
.mem.offset 0,0; st8.spill [r2]=r16,16
.mem.offset 8,0; st8.spill [r3]=r17,16
- ;;
+ ;;
.mem.offset 0,0; st8.spill [r2]=r18,16
.mem.offset 8,0; st8.spill [r3]=r19,16
- ;;
+ ;;
.mem.offset 0,0; st8.spill [r2]=r20,16
.mem.offset 8,0; st8.spill [r3]=r21,16
- mov r18=b6
- ;;
+ mov r18=b6
+ ;;
.mem.offset 0,0; st8.spill [r2]=r22,16
.mem.offset 8,0; st8.spill [r3]=r23,16
- mov r19=b7
- ;;
+ mov r19=b7
+ ;;
.mem.offset 0,0; st8.spill [r2]=r24,16
.mem.offset 8,0; st8.spill [r3]=r25,16
- ;;
+ ;;
.mem.offset 0,0; st8.spill [r2]=r26,16
.mem.offset 8,0; st8.spill [r3]=r27,16
- ;;
+ ;;
.mem.offset 0,0; st8.spill [r2]=r28,16
.mem.offset 8,0; st8.spill [r3]=r29,16
- ;;
+ ;;
.mem.offset 0,0; st8.spill [r2]=r30,16
.mem.offset 8,0; st8.spill [r3]=r31,32
- ;;
- mov ar.fpsr=r11 /* M-unit */
- st8 [r2]=r8,8 /* ar.ccv */
- adds r24=PT(B6)-PT(F7),r3
- ;;
- stf.spill [r2]=f6,32
- stf.spill [r3]=f7,32
- ;;
- stf.spill [r2]=f8,32
- stf.spill [r3]=f9,32
- ;;
- stf.spill [r2]=f10
- stf.spill [r3]=f11
- adds r25=PT(B7)-PT(F11),r3
- ;;
- st8 [r24]=r18,16 /* b6 */
- st8 [r25]=r19,16 /* b7 */
- ;;
- st8 [r24]=r9 /* ar.csd */
- st8 [r25]=r10 /* ar.ssd */
- ;;
- srlz.d // make sure we see the effect of cr.ivr
- addl r14=@gprel(ia64_leave_nested),gp
- ;;
- mov rp=r14
- br.call.sptk.many b6=kvm_ia64_handle_irq
- ;;
+ ;;
+ mov ar.fpsr=r11 /* M-unit */
+ st8 [r2]=r8,8 /* ar.ccv */
+ adds r24=PT(B6)-PT(F7),r3
+ ;;
+ stf.spill [r2]=f6,32
+ stf.spill [r3]=f7,32
+ ;;
+ stf.spill [r2]=f8,32
+ stf.spill [r3]=f9,32
+ ;;
+ stf.spill [r2]=f10
+ stf.spill [r3]=f11
+ adds r25=PT(B7)-PT(F11),r3
+ ;;
+ st8 [r24]=r18,16 /* b6 */
+ st8 [r25]=r19,16 /* b7 */
+ ;;
+ st8 [r24]=r9 /* ar.csd */
+ st8 [r25]=r10 /* ar.ssd */
+ ;;
+ srlz.d // make sure we see the effect of cr.ivr
+ addl r14=@gprel(ia64_leave_nested),gp
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=kvm_ia64_handle_irq
+ ;;
END(kvm_interrupt)
.global kvm_dispatch_vexirq
@@ -414,387 +420,385 @@ END(kvm_interrupt)
//////////////////////////////////////////////////////////////////////
// 0x3400 Entry 13 (size 64 bundles) Reserved
ENTRY(kvm_virtual_exirq)
- mov r31=pr
- mov r19=13
- mov r30 =r0
- ;;
+ mov r31=pr
+ mov r19=13
+ mov r30 =r0
+ ;;
kvm_dispatch_vexirq:
- cmp.eq p6,p0 = 1,r30
- ;;
-(p6)add r29 = VMM_VCPU_SAVED_GP_OFFSET,r21
- ;;
-(p6)ld8 r1 = [r29]
- ;;
- KVM_SAVE_MIN_WITH_COVER_R19
- alloc r14=ar.pfs,0,0,1,0
- mov out0=r13
-
- ssm psr.ic
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
- //(p15) ssm psr.i // restore psr.i
- adds r3=8,r2 // set up second base pointer
- ;;
- KVM_SAVE_REST
- addl r14=@gprel(ia64_leave_hypervisor),gp
- ;;
- mov rp=r14
- br.call.sptk.many b6=kvm_vexirq
+ cmp.eq p6,p0 = 1,r30
+ ;;
+(p6) add r29 = VMM_VCPU_SAVED_GP_OFFSET,r21
+ ;;
+(p6) ld8 r1 = [r29]
+ ;;
+ KVM_SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,1,0
+ mov out0=r13
+
+ ssm psr.ic
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+ //(p15) ssm psr.i // restore psr.i
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ KVM_SAVE_REST
+ addl r14=@gprel(ia64_leave_hypervisor),gp
+ ;;
+ mov rp=r14
+ br.call.sptk.many b6=kvm_vexirq
END(kvm_virtual_exirq)
.org kvm_ia64_ivt+0x3800
/////////////////////////////////////////////////////////////////////
// 0x3800 Entry 14 (size 64 bundles) Reserved
- KVM_FAULT(14)
- // this code segment is from 2.6.16.13
-
+ KVM_FAULT(14)
+ // this code segment is from 2.6.16.13
.org kvm_ia64_ivt+0x3c00
///////////////////////////////////////////////////////////////////////
// 0x3c00 Entry 15 (size 64 bundles) Reserved
- KVM_FAULT(15)
-
+ KVM_FAULT(15)
.org kvm_ia64_ivt+0x4000
///////////////////////////////////////////////////////////////////////
// 0x4000 Entry 16 (size 64 bundles) Reserved
- KVM_FAULT(16)
+ KVM_FAULT(16)
.org kvm_ia64_ivt+0x4400
//////////////////////////////////////////////////////////////////////
// 0x4400 Entry 17 (size 64 bundles) Reserved
- KVM_FAULT(17)
+ KVM_FAULT(17)
.org kvm_ia64_ivt+0x4800
//////////////////////////////////////////////////////////////////////
// 0x4800 Entry 18 (size 64 bundles) Reserved
- KVM_FAULT(18)
+ KVM_FAULT(18)
.org kvm_ia64_ivt+0x4c00
//////////////////////////////////////////////////////////////////////
// 0x4c00 Entry 19 (size 64 bundles) Reserved
- KVM_FAULT(19)
+ KVM_FAULT(19)
.org kvm_ia64_ivt+0x5000
//////////////////////////////////////////////////////////////////////
// 0x5000 Entry 20 (size 16 bundles) Page Not Present
ENTRY(kvm_page_not_present)
- KVM_REFLECT(20)
+ KVM_REFLECT(20)
END(kvm_page_not_present)
.org kvm_ia64_ivt+0x5100
///////////////////////////////////////////////////////////////////////
// 0x5100 Entry 21 (size 16 bundles) Key Permission vector
ENTRY(kvm_key_permission)
- KVM_REFLECT(21)
+ KVM_REFLECT(21)
END(kvm_key_permission)
.org kvm_ia64_ivt+0x5200
//////////////////////////////////////////////////////////////////////
// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
ENTRY(kvm_iaccess_rights)
- KVM_REFLECT(22)
+ KVM_REFLECT(22)
END(kvm_iaccess_rights)
.org kvm_ia64_ivt+0x5300
//////////////////////////////////////////////////////////////////////
// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
ENTRY(kvm_daccess_rights)
- KVM_REFLECT(23)
+ KVM_REFLECT(23)
END(kvm_daccess_rights)
.org kvm_ia64_ivt+0x5400
/////////////////////////////////////////////////////////////////////
// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39)
ENTRY(kvm_general_exception)
- KVM_REFLECT(24)
- KVM_FAULT(24)
+ KVM_REFLECT(24)
+ KVM_FAULT(24)
END(kvm_general_exception)
.org kvm_ia64_ivt+0x5500
//////////////////////////////////////////////////////////////////////
// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
ENTRY(kvm_disabled_fp_reg)
- KVM_REFLECT(25)
+ KVM_REFLECT(25)
END(kvm_disabled_fp_reg)
.org kvm_ia64_ivt+0x5600
////////////////////////////////////////////////////////////////////
// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
ENTRY(kvm_nat_consumption)
- KVM_REFLECT(26)
+ KVM_REFLECT(26)
END(kvm_nat_consumption)
.org kvm_ia64_ivt+0x5700
/////////////////////////////////////////////////////////////////////
// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
ENTRY(kvm_speculation_vector)
- KVM_REFLECT(27)
+ KVM_REFLECT(27)
END(kvm_speculation_vector)
.org kvm_ia64_ivt+0x5800
/////////////////////////////////////////////////////////////////////
// 0x5800 Entry 28 (size 16 bundles) Reserved
- KVM_FAULT(28)
+ KVM_FAULT(28)
.org kvm_ia64_ivt+0x5900
///////////////////////////////////////////////////////////////////
// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
ENTRY(kvm_debug_vector)
- KVM_FAULT(29)
+ KVM_FAULT(29)
END(kvm_debug_vector)
.org kvm_ia64_ivt+0x5a00
///////////////////////////////////////////////////////////////
// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
ENTRY(kvm_unaligned_access)
- KVM_REFLECT(30)
+ KVM_REFLECT(30)
END(kvm_unaligned_access)
.org kvm_ia64_ivt+0x5b00
//////////////////////////////////////////////////////////////////////
// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
ENTRY(kvm_unsupported_data_reference)
- KVM_REFLECT(31)
+ KVM_REFLECT(31)
END(kvm_unsupported_data_reference)
.org kvm_ia64_ivt+0x5c00
////////////////////////////////////////////////////////////////////
// 0x5c00 Entry 32 (size 16 bundles) Floating Point FAULT (65)
ENTRY(kvm_floating_point_fault)
- KVM_REFLECT(32)
+ KVM_REFLECT(32)
END(kvm_floating_point_fault)
.org kvm_ia64_ivt+0x5d00
/////////////////////////////////////////////////////////////////////
// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
ENTRY(kvm_floating_point_trap)
- KVM_REFLECT(33)
+ KVM_REFLECT(33)
END(kvm_floating_point_trap)
.org kvm_ia64_ivt+0x5e00
//////////////////////////////////////////////////////////////////////
// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
ENTRY(kvm_lower_privilege_trap)
- KVM_REFLECT(34)
+ KVM_REFLECT(34)
END(kvm_lower_privilege_trap)
.org kvm_ia64_ivt+0x5f00
//////////////////////////////////////////////////////////////////////
// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
ENTRY(kvm_taken_branch_trap)
- KVM_REFLECT(35)
+ KVM_REFLECT(35)
END(kvm_taken_branch_trap)
.org kvm_ia64_ivt+0x6000
////////////////////////////////////////////////////////////////////
// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
ENTRY(kvm_single_step_trap)
- KVM_REFLECT(36)
+ KVM_REFLECT(36)
END(kvm_single_step_trap)
.global kvm_virtualization_fault_back
.org kvm_ia64_ivt+0x6100
/////////////////////////////////////////////////////////////////////
// 0x6100 Entry 37 (size 16 bundles) Virtualization Fault
ENTRY(kvm_virtualization_fault)
- mov r31=pr
- adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
- ;;
- st8 [r16] = r1
- adds r17 = VMM_VCPU_GP_OFFSET, r21
- ;;
- ld8 r1 = [r17]
- cmp.eq p6,p0=EVENT_MOV_FROM_AR,r24
- cmp.eq p7,p0=EVENT_MOV_FROM_RR,r24
- cmp.eq p8,p0=EVENT_MOV_TO_RR,r24
- cmp.eq p9,p0=EVENT_RSM,r24
- cmp.eq p10,p0=EVENT_SSM,r24
- cmp.eq p11,p0=EVENT_MOV_TO_PSR,r24
- cmp.eq p12,p0=EVENT_THASH,r24
- (p6) br.dptk.many kvm_asm_mov_from_ar
- (p7) br.dptk.many kvm_asm_mov_from_rr
- (p8) br.dptk.many kvm_asm_mov_to_rr
- (p9) br.dptk.many kvm_asm_rsm
- (p10) br.dptk.many kvm_asm_ssm
- (p11) br.dptk.many kvm_asm_mov_to_psr
- (p12) br.dptk.many kvm_asm_thash
- ;;
+ mov r31=pr
+ adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
+ ;;
+ st8 [r16] = r1
+ adds r17 = VMM_VCPU_GP_OFFSET, r21
+ ;;
+ ld8 r1 = [r17]
+ cmp.eq p6,p0=EVENT_MOV_FROM_AR,r24
+ cmp.eq p7,p0=EVENT_MOV_FROM_RR,r24
+ cmp.eq p8,p0=EVENT_MOV_TO_RR,r24
+ cmp.eq p9,p0=EVENT_RSM,r24
+ cmp.eq p10,p0=EVENT_SSM,r24
+ cmp.eq p11,p0=EVENT_MOV_TO_PSR,r24
+ cmp.eq p12,p0=EVENT_THASH,r24
+(p6) br.dptk.many kvm_asm_mov_from_ar
+(p7) br.dptk.many kvm_asm_mov_from_rr
+(p8) br.dptk.many kvm_asm_mov_to_rr
+(p9) br.dptk.many kvm_asm_rsm
+(p10) br.dptk.many kvm_asm_ssm
+(p11) br.dptk.many kvm_asm_mov_to_psr
+(p12) br.dptk.many kvm_asm_thash
+ ;;
kvm_virtualization_fault_back:
- adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
- ;;
- ld8 r1 = [r16]
- ;;
- mov r19=37
- adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
- adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
- ;;
- st8 [r16] = r24
- st8 [r17] = r25
- ;;
- cmp.ne p6,p0=EVENT_RFI, r24
- (p6) br.sptk kvm_dispatch_virtualization_fault
- ;;
- adds r18=VMM_VPD_BASE_OFFSET,r21
- ;;
- ld8 r18=[r18]
- ;;
- adds r18=VMM_VPD_VIFS_OFFSET,r18
- ;;
- ld8 r18=[r18]
- ;;
- tbit.z p6,p0=r18,63
- (p6) br.sptk kvm_dispatch_virtualization_fault
- ;;
- //if vifs.v=1 desert current register frame
- alloc r18=ar.pfs,0,0,0,0
- br.sptk kvm_dispatch_virtualization_fault
+ adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21
+ ;;
+ ld8 r1 = [r16]
+ ;;
+ mov r19=37
+ adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
+ adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
+ ;;
+ st8 [r16] = r24
+ st8 [r17] = r25
+ ;;
+ cmp.ne p6,p0=EVENT_RFI, r24
+(p6) br.sptk kvm_dispatch_virtualization_fault
+ ;;
+ adds r18=VMM_VPD_BASE_OFFSET,r21
+ ;;
+ ld8 r18=[r18]
+ ;;
+ adds r18=VMM_VPD_VIFS_OFFSET,r18
+ ;;
+ ld8 r18=[r18]
+ ;;
+ tbit.z p6,p0=r18,63
+(p6) br.sptk kvm_dispatch_virtualization_fault
+ ;;
+//if vifs.v=1 desert current register frame
+ alloc r18=ar.pfs,0,0,0,0
+ br.sptk kvm_dispatch_virtualization_fault
END(kvm_virtualization_fault)
.org kvm_ia64_ivt+0x6200
//////////////////////////////////////////////////////////////
// 0x6200 Entry 38 (size 16 bundles) Reserved
- KVM_FAULT(38)
+ KVM_FAULT(38)
.org kvm_ia64_ivt+0x6300
/////////////////////////////////////////////////////////////////
// 0x6300 Entry 39 (size 16 bundles) Reserved
- KVM_FAULT(39)
+ KVM_FAULT(39)
.org kvm_ia64_ivt+0x6400
/////////////////////////////////////////////////////////////////
// 0x6400 Entry 40 (size 16 bundles) Reserved
- KVM_FAULT(40)
+ KVM_FAULT(40)
.org kvm_ia64_ivt+0x6500
//////////////////////////////////////////////////////////////////
// 0x6500 Entry 41 (size 16 bundles) Reserved
- KVM_FAULT(41)
+ KVM_FAULT(41)
.org kvm_ia64_ivt+0x6600
//////////////////////////////////////////////////////////////////
// 0x6600 Entry 42 (size 16 bundles) Reserved
- KVM_FAULT(42)
+ KVM_FAULT(42)
.org kvm_ia64_ivt+0x6700
//////////////////////////////////////////////////////////////////
// 0x6700 Entry 43 (size 16 bundles) Reserved
- KVM_FAULT(43)
+ KVM_FAULT(43)
.org kvm_ia64_ivt+0x6800
//////////////////////////////////////////////////////////////////
// 0x6800 Entry 44 (size 16 bundles) Reserved
- KVM_FAULT(44)
+ KVM_FAULT(44)
.org kvm_ia64_ivt+0x6900
///////////////////////////////////////////////////////////////////
// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception
//(17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
ENTRY(kvm_ia32_exception)
- KVM_FAULT(45)
+ KVM_FAULT(45)
END(kvm_ia32_exception)
.org kvm_ia64_ivt+0x6a00
////////////////////////////////////////////////////////////////////
// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
ENTRY(kvm_ia32_intercept)
- KVM_FAULT(47)
+ KVM_FAULT(47)
END(kvm_ia32_intercept)
.org kvm_ia64_ivt+0x6c00
/////////////////////////////////////////////////////////////////////
// 0x6c00 Entry 48 (size 16 bundles) Reserved
- KVM_FAULT(48)
+ KVM_FAULT(48)
.org kvm_ia64_ivt+0x6d00
//////////////////////////////////////////////////////////////////////
// 0x6d00 Entry 49 (size 16 bundles) Reserved
- KVM_FAULT(49)
+ KVM_FAULT(49)
.org kvm_ia64_ivt+0x6e00
//////////////////////////////////////////////////////////////////////
// 0x6e00 Entry 50 (size 16 bundles) Reserved
- KVM_FAULT(50)
+ KVM_FAULT(50)
.org kvm_ia64_ivt+0x6f00
/////////////////////////////////////////////////////////////////////
// 0x6f00 Entry 51 (size 16 bundles) Reserved
- KVM_FAULT(52)
+ KVM_FAULT(52)
.org kvm_ia64_ivt+0x7100
////////////////////////////////////////////////////////////////////
// 0x7100 Entry 53 (size 16 bundles) Reserved
- KVM_FAULT(53)
+ KVM_FAULT(53)
.org kvm_ia64_ivt+0x7200
/////////////////////////////////////////////////////////////////////
// 0x7200 Entry 54 (size 16 bundles) Reserved
- KVM_FAULT(54)
+ KVM_FAULT(54)
.org kvm_ia64_ivt+0x7300
////////////////////////////////////////////////////////////////////
// 0x7300 Entry 55 (size 16 bundles) Reserved
- KVM_FAULT(55)
+ KVM_FAULT(55)
.org kvm_ia64_ivt+0x7400
////////////////////////////////////////////////////////////////////
// 0x7400 Entry 56 (size 16 bundles) Reserved
- KVM_FAULT(56)
+ KVM_FAULT(56)
.org kvm_ia64_ivt+0x7500
/////////////////////////////////////////////////////////////////////
// 0x7500 Entry 57 (size 16 bundles) Reserved
- KVM_FAULT(57)
+ KVM_FAULT(57)
.org kvm_ia64_ivt+0x7600
/////////////////////////////////////////////////////////////////////
// 0x7600 Entry 58 (size 16 bundles) Reserved
- KVM_FAULT(58)
+ KVM_FAULT(58)
.org kvm_ia64_ivt+0x7700
////////////////////////////////////////////////////////////////////
// 0x7700 Entry 59 (size 16 bundles) Reserved
- KVM_FAULT(59)
+ KVM_FAULT(59)
.org kvm_ia64_ivt+0x7800
////////////////////////////////////////////////////////////////////
// 0x7800 Entry 60 (size 16 bundles) Reserved
- KVM_FAULT(60)
+ KVM_FAULT(60)
.org kvm_ia64_ivt+0x7900
/////////////////////////////////////////////////////////////////////
// 0x7900 Entry 61 (size 16 bundles) Reserved
- KVM_FAULT(61)
+ KVM_FAULT(61)
.org kvm_ia64_ivt+0x7a00
/////////////////////////////////////////////////////////////////////
// 0x7a00 Entry 62 (size 16 bundles) Reserved
- KVM_FAULT(62)
+ KVM_FAULT(62)
.org kvm_ia64_ivt+0x7b00
/////////////////////////////////////////////////////////////////////
// 0x7b00 Entry 63 (size 16 bundles) Reserved
- KVM_FAULT(63)
+ KVM_FAULT(63)
.org kvm_ia64_ivt+0x7c00
////////////////////////////////////////////////////////////////////
// 0x7c00 Entry 64 (size 16 bundles) Reserved
- KVM_FAULT(64)
+ KVM_FAULT(64)
.org kvm_ia64_ivt+0x7d00
/////////////////////////////////////////////////////////////////////
// 0x7d00 Entry 65 (size 16 bundles) Reserved
- KVM_FAULT(65)
+ KVM_FAULT(65)
.org kvm_ia64_ivt+0x7e00
/////////////////////////////////////////////////////////////////////
// 0x7e00 Entry 66 (size 16 bundles) Reserved
- KVM_FAULT(66)
+ KVM_FAULT(66)
.org kvm_ia64_ivt+0x7f00
////////////////////////////////////////////////////////////////////
// 0x7f00 Entry 67 (size 16 bundles) Reserved
- KVM_FAULT(67)
+ KVM_FAULT(67)
.org kvm_ia64_ivt+0x8000
// There is no particular reason for this code to be here, other than that
@@ -804,132 +808,128 @@ END(kvm_ia32_intercept)
ENTRY(kvm_dtlb_miss_dispatch)
- mov r19 = 2
- KVM_SAVE_MIN_WITH_COVER_R19
- alloc r14=ar.pfs,0,0,3,0
- mov out0=cr.ifa
- mov out1=r15
- adds r3=8,r2 // set up second base pointer
- ;;
- ssm psr.ic
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
- //(p15) ssm psr.i // restore psr.i
- addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
- ;;
- KVM_SAVE_REST
- KVM_SAVE_EXTRA
- mov rp=r14
- ;;
- adds out2=16,r12
- br.call.sptk.many b6=kvm_page_fault
+ mov r19 = 2
+ KVM_SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,3,0
+ mov out0=cr.ifa
+ mov out1=r15
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+ //(p15) ssm psr.i // restore psr.i
+ addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
+ ;;
+ KVM_SAVE_REST
+ KVM_SAVE_EXTRA
+ mov rp=r14
+ ;;
+ adds out2=16,r12
+ br.call.sptk.many b6=kvm_page_fault
END(kvm_dtlb_miss_dispatch)
ENTRY(kvm_itlb_miss_dispatch)
- KVM_SAVE_MIN_WITH_COVER_R19
- alloc r14=ar.pfs,0,0,3,0
- mov out0=cr.ifa
- mov out1=r15
- adds r3=8,r2 // set up second base pointer
- ;;
- ssm psr.ic
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
- //(p15) ssm psr.i // restore psr.i
- addl r14=@gprel(ia64_leave_hypervisor),gp
- ;;
- KVM_SAVE_REST
- mov rp=r14
- ;;
- adds out2=16,r12
- br.call.sptk.many b6=kvm_page_fault
+ KVM_SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,3,0
+ mov out0=cr.ifa
+ mov out1=r15
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+ //(p15) ssm psr.i // restore psr.i
+ addl r14=@gprel(ia64_leave_hypervisor),gp
+ ;;
+ KVM_SAVE_REST
+ mov rp=r14
+ ;;
+ adds out2=16,r12
+ br.call.sptk.many b6=kvm_page_fault
END(kvm_itlb_miss_dispatch)
ENTRY(kvm_dispatch_reflection)
- /*
- * Input:
- * psr.ic: off
- * r19: intr type (offset into ivt, see ia64_int.h)
- * r31: contains saved predicates (pr)
- */
- KVM_SAVE_MIN_WITH_COVER_R19
- alloc r14=ar.pfs,0,0,5,0
- mov out0=cr.ifa
- mov out1=cr.isr
- mov out2=cr.iim
- mov out3=r15
- adds r3=8,r2 // set up second base pointer
- ;;
- ssm psr.ic
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
- //(p15) ssm psr.i // restore psr.i
- addl r14=@gprel(ia64_leave_hypervisor),gp
- ;;
- KVM_SAVE_REST
- mov rp=r14
- ;;
- adds out4=16,r12
- br.call.sptk.many b6=reflect_interruption
+/*
+ * Input:
+ * psr.ic: off
+ * r19: intr type (offset into ivt, see ia64_int.h)
+ * r31: contains saved predicates (pr)
+ */
+ KVM_SAVE_MIN_WITH_COVER_R19
+ alloc r14=ar.pfs,0,0,5,0
+ mov out0=cr.ifa
+ mov out1=cr.isr
+ mov out2=cr.iim
+ mov out3=r15
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+ //(p15) ssm psr.i // restore psr.i
+ addl r14=@gprel(ia64_leave_hypervisor),gp
+ ;;
+ KVM_SAVE_REST
+ mov rp=r14
+ ;;
+ adds out4=16,r12
+ br.call.sptk.many b6=reflect_interruption
END(kvm_dispatch_reflection)
ENTRY(kvm_dispatch_virtualization_fault)
- adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
- adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
- ;;
- st8 [r16] = r24
- st8 [r17] = r25
- ;;
- KVM_SAVE_MIN_WITH_COVER_R19
- ;;
- alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!)
- mov out0=r13 //vcpu
- adds r3=8,r2 // set up second base pointer
- ;;
- ssm psr.ic
- ;;
- srlz.i // guarantee that interruption collection is on
- ;;
- //(p15) ssm psr.i // restore psr.i
- addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
- ;;
- KVM_SAVE_REST
- KVM_SAVE_EXTRA
- mov rp=r14
- ;;
- adds out1=16,sp //regs
- br.call.sptk.many b6=kvm_emulate
+ adds r16 = VMM_VCPU_CAUSE_OFFSET,r21
+ adds r17 = VMM_VCPU_OPCODE_OFFSET,r21
+ ;;
+ st8 [r16] = r24
+ st8 [r17] = r25
+ ;;
+ KVM_SAVE_MIN_WITH_COVER_R19
+ ;;
+ alloc r14=ar.pfs,0,0,2,0 // (must be first in insn group!)
+ mov out0=r13 //vcpu
+ adds r3=8,r2 // set up second base pointer
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i // guarantee that interruption collection is on
+ ;;
+ //(p15) ssm psr.i // restore psr.i
+ addl r14=@gprel(ia64_leave_hypervisor_prepare),gp
+ ;;
+ KVM_SAVE_REST
+ KVM_SAVE_EXTRA
+ mov rp=r14
+ ;;
+ adds out1=16,sp //regs
+ br.call.sptk.many b6=kvm_emulate
END(kvm_dispatch_virtualization_fault)
ENTRY(kvm_dispatch_interrupt)
- KVM_SAVE_MIN_WITH_COVER_R19 // uses r31; defines r2 and r3
- ;;
- alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
- //mov out0=cr.ivr // pass cr.ivr as first arg
- adds r3=8,r2 // set up second base pointer for SAVE_REST
- ;;
- ssm psr.ic
- ;;
- srlz.i
- ;;
- //(p15) ssm psr.i
- addl r14=@gprel(ia64_leave_hypervisor),gp
- ;;
- KVM_SAVE_REST
- mov rp=r14
- ;;
- mov out0=r13 // pass pointer to pt_regs as second arg
- br.call.sptk.many b6=kvm_ia64_handle_irq
+ KVM_SAVE_MIN_WITH_COVER_R19 // uses r31; defines r2 and r3
+ ;;
+ alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group
+ adds r3=8,r2 // set up second base pointer for SAVE_REST
+ ;;
+ ssm psr.ic
+ ;;
+ srlz.i
+ ;;
+ //(p15) ssm psr.i
+ addl r14=@gprel(ia64_leave_hypervisor),gp
+ ;;
+ KVM_SAVE_REST
+ mov rp=r14
+ ;;
+ mov out0=r13 // pass pointer to pt_regs as second arg
+ br.call.sptk.many b6=kvm_ia64_handle_irq
END(kvm_dispatch_interrupt)
-
-
-
GLOBAL_ENTRY(ia64_leave_nested)
rsm psr.i
;;
@@ -1008,7 +1008,7 @@ GLOBAL_ENTRY(ia64_leave_nested)
;;
ldf.fill f11=[r2]
// mov r18=r13
-// mov r21=r13
+// mov r21=r13
adds r16=PT(CR_IPSR)+16,r12
adds r17=PT(CR_IIP)+16,r12
;;
@@ -1058,138 +1058,135 @@ GLOBAL_ENTRY(ia64_leave_nested)
rfi
END(ia64_leave_nested)
-
-
GLOBAL_ENTRY(ia64_leave_hypervisor_prepare)
- /*
- * work.need_resched etc. mustn't get changed
- *by this CPU before it returns to
- ;;
- * user- or fsys-mode, hence we disable interrupts early on:
- */
- adds r2 = PT(R4)+16,r12
- adds r3 = PT(R5)+16,r12
- adds r8 = PT(EML_UNAT)+16,r12
- ;;
- ld8 r8 = [r8]
- ;;
- mov ar.unat=r8
- ;;
- ld8.fill r4=[r2],16 //load r4
- ld8.fill r5=[r3],16 //load r5
- ;;
- ld8.fill r6=[r2] //load r6
- ld8.fill r7=[r3] //load r7
- ;;
+/*
+ * work.need_resched etc. mustn't get changed
+ *by this CPU before it returns to
+ * user- or fsys-mode, hence we disable interrupts early on:
+ */
+ adds r2 = PT(R4)+16,r12
+ adds r3 = PT(R5)+16,r12
+ adds r8 = PT(EML_UNAT)+16,r12
+ ;;
+ ld8 r8 = [r8]
+ ;;
+ mov ar.unat=r8
+ ;;
+ ld8.fill r4=[r2],16 //load r4
+ ld8.fill r5=[r3],16 //load r5
+ ;;
+ ld8.fill r6=[r2] //load r6
+ ld8.fill r7=[r3] //load r7
+ ;;
END(ia64_leave_hypervisor_prepare)
//fall through
GLOBAL_ENTRY(ia64_leave_hypervisor)
- rsm psr.i
- ;;
- br.call.sptk.many b0=leave_hypervisor_tail
- ;;
- adds r20=PT(PR)+16,r12
- adds r8=PT(EML_UNAT)+16,r12
- ;;
- ld8 r8=[r8]
- ;;
- mov ar.unat=r8
- ;;
- lfetch [r20],PT(CR_IPSR)-PT(PR)
- adds r2 = PT(B6)+16,r12
- adds r3 = PT(B7)+16,r12
- ;;
- lfetch [r20]
- ;;
- ld8 r24=[r2],16 /* B6 */
- ld8 r25=[r3],16 /* B7 */
- ;;
- ld8 r26=[r2],16 /* ar_csd */
- ld8 r27=[r3],16 /* ar_ssd */
- mov b6 = r24
- ;;
- ld8.fill r8=[r2],16
- ld8.fill r9=[r3],16
- mov b7 = r25
- ;;
- mov ar.csd = r26
- mov ar.ssd = r27
- ;;
- ld8.fill r10=[r2],PT(R15)-PT(R10)
- ld8.fill r11=[r3],PT(R14)-PT(R11)
- ;;
- ld8.fill r15=[r2],PT(R16)-PT(R15)
- ld8.fill r14=[r3],PT(R17)-PT(R14)
- ;;
- ld8.fill r16=[r2],16
- ld8.fill r17=[r3],16
- ;;
- ld8.fill r18=[r2],16
- ld8.fill r19=[r3],16
- ;;
- ld8.fill r20=[r2],16
- ld8.fill r21=[r3],16
- ;;
- ld8.fill r22=[r2],16
- ld8.fill r23=[r3],16
- ;;
- ld8.fill r24=[r2],16
- ld8.fill r25=[r3],16
- ;;
- ld8.fill r26=[r2],16
- ld8.fill r27=[r3],16
- ;;
- ld8.fill r28=[r2],16
- ld8.fill r29=[r3],16
- ;;
- ld8.fill r30=[r2],PT(F6)-PT(R30)
- ld8.fill r31=[r3],PT(F7)-PT(R31)
- ;;
- rsm psr.i | psr.ic
- // initiate turning off of interrupt and interruption collection
- invala // invalidate ALAT
- ;;
- srlz.i // ensure interruption collection is off
- ;;
- bsw.0
- ;;
- adds r16 = PT(CR_IPSR)+16,r12
- adds r17 = PT(CR_IIP)+16,r12
- mov r21=r13 // get current
- ;;
- ld8 r31=[r16],16 // load cr.ipsr
- ld8 r30=[r17],16 // load cr.iip
- ;;
- ld8 r29=[r16],16 // load cr.ifs
- ld8 r28=[r17],16 // load ar.unat
- ;;
- ld8 r27=[r16],16 // load ar.pfs
- ld8 r26=[r17],16 // load ar.rsc
- ;;
- ld8 r25=[r16],16 // load ar.rnat
- ld8 r24=[r17],16 // load ar.bspstore
- ;;
- ld8 r23=[r16],16 // load predicates
- ld8 r22=[r17],16 // load b0
- ;;
- ld8 r20=[r16],16 // load ar.rsc value for "loadrs"
- ld8.fill r1=[r17],16 //load r1
- ;;
- ld8.fill r12=[r16],16 //load r12
- ld8.fill r13=[r17],PT(R2)-PT(R13) //load r13
- ;;
- ld8 r19=[r16],PT(R3)-PT(AR_FPSR) //load ar_fpsr
- ld8.fill r2=[r17],PT(AR_CCV)-PT(R2) //load r2
- ;;
- ld8.fill r3=[r16] //load r3
- ld8 r18=[r17] //load ar_ccv
- ;;
- mov ar.fpsr=r19
- mov ar.ccv=r18
- shr.u r18=r20,16
- ;;
+ rsm psr.i
+ ;;
+ br.call.sptk.many b0=leave_hypervisor_tail
+ ;;
+ adds r20=PT(PR)+16,r12
+ adds r8=PT(EML_UNAT)+16,r12
+ ;;
+ ld8 r8=[r8]
+ ;;
+ mov ar.unat=r8
+ ;;
+ lfetch [r20],PT(CR_IPSR)-PT(PR)
+ adds r2 = PT(B6)+16,r12
+ adds r3 = PT(B7)+16,r12
+ ;;
+ lfetch [r20]
+ ;;
+ ld8 r24=[r2],16 /* B6 */
+ ld8 r25=[r3],16 /* B7 */
+ ;;
+ ld8 r26=[r2],16 /* ar_csd */
+ ld8 r27=[r3],16 /* ar_ssd */
+ mov b6 = r24
+ ;;
+ ld8.fill r8=[r2],16
+ ld8.fill r9=[r3],16
+ mov b7 = r25
+ ;;
+ mov ar.csd = r26
+ mov ar.ssd = r27
+ ;;
+ ld8.fill r10=[r2],PT(R15)-PT(R10)
+ ld8.fill r11=[r3],PT(R14)-PT(R11)
+ ;;
+ ld8.fill r15=[r2],PT(R16)-PT(R15)
+ ld8.fill r14=[r3],PT(R17)-PT(R14)
+ ;;
+ ld8.fill r16=[r2],16
+ ld8.fill r17=[r3],16
+ ;;
+ ld8.fill r18=[r2],16
+ ld8.fill r19=[r3],16
+ ;;
+ ld8.fill r20=[r2],16
+ ld8.fill r21=[r3],16
+ ;;
+ ld8.fill r22=[r2],16
+ ld8.fill r23=[r3],16
+ ;;
+ ld8.fill r24=[r2],16
+ ld8.fill r25=[r3],16
+ ;;
+ ld8.fill r26=[r2],16
+ ld8.fill r27=[r3],16
+ ;;
+ ld8.fill r28=[r2],16
+ ld8.fill r29=[r3],16
+ ;;
+ ld8.fill r30=[r2],PT(F6)-PT(R30)
+ ld8.fill r31=[r3],PT(F7)-PT(R31)
+ ;;
+ rsm psr.i | psr.ic
+ // initiate turning off of interrupt and interruption collection
+ invala // invalidate ALAT
+ ;;
+ srlz.i // ensure interruption collection is off
+ ;;
+ bsw.0
+ ;;
+ adds r16 = PT(CR_IPSR)+16,r12
+ adds r17 = PT(CR_IIP)+16,r12
+ mov r21=r13 // get current
+ ;;
+ ld8 r31=[r16],16 // load cr.ipsr
+ ld8 r30=[r17],16 // load cr.iip
+ ;;
+ ld8 r29=[r16],16 // load cr.ifs
+ ld8 r28=[r17],16 // load ar.unat
+ ;;
+ ld8 r27=[r16],16 // load ar.pfs
+ ld8 r26=[r17],16 // load ar.rsc
+ ;;
+ ld8 r25=[r16],16 // load ar.rnat
+ ld8 r24=[r17],16 // load ar.bspstore
+ ;;
+ ld8 r23=[r16],16 // load predicates
+ ld8 r22=[r17],16 // load b0
+ ;;
+ ld8 r20=[r16],16 // load ar.rsc value for "loadrs"
+ ld8.fill r1=[r17],16 //load r1
+ ;;
+ ld8.fill r12=[r16],16 //load r12
+ ld8.fill r13=[r17],PT(R2)-PT(R13) //load r13
+ ;;
+ ld8 r19=[r16],PT(R3)-PT(AR_FPSR) //load ar_fpsr
+ ld8.fill r2=[r17],PT(AR_CCV)-PT(R2) //load r2
+ ;;
+ ld8.fill r3=[r16] //load r3
+ ld8 r18=[r17] //load ar_ccv
+ ;;
+ mov ar.fpsr=r19
+ mov ar.ccv=r18
+ shr.u r18=r20,16
+ ;;
kvm_rbs_switch:
- mov r19=96
+ mov r19=96
kvm_dont_preserve_current_frame:
/*
@@ -1201,76 +1198,76 @@ kvm_dont_preserve_current_frame:
# define pReturn p7
# define Nregs 14
- alloc loc0=ar.pfs,2,Nregs-2,2,0
- shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
- sub r19=r19,r18 // r19 = (physStackedSize + 8) - dirtySize
- ;;
- mov ar.rsc=r20 // load ar.rsc to be used for "loadrs"
- shladd in0=loc1,3,r19
- mov in1=0
- ;;
- TEXT_ALIGN(32)
+ alloc loc0=ar.pfs,2,Nregs-2,2,0
+ shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
+ sub r19=r19,r18 // r19 = (physStackedSize + 8) - dirtySize
+ ;;
+ mov ar.rsc=r20 // load ar.rsc to be used for "loadrs"
+ shladd in0=loc1,3,r19
+ mov in1=0
+ ;;
+ TEXT_ALIGN(32)
kvm_rse_clear_invalid:
- alloc loc0=ar.pfs,2,Nregs-2,2,0
- cmp.lt pRecurse,p0=Nregs*8,in0
- // if more than Nregs regs left to clear, (re)curse
- add out0=-Nregs*8,in0
- add out1=1,in1 // increment recursion count
- mov loc1=0
- mov loc2=0
- ;;
- mov loc3=0
- mov loc4=0
- mov loc5=0
- mov loc6=0
- mov loc7=0
+ alloc loc0=ar.pfs,2,Nregs-2,2,0
+ cmp.lt pRecurse,p0=Nregs*8,in0
+ // if more than Nregs regs left to clear, (re)curse
+ add out0=-Nregs*8,in0
+ add out1=1,in1 // increment recursion count
+ mov loc1=0
+ mov loc2=0
+ ;;
+ mov loc3=0
+ mov loc4=0
+ mov loc5=0
+ mov loc6=0
+ mov loc7=0
(pRecurse) br.call.dptk.few b0=kvm_rse_clear_invalid
- ;;
- mov loc8=0
- mov loc9=0
- cmp.ne pReturn,p0=r0,in1
- // if recursion count != 0, we need to do a br.ret
- mov loc10=0
- mov loc11=0
+ ;;
+ mov loc8=0
+ mov loc9=0
+ cmp.ne pReturn,p0=r0,in1
+ // if recursion count != 0, we need to do a br.ret
+ mov loc10=0
+ mov loc11=0
(pReturn) br.ret.dptk.many b0
# undef pRecurse
# undef pReturn
// loadrs has already been shifted
- alloc r16=ar.pfs,0,0,0,0 // drop current register frame
- ;;
- loadrs
- ;;
- mov ar.bspstore=r24
- ;;
- mov ar.unat=r28
- mov ar.rnat=r25
- mov ar.rsc=r26
- ;;
- mov cr.ipsr=r31
- mov cr.iip=r30
- mov cr.ifs=r29
- mov ar.pfs=r27
- adds r18=VMM_VPD_BASE_OFFSET,r21
- ;;
- ld8 r18=[r18] //vpd
- adds r17=VMM_VCPU_ISR_OFFSET,r21
- ;;
- ld8 r17=[r17]
- adds r19=VMM_VPD_VPSR_OFFSET,r18
- ;;
- ld8 r19=[r19] //vpsr
- mov r25=r18
- adds r16= VMM_VCPU_GP_OFFSET,r21
- ;;
- ld8 r16= [r16] // Put gp in r24
- movl r24=@gprel(ia64_vmm_entry) // calculate return address
- ;;
- add r24=r24,r16
- ;;
- br.sptk.many kvm_vps_sync_write // call the service
- ;;
+ alloc r16=ar.pfs,0,0,0,0 // drop current register frame
+ ;;
+ loadrs
+ ;;
+ mov ar.bspstore=r24
+ ;;
+ mov ar.unat=r28
+ mov ar.rnat=r25
+ mov ar.rsc=r26
+ ;;
+ mov cr.ipsr=r31
+ mov cr.iip=r30
+ mov cr.ifs=r29
+ mov ar.pfs=r27
+ adds r18=VMM_VPD_BASE_OFFSET,r21
+ ;;
+ ld8 r18=[r18] //vpd
+ adds r17=VMM_VCPU_ISR_OFFSET,r21
+ ;;
+ ld8 r17=[r17]
+ adds r19=VMM_VPD_VPSR_OFFSET,r18
+ ;;
+ ld8 r19=[r19] //vpsr
+ mov r25=r18
+ adds r16= VMM_VCPU_GP_OFFSET,r21
+ ;;
+ ld8 r16= [r16] // Put gp in r24
+ movl r24=@gprel(ia64_vmm_entry) // calculate return address
+ ;;
+ add r24=r24,r16
+ ;;
+ br.sptk.many kvm_vps_sync_write // call the service
+ ;;
END(ia64_leave_hypervisor)
// fall through
GLOBAL_ENTRY(ia64_vmm_entry)
@@ -1283,16 +1280,14 @@ GLOBAL_ENTRY(ia64_vmm_entry)
* r22:b0
* r23:predicate
*/
- mov r24=r22
- mov r25=r18
- tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
- (p1) br.cond.sptk.few kvm_vps_resume_normal
- (p2) br.cond.sptk.many kvm_vps_resume_handler
- ;;
+ mov r24=r22
+ mov r25=r18
+ tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic
+(p1) br.cond.sptk.few kvm_vps_resume_normal
+(p2) br.cond.sptk.many kvm_vps_resume_handler
+ ;;
END(ia64_vmm_entry)
-
-
/*
* extern u64 ia64_call_vsa(u64 proc, u64 arg1, u64 arg2,
* u64 arg3, u64 arg4, u64 arg5,
@@ -1310,88 +1305,88 @@ psrsave = loc2
entry = loc3
hostret = r24
- alloc pfssave=ar.pfs,4,4,0,0
- mov rpsave=rp
- adds entry=VMM_VCPU_VSA_BASE_OFFSET, r13
- ;;
- ld8 entry=[entry]
-1: mov hostret=ip
- mov r25=in1 // copy arguments
- mov r26=in2
- mov r27=in3
- mov psrsave=psr
- ;;
- tbit.nz p6,p0=psrsave,14 // IA64_PSR_I
- tbit.nz p7,p0=psrsave,13 // IA64_PSR_IC
- ;;
- add hostret=2f-1b,hostret // calculate return address
- add entry=entry,in0
- ;;
- rsm psr.i | psr.ic
- ;;
- srlz.i
- mov b6=entry
- br.cond.sptk b6 // call the service
+ alloc pfssave=ar.pfs,4,4,0,0
+ mov rpsave=rp
+ adds entry=VMM_VCPU_VSA_BASE_OFFSET, r13
+ ;;
+ ld8 entry=[entry]
+1: mov hostret=ip
+ mov r25=in1 // copy arguments
+ mov r26=in2
+ mov r27=in3
+ mov psrsave=psr
+ ;;
+ tbit.nz p6,p0=psrsave,14 // IA64_PSR_I
+ tbit.nz p7,p0=psrsave,13 // IA64_PSR_IC
+ ;;
+ add hostret=2f-1b,hostret // calculate return address
+ add entry=entry,in0
+ ;;
+ rsm psr.i | psr.ic
+ ;;
+ srlz.i
+ mov b6=entry
+ br.cond.sptk b6 // call the service
2:
- // Architectural sequence for enabling interrupts if necessary
+// Architectural sequence for enabling interrupts if necessary
(p7) ssm psr.ic
- ;;
+ ;;
(p7) srlz.i
- ;;
+ ;;
//(p6) ssm psr.i
- ;;
- mov rp=rpsave
- mov ar.pfs=pfssave
- mov r8=r31
- ;;
- srlz.d
- br.ret.sptk rp
+ ;;
+ mov rp=rpsave
+ mov ar.pfs=pfssave
+ mov r8=r31
+ ;;
+ srlz.d
+ br.ret.sptk rp
END(ia64_call_vsa)
#define INIT_BSPSTORE ((4<<30)-(12<<20)-0x100)
GLOBAL_ENTRY(vmm_reset_entry)
- //set up ipsr, iip, vpd.vpsr, dcr
- // For IPSR: it/dt/rt=1, i/ic=1, si=1, vm/bn=1
- // For DCR: all bits 0
- bsw.0
- ;;
- mov r21 =r13
- adds r14=-VMM_PT_REGS_SIZE, r12
- ;;
- movl r6=0x501008826000 // IPSR dt/rt/it:1;i/ic:1, si:1, vm/bn:1
- movl r10=0x8000000000000000
- adds r16=PT(CR_IIP), r14
- adds r20=PT(R1), r14
- ;;
- rsm psr.ic | psr.i
- ;;
- srlz.i
- ;;
- mov ar.rsc = 0
- ;;
- flushrs
- ;;
- mov ar.bspstore = 0
- // clear BSPSTORE
- ;;
- mov cr.ipsr=r6
- mov cr.ifs=r10
- ld8 r4 = [r16] // Set init iip for first run.
- ld8 r1 = [r20]
- ;;
- mov cr.iip=r4
- adds r16=VMM_VPD_BASE_OFFSET,r13
- ;;
- ld8 r18=[r16]
- ;;
- adds r19=VMM_VPD_VPSR_OFFSET,r18
- ;;
- ld8 r19=[r19]
- mov r17=r0
- mov r22=r0
- mov r23=r0
- br.cond.sptk ia64_vmm_entry
- br.ret.sptk b0
+ //set up ipsr, iip, vpd.vpsr, dcr
+ // For IPSR: it/dt/rt=1, i/ic=1, si=1, vm/bn=1
+ // For DCR: all bits 0
+ bsw.0
+ ;;
+ mov r21 =r13
+ adds r14=-VMM_PT_REGS_SIZE, r12
+ ;;
+ movl r6=0x501008826000 // IPSR dt/rt/it:1;i/ic:1, si:1, vm/bn:1
+ movl r10=0x8000000000000000
+ adds r16=PT(CR_IIP), r14
+ adds r20=PT(R1), r14
+ ;;
+ rsm psr.ic | psr.i
+ ;;
+ srlz.i
+ ;;
+ mov ar.rsc = 0
+ ;;
+ flushrs
+ ;;
+ mov ar.bspstore = 0
+ // clear BSPSTORE
+ ;;
+ mov cr.ipsr=r6
+ mov cr.ifs=r10
+ ld8 r4 = [r16] // Set init iip for first run.
+ ld8 r1 = [r20]
+ ;;
+ mov cr.iip=r4
+ adds r16=VMM_VPD_BASE_OFFSET,r13
+ ;;
+ ld8 r18=[r16]
+ ;;
+ adds r19=VMM_VPD_VPSR_OFFSET,r18
+ ;;
+ ld8 r19=[r19]
+ mov r17=r0
+ mov r22=r0
+ mov r23=r0
+ br.cond.sptk ia64_vmm_entry
+ br.ret.sptk b0
END(vmm_reset_entry)
diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c
index e22b93361e08..6b6307a3bd55 100644
--- a/arch/ia64/kvm/vtlb.c
+++ b/arch/ia64/kvm/vtlb.c
@@ -183,8 +183,8 @@ void mark_pages_dirty(struct kvm_vcpu *v, u64 pte, u64 ps)
u64 i, dirty_pages = 1;
u64 base_gfn = (pte&_PAGE_PPN_MASK) >> PAGE_SHIFT;
spinlock_t *lock = __kvm_va(v->arch.dirty_log_lock_pa);
- void *dirty_bitmap = (void *)v - (KVM_VCPU_OFS + v->vcpu_id * VCPU_SIZE)
- + KVM_MEM_DIRTY_LOG_OFS;
+ void *dirty_bitmap = (void *)KVM_MEM_DIRTY_LOG_BASE;
+
dirty_pages <<= ps <= PAGE_SHIFT ? 0 : ps - PAGE_SHIFT;
vmm_spin_lock(lock);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 054bcd9439aa..56e12903973c 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -692,7 +692,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
pgdat = NODE_DATA(nid);
zone = pgdat->node_zones + ZONE_NORMAL;
- ret = __add_pages(zone, start_pfn, nr_pages);
+ ret = __add_pages(nid, zone, start_pfn, nr_pages);
if (ret)
printk("%s: Problem encountered in __add_pages() as ret=%d\n",
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 211fcfd115f9..61f1af5c23c1 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -19,6 +19,7 @@
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/bootmem.h>
#include <asm/machvec.h>
#include <asm/page.h>
@@ -748,6 +749,32 @@ static void __init set_pci_cacheline_size(void)
pci_cache_line_size = (1 << cci.pcci_line_size) / 4;
}
+u64 ia64_dma_get_required_mask(struct device *dev)
+{
+ u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
+ u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));
+ u64 mask;
+
+ if (!high_totalram) {
+ /* convert to mask just covering totalram */
+ low_totalram = (1 << (fls(low_totalram) - 1));
+ low_totalram += low_totalram - 1;
+ mask = low_totalram;
+ } else {
+ high_totalram = (1 << (fls(high_totalram) - 1));
+ high_totalram += high_totalram - 1;
+ mask = (((u64)high_totalram) << 32) + 0xffffffff;
+ }
+ return mask;
+}
+EXPORT_SYMBOL_GPL(ia64_dma_get_required_mask);
+
+u64 dma_get_required_mask(struct device *dev)
+{
+ return platform_dma_get_required_mask(dev);
+}
+EXPORT_SYMBOL_GPL(dma_get_required_mask);
+
static int __init pcibios_init(void)
{
set_pci_cacheline_size();
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
index bc610a6c7851..c5a214026a77 100644
--- a/arch/ia64/sn/kernel/io_acpi_init.c
+++ b/arch/ia64/sn/kernel/io_acpi_init.c
@@ -13,7 +13,6 @@
#include <asm/sn/sn_sal.h>
#include "xtalk/hubdev.h"
#include <linux/acpi.h>
-#include <acpi/acnamesp.h>
/*
@@ -64,6 +63,7 @@ static acpi_status __init
sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
u64 addr;
struct hubdev_info *hubdev;
struct hubdev_info *hubdev_ptr;
@@ -77,11 +77,12 @@ sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
&sn_uuid, &buffer);
if (ACPI_FAILURE(status)) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
printk(KERN_ERR
"sn_acpi_hubdev_init: acpi_get_vendor_resource() "
- "(0x%x) failed for: ", status);
- acpi_ns_print_node_pathname(handle, NULL);
- printk("\n");
+ "(0x%x) failed for: %s\n", status,
+ (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
return AE_OK; /* Continue walking namespace */
}
@@ -89,11 +90,12 @@ sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
vendor = &resource->data.vendor_typed;
if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
sizeof(struct hubdev_info *)) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
printk(KERN_ERR
- "sn_acpi_hubdev_init: Invalid vendor data length: %d for: ",
- vendor->byte_length);
- acpi_ns_print_node_pathname(handle, NULL);
- printk("\n");
+ "sn_acpi_hubdev_init: Invalid vendor data length: "
+ "%d for: %s\n",
+ vendor->byte_length, (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
goto exit;
}
@@ -120,6 +122,7 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
{
u64 addr;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle;
struct pcibus_bussoft *prom_bussoft_ptr;
struct acpi_resource *resource;
@@ -131,11 +134,11 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
&sn_uuid, &buffer);
if (ACPI_FAILURE(status)) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
printk(KERN_ERR "%s: "
- "acpi_get_vendor_resource() failed (0x%x) for: ",
- __func__, status);
- acpi_ns_print_node_pathname(handle, NULL);
- printk("\n");
+ "acpi_get_vendor_resource() failed (0x%x) for: %s\n",
+ __func__, status, (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
return NULL;
}
resource = buffer.pointer;
@@ -168,6 +171,7 @@ sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
{
u64 addr;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct sn_irq_info *irq_info, *irq_info_prom;
struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
struct acpi_resource *resource;
@@ -182,11 +186,11 @@ sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
&sn_uuid, &buffer);
if (ACPI_FAILURE(status)) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
printk(KERN_ERR
- "%s: acpi_get_vendor_resource() failed (0x%x) for: ",
- __func__, status);
- acpi_ns_print_node_pathname(handle, NULL);
- printk("\n");
+ "%s: acpi_get_vendor_resource() failed (0x%x) for: %s\n",
+ __func__, status, (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
return 1;
}
@@ -194,11 +198,12 @@ sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
vendor = &resource->data.vendor_typed;
if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
sizeof(struct pci_devdev_info *)) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
printk(KERN_ERR
- "%s: Invalid vendor data length: %d for: ",
- __func__, vendor->byte_length);
- acpi_ns_print_node_pathname(handle, NULL);
- printk("\n");
+ "%s: Invalid vendor data length: %d for: %s\n",
+ __func__, vendor->byte_length,
+ (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
ret = 1;
goto exit;
}
@@ -239,6 +244,9 @@ get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
acpi_handle parent;
int slot;
acpi_status status;
+ struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ acpi_get_name(device_handle, ACPI_FULL_PATHNAME, &name_buffer);
/*
* Do an upward search to find the root bus device, and
@@ -249,9 +257,8 @@ get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
status = acpi_get_parent(child, &parent);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR "%s: acpi_get_parent() failed "
- "(0x%x) for: ", __func__, status);
- acpi_ns_print_node_pathname(child, NULL);
- printk("\n");
+ "(0x%x) for: %s\n", __func__, status,
+ (char *)name_buffer.pointer);
panic("%s: Unable to find host devfn\n", __func__);
}
if (parent == rootbus_handle)
@@ -259,22 +266,20 @@ get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
child = parent;
}
if (!child) {
- printk(KERN_ERR "%s: Unable to find root bus for: ",
- __func__);
- acpi_ns_print_node_pathname(device_handle, NULL);
- printk("\n");
+ printk(KERN_ERR "%s: Unable to find root bus for: %s\n",
+ __func__, (char *)name_buffer.pointer);
BUG();
}
status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
if (ACPI_FAILURE(status)) {
- printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: ",
- __func__, status);
- acpi_ns_print_node_pathname(child, NULL);
- printk("\n");
+ printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: %s\n",
+ __func__, status, (char *)name_buffer.pointer);
panic("%s: Unable to find host devfn\n", __func__);
}
+ kfree(name_buffer.pointer);
+
slot = (adr >> 16) & 0xffff;
function = adr & 0xffff;
devfn = PCI_DEVFN(slot, function);
@@ -300,27 +305,28 @@ find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
int function;
int slot;
struct sn_pcidev_match *info = context;
+ struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
&adr);
if (ACPI_SUCCESS(status)) {
status = acpi_get_parent(handle, &parent);
if (ACPI_FAILURE(status)) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
printk(KERN_ERR
- "%s: acpi_get_parent() failed (0x%x) for: ",
- __func__, status);
- acpi_ns_print_node_pathname(handle, NULL);
- printk("\n");
+ "%s: acpi_get_parent() failed (0x%x) for: %s\n",
+ __func__, status, (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
return AE_OK;
}
status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
NULL, &bbn);
if (ACPI_FAILURE(status)) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
printk(KERN_ERR
- "%s: Failed to find _BBN in parent of: ",
- __func__);
- acpi_ns_print_node_pathname(handle, NULL);
- printk("\n");
+ "%s: Failed to find _BBN in parent of: %s\n",
+ __func__, (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
return AE_OK;
}
@@ -350,24 +356,27 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
acpi_handle rootbus_handle;
unsigned long long segment;
acpi_status status;
+ struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
&segment);
if (ACPI_SUCCESS(status)) {
if (segment != pci_domain_nr(dev)) {
+ acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME,
+ &name_buffer);
printk(KERN_ERR
- "%s: Segment number mismatch, 0x%llx vs 0x%x for: ",
- __func__, segment, pci_domain_nr(dev));
- acpi_ns_print_node_pathname(rootbus_handle, NULL);
- printk("\n");
+ "%s: Segment number mismatch, 0x%llx vs 0x%x for: %s\n",
+ __func__, segment, pci_domain_nr(dev),
+ (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
return 1;
}
} else {
- printk(KERN_ERR "%s: Unable to get __SEG from: ",
- __func__);
- acpi_ns_print_node_pathname(rootbus_handle, NULL);
- printk("\n");
+ acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME, &name_buffer);
+ printk(KERN_ERR "%s: Unable to get __SEG from: %s\n",
+ __func__, (char *)name_buffer.pointer);
+ kfree(name_buffer.pointer);
return 1;
}
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
index 8a924a5661dd..0d4ffa4da1da 100644
--- a/arch/ia64/sn/kernel/io_common.c
+++ b/arch/ia64/sn/kernel/io_common.c
@@ -26,7 +26,6 @@
#include <linux/acpi.h>
#include <asm/sn/sn2/sn_hwperf.h>
#include <asm/sn/acpi.h>
-#include "acpi/acglobal.h"
extern void sn_init_cpei_timer(void);
extern void register_sn_procfs(void);
@@ -473,7 +472,7 @@ sn_io_early_init(void)
{
struct acpi_table_header *header = NULL;
- acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header);
+ acpi_get_table(ACPI_SIG_DSDT, 1, &header);
BUG_ON(header == NULL);
sn_acpi_rev = header->oem_revision;
}
@@ -505,7 +504,7 @@ sn_io_early_init(void)
{
struct acpi_table_header *header;
- (void)acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header);
+ (void)acpi_get_table(ACPI_SIG_DSDT, 1, &header);
printk(KERN_INFO "ACPI DSDT OEM Rev 0x%x\n",
header->oem_revision);
}
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 0c66dbdd1d72..66fd705e82c0 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -227,14 +227,14 @@ finish_up:
return new_irq_info;
}
-static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
+static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
{
struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
nasid_t nasid;
int slice;
- nasid = cpuid_to_nasid(first_cpu(mask));
- slice = cpuid_to_slice(first_cpu(mask));
+ nasid = cpuid_to_nasid(cpumask_first(mask));
+ slice = cpuid_to_slice(cpumask_first(mask));
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
sn_irq_lh[irq], list)
diff --git a/arch/ia64/sn/kernel/msi_sn.c b/arch/ia64/sn/kernel/msi_sn.c
index 83f190ffe350..ca553b0429ce 100644
--- a/arch/ia64/sn/kernel/msi_sn.c
+++ b/arch/ia64/sn/kernel/msi_sn.c
@@ -151,7 +151,8 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
}
#ifdef CONFIG_SMP
-static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
+static void sn_set_msi_irq_affinity(unsigned int irq,
+ const struct cpumask *cpu_mask)
{
struct msi_msg msg;
int slice;
@@ -164,7 +165,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
struct sn_pcibus_provider *provider;
unsigned int cpu;
- cpu = first_cpu(cpu_mask);
+ cpu = cpumask_first(cpu_mask);
sn_irq_info = sn_msi_info[irq].sn_irq_info;
if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
return;
@@ -204,7 +205,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
write_msi_msg(irq, &msg);
- irq_desc[irq].affinity = cpu_mask;
+ irq_desc[irq].affinity = *cpu_mask;
}
#endif /* CONFIG_SMP */
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 636588e7e068..be339477f906 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -385,7 +385,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
int j;
const char *slabname;
int ordinal;
- cpumask_t cpumask;
char slice;
struct cpuinfo_ia64 *c;
struct sn_hwperf_port_info *ptdata;
@@ -473,23 +472,21 @@ static int sn_topology_show(struct seq_file *s, void *d)
* CPUs on this node, if any
*/
if (!SN_HWPERF_IS_IONODE(obj)) {
- cpumask = node_to_cpumask(ordinal);
- for_each_online_cpu(i) {
- if (cpu_isset(i, cpumask)) {
- slice = 'a' + cpuid_to_slice(i);
- c = cpu_data(i);
- seq_printf(s, "cpu %d %s%c local"
- " freq %luMHz, arch ia64",
- i, obj->location, slice,
- c->proc_freq / 1000000);
- for_each_online_cpu(j) {
- seq_printf(s, j ? ":%d" : ", dist %d",
- node_distance(
+ for_each_cpu_and(i, cpu_online_mask,
+ cpumask_of_node(ordinal)) {
+ slice = 'a' + cpuid_to_slice(i);
+ c = cpu_data(i);
+ seq_printf(s, "cpu %d %s%c local"
+ " freq %luMHz, arch ia64",
+ i, obj->location, slice,
+ c->proc_freq / 1000000);
+ for_each_online_cpu(j) {
+ seq_printf(s, j ? ":%d" : ", dist %d",
+ node_distance(
cpu_to_node(i),
cpu_to_node(j)));
- }
- seq_putc(s, '\n');
}
+ seq_putc(s, '\n');
}
}
}
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index a88eba3314d7..3f864238566d 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -206,8 +206,7 @@ cx_device_register(nasid_t nasid, int part_num, int mfg_num,
cx_dev->dev.parent = NULL;
cx_dev->dev.bus = &tiocx_bus_type;
cx_dev->dev.release = tiocx_bus_release;
- snprintf(cx_dev->dev.bus_id, BUS_ID_SIZE, "%d",
- cx_dev->cx_id.nasid);
+ dev_set_name(&cx_dev->dev, "%d", cx_dev->cx_id.nasid);
device_register(&cx_dev->dev);
get_device(&cx_dev->dev);
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 53ebb6484495..863f5017baae 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -356,6 +356,12 @@ int sn_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
}
EXPORT_SYMBOL(sn_dma_mapping_error);
+u64 sn_dma_get_required_mask(struct device *dev)
+{
+ return DMA_64BIT_MASK;
+}
+EXPORT_SYMBOL_GPL(sn_dma_get_required_mask);
+
char *sn_pci_get_legacy_mem(struct pci_bus *bus)
{
if (!SN_PCIBUS_BUSSOFT(bus))
diff --git a/arch/ia64/xen/time.c b/arch/ia64/xen/time.c
index d15a94c330fb..68d6204c3f16 100644
--- a/arch/ia64/xen/time.c
+++ b/arch/ia64/xen/time.c
@@ -129,8 +129,8 @@ consider_steal_time(unsigned long new_itm)
blocked = stolentick;
if (stolen > 0 || blocked > 0) {
- account_steal_time(NULL, jiffies_to_cputime(stolen));
- account_steal_time(idle_task(cpu), jiffies_to_cputime(blocked));
+ account_steal_ticks(stolen);
+ account_idle_ticks(blocked);
run_local_timers();
if (rcu_pending(cpu))
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 29047d5c259a..cabba332cc48 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -10,6 +10,7 @@ config M32R
default y
select HAVE_IDE
select HAVE_OPROFILE
+ select INIT_ALL_POSSIBLE
config SBUS
bool
diff --git a/arch/m32r/configs/m32104ut_defconfig b/arch/m32r/configs/m32104ut_defconfig
index 9b5af6cd2e0b..6f54b00b3838 100644
--- a/arch/m32r/configs/m32104ut_defconfig
+++ b/arch/m32r/configs/m32104ut_defconfig
@@ -621,7 +621,7 @@ CONFIG_I2C_ELEKTOR=m
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/m32r/kernel/init_task.c b/arch/m32r/kernel/init_task.c
index 0d658dbb6766..016885c6f260 100644
--- a/arch/m32r/kernel/init_task.c
+++ b/arch/m32r/kernel/init_task.c
@@ -11,7 +11,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c
index 39cb6da72dcb..2547d6c4a827 100644
--- a/arch/m32r/kernel/smpboot.c
+++ b/arch/m32r/kernel/smpboot.c
@@ -73,17 +73,11 @@ static unsigned int bsp_phys_id = -1;
/* Bitmask of physically existing CPUs */
physid_mask_t phys_cpu_present_map;
-/* Bitmask of currently online CPUs */
-cpumask_t cpu_online_map;
-EXPORT_SYMBOL(cpu_online_map);
-
cpumask_t cpu_bootout_map;
cpumask_t cpu_bootin_map;
static cpumask_t cpu_callin_map;
cpumask_t cpu_callout_map;
EXPORT_SYMBOL(cpu_callout_map);
-cpumask_t cpu_possible_map = CPU_MASK_ALL;
-EXPORT_SYMBOL(cpu_possible_map);
/* Per CPU bogomips and other parameters */
struct cpuinfo_m32r cpu_data[NR_CPUS] __cacheline_aligned;
@@ -598,7 +592,7 @@ int setup_profiling_timer(unsigned int multiplier)
* accounting. At that time they also adjust their APIC timers
* accordingly.
*/
- for (i = 0; i < NR_CPUS; ++i)
+ for_each_possible_cpu(i)
per_cpu(prof_multiplier, i) = multiplier;
return 0;
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 836fb66f080d..fb87c08c6b57 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -280,7 +280,6 @@ config M68060
config MMU_MOTOROLA
bool
- depends on MMU && !MMU_SUN3
config MMU_SUN3
bool
@@ -304,7 +303,7 @@ config M68KFPU_EMU_EXTRAPREC
correct rounding, the emulator can (often) do the same but this
extra calculation can cost quite some time, so you can disable
it here. The emulator will then "only" calculate with a 64 bit
- mantissa and round slightly incorrect, what is more then enough
+ mantissa and round slightly incorrect, what is more than enough
for normal usage.
config M68KFPU_EMU_ONLY
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 907a5533c845..c5b5212cc3f9 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -72,10 +72,14 @@ static struct irq_controller amiga_irq_controller = {
void __init amiga_init_IRQ(void)
{
- request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL);
- request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL);
- request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL);
- request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL);
+ if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
+ pr_err("Couldn't register int%d\n", 1);
+ if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
+ pr_err("Couldn't register int%d\n", 3);
+ if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
+ pr_err("Couldn't register int%d\n", 4);
+ if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
+ pr_err("Couldn't register int%d\n", 5);
m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index 343fab49bd9a..ecd0f7ca6f0e 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -176,5 +176,7 @@ void __init cia_init_IRQ(struct ciabase *base)
/* override auto int and install CIA handler */
m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
m68k_irq_startup(base->handler_irq);
- request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base);
+ if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
+ base->name, base))
+ pr_err("Couldn't register %s interrupt\n", base->name);
}
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index ab9862c3a136..6e562751ad51 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -493,7 +493,8 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
* Please don't change this to use ciaa, as it interferes with the
* SCSI code. We'll have to take a look at this later
*/
- request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
+ if (request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL))
+ pr_err("Couldn't register timer interrupt\n");
/* start timer */
ciab.cra |= 0x11;
}
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 78df98f2029a..8d3eafab1ffe 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -31,10 +31,6 @@ extern unsigned long dn_gettimeoffset(void);
extern int dn_dummy_hwclk(int, struct rtc_time *);
extern int dn_dummy_set_clock_mmss(unsigned long);
extern void dn_dummy_reset(void);
-extern void dn_dummy_waitbut(void);
-extern struct fb_info *dn_fb_init(long *);
-extern void dn_dummy_debug_init(void);
-extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
#ifdef CONFIG_HEARTBEAT
static void dn_heartbeat(int on);
#endif
@@ -204,7 +200,8 @@ void dn_sched_init(irq_handler_t timer_routine)
printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
#endif
- request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine);
+ if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine))
+ pr_err("Couldn't register timer interrupt\n");
}
unsigned long dn_gettimeoffset(void) {
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index c038b7c7eff0..a5f33c059979 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -33,7 +33,6 @@
#include <asm/atari_joystick.h>
#include <asm/irq.h>
-extern unsigned int keymap_count;
/* Hook for MIDI serial driver */
void (*atari_MIDI_interrupt_hook) (void);
@@ -567,14 +566,19 @@ static int atari_keyb_done = 0;
int atari_keyb_init(void)
{
+ int error;
+
if (atari_keyb_done)
return 0;
kb_state.state = KEYBOARD;
kb_state.len = 0;
- request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
- "keyboard/mouse/MIDI", atari_keyboard_interrupt);
+ error = request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt,
+ IRQ_TYPE_SLOW, "keyboard/mouse/MIDI",
+ atari_keyboard_interrupt);
+ if (error)
+ return error;
atari_turnoff_irq(IRQ_MFP_ACIA);
do {
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index d1bd029a34ac..604329fafbb8 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -179,8 +179,9 @@ EXPORT_SYMBOL(stdma_islocked);
void __init stdma_init(void)
{
stdma_isr = NULL;
- request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
- "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
+ if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
+ "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int))
+ pr_err("Couldn't register ST-DMA interrupt\n");
}
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 1edde27fa32d..d076ff8d1b39 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -31,8 +31,9 @@ atari_sched_init(irq_handler_t timer_routine)
/* start timer C, div = 1:100 */
mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
/* install interrupt service routine for MFP Timer C */
- request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
- "timer", timer_routine);
+ if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
+ "timer", timer_routine))
+ pr_err("Couldn't register timer interrupt\n");
}
/* ++andreas: gettimeoffset fixed to check for pending interrupt */
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index c072595928c0..9fe6fefb5e14 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -43,7 +43,6 @@ extern unsigned long bvme6000_gettimeoffset (void);
extern int bvme6000_hwclk (int, struct rtc_time *);
extern int bvme6000_set_clock_mmss (unsigned long);
extern void bvme6000_reset (void);
-extern void bvme6000_waitbut(void);
void bvme6000_set_vectors (void);
/* Save tick handler routine pointer, will point to do_timer() in
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index dd7c8a2583d3..f6312c7d8727 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -70,7 +70,8 @@ void __init hp300_sched_init(irq_handler_t vector)
asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
- request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
+ if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+ pr_err("Couldn't register timer interrupt\n");
out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */
diff --git a/include/asm-m68k/Kbuild b/arch/m68k/include/asm/Kbuild
index 1a922fad76f7..1a922fad76f7 100644
--- a/include/asm-m68k/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
diff --git a/arch/m68knommu/include/asm/MC68328.h b/arch/m68k/include/asm/MC68328.h
index a337e56d09bf..a337e56d09bf 100644
--- a/arch/m68knommu/include/asm/MC68328.h
+++ b/arch/m68k/include/asm/MC68328.h
diff --git a/arch/m68knommu/include/asm/MC68332.h b/arch/m68k/include/asm/MC68332.h
index 6bb8f02685a2..6bb8f02685a2 100644
--- a/arch/m68knommu/include/asm/MC68332.h
+++ b/arch/m68k/include/asm/MC68332.h
diff --git a/arch/m68knommu/include/asm/MC68EZ328.h b/arch/m68k/include/asm/MC68EZ328.h
index 69b7f9139e5e..69b7f9139e5e 100644
--- a/arch/m68knommu/include/asm/MC68EZ328.h
+++ b/arch/m68k/include/asm/MC68EZ328.h
diff --git a/arch/m68knommu/include/asm/MC68VZ328.h b/arch/m68k/include/asm/MC68VZ328.h
index 2b9bf626a0a5..2b9bf626a0a5 100644
--- a/arch/m68knommu/include/asm/MC68VZ328.h
+++ b/arch/m68k/include/asm/MC68VZ328.h
diff --git a/include/asm-m68k/a.out-core.h b/arch/m68k/include/asm/a.out-core.h
index f6bfc1d63ff6..f6bfc1d63ff6 100644
--- a/include/asm-m68k/a.out-core.h
+++ b/arch/m68k/include/asm/a.out-core.h
diff --git a/include/asm-m68k/a.out.h b/arch/m68k/include/asm/a.out.h
index 3885fe43432a..3885fe43432a 100644
--- a/include/asm-m68k/a.out.h
+++ b/arch/m68k/include/asm/a.out.h
diff --git a/include/asm-m68k/adb_iop.h b/arch/m68k/include/asm/adb_iop.h
index 8a48e56f2d62..8a48e56f2d62 100644
--- a/include/asm-m68k/adb_iop.h
+++ b/arch/m68k/include/asm/adb_iop.h
diff --git a/include/asm-m68k/amigahw.h b/arch/m68k/include/asm/amigahw.h
index 5ca5dd951a4a..5ca5dd951a4a 100644
--- a/include/asm-m68k/amigahw.h
+++ b/arch/m68k/include/asm/amigahw.h
diff --git a/include/asm-m68k/amigaints.h b/arch/m68k/include/asm/amigaints.h
index b1bcdb835ab9..b1bcdb835ab9 100644
--- a/include/asm-m68k/amigaints.h
+++ b/arch/m68k/include/asm/amigaints.h
diff --git a/include/asm-m68k/amigayle.h b/arch/m68k/include/asm/amigayle.h
index bb5a6aa329f3..bb5a6aa329f3 100644
--- a/include/asm-m68k/amigayle.h
+++ b/arch/m68k/include/asm/amigayle.h
diff --git a/include/asm-m68k/amipcmcia.h b/arch/m68k/include/asm/amipcmcia.h
index 6f1ec1887d82..6f1ec1887d82 100644
--- a/include/asm-m68k/amipcmcia.h
+++ b/arch/m68k/include/asm/amipcmcia.h
diff --git a/arch/m68knommu/include/asm/anchor.h b/arch/m68k/include/asm/anchor.h
index 871c0d5cfc3d..871c0d5cfc3d 100644
--- a/arch/m68knommu/include/asm/anchor.h
+++ b/arch/m68k/include/asm/anchor.h
diff --git a/include/asm-m68k/apollodma.h b/arch/m68k/include/asm/apollodma.h
index 954adc851adb..954adc851adb 100644
--- a/include/asm-m68k/apollodma.h
+++ b/arch/m68k/include/asm/apollodma.h
diff --git a/include/asm-m68k/apollohw.h b/arch/m68k/include/asm/apollohw.h
index a1373b9aa281..a1373b9aa281 100644
--- a/include/asm-m68k/apollohw.h
+++ b/arch/m68k/include/asm/apollohw.h
diff --git a/include/asm-m68k/atafd.h b/arch/m68k/include/asm/atafd.h
index 8456889ee7da..8456889ee7da 100644
--- a/include/asm-m68k/atafd.h
+++ b/arch/m68k/include/asm/atafd.h
diff --git a/include/asm-m68k/atafdreg.h b/arch/m68k/include/asm/atafdreg.h
index bbf80949fd9f..bbf80949fd9f 100644
--- a/include/asm-m68k/atafdreg.h
+++ b/arch/m68k/include/asm/atafdreg.h
diff --git a/include/asm-m68k/atari_joystick.h b/arch/m68k/include/asm/atari_joystick.h
index 93be7da9f2c7..93be7da9f2c7 100644
--- a/include/asm-m68k/atari_joystick.h
+++ b/arch/m68k/include/asm/atari_joystick.h
diff --git a/include/asm-m68k/atari_stdma.h b/arch/m68k/include/asm/atari_stdma.h
index 8e389b7fa70c..8e389b7fa70c 100644
--- a/include/asm-m68k/atari_stdma.h
+++ b/arch/m68k/include/asm/atari_stdma.h
diff --git a/include/asm-m68k/atari_stram.h b/arch/m68k/include/asm/atari_stram.h
index 7546d13963be..7546d13963be 100644
--- a/include/asm-m68k/atari_stram.h
+++ b/arch/m68k/include/asm/atari_stram.h
diff --git a/include/asm-m68k/atarihw.h b/arch/m68k/include/asm/atarihw.h
index 1412b4ab202f..1412b4ab202f 100644
--- a/include/asm-m68k/atarihw.h
+++ b/arch/m68k/include/asm/atarihw.h
diff --git a/include/asm-m68k/atariints.h b/arch/m68k/include/asm/atariints.h
index 5748e99f4e26..5748e99f4e26 100644
--- a/include/asm-m68k/atariints.h
+++ b/arch/m68k/include/asm/atariints.h
diff --git a/include/asm-m68k/atarikb.h b/arch/m68k/include/asm/atarikb.h
index 546e7da5804f..546e7da5804f 100644
--- a/include/asm-m68k/atarikb.h
+++ b/arch/m68k/include/asm/atarikb.h
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
new file mode 100644
index 000000000000..8d29145ebb27
--- /dev/null
+++ b/arch/m68k/include/asm/atomic.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "atomic_no.h"
+#else
+#include "atomic_mm.h"
+#endif
diff --git a/include/asm-m68k/atomic.h b/arch/m68k/include/asm/atomic_mm.h
index 4915294fea63..eb0ab9d4ee77 100644
--- a/include/asm-m68k/atomic.h
+++ b/arch/m68k/include/asm/atomic_mm.h
@@ -1,7 +1,7 @@
#ifndef __ARCH_M68K_ATOMIC__
#define __ARCH_M68K_ATOMIC__
-
+#include <linux/types.h>
#include <asm/system.h>
/*
@@ -13,7 +13,6 @@
* We do not have SMP m68k systems, so we don't have to deal with that.
*/
-typedef struct { int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
diff --git a/arch/m68knommu/include/asm/atomic.h b/arch/m68k/include/asm/atomic_no.h
index d5632a305dae..6bb674855a3f 100644
--- a/arch/m68knommu/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic_no.h
@@ -1,6 +1,7 @@
#ifndef __ARCH_M68KNOMMU_ATOMIC__
#define __ARCH_M68KNOMMU_ATOMIC__
+#include <linux/types.h>
#include <asm/system.h>
/*
@@ -12,7 +13,6 @@
* We do not have SMP m68k systems, so we don't have to deal with that.
*/
-typedef struct { int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
diff --git a/arch/m68knommu/include/asm/auxvec.h b/arch/m68k/include/asm/auxvec.h
index 844d6d52204b..844d6d52204b 100644
--- a/arch/m68knommu/include/asm/auxvec.h
+++ b/arch/m68k/include/asm/auxvec.h
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h
new file mode 100644
index 000000000000..ce163abddaba
--- /dev/null
+++ b/arch/m68k/include/asm/bitops.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "bitops_no.h"
+#else
+#include "bitops_mm.h"
+#endif
diff --git a/include/asm-m68k/bitops.h b/arch/m68k/include/asm/bitops_mm.h
index 3e8106442d5a..9bde784e7bad 100644
--- a/include/asm-m68k/bitops.h
+++ b/arch/m68k/include/asm/bitops_mm.h
@@ -315,6 +315,11 @@ static inline int fls(int x)
return 32 - cnt;
}
+static inline int __fls(int x)
+{
+ return fls(x) - 1;
+}
+
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/hweight.h>
diff --git a/arch/m68knommu/include/asm/bitops.h b/arch/m68k/include/asm/bitops_no.h
index 6f3685eab44c..9d3cbe5fad1e 100644
--- a/arch/m68knommu/include/asm/bitops.h
+++ b/arch/m68k/include/asm/bitops_no.h
@@ -331,6 +331,7 @@ found_middle:
#endif /* __KERNEL__ */
#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#endif /* _M68KNOMMU_BITOPS_H */
diff --git a/include/asm-m68k/blinken.h b/arch/m68k/include/asm/blinken.h
index 1a749cf7b06d..1a749cf7b06d 100644
--- a/include/asm-m68k/blinken.h
+++ b/arch/m68k/include/asm/blinken.h
diff --git a/arch/m68k/include/asm/bootinfo.h b/arch/m68k/include/asm/bootinfo.h
new file mode 100644
index 000000000000..fedf3e326121
--- /dev/null
+++ b/arch/m68k/include/asm/bootinfo.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "bootinfo_no.h"
+#else
+#include "bootinfo_mm.h"
+#endif
diff --git a/include/asm-m68k/bootinfo.h b/arch/m68k/include/asm/bootinfo_mm.h
index fb8a06b9ab6a..fb8a06b9ab6a 100644
--- a/include/asm-m68k/bootinfo.h
+++ b/arch/m68k/include/asm/bootinfo_mm.h
diff --git a/arch/m68knommu/include/asm/bootinfo.h b/arch/m68k/include/asm/bootinfo_no.h
index c12e526f5189..c12e526f5189 100644
--- a/arch/m68knommu/include/asm/bootinfo.h
+++ b/arch/m68k/include/asm/bootinfo_no.h
diff --git a/arch/m68knommu/include/asm/bootstd.h b/arch/m68k/include/asm/bootstd.h
index bdc1a4ac4fe9..bdc1a4ac4fe9 100644
--- a/arch/m68knommu/include/asm/bootstd.h
+++ b/arch/m68k/include/asm/bootstd.h
diff --git a/arch/m68k/include/asm/bug.h b/arch/m68k/include/asm/bug.h
new file mode 100644
index 000000000000..997e0944ebc1
--- /dev/null
+++ b/arch/m68k/include/asm/bug.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "bug_no.h"
+#else
+#include "bug_mm.h"
+#endif
diff --git a/include/asm-m68k/bug.h b/arch/m68k/include/asm/bug_mm.h
index e5b528deb8a8..e5b528deb8a8 100644
--- a/include/asm-m68k/bug.h
+++ b/arch/m68k/include/asm/bug_mm.h
diff --git a/arch/m68knommu/include/asm/bug.h b/arch/m68k/include/asm/bug_no.h
index 70e7dc0af21a..70e7dc0af21a 100644
--- a/arch/m68knommu/include/asm/bug.h
+++ b/arch/m68k/include/asm/bug_no.h
diff --git a/arch/m68k/include/asm/bugs.h b/arch/m68k/include/asm/bugs.h
new file mode 100644
index 000000000000..01f047d784ec
--- /dev/null
+++ b/arch/m68k/include/asm/bugs.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "bugs_no.h"
+#else
+#include "bugs_mm.h"
+#endif
diff --git a/include/asm-m68k/bugs.h b/arch/m68k/include/asm/bugs_mm.h
index d01935592410..d01935592410 100644
--- a/include/asm-m68k/bugs.h
+++ b/arch/m68k/include/asm/bugs_mm.h
diff --git a/arch/m68knommu/include/asm/bugs.h b/arch/m68k/include/asm/bugs_no.h
index 5f382dac3a60..5f382dac3a60 100644
--- a/arch/m68knommu/include/asm/bugs.h
+++ b/arch/m68k/include/asm/bugs_no.h
diff --git a/include/asm-m68k/bvme6000hw.h b/arch/m68k/include/asm/bvme6000hw.h
index f40d2f8510ee..f40d2f8510ee 100644
--- a/include/asm-m68k/bvme6000hw.h
+++ b/arch/m68k/include/asm/bvme6000hw.h
diff --git a/arch/m68k/include/asm/byteorder.h b/arch/m68k/include/asm/byteorder.h
new file mode 100644
index 000000000000..31b260a88803
--- /dev/null
+++ b/arch/m68k/include/asm/byteorder.h
@@ -0,0 +1,6 @@
+#ifndef _M68K_BYTEORDER_H
+#define _M68K_BYTEORDER_H
+
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _M68K_BYTEORDER_H */
diff --git a/arch/m68k/include/asm/cache.h b/arch/m68k/include/asm/cache.h
new file mode 100644
index 000000000000..599c29bc8f40
--- /dev/null
+++ b/arch/m68k/include/asm/cache.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "cache_no.h"
+#else
+#include "cache_mm.h"
+#endif
diff --git a/include/asm-m68k/cache.h b/arch/m68k/include/asm/cache_mm.h
index fed3fd30de7e..fed3fd30de7e 100644
--- a/include/asm-m68k/cache.h
+++ b/arch/m68k/include/asm/cache_mm.h
diff --git a/arch/m68knommu/include/asm/cache.h b/arch/m68k/include/asm/cache_no.h
index 24e9eace5f8c..24e9eace5f8c 100644
--- a/arch/m68knommu/include/asm/cache.h
+++ b/arch/m68k/include/asm/cache_no.h
diff --git a/include/asm-m68k/cachectl.h b/arch/m68k/include/asm/cachectl.h
index 525978e959e3..525978e959e3 100644
--- a/include/asm-m68k/cachectl.h
+++ b/arch/m68k/include/asm/cachectl.h
diff --git a/arch/m68k/include/asm/cacheflush.h b/arch/m68k/include/asm/cacheflush.h
new file mode 100644
index 000000000000..a70d7319630a
--- /dev/null
+++ b/arch/m68k/include/asm/cacheflush.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "cacheflush_no.h"
+#else
+#include "cacheflush_mm.h"
+#endif
diff --git a/include/asm-m68k/cacheflush.h b/arch/m68k/include/asm/cacheflush_mm.h
index 16bf375fdbe1..16bf375fdbe1 100644
--- a/include/asm-m68k/cacheflush.h
+++ b/arch/m68k/include/asm/cacheflush_mm.h
diff --git a/arch/m68knommu/include/asm/cacheflush.h b/arch/m68k/include/asm/cacheflush_no.h
index 87e5dc0413b4..c65f00a94553 100644
--- a/arch/m68knommu/include/asm/cacheflush.h
+++ b/arch/m68k/include/asm/cacheflush_no.h
@@ -51,13 +51,20 @@ static inline void __flush_cache_all(void)
"movec %%d0,%%CACR\n\t"
: : : "d0", "a0" );
#endif /* CONFIG_M5407 */
-#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x)
+ __asm__ __volatile__ (
+ "movel #0x81400100, %%d0\n\t"
+ "movec %%d0, %%CACR\n\t"
+ "nop\n\t"
+ : : : "d0" );
+#endif /* CONFIG_M523x || CONFIG_M527x */
+#if defined(CONFIG_M528x)
__asm__ __volatile__ (
"movel #0x81000200, %%d0\n\t"
"movec %%d0, %%CACR\n\t"
"nop\n\t"
: : : "d0" );
-#endif /* CONFIG_M527x || CONFIG_M528x */
+#endif /* CONFIG_M528x */
#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || defined(CONFIG_M5272)
__asm__ __volatile__ (
"movel #0x81000100, %%d0\n\t"
diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h
new file mode 100644
index 000000000000..1cf544767453
--- /dev/null
+++ b/arch/m68k/include/asm/checksum.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "checksum_no.h"
+#else
+#include "checksum_mm.h"
+#endif
diff --git a/include/asm-m68k/checksum.h b/arch/m68k/include/asm/checksum_mm.h
index 494f9aec37ea..494f9aec37ea 100644
--- a/include/asm-m68k/checksum.h
+++ b/arch/m68k/include/asm/checksum_mm.h
diff --git a/arch/m68knommu/include/asm/checksum.h b/arch/m68k/include/asm/checksum_no.h
index 81883482ffb1..81883482ffb1 100644
--- a/arch/m68knommu/include/asm/checksum.h
+++ b/arch/m68k/include/asm/checksum_no.h
diff --git a/arch/m68knommu/include/asm/coldfire.h b/arch/m68k/include/asm/coldfire.h
index 83a9fa4e618a..83a9fa4e618a 100644
--- a/arch/m68knommu/include/asm/coldfire.h
+++ b/arch/m68k/include/asm/coldfire.h
diff --git a/arch/m68knommu/include/asm/commproc.h b/arch/m68k/include/asm/commproc.h
index edf5eb6c08d2..edf5eb6c08d2 100644
--- a/arch/m68knommu/include/asm/commproc.h
+++ b/arch/m68k/include/asm/commproc.h
diff --git a/include/asm-m68k/contregs.h b/arch/m68k/include/asm/contregs.h
index d1ea750bddfe..d1ea750bddfe 100644
--- a/include/asm-m68k/contregs.h
+++ b/arch/m68k/include/asm/contregs.h
diff --git a/include/asm-m68k/cputime.h b/arch/m68k/include/asm/cputime.h
index c79c5e892305..c79c5e892305 100644
--- a/include/asm-m68k/cputime.h
+++ b/arch/m68k/include/asm/cputime.h
diff --git a/arch/m68k/include/asm/current.h b/arch/m68k/include/asm/current.h
new file mode 100644
index 000000000000..51b056dfaedd
--- /dev/null
+++ b/arch/m68k/include/asm/current.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "current_no.h"
+#else
+#include "current_mm.h"
+#endif
diff --git a/include/asm-m68k/current.h b/arch/m68k/include/asm/current_mm.h
index 8de8f8ceda61..8de8f8ceda61 100644
--- a/include/asm-m68k/current.h
+++ b/arch/m68k/include/asm/current_mm.h
diff --git a/arch/m68knommu/include/asm/current.h b/arch/m68k/include/asm/current_no.h
index 53ee0f9f7cef..53ee0f9f7cef 100644
--- a/arch/m68knommu/include/asm/current.h
+++ b/arch/m68k/include/asm/current_no.h
diff --git a/arch/m68knommu/include/asm/dbg.h b/arch/m68k/include/asm/dbg.h
index 27af3270f671..27af3270f671 100644
--- a/arch/m68knommu/include/asm/dbg.h
+++ b/arch/m68k/include/asm/dbg.h
diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h
new file mode 100644
index 000000000000..d2598e3dd7b2
--- /dev/null
+++ b/arch/m68k/include/asm/delay.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "delay_no.h"
+#else
+#include "delay_mm.h"
+#endif
diff --git a/include/asm-m68k/delay.h b/arch/m68k/include/asm/delay_mm.h
index 5ed92851bc6f..5ed92851bc6f 100644
--- a/include/asm-m68k/delay.h
+++ b/arch/m68k/include/asm/delay_mm.h
diff --git a/arch/m68knommu/include/asm/delay.h b/arch/m68k/include/asm/delay_no.h
index 55cbd6294ab6..55cbd6294ab6 100644
--- a/arch/m68knommu/include/asm/delay.h
+++ b/arch/m68k/include/asm/delay_no.h
diff --git a/arch/m68knommu/include/asm/device.h b/arch/m68k/include/asm/device.h
index d8f9872b0e2d..d8f9872b0e2d 100644
--- a/arch/m68knommu/include/asm/device.h
+++ b/arch/m68k/include/asm/device.h
diff --git a/arch/m68k/include/asm/div64.h b/arch/m68k/include/asm/div64.h
new file mode 100644
index 000000000000..d211d9f54276
--- /dev/null
+++ b/arch/m68k/include/asm/div64.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "div64_no.h"
+#else
+#include "div64_mm.h"
+#endif
diff --git a/include/asm-m68k/div64.h b/arch/m68k/include/asm/div64_mm.h
index 8243c931b5c0..8243c931b5c0 100644
--- a/include/asm-m68k/div64.h
+++ b/arch/m68k/include/asm/div64_mm.h
diff --git a/arch/m68knommu/include/asm/div64.h b/arch/m68k/include/asm/div64_no.h
index 6cd978cefb28..6cd978cefb28 100644
--- a/arch/m68knommu/include/asm/div64.h
+++ b/arch/m68k/include/asm/div64_no.h
diff --git a/arch/m68k/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping.h
new file mode 100644
index 000000000000..f4a4c7638f89
--- /dev/null
+++ b/arch/m68k/include/asm/dma-mapping.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "dma-mapping_no.h"
+#else
+#include "dma-mapping_mm.h"
+#endif
diff --git a/include/asm-m68k/dma-mapping.h b/arch/m68k/include/asm/dma-mapping_mm.h
index 26f505488c11..26f505488c11 100644
--- a/include/asm-m68k/dma-mapping.h
+++ b/arch/m68k/include/asm/dma-mapping_mm.h
diff --git a/arch/m68knommu/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping_no.h
index 6aeab18e58bd..1748f2bca940 100644
--- a/arch/m68knommu/include/asm/dma-mapping.h
+++ b/arch/m68k/include/asm/dma-mapping_no.h
@@ -1,10 +1,6 @@
#ifndef _M68KNOMMU_DMA_MAPPING_H
#define _M68KNOMMU_DMA_MAPPING_H
-#ifdef CONFIG_PCI
-#include <asm-generic/dma-mapping.h>
-#else
#include <asm-generic/dma-mapping-broken.h>
-#endif
#endif /* _M68KNOMMU_DMA_MAPPING_H */
diff --git a/arch/m68k/include/asm/dma.h b/arch/m68k/include/asm/dma.h
new file mode 100644
index 000000000000..b82e660cf1c2
--- /dev/null
+++ b/arch/m68k/include/asm/dma.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "dma_no.h"
+#else
+#include "dma_mm.h"
+#endif
diff --git a/include/asm-m68k/dma.h b/arch/m68k/include/asm/dma_mm.h
index 4240fbc946f8..4240fbc946f8 100644
--- a/include/asm-m68k/dma.h
+++ b/arch/m68k/include/asm/dma_mm.h
diff --git a/arch/m68knommu/include/asm/dma.h b/arch/m68k/include/asm/dma_no.h
index 939a02056217..939a02056217 100644
--- a/arch/m68knommu/include/asm/dma.h
+++ b/arch/m68k/include/asm/dma_no.h
diff --git a/include/asm-m68k/dsp56k.h b/arch/m68k/include/asm/dsp56k.h
index 2d8c0c9f794b..2d8c0c9f794b 100644
--- a/include/asm-m68k/dsp56k.h
+++ b/arch/m68k/include/asm/dsp56k.h
diff --git a/include/asm-m68k/dvma.h b/arch/m68k/include/asm/dvma.h
index 890bbf7e7758..890bbf7e7758 100644
--- a/include/asm-m68k/dvma.h
+++ b/arch/m68k/include/asm/dvma.h
diff --git a/arch/m68k/include/asm/elf.h b/arch/m68k/include/asm/elf.h
new file mode 100644
index 000000000000..04ce488bc63f
--- /dev/null
+++ b/arch/m68k/include/asm/elf.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "elf_no.h"
+#else
+#include "elf_mm.h"
+#endif
diff --git a/include/asm-m68k/elf.h b/arch/m68k/include/asm/elf_mm.h
index 0b0f49eb876b..0b0f49eb876b 100644
--- a/include/asm-m68k/elf.h
+++ b/arch/m68k/include/asm/elf_mm.h
diff --git a/arch/m68knommu/include/asm/elf.h b/arch/m68k/include/asm/elf_no.h
index b8046837f384..b8046837f384 100644
--- a/arch/m68knommu/include/asm/elf.h
+++ b/arch/m68k/include/asm/elf_no.h
diff --git a/arch/m68knommu/include/asm/elia.h b/arch/m68k/include/asm/elia.h
index e037d4e2de33..e037d4e2de33 100644
--- a/arch/m68knommu/include/asm/elia.h
+++ b/arch/m68k/include/asm/elia.h
diff --git a/arch/m68knommu/include/asm/emergency-restart.h b/arch/m68k/include/asm/emergency-restart.h
index 108d8c48e42e..108d8c48e42e 100644
--- a/arch/m68knommu/include/asm/emergency-restart.h
+++ b/arch/m68k/include/asm/emergency-restart.h
diff --git a/arch/m68k/include/asm/entry.h b/arch/m68k/include/asm/entry.h
new file mode 100644
index 000000000000..876eec6f2b52
--- /dev/null
+++ b/arch/m68k/include/asm/entry.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "entry_no.h"
+#else
+#include "entry_mm.h"
+#endif
diff --git a/include/asm-m68k/entry.h b/arch/m68k/include/asm/entry_mm.h
index 5202f5a5b420..5202f5a5b420 100644
--- a/include/asm-m68k/entry.h
+++ b/arch/m68k/include/asm/entry_mm.h
diff --git a/arch/m68knommu/include/asm/entry.h b/arch/m68k/include/asm/entry_no.h
index c2553d26273d..c2553d26273d 100644
--- a/arch/m68knommu/include/asm/entry.h
+++ b/arch/m68k/include/asm/entry_no.h
diff --git a/include/asm-m68k/errno.h b/arch/m68k/include/asm/errno.h
index 0d4e188d6ef6..0d4e188d6ef6 100644
--- a/include/asm-m68k/errno.h
+++ b/arch/m68k/include/asm/errno.h
diff --git a/arch/m68k/include/asm/fb.h b/arch/m68k/include/asm/fb.h
new file mode 100644
index 000000000000..97bcaefd2064
--- /dev/null
+++ b/arch/m68k/include/asm/fb.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "fb_no.h"
+#else
+#include "fb_mm.h"
+#endif
diff --git a/include/asm-m68k/fb.h b/arch/m68k/include/asm/fb_mm.h
index 380b97ae8157..380b97ae8157 100644
--- a/include/asm-m68k/fb.h
+++ b/arch/m68k/include/asm/fb_mm.h
diff --git a/arch/m68knommu/include/asm/fb.h b/arch/m68k/include/asm/fb_no.h
index c7df38030992..c7df38030992 100644
--- a/arch/m68knommu/include/asm/fb.h
+++ b/arch/m68k/include/asm/fb_no.h
diff --git a/include/asm-m68k/fbio.h b/arch/m68k/include/asm/fbio.h
index b9215a0907d3..b9215a0907d3 100644
--- a/include/asm-m68k/fbio.h
+++ b/arch/m68k/include/asm/fbio.h
diff --git a/include/asm-m68k/fcntl.h b/arch/m68k/include/asm/fcntl.h
index 1c369b20dc45..1c369b20dc45 100644
--- a/include/asm-m68k/fcntl.h
+++ b/arch/m68k/include/asm/fcntl.h
diff --git a/arch/m68knommu/include/asm/flat.h b/arch/m68k/include/asm/flat.h
index 814b5174a8e0..814b5174a8e0 100644
--- a/arch/m68knommu/include/asm/flat.h
+++ b/arch/m68k/include/asm/flat.h
diff --git a/include/asm-m68k/floppy.h b/arch/m68k/include/asm/floppy.h
index 697d50393dd0..697d50393dd0 100644
--- a/include/asm-m68k/floppy.h
+++ b/arch/m68k/include/asm/floppy.h
diff --git a/arch/m68k/include/asm/fpu.h b/arch/m68k/include/asm/fpu.h
new file mode 100644
index 000000000000..e19bc5ed9c37
--- /dev/null
+++ b/arch/m68k/include/asm/fpu.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "fpu_no.h"
+#else
+#include "fpu_mm.h"
+#endif
diff --git a/include/asm-m68k/fpu.h b/arch/m68k/include/asm/fpu_mm.h
index ffb6b8cfc6d5..ffb6b8cfc6d5 100644
--- a/include/asm-m68k/fpu.h
+++ b/arch/m68k/include/asm/fpu_mm.h
diff --git a/arch/m68knommu/include/asm/fpu.h b/arch/m68k/include/asm/fpu_no.h
index b16b2e4fca2a..b16b2e4fca2a 100644
--- a/arch/m68knommu/include/asm/fpu.h
+++ b/arch/m68k/include/asm/fpu_no.h
diff --git a/arch/m68knommu/include/asm/futex.h b/arch/m68k/include/asm/futex.h
index 6a332a9f099c..6a332a9f099c 100644
--- a/arch/m68knommu/include/asm/futex.h
+++ b/arch/m68k/include/asm/futex.h
diff --git a/arch/m68k/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq.h
new file mode 100644
index 000000000000..56d0d5db231c
--- /dev/null
+++ b/arch/m68k/include/asm/hardirq.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "hardirq_no.h"
+#else
+#include "hardirq_mm.h"
+#endif
diff --git a/include/asm-m68k/hardirq.h b/arch/m68k/include/asm/hardirq_mm.h
index 394ee946015c..394ee946015c 100644
--- a/include/asm-m68k/hardirq.h
+++ b/arch/m68k/include/asm/hardirq_mm.h
diff --git a/arch/m68knommu/include/asm/hardirq.h b/arch/m68k/include/asm/hardirq_no.h
index bfad28149a49..bfad28149a49 100644
--- a/arch/m68knommu/include/asm/hardirq.h
+++ b/arch/m68k/include/asm/hardirq_no.h
diff --git a/include/asm-m68k/hp300hw.h b/arch/m68k/include/asm/hp300hw.h
index d998ea67c19c..d998ea67c19c 100644
--- a/include/asm-m68k/hp300hw.h
+++ b/arch/m68k/include/asm/hp300hw.h
diff --git a/arch/m68k/include/asm/hw_irq.h b/arch/m68k/include/asm/hw_irq.h
new file mode 100644
index 000000000000..e19526015890
--- /dev/null
+++ b/arch/m68k/include/asm/hw_irq.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "hw_irq_no.h"
+#else
+#include "hw_irq_mm.h"
+#endif
diff --git a/include/asm-m68k/hw_irq.h b/arch/m68k/include/asm/hw_irq_mm.h
index eacef0951fbf..eacef0951fbf 100644
--- a/include/asm-m68k/hw_irq.h
+++ b/arch/m68k/include/asm/hw_irq_mm.h
diff --git a/arch/m68knommu/include/asm/hw_irq.h b/arch/m68k/include/asm/hw_irq_no.h
index f3ec9e5ae049..f3ec9e5ae049 100644
--- a/arch/m68knommu/include/asm/hw_irq.h
+++ b/arch/m68k/include/asm/hw_irq_no.h
diff --git a/include/asm-m68k/hwtest.h b/arch/m68k/include/asm/hwtest.h
index 402c8a4401fe..402c8a4401fe 100644
--- a/include/asm-m68k/hwtest.h
+++ b/arch/m68k/include/asm/hwtest.h
diff --git a/include/asm-m68k/ide.h b/arch/m68k/include/asm/ide.h
index b996a3c8cff5..b996a3c8cff5 100644
--- a/include/asm-m68k/ide.h
+++ b/arch/m68k/include/asm/ide.h
diff --git a/include/asm-m68k/idprom.h b/arch/m68k/include/asm/idprom.h
index 160616a89e05..160616a89e05 100644
--- a/include/asm-m68k/idprom.h
+++ b/arch/m68k/include/asm/idprom.h
diff --git a/include/asm-m68k/intersil.h b/arch/m68k/include/asm/intersil.h
index f482902cac8a..f482902cac8a 100644
--- a/include/asm-m68k/intersil.h
+++ b/arch/m68k/include/asm/intersil.h
diff --git a/arch/m68k/include/asm/io.h b/arch/m68k/include/asm/io.h
new file mode 100644
index 000000000000..c7210ba184ea
--- /dev/null
+++ b/arch/m68k/include/asm/io.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "io_no.h"
+#else
+#include "io_mm.h"
+#endif
diff --git a/include/asm-m68k/io.h b/arch/m68k/include/asm/io_mm.h
index 9e673e3bd434..9e673e3bd434 100644
--- a/include/asm-m68k/io.h
+++ b/arch/m68k/include/asm/io_mm.h
diff --git a/arch/m68knommu/include/asm/io.h b/arch/m68k/include/asm/io_no.h
index 6adef1ee2082..6adef1ee2082 100644
--- a/arch/m68knommu/include/asm/io.h
+++ b/arch/m68k/include/asm/io_no.h
diff --git a/arch/m68knommu/include/asm/ioctl.h b/arch/m68k/include/asm/ioctl.h
index b279fe06dfe5..b279fe06dfe5 100644
--- a/arch/m68knommu/include/asm/ioctl.h
+++ b/arch/m68k/include/asm/ioctl.h
diff --git a/include/asm-m68k/ioctls.h b/arch/m68k/include/asm/ioctls.h
index b8d2f4be7fd7..b8d2f4be7fd7 100644
--- a/include/asm-m68k/ioctls.h
+++ b/arch/m68k/include/asm/ioctls.h
diff --git a/include/asm-m68k/ipcbuf.h b/arch/m68k/include/asm/ipcbuf.h
index a623ea3f0955..a623ea3f0955 100644
--- a/include/asm-m68k/ipcbuf.h
+++ b/arch/m68k/include/asm/ipcbuf.h
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
new file mode 100644
index 000000000000..d031416595b2
--- /dev/null
+++ b/arch/m68k/include/asm/irq.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "irq_no.h"
+#else
+#include "irq_mm.h"
+#endif
diff --git a/include/asm-m68k/irq.h b/arch/m68k/include/asm/irq_mm.h
index 226bfc0f21b1..226bfc0f21b1 100644
--- a/include/asm-m68k/irq.h
+++ b/arch/m68k/include/asm/irq_mm.h
diff --git a/arch/m68knommu/include/asm/irq.h b/arch/m68k/include/asm/irq_no.h
index 9373c31ac87d..9373c31ac87d 100644
--- a/arch/m68knommu/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq_no.h
diff --git a/arch/m68knommu/include/asm/irq_regs.h b/arch/m68k/include/asm/irq_regs.h
index 3dd9c0b70270..3dd9c0b70270 100644
--- a/arch/m68knommu/include/asm/irq_regs.h
+++ b/arch/m68k/include/asm/irq_regs.h
diff --git a/arch/m68knommu/include/asm/kdebug.h b/arch/m68k/include/asm/kdebug.h
index 6ece1b037665..6ece1b037665 100644
--- a/arch/m68knommu/include/asm/kdebug.h
+++ b/arch/m68k/include/asm/kdebug.h
diff --git a/arch/m68k/include/asm/kmap_types.h b/arch/m68k/include/asm/kmap_types.h
new file mode 100644
index 000000000000..045d9fd122a2
--- /dev/null
+++ b/arch/m68k/include/asm/kmap_types.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "kmap_types_no.h"
+#else
+#include "kmap_types_mm.h"
+#endif
diff --git a/include/asm-m68k/kmap_types.h b/arch/m68k/include/asm/kmap_types_mm.h
index c843c63d3801..c843c63d3801 100644
--- a/include/asm-m68k/kmap_types.h
+++ b/arch/m68k/include/asm/kmap_types_mm.h
diff --git a/arch/m68knommu/include/asm/kmap_types.h b/arch/m68k/include/asm/kmap_types_no.h
index bfb6707575d1..bfb6707575d1 100644
--- a/arch/m68knommu/include/asm/kmap_types.h
+++ b/arch/m68k/include/asm/kmap_types_no.h
diff --git a/include/asm-m68k/linkage.h b/arch/m68k/include/asm/linkage.h
index 5a822bb790f7..5a822bb790f7 100644
--- a/include/asm-m68k/linkage.h
+++ b/arch/m68k/include/asm/linkage.h
diff --git a/include/asm-m68k/local.h b/arch/m68k/include/asm/local.h
index 6c259263e1f0..6c259263e1f0 100644
--- a/include/asm-m68k/local.h
+++ b/arch/m68k/include/asm/local.h
diff --git a/arch/m68knommu/include/asm/m5206sim.h b/arch/m68k/include/asm/m5206sim.h
index 7e3594dea88b..7e3594dea88b 100644
--- a/arch/m68knommu/include/asm/m5206sim.h
+++ b/arch/m68k/include/asm/m5206sim.h
diff --git a/arch/m68knommu/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h
index 49d016e6391a..49d016e6391a 100644
--- a/arch/m68knommu/include/asm/m520xsim.h
+++ b/arch/m68k/include/asm/m520xsim.h
diff --git a/arch/m68knommu/include/asm/m523xsim.h b/arch/m68k/include/asm/m523xsim.h
index bf397313e93f..bf397313e93f 100644
--- a/arch/m68knommu/include/asm/m523xsim.h
+++ b/arch/m68k/include/asm/m523xsim.h
diff --git a/arch/m68knommu/include/asm/m5249sim.h b/arch/m68k/include/asm/m5249sim.h
index 366eb8602d2f..366eb8602d2f 100644
--- a/arch/m68knommu/include/asm/m5249sim.h
+++ b/arch/m68k/include/asm/m5249sim.h
diff --git a/arch/m68knommu/include/asm/m5272sim.h b/arch/m68k/include/asm/m5272sim.h
index 6217edc21139..6217edc21139 100644
--- a/arch/m68knommu/include/asm/m5272sim.h
+++ b/arch/m68k/include/asm/m5272sim.h
diff --git a/arch/m68knommu/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h
index 1f63ab3fb3e6..1f63ab3fb3e6 100644
--- a/arch/m68knommu/include/asm/m527xsim.h
+++ b/arch/m68k/include/asm/m527xsim.h
diff --git a/arch/m68knommu/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h
index 28bf783a5d6d..28bf783a5d6d 100644
--- a/arch/m68knommu/include/asm/m528xsim.h
+++ b/arch/m68k/include/asm/m528xsim.h
diff --git a/arch/m68knommu/include/asm/m5307sim.h b/arch/m68k/include/asm/m5307sim.h
index 5886728409c0..5886728409c0 100644
--- a/arch/m68knommu/include/asm/m5307sim.h
+++ b/arch/m68k/include/asm/m5307sim.h
diff --git a/arch/m68knommu/include/asm/m532xsim.h b/arch/m68k/include/asm/m532xsim.h
index 1835fd20a82c..1835fd20a82c 100644
--- a/arch/m68knommu/include/asm/m532xsim.h
+++ b/arch/m68k/include/asm/m532xsim.h
diff --git a/arch/m68knommu/include/asm/m5407sim.h b/arch/m68k/include/asm/m5407sim.h
index cc22c4a53005..cc22c4a53005 100644
--- a/arch/m68knommu/include/asm/m5407sim.h
+++ b/arch/m68k/include/asm/m5407sim.h
diff --git a/arch/m68knommu/include/asm/m68360.h b/arch/m68k/include/asm/m68360.h
index eb7d39ef2855..eb7d39ef2855 100644
--- a/arch/m68knommu/include/asm/m68360.h
+++ b/arch/m68k/include/asm/m68360.h
diff --git a/arch/m68knommu/include/asm/m68360_enet.h b/arch/m68k/include/asm/m68360_enet.h
index c36f4d059203..c36f4d059203 100644
--- a/arch/m68knommu/include/asm/m68360_enet.h
+++ b/arch/m68k/include/asm/m68360_enet.h
diff --git a/arch/m68knommu/include/asm/m68360_pram.h b/arch/m68k/include/asm/m68360_pram.h
index e6088bbce93d..e6088bbce93d 100644
--- a/arch/m68knommu/include/asm/m68360_pram.h
+++ b/arch/m68k/include/asm/m68360_pram.h
diff --git a/arch/m68knommu/include/asm/m68360_quicc.h b/arch/m68k/include/asm/m68360_quicc.h
index 6d40f4d18e10..6d40f4d18e10 100644
--- a/arch/m68knommu/include/asm/m68360_quicc.h
+++ b/arch/m68k/include/asm/m68360_quicc.h
diff --git a/arch/m68knommu/include/asm/m68360_regs.h b/arch/m68k/include/asm/m68360_regs.h
index d57217ca4f27..d57217ca4f27 100644
--- a/arch/m68knommu/include/asm/m68360_regs.h
+++ b/arch/m68k/include/asm/m68360_regs.h
diff --git a/include/asm-m68k/mac_asc.h b/arch/m68k/include/asm/mac_asc.h
index fc2e5467b41e..fc2e5467b41e 100644
--- a/include/asm-m68k/mac_asc.h
+++ b/arch/m68k/include/asm/mac_asc.h
diff --git a/include/asm-m68k/mac_baboon.h b/arch/m68k/include/asm/mac_baboon.h
index c2a042b8c349..c2a042b8c349 100644
--- a/include/asm-m68k/mac_baboon.h
+++ b/arch/m68k/include/asm/mac_baboon.h
diff --git a/include/asm-m68k/mac_iop.h b/arch/m68k/include/asm/mac_iop.h
index a2c7e6fcca38..a2c7e6fcca38 100644
--- a/include/asm-m68k/mac_iop.h
+++ b/arch/m68k/include/asm/mac_iop.h
diff --git a/include/asm-m68k/mac_mouse.h b/arch/m68k/include/asm/mac_mouse.h
index 39a5c292eaee..39a5c292eaee 100644
--- a/include/asm-m68k/mac_mouse.h
+++ b/arch/m68k/include/asm/mac_mouse.h
diff --git a/include/asm-m68k/mac_oss.h b/arch/m68k/include/asm/mac_oss.h
index 7221f7251934..7221f7251934 100644
--- a/include/asm-m68k/mac_oss.h
+++ b/arch/m68k/include/asm/mac_oss.h
diff --git a/include/asm-m68k/mac_psc.h b/arch/m68k/include/asm/mac_psc.h
index 7808bb0b2323..7808bb0b2323 100644
--- a/include/asm-m68k/mac_psc.h
+++ b/arch/m68k/include/asm/mac_psc.h
diff --git a/include/asm-m68k/mac_via.h b/arch/m68k/include/asm/mac_via.h
index 39afb438b656..39afb438b656 100644
--- a/include/asm-m68k/mac_via.h
+++ b/arch/m68k/include/asm/mac_via.h
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
new file mode 100644
index 000000000000..fc24b6fc5508
--- /dev/null
+++ b/arch/m68k/include/asm/machdep.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "machdep_no.h"
+#else
+#include "machdep_mm.h"
+#endif
diff --git a/include/asm-m68k/machdep.h b/arch/m68k/include/asm/machdep_mm.h
index 5637dcef314e..5637dcef314e 100644
--- a/include/asm-m68k/machdep.h
+++ b/arch/m68k/include/asm/machdep_mm.h
diff --git a/arch/m68knommu/include/asm/machdep.h b/arch/m68k/include/asm/machdep_no.h
index de9f47a51cc2..de9f47a51cc2 100644
--- a/arch/m68knommu/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep_no.h
diff --git a/include/asm-m68k/machines.h b/arch/m68k/include/asm/machines.h
index be667e84f01b..be667e84f01b 100644
--- a/include/asm-m68k/machines.h
+++ b/arch/m68k/include/asm/machines.h
diff --git a/include/asm-m68k/machw.h b/arch/m68k/include/asm/machw.h
index 2b4de0c2ce4a..2b4de0c2ce4a 100644
--- a/include/asm-m68k/machw.h
+++ b/arch/m68k/include/asm/machw.h
diff --git a/include/asm-m68k/macintosh.h b/arch/m68k/include/asm/macintosh.h
index 05309f7e3d06..05309f7e3d06 100644
--- a/include/asm-m68k/macintosh.h
+++ b/arch/m68k/include/asm/macintosh.h
diff --git a/include/asm-m68k/macints.h b/arch/m68k/include/asm/macints.h
index 679c48ab4407..679c48ab4407 100644
--- a/include/asm-m68k/macints.h
+++ b/arch/m68k/include/asm/macints.h
diff --git a/include/asm-m68k/math-emu.h b/arch/m68k/include/asm/math-emu.h
index ddfab96403cb..ddfab96403cb 100644
--- a/include/asm-m68k/math-emu.h
+++ b/arch/m68k/include/asm/math-emu.h
diff --git a/arch/m68k/include/asm/mc146818rtc.h b/arch/m68k/include/asm/mc146818rtc.h
new file mode 100644
index 000000000000..fb90dcf78426
--- /dev/null
+++ b/arch/m68k/include/asm/mc146818rtc.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "mc146818rtc_no.h"
+#else
+#include "mc146818rtc_mm.h"
+#endif
diff --git a/include/asm-m68k/mc146818rtc.h b/arch/m68k/include/asm/mc146818rtc_mm.h
index 9f70a01f73dc..9f70a01f73dc 100644
--- a/include/asm-m68k/mc146818rtc.h
+++ b/arch/m68k/include/asm/mc146818rtc_mm.h
diff --git a/arch/m68knommu/include/asm/mc146818rtc.h b/arch/m68k/include/asm/mc146818rtc_no.h
index 907a0481a140..907a0481a140 100644
--- a/arch/m68knommu/include/asm/mc146818rtc.h
+++ b/arch/m68k/include/asm/mc146818rtc_no.h
diff --git a/arch/m68knommu/include/asm/mcfcache.h b/arch/m68k/include/asm/mcfcache.h
index c042634fadaa..c042634fadaa 100644
--- a/arch/m68knommu/include/asm/mcfcache.h
+++ b/arch/m68k/include/asm/mcfcache.h
diff --git a/arch/m68knommu/include/asm/mcfdma.h b/arch/m68k/include/asm/mcfdma.h
index 705c52c79cd8..705c52c79cd8 100644
--- a/arch/m68knommu/include/asm/mcfdma.h
+++ b/arch/m68k/include/asm/mcfdma.h
diff --git a/arch/m68knommu/include/asm/mcfmbus.h b/arch/m68k/include/asm/mcfmbus.h
index 319899c47a2c..319899c47a2c 100644
--- a/arch/m68knommu/include/asm/mcfmbus.h
+++ b/arch/m68k/include/asm/mcfmbus.h
diff --git a/arch/m68knommu/include/asm/mcfne.h b/arch/m68k/include/asm/mcfne.h
index 431f63aadd0e..431f63aadd0e 100644
--- a/arch/m68knommu/include/asm/mcfne.h
+++ b/arch/m68k/include/asm/mcfne.h
diff --git a/arch/m68knommu/include/asm/mcfpci.h b/arch/m68k/include/asm/mcfpci.h
index f1507dd06ec6..f1507dd06ec6 100644
--- a/arch/m68knommu/include/asm/mcfpci.h
+++ b/arch/m68k/include/asm/mcfpci.h
diff --git a/arch/m68knommu/include/asm/mcfpit.h b/arch/m68k/include/asm/mcfpit.h
index f570cf64fd29..f570cf64fd29 100644
--- a/arch/m68knommu/include/asm/mcfpit.h
+++ b/arch/m68k/include/asm/mcfpit.h
diff --git a/arch/m68knommu/include/asm/mcfsim.h b/arch/m68k/include/asm/mcfsim.h
index da3f2ceff3a4..da3f2ceff3a4 100644
--- a/arch/m68knommu/include/asm/mcfsim.h
+++ b/arch/m68k/include/asm/mcfsim.h
diff --git a/arch/m68knommu/include/asm/mcfsmc.h b/arch/m68k/include/asm/mcfsmc.h
index 2d7a4dbd9683..2d7a4dbd9683 100644
--- a/arch/m68knommu/include/asm/mcfsmc.h
+++ b/arch/m68k/include/asm/mcfsmc.h
diff --git a/arch/m68knommu/include/asm/mcftimer.h b/arch/m68k/include/asm/mcftimer.h
index 0f90f6d2227a..0f90f6d2227a 100644
--- a/arch/m68knommu/include/asm/mcftimer.h
+++ b/arch/m68k/include/asm/mcftimer.h
diff --git a/arch/m68knommu/include/asm/mcfuart.h b/arch/m68k/include/asm/mcfuart.h
index ef2293873612..ef2293873612 100644
--- a/arch/m68knommu/include/asm/mcfuart.h
+++ b/arch/m68k/include/asm/mcfuart.h
diff --git a/arch/m68knommu/include/asm/mcfwdebug.h b/arch/m68k/include/asm/mcfwdebug.h
index 27f70e45d700..27f70e45d700 100644
--- a/arch/m68knommu/include/asm/mcfwdebug.h
+++ b/arch/m68k/include/asm/mcfwdebug.h
diff --git a/include/asm-m68k/md.h b/arch/m68k/include/asm/md.h
index d2f78f226f3d..d2f78f226f3d 100644
--- a/include/asm-m68k/md.h
+++ b/arch/m68k/include/asm/md.h
diff --git a/include/asm-m68k/mman.h b/arch/m68k/include/asm/mman.h
index 1626d37f4898..1626d37f4898 100644
--- a/include/asm-m68k/mman.h
+++ b/arch/m68k/include/asm/mman.h
diff --git a/arch/m68k/include/asm/mmu.h b/arch/m68k/include/asm/mmu.h
new file mode 100644
index 000000000000..a81d3946675f
--- /dev/null
+++ b/arch/m68k/include/asm/mmu.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "mmu_no.h"
+#else
+#include "mmu_mm.h"
+#endif
diff --git a/arch/m68k/include/asm/mmu_context.h b/arch/m68k/include/asm/mmu_context.h
new file mode 100644
index 000000000000..b440928fc6c7
--- /dev/null
+++ b/arch/m68k/include/asm/mmu_context.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "mmu_context_no.h"
+#else
+#include "mmu_context_mm.h"
+#endif
diff --git a/include/asm-m68k/mmu_context.h b/arch/m68k/include/asm/mmu_context_mm.h
index 894dacbcee14..894dacbcee14 100644
--- a/include/asm-m68k/mmu_context.h
+++ b/arch/m68k/include/asm/mmu_context_mm.h
diff --git a/arch/m68knommu/include/asm/mmu_context.h b/arch/m68k/include/asm/mmu_context_no.h
index 9ccee4278c97..9ccee4278c97 100644
--- a/arch/m68knommu/include/asm/mmu_context.h
+++ b/arch/m68k/include/asm/mmu_context_no.h
diff --git a/include/asm-m68k/mmu.h b/arch/m68k/include/asm/mmu_mm.h
index ccd36d26615a..ccd36d26615a 100644
--- a/include/asm-m68k/mmu.h
+++ b/arch/m68k/include/asm/mmu_mm.h
diff --git a/arch/m68knommu/include/asm/mmu.h b/arch/m68k/include/asm/mmu_no.h
index 5fa6b68353ba..e2da1e6f09fe 100644
--- a/arch/m68knommu/include/asm/mmu.h
+++ b/arch/m68k/include/asm/mmu_no.h
@@ -4,7 +4,6 @@
/* Copyright (C) 2002, David McCullough <davidm@snapgear.com> */
typedef struct {
- struct vm_list_struct *vmlist;
unsigned long end_brk;
} mm_context_t;
diff --git a/include/asm-m68k/mmzone.h b/arch/m68k/include/asm/mmzone.h
index e1f1ec7b7006..e1f1ec7b7006 100644
--- a/include/asm-m68k/mmzone.h
+++ b/arch/m68k/include/asm/mmzone.h
diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h
new file mode 100644
index 000000000000..79b59d137dd0
--- /dev/null
+++ b/arch/m68k/include/asm/module.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "module_no.h"
+#else
+#include "module_mm.h"
+#endif
diff --git a/include/asm-m68k/module.h b/arch/m68k/include/asm/module_mm.h
index 382d20a6fc18..382d20a6fc18 100644
--- a/include/asm-m68k/module.h
+++ b/arch/m68k/include/asm/module_mm.h
diff --git a/arch/m68knommu/include/asm/module.h b/arch/m68k/include/asm/module_no.h
index 2e45ab50b232..2e45ab50b232 100644
--- a/arch/m68knommu/include/asm/module.h
+++ b/arch/m68k/include/asm/module_no.h
diff --git a/include/asm-m68k/motorola_pgalloc.h b/arch/m68k/include/asm/motorola_pgalloc.h
index d08bf6261df8..d08bf6261df8 100644
--- a/include/asm-m68k/motorola_pgalloc.h
+++ b/arch/m68k/include/asm/motorola_pgalloc.h
diff --git a/include/asm-m68k/motorola_pgtable.h b/arch/m68k/include/asm/motorola_pgtable.h
index 8e9a8a754dde..8e9a8a754dde 100644
--- a/include/asm-m68k/motorola_pgtable.h
+++ b/arch/m68k/include/asm/motorola_pgtable.h
diff --git a/include/asm-m68k/movs.h b/arch/m68k/include/asm/movs.h
index 67dbea36960f..67dbea36960f 100644
--- a/include/asm-m68k/movs.h
+++ b/arch/m68k/include/asm/movs.h
diff --git a/include/asm-m68k/msgbuf.h b/arch/m68k/include/asm/msgbuf.h
index 243cb798de8f..243cb798de8f 100644
--- a/include/asm-m68k/msgbuf.h
+++ b/arch/m68k/include/asm/msgbuf.h
diff --git a/arch/m68knommu/include/asm/mutex.h b/arch/m68k/include/asm/mutex.h
index 458c1f7fbc18..458c1f7fbc18 100644
--- a/arch/m68knommu/include/asm/mutex.h
+++ b/arch/m68k/include/asm/mutex.h
diff --git a/include/asm-m68k/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h
index b81043108472..b81043108472 100644
--- a/include/asm-m68k/mvme147hw.h
+++ b/arch/m68k/include/asm/mvme147hw.h
diff --git a/include/asm-m68k/mvme16xhw.h b/arch/m68k/include/asm/mvme16xhw.h
index 6117f56653d2..6117f56653d2 100644
--- a/include/asm-m68k/mvme16xhw.h
+++ b/arch/m68k/include/asm/mvme16xhw.h
diff --git a/arch/m68knommu/include/asm/nettel.h b/arch/m68k/include/asm/nettel.h
index 0299f6a2deeb..0299f6a2deeb 100644
--- a/arch/m68knommu/include/asm/nettel.h
+++ b/arch/m68k/include/asm/nettel.h
diff --git a/include/asm-m68k/nubus.h b/arch/m68k/include/asm/nubus.h
index d6be9976f1ae..d6be9976f1ae 100644
--- a/include/asm-m68k/nubus.h
+++ b/arch/m68k/include/asm/nubus.h
diff --git a/include/asm-m68k/openprom.h b/arch/m68k/include/asm/openprom.h
index d33cdadf78e1..d33cdadf78e1 100644
--- a/include/asm-m68k/openprom.h
+++ b/arch/m68k/include/asm/openprom.h
diff --git a/include/asm-m68k/oplib.h b/arch/m68k/include/asm/oplib.h
index f082d03336bd..f082d03336bd 100644
--- a/include/asm-m68k/oplib.h
+++ b/arch/m68k/include/asm/oplib.h
diff --git a/arch/m68k/include/asm/page.h b/arch/m68k/include/asm/page.h
new file mode 100644
index 000000000000..f2b4480cc98a
--- /dev/null
+++ b/arch/m68k/include/asm/page.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "page_no.h"
+#else
+#include "page_mm.h"
+#endif
diff --git a/include/asm-m68k/page.h b/arch/m68k/include/asm/page_mm.h
index a34b8bad7847..a34b8bad7847 100644
--- a/include/asm-m68k/page.h
+++ b/arch/m68k/include/asm/page_mm.h
diff --git a/arch/m68knommu/include/asm/page.h b/arch/m68k/include/asm/page_no.h
index 3a1ede4544cb..3a1ede4544cb 100644
--- a/arch/m68knommu/include/asm/page.h
+++ b/arch/m68k/include/asm/page_no.h
diff --git a/arch/m68k/include/asm/page_offset.h b/arch/m68k/include/asm/page_offset.h
new file mode 100644
index 000000000000..66455c849fbb
--- /dev/null
+++ b/arch/m68k/include/asm/page_offset.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "page_offset_no.h"
+#else
+#include "page_offset_mm.h"
+#endif
diff --git a/include/asm-m68k/page_offset.h b/arch/m68k/include/asm/page_offset_mm.h
index 1cbdb7f30ac2..1cbdb7f30ac2 100644
--- a/include/asm-m68k/page_offset.h
+++ b/arch/m68k/include/asm/page_offset_mm.h
diff --git a/arch/m68knommu/include/asm/page_offset.h b/arch/m68k/include/asm/page_offset_no.h
index d4e73e0ba646..d4e73e0ba646 100644
--- a/arch/m68knommu/include/asm/page_offset.h
+++ b/arch/m68k/include/asm/page_offset_no.h
diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/asm/param.h
new file mode 100644
index 000000000000..40d1112a4588
--- /dev/null
+++ b/arch/m68k/include/asm/param.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "param_no.h"
+#else
+#include "param_mm.h"
+#endif
diff --git a/include/asm-m68k/param.h b/arch/m68k/include/asm/param_mm.h
index 536a27888358..536a27888358 100644
--- a/include/asm-m68k/param.h
+++ b/arch/m68k/include/asm/param_mm.h
diff --git a/arch/m68knommu/include/asm/param.h b/arch/m68k/include/asm/param_no.h
index 6044397adb64..6044397adb64 100644
--- a/arch/m68knommu/include/asm/param.h
+++ b/arch/m68k/include/asm/param_no.h
diff --git a/include/asm-m68k/parport.h b/arch/m68k/include/asm/parport.h
index 646b1872f73b..646b1872f73b 100644
--- a/include/asm-m68k/parport.h
+++ b/arch/m68k/include/asm/parport.h
diff --git a/arch/m68k/include/asm/pci.h b/arch/m68k/include/asm/pci.h
new file mode 100644
index 000000000000..dbea95373080
--- /dev/null
+++ b/arch/m68k/include/asm/pci.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "pci_no.h"
+#else
+#include "pci_mm.h"
+#endif
diff --git a/include/asm-m68k/pci.h b/arch/m68k/include/asm/pci_mm.h
index 4ad0aea48ab4..4ad0aea48ab4 100644
--- a/include/asm-m68k/pci.h
+++ b/arch/m68k/include/asm/pci_mm.h
diff --git a/arch/m68knommu/include/asm/pci.h b/arch/m68k/include/asm/pci_no.h
index a13f3cc87451..9abbc03c73ee 100644
--- a/arch/m68knommu/include/asm/pci.h
+++ b/arch/m68k/include/asm/pci_no.h
@@ -1,7 +1,7 @@
#ifndef M68KNOMMU_PCI_H
#define M68KNOMMU_PCI_H
-#include <asm-m68k/pci.h>
+#include <asm/pci_mm.h>
#ifdef CONFIG_COMEMPCI
/*
diff --git a/include/asm-m68k/percpu.h b/arch/m68k/include/asm/percpu.h
index 0859d048faf5..0859d048faf5 100644
--- a/include/asm-m68k/percpu.h
+++ b/arch/m68k/include/asm/percpu.h
diff --git a/arch/m68k/include/asm/pgalloc.h b/arch/m68k/include/asm/pgalloc.h
new file mode 100644
index 000000000000..059cb73e78fc
--- /dev/null
+++ b/arch/m68k/include/asm/pgalloc.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "pgalloc_no.h"
+#else
+#include "pgalloc_mm.h"
+#endif
diff --git a/include/asm-m68k/pgalloc.h b/arch/m68k/include/asm/pgalloc_mm.h
index 4cb1a57ab763..4cb1a57ab763 100644
--- a/include/asm-m68k/pgalloc.h
+++ b/arch/m68k/include/asm/pgalloc_mm.h
diff --git a/arch/m68knommu/include/asm/pgalloc.h b/arch/m68k/include/asm/pgalloc_no.h
index d6352f671ec0..d6352f671ec0 100644
--- a/arch/m68knommu/include/asm/pgalloc.h
+++ b/arch/m68k/include/asm/pgalloc_no.h
diff --git a/arch/m68k/include/asm/pgtable.h b/arch/m68k/include/asm/pgtable.h
new file mode 100644
index 000000000000..ee6759eb445a
--- /dev/null
+++ b/arch/m68k/include/asm/pgtable.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "pgtable_no.h"
+#else
+#include "pgtable_mm.h"
+#endif
diff --git a/include/asm-m68k/pgtable.h b/arch/m68k/include/asm/pgtable_mm.h
index 0b604f0f192d..0b604f0f192d 100644
--- a/include/asm-m68k/pgtable.h
+++ b/arch/m68k/include/asm/pgtable_mm.h
diff --git a/arch/m68knommu/include/asm/pgtable.h b/arch/m68k/include/asm/pgtable_no.h
index 46251016e821..46251016e821 100644
--- a/arch/m68knommu/include/asm/pgtable.h
+++ b/arch/m68k/include/asm/pgtable_no.h
diff --git a/include/asm-m68k/poll.h b/arch/m68k/include/asm/poll.h
index f080fcdb61bf..f080fcdb61bf 100644
--- a/include/asm-m68k/poll.h
+++ b/arch/m68k/include/asm/poll.h
diff --git a/include/asm-m68k/posix_types.h b/arch/m68k/include/asm/posix_types.h
index 63cdcc142d93..63cdcc142d93 100644
--- a/include/asm-m68k/posix_types.h
+++ b/arch/m68k/include/asm/posix_types.h
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
new file mode 100644
index 000000000000..fc3f2c22f2b8
--- /dev/null
+++ b/arch/m68k/include/asm/processor.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "processor_no.h"
+#else
+#include "processor_mm.h"
+#endif
diff --git a/include/asm-m68k/processor.h b/arch/m68k/include/asm/processor_mm.h
index 1f61ef53f0e0..1f61ef53f0e0 100644
--- a/include/asm-m68k/processor.h
+++ b/arch/m68k/include/asm/processor_mm.h
diff --git a/arch/m68knommu/include/asm/processor.h b/arch/m68k/include/asm/processor_no.h
index 91cba18acdd3..91cba18acdd3 100644
--- a/arch/m68knommu/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor_no.h
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
new file mode 100644
index 000000000000..e83cd2f66101
--- /dev/null
+++ b/arch/m68k/include/asm/ptrace.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "ptrace_no.h"
+#else
+#include "ptrace_mm.h"
+#endif
diff --git a/include/asm-m68k/ptrace.h b/arch/m68k/include/asm/ptrace_mm.h
index 57e763d79bf4..57e763d79bf4 100644
--- a/include/asm-m68k/ptrace.h
+++ b/arch/m68k/include/asm/ptrace_mm.h
diff --git a/arch/m68knommu/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace_no.h
index 8c9194b98548..8c9194b98548 100644
--- a/arch/m68knommu/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace_no.h
diff --git a/include/asm-m68k/q40_master.h b/arch/m68k/include/asm/q40_master.h
index 3907a09d4fca..3907a09d4fca 100644
--- a/include/asm-m68k/q40_master.h
+++ b/arch/m68k/include/asm/q40_master.h
diff --git a/include/asm-m68k/q40ints.h b/arch/m68k/include/asm/q40ints.h
index 3d970afb708f..3d970afb708f 100644
--- a/include/asm-m68k/q40ints.h
+++ b/arch/m68k/include/asm/q40ints.h
diff --git a/arch/m68knommu/include/asm/quicc_simple.h b/arch/m68k/include/asm/quicc_simple.h
index c3636932d4bc..c3636932d4bc 100644
--- a/arch/m68knommu/include/asm/quicc_simple.h
+++ b/arch/m68k/include/asm/quicc_simple.h
diff --git a/include/asm-m68k/raw_io.h b/arch/m68k/include/asm/raw_io.h
index d9eb9834ccc8..d9eb9834ccc8 100644
--- a/include/asm-m68k/raw_io.h
+++ b/arch/m68k/include/asm/raw_io.h
diff --git a/include/asm-m68k/resource.h b/arch/m68k/include/asm/resource.h
index e7d35019f337..e7d35019f337 100644
--- a/include/asm-m68k/resource.h
+++ b/arch/m68k/include/asm/resource.h
diff --git a/include/asm-m68k/rtc.h b/arch/m68k/include/asm/rtc.h
index 5d3e03859844..5d3e03859844 100644
--- a/include/asm-m68k/rtc.h
+++ b/arch/m68k/include/asm/rtc.h
diff --git a/include/asm-m68k/sbus.h b/arch/m68k/include/asm/sbus.h
index bfe3ba147f2e..bfe3ba147f2e 100644
--- a/include/asm-m68k/sbus.h
+++ b/arch/m68k/include/asm/sbus.h
diff --git a/arch/m68k/include/asm/scatterlist.h b/arch/m68k/include/asm/scatterlist.h
new file mode 100644
index 000000000000..b7e528636252
--- /dev/null
+++ b/arch/m68k/include/asm/scatterlist.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "scatterlist_no.h"
+#else
+#include "scatterlist_mm.h"
+#endif
diff --git a/include/asm-m68k/scatterlist.h b/arch/m68k/include/asm/scatterlist_mm.h
index d3a7a0edfeca..d3a7a0edfeca 100644
--- a/include/asm-m68k/scatterlist.h
+++ b/arch/m68k/include/asm/scatterlist_mm.h
diff --git a/arch/m68knommu/include/asm/scatterlist.h b/arch/m68k/include/asm/scatterlist_no.h
index afc4788b0d2c..afc4788b0d2c 100644
--- a/arch/m68knommu/include/asm/scatterlist.h
+++ b/arch/m68k/include/asm/scatterlist_no.h
diff --git a/include/asm-m68k/sections.h b/arch/m68k/include/asm/sections.h
index d64967ecfec6..d64967ecfec6 100644
--- a/include/asm-m68k/sections.h
+++ b/arch/m68k/include/asm/sections.h
diff --git a/arch/m68k/include/asm/segment.h b/arch/m68k/include/asm/segment.h
new file mode 100644
index 000000000000..82583bc004bd
--- /dev/null
+++ b/arch/m68k/include/asm/segment.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "segment_no.h"
+#else
+#include "segment_mm.h"
+#endif
diff --git a/include/asm-m68k/segment.h b/arch/m68k/include/asm/segment_mm.h
index 7b0b2d3127f9..7b0b2d3127f9 100644
--- a/include/asm-m68k/segment.h
+++ b/arch/m68k/include/asm/segment_mm.h
diff --git a/arch/m68knommu/include/asm/segment.h b/arch/m68k/include/asm/segment_no.h
index 42318ebec7ec..42318ebec7ec 100644
--- a/arch/m68knommu/include/asm/segment.h
+++ b/arch/m68k/include/asm/segment_no.h
diff --git a/include/asm-m68k/sembuf.h b/arch/m68k/include/asm/sembuf.h
index 2308052a8c24..2308052a8c24 100644
--- a/include/asm-m68k/sembuf.h
+++ b/arch/m68k/include/asm/sembuf.h
diff --git a/include/asm-m68k/serial.h b/arch/m68k/include/asm/serial.h
index 2b90d6e69070..2b90d6e69070 100644
--- a/include/asm-m68k/serial.h
+++ b/arch/m68k/include/asm/serial.h
diff --git a/arch/m68k/include/asm/setup.h b/arch/m68k/include/asm/setup.h
new file mode 100644
index 000000000000..842f86f75ccd
--- /dev/null
+++ b/arch/m68k/include/asm/setup.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "setup_no.h"
+#else
+#include "setup_mm.h"
+#endif
diff --git a/include/asm-m68k/setup.h b/arch/m68k/include/asm/setup_mm.h
index 4dfb3952b375..4dfb3952b375 100644
--- a/include/asm-m68k/setup.h
+++ b/arch/m68k/include/asm/setup_mm.h
diff --git a/arch/m68knommu/include/asm/setup.h b/arch/m68k/include/asm/setup_no.h
index fb86bb2a6078..45d286ce9398 100644
--- a/arch/m68knommu/include/asm/setup.h
+++ b/arch/m68k/include/asm/setup_no.h
@@ -1,6 +1,6 @@
#ifdef __KERNEL__
-#include <asm-m68k/setup.h>
+#include <asm/setup_mm.h>
/* We have a bigger command line buffer. */
#undef COMMAND_LINE_SIZE
diff --git a/include/asm-m68k/shm.h b/arch/m68k/include/asm/shm.h
index fa56ec84a126..fa56ec84a126 100644
--- a/include/asm-m68k/shm.h
+++ b/arch/m68k/include/asm/shm.h
diff --git a/include/asm-m68k/shmbuf.h b/arch/m68k/include/asm/shmbuf.h
index f8928d62f1b7..f8928d62f1b7 100644
--- a/include/asm-m68k/shmbuf.h
+++ b/arch/m68k/include/asm/shmbuf.h
diff --git a/include/asm-m68k/shmparam.h b/arch/m68k/include/asm/shmparam.h
index 558892a2efb3..558892a2efb3 100644
--- a/include/asm-m68k/shmparam.h
+++ b/arch/m68k/include/asm/shmparam.h
diff --git a/arch/m68k/include/asm/sigcontext.h b/arch/m68k/include/asm/sigcontext.h
new file mode 100644
index 000000000000..bff6d40345a9
--- /dev/null
+++ b/arch/m68k/include/asm/sigcontext.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "sigcontext_no.h"
+#else
+#include "sigcontext_mm.h"
+#endif
diff --git a/include/asm-m68k/sigcontext.h b/arch/m68k/include/asm/sigcontext_mm.h
index 64fbe34cf26f..64fbe34cf26f 100644
--- a/include/asm-m68k/sigcontext.h
+++ b/arch/m68k/include/asm/sigcontext_mm.h
diff --git a/arch/m68knommu/include/asm/sigcontext.h b/arch/m68k/include/asm/sigcontext_no.h
index 36c293fc133d..36c293fc133d 100644
--- a/arch/m68knommu/include/asm/sigcontext.h
+++ b/arch/m68k/include/asm/sigcontext_no.h
diff --git a/arch/m68k/include/asm/siginfo.h b/arch/m68k/include/asm/siginfo.h
new file mode 100644
index 000000000000..61219d7affc8
--- /dev/null
+++ b/arch/m68k/include/asm/siginfo.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "siginfo_no.h"
+#else
+#include "siginfo_mm.h"
+#endif
diff --git a/include/asm-m68k/siginfo.h b/arch/m68k/include/asm/siginfo_mm.h
index 05a8d6d90b58..05a8d6d90b58 100644
--- a/include/asm-m68k/siginfo.h
+++ b/arch/m68k/include/asm/siginfo_mm.h
diff --git a/arch/m68knommu/include/asm/siginfo.h b/arch/m68k/include/asm/siginfo_no.h
index b18e5f4064ae..b18e5f4064ae 100644
--- a/arch/m68knommu/include/asm/siginfo.h
+++ b/arch/m68k/include/asm/siginfo_no.h
diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h
new file mode 100644
index 000000000000..3c19988bd93c
--- /dev/null
+++ b/arch/m68k/include/asm/signal.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "signal_no.h"
+#else
+#include "signal_mm.h"
+#endif
diff --git a/include/asm-m68k/signal.h b/arch/m68k/include/asm/signal_mm.h
index 3db8a81942f1..3db8a81942f1 100644
--- a/include/asm-m68k/signal.h
+++ b/arch/m68k/include/asm/signal_mm.h
diff --git a/arch/m68knommu/include/asm/signal.h b/arch/m68k/include/asm/signal_no.h
index 216c08be54a0..216c08be54a0 100644
--- a/arch/m68knommu/include/asm/signal.h
+++ b/arch/m68k/include/asm/signal_no.h
diff --git a/arch/m68knommu/include/asm/smp.h b/arch/m68k/include/asm/smp.h
index 9e9bd7e58922..9e9bd7e58922 100644
--- a/arch/m68knommu/include/asm/smp.h
+++ b/arch/m68k/include/asm/smp.h
diff --git a/include/asm-m68k/socket.h b/arch/m68k/include/asm/socket.h
index dbc64e92c41a..dbc64e92c41a 100644
--- a/include/asm-m68k/socket.h
+++ b/arch/m68k/include/asm/socket.h
diff --git a/include/asm-m68k/sockios.h b/arch/m68k/include/asm/sockios.h
index c04a23943cb7..c04a23943cb7 100644
--- a/include/asm-m68k/sockios.h
+++ b/arch/m68k/include/asm/sockios.h
diff --git a/include/asm-m68k/spinlock.h b/arch/m68k/include/asm/spinlock.h
index 20f46e27b534..20f46e27b534 100644
--- a/include/asm-m68k/spinlock.h
+++ b/arch/m68k/include/asm/spinlock.h
diff --git a/include/asm-m68k/stat.h b/arch/m68k/include/asm/stat.h
index dd38bc2e9f98..dd38bc2e9f98 100644
--- a/include/asm-m68k/stat.h
+++ b/arch/m68k/include/asm/stat.h
diff --git a/include/asm-m68k/statfs.h b/arch/m68k/include/asm/statfs.h
index 08d93f14e061..08d93f14e061 100644
--- a/include/asm-m68k/statfs.h
+++ b/arch/m68k/include/asm/statfs.h
diff --git a/arch/m68k/include/asm/string.h b/arch/m68k/include/asm/string.h
new file mode 100644
index 000000000000..2c356f90f171
--- /dev/null
+++ b/arch/m68k/include/asm/string.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "string_no.h"
+#else
+#include "string_mm.h"
+#endif
diff --git a/include/asm-m68k/string.h b/arch/m68k/include/asm/string_mm.h
index 2eb7df1e0f5d..2eb7df1e0f5d 100644
--- a/include/asm-m68k/string.h
+++ b/arch/m68k/include/asm/string_mm.h
diff --git a/arch/m68knommu/include/asm/string.h b/arch/m68k/include/asm/string_no.h
index af09e17000fc..af09e17000fc 100644
--- a/arch/m68knommu/include/asm/string.h
+++ b/arch/m68k/include/asm/string_no.h
diff --git a/include/asm-m68k/sun3-head.h b/arch/m68k/include/asm/sun3-head.h
index 05af2f18b3bd..05af2f18b3bd 100644
--- a/include/asm-m68k/sun3-head.h
+++ b/arch/m68k/include/asm/sun3-head.h
diff --git a/include/asm-m68k/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h
index d4c83f143816..d4c83f143816 100644
--- a/include/asm-m68k/sun3_pgalloc.h
+++ b/arch/m68k/include/asm/sun3_pgalloc.h
diff --git a/include/asm-m68k/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h
index f847ec732d62..f847ec732d62 100644
--- a/include/asm-m68k/sun3_pgtable.h
+++ b/arch/m68k/include/asm/sun3_pgtable.h
diff --git a/include/asm-m68k/sun3ints.h b/arch/m68k/include/asm/sun3ints.h
index 309d6e6a1374..309d6e6a1374 100644
--- a/include/asm-m68k/sun3ints.h
+++ b/arch/m68k/include/asm/sun3ints.h
diff --git a/include/asm-m68k/sun3mmu.h b/arch/m68k/include/asm/sun3mmu.h
index d8f17a0d8c9f..d8f17a0d8c9f 100644
--- a/include/asm-m68k/sun3mmu.h
+++ b/arch/m68k/include/asm/sun3mmu.h
diff --git a/include/asm-m68k/sun3x.h b/arch/m68k/include/asm/sun3x.h
index f5691a1ed7cc..f5691a1ed7cc 100644
--- a/include/asm-m68k/sun3x.h
+++ b/arch/m68k/include/asm/sun3x.h
diff --git a/include/asm-m68k/sun3xflop.h b/arch/m68k/include/asm/sun3xflop.h
index 32c45f84ac60..32c45f84ac60 100644
--- a/include/asm-m68k/sun3xflop.h
+++ b/arch/m68k/include/asm/sun3xflop.h
diff --git a/include/asm-m68k/sun3xprom.h b/arch/m68k/include/asm/sun3xprom.h
index 6735efcf5f6d..6735efcf5f6d 100644
--- a/include/asm-m68k/sun3xprom.h
+++ b/arch/m68k/include/asm/sun3xprom.h
diff --git a/include/asm-m68k/suspend.h b/arch/m68k/include/asm/suspend.h
index 57b3ddb4d269..57b3ddb4d269 100644
--- a/include/asm-m68k/suspend.h
+++ b/arch/m68k/include/asm/suspend.h
diff --git a/arch/m68k/include/asm/swab.h b/arch/m68k/include/asm/swab.h
new file mode 100644
index 000000000000..7d7dde1c73ec
--- /dev/null
+++ b/arch/m68k/include/asm/swab.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "swab_no.h"
+#else
+#include "swab_mm.h"
+#endif
diff --git a/include/asm-m68k/byteorder.h b/arch/m68k/include/asm/swab_mm.h
index b354acdafec8..7221e3066825 100644
--- a/include/asm-m68k/byteorder.h
+++ b/arch/m68k/include/asm/swab_mm.h
@@ -1,10 +1,9 @@
-#ifndef _M68K_BYTEORDER_H
-#define _M68K_BYTEORDER_H
+#ifndef _M68K_SWAB_H
+#define _M68K_SWAB_H
#include <asm/types.h>
#include <linux/compiler.h>
-#define __BIG_ENDIAN
#define __SWAB_64_THRU_32__
static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
@@ -14,6 +13,4 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
}
#define __arch_swab32 __arch_swab32
-#include <linux/byteorder.h>
-
-#endif /* _M68K_BYTEORDER_H */
+#endif /* _M68K_SWAB_H */
diff --git a/arch/m68k/include/asm/swab_no.h b/arch/m68k/include/asm/swab_no.h
new file mode 100644
index 000000000000..e582257db300
--- /dev/null
+++ b/arch/m68k/include/asm/swab_no.h
@@ -0,0 +1,24 @@
+#ifndef _M68KNOMMU_SWAB_H
+#define _M68KNOMMU_SWAB_H
+
+#include <linux/types.h>
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __SWAB_64_THRU_32__
+#endif
+
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+ asm(
+ "byterev %0"
+ : "=d" (val)
+ : "0" (val)
+ );
+ return val;
+}
+
+#define __arch_swab32 __arch_swab32
+#endif
+
+#endif /* _M68KNOMMU_SWAB_H */
diff --git a/arch/m68k/include/asm/system.h b/arch/m68k/include/asm/system.h
new file mode 100644
index 000000000000..ccea925ff4f5
--- /dev/null
+++ b/arch/m68k/include/asm/system.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "system_no.h"
+#else
+#include "system_mm.h"
+#endif
diff --git a/include/asm-m68k/system.h b/arch/m68k/include/asm/system_mm.h
index dbb6515ffd5b..dbb6515ffd5b 100644
--- a/include/asm-m68k/system.h
+++ b/arch/m68k/include/asm/system_mm.h
diff --git a/arch/m68knommu/include/asm/system.h b/arch/m68k/include/asm/system_no.h
index 40f49de69821..4496c0aa8379 100644
--- a/arch/m68knommu/include/asm/system.h
+++ b/arch/m68k/include/asm/system_no.h
@@ -230,7 +230,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
jmp 0xf0000400; \
"); \
})
-#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
+#elif defined(CONFIG_NETtel) || \
defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
#define HARD_RESET_NOW() ({ \
asm(" \
diff --git a/include/asm-m68k/termbits.h b/arch/m68k/include/asm/termbits.h
index 8c14170996bb..8c14170996bb 100644
--- a/include/asm-m68k/termbits.h
+++ b/arch/m68k/include/asm/termbits.h
diff --git a/include/asm-m68k/termios.h b/arch/m68k/include/asm/termios.h
index 0823032e4045..0823032e4045 100644
--- a/include/asm-m68k/termios.h
+++ b/arch/m68k/include/asm/termios.h
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h
new file mode 100644
index 000000000000..f31a3f42b7b3
--- /dev/null
+++ b/arch/m68k/include/asm/thread_info.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "thread_info_no.h"
+#else
+#include "thread_info_mm.h"
+#endif
diff --git a/include/asm-m68k/thread_info.h b/arch/m68k/include/asm/thread_info_mm.h
index af0fda46e94b..af0fda46e94b 100644
--- a/include/asm-m68k/thread_info.h
+++ b/arch/m68k/include/asm/thread_info_mm.h
diff --git a/arch/m68knommu/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info_no.h
index 82529f424ea3..82529f424ea3 100644
--- a/arch/m68knommu/include/asm/thread_info.h
+++ b/arch/m68k/include/asm/thread_info_no.h
diff --git a/arch/m68k/include/asm/timex.h b/arch/m68k/include/asm/timex.h
new file mode 100644
index 000000000000..719762980578
--- /dev/null
+++ b/arch/m68k/include/asm/timex.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "timex_no.h"
+#else
+#include "timex_mm.h"
+#endif
diff --git a/include/asm-m68k/timex.h b/arch/m68k/include/asm/timex_mm.h
index b87f2f278f67..b87f2f278f67 100644
--- a/include/asm-m68k/timex.h
+++ b/arch/m68k/include/asm/timex_mm.h
diff --git a/arch/m68knommu/include/asm/timex.h b/arch/m68k/include/asm/timex_no.h
index 109050f3fe91..109050f3fe91 100644
--- a/arch/m68knommu/include/asm/timex.h
+++ b/arch/m68k/include/asm/timex_no.h
diff --git a/include/asm-m68k/tlb.h b/arch/m68k/include/asm/tlb.h
index 1785cff73449..1785cff73449 100644
--- a/include/asm-m68k/tlb.h
+++ b/arch/m68k/include/asm/tlb.h
diff --git a/arch/m68k/include/asm/tlbflush.h b/arch/m68k/include/asm/tlbflush.h
new file mode 100644
index 000000000000..b6f93b30951e
--- /dev/null
+++ b/arch/m68k/include/asm/tlbflush.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "tlbflush_no.h"
+#else
+#include "tlbflush_mm.h"
+#endif
diff --git a/include/asm-m68k/tlbflush.h b/arch/m68k/include/asm/tlbflush_mm.h
index acb6bf21a321..acb6bf21a321 100644
--- a/include/asm-m68k/tlbflush.h
+++ b/arch/m68k/include/asm/tlbflush_mm.h
diff --git a/arch/m68knommu/include/asm/tlbflush.h b/arch/m68k/include/asm/tlbflush_no.h
index a470cfb803eb..a470cfb803eb 100644
--- a/arch/m68knommu/include/asm/tlbflush.h
+++ b/arch/m68k/include/asm/tlbflush_no.h
diff --git a/arch/m68knommu/include/asm/topology.h b/arch/m68k/include/asm/topology.h
index ca173e9f26ff..ca173e9f26ff 100644
--- a/arch/m68knommu/include/asm/topology.h
+++ b/arch/m68k/include/asm/topology.h
diff --git a/arch/m68k/include/asm/traps.h b/arch/m68k/include/asm/traps.h
new file mode 100644
index 000000000000..3011ec0f5365
--- /dev/null
+++ b/arch/m68k/include/asm/traps.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "traps_no.h"
+#else
+#include "traps_mm.h"
+#endif
diff --git a/include/asm-m68k/traps.h b/arch/m68k/include/asm/traps_mm.h
index 8caef25624c7..8caef25624c7 100644
--- a/include/asm-m68k/traps.h
+++ b/arch/m68k/include/asm/traps_mm.h
diff --git a/arch/m68knommu/include/asm/traps.h b/arch/m68k/include/asm/traps_no.h
index d0671e5f8e29..d0671e5f8e29 100644
--- a/arch/m68knommu/include/asm/traps.h
+++ b/arch/m68k/include/asm/traps_no.h
diff --git a/include/asm-m68k/types.h b/arch/m68k/include/asm/types.h
index 6441cb5f8e7c..6441cb5f8e7c 100644
--- a/include/asm-m68k/types.h
+++ b/arch/m68k/include/asm/types.h
diff --git a/arch/m68k/include/asm/uaccess.h b/arch/m68k/include/asm/uaccess.h
new file mode 100644
index 000000000000..38f92dbb9a45
--- /dev/null
+++ b/arch/m68k/include/asm/uaccess.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "uaccess_no.h"
+#else
+#include "uaccess_mm.h"
+#endif
diff --git a/include/asm-m68k/uaccess.h b/arch/m68k/include/asm/uaccess_mm.h
index 7107f3fbdbb6..7107f3fbdbb6 100644
--- a/include/asm-m68k/uaccess.h
+++ b/arch/m68k/include/asm/uaccess_mm.h
diff --git a/arch/m68knommu/include/asm/uaccess.h b/arch/m68k/include/asm/uaccess_no.h
index 68bbe9b312f1..68bbe9b312f1 100644
--- a/arch/m68knommu/include/asm/uaccess.h
+++ b/arch/m68k/include/asm/uaccess_no.h
diff --git a/arch/m68k/include/asm/ucontext.h b/arch/m68k/include/asm/ucontext.h
new file mode 100644
index 000000000000..b53cd160c0b3
--- /dev/null
+++ b/arch/m68k/include/asm/ucontext.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "ucontext_no.h"
+#else
+#include "ucontext_mm.h"
+#endif
diff --git a/include/asm-m68k/ucontext.h b/arch/m68k/include/asm/ucontext_mm.h
index e4e22669edc0..e4e22669edc0 100644
--- a/include/asm-m68k/ucontext.h
+++ b/arch/m68k/include/asm/ucontext_mm.h
diff --git a/arch/m68knommu/include/asm/ucontext.h b/arch/m68k/include/asm/ucontext_no.h
index 713a27f901cd..713a27f901cd 100644
--- a/arch/m68knommu/include/asm/ucontext.h
+++ b/arch/m68k/include/asm/ucontext_no.h
diff --git a/arch/m68k/include/asm/unaligned.h b/arch/m68k/include/asm/unaligned.h
new file mode 100644
index 000000000000..c640bba3bdf4
--- /dev/null
+++ b/arch/m68k/include/asm/unaligned.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "unaligned_no.h"
+#else
+#include "unaligned_mm.h"
+#endif
diff --git a/include/asm-m68k/unaligned.h b/arch/m68k/include/asm/unaligned_mm.h
index 77698f2dc33c..77698f2dc33c 100644
--- a/include/asm-m68k/unaligned.h
+++ b/arch/m68k/include/asm/unaligned_mm.h
diff --git a/arch/m68knommu/include/asm/unaligned.h b/arch/m68k/include/asm/unaligned_no.h
index eb1ea4cb9a59..eb1ea4cb9a59 100644
--- a/arch/m68knommu/include/asm/unaligned.h
+++ b/arch/m68k/include/asm/unaligned_no.h
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
new file mode 100644
index 000000000000..df1d9d4cb1fd
--- /dev/null
+++ b/arch/m68k/include/asm/unistd.h
@@ -0,0 +1,5 @@
+#ifdef __uClinux__
+#include "unistd_no.h"
+#else
+#include "unistd_mm.h"
+#endif
diff --git a/include/asm-m68k/unistd.h b/arch/m68k/include/asm/unistd_mm.h
index 965abb8bc7ff..3c19027331fa 100644
--- a/include/asm-m68k/unistd.h
+++ b/arch/m68k/include/asm/unistd_mm.h
@@ -5,6 +5,7 @@
* This file contains the system call numbers.
*/
+#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
@@ -359,9 +360,6 @@
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
-/* whitelist for checksyscalls */
-#define __IGNORE_restart_syscall
-
/*
* "Conditional" syscalls
*
diff --git a/arch/m68knommu/include/asm/unistd.h b/arch/m68k/include/asm/unistd_no.h
index b034a2f7b444..b034a2f7b444 100644
--- a/arch/m68knommu/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd_no.h
diff --git a/include/asm-m68k/user.h b/arch/m68k/include/asm/user.h
index f1f478d6e050..f1f478d6e050 100644
--- a/include/asm-m68k/user.h
+++ b/arch/m68k/include/asm/user.h
diff --git a/include/asm-m68k/virtconvert.h b/arch/m68k/include/asm/virtconvert.h
index 22ab05c9c52b..22ab05c9c52b 100644
--- a/include/asm-m68k/virtconvert.h
+++ b/arch/m68k/include/asm/virtconvert.h
diff --git a/arch/m68k/include/asm/xor.h b/arch/m68k/include/asm/xor.h
new file mode 100644
index 000000000000..c82eb12a5b18
--- /dev/null
+++ b/arch/m68k/include/asm/xor.h
@@ -0,0 +1 @@
+#include <asm-generic/xor.h>
diff --git a/include/asm-m68k/zorro.h b/arch/m68k/include/asm/zorro.h
index 5ce97c22b582..5ce97c22b582 100644
--- a/include/asm-m68k/zorro.h
+++ b/arch/m68k/include/asm/zorro.h
diff --git a/arch/m68k/kernel/.gitignore b/arch/m68k/kernel/.gitignore
new file mode 100644
index 000000000000..c5f676c3c224
--- /dev/null
+++ b/arch/m68k/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index f28404d9a2bc..5c332f2b9b83 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -424,7 +424,7 @@ resume:
.data
ALIGN
sys_call_table:
- .long sys_ni_syscall /* 0 - old "setup()" system call*/
+ .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
.long sys_exit
.long sys_fork
.long sys_read
@@ -513,7 +513,7 @@ sys_call_table:
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 3042c2bc8c58..632ce016014d 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -40,7 +40,6 @@
* alignment requirements and potentially different initial
* setup.
*/
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 4d97bd2bd573..303730afb1c9 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -26,6 +26,7 @@
#include <linux/initrd.h>
#include <asm/bootinfo.h>
+#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/fpu.h>
#include <asm/irq.h>
@@ -62,7 +63,6 @@ EXPORT_SYMBOL(vme_brdtype);
int m68k_is040or060;
EXPORT_SYMBOL(m68k_is040or060);
-extern int end;
extern unsigned long availmem;
int m68k_num_memory;
@@ -215,11 +215,10 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
void __init setup_arch(char **cmdline_p)
{
- extern int _etext, _edata, _end;
int i;
/* The bootinfo is located right after the kernel bss */
- m68k_parse_bootinfo((const struct bi_record *)&_end);
+ m68k_parse_bootinfo((const struct bi_record *)_end);
if (CPU_IS_040)
m68k_is040or060 = 4;
@@ -252,9 +251,9 @@ void __init setup_arch(char **cmdline_p)
}
init_mm.start_code = PAGE_OFFSET;
- init_mm.end_code = (unsigned long) &_etext;
- init_mm.end_data = (unsigned long) &_edata;
- init_mm.brk = (unsigned long) &_end;
+ init_mm.end_code = (unsigned long)_etext;
+ init_mm.end_data = (unsigned long)_edata;
+ init_mm.brk = (unsigned long)_end;
*cmdline_p = m68k_command_line;
memcpy(boot_command_line, *cmdline_p, CL_SIZE);
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index f9af893cd289..de2d05ddd86d 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -326,6 +326,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
struct sigcontext context;
int err;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
/* get previous context */
if (copy_from_user(&context, usc, sizeof(context)))
goto badframe;
@@ -411,6 +414,9 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
unsigned long usp;
int err;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
err = __get_user(temp, &uc->uc_mcontext.version);
if (temp != MCONTEXT_VERSION)
goto badframe;
@@ -937,6 +943,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
regs->d0 = -EINTR;
break;
+ case -ERESTART_RESTARTBLOCK:
+ if (!has_handler) {
+ regs->d0 = __NR_restart_syscall;
+ regs->pc -= 2;
+ break;
+ }
+ regs->d0 = -EINTR;
+ break;
+
case -ERESTARTSYS:
if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
regs->d0 = -EINTR;
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 6d813de2baf1..184acc90808d 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -401,7 +401,7 @@ static inline void do_040writebacks(struct frame *fp)
* called from sigreturn(), must ensure userspace code didn't
* manipulate exception frame to circumvent protection, then complete
* pending writebacks
- * we just clear TM2 to turn it into an userspace access
+ * we just clear TM2 to turn it into a userspace access
*/
asmlinkage void berr_040cleanup(struct frame *fp)
{
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 8a4919e4d36a..d9368c0709ba 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -33,6 +33,7 @@ SECTIONS
} :data
/* End of data goes *here* so that freeing init code works properly. */
_edata = .;
+ NOTES
/* will be freed after init */
. = ALIGN(PAGE_SIZE); /* Init code and data */
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index 245d16d078ad..2a96bebd8969 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -92,7 +92,8 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
void __init baboon_register_interrupts(void)
{
baboon_disabled = 0;
- request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon);
+ if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
+ pr_err("Couldn't register baboon interrupt\n");
}
/*
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 8819b97be324..98b6bcfb37bf 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -47,13 +47,6 @@
struct mac_booter_data mac_bi_data;
-/* New m68k bootinfo stuff and videobase */
-
-extern int m68k_num_memory;
-extern struct mem_info m68k_memory[NUM_MEMINFO];
-
-extern struct mem_info m68k_ramdisk;
-
/* The phys. video addr. - might be bogus on some machines */
static unsigned long mac_orig_videoaddr;
@@ -61,7 +54,6 @@ static unsigned long mac_orig_videoaddr;
extern unsigned long mac_gettimeoffset(void);
extern int mac_hwclk(int, struct rtc_time *);
extern int mac_set_clock_mmss(unsigned long);
-extern int show_mac_interrupts(struct seq_file *, void *);
extern void iop_preinit(void);
extern void iop_init(void);
extern void via_init(void);
@@ -805,10 +797,6 @@ static void __init mac_identify(void)
mac_bi_data.boottime, mac_bi_data.gmtbias);
printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
-#if 0
- printk("Ramdisk: addr 0x%lx size 0x%lx\n",
- m68k_ramdisk.addr, m68k_ramdisk.size);
-#endif
iop_init();
via_init();
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index 65dd77a742a3..bce074ceb768 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -27,7 +27,6 @@
#include <asm/macints.h>
extern unsigned long mac_videobase;
-extern unsigned long mac_videodepth;
extern unsigned long mac_rowbytes;
extern void mac_serial_print(const char *);
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 326fb9978094..1ad4e9d80eba 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -305,14 +305,16 @@ void __init iop_register_interrupts(void)
{
if (iop_ism_present) {
if (oss_present) {
- request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
+ if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
IRQ_FLG_LOCK, "ISM IOP",
- (void *) IOP_NUM_ISM);
+ (void *) IOP_NUM_ISM))
+ pr_err("Couldn't register ISM IOP interrupt\n");
oss_irq_enable(IRQ_MAC_ADB);
} else {
- request_irq(IRQ_VIA2_0, iop_ism_irq,
+ if (request_irq(IRQ_VIA2_0, iop_ism_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
- (void *) IOP_NUM_ISM);
+ (void *) IOP_NUM_ISM))
+ pr_err("Couldn't register ISM IOP interrupt\n");
}
if (!iop_alive(iop_base[IOP_NUM_ISM])) {
printk("IOP: oh my god, they killed the ISM IOP!\n");
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 82e560c076ce..23711074e0e2 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -134,6 +134,7 @@
#include <asm/errno.h>
#include <asm/macints.h>
#include <asm/irq_regs.h>
+#include <asm/mac_oss.h>
#define DEBUG_SPURIOUS
#define SHUTUP_SONIC
@@ -146,7 +147,6 @@ static int scc_mask;
* VIA/RBV hooks
*/
-extern void via_init(void);
extern void via_register_interrupts(void);
extern void via_irq_enable(int);
extern void via_irq_disable(int);
@@ -157,9 +157,6 @@ extern int via_irq_pending(int);
* OSS hooks
*/
-extern int oss_present;
-
-extern void oss_init(void);
extern void oss_register_interrupts(void);
extern void oss_irq_enable(int);
extern void oss_irq_disable(int);
@@ -170,9 +167,6 @@ extern int oss_irq_pending(int);
* PSC hooks
*/
-extern int psc_present;
-
-extern void psc_init(void);
extern void psc_register_interrupts(void);
extern void psc_irq_enable(int);
extern void psc_irq_disable(int);
@@ -191,12 +185,10 @@ extern void iop_register_interrupts(void);
extern int baboon_present;
-extern void baboon_init(void);
extern void baboon_register_interrupts(void);
extern void baboon_irq_enable(int);
extern void baboon_irq_disable(int);
extern void baboon_irq_clear(int);
-extern int baboon_irq_pending(int);
/*
* SCC interrupt routines
@@ -258,8 +250,9 @@ void __init mac_init_IRQ(void)
if (baboon_present)
baboon_register_interrupts();
iop_register_interrupts();
- request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
- mac_nmi_handler);
+ if (request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
+ mac_nmi_handler))
+ pr_err("Couldn't register NMI\n");
#ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Done!\n");
#endif
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
index a44c7086ab39..5d818568b343 100644
--- a/arch/m68k/mac/misc.c
+++ b/arch/m68k/mac/misc.c
@@ -35,7 +35,6 @@
#define RTC_OFFSET 2082844800
-extern struct mac_booter_data mac_bi_data;
static void (*rom_reset)(void);
#ifdef CONFIG_ADB_CUDA
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index 8426501119ca..f3d23d6ebcf8 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -66,16 +66,21 @@ void __init oss_init(void)
void __init oss_register_interrupts(void)
{
- request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
- "scsi", (void *) oss);
- request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
- "scc", mac_scc_dispatch);
- request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
- "nubus", (void *) oss);
- request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
- "sound", (void *) oss);
- request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
- "via1", (void *) via1);
+ if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
+ "scsi", (void *) oss))
+ pr_err("Couldn't register %s interrupt\n", "scsi");
+ if (request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
+ "scc", mac_scc_dispatch))
+ pr_err("Couldn't register %s interrupt\n", "scc");
+ if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
+ "nubus", (void *) oss))
+ pr_err("Couldn't register %s interrupt\n", "nubus");
+ if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
+ "sound", (void *) oss))
+ pr_err("Couldn't register %s interrupt\n", "sound");
+ if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
+ "via1", (void *) via1))
+ pr_err("Couldn't register %s interrupt\n", "via1");
}
/*
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index f84a4dd64f94..ba6ccab64018 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -117,10 +117,14 @@ void __init psc_init(void)
void __init psc_register_interrupts(void)
{
- request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30);
- request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40);
- request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50);
- request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60);
+ if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
+ pr_err("Couldn't register psc%d interrupt\n", 3);
+ if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
+ pr_err("Couldn't register psc%d interrupt\n", 4);
+ if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
+ pr_err("Couldn't register psc%d interrupt\n", 5);
+ if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
+ pr_err("Couldn't register psc%d interrupt\n", 6);
}
/*
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index f01d418e64fe..7d97ba54536e 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -34,6 +34,7 @@
#include <asm/macints.h>
#include <asm/mac_via.h>
#include <asm/mac_psc.h>
+#include <asm/mac_oss.h>
volatile __u8 *via1, *via2;
int rbv_present;
@@ -84,7 +85,6 @@ void via_irq_disable(int irq);
void via_irq_clear(int irq);
extern irqreturn_t mac_scc_dispatch(int, void *);
-extern int oss_present;
/*
* Initialize the VIAs
@@ -283,7 +283,8 @@ void __init via_init_clock(irq_handler_t func)
via1[vT1CL] = MAC_CLOCK_LOW;
via1[vT1CH] = MAC_CLOCK_HIGH;
- request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
+ if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+ pr_err("Couldn't register %s interrupt\n", "timer");
}
/*
@@ -293,25 +294,31 @@ void __init via_init_clock(irq_handler_t func)
void __init via_register_interrupts(void)
{
if (via_alt_mapping) {
- request_irq(IRQ_AUTO_1, via1_irq,
+ if (request_irq(IRQ_AUTO_1, via1_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
- (void *) via1);
- request_irq(IRQ_AUTO_6, via1_irq,
+ (void *) via1))
+ pr_err("Couldn't register %s interrupt\n", "software");
+ if (request_irq(IRQ_AUTO_6, via1_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
- (void *) via1);
+ (void *) via1))
+ pr_err("Couldn't register %s interrupt\n", "via1");
} else {
- request_irq(IRQ_AUTO_1, via1_irq,
+ if (request_irq(IRQ_AUTO_1, via1_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
- (void *) via1);
+ (void *) via1))
+ pr_err("Couldn't register %s interrupt\n", "via1");
}
- request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "via2", (void *) via2);
+ if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "via2", (void *) via2))
+ pr_err("Couldn't register %s interrupt\n", "via2");
if (!psc_present) {
- request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
- "scc", mac_scc_dispatch);
+ if (request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
+ "scc", mac_scc_dispatch))
+ pr_err("Couldn't register %s interrupt\n", "scc");
}
- request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "nubus", (void *) via2);
+ if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
+ IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
+ pr_err("Couldn't register %s interrupt\n", "nubus");
}
/*
diff --git a/arch/m68k/math-emu/fp_log.c b/arch/m68k/math-emu/fp_log.c
index b1033ae0d6f0..367ecee2f981 100644
--- a/arch/m68k/math-emu/fp_log.c
+++ b/arch/m68k/math-emu/fp_log.c
@@ -24,7 +24,6 @@ static const struct fp_ext fp_one =
extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src);
extern struct fp_ext *fp_fdiv(struct fp_ext *dest, const struct fp_ext *src);
-extern struct fp_ext *fp_fmul(struct fp_ext *dest, const struct fp_ext *src);
struct fp_ext *
fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 81bb08ceec18..0007b2adf3a3 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -28,6 +28,7 @@
#ifdef CONFIG_ATARI
#include <asm/atari_stram.h>
#endif
+#include <asm/sections.h>
#include <asm/tlb.h>
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -73,9 +74,6 @@ extern void init_pointer_table(unsigned long ptable);
/* References to section boundaries */
-extern char _text[], _etext[];
-extern char __init_begin[], __init_end[];
-
extern pmd_t *zero_pgtable;
void __init mem_init(void)
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index c5dbb9bdb322..4665fc84b7dc 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -30,6 +30,7 @@
#ifdef CONFIG_ATARI
#include <asm/atari_stram.h>
#endif
+#include <asm/sections.h>
#undef DEBUG
@@ -301,14 +302,12 @@ void __init paging_init(void)
}
}
-extern char __init_begin, __init_end;
-
void free_initmem(void)
{
unsigned long addr;
- addr = (unsigned long)&__init_begin;
- for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
+ addr = (unsigned long)__init_begin;
+ for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
virt_to_page(addr)->flags &= ~(1 << PG_reserved);
init_page_count(virt_to_page(addr));
free_page(addr);
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 43cdf476ffab..100baaa692a1 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -42,7 +42,6 @@ extern unsigned long mvme147_gettimeoffset (void);
extern int mvme147_hwclk (int, struct rtc_time *);
extern int mvme147_set_clock_mmss (unsigned long);
extern void mvme147_reset (void);
-extern void mvme147_waitbut(void);
static int bcd2int (unsigned char b);
@@ -115,8 +114,9 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
void mvme147_sched_init (irq_handler_t timer_routine)
{
tick_handler = timer_routine;
- request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
- IRQ_FLG_REPLACE, "timer 1", NULL);
+ if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
+ "timer 1", NULL))
+ pr_err("Couldn't register timer interrupt\n");
/* Init the clock with a value */
/* our clock goes off every 6.25us */
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 1521826fc3c7..11edf61cc2c4 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -48,7 +48,6 @@ extern unsigned long mvme16x_gettimeoffset (void);
extern int mvme16x_hwclk (int, struct rtc_time *);
extern int mvme16x_set_clock_mmss (unsigned long);
extern void mvme16x_reset (void);
-extern void mvme16x_waitbut(void);
int bcd2int (unsigned char b);
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 7110546e3c00..31ab3f08bbda 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -36,7 +36,6 @@
#include <asm/machdep.h>
#include <asm/q40_master.h>
-extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
extern void q40_init_IRQ(void);
static void q40_get_model(char *model);
extern void q40_sched_init(irq_handler_t handler);
@@ -47,8 +46,6 @@ static unsigned int q40_get_ss(void);
static int q40_set_clock_mmss(unsigned long);
static int q40_get_rtc_pll(struct rtc_pll_info *pll);
static int q40_set_rtc_pll(struct rtc_pll_info *pll);
-extern void q40_waitbut(void);
-void q40_set_vectors(void);
extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 8dfaa201342e..2ca25bd01a96 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -27,23 +27,21 @@
#include <asm/sun3mmu.h>
#include <asm/rtc.h>
#include <asm/machdep.h>
+#include <asm/idprom.h>
#include <asm/intersil.h>
#include <asm/irq.h>
+#include <asm/sections.h>
#include <asm/segment.h>
#include <asm/sun3ints.h>
-extern char _text, _end;
-
char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
extern unsigned long sun3_gettimeoffset(void);
static void sun3_sched_init(irq_handler_t handler);
extern void sun3_get_model (char* model);
-extern void idprom_init (void);
extern int sun3_hwclk(int set, struct rtc_time *t);
volatile char* clock_va;
-extern volatile unsigned char* sun3_intreg;
extern unsigned long availmem;
unsigned long num_pages;
@@ -149,7 +147,7 @@ void __init config_sun3(void)
mach_halt = sun3_halt;
mach_get_hardware_list = sun3_get_hardware_list;
- memory_start = ((((int)&_end) + 0x2000) & ~0x1fff);
+ memory_start = ((((unsigned long)_end) + 0x2000) & ~0x1fff);
// PROM seems to want the last couple of physical pages. --m
memory_end = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE;
diff --git a/arch/m68k/sun3/mmu_emu.c b/arch/m68k/sun3/mmu_emu.c
index 60f9d4500d72..3cd19390aae5 100644
--- a/arch/m68k/sun3/mmu_emu.c
+++ b/arch/m68k/sun3/mmu_emu.c
@@ -27,7 +27,6 @@
#include <asm/mmu_context.h>
#include <asm/dvma.h>
-extern void prom_reboot (char *) __attribute__ ((__noreturn__));
#undef DEBUG_MMU_EMU
#define DEBUG_PROM_MAPS
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index 7364cd67455e..ad90393a3361 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -105,7 +105,10 @@ void __init sun3_init_IRQ(void)
m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
m68k_setup_user_interrupt(VEC_USER, 128, NULL);
- request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
- request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
- request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL);
+ if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
+ pr_err("Couldn't register %s interrupt\n", "int5");
+ if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL))
+ pr_err("Couldn't register %s interrupt\n", "int7");
+ if (request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL))
+ pr_err("Couldn't register %s interrupt\n", "vec255");
}
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index 2b1ca2db070f..fc599fad4a54 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -23,7 +23,6 @@
#include "time.h"
volatile char *clock_va;
-extern volatile unsigned char *sun3_intreg;
extern void sun3_get_model(char *model);
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 76b66feb74df..4beb59dfc6ec 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -14,6 +14,10 @@ config MMU
bool
default n
+config NO_DMA
+ bool
+ default y
+
config FPU
bool
default n
@@ -398,12 +402,6 @@ config M5307C3
help
Support for the Motorola M5307C3 board.
-config eLIA
- bool "Moreton Bay eLIA board support"
- depends on M5307
- help
- Support for the Moreton Bay eLIA board.
-
config SECUREEDGEMP3
bool "SnapGear SecureEdge/MP3 platform support"
depends on M5307
@@ -697,25 +695,8 @@ config ISA_DMA_API
depends on !M5272
default y
-menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
-
-config PCI
- bool "PCI support"
- help
- Support for PCI bus.
-
-config COMEMPCI
- bool "CO-MEM lite PCI controller support"
- depends on (M5307 || M5407)
-
-source "drivers/pci/Kconfig"
-
source "drivers/pcmcia/Kconfig"
-source "drivers/pci/hotplug/Kconfig"
-
-endmenu
-
menu "Executable file formats"
source "fs/Kconfig.binfmt"
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index b63bbcf874ff..fd0fb303d885 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -41,7 +41,6 @@ board-$(CONFIG_M5271EVB) := M5271EVB
board-$(CONFIG_M5275EVB) := M5275EVB
board-$(CONFIG_M5282EVB) := M5282EVB
board-$(CONFIG_ELITE) := eLITE
-board-$(CONFIG_eLIA) := eLIA
board-$(CONFIG_NETtel) := NETtel
board-$(CONFIG_SECUREEDGEMP3) := MP3
board-$(CONFIG_CLEOPATRA) := CLEOPATRA
diff --git a/arch/m68knommu/include/asm/byteorder.h b/arch/m68knommu/include/asm/byteorder.h
deleted file mode 100644
index 20bb4426b610..000000000000
--- a/arch/m68knommu/include/asm/byteorder.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _M68KNOMMU_BYTEORDER_H
-#define _M68KNOMMU_BYTEORDER_H
-
-#include <linux/types.h>
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
-
-#if defined (__mcfisaaplus__) || defined (__mcfisac__)
-static inline __attribute_const__ __u32 ___arch__swab32(__u32 val)
-{
- asm(
- "byterev %0"
- : "=d" (val)
- : "0" (val)
- );
- return val;
-}
-
-#define __arch__swab32(x) ___arch__swab32(x)
-#endif
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _M68KNOMMU_BYTEORDER_H */
diff --git a/arch/m68knommu/include/asm/cachectl.h b/arch/m68knommu/include/asm/cachectl.h
deleted file mode 100644
index bcf5a6a9dd52..000000000000
--- a/arch/m68knommu/include/asm/cachectl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/cachectl.h>
diff --git a/arch/m68knommu/include/asm/cputime.h b/arch/m68knommu/include/asm/cputime.h
deleted file mode 100644
index a0c4a660878d..000000000000
--- a/arch/m68knommu/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __M68KNOMMU_CPUTIME_H
-#define __M68KNOMMU_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __M68KNOMMU_CPUTIME_H */
diff --git a/arch/m68knommu/include/asm/errno.h b/arch/m68knommu/include/asm/errno.h
deleted file mode 100644
index 7e8c22b9a5e6..000000000000
--- a/arch/m68knommu/include/asm/errno.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/errno.h>
diff --git a/arch/m68knommu/include/asm/fcntl.h b/arch/m68knommu/include/asm/fcntl.h
deleted file mode 100644
index f6a552cda4cd..000000000000
--- a/arch/m68knommu/include/asm/fcntl.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/fcntl.h>
diff --git a/arch/m68knommu/include/asm/hwtest.h b/arch/m68knommu/include/asm/hwtest.h
deleted file mode 100644
index 700626a1b1bf..000000000000
--- a/arch/m68knommu/include/asm/hwtest.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/hwtest.h>
diff --git a/arch/m68knommu/include/asm/ioctls.h b/arch/m68knommu/include/asm/ioctls.h
deleted file mode 100644
index 0b1eb4d85059..000000000000
--- a/arch/m68knommu/include/asm/ioctls.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/ioctls.h>
diff --git a/arch/m68knommu/include/asm/ipcbuf.h b/arch/m68knommu/include/asm/ipcbuf.h
deleted file mode 100644
index e4a7be6dd706..000000000000
--- a/arch/m68knommu/include/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/ipcbuf.h>
diff --git a/arch/m68knommu/include/asm/linkage.h b/arch/m68knommu/include/asm/linkage.h
deleted file mode 100644
index c288a19ff489..000000000000
--- a/arch/m68knommu/include/asm/linkage.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/linkage.h>
diff --git a/arch/m68knommu/include/asm/local.h b/arch/m68knommu/include/asm/local.h
deleted file mode 100644
index 84a39c1b86f8..000000000000
--- a/arch/m68knommu/include/asm/local.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __M68KNOMMU_LOCAL_H
-#define __M68KNOMMU_LOCAL_H
-
-#include <asm-generic/local.h>
-
-#endif /* __M68KNOMMU_LOCAL_H */
diff --git a/arch/m68knommu/include/asm/math-emu.h b/arch/m68knommu/include/asm/math-emu.h
deleted file mode 100644
index 7e7090517b72..000000000000
--- a/arch/m68knommu/include/asm/math-emu.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/math-emu.h>
diff --git a/arch/m68knommu/include/asm/md.h b/arch/m68knommu/include/asm/md.h
deleted file mode 100644
index d810c78de5ff..000000000000
--- a/arch/m68knommu/include/asm/md.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/md.h>
diff --git a/arch/m68knommu/include/asm/mman.h b/arch/m68knommu/include/asm/mman.h
deleted file mode 100644
index 4846c682efed..000000000000
--- a/arch/m68knommu/include/asm/mman.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/mman.h>
diff --git a/arch/m68knommu/include/asm/movs.h b/arch/m68knommu/include/asm/movs.h
deleted file mode 100644
index 81a16779e833..000000000000
--- a/arch/m68knommu/include/asm/movs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/movs.h>
diff --git a/arch/m68knommu/include/asm/msgbuf.h b/arch/m68knommu/include/asm/msgbuf.h
deleted file mode 100644
index bdfadec4d52d..000000000000
--- a/arch/m68knommu/include/asm/msgbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/msgbuf.h>
diff --git a/arch/m68knommu/include/asm/openprom.h b/arch/m68knommu/include/asm/openprom.h
deleted file mode 100644
index fdba7953ff9f..000000000000
--- a/arch/m68knommu/include/asm/openprom.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/openprom.h>
diff --git a/arch/m68knommu/include/asm/oplib.h b/arch/m68knommu/include/asm/oplib.h
deleted file mode 100644
index ce079dc332d9..000000000000
--- a/arch/m68knommu/include/asm/oplib.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/oplib.h>
diff --git a/arch/m68knommu/include/asm/percpu.h b/arch/m68knommu/include/asm/percpu.h
deleted file mode 100644
index 5de72c327efd..000000000000
--- a/arch/m68knommu/include/asm/percpu.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ARCH_M68KNOMMU_PERCPU__
-#define __ARCH_M68KNOMMU_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* __ARCH_M68KNOMMU_PERCPU__ */
diff --git a/arch/m68knommu/include/asm/poll.h b/arch/m68knommu/include/asm/poll.h
deleted file mode 100644
index ee1b6cb549ca..000000000000
--- a/arch/m68knommu/include/asm/poll.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/poll.h>
diff --git a/arch/m68knommu/include/asm/posix_types.h b/arch/m68knommu/include/asm/posix_types.h
deleted file mode 100644
index 6205fb9392a3..000000000000
--- a/arch/m68knommu/include/asm/posix_types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/posix_types.h>
diff --git a/arch/m68knommu/include/asm/resource.h b/arch/m68knommu/include/asm/resource.h
deleted file mode 100644
index 7fa63d5ea576..000000000000
--- a/arch/m68knommu/include/asm/resource.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/resource.h>
diff --git a/arch/m68knommu/include/asm/rtc.h b/arch/m68knommu/include/asm/rtc.h
deleted file mode 100644
index eaf18ec83c8e..000000000000
--- a/arch/m68knommu/include/asm/rtc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/rtc.h>
diff --git a/arch/m68knommu/include/asm/sections.h b/arch/m68knommu/include/asm/sections.h
deleted file mode 100644
index dd0ecb98ec08..000000000000
--- a/arch/m68knommu/include/asm/sections.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _M68KNOMMU_SECTIONS_H
-#define _M68KNOMMU_SECTIONS_H
-
-/* nothing to see, move along */
-#include <asm-generic/sections.h>
-
-#endif
diff --git a/arch/m68knommu/include/asm/sembuf.h b/arch/m68knommu/include/asm/sembuf.h
deleted file mode 100644
index 3a634f9ecf50..000000000000
--- a/arch/m68knommu/include/asm/sembuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/sembuf.h>
diff --git a/arch/m68knommu/include/asm/shm.h b/arch/m68knommu/include/asm/shm.h
deleted file mode 100644
index cc8e522d9050..000000000000
--- a/arch/m68knommu/include/asm/shm.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/shm.h>
diff --git a/arch/m68knommu/include/asm/shmbuf.h b/arch/m68knommu/include/asm/shmbuf.h
deleted file mode 100644
index bc34cf8eefce..000000000000
--- a/arch/m68knommu/include/asm/shmbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/shmbuf.h>
diff --git a/arch/m68knommu/include/asm/shmparam.h b/arch/m68knommu/include/asm/shmparam.h
deleted file mode 100644
index d7ee69648ebf..000000000000
--- a/arch/m68knommu/include/asm/shmparam.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/shmparam.h>
diff --git a/arch/m68knommu/include/asm/socket.h b/arch/m68knommu/include/asm/socket.h
deleted file mode 100644
index ac5478bf6371..000000000000
--- a/arch/m68knommu/include/asm/socket.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/socket.h>
diff --git a/arch/m68knommu/include/asm/sockios.h b/arch/m68knommu/include/asm/sockios.h
deleted file mode 100644
index dcc6a8900ce2..000000000000
--- a/arch/m68knommu/include/asm/sockios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/sockios.h>
diff --git a/arch/m68knommu/include/asm/spinlock.h b/arch/m68knommu/include/asm/spinlock.h
deleted file mode 100644
index 6bb1f06c4781..000000000000
--- a/arch/m68knommu/include/asm/spinlock.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/spinlock.h>
diff --git a/arch/m68knommu/include/asm/stat.h b/arch/m68knommu/include/asm/stat.h
deleted file mode 100644
index 3d4b260e7c03..000000000000
--- a/arch/m68knommu/include/asm/stat.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/stat.h>
diff --git a/arch/m68knommu/include/asm/statfs.h b/arch/m68knommu/include/asm/statfs.h
deleted file mode 100644
index 2ce99eaf0970..000000000000
--- a/arch/m68knommu/include/asm/statfs.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/statfs.h>
diff --git a/arch/m68knommu/include/asm/termbits.h b/arch/m68knommu/include/asm/termbits.h
deleted file mode 100644
index 05dd6bc27285..000000000000
--- a/arch/m68knommu/include/asm/termbits.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/termbits.h>
diff --git a/arch/m68knommu/include/asm/termios.h b/arch/m68knommu/include/asm/termios.h
deleted file mode 100644
index e7337881a985..000000000000
--- a/arch/m68knommu/include/asm/termios.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/termios.h>
diff --git a/arch/m68knommu/include/asm/tlb.h b/arch/m68knommu/include/asm/tlb.h
deleted file mode 100644
index 77a7c51ca299..000000000000
--- a/arch/m68knommu/include/asm/tlb.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/tlb.h>
diff --git a/arch/m68knommu/include/asm/types.h b/arch/m68knommu/include/asm/types.h
deleted file mode 100644
index 031238c2d180..000000000000
--- a/arch/m68knommu/include/asm/types.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/types.h>
diff --git a/arch/m68knommu/include/asm/user.h b/arch/m68knommu/include/asm/user.h
deleted file mode 100644
index a5a555b761c4..000000000000
--- a/arch/m68knommu/include/asm/user.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-m68k/user.h>
diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile
index f0eab3dedb5a..37c3fc074c0a 100644
--- a/arch/m68knommu/kernel/Makefile
+++ b/arch/m68knommu/kernel/Makefile
@@ -8,4 +8,3 @@ obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \
setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_COMEMPCI) += comempci.o
diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c
deleted file mode 100644
index 0a68b5a85f86..000000000000
--- a/arch/m68knommu/kernel/comempci.c
+++ /dev/null
@@ -1,980 +0,0 @@
-/*****************************************************************************/
-
-/*
- * comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller.
- *
- * (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com).
- * (C) Copyright 2000, Lineo (www.lineo.com)
- */
-
-/*****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/ptrace.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/irq.h>
-#include <asm/anchor.h>
-
-#ifdef CONFIG_eLIA
-#include <asm/elia.h>
-#endif
-
-/*****************************************************************************/
-
-/*
- * Debug configuration defines. DEBUGRES sets debugging output for
- * the resource allocation phase. DEBUGPCI traces on pcibios_ function
- * calls, and DEBUGIO traces all accesses to devices on the PCI bus.
- */
-/*#define DEBUGRES 1*/
-/*#define DEBUGPCI 1*/
-/*#define DEBUGIO 1*/
-
-/*****************************************************************************/
-
-/*
- * PCI markers for bus present and active slots.
- */
-int pci_bus_is_present = 0;
-unsigned long pci_slotmask = 0;
-
-/*
- * We may or may not need to swap the bytes of PCI bus tranfers.
- * The endianess is re-roder automatically by the CO-MEM, but it
- * will get the wrong byte order for a pure data stream.
- */
-#define pci_byteswap 0
-
-
-/*
- * Resource tracking. The CO-MEM part creates a virtual address
- * space that all the PCI devices live in - it is not in any way
- * directly mapped into the ColdFire address space. So we can
- * really assign any resources we like to devices, as long as
- * they do not clash with other PCI devices.
- */
-unsigned int pci_iobase = PCIBIOS_MIN_IO; /* Arbitrary start address */
-unsigned int pci_membase = PCIBIOS_MIN_MEM; /* Arbitrary start address */
-
-#define PCI_MINIO 0x100 /* 256 byte minimum I/O */
-#define PCI_MINMEM 0x00010000 /* 64k minimum chunk */
-
-/*
- * The CO-MEM's shared memory segment is visible inside the PCI
- * memory address space. We need to keep track of the address that
- * this is mapped at, to setup the bus masters pointers.
- */
-unsigned int pci_shmemaddr;
-
-/*****************************************************************************/
-
-void pci_interrupt(int irq, void *id, struct pt_regs *fp);
-
-/*****************************************************************************/
-
-/*
- * Some platforms have custom ways of reseting the PCI bus.
- */
-
-void pci_resetbus(void)
-{
-#ifdef CONFIG_eLIA
- int i;
-
-#ifdef DEBUGPCI
- printk(KERN_DEBUG "pci_resetbus()\n");
-#endif
-
- *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADDR)) |= eLIA_PCIRESET;
- for (i = 0; (i < 1000); i++) {
- *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) =
- (ppdata | eLIA_PCIRESET);
- }
-
-
- *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = ppdata;
-#endif
-}
-
-/*****************************************************************************/
-
-int pcibios_assign_resource_slot(int slot)
-{
- volatile unsigned long *rp;
- volatile unsigned char *ip;
- unsigned int idsel, addr, val, align, i;
- int bar;
-
-#ifdef DEBUGPCI
- printk(KERN_INFO "pcibios_assign_resource_slot(slot=%x)\n", slot);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
-
- /* Try to assign resource to each BAR */
- for (bar = 0; (bar < 6); bar++) {
- addr = COMEM_PCIBUS + PCI_BASE_ADDRESS_0 + (bar * 4);
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
- val = rp[LREG(addr)];
-#ifdef DEBUGRES
- printk(KERN_DEBUG "-----------------------------------"
- "-------------------------------------\n");
- printk(KERN_DEBUG "BAR[%d]: read=%08x ", bar, val);
-#endif
-
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
- rp[LREG(addr)] = 0xffffffff;
-
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
- val = rp[LREG(addr)];
-#ifdef DEBUGRES
- printk(KERN_DEBUG "write=%08x ", val);
-#endif
- if (val == 0) {
-#ifdef DEBUGRES
- printk(KERN_DEBUG "\n");
-#endif
- continue;
- }
-
- /* Determine space required by BAR */
- /* FIXME: this should go backwords from 0x80000000... */
- for (i = 0; (i < 32); i++) {
- if ((0x1 << i) & (val & 0xfffffffc))
- break;
- }
-
-#ifdef DEBUGRES
- printk(KERN_DEBUG "size=%08x(%d)\n", (0x1 << i), i);
-#endif
- i = 0x1 << i;
-
- /* Assign a resource */
- if (val & PCI_BASE_ADDRESS_SPACE_IO) {
- if (i < PCI_MINIO)
- i = PCI_MINIO;
-#ifdef DEBUGRES
- printk(KERN_DEBUG "BAR[%d]: IO size=%08x iobase=%08x\n",
- bar, i, pci_iobase);
-#endif
- if (i > 0xffff) {
- /* Invalid size?? */
- val = 0 | PCI_BASE_ADDRESS_SPACE_IO;
-#ifdef DEBUGRES
- printk(KERN_DEBUG "BAR[%d]: too big for IO??\n", bar);
-#endif
- } else {
- /* Check for un-alignment */
- if ((align = pci_iobase % i))
- pci_iobase += (i - align);
- val = pci_iobase | PCI_BASE_ADDRESS_SPACE_IO;
- pci_iobase += i;
- }
- } else {
- if (i < PCI_MINMEM)
- i = PCI_MINMEM;
-#ifdef DEBUGRES
- printk(KERN_DEBUG "BAR[%d]: MEMORY size=%08x membase=%08x\n",
- bar, i, pci_membase);
-#endif
- /* Check for un-alignment */
- if ((align = pci_membase % i))
- pci_membase += (i - align);
- val = pci_membase | PCI_BASE_ADDRESS_SPACE_MEMORY;
- pci_membase += i;
- }
-
- /* Write resource back into BAR register */
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
- rp[LREG(addr)] = val;
-#ifdef DEBUGRES
- printk(KERN_DEBUG "BAR[%d]: assigned bar=%08x\n", bar, val);
-#endif
- }
-
-#ifdef DEBUGRES
- printk(KERN_DEBUG "-----------------------------------"
- "-------------------------------------\n");
-#endif
-
- /* Assign IRQ if one is wanted... */
- ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS);
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
-
- addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03);
- if (ip[addr]) {
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
- addr = (PCI_INTERRUPT_LINE & 0xfc)+(~PCI_INTERRUPT_LINE & 0x03);
- ip[addr] = 25;
-#ifdef DEBUGRES
- printk(KERN_DEBUG "IRQ LINE=25\n");
-#endif
- }
-
- return(0);
-}
-
-/*****************************************************************************/
-
-int pcibios_enable_slot(int slot)
-{
- volatile unsigned long *rp;
- volatile unsigned short *wp;
- unsigned int idsel, addr;
- unsigned short cmd;
-
-#ifdef DEBUGPCI
- printk(KERN_DEBUG "pcibios_enbale_slot(slot=%x)\n", slot);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- wp = (volatile unsigned short *) COMEM_BASE;
- idsel = COMEM_DA_ADDR(0x1 << (slot + 16));
-
- /* Get current command settings */
- addr = COMEM_PCIBUS + PCI_COMMAND;
- addr = (addr & ~0x3) + (~addr & 0x02);
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel;
- cmd = wp[WREG(addr)];
- /*val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);*/
-
- /* Enable I/O and memory accesses to this device */
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel;
- cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
- wp[WREG(addr)] = cmd;
-
- return(0);
-}
-
-/*****************************************************************************/
-
-void pcibios_assign_resources(void)
-{
- volatile unsigned long *rp;
- unsigned long sel, id;
- int slot;
-
- rp = (volatile unsigned long *) COMEM_BASE;
-
- /*
- * Do a quick scan of the PCI bus and see what is here.
- */
- for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) {
- sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
- rp[LREG(COMEM_DAHBASE)] = sel;
- rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
- id = rp[LREG(COMEM_PCIBUS)];
- if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) {
- printk(KERN_INFO "PCI: slot=%d id=%08x\n", slot, (int) id);
- pci_slotmask |= 0x1 << slot;
- pcibios_assign_resource_slot(slot);
- pcibios_enable_slot(slot);
- }
- }
-}
-
-/*****************************************************************************/
-
-int pcibios_init(void)
-{
- volatile unsigned long *rp;
- unsigned long sel, id;
- int slot;
-
-#ifdef DEBUGPCI
- printk(KERN_DEBUG "pcibios_init()\n");
-#endif
-
- pci_resetbus();
-
- /*
- * Do some sort of basic check to see if the CO-MEM part
- * is present... This works ok, but I think we really need
- * something better...
- */
- rp = (volatile unsigned long *) COMEM_BASE;
- if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) {
- printk(KERN_INFO "PCI: no PCI bus present\n");
- return(0);
- }
-
-#ifdef COMEM_BRIDGEDEV
- /*
- * Setup the PCI bridge device first. It needs resources too,
- * so that bus masters can get to its shared memory.
- */
- slot = COMEM_BRIDGEDEV;
- sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16));
- rp[LREG(COMEM_DAHBASE)] = sel;
- rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */
- id = rp[LREG(COMEM_PCIBUS)];
- if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) {
- printk(KERN_INFO "PCI: no PCI bus bridge present\n");
- return(0);
- }
-
- printk(KERN_INFO "PCI: bridge device at slot=%d id=%08x\n", slot, (int) id);
- pci_slotmask |= 0x1 << slot;
- pci_shmemaddr = pci_membase;
- pcibios_assign_resource_slot(slot);
- pcibios_enable_slot(slot);
-#endif
-
- pci_bus_is_present = 1;
-
- /* Get PCI irq for local vectoring */
- if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) {
- printk(KERN_WARNING "PCI: failed to acquire interrupt %d\n", COMEM_IRQ);
- } else {
- mcf_autovector(COMEM_IRQ);
- }
-
- pcibios_assign_resources();
-
- return(0);
-}
-
-/*****************************************************************************/
-
-char *pcibios_setup(char *option)
-{
- /* Nothing for us to handle. */
- return(option);
-}
-/*****************************************************************************/
-
-void pcibios_fixup_bus(struct pci_bus *b)
-{
-}
-
-/*****************************************************************************/
-
-void pcibios_align_resource(void *data, struct resource *res,
- resource_size_t size, resource_size_t align)
-{
-}
-
-/*****************************************************************************/
-
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
- int slot;
-
- slot = PCI_SLOT(dev->devfn);
- if ((dev->bus == 0) && (pci_slotmask & (1 << slot)))
- pcibios_enable_slot(slot);
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Local routines to interrcept the standard I/O and vector handling
- * code. Don't include this 'till now - initialization code above needs
- * access to the real code too.
- */
-#include <asm/mcfpci.h>
-
-/*****************************************************************************/
-
-void pci_outb(unsigned char val, unsigned int addr)
-{
- volatile unsigned long *rp;
- volatile unsigned char *bp;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_outb(val=%02x,addr=%x)\n", val, addr);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- bp = (volatile unsigned char *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
- addr = (addr & ~0x3) + (~addr & 0x03);
- bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
-}
-
-/*****************************************************************************/
-
-void pci_outw(unsigned short val, unsigned int addr)
-{
- volatile unsigned long *rp;
- volatile unsigned short *sp;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_outw(val=%04x,addr=%x)\n", val, addr);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- sp = (volatile unsigned short *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
- addr = (addr & ~0x3) + (~addr & 0x02);
- if (pci_byteswap)
- val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
- sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
-}
-
-/*****************************************************************************/
-
-void pci_outl(unsigned int val, unsigned int addr)
-{
- volatile unsigned long *rp;
- volatile unsigned int *lp;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_outl(val=%08x,addr=%x)\n", val, addr);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- lp = (volatile unsigned int *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr);
-
- if (pci_byteswap)
- val = (val << 24) | ((val & 0x0000ff00) << 8) |
- ((val & 0x00ff0000) >> 8) | (val >> 24);
-
- lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val;
-}
-
-/*****************************************************************************/
-
-unsigned long pci_blmask[] = {
- 0x000000e0,
- 0x000000d0,
- 0x000000b0,
- 0x00000070
-};
-
-unsigned char pci_inb(unsigned int addr)
-{
- volatile unsigned long *rp;
- volatile unsigned char *bp;
- unsigned long r;
- unsigned char val;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_inb(addr=%x)\n", addr);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- bp = (volatile unsigned char *) COMEM_BASE;
-
- r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_blmask[(addr & 0x3)];
- rp[LREG(COMEM_DAHBASE)] = r;
-
- addr = (addr & ~0x3) + (~addr & 0x3);
- val = bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
- return(val);
-}
-
-/*****************************************************************************/
-
-unsigned long pci_bwmask[] = {
- 0x000000c0,
- 0x000000c0,
- 0x00000030,
- 0x00000030
-};
-
-unsigned short pci_inw(unsigned int addr)
-{
- volatile unsigned long *rp;
- volatile unsigned short *sp;
- unsigned long r;
- unsigned short val;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_inw(addr=%x)", addr);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_bwmask[(addr & 0x3)];
- rp[LREG(COMEM_DAHBASE)] = r;
-
- sp = (volatile unsigned short *) COMEM_BASE;
- addr = (addr & ~0x3) + (~addr & 0x02);
- val = sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
- if (pci_byteswap)
- val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);
-#ifdef DEBUGIO
- printk(KERN_DEBUG "=%04x\n", val);
-#endif
- return(val);
-}
-
-/*****************************************************************************/
-
-unsigned int pci_inl(unsigned int addr)
-{
- volatile unsigned long *rp;
- volatile unsigned int *lp;
- unsigned int val;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_inl(addr=%x)", addr);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- lp = (volatile unsigned int *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr);
- val = lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))];
-
- if (pci_byteswap)
- val = (val << 24) | ((val & 0x0000ff00) << 8) |
- ((val & 0x00ff0000) >> 8) | (val >> 24);
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "=%08x\n", val);
-#endif
- return(val);
-}
-
-/*****************************************************************************/
-
-void pci_outsb(void *addr, void *buf, int len)
-{
- volatile unsigned long *rp;
- volatile unsigned char *bp;
- unsigned char *dp = (unsigned char *) buf;
- unsigned int a = (unsigned int) addr;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_outsb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
-
- a = (a & ~0x3) + (~a & 0x03);
- bp = (volatile unsigned char *)
- (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
-
- while (len--)
- *bp = *dp++;
-}
-
-/*****************************************************************************/
-
-void pci_outsw(void *addr, void *buf, int len)
-{
- volatile unsigned long *rp;
- volatile unsigned short *wp;
- unsigned short w, *dp = (unsigned short *) buf;
- unsigned int a = (unsigned int) addr;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_outsw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
-
- a = (a & ~0x3) + (~a & 0x2);
- wp = (volatile unsigned short *)
- (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
-
- while (len--) {
- w = *dp++;
- if (pci_byteswap)
- w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
- *wp = w;
- }
-}
-
-/*****************************************************************************/
-
-void pci_outsl(void *addr, void *buf, int len)
-{
- volatile unsigned long *rp;
- volatile unsigned long *lp;
- unsigned long l, *dp = (unsigned long *) buf;
- unsigned int a = (unsigned int) addr;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_outsl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a);
-
- lp = (volatile unsigned long *)
- (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
-
- while (len--) {
- l = *dp++;
- if (pci_byteswap)
- l = (l << 24) | ((l & 0x0000ff00) << 8) |
- ((l & 0x00ff0000) >> 8) | (l >> 24);
- *lp = l;
- }
-}
-
-/*****************************************************************************/
-
-void pci_insb(void *addr, void *buf, int len)
-{
- volatile unsigned long *rp;
- volatile unsigned char *bp;
- unsigned char *dp = (unsigned char *) buf;
- unsigned int a = (unsigned int) addr;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_insb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
-
- a = (a & ~0x3) + (~a & 0x03);
- bp = (volatile unsigned char *)
- (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
-
- while (len--)
- *dp++ = *bp;
-}
-
-/*****************************************************************************/
-
-void pci_insw(void *addr, void *buf, int len)
-{
- volatile unsigned long *rp;
- volatile unsigned short *wp;
- unsigned short w, *dp = (unsigned short *) buf;
- unsigned int a = (unsigned int) addr;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_insw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
-
- a = (a & ~0x3) + (~a & 0x2);
- wp = (volatile unsigned short *)
- (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
-
- while (len--) {
- w = *wp;
- if (pci_byteswap)
- w = ((w & 0xff) << 8) | ((w >> 8) & 0xff);
- *dp++ = w;
- }
-}
-
-/*****************************************************************************/
-
-void pci_insl(void *addr, void *buf, int len)
-{
- volatile unsigned long *rp;
- volatile unsigned long *lp;
- unsigned long l, *dp = (unsigned long *) buf;
- unsigned int a = (unsigned int) addr;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_insl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len);
-#endif
-
- rp = (volatile unsigned long *) COMEM_BASE;
- rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a);
-
- lp = (volatile unsigned long *)
- (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a));
-
- while (len--) {
- l = *lp;
- if (pci_byteswap)
- l = (l << 24) | ((l & 0x0000ff00) << 8) |
- ((l & 0x00ff0000) >> 8) | (l >> 24);
- *dp++ = l;
- }
-}
-
-/*****************************************************************************/
-
-struct pci_localirqlist {
- void (*handler)(int, void *, struct pt_regs *);
- const char *device;
- void *dev_id;
-};
-
-struct pci_localirqlist pci_irqlist[COMEM_MAXPCI];
-
-/*****************************************************************************/
-
-int pci_request_irq(unsigned int irq,
- void (*handler)(int, void *, struct pt_regs *),
- unsigned long flags, const char *device, void *dev_id)
-{
- int i;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_request_irq(irq=%d,handler=%x,flags=%x,device=%s,"
- "dev_id=%x)\n", irq, (int) handler, (int) flags, device,
- (int) dev_id);
-#endif
-
- /* Check if this interrupt handler is already lodged */
- for (i = 0; (i < COMEM_MAXPCI); i++) {
- if (pci_irqlist[i].handler == handler)
- return(0);
- }
-
- /* Find a free spot to put this handler */
- for (i = 0; (i < COMEM_MAXPCI); i++) {
- if (pci_irqlist[i].handler == 0) {
- pci_irqlist[i].handler = handler;
- pci_irqlist[i].device = device;
- pci_irqlist[i].dev_id = dev_id;
- return(0);
- }
- }
-
- /* Couldn't fit?? */
- return(1);
-}
-
-/*****************************************************************************/
-
-void pci_free_irq(unsigned int irq, void *dev_id)
-{
- int i;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_free_irq(irq=%d,dev_id=%x)\n", irq, (int) dev_id);
-#endif
-
- if (dev_id == (void *) NULL)
- return;
-
- /* Check if this interrupt handler is lodged */
- for (i = 0; (i < COMEM_MAXPCI); i++) {
- if (pci_irqlist[i].dev_id == dev_id) {
- pci_irqlist[i].handler = NULL;
- pci_irqlist[i].device = NULL;
- pci_irqlist[i].dev_id = NULL;
- break;
- }
- }
-}
-
-/*****************************************************************************/
-
-void pci_interrupt(int irq, void *id, struct pt_regs *fp)
-{
- int i;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_interrupt(irq=%d,id=%x,fp=%x)\n", irq, (int) id, (int) fp);
-#endif
-
- for (i = 0; (i < COMEM_MAXPCI); i++) {
- if (pci_irqlist[i].handler)
- (*pci_irqlist[i].handler)(irq,pci_irqlist[i].dev_id,fp);
- }
-}
-
-/*****************************************************************************/
-
-/*
- * The shared memory region is broken up into contiguous 512 byte
- * regions for easy allocation... This is not an optimal solution
- * but it makes allocation and freeing regions really easy.
- */
-
-#define PCI_MEMSLOTSIZE 512
-#define PCI_MEMSLOTS (COMEM_SHMEMSIZE / PCI_MEMSLOTSIZE)
-
-char pci_shmemmap[PCI_MEMSLOTS];
-
-
-void *pci_bmalloc(int size)
-{
- int i, j, nrslots;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_bmalloc(size=%d)\n", size);
-#endif
-
- if (size <= 0)
- return((void *) NULL);
-
- nrslots = (size - 1) / PCI_MEMSLOTSIZE;
-
- for (i = 0; (i < (PCI_MEMSLOTS-nrslots)); i++) {
- if (pci_shmemmap[i] == 0) {
- for (j = i+1; (j < (i+nrslots)); j++) {
- if (pci_shmemmap[j])
- goto restart;
- }
-
- for (j = i; (j <= i+nrslots); j++)
- pci_shmemmap[j] = 1;
- break;
- }
-restart:
- }
-
- return((void *) (COMEM_BASE + COMEM_SHMEM + (i * PCI_MEMSLOTSIZE)));
-}
-
-/*****************************************************************************/
-
-void pci_bmfree(void *mp, int size)
-{
- int i, j, nrslots;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_bmfree(mp=%x,size=%d)\n", (int) mp, size);
-#endif
-
- nrslots = size / PCI_MEMSLOTSIZE;
- i = (((unsigned long) mp) - (COMEM_BASE + COMEM_SHMEM)) /
- PCI_MEMSLOTSIZE;
-
- for (j = i; (j < (i+nrslots)); j++)
- pci_shmemmap[j] = 0;
-}
-
-/*****************************************************************************/
-
-unsigned long pci_virt_to_bus(volatile void *address)
-{
- unsigned long l;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_virt_to_bus(address=%x)", (int) address);
-#endif
-
- l = ((unsigned long) address) - COMEM_BASE;
-#ifdef DEBUGIO
- printk(KERN_DEBUG "=%x\n", (int) (l+pci_shmemaddr));
-#endif
- return(l + pci_shmemaddr);
-}
-
-/*****************************************************************************/
-
-void *pci_bus_to_virt(unsigned long address)
-{
- unsigned long l;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_bus_to_virt(address=%x)", (int) address);
-#endif
-
- l = address - pci_shmemaddr;
-#ifdef DEBUGIO
- printk(KERN_DEBUG "=%x\n", (int) (address + COMEM_BASE));
-#endif
- return((void *) (address + COMEM_BASE));
-}
-
-/*****************************************************************************/
-
-void pci_bmcpyto(void *dst, void *src, int len)
-{
- unsigned long *dp, *sp, val;
- unsigned char *dcp, *scp;
- int i, j;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_bmcpyto(dst=%x,src=%x,len=%d)\n", (int)dst, (int)src, len);
-#endif
-
- dp = (unsigned long *) dst;
- sp = (unsigned long *) src;
- i = len >> 2;
-
-#if 0
- printk(KERN_INFO "DATA:");
- scp = (unsigned char *) sp;
- for (i = 0; (i < len); i++) {
- if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
- printk(KERN_INFO "%02x ", *scp++);
- }
- printk(KERN_INFO "\n");
-#endif
-
- for (j = 0; (i >= 0); i--, j++) {
- val = *sp++;
- val = (val << 24) | ((val & 0x0000ff00) << 8) |
- ((val & 0x00ff0000) >> 8) | (val >> 24);
- *dp++ = val;
- }
-
- if (len & 0x3) {
- dcp = (unsigned char *) dp;
- scp = ((unsigned char *) sp) + 3;
- for (i = 0; (i < (len & 0x3)); i++)
- *dcp++ = *scp--;
- }
-}
-
-/*****************************************************************************/
-
-void pci_bmcpyfrom(void *dst, void *src, int len)
-{
- unsigned long *dp, *sp, val;
- unsigned char *dcp, *scp;
- int i;
-
-#ifdef DEBUGIO
- printk(KERN_DEBUG "pci_bmcpyfrom(dst=%x,src=%x,len=%d)\n",(int)dst,(int)src,len);
-#endif
-
- dp = (unsigned long *) dst;
- sp = (unsigned long *) src;
- i = len >> 2;
-
- for (; (i >= 0); i--) {
- val = *sp++;
- val = (val << 24) | ((val & 0x0000ff00) << 8) |
- ((val & 0x00ff0000) >> 8) | (val >> 24);
- *dp++ = val;
- }
-
- if (len & 0x3) {
- dcp = ((unsigned char *) dp) + 3;
- scp = (unsigned char *) sp;
- for (i = 0; (i < (len & 0x3)); i++)
- *dcp++ = *scp--;
- }
-
-#if 0
- printk(KERN_INFO "DATA:");
- dcp = (unsigned char *) dst;
- for (i = 0; (i < len); i++) {
- if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i);
- printk(KERN_INFO "%02x ", *dcp++);
- }
- printk(KERN_INFO "\n");
-#endif
-}
-
-/*****************************************************************************/
-
-void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addr)
-{
- void *mp;
- if ((mp = pci_bmalloc(size)) != NULL) {
- dma_addr = mp - (COMEM_BASE + COMEM_SHMEM);
- return(mp);
- }
- *dma_addr = (dma_addr_t) NULL;
- return(NULL);
-}
-
-/*****************************************************************************/
-
-void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr)
-{
- pci_bmfree(cpu_addr, size);
-}
-
-/*****************************************************************************/
diff --git a/arch/m68knommu/kernel/init_task.c b/arch/m68knommu/kernel/init_task.c
index 344c01aede08..fe282de1d596 100644
--- a/arch/m68knommu/kernel/init_task.c
+++ b/arch/m68knommu/kernel/init_task.c
@@ -12,7 +12,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index bbfcae9e52b4..5ab6a04af14e 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -279,6 +279,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
struct sigcontext context;
int err = 0;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
/* get previous context */
if (copy_from_user(&context, usc, sizeof(context)))
goto badframe;
@@ -316,6 +319,9 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
unsigned long usp;
int err;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
err = __get_user(temp, &uc->uc_mcontext.version);
if (temp != MCONTEXT_VERSION)
goto badframe;
@@ -692,6 +698,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
regs->d0 = -EINTR;
break;
+ case -ERESTART_RESTARTBLOCK:
+ if (!has_handler) {
+ regs->d0 = __NR_restart_syscall;
+ regs->pc -= 2;
+ break;
+ }
+ regs->d0 = -EINTR;
+ break;
+
case -ERESTARTSYS:
if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
regs->d0 = -EINTR;
diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
index 812f8d8b7a85..1017e76f3711 100644
--- a/arch/m68knommu/kernel/syscalltable.S
+++ b/arch/m68knommu/kernel/syscalltable.S
@@ -18,7 +18,7 @@
.text
ALIGN
ENTRY(sys_call_table)
- .long sys_ni_syscall /* 0 - old "setup()" system call*/
+ .long sys_restart_syscall /* 0 - old "setup()" system call */
.long sys_exit
.long sys_fork
.long sys_read
@@ -107,7 +107,7 @@ ENTRY(sys_call_table)
.long sys_uselib
.long sys_ni_syscall /* sys_swapon */
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c
index 11cff6625dcc..724faf05852a 100644
--- a/arch/m68knommu/platform/5307/config.c
+++ b/arch/m68knommu/platform/5307/config.c
@@ -123,7 +123,7 @@ void __init config_BSP(char *commandp, int size)
{
mcf_setimr(MCFSIM_IMR_MASKALL);
-#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
+#if defined(CONFIG_NETtel) || \
defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
/* Copy command line from FLASH to local buffer... */
memcpy(commandp, (char *) 0xf0004000, size);
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
index 4f44b632045b..a347623d6ee6 100644
--- a/arch/m68knommu/platform/532x/config.c
+++ b/arch/m68knommu/platform/532x/config.c
@@ -41,15 +41,15 @@ extern unsigned int mcf_timerlevel;
static struct mcf_platform_uart m532x_uart_platform[] = {
{
- .mapbase = MCF_MBAR + MCFUART_BASE1,
+ .mapbase = MCFUART_BASE1,
.irq = MCFINT_VECBASE + MCFINT_UART0,
},
{
- .mapbase = MCF_MBAR + MCFUART_BASE2,
+ .mapbase = MCFUART_BASE2,
.irq = MCFINT_VECBASE + MCFINT_UART1,
},
{
- .mapbase = MCF_MBAR + MCFUART_BASE3,
+ .mapbase = MCFUART_BASE3,
.irq = MCFINT_VECBASE + MCFINT_UART2,
},
{ },
@@ -108,7 +108,7 @@ void mcf_settimericr(unsigned int timer, unsigned int level)
default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
}
- icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+ icrp = (volatile unsigned char *) (icr);
*icrp = level;
mcf_enable_irq0(irq);
}
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S
index 1e3c0dcbd7ac..3b471c0da24a 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68knommu/platform/coldfire/entry.S
@@ -215,19 +215,8 @@ ENTRY(fasthandler)
RESTORE_LOCAL
ENTRY(ret_from_interrupt)
- moveb %sp@(PT_SR),%d0
- andl #0x7,%d0
- jeq 1f
-
- RESTORE_ALL
-
-1:
- /* check if we need to do software interrupts */
- movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
- jeq ret_from_exception
-
- pea ret_from_exception
- jmp do_softirq
+ /* the fasthandler is confusing me, haven't seen any user */
+ jmp ret_from_exception
/*
* Beware - when entering resume, prev (the current task) is
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c
index c5b916700b22..2a12e7fa9748 100644
--- a/arch/m68knommu/platform/coldfire/pit.c
+++ b/arch/m68knommu/platform/coldfire/pit.c
@@ -156,7 +156,7 @@ void hw_timer_init(void)
{
u32 imr;
- cf_pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
+ cf_pit_clockevent.cpumask = cpumask_of(smp_processor_id());
cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
cf_pit_clockevent.max_delta_ns =
clockevent_delta2ns(0xFFFF, &cf_pit_clockevent);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index a5255e7c79e0..600eef3f3ac7 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -351,7 +351,7 @@ config SGI_IP27
select ARC64
select BOOT_ELF64
select DEFAULT_SGI_PARTITION
- select DMA_IP27
+ select DMA_COHERENT
select SYS_HAS_EARLY_PRINTK
select HW_HAS_PCI
select NR_CPUS_DEFAULT_64
@@ -595,6 +595,44 @@ config WR_PPMC
This enables support for the Wind River MIPS32 4KC PPMC evaluation
board, which is based on GT64120 bridge chip.
+config CAVIUM_OCTEON_SIMULATOR
+ bool "Support for the Cavium Networks Octeon Simulator"
+ select CEVT_R4K
+ select 64BIT_PHYS_ADDR
+ select DMA_COHERENT
+ select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
+ select CPU_CAVIUM_OCTEON
+ help
+ The Octeon simulator is software performance model of the Cavium
+ Octeon Processor. It supports simulating Octeon processors on x86
+ hardware.
+
+config CAVIUM_OCTEON_REFERENCE_BOARD
+ bool "Support for the Cavium Networks Octeon reference board"
+ select CEVT_R4K
+ select 64BIT_PHYS_ADDR
+ select DMA_COHERENT
+ select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
+ select SYS_HAS_EARLY_PRINTK
+ select CPU_CAVIUM_OCTEON
+ select SWAP_IO_SPACE
+ help
+ This option supports all of the Octeon reference boards from Cavium
+ Networks. It builds a kernel that dynamically determines the Octeon
+ CPU type and supports all known board reference implementations.
+ Some of the supported boards are:
+ EBT3000
+ EBH3000
+ EBH3100
+ Thunder
+ Kodama
+ Hikari
+ Say Y here for most Octeon reference boards.
+
endchoice
source "arch/mips/alchemy/Kconfig"
@@ -607,6 +645,7 @@ source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig"
+source "arch/mips/cavium-octeon/Kconfig"
endmenu
@@ -682,7 +721,11 @@ config CEVT_DS1287
config CEVT_GT641XX
bool
+config CEVT_R4K_LIB
+ bool
+
config CEVT_R4K
+ select CEVT_R4K_LIB
bool
config CEVT_SB1250
@@ -697,7 +740,11 @@ config CSRC_BCM1480
config CSRC_IOASIC
bool
+config CSRC_R4K_LIB
+ bool
+
config CSRC_R4K
+ select CSRC_R4K_LIB
bool
config CSRC_SB1250
@@ -714,9 +761,6 @@ config CFE
config DMA_COHERENT
bool
-config DMA_IP27
- bool
-
config DMA_NONCOHERENT
bool
select DMA_NEED_PCI_MAP_STATE
@@ -835,6 +879,9 @@ config IRQ_GT641XX
config IRQ_GIC
bool
+config IRQ_CPU_OCTEON
+ bool
+
config MIPS_BOARDS_GEN
bool
@@ -924,7 +971,7 @@ config BOOT_ELF32
config MIPS_L1_CACHE_SHIFT
int
default "4" if MACH_DECSTATION || MIKROTIK_RB532
- default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM
+ default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
default "4" if PMC_MSP4200_EVAL
default "5"
@@ -1185,6 +1232,23 @@ config CPU_SB1
select CPU_SUPPORTS_HIGHMEM
select WEAK_ORDERING
+config CPU_CAVIUM_OCTEON
+ bool "Cavium Octeon processor"
+ select IRQ_CPU
+ select IRQ_CPU_OCTEON
+ select CPU_HAS_PREFETCH
+ select CPU_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_SMP
+ select NR_CPUS_DEFAULT_16
+ select WEAK_ORDERING
+ select WEAK_REORDERING_BEYOND_LLSC
+ select CPU_SUPPORTS_HIGHMEM
+ help
+ The Cavium Octeon processor is a highly integrated chip containing
+ many ethernet hardware widgets for networking tasks. The processor
+ can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets.
+ Full details can be found at http://www.caviumnetworks.com.
+
endchoice
config SYS_HAS_CPU_LOONGSON2
@@ -1285,7 +1349,7 @@ config CPU_MIPSR1
config CPU_MIPSR2
bool
- default y if CPU_MIPS32_R2 || CPU_MIPS64_R2
+ default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
config SYS_SUPPORTS_32BIT_KERNEL
bool
@@ -1301,7 +1365,7 @@ config CPU_SUPPORTS_64BIT_KERNEL
#
config HARDWARE_WATCHPOINTS
bool
- default y if CPU_MIPS32 || CPU_MIPS64
+ default y if CPU_MIPSR1 || CPU_MIPSR2
menu "Kernel type"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 28c55f608913..21b00e95daef 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -144,6 +144,10 @@ cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \
cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap
cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \
-Wa,--trap
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += $(call cc-option,-march=octeon) -Wa,--trap
+ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON))))
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
+endif
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
@@ -184,84 +188,84 @@ cflags-$(CONFIG_SOC_AU1X00) += -I$(srctree)/arch/mips/include/asm/mach-au1x00
#
# AMD Alchemy Pb1000 eval board
#
-libs-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/pb1000/
+core-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000
#
# AMD Alchemy Pb1100 eval board
#
-libs-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/pb1100/
+core-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000
#
# AMD Alchemy Pb1500 eval board
#
-libs-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/pb1500/
+core-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000
#
# AMD Alchemy Pb1550 eval board
#
-libs-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/pb1550/
+core-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000
#
# AMD Alchemy Pb1200 eval board
#
-libs-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/pb1200/
+core-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000
#
# AMD Alchemy Db1000 eval board
#
-libs-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000
#
# AMD Alchemy Db1100 eval board
#
-libs-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000
#
# AMD Alchemy Db1500 eval board
#
-libs-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000
#
# AMD Alchemy Db1550 eval board
#
-libs-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000
#
# AMD Alchemy Db1200 eval board
#
-libs-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/pb1200/
+core-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000
#
# AMD Alchemy Bosporus eval board
#
-libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000
#
# AMD Alchemy Mirage eval board
#
-libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/devboards/
cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000
@@ -586,6 +590,18 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/
core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/
+#
+# Cavium Octeon
+#
+core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon
+core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/executive/
+ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff84100000
+else
+load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000
+endif
+
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
drivers-$(CONFIG_PCI) += arch/mips/pci/
diff --git a/arch/mips/alchemy/Kconfig b/arch/mips/alchemy/Kconfig
index e4a057d80ab6..7f8ef13d0014 100644
--- a/arch/mips/alchemy/Kconfig
+++ b/arch/mips/alchemy/Kconfig
@@ -128,9 +128,10 @@ config SOC_AU1200
config SOC_AU1X00
bool
select 64BIT_PHYS_ADDR
- select CEVT_R4K
- select CSRC_R4K
+ select CEVT_R4K_LIB
+ select CSRC_R4K_LIB
select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_APM_EMULATION
+ select GENERIC_HARDIRQS_NO__DO_IRQ
diff --git a/arch/mips/alchemy/common/Makefile b/arch/mips/alchemy/common/Makefile
index df48fd65bbf3..d50d4764eafe 100644
--- a/arch/mips/alchemy/common/Makefile
+++ b/arch/mips/alchemy/common/Makefile
@@ -6,8 +6,8 @@
#
obj-y += prom.o irq.o puts.o time.o reset.o \
- au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
- sleeper.o cputable.o dma.o dbdma.o gpio.o
+ clocks.o platform.o power.o setup.o \
+ sleeper.o dma.o dbdma.o gpio.o
obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/mips/alchemy/common/au1xxx_irqmap.c b/arch/mips/alchemy/common/au1xxx_irqmap.c
deleted file mode 100644
index c7ca1596394c..000000000000
--- a/arch/mips/alchemy/common/au1xxx_irqmap.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Au1xxx processor specific IRQ tables
- *
- * Copyright 2004 Embedded Edge, LLC
- * dan@embeddededge.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <au1000.h>
-
-/* The IC0 interrupt table. This is processor, rather than
- * board dependent, so no reason to keep this info in the board
- * dependent files.
- *
- * Careful if you change match 2 request!
- * The interrupt handler is called directly from the low level dispatch code.
- */
-struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = {
-
-#if defined(CONFIG_SOC_AU1000)
- { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
- { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
-
-#elif defined(CONFIG_SOC_AU1500)
-
- { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
- { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
-
-#elif defined(CONFIG_SOC_AU1100)
-
- { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
- { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- /* { AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0 }, */
- { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
-
-#elif defined(CONFIG_SOC_AU1550)
-
- { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
- { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
- { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
- { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
- { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 },
- { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
- { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
- { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-
-#elif defined(CONFIG_SOC_AU1200)
-
- { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
- { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0 },
- { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
- { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0 },
-
-#else
-#error "Error: Unknown Alchemy SOC"
-#endif
-
-};
-
-int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map);
diff --git a/arch/mips/alchemy/common/clocks.c b/arch/mips/alchemy/common/clocks.c
index 043429d17c5f..d8991854530e 100644
--- a/arch/mips/alchemy/common/clocks.c
+++ b/arch/mips/alchemy/common/clocks.c
@@ -27,12 +27,21 @@
*/
#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/time.h>
#include <asm/mach-au1x00/au1000.h>
+/*
+ * I haven't found anyone that doesn't use a 12 MHz source clock,
+ * but just in case.....
+ */
+#define AU1000_SRC_CLK 12000000
+
static unsigned int au1x00_clock; /* Hz */
-static unsigned int lcd_clock; /* KHz */
static unsigned long uart_baud_base;
+static DEFINE_SPINLOCK(time_lock);
+
/*
* Set the au1000_clock
*/
@@ -63,31 +72,45 @@ void set_au1x00_uart_baud_base(unsigned long new_baud_base)
}
/*
- * Calculate the Au1x00's LCD clock based on the current
- * cpu clock and the system bus clock, and try to keep it
- * below 40 MHz (the Pb1000 board can lock-up if the LCD
- * clock is over 40 MHz).
+ * We read the real processor speed from the PLL. This is important
+ * because it is more accurate than computing it from the 32 KHz
+ * counter, if it exists. If we don't have an accurate processor
+ * speed, all of the peripherals that derive their clocks based on
+ * this advertised speed will introduce error and sometimes not work
+ * properly. This function is futher convoluted to still allow configurations
+ * to do that in case they have really, really old silicon with a
+ * write-only PLL register. -- Dan
*/
-void set_au1x00_lcd_clock(void)
+unsigned long au1xxx_calc_clock(void)
{
- unsigned int static_cfg0;
- unsigned int sys_busclk = (get_au1x00_speed() / 1000) /
- ((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2);
+ unsigned long cpu_speed;
+ unsigned long flags;
- static_cfg0 = au_readl(MEM_STCFG0);
+ spin_lock_irqsave(&time_lock, flags);
- if (static_cfg0 & (1 << 11))
- lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
+ /*
+ * On early Au1000, sys_cpupll was write-only. Since these
+ * silicon versions of Au1000 are not sold by AMD, we don't bend
+ * over backwards trying to determine the frequency.
+ */
+ if (au1xxx_cpu_has_pll_wo())
+#ifdef CONFIG_SOC_AU1000_FREQUENCY
+ cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
+#else
+ cpu_speed = 396000000;
+#endif
else
- lcd_clock = sys_busclk / 4;
+ cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
- if (lcd_clock > 50000) /* Epson MAX */
- printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n",
- lcd_clock);
-}
+ /* On Alchemy CPU:counter ratio is 1:1 */
+ mips_hpt_frequency = cpu_speed;
+ /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
+ set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
+ & 0x03) + 2) * 16));
-unsigned int get_au1x00_lcd_clock(void)
-{
- return lcd_clock;
+ spin_unlock_irqrestore(&time_lock, flags);
+
+ set_au1x00_speed(cpu_speed);
+
+ return cpu_speed;
}
-EXPORT_SYMBOL(get_au1x00_lcd_clock);
diff --git a/arch/mips/alchemy/common/cputable.c b/arch/mips/alchemy/common/cputable.c
deleted file mode 100644
index ba6430bc2d03..000000000000
--- a/arch/mips/alchemy/common/cputable.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * arch/mips/au1000/common/cputable.c
- *
- * Copyright (C) 2004 Dan Malek (dan@embeddededge.com)
- * Copied from PowerPC and updated for Alchemy Au1xxx processors.
- *
- * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/mach-au1x00/au1000.h>
-
-struct cpu_spec *cur_cpu_spec[NR_CPUS];
-
-/* With some thought, we can probably use the mask to reduce the
- * size of the table.
- */
-struct cpu_spec cpu_specs[] = {
- { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 },
- { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 },
- { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 },
- { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 },
- { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 },
- { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 },
- { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 },
- { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 },
- { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 },
- { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 },
- { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 },
- { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 },
- { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 },
- { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 },
- { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 },
- { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 },
- { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 }
-};
-
-void set_cpuspec(void)
-{
- struct cpu_spec *sp;
- u32 prid;
-
- prid = read_c0_prid();
- sp = cpu_specs;
- while ((prid & sp->prid_mask) != sp->prid_value)
- sp++;
- cur_cpu_spec[0] = sp;
-}
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index 601ee9180ee4..3ab6d80d150d 100644
--- a/arch/mips/alchemy/common/dbdma.c
+++ b/arch/mips/alchemy/common/dbdma.c
@@ -174,6 +174,11 @@ static dbdev_tab_t dbdev_tab[] = {
#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab)
+#ifdef CONFIG_PM
+static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][8];
+#endif
+
+
static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
static dbdev_tab_t *find_dbdev_id(u32 id)
@@ -975,4 +980,64 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
return nbytes;
}
+#ifdef CONFIG_PM
+void au1xxx_dbdma_suspend(void)
+{
+ int i;
+ u32 addr;
+
+ addr = DDMA_GLOBAL_BASE;
+ au1xxx_dbdma_pm_regs[0][0] = au_readl(addr + 0x00);
+ au1xxx_dbdma_pm_regs[0][1] = au_readl(addr + 0x04);
+ au1xxx_dbdma_pm_regs[0][2] = au_readl(addr + 0x08);
+ au1xxx_dbdma_pm_regs[0][3] = au_readl(addr + 0x0c);
+
+ /* save channel configurations */
+ for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
+ au1xxx_dbdma_pm_regs[i][0] = au_readl(addr + 0x00);
+ au1xxx_dbdma_pm_regs[i][1] = au_readl(addr + 0x04);
+ au1xxx_dbdma_pm_regs[i][2] = au_readl(addr + 0x08);
+ au1xxx_dbdma_pm_regs[i][3] = au_readl(addr + 0x0c);
+ au1xxx_dbdma_pm_regs[i][4] = au_readl(addr + 0x10);
+ au1xxx_dbdma_pm_regs[i][5] = au_readl(addr + 0x14);
+ au1xxx_dbdma_pm_regs[i][6] = au_readl(addr + 0x18);
+
+ /* halt channel */
+ au_writel(au1xxx_dbdma_pm_regs[i][0] & ~1, addr + 0x00);
+ au_sync();
+ while (!(au_readl(addr + 0x14) & 1))
+ au_sync();
+
+ addr += 0x100; /* next channel base */
+ }
+ /* disable channel interrupts */
+ au_writel(0, DDMA_GLOBAL_BASE + 0x0c);
+ au_sync();
+}
+
+void au1xxx_dbdma_resume(void)
+{
+ int i;
+ u32 addr;
+
+ addr = DDMA_GLOBAL_BASE;
+ au_writel(au1xxx_dbdma_pm_regs[0][0], addr + 0x00);
+ au_writel(au1xxx_dbdma_pm_regs[0][1], addr + 0x04);
+ au_writel(au1xxx_dbdma_pm_regs[0][2], addr + 0x08);
+ au_writel(au1xxx_dbdma_pm_regs[0][3], addr + 0x0c);
+
+ /* restore channel configurations */
+ for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
+ au_writel(au1xxx_dbdma_pm_regs[i][0], addr + 0x00);
+ au_writel(au1xxx_dbdma_pm_regs[i][1], addr + 0x04);
+ au_writel(au1xxx_dbdma_pm_regs[i][2], addr + 0x08);
+ au_writel(au1xxx_dbdma_pm_regs[i][3], addr + 0x0c);
+ au_writel(au1xxx_dbdma_pm_regs[i][4], addr + 0x10);
+ au_writel(au1xxx_dbdma_pm_regs[i][5], addr + 0x14);
+ au_writel(au1xxx_dbdma_pm_regs[i][6], addr + 0x18);
+ au_sync();
+ addr += 0x100; /* next channel base */
+ }
+}
+#endif /* CONFIG_PM */
#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
diff --git a/arch/mips/alchemy/common/irq.c b/arch/mips/alchemy/common/irq.c
index 40c6ceceb5f9..c88c821b4c36 100644
--- a/arch/mips/alchemy/common/irq.c
+++ b/arch/mips/alchemy/common/irq.c
@@ -24,6 +24,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -36,15 +37,172 @@
#include <asm/mach-pb1x00/pb1000.h>
#endif
-#define EXT_INTC0_REQ0 2 /* IP 2 */
-#define EXT_INTC0_REQ1 3 /* IP 3 */
-#define EXT_INTC1_REQ0 4 /* IP 4 */
-#define EXT_INTC1_REQ1 5 /* IP 5 */
-#define MIPS_TIMER_IP 7 /* IP 7 */
-
-void (*board_init_irq)(void) __initdata = NULL;
+static int au1x_ic_settype(unsigned int irq, unsigned int flow_type);
+
+/* per-processor fixed function irqs */
+struct au1xxx_irqmap au1xxx_ic0_map[] __initdata = {
+
+#if defined(CONFIG_SOC_AU1000)
+ { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+ { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
+
+#elif defined(CONFIG_SOC_AU1500)
+
+ { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1000_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1000_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+ { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
+
+#elif defined(CONFIG_SOC_AU1100)
+
+ { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+ { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
+
+#elif defined(CONFIG_SOC_AU1550)
+
+ { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+ { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+ { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+
+#elif defined(CONFIG_SOC_AU1200)
+
+ { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+ { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 },
+ { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+ { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+
+#else
+#error "Error: Unknown Alchemy SOC"
+#endif
+};
-static DEFINE_SPINLOCK(irq_lock);
#ifdef CONFIG_PM
@@ -130,67 +288,47 @@ void restore_au1xxx_intctl(void)
#endif /* CONFIG_PM */
-inline void local_enable_irq(unsigned int irq_nr)
+static void au1x_ic0_unmask(unsigned int irq_nr)
{
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
- if (bit >= 32) {
- au_writel(1 << (bit - 32), IC1_MASKSET);
- au_writel(1 << (bit - 32), IC1_WAKESET);
- } else {
- au_writel(1 << bit, IC0_MASKSET);
- au_writel(1 << bit, IC0_WAKESET);
- }
+ au_writel(1 << bit, IC0_MASKSET);
+ au_writel(1 << bit, IC0_WAKESET);
au_sync();
}
-
-inline void local_disable_irq(unsigned int irq_nr)
+static void au1x_ic1_unmask(unsigned int irq_nr)
{
- unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+ unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+ au_writel(1 << bit, IC1_MASKSET);
+ au_writel(1 << bit, IC1_WAKESET);
- if (bit >= 32) {
- au_writel(1 << (bit - 32), IC1_MASKCLR);
- au_writel(1 << (bit - 32), IC1_WAKECLR);
- } else {
- au_writel(1 << bit, IC0_MASKCLR);
- au_writel(1 << bit, IC0_WAKECLR);
- }
+/* very hacky. does the pb1000 cpld auto-disable this int?
+ * nowhere in the current kernel sources is it disabled. --mlau
+ */
+#if defined(CONFIG_MIPS_PB1000)
+ if (irq_nr == AU1000_GPIO_15)
+ au_writel(0x4000, PB1000_MDR); /* enable int */
+#endif
au_sync();
}
-
-static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
+static void au1x_ic0_mask(unsigned int irq_nr)
{
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
- if (bit >= 32) {
- au_writel(1 << (bit - 32), IC1_RISINGCLR);
- au_writel(1 << (bit - 32), IC1_MASKCLR);
- } else {
- au_writel(1 << bit, IC0_RISINGCLR);
- au_writel(1 << bit, IC0_MASKCLR);
- }
+ au_writel(1 << bit, IC0_MASKCLR);
+ au_writel(1 << bit, IC0_WAKECLR);
au_sync();
}
-
-static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
+static void au1x_ic1_mask(unsigned int irq_nr)
{
- unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
- if (bit >= 32) {
- au_writel(1 << (bit - 32), IC1_FALLINGCLR);
- au_writel(1 << (bit - 32), IC1_MASKCLR);
- } else {
- au_writel(1 << bit, IC0_FALLINGCLR);
- au_writel(1 << bit, IC0_MASKCLR);
- }
+ unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+ au_writel(1 << bit, IC1_MASKCLR);
+ au_writel(1 << bit, IC1_WAKECLR);
au_sync();
}
-
-static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
+static void au1x_ic0_ack(unsigned int irq_nr)
{
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
@@ -198,349 +336,229 @@ static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
* This may assume that we don't get interrupts from
* both edges at once, or if we do, that we don't care.
*/
- if (bit >= 32) {
- au_writel(1 << (bit - 32), IC1_FALLINGCLR);
- au_writel(1 << (bit - 32), IC1_RISINGCLR);
- au_writel(1 << (bit - 32), IC1_MASKCLR);
- } else {
- au_writel(1 << bit, IC0_FALLINGCLR);
- au_writel(1 << bit, IC0_RISINGCLR);
- au_writel(1 << bit, IC0_MASKCLR);
- }
+ au_writel(1 << bit, IC0_FALLINGCLR);
+ au_writel(1 << bit, IC0_RISINGCLR);
au_sync();
}
-static inline void mask_and_ack_level_irq(unsigned int irq_nr)
+static void au1x_ic1_ack(unsigned int irq_nr)
{
- local_disable_irq(irq_nr);
- au_sync();
-#if defined(CONFIG_MIPS_PB1000)
- if (irq_nr == AU1000_GPIO_15) {
- au_writel(0x8000, PB1000_MDR); /* ack int */
- au_sync();
- }
-#endif
-}
-
-static void end_irq(unsigned int irq_nr)
-{
- if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- local_enable_irq(irq_nr);
+ unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
-#if defined(CONFIG_MIPS_PB1000)
- if (irq_nr == AU1000_GPIO_15) {
- au_writel(0x4000, PB1000_MDR); /* enable int */
- au_sync();
- }
-#endif
+ /*
+ * This may assume that we don't get interrupts from
+ * both edges at once, or if we do, that we don't care.
+ */
+ au_writel(1 << bit, IC1_FALLINGCLR);
+ au_writel(1 << bit, IC1_RISINGCLR);
+ au_sync();
}
-unsigned long save_local_and_disable(int controller)
+static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
{
- int i;
- unsigned long flags, mask;
-
- spin_lock_irqsave(&irq_lock, flags);
- if (controller) {
- mask = au_readl(IC1_MASKSET);
- for (i = 32; i < 64; i++)
- local_disable_irq(i);
- } else {
- mask = au_readl(IC0_MASKSET);
- for (i = 0; i < 32; i++)
- local_disable_irq(i);
- }
- spin_unlock_irqrestore(&irq_lock, flags);
-
- return mask;
-}
+ unsigned int bit = irq - AU1000_INTC1_INT_BASE;
+ unsigned long wakemsk, flags;
-void restore_local_and_enable(int controller, unsigned long mask)
-{
- int i;
- unsigned long flags, new_mask;
-
- spin_lock_irqsave(&irq_lock, flags);
- for (i = 0; i < 32; i++)
- if (mask & (1 << i)) {
- if (controller)
- local_enable_irq(i + 32);
- else
- local_enable_irq(i);
- }
+ /* only GPIO 0-7 can act as wakeup source: */
+ if ((irq < AU1000_GPIO_0) || (irq > AU1000_GPIO_7))
+ return -EINVAL;
- if (controller)
- new_mask = au_readl(IC1_MASKSET);
+ local_irq_save(flags);
+ wakemsk = au_readl(SYS_WAKEMSK);
+ if (on)
+ wakemsk |= 1 << bit;
else
- new_mask = au_readl(IC0_MASKSET);
+ wakemsk &= ~(1 << bit);
+ au_writel(wakemsk, SYS_WAKEMSK);
+ au_sync();
+ local_irq_restore(flags);
- spin_unlock_irqrestore(&irq_lock, flags);
+ return 0;
}
-
-static struct irq_chip rise_edge_irq_type = {
- .name = "Au1000 Rise Edge",
- .ack = mask_and_ack_rise_edge_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_rise_edge_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
-};
-
-static struct irq_chip fall_edge_irq_type = {
- .name = "Au1000 Fall Edge",
- .ack = mask_and_ack_fall_edge_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_fall_edge_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
-};
-
-static struct irq_chip either_edge_irq_type = {
- .name = "Au1000 Rise or Fall Edge",
- .ack = mask_and_ack_either_edge_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_either_edge_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
+/*
+ * irq_chips for both ICs; this way the mask handlers can be
+ * as short as possible.
+ *
+ * NOTE: the ->ack() callback is used by the handle_edge_irq
+ * flowhandler only, the ->mask_ack() one by handle_level_irq,
+ * so no need for an irq_chip for each type of irq (level/edge).
+ */
+static struct irq_chip au1x_ic0_chip = {
+ .name = "Alchemy-IC0",
+ .ack = au1x_ic0_ack, /* edge */
+ .mask = au1x_ic0_mask,
+ .mask_ack = au1x_ic0_mask, /* level */
+ .unmask = au1x_ic0_unmask,
+ .set_type = au1x_ic_settype,
};
-static struct irq_chip level_irq_type = {
- .name = "Au1000 Level",
- .ack = mask_and_ack_level_irq,
- .mask = local_disable_irq,
- .mask_ack = mask_and_ack_level_irq,
- .unmask = local_enable_irq,
- .end = end_irq,
+static struct irq_chip au1x_ic1_chip = {
+ .name = "Alchemy-IC1",
+ .ack = au1x_ic1_ack, /* edge */
+ .mask = au1x_ic1_mask,
+ .mask_ack = au1x_ic1_mask, /* level */
+ .unmask = au1x_ic1_unmask,
+ .set_type = au1x_ic_settype,
+ .set_wake = au1x_ic1_setwake,
};
-static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req)
+static int au1x_ic_settype(unsigned int irq, unsigned int flow_type)
{
- unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
- if (irq_nr > AU1000_MAX_INTR)
- return;
-
- /* Config2[n], Config1[n], Config0[n] */
- if (bit >= 32) {
- switch (type) {
- case INTC_INT_RISE_EDGE: /* 0:0:1 */
- au_writel(1 << (bit - 32), IC1_CFG2CLR);
- au_writel(1 << (bit - 32), IC1_CFG1CLR);
- au_writel(1 << (bit - 32), IC1_CFG0SET);
- set_irq_chip(irq_nr, &rise_edge_irq_type);
- break;
- case INTC_INT_FALL_EDGE: /* 0:1:0 */
- au_writel(1 << (bit - 32), IC1_CFG2CLR);
- au_writel(1 << (bit - 32), IC1_CFG1SET);
- au_writel(1 << (bit - 32), IC1_CFG0CLR);
- set_irq_chip(irq_nr, &fall_edge_irq_type);
- break;
- case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
- au_writel(1 << (bit - 32), IC1_CFG2CLR);
- au_writel(1 << (bit - 32), IC1_CFG1SET);
- au_writel(1 << (bit - 32), IC1_CFG0SET);
- set_irq_chip(irq_nr, &either_edge_irq_type);
- break;
- case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
- au_writel(1 << (bit - 32), IC1_CFG2SET);
- au_writel(1 << (bit - 32), IC1_CFG1CLR);
- au_writel(1 << (bit - 32), IC1_CFG0SET);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_LOW_LEVEL: /* 1:1:0 */
- au_writel(1 << (bit - 32), IC1_CFG2SET);
- au_writel(1 << (bit - 32), IC1_CFG1SET);
- au_writel(1 << (bit - 32), IC1_CFG0CLR);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_DISABLED: /* 0:0:0 */
- au_writel(1 << (bit - 32), IC1_CFG0CLR);
- au_writel(1 << (bit - 32), IC1_CFG1CLR);
- au_writel(1 << (bit - 32), IC1_CFG2CLR);
- break;
- default: /* disable the interrupt */
- printk(KERN_WARNING "unexpected int type %d (irq %d)\n",
- type, irq_nr);
- au_writel(1 << (bit - 32), IC1_CFG0CLR);
- au_writel(1 << (bit - 32), IC1_CFG1CLR);
- au_writel(1 << (bit - 32), IC1_CFG2CLR);
- return;
- }
- if (int_req) /* assign to interrupt request 1 */
- au_writel(1 << (bit - 32), IC1_ASSIGNCLR);
- else /* assign to interrupt request 0 */
- au_writel(1 << (bit - 32), IC1_ASSIGNSET);
- au_writel(1 << (bit - 32), IC1_SRCSET);
- au_writel(1 << (bit - 32), IC1_MASKCLR);
- au_writel(1 << (bit - 32), IC1_WAKECLR);
+ struct irq_chip *chip;
+ unsigned long icr[6];
+ unsigned int bit, ic;
+ int ret;
+
+ if (irq >= AU1000_INTC1_INT_BASE) {
+ bit = irq - AU1000_INTC1_INT_BASE;
+ chip = &au1x_ic1_chip;
+ ic = 1;
} else {
- switch (type) {
- case INTC_INT_RISE_EDGE: /* 0:0:1 */
- au_writel(1 << bit, IC0_CFG2CLR);
- au_writel(1 << bit, IC0_CFG1CLR);
- au_writel(1 << bit, IC0_CFG0SET);
- set_irq_chip(irq_nr, &rise_edge_irq_type);
- break;
- case INTC_INT_FALL_EDGE: /* 0:1:0 */
- au_writel(1 << bit, IC0_CFG2CLR);
- au_writel(1 << bit, IC0_CFG1SET);
- au_writel(1 << bit, IC0_CFG0CLR);
- set_irq_chip(irq_nr, &fall_edge_irq_type);
- break;
- case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
- au_writel(1 << bit, IC0_CFG2CLR);
- au_writel(1 << bit, IC0_CFG1SET);
- au_writel(1 << bit, IC0_CFG0SET);
- set_irq_chip(irq_nr, &either_edge_irq_type);
- break;
- case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
- au_writel(1 << bit, IC0_CFG2SET);
- au_writel(1 << bit, IC0_CFG1CLR);
- au_writel(1 << bit, IC0_CFG0SET);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_LOW_LEVEL: /* 1:1:0 */
- au_writel(1 << bit, IC0_CFG2SET);
- au_writel(1 << bit, IC0_CFG1SET);
- au_writel(1 << bit, IC0_CFG0CLR);
- set_irq_chip(irq_nr, &level_irq_type);
- break;
- case INTC_INT_DISABLED: /* 0:0:0 */
- au_writel(1 << bit, IC0_CFG0CLR);
- au_writel(1 << bit, IC0_CFG1CLR);
- au_writel(1 << bit, IC0_CFG2CLR);
- break;
- default: /* disable the interrupt */
- printk(KERN_WARNING "unexpected int type %d (irq %d)\n",
- type, irq_nr);
- au_writel(1 << bit, IC0_CFG0CLR);
- au_writel(1 << bit, IC0_CFG1CLR);
- au_writel(1 << bit, IC0_CFG2CLR);
- return;
- }
- if (int_req) /* assign to interrupt request 1 */
- au_writel(1 << bit, IC0_ASSIGNCLR);
- else /* assign to interrupt request 0 */
- au_writel(1 << bit, IC0_ASSIGNSET);
- au_writel(1 << bit, IC0_SRCSET);
- au_writel(1 << bit, IC0_MASKCLR);
- au_writel(1 << bit, IC0_WAKECLR);
+ bit = irq - AU1000_INTC0_INT_BASE;
+ chip = &au1x_ic0_chip;
+ ic = 0;
+ }
+
+ if (bit > 31)
+ return -EINVAL;
+
+ icr[0] = ic ? IC1_CFG0SET : IC0_CFG0SET;
+ icr[1] = ic ? IC1_CFG1SET : IC0_CFG1SET;
+ icr[2] = ic ? IC1_CFG2SET : IC0_CFG2SET;
+ icr[3] = ic ? IC1_CFG0CLR : IC0_CFG0CLR;
+ icr[4] = ic ? IC1_CFG1CLR : IC0_CFG1CLR;
+ icr[5] = ic ? IC1_CFG2CLR : IC0_CFG2CLR;
+
+ ret = 0;
+
+ switch (flow_type) { /* cfgregs 2:1:0 */
+ case IRQ_TYPE_EDGE_RISING: /* 0:0:1 */
+ au_writel(1 << bit, icr[5]);
+ au_writel(1 << bit, icr[4]);
+ au_writel(1 << bit, icr[0]);
+ set_irq_chip_and_handler_name(irq, chip,
+ handle_edge_irq, "riseedge");
+ break;
+ case IRQ_TYPE_EDGE_FALLING: /* 0:1:0 */
+ au_writel(1 << bit, icr[5]);
+ au_writel(1 << bit, icr[1]);
+ au_writel(1 << bit, icr[3]);
+ set_irq_chip_and_handler_name(irq, chip,
+ handle_edge_irq, "falledge");
+ break;
+ case IRQ_TYPE_EDGE_BOTH: /* 0:1:1 */
+ au_writel(1 << bit, icr[5]);
+ au_writel(1 << bit, icr[1]);
+ au_writel(1 << bit, icr[0]);
+ set_irq_chip_and_handler_name(irq, chip,
+ handle_edge_irq, "bothedge");
+ break;
+ case IRQ_TYPE_LEVEL_HIGH: /* 1:0:1 */
+ au_writel(1 << bit, icr[2]);
+ au_writel(1 << bit, icr[4]);
+ au_writel(1 << bit, icr[0]);
+ set_irq_chip_and_handler_name(irq, chip,
+ handle_level_irq, "hilevel");
+ break;
+ case IRQ_TYPE_LEVEL_LOW: /* 1:1:0 */
+ au_writel(1 << bit, icr[2]);
+ au_writel(1 << bit, icr[1]);
+ au_writel(1 << bit, icr[3]);
+ set_irq_chip_and_handler_name(irq, chip,
+ handle_level_irq, "lowlevel");
+ break;
+ case IRQ_TYPE_NONE: /* 0:0:0 */
+ au_writel(1 << bit, icr[5]);
+ au_writel(1 << bit, icr[4]);
+ au_writel(1 << bit, icr[3]);
+ /* set at least chip so we can call set_irq_type() on it */
+ set_irq_chip(irq, chip);
+ break;
+ default:
+ ret = -EINVAL;
}
au_sync();
-}
-/*
- * Interrupts are nested. Even if an interrupt handler is registered
- * as "fast", we might get another interrupt before we return from
- * intcX_reqX_irqdispatch().
- */
+ return ret;
+}
-static void intc0_req0_irqdispatch(void)
+asmlinkage void plat_irq_dispatch(void)
{
- static unsigned long intc0_req0;
- unsigned int bit;
-
- intc0_req0 |= au_readl(IC0_REQ0INT);
+ unsigned int pending = read_c0_status() & read_c0_cause();
+ unsigned long s, off, bit;
- if (!intc0_req0)
+ if (pending & CAUSEF_IP7) {
+ do_IRQ(MIPS_CPU_IRQ_BASE + 7);
return;
-
+ } else if (pending & CAUSEF_IP2) {
+ s = IC0_REQ0INT;
+ off = AU1000_INTC0_INT_BASE;
+ } else if (pending & CAUSEF_IP3) {
+ s = IC0_REQ1INT;
+ off = AU1000_INTC0_INT_BASE;
+ } else if (pending & CAUSEF_IP4) {
+ s = IC1_REQ0INT;
+ off = AU1000_INTC1_INT_BASE;
+ } else if (pending & CAUSEF_IP5) {
+ s = IC1_REQ1INT;
+ off = AU1000_INTC1_INT_BASE;
+ } else
+ goto spurious;
+
+ bit = 0;
+ s = au_readl(s);
+ if (unlikely(!s)) {
+spurious:
+ spurious_interrupt();
+ return;
+ }
#ifdef AU1000_USB_DEV_REQ_INT
/*
* Because of the tight timing of SETUP token to reply
* transactions, the USB devices-side packet complete
* interrupt needs the highest priority.
*/
- if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) {
- intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT);
+ bit = 1 << (AU1000_USB_DEV_REQ_INT - AU1000_INTC0_INT_BASE);
+ if ((pending & CAUSEF_IP2) && (s & bit)) {
do_IRQ(AU1000_USB_DEV_REQ_INT);
return;
}
#endif
- bit = __ffs(intc0_req0);
- intc0_req0 &= ~(1 << bit);
- do_IRQ(AU1000_INTC0_INT_BASE + bit);
+ do_IRQ(__ffs(s) + off);
}
-
-static void intc0_req1_irqdispatch(void)
-{
- static unsigned long intc0_req1;
- unsigned int bit;
-
- intc0_req1 |= au_readl(IC0_REQ1INT);
-
- if (!intc0_req1)
- return;
-
- bit = __ffs(intc0_req1);
- intc0_req1 &= ~(1 << bit);
- do_IRQ(AU1000_INTC0_INT_BASE + bit);
-}
-
-
-/*
- * Interrupt Controller 1:
- * interrupts 32 - 63
- */
-static void intc1_req0_irqdispatch(void)
+/* setup edge/level and assign request 0/1 */
+void __init au1xxx_setup_irqmap(struct au1xxx_irqmap *map, int count)
{
- static unsigned long intc1_req0;
- unsigned int bit;
-
- intc1_req0 |= au_readl(IC1_REQ0INT);
-
- if (!intc1_req0)
- return;
-
- bit = __ffs(intc1_req0);
- intc1_req0 &= ~(1 << bit);
- do_IRQ(AU1000_INTC1_INT_BASE + bit);
-}
-
-
-static void intc1_req1_irqdispatch(void)
-{
- static unsigned long intc1_req1;
- unsigned int bit;
-
- intc1_req1 |= au_readl(IC1_REQ1INT);
-
- if (!intc1_req1)
- return;
-
- bit = __ffs(intc1_req1);
- intc1_req1 &= ~(1 << bit);
- do_IRQ(AU1000_INTC1_INT_BASE + bit);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_status() & read_c0_cause();
+ unsigned int bit, irq_nr;
+
+ while (count--) {
+ irq_nr = map[count].im_irq;
+
+ if (((irq_nr < AU1000_INTC0_INT_BASE) ||
+ (irq_nr >= AU1000_INTC0_INT_BASE + 32)) &&
+ ((irq_nr < AU1000_INTC1_INT_BASE) ||
+ (irq_nr >= AU1000_INTC1_INT_BASE + 32)))
+ continue;
+
+ if (irq_nr >= AU1000_INTC1_INT_BASE) {
+ bit = irq_nr - AU1000_INTC1_INT_BASE;
+ if (map[count].im_request)
+ au_writel(1 << bit, IC1_ASSIGNCLR);
+ } else {
+ bit = irq_nr - AU1000_INTC0_INT_BASE;
+ if (map[count].im_request)
+ au_writel(1 << bit, IC0_ASSIGNCLR);
+ }
- if (pending & CAUSEF_IP7)
- do_IRQ(MIPS_CPU_IRQ_BASE + 7);
- else if (pending & CAUSEF_IP2)
- intc0_req0_irqdispatch();
- else if (pending & CAUSEF_IP3)
- intc0_req1_irqdispatch();
- else if (pending & CAUSEF_IP4)
- intc1_req0_irqdispatch();
- else if (pending & CAUSEF_IP5)
- intc1_req1_irqdispatch();
- else
- spurious_interrupt();
+ au1x_ic_settype(irq_nr, map[count].im_type);
+ }
}
void __init arch_init_irq(void)
{
int i;
- struct au1xxx_irqmap *imp;
- extern struct au1xxx_irqmap au1xxx_irq_map[];
- extern struct au1xxx_irqmap au1xxx_ic0_map[];
- extern int au1xxx_nr_irqs;
- extern int au1xxx_ic0_nr_irqs;
/*
* Initialize interrupt controllers to a safe state.
@@ -569,28 +587,25 @@ void __init arch_init_irq(void)
mips_cpu_irq_init();
- /*
- * Initialize IC0, which is fixed per processor.
+ /* register all 64 possible IC0+IC1 irq sources as type "none".
+ * Use set_irq_type() to set edge/level behaviour at runtime.
*/
- imp = au1xxx_ic0_map;
- for (i = 0; i < au1xxx_ic0_nr_irqs; i++) {
- setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
- imp++;
- }
+ for (i = AU1000_INTC0_INT_BASE;
+ (i < AU1000_INTC0_INT_BASE + 32); i++)
+ au1x_ic_settype(i, IRQ_TYPE_NONE);
+
+ for (i = AU1000_INTC1_INT_BASE;
+ (i < AU1000_INTC1_INT_BASE + 32); i++)
+ au1x_ic_settype(i, IRQ_TYPE_NONE);
/*
- * Now set up the irq mapping for the board.
+ * Initialize IC0, which is fixed per processor.
*/
- imp = au1xxx_irq_map;
- for (i = 0; i < au1xxx_nr_irqs; i++) {
- setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
- imp++;
- }
-
- set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+ au1xxx_setup_irqmap(au1xxx_ic0_map, ARRAY_SIZE(au1xxx_ic0_map));
- /* Board specific IRQ initialization.
+ /* Boards can register additional (GPIO-based) IRQs.
*/
- if (board_init_irq)
- board_init_irq();
+ board_init_irq();
+
+ set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
}
diff --git a/arch/mips/alchemy/common/power.c b/arch/mips/alchemy/common/power.c
index bd854a6d1d89..6ab7b42aa1be 100644
--- a/arch/mips/alchemy/common/power.c
+++ b/arch/mips/alchemy/common/power.c
@@ -35,25 +35,12 @@
#include <linux/jiffies.h>
#include <asm/uaccess.h>
-#include <asm/cacheflush.h>
#include <asm/mach-au1x00/au1000.h>
-
-#ifdef CONFIG_PM
-
-#define DEBUG 1
-#ifdef DEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
-#else
-#define DPRINTK(fmt, args...)
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
#endif
-static void au1000_calibrate_delay(void);
-
-extern unsigned long save_local_and_disable(int controller);
-extern void restore_local_and_enable(int controller, unsigned long mask);
-extern void local_enable_irq(unsigned int irq_nr);
-
-static DEFINE_SPINLOCK(pm_lock);
+#ifdef CONFIG_PM
/*
* We need to save/restore a bunch of core registers that are
@@ -65,29 +52,16 @@ static DEFINE_SPINLOCK(pm_lock);
* We only have to save/restore registers that aren't otherwise
* done as part of a driver pm_* function.
*/
-static unsigned int sleep_aux_pll_cntrl;
-static unsigned int sleep_cpu_pll_cntrl;
-static unsigned int sleep_pin_function;
-static unsigned int sleep_uart0_inten;
-static unsigned int sleep_uart0_fifoctl;
-static unsigned int sleep_uart0_linectl;
-static unsigned int sleep_uart0_clkdiv;
-static unsigned int sleep_uart0_enable;
-static unsigned int sleep_usbhost_enable;
-static unsigned int sleep_usbdev_enable;
-static unsigned int sleep_static_memctlr[4][3];
+static unsigned int sleep_uart0_inten;
+static unsigned int sleep_uart0_fifoctl;
+static unsigned int sleep_uart0_linectl;
+static unsigned int sleep_uart0_clkdiv;
+static unsigned int sleep_uart0_enable;
+static unsigned int sleep_usb[2];
+static unsigned int sleep_sys_clocks[5];
+static unsigned int sleep_sys_pinfunc;
+static unsigned int sleep_static_memctlr[4][3];
-/*
- * Define this to cause the value you write to /proc/sys/pm/sleep to
- * set the TOY timer for the amount of time you want to sleep.
- * This is done mainly for testing, but may be useful in other cases.
- * The value is number of 32KHz ticks to sleep.
- */
-#define SLEEP_TEST_TIMEOUT 1
-#ifdef SLEEP_TEST_TIMEOUT
-static int sleep_ticks;
-void wakeup_counter0_set(int ticks);
-#endif
static void save_core_regs(void)
{
@@ -105,31 +79,45 @@ static void save_core_regs(void)
sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
+ au_sync();
+#ifndef CONFIG_SOC_AU1200
/* Shutdown USB host/device. */
- sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
+ sleep_usb[0] = au_readl(USB_HOST_CONFIG);
/* There appears to be some undocumented reset register.... */
- au_writel(0, 0xb0100004); au_sync();
- au_writel(0, USB_HOST_CONFIG); au_sync();
+ au_writel(0, 0xb0100004);
+ au_sync();
+ au_writel(0, USB_HOST_CONFIG);
+ au_sync();
- sleep_usbdev_enable = au_readl(USBD_ENABLE);
- au_writel(0, USBD_ENABLE); au_sync();
+ sleep_usb[1] = au_readl(USBD_ENABLE);
+ au_writel(0, USBD_ENABLE);
+ au_sync();
+
+#else /* AU1200 */
+
+ /* enable access to OTG mmio so we can save OTG CAP/MUX.
+ * FIXME: write an OTG driver and move this stuff there!
+ */
+ au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
+ au_sync();
+ sleep_usb[0] = au_readl(0xb4020020); /* OTG_CAP */
+ sleep_usb[1] = au_readl(0xb4020024); /* OTG_MUX */
+#endif
/* Save interrupt controller state. */
save_au1xxx_intctl();
/* Clocks and PLLs. */
- sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL);
+ sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
+ sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
+ sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
+ sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
+ sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
- /*
- * We don't really need to do this one, but unless we
- * write it again it won't have a valid value if we
- * happen to read it.
- */
- sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL);
-
- sleep_pin_function = au_readl(SYS_PINFUNC);
+ /* pin mux config */
+ sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
/* Save the static memory controller configuration. */
sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
@@ -144,16 +132,45 @@ static void save_core_regs(void)
sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+ au1xxx_dbdma_suspend();
+#endif
}
static void restore_core_regs(void)
{
- extern void restore_au1xxx_intctl(void);
- extern void wakeup_counter0_adjust(void);
+ /* restore clock configuration. Writing CPUPLL last will
+ * stall a bit and stabilize other clocks (unless this is
+ * one of those Au1000 with a write-only PLL, where we dont
+ * have a valid value)
+ */
+ au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
+ au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
+ au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
+ au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
+ if (!au1xxx_cpu_has_pll_wo())
+ au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
+ au_sync();
- au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync();
- au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync();
- au_writel(sleep_pin_function, SYS_PINFUNC); au_sync();
+ au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
+ au_sync();
+
+#ifndef CONFIG_SOC_AU1200
+ au_writel(sleep_usb[0], USB_HOST_CONFIG);
+ au_writel(sleep_usb[1], USBD_ENABLE);
+ au_sync();
+#else
+ /* enable accces to OTG memory */
+ au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
+ au_sync();
+
+ /* restore OTG caps and port mux. */
+ au_writel(sleep_usb[0], 0xb4020020 + 0); /* OTG_CAP */
+ au_sync();
+ au_writel(sleep_usb[1], 0xb4020020 + 4); /* OTG_MUX */
+ au_sync();
+#endif
/* Restore the static memory controller configuration. */
au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
@@ -184,282 +201,17 @@ static void restore_core_regs(void)
}
restore_au1xxx_intctl();
- wakeup_counter0_adjust();
-}
-
-unsigned long suspend_mode;
-void wakeup_from_suspend(void)
-{
- suspend_mode = 0;
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+ au1xxx_dbdma_resume();
+#endif
}
-int au_sleep(void)
+void au_sleep(void)
{
- unsigned long wakeup, flags;
- extern void save_and_sleep(void);
-
- spin_lock_irqsave(&pm_lock, flags);
-
save_core_regs();
-
- flush_cache_all();
-
- /**
- ** The code below is all system dependent and we should probably
- ** have a function call out of here to set this up. You need
- ** to configure the GPIO or timer interrupts that will bring
- ** you out of sleep.
- ** For testing, the TOY counter wakeup is useful.
- **/
-#if 0
- au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
-
- /* GPIO 6 can cause a wake up event */
- wakeup = au_readl(SYS_WAKEMSK);
- wakeup &= ~(1 << 8); /* turn off match20 wakeup */
- wakeup |= 1 << 6; /* turn on GPIO 6 wakeup */
-#else
- /* For testing, allow match20 to wake us up. */
-#ifdef SLEEP_TEST_TIMEOUT
- wakeup_counter0_set(sleep_ticks);
-#endif
- wakeup = 1 << 8; /* turn on match20 wakeup */
- wakeup = 0;
-#endif
- au_writel(1, SYS_WAKESRC); /* clear cause */
- au_sync();
- au_writel(wakeup, SYS_WAKEMSK);
- au_sync();
-
- save_and_sleep();
-
- /*
- * After a wakeup, the cpu vectors back to 0x1fc00000, so
- * it's up to the boot code to get us back here.
- */
+ au1xxx_save_and_sleep();
restore_core_regs();
- spin_unlock_irqrestore(&pm_lock, flags);
- return 0;
-}
-
-static int pm_do_sleep(ctl_table *ctl, int write, struct file *file,
- void __user *buffer, size_t *len, loff_t *ppos)
-{
-#ifdef SLEEP_TEST_TIMEOUT
-#define TMPBUFLEN2 16
- char buf[TMPBUFLEN2], *p;
-#endif
-
- if (!write)
- *len = 0;
- else {
-#ifdef SLEEP_TEST_TIMEOUT
- if (*len > TMPBUFLEN2 - 1)
- return -EFAULT;
- if (copy_from_user(buf, buffer, *len))
- return -EFAULT;
- buf[*len] = 0;
- p = buf;
- sleep_ticks = simple_strtoul(p, &p, 0);
-#endif
-
- au_sleep();
- }
- return 0;
-}
-
-static int pm_do_freq(ctl_table *ctl, int write, struct file *file,
- void __user *buffer, size_t *len, loff_t *ppos)
-{
- int retval = 0, i;
- unsigned long val, pll;
-#define TMPBUFLEN 64
-#define MAX_CPU_FREQ 396
- char buf[TMPBUFLEN], *p;
- unsigned long flags, intc0_mask, intc1_mask;
- unsigned long old_baud_base, old_cpu_freq, old_clk, old_refresh;
- unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
- unsigned long baud_rate;
-
- spin_lock_irqsave(&pm_lock, flags);
- if (!write)
- *len = 0;
- else {
- /* Parse the new frequency */
- if (*len > TMPBUFLEN - 1) {
- spin_unlock_irqrestore(&pm_lock, flags);
- return -EFAULT;
- }
- if (copy_from_user(buf, buffer, *len)) {
- spin_unlock_irqrestore(&pm_lock, flags);
- return -EFAULT;
- }
- buf[*len] = 0;
- p = buf;
- val = simple_strtoul(p, &p, 0);
- if (val > MAX_CPU_FREQ) {
- spin_unlock_irqrestore(&pm_lock, flags);
- return -EFAULT;
- }
-
- pll = val / 12;
- if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */
- /* Revisit this for higher speed CPUs */
- spin_unlock_irqrestore(&pm_lock, flags);
- return -EFAULT;
- }
-
- old_baud_base = get_au1x00_uart_baud_base();
- old_cpu_freq = get_au1x00_speed();
-
- new_cpu_freq = pll * 12 * 1000000;
- new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)
- & 0x03) + 2) * 16));
- set_au1x00_speed(new_cpu_freq);
- set_au1x00_uart_baud_base(new_baud_base);
-
- old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
- new_refresh = ((old_refresh * new_cpu_freq) / old_cpu_freq) |
- (au_readl(MEM_SDREFCFG) & ~0x1ffffff);
-
- au_writel(pll, SYS_CPUPLL);
- au_sync_delay(1);
- au_writel(new_refresh, MEM_SDREFCFG);
- au_sync_delay(1);
-
- for (i = 0; i < 4; i++)
- if (au_readl(UART_BASE + UART_MOD_CNTRL +
- i * 0x00100000) == 3) {
- old_clk = au_readl(UART_BASE + UART_CLK +
- i * 0x00100000);
- baud_rate = old_baud_base / old_clk;
- /*
- * We won't get an exact baud rate and the error
- * could be significant enough that our new
- * calculation will result in a clock that will
- * give us a baud rate that's too far off from
- * what we really want.
- */
- if (baud_rate > 100000)
- baud_rate = 115200;
- else if (baud_rate > 50000)
- baud_rate = 57600;
- else if (baud_rate > 30000)
- baud_rate = 38400;
- else if (baud_rate > 17000)
- baud_rate = 19200;
- else
- baud_rate = 9600;
- new_clk = new_baud_base / baud_rate;
- au_writel(new_clk, UART_BASE + UART_CLK +
- i * 0x00100000);
- au_sync_delay(10);
- }
- }
-
- /*
- * We don't want _any_ interrupts other than match20. Otherwise our
- * au1000_calibrate_delay() calculation will be off, potentially a lot.
- */
- intc0_mask = save_local_and_disable(0);
- intc1_mask = save_local_and_disable(1);
- local_enable_irq(AU1000_TOY_MATCH2_INT);
- spin_unlock_irqrestore(&pm_lock, flags);
- au1000_calibrate_delay();
- restore_local_and_enable(0, intc0_mask);
- restore_local_and_enable(1, intc1_mask);
-
- return retval;
}
-
-static struct ctl_table pm_table[] = {
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "sleep",
- .data = NULL,
- .maxlen = 0,
- .mode = 0600,
- .proc_handler = &pm_do_sleep
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "freq",
- .data = NULL,
- .maxlen = 0,
- .mode = 0600,
- .proc_handler = &pm_do_freq
- },
- {}
-};
-
-static struct ctl_table pm_dir_table[] = {
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "pm",
- .mode = 0555,
- .child = pm_table
- },
- {}
-};
-
-/*
- * Initialize power interface
- */
-static int __init pm_init(void)
-{
- register_sysctl_table(pm_dir_table);
- return 0;
-}
-
-__initcall(pm_init);
-
-/*
- * This is right out of init/main.c
- */
-
-/*
- * This is the number of bits of precision for the loops_per_jiffy.
- * Each bit takes on average 1.5/HZ seconds. This (like the original)
- * is a little better than 1%.
- */
-#define LPS_PREC 8
-
-static void au1000_calibrate_delay(void)
-{
- unsigned long ticks, loopbit;
- int lps_precision = LPS_PREC;
-
- loops_per_jiffy = 1 << 12;
-
- while (loops_per_jiffy <<= 1) {
- /* Wait for "start of" clock tick */
- ticks = jiffies;
- while (ticks == jiffies)
- /* nothing */ ;
- /* Go ... */
- ticks = jiffies;
- __delay(loops_per_jiffy);
- ticks = jiffies - ticks;
- if (ticks)
- break;
- }
-
- /*
- * Do a binary approximation to get loops_per_jiffy set to be equal
- * one clock (up to lps_precision bits)
- */
- loops_per_jiffy >>= 1;
- loopbit = loops_per_jiffy;
- while (lps_precision-- && (loopbit >>= 1)) {
- loops_per_jiffy |= loopbit;
- ticks = jiffies;
- while (ticks == jiffies);
- ticks = jiffies;
- __delay(loops_per_jiffy);
- if (jiffies != ticks) /* longer than 1 tick */
- loops_per_jiffy &= ~loopbit;
- }
-}
#endif /* CONFIG_PM */
diff --git a/arch/mips/alchemy/common/reset.c b/arch/mips/alchemy/common/reset.c
index d555429c8d6f..0191c936cb5e 100644
--- a/arch/mips/alchemy/common/reset.c
+++ b/arch/mips/alchemy/common/reset.c
@@ -31,8 +31,6 @@
#include <asm/mach-au1x00/au1000.h>
-extern int au_sleep(void);
-
void au1000_restart(char *command)
{
/* Set all integrated peripherals to disabled states */
diff --git a/arch/mips/alchemy/common/setup.c b/arch/mips/alchemy/common/setup.c
index 1ac6b06f42a3..3f036b3d400e 100644
--- a/arch/mips/alchemy/common/setup.c
+++ b/arch/mips/alchemy/common/setup.c
@@ -35,7 +35,6 @@
#include <asm/time.h>
#include <au1000.h>
-#include <prom.h>
extern void __init board_setup(void);
extern void au1000_restart(char *);
@@ -45,80 +44,34 @@ extern void set_cpuspec(void);
void __init plat_mem_setup(void)
{
- struct cpu_spec *sp;
- char *argptr;
- unsigned long prid, cpufreq, bclk;
+ unsigned long est_freq;
- set_cpuspec();
- sp = cur_cpu_spec[0];
+ /* determine core clock */
+ est_freq = au1xxx_calc_clock();
+ est_freq += 5000; /* round */
+ est_freq -= est_freq % 10000;
+ printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
+ est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
- board_setup(); /* board specific setup */
-
- prid = read_c0_prid();
- if (sp->cpu_pll_wo)
-#ifdef CONFIG_SOC_AU1000_FREQUENCY
- cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000;
-#else
- cpufreq = 396;
-#endif
- else
- cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12;
- printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq);
+ _machine_restart = au1000_restart;
+ _machine_halt = au1000_halt;
+ pm_power_off = au1000_power_off;
- if (sp->cpu_bclk) {
- /* Enable BCLK switching */
- bclk = au_readl(SYS_POWERCTRL);
- au_writel(bclk | 0x60, SYS_POWERCTRL);
- printk(KERN_INFO "BCLK switching enabled!\n");
- }
+ board_setup(); /* board specific setup */
- if (sp->cpu_od)
+ if (au1xxx_cpu_needs_config_od())
/* Various early Au1xx0 errata corrected by this */
set_c0_config(1 << 19); /* Set Config[OD] */
else
/* Clear to obtain best system bus performance */
clear_c0_config(1 << 19); /* Clear Config[OD] */
- argptr = prom_getcmdline();
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- argptr = strstr(argptr, "console=");
- if (argptr == NULL) {
- argptr = prom_getcmdline();
- strcat(argptr, " console=ttyS0,115200");
- }
-#endif
-
-#ifdef CONFIG_FB_AU1100
- argptr = strstr(argptr, "video=");
- if (argptr == NULL) {
- argptr = prom_getcmdline();
- /* default panel */
- /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
- }
-#endif
-
-#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
- /* au1000 does not support vra, au1500 and au1100 do */
- strcat(argptr, " au1000_audio=vra");
- argptr = prom_getcmdline();
-#endif
- _machine_restart = au1000_restart;
- _machine_halt = au1000_halt;
- pm_power_off = au1000_power_off;
-
/* IO/MEM resources. */
set_io_port_base(0);
ioport_resource.start = IOPORT_RESOURCE_START;
ioport_resource.end = IOPORT_RESOURCE_END;
iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END;
-
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
- au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
- au_sync();
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
- au_writel(0, SYS_TOYTRIM);
}
#if defined(CONFIG_64BIT_PHYS_ADDR)
diff --git a/arch/mips/alchemy/common/sleeper.S b/arch/mips/alchemy/common/sleeper.S
index 3006e270c8bc..4f4b16741d12 100644
--- a/arch/mips/alchemy/common/sleeper.S
+++ b/arch/mips/alchemy/common/sleeper.S
@@ -15,16 +15,17 @@
#include <asm/regdef.h>
#include <asm/stackframe.h>
+ .extern __flush_cache_all
+
.text
- .set macro
- .set noat
+ .set noreorder
+ .set noat
.align 5
/* Save all of the processor general registers and go to sleep.
* A wakeup condition will get us back here to restore the registers.
*/
-LEAF(save_and_sleep)
-
+LEAF(au1xxx_save_and_sleep)
subu sp, PT_SIZE
sw $1, PT_R1(sp)
sw $2, PT_R2(sp)
@@ -33,14 +34,6 @@ LEAF(save_and_sleep)
sw $5, PT_R5(sp)
sw $6, PT_R6(sp)
sw $7, PT_R7(sp)
- sw $8, PT_R8(sp)
- sw $9, PT_R9(sp)
- sw $10, PT_R10(sp)
- sw $11, PT_R11(sp)
- sw $12, PT_R12(sp)
- sw $13, PT_R13(sp)
- sw $14, PT_R14(sp)
- sw $15, PT_R15(sp)
sw $16, PT_R16(sp)
sw $17, PT_R17(sp)
sw $18, PT_R18(sp)
@@ -49,12 +42,9 @@ LEAF(save_and_sleep)
sw $21, PT_R21(sp)
sw $22, PT_R22(sp)
sw $23, PT_R23(sp)
- sw $24, PT_R24(sp)
- sw $25, PT_R25(sp)
sw $26, PT_R26(sp)
sw $27, PT_R27(sp)
sw $28, PT_R28(sp)
- sw $29, PT_R29(sp)
sw $30, PT_R30(sp)
sw $31, PT_R31(sp)
mfc0 k0, CP0_STATUS
@@ -66,20 +56,26 @@ LEAF(save_and_sleep)
mfc0 k0, CP0_CONFIG
sw k0, 0x14(sp)
+ /* flush caches to make sure context is in memory */
+ la t1, __flush_cache_all
+ lw t0, 0(t1)
+ jalr t0
+ nop
+
/* Now set up the scratch registers so the boot rom will
* return to this point upon wakeup.
+ * sys_scratch0 : SP
+ * sys_scratch1 : RA
*/
- la k0, 1f
- lui k1, 0xb190
- ori k1, 0x18
- sw sp, 0(k1)
- ori k1, 0x1c
- sw k0, 0(k1)
+ lui t3, 0xb190 /* sys_xxx */
+ sw sp, 0x0018(t3)
+ la k0, 3f /* resume path */
+ sw k0, 0x001c(t3)
-/* Put SDRAM into self refresh. Preload instructions into cache,
- * issue a precharge, then auto refresh, then sleep commands to it.
- */
- la t0, sdsleep
+ /* Put SDRAM into self refresh: Preload instructions into cache,
+ * issue a precharge, auto/self refresh, then sleep commands to it.
+ */
+ la t0, 1f
.set mips3
cache 0x14, 0(t0)
cache 0x14, 32(t0)
@@ -87,24 +83,57 @@ LEAF(save_and_sleep)
cache 0x14, 96(t0)
.set mips0
-sdsleep:
- lui k0, 0xb400
- sw zero, 0x001c(k0) /* Precharge */
- sw zero, 0x0020(k0) /* Auto refresh */
- sw zero, 0x0030(k0) /* SDRAM sleep */
+1: lui a0, 0xb400 /* mem_xxx */
+#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \
+ defined(CONFIG_SOC_AU1500)
+ sw zero, 0x001c(a0) /* Precharge */
+ sync
+ sw zero, 0x0020(a0) /* Auto Refresh */
+ sync
+ sw zero, 0x0030(a0) /* Sleep */
+ sync
+#endif
+
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+ sw zero, 0x08c0(a0) /* Precharge */
sync
+ sw zero, 0x08d0(a0) /* Self Refresh */
+ sync
+
+ /* wait for sdram to enter self-refresh mode */
+ lui t0, 0x0100
+2: lw t1, 0x0850(a0) /* mem_sdstat */
+ and t2, t1, t0
+ beq t2, zero, 2b
+ nop
- lui k1, 0xb190
- sw zero, 0x0078(k1) /* get ready to sleep */
+ /* disable SDRAM clocks */
+ lui t0, 0xcfff
+ ori t0, t0, 0xffff
+ lw t1, 0x0840(a0) /* mem_sdconfiga */
+ and t1, t0, t1 /* clear CE[1:0] */
+ sw t1, 0x0840(a0) /* mem_sdconfiga */
sync
- sw zero, 0x007c(k1) /* Put processor to sleep */
+#endif
+
+ /* put power supply and processor to sleep */
+ sw zero, 0x0078(t3) /* sys_slppwr */
+ sync
+ sw zero, 0x007c(t3) /* sys_sleep */
sync
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
/* This is where we return upon wakeup.
* Reload all of the registers and return.
*/
-1: nop
- lw k0, 0x20(sp)
+3: lw k0, 0x20(sp)
mtc0 k0, CP0_STATUS
lw k0, 0x1c(sp)
mtc0 k0, CP0_CONTEXT
@@ -113,10 +142,11 @@ sdsleep:
lw k0, 0x14(sp)
mtc0 k0, CP0_CONFIG
- /* We need to catch the ealry Alchemy SOCs with
+ /* We need to catch the early Alchemy SOCs with
* the write-only Config[OD] bit and set it back to one...
*/
jal au1x00_fixup_config_od
+ nop
lw $1, PT_R1(sp)
lw $2, PT_R2(sp)
lw $3, PT_R3(sp)
@@ -124,14 +154,6 @@ sdsleep:
lw $5, PT_R5(sp)
lw $6, PT_R6(sp)
lw $7, PT_R7(sp)
- lw $8, PT_R8(sp)
- lw $9, PT_R9(sp)
- lw $10, PT_R10(sp)
- lw $11, PT_R11(sp)
- lw $12, PT_R12(sp)
- lw $13, PT_R13(sp)
- lw $14, PT_R14(sp)
- lw $15, PT_R15(sp)
lw $16, PT_R16(sp)
lw $17, PT_R17(sp)
lw $18, PT_R18(sp)
@@ -140,15 +162,11 @@ sdsleep:
lw $21, PT_R21(sp)
lw $22, PT_R22(sp)
lw $23, PT_R23(sp)
- lw $24, PT_R24(sp)
- lw $25, PT_R25(sp)
lw $26, PT_R26(sp)
lw $27, PT_R27(sp)
lw $28, PT_R28(sp)
- lw $29, PT_R29(sp)
lw $30, PT_R30(sp)
lw $31, PT_R31(sp)
- addiu sp, PT_SIZE
-
jr ra
-END(save_and_sleep)
+ addiu sp, PT_SIZE
+END(au1xxx_save_and_sleep)
diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c
index 563d9390a872..6fd441d16af5 100644
--- a/arch/mips/alchemy/common/time.c
+++ b/arch/mips/alchemy/common/time.c
@@ -1,5 +1,7 @@
/*
+ * Copyright (C) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
*
+ * Previous incarnations were:
* Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com>
* Copied and modified Carsten Langgaard's time.c
*
@@ -23,244 +25,141 @@
*
* ########################################################################
*
- * Setting up the clock on the MIPS boards.
- *
- * We provide the clock interrupt processing and the timer offset compute
- * functions. If CONFIG_PM is selected, we also ensure the 32KHz timer is
- * available. -- Dan
+ * Clocksource/event using the 32.768kHz-clocked Counter1 ('RTC' in the
+ * databooks). Firmware/Board init code must enable the counters in the
+ * counter control register, otherwise the CP0 counter clocksource/event
+ * will be installed instead (and use of 'wait' instruction is prohibited).
*/
-#include <linux/types.h>
-#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <asm/mipsregs.h>
#include <asm/time.h>
#include <asm/mach-au1x00/au1000.h>
-static int no_au1xxx_32khz;
-extern int allow_au1k_wait; /* default off for CP0 Counter */
-
-#ifdef CONFIG_PM
-#if HZ < 100 || HZ > 1000
-#error "unsupported HZ value! Must be in [100,1000]"
-#endif
-#define MATCH20_INC (328 * 100 / HZ) /* magic number 328 is for HZ=100... */
-static unsigned long last_pc0, last_match20;
-#endif
+/* 32kHz clock enabled and detected */
+#define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
-static DEFINE_SPINLOCK(time_lock);
-
-unsigned long wtimer;
+extern int allow_au1k_wait; /* default off for CP0 Counter */
-#ifdef CONFIG_PM
-static irqreturn_t counter0_irq(int irq, void *dev_id)
+static cycle_t au1x_counter1_read(void)
{
- unsigned long pc0;
- int time_elapsed;
- static int jiffie_drift;
-
- if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
- /* should never happen! */
- printk(KERN_WARNING "counter 0 w status error\n");
- return IRQ_NONE;
- }
-
- pc0 = au_readl(SYS_TOYREAD);
- if (pc0 < last_match20)
- /* counter overflowed */
- time_elapsed = (0xffffffff - last_match20) + pc0;
- else
- time_elapsed = pc0 - last_match20;
-
- while (time_elapsed > 0) {
- do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- time_elapsed -= MATCH20_INC;
- last_match20 += MATCH20_INC;
- jiffie_drift++;
- }
-
- last_pc0 = pc0;
- au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
- au_sync();
-
- /*
- * Our counter ticks at 10.009765625 ms/tick, we we're running
- * almost 10 uS too slow per tick.
- */
-
- if (jiffie_drift >= 999) {
- jiffie_drift -= 999;
- do_timer(1); /* increment jiffies by one */
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- }
-
- return IRQ_HANDLED;
+ return au_readl(SYS_RTCREAD);
}
-struct irqaction counter0_action = {
- .handler = counter0_irq,
- .flags = IRQF_DISABLED,
- .name = "alchemy-toy",
- .dev_id = NULL,
+static struct clocksource au1x_counter1_clocksource = {
+ .name = "alchemy-counter1",
+ .read = au1x_counter1_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .rating = 100,
};
-/* When we wakeup from sleep, we have to "catch up" on all of the
- * timer ticks we have missed.
- */
-void wakeup_counter0_adjust(void)
+static int au1x_rtcmatch2_set_next_event(unsigned long delta,
+ struct clock_event_device *cd)
{
- unsigned long pc0;
- int time_elapsed;
-
- pc0 = au_readl(SYS_TOYREAD);
- if (pc0 < last_match20)
- /* counter overflowed */
- time_elapsed = (0xffffffff - last_match20) + pc0;
- else
- time_elapsed = pc0 - last_match20;
-
- while (time_elapsed > 0) {
- time_elapsed -= MATCH20_INC;
- last_match20 += MATCH20_INC;
- }
-
- last_pc0 = pc0;
- au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+ delta += au_readl(SYS_RTCREAD);
+ /* wait for register access */
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
+ ;
+ au_writel(delta, SYS_RTCMATCH2);
au_sync();
+ return 0;
}
-/* This is just for debugging to set the timer for a sleep delay. */
-void wakeup_counter0_set(int ticks)
+static void au1x_rtcmatch2_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *cd)
{
- unsigned long pc0;
-
- pc0 = au_readl(SYS_TOYREAD);
- last_pc0 = pc0;
- au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2);
- au_sync();
}
-#endif
-/*
- * I haven't found anyone that doesn't use a 12 MHz source clock,
- * but just in case.....
- */
-#define AU1000_SRC_CLK 12000000
-
-/*
- * We read the real processor speed from the PLL. This is important
- * because it is more accurate than computing it from the 32 KHz
- * counter, if it exists. If we don't have an accurate processor
- * speed, all of the peripherals that derive their clocks based on
- * this advertised speed will introduce error and sometimes not work
- * properly. This function is futher convoluted to still allow configurations
- * to do that in case they have really, really old silicon with a
- * write-only PLL register, that we need the 32 KHz when power management
- * "wait" is enabled, and we need to detect if the 32 KHz isn't present
- * but requested......got it? :-) -- Dan
- */
-unsigned long calc_clock(void)
+static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id)
{
- unsigned long cpu_speed;
- unsigned long flags;
- unsigned long counter;
-
- spin_lock_irqsave(&time_lock, flags);
-
- /* Power management cares if we don't have a 32 KHz counter. */
- no_au1xxx_32khz = 0;
- counter = au_readl(SYS_COUNTER_CNTRL);
- if (counter & SYS_CNTRL_E0) {
- int trim_divide = 16;
-
- au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);
-
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
- /* RTC now ticks at 32.768/16 kHz */
- au_writel(trim_divide - 1, SYS_RTCTRIM);
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
+ struct clock_event_device *cd = dev_id;
+ cd->event_handler(cd);
+ return IRQ_HANDLED;
+}
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
- au_writel(0, SYS_TOYWRITE);
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
- } else
- no_au1xxx_32khz = 1;
+static struct clock_event_device au1x_rtcmatch2_clockdev = {
+ .name = "rtcmatch2",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 100,
+ .irq = AU1000_RTC_MATCH2_INT,
+ .set_next_event = au1x_rtcmatch2_set_next_event,
+ .set_mode = au1x_rtcmatch2_set_mode,
+ .cpumask = CPU_MASK_ALL_PTR,
+};
- /*
- * On early Au1000, sys_cpupll was write-only. Since these
- * silicon versions of Au1000 are not sold by AMD, we don't bend
- * over backwards trying to determine the frequency.
- */
- if (cur_cpu_spec[0]->cpu_pll_wo)
-#ifdef CONFIG_SOC_AU1000_FREQUENCY
- cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
-#else
- cpu_speed = 396000000;
-#endif
- else
- cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
- /* On Alchemy CPU:counter ratio is 1:1 */
- mips_hpt_frequency = cpu_speed;
- /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
- set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
- & 0x03) + 2) * 16));
- spin_unlock_irqrestore(&time_lock, flags);
- return cpu_speed;
-}
+static struct irqaction au1x_rtcmatch2_irqaction = {
+ .handler = au1x_rtcmatch2_irq,
+ .flags = IRQF_DISABLED | IRQF_TIMER,
+ .name = "timer",
+ .dev_id = &au1x_rtcmatch2_clockdev,
+};
void __init plat_time_init(void)
{
- unsigned int est_freq = calc_clock();
-
- est_freq += 5000; /* round */
- est_freq -= est_freq%10000;
- printk(KERN_INFO "CPU frequency %u.%02u MHz\n",
- est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
- set_au1x00_speed(est_freq);
- set_au1x00_lcd_clock(); /* program the LCD clock */
+ struct clock_event_device *cd = &au1x_rtcmatch2_clockdev;
+ unsigned long t;
+
+ /* Check if firmware (YAMON, ...) has enabled 32kHz and clock
+ * has been detected. If so install the rtcmatch2 clocksource,
+ * otherwise don't bother. Note that both bits being set is by
+ * no means a definite guarantee that the counters actually work
+ * (the 32S bit seems to be stuck set to 1 once a single clock-
+ * edge is detected, hence the timeouts).
+ */
+ if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
+ goto cntr_err;
-#ifdef CONFIG_PM
/*
- * setup counter 0, since it keeps ticking after a
- * 'wait' instruction has been executed. The CP0 timer and
- * counter 1 do NOT continue running after 'wait'
- *
- * It's too early to call request_irq() here, so we handle
- * counter 0 interrupt as a special irq and it doesn't show
- * up under /proc/interrupts.
- *
- * Check to ensure we really have a 32 KHz oscillator before
- * we do this.
+ * setup counter 1 (RTC) to tick at full speed
*/
- if (no_au1xxx_32khz)
- printk(KERN_WARNING "WARNING: no 32KHz clock found.\n");
- else {
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
- au_writel(0, SYS_TOYWRITE);
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
-
- au_writel(au_readl(SYS_WAKEMSK) | (1 << 8), SYS_WAKEMSK);
- au_writel(~0, SYS_WAKESRC);
- au_sync();
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+ t = 0xffffff;
+ while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && t--)
+ asm volatile ("nop");
+ if (!t)
+ goto cntr_err;
- /* Setup match20 to interrupt once every HZ */
- last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
- au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
- au_sync();
- while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
- setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action);
+ au_writel(0, SYS_RTCTRIM); /* 32.768 kHz */
+ au_sync();
- /* We can use the real 'wait' instruction. */
- allow_au1k_wait = 1;
- }
+ t = 0xffffff;
+ while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+ asm volatile ("nop");
+ if (!t)
+ goto cntr_err;
+ au_writel(0, SYS_RTCWRITE);
+ au_sync();
-#endif
+ t = 0xffffff;
+ while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+ asm volatile ("nop");
+ if (!t)
+ goto cntr_err;
+
+ /* register counter1 clocksource and event device */
+ clocksource_set_clock(&au1x_counter1_clocksource, 32768);
+ clocksource_register(&au1x_counter1_clocksource);
+
+ cd->shift = 32;
+ cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift);
+ cd->max_delta_ns = clockevent_delta2ns(0xffffffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(8, cd); /* ~0.25ms */
+ clockevents_register_device(cd);
+ setup_irq(AU1000_RTC_MATCH2_INT, &au1x_rtcmatch2_irqaction);
+
+ printk(KERN_INFO "Alchemy clocksource installed\n");
+
+ /* can now use 'wait' */
+ allow_au1k_wait = 1;
+ return;
+
+cntr_err:
+ /* counters unusable, use C0 counter */
+ r4k_clockevent_init();
+ init_r4k_clocksource();
+ allow_au1k_wait = 0;
}
diff --git a/arch/mips/alchemy/db1x00/init.c b/arch/mips/alchemy/db1x00/init.c
deleted file mode 100644
index 847413514964..000000000000
--- a/arch/mips/alchemy/db1x00/init.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * PB1000 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
-#ifdef CONFIG_MIPS_BOSPORUS
- return "Alchemy Bosporus Gateway Reference";
-#else
- return "Alchemy Db1x00";
-#endif
-}
-
-void __init prom_init(void)
-{
- unsigned char *memsize_str;
- unsigned long memsize;
-
- prom_argc = fw_arg0;
- prom_argv = (char **)fw_arg1;
- prom_envp = (char **)fw_arg2;
-
- prom_init_cmdline();
-
- memsize_str = prom_getenv("memsize");
- if (!memsize_str)
- memsize = 0x04000000;
- else
- strict_strtol(memsize_str, 0, &memsize);
- add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile
new file mode 100644
index 000000000000..730f9f2b30e8
--- /dev/null
+++ b/arch/mips/alchemy/devboards/Makefile
@@ -0,0 +1,18 @@
+#
+# Alchemy Develboards
+#
+
+obj-y += prom.o
+obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_MIPS_PB1000) += pb1000/
+obj-$(CONFIG_MIPS_PB1100) += pb1100/
+obj-$(CONFIG_MIPS_PB1200) += pb1200/
+obj-$(CONFIG_MIPS_PB1500) += pb1500/
+obj-$(CONFIG_MIPS_PB1550) += pb1550/
+obj-$(CONFIG_MIPS_DB1000) += db1x00/
+obj-$(CONFIG_MIPS_DB1100) += db1x00/
+obj-$(CONFIG_MIPS_DB1200) += pb1200/
+obj-$(CONFIG_MIPS_DB1500) += db1x00/
+obj-$(CONFIG_MIPS_DB1550) += db1x00/
+obj-$(CONFIG_MIPS_BOSPORUS) += db1x00/
+obj-$(CONFIG_MIPS_MIRAGE) += db1x00/
diff --git a/arch/mips/alchemy/db1x00/Makefile b/arch/mips/alchemy/devboards/db1x00/Makefile
index 274db3b55d82..432241ab8677 100644
--- a/arch/mips/alchemy/db1x00/Makefile
+++ b/arch/mips/alchemy/devboards/db1x00/Makefile
@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor DBAu1xx0 boards.
#
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o irqmap.o
diff --git a/arch/mips/alchemy/db1x00/board_setup.c b/arch/mips/alchemy/devboards/db1x00/board_setup.c
index 9e5ccbbfcedd..a75ffbf99f25 100644
--- a/arch/mips/alchemy/db1x00/board_setup.c
+++ b/arch/mips/alchemy/devboards/db1x00/board_setup.c
@@ -32,8 +32,20 @@
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-db1x00/db1x00.h>
+#include <prom.h>
+
+
static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
+const char *get_system_type(void)
+{
+#ifdef CONFIG_MIPS_BOSPORUS
+ return "Alchemy Bosporus Gateway Reference";
+#else
+ return "Alchemy Db1x00";
+#endif
+}
+
void board_reset(void)
{
/* Hit BCSR.SW_RESET[RESET] */
@@ -43,6 +55,31 @@ void board_reset(void)
void __init board_setup(void)
{
u32 pin_func = 0;
+ char *argptr;
+
+ argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
+#ifdef CONFIG_FB_AU1100
+ argptr = strstr(argptr, "video=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ /* default panel */
+ /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
+ }
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+ /* au1000 does not support vra, au1500 and au1100 do */
+ strcat(argptr, " au1000_audio=vra");
+ argptr = prom_getcmdline();
+#endif
/* Not valid for Au1550 */
#if defined(CONFIG_IRDA) && \
diff --git a/arch/mips/alchemy/db1x00/irqmap.c b/arch/mips/alchemy/devboards/db1x00/irqmap.c
index 94c090e8bf7a..0b09025087c6 100644
--- a/arch/mips/alchemy/db1x00/irqmap.c
+++ b/arch/mips/alchemy/devboards/db1x00/irqmap.c
@@ -27,6 +27,7 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
@@ -66,21 +67,24 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
#ifndef CONFIG_MIPS_MIRAGE
#ifdef CONFIG_MIPS_DB1550
- { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
- { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+ { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
+ { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
#else
- { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */
- { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */
- { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
+ { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 Fully_Interted# */
+ { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 STSCHG# */
+ { AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
- { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */
- { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */
- { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+ { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 Fully_Interted# */
+ { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 STSCHG# */
+ { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
#endif
#else
- { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */
+ { AU1000_GPIO_7, IRQF_TRIGGER_RISING, 0 }, /* touchscreen pen down */
#endif
};
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
+void __init board_init_irq(void)
+{
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
diff --git a/arch/mips/alchemy/pb1000/Makefile b/arch/mips/alchemy/devboards/pb1000/Makefile
index 99bbec0ca41b..97c6615ba2bb 100644
--- a/arch/mips/alchemy/pb1000/Makefile
+++ b/arch/mips/alchemy/devboards/pb1000/Makefile
@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1000 board.
#
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
diff --git a/arch/mips/alchemy/pb1000/board_setup.c b/arch/mips/alchemy/devboards/pb1000/board_setup.c
index 25df167a95b3..aed2fdecc709 100644
--- a/arch/mips/alchemy/pb1000/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1000/board_setup.c
@@ -23,22 +23,48 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/init.h>
#include <linux/delay.h>
-
+#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1000.h>
+#include <prom.h>
+
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+ { AU1000_GPIO_15, IRQF_TRIGGER_LOW, 0 },
+};
+
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1000";
+}
void board_reset(void)
{
}
+void __init board_init_irq(void)
+{
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
void __init board_setup(void)
{
u32 pin_func, static_cfg0;
u32 sys_freqctrl, sys_clksrc;
u32 prid = read_c0_prid();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char *argptr = prom_getcmdline();
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
au_writel(8, SYS_AUXPLL);
au_writel(0, SYS_PINSTATERD);
diff --git a/arch/mips/alchemy/pb1100/Makefile b/arch/mips/alchemy/devboards/pb1100/Makefile
index 793e97c49e46..c586dd7e91dc 100644
--- a/arch/mips/alchemy/pb1100/Makefile
+++ b/arch/mips/alchemy/devboards/pb1100/Makefile
@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1100 board.
#
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
diff --git a/arch/mips/alchemy/pb1100/board_setup.c b/arch/mips/alchemy/devboards/pb1100/board_setup.c
index c0bfd59a7a36..4df57fae15d4 100644
--- a/arch/mips/alchemy/pb1100/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1100/board_setup.c
@@ -25,19 +25,66 @@
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1100.h>
+#include <prom.h>
+
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+ { AU1000_GPIO_9, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card Fully_Inserted# */
+ { AU1000_GPIO_10, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card STSCHG# */
+ { AU1000_GPIO_11, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card IRQ# */
+ { AU1000_GPIO_13, IRQF_TRIGGER_LOW, 0 }, /* DC_IRQ# */
+};
+
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1100";
+}
+
void board_reset(void)
{
/* Hit BCSR.RST_VDDI[SOFT_RESET] */
au_writel(0x00000000, PB1100_RST_VDDI);
}
+void __init board_init_irq(void)
+{
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
void __init board_setup(void)
{
volatile void __iomem *base = (volatile void __iomem *)0xac000000UL;
+ char *argptr;
+
+ argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
+#ifdef CONFIG_FB_AU1100
+ argptr = strstr(argptr, "video=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ /* default panel */
+ /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
+ }
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+ /* au1000 does not support vra, au1500 and au1100 do */
+ strcat(argptr, " au1000_audio=vra");
+ argptr = prom_getcmdline();
+#endif
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
au_writel(8, SYS_AUXPLL);
diff --git a/arch/mips/alchemy/pb1200/Makefile b/arch/mips/alchemy/devboards/pb1200/Makefile
index d678adf7ce85..c8c3a99fb68a 100644
--- a/arch/mips/alchemy/pb1200/Makefile
+++ b/arch/mips/alchemy/devboards/pb1200/Makefile
@@ -2,7 +2,6 @@
# Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards.
#
-lib-y := init.o board_setup.o irqmap.o
-obj-y += platform.o
+obj-y := board_setup.o irqmap.o platform.o
EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/alchemy/pb1200/board_setup.c b/arch/mips/alchemy/devboards/pb1200/board_setup.c
index 6cb2115059ad..94e6b7e7753d 100644
--- a/arch/mips/alchemy/pb1200/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1200/board_setup.c
@@ -30,8 +30,11 @@
#include <prom.h>
#include <au1xxx.h>
-extern void _board_init_irq(void);
-extern void (*board_init_irq)(void);
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1200";
+}
void board_reset(void)
{
@@ -41,7 +44,19 @@ void board_reset(void)
void __init board_setup(void)
{
- char *argptr = NULL;
+ char *argptr;
+
+ argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+#ifdef CONFIG_FB_AU1200
+ strcat(argptr, " video=au1200fb:panel:bs");
+#endif
#if 0
{
@@ -99,16 +114,6 @@ void __init board_setup(void)
}
#endif
-#ifdef CONFIG_FB_AU1200
- argptr = prom_getcmdline();
-#ifdef CONFIG_MIPS_PB1200
- strcat(argptr, " video=au1200fb:panel:bs");
-#endif
-#ifdef CONFIG_MIPS_DB1200
- strcat(argptr, " video=au1200fb:panel:bs");
-#endif
-#endif
-
/*
* The Pb1200 development board uses external MUX for PSC0 to
* support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
@@ -124,9 +129,6 @@ void __init board_setup(void)
#ifdef CONFIG_MIPS_DB1200
printk(KERN_INFO "AMD Alchemy Db1200 Board\n");
#endif
-
- /* Setup Pb1200 External Interrupt Controller */
- board_init_irq = _board_init_irq;
}
int board_au1200fb_panel(void)
diff --git a/arch/mips/alchemy/pb1200/irqmap.c b/arch/mips/alchemy/devboards/pb1200/irqmap.c
index 2a505ad8715b..fe47498da280 100644
--- a/arch/mips/alchemy/pb1200/irqmap.c
+++ b/arch/mips/alchemy/devboards/pb1200/irqmap.c
@@ -40,91 +40,65 @@
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
/* This is external interrupt cascade */
- { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 },
};
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
/*
* Support for External interrupts on the Pb1200 Development platform.
*/
-static volatile int pb1200_cascade_en;
-irqreturn_t pb1200_cascade_handler(int irq, void *dev_id)
+static void pb1200_cascade_handler(unsigned int irq, struct irq_desc *d)
{
unsigned short bisr = bcsr->int_status;
- int extirq_nr = 0;
-
- /* Clear all the edge interrupts. This has no effect on level. */
- bcsr->int_status = bisr;
- for ( ; bisr; bisr &= bisr - 1) {
- extirq_nr = PB1200_INT_BEGIN + __ffs(bisr);
- /* Ack and dispatch IRQ */
- do_IRQ(extirq_nr);
- }
-
- return IRQ_RETVAL(1);
-}
-inline void pb1200_enable_irq(unsigned int irq_nr)
-{
- bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
- bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
+ for ( ; bisr; bisr &= bisr - 1)
+ generic_handle_irq(PB1200_INT_BEGIN + __ffs(bisr));
}
-inline void pb1200_disable_irq(unsigned int irq_nr)
+/* NOTE: both the enable and mask bits must be cleared, otherwise the
+ * CPLD generates tons of spurious interrupts (at least on the DB1200).
+ */
+static void pb1200_mask_irq(unsigned int irq_nr)
{
bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
+ au_sync();
}
-static unsigned int pb1200_setup_cascade(void)
-{
- return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
- 0, "Pb1200 Cascade", &pb1200_cascade_handler);
-}
-
-static unsigned int pb1200_startup_irq(unsigned int irq)
+static void pb1200_maskack_irq(unsigned int irq_nr)
{
- if (++pb1200_cascade_en == 1) {
- int res;
-
- res = pb1200_setup_cascade();
- if (res)
- return res;
- }
-
- pb1200_enable_irq(irq);
-
- return 0;
+ bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
+ bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
+ bcsr->int_status = 1 << (irq_nr - PB1200_INT_BEGIN); /* ack */
+ au_sync();
}
-static void pb1200_shutdown_irq(unsigned int irq)
+static void pb1200_unmask_irq(unsigned int irq_nr)
{
- pb1200_disable_irq(irq);
- if (--pb1200_cascade_en == 0)
- free_irq(AU1000_GPIO_7, &pb1200_cascade_handler);
+ bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
+ bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
+ au_sync();
}
-static struct irq_chip external_irq_type = {
+static struct irq_chip pb1200_cpld_irq_type = {
#ifdef CONFIG_MIPS_PB1200
.name = "Pb1200 Ext",
#endif
#ifdef CONFIG_MIPS_DB1200
.name = "Db1200 Ext",
#endif
- .startup = pb1200_startup_irq,
- .shutdown = pb1200_shutdown_irq,
- .ack = pb1200_disable_irq,
- .mask = pb1200_disable_irq,
- .mask_ack = pb1200_disable_irq,
- .unmask = pb1200_enable_irq,
+ .mask = pb1200_mask_irq,
+ .mask_ack = pb1200_maskack_irq,
+ .unmask = pb1200_unmask_irq,
};
-void _board_init_irq(void)
+void __init board_init_irq(void)
{
unsigned int irq;
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+
#ifdef CONFIG_MIPS_PB1200
/* We have a problem with CPLD rev 3. */
if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) {
@@ -146,15 +120,15 @@ void _board_init_irq(void)
panic("Game over. Your score is 0.");
}
#endif
+ /* mask & disable & ack all */
+ bcsr->intclr_mask = 0xffff;
+ bcsr->intclr = 0xffff;
+ bcsr->int_status = 0xffff;
+ au_sync();
- for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) {
- set_irq_chip_and_handler(irq, &external_irq_type,
- handle_level_irq);
- pb1200_disable_irq(irq);
- }
+ for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++)
+ set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type,
+ handle_level_irq, "level");
- /*
- * GPIO_7 can not be hooked here, so it is hooked upon first
- * request of any source attached to the cascade.
- */
+ set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler);
}
diff --git a/arch/mips/alchemy/pb1200/platform.c b/arch/mips/alchemy/devboards/pb1200/platform.c
index 95303297c534..95303297c534 100644
--- a/arch/mips/alchemy/pb1200/platform.c
+++ b/arch/mips/alchemy/devboards/pb1200/platform.c
diff --git a/arch/mips/alchemy/pb1500/Makefile b/arch/mips/alchemy/devboards/pb1500/Makefile
index 602f38df20bb..173b419a7479 100644
--- a/arch/mips/alchemy/pb1500/Makefile
+++ b/arch/mips/alchemy/devboards/pb1500/Makefile
@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1500 board.
#
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
diff --git a/arch/mips/alchemy/pb1500/board_setup.c b/arch/mips/alchemy/devboards/pb1500/board_setup.c
index 035771c6e5b8..fed3b093156a 100644
--- a/arch/mips/alchemy/pb1500/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1500/board_setup.c
@@ -25,20 +25,64 @@
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1500.h>
+#include <prom.h>
+
+
+char irq_tab_alchemy[][5] __initdata = {
+ [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT370 */
+ [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */
+};
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+ { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
+ { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
+};
+
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1500";
+}
+
void board_reset(void)
{
/* Hit BCSR.RST_VDDI[SOFT_RESET] */
au_writel(0x00000000, PB1500_RST_VDDI);
}
+void __init board_init_irq(void)
+{
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
void __init board_setup(void)
{
u32 pin_func;
u32 sys_freqctrl, sys_clksrc;
+ char *argptr;
+
+ argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+ /* au1000 does not support vra, au1500 and au1100 do */
+ strcat(argptr, " au1000_audio=vra");
+ argptr = prom_getcmdline();
+#endif
sys_clksrc = sys_freqctrl = pin_func = 0;
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
diff --git a/arch/mips/alchemy/pb1550/Makefile b/arch/mips/alchemy/devboards/pb1550/Makefile
index 7d8beca87fa5..cff95bcdb2ca 100644
--- a/arch/mips/alchemy/pb1550/Makefile
+++ b/arch/mips/alchemy/devboards/pb1550/Makefile
@@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1550 board.
#
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
diff --git a/arch/mips/alchemy/pb1550/board_setup.c b/arch/mips/alchemy/devboards/pb1550/board_setup.c
index 0ed76b64b6ab..b6e9e7d247a3 100644
--- a/arch/mips/alchemy/pb1550/board_setup.c
+++ b/arch/mips/alchemy/devboards/pb1550/board_setup.c
@@ -28,20 +28,54 @@
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1550.h>
+#include <prom.h>
+
+
+char irq_tab_alchemy[][5] __initdata = {
+ [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */
+ [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */
+};
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+ { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
+ { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
+};
+
+const char *get_system_type(void)
+{
+ return "Alchemy Pb1550";
+}
+
void board_reset(void)
{
/* Hit BCSR.SYSTEM[RESET] */
au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C);
}
+void __init board_init_irq(void)
+{
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
void __init board_setup(void)
{
u32 pin_func;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char *argptr;
+ argptr = prom_getcmdline();
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
/*
* Enable PSC1 SYNC for AC'97. Normaly done in audio driver,
* but it is board specific code, so put it here.
diff --git a/arch/mips/alchemy/devboards/pm.c b/arch/mips/alchemy/devboards/pm.c
new file mode 100644
index 000000000000..d5eb9c325ed0
--- /dev/null
+++ b/arch/mips/alchemy/devboards/pm.c
@@ -0,0 +1,229 @@
+/*
+ * Alchemy Development Board example suspend userspace interface.
+ *
+ * (c) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
+ */
+
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/suspend.h>
+#include <linux/sysfs.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/*
+ * Generic suspend userspace interface for Alchemy development boards.
+ * This code exports a few sysfs nodes under /sys/power/db1x/ which
+ * can be used by userspace to en/disable all au1x-provided wakeup
+ * sources and configure the timeout after which the the TOYMATCH2 irq
+ * is to trigger a wakeup.
+ */
+
+
+static unsigned long db1x_pm_sleep_secs;
+static unsigned long db1x_pm_wakemsk;
+static unsigned long db1x_pm_last_wakesrc;
+
+static int db1x_pm_enter(suspend_state_t state)
+{
+ /* enable GPIO based wakeup */
+ au_writel(1, SYS_PININPUTEN);
+
+ /* clear and setup wake cause and source */
+ au_writel(0, SYS_WAKEMSK);
+ au_sync();
+ au_writel(0, SYS_WAKESRC);
+ au_sync();
+
+ au_writel(db1x_pm_wakemsk, SYS_WAKEMSK);
+ au_sync();
+
+ /* setup 1Hz-timer-based wakeup: wait for reg access */
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+ asm volatile ("nop");
+
+ au_writel(au_readl(SYS_TOYREAD) + db1x_pm_sleep_secs, SYS_TOYMATCH2);
+ au_sync();
+
+ /* wait for value to really hit the register */
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+ asm volatile ("nop");
+
+ /* ...and now the sandman can come! */
+ au_sleep();
+
+ return 0;
+}
+
+static int db1x_pm_begin(suspend_state_t state)
+{
+ if (!db1x_pm_wakemsk) {
+ printk(KERN_ERR "db1x: no wakeup source activated!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void db1x_pm_end(void)
+{
+ /* read and store wakeup source, the clear the register. To
+ * be able to clear it, WAKEMSK must be cleared first.
+ */
+ db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+
+ au_writel(0, SYS_WAKEMSK);
+ au_writel(0, SYS_WAKESRC);
+ au_sync();
+
+}
+
+static struct platform_suspend_ops db1x_pm_ops = {
+ .valid = suspend_valid_only_mem,
+ .begin = db1x_pm_begin,
+ .enter = db1x_pm_enter,
+ .end = db1x_pm_end,
+};
+
+#define ATTRCMP(x) (0 == strcmp(attr->attr.name, #x))
+
+static ssize_t db1x_pmattr_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int idx;
+
+ if (ATTRCMP(timer_timeout))
+ return sprintf(buf, "%lu\n", db1x_pm_sleep_secs);
+
+ else if (ATTRCMP(timer))
+ return sprintf(buf, "%u\n",
+ !!(db1x_pm_wakemsk & SYS_WAKEMSK_M2));
+
+ else if (ATTRCMP(wakesrc))
+ return sprintf(buf, "%lu\n", db1x_pm_last_wakesrc);
+
+ else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
+ ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
+ ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
+ idx = (attr->attr.name)[4] - '0';
+ return sprintf(buf, "%d\n",
+ !!(db1x_pm_wakemsk & SYS_WAKEMSK_GPIO(idx)));
+
+ } else if (ATTRCMP(wakemsk)) {
+ return sprintf(buf, "%08lx\n", db1x_pm_wakemsk);
+ }
+
+ return -ENOENT;
+}
+
+static ssize_t db1x_pmattr_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *instr,
+ size_t bytes)
+{
+ unsigned long l;
+ int tmp;
+
+ if (ATTRCMP(timer_timeout)) {
+ tmp = strict_strtoul(instr, 0, &l);
+ if (tmp)
+ return tmp;
+
+ db1x_pm_sleep_secs = l;
+
+ } else if (ATTRCMP(timer)) {
+ if (instr[0] != '0')
+ db1x_pm_wakemsk |= SYS_WAKEMSK_M2;
+ else
+ db1x_pm_wakemsk &= ~SYS_WAKEMSK_M2;
+
+ } else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
+ ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
+ ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
+ tmp = (attr->attr.name)[4] - '0';
+ if (instr[0] != '0') {
+ db1x_pm_wakemsk |= SYS_WAKEMSK_GPIO(tmp);
+ } else {
+ db1x_pm_wakemsk &= ~SYS_WAKEMSK_GPIO(tmp);
+ }
+
+ } else if (ATTRCMP(wakemsk)) {
+ tmp = strict_strtoul(instr, 0, &l);
+ if (tmp)
+ return tmp;
+
+ db1x_pm_wakemsk = l & 0x0000003f;
+
+ } else
+ bytes = -ENOENT;
+
+ return bytes;
+}
+
+#define ATTR(x) \
+ static struct kobj_attribute x##_attribute = \
+ __ATTR(x, 0664, db1x_pmattr_show, \
+ db1x_pmattr_store);
+
+ATTR(gpio0) /* GPIO-based wakeup enable */
+ATTR(gpio1)
+ATTR(gpio2)
+ATTR(gpio3)
+ATTR(gpio4)
+ATTR(gpio5)
+ATTR(gpio6)
+ATTR(gpio7)
+ATTR(timer) /* TOYMATCH2-based wakeup enable */
+ATTR(timer_timeout) /* timer-based wakeup timeout value, in seconds */
+ATTR(wakesrc) /* contents of SYS_WAKESRC after last wakeup */
+ATTR(wakemsk) /* direct access to SYS_WAKEMSK */
+
+#define ATTR_LIST(x) & x ## _attribute.attr
+static struct attribute *db1x_pmattrs[] = {
+ ATTR_LIST(gpio0),
+ ATTR_LIST(gpio1),
+ ATTR_LIST(gpio2),
+ ATTR_LIST(gpio3),
+ ATTR_LIST(gpio4),
+ ATTR_LIST(gpio5),
+ ATTR_LIST(gpio6),
+ ATTR_LIST(gpio7),
+ ATTR_LIST(timer),
+ ATTR_LIST(timer_timeout),
+ ATTR_LIST(wakesrc),
+ ATTR_LIST(wakemsk),
+ NULL, /* terminator */
+};
+
+static struct attribute_group db1x_pmattr_group = {
+ .name = "db1x",
+ .attrs = db1x_pmattrs,
+};
+
+/*
+ * Initialize suspend interface
+ */
+static int __init pm_init(void)
+{
+ /* init TOY to tick at 1Hz if not already done. No need to wait
+ * for confirmation since there's plenty of time from here to
+ * the next suspend cycle.
+ */
+ if (au_readl(SYS_TOYTRIM) != 32767) {
+ au_writel(32767, SYS_TOYTRIM);
+ au_sync();
+ }
+
+ db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+
+ au_writel(0, SYS_WAKESRC);
+ au_sync();
+ au_writel(0, SYS_WAKEMSK);
+ au_sync();
+
+ suspend_set_ops(&db1x_pm_ops);
+
+ return sysfs_create_group(power_kobj, &db1x_pmattr_group);
+}
+
+late_initcall(pm_init);
diff --git a/arch/mips/alchemy/pb1200/init.c b/arch/mips/alchemy/devboards/prom.c
index e9b2a0fd48ae..0042bd6b1d7d 100644
--- a/arch/mips/alchemy/pb1200/init.c
+++ b/arch/mips/alchemy/devboards/prom.c
@@ -1,9 +1,9 @@
/*
+ * Common code used by all Alchemy develboards.
*
- * BRIEF MODULE DESCRIPTION
- * PB1200 board setup
+ * Extracted from files which had this to say:
*
- * Copyright 2001, 2008 MontaVista Software Inc.
+ * Copyright 2000, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.com>
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,15 +29,19 @@
#include <linux/init.h>
#include <linux/kernel.h>
-
#include <asm/bootinfo.h>
-
+#include <asm/mach-au1x00/au1000.h>
#include <prom.h>
-const char *get_system_type(void)
-{
- return "Alchemy Pb1200";
-}
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_DB1000) || \
+ defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || \
+ defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500) || \
+ defined(CONFIG_MIPS_BOSPORUS) || defined(CONFIG_MIPS_MIRAGE)
+#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x04000000
+
+#else /* Au1550/Au1200-based develboards */
+#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x08000000
+#endif
void __init prom_init(void)
{
@@ -51,8 +55,8 @@ void __init prom_init(void)
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str)
- memsize = 0x08000000;
+ memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
else
- strict_strtol(memsize_str, 0, &memsize);
+ strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
diff --git a/arch/mips/alchemy/mtx-1/board_setup.c b/arch/mips/alchemy/mtx-1/board_setup.c
index 3f8079186cf2..8ed1ae12bc55 100644
--- a/arch/mips/alchemy/mtx-1/board_setup.c
+++ b/arch/mips/alchemy/mtx-1/board_setup.c
@@ -32,6 +32,8 @@
#include <asm/mach-au1x00/au1000.h>
+#include <prom.h>
+
extern int (*board_pci_idsel)(unsigned int devsel, int assert);
int mtx1_pci_idsel(unsigned int devsel, int assert);
@@ -43,6 +45,16 @@ void board_reset(void)
void __init board_setup(void)
{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char *argptr;
+ argptr = prom_getcmdline();
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
/* Enable USB power switch */
au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR);
diff --git a/arch/mips/alchemy/mtx-1/init.c b/arch/mips/alchemy/mtx-1/init.c
index 3bae13c28954..5e871c8d9e96 100644
--- a/arch/mips/alchemy/mtx-1/init.c
+++ b/arch/mips/alchemy/mtx-1/init.c
@@ -55,6 +55,6 @@ void __init prom_init(void)
if (!memsize_str)
memsize = 0x04000000;
else
- strict_strtol(memsize_str, 0, &memsize);
+ strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
diff --git a/arch/mips/alchemy/mtx-1/irqmap.c b/arch/mips/alchemy/mtx-1/irqmap.c
index f2bf02951e9c..f1ab12ab3433 100644
--- a/arch/mips/alchemy/mtx-1/irqmap.c
+++ b/arch/mips/alchemy/mtx-1/irqmap.c
@@ -27,7 +27,7 @@
*/
#include <linux/init.h>
-
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
char irq_tab_alchemy[][5] __initdata = {
@@ -42,11 +42,15 @@ char irq_tab_alchemy[][5] __initdata = {
};
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
- { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
- { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
+ { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
};
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
+
+void __init board_init_irq(void)
+{
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
diff --git a/arch/mips/alchemy/pb1000/init.c b/arch/mips/alchemy/pb1000/init.c
deleted file mode 100644
index 8a9c7d57208d..000000000000
--- a/arch/mips/alchemy/pb1000/init.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Pb1000 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
- return "Alchemy Pb1000";
-}
-
-void __init prom_init(void)
-{
- unsigned char *memsize_str;
- unsigned long memsize;
-
- prom_argc = (int)fw_arg0;
- prom_argv = (char **)fw_arg1;
- prom_envp = (char **)fw_arg2;
-
- prom_init_cmdline();
- memsize_str = prom_getenv("memsize");
- if (!memsize_str)
- memsize = 0x04000000;
- else
- strict_strtol(memsize_str, 0, &memsize);
- add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1000/irqmap.c b/arch/mips/alchemy/pb1000/irqmap.c
deleted file mode 100644
index b3d56b0af321..000000000000
--- a/arch/mips/alchemy/pb1000/irqmap.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Au1xxx irq map table
- *
- * Copyright 2003 Embedded Edge, LLC
- * dan@embeddededge.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
- { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/alchemy/pb1100/init.c b/arch/mips/alchemy/pb1100/init.c
deleted file mode 100644
index 7c6792308bc5..000000000000
--- a/arch/mips/alchemy/pb1100/init.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- * Pb1100 board setup
- *
- * Copyright 2002, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
- return "Alchemy Pb1100";
-}
-
-void __init prom_init(void)
-{
- unsigned char *memsize_str;
- unsigned long memsize;
-
- prom_argc = fw_arg0;
- prom_argv = (char **)fw_arg1;
- prom_envp = (char **)fw_arg3;
-
- prom_init_cmdline();
-
- memsize_str = prom_getenv("memsize");
- if (!memsize_str)
- memsize = 0x04000000;
- else
- strict_strtol(memsize_str, 0, &memsize);
-
- add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1100/irqmap.c b/arch/mips/alchemy/pb1100/irqmap.c
deleted file mode 100644
index 9b7dd8b41283..000000000000
--- a/arch/mips/alchemy/pb1100/irqmap.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Au1xx0 IRQ map table
- *
- * Copyright 2003 Embedded Edge, LLC
- * dan@embeddededge.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
- { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card Fully_Inserted# */
- { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card STSCHG# */
- { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card IRQ# */
- { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, /* DC_IRQ# */
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/alchemy/pb1500/init.c b/arch/mips/alchemy/pb1500/init.c
deleted file mode 100644
index 3b6e395cf952..000000000000
--- a/arch/mips/alchemy/pb1500/init.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- * Pb1500 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
- return "Alchemy Pb1500";
-}
-
-void __init prom_init(void)
-{
- unsigned char *memsize_str;
- unsigned long memsize;
-
- prom_argc = (int)fw_arg0;
- prom_argv = (char **)fw_arg1;
- prom_envp = (char **)fw_arg2;
-
- prom_init_cmdline();
- memsize_str = prom_getenv("memsize");
- if (!memsize_str)
- memsize = 0x04000000;
- else
- strict_strtol(memsize_str, 0, &memsize);
- add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1500/irqmap.c b/arch/mips/alchemy/pb1500/irqmap.c
deleted file mode 100644
index 39c4682766a8..000000000000
--- a/arch/mips/alchemy/pb1500/irqmap.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Au1xxx irq map table
- *
- * Copyright 2003 Embedded Edge, LLC
- * dan@embeddededge.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-char irq_tab_alchemy[][5] __initdata = {
- [12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT370 */
- [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */
-};
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
- { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
- { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/alchemy/pb1550/init.c b/arch/mips/alchemy/pb1550/init.c
deleted file mode 100644
index e1055a13a1a0..000000000000
--- a/arch/mips/alchemy/pb1550/init.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- * Pb1550 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
- return "Alchemy Pb1550";
-}
-
-void __init prom_init(void)
-{
- unsigned char *memsize_str;
- unsigned long memsize;
-
- prom_argc = (int)fw_arg0;
- prom_argv = (char **)fw_arg1;
- prom_envp = (char **)fw_arg2;
-
- prom_init_cmdline();
- memsize_str = prom_getenv("memsize");
- if (!memsize_str)
- memsize = 0x08000000;
- else
- strict_strtol(memsize_str, 0, &memsize);
- add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1550/irqmap.c b/arch/mips/alchemy/pb1550/irqmap.c
deleted file mode 100644
index a02a4d1fa899..000000000000
--- a/arch/mips/alchemy/pb1550/irqmap.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Au1xx0 IRQ map table
- *
- * Copyright 2003 Embedded Edge, LLC
- * dan@embeddededge.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-char irq_tab_alchemy[][5] __initdata = {
- [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */
- [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */
-};
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
- { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/alchemy/xxs1500/board_setup.c b/arch/mips/alchemy/xxs1500/board_setup.c
index 4c587acac5c3..a2634fabc50d 100644
--- a/arch/mips/alchemy/xxs1500/board_setup.c
+++ b/arch/mips/alchemy/xxs1500/board_setup.c
@@ -28,6 +28,8 @@
#include <asm/mach-au1x00/au1000.h>
+#include <prom.h>
+
void board_reset(void)
{
/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
@@ -38,6 +40,16 @@ void __init board_setup(void)
{
u32 pin_func;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ char *argptr;
+ argptr = prom_getcmdline();
+ argptr = strstr(argptr, "console=");
+ if (argptr == NULL) {
+ argptr = prom_getcmdline();
+ strcat(argptr, " console=ttyS0,115200");
+ }
+#endif
+
/* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
pin_func |= SYS_PF_UR3;
diff --git a/arch/mips/alchemy/xxs1500/init.c b/arch/mips/alchemy/xxs1500/init.c
index 7516434760a1..456fa142c093 100644
--- a/arch/mips/alchemy/xxs1500/init.c
+++ b/arch/mips/alchemy/xxs1500/init.c
@@ -53,6 +53,6 @@ void __init prom_init(void)
if (!memsize_str)
memsize = 0x04000000;
else
- strict_strtol(memsize_str, 0, &memsize);
+ strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
diff --git a/arch/mips/alchemy/xxs1500/irqmap.c b/arch/mips/alchemy/xxs1500/irqmap.c
index edf06ed11870..0f0f3012e5fd 100644
--- a/arch/mips/alchemy/xxs1500/irqmap.c
+++ b/arch/mips/alchemy/xxs1500/irqmap.c
@@ -27,23 +27,26 @@
*/
#include <linux/init.h>
-
+#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h>
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
- { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
- { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
- { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+ { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
+ { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
+ { AU1500_GPIO_207, IRQF_TRIGGER_LOW, 0 },
- { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
- { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
- { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
+ { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
+ { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
+ { AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 },
+ { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 },
+ { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* CF interrupt */
+ { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 },
};
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
+void __init board_init_irq(void)
+{
+ au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
new file mode 100644
index 000000000000..094c17e38e16
--- /dev/null
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -0,0 +1,85 @@
+config CAVIUM_OCTEON_SPECIFIC_OPTIONS
+ bool "Enable Octeon specific options"
+ depends on CPU_CAVIUM_OCTEON
+ default "y"
+
+config CAVIUM_OCTEON_2ND_KERNEL
+ bool "Build the kernel to be used as a 2nd kernel on the same chip"
+ depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+ default "n"
+ help
+ This option configures this kernel to be linked at a different
+ address and use the 2nd uart for output. This allows a kernel built
+ with this option to be run at the same time as one built without this
+ option.
+
+config CAVIUM_OCTEON_HW_FIX_UNALIGNED
+ bool "Enable hardware fixups of unaligned loads and stores"
+ depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+ default "y"
+ help
+ Configure the Octeon hardware to automatically fix unaligned loads
+ and stores. Normally unaligned accesses are fixed using a kernel
+ exception handler. This option enables the hardware automatic fixups,
+ which requires only an extra 3 cycles. Disable this option if you
+ are running code that relies on address exceptions on unaligned
+ accesses.
+
+config CAVIUM_OCTEON_CVMSEG_SIZE
+ int "Number of L1 cache lines reserved for CVMSEG memory"
+ depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+ range 0 54
+ default 1
+ help
+ CVMSEG LM is a segment that accesses portions of the dcache as a
+ local memory; the larger CVMSEG is, the smaller the cache is.
+ This selects the size of CVMSEG LM, which is in cache blocks. The
+ legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
+ between zero and 6192 bytes).
+
+config CAVIUM_OCTEON_LOCK_L2
+ bool "Lock often used kernel code in the L2"
+ depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+ default "y"
+ help
+ Enable locking parts of the kernel into the L2 cache.
+
+config CAVIUM_OCTEON_LOCK_L2_TLB
+ bool "Lock the TLB handler in L2"
+ depends on CAVIUM_OCTEON_LOCK_L2
+ default "y"
+ help
+ Lock the low level TLB fast path into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_EXCEPTION
+ bool "Lock the exception handler in L2"
+ depends on CAVIUM_OCTEON_LOCK_L2
+ default "y"
+ help
+ Lock the low level exception handler into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT
+ bool "Lock the interrupt handler in L2"
+ depends on CAVIUM_OCTEON_LOCK_L2
+ default "y"
+ help
+ Lock the low level interrupt handler into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_INTERRUPT
+ bool "Lock the 2nd level interrupt handler in L2"
+ depends on CAVIUM_OCTEON_LOCK_L2
+ default "y"
+ help
+ Lock the 2nd level interrupt handler in L2.
+
+config CAVIUM_OCTEON_LOCK_L2_MEMCPY
+ bool "Lock memcpy() in L2"
+ depends on CAVIUM_OCTEON_LOCK_L2
+ default "y"
+ help
+ Lock the kernel's implementation of memcpy() into L2.
+
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ select SPARSEMEM_STATIC
+ depends on CPU_CAVIUM_OCTEON
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
new file mode 100644
index 000000000000..1c2a7faf5881
--- /dev/null
+++ b/arch/mips/cavium-octeon/Makefile
@@ -0,0 +1,16 @@
+#
+# Makefile for the Cavium Octeon specific kernel interface routines
+# under Linux.
+#
+# 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) 2005-2008 Cavium Networks
+#
+
+obj-y := setup.o serial.o octeon-irq.o csrc-octeon.o
+obj-y += dma-octeon.o flash_setup.o
+obj-y += octeon-memcpy.o
+
+obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c
new file mode 100644
index 000000000000..70fd92c31657
--- /dev/null
+++ b/arch/mips/cavium-octeon/csrc-octeon.c
@@ -0,0 +1,58 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 by Ralf Baechle
+ */
+#include <linux/clocksource.h>
+#include <linux/init.h>
+
+#include <asm/time.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-ipd-defs.h>
+
+/*
+ * Set the current core's cvmcount counter to the value of the
+ * IPD_CLK_COUNT. We do this on all cores as they are brought
+ * on-line. This allows for a read from a local cpu register to
+ * access a synchronized counter.
+ *
+ */
+void octeon_init_cvmcount(void)
+{
+ unsigned long flags;
+ unsigned loops = 2;
+
+ /* Clobber loops so GCC will not unroll the following while loop. */
+ asm("" : "+r" (loops));
+
+ local_irq_save(flags);
+ /*
+ * Loop several times so we are executing from the cache,
+ * which should give more deterministic timing.
+ */
+ while (loops--)
+ write_c0_cvmcount(cvmx_read_csr(CVMX_IPD_CLK_COUNT));
+ local_irq_restore(flags);
+}
+
+static cycle_t octeon_cvmcount_read(void)
+{
+ return read_c0_cvmcount();
+}
+
+static struct clocksource clocksource_mips = {
+ .name = "OCTEON_CVMCOUNT",
+ .read = octeon_cvmcount_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init plat_time_init(void)
+{
+ clocksource_mips.rating = 300;
+ clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
+ clocksource_register(&clocksource_mips);
+}
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
new file mode 100644
index 000000000000..01b1ef94b361
--- /dev/null
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -0,0 +1,32 @@
+/*
+ * 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) 2000 Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001 Ralf Baechle <ralf@gnu.org>
+ * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ * IP32 changes by Ilya.
+ * Cavium Networks: Create new dma setup for Cavium Networks Octeon based on
+ * the kernels original.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+
+#include <dma-coherence.h>
+
+dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
+{
+ /* Without PCI/PCIe this function can be called for Octeon internal
+ devices such as USB. These devices all support 64bit addressing */
+ mb();
+ return virt_to_phys(ptr);
+}
+
+void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+{
+ /* Without PCI/PCIe this function can be called for Octeon internal
+ * devices such as USB. These devices all support 64bit addressing */
+ return;
+}
diff --git a/arch/mips/cavium-octeon/executive/Makefile b/arch/mips/cavium-octeon/executive/Makefile
new file mode 100644
index 000000000000..80d6cb26766b
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Cavium Octeon specific kernel interface routines
+# under Linux.
+#
+# 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) 2005-2008 Cavium Networks
+#
+
+obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
+
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
new file mode 100644
index 000000000000..4f5a08b37ccd
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
@@ -0,0 +1,586 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * Simple allocate only memory allocator. Used to allocate memory at
+ * application start time.
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-spinlock.h>
+#include <asm/octeon/cvmx-bootmem.h>
+
+/*#define DEBUG */
+
+
+static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
+
+/* See header file for descriptions of functions */
+
+/*
+ * Wrapper functions are provided for reading/writing the size and
+ * next block values as these may not be directly addressible (in 32
+ * bit applications, for instance.) Offsets of data elements in
+ * bootmem list, must match cvmx_bootmem_block_header_t.
+ */
+#define NEXT_OFFSET 0
+#define SIZE_OFFSET 8
+
+static void cvmx_bootmem_phy_set_size(uint64_t addr, uint64_t size)
+{
+ cvmx_write64_uint64((addr + SIZE_OFFSET) | (1ull << 63), size);
+}
+
+static void cvmx_bootmem_phy_set_next(uint64_t addr, uint64_t next)
+{
+ cvmx_write64_uint64((addr + NEXT_OFFSET) | (1ull << 63), next);
+}
+
+static uint64_t cvmx_bootmem_phy_get_size(uint64_t addr)
+{
+ return cvmx_read64_uint64((addr + SIZE_OFFSET) | (1ull << 63));
+}
+
+static uint64_t cvmx_bootmem_phy_get_next(uint64_t addr)
+{
+ return cvmx_read64_uint64((addr + NEXT_OFFSET) | (1ull << 63));
+}
+
+void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
+ uint64_t min_addr, uint64_t max_addr)
+{
+ int64_t address;
+ address =
+ cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment, 0);
+
+ if (address > 0)
+ return cvmx_phys_to_ptr(address);
+ else
+ return NULL;
+}
+
+void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address,
+ uint64_t alignment)
+{
+ return cvmx_bootmem_alloc_range(size, alignment, address,
+ address + size);
+}
+
+void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment)
+{
+ return cvmx_bootmem_alloc_range(size, alignment, 0, 0);
+}
+
+int cvmx_bootmem_free_named(char *name)
+{
+ return cvmx_bootmem_phy_named_block_free(name, 0);
+}
+
+struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name)
+{
+ return cvmx_bootmem_phy_named_block_find(name, 0);
+}
+
+void cvmx_bootmem_lock(void)
+{
+ cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+}
+
+void cvmx_bootmem_unlock(void)
+{
+ cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+}
+
+int cvmx_bootmem_init(void *mem_desc_ptr)
+{
+ /* Here we set the global pointer to the bootmem descriptor
+ * block. This pointer will be used directly, so we will set
+ * it up to be directly usable by the application. It is set
+ * up as follows for the various runtime/ABI combinations:
+ *
+ * Linux 64 bit: Set XKPHYS bit
+ * Linux 32 bit: use mmap to create mapping, use virtual address
+ * CVMX 64 bit: use physical address directly
+ * CVMX 32 bit: use physical address directly
+ *
+ * Note that the CVMX environment assumes the use of 1-1 TLB
+ * mappings so that the physical addresses can be used
+ * directly
+ */
+ if (!cvmx_bootmem_desc) {
+#if defined(CVMX_ABI_64)
+ /* Set XKPHYS bit */
+ cvmx_bootmem_desc = cvmx_phys_to_ptr(CAST64(mem_desc_ptr));
+#else
+ cvmx_bootmem_desc = (struct cvmx_bootmem_desc *) mem_desc_ptr;
+#endif
+ }
+
+ return 0;
+}
+
+/*
+ * The cvmx_bootmem_phy* functions below return 64 bit physical
+ * addresses, and expose more features that the cvmx_bootmem_functions
+ * above. These are required for full memory space access in 32 bit
+ * applications, as well as for using some advance features. Most
+ * applications should not need to use these.
+ */
+
+int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
+ uint64_t address_max, uint64_t alignment,
+ uint32_t flags)
+{
+
+ uint64_t head_addr;
+ uint64_t ent_addr;
+ /* points to previous list entry, NULL current entry is head of list */
+ uint64_t prev_addr = 0;
+ uint64_t new_ent_addr = 0;
+ uint64_t desired_min_addr;
+
+#ifdef DEBUG
+ cvmx_dprintf("cvmx_bootmem_phy_alloc: req_size: 0x%llx, "
+ "min_addr: 0x%llx, max_addr: 0x%llx, align: 0x%llx\n",
+ (unsigned long long)req_size,
+ (unsigned long long)address_min,
+ (unsigned long long)address_max,
+ (unsigned long long)alignment);
+#endif
+
+ if (cvmx_bootmem_desc->major_version > 3) {
+ cvmx_dprintf("ERROR: Incompatible bootmem descriptor "
+ "version: %d.%d at addr: %p\n",
+ (int)cvmx_bootmem_desc->major_version,
+ (int)cvmx_bootmem_desc->minor_version,
+ cvmx_bootmem_desc);
+ goto error_out;
+ }
+
+ /*
+ * Do a variety of checks to validate the arguments. The
+ * allocator code will later assume that these checks have
+ * been made. We validate that the requested constraints are
+ * not self-contradictory before we look through the list of
+ * available memory.
+ */
+
+ /* 0 is not a valid req_size for this allocator */
+ if (!req_size)
+ goto error_out;
+
+ /* Round req_size up to mult of minimum alignment bytes */
+ req_size = (req_size + (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1)) &
+ ~(CVMX_BOOTMEM_ALIGNMENT_SIZE - 1);
+
+ /*
+ * Convert !0 address_min and 0 address_max to special case of
+ * range that specifies an exact memory block to allocate. Do
+ * this before other checks and adjustments so that this
+ * tranformation will be validated.
+ */
+ if (address_min && !address_max)
+ address_max = address_min + req_size;
+ else if (!address_min && !address_max)
+ address_max = ~0ull; /* If no limits given, use max limits */
+
+
+ /*
+ * Enforce minimum alignment (this also keeps the minimum free block
+ * req_size the same as the alignment req_size.
+ */
+ if (alignment < CVMX_BOOTMEM_ALIGNMENT_SIZE)
+ alignment = CVMX_BOOTMEM_ALIGNMENT_SIZE;
+
+ /*
+ * Adjust address minimum based on requested alignment (round
+ * up to meet alignment). Do this here so we can reject
+ * impossible requests up front. (NOP for address_min == 0)
+ */
+ if (alignment)
+ address_min = __ALIGN_MASK(address_min, (alignment - 1));
+
+ /*
+ * Reject inconsistent args. We have adjusted these, so this
+ * may fail due to our internal changes even if this check
+ * would pass for the values the user supplied.
+ */
+ if (req_size > address_max - address_min)
+ goto error_out;
+
+ /* Walk through the list entries - first fit found is returned */
+
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_lock();
+ head_addr = cvmx_bootmem_desc->head_addr;
+ ent_addr = head_addr;
+ for (; ent_addr;
+ prev_addr = ent_addr,
+ ent_addr = cvmx_bootmem_phy_get_next(ent_addr)) {
+ uint64_t usable_base, usable_max;
+ uint64_t ent_size = cvmx_bootmem_phy_get_size(ent_addr);
+
+ if (cvmx_bootmem_phy_get_next(ent_addr)
+ && ent_addr > cvmx_bootmem_phy_get_next(ent_addr)) {
+ cvmx_dprintf("Internal bootmem_alloc() error: ent: "
+ "0x%llx, next: 0x%llx\n",
+ (unsigned long long)ent_addr,
+ (unsigned long long)
+ cvmx_bootmem_phy_get_next(ent_addr));
+ goto error_out;
+ }
+
+ /*
+ * Determine if this is an entry that can satisify the
+ * request Check to make sure entry is large enough to
+ * satisfy request.
+ */
+ usable_base =
+ __ALIGN_MASK(max(address_min, ent_addr), alignment - 1);
+ usable_max = min(address_max, ent_addr + ent_size);
+ /*
+ * We should be able to allocate block at address
+ * usable_base.
+ */
+
+ desired_min_addr = usable_base;
+ /*
+ * Determine if request can be satisfied from the
+ * current entry.
+ */
+ if (!((ent_addr + ent_size) > usable_base
+ && ent_addr < address_max
+ && req_size <= usable_max - usable_base))
+ continue;
+ /*
+ * We have found an entry that has room to satisfy the
+ * request, so allocate it from this entry. If end
+ * CVMX_BOOTMEM_FLAG_END_ALLOC set, then allocate from
+ * the end of this block rather than the beginning.
+ */
+ if (flags & CVMX_BOOTMEM_FLAG_END_ALLOC) {
+ desired_min_addr = usable_max - req_size;
+ /*
+ * Align desired address down to required
+ * alignment.
+ */
+ desired_min_addr &= ~(alignment - 1);
+ }
+
+ /* Match at start of entry */
+ if (desired_min_addr == ent_addr) {
+ if (req_size < ent_size) {
+ /*
+ * big enough to create a new block
+ * from top portion of block.
+ */
+ new_ent_addr = ent_addr + req_size;
+ cvmx_bootmem_phy_set_next(new_ent_addr,
+ cvmx_bootmem_phy_get_next(ent_addr));
+ cvmx_bootmem_phy_set_size(new_ent_addr,
+ ent_size -
+ req_size);
+
+ /*
+ * Adjust next pointer as following
+ * code uses this.
+ */
+ cvmx_bootmem_phy_set_next(ent_addr,
+ new_ent_addr);
+ }
+
+ /*
+ * adjust prev ptr or head to remove this
+ * entry from list.
+ */
+ if (prev_addr)
+ cvmx_bootmem_phy_set_next(prev_addr,
+ cvmx_bootmem_phy_get_next(ent_addr));
+ else
+ /*
+ * head of list being returned, so
+ * update head ptr.
+ */
+ cvmx_bootmem_desc->head_addr =
+ cvmx_bootmem_phy_get_next(ent_addr);
+
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_unlock();
+ return desired_min_addr;
+ }
+ /*
+ * block returned doesn't start at beginning of entry,
+ * so we know that we will be splitting a block off
+ * the front of this one. Create a new block from the
+ * beginning, add to list, and go to top of loop
+ * again.
+ *
+ * create new block from high portion of
+ * block, so that top block starts at desired
+ * addr.
+ */
+ new_ent_addr = desired_min_addr;
+ cvmx_bootmem_phy_set_next(new_ent_addr,
+ cvmx_bootmem_phy_get_next
+ (ent_addr));
+ cvmx_bootmem_phy_set_size(new_ent_addr,
+ cvmx_bootmem_phy_get_size
+ (ent_addr) -
+ (desired_min_addr -
+ ent_addr));
+ cvmx_bootmem_phy_set_size(ent_addr,
+ desired_min_addr - ent_addr);
+ cvmx_bootmem_phy_set_next(ent_addr, new_ent_addr);
+ /* Loop again to handle actual alloc from new block */
+ }
+error_out:
+ /* We didn't find anything, so return error */
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_unlock();
+ return -1;
+}
+
+int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags)
+{
+ uint64_t cur_addr;
+ uint64_t prev_addr = 0; /* zero is invalid */
+ int retval = 0;
+
+#ifdef DEBUG
+ cvmx_dprintf("__cvmx_bootmem_phy_free addr: 0x%llx, size: 0x%llx\n",
+ (unsigned long long)phy_addr, (unsigned long long)size);
+#endif
+ if (cvmx_bootmem_desc->major_version > 3) {
+ cvmx_dprintf("ERROR: Incompatible bootmem descriptor "
+ "version: %d.%d at addr: %p\n",
+ (int)cvmx_bootmem_desc->major_version,
+ (int)cvmx_bootmem_desc->minor_version,
+ cvmx_bootmem_desc);
+ return 0;
+ }
+
+ /* 0 is not a valid size for this allocator */
+ if (!size)
+ return 0;
+
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_lock();
+ cur_addr = cvmx_bootmem_desc->head_addr;
+ if (cur_addr == 0 || phy_addr < cur_addr) {
+ /* add at front of list - special case with changing head ptr */
+ if (cur_addr && phy_addr + size > cur_addr)
+ goto bootmem_free_done; /* error, overlapping section */
+ else if (phy_addr + size == cur_addr) {
+ /* Add to front of existing first block */
+ cvmx_bootmem_phy_set_next(phy_addr,
+ cvmx_bootmem_phy_get_next
+ (cur_addr));
+ cvmx_bootmem_phy_set_size(phy_addr,
+ cvmx_bootmem_phy_get_size
+ (cur_addr) + size);
+ cvmx_bootmem_desc->head_addr = phy_addr;
+
+ } else {
+ /* New block before first block. OK if cur_addr is 0 */
+ cvmx_bootmem_phy_set_next(phy_addr, cur_addr);
+ cvmx_bootmem_phy_set_size(phy_addr, size);
+ cvmx_bootmem_desc->head_addr = phy_addr;
+ }
+ retval = 1;
+ goto bootmem_free_done;
+ }
+
+ /* Find place in list to add block */
+ while (cur_addr && phy_addr > cur_addr) {
+ prev_addr = cur_addr;
+ cur_addr = cvmx_bootmem_phy_get_next(cur_addr);
+ }
+
+ if (!cur_addr) {
+ /*
+ * We have reached the end of the list, add on to end,
+ * checking to see if we need to combine with last
+ * block
+ */
+ if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) ==
+ phy_addr) {
+ cvmx_bootmem_phy_set_size(prev_addr,
+ cvmx_bootmem_phy_get_size
+ (prev_addr) + size);
+ } else {
+ cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
+ cvmx_bootmem_phy_set_size(phy_addr, size);
+ cvmx_bootmem_phy_set_next(phy_addr, 0);
+ }
+ retval = 1;
+ goto bootmem_free_done;
+ } else {
+ /*
+ * insert between prev and cur nodes, checking for
+ * merge with either/both.
+ */
+ if (prev_addr + cvmx_bootmem_phy_get_size(prev_addr) ==
+ phy_addr) {
+ /* Merge with previous */
+ cvmx_bootmem_phy_set_size(prev_addr,
+ cvmx_bootmem_phy_get_size
+ (prev_addr) + size);
+ if (phy_addr + size == cur_addr) {
+ /* Also merge with current */
+ cvmx_bootmem_phy_set_size(prev_addr,
+ cvmx_bootmem_phy_get_size(cur_addr) +
+ cvmx_bootmem_phy_get_size(prev_addr));
+ cvmx_bootmem_phy_set_next(prev_addr,
+ cvmx_bootmem_phy_get_next(cur_addr));
+ }
+ retval = 1;
+ goto bootmem_free_done;
+ } else if (phy_addr + size == cur_addr) {
+ /* Merge with current */
+ cvmx_bootmem_phy_set_size(phy_addr,
+ cvmx_bootmem_phy_get_size
+ (cur_addr) + size);
+ cvmx_bootmem_phy_set_next(phy_addr,
+ cvmx_bootmem_phy_get_next
+ (cur_addr));
+ cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
+ retval = 1;
+ goto bootmem_free_done;
+ }
+
+ /* It is a standalone block, add in between prev and cur */
+ cvmx_bootmem_phy_set_size(phy_addr, size);
+ cvmx_bootmem_phy_set_next(phy_addr, cur_addr);
+ cvmx_bootmem_phy_set_next(prev_addr, phy_addr);
+
+ }
+ retval = 1;
+
+bootmem_free_done:
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_unlock();
+ return retval;
+
+}
+
+struct cvmx_bootmem_named_block_desc *
+ cvmx_bootmem_phy_named_block_find(char *name, uint32_t flags)
+{
+ unsigned int i;
+ struct cvmx_bootmem_named_block_desc *named_block_array_ptr;
+
+#ifdef DEBUG
+ cvmx_dprintf("cvmx_bootmem_phy_named_block_find: %s\n", name);
+#endif
+ /*
+ * Lock the structure to make sure that it is not being
+ * changed while we are examining it.
+ */
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_lock();
+
+ /* Use XKPHYS for 64 bit linux */
+ named_block_array_ptr = (struct cvmx_bootmem_named_block_desc *)
+ cvmx_phys_to_ptr(cvmx_bootmem_desc->named_block_array_addr);
+
+#ifdef DEBUG
+ cvmx_dprintf
+ ("cvmx_bootmem_phy_named_block_find: named_block_array_ptr: %p\n",
+ named_block_array_ptr);
+#endif
+ if (cvmx_bootmem_desc->major_version == 3) {
+ for (i = 0;
+ i < cvmx_bootmem_desc->named_block_num_blocks; i++) {
+ if ((name && named_block_array_ptr[i].size
+ && !strncmp(name, named_block_array_ptr[i].name,
+ cvmx_bootmem_desc->named_block_name_len
+ - 1))
+ || (!name && !named_block_array_ptr[i].size)) {
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_unlock();
+
+ return &(named_block_array_ptr[i]);
+ }
+ }
+ } else {
+ cvmx_dprintf("ERROR: Incompatible bootmem descriptor "
+ "version: %d.%d at addr: %p\n",
+ (int)cvmx_bootmem_desc->major_version,
+ (int)cvmx_bootmem_desc->minor_version,
+ cvmx_bootmem_desc);
+ }
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_bootmem_unlock();
+
+ return NULL;
+}
+
+int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags)
+{
+ struct cvmx_bootmem_named_block_desc *named_block_ptr;
+
+ if (cvmx_bootmem_desc->major_version != 3) {
+ cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: "
+ "%d.%d at addr: %p\n",
+ (int)cvmx_bootmem_desc->major_version,
+ (int)cvmx_bootmem_desc->minor_version,
+ cvmx_bootmem_desc);
+ return 0;
+ }
+#ifdef DEBUG
+ cvmx_dprintf("cvmx_bootmem_phy_named_block_free: %s\n", name);
+#endif
+
+ /*
+ * Take lock here, as name lookup/block free/name free need to
+ * be atomic.
+ */
+ cvmx_bootmem_lock();
+
+ named_block_ptr =
+ cvmx_bootmem_phy_named_block_find(name,
+ CVMX_BOOTMEM_FLAG_NO_LOCKING);
+ if (named_block_ptr) {
+#ifdef DEBUG
+ cvmx_dprintf("cvmx_bootmem_phy_named_block_free: "
+ "%s, base: 0x%llx, size: 0x%llx\n",
+ name,
+ (unsigned long long)named_block_ptr->base_addr,
+ (unsigned long long)named_block_ptr->size);
+#endif
+ __cvmx_bootmem_phy_free(named_block_ptr->base_addr,
+ named_block_ptr->size,
+ CVMX_BOOTMEM_FLAG_NO_LOCKING);
+ named_block_ptr->size = 0;
+ /* Set size to zero to indicate block not used. */
+ }
+
+ cvmx_bootmem_unlock();
+ return named_block_ptr != NULL; /* 0 on failure, 1 on success */
+}
diff --git a/arch/mips/cavium-octeon/executive/cvmx-l2c.c b/arch/mips/cavium-octeon/executive/cvmx-l2c.c
new file mode 100644
index 000000000000..6abe56f1e097
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/cvmx-l2c.c
@@ -0,0 +1,734 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * Implementation of the Level 2 Cache (L2C) control, measurement, and
+ * debugging facilities.
+ */
+
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-l2c.h>
+#include <asm/octeon/cvmx-spinlock.h>
+
+/*
+ * This spinlock is used internally to ensure that only one core is
+ * performing certain L2 operations at a time.
+ *
+ * NOTE: This only protects calls from within a single application -
+ * if multiple applications or operating systems are running, then it
+ * is up to the user program to coordinate between them.
+ */
+static cvmx_spinlock_t cvmx_l2c_spinlock;
+
+static inline int l2_size_half(void)
+{
+ uint64_t val = cvmx_read_csr(CVMX_L2D_FUS3);
+ return !!(val & (1ull << 34));
+}
+
+int cvmx_l2c_get_core_way_partition(uint32_t core)
+{
+ uint32_t field;
+
+ /* Validate the core number */
+ if (core >= cvmx_octeon_num_cores())
+ return -1;
+
+ /*
+ * Use the lower two bits of the coreNumber to determine the
+ * bit offset of the UMSK[] field in the L2C_SPAR register.
+ */
+ field = (core & 0x3) * 8;
+
+ /*
+ * Return the UMSK[] field from the appropriate L2C_SPAR
+ * register based on the coreNumber.
+ */
+
+ switch (core & 0xC) {
+ case 0x0:
+ return (cvmx_read_csr(CVMX_L2C_SPAR0) & (0xFF << field)) >>
+ field;
+ case 0x4:
+ return (cvmx_read_csr(CVMX_L2C_SPAR1) & (0xFF << field)) >>
+ field;
+ case 0x8:
+ return (cvmx_read_csr(CVMX_L2C_SPAR2) & (0xFF << field)) >>
+ field;
+ case 0xC:
+ return (cvmx_read_csr(CVMX_L2C_SPAR3) & (0xFF << field)) >>
+ field;
+ }
+ return 0;
+}
+
+int cvmx_l2c_set_core_way_partition(uint32_t core, uint32_t mask)
+{
+ uint32_t field;
+ uint32_t valid_mask;
+
+ valid_mask = (0x1 << cvmx_l2c_get_num_assoc()) - 1;
+
+ mask &= valid_mask;
+
+ /* A UMSK setting which blocks all L2C Ways is an error. */
+ if (mask == valid_mask)
+ return -1;
+
+ /* Validate the core number */
+ if (core >= cvmx_octeon_num_cores())
+ return -1;
+
+ /* Check to make sure current mask & new mask don't block all ways */
+ if (((mask | cvmx_l2c_get_core_way_partition(core)) & valid_mask) ==
+ valid_mask)
+ return -1;
+
+ /* Use the lower two bits of core to determine the bit offset of the
+ * UMSK[] field in the L2C_SPAR register.
+ */
+ field = (core & 0x3) * 8;
+
+ /* Assign the new mask setting to the UMSK[] field in the appropriate
+ * L2C_SPAR register based on the core_num.
+ *
+ */
+ switch (core & 0xC) {
+ case 0x0:
+ cvmx_write_csr(CVMX_L2C_SPAR0,
+ (cvmx_read_csr(CVMX_L2C_SPAR0) &
+ ~(0xFF << field)) | mask << field);
+ break;
+ case 0x4:
+ cvmx_write_csr(CVMX_L2C_SPAR1,
+ (cvmx_read_csr(CVMX_L2C_SPAR1) &
+ ~(0xFF << field)) | mask << field);
+ break;
+ case 0x8:
+ cvmx_write_csr(CVMX_L2C_SPAR2,
+ (cvmx_read_csr(CVMX_L2C_SPAR2) &
+ ~(0xFF << field)) | mask << field);
+ break;
+ case 0xC:
+ cvmx_write_csr(CVMX_L2C_SPAR3,
+ (cvmx_read_csr(CVMX_L2C_SPAR3) &
+ ~(0xFF << field)) | mask << field);
+ break;
+ }
+ return 0;
+}
+
+int cvmx_l2c_set_hw_way_partition(uint32_t mask)
+{
+ uint32_t valid_mask;
+
+ valid_mask = 0xff;
+
+ if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN38XX)) {
+ if (l2_size_half())
+ valid_mask = 0xf;
+ } else if (l2_size_half())
+ valid_mask = 0x3;
+
+ mask &= valid_mask;
+
+ /* A UMSK setting which blocks all L2C Ways is an error. */
+ if (mask == valid_mask)
+ return -1;
+ /* Check to make sure current mask & new mask don't block all ways */
+ if (((mask | cvmx_l2c_get_hw_way_partition()) & valid_mask) ==
+ valid_mask)
+ return -1;
+
+ cvmx_write_csr(CVMX_L2C_SPAR4,
+ (cvmx_read_csr(CVMX_L2C_SPAR4) & ~0xFF) | mask);
+ return 0;
+}
+
+int cvmx_l2c_get_hw_way_partition(void)
+{
+ return cvmx_read_csr(CVMX_L2C_SPAR4) & (0xFF);
+}
+
+void cvmx_l2c_config_perf(uint32_t counter, enum cvmx_l2c_event event,
+ uint32_t clear_on_read)
+{
+ union cvmx_l2c_pfctl pfctl;
+
+ pfctl.u64 = cvmx_read_csr(CVMX_L2C_PFCTL);
+
+ switch (counter) {
+ case 0:
+ pfctl.s.cnt0sel = event;
+ pfctl.s.cnt0ena = 1;
+ if (!cvmx_octeon_is_pass1())
+ pfctl.s.cnt0rdclr = clear_on_read;
+ break;
+ case 1:
+ pfctl.s.cnt1sel = event;
+ pfctl.s.cnt1ena = 1;
+ if (!cvmx_octeon_is_pass1())
+ pfctl.s.cnt1rdclr = clear_on_read;
+ break;
+ case 2:
+ pfctl.s.cnt2sel = event;
+ pfctl.s.cnt2ena = 1;
+ if (!cvmx_octeon_is_pass1())
+ pfctl.s.cnt2rdclr = clear_on_read;
+ break;
+ case 3:
+ default:
+ pfctl.s.cnt3sel = event;
+ pfctl.s.cnt3ena = 1;
+ if (!cvmx_octeon_is_pass1())
+ pfctl.s.cnt3rdclr = clear_on_read;
+ break;
+ }
+
+ cvmx_write_csr(CVMX_L2C_PFCTL, pfctl.u64);
+}
+
+uint64_t cvmx_l2c_read_perf(uint32_t counter)
+{
+ switch (counter) {
+ case 0:
+ return cvmx_read_csr(CVMX_L2C_PFC0);
+ case 1:
+ return cvmx_read_csr(CVMX_L2C_PFC1);
+ case 2:
+ return cvmx_read_csr(CVMX_L2C_PFC2);
+ case 3:
+ default:
+ return cvmx_read_csr(CVMX_L2C_PFC3);
+ }
+}
+
+/**
+ * @INTERNAL
+ * Helper function use to fault in cache lines for L2 cache locking
+ *
+ * @addr: Address of base of memory region to read into L2 cache
+ * @len: Length (in bytes) of region to fault in
+ */
+static void fault_in(uint64_t addr, int len)
+{
+ volatile char *ptr;
+ volatile char dummy;
+ /*
+ * Adjust addr and length so we get all cache lines even for
+ * small ranges spanning two cache lines
+ */
+ len += addr & CVMX_CACHE_LINE_MASK;
+ addr &= ~CVMX_CACHE_LINE_MASK;
+ ptr = (volatile char *)cvmx_phys_to_ptr(addr);
+ /*
+ * Invalidate L1 cache to make sure all loads result in data
+ * being in L2.
+ */
+ CVMX_DCACHE_INVALIDATE;
+ while (len > 0) {
+ dummy += *ptr;
+ len -= CVMX_CACHE_LINE_SIZE;
+ ptr += CVMX_CACHE_LINE_SIZE;
+ }
+}
+
+int cvmx_l2c_lock_line(uint64_t addr)
+{
+ int retval = 0;
+ union cvmx_l2c_dbg l2cdbg;
+ union cvmx_l2c_lckbase lckbase;
+ union cvmx_l2c_lckoff lckoff;
+ union cvmx_l2t_err l2t_err;
+ l2cdbg.u64 = 0;
+ lckbase.u64 = 0;
+ lckoff.u64 = 0;
+
+ cvmx_spinlock_lock(&cvmx_l2c_spinlock);
+
+ /* Clear l2t error bits if set */
+ l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+ l2t_err.s.lckerr = 1;
+ l2t_err.s.lckerr2 = 1;
+ cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64);
+
+ addr &= ~CVMX_CACHE_LINE_MASK;
+
+ /* Set this core as debug core */
+ l2cdbg.s.ppnum = cvmx_get_core_num();
+ CVMX_SYNC;
+ cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+ cvmx_read_csr(CVMX_L2C_DBG);
+
+ lckoff.s.lck_offset = 0; /* Only lock 1 line at a time */
+ cvmx_write_csr(CVMX_L2C_LCKOFF, lckoff.u64);
+ cvmx_read_csr(CVMX_L2C_LCKOFF);
+
+ if (((union cvmx_l2c_cfg) (cvmx_read_csr(CVMX_L2C_CFG))).s.idxalias) {
+ int alias_shift =
+ CVMX_L2C_IDX_ADDR_SHIFT + 2 * CVMX_L2_SET_BITS - 1;
+ uint64_t addr_tmp =
+ addr ^ (addr & ((1 << alias_shift) - 1)) >>
+ CVMX_L2_SET_BITS;
+ lckbase.s.lck_base = addr_tmp >> 7;
+ } else {
+ lckbase.s.lck_base = addr >> 7;
+ }
+
+ lckbase.s.lck_ena = 1;
+ cvmx_write_csr(CVMX_L2C_LCKBASE, lckbase.u64);
+ cvmx_read_csr(CVMX_L2C_LCKBASE); /* Make sure it gets there */
+
+ fault_in(addr, CVMX_CACHE_LINE_SIZE);
+
+ lckbase.s.lck_ena = 0;
+ cvmx_write_csr(CVMX_L2C_LCKBASE, lckbase.u64);
+ cvmx_read_csr(CVMX_L2C_LCKBASE); /* Make sure it gets there */
+
+ /* Stop being debug core */
+ cvmx_write_csr(CVMX_L2C_DBG, 0);
+ cvmx_read_csr(CVMX_L2C_DBG);
+
+ l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR);
+ if (l2t_err.s.lckerr || l2t_err.s.lckerr2)
+ retval = 1; /* We were unable to lock the line */
+
+ cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+
+ return retval;
+}
+
+int cvmx_l2c_lock_mem_region(uint64_t start, uint64_t len)
+{
+ int retval = 0;
+
+ /* Round start/end to cache line boundaries */
+ len += start & CVMX_CACHE_LINE_MASK;
+ start &= ~CVMX_CACHE_LINE_MASK;
+ len = (len + CVMX_CACHE_LINE_MASK) & ~CVMX_CACHE_LINE_MASK;
+
+ while (len) {
+ retval += cvmx_l2c_lock_line(start);
+ start += CVMX_CACHE_LINE_SIZE;
+ len -= CVMX_CACHE_LINE_SIZE;
+ }
+
+ return retval;
+}
+
+void cvmx_l2c_flush(void)
+{
+ uint64_t assoc, set;
+ uint64_t n_assoc, n_set;
+ union cvmx_l2c_dbg l2cdbg;
+
+ cvmx_spinlock_lock(&cvmx_l2c_spinlock);
+
+ l2cdbg.u64 = 0;
+ if (!OCTEON_IS_MODEL(OCTEON_CN30XX))
+ l2cdbg.s.ppnum = cvmx_get_core_num();
+ l2cdbg.s.finv = 1;
+ n_set = CVMX_L2_SETS;
+ n_assoc = l2_size_half() ? (CVMX_L2_ASSOC / 2) : CVMX_L2_ASSOC;
+ for (set = 0; set < n_set; set++) {
+ for (assoc = 0; assoc < n_assoc; assoc++) {
+ l2cdbg.s.set = assoc;
+ /* Enter debug mode, and make sure all other
+ ** writes complete before we enter debug
+ ** mode */
+ CVMX_SYNCW;
+ cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+ cvmx_read_csr(CVMX_L2C_DBG);
+
+ CVMX_PREPARE_FOR_STORE(CVMX_ADD_SEG
+ (CVMX_MIPS_SPACE_XKPHYS,
+ set * CVMX_CACHE_LINE_SIZE), 0);
+ CVMX_SYNCW; /* Push STF out to L2 */
+ /* Exit debug mode */
+ CVMX_SYNC;
+ cvmx_write_csr(CVMX_L2C_DBG, 0);
+ cvmx_read_csr(CVMX_L2C_DBG);
+ }
+ }
+
+ cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+}
+
+int cvmx_l2c_unlock_line(uint64_t address)
+{
+ int assoc;
+ union cvmx_l2c_tag tag;
+ union cvmx_l2c_dbg l2cdbg;
+ uint32_t tag_addr;
+
+ uint32_t index = cvmx_l2c_address_to_index(address);
+
+ cvmx_spinlock_lock(&cvmx_l2c_spinlock);
+ /* Compute portion of address that is stored in tag */
+ tag_addr =
+ ((address >> CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) &
+ ((1 << CVMX_L2C_TAG_ADDR_ALIAS_SHIFT) - 1));
+ for (assoc = 0; assoc < CVMX_L2_ASSOC; assoc++) {
+ tag = cvmx_get_l2c_tag(assoc, index);
+
+ if (tag.s.V && (tag.s.addr == tag_addr)) {
+ l2cdbg.u64 = 0;
+ l2cdbg.s.ppnum = cvmx_get_core_num();
+ l2cdbg.s.set = assoc;
+ l2cdbg.s.finv = 1;
+
+ CVMX_SYNC;
+ /* Enter debug mode */
+ cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+ cvmx_read_csr(CVMX_L2C_DBG);
+
+ CVMX_PREPARE_FOR_STORE(CVMX_ADD_SEG
+ (CVMX_MIPS_SPACE_XKPHYS,
+ address), 0);
+ CVMX_SYNC;
+ /* Exit debug mode */
+ cvmx_write_csr(CVMX_L2C_DBG, 0);
+ cvmx_read_csr(CVMX_L2C_DBG);
+ cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+ return tag.s.L;
+ }
+ }
+ cvmx_spinlock_unlock(&cvmx_l2c_spinlock);
+ return 0;
+}
+
+int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len)
+{
+ int num_unlocked = 0;
+ /* Round start/end to cache line boundaries */
+ len += start & CVMX_CACHE_LINE_MASK;
+ start &= ~CVMX_CACHE_LINE_MASK;
+ len = (len + CVMX_CACHE_LINE_MASK) & ~CVMX_CACHE_LINE_MASK;
+ while (len > 0) {
+ num_unlocked += cvmx_l2c_unlock_line(start);
+ start += CVMX_CACHE_LINE_SIZE;
+ len -= CVMX_CACHE_LINE_SIZE;
+ }
+
+ return num_unlocked;
+}
+
+/*
+ * Internal l2c tag types. These are converted to a generic structure
+ * that can be used on all chips.
+ */
+union __cvmx_l2c_tag {
+ uint64_t u64;
+ struct cvmx_l2c_tag_cn50xx {
+ uint64_t reserved:40;
+ uint64_t V:1; /* Line valid */
+ uint64_t D:1; /* Line dirty */
+ uint64_t L:1; /* Line locked */
+ uint64_t U:1; /* Use, LRU eviction */
+ uint64_t addr:20; /* Phys mem addr (33..14) */
+ } cn50xx;
+ struct cvmx_l2c_tag_cn30xx {
+ uint64_t reserved:41;
+ uint64_t V:1; /* Line valid */
+ uint64_t D:1; /* Line dirty */
+ uint64_t L:1; /* Line locked */
+ uint64_t U:1; /* Use, LRU eviction */
+ uint64_t addr:19; /* Phys mem addr (33..15) */
+ } cn30xx;
+ struct cvmx_l2c_tag_cn31xx {
+ uint64_t reserved:42;
+ uint64_t V:1; /* Line valid */
+ uint64_t D:1; /* Line dirty */
+ uint64_t L:1; /* Line locked */
+ uint64_t U:1; /* Use, LRU eviction */
+ uint64_t addr:18; /* Phys mem addr (33..16) */
+ } cn31xx;
+ struct cvmx_l2c_tag_cn38xx {
+ uint64_t reserved:43;
+ uint64_t V:1; /* Line valid */
+ uint64_t D:1; /* Line dirty */
+ uint64_t L:1; /* Line locked */
+ uint64_t U:1; /* Use, LRU eviction */
+ uint64_t addr:17; /* Phys mem addr (33..17) */
+ } cn38xx;
+ struct cvmx_l2c_tag_cn58xx {
+ uint64_t reserved:44;
+ uint64_t V:1; /* Line valid */
+ uint64_t D:1; /* Line dirty */
+ uint64_t L:1; /* Line locked */
+ uint64_t U:1; /* Use, LRU eviction */
+ uint64_t addr:16; /* Phys mem addr (33..18) */
+ } cn58xx;
+ struct cvmx_l2c_tag_cn58xx cn56xx; /* 2048 sets */
+ struct cvmx_l2c_tag_cn31xx cn52xx; /* 512 sets */
+};
+
+/**
+ * @INTERNAL
+ * Function to read a L2C tag. This code make the current core
+ * the 'debug core' for the L2. This code must only be executed by
+ * 1 core at a time.
+ *
+ * @assoc: Association (way) of the tag to dump
+ * @index: Index of the cacheline
+ *
+ * Returns The Octeon model specific tag structure. This is
+ * translated by a wrapper function to a generic form that is
+ * easier for applications to use.
+ */
+static union __cvmx_l2c_tag __read_l2_tag(uint64_t assoc, uint64_t index)
+{
+
+ uint64_t debug_tag_addr = (((1ULL << 63) | (index << 7)) + 96);
+ uint64_t core = cvmx_get_core_num();
+ union __cvmx_l2c_tag tag_val;
+ uint64_t dbg_addr = CVMX_L2C_DBG;
+ unsigned long flags;
+
+ union cvmx_l2c_dbg debug_val;
+ debug_val.u64 = 0;
+ /*
+ * For low core count parts, the core number is always small enough
+ * to stay in the correct field and not set any reserved bits.
+ */
+ debug_val.s.ppnum = core;
+ debug_val.s.l2t = 1;
+ debug_val.s.set = assoc;
+ /*
+ * Make sure core is quiet (no prefetches, etc.) before
+ * entering debug mode.
+ */
+ CVMX_SYNC;
+ /* Flush L1 to make sure debug load misses L1 */
+ CVMX_DCACHE_INVALIDATE;
+
+ local_irq_save(flags);
+
+ /*
+ * The following must be done in assembly as when in debug
+ * mode all data loads from L2 return special debug data, not
+ * normal memory contents. Also, interrupts must be
+ * disabled, since if an interrupt occurs while in debug mode
+ * the ISR will get debug data from all its memory reads
+ * instead of the contents of memory
+ */
+
+ asm volatile (".set push \n"
+ " .set mips64 \n"
+ " .set noreorder \n"
+ /* Enter debug mode, wait for store */
+ " sd %[dbg_val], 0(%[dbg_addr]) \n"
+ " ld $0, 0(%[dbg_addr]) \n"
+ /* Read L2C tag data */
+ " ld %[tag_val], 0(%[tag_addr]) \n"
+ /* Exit debug mode, wait for store */
+ " sd $0, 0(%[dbg_addr]) \n"
+ " ld $0, 0(%[dbg_addr]) \n"
+ /* Invalidate dcache to discard debug data */
+ " cache 9, 0($0) \n"
+ " .set pop" :
+ [tag_val] "=r"(tag_val.u64) : [dbg_addr] "r"(dbg_addr),
+ [dbg_val] "r"(debug_val.u64),
+ [tag_addr] "r"(debug_tag_addr) : "memory");
+
+ local_irq_restore(flags);
+ return tag_val;
+
+}
+
+union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index)
+{
+ union __cvmx_l2c_tag tmp_tag;
+ union cvmx_l2c_tag tag;
+ tag.u64 = 0;
+
+ if ((int)association >= cvmx_l2c_get_num_assoc()) {
+ cvmx_dprintf
+ ("ERROR: cvmx_get_l2c_tag association out of range\n");
+ return tag;
+ }
+ if ((int)index >= cvmx_l2c_get_num_sets()) {
+ cvmx_dprintf("ERROR: cvmx_get_l2c_tag "
+ "index out of range (arg: %d, max: %d\n",
+ index, cvmx_l2c_get_num_sets());
+ return tag;
+ }
+ /* __read_l2_tag is intended for internal use only */
+ tmp_tag = __read_l2_tag(association, index);
+
+ /*
+ * Convert all tag structure types to generic version, as it
+ * can represent all models.
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN56XX)) {
+ tag.s.V = tmp_tag.cn58xx.V;
+ tag.s.D = tmp_tag.cn58xx.D;
+ tag.s.L = tmp_tag.cn58xx.L;
+ tag.s.U = tmp_tag.cn58xx.U;
+ tag.s.addr = tmp_tag.cn58xx.addr;
+ } else if (OCTEON_IS_MODEL(OCTEON_CN38XX)) {
+ tag.s.V = tmp_tag.cn38xx.V;
+ tag.s.D = tmp_tag.cn38xx.D;
+ tag.s.L = tmp_tag.cn38xx.L;
+ tag.s.U = tmp_tag.cn38xx.U;
+ tag.s.addr = tmp_tag.cn38xx.addr;
+ } else if (OCTEON_IS_MODEL(OCTEON_CN31XX)
+ || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
+ tag.s.V = tmp_tag.cn31xx.V;
+ tag.s.D = tmp_tag.cn31xx.D;
+ tag.s.L = tmp_tag.cn31xx.L;
+ tag.s.U = tmp_tag.cn31xx.U;
+ tag.s.addr = tmp_tag.cn31xx.addr;
+ } else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) {
+ tag.s.V = tmp_tag.cn30xx.V;
+ tag.s.D = tmp_tag.cn30xx.D;
+ tag.s.L = tmp_tag.cn30xx.L;
+ tag.s.U = tmp_tag.cn30xx.U;
+ tag.s.addr = tmp_tag.cn30xx.addr;
+ } else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) {
+ tag.s.V = tmp_tag.cn50xx.V;
+ tag.s.D = tmp_tag.cn50xx.D;
+ tag.s.L = tmp_tag.cn50xx.L;
+ tag.s.U = tmp_tag.cn50xx.U;
+ tag.s.addr = tmp_tag.cn50xx.addr;
+ } else {
+ cvmx_dprintf("Unsupported OCTEON Model in %s\n", __func__);
+ }
+
+ return tag;
+}
+
+uint32_t cvmx_l2c_address_to_index(uint64_t addr)
+{
+ uint64_t idx = addr >> CVMX_L2C_IDX_ADDR_SHIFT;
+ union cvmx_l2c_cfg l2c_cfg;
+ l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
+
+ if (l2c_cfg.s.idxalias) {
+ idx ^=
+ ((addr & CVMX_L2C_ALIAS_MASK) >>
+ CVMX_L2C_TAG_ADDR_ALIAS_SHIFT);
+ }
+ idx &= CVMX_L2C_IDX_MASK;
+ return idx;
+}
+
+int cvmx_l2c_get_cache_size_bytes(void)
+{
+ return cvmx_l2c_get_num_sets() * cvmx_l2c_get_num_assoc() *
+ CVMX_CACHE_LINE_SIZE;
+}
+
+/**
+ * Return log base 2 of the number of sets in the L2 cache
+ * Returns
+ */
+int cvmx_l2c_get_set_bits(void)
+{
+ int l2_set_bits;
+ if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
+ l2_set_bits = 11; /* 2048 sets */
+ else if (OCTEON_IS_MODEL(OCTEON_CN38XX))
+ l2_set_bits = 10; /* 1024 sets */
+ else if (OCTEON_IS_MODEL(OCTEON_CN31XX)
+ || OCTEON_IS_MODEL(OCTEON_CN52XX))
+ l2_set_bits = 9; /* 512 sets */
+ else if (OCTEON_IS_MODEL(OCTEON_CN30XX))
+ l2_set_bits = 8; /* 256 sets */
+ else if (OCTEON_IS_MODEL(OCTEON_CN50XX))
+ l2_set_bits = 7; /* 128 sets */
+ else {
+ cvmx_dprintf("Unsupported OCTEON Model in %s\n", __func__);
+ l2_set_bits = 11; /* 2048 sets */
+ }
+ return l2_set_bits;
+
+}
+
+/* Return the number of sets in the L2 Cache */
+int cvmx_l2c_get_num_sets(void)
+{
+ return 1 << cvmx_l2c_get_set_bits();
+}
+
+/* Return the number of associations in the L2 Cache */
+int cvmx_l2c_get_num_assoc(void)
+{
+ int l2_assoc;
+ if (OCTEON_IS_MODEL(OCTEON_CN56XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN52XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN58XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN50XX) || OCTEON_IS_MODEL(OCTEON_CN38XX))
+ l2_assoc = 8;
+ else if (OCTEON_IS_MODEL(OCTEON_CN31XX) ||
+ OCTEON_IS_MODEL(OCTEON_CN30XX))
+ l2_assoc = 4;
+ else {
+ cvmx_dprintf("Unsupported OCTEON Model in %s\n", __func__);
+ l2_assoc = 8;
+ }
+
+ /* Check to see if part of the cache is disabled */
+ if (cvmx_fuse_read(265))
+ l2_assoc = l2_assoc >> 2;
+ else if (cvmx_fuse_read(264))
+ l2_assoc = l2_assoc >> 1;
+
+ return l2_assoc;
+}
+
+/**
+ * Flush a line from the L2 cache
+ * This should only be called from one core at a time, as this routine
+ * sets the core to the 'debug' core in order to flush the line.
+ *
+ * @assoc: Association (or way) to flush
+ * @index: Index to flush
+ */
+void cvmx_l2c_flush_line(uint32_t assoc, uint32_t index)
+{
+ union cvmx_l2c_dbg l2cdbg;
+
+ l2cdbg.u64 = 0;
+ l2cdbg.s.ppnum = cvmx_get_core_num();
+ l2cdbg.s.finv = 1;
+
+ l2cdbg.s.set = assoc;
+ /*
+ * Enter debug mode, and make sure all other writes complete
+ * before we enter debug mode.
+ */
+ asm volatile ("sync" : : : "memory");
+ cvmx_write_csr(CVMX_L2C_DBG, l2cdbg.u64);
+ cvmx_read_csr(CVMX_L2C_DBG);
+
+ CVMX_PREPARE_FOR_STORE(((1ULL << 63) + (index) * 128), 0);
+ /* Exit debug mode */
+ asm volatile ("sync" : : : "memory");
+ cvmx_write_csr(CVMX_L2C_DBG, 0);
+ cvmx_read_csr(CVMX_L2C_DBG);
+}
diff --git a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
new file mode 100644
index 000000000000..4812370706a1
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
@@ -0,0 +1,116 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * This module provides system/board/application information obtained
+ * by the bootloader.
+ */
+
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-spinlock.h>
+#include <asm/octeon/cvmx-sysinfo.h>
+
+/**
+ * This structure defines the private state maintained by sysinfo module.
+ *
+ */
+static struct {
+ struct cvmx_sysinfo sysinfo; /* system information */
+ cvmx_spinlock_t lock; /* mutex spinlock */
+
+} state = {
+ .lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER
+};
+
+
+/*
+ * Global variables that define the min/max of the memory region set
+ * up for 32 bit userspace access.
+ */
+uint64_t linux_mem32_min;
+uint64_t linux_mem32_max;
+uint64_t linux_mem32_wired;
+uint64_t linux_mem32_offset;
+
+/**
+ * This function returns the application information as obtained
+ * by the bootloader. This provides the core mask of the cores
+ * running the same application image, as well as the physical
+ * memory regions available to the core.
+ *
+ * Returns Pointer to the boot information structure
+ *
+ */
+struct cvmx_sysinfo *cvmx_sysinfo_get(void)
+{
+ return &(state.sysinfo);
+}
+
+/**
+ * This function is used in non-simple executive environments (such as
+ * Linux kernel, u-boot, etc.) to configure the minimal fields that
+ * are required to use simple executive files directly.
+ *
+ * Locking (if required) must be handled outside of this
+ * function
+ *
+ * @phy_mem_desc_ptr:
+ * Pointer to global physical memory descriptor
+ * (bootmem descriptor) @board_type: Octeon board
+ * type enumeration
+ *
+ * @board_rev_major:
+ * Board major revision
+ * @board_rev_minor:
+ * Board minor revision
+ * @cpu_clock_hz:
+ * CPU clock freqency in hertz
+ *
+ * Returns 0: Failure
+ * 1: success
+ */
+int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr,
+ uint16_t board_type,
+ uint8_t board_rev_major,
+ uint8_t board_rev_minor,
+ uint32_t cpu_clock_hz)
+{
+
+ /* The sysinfo structure was already initialized */
+ if (state.sysinfo.board_type)
+ return 0;
+
+ memset(&(state.sysinfo), 0x0, sizeof(state.sysinfo));
+ state.sysinfo.phy_mem_desc_ptr = phy_mem_desc_ptr;
+ state.sysinfo.board_type = board_type;
+ state.sysinfo.board_rev_major = board_rev_major;
+ state.sysinfo.board_rev_minor = board_rev_minor;
+ state.sysinfo.cpu_clock_hz = cpu_clock_hz;
+
+ return 1;
+}
+
diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c
new file mode 100644
index 000000000000..9afc3794ed1b
--- /dev/null
+++ b/arch/mips/cavium-octeon/executive/octeon-model.c
@@ -0,0 +1,358 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * File defining functions for working with different Octeon
+ * models.
+ */
+#include <asm/octeon/octeon.h>
+
+/**
+ * Given the chip processor ID from COP0, this function returns a
+ * string representing the chip model number. The string is of the
+ * form CNXXXXpX.X-FREQ-SUFFIX.
+ * - XXXX = The chip model number
+ * - X.X = Chip pass number
+ * - FREQ = Current frequency in Mhz
+ * - SUFFIX = NSP, EXP, SCP, SSP, or CP
+ *
+ * @chip_id: Chip ID
+ *
+ * Returns Model string
+ */
+const char *octeon_model_get_string(uint32_t chip_id)
+{
+ static char buffer[32];
+ return octeon_model_get_string_buffer(chip_id, buffer);
+}
+
+/*
+ * Version of octeon_model_get_string() that takes buffer as argument,
+ * as running early in u-boot static/global variables don't work when
+ * running from flash.
+ */
+const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
+{
+ const char *family;
+ const char *core_model;
+ char pass[4];
+ int clock_mhz;
+ const char *suffix;
+ union cvmx_l2d_fus3 fus3;
+ int num_cores;
+ union cvmx_mio_fus_dat2 fus_dat2;
+ union cvmx_mio_fus_dat3 fus_dat3;
+ char fuse_model[10];
+ uint32_t fuse_data = 0;
+
+ fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
+ fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
+ fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
+
+ num_cores = cvmx_octeon_num_cores();
+
+ /* Make sure the non existant devices look disabled */
+ switch ((chip_id >> 8) & 0xff) {
+ case 6: /* CN50XX */
+ case 2: /* CN30XX */
+ fus_dat3.s.nodfa_dte = 1;
+ fus_dat3.s.nozip = 1;
+ break;
+ case 4: /* CN57XX or CN56XX */
+ fus_dat3.s.nodfa_dte = 1;
+ break;
+ default:
+ break;
+ }
+
+ /* Make a guess at the suffix */
+ /* NSP = everything */
+ /* EXP = No crypto */
+ /* SCP = No DFA, No zip */
+ /* CP = No DFA, No crypto, No zip */
+ if (fus_dat3.s.nodfa_dte) {
+ if (fus_dat2.s.nocrypto)
+ suffix = "CP";
+ else
+ suffix = "SCP";
+ } else if (fus_dat2.s.nocrypto)
+ suffix = "EXP";
+ else
+ suffix = "NSP";
+
+ /*
+ * Assume pass number is encoded using <5:3><2:0>. Exceptions
+ * will be fixed later.
+ */
+ sprintf(pass, "%u.%u", ((chip_id >> 3) & 7) + 1, chip_id & 7);
+
+ /*
+ * Use the number of cores to determine the last 2 digits of
+ * the model number. There are some exceptions that are fixed
+ * later.
+ */
+ switch (num_cores) {
+ case 16:
+ core_model = "60";
+ break;
+ case 15:
+ core_model = "58";
+ break;
+ case 14:
+ core_model = "55";
+ break;
+ case 13:
+ core_model = "52";
+ break;
+ case 12:
+ core_model = "50";
+ break;
+ case 11:
+ core_model = "48";
+ break;
+ case 10:
+ core_model = "45";
+ break;
+ case 9:
+ core_model = "42";
+ break;
+ case 8:
+ core_model = "40";
+ break;
+ case 7:
+ core_model = "38";
+ break;
+ case 6:
+ core_model = "34";
+ break;
+ case 5:
+ core_model = "32";
+ break;
+ case 4:
+ core_model = "30";
+ break;
+ case 3:
+ core_model = "25";
+ break;
+ case 2:
+ core_model = "20";
+ break;
+ case 1:
+ core_model = "10";
+ break;
+ default:
+ core_model = "XX";
+ break;
+ }
+
+ /* Now figure out the family, the first two digits */
+ switch ((chip_id >> 8) & 0xff) {
+ case 0: /* CN38XX, CN37XX or CN36XX */
+ if (fus3.cn38xx.crip_512k) {
+ /*
+ * For some unknown reason, the 16 core one is
+ * called 37 instead of 36.
+ */
+ if (num_cores >= 16)
+ family = "37";
+ else
+ family = "36";
+ } else
+ family = "38";
+ /*
+ * This series of chips didn't follow the standard
+ * pass numbering.
+ */
+ switch (chip_id & 0xf) {
+ case 0:
+ strcpy(pass, "1.X");
+ break;
+ case 1:
+ strcpy(pass, "2.X");
+ break;
+ case 3:
+ strcpy(pass, "3.X");
+ break;
+ default:
+ strcpy(pass, "X.X");
+ break;
+ }
+ break;
+ case 1: /* CN31XX or CN3020 */
+ if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
+ family = "30";
+ else
+ family = "31";
+ /*
+ * This series of chips didn't follow the standard
+ * pass numbering.
+ */
+ switch (chip_id & 0xf) {
+ case 0:
+ strcpy(pass, "1.0");
+ break;
+ case 2:
+ strcpy(pass, "1.1");
+ break;
+ default:
+ strcpy(pass, "X.X");
+ break;
+ }
+ break;
+ case 2: /* CN3010 or CN3005 */
+ family = "30";
+ /* A chip with half cache is an 05 */
+ if (fus3.cn30xx.crip_64k)
+ core_model = "05";
+ /*
+ * This series of chips didn't follow the standard
+ * pass numbering.
+ */
+ switch (chip_id & 0xf) {
+ case 0:
+ strcpy(pass, "1.0");
+ break;
+ case 2:
+ strcpy(pass, "1.1");
+ break;
+ default:
+ strcpy(pass, "X.X");
+ break;
+ }
+ break;
+ case 3: /* CN58XX */
+ family = "58";
+ /* Special case. 4 core, no crypto */
+ if ((num_cores == 4) && fus_dat2.cn38xx.nocrypto)
+ core_model = "29";
+
+ /* Pass 1 uses different encodings for pass numbers */
+ if ((chip_id & 0xFF) < 0x8) {
+ switch (chip_id & 0x3) {
+ case 0:
+ strcpy(pass, "1.0");
+ break;
+ case 1:
+ strcpy(pass, "1.1");
+ break;
+ case 3:
+ strcpy(pass, "1.2");
+ break;
+ default:
+ strcpy(pass, "1.X");
+ break;
+ }
+ }
+ break;
+ case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */
+ if (fus_dat2.cn56xx.raid_en) {
+ if (fus3.cn56xx.crip_1024k)
+ family = "55";
+ else
+ family = "57";
+ if (fus_dat2.cn56xx.nocrypto)
+ suffix = "SP";
+ else
+ suffix = "SSP";
+ } else {
+ if (fus_dat2.cn56xx.nocrypto)
+ suffix = "CP";
+ else {
+ suffix = "NSP";
+ if (fus_dat3.s.nozip)
+ suffix = "SCP";
+ }
+ if (fus3.cn56xx.crip_1024k)
+ family = "54";
+ else
+ family = "56";
+ }
+ break;
+ case 6: /* CN50XX */
+ family = "50";
+ break;
+ case 7: /* CN52XX */
+ if (fus3.cn52xx.crip_256k)
+ family = "51";
+ else
+ family = "52";
+ break;
+ default:
+ family = "XX";
+ core_model = "XX";
+ strcpy(pass, "X.X");
+ suffix = "XXX";
+ break;
+ }
+
+ clock_mhz = octeon_get_clock_rate() / 1000000;
+
+ if (family[0] != '3') {
+ /* Check for model in fuses, overrides normal decode */
+ /* This is _not_ valid for Octeon CN3XXX models */
+ fuse_data |= cvmx_fuse_read_byte(51);
+ fuse_data = fuse_data << 8;
+ fuse_data |= cvmx_fuse_read_byte(50);
+ fuse_data = fuse_data << 8;
+ fuse_data |= cvmx_fuse_read_byte(49);
+ fuse_data = fuse_data << 8;
+ fuse_data |= cvmx_fuse_read_byte(48);
+ if (fuse_data & 0x7ffff) {
+ int model = fuse_data & 0x3fff;
+ int suffix = (fuse_data >> 14) & 0x1f;
+ if (suffix && model) {
+ /*
+ * Have both number and suffix in
+ * fuses, so both
+ */
+ sprintf(fuse_model, "%d%c",
+ model, 'A' + suffix - 1);
+ core_model = "";
+ family = fuse_model;
+ } else if (suffix && !model) {
+ /*
+ * Only have suffix, so add suffix to
+ * 'normal' model number.
+ */
+ sprintf(fuse_model, "%s%c", core_model,
+ 'A' + suffix - 1);
+ core_model = fuse_model;
+ } else {
+ /*
+ * Don't have suffix, so just use
+ * model from fuses.
+ */
+ sprintf(fuse_model, "%d", model);
+ core_model = "";
+ family = fuse_model;
+ }
+ }
+ }
+ sprintf(buffer, "CN%s%sp%s-%d-%s",
+ family, core_model, pass, clock_mhz, suffix);
+ return buffer;
+}
diff --git a/arch/mips/cavium-octeon/flash_setup.c b/arch/mips/cavium-octeon/flash_setup.c
new file mode 100644
index 000000000000..553d36cbcc42
--- /dev/null
+++ b/arch/mips/cavium-octeon/flash_setup.c
@@ -0,0 +1,84 @@
+/*
+ * Octeon Bootbus flash setup
+ *
+ * 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) 2007, 2008 Cavium Networks
+ */
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/octeon/octeon.h>
+
+static struct map_info flash_map;
+static struct mtd_info *mymtd;
+#ifdef CONFIG_MTD_PARTITIONS
+static int nr_parts;
+static struct mtd_partition *parts;
+static const char *part_probe_types[] = {
+ "cmdlinepart",
+#ifdef CONFIG_MTD_REDBOOT_PARTS
+ "RedBoot",
+#endif
+ NULL
+};
+#endif
+
+/**
+ * Module/ driver initialization.
+ *
+ * Returns Zero on success
+ */
+static int __init flash_init(void)
+{
+ /*
+ * Read the bootbus region 0 setup to determine the base
+ * address of the flash.
+ */
+ union cvmx_mio_boot_reg_cfgx region_cfg;
+ region_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(0));
+ if (region_cfg.s.en) {
+ /*
+ * The bootloader always takes the flash and sets its
+ * address so the entire flash fits below
+ * 0x1fc00000. This way the flash aliases to
+ * 0x1fc00000 for booting. Software can access the
+ * full flash at the true address, while core boot can
+ * access 4MB.
+ */
+ /* Use this name so old part lines work */
+ flash_map.name = "phys_mapped_flash";
+ flash_map.phys = region_cfg.s.base << 16;
+ flash_map.size = 0x1fc00000 - flash_map.phys;
+ flash_map.bankwidth = 1;
+ flash_map.virt = ioremap(flash_map.phys, flash_map.size);
+ pr_notice("Bootbus flash: Setting flash for %luMB flash at "
+ "0x%08lx\n", flash_map.size >> 20, flash_map.phys);
+ simple_map_init(&flash_map);
+ mymtd = do_map_probe("cfi_probe", &flash_map);
+ if (mymtd) {
+ mymtd->owner = THIS_MODULE;
+
+#ifdef CONFIG_MTD_PARTITIONS
+ nr_parts = parse_mtd_partitions(mymtd,
+ part_probe_types,
+ &parts, 0);
+ if (nr_parts > 0)
+ add_mtd_partitions(mymtd, parts, nr_parts);
+ else
+ add_mtd_device(mymtd);
+#else
+ add_mtd_device(mymtd);
+#endif
+ } else {
+ pr_err("Failed to register MTD device for flash\n");
+ }
+ }
+ return 0;
+}
+
+late_initcall(flash_init);
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
new file mode 100644
index 000000000000..fc72984a5dae
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -0,0 +1,497 @@
+/*
+ * 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) 2004-2008 Cavium Networks
+ */
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
+
+#include <asm/octeon/octeon.h>
+
+DEFINE_RWLOCK(octeon_irq_ciu0_rwlock);
+DEFINE_RWLOCK(octeon_irq_ciu1_rwlock);
+DEFINE_SPINLOCK(octeon_irq_msi_lock);
+
+static void octeon_irq_core_ack(unsigned int irq)
+{
+ unsigned int bit = irq - OCTEON_IRQ_SW0;
+ /*
+ * We don't need to disable IRQs to make these atomic since
+ * they are already disabled earlier in the low level
+ * interrupt code.
+ */
+ clear_c0_status(0x100 << bit);
+ /* The two user interrupts must be cleared manually. */
+ if (bit < 2)
+ clear_c0_cause(0x100 << bit);
+}
+
+static void octeon_irq_core_eoi(unsigned int irq)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned int bit = irq - OCTEON_IRQ_SW0;
+ /*
+ * If an IRQ is being processed while we are disabling it the
+ * handler will attempt to unmask the interrupt after it has
+ * been disabled.
+ */
+ if (desc->status & IRQ_DISABLED)
+ return;
+
+ /* There is a race here. We should fix it. */
+
+ /*
+ * We don't need to disable IRQs to make these atomic since
+ * they are already disabled earlier in the low level
+ * interrupt code.
+ */
+ set_c0_status(0x100 << bit);
+}
+
+static void octeon_irq_core_enable(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned int bit = irq - OCTEON_IRQ_SW0;
+
+ /*
+ * We need to disable interrupts to make sure our updates are
+ * atomic.
+ */
+ local_irq_save(flags);
+ set_c0_status(0x100 << bit);
+ local_irq_restore(flags);
+}
+
+static void octeon_irq_core_disable_local(unsigned int irq)
+{
+ unsigned long flags;
+ unsigned int bit = irq - OCTEON_IRQ_SW0;
+ /*
+ * We need to disable interrupts to make sure our updates are
+ * atomic.
+ */
+ local_irq_save(flags);
+ clear_c0_status(0x100 << bit);
+ local_irq_restore(flags);
+}
+
+static void octeon_irq_core_disable(unsigned int irq)
+{
+#ifdef CONFIG_SMP
+ on_each_cpu((void (*)(void *)) octeon_irq_core_disable_local,
+ (void *) (long) irq, 1);
+#else
+ octeon_irq_core_disable_local(irq);
+#endif
+}
+
+static struct irq_chip octeon_irq_chip_core = {
+ .name = "Core",
+ .enable = octeon_irq_core_enable,
+ .disable = octeon_irq_core_disable,
+ .ack = octeon_irq_core_ack,
+ .eoi = octeon_irq_core_eoi,
+};
+
+
+static void octeon_irq_ciu0_ack(unsigned int irq)
+{
+ /*
+ * In order to avoid any locking accessing the CIU, we
+ * acknowledge CIU interrupts by disabling all of them. This
+ * way we can use a per core register and avoid any out of
+ * core locking requirements. This has the side affect that
+ * CIU interrupts can't be processed recursively.
+ *
+ * We don't need to disable IRQs to make these atomic since
+ * they are already disabled earlier in the low level
+ * interrupt code.
+ */
+ clear_c0_status(0x100 << 2);
+}
+
+static void octeon_irq_ciu0_eoi(unsigned int irq)
+{
+ /*
+ * Enable all CIU interrupts again. We don't need to disable
+ * IRQs to make these atomic since they are already disabled
+ * earlier in the low level interrupt code.
+ */
+ set_c0_status(0x100 << 2);
+}
+
+static void octeon_irq_ciu0_enable(unsigned int irq)
+{
+ int coreid = cvmx_get_core_num();
+ unsigned long flags;
+ uint64_t en0;
+ int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
+
+ /*
+ * A read lock is used here to make sure only one core is ever
+ * updating the CIU enable bits at a time. During an enable
+ * the cores don't interfere with each other. During a disable
+ * the write lock stops any enables that might cause a
+ * problem.
+ */
+ read_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
+ en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+ en0 |= 1ull << bit;
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+ cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+ read_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
+}
+
+static void octeon_irq_ciu0_disable(unsigned int irq)
+{
+ int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
+ unsigned long flags;
+ uint64_t en0;
+#ifdef CONFIG_SMP
+ int cpu;
+ write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags);
+ for_each_online_cpu(cpu) {
+ int coreid = cpu_logical_map(cpu);
+ en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+ en0 &= ~(1ull << bit);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+ }
+ /*
+ * We need to do a read after the last update to make sure all
+ * of them are done.
+ */
+ cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
+ write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags);
+#else
+ int coreid = cvmx_get_core_num();
+ local_irq_save(flags);
+ en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+ en0 &= ~(1ull << bit);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+ cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+ local_irq_restore(flags);
+#endif
+}
+
+#ifdef CONFIG_SMP
+static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
+{
+ int cpu;
+ int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
+
+ write_lock(&octeon_irq_ciu0_rwlock);
+ for_each_online_cpu(cpu) {
+ int coreid = cpu_logical_map(cpu);
+ uint64_t en0 =
+ cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
+ if (cpumask_test_cpu(cpu, dest))
+ en0 |= 1ull << bit;
+ else
+ en0 &= ~(1ull << bit);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+ }
+ /*
+ * We need to do a read after the last update to make sure all
+ * of them are done.
+ */
+ cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
+ write_unlock(&octeon_irq_ciu0_rwlock);
+}
+#endif
+
+static struct irq_chip octeon_irq_chip_ciu0 = {
+ .name = "CIU0",
+ .enable = octeon_irq_ciu0_enable,
+ .disable = octeon_irq_ciu0_disable,
+ .ack = octeon_irq_ciu0_ack,
+ .eoi = octeon_irq_ciu0_eoi,
+#ifdef CONFIG_SMP
+ .set_affinity = octeon_irq_ciu0_set_affinity,
+#endif
+};
+
+
+static void octeon_irq_ciu1_ack(unsigned int irq)
+{
+ /*
+ * In order to avoid any locking accessing the CIU, we
+ * acknowledge CIU interrupts by disabling all of them. This
+ * way we can use a per core register and avoid any out of
+ * core locking requirements. This has the side affect that
+ * CIU interrupts can't be processed recursively. We don't
+ * need to disable IRQs to make these atomic since they are
+ * already disabled earlier in the low level interrupt code.
+ */
+ clear_c0_status(0x100 << 3);
+}
+
+static void octeon_irq_ciu1_eoi(unsigned int irq)
+{
+ /*
+ * Enable all CIU interrupts again. We don't need to disable
+ * IRQs to make these atomic since they are already disabled
+ * earlier in the low level interrupt code.
+ */
+ set_c0_status(0x100 << 3);
+}
+
+static void octeon_irq_ciu1_enable(unsigned int irq)
+{
+ int coreid = cvmx_get_core_num();
+ unsigned long flags;
+ uint64_t en1;
+ int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
+
+ /*
+ * A read lock is used here to make sure only one core is ever
+ * updating the CIU enable bits at a time. During an enable
+ * the cores don't interfere with each other. During a disable
+ * the write lock stops any enables that might cause a
+ * problem.
+ */
+ read_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
+ en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+ en1 |= 1ull << bit;
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+ cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+ read_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
+}
+
+static void octeon_irq_ciu1_disable(unsigned int irq)
+{
+ int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
+ unsigned long flags;
+ uint64_t en1;
+#ifdef CONFIG_SMP
+ int cpu;
+ write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags);
+ for_each_online_cpu(cpu) {
+ int coreid = cpu_logical_map(cpu);
+ en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+ en1 &= ~(1ull << bit);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+ }
+ /*
+ * We need to do a read after the last update to make sure all
+ * of them are done.
+ */
+ cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
+ write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags);
+#else
+ int coreid = cvmx_get_core_num();
+ local_irq_save(flags);
+ en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+ en1 &= ~(1ull << bit);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+ cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+ local_irq_restore(flags);
+#endif
+}
+
+#ifdef CONFIG_SMP
+static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
+{
+ int cpu;
+ int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
+
+ write_lock(&octeon_irq_ciu1_rwlock);
+ for_each_online_cpu(cpu) {
+ int coreid = cpu_logical_map(cpu);
+ uint64_t en1 =
+ cvmx_read_csr(CVMX_CIU_INTX_EN1
+ (coreid * 2 + 1));
+ if (cpumask_test_cpu(cpu, dest))
+ en1 |= 1ull << bit;
+ else
+ en1 &= ~(1ull << bit);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+ }
+ /*
+ * We need to do a read after the last update to make sure all
+ * of them are done.
+ */
+ cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
+ write_unlock(&octeon_irq_ciu1_rwlock);
+}
+#endif
+
+static struct irq_chip octeon_irq_chip_ciu1 = {
+ .name = "CIU1",
+ .enable = octeon_irq_ciu1_enable,
+ .disable = octeon_irq_ciu1_disable,
+ .ack = octeon_irq_ciu1_ack,
+ .eoi = octeon_irq_ciu1_eoi,
+#ifdef CONFIG_SMP
+ .set_affinity = octeon_irq_ciu1_set_affinity,
+#endif
+};
+
+#ifdef CONFIG_PCI_MSI
+
+static void octeon_irq_msi_ack(unsigned int irq)
+{
+ if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+ /* These chips have PCI */
+ cvmx_write_csr(CVMX_NPI_NPI_MSI_RCV,
+ 1ull << (irq - OCTEON_IRQ_MSI_BIT0));
+ } else {
+ /*
+ * These chips have PCIe. Thankfully the ACK doesn't
+ * need any locking.
+ */
+ cvmx_write_csr(CVMX_PEXP_NPEI_MSI_RCV0,
+ 1ull << (irq - OCTEON_IRQ_MSI_BIT0));
+ }
+}
+
+static void octeon_irq_msi_eoi(unsigned int irq)
+{
+ /* Nothing needed */
+}
+
+static void octeon_irq_msi_enable(unsigned int irq)
+{
+ if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+ /*
+ * Octeon PCI doesn't have the ability to mask/unmask
+ * MSI interrupts individually. Instead of
+ * masking/unmasking them in groups of 16, we simple
+ * assume MSI devices are well behaved. MSI
+ * interrupts are always enable and the ACK is assumed
+ * to be enough.
+ */
+ } else {
+ /* These chips have PCIe. Note that we only support
+ * the first 64 MSI interrupts. Unfortunately all the
+ * MSI enables are in the same register. We use
+ * MSI0's lock to control access to them all.
+ */
+ uint64_t en;
+ unsigned long flags;
+ spin_lock_irqsave(&octeon_irq_msi_lock, flags);
+ en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+ en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0);
+ cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en);
+ cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+ spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
+ }
+}
+
+static void octeon_irq_msi_disable(unsigned int irq)
+{
+ if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) {
+ /* See comment in enable */
+ } else {
+ /*
+ * These chips have PCIe. Note that we only support
+ * the first 64 MSI interrupts. Unfortunately all the
+ * MSI enables are in the same register. We use
+ * MSI0's lock to control access to them all.
+ */
+ uint64_t en;
+ unsigned long flags;
+ spin_lock_irqsave(&octeon_irq_msi_lock, flags);
+ en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+ en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0));
+ cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en);
+ cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0);
+ spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
+ }
+}
+
+static struct irq_chip octeon_irq_chip_msi = {
+ .name = "MSI",
+ .enable = octeon_irq_msi_enable,
+ .disable = octeon_irq_msi_disable,
+ .ack = octeon_irq_msi_ack,
+ .eoi = octeon_irq_msi_eoi,
+};
+#endif
+
+void __init arch_init_irq(void)
+{
+ int irq;
+
+#ifdef CONFIG_SMP
+ /* Set the default affinity to the boot cpu. */
+ cpumask_clear(irq_default_affinity);
+ cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+#endif
+
+ if (NR_IRQS < OCTEON_IRQ_LAST)
+ pr_err("octeon_irq_init: NR_IRQS is set too low\n");
+
+ /* 0 - 15 reserved for i8259 master and slave controller. */
+
+ /* 17 - 23 Mips internal */
+ for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) {
+ set_irq_chip_and_handler(irq, &octeon_irq_chip_core,
+ handle_percpu_irq);
+ }
+
+ /* 24 - 87 CIU_INT_SUM0 */
+ for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
+ set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu0,
+ handle_percpu_irq);
+ }
+
+ /* 88 - 151 CIU_INT_SUM1 */
+ for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_RESERVED151; irq++) {
+ set_irq_chip_and_handler(irq, &octeon_irq_chip_ciu1,
+ handle_percpu_irq);
+ }
+
+#ifdef CONFIG_PCI_MSI
+ /* 152 - 215 PCI/PCIe MSI interrupts */
+ for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_BIT63; irq++) {
+ set_irq_chip_and_handler(irq, &octeon_irq_chip_msi,
+ handle_percpu_irq);
+ }
+#endif
+ set_c0_status(0x300 << 2);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ const unsigned long core_id = cvmx_get_core_num();
+ const uint64_t ciu_sum0_address = CVMX_CIU_INTX_SUM0(core_id * 2);
+ const uint64_t ciu_en0_address = CVMX_CIU_INTX_EN0(core_id * 2);
+ const uint64_t ciu_sum1_address = CVMX_CIU_INT_SUM1;
+ const uint64_t ciu_en1_address = CVMX_CIU_INTX_EN1(core_id * 2 + 1);
+ unsigned long cop0_cause;
+ unsigned long cop0_status;
+ uint64_t ciu_en;
+ uint64_t ciu_sum;
+
+ while (1) {
+ cop0_cause = read_c0_cause();
+ cop0_status = read_c0_status();
+ cop0_cause &= cop0_status;
+ cop0_cause &= ST0_IM;
+
+ if (unlikely(cop0_cause & STATUSF_IP2)) {
+ ciu_sum = cvmx_read_csr(ciu_sum0_address);
+ ciu_en = cvmx_read_csr(ciu_en0_address);
+ ciu_sum &= ciu_en;
+ if (likely(ciu_sum))
+ do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1);
+ else
+ spurious_interrupt();
+ } else if (unlikely(cop0_cause & STATUSF_IP3)) {
+ ciu_sum = cvmx_read_csr(ciu_sum1_address);
+ ciu_en = cvmx_read_csr(ciu_en1_address);
+ ciu_sum &= ciu_en;
+ if (likely(ciu_sum))
+ do_IRQ(fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1);
+ else
+ spurious_interrupt();
+ } else if (likely(cop0_cause)) {
+ do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE);
+ } else {
+ break;
+ }
+ }
+}
diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S
new file mode 100644
index 000000000000..88e0cddca205
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon-memcpy.S
@@ -0,0 +1,521 @@
+/*
+ * 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.
+ *
+ * Unified implementation of memcpy, memmove and the __copy_user backend.
+ *
+ * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc.
+ * Copyright (C) 2002 Broadcom, Inc.
+ * memcpy/copy_user author: Mark Vandevoorde
+ *
+ * Mnemonic names for arguments to memcpy/__copy_user
+ */
+
+#include <asm/asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/regdef.h>
+
+#define dst a0
+#define src a1
+#define len a2
+
+/*
+ * Spec
+ *
+ * memcpy copies len bytes from src to dst and sets v0 to dst.
+ * It assumes that
+ * - src and dst don't overlap
+ * - src is readable
+ * - dst is writable
+ * memcpy uses the standard calling convention
+ *
+ * __copy_user copies up to len bytes from src to dst and sets a2 (len) to
+ * the number of uncopied bytes due to an exception caused by a read or write.
+ * __copy_user assumes that src and dst don't overlap, and that the call is
+ * implementing one of the following:
+ * copy_to_user
+ * - src is readable (no exceptions when reading src)
+ * copy_from_user
+ * - dst is writable (no exceptions when writing dst)
+ * __copy_user uses a non-standard calling convention; see
+ * arch/mips/include/asm/uaccess.h
+ *
+ * When an exception happens on a load, the handler must
+ # ensure that all of the destination buffer is overwritten to prevent
+ * leaking information to user mode programs.
+ */
+
+/*
+ * Implementation
+ */
+
+/*
+ * The exception handler for loads requires that:
+ * 1- AT contain the address of the byte just past the end of the source
+ * of the copy,
+ * 2- src_entry <= src < AT, and
+ * 3- (dst - src) == (dst_entry - src_entry),
+ * The _entry suffix denotes values when __copy_user was called.
+ *
+ * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user
+ * (2) is met by incrementing src by the number of bytes copied
+ * (3) is met by not doing loads between a pair of increments of dst and src
+ *
+ * The exception handlers for stores adjust len (if necessary) and return.
+ * These handlers do not need to overwrite any data.
+ *
+ * For __rmemcpy and memmove an exception is always a kernel bug, therefore
+ * they're not protected.
+ */
+
+#define EXC(inst_reg,addr,handler) \
+9: inst_reg, addr; \
+ .section __ex_table,"a"; \
+ PTR 9b, handler; \
+ .previous
+
+/*
+ * Only on the 64-bit kernel we can made use of 64-bit registers.
+ */
+#ifdef CONFIG_64BIT
+#define USE_DOUBLE
+#endif
+
+#ifdef USE_DOUBLE
+
+#define LOAD ld
+#define LOADL ldl
+#define LOADR ldr
+#define STOREL sdl
+#define STORER sdr
+#define STORE sd
+#define ADD daddu
+#define SUB dsubu
+#define SRL dsrl
+#define SRA dsra
+#define SLL dsll
+#define SLLV dsllv
+#define SRLV dsrlv
+#define NBYTES 8
+#define LOG_NBYTES 3
+
+/*
+ * As we are sharing code base with the mips32 tree (which use the o32 ABI
+ * register definitions). We need to redefine the register definitions from
+ * the n64 ABI register naming to the o32 ABI register naming.
+ */
+#undef t0
+#undef t1
+#undef t2
+#undef t3
+#define t0 $8
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+
+#else
+
+#define LOAD lw
+#define LOADL lwl
+#define LOADR lwr
+#define STOREL swl
+#define STORER swr
+#define STORE sw
+#define ADD addu
+#define SUB subu
+#define SRL srl
+#define SLL sll
+#define SRA sra
+#define SLLV sllv
+#define SRLV srlv
+#define NBYTES 4
+#define LOG_NBYTES 2
+
+#endif /* USE_DOUBLE */
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define LDFIRST LOADR
+#define LDREST LOADL
+#define STFIRST STORER
+#define STREST STOREL
+#define SHIFT_DISCARD SLLV
+#else
+#define LDFIRST LOADL
+#define LDREST LOADR
+#define STFIRST STOREL
+#define STREST STORER
+#define SHIFT_DISCARD SRLV
+#endif
+
+#define FIRST(unit) ((unit)*NBYTES)
+#define REST(unit) (FIRST(unit)+NBYTES-1)
+#define UNIT(unit) FIRST(unit)
+
+#define ADDRMASK (NBYTES-1)
+
+ .text
+ .set noreorder
+ .set noat
+
+/*
+ * A combined memcpy/__copy_user
+ * __copy_user sets len to 0 for success; else to an upper bound of
+ * the number of uncopied bytes.
+ * memcpy sets v0 to dst.
+ */
+ .align 5
+LEAF(memcpy) /* a0=dst a1=src a2=len */
+ move v0, dst /* return value */
+__memcpy:
+FEXPORT(__copy_user)
+ /*
+ * Note: dst & src may be unaligned, len may be 0
+ * Temps
+ */
+ #
+ # Octeon doesn't care if the destination is unaligned. The hardware
+ # can fix it faster than we can special case the assembly.
+ #
+ pref 0, 0(src)
+ sltu t0, len, NBYTES # Check if < 1 word
+ bnez t0, copy_bytes_checklen
+ and t0, src, ADDRMASK # Check if src unaligned
+ bnez t0, src_unaligned
+ sltu t0, len, 4*NBYTES # Check if < 4 words
+ bnez t0, less_than_4units
+ sltu t0, len, 8*NBYTES # Check if < 8 words
+ bnez t0, less_than_8units
+ sltu t0, len, 16*NBYTES # Check if < 16 words
+ bnez t0, cleanup_both_aligned
+ sltu t0, len, 128+1 # Check if len < 129
+ bnez t0, 1f # Skip prefetch if len is too short
+ sltu t0, len, 256+1 # Check if len < 257
+ bnez t0, 1f # Skip prefetch if len is too short
+ pref 0, 128(src) # We must not prefetch invalid addresses
+ #
+ # This is where we loop if there is more than 128 bytes left
+2: pref 0, 256(src) # We must not prefetch invalid addresses
+ #
+ # This is where we loop if we can't prefetch anymore
+1:
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 16*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc_p16u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p15u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p14u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p13u)
+EXC( LOAD t0, UNIT(4)(src), l_exc_copy)
+EXC( LOAD t1, UNIT(5)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(6)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(7)(src), l_exc_copy)
+EXC( STORE t0, UNIT(4)(dst), s_exc_p12u)
+EXC( STORE t1, UNIT(5)(dst), s_exc_p11u)
+EXC( STORE t2, UNIT(6)(dst), s_exc_p10u)
+ ADD src, src, 16*NBYTES
+EXC( STORE t3, UNIT(7)(dst), s_exc_p9u)
+ ADD dst, dst, 16*NBYTES
+EXC( LOAD t0, UNIT(-8)(src), l_exc_copy)
+EXC( LOAD t1, UNIT(-7)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(-6)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(-5)(src), l_exc_copy)
+EXC( STORE t0, UNIT(-8)(dst), s_exc_p8u)
+EXC( STORE t1, UNIT(-7)(dst), s_exc_p7u)
+EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u)
+EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u)
+EXC( LOAD t0, UNIT(-4)(src), l_exc_copy)
+EXC( LOAD t1, UNIT(-3)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(-2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(-1)(src), l_exc_copy)
+EXC( STORE t0, UNIT(-4)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(-3)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(-2)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(-1)(dst), s_exc_p1u)
+ sltu t0, len, 256+1 # See if we can prefetch more
+ beqz t0, 2b
+ sltu t0, len, 128 # See if we can loop more time
+ beqz t0, 1b
+ nop
+ #
+ # Jump here if there are less than 16*NBYTES left.
+ #
+cleanup_both_aligned:
+ beqz len, done
+ sltu t0, len, 8*NBYTES
+ bnez t0, less_than_8units
+ nop
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 8*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc_p8u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p7u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p6u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p5u)
+EXC( LOAD t0, UNIT(4)(src), l_exc_copy)
+EXC( LOAD t1, UNIT(5)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(6)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(7)(src), l_exc_copy)
+EXC( STORE t0, UNIT(4)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(5)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(6)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(7)(dst), s_exc_p1u)
+ ADD src, src, 8*NBYTES
+ beqz len, done
+ ADD dst, dst, 8*NBYTES
+ #
+ # Jump here if there are less than 8*NBYTES left.
+ #
+less_than_8units:
+ sltu t0, len, 4*NBYTES
+ bnez t0, less_than_4units
+ nop
+EXC( LOAD t0, UNIT(0)(src), l_exc)
+EXC( LOAD t1, UNIT(1)(src), l_exc_copy)
+EXC( LOAD t2, UNIT(2)(src), l_exc_copy)
+EXC( LOAD t3, UNIT(3)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p1u)
+ ADD src, src, 4*NBYTES
+ beqz len, done
+ ADD dst, dst, 4*NBYTES
+ #
+ # Jump here if there are less than 4*NBYTES left. This means
+ # we may need to copy up to 3 NBYTES words.
+ #
+less_than_4units:
+ sltu t0, len, 1*NBYTES
+ bnez t0, copy_bytes_checklen
+ nop
+ #
+ # 1) Copy NBYTES, then check length again
+ #
+EXC( LOAD t0, 0(src), l_exc)
+ SUB len, len, NBYTES
+ sltu t1, len, 8
+EXC( STORE t0, 0(dst), s_exc_p1u)
+ ADD src, src, NBYTES
+ bnez t1, copy_bytes_checklen
+ ADD dst, dst, NBYTES
+ #
+ # 2) Copy NBYTES, then check length again
+ #
+EXC( LOAD t0, 0(src), l_exc)
+ SUB len, len, NBYTES
+ sltu t1, len, 8
+EXC( STORE t0, 0(dst), s_exc_p1u)
+ ADD src, src, NBYTES
+ bnez t1, copy_bytes_checklen
+ ADD dst, dst, NBYTES
+ #
+ # 3) Copy NBYTES, then check length again
+ #
+EXC( LOAD t0, 0(src), l_exc)
+ SUB len, len, NBYTES
+ ADD src, src, NBYTES
+ ADD dst, dst, NBYTES
+ b copy_bytes_checklen
+EXC( STORE t0, -8(dst), s_exc_p1u)
+
+src_unaligned:
+#define rem t8
+ SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
+ beqz t0, cleanup_src_unaligned
+ and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
+1:
+/*
+ * Avoid consecutive LD*'s to the same register since some mips
+ * implementations can't issue them in the same cycle.
+ * It's OK to load FIRST(N+1) before REST(N) because the two addresses
+ * are to the same unit (unless src is aligned, but it's not).
+ */
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy)
+ SUB len, len, 4*NBYTES
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+EXC( LDREST t1, REST(1)(src), l_exc_copy)
+EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy)
+EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy)
+EXC( LDREST t2, REST(2)(src), l_exc_copy)
+EXC( LDREST t3, REST(3)(src), l_exc_copy)
+ ADD src, src, 4*NBYTES
+EXC( STORE t0, UNIT(0)(dst), s_exc_p4u)
+EXC( STORE t1, UNIT(1)(dst), s_exc_p3u)
+EXC( STORE t2, UNIT(2)(dst), s_exc_p2u)
+EXC( STORE t3, UNIT(3)(dst), s_exc_p1u)
+ bne len, rem, 1b
+ ADD dst, dst, 4*NBYTES
+
+cleanup_src_unaligned:
+ beqz len, done
+ and rem, len, NBYTES-1 # rem = len % NBYTES
+ beq rem, len, copy_bytes
+ nop
+1:
+EXC( LDFIRST t0, FIRST(0)(src), l_exc)
+EXC( LDREST t0, REST(0)(src), l_exc_copy)
+ SUB len, len, NBYTES
+EXC( STORE t0, 0(dst), s_exc_p1u)
+ ADD src, src, NBYTES
+ bne len, rem, 1b
+ ADD dst, dst, NBYTES
+
+copy_bytes_checklen:
+ beqz len, done
+ nop
+copy_bytes:
+ /* 0 < len < NBYTES */
+#define COPY_BYTE(N) \
+EXC( lb t0, N(src), l_exc); \
+ SUB len, len, 1; \
+ beqz len, done; \
+EXC( sb t0, N(dst), s_exc_p1)
+
+ COPY_BYTE(0)
+ COPY_BYTE(1)
+#ifdef USE_DOUBLE
+ COPY_BYTE(2)
+ COPY_BYTE(3)
+ COPY_BYTE(4)
+ COPY_BYTE(5)
+#endif
+EXC( lb t0, NBYTES-2(src), l_exc)
+ SUB len, len, 1
+ jr ra
+EXC( sb t0, NBYTES-2(dst), s_exc_p1)
+done:
+ jr ra
+ nop
+ END(memcpy)
+
+l_exc_copy:
+ /*
+ * Copy bytes from src until faulting load address (or until a
+ * lb faults)
+ *
+ * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28)
+ * may be more than a byte beyond the last address.
+ * Hence, the lb below may get an exception.
+ *
+ * Assumes src < THREAD_BUADDR($28)
+ */
+ LOAD t0, TI_TASK($28)
+ nop
+ LOAD t0, THREAD_BUADDR(t0)
+1:
+EXC( lb t1, 0(src), l_exc)
+ ADD src, src, 1
+ sb t1, 0(dst) # can't fault -- we're copy_from_user
+ bne src, t0, 1b
+ ADD dst, dst, 1
+l_exc:
+ LOAD t0, TI_TASK($28)
+ nop
+ LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
+ nop
+ SUB len, AT, t0 # len number of uncopied bytes
+ /*
+ * Here's where we rely on src and dst being incremented in tandem,
+ * See (3) above.
+ * dst += (fault addr - src) to put dst at first byte to clear
+ */
+ ADD dst, t0 # compute start address in a1
+ SUB dst, src
+ /*
+ * Clear len bytes starting at dst. Can't call __bzero because it
+ * might modify len. An inefficient loop for these rare times...
+ */
+ beqz len, done
+ SUB src, len, 1
+1: sb zero, 0(dst)
+ ADD dst, dst, 1
+ bnez src, 1b
+ SUB src, src, 1
+ jr ra
+ nop
+
+
+#define SEXC(n) \
+s_exc_p ## n ## u: \
+ jr ra; \
+ ADD len, len, n*NBYTES
+
+SEXC(16)
+SEXC(15)
+SEXC(14)
+SEXC(13)
+SEXC(12)
+SEXC(11)
+SEXC(10)
+SEXC(9)
+SEXC(8)
+SEXC(7)
+SEXC(6)
+SEXC(5)
+SEXC(4)
+SEXC(3)
+SEXC(2)
+SEXC(1)
+
+s_exc_p1:
+ jr ra
+ ADD len, len, 1
+s_exc:
+ jr ra
+ nop
+
+ .align 5
+LEAF(memmove)
+ ADD t0, a0, a2
+ ADD t1, a1, a2
+ sltu t0, a1, t0 # dst + len <= src -> memcpy
+ sltu t1, a0, t1 # dst >= src + len -> memcpy
+ and t0, t1
+ beqz t0, __memcpy
+ move v0, a0 /* return value */
+ beqz a2, r_out
+ END(memmove)
+
+ /* fall through to __rmemcpy */
+LEAF(__rmemcpy) /* a0=dst a1=src a2=len */
+ sltu t0, a1, a0
+ beqz t0, r_end_bytes_up # src >= dst
+ nop
+ ADD a0, a2 # dst = dst + len
+ ADD a1, a2 # src = src + len
+
+r_end_bytes:
+ lb t0, -1(a1)
+ SUB a2, a2, 0x1
+ sb t0, -1(a0)
+ SUB a1, a1, 0x1
+ bnez a2, r_end_bytes
+ SUB a0, a0, 0x1
+
+r_out:
+ jr ra
+ move a2, zero
+
+r_end_bytes_up:
+ lb t0, (a1)
+ SUB a2, a2, 0x1
+ sb t0, (a0)
+ ADD a1, a1, 0x1
+ bnez a2, r_end_bytes_up
+ ADD a0, a0, 0x1
+
+ jr ra
+ move a2, zero
+ END(__rmemcpy)
diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c
new file mode 100644
index 000000000000..8240728d485a
--- /dev/null
+++ b/arch/mips/cavium-octeon/serial.c
@@ -0,0 +1,136 @@
+/*
+ * 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) 2004-2007 Cavium Networks
+ */
+#include <linux/console.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+#include <linux/tty.h>
+
+#include <asm/time.h>
+
+#include <asm/octeon/octeon.h>
+
+#ifdef CONFIG_GDB_CONSOLE
+#define DEBUG_UART 0
+#else
+#define DEBUG_UART 1
+#endif
+
+unsigned int octeon_serial_in(struct uart_port *up, int offset)
+{
+ int rv = cvmx_read_csr((uint64_t)(up->membase + (offset << 3)));
+ if (offset == UART_IIR && (rv & 0xf) == 7) {
+ /* Busy interrupt, read the USR (39) and try again. */
+ cvmx_read_csr((uint64_t)(up->membase + (39 << 3)));
+ rv = cvmx_read_csr((uint64_t)(up->membase + (offset << 3)));
+ }
+ return rv;
+}
+
+void octeon_serial_out(struct uart_port *up, int offset, int value)
+{
+ /*
+ * If bits 6 or 7 of the OCTEON UART's LCR are set, it quits
+ * working.
+ */
+ if (offset == UART_LCR)
+ value &= 0x9f;
+ cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value);
+}
+
+/*
+ * Allocated in .bss, so it is all zeroed.
+ */
+#define OCTEON_MAX_UARTS 3
+static struct plat_serial8250_port octeon_uart8250_data[OCTEON_MAX_UARTS + 1];
+static struct platform_device octeon_uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = octeon_uart8250_data,
+ },
+};
+
+static void __init octeon_uart_set_common(struct plat_serial8250_port *p)
+{
+ p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+ p->type = PORT_OCTEON;
+ p->iotype = UPIO_MEM;
+ p->regshift = 3; /* I/O addresses are every 8 bytes */
+ p->uartclk = mips_hpt_frequency;
+ p->serial_in = octeon_serial_in;
+ p->serial_out = octeon_serial_out;
+}
+
+static int __init octeon_serial_init(void)
+{
+ int enable_uart0;
+ int enable_uart1;
+ int enable_uart2;
+ struct plat_serial8250_port *p;
+
+#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+ /*
+ * If we are configured to run as the second of two kernels,
+ * disable uart0 and enable uart1. Uart0 is owned by the first
+ * kernel
+ */
+ enable_uart0 = 0;
+ enable_uart1 = 1;
+#else
+ /*
+ * We are configured for the first kernel. We'll enable uart0
+ * if the bootloader told us to use 0, otherwise will enable
+ * uart 1.
+ */
+ enable_uart0 = (octeon_get_boot_uart() == 0);
+ enable_uart1 = (octeon_get_boot_uart() == 1);
+#ifdef CONFIG_KGDB
+ enable_uart1 = 1;
+#endif
+#endif
+
+ /* Right now CN52XX is the only chip with a third uart */
+ enable_uart2 = OCTEON_IS_MODEL(OCTEON_CN52XX);
+
+ p = octeon_uart8250_data;
+ if (enable_uart0) {
+ /* Add a ttyS device for hardware uart 0 */
+ octeon_uart_set_common(p);
+ p->membase = (void *) CVMX_MIO_UARTX_RBR(0);
+ p->mapbase = CVMX_MIO_UARTX_RBR(0) & ((1ull << 49) - 1);
+ p->irq = OCTEON_IRQ_UART0;
+ p++;
+ }
+
+ if (enable_uart1) {
+ /* Add a ttyS device for hardware uart 1 */
+ octeon_uart_set_common(p);
+ p->membase = (void *) CVMX_MIO_UARTX_RBR(1);
+ p->mapbase = CVMX_MIO_UARTX_RBR(1) & ((1ull << 49) - 1);
+ p->irq = OCTEON_IRQ_UART1;
+ p++;
+ }
+ if (enable_uart2) {
+ /* Add a ttyS device for hardware uart 2 */
+ octeon_uart_set_common(p);
+ p->membase = (void *) CVMX_MIO_UART2_RBR;
+ p->mapbase = CVMX_MIO_UART2_RBR & ((1ull << 49) - 1);
+ p->irq = OCTEON_IRQ_UART2;
+ p++;
+ }
+
+ BUG_ON(p > &octeon_uart8250_data[OCTEON_MAX_UARTS]);
+
+ return platform_device_register(&octeon_uart8250_device);
+}
+
+device_initcall(octeon_serial_init);
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
new file mode 100644
index 000000000000..5f4e49ba4713
--- /dev/null
+++ b/arch/mips/cavium-octeon/setup.c
@@ -0,0 +1,927 @@
+/*
+ * 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) 2004-2007 Cavium Networks
+ * Copyright (C) 2008 Wind River Systems
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/serial.h>
+#include <linux/types.h>
+#include <linux/string.h> /* for memset */
+#include <linux/tty.h>
+#include <linux/time.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/smp-ops.h>
+#include <asm/system.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/bootinfo.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+
+#include <asm/octeon/octeon.h>
+
+#ifdef CONFIG_CAVIUM_DECODE_RSL
+extern void cvmx_interrupt_rsl_decode(void);
+extern int __cvmx_interrupt_ecc_report_single_bit_errors;
+extern void cvmx_interrupt_rsl_enable(void);
+#endif
+
+extern struct plat_smp_ops octeon_smp_ops;
+
+#ifdef CONFIG_PCI
+extern void pci_console_init(const char *arg);
+#endif
+
+#ifdef CONFIG_CAVIUM_RESERVE32
+extern uint64_t octeon_reserve32_memory;
+#endif
+static unsigned long long MAX_MEMORY = 512ull << 20;
+
+struct octeon_boot_descriptor *octeon_boot_desc_ptr;
+
+struct cvmx_bootinfo *octeon_bootinfo;
+EXPORT_SYMBOL(octeon_bootinfo);
+
+#ifdef CONFIG_CAVIUM_RESERVE32
+uint64_t octeon_reserve32_memory;
+EXPORT_SYMBOL(octeon_reserve32_memory);
+#endif
+
+static int octeon_uart;
+
+extern asmlinkage void handle_int(void);
+extern asmlinkage void plat_irq_dispatch(void);
+
+/**
+ * Return non zero if we are currently running in the Octeon simulator
+ *
+ * Returns
+ */
+int octeon_is_simulation(void)
+{
+ return octeon_bootinfo->board_type == CVMX_BOARD_TYPE_SIM;
+}
+EXPORT_SYMBOL(octeon_is_simulation);
+
+/**
+ * Return true if Octeon is in PCI Host mode. This means
+ * Linux can control the PCI bus.
+ *
+ * Returns Non zero if Octeon in host mode.
+ */
+int octeon_is_pci_host(void)
+{
+#ifdef CONFIG_PCI
+ return octeon_bootinfo->config_flags & CVMX_BOOTINFO_CFG_FLAG_PCI_HOST;
+#else
+ return 0;
+#endif
+}
+
+/**
+ * Get the clock rate of Octeon
+ *
+ * Returns Clock rate in HZ
+ */
+uint64_t octeon_get_clock_rate(void)
+{
+ if (octeon_is_simulation())
+ octeon_bootinfo->eclock_hz = 6000000;
+ return octeon_bootinfo->eclock_hz;
+}
+EXPORT_SYMBOL(octeon_get_clock_rate);
+
+/**
+ * Write to the LCD display connected to the bootbus. This display
+ * exists on most Cavium evaluation boards. If it doesn't exist, then
+ * this function doesn't do anything.
+ *
+ * @s: String to write
+ */
+void octeon_write_lcd(const char *s)
+{
+ if (octeon_bootinfo->led_display_base_addr) {
+ void __iomem *lcd_address =
+ ioremap_nocache(octeon_bootinfo->led_display_base_addr,
+ 8);
+ int i;
+ for (i = 0; i < 8; i++, s++) {
+ if (*s)
+ iowrite8(*s, lcd_address + i);
+ else
+ iowrite8(' ', lcd_address + i);
+ }
+ iounmap(lcd_address);
+ }
+}
+
+/**
+ * Return the console uart passed by the bootloader
+ *
+ * Returns uart (0 or 1)
+ */
+int octeon_get_boot_uart(void)
+{
+ int uart;
+#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+ uart = 1;
+#else
+ uart = (octeon_boot_desc_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) ?
+ 1 : 0;
+#endif
+ return uart;
+}
+
+/**
+ * Get the coremask Linux was booted on.
+ *
+ * Returns Core mask
+ */
+int octeon_get_boot_coremask(void)
+{
+ return octeon_boot_desc_ptr->core_mask;
+}
+
+/**
+ * Check the hardware BIST results for a CPU
+ */
+void octeon_check_cpu_bist(void)
+{
+ const int coreid = cvmx_get_core_num();
+ unsigned long long mask;
+ unsigned long long bist_val;
+
+ /* Check BIST results for COP0 registers */
+ mask = 0x1f00000000ull;
+ bist_val = read_octeon_c0_icacheerr();
+ if (bist_val & mask)
+ pr_err("Core%d BIST Failure: CacheErr(icache) = 0x%llx\n",
+ coreid, bist_val);
+
+ bist_val = read_octeon_c0_dcacheerr();
+ if (bist_val & 1)
+ pr_err("Core%d L1 Dcache parity error: "
+ "CacheErr(dcache) = 0x%llx\n",
+ coreid, bist_val);
+
+ mask = 0xfc00000000000000ull;
+ bist_val = read_c0_cvmmemctl();
+ if (bist_val & mask)
+ pr_err("Core%d BIST Failure: COP0_CVM_MEM_CTL = 0x%llx\n",
+ coreid, bist_val);
+
+ write_octeon_c0_dcacheerr(0);
+}
+
+#ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB
+/**
+ * Called on every core to setup the wired tlb entry needed
+ * if CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB is set.
+ *
+ */
+static void octeon_hal_setup_per_cpu_reserved32(void *unused)
+{
+ /*
+ * The config has selected to wire the reserve32 memory for all
+ * userspace applications. We need to put a wired TLB entry in for each
+ * 512MB of reserve32 memory. We only handle double 256MB pages here,
+ * so reserve32 must be multiple of 512MB.
+ */
+ uint32_t size = CONFIG_CAVIUM_RESERVE32;
+ uint32_t entrylo0 =
+ 0x7 | ((octeon_reserve32_memory & ((1ul << 40) - 1)) >> 6);
+ uint32_t entrylo1 = entrylo0 + (256 << 14);
+ uint32_t entryhi = (0x80000000UL - (CONFIG_CAVIUM_RESERVE32 << 20));
+ while (size >= 512) {
+#if 0
+ pr_info("CPU%d: Adding double wired TLB entry for 0x%lx\n",
+ smp_processor_id(), entryhi);
+#endif
+ add_wired_entry(entrylo0, entrylo1, entryhi, PM_256M);
+ entrylo0 += 512 << 14;
+ entrylo1 += 512 << 14;
+ entryhi += 512 << 20;
+ size -= 512;
+ }
+}
+#endif /* CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB */
+
+/**
+ * Called to release the named block which was used to made sure
+ * that nobody used the memory for something else during
+ * init. Now we'll free it so userspace apps can use this
+ * memory region with bootmem_alloc.
+ *
+ * This function is called only once from prom_free_prom_memory().
+ */
+void octeon_hal_setup_reserved32(void)
+{
+#ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB
+ on_each_cpu(octeon_hal_setup_per_cpu_reserved32, NULL, 0, 1);
+#endif
+}
+
+/**
+ * Reboot Octeon
+ *
+ * @command: Command to pass to the bootloader. Currently ignored.
+ */
+static void octeon_restart(char *command)
+{
+ /* Disable all watchdogs before soft reset. They don't get cleared */
+#ifdef CONFIG_SMP
+ int cpu;
+ for_each_online_cpu(cpu)
+ cvmx_write_csr(CVMX_CIU_WDOGX(cpu_logical_map(cpu)), 0);
+#else
+ cvmx_write_csr(CVMX_CIU_WDOGX(cvmx_get_core_num()), 0);
+#endif
+
+ mb();
+ while (1)
+ cvmx_write_csr(CVMX_CIU_SOFT_RST, 1);
+}
+
+
+/**
+ * Permanently stop a core.
+ *
+ * @arg: Ignored.
+ */
+static void octeon_kill_core(void *arg)
+{
+ mb();
+ if (octeon_is_simulation()) {
+ /* The simulator needs the watchdog to stop for dead cores */
+ cvmx_write_csr(CVMX_CIU_WDOGX(cvmx_get_core_num()), 0);
+ /* A break instruction causes the simulator stop a core */
+ asm volatile ("sync\nbreak");
+ }
+}
+
+
+/**
+ * Halt the system
+ */
+static void octeon_halt(void)
+{
+ smp_call_function(octeon_kill_core, NULL, 0);
+
+ switch (octeon_bootinfo->board_type) {
+ case CVMX_BOARD_TYPE_NAO38:
+ /* Driving a 1 to GPIO 12 shuts off this board */
+ cvmx_write_csr(CVMX_GPIO_BIT_CFGX(12), 1);
+ cvmx_write_csr(CVMX_GPIO_TX_SET, 0x1000);
+ break;
+ default:
+ octeon_write_lcd("PowerOff");
+ break;
+ }
+
+ octeon_kill_core(NULL);
+}
+
+#if 0
+/**
+ * Platform time init specifics.
+ * Returns
+ */
+void __init plat_time_init(void)
+{
+ /* Nothing special here, but we are required to have one */
+}
+
+#endif
+
+/**
+ * Handle all the error condition interrupts that might occur.
+ *
+ */
+#ifdef CONFIG_CAVIUM_DECODE_RSL
+static irqreturn_t octeon_rlm_interrupt(int cpl, void *dev_id)
+{
+ cvmx_interrupt_rsl_decode();
+ return IRQ_HANDLED;
+}
+#endif
+
+/**
+ * Return a string representing the system type
+ *
+ * Returns
+ */
+const char *octeon_board_type_string(void)
+{
+ static char name[80];
+ sprintf(name, "%s (%s)",
+ cvmx_board_type_to_string(octeon_bootinfo->board_type),
+ octeon_model_get_string(read_c0_prid()));
+ return name;
+}
+
+const char *get_system_type(void)
+ __attribute__ ((alias("octeon_board_type_string")));
+
+void octeon_user_io_init(void)
+{
+ union octeon_cvmemctl cvmmemctl;
+ union cvmx_iob_fau_timeout fau_timeout;
+ union cvmx_pow_nw_tim nm_tim;
+ uint64_t cvmctl;
+
+ /* Get the current settings for CP0_CVMMEMCTL_REG */
+ cvmmemctl.u64 = read_c0_cvmmemctl();
+ /* R/W If set, marked write-buffer entries time out the same
+ * as as other entries; if clear, marked write-buffer entries
+ * use the maximum timeout. */
+ cvmmemctl.s.dismarkwblongto = 1;
+ /* R/W If set, a merged store does not clear the write-buffer
+ * entry timeout state. */
+ cvmmemctl.s.dismrgclrwbto = 0;
+ /* R/W Two bits that are the MSBs of the resultant CVMSEG LM
+ * word location for an IOBDMA. The other 8 bits come from the
+ * SCRADDR field of the IOBDMA. */
+ cvmmemctl.s.iobdmascrmsb = 0;
+ /* R/W If set, SYNCWS and SYNCS only order marked stores; if
+ * clear, SYNCWS and SYNCS only order unmarked
+ * stores. SYNCWSMARKED has no effect when DISSYNCWS is
+ * set. */
+ cvmmemctl.s.syncwsmarked = 0;
+ /* R/W If set, SYNCWS acts as SYNCW and SYNCS acts as SYNC. */
+ cvmmemctl.s.dissyncws = 0;
+ /* R/W If set, no stall happens on write buffer full. */
+ if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
+ cvmmemctl.s.diswbfst = 1;
+ else
+ cvmmemctl.s.diswbfst = 0;
+ /* R/W If set (and SX set), supervisor-level loads/stores can
+ * use XKPHYS addresses with <48>==0 */
+ cvmmemctl.s.xkmemenas = 0;
+
+ /* R/W If set (and UX set), user-level loads/stores can use
+ * XKPHYS addresses with VA<48>==0 */
+ cvmmemctl.s.xkmemenau = 0;
+
+ /* R/W If set (and SX set), supervisor-level loads/stores can
+ * use XKPHYS addresses with VA<48>==1 */
+ cvmmemctl.s.xkioenas = 0;
+
+ /* R/W If set (and UX set), user-level loads/stores can use
+ * XKPHYS addresses with VA<48>==1 */
+ cvmmemctl.s.xkioenau = 0;
+
+ /* R/W If set, all stores act as SYNCW (NOMERGE must be set
+ * when this is set) RW, reset to 0. */
+ cvmmemctl.s.allsyncw = 0;
+
+ /* R/W If set, no stores merge, and all stores reach the
+ * coherent bus in order. */
+ cvmmemctl.s.nomerge = 0;
+ /* R/W Selects the bit in the counter used for DID time-outs 0
+ * = 231, 1 = 230, 2 = 229, 3 = 214. Actual time-out is
+ * between 1x and 2x this interval. For example, with
+ * DIDTTO=3, expiration interval is between 16K and 32K. */
+ cvmmemctl.s.didtto = 0;
+ /* R/W If set, the (mem) CSR clock never turns off. */
+ cvmmemctl.s.csrckalwys = 0;
+ /* R/W If set, mclk never turns off. */
+ cvmmemctl.s.mclkalwys = 0;
+ /* R/W Selects the bit in the counter used for write buffer
+ * flush time-outs (WBFLT+11) is the bit position in an
+ * internal counter used to determine expiration. The write
+ * buffer expires between 1x and 2x this interval. For
+ * example, with WBFLT = 0, a write buffer expires between 2K
+ * and 4K cycles after the write buffer entry is allocated. */
+ cvmmemctl.s.wbfltime = 0;
+ /* R/W If set, do not put Istream in the L2 cache. */
+ cvmmemctl.s.istrnol2 = 0;
+ /* R/W The write buffer threshold. */
+ cvmmemctl.s.wbthresh = 10;
+ /* R/W If set, CVMSEG is available for loads/stores in
+ * kernel/debug mode. */
+#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
+ cvmmemctl.s.cvmsegenak = 1;
+#else
+ cvmmemctl.s.cvmsegenak = 0;
+#endif
+ /* R/W If set, CVMSEG is available for loads/stores in
+ * supervisor mode. */
+ cvmmemctl.s.cvmsegenas = 0;
+ /* R/W If set, CVMSEG is available for loads/stores in user
+ * mode. */
+ cvmmemctl.s.cvmsegenau = 0;
+ /* R/W Size of local memory in cache blocks, 54 (6912 bytes)
+ * is max legal value. */
+ cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE;
+
+
+ if (smp_processor_id() == 0)
+ pr_notice("CVMSEG size: %d cache lines (%d bytes)\n",
+ CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
+ CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
+
+ write_c0_cvmmemctl(cvmmemctl.u64);
+
+ /* Move the performance counter interrupts to IRQ 6 */
+ cvmctl = read_c0_cvmctl();
+ cvmctl &= ~(7 << 7);
+ cvmctl |= 6 << 7;
+ write_c0_cvmctl(cvmctl);
+
+ /* Set a default for the hardware timeouts */
+ fau_timeout.u64 = 0;
+ fau_timeout.s.tout_val = 0xfff;
+ /* Disable tagwait FAU timeout */
+ fau_timeout.s.tout_enb = 0;
+ cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64);
+
+ nm_tim.u64 = 0;
+ /* 4096 cycles */
+ nm_tim.s.nw_tim = 3;
+ cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64);
+
+ write_octeon_c0_icacheerr(0);
+ write_c0_derraddr1(0);
+}
+
+/**
+ * Early entry point for arch setup
+ */
+void __init prom_init(void)
+{
+ struct cvmx_sysinfo *sysinfo;
+ const int coreid = cvmx_get_core_num();
+ int i;
+ int argc;
+ struct uart_port octeon_port;
+#ifdef CONFIG_CAVIUM_RESERVE32
+ int64_t addr = -1;
+#endif
+ /*
+ * The bootloader passes a pointer to the boot descriptor in
+ * $a3, this is available as fw_arg3.
+ */
+ octeon_boot_desc_ptr = (struct octeon_boot_descriptor *)fw_arg3;
+ octeon_bootinfo =
+ cvmx_phys_to_ptr(octeon_boot_desc_ptr->cvmx_desc_vaddr);
+ cvmx_bootmem_init(cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr));
+
+ /*
+ * Only enable the LED controller if we're running on a CN38XX, CN58XX,
+ * or CN56XX. The CN30XX and CN31XX don't have an LED controller.
+ */
+ if (!octeon_is_simulation() &&
+ octeon_has_feature(OCTEON_FEATURE_LED_CONTROLLER)) {
+ cvmx_write_csr(CVMX_LED_EN, 0);
+ cvmx_write_csr(CVMX_LED_PRT, 0);
+ cvmx_write_csr(CVMX_LED_DBG, 0);
+ cvmx_write_csr(CVMX_LED_PRT_FMT, 0);
+ cvmx_write_csr(CVMX_LED_UDD_CNTX(0), 32);
+ cvmx_write_csr(CVMX_LED_UDD_CNTX(1), 32);
+ cvmx_write_csr(CVMX_LED_UDD_DATX(0), 0);
+ cvmx_write_csr(CVMX_LED_UDD_DATX(1), 0);
+ cvmx_write_csr(CVMX_LED_EN, 1);
+ }
+#ifdef CONFIG_CAVIUM_RESERVE32
+ /*
+ * We need to temporarily allocate all memory in the reserve32
+ * region. This makes sure the kernel doesn't allocate this
+ * memory when it is getting memory from the
+ * bootloader. Later, after the memory allocations are
+ * complete, the reserve32 will be freed.
+ */
+#ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB
+ if (CONFIG_CAVIUM_RESERVE32 & 0x1ff)
+ pr_err("CAVIUM_RESERVE32 isn't a multiple of 512MB. "
+ "This is required if CAVIUM_RESERVE32_USE_WIRED_TLB "
+ "is set\n");
+ else
+ addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
+ 0, 0, 512 << 20,
+ "CAVIUM_RESERVE32", 0);
+#else
+ /*
+ * Allocate memory for RESERVED32 aligned on 2MB boundary. This
+ * is in case we later use hugetlb entries with it.
+ */
+ addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
+ 0, 0, 2 << 20,
+ "CAVIUM_RESERVE32", 0);
+#endif
+ if (addr < 0)
+ pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
+ else
+ octeon_reserve32_memory = addr;
+#endif
+
+#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2
+ if (cvmx_read_csr(CVMX_L2D_FUS3) & (3ull << 34)) {
+ pr_info("Skipping L2 locking due to reduced L2 cache size\n");
+ } else {
+ uint32_t ebase = read_c0_ebase() & 0x3ffff000;
+#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB
+ /* TLB refill */
+ cvmx_l2c_lock_mem_region(ebase, 0x100);
+#endif
+#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2_EXCEPTION
+ /* General exception */
+ cvmx_l2c_lock_mem_region(ebase + 0x180, 0x80);
+#endif
+#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT
+ /* Interrupt handler */
+ cvmx_l2c_lock_mem_region(ebase + 0x200, 0x80);
+#endif
+#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2_INTERRUPT
+ cvmx_l2c_lock_mem_region(__pa_symbol(handle_int), 0x100);
+ cvmx_l2c_lock_mem_region(__pa_symbol(plat_irq_dispatch), 0x80);
+#endif
+#ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2_MEMCPY
+ cvmx_l2c_lock_mem_region(__pa_symbol(memcpy), 0x480);
+#endif
+ }
+#endif
+
+ sysinfo = cvmx_sysinfo_get();
+ memset(sysinfo, 0, sizeof(*sysinfo));
+ sysinfo->system_dram_size = octeon_bootinfo->dram_size << 20;
+ sysinfo->phy_mem_desc_ptr =
+ cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr);
+ sysinfo->core_mask = octeon_bootinfo->core_mask;
+ sysinfo->exception_base_addr = octeon_bootinfo->exception_base_addr;
+ sysinfo->cpu_clock_hz = octeon_bootinfo->eclock_hz;
+ sysinfo->dram_data_rate_hz = octeon_bootinfo->dclock_hz * 2;
+ sysinfo->board_type = octeon_bootinfo->board_type;
+ sysinfo->board_rev_major = octeon_bootinfo->board_rev_major;
+ sysinfo->board_rev_minor = octeon_bootinfo->board_rev_minor;
+ memcpy(sysinfo->mac_addr_base, octeon_bootinfo->mac_addr_base,
+ sizeof(sysinfo->mac_addr_base));
+ sysinfo->mac_addr_count = octeon_bootinfo->mac_addr_count;
+ memcpy(sysinfo->board_serial_number,
+ octeon_bootinfo->board_serial_number,
+ sizeof(sysinfo->board_serial_number));
+ sysinfo->compact_flash_common_base_addr =
+ octeon_bootinfo->compact_flash_common_base_addr;
+ sysinfo->compact_flash_attribute_base_addr =
+ octeon_bootinfo->compact_flash_attribute_base_addr;
+ sysinfo->led_display_base_addr = octeon_bootinfo->led_display_base_addr;
+ sysinfo->dfa_ref_clock_hz = octeon_bootinfo->dfa_ref_clock_hz;
+ sysinfo->bootloader_config_flags = octeon_bootinfo->config_flags;
+
+
+ octeon_check_cpu_bist();
+
+ octeon_uart = octeon_get_boot_uart();
+
+ /*
+ * Disable All CIU Interrupts. The ones we need will be
+ * enabled later. Read the SUM register so we know the write
+ * completed.
+ */
+ cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
+ cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2)));
+
+#ifdef CONFIG_SMP
+ octeon_write_lcd("LinuxSMP");
+#else
+ octeon_write_lcd("Linux");
+#endif
+
+#ifdef CONFIG_CAVIUM_GDB
+ /*
+ * When debugging the linux kernel, force the cores to enter
+ * the debug exception handler to break in.
+ */
+ if (octeon_get_boot_debug_flag()) {
+ cvmx_write_csr(CVMX_CIU_DINT, 1 << cvmx_get_core_num());
+ cvmx_read_csr(CVMX_CIU_DINT);
+ }
+#endif
+
+ /*
+ * BIST should always be enabled when doing a soft reset. L2
+ * Cache locking for instance is not cleared unless BIST is
+ * enabled. Unfortunately due to a chip errata G-200 for
+ * Cn38XX and CN31XX, BIST msut be disabled on these parts.
+ */
+ if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) ||
+ OCTEON_IS_MODEL(OCTEON_CN31XX))
+ cvmx_write_csr(CVMX_CIU_SOFT_BIST, 0);
+ else
+ cvmx_write_csr(CVMX_CIU_SOFT_BIST, 1);
+
+ /* Default to 64MB in the simulator to speed things up */
+ if (octeon_is_simulation())
+ MAX_MEMORY = 64ull << 20;
+
+ arcs_cmdline[0] = 0;
+ argc = octeon_boot_desc_ptr->argc;
+ for (i = 0; i < argc; i++) {
+ const char *arg =
+ cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]);
+ if ((strncmp(arg, "MEM=", 4) == 0) ||
+ (strncmp(arg, "mem=", 4) == 0)) {
+ sscanf(arg + 4, "%llu", &MAX_MEMORY);
+ MAX_MEMORY <<= 20;
+ if (MAX_MEMORY == 0)
+ MAX_MEMORY = 32ull << 30;
+ } else if (strcmp(arg, "ecc_verbose") == 0) {
+#ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC
+ __cvmx_interrupt_ecc_report_single_bit_errors = 1;
+ pr_notice("Reporting of single bit ECC errors is "
+ "turned on\n");
+#endif
+ } else if (strlen(arcs_cmdline) + strlen(arg) + 1 <
+ sizeof(arcs_cmdline) - 1) {
+ strcat(arcs_cmdline, " ");
+ strcat(arcs_cmdline, arg);
+ }
+ }
+
+ if (strstr(arcs_cmdline, "console=") == NULL) {
+#ifdef CONFIG_GDB_CONSOLE
+ strcat(arcs_cmdline, " console=gdb");
+#else
+#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+ strcat(arcs_cmdline, " console=ttyS0,115200");
+#else
+ if (octeon_uart == 1)
+ strcat(arcs_cmdline, " console=ttyS1,115200");
+ else
+ strcat(arcs_cmdline, " console=ttyS0,115200");
+#endif
+#endif
+ }
+
+ if (octeon_is_simulation()) {
+ /*
+ * The simulator uses a mtdram device pre filled with
+ * the filesystem. Also specify the calibration delay
+ * to avoid calculating it every time.
+ */
+ strcat(arcs_cmdline, " rw root=1f00"
+ " lpj=60176 slram=root,0x40000000,+1073741824");
+ }
+
+ mips_hpt_frequency = octeon_get_clock_rate();
+
+ octeon_init_cvmcount();
+
+ _machine_restart = octeon_restart;
+ _machine_halt = octeon_halt;
+
+ memset(&octeon_port, 0, sizeof(octeon_port));
+ /*
+ * For early_serial_setup we don't set the port type or
+ * UPF_FIXED_TYPE.
+ */
+ octeon_port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ;
+ octeon_port.iotype = UPIO_MEM;
+ /* I/O addresses are every 8 bytes */
+ octeon_port.regshift = 3;
+ /* Clock rate of the chip */
+ octeon_port.uartclk = mips_hpt_frequency;
+ octeon_port.fifosize = 64;
+ octeon_port.mapbase = 0x0001180000000800ull + (1024 * octeon_uart);
+ octeon_port.membase = cvmx_phys_to_ptr(octeon_port.mapbase);
+ octeon_port.serial_in = octeon_serial_in;
+ octeon_port.serial_out = octeon_serial_out;
+#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+ octeon_port.line = 0;
+#else
+ octeon_port.line = octeon_uart;
+#endif
+ octeon_port.irq = 42 + octeon_uart;
+ early_serial_setup(&octeon_port);
+
+ octeon_user_io_init();
+ register_smp_ops(&octeon_smp_ops);
+}
+
+void __init plat_mem_setup(void)
+{
+ uint64_t mem_alloc_size;
+ uint64_t total;
+ int64_t memory;
+
+ total = 0;
+
+ /* First add the init memory we will be returning. */
+ memory = __pa_symbol(&__init_begin) & PAGE_MASK;
+ mem_alloc_size = (__pa_symbol(&__init_end) & PAGE_MASK) - memory;
+ if (mem_alloc_size > 0) {
+ add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM);
+ total += mem_alloc_size;
+ }
+
+ /*
+ * The Mips memory init uses the first memory location for
+ * some memory vectors. When SPARSEMEM is in use, it doesn't
+ * verify that the size is big enough for the final
+ * vectors. Making the smallest chuck 4MB seems to be enough
+ * to consistantly work.
+ */
+ mem_alloc_size = 4 << 20;
+ if (mem_alloc_size > MAX_MEMORY)
+ mem_alloc_size = MAX_MEMORY;
+
+ /*
+ * When allocating memory, we want incrementing addresses from
+ * bootmem_alloc so the code in add_memory_region can merge
+ * regions next to each other.
+ */
+ cvmx_bootmem_lock();
+ while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX)
+ && (total < MAX_MEMORY)) {
+#if defined(CONFIG_64BIT) || defined(CONFIG_64BIT_PHYS_ADDR)
+ memory = cvmx_bootmem_phy_alloc(mem_alloc_size,
+ __pa_symbol(&__init_end), -1,
+ 0x100000,
+ CVMX_BOOTMEM_FLAG_NO_LOCKING);
+#elif defined(CONFIG_HIGHMEM)
+ memory = cvmx_bootmem_phy_alloc(mem_alloc_size, 0, 1ull << 31,
+ 0x100000,
+ CVMX_BOOTMEM_FLAG_NO_LOCKING);
+#else
+ memory = cvmx_bootmem_phy_alloc(mem_alloc_size, 0, 512 << 20,
+ 0x100000,
+ CVMX_BOOTMEM_FLAG_NO_LOCKING);
+#endif
+ if (memory >= 0) {
+ /*
+ * This function automatically merges address
+ * regions next to each other if they are
+ * received in incrementing order.
+ */
+ add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM);
+ total += mem_alloc_size;
+ } else {
+ break;
+ }
+ }
+ cvmx_bootmem_unlock();
+
+#ifdef CONFIG_CAVIUM_RESERVE32
+ /*
+ * Now that we've allocated the kernel memory it is safe to
+ * free the reserved region. We free it here so that builtin
+ * drivers can use the memory.
+ */
+ if (octeon_reserve32_memory)
+ cvmx_bootmem_free_named("CAVIUM_RESERVE32");
+#endif /* CONFIG_CAVIUM_RESERVE32 */
+
+ if (total == 0)
+ panic("Unable to allocate memory from "
+ "cvmx_bootmem_phy_alloc\n");
+}
+
+
+int prom_putchar(char c)
+{
+ uint64_t lsrval;
+
+ /* Spin until there is room */
+ do {
+ lsrval = cvmx_read_csr(CVMX_MIO_UARTX_LSR(octeon_uart));
+ } while ((lsrval & 0x20) == 0);
+
+ /* Write the byte */
+ cvmx_write_csr(CVMX_MIO_UARTX_THR(octeon_uart), c);
+ return 1;
+}
+
+void prom_free_prom_memory(void)
+{
+#ifdef CONFIG_CAVIUM_DECODE_RSL
+ cvmx_interrupt_rsl_enable();
+
+ /* Add an interrupt handler for general failures. */
+ if (request_irq(OCTEON_IRQ_RML, octeon_rlm_interrupt, IRQF_SHARED,
+ "RML/RSL", octeon_rlm_interrupt)) {
+ panic("Unable to request_irq(OCTEON_IRQ_RML)\n");
+ }
+#endif
+
+ /* This call is here so that it is performed after any TLB
+ initializations. It needs to be after these in case the
+ CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB option is set */
+ octeon_hal_setup_reserved32();
+}
+
+static struct octeon_cf_data octeon_cf_data;
+
+static int __init octeon_cf_device_init(void)
+{
+ union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
+ unsigned long base_ptr, region_base, region_size;
+ struct platform_device *pd;
+ struct resource cf_resources[3];
+ unsigned int num_resources;
+ int i;
+ int ret = 0;
+
+ /* Setup octeon-cf platform device if present. */
+ base_ptr = 0;
+ if (octeon_bootinfo->major_version == 1
+ && octeon_bootinfo->minor_version >= 1) {
+ if (octeon_bootinfo->compact_flash_common_base_addr)
+ base_ptr =
+ octeon_bootinfo->compact_flash_common_base_addr;
+ } else {
+ base_ptr = 0x1d000800;
+ }
+
+ if (!base_ptr)
+ return ret;
+
+ /* Find CS0 region. */
+ for (i = 0; i < 8; i++) {
+ mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i));
+ region_base = mio_boot_reg_cfg.s.base << 16;
+ region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
+ if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
+ && base_ptr < region_base + region_size)
+ break;
+ }
+ if (i >= 7) {
+ /* i and i + 1 are CS0 and CS1, both must be less than 8. */
+ goto out;
+ }
+ octeon_cf_data.base_region = i;
+ octeon_cf_data.is16bit = mio_boot_reg_cfg.s.width;
+ octeon_cf_data.base_region_bias = base_ptr - region_base;
+ memset(cf_resources, 0, sizeof(cf_resources));
+ num_resources = 0;
+ cf_resources[num_resources].flags = IORESOURCE_MEM;
+ cf_resources[num_resources].start = region_base;
+ cf_resources[num_resources].end = region_base + region_size - 1;
+ num_resources++;
+
+
+ if (!(base_ptr & 0xfffful)) {
+ /*
+ * Boot loader signals availability of DMA (true_ide
+ * mode) by setting low order bits of base_ptr to
+ * zero.
+ */
+
+ /* Asume that CS1 immediately follows. */
+ mio_boot_reg_cfg.u64 =
+ cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1));
+ region_base = mio_boot_reg_cfg.s.base << 16;
+ region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
+ if (!mio_boot_reg_cfg.s.en)
+ goto out;
+
+ cf_resources[num_resources].flags = IORESOURCE_MEM;
+ cf_resources[num_resources].start = region_base;
+ cf_resources[num_resources].end = region_base + region_size - 1;
+ num_resources++;
+
+ octeon_cf_data.dma_engine = 0;
+ cf_resources[num_resources].flags = IORESOURCE_IRQ;
+ cf_resources[num_resources].start = OCTEON_IRQ_BOOTDMA;
+ cf_resources[num_resources].end = OCTEON_IRQ_BOOTDMA;
+ num_resources++;
+ } else {
+ octeon_cf_data.dma_engine = -1;
+ }
+
+ pd = platform_device_alloc("pata_octeon_cf", -1);
+ if (!pd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ pd->dev.platform_data = &octeon_cf_data;
+
+ ret = platform_device_add_resources(pd, cf_resources, num_resources);
+ if (ret)
+ goto fail;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ goto fail;
+
+ return ret;
+fail:
+ platform_device_put(pd);
+out:
+ return ret;
+}
+device_initcall(octeon_cf_device_init);
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
new file mode 100644
index 000000000000..24e0ad63980a
--- /dev/null
+++ b/arch/mips/cavium-octeon/smp.c
@@ -0,0 +1,211 @@
+/*
+ * 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) 2004-2008 Cavium Networks
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/time.h>
+
+#include <asm/octeon/octeon.h>
+
+volatile unsigned long octeon_processor_boot = 0xff;
+volatile unsigned long octeon_processor_sp;
+volatile unsigned long octeon_processor_gp;
+
+static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
+{
+ const int coreid = cvmx_get_core_num();
+ uint64_t action;
+
+ /* Load the mailbox register to figure out what we're supposed to do */
+ action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid));
+
+ /* Clear the mailbox to clear the interrupt */
+ cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
+
+ if (action & SMP_CALL_FUNCTION)
+ smp_call_function_interrupt();
+
+ /* Check if we've been told to flush the icache */
+ if (action & SMP_ICACHE_FLUSH)
+ asm volatile ("synci 0($0)\n");
+ return IRQ_HANDLED;
+}
+
+/**
+ * Cause the function described by call_data to be executed on the passed
+ * cpu. When the function has finished, increment the finished field of
+ * call_data.
+ */
+void octeon_send_ipi_single(int cpu, unsigned int action)
+{
+ int coreid = cpu_logical_map(cpu);
+ /*
+ pr_info("SMP: Mailbox send cpu=%d, coreid=%d, action=%u\n", cpu,
+ coreid, action);
+ */
+ cvmx_write_csr(CVMX_CIU_MBOX_SETX(coreid), action);
+}
+
+static inline void octeon_send_ipi_mask(cpumask_t mask, unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu_mask(i, mask)
+ octeon_send_ipi_single(i, action);
+}
+
+/**
+ * Detect available CPUs, populate phys_cpu_present_map
+ */
+static void octeon_smp_setup(void)
+{
+ const int coreid = cvmx_get_core_num();
+ int cpus;
+ int id;
+
+ int core_mask = octeon_get_boot_coremask();
+
+ cpus_clear(cpu_possible_map);
+ __cpu_number_map[coreid] = 0;
+ __cpu_logical_map[0] = coreid;
+ cpu_set(0, cpu_possible_map);
+
+ cpus = 1;
+ for (id = 0; id < 16; id++) {
+ if ((id != coreid) && (core_mask & (1 << id))) {
+ cpu_set(cpus, cpu_possible_map);
+ __cpu_number_map[id] = cpus;
+ __cpu_logical_map[cpus] = id;
+ cpus++;
+ }
+ }
+}
+
+/**
+ * Firmware CPU startup hook
+ *
+ */
+static void octeon_boot_secondary(int cpu, struct task_struct *idle)
+{
+ int count;
+
+ pr_info("SMP: Booting CPU%02d (CoreId %2d)...\n", cpu,
+ cpu_logical_map(cpu));
+
+ octeon_processor_sp = __KSTK_TOS(idle);
+ octeon_processor_gp = (unsigned long)(task_thread_info(idle));
+ octeon_processor_boot = cpu_logical_map(cpu);
+ mb();
+
+ count = 10000;
+ while (octeon_processor_sp && count) {
+ /* Waiting for processor to get the SP and GP */
+ udelay(1);
+ count--;
+ }
+ if (count == 0)
+ pr_err("Secondary boot timeout\n");
+}
+
+/**
+ * After we've done initial boot, this function is called to allow the
+ * board code to clean up state, if needed
+ */
+static void octeon_init_secondary(void)
+{
+ const int coreid = cvmx_get_core_num();
+ union cvmx_ciu_intx_sum0 interrupt_enable;
+
+ octeon_check_cpu_bist();
+ octeon_init_cvmcount();
+ /*
+ pr_info("SMP: CPU%d (CoreId %lu) started\n", cpu, coreid);
+ */
+ /* Enable Mailbox interrupts to this core. These are the only
+ interrupts allowed on line 3 */
+ cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), 0xffffffff);
+ interrupt_enable.u64 = 0;
+ interrupt_enable.s.mbox = 0x3;
+ cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), interrupt_enable.u64);
+ cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
+ cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
+ /* Enable core interrupt processing for 2,3 and 7 */
+ set_c0_status(0x8c01);
+}
+
+/**
+ * Callout to firmware before smp_init
+ *
+ */
+void octeon_prepare_cpus(unsigned int max_cpus)
+{
+ cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
+ if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_SHARED,
+ "mailbox0", mailbox_interrupt)) {
+ panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
+ }
+ if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_SHARED,
+ "mailbox1", mailbox_interrupt)) {
+ panic("Cannot request_irq(OCTEON_IRQ_MBOX1)\n");
+ }
+}
+
+/**
+ * Last chance for the board code to finish SMP initialization before
+ * the CPU is "online".
+ */
+static void octeon_smp_finish(void)
+{
+#ifdef CONFIG_CAVIUM_GDB
+ unsigned long tmp;
+ /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
+ to be not masked by this core so we know the signal is received by
+ someone */
+ asm volatile ("dmfc0 %0, $22\n"
+ "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
+#endif
+
+ octeon_user_io_init();
+
+ /* to generate the first CPU timer interrupt */
+ write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
+}
+
+/**
+ * Hook for after all CPUs are online
+ */
+static void octeon_cpus_done(void)
+{
+#ifdef CONFIG_CAVIUM_GDB
+ unsigned long tmp;
+ /* Pulse MCD0 signal on Ctrl-C to stop all the cores. Also set the MCD0
+ to be not masked by this core so we know the signal is received by
+ someone */
+ asm volatile ("dmfc0 %0, $22\n"
+ "ori %0, %0, 0x9100\n" "dmtc0 %0, $22\n" : "=r" (tmp));
+#endif
+}
+
+struct plat_smp_ops octeon_smp_ops = {
+ .send_ipi_single = octeon_send_ipi_single,
+ .send_ipi_mask = octeon_send_ipi_mask,
+ .init_secondary = octeon_init_secondary,
+ .smp_finish = octeon_smp_finish,
+ .cpus_done = octeon_cpus_done,
+ .boot_secondary = octeon_boot_secondary,
+ .smp_setup = octeon_smp_setup,
+ .prepare_cpus = octeon_prepare_cpus,
+};
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index a3bbbf067a3b..783da855a2e3 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -959,7 +959,7 @@ CONFIG_I2C_SIBYTE=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_LEGACY=y
CONFIG_SENSORS_PCF8574=y
# CONFIG_PCF8575 is not set
CONFIG_SENSORS_PCF8591=y
diff --git a/arch/mips/configs/cavium-octeon_defconfig b/arch/mips/configs/cavium-octeon_defconfig
new file mode 100644
index 000000000000..7afaa28a3768
--- /dev/null
+++ b/arch/mips/configs/cavium-octeon_defconfig
@@ -0,0 +1,943 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28-rc6
+# Wed Dec 3 11:00:58 2008
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MACH_EMMA is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD=y
+CONFIG_CAVIUM_OCTEON_SPECIFIC_OPTIONS=y
+# CONFIG_CAVIUM_OCTEON_2ND_KERNEL is not set
+CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED=y
+CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE=2
+CONFIG_CAVIUM_OCTEON_LOCK_L2=y
+CONFIG_CAVIUM_OCTEON_LOCK_L2_TLB=y
+CONFIG_CAVIUM_OCTEON_LOCK_L2_EXCEPTION=y
+CONFIG_CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT=y
+CONFIG_CAVIUM_OCTEON_LOCK_L2_INTERRUPT=y
+CONFIG_CAVIUM_OCTEON_LOCK_L2_MEMCPY=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_COHERENT=y
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_OCTEON=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_MIPS_L1_CACHE_SHIFT=7
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_CPU_CAVIUM_OCTEON=y
+CONFIG_WEAK_ORDERING=y
+CONFIG_WEAK_REORDERING_BEYOND_LLSC=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_64BIT_PHYS_ADDR=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_SMP=y
+CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_NR_CPUS_DEFAULT_16=y
+CONFIG_NR_CPUS=16
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_KEXEC is not set
+CONFIG_SECCOMP=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PROBE_INITRD_HEADER is not set
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_STAGING_EXCLUDE_BUILD=y
+
+#
+# File systems
+#
+# 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_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_RUNTIME_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index 634bb4eaf132..fea9bc9865a3 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -996,7 +996,7 @@ CONFIG_I2C_CHARDEV=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/mips/configs/fulong_defconfig b/arch/mips/configs/fulong_defconfig
index b6698a232ae9..786a9bc9a696 100644
--- a/arch/mips/configs/fulong_defconfig
+++ b/arch/mips/configs/fulong_defconfig
@@ -1006,8 +1006,8 @@ CONFIG_I2C_VIAPRO=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 34ea319be94c..f2baea3039bb 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -53,7 +53,7 @@ CONFIG_GENERIC_TIME=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_ARC=y
-CONFIG_DMA_IP27=y
+CONFIG_DMA_COHERENT=y
CONFIG_EARLY_PRINTK=y
CONFIG_SYS_HAS_EARLY_PRINTK=y
# CONFIG_NO_IOPORT is not set
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig
index dd13db4d0fb9..84d6491b3d41 100644
--- a/arch/mips/configs/msp71xx_defconfig
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -929,7 +929,7 @@ CONFIG_I2C_PMCMSP=y
#
# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_DS1374 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
CONFIG_PMCTWILED=y
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index db9272677aa2..8426d3b9501c 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -1845,7 +1845,7 @@ CONFIG_I2C_VOODOO3=m
CONFIG_SENSORS_DS1337=m
CONFIG_SENSORS_DS1374=m
# CONFIG_DS1682 is not set
-CONFIG_SENSORS_EEPROM=m
+CONFIG_EEPROM_LEGACY=m
CONFIG_SENSORS_PCF8574=m
CONFIG_SENSORS_PCA9539=m
CONFIG_SENSORS_PCF8591=m
@@ -1872,7 +1872,7 @@ CONFIG_SPI_BUTTERFLY=m
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_W1=m
diff --git a/arch/mips/configs/pnx8335-stb225_defconfig b/arch/mips/configs/pnx8335-stb225_defconfig
index d9536522cff5..2728caa6c2fb 100644
--- a/arch/mips/configs/pnx8335-stb225_defconfig
+++ b/arch/mips/configs/pnx8335-stb225_defconfig
@@ -640,8 +640,8 @@ CONFIG_I2C_CHARDEV=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/mips/configs/rbtx49xx_defconfig b/arch/mips/configs/rbtx49xx_defconfig
index c7c0864b8ce9..83d5c58662c8 100644
--- a/arch/mips/configs/rbtx49xx_defconfig
+++ b/arch/mips/configs/rbtx49xx_defconfig
@@ -522,7 +522,7 @@ CONFIG_SPI_TXX9=y
#
# SPI Protocol Masters
#
-CONFIG_SPI_AT25=y
+CONFIG_EEPROM_AT25=y
# CONFIG_SPI_TLE62X0 is not set
CONFIG_HAVE_GPIO_LIB=y
diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h
index 1232be3885b0..1b332e15ab52 100644
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -15,13 +15,12 @@
#define _ASM_ATOMIC_H
#include <linux/irqflags.h>
+#include <linux/types.h>
#include <asm/barrier.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
#include <asm/system.h>
-typedef struct { volatile int counter; } atomic_t;
-
#define ATOMIC_INIT(i) { (i) }
/*
@@ -51,7 +50,7 @@ typedef struct { volatile int counter; } atomic_t;
static __inline__ void atomic_add(int i, atomic_t * v)
{
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -63,7 +62,7 @@ static __inline__ void atomic_add(int i, atomic_t * v)
: "=&r" (temp), "=m" (v->counter)
: "Ir" (i), "m" (v->counter));
} else if (cpu_has_llsc) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -96,7 +95,7 @@ static __inline__ void atomic_add(int i, atomic_t * v)
static __inline__ void atomic_sub(int i, atomic_t * v)
{
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -108,7 +107,7 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
: "=&r" (temp), "=m" (v->counter)
: "Ir" (i), "m" (v->counter));
} else if (cpu_has_llsc) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -136,12 +135,12 @@ static __inline__ void atomic_sub(int i, atomic_t * v)
*/
static __inline__ int atomic_add_return(int i, atomic_t * v)
{
- unsigned long result;
+ int result;
smp_llsc_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -155,7 +154,7 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
: "Ir" (i), "m" (v->counter)
: "memory");
} else if (cpu_has_llsc) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -188,12 +187,12 @@ static __inline__ int atomic_add_return(int i, atomic_t * v)
static __inline__ int atomic_sub_return(int i, atomic_t * v)
{
- unsigned long result;
+ int result;
smp_llsc_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -207,7 +206,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
: "Ir" (i), "m" (v->counter)
: "memory");
} else if (cpu_has_llsc) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -248,12 +247,12 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v)
*/
static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
{
- unsigned long result;
+ int result;
smp_llsc_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -271,7 +270,7 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
: "Ir" (i), "m" (v->counter)
: "memory");
} else if (cpu_has_llsc) {
- unsigned long temp;
+ int temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -404,8 +403,6 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#ifdef CONFIG_64BIT
-typedef struct { volatile long counter; } atomic64_t;
-
#define ATOMIC64_INIT(i) { (i) }
/*
@@ -432,7 +429,7 @@ typedef struct { volatile long counter; } atomic64_t;
static __inline__ void atomic64_add(long i, atomic64_t * v)
{
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -444,7 +441,7 @@ static __inline__ void atomic64_add(long i, atomic64_t * v)
: "=&r" (temp), "=m" (v->counter)
: "Ir" (i), "m" (v->counter));
} else if (cpu_has_llsc) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -477,7 +474,7 @@ static __inline__ void atomic64_add(long i, atomic64_t * v)
static __inline__ void atomic64_sub(long i, atomic64_t * v)
{
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -489,7 +486,7 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
: "=&r" (temp), "=m" (v->counter)
: "Ir" (i), "m" (v->counter));
} else if (cpu_has_llsc) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -517,12 +514,12 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
*/
static __inline__ long atomic64_add_return(long i, atomic64_t * v)
{
- unsigned long result;
+ long result;
smp_llsc_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -536,7 +533,7 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
: "Ir" (i), "m" (v->counter)
: "memory");
} else if (cpu_has_llsc) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -569,12 +566,12 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v)
static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
{
- unsigned long result;
+ long result;
smp_llsc_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -588,7 +585,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
: "Ir" (i), "m" (v->counter)
: "memory");
} else if (cpu_has_llsc) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -629,12 +626,12 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
*/
static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
{
- unsigned long result;
+ long result;
smp_llsc_mb();
if (cpu_has_llsc && R10000_LLSC_WAR) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -652,7 +649,7 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
: "Ir" (i), "m" (v->counter)
: "memory");
} else if (cpu_has_llsc) {
- unsigned long temp;
+ long temp;
__asm__ __volatile__(
" .set mips3 \n"
diff --git a/arch/mips/include/asm/byteorder.h b/arch/mips/include/asm/byteorder.h
index 33790b9e0cc0..9579051ff1c7 100644
--- a/arch/mips/include/asm/byteorder.h
+++ b/arch/mips/include/asm/byteorder.h
@@ -8,60 +8,12 @@
#ifndef _ASM_BYTEORDER_H
#define _ASM_BYTEORDER_H
-#include <linux/compiler.h>
-#include <asm/types.h>
-
#if defined(__MIPSEB__)
-# define __BIG_ENDIAN
+#include <linux/byteorder/big_endian.h>
#elif defined(__MIPSEL__)
-# define __LITTLE_ENDIAN
+#include <linux/byteorder/little_endian.h>
#else
# error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???"
#endif
-#define __SWAB_64_THRU_32__
-
-#ifdef CONFIG_CPU_MIPSR2
-
-static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
-{
- __asm__(
- " wsbh %0, %1 \n"
- : "=r" (x)
- : "r" (x));
-
- return x;
-}
-#define __arch_swab16 __arch_swab16
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
-{
- __asm__(
- " wsbh %0, %1 \n"
- " rotr %0, %0, 16 \n"
- : "=r" (x)
- : "r" (x));
-
- return x;
-}
-#define __arch_swab32 __arch_swab32
-
-#ifdef CONFIG_CPU_MIPS64_R2
-static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
-{
- __asm__(
- " dsbh %0, %1\n"
- " dshd %0, %0"
- : "=r" (x)
- : "r" (x));
-
- return x;
-}
-#define __arch_swab64 __arch_swab64
-#endif /* CONFIG_CPU_MIPS64_R2 */
-
-#endif /* CONFIG_CPU_MIPSR2 */
-
-#include <linux/byteorder.h>
-
#endif /* _ASM_BYTEORDER_H */
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 12d12dfe73c0..a0d14f85b781 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -38,6 +38,9 @@
#ifndef cpu_has_tx39_cache
#define cpu_has_tx39_cache (cpu_data[0].options & MIPS_CPU_TX39_CACHE)
#endif
+#ifndef cpu_has_octeon_cache
+#define cpu_has_octeon_cache 0
+#endif
#ifndef cpu_has_fpu
#define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU)
#define raw_cpu_has_fpu (raw_current_cpu_data.options & MIPS_CPU_FPU)
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 229a786101d9..c018727c7ddc 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -33,6 +33,7 @@
#define PRID_COMP_TOSHIBA 0x070000
#define PRID_COMP_LSI 0x080000
#define PRID_COMP_LEXRA 0x0b0000
+#define PRID_COMP_CAVIUM 0x0d0000
/*
@@ -114,6 +115,18 @@
#define PRID_IMP_BCM3302 0x9000
/*
+ * These are the PRID's for when 23:16 == PRID_COMP_CAVIUM
+ */
+
+#define PRID_IMP_CAVIUM_CN38XX 0x0000
+#define PRID_IMP_CAVIUM_CN31XX 0x0100
+#define PRID_IMP_CAVIUM_CN30XX 0x0200
+#define PRID_IMP_CAVIUM_CN58XX 0x0300
+#define PRID_IMP_CAVIUM_CN56XX 0x0400
+#define PRID_IMP_CAVIUM_CN50XX 0x0600
+#define PRID_IMP_CAVIUM_CN52XX 0x0700
+
+/*
* Definitions for 7:0 on legacy processors
*/
@@ -203,6 +216,7 @@ enum cpu_type_enum {
* MIPS64 class processors
*/
CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
+ CPU_CAVIUM_OCTEON,
CPU_LAST
};
diff --git a/arch/mips/include/asm/hazards.h b/arch/mips/include/asm/hazards.h
index 2de638f84c86..43baed16a109 100644
--- a/arch/mips/include/asm/hazards.h
+++ b/arch/mips/include/asm/hazards.h
@@ -42,7 +42,7 @@ ASMMACRO(_ehb,
/*
* TLB hazards
*/
-#if defined(CONFIG_CPU_MIPSR2)
+#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
/*
* MIPSR2 defines ehb for hazard avoidance
@@ -138,7 +138,7 @@ do { \
__instruction_hazard(); \
} while (0)
-#elif defined(CONFIG_CPU_R10000)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_CAVIUM_OCTEON)
/*
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 501a40b9f18d..436878e4e063 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -295,6 +295,12 @@ static inline void iounmap(const volatile void __iomem *addr)
#undef __IS_KSEG1
}
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define war_octeon_io_reorder_wmb() wmb()
+#else
+#define war_octeon_io_reorder_wmb() do { } while (0)
+#endif
+
#define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq) \
\
static inline void pfx##write##bwlq(type val, \
@@ -303,6 +309,8 @@ static inline void pfx##write##bwlq(type val, \
volatile type *__mem; \
type __val; \
\
+ war_octeon_io_reorder_wmb(); \
+ \
__mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem)); \
\
__val = pfx##ioswab##bwlq(__mem, val); \
@@ -370,6 +378,8 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \
volatile type *__addr; \
type __val; \
\
+ war_octeon_io_reorder_wmb(); \
+ \
__addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
\
__val = pfx##ioswab##bwlq(__addr, val); \
@@ -504,8 +514,12 @@ BUILDSTRING(q, u64)
#endif
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define mmiowb() wmb()
+#else
/* Depends on MIPS II instruction set */
#define mmiowb() asm volatile ("sync" ::: "memory")
+#endif
static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
{
diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h
index a58f0eecc68f..abc62aa744ac 100644
--- a/arch/mips/include/asm/irq.h
+++ b/arch/mips/include/asm/irq.h
@@ -49,7 +49,8 @@ static inline void smtc_im_ack_irq(unsigned int irq)
#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
#include <linux/cpumask.h>
-extern void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity);
+extern void plat_set_irq_affinity(unsigned int irq,
+ const struct cpumask *affinity);
extern void smtc_forward_irq(unsigned int irq);
/*
diff --git a/arch/mips/include/asm/mach-au1x00/au1000.h b/arch/mips/include/asm/mach-au1x00/au1000.h
index 0d302bad4492..62f91f50b5b5 100644
--- a/arch/mips/include/asm/mach-au1x00/au1000.h
+++ b/arch/mips/include/asm/mach-au1x00/au1000.h
@@ -91,14 +91,57 @@ static inline u32 au_readl(unsigned long reg)
return *(volatile u32 *)reg;
}
+/* Early Au1000 have a write-only SYS_CPUPLL register. */
+static inline int au1xxx_cpu_has_pll_wo(void)
+{
+ switch (read_c0_prid()) {
+ case 0x00030100: /* Au1000 DA */
+ case 0x00030201: /* Au1000 HA */
+ case 0x00030202: /* Au1000 HB */
+ return 1;
+ }
+ return 0;
+}
+
+/* does CPU need CONFIG[OD] set to fix tons of errata? */
+static inline int au1xxx_cpu_needs_config_od(void)
+{
+ /*
+ * c0_config.od (bit 19) was write only (and read as 0) on the
+ * early revisions of Alchemy SOCs. It disables the bus trans-
+ * action overlapping and needs to be set to fix various errata.
+ */
+ switch (read_c0_prid()) {
+ case 0x00030100: /* Au1000 DA */
+ case 0x00030201: /* Au1000 HA */
+ case 0x00030202: /* Au1000 HB */
+ case 0x01030200: /* Au1500 AB */
+ /*
+ * Au1100/Au1200 errata actually keep silence about this bit,
+ * so we set it just in case for those revisions that require
+ * it to be set according to the (now gone) cpu_table.
+ */
+ case 0x02030200: /* Au1100 AB */
+ case 0x02030201: /* Au1100 BA */
+ case 0x02030202: /* Au1100 BC */
+ case 0x04030201: /* Au1200 AC */
+ return 1;
+ }
+ return 0;
+}
/* arch/mips/au1000/common/clocks.c */
extern void set_au1x00_speed(unsigned int new_freq);
extern unsigned int get_au1x00_speed(void);
extern void set_au1x00_uart_baud_base(unsigned long new_baud_base);
extern unsigned long get_au1x00_uart_baud_base(void);
-extern void set_au1x00_lcd_clock(void);
-extern unsigned int get_au1x00_lcd_clock(void);
+extern unsigned long au1xxx_calc_clock(void);
+
+/* PM: arch/mips/alchemy/common/sleeper.S, power.c, irq.c */
+void au1xxx_save_and_sleep(void);
+void au_sleep(void);
+void save_au1xxx_intctl(void);
+void restore_au1xxx_intctl(void);
/*
* Every board describes its IRQ mapping with this table.
@@ -109,10 +152,11 @@ struct au1xxx_irqmap {
int im_request;
};
-/*
- * init_IRQ looks for a table with this name.
- */
-extern struct au1xxx_irqmap au1xxx_irq_map[];
+/* core calls this function to let boards initialize other IRQ sources */
+void board_init_irq(void);
+
+/* boards call this to register additional (GPIO) interrupts */
+void au1xxx_setup_irqmap(struct au1xxx_irqmap *map, int count);
#endif /* !defined (_LANGUAGE_ASSEMBLY) */
@@ -505,15 +549,6 @@ extern struct au1xxx_irqmap au1xxx_irq_map[];
#define IC1_TESTBIT 0xB1800080
-/* Interrupt Configuration Modes */
-#define INTC_INT_DISABLED 0x0
-#define INTC_INT_RISE_EDGE 0x1
-#define INTC_INT_FALL_EDGE 0x2
-#define INTC_INT_RISE_AND_FALL_EDGE 0x3
-#define INTC_INT_HIGH_LEVEL 0x5
-#define INTC_INT_LOW_LEVEL 0x6
-#define INTC_INT_HIGH_AND_LOW_LEVEL 0x7
-
/* Interrupt Numbers */
/* Au1000 */
#ifdef CONFIG_SOC_AU1000
@@ -1525,6 +1560,10 @@ enum soc_au1200_ints {
#define SYS_SLPPWR 0xB1900078
#define SYS_SLEEP 0xB190007C
+#define SYS_WAKEMSK_D2 (1 << 9)
+#define SYS_WAKEMSK_M2 (1 << 8)
+#define SYS_WAKEMSK_GPIO(x) (1 << (x))
+
/* Clock Controller */
#define SYS_FREQCTRL0 0xB1900020
# define SYS_FC_FRDIV2_BIT 22
@@ -1749,24 +1788,4 @@ static AU1X00_SYS * const sys = (AU1X00_SYS *)SYS_BASE;
#endif
-/*
- * Processor information based on PRID.
- * Copied from PowerPC.
- */
-#ifndef _LANGUAGE_ASSEMBLY
-struct cpu_spec {
- /* CPU is matched via (PRID & prid_mask) == prid_value */
- unsigned int prid_mask;
- unsigned int prid_value;
-
- char *cpu_name;
- unsigned char cpu_od; /* Set Config[OD] */
- unsigned char cpu_bclk; /* Enable BCLK switching */
- unsigned char cpu_pll_wo; /* sys_cpupll reg. write-only */
-};
-
-extern struct cpu_spec cpu_specs[];
-extern struct cpu_spec *cur_cpu_spec[];
-#endif
-
#endif
diff --git a/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
index 44a67bf05dc1..06f68f43800a 100644
--- a/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
+++ b/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
@@ -357,6 +357,11 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr);
u32 au1xxx_ddma_add_device(dbdev_tab_t *dev);
extern void au1xxx_ddma_del_device(u32 devid);
void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp);
+#ifdef CONFIG_PM
+void au1xxx_dbdma_suspend(void);
+void au1xxx_dbdma_resume(void);
+#endif
+
/*
* Some compatibilty macros -- needed to make changes to API
diff --git a/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
new file mode 100644
index 000000000000..04ce6e6569da
--- /dev/null
+++ b/arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
@@ -0,0 +1,78 @@
+/*
+ * 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) 2004 Cavium Networks
+ */
+#ifndef __ASM_MACH_CAVIUM_OCTEON_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_CAVIUM_OCTEON_CPU_FEATURE_OVERRIDES_H
+
+#include <linux/types.h>
+#include <asm/mipsregs.h>
+
+/*
+ * Cavium Octeons are MIPS64v2 processors
+ */
+#define cpu_dcache_line_size() 128
+#define cpu_icache_line_size() 128
+
+
+#define cpu_has_4kex 1
+#define cpu_has_3k_cache 0
+#define cpu_has_4k_cache 0
+#define cpu_has_tx39_cache 0
+#define cpu_has_fpu 0
+#define cpu_has_counter 1
+#define cpu_has_watch 1
+#define cpu_has_divec 1
+#define cpu_has_vce 0
+#define cpu_has_cache_cdex_p 0
+#define cpu_has_cache_cdex_s 0
+#define cpu_has_prefetch 1
+
+/*
+ * We should disable LL/SC on non SMP systems as it is faster to
+ * disable interrupts for atomic access than a LL/SC. Unfortunatly we
+ * cannot as this breaks asm/futex.h
+ */
+#define cpu_has_llsc 1
+#define cpu_has_vtag_icache 1
+#define cpu_has_dc_aliases 0
+#define cpu_has_ic_fills_f_dc 0
+#define cpu_has_64bits 1
+#define cpu_has_octeon_cache 1
+#define cpu_has_saa octeon_has_saa()
+#define cpu_has_mips32r1 0
+#define cpu_has_mips32r2 0
+#define cpu_has_mips64r1 0
+#define cpu_has_mips64r2 1
+#define cpu_has_dsp 0
+#define cpu_has_mipsmt 0
+#define cpu_has_userlocal 0
+#define cpu_has_vint 0
+#define cpu_has_veic 0
+#define ARCH_HAS_READ_CURRENT_TIMER 1
+#define ARCH_HAS_IRQ_PER_CPU 1
+#define ARCH_HAS_SPINLOCK_PREFETCH 1
+#define spin_lock_prefetch(x) prefetch(x)
+#define PREFETCH_STRIDE 128
+
+static inline int read_current_timer(unsigned long *result)
+{
+ asm volatile ("rdhwr %0,$31\n"
+#ifndef CONFIG_64BIT
+ "\tsll %0, 0"
+#endif
+ : "=r" (*result));
+ return 0;
+}
+
+static inline int octeon_has_saa(void)
+{
+ int id;
+ asm volatile ("mfc0 %0, $15,0" : "=r" (id));
+ return id >= 0x000d0300;
+}
+
+#endif
diff --git a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
new file mode 100644
index 000000000000..f30fce92aabb
--- /dev/null
+++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
@@ -0,0 +1,64 @@
+/*
+ * 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 Ralf Baechle <ralf@linux-mips.org>
+ *
+ *
+ * Similar to mach-generic/dma-coherence.h except
+ * plat_device_is_coherent hard coded to return 1.
+ *
+ */
+#ifndef __ASM_MACH_CAVIUM_OCTEON_DMA_COHERENCE_H
+#define __ASM_MACH_CAVIUM_OCTEON_DMA_COHERENCE_H
+
+struct device;
+
+dma_addr_t octeon_map_dma_mem(struct device *, void *, size_t);
+void octeon_unmap_dma_mem(struct device *, dma_addr_t);
+
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+ size_t size)
+{
+ return octeon_map_dma_mem(dev, addr, size);
+}
+
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+ struct page *page)
+{
+ return octeon_map_dma_mem(dev, page_address(page), PAGE_SIZE);
+}
+
+static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+ return dma_addr;
+}
+
+static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+{
+ octeon_unmap_dma_mem(dev, dma_addr);
+}
+
+static inline int plat_dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline void plat_extra_sync_for_device(struct device *dev)
+{
+ mb();
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+ return 1;
+}
+
+static inline int plat_dma_mapping_error(struct device *dev,
+ dma_addr_t dma_addr)
+{
+ return dma_addr == -1;
+}
+
+#endif /* __ASM_MACH_CAVIUM_OCTEON_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h
new file mode 100644
index 000000000000..d32220fbf4f1
--- /dev/null
+++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h
@@ -0,0 +1,244 @@
+/*
+ * 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) 2004-2008 Cavium Networks
+ */
+#ifndef __OCTEON_IRQ_H__
+#define __OCTEON_IRQ_H__
+
+#define NR_IRQS OCTEON_IRQ_LAST
+#define MIPS_CPU_IRQ_BASE OCTEON_IRQ_SW0
+
+/* 0 - 7 represent the i8259 master */
+#define OCTEON_IRQ_I8259M0 0
+#define OCTEON_IRQ_I8259M1 1
+#define OCTEON_IRQ_I8259M2 2
+#define OCTEON_IRQ_I8259M3 3
+#define OCTEON_IRQ_I8259M4 4
+#define OCTEON_IRQ_I8259M5 5
+#define OCTEON_IRQ_I8259M6 6
+#define OCTEON_IRQ_I8259M7 7
+/* 8 - 15 represent the i8259 slave */
+#define OCTEON_IRQ_I8259S0 8
+#define OCTEON_IRQ_I8259S1 9
+#define OCTEON_IRQ_I8259S2 10
+#define OCTEON_IRQ_I8259S3 11
+#define OCTEON_IRQ_I8259S4 12
+#define OCTEON_IRQ_I8259S5 13
+#define OCTEON_IRQ_I8259S6 14
+#define OCTEON_IRQ_I8259S7 15
+/* 16 - 23 represent the 8 MIPS standard interrupt sources */
+#define OCTEON_IRQ_SW0 16
+#define OCTEON_IRQ_SW1 17
+#define OCTEON_IRQ_CIU0 18
+#define OCTEON_IRQ_CIU1 19
+#define OCTEON_IRQ_CIU4 20
+#define OCTEON_IRQ_5 21
+#define OCTEON_IRQ_PERF 22
+#define OCTEON_IRQ_TIMER 23
+/* 24 - 87 represent the sources in CIU_INTX_EN0 */
+#define OCTEON_IRQ_WORKQ0 24
+#define OCTEON_IRQ_WORKQ1 25
+#define OCTEON_IRQ_WORKQ2 26
+#define OCTEON_IRQ_WORKQ3 27
+#define OCTEON_IRQ_WORKQ4 28
+#define OCTEON_IRQ_WORKQ5 29
+#define OCTEON_IRQ_WORKQ6 30
+#define OCTEON_IRQ_WORKQ7 31
+#define OCTEON_IRQ_WORKQ8 32
+#define OCTEON_IRQ_WORKQ9 33
+#define OCTEON_IRQ_WORKQ10 34
+#define OCTEON_IRQ_WORKQ11 35
+#define OCTEON_IRQ_WORKQ12 36
+#define OCTEON_IRQ_WORKQ13 37
+#define OCTEON_IRQ_WORKQ14 38
+#define OCTEON_IRQ_WORKQ15 39
+#define OCTEON_IRQ_GPIO0 40
+#define OCTEON_IRQ_GPIO1 41
+#define OCTEON_IRQ_GPIO2 42
+#define OCTEON_IRQ_GPIO3 43
+#define OCTEON_IRQ_GPIO4 44
+#define OCTEON_IRQ_GPIO5 45
+#define OCTEON_IRQ_GPIO6 46
+#define OCTEON_IRQ_GPIO7 47
+#define OCTEON_IRQ_GPIO8 48
+#define OCTEON_IRQ_GPIO9 49
+#define OCTEON_IRQ_GPIO10 50
+#define OCTEON_IRQ_GPIO11 51
+#define OCTEON_IRQ_GPIO12 52
+#define OCTEON_IRQ_GPIO13 53
+#define OCTEON_IRQ_GPIO14 54
+#define OCTEON_IRQ_GPIO15 55
+#define OCTEON_IRQ_MBOX0 56
+#define OCTEON_IRQ_MBOX1 57
+#define OCTEON_IRQ_UART0 58
+#define OCTEON_IRQ_UART1 59
+#define OCTEON_IRQ_PCI_INT0 60
+#define OCTEON_IRQ_PCI_INT1 61
+#define OCTEON_IRQ_PCI_INT2 62
+#define OCTEON_IRQ_PCI_INT3 63
+#define OCTEON_IRQ_PCI_MSI0 64
+#define OCTEON_IRQ_PCI_MSI1 65
+#define OCTEON_IRQ_PCI_MSI2 66
+#define OCTEON_IRQ_PCI_MSI3 67
+#define OCTEON_IRQ_RESERVED68 68 /* Summary of CIU_INT_SUM1 */
+#define OCTEON_IRQ_TWSI 69
+#define OCTEON_IRQ_RML 70
+#define OCTEON_IRQ_TRACE 71
+#define OCTEON_IRQ_GMX_DRP0 72
+#define OCTEON_IRQ_GMX_DRP1 73
+#define OCTEON_IRQ_IPD_DRP 74
+#define OCTEON_IRQ_KEY_ZERO 75
+#define OCTEON_IRQ_TIMER0 76
+#define OCTEON_IRQ_TIMER1 77
+#define OCTEON_IRQ_TIMER2 78
+#define OCTEON_IRQ_TIMER3 79
+#define OCTEON_IRQ_USB0 80
+#define OCTEON_IRQ_PCM 81
+#define OCTEON_IRQ_MPI 82
+#define OCTEON_IRQ_TWSI2 83
+#define OCTEON_IRQ_POWIQ 84
+#define OCTEON_IRQ_IPDPPTHR 85
+#define OCTEON_IRQ_MII0 86
+#define OCTEON_IRQ_BOOTDMA 87
+/* 88 - 151 represent the sources in CIU_INTX_EN1 */
+#define OCTEON_IRQ_WDOG0 88
+#define OCTEON_IRQ_WDOG1 89
+#define OCTEON_IRQ_WDOG2 90
+#define OCTEON_IRQ_WDOG3 91
+#define OCTEON_IRQ_WDOG4 92
+#define OCTEON_IRQ_WDOG5 93
+#define OCTEON_IRQ_WDOG6 94
+#define OCTEON_IRQ_WDOG7 95
+#define OCTEON_IRQ_WDOG8 96
+#define OCTEON_IRQ_WDOG9 97
+#define OCTEON_IRQ_WDOG10 98
+#define OCTEON_IRQ_WDOG11 99
+#define OCTEON_IRQ_WDOG12 100
+#define OCTEON_IRQ_WDOG13 101
+#define OCTEON_IRQ_WDOG14 102
+#define OCTEON_IRQ_WDOG15 103
+#define OCTEON_IRQ_UART2 104
+#define OCTEON_IRQ_USB1 105
+#define OCTEON_IRQ_MII1 106
+#define OCTEON_IRQ_RESERVED107 107
+#define OCTEON_IRQ_RESERVED108 108
+#define OCTEON_IRQ_RESERVED109 109
+#define OCTEON_IRQ_RESERVED110 110
+#define OCTEON_IRQ_RESERVED111 111
+#define OCTEON_IRQ_RESERVED112 112
+#define OCTEON_IRQ_RESERVED113 113
+#define OCTEON_IRQ_RESERVED114 114
+#define OCTEON_IRQ_RESERVED115 115
+#define OCTEON_IRQ_RESERVED116 116
+#define OCTEON_IRQ_RESERVED117 117
+#define OCTEON_IRQ_RESERVED118 118
+#define OCTEON_IRQ_RESERVED119 119
+#define OCTEON_IRQ_RESERVED120 120
+#define OCTEON_IRQ_RESERVED121 121
+#define OCTEON_IRQ_RESERVED122 122
+#define OCTEON_IRQ_RESERVED123 123
+#define OCTEON_IRQ_RESERVED124 124
+#define OCTEON_IRQ_RESERVED125 125
+#define OCTEON_IRQ_RESERVED126 126
+#define OCTEON_IRQ_RESERVED127 127
+#define OCTEON_IRQ_RESERVED128 128
+#define OCTEON_IRQ_RESERVED129 129
+#define OCTEON_IRQ_RESERVED130 130
+#define OCTEON_IRQ_RESERVED131 131
+#define OCTEON_IRQ_RESERVED132 132
+#define OCTEON_IRQ_RESERVED133 133
+#define OCTEON_IRQ_RESERVED134 134
+#define OCTEON_IRQ_RESERVED135 135
+#define OCTEON_IRQ_RESERVED136 136
+#define OCTEON_IRQ_RESERVED137 137
+#define OCTEON_IRQ_RESERVED138 138
+#define OCTEON_IRQ_RESERVED139 139
+#define OCTEON_IRQ_RESERVED140 140
+#define OCTEON_IRQ_RESERVED141 141
+#define OCTEON_IRQ_RESERVED142 142
+#define OCTEON_IRQ_RESERVED143 143
+#define OCTEON_IRQ_RESERVED144 144
+#define OCTEON_IRQ_RESERVED145 145
+#define OCTEON_IRQ_RESERVED146 146
+#define OCTEON_IRQ_RESERVED147 147
+#define OCTEON_IRQ_RESERVED148 148
+#define OCTEON_IRQ_RESERVED149 149
+#define OCTEON_IRQ_RESERVED150 150
+#define OCTEON_IRQ_RESERVED151 151
+
+#ifdef CONFIG_PCI_MSI
+/* 152 - 215 represent the MSI interrupts 0-63 */
+#define OCTEON_IRQ_MSI_BIT0 152
+#define OCTEON_IRQ_MSI_BIT1 153
+#define OCTEON_IRQ_MSI_BIT2 154
+#define OCTEON_IRQ_MSI_BIT3 155
+#define OCTEON_IRQ_MSI_BIT4 156
+#define OCTEON_IRQ_MSI_BIT5 157
+#define OCTEON_IRQ_MSI_BIT6 158
+#define OCTEON_IRQ_MSI_BIT7 159
+#define OCTEON_IRQ_MSI_BIT8 160
+#define OCTEON_IRQ_MSI_BIT9 161
+#define OCTEON_IRQ_MSI_BIT10 162
+#define OCTEON_IRQ_MSI_BIT11 163
+#define OCTEON_IRQ_MSI_BIT12 164
+#define OCTEON_IRQ_MSI_BIT13 165
+#define OCTEON_IRQ_MSI_BIT14 166
+#define OCTEON_IRQ_MSI_BIT15 167
+#define OCTEON_IRQ_MSI_BIT16 168
+#define OCTEON_IRQ_MSI_BIT17 169
+#define OCTEON_IRQ_MSI_BIT18 170
+#define OCTEON_IRQ_MSI_BIT19 171
+#define OCTEON_IRQ_MSI_BIT20 172
+#define OCTEON_IRQ_MSI_BIT21 173
+#define OCTEON_IRQ_MSI_BIT22 174
+#define OCTEON_IRQ_MSI_BIT23 175
+#define OCTEON_IRQ_MSI_BIT24 176
+#define OCTEON_IRQ_MSI_BIT25 177
+#define OCTEON_IRQ_MSI_BIT26 178
+#define OCTEON_IRQ_MSI_BIT27 179
+#define OCTEON_IRQ_MSI_BIT28 180
+#define OCTEON_IRQ_MSI_BIT29 181
+#define OCTEON_IRQ_MSI_BIT30 182
+#define OCTEON_IRQ_MSI_BIT31 183
+#define OCTEON_IRQ_MSI_BIT32 184
+#define OCTEON_IRQ_MSI_BIT33 185
+#define OCTEON_IRQ_MSI_BIT34 186
+#define OCTEON_IRQ_MSI_BIT35 187
+#define OCTEON_IRQ_MSI_BIT36 188
+#define OCTEON_IRQ_MSI_BIT37 189
+#define OCTEON_IRQ_MSI_BIT38 190
+#define OCTEON_IRQ_MSI_BIT39 191
+#define OCTEON_IRQ_MSI_BIT40 192
+#define OCTEON_IRQ_MSI_BIT41 193
+#define OCTEON_IRQ_MSI_BIT42 194
+#define OCTEON_IRQ_MSI_BIT43 195
+#define OCTEON_IRQ_MSI_BIT44 196
+#define OCTEON_IRQ_MSI_BIT45 197
+#define OCTEON_IRQ_MSI_BIT46 198
+#define OCTEON_IRQ_MSI_BIT47 199
+#define OCTEON_IRQ_MSI_BIT48 200
+#define OCTEON_IRQ_MSI_BIT49 201
+#define OCTEON_IRQ_MSI_BIT50 202
+#define OCTEON_IRQ_MSI_BIT51 203
+#define OCTEON_IRQ_MSI_BIT52 204
+#define OCTEON_IRQ_MSI_BIT53 205
+#define OCTEON_IRQ_MSI_BIT54 206
+#define OCTEON_IRQ_MSI_BIT55 207
+#define OCTEON_IRQ_MSI_BIT56 208
+#define OCTEON_IRQ_MSI_BIT57 209
+#define OCTEON_IRQ_MSI_BIT58 210
+#define OCTEON_IRQ_MSI_BIT59 211
+#define OCTEON_IRQ_MSI_BIT60 212
+#define OCTEON_IRQ_MSI_BIT61 213
+#define OCTEON_IRQ_MSI_BIT62 214
+#define OCTEON_IRQ_MSI_BIT63 215
+
+#define OCTEON_IRQ_LAST 216
+#else
+#define OCTEON_IRQ_LAST 152
+#endif
+
+#endif
diff --git a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
new file mode 100644
index 000000000000..0b2b5eb22e9b
--- /dev/null
+++ b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
@@ -0,0 +1,131 @@
+/*
+ * 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) 2005-2008 Cavium Networks, Inc
+ */
+#ifndef __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
+#define __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H
+
+
+#define CP0_CYCLE_COUNTER $9, 6
+#define CP0_CVMCTL_REG $9, 7
+#define CP0_CVMMEMCTL_REG $11,7
+#define CP0_PRID_REG $15, 0
+#define CP0_PRID_OCTEON_PASS1 0x000d0000
+#define CP0_PRID_OCTEON_CN30XX 0x000d0200
+
+.macro kernel_entry_setup
+ # Registers set by bootloader:
+ # (only 32 bits set by bootloader, all addresses are physical
+ # addresses, and need to have the appropriate memory region set
+ # by the kernel
+ # a0 = argc
+ # a1 = argv (kseg0 compat addr)
+ # a2 = 1 if init core, zero otherwise
+ # a3 = address of boot descriptor block
+ .set push
+ .set arch=octeon
+ # Read the cavium mem control register
+ dmfc0 v0, CP0_CVMMEMCTL_REG
+ # Clear the lower 6 bits, the CVMSEG size
+ dins v0, $0, 0, 6
+ ori v0, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE
+ dmtc0 v0, CP0_CVMMEMCTL_REG # Write the cavium mem control register
+ dmfc0 v0, CP0_CVMCTL_REG # Read the cavium control register
+#ifdef CONFIG_CAVIUM_OCTEON_HW_FIX_UNALIGNED
+ # Disable unaligned load/store support but leave HW fixup enabled
+ or v0, v0, 0x5001
+ xor v0, v0, 0x1001
+#else
+ # Disable unaligned load/store and HW fixup support
+ or v0, v0, 0x5001
+ xor v0, v0, 0x5001
+#endif
+ # Read the processor ID register
+ mfc0 v1, CP0_PRID_REG
+ # Disable instruction prefetching (Octeon Pass1 errata)
+ or v0, v0, 0x2000
+ # Skip reenable of prefetching for Octeon Pass1
+ beq v1, CP0_PRID_OCTEON_PASS1, skip
+ nop
+ # Reenable instruction prefetching, not on Pass1
+ xor v0, v0, 0x2000
+ # Strip off pass number off of processor id
+ srl v1, 8
+ sll v1, 8
+ # CN30XX needs some extra stuff turned off for better performance
+ bne v1, CP0_PRID_OCTEON_CN30XX, skip
+ nop
+ # CN30XX Use random Icache replacement
+ or v0, v0, 0x400
+ # CN30XX Disable instruction prefetching
+ or v0, v0, 0x2000
+skip:
+ # Write the cavium control register
+ dmtc0 v0, CP0_CVMCTL_REG
+ sync
+ # Flush dcache after config change
+ cache 9, 0($0)
+ # Get my core id
+ rdhwr v0, $0
+ # Jump the master to kernel_entry
+ bne a2, zero, octeon_main_processor
+ nop
+
+#ifdef CONFIG_SMP
+
+ #
+ # All cores other than the master need to wait here for SMP bootstrap
+ # to begin
+ #
+
+ # This is the variable where the next core to boot os stored
+ PTR_LA t0, octeon_processor_boot
+octeon_spin_wait_boot:
+ # Get the core id of the next to be booted
+ LONG_L t1, (t0)
+ # Keep looping if it isn't me
+ bne t1, v0, octeon_spin_wait_boot
+ nop
+ # Get my GP from the global variable
+ PTR_LA t0, octeon_processor_gp
+ LONG_L gp, (t0)
+ # Get my SP from the global variable
+ PTR_LA t0, octeon_processor_sp
+ LONG_L sp, (t0)
+ # Set the SP global variable to zero so the master knows we've started
+ LONG_S zero, (t0)
+#ifdef __OCTEON__
+ syncw
+ syncw
+#else
+ sync
+#endif
+ # Jump to the normal Linux SMP entry point
+ j smp_bootstrap
+ nop
+#else /* CONFIG_SMP */
+
+ #
+ # Someone tried to boot SMP with a non SMP kernel. All extra cores
+ # will halt here.
+ #
+octeon_wait_forever:
+ wait
+ b octeon_wait_forever
+ nop
+
+#endif /* CONFIG_SMP */
+octeon_main_processor:
+ .set pop
+.endm
+
+/*
+ * Do SMP slave processor setup necessary before we can savely execute C code.
+ */
+ .macro smp_slave_setup
+ .endm
+
+#endif /* __ASM_MACH_CAVIUM_OCTEON_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-cavium-octeon/war.h b/arch/mips/include/asm/mach-cavium-octeon/war.h
new file mode 100644
index 000000000000..c4712d7cc81d
--- /dev/null
+++ b/arch/mips/include/asm/mach-cavium-octeon/war.h
@@ -0,0 +1,26 @@
+/*
+ * 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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2008 Cavium Networks <support@caviumnetworks.com>
+ */
+#ifndef __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H
+#define __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MIPS_MACH_CAVIUM_OCTEON_WAR_H */
diff --git a/arch/mips/include/asm/mach-generic/dma-coherence.h b/arch/mips/include/asm/mach-generic/dma-coherence.h
index 76e04e7feb84..36c611b6c597 100644
--- a/arch/mips/include/asm/mach-generic/dma-coherence.h
+++ b/arch/mips/include/asm/mach-generic/dma-coherence.h
@@ -28,10 +28,34 @@ static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
return dma_addr;
}
-static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+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)
{
#ifdef CONFIG_DMA_COHERENT
diff --git a/arch/mips/include/asm/mach-ip27/dma-coherence.h b/arch/mips/include/asm/mach-ip27/dma-coherence.h
index ed7e6222dc15..4c21bfca10c3 100644
--- a/arch/mips/include/asm/mach-ip27/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip27/dma-coherence.h
@@ -38,10 +38,34 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
return dma_addr & ~(0xffUL << 56);
}
-static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+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 1; /* IP27 non-cohernet mode is unsupported */
diff --git a/arch/mips/include/asm/mach-ip27/topology.h b/arch/mips/include/asm/mach-ip27/topology.h
index 7785bec732f2..55d481569a1f 100644
--- a/arch/mips/include/asm/mach-ip27/topology.h
+++ b/arch/mips/include/asm/mach-ip27/topology.h
@@ -25,11 +25,13 @@ extern struct cpuinfo_ip27 sn_cpu_info[NR_CPUS];
#define cpu_to_node(cpu) (sn_cpu_info[(cpu)].p_nodeid)
#define parent_node(node) (node)
#define node_to_cpumask(node) (hub_data(node)->h_cpus)
-#define node_to_first_cpu(node) (first_cpu(node_to_cpumask(node)))
+#define cpumask_of_node(node) (&hub_data(node)->h_cpus)
+#define node_to_first_cpu(node) (cpumask_first(cpumask_of_node(node)))
struct pci_bus;
extern int pcibus_to_node(struct pci_bus *);
#define pcibus_to_cpumask(bus) (cpu_online_map)
+#define cpumask_of_pcibus(bus) (cpu_online_mask)
extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
@@ -37,7 +39,6 @@ extern unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
/* sched_domains SD_NODE_INIT for SGI IP27 machines */
#define SD_NODE_INIT (struct sched_domain) { \
- .span = CPU_MASK_NONE, \
.parent = NULL, \
.child = NULL, \
.groups = NULL, \
diff --git a/arch/mips/include/asm/mach-ip32/dma-coherence.h b/arch/mips/include/asm/mach-ip32/dma-coherence.h
index a5511ebb2d53..7ae40f4b1c80 100644
--- a/arch/mips/include/asm/mach-ip32/dma-coherence.h
+++ b/arch/mips/include/asm/mach-ip32/dma-coherence.h
@@ -60,10 +60,34 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
return addr;
}
-static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+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; /* IP32 is non-cohernet */
diff --git a/arch/mips/include/asm/mach-jazz/dma-coherence.h b/arch/mips/include/asm/mach-jazz/dma-coherence.h
index d66979a124a8..1c7cd27efa7b 100644
--- a/arch/mips/include/asm/mach-jazz/dma-coherence.h
+++ b/arch/mips/include/asm/mach-jazz/dma-coherence.h
@@ -27,11 +27,35 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
return vdma_log2phys(dma_addr);
}
-static void plat_unmap_dma_mem(dma_addr_t dma_addr)
+static void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
{
vdma_free(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;
diff --git a/arch/mips/include/asm/mach-lemote/dma-coherence.h b/arch/mips/include/asm/mach-lemote/dma-coherence.h
index 7e914777ebc4..38fad7dfe7da 100644
--- a/arch/mips/include/asm/mach-lemote/dma-coherence.h
+++ b/arch/mips/include/asm/mach-lemote/dma-coherence.h
@@ -30,10 +30,34 @@ 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(dma_addr_t dma_addr)
+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;
diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h
index b5cf6457305a..3cb50d17b62d 100644
--- a/arch/mips/include/asm/mach-rc32434/gpio.h
+++ b/arch/mips/include/asm/mach-rc32434/gpio.h
@@ -80,11 +80,8 @@ struct rb532_gpio_reg {
/* Compact Flash GPIO pin */
#define CF_GPIO_NUM 13
-extern void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val);
-extern unsigned get_434_reg(unsigned reg_offs);
-extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask);
-extern unsigned char get_latch_u5(void);
extern void rb532_gpio_set_ilevel(int bit, unsigned gpio);
extern void rb532_gpio_set_istat(int bit, unsigned gpio);
+extern void rb532_gpio_set_func(unsigned gpio);
#endif /* _RC32434_GPIO_H_ */
diff --git a/arch/mips/include/asm/mach-rc32434/irq.h b/arch/mips/include/asm/mach-rc32434/irq.h
index 56738d8ec4e2..023a5b100ed0 100644
--- a/arch/mips/include/asm/mach-rc32434/irq.h
+++ b/arch/mips/include/asm/mach-rc32434/irq.h
@@ -30,4 +30,7 @@
#define ETH0_RX_OVR_IRQ (GROUP3_IRQ_BASE + 9)
#define ETH0_TX_UND_IRQ (GROUP3_IRQ_BASE + 10)
+#define GPIO_MAPPED_IRQ_BASE GROUP4_IRQ_BASE
+#define GPIO_MAPPED_IRQ_GROUP 4
+
#endif /* __ASM_RC32434_IRQ_H */
diff --git a/arch/mips/include/asm/mach-rc32434/rb.h b/arch/mips/include/asm/mach-rc32434/rb.h
index f25a84916703..6dc5f8df1f3e 100644
--- a/arch/mips/include/asm/mach-rc32434/rb.h
+++ b/arch/mips/include/asm/mach-rc32434/rb.h
@@ -83,4 +83,7 @@ struct mpmc_device {
void __iomem *base;
};
+extern void set_latch_u5(unsigned char or_mask, unsigned char nand_mask);
+extern unsigned char get_latch_u5(void);
+
#endif /* __ASM_RC32434_RB_H */
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 9316324d070d..0417516503f6 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1000,6 +1000,26 @@ do { \
#define read_c0_ebase() __read_32bit_c0_register($15, 1)
#define write_c0_ebase(val) __write_32bit_c0_register($15, 1, val)
+
+/* Cavium OCTEON (cnMIPS) */
+#define read_c0_cvmcount() __read_ulong_c0_register($9, 6)
+#define write_c0_cvmcount(val) __write_ulong_c0_register($9, 6, val)
+
+#define read_c0_cvmctl() __read_64bit_c0_register($9, 7)
+#define write_c0_cvmctl(val) __write_64bit_c0_register($9, 7, val)
+
+#define read_c0_cvmmemctl() __read_64bit_c0_register($11, 7)
+#define write_c0_cvmmemctl(val) __write_64bit_c0_register($11, 7, val)
+/*
+ * The cacheerr registers are not standardized. On OCTEON, they are
+ * 64 bits wide.
+ */
+#define read_octeon_c0_icacheerr() __read_64bit_c0_register($27, 0)
+#define write_octeon_c0_icacheerr(val) __write_64bit_c0_register($27, 0, val)
+
+#define read_octeon_c0_dcacheerr() __read_64bit_c0_register($27, 1)
+#define write_octeon_c0_dcacheerr(val) __write_64bit_c0_register($27, 1, val)
+
/*
* Macros to access the floating point coprocessor control registers
*/
@@ -1008,6 +1028,8 @@ do { \
__asm__ __volatile__( \
".set\tpush\n\t" \
".set\treorder\n\t" \
+ /* gas fails to assemble cfc1 for some archs (octeon).*/ \
+ ".set\tmips1\n\t" \
"cfc1\t%0,"STR(source)"\n\t" \
".set\tpop" \
: "=r" (__res)); \
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index e2e09b2cd265..d94085a3eafb 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -116,6 +116,8 @@ search_module_dbetables(unsigned long addr)
#define MODULE_PROC_FAMILY "SB1 "
#elif defined CONFIG_CPU_LOONGSON2
#define MODULE_PROC_FAMILY "LOONGSON2 "
+#elif defined CONFIG_CPU_CAVIUM_OCTEON
+#define MODULE_PROC_FAMILY "OCTEON "
#else
#error MODULE_PROC_FAMILY undefined for your processor configuration
#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-asm.h b/arch/mips/include/asm/octeon/cvmx-asm.h
new file mode 100644
index 000000000000..b21d3fc1ef91
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-asm.h
@@ -0,0 +1,128 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ *
+ * This is file defines ASM primitives for the executive.
+ */
+#ifndef __CVMX_ASM_H__
+#define __CVMX_ASM_H__
+
+#include "octeon-model.h"
+
+/* other useful stuff */
+#define CVMX_SYNC asm volatile ("sync" : : : "memory")
+/* String version of SYNCW macro for using in inline asm constructs */
+#define CVMX_SYNCW_STR "syncw\nsyncw\n"
+#ifdef __OCTEON__
+
+/* Deprecated, will be removed in future release */
+#define CVMX_SYNCIO asm volatile ("nop")
+
+#define CVMX_SYNCIOBDMA asm volatile ("synciobdma" : : : "memory")
+
+/* Deprecated, will be removed in future release */
+#define CVMX_SYNCIOALL asm volatile ("nop")
+
+/*
+ * We actually use two syncw instructions in a row when we need a write
+ * memory barrier. This is because the CN3XXX series of Octeons have
+ * errata Core-401. This can cause a single syncw to not enforce
+ * ordering under very rare conditions. Even if it is rare, better safe
+ * than sorry.
+ */
+#define CVMX_SYNCW asm volatile ("syncw\n\tsyncw" : : : "memory")
+
+/*
+ * Define new sync instructions to be normal SYNC instructions for
+ * operating systems that use threads.
+ */
+#define CVMX_SYNCWS CVMX_SYNCW
+#define CVMX_SYNCS CVMX_SYNC
+#define CVMX_SYNCWS_STR CVMX_SYNCW_STR
+#else
+/*
+ * Not using a Cavium compiler, always use the slower sync so the
+ * assembler stays happy.
+ */
+/* Deprecated, will be removed in future release */
+#define CVMX_SYNCIO asm volatile ("nop")
+
+#define CVMX_SYNCIOBDMA asm volatile ("sync" : : : "memory")
+
+/* Deprecated, will be removed in future release */
+#define CVMX_SYNCIOALL asm volatile ("nop")
+
+#define CVMX_SYNCW asm volatile ("sync" : : : "memory")
+#define CVMX_SYNCWS CVMX_SYNCW
+#define CVMX_SYNCS CVMX_SYNC
+#define CVMX_SYNCWS_STR CVMX_SYNCW_STR
+#endif
+
+/*
+ * CVMX_PREPARE_FOR_STORE makes each byte of the block unpredictable
+ * (actually old value or zero) until that byte is stored to (by this or
+ * another processor. Note that the value of each byte is not only
+ * unpredictable, but may also change again - up until the point when one
+ * of the cores stores to the byte.
+ */
+#define CVMX_PREPARE_FOR_STORE(address, offset) \
+ asm volatile ("pref 30, " CVMX_TMP_STR(offset) "(%[rbase])" : : \
+ [rbase] "d" (address))
+/*
+ * This is a command headed to the L2 controller to tell it to clear
+ * its dirty bit for a block. Basically, SW is telling HW that the
+ * current version of the block will not be used.
+ */
+#define CVMX_DONT_WRITE_BACK(address, offset) \
+ asm volatile ("pref 29, " CVMX_TMP_STR(offset) "(%[rbase])" : : \
+ [rbase] "d" (address))
+
+/* flush stores, invalidate entire icache */
+#define CVMX_ICACHE_INVALIDATE \
+ { CVMX_SYNC; asm volatile ("synci 0($0)" : : ); }
+
+/* flush stores, invalidate entire icache */
+#define CVMX_ICACHE_INVALIDATE2 \
+ { CVMX_SYNC; asm volatile ("cache 0, 0($0)" : : ); }
+
+/* complete prefetches, invalidate entire dcache */
+#define CVMX_DCACHE_INVALIDATE \
+ { CVMX_SYNC; asm volatile ("cache 9, 0($0)" : : ); }
+
+
+#define CVMX_POP(result, input) \
+ asm ("pop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+#define CVMX_DPOP(result, input) \
+ asm ("dpop %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input))
+
+/* some new cop0-like stuff */
+#define CVMX_RDHWR(result, regstr) \
+ asm volatile ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result))
+#define CVMX_RDHWRNV(result, regstr) \
+ asm ("rdhwr %[rt],$" CVMX_TMP_STR(regstr) : [rt] "=d" (result))
+#endif /* __CVMX_ASM_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-bootinfo.h b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
new file mode 100644
index 000000000000..692989acd8a9
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-bootinfo.h
@@ -0,0 +1,262 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * Header file containing the ABI with the bootloader.
+ */
+
+#ifndef __CVMX_BOOTINFO_H__
+#define __CVMX_BOOTINFO_H__
+
+/*
+ * Current major and minor versions of the CVMX bootinfo block that is
+ * passed from the bootloader to the application. This is versioned
+ * so that applications can properly handle multiple bootloader
+ * versions.
+ */
+#define CVMX_BOOTINFO_MAJ_VER 1
+#define CVMX_BOOTINFO_MIN_VER 2
+
+#if (CVMX_BOOTINFO_MAJ_VER == 1)
+#define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20
+/*
+ * This structure is populated by the bootloader. For binary
+ * compatibility the only changes that should be made are
+ * adding members to the end of the structure, and the minor
+ * version should be incremented at that time.
+ * If an incompatible change is made, the major version
+ * must be incremented, and the minor version should be reset
+ * to 0.
+ */
+struct cvmx_bootinfo {
+ uint32_t major_version;
+ uint32_t minor_version;
+
+ uint64_t stack_top;
+ uint64_t heap_base;
+ uint64_t heap_end;
+ uint64_t desc_vaddr;
+
+ uint32_t exception_base_addr;
+ uint32_t stack_size;
+ uint32_t flags;
+ uint32_t core_mask;
+ /* DRAM size in megabytes */
+ uint32_t dram_size;
+ /* physical address of free memory descriptor block*/
+ uint32_t phy_mem_desc_addr;
+ /* used to pass flags from app to debugger */
+ uint32_t debugger_flags_base_addr;
+
+ /* CPU clock speed, in hz */
+ uint32_t eclock_hz;
+
+ /* DRAM clock speed, in hz */
+ uint32_t dclock_hz;
+
+ uint32_t reserved0;
+ uint16_t board_type;
+ uint8_t board_rev_major;
+ uint8_t board_rev_minor;
+ uint16_t reserved1;
+ uint8_t reserved2;
+ uint8_t reserved3;
+ char board_serial_number[CVMX_BOOTINFO_OCTEON_SERIAL_LEN];
+ uint8_t mac_addr_base[6];
+ uint8_t mac_addr_count;
+#if (CVMX_BOOTINFO_MIN_VER >= 1)
+ /*
+ * Several boards support compact flash on the Octeon boot
+ * bus. The CF memory spaces may be mapped to different
+ * addresses on different boards. These are the physical
+ * addresses, so care must be taken to use the correct
+ * XKPHYS/KSEG0 addressing depending on the application's
+ * ABI. These values will be 0 if CF is not present.
+ */
+ uint64_t compact_flash_common_base_addr;
+ uint64_t compact_flash_attribute_base_addr;
+ /*
+ * Base address of the LED display (as on EBT3000 board)
+ * This will be 0 if LED display not present.
+ */
+ uint64_t led_display_base_addr;
+#endif
+#if (CVMX_BOOTINFO_MIN_VER >= 2)
+ /* DFA reference clock in hz (if applicable)*/
+ uint32_t dfa_ref_clock_hz;
+
+ /*
+ * flags indicating various configuration options. These
+ * flags supercede the 'flags' variable and should be used
+ * instead if available.
+ */
+ uint32_t config_flags;
+#endif
+
+};
+
+#define CVMX_BOOTINFO_CFG_FLAG_PCI_HOST (1ull << 0)
+#define CVMX_BOOTINFO_CFG_FLAG_PCI_TARGET (1ull << 1)
+#define CVMX_BOOTINFO_CFG_FLAG_DEBUG (1ull << 2)
+#define CVMX_BOOTINFO_CFG_FLAG_NO_MAGIC (1ull << 3)
+/* This flag is set if the TLB mappings are not contained in the
+ * 0x10000000 - 0x20000000 boot bus region. */
+#define CVMX_BOOTINFO_CFG_FLAG_OVERSIZE_TLB_MAPPING (1ull << 4)
+#define CVMX_BOOTINFO_CFG_FLAG_BREAK (1ull << 5)
+
+#endif /* (CVMX_BOOTINFO_MAJ_VER == 1) */
+
+/* Type defines for board and chip types */
+enum cvmx_board_types_enum {
+ CVMX_BOARD_TYPE_NULL = 0,
+ CVMX_BOARD_TYPE_SIM = 1,
+ CVMX_BOARD_TYPE_EBT3000 = 2,
+ CVMX_BOARD_TYPE_KODAMA = 3,
+ CVMX_BOARD_TYPE_NIAGARA = 4,
+ CVMX_BOARD_TYPE_NAC38 = 5, /* formerly NAO38 */
+ CVMX_BOARD_TYPE_THUNDER = 6,
+ CVMX_BOARD_TYPE_TRANTOR = 7,
+ CVMX_BOARD_TYPE_EBH3000 = 8,
+ CVMX_BOARD_TYPE_EBH3100 = 9,
+ CVMX_BOARD_TYPE_HIKARI = 10,
+ CVMX_BOARD_TYPE_CN3010_EVB_HS5 = 11,
+ CVMX_BOARD_TYPE_CN3005_EVB_HS5 = 12,
+ CVMX_BOARD_TYPE_KBP = 13,
+ /* Deprecated, CVMX_BOARD_TYPE_CN3010_EVB_HS5 supports the CN3020 */
+ CVMX_BOARD_TYPE_CN3020_EVB_HS5 = 14,
+ CVMX_BOARD_TYPE_EBT5800 = 15,
+ CVMX_BOARD_TYPE_NICPRO2 = 16,
+ CVMX_BOARD_TYPE_EBH5600 = 17,
+ CVMX_BOARD_TYPE_EBH5601 = 18,
+ CVMX_BOARD_TYPE_EBH5200 = 19,
+ CVMX_BOARD_TYPE_BBGW_REF = 20,
+ CVMX_BOARD_TYPE_NIC_XLE_4G = 21,
+ CVMX_BOARD_TYPE_EBT5600 = 22,
+ CVMX_BOARD_TYPE_EBH5201 = 23,
+ CVMX_BOARD_TYPE_MAX,
+
+ /*
+ * The range from CVMX_BOARD_TYPE_MAX to
+ * CVMX_BOARD_TYPE_CUST_DEFINED_MIN is reserved for future
+ * SDK use.
+ */
+
+ /*
+ * Set aside a range for customer boards. These numbers are managed
+ * by Cavium.
+ */
+ CVMX_BOARD_TYPE_CUST_DEFINED_MIN = 10000,
+ CVMX_BOARD_TYPE_CUST_WSX16 = 10001,
+ CVMX_BOARD_TYPE_CUST_NS0216 = 10002,
+ CVMX_BOARD_TYPE_CUST_NB5 = 10003,
+ CVMX_BOARD_TYPE_CUST_WMR500 = 10004,
+ CVMX_BOARD_TYPE_CUST_DEFINED_MAX = 20000,
+
+ /*
+ * Set aside a range for customer private use. The SDK won't
+ * use any numbers in this range.
+ */
+ CVMX_BOARD_TYPE_CUST_PRIVATE_MIN = 20001,
+ CVMX_BOARD_TYPE_CUST_PRIVATE_MAX = 30000,
+
+ /* The remaining range is reserved for future use. */
+};
+
+enum cvmx_chip_types_enum {
+ CVMX_CHIP_TYPE_NULL = 0,
+ CVMX_CHIP_SIM_TYPE_DEPRECATED = 1,
+ CVMX_CHIP_TYPE_OCTEON_SAMPLE = 2,
+ CVMX_CHIP_TYPE_MAX,
+};
+
+/* Compatability alias for NAC38 name change, planned to be removed
+ * from SDK 1.7 */
+#define CVMX_BOARD_TYPE_NAO38 CVMX_BOARD_TYPE_NAC38
+
+/* Functions to return string based on type */
+#define ENUM_BRD_TYPE_CASE(x) \
+ case x: return(#x + 16); /* Skip CVMX_BOARD_TYPE_ */
+static inline const char *cvmx_board_type_to_string(enum
+ cvmx_board_types_enum type)
+{
+ switch (type) {
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NULL)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_SIM)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT3000)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KODAMA)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIAGARA)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NAC38)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_THUNDER)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_TRANTOR)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3000)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH3100)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_HIKARI)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3010_EVB_HS5)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3005_EVB_HS5)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KBP)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CN3020_EVB_HS5)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5800)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NICPRO2)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5600)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5601)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5200)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_BBGW_REF)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_NIC_XLE_4G)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBT5600)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_EBH5201)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_MAX)
+
+ /* Customer boards listed here */
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MIN)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WSX16)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NS0216)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_NB5)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_WMR500)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_DEFINED_MAX)
+
+ /* Customer private range */
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MIN)
+ ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
+ }
+ return "Unsupported Board";
+}
+
+#define ENUM_CHIP_TYPE_CASE(x) \
+ case x: return(#x + 15); /* Skip CVMX_CHIP_TYPE */
+static inline const char *cvmx_chip_type_to_string(enum
+ cvmx_chip_types_enum type)
+{
+ switch (type) {
+ ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_NULL)
+ ENUM_CHIP_TYPE_CASE(CVMX_CHIP_SIM_TYPE_DEPRECATED)
+ ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_OCTEON_SAMPLE)
+ ENUM_CHIP_TYPE_CASE(CVMX_CHIP_TYPE_MAX)
+ }
+ return "Unsupported Chip";
+}
+
+#endif /* __CVMX_BOOTINFO_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-bootmem.h b/arch/mips/include/asm/octeon/cvmx-bootmem.h
new file mode 100644
index 000000000000..1cbe4b55889d
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h
@@ -0,0 +1,288 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * Simple allocate only memory allocator. Used to allocate memory at
+ * application start time.
+ */
+
+#ifndef __CVMX_BOOTMEM_H__
+#define __CVMX_BOOTMEM_H__
+/* Must be multiple of 8, changing breaks ABI */
+#define CVMX_BOOTMEM_NAME_LEN 128
+
+/* Can change without breaking ABI */
+#define CVMX_BOOTMEM_NUM_NAMED_BLOCKS 64
+
+/* minimum alignment of bootmem alloced blocks */
+#define CVMX_BOOTMEM_ALIGNMENT_SIZE (16ull)
+
+/* Flags for cvmx_bootmem_phy_mem* functions */
+/* Allocate from end of block instead of beginning */
+#define CVMX_BOOTMEM_FLAG_END_ALLOC (1 << 0)
+
+/* Don't do any locking. */
+#define CVMX_BOOTMEM_FLAG_NO_LOCKING (1 << 1)
+
+/* First bytes of each free physical block of memory contain this structure,
+ * which is used to maintain the free memory list. Since the bootloader is
+ * only 32 bits, there is a union providing 64 and 32 bit versions. The
+ * application init code converts addresses to 64 bit addresses before the
+ * application starts.
+ */
+struct cvmx_bootmem_block_header {
+ /*
+ * Note: these are referenced from assembly routines in the
+ * bootloader, so this structure should not be changed
+ * without changing those routines as well.
+ */
+ uint64_t next_block_addr;
+ uint64_t size;
+
+};
+
+/*
+ * Structure for named memory blocks. Number of descriptors available
+ * can be changed without affecting compatiblity, but name length
+ * changes require a bump in the bootmem descriptor version Note: This
+ * structure must be naturally 64 bit aligned, as a single memory
+ * image will be used by both 32 and 64 bit programs.
+ */
+struct cvmx_bootmem_named_block_desc {
+ /* Base address of named block */
+ uint64_t base_addr;
+ /*
+ * Size actually allocated for named block (may differ from
+ * requested).
+ */
+ uint64_t size;
+ /* name of named block */
+ char name[CVMX_BOOTMEM_NAME_LEN];
+};
+
+/* Current descriptor versions */
+/* CVMX bootmem descriptor major version */
+#define CVMX_BOOTMEM_DESC_MAJ_VER 3
+
+/* CVMX bootmem descriptor minor version */
+#define CVMX_BOOTMEM_DESC_MIN_VER 0
+
+/* First three members of cvmx_bootmem_desc_t are left in original
+ * positions for backwards compatibility.
+ */
+struct cvmx_bootmem_desc {
+ /* spinlock to control access to list */
+ uint32_t lock;
+ /* flags for indicating various conditions */
+ uint32_t flags;
+ uint64_t head_addr;
+
+ /* Incremented when incompatible changes made */
+ uint32_t major_version;
+
+ /*
+ * Incremented changed when compatible changes made, reset to
+ * zero when major incremented.
+ */
+ uint32_t minor_version;
+
+ uint64_t app_data_addr;
+ uint64_t app_data_size;
+
+ /* number of elements in named blocks array */
+ uint32_t named_block_num_blocks;
+
+ /* length of name array in bootmem blocks */
+ uint32_t named_block_name_len;
+ /* address of named memory block descriptors */
+ uint64_t named_block_array_addr;
+
+};
+
+/**
+ * Initialize the boot alloc memory structures. This is
+ * normally called inside of cvmx_user_app_init()
+ *
+ * @mem_desc_ptr: Address of the free memory list
+ */
+extern int cvmx_bootmem_init(void *mem_desc_ptr);
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader.
+ * This is an allocate-only algorithm, so freeing memory is not possible.
+ *
+ * @size: Size in bytes of block to allocate
+ * @alignment: Alignment required - must be power of 2
+ *
+ * Returns pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment);
+
+/**
+ * Allocate a block of memory from the free list that was
+ * passed to the application by the bootloader at a specific
+ * address. This is an allocate-only algorithm, so
+ * freeing memory is not possible. Allocation will fail if
+ * memory cannot be allocated at the specified address.
+ *
+ * @size: Size in bytes of block to allocate
+ * @address: Physical address to allocate memory at. If this memory is not
+ * available, the allocation fails.
+ * @alignment: Alignment required - must be power of 2
+ * Returns pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address,
+ uint64_t alignment);
+
+/**
+ * Allocate a block of memory from the free list that was
+ * passed to the application by the bootloader within a specified
+ * address range. This is an allocate-only algorithm, so
+ * freeing memory is not possible. Allocation will fail if
+ * memory cannot be allocated in the requested range.
+ *
+ * @size: Size in bytes of block to allocate
+ * @min_addr: defines the minimum address of the range
+ * @max_addr: defines the maximum address of the range
+ * @alignment: Alignment required - must be power of 2
+ * Returns pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
+ uint64_t min_addr, uint64_t max_addr);
+
+/**
+ * Frees a previously allocated named bootmem block.
+ *
+ * @name: name of block to free
+ *
+ * Returns 0 on failure,
+ * !0 on success
+ */
+extern int cvmx_bootmem_free_named(char *name);
+
+/**
+ * Finds a named bootmem block by name.
+ *
+ * @name: name of block to free
+ *
+ * Returns pointer to named block descriptor on success
+ * 0 on failure
+ */
+struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name);
+
+/**
+ * Allocates a block of physical memory from the free list, at
+ * (optional) requested address and alignment.
+ *
+ * @req_size: size of region to allocate. All requests are rounded up
+ * to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE bytes size
+ *
+ * @address_min: Minimum address that block can occupy.
+ *
+ * @address_max: Specifies the maximum address_min (inclusive) that
+ * the allocation can use.
+ *
+ * @alignment: Requested alignment of the block. If this alignment
+ * cannot be met, the allocation fails. This must be a
+ * power of 2. (Note: Alignment of
+ * CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and
+ * internally enforced. Requested alignments of less than
+ * CVMX_BOOTMEM_ALIGNMENT_SIZE are set to
+ * CVMX_BOOTMEM_ALIGNMENT_SIZE.)
+ *
+ * @flags: Flags to control options for the allocation.
+ *
+ * Returns physical address of block allocated, or -1 on failure
+ */
+int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
+ uint64_t address_max, uint64_t alignment,
+ uint32_t flags);
+
+/**
+ * Finds a named memory block by name.
+ * Also used for finding an unused entry in the named block table.
+ *
+ * @name: Name of memory block to find. If NULL pointer given, then
+ * finds unused descriptor, if available.
+ *
+ * @flags: Flags to control options for the allocation.
+ *
+ * Returns Pointer to memory block descriptor, NULL if not found.
+ * If NULL returned when name parameter is NULL, then no memory
+ * block descriptors are available.
+ */
+struct cvmx_bootmem_named_block_desc *
+cvmx_bootmem_phy_named_block_find(char *name, uint32_t flags);
+
+/**
+ * Frees a named block.
+ *
+ * @name: name of block to free
+ * @flags: flags for passing options
+ *
+ * Returns 0 on failure
+ * 1 on success
+ */
+int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags);
+
+/**
+ * Frees a block to the bootmem allocator list. This must
+ * be used with care, as the size provided must match the size
+ * of the block that was allocated, or the list will become
+ * corrupted.
+ *
+ * IMPORTANT: This is only intended to be used as part of named block
+ * frees and initial population of the free memory list.
+ * *
+ *
+ * @phy_addr: physical address of block
+ * @size: size of block in bytes.
+ * @flags: flags for passing options
+ *
+ * Returns 1 on success,
+ * 0 on failure
+ */
+int __cvmx_bootmem_phy_free(uint64_t phy_addr, uint64_t size, uint32_t flags);
+
+/**
+ * Locks the bootmem allocator. This is useful in certain situations
+ * where multiple allocations must be made without being interrupted.
+ * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag.
+ *
+ */
+void cvmx_bootmem_lock(void);
+
+/**
+ * Unlocks the bootmem allocator. This is useful in certain situations
+ * where multiple allocations must be made without being interrupted.
+ * This should be used with the CVMX_BOOTMEM_FLAG_NO_LOCKING flag.
+ *
+ */
+void cvmx_bootmem_unlock(void);
+
+#endif /* __CVMX_BOOTMEM_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-ciu-defs.h b/arch/mips/include/asm/octeon/cvmx-ciu-defs.h
new file mode 100644
index 000000000000..f8f05b7764b7
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-ciu-defs.h
@@ -0,0 +1,1616 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_CIU_DEFS_H__
+#define __CVMX_CIU_DEFS_H__
+
+#define CVMX_CIU_BIST \
+ CVMX_ADD_IO_SEG(0x0001070000000730ull)
+#define CVMX_CIU_DINT \
+ CVMX_ADD_IO_SEG(0x0001070000000720ull)
+#define CVMX_CIU_FUSE \
+ CVMX_ADD_IO_SEG(0x0001070000000728ull)
+#define CVMX_CIU_GSTOP \
+ CVMX_ADD_IO_SEG(0x0001070000000710ull)
+#define CVMX_CIU_INTX_EN0(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000200ull + (((offset) & 63) * 16))
+#define CVMX_CIU_INTX_EN0_W1C(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000002200ull + (((offset) & 63) * 16))
+#define CVMX_CIU_INTX_EN0_W1S(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000006200ull + (((offset) & 63) * 16))
+#define CVMX_CIU_INTX_EN1(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000208ull + (((offset) & 63) * 16))
+#define CVMX_CIU_INTX_EN1_W1C(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000002208ull + (((offset) & 63) * 16))
+#define CVMX_CIU_INTX_EN1_W1S(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000006208ull + (((offset) & 63) * 16))
+#define CVMX_CIU_INTX_EN4_0(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000C80ull + (((offset) & 15) * 16))
+#define CVMX_CIU_INTX_EN4_0_W1C(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000002C80ull + (((offset) & 15) * 16))
+#define CVMX_CIU_INTX_EN4_0_W1S(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000006C80ull + (((offset) & 15) * 16))
+#define CVMX_CIU_INTX_EN4_1(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000C88ull + (((offset) & 15) * 16))
+#define CVMX_CIU_INTX_EN4_1_W1C(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000002C88ull + (((offset) & 15) * 16))
+#define CVMX_CIU_INTX_EN4_1_W1S(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000006C88ull + (((offset) & 15) * 16))
+#define CVMX_CIU_INTX_SUM0(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000000ull + (((offset) & 63) * 8))
+#define CVMX_CIU_INTX_SUM4(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000C00ull + (((offset) & 15) * 8))
+#define CVMX_CIU_INT_SUM1 \
+ CVMX_ADD_IO_SEG(0x0001070000000108ull)
+#define CVMX_CIU_MBOX_CLRX(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000680ull + (((offset) & 15) * 8))
+#define CVMX_CIU_MBOX_SETX(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000600ull + (((offset) & 15) * 8))
+#define CVMX_CIU_NMI \
+ CVMX_ADD_IO_SEG(0x0001070000000718ull)
+#define CVMX_CIU_PCI_INTA \
+ CVMX_ADD_IO_SEG(0x0001070000000750ull)
+#define CVMX_CIU_PP_DBG \
+ CVMX_ADD_IO_SEG(0x0001070000000708ull)
+#define CVMX_CIU_PP_POKEX(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000580ull + (((offset) & 15) * 8))
+#define CVMX_CIU_PP_RST \
+ CVMX_ADD_IO_SEG(0x0001070000000700ull)
+#define CVMX_CIU_QLM_DCOK \
+ CVMX_ADD_IO_SEG(0x0001070000000760ull)
+#define CVMX_CIU_QLM_JTGC \
+ CVMX_ADD_IO_SEG(0x0001070000000768ull)
+#define CVMX_CIU_QLM_JTGD \
+ CVMX_ADD_IO_SEG(0x0001070000000770ull)
+#define CVMX_CIU_SOFT_BIST \
+ CVMX_ADD_IO_SEG(0x0001070000000738ull)
+#define CVMX_CIU_SOFT_PRST \
+ CVMX_ADD_IO_SEG(0x0001070000000748ull)
+#define CVMX_CIU_SOFT_PRST1 \
+ CVMX_ADD_IO_SEG(0x0001070000000758ull)
+#define CVMX_CIU_SOFT_RST \
+ CVMX_ADD_IO_SEG(0x0001070000000740ull)
+#define CVMX_CIU_TIMX(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000480ull + (((offset) & 3) * 8))
+#define CVMX_CIU_WDOGX(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000500ull + (((offset) & 15) * 8))
+
+union cvmx_ciu_bist {
+ uint64_t u64;
+ struct cvmx_ciu_bist_s {
+ uint64_t reserved_4_63:60;
+ uint64_t bist:4;
+ } s;
+ struct cvmx_ciu_bist_s cn30xx;
+ struct cvmx_ciu_bist_s cn31xx;
+ struct cvmx_ciu_bist_s cn38xx;
+ struct cvmx_ciu_bist_s cn38xxp2;
+ struct cvmx_ciu_bist_cn50xx {
+ uint64_t reserved_2_63:62;
+ uint64_t bist:2;
+ } cn50xx;
+ struct cvmx_ciu_bist_cn52xx {
+ uint64_t reserved_3_63:61;
+ uint64_t bist:3;
+ } cn52xx;
+ struct cvmx_ciu_bist_cn52xx cn52xxp1;
+ struct cvmx_ciu_bist_s cn56xx;
+ struct cvmx_ciu_bist_s cn56xxp1;
+ struct cvmx_ciu_bist_s cn58xx;
+ struct cvmx_ciu_bist_s cn58xxp1;
+};
+
+union cvmx_ciu_dint {
+ uint64_t u64;
+ struct cvmx_ciu_dint_s {
+ uint64_t reserved_16_63:48;
+ uint64_t dint:16;
+ } s;
+ struct cvmx_ciu_dint_cn30xx {
+ uint64_t reserved_1_63:63;
+ uint64_t dint:1;
+ } cn30xx;
+ struct cvmx_ciu_dint_cn31xx {
+ uint64_t reserved_2_63:62;
+ uint64_t dint:2;
+ } cn31xx;
+ struct cvmx_ciu_dint_s cn38xx;
+ struct cvmx_ciu_dint_s cn38xxp2;
+ struct cvmx_ciu_dint_cn31xx cn50xx;
+ struct cvmx_ciu_dint_cn52xx {
+ uint64_t reserved_4_63:60;
+ uint64_t dint:4;
+ } cn52xx;
+ struct cvmx_ciu_dint_cn52xx cn52xxp1;
+ struct cvmx_ciu_dint_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t dint:12;
+ } cn56xx;
+ struct cvmx_ciu_dint_cn56xx cn56xxp1;
+ struct cvmx_ciu_dint_s cn58xx;
+ struct cvmx_ciu_dint_s cn58xxp1;
+};
+
+union cvmx_ciu_fuse {
+ uint64_t u64;
+ struct cvmx_ciu_fuse_s {
+ uint64_t reserved_16_63:48;
+ uint64_t fuse:16;
+ } s;
+ struct cvmx_ciu_fuse_cn30xx {
+ uint64_t reserved_1_63:63;
+ uint64_t fuse:1;
+ } cn30xx;
+ struct cvmx_ciu_fuse_cn31xx {
+ uint64_t reserved_2_63:62;
+ uint64_t fuse:2;
+ } cn31xx;
+ struct cvmx_ciu_fuse_s cn38xx;
+ struct cvmx_ciu_fuse_s cn38xxp2;
+ struct cvmx_ciu_fuse_cn31xx cn50xx;
+ struct cvmx_ciu_fuse_cn52xx {
+ uint64_t reserved_4_63:60;
+ uint64_t fuse:4;
+ } cn52xx;
+ struct cvmx_ciu_fuse_cn52xx cn52xxp1;
+ struct cvmx_ciu_fuse_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t fuse:12;
+ } cn56xx;
+ struct cvmx_ciu_fuse_cn56xx cn56xxp1;
+ struct cvmx_ciu_fuse_s cn58xx;
+ struct cvmx_ciu_fuse_s cn58xxp1;
+};
+
+union cvmx_ciu_gstop {
+ uint64_t u64;
+ struct cvmx_ciu_gstop_s {
+ uint64_t reserved_1_63:63;
+ uint64_t gstop:1;
+ } s;
+ struct cvmx_ciu_gstop_s cn30xx;
+ struct cvmx_ciu_gstop_s cn31xx;
+ struct cvmx_ciu_gstop_s cn38xx;
+ struct cvmx_ciu_gstop_s cn38xxp2;
+ struct cvmx_ciu_gstop_s cn50xx;
+ struct cvmx_ciu_gstop_s cn52xx;
+ struct cvmx_ciu_gstop_s cn52xxp1;
+ struct cvmx_ciu_gstop_s cn56xx;
+ struct cvmx_ciu_gstop_s cn56xxp1;
+ struct cvmx_ciu_gstop_s cn58xx;
+ struct cvmx_ciu_gstop_s cn58xxp1;
+};
+
+union cvmx_ciu_intx_en0 {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en0_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_en0_cn30xx {
+ uint64_t reserved_59_63:5;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t reserved_47_47:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn30xx;
+ struct cvmx_ciu_intx_en0_cn31xx {
+ uint64_t reserved_59_63:5;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn31xx;
+ struct cvmx_ciu_intx_en0_cn38xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn38xx;
+ struct cvmx_ciu_intx_en0_cn38xx cn38xxp2;
+ struct cvmx_ciu_intx_en0_cn30xx cn50xx;
+ struct cvmx_ciu_intx_en0_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_en0_cn52xx cn52xxp1;
+ struct cvmx_ciu_intx_en0_cn56xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn56xx;
+ struct cvmx_ciu_intx_en0_cn56xx cn56xxp1;
+ struct cvmx_ciu_intx_en0_cn38xx cn58xx;
+ struct cvmx_ciu_intx_en0_cn38xx cn58xxp1;
+};
+
+union cvmx_ciu_intx_en0_w1c {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en0_w1c_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_en0_w1c_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_en0_w1c_s cn56xx;
+ struct cvmx_ciu_intx_en0_w1c_cn58xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_en0_w1s {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en0_w1s_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_en0_w1s_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_en0_w1s_s cn56xx;
+ struct cvmx_ciu_intx_en0_w1s_cn58xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_en1 {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en1_s {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t wdog:16;
+ } s;
+ struct cvmx_ciu_intx_en1_cn30xx {
+ uint64_t reserved_1_63:63;
+ uint64_t wdog:1;
+ } cn30xx;
+ struct cvmx_ciu_intx_en1_cn31xx {
+ uint64_t reserved_2_63:62;
+ uint64_t wdog:2;
+ } cn31xx;
+ struct cvmx_ciu_intx_en1_cn38xx {
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+ } cn38xx;
+ struct cvmx_ciu_intx_en1_cn38xx cn38xxp2;
+ struct cvmx_ciu_intx_en1_cn31xx cn50xx;
+ struct cvmx_ciu_intx_en1_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xx;
+ struct cvmx_ciu_intx_en1_cn52xxp1 {
+ uint64_t reserved_19_63:45;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xxp1;
+ struct cvmx_ciu_intx_en1_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t wdog:12;
+ } cn56xx;
+ struct cvmx_ciu_intx_en1_cn56xx cn56xxp1;
+ struct cvmx_ciu_intx_en1_cn38xx cn58xx;
+ struct cvmx_ciu_intx_en1_cn38xx cn58xxp1;
+};
+
+union cvmx_ciu_intx_en1_w1c {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en1_w1c_s {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t wdog:16;
+ } s;
+ struct cvmx_ciu_intx_en1_w1c_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xx;
+ struct cvmx_ciu_intx_en1_w1c_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t wdog:12;
+ } cn56xx;
+ struct cvmx_ciu_intx_en1_w1c_cn58xx {
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_en1_w1s {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en1_w1s_s {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t wdog:16;
+ } s;
+ struct cvmx_ciu_intx_en1_w1s_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xx;
+ struct cvmx_ciu_intx_en1_w1s_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t wdog:12;
+ } cn56xx;
+ struct cvmx_ciu_intx_en1_w1s_cn58xx {
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_en4_0 {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en4_0_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_en4_0_cn50xx {
+ uint64_t reserved_59_63:5;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t reserved_47_47:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn50xx;
+ struct cvmx_ciu_intx_en4_0_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_en4_0_cn52xx cn52xxp1;
+ struct cvmx_ciu_intx_en4_0_cn56xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn56xx;
+ struct cvmx_ciu_intx_en4_0_cn56xx cn56xxp1;
+ struct cvmx_ciu_intx_en4_0_cn58xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn58xx;
+ struct cvmx_ciu_intx_en4_0_cn58xx cn58xxp1;
+};
+
+union cvmx_ciu_intx_en4_0_w1c {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en4_0_w1c_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_en4_0_w1c_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_en4_0_w1c_s cn56xx;
+ struct cvmx_ciu_intx_en4_0_w1c_cn58xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_en4_0_w1s {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en4_0_w1s_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_en4_0_w1s_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_en4_0_w1s_s cn56xx;
+ struct cvmx_ciu_intx_en4_0_w1s_cn58xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t reserved_44_44:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_en4_1 {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en4_1_s {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t wdog:16;
+ } s;
+ struct cvmx_ciu_intx_en4_1_cn50xx {
+ uint64_t reserved_2_63:62;
+ uint64_t wdog:2;
+ } cn50xx;
+ struct cvmx_ciu_intx_en4_1_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xx;
+ struct cvmx_ciu_intx_en4_1_cn52xxp1 {
+ uint64_t reserved_19_63:45;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xxp1;
+ struct cvmx_ciu_intx_en4_1_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t wdog:12;
+ } cn56xx;
+ struct cvmx_ciu_intx_en4_1_cn56xx cn56xxp1;
+ struct cvmx_ciu_intx_en4_1_cn58xx {
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+ } cn58xx;
+ struct cvmx_ciu_intx_en4_1_cn58xx cn58xxp1;
+};
+
+union cvmx_ciu_intx_en4_1_w1c {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en4_1_w1c_s {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t wdog:16;
+ } s;
+ struct cvmx_ciu_intx_en4_1_w1c_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xx;
+ struct cvmx_ciu_intx_en4_1_w1c_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t wdog:12;
+ } cn56xx;
+ struct cvmx_ciu_intx_en4_1_w1c_cn58xx {
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_en4_1_w1s {
+ uint64_t u64;
+ struct cvmx_ciu_intx_en4_1_w1s_s {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t wdog:16;
+ } s;
+ struct cvmx_ciu_intx_en4_1_w1s_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xx;
+ struct cvmx_ciu_intx_en4_1_w1s_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t wdog:12;
+ } cn56xx;
+ struct cvmx_ciu_intx_en4_1_w1s_cn58xx {
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+ } cn58xx;
+};
+
+union cvmx_ciu_intx_sum0 {
+ uint64_t u64;
+ struct cvmx_ciu_intx_sum0_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_sum0_cn30xx {
+ uint64_t reserved_59_63:5;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t reserved_47_47:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn30xx;
+ struct cvmx_ciu_intx_sum0_cn31xx {
+ uint64_t reserved_59_63:5;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn31xx;
+ struct cvmx_ciu_intx_sum0_cn38xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn38xx;
+ struct cvmx_ciu_intx_sum0_cn38xx cn38xxp2;
+ struct cvmx_ciu_intx_sum0_cn30xx cn50xx;
+ struct cvmx_ciu_intx_sum0_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_sum0_cn52xx cn52xxp1;
+ struct cvmx_ciu_intx_sum0_cn56xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn56xx;
+ struct cvmx_ciu_intx_sum0_cn56xx cn56xxp1;
+ struct cvmx_ciu_intx_sum0_cn38xx cn58xx;
+ struct cvmx_ciu_intx_sum0_cn38xx cn58xxp1;
+};
+
+union cvmx_ciu_intx_sum4 {
+ uint64_t u64;
+ struct cvmx_ciu_intx_sum4_s {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } s;
+ struct cvmx_ciu_intx_sum4_cn50xx {
+ uint64_t reserved_59_63:5;
+ uint64_t mpi:1;
+ uint64_t pcm:1;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t reserved_47_47:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn50xx;
+ struct cvmx_ciu_intx_sum4_cn52xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t reserved_51_51:1;
+ uint64_t ipd_drp:1;
+ uint64_t reserved_49_49:1;
+ uint64_t gmx_drp:1;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn52xx;
+ struct cvmx_ciu_intx_sum4_cn52xx cn52xxp1;
+ struct cvmx_ciu_intx_sum4_cn56xx {
+ uint64_t bootdma:1;
+ uint64_t mii:1;
+ uint64_t ipdppthr:1;
+ uint64_t powiq:1;
+ uint64_t twsi2:1;
+ uint64_t reserved_57_58:2;
+ uint64_t usb:1;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn56xx;
+ struct cvmx_ciu_intx_sum4_cn56xx cn56xxp1;
+ struct cvmx_ciu_intx_sum4_cn58xx {
+ uint64_t reserved_56_63:8;
+ uint64_t timer:4;
+ uint64_t key_zero:1;
+ uint64_t ipd_drp:1;
+ uint64_t gmx_drp:2;
+ uint64_t trace:1;
+ uint64_t rml:1;
+ uint64_t twsi:1;
+ uint64_t wdog_sum:1;
+ uint64_t pci_msi:4;
+ uint64_t pci_int:4;
+ uint64_t uart:2;
+ uint64_t mbox:2;
+ uint64_t gpio:16;
+ uint64_t workq:16;
+ } cn58xx;
+ struct cvmx_ciu_intx_sum4_cn58xx cn58xxp1;
+};
+
+union cvmx_ciu_int_sum1 {
+ uint64_t u64;
+ struct cvmx_ciu_int_sum1_s {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t wdog:16;
+ } s;
+ struct cvmx_ciu_int_sum1_cn30xx {
+ uint64_t reserved_1_63:63;
+ uint64_t wdog:1;
+ } cn30xx;
+ struct cvmx_ciu_int_sum1_cn31xx {
+ uint64_t reserved_2_63:62;
+ uint64_t wdog:2;
+ } cn31xx;
+ struct cvmx_ciu_int_sum1_cn38xx {
+ uint64_t reserved_16_63:48;
+ uint64_t wdog:16;
+ } cn38xx;
+ struct cvmx_ciu_int_sum1_cn38xx cn38xxp2;
+ struct cvmx_ciu_int_sum1_cn31xx cn50xx;
+ struct cvmx_ciu_int_sum1_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t nand:1;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xx;
+ struct cvmx_ciu_int_sum1_cn52xxp1 {
+ uint64_t reserved_19_63:45;
+ uint64_t mii1:1;
+ uint64_t usb1:1;
+ uint64_t uart2:1;
+ uint64_t reserved_4_15:12;
+ uint64_t wdog:4;
+ } cn52xxp1;
+ struct cvmx_ciu_int_sum1_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t wdog:12;
+ } cn56xx;
+ struct cvmx_ciu_int_sum1_cn56xx cn56xxp1;
+ struct cvmx_ciu_int_sum1_cn38xx cn58xx;
+ struct cvmx_ciu_int_sum1_cn38xx cn58xxp1;
+};
+
+union cvmx_ciu_mbox_clrx {
+ uint64_t u64;
+ struct cvmx_ciu_mbox_clrx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t bits:32;
+ } s;
+ struct cvmx_ciu_mbox_clrx_s cn30xx;
+ struct cvmx_ciu_mbox_clrx_s cn31xx;
+ struct cvmx_ciu_mbox_clrx_s cn38xx;
+ struct cvmx_ciu_mbox_clrx_s cn38xxp2;
+ struct cvmx_ciu_mbox_clrx_s cn50xx;
+ struct cvmx_ciu_mbox_clrx_s cn52xx;
+ struct cvmx_ciu_mbox_clrx_s cn52xxp1;
+ struct cvmx_ciu_mbox_clrx_s cn56xx;
+ struct cvmx_ciu_mbox_clrx_s cn56xxp1;
+ struct cvmx_ciu_mbox_clrx_s cn58xx;
+ struct cvmx_ciu_mbox_clrx_s cn58xxp1;
+};
+
+union cvmx_ciu_mbox_setx {
+ uint64_t u64;
+ struct cvmx_ciu_mbox_setx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t bits:32;
+ } s;
+ struct cvmx_ciu_mbox_setx_s cn30xx;
+ struct cvmx_ciu_mbox_setx_s cn31xx;
+ struct cvmx_ciu_mbox_setx_s cn38xx;
+ struct cvmx_ciu_mbox_setx_s cn38xxp2;
+ struct cvmx_ciu_mbox_setx_s cn50xx;
+ struct cvmx_ciu_mbox_setx_s cn52xx;
+ struct cvmx_ciu_mbox_setx_s cn52xxp1;
+ struct cvmx_ciu_mbox_setx_s cn56xx;
+ struct cvmx_ciu_mbox_setx_s cn56xxp1;
+ struct cvmx_ciu_mbox_setx_s cn58xx;
+ struct cvmx_ciu_mbox_setx_s cn58xxp1;
+};
+
+union cvmx_ciu_nmi {
+ uint64_t u64;
+ struct cvmx_ciu_nmi_s {
+ uint64_t reserved_16_63:48;
+ uint64_t nmi:16;
+ } s;
+ struct cvmx_ciu_nmi_cn30xx {
+ uint64_t reserved_1_63:63;
+ uint64_t nmi:1;
+ } cn30xx;
+ struct cvmx_ciu_nmi_cn31xx {
+ uint64_t reserved_2_63:62;
+ uint64_t nmi:2;
+ } cn31xx;
+ struct cvmx_ciu_nmi_s cn38xx;
+ struct cvmx_ciu_nmi_s cn38xxp2;
+ struct cvmx_ciu_nmi_cn31xx cn50xx;
+ struct cvmx_ciu_nmi_cn52xx {
+ uint64_t reserved_4_63:60;
+ uint64_t nmi:4;
+ } cn52xx;
+ struct cvmx_ciu_nmi_cn52xx cn52xxp1;
+ struct cvmx_ciu_nmi_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t nmi:12;
+ } cn56xx;
+ struct cvmx_ciu_nmi_cn56xx cn56xxp1;
+ struct cvmx_ciu_nmi_s cn58xx;
+ struct cvmx_ciu_nmi_s cn58xxp1;
+};
+
+union cvmx_ciu_pci_inta {
+ uint64_t u64;
+ struct cvmx_ciu_pci_inta_s {
+ uint64_t reserved_2_63:62;
+ uint64_t intr:2;
+ } s;
+ struct cvmx_ciu_pci_inta_s cn30xx;
+ struct cvmx_ciu_pci_inta_s cn31xx;
+ struct cvmx_ciu_pci_inta_s cn38xx;
+ struct cvmx_ciu_pci_inta_s cn38xxp2;
+ struct cvmx_ciu_pci_inta_s cn50xx;
+ struct cvmx_ciu_pci_inta_s cn52xx;
+ struct cvmx_ciu_pci_inta_s cn52xxp1;
+ struct cvmx_ciu_pci_inta_s cn56xx;
+ struct cvmx_ciu_pci_inta_s cn56xxp1;
+ struct cvmx_ciu_pci_inta_s cn58xx;
+ struct cvmx_ciu_pci_inta_s cn58xxp1;
+};
+
+union cvmx_ciu_pp_dbg {
+ uint64_t u64;
+ struct cvmx_ciu_pp_dbg_s {
+ uint64_t reserved_16_63:48;
+ uint64_t ppdbg:16;
+ } s;
+ struct cvmx_ciu_pp_dbg_cn30xx {
+ uint64_t reserved_1_63:63;
+ uint64_t ppdbg:1;
+ } cn30xx;
+ struct cvmx_ciu_pp_dbg_cn31xx {
+ uint64_t reserved_2_63:62;
+ uint64_t ppdbg:2;
+ } cn31xx;
+ struct cvmx_ciu_pp_dbg_s cn38xx;
+ struct cvmx_ciu_pp_dbg_s cn38xxp2;
+ struct cvmx_ciu_pp_dbg_cn31xx cn50xx;
+ struct cvmx_ciu_pp_dbg_cn52xx {
+ uint64_t reserved_4_63:60;
+ uint64_t ppdbg:4;
+ } cn52xx;
+ struct cvmx_ciu_pp_dbg_cn52xx cn52xxp1;
+ struct cvmx_ciu_pp_dbg_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t ppdbg:12;
+ } cn56xx;
+ struct cvmx_ciu_pp_dbg_cn56xx cn56xxp1;
+ struct cvmx_ciu_pp_dbg_s cn58xx;
+ struct cvmx_ciu_pp_dbg_s cn58xxp1;
+};
+
+union cvmx_ciu_pp_pokex {
+ uint64_t u64;
+ struct cvmx_ciu_pp_pokex_s {
+ uint64_t reserved_0_63:64;
+ } s;
+ struct cvmx_ciu_pp_pokex_s cn30xx;
+ struct cvmx_ciu_pp_pokex_s cn31xx;
+ struct cvmx_ciu_pp_pokex_s cn38xx;
+ struct cvmx_ciu_pp_pokex_s cn38xxp2;
+ struct cvmx_ciu_pp_pokex_s cn50xx;
+ struct cvmx_ciu_pp_pokex_s cn52xx;
+ struct cvmx_ciu_pp_pokex_s cn52xxp1;
+ struct cvmx_ciu_pp_pokex_s cn56xx;
+ struct cvmx_ciu_pp_pokex_s cn56xxp1;
+ struct cvmx_ciu_pp_pokex_s cn58xx;
+ struct cvmx_ciu_pp_pokex_s cn58xxp1;
+};
+
+union cvmx_ciu_pp_rst {
+ uint64_t u64;
+ struct cvmx_ciu_pp_rst_s {
+ uint64_t reserved_16_63:48;
+ uint64_t rst:15;
+ uint64_t rst0:1;
+ } s;
+ struct cvmx_ciu_pp_rst_cn30xx {
+ uint64_t reserved_1_63:63;
+ uint64_t rst0:1;
+ } cn30xx;
+ struct cvmx_ciu_pp_rst_cn31xx {
+ uint64_t reserved_2_63:62;
+ uint64_t rst:1;
+ uint64_t rst0:1;
+ } cn31xx;
+ struct cvmx_ciu_pp_rst_s cn38xx;
+ struct cvmx_ciu_pp_rst_s cn38xxp2;
+ struct cvmx_ciu_pp_rst_cn31xx cn50xx;
+ struct cvmx_ciu_pp_rst_cn52xx {
+ uint64_t reserved_4_63:60;
+ uint64_t rst:3;
+ uint64_t rst0:1;
+ } cn52xx;
+ struct cvmx_ciu_pp_rst_cn52xx cn52xxp1;
+ struct cvmx_ciu_pp_rst_cn56xx {
+ uint64_t reserved_12_63:52;
+ uint64_t rst:11;
+ uint64_t rst0:1;
+ } cn56xx;
+ struct cvmx_ciu_pp_rst_cn56xx cn56xxp1;
+ struct cvmx_ciu_pp_rst_s cn58xx;
+ struct cvmx_ciu_pp_rst_s cn58xxp1;
+};
+
+union cvmx_ciu_qlm_dcok {
+ uint64_t u64;
+ struct cvmx_ciu_qlm_dcok_s {
+ uint64_t reserved_4_63:60;
+ uint64_t qlm_dcok:4;
+ } s;
+ struct cvmx_ciu_qlm_dcok_cn52xx {
+ uint64_t reserved_2_63:62;
+ uint64_t qlm_dcok:2;
+ } cn52xx;
+ struct cvmx_ciu_qlm_dcok_cn52xx cn52xxp1;
+ struct cvmx_ciu_qlm_dcok_s cn56xx;
+ struct cvmx_ciu_qlm_dcok_s cn56xxp1;
+};
+
+union cvmx_ciu_qlm_jtgc {
+ uint64_t u64;
+ struct cvmx_ciu_qlm_jtgc_s {
+ uint64_t reserved_11_63:53;
+ uint64_t clk_div:3;
+ uint64_t reserved_6_7:2;
+ uint64_t mux_sel:2;
+ uint64_t bypass:4;
+ } s;
+ struct cvmx_ciu_qlm_jtgc_cn52xx {
+ uint64_t reserved_11_63:53;
+ uint64_t clk_div:3;
+ uint64_t reserved_5_7:3;
+ uint64_t mux_sel:1;
+ uint64_t reserved_2_3:2;
+ uint64_t bypass:2;
+ } cn52xx;
+ struct cvmx_ciu_qlm_jtgc_cn52xx cn52xxp1;
+ struct cvmx_ciu_qlm_jtgc_s cn56xx;
+ struct cvmx_ciu_qlm_jtgc_s cn56xxp1;
+};
+
+union cvmx_ciu_qlm_jtgd {
+ uint64_t u64;
+ struct cvmx_ciu_qlm_jtgd_s {
+ uint64_t capture:1;
+ uint64_t shift:1;
+ uint64_t update:1;
+ uint64_t reserved_44_60:17;
+ uint64_t select:4;
+ uint64_t reserved_37_39:3;
+ uint64_t shft_cnt:5;
+ uint64_t shft_reg:32;
+ } s;
+ struct cvmx_ciu_qlm_jtgd_cn52xx {
+ uint64_t capture:1;
+ uint64_t shift:1;
+ uint64_t update:1;
+ uint64_t reserved_42_60:19;
+ uint64_t select:2;
+ uint64_t reserved_37_39:3;
+ uint64_t shft_cnt:5;
+ uint64_t shft_reg:32;
+ } cn52xx;
+ struct cvmx_ciu_qlm_jtgd_cn52xx cn52xxp1;
+ struct cvmx_ciu_qlm_jtgd_s cn56xx;
+ struct cvmx_ciu_qlm_jtgd_cn56xxp1 {
+ uint64_t capture:1;
+ uint64_t shift:1;
+ uint64_t update:1;
+ uint64_t reserved_37_60:24;
+ uint64_t shft_cnt:5;
+ uint64_t shft_reg:32;
+ } cn56xxp1;
+};
+
+union cvmx_ciu_soft_bist {
+ uint64_t u64;
+ struct cvmx_ciu_soft_bist_s {
+ uint64_t reserved_1_63:63;
+ uint64_t soft_bist:1;
+ } s;
+ struct cvmx_ciu_soft_bist_s cn30xx;
+ struct cvmx_ciu_soft_bist_s cn31xx;
+ struct cvmx_ciu_soft_bist_s cn38xx;
+ struct cvmx_ciu_soft_bist_s cn38xxp2;
+ struct cvmx_ciu_soft_bist_s cn50xx;
+ struct cvmx_ciu_soft_bist_s cn52xx;
+ struct cvmx_ciu_soft_bist_s cn52xxp1;
+ struct cvmx_ciu_soft_bist_s cn56xx;
+ struct cvmx_ciu_soft_bist_s cn56xxp1;
+ struct cvmx_ciu_soft_bist_s cn58xx;
+ struct cvmx_ciu_soft_bist_s cn58xxp1;
+};
+
+union cvmx_ciu_soft_prst {
+ uint64_t u64;
+ struct cvmx_ciu_soft_prst_s {
+ uint64_t reserved_3_63:61;
+ uint64_t host64:1;
+ uint64_t npi:1;
+ uint64_t soft_prst:1;
+ } s;
+ struct cvmx_ciu_soft_prst_s cn30xx;
+ struct cvmx_ciu_soft_prst_s cn31xx;
+ struct cvmx_ciu_soft_prst_s cn38xx;
+ struct cvmx_ciu_soft_prst_s cn38xxp2;
+ struct cvmx_ciu_soft_prst_s cn50xx;
+ struct cvmx_ciu_soft_prst_cn52xx {
+ uint64_t reserved_1_63:63;
+ uint64_t soft_prst:1;
+ } cn52xx;
+ struct cvmx_ciu_soft_prst_cn52xx cn52xxp1;
+ struct cvmx_ciu_soft_prst_cn52xx cn56xx;
+ struct cvmx_ciu_soft_prst_cn52xx cn56xxp1;
+ struct cvmx_ciu_soft_prst_s cn58xx;
+ struct cvmx_ciu_soft_prst_s cn58xxp1;
+};
+
+union cvmx_ciu_soft_prst1 {
+ uint64_t u64;
+ struct cvmx_ciu_soft_prst1_s {
+ uint64_t reserved_1_63:63;
+ uint64_t soft_prst:1;
+ } s;
+ struct cvmx_ciu_soft_prst1_s cn52xx;
+ struct cvmx_ciu_soft_prst1_s cn52xxp1;
+ struct cvmx_ciu_soft_prst1_s cn56xx;
+ struct cvmx_ciu_soft_prst1_s cn56xxp1;
+};
+
+union cvmx_ciu_soft_rst {
+ uint64_t u64;
+ struct cvmx_ciu_soft_rst_s {
+ uint64_t reserved_1_63:63;
+ uint64_t soft_rst:1;
+ } s;
+ struct cvmx_ciu_soft_rst_s cn30xx;
+ struct cvmx_ciu_soft_rst_s cn31xx;
+ struct cvmx_ciu_soft_rst_s cn38xx;
+ struct cvmx_ciu_soft_rst_s cn38xxp2;
+ struct cvmx_ciu_soft_rst_s cn50xx;
+ struct cvmx_ciu_soft_rst_s cn52xx;
+ struct cvmx_ciu_soft_rst_s cn52xxp1;
+ struct cvmx_ciu_soft_rst_s cn56xx;
+ struct cvmx_ciu_soft_rst_s cn56xxp1;
+ struct cvmx_ciu_soft_rst_s cn58xx;
+ struct cvmx_ciu_soft_rst_s cn58xxp1;
+};
+
+union cvmx_ciu_timx {
+ uint64_t u64;
+ struct cvmx_ciu_timx_s {
+ uint64_t reserved_37_63:27;
+ uint64_t one_shot:1;
+ uint64_t len:36;
+ } s;
+ struct cvmx_ciu_timx_s cn30xx;
+ struct cvmx_ciu_timx_s cn31xx;
+ struct cvmx_ciu_timx_s cn38xx;
+ struct cvmx_ciu_timx_s cn38xxp2;
+ struct cvmx_ciu_timx_s cn50xx;
+ struct cvmx_ciu_timx_s cn52xx;
+ struct cvmx_ciu_timx_s cn52xxp1;
+ struct cvmx_ciu_timx_s cn56xx;
+ struct cvmx_ciu_timx_s cn56xxp1;
+ struct cvmx_ciu_timx_s cn58xx;
+ struct cvmx_ciu_timx_s cn58xxp1;
+};
+
+union cvmx_ciu_wdogx {
+ uint64_t u64;
+ struct cvmx_ciu_wdogx_s {
+ uint64_t reserved_46_63:18;
+ uint64_t gstopen:1;
+ uint64_t dstop:1;
+ uint64_t cnt:24;
+ uint64_t len:16;
+ uint64_t state:2;
+ uint64_t mode:2;
+ } s;
+ struct cvmx_ciu_wdogx_s cn30xx;
+ struct cvmx_ciu_wdogx_s cn31xx;
+ struct cvmx_ciu_wdogx_s cn38xx;
+ struct cvmx_ciu_wdogx_s cn38xxp2;
+ struct cvmx_ciu_wdogx_s cn50xx;
+ struct cvmx_ciu_wdogx_s cn52xx;
+ struct cvmx_ciu_wdogx_s cn52xxp1;
+ struct cvmx_ciu_wdogx_s cn56xx;
+ struct cvmx_ciu_wdogx_s cn56xxp1;
+ struct cvmx_ciu_wdogx_s cn58xx;
+ struct cvmx_ciu_wdogx_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-gpio-defs.h b/arch/mips/include/asm/octeon/cvmx-gpio-defs.h
new file mode 100644
index 000000000000..5fdd6ba48a05
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-gpio-defs.h
@@ -0,0 +1,219 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_GPIO_DEFS_H__
+#define __CVMX_GPIO_DEFS_H__
+
+#define CVMX_GPIO_BIT_CFGX(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000800ull + (((offset) & 15) * 8))
+#define CVMX_GPIO_BOOT_ENA \
+ CVMX_ADD_IO_SEG(0x00010700000008A8ull)
+#define CVMX_GPIO_CLK_GENX(offset) \
+ CVMX_ADD_IO_SEG(0x00010700000008C0ull + (((offset) & 3) * 8))
+#define CVMX_GPIO_DBG_ENA \
+ CVMX_ADD_IO_SEG(0x00010700000008A0ull)
+#define CVMX_GPIO_INT_CLR \
+ CVMX_ADD_IO_SEG(0x0001070000000898ull)
+#define CVMX_GPIO_RX_DAT \
+ CVMX_ADD_IO_SEG(0x0001070000000880ull)
+#define CVMX_GPIO_TX_CLR \
+ CVMX_ADD_IO_SEG(0x0001070000000890ull)
+#define CVMX_GPIO_TX_SET \
+ CVMX_ADD_IO_SEG(0x0001070000000888ull)
+#define CVMX_GPIO_XBIT_CFGX(offset) \
+ CVMX_ADD_IO_SEG(0x0001070000000900ull + (((offset) & 31) * 8) - 8 * 16)
+
+union cvmx_gpio_bit_cfgx {
+ uint64_t u64;
+ struct cvmx_gpio_bit_cfgx_s {
+ uint64_t reserved_15_63:49;
+ uint64_t clk_gen:1;
+ uint64_t clk_sel:2;
+ uint64_t fil_sel:4;
+ uint64_t fil_cnt:4;
+ uint64_t int_type:1;
+ uint64_t int_en:1;
+ uint64_t rx_xor:1;
+ uint64_t tx_oe:1;
+ } s;
+ struct cvmx_gpio_bit_cfgx_cn30xx {
+ uint64_t reserved_12_63:52;
+ uint64_t fil_sel:4;
+ uint64_t fil_cnt:4;
+ uint64_t int_type:1;
+ uint64_t int_en:1;
+ uint64_t rx_xor:1;
+ uint64_t tx_oe:1;
+ } cn30xx;
+ struct cvmx_gpio_bit_cfgx_cn30xx cn31xx;
+ struct cvmx_gpio_bit_cfgx_cn30xx cn38xx;
+ struct cvmx_gpio_bit_cfgx_cn30xx cn38xxp2;
+ struct cvmx_gpio_bit_cfgx_cn30xx cn50xx;
+ struct cvmx_gpio_bit_cfgx_s cn52xx;
+ struct cvmx_gpio_bit_cfgx_s cn52xxp1;
+ struct cvmx_gpio_bit_cfgx_s cn56xx;
+ struct cvmx_gpio_bit_cfgx_s cn56xxp1;
+ struct cvmx_gpio_bit_cfgx_cn30xx cn58xx;
+ struct cvmx_gpio_bit_cfgx_cn30xx cn58xxp1;
+};
+
+union cvmx_gpio_boot_ena {
+ uint64_t u64;
+ struct cvmx_gpio_boot_ena_s {
+ uint64_t reserved_12_63:52;
+ uint64_t boot_ena:4;
+ uint64_t reserved_0_7:8;
+ } s;
+ struct cvmx_gpio_boot_ena_s cn30xx;
+ struct cvmx_gpio_boot_ena_s cn31xx;
+ struct cvmx_gpio_boot_ena_s cn50xx;
+};
+
+union cvmx_gpio_clk_genx {
+ uint64_t u64;
+ struct cvmx_gpio_clk_genx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t n:32;
+ } s;
+ struct cvmx_gpio_clk_genx_s cn52xx;
+ struct cvmx_gpio_clk_genx_s cn52xxp1;
+ struct cvmx_gpio_clk_genx_s cn56xx;
+ struct cvmx_gpio_clk_genx_s cn56xxp1;
+};
+
+union cvmx_gpio_dbg_ena {
+ uint64_t u64;
+ struct cvmx_gpio_dbg_ena_s {
+ uint64_t reserved_21_63:43;
+ uint64_t dbg_ena:21;
+ } s;
+ struct cvmx_gpio_dbg_ena_s cn30xx;
+ struct cvmx_gpio_dbg_ena_s cn31xx;
+ struct cvmx_gpio_dbg_ena_s cn50xx;
+};
+
+union cvmx_gpio_int_clr {
+ uint64_t u64;
+ struct cvmx_gpio_int_clr_s {
+ uint64_t reserved_16_63:48;
+ uint64_t type:16;
+ } s;
+ struct cvmx_gpio_int_clr_s cn30xx;
+ struct cvmx_gpio_int_clr_s cn31xx;
+ struct cvmx_gpio_int_clr_s cn38xx;
+ struct cvmx_gpio_int_clr_s cn38xxp2;
+ struct cvmx_gpio_int_clr_s cn50xx;
+ struct cvmx_gpio_int_clr_s cn52xx;
+ struct cvmx_gpio_int_clr_s cn52xxp1;
+ struct cvmx_gpio_int_clr_s cn56xx;
+ struct cvmx_gpio_int_clr_s cn56xxp1;
+ struct cvmx_gpio_int_clr_s cn58xx;
+ struct cvmx_gpio_int_clr_s cn58xxp1;
+};
+
+union cvmx_gpio_rx_dat {
+ uint64_t u64;
+ struct cvmx_gpio_rx_dat_s {
+ uint64_t reserved_24_63:40;
+ uint64_t dat:24;
+ } s;
+ struct cvmx_gpio_rx_dat_s cn30xx;
+ struct cvmx_gpio_rx_dat_s cn31xx;
+ struct cvmx_gpio_rx_dat_cn38xx {
+ uint64_t reserved_16_63:48;
+ uint64_t dat:16;
+ } cn38xx;
+ struct cvmx_gpio_rx_dat_cn38xx cn38xxp2;
+ struct cvmx_gpio_rx_dat_s cn50xx;
+ struct cvmx_gpio_rx_dat_cn38xx cn52xx;
+ struct cvmx_gpio_rx_dat_cn38xx cn52xxp1;
+ struct cvmx_gpio_rx_dat_cn38xx cn56xx;
+ struct cvmx_gpio_rx_dat_cn38xx cn56xxp1;
+ struct cvmx_gpio_rx_dat_cn38xx cn58xx;
+ struct cvmx_gpio_rx_dat_cn38xx cn58xxp1;
+};
+
+union cvmx_gpio_tx_clr {
+ uint64_t u64;
+ struct cvmx_gpio_tx_clr_s {
+ uint64_t reserved_24_63:40;
+ uint64_t clr:24;
+ } s;
+ struct cvmx_gpio_tx_clr_s cn30xx;
+ struct cvmx_gpio_tx_clr_s cn31xx;
+ struct cvmx_gpio_tx_clr_cn38xx {
+ uint64_t reserved_16_63:48;
+ uint64_t clr:16;
+ } cn38xx;
+ struct cvmx_gpio_tx_clr_cn38xx cn38xxp2;
+ struct cvmx_gpio_tx_clr_s cn50xx;
+ struct cvmx_gpio_tx_clr_cn38xx cn52xx;
+ struct cvmx_gpio_tx_clr_cn38xx cn52xxp1;
+ struct cvmx_gpio_tx_clr_cn38xx cn56xx;
+ struct cvmx_gpio_tx_clr_cn38xx cn56xxp1;
+ struct cvmx_gpio_tx_clr_cn38xx cn58xx;
+ struct cvmx_gpio_tx_clr_cn38xx cn58xxp1;
+};
+
+union cvmx_gpio_tx_set {
+ uint64_t u64;
+ struct cvmx_gpio_tx_set_s {
+ uint64_t reserved_24_63:40;
+ uint64_t set:24;
+ } s;
+ struct cvmx_gpio_tx_set_s cn30xx;
+ struct cvmx_gpio_tx_set_s cn31xx;
+ struct cvmx_gpio_tx_set_cn38xx {
+ uint64_t reserved_16_63:48;
+ uint64_t set:16;
+ } cn38xx;
+ struct cvmx_gpio_tx_set_cn38xx cn38xxp2;
+ struct cvmx_gpio_tx_set_s cn50xx;
+ struct cvmx_gpio_tx_set_cn38xx cn52xx;
+ struct cvmx_gpio_tx_set_cn38xx cn52xxp1;
+ struct cvmx_gpio_tx_set_cn38xx cn56xx;
+ struct cvmx_gpio_tx_set_cn38xx cn56xxp1;
+ struct cvmx_gpio_tx_set_cn38xx cn58xx;
+ struct cvmx_gpio_tx_set_cn38xx cn58xxp1;
+};
+
+union cvmx_gpio_xbit_cfgx {
+ uint64_t u64;
+ struct cvmx_gpio_xbit_cfgx_s {
+ uint64_t reserved_12_63:52;
+ uint64_t fil_sel:4;
+ uint64_t fil_cnt:4;
+ uint64_t reserved_2_3:2;
+ uint64_t rx_xor:1;
+ uint64_t tx_oe:1;
+ } s;
+ struct cvmx_gpio_xbit_cfgx_s cn30xx;
+ struct cvmx_gpio_xbit_cfgx_s cn31xx;
+ struct cvmx_gpio_xbit_cfgx_s cn50xx;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-iob-defs.h b/arch/mips/include/asm/octeon/cvmx-iob-defs.h
new file mode 100644
index 000000000000..0ee36baec500
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-iob-defs.h
@@ -0,0 +1,530 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_IOB_DEFS_H__
+#define __CVMX_IOB_DEFS_H__
+
+#define CVMX_IOB_BIST_STATUS \
+ CVMX_ADD_IO_SEG(0x00011800F00007F8ull)
+#define CVMX_IOB_CTL_STATUS \
+ CVMX_ADD_IO_SEG(0x00011800F0000050ull)
+#define CVMX_IOB_DWB_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000028ull)
+#define CVMX_IOB_FAU_TIMEOUT \
+ CVMX_ADD_IO_SEG(0x00011800F0000000ull)
+#define CVMX_IOB_I2C_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000010ull)
+#define CVMX_IOB_INB_CONTROL_MATCH \
+ CVMX_ADD_IO_SEG(0x00011800F0000078ull)
+#define CVMX_IOB_INB_CONTROL_MATCH_ENB \
+ CVMX_ADD_IO_SEG(0x00011800F0000088ull)
+#define CVMX_IOB_INB_DATA_MATCH \
+ CVMX_ADD_IO_SEG(0x00011800F0000070ull)
+#define CVMX_IOB_INB_DATA_MATCH_ENB \
+ CVMX_ADD_IO_SEG(0x00011800F0000080ull)
+#define CVMX_IOB_INT_ENB \
+ CVMX_ADD_IO_SEG(0x00011800F0000060ull)
+#define CVMX_IOB_INT_SUM \
+ CVMX_ADD_IO_SEG(0x00011800F0000058ull)
+#define CVMX_IOB_N2C_L2C_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000020ull)
+#define CVMX_IOB_N2C_RSP_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000008ull)
+#define CVMX_IOB_OUTB_COM_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000040ull)
+#define CVMX_IOB_OUTB_CONTROL_MATCH \
+ CVMX_ADD_IO_SEG(0x00011800F0000098ull)
+#define CVMX_IOB_OUTB_CONTROL_MATCH_ENB \
+ CVMX_ADD_IO_SEG(0x00011800F00000A8ull)
+#define CVMX_IOB_OUTB_DATA_MATCH \
+ CVMX_ADD_IO_SEG(0x00011800F0000090ull)
+#define CVMX_IOB_OUTB_DATA_MATCH_ENB \
+ CVMX_ADD_IO_SEG(0x00011800F00000A0ull)
+#define CVMX_IOB_OUTB_FPA_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000048ull)
+#define CVMX_IOB_OUTB_REQ_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000038ull)
+#define CVMX_IOB_P2C_REQ_PRI_CNT \
+ CVMX_ADD_IO_SEG(0x00011800F0000018ull)
+#define CVMX_IOB_PKT_ERR \
+ CVMX_ADD_IO_SEG(0x00011800F0000068ull)
+
+union cvmx_iob_bist_status {
+ uint64_t u64;
+ struct cvmx_iob_bist_status_s {
+ uint64_t reserved_18_63:46;
+ uint64_t icnrcb:1;
+ uint64_t icr0:1;
+ uint64_t icr1:1;
+ uint64_t icnr1:1;
+ uint64_t icnr0:1;
+ uint64_t ibdr0:1;
+ uint64_t ibdr1:1;
+ uint64_t ibr0:1;
+ uint64_t ibr1:1;
+ uint64_t icnrt:1;
+ uint64_t ibrq0:1;
+ uint64_t ibrq1:1;
+ uint64_t icrn0:1;
+ uint64_t icrn1:1;
+ uint64_t icrp0:1;
+ uint64_t icrp1:1;
+ uint64_t ibd:1;
+ uint64_t icd:1;
+ } s;
+ struct cvmx_iob_bist_status_s cn30xx;
+ struct cvmx_iob_bist_status_s cn31xx;
+ struct cvmx_iob_bist_status_s cn38xx;
+ struct cvmx_iob_bist_status_s cn38xxp2;
+ struct cvmx_iob_bist_status_s cn50xx;
+ struct cvmx_iob_bist_status_s cn52xx;
+ struct cvmx_iob_bist_status_s cn52xxp1;
+ struct cvmx_iob_bist_status_s cn56xx;
+ struct cvmx_iob_bist_status_s cn56xxp1;
+ struct cvmx_iob_bist_status_s cn58xx;
+ struct cvmx_iob_bist_status_s cn58xxp1;
+};
+
+union cvmx_iob_ctl_status {
+ uint64_t u64;
+ struct cvmx_iob_ctl_status_s {
+ uint64_t reserved_5_63:59;
+ uint64_t outb_mat:1;
+ uint64_t inb_mat:1;
+ uint64_t pko_enb:1;
+ uint64_t dwb_enb:1;
+ uint64_t fau_end:1;
+ } s;
+ struct cvmx_iob_ctl_status_s cn30xx;
+ struct cvmx_iob_ctl_status_s cn31xx;
+ struct cvmx_iob_ctl_status_s cn38xx;
+ struct cvmx_iob_ctl_status_s cn38xxp2;
+ struct cvmx_iob_ctl_status_s cn50xx;
+ struct cvmx_iob_ctl_status_s cn52xx;
+ struct cvmx_iob_ctl_status_s cn52xxp1;
+ struct cvmx_iob_ctl_status_s cn56xx;
+ struct cvmx_iob_ctl_status_s cn56xxp1;
+ struct cvmx_iob_ctl_status_s cn58xx;
+ struct cvmx_iob_ctl_status_s cn58xxp1;
+};
+
+union cvmx_iob_dwb_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_dwb_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_dwb_pri_cnt_s cn38xx;
+ struct cvmx_iob_dwb_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_dwb_pri_cnt_s cn52xx;
+ struct cvmx_iob_dwb_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_dwb_pri_cnt_s cn56xx;
+ struct cvmx_iob_dwb_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_dwb_pri_cnt_s cn58xx;
+ struct cvmx_iob_dwb_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_fau_timeout {
+ uint64_t u64;
+ struct cvmx_iob_fau_timeout_s {
+ uint64_t reserved_13_63:51;
+ uint64_t tout_enb:1;
+ uint64_t tout_val:12;
+ } s;
+ struct cvmx_iob_fau_timeout_s cn30xx;
+ struct cvmx_iob_fau_timeout_s cn31xx;
+ struct cvmx_iob_fau_timeout_s cn38xx;
+ struct cvmx_iob_fau_timeout_s cn38xxp2;
+ struct cvmx_iob_fau_timeout_s cn50xx;
+ struct cvmx_iob_fau_timeout_s cn52xx;
+ struct cvmx_iob_fau_timeout_s cn52xxp1;
+ struct cvmx_iob_fau_timeout_s cn56xx;
+ struct cvmx_iob_fau_timeout_s cn56xxp1;
+ struct cvmx_iob_fau_timeout_s cn58xx;
+ struct cvmx_iob_fau_timeout_s cn58xxp1;
+};
+
+union cvmx_iob_i2c_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_i2c_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_i2c_pri_cnt_s cn38xx;
+ struct cvmx_iob_i2c_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_i2c_pri_cnt_s cn52xx;
+ struct cvmx_iob_i2c_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_i2c_pri_cnt_s cn56xx;
+ struct cvmx_iob_i2c_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_i2c_pri_cnt_s cn58xx;
+ struct cvmx_iob_i2c_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_inb_control_match {
+ uint64_t u64;
+ struct cvmx_iob_inb_control_match_s {
+ uint64_t reserved_29_63:35;
+ uint64_t mask:8;
+ uint64_t opc:4;
+ uint64_t dst:9;
+ uint64_t src:8;
+ } s;
+ struct cvmx_iob_inb_control_match_s cn30xx;
+ struct cvmx_iob_inb_control_match_s cn31xx;
+ struct cvmx_iob_inb_control_match_s cn38xx;
+ struct cvmx_iob_inb_control_match_s cn38xxp2;
+ struct cvmx_iob_inb_control_match_s cn50xx;
+ struct cvmx_iob_inb_control_match_s cn52xx;
+ struct cvmx_iob_inb_control_match_s cn52xxp1;
+ struct cvmx_iob_inb_control_match_s cn56xx;
+ struct cvmx_iob_inb_control_match_s cn56xxp1;
+ struct cvmx_iob_inb_control_match_s cn58xx;
+ struct cvmx_iob_inb_control_match_s cn58xxp1;
+};
+
+union cvmx_iob_inb_control_match_enb {
+ uint64_t u64;
+ struct cvmx_iob_inb_control_match_enb_s {
+ uint64_t reserved_29_63:35;
+ uint64_t mask:8;
+ uint64_t opc:4;
+ uint64_t dst:9;
+ uint64_t src:8;
+ } s;
+ struct cvmx_iob_inb_control_match_enb_s cn30xx;
+ struct cvmx_iob_inb_control_match_enb_s cn31xx;
+ struct cvmx_iob_inb_control_match_enb_s cn38xx;
+ struct cvmx_iob_inb_control_match_enb_s cn38xxp2;
+ struct cvmx_iob_inb_control_match_enb_s cn50xx;
+ struct cvmx_iob_inb_control_match_enb_s cn52xx;
+ struct cvmx_iob_inb_control_match_enb_s cn52xxp1;
+ struct cvmx_iob_inb_control_match_enb_s cn56xx;
+ struct cvmx_iob_inb_control_match_enb_s cn56xxp1;
+ struct cvmx_iob_inb_control_match_enb_s cn58xx;
+ struct cvmx_iob_inb_control_match_enb_s cn58xxp1;
+};
+
+union cvmx_iob_inb_data_match {
+ uint64_t u64;
+ struct cvmx_iob_inb_data_match_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_iob_inb_data_match_s cn30xx;
+ struct cvmx_iob_inb_data_match_s cn31xx;
+ struct cvmx_iob_inb_data_match_s cn38xx;
+ struct cvmx_iob_inb_data_match_s cn38xxp2;
+ struct cvmx_iob_inb_data_match_s cn50xx;
+ struct cvmx_iob_inb_data_match_s cn52xx;
+ struct cvmx_iob_inb_data_match_s cn52xxp1;
+ struct cvmx_iob_inb_data_match_s cn56xx;
+ struct cvmx_iob_inb_data_match_s cn56xxp1;
+ struct cvmx_iob_inb_data_match_s cn58xx;
+ struct cvmx_iob_inb_data_match_s cn58xxp1;
+};
+
+union cvmx_iob_inb_data_match_enb {
+ uint64_t u64;
+ struct cvmx_iob_inb_data_match_enb_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_iob_inb_data_match_enb_s cn30xx;
+ struct cvmx_iob_inb_data_match_enb_s cn31xx;
+ struct cvmx_iob_inb_data_match_enb_s cn38xx;
+ struct cvmx_iob_inb_data_match_enb_s cn38xxp2;
+ struct cvmx_iob_inb_data_match_enb_s cn50xx;
+ struct cvmx_iob_inb_data_match_enb_s cn52xx;
+ struct cvmx_iob_inb_data_match_enb_s cn52xxp1;
+ struct cvmx_iob_inb_data_match_enb_s cn56xx;
+ struct cvmx_iob_inb_data_match_enb_s cn56xxp1;
+ struct cvmx_iob_inb_data_match_enb_s cn58xx;
+ struct cvmx_iob_inb_data_match_enb_s cn58xxp1;
+};
+
+union cvmx_iob_int_enb {
+ uint64_t u64;
+ struct cvmx_iob_int_enb_s {
+ uint64_t reserved_6_63:58;
+ uint64_t p_dat:1;
+ uint64_t np_dat:1;
+ uint64_t p_eop:1;
+ uint64_t p_sop:1;
+ uint64_t np_eop:1;
+ uint64_t np_sop:1;
+ } s;
+ struct cvmx_iob_int_enb_cn30xx {
+ uint64_t reserved_4_63:60;
+ uint64_t p_eop:1;
+ uint64_t p_sop:1;
+ uint64_t np_eop:1;
+ uint64_t np_sop:1;
+ } cn30xx;
+ struct cvmx_iob_int_enb_cn30xx cn31xx;
+ struct cvmx_iob_int_enb_cn30xx cn38xx;
+ struct cvmx_iob_int_enb_cn30xx cn38xxp2;
+ struct cvmx_iob_int_enb_s cn50xx;
+ struct cvmx_iob_int_enb_s cn52xx;
+ struct cvmx_iob_int_enb_s cn52xxp1;
+ struct cvmx_iob_int_enb_s cn56xx;
+ struct cvmx_iob_int_enb_s cn56xxp1;
+ struct cvmx_iob_int_enb_s cn58xx;
+ struct cvmx_iob_int_enb_s cn58xxp1;
+};
+
+union cvmx_iob_int_sum {
+ uint64_t u64;
+ struct cvmx_iob_int_sum_s {
+ uint64_t reserved_6_63:58;
+ uint64_t p_dat:1;
+ uint64_t np_dat:1;
+ uint64_t p_eop:1;
+ uint64_t p_sop:1;
+ uint64_t np_eop:1;
+ uint64_t np_sop:1;
+ } s;
+ struct cvmx_iob_int_sum_cn30xx {
+ uint64_t reserved_4_63:60;
+ uint64_t p_eop:1;
+ uint64_t p_sop:1;
+ uint64_t np_eop:1;
+ uint64_t np_sop:1;
+ } cn30xx;
+ struct cvmx_iob_int_sum_cn30xx cn31xx;
+ struct cvmx_iob_int_sum_cn30xx cn38xx;
+ struct cvmx_iob_int_sum_cn30xx cn38xxp2;
+ struct cvmx_iob_int_sum_s cn50xx;
+ struct cvmx_iob_int_sum_s cn52xx;
+ struct cvmx_iob_int_sum_s cn52xxp1;
+ struct cvmx_iob_int_sum_s cn56xx;
+ struct cvmx_iob_int_sum_s cn56xxp1;
+ struct cvmx_iob_int_sum_s cn58xx;
+ struct cvmx_iob_int_sum_s cn58xxp1;
+};
+
+union cvmx_iob_n2c_l2c_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn38xx;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn52xx;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn56xx;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn58xx;
+ struct cvmx_iob_n2c_l2c_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_n2c_rsp_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn38xx;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn52xx;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn56xx;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn58xx;
+ struct cvmx_iob_n2c_rsp_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_outb_com_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_outb_com_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_outb_com_pri_cnt_s cn38xx;
+ struct cvmx_iob_outb_com_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_outb_com_pri_cnt_s cn52xx;
+ struct cvmx_iob_outb_com_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_outb_com_pri_cnt_s cn56xx;
+ struct cvmx_iob_outb_com_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_outb_com_pri_cnt_s cn58xx;
+ struct cvmx_iob_outb_com_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_outb_control_match {
+ uint64_t u64;
+ struct cvmx_iob_outb_control_match_s {
+ uint64_t reserved_26_63:38;
+ uint64_t mask:8;
+ uint64_t eot:1;
+ uint64_t dst:8;
+ uint64_t src:9;
+ } s;
+ struct cvmx_iob_outb_control_match_s cn30xx;
+ struct cvmx_iob_outb_control_match_s cn31xx;
+ struct cvmx_iob_outb_control_match_s cn38xx;
+ struct cvmx_iob_outb_control_match_s cn38xxp2;
+ struct cvmx_iob_outb_control_match_s cn50xx;
+ struct cvmx_iob_outb_control_match_s cn52xx;
+ struct cvmx_iob_outb_control_match_s cn52xxp1;
+ struct cvmx_iob_outb_control_match_s cn56xx;
+ struct cvmx_iob_outb_control_match_s cn56xxp1;
+ struct cvmx_iob_outb_control_match_s cn58xx;
+ struct cvmx_iob_outb_control_match_s cn58xxp1;
+};
+
+union cvmx_iob_outb_control_match_enb {
+ uint64_t u64;
+ struct cvmx_iob_outb_control_match_enb_s {
+ uint64_t reserved_26_63:38;
+ uint64_t mask:8;
+ uint64_t eot:1;
+ uint64_t dst:8;
+ uint64_t src:9;
+ } s;
+ struct cvmx_iob_outb_control_match_enb_s cn30xx;
+ struct cvmx_iob_outb_control_match_enb_s cn31xx;
+ struct cvmx_iob_outb_control_match_enb_s cn38xx;
+ struct cvmx_iob_outb_control_match_enb_s cn38xxp2;
+ struct cvmx_iob_outb_control_match_enb_s cn50xx;
+ struct cvmx_iob_outb_control_match_enb_s cn52xx;
+ struct cvmx_iob_outb_control_match_enb_s cn52xxp1;
+ struct cvmx_iob_outb_control_match_enb_s cn56xx;
+ struct cvmx_iob_outb_control_match_enb_s cn56xxp1;
+ struct cvmx_iob_outb_control_match_enb_s cn58xx;
+ struct cvmx_iob_outb_control_match_enb_s cn58xxp1;
+};
+
+union cvmx_iob_outb_data_match {
+ uint64_t u64;
+ struct cvmx_iob_outb_data_match_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_iob_outb_data_match_s cn30xx;
+ struct cvmx_iob_outb_data_match_s cn31xx;
+ struct cvmx_iob_outb_data_match_s cn38xx;
+ struct cvmx_iob_outb_data_match_s cn38xxp2;
+ struct cvmx_iob_outb_data_match_s cn50xx;
+ struct cvmx_iob_outb_data_match_s cn52xx;
+ struct cvmx_iob_outb_data_match_s cn52xxp1;
+ struct cvmx_iob_outb_data_match_s cn56xx;
+ struct cvmx_iob_outb_data_match_s cn56xxp1;
+ struct cvmx_iob_outb_data_match_s cn58xx;
+ struct cvmx_iob_outb_data_match_s cn58xxp1;
+};
+
+union cvmx_iob_outb_data_match_enb {
+ uint64_t u64;
+ struct cvmx_iob_outb_data_match_enb_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_iob_outb_data_match_enb_s cn30xx;
+ struct cvmx_iob_outb_data_match_enb_s cn31xx;
+ struct cvmx_iob_outb_data_match_enb_s cn38xx;
+ struct cvmx_iob_outb_data_match_enb_s cn38xxp2;
+ struct cvmx_iob_outb_data_match_enb_s cn50xx;
+ struct cvmx_iob_outb_data_match_enb_s cn52xx;
+ struct cvmx_iob_outb_data_match_enb_s cn52xxp1;
+ struct cvmx_iob_outb_data_match_enb_s cn56xx;
+ struct cvmx_iob_outb_data_match_enb_s cn56xxp1;
+ struct cvmx_iob_outb_data_match_enb_s cn58xx;
+ struct cvmx_iob_outb_data_match_enb_s cn58xxp1;
+};
+
+union cvmx_iob_outb_fpa_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_outb_fpa_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn38xx;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn52xx;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn56xx;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn58xx;
+ struct cvmx_iob_outb_fpa_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_outb_req_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_outb_req_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_outb_req_pri_cnt_s cn38xx;
+ struct cvmx_iob_outb_req_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_outb_req_pri_cnt_s cn52xx;
+ struct cvmx_iob_outb_req_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_outb_req_pri_cnt_s cn56xx;
+ struct cvmx_iob_outb_req_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_outb_req_pri_cnt_s cn58xx;
+ struct cvmx_iob_outb_req_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_p2c_req_pri_cnt {
+ uint64_t u64;
+ struct cvmx_iob_p2c_req_pri_cnt_s {
+ uint64_t reserved_16_63:48;
+ uint64_t cnt_enb:1;
+ uint64_t cnt_val:15;
+ } s;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn38xx;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn38xxp2;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn52xx;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn52xxp1;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn56xx;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn56xxp1;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn58xx;
+ struct cvmx_iob_p2c_req_pri_cnt_s cn58xxp1;
+};
+
+union cvmx_iob_pkt_err {
+ uint64_t u64;
+ struct cvmx_iob_pkt_err_s {
+ uint64_t reserved_6_63:58;
+ uint64_t port:6;
+ } s;
+ struct cvmx_iob_pkt_err_s cn30xx;
+ struct cvmx_iob_pkt_err_s cn31xx;
+ struct cvmx_iob_pkt_err_s cn38xx;
+ struct cvmx_iob_pkt_err_s cn38xxp2;
+ struct cvmx_iob_pkt_err_s cn50xx;
+ struct cvmx_iob_pkt_err_s cn52xx;
+ struct cvmx_iob_pkt_err_s cn52xxp1;
+ struct cvmx_iob_pkt_err_s cn56xx;
+ struct cvmx_iob_pkt_err_s cn56xxp1;
+ struct cvmx_iob_pkt_err_s cn58xx;
+ struct cvmx_iob_pkt_err_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-ipd-defs.h b/arch/mips/include/asm/octeon/cvmx-ipd-defs.h
new file mode 100644
index 000000000000..f8b8fc657d2c
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-ipd-defs.h
@@ -0,0 +1,877 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_IPD_DEFS_H__
+#define __CVMX_IPD_DEFS_H__
+
+#define CVMX_IPD_1ST_MBUFF_SKIP \
+ CVMX_ADD_IO_SEG(0x00014F0000000000ull)
+#define CVMX_IPD_1st_NEXT_PTR_BACK \
+ CVMX_ADD_IO_SEG(0x00014F0000000150ull)
+#define CVMX_IPD_2nd_NEXT_PTR_BACK \
+ CVMX_ADD_IO_SEG(0x00014F0000000158ull)
+#define CVMX_IPD_BIST_STATUS \
+ CVMX_ADD_IO_SEG(0x00014F00000007F8ull)
+#define CVMX_IPD_BP_PRT_RED_END \
+ CVMX_ADD_IO_SEG(0x00014F0000000328ull)
+#define CVMX_IPD_CLK_COUNT \
+ CVMX_ADD_IO_SEG(0x00014F0000000338ull)
+#define CVMX_IPD_CTL_STATUS \
+ CVMX_ADD_IO_SEG(0x00014F0000000018ull)
+#define CVMX_IPD_INT_ENB \
+ CVMX_ADD_IO_SEG(0x00014F0000000160ull)
+#define CVMX_IPD_INT_SUM \
+ CVMX_ADD_IO_SEG(0x00014F0000000168ull)
+#define CVMX_IPD_NOT_1ST_MBUFF_SKIP \
+ CVMX_ADD_IO_SEG(0x00014F0000000008ull)
+#define CVMX_IPD_PACKET_MBUFF_SIZE \
+ CVMX_ADD_IO_SEG(0x00014F0000000010ull)
+#define CVMX_IPD_PKT_PTR_VALID \
+ CVMX_ADD_IO_SEG(0x00014F0000000358ull)
+#define CVMX_IPD_PORTX_BP_PAGE_CNT(offset) \
+ CVMX_ADD_IO_SEG(0x00014F0000000028ull + (((offset) & 63) * 8))
+#define CVMX_IPD_PORTX_BP_PAGE_CNT2(offset) \
+ CVMX_ADD_IO_SEG(0x00014F0000000368ull + (((offset) & 63) * 8) - 8 * 36)
+#define CVMX_IPD_PORT_BP_COUNTERS2_PAIRX(offset) \
+ CVMX_ADD_IO_SEG(0x00014F0000000388ull + (((offset) & 63) * 8) - 8 * 36)
+#define CVMX_IPD_PORT_BP_COUNTERS_PAIRX(offset) \
+ CVMX_ADD_IO_SEG(0x00014F00000001B8ull + (((offset) & 63) * 8))
+#define CVMX_IPD_PORT_QOS_INTX(offset) \
+ CVMX_ADD_IO_SEG(0x00014F0000000808ull + (((offset) & 7) * 8))
+#define CVMX_IPD_PORT_QOS_INT_ENBX(offset) \
+ CVMX_ADD_IO_SEG(0x00014F0000000848ull + (((offset) & 7) * 8))
+#define CVMX_IPD_PORT_QOS_X_CNT(offset) \
+ CVMX_ADD_IO_SEG(0x00014F0000000888ull + (((offset) & 511) * 8))
+#define CVMX_IPD_PRC_HOLD_PTR_FIFO_CTL \
+ CVMX_ADD_IO_SEG(0x00014F0000000348ull)
+#define CVMX_IPD_PRC_PORT_PTR_FIFO_CTL \
+ CVMX_ADD_IO_SEG(0x00014F0000000350ull)
+#define CVMX_IPD_PTR_COUNT \
+ CVMX_ADD_IO_SEG(0x00014F0000000320ull)
+#define CVMX_IPD_PWP_PTR_FIFO_CTL \
+ CVMX_ADD_IO_SEG(0x00014F0000000340ull)
+#define CVMX_IPD_QOS0_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F0000000178ull)
+#define CVMX_IPD_QOS1_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F0000000180ull)
+#define CVMX_IPD_QOS2_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F0000000188ull)
+#define CVMX_IPD_QOS3_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F0000000190ull)
+#define CVMX_IPD_QOS4_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F0000000198ull)
+#define CVMX_IPD_QOS5_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F00000001A0ull)
+#define CVMX_IPD_QOS6_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F00000001A8ull)
+#define CVMX_IPD_QOS7_RED_MARKS \
+ CVMX_ADD_IO_SEG(0x00014F00000001B0ull)
+#define CVMX_IPD_QOSX_RED_MARKS(offset) \
+ CVMX_ADD_IO_SEG(0x00014F0000000178ull + (((offset) & 7) * 8))
+#define CVMX_IPD_QUE0_FREE_PAGE_CNT \
+ CVMX_ADD_IO_SEG(0x00014F0000000330ull)
+#define CVMX_IPD_RED_PORT_ENABLE \
+ CVMX_ADD_IO_SEG(0x00014F00000002D8ull)
+#define CVMX_IPD_RED_PORT_ENABLE2 \
+ CVMX_ADD_IO_SEG(0x00014F00000003A8ull)
+#define CVMX_IPD_RED_QUE0_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F00000002E0ull)
+#define CVMX_IPD_RED_QUE1_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F00000002E8ull)
+#define CVMX_IPD_RED_QUE2_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F00000002F0ull)
+#define CVMX_IPD_RED_QUE3_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F00000002F8ull)
+#define CVMX_IPD_RED_QUE4_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F0000000300ull)
+#define CVMX_IPD_RED_QUE5_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F0000000308ull)
+#define CVMX_IPD_RED_QUE6_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F0000000310ull)
+#define CVMX_IPD_RED_QUE7_PARAM \
+ CVMX_ADD_IO_SEG(0x00014F0000000318ull)
+#define CVMX_IPD_RED_QUEX_PARAM(offset) \
+ CVMX_ADD_IO_SEG(0x00014F00000002E0ull + (((offset) & 7) * 8))
+#define CVMX_IPD_SUB_PORT_BP_PAGE_CNT \
+ CVMX_ADD_IO_SEG(0x00014F0000000148ull)
+#define CVMX_IPD_SUB_PORT_FCS \
+ CVMX_ADD_IO_SEG(0x00014F0000000170ull)
+#define CVMX_IPD_SUB_PORT_QOS_CNT \
+ CVMX_ADD_IO_SEG(0x00014F0000000800ull)
+#define CVMX_IPD_WQE_FPA_QUEUE \
+ CVMX_ADD_IO_SEG(0x00014F0000000020ull)
+#define CVMX_IPD_WQE_PTR_VALID \
+ CVMX_ADD_IO_SEG(0x00014F0000000360ull)
+
+union cvmx_ipd_1st_mbuff_skip {
+ uint64_t u64;
+ struct cvmx_ipd_1st_mbuff_skip_s {
+ uint64_t reserved_6_63:58;
+ uint64_t skip_sz:6;
+ } s;
+ struct cvmx_ipd_1st_mbuff_skip_s cn30xx;
+ struct cvmx_ipd_1st_mbuff_skip_s cn31xx;
+ struct cvmx_ipd_1st_mbuff_skip_s cn38xx;
+ struct cvmx_ipd_1st_mbuff_skip_s cn38xxp2;
+ struct cvmx_ipd_1st_mbuff_skip_s cn50xx;
+ struct cvmx_ipd_1st_mbuff_skip_s cn52xx;
+ struct cvmx_ipd_1st_mbuff_skip_s cn52xxp1;
+ struct cvmx_ipd_1st_mbuff_skip_s cn56xx;
+ struct cvmx_ipd_1st_mbuff_skip_s cn56xxp1;
+ struct cvmx_ipd_1st_mbuff_skip_s cn58xx;
+ struct cvmx_ipd_1st_mbuff_skip_s cn58xxp1;
+};
+
+union cvmx_ipd_1st_next_ptr_back {
+ uint64_t u64;
+ struct cvmx_ipd_1st_next_ptr_back_s {
+ uint64_t reserved_4_63:60;
+ uint64_t back:4;
+ } s;
+ struct cvmx_ipd_1st_next_ptr_back_s cn30xx;
+ struct cvmx_ipd_1st_next_ptr_back_s cn31xx;
+ struct cvmx_ipd_1st_next_ptr_back_s cn38xx;
+ struct cvmx_ipd_1st_next_ptr_back_s cn38xxp2;
+ struct cvmx_ipd_1st_next_ptr_back_s cn50xx;
+ struct cvmx_ipd_1st_next_ptr_back_s cn52xx;
+ struct cvmx_ipd_1st_next_ptr_back_s cn52xxp1;
+ struct cvmx_ipd_1st_next_ptr_back_s cn56xx;
+ struct cvmx_ipd_1st_next_ptr_back_s cn56xxp1;
+ struct cvmx_ipd_1st_next_ptr_back_s cn58xx;
+ struct cvmx_ipd_1st_next_ptr_back_s cn58xxp1;
+};
+
+union cvmx_ipd_2nd_next_ptr_back {
+ uint64_t u64;
+ struct cvmx_ipd_2nd_next_ptr_back_s {
+ uint64_t reserved_4_63:60;
+ uint64_t back:4;
+ } s;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn30xx;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn31xx;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn38xx;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn38xxp2;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn50xx;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn52xx;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn52xxp1;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn56xx;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn56xxp1;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn58xx;
+ struct cvmx_ipd_2nd_next_ptr_back_s cn58xxp1;
+};
+
+union cvmx_ipd_bist_status {
+ uint64_t u64;
+ struct cvmx_ipd_bist_status_s {
+ uint64_t reserved_18_63:46;
+ uint64_t csr_mem:1;
+ uint64_t csr_ncmd:1;
+ uint64_t pwq_wqed:1;
+ uint64_t pwq_wp1:1;
+ uint64_t pwq_pow:1;
+ uint64_t ipq_pbe1:1;
+ uint64_t ipq_pbe0:1;
+ uint64_t pbm3:1;
+ uint64_t pbm2:1;
+ uint64_t pbm1:1;
+ uint64_t pbm0:1;
+ uint64_t pbm_word:1;
+ uint64_t pwq1:1;
+ uint64_t pwq0:1;
+ uint64_t prc_off:1;
+ uint64_t ipd_old:1;
+ uint64_t ipd_new:1;
+ uint64_t pwp:1;
+ } s;
+ struct cvmx_ipd_bist_status_cn30xx {
+ uint64_t reserved_16_63:48;
+ uint64_t pwq_wqed:1;
+ uint64_t pwq_wp1:1;
+ uint64_t pwq_pow:1;
+ uint64_t ipq_pbe1:1;
+ uint64_t ipq_pbe0:1;
+ uint64_t pbm3:1;
+ uint64_t pbm2:1;
+ uint64_t pbm1:1;
+ uint64_t pbm0:1;
+ uint64_t pbm_word:1;
+ uint64_t pwq1:1;
+ uint64_t pwq0:1;
+ uint64_t prc_off:1;
+ uint64_t ipd_old:1;
+ uint64_t ipd_new:1;
+ uint64_t pwp:1;
+ } cn30xx;
+ struct cvmx_ipd_bist_status_cn30xx cn31xx;
+ struct cvmx_ipd_bist_status_cn30xx cn38xx;
+ struct cvmx_ipd_bist_status_cn30xx cn38xxp2;
+ struct cvmx_ipd_bist_status_cn30xx cn50xx;
+ struct cvmx_ipd_bist_status_s cn52xx;
+ struct cvmx_ipd_bist_status_s cn52xxp1;
+ struct cvmx_ipd_bist_status_s cn56xx;
+ struct cvmx_ipd_bist_status_s cn56xxp1;
+ struct cvmx_ipd_bist_status_cn30xx cn58xx;
+ struct cvmx_ipd_bist_status_cn30xx cn58xxp1;
+};
+
+union cvmx_ipd_bp_prt_red_end {
+ uint64_t u64;
+ struct cvmx_ipd_bp_prt_red_end_s {
+ uint64_t reserved_40_63:24;
+ uint64_t prt_enb:40;
+ } s;
+ struct cvmx_ipd_bp_prt_red_end_cn30xx {
+ uint64_t reserved_36_63:28;
+ uint64_t prt_enb:36;
+ } cn30xx;
+ struct cvmx_ipd_bp_prt_red_end_cn30xx cn31xx;
+ struct cvmx_ipd_bp_prt_red_end_cn30xx cn38xx;
+ struct cvmx_ipd_bp_prt_red_end_cn30xx cn38xxp2;
+ struct cvmx_ipd_bp_prt_red_end_cn30xx cn50xx;
+ struct cvmx_ipd_bp_prt_red_end_s cn52xx;
+ struct cvmx_ipd_bp_prt_red_end_s cn52xxp1;
+ struct cvmx_ipd_bp_prt_red_end_s cn56xx;
+ struct cvmx_ipd_bp_prt_red_end_s cn56xxp1;
+ struct cvmx_ipd_bp_prt_red_end_cn30xx cn58xx;
+ struct cvmx_ipd_bp_prt_red_end_cn30xx cn58xxp1;
+};
+
+union cvmx_ipd_clk_count {
+ uint64_t u64;
+ struct cvmx_ipd_clk_count_s {
+ uint64_t clk_cnt:64;
+ } s;
+ struct cvmx_ipd_clk_count_s cn30xx;
+ struct cvmx_ipd_clk_count_s cn31xx;
+ struct cvmx_ipd_clk_count_s cn38xx;
+ struct cvmx_ipd_clk_count_s cn38xxp2;
+ struct cvmx_ipd_clk_count_s cn50xx;
+ struct cvmx_ipd_clk_count_s cn52xx;
+ struct cvmx_ipd_clk_count_s cn52xxp1;
+ struct cvmx_ipd_clk_count_s cn56xx;
+ struct cvmx_ipd_clk_count_s cn56xxp1;
+ struct cvmx_ipd_clk_count_s cn58xx;
+ struct cvmx_ipd_clk_count_s cn58xxp1;
+};
+
+union cvmx_ipd_ctl_status {
+ uint64_t u64;
+ struct cvmx_ipd_ctl_status_s {
+ uint64_t reserved_15_63:49;
+ uint64_t no_wptr:1;
+ uint64_t pq_apkt:1;
+ uint64_t pq_nabuf:1;
+ uint64_t ipd_full:1;
+ uint64_t pkt_off:1;
+ uint64_t len_m8:1;
+ uint64_t reset:1;
+ uint64_t addpkt:1;
+ uint64_t naddbuf:1;
+ uint64_t pkt_lend:1;
+ uint64_t wqe_lend:1;
+ uint64_t pbp_en:1;
+ uint64_t opc_mode:2;
+ uint64_t ipd_en:1;
+ } s;
+ struct cvmx_ipd_ctl_status_cn30xx {
+ uint64_t reserved_10_63:54;
+ uint64_t len_m8:1;
+ uint64_t reset:1;
+ uint64_t addpkt:1;
+ uint64_t naddbuf:1;
+ uint64_t pkt_lend:1;
+ uint64_t wqe_lend:1;
+ uint64_t pbp_en:1;
+ uint64_t opc_mode:2;
+ uint64_t ipd_en:1;
+ } cn30xx;
+ struct cvmx_ipd_ctl_status_cn30xx cn31xx;
+ struct cvmx_ipd_ctl_status_cn30xx cn38xx;
+ struct cvmx_ipd_ctl_status_cn38xxp2 {
+ uint64_t reserved_9_63:55;
+ uint64_t reset:1;
+ uint64_t addpkt:1;
+ uint64_t naddbuf:1;
+ uint64_t pkt_lend:1;
+ uint64_t wqe_lend:1;
+ uint64_t pbp_en:1;
+ uint64_t opc_mode:2;
+ uint64_t ipd_en:1;
+ } cn38xxp2;
+ struct cvmx_ipd_ctl_status_s cn50xx;
+ struct cvmx_ipd_ctl_status_s cn52xx;
+ struct cvmx_ipd_ctl_status_s cn52xxp1;
+ struct cvmx_ipd_ctl_status_s cn56xx;
+ struct cvmx_ipd_ctl_status_s cn56xxp1;
+ struct cvmx_ipd_ctl_status_cn58xx {
+ uint64_t reserved_12_63:52;
+ uint64_t ipd_full:1;
+ uint64_t pkt_off:1;
+ uint64_t len_m8:1;
+ uint64_t reset:1;
+ uint64_t addpkt:1;
+ uint64_t naddbuf:1;
+ uint64_t pkt_lend:1;
+ uint64_t wqe_lend:1;
+ uint64_t pbp_en:1;
+ uint64_t opc_mode:2;
+ uint64_t ipd_en:1;
+ } cn58xx;
+ struct cvmx_ipd_ctl_status_cn58xx cn58xxp1;
+};
+
+union cvmx_ipd_int_enb {
+ uint64_t u64;
+ struct cvmx_ipd_int_enb_s {
+ uint64_t reserved_12_63:52;
+ uint64_t pq_sub:1;
+ uint64_t pq_add:1;
+ uint64_t bc_ovr:1;
+ uint64_t d_coll:1;
+ uint64_t c_coll:1;
+ uint64_t cc_ovr:1;
+ uint64_t dc_ovr:1;
+ uint64_t bp_sub:1;
+ uint64_t prc_par3:1;
+ uint64_t prc_par2:1;
+ uint64_t prc_par1:1;
+ uint64_t prc_par0:1;
+ } s;
+ struct cvmx_ipd_int_enb_cn30xx {
+ uint64_t reserved_5_63:59;
+ uint64_t bp_sub:1;
+ uint64_t prc_par3:1;
+ uint64_t prc_par2:1;
+ uint64_t prc_par1:1;
+ uint64_t prc_par0:1;
+ } cn30xx;
+ struct cvmx_ipd_int_enb_cn30xx cn31xx;
+ struct cvmx_ipd_int_enb_cn38xx {
+ uint64_t reserved_10_63:54;
+ uint64_t bc_ovr:1;
+ uint64_t d_coll:1;
+ uint64_t c_coll:1;
+ uint64_t cc_ovr:1;
+ uint64_t dc_ovr:1;
+ uint64_t bp_sub:1;
+ uint64_t prc_par3:1;
+ uint64_t prc_par2:1;
+ uint64_t prc_par1:1;
+ uint64_t prc_par0:1;
+ } cn38xx;
+ struct cvmx_ipd_int_enb_cn30xx cn38xxp2;
+ struct cvmx_ipd_int_enb_cn38xx cn50xx;
+ struct cvmx_ipd_int_enb_s cn52xx;
+ struct cvmx_ipd_int_enb_s cn52xxp1;
+ struct cvmx_ipd_int_enb_s cn56xx;
+ struct cvmx_ipd_int_enb_s cn56xxp1;
+ struct cvmx_ipd_int_enb_cn38xx cn58xx;
+ struct cvmx_ipd_int_enb_cn38xx cn58xxp1;
+};
+
+union cvmx_ipd_int_sum {
+ uint64_t u64;
+ struct cvmx_ipd_int_sum_s {
+ uint64_t reserved_12_63:52;
+ uint64_t pq_sub:1;
+ uint64_t pq_add:1;
+ uint64_t bc_ovr:1;
+ uint64_t d_coll:1;
+ uint64_t c_coll:1;
+ uint64_t cc_ovr:1;
+ uint64_t dc_ovr:1;
+ uint64_t bp_sub:1;
+ uint64_t prc_par3:1;
+ uint64_t prc_par2:1;
+ uint64_t prc_par1:1;
+ uint64_t prc_par0:1;
+ } s;
+ struct cvmx_ipd_int_sum_cn30xx {
+ uint64_t reserved_5_63:59;
+ uint64_t bp_sub:1;
+ uint64_t prc_par3:1;
+ uint64_t prc_par2:1;
+ uint64_t prc_par1:1;
+ uint64_t prc_par0:1;
+ } cn30xx;
+ struct cvmx_ipd_int_sum_cn30xx cn31xx;
+ struct cvmx_ipd_int_sum_cn38xx {
+ uint64_t reserved_10_63:54;
+ uint64_t bc_ovr:1;
+ uint64_t d_coll:1;
+ uint64_t c_coll:1;
+ uint64_t cc_ovr:1;
+ uint64_t dc_ovr:1;
+ uint64_t bp_sub:1;
+ uint64_t prc_par3:1;
+ uint64_t prc_par2:1;
+ uint64_t prc_par1:1;
+ uint64_t prc_par0:1;
+ } cn38xx;
+ struct cvmx_ipd_int_sum_cn30xx cn38xxp2;
+ struct cvmx_ipd_int_sum_cn38xx cn50xx;
+ struct cvmx_ipd_int_sum_s cn52xx;
+ struct cvmx_ipd_int_sum_s cn52xxp1;
+ struct cvmx_ipd_int_sum_s cn56xx;
+ struct cvmx_ipd_int_sum_s cn56xxp1;
+ struct cvmx_ipd_int_sum_cn38xx cn58xx;
+ struct cvmx_ipd_int_sum_cn38xx cn58xxp1;
+};
+
+union cvmx_ipd_not_1st_mbuff_skip {
+ uint64_t u64;
+ struct cvmx_ipd_not_1st_mbuff_skip_s {
+ uint64_t reserved_6_63:58;
+ uint64_t skip_sz:6;
+ } s;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn30xx;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn31xx;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn38xx;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn38xxp2;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn50xx;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn52xx;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn52xxp1;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn56xx;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn56xxp1;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn58xx;
+ struct cvmx_ipd_not_1st_mbuff_skip_s cn58xxp1;
+};
+
+union cvmx_ipd_packet_mbuff_size {
+ uint64_t u64;
+ struct cvmx_ipd_packet_mbuff_size_s {
+ uint64_t reserved_12_63:52;
+ uint64_t mb_size:12;
+ } s;
+ struct cvmx_ipd_packet_mbuff_size_s cn30xx;
+ struct cvmx_ipd_packet_mbuff_size_s cn31xx;
+ struct cvmx_ipd_packet_mbuff_size_s cn38xx;
+ struct cvmx_ipd_packet_mbuff_size_s cn38xxp2;
+ struct cvmx_ipd_packet_mbuff_size_s cn50xx;
+ struct cvmx_ipd_packet_mbuff_size_s cn52xx;
+ struct cvmx_ipd_packet_mbuff_size_s cn52xxp1;
+ struct cvmx_ipd_packet_mbuff_size_s cn56xx;
+ struct cvmx_ipd_packet_mbuff_size_s cn56xxp1;
+ struct cvmx_ipd_packet_mbuff_size_s cn58xx;
+ struct cvmx_ipd_packet_mbuff_size_s cn58xxp1;
+};
+
+union cvmx_ipd_pkt_ptr_valid {
+ uint64_t u64;
+ struct cvmx_ipd_pkt_ptr_valid_s {
+ uint64_t reserved_29_63:35;
+ uint64_t ptr:29;
+ } s;
+ struct cvmx_ipd_pkt_ptr_valid_s cn30xx;
+ struct cvmx_ipd_pkt_ptr_valid_s cn31xx;
+ struct cvmx_ipd_pkt_ptr_valid_s cn38xx;
+ struct cvmx_ipd_pkt_ptr_valid_s cn50xx;
+ struct cvmx_ipd_pkt_ptr_valid_s cn52xx;
+ struct cvmx_ipd_pkt_ptr_valid_s cn52xxp1;
+ struct cvmx_ipd_pkt_ptr_valid_s cn56xx;
+ struct cvmx_ipd_pkt_ptr_valid_s cn56xxp1;
+ struct cvmx_ipd_pkt_ptr_valid_s cn58xx;
+ struct cvmx_ipd_pkt_ptr_valid_s cn58xxp1;
+};
+
+union cvmx_ipd_portx_bp_page_cnt {
+ uint64_t u64;
+ struct cvmx_ipd_portx_bp_page_cnt_s {
+ uint64_t reserved_18_63:46;
+ uint64_t bp_enb:1;
+ uint64_t page_cnt:17;
+ } s;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn30xx;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn31xx;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn38xx;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn38xxp2;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn50xx;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn52xx;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn52xxp1;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn56xx;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn56xxp1;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn58xx;
+ struct cvmx_ipd_portx_bp_page_cnt_s cn58xxp1;
+};
+
+union cvmx_ipd_portx_bp_page_cnt2 {
+ uint64_t u64;
+ struct cvmx_ipd_portx_bp_page_cnt2_s {
+ uint64_t reserved_18_63:46;
+ uint64_t bp_enb:1;
+ uint64_t page_cnt:17;
+ } s;
+ struct cvmx_ipd_portx_bp_page_cnt2_s cn52xx;
+ struct cvmx_ipd_portx_bp_page_cnt2_s cn52xxp1;
+ struct cvmx_ipd_portx_bp_page_cnt2_s cn56xx;
+ struct cvmx_ipd_portx_bp_page_cnt2_s cn56xxp1;
+};
+
+union cvmx_ipd_port_bp_counters2_pairx {
+ uint64_t u64;
+ struct cvmx_ipd_port_bp_counters2_pairx_s {
+ uint64_t reserved_25_63:39;
+ uint64_t cnt_val:25;
+ } s;
+ struct cvmx_ipd_port_bp_counters2_pairx_s cn52xx;
+ struct cvmx_ipd_port_bp_counters2_pairx_s cn52xxp1;
+ struct cvmx_ipd_port_bp_counters2_pairx_s cn56xx;
+ struct cvmx_ipd_port_bp_counters2_pairx_s cn56xxp1;
+};
+
+union cvmx_ipd_port_bp_counters_pairx {
+ uint64_t u64;
+ struct cvmx_ipd_port_bp_counters_pairx_s {
+ uint64_t reserved_25_63:39;
+ uint64_t cnt_val:25;
+ } s;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn30xx;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn31xx;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn38xx;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn38xxp2;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn50xx;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn52xx;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn52xxp1;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn56xx;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn56xxp1;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn58xx;
+ struct cvmx_ipd_port_bp_counters_pairx_s cn58xxp1;
+};
+
+union cvmx_ipd_port_qos_x_cnt {
+ uint64_t u64;
+ struct cvmx_ipd_port_qos_x_cnt_s {
+ uint64_t wmark:32;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_ipd_port_qos_x_cnt_s cn52xx;
+ struct cvmx_ipd_port_qos_x_cnt_s cn52xxp1;
+ struct cvmx_ipd_port_qos_x_cnt_s cn56xx;
+ struct cvmx_ipd_port_qos_x_cnt_s cn56xxp1;
+};
+
+union cvmx_ipd_port_qos_intx {
+ uint64_t u64;
+ struct cvmx_ipd_port_qos_intx_s {
+ uint64_t intr:64;
+ } s;
+ struct cvmx_ipd_port_qos_intx_s cn52xx;
+ struct cvmx_ipd_port_qos_intx_s cn52xxp1;
+ struct cvmx_ipd_port_qos_intx_s cn56xx;
+ struct cvmx_ipd_port_qos_intx_s cn56xxp1;
+};
+
+union cvmx_ipd_port_qos_int_enbx {
+ uint64_t u64;
+ struct cvmx_ipd_port_qos_int_enbx_s {
+ uint64_t enb:64;
+ } s;
+ struct cvmx_ipd_port_qos_int_enbx_s cn52xx;
+ struct cvmx_ipd_port_qos_int_enbx_s cn52xxp1;
+ struct cvmx_ipd_port_qos_int_enbx_s cn56xx;
+ struct cvmx_ipd_port_qos_int_enbx_s cn56xxp1;
+};
+
+union cvmx_ipd_prc_hold_ptr_fifo_ctl {
+ uint64_t u64;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s {
+ uint64_t reserved_39_63:25;
+ uint64_t max_pkt:3;
+ uint64_t praddr:3;
+ uint64_t ptr:29;
+ uint64_t cena:1;
+ uint64_t raddr:3;
+ } s;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn30xx;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn31xx;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn38xx;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn50xx;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn52xx;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn52xxp1;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn56xx;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn56xxp1;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn58xx;
+ struct cvmx_ipd_prc_hold_ptr_fifo_ctl_s cn58xxp1;
+};
+
+union cvmx_ipd_prc_port_ptr_fifo_ctl {
+ uint64_t u64;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s {
+ uint64_t reserved_44_63:20;
+ uint64_t max_pkt:7;
+ uint64_t ptr:29;
+ uint64_t cena:1;
+ uint64_t raddr:7;
+ } s;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn30xx;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn31xx;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn38xx;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn50xx;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn52xx;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn52xxp1;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn56xx;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn56xxp1;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn58xx;
+ struct cvmx_ipd_prc_port_ptr_fifo_ctl_s cn58xxp1;
+};
+
+union cvmx_ipd_ptr_count {
+ uint64_t u64;
+ struct cvmx_ipd_ptr_count_s {
+ uint64_t reserved_19_63:45;
+ uint64_t pktv_cnt:1;
+ uint64_t wqev_cnt:1;
+ uint64_t pfif_cnt:3;
+ uint64_t pkt_pcnt:7;
+ uint64_t wqe_pcnt:7;
+ } s;
+ struct cvmx_ipd_ptr_count_s cn30xx;
+ struct cvmx_ipd_ptr_count_s cn31xx;
+ struct cvmx_ipd_ptr_count_s cn38xx;
+ struct cvmx_ipd_ptr_count_s cn38xxp2;
+ struct cvmx_ipd_ptr_count_s cn50xx;
+ struct cvmx_ipd_ptr_count_s cn52xx;
+ struct cvmx_ipd_ptr_count_s cn52xxp1;
+ struct cvmx_ipd_ptr_count_s cn56xx;
+ struct cvmx_ipd_ptr_count_s cn56xxp1;
+ struct cvmx_ipd_ptr_count_s cn58xx;
+ struct cvmx_ipd_ptr_count_s cn58xxp1;
+};
+
+union cvmx_ipd_pwp_ptr_fifo_ctl {
+ uint64_t u64;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s {
+ uint64_t reserved_61_63:3;
+ uint64_t max_cnts:7;
+ uint64_t wraddr:8;
+ uint64_t praddr:8;
+ uint64_t ptr:29;
+ uint64_t cena:1;
+ uint64_t raddr:8;
+ } s;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn30xx;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn31xx;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn38xx;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn50xx;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn52xx;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn52xxp1;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn56xx;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn56xxp1;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn58xx;
+ struct cvmx_ipd_pwp_ptr_fifo_ctl_s cn58xxp1;
+};
+
+union cvmx_ipd_qosx_red_marks {
+ uint64_t u64;
+ struct cvmx_ipd_qosx_red_marks_s {
+ uint64_t drop:32;
+ uint64_t pass:32;
+ } s;
+ struct cvmx_ipd_qosx_red_marks_s cn30xx;
+ struct cvmx_ipd_qosx_red_marks_s cn31xx;
+ struct cvmx_ipd_qosx_red_marks_s cn38xx;
+ struct cvmx_ipd_qosx_red_marks_s cn38xxp2;
+ struct cvmx_ipd_qosx_red_marks_s cn50xx;
+ struct cvmx_ipd_qosx_red_marks_s cn52xx;
+ struct cvmx_ipd_qosx_red_marks_s cn52xxp1;
+ struct cvmx_ipd_qosx_red_marks_s cn56xx;
+ struct cvmx_ipd_qosx_red_marks_s cn56xxp1;
+ struct cvmx_ipd_qosx_red_marks_s cn58xx;
+ struct cvmx_ipd_qosx_red_marks_s cn58xxp1;
+};
+
+union cvmx_ipd_que0_free_page_cnt {
+ uint64_t u64;
+ struct cvmx_ipd_que0_free_page_cnt_s {
+ uint64_t reserved_32_63:32;
+ uint64_t q0_pcnt:32;
+ } s;
+ struct cvmx_ipd_que0_free_page_cnt_s cn30xx;
+ struct cvmx_ipd_que0_free_page_cnt_s cn31xx;
+ struct cvmx_ipd_que0_free_page_cnt_s cn38xx;
+ struct cvmx_ipd_que0_free_page_cnt_s cn38xxp2;
+ struct cvmx_ipd_que0_free_page_cnt_s cn50xx;
+ struct cvmx_ipd_que0_free_page_cnt_s cn52xx;
+ struct cvmx_ipd_que0_free_page_cnt_s cn52xxp1;
+ struct cvmx_ipd_que0_free_page_cnt_s cn56xx;
+ struct cvmx_ipd_que0_free_page_cnt_s cn56xxp1;
+ struct cvmx_ipd_que0_free_page_cnt_s cn58xx;
+ struct cvmx_ipd_que0_free_page_cnt_s cn58xxp1;
+};
+
+union cvmx_ipd_red_port_enable {
+ uint64_t u64;
+ struct cvmx_ipd_red_port_enable_s {
+ uint64_t prb_dly:14;
+ uint64_t avg_dly:14;
+ uint64_t prt_enb:36;
+ } s;
+ struct cvmx_ipd_red_port_enable_s cn30xx;
+ struct cvmx_ipd_red_port_enable_s cn31xx;
+ struct cvmx_ipd_red_port_enable_s cn38xx;
+ struct cvmx_ipd_red_port_enable_s cn38xxp2;
+ struct cvmx_ipd_red_port_enable_s cn50xx;
+ struct cvmx_ipd_red_port_enable_s cn52xx;
+ struct cvmx_ipd_red_port_enable_s cn52xxp1;
+ struct cvmx_ipd_red_port_enable_s cn56xx;
+ struct cvmx_ipd_red_port_enable_s cn56xxp1;
+ struct cvmx_ipd_red_port_enable_s cn58xx;
+ struct cvmx_ipd_red_port_enable_s cn58xxp1;
+};
+
+union cvmx_ipd_red_port_enable2 {
+ uint64_t u64;
+ struct cvmx_ipd_red_port_enable2_s {
+ uint64_t reserved_4_63:60;
+ uint64_t prt_enb:4;
+ } s;
+ struct cvmx_ipd_red_port_enable2_s cn52xx;
+ struct cvmx_ipd_red_port_enable2_s cn52xxp1;
+ struct cvmx_ipd_red_port_enable2_s cn56xx;
+ struct cvmx_ipd_red_port_enable2_s cn56xxp1;
+};
+
+union cvmx_ipd_red_quex_param {
+ uint64_t u64;
+ struct cvmx_ipd_red_quex_param_s {
+ uint64_t reserved_49_63:15;
+ uint64_t use_pcnt:1;
+ uint64_t new_con:8;
+ uint64_t avg_con:8;
+ uint64_t prb_con:32;
+ } s;
+ struct cvmx_ipd_red_quex_param_s cn30xx;
+ struct cvmx_ipd_red_quex_param_s cn31xx;
+ struct cvmx_ipd_red_quex_param_s cn38xx;
+ struct cvmx_ipd_red_quex_param_s cn38xxp2;
+ struct cvmx_ipd_red_quex_param_s cn50xx;
+ struct cvmx_ipd_red_quex_param_s cn52xx;
+ struct cvmx_ipd_red_quex_param_s cn52xxp1;
+ struct cvmx_ipd_red_quex_param_s cn56xx;
+ struct cvmx_ipd_red_quex_param_s cn56xxp1;
+ struct cvmx_ipd_red_quex_param_s cn58xx;
+ struct cvmx_ipd_red_quex_param_s cn58xxp1;
+};
+
+union cvmx_ipd_sub_port_bp_page_cnt {
+ uint64_t u64;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s {
+ uint64_t reserved_31_63:33;
+ uint64_t port:6;
+ uint64_t page_cnt:25;
+ } s;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn30xx;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn31xx;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn38xx;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn38xxp2;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn50xx;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn52xx;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn52xxp1;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn56xx;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn56xxp1;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn58xx;
+ struct cvmx_ipd_sub_port_bp_page_cnt_s cn58xxp1;
+};
+
+union cvmx_ipd_sub_port_fcs {
+ uint64_t u64;
+ struct cvmx_ipd_sub_port_fcs_s {
+ uint64_t reserved_40_63:24;
+ uint64_t port_bit2:4;
+ uint64_t reserved_32_35:4;
+ uint64_t port_bit:32;
+ } s;
+ struct cvmx_ipd_sub_port_fcs_cn30xx {
+ uint64_t reserved_3_63:61;
+ uint64_t port_bit:3;
+ } cn30xx;
+ struct cvmx_ipd_sub_port_fcs_cn30xx cn31xx;
+ struct cvmx_ipd_sub_port_fcs_cn38xx {
+ uint64_t reserved_32_63:32;
+ uint64_t port_bit:32;
+ } cn38xx;
+ struct cvmx_ipd_sub_port_fcs_cn38xx cn38xxp2;
+ struct cvmx_ipd_sub_port_fcs_cn30xx cn50xx;
+ struct cvmx_ipd_sub_port_fcs_s cn52xx;
+ struct cvmx_ipd_sub_port_fcs_s cn52xxp1;
+ struct cvmx_ipd_sub_port_fcs_s cn56xx;
+ struct cvmx_ipd_sub_port_fcs_s cn56xxp1;
+ struct cvmx_ipd_sub_port_fcs_cn38xx cn58xx;
+ struct cvmx_ipd_sub_port_fcs_cn38xx cn58xxp1;
+};
+
+union cvmx_ipd_sub_port_qos_cnt {
+ uint64_t u64;
+ struct cvmx_ipd_sub_port_qos_cnt_s {
+ uint64_t reserved_41_63:23;
+ uint64_t port_qos:9;
+ uint64_t cnt:32;
+ } s;
+ struct cvmx_ipd_sub_port_qos_cnt_s cn52xx;
+ struct cvmx_ipd_sub_port_qos_cnt_s cn52xxp1;
+ struct cvmx_ipd_sub_port_qos_cnt_s cn56xx;
+ struct cvmx_ipd_sub_port_qos_cnt_s cn56xxp1;
+};
+
+union cvmx_ipd_wqe_fpa_queue {
+ uint64_t u64;
+ struct cvmx_ipd_wqe_fpa_queue_s {
+ uint64_t reserved_3_63:61;
+ uint64_t wqe_pool:3;
+ } s;
+ struct cvmx_ipd_wqe_fpa_queue_s cn30xx;
+ struct cvmx_ipd_wqe_fpa_queue_s cn31xx;
+ struct cvmx_ipd_wqe_fpa_queue_s cn38xx;
+ struct cvmx_ipd_wqe_fpa_queue_s cn38xxp2;
+ struct cvmx_ipd_wqe_fpa_queue_s cn50xx;
+ struct cvmx_ipd_wqe_fpa_queue_s cn52xx;
+ struct cvmx_ipd_wqe_fpa_queue_s cn52xxp1;
+ struct cvmx_ipd_wqe_fpa_queue_s cn56xx;
+ struct cvmx_ipd_wqe_fpa_queue_s cn56xxp1;
+ struct cvmx_ipd_wqe_fpa_queue_s cn58xx;
+ struct cvmx_ipd_wqe_fpa_queue_s cn58xxp1;
+};
+
+union cvmx_ipd_wqe_ptr_valid {
+ uint64_t u64;
+ struct cvmx_ipd_wqe_ptr_valid_s {
+ uint64_t reserved_29_63:35;
+ uint64_t ptr:29;
+ } s;
+ struct cvmx_ipd_wqe_ptr_valid_s cn30xx;
+ struct cvmx_ipd_wqe_ptr_valid_s cn31xx;
+ struct cvmx_ipd_wqe_ptr_valid_s cn38xx;
+ struct cvmx_ipd_wqe_ptr_valid_s cn50xx;
+ struct cvmx_ipd_wqe_ptr_valid_s cn52xx;
+ struct cvmx_ipd_wqe_ptr_valid_s cn52xxp1;
+ struct cvmx_ipd_wqe_ptr_valid_s cn56xx;
+ struct cvmx_ipd_wqe_ptr_valid_s cn56xxp1;
+ struct cvmx_ipd_wqe_ptr_valid_s cn58xx;
+ struct cvmx_ipd_wqe_ptr_valid_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-l2c-defs.h b/arch/mips/include/asm/octeon/cvmx-l2c-defs.h
new file mode 100644
index 000000000000..337583842b51
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-l2c-defs.h
@@ -0,0 +1,963 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_L2C_DEFS_H__
+#define __CVMX_L2C_DEFS_H__
+
+#define CVMX_L2C_BST0 \
+ CVMX_ADD_IO_SEG(0x00011800800007F8ull)
+#define CVMX_L2C_BST1 \
+ CVMX_ADD_IO_SEG(0x00011800800007F0ull)
+#define CVMX_L2C_BST2 \
+ CVMX_ADD_IO_SEG(0x00011800800007E8ull)
+#define CVMX_L2C_CFG \
+ CVMX_ADD_IO_SEG(0x0001180080000000ull)
+#define CVMX_L2C_DBG \
+ CVMX_ADD_IO_SEG(0x0001180080000030ull)
+#define CVMX_L2C_DUT \
+ CVMX_ADD_IO_SEG(0x0001180080000050ull)
+#define CVMX_L2C_GRPWRR0 \
+ CVMX_ADD_IO_SEG(0x00011800800000C8ull)
+#define CVMX_L2C_GRPWRR1 \
+ CVMX_ADD_IO_SEG(0x00011800800000D0ull)
+#define CVMX_L2C_INT_EN \
+ CVMX_ADD_IO_SEG(0x0001180080000100ull)
+#define CVMX_L2C_INT_STAT \
+ CVMX_ADD_IO_SEG(0x00011800800000F8ull)
+#define CVMX_L2C_LCKBASE \
+ CVMX_ADD_IO_SEG(0x0001180080000058ull)
+#define CVMX_L2C_LCKOFF \
+ CVMX_ADD_IO_SEG(0x0001180080000060ull)
+#define CVMX_L2C_LFB0 \
+ CVMX_ADD_IO_SEG(0x0001180080000038ull)
+#define CVMX_L2C_LFB1 \
+ CVMX_ADD_IO_SEG(0x0001180080000040ull)
+#define CVMX_L2C_LFB2 \
+ CVMX_ADD_IO_SEG(0x0001180080000048ull)
+#define CVMX_L2C_LFB3 \
+ CVMX_ADD_IO_SEG(0x00011800800000B8ull)
+#define CVMX_L2C_OOB \
+ CVMX_ADD_IO_SEG(0x00011800800000D8ull)
+#define CVMX_L2C_OOB1 \
+ CVMX_ADD_IO_SEG(0x00011800800000E0ull)
+#define CVMX_L2C_OOB2 \
+ CVMX_ADD_IO_SEG(0x00011800800000E8ull)
+#define CVMX_L2C_OOB3 \
+ CVMX_ADD_IO_SEG(0x00011800800000F0ull)
+#define CVMX_L2C_PFC0 \
+ CVMX_ADD_IO_SEG(0x0001180080000098ull)
+#define CVMX_L2C_PFC1 \
+ CVMX_ADD_IO_SEG(0x00011800800000A0ull)
+#define CVMX_L2C_PFC2 \
+ CVMX_ADD_IO_SEG(0x00011800800000A8ull)
+#define CVMX_L2C_PFC3 \
+ CVMX_ADD_IO_SEG(0x00011800800000B0ull)
+#define CVMX_L2C_PFCTL \
+ CVMX_ADD_IO_SEG(0x0001180080000090ull)
+#define CVMX_L2C_PFCX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180080000098ull + (((offset) & 3) * 8))
+#define CVMX_L2C_PPGRP \
+ CVMX_ADD_IO_SEG(0x00011800800000C0ull)
+#define CVMX_L2C_SPAR0 \
+ CVMX_ADD_IO_SEG(0x0001180080000068ull)
+#define CVMX_L2C_SPAR1 \
+ CVMX_ADD_IO_SEG(0x0001180080000070ull)
+#define CVMX_L2C_SPAR2 \
+ CVMX_ADD_IO_SEG(0x0001180080000078ull)
+#define CVMX_L2C_SPAR3 \
+ CVMX_ADD_IO_SEG(0x0001180080000080ull)
+#define CVMX_L2C_SPAR4 \
+ CVMX_ADD_IO_SEG(0x0001180080000088ull)
+
+union cvmx_l2c_bst0 {
+ uint64_t u64;
+ struct cvmx_l2c_bst0_s {
+ uint64_t reserved_24_63:40;
+ uint64_t dtbnk:1;
+ uint64_t wlb_msk:4;
+ uint64_t dtcnt:13;
+ uint64_t dt:1;
+ uint64_t stin_msk:1;
+ uint64_t wlb_dat:4;
+ } s;
+ struct cvmx_l2c_bst0_cn30xx {
+ uint64_t reserved_23_63:41;
+ uint64_t wlb_msk:4;
+ uint64_t reserved_15_18:4;
+ uint64_t dtcnt:9;
+ uint64_t dt:1;
+ uint64_t reserved_4_4:1;
+ uint64_t wlb_dat:4;
+ } cn30xx;
+ struct cvmx_l2c_bst0_cn31xx {
+ uint64_t reserved_23_63:41;
+ uint64_t wlb_msk:4;
+ uint64_t reserved_16_18:3;
+ uint64_t dtcnt:10;
+ uint64_t dt:1;
+ uint64_t stin_msk:1;
+ uint64_t wlb_dat:4;
+ } cn31xx;
+ struct cvmx_l2c_bst0_cn38xx {
+ uint64_t reserved_19_63:45;
+ uint64_t dtcnt:13;
+ uint64_t dt:1;
+ uint64_t stin_msk:1;
+ uint64_t wlb_dat:4;
+ } cn38xx;
+ struct cvmx_l2c_bst0_cn38xx cn38xxp2;
+ struct cvmx_l2c_bst0_cn50xx {
+ uint64_t reserved_24_63:40;
+ uint64_t dtbnk:1;
+ uint64_t wlb_msk:4;
+ uint64_t reserved_16_18:3;
+ uint64_t dtcnt:10;
+ uint64_t dt:1;
+ uint64_t stin_msk:1;
+ uint64_t wlb_dat:4;
+ } cn50xx;
+ struct cvmx_l2c_bst0_cn50xx cn52xx;
+ struct cvmx_l2c_bst0_cn50xx cn52xxp1;
+ struct cvmx_l2c_bst0_s cn56xx;
+ struct cvmx_l2c_bst0_s cn56xxp1;
+ struct cvmx_l2c_bst0_s cn58xx;
+ struct cvmx_l2c_bst0_s cn58xxp1;
+};
+
+union cvmx_l2c_bst1 {
+ uint64_t u64;
+ struct cvmx_l2c_bst1_s {
+ uint64_t reserved_9_63:55;
+ uint64_t l2t:9;
+ } s;
+ struct cvmx_l2c_bst1_cn30xx {
+ uint64_t reserved_16_63:48;
+ uint64_t vwdf:4;
+ uint64_t lrf:2;
+ uint64_t vab_vwcf:1;
+ uint64_t reserved_5_8:4;
+ uint64_t l2t:5;
+ } cn30xx;
+ struct cvmx_l2c_bst1_cn30xx cn31xx;
+ struct cvmx_l2c_bst1_cn38xx {
+ uint64_t reserved_16_63:48;
+ uint64_t vwdf:4;
+ uint64_t lrf:2;
+ uint64_t vab_vwcf:1;
+ uint64_t l2t:9;
+ } cn38xx;
+ struct cvmx_l2c_bst1_cn38xx cn38xxp2;
+ struct cvmx_l2c_bst1_cn38xx cn50xx;
+ struct cvmx_l2c_bst1_cn52xx {
+ uint64_t reserved_19_63:45;
+ uint64_t plc2:1;
+ uint64_t plc1:1;
+ uint64_t plc0:1;
+ uint64_t vwdf:4;
+ uint64_t reserved_11_11:1;
+ uint64_t ilc:1;
+ uint64_t vab_vwcf:1;
+ uint64_t l2t:9;
+ } cn52xx;
+ struct cvmx_l2c_bst1_cn52xx cn52xxp1;
+ struct cvmx_l2c_bst1_cn56xx {
+ uint64_t reserved_24_63:40;
+ uint64_t plc2:1;
+ uint64_t plc1:1;
+ uint64_t plc0:1;
+ uint64_t ilc:1;
+ uint64_t vwdf1:4;
+ uint64_t vwdf0:4;
+ uint64_t vab_vwcf1:1;
+ uint64_t reserved_10_10:1;
+ uint64_t vab_vwcf0:1;
+ uint64_t l2t:9;
+ } cn56xx;
+ struct cvmx_l2c_bst1_cn56xx cn56xxp1;
+ struct cvmx_l2c_bst1_cn38xx cn58xx;
+ struct cvmx_l2c_bst1_cn38xx cn58xxp1;
+};
+
+union cvmx_l2c_bst2 {
+ uint64_t u64;
+ struct cvmx_l2c_bst2_s {
+ uint64_t reserved_16_63:48;
+ uint64_t mrb:4;
+ uint64_t reserved_4_11:8;
+ uint64_t ipcbst:1;
+ uint64_t picbst:1;
+ uint64_t xrdmsk:1;
+ uint64_t xrddat:1;
+ } s;
+ struct cvmx_l2c_bst2_cn30xx {
+ uint64_t reserved_16_63:48;
+ uint64_t mrb:4;
+ uint64_t rmdf:4;
+ uint64_t reserved_4_7:4;
+ uint64_t ipcbst:1;
+ uint64_t reserved_2_2:1;
+ uint64_t xrdmsk:1;
+ uint64_t xrddat:1;
+ } cn30xx;
+ struct cvmx_l2c_bst2_cn30xx cn31xx;
+ struct cvmx_l2c_bst2_cn38xx {
+ uint64_t reserved_16_63:48;
+ uint64_t mrb:4;
+ uint64_t rmdf:4;
+ uint64_t rhdf:4;
+ uint64_t ipcbst:1;
+ uint64_t picbst:1;
+ uint64_t xrdmsk:1;
+ uint64_t xrddat:1;
+ } cn38xx;
+ struct cvmx_l2c_bst2_cn38xx cn38xxp2;
+ struct cvmx_l2c_bst2_cn30xx cn50xx;
+ struct cvmx_l2c_bst2_cn30xx cn52xx;
+ struct cvmx_l2c_bst2_cn30xx cn52xxp1;
+ struct cvmx_l2c_bst2_cn56xx {
+ uint64_t reserved_16_63:48;
+ uint64_t mrb:4;
+ uint64_t rmdb:4;
+ uint64_t rhdb:4;
+ uint64_t ipcbst:1;
+ uint64_t picbst:1;
+ uint64_t xrdmsk:1;
+ uint64_t xrddat:1;
+ } cn56xx;
+ struct cvmx_l2c_bst2_cn56xx cn56xxp1;
+ struct cvmx_l2c_bst2_cn56xx cn58xx;
+ struct cvmx_l2c_bst2_cn56xx cn58xxp1;
+};
+
+union cvmx_l2c_cfg {
+ uint64_t u64;
+ struct cvmx_l2c_cfg_s {
+ uint64_t reserved_20_63:44;
+ uint64_t bstrun:1;
+ uint64_t lbist:1;
+ uint64_t xor_bank:1;
+ uint64_t dpres1:1;
+ uint64_t dpres0:1;
+ uint64_t dfill_dis:1;
+ uint64_t fpexp:4;
+ uint64_t fpempty:1;
+ uint64_t fpen:1;
+ uint64_t idxalias:1;
+ uint64_t mwf_crd:4;
+ uint64_t rsp_arb_mode:1;
+ uint64_t rfb_arb_mode:1;
+ uint64_t lrf_arb_mode:1;
+ } s;
+ struct cvmx_l2c_cfg_cn30xx {
+ uint64_t reserved_14_63:50;
+ uint64_t fpexp:4;
+ uint64_t fpempty:1;
+ uint64_t fpen:1;
+ uint64_t idxalias:1;
+ uint64_t mwf_crd:4;
+ uint64_t rsp_arb_mode:1;
+ uint64_t rfb_arb_mode:1;
+ uint64_t lrf_arb_mode:1;
+ } cn30xx;
+ struct cvmx_l2c_cfg_cn30xx cn31xx;
+ struct cvmx_l2c_cfg_cn30xx cn38xx;
+ struct cvmx_l2c_cfg_cn30xx cn38xxp2;
+ struct cvmx_l2c_cfg_cn50xx {
+ uint64_t reserved_20_63:44;
+ uint64_t bstrun:1;
+ uint64_t lbist:1;
+ uint64_t reserved_14_17:4;
+ uint64_t fpexp:4;
+ uint64_t fpempty:1;
+ uint64_t fpen:1;
+ uint64_t idxalias:1;
+ uint64_t mwf_crd:4;
+ uint64_t rsp_arb_mode:1;
+ uint64_t rfb_arb_mode:1;
+ uint64_t lrf_arb_mode:1;
+ } cn50xx;
+ struct cvmx_l2c_cfg_cn50xx cn52xx;
+ struct cvmx_l2c_cfg_cn50xx cn52xxp1;
+ struct cvmx_l2c_cfg_s cn56xx;
+ struct cvmx_l2c_cfg_s cn56xxp1;
+ struct cvmx_l2c_cfg_cn58xx {
+ uint64_t reserved_20_63:44;
+ uint64_t bstrun:1;
+ uint64_t lbist:1;
+ uint64_t reserved_15_17:3;
+ uint64_t dfill_dis:1;
+ uint64_t fpexp:4;
+ uint64_t fpempty:1;
+ uint64_t fpen:1;
+ uint64_t idxalias:1;
+ uint64_t mwf_crd:4;
+ uint64_t rsp_arb_mode:1;
+ uint64_t rfb_arb_mode:1;
+ uint64_t lrf_arb_mode:1;
+ } cn58xx;
+ struct cvmx_l2c_cfg_cn58xxp1 {
+ uint64_t reserved_15_63:49;
+ uint64_t dfill_dis:1;
+ uint64_t fpexp:4;
+ uint64_t fpempty:1;
+ uint64_t fpen:1;
+ uint64_t idxalias:1;
+ uint64_t mwf_crd:4;
+ uint64_t rsp_arb_mode:1;
+ uint64_t rfb_arb_mode:1;
+ uint64_t lrf_arb_mode:1;
+ } cn58xxp1;
+};
+
+union cvmx_l2c_dbg {
+ uint64_t u64;
+ struct cvmx_l2c_dbg_s {
+ uint64_t reserved_15_63:49;
+ uint64_t lfb_enum:4;
+ uint64_t lfb_dmp:1;
+ uint64_t ppnum:4;
+ uint64_t set:3;
+ uint64_t finv:1;
+ uint64_t l2d:1;
+ uint64_t l2t:1;
+ } s;
+ struct cvmx_l2c_dbg_cn30xx {
+ uint64_t reserved_13_63:51;
+ uint64_t lfb_enum:2;
+ uint64_t lfb_dmp:1;
+ uint64_t reserved_5_9:5;
+ uint64_t set:2;
+ uint64_t finv:1;
+ uint64_t l2d:1;
+ uint64_t l2t:1;
+ } cn30xx;
+ struct cvmx_l2c_dbg_cn31xx {
+ uint64_t reserved_14_63:50;
+ uint64_t lfb_enum:3;
+ uint64_t lfb_dmp:1;
+ uint64_t reserved_7_9:3;
+ uint64_t ppnum:1;
+ uint64_t reserved_5_5:1;
+ uint64_t set:2;
+ uint64_t finv:1;
+ uint64_t l2d:1;
+ uint64_t l2t:1;
+ } cn31xx;
+ struct cvmx_l2c_dbg_s cn38xx;
+ struct cvmx_l2c_dbg_s cn38xxp2;
+ struct cvmx_l2c_dbg_cn50xx {
+ uint64_t reserved_14_63:50;
+ uint64_t lfb_enum:3;
+ uint64_t lfb_dmp:1;
+ uint64_t reserved_7_9:3;
+ uint64_t ppnum:1;
+ uint64_t set:3;
+ uint64_t finv:1;
+ uint64_t l2d:1;
+ uint64_t l2t:1;
+ } cn50xx;
+ struct cvmx_l2c_dbg_cn52xx {
+ uint64_t reserved_14_63:50;
+ uint64_t lfb_enum:3;
+ uint64_t lfb_dmp:1;
+ uint64_t reserved_8_9:2;
+ uint64_t ppnum:2;
+ uint64_t set:3;
+ uint64_t finv:1;
+ uint64_t l2d:1;
+ uint64_t l2t:1;
+ } cn52xx;
+ struct cvmx_l2c_dbg_cn52xx cn52xxp1;
+ struct cvmx_l2c_dbg_s cn56xx;
+ struct cvmx_l2c_dbg_s cn56xxp1;
+ struct cvmx_l2c_dbg_s cn58xx;
+ struct cvmx_l2c_dbg_s cn58xxp1;
+};
+
+union cvmx_l2c_dut {
+ uint64_t u64;
+ struct cvmx_l2c_dut_s {
+ uint64_t reserved_32_63:32;
+ uint64_t dtena:1;
+ uint64_t reserved_30_30:1;
+ uint64_t dt_vld:1;
+ uint64_t dt_tag:29;
+ } s;
+ struct cvmx_l2c_dut_s cn30xx;
+ struct cvmx_l2c_dut_s cn31xx;
+ struct cvmx_l2c_dut_s cn38xx;
+ struct cvmx_l2c_dut_s cn38xxp2;
+ struct cvmx_l2c_dut_s cn50xx;
+ struct cvmx_l2c_dut_s cn52xx;
+ struct cvmx_l2c_dut_s cn52xxp1;
+ struct cvmx_l2c_dut_s cn56xx;
+ struct cvmx_l2c_dut_s cn56xxp1;
+ struct cvmx_l2c_dut_s cn58xx;
+ struct cvmx_l2c_dut_s cn58xxp1;
+};
+
+union cvmx_l2c_grpwrr0 {
+ uint64_t u64;
+ struct cvmx_l2c_grpwrr0_s {
+ uint64_t plc1rmsk:32;
+ uint64_t plc0rmsk:32;
+ } s;
+ struct cvmx_l2c_grpwrr0_s cn52xx;
+ struct cvmx_l2c_grpwrr0_s cn52xxp1;
+ struct cvmx_l2c_grpwrr0_s cn56xx;
+ struct cvmx_l2c_grpwrr0_s cn56xxp1;
+};
+
+union cvmx_l2c_grpwrr1 {
+ uint64_t u64;
+ struct cvmx_l2c_grpwrr1_s {
+ uint64_t ilcrmsk:32;
+ uint64_t plc2rmsk:32;
+ } s;
+ struct cvmx_l2c_grpwrr1_s cn52xx;
+ struct cvmx_l2c_grpwrr1_s cn52xxp1;
+ struct cvmx_l2c_grpwrr1_s cn56xx;
+ struct cvmx_l2c_grpwrr1_s cn56xxp1;
+};
+
+union cvmx_l2c_int_en {
+ uint64_t u64;
+ struct cvmx_l2c_int_en_s {
+ uint64_t reserved_9_63:55;
+ uint64_t lck2ena:1;
+ uint64_t lckena:1;
+ uint64_t l2ddeden:1;
+ uint64_t l2dsecen:1;
+ uint64_t l2tdeden:1;
+ uint64_t l2tsecen:1;
+ uint64_t oob3en:1;
+ uint64_t oob2en:1;
+ uint64_t oob1en:1;
+ } s;
+ struct cvmx_l2c_int_en_s cn52xx;
+ struct cvmx_l2c_int_en_s cn52xxp1;
+ struct cvmx_l2c_int_en_s cn56xx;
+ struct cvmx_l2c_int_en_s cn56xxp1;
+};
+
+union cvmx_l2c_int_stat {
+ uint64_t u64;
+ struct cvmx_l2c_int_stat_s {
+ uint64_t reserved_9_63:55;
+ uint64_t lck2:1;
+ uint64_t lck:1;
+ uint64_t l2dded:1;
+ uint64_t l2dsec:1;
+ uint64_t l2tded:1;
+ uint64_t l2tsec:1;
+ uint64_t oob3:1;
+ uint64_t oob2:1;
+ uint64_t oob1:1;
+ } s;
+ struct cvmx_l2c_int_stat_s cn52xx;
+ struct cvmx_l2c_int_stat_s cn52xxp1;
+ struct cvmx_l2c_int_stat_s cn56xx;
+ struct cvmx_l2c_int_stat_s cn56xxp1;
+};
+
+union cvmx_l2c_lckbase {
+ uint64_t u64;
+ struct cvmx_l2c_lckbase_s {
+ uint64_t reserved_31_63:33;
+ uint64_t lck_base:27;
+ uint64_t reserved_1_3:3;
+ uint64_t lck_ena:1;
+ } s;
+ struct cvmx_l2c_lckbase_s cn30xx;
+ struct cvmx_l2c_lckbase_s cn31xx;
+ struct cvmx_l2c_lckbase_s cn38xx;
+ struct cvmx_l2c_lckbase_s cn38xxp2;
+ struct cvmx_l2c_lckbase_s cn50xx;
+ struct cvmx_l2c_lckbase_s cn52xx;
+ struct cvmx_l2c_lckbase_s cn52xxp1;
+ struct cvmx_l2c_lckbase_s cn56xx;
+ struct cvmx_l2c_lckbase_s cn56xxp1;
+ struct cvmx_l2c_lckbase_s cn58xx;
+ struct cvmx_l2c_lckbase_s cn58xxp1;
+};
+
+union cvmx_l2c_lckoff {
+ uint64_t u64;
+ struct cvmx_l2c_lckoff_s {
+ uint64_t reserved_10_63:54;
+ uint64_t lck_offset:10;
+ } s;
+ struct cvmx_l2c_lckoff_s cn30xx;
+ struct cvmx_l2c_lckoff_s cn31xx;
+ struct cvmx_l2c_lckoff_s cn38xx;
+ struct cvmx_l2c_lckoff_s cn38xxp2;
+ struct cvmx_l2c_lckoff_s cn50xx;
+ struct cvmx_l2c_lckoff_s cn52xx;
+ struct cvmx_l2c_lckoff_s cn52xxp1;
+ struct cvmx_l2c_lckoff_s cn56xx;
+ struct cvmx_l2c_lckoff_s cn56xxp1;
+ struct cvmx_l2c_lckoff_s cn58xx;
+ struct cvmx_l2c_lckoff_s cn58xxp1;
+};
+
+union cvmx_l2c_lfb0 {
+ uint64_t u64;
+ struct cvmx_l2c_lfb0_s {
+ uint64_t reserved_32_63:32;
+ uint64_t stcpnd:1;
+ uint64_t stpnd:1;
+ uint64_t stinv:1;
+ uint64_t stcfl:1;
+ uint64_t vam:1;
+ uint64_t inxt:4;
+ uint64_t itl:1;
+ uint64_t ihd:1;
+ uint64_t set:3;
+ uint64_t vabnum:4;
+ uint64_t sid:9;
+ uint64_t cmd:4;
+ uint64_t vld:1;
+ } s;
+ struct cvmx_l2c_lfb0_cn30xx {
+ uint64_t reserved_32_63:32;
+ uint64_t stcpnd:1;
+ uint64_t stpnd:1;
+ uint64_t stinv:1;
+ uint64_t stcfl:1;
+ uint64_t vam:1;
+ uint64_t reserved_25_26:2;
+ uint64_t inxt:2;
+ uint64_t itl:1;
+ uint64_t ihd:1;
+ uint64_t reserved_20_20:1;
+ uint64_t set:2;
+ uint64_t reserved_16_17:2;
+ uint64_t vabnum:2;
+ uint64_t sid:9;
+ uint64_t cmd:4;
+ uint64_t vld:1;
+ } cn30xx;
+ struct cvmx_l2c_lfb0_cn31xx {
+ uint64_t reserved_32_63:32;
+ uint64_t stcpnd:1;
+ uint64_t stpnd:1;
+ uint64_t stinv:1;
+ uint64_t stcfl:1;
+ uint64_t vam:1;
+ uint64_t reserved_26_26:1;
+ uint64_t inxt:3;
+ uint64_t itl:1;
+ uint64_t ihd:1;
+ uint64_t reserved_20_20:1;
+ uint64_t set:2;
+ uint64_t reserved_17_17:1;
+ uint64_t vabnum:3;
+ uint64_t sid:9;
+ uint64_t cmd:4;
+ uint64_t vld:1;
+ } cn31xx;
+ struct cvmx_l2c_lfb0_s cn38xx;
+ struct cvmx_l2c_lfb0_s cn38xxp2;
+ struct cvmx_l2c_lfb0_cn50xx {
+ uint64_t reserved_32_63:32;
+ uint64_t stcpnd:1;
+ uint64_t stpnd:1;
+ uint64_t stinv:1;
+ uint64_t stcfl:1;
+ uint64_t vam:1;
+ uint64_t reserved_26_26:1;
+ uint64_t inxt:3;
+ uint64_t itl:1;
+ uint64_t ihd:1;
+ uint64_t set:3;
+ uint64_t reserved_17_17:1;
+ uint64_t vabnum:3;
+ uint64_t sid:9;
+ uint64_t cmd:4;
+ uint64_t vld:1;
+ } cn50xx;
+ struct cvmx_l2c_lfb0_cn50xx cn52xx;
+ struct cvmx_l2c_lfb0_cn50xx cn52xxp1;
+ struct cvmx_l2c_lfb0_s cn56xx;
+ struct cvmx_l2c_lfb0_s cn56xxp1;
+ struct cvmx_l2c_lfb0_s cn58xx;
+ struct cvmx_l2c_lfb0_s cn58xxp1;
+};
+
+union cvmx_l2c_lfb1 {
+ uint64_t u64;
+ struct cvmx_l2c_lfb1_s {
+ uint64_t reserved_19_63:45;
+ uint64_t dsgoing:1;
+ uint64_t bid:2;
+ uint64_t wtrsp:1;
+ uint64_t wtdw:1;
+ uint64_t wtdq:1;
+ uint64_t wtwhp:1;
+ uint64_t wtwhf:1;
+ uint64_t wtwrm:1;
+ uint64_t wtstm:1;
+ uint64_t wtrda:1;
+ uint64_t wtstdt:1;
+ uint64_t wtstrsp:1;
+ uint64_t wtstrsc:1;
+ uint64_t wtvtm:1;
+ uint64_t wtmfl:1;
+ uint64_t prbrty:1;
+ uint64_t wtprb:1;
+ uint64_t vld:1;
+ } s;
+ struct cvmx_l2c_lfb1_s cn30xx;
+ struct cvmx_l2c_lfb1_s cn31xx;
+ struct cvmx_l2c_lfb1_s cn38xx;
+ struct cvmx_l2c_lfb1_s cn38xxp2;
+ struct cvmx_l2c_lfb1_s cn50xx;
+ struct cvmx_l2c_lfb1_s cn52xx;
+ struct cvmx_l2c_lfb1_s cn52xxp1;
+ struct cvmx_l2c_lfb1_s cn56xx;
+ struct cvmx_l2c_lfb1_s cn56xxp1;
+ struct cvmx_l2c_lfb1_s cn58xx;
+ struct cvmx_l2c_lfb1_s cn58xxp1;
+};
+
+union cvmx_l2c_lfb2 {
+ uint64_t u64;
+ struct cvmx_l2c_lfb2_s {
+ uint64_t reserved_0_63:64;
+ } s;
+ struct cvmx_l2c_lfb2_cn30xx {
+ uint64_t reserved_27_63:37;
+ uint64_t lfb_tag:19;
+ uint64_t lfb_idx:8;
+ } cn30xx;
+ struct cvmx_l2c_lfb2_cn31xx {
+ uint64_t reserved_27_63:37;
+ uint64_t lfb_tag:17;
+ uint64_t lfb_idx:10;
+ } cn31xx;
+ struct cvmx_l2c_lfb2_cn31xx cn38xx;
+ struct cvmx_l2c_lfb2_cn31xx cn38xxp2;
+ struct cvmx_l2c_lfb2_cn50xx {
+ uint64_t reserved_27_63:37;
+ uint64_t lfb_tag:20;
+ uint64_t lfb_idx:7;
+ } cn50xx;
+ struct cvmx_l2c_lfb2_cn52xx {
+ uint64_t reserved_27_63:37;
+ uint64_t lfb_tag:18;
+ uint64_t lfb_idx:9;
+ } cn52xx;
+ struct cvmx_l2c_lfb2_cn52xx cn52xxp1;
+ struct cvmx_l2c_lfb2_cn56xx {
+ uint64_t reserved_27_63:37;
+ uint64_t lfb_tag:16;
+ uint64_t lfb_idx:11;
+ } cn56xx;
+ struct cvmx_l2c_lfb2_cn56xx cn56xxp1;
+ struct cvmx_l2c_lfb2_cn56xx cn58xx;
+ struct cvmx_l2c_lfb2_cn56xx cn58xxp1;
+};
+
+union cvmx_l2c_lfb3 {
+ uint64_t u64;
+ struct cvmx_l2c_lfb3_s {
+ uint64_t reserved_5_63:59;
+ uint64_t stpartdis:1;
+ uint64_t lfb_hwm:4;
+ } s;
+ struct cvmx_l2c_lfb3_cn30xx {
+ uint64_t reserved_5_63:59;
+ uint64_t stpartdis:1;
+ uint64_t reserved_2_3:2;
+ uint64_t lfb_hwm:2;
+ } cn30xx;
+ struct cvmx_l2c_lfb3_cn31xx {
+ uint64_t reserved_5_63:59;
+ uint64_t stpartdis:1;
+ uint64_t reserved_3_3:1;
+ uint64_t lfb_hwm:3;
+ } cn31xx;
+ struct cvmx_l2c_lfb3_s cn38xx;
+ struct cvmx_l2c_lfb3_s cn38xxp2;
+ struct cvmx_l2c_lfb3_cn31xx cn50xx;
+ struct cvmx_l2c_lfb3_cn31xx cn52xx;
+ struct cvmx_l2c_lfb3_cn31xx cn52xxp1;
+ struct cvmx_l2c_lfb3_s cn56xx;
+ struct cvmx_l2c_lfb3_s cn56xxp1;
+ struct cvmx_l2c_lfb3_s cn58xx;
+ struct cvmx_l2c_lfb3_s cn58xxp1;
+};
+
+union cvmx_l2c_oob {
+ uint64_t u64;
+ struct cvmx_l2c_oob_s {
+ uint64_t reserved_2_63:62;
+ uint64_t dwbena:1;
+ uint64_t stena:1;
+ } s;
+ struct cvmx_l2c_oob_s cn52xx;
+ struct cvmx_l2c_oob_s cn52xxp1;
+ struct cvmx_l2c_oob_s cn56xx;
+ struct cvmx_l2c_oob_s cn56xxp1;
+};
+
+union cvmx_l2c_oob1 {
+ uint64_t u64;
+ struct cvmx_l2c_oob1_s {
+ uint64_t fadr:27;
+ uint64_t fsrc:1;
+ uint64_t reserved_34_35:2;
+ uint64_t sadr:14;
+ uint64_t reserved_14_19:6;
+ uint64_t size:14;
+ } s;
+ struct cvmx_l2c_oob1_s cn52xx;
+ struct cvmx_l2c_oob1_s cn52xxp1;
+ struct cvmx_l2c_oob1_s cn56xx;
+ struct cvmx_l2c_oob1_s cn56xxp1;
+};
+
+union cvmx_l2c_oob2 {
+ uint64_t u64;
+ struct cvmx_l2c_oob2_s {
+ uint64_t fadr:27;
+ uint64_t fsrc:1;
+ uint64_t reserved_34_35:2;
+ uint64_t sadr:14;
+ uint64_t reserved_14_19:6;
+ uint64_t size:14;
+ } s;
+ struct cvmx_l2c_oob2_s cn52xx;
+ struct cvmx_l2c_oob2_s cn52xxp1;
+ struct cvmx_l2c_oob2_s cn56xx;
+ struct cvmx_l2c_oob2_s cn56xxp1;
+};
+
+union cvmx_l2c_oob3 {
+ uint64_t u64;
+ struct cvmx_l2c_oob3_s {
+ uint64_t fadr:27;
+ uint64_t fsrc:1;
+ uint64_t reserved_34_35:2;
+ uint64_t sadr:14;
+ uint64_t reserved_14_19:6;
+ uint64_t size:14;
+ } s;
+ struct cvmx_l2c_oob3_s cn52xx;
+ struct cvmx_l2c_oob3_s cn52xxp1;
+ struct cvmx_l2c_oob3_s cn56xx;
+ struct cvmx_l2c_oob3_s cn56xxp1;
+};
+
+union cvmx_l2c_pfcx {
+ uint64_t u64;
+ struct cvmx_l2c_pfcx_s {
+ uint64_t reserved_36_63:28;
+ uint64_t pfcnt0:36;
+ } s;
+ struct cvmx_l2c_pfcx_s cn30xx;
+ struct cvmx_l2c_pfcx_s cn31xx;
+ struct cvmx_l2c_pfcx_s cn38xx;
+ struct cvmx_l2c_pfcx_s cn38xxp2;
+ struct cvmx_l2c_pfcx_s cn50xx;
+ struct cvmx_l2c_pfcx_s cn52xx;
+ struct cvmx_l2c_pfcx_s cn52xxp1;
+ struct cvmx_l2c_pfcx_s cn56xx;
+ struct cvmx_l2c_pfcx_s cn56xxp1;
+ struct cvmx_l2c_pfcx_s cn58xx;
+ struct cvmx_l2c_pfcx_s cn58xxp1;
+};
+
+union cvmx_l2c_pfctl {
+ uint64_t u64;
+ struct cvmx_l2c_pfctl_s {
+ uint64_t reserved_36_63:28;
+ uint64_t cnt3rdclr:1;
+ uint64_t cnt2rdclr:1;
+ uint64_t cnt1rdclr:1;
+ uint64_t cnt0rdclr:1;
+ uint64_t cnt3ena:1;
+ uint64_t cnt3clr:1;
+ uint64_t cnt3sel:6;
+ uint64_t cnt2ena:1;
+ uint64_t cnt2clr:1;
+ uint64_t cnt2sel:6;
+ uint64_t cnt1ena:1;
+ uint64_t cnt1clr:1;
+ uint64_t cnt1sel:6;
+ uint64_t cnt0ena:1;
+ uint64_t cnt0clr:1;
+ uint64_t cnt0sel:6;
+ } s;
+ struct cvmx_l2c_pfctl_s cn30xx;
+ struct cvmx_l2c_pfctl_s cn31xx;
+ struct cvmx_l2c_pfctl_s cn38xx;
+ struct cvmx_l2c_pfctl_s cn38xxp2;
+ struct cvmx_l2c_pfctl_s cn50xx;
+ struct cvmx_l2c_pfctl_s cn52xx;
+ struct cvmx_l2c_pfctl_s cn52xxp1;
+ struct cvmx_l2c_pfctl_s cn56xx;
+ struct cvmx_l2c_pfctl_s cn56xxp1;
+ struct cvmx_l2c_pfctl_s cn58xx;
+ struct cvmx_l2c_pfctl_s cn58xxp1;
+};
+
+union cvmx_l2c_ppgrp {
+ uint64_t u64;
+ struct cvmx_l2c_ppgrp_s {
+ uint64_t reserved_24_63:40;
+ uint64_t pp11grp:2;
+ uint64_t pp10grp:2;
+ uint64_t pp9grp:2;
+ uint64_t pp8grp:2;
+ uint64_t pp7grp:2;
+ uint64_t pp6grp:2;
+ uint64_t pp5grp:2;
+ uint64_t pp4grp:2;
+ uint64_t pp3grp:2;
+ uint64_t pp2grp:2;
+ uint64_t pp1grp:2;
+ uint64_t pp0grp:2;
+ } s;
+ struct cvmx_l2c_ppgrp_cn52xx {
+ uint64_t reserved_8_63:56;
+ uint64_t pp3grp:2;
+ uint64_t pp2grp:2;
+ uint64_t pp1grp:2;
+ uint64_t pp0grp:2;
+ } cn52xx;
+ struct cvmx_l2c_ppgrp_cn52xx cn52xxp1;
+ struct cvmx_l2c_ppgrp_s cn56xx;
+ struct cvmx_l2c_ppgrp_s cn56xxp1;
+};
+
+union cvmx_l2c_spar0 {
+ uint64_t u64;
+ struct cvmx_l2c_spar0_s {
+ uint64_t reserved_32_63:32;
+ uint64_t umsk3:8;
+ uint64_t umsk2:8;
+ uint64_t umsk1:8;
+ uint64_t umsk0:8;
+ } s;
+ struct cvmx_l2c_spar0_cn30xx {
+ uint64_t reserved_4_63:60;
+ uint64_t umsk0:4;
+ } cn30xx;
+ struct cvmx_l2c_spar0_cn31xx {
+ uint64_t reserved_12_63:52;
+ uint64_t umsk1:4;
+ uint64_t reserved_4_7:4;
+ uint64_t umsk0:4;
+ } cn31xx;
+ struct cvmx_l2c_spar0_s cn38xx;
+ struct cvmx_l2c_spar0_s cn38xxp2;
+ struct cvmx_l2c_spar0_cn50xx {
+ uint64_t reserved_16_63:48;
+ uint64_t umsk1:8;
+ uint64_t umsk0:8;
+ } cn50xx;
+ struct cvmx_l2c_spar0_s cn52xx;
+ struct cvmx_l2c_spar0_s cn52xxp1;
+ struct cvmx_l2c_spar0_s cn56xx;
+ struct cvmx_l2c_spar0_s cn56xxp1;
+ struct cvmx_l2c_spar0_s cn58xx;
+ struct cvmx_l2c_spar0_s cn58xxp1;
+};
+
+union cvmx_l2c_spar1 {
+ uint64_t u64;
+ struct cvmx_l2c_spar1_s {
+ uint64_t reserved_32_63:32;
+ uint64_t umsk7:8;
+ uint64_t umsk6:8;
+ uint64_t umsk5:8;
+ uint64_t umsk4:8;
+ } s;
+ struct cvmx_l2c_spar1_s cn38xx;
+ struct cvmx_l2c_spar1_s cn38xxp2;
+ struct cvmx_l2c_spar1_s cn56xx;
+ struct cvmx_l2c_spar1_s cn56xxp1;
+ struct cvmx_l2c_spar1_s cn58xx;
+ struct cvmx_l2c_spar1_s cn58xxp1;
+};
+
+union cvmx_l2c_spar2 {
+ uint64_t u64;
+ struct cvmx_l2c_spar2_s {
+ uint64_t reserved_32_63:32;
+ uint64_t umsk11:8;
+ uint64_t umsk10:8;
+ uint64_t umsk9:8;
+ uint64_t umsk8:8;
+ } s;
+ struct cvmx_l2c_spar2_s cn38xx;
+ struct cvmx_l2c_spar2_s cn38xxp2;
+ struct cvmx_l2c_spar2_s cn56xx;
+ struct cvmx_l2c_spar2_s cn56xxp1;
+ struct cvmx_l2c_spar2_s cn58xx;
+ struct cvmx_l2c_spar2_s cn58xxp1;
+};
+
+union cvmx_l2c_spar3 {
+ uint64_t u64;
+ struct cvmx_l2c_spar3_s {
+ uint64_t reserved_32_63:32;
+ uint64_t umsk15:8;
+ uint64_t umsk14:8;
+ uint64_t umsk13:8;
+ uint64_t umsk12:8;
+ } s;
+ struct cvmx_l2c_spar3_s cn38xx;
+ struct cvmx_l2c_spar3_s cn38xxp2;
+ struct cvmx_l2c_spar3_s cn58xx;
+ struct cvmx_l2c_spar3_s cn58xxp1;
+};
+
+union cvmx_l2c_spar4 {
+ uint64_t u64;
+ struct cvmx_l2c_spar4_s {
+ uint64_t reserved_8_63:56;
+ uint64_t umskiob:8;
+ } s;
+ struct cvmx_l2c_spar4_cn30xx {
+ uint64_t reserved_4_63:60;
+ uint64_t umskiob:4;
+ } cn30xx;
+ struct cvmx_l2c_spar4_cn30xx cn31xx;
+ struct cvmx_l2c_spar4_s cn38xx;
+ struct cvmx_l2c_spar4_s cn38xxp2;
+ struct cvmx_l2c_spar4_s cn50xx;
+ struct cvmx_l2c_spar4_s cn52xx;
+ struct cvmx_l2c_spar4_s cn52xxp1;
+ struct cvmx_l2c_spar4_s cn56xx;
+ struct cvmx_l2c_spar4_s cn56xxp1;
+ struct cvmx_l2c_spar4_s cn58xx;
+ struct cvmx_l2c_spar4_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-l2c.h b/arch/mips/include/asm/octeon/cvmx-l2c.h
new file mode 100644
index 000000000000..2a8c0902ea50
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-l2c.h
@@ -0,0 +1,325 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ *
+ * Interface to the Level 2 Cache (L2C) control, measurement, and debugging
+ * facilities.
+ */
+
+#ifndef __CVMX_L2C_H__
+#define __CVMX_L2C_H__
+
+/* Deprecated macro, use function */
+#define CVMX_L2_ASSOC cvmx_l2c_get_num_assoc()
+
+/* Deprecated macro, use function */
+#define CVMX_L2_SET_BITS cvmx_l2c_get_set_bits()
+
+/* Deprecated macro, use function */
+#define CVMX_L2_SETS cvmx_l2c_get_num_sets()
+
+#define CVMX_L2C_IDX_ADDR_SHIFT 7 /* based on 128 byte cache line size */
+#define CVMX_L2C_IDX_MASK (cvmx_l2c_get_num_sets() - 1)
+
+/* Defines for index aliasing computations */
+#define CVMX_L2C_TAG_ADDR_ALIAS_SHIFT \
+ (CVMX_L2C_IDX_ADDR_SHIFT + cvmx_l2c_get_set_bits())
+
+#define CVMX_L2C_ALIAS_MASK \
+ (CVMX_L2C_IDX_MASK << CVMX_L2C_TAG_ADDR_ALIAS_SHIFT)
+
+union cvmx_l2c_tag {
+ uint64_t u64;
+ struct {
+ uint64_t reserved:28;
+ uint64_t V:1; /* Line valid */
+ uint64_t D:1; /* Line dirty */
+ uint64_t L:1; /* Line locked */
+ uint64_t U:1; /* Use, LRU eviction */
+ uint64_t addr:32; /* Phys mem (not all bits valid) */
+ } s;
+};
+
+ /* L2C Performance Counter events. */
+enum cvmx_l2c_event {
+ CVMX_L2C_EVENT_CYCLES = 0,
+ CVMX_L2C_EVENT_INSTRUCTION_MISS = 1,
+ CVMX_L2C_EVENT_INSTRUCTION_HIT = 2,
+ CVMX_L2C_EVENT_DATA_MISS = 3,
+ CVMX_L2C_EVENT_DATA_HIT = 4,
+ CVMX_L2C_EVENT_MISS = 5,
+ CVMX_L2C_EVENT_HIT = 6,
+ CVMX_L2C_EVENT_VICTIM_HIT = 7,
+ CVMX_L2C_EVENT_INDEX_CONFLICT = 8,
+ CVMX_L2C_EVENT_TAG_PROBE = 9,
+ CVMX_L2C_EVENT_TAG_UPDATE = 10,
+ CVMX_L2C_EVENT_TAG_COMPLETE = 11,
+ CVMX_L2C_EVENT_TAG_DIRTY = 12,
+ CVMX_L2C_EVENT_DATA_STORE_NOP = 13,
+ CVMX_L2C_EVENT_DATA_STORE_READ = 14,
+ CVMX_L2C_EVENT_DATA_STORE_WRITE = 15,
+ CVMX_L2C_EVENT_FILL_DATA_VALID = 16,
+ CVMX_L2C_EVENT_WRITE_REQUEST = 17,
+ CVMX_L2C_EVENT_READ_REQUEST = 18,
+ CVMX_L2C_EVENT_WRITE_DATA_VALID = 19,
+ CVMX_L2C_EVENT_XMC_NOP = 20,
+ CVMX_L2C_EVENT_XMC_LDT = 21,
+ CVMX_L2C_EVENT_XMC_LDI = 22,
+ CVMX_L2C_EVENT_XMC_LDD = 23,
+ CVMX_L2C_EVENT_XMC_STF = 24,
+ CVMX_L2C_EVENT_XMC_STT = 25,
+ CVMX_L2C_EVENT_XMC_STP = 26,
+ CVMX_L2C_EVENT_XMC_STC = 27,
+ CVMX_L2C_EVENT_XMC_DWB = 28,
+ CVMX_L2C_EVENT_XMC_PL2 = 29,
+ CVMX_L2C_EVENT_XMC_PSL1 = 30,
+ CVMX_L2C_EVENT_XMC_IOBLD = 31,
+ CVMX_L2C_EVENT_XMC_IOBST = 32,
+ CVMX_L2C_EVENT_XMC_IOBDMA = 33,
+ CVMX_L2C_EVENT_XMC_IOBRSP = 34,
+ CVMX_L2C_EVENT_XMC_BUS_VALID = 35,
+ CVMX_L2C_EVENT_XMC_MEM_DATA = 36,
+ CVMX_L2C_EVENT_XMC_REFL_DATA = 37,
+ CVMX_L2C_EVENT_XMC_IOBRSP_DATA = 38,
+ CVMX_L2C_EVENT_RSC_NOP = 39,
+ CVMX_L2C_EVENT_RSC_STDN = 40,
+ CVMX_L2C_EVENT_RSC_FILL = 41,
+ CVMX_L2C_EVENT_RSC_REFL = 42,
+ CVMX_L2C_EVENT_RSC_STIN = 43,
+ CVMX_L2C_EVENT_RSC_SCIN = 44,
+ CVMX_L2C_EVENT_RSC_SCFL = 45,
+ CVMX_L2C_EVENT_RSC_SCDN = 46,
+ CVMX_L2C_EVENT_RSC_DATA_VALID = 47,
+ CVMX_L2C_EVENT_RSC_VALID_FILL = 48,
+ CVMX_L2C_EVENT_RSC_VALID_STRSP = 49,
+ CVMX_L2C_EVENT_RSC_VALID_REFL = 50,
+ CVMX_L2C_EVENT_LRF_REQ = 51,
+ CVMX_L2C_EVENT_DT_RD_ALLOC = 52,
+ CVMX_L2C_EVENT_DT_WR_INVAL = 53
+};
+
+/**
+ * Configure one of the four L2 Cache performance counters to capture event
+ * occurences.
+ *
+ * @counter: The counter to configure. Range 0..3.
+ * @event: The type of L2 Cache event occurrence to count.
+ * @clear_on_read: When asserted, any read of the performance counter
+ * clears the counter.
+ *
+ * The routine does not clear the counter.
+ */
+void cvmx_l2c_config_perf(uint32_t counter,
+ enum cvmx_l2c_event event, uint32_t clear_on_read);
+/**
+ * Read the given L2 Cache performance counter. The counter must be configured
+ * before reading, but this routine does not enforce this requirement.
+ *
+ * @counter: The counter to configure. Range 0..3.
+ *
+ * Returns The current counter value.
+ */
+uint64_t cvmx_l2c_read_perf(uint32_t counter);
+
+/**
+ * Return the L2 Cache way partitioning for a given core.
+ *
+ * @core: The core processor of interest.
+ *
+ * Returns The mask specifying the partitioning. 0 bits in mask indicates
+ * the cache 'ways' that a core can evict from.
+ * -1 on error
+ */
+int cvmx_l2c_get_core_way_partition(uint32_t core);
+
+/**
+ * Partitions the L2 cache for a core
+ *
+ * @core: The core that the partitioning applies to.
+ *
+ * @mask: The partitioning of the ways expressed as a binary mask. A 0
+ * bit allows the core to evict cache lines from a way, while a
+ * 1 bit blocks the core from evicting any lines from that
+ * way. There must be at least one allowed way (0 bit) in the
+ * mask.
+ *
+ * If any ways are blocked for all cores and the HW blocks, then those
+ * ways will never have any cache lines evicted from them. All cores
+ * and the hardware blocks are free to read from all ways regardless
+ * of the partitioning.
+ */
+int cvmx_l2c_set_core_way_partition(uint32_t core, uint32_t mask);
+
+/**
+ * Return the L2 Cache way partitioning for the hw blocks.
+ *
+ * Returns The mask specifying the reserved way. 0 bits in mask indicates
+ * the cache 'ways' that a core can evict from.
+ * -1 on error
+ */
+int cvmx_l2c_get_hw_way_partition(void);
+
+/**
+ * Partitions the L2 cache for the hardware blocks.
+ *
+ * @mask: The partitioning of the ways expressed as a binary mask. A 0
+ * bit allows the core to evict cache lines from a way, while a
+ * 1 bit blocks the core from evicting any lines from that
+ * way. There must be at least one allowed way (0 bit) in the
+ * mask.
+ *
+ * If any ways are blocked for all cores and the HW blocks, then those
+ * ways will never have any cache lines evicted from them. All cores
+ * and the hardware blocks are free to read from all ways regardless
+ * of the partitioning.
+ */
+int cvmx_l2c_set_hw_way_partition(uint32_t mask);
+
+/**
+ * Locks a line in the L2 cache at the specified physical address
+ *
+ * @addr: physical address of line to lock
+ *
+ * Returns 0 on success,
+ * 1 if line not locked.
+ */
+int cvmx_l2c_lock_line(uint64_t addr);
+
+/**
+ * Locks a specified memory region in the L2 cache.
+ *
+ * Note that if not all lines can be locked, that means that all
+ * but one of the ways (associations) available to the locking
+ * core are locked. Having only 1 association available for
+ * normal caching may have a significant adverse affect on performance.
+ * Care should be taken to ensure that enough of the L2 cache is left
+ * unlocked to allow for normal caching of DRAM.
+ *
+ * @start: Physical address of the start of the region to lock
+ * @len: Length (in bytes) of region to lock
+ *
+ * Returns Number of requested lines that where not locked.
+ * 0 on success (all locked)
+ */
+int cvmx_l2c_lock_mem_region(uint64_t start, uint64_t len);
+
+/**
+ * Unlock and flush a cache line from the L2 cache.
+ * IMPORTANT: Must only be run by one core at a time due to use
+ * of L2C debug features.
+ * Note that this function will flush a matching but unlocked cache line.
+ * (If address is not in L2, no lines are flushed.)
+ *
+ * @address: Physical address to unlock
+ *
+ * Returns 0: line not unlocked
+ * 1: line unlocked
+ */
+int cvmx_l2c_unlock_line(uint64_t address);
+
+/**
+ * Unlocks a region of memory that is locked in the L2 cache
+ *
+ * @start: start physical address
+ * @len: length (in bytes) to unlock
+ *
+ * Returns Number of locked lines that the call unlocked
+ */
+int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len);
+
+/**
+ * Read the L2 controller tag for a given location in L2
+ *
+ * @association:
+ * Which association to read line from
+ * @index: Which way to read from.
+ *
+ * Returns l2c tag structure for line requested.
+ */
+union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index);
+
+/* Wrapper around deprecated old function name */
+static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association,
+ uint32_t index)
+{
+ return cvmx_l2c_get_tag(association, index);
+}
+
+/**
+ * Returns the cache index for a given physical address
+ *
+ * @addr: physical address
+ *
+ * Returns L2 cache index
+ */
+uint32_t cvmx_l2c_address_to_index(uint64_t addr);
+
+/**
+ * Flushes (and unlocks) the entire L2 cache.
+ * IMPORTANT: Must only be run by one core at a time due to use
+ * of L2C debug features.
+ */
+void cvmx_l2c_flush(void);
+
+/**
+ *
+ * Returns Returns the size of the L2 cache in bytes,
+ * -1 on error (unrecognized model)
+ */
+int cvmx_l2c_get_cache_size_bytes(void);
+
+/**
+ * Return the number of sets in the L2 Cache
+ *
+ * Returns
+ */
+int cvmx_l2c_get_num_sets(void);
+
+/**
+ * Return log base 2 of the number of sets in the L2 cache
+ * Returns
+ */
+int cvmx_l2c_get_set_bits(void);
+/**
+ * Return the number of associations in the L2 Cache
+ *
+ * Returns
+ */
+int cvmx_l2c_get_num_assoc(void);
+
+/**
+ * Flush a line from the L2 cache
+ * This should only be called from one core at a time, as this routine
+ * sets the core to the 'debug' core in order to flush the line.
+ *
+ * @assoc: Association (or way) to flush
+ * @index: Index to flush
+ */
+void cvmx_l2c_flush_line(uint32_t assoc, uint32_t index);
+
+#endif /* __CVMX_L2C_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-l2d-defs.h b/arch/mips/include/asm/octeon/cvmx-l2d-defs.h
new file mode 100644
index 000000000000..d7102d455e1b
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-l2d-defs.h
@@ -0,0 +1,369 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_L2D_DEFS_H__
+#define __CVMX_L2D_DEFS_H__
+
+#define CVMX_L2D_BST0 \
+ CVMX_ADD_IO_SEG(0x0001180080000780ull)
+#define CVMX_L2D_BST1 \
+ CVMX_ADD_IO_SEG(0x0001180080000788ull)
+#define CVMX_L2D_BST2 \
+ CVMX_ADD_IO_SEG(0x0001180080000790ull)
+#define CVMX_L2D_BST3 \
+ CVMX_ADD_IO_SEG(0x0001180080000798ull)
+#define CVMX_L2D_ERR \
+ CVMX_ADD_IO_SEG(0x0001180080000010ull)
+#define CVMX_L2D_FADR \
+ CVMX_ADD_IO_SEG(0x0001180080000018ull)
+#define CVMX_L2D_FSYN0 \
+ CVMX_ADD_IO_SEG(0x0001180080000020ull)
+#define CVMX_L2D_FSYN1 \
+ CVMX_ADD_IO_SEG(0x0001180080000028ull)
+#define CVMX_L2D_FUS0 \
+ CVMX_ADD_IO_SEG(0x00011800800007A0ull)
+#define CVMX_L2D_FUS1 \
+ CVMX_ADD_IO_SEG(0x00011800800007A8ull)
+#define CVMX_L2D_FUS2 \
+ CVMX_ADD_IO_SEG(0x00011800800007B0ull)
+#define CVMX_L2D_FUS3 \
+ CVMX_ADD_IO_SEG(0x00011800800007B8ull)
+
+union cvmx_l2d_bst0 {
+ uint64_t u64;
+ struct cvmx_l2d_bst0_s {
+ uint64_t reserved_35_63:29;
+ uint64_t ftl:1;
+ uint64_t q0stat:34;
+ } s;
+ struct cvmx_l2d_bst0_s cn30xx;
+ struct cvmx_l2d_bst0_s cn31xx;
+ struct cvmx_l2d_bst0_s cn38xx;
+ struct cvmx_l2d_bst0_s cn38xxp2;
+ struct cvmx_l2d_bst0_s cn50xx;
+ struct cvmx_l2d_bst0_s cn52xx;
+ struct cvmx_l2d_bst0_s cn52xxp1;
+ struct cvmx_l2d_bst0_s cn56xx;
+ struct cvmx_l2d_bst0_s cn56xxp1;
+ struct cvmx_l2d_bst0_s cn58xx;
+ struct cvmx_l2d_bst0_s cn58xxp1;
+};
+
+union cvmx_l2d_bst1 {
+ uint64_t u64;
+ struct cvmx_l2d_bst1_s {
+ uint64_t reserved_34_63:30;
+ uint64_t q1stat:34;
+ } s;
+ struct cvmx_l2d_bst1_s cn30xx;
+ struct cvmx_l2d_bst1_s cn31xx;
+ struct cvmx_l2d_bst1_s cn38xx;
+ struct cvmx_l2d_bst1_s cn38xxp2;
+ struct cvmx_l2d_bst1_s cn50xx;
+ struct cvmx_l2d_bst1_s cn52xx;
+ struct cvmx_l2d_bst1_s cn52xxp1;
+ struct cvmx_l2d_bst1_s cn56xx;
+ struct cvmx_l2d_bst1_s cn56xxp1;
+ struct cvmx_l2d_bst1_s cn58xx;
+ struct cvmx_l2d_bst1_s cn58xxp1;
+};
+
+union cvmx_l2d_bst2 {
+ uint64_t u64;
+ struct cvmx_l2d_bst2_s {
+ uint64_t reserved_34_63:30;
+ uint64_t q2stat:34;
+ } s;
+ struct cvmx_l2d_bst2_s cn30xx;
+ struct cvmx_l2d_bst2_s cn31xx;
+ struct cvmx_l2d_bst2_s cn38xx;
+ struct cvmx_l2d_bst2_s cn38xxp2;
+ struct cvmx_l2d_bst2_s cn50xx;
+ struct cvmx_l2d_bst2_s cn52xx;
+ struct cvmx_l2d_bst2_s cn52xxp1;
+ struct cvmx_l2d_bst2_s cn56xx;
+ struct cvmx_l2d_bst2_s cn56xxp1;
+ struct cvmx_l2d_bst2_s cn58xx;
+ struct cvmx_l2d_bst2_s cn58xxp1;
+};
+
+union cvmx_l2d_bst3 {
+ uint64_t u64;
+ struct cvmx_l2d_bst3_s {
+ uint64_t reserved_34_63:30;
+ uint64_t q3stat:34;
+ } s;
+ struct cvmx_l2d_bst3_s cn30xx;
+ struct cvmx_l2d_bst3_s cn31xx;
+ struct cvmx_l2d_bst3_s cn38xx;
+ struct cvmx_l2d_bst3_s cn38xxp2;
+ struct cvmx_l2d_bst3_s cn50xx;
+ struct cvmx_l2d_bst3_s cn52xx;
+ struct cvmx_l2d_bst3_s cn52xxp1;
+ struct cvmx_l2d_bst3_s cn56xx;
+ struct cvmx_l2d_bst3_s cn56xxp1;
+ struct cvmx_l2d_bst3_s cn58xx;
+ struct cvmx_l2d_bst3_s cn58xxp1;
+};
+
+union cvmx_l2d_err {
+ uint64_t u64;
+ struct cvmx_l2d_err_s {
+ uint64_t reserved_6_63:58;
+ uint64_t bmhclsel:1;
+ uint64_t ded_err:1;
+ uint64_t sec_err:1;
+ uint64_t ded_intena:1;
+ uint64_t sec_intena:1;
+ uint64_t ecc_ena:1;
+ } s;
+ struct cvmx_l2d_err_s cn30xx;
+ struct cvmx_l2d_err_s cn31xx;
+ struct cvmx_l2d_err_s cn38xx;
+ struct cvmx_l2d_err_s cn38xxp2;
+ struct cvmx_l2d_err_s cn50xx;
+ struct cvmx_l2d_err_s cn52xx;
+ struct cvmx_l2d_err_s cn52xxp1;
+ struct cvmx_l2d_err_s cn56xx;
+ struct cvmx_l2d_err_s cn56xxp1;
+ struct cvmx_l2d_err_s cn58xx;
+ struct cvmx_l2d_err_s cn58xxp1;
+};
+
+union cvmx_l2d_fadr {
+ uint64_t u64;
+ struct cvmx_l2d_fadr_s {
+ uint64_t reserved_19_63:45;
+ uint64_t fadru:1;
+ uint64_t fowmsk:4;
+ uint64_t fset:3;
+ uint64_t fadr:11;
+ } s;
+ struct cvmx_l2d_fadr_cn30xx {
+ uint64_t reserved_18_63:46;
+ uint64_t fowmsk:4;
+ uint64_t reserved_13_13:1;
+ uint64_t fset:2;
+ uint64_t reserved_9_10:2;
+ uint64_t fadr:9;
+ } cn30xx;
+ struct cvmx_l2d_fadr_cn31xx {
+ uint64_t reserved_18_63:46;
+ uint64_t fowmsk:4;
+ uint64_t reserved_13_13:1;
+ uint64_t fset:2;
+ uint64_t reserved_10_10:1;
+ uint64_t fadr:10;
+ } cn31xx;
+ struct cvmx_l2d_fadr_cn38xx {
+ uint64_t reserved_18_63:46;
+ uint64_t fowmsk:4;
+ uint64_t fset:3;
+ uint64_t fadr:11;
+ } cn38xx;
+ struct cvmx_l2d_fadr_cn38xx cn38xxp2;
+ struct cvmx_l2d_fadr_cn50xx {
+ uint64_t reserved_18_63:46;
+ uint64_t fowmsk:4;
+ uint64_t fset:3;
+ uint64_t reserved_8_10:3;
+ uint64_t fadr:8;
+ } cn50xx;
+ struct cvmx_l2d_fadr_cn52xx {
+ uint64_t reserved_18_63:46;
+ uint64_t fowmsk:4;
+ uint64_t fset:3;
+ uint64_t reserved_10_10:1;
+ uint64_t fadr:10;
+ } cn52xx;
+ struct cvmx_l2d_fadr_cn52xx cn52xxp1;
+ struct cvmx_l2d_fadr_s cn56xx;
+ struct cvmx_l2d_fadr_s cn56xxp1;
+ struct cvmx_l2d_fadr_s cn58xx;
+ struct cvmx_l2d_fadr_s cn58xxp1;
+};
+
+union cvmx_l2d_fsyn0 {
+ uint64_t u64;
+ struct cvmx_l2d_fsyn0_s {
+ uint64_t reserved_20_63:44;
+ uint64_t fsyn_ow1:10;
+ uint64_t fsyn_ow0:10;
+ } s;
+ struct cvmx_l2d_fsyn0_s cn30xx;
+ struct cvmx_l2d_fsyn0_s cn31xx;
+ struct cvmx_l2d_fsyn0_s cn38xx;
+ struct cvmx_l2d_fsyn0_s cn38xxp2;
+ struct cvmx_l2d_fsyn0_s cn50xx;
+ struct cvmx_l2d_fsyn0_s cn52xx;
+ struct cvmx_l2d_fsyn0_s cn52xxp1;
+ struct cvmx_l2d_fsyn0_s cn56xx;
+ struct cvmx_l2d_fsyn0_s cn56xxp1;
+ struct cvmx_l2d_fsyn0_s cn58xx;
+ struct cvmx_l2d_fsyn0_s cn58xxp1;
+};
+
+union cvmx_l2d_fsyn1 {
+ uint64_t u64;
+ struct cvmx_l2d_fsyn1_s {
+ uint64_t reserved_20_63:44;
+ uint64_t fsyn_ow3:10;
+ uint64_t fsyn_ow2:10;
+ } s;
+ struct cvmx_l2d_fsyn1_s cn30xx;
+ struct cvmx_l2d_fsyn1_s cn31xx;
+ struct cvmx_l2d_fsyn1_s cn38xx;
+ struct cvmx_l2d_fsyn1_s cn38xxp2;
+ struct cvmx_l2d_fsyn1_s cn50xx;
+ struct cvmx_l2d_fsyn1_s cn52xx;
+ struct cvmx_l2d_fsyn1_s cn52xxp1;
+ struct cvmx_l2d_fsyn1_s cn56xx;
+ struct cvmx_l2d_fsyn1_s cn56xxp1;
+ struct cvmx_l2d_fsyn1_s cn58xx;
+ struct cvmx_l2d_fsyn1_s cn58xxp1;
+};
+
+union cvmx_l2d_fus0 {
+ uint64_t u64;
+ struct cvmx_l2d_fus0_s {
+ uint64_t reserved_34_63:30;
+ uint64_t q0fus:34;
+ } s;
+ struct cvmx_l2d_fus0_s cn30xx;
+ struct cvmx_l2d_fus0_s cn31xx;
+ struct cvmx_l2d_fus0_s cn38xx;
+ struct cvmx_l2d_fus0_s cn38xxp2;
+ struct cvmx_l2d_fus0_s cn50xx;
+ struct cvmx_l2d_fus0_s cn52xx;
+ struct cvmx_l2d_fus0_s cn52xxp1;
+ struct cvmx_l2d_fus0_s cn56xx;
+ struct cvmx_l2d_fus0_s cn56xxp1;
+ struct cvmx_l2d_fus0_s cn58xx;
+ struct cvmx_l2d_fus0_s cn58xxp1;
+};
+
+union cvmx_l2d_fus1 {
+ uint64_t u64;
+ struct cvmx_l2d_fus1_s {
+ uint64_t reserved_34_63:30;
+ uint64_t q1fus:34;
+ } s;
+ struct cvmx_l2d_fus1_s cn30xx;
+ struct cvmx_l2d_fus1_s cn31xx;
+ struct cvmx_l2d_fus1_s cn38xx;
+ struct cvmx_l2d_fus1_s cn38xxp2;
+ struct cvmx_l2d_fus1_s cn50xx;
+ struct cvmx_l2d_fus1_s cn52xx;
+ struct cvmx_l2d_fus1_s cn52xxp1;
+ struct cvmx_l2d_fus1_s cn56xx;
+ struct cvmx_l2d_fus1_s cn56xxp1;
+ struct cvmx_l2d_fus1_s cn58xx;
+ struct cvmx_l2d_fus1_s cn58xxp1;
+};
+
+union cvmx_l2d_fus2 {
+ uint64_t u64;
+ struct cvmx_l2d_fus2_s {
+ uint64_t reserved_34_63:30;
+ uint64_t q2fus:34;
+ } s;
+ struct cvmx_l2d_fus2_s cn30xx;
+ struct cvmx_l2d_fus2_s cn31xx;
+ struct cvmx_l2d_fus2_s cn38xx;
+ struct cvmx_l2d_fus2_s cn38xxp2;
+ struct cvmx_l2d_fus2_s cn50xx;
+ struct cvmx_l2d_fus2_s cn52xx;
+ struct cvmx_l2d_fus2_s cn52xxp1;
+ struct cvmx_l2d_fus2_s cn56xx;
+ struct cvmx_l2d_fus2_s cn56xxp1;
+ struct cvmx_l2d_fus2_s cn58xx;
+ struct cvmx_l2d_fus2_s cn58xxp1;
+};
+
+union cvmx_l2d_fus3 {
+ uint64_t u64;
+ struct cvmx_l2d_fus3_s {
+ uint64_t reserved_40_63:24;
+ uint64_t ema_ctl:3;
+ uint64_t reserved_34_36:3;
+ uint64_t q3fus:34;
+ } s;
+ struct cvmx_l2d_fus3_cn30xx {
+ uint64_t reserved_35_63:29;
+ uint64_t crip_64k:1;
+ uint64_t q3fus:34;
+ } cn30xx;
+ struct cvmx_l2d_fus3_cn31xx {
+ uint64_t reserved_35_63:29;
+ uint64_t crip_128k:1;
+ uint64_t q3fus:34;
+ } cn31xx;
+ struct cvmx_l2d_fus3_cn38xx {
+ uint64_t reserved_36_63:28;
+ uint64_t crip_256k:1;
+ uint64_t crip_512k:1;
+ uint64_t q3fus:34;
+ } cn38xx;
+ struct cvmx_l2d_fus3_cn38xx cn38xxp2;
+ struct cvmx_l2d_fus3_cn50xx {
+ uint64_t reserved_40_63:24;
+ uint64_t ema_ctl:3;
+ uint64_t reserved_36_36:1;
+ uint64_t crip_32k:1;
+ uint64_t crip_64k:1;
+ uint64_t q3fus:34;
+ } cn50xx;
+ struct cvmx_l2d_fus3_cn52xx {
+ uint64_t reserved_40_63:24;
+ uint64_t ema_ctl:3;
+ uint64_t reserved_36_36:1;
+ uint64_t crip_128k:1;
+ uint64_t crip_256k:1;
+ uint64_t q3fus:34;
+ } cn52xx;
+ struct cvmx_l2d_fus3_cn52xx cn52xxp1;
+ struct cvmx_l2d_fus3_cn56xx {
+ uint64_t reserved_40_63:24;
+ uint64_t ema_ctl:3;
+ uint64_t reserved_36_36:1;
+ uint64_t crip_512k:1;
+ uint64_t crip_1024k:1;
+ uint64_t q3fus:34;
+ } cn56xx;
+ struct cvmx_l2d_fus3_cn56xx cn56xxp1;
+ struct cvmx_l2d_fus3_cn58xx {
+ uint64_t reserved_39_63:25;
+ uint64_t ema_ctl:2;
+ uint64_t reserved_36_36:1;
+ uint64_t crip_512k:1;
+ uint64_t crip_1024k:1;
+ uint64_t q3fus:34;
+ } cn58xx;
+ struct cvmx_l2d_fus3_cn58xx cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-l2t-defs.h b/arch/mips/include/asm/octeon/cvmx-l2t-defs.h
new file mode 100644
index 000000000000..2639a3f5ffc2
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-l2t-defs.h
@@ -0,0 +1,141 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_L2T_DEFS_H__
+#define __CVMX_L2T_DEFS_H__
+
+#define CVMX_L2T_ERR \
+ CVMX_ADD_IO_SEG(0x0001180080000008ull)
+
+union cvmx_l2t_err {
+ uint64_t u64;
+ struct cvmx_l2t_err_s {
+ uint64_t reserved_29_63:35;
+ uint64_t fadru:1;
+ uint64_t lck_intena2:1;
+ uint64_t lckerr2:1;
+ uint64_t lck_intena:1;
+ uint64_t lckerr:1;
+ uint64_t fset:3;
+ uint64_t fadr:10;
+ uint64_t fsyn:6;
+ uint64_t ded_err:1;
+ uint64_t sec_err:1;
+ uint64_t ded_intena:1;
+ uint64_t sec_intena:1;
+ uint64_t ecc_ena:1;
+ } s;
+ struct cvmx_l2t_err_cn30xx {
+ uint64_t reserved_28_63:36;
+ uint64_t lck_intena2:1;
+ uint64_t lckerr2:1;
+ uint64_t lck_intena:1;
+ uint64_t lckerr:1;
+ uint64_t reserved_23_23:1;
+ uint64_t fset:2;
+ uint64_t reserved_19_20:2;
+ uint64_t fadr:8;
+ uint64_t fsyn:6;
+ uint64_t ded_err:1;
+ uint64_t sec_err:1;
+ uint64_t ded_intena:1;
+ uint64_t sec_intena:1;
+ uint64_t ecc_ena:1;
+ } cn30xx;
+ struct cvmx_l2t_err_cn31xx {
+ uint64_t reserved_28_63:36;
+ uint64_t lck_intena2:1;
+ uint64_t lckerr2:1;
+ uint64_t lck_intena:1;
+ uint64_t lckerr:1;
+ uint64_t reserved_23_23:1;
+ uint64_t fset:2;
+ uint64_t reserved_20_20:1;
+ uint64_t fadr:9;
+ uint64_t fsyn:6;
+ uint64_t ded_err:1;
+ uint64_t sec_err:1;
+ uint64_t ded_intena:1;
+ uint64_t sec_intena:1;
+ uint64_t ecc_ena:1;
+ } cn31xx;
+ struct cvmx_l2t_err_cn38xx {
+ uint64_t reserved_28_63:36;
+ uint64_t lck_intena2:1;
+ uint64_t lckerr2:1;
+ uint64_t lck_intena:1;
+ uint64_t lckerr:1;
+ uint64_t fset:3;
+ uint64_t fadr:10;
+ uint64_t fsyn:6;
+ uint64_t ded_err:1;
+ uint64_t sec_err:1;
+ uint64_t ded_intena:1;
+ uint64_t sec_intena:1;
+ uint64_t ecc_ena:1;
+ } cn38xx;
+ struct cvmx_l2t_err_cn38xx cn38xxp2;
+ struct cvmx_l2t_err_cn50xx {
+ uint64_t reserved_28_63:36;
+ uint64_t lck_intena2:1;
+ uint64_t lckerr2:1;
+ uint64_t lck_intena:1;
+ uint64_t lckerr:1;
+ uint64_t fset:3;
+ uint64_t reserved_18_20:3;
+ uint64_t fadr:7;
+ uint64_t fsyn:6;
+ uint64_t ded_err:1;
+ uint64_t sec_err:1;
+ uint64_t ded_intena:1;
+ uint64_t sec_intena:1;
+ uint64_t ecc_ena:1;
+ } cn50xx;
+ struct cvmx_l2t_err_cn52xx {
+ uint64_t reserved_28_63:36;
+ uint64_t lck_intena2:1;
+ uint64_t lckerr2:1;
+ uint64_t lck_intena:1;
+ uint64_t lckerr:1;
+ uint64_t fset:3;
+ uint64_t reserved_20_20:1;
+ uint64_t fadr:9;
+ uint64_t fsyn:6;
+ uint64_t ded_err:1;
+ uint64_t sec_err:1;
+ uint64_t ded_intena:1;
+ uint64_t sec_intena:1;
+ uint64_t ecc_ena:1;
+ } cn52xx;
+ struct cvmx_l2t_err_cn52xx cn52xxp1;
+ struct cvmx_l2t_err_s cn56xx;
+ struct cvmx_l2t_err_s cn56xxp1;
+ struct cvmx_l2t_err_s cn58xx;
+ struct cvmx_l2t_err_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-led-defs.h b/arch/mips/include/asm/octeon/cvmx-led-defs.h
new file mode 100644
index 000000000000..16f174a4dadf
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-led-defs.h
@@ -0,0 +1,240 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_LED_DEFS_H__
+#define __CVMX_LED_DEFS_H__
+
+#define CVMX_LED_BLINK \
+ CVMX_ADD_IO_SEG(0x0001180000001A48ull)
+#define CVMX_LED_CLK_PHASE \
+ CVMX_ADD_IO_SEG(0x0001180000001A08ull)
+#define CVMX_LED_CYLON \
+ CVMX_ADD_IO_SEG(0x0001180000001AF8ull)
+#define CVMX_LED_DBG \
+ CVMX_ADD_IO_SEG(0x0001180000001A18ull)
+#define CVMX_LED_EN \
+ CVMX_ADD_IO_SEG(0x0001180000001A00ull)
+#define CVMX_LED_POLARITY \
+ CVMX_ADD_IO_SEG(0x0001180000001A50ull)
+#define CVMX_LED_PRT \
+ CVMX_ADD_IO_SEG(0x0001180000001A10ull)
+#define CVMX_LED_PRT_FMT \
+ CVMX_ADD_IO_SEG(0x0001180000001A30ull)
+#define CVMX_LED_PRT_STATUSX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001A80ull + (((offset) & 7) * 8))
+#define CVMX_LED_UDD_CNTX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001A20ull + (((offset) & 1) * 8))
+#define CVMX_LED_UDD_DATX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001A38ull + (((offset) & 1) * 8))
+#define CVMX_LED_UDD_DAT_CLRX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001AC8ull + (((offset) & 1) * 16))
+#define CVMX_LED_UDD_DAT_SETX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001AC0ull + (((offset) & 1) * 16))
+
+union cvmx_led_blink {
+ uint64_t u64;
+ struct cvmx_led_blink_s {
+ uint64_t reserved_8_63:56;
+ uint64_t rate:8;
+ } s;
+ struct cvmx_led_blink_s cn38xx;
+ struct cvmx_led_blink_s cn38xxp2;
+ struct cvmx_led_blink_s cn56xx;
+ struct cvmx_led_blink_s cn56xxp1;
+ struct cvmx_led_blink_s cn58xx;
+ struct cvmx_led_blink_s cn58xxp1;
+};
+
+union cvmx_led_clk_phase {
+ uint64_t u64;
+ struct cvmx_led_clk_phase_s {
+ uint64_t reserved_7_63:57;
+ uint64_t phase:7;
+ } s;
+ struct cvmx_led_clk_phase_s cn38xx;
+ struct cvmx_led_clk_phase_s cn38xxp2;
+ struct cvmx_led_clk_phase_s cn56xx;
+ struct cvmx_led_clk_phase_s cn56xxp1;
+ struct cvmx_led_clk_phase_s cn58xx;
+ struct cvmx_led_clk_phase_s cn58xxp1;
+};
+
+union cvmx_led_cylon {
+ uint64_t u64;
+ struct cvmx_led_cylon_s {
+ uint64_t reserved_16_63:48;
+ uint64_t rate:16;
+ } s;
+ struct cvmx_led_cylon_s cn38xx;
+ struct cvmx_led_cylon_s cn38xxp2;
+ struct cvmx_led_cylon_s cn56xx;
+ struct cvmx_led_cylon_s cn56xxp1;
+ struct cvmx_led_cylon_s cn58xx;
+ struct cvmx_led_cylon_s cn58xxp1;
+};
+
+union cvmx_led_dbg {
+ uint64_t u64;
+ struct cvmx_led_dbg_s {
+ uint64_t reserved_1_63:63;
+ uint64_t dbg_en:1;
+ } s;
+ struct cvmx_led_dbg_s cn38xx;
+ struct cvmx_led_dbg_s cn38xxp2;
+ struct cvmx_led_dbg_s cn56xx;
+ struct cvmx_led_dbg_s cn56xxp1;
+ struct cvmx_led_dbg_s cn58xx;
+ struct cvmx_led_dbg_s cn58xxp1;
+};
+
+union cvmx_led_en {
+ uint64_t u64;
+ struct cvmx_led_en_s {
+ uint64_t reserved_1_63:63;
+ uint64_t en:1;
+ } s;
+ struct cvmx_led_en_s cn38xx;
+ struct cvmx_led_en_s cn38xxp2;
+ struct cvmx_led_en_s cn56xx;
+ struct cvmx_led_en_s cn56xxp1;
+ struct cvmx_led_en_s cn58xx;
+ struct cvmx_led_en_s cn58xxp1;
+};
+
+union cvmx_led_polarity {
+ uint64_t u64;
+ struct cvmx_led_polarity_s {
+ uint64_t reserved_1_63:63;
+ uint64_t polarity:1;
+ } s;
+ struct cvmx_led_polarity_s cn38xx;
+ struct cvmx_led_polarity_s cn38xxp2;
+ struct cvmx_led_polarity_s cn56xx;
+ struct cvmx_led_polarity_s cn56xxp1;
+ struct cvmx_led_polarity_s cn58xx;
+ struct cvmx_led_polarity_s cn58xxp1;
+};
+
+union cvmx_led_prt {
+ uint64_t u64;
+ struct cvmx_led_prt_s {
+ uint64_t reserved_8_63:56;
+ uint64_t prt_en:8;
+ } s;
+ struct cvmx_led_prt_s cn38xx;
+ struct cvmx_led_prt_s cn38xxp2;
+ struct cvmx_led_prt_s cn56xx;
+ struct cvmx_led_prt_s cn56xxp1;
+ struct cvmx_led_prt_s cn58xx;
+ struct cvmx_led_prt_s cn58xxp1;
+};
+
+union cvmx_led_prt_fmt {
+ uint64_t u64;
+ struct cvmx_led_prt_fmt_s {
+ uint64_t reserved_4_63:60;
+ uint64_t format:4;
+ } s;
+ struct cvmx_led_prt_fmt_s cn38xx;
+ struct cvmx_led_prt_fmt_s cn38xxp2;
+ struct cvmx_led_prt_fmt_s cn56xx;
+ struct cvmx_led_prt_fmt_s cn56xxp1;
+ struct cvmx_led_prt_fmt_s cn58xx;
+ struct cvmx_led_prt_fmt_s cn58xxp1;
+};
+
+union cvmx_led_prt_statusx {
+ uint64_t u64;
+ struct cvmx_led_prt_statusx_s {
+ uint64_t reserved_6_63:58;
+ uint64_t status:6;
+ } s;
+ struct cvmx_led_prt_statusx_s cn38xx;
+ struct cvmx_led_prt_statusx_s cn38xxp2;
+ struct cvmx_led_prt_statusx_s cn56xx;
+ struct cvmx_led_prt_statusx_s cn56xxp1;
+ struct cvmx_led_prt_statusx_s cn58xx;
+ struct cvmx_led_prt_statusx_s cn58xxp1;
+};
+
+union cvmx_led_udd_cntx {
+ uint64_t u64;
+ struct cvmx_led_udd_cntx_s {
+ uint64_t reserved_6_63:58;
+ uint64_t cnt:6;
+ } s;
+ struct cvmx_led_udd_cntx_s cn38xx;
+ struct cvmx_led_udd_cntx_s cn38xxp2;
+ struct cvmx_led_udd_cntx_s cn56xx;
+ struct cvmx_led_udd_cntx_s cn56xxp1;
+ struct cvmx_led_udd_cntx_s cn58xx;
+ struct cvmx_led_udd_cntx_s cn58xxp1;
+};
+
+union cvmx_led_udd_datx {
+ uint64_t u64;
+ struct cvmx_led_udd_datx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t dat:32;
+ } s;
+ struct cvmx_led_udd_datx_s cn38xx;
+ struct cvmx_led_udd_datx_s cn38xxp2;
+ struct cvmx_led_udd_datx_s cn56xx;
+ struct cvmx_led_udd_datx_s cn56xxp1;
+ struct cvmx_led_udd_datx_s cn58xx;
+ struct cvmx_led_udd_datx_s cn58xxp1;
+};
+
+union cvmx_led_udd_dat_clrx {
+ uint64_t u64;
+ struct cvmx_led_udd_dat_clrx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t clr:32;
+ } s;
+ struct cvmx_led_udd_dat_clrx_s cn38xx;
+ struct cvmx_led_udd_dat_clrx_s cn38xxp2;
+ struct cvmx_led_udd_dat_clrx_s cn56xx;
+ struct cvmx_led_udd_dat_clrx_s cn56xxp1;
+ struct cvmx_led_udd_dat_clrx_s cn58xx;
+ struct cvmx_led_udd_dat_clrx_s cn58xxp1;
+};
+
+union cvmx_led_udd_dat_setx {
+ uint64_t u64;
+ struct cvmx_led_udd_dat_setx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t set:32;
+ } s;
+ struct cvmx_led_udd_dat_setx_s cn38xx;
+ struct cvmx_led_udd_dat_setx_s cn38xxp2;
+ struct cvmx_led_udd_dat_setx_s cn56xx;
+ struct cvmx_led_udd_dat_setx_s cn56xxp1;
+ struct cvmx_led_udd_dat_setx_s cn58xx;
+ struct cvmx_led_udd_dat_setx_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-mio-defs.h b/arch/mips/include/asm/octeon/cvmx-mio-defs.h
new file mode 100644
index 000000000000..6555f0530988
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-mio-defs.h
@@ -0,0 +1,2004 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_MIO_DEFS_H__
+#define __CVMX_MIO_DEFS_H__
+
+#define CVMX_MIO_BOOT_BIST_STAT \
+ CVMX_ADD_IO_SEG(0x00011800000000F8ull)
+#define CVMX_MIO_BOOT_COMP \
+ CVMX_ADD_IO_SEG(0x00011800000000B8ull)
+#define CVMX_MIO_BOOT_DMA_CFGX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000100ull + (((offset) & 3) * 8))
+#define CVMX_MIO_BOOT_DMA_INTX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000138ull + (((offset) & 3) * 8))
+#define CVMX_MIO_BOOT_DMA_INT_ENX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000150ull + (((offset) & 3) * 8))
+#define CVMX_MIO_BOOT_DMA_TIMX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000120ull + (((offset) & 3) * 8))
+#define CVMX_MIO_BOOT_ERR \
+ CVMX_ADD_IO_SEG(0x00011800000000A0ull)
+#define CVMX_MIO_BOOT_INT \
+ CVMX_ADD_IO_SEG(0x00011800000000A8ull)
+#define CVMX_MIO_BOOT_LOC_ADR \
+ CVMX_ADD_IO_SEG(0x0001180000000090ull)
+#define CVMX_MIO_BOOT_LOC_CFGX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000080ull + (((offset) & 1) * 8))
+#define CVMX_MIO_BOOT_LOC_DAT \
+ CVMX_ADD_IO_SEG(0x0001180000000098ull)
+#define CVMX_MIO_BOOT_PIN_DEFS \
+ CVMX_ADD_IO_SEG(0x00011800000000C0ull)
+#define CVMX_MIO_BOOT_REG_CFGX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000000ull + (((offset) & 7) * 8))
+#define CVMX_MIO_BOOT_REG_TIMX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000040ull + (((offset) & 7) * 8))
+#define CVMX_MIO_BOOT_THR \
+ CVMX_ADD_IO_SEG(0x00011800000000B0ull)
+#define CVMX_MIO_FUS_BNK_DATX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001520ull + (((offset) & 3) * 8))
+#define CVMX_MIO_FUS_DAT0 \
+ CVMX_ADD_IO_SEG(0x0001180000001400ull)
+#define CVMX_MIO_FUS_DAT1 \
+ CVMX_ADD_IO_SEG(0x0001180000001408ull)
+#define CVMX_MIO_FUS_DAT2 \
+ CVMX_ADD_IO_SEG(0x0001180000001410ull)
+#define CVMX_MIO_FUS_DAT3 \
+ CVMX_ADD_IO_SEG(0x0001180000001418ull)
+#define CVMX_MIO_FUS_EMA \
+ CVMX_ADD_IO_SEG(0x0001180000001550ull)
+#define CVMX_MIO_FUS_PDF \
+ CVMX_ADD_IO_SEG(0x0001180000001420ull)
+#define CVMX_MIO_FUS_PLL \
+ CVMX_ADD_IO_SEG(0x0001180000001580ull)
+#define CVMX_MIO_FUS_PROG \
+ CVMX_ADD_IO_SEG(0x0001180000001510ull)
+#define CVMX_MIO_FUS_PROG_TIMES \
+ CVMX_ADD_IO_SEG(0x0001180000001518ull)
+#define CVMX_MIO_FUS_RCMD \
+ CVMX_ADD_IO_SEG(0x0001180000001500ull)
+#define CVMX_MIO_FUS_SPR_REPAIR_RES \
+ CVMX_ADD_IO_SEG(0x0001180000001548ull)
+#define CVMX_MIO_FUS_SPR_REPAIR_SUM \
+ CVMX_ADD_IO_SEG(0x0001180000001540ull)
+#define CVMX_MIO_FUS_UNLOCK \
+ CVMX_ADD_IO_SEG(0x0001180000001578ull)
+#define CVMX_MIO_FUS_WADR \
+ CVMX_ADD_IO_SEG(0x0001180000001508ull)
+#define CVMX_MIO_NDF_DMA_CFG \
+ CVMX_ADD_IO_SEG(0x0001180000000168ull)
+#define CVMX_MIO_NDF_DMA_INT \
+ CVMX_ADD_IO_SEG(0x0001180000000170ull)
+#define CVMX_MIO_NDF_DMA_INT_EN \
+ CVMX_ADD_IO_SEG(0x0001180000000178ull)
+#define CVMX_MIO_PLL_CTL \
+ CVMX_ADD_IO_SEG(0x0001180000001448ull)
+#define CVMX_MIO_PLL_SETTING \
+ CVMX_ADD_IO_SEG(0x0001180000001440ull)
+#define CVMX_MIO_TWSX_INT(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001010ull + (((offset) & 1) * 512))
+#define CVMX_MIO_TWSX_SW_TWSI(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001000ull + (((offset) & 1) * 512))
+#define CVMX_MIO_TWSX_SW_TWSI_EXT(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001018ull + (((offset) & 1) * 512))
+#define CVMX_MIO_TWSX_TWSI_SW(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000001008ull + (((offset) & 1) * 512))
+#define CVMX_MIO_UART2_DLH \
+ CVMX_ADD_IO_SEG(0x0001180000000488ull)
+#define CVMX_MIO_UART2_DLL \
+ CVMX_ADD_IO_SEG(0x0001180000000480ull)
+#define CVMX_MIO_UART2_FAR \
+ CVMX_ADD_IO_SEG(0x0001180000000520ull)
+#define CVMX_MIO_UART2_FCR \
+ CVMX_ADD_IO_SEG(0x0001180000000450ull)
+#define CVMX_MIO_UART2_HTX \
+ CVMX_ADD_IO_SEG(0x0001180000000708ull)
+#define CVMX_MIO_UART2_IER \
+ CVMX_ADD_IO_SEG(0x0001180000000408ull)
+#define CVMX_MIO_UART2_IIR \
+ CVMX_ADD_IO_SEG(0x0001180000000410ull)
+#define CVMX_MIO_UART2_LCR \
+ CVMX_ADD_IO_SEG(0x0001180000000418ull)
+#define CVMX_MIO_UART2_LSR \
+ CVMX_ADD_IO_SEG(0x0001180000000428ull)
+#define CVMX_MIO_UART2_MCR \
+ CVMX_ADD_IO_SEG(0x0001180000000420ull)
+#define CVMX_MIO_UART2_MSR \
+ CVMX_ADD_IO_SEG(0x0001180000000430ull)
+#define CVMX_MIO_UART2_RBR \
+ CVMX_ADD_IO_SEG(0x0001180000000400ull)
+#define CVMX_MIO_UART2_RFL \
+ CVMX_ADD_IO_SEG(0x0001180000000608ull)
+#define CVMX_MIO_UART2_RFW \
+ CVMX_ADD_IO_SEG(0x0001180000000530ull)
+#define CVMX_MIO_UART2_SBCR \
+ CVMX_ADD_IO_SEG(0x0001180000000620ull)
+#define CVMX_MIO_UART2_SCR \
+ CVMX_ADD_IO_SEG(0x0001180000000438ull)
+#define CVMX_MIO_UART2_SFE \
+ CVMX_ADD_IO_SEG(0x0001180000000630ull)
+#define CVMX_MIO_UART2_SRR \
+ CVMX_ADD_IO_SEG(0x0001180000000610ull)
+#define CVMX_MIO_UART2_SRT \
+ CVMX_ADD_IO_SEG(0x0001180000000638ull)
+#define CVMX_MIO_UART2_SRTS \
+ CVMX_ADD_IO_SEG(0x0001180000000618ull)
+#define CVMX_MIO_UART2_STT \
+ CVMX_ADD_IO_SEG(0x0001180000000700ull)
+#define CVMX_MIO_UART2_TFL \
+ CVMX_ADD_IO_SEG(0x0001180000000600ull)
+#define CVMX_MIO_UART2_TFR \
+ CVMX_ADD_IO_SEG(0x0001180000000528ull)
+#define CVMX_MIO_UART2_THR \
+ CVMX_ADD_IO_SEG(0x0001180000000440ull)
+#define CVMX_MIO_UART2_USR \
+ CVMX_ADD_IO_SEG(0x0001180000000538ull)
+#define CVMX_MIO_UARTX_DLH(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000888ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_DLL(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000880ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_FAR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000920ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_FCR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000850ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_HTX(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000B08ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_IER(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000808ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_IIR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000810ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_LCR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000818ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_LSR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000828ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_MCR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000820ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_MSR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000830ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_RBR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000800ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_RFL(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000A08ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_RFW(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000930ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_SBCR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000A20ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_SCR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000838ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_SFE(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000A30ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_SRR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000A10ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_SRT(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000A38ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_SRTS(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000A18ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_STT(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000B00ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_TFL(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000A00ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_TFR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000928ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_THR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000840ull + (((offset) & 1) * 1024))
+#define CVMX_MIO_UARTX_USR(offset) \
+ CVMX_ADD_IO_SEG(0x0001180000000938ull + (((offset) & 1) * 1024))
+
+union cvmx_mio_boot_bist_stat {
+ uint64_t u64;
+ struct cvmx_mio_boot_bist_stat_s {
+ uint64_t reserved_2_63:62;
+ uint64_t loc:1;
+ uint64_t ncbi:1;
+ } s;
+ struct cvmx_mio_boot_bist_stat_cn30xx {
+ uint64_t reserved_4_63:60;
+ uint64_t ncbo_1:1;
+ uint64_t ncbo_0:1;
+ uint64_t loc:1;
+ uint64_t ncbi:1;
+ } cn30xx;
+ struct cvmx_mio_boot_bist_stat_cn30xx cn31xx;
+ struct cvmx_mio_boot_bist_stat_cn38xx {
+ uint64_t reserved_3_63:61;
+ uint64_t ncbo_0:1;
+ uint64_t loc:1;
+ uint64_t ncbi:1;
+ } cn38xx;
+ struct cvmx_mio_boot_bist_stat_cn38xx cn38xxp2;
+ struct cvmx_mio_boot_bist_stat_cn50xx {
+ uint64_t reserved_6_63:58;
+ uint64_t pcm_1:1;
+ uint64_t pcm_0:1;
+ uint64_t ncbo_1:1;
+ uint64_t ncbo_0:1;
+ uint64_t loc:1;
+ uint64_t ncbi:1;
+ } cn50xx;
+ struct cvmx_mio_boot_bist_stat_cn52xx {
+ uint64_t reserved_6_63:58;
+ uint64_t ndf:2;
+ uint64_t ncbo_0:1;
+ uint64_t dma:1;
+ uint64_t loc:1;
+ uint64_t ncbi:1;
+ } cn52xx;
+ struct cvmx_mio_boot_bist_stat_cn52xxp1 {
+ uint64_t reserved_4_63:60;
+ uint64_t ncbo_0:1;
+ uint64_t dma:1;
+ uint64_t loc:1;
+ uint64_t ncbi:1;
+ } cn52xxp1;
+ struct cvmx_mio_boot_bist_stat_cn52xxp1 cn56xx;
+ struct cvmx_mio_boot_bist_stat_cn52xxp1 cn56xxp1;
+ struct cvmx_mio_boot_bist_stat_cn38xx cn58xx;
+ struct cvmx_mio_boot_bist_stat_cn38xx cn58xxp1;
+};
+
+union cvmx_mio_boot_comp {
+ uint64_t u64;
+ struct cvmx_mio_boot_comp_s {
+ uint64_t reserved_10_63:54;
+ uint64_t pctl:5;
+ uint64_t nctl:5;
+ } s;
+ struct cvmx_mio_boot_comp_s cn50xx;
+ struct cvmx_mio_boot_comp_s cn52xx;
+ struct cvmx_mio_boot_comp_s cn52xxp1;
+ struct cvmx_mio_boot_comp_s cn56xx;
+ struct cvmx_mio_boot_comp_s cn56xxp1;
+};
+
+union cvmx_mio_boot_dma_cfgx {
+ uint64_t u64;
+ struct cvmx_mio_boot_dma_cfgx_s {
+ uint64_t en:1;
+ uint64_t rw:1;
+ uint64_t clr:1;
+ uint64_t reserved_60_60:1;
+ uint64_t swap32:1;
+ uint64_t swap16:1;
+ uint64_t swap8:1;
+ uint64_t endian:1;
+ uint64_t size:20;
+ uint64_t adr:36;
+ } s;
+ struct cvmx_mio_boot_dma_cfgx_s cn52xx;
+ struct cvmx_mio_boot_dma_cfgx_s cn52xxp1;
+ struct cvmx_mio_boot_dma_cfgx_s cn56xx;
+ struct cvmx_mio_boot_dma_cfgx_s cn56xxp1;
+};
+
+union cvmx_mio_boot_dma_intx {
+ uint64_t u64;
+ struct cvmx_mio_boot_dma_intx_s {
+ uint64_t reserved_2_63:62;
+ uint64_t dmarq:1;
+ uint64_t done:1;
+ } s;
+ struct cvmx_mio_boot_dma_intx_s cn52xx;
+ struct cvmx_mio_boot_dma_intx_s cn52xxp1;
+ struct cvmx_mio_boot_dma_intx_s cn56xx;
+ struct cvmx_mio_boot_dma_intx_s cn56xxp1;
+};
+
+union cvmx_mio_boot_dma_int_enx {
+ uint64_t u64;
+ struct cvmx_mio_boot_dma_int_enx_s {
+ uint64_t reserved_2_63:62;
+ uint64_t dmarq:1;
+ uint64_t done:1;
+ } s;
+ struct cvmx_mio_boot_dma_int_enx_s cn52xx;
+ struct cvmx_mio_boot_dma_int_enx_s cn52xxp1;
+ struct cvmx_mio_boot_dma_int_enx_s cn56xx;
+ struct cvmx_mio_boot_dma_int_enx_s cn56xxp1;
+};
+
+union cvmx_mio_boot_dma_timx {
+ uint64_t u64;
+ struct cvmx_mio_boot_dma_timx_s {
+ uint64_t dmack_pi:1;
+ uint64_t dmarq_pi:1;
+ uint64_t tim_mult:2;
+ uint64_t rd_dly:3;
+ uint64_t ddr:1;
+ uint64_t width:1;
+ uint64_t reserved_48_54:7;
+ uint64_t pause:6;
+ uint64_t dmack_h:6;
+ uint64_t we_n:6;
+ uint64_t we_a:6;
+ uint64_t oe_n:6;
+ uint64_t oe_a:6;
+ uint64_t dmack_s:6;
+ uint64_t dmarq:6;
+ } s;
+ struct cvmx_mio_boot_dma_timx_s cn52xx;
+ struct cvmx_mio_boot_dma_timx_s cn52xxp1;
+ struct cvmx_mio_boot_dma_timx_s cn56xx;
+ struct cvmx_mio_boot_dma_timx_s cn56xxp1;
+};
+
+union cvmx_mio_boot_err {
+ uint64_t u64;
+ struct cvmx_mio_boot_err_s {
+ uint64_t reserved_2_63:62;
+ uint64_t wait_err:1;
+ uint64_t adr_err:1;
+ } s;
+ struct cvmx_mio_boot_err_s cn30xx;
+ struct cvmx_mio_boot_err_s cn31xx;
+ struct cvmx_mio_boot_err_s cn38xx;
+ struct cvmx_mio_boot_err_s cn38xxp2;
+ struct cvmx_mio_boot_err_s cn50xx;
+ struct cvmx_mio_boot_err_s cn52xx;
+ struct cvmx_mio_boot_err_s cn52xxp1;
+ struct cvmx_mio_boot_err_s cn56xx;
+ struct cvmx_mio_boot_err_s cn56xxp1;
+ struct cvmx_mio_boot_err_s cn58xx;
+ struct cvmx_mio_boot_err_s cn58xxp1;
+};
+
+union cvmx_mio_boot_int {
+ uint64_t u64;
+ struct cvmx_mio_boot_int_s {
+ uint64_t reserved_2_63:62;
+ uint64_t wait_int:1;
+ uint64_t adr_int:1;
+ } s;
+ struct cvmx_mio_boot_int_s cn30xx;
+ struct cvmx_mio_boot_int_s cn31xx;
+ struct cvmx_mio_boot_int_s cn38xx;
+ struct cvmx_mio_boot_int_s cn38xxp2;
+ struct cvmx_mio_boot_int_s cn50xx;
+ struct cvmx_mio_boot_int_s cn52xx;
+ struct cvmx_mio_boot_int_s cn52xxp1;
+ struct cvmx_mio_boot_int_s cn56xx;
+ struct cvmx_mio_boot_int_s cn56xxp1;
+ struct cvmx_mio_boot_int_s cn58xx;
+ struct cvmx_mio_boot_int_s cn58xxp1;
+};
+
+union cvmx_mio_boot_loc_adr {
+ uint64_t u64;
+ struct cvmx_mio_boot_loc_adr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t adr:5;
+ uint64_t reserved_0_2:3;
+ } s;
+ struct cvmx_mio_boot_loc_adr_s cn30xx;
+ struct cvmx_mio_boot_loc_adr_s cn31xx;
+ struct cvmx_mio_boot_loc_adr_s cn38xx;
+ struct cvmx_mio_boot_loc_adr_s cn38xxp2;
+ struct cvmx_mio_boot_loc_adr_s cn50xx;
+ struct cvmx_mio_boot_loc_adr_s cn52xx;
+ struct cvmx_mio_boot_loc_adr_s cn52xxp1;
+ struct cvmx_mio_boot_loc_adr_s cn56xx;
+ struct cvmx_mio_boot_loc_adr_s cn56xxp1;
+ struct cvmx_mio_boot_loc_adr_s cn58xx;
+ struct cvmx_mio_boot_loc_adr_s cn58xxp1;
+};
+
+union cvmx_mio_boot_loc_cfgx {
+ uint64_t u64;
+ struct cvmx_mio_boot_loc_cfgx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t en:1;
+ uint64_t reserved_28_30:3;
+ uint64_t base:25;
+ uint64_t reserved_0_2:3;
+ } s;
+ struct cvmx_mio_boot_loc_cfgx_s cn30xx;
+ struct cvmx_mio_boot_loc_cfgx_s cn31xx;
+ struct cvmx_mio_boot_loc_cfgx_s cn38xx;
+ struct cvmx_mio_boot_loc_cfgx_s cn38xxp2;
+ struct cvmx_mio_boot_loc_cfgx_s cn50xx;
+ struct cvmx_mio_boot_loc_cfgx_s cn52xx;
+ struct cvmx_mio_boot_loc_cfgx_s cn52xxp1;
+ struct cvmx_mio_boot_loc_cfgx_s cn56xx;
+ struct cvmx_mio_boot_loc_cfgx_s cn56xxp1;
+ struct cvmx_mio_boot_loc_cfgx_s cn58xx;
+ struct cvmx_mio_boot_loc_cfgx_s cn58xxp1;
+};
+
+union cvmx_mio_boot_loc_dat {
+ uint64_t u64;
+ struct cvmx_mio_boot_loc_dat_s {
+ uint64_t data:64;
+ } s;
+ struct cvmx_mio_boot_loc_dat_s cn30xx;
+ struct cvmx_mio_boot_loc_dat_s cn31xx;
+ struct cvmx_mio_boot_loc_dat_s cn38xx;
+ struct cvmx_mio_boot_loc_dat_s cn38xxp2;
+ struct cvmx_mio_boot_loc_dat_s cn50xx;
+ struct cvmx_mio_boot_loc_dat_s cn52xx;
+ struct cvmx_mio_boot_loc_dat_s cn52xxp1;
+ struct cvmx_mio_boot_loc_dat_s cn56xx;
+ struct cvmx_mio_boot_loc_dat_s cn56xxp1;
+ struct cvmx_mio_boot_loc_dat_s cn58xx;
+ struct cvmx_mio_boot_loc_dat_s cn58xxp1;
+};
+
+union cvmx_mio_boot_pin_defs {
+ uint64_t u64;
+ struct cvmx_mio_boot_pin_defs_s {
+ uint64_t reserved_16_63:48;
+ uint64_t ale:1;
+ uint64_t width:1;
+ uint64_t dmack_p2:1;
+ uint64_t dmack_p1:1;
+ uint64_t dmack_p0:1;
+ uint64_t term:2;
+ uint64_t nand:1;
+ uint64_t reserved_0_7:8;
+ } s;
+ struct cvmx_mio_boot_pin_defs_cn52xx {
+ uint64_t reserved_16_63:48;
+ uint64_t ale:1;
+ uint64_t width:1;
+ uint64_t reserved_13_13:1;
+ uint64_t dmack_p1:1;
+ uint64_t dmack_p0:1;
+ uint64_t term:2;
+ uint64_t nand:1;
+ uint64_t reserved_0_7:8;
+ } cn52xx;
+ struct cvmx_mio_boot_pin_defs_cn56xx {
+ uint64_t reserved_16_63:48;
+ uint64_t ale:1;
+ uint64_t width:1;
+ uint64_t dmack_p2:1;
+ uint64_t dmack_p1:1;
+ uint64_t dmack_p0:1;
+ uint64_t term:2;
+ uint64_t reserved_0_8:9;
+ } cn56xx;
+};
+
+union cvmx_mio_boot_reg_cfgx {
+ uint64_t u64;
+ struct cvmx_mio_boot_reg_cfgx_s {
+ uint64_t reserved_44_63:20;
+ uint64_t dmack:2;
+ uint64_t tim_mult:2;
+ uint64_t rd_dly:3;
+ uint64_t sam:1;
+ uint64_t we_ext:2;
+ uint64_t oe_ext:2;
+ uint64_t en:1;
+ uint64_t orbit:1;
+ uint64_t ale:1;
+ uint64_t width:1;
+ uint64_t size:12;
+ uint64_t base:16;
+ } s;
+ struct cvmx_mio_boot_reg_cfgx_cn30xx {
+ uint64_t reserved_37_63:27;
+ uint64_t sam:1;
+ uint64_t we_ext:2;
+ uint64_t oe_ext:2;
+ uint64_t en:1;
+ uint64_t orbit:1;
+ uint64_t ale:1;
+ uint64_t width:1;
+ uint64_t size:12;
+ uint64_t base:16;
+ } cn30xx;
+ struct cvmx_mio_boot_reg_cfgx_cn30xx cn31xx;
+ struct cvmx_mio_boot_reg_cfgx_cn38xx {
+ uint64_t reserved_32_63:32;
+ uint64_t en:1;
+ uint64_t orbit:1;
+ uint64_t reserved_28_29:2;
+ uint64_t size:12;
+ uint64_t base:16;
+ } cn38xx;
+ struct cvmx_mio_boot_reg_cfgx_cn38xx cn38xxp2;
+ struct cvmx_mio_boot_reg_cfgx_cn50xx {
+ uint64_t reserved_42_63:22;
+ uint64_t tim_mult:2;
+ uint64_t rd_dly:3;
+ uint64_t sam:1;
+ uint64_t we_ext:2;
+ uint64_t oe_ext:2;
+ uint64_t en:1;
+ uint64_t orbit:1;
+ uint64_t ale:1;
+ uint64_t width:1;
+ uint64_t size:12;
+ uint64_t base:16;
+ } cn50xx;
+ struct cvmx_mio_boot_reg_cfgx_s cn52xx;
+ struct cvmx_mio_boot_reg_cfgx_s cn52xxp1;
+ struct cvmx_mio_boot_reg_cfgx_s cn56xx;
+ struct cvmx_mio_boot_reg_cfgx_s cn56xxp1;
+ struct cvmx_mio_boot_reg_cfgx_cn30xx cn58xx;
+ struct cvmx_mio_boot_reg_cfgx_cn30xx cn58xxp1;
+};
+
+union cvmx_mio_boot_reg_timx {
+ uint64_t u64;
+ struct cvmx_mio_boot_reg_timx_s {
+ uint64_t pagem:1;
+ uint64_t waitm:1;
+ uint64_t pages:2;
+ uint64_t ale:6;
+ uint64_t page:6;
+ uint64_t wait:6;
+ uint64_t pause:6;
+ uint64_t wr_hld:6;
+ uint64_t rd_hld:6;
+ uint64_t we:6;
+ uint64_t oe:6;
+ uint64_t ce:6;
+ uint64_t adr:6;
+ } s;
+ struct cvmx_mio_boot_reg_timx_s cn30xx;
+ struct cvmx_mio_boot_reg_timx_s cn31xx;
+ struct cvmx_mio_boot_reg_timx_cn38xx {
+ uint64_t pagem:1;
+ uint64_t waitm:1;
+ uint64_t pages:2;
+ uint64_t reserved_54_59:6;
+ uint64_t page:6;
+ uint64_t wait:6;
+ uint64_t pause:6;
+ uint64_t wr_hld:6;
+ uint64_t rd_hld:6;
+ uint64_t we:6;
+ uint64_t oe:6;
+ uint64_t ce:6;
+ uint64_t adr:6;
+ } cn38xx;
+ struct cvmx_mio_boot_reg_timx_cn38xx cn38xxp2;
+ struct cvmx_mio_boot_reg_timx_s cn50xx;
+ struct cvmx_mio_boot_reg_timx_s cn52xx;
+ struct cvmx_mio_boot_reg_timx_s cn52xxp1;
+ struct cvmx_mio_boot_reg_timx_s cn56xx;
+ struct cvmx_mio_boot_reg_timx_s cn56xxp1;
+ struct cvmx_mio_boot_reg_timx_s cn58xx;
+ struct cvmx_mio_boot_reg_timx_s cn58xxp1;
+};
+
+union cvmx_mio_boot_thr {
+ uint64_t u64;
+ struct cvmx_mio_boot_thr_s {
+ uint64_t reserved_22_63:42;
+ uint64_t dma_thr:6;
+ uint64_t reserved_14_15:2;
+ uint64_t fif_cnt:6;
+ uint64_t reserved_6_7:2;
+ uint64_t fif_thr:6;
+ } s;
+ struct cvmx_mio_boot_thr_cn30xx {
+ uint64_t reserved_14_63:50;
+ uint64_t fif_cnt:6;
+ uint64_t reserved_6_7:2;
+ uint64_t fif_thr:6;
+ } cn30xx;
+ struct cvmx_mio_boot_thr_cn30xx cn31xx;
+ struct cvmx_mio_boot_thr_cn30xx cn38xx;
+ struct cvmx_mio_boot_thr_cn30xx cn38xxp2;
+ struct cvmx_mio_boot_thr_cn30xx cn50xx;
+ struct cvmx_mio_boot_thr_s cn52xx;
+ struct cvmx_mio_boot_thr_s cn52xxp1;
+ struct cvmx_mio_boot_thr_s cn56xx;
+ struct cvmx_mio_boot_thr_s cn56xxp1;
+ struct cvmx_mio_boot_thr_cn30xx cn58xx;
+ struct cvmx_mio_boot_thr_cn30xx cn58xxp1;
+};
+
+union cvmx_mio_fus_bnk_datx {
+ uint64_t u64;
+ struct cvmx_mio_fus_bnk_datx_s {
+ uint64_t dat:64;
+ } s;
+ struct cvmx_mio_fus_bnk_datx_s cn50xx;
+ struct cvmx_mio_fus_bnk_datx_s cn52xx;
+ struct cvmx_mio_fus_bnk_datx_s cn52xxp1;
+ struct cvmx_mio_fus_bnk_datx_s cn56xx;
+ struct cvmx_mio_fus_bnk_datx_s cn56xxp1;
+ struct cvmx_mio_fus_bnk_datx_s cn58xx;
+ struct cvmx_mio_fus_bnk_datx_s cn58xxp1;
+};
+
+union cvmx_mio_fus_dat0 {
+ uint64_t u64;
+ struct cvmx_mio_fus_dat0_s {
+ uint64_t reserved_32_63:32;
+ uint64_t man_info:32;
+ } s;
+ struct cvmx_mio_fus_dat0_s cn30xx;
+ struct cvmx_mio_fus_dat0_s cn31xx;
+ struct cvmx_mio_fus_dat0_s cn38xx;
+ struct cvmx_mio_fus_dat0_s cn38xxp2;
+ struct cvmx_mio_fus_dat0_s cn50xx;
+ struct cvmx_mio_fus_dat0_s cn52xx;
+ struct cvmx_mio_fus_dat0_s cn52xxp1;
+ struct cvmx_mio_fus_dat0_s cn56xx;
+ struct cvmx_mio_fus_dat0_s cn56xxp1;
+ struct cvmx_mio_fus_dat0_s cn58xx;
+ struct cvmx_mio_fus_dat0_s cn58xxp1;
+};
+
+union cvmx_mio_fus_dat1 {
+ uint64_t u64;
+ struct cvmx_mio_fus_dat1_s {
+ uint64_t reserved_32_63:32;
+ uint64_t man_info:32;
+ } s;
+ struct cvmx_mio_fus_dat1_s cn30xx;
+ struct cvmx_mio_fus_dat1_s cn31xx;
+ struct cvmx_mio_fus_dat1_s cn38xx;
+ struct cvmx_mio_fus_dat1_s cn38xxp2;
+ struct cvmx_mio_fus_dat1_s cn50xx;
+ struct cvmx_mio_fus_dat1_s cn52xx;
+ struct cvmx_mio_fus_dat1_s cn52xxp1;
+ struct cvmx_mio_fus_dat1_s cn56xx;
+ struct cvmx_mio_fus_dat1_s cn56xxp1;
+ struct cvmx_mio_fus_dat1_s cn58xx;
+ struct cvmx_mio_fus_dat1_s cn58xxp1;
+};
+
+union cvmx_mio_fus_dat2 {
+ uint64_t u64;
+ struct cvmx_mio_fus_dat2_s {
+ uint64_t reserved_34_63:30;
+ uint64_t fus318:1;
+ uint64_t raid_en:1;
+ uint64_t reserved_30_31:2;
+ uint64_t nokasu:1;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t reserved_0_15:16;
+ } s;
+ struct cvmx_mio_fus_dat2_cn30xx {
+ uint64_t reserved_29_63:35;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t pll_off:4;
+ uint64_t reserved_1_11:11;
+ uint64_t pp_dis:1;
+ } cn30xx;
+ struct cvmx_mio_fus_dat2_cn31xx {
+ uint64_t reserved_29_63:35;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t pll_off:4;
+ uint64_t reserved_2_11:10;
+ uint64_t pp_dis:2;
+ } cn31xx;
+ struct cvmx_mio_fus_dat2_cn38xx {
+ uint64_t reserved_29_63:35;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t pp_dis:16;
+ } cn38xx;
+ struct cvmx_mio_fus_dat2_cn38xx cn38xxp2;
+ struct cvmx_mio_fus_dat2_cn50xx {
+ uint64_t reserved_34_63:30;
+ uint64_t fus318:1;
+ uint64_t raid_en:1;
+ uint64_t reserved_30_31:2;
+ uint64_t nokasu:1;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t reserved_2_15:14;
+ uint64_t pp_dis:2;
+ } cn50xx;
+ struct cvmx_mio_fus_dat2_cn52xx {
+ uint64_t reserved_34_63:30;
+ uint64_t fus318:1;
+ uint64_t raid_en:1;
+ uint64_t reserved_30_31:2;
+ uint64_t nokasu:1;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t reserved_4_15:12;
+ uint64_t pp_dis:4;
+ } cn52xx;
+ struct cvmx_mio_fus_dat2_cn52xx cn52xxp1;
+ struct cvmx_mio_fus_dat2_cn56xx {
+ uint64_t reserved_34_63:30;
+ uint64_t fus318:1;
+ uint64_t raid_en:1;
+ uint64_t reserved_30_31:2;
+ uint64_t nokasu:1;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t reserved_12_15:4;
+ uint64_t pp_dis:12;
+ } cn56xx;
+ struct cvmx_mio_fus_dat2_cn56xx cn56xxp1;
+ struct cvmx_mio_fus_dat2_cn58xx {
+ uint64_t reserved_30_63:34;
+ uint64_t nokasu:1;
+ uint64_t nodfa_cp2:1;
+ uint64_t nomul:1;
+ uint64_t nocrypto:1;
+ uint64_t rst_sht:1;
+ uint64_t bist_dis:1;
+ uint64_t chip_id:8;
+ uint64_t pp_dis:16;
+ } cn58xx;
+ struct cvmx_mio_fus_dat2_cn58xx cn58xxp1;
+};
+
+union cvmx_mio_fus_dat3 {
+ uint64_t u64;
+ struct cvmx_mio_fus_dat3_s {
+ uint64_t reserved_32_63:32;
+ uint64_t pll_div4:1;
+ uint64_t zip_crip:2;
+ uint64_t bar2_en:1;
+ uint64_t efus_lck:1;
+ uint64_t efus_ign:1;
+ uint64_t nozip:1;
+ uint64_t nodfa_dte:1;
+ uint64_t icache:24;
+ } s;
+ struct cvmx_mio_fus_dat3_cn30xx {
+ uint64_t reserved_32_63:32;
+ uint64_t pll_div4:1;
+ uint64_t reserved_29_30:2;
+ uint64_t bar2_en:1;
+ uint64_t efus_lck:1;
+ uint64_t efus_ign:1;
+ uint64_t nozip:1;
+ uint64_t nodfa_dte:1;
+ uint64_t icache:24;
+ } cn30xx;
+ struct cvmx_mio_fus_dat3_s cn31xx;
+ struct cvmx_mio_fus_dat3_cn38xx {
+ uint64_t reserved_31_63:33;
+ uint64_t zip_crip:2;
+ uint64_t bar2_en:1;
+ uint64_t efus_lck:1;
+ uint64_t efus_ign:1;
+ uint64_t nozip:1;
+ uint64_t nodfa_dte:1;
+ uint64_t icache:24;
+ } cn38xx;
+ struct cvmx_mio_fus_dat3_cn38xxp2 {
+ uint64_t reserved_29_63:35;
+ uint64_t bar2_en:1;
+ uint64_t efus_lck:1;
+ uint64_t efus_ign:1;
+ uint64_t nozip:1;
+ uint64_t nodfa_dte:1;
+ uint64_t icache:24;
+ } cn38xxp2;
+ struct cvmx_mio_fus_dat3_cn38xx cn50xx;
+ struct cvmx_mio_fus_dat3_cn38xx cn52xx;
+ struct cvmx_mio_fus_dat3_cn38xx cn52xxp1;
+ struct cvmx_mio_fus_dat3_cn38xx cn56xx;
+ struct cvmx_mio_fus_dat3_cn38xx cn56xxp1;
+ struct cvmx_mio_fus_dat3_cn38xx cn58xx;
+ struct cvmx_mio_fus_dat3_cn38xx cn58xxp1;
+};
+
+union cvmx_mio_fus_ema {
+ uint64_t u64;
+ struct cvmx_mio_fus_ema_s {
+ uint64_t reserved_7_63:57;
+ uint64_t eff_ema:3;
+ uint64_t reserved_3_3:1;
+ uint64_t ema:3;
+ } s;
+ struct cvmx_mio_fus_ema_s cn50xx;
+ struct cvmx_mio_fus_ema_s cn52xx;
+ struct cvmx_mio_fus_ema_s cn52xxp1;
+ struct cvmx_mio_fus_ema_s cn56xx;
+ struct cvmx_mio_fus_ema_s cn56xxp1;
+ struct cvmx_mio_fus_ema_cn58xx {
+ uint64_t reserved_2_63:62;
+ uint64_t ema:2;
+ } cn58xx;
+ struct cvmx_mio_fus_ema_cn58xx cn58xxp1;
+};
+
+union cvmx_mio_fus_pdf {
+ uint64_t u64;
+ struct cvmx_mio_fus_pdf_s {
+ uint64_t pdf:64;
+ } s;
+ struct cvmx_mio_fus_pdf_s cn50xx;
+ struct cvmx_mio_fus_pdf_s cn52xx;
+ struct cvmx_mio_fus_pdf_s cn52xxp1;
+ struct cvmx_mio_fus_pdf_s cn56xx;
+ struct cvmx_mio_fus_pdf_s cn56xxp1;
+ struct cvmx_mio_fus_pdf_s cn58xx;
+};
+
+union cvmx_mio_fus_pll {
+ uint64_t u64;
+ struct cvmx_mio_fus_pll_s {
+ uint64_t reserved_2_63:62;
+ uint64_t rfslip:1;
+ uint64_t fbslip:1;
+ } s;
+ struct cvmx_mio_fus_pll_s cn50xx;
+ struct cvmx_mio_fus_pll_s cn52xx;
+ struct cvmx_mio_fus_pll_s cn52xxp1;
+ struct cvmx_mio_fus_pll_s cn56xx;
+ struct cvmx_mio_fus_pll_s cn56xxp1;
+ struct cvmx_mio_fus_pll_s cn58xx;
+ struct cvmx_mio_fus_pll_s cn58xxp1;
+};
+
+union cvmx_mio_fus_prog {
+ uint64_t u64;
+ struct cvmx_mio_fus_prog_s {
+ uint64_t reserved_1_63:63;
+ uint64_t prog:1;
+ } s;
+ struct cvmx_mio_fus_prog_s cn30xx;
+ struct cvmx_mio_fus_prog_s cn31xx;
+ struct cvmx_mio_fus_prog_s cn38xx;
+ struct cvmx_mio_fus_prog_s cn38xxp2;
+ struct cvmx_mio_fus_prog_s cn50xx;
+ struct cvmx_mio_fus_prog_s cn52xx;
+ struct cvmx_mio_fus_prog_s cn52xxp1;
+ struct cvmx_mio_fus_prog_s cn56xx;
+ struct cvmx_mio_fus_prog_s cn56xxp1;
+ struct cvmx_mio_fus_prog_s cn58xx;
+ struct cvmx_mio_fus_prog_s cn58xxp1;
+};
+
+union cvmx_mio_fus_prog_times {
+ uint64_t u64;
+ struct cvmx_mio_fus_prog_times_s {
+ uint64_t reserved_33_63:31;
+ uint64_t prog_pin:1;
+ uint64_t out:8;
+ uint64_t sclk_lo:4;
+ uint64_t sclk_hi:12;
+ uint64_t setup:8;
+ } s;
+ struct cvmx_mio_fus_prog_times_s cn50xx;
+ struct cvmx_mio_fus_prog_times_s cn52xx;
+ struct cvmx_mio_fus_prog_times_s cn52xxp1;
+ struct cvmx_mio_fus_prog_times_s cn56xx;
+ struct cvmx_mio_fus_prog_times_s cn56xxp1;
+ struct cvmx_mio_fus_prog_times_s cn58xx;
+ struct cvmx_mio_fus_prog_times_s cn58xxp1;
+};
+
+union cvmx_mio_fus_rcmd {
+ uint64_t u64;
+ struct cvmx_mio_fus_rcmd_s {
+ uint64_t reserved_24_63:40;
+ uint64_t dat:8;
+ uint64_t reserved_13_15:3;
+ uint64_t pend:1;
+ uint64_t reserved_9_11:3;
+ uint64_t efuse:1;
+ uint64_t addr:8;
+ } s;
+ struct cvmx_mio_fus_rcmd_cn30xx {
+ uint64_t reserved_24_63:40;
+ uint64_t dat:8;
+ uint64_t reserved_13_15:3;
+ uint64_t pend:1;
+ uint64_t reserved_9_11:3;
+ uint64_t efuse:1;
+ uint64_t reserved_7_7:1;
+ uint64_t addr:7;
+ } cn30xx;
+ struct cvmx_mio_fus_rcmd_cn30xx cn31xx;
+ struct cvmx_mio_fus_rcmd_cn30xx cn38xx;
+ struct cvmx_mio_fus_rcmd_cn30xx cn38xxp2;
+ struct cvmx_mio_fus_rcmd_cn30xx cn50xx;
+ struct cvmx_mio_fus_rcmd_s cn52xx;
+ struct cvmx_mio_fus_rcmd_s cn52xxp1;
+ struct cvmx_mio_fus_rcmd_s cn56xx;
+ struct cvmx_mio_fus_rcmd_s cn56xxp1;
+ struct cvmx_mio_fus_rcmd_cn30xx cn58xx;
+ struct cvmx_mio_fus_rcmd_cn30xx cn58xxp1;
+};
+
+union cvmx_mio_fus_spr_repair_res {
+ uint64_t u64;
+ struct cvmx_mio_fus_spr_repair_res_s {
+ uint64_t reserved_42_63:22;
+ uint64_t repair2:14;
+ uint64_t repair1:14;
+ uint64_t repair0:14;
+ } s;
+ struct cvmx_mio_fus_spr_repair_res_s cn30xx;
+ struct cvmx_mio_fus_spr_repair_res_s cn31xx;
+ struct cvmx_mio_fus_spr_repair_res_s cn38xx;
+ struct cvmx_mio_fus_spr_repair_res_s cn50xx;
+ struct cvmx_mio_fus_spr_repair_res_s cn52xx;
+ struct cvmx_mio_fus_spr_repair_res_s cn52xxp1;
+ struct cvmx_mio_fus_spr_repair_res_s cn56xx;
+ struct cvmx_mio_fus_spr_repair_res_s cn56xxp1;
+ struct cvmx_mio_fus_spr_repair_res_s cn58xx;
+ struct cvmx_mio_fus_spr_repair_res_s cn58xxp1;
+};
+
+union cvmx_mio_fus_spr_repair_sum {
+ uint64_t u64;
+ struct cvmx_mio_fus_spr_repair_sum_s {
+ uint64_t reserved_1_63:63;
+ uint64_t too_many:1;
+ } s;
+ struct cvmx_mio_fus_spr_repair_sum_s cn30xx;
+ struct cvmx_mio_fus_spr_repair_sum_s cn31xx;
+ struct cvmx_mio_fus_spr_repair_sum_s cn38xx;
+ struct cvmx_mio_fus_spr_repair_sum_s cn50xx;
+ struct cvmx_mio_fus_spr_repair_sum_s cn52xx;
+ struct cvmx_mio_fus_spr_repair_sum_s cn52xxp1;
+ struct cvmx_mio_fus_spr_repair_sum_s cn56xx;
+ struct cvmx_mio_fus_spr_repair_sum_s cn56xxp1;
+ struct cvmx_mio_fus_spr_repair_sum_s cn58xx;
+ struct cvmx_mio_fus_spr_repair_sum_s cn58xxp1;
+};
+
+union cvmx_mio_fus_unlock {
+ uint64_t u64;
+ struct cvmx_mio_fus_unlock_s {
+ uint64_t reserved_24_63:40;
+ uint64_t key:24;
+ } s;
+ struct cvmx_mio_fus_unlock_s cn30xx;
+ struct cvmx_mio_fus_unlock_s cn31xx;
+};
+
+union cvmx_mio_fus_wadr {
+ uint64_t u64;
+ struct cvmx_mio_fus_wadr_s {
+ uint64_t reserved_10_63:54;
+ uint64_t addr:10;
+ } s;
+ struct cvmx_mio_fus_wadr_s cn30xx;
+ struct cvmx_mio_fus_wadr_s cn31xx;
+ struct cvmx_mio_fus_wadr_s cn38xx;
+ struct cvmx_mio_fus_wadr_s cn38xxp2;
+ struct cvmx_mio_fus_wadr_cn50xx {
+ uint64_t reserved_2_63:62;
+ uint64_t addr:2;
+ } cn50xx;
+ struct cvmx_mio_fus_wadr_cn52xx {
+ uint64_t reserved_3_63:61;
+ uint64_t addr:3;
+ } cn52xx;
+ struct cvmx_mio_fus_wadr_cn52xx cn52xxp1;
+ struct cvmx_mio_fus_wadr_cn52xx cn56xx;
+ struct cvmx_mio_fus_wadr_cn52xx cn56xxp1;
+ struct cvmx_mio_fus_wadr_cn50xx cn58xx;
+ struct cvmx_mio_fus_wadr_cn50xx cn58xxp1;
+};
+
+union cvmx_mio_ndf_dma_cfg {
+ uint64_t u64;
+ struct cvmx_mio_ndf_dma_cfg_s {
+ uint64_t en:1;
+ uint64_t rw:1;
+ uint64_t clr:1;
+ uint64_t reserved_60_60:1;
+ uint64_t swap32:1;
+ uint64_t swap16:1;
+ uint64_t swap8:1;
+ uint64_t endian:1;
+ uint64_t size:20;
+ uint64_t adr:36;
+ } s;
+ struct cvmx_mio_ndf_dma_cfg_s cn52xx;
+};
+
+union cvmx_mio_ndf_dma_int {
+ uint64_t u64;
+ struct cvmx_mio_ndf_dma_int_s {
+ uint64_t reserved_1_63:63;
+ uint64_t done:1;
+ } s;
+ struct cvmx_mio_ndf_dma_int_s cn52xx;
+};
+
+union cvmx_mio_ndf_dma_int_en {
+ uint64_t u64;
+ struct cvmx_mio_ndf_dma_int_en_s {
+ uint64_t reserved_1_63:63;
+ uint64_t done:1;
+ } s;
+ struct cvmx_mio_ndf_dma_int_en_s cn52xx;
+};
+
+union cvmx_mio_pll_ctl {
+ uint64_t u64;
+ struct cvmx_mio_pll_ctl_s {
+ uint64_t reserved_5_63:59;
+ uint64_t bw_ctl:5;
+ } s;
+ struct cvmx_mio_pll_ctl_s cn30xx;
+ struct cvmx_mio_pll_ctl_s cn31xx;
+};
+
+union cvmx_mio_pll_setting {
+ uint64_t u64;
+ struct cvmx_mio_pll_setting_s {
+ uint64_t reserved_17_63:47;
+ uint64_t setting:17;
+ } s;
+ struct cvmx_mio_pll_setting_s cn30xx;
+ struct cvmx_mio_pll_setting_s cn31xx;
+};
+
+union cvmx_mio_twsx_int {
+ uint64_t u64;
+ struct cvmx_mio_twsx_int_s {
+ uint64_t reserved_12_63:52;
+ uint64_t scl:1;
+ uint64_t sda:1;
+ uint64_t scl_ovr:1;
+ uint64_t sda_ovr:1;
+ uint64_t reserved_7_7:1;
+ uint64_t core_en:1;
+ uint64_t ts_en:1;
+ uint64_t st_en:1;
+ uint64_t reserved_3_3:1;
+ uint64_t core_int:1;
+ uint64_t ts_int:1;
+ uint64_t st_int:1;
+ } s;
+ struct cvmx_mio_twsx_int_s cn30xx;
+ struct cvmx_mio_twsx_int_s cn31xx;
+ struct cvmx_mio_twsx_int_s cn38xx;
+ struct cvmx_mio_twsx_int_cn38xxp2 {
+ uint64_t reserved_7_63:57;
+ uint64_t core_en:1;
+ uint64_t ts_en:1;
+ uint64_t st_en:1;
+ uint64_t reserved_3_3:1;
+ uint64_t core_int:1;
+ uint64_t ts_int:1;
+ uint64_t st_int:1;
+ } cn38xxp2;
+ struct cvmx_mio_twsx_int_s cn50xx;
+ struct cvmx_mio_twsx_int_s cn52xx;
+ struct cvmx_mio_twsx_int_s cn52xxp1;
+ struct cvmx_mio_twsx_int_s cn56xx;
+ struct cvmx_mio_twsx_int_s cn56xxp1;
+ struct cvmx_mio_twsx_int_s cn58xx;
+ struct cvmx_mio_twsx_int_s cn58xxp1;
+};
+
+union cvmx_mio_twsx_sw_twsi {
+ uint64_t u64;
+ struct cvmx_mio_twsx_sw_twsi_s {
+ uint64_t v:1;
+ uint64_t slonly:1;
+ uint64_t eia:1;
+ uint64_t op:4;
+ uint64_t r:1;
+ uint64_t sovr:1;
+ uint64_t size:3;
+ uint64_t scr:2;
+ uint64_t a:10;
+ uint64_t ia:5;
+ uint64_t eop_ia:3;
+ uint64_t d:32;
+ } s;
+ struct cvmx_mio_twsx_sw_twsi_s cn30xx;
+ struct cvmx_mio_twsx_sw_twsi_s cn31xx;
+ struct cvmx_mio_twsx_sw_twsi_s cn38xx;
+ struct cvmx_mio_twsx_sw_twsi_s cn38xxp2;
+ struct cvmx_mio_twsx_sw_twsi_s cn50xx;
+ struct cvmx_mio_twsx_sw_twsi_s cn52xx;
+ struct cvmx_mio_twsx_sw_twsi_s cn52xxp1;
+ struct cvmx_mio_twsx_sw_twsi_s cn56xx;
+ struct cvmx_mio_twsx_sw_twsi_s cn56xxp1;
+ struct cvmx_mio_twsx_sw_twsi_s cn58xx;
+ struct cvmx_mio_twsx_sw_twsi_s cn58xxp1;
+};
+
+union cvmx_mio_twsx_sw_twsi_ext {
+ uint64_t u64;
+ struct cvmx_mio_twsx_sw_twsi_ext_s {
+ uint64_t reserved_40_63:24;
+ uint64_t ia:8;
+ uint64_t d:32;
+ } s;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn30xx;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn31xx;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn38xx;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn38xxp2;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn50xx;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn52xx;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn52xxp1;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn56xx;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn56xxp1;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn58xx;
+ struct cvmx_mio_twsx_sw_twsi_ext_s cn58xxp1;
+};
+
+union cvmx_mio_twsx_twsi_sw {
+ uint64_t u64;
+ struct cvmx_mio_twsx_twsi_sw_s {
+ uint64_t v:2;
+ uint64_t reserved_32_61:30;
+ uint64_t d:32;
+ } s;
+ struct cvmx_mio_twsx_twsi_sw_s cn30xx;
+ struct cvmx_mio_twsx_twsi_sw_s cn31xx;
+ struct cvmx_mio_twsx_twsi_sw_s cn38xx;
+ struct cvmx_mio_twsx_twsi_sw_s cn38xxp2;
+ struct cvmx_mio_twsx_twsi_sw_s cn50xx;
+ struct cvmx_mio_twsx_twsi_sw_s cn52xx;
+ struct cvmx_mio_twsx_twsi_sw_s cn52xxp1;
+ struct cvmx_mio_twsx_twsi_sw_s cn56xx;
+ struct cvmx_mio_twsx_twsi_sw_s cn56xxp1;
+ struct cvmx_mio_twsx_twsi_sw_s cn58xx;
+ struct cvmx_mio_twsx_twsi_sw_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_dlh {
+ uint64_t u64;
+ struct cvmx_mio_uartx_dlh_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dlh:8;
+ } s;
+ struct cvmx_mio_uartx_dlh_s cn30xx;
+ struct cvmx_mio_uartx_dlh_s cn31xx;
+ struct cvmx_mio_uartx_dlh_s cn38xx;
+ struct cvmx_mio_uartx_dlh_s cn38xxp2;
+ struct cvmx_mio_uartx_dlh_s cn50xx;
+ struct cvmx_mio_uartx_dlh_s cn52xx;
+ struct cvmx_mio_uartx_dlh_s cn52xxp1;
+ struct cvmx_mio_uartx_dlh_s cn56xx;
+ struct cvmx_mio_uartx_dlh_s cn56xxp1;
+ struct cvmx_mio_uartx_dlh_s cn58xx;
+ struct cvmx_mio_uartx_dlh_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_dll {
+ uint64_t u64;
+ struct cvmx_mio_uartx_dll_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dll:8;
+ } s;
+ struct cvmx_mio_uartx_dll_s cn30xx;
+ struct cvmx_mio_uartx_dll_s cn31xx;
+ struct cvmx_mio_uartx_dll_s cn38xx;
+ struct cvmx_mio_uartx_dll_s cn38xxp2;
+ struct cvmx_mio_uartx_dll_s cn50xx;
+ struct cvmx_mio_uartx_dll_s cn52xx;
+ struct cvmx_mio_uartx_dll_s cn52xxp1;
+ struct cvmx_mio_uartx_dll_s cn56xx;
+ struct cvmx_mio_uartx_dll_s cn56xxp1;
+ struct cvmx_mio_uartx_dll_s cn58xx;
+ struct cvmx_mio_uartx_dll_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_far {
+ uint64_t u64;
+ struct cvmx_mio_uartx_far_s {
+ uint64_t reserved_1_63:63;
+ uint64_t far:1;
+ } s;
+ struct cvmx_mio_uartx_far_s cn30xx;
+ struct cvmx_mio_uartx_far_s cn31xx;
+ struct cvmx_mio_uartx_far_s cn38xx;
+ struct cvmx_mio_uartx_far_s cn38xxp2;
+ struct cvmx_mio_uartx_far_s cn50xx;
+ struct cvmx_mio_uartx_far_s cn52xx;
+ struct cvmx_mio_uartx_far_s cn52xxp1;
+ struct cvmx_mio_uartx_far_s cn56xx;
+ struct cvmx_mio_uartx_far_s cn56xxp1;
+ struct cvmx_mio_uartx_far_s cn58xx;
+ struct cvmx_mio_uartx_far_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_fcr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_fcr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t rxtrig:2;
+ uint64_t txtrig:2;
+ uint64_t reserved_3_3:1;
+ uint64_t txfr:1;
+ uint64_t rxfr:1;
+ uint64_t en:1;
+ } s;
+ struct cvmx_mio_uartx_fcr_s cn30xx;
+ struct cvmx_mio_uartx_fcr_s cn31xx;
+ struct cvmx_mio_uartx_fcr_s cn38xx;
+ struct cvmx_mio_uartx_fcr_s cn38xxp2;
+ struct cvmx_mio_uartx_fcr_s cn50xx;
+ struct cvmx_mio_uartx_fcr_s cn52xx;
+ struct cvmx_mio_uartx_fcr_s cn52xxp1;
+ struct cvmx_mio_uartx_fcr_s cn56xx;
+ struct cvmx_mio_uartx_fcr_s cn56xxp1;
+ struct cvmx_mio_uartx_fcr_s cn58xx;
+ struct cvmx_mio_uartx_fcr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_htx {
+ uint64_t u64;
+ struct cvmx_mio_uartx_htx_s {
+ uint64_t reserved_1_63:63;
+ uint64_t htx:1;
+ } s;
+ struct cvmx_mio_uartx_htx_s cn30xx;
+ struct cvmx_mio_uartx_htx_s cn31xx;
+ struct cvmx_mio_uartx_htx_s cn38xx;
+ struct cvmx_mio_uartx_htx_s cn38xxp2;
+ struct cvmx_mio_uartx_htx_s cn50xx;
+ struct cvmx_mio_uartx_htx_s cn52xx;
+ struct cvmx_mio_uartx_htx_s cn52xxp1;
+ struct cvmx_mio_uartx_htx_s cn56xx;
+ struct cvmx_mio_uartx_htx_s cn56xxp1;
+ struct cvmx_mio_uartx_htx_s cn58xx;
+ struct cvmx_mio_uartx_htx_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_ier {
+ uint64_t u64;
+ struct cvmx_mio_uartx_ier_s {
+ uint64_t reserved_8_63:56;
+ uint64_t ptime:1;
+ uint64_t reserved_4_6:3;
+ uint64_t edssi:1;
+ uint64_t elsi:1;
+ uint64_t etbei:1;
+ uint64_t erbfi:1;
+ } s;
+ struct cvmx_mio_uartx_ier_s cn30xx;
+ struct cvmx_mio_uartx_ier_s cn31xx;
+ struct cvmx_mio_uartx_ier_s cn38xx;
+ struct cvmx_mio_uartx_ier_s cn38xxp2;
+ struct cvmx_mio_uartx_ier_s cn50xx;
+ struct cvmx_mio_uartx_ier_s cn52xx;
+ struct cvmx_mio_uartx_ier_s cn52xxp1;
+ struct cvmx_mio_uartx_ier_s cn56xx;
+ struct cvmx_mio_uartx_ier_s cn56xxp1;
+ struct cvmx_mio_uartx_ier_s cn58xx;
+ struct cvmx_mio_uartx_ier_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_iir {
+ uint64_t u64;
+ struct cvmx_mio_uartx_iir_s {
+ uint64_t reserved_8_63:56;
+ uint64_t fen:2;
+ uint64_t reserved_4_5:2;
+ uint64_t iid:4;
+ } s;
+ struct cvmx_mio_uartx_iir_s cn30xx;
+ struct cvmx_mio_uartx_iir_s cn31xx;
+ struct cvmx_mio_uartx_iir_s cn38xx;
+ struct cvmx_mio_uartx_iir_s cn38xxp2;
+ struct cvmx_mio_uartx_iir_s cn50xx;
+ struct cvmx_mio_uartx_iir_s cn52xx;
+ struct cvmx_mio_uartx_iir_s cn52xxp1;
+ struct cvmx_mio_uartx_iir_s cn56xx;
+ struct cvmx_mio_uartx_iir_s cn56xxp1;
+ struct cvmx_mio_uartx_iir_s cn58xx;
+ struct cvmx_mio_uartx_iir_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_lcr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_lcr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dlab:1;
+ uint64_t brk:1;
+ uint64_t reserved_5_5:1;
+ uint64_t eps:1;
+ uint64_t pen:1;
+ uint64_t stop:1;
+ uint64_t cls:2;
+ } s;
+ struct cvmx_mio_uartx_lcr_s cn30xx;
+ struct cvmx_mio_uartx_lcr_s cn31xx;
+ struct cvmx_mio_uartx_lcr_s cn38xx;
+ struct cvmx_mio_uartx_lcr_s cn38xxp2;
+ struct cvmx_mio_uartx_lcr_s cn50xx;
+ struct cvmx_mio_uartx_lcr_s cn52xx;
+ struct cvmx_mio_uartx_lcr_s cn52xxp1;
+ struct cvmx_mio_uartx_lcr_s cn56xx;
+ struct cvmx_mio_uartx_lcr_s cn56xxp1;
+ struct cvmx_mio_uartx_lcr_s cn58xx;
+ struct cvmx_mio_uartx_lcr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_lsr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_lsr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t ferr:1;
+ uint64_t temt:1;
+ uint64_t thre:1;
+ uint64_t bi:1;
+ uint64_t fe:1;
+ uint64_t pe:1;
+ uint64_t oe:1;
+ uint64_t dr:1;
+ } s;
+ struct cvmx_mio_uartx_lsr_s cn30xx;
+ struct cvmx_mio_uartx_lsr_s cn31xx;
+ struct cvmx_mio_uartx_lsr_s cn38xx;
+ struct cvmx_mio_uartx_lsr_s cn38xxp2;
+ struct cvmx_mio_uartx_lsr_s cn50xx;
+ struct cvmx_mio_uartx_lsr_s cn52xx;
+ struct cvmx_mio_uartx_lsr_s cn52xxp1;
+ struct cvmx_mio_uartx_lsr_s cn56xx;
+ struct cvmx_mio_uartx_lsr_s cn56xxp1;
+ struct cvmx_mio_uartx_lsr_s cn58xx;
+ struct cvmx_mio_uartx_lsr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_mcr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_mcr_s {
+ uint64_t reserved_6_63:58;
+ uint64_t afce:1;
+ uint64_t loop:1;
+ uint64_t out2:1;
+ uint64_t out1:1;
+ uint64_t rts:1;
+ uint64_t dtr:1;
+ } s;
+ struct cvmx_mio_uartx_mcr_s cn30xx;
+ struct cvmx_mio_uartx_mcr_s cn31xx;
+ struct cvmx_mio_uartx_mcr_s cn38xx;
+ struct cvmx_mio_uartx_mcr_s cn38xxp2;
+ struct cvmx_mio_uartx_mcr_s cn50xx;
+ struct cvmx_mio_uartx_mcr_s cn52xx;
+ struct cvmx_mio_uartx_mcr_s cn52xxp1;
+ struct cvmx_mio_uartx_mcr_s cn56xx;
+ struct cvmx_mio_uartx_mcr_s cn56xxp1;
+ struct cvmx_mio_uartx_mcr_s cn58xx;
+ struct cvmx_mio_uartx_mcr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_msr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_msr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dcd:1;
+ uint64_t ri:1;
+ uint64_t dsr:1;
+ uint64_t cts:1;
+ uint64_t ddcd:1;
+ uint64_t teri:1;
+ uint64_t ddsr:1;
+ uint64_t dcts:1;
+ } s;
+ struct cvmx_mio_uartx_msr_s cn30xx;
+ struct cvmx_mio_uartx_msr_s cn31xx;
+ struct cvmx_mio_uartx_msr_s cn38xx;
+ struct cvmx_mio_uartx_msr_s cn38xxp2;
+ struct cvmx_mio_uartx_msr_s cn50xx;
+ struct cvmx_mio_uartx_msr_s cn52xx;
+ struct cvmx_mio_uartx_msr_s cn52xxp1;
+ struct cvmx_mio_uartx_msr_s cn56xx;
+ struct cvmx_mio_uartx_msr_s cn56xxp1;
+ struct cvmx_mio_uartx_msr_s cn58xx;
+ struct cvmx_mio_uartx_msr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_rbr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_rbr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t rbr:8;
+ } s;
+ struct cvmx_mio_uartx_rbr_s cn30xx;
+ struct cvmx_mio_uartx_rbr_s cn31xx;
+ struct cvmx_mio_uartx_rbr_s cn38xx;
+ struct cvmx_mio_uartx_rbr_s cn38xxp2;
+ struct cvmx_mio_uartx_rbr_s cn50xx;
+ struct cvmx_mio_uartx_rbr_s cn52xx;
+ struct cvmx_mio_uartx_rbr_s cn52xxp1;
+ struct cvmx_mio_uartx_rbr_s cn56xx;
+ struct cvmx_mio_uartx_rbr_s cn56xxp1;
+ struct cvmx_mio_uartx_rbr_s cn58xx;
+ struct cvmx_mio_uartx_rbr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_rfl {
+ uint64_t u64;
+ struct cvmx_mio_uartx_rfl_s {
+ uint64_t reserved_7_63:57;
+ uint64_t rfl:7;
+ } s;
+ struct cvmx_mio_uartx_rfl_s cn30xx;
+ struct cvmx_mio_uartx_rfl_s cn31xx;
+ struct cvmx_mio_uartx_rfl_s cn38xx;
+ struct cvmx_mio_uartx_rfl_s cn38xxp2;
+ struct cvmx_mio_uartx_rfl_s cn50xx;
+ struct cvmx_mio_uartx_rfl_s cn52xx;
+ struct cvmx_mio_uartx_rfl_s cn52xxp1;
+ struct cvmx_mio_uartx_rfl_s cn56xx;
+ struct cvmx_mio_uartx_rfl_s cn56xxp1;
+ struct cvmx_mio_uartx_rfl_s cn58xx;
+ struct cvmx_mio_uartx_rfl_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_rfw {
+ uint64_t u64;
+ struct cvmx_mio_uartx_rfw_s {
+ uint64_t reserved_10_63:54;
+ uint64_t rffe:1;
+ uint64_t rfpe:1;
+ uint64_t rfwd:8;
+ } s;
+ struct cvmx_mio_uartx_rfw_s cn30xx;
+ struct cvmx_mio_uartx_rfw_s cn31xx;
+ struct cvmx_mio_uartx_rfw_s cn38xx;
+ struct cvmx_mio_uartx_rfw_s cn38xxp2;
+ struct cvmx_mio_uartx_rfw_s cn50xx;
+ struct cvmx_mio_uartx_rfw_s cn52xx;
+ struct cvmx_mio_uartx_rfw_s cn52xxp1;
+ struct cvmx_mio_uartx_rfw_s cn56xx;
+ struct cvmx_mio_uartx_rfw_s cn56xxp1;
+ struct cvmx_mio_uartx_rfw_s cn58xx;
+ struct cvmx_mio_uartx_rfw_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_sbcr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_sbcr_s {
+ uint64_t reserved_1_63:63;
+ uint64_t sbcr:1;
+ } s;
+ struct cvmx_mio_uartx_sbcr_s cn30xx;
+ struct cvmx_mio_uartx_sbcr_s cn31xx;
+ struct cvmx_mio_uartx_sbcr_s cn38xx;
+ struct cvmx_mio_uartx_sbcr_s cn38xxp2;
+ struct cvmx_mio_uartx_sbcr_s cn50xx;
+ struct cvmx_mio_uartx_sbcr_s cn52xx;
+ struct cvmx_mio_uartx_sbcr_s cn52xxp1;
+ struct cvmx_mio_uartx_sbcr_s cn56xx;
+ struct cvmx_mio_uartx_sbcr_s cn56xxp1;
+ struct cvmx_mio_uartx_sbcr_s cn58xx;
+ struct cvmx_mio_uartx_sbcr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_scr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_scr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t scr:8;
+ } s;
+ struct cvmx_mio_uartx_scr_s cn30xx;
+ struct cvmx_mio_uartx_scr_s cn31xx;
+ struct cvmx_mio_uartx_scr_s cn38xx;
+ struct cvmx_mio_uartx_scr_s cn38xxp2;
+ struct cvmx_mio_uartx_scr_s cn50xx;
+ struct cvmx_mio_uartx_scr_s cn52xx;
+ struct cvmx_mio_uartx_scr_s cn52xxp1;
+ struct cvmx_mio_uartx_scr_s cn56xx;
+ struct cvmx_mio_uartx_scr_s cn56xxp1;
+ struct cvmx_mio_uartx_scr_s cn58xx;
+ struct cvmx_mio_uartx_scr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_sfe {
+ uint64_t u64;
+ struct cvmx_mio_uartx_sfe_s {
+ uint64_t reserved_1_63:63;
+ uint64_t sfe:1;
+ } s;
+ struct cvmx_mio_uartx_sfe_s cn30xx;
+ struct cvmx_mio_uartx_sfe_s cn31xx;
+ struct cvmx_mio_uartx_sfe_s cn38xx;
+ struct cvmx_mio_uartx_sfe_s cn38xxp2;
+ struct cvmx_mio_uartx_sfe_s cn50xx;
+ struct cvmx_mio_uartx_sfe_s cn52xx;
+ struct cvmx_mio_uartx_sfe_s cn52xxp1;
+ struct cvmx_mio_uartx_sfe_s cn56xx;
+ struct cvmx_mio_uartx_sfe_s cn56xxp1;
+ struct cvmx_mio_uartx_sfe_s cn58xx;
+ struct cvmx_mio_uartx_sfe_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_srr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_srr_s {
+ uint64_t reserved_3_63:61;
+ uint64_t stfr:1;
+ uint64_t srfr:1;
+ uint64_t usr:1;
+ } s;
+ struct cvmx_mio_uartx_srr_s cn30xx;
+ struct cvmx_mio_uartx_srr_s cn31xx;
+ struct cvmx_mio_uartx_srr_s cn38xx;
+ struct cvmx_mio_uartx_srr_s cn38xxp2;
+ struct cvmx_mio_uartx_srr_s cn50xx;
+ struct cvmx_mio_uartx_srr_s cn52xx;
+ struct cvmx_mio_uartx_srr_s cn52xxp1;
+ struct cvmx_mio_uartx_srr_s cn56xx;
+ struct cvmx_mio_uartx_srr_s cn56xxp1;
+ struct cvmx_mio_uartx_srr_s cn58xx;
+ struct cvmx_mio_uartx_srr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_srt {
+ uint64_t u64;
+ struct cvmx_mio_uartx_srt_s {
+ uint64_t reserved_2_63:62;
+ uint64_t srt:2;
+ } s;
+ struct cvmx_mio_uartx_srt_s cn30xx;
+ struct cvmx_mio_uartx_srt_s cn31xx;
+ struct cvmx_mio_uartx_srt_s cn38xx;
+ struct cvmx_mio_uartx_srt_s cn38xxp2;
+ struct cvmx_mio_uartx_srt_s cn50xx;
+ struct cvmx_mio_uartx_srt_s cn52xx;
+ struct cvmx_mio_uartx_srt_s cn52xxp1;
+ struct cvmx_mio_uartx_srt_s cn56xx;
+ struct cvmx_mio_uartx_srt_s cn56xxp1;
+ struct cvmx_mio_uartx_srt_s cn58xx;
+ struct cvmx_mio_uartx_srt_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_srts {
+ uint64_t u64;
+ struct cvmx_mio_uartx_srts_s {
+ uint64_t reserved_1_63:63;
+ uint64_t srts:1;
+ } s;
+ struct cvmx_mio_uartx_srts_s cn30xx;
+ struct cvmx_mio_uartx_srts_s cn31xx;
+ struct cvmx_mio_uartx_srts_s cn38xx;
+ struct cvmx_mio_uartx_srts_s cn38xxp2;
+ struct cvmx_mio_uartx_srts_s cn50xx;
+ struct cvmx_mio_uartx_srts_s cn52xx;
+ struct cvmx_mio_uartx_srts_s cn52xxp1;
+ struct cvmx_mio_uartx_srts_s cn56xx;
+ struct cvmx_mio_uartx_srts_s cn56xxp1;
+ struct cvmx_mio_uartx_srts_s cn58xx;
+ struct cvmx_mio_uartx_srts_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_stt {
+ uint64_t u64;
+ struct cvmx_mio_uartx_stt_s {
+ uint64_t reserved_2_63:62;
+ uint64_t stt:2;
+ } s;
+ struct cvmx_mio_uartx_stt_s cn30xx;
+ struct cvmx_mio_uartx_stt_s cn31xx;
+ struct cvmx_mio_uartx_stt_s cn38xx;
+ struct cvmx_mio_uartx_stt_s cn38xxp2;
+ struct cvmx_mio_uartx_stt_s cn50xx;
+ struct cvmx_mio_uartx_stt_s cn52xx;
+ struct cvmx_mio_uartx_stt_s cn52xxp1;
+ struct cvmx_mio_uartx_stt_s cn56xx;
+ struct cvmx_mio_uartx_stt_s cn56xxp1;
+ struct cvmx_mio_uartx_stt_s cn58xx;
+ struct cvmx_mio_uartx_stt_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_tfl {
+ uint64_t u64;
+ struct cvmx_mio_uartx_tfl_s {
+ uint64_t reserved_7_63:57;
+ uint64_t tfl:7;
+ } s;
+ struct cvmx_mio_uartx_tfl_s cn30xx;
+ struct cvmx_mio_uartx_tfl_s cn31xx;
+ struct cvmx_mio_uartx_tfl_s cn38xx;
+ struct cvmx_mio_uartx_tfl_s cn38xxp2;
+ struct cvmx_mio_uartx_tfl_s cn50xx;
+ struct cvmx_mio_uartx_tfl_s cn52xx;
+ struct cvmx_mio_uartx_tfl_s cn52xxp1;
+ struct cvmx_mio_uartx_tfl_s cn56xx;
+ struct cvmx_mio_uartx_tfl_s cn56xxp1;
+ struct cvmx_mio_uartx_tfl_s cn58xx;
+ struct cvmx_mio_uartx_tfl_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_tfr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_tfr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t tfr:8;
+ } s;
+ struct cvmx_mio_uartx_tfr_s cn30xx;
+ struct cvmx_mio_uartx_tfr_s cn31xx;
+ struct cvmx_mio_uartx_tfr_s cn38xx;
+ struct cvmx_mio_uartx_tfr_s cn38xxp2;
+ struct cvmx_mio_uartx_tfr_s cn50xx;
+ struct cvmx_mio_uartx_tfr_s cn52xx;
+ struct cvmx_mio_uartx_tfr_s cn52xxp1;
+ struct cvmx_mio_uartx_tfr_s cn56xx;
+ struct cvmx_mio_uartx_tfr_s cn56xxp1;
+ struct cvmx_mio_uartx_tfr_s cn58xx;
+ struct cvmx_mio_uartx_tfr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_thr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_thr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t thr:8;
+ } s;
+ struct cvmx_mio_uartx_thr_s cn30xx;
+ struct cvmx_mio_uartx_thr_s cn31xx;
+ struct cvmx_mio_uartx_thr_s cn38xx;
+ struct cvmx_mio_uartx_thr_s cn38xxp2;
+ struct cvmx_mio_uartx_thr_s cn50xx;
+ struct cvmx_mio_uartx_thr_s cn52xx;
+ struct cvmx_mio_uartx_thr_s cn52xxp1;
+ struct cvmx_mio_uartx_thr_s cn56xx;
+ struct cvmx_mio_uartx_thr_s cn56xxp1;
+ struct cvmx_mio_uartx_thr_s cn58xx;
+ struct cvmx_mio_uartx_thr_s cn58xxp1;
+};
+
+union cvmx_mio_uartx_usr {
+ uint64_t u64;
+ struct cvmx_mio_uartx_usr_s {
+ uint64_t reserved_5_63:59;
+ uint64_t rff:1;
+ uint64_t rfne:1;
+ uint64_t tfe:1;
+ uint64_t tfnf:1;
+ uint64_t busy:1;
+ } s;
+ struct cvmx_mio_uartx_usr_s cn30xx;
+ struct cvmx_mio_uartx_usr_s cn31xx;
+ struct cvmx_mio_uartx_usr_s cn38xx;
+ struct cvmx_mio_uartx_usr_s cn38xxp2;
+ struct cvmx_mio_uartx_usr_s cn50xx;
+ struct cvmx_mio_uartx_usr_s cn52xx;
+ struct cvmx_mio_uartx_usr_s cn52xxp1;
+ struct cvmx_mio_uartx_usr_s cn56xx;
+ struct cvmx_mio_uartx_usr_s cn56xxp1;
+ struct cvmx_mio_uartx_usr_s cn58xx;
+ struct cvmx_mio_uartx_usr_s cn58xxp1;
+};
+
+union cvmx_mio_uart2_dlh {
+ uint64_t u64;
+ struct cvmx_mio_uart2_dlh_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dlh:8;
+ } s;
+ struct cvmx_mio_uart2_dlh_s cn52xx;
+ struct cvmx_mio_uart2_dlh_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_dll {
+ uint64_t u64;
+ struct cvmx_mio_uart2_dll_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dll:8;
+ } s;
+ struct cvmx_mio_uart2_dll_s cn52xx;
+ struct cvmx_mio_uart2_dll_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_far {
+ uint64_t u64;
+ struct cvmx_mio_uart2_far_s {
+ uint64_t reserved_1_63:63;
+ uint64_t far:1;
+ } s;
+ struct cvmx_mio_uart2_far_s cn52xx;
+ struct cvmx_mio_uart2_far_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_fcr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_fcr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t rxtrig:2;
+ uint64_t txtrig:2;
+ uint64_t reserved_3_3:1;
+ uint64_t txfr:1;
+ uint64_t rxfr:1;
+ uint64_t en:1;
+ } s;
+ struct cvmx_mio_uart2_fcr_s cn52xx;
+ struct cvmx_mio_uart2_fcr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_htx {
+ uint64_t u64;
+ struct cvmx_mio_uart2_htx_s {
+ uint64_t reserved_1_63:63;
+ uint64_t htx:1;
+ } s;
+ struct cvmx_mio_uart2_htx_s cn52xx;
+ struct cvmx_mio_uart2_htx_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_ier {
+ uint64_t u64;
+ struct cvmx_mio_uart2_ier_s {
+ uint64_t reserved_8_63:56;
+ uint64_t ptime:1;
+ uint64_t reserved_4_6:3;
+ uint64_t edssi:1;
+ uint64_t elsi:1;
+ uint64_t etbei:1;
+ uint64_t erbfi:1;
+ } s;
+ struct cvmx_mio_uart2_ier_s cn52xx;
+ struct cvmx_mio_uart2_ier_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_iir {
+ uint64_t u64;
+ struct cvmx_mio_uart2_iir_s {
+ uint64_t reserved_8_63:56;
+ uint64_t fen:2;
+ uint64_t reserved_4_5:2;
+ uint64_t iid:4;
+ } s;
+ struct cvmx_mio_uart2_iir_s cn52xx;
+ struct cvmx_mio_uart2_iir_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_lcr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_lcr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dlab:1;
+ uint64_t brk:1;
+ uint64_t reserved_5_5:1;
+ uint64_t eps:1;
+ uint64_t pen:1;
+ uint64_t stop:1;
+ uint64_t cls:2;
+ } s;
+ struct cvmx_mio_uart2_lcr_s cn52xx;
+ struct cvmx_mio_uart2_lcr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_lsr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_lsr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t ferr:1;
+ uint64_t temt:1;
+ uint64_t thre:1;
+ uint64_t bi:1;
+ uint64_t fe:1;
+ uint64_t pe:1;
+ uint64_t oe:1;
+ uint64_t dr:1;
+ } s;
+ struct cvmx_mio_uart2_lsr_s cn52xx;
+ struct cvmx_mio_uart2_lsr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_mcr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_mcr_s {
+ uint64_t reserved_6_63:58;
+ uint64_t afce:1;
+ uint64_t loop:1;
+ uint64_t out2:1;
+ uint64_t out1:1;
+ uint64_t rts:1;
+ uint64_t dtr:1;
+ } s;
+ struct cvmx_mio_uart2_mcr_s cn52xx;
+ struct cvmx_mio_uart2_mcr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_msr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_msr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t dcd:1;
+ uint64_t ri:1;
+ uint64_t dsr:1;
+ uint64_t cts:1;
+ uint64_t ddcd:1;
+ uint64_t teri:1;
+ uint64_t ddsr:1;
+ uint64_t dcts:1;
+ } s;
+ struct cvmx_mio_uart2_msr_s cn52xx;
+ struct cvmx_mio_uart2_msr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_rbr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_rbr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t rbr:8;
+ } s;
+ struct cvmx_mio_uart2_rbr_s cn52xx;
+ struct cvmx_mio_uart2_rbr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_rfl {
+ uint64_t u64;
+ struct cvmx_mio_uart2_rfl_s {
+ uint64_t reserved_7_63:57;
+ uint64_t rfl:7;
+ } s;
+ struct cvmx_mio_uart2_rfl_s cn52xx;
+ struct cvmx_mio_uart2_rfl_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_rfw {
+ uint64_t u64;
+ struct cvmx_mio_uart2_rfw_s {
+ uint64_t reserved_10_63:54;
+ uint64_t rffe:1;
+ uint64_t rfpe:1;
+ uint64_t rfwd:8;
+ } s;
+ struct cvmx_mio_uart2_rfw_s cn52xx;
+ struct cvmx_mio_uart2_rfw_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_sbcr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_sbcr_s {
+ uint64_t reserved_1_63:63;
+ uint64_t sbcr:1;
+ } s;
+ struct cvmx_mio_uart2_sbcr_s cn52xx;
+ struct cvmx_mio_uart2_sbcr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_scr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_scr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t scr:8;
+ } s;
+ struct cvmx_mio_uart2_scr_s cn52xx;
+ struct cvmx_mio_uart2_scr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_sfe {
+ uint64_t u64;
+ struct cvmx_mio_uart2_sfe_s {
+ uint64_t reserved_1_63:63;
+ uint64_t sfe:1;
+ } s;
+ struct cvmx_mio_uart2_sfe_s cn52xx;
+ struct cvmx_mio_uart2_sfe_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_srr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_srr_s {
+ uint64_t reserved_3_63:61;
+ uint64_t stfr:1;
+ uint64_t srfr:1;
+ uint64_t usr:1;
+ } s;
+ struct cvmx_mio_uart2_srr_s cn52xx;
+ struct cvmx_mio_uart2_srr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_srt {
+ uint64_t u64;
+ struct cvmx_mio_uart2_srt_s {
+ uint64_t reserved_2_63:62;
+ uint64_t srt:2;
+ } s;
+ struct cvmx_mio_uart2_srt_s cn52xx;
+ struct cvmx_mio_uart2_srt_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_srts {
+ uint64_t u64;
+ struct cvmx_mio_uart2_srts_s {
+ uint64_t reserved_1_63:63;
+ uint64_t srts:1;
+ } s;
+ struct cvmx_mio_uart2_srts_s cn52xx;
+ struct cvmx_mio_uart2_srts_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_stt {
+ uint64_t u64;
+ struct cvmx_mio_uart2_stt_s {
+ uint64_t reserved_2_63:62;
+ uint64_t stt:2;
+ } s;
+ struct cvmx_mio_uart2_stt_s cn52xx;
+ struct cvmx_mio_uart2_stt_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_tfl {
+ uint64_t u64;
+ struct cvmx_mio_uart2_tfl_s {
+ uint64_t reserved_7_63:57;
+ uint64_t tfl:7;
+ } s;
+ struct cvmx_mio_uart2_tfl_s cn52xx;
+ struct cvmx_mio_uart2_tfl_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_tfr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_tfr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t tfr:8;
+ } s;
+ struct cvmx_mio_uart2_tfr_s cn52xx;
+ struct cvmx_mio_uart2_tfr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_thr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_thr_s {
+ uint64_t reserved_8_63:56;
+ uint64_t thr:8;
+ } s;
+ struct cvmx_mio_uart2_thr_s cn52xx;
+ struct cvmx_mio_uart2_thr_s cn52xxp1;
+};
+
+union cvmx_mio_uart2_usr {
+ uint64_t u64;
+ struct cvmx_mio_uart2_usr_s {
+ uint64_t reserved_5_63:59;
+ uint64_t rff:1;
+ uint64_t rfne:1;
+ uint64_t tfe:1;
+ uint64_t tfnf:1;
+ uint64_t busy:1;
+ } s;
+ struct cvmx_mio_uart2_usr_s cn52xx;
+ struct cvmx_mio_uart2_usr_s cn52xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-packet.h b/arch/mips/include/asm/octeon/cvmx-packet.h
new file mode 100644
index 000000000000..38aefa1bab9d
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-packet.h
@@ -0,0 +1,61 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * Packet buffer defines.
+ */
+
+#ifndef __CVMX_PACKET_H__
+#define __CVMX_PACKET_H__
+
+/**
+ * This structure defines a buffer pointer on Octeon
+ */
+union cvmx_buf_ptr {
+ void *ptr;
+ uint64_t u64;
+ struct {
+ /* if set, invert the "free" pick of the overall
+ * packet. HW always sets this bit to 0 on inbound
+ * packet */
+ uint64_t i:1;
+
+ /* Indicates the amount to back up to get to the
+ * buffer start in cache lines. In most cases this is
+ * less than one complete cache line, so the value is
+ * zero */
+ uint64_t back:4;
+ /* The pool that the buffer came from / goes to */
+ uint64_t pool:3;
+ /* The size of the segment pointed to by addr (in bytes) */
+ uint64_t size:16;
+ /* Pointer to the first byte of the data, NOT buffer */
+ uint64_t addr:40;
+ } s;
+};
+
+#endif /* __CVMX_PACKET_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-pow-defs.h b/arch/mips/include/asm/octeon/cvmx-pow-defs.h
new file mode 100644
index 000000000000..2d82e24be51c
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-pow-defs.h
@@ -0,0 +1,698 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_POW_DEFS_H__
+#define __CVMX_POW_DEFS_H__
+
+#define CVMX_POW_BIST_STAT \
+ CVMX_ADD_IO_SEG(0x00016700000003F8ull)
+#define CVMX_POW_DS_PC \
+ CVMX_ADD_IO_SEG(0x0001670000000398ull)
+#define CVMX_POW_ECC_ERR \
+ CVMX_ADD_IO_SEG(0x0001670000000218ull)
+#define CVMX_POW_INT_CTL \
+ CVMX_ADD_IO_SEG(0x0001670000000220ull)
+#define CVMX_POW_IQ_CNTX(offset) \
+ CVMX_ADD_IO_SEG(0x0001670000000340ull + (((offset) & 7) * 8))
+#define CVMX_POW_IQ_COM_CNT \
+ CVMX_ADD_IO_SEG(0x0001670000000388ull)
+#define CVMX_POW_IQ_INT \
+ CVMX_ADD_IO_SEG(0x0001670000000238ull)
+#define CVMX_POW_IQ_INT_EN \
+ CVMX_ADD_IO_SEG(0x0001670000000240ull)
+#define CVMX_POW_IQ_THRX(offset) \
+ CVMX_ADD_IO_SEG(0x00016700000003A0ull + (((offset) & 7) * 8))
+#define CVMX_POW_NOS_CNT \
+ CVMX_ADD_IO_SEG(0x0001670000000228ull)
+#define CVMX_POW_NW_TIM \
+ CVMX_ADD_IO_SEG(0x0001670000000210ull)
+#define CVMX_POW_PF_RST_MSK \
+ CVMX_ADD_IO_SEG(0x0001670000000230ull)
+#define CVMX_POW_PP_GRP_MSKX(offset) \
+ CVMX_ADD_IO_SEG(0x0001670000000000ull + (((offset) & 15) * 8))
+#define CVMX_POW_QOS_RNDX(offset) \
+ CVMX_ADD_IO_SEG(0x00016700000001C0ull + (((offset) & 7) * 8))
+#define CVMX_POW_QOS_THRX(offset) \
+ CVMX_ADD_IO_SEG(0x0001670000000180ull + (((offset) & 7) * 8))
+#define CVMX_POW_TS_PC \
+ CVMX_ADD_IO_SEG(0x0001670000000390ull)
+#define CVMX_POW_WA_COM_PC \
+ CVMX_ADD_IO_SEG(0x0001670000000380ull)
+#define CVMX_POW_WA_PCX(offset) \
+ CVMX_ADD_IO_SEG(0x0001670000000300ull + (((offset) & 7) * 8))
+#define CVMX_POW_WQ_INT \
+ CVMX_ADD_IO_SEG(0x0001670000000200ull)
+#define CVMX_POW_WQ_INT_CNTX(offset) \
+ CVMX_ADD_IO_SEG(0x0001670000000100ull + (((offset) & 15) * 8))
+#define CVMX_POW_WQ_INT_PC \
+ CVMX_ADD_IO_SEG(0x0001670000000208ull)
+#define CVMX_POW_WQ_INT_THRX(offset) \
+ CVMX_ADD_IO_SEG(0x0001670000000080ull + (((offset) & 15) * 8))
+#define CVMX_POW_WS_PCX(offset) \
+ CVMX_ADD_IO_SEG(0x0001670000000280ull + (((offset) & 15) * 8))
+
+union cvmx_pow_bist_stat {
+ uint64_t u64;
+ struct cvmx_pow_bist_stat_s {
+ uint64_t reserved_32_63:32;
+ uint64_t pp:16;
+ uint64_t reserved_0_15:16;
+ } s;
+ struct cvmx_pow_bist_stat_cn30xx {
+ uint64_t reserved_17_63:47;
+ uint64_t pp:1;
+ uint64_t reserved_9_15:7;
+ uint64_t cam:1;
+ uint64_t nbt1:1;
+ uint64_t nbt0:1;
+ uint64_t index:1;
+ uint64_t fidx:1;
+ uint64_t nbr1:1;
+ uint64_t nbr0:1;
+ uint64_t pend:1;
+ uint64_t adr:1;
+ } cn30xx;
+ struct cvmx_pow_bist_stat_cn31xx {
+ uint64_t reserved_18_63:46;
+ uint64_t pp:2;
+ uint64_t reserved_9_15:7;
+ uint64_t cam:1;
+ uint64_t nbt1:1;
+ uint64_t nbt0:1;
+ uint64_t index:1;
+ uint64_t fidx:1;
+ uint64_t nbr1:1;
+ uint64_t nbr0:1;
+ uint64_t pend:1;
+ uint64_t adr:1;
+ } cn31xx;
+ struct cvmx_pow_bist_stat_cn38xx {
+ uint64_t reserved_32_63:32;
+ uint64_t pp:16;
+ uint64_t reserved_10_15:6;
+ uint64_t cam:1;
+ uint64_t nbt:1;
+ uint64_t index:1;
+ uint64_t fidx:1;
+ uint64_t nbr1:1;
+ uint64_t nbr0:1;
+ uint64_t pend1:1;
+ uint64_t pend0:1;
+ uint64_t adr1:1;
+ uint64_t adr0:1;
+ } cn38xx;
+ struct cvmx_pow_bist_stat_cn38xx cn38xxp2;
+ struct cvmx_pow_bist_stat_cn31xx cn50xx;
+ struct cvmx_pow_bist_stat_cn52xx {
+ uint64_t reserved_20_63:44;
+ uint64_t pp:4;
+ uint64_t reserved_9_15:7;
+ uint64_t cam:1;
+ uint64_t nbt1:1;
+ uint64_t nbt0:1;
+ uint64_t index:1;
+ uint64_t fidx:1;
+ uint64_t nbr1:1;
+ uint64_t nbr0:1;
+ uint64_t pend:1;
+ uint64_t adr:1;
+ } cn52xx;
+ struct cvmx_pow_bist_stat_cn52xx cn52xxp1;
+ struct cvmx_pow_bist_stat_cn56xx {
+ uint64_t reserved_28_63:36;
+ uint64_t pp:12;
+ uint64_t reserved_10_15:6;
+ uint64_t cam:1;
+ uint64_t nbt:1;
+ uint64_t index:1;
+ uint64_t fidx:1;
+ uint64_t nbr1:1;
+ uint64_t nbr0:1;
+ uint64_t pend1:1;
+ uint64_t pend0:1;
+ uint64_t adr1:1;
+ uint64_t adr0:1;
+ } cn56xx;
+ struct cvmx_pow_bist_stat_cn56xx cn56xxp1;
+ struct cvmx_pow_bist_stat_cn38xx cn58xx;
+ struct cvmx_pow_bist_stat_cn38xx cn58xxp1;
+};
+
+union cvmx_pow_ds_pc {
+ uint64_t u64;
+ struct cvmx_pow_ds_pc_s {
+ uint64_t reserved_32_63:32;
+ uint64_t ds_pc:32;
+ } s;
+ struct cvmx_pow_ds_pc_s cn30xx;
+ struct cvmx_pow_ds_pc_s cn31xx;
+ struct cvmx_pow_ds_pc_s cn38xx;
+ struct cvmx_pow_ds_pc_s cn38xxp2;
+ struct cvmx_pow_ds_pc_s cn50xx;
+ struct cvmx_pow_ds_pc_s cn52xx;
+ struct cvmx_pow_ds_pc_s cn52xxp1;
+ struct cvmx_pow_ds_pc_s cn56xx;
+ struct cvmx_pow_ds_pc_s cn56xxp1;
+ struct cvmx_pow_ds_pc_s cn58xx;
+ struct cvmx_pow_ds_pc_s cn58xxp1;
+};
+
+union cvmx_pow_ecc_err {
+ uint64_t u64;
+ struct cvmx_pow_ecc_err_s {
+ uint64_t reserved_45_63:19;
+ uint64_t iop_ie:13;
+ uint64_t reserved_29_31:3;
+ uint64_t iop:13;
+ uint64_t reserved_14_15:2;
+ uint64_t rpe_ie:1;
+ uint64_t rpe:1;
+ uint64_t reserved_9_11:3;
+ uint64_t syn:5;
+ uint64_t dbe_ie:1;
+ uint64_t sbe_ie:1;
+ uint64_t dbe:1;
+ uint64_t sbe:1;
+ } s;
+ struct cvmx_pow_ecc_err_s cn30xx;
+ struct cvmx_pow_ecc_err_cn31xx {
+ uint64_t reserved_14_63:50;
+ uint64_t rpe_ie:1;
+ uint64_t rpe:1;
+ uint64_t reserved_9_11:3;
+ uint64_t syn:5;
+ uint64_t dbe_ie:1;
+ uint64_t sbe_ie:1;
+ uint64_t dbe:1;
+ uint64_t sbe:1;
+ } cn31xx;
+ struct cvmx_pow_ecc_err_s cn38xx;
+ struct cvmx_pow_ecc_err_cn31xx cn38xxp2;
+ struct cvmx_pow_ecc_err_s cn50xx;
+ struct cvmx_pow_ecc_err_s cn52xx;
+ struct cvmx_pow_ecc_err_s cn52xxp1;
+ struct cvmx_pow_ecc_err_s cn56xx;
+ struct cvmx_pow_ecc_err_s cn56xxp1;
+ struct cvmx_pow_ecc_err_s cn58xx;
+ struct cvmx_pow_ecc_err_s cn58xxp1;
+};
+
+union cvmx_pow_int_ctl {
+ uint64_t u64;
+ struct cvmx_pow_int_ctl_s {
+ uint64_t reserved_6_63:58;
+ uint64_t pfr_dis:1;
+ uint64_t nbr_thr:5;
+ } s;
+ struct cvmx_pow_int_ctl_s cn30xx;
+ struct cvmx_pow_int_ctl_s cn31xx;
+ struct cvmx_pow_int_ctl_s cn38xx;
+ struct cvmx_pow_int_ctl_s cn38xxp2;
+ struct cvmx_pow_int_ctl_s cn50xx;
+ struct cvmx_pow_int_ctl_s cn52xx;
+ struct cvmx_pow_int_ctl_s cn52xxp1;
+ struct cvmx_pow_int_ctl_s cn56xx;
+ struct cvmx_pow_int_ctl_s cn56xxp1;
+ struct cvmx_pow_int_ctl_s cn58xx;
+ struct cvmx_pow_int_ctl_s cn58xxp1;
+};
+
+union cvmx_pow_iq_cntx {
+ uint64_t u64;
+ struct cvmx_pow_iq_cntx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t iq_cnt:32;
+ } s;
+ struct cvmx_pow_iq_cntx_s cn30xx;
+ struct cvmx_pow_iq_cntx_s cn31xx;
+ struct cvmx_pow_iq_cntx_s cn38xx;
+ struct cvmx_pow_iq_cntx_s cn38xxp2;
+ struct cvmx_pow_iq_cntx_s cn50xx;
+ struct cvmx_pow_iq_cntx_s cn52xx;
+ struct cvmx_pow_iq_cntx_s cn52xxp1;
+ struct cvmx_pow_iq_cntx_s cn56xx;
+ struct cvmx_pow_iq_cntx_s cn56xxp1;
+ struct cvmx_pow_iq_cntx_s cn58xx;
+ struct cvmx_pow_iq_cntx_s cn58xxp1;
+};
+
+union cvmx_pow_iq_com_cnt {
+ uint64_t u64;
+ struct cvmx_pow_iq_com_cnt_s {
+ uint64_t reserved_32_63:32;
+ uint64_t iq_cnt:32;
+ } s;
+ struct cvmx_pow_iq_com_cnt_s cn30xx;
+ struct cvmx_pow_iq_com_cnt_s cn31xx;
+ struct cvmx_pow_iq_com_cnt_s cn38xx;
+ struct cvmx_pow_iq_com_cnt_s cn38xxp2;
+ struct cvmx_pow_iq_com_cnt_s cn50xx;
+ struct cvmx_pow_iq_com_cnt_s cn52xx;
+ struct cvmx_pow_iq_com_cnt_s cn52xxp1;
+ struct cvmx_pow_iq_com_cnt_s cn56xx;
+ struct cvmx_pow_iq_com_cnt_s cn56xxp1;
+ struct cvmx_pow_iq_com_cnt_s cn58xx;
+ struct cvmx_pow_iq_com_cnt_s cn58xxp1;
+};
+
+union cvmx_pow_iq_int {
+ uint64_t u64;
+ struct cvmx_pow_iq_int_s {
+ uint64_t reserved_8_63:56;
+ uint64_t iq_int:8;
+ } s;
+ struct cvmx_pow_iq_int_s cn52xx;
+ struct cvmx_pow_iq_int_s cn52xxp1;
+ struct cvmx_pow_iq_int_s cn56xx;
+ struct cvmx_pow_iq_int_s cn56xxp1;
+};
+
+union cvmx_pow_iq_int_en {
+ uint64_t u64;
+ struct cvmx_pow_iq_int_en_s {
+ uint64_t reserved_8_63:56;
+ uint64_t int_en:8;
+ } s;
+ struct cvmx_pow_iq_int_en_s cn52xx;
+ struct cvmx_pow_iq_int_en_s cn52xxp1;
+ struct cvmx_pow_iq_int_en_s cn56xx;
+ struct cvmx_pow_iq_int_en_s cn56xxp1;
+};
+
+union cvmx_pow_iq_thrx {
+ uint64_t u64;
+ struct cvmx_pow_iq_thrx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t iq_thr:32;
+ } s;
+ struct cvmx_pow_iq_thrx_s cn52xx;
+ struct cvmx_pow_iq_thrx_s cn52xxp1;
+ struct cvmx_pow_iq_thrx_s cn56xx;
+ struct cvmx_pow_iq_thrx_s cn56xxp1;
+};
+
+union cvmx_pow_nos_cnt {
+ uint64_t u64;
+ struct cvmx_pow_nos_cnt_s {
+ uint64_t reserved_12_63:52;
+ uint64_t nos_cnt:12;
+ } s;
+ struct cvmx_pow_nos_cnt_cn30xx {
+ uint64_t reserved_7_63:57;
+ uint64_t nos_cnt:7;
+ } cn30xx;
+ struct cvmx_pow_nos_cnt_cn31xx {
+ uint64_t reserved_9_63:55;
+ uint64_t nos_cnt:9;
+ } cn31xx;
+ struct cvmx_pow_nos_cnt_s cn38xx;
+ struct cvmx_pow_nos_cnt_s cn38xxp2;
+ struct cvmx_pow_nos_cnt_cn31xx cn50xx;
+ struct cvmx_pow_nos_cnt_cn52xx {
+ uint64_t reserved_10_63:54;
+ uint64_t nos_cnt:10;
+ } cn52xx;
+ struct cvmx_pow_nos_cnt_cn52xx cn52xxp1;
+ struct cvmx_pow_nos_cnt_s cn56xx;
+ struct cvmx_pow_nos_cnt_s cn56xxp1;
+ struct cvmx_pow_nos_cnt_s cn58xx;
+ struct cvmx_pow_nos_cnt_s cn58xxp1;
+};
+
+union cvmx_pow_nw_tim {
+ uint64_t u64;
+ struct cvmx_pow_nw_tim_s {
+ uint64_t reserved_10_63:54;
+ uint64_t nw_tim:10;
+ } s;
+ struct cvmx_pow_nw_tim_s cn30xx;
+ struct cvmx_pow_nw_tim_s cn31xx;
+ struct cvmx_pow_nw_tim_s cn38xx;
+ struct cvmx_pow_nw_tim_s cn38xxp2;
+ struct cvmx_pow_nw_tim_s cn50xx;
+ struct cvmx_pow_nw_tim_s cn52xx;
+ struct cvmx_pow_nw_tim_s cn52xxp1;
+ struct cvmx_pow_nw_tim_s cn56xx;
+ struct cvmx_pow_nw_tim_s cn56xxp1;
+ struct cvmx_pow_nw_tim_s cn58xx;
+ struct cvmx_pow_nw_tim_s cn58xxp1;
+};
+
+union cvmx_pow_pf_rst_msk {
+ uint64_t u64;
+ struct cvmx_pow_pf_rst_msk_s {
+ uint64_t reserved_8_63:56;
+ uint64_t rst_msk:8;
+ } s;
+ struct cvmx_pow_pf_rst_msk_s cn50xx;
+ struct cvmx_pow_pf_rst_msk_s cn52xx;
+ struct cvmx_pow_pf_rst_msk_s cn52xxp1;
+ struct cvmx_pow_pf_rst_msk_s cn56xx;
+ struct cvmx_pow_pf_rst_msk_s cn56xxp1;
+ struct cvmx_pow_pf_rst_msk_s cn58xx;
+ struct cvmx_pow_pf_rst_msk_s cn58xxp1;
+};
+
+union cvmx_pow_pp_grp_mskx {
+ uint64_t u64;
+ struct cvmx_pow_pp_grp_mskx_s {
+ uint64_t reserved_48_63:16;
+ uint64_t qos7_pri:4;
+ uint64_t qos6_pri:4;
+ uint64_t qos5_pri:4;
+ uint64_t qos4_pri:4;
+ uint64_t qos3_pri:4;
+ uint64_t qos2_pri:4;
+ uint64_t qos1_pri:4;
+ uint64_t qos0_pri:4;
+ uint64_t grp_msk:16;
+ } s;
+ struct cvmx_pow_pp_grp_mskx_cn30xx {
+ uint64_t reserved_16_63:48;
+ uint64_t grp_msk:16;
+ } cn30xx;
+ struct cvmx_pow_pp_grp_mskx_cn30xx cn31xx;
+ struct cvmx_pow_pp_grp_mskx_cn30xx cn38xx;
+ struct cvmx_pow_pp_grp_mskx_cn30xx cn38xxp2;
+ struct cvmx_pow_pp_grp_mskx_s cn50xx;
+ struct cvmx_pow_pp_grp_mskx_s cn52xx;
+ struct cvmx_pow_pp_grp_mskx_s cn52xxp1;
+ struct cvmx_pow_pp_grp_mskx_s cn56xx;
+ struct cvmx_pow_pp_grp_mskx_s cn56xxp1;
+ struct cvmx_pow_pp_grp_mskx_s cn58xx;
+ struct cvmx_pow_pp_grp_mskx_s cn58xxp1;
+};
+
+union cvmx_pow_qos_rndx {
+ uint64_t u64;
+ struct cvmx_pow_qos_rndx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t rnd_p3:8;
+ uint64_t rnd_p2:8;
+ uint64_t rnd_p1:8;
+ uint64_t rnd:8;
+ } s;
+ struct cvmx_pow_qos_rndx_s cn30xx;
+ struct cvmx_pow_qos_rndx_s cn31xx;
+ struct cvmx_pow_qos_rndx_s cn38xx;
+ struct cvmx_pow_qos_rndx_s cn38xxp2;
+ struct cvmx_pow_qos_rndx_s cn50xx;
+ struct cvmx_pow_qos_rndx_s cn52xx;
+ struct cvmx_pow_qos_rndx_s cn52xxp1;
+ struct cvmx_pow_qos_rndx_s cn56xx;
+ struct cvmx_pow_qos_rndx_s cn56xxp1;
+ struct cvmx_pow_qos_rndx_s cn58xx;
+ struct cvmx_pow_qos_rndx_s cn58xxp1;
+};
+
+union cvmx_pow_qos_thrx {
+ uint64_t u64;
+ struct cvmx_pow_qos_thrx_s {
+ uint64_t reserved_60_63:4;
+ uint64_t des_cnt:12;
+ uint64_t buf_cnt:12;
+ uint64_t free_cnt:12;
+ uint64_t reserved_23_23:1;
+ uint64_t max_thr:11;
+ uint64_t reserved_11_11:1;
+ uint64_t min_thr:11;
+ } s;
+ struct cvmx_pow_qos_thrx_cn30xx {
+ uint64_t reserved_55_63:9;
+ uint64_t des_cnt:7;
+ uint64_t reserved_43_47:5;
+ uint64_t buf_cnt:7;
+ uint64_t reserved_31_35:5;
+ uint64_t free_cnt:7;
+ uint64_t reserved_18_23:6;
+ uint64_t max_thr:6;
+ uint64_t reserved_6_11:6;
+ uint64_t min_thr:6;
+ } cn30xx;
+ struct cvmx_pow_qos_thrx_cn31xx {
+ uint64_t reserved_57_63:7;
+ uint64_t des_cnt:9;
+ uint64_t reserved_45_47:3;
+ uint64_t buf_cnt:9;
+ uint64_t reserved_33_35:3;
+ uint64_t free_cnt:9;
+ uint64_t reserved_20_23:4;
+ uint64_t max_thr:8;
+ uint64_t reserved_8_11:4;
+ uint64_t min_thr:8;
+ } cn31xx;
+ struct cvmx_pow_qos_thrx_s cn38xx;
+ struct cvmx_pow_qos_thrx_s cn38xxp2;
+ struct cvmx_pow_qos_thrx_cn31xx cn50xx;
+ struct cvmx_pow_qos_thrx_cn52xx {
+ uint64_t reserved_58_63:6;
+ uint64_t des_cnt:10;
+ uint64_t reserved_46_47:2;
+ uint64_t buf_cnt:10;
+ uint64_t reserved_34_35:2;
+ uint64_t free_cnt:10;
+ uint64_t reserved_21_23:3;
+ uint64_t max_thr:9;
+ uint64_t reserved_9_11:3;
+ uint64_t min_thr:9;
+ } cn52xx;
+ struct cvmx_pow_qos_thrx_cn52xx cn52xxp1;
+ struct cvmx_pow_qos_thrx_s cn56xx;
+ struct cvmx_pow_qos_thrx_s cn56xxp1;
+ struct cvmx_pow_qos_thrx_s cn58xx;
+ struct cvmx_pow_qos_thrx_s cn58xxp1;
+};
+
+union cvmx_pow_ts_pc {
+ uint64_t u64;
+ struct cvmx_pow_ts_pc_s {
+ uint64_t reserved_32_63:32;
+ uint64_t ts_pc:32;
+ } s;
+ struct cvmx_pow_ts_pc_s cn30xx;
+ struct cvmx_pow_ts_pc_s cn31xx;
+ struct cvmx_pow_ts_pc_s cn38xx;
+ struct cvmx_pow_ts_pc_s cn38xxp2;
+ struct cvmx_pow_ts_pc_s cn50xx;
+ struct cvmx_pow_ts_pc_s cn52xx;
+ struct cvmx_pow_ts_pc_s cn52xxp1;
+ struct cvmx_pow_ts_pc_s cn56xx;
+ struct cvmx_pow_ts_pc_s cn56xxp1;
+ struct cvmx_pow_ts_pc_s cn58xx;
+ struct cvmx_pow_ts_pc_s cn58xxp1;
+};
+
+union cvmx_pow_wa_com_pc {
+ uint64_t u64;
+ struct cvmx_pow_wa_com_pc_s {
+ uint64_t reserved_32_63:32;
+ uint64_t wa_pc:32;
+ } s;
+ struct cvmx_pow_wa_com_pc_s cn30xx;
+ struct cvmx_pow_wa_com_pc_s cn31xx;
+ struct cvmx_pow_wa_com_pc_s cn38xx;
+ struct cvmx_pow_wa_com_pc_s cn38xxp2;
+ struct cvmx_pow_wa_com_pc_s cn50xx;
+ struct cvmx_pow_wa_com_pc_s cn52xx;
+ struct cvmx_pow_wa_com_pc_s cn52xxp1;
+ struct cvmx_pow_wa_com_pc_s cn56xx;
+ struct cvmx_pow_wa_com_pc_s cn56xxp1;
+ struct cvmx_pow_wa_com_pc_s cn58xx;
+ struct cvmx_pow_wa_com_pc_s cn58xxp1;
+};
+
+union cvmx_pow_wa_pcx {
+ uint64_t u64;
+ struct cvmx_pow_wa_pcx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t wa_pc:32;
+ } s;
+ struct cvmx_pow_wa_pcx_s cn30xx;
+ struct cvmx_pow_wa_pcx_s cn31xx;
+ struct cvmx_pow_wa_pcx_s cn38xx;
+ struct cvmx_pow_wa_pcx_s cn38xxp2;
+ struct cvmx_pow_wa_pcx_s cn50xx;
+ struct cvmx_pow_wa_pcx_s cn52xx;
+ struct cvmx_pow_wa_pcx_s cn52xxp1;
+ struct cvmx_pow_wa_pcx_s cn56xx;
+ struct cvmx_pow_wa_pcx_s cn56xxp1;
+ struct cvmx_pow_wa_pcx_s cn58xx;
+ struct cvmx_pow_wa_pcx_s cn58xxp1;
+};
+
+union cvmx_pow_wq_int {
+ uint64_t u64;
+ struct cvmx_pow_wq_int_s {
+ uint64_t reserved_32_63:32;
+ uint64_t iq_dis:16;
+ uint64_t wq_int:16;
+ } s;
+ struct cvmx_pow_wq_int_s cn30xx;
+ struct cvmx_pow_wq_int_s cn31xx;
+ struct cvmx_pow_wq_int_s cn38xx;
+ struct cvmx_pow_wq_int_s cn38xxp2;
+ struct cvmx_pow_wq_int_s cn50xx;
+ struct cvmx_pow_wq_int_s cn52xx;
+ struct cvmx_pow_wq_int_s cn52xxp1;
+ struct cvmx_pow_wq_int_s cn56xx;
+ struct cvmx_pow_wq_int_s cn56xxp1;
+ struct cvmx_pow_wq_int_s cn58xx;
+ struct cvmx_pow_wq_int_s cn58xxp1;
+};
+
+union cvmx_pow_wq_int_cntx {
+ uint64_t u64;
+ struct cvmx_pow_wq_int_cntx_s {
+ uint64_t reserved_28_63:36;
+ uint64_t tc_cnt:4;
+ uint64_t ds_cnt:12;
+ uint64_t iq_cnt:12;
+ } s;
+ struct cvmx_pow_wq_int_cntx_cn30xx {
+ uint64_t reserved_28_63:36;
+ uint64_t tc_cnt:4;
+ uint64_t reserved_19_23:5;
+ uint64_t ds_cnt:7;
+ uint64_t reserved_7_11:5;
+ uint64_t iq_cnt:7;
+ } cn30xx;
+ struct cvmx_pow_wq_int_cntx_cn31xx {
+ uint64_t reserved_28_63:36;
+ uint64_t tc_cnt:4;
+ uint64_t reserved_21_23:3;
+ uint64_t ds_cnt:9;
+ uint64_t reserved_9_11:3;
+ uint64_t iq_cnt:9;
+ } cn31xx;
+ struct cvmx_pow_wq_int_cntx_s cn38xx;
+ struct cvmx_pow_wq_int_cntx_s cn38xxp2;
+ struct cvmx_pow_wq_int_cntx_cn31xx cn50xx;
+ struct cvmx_pow_wq_int_cntx_cn52xx {
+ uint64_t reserved_28_63:36;
+ uint64_t tc_cnt:4;
+ uint64_t reserved_22_23:2;
+ uint64_t ds_cnt:10;
+ uint64_t reserved_10_11:2;
+ uint64_t iq_cnt:10;
+ } cn52xx;
+ struct cvmx_pow_wq_int_cntx_cn52xx cn52xxp1;
+ struct cvmx_pow_wq_int_cntx_s cn56xx;
+ struct cvmx_pow_wq_int_cntx_s cn56xxp1;
+ struct cvmx_pow_wq_int_cntx_s cn58xx;
+ struct cvmx_pow_wq_int_cntx_s cn58xxp1;
+};
+
+union cvmx_pow_wq_int_pc {
+ uint64_t u64;
+ struct cvmx_pow_wq_int_pc_s {
+ uint64_t reserved_60_63:4;
+ uint64_t pc:28;
+ uint64_t reserved_28_31:4;
+ uint64_t pc_thr:20;
+ uint64_t reserved_0_7:8;
+ } s;
+ struct cvmx_pow_wq_int_pc_s cn30xx;
+ struct cvmx_pow_wq_int_pc_s cn31xx;
+ struct cvmx_pow_wq_int_pc_s cn38xx;
+ struct cvmx_pow_wq_int_pc_s cn38xxp2;
+ struct cvmx_pow_wq_int_pc_s cn50xx;
+ struct cvmx_pow_wq_int_pc_s cn52xx;
+ struct cvmx_pow_wq_int_pc_s cn52xxp1;
+ struct cvmx_pow_wq_int_pc_s cn56xx;
+ struct cvmx_pow_wq_int_pc_s cn56xxp1;
+ struct cvmx_pow_wq_int_pc_s cn58xx;
+ struct cvmx_pow_wq_int_pc_s cn58xxp1;
+};
+
+union cvmx_pow_wq_int_thrx {
+ uint64_t u64;
+ struct cvmx_pow_wq_int_thrx_s {
+ uint64_t reserved_29_63:35;
+ uint64_t tc_en:1;
+ uint64_t tc_thr:4;
+ uint64_t reserved_23_23:1;
+ uint64_t ds_thr:11;
+ uint64_t reserved_11_11:1;
+ uint64_t iq_thr:11;
+ } s;
+ struct cvmx_pow_wq_int_thrx_cn30xx {
+ uint64_t reserved_29_63:35;
+ uint64_t tc_en:1;
+ uint64_t tc_thr:4;
+ uint64_t reserved_18_23:6;
+ uint64_t ds_thr:6;
+ uint64_t reserved_6_11:6;
+ uint64_t iq_thr:6;
+ } cn30xx;
+ struct cvmx_pow_wq_int_thrx_cn31xx {
+ uint64_t reserved_29_63:35;
+ uint64_t tc_en:1;
+ uint64_t tc_thr:4;
+ uint64_t reserved_20_23:4;
+ uint64_t ds_thr:8;
+ uint64_t reserved_8_11:4;
+ uint64_t iq_thr:8;
+ } cn31xx;
+ struct cvmx_pow_wq_int_thrx_s cn38xx;
+ struct cvmx_pow_wq_int_thrx_s cn38xxp2;
+ struct cvmx_pow_wq_int_thrx_cn31xx cn50xx;
+ struct cvmx_pow_wq_int_thrx_cn52xx {
+ uint64_t reserved_29_63:35;
+ uint64_t tc_en:1;
+ uint64_t tc_thr:4;
+ uint64_t reserved_21_23:3;
+ uint64_t ds_thr:9;
+ uint64_t reserved_9_11:3;
+ uint64_t iq_thr:9;
+ } cn52xx;
+ struct cvmx_pow_wq_int_thrx_cn52xx cn52xxp1;
+ struct cvmx_pow_wq_int_thrx_s cn56xx;
+ struct cvmx_pow_wq_int_thrx_s cn56xxp1;
+ struct cvmx_pow_wq_int_thrx_s cn58xx;
+ struct cvmx_pow_wq_int_thrx_s cn58xxp1;
+};
+
+union cvmx_pow_ws_pcx {
+ uint64_t u64;
+ struct cvmx_pow_ws_pcx_s {
+ uint64_t reserved_32_63:32;
+ uint64_t ws_pc:32;
+ } s;
+ struct cvmx_pow_ws_pcx_s cn30xx;
+ struct cvmx_pow_ws_pcx_s cn31xx;
+ struct cvmx_pow_ws_pcx_s cn38xx;
+ struct cvmx_pow_ws_pcx_s cn38xxp2;
+ struct cvmx_pow_ws_pcx_s cn50xx;
+ struct cvmx_pow_ws_pcx_s cn52xx;
+ struct cvmx_pow_ws_pcx_s cn52xxp1;
+ struct cvmx_pow_ws_pcx_s cn56xx;
+ struct cvmx_pow_ws_pcx_s cn56xxp1;
+ struct cvmx_pow_ws_pcx_s cn58xx;
+ struct cvmx_pow_ws_pcx_s cn58xxp1;
+};
+
+#endif
diff --git a/arch/mips/include/asm/octeon/cvmx-spinlock.h b/arch/mips/include/asm/octeon/cvmx-spinlock.h
new file mode 100644
index 000000000000..2fbf0871df11
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-spinlock.h
@@ -0,0 +1,232 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/**
+ * Implementation of spinlocks for Octeon CVMX. Although similar in
+ * function to Linux kernel spinlocks, they are not compatible.
+ * Octeon CVMX spinlocks are only used to synchronize with the boot
+ * monitor and other non-Linux programs running in the system.
+ */
+
+#ifndef __CVMX_SPINLOCK_H__
+#define __CVMX_SPINLOCK_H__
+
+#include "cvmx-asm.h"
+
+/* Spinlocks for Octeon */
+
+/* define these to enable recursive spinlock debugging */
+/*#define CVMX_SPINLOCK_DEBUG */
+
+/**
+ * Spinlocks for Octeon CVMX
+ */
+typedef struct {
+ volatile uint32_t value;
+} cvmx_spinlock_t;
+
+/* note - macros not expanded in inline ASM, so values hardcoded */
+#define CVMX_SPINLOCK_UNLOCKED_VAL 0
+#define CVMX_SPINLOCK_LOCKED_VAL 1
+
+#define CVMX_SPINLOCK_UNLOCKED_INITIALIZER {CVMX_SPINLOCK_UNLOCKED_VAL}
+
+/**
+ * Initialize a spinlock
+ *
+ * @lock: Lock to initialize
+ */
+static inline void cvmx_spinlock_init(cvmx_spinlock_t *lock)
+{
+ lock->value = CVMX_SPINLOCK_UNLOCKED_VAL;
+}
+
+/**
+ * Return non-zero if the spinlock is currently locked
+ *
+ * @lock: Lock to check
+ * Returns Non-zero if locked
+ */
+static inline int cvmx_spinlock_locked(cvmx_spinlock_t *lock)
+{
+ return lock->value != CVMX_SPINLOCK_UNLOCKED_VAL;
+}
+
+/**
+ * Releases lock
+ *
+ * @lock: pointer to lock structure
+ */
+static inline void cvmx_spinlock_unlock(cvmx_spinlock_t *lock)
+{
+ CVMX_SYNCWS;
+ lock->value = 0;
+ CVMX_SYNCWS;
+}
+
+/**
+ * Attempts to take the lock, but does not spin if lock is not available.
+ * May take some time to acquire the lock even if it is available
+ * due to the ll/sc not succeeding.
+ *
+ * @lock: pointer to lock structure
+ *
+ * Returns 0: lock successfully taken
+ * 1: lock not taken, held by someone else
+ * These return values match the Linux semantics.
+ */
+
+static inline unsigned int cvmx_spinlock_trylock(cvmx_spinlock_t *lock)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__(".set noreorder \n"
+ "1: ll %[tmp], %[val] \n"
+ /* if lock held, fail immediately */
+ " bnez %[tmp], 2f \n"
+ " li %[tmp], 1 \n"
+ " sc %[tmp], %[val] \n"
+ " beqz %[tmp], 1b \n"
+ " li %[tmp], 0 \n"
+ "2: \n"
+ ".set reorder \n" :
+ [val] "+m"(lock->value), [tmp] "=&r"(tmp)
+ : : "memory");
+
+ return tmp != 0; /* normalize to 0 or 1 */
+}
+
+/**
+ * Gets lock, spins until lock is taken
+ *
+ * @lock: pointer to lock structure
+ */
+static inline void cvmx_spinlock_lock(cvmx_spinlock_t *lock)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__(".set noreorder \n"
+ "1: ll %[tmp], %[val] \n"
+ " bnez %[tmp], 1b \n"
+ " li %[tmp], 1 \n"
+ " sc %[tmp], %[val] \n"
+ " beqz %[tmp], 1b \n"
+ " nop \n"
+ ".set reorder \n" :
+ [val] "+m"(lock->value), [tmp] "=&r"(tmp)
+ : : "memory");
+
+}
+
+/** ********************************************************************
+ * Bit spinlocks
+ * These spinlocks use a single bit (bit 31) of a 32 bit word for locking.
+ * The rest of the bits in the word are left undisturbed. This enables more
+ * compact data structures as only 1 bit is consumed for the lock.
+ *
+ */
+
+/**
+ * Gets lock, spins until lock is taken
+ * Preserves the low 31 bits of the 32 bit
+ * word used for the lock.
+ *
+ *
+ * @word: word to lock bit 31 of
+ */
+static inline void cvmx_spinlock_bit_lock(uint32_t *word)
+{
+ unsigned int tmp;
+ unsigned int sav;
+
+ __asm__ __volatile__(".set noreorder \n"
+ ".set noat \n"
+ "1: ll %[tmp], %[val] \n"
+ " bbit1 %[tmp], 31, 1b \n"
+ " li $at, 1 \n"
+ " ins %[tmp], $at, 31, 1 \n"
+ " sc %[tmp], %[val] \n"
+ " beqz %[tmp], 1b \n"
+ " nop \n"
+ ".set at \n"
+ ".set reorder \n" :
+ [val] "+m"(*word), [tmp] "=&r"(tmp), [sav] "=&r"(sav)
+ : : "memory");
+
+}
+
+/**
+ * Attempts to get lock, returns immediately with success/failure
+ * Preserves the low 31 bits of the 32 bit
+ * word used for the lock.
+ *
+ *
+ * @word: word to lock bit 31 of
+ * Returns 0: lock successfully taken
+ * 1: lock not taken, held by someone else
+ * These return values match the Linux semantics.
+ */
+static inline unsigned int cvmx_spinlock_bit_trylock(uint32_t *word)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__(".set noreorder\n\t"
+ ".set noat\n"
+ "1: ll %[tmp], %[val] \n"
+ /* if lock held, fail immediately */
+ " bbit1 %[tmp], 31, 2f \n"
+ " li $at, 1 \n"
+ " ins %[tmp], $at, 31, 1 \n"
+ " sc %[tmp], %[val] \n"
+ " beqz %[tmp], 1b \n"
+ " li %[tmp], 0 \n"
+ "2: \n"
+ ".set at \n"
+ ".set reorder \n" :
+ [val] "+m"(*word), [tmp] "=&r"(tmp)
+ : : "memory");
+
+ return tmp != 0; /* normalize to 0 or 1 */
+}
+
+/**
+ * Releases bit lock
+ *
+ * Unconditionally clears bit 31 of the lock word. Note that this is
+ * done non-atomically, as this implementation assumes that the rest
+ * of the bits in the word are protected by the lock.
+ *
+ * @word: word to unlock bit 31 in
+ */
+static inline void cvmx_spinlock_bit_unlock(uint32_t *word)
+{
+ CVMX_SYNCWS;
+ *word &= ~(1UL << 31);
+ CVMX_SYNCWS;
+}
+
+#endif /* __CVMX_SPINLOCK_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx-sysinfo.h b/arch/mips/include/asm/octeon/cvmx-sysinfo.h
new file mode 100644
index 000000000000..61dd5741afe4
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx-sysinfo.h
@@ -0,0 +1,152 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * This module provides system/board information obtained by the bootloader.
+ */
+
+#ifndef __CVMX_SYSINFO_H__
+#define __CVMX_SYSINFO_H__
+
+#define OCTEON_SERIAL_LEN 20
+/**
+ * Structure describing application specific information.
+ * __cvmx_app_init() populates this from the cvmx boot descriptor.
+ * This structure is private to simple executive applications, so
+ * no versioning is required.
+ *
+ * This structure must be provided with some fields set in order to
+ * use simple executive functions in other applications (Linux kernel,
+ * u-boot, etc.) The cvmx_sysinfo_minimal_initialize() function is
+ * provided to set the required values in these cases.
+ */
+struct cvmx_sysinfo {
+ /* System wide variables */
+ /* installed DRAM in system, in bytes */
+ uint64_t system_dram_size;
+
+ /* ptr to memory descriptor block */
+ void *phy_mem_desc_ptr;
+
+
+ /* Application image specific variables */
+ /* stack top address (virtual) */
+ uint64_t stack_top;
+ /* heap base address (virtual) */
+ uint64_t heap_base;
+ /* stack size in bytes */
+ uint32_t stack_size;
+ /* heap size in bytes */
+ uint32_t heap_size;
+ /* coremask defining cores running application */
+ uint32_t core_mask;
+ /* Deprecated, use cvmx_coremask_first_core() to select init core */
+ uint32_t init_core;
+
+ /* exception base address, as set by bootloader */
+ uint64_t exception_base_addr;
+
+ /* cpu clock speed in hz */
+ uint32_t cpu_clock_hz;
+
+ /* dram data rate in hz (data rate = 2 * clock rate */
+ uint32_t dram_data_rate_hz;
+
+
+ uint16_t board_type;
+ uint8_t board_rev_major;
+ uint8_t board_rev_minor;
+ uint8_t mac_addr_base[6];
+ uint8_t mac_addr_count;
+ char board_serial_number[OCTEON_SERIAL_LEN];
+ /*
+ * Several boards support compact flash on the Octeon boot
+ * bus. The CF memory spaces may be mapped to different
+ * addresses on different boards. These values will be 0 if
+ * CF is not present. Note that these addresses are physical
+ * addresses, and it is up to the application to use the
+ * proper addressing mode (XKPHYS, KSEG0, etc.)
+ */
+ uint64_t compact_flash_common_base_addr;
+ uint64_t compact_flash_attribute_base_addr;
+ /*
+ * Base address of the LED display (as on EBT3000 board) This
+ * will be 0 if LED display not present. Note that this
+ * address is a physical address, and it is up to the
+ * application to use the proper addressing mode (XKPHYS,
+ * KSEG0, etc.)
+ */
+ uint64_t led_display_base_addr;
+ /* DFA reference clock in hz (if applicable)*/
+ uint32_t dfa_ref_clock_hz;
+ /* configuration flags from bootloader */
+ uint32_t bootloader_config_flags;
+
+ /* Uart number used for console */
+ uint8_t console_uart_num;
+};
+
+/**
+ * This function returns the system/board information as obtained
+ * by the bootloader.
+ *
+ *
+ * Returns Pointer to the boot information structure
+ *
+ */
+
+extern struct cvmx_sysinfo *cvmx_sysinfo_get(void);
+
+/**
+ * This function is used in non-simple executive environments (such as
+ * Linux kernel, u-boot, etc.) to configure the minimal fields that
+ * are required to use simple executive files directly.
+ *
+ * Locking (if required) must be handled outside of this
+ * function
+ *
+ * @phy_mem_desc_ptr: Pointer to global physical memory descriptor
+ * (bootmem descriptor) @board_type: Octeon board
+ * type enumeration
+ *
+ * @board_rev_major:
+ * Board major revision
+ * @board_rev_minor:
+ * Board minor revision
+ * @cpu_clock_hz:
+ * CPU clock freqency in hertz
+ *
+ * Returns 0: Failure
+ * 1: success
+ */
+extern int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr,
+ uint16_t board_type,
+ uint8_t board_rev_major,
+ uint8_t board_rev_minor,
+ uint32_t cpu_clock_hz);
+
+#endif /* __CVMX_SYSINFO_H__ */
diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h
new file mode 100644
index 000000000000..03fddfa3e928
--- /dev/null
+++ b/arch/mips/include/asm/octeon/cvmx.h
@@ -0,0 +1,505 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+#ifndef __CVMX_H__
+#define __CVMX_H__
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include "cvmx-asm.h"
+#include "cvmx-packet.h"
+#include "cvmx-sysinfo.h"
+
+#include "cvmx-ciu-defs.h"
+#include "cvmx-gpio-defs.h"
+#include "cvmx-iob-defs.h"
+#include "cvmx-ipd-defs.h"
+#include "cvmx-l2c-defs.h"
+#include "cvmx-l2d-defs.h"
+#include "cvmx-l2t-defs.h"
+#include "cvmx-led-defs.h"
+#include "cvmx-mio-defs.h"
+#include "cvmx-pow-defs.h"
+
+#include "cvmx-bootinfo.h"
+#include "cvmx-bootmem.h"
+#include "cvmx-l2c.h"
+
+#ifndef CVMX_ENABLE_DEBUG_PRINTS
+#define CVMX_ENABLE_DEBUG_PRINTS 1
+#endif
+
+#if CVMX_ENABLE_DEBUG_PRINTS
+#define cvmx_dprintf printk
+#else
+#define cvmx_dprintf(...) {}
+#endif
+
+#define CVMX_MAX_CORES (16)
+#define CVMX_CACHE_LINE_SIZE (128) /* In bytes */
+#define CVMX_CACHE_LINE_MASK (CVMX_CACHE_LINE_SIZE - 1) /* In bytes */
+#define CVMX_CACHE_LINE_ALIGNED __attribute__ ((aligned(CVMX_CACHE_LINE_SIZE)))
+#define CAST64(v) ((long long)(long)(v))
+#define CASTPTR(type, v) ((type *)(long)(v))
+
+/*
+ * Returns processor ID, different Linux and simple exec versions
+ * provided in the cvmx-app-init*.c files.
+ */
+static inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure));
+static inline uint32_t cvmx_get_proc_id(void)
+{
+ uint32_t id;
+ asm("mfc0 %0, $15,0" : "=r"(id));
+ return id;
+}
+
+/* turn the variable name into a string */
+#define CVMX_TMP_STR(x) CVMX_TMP_STR2(x)
+#define CVMX_TMP_STR2(x) #x
+
+/**
+ * Builds a bit mask given the required size in bits.
+ *
+ * @bits: Number of bits in the mask
+ * Returns The mask
+ */ static inline uint64_t cvmx_build_mask(uint64_t bits)
+{
+ return ~((~0x0ull) << bits);
+}
+
+/**
+ * Builds a memory address for I/O based on the Major and Sub DID.
+ *
+ * @major_did: 5 bit major did
+ * @sub_did: 3 bit sub did
+ * Returns I/O base address
+ */
+static inline uint64_t cvmx_build_io_address(uint64_t major_did,
+ uint64_t sub_did)
+{
+ return (0x1ull << 48) | (major_did << 43) | (sub_did << 40);
+}
+
+/**
+ * Perform mask and shift to place the supplied value into
+ * the supplied bit rage.
+ *
+ * Example: cvmx_build_bits(39,24,value)
+ * <pre>
+ * 6 5 4 3 3 2 1
+ * 3 5 7 9 1 3 5 7 0
+ * +-------+-------+-------+-------+-------+-------+-------+------+
+ * 000000000000000000000000___________value000000000000000000000000
+ * </pre>
+ *
+ * @high_bit: Highest bit value can occupy (inclusive) 0-63
+ * @low_bit: Lowest bit value can occupy inclusive 0-high_bit
+ * @value: Value to use
+ * Returns Value masked and shifted
+ */
+static inline uint64_t cvmx_build_bits(uint64_t high_bit,
+ uint64_t low_bit, uint64_t value)
+{
+ return (value & cvmx_build_mask(high_bit - low_bit + 1)) << low_bit;
+}
+
+enum cvmx_mips_space {
+ CVMX_MIPS_SPACE_XKSEG = 3LL,
+ CVMX_MIPS_SPACE_XKPHYS = 2LL,
+ CVMX_MIPS_SPACE_XSSEG = 1LL,
+ CVMX_MIPS_SPACE_XUSEG = 0LL
+};
+
+/* These macros for use when using 32 bit pointers. */
+#define CVMX_MIPS32_SPACE_KSEG0 1l
+#define CVMX_ADD_SEG32(segment, add) \
+ (((int32_t)segment << 31) | (int32_t)(add))
+
+#define CVMX_IO_SEG CVMX_MIPS_SPACE_XKPHYS
+
+/* These macros simplify the process of creating common IO addresses */
+#define CVMX_ADD_SEG(segment, add) \
+ ((((uint64_t)segment) << 62) | (add))
+#ifndef CVMX_ADD_IO_SEG
+#define CVMX_ADD_IO_SEG(add) CVMX_ADD_SEG(CVMX_IO_SEG, (add))
+#endif
+
+/**
+ * Convert a memory pointer (void*) into a hardware compatable
+ * memory address (uint64_t). Octeon hardware widgets don't
+ * understand logical addresses.
+ *
+ * @ptr: C style memory pointer
+ * Returns Hardware physical address
+ */
+static inline uint64_t cvmx_ptr_to_phys(void *ptr)
+{
+ if (sizeof(void *) == 8) {
+ /*
+ * We're running in 64 bit mode. Normally this means
+ * that we can use 40 bits of address space (the
+ * hardware limit). Unfortunately there is one case
+ * were we need to limit this to 30 bits, sign
+ * extended 32 bit. Although these are 64 bits wide,
+ * only 30 bits can be used.
+ */
+ if ((CAST64(ptr) >> 62) == 3)
+ return CAST64(ptr) & cvmx_build_mask(30);
+ else
+ return CAST64(ptr) & cvmx_build_mask(40);
+ } else {
+ return (long)(ptr) & 0x1fffffff;
+ }
+}
+
+/**
+ * Convert a hardware physical address (uint64_t) into a
+ * memory pointer (void *).
+ *
+ * @physical_address:
+ * Hardware physical address to memory
+ * Returns Pointer to memory
+ */
+static inline void *cvmx_phys_to_ptr(uint64_t physical_address)
+{
+ if (sizeof(void *) == 8) {
+ /* Just set the top bit, avoiding any TLB uglyness */
+ return CASTPTR(void,
+ CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
+ physical_address));
+ } else {
+ return CASTPTR(void,
+ CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0,
+ physical_address));
+ }
+}
+
+/* The following #if controls the definition of the macro
+ CVMX_BUILD_WRITE64. This macro is used to build a store operation to
+ a full 64bit address. With a 64bit ABI, this can be done with a simple
+ pointer access. 32bit ABIs require more complicated assembly */
+
+/* We have a full 64bit ABI. Writing to a 64bit address can be done with
+ a simple volatile pointer */
+#define CVMX_BUILD_WRITE64(TYPE, ST) \
+static inline void cvmx_write64_##TYPE(uint64_t addr, TYPE##_t val) \
+{ \
+ *CASTPTR(volatile TYPE##_t, addr) = val; \
+}
+
+
+/* The following #if controls the definition of the macro
+ CVMX_BUILD_READ64. This macro is used to build a load operation from
+ a full 64bit address. With a 64bit ABI, this can be done with a simple
+ pointer access. 32bit ABIs require more complicated assembly */
+
+/* We have a full 64bit ABI. Writing to a 64bit address can be done with
+ a simple volatile pointer */
+#define CVMX_BUILD_READ64(TYPE, LT) \
+static inline TYPE##_t cvmx_read64_##TYPE(uint64_t addr) \
+{ \
+ return *CASTPTR(volatile TYPE##_t, addr); \
+}
+
+
+/* The following defines 8 functions for writing to a 64bit address. Each
+ takes two arguments, the address and the value to write.
+ cvmx_write64_int64 cvmx_write64_uint64
+ cvmx_write64_int32 cvmx_write64_uint32
+ cvmx_write64_int16 cvmx_write64_uint16
+ cvmx_write64_int8 cvmx_write64_uint8 */
+CVMX_BUILD_WRITE64(int64, "sd");
+CVMX_BUILD_WRITE64(int32, "sw");
+CVMX_BUILD_WRITE64(int16, "sh");
+CVMX_BUILD_WRITE64(int8, "sb");
+CVMX_BUILD_WRITE64(uint64, "sd");
+CVMX_BUILD_WRITE64(uint32, "sw");
+CVMX_BUILD_WRITE64(uint16, "sh");
+CVMX_BUILD_WRITE64(uint8, "sb");
+#define cvmx_write64 cvmx_write64_uint64
+
+/* The following defines 8 functions for reading from a 64bit address. Each
+ takes the address as the only argument
+ cvmx_read64_int64 cvmx_read64_uint64
+ cvmx_read64_int32 cvmx_read64_uint32
+ cvmx_read64_int16 cvmx_read64_uint16
+ cvmx_read64_int8 cvmx_read64_uint8 */
+CVMX_BUILD_READ64(int64, "ld");
+CVMX_BUILD_READ64(int32, "lw");
+CVMX_BUILD_READ64(int16, "lh");
+CVMX_BUILD_READ64(int8, "lb");
+CVMX_BUILD_READ64(uint64, "ld");
+CVMX_BUILD_READ64(uint32, "lw");
+CVMX_BUILD_READ64(uint16, "lhu");
+CVMX_BUILD_READ64(uint8, "lbu");
+#define cvmx_read64 cvmx_read64_uint64
+
+
+static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val)
+{
+ cvmx_write64(csr_addr, val);
+
+ /*
+ * Perform an immediate read after every write to an RSL
+ * register to force the write to complete. It doesn't matter
+ * what RSL read we do, so we choose CVMX_MIO_BOOT_BIST_STAT
+ * because it is fast and harmless.
+ */
+ if ((csr_addr >> 40) == (0x800118))
+ cvmx_read64(CVMX_MIO_BOOT_BIST_STAT);
+}
+
+static inline void cvmx_write_io(uint64_t io_addr, uint64_t val)
+{
+ cvmx_write64(io_addr, val);
+
+}
+
+static inline uint64_t cvmx_read_csr(uint64_t csr_addr)
+{
+ uint64_t val = cvmx_read64(csr_addr);
+ return val;
+}
+
+
+static inline void cvmx_send_single(uint64_t data)
+{
+ const uint64_t CVMX_IOBDMA_SENDSINGLE = 0xffffffffffffa200ull;
+ cvmx_write64(CVMX_IOBDMA_SENDSINGLE, data);
+}
+
+static inline void cvmx_read_csr_async(uint64_t scraddr, uint64_t csr_addr)
+{
+ union {
+ uint64_t u64;
+ struct {
+ uint64_t scraddr:8;
+ uint64_t len:8;
+ uint64_t addr:48;
+ } s;
+ } addr;
+ addr.u64 = csr_addr;
+ addr.s.scraddr = scraddr >> 3;
+ addr.s.len = 1;
+ cvmx_send_single(addr.u64);
+}
+
+/* Return true if Octeon is CN38XX pass 1 */
+static inline int cvmx_octeon_is_pass1(void)
+{
+#if OCTEON_IS_COMMON_BINARY()
+ return 0; /* Pass 1 isn't supported for common binaries */
+#else
+/* Now that we know we're built for a specific model, only check CN38XX */
+#if OCTEON_IS_MODEL(OCTEON_CN38XX)
+ return cvmx_get_proc_id() == OCTEON_CN38XX_PASS1;
+#else
+ return 0; /* Built for non CN38XX chip, we're not CN38XX pass1 */
+#endif
+#endif
+}
+
+static inline unsigned int cvmx_get_core_num(void)
+{
+ unsigned int core_num;
+ CVMX_RDHWRNV(core_num, 0);
+ return core_num;
+}
+
+/**
+ * Returns the number of bits set in the provided value.
+ * Simple wrapper for POP instruction.
+ *
+ * @val: 32 bit value to count set bits in
+ *
+ * Returns Number of bits set
+ */
+static inline uint32_t cvmx_pop(uint32_t val)
+{
+ uint32_t pop;
+ CVMX_POP(pop, val);
+ return pop;
+}
+
+/**
+ * Returns the number of bits set in the provided value.
+ * Simple wrapper for DPOP instruction.
+ *
+ * @val: 64 bit value to count set bits in
+ *
+ * Returns Number of bits set
+ */
+static inline int cvmx_dpop(uint64_t val)
+{
+ int pop;
+ CVMX_DPOP(pop, val);
+ return pop;
+}
+
+/**
+ * Provide current cycle counter as a return value
+ *
+ * Returns current cycle counter
+ */
+
+static inline uint64_t cvmx_get_cycle(void)
+{
+ uint64_t cycle;
+ CVMX_RDHWR(cycle, 31);
+ return cycle;
+}
+
+/**
+ * Reads a chip global cycle counter. This counts CPU cycles since
+ * chip reset. The counter is 64 bit.
+ * This register does not exist on CN38XX pass 1 silicion
+ *
+ * Returns Global chip cycle count since chip reset.
+ */
+static inline uint64_t cvmx_get_cycle_global(void)
+{
+ if (cvmx_octeon_is_pass1())
+ return 0;
+ else
+ return cvmx_read64(CVMX_IPD_CLK_COUNT);
+}
+
+/**
+ * This macro spins on a field waiting for it to reach a value. It
+ * is common in code to need to wait for a specific field in a CSR
+ * to match a specific value. Conceptually this macro expands to:
+ *
+ * 1) read csr at "address" with a csr typedef of "type"
+ * 2) Check if ("type".s."field" "op" "value")
+ * 3) If #2 isn't true loop to #1 unless too much time has passed.
+ */
+#define CVMX_WAIT_FOR_FIELD64(address, type, field, op, value, timeout_usec)\
+ ( \
+{ \
+ int result; \
+ do { \
+ uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \
+ cvmx_sysinfo_get()->cpu_clock_hz / 1000000; \
+ type c; \
+ while (1) { \
+ c.u64 = cvmx_read_csr(address); \
+ if ((c.s.field) op(value)) { \
+ result = 0; \
+ break; \
+ } else if (cvmx_get_cycle() > done) { \
+ result = -1; \
+ break; \
+ } else \
+ cvmx_wait(100); \
+ } \
+ } while (0); \
+ result; \
+})
+
+/***************************************************************************/
+
+static inline void cvmx_reset_octeon(void)
+{
+ union cvmx_ciu_soft_rst ciu_soft_rst;
+ ciu_soft_rst.u64 = 0;
+ ciu_soft_rst.s.soft_rst = 1;
+ cvmx_write_csr(CVMX_CIU_SOFT_RST, ciu_soft_rst.u64);
+}
+
+/* Return the number of cores available in the chip */
+static inline uint32_t cvmx_octeon_num_cores(void)
+{
+ uint32_t ciu_fuse = (uint32_t) cvmx_read_csr(CVMX_CIU_FUSE) & 0xffff;
+ return cvmx_pop(ciu_fuse);
+}
+
+/**
+ * Read a byte of fuse data
+ * @byte_addr: address to read
+ *
+ * Returns fuse value: 0 or 1
+ */
+static uint8_t cvmx_fuse_read_byte(int byte_addr)
+{
+ union cvmx_mio_fus_rcmd read_cmd;
+
+ read_cmd.u64 = 0;
+ read_cmd.s.addr = byte_addr;
+ read_cmd.s.pend = 1;
+ cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64);
+ while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD))
+ && read_cmd.s.pend)
+ ;
+ return read_cmd.s.dat;
+}
+
+/**
+ * Read a single fuse bit
+ *
+ * @fuse: Fuse number (0-1024)
+ *
+ * Returns fuse value: 0 or 1
+ */
+static inline int cvmx_fuse_read(int fuse)
+{
+ return (cvmx_fuse_read_byte(fuse >> 3) >> (fuse & 0x7)) & 1;
+}
+
+static inline int cvmx_octeon_model_CN36XX(void)
+{
+ return OCTEON_IS_MODEL(OCTEON_CN38XX)
+ && !cvmx_octeon_is_pass1()
+ && cvmx_fuse_read(264);
+}
+
+static inline int cvmx_octeon_zip_present(void)
+{
+ return octeon_has_feature(OCTEON_FEATURE_ZIP);
+}
+
+static inline int cvmx_octeon_dfa_present(void)
+{
+ if (!OCTEON_IS_MODEL(OCTEON_CN38XX)
+ && !OCTEON_IS_MODEL(OCTEON_CN31XX)
+ && !OCTEON_IS_MODEL(OCTEON_CN58XX))
+ return 0;
+ else if (OCTEON_IS_MODEL(OCTEON_CN3020))
+ return 0;
+ else if (cvmx_octeon_is_pass1())
+ return 1;
+ else
+ return !cvmx_fuse_read(120);
+}
+
+static inline int cvmx_octeon_crypto_present(void)
+{
+ return octeon_has_feature(OCTEON_FEATURE_CRYPTO);
+}
+
+#endif /* __CVMX_H__ */
diff --git a/arch/mips/include/asm/octeon/octeon-feature.h b/arch/mips/include/asm/octeon/octeon-feature.h
new file mode 100644
index 000000000000..04fac684069c
--- /dev/null
+++ b/arch/mips/include/asm/octeon/octeon-feature.h
@@ -0,0 +1,119 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * File defining checks for different Octeon features.
+ */
+
+#ifndef __OCTEON_FEATURE_H__
+#define __OCTEON_FEATURE_H__
+
+enum octeon_feature {
+ /*
+ * Octeon models in the CN5XXX family and higher support
+ * atomic add instructions to memory (saa/saad).
+ */
+ OCTEON_FEATURE_SAAD,
+ /* Does this Octeon support the ZIP offload engine? */
+ OCTEON_FEATURE_ZIP,
+ /* Does this Octeon support crypto acceleration using COP2? */
+ OCTEON_FEATURE_CRYPTO,
+ /* Does this Octeon support PCI express? */
+ OCTEON_FEATURE_PCIE,
+ /* Some Octeon models support internal memory for storing
+ * cryptographic keys */
+ OCTEON_FEATURE_KEY_MEMORY,
+ /* Octeon has a LED controller for banks of external LEDs */
+ OCTEON_FEATURE_LED_CONTROLLER,
+ /* Octeon has a trace buffer */
+ OCTEON_FEATURE_TRA,
+ /* Octeon has a management port */
+ OCTEON_FEATURE_MGMT_PORT,
+ /* Octeon has a raid unit */
+ OCTEON_FEATURE_RAID,
+ /* Octeon has a builtin USB */
+ OCTEON_FEATURE_USB,
+};
+
+static inline int cvmx_fuse_read(int fuse);
+
+/**
+ * Determine if the current Octeon supports a specific feature. These
+ * checks have been optimized to be fairly quick, but they should still
+ * be kept out of fast path code.
+ *
+ * @feature: Feature to check for. This should always be a constant so the
+ * compiler can remove the switch statement through optimization.
+ *
+ * Returns Non zero if the feature exists. Zero if the feature does not
+ * exist.
+ */
+static inline int octeon_has_feature(enum octeon_feature feature)
+{
+ switch (feature) {
+ case OCTEON_FEATURE_SAAD:
+ return !OCTEON_IS_MODEL(OCTEON_CN3XXX);
+
+ case OCTEON_FEATURE_ZIP:
+ if (OCTEON_IS_MODEL(OCTEON_CN30XX)
+ || OCTEON_IS_MODEL(OCTEON_CN50XX)
+ || OCTEON_IS_MODEL(OCTEON_CN52XX))
+ return 0;
+ else if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS1))
+ return 1;
+ else
+ return !cvmx_fuse_read(121);
+
+ case OCTEON_FEATURE_CRYPTO:
+ return !cvmx_fuse_read(90);
+
+ case OCTEON_FEATURE_PCIE:
+ return OCTEON_IS_MODEL(OCTEON_CN56XX)
+ || OCTEON_IS_MODEL(OCTEON_CN52XX);
+
+ case OCTEON_FEATURE_KEY_MEMORY:
+ case OCTEON_FEATURE_LED_CONTROLLER:
+ return OCTEON_IS_MODEL(OCTEON_CN38XX)
+ || OCTEON_IS_MODEL(OCTEON_CN58XX)
+ || OCTEON_IS_MODEL(OCTEON_CN56XX);
+ case OCTEON_FEATURE_TRA:
+ return !(OCTEON_IS_MODEL(OCTEON_CN30XX)
+ || OCTEON_IS_MODEL(OCTEON_CN50XX));
+ case OCTEON_FEATURE_MGMT_PORT:
+ return OCTEON_IS_MODEL(OCTEON_CN56XX)
+ || OCTEON_IS_MODEL(OCTEON_CN52XX);
+ case OCTEON_FEATURE_RAID:
+ return OCTEON_IS_MODEL(OCTEON_CN56XX)
+ || OCTEON_IS_MODEL(OCTEON_CN52XX);
+ case OCTEON_FEATURE_USB:
+ return !(OCTEON_IS_MODEL(OCTEON_CN38XX)
+ || OCTEON_IS_MODEL(OCTEON_CN58XX));
+ }
+ return 0;
+}
+
+#endif /* __OCTEON_FEATURE_H__ */
diff --git a/arch/mips/include/asm/octeon/octeon-model.h b/arch/mips/include/asm/octeon/octeon-model.h
new file mode 100644
index 000000000000..cf50336eca2e
--- /dev/null
+++ b/arch/mips/include/asm/octeon/octeon-model.h
@@ -0,0 +1,321 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ *
+ * File defining different Octeon model IDs and macros to
+ * compare them.
+ *
+ */
+
+#ifndef __OCTEON_MODEL_H__
+#define __OCTEON_MODEL_H__
+
+/* NOTE: These must match what is checked in common-config.mk */
+/* Defines to represent the different versions of Octeon. */
+
+/*
+ * IMPORTANT: When the default pass is updated for an Octeon Model,
+ * the corresponding change must also be made in the oct-sim script.
+ */
+
+/*
+ * The defines below should be used with the OCTEON_IS_MODEL() macro
+ * to determine what model of chip the software is running on. Models
+ * ending in 'XX' match multiple models (families), while specific
+ * models match only that model. If a pass (revision) is specified,
+ * then only that revision will be matched. Care should be taken when
+ * checking for both specific models and families that the specific
+ * models are checked for first. While these defines are similar to
+ * the processor ID, they are not intended to be used by anything
+ * other that the OCTEON_IS_MODEL framework, and the values are
+ * subject to change at anytime without notice.
+ *
+ * NOTE: only the OCTEON_IS_MODEL() macro/function and the OCTEON_CN*
+ * macros should be used outside of this file. All other macros are
+ * for internal use only, and may change without notice.
+ */
+
+/* Flag bits in top byte */
+/* Ignores revision in model checks */
+#define OM_IGNORE_REVISION 0x01000000
+/* Check submodels */
+#define OM_CHECK_SUBMODEL 0x02000000
+/* Match all models previous than the one specified */
+#define OM_MATCH_PREVIOUS_MODELS 0x04000000
+/* Ignores the minor revison on newer parts */
+#define OM_IGNORE_MINOR_REVISION 0x08000000
+#define OM_FLAG_MASK 0xff000000
+
+/*
+ * CN5XXX models with new revision encoding
+ */
+#define OCTEON_CN58XX_PASS1_0 0x000d0300
+#define OCTEON_CN58XX_PASS1_1 0x000d0301
+#define OCTEON_CN58XX_PASS1_2 0x000d0303
+#define OCTEON_CN58XX_PASS2_0 0x000d0308
+#define OCTEON_CN58XX_PASS2_1 0x000d0309
+#define OCTEON_CN58XX_PASS2_2 0x000d030a
+#define OCTEON_CN58XX_PASS2_3 0x000d030b
+
+#define OCTEON_CN58XX (OCTEON_CN58XX_PASS1_0 | OM_IGNORE_REVISION)
+#define OCTEON_CN58XX_PASS1_X (OCTEON_CN58XX_PASS1_0 \
+ | OM_IGNORE_MINOR_REVISION)
+#define OCTEON_CN58XX_PASS2_X (OCTEON_CN58XX_PASS2_0 \
+ | OM_IGNORE_MINOR_REVISION)
+#define OCTEON_CN58XX_PASS1 OCTEON_CN58XX_PASS1_X
+#define OCTEON_CN58XX_PASS2 OCTEON_CN58XX_PASS2_X
+
+#define OCTEON_CN56XX_PASS1_0 0x000d0400
+#define OCTEON_CN56XX_PASS1_1 0x000d0401
+#define OCTEON_CN56XX_PASS2_0 0x000d0408
+#define OCTEON_CN56XX_PASS2_1 0x000d0409
+
+#define OCTEON_CN56XX (OCTEON_CN56XX_PASS2_0 | OM_IGNORE_REVISION)
+#define OCTEON_CN56XX_PASS1_X (OCTEON_CN56XX_PASS1_0 \
+ | OM_IGNORE_MINOR_REVISION)
+#define OCTEON_CN56XX_PASS2_X (OCTEON_CN56XX_PASS2_0 \
+ | OM_IGNORE_MINOR_REVISION)
+#define OCTEON_CN56XX_PASS1 OCTEON_CN56XX_PASS1_X
+#define OCTEON_CN56XX_PASS2 OCTEON_CN56XX_PASS2_X
+
+#define OCTEON_CN57XX OCTEON_CN56XX
+#define OCTEON_CN57XX_PASS1 OCTEON_CN56XX_PASS1
+#define OCTEON_CN57XX_PASS2 OCTEON_CN56XX_PASS2
+
+#define OCTEON_CN55XX OCTEON_CN56XX
+#define OCTEON_CN55XX_PASS1 OCTEON_CN56XX_PASS1
+#define OCTEON_CN55XX_PASS2 OCTEON_CN56XX_PASS2
+
+#define OCTEON_CN54XX OCTEON_CN56XX
+#define OCTEON_CN54XX_PASS1 OCTEON_CN56XX_PASS1
+#define OCTEON_CN54XX_PASS2 OCTEON_CN56XX_PASS2
+
+#define OCTEON_CN50XX_PASS1_0 0x000d0600
+
+#define OCTEON_CN50XX (OCTEON_CN50XX_PASS1_0 | OM_IGNORE_REVISION)
+#define OCTEON_CN50XX_PASS1_X (OCTEON_CN50XX_PASS1_0 \
+ | OM_IGNORE_MINOR_REVISION)
+#define OCTEON_CN50XX_PASS1 OCTEON_CN50XX_PASS1_X
+
+/*
+ * NOTE: Octeon CN5000F model is not identifiable using the
+ * OCTEON_IS_MODEL() functions, but are treated as CN50XX.
+ */
+
+#define OCTEON_CN52XX_PASS1_0 0x000d0700
+#define OCTEON_CN52XX_PASS2_0 0x000d0708
+
+#define OCTEON_CN52XX (OCTEON_CN52XX_PASS2_0 | OM_IGNORE_REVISION)
+#define OCTEON_CN52XX_PASS1_X (OCTEON_CN52XX_PASS1_0 \
+ | OM_IGNORE_MINOR_REVISION)
+#define OCTEON_CN52XX_PASS2_X (OCTEON_CN52XX_PASS2_0 \
+ | OM_IGNORE_MINOR_REVISION)
+#define OCTEON_CN52XX_PASS1 OCTEON_CN52XX_PASS1_X
+#define OCTEON_CN52XX_PASS2 OCTEON_CN52XX_PASS2_X
+
+/*
+ * CN3XXX models with old revision enconding
+ */
+#define OCTEON_CN38XX_PASS1 0x000d0000
+#define OCTEON_CN38XX_PASS2 0x000d0001
+#define OCTEON_CN38XX_PASS3 0x000d0003
+#define OCTEON_CN38XX (OCTEON_CN38XX_PASS3 | OM_IGNORE_REVISION)
+
+#define OCTEON_CN36XX OCTEON_CN38XX
+#define OCTEON_CN36XX_PASS2 OCTEON_CN38XX_PASS2
+#define OCTEON_CN36XX_PASS3 OCTEON_CN38XX_PASS3
+
+/* The OCTEON_CN31XX matches CN31XX models and the CN3020 */
+#define OCTEON_CN31XX_PASS1 0x000d0100
+#define OCTEON_CN31XX_PASS1_1 0x000d0102
+#define OCTEON_CN31XX (OCTEON_CN31XX_PASS1 | OM_IGNORE_REVISION)
+
+/*
+ * This model is only used for internal checks, it is not a valid
+ * model for the OCTEON_MODEL environment variable. This matches the
+ * CN3010 and CN3005 but NOT the CN3020.
+ */
+#define OCTEON_CN30XX_PASS1 0x000d0200
+#define OCTEON_CN30XX_PASS1_1 0x000d0202
+#define OCTEON_CN30XX (OCTEON_CN30XX_PASS1 | OM_IGNORE_REVISION)
+
+#define OCTEON_CN3005_PASS1 (0x000d0210 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3005_PASS1_0 (0x000d0210 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3005_PASS1_1 (0x000d0212 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3005 (OCTEON_CN3005_PASS1 | OM_IGNORE_REVISION \
+ | OM_CHECK_SUBMODEL)
+
+#define OCTEON_CN3010_PASS1 (0x000d0200 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3010_PASS1_0 (0x000d0200 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3010_PASS1_1 (0x000d0202 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3010 (OCTEON_CN3010_PASS1 | OM_IGNORE_REVISION \
+ | OM_CHECK_SUBMODEL)
+
+#define OCTEON_CN3020_PASS1 (0x000d0110 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3020_PASS1_0 (0x000d0110 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3020_PASS1_1 (0x000d0112 | OM_CHECK_SUBMODEL)
+#define OCTEON_CN3020 (OCTEON_CN3020_PASS1 | OM_IGNORE_REVISION \
+ | OM_CHECK_SUBMODEL)
+
+
+
+/* This matches the complete family of CN3xxx CPUs, and not subsequent models */
+#define OCTEON_CN3XXX (OCTEON_CN58XX_PASS1_0 \
+ | OM_MATCH_PREVIOUS_MODELS \
+ | OM_IGNORE_REVISION)
+
+/* The revision byte (low byte) has two different encodings.
+ * CN3XXX:
+ *
+ * bits
+ * <7:5>: reserved (0)
+ * <4>: alternate package
+ * <3:0>: revision
+ *
+ * CN5XXX:
+ *
+ * bits
+ * <7>: reserved (0)
+ * <6>: alternate package
+ * <5:3>: major revision
+ * <2:0>: minor revision
+ *
+ */
+
+/* Masks used for the various types of model/family/revision matching */
+#define OCTEON_38XX_FAMILY_MASK 0x00ffff00
+#define OCTEON_38XX_FAMILY_REV_MASK 0x00ffff0f
+#define OCTEON_38XX_MODEL_MASK 0x00ffff10
+#define OCTEON_38XX_MODEL_REV_MASK (OCTEON_38XX_FAMILY_REV_MASK \
+ | OCTEON_38XX_MODEL_MASK)
+
+/* CN5XXX and later use different layout of bits in the revision ID field */
+#define OCTEON_58XX_FAMILY_MASK OCTEON_38XX_FAMILY_MASK
+#define OCTEON_58XX_FAMILY_REV_MASK 0x00ffff3f
+#define OCTEON_58XX_MODEL_MASK 0x00ffffc0
+#define OCTEON_58XX_MODEL_REV_MASK (OCTEON_58XX_FAMILY_REV_MASK \
+ | OCTEON_58XX_MODEL_MASK)
+#define OCTEON_58XX_MODEL_MINOR_REV_MASK (OCTEON_58XX_MODEL_REV_MASK \
+ & 0x00fffff8)
+
+#define __OCTEON_MATCH_MASK__(x, y, z) (((x) & (z)) == ((y) & (z)))
+
+/* NOTE: This is for internal (to this file) use only. */
+static inline int __OCTEON_IS_MODEL_COMPILE__(uint32_t arg_model,
+ uint32_t chip_model)
+{
+ uint32_t rev_and_sub = OM_IGNORE_REVISION | OM_CHECK_SUBMODEL;
+
+ if ((arg_model & OCTEON_38XX_FAMILY_MASK) < OCTEON_CN58XX_PASS1_0) {
+ if (((arg_model & OM_FLAG_MASK) == rev_and_sub) &&
+ __OCTEON_MATCH_MASK__(chip_model, arg_model,
+ OCTEON_38XX_MODEL_MASK))
+ return 1;
+ if (((arg_model & OM_FLAG_MASK) == 0) &&
+ __OCTEON_MATCH_MASK__(chip_model, arg_model,
+ OCTEON_38XX_FAMILY_REV_MASK))
+ return 1;
+ if (((arg_model & OM_FLAG_MASK) == OM_IGNORE_REVISION) &&
+ __OCTEON_MATCH_MASK__(chip_model, arg_model,
+ OCTEON_38XX_FAMILY_MASK))
+ return 1;
+ if (((arg_model & OM_FLAG_MASK) == OM_CHECK_SUBMODEL) &&
+ __OCTEON_MATCH_MASK__((chip_model), (arg_model),
+ OCTEON_38XX_MODEL_REV_MASK))
+ return 1;
+ if ((arg_model & OM_MATCH_PREVIOUS_MODELS) &&
+ ((chip_model & OCTEON_38XX_MODEL_MASK) <
+ (arg_model & OCTEON_38XX_MODEL_MASK)))
+ return 1;
+ } else {
+ if (((arg_model & OM_FLAG_MASK) == rev_and_sub) &&
+ __OCTEON_MATCH_MASK__((chip_model), (arg_model),
+ OCTEON_58XX_MODEL_MASK))
+ return 1;
+ if (((arg_model & OM_FLAG_MASK) == 0) &&
+ __OCTEON_MATCH_MASK__((chip_model), (arg_model),
+ OCTEON_58XX_FAMILY_REV_MASK))
+ return 1;
+ if (((arg_model & OM_FLAG_MASK) == OM_IGNORE_MINOR_REVISION) &&
+ __OCTEON_MATCH_MASK__((chip_model), (arg_model),
+ OCTEON_58XX_MODEL_MINOR_REV_MASK))
+ return 1;
+ if (((arg_model & OM_FLAG_MASK) == OM_IGNORE_REVISION) &&
+ __OCTEON_MATCH_MASK__((chip_model), (arg_model),
+ OCTEON_58XX_FAMILY_MASK))
+ return 1;
+ if (((arg_model & OM_FLAG_MASK) == OM_CHECK_SUBMODEL) &&
+ __OCTEON_MATCH_MASK__((chip_model), (arg_model),
+ OCTEON_58XX_MODEL_REV_MASK))
+ return 1;
+ if ((arg_model & OM_MATCH_PREVIOUS_MODELS) &&
+ ((chip_model & OCTEON_58XX_MODEL_MASK) <
+ (arg_model & OCTEON_58XX_MODEL_MASK)))
+ return 1;
+ }
+ return 0;
+}
+
+/* forward declarations */
+static inline uint32_t cvmx_get_proc_id(void) __attribute__ ((pure));
+static inline uint64_t cvmx_read_csr(uint64_t csr_addr);
+
+/* NOTE: This for internal use only!!!!! */
+static inline int __octeon_is_model_runtime__(uint32_t model)
+{
+ uint32_t cpuid = cvmx_get_proc_id();
+
+ /*
+ * Check for special case of mismarked 3005 samples. We only
+ * need to check if the sub model isn't being ignored.
+ */
+ if ((model & OM_CHECK_SUBMODEL) == OM_CHECK_SUBMODEL) {
+ if (cpuid == OCTEON_CN3010_PASS1 \
+ && (cvmx_read_csr(0x80011800800007B8ull) & (1ull << 34)))
+ cpuid |= 0x10;
+ }
+ return __OCTEON_IS_MODEL_COMPILE__(model, cpuid);
+}
+
+/*
+ * The OCTEON_IS_MODEL macro should be used for all Octeon model
+ * checking done in a program. This should be kept runtime if at all
+ * possible. Any compile time (#if OCTEON_IS_MODEL) usage must be
+ * condtionalized with OCTEON_IS_COMMON_BINARY() if runtime checking
+ * support is required.
+ */
+#define OCTEON_IS_MODEL(x) __octeon_is_model_runtime__(x)
+#define OCTEON_IS_COMMON_BINARY() 1
+#undef OCTEON_MODEL
+
+const char *octeon_model_get_string(uint32_t chip_id);
+const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer);
+
+#include "octeon-feature.h"
+
+#endif /* __OCTEON_MODEL_H__ */
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
new file mode 100644
index 000000000000..edc676084cda
--- /dev/null
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -0,0 +1,248 @@
+/*
+ * 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) 2004-2008 Cavium Networks
+ */
+#ifndef __ASM_OCTEON_OCTEON_H
+#define __ASM_OCTEON_OCTEON_H
+
+#include "cvmx.h"
+
+extern uint64_t octeon_bootmem_alloc_range_phys(uint64_t size,
+ uint64_t alignment,
+ uint64_t min_addr,
+ uint64_t max_addr,
+ int do_locking);
+extern void *octeon_bootmem_alloc(uint64_t size, uint64_t alignment,
+ int do_locking);
+extern void *octeon_bootmem_alloc_range(uint64_t size, uint64_t alignment,
+ uint64_t min_addr, uint64_t max_addr,
+ int do_locking);
+extern void *octeon_bootmem_alloc_named(uint64_t size, uint64_t alignment,
+ char *name);
+extern void *octeon_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
+ uint64_t max_addr, uint64_t align,
+ char *name);
+extern void *octeon_bootmem_alloc_named_address(uint64_t size, uint64_t address,
+ char *name);
+extern int octeon_bootmem_free_named(char *name);
+extern void octeon_bootmem_lock(void);
+extern void octeon_bootmem_unlock(void);
+
+extern int octeon_is_simulation(void);
+extern int octeon_is_pci_host(void);
+extern int octeon_usb_is_ref_clk(void);
+extern uint64_t octeon_get_clock_rate(void);
+extern const char *octeon_board_type_string(void);
+extern const char *octeon_get_pci_interrupts(void);
+extern int octeon_get_southbridge_interrupt(void);
+extern int octeon_get_boot_coremask(void);
+extern int octeon_get_boot_num_arguments(void);
+extern const char *octeon_get_boot_argument(int arg);
+extern void octeon_hal_setup_reserved32(void);
+extern void octeon_user_io_init(void);
+struct octeon_cop2_state;
+extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state);
+extern void octeon_crypto_disable(struct octeon_cop2_state *state,
+ unsigned long flags);
+
+extern void octeon_init_cvmcount(void);
+
+#define OCTEON_ARGV_MAX_ARGS 64
+#define OCTOEN_SERIAL_LEN 20
+
+struct octeon_boot_descriptor {
+ /* Start of block referenced by assembly code - do not change! */
+ uint32_t desc_version;
+ uint32_t desc_size;
+ uint64_t stack_top;
+ uint64_t heap_base;
+ uint64_t heap_end;
+ /* Only used by bootloader */
+ uint64_t entry_point;
+ uint64_t desc_vaddr;
+ /* End of This block referenced by assembly code - do not change! */
+ uint32_t exception_base_addr;
+ uint32_t stack_size;
+ uint32_t heap_size;
+ /* Argc count for application. */
+ uint32_t argc;
+ uint32_t argv[OCTEON_ARGV_MAX_ARGS];
+
+#define BOOT_FLAG_INIT_CORE (1 << 0)
+#define OCTEON_BL_FLAG_DEBUG (1 << 1)
+#define OCTEON_BL_FLAG_NO_MAGIC (1 << 2)
+ /* If set, use uart1 for console */
+#define OCTEON_BL_FLAG_CONSOLE_UART1 (1 << 3)
+ /* If set, use PCI console */
+#define OCTEON_BL_FLAG_CONSOLE_PCI (1 << 4)
+ /* Call exit on break on serial port */
+#define OCTEON_BL_FLAG_BREAK (1 << 5)
+
+ uint32_t flags;
+ uint32_t core_mask;
+ /* DRAM size in megabyes. */
+ uint32_t dram_size;
+ /* physical address of free memory descriptor block. */
+ uint32_t phy_mem_desc_addr;
+ /* used to pass flags from app to debugger. */
+ uint32_t debugger_flags_base_addr;
+ /* CPU clock speed, in hz. */
+ uint32_t eclock_hz;
+ /* DRAM clock speed, in hz. */
+ uint32_t dclock_hz;
+ /* SPI4 clock in hz. */
+ uint32_t spi_clock_hz;
+ uint16_t board_type;
+ uint8_t board_rev_major;
+ uint8_t board_rev_minor;
+ uint16_t chip_type;
+ uint8_t chip_rev_major;
+ uint8_t chip_rev_minor;
+ char board_serial_number[OCTOEN_SERIAL_LEN];
+ uint8_t mac_addr_base[6];
+ uint8_t mac_addr_count;
+ uint64_t cvmx_desc_vaddr;
+};
+
+union octeon_cvmemctl {
+ uint64_t u64;
+ struct {
+ /* RO 1 = BIST fail, 0 = BIST pass */
+ uint64_t tlbbist:1;
+ /* RO 1 = BIST fail, 0 = BIST pass */
+ uint64_t l1cbist:1;
+ /* RO 1 = BIST fail, 0 = BIST pass */
+ uint64_t l1dbist:1;
+ /* RO 1 = BIST fail, 0 = BIST pass */
+ uint64_t dcmbist:1;
+ /* RO 1 = BIST fail, 0 = BIST pass */
+ uint64_t ptgbist:1;
+ /* RO 1 = BIST fail, 0 = BIST pass */
+ uint64_t wbfbist:1;
+ /* Reserved */
+ uint64_t reserved:22;
+ /* R/W If set, marked write-buffer entries time out
+ * the same as as other entries; if clear, marked
+ * write-buffer entries use the maximum timeout. */
+ uint64_t dismarkwblongto:1;
+ /* R/W If set, a merged store does not clear the
+ * write-buffer entry timeout state. */
+ uint64_t dismrgclrwbto:1;
+ /* R/W Two bits that are the MSBs of the resultant
+ * CVMSEG LM word location for an IOBDMA. The other 8
+ * bits come from the SCRADDR field of the IOBDMA. */
+ uint64_t iobdmascrmsb:2;
+ /* R/W If set, SYNCWS and SYNCS only order marked
+ * stores; if clear, SYNCWS and SYNCS only order
+ * unmarked stores. SYNCWSMARKED has no effect when
+ * DISSYNCWS is set. */
+ uint64_t syncwsmarked:1;
+ /* R/W If set, SYNCWS acts as SYNCW and SYNCS acts as
+ * SYNC. */
+ uint64_t dissyncws:1;
+ /* R/W If set, no stall happens on write buffer
+ * full. */
+ uint64_t diswbfst:1;
+ /* R/W If set (and SX set), supervisor-level
+ * loads/stores can use XKPHYS addresses with
+ * VA<48>==0 */
+ uint64_t xkmemenas:1;
+ /* R/W If set (and UX set), user-level loads/stores
+ * can use XKPHYS addresses with VA<48>==0 */
+ uint64_t xkmemenau:1;
+ /* R/W If set (and SX set), supervisor-level
+ * loads/stores can use XKPHYS addresses with
+ * VA<48>==1 */
+ uint64_t xkioenas:1;
+ /* R/W If set (and UX set), user-level loads/stores
+ * can use XKPHYS addresses with VA<48>==1 */
+ uint64_t xkioenau:1;
+ /* R/W If set, all stores act as SYNCW (NOMERGE must
+ * be set when this is set) RW, reset to 0. */
+ uint64_t allsyncw:1;
+ /* R/W If set, no stores merge, and all stores reach
+ * the coherent bus in order. */
+ uint64_t nomerge:1;
+ /* R/W Selects the bit in the counter used for DID
+ * time-outs 0 = 231, 1 = 230, 2 = 229, 3 =
+ * 214. Actual time-out is between 1x and 2x this
+ * interval. For example, with DIDTTO=3, expiration
+ * interval is between 16K and 32K. */
+ uint64_t didtto:2;
+ /* R/W If set, the (mem) CSR clock never turns off. */
+ uint64_t csrckalwys:1;
+ /* R/W If set, mclk never turns off. */
+ uint64_t mclkalwys:1;
+ /* R/W Selects the bit in the counter used for write
+ * buffer flush time-outs (WBFLT+11) is the bit
+ * position in an internal counter used to determine
+ * expiration. The write buffer expires between 1x and
+ * 2x this interval. For example, with WBFLT = 0, a
+ * write buffer expires between 2K and 4K cycles after
+ * the write buffer entry is allocated. */
+ uint64_t wbfltime:3;
+ /* R/W If set, do not put Istream in the L2 cache. */
+ uint64_t istrnol2:1;
+ /* R/W The write buffer threshold. */
+ uint64_t wbthresh:4;
+ /* Reserved */
+ uint64_t reserved2:2;
+ /* R/W If set, CVMSEG is available for loads/stores in
+ * kernel/debug mode. */
+ uint64_t cvmsegenak:1;
+ /* R/W If set, CVMSEG is available for loads/stores in
+ * supervisor mode. */
+ uint64_t cvmsegenas:1;
+ /* R/W If set, CVMSEG is available for loads/stores in
+ * user mode. */
+ uint64_t cvmsegenau:1;
+ /* R/W Size of local memory in cache blocks, 54 (6912
+ * bytes) is max legal value. */
+ uint64_t lmemsz:6;
+ } s;
+};
+
+struct octeon_cf_data {
+ unsigned long base_region_bias;
+ unsigned int base_region; /* The chip select region used by CF */
+ int is16bit; /* 0 - 8bit, !0 - 16bit */
+ int dma_engine; /* -1 for no DMA */
+};
+
+extern void octeon_write_lcd(const char *s);
+extern void octeon_check_cpu_bist(void);
+extern int octeon_get_boot_debug_flag(void);
+extern int octeon_get_boot_uart(void);
+
+struct uart_port;
+extern unsigned int octeon_serial_in(struct uart_port *, int);
+extern void octeon_serial_out(struct uart_port *, int, int);
+
+/**
+ * Write a 32bit value to the Octeon NPI register space
+ *
+ * @address: Address to write to
+ * @val: Value to write
+ */
+static inline void octeon_npi_write32(uint64_t address, uint32_t val)
+{
+ cvmx_write64_uint32(address ^ 4, val);
+ cvmx_read64_uint32(address ^ 4);
+}
+
+
+/**
+ * Read a 32bit value from the Octeon NPI register space
+ *
+ * @address: Address to read
+ * Returns The result
+ */
+static inline uint32_t octeon_npi_read32(uint64_t address)
+{
+ return cvmx_read64_uint32(address ^ 4);
+}
+
+#endif /* __ASM_OCTEON_OCTEON_H */
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 18ee58e39445..0f926aa0cb47 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -118,6 +118,60 @@ union mips_watch_reg_state {
struct mips3264_watch_reg_state mips3264;
};
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+
+struct octeon_cop2_state {
+ /* DMFC2 rt, 0x0201 */
+ unsigned long cop2_crc_iv;
+ /* DMFC2 rt, 0x0202 (Set with DMTC2 rt, 0x1202) */
+ unsigned long cop2_crc_length;
+ /* DMFC2 rt, 0x0200 (set with DMTC2 rt, 0x4200) */
+ unsigned long cop2_crc_poly;
+ /* DMFC2 rt, 0x0402; DMFC2 rt, 0x040A */
+ unsigned long cop2_llm_dat[2];
+ /* DMFC2 rt, 0x0084 */
+ unsigned long cop2_3des_iv;
+ /* DMFC2 rt, 0x0080; DMFC2 rt, 0x0081; DMFC2 rt, 0x0082 */
+ unsigned long cop2_3des_key[3];
+ /* DMFC2 rt, 0x0088 (Set with DMTC2 rt, 0x0098) */
+ unsigned long cop2_3des_result;
+ /* DMFC2 rt, 0x0111 (FIXME: Read Pass1 Errata) */
+ unsigned long cop2_aes_inp0;
+ /* DMFC2 rt, 0x0102; DMFC2 rt, 0x0103 */
+ unsigned long cop2_aes_iv[2];
+ /* DMFC2 rt, 0x0104; DMFC2 rt, 0x0105; DMFC2 rt, 0x0106; DMFC2
+ * rt, 0x0107 */
+ unsigned long cop2_aes_key[4];
+ /* DMFC2 rt, 0x0110 */
+ unsigned long cop2_aes_keylen;
+ /* DMFC2 rt, 0x0100; DMFC2 rt, 0x0101 */
+ unsigned long cop2_aes_result[2];
+ /* DMFC2 rt, 0x0240; DMFC2 rt, 0x0241; DMFC2 rt, 0x0242; DMFC2
+ * rt, 0x0243; DMFC2 rt, 0x0244; DMFC2 rt, 0x0245; DMFC2 rt,
+ * 0x0246; DMFC2 rt, 0x0247; DMFC2 rt, 0x0248; DMFC2 rt,
+ * 0x0249; DMFC2 rt, 0x024A; DMFC2 rt, 0x024B; DMFC2 rt,
+ * 0x024C; DMFC2 rt, 0x024D; DMFC2 rt, 0x024E - Pass2 */
+ unsigned long cop2_hsh_datw[15];
+ /* DMFC2 rt, 0x0250; DMFC2 rt, 0x0251; DMFC2 rt, 0x0252; DMFC2
+ * rt, 0x0253; DMFC2 rt, 0x0254; DMFC2 rt, 0x0255; DMFC2 rt,
+ * 0x0256; DMFC2 rt, 0x0257 - Pass2 */
+ unsigned long cop2_hsh_ivw[8];
+ /* DMFC2 rt, 0x0258; DMFC2 rt, 0x0259 - Pass2 */
+ unsigned long cop2_gfm_mult[2];
+ /* DMFC2 rt, 0x025E - Pass2 */
+ unsigned long cop2_gfm_poly;
+ /* DMFC2 rt, 0x025A; DMFC2 rt, 0x025B - Pass2 */
+ unsigned long cop2_gfm_result[2];
+};
+#define INIT_OCTEON_COP2 {0,}
+
+struct octeon_cvmseg_state {
+ unsigned long cvmseg[CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE]
+ [cpu_dcache_line_size() / sizeof(unsigned long)];
+};
+
+#endif
+
typedef struct {
unsigned long seg;
} mm_segment_t;
@@ -160,6 +214,10 @@ struct thread_struct {
unsigned long trap_no;
unsigned long irix_trampoline; /* Wheee... */
unsigned long irix_oldctx;
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ struct octeon_cop2_state cp2 __attribute__ ((__aligned__(128)));
+ struct octeon_cvmseg_state cvmseg __attribute__ ((__aligned__(128)));
+#endif
struct mips_abi *abi;
};
@@ -171,6 +229,13 @@ struct thread_struct {
#define FPAFF_INIT
#endif /* CONFIG_MIPS_MT_FPAFF */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+#define OCTEON_INIT \
+ .cp2 = INIT_OCTEON_COP2,
+#else
+#define OCTEON_INIT
+#endif /* CONFIG_CPU_CAVIUM_OCTEON */
+
#define INIT_THREAD { \
/* \
* Saved main processor registers \
@@ -221,6 +286,10 @@ struct thread_struct {
.trap_no = 0, \
.irix_trampoline = 0, \
.irix_oldctx = 0, \
+ /* \
+ * Cavium Octeon specifics (null if not Octeon) \
+ */ \
+ OCTEON_INIT \
}
struct task_struct;
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index c2c8bac43307..ce47118e52b7 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -48,6 +48,10 @@ struct pt_regs {
#ifdef CONFIG_MIPS_MT_SMTC
unsigned long cp0_tcstatus;
#endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ unsigned long long mpl[3]; /* MTM{0,1,2} */
+ unsigned long long mtp[3]; /* MTP{0,1,2} */
+#endif
} __attribute__ ((aligned (8)));
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
@@ -101,7 +105,7 @@ struct pt_watch_regs {
enum pt_watch_style style;
union {
struct mips32_watch_regs mips32;
- struct mips32_watch_regs mips64;
+ struct mips64_watch_regs mips64;
};
};
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 0ff5b523ea77..40e5ef1d4d26 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -37,9 +37,9 @@ extern int __cpu_logical_map[NR_CPUS];
#define SMP_RESCHEDULE_YOURSELF 0x1 /* XXX braindead */
#define SMP_CALL_FUNCTION 0x2
+/* Octeon - Tell another core to flush its icache */
+#define SMP_ICACHE_FLUSH 0x4
-extern cpumask_t phys_cpu_present_map;
-#define cpu_possible_map phys_cpu_present_map
extern void asmlinkage smp_bootstrap(void);
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 4c37c4e5f72e..db0fa7b5aeaf 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -194,6 +194,19 @@
LONG_S $31, PT_R31(sp)
ori $28, sp, _THREAD_MASK
xori $28, _THREAD_MASK
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ .set mips64
+ pref 0, 0($28) /* Prefetch the current pointer */
+ pref 0, PT_R31(sp) /* Prefetch the $31(ra) */
+ /* The Octeon multiplier state is affected by general multiply
+ instructions. It must be saved before and kernel code might
+ corrupt it */
+ jal octeon_mult_save
+ LONG_L v1, 0($28) /* Load the current pointer */
+ /* Restore $31(ra) that was changed by the jal */
+ LONG_L ra, PT_R31(sp)
+ pref 0, 0(v1) /* Prefetch the current thread */
+#endif
.set pop
.endm
@@ -324,6 +337,10 @@
DVPE 5 # dvpe a1
jal mips_ihb
#endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ /* Restore the Octeon multiplier state */
+ jal octeon_mult_restore
+#endif
mfc0 a0, CP0_STATUS
ori a0, STATMASK
xori a0, STATMASK
diff --git a/arch/mips/include/asm/swab.h b/arch/mips/include/asm/swab.h
new file mode 100644
index 000000000000..88f1f7d555cb
--- /dev/null
+++ b/arch/mips/include/asm/swab.h
@@ -0,0 +1,55 @@
+/*
+ * 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) 1996, 99, 2003 by Ralf Baechle
+ */
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#include <linux/compiler.h>
+#include <asm/types.h>
+
+#define __SWAB_64_THRU_32__
+
+#ifdef CONFIG_CPU_MIPSR2
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
+{
+ __asm__(
+ " wsbh %0, %1 \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+ __asm__(
+ " wsbh %0, %1 \n"
+ " rotr %0, %0, 16 \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+#define __arch_swab32 __arch_swab32
+
+#ifdef CONFIG_CPU_MIPS64_R2
+static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
+{
+ __asm__(
+ " dsbh %0, %1\n"
+ " dshd %0, %0"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+#define __arch_swab64 __arch_swab64
+#endif /* CONFIG_CPU_MIPS64_R2 */
+#endif /* CONFIG_CPU_MIPSR2 */
+#endif /* _ASM_SWAB_H */
diff --git a/arch/mips/include/asm/termios.h b/arch/mips/include/asm/termios.h
index a275661fa7e1..8f77f774a2a0 100644
--- a/arch/mips/include/asm/termios.h
+++ b/arch/mips/include/asm/termios.h
@@ -9,6 +9,7 @@
#ifndef _ASM_TERMIOS_H
#define _ASM_TERMIOS_H
+#include <linux/errno.h>
#include <asm/termbits.h>
#include <asm/ioctls.h>
@@ -94,38 +95,81 @@ struct termio {
/*
* Translate a "termio" structure into a "termios". Ugh.
*/
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
- unsigned short tmp; \
- get_user(tmp, &(termio)->c_iflag); \
- (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
- get_user(tmp, &(termio)->c_oflag); \
- (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
- get_user(tmp, &(termio)->c_cflag); \
- (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
- get_user(tmp, &(termio)->c_lflag); \
- (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
- get_user((termios)->c_line, &(termio)->c_line); \
- copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
+static inline int user_termio_to_kernel_termios(struct ktermios *termios,
+ struct termio __user *termio)
+{
+ unsigned short iflag, oflag, cflag, lflag;
+ unsigned int err;
+
+ if (!access_ok(VERIFY_READ, termio, sizeof(struct termio)))
+ return -EFAULT;
+
+ err = __get_user(iflag, &termio->c_iflag);
+ termios->c_iflag = (termios->c_iflag & 0xffff0000) | iflag;
+ err |=__get_user(oflag, &termio->c_oflag);
+ termios->c_oflag = (termios->c_oflag & 0xffff0000) | oflag;
+ err |=__get_user(cflag, &termio->c_cflag);
+ termios->c_cflag = (termios->c_cflag & 0xffff0000) | cflag;
+ err |=__get_user(lflag, &termio->c_lflag);
+ termios->c_lflag = (termios->c_lflag & 0xffff0000) | lflag;
+ err |=__get_user(termios->c_line, &termio->c_line);
+ if (err)
+ return -EFAULT;
+
+ if (__copy_from_user(termios->c_cc, termio->c_cc, NCC))
+ return -EFAULT;
+
+ return 0;
+}
/*
* Translate a "termios" structure into a "termio". Ugh.
*/
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
- put_user((termios)->c_iflag, &(termio)->c_iflag); \
- put_user((termios)->c_oflag, &(termio)->c_oflag); \
- put_user((termios)->c_cflag, &(termio)->c_cflag); \
- put_user((termios)->c_lflag, &(termio)->c_lflag); \
- put_user((termios)->c_line, &(termio)->c_line); \
- copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
+static inline int kernel_termios_to_user_termio(struct termio __user *termio,
+ struct ktermios *termios)
+{
+ int err;
+
+ if (!access_ok(VERIFY_WRITE, termio, sizeof(struct termio)))
+ return -EFAULT;
+
+ err = __put_user(termios->c_iflag, &termio->c_iflag);
+ err |= __put_user(termios->c_oflag, &termio->c_oflag);
+ err |= __put_user(termios->c_cflag, &termio->c_cflag);
+ err |= __put_user(termios->c_lflag, &termio->c_lflag);
+ err |= __put_user(termios->c_line, &termio->c_line);
+ if (err)
+ return -EFAULT;
+
+ if (__copy_to_user(termio->c_cc, termios->c_cc, NCC))
+ return -EFAULT;
+
+ return 0;
+}
+
+static inline int user_termios_to_kernel_termios(struct ktermios __user *k,
+ struct termios2 *u)
+{
+ return copy_from_user(k, u, sizeof(struct termios2)) ? -EFAULT : 0;
+}
+
+static inline int kernel_termios_to_user_termios(struct termios2 __user *u,
+ struct ktermios *k)
+{
+ return copy_to_user(u, k, sizeof(struct termios2)) ? -EFAULT : 0;
+}
+
+static inline int user_termios_to_kernel_termios_1(struct ktermios *k,
+ struct termios __user *u)
+{
+ return copy_from_user(k, u, sizeof(struct termios)) ? -EFAULT : 0;
+}
+
+static inline int kernel_termios_to_user_termios_1(struct termios __user *u,
+ struct ktermios *k)
+{
+ return copy_to_user(u, k, sizeof(struct termios)) ? -EFAULT : 0;
+}
#endif /* defined(__KERNEL__) */
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index 9601ea950542..38a30d2ee959 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -50,27 +50,35 @@ extern int (*perf_irq)(void);
/*
* Initialize the calling CPU's compare interrupt as clockevent device
*/
-#ifdef CONFIG_CEVT_R4K
-extern int mips_clockevent_init(void);
+#ifdef CONFIG_CEVT_R4K_LIB
extern unsigned int __weak get_c0_compare_int(void);
-#else
+extern int r4k_clockevent_init(void);
+#endif
+
static inline int mips_clockevent_init(void)
{
+#ifdef CONFIG_CEVT_R4K
+ return r4k_clockevent_init();
+#else
return -ENXIO;
-}
#endif
+}
/*
* Initialize the count register as a clocksource
*/
-#ifdef CONFIG_CSRC_R4K
-extern int init_mips_clocksource(void);
-#else
+#ifdef CONFIG_CSRC_R4K_LIB
+extern int init_r4k_clocksource(void);
+#endif
+
static inline int init_mips_clocksource(void)
{
+#ifdef CONFIG_CSRC_R4K
+ return init_r4k_clocksource();
+#else
return 0;
-}
#endif
+}
extern void clocksource_set_clock(struct clocksource *cs, unsigned int clock);
extern void clockevent_set_clock(struct clock_event_device *cd,
diff --git a/arch/mips/include/asm/txx9/tx4939.h b/arch/mips/include/asm/txx9/tx4939.h
index 88badb423010..964ef7ede268 100644
--- a/arch/mips/include/asm/txx9/tx4939.h
+++ b/arch/mips/include/asm/txx9/tx4939.h
@@ -541,5 +541,6 @@ void tx4939_irq_init(void);
int tx4939_irq(void);
void tx4939_mtd_init(int ch);
void tx4939_ata_init(void);
+void tx4939_rtc_init(void);
#endif /* __ASM_TXX9_TX4939_H */
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index d7f8a782aae4..03965cb1b252 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -146,7 +146,7 @@ void __init plat_time_init(void)
BUG_ON(HZ != 100);
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
clockevents_register_device(cd);
action->dev_id = cd;
setup_irq(JAZZ_TIMER_IRQ, action);
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index b1372c27f136..e96122159928 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -9,7 +9,7 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
time.o topology.o traps.o unaligned.o watch.o
obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
-obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
+obj-$(CONFIG_CEVT_R4K_LIB) += cevt-r4k.o
obj-$(CONFIG_MIPS_MT_SMTC) += cevt-smtc.o
obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o
obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
@@ -17,7 +17,7 @@ obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
obj-$(CONFIG_CSRC_IOASIC) += csrc-ioasic.o
-obj-$(CONFIG_CSRC_R4K) += csrc-r4k.o
+obj-$(CONFIG_CSRC_R4K_LIB) += csrc-r4k.o
obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
obj-$(CONFIG_SYNC_R4K) += sync-r4k.o
@@ -43,6 +43,7 @@ obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON) += octeon_switch.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SMP_UP) += smp-up.o
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 72942226fcdd..c901c22d7ad0 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -64,6 +64,10 @@ void output_ptreg_defines(void)
#ifdef CONFIG_MIPS_MT_SMTC
OFFSET(PT_TCSTATUS, pt_regs, cp0_tcstatus);
#endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ OFFSET(PT_MPL, pt_regs, mpl);
+ OFFSET(PT_MTP, pt_regs, mtp);
+#endif /* CONFIG_CPU_CAVIUM_OCTEON */
DEFINE(PT_SIZE, sizeof(struct pt_regs));
BLANK();
}
@@ -295,3 +299,30 @@ void output_irq_cpustat_t_defines(void)
DEFINE(IC_IRQ_CPUSTAT_T, sizeof(irq_cpustat_t));
BLANK();
}
+
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+void output_octeon_cop2_state_defines(void)
+{
+ COMMENT("Octeon specific octeon_cop2_state offsets.");
+ OFFSET(OCTEON_CP2_CRC_IV, octeon_cop2_state, cop2_crc_iv);
+ OFFSET(OCTEON_CP2_CRC_LENGTH, octeon_cop2_state, cop2_crc_length);
+ OFFSET(OCTEON_CP2_CRC_POLY, octeon_cop2_state, cop2_crc_poly);
+ OFFSET(OCTEON_CP2_LLM_DAT, octeon_cop2_state, cop2_llm_dat);
+ OFFSET(OCTEON_CP2_3DES_IV, octeon_cop2_state, cop2_3des_iv);
+ OFFSET(OCTEON_CP2_3DES_KEY, octeon_cop2_state, cop2_3des_key);
+ OFFSET(OCTEON_CP2_3DES_RESULT, octeon_cop2_state, cop2_3des_result);
+ OFFSET(OCTEON_CP2_AES_INP0, octeon_cop2_state, cop2_aes_inp0);
+ OFFSET(OCTEON_CP2_AES_IV, octeon_cop2_state, cop2_aes_iv);
+ OFFSET(OCTEON_CP2_AES_KEY, octeon_cop2_state, cop2_aes_key);
+ OFFSET(OCTEON_CP2_AES_KEYLEN, octeon_cop2_state, cop2_aes_keylen);
+ OFFSET(OCTEON_CP2_AES_RESULT, octeon_cop2_state, cop2_aes_result);
+ OFFSET(OCTEON_CP2_GFM_MULT, octeon_cop2_state, cop2_gfm_mult);
+ OFFSET(OCTEON_CP2_GFM_POLY, octeon_cop2_state, cop2_gfm_poly);
+ OFFSET(OCTEON_CP2_GFM_RESULT, octeon_cop2_state, cop2_gfm_result);
+ OFFSET(OCTEON_CP2_HSH_DATW, octeon_cop2_state, cop2_hsh_datw);
+ OFFSET(OCTEON_CP2_HSH_IVW, octeon_cop2_state, cop2_hsh_ivw);
+ OFFSET(THREAD_CP2, task_struct, thread.cp2);
+ OFFSET(THREAD_CVMSEG, task_struct, thread.cvmseg.cvmseg);
+ BLANK();
+}
+#endif
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 6b5df8bfab85..0176ed015c89 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -205,6 +205,39 @@ int __compute_return_epc(struct pt_regs *regs)
break;
}
break;
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ case lwc2_op: /* This is bbit0 on Octeon */
+ if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
+ == 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+ case ldc2_op: /* This is bbit032 on Octeon */
+ if ((regs->regs[insn.i_format.rs] &
+ (1ull<<(insn.i_format.rt+32))) == 0)
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+ case swc2_op: /* This is bbit1 on Octeon */
+ if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+ case sdc2_op: /* This is bbit132 on Octeon */
+ if (regs->regs[insn.i_format.rs] &
+ (1ull<<(insn.i_format.rt+32)))
+ epc = epc + 4 + (insn.i_format.simmediate << 2);
+ else
+ epc += 8;
+ regs->cp0_epc = epc;
+ break;
+#endif
}
return 0;
diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c
index 0a57f86945f1..b820661678b0 100644
--- a/arch/mips/kernel/cevt-bcm1480.c
+++ b/arch/mips/kernel/cevt-bcm1480.c
@@ -126,7 +126,7 @@ void __cpuinit sb1480_clockevent_init(void)
cd->min_delta_ns = clockevent_delta2ns(2, cd);
cd->rating = 200;
cd->irq = irq;
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
cd->set_next_event = sibyte_next_event;
cd->set_mode = sibyte_set_mode;
clockevents_register_device(cd);
@@ -148,6 +148,6 @@ void __cpuinit sb1480_clockevent_init(void)
action->name = name;
action->dev_id = cd;
- irq_set_affinity(irq, cpumask_of_cpu(cpu));
+ irq_set_affinity(irq, cpumask_of(cpu));
setup_irq(irq, action);
}
diff --git a/arch/mips/kernel/cevt-ds1287.c b/arch/mips/kernel/cevt-ds1287.c
index df4acb68bfb5..1ada45ea0700 100644
--- a/arch/mips/kernel/cevt-ds1287.c
+++ b/arch/mips/kernel/cevt-ds1287.c
@@ -88,7 +88,6 @@ static void ds1287_event_handler(struct clock_event_device *dev)
static struct clock_event_device ds1287_clockevent = {
.name = "ds1287",
.features = CLOCK_EVT_FEAT_PERIODIC,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = ds1287_set_next_event,
.set_mode = ds1287_set_mode,
.event_handler = ds1287_event_handler,
@@ -122,6 +121,7 @@ int __init ds1287_clockevent_init(int irq)
clockevent_set_clock(cd, 32768);
cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
+ cd->cpumask = cpumask_of(0);
clockevents_register_device(&ds1287_clockevent);
diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
index 6e2f58520afb..e9b787feedcb 100644
--- a/arch/mips/kernel/cevt-gt641xx.c
+++ b/arch/mips/kernel/cevt-gt641xx.c
@@ -96,7 +96,6 @@ static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
static struct clock_event_device gt641xx_timer0_clockevent = {
.name = "gt641xx-timer0",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
- .cpumask = CPU_MASK_CPU0,
.irq = GT641XX_TIMER0_IRQ,
.set_next_event = gt641xx_timer0_set_next_event,
.set_mode = gt641xx_timer0_set_mode,
@@ -132,6 +131,7 @@ static int __init gt641xx_timer0_clockevent_init(void)
clockevent_set_clock(cd, gt641xx_base_clock);
cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
+ cd->cpumask = cpumask_of(0);
clockevents_register_device(&gt641xx_timer0_clockevent);
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 4a4c59f2737a..0015e442572b 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -160,7 +160,7 @@ int c0_compare_int_usable(void)
#ifndef CONFIG_MIPS_MT_SMTC
-int __cpuinit mips_clockevent_init(void)
+int __cpuinit r4k_clockevent_init(void)
{
uint64_t mips_freq = mips_hpt_frequency;
unsigned int cpu = smp_processor_id();
@@ -195,7 +195,7 @@ int __cpuinit mips_clockevent_init(void)
cd->rating = 300;
cd->irq = irq;
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
cd->set_next_event = mips_next_event;
cd->set_mode = mips_set_clock_mode;
cd->event_handler = mips_event_handler;
diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c
index 63ac3ad462bc..a2eebaafda52 100644
--- a/arch/mips/kernel/cevt-sb1250.c
+++ b/arch/mips/kernel/cevt-sb1250.c
@@ -125,7 +125,7 @@ void __cpuinit sb1250_clockevent_init(void)
cd->min_delta_ns = clockevent_delta2ns(2, cd);
cd->rating = 200;
cd->irq = irq;
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
cd->set_next_event = sibyte_next_event;
cd->set_mode = sibyte_set_mode;
clockevents_register_device(cd);
@@ -147,6 +147,6 @@ void __cpuinit sb1250_clockevent_init(void)
action->name = name;
action->dev_id = cd;
- irq_set_affinity(irq, cpumask_of_cpu(cpu));
+ irq_set_affinity(irq, cpumask_of(cpu));
setup_irq(irq, action);
}
diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c
index 5162fe4b5952..6d45e24db5bf 100644
--- a/arch/mips/kernel/cevt-smtc.c
+++ b/arch/mips/kernel/cevt-smtc.c
@@ -292,7 +292,7 @@ int __cpuinit mips_clockevent_init(void)
cd->rating = 300;
cd->irq = irq;
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
cd->set_next_event = mips_next_event;
cd->set_mode = mips_set_clock_mode;
cd->event_handler = mips_event_handler;
diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c
index b5fc4eb412d2..eccf7d6096bd 100644
--- a/arch/mips/kernel/cevt-txx9.c
+++ b/arch/mips/kernel/cevt-txx9.c
@@ -112,7 +112,6 @@ static struct clock_event_device txx9tmr_clock_event_device = {
.name = "TXx9",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.rating = 200,
- .cpumask = CPU_MASK_CPU0,
.set_mode = txx9tmr_set_mode,
.set_next_event = txx9tmr_set_next_event,
};
@@ -150,6 +149,7 @@ void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd);
cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
cd->irq = irq;
+ cd->cpumask = cpumask_of(0),
clockevents_register_device(cd);
setup_irq(irq, &txx9tmr_irq);
printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n",
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index c9207b5fd923..a7162a4484cf 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -96,6 +96,9 @@ int allow_au1k_wait;
static void au1k_wait(void)
{
+ if (!allow_au1k_wait)
+ return;
+
/* using the wait instruction makes CP0 counter unusable */
__asm__(" .set mips3 \n"
" cache 0x14, 0(%0) \n"
@@ -154,6 +157,7 @@ void __init check_wait(void)
case CPU_25KF:
case CPU_PR4450:
case CPU_BCM3302:
+ case CPU_CAVIUM_OCTEON:
cpu_wait = r4k_wait;
break;
@@ -185,8 +189,7 @@ void __init check_wait(void)
case CPU_AU1200:
case CPU_AU1210:
case CPU_AU1250:
- if (allow_au1k_wait)
- cpu_wait = au1k_wait;
+ cpu_wait = au1k_wait;
break;
case CPU_20KC:
/*
@@ -875,6 +878,27 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
}
}
+static inline void cpu_probe_cavium(struct cpuinfo_mips *c, unsigned int cpu)
+{
+ decode_configs(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_CAVIUM_CN38XX:
+ case PRID_IMP_CAVIUM_CN31XX:
+ case PRID_IMP_CAVIUM_CN30XX:
+ case PRID_IMP_CAVIUM_CN58XX:
+ case PRID_IMP_CAVIUM_CN56XX:
+ case PRID_IMP_CAVIUM_CN50XX:
+ case PRID_IMP_CAVIUM_CN52XX:
+ c->cputype = CPU_CAVIUM_OCTEON;
+ __cpu_name[cpu] = "Cavium Octeon";
+ break;
+ default:
+ printk(KERN_INFO "Unknown Octeon chip!\n");
+ c->cputype = CPU_UNKNOWN;
+ break;
+ }
+}
+
const char *__cpu_name[NR_CPUS];
__cpuinit void cpu_probe(void)
@@ -909,6 +933,9 @@ __cpuinit void cpu_probe(void)
case PRID_COMP_NXP:
cpu_probe_nxp(c, cpu);
break;
+ case PRID_COMP_CAVIUM:
+ cpu_probe_cavium(c, cpu);
+ break;
}
BUG_ON(!__cpu_name[cpu]);
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index 74fb74583b4e..f1a2893931ed 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -22,7 +22,7 @@ static struct clocksource clocksource_mips = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
-int __init init_mips_clocksource(void)
+int __init init_r4k_clocksource(void)
{
if (!cpu_has_counter || !mips_hpt_frequency)
return -ENXIO;
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 757d48f0d80f..8882e5766f27 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -385,10 +385,14 @@ NESTED(nmi_handler, PT_SIZE, sp)
.endm
.macro __build_clear_fpe
+ .set push
+ /* gas fails to assemble cfc1 for some archs (octeon).*/ \
+ .set mips1
cfc1 a1, fcr31
li a2, ~(0x3f << 12)
and a2, a1
ctc1 a2, fcr31
+ .set pop
TRACE_IRQS_ON
STI
.endm
@@ -454,7 +458,11 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER fpe fpe fpe silent /* #15 */
BUILD_HANDLER mdmx mdmx sti silent /* #22 */
#ifdef CONFIG_HARDWARE_WATCHPOINTS
- BUILD_HANDLER watch watch sti silent /* #23 */
+ /*
+ * For watch, interrupts will be enabled after the watch
+ * registers are read.
+ */
+ BUILD_HANDLER watch watch cli silent /* #23 */
#else
BUILD_HANDLER watch watch sti verbose /* #23 */
#endif
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index b6ac55162b9a..f4d187825f96 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -115,7 +115,7 @@ void __init setup_pit_timer(void)
* Start pit with the boot cpu mask and make it global after the
* IO_APIC has been initialized.
*/
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
clockevent_set_clock(cd, CLOCK_TICK_RATE);
cd->max_delta_ns = clockevent_delta2ns(0x7FFF, cd);
cd->min_delta_ns = clockevent_delta2ns(0xF, cd);
diff --git a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c
index d72487ad7c15..149cd914526e 100644
--- a/arch/mips/kernel/init_task.c
+++ b/arch/mips/kernel/init_task.c
@@ -9,7 +9,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index f0a4bb19e096..494a49a317e9 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -155,7 +155,7 @@ static void gic_unmask_irq(unsigned int irq)
static DEFINE_SPINLOCK(gic_lock);
-static void gic_set_affinity(unsigned int irq, cpumask_t cpumask)
+static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
{
cpumask_t tmp = CPU_MASK_NONE;
unsigned long flags;
@@ -164,7 +164,7 @@ static void gic_set_affinity(unsigned int irq, cpumask_t cpumask)
pr_debug(KERN_DEBUG "%s called\n", __func__);
irq -= _irqbase;
- cpus_and(tmp, cpumask, cpu_online_map);
+ cpumask_and(&tmp, cpumask, cpu_online_mask);
if (cpus_empty(tmp))
return;
@@ -187,7 +187,7 @@ static void gic_set_affinity(unsigned int irq, cpumask_t cpumask)
set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
}
- irq_desc[irq].affinity = cpumask;
+ irq_desc[irq].affinity = *cpumask;
spin_unlock_irqrestore(&gic_lock, flags);
}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 4b4007b3083a..a0ff2b66e22b 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -111,6 +111,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
seq_printf(p, " %14s", irq_desc[i].chip->name);
+ seq_printf(p, "-%-8s", irq_desc[i].name);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 5e77a3a21f98..42461310b185 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -79,7 +79,8 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
euid = current_euid();
retval = -EPERM;
- if (euid != p->euid && euid != p->uid && !capable(CAP_SYS_NICE)) {
+ if (euid != p->cred->euid && euid != p->cred->uid &&
+ !capable(CAP_SYS_NICE)) {
read_unlock(&tasklist_lock);
goto out_unlock;
}
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
new file mode 100644
index 000000000000..d52389672b06
--- /dev/null
+++ b/arch/mips/kernel/octeon_switch.S
@@ -0,0 +1,506 @@
+/*
+ * 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, 1996, 1998, 1999, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1994, 1995, 1996, by Andreas Busse
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ * written by Carsten Langgaard, carstenl@mips.com
+ */
+#include <asm/asm.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/pgtable-bits.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/thread_info.h>
+
+#include <asm/asmmacro.h>
+
+/*
+ * Offset to the current process status flags, the first 32 bytes of the
+ * stack are not used.
+ */
+#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
+
+/*
+ * task_struct *resume(task_struct *prev, task_struct *next,
+ * struct thread_info *next_ti)
+ */
+ .align 7
+ LEAF(resume)
+ .set arch=octeon
+#ifndef CONFIG_CPU_HAS_LLSC
+ sw zero, ll_bit
+#endif
+ mfc0 t1, CP0_STATUS
+ LONG_S t1, THREAD_STATUS(a0)
+ cpu_save_nonscratch a0
+ LONG_S ra, THREAD_REG31(a0)
+
+ /* check if we need to save COP2 registers */
+ PTR_L t2, TASK_THREAD_INFO(a0)
+ LONG_L t0, ST_OFF(t2)
+ bbit0 t0, 30, 1f
+
+ /* Disable COP2 in the stored process state */
+ li t1, ST0_CU2
+ xor t0, t1
+ LONG_S t0, ST_OFF(t2)
+
+ /* Enable COP2 so we can save it */
+ mfc0 t0, CP0_STATUS
+ or t0, t1
+ mtc0 t0, CP0_STATUS
+
+ /* Save COP2 */
+ daddu a0, THREAD_CP2
+ jal octeon_cop2_save
+ dsubu a0, THREAD_CP2
+
+ /* Disable COP2 now that we are done */
+ mfc0 t0, CP0_STATUS
+ li t1, ST0_CU2
+ xor t0, t1
+ mtc0 t0, CP0_STATUS
+
+1:
+#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
+ /* Check if we need to store CVMSEG state */
+ mfc0 t0, $11,7 /* CvmMemCtl */
+ bbit0 t0, 6, 3f /* Is user access enabled? */
+
+ /* Store the CVMSEG state */
+ /* Extract the size of CVMSEG */
+ andi t0, 0x3f
+ /* Multiply * (cache line size/sizeof(long)/2) */
+ sll t0, 7-LONGLOG-1
+ li t1, -32768 /* Base address of CVMSEG */
+ LONG_ADDI t2, a0, THREAD_CVMSEG /* Where to store CVMSEG to */
+ synciobdma
+2:
+ .set noreorder
+ LONG_L t8, 0(t1) /* Load from CVMSEG */
+ subu t0, 1 /* Decrement loop var */
+ LONG_L t9, LONGSIZE(t1)/* Load from CVMSEG */
+ LONG_ADDU t1, LONGSIZE*2 /* Increment loc in CVMSEG */
+ LONG_S t8, 0(t2) /* Store CVMSEG to thread storage */
+ LONG_ADDU t2, LONGSIZE*2 /* Increment loc in thread storage */
+ bnez t0, 2b /* Loop until we've copied it all */
+ LONG_S t9, -LONGSIZE(t2)/* Store CVMSEG to thread storage */
+ .set reorder
+
+ /* Disable access to CVMSEG */
+ mfc0 t0, $11,7 /* CvmMemCtl */
+ xori t0, t0, 0x40 /* Bit 6 is CVMSEG user enable */
+ mtc0 t0, $11,7 /* CvmMemCtl */
+#endif
+3:
+ /*
+ * The order of restoring the registers takes care of the race
+ * updating $28, $29 and kernelsp without disabling ints.
+ */
+ move $28, a2
+ cpu_restore_nonscratch a1
+
+#if (_THREAD_SIZE - 32) < 0x8000
+ PTR_ADDIU t0, $28, _THREAD_SIZE - 32
+#else
+ PTR_LI t0, _THREAD_SIZE - 32
+ PTR_ADDU t0, $28
+#endif
+ set_saved_sp t0, t1, t2
+
+ mfc0 t1, CP0_STATUS /* Do we really need this? */
+ li a3, 0xff01
+ and t1, a3
+ LONG_L a2, THREAD_STATUS(a1)
+ nor a3, $0, a3
+ and a2, a3
+ or a2, t1
+ mtc0 a2, CP0_STATUS
+ move v0, a0
+ jr ra
+ END(resume)
+
+/*
+ * void octeon_cop2_save(struct octeon_cop2_state *a0)
+ */
+ .align 7
+ LEAF(octeon_cop2_save)
+
+ dmfc0 t9, $9,7 /* CvmCtl register. */
+
+ /* Save the COP2 CRC state */
+ dmfc2 t0, 0x0201
+ dmfc2 t1, 0x0202
+ dmfc2 t2, 0x0200
+ sd t0, OCTEON_CP2_CRC_IV(a0)
+ sd t1, OCTEON_CP2_CRC_LENGTH(a0)
+ sd t2, OCTEON_CP2_CRC_POLY(a0)
+ /* Skip next instructions if CvmCtl[NODFA_CP2] set */
+ bbit1 t9, 28, 1f
+
+ /* Save the LLM state */
+ dmfc2 t0, 0x0402
+ dmfc2 t1, 0x040A
+ sd t0, OCTEON_CP2_LLM_DAT(a0)
+ sd t1, OCTEON_CP2_LLM_DAT+8(a0)
+
+1: bbit1 t9, 26, 3f /* done if CvmCtl[NOCRYPTO] set */
+
+ /* Save the COP2 crypto state */
+ /* this part is mostly common to both pass 1 and later revisions */
+ dmfc2 t0, 0x0084
+ dmfc2 t1, 0x0080
+ dmfc2 t2, 0x0081
+ dmfc2 t3, 0x0082
+ sd t0, OCTEON_CP2_3DES_IV(a0)
+ dmfc2 t0, 0x0088
+ sd t1, OCTEON_CP2_3DES_KEY(a0)
+ dmfc2 t1, 0x0111 /* only necessary for pass 1 */
+ sd t2, OCTEON_CP2_3DES_KEY+8(a0)
+ dmfc2 t2, 0x0102
+ sd t3, OCTEON_CP2_3DES_KEY+16(a0)
+ dmfc2 t3, 0x0103
+ sd t0, OCTEON_CP2_3DES_RESULT(a0)
+ dmfc2 t0, 0x0104
+ sd t1, OCTEON_CP2_AES_INP0(a0) /* only necessary for pass 1 */
+ dmfc2 t1, 0x0105
+ sd t2, OCTEON_CP2_AES_IV(a0)
+ dmfc2 t2, 0x0106
+ sd t3, OCTEON_CP2_AES_IV+8(a0)
+ dmfc2 t3, 0x0107
+ sd t0, OCTEON_CP2_AES_KEY(a0)
+ dmfc2 t0, 0x0110
+ sd t1, OCTEON_CP2_AES_KEY+8(a0)
+ dmfc2 t1, 0x0100
+ sd t2, OCTEON_CP2_AES_KEY+16(a0)
+ dmfc2 t2, 0x0101
+ sd t3, OCTEON_CP2_AES_KEY+24(a0)
+ mfc0 t3, $15,0 /* Get the processor ID register */
+ sd t0, OCTEON_CP2_AES_KEYLEN(a0)
+ li t0, 0x000d0000 /* This is the processor ID of Octeon Pass1 */
+ sd t1, OCTEON_CP2_AES_RESULT(a0)
+ sd t2, OCTEON_CP2_AES_RESULT+8(a0)
+ /* Skip to the Pass1 version of the remainder of the COP2 state */
+ beq t3, t0, 2f
+
+ /* the non-pass1 state when !CvmCtl[NOCRYPTO] */
+ dmfc2 t1, 0x0240
+ dmfc2 t2, 0x0241
+ dmfc2 t3, 0x0242
+ dmfc2 t0, 0x0243
+ sd t1, OCTEON_CP2_HSH_DATW(a0)
+ dmfc2 t1, 0x0244
+ sd t2, OCTEON_CP2_HSH_DATW+8(a0)
+ dmfc2 t2, 0x0245
+ sd t3, OCTEON_CP2_HSH_DATW+16(a0)
+ dmfc2 t3, 0x0246
+ sd t0, OCTEON_CP2_HSH_DATW+24(a0)
+ dmfc2 t0, 0x0247
+ sd t1, OCTEON_CP2_HSH_DATW+32(a0)
+ dmfc2 t1, 0x0248
+ sd t2, OCTEON_CP2_HSH_DATW+40(a0)
+ dmfc2 t2, 0x0249
+ sd t3, OCTEON_CP2_HSH_DATW+48(a0)
+ dmfc2 t3, 0x024A
+ sd t0, OCTEON_CP2_HSH_DATW+56(a0)
+ dmfc2 t0, 0x024B
+ sd t1, OCTEON_CP2_HSH_DATW+64(a0)
+ dmfc2 t1, 0x024C
+ sd t2, OCTEON_CP2_HSH_DATW+72(a0)
+ dmfc2 t2, 0x024D
+ sd t3, OCTEON_CP2_HSH_DATW+80(a0)
+ dmfc2 t3, 0x024E
+ sd t0, OCTEON_CP2_HSH_DATW+88(a0)
+ dmfc2 t0, 0x0250
+ sd t1, OCTEON_CP2_HSH_DATW+96(a0)
+ dmfc2 t1, 0x0251
+ sd t2, OCTEON_CP2_HSH_DATW+104(a0)
+ dmfc2 t2, 0x0252
+ sd t3, OCTEON_CP2_HSH_DATW+112(a0)
+ dmfc2 t3, 0x0253
+ sd t0, OCTEON_CP2_HSH_IVW(a0)
+ dmfc2 t0, 0x0254
+ sd t1, OCTEON_CP2_HSH_IVW+8(a0)
+ dmfc2 t1, 0x0255
+ sd t2, OCTEON_CP2_HSH_IVW+16(a0)
+ dmfc2 t2, 0x0256
+ sd t3, OCTEON_CP2_HSH_IVW+24(a0)
+ dmfc2 t3, 0x0257
+ sd t0, OCTEON_CP2_HSH_IVW+32(a0)
+ dmfc2 t0, 0x0258
+ sd t1, OCTEON_CP2_HSH_IVW+40(a0)
+ dmfc2 t1, 0x0259
+ sd t2, OCTEON_CP2_HSH_IVW+48(a0)
+ dmfc2 t2, 0x025E
+ sd t3, OCTEON_CP2_HSH_IVW+56(a0)
+ dmfc2 t3, 0x025A
+ sd t0, OCTEON_CP2_GFM_MULT(a0)
+ dmfc2 t0, 0x025B
+ sd t1, OCTEON_CP2_GFM_MULT+8(a0)
+ sd t2, OCTEON_CP2_GFM_POLY(a0)
+ sd t3, OCTEON_CP2_GFM_RESULT(a0)
+ sd t0, OCTEON_CP2_GFM_RESULT+8(a0)
+ jr ra
+
+2: /* pass 1 special stuff when !CvmCtl[NOCRYPTO] */
+ dmfc2 t3, 0x0040
+ dmfc2 t0, 0x0041
+ dmfc2 t1, 0x0042
+ dmfc2 t2, 0x0043
+ sd t3, OCTEON_CP2_HSH_DATW(a0)
+ dmfc2 t3, 0x0044
+ sd t0, OCTEON_CP2_HSH_DATW+8(a0)
+ dmfc2 t0, 0x0045
+ sd t1, OCTEON_CP2_HSH_DATW+16(a0)
+ dmfc2 t1, 0x0046
+ sd t2, OCTEON_CP2_HSH_DATW+24(a0)
+ dmfc2 t2, 0x0048
+ sd t3, OCTEON_CP2_HSH_DATW+32(a0)
+ dmfc2 t3, 0x0049
+ sd t0, OCTEON_CP2_HSH_DATW+40(a0)
+ dmfc2 t0, 0x004A
+ sd t1, OCTEON_CP2_HSH_DATW+48(a0)
+ sd t2, OCTEON_CP2_HSH_IVW(a0)
+ sd t3, OCTEON_CP2_HSH_IVW+8(a0)
+ sd t0, OCTEON_CP2_HSH_IVW+16(a0)
+
+3: /* pass 1 or CvmCtl[NOCRYPTO] set */
+ jr ra
+ END(octeon_cop2_save)
+
+/*
+ * void octeon_cop2_restore(struct octeon_cop2_state *a0)
+ */
+ .align 7
+ .set push
+ .set noreorder
+ LEAF(octeon_cop2_restore)
+ /* First cache line was prefetched before the call */
+ pref 4, 128(a0)
+ dmfc0 t9, $9,7 /* CvmCtl register. */
+
+ pref 4, 256(a0)
+ ld t0, OCTEON_CP2_CRC_IV(a0)
+ pref 4, 384(a0)
+ ld t1, OCTEON_CP2_CRC_LENGTH(a0)
+ ld t2, OCTEON_CP2_CRC_POLY(a0)
+
+ /* Restore the COP2 CRC state */
+ dmtc2 t0, 0x0201
+ dmtc2 t1, 0x1202
+ bbit1 t9, 28, 2f /* Skip LLM if CvmCtl[NODFA_CP2] is set */
+ dmtc2 t2, 0x4200
+
+ /* Restore the LLM state */
+ ld t0, OCTEON_CP2_LLM_DAT(a0)
+ ld t1, OCTEON_CP2_LLM_DAT+8(a0)
+ dmtc2 t0, 0x0402
+ dmtc2 t1, 0x040A
+
+2:
+ bbit1 t9, 26, done_restore /* done if CvmCtl[NOCRYPTO] set */
+ nop
+
+ /* Restore the COP2 crypto state common to pass 1 and pass 2 */
+ ld t0, OCTEON_CP2_3DES_IV(a0)
+ ld t1, OCTEON_CP2_3DES_KEY(a0)
+ ld t2, OCTEON_CP2_3DES_KEY+8(a0)
+ dmtc2 t0, 0x0084
+ ld t0, OCTEON_CP2_3DES_KEY+16(a0)
+ dmtc2 t1, 0x0080
+ ld t1, OCTEON_CP2_3DES_RESULT(a0)
+ dmtc2 t2, 0x0081
+ ld t2, OCTEON_CP2_AES_INP0(a0) /* only really needed for pass 1 */
+ dmtc2 t0, 0x0082
+ ld t0, OCTEON_CP2_AES_IV(a0)
+ dmtc2 t1, 0x0098
+ ld t1, OCTEON_CP2_AES_IV+8(a0)
+ dmtc2 t2, 0x010A /* only really needed for pass 1 */
+ ld t2, OCTEON_CP2_AES_KEY(a0)
+ dmtc2 t0, 0x0102
+ ld t0, OCTEON_CP2_AES_KEY+8(a0)
+ dmtc2 t1, 0x0103
+ ld t1, OCTEON_CP2_AES_KEY+16(a0)
+ dmtc2 t2, 0x0104
+ ld t2, OCTEON_CP2_AES_KEY+24(a0)
+ dmtc2 t0, 0x0105
+ ld t0, OCTEON_CP2_AES_KEYLEN(a0)
+ dmtc2 t1, 0x0106
+ ld t1, OCTEON_CP2_AES_RESULT(a0)
+ dmtc2 t2, 0x0107
+ ld t2, OCTEON_CP2_AES_RESULT+8(a0)
+ mfc0 t3, $15,0 /* Get the processor ID register */
+ dmtc2 t0, 0x0110
+ li t0, 0x000d0000 /* This is the processor ID of Octeon Pass1 */
+ dmtc2 t1, 0x0100
+ bne t0, t3, 3f /* Skip the next stuff for non-pass1 */
+ dmtc2 t2, 0x0101
+
+ /* this code is specific for pass 1 */
+ ld t0, OCTEON_CP2_HSH_DATW(a0)
+ ld t1, OCTEON_CP2_HSH_DATW+8(a0)
+ ld t2, OCTEON_CP2_HSH_DATW+16(a0)
+ dmtc2 t0, 0x0040
+ ld t0, OCTEON_CP2_HSH_DATW+24(a0)
+ dmtc2 t1, 0x0041
+ ld t1, OCTEON_CP2_HSH_DATW+32(a0)
+ dmtc2 t2, 0x0042
+ ld t2, OCTEON_CP2_HSH_DATW+40(a0)
+ dmtc2 t0, 0x0043
+ ld t0, OCTEON_CP2_HSH_DATW+48(a0)
+ dmtc2 t1, 0x0044
+ ld t1, OCTEON_CP2_HSH_IVW(a0)
+ dmtc2 t2, 0x0045
+ ld t2, OCTEON_CP2_HSH_IVW+8(a0)
+ dmtc2 t0, 0x0046
+ ld t0, OCTEON_CP2_HSH_IVW+16(a0)
+ dmtc2 t1, 0x0048
+ dmtc2 t2, 0x0049
+ b done_restore /* unconditional branch */
+ dmtc2 t0, 0x004A
+
+3: /* this is post-pass1 code */
+ ld t2, OCTEON_CP2_HSH_DATW(a0)
+ ld t0, OCTEON_CP2_HSH_DATW+8(a0)
+ ld t1, OCTEON_CP2_HSH_DATW+16(a0)
+ dmtc2 t2, 0x0240
+ ld t2, OCTEON_CP2_HSH_DATW+24(a0)
+ dmtc2 t0, 0x0241
+ ld t0, OCTEON_CP2_HSH_DATW+32(a0)
+ dmtc2 t1, 0x0242
+ ld t1, OCTEON_CP2_HSH_DATW+40(a0)
+ dmtc2 t2, 0x0243
+ ld t2, OCTEON_CP2_HSH_DATW+48(a0)
+ dmtc2 t0, 0x0244
+ ld t0, OCTEON_CP2_HSH_DATW+56(a0)
+ dmtc2 t1, 0x0245
+ ld t1, OCTEON_CP2_HSH_DATW+64(a0)
+ dmtc2 t2, 0x0246
+ ld t2, OCTEON_CP2_HSH_DATW+72(a0)
+ dmtc2 t0, 0x0247
+ ld t0, OCTEON_CP2_HSH_DATW+80(a0)
+ dmtc2 t1, 0x0248
+ ld t1, OCTEON_CP2_HSH_DATW+88(a0)
+ dmtc2 t2, 0x0249
+ ld t2, OCTEON_CP2_HSH_DATW+96(a0)
+ dmtc2 t0, 0x024A
+ ld t0, OCTEON_CP2_HSH_DATW+104(a0)
+ dmtc2 t1, 0x024B
+ ld t1, OCTEON_CP2_HSH_DATW+112(a0)
+ dmtc2 t2, 0x024C
+ ld t2, OCTEON_CP2_HSH_IVW(a0)
+ dmtc2 t0, 0x024D
+ ld t0, OCTEON_CP2_HSH_IVW+8(a0)
+ dmtc2 t1, 0x024E
+ ld t1, OCTEON_CP2_HSH_IVW+16(a0)
+ dmtc2 t2, 0x0250
+ ld t2, OCTEON_CP2_HSH_IVW+24(a0)
+ dmtc2 t0, 0x0251
+ ld t0, OCTEON_CP2_HSH_IVW+32(a0)
+ dmtc2 t1, 0x0252
+ ld t1, OCTEON_CP2_HSH_IVW+40(a0)
+ dmtc2 t2, 0x0253
+ ld t2, OCTEON_CP2_HSH_IVW+48(a0)
+ dmtc2 t0, 0x0254
+ ld t0, OCTEON_CP2_HSH_IVW+56(a0)
+ dmtc2 t1, 0x0255
+ ld t1, OCTEON_CP2_GFM_MULT(a0)
+ dmtc2 t2, 0x0256
+ ld t2, OCTEON_CP2_GFM_MULT+8(a0)
+ dmtc2 t0, 0x0257
+ ld t0, OCTEON_CP2_GFM_POLY(a0)
+ dmtc2 t1, 0x0258
+ ld t1, OCTEON_CP2_GFM_RESULT(a0)
+ dmtc2 t2, 0x0259
+ ld t2, OCTEON_CP2_GFM_RESULT+8(a0)
+ dmtc2 t0, 0x025E
+ dmtc2 t1, 0x025A
+ dmtc2 t2, 0x025B
+
+done_restore:
+ jr ra
+ nop
+ END(octeon_cop2_restore)
+ .set pop
+
+/*
+ * void octeon_mult_save()
+ * sp is assumed to point to a struct pt_regs
+ *
+ * NOTE: This is called in SAVE_SOME in stackframe.h. It can only
+ * safely modify k0 and k1.
+ */
+ .align 7
+ .set push
+ .set noreorder
+ LEAF(octeon_mult_save)
+ dmfc0 k0, $9,7 /* CvmCtl register. */
+ bbit1 k0, 27, 1f /* Skip CvmCtl[NOMUL] */
+ nop
+
+ /* Save the multiplier state */
+ v3mulu k0, $0, $0
+ v3mulu k1, $0, $0
+ sd k0, PT_MTP(sp) /* PT_MTP has P0 */
+ v3mulu k0, $0, $0
+ sd k1, PT_MTP+8(sp) /* PT_MTP+8 has P1 */
+ ori k1, $0, 1
+ v3mulu k1, k1, $0
+ sd k0, PT_MTP+16(sp) /* PT_MTP+16 has P2 */
+ v3mulu k0, $0, $0
+ sd k1, PT_MPL(sp) /* PT_MPL has MPL0 */
+ v3mulu k1, $0, $0
+ sd k0, PT_MPL+8(sp) /* PT_MPL+8 has MPL1 */
+ jr ra
+ sd k1, PT_MPL+16(sp) /* PT_MPL+16 has MPL2 */
+
+1: /* Resume here if CvmCtl[NOMUL] */
+ jr ra
+ END(octeon_mult_save)
+ .set pop
+
+/*
+ * void octeon_mult_restore()
+ * sp is assumed to point to a struct pt_regs
+ *
+ * NOTE: This is called in RESTORE_SOME in stackframe.h.
+ */
+ .align 7
+ .set push
+ .set noreorder
+ LEAF(octeon_mult_restore)
+ dmfc0 k1, $9,7 /* CvmCtl register. */
+ ld v0, PT_MPL(sp) /* MPL0 */
+ ld v1, PT_MPL+8(sp) /* MPL1 */
+ ld k0, PT_MPL+16(sp) /* MPL2 */
+ bbit1 k1, 27, 1f /* Skip CvmCtl[NOMUL] */
+ /* Normally falls through, so no time wasted here */
+ nop
+
+ /* Restore the multiplier state */
+ ld k1, PT_MTP+16(sp) /* P2 */
+ MTM0 v0 /* MPL0 */
+ ld v0, PT_MTP+8(sp) /* P1 */
+ MTM1 v1 /* MPL1 */
+ ld v1, PT_MTP(sp) /* P0 */
+ MTM2 k0 /* MPL2 */
+ MTP2 k1 /* P2 */
+ MTP1 v0 /* P1 */
+ jr ra
+ MTP0 v1 /* P0 */
+
+1: /* Resume here if CvmCtl[NOMUL] */
+ jr ra
+ nop
+ END(octeon_mult_restore)
+ .set pop
+
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 1ca34104e593..c4f9ac17474a 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -49,19 +49,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
int ret;
switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned int tmp;
- int copied;
-
- copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
- ret = -EIO;
- if (copied != sizeof(tmp))
- break;
- ret = put_user(tmp, (unsigned int __user *) (unsigned long) data);
- break;
- }
/*
* Read 4 bytes of the other process' storage
@@ -208,16 +195,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
break;
}
- /* when I and D space are separate, this will have to be fixed. */
- case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- ret = 0;
- if (access_process_vm(child, addr, &data, sizeof(data), 1)
- == sizeof(data))
- break;
- ret = -EIO;
- break;
-
/*
* Write 4 bytes into the other process' storage
* data is the 4 bytes that the user wants written
@@ -332,50 +309,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
ret = ptrace_setfpregs(child, (__u32 __user *) (__u64) data);
break;
- case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
- ret = -EIO;
- if (!valid_signal(data))
- break;
- if (request == PTRACE_SYSCALL) {
- set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- else {
- clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
- }
- child->exit_code = data;
- wake_up_process(child);
- ret = 0;
- break;
- }
-
- /*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL:
- ret = 0;
- if (child->exit_state == EXIT_ZOMBIE) /* already dead */
- break;
- child->exit_code = SIGKILL;
- wake_up_process(child);
- break;
-
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned int __user *) (unsigned long) data);
break;
- case PTRACE_DETACH: /* detach a process that was attached. */
- ret = ptrace_detach(child, data);
- break;
-
- case PTRACE_GETEVENTMSG:
- ret = put_user(child->ptrace_message,
- (unsigned int __user *) (unsigned long) data);
- break;
-
case PTRACE_GET_THREAD_AREA_3264:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) (unsigned long) data);
@@ -392,7 +330,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
break;
default:
- ret = ptrace_request(child, request, addr, data);
+ ret = compat_ptrace_request(child, request, addr, data);
break;
}
out:
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index d0916a55cd77..51d1ba415b90 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -398,7 +398,7 @@ einval: li v0, -ENOSYS
sys sys_uselib 1
sys sys_swapon 2
sys sys_reboot 3
- sys old_readdir 3
+ sys sys_old_readdir 3
sys old_mmap 6 /* 4090 */
sys sys_munmap 2
sys sys_truncate 2
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index ca476c4f62a5..f27beca4b26d 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -51,10 +51,10 @@ static int __init allowcpus(char *str)
int len;
cpus_clear(cpu_allow_map);
- if (cpulist_parse(str, cpu_allow_map) == 0) {
+ if (cpulist_parse(str, &cpu_allow_map) == 0) {
cpu_set(0, cpu_allow_map);
cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map);
- len = cpulist_scnprintf(buf, sizeof(buf)-1, cpu_possible_map);
+ len = cpulist_scnprintf(buf, sizeof(buf)-1, &cpu_possible_map);
buf[len] = '\0';
pr_debug("Allowable CPUs: %s\n", buf);
return 1;
@@ -226,7 +226,7 @@ void __init cmp_smp_setup(void)
for (i = 1; i < NR_CPUS; i++) {
if (amon_cpu_avail(i)) {
- cpu_set(i, phys_cpu_present_map);
+ cpu_set(i, cpu_possible_map);
__cpu_number_map[i] = ++ncpu;
__cpu_logical_map[ncpu] = i;
}
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 87a1816c1f45..6f7ee5ac46ee 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -70,7 +70,7 @@ static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0,
write_vpe_c0_vpeconf0(tmp);
/* Record this as available CPU */
- cpu_set(tc, phys_cpu_present_map);
+ cpu_set(tc, cpu_possible_map);
__cpu_number_map[tc] = ++ncpu;
__cpu_logical_map[ncpu] = tc;
}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 8bf88faf5afd..3da94704f816 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -44,15 +44,10 @@
#include <asm/mipsmtregs.h>
#endif /* CONFIG_MIPS_MT_SMTC */
-cpumask_t phys_cpu_present_map; /* Bitmask of available CPUs */
volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
-cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
-EXPORT_SYMBOL(phys_cpu_present_map);
-EXPORT_SYMBOL(cpu_online_map);
-
extern void cpu_idle(void);
/* Number of TCs (or siblings in Intel speak) per CPU core */
@@ -195,7 +190,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/* preload SMP state for boot cpu */
void __devinit smp_prepare_boot_cpu(void)
{
- cpu_set(0, phys_cpu_present_map);
+ cpu_set(0, cpu_possible_map);
cpu_set(0, cpu_online_map);
cpu_set(0, cpu_callin_map);
}
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 897fb2b4751c..b6cca01ff82b 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -290,7 +290,7 @@ static void smtc_configure_tlb(void)
* possibly leave some TCs/VPEs as "slave" processors.
*
* Use c0_MVPConf0 to find out how many TCs are available, setting up
- * phys_cpu_present_map and the logical/physical mappings.
+ * cpu_possible_map and the logical/physical mappings.
*/
int __init smtc_build_cpu_map(int start_cpu_slot)
@@ -304,7 +304,7 @@ int __init smtc_build_cpu_map(int start_cpu_slot)
*/
ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
for (i=start_cpu_slot; i<NR_CPUS && i<ntcs; i++) {
- cpu_set(i, phys_cpu_present_map);
+ cpu_set(i, cpu_possible_map);
__cpu_number_map[i] = i;
__cpu_logical_map[i] = i;
}
@@ -521,7 +521,7 @@ void smtc_prepare_cpus(int cpus)
* Pull any physically present but unused TCs out of circulation.
*/
while (tc < (((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1)) {
- cpu_clear(tc, phys_cpu_present_map);
+ cpu_clear(tc, cpu_possible_map);
cpu_clear(tc, cpu_present_map);
tc++;
}
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c
index 0632e2a849c0..58f5cd76c8c3 100644
--- a/arch/mips/kernel/stacktrace.c
+++ b/arch/mips/kernel/stacktrace.c
@@ -32,7 +32,8 @@ static void save_raw_context_stack(struct stack_trace *trace,
}
}
-static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs)
+static void save_context_stack(struct stack_trace *trace,
+ struct task_struct *tsk, struct pt_regs *regs)
{
unsigned long sp = regs->regs[29];
#ifdef CONFIG_KALLSYMS
@@ -41,7 +42,7 @@ static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs)
if (raw_show_trace || !__kernel_text_address(pc)) {
unsigned long stack_page =
- (unsigned long)task_stack_page(current);
+ (unsigned long)task_stack_page(tsk);
if (stack_page && sp >= stack_page &&
sp <= stack_page + THREAD_SIZE - 32)
save_raw_context_stack(trace, sp);
@@ -54,7 +55,7 @@ static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs)
trace->entries[trace->nr_entries++] = pc;
if (trace->nr_entries >= trace->max_entries)
break;
- pc = unwind_stack(current, &sp, pc, &ra);
+ pc = unwind_stack(tsk, &sp, pc, &ra);
} while (pc);
#else
save_raw_context_stack(trace, sp);
@@ -66,12 +67,23 @@ static void save_context_stack(struct stack_trace *trace, struct pt_regs *regs)
*/
void save_stack_trace(struct stack_trace *trace)
{
+ save_stack_trace_tsk(current, trace);
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
struct pt_regs dummyregs;
struct pt_regs *regs = &dummyregs;
WARN_ON(trace->nr_entries || !trace->max_entries);
- prepare_frametrace(regs);
- save_context_stack(trace, regs);
+ if (tsk != current) {
+ regs->regs[29] = tsk->thread.reg29;
+ regs->regs[31] = 0;
+ regs->cp0_epc = tsk->thread.reg31;
+ } else
+ prepare_frametrace(regs);
+ save_context_stack(trace, tsk, regs);
}
-EXPORT_SYMBOL_GPL(save_stack_trace);
+EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 353056110f2b..b2d7041341b8 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -47,6 +47,7 @@
#include <asm/mmu_context.h>
#include <asm/types.h>
#include <asm/stacktrace.h>
+#include <asm/irq.h>
extern void check_wait(void);
extern asmlinkage void r4k_wait(void);
@@ -78,6 +79,10 @@ extern asmlinkage void handle_reserved(void);
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu);
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task);
+#endif
+
void (*board_be_init)(void);
int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
void (*board_nmi_handler_setup)(void);
@@ -860,6 +865,7 @@ asmlinkage void do_cpu(struct pt_regs *regs)
unsigned int opcode;
unsigned int cpid;
int status;
+ unsigned long __maybe_unused flags;
die_if_kernel("do_cpu invoked from kernel context!", regs);
@@ -915,6 +921,17 @@ asmlinkage void do_cpu(struct pt_regs *regs)
return;
case 2:
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ prefetch(&current->thread.cp2);
+ local_irq_save(flags);
+ KSTK_STATUS(current) |= ST0_CU2;
+ status = read_c0_status();
+ write_c0_status(status | ST0_CU2);
+ octeon_cop2_restore(&(current->thread.cp2));
+ write_c0_status(status & ~ST0_CU2);
+ local_irq_restore(flags);
+ return;
+#endif
case 3:
break;
}
@@ -927,6 +944,9 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
force_sig(SIGILL, current);
}
+/*
+ * Called with interrupts disabled.
+ */
asmlinkage void do_watch(struct pt_regs *regs)
{
u32 cause;
@@ -946,9 +966,12 @@ asmlinkage void do_watch(struct pt_regs *regs)
*/
if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
mips_read_watch_registers();
+ local_irq_enable();
force_sig(SIGTRAP, current);
- } else
+ } else {
mips_clear_watch_registers();
+ local_irq_enable();
+ }
}
asmlinkage void do_mcheck(struct pt_regs *regs)
@@ -1488,6 +1511,10 @@ void __cpuinit per_cpu_trap_init(void)
write_c0_hwrena(enable);
}
+#ifdef CONFIG_CPU_CAVIUM_OCTEON
+ write_c0_hwrena(0xc000000f); /* Octeon has register 30 and 31 */
+#endif
+
#ifdef CONFIG_MIPS_MT_SMTC
if (!secondaryTC) {
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -1561,7 +1588,11 @@ void __init set_handler(unsigned long offset, void *addr, unsigned long size)
static char panic_null_cerr[] __cpuinitdata =
"Trying to set NULL cache error exception handler";
-/* Install uncached CPU exception handler */
+/*
+ * Install uncached CPU exception handler.
+ * This is suitable only for the cache error exception which is the only
+ * exception handler that is being run uncached.
+ */
void __cpuinit set_uncached_handler(unsigned long offset, void *addr,
unsigned long size)
{
@@ -1572,7 +1603,7 @@ void __cpuinit set_uncached_handler(unsigned long offset, void *addr,
unsigned long uncached_ebase = TO_UNCAC(ebase);
#endif
if (cpu_has_mips_r2)
- ebase += (read_c0_ebase() & 0x3ffff000);
+ uncached_ebase += (read_c0_ebase() & 0x3ffff000);
if (!addr)
panic(panic_null_cerr);
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 010b27e01f7b..3ca5f42e819d 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1454,7 +1454,7 @@ static int __init vpe_module_init(void)
device_initialize(&vpe_device);
vpe_device.class = &vpe_class,
vpe_device.parent = NULL,
- strlcpy(vpe_device.bus_id, "vpe1", BUS_ID_SIZE);
+ dev_set_name(&vpe_device, "vpe1");
vpe_device.devt = MKDEV(major, minor);
err = device_add(&vpe_device);
if (err) {
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index dbcf6511b74e..c13c7ad2cdae 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CPU_SB1) += dump_tlb.o
obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON) += dump_tlb.o
# libgcc-style stuff needed in the kernel
obj-y += ashldi3.o ashrdi3.o cmpdi2.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/memcpy-inatomic.S b/arch/mips/lib/memcpy-inatomic.S
index 736d0fb56a94..68853a038d3f 100644
--- a/arch/mips/lib/memcpy-inatomic.S
+++ b/arch/mips/lib/memcpy-inatomic.S
@@ -21,7 +21,7 @@
* end of memory on some systems. It's also a seriously bad idea on non
* dma-coherent systems.
*/
-#if !defined(CONFIG_DMA_COHERENT) || !defined(CONFIG_DMA_IP27)
+#ifdef CONFIG_DMA_NONCOHERENT
#undef CONFIG_CPU_HAS_PREFETCH
#endif
#ifdef CONFIG_MIPS_MALTA
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S
index c06cccf60bec..56a1f85a1ce8 100644
--- a/arch/mips/lib/memcpy.S
+++ b/arch/mips/lib/memcpy.S
@@ -21,7 +21,7 @@
* end of memory on some systems. It's also a seriously bad idea on non
* dma-coherent systems.
*/
-#if !defined(CONFIG_DMA_COHERENT) || !defined(CONFIG_DMA_IP27)
+#ifdef CONFIG_DMA_NONCOHERENT
#undef CONFIG_CPU_HAS_PREFETCH
#endif
#ifdef CONFIG_MIPS_MALTA
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 95ba32b5b720..d7ec95522292 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CPU_SB1) += c-r4k.o cerr-sb1.o cex-sb1.o tlb-r4k.o
obj-$(CONFIG_CPU_TX39XX) += c-tx39.o tlb-r3k.o
obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o tlb-r4k.o
obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o tlb-r4k.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON) += c-octeon.o cex-oct.o tlb-r4k.o
obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
new file mode 100644
index 000000000000..44d01a0a8490
--- /dev/null
+++ b/arch/mips/mm/c-octeon.c
@@ -0,0 +1,307 @@
+/*
+ * 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) 2005-2007 Cavium Networks
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/bitops.h>
+#include <linux/cpu.h>
+#include <linux/io.h>
+
+#include <asm/bcache.h>
+#include <asm/bootinfo.h>
+#include <asm/cacheops.h>
+#include <asm/cpu-features.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/r4kcache.h>
+#include <asm/system.h>
+#include <asm/mmu_context.h>
+#include <asm/war.h>
+
+#include <asm/octeon/octeon.h>
+
+unsigned long long cache_err_dcache[NR_CPUS];
+
+/**
+ * Octeon automatically flushes the dcache on tlb changes, so
+ * from Linux's viewpoint it acts much like a physically
+ * tagged cache. No flushing is needed
+ *
+ */
+static void octeon_flush_data_cache_page(unsigned long addr)
+{
+ /* Nothing to do */
+}
+
+static inline void octeon_local_flush_icache(void)
+{
+ asm volatile ("synci 0($0)");
+}
+
+/*
+ * Flush local I-cache for the specified range.
+ */
+static void local_octeon_flush_icache_range(unsigned long start,
+ unsigned long end)
+{
+ octeon_local_flush_icache();
+}
+
+/**
+ * Flush caches as necessary for all cores affected by a
+ * vma. If no vma is supplied, all cores are flushed.
+ *
+ * @vma: VMA to flush or NULL to flush all icaches.
+ */
+static void octeon_flush_icache_all_cores(struct vm_area_struct *vma)
+{
+ extern void octeon_send_ipi_single(int cpu, unsigned int action);
+#ifdef CONFIG_SMP
+ int cpu;
+ cpumask_t mask;
+#endif
+
+ mb();
+ octeon_local_flush_icache();
+#ifdef CONFIG_SMP
+ preempt_disable();
+ cpu = smp_processor_id();
+
+ /*
+ * If we have a vma structure, we only need to worry about
+ * cores it has been used on
+ */
+ if (vma)
+ mask = vma->vm_mm->cpu_vm_mask;
+ else
+ mask = cpu_online_map;
+ cpu_clear(cpu, mask);
+ for_each_cpu_mask(cpu, mask)
+ octeon_send_ipi_single(cpu, SMP_ICACHE_FLUSH);
+
+ preempt_enable();
+#endif
+}
+
+
+/**
+ * Called to flush the icache on all cores
+ */
+static void octeon_flush_icache_all(void)
+{
+ octeon_flush_icache_all_cores(NULL);
+}
+
+
+/**
+ * Called to flush all memory associated with a memory
+ * context.
+ *
+ * @mm: Memory context to flush
+ */
+static void octeon_flush_cache_mm(struct mm_struct *mm)
+{
+ /*
+ * According to the R4K version of this file, CPUs without
+ * dcache aliases don't need to do anything here
+ */
+}
+
+
+/**
+ * Flush a range of kernel addresses out of the icache
+ *
+ */
+static void octeon_flush_icache_range(unsigned long start, unsigned long end)
+{
+ octeon_flush_icache_all_cores(NULL);
+}
+
+
+/**
+ * Flush the icache for a trampoline. These are used for interrupt
+ * and exception hooking.
+ *
+ * @addr: Address to flush
+ */
+static void octeon_flush_cache_sigtramp(unsigned long addr)
+{
+ struct vm_area_struct *vma;
+
+ vma = find_vma(current->mm, addr);
+ octeon_flush_icache_all_cores(vma);
+}
+
+
+/**
+ * Flush a range out of a vma
+ *
+ * @vma: VMA to flush
+ * @start:
+ * @end:
+ */
+static void octeon_flush_cache_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ if (vma->vm_flags & VM_EXEC)
+ octeon_flush_icache_all_cores(vma);
+}
+
+
+/**
+ * Flush a specific page of a vma
+ *
+ * @vma: VMA to flush page for
+ * @page: Page to flush
+ * @pfn:
+ */
+static void octeon_flush_cache_page(struct vm_area_struct *vma,
+ unsigned long page, unsigned long pfn)
+{
+ if (vma->vm_flags & VM_EXEC)
+ octeon_flush_icache_all_cores(vma);
+}
+
+
+/**
+ * Probe Octeon's caches
+ *
+ */
+static void __devinit probe_octeon(void)
+{
+ unsigned long icache_size;
+ unsigned long dcache_size;
+ unsigned int config1;
+ struct cpuinfo_mips *c = &current_cpu_data;
+
+ switch (c->cputype) {
+ case CPU_CAVIUM_OCTEON:
+ config1 = read_c0_config1();
+ c->icache.linesz = 2 << ((config1 >> 19) & 7);
+ c->icache.sets = 64 << ((config1 >> 22) & 7);
+ c->icache.ways = 1 + ((config1 >> 16) & 7);
+ c->icache.flags |= MIPS_CACHE_VTAG;
+ icache_size =
+ c->icache.sets * c->icache.ways * c->icache.linesz;
+ c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
+ c->dcache.linesz = 128;
+ if (OCTEON_IS_MODEL(OCTEON_CN3XXX))
+ c->dcache.sets = 1; /* CN3XXX has one Dcache set */
+ else
+ c->dcache.sets = 2; /* CN5XXX has two Dcache sets */
+ c->dcache.ways = 64;
+ dcache_size =
+ c->dcache.sets * c->dcache.ways * c->dcache.linesz;
+ c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+ c->options |= MIPS_CPU_PREFETCH;
+ break;
+
+ default:
+ panic("Unsupported Cavium Networks CPU type\n");
+ break;
+ }
+
+ /* compute a couple of other cache variables */
+ c->icache.waysize = icache_size / c->icache.ways;
+ c->dcache.waysize = dcache_size / c->dcache.ways;
+
+ c->icache.sets = icache_size / (c->icache.linesz * c->icache.ways);
+ c->dcache.sets = dcache_size / (c->dcache.linesz * c->dcache.ways);
+
+ if (smp_processor_id() == 0) {
+ pr_notice("Primary instruction cache %ldkB, %s, %d way, "
+ "%d sets, linesize %d bytes.\n",
+ icache_size >> 10,
+ cpu_has_vtag_icache ?
+ "virtually tagged" : "physically tagged",
+ c->icache.ways, c->icache.sets, c->icache.linesz);
+
+ pr_notice("Primary data cache %ldkB, %d-way, %d sets, "
+ "linesize %d bytes.\n",
+ dcache_size >> 10, c->dcache.ways,
+ c->dcache.sets, c->dcache.linesz);
+ }
+}
+
+
+/**
+ * Setup the Octeon cache flush routines
+ *
+ */
+void __devinit octeon_cache_init(void)
+{
+ extern unsigned long ebase;
+ extern char except_vec2_octeon;
+
+ memcpy((void *)(ebase + 0x100), &except_vec2_octeon, 0x80);
+ octeon_flush_cache_sigtramp(ebase + 0x100);
+
+ probe_octeon();
+
+ shm_align_mask = PAGE_SIZE - 1;
+
+ flush_cache_all = octeon_flush_icache_all;
+ __flush_cache_all = octeon_flush_icache_all;
+ flush_cache_mm = octeon_flush_cache_mm;
+ flush_cache_page = octeon_flush_cache_page;
+ flush_cache_range = octeon_flush_cache_range;
+ flush_cache_sigtramp = octeon_flush_cache_sigtramp;
+ flush_icache_all = octeon_flush_icache_all;
+ flush_data_cache_page = octeon_flush_data_cache_page;
+ flush_icache_range = octeon_flush_icache_range;
+ local_flush_icache_range = local_octeon_flush_icache_range;
+
+ build_clear_page();
+ build_copy_page();
+}
+
+/**
+ * Handle a cache error exception
+ */
+
+static void cache_parity_error_octeon(int non_recoverable)
+{
+ unsigned long coreid = cvmx_get_core_num();
+ uint64_t icache_err = read_octeon_c0_icacheerr();
+
+ pr_err("Cache error exception:\n");
+ pr_err("cp0_errorepc == %lx\n", read_c0_errorepc());
+ if (icache_err & 1) {
+ pr_err("CacheErr (Icache) == %llx\n",
+ (unsigned long long)icache_err);
+ write_octeon_c0_icacheerr(0);
+ }
+ if (cache_err_dcache[coreid] & 1) {
+ pr_err("CacheErr (Dcache) == %llx\n",
+ (unsigned long long)cache_err_dcache[coreid]);
+ cache_err_dcache[coreid] = 0;
+ }
+
+ if (non_recoverable)
+ panic("Can't handle cache error: nested exception");
+}
+
+/**
+ * Called when the the exception is not recoverable
+ */
+
+asmlinkage void cache_parity_error_octeon_recoverable(void)
+{
+ cache_parity_error_octeon(0);
+}
+
+/**
+ * Called when the the exception is recoverable
+ */
+
+asmlinkage void cache_parity_error_octeon_non_recoverable(void)
+{
+ cache_parity_error_octeon(1);
+}
+
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 6e99665ae860..c43f4b26a690 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -618,15 +618,35 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
if (cpu_has_inclusive_pcaches) {
if (size >= scache_size)
r4k_blast_scache();
- else
+ else {
+ unsigned long lsize = cpu_scache_line_size();
+ unsigned long almask = ~(lsize - 1);
+
+ /*
+ * There is no clearly documented alignment requirement
+ * for the cache instruction on MIPS processors and
+ * some processors, among them the RM5200 and RM7000
+ * QED processors will throw an address error for cache
+ * hit ops with insufficient alignment. Solved by
+ * aligning the address to cache line size.
+ */
+ cache_op(Hit_Writeback_Inv_SD, addr & almask);
+ cache_op(Hit_Writeback_Inv_SD,
+ (addr + size - 1) & almask);
blast_inv_scache_range(addr, addr + size);
+ }
return;
}
if (cpu_has_safe_index_cacheops && size >= dcache_size) {
r4k_blast_dcache();
} else {
+ unsigned long lsize = cpu_dcache_line_size();
+ unsigned long almask = ~(lsize - 1);
+
R4600_HIT_CACHEOP_WAR_IMPL;
+ cache_op(Hit_Writeback_Inv_D, addr & almask);
+ cache_op(Hit_Writeback_Inv_D, (addr + size - 1) & almask);
blast_inv_dcache_range(addr, addr + size);
}
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 1eb7c71e3d6a..98ad0a82c29e 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -182,6 +182,12 @@ void __devinit cpu_cache_init(void)
tx39_cache_init();
}
+ if (cpu_has_octeon_cache) {
+ extern void __weak octeon_cache_init(void);
+
+ octeon_cache_init();
+ }
+
setup_protection_map();
}
diff --git a/arch/mips/mm/cex-oct.S b/arch/mips/mm/cex-oct.S
new file mode 100644
index 000000000000..3db8553fcd34
--- /dev/null
+++ b/arch/mips/mm/cex-oct.S
@@ -0,0 +1,70 @@
+/*
+ * 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 Cavium Networks
+ * Cache error handler
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+
+/*
+ * Handle cache error. Indicate to the second level handler whether
+ * the exception is recoverable.
+ */
+ LEAF(except_vec2_octeon)
+
+ .set push
+ .set mips64r2
+ .set noreorder
+ .set noat
+
+
+ /* due to an errata we need to read the COP0 CacheErr (Dcache)
+ * before any cache/DRAM access */
+
+ rdhwr k0, $0 /* get core_id */
+ PTR_LA k1, cache_err_dcache
+ sll k0, k0, 3
+ PTR_ADDU k1, k0, k1 /* k1 = &cache_err_dcache[core_id] */
+
+ dmfc0 k0, CP0_CACHEERR, 1
+ sd k0, (k1)
+ dmtc0 $0, CP0_CACHEERR, 1
+
+ /* check whether this is a nested exception */
+ mfc0 k1, CP0_STATUS
+ andi k1, k1, ST0_EXL
+ beqz k1, 1f
+ nop
+ j cache_parity_error_octeon_non_recoverable
+ nop
+
+ /* exception is recoverable */
+1: j handle_cache_err
+ nop
+
+ .set pop
+ END(except_vec2_octeon)
+
+ /* We need to jump to handle_cache_err so that the previous handler
+ * can fit within 0x80 bytes. We also move from 0xFFFFFFFFAXXXXXXX
+ * space (uncached) to the 0xFFFFFFFF8XXXXXXX space (cached). */
+ LEAF(handle_cache_err)
+ .set push
+ .set noreorder
+ .set noat
+
+ SAVE_ALL
+ KMODE
+ jal cache_parity_error_octeon_recoverable
+ nop
+ j ret_from_exception
+ nop
+
+ .set pop
+ END(handle_cache_err)
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index e6708b3ad343..546e6977d4ff 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -111,7 +111,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
- plat_unmap_dma_mem(dma_handle);
+ plat_unmap_dma_mem(dev, dma_handle);
free_pages((unsigned long) vaddr, get_order(size));
}
@@ -122,7 +122,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{
unsigned long addr = (unsigned long) vaddr;
- plat_unmap_dma_mem(dma_handle);
+ plat_unmap_dma_mem(dev, dma_handle);
if (!plat_device_is_coherent(dev))
addr = CAC_ADDR(addr);
@@ -173,7 +173,7 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
__dma_sync(dma_addr_to_virt(dma_addr), size,
direction);
- plat_unmap_dma_mem(dma_addr);
+ plat_unmap_dma_mem(dev, dma_addr);
}
EXPORT_SYMBOL(dma_unmap_single);
@@ -229,7 +229,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
dma_cache_wback_inv(addr, size);
}
- plat_unmap_dma_mem(dma_address);
+ plat_unmap_dma_mem(dev, dma_address);
}
EXPORT_SYMBOL(dma_unmap_page);
@@ -249,7 +249,7 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
if (addr)
__dma_sync(addr, sg->length, direction);
}
- plat_unmap_dma_mem(sg->dma_address);
+ plat_unmap_dma_mem(dev, sg->dma_address);
}
}
@@ -275,6 +275,7 @@ void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
{
BUG_ON(direction == DMA_NONE);
+ plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev)) {
unsigned long addr;
@@ -305,6 +306,7 @@ void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
{
BUG_ON(direction == DMA_NONE);
+ plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev)) {
unsigned long addr;
@@ -351,22 +353,14 @@ EXPORT_SYMBOL(dma_sync_sg_for_device);
int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
- return 0;
+ return plat_dma_mapping_error(dev, dma_addr);
}
EXPORT_SYMBOL(dma_mapping_error);
int 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;
+ return plat_dma_supported(dev, mask);
}
EXPORT_SYMBOL(dma_supported);
@@ -383,6 +377,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
{
BUG_ON(direction == DMA_NONE);
+ plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev))
__dma_sync((unsigned long)vaddr, size, direction);
}
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index fa636fc6b7b9..55767ad9f00e 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -97,7 +97,6 @@ good_area:
goto bad_area;
}
-survive:
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
@@ -167,21 +166,13 @@ no_context:
field, regs->regs[31]);
die("Oops", regs);
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
out_of_memory:
- up_read(&mm->mmap_sem);
- if (is_global_init(tsk)) {
- yield();
- down_read(&mm->mmap_sem);
- goto survive;
- }
- printk("VM: killing process %s\n", tsk->comm);
- if (user_mode(regs))
- do_group_exit(SIGKILL);
- goto no_context;
+ /*
+ * We ran out of memory, call the OOM killer, and return the userspace
+ * (which will retry the fault, or kill us if we got oom-killed).
+ */
+ pagefault_out_of_memory();
+ return;
do_sigbus:
up_read(&mm->mmap_sem);
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 5ce2fa745626..9619f66e531e 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -478,7 +478,10 @@ void __cpuinit tlb_init(void)
probe_tlb(config);
write_c0_pagemask(PM_DEFAULT_MASK);
write_c0_wired(0);
- write_c0_framemask(0);
+ if (current_cpu_type() == CPU_R10000 ||
+ current_cpu_type() == CPU_R12000 ||
+ current_cpu_type() == CPU_R14000)
+ write_c0_framemask(0);
temp_tlb_entry = current_cpu_data.tlbsize - 1;
/* From this point on the ARC firmware is dead. */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 979cf9197282..42942038d0fd 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -317,6 +317,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
case CPU_BCM3302:
case CPU_BCM4710:
case CPU_LOONGSON2:
+ case CPU_CAVIUM_OCTEON:
if (m4kc_tlbp_war())
uasm_i_nop(p);
tlbw(p);
diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c
index f84a46a8ae6e..aabd7274507b 100644
--- a/arch/mips/mti-malta/malta-smtc.c
+++ b/arch/mips/mti-malta/malta-smtc.c
@@ -114,9 +114,9 @@ struct plat_smp_ops msmtc_smp_ops = {
*/
-void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity)
+void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
{
- cpumask_t tmask = affinity;
+ cpumask_t tmask = *affinity;
int cpu = 0;
void smtc_set_irq_affinity(unsigned int irq, cpumask_t aff);
@@ -139,7 +139,7 @@ void plat_set_irq_affinity(unsigned int irq, cpumask_t affinity)
* be made to forward to an offline "CPU".
*/
- for_each_cpu_mask(cpu, affinity) {
+ for_each_cpu(cpu, affinity) {
if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu))
cpu_clear(cpu, tmask);
}
diff --git a/arch/mips/nxp/pnx8550/common/time.c b/arch/mips/nxp/pnx8550/common/time.c
index 62f495b57f93..cf293b279098 100644
--- a/arch/mips/nxp/pnx8550/common/time.c
+++ b/arch/mips/nxp/pnx8550/common/time.c
@@ -102,6 +102,7 @@ __init void plat_time_init(void)
unsigned int p;
unsigned int pow2p;
+ pnx8xxx_clockevent.cpumask = cpu_none_mask;
clockevents_register_device(&pnx8xxx_clockevent);
clocksource_register(&pnx_clocksource);
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index f97ab1461012..dda6f2058665 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -146,12 +146,6 @@ int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return 0;
}
-/* Most MIPS systems have straight-forward swizzling needs. */
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
- return (((pin - 1) + slot) % 4) + 1;
-}
-
static inline struct pci_dev *bridge_root_dev(struct pci_dev *dev)
{
while (dev->bus->parent) {
diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c
index 1c2821e2f494..71f7d27b0d4c 100644
--- a/arch/mips/pci/pci-rc32434.c
+++ b/arch/mips/pci/pci-rc32434.c
@@ -205,6 +205,8 @@ static int __init rc32434_pcibridge_init(void)
static int __init rc32434_pci_init(void)
{
+ void __iomem *io_map_base;
+
pr_info("PCI: Initializing PCI\n");
ioport_resource.start = rc32434_res_pci_io1.start;
@@ -212,6 +214,15 @@ static int __init rc32434_pci_init(void)
rc32434_pcibridge_init();
+ io_map_base = ioremap(rc32434_res_pci_io1.start,
+ rc32434_res_pci_io1.end - rc32434_res_pci_io1.start + 1);
+
+ if (!io_map_base)
+ return -ENOMEM;
+
+ rc32434_controller.io_map_base =
+ (unsigned long)io_map_base - rc32434_res_pci_io1.start;
+
register_pci_controller(&rc32434_controller);
rc32434_sync();
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 62cae740e250..b0eb9e75c682 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -149,28 +149,6 @@ out:
"Skipping PCI bus scan due to resource conflict\n");
}
-/* Most MIPS systems have straight-forward swizzling needs. */
-
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
- return (((pin - 1) + slot) % 4) + 1;
-}
-
-static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
-{
- u8 pin = *pinp;
-
- while (dev->bus->parent) {
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
- /* Move up the chain of bridges. */
- dev = dev->bus->self;
- }
- *pinp = pin;
-
- /* The slot is the slot of the last bridge. */
- return PCI_SLOT(dev->devfn);
-}
-
static int __init pcibios_init(void)
{
struct pci_controller *hose;
@@ -179,7 +157,7 @@ static int __init pcibios_init(void)
for (hose = hose_head; hose; hose = hose->next)
pcibios_scanbus(hose);
- pci_fixup_irqs(common_swizzle, pcibios_map_irq);
+ pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq);
pci_initialized = 1;
diff --git a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
index 97862f45496d..caf5e9a0acc7 100644
--- a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
+++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
@@ -148,7 +148,7 @@ int read_eeprom(char *buffer, int eeprom_size, int size)
send_byte(W_HEADER);
recv_ack();
- /* EEPROM with size of more then 2K need two byte addressing */
+ /* EEPROM with size of more than 2K need two byte addressing */
if (eeprom_size > 2048) {
send_byte(0x00);
recv_ack();
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 3a7df647ca77..f78c29b68d77 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -141,7 +141,7 @@ static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle)
}
/*
- * Detect available CPUs, populate phys_cpu_present_map before smp_init
+ * Detect available CPUs, populate cpu_possible_map before smp_init
*
* We don't want to start the secondary CPU yet nor do we have a nice probing
* feature in PMON so we just assume presence of the secondary core.
@@ -150,10 +150,10 @@ static void __init yos_smp_setup(void)
{
int i;
- cpus_clear(phys_cpu_present_map);
+ cpus_clear(cpu_possible_map);
for (i = 0; i < 2; i++) {
- cpu_set(i, phys_cpu_present_map);
+ cpu_set(i, cpu_possible_map);
__cpu_number_map[i] = i;
__cpu_logical_map[i] = i;
}
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index c1c29181bd46..4a5f05b662ae 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -24,6 +24,7 @@
#include <linux/mtd/partitions.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
+#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
@@ -39,6 +40,29 @@
#define ETH0_RX_DMA_ADDR (DMA0_BASE_ADDR + 0 * DMA_CHAN_OFFSET)
#define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET)
+extern unsigned int idt_cpu_freq;
+
+static struct mpmc_device dev3;
+
+void set_latch_u5(unsigned char or_mask, unsigned char nand_mask)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev3.lock, flags);
+
+ dev3.state = (dev3.state | or_mask) & ~nand_mask;
+ writeb(dev3.state, dev3.base);
+
+ spin_unlock_irqrestore(&dev3.lock, flags);
+}
+EXPORT_SYMBOL(set_latch_u5);
+
+unsigned char get_latch_u5(void)
+{
+ return dev3.state;
+}
+EXPORT_SYMBOL(get_latch_u5);
+
static struct resource korina_dev0_res[] = {
{
.name = "korina_regs",
@@ -86,7 +110,7 @@ static struct korina_device korina_dev0_data = {
static struct platform_device korina_dev0 = {
.id = -1,
.name = "korina",
- .dev.platform_data = &korina_dev0_data,
+ .dev.driver_data = &korina_dev0_data,
.resource = korina_dev0_res,
.num_resources = ARRAY_SIZE(korina_dev0_res),
};
@@ -214,12 +238,32 @@ static struct platform_device rb532_wdt = {
.num_resources = ARRAY_SIZE(rb532_wdt_res),
};
+static struct plat_serial8250_port rb532_uart_res[] = {
+ {
+ .membase = (char *)KSEG1ADDR(REGBASE + UART0BASE),
+ .irq = UART0_IRQ,
+ .regshift = 2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF,
+ },
+ {
+ .flags = 0,
+ }
+};
+
+static struct platform_device rb532_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev.platform_data = &rb532_uart_res,
+};
+
static struct platform_device *rb532_devs[] = {
&korina_dev0,
&nand_slot0,
&cf_slot0,
&rb532_led,
&rb532_button,
+ &rb532_uart,
&rb532_wdt
};
@@ -291,9 +335,20 @@ static int __init plat_setup_devices(void)
nand_slot0_res[0].start = readl(IDT434_REG_BASE + DEV2BASE);
nand_slot0_res[0].end = nand_slot0_res[0].start + 0x1000;
+ /* Read and map device controller 3 */
+ dev3.base = ioremap_nocache(readl(IDT434_REG_BASE + DEV3BASE), 1);
+
+ if (!dev3.base) {
+ printk(KERN_ERR "rb532: cannot remap device controller 3\n");
+ return -ENXIO;
+ }
+
/* Initialise the NAND device */
rb532_nand_setup();
+ /* set the uart clock to the current cpu frequency */
+ rb532_uart_res[0].uartclk = idt_cpu_freq;
+
return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
}
diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c
index 0e84c8ab6a39..37de05d595e7 100644
--- a/arch/mips/rb532/gpio.c
+++ b/arch/mips/rb532/gpio.c
@@ -41,8 +41,6 @@ struct rb532_gpio_chip {
void __iomem *regbase;
};
-struct mpmc_device dev3;
-
static struct resource rb532_gpio_reg0_res[] = {
{
.name = "gpio_reg0",
@@ -52,61 +50,6 @@ static struct resource rb532_gpio_reg0_res[] = {
}
};
-static struct resource rb532_dev3_ctl_res[] = {
- {
- .name = "dev3_ctl",
- .start = REGBASE + DEV3BASE,
- .end = REGBASE + DEV3BASE + sizeof(struct dev_reg) - 1,
- .flags = IORESOURCE_MEM,
- }
-};
-
-void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val)
-{
- unsigned long flags;
- unsigned data;
- unsigned i = 0;
-
- spin_lock_irqsave(&dev3.lock, flags);
-
- data = readl(IDT434_REG_BASE + reg_offs);
- for (i = 0; i != len; ++i) {
- if (val & (1 << i))
- data |= (1 << (i + bit));
- else
- data &= ~(1 << (i + bit));
- }
- writel(data, (IDT434_REG_BASE + reg_offs));
-
- spin_unlock_irqrestore(&dev3.lock, flags);
-}
-EXPORT_SYMBOL(set_434_reg);
-
-unsigned get_434_reg(unsigned reg_offs)
-{
- return readl(IDT434_REG_BASE + reg_offs);
-}
-EXPORT_SYMBOL(get_434_reg);
-
-void set_latch_u5(unsigned char or_mask, unsigned char nand_mask)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&dev3.lock, flags);
-
- dev3.state = (dev3.state | or_mask) & ~nand_mask;
- writel(dev3.state, &dev3.base);
-
- spin_unlock_irqrestore(&dev3.lock, flags);
-}
-EXPORT_SYMBOL(set_latch_u5);
-
-unsigned char get_latch_u5(void)
-{
- return dev3.state;
-}
-EXPORT_SYMBOL(get_latch_u5);
-
/* rb532_set_bit - sanely set a bit
*
* bitval: new value for the bit
@@ -119,13 +62,11 @@ static inline void rb532_set_bit(unsigned bitval,
unsigned long flags;
u32 val;
- bitval = !!bitval; /* map parameter to {0,1} */
-
local_irq_save(flags);
val = readl(ioaddr);
- val &= ~( ~bitval << offset ); /* unset bit if bitval == 0 */
- val |= ( bitval << offset ); /* set bit if bitval == 1 */
+ val &= ~(!bitval << offset); /* unset bit if bitval == 0 */
+ val |= (!!bitval << offset); /* set bit if bitval == 1 */
writel(val, ioaddr);
local_irq_restore(flags);
@@ -171,8 +112,8 @@ static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC))
- return 1; /* alternate function, GPIOCFG is ignored */
+ /* disable alternate function in case it's set */
+ rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC);
rb532_set_bit(0, offset, gpch->regbase + GPIOCFG);
return 0;
@@ -188,8 +129,8 @@ static int rb532_gpio_direction_output(struct gpio_chip *chip,
gpch = container_of(chip, struct rb532_gpio_chip, chip);
- if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC))
- return 1; /* alternate function, GPIOCFG is ignored */
+ /* disable alternate function in case it's set */
+ rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC);
/* set the initial output value */
rb532_set_bit(value, offset, gpch->regbase + GPIOD);
@@ -233,10 +174,11 @@ EXPORT_SYMBOL(rb532_gpio_set_istat);
/*
* Configure GPIO alternate function
*/
-static void rb532_gpio_set_func(int bit, unsigned gpio)
+void rb532_gpio_set_func(unsigned gpio)
{
- rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOFUNC);
+ rb532_set_bit(1, gpio, rb532_gpio_chip->regbase + GPIOFUNC);
}
+EXPORT_SYMBOL(rb532_gpio_set_func);
int __init rb532_gpio_init(void)
{
@@ -253,20 +195,6 @@ int __init rb532_gpio_init(void)
/* Register our GPIO chip */
gpiochip_add(&rb532_gpio_chip->chip);
- r = rb532_dev3_ctl_res;
- dev3.base = ioremap_nocache(r->start, r->end - r->start);
-
- if (!dev3.base) {
- printk(KERN_ERR "rb532: cannot remap device controller 3\n");
- return -ENXIO;
- }
-
- /* configure CF_GPIO_NUM as CFRDY IRQ source */
- rb532_gpio_set_func(0, CF_GPIO_NUM);
- rb532_gpio_direction_input(&rb532_gpio_chip->chip, CF_GPIO_NUM);
- rb532_gpio_set_ilevel(1, CF_GPIO_NUM);
- rb532_gpio_set_istat(0, CF_GPIO_NUM);
-
return 0;
}
arch_initcall(rb532_gpio_init);
diff --git a/arch/mips/rb532/irq.c b/arch/mips/rb532/irq.c
index 549b46d2fcee..53eeb5e7bc5b 100644
--- a/arch/mips/rb532/irq.c
+++ b/arch/mips/rb532/irq.c
@@ -46,6 +46,7 @@
#include <asm/system.h>
#include <asm/mach-rc32434/irq.h>
+#include <asm/mach-rc32434/gpio.h>
struct intr_group {
u32 mask; /* mask of valid bits in pending/mask registers */
@@ -150,6 +151,9 @@ static void rb532_disable_irq(unsigned int irq_nr)
mask |= intr_bit;
WRITE_MASK(addr, mask);
+ if (group == GPIO_MAPPED_IRQ_GROUP)
+ rb532_gpio_set_istat(0, irq_nr - GPIO_MAPPED_IRQ_BASE);
+
/*
* if there are no more interrupts enabled in this
* group, disable corresponding IP
@@ -165,12 +169,35 @@ static void rb532_mask_and_ack_irq(unsigned int irq_nr)
ack_local_irq(group_to_ip(irq_to_group(irq_nr)));
}
+static int rb532_set_type(unsigned int irq_nr, unsigned type)
+{
+ int gpio = irq_nr - GPIO_MAPPED_IRQ_BASE;
+ int group = irq_to_group(irq_nr);
+
+ if (group != GPIO_MAPPED_IRQ_GROUP)
+ return (type == IRQ_TYPE_LEVEL_HIGH) ? 0 : -EINVAL;
+
+ switch (type) {
+ case IRQ_TYPE_LEVEL_HIGH:
+ rb532_gpio_set_ilevel(1, gpio);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ rb532_gpio_set_ilevel(0, gpio);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static struct irq_chip rc32434_irq_type = {
.name = "RB532",
.ack = rb532_disable_irq,
.mask = rb532_disable_irq,
.mask_ack = rb532_mask_and_ack_irq,
.unmask = rb532_enable_irq,
+ .set_type = rb532_set_type,
};
void __init arch_init_irq(void)
diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c
index 3e0d7ec3a579..00ed19f0bdb5 100644
--- a/arch/mips/rb532/serial.c
+++ b/arch/mips/rb532/serial.c
@@ -36,7 +36,7 @@
extern unsigned int idt_cpu_freq;
static struct uart_port rb532_uart = {
- .type = PORT_16550A,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
.irq = UART0_IRQ,
.iotype = UPIO_MEM,
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
index ba5cdebeaf0d..5b47d6b65275 100644
--- a/arch/mips/sgi-ip27/ip27-smp.c
+++ b/arch/mips/sgi-ip27/ip27-smp.c
@@ -76,7 +76,7 @@ static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest)
/* Only let it join in if it's marked enabled */
if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
(tot_cpus_found != NR_CPUS)) {
- cpu_set(cpuid, phys_cpu_present_map);
+ cpu_set(cpuid, cpu_possible_map);
alloc_cpupda(cpuid, tot_cpus_found);
cpus_found++;
tot_cpus_found++;
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 1327c2746fb7..f024057a35f8 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -134,7 +134,7 @@ void __cpuinit hub_rt_clock_event_init(void)
cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
cd->rating = 200;
cd->irq = irq;
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
cd->set_next_event = rt_next_event;
cd->set_mode = rt_set_mode;
clockevents_register_device(cd);
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index a35818ed4263..12b465d404df 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -50,7 +50,7 @@ static void enable_bcm1480_irq(unsigned int irq);
static void disable_bcm1480_irq(unsigned int irq);
static void ack_bcm1480_irq(unsigned int irq);
#ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask);
+static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
#endif
#ifdef CONFIG_PCI
@@ -109,7 +109,7 @@ void bcm1480_unmask_irq(int cpu, int irq)
}
#ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
+static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
{
int i = 0, old_cpu, cpu, int_on, k;
u64 cur_ints;
@@ -117,11 +117,11 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
unsigned long flags;
unsigned int irq_dirty;
- if (cpus_weight(mask) != 1) {
+ if (cpumask_weight(mask) != 1) {
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
return;
}
- i = first_cpu(mask);
+ i = cpumask_first(mask);
/* Convert logical CPU to physical CPU */
cpu = cpu_logical_map(i);
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index bd9eeb43ed0e..dddfda8e8294 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -136,7 +136,7 @@ static void __cpuinit bcm1480_boot_secondary(int cpu, struct task_struct *idle)
/*
* Use CFE to find out how many CPUs are available, setting up
- * phys_cpu_present_map and the logical/physical mappings.
+ * cpu_possible_map and the logical/physical mappings.
* XXXKW will the boot CPU ever not be physical 0?
*
* Common setup before any secondaries are started
@@ -145,14 +145,14 @@ static void __init bcm1480_smp_setup(void)
{
int i, num;
- cpus_clear(phys_cpu_present_map);
- cpu_set(0, phys_cpu_present_map);
+ cpus_clear(cpu_possible_map);
+ cpu_set(0, cpu_possible_map);
__cpu_number_map[0] = 0;
__cpu_logical_map[0] = 0;
for (i = 1, num = 0; i < NR_CPUS; i++) {
if (cfe_cpu_stop(i) == 0) {
- cpu_set(i, phys_cpu_present_map);
+ cpu_set(i, cpu_possible_map);
__cpu_number_map[i] = ++num;
__cpu_logical_map[num] = i;
}
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index a5158483986e..808ac2959b8c 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -50,7 +50,7 @@ static void enable_sb1250_irq(unsigned int irq);
static void disable_sb1250_irq(unsigned int irq);
static void ack_sb1250_irq(unsigned int irq);
#ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, cpumask_t mask);
+static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
#endif
#ifdef CONFIG_SIBYTE_HAS_LDT
@@ -103,16 +103,16 @@ void sb1250_unmask_irq(int cpu, int irq)
}
#ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
+static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
{
int i = 0, old_cpu, cpu, int_on;
u64 cur_ints;
struct irq_desc *desc = irq_desc + irq;
unsigned long flags;
- i = first_cpu(mask);
+ i = cpumask_first(mask);
- if (cpus_weight(mask) > 1) {
+ if (cpumask_weight(mask) > 1) {
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
return;
}
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index 0734b933e969..5950a288a7da 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -124,7 +124,7 @@ static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle)
/*
* Use CFE to find out how many CPUs are available, setting up
- * phys_cpu_present_map and the logical/physical mappings.
+ * cpu_possible_map and the logical/physical mappings.
* XXXKW will the boot CPU ever not be physical 0?
*
* Common setup before any secondaries are started
@@ -133,14 +133,14 @@ static void __init sb1250_smp_setup(void)
{
int i, num;
- cpus_clear(phys_cpu_present_map);
- cpu_set(0, phys_cpu_present_map);
+ cpus_clear(cpu_possible_map);
+ cpu_set(0, cpu_possible_map);
__cpu_number_map[0] = 0;
__cpu_logical_map[0] = 0;
for (i = 1, num = 0; i < NR_CPUS; i++) {
if (cfe_cpu_stop(i) == 0) {
- cpu_set(i, phys_cpu_present_map);
+ cpu_set(i, cpu_possible_map);
__cpu_number_map[i] = ++num;
__cpu_logical_map[num] = i;
}
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 796e3ce28720..69f5f88711cc 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -80,7 +80,7 @@ static void __init sni_a20r_timer_setup(void)
struct irqaction *action = &a20r_irqaction;
unsigned int cpu = smp_processor_id();
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
clockevents_register_device(cd);
action->dev_id = cd;
setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction);
diff --git a/arch/mips/txx9/generic/setup_tx4939.c b/arch/mips/txx9/generic/setup_tx4939.c
index 6c0049a5bbc1..55440967b3a8 100644
--- a/arch/mips/txx9/generic/setup_tx4939.c
+++ b/arch/mips/txx9/generic/setup_tx4939.c
@@ -435,6 +435,28 @@ void __init tx4939_ata_init(void)
platform_device_register(&ata1_dev);
}
+void __init tx4939_rtc_init(void)
+{
+ static struct resource res[] = {
+ {
+ .start = TX4939_RTC_REG & 0xfffffffffULL,
+ .end = (TX4939_RTC_REG & 0xfffffffffULL) + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = TXX9_IRQ_BASE + TX4939_IR_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+ static struct platform_device rtc_dev = {
+ .name = "tx4939rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(res),
+ .resource = res,
+ };
+
+ platform_device_register(&rtc_dev);
+}
+
static void __init tx4939_stop_unused_modules(void)
{
__u64 pcfg, rst = 0, ckd = 0;
diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c
index 98fbd9391bf8..656603b85b71 100644
--- a/arch/mips/txx9/rbtx4939/setup.c
+++ b/arch/mips/txx9/rbtx4939/setup.c
@@ -336,6 +336,7 @@ static void __init rbtx4939_device_init(void)
rbtx4939_led_setup();
tx4939_wdt_init();
tx4939_ata_init();
+ tx4939_rtc_init();
}
static void __init rbtx4939_setup(void)
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index 62fba8aa9b6e..ceeaaaa359e2 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -478,7 +478,7 @@ ENTRY(sys_call_table)
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/mn10300/kernel/init_task.c b/arch/mn10300/kernel/init_task.c
index af16f6e5c918..5ac3566f8c98 100644
--- a/arch/mn10300/kernel/init_task.c
+++ b/arch/mn10300/kernel/init_task.c
@@ -18,7 +18,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 644a70b1b04e..aacf11d33723 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -11,6 +11,7 @@ config PARISC
select HAVE_OPROFILE
select RTC_CLASS
select RTC_DRV_PARISC
+ select INIT_ALL_POSSIBLE
help
The PA-RISC microprocessor is designed by Hewlett-Packard and used
in many of their workstations & servers (HP9000 700 and 800 series,
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 5ddad7bd60ac..0d428278356d 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -77,7 +77,7 @@ libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`
drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/
-PALO := $(shell if which palo; then : ; \
+PALO := $(shell if (which palo 2>&1); then : ; \
elif [ -x /sbin/palo ]; then echo /sbin/palo; \
fi)
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index 57fcc4a5ebb4..edbfe25c5fc1 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -155,14 +155,11 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
#endif
-/* Note that we need not lock read accesses - aligned word writes/reads
- * are atomic, so a reader never sees unconsistent values.
- *
- * Cache-line alignment would conflict with, for example, linux/module.h
+/*
+ * Note that we need not lock read accesses - aligned word writes/reads
+ * are atomic, so a reader never sees inconsistent values.
*/
-typedef struct { volatile int counter; } atomic_t;
-
/* It's possible to reduce all atomic operations to either
* __atomic_add_return, atomic_set and atomic_read (the latter
* is there only for consistency).
@@ -260,8 +257,6 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#ifdef CONFIG_64BIT
-typedef struct { volatile s64 counter; } atomic64_t;
-
#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
static __inline__ int
diff --git a/arch/parisc/include/asm/byteorder.h b/arch/parisc/include/asm/byteorder.h
index db148313de5d..58af2c5f5d61 100644
--- a/arch/parisc/include/asm/byteorder.h
+++ b/arch/parisc/include/asm/byteorder.h
@@ -1,82 +1,6 @@
#ifndef _PARISC_BYTEORDER_H
#define _PARISC_BYTEORDER_H
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#ifdef __GNUC__
-
-static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
-{
- __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
- "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */
- : "=r" (x)
- : "0" (x));
- return x;
-}
-
-static __inline__ __attribute_const__ __u32 ___arch__swab24(__u32 x)
-{
- __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */
- "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */
- "shd %%r0, %0, 8, %0" /* shift 0000cbab -> 0cba */
- : "=r" (x)
- : "0" (x));
- return x;
-}
-
-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
-{
- unsigned int temp;
- __asm__("shd %0, %0, 16, %1\n\t" /* shift abcdabcd -> cdab */
- "dep %1, 15, 8, %1\n\t" /* deposit cdab -> cbab */
- "shd %0, %1, 8, %0" /* shift abcdcbab -> dcba */
- : "=r" (x), "=&r" (temp)
- : "0" (x));
- return x;
-}
-
-
-#if BITS_PER_LONG > 32
-/*
-** From "PA-RISC 2.0 Architecture", HP Professional Books.
-** See Appendix I page 8 , "Endian Byte Swapping".
-**
-** Pretty cool algorithm: (* == zero'd bits)
-** PERMH 01234567 -> 67452301 into %0
-** HSHL 67452301 -> 7*5*3*1* into %1
-** HSHR 67452301 -> *6*4*2*0 into %0
-** OR %0 | %1 -> 76543210 into %0 (all done!)
-*/
-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x) {
- __u64 temp;
- __asm__("permh,3210 %0, %0\n\t"
- "hshl %0, 8, %1\n\t"
- "hshr,u %0, 8, %0\n\t"
- "or %1, %0, %0"
- : "=r" (x), "=&r" (temp)
- : "0" (x));
- return x;
-}
-#define __arch__swab64(x) ___arch__swab64(x)
-#define __BYTEORDER_HAS_U64__
-#elif !defined(__STRICT_ANSI__)
-static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
-{
- __u32 t1 = ___arch__swab32((__u32) x);
- __u32 t2 = ___arch__swab32((__u32) (x >> 32));
- return (((__u64) t1 << 32) | t2);
-}
-#define __arch__swab64(x) ___arch__swab64(x)
-#define __BYTEORDER_HAS_U64__
-#endif
-
-#define __arch__swab16(x) ___arch__swab16(x)
-#define __arch__swab24(x) ___arch__swab24(x)
-#define __arch__swab32(x) ___arch__swab32(x)
-
-#endif /* __GNUC__ */
-
#include <linux/byteorder/big_endian.h>
#endif /* _PARISC_BYTEORDER_H */
diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h
index e9639ccc3fce..c84b2fcb18a9 100644
--- a/arch/parisc/include/asm/checksum.h
+++ b/arch/parisc/include/asm/checksum.h
@@ -182,7 +182,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
#endif
: "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len)
: "0" (sum), "1" (saddr), "2" (daddr), "3" (len), "r" (proto)
- : "r19", "r20", "r21", "r22");
+ : "r19", "r20", "r21", "r22", "memory");
return csum_fold(sum);
}
diff --git a/arch/parisc/include/asm/dma-mapping.h b/arch/parisc/include/asm/dma-mapping.h
index 53af696f23d2..da6943380908 100644
--- a/arch/parisc/include/asm/dma-mapping.h
+++ b/arch/parisc/include/asm/dma-mapping.h
@@ -5,7 +5,7 @@
#include <asm/cacheflush.h>
#include <asm/scatterlist.h>
-/* See Documentation/DMA-mapping.txt */
+/* See Documentation/PCI/PCI-DMA-mapping.txt */
struct hppa_dma_ops {
int (*dma_supported)(struct device *dev, u64 mask);
void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *iova, gfp_t flag);
diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h
index 55ddb1842107..d3031d1f9d03 100644
--- a/arch/parisc/include/asm/io.h
+++ b/arch/parisc/include/asm/io.h
@@ -4,12 +4,6 @@
#include <linux/types.h>
#include <asm/pgtable.h>
-extern unsigned long parisc_vmerge_boundary;
-extern unsigned long parisc_vmerge_max_size;
-
-#define BIO_VMERGE_BOUNDARY parisc_vmerge_boundary
-#define BIO_VMERGE_MAX_SIZE parisc_vmerge_max_size
-
#define virt_to_phys(a) ((unsigned long)__pa(a))
#define phys_to_virt(a) __va(a)
#define virt_to_bus virt_to_phys
@@ -182,9 +176,9 @@ static inline void __raw_writeq(unsigned long long b, volatile void __iomem *add
/* readb can never be const, so use __fswab instead of le*_to_cpu */
#define readb(addr) __raw_readb(addr)
-#define readw(addr) __fswab16(__raw_readw(addr))
-#define readl(addr) __fswab32(__raw_readl(addr))
-#define readq(addr) __fswab64(__raw_readq(addr))
+#define readw(addr) le16_to_cpu(__raw_readw(addr))
+#define readl(addr) le32_to_cpu(__raw_readl(addr))
+#define readq(addr) le64_to_cpu(__raw_readq(addr))
#define writeb(b, addr) __raw_writeb(b, addr)
#define writew(b, addr) __raw_writew(cpu_to_le16(b), addr)
#define writel(b, addr) __raw_writel(cpu_to_le32(b), addr)
diff --git a/arch/parisc/include/asm/mmu_context.h b/arch/parisc/include/asm/mmu_context.h
index 85856c74ad1d..354b2aca990e 100644
--- a/arch/parisc/include/asm/mmu_context.h
+++ b/arch/parisc/include/asm/mmu_context.h
@@ -34,16 +34,21 @@ destroy_context(struct mm_struct *mm)
mm->context = 0;
}
-static inline void load_context(mm_context_t context)
+static inline unsigned long __space_to_prot(mm_context_t context)
{
- mtsp(context, 3);
#if SPACEID_SHIFT == 0
- mtctl(context << 1,8);
+ return context << 1;
#else
- mtctl(context >> (SPACEID_SHIFT - 1),8);
+ return context >> (SPACEID_SHIFT - 1);
#endif
}
+static inline void load_context(mm_context_t context)
+{
+ mtsp(context, 3);
+ mtctl(__space_to_prot(context), 8);
+}
+
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
{
diff --git a/arch/parisc/include/asm/module.h b/arch/parisc/include/asm/module.h
index c2cb49e934c1..1f4123427ea0 100644
--- a/arch/parisc/include/asm/module.h
+++ b/arch/parisc/include/asm/module.h
@@ -23,8 +23,10 @@ struct mod_arch_specific
{
unsigned long got_offset, got_count, got_max;
unsigned long fdesc_offset, fdesc_count, fdesc_max;
- unsigned long stub_offset, stub_count, stub_max;
- unsigned long init_stub_offset, init_stub_count, init_stub_max;
+ struct {
+ unsigned long stub_offset;
+ unsigned int stub_entries;
+ } *section;
int unwind_section;
struct unwind_table *unwind;
};
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 3c9d34844c83..9d64df8754ba 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -17,6 +17,7 @@
#include <asm/ptrace.h>
#include <asm/types.h>
#include <asm/system.h>
+#include <asm/percpu.h>
#endif /* __ASSEMBLY__ */
#define KERNEL_STACK_SIZE (4*PAGE_SIZE)
@@ -109,8 +110,7 @@ struct cpuinfo_parisc {
};
extern struct system_cpuinfo_parisc boot_cpu_data;
-extern struct cpuinfo_parisc cpu_data[NR_CPUS];
-#define current_cpu_data cpu_data[smp_processor_id()]
+DECLARE_PER_CPU(struct cpuinfo_parisc, cpu_data);
#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
diff --git a/arch/parisc/include/asm/smp.h b/arch/parisc/include/asm/smp.h
index 409e698f4361..6ef4b7867b1b 100644
--- a/arch/parisc/include/asm/smp.h
+++ b/arch/parisc/include/asm/smp.h
@@ -16,8 +16,6 @@
#include <linux/cpumask.h>
typedef unsigned long address_t;
-extern cpumask_t cpu_online_map;
-
/*
* Private routines/data
diff --git a/arch/parisc/include/asm/swab.h b/arch/parisc/include/asm/swab.h
new file mode 100644
index 000000000000..3ff16c5a3358
--- /dev/null
+++ b/arch/parisc/include/asm/swab.h
@@ -0,0 +1,66 @@
+#ifndef _PARISC_SWAB_H
+#define _PARISC_SWAB_H
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+
+#define __SWAB_64_THRU_32__
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
+{
+ __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
+ "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */
+ : "=r" (x)
+ : "0" (x));
+ return x;
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __attribute_const__ __u32 __arch_swab24(__u32 x)
+{
+ __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */
+ "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */
+ "shd %%r0, %0, 8, %0" /* shift 0000cbab -> 0cba */
+ : "=r" (x)
+ : "0" (x));
+ return x;
+}
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+ unsigned int temp;
+ __asm__("shd %0, %0, 16, %1\n\t" /* shift abcdabcd -> cdab */
+ "dep %1, 15, 8, %1\n\t" /* deposit cdab -> cbab */
+ "shd %0, %1, 8, %0" /* shift abcdcbab -> dcba */
+ : "=r" (x), "=&r" (temp)
+ : "0" (x));
+ return x;
+}
+#define __arch_swab32 __arch_swab32
+
+#if BITS_PER_LONG > 32
+/*
+** From "PA-RISC 2.0 Architecture", HP Professional Books.
+** See Appendix I page 8 , "Endian Byte Swapping".
+**
+** Pretty cool algorithm: (* == zero'd bits)
+** PERMH 01234567 -> 67452301 into %0
+** HSHL 67452301 -> 7*5*3*1* into %1
+** HSHR 67452301 -> *6*4*2*0 into %0
+** OR %0 | %1 -> 76543210 into %0 (all done!)
+*/
+static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
+{
+ __u64 temp;
+ __asm__("permh,3210 %0, %0\n\t"
+ "hshl %0, 8, %1\n\t"
+ "hshr,u %0, 8, %0\n\t"
+ "or %1, %0, %0"
+ : "=r" (x), "=&r" (temp)
+ : "0" (x));
+ return x;
+}
+#define __arch_swab64 __arch_swab64
+#endif /* BITS_PER_LONG > 32 */
+
+#endif /* _PARISC_SWAB_H */
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 4878b9501f24..1c6dbb6f6e56 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -241,4 +241,6 @@ unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned lo
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
+int fixup_exception(struct pt_regs *regs);
+
#endif /* __PARISC_UACCESS_H */
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 884b7ce16a3b..994bcd980909 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -549,6 +549,38 @@ static int parisc_generic_match(struct device *dev, struct device_driver *drv)
return match_device(to_parisc_driver(drv), to_parisc_device(dev));
}
+static ssize_t make_modalias(struct device *dev, char *buf)
+{
+ const struct parisc_device *padev = to_parisc_device(dev);
+ const struct parisc_device_id *id = &padev->id;
+
+ return sprintf(buf, "parisc:t%02Xhv%04Xrev%02Xsv%08X\n",
+ (u8)id->hw_type, (u16)id->hversion, (u8)id->hversion_rev,
+ (u32)id->sversion);
+}
+
+static int parisc_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ const struct parisc_device *padev;
+ char modalias[40];
+
+ if (!dev)
+ return -ENODEV;
+
+ padev = to_parisc_device(dev);
+ if (!padev)
+ return -ENODEV;
+
+ if (add_uevent_var(env, "PARISC_NAME=%s", padev->name))
+ return -ENOMEM;
+
+ make_modalias(dev, modalias);
+ if (add_uevent_var(env, "MODALIAS=%s", modalias))
+ return -ENOMEM;
+
+ return 0;
+}
+
#define pa_dev_attr(name, field, format_string) \
static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
@@ -566,12 +598,7 @@ pa_dev_attr_id(sversion, "0x%05x\n");
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct parisc_device *padev = to_parisc_device(dev);
- struct parisc_device_id *id = &padev->id;
-
- return sprintf(buf, "parisc:t%02Xhv%04Xrev%02Xsv%08X\n",
- (u8)id->hw_type, (u16)id->hversion, (u8)id->hversion_rev,
- (u32)id->sversion);
+ return make_modalias(dev, buf);
}
static struct device_attribute parisc_device_attrs[] = {
@@ -587,6 +614,7 @@ static struct device_attribute parisc_device_attrs[] = {
struct bus_type parisc_bus_type = {
.name = "parisc",
.match = parisc_generic_match,
+ .uevent = parisc_uevent,
.dev_attrs = parisc_device_attrs,
.probe = parisc_driver_probe,
.remove = parisc_driver_remove,
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index 2cbf13b3ef11..5595a2f31181 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -80,6 +80,7 @@ END(hpmc_pim_data)
.import intr_save, code
ENTRY(os_hpmc)
+.os_hpmc:
/*
* registers modified:
@@ -295,5 +296,10 @@ os_hpmc_6:
b .
nop
ENDPROC(os_hpmc)
-ENTRY(os_hpmc_end) /* this label used to compute os_hpmc checksum */
+.os_hpmc_end:
nop
+.data
+.align 4
+ .export os_hpmc_size
+os_hpmc_size:
+ .word .os_hpmc_end-.os_hpmc
diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c
index f5941c086551..1e25a45d64c1 100644
--- a/arch/parisc/kernel/init_task.c
+++ b/arch/parisc/kernel/init_task.c
@@ -34,7 +34,6 @@
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index 23ef950df008..ac2c822928c7 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -131,12 +131,12 @@ int cpu_check_affinity(unsigned int irq, cpumask_t *dest)
return 0;
}
-static void cpu_set_affinity_irq(unsigned int irq, cpumask_t dest)
+static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
{
- if (cpu_check_affinity(irq, &dest))
+ if (cpu_check_affinity(irq, dest))
return;
- irq_desc[irq].affinity = dest;
+ irq_desc[irq].affinity = *dest;
}
#endif
@@ -298,7 +298,7 @@ unsigned long txn_affinity_addr(unsigned int irq, int cpu)
irq_desc[irq].affinity = cpumask_of_cpu(cpu);
#endif
- return cpu_data[cpu].txn_addr;
+ return per_cpu(cpu_data, cpu).txn_addr;
}
@@ -309,8 +309,9 @@ unsigned long txn_alloc_addr(unsigned int virt_irq)
next_cpu++; /* assign to "next" CPU we want this bugger on */
/* validate entry */
- while ((next_cpu < NR_CPUS) && (!cpu_data[next_cpu].txn_addr ||
- !cpu_online(next_cpu)))
+ while ((next_cpu < NR_CPUS) &&
+ (!per_cpu(cpu_data, next_cpu).txn_addr ||
+ !cpu_online(next_cpu)))
next_cpu++;
if (next_cpu >= NR_CPUS)
@@ -359,7 +360,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n",
irq, smp_processor_id(), cpu);
gsc_writel(irq + CPU_IRQ_BASE,
- cpu_data[cpu].hpa);
+ per_cpu(cpu_data, cpu).hpa);
goto set_out;
}
#endif
@@ -421,5 +422,5 @@ void __init init_IRQ(void)
void ack_bad_irq(unsigned int irq)
{
- printk("unexpected IRQ %d\n", irq);
+ printk(KERN_WARNING "unexpected IRQ %d\n", irq);
}
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index 44138c3e6ea7..9013243cecca 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -6,6 +6,7 @@
*
* Linux/PA-RISC Project (http://www.parisc-linux.org/)
* Copyright (C) 2003 Randolph Chung <tausq at debian . org>
+ * Copyright (C) 2008 Helge Deller <deller@gmx.de>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +25,19 @@
*
*
* Notes:
+ * - PLT stub handling
+ * On 32bit (and sometimes 64bit) and with big kernel modules like xfs or
+ * ipv6 the relocation types R_PARISC_PCREL17F and R_PARISC_PCREL22F may
+ * fail to reach their PLT stub if we only create one big stub array for
+ * all sections at the beginning of the core or init section.
+ * Instead we now insert individual PLT stub entries directly in front of
+ * of the code sections where the stubs are actually called.
+ * This reduces the distance between the PCREL location and the stub entry
+ * so that the relocations can be fulfilled.
+ * While calculating the final layout of the kernel module in memory, the
+ * kernel module loader calls arch_mod_section_prepend() to request the
+ * to be reserved amount of memory in front of each individual section.
+ *
* - SEGREL32 handling
* We are not doing SEGREL32 handling correctly. According to the ABI, we
* should do a value offset, like this:
@@ -58,9 +72,13 @@
#define DEBUGP(fmt...)
#endif
+#define RELOC_REACHABLE(val, bits) \
+ (( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
+ ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) ? \
+ 0 : 1)
+
#define CHECK_RELOC(val, bits) \
- if ( ( !((val) & (1<<((bits)-1))) && ((val)>>(bits)) != 0 ) || \
- ( ((val) & (1<<((bits)-1))) && ((val)>>(bits)) != (((__typeof__(val))(~0))>>((bits)+2)))) { \
+ if (!RELOC_REACHABLE(val, bits)) { \
printk(KERN_ERR "module %s relocation of symbol %s is out of range (0x%lx in %d bits)\n", \
me->name, strtab + sym->st_name, (unsigned long)val, bits); \
return -ENOEXEC; \
@@ -92,13 +110,6 @@ static inline int in_local(struct module *me, void *loc)
return in_init(me, loc) || in_core(me, loc);
}
-static inline int in_local_section(struct module *me, void *loc, void *dot)
-{
- return (in_init(me, loc) && in_init(me, dot)) ||
- (in_core(me, loc) && in_core(me, dot));
-}
-
-
#ifndef CONFIG_64BIT
struct got_entry {
Elf32_Addr addr;
@@ -258,23 +269,42 @@ static inline unsigned long count_stubs(const Elf_Rela *rela, unsigned long n)
/* Free memory returned from module_alloc */
void module_free(struct module *mod, void *module_region)
{
+ kfree(mod->arch.section);
+ mod->arch.section = NULL;
+
vfree(module_region);
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
}
+/* Additional bytes needed in front of individual sections */
+unsigned int arch_mod_section_prepend(struct module *mod,
+ unsigned int section)
+{
+ /* size needed for all stubs of this section (including
+ * one additional for correct alignment of the stubs) */
+ return (mod->arch.section[section].stub_entries + 1)
+ * sizeof(struct stub_entry);
+}
+
#define CONST
int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
CONST Elf_Shdr *sechdrs,
CONST char *secstrings,
struct module *me)
{
- unsigned long gots = 0, fdescs = 0, stubs = 0, init_stubs = 0;
+ unsigned long gots = 0, fdescs = 0, len;
unsigned int i;
+ len = hdr->e_shnum * sizeof(me->arch.section[0]);
+ me->arch.section = kzalloc(len, GFP_KERNEL);
+ if (!me->arch.section)
+ return -ENOMEM;
+
for (i = 1; i < hdr->e_shnum; i++) {
- const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset;
+ const Elf_Rela *rels = (void *)sechdrs[i].sh_addr;
unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
+ unsigned int count, s;
if (strncmp(secstrings + sechdrs[i].sh_name,
".PARISC.unwind", 14) == 0)
@@ -290,11 +320,23 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
*/
gots += count_gots(rels, nrels);
fdescs += count_fdescs(rels, nrels);
- if(strncmp(secstrings + sechdrs[i].sh_name,
- ".rela.init", 10) == 0)
- init_stubs += count_stubs(rels, nrels);
- else
- stubs += count_stubs(rels, nrels);
+
+ /* XXX: By sorting the relocs and finding duplicate entries
+ * we could reduce the number of necessary stubs and save
+ * some memory. */
+ count = count_stubs(rels, nrels);
+ if (!count)
+ continue;
+
+ /* so we need relocation stubs. reserve necessary memory. */
+ /* sh_info gives the section for which we need to add stubs. */
+ s = sechdrs[i].sh_info;
+
+ /* each code section should only have one relocation section */
+ WARN_ON(me->arch.section[s].stub_entries);
+
+ /* store number of stubs we need for this section */
+ me->arch.section[s].stub_entries += count;
}
/* align things a bit */
@@ -306,18 +348,8 @@ int module_frob_arch_sections(CONST Elf_Ehdr *hdr,
me->arch.fdesc_offset = me->core_size;
me->core_size += fdescs * sizeof(Elf_Fdesc);
- me->core_size = ALIGN(me->core_size, 16);
- me->arch.stub_offset = me->core_size;
- me->core_size += stubs * sizeof(struct stub_entry);
-
- me->init_size = ALIGN(me->init_size, 16);
- me->arch.init_stub_offset = me->init_size;
- me->init_size += init_stubs * sizeof(struct stub_entry);
-
me->arch.got_max = gots;
me->arch.fdesc_max = fdescs;
- me->arch.stub_max = stubs;
- me->arch.init_stub_max = init_stubs;
return 0;
}
@@ -380,23 +412,27 @@ enum elf_stub_type {
};
static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
- enum elf_stub_type stub_type, int init_section)
+ enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec)
{
- unsigned long i;
struct stub_entry *stub;
- if(init_section) {
- i = me->arch.init_stub_count++;
- BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
- stub = me->module_init + me->arch.init_stub_offset +
- i * sizeof(struct stub_entry);
- } else {
- i = me->arch.stub_count++;
- BUG_ON(me->arch.stub_count > me->arch.stub_max);
- stub = me->module_core + me->arch.stub_offset +
- i * sizeof(struct stub_entry);
+ /* initialize stub_offset to point in front of the section */
+ if (!me->arch.section[targetsec].stub_offset) {
+ loc0 -= (me->arch.section[targetsec].stub_entries + 1) *
+ sizeof(struct stub_entry);
+ /* get correct alignment for the stubs */
+ loc0 = ALIGN(loc0, sizeof(struct stub_entry));
+ me->arch.section[targetsec].stub_offset = loc0;
}
+ /* get address of stub entry */
+ stub = (void *) me->arch.section[targetsec].stub_offset;
+ me->arch.section[targetsec].stub_offset += sizeof(struct stub_entry);
+
+ /* do not write outside available stub area */
+ BUG_ON(0 == me->arch.section[targetsec].stub_entries--);
+
+
#ifndef CONFIG_64BIT
/* for 32-bit the stub looks like this:
* ldil L'XXX,%r1
@@ -489,15 +525,19 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf32_Addr val;
Elf32_Sword addend;
Elf32_Addr dot;
+ Elf_Addr loc0;
+ unsigned int targetsec = sechdrs[relsec].sh_info;
//unsigned long dp = (unsigned long)$global$;
register unsigned long dp asm ("r27");
DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
+ targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
- loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset;
+ /* This is the start of the target section */
+ loc0 = sechdrs[targetsec].sh_addr;
/* This is the symbol it is referring to */
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rel[i].r_info);
@@ -569,19 +609,32 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
break;
case R_PARISC_PCREL17F:
/* 17-bit PC relative address */
- val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
+ /* calculate direct call offset */
+ val += addend;
val = (val - dot - 8)/4;
- CHECK_RELOC(val, 17)
+ if (!RELOC_REACHABLE(val, 17)) {
+ /* direct distance too far, create
+ * stub entry instead */
+ val = get_stub(me, sym->st_value, addend,
+ ELF_STUB_DIRECT, loc0, targetsec);
+ val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 17);
+ }
*loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
break;
case R_PARISC_PCREL22F:
/* 22-bit PC relative address; only defined for pa20 */
- val = get_stub(me, val, addend, ELF_STUB_GOT, in_init(me, loc));
- DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n",
- strtab + sym->st_name, (unsigned long)loc, addend,
- val)
+ /* calculate direct call offset */
+ val += addend;
val = (val - dot - 8)/4;
- CHECK_RELOC(val, 22);
+ if (!RELOC_REACHABLE(val, 22)) {
+ /* direct distance too far, create
+ * stub entry instead */
+ val = get_stub(me, sym->st_value, addend,
+ ELF_STUB_DIRECT, loc0, targetsec);
+ val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 22);
+ }
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break;
@@ -610,13 +663,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
Elf64_Addr val;
Elf64_Sxword addend;
Elf64_Addr dot;
+ Elf_Addr loc0;
+ unsigned int targetsec = sechdrs[relsec].sh_info;
DEBUGP("Applying relocate section %u to %u\n", relsec,
- sechdrs[relsec].sh_info);
+ targetsec);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
- loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ loc = (void *)sechdrs[targetsec].sh_addr
+ rel[i].r_offset;
+ /* This is the start of the target section */
+ loc0 = sechdrs[targetsec].sh_addr;
/* This is the symbol it is referring to */
sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
+ ELF64_R_SYM(rel[i].r_info);
@@ -672,42 +729,40 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
DEBUGP("PCREL22F Symbol %s loc %p val %lx\n",
strtab + sym->st_name,
loc, val);
+ val += addend;
/* can we reach it locally? */
- if(!in_local_section(me, (void *)val, (void *)dot)) {
-
- if (in_local(me, (void *)val))
- /* this is the case where the
- * symbol is local to the
- * module, but in a different
- * section, so stub the jump
- * in case it's more than 22
- * bits away */
- val = get_stub(me, val, addend, ELF_STUB_DIRECT,
- in_init(me, loc));
- else if (strncmp(strtab + sym->st_name, "$$", 2)
+ if (in_local(me, (void *)val)) {
+ /* this is the case where the symbol is local
+ * to the module, but in a different section,
+ * so stub the jump in case it's more than 22
+ * bits away */
+ val = (val - dot - 8)/4;
+ if (!RELOC_REACHABLE(val, 22)) {
+ /* direct distance too far, create
+ * stub entry instead */
+ val = get_stub(me, sym->st_value,
+ addend, ELF_STUB_DIRECT,
+ loc0, targetsec);
+ } else {
+ /* Ok, we can reach it directly. */
+ val = sym->st_value;
+ val += addend;
+ }
+ } else {
+ val = sym->st_value;
+ if (strncmp(strtab + sym->st_name, "$$", 2)
== 0)
val = get_stub(me, val, addend, ELF_STUB_MILLI,
- in_init(me, loc));
+ loc0, targetsec);
else
val = get_stub(me, val, addend, ELF_STUB_GOT,
- in_init(me, loc));
+ loc0, targetsec);
}
DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n",
strtab + sym->st_name, loc, sym->st_value,
addend, val);
- /* FIXME: local symbols work as long as the
- * core and init pieces aren't separated too
- * far. If this is ever broken, you will trip
- * the check below. The way to fix it would
- * be to generate local stubs to go between init
- * and core */
- if((Elf64_Sxword)(val - dot - 8) > 0x800000 -1 ||
- (Elf64_Sxword)(val - dot - 8) < -0x800000) {
- printk(KERN_ERR "Module %s, symbol %s is out of range for PCREL22F relocation\n",
- me->name, strtab + sym->st_name);
- return -ENOEXEC;
- }
val = (val - dot - 8)/4;
+ CHECK_RELOC(val, 22);
*loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
break;
case R_PARISC_DIR64:
@@ -794,12 +849,8 @@ int module_finalize(const Elf_Ehdr *hdr,
addr = (u32 *)entry->addr;
printk("INSNS: %x %x %x %x\n",
addr[0], addr[1], addr[2], addr[3]);
- printk("stubs used %ld, stubs max %ld\n"
- "init_stubs used %ld, init stubs max %ld\n"
- "got entries used %ld, gots max %ld\n"
+ printk("got entries used %ld, gots max %ld\n"
"fdescs used %ld, fdescs max %ld\n",
- me->arch.stub_count, me->arch.stub_max,
- me->arch.init_stub_count, me->arch.init_stub_max,
me->arch.got_count, me->arch.got_max,
me->arch.fdesc_count, me->arch.fdesc_max);
#endif
@@ -829,7 +880,10 @@ int module_finalize(const Elf_Ehdr *hdr,
me->name, me->arch.got_count, MAX_GOTS);
return -EINVAL;
}
-
+
+ kfree(me->arch.section);
+ me->arch.section = NULL;
+
/* no symbol table */
if(symhdr == NULL)
return 0;
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index ccd61b9567a6..df47895db828 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -2,7 +2,7 @@
** PARISC 1.1 Dynamic DMA mapping support.
** This implementation is for PA-RISC platforms that do not support
** I/O TLBs (aka DMA address translation hardware).
-** See Documentation/DMA-mapping.txt for interface definitions.
+** See Documentation/PCI/PCI-DMA-mapping.txt for interface definitions.
**
** (c) Copyright 1999,2000 Hewlett-Packard Company
** (c) Copyright 2000 Grant Grundler
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index ccb68090781e..1ff366cb9685 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -52,7 +52,7 @@
#include <linux/tty.h>
#include <asm/pdc.h> /* for iodc_call() proto and friends */
-static spinlock_t pdc_console_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pdc_console_lock);
static void pdc_console_write(struct console *co, const char *s, unsigned count)
{
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index f696f57faa15..75099efb3bf3 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -541,9 +541,9 @@ static int __init perf_init(void)
spin_lock_init(&perf_lock);
/* TODO: this only lets us access the first cpu.. what to do for SMP? */
- cpu_device = cpu_data[0].dev;
+ cpu_device = per_cpu(cpu_data, 0).dev;
printk("Performance monitoring counters enabled for %s\n",
- cpu_data[0].dev->name);
+ per_cpu(cpu_data, 0).dev->name);
return 0;
}
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 370086fb8333..ecb609342feb 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -3,7 +3,7 @@
* Initial setup-routines for HP 9000 based hardware.
*
* Copyright (C) 1991, 1992, 1995 Linus Torvalds
- * Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
+ * Modifications for PA-RISC (C) 1999-2008 Helge Deller <deller@gmx.de>
* Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
* Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
* Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
@@ -46,7 +46,7 @@
struct system_cpuinfo_parisc boot_cpu_data __read_mostly;
EXPORT_SYMBOL(boot_cpu_data);
-struct cpuinfo_parisc cpu_data[NR_CPUS] __read_mostly;
+DEFINE_PER_CPU(struct cpuinfo_parisc, cpu_data);
extern int update_cr16_clocksource(void); /* from time.c */
@@ -69,6 +69,23 @@ extern int update_cr16_clocksource(void); /* from time.c */
*/
/**
+ * init_cpu_profiler - enable/setup per cpu profiling hooks.
+ * @cpunum: The processor instance.
+ *
+ * FIXME: doesn't do much yet...
+ */
+static void __cpuinit
+init_percpu_prof(unsigned long cpunum)
+{
+ struct cpuinfo_parisc *p;
+
+ p = &per_cpu(cpu_data, cpunum);
+ p->prof_counter = 1;
+ p->prof_multiplier = 1;
+}
+
+
+/**
* processor_probe - Determine if processor driver should claim this device.
* @dev: The device which has been found.
*
@@ -147,7 +164,7 @@ static int __cpuinit processor_probe(struct parisc_device *dev)
}
#endif
- p = &cpu_data[cpuid];
+ p = &per_cpu(cpu_data, cpuid);
boot_cpu_data.cpu_count++;
/* initialize counters - CPU 0 gets it_value set in time_init() */
@@ -162,12 +179,9 @@ static int __cpuinit processor_probe(struct parisc_device *dev)
#ifdef CONFIG_SMP
/*
** FIXME: review if any other initialization is clobbered
- ** for boot_cpu by the above memset().
+ ** for boot_cpu by the above memset().
*/
-
- /* stolen from init_percpu_prof() */
- cpu_data[cpuid].prof_counter = 1;
- cpu_data[cpuid].prof_multiplier = 1;
+ init_percpu_prof(cpuid);
#endif
/*
@@ -261,19 +275,6 @@ void __init collect_boot_cpu_data(void)
}
-/**
- * init_cpu_profiler - enable/setup per cpu profiling hooks.
- * @cpunum: The processor instance.
- *
- * FIXME: doesn't do much yet...
- */
-static inline void __init
-init_percpu_prof(int cpunum)
-{
- cpu_data[cpunum].prof_counter = 1;
- cpu_data[cpunum].prof_multiplier = 1;
-}
-
/**
* init_per_cpu - Handle individual processor initializations.
@@ -293,7 +294,7 @@ init_percpu_prof(int cpunum)
*
* o Enable CPU profiling hooks.
*/
-int __init init_per_cpu(int cpunum)
+int __cpuinit init_per_cpu(int cpunum)
{
int ret;
struct pdc_coproc_cfg coproc_cfg;
@@ -307,8 +308,8 @@ int __init init_per_cpu(int cpunum)
/* FWIW, FP rev/model is a more accurate way to determine
** CPU type. CPU rev/model has some ambiguous cases.
*/
- cpu_data[cpunum].fp_rev = coproc_cfg.revision;
- cpu_data[cpunum].fp_model = coproc_cfg.model;
+ per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
+ per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n",
cpunum, coproc_cfg.revision, coproc_cfg.model);
@@ -344,16 +345,17 @@ int __init init_per_cpu(int cpunum)
int
show_cpuinfo (struct seq_file *m, void *v)
{
- int n;
+ unsigned long cpu;
- for(n=0; n<boot_cpu_data.cpu_count; n++) {
+ for_each_online_cpu(cpu) {
+ const struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
#ifdef CONFIG_SMP
- if (0 == cpu_data[n].hpa)
+ if (0 == cpuinfo->hpa)
continue;
#endif
- seq_printf(m, "processor\t: %d\n"
+ seq_printf(m, "processor\t: %lu\n"
"cpu family\t: PA-RISC %s\n",
- n, boot_cpu_data.family_name);
+ cpu, boot_cpu_data.family_name);
seq_printf(m, "cpu\t\t: %s\n", boot_cpu_data.cpu_name );
@@ -365,8 +367,8 @@ show_cpuinfo (struct seq_file *m, void *v)
seq_printf(m, "model\t\t: %s\n"
"model name\t: %s\n",
boot_cpu_data.pdc.sys_model_name,
- cpu_data[n].dev ?
- cpu_data[n].dev->name : "Unknown" );
+ cpuinfo->dev ?
+ cpuinfo->dev->name : "Unknown");
seq_printf(m, "hversion\t: 0x%08x\n"
"sversion\t: 0x%08x\n",
@@ -377,8 +379,8 @@ show_cpuinfo (struct seq_file *m, void *v)
show_cache_info(m);
seq_printf(m, "bogomips\t: %lu.%02lu\n",
- cpu_data[n].loops_per_jiffy / (500000 / HZ),
- (cpu_data[n].loops_per_jiffy / (5000 / HZ)) % 100);
+ cpuinfo->loops_per_jiffy / (500000 / HZ),
+ (cpuinfo->loops_per_jiffy / (5000 / HZ)) % 100);
seq_printf(m, "software id\t: %ld\n\n",
boot_cpu_data.pdc.model.sw_id);
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 7d27853ff8c8..82131ca8e05c 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -58,11 +58,6 @@ int parisc_bus_is_phys __read_mostly = 1; /* Assume no IOMMU is present */
EXPORT_SYMBOL(parisc_bus_is_phys);
#endif
-/* This sets the vmerge boundary and size, it's here because it has to
- * be available on all platforms (zero means no-virtual merging) */
-unsigned long parisc_vmerge_boundary = 0;
-unsigned long parisc_vmerge_max_size = 0;
-
void __init setup_cmdline(char **cmdline_p)
{
extern unsigned int boot_args[];
@@ -321,7 +316,7 @@ static int __init parisc_init(void)
processor_init();
printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
- boot_cpu_data.cpu_count,
+ num_present_cpus(),
boot_cpu_data.cpu_name,
boot_cpu_data.cpu_hz / 1000000,
boot_cpu_data.cpu_hz % 1000000 );
@@ -387,8 +382,8 @@ void start_parisc(void)
if (ret >= 0 && coproc_cfg.ccr_functional) {
mtctl(coproc_cfg.ccr_functional, 10);
- cpu_data[cpunum].fp_rev = coproc_cfg.revision;
- cpu_data[cpunum].fp_model = coproc_cfg.model;
+ per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
+ per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
asm volatile ("fstd %fr0,8(%sp)");
} else {
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index d47f3975c9c6..9995d7ed5819 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -56,31 +56,17 @@ static int smp_debug_lvl = 0;
if (lvl >= smp_debug_lvl) \
printk(printargs);
#else
-#define smp_debug(lvl, ...)
+#define smp_debug(lvl, ...) do { } while(0)
#endif /* DEBUG_SMP */
DEFINE_SPINLOCK(smp_lock);
volatile struct task_struct *smp_init_current_idle_task;
-static volatile int cpu_now_booting __read_mostly = 0; /* track which CPU is booting */
+/* track which CPU is booting */
+static volatile int cpu_now_booting __cpuinitdata;
-static int parisc_max_cpus __read_mostly = 1;
-
-/* online cpus are ones that we've managed to bring up completely
- * possible cpus are all valid cpu
- * present cpus are all detected cpu
- *
- * On startup we bring up the "possible" cpus. Since we discover
- * CPUs later, we add them as hotplug, so the possible cpu mask is
- * empty in the beginning.
- */
-
-cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE; /* Bitmap of online CPUs */
-cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL; /* Bitmap of Present CPUs */
-
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_possible_map);
+static int parisc_max_cpus __cpuinitdata = 1;
DEFINE_PER_CPU(spinlock_t, ipi_lock) = SPIN_LOCK_UNLOCKED;
@@ -138,7 +124,7 @@ irqreturn_t
ipi_interrupt(int irq, void *dev_id)
{
int this_cpu = smp_processor_id();
- struct cpuinfo_parisc *p = &cpu_data[this_cpu];
+ struct cpuinfo_parisc *p = &per_cpu(cpu_data, this_cpu);
unsigned long ops;
unsigned long flags;
@@ -217,13 +203,13 @@ ipi_interrupt(int irq, void *dev_id)
static inline void
ipi_send(int cpu, enum ipi_message_type op)
{
- struct cpuinfo_parisc *p = &cpu_data[cpu];
+ struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpu);
spinlock_t *lock = &per_cpu(ipi_lock, cpu);
unsigned long flags;
spin_lock_irqsave(lock, flags);
p->pending_ipi |= 1 << op;
- gsc_writel(IPI_IRQ - CPU_IRQ_BASE, cpu_data[cpu].hpa);
+ gsc_writel(IPI_IRQ - CPU_IRQ_BASE, p->hpa);
spin_unlock_irqrestore(lock, flags);
}
@@ -239,10 +225,7 @@ send_IPI_mask(cpumask_t mask, enum ipi_message_type op)
static inline void
send_IPI_single(int dest_cpu, enum ipi_message_type op)
{
- if (dest_cpu == NO_PROC_ID) {
- BUG();
- return;
- }
+ BUG_ON(dest_cpu == NO_PROC_ID);
ipi_send(dest_cpu, op);
}
@@ -324,8 +307,7 @@ smp_cpu_init(int cpunum)
/* Initialise the idle task for this CPU */
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- if(current->mm)
- BUG();
+ BUG_ON(current->mm);
enter_lazy_tlb(&init_mm, current);
init_IRQ(); /* make sure no IRQs are enabled or pending */
@@ -360,6 +342,7 @@ void __init smp_callin(void)
*/
int __cpuinit smp_boot_one_cpu(int cpuid)
{
+ const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid);
struct task_struct *idle;
long timeout;
@@ -391,7 +374,7 @@ int __cpuinit smp_boot_one_cpu(int cpuid)
smp_init_current_idle_task = idle ;
mb();
- printk("Releasing cpu %d now, hpa=%lx\n", cpuid, cpu_data[cpuid].hpa);
+ printk(KERN_INFO "Releasing cpu %d now, hpa=%lx\n", cpuid, p->hpa);
/*
** This gets PDC to release the CPU from a very tight loop.
@@ -402,7 +385,7 @@ int __cpuinit smp_boot_one_cpu(int cpuid)
** EIR{0}). MEM_RENDEZ is valid only when it is nonzero and the
** contents of memory are valid."
*/
- gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, cpu_data[cpuid].hpa);
+ gsc_writel(TIMER_IRQ - CPU_IRQ_BASE, p->hpa);
mb();
/*
@@ -434,12 +417,12 @@ alive:
return 0;
}
-void __devinit smp_prepare_boot_cpu(void)
+void __init smp_prepare_boot_cpu(void)
{
- int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */
+ int bootstrap_processor = per_cpu(cpu_data, 0).cpuid;
/* Setup BSP mappings */
- printk("SMP: bootstrap CPU ID is %d\n",bootstrap_processor);
+ printk(KERN_INFO "SMP: bootstrap CPU ID is %d\n", bootstrap_processor);
cpu_set(bootstrap_processor, cpu_online_map);
cpu_set(bootstrap_processor, cpu_present_map);
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 4d09203bc693..9d46c43a4152 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -60,7 +60,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
unsigned long cycles_elapsed, ticks_elapsed;
unsigned long cycles_remainder;
unsigned int cpu = smp_processor_id();
- struct cpuinfo_parisc *cpuinfo = &cpu_data[cpu];
+ struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
/* gcc can optimize for "read-only" case with a local clocktick */
unsigned long cpt = clocktick;
@@ -213,7 +213,7 @@ void __init start_cpu_itimer(void)
mtctl(next_tick, 16); /* kick off Interval Timer (CR16) */
- cpu_data[cpu].it_value = next_tick;
+ per_cpu(cpu_data, cpu).it_value = next_tick;
}
struct platform_device rtc_parisc_dev = {
diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c
index d71cb018a21e..f5159381fdd6 100644
--- a/arch/parisc/kernel/topology.c
+++ b/arch/parisc/kernel/topology.c
@@ -22,14 +22,14 @@
#include <linux/cpu.h>
#include <linux/cache.h>
-static struct cpu cpu_devices[NR_CPUS] __read_mostly;
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
static int __init topology_init(void)
{
int num;
for_each_present_cpu(num) {
- register_cpu(&cpu_devices[num], num);
+ register_cpu(&per_cpu(cpu_devices, num), num);
}
return 0;
}
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 4c771cd580ec..ba658d2086f7 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -745,6 +745,10 @@ void handle_interruption(int code, struct pt_regs *regs)
/* Fall Through */
case 27:
/* Data memory protection ID trap */
+ if (code == 27 && !user_mode(regs) &&
+ fixup_exception(regs))
+ return;
+
die_if_kernel("Protection id trap", regs, code);
si.si_code = SEGV_MAPERR;
si.si_signo = SIGSEGV;
@@ -821,8 +825,8 @@ void handle_interruption(int code, struct pt_regs *regs)
int __init check_ivt(void *iva)
{
+ extern u32 os_hpmc_size;
extern const u32 os_hpmc[];
- extern const u32 os_hpmc_end[];
int i;
u32 check = 0;
@@ -839,8 +843,7 @@ int __init check_ivt(void *iva)
*ivap++ = 0;
/* Compute Checksum for HPMC handler */
-
- length = os_hpmc_end - os_hpmc;
+ length = os_hpmc_size;
ivap[7] = length;
hpmcp = (u32 *)os_hpmc;
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 6773c582e457..69dad5a850a8 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -372,7 +372,7 @@ void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct
struct pt_regs *r = &t->thread.regs;
struct pt_regs *r2;
- r2 = kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+ r2 = kmalloc(sizeof(struct pt_regs), GFP_ATOMIC);
if (!r2)
return;
*r2 = *r;
diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c
index 9abed07db7fc..5069e8b2ca71 100644
--- a/arch/parisc/lib/iomap.c
+++ b/arch/parisc/lib/iomap.c
@@ -261,7 +261,7 @@ static const struct iomap_ops iomem_ops = {
iomem_write32r,
};
-const struct iomap_ops *iomap_ops[8] = {
+static const struct iomap_ops *iomap_ops[8] = {
[0] = &ioport_ops,
[7] = &iomem_ops
};
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index 2d68431fc22e..bbda909c866e 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -275,7 +275,7 @@ handle_store_error:
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
-unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
+static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
{
register unsigned long src, dst, t1, t2, t3;
register unsigned char *pcs, *pcd;
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index b2e3e9a8cece..92c7fa4ecc3f 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -139,13 +139,41 @@ parisc_acctyp(unsigned long code, unsigned int inst)
}
#endif
+int fixup_exception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fix;
+
+ fix = search_exception_tables(regs->iaoq[0]);
+ if (fix) {
+ struct exception_data *d;
+ d = &__get_cpu_var(exception_data);
+ d->fault_ip = regs->iaoq[0];
+ d->fault_space = regs->isr;
+ d->fault_addr = regs->ior;
+
+ regs->iaoq[0] = ((fix->fixup) & ~3);
+ /*
+ * NOTE: In some cases the faulting instruction
+ * may be in the delay slot of a branch. We
+ * don't want to take the branch, so we don't
+ * increment iaoq[1], instead we set it to be
+ * iaoq[0]+4, and clear the B bit in the PSW
+ */
+ regs->iaoq[1] = regs->iaoq[0] + 4;
+ regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
+
+ return 1;
+ }
+
+ return 0;
+}
+
void do_page_fault(struct pt_regs *regs, unsigned long code,
unsigned long address)
{
struct vm_area_struct *vma, *prev_vma;
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
- const struct exception_table_entry *fix;
unsigned long acc_type;
int fault;
@@ -229,32 +257,8 @@ bad_area:
no_context:
- if (!user_mode(regs)) {
- fix = search_exception_tables(regs->iaoq[0]);
-
- if (fix) {
- struct exception_data *d;
-
- d = &__get_cpu_var(exception_data);
- d->fault_ip = regs->iaoq[0];
- d->fault_space = regs->isr;
- d->fault_addr = regs->ior;
-
- regs->iaoq[0] = ((fix->fixup) & ~3);
-
- /*
- * NOTE: In some cases the faulting instruction
- * may be in the delay slot of a branch. We
- * don't want to take the branch, so we don't
- * increment iaoq[1], instead we set it to be
- * iaoq[0]+4, and clear the B bit in the PSW
- */
-
- regs->iaoq[1] = regs->iaoq[0] + 4;
- regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
-
- return;
- }
+ if (!user_mode(regs) && fixup_exception(regs)) {
+ return;
}
parisc_terminate("Bad Address (null pointer deref?)", regs, code, address);
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 79f25cef32df..74cc312c347c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -108,6 +108,8 @@ config ARCH_NO_VIRT_TO_BUS
config PPC
bool
default y
+ select HAVE_FTRACE_MCOUNT_RECORD
+ select HAVE_DYNAMIC_FTRACE
select HAVE_FUNCTION_TRACER
select ARCH_WANT_OPTIONAL_GPIOLIB
select HAVE_IDE
@@ -121,6 +123,7 @@ config PPC
select HAVE_DMA_ATTRS if PPC64
select USE_GENERIC_SMP_HELPERS if SMP
select HAVE_OPROFILE
+ select HAVE_SYSCALL_WRAPPERS if PPC64
config EARLY_PRINTK
bool
@@ -326,7 +329,8 @@ config KEXEC
config CRASH_DUMP
bool "Build a kdump crash kernel"
- depends on (PPC64 && RELOCATABLE) || 6xx
+ depends on PPC64 || 6xx
+ select RELOCATABLE if PPC64
help
Build a kernel suitable for use as a kdump capture kernel.
The same kernel binary can be used as production kernel and dump
@@ -872,10 +876,6 @@ source "drivers/Kconfig"
source "fs/Kconfig"
-# XXX source "arch/ppc/8xx_io/Kconfig"
-
-# XXX source "arch/ppc/8260_io/Kconfig"
-
source "arch/powerpc/sysdev/qe_lib/Kconfig"
source "lib/Kconfig"
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index f32829937aad..e84df338ea29 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -208,7 +208,7 @@ image-$(CONFIG_DEFAULT_UIMAGE) += uImage
#
# Theses are default targets to build images which embed device tree blobs.
# They are only required on boards which do not have FDT support in firmware.
-# Boards with newish u-boot firmare can use the uImage target above
+# Boards with newish u-boot firmware can use the uImage target above
#
# Board ports in arch/powerpc/platform/40x/Kconfig
@@ -356,7 +356,7 @@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y))
@rm -f $@; ln $< $@
install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y))
- sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $<
+ sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $^
# anything not in $(targets)
clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index 21780210057d..806df693fea6 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -18,57 +18,14 @@
static bd_t bd;
-static void warp_fixup_one_nor(u32 from, u32 to)
-{
- void *devp;
- char name[50];
- u32 v[2];
-
- sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
-
- devp = finddevice(name);
- if (!devp)
- return;
-
- if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
- v[0] = to;
- setprop(devp, "reg", v, sizeof(v));
-
- printf("NOR 64M fixup %x -> %x\r\n", from, to);
- }
-}
-
-
static void warp_fixups(void)
{
ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
ibm4xx_sdram_fixup_memsize();
ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
-
- /* Fixup for 64M flash on Rev A boards. */
- if (bd.bi_flashsize == 0x4000000) {
- void *devp;
- u32 v[3];
-
- devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
- if (!devp)
- return;
-
- /* Fixup the size */
- if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
- v[2] = bd.bi_flashsize;
- setprop(devp, "reg", v, sizeof(v));
- }
-
- /* Fixup parition offsets */
- warp_fixup_one_nor(0x300000, 0x3f00000);
- warp_fixup_one_nor(0x340000, 0x3f40000);
- warp_fixup_one_nor(0x380000, 0x3f80000);
- }
}
-
void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
diff --git a/arch/powerpc/boot/dts/gef_sbc610.dts b/arch/powerpc/boot/dts/gef_sbc610.dts
index 9708b3423bbd..e78c355c7bac 100644
--- a/arch/powerpc/boot/dts/gef_sbc610.dts
+++ b/arch/powerpc/boot/dts/gef_sbc610.dts
@@ -88,6 +88,21 @@
compatible = "gef,fpga-regs";
reg = <0x4 0x0 0x40>;
};
+
+ wdt@4,2000 {
+ compatible = "gef,fpga-wdt";
+ reg = <0x4 0x2000 0x8>;
+ interrupts = <0x1a 0x4>;
+ interrupt-parent = <&gef_pic>;
+ };
+ /* Second watchdog available, driver currently supports one.
+ wdt@4,2010 {
+ compatible = "gef,fpga-wdt";
+ reg = <0x4 0x2010 0x8>;
+ interrupts = <0x1b 0x4>;
+ interrupt-parent = <&gef_pic>;
+ };
+ */
gef_pic: pic@4,4000 {
#interrupt-cells = <1>;
interrupt-controller;
diff --git a/arch/powerpc/boot/dts/haleakala.dts b/arch/powerpc/boot/dts/haleakala.dts
index 513bc43a71af..5b2a4947bf82 100644
--- a/arch/powerpc/boot/dts/haleakala.dts
+++ b/arch/powerpc/boot/dts/haleakala.dts
@@ -89,8 +89,11 @@
clock-frequency = <0>; /* Filled in by U-Boot */
SDRAM0: memory-controller {
- compatible = "ibm,sdram-405exr";
+ compatible = "ibm,sdram-405exr", "ibm,sdram-4xx-ddr2";
dcr-reg = <0x010 0x002>;
+ interrupt-parent = <&UIC2>;
+ interrupts = <0x5 0x4 /* ECC DED Error */
+ 0x6 0x4>; /* ECC SEC Error */
};
MAL0: mcmal {
diff --git a/arch/powerpc/boot/dts/kilauea.dts b/arch/powerpc/boot/dts/kilauea.dts
index dececc4b5ff2..2804444812e5 100644
--- a/arch/powerpc/boot/dts/kilauea.dts
+++ b/arch/powerpc/boot/dts/kilauea.dts
@@ -90,8 +90,11 @@
clock-frequency = <0>; /* Filled in by U-Boot */
SDRAM0: memory-controller {
- compatible = "ibm,sdram-405ex";
+ compatible = "ibm,sdram-405ex", "ibm,sdram-4xx-ddr2";
dcr-reg = <0x010 0x002>;
+ interrupt-parent = <&UIC2>;
+ interrupts = <0x5 0x4 /* ECC DED Error */
+ 0x6 0x4>; /* ECC SEC Error */
};
MAL0: mcmal {
diff --git a/arch/powerpc/boot/dts/makalu.dts b/arch/powerpc/boot/dts/makalu.dts
index 945508c7e7d8..ffc246e72670 100644
--- a/arch/powerpc/boot/dts/makalu.dts
+++ b/arch/powerpc/boot/dts/makalu.dts
@@ -90,8 +90,11 @@
clock-frequency = <0>; /* Filled in by U-Boot */
SDRAM0: memory-controller {
- compatible = "ibm,sdram-405ex";
+ compatible = "ibm,sdram-405ex", "ibm,sdram-4xx-ddr2";
dcr-reg = <0x010 0x002>;
+ interrupt-parent = <&UIC2>;
+ interrupts = <0x5 0x4 /* ECC DED Error */
+ 0x6 0x4 /* ECC SEC Error */ >;
};
MAL0: mcmal {
diff --git a/arch/powerpc/boot/dts/mpc8313erdb.dts b/arch/powerpc/boot/dts/mpc8313erdb.dts
index d4df8b6857a4..909a89cab9ac 100644
--- a/arch/powerpc/boot/dts/mpc8313erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8313erdb.dts
@@ -185,7 +185,7 @@
cell-index = <0>;
device_type = "network";
model = "eTSEC";
- compatible = "gianfar", "simple-bus";
+ compatible = "gianfar";
reg = <0x24000 0x1000>;
local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <37 0x8 36 0x8 35 0x8>;
diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts
index 072c9b0f8c8e..71784165b77e 100644
--- a/arch/powerpc/boot/dts/mpc8315erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8315erdb.dts
@@ -255,7 +255,7 @@
device_type = "serial";
compatible = "ns16550";
reg = <0x4500 0x100>;
- clock-frequency = <0>;
+ clock-frequency = <133333333>;
interrupts = <9 0x8>;
interrupt-parent = <&ipic>;
};
@@ -265,7 +265,7 @@
device_type = "serial";
compatible = "ns16550";
reg = <0x4600 0x100>;
- clock-frequency = <0>;
+ clock-frequency = <133333333>;
interrupts = <10 0x8>;
interrupt-parent = <&ipic>;
};
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts
index 14534d04e4db..6e34f170fa62 100644
--- a/arch/powerpc/boot/dts/mpc836x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc836x_mds.dts
@@ -69,8 +69,18 @@
};
bcsr@1,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
compatible = "fsl,mpc8360mds-bcsr";
reg = <1 0 0x8000>;
+ ranges = <0 1 0 0x8000>;
+
+ bcsr13: gpio-controller@d {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8360mds-bcsr-gpio";
+ reg = <0xd 1>;
+ gpio-controller;
+ };
};
};
@@ -195,10 +205,21 @@
};
par_io@1400 {
+ #address-cells = <1>;
+ #size-cells = <1>;
reg = <0x1400 0x100>;
+ ranges = <0 0x1400 0x100>;
device_type = "par_io";
num-ports = <7>;
+ qe_pio_b: gpio-controller@18 {
+ #gpio-cells = <2>;
+ compatible = "fsl,mpc8360-qe-pario-bank",
+ "fsl,mpc8323-qe-pario-bank";
+ reg = <0x18 0x18>;
+ gpio-controller;
+ };
+
pio1: ucc_pin@01 {
pio-map = <
/* port pin dir open_drain assignment has_irq */
@@ -282,6 +303,15 @@
};
};
+ timer@440 {
+ compatible = "fsl,mpc8360-qe-gtm",
+ "fsl,qe-gtm", "fsl,gtm";
+ reg = <0x440 0x40>;
+ clock-frequency = <132000000>;
+ interrupts = <12 13 14 15>;
+ interrupt-parent = <&qeic>;
+ };
+
spi@4c0 {
cell-index = <0>;
compatible = "fsl,spi";
@@ -301,11 +331,20 @@
};
usb@6c0 {
- compatible = "qe_udc";
+ compatible = "fsl,mpc8360-qe-usb",
+ "fsl,mpc8323-qe-usb";
reg = <0x6c0 0x40 0x8b00 0x100>;
interrupts = <11>;
interrupt-parent = <&qeic>;
- mode = "slave";
+ fsl,fullspeed-clock = "clk21";
+ fsl,lowspeed-clock = "brg9";
+ gpios = <&qe_pio_b 2 0 /* USBOE */
+ &qe_pio_b 3 0 /* USBTP */
+ &qe_pio_b 8 0 /* USBTN */
+ &qe_pio_b 9 0 /* USBRP */
+ &qe_pio_b 11 0 /* USBRN */
+ &bcsr13 5 0 /* SPEED */
+ &bcsr13 4 1>; /* POWER */
};
enet0: ucc@2000 {
diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts
index decadf3d9e98..37b789510d68 100644
--- a/arch/powerpc/boot/dts/mpc836x_rdk.dts
+++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts
@@ -218,8 +218,23 @@
reg = <0x440 0x40>;
interrupts = <12 13 14 15>;
interrupt-parent = <&qeic>;
- /* filled by u-boot */
- clock-frequency = <0>;
+ clock-frequency = <166666666>;
+ };
+
+ usb@6c0 {
+ compatible = "fsl,mpc8360-qe-usb",
+ "fsl,mpc8323-qe-usb";
+ reg = <0x6c0 0x40 0x8b00 0x100>;
+ interrupts = <11>;
+ interrupt-parent = <&qeic>;
+ fsl,fullspeed-clock = "clk21";
+ gpios = <&qe_pio_b 2 0 /* USBOE */
+ &qe_pio_b 3 0 /* USBTP */
+ &qe_pio_b 8 0 /* USBTN */
+ &qe_pio_b 9 0 /* USBRP */
+ &qe_pio_b 11 0 /* USBRN */
+ &qe_pio_e 20 0 /* SPEED */
+ &qe_pio_e 21 1 /* POWER */>;
};
spi@4c0 {
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index b9da42105066..0668d1048779 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -313,7 +313,7 @@
0x1000000 0x0 0x0 0xe1010000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
- interrupts = <26 2>;
+ interrupts = <25 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
@@ -350,7 +350,7 @@
0x1000000 0x0 0x0 0xe1020000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
- interrupts = <25 2>;
+ interrupts = <26 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts
index 21459e161d02..359c3b727420 100644
--- a/arch/powerpc/boot/dts/mpc8572ds.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds.dts
@@ -89,7 +89,7 @@
ramdisk@0 {
reg = <0x0 0x03000000>;
- readl-only;
+ read-only;
};
diagnostic@3000000 {
@@ -724,7 +724,7 @@
0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x00010000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
- interrupts = <26 2>;
+ interrupts = <25 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
@@ -761,7 +761,7 @@
0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x00010000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
- interrupts = <27 2>;
+ interrupts = <26 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
index c114c4ee9931..fd462efa9e61 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
@@ -457,7 +457,7 @@
0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
- interrupts = <26 2>;
+ interrupts = <25 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
index 04ecda18d206..e35230f2ac93 100644
--- a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
+++ b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
@@ -208,7 +208,7 @@
0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
- interrupts = <27 2>;
+ interrupts = <26 2>;
interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
interrupt-map = <
/* IDSEL 0x0 */
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
index 35d5e248ccd7..4481532cbe77 100644
--- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -26,7 +26,13 @@
serial1 = &serial1;
pci0 = &pci0;
pci1 = &pci1;
- rapidio0 = &rapidio0;
+/*
+ * Only one of Rapid IO or PCI can be present due to HW limitations and
+ * due to the fact that the 2 now share address space in the new memory
+ * map. The most likely case is that we have PCI, so comment out the
+ * rapidio node. Leave it here for reference.
+ */
+ /* rapidio0 = &rapidio0; */
};
cpus {
@@ -62,18 +68,17 @@
reg = <0x00000000 0x40000000>; // 1G at 0x0
};
- localbus@f8005000 {
+ localbus@ffe05000 {
#address-cells = <2>;
#size-cells = <1>;
compatible = "fsl,mpc8641-localbus", "simple-bus";
- reg = <0xf8005000 0x1000>;
+ reg = <0xffe05000 0x1000>;
interrupts = <19 2>;
interrupt-parent = <&mpic>;
- ranges = <0 0 0xff800000 0x00800000
- 1 0 0xfe000000 0x01000000
- 2 0 0xf8200000 0x00100000
- 3 0 0xf8100000 0x00100000>;
+ ranges = <0 0 0xef800000 0x00800000
+ 2 0 0xffdf8000 0x00008000
+ 3 0 0xffdf0000 0x00008000>;
flash@0,0 {
compatible = "cfi-flash";
@@ -103,13 +108,13 @@
};
};
- soc8641@f8000000 {
+ soc8641@ffe00000 {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
compatible = "simple-bus";
- ranges = <0x00000000 0xf8000000 0x00100000>;
- reg = <0xf8000000 0x00001000>; // CCSRBAR
+ ranges = <0x00000000 0xffe00000 0x00100000>;
+ reg = <0xffe00000 0x00001000>; // CCSRBAR
bus-frequency = <0>;
i2c@3000 {
@@ -340,17 +345,17 @@
};
};
- pci0: pcie@f8008000 {
+ pci0: pcie@ffe08000 {
cell-index = <0>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
- reg = <0xf8008000 0x1000>;
+ reg = <0xffe08000 0x1000>;
bus-range = <0x0 0xff>;
ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
- 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+ 0x01000000 0x0 0x00000000 0xffc00000 0x0 0x00010000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <24 2>;
@@ -481,7 +486,7 @@
0x01000000 0x0 0x00000000
0x01000000 0x0 0x00000000
- 0x0 0x00100000>;
+ 0x0 0x00010000>;
uli1575@0 {
reg = <0 0 0 0 0>;
#size-cells = <2>;
@@ -491,7 +496,7 @@
0x0 0x20000000
0x01000000 0x0 0x00000000
0x01000000 0x0 0x00000000
- 0x0 0x00100000>;
+ 0x0 0x00010000>;
isa@1e {
device_type = "isa";
#interrupt-cells = <2>;
@@ -549,17 +554,17 @@
};
- pci1: pcie@f8009000 {
+ pci1: pcie@ffe09000 {
cell-index = <1>;
compatible = "fsl,mpc8641-pcie";
device_type = "pci";
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
- reg = <0xf8009000 0x1000>;
+ reg = <0xffe09000 0x1000>;
bus-range = <0 0xff>;
ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
- 0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
+ 0x01000000 0x0 0x00000000 0xffc10000 0x0 0x00010000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <25 2>;
@@ -582,18 +587,21 @@
0x01000000 0x0 0x00000000
0x01000000 0x0 0x00000000
- 0x0 0x00100000>;
+ 0x0 0x00010000>;
};
};
- rapidio0: rapidio@f80c0000 {
+/*
+ rapidio0: rapidio@ffec0000 {
#address-cells = <2>;
#size-cells = <2>;
compatible = "fsl,rapidio-delta";
- reg = <0xf80c0000 0x20000>;
- ranges = <0 0 0xc0000000 0 0x20000000>;
+ reg = <0xffec0000 0x20000>;
+ ranges = <0 0 0x80000000 0 0x20000000>;
interrupt-parent = <&mpic>;
- /* err_irq bell_outb_irq bell_inb_irq
- msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */
+ // err_irq bell_outb_irq bell_inb_irq
+ // msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq
interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>;
};
+*/
+
};
diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts
index 3b295e8df53f..43cc68bd3192 100644
--- a/arch/powerpc/boot/dts/sequoia.dts
+++ b/arch/powerpc/boot/dts/sequoia.dts
@@ -134,7 +134,7 @@
};
USB1: usb@e0000400 {
- compatible = "ohci-be";
+ compatible = "ibm,usb-ohci-440epx", "ohci-be";
reg = <0x00000000 0xe0000400 0x00000060>;
interrupt-parent = <&UIC0>;
interrupts = <0x15 0x8>;
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index f4e4ba69eef7..7e183ff9a317 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -149,12 +149,17 @@
reg = <0x00000002 0x00004000 0x00000A00>;
};
- nor_flash@0,0 {
+ nor@0,0 {
compatible = "amd,s29gl032a", "cfi-flash";
bank-width = <2>;
reg = <0x00000000 0x00000000 0x00400000>;
#address-cells = <1>;
#size-cells = <1>;
+
+ partition@0 {
+ label = "splash";
+ reg = <0x00000000 0x00020000>;
+ };
partition@300000 {
label = "fpga";
reg = <0x0300000 0x00040000>;
@@ -168,6 +173,41 @@
reg = <0x0380000 0x00080000>;
};
};
+
+ ndfc@1,0 {
+ compatible = "ibm,ndfc";
+ reg = <0x00000001 0x00000000 0x00002000>;
+ ccr = <0x00001000>;
+ bank-settings = <0x80002222>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ nand {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "kernel";
+ reg = <0x00000000 0x00200000>;
+ };
+ partition@200000 {
+ label = "root";
+ reg = <0x00200000 0x03E00000>;
+ };
+ partition@40000000 {
+ label = "persistent";
+ reg = <0x04000000 0x04000000>;
+ };
+ partition@80000000 {
+ label = "persistent1";
+ reg = <0x08000000 0x04000000>;
+ };
+ partition@C0000000 {
+ label = "persistent2";
+ reg = <0x0C000000 0x04000000>;
+ };
+ };
+ };
};
UART0: serial@ef600300 {
diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh
index b002bfd56786..51b2387bdba0 100644
--- a/arch/powerpc/boot/install.sh
+++ b/arch/powerpc/boot/install.sh
@@ -15,7 +15,7 @@
# $2 - kernel image file
# $3 - kernel map file
# $4 - default install path (blank if root directory)
-# $5 - kernel boot file, the zImage
+# $5 and more - kernel boot files; zImage*, uImage, cuImage.*, etc.
#
# User may have a custom install script
@@ -38,3 +38,15 @@ fi
cat $2 > $4/$image_name
cp $3 $4/System.map
+
+# Copy all the bootable image files
+path=$4
+shift 4
+while [ $# -ne 0 ]; do
+ image_name=`basename $1`
+ if [ -f $path/$image_name ]; then
+ mv $path/$image_name $path/$image_name.old
+ fi
+ cat $1 > $path/$image_name
+ shift
+done;
diff --git a/arch/powerpc/configs/40x/acadia_defconfig b/arch/powerpc/configs/40x/acadia_defconfig
index 25572cc837ca..a32ec8d323a0 100644
--- a/arch/powerpc/configs/40x/acadia_defconfig
+++ b/arch/powerpc/configs/40x/acadia_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:49:18 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:17:46 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,12 +72,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -89,6 +90,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -111,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -182,6 +184,7 @@ CONFIG_405EZ=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -205,6 +208,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -219,12 +223,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -248,6 +254,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -272,6 +279,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -322,6 +330,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -334,6 +343,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -359,6 +369,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -431,6 +442,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -524,6 +541,10 @@ CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -576,9 +597,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -597,11 +621,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -611,7 +635,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -670,7 +694,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -704,10 +730,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -717,6 +740,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -757,6 +781,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -807,6 +832,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -815,18 +841,24 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -853,11 +885,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig
index b80ba7aa3129..4e9d85f39da0 100644
--- a/arch/powerpc/configs/40x/ep405_defconfig
+++ b/arch/powerpc/configs/40x/ep405_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:49:20 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:17:48 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,12 +72,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -89,6 +90,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -111,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -184,6 +186,7 @@ CONFIG_IBM405_ERR51=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -207,6 +210,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -221,12 +225,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -250,6 +256,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -274,6 +281,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -324,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -336,6 +345,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -361,6 +371,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -433,6 +444,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -464,6 +481,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -546,6 +564,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -570,6 +589,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -629,9 +652,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -650,11 +676,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -664,7 +690,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -723,6 +749,7 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -748,11 +775,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
# CONFIG_USB_LIBUSUAL is not set
@@ -791,6 +818,10 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -816,7 +847,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -850,10 +883,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -863,6 +893,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -903,6 +934,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -953,6 +985,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -961,18 +994,24 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -999,11 +1038,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/40x/hcu4_defconfig b/arch/powerpc/configs/40x/hcu4_defconfig
index 45dcb824503f..8c019d79bf2a 100644
--- a/arch/powerpc/configs/40x/hcu4_defconfig
+++ b/arch/powerpc/configs/40x/hcu4_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:49:22 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:17:50 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,12 +72,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -89,6 +90,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -111,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -182,6 +184,7 @@ CONFIG_405GPR=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -205,6 +208,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -219,12 +223,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -248,6 +254,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -272,6 +279,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -322,6 +330,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -334,6 +343,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -359,6 +369,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -431,6 +442,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -461,6 +478,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -543,6 +561,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -565,6 +584,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -617,9 +640,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -639,11 +665,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -653,7 +679,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -712,7 +738,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -746,10 +774,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -759,6 +784,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -799,6 +825,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -849,6 +876,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -857,18 +885,24 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -895,11 +929,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/40x/kilauea_defconfig b/arch/powerpc/configs/40x/kilauea_defconfig
index e2f3695d9d0b..9917a09bad3a 100644
--- a/arch/powerpc/configs/40x/kilauea_defconfig
+++ b/arch/powerpc/configs/40x/kilauea_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:49:23 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:17:52 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,12 +72,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -89,6 +90,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -111,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
CONFIG_PPC4xx_PCI_EXPRESS=y
@@ -182,6 +184,7 @@ CONFIG_405EX=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -205,6 +208,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -219,12 +223,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -248,6 +254,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -272,6 +279,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -322,6 +330,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -334,6 +343,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -359,6 +369,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -431,6 +442,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -524,6 +541,10 @@ CONFIG_IBM_NEW_EMAC_EMAC4=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -576,9 +597,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -597,11 +621,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -611,7 +635,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -670,7 +694,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -704,10 +730,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -717,6 +740,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -757,6 +781,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -807,6 +832,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -815,18 +841,24 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -853,11 +885,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/40x/makalu_defconfig b/arch/powerpc/configs/40x/makalu_defconfig
index 413c778ecd7c..58bf2ac2e0dd 100644
--- a/arch/powerpc/configs/40x/makalu_defconfig
+++ b/arch/powerpc/configs/40x/makalu_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:49:25 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:17:53 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,12 +72,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -89,6 +90,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -111,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
CONFIG_PPC4xx_PCI_EXPRESS=y
@@ -182,6 +184,7 @@ CONFIG_405EX=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -205,6 +208,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -219,12 +223,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -248,6 +254,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -272,6 +279,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -322,6 +330,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -334,6 +343,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -359,6 +369,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -431,6 +442,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -524,6 +541,10 @@ CONFIG_IBM_NEW_EMAC_EMAC4=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -576,9 +597,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -597,11 +621,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -611,7 +635,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -670,7 +694,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -704,10 +730,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -717,6 +740,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -757,6 +781,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -807,6 +832,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -815,18 +841,24 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -853,11 +885,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/40x/virtex_defconfig b/arch/powerpc/configs/40x/virtex_defconfig
index 9a9350ded292..b6888384dd74 100644
--- a/arch/powerpc/configs/40x/virtex_defconfig
+++ b/arch/powerpc/configs/40x/virtex_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Fri Nov 14 10:49:16 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:17:55 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -41,7 +42,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -74,8 +75,8 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +114,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -124,7 +124,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -132,11 +131,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +150,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -188,6 +189,7 @@ CONFIG_IBM405_ERR51=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -205,13 +207,13 @@ CONFIG_HZ=250
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -226,12 +228,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -256,6 +260,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -280,6 +285,8 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -423,6 +430,7 @@ CONFIG_IP_NF_MANGLE=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -438,8 +446,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -574,6 +583,10 @@ CONFIG_NETDEV_1000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -674,9 +687,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
# CONFIG_NVRAM is not set
@@ -854,7 +870,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -870,6 +885,7 @@ CONFIG_EXT2_FS=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -906,10 +922,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -918,6 +931,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -997,6 +1011,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1046,6 +1061,7 @@ CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1055,6 +1071,8 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1064,11 +1082,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1094,6 +1114,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/40x/walnut_defconfig b/arch/powerpc/configs/40x/walnut_defconfig
index 5820e0a4fc55..5ab29dddd21c 100644
--- a/arch/powerpc/configs/40x/walnut_defconfig
+++ b/arch/powerpc/configs/40x/walnut_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 08:49:27 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:17:57 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,12 +72,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -89,6 +90,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -111,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -185,6 +187,7 @@ CONFIG_IBM405_ERR51=y
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_OF_RTC=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -208,6 +211,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -222,12 +226,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -251,6 +257,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -275,6 +282,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -325,6 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -337,6 +346,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -362,6 +372,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -434,6 +445,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -464,6 +481,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -546,6 +564,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -568,6 +587,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -620,9 +643,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -641,11 +667,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -655,7 +681,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -701,9 +727,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -729,7 +759,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -763,10 +795,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -776,6 +805,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -816,6 +846,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -866,6 +897,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -874,18 +906,24 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -912,11 +950,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/arches_defconfig b/arch/powerpc/configs/44x/arches_defconfig
index 082158d591c5..1d72b0ac3f25 100644
--- a/arch/powerpc/configs/44x/arches_defconfig
+++ b/arch/powerpc/configs/44x/arches_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:04 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:31 2009
#
# CONFIG_PPC64 is not set
@@ -19,6 +19,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -44,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,8 +76,8 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -111,7 +112,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
CONFIG_PPC4xx_PCI_EXPRESS=y
@@ -188,6 +189,7 @@ CONFIG_460EX=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -212,6 +214,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -226,12 +229,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -255,6 +260,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -279,6 +285,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -329,6 +336,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -341,6 +349,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -453,6 +462,10 @@ CONFIG_IBM_NEW_EMAC_EMAC4=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -505,9 +518,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -527,11 +543,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -541,7 +557,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -600,7 +616,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -634,10 +652,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -646,6 +661,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -686,6 +702,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -736,6 +753,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -744,18 +762,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
diff --git a/arch/powerpc/configs/44x/bamboo_defconfig b/arch/powerpc/configs/44x/bamboo_defconfig
index f47c2f3420f6..959bdc43a491 100644
--- a/arch/powerpc/configs/44x/bamboo_defconfig
+++ b/arch/powerpc/configs/44x/bamboo_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:06 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:33 2009
#
# CONFIG_PPC64 is not set
@@ -19,6 +19,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -44,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +76,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -115,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -126,7 +126,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -134,11 +133,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -155,6 +152,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -193,6 +194,7 @@ CONFIG_IBM440EP_ERR42=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -216,6 +218,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -230,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -259,6 +264,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -283,6 +289,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -333,6 +340,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -345,6 +353,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -394,6 +403,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -476,6 +486,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -498,6 +509,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -550,9 +565,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -571,11 +589,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -585,7 +603,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -631,9 +649,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -659,7 +681,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -693,10 +717,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -705,6 +726,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -745,6 +767,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -795,6 +818,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -803,18 +827,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -841,11 +871,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
index 0694756ac759..81cdcc4b9278 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:08 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:35 2009
#
# CONFIG_PPC64 is not set
@@ -19,6 +19,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -44,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,8 +76,8 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -111,7 +112,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -122,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
CONFIG_PPC4xx_PCI_EXPRESS=y
@@ -188,6 +189,7 @@ CONFIG_460EX=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -212,6 +214,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -226,12 +229,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -255,6 +260,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -279,6 +285,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -329,6 +336,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -341,6 +349,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -453,6 +462,10 @@ CONFIG_IBM_NEW_EMAC_EMAC4=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -505,9 +518,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -527,11 +543,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -541,7 +557,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -600,7 +616,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -634,10 +652,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -646,6 +661,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -686,6 +702,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -736,6 +753,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -744,18 +762,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
diff --git a/arch/powerpc/configs/44x/ebony_defconfig b/arch/powerpc/configs/44x/ebony_defconfig
index c9937578ef7f..be64aa644d15 100644
--- a/arch/powerpc/configs/44x/ebony_defconfig
+++ b/arch/powerpc/configs/44x/ebony_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:09 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:36 2009
#
# CONFIG_PPC64 is not set
@@ -18,6 +18,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -43,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -74,12 +75,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -92,6 +93,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -114,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -125,7 +126,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -133,11 +133,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -154,6 +152,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -192,6 +194,7 @@ CONFIG_440GP=y
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_OF_RTC=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -215,6 +218,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -229,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -257,6 +263,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -281,6 +288,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -331,6 +339,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -343,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -368,6 +378,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_OF_PARTS=y
@@ -439,6 +450,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -469,6 +486,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -551,6 +569,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -573,6 +592,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -625,9 +648,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -646,11 +672,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -660,7 +686,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -706,9 +732,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -734,7 +764,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -768,10 +800,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -791,6 +820,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -831,6 +861,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -882,6 +913,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -890,18 +922,24 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -928,11 +966,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/katmai_defconfig b/arch/powerpc/configs/44x/katmai_defconfig
index e326ee8bd195..f67250b24ec5 100644
--- a/arch/powerpc/configs/44x/katmai_defconfig
+++ b/arch/powerpc/configs/44x/katmai_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:11 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:38 2009
#
# CONFIG_PPC64 is not set
@@ -18,6 +18,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -43,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -74,8 +75,8 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -110,7 +111,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -121,7 +121,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -129,11 +128,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -150,6 +147,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
CONFIG_PPC4xx_PCI_EXPRESS=y
@@ -187,6 +188,7 @@ CONFIG_440SPe=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -210,6 +212,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -224,12 +227,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -253,6 +258,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -277,6 +283,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -327,6 +334,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -339,6 +347,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -388,6 +397,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -472,6 +482,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -494,6 +505,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -546,9 +561,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -568,11 +586,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -582,7 +600,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -628,9 +646,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -656,7 +678,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -690,10 +714,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -702,6 +723,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -742,6 +764,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -792,6 +815,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -800,18 +824,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -837,11 +867,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/rainier_defconfig b/arch/powerpc/configs/44x/rainier_defconfig
index 927f829e2087..9348c12bd7a6 100644
--- a/arch/powerpc/configs/44x/rainier_defconfig
+++ b/arch/powerpc/configs/44x/rainier_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:13 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:41 2009
#
# CONFIG_PPC64 is not set
@@ -18,6 +18,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -43,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -74,12 +75,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +115,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -125,7 +125,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -133,11 +132,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -154,6 +151,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -191,6 +192,7 @@ CONFIG_440GRX=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -214,6 +216,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -228,12 +231,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -257,6 +262,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -281,6 +287,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -331,6 +338,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -343,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -368,6 +377,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -440,6 +450,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -470,6 +486,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -532,6 +549,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -554,6 +572,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -606,9 +628,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -627,11 +652,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -641,7 +666,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -687,9 +712,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -715,7 +744,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -749,10 +780,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -772,6 +800,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -812,6 +841,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -863,6 +893,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -871,18 +902,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -922,11 +959,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig
index 15f48e03ec2e..70d5c3fa3283 100644
--- a/arch/powerpc/configs/44x/sam440ep_defconfig
+++ b/arch/powerpc/configs/44x/sam440ep_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:15 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:42 2009
#
# CONFIG_PPC64 is not set
@@ -19,6 +19,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -44,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +77,12 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -115,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -126,7 +126,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -134,11 +133,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -155,6 +152,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -193,6 +194,7 @@ CONFIG_IBM440EP_ERR42=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -216,6 +218,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -230,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -258,6 +263,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -282,6 +288,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -332,6 +339,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -344,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -551,6 +560,10 @@ CONFIG_IBM_NEW_EMAC_ZMII=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -605,6 +618,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_APPLETOUCH is not set
@@ -661,9 +675,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -730,8 +747,8 @@ CONFIG_I2C_IBM_IIC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -751,11 +768,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -764,9 +781,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -848,12 +869,13 @@ CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
# CONFIG_LCD_ILI9320 is not set
# CONFIG_LCD_PLATFORM is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_GENERIC=y
#
# Display device support
@@ -894,11 +916,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -906,12 +926,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -943,6 +966,7 @@ CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -968,18 +992,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1027,6 +1050,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1065,6 +1092,7 @@ CONFIG_RTC_DRV_M41T80=y
CONFIG_RTC_DRV_M41T80_WDT=y
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1117,6 +1145,7 @@ CONFIG_FS_POSIX_ACL=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1156,10 +1185,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
# CONFIG_HFS_FS is not set
@@ -1168,6 +1194,7 @@ CONFIG_AFFS_FS=m
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1245,6 +1272,7 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1278,12 +1306,17 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/configs/44x/sequoia_defconfig b/arch/powerpc/configs/44x/sequoia_defconfig
index 562beeaab53d..a921fe3c3711 100644
--- a/arch/powerpc/configs/44x/sequoia_defconfig
+++ b/arch/powerpc/configs/44x/sequoia_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:16 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:45 2009
#
# CONFIG_PPC64 is not set
@@ -19,6 +19,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -44,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +76,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -115,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -126,7 +126,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -134,11 +133,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -155,6 +152,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -192,6 +193,7 @@ CONFIG_440EPX=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -216,6 +218,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -230,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -259,6 +264,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -283,6 +289,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -333,6 +340,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -345,6 +353,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -370,6 +379,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -442,6 +452,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -472,6 +488,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -554,6 +571,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -576,6 +594,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -628,9 +650,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -649,11 +674,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -663,7 +688,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -709,9 +734,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -737,7 +766,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -771,10 +802,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -794,6 +822,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -834,6 +863,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -885,6 +915,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -893,18 +924,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -944,11 +981,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/taishan_defconfig b/arch/powerpc/configs/44x/taishan_defconfig
index 427bb6a11be5..826700872d26 100644
--- a/arch/powerpc/configs/44x/taishan_defconfig
+++ b/arch/powerpc/configs/44x/taishan_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:18 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:47 2009
#
# CONFIG_PPC64 is not set
@@ -18,6 +18,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -43,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -74,12 +75,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +115,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -125,7 +125,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -133,11 +132,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -154,6 +151,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -191,6 +192,7 @@ CONFIG_440GX=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -214,6 +216,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -228,12 +231,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -257,6 +262,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -281,6 +287,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -331,6 +338,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -343,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -368,6 +377,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_OF_PARTS is not set
@@ -440,6 +450,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -470,6 +486,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -554,6 +571,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -576,6 +594,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -628,9 +650,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -649,11 +674,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -663,7 +688,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -709,9 +734,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -737,7 +766,9 @@ CONFIG_EXT2_FS=y
# 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
@@ -771,10 +802,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -784,6 +812,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -824,6 +853,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -874,6 +904,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -882,18 +913,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -920,11 +957,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/virtex5_defconfig b/arch/powerpc/configs/44x/virtex5_defconfig
index 7513d360e0b0..15aab1ca6384 100644
--- a/arch/powerpc/configs/44x/virtex5_defconfig
+++ b/arch/powerpc/configs/44x/virtex5_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Fri Nov 14 10:31:16 2008
+# Linux kernel version: 2.6.29-rc2
+# Tue Jan 20 08:22:49 2009
#
# CONFIG_PPC64 is not set
@@ -18,6 +18,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -44,7 +45,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -77,8 +78,8 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -116,7 +117,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -127,7 +127,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -135,11 +134,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -156,6 +153,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
# CONFIG_PPC4xx_PCI_EXPRESS is not set
@@ -194,6 +195,7 @@ CONFIG_XILINX_VIRTEX_5_FXT=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -211,13 +213,13 @@ CONFIG_HZ=250
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -232,12 +234,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -261,6 +265,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -285,6 +290,8 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -428,6 +435,7 @@ CONFIG_IP_NF_MANGLE=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -443,8 +451,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -579,6 +588,10 @@ CONFIG_NETDEV_1000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -679,9 +692,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
# CONFIG_NVRAM is not set
@@ -859,7 +875,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -875,6 +890,7 @@ CONFIG_EXT2_FS=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -911,10 +927,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -923,6 +936,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1002,6 +1016,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1051,6 +1066,7 @@ CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1060,6 +1076,8 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1069,11 +1087,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1099,6 +1119,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/44x/warp_defconfig b/arch/powerpc/configs/44x/warp_defconfig
index 59cbd2761ed7..3b77f092abe1 100644
--- a/arch/powerpc/configs/44x/warp_defconfig
+++ b/arch/powerpc/configs/44x/warp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 09:16:22 2008
+# Linux kernel version: 2.6.29-rc2
+# Fri Jan 23 07:57:16 2009
#
# CONFIG_PPC64 is not set
@@ -19,6 +19,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -44,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +76,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +114,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -124,7 +124,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -132,11 +131,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +150,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -190,6 +191,7 @@ CONFIG_IBM440EP_ERR42=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -213,6 +215,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -227,12 +230,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -273,6 +278,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -348,6 +354,7 @@ CONFIG_VLAN_8021Q=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,6 +367,7 @@ CONFIG_VLAN_8021Q=y
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -380,8 +388,9 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
# CONFIG_MTD_AR7_PARTS is not set
@@ -396,7 +405,7 @@ CONFIG_MTD_BLOCK=y
# CONFIG_INFTL is not set
# CONFIG_RFD_FTL is not set
# CONFIG_SSFDC is not set
-CONFIG_MTD_OOPS=m
+# CONFIG_MTD_OOPS is not set
#
# RAM/ROM/Flash chip drivers
@@ -450,6 +459,7 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC_SMC=y
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_NDFC=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_PLATFORM is not set
@@ -458,6 +468,12 @@ CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -480,7 +496,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -562,6 +580,10 @@ CONFIG_IBM_NEW_EMAC_ZMII=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -616,9 +638,12 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -638,7 +663,7 @@ CONFIG_I2C_HELPER_AUTO=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
-# CONFIG_I2C_IBM_IIC is not set
+CONFIG_I2C_IBM_IIC=y
# CONFIG_I2C_MPC is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SIMTEC is not set
@@ -660,8 +685,8 @@ CONFIG_I2C_HELPER_AUTO=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -679,7 +704,7 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_AD7414 is not set
+CONFIG_SENSORS_AD7414=y
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
@@ -687,8 +712,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -708,6 +735,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -729,13 +757,26 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
CONFIG_THERMAL=y
-# CONFIG_THERMAL_HWMON is not set
-# CONFIG_WATCHDOG is not set
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
#
-# Sonics Silicon Backplane
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_PIKA_WDT=y
+# CONFIG_BOOKE_WDT is not set
+
+#
+# USB-based Watchdog Cards
#
+# CONFIG_USBPCWATCHDOG is not set
CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
# CONFIG_SSB is not set
#
@@ -744,9 +785,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -802,6 +847,7 @@ CONFIG_USB_MON=y
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -824,18 +870,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -880,14 +925,18 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
-CONFIG_MMC=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
# CONFIG_MMC_UNSAFE_RESUME is not set
#
# MMC/SD/SDIO Card Drivers
#
-CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_BOUNCE=y
# CONFIG_SDIO_UART is not set
# CONFIG_MMC_TEST is not set
@@ -898,7 +947,18 @@ CONFIG_MMC_BLOCK_BOUNCE=y
# CONFIG_MMC_SDHCI is not set
# CONFIG_MMC_WBSD is not set
# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+# CONFIG_LEDS_TRIGGERS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
@@ -912,14 +972,18 @@ CONFIG_MMC_BLOCK_BOUNCE=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG 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_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
@@ -952,13 +1016,11 @@ CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -978,6 +1040,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1057,6 +1120,7 @@ CONFIG_NLS_UTF8=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1107,6 +1171,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1115,18 +1180,24 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1134,7 +1205,7 @@ CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
# CONFIG_XMON is not set
-# CONFIG_IRQSTACKS is not set
+CONFIG_IRQSTACKS=y
# CONFIG_VIRQ_DEBUG is not set
CONFIG_BDI_SWITCH=y
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1153,6 +1224,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig
index 3df627494b65..1239c6132b4a 100644
--- a/arch/powerpc/configs/52xx/cm5200_defconfig
+++ b/arch/powerpc/configs/52xx/cm5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Thu Nov 13 02:12:40 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 21:41:58 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,14 +71,23 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -110,7 +119,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -121,13 +129,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -143,7 +149,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -182,9 +187,8 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_PPC_BESTCOMM=y
-# CONFIG_PPC_BESTCOMM_ATA is not set
CONFIG_PPC_BESTCOMM_FEC=y
-# CONFIG_PPC_BESTCOMM_GEN_BD is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -211,6 +215,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -222,12 +227,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -268,6 +275,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -324,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -336,6 +345,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -427,6 +437,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -514,6 +530,9 @@ CONFIG_LXT_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -539,6 +558,10 @@ CONFIG_FEC_MPC52xx_MDIO=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -588,8 +611,10 @@ CONFIG_SERIAL_MPC52xx=y
CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=57600
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -629,8 +654,6 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -675,10 +698,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -736,6 +761,7 @@ CONFIG_USB_DEVICEFS=y
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -760,18 +786,17 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -817,6 +842,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -826,7 +855,6 @@ CONFIG_USB_STORAGE=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -847,6 +875,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -883,10 +912,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -906,6 +932,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1002,6 +1029,7 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1053,6 +1081,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1061,6 +1090,8 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1069,11 +1100,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1100,11 +1133,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/52xx/lite5200b_defconfig b/arch/powerpc/configs/52xx/lite5200b_defconfig
index 5b969f9c925e..b7b880562906 100644
--- a/arch/powerpc/configs/52xx/lite5200b_defconfig
+++ b/arch/powerpc/configs/52xx/lite5200b_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Thu Nov 13 02:10:16 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 21:41:14 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -72,14 +72,23 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -112,7 +121,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +131,6 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +138,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,7 +156,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
CONFIG_FREEZER=y
#
@@ -192,7 +196,7 @@ CONFIG_PPC_LITE5200=y
CONFIG_PPC_BESTCOMM=y
CONFIG_PPC_BESTCOMM_ATA=y
CONFIG_PPC_BESTCOMM_FEC=y
-CONFIG_PPC_BESTCOMM_GEN_BD=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -220,6 +224,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -231,12 +236,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -264,6 +271,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -286,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -342,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -354,6 +364,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -396,13 +407,19 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -445,6 +462,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -461,6 +479,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -580,6 +600,9 @@ CONFIG_LXT_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -626,6 +649,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -648,6 +672,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -695,8 +723,10 @@ CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -762,8 +792,6 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -796,10 +824,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -846,9 +876,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -860,7 +894,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -881,6 +914,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -914,10 +948,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -926,6 +957,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -967,6 +999,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1016,6 +1049,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1024,6 +1058,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1032,11 +1068,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1063,11 +1101,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig
index 3c0d4e561726..fb10f22fd0d2 100644
--- a/arch/powerpc/configs/52xx/motionpro_defconfig
+++ b/arch/powerpc/configs/52xx/motionpro_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Thu Nov 13 02:11:02 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 21:42:29 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,14 +71,23 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -110,7 +119,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -121,13 +129,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -143,7 +149,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -182,9 +187,9 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_PPC_BESTCOMM=y
-# CONFIG_PPC_BESTCOMM_ATA is not set
+CONFIG_PPC_BESTCOMM_ATA=y
CONFIG_PPC_BESTCOMM_FEC=y
-# CONFIG_PPC_BESTCOMM_GEN_BD is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -211,6 +216,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -222,12 +228,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -268,6 +276,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -324,6 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -336,6 +346,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -427,6 +438,12 @@ CONFIG_MTD_ROM=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -447,10 +464,16 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_ATA_OVER_ETH is not set
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -492,6 +515,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
@@ -525,6 +549,9 @@ CONFIG_SMSC_PHY=y
CONFIG_BROADCOM_PHY=y
CONFIG_ICPLUS_PHY=y
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
CONFIG_NET_ETHERNET=y
@@ -548,6 +575,10 @@ CONFIG_FEC_MPC52xx_MDIO=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -590,8 +621,10 @@ CONFIG_SERIAL_MPC52xx=y
CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -629,8 +662,6 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -659,6 +690,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -678,6 +710,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -721,10 +754,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -835,7 +870,6 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -856,6 +890,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -892,10 +927,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -915,6 +947,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1011,6 +1044,7 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1062,6 +1096,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1070,6 +1105,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1078,11 +1115,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1109,11 +1148,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig
index 9d0207783d60..00944c09a0ae 100644
--- a/arch/powerpc/configs/52xx/pcm030_defconfig
+++ b/arch/powerpc/configs/52xx/pcm030_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Thu Nov 13 02:13:16 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 21:41:33 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -72,15 +72,24 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -112,7 +121,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -124,7 +132,6 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -132,11 +139,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,7 +157,6 @@ CONFIG_IOSCHED_NOOP=y
# CONFIG_DEFAULT_CFQ is not set
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -191,9 +195,9 @@ CONFIG_PPC_MPC5200_SIMPLE=y
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_PPC_BESTCOMM=y
-CONFIG_PPC_BESTCOMM_ATA=y
+CONFIG_PPC_BESTCOMM_ATA=m
CONFIG_PPC_BESTCOMM_FEC=y
-CONFIG_PPC_BESTCOMM_GEN_BD=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -212,7 +216,6 @@ CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
@@ -222,6 +225,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -233,12 +237,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -261,6 +267,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -283,6 +290,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -333,6 +341,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -345,6 +354,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -365,6 +375,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_OF_PARTS is not set
@@ -413,9 +424,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -439,6 +448,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -587,6 +602,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -621,6 +639,10 @@ CONFIG_FEC_MPC52xx_MDIO=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -675,7 +697,9 @@ CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=9600
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -740,8 +764,6 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -774,10 +796,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -837,6 +861,7 @@ CONFIG_USB_DEVICEFS=y
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=m
@@ -864,18 +889,17 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -921,6 +945,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -983,7 +1011,6 @@ CONFIG_RTC_DRV_PCF8563=m
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1004,6 +1031,7 @@ CONFIG_FS_MBCACHE=m
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -1039,10 +1067,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1062,6 +1087,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1141,6 +1167,7 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1173,6 +1200,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1180,6 +1209,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
index bc190051e8d5..65237ad6f07e 100644
--- a/arch/powerpc/configs/52xx/tqm5200_defconfig
+++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Thu Nov 13 02:09:30 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 21:42:58 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,14 +71,23 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -110,7 +119,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -121,7 +129,6 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -129,11 +136,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -149,7 +154,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
# CONFIG_FREEZER is not set
#
@@ -188,9 +192,9 @@ CONFIG_PPC_MPC5200_BUGFIX=y
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_PPC_BESTCOMM=y
-# CONFIG_PPC_BESTCOMM_ATA is not set
+CONFIG_PPC_BESTCOMM_ATA=y
CONFIG_PPC_BESTCOMM_FEC=y
-# CONFIG_PPC_BESTCOMM_GEN_BD is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -217,6 +221,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -228,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -274,6 +281,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -330,6 +338,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -342,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -364,6 +374,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_OF_PARTS is not set
@@ -433,6 +444,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -496,6 +513,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
@@ -530,6 +548,9 @@ CONFIG_LXT_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -555,6 +576,10 @@ CONFIG_FEC_MPC52xx_MDIO=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -604,8 +629,10 @@ CONFIG_SERIAL_MPC52xx=y
CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -645,8 +672,6 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -675,6 +700,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
@@ -694,6 +720,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -742,10 +769,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -803,6 +832,7 @@ CONFIG_USB_MON=y
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -827,18 +857,17 @@ CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -884,6 +913,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -947,7 +980,6 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -968,6 +1000,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1004,10 +1037,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1027,6 +1057,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1123,6 +1154,7 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1174,6 +1206,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1182,6 +1215,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1190,11 +1225,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1221,11 +1258,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/asp8347_defconfig b/arch/powerpc/configs/83xx/asp8347_defconfig
index cbecaf3d7906..fc4a39a40e72 100644
--- a/arch/powerpc/configs/83xx/asp8347_defconfig
+++ b/arch/powerpc/configs/83xx/asp8347_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:49 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:47 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +76,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +114,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -124,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -132,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -199,6 +199,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -226,6 +228,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -237,12 +240,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -267,6 +272,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +295,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -345,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +368,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -382,6 +391,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
@@ -456,6 +466,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -486,8 +502,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -536,6 +554,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -590,6 +611,10 @@ CONFIG_GIANFAR=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -666,8 +691,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -732,15 +759,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -760,8 +786,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -782,6 +810,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -827,11 +856,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -840,18 +869,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -916,6 +940,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
@@ -934,11 +959,11 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
# CONFIG_USB_LIBUSUAL is not set
@@ -977,6 +1002,10 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1014,6 +1043,7 @@ CONFIG_RTC_DRV_DS1374=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1061,6 +1091,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1094,10 +1125,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1117,6 +1145,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1209,6 +1238,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1244,6 +1274,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1251,6 +1283,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1269,11 +1302,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
index bfc32ea265a7..9e47ae957e2e 100644
--- a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:50 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:48 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -236,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -267,6 +272,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +295,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -345,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +368,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -384,6 +393,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_OF_PARTS=y
@@ -468,6 +478,12 @@ CONFIG_MTD_NAND_FSL_ELBC=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -499,8 +515,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -543,6 +561,7 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -559,6 +578,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -627,6 +648,9 @@ CONFIG_CICADA_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -651,7 +675,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -661,6 +684,7 @@ CONFIG_E100=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -691,6 +715,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -715,6 +740,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -792,8 +821,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -858,15 +889,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -884,7 +914,7 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
@@ -902,8 +932,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -925,6 +957,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
@@ -971,11 +1004,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -984,18 +1017,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1080,6 +1108,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1106,18 +1135,17 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1177,9 +1205,11 @@ CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_PXA25X is not set
# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
# CONFIG_USB_GADGET_M66592 is not set
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
CONFIG_USB_GADGET_NET2280=y
CONFIG_USB_NET2280=y
# CONFIG_USB_GADGET_GOKU is not set
@@ -1194,6 +1224,10 @@ CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1231,12 +1265,14 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
@@ -1284,6 +1320,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1317,10 +1354,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1340,6 +1374,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1397,6 +1432,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1448,6 +1484,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1457,6 +1494,8 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1465,11 +1504,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1496,11 +1537,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
index aad0e1a98c55..03db97c6cf33 100644
--- a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:51 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:49 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -236,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -267,6 +272,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +295,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -345,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +368,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -384,6 +393,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_OF_PARTS is not set
@@ -468,6 +478,12 @@ CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -499,8 +515,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -543,6 +561,7 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -559,6 +578,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -688,6 +709,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -712,7 +736,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -722,6 +745,7 @@ CONFIG_E100=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -752,6 +776,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -776,6 +801,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -853,8 +882,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -919,15 +950,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -945,7 +975,7 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
@@ -963,8 +993,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -986,6 +1018,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
@@ -1032,11 +1065,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1045,18 +1078,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1141,6 +1169,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1167,18 +1196,17 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1238,9 +1266,11 @@ CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_PXA25X is not set
# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
# CONFIG_USB_GADGET_M66592 is not set
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
CONFIG_USB_GADGET_NET2280=y
CONFIG_USB_NET2280=y
# CONFIG_USB_GADGET_GOKU is not set
@@ -1255,6 +1285,10 @@ CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1292,12 +1326,14 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
@@ -1345,6 +1381,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1378,10 +1415,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1401,6 +1435,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1458,6 +1493,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1509,6 +1545,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1518,6 +1555,8 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1526,11 +1565,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1557,11 +1598,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc832x_mds_defconfig b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
index 9cb8c8b956e4..fb17de53cc02 100644
--- a/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
+++ b/arch/powerpc/configs/83xx/mpc832x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:53 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:50 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
CONFIG_QUICC_ENGINE=y
# CONFIG_QE_GPIO is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -226,6 +228,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -237,12 +240,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -267,6 +272,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +295,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -345,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +368,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -405,8 +414,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -449,6 +460,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -465,6 +477,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -523,6 +537,9 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -563,7 +580,6 @@ CONFIG_NETDEV_1000=y
# CONFIG_GIANFAR is not set
CONFIG_UCC_GETH=y
# CONFIG_UGETH_MAGIC_PACKET is not set
-# CONFIG_UGETH_FILTERING is not set
# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
@@ -572,6 +588,7 @@ CONFIG_UCC_GETH=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -594,6 +611,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -665,8 +686,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
# CONFIG_SERIAL_QE is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -730,15 +753,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -758,8 +780,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -780,6 +804,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -820,11 +845,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -833,18 +858,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -900,9 +920,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -940,6 +964,7 @@ CONFIG_RTC_DRV_DS1374=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -987,6 +1012,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1020,10 +1046,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1032,6 +1055,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1087,6 +1111,7 @@ CONFIG_UCC=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1120,6 +1145,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1127,6 +1154,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1145,11 +1173,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
index 9cc976f010c9..a012ce235203 100644
--- a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:54 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:52 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
CONFIG_QUICC_ENGINE=y
# CONFIG_QE_GPIO is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -226,6 +228,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -237,12 +240,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -267,6 +272,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +295,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -345,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +368,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -407,8 +416,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -451,6 +462,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -467,6 +479,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -525,6 +539,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
CONFIG_ICPLUS_PHY=y
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -566,7 +583,6 @@ CONFIG_E1000=y
# CONFIG_GIANFAR is not set
CONFIG_UCC_GETH=y
# CONFIG_UGETH_MAGIC_PACKET is not set
-# CONFIG_UGETH_FILTERING is not set
# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
@@ -575,6 +591,7 @@ CONFIG_UCC_GETH=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -599,6 +616,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -677,8 +698,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
# CONFIG_SERIAL_QE is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -745,15 +768,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -770,7 +792,7 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
@@ -788,8 +810,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -811,6 +835,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
@@ -857,11 +882,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -870,18 +895,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -966,6 +986,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -991,18 +1012,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1050,6 +1070,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
@@ -1099,6 +1123,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1135,10 +1160,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1147,6 +1169,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1246,6 +1269,7 @@ CONFIG_UCC=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1279,6 +1303,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1286,6 +1312,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1304,11 +1331,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
index 07a674f5344e..4bcc4a1ff308 100644
--- a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:56 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:53 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -236,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -266,6 +271,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -288,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -344,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -359,8 +367,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -381,6 +390,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_TESTS is not set
#
# User Modules And Translation Layers
@@ -426,9 +436,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xfe000000
-CONFIG_MTD_PHYSMAP_LEN=0x1000000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -454,6 +462,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -485,8 +499,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -499,7 +515,6 @@ CONFIG_IDE_GD_ATA=y
# CONFIG_IDE_GD_ATAPI is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -524,6 +539,7 @@ CONFIG_IDE_PROC_FS=y
# 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
@@ -577,6 +593,7 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -593,6 +610,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -723,6 +742,9 @@ CONFIG_CICADA_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
# CONFIG_NET_ETHERNET is not set
@@ -751,6 +773,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -775,6 +798,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -832,8 +859,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -898,15 +927,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
CONFIG_SENSORS_PCF8574=y
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -923,7 +951,7 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
@@ -953,11 +981,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -966,18 +994,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1041,6 +1064,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
@@ -1059,18 +1083,17 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1117,6 +1140,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1154,12 +1181,14 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
@@ -1207,6 +1236,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1243,10 +1273,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1256,6 +1283,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1352,6 +1380,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1385,6 +1414,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1392,6 +1423,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1410,11 +1442,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
index 426232cb0097..9ba5518ce8df 100644
--- a/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
+++ b/arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:57 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:55 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -236,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -266,6 +271,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -288,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -344,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -359,8 +367,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -381,6 +390,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_TESTS is not set
#
# User Modules And Translation Layers
@@ -426,9 +436,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xfe000000
-CONFIG_MTD_PHYSMAP_LEN=0x800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -454,6 +462,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -485,8 +499,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -529,6 +545,7 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -545,6 +562,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -603,6 +622,9 @@ CONFIG_CICADA_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
# CONFIG_NET_ETHERNET is not set
@@ -631,6 +653,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -655,6 +678,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -712,8 +739,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -778,15 +807,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
CONFIG_SENSORS_PCF8574=y
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -803,7 +831,7 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
@@ -833,11 +861,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -846,18 +874,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -921,6 +944,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
@@ -939,18 +963,17 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -996,6 +1019,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1033,12 +1060,14 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
@@ -1086,6 +1115,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1122,10 +1152,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1135,6 +1162,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1231,6 +1259,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1264,6 +1293,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1271,6 +1302,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1289,11 +1321,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc834x_mds_defconfig b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
index 36e2e93a1c53..18e4bc0b3c11 100644
--- a/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
+++ b/arch/powerpc/configs/83xx/mpc834x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:58 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:56 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -236,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -266,6 +271,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -288,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -344,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -359,8 +367,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -404,8 +413,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -454,6 +465,9 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -477,7 +491,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -487,6 +500,7 @@ CONFIG_E100=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -517,6 +531,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -539,6 +554,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -608,8 +627,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -673,15 +694,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -701,8 +721,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -723,6 +745,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -763,11 +786,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -776,18 +799,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -843,9 +861,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -883,6 +905,7 @@ CONFIG_RTC_DRV_DS1374=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -930,6 +953,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -963,10 +987,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -975,6 +996,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1028,6 +1050,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1061,6 +1084,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1068,6 +1093,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1086,11 +1112,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
index 80eb6c9a05c4..76db8138eac7 100644
--- a/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
+++ b/arch/powerpc/configs/83xx/mpc836x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:59 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:58 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +122,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +129,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -197,6 +197,8 @@ CONFIG_IPIC=y
CONFIG_QUICC_ENGINE=y
# CONFIG_QE_GPIO is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -224,6 +226,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -235,12 +238,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -265,6 +270,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -287,6 +293,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -343,6 +350,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -358,8 +366,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -380,6 +389,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_OF_PARTS is not set
@@ -451,6 +461,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -480,8 +496,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -524,6 +542,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -540,6 +559,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -598,6 +619,9 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -638,7 +662,6 @@ CONFIG_NETDEV_1000=y
# CONFIG_GIANFAR is not set
CONFIG_UCC_GETH=y
# CONFIG_UGETH_MAGIC_PACKET is not set
-# CONFIG_UGETH_FILTERING is not set
# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
@@ -647,6 +670,7 @@ CONFIG_UCC_GETH=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -669,6 +693,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -740,8 +768,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
# CONFIG_SERIAL_QE is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -805,15 +835,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -833,8 +862,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -855,6 +886,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -895,11 +927,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -908,18 +940,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -975,9 +1002,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1015,6 +1046,7 @@ CONFIG_RTC_DRV_DS1374=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1062,6 +1094,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1095,10 +1128,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1108,6 +1138,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1163,6 +1194,7 @@ CONFIG_UCC=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1196,6 +1228,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1203,6 +1237,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1221,11 +1256,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
index b9b236806e9f..0dc11c44306b 100644
--- a/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
+++ b/arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:00 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:01 2009
#
# CONFIG_PPC64 is not set
@@ -45,7 +45,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +76,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +114,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -124,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -132,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +198,8 @@ CONFIG_IPIC=y
CONFIG_QUICC_ENGINE=y
CONFIG_QE_GPIO=y
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -224,6 +226,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -235,12 +238,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -267,6 +272,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +295,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -345,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +368,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -384,6 +393,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_OF_PARTS is not set
@@ -462,6 +472,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -493,8 +509,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -543,6 +561,9 @@ CONFIG_PHYLIB=y
CONFIG_BROADCOM_PHY=y
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
# CONFIG_NET_ETHERNET is not set
@@ -566,7 +587,6 @@ CONFIG_NETDEV_1000=y
# CONFIG_GIANFAR is not set
CONFIG_UCC_GETH=y
# CONFIG_UGETH_MAGIC_PACKET is not set
-# CONFIG_UGETH_FILTERING is not set
# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
@@ -582,6 +602,10 @@ CONFIG_UCC_GETH=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -656,8 +680,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_SERIAL_QE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -723,16 +749,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -744,12 +768,13 @@ CONFIG_SPI_MASTER=y
# SPI Master Controller Drivers
#
CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_GPIO is not set
CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
CONFIG_SPI_SPIDEV=y
# CONFIG_SPI_TLE62X0 is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
@@ -758,6 +783,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -794,11 +824,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -807,18 +837,14 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -897,6 +923,7 @@ CONFIG_FB_OF=y
# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -962,6 +989,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -995,10 +1023,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1018,6 +1043,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1074,6 +1100,7 @@ CONFIG_UCC=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1109,6 +1136,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1116,6 +1145,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
CONFIG_PPC_EARLY_DEBUG=y
@@ -1145,11 +1175,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc837x_mds_defconfig b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
index f6350d7e1688..e42f6b3917d2 100644
--- a/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
+++ b/arch/powerpc/configs/83xx/mpc837x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:00 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:59 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -124,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -132,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -199,6 +199,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -236,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -266,6 +271,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -288,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -344,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -359,8 +367,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -404,8 +413,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -448,6 +459,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -464,6 +476,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -583,6 +597,9 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -628,6 +645,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -650,6 +668,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -720,8 +742,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -787,15 +811,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -815,8 +838,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -837,6 +862,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -877,11 +903,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -890,18 +916,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -957,9 +978,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -991,6 +1016,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1024,10 +1050,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1036,6 +1059,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1093,6 +1117,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1124,6 +1149,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1131,6 +1158,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1149,11 +1177,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
index f447de16f75d..408022f79a50 100644
--- a/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:01 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:01 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +113,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -124,7 +123,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -132,11 +130,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -153,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -199,6 +199,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -236,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -266,6 +271,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -288,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -339,6 +346,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -354,8 +362,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -400,8 +409,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -460,6 +471,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -590,6 +603,9 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -644,6 +660,10 @@ CONFIG_GIANFAR=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -721,8 +741,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -789,15 +811,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -817,8 +838,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -839,6 +862,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -884,11 +908,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -897,18 +921,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -961,11 +980,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -973,12 +990,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1011,6 +1031,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
@@ -1029,11 +1050,11 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_LIBUSUAL is not set
@@ -1074,6 +1095,10 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1105,6 +1130,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1138,10 +1164,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1150,6 +1173,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1207,6 +1231,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1238,6 +1263,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1245,6 +1272,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1267,11 +1295,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/83xx/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig
index 8d2d7eeab5f5..a0c42fb65cb9 100644
--- a/arch/powerpc/configs/83xx/sbc834x_defconfig
+++ b/arch/powerpc/configs/83xx/sbc834x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:02 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:02 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -112,7 +112,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -122,7 +121,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -130,11 +128,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +147,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -197,6 +197,8 @@ CONFIG_IPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -223,6 +225,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -234,12 +237,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -264,6 +269,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -286,6 +292,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -342,6 +349,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -357,8 +365,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -402,8 +411,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -452,6 +463,9 @@ CONFIG_PHYLIB=y
CONFIG_BROADCOM_PHY=y
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -504,6 +518,10 @@ CONFIG_GIANFAR=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -573,8 +591,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -640,15 +660,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -668,8 +687,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -690,6 +711,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -730,11 +752,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -743,18 +765,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -822,6 +839,7 @@ CONFIG_HID_COMPAT=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -855,10 +873,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -867,6 +882,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -908,6 +924,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -939,6 +956,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -946,6 +965,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -964,11 +984,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/ksi8560_defconfig b/arch/powerpc/configs/85xx/ksi8560_defconfig
index 1af7b9e37b61..6479bb9f3f57 100644
--- a/arch/powerpc/configs/85xx/ksi8560_defconfig
+++ b/arch/powerpc/configs/85xx/ksi8560_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:03 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:03 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -46,7 +48,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,8 +78,8 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -111,7 +113,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -122,13 +123,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -145,6 +144,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -185,6 +188,7 @@ CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -222,12 +226,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -268,6 +274,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -324,6 +331,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -339,8 +347,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -432,6 +441,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -454,6 +469,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -507,9 +523,12 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
-# CONFIG_MDIO_OF_GPIO is not set
+# CONFIG_MDIO_GPIO is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -534,6 +553,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -595,8 +618,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -614,6 +639,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
@@ -642,11 +672,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -656,14 +686,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -716,9 +739,13 @@ CONFIG_USB_SUPPORT=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -749,6 +776,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -782,10 +810,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -795,6 +820,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -845,6 +871,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -895,6 +922,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -904,6 +932,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -912,11 +942,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -943,6 +975,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/mpc8536_ds_defconfig b/arch/powerpc/configs/85xx/mpc8536_ds_defconfig
index e243e14a6708..e31b6a4732ed 100644
--- a/arch/powerpc/configs/85xx/mpc8536_ds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8536_ds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:05 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:04 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -78,12 +80,12 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -96,6 +98,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -118,7 +121,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -129,7 +131,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -137,11 +138,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -158,6 +157,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -197,6 +200,7 @@ CONFIG_MPIC=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -235,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -265,6 +271,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -288,6 +295,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -376,6 +384,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -392,8 +401,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -442,8 +452,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -487,6 +499,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -503,6 +516,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -622,6 +637,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -668,6 +686,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -692,6 +711,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -783,8 +806,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -849,8 +874,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -869,11 +894,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -882,18 +907,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -920,6 +940,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -965,6 +986,12 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
# DVB-S (satellite) frontends
#
# CONFIG_DVB_CX24110 is not set
@@ -976,8 +1003,10 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_CX24116 is not set
@@ -1018,11 +1047,17 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3304 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_AU8522 is not set
# CONFIG_DVB_S5H1411 is not set
#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
# Digital terrestrial only tuners/PLL
#
# CONFIG_DVB_PLL is not set
@@ -1073,6 +1108,7 @@ CONFIG_SND_PCM=y
# CONFIG_SND_SEQUENCER is not set
# CONFIG_SND_MIXER_OSS is not set
# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1175,11 +1211,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1187,12 +1221,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1225,6 +1262,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1250,18 +1288,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1309,6 +1346,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1346,6 +1387,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1405,7 +1447,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -1447,10 +1491,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=m
@@ -1461,6 +1502,7 @@ CONFIG_BEFS_FS=m
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1562,6 +1604,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1613,6 +1656,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1622,6 +1666,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1630,11 +1676,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1661,11 +1709,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1699,7 +1752,7 @@ CONFIG_CRYPTO_HMAC=y
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/powerpc/configs/85xx/mpc8540_ads_defconfig b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
index d790cbab80b8..905e8a3388d6 100644
--- a/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:06 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:05 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -124,13 +125,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -147,6 +146,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -186,6 +189,7 @@ CONFIG_MPIC=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -224,12 +228,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -270,6 +276,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -326,6 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -341,8 +349,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -380,6 +389,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -415,6 +425,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -437,6 +450,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -502,8 +519,10 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -534,11 +553,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -548,14 +567,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -608,9 +620,13 @@ CONFIG_USB_SUPPORT=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -640,6 +656,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -673,10 +690,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -685,6 +699,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -735,6 +750,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -784,6 +800,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -793,6 +810,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -801,11 +820,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -831,6 +852,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
index f6cb01495ea6..f6fa0b761cb3 100644
--- a/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8544_ds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:08 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:07 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -78,12 +80,12 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -96,6 +98,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -118,7 +121,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -129,7 +131,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -137,11 +138,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -158,6 +157,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -197,6 +200,7 @@ CONFIG_PPC_I8259=y
# CONFIG_CPM2 is not set
CONFIG_FSL_ULI1575=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -235,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -266,6 +272,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +296,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -377,6 +385,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -393,8 +402,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -443,8 +453,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -488,6 +500,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -504,6 +517,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -623,6 +638,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -667,6 +685,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -691,6 +710,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -782,8 +805,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
CONFIG_NVRAM=y
@@ -848,8 +873,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -869,11 +894,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -882,18 +907,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -920,6 +940,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -965,6 +986,12 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
# DVB-S (satellite) frontends
#
# CONFIG_DVB_CX24110 is not set
@@ -976,8 +1003,10 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_CX24116 is not set
@@ -1018,11 +1047,17 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3304 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_AU8522 is not set
# CONFIG_DVB_S5H1411 is not set
#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
# Digital terrestrial only tuners/PLL
#
# CONFIG_DVB_PLL is not set
@@ -1075,6 +1110,7 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1177,11 +1213,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1189,12 +1223,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1227,6 +1264,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1252,18 +1290,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1311,6 +1348,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1348,6 +1389,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1406,7 +1448,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -1448,10 +1492,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=m
@@ -1462,6 +1503,7 @@ CONFIG_BEFS_FS=m
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1563,6 +1605,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1614,6 +1657,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1623,6 +1667,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1631,11 +1677,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1661,11 +1709,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1699,7 +1752,7 @@ CONFIG_CRYPTO_HMAC=y
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/powerpc/configs/85xx/mpc8560_ads_defconfig b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
index 6cf929259ba7..095e2ded6e8b 100644
--- a/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8560_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:09 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:09 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -46,7 +48,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +78,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -116,7 +118,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -127,13 +128,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -150,6 +149,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -190,6 +193,7 @@ CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -227,12 +231,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -257,6 +263,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
CONFIG_PCI_DEBUG=y
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -280,6 +287,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -336,6 +344,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -351,8 +360,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -400,6 +410,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -448,6 +459,9 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -496,6 +510,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -518,6 +533,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -583,8 +602,10 @@ CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -604,6 +625,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
@@ -637,11 +663,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -651,14 +677,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -714,9 +733,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -748,6 +771,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -781,10 +805,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -793,6 +814,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -843,6 +865,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -892,6 +915,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -901,6 +925,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -909,11 +935,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -939,6 +967,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/mpc8568mds_defconfig b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
index 597be8491812..186c1010a135 100644
--- a/arch/powerpc/configs/85xx/mpc8568mds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8568mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:11 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:10 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +115,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,7 +124,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +131,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +150,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -192,6 +194,7 @@ CONFIG_QUICC_ENGINE=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -230,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -260,6 +265,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -283,6 +289,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -339,6 +346,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -354,8 +362,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -401,8 +410,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -445,6 +456,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -461,6 +473,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -519,6 +533,9 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -564,6 +581,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -586,6 +604,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -658,8 +680,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
# CONFIG_SERIAL_QE is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -723,8 +747,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -750,8 +774,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -772,6 +798,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -812,11 +839,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -825,18 +852,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -892,9 +914,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -932,6 +958,7 @@ CONFIG_RTC_DRV_DS1374=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -979,6 +1006,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1012,10 +1040,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1024,6 +1049,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1077,6 +1103,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1126,6 +1153,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1135,6 +1163,8 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1143,11 +1173,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1184,11 +1216,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
index 635588319e0d..813223ae174d 100644
--- a/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc8572_ds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:13 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:12 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,10 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,12 +48,12 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
CONFIG_PPC_UDBG_16550=y
-# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_GENERIC_TBSYNC=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
CONFIG_DEFAULT_UIMAGE=y
@@ -62,7 +65,7 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
# General setup
#
CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
@@ -78,12 +81,12 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -96,6 +99,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -118,7 +122,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -126,10 +129,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -137,11 +140,10 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -158,6 +160,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -197,6 +203,7 @@ CONFIG_PPC_I8259=y
# CONFIG_CPM2 is not set
CONFIG_FSL_ULI1575=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -224,6 +231,7 @@ CONFIG_MATH_EMULATION=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_IRQ_ALL_CPUS is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -235,12 +243,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -266,6 +276,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +300,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -377,6 +389,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -393,8 +406,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -443,8 +457,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -488,6 +504,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -504,6 +521,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -623,6 +642,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -667,6 +689,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -691,6 +714,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -782,8 +809,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
CONFIG_NVRAM=y
@@ -848,8 +877,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -869,11 +898,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -882,18 +911,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -920,6 +944,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -965,6 +990,12 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
# DVB-S (satellite) frontends
#
# CONFIG_DVB_CX24110 is not set
@@ -976,8 +1007,10 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_CX24116 is not set
@@ -1018,11 +1051,17 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3304 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_AU8522 is not set
# CONFIG_DVB_S5H1411 is not set
#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
# Digital terrestrial only tuners/PLL
#
# CONFIG_DVB_PLL is not set
@@ -1075,6 +1114,7 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1177,11 +1217,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1189,12 +1227,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1227,6 +1268,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1252,18 +1294,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1311,6 +1352,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1348,6 +1393,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1394,7 +1440,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -1436,10 +1484,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=m
@@ -1450,6 +1495,7 @@ CONFIG_BEFS_FS=m
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1551,6 +1597,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1602,6 +1649,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1611,6 +1659,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1619,11 +1669,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1649,11 +1701,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1687,7 +1744,7 @@ CONFIG_CRYPTO_HMAC=y
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
index 8769359dfe6a..f95961c04a20 100644
--- a/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
+++ b/arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:14 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:13 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -115,7 +117,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -125,13 +126,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -148,6 +147,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -187,6 +190,7 @@ CONFIG_PPC_I8259=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -225,12 +229,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -255,6 +261,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -278,6 +285,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -334,6 +342,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -349,8 +358,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -397,6 +407,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -439,6 +450,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -498,6 +510,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -542,6 +557,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -564,6 +580,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -634,8 +654,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -672,11 +694,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -686,14 +708,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -749,9 +764,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -783,6 +802,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -816,10 +836,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -828,6 +845,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -878,6 +896,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -927,6 +946,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -936,6 +956,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -944,11 +966,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -974,6 +998,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/sbc8548_defconfig b/arch/powerpc/configs/85xx/sbc8548_defconfig
index bfe3c9731573..e68e80987aa9 100644
--- a/arch/powerpc/configs/85xx/sbc8548_defconfig
+++ b/arch/powerpc/configs/85xx/sbc8548_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:16 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:15 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +115,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,13 +124,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -146,6 +145,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -185,6 +188,7 @@ CONFIG_MPIC=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -222,12 +226,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -251,6 +257,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -274,6 +281,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -330,6 +338,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -345,8 +354,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -391,6 +401,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -439,6 +450,9 @@ CONFIG_PHYLIB=y
CONFIG_BROADCOM_PHY=y
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -483,6 +497,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -505,6 +520,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -575,8 +594,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -613,11 +634,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -627,14 +648,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -693,6 +707,7 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -726,10 +741,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -738,6 +750,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -776,6 +789,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -807,6 +821,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -814,6 +830,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -831,6 +848,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/sbc8560_defconfig b/arch/powerpc/configs/85xx/sbc8560_defconfig
index 8c507f8d15a8..b1c766ef7e2e 100644
--- a/arch/powerpc/configs/85xx/sbc8560_defconfig
+++ b/arch/powerpc/configs/85xx/sbc8560_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:17 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:17 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +115,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,13 +124,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -146,6 +145,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -185,6 +188,7 @@ CONFIG_MPIC=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -222,12 +226,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -268,6 +274,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -324,6 +331,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -339,8 +347,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -378,6 +387,7 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -413,6 +423,9 @@ CONFIG_PHYLIB=y
CONFIG_BROADCOM_PHY=y
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -435,6 +448,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -500,8 +517,10 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -530,11 +549,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -544,14 +563,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -604,9 +616,13 @@ CONFIG_USB_SUPPORT=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -666,6 +682,7 @@ CONFIG_RTC_DRV_M48T59=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -699,10 +716,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -711,6 +725,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -761,6 +776,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -809,6 +825,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -818,6 +835,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -826,11 +845,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -867,6 +888,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/stx_gp3_defconfig b/arch/powerpc/configs/85xx/stx_gp3_defconfig
index 5a0cf58d2b8c..eb4ba7a5f41f 100644
--- a/arch/powerpc/configs/85xx/stx_gp3_defconfig
+++ b/arch/powerpc/configs/85xx/stx_gp3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:19 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:18 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -46,7 +48,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +78,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -116,7 +118,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -128,18 +129,15 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -156,6 +154,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -196,6 +198,7 @@ CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -233,12 +236,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -263,6 +268,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -286,6 +292,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -400,6 +407,7 @@ CONFIG_IP_NF_FILTER=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -415,8 +423,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -470,14 +479,17 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -485,7 +497,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=m
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -510,6 +521,7 @@ CONFIG_IDE_PROC_FS=y
# 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
@@ -564,6 +576,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -580,6 +593,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -640,6 +655,9 @@ CONFIG_MARVELL_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -686,6 +704,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -708,6 +727,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -805,11 +828,13 @@ CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
CONFIG_PRINTER=m
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
# CONFIG_NVRAM is not set
@@ -823,6 +848,7 @@ CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
#
# I2C Hardware Bus support
@@ -877,13 +903,12 @@ CONFIG_I2C_HELPER_AUTO=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -898,6 +923,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -924,8 +954,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -946,6 +978,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -972,11 +1005,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -985,17 +1018,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1061,9 +1089,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1096,6 +1128,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1135,10 +1168,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1147,6 +1177,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=m
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1227,6 +1258,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=m
@@ -1278,6 +1310,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1287,6 +1320,8 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1295,11 +1330,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1325,6 +1362,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/tqm8540_defconfig b/arch/powerpc/configs/85xx/tqm8540_defconfig
index f3e4f3481fda..f4379b1cf841 100644
--- a/arch/powerpc/configs/85xx/tqm8540_defconfig
+++ b/arch/powerpc/configs/85xx/tqm8540_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:20 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:19 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -113,7 +115,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -123,13 +124,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -146,6 +145,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -186,6 +189,7 @@ CONFIG_MPIC=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -223,12 +227,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -252,6 +258,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_HAS_RAPIDIO is not set
#
@@ -273,6 +280,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -329,6 +337,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -344,8 +353,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -435,6 +445,12 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -464,8 +480,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -508,6 +526,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -567,6 +586,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -590,7 +612,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -600,6 +621,7 @@ CONFIG_E100=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -629,6 +651,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -651,6 +674,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -721,8 +748,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -787,8 +816,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -814,8 +843,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -836,6 +867,7 @@ CONFIG_SENSORS_LM75=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -862,11 +894,11 @@ CONFIG_HWMON_DEBUG_CHIP=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -875,18 +907,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -942,9 +969,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -976,6 +1007,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1009,10 +1041,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1032,6 +1061,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1082,6 +1112,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1117,6 +1148,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1124,6 +1157,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1141,6 +1175,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/tqm8541_defconfig b/arch/powerpc/configs/85xx/tqm8541_defconfig
index c62489394535..b8669231c1fe 100644
--- a/arch/powerpc/configs/85xx/tqm8541_defconfig
+++ b/arch/powerpc/configs/85xx/tqm8541_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:21 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:20 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -46,7 +48,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +78,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -125,13 +126,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -148,6 +147,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -189,6 +192,7 @@ CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -226,12 +230,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -255,6 +261,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_HAS_RAPIDIO is not set
#
@@ -276,6 +283,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -332,6 +340,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -347,8 +356,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -438,6 +448,12 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -468,8 +484,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -512,6 +530,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -571,6 +590,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -594,7 +616,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -604,6 +625,7 @@ CONFIG_E100=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -634,6 +656,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -656,6 +679,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -728,8 +755,10 @@ CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -796,13 +825,12 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -816,6 +844,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -842,8 +875,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -864,6 +899,7 @@ CONFIG_SENSORS_LM75=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -890,11 +926,11 @@ CONFIG_HWMON_DEBUG_CHIP=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -903,18 +939,14 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -970,9 +1002,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1004,6 +1040,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1037,10 +1074,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1060,6 +1094,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1110,6 +1145,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1145,6 +1181,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1152,6 +1190,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1169,6 +1208,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/tqm8548_defconfig b/arch/powerpc/configs/85xx/tqm8548_defconfig
index eef45b97dc3e..0bc45975911a 100644
--- a/arch/powerpc/configs/85xx/tqm8548_defconfig
+++ b/arch/powerpc/configs/85xx/tqm8548_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:22 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:20 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -45,7 +47,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -115,7 +117,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -126,7 +127,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -134,11 +134,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -155,6 +153,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -195,6 +197,7 @@ CONFIG_MPIC=y
# CONFIG_CPM2 is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -233,12 +236,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -265,6 +270,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -288,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -344,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -359,8 +367,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -383,6 +392,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_OF_PARTS=y
@@ -465,6 +475,12 @@ CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
CONFIG_MTD_UBI=m
@@ -502,8 +518,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -546,6 +564,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -605,6 +624,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -649,6 +671,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -671,6 +694,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -741,8 +768,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -806,8 +835,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -833,8 +862,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -855,6 +886,7 @@ CONFIG_SENSORS_LM75=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -881,11 +913,11 @@ CONFIG_SENSORS_LM75=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -894,18 +926,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -961,9 +988,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1001,6 +1032,7 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1048,6 +1080,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1081,10 +1114,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1095,6 +1125,7 @@ CONFIG_TMPFS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_UBIFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1145,6 +1176,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1194,6 +1226,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1203,6 +1236,8 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1211,11 +1246,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1241,6 +1278,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/tqm8555_defconfig b/arch/powerpc/configs/85xx/tqm8555_defconfig
index 11b637e99a54..d5a864d74461 100644
--- a/arch/powerpc/configs/85xx/tqm8555_defconfig
+++ b/arch/powerpc/configs/85xx/tqm8555_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:23 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:21 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -46,7 +48,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +78,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -125,13 +126,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -148,6 +147,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -189,6 +192,7 @@ CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -226,12 +230,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -255,6 +261,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_HAS_RAPIDIO is not set
#
@@ -276,6 +283,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -332,6 +340,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -347,8 +356,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -438,6 +448,12 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -468,8 +484,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -512,6 +530,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -571,6 +590,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -594,7 +616,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -604,6 +625,7 @@ CONFIG_E100=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -634,6 +656,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -656,6 +679,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -728,8 +755,10 @@ CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -796,13 +825,12 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -816,6 +844,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -842,8 +875,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -864,6 +899,7 @@ CONFIG_SENSORS_LM75=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -890,11 +926,11 @@ CONFIG_HWMON_DEBUG_CHIP=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -903,18 +939,14 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -970,9 +1002,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1004,6 +1040,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1037,10 +1074,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1060,6 +1094,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1110,6 +1145,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1145,6 +1181,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1152,6 +1190,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1169,6 +1208,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/85xx/tqm8560_defconfig b/arch/powerpc/configs/85xx/tqm8560_defconfig
index 2519169b6d4b..a25009174f37 100644
--- a/arch/powerpc/configs/85xx/tqm8560_defconfig
+++ b/arch/powerpc/configs/85xx/tqm8560_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:25 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:22 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -46,7 +48,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +78,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -114,7 +116,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -125,13 +126,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -148,6 +147,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -189,6 +192,7 @@ CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -226,12 +230,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -255,6 +261,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_HAS_RAPIDIO is not set
#
@@ -276,6 +283,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -332,6 +340,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -347,8 +356,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -438,6 +448,12 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -468,8 +484,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -512,6 +530,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -571,6 +590,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -594,7 +616,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -604,6 +625,7 @@ CONFIG_E100=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -634,6 +656,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -656,6 +679,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -728,8 +755,10 @@ CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -796,13 +825,12 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -816,6 +844,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -842,8 +875,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -864,6 +899,7 @@ CONFIG_SENSORS_LM75=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -890,11 +926,11 @@ CONFIG_HWMON_DEBUG_CHIP=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -903,18 +939,14 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -970,9 +1002,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1004,6 +1040,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1037,10 +1074,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1060,6 +1094,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1110,6 +1145,7 @@ CONFIG_PARTITION_ADVANCED=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1145,6 +1181,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1152,6 +1190,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1169,6 +1208,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/86xx/gef_sbc610_defconfig b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
index cd1ffa449327..1ab5abae00a2 100644
--- a/arch/powerpc/configs/86xx/gef_sbc610_defconfig
+++ b/arch/powerpc/configs/86xx/gef_sbc610_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:30 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:26 2009
#
# CONFIG_PPC64 is not set
@@ -42,11 +42,12 @@ CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -78,12 +79,12 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
@@ -117,7 +118,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -129,7 +129,6 @@ CONFIG_USE_GENERIC_SMP_HELPERS=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -137,12 +136,10 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,6 +156,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -197,6 +198,7 @@ CONFIG_MPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -215,7 +217,6 @@ CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
@@ -225,6 +226,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_IRQ_ALL_CPUS=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
@@ -237,12 +239,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -270,6 +274,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
CONFIG_PCI_DEBUG=y
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
CONFIG_HAS_RAPIDIO=y
@@ -293,6 +298,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -502,6 +508,7 @@ CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
+# CONFIG_NET_SCH_DRR is not set
#
# Classification
@@ -522,6 +529,7 @@ CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_CLS_ACT is not set
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -538,8 +546,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -562,6 +571,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_OF_PARTS is not set
@@ -638,10 +648,17 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
CONFIG_OF_I2C=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
@@ -668,8 +685,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -729,6 +748,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -848,6 +869,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -902,6 +926,10 @@ CONFIG_GIANFAR=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -924,6 +952,7 @@ CONFIG_ATM_DRIVERS=y
# CONFIG_ATM_IA is not set
# CONFIG_ATM_FORE200E is not set
# CONFIG_ATM_HE is not set
+# CONFIG_ATM_SOLOS is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
CONFIG_PPP=m
@@ -1016,7 +1045,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -1055,6 +1086,7 @@ CONFIG_I2C_HELPER_AUTO=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
+# CONFIG_I2C_GPIO is not set
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SIMTEC is not set
@@ -1081,8 +1113,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
CONFIG_DS1682=y
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -1095,7 +1127,31 @@ CONFIG_DS1682=y
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
@@ -1108,8 +1164,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -1130,6 +1188,7 @@ CONFIG_HWMON=y
CONFIG_SENSORS_LM90=y
CONFIG_SENSORS_LM92=y
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -1163,6 +1222,7 @@ CONFIG_WATCHDOG=y
#
# CONFIG_SOFT_WATCHDOG is not set
# CONFIG_ALIM7101_WDT is not set
+CONFIG_GEF_WDT=y
# CONFIG_8xxx_WDT is not set
#
@@ -1175,11 +1235,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1188,18 +1248,14 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1259,11 +1315,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1271,12 +1325,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1309,6 +1366,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1331,18 +1389,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1390,6 +1447,11 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_VST is not set
# CONFIG_USB_ATM is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1477,6 +1539,7 @@ CONFIG_FS_POSIX_ACL=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1513,10 +1576,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1526,6 +1586,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1612,6 +1673,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1662,6 +1724,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1671,6 +1734,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1680,11 +1745,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1705,6 +1772,7 @@ CONFIG_SECURITY=y
# CONFIG_SECURITYFS is not set
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
+# 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
@@ -1715,11 +1783,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
index 72854a10dfa1..bbdf4bfc4327 100644
--- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:28 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:24 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_SYSVIPC_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -115,7 +115,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -126,7 +125,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -134,11 +132,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -155,6 +151,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -194,6 +194,7 @@ CONFIG_MPIC=y
# CONFIG_QUICC_ENGINE is not set
CONFIG_FSL_ULI1575=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -213,7 +214,6 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_IOMMU_HELPER is not set
@@ -221,6 +221,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -232,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -265,6 +268,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
CONFIG_PCI_DEBUG=y
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -287,6 +291,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -360,6 +365,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -375,8 +381,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -401,6 +408,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_OF_PARTS is not set
@@ -481,6 +489,12 @@ CONFIG_MTD_NAND_FSL_ELBC=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -510,8 +524,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -524,7 +540,6 @@ CONFIG_IDE_GD_ATA=y
# CONFIG_IDE_GD_ATAPI is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -549,6 +564,7 @@ CONFIG_IDE_PROC_FS=y
# 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
@@ -618,6 +634,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -757,6 +775,10 @@ CONFIG_ULI526X=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -841,7 +863,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -905,8 +929,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -926,11 +950,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -939,18 +963,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1029,6 +1048,7 @@ CONFIG_FB_FSL_DIU=y
# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1054,6 +1074,7 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1130,6 +1151,7 @@ CONFIG_SND_PPC=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_MPC8610=y
CONFIG_SND_SOC_MPC8610_HPCD=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_CS4270=y
CONFIG_SND_SOC_CS4270_VD33_ERRATA=y
@@ -1157,9 +1179,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1197,6 +1223,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1244,6 +1271,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -1276,10 +1304,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1289,6 +1314,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1388,6 +1414,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1438,6 +1465,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1447,6 +1475,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1455,11 +1485,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1486,6 +1518,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
index 41220ece603d..92acfdf3540a 100644
--- a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:29 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:25 2009
#
# CONFIG_PPC64 is not set
@@ -45,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -78,12 +78,12 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -96,6 +96,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -118,7 +119,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -130,7 +130,6 @@ CONFIG_USE_GENERIC_SMP_HELPERS=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -138,12 +137,10 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -160,6 +157,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -198,6 +199,7 @@ CONFIG_PPC_I8259=y
# CONFIG_QUICC_ENGINE is not set
CONFIG_FSL_ULI1575=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -225,6 +227,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
# CONFIG_IRQ_ALL_CPUS is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
@@ -237,12 +240,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -268,6 +273,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
CONFIG_HAS_RAPIDIO=y
@@ -291,6 +297,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -379,6 +386,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -395,8 +403,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -445,8 +454,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -490,6 +501,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -506,6 +518,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -625,6 +639,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -670,6 +687,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -694,6 +712,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -785,8 +807,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
@@ -851,8 +875,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -872,11 +896,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -885,18 +909,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -923,6 +942,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -968,6 +988,12 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
# DVB-S (satellite) frontends
#
# CONFIG_DVB_CX24110 is not set
@@ -979,8 +1005,10 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_CX24116 is not set
@@ -1021,11 +1049,17 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3304 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_AU8522 is not set
# CONFIG_DVB_S5H1411 is not set
#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
# Digital terrestrial only tuners/PLL
#
# CONFIG_DVB_PLL is not set
@@ -1078,6 +1112,7 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1180,11 +1215,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1192,12 +1225,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1230,6 +1266,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1255,18 +1292,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1314,6 +1350,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1351,6 +1391,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1397,7 +1438,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -1439,10 +1482,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=m
@@ -1453,6 +1493,7 @@ CONFIG_BEFS_FS=m
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1554,6 +1595,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1605,6 +1647,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1614,6 +1657,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1622,11 +1667,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1653,11 +1700,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1691,7 +1742,7 @@ CONFIG_CRYPTO_HMAC=y
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/powerpc/configs/86xx/sbc8641d_defconfig b/arch/powerpc/configs/86xx/sbc8641d_defconfig
index a4342862f6ef..04797e730c5a 100644
--- a/arch/powerpc/configs/86xx/sbc8641d_defconfig
+++ b/arch/powerpc/configs/86xx/sbc8641d_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:40:26 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:36:23 2009
#
# CONFIG_PPC64 is not set
@@ -46,7 +46,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -78,12 +78,12 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
@@ -117,7 +117,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -129,7 +128,6 @@ CONFIG_USE_GENERIC_SMP_HELPERS=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -137,12 +135,10 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -159,6 +155,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -197,6 +197,7 @@ CONFIG_MPIC=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -215,7 +216,6 @@ CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
@@ -225,6 +225,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_IRQ_ALL_CPUS=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
@@ -237,12 +238,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -270,6 +273,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -292,6 +296,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -501,6 +506,7 @@ CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
+# CONFIG_NET_SCH_DRR is not set
#
# Classification
@@ -521,6 +527,7 @@ CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_CLS_ACT is not set
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -537,8 +544,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -561,6 +569,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_OF_PARTS is not set
@@ -637,6 +646,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -666,8 +681,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -734,6 +751,9 @@ CONFIG_PHYLIB=y
CONFIG_BROADCOM_PHY=y
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -786,6 +806,10 @@ CONFIG_GIANFAR=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
CONFIG_ATM_DRIVERS=y
# CONFIG_ATM_DUMMY is not set
@@ -801,6 +825,7 @@ CONFIG_ATM_DRIVERS=y
# CONFIG_ATM_IA is not set
# CONFIG_ATM_FORE200E is not set
# CONFIG_ATM_HE is not set
+# CONFIG_ATM_SOLOS is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
CONFIG_PPP=m
@@ -892,8 +917,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
# CONFIG_NVRAM is not set
@@ -958,8 +985,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -985,8 +1012,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -1007,6 +1036,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -1047,11 +1077,11 @@ CONFIG_SOFT_WATCHDOG=m
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1060,18 +1090,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1134,9 +1159,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1182,11 +1211,18 @@ CONFIG_OCFS2_FS_O2CB=m
CONFIG_OCFS2_FS_STATS=y
CONFIG_OCFS2_DEBUG_MASKLOG=y
# CONFIG_OCFS2_DEBUG_FS is not set
-# CONFIG_OCFS2_COMPAT_JBD is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=m
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
# CONFIG_FUSE_FS is not set
@@ -1216,10 +1252,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1229,6 +1262,7 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
CONFIG_MINIX_FS=m
# CONFIG_OMFS_FS is not set
@@ -1317,6 +1351,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1367,6 +1402,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1376,6 +1412,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1385,11 +1423,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1411,6 +1451,7 @@ CONFIG_SECURITY=y
# CONFIG_SECURITYFS is not set
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
CONFIG_CRYPTO=y
@@ -1420,11 +1461,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/adder875_defconfig b/arch/powerpc/configs/adder875_defconfig
index 024f279af90a..aaab5cc3751c 100644
--- a/arch/powerpc/configs/adder875_defconfig
+++ b/arch/powerpc/configs/adder875_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:32 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:24 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_PPC_8xx=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_8xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -71,12 +72,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -109,7 +110,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -119,13 +119,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -142,6 +140,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -187,6 +189,7 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -205,12 +208,12 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_8XX_MINIMAL_FPEMU is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -225,12 +228,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -272,6 +277,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -323,6 +329,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -338,8 +345,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -428,6 +436,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -470,6 +484,9 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -495,6 +512,10 @@ CONFIG_FS_ENET_MDIO_FEC=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -580,7 +601,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -598,11 +621,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -612,14 +635,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -674,6 +690,7 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -706,10 +723,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -719,6 +733,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -774,6 +789,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Library routines
#
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -821,6 +837,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -829,6 +846,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -837,11 +856,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig
index 5078594cd1f5..5103319a7f56 100644
--- a/arch/powerpc/configs/c2k_defconfig
+++ b/arch/powerpc/configs/c2k_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:34 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:26 2009
#
# CONFIG_PPC64 is not set
@@ -45,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -78,12 +78,12 @@ CONFIG_AUDITSYSCALL=y
CONFIG_AUDIT_TREE=y
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -122,6 +122,7 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
@@ -135,7 +136,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -143,11 +143,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -164,6 +162,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -221,6 +223,7 @@ CONFIG_CPU_FREQ_GOV_ONDEMAND=m
#
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -243,10 +246,12 @@ CONFIG_BINFMT_ELF=y
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -258,12 +263,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -287,6 +294,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
CONFIG_HOTPLUG_PCI=y
# CONFIG_HOTPLUG_PCI_FAKE is not set
@@ -314,6 +322,8 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -574,6 +584,7 @@ CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
+# CONFIG_NET_SCH_DRR is not set
#
# Classification
@@ -594,6 +605,7 @@ CONFIG_NET_CLS_RSVP6=m
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_CLS_IND=y
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -616,8 +628,6 @@ CONFIG_BT_HIDP=m
#
# Bluetooth device drivers
#
-CONFIG_BT_HCIUSB=m
-CONFIG_BT_HCIUSB_SCO=y
# CONFIG_BT_HCIBTUSB is not set
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_H4=y
@@ -635,12 +645,9 @@ CONFIG_WIRELESS=y
CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -665,6 +672,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=m
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_OF_PARTS=y
@@ -737,6 +745,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -834,6 +848,8 @@ CONFIG_MEGARAID_MAILBOX=m
CONFIG_MEGARAID_SAS=m
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
CONFIG_SCSI_FUTURE_DOMAIN=m
@@ -852,6 +868,7 @@ CONFIG_SCSI_QLOGIC_1280=m
# CONFIG_SCSI_QLA_FC is not set
# CONFIG_SCSI_QLA_ISCSI is not set
CONFIG_SCSI_LPFC=m
+# CONFIG_SCSI_LPFC_DEBUG_FS is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
@@ -896,6 +913,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -949,6 +969,10 @@ CONFIG_MV643XX_ETH=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -1055,7 +1079,9 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
CONFIG_NVRAM=m
@@ -1124,8 +1150,8 @@ CONFIG_I2C_MV64XXX=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=m
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=m
CONFIG_SENSORS_PCF8574=m
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -1151,8 +1177,10 @@ CONFIG_SENSORS_ADM1026=m
# CONFIG_SENSORS_ADM1029 is not set
CONFIG_SENSORS_ADM1031=m
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
CONFIG_SENSORS_DS1621=m
# CONFIG_SENSORS_I5K_AMB is not set
@@ -1173,6 +1201,7 @@ CONFIG_SENSORS_LM87=m
CONFIG_SENSORS_LM90=m
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
CONFIG_SENSORS_MAX1619=m
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -1218,11 +1247,11 @@ CONFIG_WDT_501_PCI=y
# USB-based Watchdog Cards
#
CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1234,14 +1263,8 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1298,7 +1321,7 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
# CONFIG_USB_OTG is not set
-CONFIG_USB_MON=y
+CONFIG_USB_MON=m
# CONFIG_USB_WUSB is not set
# CONFIG_USB_WUSB_CBAF is not set
@@ -1310,6 +1333,7 @@ CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=m
@@ -1339,18 +1363,17 @@ CONFIG_USB_PRINTER=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_DPCM=y
# CONFIG_USB_STORAGE_USBAT is not set
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
@@ -1419,12 +1442,14 @@ CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_SERIAL_HP4X is not set
CONFIG_USB_SERIAL_SAFE=m
CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
# CONFIG_USB_SERIAL_TI is not set
CONFIG_USB_SERIAL_CYBERJACK=m
CONFIG_USB_SERIAL_XIRCOM=m
# CONFIG_USB_SERIAL_OPTION is not set
CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_OPTICON is not set
# CONFIG_USB_SERIAL_DEBUG is not set
#
@@ -1458,6 +1483,10 @@ CONFIG_USB_SPEEDTOUCH=m
# CONFIG_USB_UEAGLEATM is not set
# CONFIG_USB_XUSBATM is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1500,19 +1529,23 @@ CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
# CONFIG_EXT4_FS is not set
CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS 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_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
# CONFIG_QUOTA_NETLINK_INTERFACE is not set
CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
@@ -1549,10 +1582,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_ECRYPT_FS is not set
@@ -1573,6 +1603,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=m
+# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1678,6 +1709,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=m
@@ -1703,7 +1735,7 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
@@ -1722,6 +1754,7 @@ CONFIG_DEBUG_SPINLOCK=y
# CONFIG_DEBUG_MUTEXES is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_HIGHMEM=y
CONFIG_DEBUG_BUGVERBOSE=y
@@ -1731,6 +1764,7 @@ CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1741,7 +1775,12 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
#
# Tracers
@@ -1750,11 +1789,14 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1763,6 +1805,7 @@ CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_MSI_BITMAP_SELFTEST is not set
# CONFIG_XMON is not set
# CONFIG_IRQSTACKS is not set
+# CONFIG_VIRQ_DEBUG is not set
# CONFIG_BDI_SWITCH is not set
CONFIG_BOOTX_TEXT=y
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1776,6 +1819,7 @@ CONFIG_SECURITY=y
# CONFIG_SECURITYFS is not set
CONFIG_SECURITY_NETWORK=y
# CONFIG_SECURITY_NETWORK_XFRM is not set
+# CONFIG_SECURITY_PATH is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
CONFIG_SECURITY_SELINUX=y
@@ -1785,7 +1829,6 @@ CONFIG_SECURITY_SELINUX_DISABLE=y
CONFIG_SECURITY_SELINUX_DEVELOP=y
CONFIG_SECURITY_SELINUX_AVC_STATS=y
CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
-# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
CONFIG_CRYPTO=y
@@ -1794,11 +1837,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index c420e47426f8..c6d2baa7aaeb 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1012,7 +1012,7 @@ CONFIG_I2C_ALGOBIT=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index 9ba3c6fc2fef..d2123779512a 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -834,7 +834,7 @@ CONFIG_I2C_ALGOBIT=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index 63b3c2372ce8..5094a65a4493 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -941,8 +941,8 @@ CONFIG_I2C_ALGOBIT=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/powerpc/configs/ep8248e_defconfig b/arch/powerpc/configs/ep8248e_defconfig
index a6f1cff564e6..add6419c15d9 100644
--- a/arch/powerpc/configs/ep8248e_defconfig
+++ b/arch/powerpc/configs/ep8248e_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:36 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:27 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -86,6 +86,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -107,7 +108,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -118,13 +118,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
#
@@ -140,6 +138,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -181,6 +183,7 @@ CONFIG_8272=y
CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -206,6 +209,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_FLATMEM=y
@@ -213,12 +217,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -243,6 +249,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -265,6 +272,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -346,6 +354,7 @@ CONFIG_NETFILTER_ADVANCED=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +369,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
#
@@ -455,6 +465,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -522,9 +538,12 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
-# CONFIG_MDIO_OF_GPIO is not set
+# CONFIG_MDIO_GPIO is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
@@ -569,6 +588,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -591,6 +611,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_PPP is not set
@@ -633,6 +657,7 @@ CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -651,6 +676,11 @@ CONFIG_GPIOLIB=y
# CONFIG_DEBUG_GPIO is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
@@ -668,11 +698,11 @@ CONFIG_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -682,14 +712,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -782,13 +805,11 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HFSPLUS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -877,6 +898,7 @@ CONFIG_NLS_UTF8=y
#
# Library routines
#
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -924,6 +946,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -933,6 +956,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -941,10 +966,12 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -971,11 +998,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
diff --git a/arch/powerpc/configs/ep88xc_defconfig b/arch/powerpc/configs/ep88xc_defconfig
index 870d28976a44..b2fdfd9e183c 100644
--- a/arch/powerpc/configs/ep88xc_defconfig
+++ b/arch/powerpc/configs/ep88xc_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:37 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:28 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_PPC_8xx=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_8xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -70,12 +71,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -108,7 +109,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -118,13 +118,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -141,6 +139,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -186,6 +188,7 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -205,12 +208,12 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
CONFIG_8XX_MINIMAL_FPEMU=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -225,12 +228,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -272,6 +277,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -323,6 +329,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -338,8 +345,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -428,6 +436,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -470,6 +484,9 @@ CONFIG_LXT_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -495,6 +512,10 @@ CONFIG_FS_ENET_MDIO_FEC=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -536,7 +557,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -555,11 +578,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -569,14 +592,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -630,6 +646,7 @@ CONFIG_DAB=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -662,10 +679,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -675,6 +689,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -730,6 +745,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Library routines
#
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -777,6 +793,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -785,6 +802,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -793,11 +812,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index f85e71ccb989..fc905924c022 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -994,8 +994,8 @@ CONFIG_I2C_POWERMAC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index 54fa62481373..aa5855a156de 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:38 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:29 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -74,12 +74,12 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -118,7 +118,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -129,7 +128,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -137,11 +135,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -158,6 +154,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -200,6 +200,7 @@ CONFIG_MPIC=y
# CONFIG_TAU is not set
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -227,6 +228,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -238,12 +240,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -267,6 +271,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -289,6 +294,8 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -455,6 +462,7 @@ CONFIG_IP_NF_ARP_MANGLE=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -471,12 +479,9 @@ CONFIG_WIRELESS=y
CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=m
-CONFIG_IEEE80211_DEBUG=y
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -501,6 +506,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_OF_PARTS is not set
@@ -554,9 +560,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xffc00000
-CONFIG_MTD_PHYSMAP_LEN=0x400000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -580,6 +584,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -610,8 +620,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -654,6 +666,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -670,6 +683,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -827,6 +842,7 @@ CONFIG_R8169=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -851,6 +867,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -949,8 +969,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -1015,8 +1037,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=m
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -1042,8 +1064,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -1064,6 +1088,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -1090,11 +1115,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1103,18 +1128,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1165,12 +1185,6 @@ CONFIG_HID=m
# CONFIG_HID_PID is not set
#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-
-#
# Special HID drivers
#
CONFIG_HID_COMPAT=y
@@ -1202,6 +1216,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1227,18 +1242,17 @@ CONFIG_USB_PRINTER=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1295,12 +1309,14 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
# CONFIG_USB_SERIAL_SPCP8X5 is not set
# CONFIG_USB_SERIAL_HP4X is not set
# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
# CONFIG_USB_SERIAL_TI is not set
# CONFIG_USB_SERIAL_CYBERJACK is not set
# CONFIG_USB_SERIAL_XIRCOM is not set
# CONFIG_USB_SERIAL_OPTION is not set
# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
# CONFIG_USB_SERIAL_DEBUG is not set
#
@@ -1329,6 +1345,10 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1366,6 +1386,7 @@ CONFIG_RTC_DRV_RS5C372=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1417,6 +1438,7 @@ CONFIG_XFS_FS=m
# CONFIG_XFS_RT is not set
# CONFIG_XFS_DEBUG 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
@@ -1458,10 +1480,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1471,6 +1490,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1561,6 +1581,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1614,6 +1635,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1623,6 +1645,8 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1631,11 +1655,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1662,11 +1688,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 045f1b008ce5..8b244003b9e1 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -866,8 +866,8 @@ CONFIG_I2C_AMD8111=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/powerpc/configs/mgcoge_defconfig b/arch/powerpc/configs/mgcoge_defconfig
index 8d3c62324009..c58c38d5b7a6 100644
--- a/arch/powerpc/configs/mgcoge_defconfig
+++ b/arch/powerpc/configs/mgcoge_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:38 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:30 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -89,6 +89,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -111,7 +112,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -122,13 +122,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
#
@@ -144,6 +142,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -190,6 +192,7 @@ CONFIG_PPC_MPC106=y
CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -215,6 +218,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_FLATMEM=y
@@ -222,12 +226,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -253,6 +259,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -275,6 +282,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -337,6 +345,7 @@ CONFIG_NETFILTER_ADVANCED=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -351,8 +360,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
#
@@ -451,6 +461,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -522,6 +538,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -558,6 +577,10 @@ CONFIG_FS_ENET_HAS_SCC=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_PPP is not set
@@ -601,6 +624,7 @@ CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_BRIQ_PANEL is not set
@@ -621,6 +645,11 @@ CONFIG_GPIOLIB=y
# CONFIG_DEBUG_GPIO is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
@@ -638,11 +667,11 @@ CONFIG_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -652,14 +681,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -753,10 +775,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HFSPLUS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
@@ -768,6 +787,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -857,6 +877,7 @@ CONFIG_NLS_UTF8=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -905,6 +926,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -914,6 +936,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -922,10 +946,12 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -953,11 +979,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
diff --git a/arch/powerpc/configs/mgsuvd_defconfig b/arch/powerpc/configs/mgsuvd_defconfig
index fbaa67f7b0ef..297b5d5042be 100644
--- a/arch/powerpc/configs/mgsuvd_defconfig
+++ b/arch/powerpc/configs/mgsuvd_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:39 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:32 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_PPC_8xx=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_8xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -69,12 +70,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -106,7 +107,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -117,13 +117,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -140,6 +138,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -186,6 +188,7 @@ CONFIG_UCODE_PATCH=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -209,6 +212,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -223,12 +227,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -269,6 +275,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -325,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -340,8 +348,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -435,6 +444,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -489,6 +504,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -514,6 +532,10 @@ CONFIG_FS_ENET_HAS_SCC=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -555,7 +577,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -574,11 +598,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -588,14 +612,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -659,6 +676,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -692,10 +710,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -715,6 +730,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -771,6 +787,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -802,6 +819,8 @@ CONFIG_DEBUG_FS=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -809,6 +828,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_VIRQ_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -827,6 +847,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 15c5604d0b26..81afc8b373d7 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Thu Nov 13 02:09:07 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 21:40:44 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -72,10 +72,19 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -108,7 +117,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -119,7 +127,6 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -127,11 +134,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -147,7 +152,6 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
CONFIG_FREEZER=y
#
@@ -192,7 +196,7 @@ CONFIG_RTAS_PROC=y
CONFIG_PPC_BESTCOMM=y
CONFIG_PPC_BESTCOMM_ATA=y
CONFIG_PPC_BESTCOMM_FEC=y
-CONFIG_PPC_BESTCOMM_GEN_BD=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -220,6 +224,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -231,12 +236,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -264,6 +271,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -286,6 +294,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -342,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -354,6 +364,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -376,6 +387,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_OF_PARTS is not set
@@ -447,6 +459,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -474,13 +492,19 @@ CONFIG_BLK_DEV_RAM_SIZE=32768
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -539,6 +563,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -659,6 +685,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -693,6 +722,10 @@ CONFIG_FEC_MPC52xx_MDIO=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -774,9 +807,11 @@ CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_HVC_RTAS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -844,8 +879,6 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -874,6 +907,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -894,6 +928,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -953,10 +988,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -1051,7 +1088,7 @@ CONFIG_LCD_CLASS_DEVICE=m
# CONFIG_LCD_ILI9320 is not set
# CONFIG_LCD_PLATFORM is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_CORGI is not set
+CONFIG_BACKLIGHT_GENERIC=y
#
# Display device support
@@ -1093,21 +1130,22 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
# CONFIG_HID_APPLE is not set
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
# CONFIG_HID_CHICONY is not set
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
# CONFIG_HID_GYRATION is not set
# CONFIG_HID_LOGITECH is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
# CONFIG_HID_PANTHERLORD is not set
# CONFIG_HID_PETALYNX is not set
# 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_TOPSEED is not set
# CONFIG_THRUSTMASTER_FF is not set
# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
@@ -1137,6 +1175,7 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1164,18 +1203,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1222,6 +1260,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1243,7 +1285,6 @@ CONFIG_NEW_LEDS=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1264,6 +1305,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1300,10 +1342,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1323,6 +1362,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1403,6 +1443,7 @@ CONFIG_NLS_ISO8859_1=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1454,6 +1495,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1462,6 +1504,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1470,11 +1514,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1501,11 +1547,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
index f80b1ca43afb..38712e861c46 100644
--- a/arch/powerpc/configs/mpc7448_hpc2_defconfig
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:40 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:33 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -73,12 +73,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -112,7 +112,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -122,13 +121,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -145,6 +142,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -184,6 +185,7 @@ CONFIG_MPIC_WEIRD=y
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -211,6 +213,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -222,12 +225,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -249,6 +254,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -271,6 +277,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -327,6 +334,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -342,8 +350,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -388,6 +397,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -429,6 +439,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -445,6 +456,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -563,6 +576,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -586,7 +602,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -600,6 +615,7 @@ CONFIG_8139TOO=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -630,6 +646,7 @@ CONFIG_TSI108_ETH=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -652,6 +669,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -722,8 +743,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -760,11 +783,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -774,14 +797,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -837,9 +853,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -870,7 +890,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -904,10 +926,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -916,6 +935,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -970,6 +990,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1003,6 +1024,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1010,6 +1033,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1028,6 +1052,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/mpc8272_ads_defconfig b/arch/powerpc/configs/mpc8272_ads_defconfig
index c8f5dec1b696..d85a43cb821f 100644
--- a/arch/powerpc/configs/mpc8272_ads_defconfig
+++ b/arch/powerpc/configs/mpc8272_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:41 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:35 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -86,6 +86,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -108,7 +109,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -119,13 +119,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
#
@@ -141,6 +139,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -183,6 +185,7 @@ CONFIG_PQ2_ADS_PCI_PIC=y
CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -209,6 +212,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_FLATMEM=y
@@ -216,12 +220,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -246,6 +252,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -268,6 +275,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -349,6 +357,7 @@ CONFIG_NETFILTER_ADVANCED=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -363,8 +372,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
#
@@ -459,6 +469,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -526,9 +542,12 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
-# CONFIG_MDIO_OF_GPIO is not set
+# CONFIG_MDIO_GPIO is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
@@ -573,6 +592,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -595,6 +615,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
CONFIG_PPP=y
@@ -690,6 +714,7 @@ CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -708,6 +733,11 @@ CONFIG_GPIOLIB=y
# CONFIG_DEBUG_GPIO is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
@@ -725,11 +755,11 @@ CONFIG_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -739,14 +769,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -843,13 +866,11 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HFSPLUS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -940,6 +961,7 @@ CONFIG_NLS_UTF8=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -991,6 +1013,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1000,6 +1023,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1008,10 +1033,12 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1038,11 +1065,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
index d582014b0a38..45f03cad8db6 100644
--- a/arch/powerpc/configs/mpc83xx_defconfig
+++ b/arch/powerpc/configs/mpc83xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:42 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:36 2009
#
# CONFIG_PPC64 is not set
@@ -45,7 +45,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -77,12 +77,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -115,7 +115,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -126,7 +125,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -134,11 +132,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -155,6 +151,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -205,6 +205,8 @@ CONFIG_QUICC_ENGINE=y
CONFIG_QE_GPIO=y
# CONFIG_FSL_ULI1575 is not set
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
#
# Kernel options
@@ -232,6 +234,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -243,12 +246,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -275,6 +280,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -297,6 +303,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -353,6 +360,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -368,8 +376,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -390,6 +399,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_OF_PARTS=y
@@ -472,6 +482,12 @@ CONFIG_MTD_NAND_FSL_ELBC=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -503,8 +519,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -547,6 +565,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -563,6 +582,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -682,6 +703,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
CONFIG_ICPLUS_PHY=y
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -722,7 +746,6 @@ CONFIG_NETDEV_1000=y
CONFIG_GIANFAR=y
CONFIG_UCC_GETH=y
# CONFIG_UGETH_MAGIC_PACKET is not set
-# CONFIG_UGETH_FILTERING is not set
# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
@@ -731,6 +754,7 @@ CONFIG_UCC_GETH=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -755,6 +779,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -833,8 +861,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
# CONFIG_SERIAL_QE is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -902,16 +932,14 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -923,6 +951,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -949,8 +982,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -971,6 +1006,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -1016,11 +1052,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1029,18 +1065,14 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1093,11 +1125,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1105,12 +1135,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1143,6 +1176,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
@@ -1161,11 +1195,11 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_LIBUSUAL is not set
@@ -1206,6 +1240,11 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1237,6 +1276,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -1270,10 +1310,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1283,6 +1320,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1342,6 +1380,7 @@ CONFIG_UCC=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1373,6 +1412,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1380,6 +1421,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1398,11 +1440,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index c87b53abc617..fb08819d7cc4 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:43 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:37 2009
#
# CONFIG_PPC64 is not set
@@ -21,7 +21,9 @@ CONFIG_FSL_BOOKE=y
CONFIG_FSL_EMB_PERFMON=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
+# CONFIG_SMP is not set
CONFIG_PPC32=y
CONFIG_WORD_SIZE=32
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
@@ -46,7 +48,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -79,12 +81,12 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -97,6 +99,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -119,7 +122,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -131,7 +133,6 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -139,11 +140,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -160,6 +159,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -202,6 +205,7 @@ CONFIG_CPM2=y
CONFIG_FSL_ULI1575=y
CONFIG_CPM=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -240,12 +244,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -271,6 +277,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -294,6 +301,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -382,6 +390,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -398,8 +407,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -449,8 +459,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -494,6 +506,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -510,6 +523,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -629,6 +644,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -675,6 +693,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -699,6 +718,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -792,8 +815,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_OF_PLATFORM is not set
# CONFIG_SERIAL_QE is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
@@ -860,13 +885,12 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -881,6 +905,11 @@ CONFIG_GPIOLIB=y
# CONFIG_GPIO_SYSFS is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
# CONFIG_GPIO_MAX732X is not set
@@ -901,11 +930,11 @@ CONFIG_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -915,18 +944,14 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_UCB1400_CORE is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -953,6 +978,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -998,6 +1024,12 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
# DVB-S (satellite) frontends
#
# CONFIG_DVB_CX24110 is not set
@@ -1009,8 +1041,10 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_CX24116 is not set
@@ -1051,11 +1085,17 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3304 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_AU8522 is not set
# CONFIG_DVB_S5H1411 is not set
#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
# Digital terrestrial only tuners/PLL
#
# CONFIG_DVB_PLL is not set
@@ -1108,6 +1148,7 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1210,11 +1251,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1222,12 +1261,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1260,6 +1302,7 @@ CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1286,18 +1329,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1345,6 +1387,11 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1389,6 +1436,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1448,7 +1496,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -1490,10 +1540,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=m
@@ -1504,6 +1551,7 @@ CONFIG_BEFS_FS=m
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1605,6 +1653,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1656,6 +1705,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1665,6 +1715,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1673,11 +1725,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1704,11 +1758,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1742,7 +1800,7 @@ CONFIG_CRYPTO_HMAC=y
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/powerpc/configs/mpc866_ads_defconfig b/arch/powerpc/configs/mpc866_ads_defconfig
index 8272b1ac71f9..1793d08e9c01 100644
--- a/arch/powerpc/configs/mpc866_ads_defconfig
+++ b/arch/powerpc/configs/mpc866_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:43 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:38 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_PPC_8xx=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_8xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -69,12 +70,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -106,7 +107,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -117,13 +117,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -140,6 +138,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -185,6 +187,7 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -209,6 +212,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -223,12 +227,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
@@ -269,6 +275,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -325,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -340,8 +348,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -372,6 +381,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -407,6 +417,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -433,6 +446,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -518,7 +535,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -549,11 +568,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -563,14 +582,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -623,9 +635,13 @@ CONFIG_USB_SUPPORT=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -657,6 +673,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_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
@@ -690,10 +707,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -702,6 +716,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -758,6 +773,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -790,6 +806,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -797,6 +815,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -814,6 +833,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/mpc86xx_defconfig b/arch/powerpc/configs/mpc86xx_defconfig
index 1736bbc281ec..adc756e1f252 100644
--- a/arch/powerpc/configs/mpc86xx_defconfig
+++ b/arch/powerpc/configs/mpc86xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:44 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:39 2009
#
# CONFIG_PPC64 is not set
@@ -41,11 +41,12 @@ CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
# CONFIG_ARCH_NO_VIRT_TO_BUS is not set
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -78,12 +79,12 @@ CONFIG_AUDIT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -96,6 +97,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -118,7 +120,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -130,7 +131,6 @@ CONFIG_USE_GENERIC_SMP_HELPERS=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -138,12 +138,10 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -160,6 +158,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -199,6 +201,7 @@ CONFIG_PPC_I8259=y
# CONFIG_QUICC_ENGINE is not set
CONFIG_FSL_ULI1575=y
# CONFIG_MPC8xxx_GPIO is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -226,6 +229,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
# CONFIG_IRQ_ALL_CPUS is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
@@ -238,12 +242,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -269,6 +275,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
CONFIG_HAS_RAPIDIO=y
@@ -292,6 +299,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -380,6 +388,7 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -396,8 +405,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -420,6 +430,7 @@ CONFIG_EXTRA_FIRMWARE=""
# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
CONFIG_OF_I2C=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
@@ -446,8 +457,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -491,6 +504,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -507,6 +521,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -626,6 +642,9 @@ CONFIG_VITESSE_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -671,6 +690,7 @@ CONFIG_GIANFAR=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -695,6 +715,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -786,8 +810,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
@@ -826,6 +852,7 @@ CONFIG_I2C_HELPER_AUTO=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
+# CONFIG_I2C_GPIO is not set
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SIMTEC is not set
@@ -852,8 +879,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-CONFIG_SENSORS_EEPROM=y
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -866,18 +893,42 @@ CONFIG_SENSORS_EEPROM=y
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -886,18 +937,15 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -924,6 +972,7 @@ CONFIG_MEDIA_TUNER_TEA5767=m
CONFIG_MEDIA_TUNER_MT20XX=m
CONFIG_MEDIA_TUNER_XC2028=m
CONFIG_MEDIA_TUNER_XC5000=m
+# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -969,6 +1018,12 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_FE_CUSTOMISE is not set
#
+# Multistandard (satellite) frontends
+#
+# CONFIG_DVB_STB0899 is not set
+# CONFIG_DVB_STB6100 is not set
+
+#
# DVB-S (satellite) frontends
#
# CONFIG_DVB_CX24110 is not set
@@ -980,8 +1035,10 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA10086 is not set
+# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
+# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_CX24116 is not set
@@ -1022,11 +1079,17 @@ CONFIG_DVB_CAPTURE_DRIVERS=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LGDT330X is not set
+# CONFIG_DVB_LGDT3304 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_AU8522 is not set
# CONFIG_DVB_S5H1411 is not set
#
+# ISDB-T (terrestrial) frontends
+#
+# CONFIG_DVB_S921 is not set
+
+#
# Digital terrestrial only tuners/PLL
#
# CONFIG_DVB_PLL is not set
@@ -1079,6 +1142,7 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1181,11 +1245,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1193,12 +1255,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1231,6 +1296,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1256,18 +1322,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1315,6 +1380,11 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1352,6 +1422,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1398,7 +1469,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -1440,10 +1513,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not set
CONFIG_AFFS_FS=m
@@ -1454,6 +1524,7 @@ CONFIG_BEFS_FS=m
CONFIG_BFS_FS=m
CONFIG_EFS_FS=m
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
CONFIG_VXFS_FS=m
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1555,6 +1626,7 @@ CONFIG_NLS_UTF8=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1606,6 +1678,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1615,6 +1688,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1623,11 +1698,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1654,11 +1731,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1692,7 +1773,7 @@ CONFIG_CRYPTO_HMAC=y
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
diff --git a/arch/powerpc/configs/mpc885_ads_defconfig b/arch/powerpc/configs/mpc885_ads_defconfig
index a4283b6a43d2..4b76321c0ec4 100644
--- a/arch/powerpc/configs/mpc885_ads_defconfig
+++ b/arch/powerpc/configs/mpc885_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:46 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:41 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_PPC_8xx=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_8xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -40,7 +41,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -70,12 +71,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -108,7 +109,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -118,13 +118,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -141,6 +139,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -193,6 +195,7 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -212,12 +215,12 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
CONFIG_8XX_MINIMAL_FPEMU=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -232,12 +235,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -279,6 +284,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -330,6 +336,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -345,8 +352,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -439,6 +447,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -481,6 +495,9 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -506,6 +523,10 @@ CONFIG_FS_ENET_MDIO_FEC=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -547,7 +568,9 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
@@ -566,11 +589,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -580,14 +603,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -641,6 +657,7 @@ CONFIG_DAB=y
CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
@@ -673,10 +690,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -686,6 +700,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -741,6 +756,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Library routines
#
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -788,6 +804,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -796,6 +813,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -804,11 +823,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index 199e5f59d7a6..4f8681cc8d77 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -984,7 +984,7 @@ CONFIG_I2C_PASEMI=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_SENSORS_EEPROM=y
+CONFIG_EEPROM_LEGACY=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index de9b121820a6..5339bb44cce9 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1232,8 +1232,8 @@ CONFIG_I2C_POWERMAC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/powerpc/configs/ppc40x_defconfig b/arch/powerpc/configs/ppc40x_defconfig
index 4256e2c4534b..326205cabf77 100644
--- a/arch/powerpc/configs/ppc40x_defconfig
+++ b/arch/powerpc/configs/ppc40x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Fri Nov 14 09:54:44 2008
+# Linux kernel version: 2.6.29-rc2
+# Fri Jan 23 08:44:03 2009
#
# CONFIG_PPC64 is not set
@@ -15,6 +15,7 @@ CONFIG_40x=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_4xx=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -41,7 +42,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -72,12 +73,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -90,6 +91,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -112,7 +114,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -123,7 +124,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -131,11 +131,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -152,6 +150,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
CONFIG_PPC4xx_PCI_EXPRESS=y
@@ -192,6 +194,7 @@ CONFIG_IBM405_ERR51=y
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_OF_RTC=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -215,6 +218,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -229,12 +233,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -258,6 +264,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -282,6 +289,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -355,6 +363,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -370,8 +379,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -397,6 +407,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
@@ -469,6 +480,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
CONFIG_MTD_UBI=m
@@ -593,6 +610,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -615,6 +633,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -674,9 +696,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -745,13 +770,12 @@ CONFIG_I2C_IBM_IIC=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -803,9 +827,11 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -904,9 +930,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -918,7 +948,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -939,7 +968,9 @@ CONFIG_FS_MBCACHE=m
# 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
@@ -976,10 +1007,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1005,6 +1033,7 @@ CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_UBIFS_FS_DEBUG is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1084,6 +1113,7 @@ CONFIG_NLS_ISO8859_1=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=m
# CONFIG_CRC_T10DIF is not set
@@ -1137,6 +1167,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1146,6 +1177,8 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1154,11 +1187,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1185,11 +1220,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig
index 034a1fbdc887..5e6d55f006bb 100644
--- a/arch/powerpc/configs/ppc44x_defconfig
+++ b/arch/powerpc/configs/ppc44x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Fri Nov 14 10:06:19 2008
+# Linux kernel version: 2.6.29-rc2
+# Fri Jan 23 08:43:46 2009
#
# CONFIG_PPC64 is not set
@@ -19,6 +19,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_PPC32=y
@@ -45,7 +46,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -76,12 +77,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -94,6 +95,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -116,7 +118,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -127,7 +128,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -135,11 +135,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -157,6 +155,10 @@ CONFIG_DEFAULT_AS=y
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_PREEMPT_NOTIFIERS=y
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
CONFIG_PPC4xx_PCI_EXPRESS=y
@@ -204,6 +206,7 @@ CONFIG_XILINX_VIRTEX_5_FXT=y
# CONFIG_CPU_FREQ is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_OF_RTC=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -227,6 +230,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_MATH_EMULATION=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -241,12 +245,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-CONFIG_RESOURCES_64BIT=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -269,6 +275,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -293,6 +300,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -354,10 +362,12 @@ CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IP_SCTP is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
+CONFIG_STP=m
CONFIG_BRIDGE=m
# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
+CONFIG_LLC=m
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
@@ -366,6 +376,7 @@ CONFIG_BRIDGE=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -378,6 +389,7 @@ CONFIG_BRIDGE=m
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not set
# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -403,6 +415,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_OF_PARTS=y
@@ -474,6 +487,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
CONFIG_MTD_UBI=m
@@ -631,6 +650,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -655,6 +675,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -722,9 +746,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -794,13 +821,12 @@ CONFIG_I2C_IBM_IIC=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
@@ -853,9 +879,11 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
#
@@ -972,6 +1000,7 @@ CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=m
@@ -1012,7 +1041,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -1058,6 +1086,11 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1069,7 +1102,6 @@ CONFIG_USB_STORAGE=m
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1089,7 +1121,9 @@ CONFIG_FS_MBCACHE=m
# 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
@@ -1126,10 +1160,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1155,6 +1186,7 @@ CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_UBIFS_FS_DEBUG is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1234,6 +1266,7 @@ CONFIG_NLS_ISO8859_1=m
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=m
CONFIG_CRC_T10DIF=m
@@ -1287,6 +1320,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1296,6 +1330,8 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1304,11 +1340,13 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1333,11 +1371,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1419,5 +1461,6 @@ CONFIG_CRYPTO_LZO=m
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=y
CONFIG_KVM_440=y
+# CONFIG_KVM_EXIT_TIMING is not set
# CONFIG_VIRTIO_PCI is not set
# CONFIG_VIRTIO_BALLOON is not set
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 069ae1bbac29..88c6295b76c1 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -211,11 +211,28 @@ CONFIG_PPC_PASEMI=y
CONFIG_PPC_PASEMI_IOMMU=y
# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set
CONFIG_PPC_PASEMI_MDIO=y
-# CONFIG_PPC_PS3 is not set
+CONFIG_PPC_PS3=y
+
+#
+# PS3 Platform Options
+#
+# CONFIG_PS3_ADVANCED is not set
+CONFIG_PS3_HTAB_SIZE=20
+# CONFIG_PS3_DYNAMIC_DMA is not set
+CONFIG_PS3_VUART=y
+CONFIG_PS3_PS3AV=y
+CONFIG_PS3_SYS_MANAGER=y
+CONFIG_PS3_STORAGE=m
+CONFIG_PS3_DISK=m
+CONFIG_PS3_ROM=m
+CONFIG_PS3_FLASH=m
+CONFIG_PS3_LPM=m
CONFIG_PPC_CELL=y
+CONFIG_PPC_CELL_COMMON=y
CONFIG_PPC_CELL_NATIVE=y
CONFIG_PPC_IBM_CELL_BLADE=y
CONFIG_PPC_CELLEB=y
+CONFIG_PPC_CELL_QPACE=y
#
# Cell Broadband Engine options
@@ -981,6 +998,9 @@ CONFIG_E1000=y
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
CONFIG_SPIDER_NET=m
+CONFIG_GELIC_NET=m
+CONFIG_GELIC_WIRELESS=y
+# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
@@ -1241,8 +1261,8 @@ CONFIG_I2C_PASEMI=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -1370,6 +1390,8 @@ CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_PM3 is not set
# CONFIG_FB_CARMINE is not set
CONFIG_FB_IBM_GXT4500=y
+CONFIG_FB_PS3=m
+CONFIG_FB_PS3_DEFAULT_SIZE_M=9
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
@@ -1492,6 +1514,8 @@ CONFIG_SND_PCI=y
CONFIG_SND_PPC=y
CONFIG_SND_POWERMAC=m
CONFIG_SND_POWERMAC_AUTO_DRC=y
+CONFIG_SND_PS3=m
+CONFIG_SND_PS3_DEFAULT_START_DELAY=2000
CONFIG_SND_AOA=m
CONFIG_SND_AOA_FABRIC_LAYOUT=m
CONFIG_SND_AOA_ONYX=m
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 01f05ec5abf3..7d044dfd9236 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -1801,8 +1801,8 @@ CONFIG_I2C_STUB=m
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-CONFIG_AT24=m
-CONFIG_SENSORS_EEPROM=m
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_LEGACY=m
CONFIG_SENSORS_PCF8574=m
CONFIG_PCF8575=m
CONFIG_SENSORS_PCA9539=m
diff --git a/arch/powerpc/configs/pq2fads_defconfig b/arch/powerpc/configs/pq2fads_defconfig
index 228099d77c3b..fdded96633a1 100644
--- a/arch/powerpc/configs/pq2fads_defconfig
+++ b/arch/powerpc/configs/pq2fads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:47 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:42 2009
#
# CONFIG_PPC64 is not set
@@ -44,7 +44,7 @@ CONFIG_GENERIC_GPIO=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -87,6 +87,7 @@ CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -109,7 +110,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -120,13 +120,11 @@ CONFIG_HAVE_CLK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
#
@@ -142,6 +140,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -183,6 +185,7 @@ CONFIG_PQ2_ADS_PCI_PIC=y
CONFIG_CPM2=y
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -209,6 +212,7 @@ CONFIG_BINFMT_MISC=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_FLATMEM=y
@@ -216,12 +220,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -247,6 +253,7 @@ CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -269,6 +276,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -350,6 +358,7 @@ CONFIG_NETFILTER_ADVANCED=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -364,8 +373,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
#
@@ -460,6 +470,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -520,6 +536,7 @@ CONFIG_IDE_PROC_FS=y
# 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
@@ -577,9 +594,12 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
-# CONFIG_MDIO_OF_GPIO is not set
+# CONFIG_MDIO_GPIO is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
@@ -624,6 +644,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -646,6 +667,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
CONFIG_PPP=y
@@ -743,6 +768,7 @@ CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -761,6 +787,11 @@ CONFIG_GPIOLIB=y
# CONFIG_DEBUG_GPIO is not set
#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
# I2C GPIO expanders:
#
@@ -778,11 +809,11 @@ CONFIG_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -792,14 +823,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-
-#
-# Voltage and Current regulators
-#
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -844,7 +868,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB_GADGET_MUSB_HDRC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG is not set
@@ -859,10 +883,12 @@ CONFIG_USB_GADGET_SELECTED=y
# CONFIG_USB_GADGET_PXA25X is not set
# CONFIG_USB_GADGET_PXA27X is not set
# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
CONFIG_USB_GADGET_M66592=y
CONFIG_USB_M66592=y
# CONFIG_USB_GADGET_AMD5536UDC is not set
# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
# CONFIG_USB_GADGET_NET2280 is not set
# CONFIG_USB_GADGET_GOKU is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
@@ -876,6 +902,11 @@ CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_MIDI_GADGET is not set
# CONFIG_USB_G_PRINTER is not set
# CONFIG_USB_CDC_COMPOSITE is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -938,13 +969,11 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HFSPLUS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1035,6 +1064,7 @@ CONFIG_NLS_UTF8=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
@@ -1086,6 +1116,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1095,6 +1126,8 @@ CONFIG_DEBUG_INFO=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1103,10 +1136,12 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
@@ -1133,11 +1168,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig
index 6046dc0cbd82..e971db171138 100644
--- a/arch/powerpc/configs/prpmc2800_defconfig
+++ b/arch/powerpc/configs/prpmc2800_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:48 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:44 2009
#
# CONFIG_PPC64 is not set
@@ -45,7 +45,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -75,12 +75,12 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
# CONFIG_FAIR_GROUP_SCHED is not set
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -118,7 +118,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -128,13 +127,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -151,6 +148,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -190,6 +191,7 @@ CONFIG_MV64X60=y
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -213,10 +215,12 @@ CONFIG_BINFMT_ELF=y
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
# CONFIG_IOMMU_HELPER is not set
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -228,12 +232,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
@@ -255,6 +261,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -279,6 +286,8 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -335,6 +344,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -350,8 +360,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -445,6 +456,12 @@ CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -475,8 +492,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -489,7 +508,6 @@ CONFIG_IDE_GD_ATA=y
# CONFIG_IDE_GD_ATAPI is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -519,6 +537,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -571,6 +590,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -587,6 +607,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -707,6 +729,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -730,7 +755,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
CONFIG_E100=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -744,6 +768,7 @@ CONFIG_8139TOO=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -773,6 +798,7 @@ CONFIG_MV643XX_ETH=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -797,6 +823,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -877,8 +907,10 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
@@ -943,8 +975,8 @@ CONFIG_I2C_MV64XXX=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -970,8 +1002,10 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
@@ -992,6 +1026,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
@@ -1018,11 +1053,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1031,18 +1066,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -1101,11 +1131,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1113,12 +1141,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
CONFIG_THRUSTMASTER_FF=y
CONFIG_ZEROPLUS_FF=y
CONFIG_USB_SUPPORT=y
@@ -1148,6 +1179,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -1170,11 +1202,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_LIBUSUAL is not set
@@ -1216,6 +1248,10 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1253,6 +1289,7 @@ CONFIG_RTC_DRV_MAX6900=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1299,7 +1336,9 @@ CONFIG_FS_MBCACHE=y
# 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
@@ -1333,10 +1372,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1346,6 +1382,7 @@ CONFIG_TMPFS=y
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1400,6 +1437,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1433,6 +1471,8 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1440,6 +1480,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1458,6 +1499,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 1e520ab65118..61b100849715 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1055,8 +1055,8 @@ CONFIG_I2C_ALGOBIT=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/powerpc/configs/storcenter_defconfig b/arch/powerpc/configs/storcenter_defconfig
index b3f5671972a9..86512c8790d1 100644
--- a/arch/powerpc/configs/storcenter_defconfig
+++ b/arch/powerpc/configs/storcenter_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc3
-# Sat Nov 8 12:39:48 2008
+# Linux kernel version: 2.6.29-rc2
+# Mon Jan 26 15:35:46 2009
#
# CONFIG_PPC64 is not set
@@ -43,7 +43,7 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
CONFIG_OF=y
@@ -73,12 +73,12 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
@@ -110,7 +110,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
@@ -120,7 +119,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -128,11 +126,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -149,6 +145,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -191,6 +191,7 @@ CONFIG_MPIC=y
# CONFIG_TAU is not set
# CONFIG_QUICC_ENGINE is not set
# CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
#
# Kernel options
@@ -217,6 +218,7 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -228,12 +230,14 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=11
CONFIG_PROC_DEVICETREE=y
CONFIG_CMDLINE_BOOL=y
@@ -257,6 +261,7 @@ CONFIG_PCI_SYSCALL=y
CONFIG_ARCH_SUPPORTS_MSI=y
# CONFIG_PCI_MSI is not set
# CONFIG_PCI_LEGACY is not set
+# CONFIG_PCI_STUB is not set
# CONFIG_PCCARD is not set
# CONFIG_HOTPLUG_PCI is not set
# CONFIG_HAS_RAPIDIO is not set
@@ -279,6 +284,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=m
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -330,6 +336,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -345,8 +352,9 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -367,6 +375,7 @@ CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_OF_PARTS is not set
@@ -416,9 +425,7 @@ CONFIG_MTD_CFI_UTIL=y
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0xFF800000
-CONFIG_MTD_PHYSMAP_LEN=0x00800000
-CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
@@ -442,6 +449,12 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_ONENAND is not set
#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_QINFO_PROBE is not set
+
+#
# UBI - Unsorted block images
#
# CONFIG_MTD_UBI is not set
@@ -468,8 +481,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -483,7 +498,6 @@ CONFIG_IDE_GD_ATA=y
# CONFIG_IDE_GD_ATAPI is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -512,6 +526,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# 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
@@ -582,6 +597,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
@@ -672,6 +689,10 @@ CONFIG_R8169=y
# CONFIG_IWLWIFI_LEDS is not set
#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
# USB Network Adapters
#
# CONFIG_USB_CATC is not set
@@ -729,8 +750,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
CONFIG_NVRAM=y
@@ -795,8 +818,8 @@ CONFIG_I2C_MPC=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -816,11 +839,11 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -829,18 +852,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_MFD_PCF50633 is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
#
# Multimedia devices
@@ -903,6 +921,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_EHCI_FSL is not set
CONFIG_USB_EHCI_HCD_PPC_OF=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
@@ -925,18 +944,17 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
@@ -983,6 +1001,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1020,6 +1042,7 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1070,7 +1093,9 @@ CONFIG_XFS_FS=m
# CONFIG_XFS_POSIX_ACL is not set
# CONFIG_XFS_RT is not set
# CONFIG_XFS_DEBUG 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
@@ -1104,10 +1129,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1127,6 +1149,7 @@ CONFIG_JFFS2_ZLIB=y
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
@@ -1204,6 +1227,7 @@ CONFIG_NLS_UTF8=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
@@ -1239,6 +1263,8 @@ CONFIG_FRAME_WARN=1024
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
@@ -1246,6 +1272,7 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_IRQSTACKS is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index 499be5bdd6fa..b401950f5259 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -5,7 +5,7 @@
* PowerPC atomic operations
*/
-typedef struct { int counter; } atomic_t;
+#include <linux/types.h>
#ifdef __KERNEL__
#include <linux/compiler.h>
@@ -251,8 +251,6 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
#ifdef __powerpc64__
-typedef struct { long counter; } atomic64_t;
-
#define ATOMIC64_INIT(i) { (i) }
static __inline__ long atomic64_read(const atomic64_t *v)
diff --git a/arch/powerpc/include/asm/byteorder.h b/arch/powerpc/include/asm/byteorder.h
index d5de325472e9..aa6cc4fac965 100644
--- a/arch/powerpc/include/asm/byteorder.h
+++ b/arch/powerpc/include/asm/byteorder.h
@@ -7,87 +7,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#define __BIG_ENDIAN
-
-#ifdef __GNUC__
-#ifdef __KERNEL__
-
-static __inline__ __u16 ld_le16(const volatile __u16 *addr)
-{
- __u16 val;
-
- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
- return val;
-}
-#define __arch_swab16p ld_le16
-
-static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
-{
- __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
-}
-
-static inline void __arch_swab16s(__u16 *addr)
-{
- st_le16(addr, *addr);
-}
-#define __arch_swab16s __arch_swab16s
-
-static __inline__ __u32 ld_le32(const volatile __u32 *addr)
-{
- __u32 val;
-
- __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
- return val;
-}
-#define __arch_swab32p ld_le32
-
-static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
-{
- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
-}
-
-static inline void __arch_swab32s(__u32 *addr)
-{
- st_le32(addr, *addr);
-}
-#define __arch_swab32s __arch_swab32s
-
-static inline __attribute_const__ __u16 __arch_swab16(__u16 value)
-{
- __u16 result;
-
- __asm__("rlwimi %0,%1,8,16,23"
- : "=r" (result)
- : "r" (value), "0" (value >> 8));
- return result;
-}
-#define __arch_swab16 __arch_swab16
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 value)
-{
- __u32 result;
-
- __asm__("rlwimi %0,%1,24,16,23\n\t"
- "rlwimi %0,%1,8,8,15\n\t"
- "rlwimi %0,%1,24,0,7"
- : "=r" (result)
- : "r" (value), "0" (value >> 24));
- return result;
-}
-#define __arch_swab32 __arch_swab32
-
-#endif /* __KERNEL__ */
-
-#ifndef __powerpc64__
-#define __SWAB_64_THRU_32__
-#endif /* __powerpc64__ */
-
-#endif /* __GNUC__ */
-
-#include <linux/byteorder.h>
+#include <linux/byteorder/big_endian.h>
#endif /* _ASM_POWERPC_BYTEORDER_H */
diff --git a/arch/powerpc/include/asm/cell-pmu.h b/arch/powerpc/include/asm/cell-pmu.h
index 8066eede3a0c..b4b7338ad79e 100644
--- a/arch/powerpc/include/asm/cell-pmu.h
+++ b/arch/powerpc/include/asm/cell-pmu.h
@@ -37,9 +37,11 @@
#define CBE_PM_STOP_AT_MAX 0x40000000
#define CBE_PM_TRACE_MODE_GET(pm_control) (((pm_control) >> 28) & 0x3)
#define CBE_PM_TRACE_MODE_SET(mode) (((mode) & 0x3) << 28)
+#define CBE_PM_TRACE_BUF_OVFLW(bit) (((bit) & 0x1) << 17)
#define CBE_PM_COUNT_MODE_SET(count) (((count) & 0x3) << 18)
#define CBE_PM_FREEZE_ALL_CTRS 0x00100000
#define CBE_PM_ENABLE_EXT_TRACE 0x00008000
+#define CBE_PM_SPU_ADDR_TRACE_SET(msk) (((msk) & 0x3) << 9)
/* Macros for the trace_address register. */
#define CBE_PM_TRACE_BUF_FULL 0x00000800
diff --git a/arch/powerpc/include/asm/disassemble.h b/arch/powerpc/include/asm/disassemble.h
new file mode 100644
index 000000000000..9b198d1b3b2b
--- /dev/null
+++ b/arch/powerpc/include/asm/disassemble.h
@@ -0,0 +1,80 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __ASM_PPC_DISASSEMBLE_H__
+#define __ASM_PPC_DISASSEMBLE_H__
+
+#include <linux/types.h>
+
+static inline unsigned int get_op(u32 inst)
+{
+ return inst >> 26;
+}
+
+static inline unsigned int get_xop(u32 inst)
+{
+ return (inst >> 1) & 0x3ff;
+}
+
+static inline unsigned int get_sprn(u32 inst)
+{
+ return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
+}
+
+static inline unsigned int get_dcrn(u32 inst)
+{
+ return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
+}
+
+static inline unsigned int get_rt(u32 inst)
+{
+ return (inst >> 21) & 0x1f;
+}
+
+static inline unsigned int get_rs(u32 inst)
+{
+ return (inst >> 21) & 0x1f;
+}
+
+static inline unsigned int get_ra(u32 inst)
+{
+ return (inst >> 16) & 0x1f;
+}
+
+static inline unsigned int get_rb(u32 inst)
+{
+ return (inst >> 11) & 0x1f;
+}
+
+static inline unsigned int get_rc(u32 inst)
+{
+ return inst & 0x1;
+}
+
+static inline unsigned int get_ws(u32 inst)
+{
+ return (inst >> 11) & 0x1f;
+}
+
+static inline unsigned int get_d(u32 inst)
+{
+ return inst & 0xffff;
+}
+
+#endif /* __ASM_PPC_DISASSEMBLE_H__ */
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index 26f0d0ab27a5..b1dafb6a9743 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -18,6 +18,12 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep);
/*
+ * The version of vma_mmu_pagesize() in arch/powerpc/mm/hugetlbpage.c needs
+ * to override the version in mm/hugetlb.c
+ */
+#define vma_mmu_pagesize vma_mmu_pagesize
+
+/*
* If the arch doesn't supply something else, assume that hugepage
* size aligned regions are ok without further preparation.
*/
diff --git a/arch/powerpc/include/asm/ioctls.h b/arch/powerpc/include/asm/ioctls.h
index 279a6229584b..1842186d872c 100644
--- a/arch/powerpc/include/asm/ioctls.h
+++ b/arch/powerpc/include/asm/ioctls.h
@@ -89,6 +89,8 @@
#define TIOCSBRK 0x5427 /* BSD compatibility */
#define TIOCCBRK 0x5428 /* BSD compatibility */
#define TIOCGSID 0x5429 /* Return the session ID of FD */
+#define TIOCGRS485 0x542e
+#define TIOCSRS485 0x542f
#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 6dbffc981702..7e06b43720d3 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -48,63 +48,8 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
{
if (oldregs)
memcpy(newregs, oldregs, sizeof(*newregs));
-#ifdef __powerpc64__
- else {
- /* FIXME Merge this with xmon_save_regs ?? */
- unsigned long tmp1, tmp2;
- __asm__ __volatile__ (
- "std 0,0(%2)\n"
- "std 1,8(%2)\n"
- "std 2,16(%2)\n"
- "std 3,24(%2)\n"
- "std 4,32(%2)\n"
- "std 5,40(%2)\n"
- "std 6,48(%2)\n"
- "std 7,56(%2)\n"
- "std 8,64(%2)\n"
- "std 9,72(%2)\n"
- "std 10,80(%2)\n"
- "std 11,88(%2)\n"
- "std 12,96(%2)\n"
- "std 13,104(%2)\n"
- "std 14,112(%2)\n"
- "std 15,120(%2)\n"
- "std 16,128(%2)\n"
- "std 17,136(%2)\n"
- "std 18,144(%2)\n"
- "std 19,152(%2)\n"
- "std 20,160(%2)\n"
- "std 21,168(%2)\n"
- "std 22,176(%2)\n"
- "std 23,184(%2)\n"
- "std 24,192(%2)\n"
- "std 25,200(%2)\n"
- "std 26,208(%2)\n"
- "std 27,216(%2)\n"
- "std 28,224(%2)\n"
- "std 29,232(%2)\n"
- "std 30,240(%2)\n"
- "std 31,248(%2)\n"
- "mfmsr %0\n"
- "std %0, 264(%2)\n"
- "mfctr %0\n"
- "std %0, 280(%2)\n"
- "mflr %0\n"
- "std %0, 288(%2)\n"
- "bl 1f\n"
- "1: mflr %1\n"
- "std %1, 256(%2)\n"
- "mtlr %0\n"
- "mfxer %0\n"
- "std %0, 296(%2)\n"
- : "=&r" (tmp1), "=&r" (tmp2)
- : "b" (newregs)
- : "memory");
- }
-#else
else
ppc_save_regs(newregs);
-#endif /* __powerpc64__ */
}
extern void kexec_smp_wait(void); /* get and clear naca physid, wait for
diff --git a/arch/powerpc/include/asm/kvm_44x.h b/arch/powerpc/include/asm/kvm_44x.h
new file mode 100644
index 000000000000..f49031b632ca
--- /dev/null
+++ b/arch/powerpc/include/asm/kvm_44x.h
@@ -0,0 +1,61 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __ASM_44X_H__
+#define __ASM_44X_H__
+
+#include <linux/kvm_host.h>
+
+#define PPC44x_TLB_SIZE 64
+
+/* If the guest is expecting it, this can be as large as we like; we'd just
+ * need to find some way of advertising it. */
+#define KVM44x_GUEST_TLB_SIZE 64
+
+struct kvmppc_44x_shadow_ref {
+ struct page *page;
+ u16 gtlb_index;
+ u8 writeable;
+ u8 tid;
+};
+
+struct kvmppc_vcpu_44x {
+ /* Unmodified copy of the guest's TLB. */
+ struct kvmppc_44x_tlbe guest_tlb[KVM44x_GUEST_TLB_SIZE];
+
+ /* References to guest pages in the hardware TLB. */
+ struct kvmppc_44x_shadow_ref shadow_refs[PPC44x_TLB_SIZE];
+
+ /* State of the shadow TLB at guest context switch time. */
+ struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE];
+ u8 shadow_tlb_mod[PPC44x_TLB_SIZE];
+
+ struct kvm_vcpu vcpu;
+};
+
+static inline struct kvmppc_vcpu_44x *to_44x(struct kvm_vcpu *vcpu)
+{
+ return container_of(vcpu, struct kvmppc_vcpu_44x, vcpu);
+}
+
+void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid);
+void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu);
+void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu);
+
+#endif /* __ASM_44X_H__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 34b52b7180cd..c1e436fe7738 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -64,27 +64,58 @@ struct kvm_vcpu_stat {
u32 halt_wakeup;
};
-struct tlbe {
+struct kvmppc_44x_tlbe {
u32 tid; /* Only the low 8 bits are used. */
u32 word0;
u32 word1;
u32 word2;
};
-struct kvm_arch {
+enum kvm_exit_types {
+ MMIO_EXITS,
+ DCR_EXITS,
+ SIGNAL_EXITS,
+ ITLB_REAL_MISS_EXITS,
+ ITLB_VIRT_MISS_EXITS,
+ DTLB_REAL_MISS_EXITS,
+ DTLB_VIRT_MISS_EXITS,
+ SYSCALL_EXITS,
+ ISI_EXITS,
+ DSI_EXITS,
+ EMULATED_INST_EXITS,
+ EMULATED_MTMSRWE_EXITS,
+ EMULATED_WRTEE_EXITS,
+ EMULATED_MTSPR_EXITS,
+ EMULATED_MFSPR_EXITS,
+ EMULATED_MTMSR_EXITS,
+ EMULATED_MFMSR_EXITS,
+ EMULATED_TLBSX_EXITS,
+ EMULATED_TLBWE_EXITS,
+ EMULATED_RFI_EXITS,
+ DEC_EXITS,
+ EXT_INTR_EXITS,
+ HALT_WAKEUP,
+ USR_PR_INST,
+ FP_UNAVAIL,
+ DEBUG_EXITS,
+ TIMEINGUEST,
+ __NUMBER_OF_KVM_EXIT_TYPES
};
-struct kvm_vcpu_arch {
- /* Unmodified copy of the guest's TLB. */
- struct tlbe guest_tlb[PPC44x_TLB_SIZE];
- /* TLB that's actually used when the guest is running. */
- struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
- /* Pages which are referenced in the shadow TLB. */
- struct page *shadow_pages[PPC44x_TLB_SIZE];
+/* allow access to big endian 32bit upper/lower parts and 64bit var */
+struct kvmppc_exit_timing {
+ union {
+ u64 tv64;
+ struct {
+ u32 tbu, tbl;
+ } tv32;
+ };
+};
- /* Track which TLB entries we've modified in the current exit. */
- u8 shadow_tlb_mod[PPC44x_TLB_SIZE];
+struct kvm_arch {
+};
+struct kvm_vcpu_arch {
u32 host_stack;
u32 host_pid;
u32 host_dbcr0;
@@ -94,32 +125,32 @@ struct kvm_vcpu_arch {
u32 host_msr;
u64 fpr[32];
- u32 gpr[32];
+ ulong gpr[32];
- u32 pc;
+ ulong pc;
u32 cr;
- u32 ctr;
- u32 lr;
- u32 xer;
+ ulong ctr;
+ ulong lr;
+ ulong xer;
- u32 msr;
+ ulong msr;
u32 mmucr;
- u32 sprg0;
- u32 sprg1;
- u32 sprg2;
- u32 sprg3;
- u32 sprg4;
- u32 sprg5;
- u32 sprg6;
- u32 sprg7;
- u32 srr0;
- u32 srr1;
- u32 csrr0;
- u32 csrr1;
- u32 dsrr0;
- u32 dsrr1;
- u32 dear;
- u32 esr;
+ ulong sprg0;
+ ulong sprg1;
+ ulong sprg2;
+ ulong sprg3;
+ ulong sprg4;
+ ulong sprg5;
+ ulong sprg6;
+ ulong sprg7;
+ ulong srr0;
+ ulong srr1;
+ ulong csrr0;
+ ulong csrr1;
+ ulong dsrr0;
+ ulong dsrr1;
+ ulong dear;
+ ulong esr;
u32 dec;
u32 decar;
u32 tbl;
@@ -127,7 +158,7 @@ struct kvm_vcpu_arch {
u32 tcr;
u32 tsr;
u32 ivor[16];
- u32 ivpr;
+ ulong ivpr;
u32 pir;
u32 shadow_pid;
@@ -140,9 +171,22 @@ struct kvm_vcpu_arch {
u32 dbcr0;
u32 dbcr1;
+#ifdef CONFIG_KVM_EXIT_TIMING
+ struct kvmppc_exit_timing timing_exit;
+ struct kvmppc_exit_timing timing_last_enter;
+ u32 last_exit_type;
+ u32 timing_count_type[__NUMBER_OF_KVM_EXIT_TYPES];
+ u64 timing_sum_duration[__NUMBER_OF_KVM_EXIT_TYPES];
+ u64 timing_sum_quad_duration[__NUMBER_OF_KVM_EXIT_TYPES];
+ u64 timing_min_duration[__NUMBER_OF_KVM_EXIT_TYPES];
+ u64 timing_max_duration[__NUMBER_OF_KVM_EXIT_TYPES];
+ u64 timing_last_exit;
+ struct dentry *debugfs_exit_timing;
+#endif
+
u32 last_inst;
- u32 fault_dear;
- u32 fault_esr;
+ ulong fault_dear;
+ ulong fault_esr;
gpa_t paddr_accessed;
u8 io_gpr; /* GPR used as IO source/target */
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index bb62ad876de3..36d2a50a8487 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -29,11 +29,6 @@
#include <linux/kvm_types.h>
#include <linux/kvm_host.h>
-struct kvm_tlb {
- struct tlbe guest_tlb[PPC44x_TLB_SIZE];
- struct tlbe shadow_tlb[PPC44x_TLB_SIZE];
-};
-
enum emulation_result {
EMULATE_DONE, /* no further processing */
EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */
@@ -41,9 +36,6 @@ enum emulation_result {
EMULATE_FAIL, /* can't emulate this instruction */
};
-extern const unsigned char exception_priority[];
-extern const unsigned char priority_exception[];
-
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
extern char kvmppc_handlers_start[];
extern unsigned long kvmppc_handler_len;
@@ -58,51 +50,44 @@ extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
extern int kvmppc_emulate_instruction(struct kvm_run *run,
struct kvm_vcpu *vcpu);
extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu);
+extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
-extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn,
- u64 asid, u32 flags);
-extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
- gva_t eend, u32 asid);
+extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
+ u64 asid, u32 flags, u32 max_bytes,
+ unsigned int gtlb_idx);
extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode);
extern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid);
-/* XXX Book E specific */
-extern void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i);
-
-extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu);
-
-static inline void kvmppc_queue_exception(struct kvm_vcpu *vcpu, int exception)
-{
- unsigned int priority = exception_priority[exception];
- set_bit(priority, &vcpu->arch.pending_exceptions);
-}
-
-static inline void kvmppc_clear_exception(struct kvm_vcpu *vcpu, int exception)
-{
- unsigned int priority = exception_priority[exception];
- clear_bit(priority, &vcpu->arch.pending_exceptions);
-}
-
-/* Helper function for "full" MSR writes. No need to call this if only EE is
- * changing. */
-static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
-{
- if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
- kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
-
- vcpu->arch.msr = new_msr;
-
- if (vcpu->arch.msr & MSR_WE)
- kvm_vcpu_block(vcpu);
-}
-
-static inline void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
-{
- if (vcpu->arch.pid != new_pid) {
- vcpu->arch.pid = new_pid;
- vcpu->arch.swap_pid = 1;
- }
-}
+/* Core-specific hooks */
+
+extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm,
+ unsigned int id);
+extern void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu);
+extern int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu);
+extern int kvmppc_core_check_processor_compat(void);
+extern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
+ struct kvm_translation *tr);
+
+extern void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
+extern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);
+
+extern void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu);
+
+extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu);
+extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
+ struct kvm_interrupt *irq);
+
+extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int op, int *advance);
+extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs);
+extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt);
+
+extern int kvmppc_booke_init(void);
+extern void kvmppc_booke_exit(void);
extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
diff --git a/arch/powerpc/include/asm/mmu-44x.h b/arch/powerpc/include/asm/mmu-44x.h
index 8a97cfb08b7e..27cc6fdcd3b7 100644
--- a/arch/powerpc/include/asm/mmu-44x.h
+++ b/arch/powerpc/include/asm/mmu-44x.h
@@ -56,6 +56,7 @@
#ifndef __ASSEMBLY__
extern unsigned int tlb_44x_hwater;
+extern unsigned int tlb_44x_index;
typedef struct {
unsigned int id;
diff --git a/arch/powerpc/include/asm/oprofile_impl.h b/arch/powerpc/include/asm/oprofile_impl.h
index 95035c602ba6..639dc96077ab 100644
--- a/arch/powerpc/include/asm/oprofile_impl.h
+++ b/arch/powerpc/include/asm/oprofile_impl.h
@@ -32,6 +32,12 @@ struct op_system_config {
unsigned long mmcr0;
unsigned long mmcr1;
unsigned long mmcra;
+#ifdef CONFIG_OPROFILE_CELL
+ /* Register for oprofile user tool to check cell kernel profiling
+ * suport.
+ */
+ unsigned long cell_support;
+#endif
#endif
unsigned long enable_kernel;
unsigned long enable_user;
diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h
index cff30c0ef1ff..67f1812698d2 100644
--- a/arch/powerpc/include/asm/ps3.h
+++ b/arch/powerpc/include/asm/ps3.h
@@ -103,10 +103,10 @@ struct ps3_dma_region_ops {
int (*map)(struct ps3_dma_region *,
unsigned long virt_addr,
unsigned long len,
- unsigned long *bus_addr,
+ dma_addr_t *bus_addr,
u64 iopte_pp);
int (*unmap)(struct ps3_dma_region *,
- unsigned long bus_addr,
+ dma_addr_t bus_addr,
unsigned long len);
};
/**
@@ -124,9 +124,9 @@ int ps3_dma_region_init(struct ps3_system_bus_device *dev,
int ps3_dma_region_create(struct ps3_dma_region *r);
int ps3_dma_region_free(struct ps3_dma_region *r);
int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
- unsigned long len, unsigned long *bus_addr,
+ unsigned long len, dma_addr_t *bus_addr,
u64 iopte_pp);
-int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
+int ps3_dma_unmap(struct ps3_dma_region *r, dma_addr_t bus_addr,
unsigned long len);
/* mmio routines */
@@ -320,6 +320,7 @@ enum ps3_match_id {
enum ps3_match_sub_id {
PS3_MATCH_SUB_ID_GPU_FB = 1,
+ PS3_MATCH_SUB_ID_GPU_RAMDISK = 2,
};
#define PS3_MODULE_ALIAS_EHCI "ps3:1:0"
@@ -332,6 +333,7 @@ enum ps3_match_sub_id {
#define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8:0"
#define PS3_MODULE_ALIAS_SOUND "ps3:9:0"
#define PS3_MODULE_ALIAS_GPU_FB "ps3:10:1"
+#define PS3_MODULE_ALIAS_GPU_RAMDISK "ps3:10:2"
#define PS3_MODULE_ALIAS_LPM "ps3:11:0"
enum ps3_system_bus_device_type {
diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index edee15d269ea..2701753d9937 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -17,6 +17,8 @@
#ifdef __KERNEL__
#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/err.h>
#include <asm/cpm.h>
#include <asm/immap_qe.h>
@@ -84,7 +86,11 @@ static inline bool qe_clock_is_brg(enum qe_clock clk)
extern spinlock_t cmxgcr_lock;
/* Export QE common operations */
+#ifdef CONFIG_QUICC_ENGINE
extern void __init qe_reset(void);
+#else
+static inline void qe_reset(void) {}
+#endif
/* QE PIO */
#define QE_PIO_PINS 32
@@ -101,16 +107,43 @@ struct qe_pio_regs {
#endif
};
-extern int par_io_init(struct device_node *np);
-extern int par_io_of_config(struct device_node *np);
#define QE_PIO_DIR_IN 2
#define QE_PIO_DIR_OUT 1
extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin,
int dir, int open_drain, int assignment,
int has_irq);
+#ifdef CONFIG_QUICC_ENGINE
+extern int par_io_init(struct device_node *np);
+extern int par_io_of_config(struct device_node *np);
extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
int assignment, int has_irq);
extern int par_io_data_set(u8 port, u8 pin, u8 val);
+#else
+static inline int par_io_init(struct device_node *np) { return -ENOSYS; }
+static inline int par_io_of_config(struct device_node *np) { return -ENOSYS; }
+static inline int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
+ int assignment, int has_irq) { return -ENOSYS; }
+static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; }
+#endif /* CONFIG_QUICC_ENGINE */
+
+/*
+ * Pin multiplexing functions.
+ */
+struct qe_pin;
+#ifdef CONFIG_QE_GPIO
+extern struct qe_pin *qe_pin_request(struct device_node *np, int index);
+extern void qe_pin_free(struct qe_pin *qe_pin);
+extern void qe_pin_set_gpio(struct qe_pin *qe_pin);
+extern void qe_pin_set_dedicated(struct qe_pin *pin);
+#else
+static inline struct qe_pin *qe_pin_request(struct device_node *np, int index)
+{
+ return ERR_PTR(-ENOSYS);
+}
+static inline void qe_pin_free(struct qe_pin *qe_pin) {}
+static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {}
+static inline void qe_pin_set_dedicated(struct qe_pin *pin) {}
+#endif /* CONFIG_QE_GPIO */
/* QE internal API */
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
@@ -591,7 +624,7 @@ struct ucc_slow_pram {
#define UCC_GETH_UCCE_RXF1 0x00000002
#define UCC_GETH_UCCE_RXF0 0x00000001
-/* UPSMR, when used as a UART */
+/* UCC Protocol Specific Mode Register (UPSMR), when used for UART */
#define UCC_UART_UPSMR_FLC 0x8000
#define UCC_UART_UPSMR_SL 0x4000
#define UCC_UART_UPSMR_CL_MASK 0x3000
@@ -619,6 +652,23 @@ struct ucc_slow_pram {
#define UCC_UART_UPSMR_TPM_EVEN 0x0002
#define UCC_UART_UPSMR_TPM_HIGH 0x0003
+/* UCC Protocol Specific Mode Register (UPSMR), when used for Ethernet */
+#define UCC_GETH_UPSMR_FTFE 0x80000000
+#define UCC_GETH_UPSMR_PTPE 0x40000000
+#define UCC_GETH_UPSMR_ECM 0x04000000
+#define UCC_GETH_UPSMR_HSE 0x02000000
+#define UCC_GETH_UPSMR_PRO 0x00400000
+#define UCC_GETH_UPSMR_CAP 0x00200000
+#define UCC_GETH_UPSMR_RSH 0x00100000
+#define UCC_GETH_UPSMR_RPM 0x00080000
+#define UCC_GETH_UPSMR_R10M 0x00040000
+#define UCC_GETH_UPSMR_RLPB 0x00020000
+#define UCC_GETH_UPSMR_TBIM 0x00010000
+#define UCC_GETH_UPSMR_RES1 0x00002000
+#define UCC_GETH_UPSMR_RMM 0x00001000
+#define UCC_GETH_UPSMR_CAM 0x00000400
+#define UCC_GETH_UPSMR_BRO 0x00000200
+
/* UCC Transmit On Demand Register (UTODR) */
#define UCC_SLOW_TOD 0x8000
#define UCC_FAST_TOD 0x8000
diff --git a/arch/powerpc/include/asm/qe_ic.h b/arch/powerpc/include/asm/qe_ic.h
index 56a7745ca343..cf519663a791 100644
--- a/arch/powerpc/include/asm/qe_ic.h
+++ b/arch/powerpc/include/asm/qe_ic.h
@@ -17,6 +17,9 @@
#include <linux/irq.h>
+struct device_node;
+struct qe_ic;
+
#define NUM_OF_QE_IC_GROUPS 6
/* Flags when we init the QE IC */
@@ -54,17 +57,27 @@ enum qe_ic_grp_id {
QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */
};
+#ifdef CONFIG_QUICC_ENGINE
void qe_ic_init(struct device_node *node, unsigned int flags,
void (*low_handler)(unsigned int irq, struct irq_desc *desc),
void (*high_handler)(unsigned int irq, struct irq_desc *desc));
+unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic);
+unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic);
+#else
+static inline void qe_ic_init(struct device_node *node, unsigned int flags,
+ void (*low_handler)(unsigned int irq, struct irq_desc *desc),
+ void (*high_handler)(unsigned int irq, struct irq_desc *desc))
+{}
+static inline unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
+{ return 0; }
+static inline unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
+{ return 0; }
+#endif /* CONFIG_QUICC_ENGINE */
+
void qe_ic_set_highest_priority(unsigned int virq, int high);
int qe_ic_set_priority(unsigned int virq, unsigned int priority);
int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high);
-struct qe_ic;
-unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic);
-unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic);
-
static inline void qe_ic_cascade_low_ipic(unsigned int irq,
struct irq_desc *desc)
{
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index e0175beb4462..0aa0315fb7e8 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -18,7 +18,7 @@
*/
#define RTAS_UNKNOWN_SERVICE (-1)
-#define RTAS_INSTANTIATE_MAX (1UL<<30) /* Don't instantiate rtas at/above this value */
+#define RTAS_INSTANTIATE_MAX (1ULL<<30) /* Don't instantiate rtas at/above this value */
/* Buffer size for ppc_rtas system call. */
#define RTAS_RMOBUF_MAX (64 * 1024)
diff --git a/arch/powerpc/include/asm/spu.h b/arch/powerpc/include/asm/spu.h
index 8b2eb044270a..0ab8d869e3d6 100644
--- a/arch/powerpc/include/asm/spu.h
+++ b/arch/powerpc/include/asm/spu.h
@@ -128,7 +128,7 @@ struct spu {
int number;
unsigned int irqs[3];
u32 node;
- u64 flags;
+ unsigned long flags;
u64 class_0_pending;
u64 class_0_dar;
u64 class_1_dar;
diff --git a/arch/powerpc/include/asm/swab.h b/arch/powerpc/include/asm/swab.h
new file mode 100644
index 000000000000..ef824ae4b79c
--- /dev/null
+++ b/arch/powerpc/include/asm/swab.h
@@ -0,0 +1,90 @@
+#ifndef _ASM_POWERPC_SWAB_H
+#define _ASM_POWERPC_SWAB_H
+
+/*
+ * 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 <asm/types.h>
+#include <linux/compiler.h>
+
+#ifdef __GNUC__
+
+#ifndef __powerpc64__
+#define __SWAB_64_THRU_32__
+#endif /* __powerpc64__ */
+
+#ifdef __KERNEL__
+
+static __inline__ __u16 ld_le16(const volatile __u16 *addr)
+{
+ __u16 val;
+
+ __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+#define __arch_swab16p ld_le16
+
+static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
+{
+ __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void __arch_swab16s(__u16 *addr)
+{
+ st_le16(addr, *addr);
+}
+#define __arch_swab16s __arch_swab16s
+
+static __inline__ __u32 ld_le32(const volatile __u32 *addr)
+{
+ __u32 val;
+
+ __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+#define __arch_swab32p ld_le32
+
+static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
+{
+ __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline void __arch_swab32s(__u32 *addr)
+{
+ st_le32(addr, *addr);
+}
+#define __arch_swab32s __arch_swab32s
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 value)
+{
+ __u16 result;
+
+ __asm__("rlwimi %0,%1,8,16,23"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 8));
+ return result;
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 value)
+{
+ __u32 result;
+
+ __asm__("rlwimi %0,%1,24,16,23\n\t"
+ "rlwimi %0,%1,8,8,15\n\t"
+ "rlwimi %0,%1,24,0,7"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 24));
+ return result;
+}
+#define __arch_swab32 __arch_swab32
+
+#endif /* __KERNEL__ */
+
+#endif /* __GNUC__ */
+
+#endif /* _ASM_POWERPC_SWAB_H */
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 803def236654..72353f6070a4 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -92,7 +92,7 @@ COMPAT_SYS_SPU(readlink)
SYSCALL(uselib)
SYSCALL(swapon)
SYSCALL(reboot)
-SYSX(sys_ni_syscall,compat_sys_old_readdir,old_readdir)
+SYSX(sys_ni_syscall,compat_sys_old_readdir,sys_old_readdir)
SYSCALL_SPU(mmap)
SYSCALL_SPU(munmap)
SYSCALL_SPU(truncate)
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index c32da6f97999..375258559ae6 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -22,11 +22,11 @@ static inline cpumask_t node_to_cpumask(int node)
return numa_cpumask_lookup_table[node];
}
+#define cpumask_of_node(node) (&numa_cpumask_lookup_table[node])
+
static inline int node_to_first_cpu(int node)
{
- cpumask_t tmp;
- tmp = node_to_cpumask(node);
- return first_cpu(tmp);
+ return cpumask_first(cpumask_of_node(node));
}
int of_node_to_nid(struct device_node *device);
@@ -46,9 +46,12 @@ static inline int pcibus_to_node(struct pci_bus *bus)
node_to_cpumask(pcibus_to_node(bus)) \
)
+#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \
+ cpu_all_mask : \
+ cpumask_of_node(pcibus_to_node(bus)))
+
/* sched_domains SD_NODE_INIT for PPC64 machines */
#define SD_NODE_INIT (struct sched_domain) { \
- .span = CPU_MASK_NONE, \
.parent = NULL, \
.child = NULL, \
.groups = NULL, \
@@ -109,6 +112,8 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev,
#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
#define topology_core_siblings(cpu) (per_cpu(cpu_core_map, cpu))
+#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
+#define topology_core_cpumask(cpu) (&per_cpu(cpu_core_map, cpu))
#define topology_core_id(cpu) (cpu_to_core_id(cpu))
#endif
#endif
diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h
index c004c13f291e..7ce27a52bb34 100644
--- a/arch/powerpc/include/asm/types.h
+++ b/arch/powerpc/include/asm/types.h
@@ -1,7 +1,12 @@
#ifndef _ASM_POWERPC_TYPES_H
#define _ASM_POWERPC_TYPES_H
-#ifdef __powerpc64__
+/*
+ * This is here because we used to use l64 for 64bit powerpc
+ * and we don't want to impact user mode with our change to ll64
+ * in the kernel.
+ */
+#if defined(__powerpc64__) && !defined(__KERNEL__)
# include <asm-generic/int-l64.h>
#else
# include <asm-generic/int-ll64.h>
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 1308a86e9070..8d1a419df35d 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -29,7 +29,7 @@ endif
obj-y := cputable.o ptrace.o syscalls.o \
irq.o align.o signal_32.o pmc.o vdso.o \
init_task.o process.o systbl.o idle.o \
- signal.o sysfs.o
+ signal.o sysfs.o cacheinfo.o
obj-y += vdso32/
obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \
signal_64.o ptrace32.o \
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 661d07d2146b..19ee491e9e23 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -23,9 +23,6 @@
#include <linux/mm.h>
#include <linux/suspend.h>
#include <linux/hrtimer.h>
-#ifdef CONFIG_KVM
-#include <linux/kvm_host.h>
-#endif
#ifdef CONFIG_PPC64
#include <linux/time.h>
#include <linux/hardirq.h>
@@ -51,11 +48,18 @@
#ifdef CONFIG_PPC_ISERIES
#include <asm/iseries/alpaca.h>
#endif
+#ifdef CONFIG_KVM
+#include <asm/kvm_44x.h>
+#endif
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
#include "head_booke.h"
#endif
+#if defined(CONFIG_FSL_BOOKE)
+#include "../mm/mmu_decl.h"
+#endif
+
int main(void)
{
DEFINE(THREAD, offsetof(struct task_struct, thread));
@@ -357,12 +361,10 @@ int main(void)
DEFINE(PTE_SIZE, sizeof(pte_t));
#ifdef CONFIG_KVM
- DEFINE(TLBE_BYTES, sizeof(struct tlbe));
+ DEFINE(TLBE_BYTES, sizeof(struct kvmppc_44x_tlbe));
DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack));
DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid));
- DEFINE(VCPU_SHADOW_TLB, offsetof(struct kvm_vcpu, arch.shadow_tlb));
- DEFINE(VCPU_SHADOW_MOD, offsetof(struct kvm_vcpu, arch.shadow_tlb_mod));
DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr));
DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr));
DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr));
@@ -384,6 +386,20 @@ int main(void)
DEFINE(PGD_T_LOG2, PGD_T_LOG2);
DEFINE(PTE_T_LOG2, PTE_T_LOG2);
#endif
+#ifdef CONFIG_FSL_BOOKE
+ DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam));
+#endif
+
+#ifdef CONFIG_KVM_EXIT_TIMING
+ DEFINE(VCPU_TIMING_EXIT_TBU, offsetof(struct kvm_vcpu,
+ arch.timing_exit.tv32.tbu));
+ DEFINE(VCPU_TIMING_EXIT_TBL, offsetof(struct kvm_vcpu,
+ arch.timing_exit.tv32.tbl));
+ DEFINE(VCPU_TIMING_LAST_ENTER_TBU, offsetof(struct kvm_vcpu,
+ arch.timing_last_enter.tv32.tbu));
+ DEFINE(VCPU_TIMING_LAST_ENTER_TBL, offsetof(struct kvm_vcpu,
+ arch.timing_last_enter.tv32.tbl));
+#endif
return 0;
}
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
new file mode 100644
index 000000000000..bb37b1d19a58
--- /dev/null
+++ b/arch/powerpc/kernel/cacheinfo.c
@@ -0,0 +1,837 @@
+/*
+ * Processor cache information made available to userspace via sysfs;
+ * intended to be compatible with x86 intel_cacheinfo implementation.
+ *
+ * Copyright 2008 IBM Corporation
+ * Author: Nathan Lynch
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/percpu.h>
+#include <asm/prom.h>
+
+#include "cacheinfo.h"
+
+/* per-cpu object for tracking:
+ * - a "cache" kobject for the top-level directory
+ * - a list of "index" objects representing the cpu's local cache hierarchy
+ */
+struct cache_dir {
+ struct kobject *kobj; /* bare (not embedded) kobject for cache
+ * directory */
+ struct cache_index_dir *index; /* list of index objects */
+};
+
+/* "index" object: each cpu's cache directory has an index
+ * subdirectory corresponding to a cache object associated with the
+ * cpu. This object's lifetime is managed via the embedded kobject.
+ */
+struct cache_index_dir {
+ struct kobject kobj;
+ struct cache_index_dir *next; /* next index in parent directory */
+ struct cache *cache;
+};
+
+/* Template for determining which OF properties to query for a given
+ * cache type */
+struct cache_type_info {
+ const char *name;
+ const char *size_prop;
+
+ /* Allow for both [di]-cache-line-size and
+ * [di]-cache-block-size properties. According to the PowerPC
+ * Processor binding, -line-size should be provided if it
+ * differs from the cache block size (that which is operated
+ * on by cache instructions), so we look for -line-size first.
+ * See cache_get_line_size(). */
+
+ const char *line_size_props[2];
+ const char *nr_sets_prop;
+};
+
+/* These are used to index the cache_type_info array. */
+#define CACHE_TYPE_UNIFIED 0
+#define CACHE_TYPE_INSTRUCTION 1
+#define CACHE_TYPE_DATA 2
+
+static const struct cache_type_info cache_type_info[] = {
+ {
+ /* PowerPC Processor binding says the [di]-cache-*
+ * must be equal on unified caches, so just use
+ * d-cache properties. */
+ .name = "Unified",
+ .size_prop = "d-cache-size",
+ .line_size_props = { "d-cache-line-size",
+ "d-cache-block-size", },
+ .nr_sets_prop = "d-cache-sets",
+ },
+ {
+ .name = "Instruction",
+ .size_prop = "i-cache-size",
+ .line_size_props = { "i-cache-line-size",
+ "i-cache-block-size", },
+ .nr_sets_prop = "i-cache-sets",
+ },
+ {
+ .name = "Data",
+ .size_prop = "d-cache-size",
+ .line_size_props = { "d-cache-line-size",
+ "d-cache-block-size", },
+ .nr_sets_prop = "d-cache-sets",
+ },
+};
+
+/* Cache object: each instance of this corresponds to a distinct cache
+ * in the system. There are separate objects for Harvard caches: one
+ * each for instruction and data, and each refers to the same OF node.
+ * The refcount of the OF node is elevated for the lifetime of the
+ * cache object. A cache object is released when its shared_cpu_map
+ * is cleared (see cache_cpu_clear).
+ *
+ * A cache object is on two lists: an unsorted global list
+ * (cache_list) of cache objects; and a singly-linked list
+ * representing the local cache hierarchy, which is ordered by level
+ * (e.g. L1d -> L1i -> L2 -> L3).
+ */
+struct cache {
+ struct device_node *ofnode; /* OF node for this cache, may be cpu */
+ struct cpumask shared_cpu_map; /* online CPUs using this cache */
+ int type; /* split cache disambiguation */
+ int level; /* level not explicit in device tree */
+ struct list_head list; /* global list of cache objects */
+ struct cache *next_local; /* next cache of >= level */
+};
+
+static DEFINE_PER_CPU(struct cache_dir *, cache_dir_pcpu);
+
+/* traversal/modification of this list occurs only at cpu hotplug time;
+ * access is serialized by cpu hotplug locking
+ */
+static LIST_HEAD(cache_list);
+
+static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *k)
+{
+ return container_of(k, struct cache_index_dir, kobj);
+}
+
+static const char *cache_type_string(const struct cache *cache)
+{
+ return cache_type_info[cache->type].name;
+}
+
+static void __cpuinit cache_init(struct cache *cache, int type, int level, struct device_node *ofnode)
+{
+ cache->type = type;
+ cache->level = level;
+ cache->ofnode = of_node_get(ofnode);
+ INIT_LIST_HEAD(&cache->list);
+ list_add(&cache->list, &cache_list);
+}
+
+static struct cache *__cpuinit new_cache(int type, int level, struct device_node *ofnode)
+{
+ struct cache *cache;
+
+ cache = kzalloc(sizeof(*cache), GFP_KERNEL);
+ if (cache)
+ cache_init(cache, type, level, ofnode);
+
+ return cache;
+}
+
+static void release_cache_debugcheck(struct cache *cache)
+{
+ struct cache *iter;
+
+ list_for_each_entry(iter, &cache_list, list)
+ WARN_ONCE(iter->next_local == cache,
+ "cache for %s(%s) refers to cache for %s(%s)\n",
+ iter->ofnode->full_name,
+ cache_type_string(iter),
+ cache->ofnode->full_name,
+ cache_type_string(cache));
+}
+
+static void release_cache(struct cache *cache)
+{
+ if (!cache)
+ return;
+
+ pr_debug("freeing L%d %s cache for %s\n", cache->level,
+ cache_type_string(cache), cache->ofnode->full_name);
+
+ release_cache_debugcheck(cache);
+ list_del(&cache->list);
+ of_node_put(cache->ofnode);
+ kfree(cache);
+}
+
+static void cache_cpu_set(struct cache *cache, int cpu)
+{
+ struct cache *next = cache;
+
+ while (next) {
+ WARN_ONCE(cpumask_test_cpu(cpu, &next->shared_cpu_map),
+ "CPU %i already accounted in %s(%s)\n",
+ cpu, next->ofnode->full_name,
+ cache_type_string(next));
+ cpumask_set_cpu(cpu, &next->shared_cpu_map);
+ next = next->next_local;
+ }
+}
+
+static int cache_size(const struct cache *cache, unsigned int *ret)
+{
+ const char *propname;
+ const u32 *cache_size;
+
+ propname = cache_type_info[cache->type].size_prop;
+
+ cache_size = of_get_property(cache->ofnode, propname, NULL);
+ if (!cache_size)
+ return -ENODEV;
+
+ *ret = *cache_size;
+ return 0;
+}
+
+static int cache_size_kb(const struct cache *cache, unsigned int *ret)
+{
+ unsigned int size;
+
+ if (cache_size(cache, &size))
+ return -ENODEV;
+
+ *ret = size / 1024;
+ return 0;
+}
+
+/* not cache_line_size() because that's a macro in include/linux/cache.h */
+static int cache_get_line_size(const struct cache *cache, unsigned int *ret)
+{
+ const u32 *line_size;
+ int i, lim;
+
+ lim = ARRAY_SIZE(cache_type_info[cache->type].line_size_props);
+
+ for (i = 0; i < lim; i++) {
+ const char *propname;
+
+ propname = cache_type_info[cache->type].line_size_props[i];
+ line_size = of_get_property(cache->ofnode, propname, NULL);
+ if (line_size)
+ break;
+ }
+
+ if (!line_size)
+ return -ENODEV;
+
+ *ret = *line_size;
+ return 0;
+}
+
+static int cache_nr_sets(const struct cache *cache, unsigned int *ret)
+{
+ const char *propname;
+ const u32 *nr_sets;
+
+ propname = cache_type_info[cache->type].nr_sets_prop;
+
+ nr_sets = of_get_property(cache->ofnode, propname, NULL);
+ if (!nr_sets)
+ return -ENODEV;
+
+ *ret = *nr_sets;
+ return 0;
+}
+
+static int cache_associativity(const struct cache *cache, unsigned int *ret)
+{
+ unsigned int line_size;
+ unsigned int nr_sets;
+ unsigned int size;
+
+ if (cache_nr_sets(cache, &nr_sets))
+ goto err;
+
+ /* If the cache is fully associative, there is no need to
+ * check the other properties.
+ */
+ if (nr_sets == 1) {
+ *ret = 0;
+ return 0;
+ }
+
+ if (cache_get_line_size(cache, &line_size))
+ goto err;
+ if (cache_size(cache, &size))
+ goto err;
+
+ if (!(nr_sets > 0 && size > 0 && line_size > 0))
+ goto err;
+
+ *ret = (size / nr_sets) / line_size;
+ return 0;
+err:
+ return -ENODEV;
+}
+
+/* helper for dealing with split caches */
+static struct cache *cache_find_first_sibling(struct cache *cache)
+{
+ struct cache *iter;
+
+ if (cache->type == CACHE_TYPE_UNIFIED)
+ return cache;
+
+ list_for_each_entry(iter, &cache_list, list)
+ if (iter->ofnode == cache->ofnode && iter->next_local == cache)
+ return iter;
+
+ return cache;
+}
+
+/* return the first cache on a local list matching node */
+static struct cache *cache_lookup_by_node(const struct device_node *node)
+{
+ struct cache *cache = NULL;
+ struct cache *iter;
+
+ list_for_each_entry(iter, &cache_list, list) {
+ if (iter->ofnode != node)
+ continue;
+ cache = cache_find_first_sibling(iter);
+ break;
+ }
+
+ return cache;
+}
+
+static bool cache_node_is_unified(const struct device_node *np)
+{
+ return of_get_property(np, "cache-unified", NULL);
+}
+
+static struct cache *__cpuinit cache_do_one_devnode_unified(struct device_node *node, int level)
+{
+ struct cache *cache;
+
+ pr_debug("creating L%d ucache for %s\n", level, node->full_name);
+
+ cache = new_cache(CACHE_TYPE_UNIFIED, level, node);
+
+ return cache;
+}
+
+static struct cache *__cpuinit cache_do_one_devnode_split(struct device_node *node, int level)
+{
+ struct cache *dcache, *icache;
+
+ pr_debug("creating L%d dcache and icache for %s\n", level,
+ node->full_name);
+
+ dcache = new_cache(CACHE_TYPE_DATA, level, node);
+ icache = new_cache(CACHE_TYPE_INSTRUCTION, level, node);
+
+ if (!dcache || !icache)
+ goto err;
+
+ dcache->next_local = icache;
+
+ return dcache;
+err:
+ release_cache(dcache);
+ release_cache(icache);
+ return NULL;
+}
+
+static struct cache *__cpuinit cache_do_one_devnode(struct device_node *node, int level)
+{
+ struct cache *cache;
+
+ if (cache_node_is_unified(node))
+ cache = cache_do_one_devnode_unified(node, level);
+ else
+ cache = cache_do_one_devnode_split(node, level);
+
+ return cache;
+}
+
+static struct cache *__cpuinit cache_lookup_or_instantiate(struct device_node *node, int level)
+{
+ struct cache *cache;
+
+ cache = cache_lookup_by_node(node);
+
+ WARN_ONCE(cache && cache->level != level,
+ "cache level mismatch on lookup (got %d, expected %d)\n",
+ cache->level, level);
+
+ if (!cache)
+ cache = cache_do_one_devnode(node, level);
+
+ return cache;
+}
+
+static void __cpuinit link_cache_lists(struct cache *smaller, struct cache *bigger)
+{
+ while (smaller->next_local) {
+ if (smaller->next_local == bigger)
+ return; /* already linked */
+ smaller = smaller->next_local;
+ }
+
+ smaller->next_local = bigger;
+}
+
+static void __cpuinit do_subsidiary_caches_debugcheck(struct cache *cache)
+{
+ WARN_ON_ONCE(cache->level != 1);
+ WARN_ON_ONCE(strcmp(cache->ofnode->type, "cpu"));
+}
+
+static void __cpuinit do_subsidiary_caches(struct cache *cache)
+{
+ struct device_node *subcache_node;
+ int level = cache->level;
+
+ do_subsidiary_caches_debugcheck(cache);
+
+ while ((subcache_node = of_find_next_cache_node(cache->ofnode))) {
+ struct cache *subcache;
+
+ level++;
+ subcache = cache_lookup_or_instantiate(subcache_node, level);
+ of_node_put(subcache_node);
+ if (!subcache)
+ break;
+
+ link_cache_lists(cache, subcache);
+ cache = subcache;
+ }
+}
+
+static struct cache *__cpuinit cache_chain_instantiate(unsigned int cpu_id)
+{
+ struct device_node *cpu_node;
+ struct cache *cpu_cache = NULL;
+
+ pr_debug("creating cache object(s) for CPU %i\n", cpu_id);
+
+ cpu_node = of_get_cpu_node(cpu_id, NULL);
+ WARN_ONCE(!cpu_node, "no OF node found for CPU %i\n", cpu_id);
+ if (!cpu_node)
+ goto out;
+
+ cpu_cache = cache_lookup_or_instantiate(cpu_node, 1);
+ if (!cpu_cache)
+ goto out;
+
+ do_subsidiary_caches(cpu_cache);
+
+ cache_cpu_set(cpu_cache, cpu_id);
+out:
+ of_node_put(cpu_node);
+
+ return cpu_cache;
+}
+
+static struct cache_dir *__cpuinit cacheinfo_create_cache_dir(unsigned int cpu_id)
+{
+ struct cache_dir *cache_dir;
+ struct sys_device *sysdev;
+ struct kobject *kobj = NULL;
+
+ sysdev = get_cpu_sysdev(cpu_id);
+ WARN_ONCE(!sysdev, "no sysdev for CPU %i\n", cpu_id);
+ if (!sysdev)
+ goto err;
+
+ kobj = kobject_create_and_add("cache", &sysdev->kobj);
+ if (!kobj)
+ goto err;
+
+ cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL);
+ if (!cache_dir)
+ goto err;
+
+ cache_dir->kobj = kobj;
+
+ WARN_ON_ONCE(per_cpu(cache_dir_pcpu, cpu_id) != NULL);
+
+ per_cpu(cache_dir_pcpu, cpu_id) = cache_dir;
+
+ return cache_dir;
+err:
+ kobject_put(kobj);
+ return NULL;
+}
+
+static void cache_index_release(struct kobject *kobj)
+{
+ struct cache_index_dir *index;
+
+ index = kobj_to_cache_index_dir(kobj);
+
+ pr_debug("freeing index directory for L%d %s cache\n",
+ index->cache->level, cache_type_string(index->cache));
+
+ kfree(index);
+}
+
+static ssize_t cache_index_show(struct kobject *k, struct attribute *attr, char *buf)
+{
+ struct kobj_attribute *kobj_attr;
+
+ kobj_attr = container_of(attr, struct kobj_attribute, attr);
+
+ return kobj_attr->show(k, kobj_attr, buf);
+}
+
+static struct cache *index_kobj_to_cache(struct kobject *k)
+{
+ struct cache_index_dir *index;
+
+ index = kobj_to_cache_index_dir(k);
+
+ return index->cache;
+}
+
+static ssize_t size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+ unsigned int size_kb;
+ struct cache *cache;
+
+ cache = index_kobj_to_cache(k);
+
+ if (cache_size_kb(cache, &size_kb))
+ return -ENODEV;
+
+ return sprintf(buf, "%uK\n", size_kb);
+}
+
+static struct kobj_attribute cache_size_attr =
+ __ATTR(size, 0444, size_show, NULL);
+
+
+static ssize_t line_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+ unsigned int line_size;
+ struct cache *cache;
+
+ cache = index_kobj_to_cache(k);
+
+ if (cache_get_line_size(cache, &line_size))
+ return -ENODEV;
+
+ return sprintf(buf, "%u\n", line_size);
+}
+
+static struct kobj_attribute cache_line_size_attr =
+ __ATTR(coherency_line_size, 0444, line_size_show, NULL);
+
+static ssize_t nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+ unsigned int nr_sets;
+ struct cache *cache;
+
+ cache = index_kobj_to_cache(k);
+
+ if (cache_nr_sets(cache, &nr_sets))
+ return -ENODEV;
+
+ return sprintf(buf, "%u\n", nr_sets);
+}
+
+static struct kobj_attribute cache_nr_sets_attr =
+ __ATTR(number_of_sets, 0444, nr_sets_show, NULL);
+
+static ssize_t associativity_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+ unsigned int associativity;
+ struct cache *cache;
+
+ cache = index_kobj_to_cache(k);
+
+ if (cache_associativity(cache, &associativity))
+ return -ENODEV;
+
+ return sprintf(buf, "%u\n", associativity);
+}
+
+static struct kobj_attribute cache_assoc_attr =
+ __ATTR(ways_of_associativity, 0444, associativity_show, NULL);
+
+static ssize_t type_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+ struct cache *cache;
+
+ cache = index_kobj_to_cache(k);
+
+ return sprintf(buf, "%s\n", cache_type_string(cache));
+}
+
+static struct kobj_attribute cache_type_attr =
+ __ATTR(type, 0444, type_show, NULL);
+
+static ssize_t level_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+ struct cache_index_dir *index;
+ struct cache *cache;
+
+ index = kobj_to_cache_index_dir(k);
+ cache = index->cache;
+
+ return sprintf(buf, "%d\n", cache->level);
+}
+
+static struct kobj_attribute cache_level_attr =
+ __ATTR(level, 0444, level_show, NULL);
+
+static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
+{
+ struct cache_index_dir *index;
+ struct cache *cache;
+ int len;
+ int n = 0;
+
+ index = kobj_to_cache_index_dir(k);
+ cache = index->cache;
+ len = PAGE_SIZE - 2;
+
+ if (len > 1) {
+ n = cpumask_scnprintf(buf, len, &cache->shared_cpu_map);
+ buf[n++] = '\n';
+ buf[n] = '\0';
+ }
+ return n;
+}
+
+static struct kobj_attribute cache_shared_cpu_map_attr =
+ __ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL);
+
+/* Attributes which should always be created -- the kobject/sysfs core
+ * does this automatically via kobj_type->default_attrs. This is the
+ * minimum data required to uniquely identify a cache.
+ */
+static struct attribute *cache_index_default_attrs[] = {
+ &cache_type_attr.attr,
+ &cache_level_attr.attr,
+ &cache_shared_cpu_map_attr.attr,
+ NULL,
+};
+
+/* Attributes which should be created if the cache device node has the
+ * right properties -- see cacheinfo_create_index_opt_attrs
+ */
+static struct kobj_attribute *cache_index_opt_attrs[] = {
+ &cache_size_attr,
+ &cache_line_size_attr,
+ &cache_nr_sets_attr,
+ &cache_assoc_attr,
+};
+
+static struct sysfs_ops cache_index_ops = {
+ .show = cache_index_show,
+};
+
+static struct kobj_type cache_index_type = {
+ .release = cache_index_release,
+ .sysfs_ops = &cache_index_ops,
+ .default_attrs = cache_index_default_attrs,
+};
+
+static void __cpuinit cacheinfo_create_index_opt_attrs(struct cache_index_dir *dir)
+{
+ const char *cache_name;
+ const char *cache_type;
+ struct cache *cache;
+ char *buf;
+ int i;
+
+ buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!buf)
+ return;
+
+ cache = dir->cache;
+ cache_name = cache->ofnode->full_name;
+ cache_type = cache_type_string(cache);
+
+ /* We don't want to create an attribute that can't provide a
+ * meaningful value. Check the return value of each optional
+ * attribute's ->show method before registering the
+ * attribute.
+ */
+ for (i = 0; i < ARRAY_SIZE(cache_index_opt_attrs); i++) {
+ struct kobj_attribute *attr;
+ ssize_t rc;
+
+ attr = cache_index_opt_attrs[i];
+
+ rc = attr->show(&dir->kobj, attr, buf);
+ if (rc <= 0) {
+ pr_debug("not creating %s attribute for "
+ "%s(%s) (rc = %zd)\n",
+ attr->attr.name, cache_name,
+ cache_type, rc);
+ continue;
+ }
+ if (sysfs_create_file(&dir->kobj, &attr->attr))
+ pr_debug("could not create %s attribute for %s(%s)\n",
+ attr->attr.name, cache_name, cache_type);
+ }
+
+ kfree(buf);
+}
+
+static void __cpuinit cacheinfo_create_index_dir(struct cache *cache, int index, struct cache_dir *cache_dir)
+{
+ struct cache_index_dir *index_dir;
+ int rc;
+
+ index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL);
+ if (!index_dir)
+ goto err;
+
+ index_dir->cache = cache;
+
+ rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type,
+ cache_dir->kobj, "index%d", index);
+ if (rc)
+ goto err;
+
+ index_dir->next = cache_dir->index;
+ cache_dir->index = index_dir;
+
+ cacheinfo_create_index_opt_attrs(index_dir);
+
+ return;
+err:
+ kfree(index_dir);
+}
+
+static void __cpuinit cacheinfo_sysfs_populate(unsigned int cpu_id, struct cache *cache_list)
+{
+ struct cache_dir *cache_dir;
+ struct cache *cache;
+ int index = 0;
+
+ cache_dir = cacheinfo_create_cache_dir(cpu_id);
+ if (!cache_dir)
+ return;
+
+ cache = cache_list;
+ while (cache) {
+ cacheinfo_create_index_dir(cache, index, cache_dir);
+ index++;
+ cache = cache->next_local;
+ }
+}
+
+void __cpuinit cacheinfo_cpu_online(unsigned int cpu_id)
+{
+ struct cache *cache;
+
+ cache = cache_chain_instantiate(cpu_id);
+ if (!cache)
+ return;
+
+ cacheinfo_sysfs_populate(cpu_id, cache);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU /* functions needed for cpu offline */
+
+static struct cache *cache_lookup_by_cpu(unsigned int cpu_id)
+{
+ struct device_node *cpu_node;
+ struct cache *cache;
+
+ cpu_node = of_get_cpu_node(cpu_id, NULL);
+ WARN_ONCE(!cpu_node, "no OF node found for CPU %i\n", cpu_id);
+ if (!cpu_node)
+ return NULL;
+
+ cache = cache_lookup_by_node(cpu_node);
+ of_node_put(cpu_node);
+
+ return cache;
+}
+
+static void remove_index_dirs(struct cache_dir *cache_dir)
+{
+ struct cache_index_dir *index;
+
+ index = cache_dir->index;
+
+ while (index) {
+ struct cache_index_dir *next;
+
+ next = index->next;
+ kobject_put(&index->kobj);
+ index = next;
+ }
+}
+
+static void remove_cache_dir(struct cache_dir *cache_dir)
+{
+ remove_index_dirs(cache_dir);
+
+ kobject_put(cache_dir->kobj);
+
+ kfree(cache_dir);
+}
+
+static void cache_cpu_clear(struct cache *cache, int cpu)
+{
+ while (cache) {
+ struct cache *next = cache->next_local;
+
+ WARN_ONCE(!cpumask_test_cpu(cpu, &cache->shared_cpu_map),
+ "CPU %i not accounted in %s(%s)\n",
+ cpu, cache->ofnode->full_name,
+ cache_type_string(cache));
+
+ cpumask_clear_cpu(cpu, &cache->shared_cpu_map);
+
+ /* Release the cache object if all the cpus using it
+ * are offline */
+ if (cpumask_empty(&cache->shared_cpu_map))
+ release_cache(cache);
+
+ cache = next;
+ }
+}
+
+void cacheinfo_cpu_offline(unsigned int cpu_id)
+{
+ struct cache_dir *cache_dir;
+ struct cache *cache;
+
+ /* Prevent userspace from seeing inconsistent state - remove
+ * the sysfs hierarchy first */
+ cache_dir = per_cpu(cache_dir_pcpu, cpu_id);
+
+ /* careful, sysfs population may have failed */
+ if (cache_dir)
+ remove_cache_dir(cache_dir);
+
+ per_cpu(cache_dir_pcpu, cpu_id) = NULL;
+
+ /* clear the CPU's bit in its cache chain, possibly freeing
+ * cache objects */
+ cache = cache_lookup_by_cpu(cpu_id);
+ if (cache)
+ cache_cpu_clear(cache, cpu_id);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/powerpc/kernel/cacheinfo.h b/arch/powerpc/kernel/cacheinfo.h
new file mode 100644
index 000000000000..a7b74d36acd7
--- /dev/null
+++ b/arch/powerpc/kernel/cacheinfo.h
@@ -0,0 +1,8 @@
+#ifndef _PPC_CACHEINFO_H
+#define _PPC_CACHEINFO_H
+
+/* These are just hooks for sysfs.c to use. */
+extern void cacheinfo_cpu_online(unsigned int cpu_id);
+extern void cacheinfo_cpu_offline(unsigned int cpu_id);
+
+#endif /* _PPC_CACHEINFO_H */
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 14183af1b3fb..2983adac8cc3 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -79,10 +79,10 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
"Warning: IOMMU offset too big for device mask\n");
if (tbl)
printk(KERN_INFO
- "mask: 0x%08lx, table offset: 0x%08lx\n",
+ "mask: 0x%08llx, table offset: 0x%08lx\n",
mask, tbl->it_offset);
else
- printk(KERN_INFO "mask: 0x%08lx, table unavailable\n",
+ printk(KERN_INFO "mask: 0x%08llx, table unavailable\n",
mask);
return 0;
} else
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index b4bcf5a930fa..ebaedafc8e67 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1518,6 +1518,15 @@ _GLOBAL(pmac_secondary_start)
/* turn on 64-bit mode */
bl .enable_64b_mode
+ li r0,0
+ mfspr r3,SPRN_HID4
+ rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */
+ sync
+ mtspr SPRN_HID4,r3
+ isync
+ sync
+ slbia
+
/* get TOC pointer (real address) */
bl .relative_toc
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 11b549acc034..36ffb3504a4f 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -389,10 +389,6 @@ skpinv: addi r6,r6,1 /* Increment */
#endif
#endif
- mfspr r3,SPRN_TLB1CFG
- andi. r3,r3,0xfff
- lis r4,num_tlbcam_entries@ha
- stw r3,num_tlbcam_entries@l(r4)
/*
* Decide what sort of machine this is and initialize the MMU.
*/
@@ -711,7 +707,7 @@ interrupt_base:
EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
#ifdef CONFIG_PPC_E500MC
- EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_EE)
+ EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD)
#endif
/* Debug Interrupt */
@@ -909,7 +905,7 @@ KernelSPE:
_GLOBAL(loadcam_entry)
lis r4,TLBCAM@ha
addi r4,r4,TLBCAM@l
- mulli r5,r3,20
+ mulli r5,r3,TLBCAM_SIZE
add r3,r5,r4
lwz r4,0(r3)
mtspr SPRN_MAS0,r4
diff --git a/arch/powerpc/kernel/init_task.c b/arch/powerpc/kernel/init_task.c
index 4c85b8d56478..688b329800bd 100644
--- a/arch/powerpc/kernel/init_task.c
+++ b/arch/powerpc/kernel/init_task.c
@@ -7,7 +7,6 @@
#include <linux/mqueue.h>
#include <asm/uaccess.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 1bfa706b96e7..fd51578e29dd 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -239,12 +239,12 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
if (printk_ratelimit()) {
printk(KERN_INFO "iommu_free: invalid entry\n");
printk(KERN_INFO "\tentry = 0x%lx\n", entry);
- printk(KERN_INFO "\tdma_addr = 0x%lx\n", (u64)dma_addr);
- printk(KERN_INFO "\tTable = 0x%lx\n", (u64)tbl);
- printk(KERN_INFO "\tbus# = 0x%lx\n", (u64)tbl->it_busno);
- printk(KERN_INFO "\tsize = 0x%lx\n", (u64)tbl->it_size);
- printk(KERN_INFO "\tstartOff = 0x%lx\n", (u64)tbl->it_offset);
- printk(KERN_INFO "\tindex = 0x%lx\n", (u64)tbl->it_index);
+ printk(KERN_INFO "\tdma_addr = 0x%llx\n", (u64)dma_addr);
+ printk(KERN_INFO "\tTable = 0x%llx\n", (u64)tbl);
+ printk(KERN_INFO "\tbus# = 0x%llx\n", (u64)tbl->it_busno);
+ printk(KERN_INFO "\tsize = 0x%llx\n", (u64)tbl->it_size);
+ printk(KERN_INFO "\tstartOff = 0x%llx\n", (u64)tbl->it_offset);
+ printk(KERN_INFO "\tindex = 0x%llx\n", (u64)tbl->it_index);
WARN_ON(1);
}
return;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index ac222d0ab12e..23b8b5e36f98 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -237,7 +237,7 @@ void fixup_irqs(cpumask_t map)
mask = map;
}
if (irq_desc[irq].chip->set_affinity)
- irq_desc[irq].chip->set_affinity(irq, mask);
+ irq_desc[irq].chip->set_affinity(irq, &mask);
else if (irq_desc[irq].action && !(warned++))
printk("Cannot set affinity for irq %i\n", irq);
}
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index de79915452c8..c9329786073b 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -96,9 +96,10 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
- mutex_lock(&kprobe_mutex);
- free_insn_slot(p->ainsn.insn, 0);
- mutex_unlock(&kprobe_mutex);
+ if (p->ainsn.insn) {
+ free_insn_slot(p->ainsn.insn, 0);
+ p->ainsn.insn = NULL;
+ }
}
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -316,7 +317,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
/*
* It is possible to have multiple instances associated with a given
* task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
+ * have a return probe installed on them, and/or more than one return
* return probe was registered for a target function.
*
* We can handle this because:
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index d051e8cbcd03..182e0f642f36 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -240,7 +240,7 @@ static void parse_ppp_data(struct seq_file *m)
if (rc)
return;
- seq_printf(m, "partition_entitled_capacity=%ld\n",
+ seq_printf(m, "partition_entitled_capacity=%lld\n",
ppp_data.entitlement);
seq_printf(m, "group=%d\n", ppp_data.group_num);
seq_printf(m, "system_active_processors=%d\n",
@@ -265,7 +265,7 @@ static void parse_ppp_data(struct seq_file *m)
ppp_data.unallocated_weight);
seq_printf(m, "capacity_weight=%d\n", ppp_data.weight);
seq_printf(m, "capped=%d\n", ppp_data.capped);
- seq_printf(m, "unallocated_capacity=%ld\n",
+ seq_printf(m, "unallocated_capacity=%lld\n",
ppp_data.unallocated_entitlement);
}
@@ -509,10 +509,10 @@ static ssize_t update_ppp(u64 *entitlement, u8 *weight)
} else
return -EINVAL;
- pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
+ pr_debug("%s: current_entitled = %llu, current_weight = %u\n",
__func__, ppp_data.entitlement, ppp_data.weight);
- pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+ pr_debug("%s: new_entitled = %llu, new_weight = %u\n",
__func__, new_entitled, new_weight);
retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight);
@@ -558,7 +558,7 @@ static ssize_t update_mpp(u64 *entitlement, u8 *weight)
pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
__func__, mpp_data.entitled_mem, mpp_data.mem_weight);
- pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
+ pr_debug("%s: new_entitled = %llu, new_weight = %u\n",
__func__, new_entitled, new_weight);
rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight);
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index b3abebb7ee64..d59e2b1bdcba 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -93,10 +93,35 @@ void __init reserve_crashkernel(void)
KDUMP_KERNELBASE);
crashk_res.start = KDUMP_KERNELBASE;
+#else
+ if (!crashk_res.start) {
+ /*
+ * unspecified address, choose a region of specified size
+ * can overlap with initrd (ignoring corruption when retained)
+ * ppc64 requires kernel and some stacks to be in first segemnt
+ */
+ crashk_res.start = KDUMP_KERNELBASE;
+ }
+
+ crash_base = PAGE_ALIGN(crashk_res.start);
+ if (crash_base != crashk_res.start) {
+ printk("Crash kernel base must be aligned to 0x%lx\n",
+ PAGE_SIZE);
+ crashk_res.start = crash_base;
+ }
+
#endif
crash_size = PAGE_ALIGN(crash_size);
crashk_res.end = crashk_res.start + crash_size - 1;
+ /* The crash region must not overlap the current kernel */
+ if (overlaps_crashkernel(__pa(_stext), _end - _stext)) {
+ printk(KERN_WARNING
+ "Crash kernel can not overlap current kernel\n");
+ crashk_res.start = crashk_res.end = 0;
+ return;
+ }
+
/* Crash kernel trumps memory limit */
if (memory_limit && memory_limit <= crashk_res.end) {
memory_limit = crashk_res.end + 1;
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 2538030954d8..19b12d2cbb4b 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -16,8 +16,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#undef DEBUG
-
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/string.h>
@@ -258,7 +256,8 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
} else {
pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
oirq.size, oirq.specifier[0], oirq.specifier[1],
- oirq.controller->full_name);
+ oirq.controller ? oirq.controller->full_name :
+ "<default>");
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
@@ -1356,6 +1355,63 @@ static void __init pcibios_allocate_resources(int pass)
}
}
+static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus)
+{
+ struct pci_controller *hose = pci_bus_to_host(bus);
+ resource_size_t offset;
+ struct resource *res, *pres;
+ int i;
+
+ pr_debug("Reserving legacy ranges for domain %04x\n", pci_domain_nr(bus));
+
+ /* Check for IO */
+ if (!(hose->io_resource.flags & IORESOURCE_IO))
+ goto no_io;
+ offset = (unsigned long)hose->io_base_virt - _IO_BASE;
+ res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ BUG_ON(res == NULL);
+ res->name = "Legacy IO";
+ res->flags = IORESOURCE_IO;
+ res->start = offset;
+ res->end = (offset + 0xfff) & 0xfffffffful;
+ pr_debug("Candidate legacy IO: %pR\n", res);
+ if (request_resource(&hose->io_resource, res)) {
+ printk(KERN_DEBUG
+ "PCI %04x:%02x Cannot reserve Legacy IO %pR\n",
+ pci_domain_nr(bus), bus->number, res);
+ kfree(res);
+ }
+
+ no_io:
+ /* Check for memory */
+ offset = hose->pci_mem_offset;
+ pr_debug("hose mem offset: %016llx\n", (unsigned long long)offset);
+ for (i = 0; i < 3; i++) {
+ pres = &hose->mem_resources[i];
+ if (!(pres->flags & IORESOURCE_MEM))
+ continue;
+ pr_debug("hose mem res: %pR\n", pres);
+ if ((pres->start - offset) <= 0xa0000 &&
+ (pres->end - offset) >= 0xbffff)
+ break;
+ }
+ if (i >= 3)
+ return;
+ res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+ BUG_ON(res == NULL);
+ res->name = "Legacy VGA memory";
+ res->flags = IORESOURCE_MEM;
+ res->start = 0xa0000 + offset;
+ res->end = 0xbffff + offset;
+ pr_debug("Candidate VGA memory: %pR\n", res);
+ if (request_resource(pres, res)) {
+ printk(KERN_DEBUG
+ "PCI %04x:%02x Cannot reserve VGA memory %pR\n",
+ pci_domain_nr(bus), bus->number, res);
+ kfree(res);
+ }
+}
+
void __init pcibios_resource_survey(void)
{
struct pci_bus *b;
@@ -1371,6 +1427,18 @@ void __init pcibios_resource_survey(void)
pcibios_allocate_resources(1);
}
+ /* Before we start assigning unassigned resource, we try to reserve
+ * the low IO area and the VGA memory area if they intersect the
+ * bus available resources to avoid allocating things on top of them
+ */
+ if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
+ list_for_each_entry(b, &pci_root_buses, node)
+ pcibios_reserve_legacy_regions(b);
+ }
+
+ /* Now, if the platform didn't decide to blindly trust the firmware,
+ * we proceed to assigning things that were left unassigned
+ */
if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
pr_debug("PCI: Assigning unassigned resouces...\n");
pci_assign_unassigned_resources();
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 39fadc6e1492..ea8eda8c87cf 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -470,7 +470,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
if (bus->self) {
pr_debug("IO mapping for PCI-PCI bridge %s\n",
pci_name(bus->self));
- pr_debug(" virt=0x%016lx...0x%016lx\n",
+ pr_debug(" virt=0x%016llx...0x%016llx\n",
bus->resource[0]->start + _IO_BASE,
bus->resource[0]->end + _IO_BASE);
return 0;
@@ -502,7 +502,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
hose->io_base_phys - phys_page);
pr_debug("IO mapping for PHB %s\n", hose->dn->full_name);
- pr_debug(" phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
+ pr_debug(" phys=0x%016llx, virt=0x%p (alloc=0x%p)\n",
hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
pr_debug(" size=0x%016lx (alloc=0x%016lx)\n",
hose->pci_io_size, size_page);
@@ -517,7 +517,7 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
hose->io_resource.start += io_virt_offset;
hose->io_resource.end += io_virt_offset;
- pr_debug(" hose->io_resource=0x%016lx...0x%016lx\n",
+ pr_debug(" hose->io_resource=0x%016llx...0x%016llx\n",
hose->io_resource.start, hose->io_resource.end);
return 0;
@@ -560,9 +560,14 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
* G5 machines... So when something asks for bus 0 io base
* (bus 0 is HT root), we return the AGP one instead.
*/
- if (machine_is_compatible("MacRISC4"))
- if (in_bus == 0)
+ if (in_bus == 0 && machine_is_compatible("MacRISC4")) {
+ struct device_node *agp;
+
+ agp = of_find_compatible_node(NULL, NULL, "u3-agp");
+ if (agp)
in_bus = 0xf0;
+ of_node_put(agp);
+ }
/* That syscall isn't quite compatible with PCI domains, but it's
* used on pre-domains setup. We return the first match
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index dcec1325d340..c8b27bb4dbde 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -165,6 +165,7 @@ EXPORT_SYMBOL(timer_interrupt);
EXPORT_SYMBOL(irq_desc);
EXPORT_SYMBOL(tb_ticks_per_jiffy);
EXPORT_SYMBOL(cacheable_memcpy);
+EXPORT_SYMBOL(cacheable_memzero);
#endif
#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 51b201ddf9a1..fb7049c054c0 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -33,6 +33,7 @@
#include <linux/mqueue.h>
#include <linux/hardirq.h>
#include <linux/utsname.h>
+#include <linux/kernel_stat.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 6f73c739f1e2..f00f83109ab3 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -590,6 +590,11 @@ static void __init check_cpu_slb_size(unsigned long node)
{
u32 *slb_size_ptr;
+ slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL);
+ if (slb_size_ptr != NULL) {
+ mmu_slb_size = *slb_size_ptr;
+ return;
+ }
slb_size_ptr = of_get_flat_dt_prop(node, "ibm,slb-size", NULL);
if (slb_size_ptr != NULL) {
mmu_slb_size = *slb_size_ptr;
@@ -824,11 +829,11 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
#endif
#ifdef CONFIG_KEXEC
- lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
+ lprop = of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
if (lprop)
crashk_res.start = *lprop;
- lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL);
+ lprop = of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL);
if (lprop)
crashk_res.end = crashk_res.start + *lprop - 1;
#endif
@@ -893,12 +898,12 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
u64 base, size, lmb_size;
unsigned int is_kexec_kdump = 0, rngs;
- ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
+ ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))
return 0;
lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);
- dm = (cell_t *)of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
+ dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
if (dm == NULL || l < sizeof(cell_t))
return 0;
@@ -907,7 +912,7 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
return 0;
/* check if this is a kexec/kdump kernel. */
- usm = (cell_t *)of_get_flat_dt_prop(node, "linux,drconf-usable-memory",
+ usm = of_get_flat_dt_prop(node, "linux,drconf-usable-memory",
&l);
if (usm != NULL)
is_kexec_kdump = 1;
@@ -981,9 +986,9 @@ static int __init early_init_dt_scan_memory(unsigned long node,
} else if (strcmp(type, "memory") != 0)
return 0;
- reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+ reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
if (reg == NULL)
- reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
+ reg = of_get_flat_dt_prop(node, "reg", &l);
if (reg == NULL)
return 0;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 2445945d3761..7f1b33d5e30d 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1210,7 +1210,7 @@ static void __init prom_initialize_tce_table(void)
/* Initialize the table to have a one-to-one mapping
* over the allocated size.
*/
- tce_entryp = (unsigned long *)base;
+ tce_entryp = (u64 *)base;
for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
tce_entry = (i << PAGE_SHIFT);
tce_entry |= 0x3;
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 8c1335566089..8f0856f312da 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -232,11 +232,6 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
- return (((pin - 1) + slot) % 4) + 1;
-}
-
int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
{
struct device_node *dn, *ppnode;
@@ -306,7 +301,7 @@ int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
/* We can only get here if we hit a P2P bridge with no node,
* let's do standard swizzling and try again
*/
- lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+ lspec = pci_swizzle_interrupt_pin(pdev, lspec);
pdev = ppdev;
}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index d8bd2161e738..2d34196bba8c 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -434,8 +434,8 @@ void __init setup_system(void)
printk("Starting Linux PPC64 %s\n", init_utsname()->version);
printk("-----------------------------------------------------\n");
- printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
- printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size());
+ printk("ppc64_pft_size = 0x%llx\n", ppc64_pft_size);
+ printk("physicalMemorySize = 0x%llx\n", lmb_phys_mem_size());
if (ppc64_caches.dline_size != 0x80)
printk("ppc64_caches.dcache_line_size = 0x%x\n",
ppc64_caches.dline_size);
@@ -493,7 +493,7 @@ static void __init emergency_stack_init(void)
* bringup, we need to get at them in real mode. This means they
* must also be within the RMO region.
*/
- limit = min(0x10000000UL, lmb.rmo_size);
+ limit = min(0x10000000ULL, lmb.rmo_size);
for_each_possible_cpu(i) {
unsigned long sp;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 8ac3f721d235..65484b2200b3 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -59,13 +59,9 @@
struct thread_info *secondary_ti;
-cpumask_t cpu_possible_map = CPU_MASK_NONE;
-cpumask_t cpu_online_map = CPU_MASK_NONE;
DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
DEFINE_PER_CPU(cpumask_t, cpu_core_map) = CPU_MASK_NONE;
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_possible_map);
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
EXPORT_PER_CPU_SYMBOL(cpu_core_map);
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 0c64f10087b9..4a2ee08af6a7 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -18,6 +18,8 @@
#include <asm/machdep.h>
#include <asm/smp.h>
+#include "cacheinfo.h"
+
#ifdef CONFIG_PPC64
#include <asm/paca.h>
#include <asm/lppaca.h>
@@ -25,8 +27,6 @@
static DEFINE_PER_CPU(struct cpu, cpu_devices);
-static DEFINE_PER_CPU(struct kobject *, cache_toplevel);
-
/*
* SMT snooze delay stuff, 64-bit only for now
*/
@@ -343,283 +343,6 @@ static struct sysdev_attribute pa6t_attrs[] = {
#endif /* HAS_PPC_PMC_PA6T */
#endif /* HAS_PPC_PMC_CLASSIC */
-struct cache_desc {
- struct kobject kobj;
- struct cache_desc *next;
- const char *type; /* Instruction, Data, or Unified */
- u32 size; /* total cache size in KB */
- u32 line_size; /* in bytes */
- u32 nr_sets; /* number of sets */
- u32 level; /* e.g. 1, 2, 3... */
- u32 associativity; /* e.g. 8-way... 0 is fully associative */
-};
-
-DEFINE_PER_CPU(struct cache_desc *, cache_desc);
-
-static struct cache_desc *kobj_to_cache_desc(struct kobject *k)
-{
- return container_of(k, struct cache_desc, kobj);
-}
-
-static void cache_desc_release(struct kobject *k)
-{
- struct cache_desc *desc = kobj_to_cache_desc(k);
-
- pr_debug("%s: releasing %s\n", __func__, kobject_name(k));
-
- if (desc->next)
- kobject_put(&desc->next->kobj);
-
- kfree(kobj_to_cache_desc(k));
-}
-
-static ssize_t cache_desc_show(struct kobject *k, struct attribute *attr, char *buf)
-{
- struct kobj_attribute *kobj_attr;
-
- kobj_attr = container_of(attr, struct kobj_attribute, attr);
-
- return kobj_attr->show(k, kobj_attr, buf);
-}
-
-static struct sysfs_ops cache_desc_sysfs_ops = {
- .show = cache_desc_show,
-};
-
-static struct kobj_type cache_desc_type = {
- .release = cache_desc_release,
- .sysfs_ops = &cache_desc_sysfs_ops,
-};
-
-static ssize_t cache_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
- struct cache_desc *cache = kobj_to_cache_desc(k);
-
- return sprintf(buf, "%uK\n", cache->size);
-}
-
-static struct kobj_attribute cache_size_attr =
- __ATTR(size, 0444, cache_size_show, NULL);
-
-static ssize_t cache_line_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
- struct cache_desc *cache = kobj_to_cache_desc(k);
-
- return sprintf(buf, "%u\n", cache->line_size);
-}
-
-static struct kobj_attribute cache_line_size_attr =
- __ATTR(coherency_line_size, 0444, cache_line_size_show, NULL);
-
-static ssize_t cache_nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
- struct cache_desc *cache = kobj_to_cache_desc(k);
-
- return sprintf(buf, "%u\n", cache->nr_sets);
-}
-
-static struct kobj_attribute cache_nr_sets_attr =
- __ATTR(number_of_sets, 0444, cache_nr_sets_show, NULL);
-
-static ssize_t cache_type_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
- struct cache_desc *cache = kobj_to_cache_desc(k);
-
- return sprintf(buf, "%s\n", cache->type);
-}
-
-static struct kobj_attribute cache_type_attr =
- __ATTR(type, 0444, cache_type_show, NULL);
-
-static ssize_t cache_level_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
- struct cache_desc *cache = kobj_to_cache_desc(k);
-
- return sprintf(buf, "%u\n", cache->level);
-}
-
-static struct kobj_attribute cache_level_attr =
- __ATTR(level, 0444, cache_level_show, NULL);
-
-static ssize_t cache_assoc_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
- struct cache_desc *cache = kobj_to_cache_desc(k);
-
- return sprintf(buf, "%u\n", cache->associativity);
-}
-
-static struct kobj_attribute cache_assoc_attr =
- __ATTR(ways_of_associativity, 0444, cache_assoc_show, NULL);
-
-struct cache_desc_info {
- const char *type;
- const char *size_prop;
- const char *line_size_prop;
- const char *nr_sets_prop;
-};
-
-/* PowerPC Processor binding says the [di]-cache-* must be equal on
- * unified caches, so just use d-cache properties. */
-static struct cache_desc_info ucache_info = {
- .type = "Unified",
- .size_prop = "d-cache-size",
- .line_size_prop = "d-cache-line-size",
- .nr_sets_prop = "d-cache-sets",
-};
-
-static struct cache_desc_info dcache_info = {
- .type = "Data",
- .size_prop = "d-cache-size",
- .line_size_prop = "d-cache-line-size",
- .nr_sets_prop = "d-cache-sets",
-};
-
-static struct cache_desc_info icache_info = {
- .type = "Instruction",
- .size_prop = "i-cache-size",
- .line_size_prop = "i-cache-line-size",
- .nr_sets_prop = "i-cache-sets",
-};
-
-static struct cache_desc * __cpuinit create_cache_desc(struct device_node *np, struct kobject *parent, int index, int level, struct cache_desc_info *info)
-{
- const u32 *cache_line_size;
- struct cache_desc *new;
- const u32 *cache_size;
- const u32 *nr_sets;
- int rc;
-
- new = kzalloc(sizeof(*new), GFP_KERNEL);
- if (!new)
- return NULL;
-
- rc = kobject_init_and_add(&new->kobj, &cache_desc_type, parent,
- "index%d", index);
- if (rc)
- goto err;
-
- /* type */
- new->type = info->type;
- rc = sysfs_create_file(&new->kobj, &cache_type_attr.attr);
- WARN_ON(rc);
-
- /* level */
- new->level = level;
- rc = sysfs_create_file(&new->kobj, &cache_level_attr.attr);
- WARN_ON(rc);
-
- /* size */
- cache_size = of_get_property(np, info->size_prop, NULL);
- if (cache_size) {
- new->size = *cache_size / 1024;
- rc = sysfs_create_file(&new->kobj,
- &cache_size_attr.attr);
- WARN_ON(rc);
- }
-
- /* coherency_line_size */
- cache_line_size = of_get_property(np, info->line_size_prop, NULL);
- if (cache_line_size) {
- new->line_size = *cache_line_size;
- rc = sysfs_create_file(&new->kobj,
- &cache_line_size_attr.attr);
- WARN_ON(rc);
- }
-
- /* number_of_sets */
- nr_sets = of_get_property(np, info->nr_sets_prop, NULL);
- if (nr_sets) {
- new->nr_sets = *nr_sets;
- rc = sysfs_create_file(&new->kobj,
- &cache_nr_sets_attr.attr);
- WARN_ON(rc);
- }
-
- /* ways_of_associativity */
- if (new->nr_sets == 1) {
- /* fully associative */
- new->associativity = 0;
- goto create_assoc;
- }
-
- if (new->nr_sets && new->size && new->line_size) {
- /* If we have values for all of these we can derive
- * the associativity. */
- new->associativity =
- ((new->size * 1024) / new->nr_sets) / new->line_size;
-create_assoc:
- rc = sysfs_create_file(&new->kobj,
- &cache_assoc_attr.attr);
- WARN_ON(rc);
- }
-
- return new;
-err:
- kfree(new);
- return NULL;
-}
-
-static bool cache_is_unified(struct device_node *np)
-{
- return of_get_property(np, "cache-unified", NULL);
-}
-
-static struct cache_desc * __cpuinit create_cache_index_info(struct device_node *np, struct kobject *parent, int index, int level)
-{
- struct device_node *next_cache;
- struct cache_desc *new, **end;
-
- pr_debug("%s(node = %s, index = %d)\n", __func__, np->full_name, index);
-
- if (cache_is_unified(np)) {
- new = create_cache_desc(np, parent, index, level,
- &ucache_info);
- } else {
- new = create_cache_desc(np, parent, index, level,
- &dcache_info);
- if (new) {
- index++;
- new->next = create_cache_desc(np, parent, index, level,
- &icache_info);
- }
- }
- if (!new)
- return NULL;
-
- end = &new->next;
- while (*end)
- end = &(*end)->next;
-
- next_cache = of_find_next_cache_node(np);
- if (!next_cache)
- goto out;
-
- *end = create_cache_index_info(next_cache, parent, ++index, ++level);
-
- of_node_put(next_cache);
-out:
- return new;
-}
-
-static void __cpuinit create_cache_info(struct sys_device *sysdev)
-{
- struct kobject *cache_toplevel;
- struct device_node *np = NULL;
- int cpu = sysdev->id;
-
- cache_toplevel = kobject_create_and_add("cache", &sysdev->kobj);
- if (!cache_toplevel)
- return;
- per_cpu(cache_toplevel, cpu) = cache_toplevel;
- np = of_get_cpu_node(cpu, NULL);
- if (np != NULL) {
- per_cpu(cache_desc, cpu) =
- create_cache_index_info(np, cache_toplevel, 0, 1);
- of_node_put(np);
- }
- return;
-}
-
static void __cpuinit register_cpu_online(unsigned int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
@@ -684,25 +407,10 @@ static void __cpuinit register_cpu_online(unsigned int cpu)
sysdev_create_file(s, &attr_dscr);
#endif /* CONFIG_PPC64 */
- create_cache_info(s);
+ cacheinfo_cpu_online(cpu);
}
#ifdef CONFIG_HOTPLUG_CPU
-static void remove_cache_info(struct sys_device *sysdev)
-{
- struct kobject *cache_toplevel;
- struct cache_desc *cache_desc;
- int cpu = sysdev->id;
-
- cache_desc = per_cpu(cache_desc, cpu);
- if (cache_desc != NULL)
- kobject_put(&cache_desc->kobj);
-
- cache_toplevel = per_cpu(cache_toplevel, cpu);
- if (cache_toplevel != NULL)
- kobject_put(cache_toplevel);
-}
-
static void unregister_cpu_online(unsigned int cpu)
{
struct cpu *c = &per_cpu(cpu_devices, cpu);
@@ -769,7 +477,7 @@ static void unregister_cpu_online(unsigned int cpu)
sysdev_remove_file(s, &attr_dscr);
#endif /* CONFIG_PPC64 */
- remove_cache_info(s);
+ cacheinfo_cpu_offline(cpu);
}
#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index e1f3a5140429..c9564031a2a9 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -256,8 +256,10 @@ void account_system_vtime(struct task_struct *tsk)
delta += sys_time;
get_paca()->system_time = 0;
}
- account_system_time(tsk, 0, delta);
- account_system_time_scaled(tsk, deltascaled);
+ if (in_irq() || idle_task(smp_processor_id()) != tsk)
+ account_system_time(tsk, 0, delta, deltascaled);
+ else
+ account_idle_time(delta);
per_cpu(cputime_last_delta, smp_processor_id()) = delta;
per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
local_irq_restore(flags);
@@ -275,10 +277,8 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
utime = get_paca()->user_time;
get_paca()->user_time = 0;
- account_user_time(tsk, utime);
-
utimescaled = cputime_to_scaled(utime);
- account_user_time_scaled(tsk, utimescaled);
+ account_user_time(tsk, utime, utimescaled);
}
/*
@@ -338,8 +338,12 @@ void calculate_steal_time(void)
tb = mftb();
purr = mfspr(SPRN_PURR);
stolen = (tb - pme->tb) - (purr - pme->purr);
- if (stolen > 0)
- account_steal_time(current, stolen);
+ if (stolen > 0) {
+ if (idle_task(smp_processor_id()) != current)
+ account_steal_time(stolen);
+ else
+ account_idle_time(stolen);
+ }
pme->tb = tb;
pme->purr = purr;
}
@@ -844,7 +848,7 @@ static void register_decrementer_clockevent(int cpu)
struct clock_event_device *dec = &per_cpu(decrementers, cpu).event;
*dec = decrementer_clockevent;
- dec->cpumask = cpumask_of_cpu(cpu);
+ dec->cpumask = cpumask_of(cpu);
printk(KERN_DEBUG "clockevent: %s mult[%lx] shift[%d] cpu[%d]\n",
dec->name, dec->mult, dec->shift, cpu);
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 94aa7b011b27..d3694498f3af 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -492,14 +492,14 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
struct vio_dev *viodev = to_vio_dev(dev);
void *ret;
- if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE))) {
+ if (vio_cmo_alloc(viodev, roundup(size, PAGE_SIZE))) {
atomic_inc(&viodev->cmo.allocs_failed);
return NULL;
}
ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag);
if (unlikely(ret == NULL)) {
- vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+ vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
atomic_inc(&viodev->cmo.allocs_failed);
}
@@ -513,7 +513,7 @@ static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle);
- vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE));
+ vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
}
static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
@@ -572,6 +572,7 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
if (unlikely(!ret)) {
vio_cmo_dealloc(viodev, alloc_size);
atomic_inc(&viodev->cmo.allocs_failed);
+ return ret;
}
for (sgl = sglist, count = 0; count < ret; count++, sgl++)
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 47bf15cd2c9e..161b9b9691f0 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -87,7 +87,9 @@ SECTIONS
/* The dummy segment contents for the bug workaround mentioned above
near PHDRS. */
.dummy : AT(ADDR(.dummy) - LOAD_OFFSET) {
- LONG(0xf177)
+ LONG(0)
+ LONG(0)
+ LONG(0)
} :kernel :dummy
/*
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
new file mode 100644
index 000000000000..a66bec57265a
--- /dev/null
+++ b/arch/powerpc/kvm/44x.c
@@ -0,0 +1,228 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/err.h>
+
+#include <asm/reg.h>
+#include <asm/cputable.h>
+#include <asm/tlbflush.h>
+#include <asm/kvm_44x.h>
+#include <asm/kvm_ppc.h>
+
+#include "44x_tlb.h"
+
+/* Note: clearing MSR[DE] just means that the debug interrupt will not be
+ * delivered *immediately*. Instead, it simply sets the appropriate DBSR bits.
+ * If those DBSR bits are still set when MSR[DE] is re-enabled, the interrupt
+ * will be delivered as an "imprecise debug event" (which is indicated by
+ * DBSR[IDE].
+ */
+static void kvm44x_disable_debug_interrupts(void)
+{
+ mtmsr(mfmsr() & ~MSR_DE);
+}
+
+void kvmppc_core_load_host_debugstate(struct kvm_vcpu *vcpu)
+{
+ kvm44x_disable_debug_interrupts();
+
+ mtspr(SPRN_IAC1, vcpu->arch.host_iac[0]);
+ mtspr(SPRN_IAC2, vcpu->arch.host_iac[1]);
+ mtspr(SPRN_IAC3, vcpu->arch.host_iac[2]);
+ mtspr(SPRN_IAC4, vcpu->arch.host_iac[3]);
+ mtspr(SPRN_DBCR1, vcpu->arch.host_dbcr1);
+ mtspr(SPRN_DBCR2, vcpu->arch.host_dbcr2);
+ mtspr(SPRN_DBCR0, vcpu->arch.host_dbcr0);
+ mtmsr(vcpu->arch.host_msr);
+}
+
+void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
+{
+ struct kvm_guest_debug *dbg = &vcpu->guest_debug;
+ u32 dbcr0 = 0;
+
+ vcpu->arch.host_msr = mfmsr();
+ kvm44x_disable_debug_interrupts();
+
+ /* Save host debug register state. */
+ vcpu->arch.host_iac[0] = mfspr(SPRN_IAC1);
+ vcpu->arch.host_iac[1] = mfspr(SPRN_IAC2);
+ vcpu->arch.host_iac[2] = mfspr(SPRN_IAC3);
+ vcpu->arch.host_iac[3] = mfspr(SPRN_IAC4);
+ vcpu->arch.host_dbcr0 = mfspr(SPRN_DBCR0);
+ vcpu->arch.host_dbcr1 = mfspr(SPRN_DBCR1);
+ vcpu->arch.host_dbcr2 = mfspr(SPRN_DBCR2);
+
+ /* set registers up for guest */
+
+ if (dbg->bp[0]) {
+ mtspr(SPRN_IAC1, dbg->bp[0]);
+ dbcr0 |= DBCR0_IAC1 | DBCR0_IDM;
+ }
+ if (dbg->bp[1]) {
+ mtspr(SPRN_IAC2, dbg->bp[1]);
+ dbcr0 |= DBCR0_IAC2 | DBCR0_IDM;
+ }
+ if (dbg->bp[2]) {
+ mtspr(SPRN_IAC3, dbg->bp[2]);
+ dbcr0 |= DBCR0_IAC3 | DBCR0_IDM;
+ }
+ if (dbg->bp[3]) {
+ mtspr(SPRN_IAC4, dbg->bp[3]);
+ dbcr0 |= DBCR0_IAC4 | DBCR0_IDM;
+ }
+
+ mtspr(SPRN_DBCR0, dbcr0);
+ mtspr(SPRN_DBCR1, 0);
+ mtspr(SPRN_DBCR2, 0);
+}
+
+void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+ kvmppc_44x_tlb_load(vcpu);
+}
+
+void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
+{
+ kvmppc_44x_tlb_put(vcpu);
+}
+
+int kvmppc_core_check_processor_compat(void)
+{
+ int r;
+
+ if (strcmp(cur_cpu_spec->platform, "ppc440") == 0)
+ r = 0;
+ else
+ r = -ENOTSUPP;
+
+ return r;
+}
+
+int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0];
+ int i;
+
+ tlbe->tid = 0;
+ tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
+ tlbe->word1 = 0;
+ tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR;
+
+ tlbe++;
+ tlbe->tid = 0;
+ tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID;
+ tlbe->word1 = 0xef600000;
+ tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR
+ | PPC44x_TLB_I | PPC44x_TLB_G;
+
+ /* Since the guest can directly access the timebase, it must know the
+ * real timebase frequency. Accordingly, it must see the state of
+ * CCR1[TCS]. */
+ vcpu->arch.ccr1 = mfspr(SPRN_CCR1);
+
+ for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
+ vcpu_44x->shadow_refs[i].gtlb_index = -1;
+
+ return 0;
+}
+
+/* 'linear_address' is actually an encoding of AS|PID|EADDR . */
+int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
+ struct kvm_translation *tr)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ struct kvmppc_44x_tlbe *gtlbe;
+ int index;
+ gva_t eaddr;
+ u8 pid;
+ u8 as;
+
+ eaddr = tr->linear_address;
+ pid = (tr->linear_address >> 32) & 0xff;
+ as = (tr->linear_address >> 40) & 0x1;
+
+ index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as);
+ if (index == -1) {
+ tr->valid = 0;
+ return 0;
+ }
+
+ gtlbe = &vcpu_44x->guest_tlb[index];
+
+ tr->physical_address = tlb_xlate(gtlbe, eaddr);
+ /* XXX what does "writeable" and "usermode" even mean? */
+ tr->valid = 1;
+
+ return 0;
+}
+
+struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x;
+ struct kvm_vcpu *vcpu;
+ int err;
+
+ vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
+ if (!vcpu_44x) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ vcpu = &vcpu_44x->vcpu;
+ err = kvm_vcpu_init(vcpu, kvm, id);
+ if (err)
+ goto free_vcpu;
+
+ return vcpu;
+
+free_vcpu:
+ kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
+out:
+ return ERR_PTR(err);
+}
+
+void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+
+ kvm_vcpu_uninit(vcpu);
+ kmem_cache_free(kvm_vcpu_cache, vcpu_44x);
+}
+
+static int kvmppc_44x_init(void)
+{
+ int r;
+
+ r = kvmppc_booke_init();
+ if (r)
+ return r;
+
+ return kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), THIS_MODULE);
+}
+
+static void kvmppc_44x_exit(void)
+{
+ kvmppc_booke_exit();
+}
+
+module_init(kvmppc_44x_init);
+module_exit(kvmppc_44x_exit);
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
new file mode 100644
index 000000000000..82489a743a6f
--- /dev/null
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -0,0 +1,371 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#include <asm/kvm_ppc.h>
+#include <asm/dcr.h>
+#include <asm/dcr-regs.h>
+#include <asm/disassemble.h>
+#include <asm/kvm_44x.h>
+#include "timing.h"
+
+#include "booke.h"
+#include "44x_tlb.h"
+
+#define OP_RFI 19
+
+#define XOP_RFI 50
+#define XOP_MFMSR 83
+#define XOP_WRTEE 131
+#define XOP_MTMSR 146
+#define XOP_WRTEEI 163
+#define XOP_MFDCR 323
+#define XOP_MTDCR 451
+#define XOP_TLBSX 914
+#define XOP_ICCCI 966
+#define XOP_TLBWE 978
+
+static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.pc = vcpu->arch.srr0;
+ kvmppc_set_msr(vcpu, vcpu->arch.srr1);
+}
+
+int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int inst, int *advance)
+{
+ int emulated = EMULATE_DONE;
+ int dcrn;
+ int ra;
+ int rb;
+ int rc;
+ int rs;
+ int rt;
+ int ws;
+
+ switch (get_op(inst)) {
+ case OP_RFI:
+ switch (get_xop(inst)) {
+ case XOP_RFI:
+ kvmppc_emul_rfi(vcpu);
+ kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS);
+ *advance = 0;
+ break;
+
+ default:
+ emulated = EMULATE_FAIL;
+ break;
+ }
+ break;
+
+ case 31:
+ switch (get_xop(inst)) {
+
+ case XOP_MFMSR:
+ rt = get_rt(inst);
+ vcpu->arch.gpr[rt] = vcpu->arch.msr;
+ kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
+ break;
+
+ case XOP_MTMSR:
+ rs = get_rs(inst);
+ kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS);
+ kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
+ break;
+
+ case XOP_WRTEE:
+ rs = get_rs(inst);
+ vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ | (vcpu->arch.gpr[rs] & MSR_EE);
+ kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
+ break;
+
+ case XOP_WRTEEI:
+ vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
+ | (inst & MSR_EE);
+ kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
+ break;
+
+ case XOP_MFDCR:
+ dcrn = get_dcrn(inst);
+ rt = get_rt(inst);
+
+ /* The guest may access CPR0 registers to determine the timebase
+ * frequency, and it must know the real host frequency because it
+ * can directly access the timebase registers.
+ *
+ * It would be possible to emulate those accesses in userspace,
+ * but userspace can really only figure out the end frequency.
+ * We could decompose that into the factors that compute it, but
+ * that's tricky math, and it's easier to just report the real
+ * CPR0 values.
+ */
+ switch (dcrn) {
+ case DCRN_CPR0_CONFIG_ADDR:
+ vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr;
+ break;
+ case DCRN_CPR0_CONFIG_DATA:
+ local_irq_disable();
+ mtdcr(DCRN_CPR0_CONFIG_ADDR,
+ vcpu->arch.cpr0_cfgaddr);
+ vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA);
+ local_irq_enable();
+ break;
+ default:
+ run->dcr.dcrn = dcrn;
+ run->dcr.data = 0;
+ run->dcr.is_write = 0;
+ vcpu->arch.io_gpr = rt;
+ vcpu->arch.dcr_needed = 1;
+ kvmppc_account_exit(vcpu, DCR_EXITS);
+ emulated = EMULATE_DO_DCR;
+ }
+
+ break;
+
+ case XOP_MTDCR:
+ dcrn = get_dcrn(inst);
+ rs = get_rs(inst);
+
+ /* emulate some access in kernel */
+ switch (dcrn) {
+ case DCRN_CPR0_CONFIG_ADDR:
+ vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs];
+ break;
+ default:
+ run->dcr.dcrn = dcrn;
+ run->dcr.data = vcpu->arch.gpr[rs];
+ run->dcr.is_write = 1;
+ vcpu->arch.dcr_needed = 1;
+ kvmppc_account_exit(vcpu, DCR_EXITS);
+ emulated = EMULATE_DO_DCR;
+ }
+
+ break;
+
+ case XOP_TLBWE:
+ ra = get_ra(inst);
+ rs = get_rs(inst);
+ ws = get_ws(inst);
+ emulated = kvmppc_44x_emul_tlbwe(vcpu, ra, rs, ws);
+ break;
+
+ case XOP_TLBSX:
+ rt = get_rt(inst);
+ ra = get_ra(inst);
+ rb = get_rb(inst);
+ rc = get_rc(inst);
+ emulated = kvmppc_44x_emul_tlbsx(vcpu, rt, ra, rb, rc);
+ break;
+
+ case XOP_ICCCI:
+ break;
+
+ default:
+ emulated = EMULATE_FAIL;
+ }
+
+ break;
+
+ default:
+ emulated = EMULATE_FAIL;
+ }
+
+ return emulated;
+}
+
+int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
+{
+ switch (sprn) {
+ case SPRN_MMUCR:
+ vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
+ case SPRN_PID:
+ kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break;
+ case SPRN_CCR0:
+ vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
+ case SPRN_CCR1:
+ vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break;
+ case SPRN_DEAR:
+ vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
+ case SPRN_ESR:
+ vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
+ case SPRN_DBCR0:
+ vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
+ case SPRN_DBCR1:
+ vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
+ case SPRN_TSR:
+ vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
+ case SPRN_TCR:
+ vcpu->arch.tcr = vcpu->arch.gpr[rs];
+ kvmppc_emulate_dec(vcpu);
+ break;
+
+ /* Note: SPRG4-7 are user-readable. These values are
+ * loaded into the real SPRGs when resuming the
+ * guest. */
+ case SPRN_SPRG4:
+ vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
+ case SPRN_SPRG5:
+ vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
+ case SPRN_SPRG6:
+ vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
+ case SPRN_SPRG7:
+ vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
+
+ case SPRN_IVPR:
+ vcpu->arch.ivpr = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR0:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR1:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR2:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR3:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR4:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR5:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR6:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR7:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR8:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR9:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR10:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR11:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR12:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR13:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR14:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs];
+ break;
+ case SPRN_IVOR15:
+ vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs];
+ break;
+
+ default:
+ return EMULATE_FAIL;
+ }
+
+ kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
+ return EMULATE_DONE;
+}
+
+int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
+{
+ switch (sprn) {
+ /* 440 */
+ case SPRN_MMUCR:
+ vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
+ case SPRN_CCR0:
+ vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break;
+ case SPRN_CCR1:
+ vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break;
+
+ /* Book E */
+ case SPRN_PID:
+ vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
+ case SPRN_IVPR:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
+ case SPRN_DEAR:
+ vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
+ case SPRN_ESR:
+ vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
+ case SPRN_DBCR0:
+ vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
+ case SPRN_DBCR1:
+ vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
+
+ case SPRN_IVOR0:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL];
+ break;
+ case SPRN_IVOR1:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK];
+ break;
+ case SPRN_IVOR2:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE];
+ break;
+ case SPRN_IVOR3:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE];
+ break;
+ case SPRN_IVOR4:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL];
+ break;
+ case SPRN_IVOR5:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT];
+ break;
+ case SPRN_IVOR6:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM];
+ break;
+ case SPRN_IVOR7:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL];
+ break;
+ case SPRN_IVOR8:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL];
+ break;
+ case SPRN_IVOR9:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL];
+ break;
+ case SPRN_IVOR10:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER];
+ break;
+ case SPRN_IVOR11:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT];
+ break;
+ case SPRN_IVOR12:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG];
+ break;
+ case SPRN_IVOR13:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS];
+ break;
+ case SPRN_IVOR14:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS];
+ break;
+ case SPRN_IVOR15:
+ vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
+ break;
+
+ default:
+ return EMULATE_FAIL;
+ }
+
+ kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
+ return EMULATE_DONE;
+}
+
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index ad72c6f9811f..9a34b8edb9e2 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -22,20 +22,103 @@
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <linux/highmem.h>
+
+#include <asm/tlbflush.h>
#include <asm/mmu-44x.h>
#include <asm/kvm_ppc.h>
+#include <asm/kvm_44x.h>
+#include "timing.h"
#include "44x_tlb.h"
+#ifndef PPC44x_TLBE_SIZE
+#define PPC44x_TLBE_SIZE PPC44x_TLB_4K
+#endif
+
+#define PAGE_SIZE_4K (1<<12)
+#define PAGE_MASK_4K (~(PAGE_SIZE_4K - 1))
+
+#define PPC44x_TLB_UATTR_MASK \
+ (PPC44x_TLB_U0|PPC44x_TLB_U1|PPC44x_TLB_U2|PPC44x_TLB_U3)
#define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW)
#define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW)
-static unsigned int kvmppc_tlb_44x_pos;
+#ifdef DEBUG
+void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_44x_tlbe *tlbe;
+ int i;
+
+ printk("vcpu %d TLB dump:\n", vcpu->vcpu_id);
+ printk("| %2s | %3s | %8s | %8s | %8s |\n",
+ "nr", "tid", "word0", "word1", "word2");
+
+ for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) {
+ tlbe = &vcpu_44x->guest_tlb[i];
+ if (tlbe->word0 & PPC44x_TLB_VALID)
+ printk(" G%2d | %02X | %08X | %08X | %08X |\n",
+ i, tlbe->tid, tlbe->word0, tlbe->word1,
+ tlbe->word2);
+ }
+}
+#endif
+
+static inline void kvmppc_44x_tlbie(unsigned int index)
+{
+ /* 0 <= index < 64, so the V bit is clear and we can use the index as
+ * word0. */
+ asm volatile(
+ "tlbwe %[index], %[index], 0\n"
+ :
+ : [index] "r"(index)
+ );
+}
+
+static inline void kvmppc_44x_tlbre(unsigned int index,
+ struct kvmppc_44x_tlbe *tlbe)
+{
+ asm volatile(
+ "tlbre %[word0], %[index], 0\n"
+ "mfspr %[tid], %[sprn_mmucr]\n"
+ "andi. %[tid], %[tid], 0xff\n"
+ "tlbre %[word1], %[index], 1\n"
+ "tlbre %[word2], %[index], 2\n"
+ : [word0] "=r"(tlbe->word0),
+ [word1] "=r"(tlbe->word1),
+ [word2] "=r"(tlbe->word2),
+ [tid] "=r"(tlbe->tid)
+ : [index] "r"(index),
+ [sprn_mmucr] "i"(SPRN_MMUCR)
+ : "cc"
+ );
+}
+
+static inline void kvmppc_44x_tlbwe(unsigned int index,
+ struct kvmppc_44x_tlbe *stlbe)
+{
+ unsigned long tmp;
+
+ asm volatile(
+ "mfspr %[tmp], %[sprn_mmucr]\n"
+ "rlwimi %[tmp], %[tid], 0, 0xff\n"
+ "mtspr %[sprn_mmucr], %[tmp]\n"
+ "tlbwe %[word0], %[index], 0\n"
+ "tlbwe %[word1], %[index], 1\n"
+ "tlbwe %[word2], %[index], 2\n"
+ : [tmp] "=&r"(tmp)
+ : [word0] "r"(stlbe->word0),
+ [word1] "r"(stlbe->word1),
+ [word2] "r"(stlbe->word2),
+ [tid] "r"(stlbe->tid),
+ [index] "r"(index),
+ [sprn_mmucr] "i"(SPRN_MMUCR)
+ );
+}
static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode)
{
- /* Mask off reserved bits. */
- attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_ATTR_MASK;
+ /* We only care about the guest's permission and user bits. */
+ attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_UATTR_MASK;
if (!usermode) {
/* Guest is in supervisor mode, so we need to translate guest
@@ -47,18 +130,60 @@ static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode)
/* Make sure host can always access this memory. */
attrib |= PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW;
+ /* WIMGE = 0b00100 */
+ attrib |= PPC44x_TLB_M;
+
return attrib;
}
+/* Load shadow TLB back into hardware. */
+void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ int i;
+
+ for (i = 0; i <= tlb_44x_hwater; i++) {
+ struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i];
+
+ if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
+ kvmppc_44x_tlbwe(i, stlbe);
+ }
+}
+
+static void kvmppc_44x_tlbe_set_modified(struct kvmppc_vcpu_44x *vcpu_44x,
+ unsigned int i)
+{
+ vcpu_44x->shadow_tlb_mod[i] = 1;
+}
+
+/* Save hardware TLB to the vcpu, and invalidate all guest mappings. */
+void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ int i;
+
+ for (i = 0; i <= tlb_44x_hwater; i++) {
+ struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i];
+
+ if (vcpu_44x->shadow_tlb_mod[i])
+ kvmppc_44x_tlbre(i, stlbe);
+
+ if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
+ kvmppc_44x_tlbie(i);
+ }
+}
+
+
/* Search the guest TLB for a matching entry. */
int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid,
unsigned int as)
{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
int i;
/* XXX Replace loop with fancy data structures. */
- for (i = 0; i < PPC44x_TLB_SIZE; i++) {
- struct tlbe *tlbe = &vcpu->arch.guest_tlb[i];
+ for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) {
+ struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[i];
unsigned int tid;
if (eaddr < get_tlb_eaddr(tlbe))
@@ -83,78 +208,89 @@ int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid,
return -1;
}
-struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
+int kvmppc_44x_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
unsigned int as = !!(vcpu->arch.msr & MSR_IS);
- unsigned int index;
- index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
- if (index == -1)
- return NULL;
- return &vcpu->arch.guest_tlb[index];
+ return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
-struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr)
+int kvmppc_44x_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr)
{
unsigned int as = !!(vcpu->arch.msr & MSR_DS);
- unsigned int index;
- index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
- if (index == -1)
- return NULL;
- return &vcpu->arch.guest_tlb[index];
+ return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as);
}
-static int kvmppc_44x_tlbe_is_writable(struct tlbe *tlbe)
+static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x,
+ unsigned int stlb_index)
{
- return tlbe->word2 & (PPC44x_TLB_SW|PPC44x_TLB_UW);
-}
+ struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[stlb_index];
-static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu,
- unsigned int index)
-{
- struct tlbe *stlbe = &vcpu->arch.shadow_tlb[index];
- struct page *page = vcpu->arch.shadow_pages[index];
+ if (!ref->page)
+ return;
- if (get_tlb_v(stlbe)) {
- if (kvmppc_44x_tlbe_is_writable(stlbe))
- kvm_release_page_dirty(page);
- else
- kvm_release_page_clean(page);
- }
+ /* Discard from the TLB. */
+ /* Note: we could actually invalidate a host mapping, if the host overwrote
+ * this TLB entry since we inserted a guest mapping. */
+ kvmppc_44x_tlbie(stlb_index);
+
+ /* Now release the page. */
+ if (ref->writeable)
+ kvm_release_page_dirty(ref->page);
+ else
+ kvm_release_page_clean(ref->page);
+
+ ref->page = NULL;
+
+ /* XXX set tlb_44x_index to stlb_index? */
+
+ KVMTRACE_1D(STLB_INVAL, &vcpu_44x->vcpu, stlb_index, handler);
}
void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu)
{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
int i;
for (i = 0; i <= tlb_44x_hwater; i++)
- kvmppc_44x_shadow_release(vcpu, i);
-}
-
-void kvmppc_tlbe_set_modified(struct kvm_vcpu *vcpu, unsigned int i)
-{
- vcpu->arch.shadow_tlb_mod[i] = 1;
+ kvmppc_44x_shadow_release(vcpu_44x, i);
}
-/* Caller must ensure that the specified guest TLB entry is safe to insert into
- * the shadow TLB. */
-void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
- u32 flags)
+/**
+ * kvmppc_mmu_map -- create a host mapping for guest memory
+ *
+ * If the guest wanted a larger page than the host supports, only the first
+ * host page is mapped here and the rest are demand faulted.
+ *
+ * If the guest wanted a smaller page than the host page size, we map only the
+ * guest-size page (i.e. not a full host page mapping).
+ *
+ * Caller must ensure that the specified guest TLB entry is safe to insert into
+ * the shadow TLB.
+ */
+void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, u64 asid,
+ u32 flags, u32 max_bytes, unsigned int gtlb_index)
{
+ struct kvmppc_44x_tlbe stlbe;
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ struct kvmppc_44x_shadow_ref *ref;
struct page *new_page;
- struct tlbe *stlbe;
hpa_t hpaddr;
+ gfn_t gfn;
unsigned int victim;
- /* Future optimization: don't overwrite the TLB entry containing the
- * current PC (or stack?). */
- victim = kvmppc_tlb_44x_pos++;
- if (kvmppc_tlb_44x_pos > tlb_44x_hwater)
- kvmppc_tlb_44x_pos = 0;
- stlbe = &vcpu->arch.shadow_tlb[victim];
+ /* Select TLB entry to clobber. Indirectly guard against races with the TLB
+ * miss handler by disabling interrupts. */
+ local_irq_disable();
+ victim = ++tlb_44x_index;
+ if (victim > tlb_44x_hwater)
+ victim = 0;
+ tlb_44x_index = victim;
+ local_irq_enable();
/* Get reference to new page. */
+ gfn = gpaddr >> PAGE_SHIFT;
new_page = gfn_to_page(vcpu->kvm, gfn);
if (is_error_page(new_page)) {
printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n", gfn);
@@ -163,10 +299,8 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
}
hpaddr = page_to_phys(new_page);
- /* Drop reference to old page. */
- kvmppc_44x_shadow_release(vcpu, victim);
-
- vcpu->arch.shadow_pages[victim] = new_page;
+ /* Invalidate any previous shadow mappings. */
+ kvmppc_44x_shadow_release(vcpu_44x, victim);
/* XXX Make sure (va, size) doesn't overlap any other
* entries. 440x6 user manual says the result would be
@@ -174,78 +308,193 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid,
/* XXX what about AS? */
- stlbe->tid = !(asid & 0xff);
-
/* Force TS=1 for all guest mappings. */
- /* For now we hardcode 4KB mappings, but it will be important to
- * use host large pages in the future. */
- stlbe->word0 = (gvaddr & PAGE_MASK) | PPC44x_TLB_VALID | PPC44x_TLB_TS
- | PPC44x_TLB_4K;
- stlbe->word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
- stlbe->word2 = kvmppc_44x_tlb_shadow_attrib(flags,
- vcpu->arch.msr & MSR_PR);
- kvmppc_tlbe_set_modified(vcpu, victim);
+ stlbe.word0 = PPC44x_TLB_VALID | PPC44x_TLB_TS;
+
+ if (max_bytes >= PAGE_SIZE) {
+ /* Guest mapping is larger than or equal to host page size. We can use
+ * a "native" host mapping. */
+ stlbe.word0 |= (gvaddr & PAGE_MASK) | PPC44x_TLBE_SIZE;
+ } else {
+ /* Guest mapping is smaller than host page size. We must restrict the
+ * size of the mapping to be at most the smaller of the two, but for
+ * simplicity we fall back to a 4K mapping (this is probably what the
+ * guest is using anyways). */
+ stlbe.word0 |= (gvaddr & PAGE_MASK_4K) | PPC44x_TLB_4K;
+
+ /* 'hpaddr' is a host page, which is larger than the mapping we're
+ * inserting here. To compensate, we must add the in-page offset to the
+ * sub-page. */
+ hpaddr |= gpaddr & (PAGE_MASK ^ PAGE_MASK_4K);
+ }
- KVMTRACE_5D(STLB_WRITE, vcpu, victim,
- stlbe->tid, stlbe->word0, stlbe->word1, stlbe->word2,
- handler);
+ stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
+ stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags,
+ vcpu->arch.msr & MSR_PR);
+ stlbe.tid = !(asid & 0xff);
+
+ /* Keep track of the reference so we can properly release it later. */
+ ref = &vcpu_44x->shadow_refs[victim];
+ ref->page = new_page;
+ ref->gtlb_index = gtlb_index;
+ ref->writeable = !!(stlbe.word2 & PPC44x_TLB_UW);
+ ref->tid = stlbe.tid;
+
+ /* Insert shadow mapping into hardware TLB. */
+ kvmppc_44x_tlbe_set_modified(vcpu_44x, victim);
+ kvmppc_44x_tlbwe(victim, &stlbe);
+ KVMTRACE_5D(STLB_WRITE, vcpu, victim, stlbe.tid, stlbe.word0, stlbe.word1,
+ stlbe.word2, handler);
}
-void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, gva_t eaddr,
- gva_t eend, u32 asid)
+/* For a particular guest TLB entry, invalidate the corresponding host TLB
+ * mappings and release the host pages. */
+static void kvmppc_44x_invalidate(struct kvm_vcpu *vcpu,
+ unsigned int gtlb_index)
{
- unsigned int pid = !(asid & 0xff);
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
int i;
- /* XXX Replace loop with fancy data structures. */
- for (i = 0; i <= tlb_44x_hwater; i++) {
- struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i];
- unsigned int tid;
+ for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) {
+ struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i];
+ if (ref->gtlb_index == gtlb_index)
+ kvmppc_44x_shadow_release(vcpu_44x, i);
+ }
+}
- if (!get_tlb_v(stlbe))
- continue;
+void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
+{
+ vcpu->arch.shadow_pid = !usermode;
+}
- if (eend < get_tlb_eaddr(stlbe))
- continue;
+void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ int i;
- if (eaddr > get_tlb_end(stlbe))
- continue;
+ if (unlikely(vcpu->arch.pid == new_pid))
+ return;
- tid = get_tlb_tid(stlbe);
- if (tid && (tid != pid))
- continue;
+ vcpu->arch.pid = new_pid;
- kvmppc_44x_shadow_release(vcpu, i);
- stlbe->word0 = 0;
- kvmppc_tlbe_set_modified(vcpu, i);
- KVMTRACE_5D(STLB_INVAL, vcpu, i,
- stlbe->tid, stlbe->word0, stlbe->word1,
- stlbe->word2, handler);
+ /* Guest userspace runs with TID=0 mappings and PID=0, to make sure it
+ * can't access guest kernel mappings (TID=1). When we switch to a new
+ * guest PID, which will also use host PID=0, we must discard the old guest
+ * userspace mappings. */
+ for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) {
+ struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i];
+
+ if (ref->tid == 0)
+ kvmppc_44x_shadow_release(vcpu_44x, i);
}
}
-/* Invalidate all mappings on the privilege switch after PID has been changed.
- * The guest always runs with PID=1, so we must clear the entire TLB when
- * switching address spaces. */
-void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode)
+static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
+ const struct kvmppc_44x_tlbe *tlbe)
{
- int i;
+ gpa_t gpa;
- if (vcpu->arch.swap_pid) {
- /* XXX Replace loop with fancy data structures. */
- for (i = 0; i <= tlb_44x_hwater; i++) {
- struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i];
-
- /* Future optimization: clear only userspace mappings. */
- kvmppc_44x_shadow_release(vcpu, i);
- stlbe->word0 = 0;
- kvmppc_tlbe_set_modified(vcpu, i);
- KVMTRACE_5D(STLB_INVAL, vcpu, i,
- stlbe->tid, stlbe->word0, stlbe->word1,
- stlbe->word2, handler);
- }
- vcpu->arch.swap_pid = 0;
+ if (!get_tlb_v(tlbe))
+ return 0;
+
+ /* Does it match current guest AS? */
+ /* XXX what about IS != DS? */
+ if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
+ return 0;
+
+ gpa = get_tlb_raddr(tlbe);
+ if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT))
+ /* Mapping is not for RAM. */
+ return 0;
+
+ return 1;
+}
+
+int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws)
+{
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ struct kvmppc_44x_tlbe *tlbe;
+ unsigned int gtlb_index;
+
+ gtlb_index = vcpu->arch.gpr[ra];
+ if (gtlb_index > KVM44x_GUEST_TLB_SIZE) {
+ printk("%s: index %d\n", __func__, gtlb_index);
+ kvmppc_dump_vcpu(vcpu);
+ return EMULATE_FAIL;
}
- vcpu->arch.shadow_pid = !usermode;
+ tlbe = &vcpu_44x->guest_tlb[gtlb_index];
+
+ /* Invalidate shadow mappings for the about-to-be-clobbered TLB entry. */
+ if (tlbe->word0 & PPC44x_TLB_VALID)
+ kvmppc_44x_invalidate(vcpu, gtlb_index);
+
+ switch (ws) {
+ case PPC44x_TLB_PAGEID:
+ tlbe->tid = get_mmucr_stid(vcpu);
+ tlbe->word0 = vcpu->arch.gpr[rs];
+ break;
+
+ case PPC44x_TLB_XLAT:
+ tlbe->word1 = vcpu->arch.gpr[rs];
+ break;
+
+ case PPC44x_TLB_ATTRIB:
+ tlbe->word2 = vcpu->arch.gpr[rs];
+ break;
+
+ default:
+ return EMULATE_FAIL;
+ }
+
+ if (tlbe_is_host_safe(vcpu, tlbe)) {
+ u64 asid;
+ gva_t eaddr;
+ gpa_t gpaddr;
+ u32 flags;
+ u32 bytes;
+
+ eaddr = get_tlb_eaddr(tlbe);
+ gpaddr = get_tlb_raddr(tlbe);
+
+ /* Use the advertised page size to mask effective and real addrs. */
+ bytes = get_tlb_bytes(tlbe);
+ eaddr &= ~(bytes - 1);
+ gpaddr &= ~(bytes - 1);
+
+ asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
+ flags = tlbe->word2 & 0xffff;
+
+ kvmppc_mmu_map(vcpu, eaddr, gpaddr, asid, flags, bytes, gtlb_index);
+ }
+
+ KVMTRACE_5D(GTLB_WRITE, vcpu, gtlb_index, tlbe->tid, tlbe->word0,
+ tlbe->word1, tlbe->word2, handler);
+
+ kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS);
+ return EMULATE_DONE;
+}
+
+int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb, u8 rc)
+{
+ u32 ea;
+ int gtlb_index;
+ unsigned int as = get_mmucr_sts(vcpu);
+ unsigned int pid = get_mmucr_stid(vcpu);
+
+ ea = vcpu->arch.gpr[rb];
+ if (ra)
+ ea += vcpu->arch.gpr[ra];
+
+ gtlb_index = kvmppc_44x_tlb_index(vcpu, ea, pid, as);
+ if (rc) {
+ if (gtlb_index < 0)
+ vcpu->arch.cr &= ~0x20000000;
+ else
+ vcpu->arch.cr |= 0x20000000;
+ }
+ vcpu->arch.gpr[rt] = gtlb_index;
+
+ kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS);
+ return EMULATE_DONE;
}
diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h
index 2ccd46b6f6b7..772191f29e62 100644
--- a/arch/powerpc/kvm/44x_tlb.h
+++ b/arch/powerpc/kvm/44x_tlb.h
@@ -25,48 +25,52 @@
extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr,
unsigned int pid, unsigned int as);
-extern struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
-extern struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr);
+extern int kvmppc_44x_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr);
+extern int kvmppc_44x_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr);
+
+extern int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb,
+ u8 rc);
+extern int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws);
/* TLB helper functions */
-static inline unsigned int get_tlb_size(const struct tlbe *tlbe)
+static inline unsigned int get_tlb_size(const struct kvmppc_44x_tlbe *tlbe)
{
return (tlbe->word0 >> 4) & 0xf;
}
-static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe)
+static inline gva_t get_tlb_eaddr(const struct kvmppc_44x_tlbe *tlbe)
{
return tlbe->word0 & 0xfffffc00;
}
-static inline gva_t get_tlb_bytes(const struct tlbe *tlbe)
+static inline gva_t get_tlb_bytes(const struct kvmppc_44x_tlbe *tlbe)
{
unsigned int pgsize = get_tlb_size(tlbe);
return 1 << 10 << (pgsize << 1);
}
-static inline gva_t get_tlb_end(const struct tlbe *tlbe)
+static inline gva_t get_tlb_end(const struct kvmppc_44x_tlbe *tlbe)
{
return get_tlb_eaddr(tlbe) + get_tlb_bytes(tlbe) - 1;
}
-static inline u64 get_tlb_raddr(const struct tlbe *tlbe)
+static inline u64 get_tlb_raddr(const struct kvmppc_44x_tlbe *tlbe)
{
u64 word1 = tlbe->word1;
return ((word1 & 0xf) << 32) | (word1 & 0xfffffc00);
}
-static inline unsigned int get_tlb_tid(const struct tlbe *tlbe)
+static inline unsigned int get_tlb_tid(const struct kvmppc_44x_tlbe *tlbe)
{
return tlbe->tid & 0xff;
}
-static inline unsigned int get_tlb_ts(const struct tlbe *tlbe)
+static inline unsigned int get_tlb_ts(const struct kvmppc_44x_tlbe *tlbe)
{
return (tlbe->word0 >> 8) & 0x1;
}
-static inline unsigned int get_tlb_v(const struct tlbe *tlbe)
+static inline unsigned int get_tlb_v(const struct kvmppc_44x_tlbe *tlbe)
{
return (tlbe->word0 >> 9) & 0x1;
}
@@ -81,7 +85,7 @@ static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu)
return (vcpu->arch.mmucr >> 16) & 0x1;
}
-static inline gpa_t tlb_xlate(struct tlbe *tlbe, gva_t eaddr)
+static inline gpa_t tlb_xlate(struct kvmppc_44x_tlbe *tlbe, gva_t eaddr)
{
unsigned int pgmask = get_tlb_bytes(tlbe) - 1;
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 53aaa66b25e5..6dbdc4817d80 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -15,27 +15,33 @@ menuconfig VIRTUALIZATION
if VIRTUALIZATION
config KVM
- bool "Kernel-based Virtual Machine (KVM) support"
- depends on 44x && EXPERIMENTAL
+ bool
select PREEMPT_NOTIFIERS
select ANON_INODES
- # We can only run on Book E hosts so far
- select KVM_BOOKE_HOST
+
+config KVM_440
+ bool "KVM support for PowerPC 440 processors"
+ depends on EXPERIMENTAL && 44x
+ select KVM
---help---
- Support hosting virtualized guest machines. You will also
- need to select one or more of the processor modules below.
+ Support running unmodified 440 guest kernels in virtual machines on
+ 440 host processors.
This module provides access to the hardware capabilities through
a character device node named /dev/kvm.
If unsure, say N.
-config KVM_BOOKE_HOST
- bool "KVM host support for Book E PowerPC processors"
- depends on KVM && 44x
+config KVM_EXIT_TIMING
+ bool "Detailed exit timing"
+ depends on KVM
---help---
- Provides host support for KVM on Book E PowerPC processors. Currently
- this works on 440 processors only.
+ Calculate elapsed time for every exit/enter cycle. A per-vcpu
+ report is available in debugfs kvm/vm#_vcpu#_timing.
+ The overhead is relatively small, however it is not recommended for
+ production environments.
+
+ If unsure, say N.
config KVM_TRACE
bool "KVM trace support"
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 2a5d4397ac4b..df7ba59e6d53 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -8,10 +8,16 @@ common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
common-objs-$(CONFIG_KVM_TRACE) += $(addprefix ../../../virt/kvm/, kvm_trace.o)
-kvm-objs := $(common-objs-y) powerpc.o emulate.o booke_guest.o
+kvm-objs := $(common-objs-y) powerpc.o emulate.o
+obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o
obj-$(CONFIG_KVM) += kvm.o
AFLAGS_booke_interrupts.o := -I$(obj)
-kvm-booke-host-objs := booke_host.o booke_interrupts.o 44x_tlb.o
-obj-$(CONFIG_KVM_BOOKE_HOST) += kvm-booke-host.o
+kvm-440-objs := \
+ booke.o \
+ booke_interrupts.o \
+ 44x.o \
+ 44x_tlb.o \
+ 44x_emulate.o
+obj-$(CONFIG_KVM_440) += kvm-440.o
diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke.c
index 7b2591e26bae..35485dd6927e 100644
--- a/arch/powerpc/kvm/booke_guest.c
+++ b/arch/powerpc/kvm/booke.c
@@ -24,21 +24,26 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
+
#include <asm/cputable.h>
#include <asm/uaccess.h>
#include <asm/kvm_ppc.h>
+#include "timing.h"
+#include <asm/cacheflush.h>
+#include <asm/kvm_44x.h>
+#include "booke.h"
#include "44x_tlb.h"
+unsigned long kvmppc_booke_handlers;
+
#define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
struct kvm_stats_debugfs_item debugfs_entries[] = {
- { "exits", VCPU_STAT(sum_exits) },
{ "mmio", VCPU_STAT(mmio_exits) },
{ "dcr", VCPU_STAT(dcr_exits) },
{ "sig", VCPU_STAT(signal_exits) },
- { "light", VCPU_STAT(light_exits) },
{ "itlb_r", VCPU_STAT(itlb_real_miss_exits) },
{ "itlb_v", VCPU_STAT(itlb_virt_miss_exits) },
{ "dtlb_r", VCPU_STAT(dtlb_real_miss_exits) },
@@ -53,103 +58,19 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ NULL }
};
-static const u32 interrupt_msr_mask[16] = {
- [BOOKE_INTERRUPT_CRITICAL] = MSR_ME,
- [BOOKE_INTERRUPT_MACHINE_CHECK] = 0,
- [BOOKE_INTERRUPT_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_PROGRAM] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_SYSCALL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_FIT] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_WATCHDOG] = MSR_ME,
- [BOOKE_INTERRUPT_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE,
- [BOOKE_INTERRUPT_DEBUG] = MSR_ME,
-};
-
-const unsigned char exception_priority[] = {
- [BOOKE_INTERRUPT_DATA_STORAGE] = 0,
- [BOOKE_INTERRUPT_INST_STORAGE] = 1,
- [BOOKE_INTERRUPT_ALIGNMENT] = 2,
- [BOOKE_INTERRUPT_PROGRAM] = 3,
- [BOOKE_INTERRUPT_FP_UNAVAIL] = 4,
- [BOOKE_INTERRUPT_SYSCALL] = 5,
- [BOOKE_INTERRUPT_AP_UNAVAIL] = 6,
- [BOOKE_INTERRUPT_DTLB_MISS] = 7,
- [BOOKE_INTERRUPT_ITLB_MISS] = 8,
- [BOOKE_INTERRUPT_MACHINE_CHECK] = 9,
- [BOOKE_INTERRUPT_DEBUG] = 10,
- [BOOKE_INTERRUPT_CRITICAL] = 11,
- [BOOKE_INTERRUPT_WATCHDOG] = 12,
- [BOOKE_INTERRUPT_EXTERNAL] = 13,
- [BOOKE_INTERRUPT_FIT] = 14,
- [BOOKE_INTERRUPT_DECREMENTER] = 15,
-};
-
-const unsigned char priority_exception[] = {
- BOOKE_INTERRUPT_DATA_STORAGE,
- BOOKE_INTERRUPT_INST_STORAGE,
- BOOKE_INTERRUPT_ALIGNMENT,
- BOOKE_INTERRUPT_PROGRAM,
- BOOKE_INTERRUPT_FP_UNAVAIL,
- BOOKE_INTERRUPT_SYSCALL,
- BOOKE_INTERRUPT_AP_UNAVAIL,
- BOOKE_INTERRUPT_DTLB_MISS,
- BOOKE_INTERRUPT_ITLB_MISS,
- BOOKE_INTERRUPT_MACHINE_CHECK,
- BOOKE_INTERRUPT_DEBUG,
- BOOKE_INTERRUPT_CRITICAL,
- BOOKE_INTERRUPT_WATCHDOG,
- BOOKE_INTERRUPT_EXTERNAL,
- BOOKE_INTERRUPT_FIT,
- BOOKE_INTERRUPT_DECREMENTER,
-};
-
-
-void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu)
-{
- struct tlbe *tlbe;
- int i;
-
- printk("vcpu %d TLB dump:\n", vcpu->vcpu_id);
- printk("| %2s | %3s | %8s | %8s | %8s |\n",
- "nr", "tid", "word0", "word1", "word2");
-
- for (i = 0; i < PPC44x_TLB_SIZE; i++) {
- tlbe = &vcpu->arch.guest_tlb[i];
- if (tlbe->word0 & PPC44x_TLB_VALID)
- printk(" G%2d | %02X | %08X | %08X | %08X |\n",
- i, tlbe->tid, tlbe->word0, tlbe->word1,
- tlbe->word2);
- }
-
- for (i = 0; i < PPC44x_TLB_SIZE; i++) {
- tlbe = &vcpu->arch.shadow_tlb[i];
- if (tlbe->word0 & PPC44x_TLB_VALID)
- printk(" S%2d | %02X | %08X | %08X | %08X |\n",
- i, tlbe->tid, tlbe->word0, tlbe->word1,
- tlbe->word2);
- }
-}
-
/* TODO: use vcpu_printf() */
void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
{
int i;
- printk("pc: %08x msr: %08x\n", vcpu->arch.pc, vcpu->arch.msr);
- printk("lr: %08x ctr: %08x\n", vcpu->arch.lr, vcpu->arch.ctr);
- printk("srr0: %08x srr1: %08x\n", vcpu->arch.srr0, vcpu->arch.srr1);
+ printk("pc: %08lx msr: %08lx\n", vcpu->arch.pc, vcpu->arch.msr);
+ printk("lr: %08lx ctr: %08lx\n", vcpu->arch.lr, vcpu->arch.ctr);
+ printk("srr0: %08lx srr1: %08lx\n", vcpu->arch.srr0, vcpu->arch.srr1);
printk("exceptions: %08lx\n", vcpu->arch.pending_exceptions);
for (i = 0; i < 32; i += 4) {
- printk("gpr%02d: %08x %08x %08x %08x\n", i,
+ printk("gpr%02d: %08lx %08lx %08lx %08lx\n", i,
vcpu->arch.gpr[i],
vcpu->arch.gpr[i+1],
vcpu->arch.gpr[i+2],
@@ -157,69 +78,96 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
}
}
-/* Check if we are ready to deliver the interrupt */
-static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
+static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
+ unsigned int priority)
{
- int r;
+ set_bit(priority, &vcpu->arch.pending_exceptions);
+}
- switch (interrupt) {
- case BOOKE_INTERRUPT_CRITICAL:
- r = vcpu->arch.msr & MSR_CE;
- break;
- case BOOKE_INTERRUPT_MACHINE_CHECK:
- r = vcpu->arch.msr & MSR_ME;
- break;
- case BOOKE_INTERRUPT_EXTERNAL:
- r = vcpu->arch.msr & MSR_EE;
+void kvmppc_core_queue_program(struct kvm_vcpu *vcpu)
+{
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
+}
+
+void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
+{
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DECREMENTER);
+}
+
+int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
+{
+ return test_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
+}
+
+void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
+ struct kvm_interrupt *irq)
+{
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_EXTERNAL);
+}
+
+/* Deliver the interrupt of the corresponding priority, if possible. */
+static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
+ unsigned int priority)
+{
+ int allowed = 0;
+ ulong msr_mask;
+
+ switch (priority) {
+ case BOOKE_IRQPRIO_PROGRAM:
+ case BOOKE_IRQPRIO_DTLB_MISS:
+ case BOOKE_IRQPRIO_ITLB_MISS:
+ case BOOKE_IRQPRIO_SYSCALL:
+ case BOOKE_IRQPRIO_DATA_STORAGE:
+ case BOOKE_IRQPRIO_INST_STORAGE:
+ case BOOKE_IRQPRIO_FP_UNAVAIL:
+ case BOOKE_IRQPRIO_AP_UNAVAIL:
+ case BOOKE_IRQPRIO_ALIGNMENT:
+ allowed = 1;
+ msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
- case BOOKE_INTERRUPT_DECREMENTER:
- r = vcpu->arch.msr & MSR_EE;
+ case BOOKE_IRQPRIO_CRITICAL:
+ case BOOKE_IRQPRIO_WATCHDOG:
+ allowed = vcpu->arch.msr & MSR_CE;
+ msr_mask = MSR_ME;
break;
- case BOOKE_INTERRUPT_FIT:
- r = vcpu->arch.msr & MSR_EE;
+ case BOOKE_IRQPRIO_MACHINE_CHECK:
+ allowed = vcpu->arch.msr & MSR_ME;
+ msr_mask = 0;
break;
- case BOOKE_INTERRUPT_WATCHDOG:
- r = vcpu->arch.msr & MSR_CE;
+ case BOOKE_IRQPRIO_EXTERNAL:
+ case BOOKE_IRQPRIO_DECREMENTER:
+ case BOOKE_IRQPRIO_FIT:
+ allowed = vcpu->arch.msr & MSR_EE;
+ msr_mask = MSR_CE|MSR_ME|MSR_DE;
break;
- case BOOKE_INTERRUPT_DEBUG:
- r = vcpu->arch.msr & MSR_DE;
+ case BOOKE_IRQPRIO_DEBUG:
+ allowed = vcpu->arch.msr & MSR_DE;
+ msr_mask = MSR_ME;
break;
- default:
- r = 1;
}
- return r;
-}
+ if (allowed) {
+ vcpu->arch.srr0 = vcpu->arch.pc;
+ vcpu->arch.srr1 = vcpu->arch.msr;
+ vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
+ kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask);
-static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt)
-{
- switch (interrupt) {
- case BOOKE_INTERRUPT_DECREMENTER:
- vcpu->arch.tsr |= TSR_DIS;
- break;
+ clear_bit(priority, &vcpu->arch.pending_exceptions);
}
- vcpu->arch.srr0 = vcpu->arch.pc;
- vcpu->arch.srr1 = vcpu->arch.msr;
- vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt];
- kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]);
+ return allowed;
}
/* Check pending exceptions and deliver one, if possible. */
-void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu)
+void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
{
unsigned long *pending = &vcpu->arch.pending_exceptions;
- unsigned int exception;
unsigned int priority;
- priority = find_first_bit(pending, BITS_PER_BYTE * sizeof(*pending));
+ priority = __ffs(*pending);
while (priority <= BOOKE_MAX_INTERRUPT) {
- exception = priority_exception[priority];
- if (kvmppc_can_deliver_interrupt(vcpu, exception)) {
- kvmppc_clear_exception(vcpu, exception);
- kvmppc_deliver_interrupt(vcpu, exception);
+ if (kvmppc_booke_irqprio_deliver(vcpu, priority))
break;
- }
priority = find_next_bit(pending,
BITS_PER_BYTE * sizeof(*pending),
@@ -238,6 +186,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
enum emulation_result er;
int r = RESUME_HOST;
+ /* update before a new last_exit_type is rewritten */
+ kvmppc_update_timing_stats(vcpu);
+
local_irq_enable();
run->exit_reason = KVM_EXIT_UNKNOWN;
@@ -251,21 +202,19 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
case BOOKE_INTERRUPT_EXTERNAL:
+ kvmppc_account_exit(vcpu, EXT_INTR_EXITS);
+ if (need_resched())
+ cond_resched();
+ r = RESUME_GUEST;
+ break;
+
case BOOKE_INTERRUPT_DECREMENTER:
/* Since we switched IVPR back to the host's value, the host
* handled this interrupt the moment we enabled interrupts.
* Now we just offer it a chance to reschedule the guest. */
-
- /* XXX At this point the TLB still holds our shadow TLB, so if
- * we do reschedule the host will fault over it. Perhaps we
- * should politely restore the host's entries to minimize
- * misses before ceding control. */
+ kvmppc_account_exit(vcpu, DEC_EXITS);
if (need_resched())
cond_resched();
- if (exit_nr == BOOKE_INTERRUPT_DECREMENTER)
- vcpu->stat.dec_exits++;
- else
- vcpu->stat.ext_intr_exits++;
r = RESUME_GUEST;
break;
@@ -274,17 +223,19 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* Program traps generated by user-level software must be handled
* by the guest kernel. */
vcpu->arch.esr = vcpu->arch.fault_esr;
- kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_PROGRAM);
r = RESUME_GUEST;
+ kvmppc_account_exit(vcpu, USR_PR_INST);
break;
}
er = kvmppc_emulate_instruction(run, vcpu);
switch (er) {
case EMULATE_DONE:
+ /* don't overwrite subtypes, just account kvm_stats */
+ kvmppc_account_exit_stat(vcpu, EMULATED_INST_EXITS);
/* Future optimization: only reload non-volatiles if
* they were actually modified by emulation. */
- vcpu->stat.emulated_inst_exits++;
r = RESUME_GUEST_NV;
break;
case EMULATE_DO_DCR:
@@ -293,7 +244,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
case EMULATE_FAIL:
/* XXX Deliver Program interrupt to guest. */
- printk(KERN_CRIT "%s: emulation at %x failed (%08x)\n",
+ printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
__func__, vcpu->arch.pc, vcpu->arch.last_inst);
/* For debugging, encode the failing instruction and
* report it to userspace. */
@@ -307,48 +258,53 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
case BOOKE_INTERRUPT_FP_UNAVAIL:
- kvmppc_queue_exception(vcpu, exit_nr);
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_FP_UNAVAIL);
+ kvmppc_account_exit(vcpu, FP_UNAVAIL);
r = RESUME_GUEST;
break;
case BOOKE_INTERRUPT_DATA_STORAGE:
vcpu->arch.dear = vcpu->arch.fault_dear;
vcpu->arch.esr = vcpu->arch.fault_esr;
- kvmppc_queue_exception(vcpu, exit_nr);
- vcpu->stat.dsi_exits++;
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE);
+ kvmppc_account_exit(vcpu, DSI_EXITS);
r = RESUME_GUEST;
break;
case BOOKE_INTERRUPT_INST_STORAGE:
vcpu->arch.esr = vcpu->arch.fault_esr;
- kvmppc_queue_exception(vcpu, exit_nr);
- vcpu->stat.isi_exits++;
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE);
+ kvmppc_account_exit(vcpu, ISI_EXITS);
r = RESUME_GUEST;
break;
case BOOKE_INTERRUPT_SYSCALL:
- kvmppc_queue_exception(vcpu, exit_nr);
- vcpu->stat.syscall_exits++;
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SYSCALL);
+ kvmppc_account_exit(vcpu, SYSCALL_EXITS);
r = RESUME_GUEST;
break;
+ /* XXX move to a 440-specific file. */
case BOOKE_INTERRUPT_DTLB_MISS: {
- struct tlbe *gtlbe;
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ struct kvmppc_44x_tlbe *gtlbe;
unsigned long eaddr = vcpu->arch.fault_dear;
+ int gtlb_index;
gfn_t gfn;
/* Check the guest TLB. */
- gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr);
- if (!gtlbe) {
+ gtlb_index = kvmppc_44x_dtlb_index(vcpu, eaddr);
+ if (gtlb_index < 0) {
/* The guest didn't have a mapping for it. */
- kvmppc_queue_exception(vcpu, exit_nr);
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
vcpu->arch.dear = vcpu->arch.fault_dear;
vcpu->arch.esr = vcpu->arch.fault_esr;
- vcpu->stat.dtlb_real_miss_exits++;
+ kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS);
r = RESUME_GUEST;
break;
}
+ gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr);
gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT;
@@ -359,38 +315,45 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
* b) the guest used a large mapping which we're faking
* Either way, we need to satisfy the fault without
* invoking the guest. */
- kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
- gtlbe->word2);
- vcpu->stat.dtlb_virt_miss_exits++;
+ kvmppc_mmu_map(vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid,
+ gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index);
+ kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
r = RESUME_GUEST;
} else {
/* Guest has mapped and accessed a page which is not
* actually RAM. */
r = kvmppc_emulate_mmio(run, vcpu);
+ kvmppc_account_exit(vcpu, MMIO_EXITS);
}
break;
}
+ /* XXX move to a 440-specific file. */
case BOOKE_INTERRUPT_ITLB_MISS: {
- struct tlbe *gtlbe;
+ struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
+ struct kvmppc_44x_tlbe *gtlbe;
unsigned long eaddr = vcpu->arch.pc;
+ gpa_t gpaddr;
gfn_t gfn;
+ int gtlb_index;
r = RESUME_GUEST;
/* Check the guest TLB. */
- gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr);
- if (!gtlbe) {
+ gtlb_index = kvmppc_44x_itlb_index(vcpu, eaddr);
+ if (gtlb_index < 0) {
/* The guest didn't have a mapping for it. */
- kvmppc_queue_exception(vcpu, exit_nr);
- vcpu->stat.itlb_real_miss_exits++;
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS);
+ kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS);
break;
}
- vcpu->stat.itlb_virt_miss_exits++;
+ kvmppc_account_exit(vcpu, ITLB_VIRT_MISS_EXITS);
- gfn = tlb_xlate(gtlbe, eaddr) >> PAGE_SHIFT;
+ gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
+ gpaddr = tlb_xlate(gtlbe, eaddr);
+ gfn = gpaddr >> PAGE_SHIFT;
if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
/* The guest TLB had a mapping, but the shadow TLB
@@ -399,12 +362,11 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
* b) the guest used a large mapping which we're faking
* Either way, we need to satisfy the fault without
* invoking the guest. */
- kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid,
- gtlbe->word2);
+ kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid,
+ gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index);
} else {
/* Guest mapped and leaped at non-RAM! */
- kvmppc_queue_exception(vcpu,
- BOOKE_INTERRUPT_MACHINE_CHECK);
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK);
}
break;
@@ -421,6 +383,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
mtspr(SPRN_DBSR, dbsr);
run->exit_reason = KVM_EXIT_DEBUG;
+ kvmppc_account_exit(vcpu, DEBUG_EXITS);
r = RESUME_HOST;
break;
}
@@ -432,10 +395,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
local_irq_disable();
- kvmppc_check_and_deliver_interrupts(vcpu);
+ kvmppc_core_deliver_interrupts(vcpu);
- /* Do some exit accounting. */
- vcpu->stat.sum_exits++;
if (!(r & RESUME_HOST)) {
/* To avoid clobbering exit_reason, only check for signals if
* we aren't already exiting to userspace for some other
@@ -443,22 +404,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
if (signal_pending(current)) {
run->exit_reason = KVM_EXIT_INTR;
r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
-
- vcpu->stat.signal_exits++;
- } else {
- vcpu->stat.light_exits++;
- }
- } else {
- switch (run->exit_reason) {
- case KVM_EXIT_MMIO:
- vcpu->stat.mmio_exits++;
- break;
- case KVM_EXIT_DCR:
- vcpu->stat.dcr_exits++;
- break;
- case KVM_EXIT_INTR:
- vcpu->stat.signal_exits++;
- break;
+ kvmppc_account_exit(vcpu, SIGNAL_EXITS);
}
}
@@ -468,20 +414,6 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
/* Initial guest state: 16MB mapping 0 -> 0, PC = 0, MSR = 0, R1 = 16MB */
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
- struct tlbe *tlbe = &vcpu->arch.guest_tlb[0];
-
- tlbe->tid = 0;
- tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
- tlbe->word1 = 0;
- tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR;
-
- tlbe++;
- tlbe->tid = 0;
- tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID;
- tlbe->word1 = 0xef600000;
- tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR
- | PPC44x_TLB_I | PPC44x_TLB_G;
-
vcpu->arch.pc = 0;
vcpu->arch.msr = 0;
vcpu->arch.gpr[1] = (16<<20) - 8; /* -8 for the callee-save LR slot */
@@ -492,12 +424,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
* before it's programmed its own IVPR. */
vcpu->arch.ivpr = 0x55550000;
- /* Since the guest can directly access the timebase, it must know the
- * real timebase frequency. Accordingly, it must see the state of
- * CCR1[TCS]. */
- vcpu->arch.ccr1 = mfspr(SPRN_CCR1);
+ kvmppc_init_timing_stats(vcpu);
- return 0;
+ return kvmppc_core_vcpu_setup(vcpu);
}
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
@@ -536,7 +465,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
vcpu->arch.ctr = regs->ctr;
vcpu->arch.lr = regs->lr;
vcpu->arch.xer = regs->xer;
- vcpu->arch.msr = regs->msr;
+ kvmppc_set_msr(vcpu, regs->msr);
vcpu->arch.srr0 = regs->srr0;
vcpu->arch.srr1 = regs->srr1;
vcpu->arch.sprg0 = regs->sprg0;
@@ -575,31 +504,62 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
return -ENOTSUPP;
}
-/* 'linear_address' is actually an encoding of AS|PID|EADDR . */
int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
struct kvm_translation *tr)
{
- struct tlbe *gtlbe;
- int index;
- gva_t eaddr;
- u8 pid;
- u8 as;
-
- eaddr = tr->linear_address;
- pid = (tr->linear_address >> 32) & 0xff;
- as = (tr->linear_address >> 40) & 0x1;
-
- index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as);
- if (index == -1) {
- tr->valid = 0;
- return 0;
- }
+ return kvmppc_core_vcpu_translate(vcpu, tr);
+}
- gtlbe = &vcpu->arch.guest_tlb[index];
+int kvmppc_booke_init(void)
+{
+ unsigned long ivor[16];
+ unsigned long max_ivor = 0;
+ int i;
- tr->physical_address = tlb_xlate(gtlbe, eaddr);
- /* XXX what does "writeable" and "usermode" even mean? */
- tr->valid = 1;
+ /* We install our own exception handlers by hijacking IVPR. IVPR must
+ * be 16-bit aligned, so we need a 64KB allocation. */
+ kvmppc_booke_handlers = __get_free_pages(GFP_KERNEL | __GFP_ZERO,
+ VCPU_SIZE_ORDER);
+ if (!kvmppc_booke_handlers)
+ return -ENOMEM;
+
+ /* XXX make sure our handlers are smaller than Linux's */
+
+ /* Copy our interrupt handlers to match host IVORs. That way we don't
+ * have to swap the IVORs on every guest/host transition. */
+ ivor[0] = mfspr(SPRN_IVOR0);
+ ivor[1] = mfspr(SPRN_IVOR1);
+ ivor[2] = mfspr(SPRN_IVOR2);
+ ivor[3] = mfspr(SPRN_IVOR3);
+ ivor[4] = mfspr(SPRN_IVOR4);
+ ivor[5] = mfspr(SPRN_IVOR5);
+ ivor[6] = mfspr(SPRN_IVOR6);
+ ivor[7] = mfspr(SPRN_IVOR7);
+ ivor[8] = mfspr(SPRN_IVOR8);
+ ivor[9] = mfspr(SPRN_IVOR9);
+ ivor[10] = mfspr(SPRN_IVOR10);
+ ivor[11] = mfspr(SPRN_IVOR11);
+ ivor[12] = mfspr(SPRN_IVOR12);
+ ivor[13] = mfspr(SPRN_IVOR13);
+ ivor[14] = mfspr(SPRN_IVOR14);
+ ivor[15] = mfspr(SPRN_IVOR15);
+
+ for (i = 0; i < 16; i++) {
+ if (ivor[i] > max_ivor)
+ max_ivor = ivor[i];
+
+ memcpy((void *)kvmppc_booke_handlers + ivor[i],
+ kvmppc_handlers_start + i * kvmppc_handler_len,
+ kvmppc_handler_len);
+ }
+ flush_icache_range(kvmppc_booke_handlers,
+ kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
return 0;
}
+
+void __exit kvmppc_booke_exit(void)
+{
+ free_pages(kvmppc_booke_handlers, VCPU_SIZE_ORDER);
+ kvm_exit();
+}
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h
new file mode 100644
index 000000000000..cf7c94ca24bf
--- /dev/null
+++ b/arch/powerpc/kvm/booke.h
@@ -0,0 +1,60 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ */
+
+#ifndef __KVM_BOOKE_H__
+#define __KVM_BOOKE_H__
+
+#include <linux/types.h>
+#include <linux/kvm_host.h>
+#include "timing.h"
+
+/* interrupt priortity ordering */
+#define BOOKE_IRQPRIO_DATA_STORAGE 0
+#define BOOKE_IRQPRIO_INST_STORAGE 1
+#define BOOKE_IRQPRIO_ALIGNMENT 2
+#define BOOKE_IRQPRIO_PROGRAM 3
+#define BOOKE_IRQPRIO_FP_UNAVAIL 4
+#define BOOKE_IRQPRIO_SYSCALL 5
+#define BOOKE_IRQPRIO_AP_UNAVAIL 6
+#define BOOKE_IRQPRIO_DTLB_MISS 7
+#define BOOKE_IRQPRIO_ITLB_MISS 8
+#define BOOKE_IRQPRIO_MACHINE_CHECK 9
+#define BOOKE_IRQPRIO_DEBUG 10
+#define BOOKE_IRQPRIO_CRITICAL 11
+#define BOOKE_IRQPRIO_WATCHDOG 12
+#define BOOKE_IRQPRIO_EXTERNAL 13
+#define BOOKE_IRQPRIO_FIT 14
+#define BOOKE_IRQPRIO_DECREMENTER 15
+
+/* Helper function for "full" MSR writes. No need to call this if only EE is
+ * changing. */
+static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
+{
+ if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR))
+ kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR);
+
+ vcpu->arch.msr = new_msr;
+
+ if (vcpu->arch.msr & MSR_WE) {
+ kvm_vcpu_block(vcpu);
+ kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS);
+ };
+}
+
+#endif /* __KVM_BOOKE_H__ */
diff --git a/arch/powerpc/kvm/booke_host.c b/arch/powerpc/kvm/booke_host.c
deleted file mode 100644
index b480341bc31e..000000000000
--- a/arch/powerpc/kvm/booke_host.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Copyright IBM Corp. 2008
- *
- * Authors: Hollis Blanchard <hollisb@us.ibm.com>
- */
-
-#include <linux/errno.h>
-#include <linux/kvm_host.h>
-#include <linux/module.h>
-#include <asm/cacheflush.h>
-#include <asm/kvm_ppc.h>
-
-unsigned long kvmppc_booke_handlers;
-
-static int kvmppc_booke_init(void)
-{
- unsigned long ivor[16];
- unsigned long max_ivor = 0;
- int i;
-
- /* We install our own exception handlers by hijacking IVPR. IVPR must
- * be 16-bit aligned, so we need a 64KB allocation. */
- kvmppc_booke_handlers = __get_free_pages(GFP_KERNEL | __GFP_ZERO,
- VCPU_SIZE_ORDER);
- if (!kvmppc_booke_handlers)
- return -ENOMEM;
-
- /* XXX make sure our handlers are smaller than Linux's */
-
- /* Copy our interrupt handlers to match host IVORs. That way we don't
- * have to swap the IVORs on every guest/host transition. */
- ivor[0] = mfspr(SPRN_IVOR0);
- ivor[1] = mfspr(SPRN_IVOR1);
- ivor[2] = mfspr(SPRN_IVOR2);
- ivor[3] = mfspr(SPRN_IVOR3);
- ivor[4] = mfspr(SPRN_IVOR4);
- ivor[5] = mfspr(SPRN_IVOR5);
- ivor[6] = mfspr(SPRN_IVOR6);
- ivor[7] = mfspr(SPRN_IVOR7);
- ivor[8] = mfspr(SPRN_IVOR8);
- ivor[9] = mfspr(SPRN_IVOR9);
- ivor[10] = mfspr(SPRN_IVOR10);
- ivor[11] = mfspr(SPRN_IVOR11);
- ivor[12] = mfspr(SPRN_IVOR12);
- ivor[13] = mfspr(SPRN_IVOR13);
- ivor[14] = mfspr(SPRN_IVOR14);
- ivor[15] = mfspr(SPRN_IVOR15);
-
- for (i = 0; i < 16; i++) {
- if (ivor[i] > max_ivor)
- max_ivor = ivor[i];
-
- memcpy((void *)kvmppc_booke_handlers + ivor[i],
- kvmppc_handlers_start + i * kvmppc_handler_len,
- kvmppc_handler_len);
- }
- flush_icache_range(kvmppc_booke_handlers,
- kvmppc_booke_handlers + max_ivor + kvmppc_handler_len);
-
- return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
-}
-
-static void __exit kvmppc_booke_exit(void)
-{
- free_pages(kvmppc_booke_handlers, VCPU_SIZE_ORDER);
- kvm_exit();
-}
-
-module_init(kvmppc_booke_init)
-module_exit(kvmppc_booke_exit)
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index 95e165baf85f..084ebcd7dd83 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -107,6 +107,18 @@ _GLOBAL(kvmppc_resume_host)
li r6, 1
slw r6, r6, r5
+#ifdef CONFIG_KVM_EXIT_TIMING
+ /* save exit time */
+1:
+ mfspr r7, SPRN_TBRU
+ mfspr r8, SPRN_TBRL
+ mfspr r9, SPRN_TBRU
+ cmpw r9, r7
+ bne 1b
+ stw r8, VCPU_TIMING_EXIT_TBL(r4)
+ stw r9, VCPU_TIMING_EXIT_TBU(r4)
+#endif
+
/* Save the faulting instruction and all GPRs for emulation. */
andi. r7, r6, NEED_INST_MASK
beq ..skip_inst_copy
@@ -335,54 +347,6 @@ lightweight_exit:
lwz r3, VCPU_SHADOW_PID(r4)
mtspr SPRN_PID, r3
- /* Prevent all asynchronous TLB updates. */
- mfmsr r5
- lis r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@h
- ori r6, r6, (MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l
- andc r6, r5, r6
- mtmsr r6
-
- /* Load the guest mappings, leaving the host's "pinned" kernel mappings
- * in place. */
- mfspr r10, SPRN_MMUCR /* Save host MMUCR. */
- li r5, PPC44x_TLB_SIZE
- lis r5, tlb_44x_hwater@ha
- lwz r5, tlb_44x_hwater@l(r5)
- mtctr r5
- addi r9, r4, VCPU_SHADOW_TLB
- addi r5, r4, VCPU_SHADOW_MOD
- li r3, 0
-1:
- lbzx r7, r3, r5
- cmpwi r7, 0
- beq 3f
-
- /* Load guest entry. */
- mulli r11, r3, TLBE_BYTES
- add r11, r11, r9
- lwz r7, 0(r11)
- mtspr SPRN_MMUCR, r7
- lwz r7, 4(r11)
- tlbwe r7, r3, PPC44x_TLB_PAGEID
- lwz r7, 8(r11)
- tlbwe r7, r3, PPC44x_TLB_XLAT
- lwz r7, 12(r11)
- tlbwe r7, r3, PPC44x_TLB_ATTRIB
-3:
- addi r3, r3, 1 /* Increment index. */
- bdnz 1b
-
- mtspr SPRN_MMUCR, r10 /* Restore host MMUCR. */
-
- /* Clear bitmap of modified TLB entries */
- li r5, PPC44x_TLB_SIZE>>2
- mtctr r5
- addi r5, r4, VCPU_SHADOW_MOD - 4
- li r6, 0
-1:
- stwu r6, 4(r5)
- bdnz 1b
-
iccci 0, 0 /* XXX hack */
/* Load some guest volatiles. */
@@ -423,6 +387,18 @@ lightweight_exit:
lwz r3, VCPU_SPRG7(r4)
mtspr SPRN_SPRG7, r3
+#ifdef CONFIG_KVM_EXIT_TIMING
+ /* save enter time */
+1:
+ mfspr r6, SPRN_TBRU
+ mfspr r7, SPRN_TBRL
+ mfspr r8, SPRN_TBRU
+ cmpw r8, r6
+ bne 1b
+ stw r7, VCPU_TIMING_LAST_ENTER_TBL(r4)
+ stw r8, VCPU_TIMING_LAST_ENTER_TBU(r4)
+#endif
+
/* Finish loading guest volatiles and jump to guest. */
lwz r3, VCPU_CTR(r4)
mtctr r3
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 0fce4fbdc20d..d1d38daa93fb 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -23,161 +23,14 @@
#include <linux/string.h>
#include <linux/kvm_host.h>
-#include <asm/dcr.h>
-#include <asm/dcr-regs.h>
+#include <asm/reg.h>
#include <asm/time.h>
#include <asm/byteorder.h>
#include <asm/kvm_ppc.h>
+#include <asm/disassemble.h>
+#include "timing.h"
-#include "44x_tlb.h"
-
-/* Instruction decoding */
-static inline unsigned int get_op(u32 inst)
-{
- return inst >> 26;
-}
-
-static inline unsigned int get_xop(u32 inst)
-{
- return (inst >> 1) & 0x3ff;
-}
-
-static inline unsigned int get_sprn(u32 inst)
-{
- return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
-}
-
-static inline unsigned int get_dcrn(u32 inst)
-{
- return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0);
-}
-
-static inline unsigned int get_rt(u32 inst)
-{
- return (inst >> 21) & 0x1f;
-}
-
-static inline unsigned int get_rs(u32 inst)
-{
- return (inst >> 21) & 0x1f;
-}
-
-static inline unsigned int get_ra(u32 inst)
-{
- return (inst >> 16) & 0x1f;
-}
-
-static inline unsigned int get_rb(u32 inst)
-{
- return (inst >> 11) & 0x1f;
-}
-
-static inline unsigned int get_rc(u32 inst)
-{
- return inst & 0x1;
-}
-
-static inline unsigned int get_ws(u32 inst)
-{
- return (inst >> 11) & 0x1f;
-}
-
-static inline unsigned int get_d(u32 inst)
-{
- return inst & 0xffff;
-}
-
-static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu,
- const struct tlbe *tlbe)
-{
- gpa_t gpa;
-
- if (!get_tlb_v(tlbe))
- return 0;
-
- /* Does it match current guest AS? */
- /* XXX what about IS != DS? */
- if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS))
- return 0;
-
- gpa = get_tlb_raddr(tlbe);
- if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT))
- /* Mapping is not for RAM. */
- return 0;
-
- return 1;
-}
-
-static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst)
-{
- u64 eaddr;
- u64 raddr;
- u64 asid;
- u32 flags;
- struct tlbe *tlbe;
- unsigned int ra;
- unsigned int rs;
- unsigned int ws;
- unsigned int index;
-
- ra = get_ra(inst);
- rs = get_rs(inst);
- ws = get_ws(inst);
-
- index = vcpu->arch.gpr[ra];
- if (index > PPC44x_TLB_SIZE) {
- printk("%s: index %d\n", __func__, index);
- kvmppc_dump_vcpu(vcpu);
- return EMULATE_FAIL;
- }
-
- tlbe = &vcpu->arch.guest_tlb[index];
-
- /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */
- if (tlbe->word0 & PPC44x_TLB_VALID) {
- eaddr = get_tlb_eaddr(tlbe);
- asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
- kvmppc_mmu_invalidate(vcpu, eaddr, get_tlb_end(tlbe), asid);
- }
-
- switch (ws) {
- case PPC44x_TLB_PAGEID:
- tlbe->tid = vcpu->arch.mmucr & 0xff;
- tlbe->word0 = vcpu->arch.gpr[rs];
- break;
-
- case PPC44x_TLB_XLAT:
- tlbe->word1 = vcpu->arch.gpr[rs];
- break;
-
- case PPC44x_TLB_ATTRIB:
- tlbe->word2 = vcpu->arch.gpr[rs];
- break;
-
- default:
- return EMULATE_FAIL;
- }
-
- if (tlbe_is_host_safe(vcpu, tlbe)) {
- eaddr = get_tlb_eaddr(tlbe);
- raddr = get_tlb_raddr(tlbe);
- asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid;
- flags = tlbe->word2 & 0xffff;
-
- /* Create a 4KB mapping on the host. If the guest wanted a
- * large page, only the first 4KB is mapped here and the rest
- * are mapped on the fly. */
- kvmppc_mmu_map(vcpu, eaddr, raddr >> PAGE_SHIFT, asid, flags);
- }
-
- KVMTRACE_5D(GTLB_WRITE, vcpu, index,
- tlbe->tid, tlbe->word0, tlbe->word1, tlbe->word2,
- handler);
-
- return EMULATE_DONE;
-}
-
-static void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
+void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
{
if (vcpu->arch.tcr & TCR_DIE) {
/* The decrementer ticks at the same rate as the timebase, so
@@ -193,12 +46,6 @@ static void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
}
}
-static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
-{
- vcpu->arch.pc = vcpu->arch.srr0;
- kvmppc_set_msr(vcpu, vcpu->arch.srr1);
-}
-
/* XXX to do:
* lhax
* lhaux
@@ -213,40 +60,30 @@ static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
*
* XXX is_bigendian should depend on MMU mapping or MSR[LE]
*/
+/* XXX Should probably auto-generate instruction decoding for a particular core
+ * from opcode tables in the future. */
int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
u32 inst = vcpu->arch.last_inst;
u32 ea;
int ra;
int rb;
- int rc;
int rs;
int rt;
int sprn;
- int dcrn;
enum emulation_result emulated = EMULATE_DONE;
int advance = 1;
+ /* this default type might be overwritten by subcategories */
+ kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
+
switch (get_op(inst)) {
- case 3: /* trap */
- printk("trap!\n");
- kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM);
+ case 3: /* trap */
+ vcpu->arch.esr |= ESR_PTR;
+ kvmppc_core_queue_program(vcpu);
advance = 0;
break;
- case 19:
- switch (get_xop(inst)) {
- case 50: /* rfi */
- kvmppc_emul_rfi(vcpu);
- advance = 0;
- break;
-
- default:
- emulated = EMULATE_FAIL;
- break;
- }
- break;
-
case 31:
switch (get_xop(inst)) {
@@ -255,27 +92,11 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
break;
- case 83: /* mfmsr */
- rt = get_rt(inst);
- vcpu->arch.gpr[rt] = vcpu->arch.msr;
- break;
-
case 87: /* lbzx */
rt = get_rt(inst);
emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
break;
- case 131: /* wrtee */
- rs = get_rs(inst);
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
- | (vcpu->arch.gpr[rs] & MSR_EE);
- break;
-
- case 146: /* mtmsr */
- rs = get_rs(inst);
- kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
- break;
-
case 151: /* stwx */
rs = get_rs(inst);
emulated = kvmppc_handle_store(run, vcpu,
@@ -283,11 +104,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
4, 1);
break;
- case 163: /* wrteei */
- vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
- | (inst & MSR_EE);
- break;
-
case 215: /* stbx */
rs = get_rs(inst);
emulated = kvmppc_handle_store(run, vcpu,
@@ -328,42 +144,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
vcpu->arch.gpr[ra] = ea;
break;
- case 323: /* mfdcr */
- dcrn = get_dcrn(inst);
- rt = get_rt(inst);
-
- /* The guest may access CPR0 registers to determine the timebase
- * frequency, and it must know the real host frequency because it
- * can directly access the timebase registers.
- *
- * It would be possible to emulate those accesses in userspace,
- * but userspace can really only figure out the end frequency.
- * We could decompose that into the factors that compute it, but
- * that's tricky math, and it's easier to just report the real
- * CPR0 values.
- */
- switch (dcrn) {
- case DCRN_CPR0_CONFIG_ADDR:
- vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr;
- break;
- case DCRN_CPR0_CONFIG_DATA:
- local_irq_disable();
- mtdcr(DCRN_CPR0_CONFIG_ADDR,
- vcpu->arch.cpr0_cfgaddr);
- vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA);
- local_irq_enable();
- break;
- default:
- run->dcr.dcrn = dcrn;
- run->dcr.data = 0;
- run->dcr.is_write = 0;
- vcpu->arch.io_gpr = rt;
- vcpu->arch.dcr_needed = 1;
- emulated = EMULATE_DO_DCR;
- }
-
- break;
-
case 339: /* mfspr */
sprn = get_sprn(inst);
rt = get_rt(inst);
@@ -373,26 +153,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
vcpu->arch.gpr[rt] = vcpu->arch.srr0; break;
case SPRN_SRR1:
vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
- case SPRN_MMUCR:
- vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break;
- case SPRN_PID:
- vcpu->arch.gpr[rt] = vcpu->arch.pid; break;
- case SPRN_IVPR:
- vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
- case SPRN_CCR0:
- vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break;
- case SPRN_CCR1:
- vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break;
case SPRN_PVR:
vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
- case SPRN_DEAR:
- vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
- case SPRN_ESR:
- vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
- case SPRN_DBCR0:
- vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
- case SPRN_DBCR1:
- vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
/* Note: mftb and TBRL/TBWL are user-accessible, so
* the guest can always access the real TB anyways.
@@ -413,42 +175,12 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
/* Note: SPRG4-7 are user-readable, so we don't get
* a trap. */
- case SPRN_IVOR0:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break;
- case SPRN_IVOR1:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break;
- case SPRN_IVOR2:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break;
- case SPRN_IVOR3:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break;
- case SPRN_IVOR4:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break;
- case SPRN_IVOR5:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break;
- case SPRN_IVOR6:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break;
- case SPRN_IVOR7:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break;
- case SPRN_IVOR8:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break;
- case SPRN_IVOR9:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break;
- case SPRN_IVOR10:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break;
- case SPRN_IVOR11:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break;
- case SPRN_IVOR12:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break;
- case SPRN_IVOR13:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break;
- case SPRN_IVOR14:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break;
- case SPRN_IVOR15:
- vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break;
-
default:
- printk("mfspr: unknown spr %x\n", sprn);
- vcpu->arch.gpr[rt] = 0;
+ emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, rt);
+ if (emulated == EMULATE_FAIL) {
+ printk("mfspr: unknown spr %x\n", sprn);
+ vcpu->arch.gpr[rt] = 0;
+ }
break;
}
break;
@@ -478,25 +210,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
vcpu->arch.gpr[ra] = ea;
break;
- case 451: /* mtdcr */
- dcrn = get_dcrn(inst);
- rs = get_rs(inst);
-
- /* emulate some access in kernel */
- switch (dcrn) {
- case DCRN_CPR0_CONFIG_ADDR:
- vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs];
- break;
- default:
- run->dcr.dcrn = dcrn;
- run->dcr.data = vcpu->arch.gpr[rs];
- run->dcr.is_write = 1;
- vcpu->arch.dcr_needed = 1;
- emulated = EMULATE_DO_DCR;
- }
-
- break;
-
case 467: /* mtspr */
sprn = get_sprn(inst);
rs = get_rs(inst);
@@ -505,22 +218,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
vcpu->arch.srr0 = vcpu->arch.gpr[rs]; break;
case SPRN_SRR1:
vcpu->arch.srr1 = vcpu->arch.gpr[rs]; break;
- case SPRN_MMUCR:
- vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break;
- case SPRN_PID:
- kvmppc_set_pid(vcpu, vcpu->arch.gpr[rs]); break;
- case SPRN_CCR0:
- vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break;
- case SPRN_CCR1:
- vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break;
- case SPRN_DEAR:
- vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
- case SPRN_ESR:
- vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
- case SPRN_DBCR0:
- vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
- case SPRN_DBCR1:
- vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
/* XXX We need to context-switch the timebase for
* watchdog and FIT. */
@@ -532,14 +229,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
kvmppc_emulate_dec(vcpu);
break;
- case SPRN_TSR:
- vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
-
- case SPRN_TCR:
- vcpu->arch.tcr = vcpu->arch.gpr[rs];
- kvmppc_emulate_dec(vcpu);
- break;
-
case SPRN_SPRG0:
vcpu->arch.sprg0 = vcpu->arch.gpr[rs]; break;
case SPRN_SPRG1:
@@ -549,56 +238,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
case SPRN_SPRG3:
vcpu->arch.sprg3 = vcpu->arch.gpr[rs]; break;
- /* Note: SPRG4-7 are user-readable. These values are
- * loaded into the real SPRGs when resuming the
- * guest. */
- case SPRN_SPRG4:
- vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
- case SPRN_SPRG5:
- vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
- case SPRN_SPRG6:
- vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
- case SPRN_SPRG7:
- vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
-
- case SPRN_IVPR:
- vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR0:
- vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR1:
- vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR2:
- vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR3:
- vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR4:
- vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR5:
- vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR6:
- vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR7:
- vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR8:
- vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR9:
- vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR10:
- vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR11:
- vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR12:
- vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR13:
- vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR14:
- vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break;
- case SPRN_IVOR15:
- vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break;
-
default:
- printk("mtspr: unknown spr %x\n", sprn);
- emulated = EMULATE_FAIL;
+ emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, rs);
+ if (emulated == EMULATE_FAIL)
+ printk("mtspr: unknown spr %x\n", sprn);
break;
}
break;
@@ -629,36 +272,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
4, 0);
break;
- case 978: /* tlbwe */
- emulated = kvmppc_emul_tlbwe(vcpu, inst);
- break;
-
- case 914: { /* tlbsx */
- int index;
- unsigned int as = get_mmucr_sts(vcpu);
- unsigned int pid = get_mmucr_stid(vcpu);
-
- rt = get_rt(inst);
- ra = get_ra(inst);
- rb = get_rb(inst);
- rc = get_rc(inst);
-
- ea = vcpu->arch.gpr[rb];
- if (ra)
- ea += vcpu->arch.gpr[ra];
-
- index = kvmppc_44x_tlb_index(vcpu, ea, pid, as);
- if (rc) {
- if (index < 0)
- vcpu->arch.cr &= ~0x20000000;
- else
- vcpu->arch.cr |= 0x20000000;
- }
- vcpu->arch.gpr[rt] = index;
-
- }
- break;
-
case 790: /* lhbrx */
rt = get_rt(inst);
emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
@@ -674,14 +287,9 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
2, 0);
break;
- case 966: /* iccci */
- break;
-
default:
- printk("unknown: op %d xop %d\n", get_op(inst),
- get_xop(inst));
+ /* Attempt core-specific emulation below. */
emulated = EMULATE_FAIL;
- break;
}
break;
@@ -764,12 +372,19 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
break;
default:
- printk("unknown op %d\n", get_op(inst));
emulated = EMULATE_FAIL;
- break;
}
- KVMTRACE_3D(PPC_INSTR, vcpu, inst, vcpu->arch.pc, emulated, entryexit);
+ if (emulated == EMULATE_FAIL) {
+ emulated = kvmppc_core_emulate_op(run, vcpu, inst, &advance);
+ if (emulated == EMULATE_FAIL) {
+ advance = 0;
+ printk(KERN_ERR "Couldn't emulate instruction 0x%08x "
+ "(op %d xop %d)\n", inst, get_op(inst), get_xop(inst));
+ }
+ }
+
+ KVMTRACE_3D(PPC_INSTR, vcpu, inst, (int)vcpu->arch.pc, emulated, entryexit);
if (advance)
vcpu->arch.pc += 4; /* Advance past emulated instruction. */
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 8bef0efcdfe1..2822c8ccfaaf 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -28,9 +28,9 @@
#include <asm/uaccess.h>
#include <asm/kvm_ppc.h>
#include <asm/tlbflush.h>
+#include "timing.h"
#include "../mm/mmu_decl.h"
-
gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
{
return gfn;
@@ -99,14 +99,7 @@ void kvm_arch_hardware_unsetup(void)
void kvm_arch_check_processor_compat(void *rtn)
{
- int r;
-
- if (strcmp(cur_cpu_spec->platform, "ppc440") == 0)
- r = 0;
- else
- r = -ENOTSUPP;
-
- *(int *)rtn = r;
+ *(int *)rtn = kvmppc_core_check_processor_compat();
}
struct kvm *kvm_arch_create_vm(void)
@@ -144,9 +137,6 @@ int kvm_dev_ioctl_check_extension(long ext)
int r;
switch (ext) {
- case KVM_CAP_USER_MEMORY:
- r = 1;
- break;
case KVM_CAP_COALESCED_MMIO:
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
break;
@@ -179,30 +169,15 @@ void kvm_arch_flush_shadow(struct kvm *kvm)
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
{
struct kvm_vcpu *vcpu;
- int err;
-
- vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
- if (!vcpu) {
- err = -ENOMEM;
- goto out;
- }
-
- err = kvm_vcpu_init(vcpu, kvm, id);
- if (err)
- goto free_vcpu;
-
+ vcpu = kvmppc_core_vcpu_create(kvm, id);
+ kvmppc_create_vcpu_debugfs(vcpu, id);
return vcpu;
-
-free_vcpu:
- kmem_cache_free(kvm_vcpu_cache, vcpu);
-out:
- return ERR_PTR(err);
}
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
{
- kvm_vcpu_uninit(vcpu);
- kmem_cache_free(kvm_vcpu_cache, vcpu);
+ kvmppc_remove_vcpu_debugfs(vcpu);
+ kvmppc_core_vcpu_free(vcpu);
}
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
@@ -212,16 +187,14 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
- unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER];
-
- return test_bit(priority, &vcpu->arch.pending_exceptions);
+ return kvmppc_core_pending_dec(vcpu);
}
static void kvmppc_decrementer_func(unsigned long data)
{
struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
- kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER);
+ kvmppc_core_queue_dec(vcpu);
if (waitqueue_active(&vcpu->wq)) {
wake_up_interruptible(&vcpu->wq);
@@ -242,96 +215,25 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
kvmppc_core_destroy_mmu(vcpu);
}
-/* Note: clearing MSR[DE] just means that the debug interrupt will not be
- * delivered *immediately*. Instead, it simply sets the appropriate DBSR bits.
- * If those DBSR bits are still set when MSR[DE] is re-enabled, the interrupt
- * will be delivered as an "imprecise debug event" (which is indicated by
- * DBSR[IDE].
- */
-static void kvmppc_disable_debug_interrupts(void)
-{
- mtmsr(mfmsr() & ~MSR_DE);
-}
-
-static void kvmppc_restore_host_debug_state(struct kvm_vcpu *vcpu)
-{
- kvmppc_disable_debug_interrupts();
-
- mtspr(SPRN_IAC1, vcpu->arch.host_iac[0]);
- mtspr(SPRN_IAC2, vcpu->arch.host_iac[1]);
- mtspr(SPRN_IAC3, vcpu->arch.host_iac[2]);
- mtspr(SPRN_IAC4, vcpu->arch.host_iac[3]);
- mtspr(SPRN_DBCR1, vcpu->arch.host_dbcr1);
- mtspr(SPRN_DBCR2, vcpu->arch.host_dbcr2);
- mtspr(SPRN_DBCR0, vcpu->arch.host_dbcr0);
- mtmsr(vcpu->arch.host_msr);
-}
-
-static void kvmppc_load_guest_debug_registers(struct kvm_vcpu *vcpu)
-{
- struct kvm_guest_debug *dbg = &vcpu->guest_debug;
- u32 dbcr0 = 0;
-
- vcpu->arch.host_msr = mfmsr();
- kvmppc_disable_debug_interrupts();
-
- /* Save host debug register state. */
- vcpu->arch.host_iac[0] = mfspr(SPRN_IAC1);
- vcpu->arch.host_iac[1] = mfspr(SPRN_IAC2);
- vcpu->arch.host_iac[2] = mfspr(SPRN_IAC3);
- vcpu->arch.host_iac[3] = mfspr(SPRN_IAC4);
- vcpu->arch.host_dbcr0 = mfspr(SPRN_DBCR0);
- vcpu->arch.host_dbcr1 = mfspr(SPRN_DBCR1);
- vcpu->arch.host_dbcr2 = mfspr(SPRN_DBCR2);
-
- /* set registers up for guest */
-
- if (dbg->bp[0]) {
- mtspr(SPRN_IAC1, dbg->bp[0]);
- dbcr0 |= DBCR0_IAC1 | DBCR0_IDM;
- }
- if (dbg->bp[1]) {
- mtspr(SPRN_IAC2, dbg->bp[1]);
- dbcr0 |= DBCR0_IAC2 | DBCR0_IDM;
- }
- if (dbg->bp[2]) {
- mtspr(SPRN_IAC3, dbg->bp[2]);
- dbcr0 |= DBCR0_IAC3 | DBCR0_IDM;
- }
- if (dbg->bp[3]) {
- mtspr(SPRN_IAC4, dbg->bp[3]);
- dbcr0 |= DBCR0_IAC4 | DBCR0_IDM;
- }
-
- mtspr(SPRN_DBCR0, dbcr0);
- mtspr(SPRN_DBCR1, 0);
- mtspr(SPRN_DBCR2, 0);
-}
-
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
- int i;
-
if (vcpu->guest_debug.enabled)
- kvmppc_load_guest_debug_registers(vcpu);
+ kvmppc_core_load_guest_debugstate(vcpu);
- /* Mark every guest entry in the shadow TLB entry modified, so that they
- * will all be reloaded on the next vcpu run (instead of being
- * demand-faulted). */
- for (i = 0; i <= tlb_44x_hwater; i++)
- kvmppc_tlbe_set_modified(vcpu, i);
+ kvmppc_core_vcpu_load(vcpu, cpu);
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
if (vcpu->guest_debug.enabled)
- kvmppc_restore_host_debug_state(vcpu);
+ kvmppc_core_load_host_debugstate(vcpu);
/* Don't leave guest TLB entries resident when being de-scheduled. */
/* XXX It would be nice to differentiate between heavyweight exit and
* sched_out here, since we could avoid the TLB flush for heavyweight
* exits. */
_tlbil_all();
+ kvmppc_core_vcpu_put(vcpu);
}
int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
@@ -355,14 +257,14 @@ int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu,
struct kvm_run *run)
{
- u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
+ ulong *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
*gpr = run->dcr.data;
}
static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
struct kvm_run *run)
{
- u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
+ ulong *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr];
if (run->mmio.len > sizeof(*gpr)) {
printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len);
@@ -460,7 +362,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
vcpu->arch.dcr_needed = 0;
}
- kvmppc_check_and_deliver_interrupts(vcpu);
+ kvmppc_core_deliver_interrupts(vcpu);
local_irq_disable();
kvm_guest_enter();
@@ -478,7 +380,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq)
{
- kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL);
+ kvmppc_core_queue_external(vcpu, irq);
if (waitqueue_active(&vcpu->wq)) {
wake_up_interruptible(&vcpu->wq);
diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c
new file mode 100644
index 000000000000..47ee603f558e
--- /dev/null
+++ b/arch/powerpc/kvm/timing.c
@@ -0,0 +1,239 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Hollis Blanchard <hollisb@us.ibm.com>
+ * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ */
+
+#include <linux/kvm_host.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include <asm/time.h>
+#include <asm-generic/div64.h>
+
+#include "timing.h"
+
+void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu)
+{
+ int i;
+
+ /* pause guest execution to avoid concurrent updates */
+ local_irq_disable();
+ mutex_lock(&vcpu->mutex);
+
+ vcpu->arch.last_exit_type = 0xDEAD;
+ for (i = 0; i < __NUMBER_OF_KVM_EXIT_TYPES; i++) {
+ vcpu->arch.timing_count_type[i] = 0;
+ vcpu->arch.timing_max_duration[i] = 0;
+ vcpu->arch.timing_min_duration[i] = 0xFFFFFFFF;
+ vcpu->arch.timing_sum_duration[i] = 0;
+ vcpu->arch.timing_sum_quad_duration[i] = 0;
+ }
+ vcpu->arch.timing_last_exit = 0;
+ vcpu->arch.timing_exit.tv64 = 0;
+ vcpu->arch.timing_last_enter.tv64 = 0;
+
+ mutex_unlock(&vcpu->mutex);
+ local_irq_enable();
+}
+
+static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type)
+{
+ u64 old;
+
+ do_div(duration, tb_ticks_per_usec);
+ if (unlikely(duration > 0xFFFFFFFF)) {
+ printk(KERN_ERR"%s - duration too big -> overflow"
+ " duration %lld type %d exit #%d\n",
+ __func__, duration, type,
+ vcpu->arch.timing_count_type[type]);
+ return;
+ }
+
+ vcpu->arch.timing_count_type[type]++;
+
+ /* sum */
+ old = vcpu->arch.timing_sum_duration[type];
+ vcpu->arch.timing_sum_duration[type] += duration;
+ if (unlikely(old > vcpu->arch.timing_sum_duration[type])) {
+ printk(KERN_ERR"%s - wrap adding sum of durations"
+ " old %lld new %lld type %d exit # of type %d\n",
+ __func__, old, vcpu->arch.timing_sum_duration[type],
+ type, vcpu->arch.timing_count_type[type]);
+ }
+
+ /* square sum */
+ old = vcpu->arch.timing_sum_quad_duration[type];
+ vcpu->arch.timing_sum_quad_duration[type] += (duration*duration);
+ if (unlikely(old > vcpu->arch.timing_sum_quad_duration[type])) {
+ printk(KERN_ERR"%s - wrap adding sum of squared durations"
+ " old %lld new %lld type %d exit # of type %d\n",
+ __func__, old,
+ vcpu->arch.timing_sum_quad_duration[type],
+ type, vcpu->arch.timing_count_type[type]);
+ }
+
+ /* set min/max */
+ if (unlikely(duration < vcpu->arch.timing_min_duration[type]))
+ vcpu->arch.timing_min_duration[type] = duration;
+ if (unlikely(duration > vcpu->arch.timing_max_duration[type]))
+ vcpu->arch.timing_max_duration[type] = duration;
+}
+
+void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu)
+{
+ u64 exit = vcpu->arch.timing_last_exit;
+ u64 enter = vcpu->arch.timing_last_enter.tv64;
+
+ /* save exit time, used next exit when the reenter time is known */
+ vcpu->arch.timing_last_exit = vcpu->arch.timing_exit.tv64;
+
+ if (unlikely(vcpu->arch.last_exit_type == 0xDEAD || exit == 0))
+ return; /* skip incomplete cycle (e.g. after reset) */
+
+ /* update statistics for average and standard deviation */
+ add_exit_timing(vcpu, (enter - exit), vcpu->arch.last_exit_type);
+ /* enter -> timing_last_exit is time spent in guest - log this too */
+ add_exit_timing(vcpu, (vcpu->arch.timing_last_exit - enter),
+ TIMEINGUEST);
+}
+
+static const char *kvm_exit_names[__NUMBER_OF_KVM_EXIT_TYPES] = {
+ [MMIO_EXITS] = "MMIO",
+ [DCR_EXITS] = "DCR",
+ [SIGNAL_EXITS] = "SIGNAL",
+ [ITLB_REAL_MISS_EXITS] = "ITLBREAL",
+ [ITLB_VIRT_MISS_EXITS] = "ITLBVIRT",
+ [DTLB_REAL_MISS_EXITS] = "DTLBREAL",
+ [DTLB_VIRT_MISS_EXITS] = "DTLBVIRT",
+ [SYSCALL_EXITS] = "SYSCALL",
+ [ISI_EXITS] = "ISI",
+ [DSI_EXITS] = "DSI",
+ [EMULATED_INST_EXITS] = "EMULINST",
+ [EMULATED_MTMSRWE_EXITS] = "EMUL_WAIT",
+ [EMULATED_WRTEE_EXITS] = "EMUL_WRTEE",
+ [EMULATED_MTSPR_EXITS] = "EMUL_MTSPR",
+ [EMULATED_MFSPR_EXITS] = "EMUL_MFSPR",
+ [EMULATED_MTMSR_EXITS] = "EMUL_MTMSR",
+ [EMULATED_MFMSR_EXITS] = "EMUL_MFMSR",
+ [EMULATED_TLBSX_EXITS] = "EMUL_TLBSX",
+ [EMULATED_TLBWE_EXITS] = "EMUL_TLBWE",
+ [EMULATED_RFI_EXITS] = "EMUL_RFI",
+ [DEC_EXITS] = "DEC",
+ [EXT_INTR_EXITS] = "EXTINT",
+ [HALT_WAKEUP] = "HALT",
+ [USR_PR_INST] = "USR_PR_INST",
+ [FP_UNAVAIL] = "FP_UNAVAIL",
+ [DEBUG_EXITS] = "DEBUG",
+ [TIMEINGUEST] = "TIMEINGUEST"
+};
+
+static int kvmppc_exit_timing_show(struct seq_file *m, void *private)
+{
+ struct kvm_vcpu *vcpu = m->private;
+ int i;
+
+ seq_printf(m, "%s", "type count min max sum sum_squared\n");
+
+ for (i = 0; i < __NUMBER_OF_KVM_EXIT_TYPES; i++) {
+ seq_printf(m, "%12s %10d %10lld %10lld %20lld %20lld\n",
+ kvm_exit_names[i],
+ vcpu->arch.timing_count_type[i],
+ vcpu->arch.timing_min_duration[i],
+ vcpu->arch.timing_max_duration[i],
+ vcpu->arch.timing_sum_duration[i],
+ vcpu->arch.timing_sum_quad_duration[i]);
+ }
+ return 0;
+}
+
+/* Write 'c' to clear the timing statistics. */
+static ssize_t kvmppc_exit_timing_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ int err = -EINVAL;
+ char c;
+
+ if (count > 1) {
+ goto done;
+ }
+
+ if (get_user(c, user_buf)) {
+ err = -EFAULT;
+ goto done;
+ }
+
+ if (c == 'c') {
+ struct seq_file *seqf = (struct seq_file *)file->private_data;
+ struct kvm_vcpu *vcpu = seqf->private;
+ /* Write does not affect our buffers previously generated with
+ * show. seq_file is locked here to prevent races of init with
+ * a show call */
+ mutex_lock(&seqf->lock);
+ kvmppc_init_timing_stats(vcpu);
+ mutex_unlock(&seqf->lock);
+ err = count;
+ }
+
+done:
+ return err;
+}
+
+static int kvmppc_exit_timing_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, kvmppc_exit_timing_show, inode->i_private);
+}
+
+static struct file_operations kvmppc_exit_timing_fops = {
+ .owner = THIS_MODULE,
+ .open = kvmppc_exit_timing_open,
+ .read = seq_read,
+ .write = kvmppc_exit_timing_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+void kvmppc_create_vcpu_debugfs(struct kvm_vcpu *vcpu, unsigned int id)
+{
+ static char dbg_fname[50];
+ struct dentry *debugfs_file;
+
+ snprintf(dbg_fname, sizeof(dbg_fname), "vm%u_vcpu%u_timing",
+ current->pid, id);
+ debugfs_file = debugfs_create_file(dbg_fname, 0666,
+ kvm_debugfs_dir, vcpu,
+ &kvmppc_exit_timing_fops);
+
+ if (!debugfs_file) {
+ printk(KERN_ERR"%s: error creating debugfs file %s\n",
+ __func__, dbg_fname);
+ return;
+ }
+
+ vcpu->arch.debugfs_exit_timing = debugfs_file;
+}
+
+void kvmppc_remove_vcpu_debugfs(struct kvm_vcpu *vcpu)
+{
+ if (vcpu->arch.debugfs_exit_timing) {
+ debugfs_remove(vcpu->arch.debugfs_exit_timing);
+ vcpu->arch.debugfs_exit_timing = NULL;
+ }
+}
diff --git a/arch/powerpc/kvm/timing.h b/arch/powerpc/kvm/timing.h
new file mode 100644
index 000000000000..bb13b1f3cd5a
--- /dev/null
+++ b/arch/powerpc/kvm/timing.h
@@ -0,0 +1,102 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * Authors: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
+ */
+
+#ifndef __POWERPC_KVM_EXITTIMING_H__
+#define __POWERPC_KVM_EXITTIMING_H__
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_host.h>
+
+#ifdef CONFIG_KVM_EXIT_TIMING
+void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu);
+void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu);
+void kvmppc_create_vcpu_debugfs(struct kvm_vcpu *vcpu, unsigned int id);
+void kvmppc_remove_vcpu_debugfs(struct kvm_vcpu *vcpu);
+
+static inline void kvmppc_set_exit_type(struct kvm_vcpu *vcpu, int type)
+{
+ vcpu->arch.last_exit_type = type;
+}
+
+#else
+/* if exit timing is not configured there is no need to build the c file */
+static inline void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu) {}
+static inline void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu) {}
+static inline void kvmppc_create_vcpu_debugfs(struct kvm_vcpu *vcpu,
+ unsigned int id) {}
+static inline void kvmppc_remove_vcpu_debugfs(struct kvm_vcpu *vcpu) {}
+static inline void kvmppc_set_exit_type(struct kvm_vcpu *vcpu, int type) {}
+#endif /* CONFIG_KVM_EXIT_TIMING */
+
+/* account the exit in kvm_stats */
+static inline void kvmppc_account_exit_stat(struct kvm_vcpu *vcpu, int type)
+{
+ /* type has to be known at build time for optimization */
+ BUILD_BUG_ON(__builtin_constant_p(type));
+ switch (type) {
+ case EXT_INTR_EXITS:
+ vcpu->stat.ext_intr_exits++;
+ break;
+ case DEC_EXITS:
+ vcpu->stat.dec_exits++;
+ break;
+ case EMULATED_INST_EXITS:
+ vcpu->stat.emulated_inst_exits++;
+ break;
+ case DCR_EXITS:
+ vcpu->stat.dcr_exits++;
+ break;
+ case DSI_EXITS:
+ vcpu->stat.dsi_exits++;
+ break;
+ case ISI_EXITS:
+ vcpu->stat.isi_exits++;
+ break;
+ case SYSCALL_EXITS:
+ vcpu->stat.syscall_exits++;
+ break;
+ case DTLB_REAL_MISS_EXITS:
+ vcpu->stat.dtlb_real_miss_exits++;
+ break;
+ case DTLB_VIRT_MISS_EXITS:
+ vcpu->stat.dtlb_virt_miss_exits++;
+ break;
+ case MMIO_EXITS:
+ vcpu->stat.mmio_exits++;
+ break;
+ case ITLB_REAL_MISS_EXITS:
+ vcpu->stat.itlb_real_miss_exits++;
+ break;
+ case ITLB_VIRT_MISS_EXITS:
+ vcpu->stat.itlb_virt_miss_exits++;
+ break;
+ case SIGNAL_EXITS:
+ vcpu->stat.signal_exits++;
+ break;
+ }
+}
+
+/* wrapper to set exit time and account for it in kvm_stats */
+static inline void kvmppc_account_exit(struct kvm_vcpu *vcpu, int type)
+{
+ kvmppc_set_exit_type(vcpu, type);
+ kvmppc_account_exit_stat(vcpu, type);
+}
+
+#endif /* __POWERPC_KVM_EXITTIMING_H__ */
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c
index 23cee39534fd..1971e4ee3d6e 100644
--- a/arch/powerpc/mm/fsl_booke_mmu.c
+++ b/arch/powerpc/mm/fsl_booke_mmu.c
@@ -56,18 +56,11 @@
extern void loadcam_entry(unsigned int index);
unsigned int tlbcam_index;
-unsigned int num_tlbcam_entries;
static unsigned long __cam0, __cam1, __cam2;
#define NUM_TLBCAMS (16)
-struct tlbcam {
- u32 MAS0;
- u32 MAS1;
- u32 MAS2;
- u32 MAS3;
- u32 MAS7;
-} TLBCAM[NUM_TLBCAMS];
+struct tlbcam TLBCAM[NUM_TLBCAMS];
struct tlbcamrange {
unsigned long start;
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 201c7a5486cb..9920d6a7cf29 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -512,6 +512,13 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0);
}
+unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
+{
+ unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
+
+ return 1UL << mmu_psize_to_shift(psize);
+}
+
/*
* Called by asm hashtable.S for doing lazy icache flush
*/
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 53b06ebb3f2f..f00f09a77f12 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -132,7 +132,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
/* this should work for most non-highmem platforms */
zone = pgdata->node_zones;
- return __add_pages(zone, start_pfn, nr_pages);
+ return __add_pages(nid, zone, start_pfn, nr_pages);
}
#endif /* CONFIG_MEMORY_HOTPLUG */
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 4314b39b6faf..d1f9c62dc177 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -30,11 +30,11 @@
#if defined(CONFIG_40x) || defined(CONFIG_8xx)
static inline void _tlbil_all(void)
{
- asm volatile ("sync; tlbia; isync" : : : "memory")
+ asm volatile ("sync; tlbia; isync" : : : "memory");
}
static inline void _tlbil_pid(unsigned int pid)
{
- asm volatile ("sync; tlbia; isync" : : : "memory")
+ asm volatile ("sync; tlbia; isync" : : : "memory");
}
#else /* CONFIG_40x || CONFIG_8xx */
extern void _tlbil_all(void);
@@ -47,7 +47,7 @@ extern void _tlbil_pid(unsigned int pid);
#ifdef CONFIG_8xx
static inline void _tlbil_va(unsigned long address, unsigned int pid)
{
- asm volatile ("tlbie %0; sync" : : "r" (address) : "memory")
+ asm volatile ("tlbie %0; sync" : : "r" (address) : "memory");
}
#else /* CONFIG_8xx */
extern void _tlbil_va(unsigned long address, unsigned int pid);
@@ -75,6 +75,15 @@ extern void _tlbia(void);
#endif /* CONFIG_PPC_MMU_NOHASH */
#ifdef CONFIG_PPC32
+
+struct tlbcam {
+ u32 MAS0;
+ u32 MAS1;
+ u32 MAS2;
+ u32 MAS3;
+ u32 MAS7;
+};
+
extern void mapin_ram(void);
extern int map_page(unsigned long va, phys_addr_t pa, int flags);
extern void setbat(int index, unsigned long virt, phys_addr_t phys,
@@ -90,8 +99,6 @@ extern unsigned int rtas_data, rtas_size;
struct hash_pte;
extern struct hash_pte *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
-
-extern unsigned int num_tlbcam_entries;
#endif
extern unsigned long ioremap_bot;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index cf81049e1e51..7393bd76d698 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -822,42 +822,50 @@ static void __init dump_numa_memory_topology(void)
* required. nid is the preferred node and end is the physical address of
* the highest address in the node.
*
- * Returns the physical address of the memory.
+ * Returns the virtual address of the memory.
*/
-static void __init *careful_allocation(int nid, unsigned long size,
+static void __init *careful_zallocation(int nid, unsigned long size,
unsigned long align,
unsigned long end_pfn)
{
+ void *ret;
int new_nid;
- unsigned long ret = __lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT);
+ unsigned long ret_paddr;
+
+ ret_paddr = __lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT);
/* retry over all memory */
- if (!ret)
- ret = __lmb_alloc_base(size, align, lmb_end_of_DRAM());
+ if (!ret_paddr)
+ ret_paddr = __lmb_alloc_base(size, align, lmb_end_of_DRAM());
- if (!ret)
- panic("numa.c: cannot allocate %lu bytes on node %d",
+ if (!ret_paddr)
+ panic("numa.c: cannot allocate %lu bytes for node %d",
size, nid);
+ ret = __va(ret_paddr);
+
/*
- * If the memory came from a previously allocated node, we must
- * retry with the bootmem allocator.
+ * We initialize the nodes in numeric order: 0, 1, 2...
+ * and hand over control from the LMB allocator to the
+ * bootmem allocator. If this function is called for
+ * node 5, then we know that all nodes <5 are using the
+ * bootmem allocator instead of the LMB allocator.
+ *
+ * So, check the nid from which this allocation came
+ * and double check to see if we need to use bootmem
+ * instead of the LMB. We don't free the LMB memory
+ * since it would be useless.
*/
- new_nid = early_pfn_to_nid(ret >> PAGE_SHIFT);
+ new_nid = early_pfn_to_nid(ret_paddr >> PAGE_SHIFT);
if (new_nid < nid) {
- ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(new_nid),
+ ret = __alloc_bootmem_node(NODE_DATA(new_nid),
size, align, 0);
- if (!ret)
- panic("numa.c: cannot allocate %lu bytes on node %d",
- size, new_nid);
-
- ret = __pa(ret);
-
- dbg("alloc_bootmem %lx %lx\n", ret, size);
+ dbg("alloc_bootmem %p %lx\n", ret, size);
}
- return (void *)ret;
+ memset(ret, 0, size);
+ return ret;
}
static struct notifier_block __cpuinitdata ppc64_numa_nb = {
@@ -952,7 +960,7 @@ void __init do_init_bootmem(void)
for_each_online_node(nid) {
unsigned long start_pfn, end_pfn;
- unsigned long bootmem_paddr;
+ void *bootmem_vaddr;
unsigned long bootmap_pages;
get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
@@ -964,11 +972,9 @@ void __init do_init_bootmem(void)
* previous nodes' bootmem to be initialized and have
* all reserved areas marked.
*/
- NODE_DATA(nid) = careful_allocation(nid,
+ NODE_DATA(nid) = careful_zallocation(nid,
sizeof(struct pglist_data),
SMP_CACHE_BYTES, end_pfn);
- NODE_DATA(nid) = __va(NODE_DATA(nid));
- memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
dbg("node %d\n", nid);
dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
@@ -984,20 +990,20 @@ void __init do_init_bootmem(void)
dbg("end_paddr = %lx\n", end_pfn << PAGE_SHIFT);
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
- bootmem_paddr = (unsigned long)careful_allocation(nid,
+ bootmem_vaddr = careful_zallocation(nid,
bootmap_pages << PAGE_SHIFT,
PAGE_SIZE, end_pfn);
- memset(__va(bootmem_paddr), 0, bootmap_pages << PAGE_SHIFT);
- dbg("bootmap_paddr = %lx\n", bootmem_paddr);
+ dbg("bootmap_vaddr = %p\n", bootmem_vaddr);
- init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
+ init_bootmem_node(NODE_DATA(nid),
+ __pa(bootmem_vaddr) >> PAGE_SHIFT,
start_pfn, end_pfn);
free_bootmem_with_active_regions(nid, end_pfn);
/*
* Be very careful about moving this around. Future
- * calls to careful_allocation() depend on this getting
+ * calls to careful_zallocation() depend on this getting
* done correctly.
*/
mark_reserved_regions_for_nid(nid);
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 38ff35f2142a..22972cd83cc9 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -266,7 +266,8 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
/* The PTE should never be already set nor present in the
* hash table
*/
- BUG_ON(pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE));
+ BUG_ON((pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)) &&
+ flags);
set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT,
__pgprot(flags)));
}
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 45d925360b89..fe65c405412c 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -123,9 +123,9 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
int wimgxpp;
struct ppc_bat *bat = BATS[index];
- if (((flags & _PAGE_NO_CACHE) == 0) &&
- cpu_has_feature(CPU_FTR_NEED_COHERENT))
- flags |= _PAGE_COHERENT;
+ if ((flags & _PAGE_NO_CACHE) ||
+ (cpu_has_feature(CPU_FTR_NEED_COHERENT) == 0))
+ flags &= ~_PAGE_COHERENT;
bl = (size >> 17) - 1;
if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index db44e02e045b..ba5194817f8a 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -710,9 +710,18 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
unsigned long len)
{
struct slice_mask mask, available;
+ unsigned int psize = mm->context.user_psize;
mask = slice_range_to_mask(addr, len);
- available = slice_mask_for_size(mm, mm->context.user_psize);
+ available = slice_mask_for_size(mm, psize);
+#ifdef CONFIG_PPC_64K_PAGES
+ /* We need to account for 4k slices too */
+ if (psize == MMU_PAGE_64K) {
+ struct slice_mask compat_mask;
+ compat_mask = slice_mask_for_size(mm, MMU_PAGE_4K);
+ or_mask(available, compat_mask);
+ }
+#endif
#if 0 /* too verbose */
slice_dbg("is_hugepage_only_range(mm=%p, addr=%lx, len=%lx)\n",
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 60e6032a8088..98cd1dc2ae75 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -251,8 +251,8 @@ void __init stabs_alloc(void)
paca[cpu].stab_addr = newstab;
paca[cpu].stab_real = virt_to_abs(newstab);
- printk(KERN_INFO "Segment table for CPU %d at 0x%lx "
- "virtual, 0x%lx absolute\n",
+ printk(KERN_INFO "Segment table for CPU %d at 0x%llx "
+ "virtual, 0x%llx absolute\n",
cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
}
}
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index 803a64c02b06..39ac22b13c73 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -189,8 +189,9 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
smp_call_function(do_flush_tlb_mm_ipi, NULL, 1);
_tlbil_pid(0);
preempt_enable();
-#endif
+#else
_tlbil_pid(0);
+#endif
}
EXPORT_SYMBOL(flush_tlb_kernel_range);
diff --git a/arch/powerpc/oprofile/cell/pr_util.h b/arch/powerpc/oprofile/cell/pr_util.h
index 628009c01958..964b93974d89 100644
--- a/arch/powerpc/oprofile/cell/pr_util.h
+++ b/arch/powerpc/oprofile/cell/pr_util.h
@@ -30,6 +30,10 @@
extern struct delayed_work spu_work;
extern int spu_prof_running;
+#define TRACE_ARRAY_SIZE 1024
+
+extern spinlock_t oprof_spu_smpl_arry_lck;
+
struct spu_overlay_info { /* map of sections within an SPU overlay */
unsigned int vma; /* SPU virtual memory address from elf */
unsigned int size; /* size of section from elf */
@@ -79,7 +83,7 @@ struct spu_buffer {
* the vma-to-fileoffset map.
*/
struct vma_to_fileoffset_map *create_vma_map(const struct spu *spu,
- u64 objectid);
+ unsigned long objectid);
unsigned int vma_map_lookup(struct vma_to_fileoffset_map *map,
unsigned int vma, const struct spu *aSpu,
int *grd_val);
@@ -89,10 +93,11 @@ void vma_map_free(struct vma_to_fileoffset_map *map);
* Entry point for SPU profiling.
* cycles_reset is the SPU_CYCLES count value specified by the user.
*/
-int start_spu_profiling(unsigned int cycles_reset);
-
-void stop_spu_profiling(void);
+int start_spu_profiling_cycles(unsigned int cycles_reset);
+void start_spu_profiling_events(void);
+void stop_spu_profiling_cycles(void);
+void stop_spu_profiling_events(void);
/* add the necessary profiling hooks */
int spu_sync_start(void);
diff --git a/arch/powerpc/oprofile/cell/spu_profiler.c b/arch/powerpc/oprofile/cell/spu_profiler.c
index dd499c3e9da7..9305ddaac512 100644
--- a/arch/powerpc/oprofile/cell/spu_profiler.c
+++ b/arch/powerpc/oprofile/cell/spu_profiler.c
@@ -18,11 +18,21 @@
#include <asm/cell-pmu.h>
#include "pr_util.h"
-#define TRACE_ARRAY_SIZE 1024
#define SCALE_SHIFT 14
static u32 *samples;
+/* spu_prof_running is a flag used to indicate if spu profiling is enabled
+ * or not. It is set by the routines start_spu_profiling_cycles() and
+ * start_spu_profiling_events(). The flag is cleared by the routines
+ * stop_spu_profiling_cycles() and stop_spu_profiling_events(). These
+ * routines are called via global_start() and global_stop() which are called in
+ * op_powerpc_start() and op_powerpc_stop(). These routines are called once
+ * per system as a result of the user starting/stopping oprofile. Hence, only
+ * one CPU per user at a time will be changing the value of spu_prof_running.
+ * In general, OProfile does not protect against multiple users trying to run
+ * OProfile at a time.
+ */
int spu_prof_running;
static unsigned int profiling_interval;
@@ -31,8 +41,8 @@ static unsigned int profiling_interval;
#define SPU_PC_MASK 0xFFFF
-static DEFINE_SPINLOCK(sample_array_lock);
-unsigned long sample_array_lock_flags;
+DEFINE_SPINLOCK(oprof_spu_smpl_arry_lck);
+unsigned long oprof_spu_smpl_arry_lck_flags;
void set_spu_profiling_frequency(unsigned int freq_khz, unsigned int cycles_reset)
{
@@ -49,7 +59,7 @@ void set_spu_profiling_frequency(unsigned int freq_khz, unsigned int cycles_rese
* of precision. This is close enough for the purpose at hand.
*
* The value of the timeout should be small enough that the hw
- * trace buffer will not get more then about 1/3 full for the
+ * trace buffer will not get more than about 1/3 full for the
* maximum user specified (the LFSR value) hw sampling frequency.
* This is to ensure the trace buffer will never fill even if the
* kernel thread scheduling varies under a heavy system load.
@@ -145,13 +155,13 @@ static enum hrtimer_restart profile_spus(struct hrtimer *timer)
* sample array must be loaded and then processed for a given
* cpu. The sample array is not per cpu.
*/
- spin_lock_irqsave(&sample_array_lock,
- sample_array_lock_flags);
+ spin_lock_irqsave(&oprof_spu_smpl_arry_lck,
+ oprof_spu_smpl_arry_lck_flags);
num_samples = cell_spu_pc_collection(cpu);
if (num_samples == 0) {
- spin_unlock_irqrestore(&sample_array_lock,
- sample_array_lock_flags);
+ spin_unlock_irqrestore(&oprof_spu_smpl_arry_lck,
+ oprof_spu_smpl_arry_lck_flags);
continue;
}
@@ -162,8 +172,8 @@ static enum hrtimer_restart profile_spus(struct hrtimer *timer)
num_samples);
}
- spin_unlock_irqrestore(&sample_array_lock,
- sample_array_lock_flags);
+ spin_unlock_irqrestore(&oprof_spu_smpl_arry_lck,
+ oprof_spu_smpl_arry_lck_flags);
}
smp_wmb(); /* insure spu event buffer updates are written */
@@ -182,13 +192,13 @@ static enum hrtimer_restart profile_spus(struct hrtimer *timer)
static struct hrtimer timer;
/*
- * Entry point for SPU profiling.
+ * Entry point for SPU cycle profiling.
* NOTE: SPU profiling is done system-wide, not per-CPU.
*
* cycles_reset is the count value specified by the user when
* setting up OProfile to count SPU_CYCLES.
*/
-int start_spu_profiling(unsigned int cycles_reset)
+int start_spu_profiling_cycles(unsigned int cycles_reset)
{
ktime_t kt;
@@ -212,10 +222,30 @@ int start_spu_profiling(unsigned int cycles_reset)
return 0;
}
-void stop_spu_profiling(void)
+/*
+ * Entry point for SPU event profiling.
+ * NOTE: SPU profiling is done system-wide, not per-CPU.
+ *
+ * cycles_reset is the count value specified by the user when
+ * setting up OProfile to count SPU_CYCLES.
+ */
+void start_spu_profiling_events(void)
+{
+ spu_prof_running = 1;
+ schedule_delayed_work(&spu_work, DEFAULT_TIMER_EXPIRE);
+
+ return;
+}
+
+void stop_spu_profiling_cycles(void)
{
spu_prof_running = 0;
hrtimer_cancel(&timer);
kfree(samples);
- pr_debug("SPU_PROF: stop_spu_profiling issued\n");
+ pr_debug("SPU_PROF: stop_spu_profiling_cycles issued\n");
+}
+
+void stop_spu_profiling_events(void)
+{
+ spu_prof_running = 0;
}
diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c
index 2949126d28d1..6b793aeda72e 100644
--- a/arch/powerpc/oprofile/cell/spu_task_sync.c
+++ b/arch/powerpc/oprofile/cell/spu_task_sync.c
@@ -297,7 +297,7 @@ static inline unsigned long fast_get_dcookie(struct path *path)
{
unsigned long cookie;
- if (path->dentry->d_cookie)
+ if (path->dentry->d_flags & DCACHE_COOKIE)
return (unsigned long)path->dentry;
get_dcookie(path, &cookie);
return cookie;
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index 17807acb05d9..21f16edf6c8d 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -132,6 +132,28 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root)
oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
+#ifdef CONFIG_OPROFILE_CELL
+ /* create a file the user tool can check to see what level of profiling
+ * support exits with this kernel. Initialize bit mask to indicate
+ * what support the kernel has:
+ * bit 0 - Supports SPU event profiling in addition to PPU
+ * event and cycles; and SPU cycle profiling
+ * bits 1-31 - Currently unused.
+ *
+ * If the file does not exist, then the kernel only supports SPU
+ * cycle profiling, PPU event and cycle profiling.
+ */
+ oprofilefs_create_ulong(sb, root, "cell_support", &sys.cell_support);
+ sys.cell_support = 0x1; /* Note, the user OProfile tool must check
+ * that this bit is set before attempting to
+ * user SPU event profiling. Older kernels
+ * will not have this file, hence the user
+ * tool is not allowed to do SPU event
+ * profiling on older kernels. Older kernels
+ * will accept SPU events but collected data
+ * is garbage.
+ */
+#endif
#endif
for (i = 0; i < model->num_counters; ++i) {
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
index 25a4ec2514a3..ae06c6236d9c 100644
--- a/arch/powerpc/oprofile/op_model_cell.c
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -40,14 +40,15 @@
#include "../platforms/cell/interrupt.h"
#include "cell/pr_util.h"
-static void cell_global_stop_spu(void);
+#define PPU_PROFILING 0
+#define SPU_PROFILING_CYCLES 1
+#define SPU_PROFILING_EVENTS 2
-/*
- * spu_cycle_reset is the number of cycles between samples.
- * This variable is used for SPU profiling and should ONLY be set
- * at the beginning of cell_reg_setup; otherwise, it's read-only.
- */
-static unsigned int spu_cycle_reset;
+#define SPU_EVENT_NUM_START 4100
+#define SPU_EVENT_NUM_STOP 4399
+#define SPU_PROFILE_EVENT_ADDR 4363 /* spu, address trace, decimal */
+#define SPU_PROFILE_EVENT_ADDR_MASK_A 0x146 /* sub unit set to zero */
+#define SPU_PROFILE_EVENT_ADDR_MASK_B 0x186 /* sub unit set to zero */
#define NUM_SPUS_PER_NODE 8
#define SPU_CYCLES_EVENT_NUM 2 /* event number for SPU_CYCLES */
@@ -66,6 +67,21 @@ static unsigned int spu_cycle_reset;
#define MAX_SPU_COUNT 0xFFFFFF /* maximum 24 bit LFSR value */
+/* Minumum HW interval timer setting to send value to trace buffer is 10 cycle.
+ * To configure counter to send value every N cycles set counter to
+ * 2^32 - 1 - N.
+ */
+#define NUM_INTERVAL_CYC 0xFFFFFFFF - 10
+
+/*
+ * spu_cycle_reset is the number of cycles between samples.
+ * This variable is used for SPU profiling and should ONLY be set
+ * at the beginning of cell_reg_setup; otherwise, it's read-only.
+ */
+static unsigned int spu_cycle_reset;
+static unsigned int profiling_mode;
+static int spu_evnt_phys_spu_indx;
+
struct pmc_cntrl_data {
unsigned long vcntr;
unsigned long evnts;
@@ -105,6 +121,8 @@ struct pm_cntrl {
u16 trace_mode;
u16 freeze;
u16 count_mode;
+ u16 spu_addr_trace;
+ u8 trace_buf_ovflw;
};
static struct {
@@ -122,7 +140,7 @@ static struct {
#define GET_INPUT_CONTROL(x) ((x & 0x00000004) >> 2)
static DEFINE_PER_CPU(unsigned long[NR_PHYS_CTRS], pmc_values);
-
+static unsigned long spu_pm_cnt[MAX_NUMNODES * NUM_SPUS_PER_NODE];
static struct pmc_cntrl_data pmc_cntrl[NUM_THREADS][NR_PHYS_CTRS];
/*
@@ -152,6 +170,7 @@ static u32 hdw_thread;
static u32 virt_cntr_inter_mask;
static struct timer_list timer_virt_cntr;
+static struct timer_list timer_spu_event_swap;
/*
* pm_signal needs to be global since it is initialized in
@@ -165,7 +184,7 @@ static int spu_rtas_token; /* token for SPU cycle profiling */
static u32 reset_value[NR_PHYS_CTRS];
static int num_counters;
static int oprofile_running;
-static DEFINE_SPINLOCK(virt_cntr_lock);
+static DEFINE_SPINLOCK(cntr_lock);
static u32 ctr_enabled;
@@ -336,13 +355,13 @@ static void set_pm_event(u32 ctr, int event, u32 unit_mask)
for (i = 0; i < NUM_DEBUG_BUS_WORDS; i++) {
if (bus_word & (1 << i)) {
pm_regs.debug_bus_control |=
- (bus_type << (30 - (2 * i)));
+ (bus_type << (30 - (2 * i)));
for (j = 0; j < NUM_INPUT_BUS_WORDS; j++) {
if (input_bus[j] == 0xff) {
input_bus[j] = i;
pm_regs.group_control |=
- (i << (30 - (2 * j)));
+ (i << (30 - (2 * j)));
break;
}
@@ -367,12 +386,16 @@ static void write_pm_cntrl(int cpu)
if (pm_regs.pm_cntrl.stop_at_max == 1)
val |= CBE_PM_STOP_AT_MAX;
- if (pm_regs.pm_cntrl.trace_mode == 1)
+ if (pm_regs.pm_cntrl.trace_mode != 0)
val |= CBE_PM_TRACE_MODE_SET(pm_regs.pm_cntrl.trace_mode);
+ if (pm_regs.pm_cntrl.trace_buf_ovflw == 1)
+ val |= CBE_PM_TRACE_BUF_OVFLW(pm_regs.pm_cntrl.trace_buf_ovflw);
if (pm_regs.pm_cntrl.freeze == 1)
val |= CBE_PM_FREEZE_ALL_CTRS;
+ val |= CBE_PM_SPU_ADDR_TRACE_SET(pm_regs.pm_cntrl.spu_addr_trace);
+
/*
* Routine set_count_mode must be called previously to set
* the count mode based on the user selection of user and kernel.
@@ -441,7 +464,7 @@ static void cell_virtual_cntr(unsigned long data)
* not both playing with the counters on the same node.
*/
- spin_lock_irqsave(&virt_cntr_lock, flags);
+ spin_lock_irqsave(&cntr_lock, flags);
prev_hdw_thread = hdw_thread;
@@ -480,7 +503,7 @@ static void cell_virtual_cntr(unsigned long data)
cbe_disable_pm_interrupts(cpu);
for (i = 0; i < num_counters; i++) {
per_cpu(pmc_values, cpu + prev_hdw_thread)[i]
- = cbe_read_ctr(cpu, i);
+ = cbe_read_ctr(cpu, i);
if (per_cpu(pmc_values, cpu + next_hdw_thread)[i]
== 0xFFFFFFFF)
@@ -527,7 +550,7 @@ static void cell_virtual_cntr(unsigned long data)
cbe_enable_pm(cpu);
}
- spin_unlock_irqrestore(&virt_cntr_lock, flags);
+ spin_unlock_irqrestore(&cntr_lock, flags);
mod_timer(&timer_virt_cntr, jiffies + HZ / 10);
}
@@ -541,38 +564,146 @@ static void start_virt_cntrs(void)
add_timer(&timer_virt_cntr);
}
-/* This function is called once for all cpus combined */
-static int cell_reg_setup(struct op_counter_config *ctr,
+static int cell_reg_setup_spu_cycles(struct op_counter_config *ctr,
struct op_system_config *sys, int num_ctrs)
{
- int i, j, cpu;
- spu_cycle_reset = 0;
+ spu_cycle_reset = ctr[0].count;
- if (ctr[0].event == SPU_CYCLES_EVENT_NUM) {
- spu_cycle_reset = ctr[0].count;
+ /*
+ * Each node will need to make the rtas call to start
+ * and stop SPU profiling. Get the token once and store it.
+ */
+ spu_rtas_token = rtas_token("ibm,cbe-spu-perftools");
+
+ if (unlikely(spu_rtas_token == RTAS_UNKNOWN_SERVICE)) {
+ printk(KERN_ERR
+ "%s: rtas token ibm,cbe-spu-perftools unknown\n",
+ __func__);
+ return -EIO;
+ }
+ return 0;
+}
+
+/* Unfortunately, the hardware will only support event profiling
+ * on one SPU per node at a time. Therefore, we must time slice
+ * the profiling across all SPUs in the node. Note, we do this
+ * in parallel for each node. The following routine is called
+ * periodically based on kernel timer to switch which SPU is
+ * being monitored in a round robbin fashion.
+ */
+static void spu_evnt_swap(unsigned long data)
+{
+ int node;
+ int cur_phys_spu, nxt_phys_spu, cur_spu_evnt_phys_spu_indx;
+ unsigned long flags;
+ int cpu;
+ int ret;
+ u32 interrupt_mask;
+
+
+ /* enable interrupts on cntr 0 */
+ interrupt_mask = CBE_PM_CTR_OVERFLOW_INTR(0);
+
+ hdw_thread = 0;
+
+ /* Make sure spu event interrupt handler and spu event swap
+ * don't access the counters simultaneously.
+ */
+ spin_lock_irqsave(&cntr_lock, flags);
+
+ cur_spu_evnt_phys_spu_indx = spu_evnt_phys_spu_indx;
+
+ if (++(spu_evnt_phys_spu_indx) == NUM_SPUS_PER_NODE)
+ spu_evnt_phys_spu_indx = 0;
+
+ pm_signal[0].sub_unit = spu_evnt_phys_spu_indx;
+ pm_signal[1].sub_unit = spu_evnt_phys_spu_indx;
+ pm_signal[2].sub_unit = spu_evnt_phys_spu_indx;
+
+ /* switch the SPU being profiled on each node */
+ for_each_online_cpu(cpu) {
+ if (cbe_get_hw_thread_id(cpu))
+ continue;
+
+ node = cbe_cpu_to_node(cpu);
+ cur_phys_spu = (node * NUM_SPUS_PER_NODE)
+ + cur_spu_evnt_phys_spu_indx;
+ nxt_phys_spu = (node * NUM_SPUS_PER_NODE)
+ + spu_evnt_phys_spu_indx;
/*
- * Each node will need to make the rtas call to start
- * and stop SPU profiling. Get the token once and store it.
+ * stop counters, save counter values, restore counts
+ * for previous physical SPU
*/
- spu_rtas_token = rtas_token("ibm,cbe-spu-perftools");
+ cbe_disable_pm(cpu);
+ cbe_disable_pm_interrupts(cpu);
- if (unlikely(spu_rtas_token == RTAS_UNKNOWN_SERVICE)) {
- printk(KERN_ERR
- "%s: rtas token ibm,cbe-spu-perftools unknown\n",
- __func__);
- return -EIO;
- }
+ spu_pm_cnt[cur_phys_spu]
+ = cbe_read_ctr(cpu, 0);
+
+ /* restore previous count for the next spu to sample */
+ /* NOTE, hardware issue, counter will not start if the
+ * counter value is at max (0xFFFFFFFF).
+ */
+ if (spu_pm_cnt[nxt_phys_spu] >= 0xFFFFFFFF)
+ cbe_write_ctr(cpu, 0, 0xFFFFFFF0);
+ else
+ cbe_write_ctr(cpu, 0, spu_pm_cnt[nxt_phys_spu]);
+
+ pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
+
+ /* setup the debug bus measure the one event and
+ * the two events to route the next SPU's PC on
+ * the debug bus
+ */
+ ret = pm_rtas_activate_signals(cbe_cpu_to_node(cpu), 3);
+ if (ret)
+ printk(KERN_ERR "%s: pm_rtas_activate_signals failed, "
+ "SPU event swap\n", __func__);
+
+ /* clear the trace buffer, don't want to take PC for
+ * previous SPU*/
+ cbe_write_pm(cpu, trace_address, 0);
+
+ enable_ctr(cpu, 0, pm_regs.pm07_cntrl);
+
+ /* Enable interrupts on the CPU thread that is starting */
+ cbe_enable_pm_interrupts(cpu, hdw_thread,
+ interrupt_mask);
+ cbe_enable_pm(cpu);
}
- pm_rtas_token = rtas_token("ibm,cbe-perftools");
+ spin_unlock_irqrestore(&cntr_lock, flags);
+ /* swap approximately every 0.1 seconds */
+ mod_timer(&timer_spu_event_swap, jiffies + HZ / 25);
+}
+
+static void start_spu_event_swap(void)
+{
+ init_timer(&timer_spu_event_swap);
+ timer_spu_event_swap.function = spu_evnt_swap;
+ timer_spu_event_swap.data = 0UL;
+ timer_spu_event_swap.expires = jiffies + HZ / 25;
+ add_timer(&timer_spu_event_swap);
+}
+
+static int cell_reg_setup_spu_events(struct op_counter_config *ctr,
+ struct op_system_config *sys, int num_ctrs)
+{
+ int i;
+
+ /* routine is called once for all nodes */
+
+ spu_evnt_phys_spu_indx = 0;
/*
- * For all events excetp PPU CYCLEs, each node will need to make
+ * For all events except PPU CYCLEs, each node will need to make
* the rtas cbe-perftools call to setup and reset the debug bus.
* Make the token lookup call once and store it in the global
* variable pm_rtas_token.
*/
+ pm_rtas_token = rtas_token("ibm,cbe-perftools");
+
if (unlikely(pm_rtas_token == RTAS_UNKNOWN_SERVICE)) {
printk(KERN_ERR
"%s: rtas token ibm,cbe-perftools unknown\n",
@@ -580,6 +711,58 @@ static int cell_reg_setup(struct op_counter_config *ctr,
return -EIO;
}
+ /* setup the pm_control register settings,
+ * settings will be written per node by the
+ * cell_cpu_setup() function.
+ */
+ pm_regs.pm_cntrl.trace_buf_ovflw = 1;
+
+ /* Use the occurrence trace mode to have SPU PC saved
+ * to the trace buffer. Occurrence data in trace buffer
+ * is not used. Bit 2 must be set to store SPU addresses.
+ */
+ pm_regs.pm_cntrl.trace_mode = 2;
+
+ pm_regs.pm_cntrl.spu_addr_trace = 0x1; /* using debug bus
+ event 2 & 3 */
+
+ /* setup the debug bus event array with the SPU PC routing events.
+ * Note, pm_signal[0] will be filled in by set_pm_event() call below.
+ */
+ pm_signal[1].signal_group = SPU_PROFILE_EVENT_ADDR / 100;
+ pm_signal[1].bus_word = GET_BUS_WORD(SPU_PROFILE_EVENT_ADDR_MASK_A);
+ pm_signal[1].bit = SPU_PROFILE_EVENT_ADDR % 100;
+ pm_signal[1].sub_unit = spu_evnt_phys_spu_indx;
+
+ pm_signal[2].signal_group = SPU_PROFILE_EVENT_ADDR / 100;
+ pm_signal[2].bus_word = GET_BUS_WORD(SPU_PROFILE_EVENT_ADDR_MASK_B);
+ pm_signal[2].bit = SPU_PROFILE_EVENT_ADDR % 100;
+ pm_signal[2].sub_unit = spu_evnt_phys_spu_indx;
+
+ /* Set the user selected spu event to profile on,
+ * note, only one SPU profiling event is supported
+ */
+ num_counters = 1; /* Only support one SPU event at a time */
+ set_pm_event(0, ctr[0].event, ctr[0].unit_mask);
+
+ reset_value[0] = 0xFFFFFFFF - ctr[0].count;
+
+ /* global, used by cell_cpu_setup */
+ ctr_enabled |= 1;
+
+ /* Initialize the count for each SPU to the reset value */
+ for (i=0; i < MAX_NUMNODES * NUM_SPUS_PER_NODE; i++)
+ spu_pm_cnt[i] = reset_value[0];
+
+ return 0;
+}
+
+static int cell_reg_setup_ppu(struct op_counter_config *ctr,
+ struct op_system_config *sys, int num_ctrs)
+{
+ /* routine is called once for all nodes */
+ int i, j, cpu;
+
num_counters = num_ctrs;
if (unlikely(num_ctrs > NR_PHYS_CTRS)) {
@@ -589,14 +772,6 @@ static int cell_reg_setup(struct op_counter_config *ctr,
__func__);
return -EIO;
}
- pm_regs.group_control = 0;
- pm_regs.debug_bus_control = 0;
-
- /* setup the pm_control register */
- memset(&pm_regs.pm_cntrl, 0, sizeof(struct pm_cntrl));
- pm_regs.pm_cntrl.stop_at_max = 1;
- pm_regs.pm_cntrl.trace_mode = 0;
- pm_regs.pm_cntrl.freeze = 1;
set_count_mode(sys->enable_kernel, sys->enable_user);
@@ -665,6 +840,63 @@ static int cell_reg_setup(struct op_counter_config *ctr,
}
+/* This function is called once for all cpus combined */
+static int cell_reg_setup(struct op_counter_config *ctr,
+ struct op_system_config *sys, int num_ctrs)
+{
+ int ret=0;
+ spu_cycle_reset = 0;
+
+ /* initialize the spu_arr_trace value, will be reset if
+ * doing spu event profiling.
+ */
+ pm_regs.group_control = 0;
+ pm_regs.debug_bus_control = 0;
+ pm_regs.pm_cntrl.stop_at_max = 1;
+ pm_regs.pm_cntrl.trace_mode = 0;
+ pm_regs.pm_cntrl.freeze = 1;
+ pm_regs.pm_cntrl.trace_buf_ovflw = 0;
+ pm_regs.pm_cntrl.spu_addr_trace = 0;
+
+ /*
+ * For all events except PPU CYCLEs, each node will need to make
+ * the rtas cbe-perftools call to setup and reset the debug bus.
+ * Make the token lookup call once and store it in the global
+ * variable pm_rtas_token.
+ */
+ pm_rtas_token = rtas_token("ibm,cbe-perftools");
+
+ if (unlikely(pm_rtas_token == RTAS_UNKNOWN_SERVICE)) {
+ printk(KERN_ERR
+ "%s: rtas token ibm,cbe-perftools unknown\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (ctr[0].event == SPU_CYCLES_EVENT_NUM) {
+ profiling_mode = SPU_PROFILING_CYCLES;
+ ret = cell_reg_setup_spu_cycles(ctr, sys, num_ctrs);
+ } else if ((ctr[0].event >= SPU_EVENT_NUM_START) &&
+ (ctr[0].event <= SPU_EVENT_NUM_STOP)) {
+ profiling_mode = SPU_PROFILING_EVENTS;
+ spu_cycle_reset = ctr[0].count;
+
+ /* for SPU event profiling, need to setup the
+ * pm_signal array with the events to route the
+ * SPU PC before making the FW call. Note, only
+ * one SPU event for profiling can be specified
+ * at a time.
+ */
+ cell_reg_setup_spu_events(ctr, sys, num_ctrs);
+ } else {
+ profiling_mode = PPU_PROFILING;
+ ret = cell_reg_setup_ppu(ctr, sys, num_ctrs);
+ }
+
+ return ret;
+}
+
+
/* This function is called once for each cpu */
static int cell_cpu_setup(struct op_counter_config *cntr)
@@ -672,8 +904,13 @@ static int cell_cpu_setup(struct op_counter_config *cntr)
u32 cpu = smp_processor_id();
u32 num_enabled = 0;
int i;
+ int ret;
- if (spu_cycle_reset)
+ /* Cycle based SPU profiling does not use the performance
+ * counters. The trace array is configured to collect
+ * the data.
+ */
+ if (profiling_mode == SPU_PROFILING_CYCLES)
return 0;
/* There is one performance monitor per processor chip (i.e. node),
@@ -686,7 +923,6 @@ static int cell_cpu_setup(struct op_counter_config *cntr)
cbe_disable_pm(cpu);
cbe_disable_pm_interrupts(cpu);
- cbe_write_pm(cpu, pm_interval, 0);
cbe_write_pm(cpu, pm_start_stop, 0);
cbe_write_pm(cpu, group_control, pm_regs.group_control);
cbe_write_pm(cpu, debug_bus_control, pm_regs.debug_bus_control);
@@ -703,7 +939,20 @@ static int cell_cpu_setup(struct op_counter_config *cntr)
* The pm_rtas_activate_signals will return -EIO if the FW
* call failed.
*/
- return pm_rtas_activate_signals(cbe_cpu_to_node(cpu), num_enabled);
+ if (profiling_mode == SPU_PROFILING_EVENTS) {
+ /* For SPU event profiling also need to setup the
+ * pm interval timer
+ */
+ ret = pm_rtas_activate_signals(cbe_cpu_to_node(cpu),
+ num_enabled+2);
+ /* store PC from debug bus to Trace buffer as often
+ * as possible (every 10 cycles)
+ */
+ cbe_write_pm(cpu, pm_interval, NUM_INTERVAL_CYC);
+ return ret;
+ } else
+ return pm_rtas_activate_signals(cbe_cpu_to_node(cpu),
+ num_enabled);
}
#define ENTRIES 303
@@ -885,7 +1134,122 @@ static struct notifier_block cpu_freq_notifier_block = {
};
#endif
-static int cell_global_start_spu(struct op_counter_config *ctr)
+/*
+ * Note the generic OProfile stop calls do not support returning
+ * an error on stop. Hence, will not return an error if the FW
+ * calls fail on stop. Failure to reset the debug bus is not an issue.
+ * Failure to disable the SPU profiling is not an issue. The FW calls
+ * to enable the performance counters and debug bus will work even if
+ * the hardware was not cleanly reset.
+ */
+static void cell_global_stop_spu_cycles(void)
+{
+ int subfunc, rtn_value;
+ unsigned int lfsr_value;
+ int cpu;
+
+ oprofile_running = 0;
+ smp_wmb();
+
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_unregister_notifier(&cpu_freq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
+ for_each_online_cpu(cpu) {
+ if (cbe_get_hw_thread_id(cpu))
+ continue;
+
+ subfunc = 3; /*
+ * 2 - activate SPU tracing,
+ * 3 - deactivate
+ */
+ lfsr_value = 0x8f100000;
+
+ rtn_value = rtas_call(spu_rtas_token, 3, 1, NULL,
+ subfunc, cbe_cpu_to_node(cpu),
+ lfsr_value);
+
+ if (unlikely(rtn_value != 0)) {
+ printk(KERN_ERR
+ "%s: rtas call ibm,cbe-spu-perftools " \
+ "failed, return = %d\n",
+ __func__, rtn_value);
+ }
+
+ /* Deactivate the signals */
+ pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
+ }
+
+ stop_spu_profiling_cycles();
+}
+
+static void cell_global_stop_spu_events(void)
+{
+ int cpu;
+ oprofile_running = 0;
+
+ stop_spu_profiling_events();
+ smp_wmb();
+
+ for_each_online_cpu(cpu) {
+ if (cbe_get_hw_thread_id(cpu))
+ continue;
+
+ cbe_sync_irq(cbe_cpu_to_node(cpu));
+ /* Stop the counters */
+ cbe_disable_pm(cpu);
+ cbe_write_pm07_control(cpu, 0, 0);
+
+ /* Deactivate the signals */
+ pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
+
+ /* Deactivate interrupts */
+ cbe_disable_pm_interrupts(cpu);
+ }
+ del_timer_sync(&timer_spu_event_swap);
+}
+
+static void cell_global_stop_ppu(void)
+{
+ int cpu;
+
+ /*
+ * This routine will be called once for the system.
+ * There is one performance monitor per node, so we
+ * only need to perform this function once per node.
+ */
+ del_timer_sync(&timer_virt_cntr);
+ oprofile_running = 0;
+ smp_wmb();
+
+ for_each_online_cpu(cpu) {
+ if (cbe_get_hw_thread_id(cpu))
+ continue;
+
+ cbe_sync_irq(cbe_cpu_to_node(cpu));
+ /* Stop the counters */
+ cbe_disable_pm(cpu);
+
+ /* Deactivate the signals */
+ pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
+
+ /* Deactivate interrupts */
+ cbe_disable_pm_interrupts(cpu);
+ }
+}
+
+static void cell_global_stop(void)
+{
+ if (profiling_mode == PPU_PROFILING)
+ cell_global_stop_ppu();
+ else if (profiling_mode == SPU_PROFILING_EVENTS)
+ cell_global_stop_spu_events();
+ else
+ cell_global_stop_spu_cycles();
+}
+
+static int cell_global_start_spu_cycles(struct op_counter_config *ctr)
{
int subfunc;
unsigned int lfsr_value;
@@ -951,18 +1315,18 @@ static int cell_global_start_spu(struct op_counter_config *ctr)
/* start profiling */
ret = rtas_call(spu_rtas_token, 3, 1, NULL, subfunc,
- cbe_cpu_to_node(cpu), lfsr_value);
+ cbe_cpu_to_node(cpu), lfsr_value);
if (unlikely(ret != 0)) {
printk(KERN_ERR
- "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n",
- __func__, ret);
+ "%s: rtas call ibm,cbe-spu-perftools failed, " \
+ "return = %d\n", __func__, ret);
rtas_error = -EIO;
goto out;
}
}
- rtas_error = start_spu_profiling(spu_cycle_reset);
+ rtas_error = start_spu_profiling_cycles(spu_cycle_reset);
if (rtas_error)
goto out_stop;
@@ -970,11 +1334,74 @@ static int cell_global_start_spu(struct op_counter_config *ctr)
return 0;
out_stop:
- cell_global_stop_spu(); /* clean up the PMU/debug bus */
+ cell_global_stop_spu_cycles(); /* clean up the PMU/debug bus */
out:
return rtas_error;
}
+static int cell_global_start_spu_events(struct op_counter_config *ctr)
+{
+ int cpu;
+ u32 interrupt_mask = 0;
+ int rtn = 0;
+
+ hdw_thread = 0;
+
+ /* spu event profiling, uses the performance counters to generate
+ * an interrupt. The hardware is setup to store the SPU program
+ * counter into the trace array. The occurrence mode is used to
+ * enable storing data to the trace buffer. The bits are set
+ * to send/store the SPU address in the trace buffer. The debug
+ * bus must be setup to route the SPU program counter onto the
+ * debug bus. The occurrence data in the trace buffer is not used.
+ */
+
+ /* This routine gets called once for the system.
+ * There is one performance monitor per node, so we
+ * only need to perform this function once per node.
+ */
+
+ for_each_online_cpu(cpu) {
+ if (cbe_get_hw_thread_id(cpu))
+ continue;
+
+ /*
+ * Setup SPU event-based profiling.
+ * Set perf_mon_control bit 0 to a zero before
+ * enabling spu collection hardware.
+ *
+ * Only support one SPU event on one SPU per node.
+ */
+ if (ctr_enabled & 1) {
+ cbe_write_ctr(cpu, 0, reset_value[0]);
+ enable_ctr(cpu, 0, pm_regs.pm07_cntrl);
+ interrupt_mask |=
+ CBE_PM_CTR_OVERFLOW_INTR(0);
+ } else {
+ /* Disable counter */
+ cbe_write_pm07_control(cpu, 0, 0);
+ }
+
+ cbe_get_and_clear_pm_interrupts(cpu);
+ cbe_enable_pm_interrupts(cpu, hdw_thread, interrupt_mask);
+ cbe_enable_pm(cpu);
+
+ /* clear the trace buffer */
+ cbe_write_pm(cpu, trace_address, 0);
+ }
+
+ /* Start the timer to time slice collecting the event profile
+ * on each of the SPUs. Note, can collect profile on one SPU
+ * per node at a time.
+ */
+ start_spu_event_swap();
+ start_spu_profiling_events();
+ oprofile_running = 1;
+ smp_wmb();
+
+ return rtn;
+}
+
static int cell_global_start_ppu(struct op_counter_config *ctr)
{
u32 cpu, i;
@@ -994,8 +1421,7 @@ static int cell_global_start_ppu(struct op_counter_config *ctr)
if (ctr_enabled & (1 << i)) {
cbe_write_ctr(cpu, i, reset_value[i]);
enable_ctr(cpu, i, pm_regs.pm07_cntrl);
- interrupt_mask |=
- CBE_PM_CTR_OVERFLOW_INTR(i);
+ interrupt_mask |= CBE_PM_CTR_OVERFLOW_INTR(i);
} else {
/* Disable counter */
cbe_write_pm07_control(cpu, i, 0);
@@ -1024,99 +1450,162 @@ static int cell_global_start_ppu(struct op_counter_config *ctr)
static int cell_global_start(struct op_counter_config *ctr)
{
- if (spu_cycle_reset)
- return cell_global_start_spu(ctr);
+ if (profiling_mode == SPU_PROFILING_CYCLES)
+ return cell_global_start_spu_cycles(ctr);
+ else if (profiling_mode == SPU_PROFILING_EVENTS)
+ return cell_global_start_spu_events(ctr);
else
return cell_global_start_ppu(ctr);
}
-/*
- * Note the generic OProfile stop calls do not support returning
- * an error on stop. Hence, will not return an error if the FW
- * calls fail on stop. Failure to reset the debug bus is not an issue.
- * Failure to disable the SPU profiling is not an issue. The FW calls
- * to enable the performance counters and debug bus will work even if
- * the hardware was not cleanly reset.
+
+/* The SPU interrupt handler
+ *
+ * SPU event profiling works as follows:
+ * The pm_signal[0] holds the one SPU event to be measured. It is routed on
+ * the debug bus using word 0 or 1. The value of pm_signal[1] and
+ * pm_signal[2] contain the necessary events to route the SPU program
+ * counter for the selected SPU onto the debug bus using words 2 and 3.
+ * The pm_interval register is setup to write the SPU PC value into the
+ * trace buffer at the maximum rate possible. The trace buffer is configured
+ * to store the PCs, wrapping when it is full. The performance counter is
+ * intialized to the max hardware count minus the number of events, N, between
+ * samples. Once the N events have occured, a HW counter overflow occurs
+ * causing the generation of a HW counter interrupt which also stops the
+ * writing of the SPU PC values to the trace buffer. Hence the last PC
+ * written to the trace buffer is the SPU PC that we want. Unfortunately,
+ * we have to read from the beginning of the trace buffer to get to the
+ * last value written. We just hope the PPU has nothing better to do then
+ * service this interrupt. The PC for the specific SPU being profiled is
+ * extracted from the trace buffer processed and stored. The trace buffer
+ * is cleared, interrupts are cleared, the counter is reset to max - N.
+ * A kernel timer is used to periodically call the routine spu_evnt_swap()
+ * to switch to the next physical SPU in the node to profile in round robbin
+ * order. This way data is collected for all SPUs on the node. It does mean
+ * that we need to use a relatively small value of N to ensure enough samples
+ * on each SPU are collected each SPU is being profiled 1/8 of the time.
+ * It may also be necessary to use a longer sample collection period.
*/
-static void cell_global_stop_spu(void)
+static void cell_handle_interrupt_spu(struct pt_regs *regs,
+ struct op_counter_config *ctr)
{
- int subfunc, rtn_value;
- unsigned int lfsr_value;
- int cpu;
+ u32 cpu, cpu_tmp;
+ u64 trace_entry;
+ u32 interrupt_mask;
+ u64 trace_buffer[2];
+ u64 last_trace_buffer;
+ u32 sample;
+ u32 trace_addr;
+ unsigned long sample_array_lock_flags;
+ int spu_num;
+ unsigned long flags;
- oprofile_running = 0;
+ /* Make sure spu event interrupt handler and spu event swap
+ * don't access the counters simultaneously.
+ */
+ cpu = smp_processor_id();
+ spin_lock_irqsave(&cntr_lock, flags);
-#ifdef CONFIG_CPU_FREQ
- cpufreq_unregister_notifier(&cpu_freq_notifier_block,
- CPUFREQ_TRANSITION_NOTIFIER);
-#endif
+ cpu_tmp = cpu;
+ cbe_disable_pm(cpu);
- for_each_online_cpu(cpu) {
- if (cbe_get_hw_thread_id(cpu))
- continue;
+ interrupt_mask = cbe_get_and_clear_pm_interrupts(cpu);
- subfunc = 3; /*
- * 2 - activate SPU tracing,
- * 3 - deactivate
- */
- lfsr_value = 0x8f100000;
+ sample = 0xABCDEF;
+ trace_entry = 0xfedcba;
+ last_trace_buffer = 0xdeadbeaf;
- rtn_value = rtas_call(spu_rtas_token, 3, 1, NULL,
- subfunc, cbe_cpu_to_node(cpu),
- lfsr_value);
+ if ((oprofile_running == 1) && (interrupt_mask != 0)) {
+ /* disable writes to trace buff */
+ cbe_write_pm(cpu, pm_interval, 0);
- if (unlikely(rtn_value != 0)) {
- printk(KERN_ERR
- "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n",
- __func__, rtn_value);
+ /* only have one perf cntr being used, cntr 0 */
+ if ((interrupt_mask & CBE_PM_CTR_OVERFLOW_INTR(0))
+ && ctr[0].enabled)
+ /* The SPU PC values will be read
+ * from the trace buffer, reset counter
+ */
+
+ cbe_write_ctr(cpu, 0, reset_value[0]);
+
+ trace_addr = cbe_read_pm(cpu, trace_address);
+
+ while (!(trace_addr & CBE_PM_TRACE_BUF_EMPTY)) {
+ /* There is data in the trace buffer to process
+ * Read the buffer until you get to the last
+ * entry. This is the value we want.
+ */
+
+ cbe_read_trace_buffer(cpu, trace_buffer);
+ trace_addr = cbe_read_pm(cpu, trace_address);
}
- /* Deactivate the signals */
- pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
- }
+ /* SPU Address 16 bit count format for 128 bit
+ * HW trace buffer is used for the SPU PC storage
+ * HDR bits 0:15
+ * SPU Addr 0 bits 16:31
+ * SPU Addr 1 bits 32:47
+ * unused bits 48:127
+ *
+ * HDR: bit4 = 1 SPU Address 0 valid
+ * HDR: bit5 = 1 SPU Address 1 valid
+ * - unfortunately, the valid bits don't seem to work
+ *
+ * Note trace_buffer[0] holds bits 0:63 of the HW
+ * trace buffer, trace_buffer[1] holds bits 64:127
+ */
- stop_spu_profiling();
-}
+ trace_entry = trace_buffer[0]
+ & 0x00000000FFFF0000;
-static void cell_global_stop_ppu(void)
-{
- int cpu;
+ /* only top 16 of the 18 bit SPU PC address
+ * is stored in trace buffer, hence shift right
+ * by 16 -2 bits */
+ sample = trace_entry >> 14;
+ last_trace_buffer = trace_buffer[0];
- /*
- * This routine will be called once for the system.
- * There is one performance monitor per node, so we
- * only need to perform this function once per node.
- */
- del_timer_sync(&timer_virt_cntr);
- oprofile_running = 0;
- smp_wmb();
+ spu_num = spu_evnt_phys_spu_indx
+ + (cbe_cpu_to_node(cpu) * NUM_SPUS_PER_NODE);
- for_each_online_cpu(cpu) {
- if (cbe_get_hw_thread_id(cpu))
- continue;
+ /* make sure only one process at a time is calling
+ * spu_sync_buffer()
+ */
+ spin_lock_irqsave(&oprof_spu_smpl_arry_lck,
+ sample_array_lock_flags);
+ spu_sync_buffer(spu_num, &sample, 1);
+ spin_unlock_irqrestore(&oprof_spu_smpl_arry_lck,
+ sample_array_lock_flags);
- cbe_sync_irq(cbe_cpu_to_node(cpu));
- /* Stop the counters */
- cbe_disable_pm(cpu);
+ smp_wmb(); /* insure spu event buffer updates are written
+ * don't want events intermingled... */
- /* Deactivate the signals */
- pm_rtas_reset_signals(cbe_cpu_to_node(cpu));
+ /* The counters were frozen by the interrupt.
+ * Reenable the interrupt and restart the counters.
+ */
+ cbe_write_pm(cpu, pm_interval, NUM_INTERVAL_CYC);
+ cbe_enable_pm_interrupts(cpu, hdw_thread,
+ virt_cntr_inter_mask);
- /* Deactivate interrupts */
- cbe_disable_pm_interrupts(cpu);
- }
-}
+ /* clear the trace buffer, re-enable writes to trace buff */
+ cbe_write_pm(cpu, trace_address, 0);
+ cbe_write_pm(cpu, pm_interval, NUM_INTERVAL_CYC);
-static void cell_global_stop(void)
-{
- if (spu_cycle_reset)
- cell_global_stop_spu();
- else
- cell_global_stop_ppu();
+ /* The writes to the various performance counters only writes
+ * to a latch. The new values (interrupt setting bits, reset
+ * counter value etc.) are not copied to the actual registers
+ * until the performance monitor is enabled. In order to get
+ * this to work as desired, the permormance monitor needs to
+ * be disabled while writing to the latches. This is a
+ * HW design issue.
+ */
+ write_pm_cntrl(cpu);
+ cbe_enable_pm(cpu);
+ }
+ spin_unlock_irqrestore(&cntr_lock, flags);
}
-static void cell_handle_interrupt(struct pt_regs *regs,
- struct op_counter_config *ctr)
+static void cell_handle_interrupt_ppu(struct pt_regs *regs,
+ struct op_counter_config *ctr)
{
u32 cpu;
u64 pc;
@@ -1132,7 +1621,7 @@ static void cell_handle_interrupt(struct pt_regs *regs,
* routine are not running at the same time. See the
* cell_virtual_cntr() routine for additional comments.
*/
- spin_lock_irqsave(&virt_cntr_lock, flags);
+ spin_lock_irqsave(&cntr_lock, flags);
/*
* Need to disable and reenable the performance counters
@@ -1185,7 +1674,16 @@ static void cell_handle_interrupt(struct pt_regs *regs,
*/
cbe_enable_pm(cpu);
}
- spin_unlock_irqrestore(&virt_cntr_lock, flags);
+ spin_unlock_irqrestore(&cntr_lock, flags);
+}
+
+static void cell_handle_interrupt(struct pt_regs *regs,
+ struct op_counter_config *ctr)
+{
+ if (profiling_mode == PPU_PROFILING)
+ cell_handle_interrupt_ppu(regs, ctr);
+ else
+ cell_handle_interrupt_spu(regs, ctr);
}
/*
@@ -1195,7 +1693,8 @@ static void cell_handle_interrupt(struct pt_regs *regs,
*/
static int cell_sync_start(void)
{
- if (spu_cycle_reset)
+ if ((profiling_mode == SPU_PROFILING_CYCLES) ||
+ (profiling_mode == SPU_PROFILING_EVENTS))
return spu_sync_start();
else
return DO_GENERIC_SYNC;
@@ -1203,7 +1702,8 @@ static int cell_sync_start(void)
static int cell_sync_stop(void)
{
- if (spu_cycle_reset)
+ if ((profiling_mode == SPU_PROFILING_CYCLES) ||
+ (profiling_mode == SPU_PROFILING_EVENTS))
return spu_sync_stop();
else
return 1;
diff --git a/arch/powerpc/oprofile/op_model_pa6t.c b/arch/powerpc/oprofile/op_model_pa6t.c
index c40de461fd4e..42f778dff919 100644
--- a/arch/powerpc/oprofile/op_model_pa6t.c
+++ b/arch/powerpc/oprofile/op_model_pa6t.c
@@ -132,7 +132,7 @@ static int pa6t_reg_setup(struct op_counter_config *ctr,
for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) {
/* counters are 40 bit. Move to cputable at some point? */
reset_value[pmc] = (0x1UL << 39) - ctr[pmc].count;
- pr_debug("reset_value for pmc%u inited to 0x%lx\n",
+ pr_debug("reset_value for pmc%u inited to 0x%llx\n",
pmc, reset_value[pmc]);
}
@@ -177,7 +177,7 @@ static int pa6t_start(struct op_counter_config *ctr)
oprofile_running = 1;
- pr_debug("start on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0);
+ pr_debug("start on cpu %d, mmcr0 %llx\n", smp_processor_id(), mmcr0);
return 0;
}
@@ -193,7 +193,7 @@ static void pa6t_stop(void)
oprofile_running = 0;
- pr_debug("stop on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0);
+ pr_debug("stop on cpu %d, mmcr0 %llx\n", smp_processor_id(), mmcr0);
}
/* handle the perfmon overflow vector */
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index 698133180aee..01f51daace13 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -3,5 +3,4 @@ obj-$(CONFIG_PPC44x_SIMPLE) += ppc44x_simple.o
obj-$(CONFIG_EBONY) += ebony.o
obj-$(CONFIG_SAM440EP) += sam440ep.o
obj-$(CONFIG_WARP) += warp.o
-obj-$(CONFIG_WARP) += warp-nand.o
obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
deleted file mode 100644
index 89ecd76127d8..000000000000
--- a/arch/powerpc/platforms/44x/warp-nand.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * PIKA Warp(tm) NAND flash specific routines
- *
- * Copyright (c) 2008 PIKA Technologies
- * Sean MacLennan <smaclennan@pikatech.com>
- */
-
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/ndfc.h>
-#include <linux/of.h>
-#include <asm/machdep.h>
-
-
-#ifdef CONFIG_MTD_NAND_NDFC
-
-#define CS_NAND_0 1 /* use chip select 1 for NAND device 0 */
-
-#define WARP_NAND_FLASH_REG_ADDR 0xD0000000UL
-#define WARP_NAND_FLASH_REG_SIZE 0x2000
-
-static struct resource warp_ndfc = {
- .start = WARP_NAND_FLASH_REG_ADDR,
- .end = WARP_NAND_FLASH_REG_ADDR + WARP_NAND_FLASH_REG_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct mtd_partition nand_parts[] = {
- {
- .name = "kernel",
- .offset = 0,
- .size = 0x0200000
- },
- {
- .name = "root",
- .offset = 0x0200000,
- .size = 0x3E00000
- },
- {
- .name = "persistent",
- .offset = 0x4000000,
- .size = 0x4000000
- },
- {
- .name = "persistent1",
- .offset = 0x8000000,
- .size = 0x4000000
- },
- {
- .name = "persistent2",
- .offset = 0xC000000,
- .size = 0x4000000
- }
-};
-
-struct ndfc_controller_settings warp_ndfc_settings = {
- .ccr_settings = (NDFC_CCR_BS(CS_NAND_0) | NDFC_CCR_ARAC1),
- .ndfc_erpn = 0,
-};
-
-static struct ndfc_chip_settings warp_chip0_settings = {
- .bank_settings = 0x80002222,
-};
-
-struct platform_nand_ctrl warp_nand_ctrl = {
- .priv = &warp_ndfc_settings,
-};
-
-static struct platform_device warp_ndfc_device = {
- .name = "ndfc-nand",
- .id = 0,
- .dev = {
- .platform_data = &warp_nand_ctrl,
- },
- .num_resources = 1,
- .resource = &warp_ndfc,
-};
-
-/* Do NOT set the ecclayout: let it default so it is correct for both
- * 64M and 256M flash chips.
- */
-static struct platform_nand_chip warp_nand_chip0 = {
- .nr_chips = 1,
- .chip_offset = CS_NAND_0,
- .nr_partitions = ARRAY_SIZE(nand_parts),
- .partitions = nand_parts,
- .chip_delay = 20,
- .priv = &warp_chip0_settings,
-};
-
-static struct platform_device warp_nand_device = {
- .name = "ndfc-chip",
- .id = 0,
- .num_resources = 0,
- .dev = {
- .platform_data = &warp_nand_chip0,
- .parent = &warp_ndfc_device.dev,
- }
-};
-
-static int warp_setup_nand_flash(void)
-{
- struct device_node *np;
-
- /* Try to detect a rev A based on NOR size. */
- np = of_find_compatible_node(NULL, NULL, "cfi-flash");
- if (np) {
- struct property *pp;
-
- pp = of_find_property(np, "reg", NULL);
- if (pp && (pp->length == 12)) {
- u32 *v = pp->value;
- if (v[2] == 0x4000000) {
- /* Rev A = 64M NAND */
- warp_nand_chip0.nr_partitions = 3;
-
- nand_parts[1].size = 0x3000000;
- nand_parts[2].offset = 0x3200000;
- nand_parts[2].size = 0x0e00000;
- }
- }
- of_node_put(np);
- }
-
- platform_device_register(&warp_ndfc_device);
- platform_device_register(&warp_nand_device);
-
- return 0;
-}
-machine_device_initcall(warp, warp_setup_nand_flash);
-
-#endif
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
index f416014ee727..1bcff94eb924 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -56,12 +56,12 @@ static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
int dev_match = 0;
int id_match = 0;
- if (dev == NULL && id == NULL)
+ if (dev == NULL || id == NULL)
return NULL;
mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
- if (dev && dev == p->dev)
+ if (dev == p->dev)
dev_match++;
if (strcmp(id, p->name) == 0)
id_match++;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index ae7c34f37e1c..98367a0255f3 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -42,7 +42,7 @@ static struct of_device_id mpc52xx_bus_ids[] __initdata = {
* from interrupt context while node mapping (which calls ioremap())
* cannot be used at such point.
*/
-static spinlock_t mpc52xx_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mpc52xx_lock);
static struct mpc52xx_gpt __iomem *mpc52xx_wdt;
static struct mpc52xx_cdm __iomem *mpc52xx_cdm;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
index 8a455ebce98d..07f89ae46d04 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
@@ -363,11 +363,8 @@ static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
struct mpc52xx_gpt __iomem *regs = mm_gc->regs;
- unsigned int ret;
return (in_be32(&regs->status) & (1 << (31 - 23))) ? 1 : 0;
-
- return ret;
}
static void
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index c3f2c21024e3..87ff522f28b5 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -20,14 +20,6 @@
/* ======================================================================== */
-/* PCI windows config */
-/* ======================================================================== */
-
-#define MPC52xx_PCI_TARGET_IO 0xf0000000
-#define MPC52xx_PCI_TARGET_MEM 0x00000000
-
-
-/* ======================================================================== */
/* Structures mapping & Defines for PCI Unit */
/* ======================================================================== */
@@ -244,7 +236,7 @@ static struct pci_ops mpc52xx_pci_ops = {
static void __init
mpc52xx_pci_setup(struct pci_controller *hose,
- struct mpc52xx_pci __iomem *pci_regs)
+ struct mpc52xx_pci __iomem *pci_regs, phys_addr_t pci_phys)
{
struct resource *res;
u32 tmp;
@@ -314,10 +306,14 @@ mpc52xx_pci_setup(struct pci_controller *hose,
/* Set all the IWCR fields at once; they're in the same reg */
out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
- out_be32(&pci_regs->tbatr0,
- MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
- out_be32(&pci_regs->tbatr1,
- MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+ /* Map IMMR onto PCI bus */
+ pci_phys &= 0xfffc0000; /* bar0 has only 14 significant bits */
+ out_be32(&pci_regs->tbatr0, MPC52xx_PCI_TBATR_ENABLE | pci_phys);
+ out_be32(&pci_regs->bar0, PCI_BASE_ADDRESS_MEM_PREFETCH | pci_phys);
+
+ /* Map memory onto PCI bus */
+ out_be32(&pci_regs->tbatr1, MPC52xx_PCI_TBATR_ENABLE);
+ out_be32(&pci_regs->bar1, PCI_BASE_ADDRESS_MEM_PREFETCH);
out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD | MPC52xx_PCI_TCR_WCT8);
@@ -414,7 +410,7 @@ mpc52xx_add_bridge(struct device_node *node)
/* Finish setting up PCI using values obtained by
* pci_proces_bridge_OF_ranges */
- mpc52xx_pci_setup(hose, pci_regs);
+ mpc52xx_pci_setup(hose, pci_regs, rsrc.start);
return 0;
}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 72865e8e4b51..0a093f03c758 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -196,6 +196,7 @@ static void mpc52xx_extirq_ack(unsigned int virq)
static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
{
+ struct irq_desc *desc = get_irq_desc(virq);
u32 ctrl_reg, type;
int irq;
int l2irq;
@@ -222,6 +223,11 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
type = 0;
}
+ desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+ desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+ if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+ desc->status |= IRQ_LEVEL;
+
ctrl_reg = in_be32(&intr->ctrl);
ctrl_reg &= ~(0x3 << (22 - (l2irq * 2)));
ctrl_reg |= (type << (22 - (l2irq * 2)));
@@ -231,7 +237,7 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
}
static struct irq_chip mpc52xx_extirq_irqchip = {
- .typename = " MPC52xx IRQ[0-3] ",
+ .typename = "MPC52xx External",
.mask = mpc52xx_extirq_mask,
.unmask = mpc52xx_extirq_unmask,
.ack = mpc52xx_extirq_ack,
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index ba5028e29890..051777c542c7 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -3,6 +3,7 @@
#
obj-y := misc.o usb.o
obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
+obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
index 82a9bcb858b6..82a9bcb858b6 100644
--- a/drivers/i2c/chips/mcu_mpc8349emitx.c
+++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
diff --git a/arch/powerpc/platforms/83xx/mpc831x_rdb.c b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
index a428f8d1ac80..91a2c80b9d72 100644
--- a/arch/powerpc/platforms/83xx/mpc831x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc831x_rdb.c
@@ -42,7 +42,7 @@ static void __init mpc831x_rdb_setup_arch(void)
mpc831x_usb_cfg();
}
-void __init mpc831x_rdb_init_IRQ(void)
+static void __init mpc831x_rdb_init_IRQ(void)
{
struct device_node *np;
@@ -71,6 +71,7 @@ static int __init mpc831x_rdb_probe(void)
static struct of_device_id __initdata of_bus_ids[] = {
{ .compatible = "simple-bus" },
+ { .compatible = "gianfar" },
{},
};
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c
index ec43477caa63..ec0b401bc9cf 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c
@@ -49,8 +49,6 @@
#define DBG(fmt...)
#endif
-static u8 *bcsr_regs = NULL;
-
/* ************************************************************************
*
* Setup the architecture
@@ -59,13 +57,14 @@ static u8 *bcsr_regs = NULL;
static void __init mpc832x_sys_setup_arch(void)
{
struct device_node *np;
+ u8 __iomem *bcsr_regs = NULL;
if (ppc_md.progress)
ppc_md.progress("mpc832x_sys_setup_arch()", 0);
/* Map BCSR area */
np = of_find_node_by_name(NULL, "bcsr");
- if (np != 0) {
+ if (np) {
struct resource res;
of_address_to_resource(np, 0, &res);
@@ -93,9 +92,9 @@ static void __init mpc832x_sys_setup_arch(void)
!= NULL){
/* Reset the Ethernet PHYs */
#define BCSR8_FETH_RST 0x50
- bcsr_regs[8] &= ~BCSR8_FETH_RST;
+ clrbits8(&bcsr_regs[8], BCSR8_FETH_RST);
udelay(1000);
- bcsr_regs[8] |= BCSR8_FETH_RST;
+ setbits8(&bcsr_regs[8], BCSR8_FETH_RST);
iounmap(bcsr_regs);
of_node_put(np);
}
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index 0300268ce5b8..2a1295f19832 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -38,6 +38,7 @@
#define DBG(fmt...)
#endif
+#ifdef CONFIG_QUICC_ENGINE
static void mpc83xx_spi_activate_cs(u8 cs, u8 polarity)
{
pr_debug("%s %d %d\n", __func__, cs, polarity);
@@ -77,8 +78,8 @@ static int __init mpc832x_spi_init(void)
mpc83xx_spi_activate_cs,
mpc83xx_spi_deactivate_cs);
}
-
machine_device_initcall(mpc832x_rdb, mpc832x_spi_init);
+#endif /* CONFIG_QUICC_ENGINE */
/* ************************************************************************
*
@@ -130,7 +131,7 @@ static int __init mpc832x_declare_of_platform_devices(void)
}
machine_device_initcall(mpc832x_rdb, mpc832x_declare_of_platform_devices);
-void __init mpc832x_rdb_init_IRQ(void)
+static void __init mpc832x_rdb_init_IRQ(void)
{
struct device_node *np;
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c
index 9d46e5bdd101..09e9d6fb7411 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c
@@ -18,6 +18,7 @@
#include <linux/stddef.h>
#include <linux/kernel.h>
+#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/reboot.h>
@@ -43,6 +44,7 @@
#include <asm/udbg.h>
#include <sysdev/fsl_soc.h>
#include <sysdev/fsl_pci.h>
+#include <sysdev/simple_gpio.h>
#include <asm/qe.h>
#include <asm/qe_ic.h>
@@ -55,8 +57,6 @@
#define DBG(fmt...)
#endif
-static u8 *bcsr_regs = NULL;
-
/* ************************************************************************
*
* Setup the architecture
@@ -65,13 +65,14 @@ static u8 *bcsr_regs = NULL;
static void __init mpc836x_mds_setup_arch(void)
{
struct device_node *np;
+ u8 __iomem *bcsr_regs = NULL;
if (ppc_md.progress)
ppc_md.progress("mpc836x_mds_setup_arch()", 0);
/* Map BCSR area */
np = of_find_node_by_name(NULL, "bcsr");
- if (np != 0) {
+ if (np) {
struct resource res;
of_address_to_resource(np, 0, &res);
@@ -93,6 +94,16 @@ static void __init mpc836x_mds_setup_arch(void)
for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
par_io_of_config(np);
+#ifdef CONFIG_QE_USB
+ /* Must fixup Par IO before QE GPIO chips are registered. */
+ par_io_config_pin(1, 2, 1, 0, 3, 0); /* USBOE */
+ par_io_config_pin(1, 3, 1, 0, 3, 0); /* USBTP */
+ par_io_config_pin(1, 8, 1, 0, 1, 0); /* USBTN */
+ par_io_config_pin(1, 10, 2, 0, 3, 0); /* USBRXD */
+ par_io_config_pin(1, 9, 2, 1, 3, 0); /* USBRP */
+ par_io_config_pin(1, 11, 2, 1, 3, 0); /* USBRN */
+ par_io_config_pin(2, 20, 2, 0, 1, 0); /* CLK21 */
+#endif /* CONFIG_QE_USB */
}
if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
@@ -151,6 +162,70 @@ static int __init mpc836x_declare_of_platform_devices(void)
}
machine_device_initcall(mpc836x_mds, mpc836x_declare_of_platform_devices);
+#ifdef CONFIG_QE_USB
+static int __init mpc836x_usb_cfg(void)
+{
+ u8 __iomem *bcsr;
+ struct device_node *np;
+ const char *mode;
+ int ret = 0;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mpc8360mds-bcsr");
+ if (!np)
+ return -ENODEV;
+
+ bcsr = of_iomap(np, 0);
+ of_node_put(np);
+ if (!bcsr)
+ return -ENOMEM;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mpc8323-qe-usb");
+ if (!np) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+#define BCSR8_TSEC1M_MASK (0x3 << 6)
+#define BCSR8_TSEC1M_RGMII (0x0 << 6)
+#define BCSR8_TSEC2M_MASK (0x3 << 4)
+#define BCSR8_TSEC2M_RGMII (0x0 << 4)
+ /*
+ * Default is GMII (2), but we should set it to RGMII (0) if we use
+ * USB (Eth PHY is in RGMII mode anyway).
+ */
+ clrsetbits_8(&bcsr[8], BCSR8_TSEC1M_MASK | BCSR8_TSEC2M_MASK,
+ BCSR8_TSEC1M_RGMII | BCSR8_TSEC2M_RGMII);
+
+#define BCSR13_USBMASK 0x0f
+#define BCSR13_nUSBEN 0x08 /* 1 - Disable, 0 - Enable */
+#define BCSR13_USBSPEED 0x04 /* 1 - Full, 0 - Low */
+#define BCSR13_USBMODE 0x02 /* 1 - Host, 0 - Function */
+#define BCSR13_nUSBVCC 0x01 /* 1 - gets VBUS, 0 - supplies VBUS */
+
+ clrsetbits_8(&bcsr[13], BCSR13_USBMASK, BCSR13_USBSPEED);
+
+ mode = of_get_property(np, "mode", NULL);
+ if (mode && !strcmp(mode, "peripheral")) {
+ setbits8(&bcsr[13], BCSR13_nUSBVCC);
+ qe_usb_clock_set(QE_CLK21, 48000000);
+ } else {
+ setbits8(&bcsr[13], BCSR13_USBMODE);
+ /*
+ * The BCSR GPIOs are used to control power and
+ * speed of the USB transceiver. This is needed for
+ * the USB Host only.
+ */
+ simple_gpiochip_init("fsl,mpc8360mds-bcsr-gpio");
+ }
+
+ of_node_put(np);
+err:
+ iounmap(bcsr);
+ return ret;
+}
+machine_arch_initcall(mpc836x_mds, mpc836x_usb_cfg);
+#endif /* CONFIG_QE_USB */
+
static void __init mpc836x_mds_init_IRQ(void)
{
struct device_node *np;
diff --git a/arch/powerpc/platforms/83xx/mpc836x_rdk.c b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
index a5273bb28e1b..b0090aac9642 100644
--- a/arch/powerpc/platforms/83xx/mpc836x_rdk.c
+++ b/arch/powerpc/platforms/83xx/mpc836x_rdk.c
@@ -51,8 +51,9 @@ static void __init mpc836x_rdk_setup_arch(void)
for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
mpc83xx_add_bridge(np);
#endif
-
+#ifdef CONFIG_QUICC_ENGINE
qe_reset();
+#endif
}
static void __init mpc836x_rdk_init_IRQ(void)
@@ -71,13 +72,14 @@ static void __init mpc836x_rdk_init_IRQ(void)
*/
ipic_set_default_priority();
of_node_put(np);
-
+#ifdef CONFIG_QUICC_ENGINE
np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
if (!np)
return;
qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
of_node_put(np);
+#endif
}
/*
diff --git a/arch/powerpc/platforms/83xx/mpc837x_mds.c b/arch/powerpc/platforms/83xx/mpc837x_mds.c
index 8bb13c807142..530ef990ca7c 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_mds.c
@@ -26,7 +26,6 @@
#define BCSR12_USB_SER_MASK 0x8a
#define BCSR12_USB_SER_PIN 0x80
#define BCSR12_USB_SER_DEVICE 0x02
-extern int mpc837x_usb_cfg(void);
static int mpc837xmds_usb_cfg(void)
{
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index da030afa2e2c..1d096545322b 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -21,8 +21,6 @@
#include "mpc83xx.h"
-extern int mpc837x_usb_cfg(void);
-
/* ************************************************************************
*
* Setup the architecture
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 2a7cbabb410a..83cfe51526ec 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -61,6 +61,7 @@
extern void mpc83xx_restart(char *cmd);
extern long mpc83xx_time_init(void);
+extern int mpc837x_usb_cfg(void);
extern int mpc834x_usb_cfg(void);
extern int mpc831x_usb_cfg(void);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index a8301c8ad537..7326d904202c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -148,6 +148,9 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
/*
* Setup the architecture
*/
+#ifdef CONFIG_SMP
+extern void __init mpc85xx_smp_init(void);
+#endif
static void __init mpc85xx_ds_setup_arch(void)
{
#ifdef CONFIG_PCI
@@ -173,6 +176,10 @@ static void __init mpc85xx_ds_setup_arch(void)
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
#endif
+#ifdef CONFIG_SMP
+ mpc85xx_smp_init();
+#endif
+
printk("MPC85xx DS board from Freescale Semiconductor\n");
}
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index d652c713f496..79a0df17078b 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -58,6 +58,7 @@ smp_85xx_kick_cpu(int nr)
if (cpu_rel_addr == NULL) {
printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr);
+ local_irq_restore(flags);
return;
}
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 47e956c871fe..200b9cb900ea 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -312,4 +312,26 @@ config MPC8xxx_GPIO
Say Y here if you're going to use hardware that connects to the
MPC831x/834x/837x/8572/8610 GPIOs.
+config SIMPLE_GPIO
+ bool "Support for simple, memory-mapped GPIO controllers"
+ depends on PPC
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Say Y here to support simple, memory-mapped GPIO controllers.
+ These are usually BCSRs used to control board's switches, LEDs,
+ chip-selects, Ethernet/USB PHY's power and various other small
+ on-board peripherals.
+
+config MCU_MPC8349EMITX
+ tristate "MPC8349E-mITX MCU driver"
+ depends on I2C && PPC_83xx
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Say Y here to enable soft power-off functionality on the Freescale
+ boards with the MPC8349E-mITX-compatible MCU chips. This driver will
+ also register MCU GPIOs with the generic GPIO API, so you'll able
+ to use MCU pins as GPIOs.
+
endmenu
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 3d0c776f888d..e868b5c50723 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -231,7 +231,7 @@ config VIRT_CPU_ACCOUNTING
If in doubt, say Y here.
config SMP
- depends on PPC_STD_MMU
+ depends on PPC_STD_MMU || FSL_BOOKE
bool "Symmetric multi-processing support"
---help---
This enables support for systems with more than one CPU. If you have
diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c
index 2e67bd840e01..35b1ec492715 100644
--- a/arch/powerpc/platforms/cell/beat_htab.c
+++ b/arch/powerpc/platforms/cell/beat_htab.c
@@ -44,8 +44,8 @@ static DEFINE_SPINLOCK(beat_htab_lock);
static inline unsigned int beat_read_mask(unsigned hpte_group)
{
- unsigned long hpte_v[5];
unsigned long rmask = 0;
+ u64 hpte_v[5];
beat_read_htab_entries(0, hpte_group + 0, hpte_v);
if (!(hpte_v[0] & HPTE_V_BOLTED))
@@ -93,8 +93,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
int psize, int ssize)
{
unsigned long lpar_rc;
- unsigned long slot;
- unsigned long hpte_v, hpte_r;
+ u64 hpte_v, hpte_r, slot;
/* same as iseries */
if (vflags & HPTE_V_SECONDARY)
@@ -153,8 +152,9 @@ static long beat_lpar_hpte_remove(unsigned long hpte_group)
static unsigned long beat_lpar_hpte_getword0(unsigned long slot)
{
- unsigned long dword0, dword[5];
+ unsigned long dword0;
unsigned long lpar_rc;
+ u64 dword[5];
lpar_rc = beat_read_htab_entries(0, slot & ~3UL, dword);
@@ -170,7 +170,7 @@ static void beat_lpar_hptab_clear(void)
unsigned long size_bytes = 1UL << ppc64_pft_size;
unsigned long hpte_count = size_bytes >> 4;
int i;
- unsigned long dummy0, dummy1;
+ u64 dummy0, dummy1;
/* TODO: Use bulk call */
for (i = 0; i < hpte_count; i++)
@@ -189,7 +189,8 @@ static long beat_lpar_hpte_updatepp(unsigned long slot,
int psize, int ssize, int local)
{
unsigned long lpar_rc;
- unsigned long dummy0, dummy1, want_v;
+ u64 dummy0, dummy1;
+ unsigned long want_v;
want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
@@ -255,7 +256,8 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
unsigned long ea,
int psize, int ssize)
{
- unsigned long lpar_rc, slot, vsid, va, dummy0, dummy1;
+ unsigned long lpar_rc, slot, vsid, va;
+ u64 dummy0, dummy1;
vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
va = (vsid << 28) | (ea & 0x0fffffff);
@@ -276,7 +278,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
{
unsigned long want_v;
unsigned long lpar_rc;
- unsigned long dummy1, dummy2;
+ u64 dummy1, dummy2;
unsigned long flags;
DBG_LOW(" inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
@@ -315,8 +317,7 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
int psize, int ssize)
{
unsigned long lpar_rc;
- unsigned long slot;
- unsigned long hpte_v, hpte_r;
+ u64 hpte_v, hpte_r, slot;
/* same as iseries */
if (vflags & HPTE_V_SECONDARY)
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
index 192a93509372..72254848a228 100644
--- a/arch/powerpc/platforms/cell/beat_interrupt.c
+++ b/arch/powerpc/platforms/cell/beat_interrupt.c
@@ -99,7 +99,7 @@ static void beatic_end_irq(unsigned int irq_plug)
err = beat_downcount_of_interrupt(irq_plug);
if (err != 0) {
if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
- panic("Failed to downcount IRQ! Error = %16lx", err);
+ panic("Failed to downcount IRQ! Error = %16llx", err);
printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
}
diff --git a/arch/powerpc/platforms/cell/beat_udbg.c b/arch/powerpc/platforms/cell/beat_udbg.c
index 6b418f6b6175..350735bc8888 100644
--- a/arch/powerpc/platforms/cell/beat_udbg.c
+++ b/arch/powerpc/platforms/cell/beat_udbg.c
@@ -40,8 +40,8 @@ static void udbg_putc_beat(char c)
}
/* Buffered chars getc */
-static long inbuflen;
-static long inbuf[2]; /* must be 2 longs */
+static u64 inbuflen;
+static u64 inbuf[2]; /* must be 2 u64s */
static int udbg_getc_poll_beat(void)
{
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index ec7c8f45a215..e6506cd0ff94 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -118,7 +118,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cur = cbe_freqs[cur_pmode].frequency;
#ifdef CONFIG_SMP
- policy->cpus = per_cpu(cpu_sibling_map, policy->cpu);
+ cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu));
#endif
cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
index 70fa7aef5edd..20472e487b6f 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
@@ -54,7 +54,7 @@ int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)
{
struct cbe_pmd_regs __iomem *pmd_regs;
struct cbe_mic_tm_regs __iomem *mic_tm_regs;
- u64 flags;
+ unsigned long flags;
u64 value;
#ifdef DEBUG
long time;
diff --git a/arch/powerpc/platforms/cell/celleb_scc_epci.c b/arch/powerpc/platforms/cell/celleb_scc_epci.c
index 08c285b10e30..48ec88a38a12 100644
--- a/arch/powerpc/platforms/cell/celleb_scc_epci.c
+++ b/arch/powerpc/platforms/cell/celleb_scc_epci.c
@@ -405,7 +405,7 @@ static int __init celleb_setup_epci(struct device_node *node,
hose->cfg_addr = ioremap(r.start, (r.end - r.start + 1));
if (!hose->cfg_addr)
goto error;
- pr_debug("EPCI: cfg_addr map 0x%016lx->0x%016lx + 0x%016lx\n",
+ pr_debug("EPCI: cfg_addr map 0x%016llx->0x%016lx + 0x%016llx\n",
r.start, (unsigned long)hose->cfg_addr, (r.end - r.start + 1));
if (of_address_to_resource(node, 2, &r))
@@ -413,7 +413,7 @@ static int __init celleb_setup_epci(struct device_node *node,
hose->cfg_data = ioremap(r.start, (r.end - r.start + 1));
if (!hose->cfg_data)
goto error;
- pr_debug("EPCI: cfg_data map 0x%016lx->0x%016lx + 0x%016lx\n",
+ pr_debug("EPCI: cfg_data map 0x%016llx->0x%016lx + 0x%016llx\n",
r.start, (unsigned long)hose->cfg_data, (r.end - r.start + 1));
hose->ops = &celleb_epci_ops;
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
index a3c6c01bd6db..968c1c0b4d5b 100644
--- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -110,7 +110,7 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
}
/* initialize spu_gov_info for all affected cpus */
- for_each_cpu_mask(i, policy->cpus) {
+ for_each_cpu(i, policy->cpus) {
affected_info = &per_cpu(spu_gov_info, i);
affected_info->policy = policy;
}
@@ -127,7 +127,7 @@ static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
spu_gov_cancel_work(info);
/* clean spu_gov_info for all affected cpus */
- for_each_cpu_mask (i, policy->cpus) {
+ for_each_cpu (i, policy->cpus) {
info = &per_cpu(spu_gov_info, i);
info->policy = NULL;
}
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 2d5bb22d6c09..28c04dab2633 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -148,7 +148,7 @@ static unsigned int iic_get_irq(void)
iic = &__get_cpu_var(iic);
*(unsigned long *) &pending =
- in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
+ in_be64((u64 __iomem *) &iic->regs->pending_destr);
if (!(pending.flags & CBE_IIC_IRQ_VALID))
return NO_IRQ;
virq = irq_linear_revmap(iic_host, iic_pending_to_hwnum(pending));
diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c
index b5f84e8f0899..059cad6c3f69 100644
--- a/arch/powerpc/platforms/cell/io-workarounds.c
+++ b/arch/powerpc/platforms/cell/io-workarounds.c
@@ -130,14 +130,14 @@ static const struct ppc_pci_io __devinitconst iowa_pci_io = {
};
-static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size,
+static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size,
unsigned long flags)
{
struct iowa_bus *bus;
void __iomem *res = __ioremap(addr, size, flags);
int busno;
- bus = iowa_pci_find(0, addr);
+ bus = iowa_pci_find(0, (unsigned long)addr);
if (bus != NULL) {
busno = bus - iowa_busses;
PCI_SET_ADDR_TOKEN(res, busno + 1);
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 86db4dd170a0..ee5033eddf01 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -150,8 +150,8 @@ static int cbe_nr_iommus;
static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
long n_ptes)
{
- unsigned long __iomem *reg;
- unsigned long val;
+ u64 __iomem *reg;
+ u64 val;
long n;
reg = iommu->xlate_regs + IOC_IOPT_CacheInvd;
@@ -855,7 +855,7 @@ static int __init cell_iommu_init_disabled(void)
*/
if (np && size < lmb_end_of_DRAM()) {
printk(KERN_WARNING "iommu: force-enabled, dma window"
- " (%ldMB) smaller than total memory (%ldMB)\n",
+ " (%ldMB) smaller than total memory (%lldMB)\n",
size >> 20, lmb_end_of_DRAM() >> 20);
return -ENODEV;
}
@@ -985,7 +985,7 @@ static void cell_dma_dev_setup_fixed(struct device *dev)
addr = cell_iommu_get_fixed_address(dev) + dma_iommu_fixed_base;
archdata->dma_data = (void *)addr;
- dev_dbg(dev, "iommu: fixed addr = %lx\n", addr);
+ dev_dbg(dev, "iommu: fixed addr = %llx\n", addr);
}
static void insert_16M_pte(unsigned long addr, unsigned long *ptab,
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 7b4cefa2199b..5f961c464cc4 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -38,16 +38,16 @@ static void dump_fir(int cpu)
/* Todo: do some nicer parsing of bits and based on them go down
* to other sub-units FIRs and not only IIC
*/
- printk(KERN_ERR "Global Checkstop FIR : 0x%016lx\n",
+ printk(KERN_ERR "Global Checkstop FIR : 0x%016llx\n",
in_be64(&pregs->checkstop_fir));
- printk(KERN_ERR "Global Recoverable FIR : 0x%016lx\n",
+ printk(KERN_ERR "Global Recoverable FIR : 0x%016llx\n",
in_be64(&pregs->checkstop_fir));
- printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n",
+ printk(KERN_ERR "Global MachineCheck FIR : 0x%016llx\n",
in_be64(&pregs->spec_att_mchk_fir));
if (iregs == NULL)
return;
- printk(KERN_ERR "IOC FIR : 0x%016lx\n",
+ printk(KERN_ERR "IOC FIR : 0x%016llx\n",
in_be64(&iregs->ioc_fir));
}
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index a5bdb89a17c3..e487ad68ac11 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -151,7 +151,7 @@ static inline void spu_load_slb(struct spu *spu, int slbe, struct spu_slb *slb)
{
struct spu_priv2 __iomem *priv2 = spu->priv2;
- pr_debug("%s: adding SLB[%d] 0x%016lx 0x%016lx\n",
+ pr_debug("%s: adding SLB[%d] 0x%016llx 0x%016llx\n",
__func__, slbe, slb->vsid, slb->esid);
out_be64(&priv2->slb_index_W, slbe);
@@ -221,7 +221,7 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
{
int ret;
- pr_debug("%s, %lx, %lx\n", __func__, dsisr, ea);
+ pr_debug("%s, %llx, %lx\n", __func__, dsisr, ea);
/*
* Handle kernel space hash faults immediately. User hash
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index 19f6bfdbb933..fec1495e6b12 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -54,7 +54,7 @@ long spu_sys_callback(struct spu_syscall_block *s)
long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6);
if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) {
- pr_debug("%s: invalid syscall #%ld", __func__, s->nr_ret);
+ pr_debug("%s: invalid syscall #%lld", __func__, s->nr_ret);
return -ENOSYS;
}
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
index 906a0a2a9fe1..1410443731eb 100644
--- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c
+++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
@@ -80,10 +80,10 @@ static void cpu_affinity_set(struct spu *spu, int cpu)
u64 route;
if (nr_cpus_node(spu->node)) {
- cpumask_t spumask = node_to_cpumask(spu->node);
- cpumask_t cpumask = node_to_cpumask(cpu_to_node(cpu));
+ const struct cpumask *spumask = cpumask_of_node(spu->node),
+ *cpumask = cpumask_of_node(cpu_to_node(cpu));
- if (!cpus_intersects(spumask, cpumask))
+ if (!cpumask_intersects(spumask, cpumask))
return;
}
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index af116aadba10..c4d4a19235e0 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -42,7 +42,7 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
return spufs_coredump_read[num].read(ctx, buffer, size, off);
data = spufs_coredump_read[num].get(ctx);
- ret = snprintf(buffer, size, "0x%.16lx", data);
+ ret = snprintf(buffer, size, "0x%.16llx", data);
if (ret >= size)
return size;
return ++ret; /* count trailing NULL */
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index f093a581ac74..a4dd3ae7223a 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -132,7 +132,7 @@ int spufs_handle_class1(struct spu_context *ctx)
spuctx_switch_state(ctx, SPU_UTIL_IOWAIT);
- pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
+ pr_debug("ctx %p: ea %016llx, dsisr %016llx state %d\n", ctx, ea,
dsisr, ctx->state);
ctx->stats.hash_flt++;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 7106b63d401b..0da7f2bf5ee1 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1654,7 +1654,7 @@ out:
static int spufs_check_valid_dma(struct mfc_dma_command *cmd)
{
- pr_debug("queueing DMA %x %lx %x %x %x\n", cmd->lsa,
+ pr_debug("queueing DMA %x %llx %x %x %x\n", cmd->lsa,
cmd->ea, cmd->size, cmd->tag, cmd->cmd);
switch (cmd->cmd) {
@@ -1671,7 +1671,7 @@ static int spufs_check_valid_dma(struct mfc_dma_command *cmd)
}
if ((cmd->lsa & 0xf) != (cmd->ea &0xf)) {
- pr_debug("invalid DMA alignment, ea %lx lsa %x\n",
+ pr_debug("invalid DMA alignment, ea %llx lsa %x\n",
cmd->ea, cmd->lsa);
return -EIO;
}
@@ -2633,7 +2633,7 @@ static int spufs_show_ctx(struct seq_file *s, void *private)
}
seq_printf(s, "%c flgs(%lx) sflgs(%lx) pri(%d) ts(%d) spu(%02d)"
- " %c %lx %lx %lx %lx %x %x\n",
+ " %c %llx %llx %llx %llx %x %x\n",
ctx->state == SPU_STATE_SAVED ? 'S' : 'R',
ctx->flags,
ctx->sched_flags,
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 6296bfd9cb0b..e309ef70a531 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -97,7 +97,6 @@ spufs_new_inode(struct super_block *sb, int mode)
inode->i_mode = mode;
inode->i_uid = current_fsuid();
inode->i_gid = current_fsgid();
- inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
out:
return inode;
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 2ad914c47493..6a0ad196aeb3 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -166,9 +166,9 @@ void spu_update_sched_info(struct spu_context *ctx)
static int __node_allowed(struct spu_context *ctx, int node)
{
if (nr_cpus_node(node)) {
- cpumask_t mask = node_to_cpumask(node);
+ const struct cpumask *mask = cpumask_of_node(node);
- if (cpus_intersects(mask, ctx->cpus_allowed))
+ if (cpumask_intersects(mask, &ctx->cpus_allowed))
return 1;
}
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 15c62d3ca129..3bf908e2873a 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -314,7 +314,7 @@ extern char *isolated_loader;
* we need to call spu_release(ctx) before sleeping, and
* then spu_acquire(ctx) when awoken.
*
- * Returns with state_mutex re-acquired when successfull or
+ * Returns with state_mutex re-acquired when successful or
* with -ERESTARTSYS and the state_mutex dropped when interrupted.
*/
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c
index 8c619963becc..1db6b9e037fc 100644
--- a/arch/powerpc/platforms/fsl_uli1575.c
+++ b/arch/powerpc/platforms/fsl_uli1575.c
@@ -249,6 +249,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x5249, quirk_final_uli5249);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 0x1575, quirk_final_uli1575);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
static void __devinit hpcd_quirk_uli1575(struct pci_dev *dev)
{
diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig
index ed3753d8c109..7ddd0a2c8027 100644
--- a/arch/powerpc/platforms/iseries/Kconfig
+++ b/arch/powerpc/platforms/iseries/Kconfig
@@ -10,18 +10,21 @@ menu "iSeries device drivers"
config VIODASD
tristate "iSeries Virtual I/O disk support"
depends on BLOCK
+ select VIOPATH
help
If you are running on an iSeries system and you want to use
virtual disks created and managed by OS/400, say Y.
config VIOCD
tristate "iSeries Virtual I/O CD support"
+ select VIOPATH
help
If you are running Linux on an IBM iSeries system and you want to
read a CD drive owned by OS/400, say Y here.
config VIOTAPE
tristate "iSeries Virtual Tape Support"
+ select VIOPATH
help
If you are running Linux on an iSeries system and you want Linux
to read and/or write a tape drive owned by OS/400, say Y here.
@@ -30,5 +33,3 @@ endmenu
config VIOPATH
bool
- depends on VIODASD || VIOCD || VIOTAPE || ISERIES_VETH
- default y
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index bbe828f1b885..6ed75bffc8ab 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -66,7 +66,7 @@ static int tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
if (rc)
- panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
+ panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%llx\n",
rc);
index++;
uaddr += TCE_PAGE_SIZE;
@@ -81,7 +81,7 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
while (npages--) {
rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0);
if (rc)
- panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
+ panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%llx\n",
rc);
index++;
}
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 70b688c1aefb..24519b96d6ad 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/seq_file.h>
#include <linux/kdev_t.h>
+#include <linux/kexec.h>
#include <linux/major.h>
#include <linux/root_dev.h>
#include <linux/kernel.h>
@@ -638,6 +639,13 @@ static int __init iseries_probe(void)
return 1;
}
+#ifdef CONFIG_KEXEC
+static int iseries_kexec_prepare(struct kimage *image)
+{
+ return -ENOSYS;
+}
+#endif
+
define_machine(iseries) {
.name = "iSeries",
.setup_arch = iSeries_setup_arch,
@@ -658,6 +666,9 @@ define_machine(iseries) {
.probe = iseries_probe,
.ioremap = iseries_ioremap,
.iounmap = iseries_iounmap,
+#ifdef CONFIG_KEXEC
+ .machine_kexec_prepare = iseries_kexec_prepare,
+#endif
/* XXX Implement enable_pmcs for iSeries */
};
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index 58556b028a4c..be2527a516ea 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -112,7 +112,7 @@ static int get_gizmo_latency(void)
static void set_astate(int cpu, unsigned int astate)
{
- u64 flags;
+ unsigned long flags;
/* Return if called before init has run */
if (unlikely(!sdcasr_mapbase))
@@ -213,7 +213,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
pr_debug("current astate is at %d\n",cur_astate);
policy->cur = pas_freqs[cur_astate].frequency;
- policy->cpus = cpu_online_map;
+ cpumask_copy(policy->cpus, &cpu_online_map);
ppc_proc_freq = policy->cur * 1000ul;
diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c
index 217af321b0ca..a6152d922243 100644
--- a/arch/powerpc/platforms/pasemi/dma_lib.c
+++ b/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -509,7 +509,7 @@ fallback:
*/
int pasemi_dma_init(void)
{
- static spinlock_t init_lock = SPIN_LOCK_UNLOCKED;
+ static DEFINE_SPINLOCK(init_lock);
struct pci_dev *iob_pdev;
struct pci_dev *pdev;
struct resource res;
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index 4dfb4bc242b5..beb38333b6d2 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -362,7 +362,7 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
/* secondary CPUs are tied to the primary one by the
* cpufreq core if in the secondary policy we tell it that
* it actually must be one policy together with all others. */
- policy->cpus = cpu_online_map;
+ cpumask_copy(policy->cpus, &cpu_online_map);
cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
return cpufreq_frequency_table_cpuinfo(policy,
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index 54b7b76ed4f0..04cdd32624d4 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -661,6 +661,7 @@ static void __init init_second_ohare(void)
pci_find_hose_for_OF_device(np);
if (!hose) {
printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
+ of_node_put(np);
return;
}
early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
@@ -669,6 +670,7 @@ static void __init init_second_ohare(void)
early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
}
has_second_ohare = 1;
+ of_node_put(np);
}
/*
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 6b0711c15eca..bd8817b00fa4 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -53,7 +53,7 @@
#include <asm/pmac_low_i2c.h>
#include <asm/pmac_pfunc.h>
-#define DEBUG
+#undef DEBUG
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
index 59eb840d8ce2..1810e4226e56 100644
--- a/arch/powerpc/platforms/powermac/time.c
+++ b/arch/powerpc/platforms/powermac/time.c
@@ -265,12 +265,15 @@ int __init via_calibrate_decr(void)
struct resource rsrc;
vias = of_find_node_by_name(NULL, "via-cuda");
- if (vias == 0)
+ if (vias == NULL)
vias = of_find_node_by_name(NULL, "via-pmu");
- if (vias == 0)
+ if (vias == NULL)
vias = of_find_node_by_name(NULL, "via");
- if (vias == 0 || of_address_to_resource(vias, 0, &rsrc))
+ if (vias == NULL || of_address_to_resource(vias, 0, &rsrc)) {
+ of_node_put(vias);
return 0;
+ }
+ of_node_put(vias);
via = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
if (via == NULL) {
printk(KERN_ERR "Failed to map VIA for timer calibration !\n");
@@ -297,7 +300,7 @@ int __init via_calibrate_decr(void)
ppc_tb_freq = (dstart - dend) * 100 / 6;
iounmap(via);
-
+
return 1;
}
#endif
diff --git a/arch/powerpc/platforms/ps3/device-init.c b/arch/powerpc/platforms/ps3/device-init.c
index dbc124e05646..bb028f165fb3 100644
--- a/arch/powerpc/platforms/ps3/device-init.c
+++ b/arch/powerpc/platforms/ps3/device-init.c
@@ -82,7 +82,7 @@ static int __init ps3_register_lpm_devices(void)
goto fail_rights;
}
- pr_debug("%s:%d: pu_id %lu, rights %lu(%lxh)\n",
+ pr_debug("%s:%d: pu_id %llu, rights %llu(%llxh)\n",
__func__, __LINE__, dev->lpm.pu_id, dev->lpm.rights,
dev->lpm.rights);
@@ -348,7 +348,7 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
return -ENODEV;
}
- pr_debug("%s:%u: (%u:%u:%u): port %lu blk_size %lu num_blocks %lu "
+ pr_debug("%s:%u: (%u:%u:%u): port %llu blk_size %llu num_blocks %llu "
"num_regions %u\n", __func__, __LINE__, repo->bus_index,
repo->dev_index, repo->dev_type, port, blk_size, num_blocks,
num_regions);
@@ -394,7 +394,7 @@ static int ps3_setup_storage_dev(const struct ps3_repository_device *repo,
result = -ENODEV;
goto fail_read_region;
}
- pr_debug("%s:%u: region %u: id %u start %lu size %lu\n",
+ pr_debug("%s:%u: region %u: id %u start %llu size %llu\n",
__func__, __LINE__, i, id, start, size);
p->regions[i].id = id;
@@ -518,6 +518,41 @@ fail_device_register:
return result;
}
+static int __init ps3_register_ramdisk_device(void)
+{
+ int result;
+ struct layout {
+ struct ps3_system_bus_device dev;
+ } *p;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ p = kzalloc(sizeof(struct layout), GFP_KERNEL);
+
+ if (!p)
+ return -ENOMEM;
+
+ p->dev.match_id = PS3_MATCH_ID_GPU;
+ p->dev.match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK;
+ p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
+
+ result = ps3_system_bus_device_register(&p->dev);
+
+ if (result) {
+ pr_debug("%s:%d ps3_system_bus_device_register failed\n",
+ __func__, __LINE__);
+ goto fail_device_register;
+ }
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+ return 0;
+
+fail_device_register:
+ kfree(p);
+ pr_debug(" <- %s:%d failed\n", __func__, __LINE__);
+ return result;
+}
+
/**
* ps3_setup_dynamic_device - Setup a dynamic device from the repository
*/
@@ -627,13 +662,13 @@ static void ps3_find_and_add_device(u64 bus_id, u64 dev_id)
if (rem)
break;
}
- pr_warning("%s:%u: device %lu:%lu not found\n", __func__, __LINE__,
+ pr_warning("%s:%u: device %llu:%llu not found\n", __func__, __LINE__,
bus_id, dev_id);
return;
found:
if (retries)
- pr_debug("%s:%u: device %lu:%lu found after %u retries\n",
+ pr_debug("%s:%u: device %llu:%llu found after %u retries\n",
__func__, __LINE__, bus_id, dev_id, retries);
ps3_setup_dynamic_device(&repo);
@@ -680,14 +715,14 @@ static irqreturn_t ps3_notification_interrupt(int irq, void *data)
res = lv1_storage_get_async_status(PS3_NOTIFICATION_DEV_ID, &tag,
&status);
if (tag != dev->tag)
- pr_err("%s:%u: tag mismatch, got %lx, expected %lx\n",
+ pr_err("%s:%u: tag mismatch, got %llx, expected %llx\n",
__func__, __LINE__, tag, dev->tag);
if (res) {
- pr_err("%s:%u: res %d status 0x%lx\n", __func__, __LINE__, res,
+ pr_err("%s:%u: res %d status 0x%llx\n", __func__, __LINE__, res,
status);
} else {
- pr_debug("%s:%u: completed, status 0x%lx\n", __func__,
+ pr_debug("%s:%u: completed, status 0x%llx\n", __func__,
__LINE__, status);
dev->lv1_status = status;
complete(&dev->done);
@@ -726,7 +761,7 @@ static int ps3_notification_read_write(struct ps3_notification_device *dev,
}
if (dev->lv1_status) {
- pr_err("%s:%u: %s not completed, status 0x%lx\n", __func__,
+ pr_err("%s:%u: %s not completed, status 0x%llx\n", __func__,
__LINE__, op, dev->lv1_status);
return -EIO;
}
@@ -815,16 +850,16 @@ static int ps3_probe_thread(void *data)
if (res)
break;
- pr_debug("%s:%u: notify event type 0x%lx bus id %lu dev id %lu"
- " type %lu port %lu\n", __func__, __LINE__,
+ pr_debug("%s:%u: notify event type 0x%llx bus id %llu dev id %llu"
+ " type %llu port %llu\n", __func__, __LINE__,
notify_event->event_type, notify_event->bus_id,
notify_event->dev_id, notify_event->dev_type,
notify_event->dev_port);
if (notify_event->event_type != notify_region_probe ||
notify_event->bus_id != dev.sbd.bus_id) {
- pr_warning("%s:%u: bad notify_event: event %lu, "
- "dev_id %lu, dev_type %lu\n",
+ pr_warning("%s:%u: bad notify_event: event %llu, "
+ "dev_id %llu, dev_type %llu\n",
__func__, __LINE__, notify_event->event_type,
notify_event->dev_id,
notify_event->dev_type);
@@ -946,6 +981,8 @@ static int __init ps3_register_devices(void)
ps3_register_lpm_devices();
+ ps3_register_ramdisk_device();
+
pr_debug(" <- %s:%d\n", __func__, __LINE__);
return 0;
}
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 6eb1d4d182c9..1e8a1e39dfe8 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -75,7 +75,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
if (result) {
/* all entries bolted !*/
- pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%lx r=%lx\n",
+ pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
__func__, result, va, pa, hpte_group, hpte_v, hpte_r);
BUG();
}
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index e59634f7af96..8ec5ccf76b19 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -60,6 +60,8 @@
* gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note
* that there is no constraint on how many in this set an individual thread
* can acquire.
+ *
+ * The mask is declared as unsigned long so we can use set/clear_bit on it.
*/
#define PS3_BMP_MINALIGN 64
@@ -68,7 +70,7 @@ struct ps3_bmp {
struct {
u64 status;
u64 unused_1[3];
- u64 mask;
+ unsigned long mask;
u64 unused_2[3];
};
u64 ipi_debug_brk_mask;
@@ -102,7 +104,7 @@ static void ps3_chip_mask(unsigned int virq)
struct ps3_private *pd = get_irq_chip_data(virq);
unsigned long flags;
- pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+ pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
pd->thread_id, virq);
local_irq_save(flags);
@@ -123,7 +125,7 @@ static void ps3_chip_unmask(unsigned int virq)
struct ps3_private *pd = get_irq_chip_data(virq);
unsigned long flags;
- pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__,
+ pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
pd->thread_id, virq);
local_irq_save(flags);
@@ -221,7 +223,7 @@ static int ps3_virq_destroy(unsigned int virq)
{
const struct ps3_private *pd = get_irq_chip_data(virq);
- pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+ pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
__LINE__, pd->ppe_id, pd->thread_id, virq);
set_irq_chip_data(virq, NULL);
@@ -291,7 +293,7 @@ int ps3_irq_plug_destroy(unsigned int virq)
int result;
const struct ps3_private *pd = get_irq_chip_data(virq);
- pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__,
+ pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
__LINE__, pd->ppe_id, pd->thread_id, virq);
ps3_chip_mask(virq);
@@ -322,7 +324,7 @@ EXPORT_SYMBOL_GPL(ps3_irq_plug_destroy);
int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq)
{
int result;
- unsigned long outlet;
+ u64 outlet;
result = lv1_construct_event_receive_port(&outlet);
@@ -468,7 +470,7 @@ int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id,
unsigned int *virq)
{
int result;
- unsigned long outlet;
+ u64 outlet;
result = lv1_construct_io_irq_outlet(interrupt_id, &outlet);
@@ -525,7 +527,7 @@ int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp,
unsigned int *virq)
{
int result;
- unsigned long outlet;
+ u64 outlet;
u64 lpar_addr;
BUG_ON(!is_kernel_addr((u64)virt_addr_bmp));
@@ -581,7 +583,7 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id,
unsigned int class, unsigned int *virq)
{
int result;
- unsigned long outlet;
+ u64 outlet;
BUG_ON(class > 2);
@@ -691,7 +693,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
pd->bmp.ipi_debug_brk_mask = 0x8000000000000000UL >> virq;
- pr_debug("%s:%d: cpu %u, virq %u, mask %lxh\n", __func__, __LINE__,
+ pr_debug("%s:%d: cpu %u, virq %u, mask %llxh\n", __func__, __LINE__,
cpu, virq, pd->bmp.ipi_debug_brk_mask);
}
@@ -710,7 +712,7 @@ static unsigned int ps3_get_irq(void)
plug &= 0x3f;
if (unlikely(plug == NO_IRQ)) {
- pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__,
+ pr_debug("%s:%d: no plug found: thread_id %llu\n", __func__,
__LINE__, pd->thread_id);
dump_bmp(&per_cpu(ps3_private, 0));
dump_bmp(&per_cpu(ps3_private, 1));
@@ -745,7 +747,7 @@ void __init ps3_init_IRQ(void)
pd->thread_id = get_hard_smp_processor_id(cpu);
spin_lock_init(&pd->bmp.lock);
- pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n",
+ pr_debug("%s:%d: ppe_id %llu, thread_id %llu, bmp %lxh\n",
__func__, __LINE__, pd->ppe_id, pd->thread_id,
ps3_mm_phys_to_lpar(__pa(&pd->bmp)));
@@ -770,6 +772,6 @@ void ps3_shutdown_IRQ(int cpu)
lv1_get_logical_ppe_id(&ppe_id);
result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0);
- DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__,
+ DBG("%s:%d: lv1_configure_irq_state_bitmap (%llu:%llu/%d) %s\n", __func__,
__LINE__, ppe_id, thread_id, cpu, ps3_result(result));
}
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index a4d49dd9e8a9..67de6bf3db3d 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -79,8 +79,8 @@ enum {
*/
struct mem_region {
- unsigned long base;
- unsigned long size;
+ u64 base;
+ u64 size;
unsigned long offset;
};
@@ -103,9 +103,9 @@ struct mem_region {
*/
struct map {
- unsigned long total;
- unsigned long vas_id;
- unsigned long htab_size;
+ u64 total;
+ u64 vas_id;
+ u64 htab_size;
struct mem_region rm;
struct mem_region r1;
};
@@ -114,13 +114,13 @@ struct map {
static void __maybe_unused _debug_dump_map(const struct map *m,
const char *func, int line)
{
- DBG("%s:%d: map.total = %lxh\n", func, line, m->total);
- DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size);
- DBG("%s:%d: map.vas_id = %lu\n", func, line, m->vas_id);
- DBG("%s:%d: map.htab_size = %lxh\n", func, line, m->htab_size);
- DBG("%s:%d: map.r1.base = %lxh\n", func, line, m->r1.base);
+ DBG("%s:%d: map.total = %llxh\n", func, line, m->total);
+ DBG("%s:%d: map.rm.size = %llxh\n", func, line, m->rm.size);
+ DBG("%s:%d: map.vas_id = %llu\n", func, line, m->vas_id);
+ DBG("%s:%d: map.htab_size = %llxh\n", func, line, m->htab_size);
+ DBG("%s:%d: map.r1.base = %llxh\n", func, line, m->r1.base);
DBG("%s:%d: map.r1.offset = %lxh\n", func, line, m->r1.offset);
- DBG("%s:%d: map.r1.size = %lxh\n", func, line, m->r1.size);
+ DBG("%s:%d: map.r1.size = %llxh\n", func, line, m->r1.size);
}
static struct map map;
@@ -146,11 +146,11 @@ EXPORT_SYMBOL(ps3_mm_phys_to_lpar);
void __init ps3_mm_vas_create(unsigned long* htab_size)
{
int result;
- unsigned long start_address;
- unsigned long size;
- unsigned long access_right;
- unsigned long max_page_size;
- unsigned long flags;
+ u64 start_address;
+ u64 size;
+ u64 access_right;
+ u64 max_page_size;
+ u64 flags;
result = lv1_query_logical_partition_address_region_info(0,
&start_address, &size, &access_right, &max_page_size,
@@ -164,7 +164,7 @@ void __init ps3_mm_vas_create(unsigned long* htab_size)
}
if (max_page_size < PAGE_SHIFT_16M) {
- DBG("%s:%d: bad max_page_size %lxh\n", __func__, __LINE__,
+ DBG("%s:%d: bad max_page_size %llxh\n", __func__, __LINE__,
max_page_size);
goto fail;
}
@@ -208,7 +208,7 @@ void ps3_mm_vas_destroy(void)
{
int result;
- DBG("%s:%d: map.vas_id = %lu\n", __func__, __LINE__, map.vas_id);
+ DBG("%s:%d: map.vas_id = %llu\n", __func__, __LINE__, map.vas_id);
if (map.vas_id) {
result = lv1_select_virtual_address_space(0);
@@ -235,15 +235,14 @@ void ps3_mm_vas_destroy(void)
static int ps3_mm_region_create(struct mem_region *r, unsigned long size)
{
int result;
- unsigned long muid;
+ u64 muid;
r->size = _ALIGN_DOWN(size, 1 << PAGE_SHIFT_16M);
DBG("%s:%d requested %lxh\n", __func__, __LINE__, size);
- DBG("%s:%d actual %lxh\n", __func__, __LINE__, r->size);
- DBG("%s:%d difference %lxh (%luMB)\n", __func__, __LINE__,
- (unsigned long)(size - r->size),
- (size - r->size) / 1024 / 1024);
+ DBG("%s:%d actual %llxh\n", __func__, __LINE__, r->size);
+ DBG("%s:%d difference %llxh (%lluMB)\n", __func__, __LINE__,
+ size - r->size, (size - r->size) / 1024 / 1024);
if (r->size == 0) {
DBG("%s:%d: size == 0\n", __func__, __LINE__);
@@ -277,7 +276,7 @@ static void ps3_mm_region_destroy(struct mem_region *r)
{
int result;
- DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base);
+ DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base);
if (r->base) {
result = lv1_release_memory(r->base);
BUG_ON(result);
@@ -355,7 +354,7 @@ static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r,
static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r,
const char *func, int line)
{
- DBG("%s:%d: dev %lu:%lu\n", func, line, r->dev->bus_id,
+ DBG("%s:%d: dev %llu:%llu\n", func, line, r->dev->bus_id,
r->dev->dev_id);
DBG("%s:%d: page_size %u\n", func, line, r->page_size);
DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
@@ -390,7 +389,7 @@ struct dma_chunk {
static void _dma_dump_chunk (const struct dma_chunk* c, const char* func,
int line)
{
- DBG("%s:%d: r.dev %lu:%lu\n", func, line,
+ DBG("%s:%d: r.dev %llu:%llu\n", func, line,
c->region->dev->bus_id, c->region->dev->dev_id);
DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr);
DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size);
@@ -596,7 +595,7 @@ static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr,
/* build ioptes for the area */
pages = len >> r->page_size;
- DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__,
+ DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#llx\n", __func__,
r->page_size, r->len, pages, iopte_flag);
for (iopage = 0; iopage < pages; iopage++) {
offset = (1 << r->page_size) * iopage;
@@ -648,13 +647,14 @@ fail_alloc:
static int dma_sb_region_create(struct ps3_dma_region *r)
{
int result;
+ u64 bus_addr;
DBG(" -> %s:%d:\n", __func__, __LINE__);
BUG_ON(!r);
if (!r->dev->bus_id) {
- pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__,
+ pr_info("%s:%d: %llu:%llu no dma\n", __func__, __LINE__,
r->dev->bus_id, r->dev->dev_id);
return 0;
}
@@ -671,7 +671,8 @@ static int dma_sb_region_create(struct ps3_dma_region *r)
result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id,
roundup_pow_of_two(r->len), r->page_size, r->region_type,
- &r->bus_addr);
+ &bus_addr);
+ r->bus_addr = bus_addr;
if (result) {
DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n",
@@ -685,6 +686,7 @@ static int dma_sb_region_create(struct ps3_dma_region *r)
static int dma_ioc0_region_create(struct ps3_dma_region *r)
{
int result;
+ u64 bus_addr;
INIT_LIST_HEAD(&r->chunk_list.head);
spin_lock_init(&r->chunk_list.lock);
@@ -692,7 +694,8 @@ static int dma_ioc0_region_create(struct ps3_dma_region *r)
result = lv1_allocate_io_segment(0,
r->len,
r->page_size,
- &r->bus_addr);
+ &bus_addr);
+ r->bus_addr = bus_addr;
if (result) {
DBG("%s:%d: lv1_allocate_io_segment failed: %s\n",
__func__, __LINE__, ps3_result(result));
@@ -720,7 +723,7 @@ static int dma_sb_region_free(struct ps3_dma_region *r)
BUG_ON(!r);
if (!r->dev->bus_id) {
- pr_info("%s:%d: %lu:%lu no dma\n", __func__, __LINE__,
+ pr_info("%s:%d: %llu:%llu no dma\n", __func__, __LINE__,
r->dev->bus_id, r->dev->dev_id);
return 0;
}
@@ -777,7 +780,7 @@ static int dma_ioc0_region_free(struct ps3_dma_region *r)
*/
static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
- unsigned long len, unsigned long *bus_addr,
+ unsigned long len, dma_addr_t *bus_addr,
u64 iopte_flag)
{
int result;
@@ -800,7 +803,7 @@ static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
DBG("%s:%d lpar_addr %lxh\n", __func__, __LINE__,
lpar_addr);
DBG("%s:%d len %lxh\n", __func__, __LINE__, len);
- DBG("%s:%d bus_addr %lxh (%lxh)\n", __func__, __LINE__,
+ DBG("%s:%d bus_addr %llxh (%lxh)\n", __func__, __LINE__,
*bus_addr, len);
}
@@ -832,7 +835,7 @@ static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
}
static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
- unsigned long len, unsigned long *bus_addr,
+ unsigned long len, dma_addr_t *bus_addr,
u64 iopte_flag)
{
int result;
@@ -872,7 +875,7 @@ static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
return result;
}
*bus_addr = c->bus_addr + phys_addr - aligned_phys;
- DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__,
+ DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#llx\n", __func__,
virt_addr, phys_addr, aligned_phys, *bus_addr);
c->usage_count = 1;
@@ -889,7 +892,7 @@ static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr,
* This is the common dma unmap routine.
*/
-static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
+static int dma_sb_unmap_area(struct ps3_dma_region *r, dma_addr_t bus_addr,
unsigned long len)
{
unsigned long flags;
@@ -903,7 +906,7 @@ static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
1 << r->page_size);
unsigned long aligned_len = _ALIGN_UP(len + bus_addr
- aligned_bus, 1 << r->page_size);
- DBG("%s:%d: not found: bus_addr %lxh\n",
+ DBG("%s:%d: not found: bus_addr %llxh\n",
__func__, __LINE__, bus_addr);
DBG("%s:%d: not found: len %lxh\n",
__func__, __LINE__, len);
@@ -926,12 +929,12 @@ static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr,
}
static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
- unsigned long bus_addr, unsigned long len)
+ dma_addr_t bus_addr, unsigned long len)
{
unsigned long flags;
struct dma_chunk *c;
- DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len);
+ DBG("%s: start a=%#llx l=%#lx\n", __func__, bus_addr, len);
spin_lock_irqsave(&r->chunk_list.lock, flags);
c = dma_find_chunk(r, bus_addr, len);
@@ -941,7 +944,7 @@ static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
unsigned long aligned_len = _ALIGN_UP(len + bus_addr
- aligned_bus,
1 << r->page_size);
- DBG("%s:%d: not found: bus_addr %lxh\n",
+ DBG("%s:%d: not found: bus_addr %llxh\n",
__func__, __LINE__, bus_addr);
DBG("%s:%d: not found: len %lxh\n",
__func__, __LINE__, len);
@@ -975,7 +978,8 @@ static int dma_ioc0_unmap_area(struct ps3_dma_region *r,
static int dma_sb_region_create_linear(struct ps3_dma_region *r)
{
int result;
- unsigned long virt_addr, len, tmp;
+ unsigned long virt_addr, len;
+ dma_addr_t tmp;
if (r->len > 16*1024*1024) { /* FIXME: need proper fix */
/* force 16M dma pages for linear mapping */
@@ -1027,7 +1031,8 @@ static int dma_sb_region_create_linear(struct ps3_dma_region *r)
static int dma_sb_region_free_linear(struct ps3_dma_region *r)
{
int result;
- unsigned long bus_addr, len, lpar_addr;
+ dma_addr_t bus_addr;
+ unsigned long len, lpar_addr;
if (r->offset < map.rm.size) {
/* Unmap (part of) 1st RAM chunk */
@@ -1072,7 +1077,7 @@ static int dma_sb_region_free_linear(struct ps3_dma_region *r)
*/
static int dma_sb_map_area_linear(struct ps3_dma_region *r,
- unsigned long virt_addr, unsigned long len, unsigned long *bus_addr,
+ unsigned long virt_addr, unsigned long len, dma_addr_t *bus_addr,
u64 iopte_flag)
{
unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr)
@@ -1091,7 +1096,7 @@ static int dma_sb_map_area_linear(struct ps3_dma_region *r,
*/
static int dma_sb_unmap_area_linear(struct ps3_dma_region *r,
- unsigned long bus_addr, unsigned long len)
+ dma_addr_t bus_addr, unsigned long len)
{
return 0;
};
@@ -1169,13 +1174,13 @@ int ps3_dma_region_free(struct ps3_dma_region *r)
EXPORT_SYMBOL(ps3_dma_region_free);
int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
- unsigned long len, unsigned long *bus_addr,
+ unsigned long len, dma_addr_t *bus_addr,
u64 iopte_flag)
{
return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag);
}
-int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
+int ps3_dma_unmap(struct ps3_dma_region *r, dma_addr_t bus_addr,
unsigned long len)
{
return r->region_ops->unmap(r, bus_addr, len);
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index 1d201782d4e5..e1c83c23b435 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -306,7 +306,7 @@ static void _dump_params(const struct os_area_params *p, const char *func,
{
pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag);
pr_debug("%s:%d: p.num_params: %u\n", func, line, p->num_params);
- pr_debug("%s:%d: p.rtc_diff %ld\n", func, line, p->rtc_diff);
+ pr_debug("%s:%d: p.rtc_diff %lld\n", func, line, p->rtc_diff);
pr_debug("%s:%d: p.av_multi_out %u\n", func, line, p->av_multi_out);
pr_debug("%s:%d: p.ctrl_button: %u\n", func, line, p->ctrl_button);
pr_debug("%s:%d: p.static_ip_addr: %u.%u.%u.%u\n", func, line,
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c
index 22063adeb38b..5e304c292f68 100644
--- a/arch/powerpc/platforms/ps3/repository.c
+++ b/arch/powerpc/platforms/ps3/repository.c
@@ -44,7 +44,7 @@ static void _dump_field(const char *hdr, u64 n, const char *func, int line)
s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';
s[i] = 0;
- pr_debug("%s:%d: %s%016lx : %s\n", func, line, hdr, n, s);
+ pr_debug("%s:%d: %s%016llx : %s\n", func, line, hdr, n, s);
#endif
}
@@ -70,8 +70,8 @@ static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
_dump_field("n2: ", n2, func, line);
_dump_field("n3: ", n3, func, line);
_dump_field("n4: ", n4, func, line);
- pr_debug("%s:%d: v1: %016lx\n", func, line, v1);
- pr_debug("%s:%d: v2: %016lx\n", func, line, v2);
+ pr_debug("%s:%d: v1: %016llx\n", func, line, v1);
+ pr_debug("%s:%d: v2: %016llx\n", func, line, v2);
}
/**
@@ -149,10 +149,10 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,
*_v2 = v2;
if (v1 && !_v1)
- pr_debug("%s:%d: warning: discarding non-zero v1: %016lx\n",
+ pr_debug("%s:%d: warning: discarding non-zero v1: %016llx\n",
__func__, __LINE__, v1);
if (v2 && !_v2)
- pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",
+ pr_debug("%s:%d: warning: discarding non-zero v2: %016llx\n",
__func__, __LINE__, v2);
return 0;
@@ -327,7 +327,7 @@ int ps3_repository_find_device(struct ps3_repository_device *repo)
return result;
}
- pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %lu, num_dev %u\n",
+ pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %llu, num_dev %u\n",
__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,
num_dev);
@@ -353,7 +353,7 @@ int ps3_repository_find_device(struct ps3_repository_device *repo)
return result;
}
- pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %lu\n",
+ pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %llu\n",
__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);
*repo = tmp;
@@ -367,7 +367,7 @@ int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
struct ps3_repository_device tmp;
unsigned int num_dev;
- pr_debug(" -> %s:%u: find device by id %lu:%lu\n", __func__, __LINE__,
+ pr_debug(" -> %s:%u: find device by id %llu:%llu\n", __func__, __LINE__,
bus_id, dev_id);
for (tmp.bus_index = 0; tmp.bus_index < 10; tmp.bus_index++) {
@@ -382,7 +382,7 @@ int ps3_repository_find_device_by_id(struct ps3_repository_device *repo,
if (tmp.bus_id == bus_id)
goto found_bus;
- pr_debug("%s:%u: skip, bus_id %lu\n", __func__, __LINE__,
+ pr_debug("%s:%u: skip, bus_id %llu\n", __func__, __LINE__,
tmp.bus_id);
}
pr_debug(" <- %s:%u: bus not found\n", __func__, __LINE__);
@@ -416,7 +416,7 @@ found_bus:
if (tmp.dev_id == dev_id)
goto found_dev;
- pr_debug("%s:%u: skip, dev_id %lu\n", __func__, __LINE__,
+ pr_debug("%s:%u: skip, dev_id %llu\n", __func__, __LINE__,
tmp.dev_id);
}
pr_debug(" <- %s:%u: dev not found\n", __func__, __LINE__);
@@ -430,7 +430,7 @@ found_dev:
return result;
}
- pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%lu:%lu)\n",
+ pr_debug(" <- %s:%u: found: type (%u:%u) index (%u:%u) id (%llu:%llu)\n",
__func__, __LINE__, tmp.bus_type, tmp.dev_type, tmp.bus_index,
tmp.dev_index, tmp.bus_id, tmp.dev_id);
*repo = tmp;
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 35f3e85cf60e..3331ccbb8d38 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -186,7 +186,7 @@ early_param("ps3flash", early_parse_ps3flash);
#define prealloc_ps3flash_bounce_buffer() do { } while (0)
#endif
-static int ps3_set_dabr(u64 dabr)
+static int ps3_set_dabr(unsigned long dabr)
{
enum {DABR_USER = 1, DABR_KERNEL = 2,};
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c
index ccae3d446b98..b3c6a993f9f3 100644
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -149,7 +149,7 @@ EXPORT_SYMBOL_GPL(ps3_get_spe_id);
static unsigned long get_vas_id(void)
{
- unsigned long id;
+ u64 id;
lv1_get_logical_ppe_id(&id);
lv1_get_virtual_address_space_id_of_ppe(id, &id);
@@ -160,14 +160,18 @@ static unsigned long get_vas_id(void)
static int __init construct_spu(struct spu *spu)
{
int result;
- unsigned long unused;
+ u64 unused;
+ u64 problem_phys;
+ u64 local_store_phys;
result = lv1_construct_logical_spe(PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT,
PAGE_SHIFT, PAGE_SHIFT, get_vas_id(), SPE_TYPE_LOGICAL,
- &spu_pdata(spu)->priv2_addr, &spu->problem_phys,
- &spu->local_store_phys, &unused,
+ &spu_pdata(spu)->priv2_addr, &problem_phys,
+ &local_store_phys, &unused,
&spu_pdata(spu)->shadow_addr,
&spu_pdata(spu)->spe_id);
+ spu->problem_phys = problem_phys;
+ spu->local_store_phys = local_store_phys;
if (result) {
pr_debug("%s:%d: lv1_construct_logical_spe failed: %s\n",
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index ee0d22911621..58311a867851 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -182,7 +182,7 @@ int ps3_open_hv_device(struct ps3_system_bus_device *dev)
case PS3_MATCH_ID_SYSTEM_MANAGER:
pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
__LINE__, dev->match_id);
- pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__,
+ pr_debug("%s:%d: bus_id: %llu\n", __func__, __LINE__,
dev->bus_id);
BUG();
return -EINVAL;
@@ -220,7 +220,7 @@ int ps3_close_hv_device(struct ps3_system_bus_device *dev)
case PS3_MATCH_ID_SYSTEM_MANAGER:
pr_debug("%s:%d: unsupported match_id: %u\n", __func__,
__LINE__, dev->match_id);
- pr_debug("%s:%d: bus_id: %lu\n", __func__, __LINE__,
+ pr_debug("%s:%d: bus_id: %llu\n", __func__, __LINE__,
dev->bus_id);
BUG();
return -EINVAL;
@@ -240,7 +240,7 @@ EXPORT_SYMBOL_GPL(ps3_close_hv_device);
static void _dump_mmio_region(const struct ps3_mmio_region* r,
const char* func, int line)
{
- pr_debug("%s:%d: dev %lu:%lu\n", func, line, r->dev->bus_id,
+ pr_debug("%s:%d: dev %llu:%llu\n", func, line, r->dev->bus_id,
r->dev->dev_id);
pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr);
pr_debug("%s:%d: len %lxh\n", func, line, r->len);
@@ -250,9 +250,11 @@ static void _dump_mmio_region(const struct ps3_mmio_region* r,
static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r)
{
int result;
+ u64 lpar_addr;
result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
- r->bus_addr, r->len, r->page_size, &r->lpar_addr);
+ r->bus_addr, r->len, r->page_size, &lpar_addr);
+ r->lpar_addr = lpar_addr;
if (result) {
pr_debug("%s:%d: lv1_map_device_mmio_region failed: %s\n",
@@ -568,7 +570,7 @@ static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
- unsigned long bus_addr;
+ dma_addr_t bus_addr;
void *ptr = page_address(page) + offset;
result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
@@ -590,7 +592,7 @@ static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
- unsigned long bus_addr;
+ dma_addr_t bus_addr;
u64 iopte_flag;
void *ptr = page_address(page) + offset;
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index c90817acb472..3ee01b4f4257 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -127,10 +127,10 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
}
if (rc && printk_ratelimit()) {
- printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
- printk("\ttcenum = 0x%lx\n", (u64)tcenum);
- printk("\ttce val = 0x%lx\n", tce );
+ printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
+ printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
+ printk("\ttcenum = 0x%llx\n", (u64)tcenum);
+ printk("\ttce val = 0x%llx\n", tce );
show_stack(current, (unsigned long *)__get_SP());
}
@@ -210,10 +210,10 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
}
if (rc && printk_ratelimit()) {
- printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
- printk("\tnpages = 0x%lx\n", (u64)npages);
- printk("\ttce[0] val = 0x%lx\n", tcep[0]);
+ printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
+ printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
+ printk("\tnpages = 0x%llx\n", (u64)npages);
+ printk("\ttce[0] val = 0x%llx\n", tcep[0]);
show_stack(current, (unsigned long *)__get_SP());
}
return ret;
@@ -227,9 +227,9 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages
rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
if (rc && printk_ratelimit()) {
- printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
- printk("\ttcenum = 0x%lx\n", (u64)tcenum);
+ printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
+ printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
+ printk("\ttcenum = 0x%llx\n", (u64)tcenum);
show_stack(current, (unsigned long *)__get_SP());
}
@@ -246,9 +246,9 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n
if (rc && printk_ratelimit()) {
printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
- printk("\trc = %ld\n", rc);
- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
- printk("\tnpages = 0x%lx\n", (u64)npages);
+ printk("\trc = %lld\n", rc);
+ printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
+ printk("\tnpages = 0x%llx\n", (u64)npages);
show_stack(current, (unsigned long *)__get_SP());
}
}
@@ -261,10 +261,9 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret);
if (rc && printk_ratelimit()) {
- printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%ld\n",
- rc);
- printk("\tindex = 0x%lx\n", (u64)tbl->it_index);
- printk("\ttcenum = 0x%lx\n", (u64)tcenum);
+ printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc);
+ printk("\tindex = 0x%llx\n", (u64)tbl->it_index);
+ printk("\ttcenum = 0x%llx\n", (u64)tcenum);
show_stack(current, (unsigned long *)__get_SP());
}
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
index 6cf35cd8d0b5..15eb6107bcd2 100644
--- a/arch/powerpc/platforms/pseries/phyp_dump.c
+++ b/arch/powerpc/platforms/pseries/phyp_dump.c
@@ -144,8 +144,8 @@ static void print_dump_header(const struct phyp_dump_header *ph)
ph->first_offset_section);
printk(KERN_INFO "dump disk sections should be zero\n");
printk(KERN_INFO "dump disk section = %d\n", ph->dump_disk_section);
- printk(KERN_INFO "block num = %ld\n", ph->block_num_dd);
- printk(KERN_INFO "number of blocks = %ld\n", ph->num_of_blocks_dd);
+ printk(KERN_INFO "block num = %lld\n", ph->block_num_dd);
+ printk(KERN_INFO "number of blocks = %lld\n", ph->num_of_blocks_dd);
printk(KERN_INFO "dump disk offset = %d\n", ph->offset_dd);
printk(KERN_INFO "Max auto time= %d\n", ph->maxtime_to_auto);
@@ -154,33 +154,33 @@ static void print_dump_header(const struct phyp_dump_header *ph)
printk(KERN_INFO "cpu dump_flags =%d\n", ph->cpu_data.dump_flags);
printk(KERN_INFO "cpu source_type =%d\n", ph->cpu_data.source_type);
printk(KERN_INFO "cpu error_flags =%d\n", ph->cpu_data.error_flags);
- printk(KERN_INFO "cpu source_address =%lx\n",
+ printk(KERN_INFO "cpu source_address =%llx\n",
ph->cpu_data.source_address);
- printk(KERN_INFO "cpu source_length =%lx\n",
+ printk(KERN_INFO "cpu source_length =%llx\n",
ph->cpu_data.source_length);
- printk(KERN_INFO "cpu length_copied =%lx\n",
+ printk(KERN_INFO "cpu length_copied =%llx\n",
ph->cpu_data.length_copied);
printk(KERN_INFO " HPTE AREA \n");
printk(KERN_INFO "HPTE dump_flags =%d\n", ph->hpte_data.dump_flags);
printk(KERN_INFO "HPTE source_type =%d\n", ph->hpte_data.source_type);
printk(KERN_INFO "HPTE error_flags =%d\n", ph->hpte_data.error_flags);
- printk(KERN_INFO "HPTE source_address =%lx\n",
+ printk(KERN_INFO "HPTE source_address =%llx\n",
ph->hpte_data.source_address);
- printk(KERN_INFO "HPTE source_length =%lx\n",
+ printk(KERN_INFO "HPTE source_length =%llx\n",
ph->hpte_data.source_length);
- printk(KERN_INFO "HPTE length_copied =%lx\n",
+ printk(KERN_INFO "HPTE length_copied =%llx\n",
ph->hpte_data.length_copied);
printk(KERN_INFO " SRSD AREA \n");
printk(KERN_INFO "SRSD dump_flags =%d\n", ph->kernel_data.dump_flags);
printk(KERN_INFO "SRSD source_type =%d\n", ph->kernel_data.source_type);
printk(KERN_INFO "SRSD error_flags =%d\n", ph->kernel_data.error_flags);
- printk(KERN_INFO "SRSD source_address =%lx\n",
+ printk(KERN_INFO "SRSD source_address =%llx\n",
ph->kernel_data.source_address);
- printk(KERN_INFO "SRSD source_length =%lx\n",
+ printk(KERN_INFO "SRSD source_length =%llx\n",
ph->kernel_data.source_length);
- printk(KERN_INFO "SRSD length_copied =%lx\n",
+ printk(KERN_INFO "SRSD length_copied =%llx\n",
ph->kernel_data.length_copied);
#endif
}
@@ -367,8 +367,8 @@ static ssize_t show_release_region(struct kobject *kobj,
/* total reserved size - start of scratch area */
second_addr_range = phyp_dump_info->init_reserve_size -
phyp_dump_info->reserved_scratch_size;
- return sprintf(buf, "CPU:0x%lx-0x%lx: HPTE:0x%lx-0x%lx:"
- " DUMP:0x%lx-0x%lx, 0x%lx-0x%lx:\n",
+ return sprintf(buf, "CPU:0x%llx-0x%llx: HPTE:0x%llx-0x%llx:"
+ " DUMP:0x%llx-0x%llx, 0x%lx-0x%llx:\n",
phdr.cpu_data.destination_address,
phdr.cpu_data.length_copied,
phdr.hpte_data.destination_address,
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index f7a69021b7bf..84e058f1e1cc 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -332,7 +332,7 @@ static void xics_eoi_lpar(unsigned int virq)
lpar_xirr_info_set((0xff << 24) | irq);
}
-static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
+static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
{
unsigned int irq;
int status;
@@ -870,7 +870,7 @@ void xics_migrate_irqs_away(void)
/* Reset affinity to all cpus */
irq_desc[virq].affinity = CPU_MASK_ALL;
- desc->chip->set_affinity(virq, CPU_MASK_ALL);
+ desc->chip->set_affinity(virq, cpu_all_mask);
unlock:
spin_unlock_irqrestore(&desc->lock, flags);
}
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 5afce115ab1f..b33b28a6fe12 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y)
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o
+obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o
obj-$(CONFIG_RAPIDIO) += fsl_rio.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index d5f9ae0f1b75..9817f63723dd 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -28,65 +28,107 @@
#include <sysdev/fsl_pci.h>
#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
+static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
+ unsigned int index, const struct resource *res,
+ resource_size_t offset)
+{
+ resource_size_t pci_addr = res->start - offset;
+ resource_size_t phys_addr = res->start;
+ resource_size_t size = res->end - res->start + 1;
+ u32 flags = 0x80044000; /* enable & mem R/W */
+ unsigned int i;
+
+ pr_debug("PCI MEM resource start 0x%016llx, size 0x%016llx.\n",
+ (u64)res->start, (u64)size);
+
+ if (res->flags & IORESOURCE_PREFETCH)
+ flags |= 0x10000000; /* enable relaxed ordering */
+
+ for (i = 0; size > 0; i++) {
+ unsigned int bits = min(__ilog2(size),
+ __ffs(pci_addr | phys_addr));
+
+ if (index + i >= 5)
+ return -1;
+
+ out_be32(&pci->pow[index + i].potar, pci_addr >> 12);
+ out_be32(&pci->pow[index + i].potear, (u64)pci_addr >> 44);
+ out_be32(&pci->pow[index + i].powbar, phys_addr >> 12);
+ out_be32(&pci->pow[index + i].powar, flags | (bits - 1));
+
+ pci_addr += (resource_size_t)1U << bits;
+ phys_addr += (resource_size_t)1U << bits;
+ size -= (resource_size_t)1U << bits;
+ }
+
+ return i;
+}
+
/* atmu setup for fsl pci/pcie controller */
-void __init setup_pci_atmu(struct pci_controller *hose, struct resource *rsrc)
+static void __init setup_pci_atmu(struct pci_controller *hose,
+ struct resource *rsrc)
{
struct ccsr_pci __iomem *pci;
- int i;
+ int i, j, n;
pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
(u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+ if (!pci) {
+ dev_err(hose->parent, "Unable to map ATMU registers\n");
+ return;
+ }
- /* Disable all windows (except powar0 since its ignored) */
+ /* Disable all windows (except powar0 since it's ignored) */
for(i = 1; i < 5; i++)
out_be32(&pci->pow[i].powar, 0);
for(i = 0; i < 3; i++)
out_be32(&pci->piw[i].piwar, 0);
/* Setup outbound MEM window */
- for(i = 0; i < 3; i++)
- if (hose->mem_resources[i].flags & IORESOURCE_MEM){
- resource_size_t pci_addr_start =
- hose->mem_resources[i].start -
- hose->pci_mem_offset;
- pr_debug("PCI MEM resource start 0x%016llx, size 0x%016llx.\n",
- (u64)hose->mem_resources[i].start,
- (u64)hose->mem_resources[i].end
- - (u64)hose->mem_resources[i].start + 1);
- out_be32(&pci->pow[i+1].potar, (pci_addr_start >> 12));
- out_be32(&pci->pow[i+1].potear, 0);
- out_be32(&pci->pow[i+1].powbar,
- (hose->mem_resources[i].start >> 12));
- /* Enable, Mem R/W */
- out_be32(&pci->pow[i+1].powar, 0x80044000
- | (__ilog2(hose->mem_resources[i].end
- - hose->mem_resources[i].start + 1) - 1));
- }
+ for(i = 0, j = 1; i < 3; i++) {
+ if (!(hose->mem_resources[i].flags & IORESOURCE_MEM))
+ continue;
+
+ n = setup_one_atmu(pci, j, &hose->mem_resources[i],
+ hose->pci_mem_offset);
+
+ if (n < 0 || j >= 5) {
+ pr_err("Ran out of outbound PCI ATMUs for resource %d!\n", i);
+ hose->mem_resources[i].flags |= IORESOURCE_DISABLED;
+ } else
+ j += n;
+ }
/* Setup outbound IO window */
- if (hose->io_resource.flags & IORESOURCE_IO){
- pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, "
- "phy base 0x%016llx.\n",
- (u64)hose->io_resource.start,
- (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1,
- (u64)hose->io_base_phys);
- out_be32(&pci->pow[i+1].potar, (hose->io_resource.start >> 12));
- out_be32(&pci->pow[i+1].potear, 0);
- out_be32(&pci->pow[i+1].powbar, (hose->io_base_phys >> 12));
- /* Enable, IO R/W */
- out_be32(&pci->pow[i+1].powar, 0x80088000
- | (__ilog2(hose->io_resource.end
- - hose->io_resource.start + 1) - 1));
+ if (hose->io_resource.flags & IORESOURCE_IO) {
+ if (j >= 5) {
+ pr_err("Ran out of outbound PCI ATMUs for IO resource\n");
+ } else {
+ pr_debug("PCI IO resource start 0x%016llx, size 0x%016llx, "
+ "phy base 0x%016llx.\n",
+ (u64)hose->io_resource.start,
+ (u64)hose->io_resource.end - (u64)hose->io_resource.start + 1,
+ (u64)hose->io_base_phys);
+ out_be32(&pci->pow[j].potar, (hose->io_resource.start >> 12));
+ out_be32(&pci->pow[j].potear, 0);
+ out_be32(&pci->pow[j].powbar, (hose->io_base_phys >> 12));
+ /* Enable, IO R/W */
+ out_be32(&pci->pow[j].powar, 0x80088000
+ | (__ilog2(hose->io_resource.end
+ - hose->io_resource.start + 1) - 1));
+ }
}
/* Setup 2G inbound Memory Window @ 1 */
out_be32(&pci->piw[2].pitar, 0x00000000);
out_be32(&pci->piw[2].piwbar,0x00000000);
out_be32(&pci->piw[2].piwar, PIWAR_2G);
+
+ iounmap(pci);
}
-void __init setup_pci_cmd(struct pci_controller *hose)
+static void __init setup_pci_cmd(struct pci_controller *hose)
{
u16 cmd;
int cap_x;
@@ -130,7 +172,7 @@ static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
return ;
}
-int __init fsl_pcie_check_link(struct pci_controller *hose)
+static int __init fsl_pcie_check_link(struct pci_controller *hose)
{
u32 val;
early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 60f7f227327c..9c744e4285a0 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -5,8 +5,13 @@
#include <asm/mmu.h>
extern phys_addr_t get_immrbase(void);
+#if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
extern u32 get_brgfreq(void);
extern u32 get_baudrate(void);
+#else
+static inline u32 get_brgfreq(void) { return -1; }
+static inline u32 get_baudrate(void) { return -1; }
+#endif
extern u32 fsl_get_sys_freq(void);
struct spi_board_info;
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index c82babb70074..a35297dbac28 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -435,7 +435,7 @@ static void __init mpic_scan_ht_msi(struct mpic *mpic, u8 __iomem *devbase,
addr = addr | ((u64)readl(base + HT_MSI_ADDR_HI) << 32);
}
- printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%lx\n",
+ printk(KERN_DEBUG "mpic: - HT:%02x.%x %s MSI mapping found @ 0x%llx\n",
PCI_SLOT(devfn), PCI_FUNC(devfn),
flags & HT_MSI_FLAGS_ENABLE ? "enabled" : "disabled", addr);
@@ -806,7 +806,7 @@ static void mpic_end_ipi(unsigned int irq)
#endif /* CONFIG_SMP */
-void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
{
struct mpic *mpic = mpic_from_irq(irq);
unsigned int src = mpic_irq_to_hw(irq);
@@ -818,7 +818,7 @@ void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
} else {
cpumask_t tmp;
- cpus_and(tmp, cpumask, cpu_online_map);
+ cpumask_and(&tmp, cpumask, cpu_online_mask);
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
mpic_physmask(cpus_addr(tmp)[0]));
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 6209c62a426d..3cef2af10f42 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -36,6 +36,6 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
extern void mpic_set_vector(unsigned int virq, unsigned int vector);
-extern void mpic_set_affinity(unsigned int irq, cpumask_t cpumask);
+extern void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
#endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index 76ffbc48d4b9..41ac3dfac98e 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -22,5 +22,6 @@ config UCC
config QE_USB
bool
+ default y if USB_GADGET_FSL_QE
help
- QE USB Host Controller support
+ QE USB Controller support
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c b/arch/powerpc/sysdev/qe_lib/gpio.c
index 8e5a0bc36d0b..3485288dce31 100644
--- a/arch/powerpc/sysdev/qe_lib/gpio.c
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
@@ -24,8 +25,14 @@ struct qe_gpio_chip {
struct of_mm_gpio_chip mm_gc;
spinlock_t lock;
+ unsigned long pin_flags[QE_PIO_PINS];
+#define QE_PIN_REQUESTED 0
+
/* shadowed data register to clear/set bits safely */
u32 cpdata;
+
+ /* saved_regs used to restore dedicated functions */
+ struct qe_pio_regs saved_regs;
};
static inline struct qe_gpio_chip *
@@ -40,6 +47,12 @@ static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
struct qe_pio_regs __iomem *regs = mm_gc->regs;
qe_gc->cpdata = in_be32(&regs->cpdata);
+ qe_gc->saved_regs.cpdata = qe_gc->cpdata;
+ qe_gc->saved_regs.cpdir1 = in_be32(&regs->cpdir1);
+ qe_gc->saved_regs.cpdir2 = in_be32(&regs->cpdir2);
+ qe_gc->saved_regs.cppar1 = in_be32(&regs->cppar1);
+ qe_gc->saved_regs.cppar2 = in_be32(&regs->cppar2);
+ qe_gc->saved_regs.cpodr = in_be32(&regs->cpodr);
}
static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
@@ -103,6 +116,188 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
return 0;
}
+struct qe_pin {
+ /*
+ * The qe_gpio_chip name is unfortunate, we should change that to
+ * something like qe_pio_controller. Someday.
+ */
+ struct qe_gpio_chip *controller;
+ int num;
+};
+
+/**
+ * qe_pin_request - Request a QE pin
+ * @np: device node to get a pin from
+ * @index: index of a pin in the device tree
+ * Context: non-atomic
+ *
+ * This function return qe_pin so that you could use it with the rest of
+ * the QE Pin Multiplexing API.
+ */
+struct qe_pin *qe_pin_request(struct device_node *np, int index)
+{
+ struct qe_pin *qe_pin;
+ struct device_node *gc;
+ struct of_gpio_chip *of_gc = NULL;
+ struct of_mm_gpio_chip *mm_gc;
+ struct qe_gpio_chip *qe_gc;
+ int err;
+ int size;
+ const void *gpio_spec;
+ const u32 *gpio_cells;
+ unsigned long flags;
+
+ qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL);
+ if (!qe_pin) {
+ pr_debug("%s: can't allocate memory\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ err = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+ &gc, &gpio_spec);
+ if (err) {
+ pr_debug("%s: can't parse gpios property\n", __func__);
+ goto err0;
+ }
+
+ if (!of_device_is_compatible(gc, "fsl,mpc8323-qe-pario-bank")) {
+ pr_debug("%s: tried to get a non-qe pin\n", __func__);
+ err = -EINVAL;
+ goto err1;
+ }
+
+ of_gc = gc->data;
+ if (!of_gc) {
+ pr_debug("%s: gpio controller %s isn't registered\n",
+ np->full_name, gc->full_name);
+ err = -ENODEV;
+ goto err1;
+ }
+
+ gpio_cells = of_get_property(gc, "#gpio-cells", &size);
+ if (!gpio_cells || size != sizeof(*gpio_cells) ||
+ *gpio_cells != of_gc->gpio_cells) {
+ pr_debug("%s: wrong #gpio-cells for %s\n",
+ np->full_name, gc->full_name);
+ err = -EINVAL;
+ goto err1;
+ }
+
+ err = of_gc->xlate(of_gc, np, gpio_spec, NULL);
+ if (err < 0)
+ goto err1;
+
+ mm_gc = to_of_mm_gpio_chip(&of_gc->gc);
+ qe_gc = to_qe_gpio_chip(mm_gc);
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) {
+ qe_pin->controller = qe_gc;
+ qe_pin->num = err;
+ err = 0;
+ } else {
+ err = -EBUSY;
+ }
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ if (!err)
+ return qe_pin;
+err1:
+ of_node_put(gc);
+err0:
+ kfree(qe_pin);
+ pr_debug("%s failed with status %d\n", __func__, err);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(qe_pin_request);
+
+/**
+ * qe_pin_free - Free a pin
+ * @qe_pin: pointer to the qe_pin structure
+ * Context: any
+ *
+ * This function frees the qe_pin structure and makes a pin available
+ * for further qe_pin_request() calls.
+ */
+void qe_pin_free(struct qe_pin *qe_pin)
+{
+ struct qe_gpio_chip *qe_gc = qe_pin->controller;
+ unsigned long flags;
+ const int pin = qe_pin->num;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+ test_and_clear_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[pin]);
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+
+ kfree(qe_pin);
+}
+EXPORT_SYMBOL(qe_pin_free);
+
+/**
+ * qe_pin_set_dedicated - Revert a pin to a dedicated peripheral function mode
+ * @qe_pin: pointer to the qe_pin structure
+ * Context: any
+ *
+ * This function resets a pin to a dedicated peripheral function that
+ * has been set up by the firmware.
+ */
+void qe_pin_set_dedicated(struct qe_pin *qe_pin)
+{
+ struct qe_gpio_chip *qe_gc = qe_pin->controller;
+ struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs;
+ struct qe_pio_regs *sregs = &qe_gc->saved_regs;
+ int pin = qe_pin->num;
+ u32 mask1 = 1 << (QE_PIO_PINS - (pin + 1));
+ u32 mask2 = 0x3 << (QE_PIO_PINS - (pin % (QE_PIO_PINS / 2) + 1) * 2);
+ bool second_reg = pin > (QE_PIO_PINS / 2) - 1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ if (second_reg) {
+ clrsetbits_be32(&regs->cpdir2, mask2, sregs->cpdir2 & mask2);
+ clrsetbits_be32(&regs->cppar2, mask2, sregs->cppar2 & mask2);
+ } else {
+ clrsetbits_be32(&regs->cpdir1, mask2, sregs->cpdir1 & mask2);
+ clrsetbits_be32(&regs->cppar1, mask2, sregs->cppar1 & mask2);
+ }
+
+ if (sregs->cpdata & mask1)
+ qe_gc->cpdata |= mask1;
+ else
+ qe_gc->cpdata &= ~mask1;
+
+ out_be32(&regs->cpdata, qe_gc->cpdata);
+ clrsetbits_be32(&regs->cpodr, mask1, sregs->cpodr & mask1);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+EXPORT_SYMBOL(qe_pin_set_dedicated);
+
+/**
+ * qe_pin_set_gpio - Set a pin to the GPIO mode
+ * @qe_pin: pointer to the qe_pin structure
+ * Context: any
+ *
+ * This function sets a pin to the GPIO mode.
+ */
+void qe_pin_set_gpio(struct qe_pin *qe_pin)
+{
+ struct qe_gpio_chip *qe_gc = qe_pin->controller;
+ struct qe_pio_regs __iomem *regs = qe_gc->mm_gc.regs;
+ unsigned long flags;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ /* Let's make it input by default, GPIO API is able to change that. */
+ __par_io_config_pin(regs, qe_pin->num, QE_PIO_DIR_IN, 0, 0, 0);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+EXPORT_SYMBOL(qe_pin_set_gpio);
+
static int __init qe_add_gpiochips(void)
{
struct device_node *np;
diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c
new file mode 100644
index 000000000000..43c4569e24b7
--- /dev/null
+++ b/arch/powerpc/sysdev/simple_gpio.c
@@ -0,0 +1,155 @@
+/*
+ * Simple Memory-Mapped GPIOs
+ *
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <asm/prom.h>
+#include "simple_gpio.h"
+
+struct u8_gpio_chip {
+ struct of_mm_gpio_chip mm_gc;
+ spinlock_t lock;
+
+ /* shadowed data register to clear/set bits safely */
+ u8 data;
+};
+
+static struct u8_gpio_chip *to_u8_gpio_chip(struct of_mm_gpio_chip *mm_gc)
+{
+ return container_of(mm_gc, struct u8_gpio_chip, mm_gc);
+}
+
+static u8 u8_pin2mask(unsigned int pin)
+{
+ return 1 << (8 - 1 - pin);
+}
+
+static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+
+ return in_8(mm_gc->regs) & u8_pin2mask(gpio);
+}
+
+static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&u8_gc->lock, flags);
+
+ if (val)
+ u8_gc->data |= u8_pin2mask(gpio);
+ else
+ u8_gc->data &= ~u8_pin2mask(gpio);
+
+ out_8(mm_gc->regs, u8_gc->data);
+
+ spin_unlock_irqrestore(&u8_gc->lock, flags);
+}
+
+static int u8_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+ return 0;
+}
+
+static int u8_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ u8_gpio_set(gc, gpio, val);
+ return 0;
+}
+
+static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+ struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc);
+
+ u8_gc->data = in_8(mm_gc->regs);
+}
+
+static int __init u8_simple_gpiochip_add(struct device_node *np)
+{
+ int ret;
+ struct u8_gpio_chip *u8_gc;
+ struct of_mm_gpio_chip *mm_gc;
+ struct of_gpio_chip *of_gc;
+ struct gpio_chip *gc;
+
+ u8_gc = kzalloc(sizeof(*u8_gc), GFP_KERNEL);
+ if (!u8_gc)
+ return -ENOMEM;
+
+ spin_lock_init(&u8_gc->lock);
+
+ mm_gc = &u8_gc->mm_gc;
+ of_gc = &mm_gc->of_gc;
+ gc = &of_gc->gc;
+
+ mm_gc->save_regs = u8_gpio_save_regs;
+ of_gc->gpio_cells = 2;
+ gc->ngpio = 8;
+ gc->direction_input = u8_gpio_dir_in;
+ gc->direction_output = u8_gpio_dir_out;
+ gc->get = u8_gpio_get;
+ gc->set = u8_gpio_set;
+
+ ret = of_mm_gpiochip_add(np, mm_gc);
+ if (ret)
+ goto err;
+ return 0;
+err:
+ kfree(u8_gc);
+ return ret;
+}
+
+void __init simple_gpiochip_init(const char *compatible)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, compatible) {
+ int ret;
+ struct resource r;
+
+ ret = of_address_to_resource(np, 0, &r);
+ if (ret)
+ goto err;
+
+ switch (resource_size(&r)) {
+ case 1:
+ ret = u8_simple_gpiochip_add(np);
+ if (ret)
+ goto err;
+ break;
+ default:
+ /*
+ * Whenever you need support for GPIO bank width > 1,
+ * please just turn u8_ code into huge macros, and
+ * construct needed uX_ code with it.
+ */
+ ret = -ENOSYS;
+ goto err;
+ }
+ continue;
+err:
+ pr_err("%s: registration failed, status %d\n",
+ np->full_name, ret);
+ }
+}
diff --git a/arch/powerpc/sysdev/simple_gpio.h b/arch/powerpc/sysdev/simple_gpio.h
new file mode 100644
index 000000000000..3a7b0c513c76
--- /dev/null
+++ b/arch/powerpc/sysdev/simple_gpio.h
@@ -0,0 +1,12 @@
+#ifndef __SYSDEV_SIMPLE_GPIO_H
+#define __SYSDEV_SIMPLE_GPIO_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_SIMPLE_GPIO
+extern void simple_gpiochip_init(const char *compatible);
+#else
+static inline void simple_gpiochip_init(const char *compatible) {}
+#endif /* CONFIG_SIMPLE_GPIO */
+
+#endif /* __SYSDEV_SIMPLE_GPIO_H */
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 8152fefc97b9..6b0a3538dc63 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -77,12 +77,14 @@ mainmenu "Linux Kernel Configuration"
config S390
def_bool y
select USE_GENERIC_SMP_HELPERS if SMP
+ select HAVE_SYSCALL_WRAPPERS
select HAVE_FUNCTION_TRACER
select HAVE_OPROFILE
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_KVM if 64BIT
select HAVE_ARCH_TRACEHOOK
+ select INIT_ALL_POSSIBLE
source "init/Kconfig"
@@ -298,7 +300,7 @@ config WARN_STACK
This option enables the compiler options -mwarn-framesize and
-mwarn-dynamicstack. If the compiler supports these options it
will generate warnings for function which either use alloca or
- create a stack frame bigger then CONFIG_WARN_STACK_SIZE.
+ create a stack frame bigger than CONFIG_WARN_STACK_SIZE.
Say N if you are unsure.
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 9d4f8e6c0800..5a805df216bb 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -106,7 +106,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
ret->i_mode = mode;
ret->i_uid = hypfs_info->uid;
ret->i_gid = hypfs_info->gid;
- ret->i_blocks = 0;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
if (mode & S_IFDIR)
ret->i_nlink = 2;
diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h
index 2d184655bc5d..de432f2de2d2 100644
--- a/arch/s390/include/asm/atomic.h
+++ b/arch/s390/include/asm/atomic.h
@@ -2,6 +2,7 @@
#define __ARCH_S390_ATOMIC__
#include <linux/compiler.h>
+#include <linux/types.h>
/*
* include/asm-s390/atomic.h
@@ -23,9 +24,6 @@
* S390 uses 'Compare And Swap' for atomicity in SMP enviroment
*/
-typedef struct {
- int counter;
-} __attribute__ ((aligned (4))) atomic_t;
#define ATOMIC_INIT(i) { (i) }
#ifdef __KERNEL__
@@ -149,9 +147,6 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#undef __CS_LOOP
#ifdef __s390x__
-typedef struct {
- long long counter;
-} __attribute__ ((aligned (8))) atomic64_t;
#define ATOMIC64_INIT(i) { (i) }
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
diff --git a/arch/s390/include/asm/byteorder.h b/arch/s390/include/asm/byteorder.h
index 8bcf277c8468..a332e59e26fc 100644
--- a/arch/s390/include/asm/byteorder.h
+++ b/arch/s390/include/asm/byteorder.h
@@ -1,95 +1,6 @@
#ifndef _S390_BYTEORDER_H
#define _S390_BYTEORDER_H
-/*
- * include/asm-s390/byteorder.h
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- */
-
-#include <asm/types.h>
-
-#define __BIG_ENDIAN
-
-#ifndef __s390x__
-# define __SWAB_64_THRU_32__
-#endif
-
-#ifdef __s390x__
-static inline __u64 __arch_swab64p(const __u64 *x)
-{
- __u64 result;
-
- asm volatile("lrvg %0,%1" : "=d" (result) : "m" (*x));
- return result;
-}
-#define __arch_swab64p __arch_swab64p
-
-static inline __u64 __arch_swab64(__u64 x)
-{
- __u64 result;
-
- asm volatile("lrvgr %0,%1" : "=d" (result) : "d" (x));
- return result;
-}
-#define __arch_swab64 __arch_swab64
-
-static inline void __arch_swab64s(__u64 *x)
-{
- *x = __arch_swab64p(x);
-}
-#define __arch_swab64s __arch_swab64s
-#endif /* __s390x__ */
-
-static inline __u32 __arch_swab32p(const __u32 *x)
-{
- __u32 result;
-
- asm volatile(
-#ifndef __s390x__
- " icm %0,8,3(%1)\n"
- " icm %0,4,2(%1)\n"
- " icm %0,2,1(%1)\n"
- " ic %0,0(%1)"
- : "=&d" (result) : "a" (x), "m" (*x) : "cc");
-#else /* __s390x__ */
- " lrv %0,%1"
- : "=d" (result) : "m" (*x));
-#endif /* __s390x__ */
- return result;
-}
-#define __arch_swab32p __arch_swab32p
-
-#ifdef __s390x__
-static inline __u32 __arch_swab32(__u32 x)
-{
- __u32 result;
-
- asm volatile("lrvr %0,%1" : "=d" (result) : "d" (x));
- return result;
-}
-#define __arch_swab32 __arch_swab32
-#endif /* __s390x__ */
-
-static inline __u16 __arch_swab16p(const __u16 *x)
-{
- __u16 result;
-
- asm volatile(
-#ifndef __s390x__
- " icm %0,2,1(%1)\n"
- " ic %0,0(%1)\n"
- : "=&d" (result) : "a" (x), "m" (*x) : "cc");
-#else /* __s390x__ */
- " lrvh %0,%1"
- : "=d" (result) : "m" (*x));
-#endif /* __s390x__ */
- return result;
-}
-#define __arch_swab16p __arch_swab16p
-
-#include <linux/byteorder.h>
+#include <linux/byteorder/big_endian.h>
#endif /* _S390_BYTEORDER_H */
diff --git a/arch/s390/include/asm/chpid.h b/arch/s390/include/asm/chpid.h
index dfe3c7f3439a..fc71d8a6709b 100644
--- a/arch/s390/include/asm/chpid.h
+++ b/arch/s390/include/asm/chpid.h
@@ -9,7 +9,7 @@
#define _ASM_S390_CHPID_H _ASM_S390_CHPID_H
#include <linux/string.h>
-#include <asm/types.h>
+#include <linux/types.h>
#define __MAX_CHPID 255
diff --git a/arch/s390/include/asm/chsc.h b/arch/s390/include/asm/chsc.h
index d38d0cf62d4b..807997f7414b 100644
--- a/arch/s390/include/asm/chsc.h
+++ b/arch/s390/include/asm/chsc.h
@@ -8,6 +8,7 @@
#ifndef _ASM_CHSC_H
#define _ASM_CHSC_H
+#include <linux/types.h>
#include <asm/chpid.h>
#include <asm/schid.h>
diff --git a/arch/s390/include/asm/cmb.h b/arch/s390/include/asm/cmb.h
index 50196857d27a..39ae03294794 100644
--- a/arch/s390/include/asm/cmb.h
+++ b/arch/s390/include/asm/cmb.h
@@ -1,5 +1,8 @@
#ifndef S390_CMB_H
#define S390_CMB_H
+
+#include <linux/types.h>
+
/**
* struct cmbdata - channel measurement block data for user space
* @size: size of the stored data
diff --git a/arch/s390/include/asm/cpu.h b/arch/s390/include/asm/cpu.h
index e5a6a9ba3adf..d60a2eefb17b 100644
--- a/arch/s390/include/asm/cpu.h
+++ b/arch/s390/include/asm/cpu.h
@@ -14,7 +14,6 @@
struct s390_idle_data {
spinlock_t lock;
- unsigned int in_idle;
unsigned long long idle_count;
unsigned long long idle_enter;
unsigned long long idle_time;
@@ -22,12 +21,12 @@ struct s390_idle_data {
DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
-void s390_idle_leave(void);
+void vtime_start_cpu(void);
static inline void s390_idle_check(void)
{
- if ((&__get_cpu_var(s390_idle))->in_idle)
- s390_idle_leave();
+ if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL)
+ vtime_start_cpu();
}
#endif /* _ASM_S390_CPU_H_ */
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 133ce054fc89..521726430afa 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -11,7 +11,7 @@
#include <asm/div64.h>
-/* We want to use micro-second resolution. */
+/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */
typedef unsigned long long cputime_t;
typedef unsigned long long cputime64_t;
@@ -53,9 +53,9 @@ __div(unsigned long long n, unsigned int base)
#define cputime_ge(__a, __b) ((__a) >= (__b))
#define cputime_lt(__a, __b) ((__a) < (__b))
#define cputime_le(__a, __b) ((__a) <= (__b))
-#define cputime_to_jiffies(__ct) (__div((__ct), 1000000 / HZ))
+#define cputime_to_jiffies(__ct) (__div((__ct), 4096000000ULL / HZ))
#define cputime_to_scaled(__ct) (__ct)
-#define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (1000000 / HZ))
+#define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (4096000000ULL / HZ))
#define cputime64_zero (0ULL)
#define cputime64_add(__a, __b) ((__a) + (__b))
@@ -64,7 +64,7 @@ __div(unsigned long long n, unsigned int base)
static inline u64
cputime64_to_jiffies64(cputime64_t cputime)
{
- do_div(cputime, 1000000 / HZ);
+ do_div(cputime, 4096000000ULL / HZ);
return cputime;
}
@@ -74,13 +74,13 @@ cputime64_to_jiffies64(cputime64_t cputime)
static inline unsigned int
cputime_to_msecs(const cputime_t cputime)
{
- return __div(cputime, 1000);
+ return __div(cputime, 4096000);
}
static inline cputime_t
msecs_to_cputime(const unsigned int m)
{
- return (cputime_t) m * 1000;
+ return (cputime_t) m * 4096000;
}
/*
@@ -89,13 +89,13 @@ msecs_to_cputime(const unsigned int m)
static inline unsigned int
cputime_to_secs(const cputime_t cputime)
{
- return __div(cputime, 1000000);
+ return __div(cputime, 2048000000) >> 1;
}
static inline cputime_t
secs_to_cputime(const unsigned int s)
{
- return (cputime_t) s * 1000000;
+ return (cputime_t) s * 4096000000ULL;
}
/*
@@ -104,7 +104,7 @@ secs_to_cputime(const unsigned int s)
static inline cputime_t
timespec_to_cputime(const struct timespec *value)
{
- return value->tv_nsec / 1000 + (u64) value->tv_sec * 1000000;
+ return value->tv_nsec * 4096 / 1000 + (u64) value->tv_sec * 4096000000ULL;
}
static inline void
@@ -114,12 +114,12 @@ cputime_to_timespec(const cputime_t cputime, struct timespec *value)
register_pair rp;
rp.pair = cputime >> 1;
- asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
- value->tv_nsec = rp.subreg.even * 1000;
+ asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));
+ value->tv_nsec = rp.subreg.even * 1000 / 4096;
value->tv_sec = rp.subreg.odd;
#else
- value->tv_nsec = (cputime % 1000000) * 1000;
- value->tv_sec = cputime / 1000000;
+ value->tv_nsec = (cputime % 4096000000ULL) * 1000 / 4096;
+ value->tv_sec = cputime / 4096000000ULL;
#endif
}
@@ -131,7 +131,7 @@ cputime_to_timespec(const cputime_t cputime, struct timespec *value)
static inline cputime_t
timeval_to_cputime(const struct timeval *value)
{
- return value->tv_usec + (u64) value->tv_sec * 1000000;
+ return value->tv_usec * 4096 + (u64) value->tv_sec * 4096000000ULL;
}
static inline void
@@ -141,12 +141,12 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
register_pair rp;
rp.pair = cputime >> 1;
- asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1));
- value->tv_usec = rp.subreg.even;
+ asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));
+ value->tv_usec = rp.subreg.even / 4096;
value->tv_sec = rp.subreg.odd;
#else
- value->tv_usec = cputime % 1000000;
- value->tv_sec = cputime / 1000000;
+ value->tv_usec = cputime % 4096000000ULL;
+ value->tv_sec = cputime / 4096000000ULL;
#endif
}
@@ -156,13 +156,13 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
static inline clock_t
cputime_to_clock_t(cputime_t cputime)
{
- return __div(cputime, 1000000 / USER_HZ);
+ return __div(cputime, 4096000000ULL / USER_HZ);
}
static inline cputime_t
clock_t_to_cputime(unsigned long x)
{
- return (cputime_t) x * (1000000 / USER_HZ);
+ return (cputime_t) x * (4096000000ULL / USER_HZ);
}
/*
@@ -171,7 +171,7 @@ clock_t_to_cputime(unsigned long x)
static inline clock_t
cputime64_to_clock_t(cputime64_t cputime)
{
- return __div(cputime, 1000000 / USER_HZ);
+ return __div(cputime, 4096000000ULL / USER_HZ);
}
#endif /* _S390_CPUTIME_H */
diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/asm/dasd.h
index 55b2b80cdf6e..e2db6f16d9c8 100644
--- a/arch/s390/include/asm/dasd.h
+++ b/arch/s390/include/asm/dasd.h
@@ -14,6 +14,7 @@
#ifndef DASD_H
#define DASD_H
+#include <linux/types.h>
#include <linux/ioctl.h>
#define DASD_IOCTL_LETTER 'D'
@@ -78,6 +79,7 @@ typedef struct dasd_information2_t {
#define DASD_FEATURE_USEDIAG 0x02
#define DASD_FEATURE_INITIAL_ONLINE 0x04
#define DASD_FEATURE_ERPLOG 0x08
+#define DASD_FEATURE_FAILFAST 0x10
#define DASD_PARTN_BITS 2
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index d480f39d65e6..74d0bbb7d955 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -172,14 +172,14 @@ extern char elf_platform[];
#ifndef __s390x__
#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
#else /* __s390x__ */
-#define SET_PERSONALITY(ex) \
-do { \
- if (current->personality != PER_LINUX32) \
- set_personality(PER_LINUX); \
- if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
- set_thread_flag(TIF_31BIT); \
- else \
- clear_thread_flag(TIF_31BIT); \
+#define SET_PERSONALITY(ex) \
+do { \
+ if (personality(current->personality) != PER_LINUX32) \
+ set_personality(PER_LINUX); \
+ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+ set_thread_flag(TIF_31BIT); \
+ else \
+ clear_thread_flag(TIF_31BIT); \
} while (0)
#endif /* __s390x__ */
diff --git a/arch/s390/include/asm/kvm.h b/arch/s390/include/asm/kvm.h
index d74002f95794..e1f54654e3ae 100644
--- a/arch/s390/include/asm/kvm.h
+++ b/arch/s390/include/asm/kvm.h
@@ -13,7 +13,7 @@
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Christian Borntraeger <borntraeger@de.ibm.com>
*/
-#include <asm/types.h>
+#include <linux/types.h>
/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
struct kvm_pic_state {
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 0bc51d52a899..ffdef5fe8587 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -67,11 +67,11 @@
#define __LC_SYNC_ENTER_TIMER 0x248
#define __LC_ASYNC_ENTER_TIMER 0x250
#define __LC_EXIT_TIMER 0x258
-#define __LC_LAST_UPDATE_TIMER 0x260
-#define __LC_USER_TIMER 0x268
-#define __LC_SYSTEM_TIMER 0x270
-#define __LC_LAST_UPDATE_CLOCK 0x278
-#define __LC_STEAL_CLOCK 0x280
+#define __LC_USER_TIMER 0x260
+#define __LC_SYSTEM_TIMER 0x268
+#define __LC_STEAL_TIMER 0x270
+#define __LC_LAST_UPDATE_TIMER 0x278
+#define __LC_LAST_UPDATE_CLOCK 0x280
#define __LC_RETURN_MCCK_PSW 0x288
#define __LC_KERNEL_STACK 0xC40
#define __LC_THREAD_INFO 0xC44
@@ -89,11 +89,11 @@
#define __LC_SYNC_ENTER_TIMER 0x250
#define __LC_ASYNC_ENTER_TIMER 0x258
#define __LC_EXIT_TIMER 0x260
-#define __LC_LAST_UPDATE_TIMER 0x268
-#define __LC_USER_TIMER 0x270
-#define __LC_SYSTEM_TIMER 0x278
-#define __LC_LAST_UPDATE_CLOCK 0x280
-#define __LC_STEAL_CLOCK 0x288
+#define __LC_USER_TIMER 0x268
+#define __LC_SYSTEM_TIMER 0x270
+#define __LC_STEAL_TIMER 0x278
+#define __LC_LAST_UPDATE_TIMER 0x280
+#define __LC_LAST_UPDATE_CLOCK 0x288
#define __LC_RETURN_MCCK_PSW 0x290
#define __LC_KERNEL_STACK 0xD40
#define __LC_THREAD_INFO 0xD48
@@ -106,8 +106,10 @@
#define __LC_IPLDEV 0xDB8
#define __LC_CURRENT 0xDD8
#define __LC_INT_CLOCK 0xDE8
+#define __LC_VDSO_PER_CPU 0xE38
#endif /* __s390x__ */
+#define __LC_PASTE 0xE40
#define __LC_PANIC_MAGIC 0xE00
#ifndef __s390x__
@@ -252,11 +254,11 @@ struct _lowcore
__u64 sync_enter_timer; /* 0x248 */
__u64 async_enter_timer; /* 0x250 */
__u64 exit_timer; /* 0x258 */
- __u64 last_update_timer; /* 0x260 */
- __u64 user_timer; /* 0x268 */
- __u64 system_timer; /* 0x270 */
- __u64 last_update_clock; /* 0x278 */
- __u64 steal_clock; /* 0x280 */
+ __u64 user_timer; /* 0x260 */
+ __u64 system_timer; /* 0x268 */
+ __u64 steal_timer; /* 0x270 */
+ __u64 last_update_timer; /* 0x278 */
+ __u64 last_update_clock; /* 0x280 */
psw_t return_mcck_psw; /* 0x288 */
__u8 pad8[0xc00-0x290]; /* 0x290 */
@@ -343,11 +345,11 @@ struct _lowcore
__u64 sync_enter_timer; /* 0x250 */
__u64 async_enter_timer; /* 0x258 */
__u64 exit_timer; /* 0x260 */
- __u64 last_update_timer; /* 0x268 */
- __u64 user_timer; /* 0x270 */
- __u64 system_timer; /* 0x278 */
- __u64 last_update_clock; /* 0x280 */
- __u64 steal_clock; /* 0x288 */
+ __u64 user_timer; /* 0x268 */
+ __u64 system_timer; /* 0x270 */
+ __u64 steal_timer; /* 0x278 */
+ __u64 last_update_timer; /* 0x280 */
+ __u64 last_update_clock; /* 0x288 */
psw_t return_mcck_psw; /* 0x290 */
__u8 pad8[0xc00-0x2a0]; /* 0x2a0 */
/* System info area */
@@ -381,7 +383,12 @@ struct _lowcore
/* whether the kernel died with panic() or not */
__u32 panic_magic; /* 0xe00 */
- __u8 pad13[0x11b8-0xe04]; /* 0xe04 */
+ /* Per cpu primary space access list */
+ __u8 pad_0xe04[0xe3c-0xe04]; /* 0xe04 */
+ __u32 vdso_per_cpu_data; /* 0xe3c */
+ __u32 paste[16]; /* 0xe40 */
+
+ __u8 pad13[0x11b8-0xe80]; /* 0xe80 */
/* 64 bit extparam used for pfault, diag 250 etc */
__u64 ext_params2; /* 0x11B8 */
diff --git a/arch/s390/include/asm/posix_types.h b/arch/s390/include/asm/posix_types.h
index 397d93fba3a7..8cc113f92523 100644
--- a/arch/s390/include/asm/posix_types.h
+++ b/arch/s390/include/asm/posix_types.h
@@ -68,11 +68,7 @@ typedef unsigned short __kernel_old_dev_t;
#endif /* __s390x__ */
typedef struct {
-#if defined(__KERNEL__) || defined(__USE_ALL)
int val[2];
-#else /* !defined(__KERNEL__) && !defined(__USE_ALL)*/
- int __val[2];
-#endif /* !defined(__KERNEL__) && !defined(__USE_ALL)*/
} __kernel_fsid_t;
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 5396f9f12263..8920025c3c02 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -272,12 +272,15 @@ typedef struct
#define PSW_ASC_SECONDARY 0x0000800000000000UL
#define PSW_ASC_HOME 0x0000C00000000000UL
-extern long psw_user32_bits;
-
#endif /* __s390x__ */
+#ifdef __KERNEL__
extern long psw_kernel_bits;
extern long psw_user_bits;
+#ifdef CONFIG_64BIT
+extern long psw_user32_bits;
+#endif
+#endif
/* This macro merges a NEW PSW mask specified by the user into
the currently active PSW mask CURRENT, modifying only those
diff --git a/arch/s390/include/asm/qeth.h b/arch/s390/include/asm/qeth.h
index 930d378ef75a..06cbd1e8c943 100644
--- a/arch/s390/include/asm/qeth.h
+++ b/arch/s390/include/asm/qeth.h
@@ -10,6 +10,7 @@
*/
#ifndef __ASM_S390_QETH_IOCTL_H__
#define __ASM_S390_QETH_IOCTL_H__
+#include <linux/types.h>
#include <linux/ioctl.h>
#define SIOC_QETH_ARP_SET_NO_ENTRIES (SIOCDEVPRIVATE)
diff --git a/arch/s390/include/asm/s390_rdev.h b/arch/s390/include/asm/s390_rdev.h
deleted file mode 100644
index 6fa20442a48c..000000000000
--- a/arch/s390/include/asm/s390_rdev.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * include/asm-s390/ccwdev.h
- *
- * Copyright (C) 2002,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
- * Carsten Otte <cotte@de.ibm.com>
- *
- * Interface for s390 root device
- */
-
-#ifndef _S390_RDEV_H_
-#define _S390_RDEV_H_
-extern struct device *s390_root_dev_register(const char *);
-extern void s390_root_dev_unregister(struct device *);
-#endif /* _S390_RDEV_H_ */
diff --git a/arch/s390/include/asm/schid.h b/arch/s390/include/asm/schid.h
index 825503cf3dc2..3e4d401b4e45 100644
--- a/arch/s390/include/asm/schid.h
+++ b/arch/s390/include/asm/schid.h
@@ -1,6 +1,8 @@
#ifndef ASM_SCHID_H
#define ASM_SCHID_H
+#include <linux/types.h>
+
struct subchannel_id {
__u32 cssid : 8;
__u32 : 4;
diff --git a/arch/s390/include/asm/swab.h b/arch/s390/include/asm/swab.h
new file mode 100644
index 000000000000..eb18dc1f327b
--- /dev/null
+++ b/arch/s390/include/asm/swab.h
@@ -0,0 +1,91 @@
+#ifndef _S390_SWAB_H
+#define _S390_SWAB_H
+
+/*
+ * include/asm-s390/swab.h
+ *
+ * S390 version
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+#include <linux/types.h>
+
+#ifndef __s390x__
+# define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __s390x__
+static inline __u64 __arch_swab64p(const __u64 *x)
+{
+ __u64 result;
+
+ asm volatile("lrvg %0,%1" : "=d" (result) : "m" (*x));
+ return result;
+}
+#define __arch_swab64p __arch_swab64p
+
+static inline __u64 __arch_swab64(__u64 x)
+{
+ __u64 result;
+
+ asm volatile("lrvgr %0,%1" : "=d" (result) : "d" (x));
+ return result;
+}
+#define __arch_swab64 __arch_swab64
+
+static inline void __arch_swab64s(__u64 *x)
+{
+ *x = __arch_swab64p(x);
+}
+#define __arch_swab64s __arch_swab64s
+#endif /* __s390x__ */
+
+static inline __u32 __arch_swab32p(const __u32 *x)
+{
+ __u32 result;
+
+ asm volatile(
+#ifndef __s390x__
+ " icm %0,8,3(%1)\n"
+ " icm %0,4,2(%1)\n"
+ " icm %0,2,1(%1)\n"
+ " ic %0,0(%1)"
+ : "=&d" (result) : "a" (x), "m" (*x) : "cc");
+#else /* __s390x__ */
+ " lrv %0,%1"
+ : "=d" (result) : "m" (*x));
+#endif /* __s390x__ */
+ return result;
+}
+#define __arch_swab32p __arch_swab32p
+
+#ifdef __s390x__
+static inline __u32 __arch_swab32(__u32 x)
+{
+ __u32 result;
+
+ asm volatile("lrvr %0,%1" : "=d" (result) : "d" (x));
+ return result;
+}
+#define __arch_swab32 __arch_swab32
+#endif /* __s390x__ */
+
+static inline __u16 __arch_swab16p(const __u16 *x)
+{
+ __u16 result;
+
+ asm volatile(
+#ifndef __s390x__
+ " icm %0,2,1(%1)\n"
+ " ic %0,0(%1)\n"
+ : "=&d" (result) : "a" (x), "m" (*x) : "cc");
+#else /* __s390x__ */
+ " lrvh %0,%1"
+ : "=d" (result) : "m" (*x));
+#endif /* __s390x__ */
+ return result;
+}
+#define __arch_swab16p __arch_swab16p
+
+#endif /* _S390_SWAB_H */
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h
index 024ef42ed6d7..3a8b26eb1f2e 100644
--- a/arch/s390/include/asm/system.h
+++ b/arch/s390/include/asm/system.h
@@ -99,7 +99,7 @@ static inline void restore_access_regs(unsigned int *acrs)
prev = __switch_to(prev,next); \
} while (0)
-extern void account_vtime(struct task_struct *);
+extern void account_vtime(struct task_struct *, struct task_struct *);
extern void account_tick_vtime(struct task_struct *);
extern void account_system_vtime(struct task_struct *);
@@ -121,7 +121,7 @@ static inline void cmma_init(void) { }
#define finish_arch_switch(prev) do { \
set_fs(current->thread.mm_segment); \
- account_vtime(prev); \
+ account_vtime(prev, current); \
} while (0)
#define nop() asm volatile("nop")
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index c1eaf9604da7..c544aa524535 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -47,6 +47,8 @@ struct thread_info {
unsigned int cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
+ __u64 user_timer;
+ __u64 system_timer;
};
/*
diff --git a/arch/s390/include/asm/timer.h b/arch/s390/include/asm/timer.h
index 61705d60f995..e4bcab739c19 100644
--- a/arch/s390/include/asm/timer.h
+++ b/arch/s390/include/asm/timer.h
@@ -23,20 +23,18 @@ struct vtimer_list {
__u64 expires;
__u64 interval;
- spinlock_t lock;
- unsigned long magic;
-
void (*function)(unsigned long);
unsigned long data;
};
-/* the offset value will wrap after ca. 71 years */
+/* the vtimer value will wrap after ca. 71 years */
struct vtimer_queue {
struct list_head list;
spinlock_t lock;
- __u64 to_expire; /* current event expire time */
- __u64 offset; /* list offset to zero */
- __u64 idle; /* temp var for idle */
+ __u64 timer; /* last programmed timer */
+ __u64 elapsed; /* elapsed time of timer expire values */
+ __u64 idle; /* temp var for idle */
+ int do_spt; /* =1: reprogram cpu timer in idle */
};
extern void init_virt_timer(struct vtimer_list *timer);
@@ -48,8 +46,8 @@ extern int del_virt_timer(struct vtimer_list *timer);
extern void init_cpu_vtimer(void);
extern void vtime_init(void);
-extern void vtime_start_cpu_timer(void);
-extern void vtime_stop_cpu_timer(void);
+extern void vtime_stop_cpu(void);
+extern void vtime_start_leave(void);
#endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index d96c91643458..c93eb50e1d09 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -6,10 +6,12 @@
#define mc_capable() (1)
cpumask_t cpu_coregroup_map(unsigned int cpu);
+const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
extern cpumask_t cpu_core_map[NR_CPUS];
#define topology_core_siblings(cpu) (cpu_core_map[cpu])
+#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
int topology_set_cpu_management(int fc);
void topology_schedule_update(void);
diff --git a/arch/s390/include/asm/types.h b/arch/s390/include/asm/types.h
index 41c547656130..3dc3fc228812 100644
--- a/arch/s390/include/asm/types.h
+++ b/arch/s390/include/asm/types.h
@@ -9,11 +9,7 @@
#ifndef _S390_TYPES_H
#define _S390_TYPES_H
-#ifndef __s390x__
-# include <asm-generic/int-ll64.h>
-#else
-# include <asm-generic/int-l64.h>
-#endif
+#include <asm-generic/int-ll64.h>
#ifndef __ASSEMBLY__
diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h
index a44f4fe16a35..7bdd7c8ebc91 100644
--- a/arch/s390/include/asm/vdso.h
+++ b/arch/s390/include/asm/vdso.h
@@ -12,9 +12,9 @@
#ifndef __ASSEMBLY__
/*
- * Note about this structure:
+ * Note about the vdso_data and vdso_per_cpu_data structures:
*
- * NEVER USE THIS IN USERSPACE CODE DIRECTLY. The layout of this
+ * NEVER USE THEM IN USERSPACE CODE DIRECTLY. The layout of the
* structure is supposed to be known only to the function in the vdso
* itself and may change without notice.
*/
@@ -28,10 +28,21 @@ struct vdso_data {
__u64 wtom_clock_nsec; /* 0x28 */
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */
__u32 tz_dsttime; /* Type of dst correction 0x34 */
+ __u32 ectg_available;
+};
+
+struct vdso_per_cpu_data {
+ __u64 ectg_timer_base;
+ __u64 ectg_user_time;
};
extern struct vdso_data *vdso_data;
+#ifdef CONFIG_64BIT
+int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore);
+void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore);
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index e641f60bac99..67a60016babb 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -48,6 +48,11 @@ int main(void)
DEFINE(__VDSO_WTOM_SEC, offsetof(struct vdso_data, wtom_clock_sec));
DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
+ DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
+ DEFINE(__VDSO_ECTG_BASE,
+ offsetof(struct vdso_per_cpu_data, ectg_timer_base));
+ DEFINE(__VDSO_ECTG_USER,
+ offsetof(struct vdso_per_cpu_data, ectg_user_time));
/* constants used by the vdso */
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index fc2c97197a53..62c706eb0de6 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -547,7 +547,7 @@ sys32_setdomainname_wrapper:
.globl sys32_newuname_wrapper
sys32_newuname_wrapper:
llgtr %r2,%r2 # struct new_utsname *
- jg s390x_newuname # branch to system call
+ jg sys_s390_newuname # branch to system call
.globl compat_sys_adjtimex_wrapper
compat_sys_adjtimex_wrapper:
@@ -615,7 +615,7 @@ sys32_sysfs_wrapper:
.globl sys32_personality_wrapper
sys32_personality_wrapper:
llgfr %r2,%r2 # unsigned long
- jg s390x_personality # branch to system call
+ jg sys_s390_personality # branch to system call
.globl sys32_setfsuid16_wrapper
sys32_setfsuid16_wrapper:
@@ -1767,3 +1767,41 @@ sys_dup3_wrapper:
sys_epoll_create1_wrapper:
lgfr %r2,%r2 # int
jg sys_epoll_create1 # branch to system call
+
+ .globl sys32_readahead_wrapper
+sys32_readahead_wrapper:
+ lgfr %r2,%r2 # int
+ llgfr %r3,%r3 # u32
+ llgfr %r4,%r4 # u32
+ lgfr %r5,%r5 # s32
+ jg sys32_readahead # branch to system call
+
+ .globl sys32_sendfile64_wrapper
+sys32_sendfile64_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # int
+ llgtr %r4,%r4 # compat_loff_t *
+ lgfr %r5,%r5 # s32
+ jg sys32_sendfile64 # branch to system call
+
+ .globl sys_tkill_wrapper
+sys_tkill_wrapper:
+ lgfr %r2,%r2 # pid_t
+ lgfr %r3,%r3 # int
+ jg sys_tkill # branch to system call
+
+ .globl sys_tgkill_wrapper
+sys_tgkill_wrapper:
+ lgfr %r2,%r2 # pid_t
+ lgfr %r3,%r3 # pid_t
+ lgfr %r4,%r4 # int
+ jg sys_tgkill # branch to system call
+
+ .globl compat_sys_keyctl_wrapper
+compat_sys_keyctl_wrapper:
+ llgfr %r2,%r2 # u32
+ llgfr %r3,%r3 # u32
+ llgfr %r4,%r4 # u32
+ llgfr %r5,%r5 # u32
+ llgfr %r6,%r6 # u32
+ jg compat_sys_keyctl # branch to system call
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 55de521aef77..1268aa2991bf 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -583,8 +583,8 @@ kernel_per:
.globl io_int_handler
io_int_handler:
- stpt __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
+ stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA+16
SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
@@ -723,8 +723,8 @@ io_notify_resume:
.globl ext_int_handler
ext_int_handler:
- stpt __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
+ stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA+16
SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
@@ -750,6 +750,7 @@ __critical_end:
.globl mcck_int_handler
mcck_int_handler:
+ stck __LC_INT_CLOCK
spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+32
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index 6b1896345eda..950c59c6688b 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -30,23 +30,23 @@ struct fadvise64_64_args;
struct old_sigaction;
struct sel_arg_struct;
-long sys_pipe(unsigned long __user *fildes);
long sys_mmap2(struct mmap_arg_struct __user *arg);
-long old_mmap(struct mmap_arg_struct __user *arg);
+long sys_s390_old_mmap(struct mmap_arg_struct __user *arg);
long sys_ipc(uint call, int first, unsigned long second,
unsigned long third, void __user *ptr);
-long s390x_newuname(struct new_utsname __user *name);
-long s390x_personality(unsigned long personality);
-long s390_fadvise64(int fd, u32 offset_high, u32 offset_low,
+long sys_s390_newuname(struct new_utsname __user *name);
+long sys_s390_personality(unsigned long personality);
+long sys_s390_fadvise64(int fd, u32 offset_high, u32 offset_low,
size_t len, int advice);
-long s390_fadvise64_64(struct fadvise64_64_args __user *args);
-long s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, u32 len_low);
+long sys_s390_fadvise64_64(struct fadvise64_64_args __user *args);
+long sys_s390_fallocate(int fd, int mode, loff_t offset, u32 len_high,
+ u32 len_low);
long sys_fork(void);
long sys_clone(void);
long sys_vfork(void);
void execve_tail(void);
long sys_execve(void);
-int sys_sigsuspend(int history0, int history1, old_sigset_t mask);
+long sys_sigsuspend(int history0, int history1, old_sigset_t mask);
long sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact);
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss);
@@ -54,7 +54,5 @@ long sys_sigreturn(void);
long sys_rt_sigreturn(void);
long sys32_sigreturn(void);
long sys32_rt_sigreturn(void);
-long old_select(struct sel_arg_struct __user *arg);
-long sys_ptrace(long request, long pid, long addr, long data);
#endif /* _ENTRY_H */
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 16bb4fd1a403..c6fbde13971a 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -177,8 +177,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
.if !\sync
ni \psworg+1,0xfd # clear wait state bit
.endif
- lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user
+ lg %r14,__LC_VDSO_PER_CPU
+ lmg %r0,%r13,SP_R0(%r15) # load gprs 0-13 of user
stpt __LC_EXIT_TIMER
+ mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
+ lmg %r14,%r15,SP_R14(%r15) # load grps 14-15 of user
lpswe \psworg # back to caller
.endm
@@ -559,8 +562,8 @@ kernel_per:
*/
.globl io_int_handler
io_int_handler:
- stpt __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
+ stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA+32
SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
@@ -721,8 +724,8 @@ io_notify_resume:
*/
.globl ext_int_handler
ext_int_handler:
- stpt __LC_ASYNC_ENTER_TIMER
stck __LC_INT_CLOCK
+ stpt __LC_ASYNC_ENTER_TIMER
SAVE_ALL_BASE __LC_SAVE_AREA+32
SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
@@ -746,6 +749,7 @@ __critical_end:
*/
.globl mcck_int_handler
mcck_int_handler:
+ stck __LC_INT_CLOCK
la %r1,4095 # revalidate r1
spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
@@ -979,23 +983,23 @@ cleanup_sysc_return:
cleanup_sysc_leave:
clc 8(8,%r12),BASED(cleanup_sysc_leave_insn)
- je 2f
- mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ je 3f
clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8)
- je 2f
- mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
+ jhe 0f
+ mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
cghi %r12,__LC_MCK_OLD_PSW
- jne 0f
+ jne 1f
mvc __LC_SAVE_AREA+64(32),SP_R12(%r15)
- j 1f
-0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
-1: lmg %r0,%r11,SP_R0(%r15)
+ j 2f
+1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
+2: lmg %r0,%r11,SP_R0(%r15)
lg %r15,SP_R15(%r15)
-2: la %r12,__LC_RETURN_PSW
+3: la %r12,__LC_RETURN_PSW
br %r14
cleanup_sysc_leave_insn:
.quad sysc_done - 4
- .quad sysc_done - 8
+ .quad sysc_done - 16
cleanup_io_return:
mvc __LC_RETURN_PSW(8),0(%r12)
@@ -1005,23 +1009,23 @@ cleanup_io_return:
cleanup_io_leave:
clc 8(8,%r12),BASED(cleanup_io_leave_insn)
- je 2f
- mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ je 3f
clc 8(8,%r12),BASED(cleanup_io_leave_insn+8)
- je 2f
- mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
+ jhe 0f
+ mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
cghi %r12,__LC_MCK_OLD_PSW
- jne 0f
+ jne 1f
mvc __LC_SAVE_AREA+64(32),SP_R12(%r15)
- j 1f
-0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
-1: lmg %r0,%r11,SP_R0(%r15)
+ j 2f
+1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
+2: lmg %r0,%r11,SP_R0(%r15)
lg %r15,SP_R15(%r15)
-2: la %r12,__LC_RETURN_PSW
+3: la %r12,__LC_RETURN_PSW
br %r14
cleanup_io_leave_insn:
.quad io_done - 4
- .quad io_done - 8
+ .quad io_done - 16
/*
* Integer constants
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 3ccd36b24b8f..f9f70aa15244 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -87,6 +87,8 @@ startup_continue:
lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area
# move IPL device to lowcore
mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
+ lghi %r0,__LC_PASTE
+ stg %r0,__LC_VDSO_PER_CPU
#
# Setup stack
#
diff --git a/arch/s390/kernel/init_task.c b/arch/s390/kernel/init_task.c
index e80716843619..7db95c0b8693 100644
--- a/arch/s390/kernel/init_task.c
+++ b/arch/s390/kernel/init_task.c
@@ -16,7 +16,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 569079ec4ff0..a01cf0284db2 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -218,9 +218,10 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
- mutex_lock(&kprobe_mutex);
- free_insn_slot(p->ainsn.insn, 0);
- mutex_unlock(&kprobe_mutex);
+ if (p->ainsn.insn) {
+ free_insn_slot(p->ainsn.insn, 0);
+ p->ainsn.insn = NULL;
+ }
}
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -381,7 +382,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
/*
* It is possible to have multiple instances associated with a given
* task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
+ * have a return probe installed on them, and/or more than one return
* return probe was registered for a target function.
*
* We can handle this because:
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 04f8c67a6101..5cd38a90e64d 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -38,6 +38,8 @@
#include <linux/utsname.h>
#include <linux/tick.h>
#include <linux/elfcore.h>
+#include <linux/kernel_stat.h>
+#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -45,7 +47,6 @@
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/timer.h>
-#include <asm/cpu.h>
#include "entry.h"
asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -75,36 +76,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
return sf->gprs[8];
}
-DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
- .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
-};
-
-static int s390_idle_enter(void)
-{
- struct s390_idle_data *idle;
-
- idle = &__get_cpu_var(s390_idle);
- spin_lock(&idle->lock);
- idle->idle_count++;
- idle->in_idle = 1;
- idle->idle_enter = get_clock();
- spin_unlock(&idle->lock);
- vtime_stop_cpu_timer();
- return NOTIFY_OK;
-}
-
-void s390_idle_leave(void)
-{
- struct s390_idle_data *idle;
-
- vtime_start_cpu_timer();
- idle = &__get_cpu_var(s390_idle);
- spin_lock(&idle->lock);
- idle->idle_time += get_clock() - idle->idle_enter;
- idle->in_idle = 0;
- spin_unlock(&idle->lock);
-}
-
extern void s390_handle_mcck(void);
/*
* The idle loop on a S390...
@@ -117,10 +88,6 @@ static void default_idle(void)
local_irq_enable();
return;
}
- if (s390_idle_enter() == NOTIFY_BAD) {
- local_irq_enable();
- return;
- }
#ifdef CONFIG_HOTPLUG_CPU
if (cpu_is_offline(smp_processor_id())) {
preempt_enable_no_resched();
@@ -130,7 +97,6 @@ static void default_idle(void)
local_mcck_disable();
if (test_thread_flag(TIF_MCCK_PENDING)) {
local_mcck_enable();
- s390_idle_leave();
local_irq_enable();
s390_handle_mcck();
return;
@@ -138,9 +104,9 @@ static void default_idle(void)
trace_hardirqs_on();
/* Don't trace preempt off for idle. */
stop_critical_timings();
- /* Wait for external, I/O or machine check interrupt. */
- __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
- PSW_MASK_IO | PSW_MASK_EXT);
+ /* Stop virtual timer and halt the cpu. */
+ vtime_stop_cpu();
+ /* Reenable preemption tracer. */
start_critical_timings();
}
@@ -260,13 +226,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
return 0;
}
-asmlinkage long sys_fork(void)
+SYSCALL_DEFINE0(fork)
{
struct pt_regs *regs = task_pt_regs(current);
return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL);
}
-asmlinkage long sys_clone(void)
+SYSCALL_DEFINE0(clone)
{
struct pt_regs *regs = task_pt_regs(current);
unsigned long clone_flags;
@@ -293,7 +259,7 @@ asmlinkage long sys_clone(void)
* do not have enough call-clobbered registers to hold all
* the information you need.
*/
-asmlinkage long sys_vfork(void)
+SYSCALL_DEFINE0(vfork)
{
struct pt_regs *regs = task_pt_regs(current);
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
@@ -313,7 +279,7 @@ asmlinkage void execve_tail(void)
/*
* sys_execve() executes a new program.
*/
-asmlinkage long sys_execve(void)
+SYSCALL_DEFINE0(execve)
{
struct pt_regs *regs = task_pt_regs(current);
char *filename;
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index e019b419efc6..a0d2d55d7fb3 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -119,8 +119,8 @@ void do_extint(struct pt_regs *regs, unsigned short code)
struct pt_regs *old_regs;
old_regs = set_irq_regs(regs);
- irq_enter();
s390_idle_check();
+ irq_enter();
if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/* Serve timer interrupts first. */
clock_comparator_work();
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index b7a1efd5522c..d825f4950e4e 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -427,6 +427,8 @@ setup_lowcore(void)
/* enable extended save area */
__ctl_set_bit(14, 29);
}
+#else
+ lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
#endif
set_prefix((u32)(unsigned long) lc);
}
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 8e6812a22670..3cf74c3ccb69 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -25,6 +25,7 @@
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/tracehook.h>
+#include <linux/syscalls.h>
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/lowcore.h>
@@ -53,8 +54,7 @@ typedef struct
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
-asmlinkage int
-sys_sigsuspend(int history0, int history1, old_sigset_t mask)
+SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
{
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
@@ -70,9 +70,8 @@ sys_sigsuspend(int history0, int history1, old_sigset_t mask)
return -ERESTARTNOHAND;
}
-asmlinkage long
-sys_sigaction(int sig, const struct old_sigaction __user *act,
- struct old_sigaction __user *oact)
+SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act,
+ struct old_sigaction __user *, oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
@@ -102,15 +101,13 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
return ret;
}
-asmlinkage long
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss,
+ stack_t __user *, uoss)
{
struct pt_regs *regs = task_pt_regs(current);
return do_sigaltstack(uss, uoss, regs->gprs[15]);
}
-
-
/* Returns non-zero on fault. */
static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
{
@@ -164,7 +161,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
return 0;
}
-asmlinkage long sys_sigreturn(void)
+SYSCALL_DEFINE0(sigreturn)
{
struct pt_regs *regs = task_pt_regs(current);
sigframe __user *frame = (sigframe __user *)regs->gprs[15];
@@ -191,7 +188,7 @@ badframe:
return 0;
}
-asmlinkage long sys_rt_sigreturn(void)
+SYSCALL_DEFINE0(rt_sigreturn)
{
struct pt_regs *regs = task_pt_regs(current);
rt_sigframe __user *frame = (rt_sigframe __user *)regs->gprs[15];
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 6fc78541dc57..2d337cbb9329 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -47,6 +47,7 @@
#include <asm/lowcore.h>
#include <asm/sclp.h>
#include <asm/cpu.h>
+#include <asm/vdso.h>
#include "entry.h"
/*
@@ -55,12 +56,6 @@
struct _lowcore *lowcore_ptr[NR_CPUS];
EXPORT_SYMBOL(lowcore_ptr);
-cpumask_t cpu_online_map = CPU_MASK_NONE;
-EXPORT_SYMBOL(cpu_online_map);
-
-cpumask_t cpu_possible_map = CPU_MASK_ALL;
-EXPORT_SYMBOL(cpu_possible_map);
-
static struct task_struct *current_set[NR_CPUS];
static u8 smp_cpu_type;
@@ -506,6 +501,9 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
goto out;
lowcore->extended_save_area_addr = (u32) save_area;
}
+#else
+ if (vdso_alloc_per_cpu(cpu, lowcore))
+ goto out;
#endif
lowcore_ptr[cpu] = lowcore;
return 0;
@@ -528,6 +526,8 @@ static void smp_free_lowcore(int cpu)
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE)
free_page((unsigned long) lowcore->extended_save_area_addr);
+#else
+ vdso_free_per_cpu(cpu, lowcore);
#endif
free_page(lowcore->panic_stack - PAGE_SIZE);
free_pages(lowcore->async_stack - ASYNC_SIZE, ASYNC_ORDER);
@@ -670,6 +670,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order);
panic_stack = __get_free_page(GFP_KERNEL);
async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
+ BUG_ON(!lowcore || !panic_stack || !async_stack);
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE)
save_area = get_zeroed_page(GFP_KERNEL);
@@ -683,6 +684,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE)
lowcore->extended_save_area_addr = (u32) save_area;
+#else
+ if (vdso_alloc_per_cpu(smp_processor_id(), lowcore))
+ BUG();
#endif
set_prefix((u32)(unsigned long) lowcore);
local_mcck_enable();
@@ -851,9 +855,11 @@ static ssize_t show_idle_count(struct sys_device *dev,
unsigned long long idle_count;
idle = &per_cpu(s390_idle, dev->id);
- spin_lock_irq(&idle->lock);
+ spin_lock(&idle->lock);
idle_count = idle->idle_count;
- spin_unlock_irq(&idle->lock);
+ if (idle->idle_enter)
+ idle_count++;
+ spin_unlock(&idle->lock);
return sprintf(buf, "%llu\n", idle_count);
}
static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL);
@@ -862,18 +868,17 @@ static ssize_t show_idle_time(struct sys_device *dev,
struct sysdev_attribute *attr, char *buf)
{
struct s390_idle_data *idle;
- unsigned long long new_time;
+ unsigned long long now, idle_time, idle_enter;
idle = &per_cpu(s390_idle, dev->id);
- spin_lock_irq(&idle->lock);
- if (idle->in_idle) {
- new_time = get_clock();
- idle->idle_time += new_time - idle->idle_enter;
- idle->idle_enter = new_time;
- }
- new_time = idle->idle_time;
- spin_unlock_irq(&idle->lock);
- return sprintf(buf, "%llu\n", new_time >> 12);
+ spin_lock(&idle->lock);
+ now = get_clock();
+ idle_time = idle->idle_time;
+ idle_enter = idle->idle_enter;
+ if (idle_enter != 0ULL && idle_enter < now)
+ idle_time += now - idle_enter;
+ spin_unlock(&idle->lock);
+ return sprintf(buf, "%llu\n", idle_time >> 12);
}
static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 4fe952e557ac..c7ae4b17e0e3 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -29,6 +29,7 @@
#include <linux/personality.h>
#include <linux/unistd.h>
#include <linux/ipc.h>
+#include <linux/syscalls.h>
#include <asm/uaccess.h>
#include "entry.h"
@@ -74,7 +75,7 @@ struct mmap_arg_struct {
unsigned long offset;
};
-asmlinkage long sys_mmap2(struct mmap_arg_struct __user *arg)
+SYSCALL_DEFINE1(mmap2, struct mmap_arg_struct __user *, arg)
{
struct mmap_arg_struct a;
int error = -EFAULT;
@@ -86,7 +87,7 @@ out:
return error;
}
-asmlinkage long old_mmap(struct mmap_arg_struct __user *arg)
+SYSCALL_DEFINE1(s390_old_mmap, struct mmap_arg_struct __user *, arg)
{
struct mmap_arg_struct a;
long error = -EFAULT;
@@ -103,32 +104,13 @@ out:
return error;
}
-#ifndef CONFIG_64BIT
-struct sel_arg_struct {
- unsigned long n;
- fd_set __user *inp, *outp, *exp;
- struct timeval __user *tvp;
-};
-
-asmlinkage long old_select(struct sel_arg_struct __user *arg)
-{
- struct sel_arg_struct a;
-
- if (copy_from_user(&a, arg, sizeof(a)))
- return -EFAULT;
- /* sys_select() does the appropriate kernel locking */
- return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-
-}
-#endif /* CONFIG_64BIT */
-
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
* This is really horribly ugly.
*/
-asmlinkage long sys_ipc(uint call, int first, unsigned long second,
- unsigned long third, void __user *ptr)
+SYSCALL_DEFINE5(ipc, uint, call, int, first, unsigned long, second,
+ unsigned long, third, void __user *, ptr)
{
struct ipc_kludge tmp;
int ret;
@@ -194,7 +176,7 @@ asmlinkage long sys_ipc(uint call, int first, unsigned long second,
}
#ifdef CONFIG_64BIT
-asmlinkage long s390x_newuname(struct new_utsname __user *name)
+SYSCALL_DEFINE1(s390_newuname, struct new_utsname __user *, name)
{
int ret = sys_newuname(name);
@@ -205,7 +187,7 @@ asmlinkage long s390x_newuname(struct new_utsname __user *name)
return ret;
}
-asmlinkage long s390x_personality(unsigned long personality)
+SYSCALL_DEFINE1(s390_personality, unsigned long, personality)
{
int ret;
@@ -224,15 +206,13 @@ asmlinkage long s390x_personality(unsigned long personality)
*/
#ifndef CONFIG_64BIT
-asmlinkage long
-s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice)
+SYSCALL_DEFINE5(s390_fadvise64, int, fd, u32, offset_high, u32, offset_low,
+ size_t, len, int, advice)
{
return sys_fadvise64(fd, (u64) offset_high << 32 | offset_low,
len, advice);
}
-#endif
-
struct fadvise64_64_args {
int fd;
long long offset;
@@ -240,8 +220,7 @@ struct fadvise64_64_args {
int advice;
};
-asmlinkage long
-s390_fadvise64_64(struct fadvise64_64_args __user *args)
+SYSCALL_DEFINE1(s390_fadvise64_64, struct fadvise64_64_args __user *, args)
{
struct fadvise64_64_args a;
@@ -250,7 +229,6 @@ s390_fadvise64_64(struct fadvise64_64_args __user *args)
return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
}
-#ifndef CONFIG_64BIT
/*
* This is a wrapper to call sys_fallocate(). For 31 bit s390 the last
* 64 bit argument "len" is split into the upper and lower 32 bits. The
@@ -263,9 +241,19 @@ s390_fadvise64_64(struct fadvise64_64_args __user *args)
* to
* %r2: fd, %r3: mode, %r4/%r5: offset, 96(%r15)-103(%r15): len
*/
-asmlinkage long s390_fallocate(int fd, int mode, loff_t offset,
+SYSCALL_DEFINE(s390_fallocate)(int fd, int mode, loff_t offset,
u32 len_high, u32 len_low)
{
return sys_fallocate(fd, mode, offset, ((u64)len_high << 32) | len_low);
}
+#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
+asmlinkage long SyS_s390_fallocate(long fd, long mode, loff_t offset,
+ long len_high, long len_low)
+{
+ return SYSC_s390_fallocate((int) fd, (int) mode, offset,
+ (u32) len_high, (u32) len_low);
+}
+SYSCALL_ALIAS(sys_s390_fallocate, SyS_s390_fallocate);
+#endif
+
#endif
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 2d61787949d5..fe5b25a988ab 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -98,7 +98,7 @@ SYSCALL(sys_uselib,sys_uselib,sys32_uselib_wrapper)
SYSCALL(sys_swapon,sys_swapon,sys32_swapon_wrapper)
SYSCALL(sys_reboot,sys_reboot,sys32_reboot_wrapper)
SYSCALL(sys_ni_syscall,sys_ni_syscall,old32_readdir_wrapper) /* old readdir syscall */
-SYSCALL(old_mmap,old_mmap,old32_mmap_wrapper) /* 90 */
+SYSCALL(sys_s390_old_mmap,sys_s390_old_mmap,old32_mmap_wrapper) /* 90 */
SYSCALL(sys_munmap,sys_munmap,sys32_munmap_wrapper)
SYSCALL(sys_truncate,sys_truncate,sys32_truncate_wrapper)
SYSCALL(sys_ftruncate,sys_ftruncate,sys32_ftruncate_wrapper)
@@ -130,7 +130,7 @@ SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper)
SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn)
SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */
SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper)
-SYSCALL(sys_newuname,s390x_newuname,sys32_newuname_wrapper)
+SYSCALL(sys_newuname,sys_s390_newuname,sys32_newuname_wrapper)
NI_SYSCALL /* modify_ldt for i386 */
SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper)
SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */
@@ -144,7 +144,7 @@ SYSCALL(sys_getpgid,sys_getpgid,sys32_getpgid_wrapper)
SYSCALL(sys_fchdir,sys_fchdir,sys32_fchdir_wrapper)
SYSCALL(sys_bdflush,sys_bdflush,sys32_bdflush_wrapper)
SYSCALL(sys_sysfs,sys_sysfs,sys32_sysfs_wrapper) /* 135 */
-SYSCALL(sys_personality,s390x_personality,sys32_personality_wrapper)
+SYSCALL(sys_personality,sys_s390_personality,sys32_personality_wrapper)
NI_SYSCALL /* for afs_syscall */
SYSCALL(sys_setfsuid16,sys_ni_syscall,sys32_setfsuid16_wrapper) /* old setfsuid16 syscall */
SYSCALL(sys_setfsgid16,sys_ni_syscall,sys32_setfsgid16_wrapper) /* old setfsgid16 syscall */
@@ -194,7 +194,7 @@ SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper) /* old chown16 syscall
SYSCALL(sys_getcwd,sys_getcwd,sys32_getcwd_wrapper)
SYSCALL(sys_capget,sys_capget,sys32_capget_wrapper)
SYSCALL(sys_capset,sys_capset,sys32_capset_wrapper) /* 185 */
-SYSCALL(sys_sigaltstack,sys_sigaltstack,sys32_sigaltstack)
+SYSCALL(sys_sigaltstack,sys_sigaltstack,sys32_sigaltstack_wrapper)
SYSCALL(sys_sendfile,sys_sendfile64,sys32_sendfile_wrapper)
NI_SYSCALL /* streams1 */
NI_SYSCALL /* streams2 */
@@ -230,8 +230,8 @@ SYSCALL(sys_mincore,sys_mincore,sys32_mincore_wrapper)
SYSCALL(sys_madvise,sys_madvise,sys32_madvise_wrapper)
SYSCALL(sys_getdents64,sys_getdents64,sys32_getdents64_wrapper) /* 220 */
SYSCALL(sys_fcntl64,sys_ni_syscall,compat_sys_fcntl64_wrapper)
-SYSCALL(sys_readahead,sys_readahead,sys32_readahead)
-SYSCALL(sys_sendfile64,sys_ni_syscall,sys32_sendfile64)
+SYSCALL(sys_readahead,sys_readahead,sys32_readahead_wrapper)
+SYSCALL(sys_sendfile64,sys_ni_syscall,sys32_sendfile64_wrapper)
SYSCALL(sys_setxattr,sys_setxattr,sys32_setxattr_wrapper)
SYSCALL(sys_lsetxattr,sys_lsetxattr,sys32_lsetxattr_wrapper) /* 225 */
SYSCALL(sys_fsetxattr,sys_fsetxattr,sys32_fsetxattr_wrapper)
@@ -245,11 +245,11 @@ SYSCALL(sys_removexattr,sys_removexattr,sys32_removexattr_wrapper)
SYSCALL(sys_lremovexattr,sys_lremovexattr,sys32_lremovexattr_wrapper)
SYSCALL(sys_fremovexattr,sys_fremovexattr,sys32_fremovexattr_wrapper) /* 235 */
SYSCALL(sys_gettid,sys_gettid,sys_gettid)
-SYSCALL(sys_tkill,sys_tkill,sys_tkill)
+SYSCALL(sys_tkill,sys_tkill,sys_tkill_wrapper)
SYSCALL(sys_futex,sys_futex,compat_sys_futex_wrapper)
SYSCALL(sys_sched_setaffinity,sys_sched_setaffinity,sys32_sched_setaffinity_wrapper)
SYSCALL(sys_sched_getaffinity,sys_sched_getaffinity,sys32_sched_getaffinity_wrapper) /* 240 */
-SYSCALL(sys_tgkill,sys_tgkill,sys_tgkill)
+SYSCALL(sys_tgkill,sys_tgkill,sys_tgkill_wrapper)
NI_SYSCALL /* reserved for TUX */
SYSCALL(sys_io_setup,sys_io_setup,sys32_io_setup_wrapper)
SYSCALL(sys_io_destroy,sys_io_destroy,sys32_io_destroy_wrapper)
@@ -261,7 +261,7 @@ SYSCALL(sys_epoll_create,sys_epoll_create,sys_epoll_create_wrapper)
SYSCALL(sys_epoll_ctl,sys_epoll_ctl,sys_epoll_ctl_wrapper) /* 250 */
SYSCALL(sys_epoll_wait,sys_epoll_wait,sys_epoll_wait_wrapper)
SYSCALL(sys_set_tid_address,sys_set_tid_address,sys32_set_tid_address_wrapper)
-SYSCALL(s390_fadvise64,sys_fadvise64_64,sys32_fadvise64_wrapper)
+SYSCALL(sys_s390_fadvise64,sys_fadvise64_64,sys32_fadvise64_wrapper)
SYSCALL(sys_timer_create,sys_timer_create,sys32_timer_create_wrapper)
SYSCALL(sys_timer_settime,sys_timer_settime,sys32_timer_settime_wrapper) /* 255 */
SYSCALL(sys_timer_gettime,sys_timer_gettime,sys32_timer_gettime_wrapper)
@@ -272,7 +272,7 @@ SYSCALL(sys_clock_gettime,sys_clock_gettime,sys32_clock_gettime_wrapper) /* 260
SYSCALL(sys_clock_getres,sys_clock_getres,sys32_clock_getres_wrapper)
SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys32_clock_nanosleep_wrapper)
NI_SYSCALL /* reserved for vserver */
-SYSCALL(s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper)
+SYSCALL(sys_s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper)
SYSCALL(sys_statfs64,sys_statfs64,compat_sys_statfs64_wrapper)
SYSCALL(sys_fstatfs64,sys_fstatfs64,compat_sys_fstatfs64_wrapper)
SYSCALL(sys_remap_file_pages,sys_remap_file_pages,sys32_remap_file_pages_wrapper)
@@ -288,7 +288,7 @@ SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper)
SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load_wrapper)
SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper)
SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper)
-SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl) /* 280 */
+SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl_wrapper) /* 280 */
SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid_wrapper)
SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper)
SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper)
@@ -322,7 +322,7 @@ NI_SYSCALL /* 310 sys_move_pages */
SYSCALL(sys_getcpu,sys_getcpu,sys_getcpu_wrapper)
SYSCALL(sys_epoll_pwait,sys_epoll_pwait,compat_sys_epoll_pwait_wrapper)
SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
-SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
+SYSCALL(sys_s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper) /* 315 */
SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
NI_SYSCALL /* 317 old sys_timer_fd */
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 5be981a36c3e..fc468cae4460 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -160,7 +160,7 @@ void init_cpu_timer(void)
cd->min_delta_ns = 1;
cd->max_delta_ns = LONG_MAX;
cd->rating = 400;
- cd->cpumask = cpumask_of_cpu(cpu);
+ cd->cpumask = cpumask_of(cpu);
cd->set_next_event = s390_next_event;
cd->set_mode = s390_set_mode;
@@ -399,8 +399,10 @@ static struct workqueue_struct *time_sync_wq;
static void __init time_init_wq(void)
{
- if (!time_sync_wq)
- time_sync_wq = create_singlethread_workqueue("timesync");
+ if (time_sync_wq)
+ return;
+ time_sync_wq = create_singlethread_workqueue("timesync");
+ stop_machine_create();
}
/*
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 90e9ba11eba1..cc362c9ea8f1 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -97,6 +97,11 @@ cpumask_t cpu_coregroup_map(unsigned int cpu)
return mask;
}
+const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+{
+ return &cpu_core_map[cpu];
+}
+
static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core)
{
unsigned int cpu;
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 10a6ccef4412..690e17819686 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -31,9 +31,6 @@
#include <asm/sections.h>
#include <asm/vdso.h>
-/* Max supported size for symbol names */
-#define MAX_SYMNAME 64
-
#if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
extern char vdso32_start, vdso32_end;
static void *vdso32_kbase = &vdso32_start;
@@ -71,6 +68,119 @@ static union {
struct vdso_data *vdso_data = &vdso_data_store.data;
/*
+ * Setup vdso data page.
+ */
+static void vdso_init_data(struct vdso_data *vd)
+{
+ unsigned int facility_list;
+
+ facility_list = stfl();
+ vd->ectg_available = switch_amode && (facility_list & 1);
+}
+
+#ifdef CONFIG_64BIT
+/*
+ * Setup per cpu vdso data page.
+ */
+static void vdso_init_per_cpu_data(int cpu, struct vdso_per_cpu_data *vpcd)
+{
+}
+
+/*
+ * Allocate/free per cpu vdso data.
+ */
+#ifdef CONFIG_64BIT
+#define SEGMENT_ORDER 2
+#else
+#define SEGMENT_ORDER 1
+#endif
+
+int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore)
+{
+ unsigned long segment_table, page_table, page_frame;
+ u32 *psal, *aste;
+ int i;
+
+ lowcore->vdso_per_cpu_data = __LC_PASTE;
+
+ if (!switch_amode || !vdso_enabled)
+ return 0;
+
+ segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
+ page_table = get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ page_frame = get_zeroed_page(GFP_KERNEL);
+ if (!segment_table || !page_table || !page_frame)
+ goto out;
+
+ clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY,
+ PAGE_SIZE << SEGMENT_ORDER);
+ clear_table((unsigned long *) page_table, _PAGE_TYPE_EMPTY,
+ 256*sizeof(unsigned long));
+
+ *(unsigned long *) segment_table = _SEGMENT_ENTRY + page_table;
+ *(unsigned long *) page_table = _PAGE_RO + page_frame;
+
+ psal = (u32 *) (page_table + 256*sizeof(unsigned long));
+ aste = psal + 32;
+
+ for (i = 4; i < 32; i += 4)
+ psal[i] = 0x80000000;
+
+ lowcore->paste[4] = (u32)(addr_t) psal;
+ psal[0] = 0x20000000;
+ psal[2] = (u32)(addr_t) aste;
+ *(unsigned long *) (aste + 2) = segment_table +
+ _ASCE_TABLE_LENGTH + _ASCE_USER_BITS + _ASCE_TYPE_SEGMENT;
+ aste[4] = (u32)(addr_t) psal;
+ lowcore->vdso_per_cpu_data = page_frame;
+
+ vdso_init_per_cpu_data(cpu, (struct vdso_per_cpu_data *) page_frame);
+ return 0;
+
+out:
+ free_page(page_frame);
+ free_page(page_table);
+ free_pages(segment_table, SEGMENT_ORDER);
+ return -ENOMEM;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore)
+{
+ unsigned long segment_table, page_table, page_frame;
+ u32 *psal, *aste;
+
+ if (!switch_amode || !vdso_enabled)
+ return;
+
+ psal = (u32 *)(addr_t) lowcore->paste[4];
+ aste = (u32 *)(addr_t) psal[2];
+ segment_table = *(unsigned long *)(aste + 2) & PAGE_MASK;
+ page_table = *(unsigned long *) segment_table;
+ page_frame = *(unsigned long *) page_table;
+
+ free_page(page_frame);
+ free_page(page_table);
+ free_pages(segment_table, SEGMENT_ORDER);
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static void __vdso_init_cr5(void *dummy)
+{
+ unsigned long cr5;
+
+ cr5 = offsetof(struct _lowcore, paste);
+ __ctl_load(cr5, 5, 5);
+}
+
+static void vdso_init_cr5(void)
+{
+ if (switch_amode && vdso_enabled)
+ on_each_cpu(__vdso_init_cr5, NULL, 1);
+}
+#endif /* CONFIG_64BIT */
+
+/*
* This is called from binfmt_elf, we create the special vma for the
* vDSO and insert it into the mm struct tree
*/
@@ -172,6 +282,9 @@ static int __init vdso_init(void)
{
int i;
+ if (!vdso_enabled)
+ return 0;
+ vdso_init_data(vdso_data);
#if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT)
/* Calculate the size of the 32 bit vDSO */
vdso32_pages = ((&vdso32_end - &vdso32_start
@@ -208,6 +321,11 @@ static int __init vdso_init(void)
}
vdso64_pagelist[vdso64_pages - 1] = virt_to_page(vdso_data);
vdso64_pagelist[vdso64_pages] = NULL;
+#ifndef CONFIG_SMP
+ if (vdso_alloc_per_cpu(0, &S390_lowcore))
+ BUG();
+#endif
+ vdso_init_cr5();
#endif /* CONFIG_64BIT */
get_page(virt_to_page(vdso_data));
diff --git a/arch/s390/kernel/vdso32/gettimeofday.S b/arch/s390/kernel/vdso32/gettimeofday.S
index c32f29c3d70c..ad8acfc949fb 100644
--- a/arch/s390/kernel/vdso32/gettimeofday.S
+++ b/arch/s390/kernel/vdso32/gettimeofday.S
@@ -13,10 +13,6 @@
#include <asm/asm-offsets.h>
#include <asm/unistd.h>
-#include <asm/vdso.h>
-#include <asm/asm-offsets.h>
-#include <asm/unistd.h>
-
.text
.align 4
.globl __kernel_gettimeofday
diff --git a/arch/s390/kernel/vdso64/clock_getres.S b/arch/s390/kernel/vdso64/clock_getres.S
index 488e31a3c0e7..9ce8caafdb4e 100644
--- a/arch/s390/kernel/vdso64/clock_getres.S
+++ b/arch/s390/kernel/vdso64/clock_getres.S
@@ -22,7 +22,12 @@ __kernel_clock_getres:
cghi %r2,CLOCK_REALTIME
je 0f
cghi %r2,CLOCK_MONOTONIC
+ je 0f
+ cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */
jne 2f
+ larl %r5,_vdso_data
+ icm %r0,15,__LC_ECTG_OK(%r5)
+ jz 2f
0: ltgr %r3,%r3
jz 1f /* res == NULL */
larl %r1,3f
diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S
index 738a410b7eb2..79dbfee831ec 100644
--- a/arch/s390/kernel/vdso64/clock_gettime.S
+++ b/arch/s390/kernel/vdso64/clock_gettime.S
@@ -22,8 +22,10 @@ __kernel_clock_gettime:
larl %r5,_vdso_data
cghi %r2,CLOCK_REALTIME
je 4f
+ cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */
+ je 9f
cghi %r2,CLOCK_MONOTONIC
- jne 9f
+ jne 12f
/* CLOCK_MONOTONIC */
ltgr %r3,%r3
@@ -42,7 +44,7 @@ __kernel_clock_gettime:
alg %r0,__VDSO_WTOM_SEC(%r5)
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
jne 0b
- larl %r5,10f
+ larl %r5,13f
1: clg %r1,0(%r5)
jl 2f
slg %r1,0(%r5)
@@ -68,7 +70,7 @@ __kernel_clock_gettime:
lg %r0,__VDSO_XTIME_SEC(%r5)
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
jne 5b
- larl %r5,10f
+ larl %r5,13f
6: clg %r1,0(%r5)
jl 7f
slg %r1,0(%r5)
@@ -79,11 +81,38 @@ __kernel_clock_gettime:
8: lghi %r2,0
br %r14
+ /* CLOCK_THREAD_CPUTIME_ID for this thread */
+9: icm %r0,15,__VDSO_ECTG_OK(%r5)
+ jz 12f
+ ear %r2,%a4
+ llilh %r4,0x0100
+ sar %a4,%r4
+ lghi %r4,0
+ sacf 512 /* Magic ectg instruction */
+ .insn ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
+ sacf 0
+ sar %a4,%r2
+ algr %r1,%r0 /* r1 = cputime as TOD value */
+ mghi %r1,1000 /* convert to nanoseconds */
+ srlg %r1,%r1,12 /* r1 = cputime in nanosec */
+ lgr %r4,%r1
+ larl %r5,13f
+ srlg %r1,%r1,9 /* divide by 1000000000 */
+ mlg %r0,8(%r5)
+ srlg %r0,%r0,11 /* r0 = tv_sec */
+ stg %r0,0(%r3)
+ msg %r0,0(%r5) /* calculate tv_nsec */
+ slgr %r4,%r0 /* r4 = tv_nsec */
+ stg %r4,8(%r3)
+ lghi %r2,0
+ br %r14
+
/* Fallback to system call */
-9: lghi %r1,__NR_clock_gettime
+12: lghi %r1,__NR_clock_gettime
svc 0
br %r14
-10: .quad 1000000000
+13: .quad 1000000000
+14: .quad 19342813113834067
.cfi_endproc
.size __kernel_clock_gettime,.-__kernel_clock_gettime
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 75a6e62ea973..ecf0304e61c1 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -23,19 +23,43 @@
#include <asm/s390_ext.h>
#include <asm/timer.h>
#include <asm/irq_regs.h>
+#include <asm/cpu.h>
static ext_int_info_t ext_int_info_timer;
+
static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
+DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
+ .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
+};
+
+static inline __u64 get_vtimer(void)
+{
+ __u64 timer;
+
+ asm volatile("STPT %0" : "=m" (timer));
+ return timer;
+}
+
+static inline void set_vtimer(__u64 expires)
+{
+ __u64 timer;
+
+ asm volatile (" STPT %0\n" /* Store current cpu timer value */
+ " SPT %1" /* Set new value immediatly afterwards */
+ : "=m" (timer) : "m" (expires) );
+ S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
+ S390_lowcore.last_update_timer = expires;
+}
+
/*
* Update process times based on virtual cpu times stored by entry.S
* to the lowcore fields user_timer, system_timer & steal_clock.
*/
-void account_process_tick(struct task_struct *tsk, int user_tick)
+static void do_account_vtime(struct task_struct *tsk, int hardirq_offset)
{
- cputime_t cputime;
- __u64 timer, clock;
- int rcu_user_flag;
+ struct thread_info *ti = task_thread_info(tsk);
+ __u64 timer, clock, user, system, steal;
timer = S390_lowcore.last_update_timer;
clock = S390_lowcore.last_update_clock;
@@ -44,50 +68,41 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
: "=m" (S390_lowcore.last_update_timer),
"=m" (S390_lowcore.last_update_clock) );
S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
- S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock;
-
- cputime = S390_lowcore.user_timer >> 12;
- rcu_user_flag = cputime != 0;
- S390_lowcore.user_timer -= cputime << 12;
- S390_lowcore.steal_clock -= cputime << 12;
- account_user_time(tsk, cputime);
-
- cputime = S390_lowcore.system_timer >> 12;
- S390_lowcore.system_timer -= cputime << 12;
- S390_lowcore.steal_clock -= cputime << 12;
- account_system_time(tsk, HARDIRQ_OFFSET, cputime);
-
- cputime = S390_lowcore.steal_clock;
- if ((__s64) cputime > 0) {
- cputime >>= 12;
- S390_lowcore.steal_clock -= cputime << 12;
- account_steal_time(tsk, cputime);
+ S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
+
+ user = S390_lowcore.user_timer - ti->user_timer;
+ S390_lowcore.steal_timer -= user;
+ ti->user_timer = S390_lowcore.user_timer;
+ account_user_time(tsk, user, user);
+
+ system = S390_lowcore.system_timer - ti->system_timer;
+ S390_lowcore.steal_timer -= system;
+ ti->system_timer = S390_lowcore.system_timer;
+ account_system_time(tsk, hardirq_offset, system, system);
+
+ steal = S390_lowcore.steal_timer;
+ if ((s64) steal > 0) {
+ S390_lowcore.steal_timer = 0;
+ account_steal_time(steal);
}
}
-/*
- * Update process times based on virtual cpu times stored by entry.S
- * to the lowcore fields user_timer, system_timer & steal_clock.
- */
-void account_vtime(struct task_struct *tsk)
+void account_vtime(struct task_struct *prev, struct task_struct *next)
{
- cputime_t cputime;
- __u64 timer;
-
- timer = S390_lowcore.last_update_timer;
- asm volatile (" STPT %0" /* Store current cpu timer value */
- : "=m" (S390_lowcore.last_update_timer) );
- S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
-
- cputime = S390_lowcore.user_timer >> 12;
- S390_lowcore.user_timer -= cputime << 12;
- S390_lowcore.steal_clock -= cputime << 12;
- account_user_time(tsk, cputime);
+ struct thread_info *ti;
+
+ do_account_vtime(prev, 0);
+ ti = task_thread_info(prev);
+ ti->user_timer = S390_lowcore.user_timer;
+ ti->system_timer = S390_lowcore.system_timer;
+ ti = task_thread_info(next);
+ S390_lowcore.user_timer = ti->user_timer;
+ S390_lowcore.system_timer = ti->system_timer;
+}
- cputime = S390_lowcore.system_timer >> 12;
- S390_lowcore.system_timer -= cputime << 12;
- S390_lowcore.steal_clock -= cputime << 12;
- account_system_time(tsk, 0, cputime);
+void account_process_tick(struct task_struct *tsk, int user_tick)
+{
+ do_account_vtime(tsk, HARDIRQ_OFFSET);
}
/*
@@ -96,80 +111,131 @@ void account_vtime(struct task_struct *tsk)
*/
void account_system_vtime(struct task_struct *tsk)
{
- cputime_t cputime;
- __u64 timer;
+ struct thread_info *ti = task_thread_info(tsk);
+ __u64 timer, system;
timer = S390_lowcore.last_update_timer;
- asm volatile (" STPT %0" /* Store current cpu timer value */
- : "=m" (S390_lowcore.last_update_timer) );
+ S390_lowcore.last_update_timer = get_vtimer();
S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
- cputime = S390_lowcore.system_timer >> 12;
- S390_lowcore.system_timer -= cputime << 12;
- S390_lowcore.steal_clock -= cputime << 12;
- account_system_time(tsk, 0, cputime);
+ system = S390_lowcore.system_timer - ti->system_timer;
+ S390_lowcore.steal_timer -= system;
+ ti->system_timer = S390_lowcore.system_timer;
+ account_system_time(tsk, 0, system, system);
}
EXPORT_SYMBOL_GPL(account_system_vtime);
-static inline void set_vtimer(__u64 expires)
-{
- __u64 timer;
-
- asm volatile (" STPT %0\n" /* Store current cpu timer value */
- " SPT %1" /* Set new value immediatly afterwards */
- : "=m" (timer) : "m" (expires) );
- S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
- S390_lowcore.last_update_timer = expires;
-
- /* store expire time for this CPU timer */
- __get_cpu_var(virt_cpu_timer).to_expire = expires;
-}
-
-void vtime_start_cpu_timer(void)
+void vtime_start_cpu(void)
{
- struct vtimer_queue *vt_list;
-
- vt_list = &__get_cpu_var(virt_cpu_timer);
-
- /* CPU timer interrupt is pending, don't reprogramm it */
- if (vt_list->idle & 1LL<<63)
- return;
+ struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
+ struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
+ __u64 idle_time, expires;
+
+ /* Account time spent with enabled wait psw loaded as idle time. */
+ idle_time = S390_lowcore.int_clock - idle->idle_enter;
+ account_idle_time(idle_time);
+ S390_lowcore.last_update_clock = S390_lowcore.int_clock;
+
+ /* Account system time spent going idle. */
+ S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle;
+ S390_lowcore.last_update_timer = S390_lowcore.async_enter_timer;
+
+ /* Restart vtime CPU timer */
+ if (vq->do_spt) {
+ /* Program old expire value but first save progress. */
+ expires = vq->idle - S390_lowcore.async_enter_timer;
+ expires += get_vtimer();
+ set_vtimer(expires);
+ } else {
+ /* Don't account the CPU timer delta while the cpu was idle. */
+ vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer;
+ }
- if (!list_empty(&vt_list->list))
- set_vtimer(vt_list->idle);
+ spin_lock(&idle->lock);
+ idle->idle_time += idle_time;
+ idle->idle_enter = 0ULL;
+ idle->idle_count++;
+ spin_unlock(&idle->lock);
}
-void vtime_stop_cpu_timer(void)
+void vtime_stop_cpu(void)
{
- struct vtimer_queue *vt_list;
-
- vt_list = &__get_cpu_var(virt_cpu_timer);
-
- /* nothing to do */
- if (list_empty(&vt_list->list)) {
- vt_list->idle = VTIMER_MAX_SLICE;
- goto fire;
+ struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
+ struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
+ psw_t psw;
+
+ /* Wait for external, I/O or machine check interrupt. */
+ psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
+
+ /* Check if the CPU timer needs to be reprogrammed. */
+ if (vq->do_spt) {
+ __u64 vmax = VTIMER_MAX_SLICE;
+ /*
+ * The inline assembly is equivalent to
+ * vq->idle = get_cpu_timer();
+ * set_cpu_timer(VTIMER_MAX_SLICE);
+ * idle->idle_enter = get_clock();
+ * __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
+ * PSW_MASK_IO | PSW_MASK_EXT);
+ * The difference is that the inline assembly makes sure that
+ * the last three instruction are stpt, stck and lpsw in that
+ * order. This is done to increase the precision.
+ */
+ asm volatile(
+#ifndef CONFIG_64BIT
+ " basr 1,0\n"
+ "0: ahi 1,1f-0b\n"
+ " st 1,4(%2)\n"
+#else /* CONFIG_64BIT */
+ " larl 1,1f\n"
+ " stg 1,8(%2)\n"
+#endif /* CONFIG_64BIT */
+ " stpt 0(%4)\n"
+ " spt 0(%5)\n"
+ " stck 0(%3)\n"
+#ifndef CONFIG_64BIT
+ " lpsw 0(%2)\n"
+#else /* CONFIG_64BIT */
+ " lpswe 0(%2)\n"
+#endif /* CONFIG_64BIT */
+ "1:"
+ : "=m" (idle->idle_enter), "=m" (vq->idle)
+ : "a" (&psw), "a" (&idle->idle_enter),
+ "a" (&vq->idle), "a" (&vmax), "m" (vmax), "m" (psw)
+ : "memory", "cc", "1");
+ } else {
+ /*
+ * The inline assembly is equivalent to
+ * vq->idle = get_cpu_timer();
+ * idle->idle_enter = get_clock();
+ * __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
+ * PSW_MASK_IO | PSW_MASK_EXT);
+ * The difference is that the inline assembly makes sure that
+ * the last three instruction are stpt, stck and lpsw in that
+ * order. This is done to increase the precision.
+ */
+ asm volatile(
+#ifndef CONFIG_64BIT
+ " basr 1,0\n"
+ "0: ahi 1,1f-0b\n"
+ " st 1,4(%2)\n"
+#else /* CONFIG_64BIT */
+ " larl 1,1f\n"
+ " stg 1,8(%2)\n"
+#endif /* CONFIG_64BIT */
+ " stpt 0(%4)\n"
+ " stck 0(%3)\n"
+#ifndef CONFIG_64BIT
+ " lpsw 0(%2)\n"
+#else /* CONFIG_64BIT */
+ " lpswe 0(%2)\n"
+#endif /* CONFIG_64BIT */
+ "1:"
+ : "=m" (idle->idle_enter), "=m" (vq->idle)
+ : "a" (&psw), "a" (&idle->idle_enter),
+ "a" (&vq->idle), "m" (psw)
+ : "memory", "cc", "1");
}
-
- /* store the actual expire value */
- asm volatile ("STPT %0" : "=m" (vt_list->idle));
-
- /*
- * If the CPU timer is negative we don't reprogramm
- * it because we will get instantly an interrupt.
- */
- if (vt_list->idle & 1LL<<63)
- return;
-
- vt_list->offset += vt_list->to_expire - vt_list->idle;
-
- /*
- * We cannot halt the CPU timer, we just write a value that
- * nearly never expires (only after 71 years) and re-write
- * the stored expire value if we continue the timer
- */
- fire:
- set_vtimer(VTIMER_MAX_SLICE);
}
/*
@@ -195,30 +261,23 @@ static void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
*/
static void do_callbacks(struct list_head *cb_list)
{
- struct vtimer_queue *vt_list;
+ struct vtimer_queue *vq;
struct vtimer_list *event, *tmp;
- void (*fn)(unsigned long);
- unsigned long data;
if (list_empty(cb_list))
return;
- vt_list = &__get_cpu_var(virt_cpu_timer);
+ vq = &__get_cpu_var(virt_cpu_timer);
list_for_each_entry_safe(event, tmp, cb_list, entry) {
- fn = event->function;
- data = event->data;
- fn(data);
-
- if (!event->interval)
- /* delete one shot timer */
- list_del_init(&event->entry);
- else {
- /* move interval timer back to list */
- spin_lock(&vt_list->lock);
- list_del_init(&event->entry);
- list_add_sorted(event, &vt_list->list);
- spin_unlock(&vt_list->lock);
+ list_del_init(&event->entry);
+ (event->function)(event->data);
+ if (event->interval) {
+ /* Recharge interval timer */
+ event->expires = event->interval + vq->elapsed;
+ spin_lock(&vq->lock);
+ list_add_sorted(event, &vq->list);
+ spin_unlock(&vq->lock);
}
}
}
@@ -228,64 +287,57 @@ static void do_callbacks(struct list_head *cb_list)
*/
static void do_cpu_timer_interrupt(__u16 error_code)
{
- __u64 next, delta;
- struct vtimer_queue *vt_list;
+ struct vtimer_queue *vq;
struct vtimer_list *event, *tmp;
- struct list_head *ptr;
- /* the callback queue */
- struct list_head cb_list;
+ struct list_head cb_list; /* the callback queue */
+ __u64 elapsed, next;
INIT_LIST_HEAD(&cb_list);
- vt_list = &__get_cpu_var(virt_cpu_timer);
+ vq = &__get_cpu_var(virt_cpu_timer);
/* walk timer list, fire all expired events */
- spin_lock(&vt_list->lock);
-
- if (vt_list->to_expire < VTIMER_MAX_SLICE)
- vt_list->offset += vt_list->to_expire;
-
- list_for_each_entry_safe(event, tmp, &vt_list->list, entry) {
- if (event->expires > vt_list->offset)
- /* found first unexpired event, leave */
- break;
-
- /* re-charge interval timer, we have to add the offset */
- if (event->interval)
- event->expires = event->interval + vt_list->offset;
-
- /* move expired timer to the callback queue */
- list_move_tail(&event->entry, &cb_list);
+ spin_lock(&vq->lock);
+
+ elapsed = vq->elapsed + (vq->timer - S390_lowcore.async_enter_timer);
+ BUG_ON((s64) elapsed < 0);
+ vq->elapsed = 0;
+ list_for_each_entry_safe(event, tmp, &vq->list, entry) {
+ if (event->expires < elapsed)
+ /* move expired timer to the callback queue */
+ list_move_tail(&event->entry, &cb_list);
+ else
+ event->expires -= elapsed;
}
- spin_unlock(&vt_list->lock);
+ spin_unlock(&vq->lock);
+
+ vq->do_spt = list_empty(&cb_list);
do_callbacks(&cb_list);
/* next event is first in list */
- spin_lock(&vt_list->lock);
- if (!list_empty(&vt_list->list)) {
- ptr = vt_list->list.next;
- event = list_entry(ptr, struct vtimer_list, entry);
- next = event->expires - vt_list->offset;
-
- /* add the expired time from this interrupt handler
- * and the callback functions
- */
- asm volatile ("STPT %0" : "=m" (delta));
- delta = 0xffffffffffffffffLL - delta + 1;
- vt_list->offset += delta;
- next -= delta;
- } else {
- vt_list->offset = 0;
- next = VTIMER_MAX_SLICE;
- }
- spin_unlock(&vt_list->lock);
- set_vtimer(next);
+ next = VTIMER_MAX_SLICE;
+ spin_lock(&vq->lock);
+ if (!list_empty(&vq->list)) {
+ event = list_first_entry(&vq->list, struct vtimer_list, entry);
+ next = event->expires;
+ } else
+ vq->do_spt = 0;
+ spin_unlock(&vq->lock);
+ /*
+ * To improve precision add the time spent by the
+ * interrupt handler to the elapsed time.
+ * Note: CPU timer counts down and we got an interrupt,
+ * the current content is negative
+ */
+ elapsed = S390_lowcore.async_enter_timer - get_vtimer();
+ set_vtimer(next - elapsed);
+ vq->timer = next - elapsed;
+ vq->elapsed = elapsed;
}
void init_virt_timer(struct vtimer_list *timer)
{
timer->function = NULL;
INIT_LIST_HEAD(&timer->entry);
- spin_lock_init(&timer->lock);
}
EXPORT_SYMBOL(init_virt_timer);
@@ -299,44 +351,40 @@ static inline int vtimer_pending(struct vtimer_list *timer)
*/
static void internal_add_vtimer(struct vtimer_list *timer)
{
+ struct vtimer_queue *vq;
unsigned long flags;
- __u64 done;
- struct vtimer_list *event;
- struct vtimer_queue *vt_list;
+ __u64 left, expires;
- vt_list = &per_cpu(virt_cpu_timer, timer->cpu);
- spin_lock_irqsave(&vt_list->lock, flags);
+ vq = &per_cpu(virt_cpu_timer, timer->cpu);
+ spin_lock_irqsave(&vq->lock, flags);
BUG_ON(timer->cpu != smp_processor_id());
- /* if list is empty we only have to set the timer */
- if (list_empty(&vt_list->list)) {
- /* reset the offset, this may happen if the last timer was
- * just deleted by mod_virt_timer and the interrupt
- * didn't happen until here
- */
- vt_list->offset = 0;
- goto fire;
+ if (list_empty(&vq->list)) {
+ /* First timer on this cpu, just program it. */
+ list_add(&timer->entry, &vq->list);
+ set_vtimer(timer->expires);
+ vq->timer = timer->expires;
+ vq->elapsed = 0;
+ } else {
+ /* Check progress of old timers. */
+ expires = timer->expires;
+ left = get_vtimer();
+ if (likely((s64) expires < (s64) left)) {
+ /* The new timer expires before the current timer. */
+ set_vtimer(expires);
+ vq->elapsed += vq->timer - left;
+ vq->timer = expires;
+ } else {
+ vq->elapsed += vq->timer - left;
+ vq->timer = left;
+ }
+ /* Insert new timer into per cpu list. */
+ timer->expires += vq->elapsed;
+ list_add_sorted(timer, &vq->list);
}
- /* save progress */
- asm volatile ("STPT %0" : "=m" (done));
-
- /* calculate completed work */
- done = vt_list->to_expire - done + vt_list->offset;
- vt_list->offset = 0;
-
- list_for_each_entry(event, &vt_list->list, entry)
- event->expires -= done;
-
- fire:
- list_add_sorted(timer, &vt_list->list);
-
- /* get first element, which is the next vtimer slice */
- event = list_entry(vt_list->list.next, struct vtimer_list, entry);
-
- set_vtimer(event->expires);
- spin_unlock_irqrestore(&vt_list->lock, flags);
+ spin_unlock_irqrestore(&vq->lock, flags);
/* release CPU acquired in prepare_vtimer or mod_virt_timer() */
put_cpu();
}
@@ -381,14 +429,15 @@ EXPORT_SYMBOL(add_virt_timer_periodic);
* If we change a pending timer the function must be called on the CPU
* where the timer is running on, e.g. by smp_call_function_single()
*
- * The original mod_timer adds the timer if it is not pending. For compatibility
- * we do the same. The timer will be added on the current CPU as a oneshot timer.
+ * The original mod_timer adds the timer if it is not pending. For
+ * compatibility we do the same. The timer will be added on the current
+ * CPU as a oneshot timer.
*
* returns whether it has modified a pending timer (1) or not (0)
*/
int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
{
- struct vtimer_queue *vt_list;
+ struct vtimer_queue *vq;
unsigned long flags;
int cpu;
@@ -404,17 +453,17 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
return 1;
cpu = get_cpu();
- vt_list = &per_cpu(virt_cpu_timer, cpu);
+ vq = &per_cpu(virt_cpu_timer, cpu);
/* check if we run on the right CPU */
BUG_ON(timer->cpu != cpu);
/* disable interrupts before test if timer is pending */
- spin_lock_irqsave(&vt_list->lock, flags);
+ spin_lock_irqsave(&vq->lock, flags);
/* if timer isn't pending add it on the current CPU */
if (!vtimer_pending(timer)) {
- spin_unlock_irqrestore(&vt_list->lock, flags);
+ spin_unlock_irqrestore(&vq->lock, flags);
/* we do not activate an interval timer with mod_virt_timer */
timer->interval = 0;
timer->expires = expires;
@@ -431,7 +480,7 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
timer->interval = expires;
/* the timer can't expire anymore so we can release the lock */
- spin_unlock_irqrestore(&vt_list->lock, flags);
+ spin_unlock_irqrestore(&vq->lock, flags);
internal_add_vtimer(timer);
return 1;
}
@@ -445,25 +494,19 @@ EXPORT_SYMBOL(mod_virt_timer);
int del_virt_timer(struct vtimer_list *timer)
{
unsigned long flags;
- struct vtimer_queue *vt_list;
+ struct vtimer_queue *vq;
/* check if timer is pending */
if (!vtimer_pending(timer))
return 0;
- vt_list = &per_cpu(virt_cpu_timer, timer->cpu);
- spin_lock_irqsave(&vt_list->lock, flags);
+ vq = &per_cpu(virt_cpu_timer, timer->cpu);
+ spin_lock_irqsave(&vq->lock, flags);
/* we don't interrupt a running timer, just let it expire! */
list_del_init(&timer->entry);
- /* last timer removed */
- if (list_empty(&vt_list->list)) {
- vt_list->to_expire = 0;
- vt_list->offset = 0;
- }
-
- spin_unlock_irqrestore(&vt_list->lock, flags);
+ spin_unlock_irqrestore(&vq->lock, flags);
return 1;
}
EXPORT_SYMBOL(del_virt_timer);
@@ -473,24 +516,23 @@ EXPORT_SYMBOL(del_virt_timer);
*/
void init_cpu_vtimer(void)
{
- struct vtimer_queue *vt_list;
+ struct thread_info *ti = current_thread_info();
+ struct vtimer_queue *vq;
+
+ S390_lowcore.user_timer = ti->user_timer;
+ S390_lowcore.system_timer = ti->system_timer;
/* kick the virtual timer */
- S390_lowcore.exit_timer = VTIMER_MAX_SLICE;
- S390_lowcore.last_update_timer = VTIMER_MAX_SLICE;
- asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
+ asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer));
+
+ /* initialize per cpu vtimer structure */
+ vq = &__get_cpu_var(virt_cpu_timer);
+ INIT_LIST_HEAD(&vq->list);
+ spin_lock_init(&vq->lock);
/* enable cpu timer interrupts */
__ctl_set_bit(0,10);
-
- vt_list = &__get_cpu_var(virt_cpu_timer);
- INIT_LIST_HEAD(&vt_list->list);
- spin_lock_init(&vt_list->lock);
- vt_list->to_expire = 0;
- vt_list->offset = 0;
- vt_list->idle = 0;
-
}
void __init vtime_init(void)
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index a0775e1f08df..8300309698fa 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -47,7 +47,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
vcpu->run->exit_reason = KVM_EXIT_S390_RESET;
- VCPU_EVENT(vcpu, 3, "requesting userspace resets %lx",
+ VCPU_EVENT(vcpu, 3, "requesting userspace resets %llx",
vcpu->run->s390_reset_flags);
return -EREMOTE;
}
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 2960702b4824..f4fe28a2521a 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -160,7 +160,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
break;
case KVM_S390_INT_VIRTIO:
- VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%lx",
+ VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
inti->ext.ext_params, inti->ext.ext_params2);
vcpu->stat.deliver_virtio_interrupt++;
rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2603);
@@ -360,7 +360,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
vcpu->arch.ckc_timer.expires = jiffies + sltime;
add_timer(&vcpu->arch.ckc_timer);
- VCPU_EVENT(vcpu, 5, "enabled wait timer:%lx jiffies", sltime);
+ VCPU_EVENT(vcpu, 5, "enabled wait timer:%llx jiffies", sltime);
no_timer:
spin_lock_bh(&vcpu->arch.local_int.float_int->lock);
spin_lock_bh(&vcpu->arch.local_int.lock);
@@ -491,7 +491,7 @@ int kvm_s390_inject_vm(struct kvm *kvm,
switch (s390int->type) {
case KVM_S390_INT_VIRTIO:
- VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%lx",
+ VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx",
s390int->parm, s390int->parm64);
inti->type = s390int->type;
inti->ext.ext_params = s390int->parm;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 8b00eb2ddf57..be8497186b96 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -113,8 +113,6 @@ long kvm_arch_dev_ioctl(struct file *filp,
int kvm_dev_ioctl_check_extension(long ext)
{
switch (ext) {
- case KVM_CAP_USER_MEMORY:
- return 1;
default:
return 0;
}
@@ -185,8 +183,6 @@ struct kvm *kvm_arch_create_vm(void)
debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
VM_EVENT(kvm, 3, "%s", "vm created");
- try_module_get(THIS_MODULE);
-
return kvm;
out_nodbf:
free_page((unsigned long)(kvm->arch.sca));
@@ -196,13 +192,33 @@ out_nokvm:
return ERR_PTR(rc);
}
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+ VCPU_EVENT(vcpu, 3, "%s", "free cpu");
+ free_page((unsigned long)(vcpu->arch.sie_block));
+ kvm_vcpu_uninit(vcpu);
+ kfree(vcpu);
+}
+
+static void kvm_free_vcpus(struct kvm *kvm)
+{
+ unsigned int i;
+
+ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+ if (kvm->vcpus[i]) {
+ kvm_arch_vcpu_destroy(kvm->vcpus[i]);
+ kvm->vcpus[i] = NULL;
+ }
+ }
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
- debug_unregister(kvm->arch.dbf);
+ kvm_free_vcpus(kvm);
kvm_free_physmem(kvm);
free_page((unsigned long)(kvm->arch.sca));
+ debug_unregister(kvm->arch.dbf);
kfree(kvm);
- module_put(THIS_MODULE);
}
/* Section: vcpu related */
@@ -213,8 +229,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
{
- /* kvm common code refers to this, but does'nt call it */
- BUG();
+ /* Nothing todo */
}
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -308,8 +323,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
vcpu->arch.sie_block);
- try_module_get(THIS_MODULE);
-
return vcpu;
out_free_cpu:
kfree(vcpu);
@@ -317,14 +330,6 @@ out_nomem:
return ERR_PTR(rc);
}
-void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
-{
- VCPU_EVENT(vcpu, 3, "%s", "destroy cpu");
- free_page((unsigned long)(vcpu->arch.sie_block));
- kfree(vcpu);
- module_put(THIS_MODULE);
-}
-
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
/* kvm common code refers to this, but never calls it */
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index cce40ff2913b..3605df45dd41 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -118,7 +118,7 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
goto out;
}
- VCPU_EVENT(vcpu, 5, "storing cpu address to %lx", useraddr);
+ VCPU_EVENT(vcpu, 5, "storing cpu address to %llx", useraddr);
out:
return 0;
}
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 158b0d6d7046..f0258ca3b17e 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -183,7 +183,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
rc = vmem_add_mapping(start, size);
if (rc)
return rc;
- rc = __add_pages(zone, PFN_DOWN(start), PFN_DOWN(size));
+ rc = __add_pages(nid, zone, PFN_DOWN(start), PFN_DOWN(size));
if (rc)
vmem_remove_mapping(start, size);
return rc;
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index f32a5197128d..ebabe518e729 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -644,66 +644,25 @@ endmenu
menu "Bus options"
-# Even on SuperH devices which don't have an ISA bus,
-# this variable helps the PCMCIA modules handle
-# IRQ requesting properly -- Greg Banks.
-#
-# Though we're generally not interested in it when
-# we're not using PCMCIA, so we make it dependent on
-# PCMCIA outright. -- PFM.
-config ISA
- def_bool y
- depends on PCMCIA && HD6446X_SERIES
- help
- Find out whether you have ISA slots on your motherboard. ISA is the
- name of a bus system, i.e. the way the CPU talks to the other stuff
- inside your box. Other bus systems are PCI, EISA, MicroChannel
- (MCA) or VESA. ISA is an older system, now being displaced by PCI;
- newer boards don't support it. If you have ISA, say Y, otherwise N.
-
-config EISA
- bool
- ---help---
- The Extended Industry Standard Architecture (EISA) bus was
- developed as an open alternative to the IBM MicroChannel bus.
-
- The EISA bus provided some of the features of the IBM MicroChannel
- bus while maintaining backward compatibility with cards made for
- the older ISA bus. The EISA bus saw limited use between 1988 and
- 1995 when it was made obsolete by the PCI bus.
-
- Say Y here if you are building a kernel for an EISA-based machine.
-
- Otherwise, say N.
-
-config MCA
- bool
- help
- MicroChannel Architecture is found in some IBM PS/2 machines and
- laptops. It is a bus system similar to PCI or ISA. See
- <file:Documentation/mca.txt> (and especially the web page given
- there) before attempting to build an MCA bus kernel.
-
-config SBUS
- bool
-
config SUPERHYWAY
tristate "SuperHyway Bus support"
depends on CPU_SUBTYPE_SH4_202
config MAPLE
- bool "Maple Bus support"
- depends on SH_DREAMCAST
- help
- The Maple Bus is SEGA's serial communication bus for peripherals
- on the Dreamcast. Without this bus support you won't be able to
- get your Dreamcast keyboard etc to work, so most users
- probably want to say 'Y' here, unless you are only using the
- Dreamcast with a serial line terminal or a remote network
- connection.
+ bool "Maple Bus support"
+ depends on SH_DREAMCAST
+ help
+ The Maple Bus is SEGA's serial communication bus for peripherals
+ on the Dreamcast. Without this bus support you won't be able to
+ get your Dreamcast keyboard etc to work, so most users
+ probably want to say 'Y' here, unless you are only using the
+ Dreamcast with a serial line terminal or a remote network
+ connection.
source "arch/sh/drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
+
source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index 1c67cba6e34f..caf4c33f4e84 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -18,8 +18,10 @@
#include <linux/mtd/sh_flctl.h>
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/smc911x.h>
+#include <linux/smsc911x.h>
#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
#include <media/soc_camera_platform.h>
#include <media/sh_mobile_ceu.h>
#include <video/sh_mobile_lcdc.h>
@@ -27,12 +29,14 @@
#include <asm/clock.h>
#include <cpu/sh7723.h>
-static struct smc911x_platdata smc911x_info = {
- .flags = SMC911X_USE_32BIT,
- .irq_flags = IRQF_TRIGGER_LOW,
+static struct smsc911x_platform_config smsc911x_config = {
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+ .flags = SMSC911X_USE_32BIT,
};
-static struct resource smc9118_resources[] = {
+static struct resource smsc9118_resources[] = {
[0] = {
.start = 0xb6080000,
.end = 0xb60fffff,
@@ -45,13 +49,13 @@ static struct resource smc9118_resources[] = {
}
};
-static struct platform_device smc9118_device = {
- .name = "smc911x",
+static struct platform_device smsc9118_device = {
+ .name = "smsc911x",
.id = -1,
- .num_resources = ARRAY_SIZE(smc9118_resources),
- .resource = smc9118_resources,
+ .num_resources = ARRAY_SIZE(smsc9118_resources),
+ .resource = smsc9118_resources,
.dev = {
- .platform_data = &smc911x_info,
+ .platform_data = &smsc911x_config,
},
};
@@ -315,8 +319,22 @@ static struct platform_device ceu_device = {
},
};
+struct spi_gpio_platform_data sdcard_cn3_platform_data = {
+ .sck = GPIO_PTD0,
+ .mosi = GPIO_PTD1,
+ .miso = GPIO_PTD2,
+ .num_chipselect = 1,
+};
+
+static struct platform_device sdcard_cn3_device = {
+ .name = "spi_gpio",
+ .dev = {
+ .platform_data = &sdcard_cn3_platform_data,
+ },
+};
+
static struct platform_device *ap325rxa_devices[] __initdata = {
- &smc9118_device,
+ &smsc9118_device,
&ap325rxa_nor_flash_device,
&lcdc_device,
&ceu_device,
@@ -324,6 +342,7 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
&camera_device,
#endif
&nand_flash_device,
+ &sdcard_cn3_device,
};
static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
@@ -332,6 +351,15 @@ static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
},
};
+static struct spi_board_info ap325rxa_spi_devices[] = {
+ {
+ .modalias = "mmc_spi",
+ .max_speed_hz = 5000000,
+ .chip_select = 0,
+ .controller_data = (void *) GPIO_PTD5,
+ },
+};
+
static int __init ap325rxa_devices_setup(void)
{
/* LD3 and LD4 LEDs */
@@ -429,6 +457,9 @@ static int __init ap325rxa_devices_setup(void)
i2c_register_board_info(0, ap325rxa_i2c_devices,
ARRAY_SIZE(ap325rxa_i2c_devices));
+ spi_register_board_info(ap325rxa_spi_devices,
+ ARRAY_SIZE(ap325rxa_spi_devices));
+
return platform_add_devices(ap325rxa_devices,
ARRAY_SIZE(ap325rxa_devices));
}
diff --git a/arch/sh/boards/board-magicpanelr2.c b/arch/sh/boards/board-magicpanelr2.c
index 3de22ccdeb7e..0a37c8bfc959 100644
--- a/arch/sh/boards/board-magicpanelr2.c
+++ b/arch/sh/boards/board-magicpanelr2.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/smsc911x.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
@@ -242,7 +243,7 @@ static void __init mpr2_setup(char **cmdline_p)
printk(KERN_WARNING "Ethernet not ready\n");
}
-static struct resource smc911x_resources[] = {
+static struct resource smsc911x_resources[] = {
[0] = {
.start = 0xa8000000,
.end = 0xabffffff,
@@ -255,11 +256,21 @@ static struct resource smc911x_resources[] = {
},
};
-static struct platform_device smc911x_device = {
- .name = "smc911x",
+static struct smsc911x_platform_config smsc911x_config = {
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+ .flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device smsc911x_device = {
+ .name = "smsc911x",
.id = -1,
- .num_resources = ARRAY_SIZE(smc911x_resources),
- .resource = smc911x_resources,
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
+ .dev = {
+ .platform_data = &smsc911x_config,
+ },
};
static struct resource heartbeat_resources[] = {
@@ -360,7 +371,7 @@ static void __init set_mtd_partitions(void)
static struct platform_device *mpr2_devices[] __initdata = {
&heartbeat_device,
- &smc911x_device,
+ &smsc911x_device,
&flash_device,
};
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index 408bbddaf325..38a64968d7bf 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -18,6 +18,7 @@
#include <linux/i2c.h>
#include <linux/i2c-pca-platform.h>
#include <linux/i2c-algo-pca.h>
+#include <linux/irq.h>
#include <asm/heartbeat.h>
#include <mach/sh7785lcr.h>
diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c
index 806438b42cac..20fe72c515d5 100644
--- a/arch/sh/boards/mach-highlander/setup.c
+++ b/arch/sh/boards/mach-highlander/setup.c
@@ -18,6 +18,7 @@
#include <linux/ata_platform.h>
#include <linux/types.h>
#include <linux/i2c.h>
+#include <linux/irq.h>
#include <net/ax88796.h>
#include <asm/machvec.h>
#include <mach/highlander.h>
diff --git a/arch/sh/boards/mach-hp6xx/setup.c b/arch/sh/boards/mach-hp6xx/setup.c
index 48fece78ff54..746742bdc014 100644
--- a/arch/sh/boards/mach-hp6xx/setup.c
+++ b/arch/sh/boards/mach-hp6xx/setup.c
@@ -12,9 +12,9 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/irq.h>
#include <asm/hd64461.h>
#include <asm/io.h>
-#include <asm/irq.h>
#include <mach/hp6xx.h>
#include <cpu/dac.h>
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index cc1408119c24..28e56c5809a2 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -18,9 +18,12 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/gpio.h>
-#include <media/soc_camera_platform.h>
-#include <media/sh_mobile_ceu.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
#include <video/sh_mobile_lcdc.h>
+#include <media/sh_mobile_ceu.h>
+#include <media/ov772x.h>
+#include <media/tw9910.h>
#include <asm/clock.h>
#include <asm/machvec.h>
#include <asm/io.h>
@@ -292,9 +295,12 @@ static struct platform_device migor_lcdc_device = {
};
static struct clk *camera_clk;
+static DEFINE_MUTEX(camera_lock);
-static void camera_power_on(void)
+static void camera_power_on(int is_tw)
{
+ mutex_lock(&camera_lock);
+
/* Use 10 MHz VIO_CKO instead of 24 MHz to work
* around signal quality issues on Panel Board V2.1.
*/
@@ -304,6 +310,12 @@ static void camera_power_on(void)
/* use VIO_RST to take camera out of reset */
mdelay(10);
+ if (is_tw) {
+ gpio_set_value(GPIO_PTT2, 0);
+ gpio_set_value(GPIO_PTT0, 0);
+ } else {
+ gpio_set_value(GPIO_PTT0, 1);
+ }
gpio_set_value(GPIO_PTT3, 0);
mdelay(10);
gpio_set_value(GPIO_PTT3, 1);
@@ -316,107 +328,29 @@ static void camera_power_off(void)
clk_put(camera_clk);
gpio_set_value(GPIO_PTT3, 0);
+ mutex_unlock(&camera_lock);
}
-static void camera_power(int mode)
+static int ov7725_power(struct device *dev, int mode)
{
if (mode)
- camera_power_on();
+ camera_power_on(0);
else
camera_power_off();
-}
-#ifdef CONFIG_I2C
-static unsigned char camera_ov772x_magic[] =
-{
- 0x09, 0x01, 0x0c, 0x20, 0x0d, 0x41, 0x0e, 0x01,
- 0x12, 0x00, 0x13, 0x8F, 0x14, 0x4A, 0x15, 0x00,
- 0x16, 0x00, 0x17, 0x23, 0x18, 0xa0, 0x19, 0x07,
- 0x1a, 0xf0, 0x1b, 0x40, 0x1f, 0x00, 0x20, 0x10,
- 0x22, 0xff, 0x23, 0x01, 0x28, 0x00, 0x29, 0xa0,
- 0x2a, 0x00, 0x2b, 0x00, 0x2c, 0xf0, 0x2d, 0x00,
- 0x2e, 0x00, 0x30, 0x80, 0x31, 0x60, 0x32, 0x00,
- 0x33, 0x00, 0x34, 0x00, 0x3d, 0x80, 0x3e, 0xe2,
- 0x3f, 0x1f, 0x42, 0x80, 0x43, 0x80, 0x44, 0x80,
- 0x45, 0x80, 0x46, 0x00, 0x47, 0x00, 0x48, 0x00,
- 0x49, 0x50, 0x4a, 0x30, 0x4b, 0x50, 0x4c, 0x50,
- 0x4d, 0x00, 0x4e, 0xef, 0x4f, 0x10, 0x50, 0x60,
- 0x51, 0x00, 0x52, 0x00, 0x53, 0x24, 0x54, 0x7a,
- 0x55, 0xfc, 0x62, 0xff, 0x63, 0xf0, 0x64, 0x1f,
- 0x65, 0x00, 0x66, 0x10, 0x67, 0x00, 0x68, 0x00,
- 0x69, 0x5c, 0x6a, 0x11, 0x6b, 0xa2, 0x6c, 0x01,
- 0x6d, 0x50, 0x6e, 0x80, 0x6f, 0x80, 0x70, 0x0f,
- 0x71, 0x00, 0x72, 0x00, 0x73, 0x0f, 0x74, 0x0f,
- 0x75, 0xff, 0x78, 0x10, 0x79, 0x70, 0x7a, 0x70,
- 0x7b, 0xf0, 0x7c, 0xf0, 0x7d, 0xf0, 0x7e, 0x0e,
- 0x7f, 0x1a, 0x80, 0x31, 0x81, 0x5a, 0x82, 0x69,
- 0x83, 0x75, 0x84, 0x7e, 0x85, 0x88, 0x86, 0x8f,
- 0x87, 0x96, 0x88, 0xa3, 0x89, 0xaf, 0x8a, 0xc4,
- 0x8b, 0xd7, 0x8c, 0xe8, 0x8d, 0x20, 0x8e, 0x00,
- 0x8f, 0x00, 0x90, 0x08, 0x91, 0x10, 0x92, 0x1f,
- 0x93, 0x01, 0x94, 0x2c, 0x95, 0x24, 0x96, 0x08,
- 0x97, 0x14, 0x98, 0x24, 0x99, 0x38, 0x9a, 0x9e,
- 0x9b, 0x00, 0x9c, 0x40, 0x9e, 0x11, 0x9f, 0x02,
- 0xa0, 0x00, 0xa1, 0x40, 0xa2, 0x40, 0xa3, 0x06,
- 0xa4, 0x00, 0xa6, 0x00, 0xa7, 0x40, 0xa8, 0x40,
- 0xa9, 0x80, 0xaa, 0x80, 0xab, 0x06, 0xac, 0xff,
- 0x12, 0x06, 0x64, 0x3f, 0x12, 0x46, 0x17, 0x3f,
- 0x18, 0x50, 0x19, 0x03, 0x1a, 0x78, 0x29, 0x50,
- 0x2c, 0x78,
-};
+ return 0;
+}
-static int ov772x_set_capture(struct soc_camera_platform_info *info,
- int enable)
+static int tw9910_power(struct device *dev, int mode)
{
- struct i2c_adapter *a = i2c_get_adapter(0);
- struct i2c_msg msg;
- int ret = 0;
- int i;
-
- if (!enable)
- return 0; /* camera_power_off() is enough */
-
- for (i = 0; i < ARRAY_SIZE(camera_ov772x_magic); i += 2) {
- u_int8_t buf[8];
-
- msg.addr = 0x21;
- msg.buf = buf;
- msg.len = 2;
- msg.flags = 0;
-
- buf[0] = camera_ov772x_magic[i];
- buf[1] = camera_ov772x_magic[i + 1];
-
- ret = (ret < 0) ? ret : i2c_transfer(a, &msg, 1);
- }
+ if (mode)
+ camera_power_on(1);
+ else
+ camera_power_off();
- return ret;
+ return 0;
}
-static struct soc_camera_platform_info ov772x_info = {
- .iface = 0,
- .format_name = "RGB565",
- .format_depth = 16,
- .format = {
- .pixelformat = V4L2_PIX_FMT_RGB565,
- .colorspace = V4L2_COLORSPACE_SRGB,
- .width = 320,
- .height = 240,
- },
- .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
- SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
- .power = camera_power,
- .set_capture = ov772x_set_capture,
-};
-
-static struct platform_device migor_camera_device = {
- .name = "soc_camera_platform",
- .dev = {
- .platform_data = &ov772x_info,
- },
-};
-#endif /* CONFIG_I2C */
-
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \
| SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH,
@@ -448,16 +382,43 @@ static struct platform_device migor_ceu_device = {
},
};
+static struct ov772x_camera_info ov7725_info = {
+ .buswidth = SOCAM_DATAWIDTH_8,
+ .link = {
+ .power = ov7725_power,
+ },
+};
+
+static struct tw9910_video_info tw9910_info = {
+ .buswidth = SOCAM_DATAWIDTH_8,
+ .mpout = TW9910_MPO_FIELD,
+ .link = {
+ .power = tw9910_power,
+ }
+};
+
+struct spi_gpio_platform_data sdcard_cn9_platform_data = {
+ .sck = GPIO_PTD0,
+ .mosi = GPIO_PTD1,
+ .miso = GPIO_PTD2,
+ .num_chipselect = 1,
+};
+
+static struct platform_device sdcard_cn9_device = {
+ .name = "spi_gpio",
+ .dev = {
+ .platform_data = &sdcard_cn9_platform_data,
+ },
+};
+
static struct platform_device *migor_devices[] __initdata = {
&smc91x_eth_device,
&sh_keysc_device,
&migor_lcdc_device,
&migor_ceu_device,
-#ifdef CONFIG_I2C
- &migor_camera_device,
-#endif
&migor_nor_flash_device,
&migor_nand_flash_device,
+ &sdcard_cn9_device,
};
static struct i2c_board_info migor_i2c_devices[] = {
@@ -468,6 +429,23 @@ static struct i2c_board_info migor_i2c_devices[] = {
I2C_BOARD_INFO("migor_ts", 0x51),
.irq = 38, /* IRQ6 */
},
+ {
+ I2C_BOARD_INFO("ov772x", 0x21),
+ .platform_data = &ov7725_info,
+ },
+ {
+ I2C_BOARD_INFO("tw9910", 0x45),
+ .platform_data = &tw9910_info,
+ },
+};
+
+static struct spi_board_info migor_spi_devices[] = {
+ {
+ .modalias = "mmc_spi",
+ .max_speed_hz = 5000000,
+ .chip_select = 0,
+ .controller_data = (void *) GPIO_PTD5,
+ },
};
static int __init migor_devices_setup(void)
@@ -592,6 +570,9 @@ static int __init migor_devices_setup(void)
i2c_register_board_info(0, migor_i2c_devices,
ARRAY_SIZE(migor_i2c_devices));
+ spi_register_board_info(migor_spi_devices,
+ ARRAY_SIZE(migor_spi_devices));
+
return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
}
__initcall(migor_devices_setup);
diff --git a/arch/sh/boards/mach-rsk/devices-rsk7203.c b/arch/sh/boards/mach-rsk/devices-rsk7203.c
index 73f743b9be8d..d8a65ea91665 100644
--- a/arch/sh/boards/mach-rsk/devices-rsk7203.c
+++ b/arch/sh/boards/mach-rsk/devices-rsk7203.c
@@ -15,19 +15,21 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/map.h>
-#include <linux/smc911x.h>
+#include <linux/smsc911x.h>
#include <linux/gpio.h>
#include <linux/leds.h>
#include <asm/machvec.h>
#include <asm/io.h>
#include <cpu/sh7203.h>
-static struct smc911x_platdata smc911x_info = {
- .flags = SMC911X_USE_16BIT,
- .irq_flags = IRQF_TRIGGER_LOW,
+static struct smsc911x_platform_config smsc911x_config = {
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+ .flags = SMSC911X_USE_16BIT,
};
-static struct resource smc911x_resources[] = {
+static struct resource smsc911x_resources[] = {
[0] = {
.start = 0x24000000,
.end = 0x24000000 + 0x100,
@@ -40,13 +42,13 @@ static struct resource smc911x_resources[] = {
},
};
-static struct platform_device smc911x_device = {
- .name = "smc911x",
+static struct platform_device smsc911x_device = {
+ .name = "smsc911x",
.id = -1,
- .num_resources = ARRAY_SIZE(smc911x_resources),
- .resource = smc911x_resources,
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
.dev = {
- .platform_data = &smc911x_info,
+ .platform_data = &smsc911x_config,
},
};
@@ -87,7 +89,7 @@ static struct platform_device led_device = {
};
static struct platform_device *rsk7203_devices[] __initdata = {
- &smc911x_device,
+ &smsc911x_device,
&led_device,
};
diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c
index a70d23b21788..a340492087fa 100644
--- a/arch/sh/boards/mach-x3proto/setup.c
+++ b/arch/sh/boards/mach-x3proto/setup.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/smc91x.h>
+#include <linux/irq.h>
#include <asm/ilsel.h>
static struct resource heartbeat_resources[] = {
diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig
index 874dd9726e52..5c423fa8e6b8 100644
--- a/arch/sh/configs/ap325rxa_defconfig
+++ b/arch/sh/configs/ap325rxa_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Tue Oct 21 18:20:06 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 16:54:19 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -75,12 +77,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -90,7 +90,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -98,11 +97,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -119,6 +116,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -128,6 +129,7 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -192,7 +194,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -269,7 +270,6 @@ CONFIG_SECCOMP=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
#
@@ -293,11 +293,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -353,6 +360,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -368,8 +376,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -447,6 +455,8 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
#
# Self-contained MTD device drivers
#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
@@ -472,7 +482,15 @@ CONFIG_MTD_NAND_SH_FLCTL=y
#
# UBI - Unsorted block images
#
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -487,7 +505,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -530,6 +550,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
@@ -541,13 +562,34 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_STNIC is not set
# CONFIG_SMC91X is not set
-CONFIG_SMC911X=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -630,6 +672,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -637,19 +680,102 @@ CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
-# CONFIG_SPI is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_SH_MOBILE=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 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=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_GPIO=y
+# CONFIG_SPI_SH_SCI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -658,8 +784,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -668,13 +799,47 @@ CONFIG_SSB_POSSIBLE=y
#
# Multimedia core support
#
-# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
+CONFIG_VIDEO_V4L1_COMPAT=y
# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
+CONFIG_VIDEO_MEDIA=y
#
# Multimedia drivers
#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEOBUF_GEN=y
+CONFIG_VIDEOBUF_DMA_CONTIG=y
+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_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+CONFIG_SOC_CAMERA=y
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+CONFIG_SOC_CAMERA_PLATFORM=y
+# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_VIDEO_SH_MOBILE_CEU=y
+# CONFIG_RADIO_ADAPTERS is not set
# CONFIG_DAB is not set
#
@@ -682,7 +847,34 @@ CONFIG_SSB_POSSIBLE=y
#
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -694,14 +886,103 @@ CONFIG_SSB_POSSIBLE=y
# Console display driver support
#
CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_LOGO_SUPERH_MONO=y
+CONFIG_LOGO_SUPERH_VGA16=y
+CONFIG_LOGO_SUPERH_CLUT224=y
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
-# CONFIG_MMC is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_SPI=y
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_PCF8563=y
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SH is not set
# CONFIG_DMADEVICES is not set
CONFIG_UIO=y
# CONFIG_UIO_PDRV is not set
@@ -768,10 +1049,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -780,6 +1058,7 @@ CONFIG_TMPFS=y
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
# CONFIG_JFFS2_FS is not set
+# CONFIG_UBIFS_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
@@ -878,13 +1157,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -900,11 +1185,14 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -987,12 +1275,13 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC_ITU_T=y
CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
+CONFIG_CRC7=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
diff --git a/arch/sh/configs/cayman_defconfig b/arch/sh/configs/cayman_defconfig
index e21c0e8e22d9..92895013813d 100644
--- a/arch/sh/configs/cayman_defconfig
+++ b/arch/sh/configs/cayman_defconfig
@@ -700,8 +700,8 @@ CONFIG_I2C_HELPER_AUTO=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
index be4c2e0dbb26..2d86e0487517 100644
--- a/arch/sh/configs/dreamcast_defconfig
+++ b/arch/sh/configs/dreamcast_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:18:02 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 16:54:55 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -78,7 +80,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -90,7 +91,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -98,11 +98,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -119,6 +117,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -126,6 +128,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -195,7 +198,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -290,7 +292,6 @@ CONFIG_SECCOMP=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
# CONFIG_GUSA_RB is not set
@@ -310,6 +311,7 @@ CONFIG_MAPLE=y
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCCARD is not set
@@ -322,11 +324,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -379,6 +388,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -394,8 +404,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -434,6 +444,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -477,6 +488,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -492,7 +504,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -506,6 +517,7 @@ CONFIG_8139TOO=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -611,6 +623,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -643,11 +656,11 @@ CONFIG_SH_WDT=y
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -657,7 +670,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -732,6 +745,7 @@ CONFIG_FB_PVR2=y
# CONFIG_FB_SH_MOBILE_LCDC is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -788,9 +802,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -847,10 +862,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -901,13 +913,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -923,6 +941,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1006,6 +1025,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/edosk7705_defconfig b/arch/sh/configs/edosk7705_defconfig
index 8f4329fbbd39..461bfb350221 100644
--- a/arch/sh/configs/edosk7705_defconfig
+++ b/arch/sh/configs/edosk7705_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc6
-# Wed Dec 17 13:53:02 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 16:55:29 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -64,7 +64,6 @@ CONFIG_SHMEM=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -72,11 +71,14 @@ CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
# CONFIG_BLOCK is not set
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -151,7 +153,6 @@ CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -362,7 +363,6 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -382,10 +382,7 @@ CONFIG_STAGING_EXCLUDE_BUILD=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_NLS is not set
#
@@ -426,6 +423,7 @@ CONFIG_HAVE_ARCH_KGDB=y
#
# Library routines
#
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/edosk7760_defconfig b/arch/sh/configs/edosk7760_defconfig
index 158006847ad6..14d4b35685a1 100644
--- a/arch/sh/configs/edosk7760_defconfig
+++ b/arch/sh/configs/edosk7760_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:20:09 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 16:55:48 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -59,6 +61,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -75,13 +78,11 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -92,7 +93,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -100,11 +100,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -121,6 +119,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -128,6 +130,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -191,7 +194,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -272,7 +274,6 @@ CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
# CONFIG_GUSA_RB is not set
@@ -298,11 +299,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -353,6 +361,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -368,8 +377,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -510,6 +519,7 @@ CONFIG_MII=y
# CONFIG_STNIC is not set
CONFIG_SMC91X=y
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -592,6 +602,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -632,8 +643,8 @@ CONFIG_I2C_SH7760=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -651,11 +662,11 @@ CONFIG_I2C_DEBUG_CHIP=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -664,9 +675,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -693,15 +707,16 @@ CONFIG_FB=m
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
# CONFIG_FB_BOOT_VESA_SUPPORT is not set
-CONFIG_FB_CFB_FILLRECT=m
-CONFIG_FB_CFB_COPYAREA=m
-CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -716,6 +731,7 @@ CONFIG_FB_SH_MOBILE_LCDC=m
# CONFIG_FB_SH7760 is not set
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -737,6 +753,7 @@ CONFIG_SND_PCM=y
# CONFIG_SND_SEQUENCER is not set
# CONFIG_SND_MIXER_OSS is not set
# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
# CONFIG_SND_SUPPORT_OLD_API is not set
# CONFIG_SND_VERBOSE_PROCFS is not set
@@ -753,6 +770,7 @@ CONFIG_SND_SOC=y
#
# SoC Audio support for SuperH
#
+CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
# CONFIG_SOUND_PRIME is not set
# CONFIG_HID_SUPPORT is not set
@@ -823,10 +841,7 @@ CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -950,6 +965,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -958,17 +974,25 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
@@ -978,7 +1002,9 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -994,7 +1020,11 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1077,6 +1107,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/hp6xx_defconfig b/arch/sh/configs/hp6xx_defconfig
index 1032b235f080..847a25106635 100644
--- a/arch/sh/configs/hp6xx_defconfig
+++ b/arch/sh/configs/hp6xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:23:53 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 16:56:55 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,7 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_SYS_SUPPORTS_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -70,12 +71,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -85,13 +84,11 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -108,6 +105,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
CONFIG_FREEZER=y
#
@@ -115,6 +116,7 @@ CONFIG_FREEZER=y
#
CONFIG_CPU_SH3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -178,7 +180,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -236,7 +237,6 @@ CONFIG_NR_ONCHIP_DMA_CHANNELS=4
#
CONFIG_HD6446X_SERIES=y
CONFIG_HD64461=y
-# CONFIG_HD64465 is not set
CONFIG_HD64461_IRQ=36
CONFIG_HD64461_IOBASE=0xb0000000
CONFIG_HD64461_ENABLER=y
@@ -275,7 +275,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
# Bus options
#
-CONFIG_ISA=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCCARD=y
# CONFIG_PCMCIA_DEBUG is not set
@@ -286,9 +285,6 @@ CONFIG_PCMCIA_IOCTL=y
#
# PC-card bridges
#
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_PROBE=y
#
# Executable file formats
@@ -301,13 +297,13 @@ CONFIG_BINFMT_ELF=y
#
# Power management options (EXPERIMENTAL)
#
-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_APM_EMULATION=y
+# CONFIG_CPU_IDLE is not set
# CONFIG_NET is not set
#
@@ -326,7 +322,6 @@ CONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
-# CONFIG_PNP is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
@@ -336,6 +331,7 @@ CONFIG_BLK_DEV=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -375,18 +371,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_SAS_LIBSAS is not set
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_T128 is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
# CONFIG_SCSI_DH is not set
@@ -395,10 +380,7 @@ CONFIG_ATA=y
CONFIG_SATA_PMP=y
CONFIG_ATA_SFF=y
# CONFIG_SATA_MV is not set
-# CONFIG_PATA_LEGACY is not set
# CONFIG_PATA_PCMCIA is not set
-# CONFIG_PATA_QDI is not set
-# CONFIG_PATA_WINBOND_VLB is not set
CONFIG_PATA_PLATFORM=y
# CONFIG_MD is not set
# CONFIG_PHONE is not set
@@ -438,11 +420,11 @@ CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
# CONFIG_TOUCHSCREEN_INEXIO is not set
# CONFIG_TOUCHSCREEN_MK712 is not set
CONFIG_TOUCHSCREEN_HP600=y
-# CONFIG_TOUCHSCREEN_HTCPEN is not set
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
@@ -484,11 +466,11 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=64
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
#
@@ -499,7 +481,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_CARDMAN_4040 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
-CONFIG_DEVPORT=y
# CONFIG_I2C is not set
# CONFIG_SPI is not set
# CONFIG_W1 is not set
@@ -508,11 +489,11 @@ CONFIG_DEVPORT=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -522,7 +503,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -552,11 +533,12 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -571,6 +553,7 @@ CONFIG_FB_HIT=y
CONFIG_FB_SH_MOBILE_LCDC=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
# CONFIG_LCD_ILI9320 is not set
@@ -587,7 +570,6 @@ CONFIG_BACKLIGHT_HP680=y
#
# Console display driver support
#
-# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
@@ -701,10 +683,7 @@ CONFIG_SYSFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -785,13 +764,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -807,11 +792,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -893,6 +882,7 @@ CONFIG_CRYPTO_MD5=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=y
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
index b82dfb4da3aa..d3bbbb037716 100644
--- a/arch/sh/configs/landisk_defconfig
+++ b/arch/sh/configs/landisk_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:25:51 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 16:58:46 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -76,7 +78,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -87,7 +88,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -95,11 +95,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -116,6 +114,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -123,6 +125,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -186,7 +189,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -285,6 +287,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
CONFIG_PCCARD=y
@@ -315,11 +318,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -401,6 +411,7 @@ CONFIG_ATALK=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -416,8 +427,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -462,6 +473,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -478,7 +490,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -508,6 +519,7 @@ CONFIG_BLK_DEV_AEC62XX=y
# 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
@@ -560,6 +572,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -573,6 +586,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -634,6 +649,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -649,7 +665,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -659,6 +674,7 @@ CONFIG_8139CP=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -687,6 +703,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -695,6 +712,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -791,6 +809,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -832,11 +851,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -846,7 +865,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -952,11 +971,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=m
CONFIG_HID_APPLE=m
CONFIG_HID_BELKIN=m
-CONFIG_HID_BRIGHT=m
CONFIG_HID_CHERRY=m
CONFIG_HID_CHICONY=m
CONFIG_HID_CYPRESS=m
-CONFIG_HID_DELL=m
CONFIG_HID_EZKEY=m
CONFIG_HID_GYRATION=m
CONFIG_HID_LOGITECH=m
@@ -964,12 +981,15 @@ CONFIG_HID_LOGITECH=m
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=m
CONFIG_HID_MONTEREY=m
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=m
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=m
CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -990,6 +1010,8 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1007,6 +1029,8 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -1017,11 +1041,11 @@ CONFIG_USB_PRINTER=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1119,6 +1143,7 @@ CONFIG_USB_SISUSBVGA_CON=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1192,10 +1217,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1302,14 +1324,20 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1325,6 +1353,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1408,6 +1437,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/lboxre2_defconfig b/arch/sh/configs/lboxre2_defconfig
index c3ecedfc1bc7..d5c5a1dbaa62 100644
--- a/arch/sh/configs/lboxre2_defconfig
+++ b/arch/sh/configs/lboxre2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:29:42 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:02:46 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -76,7 +78,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -87,7 +88,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -95,11 +95,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -116,6 +114,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -123,6 +125,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -186,7 +189,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -286,6 +288,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
CONFIG_PCCARD=y
@@ -315,11 +318,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -399,6 +409,7 @@ CONFIG_NETFILTER_ADVANCED=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -414,8 +425,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -459,6 +470,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -501,6 +513,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -514,6 +527,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -627,6 +642,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -642,7 +658,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -656,6 +671,7 @@ CONFIG_8139TOO_TUNE_TWISTER=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -684,6 +700,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -692,6 +709,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -787,6 +805,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -828,11 +847,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -842,7 +861,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -902,9 +921,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1007,10 +1027,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1100,14 +1117,20 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1123,6 +1146,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1206,6 +1230,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/magicpanelr2_defconfig b/arch/sh/configs/magicpanelr2_defconfig
index 499ed7204385..125d8019dc2f 100644
--- a/arch/sh/configs/magicpanelr2_defconfig
+++ b/arch/sh/configs/magicpanelr2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:32:23 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:03:37 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -58,6 +60,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -74,12 +77,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -90,7 +91,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -98,11 +98,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -119,6 +117,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -126,6 +128,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -189,7 +192,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -296,11 +298,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -351,6 +360,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -366,8 +376,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -483,6 +493,7 @@ CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -502,13 +513,33 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_STNIC is not set
# CONFIG_SMC91X is not set
-CONFIG_SMC911X=y
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -618,6 +649,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -627,17 +659,37 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -647,7 +699,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -778,10 +830,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -912,6 +961,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -920,16 +970,24 @@ CONFIG_FRAME_POINTER=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xa4430000
@@ -939,25 +997,9 @@ CONFIG_EARLY_PRINTK=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-CONFIG_SH_KGDB=y
-
-#
-# KGDB configuration options
-#
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
# CONFIG_MORE_COMPILE_OPTIONS is not set
-# CONFIG_KGDB_NMI is not set
-CONFIG_KGDB_SYSRQ=y
-
-#
-# Serial port setup
-#
-CONFIG_KGDB_DEFPORT=0
-CONFIG_KGDB_DEFBAUD=115200
-CONFIG_KGDB_DEFPARITY_N=y
-# CONFIG_KGDB_DEFPARITY_E is not set
-# CONFIG_KGDB_DEFPARITY_O is not set
-CONFIG_KGDB_DEFBITS_8=y
-# CONFIG_KGDB_DEFBITS_7 is not set
#
# Security options
@@ -972,6 +1014,7 @@ CONFIG_KGDB_DEFBITS_8=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig
index b8ada8ce98d9..5a1c0485a354 100644
--- a/arch/sh/configs/microdev_defconfig
+++ b/arch/sh/configs/microdev_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:37:41 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:06:47 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -72,12 +74,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -87,13 +87,11 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -110,6 +108,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -117,6 +119,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -186,7 +189,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -265,7 +267,6 @@ CONFIG_HZ=250
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
# CONFIG_GUSA_RB is not set
@@ -292,11 +293,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_PACKET is not set
# CONFIG_UNIX is not set
CONFIG_XFRM=y
@@ -351,6 +359,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -366,8 +375,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -400,12 +409,14 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -445,6 +456,7 @@ CONFIG_MII=y
# CONFIG_STNIC is not set
CONFIG_SMC91X=y
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -503,6 +515,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -530,11 +543,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -544,7 +557,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -588,7 +601,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -656,10 +669,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -761,13 +771,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -783,11 +799,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -869,6 +889,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig
index 30cac42f25e7..7758263514bc 100644
--- a/arch/sh/configs/migor_defconfig
+++ b/arch/sh/configs/migor_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Fri Oct 31 15:58:06 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:09:35 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -77,6 +79,7 @@ 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_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -89,18 +92,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -117,6 +117,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -127,6 +131,7 @@ CONFIG_CPU_SH4A=y
CONFIG_CPU_SH4AL_DSP=y
CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -196,7 +201,6 @@ CONFIG_SPARSEMEM_STATIC=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_MIGRATION is not set
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -299,11 +303,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -359,6 +370,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -375,8 +387,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -493,7 +505,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -536,6 +550,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
@@ -554,6 +569,7 @@ CONFIG_MII=y
# CONFIG_STNIC is not set
CONFIG_SMC91X=y
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -644,6 +660,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -684,8 +701,8 @@ CONFIG_I2C_SH_MOBILE=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -697,17 +714,39 @@ CONFIG_I2C_SH_MOBILE=y
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -716,10 +755,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -762,8 +804,11 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_SOC_CAMERA=y
# CONFIG_SOC_CAMERA_MT9M001 is not set
# CONFIG_SOC_CAMERA_MT9M111 is not set
+# CONFIG_SOC_CAMERA_MT9T031 is not set
# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
CONFIG_SOC_CAMERA_PLATFORM=y
+# CONFIG_SOC_CAMERA_OV772X is not set
CONFIG_VIDEO_SH_MOBILE_CEU=y
# CONFIG_RADIO_ADAPTERS is not set
# CONFIG_DAB is not set
@@ -806,7 +851,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB_GADGET_MUSB_HDRC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG_FILES is not set
@@ -872,6 +917,7 @@ CONFIG_RTC_DRV_RS5C372=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -948,10 +994,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1008,19 +1051,29 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000
CONFIG_EARLY_PRINTK=y
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1035,12 +1088,13 @@ CONFIG_CRYPTO=y
# Crypto core or helper
#
# CONFIG_CRYPTO_FIPS is not set
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1123,6 +1177,7 @@ CONFIG_CRYPTO_MANAGER=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig
index 2e65149e9502..65b01a9e5934 100644
--- a/arch/sh/configs/r7780mp_defconfig
+++ b/arch/sh/configs/r7780mp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 20:03:46 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:10:19 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -85,6 +87,7 @@ 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_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
@@ -96,7 +99,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -104,11 +106,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -125,6 +125,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -133,6 +137,7 @@ CONFIG_CLASSIC_RCU=y
CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -203,7 +208,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -284,7 +288,6 @@ CONFIG_KEXEC=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
#
@@ -302,6 +305,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
@@ -315,11 +319,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -382,6 +393,7 @@ CONFIG_LLC=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -398,8 +410,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -442,8 +454,10 @@ CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_93CX6=y
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -486,6 +500,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -499,6 +514,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -611,6 +628,7 @@ CONFIG_AX88796_93CX6=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -626,7 +644,6 @@ CONFIG_PCNET32=m
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -640,6 +657,7 @@ CONFIG_8139TOO_8129=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
CONFIG_VIA_RHINE=m
@@ -669,6 +687,7 @@ CONFIG_R8169=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -677,6 +696,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -771,6 +791,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -836,8 +857,8 @@ CONFIG_I2C_HIGHLANDER=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -861,6 +882,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
@@ -909,11 +931,11 @@ CONFIG_HWMON=y
CONFIG_THERMAL=y
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -922,9 +944,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -982,9 +1007,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1020,6 +1046,7 @@ CONFIG_RTC_DRV_RS5C372=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1106,10 +1133,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1228,6 +1252,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
@@ -1236,6 +1261,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1244,16 +1270,28 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
CONFIG_EARLY_PRINTK=y
@@ -1262,7 +1300,9 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1278,11 +1318,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1366,6 +1410,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig
index 043a8a509e09..8defaa5f13b9 100644
--- a/arch/sh/configs/r7785rp_defconfig
+++ b/arch/sh/configs/r7785rp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 16:25:30 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:14:41 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -13,9 +13,11 @@ CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_GENERIC_IRQ_PROBE=y
-# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
@@ -63,6 +65,7 @@ CONFIG_UID16=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -84,6 +87,7 @@ 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_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -97,7 +101,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -105,11 +108,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -126,6 +127,11 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
# CONFIG_CLASSIC_RCU is not set
+# CONFIG_TREE_RCU is not set
+CONFIG_PREEMPT_RCU=y
+CONFIG_RCU_TRACE=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_PREEMPT_RCU_TRACE=y
# CONFIG_FREEZER is not set
#
@@ -135,6 +141,7 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -211,7 +218,6 @@ CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -307,8 +313,6 @@ CONFIG_KEXEC=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-CONFIG_PREEMPT_RCU=y
-CONFIG_RCU_TRACE=y
CONFIG_GUSA=y
#
@@ -326,6 +330,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
@@ -339,11 +344,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=m
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -406,6 +418,7 @@ CONFIG_LLC=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -423,8 +436,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -467,8 +480,10 @@ CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_93CX6=y
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -511,6 +526,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -524,6 +540,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -636,6 +654,7 @@ CONFIG_AX88796_93CX6=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -671,6 +690,7 @@ CONFIG_R8169=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -679,6 +699,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -732,6 +753,7 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO is not set
# CONFIG_KEYBOARD_SH_KEYSC is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
@@ -773,6 +795,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -812,6 +835,7 @@ CONFIG_I2C_HELPER_AUTO=y
#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
+# CONFIG_I2C_GPIO is not set
CONFIG_I2C_HIGHLANDER=y
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_SH_MOBILE is not set
@@ -838,8 +862,8 @@ CONFIG_I2C_HIGHLANDER=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -851,6 +875,30 @@ CONFIG_I2C_HIGHLANDER=y
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+# CONFIG_GPIO_BT8XX is not set
+
+#
+# SPI GPIO expanders:
+#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
@@ -863,6 +911,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
@@ -911,11 +960,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -924,9 +973,13 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -954,15 +1007,16 @@ CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
# CONFIG_FB_BOOT_VESA_SUPPORT is not set
-CONFIG_FB_CFB_FILLRECT=m
-CONFIG_FB_CFB_COPYAREA=m
-CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -1000,6 +1054,7 @@ CONFIG_FB_CFB_IMAGEBLIT=m
CONFIG_FB_SH_MOBILE_LCDC=m
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1034,9 +1089,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1072,6 +1128,7 @@ CONFIG_RTC_DRV_RS5C372=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1158,10 +1215,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1291,6 +1345,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_KPROBES_SANITY_TEST is not set
@@ -1300,16 +1355,28 @@ CONFIG_FRAME_POINTER=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
CONFIG_EARLY_PRINTK=y
@@ -1318,7 +1385,9 @@ CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_4KSTACKS=y
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1334,11 +1403,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1422,6 +1495,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/rsk7201_defconfig b/arch/sh/configs/rsk7201_defconfig
index 014c18cbf46a..64ee69eef47c 100644
--- a/arch/sh/configs/rsk7201_defconfig
+++ b/arch/sh/configs/rsk7201_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc6
-# Mon Dec 8 14:48:02 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:19:04 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -77,6 +77,7 @@ CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_SLUB is not set
CONFIG_SLOB=y
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -87,18 +88,15 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -115,6 +113,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -185,7 +187,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -563,7 +564,6 @@ CONFIG_RTC_DRV_SH=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -606,10 +606,7 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -658,22 +655,28 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
#
# Tracers
#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -688,6 +691,7 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/rsk7203_defconfig b/arch/sh/configs/rsk7203_defconfig
index dcdef31cf19b..8d7a5972a86a 100644
--- a/arch/sh/configs/rsk7203_defconfig
+++ b/arch/sh/configs/rsk7203_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc6
-# Mon Dec 8 14:35:03 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:20:31 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -62,6 +62,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -81,6 +82,7 @@ CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_SLUB is not set
CONFIG_SLOB=y
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -91,18 +93,15 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -119,6 +118,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -189,7 +192,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -313,6 +315,8 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_PACKET is not set
# CONFIG_UNIX is not set
# CONFIG_NET_KEY is not set
@@ -361,6 +365,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -376,8 +381,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -509,13 +514,33 @@ CONFIG_NETDEVICES=y
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_STNIC is not set
# CONFIG_SMC91X is not set
-CONFIG_SMC911X=y
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -611,6 +636,26 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_TCG_TPM is not set
# CONFIG_I2C is not set
# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
@@ -685,11 +730,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -697,12 +740,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -847,7 +893,6 @@ CONFIG_RTC_DRV_SH=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -890,10 +935,7 @@ CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -961,6 +1003,7 @@ CONFIG_DEBUG_OBJECTS=y
# CONFIG_DEBUG_OBJECTS_SELFTEST is not set
# CONFIG_DEBUG_OBJECTS_FREE is not set
# CONFIG_DEBUG_OBJECTS_TIMERS is not set
+CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -970,6 +1013,7 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_LOCK_STAT is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
@@ -978,6 +1022,7 @@ CONFIG_DEBUG_WRITECOUNT=y
# CONFIG_DEBUG_MEMORY_INIT is not set
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_SG=y
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -986,9 +1031,12 @@ CONFIG_FRAME_POINTER=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
#
# Tracers
@@ -997,9 +1045,13 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xfffe8000
@@ -1008,6 +1060,9 @@ CONFIG_DEBUG_BOOTMEM=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_IRQSTACKS is not set
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1022,6 +1077,7 @@ CONFIG_DEBUG_STACK_USAGE=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig
index 7d2a9e88838b..d6680f4382c2 100644
--- a/arch/sh/configs/rts7751r2d1_defconfig
+++ b/arch/sh/configs/rts7751r2d1_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:44:36 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:23:15 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -77,6 +79,7 @@ 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_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -89,18 +92,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -117,6 +117,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -124,6 +128,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -187,7 +192,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -293,6 +297,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCCARD is not set
@@ -308,11 +313,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -365,6 +377,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -381,8 +394,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -426,6 +439,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -468,6 +482,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -481,6 +496,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -593,6 +610,7 @@ CONFIG_MII=y
# CONFIG_SMC91X is not set
# CONFIG_ENC28J60 is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -608,7 +626,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -622,6 +639,7 @@ CONFIG_8139TOO=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -650,6 +668,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -658,6 +677,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -755,6 +775,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -777,7 +798,7 @@ CONFIG_SPI_SH_SCI=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
@@ -805,11 +826,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -819,7 +840,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_MFD_SM501=y
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -852,11 +873,12 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -895,6 +917,7 @@ CONFIG_FB_SH_MOBILE_LCDC=m
CONFIG_FB_SM501=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1031,11 +1054,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1043,12 +1064,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1069,6 +1093,8 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1084,6 +1110,8 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -1094,11 +1122,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1151,6 +1179,7 @@ CONFIG_USB_LIBUSUAL=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1176,6 +1205,7 @@ CONFIG_RTC_INTF_DEV=y
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
CONFIG_RTC_DRV_R9701=y
# CONFIG_RTC_DRV_RS5C348 is not set
@@ -1254,10 +1284,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1343,19 +1370,29 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
CONFIG_EARLY_PRINTK=y
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1371,6 +1408,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1454,6 +1492,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig
index f680d3eecdfb..3fca10e24833 100644
--- a/arch/sh/configs/rts7751r2dplus_defconfig
+++ b/arch/sh/configs/rts7751r2dplus_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:47:39 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:26:10 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -77,6 +79,7 @@ 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_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -89,18 +92,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -117,6 +117,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -124,6 +128,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -187,7 +192,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -293,6 +297,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCCARD is not set
@@ -308,11 +313,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -365,6 +377,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -381,8 +394,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -426,6 +439,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -468,6 +482,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -481,6 +496,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -593,6 +610,7 @@ CONFIG_MII=y
# CONFIG_SMC91X is not set
# CONFIG_ENC28J60 is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -608,7 +626,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -622,6 +639,7 @@ CONFIG_8139TOO=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -650,6 +668,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -658,6 +677,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -755,6 +775,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -777,7 +798,7 @@ CONFIG_SPI_SH_SCI=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
@@ -805,11 +826,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -819,7 +840,7 @@ CONFIG_SSB_POSSIBLE=y
CONFIG_MFD_SM501=y
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -852,11 +873,12 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -895,6 +917,7 @@ CONFIG_FB_SH_MOBILE_LCDC=m
CONFIG_FB_SM501=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1031,11 +1054,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1043,12 +1064,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1069,6 +1093,8 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1084,6 +1110,8 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -1094,11 +1122,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1151,6 +1179,7 @@ CONFIG_USB_LIBUSUAL=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1176,6 +1205,7 @@ CONFIG_RTC_INTF_DEV=y
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
CONFIG_RTC_DRV_R9701=y
# CONFIG_RTC_DRV_RS5C348 is not set
@@ -1254,10 +1284,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1343,19 +1370,29 @@ CONFIG_FRAME_WARN=1024
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
CONFIG_EARLY_PRINTK=y
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1371,6 +1408,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1454,6 +1492,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/sdk7780_defconfig b/arch/sh/configs/sdk7780_defconfig
index 543287b97a6a..5d6b06755ae7 100644
--- a/arch/sh/configs/sdk7780_defconfig
+++ b/arch/sh/configs/sdk7780_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:53:22 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:26:40 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -59,6 +61,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -81,7 +84,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -92,7 +94,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -100,11 +101,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
CONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -121,6 +120,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -129,6 +132,7 @@ CONFIG_CLASSIC_RCU=y
CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -199,7 +203,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -282,7 +285,6 @@ CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
#
@@ -300,6 +302,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCI_LEGACY is not set
CONFIG_PCI_DEBUG=y
@@ -334,11 +337,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -434,6 +444,7 @@ CONFIG_NET_SCHED=y
# CONFIG_NET_SCH_GRED is not set
# CONFIG_NET_SCH_DSMARK is not set
# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
#
# Classification
@@ -449,6 +460,7 @@ CONFIG_NET_SCHED=y
# CONFIG_NET_EMATCH is not set
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -464,8 +476,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -516,6 +528,7 @@ CONFIG_IDE=y
#
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
+CONFIG_IDE_ATAPI=y
# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_IDE_GD=y
CONFIG_IDE_GD_ATA=y
@@ -525,7 +538,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -553,6 +565,7 @@ CONFIG_BLK_DEV_GENERIC=y
# 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
@@ -619,6 +632,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -742,6 +757,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
CONFIG_SMC91X=y
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -826,6 +842,7 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_APPLETOUCH is not set
@@ -875,6 +892,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_PRINTER is not set
@@ -905,11 +923,11 @@ CONFIG_POWER_SUPPLY=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
CONFIG_SSB=y
CONFIG_SSB_SPROM=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
@@ -929,7 +947,7 @@ CONFIG_SSB_DRIVER_PCICORE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -957,15 +975,16 @@ CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
# CONFIG_FB_BOOT_VESA_SUPPORT is not set
-CONFIG_FB_CFB_FILLRECT=m
-CONFIG_FB_CFB_COPYAREA=m
-CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -1003,6 +1022,7 @@ CONFIG_FB_CFB_IMAGEBLIT=m
CONFIG_FB_SH_MOBILE_LCDC=m
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -1054,11 +1074,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -1066,12 +1084,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1092,6 +1113,8 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1106,6 +1129,8 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -1116,11 +1141,11 @@ CONFIG_USB_PRINTER=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1176,6 +1201,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
@@ -1260,10 +1286,7 @@ CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1392,6 +1415,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1400,17 +1424,25 @@ CONFIG_DEBUG_INFO=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
@@ -1419,7 +1451,9 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1435,7 +1469,11 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1519,6 +1557,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index 25717ff26ca9..e5b55b6f002d 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 18:57:39 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:31:27 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
# CONFIG_GENERIC_TIME is not set
# CONFIG_GENERIC_CLOCKEVENTS is not set
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -69,6 +71,7 @@ CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -84,11 +87,11 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
# CONFIG_SLAB is not set
# CONFIG_SLUB is not set
CONFIG_SLOB=y
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -99,7 +102,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -107,11 +109,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -128,6 +128,11 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
# CONFIG_CLASSIC_RCU is not set
+# CONFIG_TREE_RCU is not set
+CONFIG_PREEMPT_RCU=y
+CONFIG_RCU_TRACE=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_PREEMPT_RCU_TRACE=y
# CONFIG_FREEZER is not set
#
@@ -136,6 +141,7 @@ CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CPU_SH2=y
CONFIG_CPU_SH2A=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
CONFIG_CPU_SUBTYPE_SH7206=y
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -197,7 +203,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -281,8 +286,6 @@ CONFIG_KEXEC=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-CONFIG_PREEMPT_RCU=y
-CONFIG_RCU_TRACE=y
CONFIG_GUSA=y
#
@@ -296,10 +299,6 @@ CONFIG_CMDLINE="console=ttySC3,115200 ignore_loglevel earlyprintk=serial"
#
# Bus options
#
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -312,11 +311,19 @@ CONFIG_BINFMT_ZFLAT=y
CONFIG_BINFMT_SHARED_FLAT=y
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -372,6 +379,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -387,8 +395,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -500,6 +508,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_MISC_DEVICES=y
CONFIG_EEPROM_93CX6=y
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -526,6 +535,7 @@ CONFIG_MII=y
# CONFIG_STNIC is not set
CONFIG_SMC91X=y
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -598,11 +608,11 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -612,7 +622,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -732,10 +742,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=y
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -812,6 +819,7 @@ CONFIG_DEBUG_PREEMPT=y
# CONFIG_LOCK_STAT is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
@@ -820,6 +828,7 @@ CONFIG_DEBUG_VM=y
# CONFIG_DEBUG_MEMORY_INIT is not set
CONFIG_DEBUG_LIST=y
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
@@ -827,20 +836,35 @@ CONFIG_FRAME_POINTER=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_DEBUG_BOOTMEM is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_IRQSTACKS is not set
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -856,7 +880,11 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -890,7 +918,7 @@ CONFIG_CRYPTO_ALGAPI=y
#
# Digest
#
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=y
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
@@ -939,6 +967,7 @@ CONFIG_CRYPTO_LZO=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
CONFIG_CRC16=y
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig
index be246f381507..390052577031 100644
--- a/arch/sh/configs/se7343_defconfig
+++ b/arch/sh/configs/se7343_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc6
-# Thu Dec 4 16:40:25 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:33:53 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -78,7 +80,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -88,7 +89,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -96,11 +96,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -117,6 +115,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -190,7 +192,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -280,7 +281,6 @@ CONFIG_CMDLINE="console=ttySC0,115200"
#
# Bus options
#
-# CONFIG_CF_ENABLER is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -291,11 +291,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -347,6 +354,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -362,8 +370,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -661,8 +669,8 @@ CONFIG_I2C_SH_MOBILE=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -693,6 +701,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
@@ -743,11 +752,13 @@ CONFIG_V4L_USB_DRIVERS=y
# CONFIG_USB_VIDEO_CLASS is not set
CONFIG_USB_GSPCA=m
# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
# CONFIG_USB_GSPCA_CONEX is not set
# CONFIG_USB_GSPCA_ETOMS is not set
# CONFIG_USB_GSPCA_FINEPIX is not set
# CONFIG_USB_GSPCA_MARS is not set
# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
# CONFIG_USB_GSPCA_PAC207 is not set
# CONFIG_USB_GSPCA_PAC7311 is not set
# CONFIG_USB_GSPCA_SONIXB is not set
@@ -786,6 +797,7 @@ CONFIG_RADIO_ADAPTERS=y
# CONFIG_USB_DSBR is not set
# CONFIG_USB_SI470X is not set
# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
# CONFIG_DAB is not set
#
@@ -797,15 +809,16 @@ CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
# CONFIG_FB_BOOT_VESA_SUPPORT is not set
-CONFIG_FB_CFB_FILLRECT=m
-CONFIG_FB_CFB_COPYAREA=m
-CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -881,11 +894,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -893,12 +904,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
# CONFIG_THRUSTMASTER_FF is not set
# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
@@ -997,7 +1011,6 @@ CONFIG_UIO=y
# CONFIG_UIO_SMX is not set
# CONFIG_UIO_SERCOS3 is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# File systems
@@ -1051,10 +1064,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1138,11 +1148,12 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
CONFIG_EARLY_SCIF_CONSOLE=y
CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe00000
CONFIG_EARLY_PRINTK=y
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1158,6 +1169,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1240,6 +1252,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig
index db9cacd7c4e7..932b0235b1de 100644
--- a/arch/sh/configs/se7619_defconfig
+++ b/arch/sh/configs/se7619_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:03:29 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:36:46 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
# CONFIG_GENERIC_TIME is not set
# CONFIG_GENERIC_CLOCKEVENTS is not set
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -61,12 +63,10 @@ CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_AIO=y
# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
@@ -74,12 +74,10 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -96,6 +94,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -103,6 +105,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH2=y
CONFIG_CPU_SUBTYPE_SH7619=y
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -164,7 +167,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -244,7 +246,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
# Bus options
#
-# CONFIG_CF_ENABLER is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
#
@@ -256,6 +257,12 @@ CONFIG_BINFMT_ZFLAT=y
# CONFIG_BINFMT_SHARED_FLAT is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
# CONFIG_NET is not set
#
@@ -359,6 +366,7 @@ CONFIG_BLK_DEV=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -439,11 +447,11 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -453,7 +461,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -506,7 +514,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -557,10 +565,7 @@ CONFIG_PROC_SYSCTL=y
# CONFIG_SYSFS is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -602,12 +607,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -621,6 +633,7 @@ CONFIG_HAVE_FTRACE=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig
index d88190fdd7c1..8574d6eb00a3 100644
--- a/arch/sh/configs/se7705_defconfig
+++ b/arch/sh/configs/se7705_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:04:52 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:37:50 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -68,12 +70,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -83,17 +83,14 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -110,6 +107,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -117,6 +118,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -180,7 +182,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -258,7 +259,6 @@ CONFIG_HZ=250
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
# CONFIG_GUSA_RB is not set
@@ -272,10 +272,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
# Bus options
#
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
# CONFIG_ARCH_SUPPORTS_MSI is not set
#
@@ -285,11 +281,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -345,6 +348,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -360,8 +364,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -465,6 +469,7 @@ CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -491,6 +496,7 @@ CONFIG_NET_ETHERNET=y
CONFIG_STNIC=y
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -583,6 +589,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
@@ -609,11 +616,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -623,7 +630,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -677,7 +684,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -734,10 +741,7 @@ CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -806,13 +810,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -827,6 +837,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -909,6 +920,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7712_defconfig b/arch/sh/configs/se7712_defconfig
index 869ab1737deb..e31ea84f116d 100644
--- a/arch/sh/configs/se7712_defconfig
+++ b/arch/sh/configs/se7712_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:08:12 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:40:12 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -15,6 +15,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -55,6 +57,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -71,12 +74,10 @@ CONFIG_EVENTFD=y
# CONFIG_SHMEM is not set
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -87,18 +88,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -115,6 +113,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -122,6 +124,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -185,7 +188,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -277,10 +279,6 @@ CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1"
#
# Bus options
#
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -291,11 +289,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -376,6 +381,7 @@ CONFIG_NET_SCH_TBF=y
CONFIG_NET_SCH_GRED=y
CONFIG_NET_SCH_DSMARK=y
CONFIG_NET_SCH_NETEM=y
+# CONFIG_NET_SCH_DRR is not set
#
# Classification
@@ -394,6 +400,7 @@ CONFIG_NET_CLS_FW=y
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_CLS_IND=y
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -410,8 +417,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -518,6 +525,7 @@ CONFIG_BLK_DEV=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -560,6 +568,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
@@ -591,6 +600,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
CONFIG_NET_ETHERNET=y
@@ -600,6 +612,7 @@ CONFIG_MII=y
CONFIG_SH_ETH=y
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -658,6 +671,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
@@ -672,11 +686,11 @@ CONFIG_HW_RANDOM=m
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -686,7 +700,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -730,7 +744,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -748,6 +762,7 @@ CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
# CONFIG_LEDS_TRIGGER_TIMER is not set
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
@@ -809,10 +824,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -902,6 +914,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -910,16 +923,24 @@ CONFIG_FRAME_POINTER=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_DEBUG_BOOTMEM is not set
@@ -927,7 +948,9 @@ CONFIG_HAVE_FTRACE=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_DUMP_CODE is not set
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -943,11 +966,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1030,6 +1058,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7721_defconfig b/arch/sh/configs/se7721_defconfig
index b52be14074d8..ad1bace3ad46 100644
--- a/arch/sh/configs/se7721_defconfig
+++ b/arch/sh/configs/se7721_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:12:06 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:43:33 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -15,6 +15,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -59,6 +61,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -75,12 +78,10 @@ CONFIG_EVENTFD=y
# CONFIG_SHMEM is not set
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -91,18 +92,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -119,6 +117,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -126,6 +128,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -189,7 +192,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -280,10 +282,6 @@ CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda2"
#
# Bus options
#
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -294,11 +292,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -379,6 +384,7 @@ CONFIG_NET_SCH_TBF=y
CONFIG_NET_SCH_GRED=y
CONFIG_NET_SCH_DSMARK=y
CONFIG_NET_SCH_NETEM=y
+# CONFIG_NET_SCH_DRR is not set
#
# Classification
@@ -397,6 +403,7 @@ CONFIG_NET_CLS_FW=y
# CONFIG_NET_CLS_ACT is not set
CONFIG_NET_CLS_IND=y
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -413,8 +420,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -522,6 +529,7 @@ CONFIG_BLK_DEV=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -673,6 +681,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
@@ -686,11 +695,11 @@ CONFIG_UNIX98_PTYS=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -700,7 +709,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -750,11 +759,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -762,12 +769,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -788,19 +798,21 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -811,11 +823,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -883,6 +895,7 @@ CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
# CONFIG_LEDS_TRIGGER_TIMER is not set
# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_RTC_CLASS is not set
@@ -947,10 +960,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1063,6 +1073,7 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1071,16 +1082,24 @@ CONFIG_FRAME_POINTER=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_DEBUG_BOOTMEM is not set
@@ -1088,7 +1107,9 @@ CONFIG_HAVE_FTRACE=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_DUMP_CODE is not set
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1104,11 +1125,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1191,6 +1217,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig
index e6df51f098f0..abb189a1d314 100644
--- a/arch/sh/configs/se7722_defconfig
+++ b/arch/sh/configs/se7722_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:15:10 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:46:59 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -75,13 +77,11 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -93,7 +93,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -101,11 +100,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -122,6 +119,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -132,6 +133,7 @@ CONFIG_CPU_SH4A=y
CONFIG_CPU_SH4AL_DSP=y
CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -207,7 +209,6 @@ CONFIG_SPARSEMEM_STATIC=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -287,7 +288,6 @@ CONFIG_KEXEC=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
#
@@ -300,10 +300,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
# Bus options
#
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_PCCARD is not set
@@ -314,11 +310,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -371,6 +374,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -386,8 +390,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -420,6 +424,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -462,6 +467,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
@@ -485,6 +491,7 @@ CONFIG_MII=y
# CONFIG_STNIC is not set
CONFIG_SMC91X=y
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -577,6 +584,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -604,11 +612,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -618,7 +626,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -672,7 +680,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -774,10 +782,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -831,14 +836,20 @@ CONFIG_DEBUG_FS=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -854,6 +865,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -936,6 +948,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig
index a577099c3247..ac874f63a625 100644
--- a/arch/sh/configs/se7750_defconfig
+++ b/arch/sh/configs/se7750_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:17:29 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:49:22 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -72,12 +74,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -88,18 +88,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -116,6 +113,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -123,6 +124,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -186,7 +188,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -278,10 +279,6 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000
#
# Bus options
#
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
# CONFIG_ARCH_SUPPORTS_MSI is not set
#
@@ -291,11 +288,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -352,6 +356,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -367,8 +372,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -469,6 +474,7 @@ CONFIG_BLK_DEV=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -481,7 +487,6 @@ CONFIG_IDE_GD_ATA=y
# CONFIG_IDE_GD_ATAPI is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -530,6 +535,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
@@ -548,6 +554,7 @@ CONFIG_NET_ETHERNET=y
CONFIG_STNIC=y
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -610,6 +617,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -645,11 +653,11 @@ CONFIG_WATCHDOG=y
# CONFIG_SOFT_WATCHDOG is not set
CONFIG_SH_WDT=y
# CONFIG_SH_WDT_MMAP is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -659,7 +667,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -703,7 +711,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -761,10 +769,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -847,13 +852,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -869,6 +880,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -951,6 +963,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig
index d99a6bdf410f..f54ae056f177 100644
--- a/arch/sh/configs/se7751_defconfig
+++ b/arch/sh/configs/se7751_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:21:12 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:51:47 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -72,12 +74,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -88,18 +88,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -116,6 +113,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -123,6 +124,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -186,7 +188,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -280,7 +281,6 @@ CONFIG_CMDLINE="console=ttySC1,38400"
#
# Bus options
#
-# CONFIG_CF_ENABLER is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
#
@@ -290,11 +290,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -370,6 +377,7 @@ CONFIG_IP_NF_QUEUE=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -385,8 +393,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -490,6 +498,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -516,6 +525,7 @@ CONFIG_MII=y
# CONFIG_STNIC is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -570,6 +580,7 @@ CONFIG_DEVKMEM=y
#
# CONFIG_SERIAL_SH_SCI is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -604,11 +615,11 @@ CONFIG_WATCHDOG=y
#
# CONFIG_SOFT_WATCHDOG is not set
# CONFIG_SH_WDT is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -618,7 +629,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -662,7 +673,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -722,10 +733,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -787,13 +795,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -809,6 +823,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -891,6 +906,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/se7780_defconfig b/arch/sh/configs/se7780_defconfig
index ad95b80bb198..7504978e8747 100644
--- a/arch/sh/configs/se7780_defconfig
+++ b/arch/sh/configs/se7780_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:27:30 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:53:50 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -74,7 +76,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -84,18 +85,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
#
@@ -111,6 +109,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -119,6 +121,7 @@ CONFIG_CLASSIC_RCU=y
CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -185,7 +188,6 @@ CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -274,11 +276,11 @@ CONFIG_CMDLINE="console=ttySC0.115200 root=/dev/sda1"
#
# Bus options
#
-# CONFIG_CF_ENABLER is not set
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -294,6 +296,7 @@ CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -349,6 +352,7 @@ CONFIG_IPV6=y
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -363,8 +367,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
#
@@ -533,6 +537,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -569,11 +575,13 @@ CONFIG_SATA_SIL=y
# 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 is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
# CONFIG_PATA_EFAR is not set
# CONFIG_ATA_GENERIC is not set
# CONFIG_PATA_HPT366 is not set
@@ -585,10 +593,15 @@ CONFIG_SATA_SIL=y
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_PDC_OLD 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_PLATFORM is not set
@@ -627,6 +640,9 @@ CONFIG_SMSC_PHY=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
@@ -639,6 +655,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
CONFIG_SMC91X=y
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -654,7 +671,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -663,6 +679,7 @@ CONFIG_NET_PCI=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -754,6 +771,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
@@ -779,11 +797,11 @@ CONFIG_HWMON=y
CONFIG_THERMAL=y
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -793,7 +811,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -821,15 +839,16 @@ CONFIG_FB=y
CONFIG_FIRMWARE_EDID=y
# CONFIG_FB_DDC is not set
# CONFIG_FB_BOOT_VESA_SUPPORT is not set
-CONFIG_FB_CFB_FILLRECT=m
-CONFIG_FB_CFB_COPYAREA=m
-CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -865,6 +884,7 @@ CONFIG_FB_CFB_IMAGEBLIT=m
CONFIG_FB_SH_MOBILE_LCDC=m
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -912,11 +932,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -924,12 +942,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -949,6 +970,7 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -974,11 +996,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1094,10 +1116,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_HFSPLUS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_CRAMFS=y
@@ -1188,13 +1207,19 @@ CONFIG_DEBUG_FS=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1210,6 +1235,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
@@ -1288,6 +1314,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig
index 95f0f5d5b631..04bde1e96965 100644
--- a/arch/sh/configs/sh03_defconfig
+++ b/arch/sh/configs/sh03_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:31:54 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 17:56:46 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -79,6 +81,7 @@ 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_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
@@ -91,7 +94,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -99,11 +101,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -120,6 +120,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -127,6 +131,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -190,7 +195,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -268,7 +272,6 @@ CONFIG_HZ=250
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
# CONFIG_GUSA_RB is not set
@@ -284,14 +287,11 @@ CONFIG_CMDLINE="console=ttySC1,115200 mem=64M root=/dev/nfs"
#
# Bus options
#
-CONFIG_CF_ENABLER=y
-CONFIG_CF_AREA5=y
-# CONFIG_CF_AREA6 is not set
-CONFIG_CF_BASE_ADDR=0xb4000000
CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCCARD is not set
@@ -307,11 +307,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -369,6 +376,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -384,8 +392,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -427,6 +435,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -441,7 +450,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=m
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
CONFIG_BLK_DEV_IDETAPE=m
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -466,6 +474,7 @@ CONFIG_IDE_PROC_FS=y
# 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
@@ -519,6 +528,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -532,6 +542,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -583,6 +595,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -598,7 +611,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -608,6 +620,7 @@ CONFIG_8139CP=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -636,6 +649,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -644,6 +658,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -734,6 +749,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -782,11 +798,11 @@ CONFIG_SH_WDT=m
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -796,7 +812,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -856,9 +872,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -883,6 +900,7 @@ CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
@@ -930,10 +948,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1048,21 +1063,31 @@ CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_EARLY_PRINTK is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1078,11 +1103,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1166,6 +1195,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig
index 9a768b28adcb..1b869f452ad1 100644
--- a/arch/sh/configs/sh7710voipgw_defconfig
+++ b/arch/sh/configs/sh7710voipgw_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:35:18 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:00:31 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -74,12 +76,10 @@ CONFIG_EVENTFD=y
# CONFIG_SHMEM is not set
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -89,7 +89,6 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -97,11 +96,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -118,6 +115,10 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -125,6 +126,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -188,7 +190,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -287,11 +288,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -378,6 +386,7 @@ CONFIG_NET_SCH_CBQ=y
# CONFIG_NET_SCH_GRED is not set
# CONFIG_NET_SCH_DSMARK is not set
# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
#
# Classification
@@ -398,6 +407,7 @@ CONFIG_NET_CLS_U32=y
# CONFIG_NET_CLS_ACT is not set
# CONFIG_NET_CLS_IND is not set
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -413,8 +423,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -519,6 +529,7 @@ CONFIG_BLK_DEV=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -546,6 +557,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_SH_ETH is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -638,11 +650,11 @@ CONFIG_HW_RANDOM=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -652,7 +664,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -706,7 +718,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -763,10 +775,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -828,13 +837,19 @@ CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -850,6 +865,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -932,6 +948,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/sh7763rdp_defconfig b/arch/sh/configs/sh7763rdp_defconfig
index 6a77f691fb87..ba33aca75af6 100644
--- a/arch/sh/configs/sh7763rdp_defconfig
+++ b/arch/sh/configs/sh7763rdp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:37:12 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:02:28 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -79,11 +81,11 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=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_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -96,18 +98,15 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -124,6 +123,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -132,6 +135,7 @@ CONFIG_CLASSIC_RCU=y
CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -199,7 +203,6 @@ CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -297,11 +300,19 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -357,6 +368,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -373,8 +385,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -529,6 +541,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
@@ -555,6 +568,9 @@ CONFIG_PHYLIB=y
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
CONFIG_NET_ETHERNET=y
@@ -564,6 +580,7 @@ CONFIG_MII=y
CONFIG_SH_ETH=y
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -655,6 +672,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -670,11 +688,11 @@ CONFIG_HW_RANDOM=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -684,7 +702,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -737,6 +755,7 @@ CONFIG_FB_BOTH_ENDIAN=y
CONFIG_FB_SH7760=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -781,19 +800,21 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
CONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -804,11 +825,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -897,6 +918,7 @@ CONFIG_EXT3_FS_XATTR=y
# CONFIG_EXT3_FS_SECURITY is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
@@ -942,10 +964,7 @@ CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1038,20 +1057,30 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1067,6 +1096,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1149,6 +1179,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
diff --git a/arch/sh/configs/sh7785lcr_defconfig b/arch/sh/configs/sh7785lcr_defconfig
index 07e33c285b93..1d63628df6f6 100644
--- a/arch/sh/configs/sh7785lcr_defconfig
+++ b/arch/sh/configs/sh7785lcr_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:49:23 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:05:18 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
@@ -86,7 +88,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -98,7 +99,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -106,11 +106,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -127,6 +125,10 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -136,6 +138,7 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -206,7 +209,6 @@ CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -285,7 +287,6 @@ CONFIG_KEXEC=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
#
@@ -302,6 +303,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
@@ -315,11 +317,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -380,6 +389,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -396,8 +406,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -757,6 +767,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -823,8 +834,8 @@ CONFIG_I2C_PCA_PLATFORM=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -842,11 +853,11 @@ CONFIG_I2C_PCA_PLATFORM=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -855,9 +866,12 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_CORE is not set
CONFIG_MFD_SM501=y
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -889,11 +903,12 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
@@ -932,6 +947,7 @@ CONFIG_FB_SH_MOBILE_LCDC=m
CONFIG_FB_SM501=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
@@ -976,11 +992,9 @@ CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
-CONFIG_HID_BRIGHT=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
-CONFIG_HID_DELL=y
CONFIG_HID_EZKEY=y
CONFIG_HID_GYRATION=y
CONFIG_HID_LOGITECH=y
@@ -988,12 +1002,15 @@ CONFIG_HID_LOGITECH=y
# CONFIG_LOGIRUMBLEPAD2_FF is not set
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MONTEREY=y
+# CONFIG_HID_NTRIG is not set
CONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not set
CONFIG_HID_PETALYNX=y
CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
CONFIG_THRUSTMASTER_FF=m
CONFIG_ZEROPLUS_FF=m
CONFIG_USB_SUPPORT=y
@@ -1014,6 +1031,8 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1031,6 +1050,8 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
CONFIG_USB_R8A66597_HCD=y
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -1041,11 +1062,11 @@ CONFIG_USB_R8A66597_HCD=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1100,6 +1121,7 @@ CONFIG_USB_TEST=m
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1135,6 +1157,7 @@ CONFIG_RTC_DRV_RS5C372=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1220,10 +1243,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1353,6 +1373,7 @@ CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1361,17 +1382,25 @@ CONFIG_DEBUG_PREEMPT=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_DEBUG_BOOTMEM is not set
@@ -1379,7 +1408,9 @@ CONFIG_HAVE_FTRACE=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_DUMP_CODE is not set
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1395,11 +1426,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1482,6 +1517,7 @@ CONFIG_CRYPTO_DES=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/shmin_defconfig b/arch/sh/configs/shmin_defconfig
index e2b38a334976..8ba10e1e08cd 100644
--- a/arch/sh/configs/shmin_defconfig
+++ b/arch/sh/configs/shmin_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:52:59 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:09:00 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -15,6 +15,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -65,12 +67,10 @@ CONFIG_EVENTFD=y
# CONFIG_SHMEM is not set
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
# CONFIG_SLAB is not set
# CONFIG_SLUB is not set
CONFIG_SLOB=y
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -78,12 +78,10 @@ CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=1
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -100,6 +98,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -107,6 +109,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -170,7 +173,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -268,11 +270,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
@@ -327,6 +336,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -342,8 +352,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -448,6 +458,7 @@ CONFIG_BLK_DEV_LOOP=y
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -474,6 +485,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_STNIC is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -532,6 +544,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -547,11 +560,11 @@ CONFIG_HW_RANDOM=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -561,7 +574,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -605,7 +618,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -660,10 +673,7 @@ CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -723,14 +733,20 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
CONFIG_EARLY_PRINTK=y
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -745,6 +761,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -826,6 +843,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig
index ae5cbe237fff..ed90a7e81099 100644
--- a/arch/sh/configs/shx3_defconfig
+++ b/arch/sh/configs/shx3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Tue Oct 21 12:16:25 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:10:57 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -18,6 +18,8 @@ CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_LOCKBREAK=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_SMP=y
CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_STACKTRACE_SUPPORT=y
@@ -79,6 +81,7 @@ CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -95,11 +98,11 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
# CONFIG_SLAB is not set
# CONFIG_SLUB is not set
CONFIG_SLOB=y
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
@@ -113,7 +116,6 @@ CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -121,12 +123,10 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -143,6 +143,11 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
# CONFIG_CLASSIC_RCU is not set
+# CONFIG_TREE_RCU is not set
+CONFIG_PREEMPT_RCU=y
+CONFIG_RCU_TRACE=y
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_PREEMPT_RCU_TRACE=y
CONFIG_FREEZER=y
#
@@ -152,6 +157,7 @@ CONFIG_CPU_SH4=y
CONFIG_CPU_SH4A=y
CONFIG_CPU_SHX3=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -230,7 +236,6 @@ CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -323,8 +328,6 @@ CONFIG_NR_CPUS=4
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-CONFIG_PREEMPT_RCU=y
-CONFIG_RCU_TRACE=y
#
# Boot options
@@ -347,11 +350,19 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
CONFIG_BINFMT_MISC=y
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_PACKET is not set
# CONFIG_UNIX is not set
CONFIG_XFRM=y
@@ -424,6 +435,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -479,7 +491,9 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -522,6 +536,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
@@ -546,6 +561,7 @@ CONFIG_MII=y
CONFIG_SMC91X=y
# CONFIG_ENC28J60 is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -613,6 +629,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -653,8 +670,8 @@ CONFIG_I2C_HELPER_AUTO=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -678,7 +695,7 @@ CONFIG_SPI_MASTER=y
#
# SPI Protocol Masters
#
-# CONFIG_SPI_AT25 is not set
+# CONFIG_EEPROM_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_W1 is not set
@@ -699,11 +716,11 @@ CONFIG_WATCHDOG=y
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -715,6 +732,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_WM8400 is not set
# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -763,15 +781,17 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_SL811_HCD is not set
CONFIG_USB_R8A66597_HCD=m
+# CONFIG_USB_HWA_HCD is not set
# CONFIG_USB_GADGET_MUSB_HDRC is not set
#
@@ -783,11 +803,11 @@ CONFIG_USB_R8A66597_HCD=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
# CONFIG_USB_STORAGE is not set
# CONFIG_USB_LIBUSUAL is not set
@@ -890,12 +910,14 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
@@ -981,10 +1003,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1049,6 +1068,7 @@ CONFIG_DEBUG_PREEMPT=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
@@ -1057,6 +1077,7 @@ CONFIG_DEBUG_VM=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_KPROBES_SANITY_TEST is not set
@@ -1066,16 +1087,28 @@ CONFIG_FRAME_POINTER=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
CONFIG_SH_STANDARD_BIOS=y
# CONFIG_EARLY_SCIF_CONSOLE is not set
CONFIG_EARLY_PRINTK=y
@@ -1083,7 +1116,9 @@ CONFIG_EARLY_PRINTK=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+CONFIG_DUMP_CODE=y
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1099,6 +1134,7 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1181,6 +1217,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/snapgear_defconfig b/arch/sh/configs/snapgear_defconfig
index b4ca5110958f..98377e502650 100644
--- a/arch/sh/configs/snapgear_defconfig
+++ b/arch/sh/configs/snapgear_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:55:03 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:14:08 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -76,7 +78,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
@@ -86,13 +87,11 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -109,6 +108,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -116,6 +119,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -179,7 +183,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -282,6 +285,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
@@ -292,11 +296,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_PACKET is not set
# CONFIG_UNIX is not set
# CONFIG_NET_KEY is not set
@@ -342,6 +353,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -357,8 +369,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_OLD_REGULATORY is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -515,6 +527,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -530,7 +543,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -544,6 +556,7 @@ CONFIG_8139TOO_PIO=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -624,6 +637,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -641,11 +655,11 @@ CONFIG_DEVPORT=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -655,7 +669,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -689,6 +703,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -746,10 +761,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -801,13 +813,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -822,6 +840,7 @@ CONFIG_HAVE_FTRACE=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/systemh_defconfig b/arch/sh/configs/systemh_defconfig
index 1711f0f70d72..72703bf57afa 100644
--- a/arch/sh/configs/systemh_defconfig
+++ b/arch/sh/configs/systemh_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:56:48 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:15:56 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -68,12 +70,10 @@ CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -84,7 +84,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -92,11 +91,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -113,6 +110,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -120,6 +121,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -183,7 +185,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -264,7 +265,6 @@ CONFIG_HZ=250
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
# CONFIG_GUSA_RB is not set
@@ -288,6 +288,12 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
# CONFIG_NET is not set
#
@@ -314,6 +320,7 @@ CONFIG_BLK_DEV_RAM_SIZE=1024
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -360,6 +367,7 @@ CONFIG_DEVKMEM=y
#
# CONFIG_SERIAL_SH_SCI is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -387,11 +395,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -401,7 +409,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -444,7 +452,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
@@ -501,10 +509,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -546,13 +551,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -567,6 +578,7 @@ CONFIG_HAVE_FTRACE=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
index ea3c5e838fc3..01fc1defb33b 100644
--- a/arch/sh/configs/titan_defconfig
+++ b/arch/sh/configs/titan_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27
-# Wed Oct 22 19:58:12 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:17:19 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_PCI=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -79,7 +81,6 @@ CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_IOREMAP_PROT=y
@@ -90,7 +91,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -98,11 +98,9 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -119,6 +117,10 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -126,6 +128,7 @@ CONFIG_CLASSIC_RCU=y
#
CONFIG_CPU_SH4=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -189,7 +192,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -293,6 +295,7 @@ CONFIG_PCI=y
CONFIG_SH_PCIDMA_NONCOHERENT=y
CONFIG_PCI_AUTO=y
CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+# CONFIG_PCIEPORTBUS is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
@@ -309,11 +312,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -507,6 +517,7 @@ CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
+# CONFIG_NET_SCH_DRR is not set
CONFIG_NET_SCH_INGRESS=m
#
@@ -543,6 +554,7 @@ CONFIG_NET_ACT_PEDIT=m
# CONFIG_NET_ACT_SKBEDIT is not set
CONFIG_NET_CLS_IND=y
CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
#
# Network testing
@@ -560,12 +572,8 @@ CONFIG_WIRELESS=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_CRYPT_TKIP=y
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -695,6 +703,7 @@ CONFIG_MISC_DEVICES=y
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -738,6 +747,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -751,6 +761,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -807,6 +819,9 @@ CONFIG_CICADA_PHY=m
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
@@ -818,6 +833,7 @@ CONFIG_MII=y
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
@@ -833,7 +849,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -847,6 +862,7 @@ CONFIG_8139_OLD_RX_RESET=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -875,6 +891,7 @@ CONFIG_NETDEV_1000=y
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -883,6 +900,7 @@ CONFIG_NETDEV_10000=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
@@ -1002,6 +1020,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
@@ -1055,11 +1074,11 @@ CONFIG_SH_WDT=m
# USB-based Watchdog Cards
#
# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1069,7 +1088,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_WM8400 is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -1145,6 +1164,8 @@ CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
@@ -1162,6 +1183,8 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
@@ -1172,11 +1195,11 @@ CONFIG_USB_PRINTER=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1273,6 +1296,7 @@ CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
@@ -1379,10 +1403,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLBFS is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1530,6 +1551,7 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_FRAME_POINTER is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1537,16 +1559,24 @@ CONFIG_SCHED_DEBUG=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
# CONFIG_DEBUG_BOOTMEM is not set
@@ -1554,7 +1584,9 @@ CONFIG_HAVE_FTRACE=y
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_4KSTACKS is not set
# CONFIG_IRQSTACKS is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_DUMP_CODE is not set
+# CONFIG_SH_NO_BSS_INIT is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1570,11 +1602,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1659,6 +1696,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=m
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/configs/ul2_defconfig b/arch/sh/configs/ul2_defconfig
index 9afff67d9ff2..27f968a959f8 100644
--- a/arch/sh/configs/ul2_defconfig
+++ b/arch/sh/configs/ul2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc2
-# Tue Oct 28 17:35:17 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 9 18:22:53 2009
#
CONFIG_SUPERH=y
CONFIG_SUPERH32=y
@@ -16,6 +16,8 @@ CONFIG_GENERIC_IRQ_PROBE=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_ARCH_SUSPEND_POSSIBLE is not set
+# CONFIG_ARCH_HIBERNATION_POSSIBLE is not set
CONFIG_SYS_SUPPORTS_NUMA=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
@@ -80,7 +82,6 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
-# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
@@ -92,7 +93,6 @@ CONFIG_HAVE_CLK=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
@@ -100,11 +100,9 @@ CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
@@ -121,6 +119,10 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_DEFAULT_NOOP=y
CONFIG_DEFAULT_IOSCHED="noop"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
@@ -131,6 +133,7 @@ CONFIG_CPU_SH4A=y
CONFIG_CPU_SH4AL_DSP=y
CONFIG_CPU_SHX2=y
# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7201 is not set
# CONFIG_CPU_SUBTYPE_SH7203 is not set
# CONFIG_CPU_SUBTYPE_SH7206 is not set
# CONFIG_CPU_SUBTYPE_SH7263 is not set
@@ -206,7 +209,6 @@ CONFIG_SPARSEMEM_STATIC=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_MIGRATION is not set
-# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=2
@@ -283,7 +285,6 @@ CONFIG_KEXEC=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
CONFIG_GUSA=y
#
@@ -307,11 +308,18 @@ CONFIG_BINFMT_ELF=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+# CONFIG_CPU_IDLE is not set
CONFIG_NET=y
#
# Networking options
#
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -367,6 +375,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -380,10 +389,12 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_PHONET is not set
CONFIG_WIRELESS=y
CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
CONFIG_NL80211=y
# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
CONFIG_MAC80211=y
#
@@ -397,11 +408,6 @@ CONFIG_MAC80211_RC_DEFAULT="pid"
# CONFIG_MAC80211_MESH is not set
# CONFIG_MAC80211_LEDS is not set
# CONFIG_MAC80211_DEBUG_MENU is not set
-CONFIG_IEEE80211=m
-CONFIG_IEEE80211_DEBUG=y
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -510,6 +516,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -552,6 +559,7 @@ CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_DH is not set
CONFIG_ATA=y
@@ -575,6 +583,7 @@ CONFIG_MII=y
# CONFIG_STNIC is not set
# CONFIG_SMC91X is not set
# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -714,11 +723,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -728,6 +737,7 @@ CONFIG_SSB_POSSIBLE=y
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
@@ -785,7 +795,6 @@ CONFIG_USB_MON=y
#
# CONFIG_USB_C67X00_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_SL811_HCD is not set
CONFIG_USB_R8A66597_HCD=y
# CONFIG_SUPERH_ON_CHIP_R8A66597 is not set
@@ -800,11 +809,11 @@ CONFIG_USB_R8A66597_HCD=y
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -937,10 +946,7 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -1046,13 +1052,19 @@ CONFIG_FRAME_WARN=1024
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FTRACE=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_SH_STANDARD_BIOS is not set
# CONFIG_EARLY_SCIF_CONSOLE is not set
-# CONFIG_SH_KGDB is not set
+# CONFIG_MORE_COMPILE_OPTIONS is not set
#
# Security options
@@ -1068,11 +1080,15 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_CRYPTD is not set
@@ -1155,6 +1171,7 @@ CONFIG_CRYPTO_HW=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
# CONFIG_CRC_T10DIF is not set
diff --git a/arch/sh/drivers/pci/ops-cayman.c b/arch/sh/drivers/pci/ops-cayman.c
index 5ccf9ea3a9de..38ef76207af6 100644
--- a/arch/sh/drivers/pci/ops-cayman.c
+++ b/arch/sh/drivers/pci/ops-cayman.c
@@ -5,11 +5,6 @@
#include <cpu/irq.h>
#include "pci-sh5.h"
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
- return (((pin - 1) + slot) % 4) + 1;
-}
-
int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int result = -1;
@@ -42,7 +37,7 @@ int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
while (dev->bus->number > 0) {
slot = path[i].slot = PCI_SLOT(dev->devfn);
- pin = path[i].pin = bridge_swizzle(pin, slot);
+ pin = path[i].pin = pci_swizzle_interrupt_pin(dev, pin);
dev = dev->bus->self;
i++;
if (i > 3) panic("PCI path to root bus too long!\n");
@@ -56,7 +51,7 @@ int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
if ((slot < 3) || (i == 0)) {
/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
swizzle now. */
- result = IRQ_INTA + bridge_swizzle(pin, slot) - 1;
+ result = IRQ_INTA + pci_swizzle_interrupt_pin(dev, pin) - 1;
} else {
i--;
slot = path[i].slot;
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index d3839e609aac..e36c7b870861 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -21,26 +21,6 @@
#include <linux/init.h>
#include <asm/io.h>
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
- return (((pin - 1) + slot) % 4) + 1;
-}
-
-static u8 __init simple_swizzle(struct pci_dev *dev, u8 *pinp)
-{
- u8 pin = *pinp;
-
- while (dev->bus->parent) {
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
- /* Move up the chain of bridges. */
- dev = dev->bus->self;
- }
- *pinp = pin;
-
- /* The slot is the slot of the last bridge. */
- return PCI_SLOT(dev->devfn);
-}
-
static int __init pcibios_init(void)
{
struct pci_channel *p;
@@ -61,7 +41,7 @@ static int __init pcibios_init(void)
busno = bus->subordinate + 1;
}
- pci_fixup_irqs(simple_swizzle, pcibios_map_platform_irq);
+ pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
return 0;
}
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index c043ef003028..6327ffbb1992 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -7,16 +7,15 @@
*
*/
-typedef struct { volatile int counter; } atomic_t;
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm/system.h>
#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) ((v)->counter = (i))
-#include <linux/compiler.h>
-#include <asm/system.h>
-
#if defined(CONFIG_GUSA_RB)
#include <asm/atomic-grb.h>
#elif defined(CONFIG_CPU_SH4A)
diff --git a/arch/sh/include/asm/byteorder.h b/arch/sh/include/asm/byteorder.h
index f5fa0653ebc6..db2f5d7cb17d 100644
--- a/arch/sh/include/asm/byteorder.h
+++ b/arch/sh/include/asm/byteorder.h
@@ -1,68 +1,10 @@
#ifndef __ASM_SH_BYTEORDER_H
#define __ASM_SH_BYTEORDER_H
-/*
- * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2000, 2001 Paolo Alberelli
- */
-#include <linux/compiler.h>
-#include <linux/types.h>
-
#ifdef __LITTLE_ENDIAN__
-# define __LITTLE_ENDIAN
-#else
-# define __BIG_ENDIAN
-#endif
-
-#define __SWAB_64_THRU_32__
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
-{
- __asm__(
-#ifdef __SH5__
- "byterev %0, %0\n\t"
- "shari %0, 32, %0"
-#else
- "swap.b %0, %0\n\t"
- "swap.w %0, %0\n\t"
- "swap.b %0, %0"
-#endif
- : "=r" (x)
- : "0" (x));
-
- return x;
-}
-#define __arch_swab32 __arch_swab32
-
-static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
-{
- __asm__(
-#ifdef __SH5__
- "byterev %0, %0\n\t"
- "shari %0, 32, %0"
+#include <linux/byteorder/little_endian.h>
#else
- "swap.b %0, %0"
+#include <linux/byteorder/big_endian.h>
#endif
- : "=r" (x)
- : "0" (x));
-
- return x;
-}
-#define __arch_swab16 __arch_swab16
-
-static inline __u64 __arch_swab64(__u64 val)
-{
- union {
- struct { __u32 a,b; } s;
- __u64 u;
- } v, w;
- v.u = val;
- w.s.b = __arch_swab32(v.s.a);
- w.s.a = __arch_swab32(v.s.b);
- return w.u;
-}
-#define __arch_swab64 __arch_swab64
-
-#include <linux/byteorder.h>
#endif /* __ASM_SH_BYTEORDER_H */
diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h
index fdcb93bc6d11..6c43625bb1a5 100644
--- a/arch/sh/include/asm/mmu.h
+++ b/arch/sh/include/asm/mmu.h
@@ -9,7 +9,6 @@ typedef struct {
mm_context_id_t id;
void *vdso;
#else
- struct vm_list_struct *vmlist;
unsigned long end_brk;
#endif
#ifdef CONFIG_BINFMT_ELF_FDPIC
diff --git a/arch/sh/include/asm/posix_types_32.h b/arch/sh/include/asm/posix_types_32.h
index 0a3d2f54ab27..2172732c55c8 100644
--- a/arch/sh/include/asm/posix_types_32.h
+++ b/arch/sh/include/asm/posix_types_32.h
@@ -39,14 +39,10 @@ typedef long long __kernel_loff_t;
#endif
typedef struct {
-#if defined(__KERNEL__) || defined(__USE_ALL)
int val[2];
-#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
- int __val[2];
-#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
} __kernel_fsid_t;
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+#if defined(__KERNEL__)
#undef __FD_SET
static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
@@ -117,6 +113,6 @@ static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
}
}
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#endif /* defined(__KERNEL__) */
#endif /* __ASM_SH_POSIX_TYPES_H */
diff --git a/arch/sh/include/asm/posix_types_64.h b/arch/sh/include/asm/posix_types_64.h
index 0620317a6f0f..f83e9bd463d8 100644
--- a/arch/sh/include/asm/posix_types_64.h
+++ b/arch/sh/include/asm/posix_types_64.h
@@ -48,14 +48,10 @@ typedef long long __kernel_loff_t;
#endif
typedef struct {
-#if defined(__KERNEL__) || defined(__USE_ALL)
int val[2];
-#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
- int __val[2];
-#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
} __kernel_fsid_t;
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+#if defined(__KERNEL__)
#undef __FD_SET
static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
@@ -126,6 +122,6 @@ static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
}
}
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#endif /* defined(__KERNEL__) */
#endif /* __ASM_SH64_POSIX_TYPES_H */
diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h
index 85b660c17eb0..c24e9c6a1736 100644
--- a/arch/sh/include/asm/smp.h
+++ b/arch/sh/include/asm/smp.h
@@ -31,7 +31,7 @@ enum {
};
void smp_message_recv(unsigned int msg);
-void smp_timer_broadcast(cpumask_t mask);
+void smp_timer_broadcast(const struct cpumask *mask);
void local_timer_interrupt(void);
void local_timer_setup(unsigned int cpu);
diff --git a/arch/sh/include/asm/swab.h b/arch/sh/include/asm/swab.h
new file mode 100644
index 000000000000..e69315935107
--- /dev/null
+++ b/arch/sh/include/asm/swab.h
@@ -0,0 +1,60 @@
+#ifndef __ASM_SH_SWAB_H
+#define __ASM_SH_SWAB_H
+
+/*
+ * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 2000, 2001 Paolo Alberelli
+ */
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#define __SWAB_64_THRU_32__
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+ __asm__(
+#ifdef __SH5__
+ "byterev %0, %0\n\t"
+ "shari %0, 32, %0"
+#else
+ "swap.b %0, %0\n\t"
+ "swap.w %0, %0\n\t"
+ "swap.b %0, %0"
+#endif
+ : "=r" (x)
+ : "0" (x));
+
+ return x;
+}
+#define __arch_swab32 __arch_swab32
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
+{
+ __asm__(
+#ifdef __SH5__
+ "byterev %0, %0\n\t"
+ "shari %0, 32, %0"
+#else
+ "swap.b %0, %0"
+#endif
+ : "=r" (x)
+ : "0" (x));
+
+ return x;
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __u64 __arch_swab64(__u64 val)
+{
+ union {
+ struct { __u32 a,b; } s;
+ __u64 u;
+ } v, w;
+ v.u = val;
+ w.s.b = __arch_swab32(v.s.a);
+ w.s.a = __arch_swab32(v.s.b);
+ return w.u;
+}
+#define __arch_swab64 __arch_swab64
+
+#endif /* __ASM_SH_SWAB_H */
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h
index 104c5e686106..8b30200305c3 100644
--- a/arch/sh/include/asm/syscalls_32.h
+++ b/arch/sh/include/asm/syscalls_32.h
@@ -36,9 +36,9 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs);
-asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7,
- struct pt_regs __regs);
+asmlinkage int sys_sh_pipe(unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7,
+ struct pt_regs __regs);
asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char __user *buf,
size_t count, long dummy, loff_t pos);
asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char __user *buf,
diff --git a/arch/sh/include/asm/topology.h b/arch/sh/include/asm/topology.h
index 95f0085e098a..066f0fba590e 100644
--- a/arch/sh/include/asm/topology.h
+++ b/arch/sh/include/asm/topology.h
@@ -5,7 +5,6 @@
/* sched_domains SD_NODE_INIT for sh machines */
#define SD_NODE_INIT (struct sched_domain) { \
- .span = CPU_MASK_NONE, \
.parent = NULL, \
.child = NULL, \
.groups = NULL, \
@@ -33,6 +32,7 @@
#define parent_node(node) ((void)(node),0)
#define node_to_cpumask(node) ((void)node, cpu_online_map)
+#define cpumask_of_node(node) ((void)node, cpu_online_mask)
#define node_to_first_cpu(node) ((void)(node),0)
#define pcibus_to_node(bus) ((void)(bus), -1)
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 0623e377f488..4ff4dc64520c 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -112,6 +112,34 @@ static struct platform_device veu_device = {
.num_resources = ARRAY_SIZE(veu_resources),
};
+static struct uio_info jpu_platform_data = {
+ .name = "JPU",
+ .version = "0",
+ .irq = 27,
+};
+
+static struct resource jpu_resources[] = {
+ [0] = {
+ .name = "JPU",
+ .start = 0xfea00000,
+ .end = 0xfea102d3,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device jpu_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 2,
+ .dev = {
+ .platform_data = &jpu_platform_data,
+ },
+ .resource = jpu_resources,
+ .num_resources = ARRAY_SIZE(jpu_resources),
+};
+
static struct plat_sci_port sci_platform_data[] = {
{
.mapbase = 0xffe00000,
@@ -152,6 +180,7 @@ static struct platform_device *sh7343_devices[] __initdata = {
&sci_device,
&vpu_device,
&veu_device,
+ &jpu_device,
};
static int __init sh7343_devices_setup(void)
@@ -160,9 +189,11 @@ static int __init sh7343_devices_setup(void)
clk_always_enable("xymem0"); /* XYMEM */
clk_always_enable("veu0"); /* VEU */
clk_always_enable("vpu0"); /* VPU */
+ clk_always_enable("jpu0"); /* JPU */
platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
+ platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20);
return platform_add_devices(sh7343_devices,
ARRAY_SIZE(sh7343_devices));
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 50cf6838ec41..5146afc156e0 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -158,7 +158,7 @@ static struct resource jpu_resources[] = {
[0] = {
.name = "JPU",
.start = 0xfea00000,
- .end = 0xfea102d0,
+ .end = 0xfea102d3,
.flags = IORESOURCE_MEM,
},
[1] = {
diff --git a/arch/sh/kernel/init_task.c b/arch/sh/kernel/init_task.c
index b151a25cb14d..80c35ff71d56 100644
--- a/arch/sh/kernel/init_task.c
+++ b/arch/sh/kernel/init_task.c
@@ -7,7 +7,6 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct pt_regs fake_swapper_regs;
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index a7e5f2e74bac..c90c7e5e5fee 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -520,7 +520,6 @@ asmlinkage int sys_execve(char *ufilename, char **uargv,
int error;
char *filename;
- lock_kernel();
filename = getname((char __user *)ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
@@ -537,7 +536,6 @@ asmlinkage int sys_execve(char *ufilename, char **uargv,
}
putname(filename);
out:
- unlock_kernel();
return error;
}
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index 3c5ad1660bbc..8f4027412614 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -31,12 +31,6 @@
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
-cpumask_t cpu_possible_map;
-EXPORT_SYMBOL(cpu_possible_map);
-
-cpumask_t cpu_online_map;
-EXPORT_SYMBOL(cpu_online_map);
-
static inline void __init smp_store_cpu_info(unsigned int cpu)
{
struct sh_cpuinfo *c = cpu_data + cpu;
@@ -190,11 +184,11 @@ void arch_send_call_function_single_ipi(int cpu)
plat_send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE);
}
-void smp_timer_broadcast(cpumask_t mask)
+void smp_timer_broadcast(const struct cpumask *mask)
{
int cpu;
- for_each_cpu_mask(cpu, mask)
+ for_each_cpu(cpu, mask)
plat_send_ipi(cpu, SMP_MSG_TIMER);
}
diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c
index dbba1e1833d4..63ba12836eae 100644
--- a/arch/sh/kernel/sys_sh32.c
+++ b/arch/sh/kernel/sys_sh32.c
@@ -22,7 +22,7 @@
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way Unix traditionally does this, though.
*/
-asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
+asmlinkage int sys_sh_pipe(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 0af693e65764..e67c1733e1b9 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -58,7 +58,7 @@ ENTRY(sys_call_table)
.long sys_mkdir
.long sys_rmdir /* 40 */
.long sys_dup
- .long sys_pipe
+ .long sys_sh_pipe
.long sys_times
.long sys_ni_syscall /* old prof syscall holder */
.long sys_brk /* 45 */
@@ -105,7 +105,7 @@ ENTRY(sys_call_table)
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 0b436aa3cad7..557cb91f5caf 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -109,7 +109,7 @@ sys_call_table:
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/sh/kernel/timers/timer-broadcast.c b/arch/sh/kernel/timers/timer-broadcast.c
index c2317635230f..96e8eaea1e62 100644
--- a/arch/sh/kernel/timers/timer-broadcast.c
+++ b/arch/sh/kernel/timers/timer-broadcast.c
@@ -51,7 +51,7 @@ void __cpuinit local_timer_setup(unsigned int cpu)
clk->mult = 1;
clk->set_mode = dummy_timer_set_mode;
clk->broadcast = smp_timer_broadcast;
- clk->cpumask = cpumask_of_cpu(cpu);
+ clk->cpumask = cpumask_of(cpu);
clockevents_register_device(clk);
}
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 3c61ddd4d43e..0db3f9510336 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -263,7 +263,7 @@ static int tmu_timer_init(void)
tmu0_clockevent.min_delta_ns =
clockevent_delta2ns(1, &tmu0_clockevent);
- tmu0_clockevent.cpumask = cpumask_of_cpu(0);
+ tmu0_clockevent.cpumask = cpumask_of(0);
clockevents_register_device(&tmu0_clockevent);
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index 88807a2aacc3..60dcf87ed019 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -13,6 +13,7 @@
*/
#include <linux/kernel.h>
#include <linux/ptrace.h>
+#include <linux/hardirq.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/module.h>
@@ -124,20 +125,18 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs,
* - userspace errors just cause EFAULT to be returned, resulting in SEGV
* - kernel/userspace interfaces cause a jump to an appropriate handler
* - other kernel errors are bad
- * - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault
*/
-static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
+static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
{
if (!user_mode(regs)) {
const struct exception_table_entry *fixup;
fixup = search_exception_tables(regs->pc);
if (fixup) {
regs->pc = fixup->fixup;
- return 0;
+ return;
}
die(str, regs, err);
}
- return -EFAULT;
}
static inline void sign_extend(unsigned int count, unsigned char *dst)
@@ -313,7 +312,8 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
/* Argh. Address not only misaligned but also non-existent.
* Raise an EFAULT and see if it's trapped
*/
- return die_if_no_fixup("Fault in unaligned fixup", regs, 0);
+ die_if_no_fixup("Fault in unaligned fixup", regs, 0);
+ return -EFAULT;
}
/*
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 6cbef8caeb56..3edf297c829b 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -311,7 +311,8 @@ int arch_add_memory(int nid, u64 start, u64 size)
pgdat = NODE_DATA(nid);
/* We only have ZONE_NORMAL, so this is easy.. */
- ret = __add_pages(pgdat->node_zones + ZONE_NORMAL, start_pfn, nr_pages);
+ ret = __add_pages(nid, pgdat->node_zones + ZONE_NORMAL,
+ start_pfn, nr_pages);
if (unlikely(ret))
printk("%s: Failed, __add_pages() == %d\n", __func__, ret);
diff --git a/arch/sh/mm/ioremap_64.c b/arch/sh/mm/ioremap_64.c
index 6e0be24d26e2..31e1bb5effbe 100644
--- a/arch/sh/mm/ioremap_64.c
+++ b/arch/sh/mm/ioremap_64.c
@@ -71,9 +71,9 @@ void *__ioremap(unsigned long phys_addr, unsigned long size,
* Ok, go for it..
*/
area = get_vm_area(size, VM_IOREMAP);
- pr_debug("Get vm_area returns %p addr %p\n",area,area->addr);
if (!area)
return NULL;
+ pr_debug("Get vm_area returns %p addr %p\n", area, area->addr);
area->phys_addr = phys_addr;
addr = area->addr;
if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 0a94d9c9cde1..c3ea215334f6 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -4,6 +4,17 @@
mainmenu "Linux/SPARC Kernel Configuration"
+config 64BIT
+ bool "64-bit kernel" if ARCH = "sparc"
+ default ARCH = "sparc64"
+ help
+ SPARC is a family of RISC microprocessors designed and marketed by
+ Sun Microsystems, incorporated. They are very widely found in Sun
+ workstations and clones.
+
+ Say yes to build a 64-bit kernel - formerly known as sparc64
+ Say no to build a 32-bit kernel - formerly known as sparc
+
config SPARC
bool
default y
@@ -15,27 +26,17 @@ config SPARC
select RTC_CLASS
select RTC_DRV_M48T59
-# Identify this as a Sparc32 build
config SPARC32
- bool
- default y if ARCH = "sparc"
- help
- SPARC is a family of RISC microprocessors designed and marketed by
- Sun Microsystems, incorporated. They are very widely found in Sun
- workstations and clones. This port covers the original 32-bit SPARC;
- it is old and stable and usually considered one of the "big three"
- along with the Intel and Alpha ports. The UltraLinux project
- maintains both the SPARC32 and SPARC64 ports; its web page is
- available at <http://www.ultralinux.org/>.
+ def_bool !64BIT
config SPARC64
- bool
- default y if ARCH = "sparc64"
+ def_bool 64BIT
select ARCH_SUPPORTS_MSI
select HAVE_FUNCTION_TRACER
select HAVE_KRETPROBES
select HAVE_KPROBES
select HAVE_LMB
+ select HAVE_SYSCALL_WRAPPERS
select USE_GENERIC_SMP_HELPERS if SMP
select RTC_DRV_CMOS
select RTC_DRV_BQ4802
@@ -53,9 +54,6 @@ config BITS
default 32 if SPARC32
default 64 if SPARC64
-config 64BIT
- def_bool y if SPARC64
-
config GENERIC_TIME
bool
default y if SPARC64
@@ -188,14 +186,6 @@ config ARCH_MAY_HAVE_PC_FDC
bool
default y
-config ARCH_HAS_ILOG2_U32
- bool
- default n
-
-config ARCH_HAS_ILOG2_U64
- bool
- default n
-
config EMULATED_CMPXCHG
bool
default y if SPARC32
@@ -442,26 +432,6 @@ config SERIAL_CONSOLE
endmenu
menu "Bus options (PCI etc.)"
-config ISA
- bool
- help
- ISA is found on Espresso only and is not supported currently.
-
-config ISAPNP
- bool
- help
- ISAPNP is not supported
-
-config EISA
- bool
- help
- EISA is not supported.
-
-config MCA
- bool
- help
- MCA is not supported.
-
config SBUS
bool
default y
diff --git a/arch/sparc/configs/sparc32_defconfig b/arch/sparc/configs/sparc32_defconfig
index 2e3a149ea0e7..09ab46e4c59d 100644
--- a/arch/sparc/configs/sparc32_defconfig
+++ b/arch/sparc/configs/sparc32_defconfig
@@ -1,15 +1,21 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25
-# Tue Apr 29 01:28:58 2008
+# Linux kernel version: 2.6.28
+# Thu Jan 8 16:45:44 2009
#
+# CONFIG_64BIT is not set
+CONFIG_SPARC=y
+CONFIG_SPARC32=y
+# CONFIG_SPARC64 is not set
+CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc32_defconfig"
+CONFIG_BITS=32
+CONFIG_AUDIT_ARCH=y
CONFIG_MMU=y
CONFIG_HIGHMEM=y
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
-CONFIG_HZ=100
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -66,31 +72,30 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
CONFIG_SLAB=y
# CONFIG_SLUB is not set
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
CONFIG_HAVE_OPROFILE=y
-# CONFIG_HAVE_KPROBES is not set
-# CONFIG_HAVE_KRETPROBES is not set
-CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
@@ -105,59 +110,73 @@ CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_FREEZER is not set
#
-# General machine setup
+# Processor type and features
#
# CONFIG_SMP is not set
-CONFIG_SPARC=y
-CONFIG_SPARC32=y
-CONFIG_SBUS=y
-CONFIG_SBUSCHAR=y
-CONFIG_SERIAL_CONSOLE=y
-CONFIG_SUN_AUXIO=y
-CONFIG_SUN_IO=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_EMULATED_CMPXCHG=y
-CONFIG_SUN_PM=y
-# CONFIG_SUN4 is not set
-CONFIG_PCI=y
-CONFIG_PCI_SYSCALL=y
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-CONFIG_PCI_LEGACY=y
-# CONFIG_PCI_DEBUG is not set
-# CONFIG_NO_DMA is not set
-CONFIG_SUN_OPENPROMFS=m
-# CONFIG_SPARC_LED is not set
-CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_MISC=m
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_SUN_PM=y
+# CONFIG_SPARC_LED is not set
+CONFIG_SERIAL_CONSOLE=y
#
-# Networking
+# Bus options (PCI etc.)
#
+CONFIG_SBUS=y
+CONFIG_SBUSCHAR=y
+CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCCARD is not set
+CONFIG_SUN_OPENPROMFS=m
+CONFIG_SPARC32_PCI=y
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -166,6 +185,7 @@ CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
CONFIG_NET_KEY=m
# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
@@ -221,6 +241,7 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -231,6 +252,7 @@ CONFIG_IPV6_TUNNEL=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -241,14 +263,14 @@ CONFIG_NET_PKTGEN=m
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -262,7 +284,9 @@ CONFIG_NET_PKTGEN=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
@@ -286,12 +310,15 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
# CONFIG_BLK_DEV_XIP is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -335,6 +362,7 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -348,6 +376,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -367,6 +397,7 @@ CONFIG_SCSI_QLOGICPTI=m
# CONFIG_SCSI_DEBUG is not set
CONFIG_SCSI_SUNESP=y
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
@@ -374,11 +405,14 @@ CONFIG_SCSI_SUNESP=y
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
@@ -402,14 +436,16 @@ CONFIG_SUNQE=m
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
# CONFIG_NET_PCI is not set
# CONFIG_B44 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
-# CONFIG_E1000E is not set
-# CONFIG_E1000E_ENABLED is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
# CONFIG_MYRI_SBUS is not set
@@ -425,18 +461,25 @@ CONFIG_NETDEV_1000=y
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
# CONFIG_MLX4_CORE is not set
# CONFIG_TEHUTI is not set
# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
# CONFIG_TR is not set
#
@@ -445,6 +488,10 @@ CONFIG_NETDEV_10000=y
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -492,9 +539,11 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_SERIAL=m
# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
@@ -516,15 +565,18 @@ CONFIG_SERIO_LIBPS2=m
# Character devices
#
CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_NOZOMI is not set
#
# Serial drivers
#
+# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
@@ -540,23 +592,20 @@ CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_CONSOLE_POLL=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
-CONFIG_JS_RTC=m
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
CONFIG_DEVPORT=y
# CONFIG_I2C is not set
-
-#
-# SPI support
-#
# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
@@ -577,25 +626,38 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
# CONFIG_VIDEO_DEV is not set
# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
# CONFIG_DAB is not set
#
@@ -616,15 +678,17 @@ CONFIG_SSB_POSSIBLE=y
#
# CONFIG_PROM_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
# CONFIG_HIDRAW is not set
+# CONFIG_HID_PID is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
@@ -632,32 +696,71 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_USB is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+CONFIG_RTC_DRV_M48T59=y
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# Misc Linux/SPARC drivers
#
CONFIG_SUN_OPENPROMIO=m
-CONFIG_SUN_MOSTEK_RTC=m
-# CONFIG_SUN_BPP is not set
-# CONFIG_SUN_VIDEOPIX is not set
# CONFIG_TADPOLE_TS102_UCTRL is not set
# CONFIG_SUN_JSFLASH is not set
#
-# Unix98 PTY support
-#
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -666,11 +769,12 @@ CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
+# CONFIG_EXT4_FS is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS 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_OCFS2_FS is not set
CONFIG_DNOTIFY=y
@@ -702,14 +806,12 @@ CONFIG_ISO9660_FS=m
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
# CONFIG_TMPFS is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -720,6 +822,7 @@ CONFIG_SYSFS=y
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
CONFIG_ROMFS_FS=m
@@ -729,13 +832,13 @@ CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=m
-# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_SUNRPC_REGISTER_V4 is not set
CONFIG_RPCSEC_GSS_KRB5=m
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -806,9 +909,12 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
@@ -822,37 +928,59 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
-CONFIG_KGDB=y
CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_TESTS=y
# CONFIG_KGDB_TESTS_ON_BOOT is not set
# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_STACK_DEBUG is not set
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set
@@ -890,6 +1018,10 @@ CONFIG_CRYPTO_CRC32C=m
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
@@ -921,15 +1053,21 @@ CONFIG_CRYPTO_TWOFISH_COMMON=m
#
CONFIG_CRYPTO_DEFLATE=y
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig
index 05d19a3e590f..ade49941def2 100644
--- a/arch/sparc/configs/sparc64_defconfig
+++ b/arch/sparc/configs/sparc64_defconfig
@@ -1,27 +1,27 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28-rc4
-# Mon Nov 10 12:35:09 2008
+# Linux kernel version: 2.6.28
+# Fri Jan 2 18:14:26 2009
#
CONFIG_SPARC=y
CONFIG_SPARC64=y
+CONFIG_ARCH_DEFCONFIG="arch/sparc/configs/sparc64_defconfig"
+CONFIG_BITS=64
+CONFIG_64BIT=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_64BIT=y
-CONFIG_MMU=y
CONFIG_IOMMU_HELPER=y
CONFIG_QUICKLIST=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_AUDIT_ARCH=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_MMU=y
CONFIG_ARCH_NO_VIRT_TO_BUS=y
CONFIG_OF=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -86,6 +86,7 @@ CONFIG_SLUB_DEBUG=y
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=m
CONFIG_HAVE_OPROFILE=y
@@ -127,34 +128,40 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_FREEZER is not set
#
# Processor type and features
#
-CONFIG_SPARC64_PAGE_SIZE_8KB=y
-# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
-CONFIG_SECCOMP=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_SPARC64_SMP=y
+CONFIG_SPARC64_PAGE_SIZE_8KB=y
+# CONFIG_SPARC64_PAGE_SIZE_64KB is not set
+CONFIG_SECCOMP=y
CONFIG_HOTPLUG_CPU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=64
# CONFIG_CPU_FREQ is not set
CONFIG_US3_MC=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_HUGETLB_PAGE_SIZE_4MB=y
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set
# CONFIG_HUGETLB_PAGE_SIZE_64K is not set
@@ -183,10 +190,18 @@ CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=0
CONFIG_NR_QUICK=1
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options (PCI etc.)
+#
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
-CONFIG_SUN_AUXIO=y
-CONFIG_SUN_IO=y
CONFIG_SUN_LDOMS=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
@@ -195,7 +210,9 @@ CONFIG_ARCH_SUPPORTS_MSI=y
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY is not set
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCCARD is not set
CONFIG_SUN_OPENPROMFS=m
+CONFIG_SPARC64_PCI=y
#
# Executable file formats
@@ -207,17 +224,13 @@ CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
CONFIG_COMPAT=y
CONFIG_SYSVIPC_COMPAT=y
-CONFIG_SCHED_SMT=y
-CONFIG_SCHED_MC=y
-# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
-# CONFIG_CMDLINE_BOOL is not set
CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -314,6 +327,7 @@ CONFIG_VLAN_8021Q=m
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
@@ -330,8 +344,8 @@ CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
@@ -378,8 +392,10 @@ CONFIG_MISC_DEVICES=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
CONFIG_HAVE_IDE=y
CONFIG_IDE=y
@@ -387,6 +403,7 @@ CONFIG_IDE=y
# Please see Documentation/ide/ide.txt for help/info on IDE drives
#
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
@@ -394,7 +411,6 @@ CONFIG_IDE_GD_ATA=y
CONFIG_BLK_DEV_IDECD=y
CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
CONFIG_IDE_PROC_FS=y
@@ -477,6 +493,7 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_SRP_ATTRS is not set
CONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -490,6 +507,8 @@ CONFIG_SCSI_LOWLEVEL=y
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
@@ -564,6 +583,9 @@ CONFIG_PHYLIB=m
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
@@ -590,7 +612,6 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
@@ -600,6 +621,7 @@ CONFIG_NET_PCI=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -629,6 +651,7 @@ CONFIG_BNX2=m
# CONFIG_JME is not set
CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
# CONFIG_CHELSIO_T3 is not set
# CONFIG_ENIC is not set
# CONFIG_IXGBE is not set
@@ -778,6 +801,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=m
@@ -843,8 +867,8 @@ CONFIG_I2C_ALGOBIT=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
@@ -870,6 +894,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
# CONFIG_SENSORS_ATXP1 is not set
@@ -919,11 +944,11 @@ CONFIG_HWMON=y
# CONFIG_THERMAL is not set
# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
@@ -1071,6 +1096,7 @@ CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_HRTIMER is not set
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
@@ -1242,11 +1268,11 @@ CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
@@ -1337,6 +1363,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
@@ -1365,7 +1392,6 @@ CONFIG_RTC_DRV_STARFIRE=y
# CONFIG_DMADEVICES is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
-CONFIG_STAGING_EXCLUDE_BUILD=y
#
# Misc Linux/SPARC drivers
@@ -1544,6 +1570,7 @@ CONFIG_SCHEDSTATS=y
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
@@ -1552,6 +1579,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
@@ -1560,8 +1588,12 @@ CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
#
# Tracers
@@ -1571,7 +1603,9 @@ CONFIG_HAVE_FUNCTION_TRACER=y
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
@@ -1600,11 +1634,16 @@ CONFIG_CRYPTO=y
#
# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_GF128MUL=m
CONFIG_CRYPTO_NULL=m
# CONFIG_CRYPTO_CRYPTD is not set
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 89c260aab45c..deeb0fba8029 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -1,21 +1,6 @@
# User exported sparc header files
include include/asm-generic/Kbuild.asm
-header-y += ipcbuf_32.h
-header-y += ipcbuf_64.h
-header-y += posix_types_32.h
-header-y += posix_types_64.h
-header-y += ptrace_32.h
-header-y += ptrace_64.h
-header-y += sigcontext_32.h
-header-y += sigcontext_64.h
-header-y += siginfo_32.h
-header-y += siginfo_64.h
-header-y += signal_32.h
-header-y += signal_64.h
-header-y += stat_32.h
-header-y += stat_64.h
-
header-y += apc.h
header-y += asi.h
header-y += display7seg.h
@@ -23,16 +8,11 @@ header-y += envctrl.h
header-y += fbio.h
header-y += jsflash.h
header-y += openprom.h
-header-y += openprom_32.h
-header-y += openprom_64.h
header-y += openpromio.h
header-y += perfctr.h
header-y += psrcompat.h
header-y += psr.h
header-y += pstate.h
-header-y += reg.h
-header-y += reg_32.h
-header-y += reg_64.h
header-y += traps.h
header-y += uctx.h
header-y += utrap.h
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
index 5c944b5a8040..ce465975a6a5 100644
--- a/arch/sparc/include/asm/atomic_32.h
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -13,8 +13,6 @@
#include <linux/types.h>
-typedef struct { volatile int counter; } atomic_t;
-
#ifdef __KERNEL__
#define ATOMIC_INIT(i) { (i) }
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
index 5982c5ae7f07..a0a706492696 100644
--- a/arch/sparc/include/asm/atomic_64.h
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -10,9 +10,6 @@
#include <linux/types.h>
#include <asm/system.h>
-typedef struct { volatile int counter; } atomic_t;
-typedef struct { volatile __s64 counter; } atomic64_t;
-
#define ATOMIC_INIT(i) { (i) }
#define ATOMIC64_INIT(i) { (i) }
diff --git a/arch/sparc/include/asm/byteorder.h b/arch/sparc/include/asm/byteorder.h
index 5a70f137f1f7..ccc1b6b7de6c 100644
--- a/arch/sparc/include/asm/byteorder.h
+++ b/arch/sparc/include/asm/byteorder.h
@@ -1,51 +1,6 @@
#ifndef _SPARC_BYTEORDER_H
#define _SPARC_BYTEORDER_H
-#include <asm/types.h>
-#include <asm/asi.h>
-
-#define __BIG_ENDIAN
-
-#ifdef CONFIG_SPARC32
-#define __SWAB_64_THRU_32__
-#endif
-
-#ifdef CONFIG_SPARC64
-static inline __u16 __arch_swab16p(const __u16 *addr)
-{
- __u16 ret;
-
- __asm__ __volatile__ ("lduha [%1] %2, %0"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PL));
- return ret;
-}
-#define __arch_swab16p __arch_swab16p
-
-static inline __u32 __arch_swab32p(const __u32 *addr)
-{
- __u32 ret;
-
- __asm__ __volatile__ ("lduwa [%1] %2, %0"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PL));
- return ret;
-}
-#define __arch_swab32p __arch_swab32p
-
-static inline __u64 __arch_swab64p(const __u64 *addr)
-{
- __u64 ret;
-
- __asm__ __volatile__ ("ldxa [%1] %2, %0"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PL));
- return ret;
-}
-#define __arch_swab64p __arch_swab64p
-
-#endif /* CONFIG_SPARC64 */
-
-#include <linux/byteorder.h>
+#include <linux/byteorder/big_endian.h>
#endif /* _SPARC_BYTEORDER_H */
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h
index 7da7c13d23c4..a11b89ee9ef8 100644
--- a/arch/sparc/include/asm/cpudata_64.h
+++ b/arch/sparc/include/asm/cpudata_64.h
@@ -17,7 +17,7 @@
typedef struct {
/* Dcache line 1 */
unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
- unsigned int __pad0;
+ unsigned int __nmi_count;
unsigned long clock_tick; /* %tick's per second */
unsigned long __pad;
unsigned int __pad1;
diff --git a/arch/sparc/include/asm/ipcbuf.h b/arch/sparc/include/asm/ipcbuf.h
index 17d6ef7b23a4..66013b4fe10d 100644
--- a/arch/sparc/include/asm/ipcbuf.h
+++ b/arch/sparc/include/asm/ipcbuf.h
@@ -1,8 +1,32 @@
-#ifndef ___ASM_SPARC_IPCBUF_H
-#define ___ASM_SPARC_IPCBUF_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/ipcbuf_64.h>
-#else
-#include <asm/ipcbuf_32.h>
-#endif
+#ifndef __SPARC_IPCBUF_H
+#define __SPARC_IPCBUF_H
+
+/*
+ * The ipc64_perm structure for sparc/sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit seq
+ * - on sparc for 32 bit mode (it is 32 bit on sparc64)
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct ipc64_perm
+{
+ __kernel_key_t key;
+ __kernel_uid_t uid;
+ __kernel_gid_t gid;
+ __kernel_uid_t cuid;
+ __kernel_gid_t cgid;
+#ifndef __arch64__
+ unsigned short __pad0;
#endif
+ __kernel_mode_t mode;
+ unsigned short __pad1;
+ unsigned short seq;
+ unsigned long long __unused1;
+ unsigned long long __unused2;
+};
+
+#endif /* __SPARC_IPCBUF_H */
diff --git a/arch/sparc/include/asm/ipcbuf_32.h b/arch/sparc/include/asm/ipcbuf_32.h
deleted file mode 100644
index 6387209518f2..000000000000
--- a/arch/sparc/include/asm/ipcbuf_32.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _SPARC_IPCBUF_H
-#define _SPARC_IPCBUF_H
-
-/*
- * The ipc64_perm structure for sparc architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode
- * - 32-bit seq
- * - 2 miscellaneous 64-bit values (so that this structure matches
- * sparc64 ipc64_perm)
- */
-
-struct ipc64_perm
-{
- __kernel_key_t key;
- __kernel_uid32_t uid;
- __kernel_gid32_t gid;
- __kernel_uid32_t cuid;
- __kernel_gid32_t cgid;
- unsigned short __pad1;
- __kernel_mode_t mode;
- unsigned short __pad2;
- unsigned short seq;
- unsigned long long __unused1;
- unsigned long long __unused2;
-};
-
-#endif /* _SPARC_IPCBUF_H */
diff --git a/arch/sparc/include/asm/ipcbuf_64.h b/arch/sparc/include/asm/ipcbuf_64.h
deleted file mode 100644
index a44b855b98db..000000000000
--- a/arch/sparc/include/asm/ipcbuf_64.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef _SPARC64_IPCBUF_H
-#define _SPARC64_IPCBUF_H
-
-/*
- * The ipc64_perm structure for sparc64 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit seq
- * - 2 miscellaneous 64-bit values
- */
-
-struct ipc64_perm
-{
- __kernel_key_t key;
- __kernel_uid_t uid;
- __kernel_gid_t gid;
- __kernel_uid_t cuid;
- __kernel_gid_t cgid;
- __kernel_mode_t mode;
- unsigned short __pad1;
- unsigned short seq;
- unsigned long __unused1;
- unsigned long __unused2;
-};
-
-#endif /* _SPARC64_IPCBUF_H */
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h
index d47d4a1955a9..1934f2cbf513 100644
--- a/arch/sparc/include/asm/irq_64.h
+++ b/arch/sparc/include/asm/irq_64.h
@@ -66,9 +66,6 @@ extern void virt_irq_free(unsigned int virt_irq);
extern void __init init_IRQ(void);
extern void fixup_irqs(void);
-extern int register_perfctr_intr(void (*handler)(struct pt_regs *));
-extern void release_perfctr_intr(void (*handler)(struct pt_regs *));
-
static inline void set_softint(unsigned long bits)
{
__asm__ __volatile__("wr %0, 0x0, %%set_softint"
@@ -98,5 +95,6 @@ void __trigger_all_cpu_backtrace(void);
extern void *hardirq_stack[NR_CPUS];
extern void *softirq_stack[NR_CPUS];
#define __ARCH_HAS_DO_SOFTIRQ
+#define ARCH_HAS_NMI_WATCHDOG
#endif
diff --git a/arch/sparc/include/asm/jsflash.h b/arch/sparc/include/asm/jsflash.h
index 3457f29bd73b..0717d9e39d2d 100644
--- a/arch/sparc/include/asm/jsflash.h
+++ b/arch/sparc/include/asm/jsflash.h
@@ -8,7 +8,7 @@
#define _SPARC_JSFLASH_H
#ifndef _SPARC_TYPES_H
-#include <asm/types.h>
+#include <linux/types.h>
#endif
/*
diff --git a/arch/sparc/include/asm/kdebug_64.h b/arch/sparc/include/asm/kdebug_64.h
index f905b773235a..feb3578e12c4 100644
--- a/arch/sparc/include/asm/kdebug_64.h
+++ b/arch/sparc/include/asm/kdebug_64.h
@@ -14,6 +14,8 @@ enum die_val {
DIE_TRAP,
DIE_TRAP_TL1,
DIE_CALL,
+ DIE_NMI,
+ DIE_NMIWATCHDOG,
};
#endif
diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h
new file mode 100644
index 000000000000..fbd546dd4feb
--- /dev/null
+++ b/arch/sparc/include/asm/nmi.h
@@ -0,0 +1,10 @@
+#ifndef __NMI_H
+#define __NMI_H
+
+extern int __init nmi_init(void);
+extern void perfctr_irq(int irq, struct pt_regs *regs);
+extern void nmi_adjust_hz(unsigned int new_hz);
+
+extern int nmi_usable;
+
+#endif /* __NMI_H */
diff --git a/arch/sparc/include/asm/openprom.h b/arch/sparc/include/asm/openprom.h
index aaeae905ed3f..963e1a45c35f 100644
--- a/arch/sparc/include/asm/openprom.h
+++ b/arch/sparc/include/asm/openprom.h
@@ -1,8 +1,277 @@
-#ifndef ___ASM_SPARC_OPENPROM_H
-#define ___ASM_SPARC_OPENPROM_H
+#ifndef __SPARC_OPENPROM_H
+#define __SPARC_OPENPROM_H
+
+/* openprom.h: Prom structures and defines for access to the OPENBOOT
+ * prom routines and data areas.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* Empirical constants... */
+#define LINUX_OPPROM_MAGIC 0x10010407
+
+#ifndef __ASSEMBLY__
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+ int (*v0_devopen)(char *device_str);
+ int (*v0_devclose)(int dev_desc);
+ int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+ int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
+ char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+ void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+ /* To map devices into virtual I/O space. */
+ char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+ void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+ int (*v2_dev_open)(char *devpath);
+ void (*v2_dev_close)(int d);
+ int (*v2_dev_read)(int d, char *buf, int nbytes);
+ int (*v2_dev_write)(int d, char *buf, int nbytes);
+ int (*v2_dev_seek)(int d, int hi, int lo);
+
+ /* Never issued (multistage load support) */
+ void (*v2_wheee2)(void);
+ void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+ struct linux_mlist_v0 *theres_more;
+ unsigned int start_adr;
+ unsigned num_bytes;
+};
+
+struct linux_mem_v0 {
+ struct linux_mlist_v0 **v0_totphys;
+ struct linux_mlist_v0 **v0_prommap;
+ struct linux_mlist_v0 **v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+ char *argv[8];
+ char args[100];
+ char boot_dev[2];
+ int boot_dev_ctrl;
+ int boot_dev_unit;
+ int dev_partition;
+ char *kernel_file_name;
+ void *aieee1; /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+ char **bootpath;
+ char **bootargs;
+ int *fd_stdin;
+ int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+ /* Version numbers. */
+ unsigned int pv_magic_cookie;
+ unsigned int pv_romvers;
+ unsigned int pv_plugin_revision;
+ unsigned int pv_printrev;
+
+ /* Version 0 memory descriptors. */
+ struct linux_mem_v0 pv_v0mem;
+
+ /* Node operations. */
+ struct linux_nodeops *pv_nodeops;
+
+ char **pv_bootstr;
+ struct linux_dev_v0_funcs pv_v0devops;
+
+ char *pv_stdin;
+ char *pv_stdout;
+#define PROMDEV_KBD 0 /* input from keyboard */
+#define PROMDEV_SCREEN 0 /* output to screen */
+#define PROMDEV_TTYA 1 /* in/out to ttya */
+#define PROMDEV_TTYB 2 /* in/out to ttyb */
+
+ /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
+ int (*pv_getchar)(void);
+ void (*pv_putchar)(int ch);
+
+ /* Non-blocking variants. */
+ int (*pv_nbgetchar)(void);
+ int (*pv_nbputchar)(int ch);
+
+ void (*pv_putstr)(char *str, int len);
+
+ /* Miscellany. */
+ void (*pv_reboot)(char *bootstr);
+ void (*pv_printf)(__const__ char *fmt, ...);
+ void (*pv_abort)(void);
+ __volatile__ int *pv_ticks;
+ void (*pv_halt)(void);
+ void (**pv_synchook)(void);
+
+ /* Evaluate a forth string, not different proto for V0 and V2->up. */
+ union {
+ void (*v0_eval)(int len, char *str);
+ void (*v2_eval)(char *str);
+ } pv_fortheval;
+
+ struct linux_arguments_v0 **pv_v0bootargs;
+
+ /* Get ether address. */
+ unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+ struct linux_bootargs_v2 pv_v2bootargs;
+ struct linux_dev_v2_funcs pv_v2devops;
+
+ int filler[15];
+
+ /* This one is sun4c/sun4 only. */
+ void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+ /* Prom version 3 Multiprocessor routines. This stuff is crazy.
+ * No joke. Calling these when there is only one cpu probably
+ * crashes the machine, have to test this. :-)
+ */
+
+ /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+ * 'thiscontext' executing at address 'prog_counter'
+ */
+ int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+ int thiscontext, char *prog_counter);
+
+ /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+ * until a resume cpu call is made.
+ */
+ int (*v3_cpustop)(unsigned int whichcpu);
+
+ /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+ * resume cpu call is made.
+ */
+ int (*v3_cpuidle)(unsigned int whichcpu);
+
+ /* v3_cpuresume() will resume processor 'whichcpu' executing
+ * starting with whatever 'pc' and 'npc' were left at the
+ * last 'idle' or 'stop' call.
+ */
+ int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+ int (*no_nextnode)(int node);
+ int (*no_child)(int node);
+ int (*no_proplen)(int node, const char *name);
+ int (*no_getprop)(int node, const char *name, char *val);
+ int (*no_setprop)(int node, const char *name, char *val, int len);
+ char * (*no_nextprop)(int node, char *name);
+};
+
+/* More fun PROM structures for device probing. */
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/openprom_64.h>
+#define PROMREG_MAX 24
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 32
#else
-#include <asm/openprom_32.h>
+#define PROMREG_MAX 16
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 15
#endif
+
+struct linux_prom_registers {
+ unsigned int which_io; /* hi part of physical address */
+ unsigned int phys_addr; /* The physical address of this register */
+ unsigned int reg_size; /* How many bytes does this register take up? */
+};
+
+struct linux_prom64_registers {
+ unsigned long phys_addr;
+ unsigned long reg_size;
+};
+
+struct linux_prom_irqs {
+ int pri; /* IRQ priority */
+ int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+ unsigned int ot_child_space;
+ unsigned int ot_child_base; /* Bus feels this */
+ unsigned int ot_parent_space;
+ unsigned int ot_parent_base; /* CPU looks from here */
+ unsigned int or_size;
+};
+
+/*
+ * Ranges and reg properties are a bit different for PCI.
+ */
+#if defined(__sparc__) && defined(__arch64__)
+struct linux_prom_pci_registers {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+#else
+struct linux_prom_pci_registers {
+ /*
+ * We don't know what information this field contain.
+ * We guess, PCI device function is in bits 15:8
+ * So, ...
+ */
+ unsigned int which_io; /* Let it be which_io */
+
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
#endif
+
+struct linux_prom_pci_ranges {
+ unsigned int child_phys_hi; /* Only certain bits are encoded here. */
+ unsigned int child_phys_mid;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_intmap {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int interrupt;
+
+ int cnode;
+ unsigned int cinterrupt;
+};
+
+struct linux_prom_pci_intmask {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+ unsigned int interrupt;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/openprom_32.h b/arch/sparc/include/asm/openprom_32.h
deleted file mode 100644
index 875da3552d80..000000000000
--- a/arch/sparc/include/asm/openprom_32.h
+++ /dev/null
@@ -1,255 +0,0 @@
-#ifndef __SPARC_OPENPROM_H
-#define __SPARC_OPENPROM_H
-
-/* openprom.h: Prom structures and defines for access to the OPENBOOT
- * prom routines and data areas.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-/* Empirical constants... */
-#define LINUX_OPPROM_MAGIC 0x10010407
-
-#ifndef __ASSEMBLY__
-/* V0 prom device operations. */
-struct linux_dev_v0_funcs {
- int (*v0_devopen)(char *device_str);
- int (*v0_devclose)(int dev_desc);
- int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
-};
-
-/* V2 and later prom device operations. */
-struct linux_dev_v2_funcs {
- int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
- char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
- void (*v2_dumb_mem_free)(char *va, unsigned sz);
-
- /* To map devices into virtual I/O space. */
- char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
- void (*v2_dumb_munmap)(char *virta, unsigned size);
-
- int (*v2_dev_open)(char *devpath);
- void (*v2_dev_close)(int d);
- int (*v2_dev_read)(int d, char *buf, int nbytes);
- int (*v2_dev_write)(int d, char *buf, int nbytes);
- int (*v2_dev_seek)(int d, int hi, int lo);
-
- /* Never issued (multistage load support) */
- void (*v2_wheee2)(void);
- void (*v2_wheee3)(void);
-};
-
-struct linux_mlist_v0 {
- struct linux_mlist_v0 *theres_more;
- char *start_adr;
- unsigned num_bytes;
-};
-
-struct linux_mem_v0 {
- struct linux_mlist_v0 **v0_totphys;
- struct linux_mlist_v0 **v0_prommap;
- struct linux_mlist_v0 **v0_available; /* What we can use */
-};
-
-/* Arguments sent to the kernel from the boot prompt. */
-struct linux_arguments_v0 {
- char *argv[8];
- char args[100];
- char boot_dev[2];
- int boot_dev_ctrl;
- int boot_dev_unit;
- int dev_partition;
- char *kernel_file_name;
- void *aieee1; /* XXX */
-};
-
-/* V2 and up boot things. */
-struct linux_bootargs_v2 {
- char **bootpath;
- char **bootargs;
- int *fd_stdin;
- int *fd_stdout;
-};
-
-/* The top level PROM vector. */
-struct linux_romvec {
- /* Version numbers. */
- unsigned int pv_magic_cookie;
- unsigned int pv_romvers;
- unsigned int pv_plugin_revision;
- unsigned int pv_printrev;
-
- /* Version 0 memory descriptors. */
- struct linux_mem_v0 pv_v0mem;
-
- /* Node operations. */
- struct linux_nodeops *pv_nodeops;
-
- char **pv_bootstr;
- struct linux_dev_v0_funcs pv_v0devops;
-
- char *pv_stdin;
- char *pv_stdout;
-#define PROMDEV_KBD 0 /* input from keyboard */
-#define PROMDEV_SCREEN 0 /* output to screen */
-#define PROMDEV_TTYA 1 /* in/out to ttya */
-#define PROMDEV_TTYB 2 /* in/out to ttyb */
-
- /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
- int (*pv_getchar)(void);
- void (*pv_putchar)(int ch);
-
- /* Non-blocking variants. */
- int (*pv_nbgetchar)(void);
- int (*pv_nbputchar)(int ch);
-
- void (*pv_putstr)(char *str, int len);
-
- /* Miscellany. */
- void (*pv_reboot)(char *bootstr);
- void (*pv_printf)(__const__ char *fmt, ...);
- void (*pv_abort)(void);
- __volatile__ int *pv_ticks;
- void (*pv_halt)(void);
- void (**pv_synchook)(void);
-
- /* Evaluate a forth string, not different proto for V0 and V2->up. */
- union {
- void (*v0_eval)(int len, char *str);
- void (*v2_eval)(char *str);
- } pv_fortheval;
-
- struct linux_arguments_v0 **pv_v0bootargs;
-
- /* Get ether address. */
- unsigned int (*pv_enaddr)(int d, char *enaddr);
-
- struct linux_bootargs_v2 pv_v2bootargs;
- struct linux_dev_v2_funcs pv_v2devops;
-
- int filler[15];
-
- /* This one is sun4c/sun4 only. */
- void (*pv_setctxt)(int ctxt, char *va, int pmeg);
-
- /* Prom version 3 Multiprocessor routines. This stuff is crazy.
- * No joke. Calling these when there is only one cpu probably
- * crashes the machine, have to test this. :-)
- */
-
- /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
- * 'thiscontext' executing at address 'prog_counter'
- */
- int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
- int thiscontext, char *prog_counter);
-
- /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
- * until a resume cpu call is made.
- */
- int (*v3_cpustop)(unsigned int whichcpu);
-
- /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
- * resume cpu call is made.
- */
- int (*v3_cpuidle)(unsigned int whichcpu);
-
- /* v3_cpuresume() will resume processor 'whichcpu' executing
- * starting with whatever 'pc' and 'npc' were left at the
- * last 'idle' or 'stop' call.
- */
- int (*v3_cpuresume)(unsigned int whichcpu);
-};
-
-/* Routines for traversing the prom device tree. */
-struct linux_nodeops {
- int (*no_nextnode)(int node);
- int (*no_child)(int node);
- int (*no_proplen)(int node, const char *name);
- int (*no_getprop)(int node, const char *name, char *val);
- int (*no_setprop)(int node, const char *name, char *val, int len);
- char * (*no_nextprop)(int node, char *name);
-};
-
-/* More fun PROM structures for device probing. */
-#define PROMREG_MAX 16
-#define PROMVADDR_MAX 16
-#define PROMINTR_MAX 15
-
-struct linux_prom_registers {
- unsigned int which_io; /* is this in OBIO space? */
- unsigned int phys_addr; /* The physical address of this register */
- unsigned int reg_size; /* How many bytes does this register take up? */
-};
-
-struct linux_prom_irqs {
- int pri; /* IRQ priority */
- int vector; /* This is foobar, what does it do? */
-};
-
-/* Element of the "ranges" vector */
-struct linux_prom_ranges {
- unsigned int ot_child_space;
- unsigned int ot_child_base; /* Bus feels this */
- unsigned int ot_parent_space;
- unsigned int ot_parent_base; /* CPU looks from here */
- unsigned int or_size;
-};
-
-/* Ranges and reg properties are a bit different for PCI. */
-struct linux_prom_pci_registers {
- /*
- * We don't know what information this field contain.
- * We guess, PCI device function is in bits 15:8
- * So, ...
- */
- unsigned int which_io; /* Let it be which_io */
-
- unsigned int phys_hi;
- unsigned int phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_ranges {
- unsigned int child_phys_hi; /* Only certain bits are encoded here. */
- unsigned int child_phys_mid;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_assigned_addresses {
- unsigned int which_io;
-
- unsigned int phys_hi;
- unsigned int phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_ebus_ranges {
- unsigned int child_phys_hi;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_mid;
- unsigned int parent_phys_lo;
-
- unsigned int size;
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/openprom_64.h b/arch/sparc/include/asm/openprom_64.h
deleted file mode 100644
index b69e4a8c9170..000000000000
--- a/arch/sparc/include/asm/openprom_64.h
+++ /dev/null
@@ -1,280 +0,0 @@
-#ifndef __SPARC64_OPENPROM_H
-#define __SPARC64_OPENPROM_H
-
-/* openprom.h: Prom structures and defines for access to the OPENBOOT
- * prom routines and data areas.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef __ASSEMBLY__
-/* V0 prom device operations. */
-struct linux_dev_v0_funcs {
- int (*v0_devopen)(char *device_str);
- int (*v0_devclose)(int dev_desc);
- int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
- int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
- int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
- int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
-};
-
-/* V2 and later prom device operations. */
-struct linux_dev_v2_funcs {
- int (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
- char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
- void (*v2_dumb_mem_free)(char *va, unsigned sz);
-
- /* To map devices into virtual I/O space. */
- char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
- void (*v2_dumb_munmap)(char *virta, unsigned size);
-
- int (*v2_dev_open)(char *devpath);
- void (*v2_dev_close)(int d);
- int (*v2_dev_read)(int d, char *buf, int nbytes);
- int (*v2_dev_write)(int d, char *buf, int nbytes);
- int (*v2_dev_seek)(int d, int hi, int lo);
-
- /* Never issued (multistage load support) */
- void (*v2_wheee2)(void);
- void (*v2_wheee3)(void);
-};
-
-struct linux_mlist_v0 {
- struct linux_mlist_v0 *theres_more;
- unsigned start_adr;
- unsigned num_bytes;
-};
-
-struct linux_mem_v0 {
- struct linux_mlist_v0 **v0_totphys;
- struct linux_mlist_v0 **v0_prommap;
- struct linux_mlist_v0 **v0_available; /* What we can use */
-};
-
-/* Arguments sent to the kernel from the boot prompt. */
-struct linux_arguments_v0 {
- char *argv[8];
- char args[100];
- char boot_dev[2];
- int boot_dev_ctrl;
- int boot_dev_unit;
- int dev_partition;
- char *kernel_file_name;
- void *aieee1; /* XXX */
-};
-
-/* V2 and up boot things. */
-struct linux_bootargs_v2 {
- char **bootpath;
- char **bootargs;
- int *fd_stdin;
- int *fd_stdout;
-};
-
-/* The top level PROM vector. */
-struct linux_romvec {
- /* Version numbers. */
- unsigned int pv_magic_cookie;
- unsigned int pv_romvers;
- unsigned int pv_plugin_revision;
- unsigned int pv_printrev;
-
- /* Version 0 memory descriptors. */
- struct linux_mem_v0 pv_v0mem;
-
- /* Node operations. */
- struct linux_nodeops *pv_nodeops;
-
- char **pv_bootstr;
- struct linux_dev_v0_funcs pv_v0devops;
-
- char *pv_stdin;
- char *pv_stdout;
-#define PROMDEV_KBD 0 /* input from keyboard */
-#define PROMDEV_SCREEN 0 /* output to screen */
-#define PROMDEV_TTYA 1 /* in/out to ttya */
-#define PROMDEV_TTYB 2 /* in/out to ttyb */
-
- /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
- int (*pv_getchar)(void);
- void (*pv_putchar)(int ch);
-
- /* Non-blocking variants. */
- int (*pv_nbgetchar)(void);
- int (*pv_nbputchar)(int ch);
-
- void (*pv_putstr)(char *str, int len);
-
- /* Miscellany. */
- void (*pv_reboot)(char *bootstr);
- void (*pv_printf)(__const__ char *fmt, ...);
- void (*pv_abort)(void);
- __volatile__ int *pv_ticks;
- void (*pv_halt)(void);
- void (**pv_synchook)(void);
-
- /* Evaluate a forth string, not different proto for V0 and V2->up. */
- union {
- void (*v0_eval)(int len, char *str);
- void (*v2_eval)(char *str);
- } pv_fortheval;
-
- struct linux_arguments_v0 **pv_v0bootargs;
-
- /* Get ether address. */
- unsigned int (*pv_enaddr)(int d, char *enaddr);
-
- struct linux_bootargs_v2 pv_v2bootargs;
- struct linux_dev_v2_funcs pv_v2devops;
-
- int filler[15];
-
- /* This one is sun4c/sun4 only. */
- void (*pv_setctxt)(int ctxt, char *va, int pmeg);
-
- /* Prom version 3 Multiprocessor routines. This stuff is crazy.
- * No joke. Calling these when there is only one cpu probably
- * crashes the machine, have to test this. :-)
- */
-
- /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
- * 'thiscontext' executing at address 'prog_counter'
- */
- int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
- int thiscontext, char *prog_counter);
-
- /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
- * until a resume cpu call is made.
- */
- int (*v3_cpustop)(unsigned int whichcpu);
-
- /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
- * resume cpu call is made.
- */
- int (*v3_cpuidle)(unsigned int whichcpu);
-
- /* v3_cpuresume() will resume processor 'whichcpu' executing
- * starting with whatever 'pc' and 'npc' were left at the
- * last 'idle' or 'stop' call.
- */
- int (*v3_cpuresume)(unsigned int whichcpu);
-};
-
-/* Routines for traversing the prom device tree. */
-struct linux_nodeops {
- int (*no_nextnode)(int node);
- int (*no_child)(int node);
- int (*no_proplen)(int node, char *name);
- int (*no_getprop)(int node, char *name, char *val);
- int (*no_setprop)(int node, char *name, char *val, int len);
- char * (*no_nextprop)(int node, char *name);
-};
-
-/* More fun PROM structures for device probing. */
-#define PROMREG_MAX 24
-#define PROMVADDR_MAX 16
-#define PROMINTR_MAX 32
-
-struct linux_prom_registers {
- unsigned which_io; /* hi part of physical address */
- unsigned phys_addr; /* The physical address of this register */
- int reg_size; /* How many bytes does this register take up? */
-};
-
-struct linux_prom64_registers {
- unsigned long phys_addr;
- unsigned long reg_size;
-};
-
-struct linux_prom_irqs {
- int pri; /* IRQ priority */
- int vector; /* This is foobar, what does it do? */
-};
-
-/* Element of the "ranges" vector */
-struct linux_prom_ranges {
- unsigned int ot_child_space;
- unsigned int ot_child_base; /* Bus feels this */
- unsigned int ot_parent_space;
- unsigned int ot_parent_base; /* CPU looks from here */
- unsigned int or_size;
-};
-
-struct linux_prom64_ranges {
- unsigned long ot_child_base; /* Bus feels this */
- unsigned long ot_parent_base; /* CPU looks from here */
- unsigned long or_size;
-};
-
-/* Ranges and reg properties are a bit different for PCI. */
-struct linux_prom_pci_registers {
- unsigned int phys_hi;
- unsigned int phys_mid;
- unsigned int phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_ranges {
- unsigned int child_phys_hi; /* Only certain bits are encoded here. */
- unsigned int child_phys_mid;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_lo;
-
- unsigned int size_hi;
- unsigned int size_lo;
-};
-
-struct linux_prom_pci_intmap {
- unsigned int phys_hi;
- unsigned int phys_mid;
- unsigned int phys_lo;
-
- unsigned int interrupt;
-
- int cnode;
- unsigned int cinterrupt;
-};
-
-struct linux_prom_pci_intmask {
- unsigned int phys_hi;
- unsigned int phys_mid;
- unsigned int phys_lo;
- unsigned int interrupt;
-};
-
-struct linux_prom_ebus_ranges {
- unsigned int child_phys_hi;
- unsigned int child_phys_lo;
-
- unsigned int parent_phys_hi;
- unsigned int parent_phys_mid;
- unsigned int parent_phys_lo;
-
- unsigned int size;
-};
-
-struct linux_prom_ebus_intmap {
- unsigned int phys_hi;
- unsigned int phys_lo;
-
- unsigned int interrupt;
-
- int cnode;
- unsigned int cinterrupt;
-};
-
-struct linux_prom_ebus_intmask {
- unsigned int phys_hi;
- unsigned int phys_lo;
- unsigned int interrupt;
-};
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h
index 73d45521db04..33e31ce6b31f 100644
--- a/arch/sparc/include/asm/oplib_32.h
+++ b/arch/sparc/include/asm/oplib_32.h
@@ -177,17 +177,6 @@ extern void prom_putsegment(int context, unsigned long virt_addr,
/* PROM device tree traversal functions... */
-#ifdef PROMLIB_INTERNAL
-
-/* Internal version of prom_getchild. */
-extern int __prom_getchild(int parent_node);
-
-/* Internal version of prom_getsibling. */
-extern int __prom_getsibling(int node);
-
-#endif
-
-
/* Get the child node of the given node, or zero if no child exists. */
extern int prom_getchild(int parent_node);
diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h
index 6d2c2ca98039..a5db0317b5fb 100644
--- a/arch/sparc/include/asm/oplib_64.h
+++ b/arch/sparc/include/asm/oplib_64.h
@@ -218,16 +218,6 @@ extern void prom_unmap(unsigned long size, unsigned long vaddr);
/* PROM device tree traversal functions... */
-#ifdef PROMLIB_INTERNAL
-
-/* Internal version of prom_getchild. */
-extern int __prom_getchild(int parent_node);
-
-/* Internal version of prom_getsibling. */
-extern int __prom_getsibling(int node);
-
-#endif
-
/* Get the child node of the given node, or zero if no child exists. */
extern int prom_getchild(int parent_node);
diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h
new file mode 100644
index 000000000000..a2f5c61f924e
--- /dev/null
+++ b/arch/sparc/include/asm/pcr.h
@@ -0,0 +1,46 @@
+#ifndef __PCR_H
+#define __PCR_H
+
+struct pcr_ops {
+ u64 (*read)(void);
+ void (*write)(u64);
+};
+extern const struct pcr_ops *pcr_ops;
+
+extern void deferred_pcr_work_irq(int irq, struct pt_regs *regs);
+extern void schedule_deferred_pcr_work(void);
+
+#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */
+#define PCR_STRACE 0x00000002 /* Trace supervisor events */
+#define PCR_UTRACE 0x00000004 /* Trace user events */
+#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */
+#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */
+#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */
+#define PCR_N2_MASK0 0x00003fc0
+#define PCR_N2_MASK0_SHIFT 6
+#define PCR_N2_SL0 0x0003c000
+#define PCR_N2_SL0_SHIFT 14
+#define PCR_N2_OV0 0x00040000
+#define PCR_N2_MASK1 0x07f80000
+#define PCR_N2_MASK1_SHIFT 19
+#define PCR_N2_SL1 0x78000000
+#define PCR_N2_SL1_SHIFT 27
+#define PCR_N2_OV1 0x80000000
+
+extern unsigned int picl_shift;
+
+/* In order to commonize as much of the implementation as
+ * possible, we use PICH as our counter. Mostly this is
+ * to accomodate Niagara-1 which can only count insn cycles
+ * in PICH.
+ */
+static inline u64 picl_value(unsigned int nmi_hz)
+{
+ u32 delta = local_cpu_data().clock_tick / (nmi_hz << picl_shift);
+
+ return ((u64)((0 - delta) & 0xffffffff)) << 32;
+}
+
+extern u64 pcr_enable;
+
+#endif /* __PCR_H */
diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h
index d573820c0ff4..32a7efe76d00 100644
--- a/arch/sparc/include/asm/pil.h
+++ b/arch/sparc/include/asm/pil.h
@@ -23,6 +23,7 @@
#define PIL_SMP_CTX_NEW_VERSION 4
#define PIL_DEVICE_IRQ 5
#define PIL_SMP_CALL_FUNC_SNGL 6
+#define PIL_DEFERRED_PCR_WORK 7
#define PIL_NORMAL_MAX 14
#define PIL_NMI 15
diff --git a/arch/sparc/include/asm/posix_types.h b/arch/sparc/include/asm/posix_types.h
index 03a0e091a884..98d6ebb922fb 100644
--- a/arch/sparc/include/asm/posix_types.h
+++ b/arch/sparc/include/asm/posix_types.h
@@ -1,8 +1,155 @@
-#ifndef ___ASM_SPARC_POSIX_TYPES_H
-#define ___ASM_SPARC_POSIX_TYPES_H
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+#ifndef __SPARC_POSIX_TYPES_H
+#define __SPARC_POSIX_TYPES_H
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/posix_types_64.h>
+/* sparc 64 bit */
+typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
+typedef long __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_pid_t;
+typedef int __kernel_ipc_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned int __kernel_mode_t;
+typedef unsigned short __kernel_umode_t;
+typedef unsigned int __kernel_nlink_t;
+typedef int __kernel_daddr_t;
+typedef long __kernel_off_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_timer_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef __kernel_uid_t __kernel_uid32_t;
+typedef __kernel_gid_t __kernel_gid32_t;
+
+typedef unsigned int __kernel_old_dev_t;
+
+/* Note this piece of asymmetry from the v9 ABI. */
+typedef int __kernel_suseconds_t;
+
#else
-#include <asm/posix_types_32.h>
-#endif
+/* sparc 32 bit */
+
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef long int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_umode_t;
+typedef short __kernel_nlink_t;
+typedef long __kernel_daddr_t;
+typedef long __kernel_off_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef unsigned short __kernel_old_dev_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_timer_t;
+
+#endif /* defined(__sparc__) && defined(__arch64__) */
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
#endif
+
+typedef struct {
+ int val[2];
+} __kernel_fsid_t;
+
+#ifdef __KERNEL__
+
+#undef __FD_SET
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant cases (8 or 32 longs,
+ * for 256 and 1024-bit fd_sets respectively)
+ */
+#undef __FD_ZERO
+static inline void __FD_ZERO(__kernel_fd_set *p)
+{
+ unsigned long *tmp = p->fds_bits;
+ int i;
+
+ if (__builtin_constant_p(__FDSET_LONGS)) {
+ switch (__FDSET_LONGS) {
+ case 32:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+ tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+ tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+ tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
+ tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
+ tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
+ tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
+ return;
+ case 16:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+ tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
+ tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
+ return;
+ case 8:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
+ return;
+ case 4:
+ tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
+ return;
+ }
+ }
+ i = __FDSET_LONGS;
+ while (i) {
+ i--;
+ *tmp = 0;
+ tmp++;
+ }
+}
+
+#endif /* __KERNEL__ */
+#endif /* __SPARC_POSIX_TYPES_H */
diff --git a/arch/sparc/include/asm/posix_types_32.h b/arch/sparc/include/asm/posix_types_32.h
deleted file mode 100644
index 6bb6eb1ca0f2..000000000000
--- a/arch/sparc/include/asm/posix_types_32.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef __ARCH_SPARC_POSIX_TYPES_H
-#define __ARCH_SPARC_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned int __kernel_size_t;
-typedef int __kernel_ssize_t;
-typedef long int __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
-typedef long __kernel_suseconds_t;
-typedef long __kernel_clock_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_umode_t;
-typedef short __kernel_nlink_t;
-typedef long __kernel_daddr_t;
-typedef long __kernel_off_t;
-typedef char * __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int __kernel_uid32_t;
-typedef unsigned int __kernel_gid32_t;
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-typedef unsigned short __kernel_old_dev_t;
-typedef int __kernel_clockid_t;
-typedef int __kernel_timer_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
- int val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
- unsigned long *tmp = p->fds_bits;
- int i;
-
- if (__builtin_constant_p(__FDSET_LONGS)) {
- switch (__FDSET_LONGS) {
- case 32:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
- tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
- tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
- tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
- return;
- case 16:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- return;
- case 8:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- return;
- case 4:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- return;
- }
- }
- i = __FDSET_LONGS;
- while (i) {
- i--;
- *tmp = 0;
- tmp++;
- }
-}
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* !(__ARCH_SPARC_POSIX_TYPES_H) */
diff --git a/arch/sparc/include/asm/posix_types_64.h b/arch/sparc/include/asm/posix_types_64.h
deleted file mode 100644
index ba8f93295763..000000000000
--- a/arch/sparc/include/asm/posix_types_64.h
+++ /dev/null
@@ -1,122 +0,0 @@
-#ifndef __ARCH_SPARC64_POSIX_TYPES_H
-#define __ARCH_SPARC64_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_size_t;
-typedef long __kernel_ssize_t;
-typedef long __kernel_ptrdiff_t;
-typedef long __kernel_time_t;
-typedef long __kernel_clock_t;
-typedef int __kernel_pid_t;
-typedef int __kernel_ipc_pid_t;
-typedef unsigned int __kernel_uid_t;
-typedef unsigned int __kernel_gid_t;
-typedef unsigned long __kernel_ino_t;
-typedef unsigned int __kernel_mode_t;
-typedef unsigned short __kernel_umode_t;
-typedef unsigned int __kernel_nlink_t;
-typedef int __kernel_daddr_t;
-typedef long __kernel_off_t;
-typedef char * __kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef int __kernel_clockid_t;
-typedef int __kernel_timer_t;
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-typedef __kernel_uid_t __kernel_uid32_t;
-typedef __kernel_gid_t __kernel_gid32_t;
-
-typedef unsigned int __kernel_old_dev_t;
-
-/* Note this piece of asymmetry from the v9 ABI. */
-typedef int __kernel_suseconds_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
- int val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, __const__ __kernel_fd_set *p)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant cases (8 or 32 longs,
- * for 256 and 1024-bit fd_sets respectively)
- */
-#undef __FD_ZERO
-static inline void __FD_ZERO(__kernel_fd_set *p)
-{
- unsigned long *tmp = p->fds_bits;
- int i;
-
- if (__builtin_constant_p(__FDSET_LONGS)) {
- switch (__FDSET_LONGS) {
- case 32:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- tmp[16] = 0; tmp[17] = 0; tmp[18] = 0; tmp[19] = 0;
- tmp[20] = 0; tmp[21] = 0; tmp[22] = 0; tmp[23] = 0;
- tmp[24] = 0; tmp[25] = 0; tmp[26] = 0; tmp[27] = 0;
- tmp[28] = 0; tmp[29] = 0; tmp[30] = 0; tmp[31] = 0;
- return;
- case 16:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0;
- tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0;
- return;
- case 8:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0;
- return;
- case 4:
- tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0;
- return;
- }
- }
- i = __FDSET_LONGS;
- while (i) {
- i--;
- *tmp = 0;
- tmp++;
- }
-}
-
-#endif /* defined(__KERNEL__) */
-
-#endif /* !(__ARCH_SPARC64_POSIX_TYPES_H) */
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
index 2ae67a2e7f3a..09521c6a5edb 100644
--- a/arch/sparc/include/asm/processor_32.h
+++ b/arch/sparc/include/asm/processor_32.h
@@ -99,7 +99,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
"st\t%%g0, [%0 + %3 + 0x3c]"
: /* no outputs */
: "r" (regs),
- "r" (sp - sizeof(struct reg_window)),
+ "r" (sp - sizeof(struct reg_window32)),
"r" (zero),
"i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))
: "memory");
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
index 6dcbe2eed2e2..30b0b797dc0c 100644
--- a/arch/sparc/include/asm/ptrace.h
+++ b/arch/sparc/include/asm/ptrace.h
@@ -1,8 +1,448 @@
-#ifndef ___ASM_SPARC_PTRACE_H
-#define ___ASM_SPARC_PTRACE_H
+#ifndef __SPARC_PTRACE_H
+#define __SPARC_PTRACE_H
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/ptrace_64.h>
+/* 64 bit sparc */
+#include <asm/pstate.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+
+/* This magic value must have the low 9 bits clear,
+ * as that is where we encode the %tt value, see below.
+ */
+#define PT_REGS_MAGIC 0x57ac6c00
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct pt_regs {
+ unsigned long u_regs[16]; /* globals and ins */
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned int y;
+
+ /* We encode a magic number, PT_REGS_MAGIC, along
+ * with the %tt (trap type) register value at trap
+ * entry time. The magic number allows us to identify
+ * accurately a trap stack frame in the stack
+ * unwinder, and the %tt value allows us to test
+ * things like "in a system call" etc. for an arbitray
+ * process.
+ *
+ * The PT_REGS_MAGIC is choosen such that it can be
+ * loaded completely using just a sethi instruction.
+ */
+ unsigned int magic;
+};
+
+struct pt_regs32 {
+ unsigned int psr;
+ unsigned int pc;
+ unsigned int npc;
+ unsigned int y;
+ unsigned int u_regs[16]; /* globals and ins */
+};
+
+/* A V9 register window */
+struct reg_window {
+ unsigned long locals[8];
+ unsigned long ins[8];
+};
+
+/* A 32-bit register window. */
+struct reg_window32 {
+ unsigned int locals[8];
+ unsigned int ins[8];
+};
+
+/* A V9 Sparc stack frame */
+struct sparc_stackf {
+ unsigned long locals[8];
+ unsigned long ins[6];
+ struct sparc_stackf *fp;
+ unsigned long callers_pc;
+ char *structptr;
+ unsigned long xargs[6];
+ unsigned long xxargs[1];
+};
+
+/* A 32-bit Sparc stack frame */
+struct sparc_stackf32 {
+ unsigned int locals[8];
+ unsigned int ins[6];
+ unsigned int fp;
+ unsigned int callers_pc;
+ unsigned int structptr;
+ unsigned int xargs[6];
+ unsigned int xxargs[1];
+};
+
+struct sparc_trapf {
+ unsigned long locals[8];
+ unsigned long ins[8];
+ unsigned long _unused;
+ struct pt_regs *regs;
+};
+#endif /* (!__ASSEMBLY__) */
#else
-#include <asm/ptrace_32.h>
+/* 32 bit sparc */
+
+#include <asm/psr.h>
+
+/* This struct defines the way the registers are stored on the
+ * stack during a system call and basically all traps.
+ */
+#ifndef __ASSEMBLY__
+
+struct pt_regs {
+ unsigned long psr;
+ unsigned long pc;
+ unsigned long npc;
+ unsigned long y;
+ unsigned long u_regs[16]; /* globals and ins */
+};
+
+/* A 32-bit register window. */
+struct reg_window32 {
+ unsigned long locals[8];
+ unsigned long ins[8];
+};
+
+/* A Sparc stack frame */
+struct sparc_stackf {
+ unsigned long locals[8];
+ unsigned long ins[6];
+ struct sparc_stackf *fp;
+ unsigned long callers_pc;
+ char *structptr;
+ unsigned long xargs[6];
+ unsigned long xxargs[1];
+};
+#endif /* (!__ASSEMBLY__) */
+
+#endif /* (defined(__sparc__) && defined(__arch64__))*/
+
+#ifndef __ASSEMBLY__
+
+#define TRACEREG_SZ sizeof(struct pt_regs)
+#define STACKFRAME_SZ sizeof(struct sparc_stackf)
+
+#define TRACEREG32_SZ sizeof(struct pt_regs32)
+#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
+
+#endif /* (!__ASSEMBLY__) */
+
+#define UREG_G0 0
+#define UREG_G1 1
+#define UREG_G2 2
+#define UREG_G3 3
+#define UREG_G4 4
+#define UREG_G5 5
+#define UREG_G6 6
+#define UREG_G7 7
+#define UREG_I0 8
+#define UREG_I1 9
+#define UREG_I2 10
+#define UREG_I3 11
+#define UREG_I4 12
+#define UREG_I5 13
+#define UREG_I6 14
+#define UREG_I7 15
+#define UREG_FP UREG_I6
+#define UREG_RETPC UREG_I7
+
+#if defined(__sparc__) && defined(__arch64__)
+/* 64 bit sparc */
+
+#ifndef __ASSEMBLY__
+
+#ifdef __KERNEL__
+
+#include <linux/threads.h>
+#include <asm/system.h>
+
+static inline int pt_regs_trap_type(struct pt_regs *regs)
+{
+ return regs->magic & 0x1ff;
+}
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+ return (regs->tstate & TSTATE_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+ return (regs->tstate &= ~TSTATE_SYSCALL);
+}
+
+#define arch_ptrace_stop_needed(exit_code, info) \
+({ flush_user_windows(); \
+ get_thread_wsaved() != 0; \
+})
+
+#define arch_ptrace_stop(exit_code, info) \
+ synchronize_user_stack()
+
+struct global_reg_snapshot {
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned long o7;
+ unsigned long i7;
+ unsigned long rpc;
+ struct thread_info *thread;
+ unsigned long pad1;
+};
+extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
+
+#define force_successful_syscall_return() \
+do { current_thread_info()->syscall_noerror = 1; \
+} while (0)
+#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
+#define instruction_pointer(regs) ((regs)->tpc)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
+#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
#endif
+extern void show_regs(struct pt_regs *);
+#endif /* (__KERNEL__) */
+
+#else /* __ASSEMBLY__ */
+/* For assembly code. */
+#define TRACEREG_SZ 0xa0
+#define STACKFRAME_SZ 0xc0
+
+#define TRACEREG32_SZ 0x50
+#define STACKFRAME32_SZ 0x60
+#endif /* __ASSEMBLY__ */
+
+#else /* (defined(__sparc__) && defined(__arch64__)) */
+
+/* 32 bit sparc */
+
+#ifndef __ASSEMBLY__
+
+#ifdef __KERNEL__
+
+#include <asm/system.h>
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+ return (regs->psr & PSR_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+ return (regs->psr &= ~PSR_SYSCALL);
+}
+
+#define arch_ptrace_stop_needed(exit_code, info) \
+({ flush_user_windows(); \
+ current_thread_info()->w_saved != 0; \
+})
+
+#define arch_ptrace_stop(exit_code, info) \
+ synchronize_user_stack()
+
+#define user_mode(regs) (!((regs)->psr & PSR_PS))
+#define instruction_pointer(regs) ((regs)->pc)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
+unsigned long profile_pc(struct pt_regs *);
+extern void show_regs(struct pt_regs *);
+#endif /* (__KERNEL__) */
+
+#else /* (!__ASSEMBLY__) */
+/* For assembly code. */
+#define TRACEREG_SZ 0x50
+#define STACKFRAME_SZ 0x60
+#endif /* (!__ASSEMBLY__) */
+
+#endif /* (defined(__sparc__) && defined(__arch64__)) */
+
+#ifdef __KERNEL__
+#define STACK_BIAS 2047
#endif
+
+/* These are for pt_regs. */
+#define PT_V9_G0 0x00
+#define PT_V9_G1 0x08
+#define PT_V9_G2 0x10
+#define PT_V9_G3 0x18
+#define PT_V9_G4 0x20
+#define PT_V9_G5 0x28
+#define PT_V9_G6 0x30
+#define PT_V9_G7 0x38
+#define PT_V9_I0 0x40
+#define PT_V9_I1 0x48
+#define PT_V9_I2 0x50
+#define PT_V9_I3 0x58
+#define PT_V9_I4 0x60
+#define PT_V9_I5 0x68
+#define PT_V9_I6 0x70
+#define PT_V9_FP PT_V9_I6
+#define PT_V9_I7 0x78
+#define PT_V9_TSTATE 0x80
+#define PT_V9_TPC 0x88
+#define PT_V9_TNPC 0x90
+#define PT_V9_Y 0x98
+#define PT_V9_MAGIC 0x9c
+#define PT_TSTATE PT_V9_TSTATE
+#define PT_TPC PT_V9_TPC
+#define PT_TNPC PT_V9_TNPC
+
+/* These for pt_regs32. */
+#define PT_PSR 0x0
+#define PT_PC 0x4
+#define PT_NPC 0x8
+#define PT_Y 0xc
+#define PT_G0 0x10
+#define PT_WIM PT_G0
+#define PT_G1 0x14
+#define PT_G2 0x18
+#define PT_G3 0x1c
+#define PT_G4 0x20
+#define PT_G5 0x24
+#define PT_G6 0x28
+#define PT_G7 0x2c
+#define PT_I0 0x30
+#define PT_I1 0x34
+#define PT_I2 0x38
+#define PT_I3 0x3c
+#define PT_I4 0x40
+#define PT_I5 0x44
+#define PT_I6 0x48
+#define PT_FP PT_I6
+#define PT_I7 0x4c
+
+/* Reg_window offsets */
+#define RW_V9_L0 0x00
+#define RW_V9_L1 0x08
+#define RW_V9_L2 0x10
+#define RW_V9_L3 0x18
+#define RW_V9_L4 0x20
+#define RW_V9_L5 0x28
+#define RW_V9_L6 0x30
+#define RW_V9_L7 0x38
+#define RW_V9_I0 0x40
+#define RW_V9_I1 0x48
+#define RW_V9_I2 0x50
+#define RW_V9_I3 0x58
+#define RW_V9_I4 0x60
+#define RW_V9_I5 0x68
+#define RW_V9_I6 0x70
+#define RW_V9_I7 0x78
+
+#define RW_L0 0x00
+#define RW_L1 0x04
+#define RW_L2 0x08
+#define RW_L3 0x0c
+#define RW_L4 0x10
+#define RW_L5 0x14
+#define RW_L6 0x18
+#define RW_L7 0x1c
+#define RW_I0 0x20
+#define RW_I1 0x24
+#define RW_I2 0x28
+#define RW_I3 0x2c
+#define RW_I4 0x30
+#define RW_I5 0x34
+#define RW_I6 0x38
+#define RW_I7 0x3c
+
+/* Stack_frame offsets */
+#define SF_V9_L0 0x00
+#define SF_V9_L1 0x08
+#define SF_V9_L2 0x10
+#define SF_V9_L3 0x18
+#define SF_V9_L4 0x20
+#define SF_V9_L5 0x28
+#define SF_V9_L6 0x30
+#define SF_V9_L7 0x38
+#define SF_V9_I0 0x40
+#define SF_V9_I1 0x48
+#define SF_V9_I2 0x50
+#define SF_V9_I3 0x58
+#define SF_V9_I4 0x60
+#define SF_V9_I5 0x68
+#define SF_V9_FP 0x70
+#define SF_V9_PC 0x78
+#define SF_V9_RETP 0x80
+#define SF_V9_XARG0 0x88
+#define SF_V9_XARG1 0x90
+#define SF_V9_XARG2 0x98
+#define SF_V9_XARG3 0xa0
+#define SF_V9_XARG4 0xa8
+#define SF_V9_XARG5 0xb0
+#define SF_V9_XXARG 0xb8
+
+#define SF_L0 0x00
+#define SF_L1 0x04
+#define SF_L2 0x08
+#define SF_L3 0x0c
+#define SF_L4 0x10
+#define SF_L5 0x14
+#define SF_L6 0x18
+#define SF_L7 0x1c
+#define SF_I0 0x20
+#define SF_I1 0x24
+#define SF_I2 0x28
+#define SF_I3 0x2c
+#define SF_I4 0x30
+#define SF_I5 0x34
+#define SF_FP 0x38
+#define SF_PC 0x3c
+#define SF_RETP 0x40
+#define SF_XARG0 0x44
+#define SF_XARG1 0x48
+#define SF_XARG2 0x4c
+#define SF_XARG3 0x50
+#define SF_XARG4 0x54
+#define SF_XARG5 0x58
+#define SF_XXARG 0x5c
+
+#ifdef __KERNEL__
+
+/* global_reg_snapshot offsets */
+#define GR_SNAP_TSTATE 0x00
+#define GR_SNAP_TPC 0x08
+#define GR_SNAP_TNPC 0x10
+#define GR_SNAP_O7 0x18
+#define GR_SNAP_I7 0x20
+#define GR_SNAP_RPC 0x28
+#define GR_SNAP_THREAD 0x30
+#define GR_SNAP_PAD1 0x38
+
+#endif /* __KERNEL__ */
+
+/* Stuff for the ptrace system call */
+#define PTRACE_SPARC_DETACH 11
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_READDATA 16
+#define PTRACE_WRITEDATA 17
+#define PTRACE_READTEXT 18
+#define PTRACE_WRITETEXT 19
+#define PTRACE_GETFPAREGS 20
+#define PTRACE_SETFPAREGS 21
+
+/* There are for debugging 64-bit processes, either from a 32 or 64 bit
+ * parent. Thus their complements are for debugging 32-bit processes only.
+ */
+
+#define PTRACE_GETREGS64 22
+#define PTRACE_SETREGS64 23
+/* PTRACE_SYSCALL is 24 */
+#define PTRACE_GETFPREGS64 25
+#define PTRACE_SETFPREGS64 26
+
+#endif /* !(__SPARC_PTRACE_H) */
diff --git a/arch/sparc/include/asm/ptrace_32.h b/arch/sparc/include/asm/ptrace_32.h
deleted file mode 100644
index 4cef450167dd..000000000000
--- a/arch/sparc/include/asm/ptrace_32.h
+++ /dev/null
@@ -1,186 +0,0 @@
-#ifndef _SPARC_PTRACE_H
-#define _SPARC_PTRACE_H
-
-#include <asm/psr.h>
-
-/* This struct defines the way the registers are stored on the
- * stack during a system call and basically all traps.
- */
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
- unsigned long psr;
- unsigned long pc;
- unsigned long npc;
- unsigned long y;
- unsigned long u_regs[16]; /* globals and ins */
-};
-
-#define UREG_G0 0
-#define UREG_G1 1
-#define UREG_G2 2
-#define UREG_G3 3
-#define UREG_G4 4
-#define UREG_G5 5
-#define UREG_G6 6
-#define UREG_G7 7
-#define UREG_I0 8
-#define UREG_I1 9
-#define UREG_I2 10
-#define UREG_I3 11
-#define UREG_I4 12
-#define UREG_I5 13
-#define UREG_I6 14
-#define UREG_I7 15
-#define UREG_WIM UREG_G0
-#define UREG_FADDR UREG_G0
-#define UREG_FP UREG_I6
-#define UREG_RETPC UREG_I7
-
-/* A register window */
-struct reg_window {
- unsigned long locals[8];
- unsigned long ins[8];
-};
-
-/* A Sparc stack frame */
-struct sparc_stackf {
- unsigned long locals[8];
- unsigned long ins[6];
- struct sparc_stackf *fp;
- unsigned long callers_pc;
- char *structptr;
- unsigned long xargs[6];
- unsigned long xxargs[1];
-};
-
-#define TRACEREG_SZ sizeof(struct pt_regs)
-#define STACKFRAME_SZ sizeof(struct sparc_stackf)
-
-#ifdef __KERNEL__
-
-#include <asm/system.h>
-
-static inline bool pt_regs_is_syscall(struct pt_regs *regs)
-{
- return (regs->psr & PSR_SYSCALL);
-}
-
-static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
-{
- return (regs->psr &= ~PSR_SYSCALL);
-}
-
-#define arch_ptrace_stop_needed(exit_code, info) \
-({ flush_user_windows(); \
- current_thread_info()->w_saved != 0; \
-})
-
-#define arch_ptrace_stop(exit_code, info) \
- synchronize_user_stack()
-
-#define user_mode(regs) (!((regs)->psr & PSR_PS))
-#define instruction_pointer(regs) ((regs)->pc)
-#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
-unsigned long profile_pc(struct pt_regs *);
-extern void show_regs(struct pt_regs *);
-#endif
-
-#else /* __ASSEMBLY__ */
-/* For assembly code. */
-#define TRACEREG_SZ 0x50
-#define STACKFRAME_SZ 0x60
-#endif
-
-/*
- * The asm-offsets.h is a generated file, so we cannot include it.
- * It may be OK for glibc headers, but it's utterly pointless for C code.
- * The assembly code using those offsets has to include it explicitly.
- */
-/* #include <asm/asm-offsets.h> */
-
-/* These are for pt_regs. */
-#define PT_PSR 0x0
-#define PT_PC 0x4
-#define PT_NPC 0x8
-#define PT_Y 0xc
-#define PT_G0 0x10
-#define PT_WIM PT_G0
-#define PT_G1 0x14
-#define PT_G2 0x18
-#define PT_G3 0x1c
-#define PT_G4 0x20
-#define PT_G5 0x24
-#define PT_G6 0x28
-#define PT_G7 0x2c
-#define PT_I0 0x30
-#define PT_I1 0x34
-#define PT_I2 0x38
-#define PT_I3 0x3c
-#define PT_I4 0x40
-#define PT_I5 0x44
-#define PT_I6 0x48
-#define PT_FP PT_I6
-#define PT_I7 0x4c
-
-/* Reg_window offsets */
-#define RW_L0 0x00
-#define RW_L1 0x04
-#define RW_L2 0x08
-#define RW_L3 0x0c
-#define RW_L4 0x10
-#define RW_L5 0x14
-#define RW_L6 0x18
-#define RW_L7 0x1c
-#define RW_I0 0x20
-#define RW_I1 0x24
-#define RW_I2 0x28
-#define RW_I3 0x2c
-#define RW_I4 0x30
-#define RW_I5 0x34
-#define RW_I6 0x38
-#define RW_I7 0x3c
-
-/* Stack_frame offsets */
-#define SF_L0 0x00
-#define SF_L1 0x04
-#define SF_L2 0x08
-#define SF_L3 0x0c
-#define SF_L4 0x10
-#define SF_L5 0x14
-#define SF_L6 0x18
-#define SF_L7 0x1c
-#define SF_I0 0x20
-#define SF_I1 0x24
-#define SF_I2 0x28
-#define SF_I3 0x2c
-#define SF_I4 0x30
-#define SF_I5 0x34
-#define SF_FP 0x38
-#define SF_PC 0x3c
-#define SF_RETP 0x40
-#define SF_XARG0 0x44
-#define SF_XARG1 0x48
-#define SF_XARG2 0x4c
-#define SF_XARG3 0x50
-#define SF_XARG4 0x54
-#define SF_XARG5 0x58
-#define SF_XXARG 0x5c
-
-/* Stuff for the ptrace system call */
-#define PTRACE_SPARC_DETACH 11
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-#define PTRACE_GETFPREGS 14
-#define PTRACE_SETFPREGS 15
-#define PTRACE_READDATA 16
-#define PTRACE_WRITEDATA 17
-#define PTRACE_READTEXT 18
-#define PTRACE_WRITETEXT 19
-#define PTRACE_GETFPAREGS 20
-#define PTRACE_SETFPAREGS 21
-
-#endif /* !(_SPARC_PTRACE_H) */
diff --git a/arch/sparc/include/asm/ptrace_64.h b/arch/sparc/include/asm/ptrace_64.h
deleted file mode 100644
index cd6fbfc20435..000000000000
--- a/arch/sparc/include/asm/ptrace_64.h
+++ /dev/null
@@ -1,356 +0,0 @@
-#ifndef _SPARC64_PTRACE_H
-#define _SPARC64_PTRACE_H
-
-#include <asm/pstate.h>
-
-/* This struct defines the way the registers are stored on the
- * stack during a system call and basically all traps.
- */
-
-/* This magic value must have the low 9 bits clear,
- * as that is where we encode the %tt value, see below.
- */
-#define PT_REGS_MAGIC 0x57ac6c00
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-struct pt_regs {
- unsigned long u_regs[16]; /* globals and ins */
- unsigned long tstate;
- unsigned long tpc;
- unsigned long tnpc;
- unsigned int y;
-
- /* We encode a magic number, PT_REGS_MAGIC, along
- * with the %tt (trap type) register value at trap
- * entry time. The magic number allows us to identify
- * accurately a trap stack frame in the stack
- * unwinder, and the %tt value allows us to test
- * things like "in a system call" etc. for an arbitray
- * process.
- *
- * The PT_REGS_MAGIC is choosen such that it can be
- * loaded completely using just a sethi instruction.
- */
- unsigned int magic;
-};
-
-struct pt_regs32 {
- unsigned int psr;
- unsigned int pc;
- unsigned int npc;
- unsigned int y;
- unsigned int u_regs[16]; /* globals and ins */
-};
-
-#define UREG_G0 0
-#define UREG_G1 1
-#define UREG_G2 2
-#define UREG_G3 3
-#define UREG_G4 4
-#define UREG_G5 5
-#define UREG_G6 6
-#define UREG_G7 7
-#define UREG_I0 8
-#define UREG_I1 9
-#define UREG_I2 10
-#define UREG_I3 11
-#define UREG_I4 12
-#define UREG_I5 13
-#define UREG_I6 14
-#define UREG_I7 15
-#define UREG_FP UREG_I6
-#define UREG_RETPC UREG_I7
-
-/* A V9 register window */
-struct reg_window {
- unsigned long locals[8];
- unsigned long ins[8];
-};
-
-/* A 32-bit register window. */
-struct reg_window32 {
- unsigned int locals[8];
- unsigned int ins[8];
-};
-
-/* A V9 Sparc stack frame */
-struct sparc_stackf {
- unsigned long locals[8];
- unsigned long ins[6];
- struct sparc_stackf *fp;
- unsigned long callers_pc;
- char *structptr;
- unsigned long xargs[6];
- unsigned long xxargs[1];
-};
-
-/* A 32-bit Sparc stack frame */
-struct sparc_stackf32 {
- unsigned int locals[8];
- unsigned int ins[6];
- unsigned int fp;
- unsigned int callers_pc;
- unsigned int structptr;
- unsigned int xargs[6];
- unsigned int xxargs[1];
-};
-
-struct sparc_trapf {
- unsigned long locals[8];
- unsigned long ins[8];
- unsigned long _unused;
- struct pt_regs *regs;
-};
-
-#define TRACEREG_SZ sizeof(struct pt_regs)
-#define STACKFRAME_SZ sizeof(struct sparc_stackf)
-
-#define TRACEREG32_SZ sizeof(struct pt_regs32)
-#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
-
-#ifdef __KERNEL__
-
-#include <linux/threads.h>
-#include <asm/system.h>
-
-static inline int pt_regs_trap_type(struct pt_regs *regs)
-{
- return regs->magic & 0x1ff;
-}
-
-static inline bool pt_regs_is_syscall(struct pt_regs *regs)
-{
- return (regs->tstate & TSTATE_SYSCALL);
-}
-
-static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
-{
- return (regs->tstate &= ~TSTATE_SYSCALL);
-}
-
-#define arch_ptrace_stop_needed(exit_code, info) \
-({ flush_user_windows(); \
- get_thread_wsaved() != 0; \
-})
-
-#define arch_ptrace_stop(exit_code, info) \
- synchronize_user_stack()
-
-struct global_reg_snapshot {
- unsigned long tstate;
- unsigned long tpc;
- unsigned long tnpc;
- unsigned long o7;
- unsigned long i7;
- unsigned long rpc;
- struct thread_info *thread;
- unsigned long pad1;
-};
-extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
-
-#define force_successful_syscall_return() \
-do { current_thread_info()->syscall_noerror = 1; \
-} while (0)
-#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
-#define instruction_pointer(regs) ((regs)->tpc)
-#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
-#define regs_return_value(regs) ((regs)->u_regs[UREG_I0])
-#ifdef CONFIG_SMP
-extern unsigned long profile_pc(struct pt_regs *);
-#else
-#define profile_pc(regs) instruction_pointer(regs)
-#endif
-extern void show_regs(struct pt_regs *);
-#endif
-
-#else /* __ASSEMBLY__ */
-/* For assembly code. */
-#define TRACEREG_SZ 0xa0
-#define STACKFRAME_SZ 0xc0
-
-#define TRACEREG32_SZ 0x50
-#define STACKFRAME32_SZ 0x60
-#endif
-
-#ifdef __KERNEL__
-#define STACK_BIAS 2047
-#endif
-
-/* These are for pt_regs. */
-#define PT_V9_G0 0x00
-#define PT_V9_G1 0x08
-#define PT_V9_G2 0x10
-#define PT_V9_G3 0x18
-#define PT_V9_G4 0x20
-#define PT_V9_G5 0x28
-#define PT_V9_G6 0x30
-#define PT_V9_G7 0x38
-#define PT_V9_I0 0x40
-#define PT_V9_I1 0x48
-#define PT_V9_I2 0x50
-#define PT_V9_I3 0x58
-#define PT_V9_I4 0x60
-#define PT_V9_I5 0x68
-#define PT_V9_I6 0x70
-#define PT_V9_FP PT_V9_I6
-#define PT_V9_I7 0x78
-#define PT_V9_TSTATE 0x80
-#define PT_V9_TPC 0x88
-#define PT_V9_TNPC 0x90
-#define PT_V9_Y 0x98
-#define PT_V9_MAGIC 0x9c
-#define PT_TSTATE PT_V9_TSTATE
-#define PT_TPC PT_V9_TPC
-#define PT_TNPC PT_V9_TNPC
-
-/* These for pt_regs32. */
-#define PT_PSR 0x0
-#define PT_PC 0x4
-#define PT_NPC 0x8
-#define PT_Y 0xc
-#define PT_G0 0x10
-#define PT_WIM PT_G0
-#define PT_G1 0x14
-#define PT_G2 0x18
-#define PT_G3 0x1c
-#define PT_G4 0x20
-#define PT_G5 0x24
-#define PT_G6 0x28
-#define PT_G7 0x2c
-#define PT_I0 0x30
-#define PT_I1 0x34
-#define PT_I2 0x38
-#define PT_I3 0x3c
-#define PT_I4 0x40
-#define PT_I5 0x44
-#define PT_I6 0x48
-#define PT_FP PT_I6
-#define PT_I7 0x4c
-
-/* Reg_window offsets */
-#define RW_V9_L0 0x00
-#define RW_V9_L1 0x08
-#define RW_V9_L2 0x10
-#define RW_V9_L3 0x18
-#define RW_V9_L4 0x20
-#define RW_V9_L5 0x28
-#define RW_V9_L6 0x30
-#define RW_V9_L7 0x38
-#define RW_V9_I0 0x40
-#define RW_V9_I1 0x48
-#define RW_V9_I2 0x50
-#define RW_V9_I3 0x58
-#define RW_V9_I4 0x60
-#define RW_V9_I5 0x68
-#define RW_V9_I6 0x70
-#define RW_V9_I7 0x78
-
-#define RW_L0 0x00
-#define RW_L1 0x04
-#define RW_L2 0x08
-#define RW_L3 0x0c
-#define RW_L4 0x10
-#define RW_L5 0x14
-#define RW_L6 0x18
-#define RW_L7 0x1c
-#define RW_I0 0x20
-#define RW_I1 0x24
-#define RW_I2 0x28
-#define RW_I3 0x2c
-#define RW_I4 0x30
-#define RW_I5 0x34
-#define RW_I6 0x38
-#define RW_I7 0x3c
-
-/* Stack_frame offsets */
-#define SF_V9_L0 0x00
-#define SF_V9_L1 0x08
-#define SF_V9_L2 0x10
-#define SF_V9_L3 0x18
-#define SF_V9_L4 0x20
-#define SF_V9_L5 0x28
-#define SF_V9_L6 0x30
-#define SF_V9_L7 0x38
-#define SF_V9_I0 0x40
-#define SF_V9_I1 0x48
-#define SF_V9_I2 0x50
-#define SF_V9_I3 0x58
-#define SF_V9_I4 0x60
-#define SF_V9_I5 0x68
-#define SF_V9_FP 0x70
-#define SF_V9_PC 0x78
-#define SF_V9_RETP 0x80
-#define SF_V9_XARG0 0x88
-#define SF_V9_XARG1 0x90
-#define SF_V9_XARG2 0x98
-#define SF_V9_XARG3 0xa0
-#define SF_V9_XARG4 0xa8
-#define SF_V9_XARG5 0xb0
-#define SF_V9_XXARG 0xb8
-
-#define SF_L0 0x00
-#define SF_L1 0x04
-#define SF_L2 0x08
-#define SF_L3 0x0c
-#define SF_L4 0x10
-#define SF_L5 0x14
-#define SF_L6 0x18
-#define SF_L7 0x1c
-#define SF_I0 0x20
-#define SF_I1 0x24
-#define SF_I2 0x28
-#define SF_I3 0x2c
-#define SF_I4 0x30
-#define SF_I5 0x34
-#define SF_FP 0x38
-#define SF_PC 0x3c
-#define SF_RETP 0x40
-#define SF_XARG0 0x44
-#define SF_XARG1 0x48
-#define SF_XARG2 0x4c
-#define SF_XARG3 0x50
-#define SF_XARG4 0x54
-#define SF_XARG5 0x58
-#define SF_XXARG 0x5c
-
-#ifdef __KERNEL__
-
-/* global_reg_snapshot offsets */
-#define GR_SNAP_TSTATE 0x00
-#define GR_SNAP_TPC 0x08
-#define GR_SNAP_TNPC 0x10
-#define GR_SNAP_O7 0x18
-#define GR_SNAP_I7 0x20
-#define GR_SNAP_RPC 0x28
-#define GR_SNAP_THREAD 0x30
-#define GR_SNAP_PAD1 0x38
-
-#endif /* __KERNEL__ */
-
-/* Stuff for the ptrace system call */
-#define PTRACE_SPARC_DETACH 11
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-#define PTRACE_GETFPREGS 14
-#define PTRACE_SETFPREGS 15
-#define PTRACE_READDATA 16
-#define PTRACE_WRITEDATA 17
-#define PTRACE_READTEXT 18
-#define PTRACE_WRITETEXT 19
-#define PTRACE_GETFPAREGS 20
-#define PTRACE_SETFPAREGS 21
-
-/* There are for debugging 64-bit processes, either from a 32 or 64 bit
- * parent. Thus their complements are for debugging 32-bit processes only.
- */
-
-#define PTRACE_GETREGS64 22
-#define PTRACE_SETREGS64 23
-/* PTRACE_SYSCALL is 24 */
-#define PTRACE_GETFPREGS64 25
-#define PTRACE_SETFPREGS64 26
-
-#endif /* !(_SPARC64_PTRACE_H) */
diff --git a/arch/sparc/include/asm/reg.h b/arch/sparc/include/asm/reg.h
deleted file mode 100644
index 0c16e19cae4d..000000000000
--- a/arch/sparc/include/asm/reg.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ___ASM_SPARC_REG_H
-#define ___ASM_SPARC_REG_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/reg_64.h>
-#else
-#include <asm/reg_32.h>
-#endif
-#endif
diff --git a/arch/sparc/include/asm/reg_32.h b/arch/sparc/include/asm/reg_32.h
deleted file mode 100644
index 1efb056fb3d1..000000000000
--- a/arch/sparc/include/asm/reg_32.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * linux/include/asm/reg.h
- * Layout of the registers as expected by gdb on the Sparc
- * we should replace the user.h definitions with those in
- * this file, we don't even use the other
- * -miguel
- *
- * The names of the structures, constants and aliases in this file
- * have the same names as the sunos ones, some programs rely on these
- * names (gdb for example).
- *
- */
-
-#ifndef __SPARC_REG_H
-#define __SPARC_REG_H
-
-struct regs {
- int r_psr;
-#define r_ps r_psr
- int r_pc;
- int r_npc;
- int r_y;
- int r_g1;
- int r_g2;
- int r_g3;
- int r_g4;
- int r_g5;
- int r_g6;
- int r_g7;
- int r_o0;
- int r_o1;
- int r_o2;
- int r_o3;
- int r_o4;
- int r_o5;
- int r_o6;
- int r_o7;
-};
-
-struct fpq {
- unsigned long *addr;
- unsigned long instr;
-};
-
-struct fq {
- union {
- double whole;
- struct fpq fpq;
- } FQu;
-};
-
-#define FPU_REGS_TYPE unsigned int
-#define FPU_FSR_TYPE unsigned
-
-struct fp_status {
- union {
- FPU_REGS_TYPE Fpu_regs[32];
- double Fpu_dregs[16];
- } fpu_fr;
- FPU_FSR_TYPE Fpu_fsr;
- unsigned Fpu_flags;
- unsigned Fpu_extra;
- unsigned Fpu_qcnt;
- struct fq Fpu_q[16];
-};
-
-#define fpu_regs f_fpstatus.fpu_fr.Fpu_regs
-#define fpu_dregs f_fpstatus.fpu_fr.Fpu_dregs
-#define fpu_fsr f_fpstatus.Fpu_fsr
-#define fpu_flags f_fpstatus.Fpu_flags
-#define fpu_extra f_fpstatus.Fpu_extra
-#define fpu_q f_fpstatus.Fpu_q
-#define fpu_qcnt f_fpstatus.Fpu_qcnt
-
-struct fpu {
- struct fp_status f_fpstatus;
-};
-
-#endif /* __SPARC_REG_H */
diff --git a/arch/sparc/include/asm/reg_64.h b/arch/sparc/include/asm/reg_64.h
deleted file mode 100644
index 6f277d7c7d88..000000000000
--- a/arch/sparc/include/asm/reg_64.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * linux/asm/reg.h
- * Layout of the registers as expected by gdb on the Sparc
- * we should replace the user.h definitions with those in
- * this file, we don't even use the other
- * -miguel
- *
- * The names of the structures, constants and aliases in this file
- * have the same names as the sunos ones, some programs rely on these
- * names (gdb for example).
- *
- */
-
-#ifndef __SPARC64_REG_H
-#define __SPARC64_REG_H
-
-struct regs {
- unsigned long r_g1;
- unsigned long r_g2;
- unsigned long r_g3;
- unsigned long r_g4;
- unsigned long r_g5;
- unsigned long r_g6;
- unsigned long r_g7;
- unsigned long r_o0;
- unsigned long r_o1;
- unsigned long r_o2;
- unsigned long r_o3;
- unsigned long r_o4;
- unsigned long r_o5;
- unsigned long r_o6;
- unsigned long r_o7;
- unsigned long __pad;
- unsigned long r_tstate;
- unsigned long r_tpc;
- unsigned long r_tnpc;
- unsigned int r_y;
- unsigned int r_fprs;
-};
-
-#define FPU_REGS_TYPE unsigned int
-#define FPU_FSR_TYPE unsigned long
-
-struct fp_status {
- unsigned long fpu_fr[32];
- unsigned long Fpu_fsr;
-};
-
-struct fpu {
- struct fp_status f_fpstatus;
-};
-
-#define fpu_regs f_fpstatus.fpu_fr
-#define fpu_fsr f_fpstatus.Fpu_fsr
-
-#endif /* __SPARC64_REG_H */
diff --git a/arch/sparc/include/asm/sigcontext.h b/arch/sparc/include/asm/sigcontext.h
index e92de7e286b5..a1607d180354 100644
--- a/arch/sparc/include/asm/sigcontext.h
+++ b/arch/sparc/include/asm/sigcontext.h
@@ -1,8 +1,96 @@
-#ifndef ___ASM_SPARC_SIGCONTEXT_H
-#define ___ASM_SPARC_SIGCONTEXT_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/sigcontext_64.h>
+#ifndef __SPARC_SIGCONTEXT_H
+#define __SPARC_SIGCONTEXT_H
+
+#ifdef __KERNEL__
+#include <asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+
+#define __SUNOS_MAXWIN 31
+
+/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
+struct sigcontext32 {
+ int sigc_onstack; /* state to restore */
+ int sigc_mask; /* sigmask to restore */
+ int sigc_sp; /* stack pointer */
+ int sigc_pc; /* program counter */
+ int sigc_npc; /* next program counter */
+ int sigc_psr; /* for condition codes etc */
+ int sigc_g1; /* User uses these two registers */
+ int sigc_o0; /* within the trampoline code. */
+
+ /* Now comes information regarding the users window set
+ * at the time of the signal.
+ */
+ int sigc_oswins; /* outstanding windows */
+
+ /* stack ptrs for each regwin buf */
+ unsigned sigc_spbuf[__SUNOS_MAXWIN];
+
+ /* Windows to restore after signal */
+ struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
+};
+
+
+/* This is what we use for 32bit new non-rt signals. */
+
+typedef struct {
+ struct {
+ unsigned int psr;
+ unsigned int pc;
+ unsigned int npc;
+ unsigned int y;
+ unsigned int u_regs[16]; /* globals and ins */
+ } si_regs;
+ int si_mask;
+} __siginfo32_t;
+
+#ifdef CONFIG_SPARC64
+typedef struct {
+ unsigned int si_float_regs [64];
+ unsigned long si_fsr;
+ unsigned long si_gsr;
+ unsigned long si_fprs;
+} __siginfo_fpu_t;
+
+/* This is what SunOS doesn't, so we have to write this alone
+ and do it properly. */
+struct sigcontext {
+ /* The size of this array has to match SI_MAX_SIZE from siginfo.h */
+ char sigc_info[128];
+ struct {
+ unsigned long u_regs[16]; /* globals and ins */
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned int y;
+ unsigned int fprs;
+ } sigc_regs;
+ __siginfo_fpu_t * sigc_fpu_save;
+ struct {
+ void * ss_sp;
+ int ss_flags;
+ unsigned long ss_size;
+ } sigc_stack;
+ unsigned long sigc_mask;
+};
+
#else
-#include <asm/sigcontext_32.h>
-#endif
-#endif
+
+typedef struct {
+ unsigned long si_float_regs [32];
+ unsigned long si_fsr;
+ unsigned long si_fpqdepth;
+ struct {
+ unsigned long *insn_addr;
+ unsigned long insn;
+ } si_fpqueue [16];
+} __siginfo_fpu_t;
+#endif /* (CONFIG_SPARC64) */
+
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* (__KERNEL__) */
+
+#endif /* !(__SPARC_SIGCONTEXT_H) */
diff --git a/arch/sparc/include/asm/sigcontext_32.h b/arch/sparc/include/asm/sigcontext_32.h
deleted file mode 100644
index c5fb60dcbd75..000000000000
--- a/arch/sparc/include/asm/sigcontext_32.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef __SPARC_SIGCONTEXT_H
-#define __SPARC_SIGCONTEXT_H
-
-#ifdef __KERNEL__
-#include <asm/ptrace.h>
-
-#ifndef __ASSEMBLY__
-
-#define __SUNOS_MAXWIN 31
-
-/* This is what SunOS does, so shall I. */
-struct sigcontext {
- int sigc_onstack; /* state to restore */
- int sigc_mask; /* sigmask to restore */
- int sigc_sp; /* stack pointer */
- int sigc_pc; /* program counter */
- int sigc_npc; /* next program counter */
- int sigc_psr; /* for condition codes etc */
- int sigc_g1; /* User uses these two registers */
- int sigc_o0; /* within the trampoline code. */
-
- /* Now comes information regarding the users window set
- * at the time of the signal.
- */
- int sigc_oswins; /* outstanding windows */
-
- /* stack ptrs for each regwin buf */
- char *sigc_spbuf[__SUNOS_MAXWIN];
-
- /* Windows to restore after signal */
- struct {
- unsigned long locals[8];
- unsigned long ins[8];
- } sigc_wbuf[__SUNOS_MAXWIN];
-};
-
-typedef struct {
- struct {
- unsigned long psr;
- unsigned long pc;
- unsigned long npc;
- unsigned long y;
- unsigned long u_regs[16]; /* globals and ins */
- } si_regs;
- int si_mask;
-} __siginfo_t;
-
-typedef struct {
- unsigned long si_float_regs [32];
- unsigned long si_fsr;
- unsigned long si_fpqdepth;
- struct {
- unsigned long *insn_addr;
- unsigned long insn;
- } si_fpqueue [16];
-} __siginfo_fpu_t;
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* (__KERNEL__) */
-
-#endif /* !(__SPARC_SIGCONTEXT_H) */
diff --git a/arch/sparc/include/asm/sigcontext_64.h b/arch/sparc/include/asm/sigcontext_64.h
deleted file mode 100644
index 1c868d680cfc..000000000000
--- a/arch/sparc/include/asm/sigcontext_64.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef __SPARC64_SIGCONTEXT_H
-#define __SPARC64_SIGCONTEXT_H
-
-#ifdef __KERNEL__
-#include <asm/ptrace.h>
-#endif
-
-#ifndef __ASSEMBLY__
-
-#ifdef __KERNEL__
-
-#define __SUNOS_MAXWIN 31
-
-/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
-struct sigcontext32 {
- int sigc_onstack; /* state to restore */
- int sigc_mask; /* sigmask to restore */
- int sigc_sp; /* stack pointer */
- int sigc_pc; /* program counter */
- int sigc_npc; /* next program counter */
- int sigc_psr; /* for condition codes etc */
- int sigc_g1; /* User uses these two registers */
- int sigc_o0; /* within the trampoline code. */
-
- /* Now comes information regarding the users window set
- * at the time of the signal.
- */
- int sigc_oswins; /* outstanding windows */
-
- /* stack ptrs for each regwin buf */
- unsigned sigc_spbuf[__SUNOS_MAXWIN];
-
- /* Windows to restore after signal */
- struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
-};
-
-#endif
-
-#ifdef __KERNEL__
-
-/* This is what we use for 32bit new non-rt signals. */
-
-typedef struct {
- struct {
- unsigned int psr;
- unsigned int pc;
- unsigned int npc;
- unsigned int y;
- unsigned int u_regs[16]; /* globals and ins */
- } si_regs;
- int si_mask;
-} __siginfo32_t;
-
-#endif
-
-typedef struct {
- unsigned int si_float_regs [64];
- unsigned long si_fsr;
- unsigned long si_gsr;
- unsigned long si_fprs;
-} __siginfo_fpu_t;
-
-/* This is what SunOS doesn't, so we have to write this alone
- and do it properly. */
-struct sigcontext {
- /* The size of this array has to match SI_MAX_SIZE from siginfo.h */
- char sigc_info[128];
- struct {
- unsigned long u_regs[16]; /* globals and ins */
- unsigned long tstate;
- unsigned long tpc;
- unsigned long tnpc;
- unsigned int y;
- unsigned int fprs;
- } sigc_regs;
- __siginfo_fpu_t * sigc_fpu_save;
- struct {
- void * ss_sp;
- int ss_flags;
- unsigned long ss_size;
- } sigc_stack;
- unsigned long sigc_mask;
-};
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_SIGCONTEXT_H) */
diff --git a/arch/sparc/include/asm/siginfo.h b/arch/sparc/include/asm/siginfo.h
index bd81f8d7f5ce..988e5d8ed11a 100644
--- a/arch/sparc/include/asm/siginfo.h
+++ b/arch/sparc/include/asm/siginfo.h
@@ -1,8 +1,37 @@
-#ifndef ___ASM_SPARC_SIGINFO_H
-#define ___ASM_SPARC_SIGINFO_H
+#ifndef __SPARC_SIGINFO_H
+#define __SPARC_SIGINFO_H
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/siginfo_64.h>
-#else
-#include <asm/siginfo_32.h>
-#endif
-#endif
+
+#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
+#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+#define __ARCH_SI_BAND_T int
+
+#endif /* defined(__sparc__) && defined(__arch64__) */
+
+
+#define __ARCH_SI_TRAPNO
+
+#include <asm-generic/siginfo.h>
+
+#ifdef __KERNEL__
+
+#include <linux/compat.h>
+
+#ifdef CONFIG_COMPAT
+
+struct compat_siginfo;
+
+#endif /* CONFIG_COMPAT */
+
+#endif /* __KERNEL__ */
+
+#define SI_NOINFO 32767 /* no information in siginfo_t */
+
+/*
+ * SIGEMT si_codes
+ */
+#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
+#define NSIGEMT 1
+
+#endif /* !(__SPARC_SIGINFO_H) */
diff --git a/arch/sparc/include/asm/siginfo_32.h b/arch/sparc/include/asm/siginfo_32.h
deleted file mode 100644
index 3c71af135c52..000000000000
--- a/arch/sparc/include/asm/siginfo_32.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _SPARC_SIGINFO_H
-#define _SPARC_SIGINFO_H
-
-#define __ARCH_SI_UID_T unsigned int
-#define __ARCH_SI_TRAPNO
-
-#include <asm-generic/siginfo.h>
-
-#define SI_NOINFO 32767 /* no information in siginfo_t */
-
-/*
- * SIGEMT si_codes
- */
-#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
-#define NSIGEMT 1
-
-#endif /* !(_SPARC_SIGINFO_H) */
diff --git a/arch/sparc/include/asm/siginfo_64.h b/arch/sparc/include/asm/siginfo_64.h
deleted file mode 100644
index c96e6c30f8b0..000000000000
--- a/arch/sparc/include/asm/siginfo_64.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _SPARC64_SIGINFO_H
-#define _SPARC64_SIGINFO_H
-
-#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
-
-#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
-#define __ARCH_SI_TRAPNO
-#define __ARCH_SI_BAND_T int
-
-#include <asm-generic/siginfo.h>
-
-#ifdef __KERNEL__
-
-#include <linux/compat.h>
-
-#ifdef CONFIG_COMPAT
-
-struct compat_siginfo;
-
-#endif /* CONFIG_COMPAT */
-
-#endif /* __KERNEL__ */
-
-#define SI_NOINFO 32767 /* no information in siginfo_t */
-
-/*
- * SIGEMT si_codes
- */
-#define EMT_TAGOVF (__SI_FAULT|1) /* tag overflow */
-#define NSIGEMT 1
-
-#endif
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h
index 27ab05dc203e..cba45206b7f2 100644
--- a/arch/sparc/include/asm/signal.h
+++ b/arch/sparc/include/asm/signal.h
@@ -1,8 +1,214 @@
-#ifndef ___ASM_SPARC_SIGNAL_H
-#define ___ASM_SPARC_SIGNAL_H
-#if defined(__sparc__) && defined(__arch64__)
-#include <asm/signal_64.h>
+#ifndef __SPARC_SIGNAL_H
+#define __SPARC_SIGNAL_H
+
+#include <asm/sigcontext.h>
+#include <linux/compiler.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#include <linux/personality.h>
+#include <linux/types.h>
+#endif
+#endif
+
+/* On the Sparc the signal handlers get passed a 'sub-signal' code
+ * for certain signal types, which we document here.
+ */
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SUBSIG_STACK 0
+#define SUBSIG_ILLINST 2
+#define SUBSIG_PRIVINST 3
+#define SUBSIG_BADTRAP(t) (0x80 + (t))
+
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+
+#define SIGEMT 7
+#define SUBSIG_TAG 10
+
+#define SIGFPE 8
+#define SUBSIG_FPDISABLED 0x400
+#define SUBSIG_FPERROR 0x404
+#define SUBSIG_FPINTOVFL 0x001
+#define SUBSIG_FPSTSIG 0x002
+#define SUBSIG_IDIVZERO 0x014
+#define SUBSIG_FPINEXACT 0x0c4
+#define SUBSIG_FPDIVZERO 0x0c8
+#define SUBSIG_FPUNFLOW 0x0cc
+#define SUBSIG_FPOPERROR 0x0d0
+#define SUBSIG_FPOVFLOW 0x0d4
+
+#define SIGKILL 9
+#define SIGBUS 10
+#define SUBSIG_BUSTIMEOUT 1
+#define SUBSIG_ALIGNMENT 2
+#define SUBSIG_MISCERROR 5
+
+#define SIGSEGV 11
+#define SUBSIG_NOMAPPING 3
+#define SUBSIG_PROTECTION 4
+#define SUBSIG_SEGERROR 5
+
+#define SIGSYS 12
+
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGURG 16
+
+/* SunOS values which deviate from the Linux/i386 ones */
+#define SIGSTOP 17
+#define SIGTSTP 18
+#define SIGCONT 19
+#define SIGCHLD 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGIO 23
+#define SIGPOLL SIGIO /* SysV name for SIGIO */
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGLOST 29
+#define SIGPWR SIGLOST
+#define SIGUSR1 30
+#define SIGUSR2 31
+
+/* Most things should be clean enough to redefine this at will, if care
+ is taken to make libc match. */
+
+#define __OLD_NSIG 32
+#define __NEW_NSIG 64
+#ifdef __arch64__
+#define _NSIG_BPW 64
+#else
+#define _NSIG_BPW 32
+#endif
+#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
+
+#define SIGRTMIN 32
+#define SIGRTMAX __NEW_NSIG
+
+#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
+#define _NSIG __NEW_NSIG
+#define __new_sigset_t sigset_t
+#define __new_sigaction sigaction
+#define __new_sigaction32 sigaction32
+#define __old_sigset_t old_sigset_t
+#define __old_sigaction old_sigaction
+#define __old_sigaction32 old_sigaction32
#else
-#include <asm/signal_32.h>
+#define _NSIG __OLD_NSIG
+#define NSIG _NSIG
+#define __old_sigset_t sigset_t
+#define __old_sigaction sigaction
+#define __old_sigaction32 sigaction32
#endif
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long __old_sigset_t; /* at least 32 bits */
+
+typedef struct {
+ unsigned long sig[_NSIG_WORDS];
+} __new_sigset_t;
+
+/* A SunOS sigstack */
+struct sigstack {
+ /* XXX 32-bit pointers pinhead XXX */
+ char *the_stack;
+ int cur_status;
+};
+
+/* Sigvec flags */
+#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
+#define _SV_INTR 2u /* Sig return should not restart system call */
+#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
+#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_NOCLDSTOP _SV_IGNCHILD
+#define SA_STACK _SV_SSTACK
+#define SA_ONSTACK _SV_SSTACK
+#define SA_RESTART _SV_INTR
+#define SA_ONESHOT _SV_RESET
+#define SA_NOMASK 0x20u
+#define SA_NOCLDWAIT 0x100u
+#define SA_SIGINFO 0x200u
+
+
+#define SIG_BLOCK 0x01 /* for blocking signals */
+#define SIG_UNBLOCK 0x02 /* for unblocking signals */
+#define SIG_SETMASK 0x04 /* for setting the signal mask */
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 4096
+#define SIGSTKSZ 16384
+
+#ifdef __KERNEL__
+/*
+ * DJHR
+ * SA_STATIC_ALLOC is used for the sparc32 system to indicate that this
+ * interrupt handler's irq structure should be statically allocated
+ * by the request_irq routine.
+ * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
+ * of interrupt usage and that sucks. Also without a flag like this
+ * it may be possible for the free_irq routine to attempt to free
+ * statically allocated data.. which is NOT GOOD.
+ *
+ */
+#define SA_STATIC_ALLOC 0x8000
#endif
+
+#include <asm-generic/signal.h>
+
+struct __new_sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ __sigrestore_t sa_restorer; /* not used by Linux/SPARC yet */
+ __new_sigset_t sa_mask;
+};
+
+struct __old_sigaction {
+ __sighandler_t sa_handler;
+ __old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void); /* not used by Linux/SPARC yet */
+};
+
+typedef struct sigaltstack {
+ void __user *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+
+struct k_sigaction {
+ struct __new_sigaction sa;
+ void __user *ka_restorer;
+};
+
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif /* !(__KERNEL__) */
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/signal_32.h b/arch/sparc/include/asm/signal_32.h
deleted file mode 100644
index 96a60ab03ca1..000000000000
--- a/arch/sparc/include/asm/signal_32.h
+++ /dev/null
@@ -1,207 +0,0 @@
-#ifndef _ASMSPARC_SIGNAL_H
-#define _ASMSPARC_SIGNAL_H
-
-#include <asm/sigcontext.h>
-#include <linux/compiler.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-#include <linux/personality.h>
-#include <linux/types.h>
-#endif
-#endif
-
-/* On the Sparc the signal handlers get passed a 'sub-signal' code
- * for certain signal types, which we document here.
- */
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SUBSIG_STACK 0
-#define SUBSIG_ILLINST 2
-#define SUBSIG_PRIVINST 3
-#define SUBSIG_BADTRAP(t) (0x80 + (t))
-
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-
-#define SIGEMT 7
-#define SUBSIG_TAG 10
-
-#define SIGFPE 8
-#define SUBSIG_FPDISABLED 0x400
-#define SUBSIG_FPERROR 0x404
-#define SUBSIG_FPINTOVFL 0x001
-#define SUBSIG_FPSTSIG 0x002
-#define SUBSIG_IDIVZERO 0x014
-#define SUBSIG_FPINEXACT 0x0c4
-#define SUBSIG_FPDIVZERO 0x0c8
-#define SUBSIG_FPUNFLOW 0x0cc
-#define SUBSIG_FPOPERROR 0x0d0
-#define SUBSIG_FPOVFLOW 0x0d4
-
-#define SIGKILL 9
-#define SIGBUS 10
-#define SUBSIG_BUSTIMEOUT 1
-#define SUBSIG_ALIGNMENT 2
-#define SUBSIG_MISCERROR 5
-
-#define SIGSEGV 11
-#define SUBSIG_NOMAPPING 3
-#define SUBSIG_PROTECTION 4
-#define SUBSIG_SEGERROR 5
-
-#define SIGSYS 12
-
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGURG 16
-
-/* SunOS values which deviate from the Linux/i386 ones */
-#define SIGSTOP 17
-#define SIGTSTP 18
-#define SIGCONT 19
-#define SIGCHLD 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGIO 23
-#define SIGPOLL SIGIO /* SysV name for SIGIO */
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGLOST 29
-#define SIGPWR SIGLOST
-#define SIGUSR1 30
-#define SIGUSR2 31
-
-/* Most things should be clean enough to redefine this at will, if care
- * is taken to make libc match.
- */
-
-#define __OLD_NSIG 32
-#define __NEW_NSIG 64
-#define _NSIG_BPW 32
-#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
-
-#define SIGRTMIN 32
-#define SIGRTMAX __NEW_NSIG
-
-#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
-#define _NSIG __NEW_NSIG
-#define __new_sigset_t sigset_t
-#define __new_sigaction sigaction
-#define __old_sigset_t old_sigset_t
-#define __old_sigaction old_sigaction
-#else
-#define _NSIG __OLD_NSIG
-#define __old_sigset_t sigset_t
-#define __old_sigaction sigaction
-#endif
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long __old_sigset_t;
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} __new_sigset_t;
-
-
-#ifdef __KERNEL__
-/* A SunOS sigstack */
-struct sigstack {
- char *the_stack;
- int cur_status;
-};
-#endif
-
-/* Sigvec flags */
-#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
-#define _SV_INTR 2u /* Sig return should not restart system call */
-#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
-#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
-
-/*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- */
-#define SA_NOCLDSTOP _SV_IGNCHILD
-#define SA_STACK _SV_SSTACK
-#define SA_ONSTACK _SV_SSTACK
-#define SA_RESTART _SV_INTR
-#define SA_ONESHOT _SV_RESET
-#define SA_NOMASK 0x20u
-#define SA_NOCLDWAIT 0x100u
-#define SA_SIGINFO 0x200u
-
-#define SIG_BLOCK 0x01 /* for blocking signals */
-#define SIG_UNBLOCK 0x02 /* for unblocking signals */
-#define SIG_SETMASK 0x04 /* for setting the signal mask */
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK 1
-#define SS_DISABLE 2
-
-#define MINSIGSTKSZ 4096
-#define SIGSTKSZ 16384
-
-#ifdef __KERNEL__
-/*
- * DJHR
- * SA_STATIC_ALLOC is used for the SPARC system to indicate that this
- * interrupt handler's irq structure should be statically allocated
- * by the request_irq routine.
- * The alternative is that arch/sparc/kernel/irq.c has carnal knowledge
- * of interrupt usage and that sucks. Also without a flag like this
- * it may be possible for the free_irq routine to attempt to free
- * statically allocated data.. which is NOT GOOD.
- *
- */
-#define SA_STATIC_ALLOC 0x8000
-#endif
-
-#include <asm-generic/signal.h>
-
-#ifdef __KERNEL__
-struct __new_sigaction {
- __sighandler_t sa_handler;
- unsigned long sa_flags;
- void (*sa_restorer)(void); /* Not used by Linux/SPARC */
- __new_sigset_t sa_mask;
-};
-
-struct k_sigaction {
- struct __new_sigaction sa;
- void __user *ka_restorer;
-};
-
-struct __old_sigaction {
- __sighandler_t sa_handler;
- __old_sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer) (void); /* not used by Linux/SPARC */
-};
-
-typedef struct sigaltstack {
- void __user *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_ASMSPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/signal_64.h b/arch/sparc/include/asm/signal_64.h
deleted file mode 100644
index ab1509a101c5..000000000000
--- a/arch/sparc/include/asm/signal_64.h
+++ /dev/null
@@ -1,194 +0,0 @@
-#ifndef _ASMSPARC64_SIGNAL_H
-#define _ASMSPARC64_SIGNAL_H
-
-#include <asm/sigcontext.h>
-
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-#include <linux/personality.h>
-#include <linux/types.h>
-#endif
-#endif
-
-/* On the Sparc the signal handlers get passed a 'sub-signal' code
- * for certain signal types, which we document here.
- */
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SUBSIG_STACK 0
-#define SUBSIG_ILLINST 2
-#define SUBSIG_PRIVINST 3
-#define SUBSIG_BADTRAP(t) (0x80 + (t))
-
-#define SIGTRAP 5
-#define SIGABRT 6
-#define SIGIOT 6
-
-#define SIGEMT 7
-#define SUBSIG_TAG 10
-
-#define SIGFPE 8
-#define SUBSIG_FPDISABLED 0x400
-#define SUBSIG_FPERROR 0x404
-#define SUBSIG_FPINTOVFL 0x001
-#define SUBSIG_FPSTSIG 0x002
-#define SUBSIG_IDIVZERO 0x014
-#define SUBSIG_FPINEXACT 0x0c4
-#define SUBSIG_FPDIVZERO 0x0c8
-#define SUBSIG_FPUNFLOW 0x0cc
-#define SUBSIG_FPOPERROR 0x0d0
-#define SUBSIG_FPOVFLOW 0x0d4
-
-#define SIGKILL 9
-#define SIGBUS 10
-#define SUBSIG_BUSTIMEOUT 1
-#define SUBSIG_ALIGNMENT 2
-#define SUBSIG_MISCERROR 5
-
-#define SIGSEGV 11
-#define SUBSIG_NOMAPPING 3
-#define SUBSIG_PROTECTION 4
-#define SUBSIG_SEGERROR 5
-
-#define SIGSYS 12
-
-#define SIGPIPE 13
-#define SIGALRM 14
-#define SIGTERM 15
-#define SIGURG 16
-
-/* SunOS values which deviate from the Linux/i386 ones */
-#define SIGSTOP 17
-#define SIGTSTP 18
-#define SIGCONT 19
-#define SIGCHLD 20
-#define SIGTTIN 21
-#define SIGTTOU 22
-#define SIGIO 23
-#define SIGPOLL SIGIO /* SysV name for SIGIO */
-#define SIGXCPU 24
-#define SIGXFSZ 25
-#define SIGVTALRM 26
-#define SIGPROF 27
-#define SIGWINCH 28
-#define SIGLOST 29
-#define SIGPWR SIGLOST
-#define SIGUSR1 30
-#define SIGUSR2 31
-
-/* Most things should be clean enough to redefine this at will, if care
- is taken to make libc match. */
-
-#define __OLD_NSIG 32
-#define __NEW_NSIG 64
-#define _NSIG_BPW 64
-#define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW)
-
-#define SIGRTMIN 32
-#define SIGRTMAX __NEW_NSIG
-
-#if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__)
-#define _NSIG __NEW_NSIG
-#define __new_sigset_t sigset_t
-#define __new_sigaction sigaction
-#define __new_sigaction32 sigaction32
-#define __old_sigset_t old_sigset_t
-#define __old_sigaction old_sigaction
-#define __old_sigaction32 old_sigaction32
-#else
-#define _NSIG __OLD_NSIG
-#define NSIG _NSIG
-#define __old_sigset_t sigset_t
-#define __old_sigaction sigaction
-#define __old_sigaction32 sigaction32
-#endif
-
-#ifndef __ASSEMBLY__
-
-typedef unsigned long __old_sigset_t; /* at least 32 bits */
-
-typedef struct {
- unsigned long sig[_NSIG_WORDS];
-} __new_sigset_t;
-
-/* A SunOS sigstack */
-struct sigstack {
- /* XXX 32-bit pointers pinhead XXX */
- char *the_stack;
- int cur_status;
-};
-
-/* Sigvec flags */
-#define _SV_SSTACK 1u /* This signal handler should use sig-stack */
-#define _SV_INTR 2u /* Sig return should not restart system call */
-#define _SV_RESET 4u /* Set handler to SIG_DFL upon taken signal */
-#define _SV_IGNCHILD 8u /* Do not send SIGCHLD */
-
-/*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- */
-#define SA_NOCLDSTOP _SV_IGNCHILD
-#define SA_STACK _SV_SSTACK
-#define SA_ONSTACK _SV_SSTACK
-#define SA_RESTART _SV_INTR
-#define SA_ONESHOT _SV_RESET
-#define SA_NOMASK 0x20u
-#define SA_NOCLDWAIT 0x100u
-#define SA_SIGINFO 0x200u
-
-
-#define SIG_BLOCK 0x01 /* for blocking signals */
-#define SIG_UNBLOCK 0x02 /* for unblocking signals */
-#define SIG_SETMASK 0x04 /* for setting the signal mask */
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK 1
-#define SS_DISABLE 2
-
-#define MINSIGSTKSZ 4096
-#define SIGSTKSZ 16384
-
-#include <asm-generic/signal.h>
-
-struct __new_sigaction {
- __sighandler_t sa_handler;
- unsigned long sa_flags;
- __sigrestore_t sa_restorer; /* not used by Linux/SPARC yet */
- __new_sigset_t sa_mask;
-};
-
-struct __old_sigaction {
- __sighandler_t sa_handler;
- __old_sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void); /* not used by Linux/SPARC yet */
-};
-
-typedef struct sigaltstack {
- void __user *ss_sp;
- int ss_flags;
- size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
-struct k_sigaction {
- struct __new_sigaction sa;
- void __user *ka_restorer;
-};
-
-#define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#endif /* !(__KERNEL__) */
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(_ASMSPARC64_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index a8180e546a48..58101dc70493 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -29,8 +29,6 @@
*/
extern unsigned char boot_cpu_id;
-extern cpumask_t phys_cpu_present_map;
-#define cpu_possible_map phys_cpu_present_map
typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long);
@@ -172,7 +170,4 @@ void smp_setup_cpu_possible_map(void);
#define smp_setup_cpu_possible_map() do { } while (0)
#endif /* !(SMP) */
-
-#define NO_PROC_ID 0xFF
-
#endif /* !(_SPARC_SMP_H) */
diff --git a/arch/sparc/include/asm/stat.h b/arch/sparc/include/asm/stat.h
index d8153013df72..55db5eca08e2 100644
--- a/arch/sparc/include/asm/stat.h
+++ b/arch/sparc/include/asm/stat.h
@@ -1,8 +1,107 @@
-#ifndef ___ASM_SPARC_STAT_H
-#define ___ASM_SPARC_STAT_H
+#ifndef __SPARC_STAT_H
+#define __SPARC_STAT_H
+
+#include <linux/types.h>
+
#if defined(__sparc__) && defined(__arch64__)
-#include <asm/stat_64.h>
+/* 64 bit sparc */
+struct stat {
+ unsigned st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ short st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned st_rdev;
+ off_t st_size;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+ off_t st_blksize;
+ off_t st_blocks;
+ unsigned long __unused4[2];
+};
+
+struct stat64 {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad0;
+
+ unsigned long st_rdev;
+ long st_size;
+ long st_blksize;
+ long st_blocks;
+
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ long __unused[3];
+};
+
#else
-#include <asm/stat_32.h>
-#endif
-#endif
+/* 32 bit sparc */
+struct stat {
+ unsigned short st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ short st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ unsigned short st_rdev;
+ off_t st_size;
+ time_t st_atime;
+ unsigned long st_atime_nsec;
+ time_t st_mtime;
+ unsigned long st_mtime_nsec;
+ time_t st_ctime;
+ unsigned long st_ctime_nsec;
+ off_t st_blksize;
+ off_t st_blocks;
+ unsigned long __unused4[2];
+};
+
+#define STAT_HAVE_NSEC 1
+
+struct stat64 {
+ unsigned long long st_dev;
+
+ unsigned long long st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned int st_uid;
+ unsigned int st_gid;
+
+ unsigned long long st_rdev;
+
+ unsigned char __pad3[8];
+
+ long long st_size;
+ unsigned int st_blksize;
+
+ unsigned char __pad4[8];
+ unsigned int st_blocks;
+
+ unsigned int st_atime;
+ unsigned int st_atime_nsec;
+
+ unsigned int st_mtime;
+ unsigned int st_mtime_nsec;
+
+ unsigned int st_ctime;
+ unsigned int st_ctime_nsec;
+
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+#endif /* defined(__sparc__) && defined(__arch64__) */
+#endif /* __SPARC_STAT_H */
diff --git a/arch/sparc/include/asm/stat_32.h b/arch/sparc/include/asm/stat_32.h
deleted file mode 100644
index 2299e1d5d94c..000000000000
--- a/arch/sparc/include/asm/stat_32.h
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef _SPARC_STAT_H
-#define _SPARC_STAT_H
-
-#include <linux/types.h>
-
-struct __old_kernel_stat {
- unsigned short st_dev;
- unsigned short st_ino;
- unsigned short st_mode;
- unsigned short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- unsigned long st_size;
- unsigned long st_atime;
- unsigned long st_mtime;
- unsigned long st_ctime;
-};
-
-struct stat {
- unsigned short st_dev;
- unsigned long st_ino;
- unsigned short st_mode;
- short st_nlink;
- unsigned short st_uid;
- unsigned short st_gid;
- unsigned short st_rdev;
- long st_size;
- long st_atime;
- unsigned long st_atime_nsec;
- long st_mtime;
- unsigned long st_mtime_nsec;
- long st_ctime;
- unsigned long st_ctime_nsec;
- long st_blksize;
- long st_blocks;
- unsigned long __unused4[2];
-};
-
-#define STAT_HAVE_NSEC 1
-
-struct stat64 {
- unsigned long long st_dev;
-
- unsigned long long st_ino;
-
- unsigned int st_mode;
- unsigned int st_nlink;
-
- unsigned int st_uid;
- unsigned int st_gid;
-
- unsigned long long st_rdev;
-
- unsigned char __pad3[8];
-
- long long st_size;
- unsigned int st_blksize;
-
- unsigned char __pad4[8];
- unsigned int st_blocks;
-
- unsigned int st_atime;
- unsigned int st_atime_nsec;
-
- unsigned int st_mtime;
- unsigned int st_mtime_nsec;
-
- unsigned int st_ctime;
- unsigned int st_ctime_nsec;
-
- unsigned int __unused4;
- unsigned int __unused5;
-};
-
-#endif
diff --git a/arch/sparc/include/asm/stat_64.h b/arch/sparc/include/asm/stat_64.h
deleted file mode 100644
index 9650fdea847f..000000000000
--- a/arch/sparc/include/asm/stat_64.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _SPARC64_STAT_H
-#define _SPARC64_STAT_H
-
-#include <linux/types.h>
-
-struct stat {
- unsigned st_dev;
- ino_t st_ino;
- mode_t st_mode;
- short st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- unsigned st_rdev;
- off_t st_size;
- time_t st_atime;
- time_t st_mtime;
- time_t st_ctime;
- off_t st_blksize;
- off_t st_blocks;
- unsigned long __unused4[2];
-};
-
-struct stat64 {
- unsigned long st_dev;
- unsigned long st_ino;
- unsigned long st_nlink;
-
- unsigned int st_mode;
- unsigned int st_uid;
- unsigned int st_gid;
- unsigned int __pad0;
-
- unsigned long st_rdev;
- long st_size;
- long st_blksize;
- long st_blocks;
-
- unsigned long st_atime;
- unsigned long st_atime_nsec;
- unsigned long st_mtime;
- unsigned long st_mtime_nsec;
- unsigned long st_ctime;
- unsigned long st_ctime_nsec;
- long __unused[3];
-};
-
-#endif
diff --git a/arch/sparc/include/asm/swab.h b/arch/sparc/include/asm/swab.h
new file mode 100644
index 000000000000..a34ad079487e
--- /dev/null
+++ b/arch/sparc/include/asm/swab.h
@@ -0,0 +1,45 @@
+#ifndef _SPARC_SWAB_H
+#define _SPARC_SWAB_H
+
+#include <linux/types.h>
+#include <asm/asi.h>
+
+#if defined(__sparc__) && defined(__arch64__)
+static inline __u16 __arch_swab16p(const __u16 *addr)
+{
+ __u16 ret;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PL));
+ return ret;
+}
+#define __arch_swab16p __arch_swab16p
+
+static inline __u32 __arch_swab32p(const __u32 *addr)
+{
+ __u32 ret;
+
+ __asm__ __volatile__ ("lduwa [%1] %2, %0"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PL));
+ return ret;
+}
+#define __arch_swab32p __arch_swab32p
+
+static inline __u64 __arch_swab64p(const __u64 *addr)
+{
+ __u64 ret;
+
+ __asm__ __volatile__ ("ldxa [%1] %2, %0"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PL));
+ return ret;
+}
+#define __arch_swab64p __arch_swab64p
+
+#else
+#define __SWAB_64_THRU_32__
+#endif /* defined(__sparc__) && defined(__arch64__) */
+
+#endif /* _SPARC_SWAB_H */
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index 80fe547c3f45..0f7b0e5fb1c7 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -45,7 +45,7 @@ struct thread_info {
/* A place to store user windows and stack pointers
* when the stack needs inspection.
*/
- struct reg_window reg_window[NSWINS]; /* align for ldd! */
+ struct reg_window32 reg_window[NSWINS]; /* align for ldd! */
unsigned long rwbuf_stkptrs[NSWINS];
unsigned long w_saved;
diff --git a/arch/sparc/include/asm/timer_64.h b/arch/sparc/include/asm/timer_64.h
index 5b779fd1f788..ef3c3682debf 100644
--- a/arch/sparc/include/asm/timer_64.h
+++ b/arch/sparc/include/asm/timer_64.h
@@ -10,7 +10,7 @@
#include <linux/init.h>
struct sparc64_tick_ops {
- unsigned long (*get_tick)(void);
+ unsigned long long (*get_tick)(void);
int (*add_compare)(unsigned long);
unsigned long softint_mask;
void (*disable_irq)(void);
diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h
index 001c04027c82..5bc0b8fd6374 100644
--- a/arch/sparc/include/asm/topology_64.h
+++ b/arch/sparc/include/asm/topology_64.h
@@ -16,8 +16,12 @@ static inline cpumask_t node_to_cpumask(int node)
{
return numa_cpumask_lookup_table[node];
}
+#define cpumask_of_node(node) (&numa_cpumask_lookup_table[node])
-/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
+/*
+ * Returns a pointer to the cpumask of CPUs on Node 'node'.
+ * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)"
+ */
#define node_to_cpumask_ptr(v, node) \
cpumask_t *v = &(numa_cpumask_lookup_table[node])
@@ -26,9 +30,7 @@ static inline cpumask_t node_to_cpumask(int node)
static inline int node_to_first_cpu(int node)
{
- cpumask_t tmp;
- tmp = node_to_cpumask(node);
- return first_cpu(tmp);
+ return cpumask_first(cpumask_of_node(node));
}
struct pci_bus;
@@ -45,6 +47,10 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
(pcibus_to_node(bus) == -1 ? \
CPU_MASK_ALL : \
node_to_cpumask(pcibus_to_node(bus)))
+#define cpumask_of_pcibus(bus) \
+ (pcibus_to_node(bus) == -1 ? \
+ CPU_MASK_ALL_PTR : \
+ cpumask_of_node(pcibus_to_node(bus)))
#define SD_NODE_INIT (struct sched_domain) { \
.min_interval = 8, \
@@ -77,10 +83,13 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
#define topology_core_siblings(cpu) (cpu_core_map[cpu])
#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
+#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
+#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
#define mc_capable() (sparc64_multi_core)
#define smt_capable() (sparc64_multi_core)
#endif /* CONFIG_SMP */
#define cpu_coregroup_map(cpu) (cpu_core_map[cpu])
+#define cpu_coregroup_mask(cpu) (&cpu_core_map[cpu])
#endif /* _ASM_SPARC64_TOPOLOGY_H */
diff --git a/arch/sparc/include/asm/traps.h b/arch/sparc/include/asm/traps.h
index bebdbf8f43a8..3aa62dde343f 100644
--- a/arch/sparc/include/asm/traps.h
+++ b/arch/sparc/include/asm/traps.h
@@ -10,7 +10,7 @@
#define NUM_SPARC_TRAPS 255
#ifndef __ASSEMBLY__
-
+#ifdef __KERNEL__
/* This is for V8 compliant Sparc CPUS */
struct tt_entry {
unsigned long inst_one;
@@ -22,14 +22,7 @@ struct tt_entry {
/* We set this to _start in system setup. */
extern struct tt_entry *sparc_ttable;
-static inline unsigned long get_tbr(void)
-{
- unsigned long tbr;
-
- __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (tbr));
- return tbr;
-}
-
+#endif /* (__KERNEL__) */
#endif /* !(__ASSEMBLY__) */
/* For patching the trap table at boot time, we need to know how to
diff --git a/arch/sparc/include/asm/types.h b/arch/sparc/include/asm/types.h
index 8c28fde5eaa2..2237118825d0 100644
--- a/arch/sparc/include/asm/types.h
+++ b/arch/sparc/include/asm/types.h
@@ -11,7 +11,7 @@
#if defined(__sparc__) && defined(__arch64__)
/*** SPARC 64 bit ***/
-#include <asm-generic/int-l64.h>
+#include <asm-generic/int-ll64.h>
#ifndef __ASSEMBLY__
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 53adcaa0348b..54742e58831c 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -52,6 +52,8 @@ obj-$(CONFIG_SPARC64) += visemul.o
obj-$(CONFIG_SPARC64) += hvapi.o
obj-$(CONFIG_SPARC64) += sstate.o
obj-$(CONFIG_SPARC64) += mdesc.o
+obj-$(CONFIG_SPARC64) += pcr.o
+obj-$(CONFIG_SPARC64) += nmi.o
# sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation
obj-$(CONFIG_SPARC32) += devres.o
diff --git a/arch/sparc/kernel/auxio_32.c b/arch/sparc/kernel/auxio_32.c
index 09c857215a52..45c41232fc4c 100644
--- a/arch/sparc/kernel/auxio_32.c
+++ b/arch/sparc/kernel/auxio_32.c
@@ -76,6 +76,7 @@ unsigned char get_auxio(void)
return sbus_readb(auxio_register);
return 0;
}
+EXPORT_SYMBOL(get_auxio);
void set_auxio(unsigned char bits_on, unsigned char bits_off)
{
@@ -102,7 +103,7 @@ void set_auxio(unsigned char bits_on, unsigned char bits_off)
};
spin_unlock_irqrestore(&auxio_lock, flags);
}
-
+EXPORT_SYMBOL(set_auxio);
/* sun4m power control register (AUXIO2) */
diff --git a/arch/sparc/kernel/auxio_64.c b/arch/sparc/kernel/auxio_64.c
index 8b67347d4221..9f52db2d441c 100644
--- a/arch/sparc/kernel/auxio_64.c
+++ b/arch/sparc/kernel/auxio_64.c
@@ -72,6 +72,7 @@ void auxio_set_led(int on)
bit = (ebus ? AUXIO_PCIO_LED : AUXIO_AUX1_LED);
__auxio_set_bit(bit, on, ebus);
}
+EXPORT_SYMBOL(auxio_set_led);
static void __auxio_sbus_set_lte(int on)
{
@@ -90,6 +91,7 @@ void auxio_set_lte(int on)
break;
}
}
+EXPORT_SYMBOL(auxio_set_lte);
static struct of_device_id __initdata auxio_match[] = {
{
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c
index 05f1c916db06..f3b5466c389c 100644
--- a/arch/sparc/kernel/central.c
+++ b/arch/sparc/kernel/central.c
@@ -103,6 +103,7 @@ static int __devinit clock_board_probe(struct of_device *op,
p->leds_resource.name = "leds";
p->leds_pdev.name = "sunfire-clockboard-leds";
+ p->leds_pdev.id = -1;
p->leds_pdev.resource = &p->leds_resource;
p->leds_pdev.num_resources = 1;
p->leds_pdev.dev.parent = &op->dev;
@@ -197,6 +198,7 @@ static int __devinit fhc_probe(struct of_device *op,
p->leds_resource.name = "leds";
p->leds_pdev.name = "sunfire-fhc-leds";
+ p->leds_pdev.id = p->board_num;
p->leds_pdev.resource = &p->leds_resource;
p->leds_pdev.num_resources = 1;
p->leds_pdev.dev.parent = &op->dev;
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
index 6c2da2420f76..d85c3dc4953a 100644
--- a/arch/sparc/kernel/cpu.c
+++ b/arch/sparc/kernel/cpu.c
@@ -5,6 +5,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/threads.h>
@@ -20,10 +21,12 @@
#include "kernel.h"
DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
+EXPORT_PER_CPU_SYMBOL(__cpu_data);
struct cpu_info {
int psr_vers;
const char *name;
+ const char *pmu_name;
};
struct fpu_info {
@@ -43,6 +46,9 @@ struct manufacturer_info {
#define CPU(ver, _name) \
{ .psr_vers = ver, .name = _name }
+#define CPU_PMU(ver, _name, _pmu_name) \
+{ .psr_vers = ver, .name = _name, .pmu_name = _pmu_name }
+
#define FPU(ver, _name) \
{ .fp_vers = ver, .name = _name }
@@ -181,10 +187,10 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
},{
0x17,
.cpu_info = {
- CPU(0x10, "TI UltraSparc I (SpitFire)"),
- CPU(0x11, "TI UltraSparc II (BlackBird)"),
- CPU(0x12, "TI UltraSparc IIi (Sabre)"),
- CPU(0x13, "TI UltraSparc IIe (Hummingbird)"),
+ CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"),
+ CPU_PMU(0x11, "TI UltraSparc II (BlackBird)", "ultra12"),
+ CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"),
+ CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"),
CPU(-1, NULL)
},
.fpu_info = {
@@ -197,7 +203,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
},{
0x22,
.cpu_info = {
- CPU(0x10, "TI UltraSparc I (SpitFire)"),
+ CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"),
CPU(-1, NULL)
},
.fpu_info = {
@@ -207,12 +213,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
},{
0x3e,
.cpu_info = {
- CPU(0x14, "TI UltraSparc III (Cheetah)"),
- CPU(0x15, "TI UltraSparc III+ (Cheetah+)"),
- CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"),
- CPU(0x18, "TI UltraSparc IV (Jaguar)"),
- CPU(0x19, "TI UltraSparc IV+ (Panther)"),
- CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"),
+ CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"),
+ CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"),
+ CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"),
+ CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"),
+ CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"),
+ CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"),
CPU(-1, NULL)
},
.fpu_info = {
@@ -232,29 +238,44 @@ static const struct manufacturer_info __initconst manufacturer_info[] = {
const char *sparc_cpu_type;
const char *sparc_fpu_type;
+const char *sparc_pmu_type;
unsigned int fsr_storage;
static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
{
+ const struct manufacturer_info *manuf;
+ int i;
+
sparc_cpu_type = NULL;
sparc_fpu_type = NULL;
- if (psr_impl < ARRAY_SIZE(manufacturer_info))
+ sparc_pmu_type = NULL;
+ manuf = NULL;
+
+ for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++)
+ {
+ if (psr_impl == manufacturer_info[i].psr_impl) {
+ manuf = &manufacturer_info[i];
+ break;
+ }
+ }
+ if (manuf != NULL)
{
const struct cpu_info *cpu;
const struct fpu_info *fpu;
- cpu = &manufacturer_info[psr_impl].cpu_info[0];
+ cpu = &manuf->cpu_info[0];
while (cpu->psr_vers != -1)
{
if (cpu->psr_vers == psr_vers) {
sparc_cpu_type = cpu->name;
+ sparc_pmu_type = cpu->pmu_name;
sparc_fpu_type = "No FPU";
break;
}
cpu++;
}
- fpu = &manufacturer_info[psr_impl].fpu_info[0];
+ fpu = &manuf->fpu_info[0];
while (fpu->fp_vers != -1)
{
if (fpu->fp_vers == fpu_vers) {
@@ -276,6 +297,8 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers)
psr_impl, fpu_vers);
sparc_fpu_type = "Unknown FPU";
}
+ if (sparc_pmu_type == NULL)
+ sparc_pmu_type = "Unknown PMU";
}
#ifdef CONFIG_SPARC32
@@ -301,11 +324,13 @@ static void __init sun4v_cpu_probe(void)
case SUN4V_CHIP_NIAGARA1:
sparc_cpu_type = "UltraSparc T1 (Niagara)";
sparc_fpu_type = "UltraSparc T1 integrated FPU";
+ sparc_pmu_type = "niagara";
break;
case SUN4V_CHIP_NIAGARA2:
sparc_cpu_type = "UltraSparc T2 (Niagara2)";
sparc_fpu_type = "UltraSparc T2 integrated FPU";
+ sparc_pmu_type = "niagara2";
break;
default:
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index f52e0534d91d..57c39843fb2a 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -286,7 +286,7 @@ static void md_update_data(struct ds_info *dp,
rp = (struct ds_md_update_req *) (dpkt + 1);
- printk(KERN_INFO "ds-%lu: Machine description update.\n", dp->id);
+ printk(KERN_INFO "ds-%llu: Machine description update.\n", dp->id);
mdesc_update();
@@ -325,7 +325,7 @@ static void domain_shutdown_data(struct ds_info *dp,
rp = (struct ds_shutdown_req *) (dpkt + 1);
- printk(KERN_ALERT "ds-%lu: Shutdown request from "
+ printk(KERN_ALERT "ds-%llu: Shutdown request from "
"LDOM manager received.\n", dp->id);
memset(&pkt, 0, sizeof(pkt));
@@ -365,7 +365,7 @@ static void domain_panic_data(struct ds_info *dp,
rp = (struct ds_panic_req *) (dpkt + 1);
- printk(KERN_ALERT "ds-%lu: Panic request from "
+ printk(KERN_ALERT "ds-%llu: Panic request from "
"LDOM manager received.\n", dp->id);
memset(&pkt, 0, sizeof(pkt));
@@ -549,7 +549,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp,
for_each_cpu_mask(cpu, *mask) {
int err;
- printk(KERN_INFO "ds-%lu: Starting cpu %d...\n",
+ printk(KERN_INFO "ds-%llu: Starting cpu %d...\n",
dp->id, cpu);
err = cpu_up(cpu);
if (err) {
@@ -565,7 +565,7 @@ static int __cpuinit dr_cpu_configure(struct ds_info *dp,
res = DR_CPU_RES_CPU_NOT_RESPONDING;
}
- printk(KERN_INFO "ds-%lu: CPU startup failed err=%d\n",
+ printk(KERN_INFO "ds-%llu: CPU startup failed err=%d\n",
dp->id, err);
dr_cpu_mark(resp, cpu, ncpus, res, stat);
}
@@ -605,7 +605,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp,
for_each_cpu_mask(cpu, *mask) {
int err;
- printk(KERN_INFO "ds-%lu: Shutting down cpu %d...\n",
+ printk(KERN_INFO "ds-%llu: Shutting down cpu %d...\n",
dp->id, cpu);
err = cpu_down(cpu);
if (err)
@@ -684,7 +684,7 @@ static void ds_pri_data(struct ds_info *dp,
rp = (struct ds_pri_msg *) (dpkt + 1);
- printk(KERN_INFO "ds-%lu: PRI REQ [%lx:%lx], len=%d\n",
+ printk(KERN_INFO "ds-%llu: PRI REQ [%llx:%llx], len=%d\n",
dp->id, rp->req_num, rp->type, len);
}
@@ -816,7 +816,7 @@ void ldom_set_var(const char *var, const char *value)
if (ds_var_doorbell == 0 ||
ds_var_response != DS_VAR_SUCCESS)
- printk(KERN_ERR "ds-%lu: var-config [%s:%s] "
+ printk(KERN_ERR "ds-%llu: var-config [%s:%s] "
"failed, response(%d).\n",
dp->id, var, value,
ds_var_response);
@@ -850,7 +850,7 @@ void ldom_power_off(void)
static void ds_conn_reset(struct ds_info *dp)
{
- printk(KERN_ERR "ds-%lu: ds_conn_reset() from %p\n",
+ printk(KERN_ERR "ds-%llu: ds_conn_reset() from %p\n",
dp->id, __builtin_return_address(0));
}
@@ -912,11 +912,11 @@ static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
struct ds_cap_state *cp = find_cap(dp, ap->handle);
if (!cp) {
- printk(KERN_ERR "ds-%lu: REG ACK for unknown "
- "handle %lx\n", dp->id, ap->handle);
+ printk(KERN_ERR "ds-%llu: REG ACK for unknown "
+ "handle %llx\n", dp->id, ap->handle);
return 0;
}
- printk(KERN_INFO "ds-%lu: Registered %s service.\n",
+ printk(KERN_INFO "ds-%llu: Registered %s service.\n",
dp->id, cp->service_id);
cp->state = CAP_STATE_REGISTERED;
} else if (pkt->type == DS_REG_NACK) {
@@ -924,8 +924,8 @@ static int ds_handshake(struct ds_info *dp, struct ds_msg_tag *pkt)
struct ds_cap_state *cp = find_cap(dp, np->handle);
if (!cp) {
- printk(KERN_ERR "ds-%lu: REG NACK for "
- "unknown handle %lx\n",
+ printk(KERN_ERR "ds-%llu: REG NACK for "
+ "unknown handle %llx\n",
dp->id, np->handle);
return 0;
}
@@ -982,8 +982,8 @@ static void process_ds_work(void)
int req_len = qp->req_len;
if (!cp) {
- printk(KERN_ERR "ds-%lu: Data for unknown "
- "handle %lu\n",
+ printk(KERN_ERR "ds-%llu: Data for unknown "
+ "handle %llu\n",
dp->id, dpkt->handle);
spin_lock_irqsave(&ds_lock, flags);
@@ -1085,7 +1085,7 @@ static void ds_event(void *arg, int event)
}
if (event != LDC_EVENT_DATA_READY) {
- printk(KERN_WARNING "ds-%lu: Unexpected LDC event %d\n",
+ printk(KERN_WARNING "ds-%llu: Unexpected LDC event %d\n",
dp->id, event);
spin_unlock_irqrestore(&ds_lock, flags);
return;
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index faf9ccd9ef5d..f41ecc5ac0b4 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1088,8 +1088,8 @@ sunos_execv:
ld [%sp + STACKFRAME_SZ + PT_I0], %o0
.align 4
- .globl sys_pipe
-sys_pipe:
+ .globl sys_sparc_pipe
+sys_sparc_pipe:
mov %o7, %l5
add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg
call sparc_pipe
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c
index c16135e0c151..57922f69c3f7 100644
--- a/arch/sparc/kernel/idprom.c
+++ b/arch/sparc/kernel/idprom.c
@@ -8,11 +8,14 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/oplib.h>
#include <asm/idprom.h>
struct idprom *idprom;
+EXPORT_SYMBOL(idprom);
+
static struct idprom idprom_buffer;
#ifdef CONFIG_SPARC32
diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c
index 62126e4cec54..f28cb8278e98 100644
--- a/arch/sparc/kernel/init_task.c
+++ b/arch/sparc/kernel/init_task.c
@@ -8,7 +8,6 @@
#include <asm/pgtable.h>
#include <asm/uaccess.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 1cc1995531e2..d8900e1d5aad 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -434,7 +434,7 @@ static void strbuf_flush(struct strbuf *strbuf, struct iommu *iommu,
val = iommu_read(matchreg);
if (unlikely(val)) {
printk(KERN_WARNING "strbuf_flush: ctx flush "
- "timeout matchreg[%lx] ctx[%lx]\n",
+ "timeout matchreg[%llx] ctx[%lx]\n",
val, ctx);
goto do_page_flush;
}
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 7ce14f05eb48..87ea0d03d975 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -120,6 +120,7 @@ void __iomem *ioremap(unsigned long offset, unsigned long size)
sprintf(name, "phys_%08x", (u32)offset);
return _sparc_alloc_io(0, offset, size, name);
}
+EXPORT_SYMBOL(ioremap);
/*
* Comlimentary to ioremap().
@@ -141,6 +142,7 @@ void iounmap(volatile void __iomem *virtual)
kfree(res);
}
}
+EXPORT_SYMBOL(iounmap);
void __iomem *of_ioremap(struct resource *res, unsigned long offset,
unsigned long size, char *name)
@@ -237,6 +239,7 @@ void sbus_set_sbus64(struct device *dev, int x)
{
printk("sbus_set_sbus64: unsupported\n");
}
+EXPORT_SYMBOL(sbus_set_sbus64);
/*
* Allocate a chunk of memory suitable for DMA.
@@ -436,6 +439,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
*pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
return (void *) res->start;
}
+EXPORT_SYMBOL(pci_alloc_consistent);
/* Free and unmap a consistent DMA buffer.
* cpu_addr is what was returned from pci_alloc_consistent,
@@ -477,6 +481,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
free_pages(pgp, get_order(n));
}
+EXPORT_SYMBOL(pci_free_consistent);
/* Map a single buffer of the indicated size for DMA in streaming mode.
* The 32-bit bus address to use is returned.
@@ -491,6 +496,7 @@ dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
/* IIep is write-through, not flushing. */
return virt_to_phys(ptr);
}
+EXPORT_SYMBOL(pci_map_single);
/* Unmap a single streaming mode DMA translation. The dma_addr and size
* must match what was provided for in a previous pci_map_single call. All
@@ -508,6 +514,7 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size,
(size + PAGE_SIZE-1) & PAGE_MASK);
}
}
+EXPORT_SYMBOL(pci_unmap_single);
/*
* Same as pci_map_single, but with pages.
@@ -519,6 +526,7 @@ dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
/* IIep is write-through, not flushing. */
return page_to_phys(page) + offset;
}
+EXPORT_SYMBOL(pci_map_page);
void pci_unmap_page(struct pci_dev *hwdev,
dma_addr_t dma_address, size_t size, int direction)
@@ -526,6 +534,7 @@ void pci_unmap_page(struct pci_dev *hwdev,
BUG_ON(direction == PCI_DMA_NONE);
/* mmu_inval_dma_area XXX */
}
+EXPORT_SYMBOL(pci_unmap_page);
/* Map a set of buffers described by scatterlist in streaming
* mode for DMA. This is the scather-gather version of the
@@ -557,6 +566,7 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
}
return nents;
}
+EXPORT_SYMBOL(pci_map_sg);
/* Unmap a set of streaming mode DMA translations.
* Again, cpu read rules concerning calls here are the same as for
@@ -578,6 +588,7 @@ void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
}
}
}
+EXPORT_SYMBOL(pci_unmap_sg);
/* Make physical memory consistent for a single
* streaming mode DMA translation before or after a transfer.
@@ -597,6 +608,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t ba, size_t si
(size + PAGE_SIZE-1) & PAGE_MASK);
}
}
+EXPORT_SYMBOL(pci_dma_sync_single_for_cpu);
void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t ba, size_t size, int direction)
{
@@ -606,6 +618,7 @@ void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t ba, size_t
(size + PAGE_SIZE-1) & PAGE_MASK);
}
}
+EXPORT_SYMBOL(pci_dma_sync_single_for_device);
/* Make physical memory consistent for a set of streaming
* mode DMA translations after a transfer.
@@ -628,6 +641,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sgl, int
}
}
}
+EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu);
void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction)
{
@@ -644,6 +658,7 @@ void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl,
}
}
}
+EXPORT_SYMBOL(pci_dma_sync_sg_for_device);
#endif /* CONFIG_PCI */
#ifdef CONFIG_PROC_FS
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index f3488c45d57a..44dd5ee64339 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -294,6 +294,7 @@ void synchronize_irq(unsigned int irq)
while (sparc_irq[cpu_irq].flags & SPARC_IRQ_INPROGRESS)
cpu_relax();
}
+EXPORT_SYMBOL(synchronize_irq);
#endif /* SMP */
void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
@@ -669,7 +670,9 @@ void __init init_IRQ(void)
btfixup();
}
+#ifdef CONFIG_PROC_FS
void init_irq_proc(void)
{
/* For now, nothing... */
}
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index a3ea2bcb95de..e289376198eb 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -196,6 +196,11 @@ int show_interrupts(struct seq_file *p, void *v)
seq_putc(p, '\n');
skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ } else if (i == NR_IRQS) {
+ seq_printf(p, "NMI: ");
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", cpu_data(j).__nmi_count);
+ seq_printf(p, " Non-maskable interrupts\n");
}
return 0;
}
@@ -312,7 +317,8 @@ static void sun4u_irq_enable(unsigned int virt_irq)
}
}
-static void sun4u_set_affinity(unsigned int virt_irq, cpumask_t mask)
+static void sun4u_set_affinity(unsigned int virt_irq,
+ const struct cpumask *mask)
{
sun4u_irq_enable(virt_irq);
}
@@ -362,7 +368,8 @@ static void sun4v_irq_enable(unsigned int virt_irq)
ino, err);
}
-static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask)
+static void sun4v_set_affinity(unsigned int virt_irq,
+ const struct cpumask *mask)
{
unsigned int ino = virt_irq_table[virt_irq].dev_ino;
unsigned long cpuid = irq_choose_cpu(virt_irq);
@@ -429,7 +436,8 @@ static void sun4v_virq_enable(unsigned int virt_irq)
dev_handle, dev_ino, err);
}
-static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask)
+static void sun4v_virt_set_affinity(unsigned int virt_irq,
+ const struct cpumask *mask)
{
unsigned long cpuid, dev_handle, dev_ino;
int err;
@@ -775,69 +783,6 @@ void do_softirq(void)
local_irq_restore(flags);
}
-static void unhandled_perf_irq(struct pt_regs *regs)
-{
- unsigned long pcr, pic;
-
- read_pcr(pcr);
- read_pic(pic);
-
- write_pcr(0);
-
- printk(KERN_EMERG "CPU %d: Got unexpected perf counter IRQ.\n",
- smp_processor_id());
- printk(KERN_EMERG "CPU %d: PCR[%016lx] PIC[%016lx]\n",
- smp_processor_id(), pcr, pic);
-}
-
-/* Almost a direct copy of the powerpc PMC code. */
-static DEFINE_SPINLOCK(perf_irq_lock);
-static void *perf_irq_owner_caller; /* mostly for debugging */
-static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq;
-
-/* Invoked from level 15 PIL handler in trap table. */
-void perfctr_irq(int irq, struct pt_regs *regs)
-{
- clear_softint(1 << irq);
- perf_irq(regs);
-}
-
-int register_perfctr_intr(void (*handler)(struct pt_regs *))
-{
- int ret;
-
- if (!handler)
- return -EINVAL;
-
- spin_lock(&perf_irq_lock);
- if (perf_irq != unhandled_perf_irq) {
- printk(KERN_WARNING "register_perfctr_intr: "
- "perf IRQ busy (reserved by caller %p)\n",
- perf_irq_owner_caller);
- ret = -EBUSY;
- goto out;
- }
-
- perf_irq_owner_caller = __builtin_return_address(0);
- perf_irq = handler;
-
- ret = 0;
-out:
- spin_unlock(&perf_irq_lock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(register_perfctr_intr);
-
-void release_perfctr_intr(void (*handler)(struct pt_regs *))
-{
- spin_lock(&perf_irq_lock);
- perf_irq_owner_caller = NULL;
- perf_irq = unhandled_perf_irq;
- spin_unlock(&perf_irq_lock);
-}
-EXPORT_SYMBOL_GPL(release_perfctr_intr);
-
#ifdef CONFIG_HOTPLUG_CPU
void fixup_irqs(void)
{
@@ -851,7 +796,7 @@ void fixup_irqs(void)
!(irq_desc[irq].status & IRQ_PER_CPU)) {
if (irq_desc[irq].chip->set_affinity)
irq_desc[irq].chip->set_affinity(irq,
- irq_desc[irq].affinity);
+ &irq_desc[irq].affinity);
}
spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
}
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index 81a972e8d8ea..15d8a3f645c9 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -5,6 +5,7 @@
/* cpu.c */
extern const char *sparc_cpu_type;
+extern const char *sparc_pmu_type;
extern const char *sparc_fpu_type;
extern unsigned int fsr_storage;
diff --git a/arch/sparc/kernel/kgdb_32.c b/arch/sparc/kernel/kgdb_32.c
index 757805ce02ee..04df4edc0073 100644
--- a/arch/sparc/kernel/kgdb_32.c
+++ b/arch/sparc/kernel/kgdb_32.c
@@ -14,14 +14,14 @@ extern unsigned long trapbase;
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
int i;
gdb_regs[GDB_G0] = 0;
for (i = 0; i < 15; i++)
gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
for (i = 0; i < 8; i++)
gdb_regs[GDB_L0 + i] = win->locals[i];
for (i = 0; i < 8; i++)
@@ -43,7 +43,7 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
struct thread_info *t = task_thread_info(p);
- struct reg_window *win;
+ struct reg_window32 *win;
int i;
for (i = GDB_G0; i < GDB_G6; i++)
@@ -55,7 +55,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
gdb_regs[GDB_SP] = t->ksp;
gdb_regs[GDB_O7] = 0;
- win = (struct reg_window *) t->ksp;
+ win = (struct reg_window32 *) t->ksp;
for (i = 0; i < 8; i++)
gdb_regs[GDB_L0 + i] = win->locals[i];
for (i = 0; i < 8; i++)
@@ -77,7 +77,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
int i;
for (i = 0; i < 15; i++)
@@ -96,7 +96,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
regs->npc = gdb_regs[GDB_NPC];
regs->y = gdb_regs[GDB_Y];
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
for (i = 0; i < 8; i++)
win->locals[i] = gdb_regs[GDB_L0 + i];
for (i = 0; i < 8; i++)
diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c
index 201a6e547e4a..3bc6527c95af 100644
--- a/arch/sparc/kernel/kprobes.c
+++ b/arch/sparc/kernel/kprobes.c
@@ -517,7 +517,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
/*
* It is possible to have multiple instances associated with a given
* task either because an multiple functions in the call path
- * have a return probe installed on them, and/or more then one return
+ * have a return probe installed on them, and/or more than one return
* return probe was registered for a target function.
*
* We can handle this because:
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index d68982330f66..6ce5d2598a09 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -625,22 +625,23 @@ static int process_ver_ack(struct ldc_channel *lp, struct ldc_version *vp)
static int process_ver_nack(struct ldc_channel *lp, struct ldc_version *vp)
{
struct ldc_version *vap;
+ struct ldc_packet *p;
+ unsigned long new_tail;
- if ((vp->major == 0 && vp->minor == 0) ||
- !(vap = find_by_major(vp->major))) {
+ if (vp->major == 0 && vp->minor == 0)
+ return ldc_abort(lp);
+
+ vap = find_by_major(vp->major);
+ if (!vap)
return ldc_abort(lp);
- } else {
- struct ldc_packet *p;
- unsigned long new_tail;
- p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
+ p = handshake_compose_ctrl(lp, LDC_INFO, LDC_VERS,
vap, sizeof(*vap),
&new_tail);
- if (p)
- return send_tx_packet(lp, p, new_tail);
- else
- return ldc_abort(lp);
- }
+ if (!p)
+ return ldc_abort(lp);
+
+ return send_tx_packet(lp, p, new_tail);
}
static int process_version(struct ldc_channel *lp,
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 3c539a6d7c18..3f79f0c23a08 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -536,24 +536,24 @@ static void __init report_platform_properties(void)
v = mdesc_get_property(hp, pn, "hostid", NULL);
if (v)
- printk("PLATFORM: hostid [%08lx]\n", *v);
+ printk("PLATFORM: hostid [%08llx]\n", *v);
v = mdesc_get_property(hp, pn, "serial#", NULL);
if (v)
- printk("PLATFORM: serial# [%08lx]\n", *v);
+ printk("PLATFORM: serial# [%08llx]\n", *v);
v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
- printk("PLATFORM: stick-frequency [%08lx]\n", *v);
+ printk("PLATFORM: stick-frequency [%08llx]\n", *v);
v = mdesc_get_property(hp, pn, "mac-address", NULL);
if (v)
- printk("PLATFORM: mac-address [%lx]\n", *v);
+ printk("PLATFORM: mac-address [%llx]\n", *v);
v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
if (v)
- printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);
+ printk("PLATFORM: watchdog-resolution [%llu ms]\n", *v);
v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
if (v)
- printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);
+ printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v);
v = mdesc_get_property(hp, pn, "max-cpus", NULL);
if (v)
- printk("PLATFORM: max-cpus [%lu]\n", *v);
+ printk("PLATFORM: max-cpus [%llu]\n", *v);
#ifdef CONFIG_SMP
{
diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c
index ba960c02bb55..6ce1021d487c 100644
--- a/arch/sparc/kernel/muldiv.c
+++ b/arch/sparc/kernel/muldiv.c
@@ -60,7 +60,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
}
#define fetch_reg(reg, regs) ({ \
- struct reg_window __user *win; \
+ struct reg_window32 __user *win; \
register unsigned long ret; \
\
if (!(reg)) ret = 0; \
@@ -68,7 +68,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
ret = regs->u_regs[(reg)]; \
} else { \
/* Ho hum, the slightly complicated case. */ \
- win = (struct reg_window __user *)regs->u_regs[UREG_FP];\
+ win = (struct reg_window32 __user *)regs->u_regs[UREG_FP];\
if (get_user (ret, &win->locals[(reg) - 16])) return -1;\
} \
ret; \
@@ -77,7 +77,7 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
static inline int
store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
{
- struct reg_window __user *win;
+ struct reg_window32 __user *win;
if (!reg)
return 0;
@@ -86,7 +86,7 @@ store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs)
return 0;
} else {
/* need to use put_user() in this case: */
- win = (struct reg_window __user *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
return (put_user(result, &win->locals[reg - 16]));
}
}
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
new file mode 100644
index 000000000000..09f088ed4a64
--- /dev/null
+++ b/arch/sparc/kernel/nmi.c
@@ -0,0 +1,224 @@
+/* Pseudo NMI support on sparc64 systems.
+ *
+ * Copyright (C) 2009 David S. Miller <davem@davemloft.net>
+ *
+ * The NMI watchdog support and infrastructure is based almost
+ * entirely upon the x86 NMI support code.
+ */
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/nmi.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kernel_stat.h>
+#include <linux/slab.h>
+#include <linux/kdebug.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/ptrace.h>
+#include <asm/local.h>
+#include <asm/pcr.h>
+
+/* We don't have a real NMI on sparc64, but we can fake one
+ * up using profiling counter overflow interrupts and interrupt
+ * levels.
+ *
+ * The profile overflow interrupts at level 15, so we use
+ * level 14 as our IRQ off level.
+ */
+
+static int nmi_watchdog_active;
+static int panic_on_timeout;
+
+int nmi_usable;
+EXPORT_SYMBOL_GPL(nmi_usable);
+
+static unsigned int nmi_hz = HZ;
+
+static DEFINE_PER_CPU(unsigned int, last_irq_sum);
+static DEFINE_PER_CPU(local_t, alert_counter);
+static DEFINE_PER_CPU(int, nmi_touch);
+
+void touch_nmi_watchdog(void)
+{
+ if (nmi_watchdog_active) {
+ int cpu;
+
+ for_each_present_cpu(cpu) {
+ if (per_cpu(nmi_touch, cpu) != 1)
+ per_cpu(nmi_touch, cpu) = 1;
+ }
+ }
+
+ touch_softlockup_watchdog();
+}
+EXPORT_SYMBOL(touch_nmi_watchdog);
+
+static void die_nmi(const char *str, struct pt_regs *regs, int do_panic)
+{
+ if (notify_die(DIE_NMIWATCHDOG, str, regs, 0,
+ pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
+ return;
+
+ console_verbose();
+ bust_spinlocks(1);
+
+ printk(KERN_EMERG "%s", str);
+ printk(" on CPU%d, ip %08lx, registers:\n",
+ smp_processor_id(), regs->tpc);
+ show_regs(regs);
+
+ bust_spinlocks(0);
+
+ if (do_panic || panic_on_oops)
+ panic("Non maskable interrupt");
+
+ local_irq_enable();
+ do_exit(SIGBUS);
+}
+
+notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
+{
+ unsigned int sum, touched = 0;
+ int cpu = smp_processor_id();
+
+ clear_softint(1 << irq);
+ pcr_ops->write(PCR_PIC_PRIV);
+
+ local_cpu_data().__nmi_count++;
+
+ if (notify_die(DIE_NMI, "nmi", regs, 0,
+ pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
+ touched = 1;
+
+ sum = kstat_irqs_cpu(0, cpu);
+ if (__get_cpu_var(nmi_touch)) {
+ __get_cpu_var(nmi_touch) = 0;
+ touched = 1;
+ }
+ if (!touched && __get_cpu_var(last_irq_sum) == sum) {
+ local_inc(&__get_cpu_var(alert_counter));
+ if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz)
+ die_nmi("BUG: NMI Watchdog detected LOCKUP",
+ regs, panic_on_timeout);
+ } else {
+ __get_cpu_var(last_irq_sum) = sum;
+ local_set(&__get_cpu_var(alert_counter), 0);
+ }
+ if (nmi_usable) {
+ write_pic(picl_value(nmi_hz));
+ pcr_ops->write(pcr_enable);
+ }
+}
+
+static inline unsigned int get_nmi_count(int cpu)
+{
+ return cpu_data(cpu).__nmi_count;
+}
+
+static int endflag __initdata;
+
+static __init void nmi_cpu_busy(void *data)
+{
+ local_irq_enable_in_hardirq();
+ while (endflag == 0)
+ mb();
+}
+
+static void report_broken_nmi(int cpu, int *prev_nmi_count)
+{
+ printk(KERN_CONT "\n");
+
+ printk(KERN_WARNING
+ "WARNING: CPU#%d: NMI appears to be stuck (%d->%d)!\n",
+ cpu, prev_nmi_count[cpu], get_nmi_count(cpu));
+
+ printk(KERN_WARNING
+ "Please report this to bugzilla.kernel.org,\n");
+ printk(KERN_WARNING
+ "and attach the output of the 'dmesg' command.\n");
+
+ nmi_usable = 0;
+}
+
+static void stop_watchdog(void *unused)
+{
+ pcr_ops->write(PCR_PIC_PRIV);
+}
+
+static int __init check_nmi_watchdog(void)
+{
+ unsigned int *prev_nmi_count;
+ int cpu, err;
+
+ prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(unsigned int), GFP_KERNEL);
+ if (!prev_nmi_count) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ printk(KERN_INFO "Testing NMI watchdog ... ");
+
+ smp_call_function(nmi_cpu_busy, (void *)&endflag, 0);
+
+ for_each_possible_cpu(cpu)
+ prev_nmi_count[cpu] = get_nmi_count(cpu);
+ local_irq_enable();
+ mdelay((20 * 1000) / nmi_hz); /* wait 20 ticks */
+
+ for_each_online_cpu(cpu) {
+ if (get_nmi_count(cpu) - prev_nmi_count[cpu] <= 5)
+ report_broken_nmi(cpu, prev_nmi_count);
+ }
+ endflag = 1;
+ if (!nmi_usable) {
+ kfree(prev_nmi_count);
+ err = -ENODEV;
+ goto error;
+ }
+ printk("OK.\n");
+
+ nmi_hz = 1;
+
+ kfree(prev_nmi_count);
+ return 0;
+error:
+ on_each_cpu(stop_watchdog, NULL, 1);
+ return err;
+}
+
+static void start_watchdog(void *unused)
+{
+ pcr_ops->write(PCR_PIC_PRIV);
+ write_pic(picl_value(nmi_hz));
+
+ pcr_ops->write(pcr_enable);
+}
+
+void nmi_adjust_hz(unsigned int new_hz)
+{
+ nmi_hz = new_hz;
+ on_each_cpu(start_watchdog, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(nmi_adjust_hz);
+
+int __init nmi_init(void)
+{
+ nmi_usable = 1;
+
+ on_each_cpu(start_watchdog, NULL, 1);
+
+ return check_nmi_watchdog();
+}
+
+static int __init setup_nmi_watchdog(char *str)
+{
+ if (!strncmp(str, "panic", 5))
+ panic_on_timeout = 1;
+
+ return 0;
+}
+__setup("nmi_watchdog=", setup_nmi_watchdog);
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c
index 46e231f7c5ce..b4a12c9aa5f8 100644
--- a/arch/sparc/kernel/of_device_64.c
+++ b/arch/sparc/kernel/of_device_64.c
@@ -554,7 +554,7 @@ static void __init build_device_resources(struct of_device *op,
memset(r, 0, sizeof(*r));
if (of_resource_verbose)
- printk("%s reg[%d] -> %lx\n",
+ printk("%s reg[%d] -> %llx\n",
op->node->full_name, index,
result);
@@ -778,9 +778,9 @@ static unsigned int __init build_one_device_irq(struct of_device *op,
out:
nid = of_node_to_nid(dp);
if (nid != -1) {
- cpumask_t numa_mask = node_to_cpumask(nid);
+ cpumask_t numa_mask = *cpumask_of_node(nid);
- irq_set_affinity(irq, numa_mask);
+ irq_set_affinity(irq, &numa_mask);
}
return irq;
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index bdb7c0a6d83d..4638fba799e4 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -223,7 +223,7 @@ static void pci_parse_of_addrs(struct of_device *op,
continue;
i = addrs[0] & 0xff;
if (ofpci_verbose)
- printk(" start: %lx, end: %lx, i: %x\n",
+ printk(" start: %llx, end: %llx, i: %x\n",
op_res->start, op_res->end, i);
if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
@@ -1077,6 +1077,7 @@ int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
return (device_mask & dma_addr_mask) == dma_addr_mask;
}
+EXPORT_SYMBOL(pci_dma_supported);
void pci_resource_to_user(const struct pci_dev *pdev, int bar,
const struct resource *rp, resource_size_t *start,
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c
index 23b88082d0b2..64e6edf17b9d 100644
--- a/arch/sparc/kernel/pci_common.c
+++ b/arch/sparc/kernel/pci_common.c
@@ -457,7 +457,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
prom_halt();
}
- printk("%s: PCI IO[%lx] MEM[%lx]\n",
+ printk("%s: PCI IO[%llx] MEM[%llx]\n",
pbm->name,
pbm->io_space.start,
pbm->mem_space.start);
diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c
index 2e680f34f727..f1be37a7b123 100644
--- a/arch/sparc/kernel/pci_msi.c
+++ b/arch/sparc/kernel/pci_msi.c
@@ -286,9 +286,9 @@ static int bringup_one_msi_queue(struct pci_pbm_info *pbm,
nid = pbm->numa_node;
if (nid != -1) {
- cpumask_t numa_mask = node_to_cpumask(nid);
+ cpumask_t numa_mask = *cpumask_of_node(nid);
- irq_set_affinity(irq, numa_mask);
+ irq_set_affinity(irq, &numa_mask);
}
err = request_irq(irq, sparc64_msiq_interrupt, 0,
"MSIQ",
@@ -426,8 +426,8 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm,
pbm->name,
pbm->msi_first, pbm->msi_num, pbm->msi_data_mask,
pbm->msix_data_width);
- printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] "
- "addr64[0x%lx:0x%x]\n",
+ printk(KERN_INFO "%s: MSI addr32[0x%llx:0x%x] "
+ "addr64[0x%llx:0x%x]\n",
pbm->name,
pbm->msi32_start, pbm->msi32_len,
pbm->msi64_start, pbm->msi64_len);
diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c
index dfb3ec892987..3b34344082ef 100644
--- a/arch/sparc/kernel/pci_psycho.c
+++ b/arch/sparc/kernel/pci_psycho.c
@@ -307,10 +307,7 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm)
/* We really mean to ignore the return result here. Two
* PCI controller share the same interrupt numbers and
- * drive the same front-end hardware. Whichever of the
- * two get in here first will register the IRQ handler
- * the second will just error out since we do not pass in
- * IRQF_SHARED.
+ * drive the same front-end hardware.
*/
err = request_irq(op->irqs[1], psycho_ue_intr, IRQF_SHARED,
"PSYCHO_UE", pbm);
diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c
index 45d9dba1ba11..2b5cdde77af7 100644
--- a/arch/sparc/kernel/pci_schizo.c
+++ b/arch/sparc/kernel/pci_schizo.c
@@ -794,7 +794,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id)
pbm->controller_regs + SCHIZO_SAFARI_ERRLOG);
if (!(errlog & BUS_ERROR_UNMAP)) {
- printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
+ printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016llx]\n",
pbm->name, errlog);
return IRQ_HANDLED;
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 34a1fded3941..0ef0ab3d4763 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -73,7 +73,7 @@ static long iommu_batch_flush(struct iommu_batch *p)
if (unlikely(num < 0)) {
if (printk_ratelimit())
printk("iommu_batch_flush: IOMMU map of "
- "[%08lx:%08lx:%lx:%lx:%lx] failed with "
+ "[%08lx:%08llx:%lx:%lx:%lx] failed with "
"status %ld\n",
devhandle, HV_PCI_TSBID(0, entry),
npages, prot, __pa(pglist), num);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 75ed98be3edf..85e7037429b9 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -956,6 +956,7 @@ void outsb(unsigned long addr, const void *src, unsigned long count)
/* addr += 1; */
}
}
+EXPORT_SYMBOL(outsb);
void outsw(unsigned long addr, const void *src, unsigned long count)
{
@@ -966,6 +967,7 @@ void outsw(unsigned long addr, const void *src, unsigned long count)
/* addr += 2; */
}
}
+EXPORT_SYMBOL(outsw);
void outsl(unsigned long addr, const void *src, unsigned long count)
{
@@ -976,6 +978,7 @@ void outsl(unsigned long addr, const void *src, unsigned long count)
/* addr += 4; */
}
}
+EXPORT_SYMBOL(outsl);
void insb(unsigned long addr, void *dst, unsigned long count)
{
@@ -986,6 +989,7 @@ void insb(unsigned long addr, void *dst, unsigned long count)
/* addr += 1; */
}
}
+EXPORT_SYMBOL(insb);
void insw(unsigned long addr, void *dst, unsigned long count)
{
@@ -996,6 +1000,7 @@ void insw(unsigned long addr, void *dst, unsigned long count)
/* addr += 2; */
}
}
+EXPORT_SYMBOL(insw);
void insl(unsigned long addr, void *dst, unsigned long count)
{
@@ -1009,5 +1014,6 @@ void insl(unsigned long addr, void *dst, unsigned long count)
/* addr += 4; */
}
}
+EXPORT_SYMBOL(insl);
subsys_initcall(pcic_init);
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
new file mode 100644
index 000000000000..92e0dda141a4
--- /dev/null
+++ b/arch/sparc/kernel/pcr.c
@@ -0,0 +1,153 @@
+/* pcr.c: Generic sparc64 performance counter infrastructure.
+ *
+ * Copyright (C) 2009 David S. Miller (davem@davemloft.net)
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/pil.h>
+#include <asm/pcr.h>
+#include <asm/nmi.h>
+
+/* This code is shared between various users of the performance
+ * counters. Users will be oprofile, pseudo-NMI watchdog, and the
+ * perf_counter support layer.
+ */
+
+#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE)
+#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \
+ PCR_N2_TOE_OV1 | \
+ (2 << PCR_N2_SL1_SHIFT) | \
+ (0xff << PCR_N2_MASK1_SHIFT))
+
+u64 pcr_enable;
+unsigned int picl_shift;
+
+/* Performance counter interrupts run unmasked at PIL level 15.
+ * Therefore we can't do things like wakeups and other work
+ * that expects IRQ disabling to be adhered to in locking etc.
+ *
+ * Therefore in such situations we defer the work by signalling
+ * a lower level cpu IRQ.
+ */
+void deferred_pcr_work_irq(int irq, struct pt_regs *regs)
+{
+ clear_softint(1 << PIL_DEFERRED_PCR_WORK);
+}
+
+void schedule_deferred_pcr_work(void)
+{
+ set_softint(1 << PIL_DEFERRED_PCR_WORK);
+}
+
+const struct pcr_ops *pcr_ops;
+EXPORT_SYMBOL_GPL(pcr_ops);
+
+static u64 direct_pcr_read(void)
+{
+ u64 val;
+
+ read_pcr(val);
+ return val;
+}
+
+static void direct_pcr_write(u64 val)
+{
+ write_pcr(val);
+}
+
+static const struct pcr_ops direct_pcr_ops = {
+ .read = direct_pcr_read,
+ .write = direct_pcr_write,
+};
+
+static void n2_pcr_write(u64 val)
+{
+ unsigned long ret;
+
+ ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
+ if (val != HV_EOK)
+ write_pcr(val);
+}
+
+static const struct pcr_ops n2_pcr_ops = {
+ .read = direct_pcr_read,
+ .write = n2_pcr_write,
+};
+
+static unsigned long perf_hsvc_group;
+static unsigned long perf_hsvc_major;
+static unsigned long perf_hsvc_minor;
+
+static int __init register_perf_hsvc(void)
+{
+ if (tlb_type == hypervisor) {
+ switch (sun4v_chip_type) {
+ case SUN4V_CHIP_NIAGARA1:
+ perf_hsvc_group = HV_GRP_NIAG_PERF;
+ break;
+
+ case SUN4V_CHIP_NIAGARA2:
+ perf_hsvc_group = HV_GRP_N2_CPU;
+ break;
+
+ default:
+ return -ENODEV;
+ }
+
+
+ perf_hsvc_major = 1;
+ perf_hsvc_minor = 0;
+ if (sun4v_hvapi_register(perf_hsvc_group,
+ perf_hsvc_major,
+ &perf_hsvc_minor)) {
+ printk("perfmon: Could not register hvapi.\n");
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+static void __init unregister_perf_hsvc(void)
+{
+ if (tlb_type != hypervisor)
+ return;
+ sun4v_hvapi_unregister(perf_hsvc_group);
+}
+
+int __init pcr_arch_init(void)
+{
+ int err = register_perf_hsvc();
+
+ if (err)
+ return err;
+
+ switch (tlb_type) {
+ case hypervisor:
+ pcr_ops = &n2_pcr_ops;
+ pcr_enable = PCR_N2_ENABLE;
+ picl_shift = 2;
+ break;
+
+ case cheetah:
+ case cheetah_plus:
+ case spitfire:
+ pcr_ops = &direct_pcr_ops;
+ pcr_enable = PCR_SUN4U_ENABLE;
+ break;
+
+ default:
+ err = -ENODEV;
+ goto out_unregister;
+ }
+
+ return nmi_init();
+
+out_unregister:
+ unregister_perf_hsvc();
+ return err;
+}
+
+arch_initcall(pcr_arch_init);
diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c
index 076cad7f9757..ae88f06a7ec4 100644
--- a/arch/sparc/kernel/power.c
+++ b/arch/sparc/kernel/power.c
@@ -40,7 +40,7 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id
power_reg = of_ioremap(res, 0, 0x4, "power");
- printk(KERN_INFO "%s: Control reg at %lx\n",
+ printk(KERN_INFO "%s: Control reg at %llx\n",
op->node->name, res->start);
if (has_button_interrupt(irq, op->node)) {
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index 69d9315f4a93..f4bee35a1b46 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -44,6 +44,7 @@
* Set in pm platform drivers (apc.c and pmc.c)
*/
void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
/*
* Power-off handler instantiation for pm.h compliance
@@ -180,13 +181,13 @@ static DEFINE_SPINLOCK(sparc_backtrace_lock);
void __show_backtrace(unsigned long fp)
{
- struct reg_window *rw;
+ struct reg_window32 *rw;
unsigned long flags;
int cpu = smp_processor_id();
spin_lock_irqsave(&sparc_backtrace_lock, flags);
- rw = (struct reg_window *)fp;
+ rw = (struct reg_window32 *)fp;
while(rw && (((unsigned long) rw) >= PAGE_OFFSET) &&
!(((unsigned long) rw) & 0x7)) {
printk("CPU[%d]: ARGS[%08lx,%08lx,%08lx,%08lx,%08lx,%08lx] "
@@ -196,7 +197,7 @@ void __show_backtrace(unsigned long fp)
rw->ins[6],
rw->ins[7]);
printk("%pS\n", (void *) rw->ins[7]);
- rw = (struct reg_window *) rw->ins[6];
+ rw = (struct reg_window32 *) rw->ins[6];
}
spin_unlock_irqrestore(&sparc_backtrace_lock, flags);
}
@@ -258,7 +259,7 @@ void show_stackframe(struct sparc_stackf *sf)
void show_regs(struct pt_regs *r)
{
- struct reg_window *rw = (struct reg_window *) r->u_regs[14];
+ struct reg_window32 *rw = (struct reg_window32 *) r->u_regs[14];
printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n",
r->psr, r->pc, r->npc, r->y, print_tainted());
@@ -287,7 +288,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
{
unsigned long pc, fp;
unsigned long task_base;
- struct reg_window *rw;
+ struct reg_window32 *rw;
int count = 0;
if (tsk != NULL)
@@ -301,7 +302,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
if (fp < (task_base + sizeof(struct thread_info)) ||
fp >= (task_base + (PAGE_SIZE << 1)))
break;
- rw = (struct reg_window *) fp;
+ rw = (struct reg_window32 *) fp;
pc = rw->ins[7];
printk("[%08lx : ", pc);
printk("%pS ] ", (void *) pc);
@@ -673,13 +674,14 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
"g1", "g2", "g3", "o0", "o1", "memory", "cc");
return retval;
}
+EXPORT_SYMBOL(kernel_thread);
unsigned long get_wchan(struct task_struct *task)
{
unsigned long pc, fp, bias = 0;
unsigned long task_base = (unsigned long) task;
unsigned long ret = 0;
- struct reg_window *rw;
+ struct reg_window32 *rw;
int count = 0;
if (!task || task == current ||
@@ -692,7 +694,7 @@ unsigned long get_wchan(struct task_struct *task)
if (fp < (task_base + sizeof(struct thread_info)) ||
fp >= (task_base + (2 * PAGE_SIZE)))
break;
- rw = (struct reg_window *) fp;
+ rw = (struct reg_window32 *) fp;
pc = rw->ins[7];
if (!in_sched_functions(pc)) {
ret = pc;
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index d5e2acef9877..a73954b87f0a 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -29,6 +29,7 @@
#include <linux/cpu.h>
#include <linux/elfcore.h>
#include <linux/sysrq.h>
+#include <linux/nmi.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -52,8 +53,10 @@
static void sparc64_yield(int cpu)
{
- if (tlb_type != hypervisor)
+ if (tlb_type != hypervisor) {
+ touch_nmi_watchdog();
return;
+ }
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
@@ -678,6 +681,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
"g1", "g2", "g3", "o0", "o1", "memory", "cc");
return retval;
}
+EXPORT_SYMBOL(kernel_thread);
typedef struct {
union {
@@ -743,6 +747,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
}
return 1;
}
+EXPORT_SYMBOL(dump_fpu);
/*
* sparc_execve() executes a new program after the asm stub has set
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index 4e9af593db49..ff7b591c8946 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -155,20 +155,12 @@ static struct property * __init build_one_prop(phandle node, char *prev,
p->value = prom_early_alloc(special_len);
memcpy(p->value, special_val, special_len);
} else {
-#ifdef CONFIG_SPARC32
- if (prev == NULL) {
- name = prom_firstprop(node, NULL);
- } else {
- name = prom_nextprop(node, prev, NULL);
- }
-#else
if (prev == NULL) {
- prom_firstprop(node, p->name);
+ name = prom_firstprop(node, p->name);
} else {
- prom_nextprop(node, prev, p->name);
+ name = prom_nextprop(node, prev, p->name);
}
- name = p->name;
-#endif
+
if (strlen(name) == 0) {
tmp = p;
return NULL;
diff --git a/arch/sparc/kernel/prom_irqtrans.c b/arch/sparc/kernel/prom_irqtrans.c
index 96958c4dce8e..5702ad4710cb 100644
--- a/arch/sparc/kernel/prom_irqtrans.c
+++ b/arch/sparc/kernel/prom_irqtrans.c
@@ -346,7 +346,7 @@ static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
break;
}
if (limit <= 0) {
- printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n",
+ printk("tomatillo_wsync_handler: DMA won't sync [%llx:%llx]\n",
val, mask);
}
diff --git a/arch/sparc/kernel/psycho_common.c b/arch/sparc/kernel/psycho_common.c
index 790996428c14..8f1478475421 100644
--- a/arch/sparc/kernel/psycho_common.c
+++ b/arch/sparc/kernel/psycho_common.c
@@ -11,19 +11,19 @@
#include "iommu_common.h"
#include "psycho_common.h"
-#define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002UL
-#define PSYCHO_STCERR_WRITE 0x0000000000000002UL
-#define PSYCHO_STCERR_READ 0x0000000000000001UL
-#define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL
-#define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL
-#define PSYCHO_STCTAG_VALID 0x0000000000000002UL
-#define PSYCHO_STCTAG_WRITE 0x0000000000000001UL
-#define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL
-#define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL
-#define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL
-#define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL
-#define PSYCHO_STCLINE_VALID 0x0000000000000002UL
-#define PSYCHO_STCLINE_FOFN 0x0000000000000001UL
+#define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002ULL
+#define PSYCHO_STCERR_WRITE 0x0000000000000002ULL
+#define PSYCHO_STCERR_READ 0x0000000000000001ULL
+#define PSYCHO_STCTAG_PPN 0x0fffffff00000000ULL
+#define PSYCHO_STCTAG_VPN 0x00000000ffffe000ULL
+#define PSYCHO_STCTAG_VALID 0x0000000000000002ULL
+#define PSYCHO_STCTAG_WRITE 0x0000000000000001ULL
+#define PSYCHO_STCLINE_LINDX 0x0000000001e00000ULL
+#define PSYCHO_STCLINE_SPTR 0x00000000001f8000ULL
+#define PSYCHO_STCLINE_LADDR 0x0000000000007f00ULL
+#define PSYCHO_STCLINE_EPTR 0x00000000000000fcULL
+#define PSYCHO_STCLINE_VALID 0x0000000000000002ULL
+#define PSYCHO_STCLINE_FOFN 0x0000000000000001ULL
static DEFINE_SPINLOCK(stc_buf_lock);
static unsigned long stc_error_buf[128];
@@ -94,7 +94,7 @@ static void psycho_check_stc_error(struct pci_pbm_info *pbm)
if (saw_error != 0) {
u64 tagval = stc_tag_buf[i];
u64 lineval = stc_line_buf[i];
- printk(KERN_ERR "%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)"
+ printk(KERN_ERR "%s: STC_TAG(%d)[PA(%016llx)VA(%08llx)"
"V(%d)W(%d)]\n",
pbm->name,
i,
@@ -102,8 +102,8 @@ static void psycho_check_stc_error(struct pci_pbm_info *pbm)
(tagval & PSYCHO_STCTAG_VPN),
((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0),
((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0));
- printk(KERN_ERR "%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)"
- "LADDR(%lx)EP(%lx)V(%d)FOFN(%d)]\n",
+ printk(KERN_ERR "%s: STC_LINE(%d)[LIDX(%llx)SP(%llx)"
+ "LADDR(%llx)EP(%llx)V(%d)FOFN(%d)]\n",
pbm->name,
i,
((lineval & PSYCHO_STCLINE_LINDX) >> 21UL),
@@ -144,10 +144,10 @@ static void psycho_record_iommu_tags_and_data(struct pci_pbm_info *pbm,
#define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL)
#define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL)
#define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL)
-#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL
+#define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffULL
#define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL)
#define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL)
-#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL
+#define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffULL
static void psycho_dump_iommu_tags_and_data(struct pci_pbm_info *pbm,
u64 *tag, u64 *data)
@@ -179,18 +179,18 @@ static void psycho_dump_iommu_tags_and_data(struct pci_pbm_info *pbm,
}
printk(KERN_ERR "%s: IOMMU TAG(%d)[error(%s) wr(%d) "
- "str(%d) sz(%dK) vpg(%08lx)]\n",
+ "str(%d) sz(%dK) vpg(%08llx)]\n",
pbm->name, i, type_str,
((tag_val & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0),
((tag_val & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0),
((tag_val & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8),
(tag_val & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT);
printk(KERN_ERR "%s: IOMMU DATA(%d)[valid(%d) cache(%d) "
- "ppg(%016lx)]\n",
+ "ppg(%016llx)]\n",
pbm->name, i,
((data_val & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0),
((data_val & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0),
- (data_val & PSYCHO_IOMMU_DATA_PPAGE)<<IOMMU_PAGE_SHIFT);
+ (data_val & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT);
}
}
@@ -285,20 +285,20 @@ static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm)
return ret;
}
-#define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL
-#define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL
-#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL
-#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL
-#define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL
-#define PSYCHO_PCIAFSR_STA 0x0400000000000000UL
-#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL
-#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL
-#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL
-#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL
-#define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL
-#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL
-#define PSYCHO_PCIAFSR_MID 0x000000003e000000UL
-#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL
+#define PSYCHO_PCIAFSR_PMA 0x8000000000000000ULL
+#define PSYCHO_PCIAFSR_PTA 0x4000000000000000ULL
+#define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000ULL
+#define PSYCHO_PCIAFSR_PPERR 0x1000000000000000ULL
+#define PSYCHO_PCIAFSR_SMA 0x0800000000000000ULL
+#define PSYCHO_PCIAFSR_STA 0x0400000000000000ULL
+#define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000ULL
+#define PSYCHO_PCIAFSR_SPERR 0x0100000000000000ULL
+#define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000ULL
+#define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000ULL
+#define PSYCHO_PCIAFSR_BLK 0x0000000080000000ULL
+#define PSYCHO_PCIAFSR_RESV2 0x0000000040000000ULL
+#define PSYCHO_PCIAFSR_MID 0x000000003e000000ULL
+#define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffULL
irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
{
@@ -326,12 +326,12 @@ irqreturn_t psycho_pcierr_intr(int irq, void *dev_id)
"Excessive Retries" :
((error_bits & PSYCHO_PCIAFSR_PPERR) ?
"Parity Error" : "???"))))));
- printk(KERN_ERR "%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n",
+ printk(KERN_ERR "%s: bytemask[%04llx] UPA_MID[%02llx] was_block(%d)\n",
pbm->name,
(afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL,
(afsr & PSYCHO_PCIAFSR_MID) >> 25UL,
(afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0);
- printk(KERN_ERR "%s: PCI AFAR [%016lx]\n", pbm->name, afar);
+ printk(KERN_ERR "%s: PCI AFAR [%016llx]\n", pbm->name, afar);
printk(KERN_ERR "%s: PCI Secondary errors [", pbm->name);
reported = 0;
if (afsr & PSYCHO_PCIAFSR_SMA) {
diff --git a/arch/sparc/kernel/sbus.c b/arch/sparc/kernel/sbus.c
index 2ead310066d1..406e0872504e 100644
--- a/arch/sparc/kernel/sbus.c
+++ b/arch/sparc/kernel/sbus.c
@@ -117,6 +117,7 @@ void sbus_set_sbus64(struct device *dev, int bursts)
val |= (1UL << 4UL);
upa_writeq(val, cfg_reg);
}
+EXPORT_SYMBOL(sbus_set_sbus64);
/* INO number to IMAP register offset for SYSIO external IRQ's.
* This should conform to both Sunfire/Wildfire server and Fusion
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index c96c65d1b58b..998cadb4e7f2 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -199,7 +199,9 @@ extern unsigned short ram_flags;
extern int root_mountflags;
char reboot_command[COMMAND_LINE_SIZE];
+
enum sparc_cpu sparc_cpu_model;
+EXPORT_SYMBOL(sparc_cpu_model);
struct tt_entry *sparc_ttable;
@@ -391,6 +393,7 @@ void sun_do_break(void)
prom_cmdline();
}
+EXPORT_SYMBOL(sun_do_break);
int stop_a_enabled = 1;
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 555db7452ebe..f2bcfd2967d7 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -58,6 +58,7 @@
* operations in asm/ns87303.h
*/
DEFINE_SPINLOCK(ns87303_lock);
+EXPORT_SYMBOL(ns87303_lock);
struct screen_info screen_info = {
0, 0, /* orig-x, orig-y */
@@ -353,6 +354,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
seq_printf(m,
"cpu\t\t: %s\n"
"fpu\t\t: %s\n"
+ "pmu\t\t: %s\n"
"prom\t\t: %s\n"
"type\t\t: %s\n"
"ncpus probed\t: %d\n"
@@ -365,6 +367,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
,
sparc_cpu_type,
sparc_fpu_type,
+ sparc_pmu_type,
prom_version,
((tlb_type == hypervisor) ?
"sun4v" :
@@ -425,5 +428,7 @@ void sun_do_break(void)
prom_cmdline();
}
+EXPORT_SYMBOL(sun_do_break);
int stop_a_enabled = 1;
+EXPORT_SYMBOL(stop_a_enabled);
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index c94f91c8b6e0..181d069a2d44 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -34,7 +34,7 @@ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
struct signal_frame {
struct sparc_stackf ss;
- __siginfo_t info;
+ __siginfo32_t info;
__siginfo_fpu_t __user *fpu_save;
unsigned long insns[2] __attribute__ ((aligned (8)));
unsigned int extramask[_NSIG_WORDS - 1];
@@ -351,7 +351,7 @@ static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __copy_to_user(sf->extramask, &oldset->sig[1],
(_NSIG_WORDS - 1) * sizeof(unsigned int));
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
- sizeof(struct reg_window));
+ sizeof(struct reg_window32));
if (err)
goto sigsegv;
@@ -433,7 +433,7 @@ static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP],
- sizeof(struct reg_window));
+ sizeof(struct reg_window32));
err |= copy_siginfo_to_user(&sf->info, info);
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c
index e396c1f17a92..1e5ac4e282e1 100644
--- a/arch/sparc/kernel/smp_32.c
+++ b/arch/sparc/kernel/smp_32.c
@@ -39,8 +39,6 @@ volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,};
unsigned char boot_cpu_id = 0;
unsigned char boot_cpu_id4 = 0; /* boot_cpu_id << 2 */
-cpumask_t cpu_online_map = CPU_MASK_NONE;
-cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
cpumask_t smp_commenced_mask = CPU_MASK_NONE;
/* The only guaranteed locking primitive available on all Sparc
@@ -334,7 +332,7 @@ void __init smp_setup_cpu_possible_map(void)
instance = 0;
while (!cpu_find_by_instance(instance, NULL, &mid)) {
if (mid < NR_CPUS) {
- cpu_set(mid, phys_cpu_present_map);
+ cpu_set(mid, cpu_possible_map);
cpu_set(mid, cpu_present_map);
}
instance++;
@@ -354,7 +352,7 @@ void __init smp_prepare_boot_cpu(void)
current_thread_info()->cpu = cpuid;
cpu_set(cpuid, cpu_online_map);
- cpu_set(cpuid, phys_cpu_present_map);
+ cpu_set(cpuid, cpu_possible_map);
}
int __cpuinit __cpu_up(unsigned int cpu)
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index bfe99d82d458..6cd1a5b65067 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -49,14 +49,10 @@
int sparc64_multi_core __read_mostly;
-cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
-cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
-EXPORT_SYMBOL(cpu_possible_map);
-EXPORT_SYMBOL(cpu_online_map);
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
EXPORT_SYMBOL(cpu_core_map);
@@ -453,7 +449,7 @@ again:
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: : "r" (pstate));
if (stuck == 0) {
- printk("CPU[%d]: mondo stuckage result[%016lx]\n",
+ printk("CPU[%d]: mondo stuckage result[%016llx]\n",
smp_processor_id(), result);
} else {
udelay(2);
@@ -588,7 +584,7 @@ retry:
/* Busy bits will not clear, continue instead
* of freezing up on this cpu.
*/
- printk("CPU[%d]: mondo stuckage result[%016lx]\n",
+ printk("CPU[%d]: mondo stuckage result[%016llx]\n",
smp_processor_id(), dispatch_stat);
} else {
int i, this_busy_nack = 0;
diff --git a/arch/sparc/kernel/sparc_ksyms_32.c b/arch/sparc/kernel/sparc_ksyms_32.c
index a4d45fc29b21..baeab8720237 100644
--- a/arch/sparc/kernel/sparc_ksyms_32.c
+++ b/arch/sparc/kernel/sparc_ksyms_32.c
@@ -5,49 +5,14 @@
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
*/
-/* Tell string.h we don't want memcpy etc. as cpp defines */
-#define EXPORT_SYMTAB_STROPS
-#define PROMLIB_INTERNAL
-
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/in6.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/syscalls.h>
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
-#include <linux/pm.h>
-#ifdef CONFIG_HIGHMEM
-#include <linux/highmem.h>
-#endif
-#include <asm/oplib.h>
-#include <asm/delay.h>
-#include <asm/system.h>
-#include <asm/auxio.h>
#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/idprom.h>
-#include <asm/head.h>
-#include <asm/smp.h>
-#include <asm/ptrace.h>
#include <asm/uaccess.h>
-#include <asm/checksum.h>
-#ifdef CONFIG_SBUS
+#include <asm/delay.h>
+#include <asm/head.h>
#include <asm/dma.h>
-#endif
-#include <asm/io-unit.h>
-#include <asm/bug.h>
-
-extern spinlock_t rtc_lock;
struct poll {
int fd;
@@ -55,76 +20,15 @@ struct poll {
short revents;
};
-extern void (*__copy_1page)(void *, const void *);
-extern void __memmove(void *, const void *, __kernel_size_t);
-extern void (*bzero_1page)(void *);
-extern void *__bzero(void *, size_t);
-extern void *__memscan_zero(void *, size_t);
-extern void *__memscan_generic(void *, int, size_t);
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-
-extern int __ashrdi3(int, int);
-extern int __ashldi3(int, int);
-extern int __lshrdi3(int, int);
-extern int __muldi3(int, int);
-extern int __divdi3(int, int);
-
-/* Private functions with odd calling conventions. */
-extern void ___atomic24_add(void);
-extern void ___atomic24_sub(void);
-extern void ___rw_read_enter(void);
-extern void ___rw_read_try(void);
-extern void ___rw_read_exit(void);
-extern void ___rw_write_enter(void);
-
-/* Alias functions whose names begin with "." and export the aliases.
- * The module references will be fixed up by module_frob_arch_sections.
- */
-extern int _Div(int, int);
-extern int _Mul(int, int);
-extern int _Rem(int, int);
-extern unsigned _Udiv(unsigned, unsigned);
-extern unsigned _Umul(unsigned, unsigned);
-extern unsigned _Urem(unsigned, unsigned);
-
-/* used by various drivers */
-EXPORT_SYMBOL(sparc_cpu_model);
-EXPORT_SYMBOL(kernel_thread);
-#ifdef CONFIG_SMP
-// XXX find what uses (or used) these. AV: see asm/spinlock.h
-EXPORT_SYMBOL(___rw_read_enter);
-EXPORT_SYMBOL(___rw_read_try);
-EXPORT_SYMBOL(___rw_read_exit);
-EXPORT_SYMBOL(___rw_write_enter);
-#endif
-
-EXPORT_SYMBOL(sparc_valid_addr_bitmap);
-EXPORT_SYMBOL(phys_base);
-EXPORT_SYMBOL(pfn_base);
-
-/* Atomic operations. */
-EXPORT_SYMBOL(___atomic24_add);
-EXPORT_SYMBOL(___atomic24_sub);
-
-/* Per-CPU information table */
-EXPORT_PER_CPU_SYMBOL(__cpu_data);
-
-#ifdef CONFIG_SMP
-/* IRQ implementation. */
-EXPORT_SYMBOL(synchronize_irq);
-
-/* CPU online map and active count. */
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(phys_cpu_present_map);
-#endif
-
+/* from entry.S */
EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(rtc_lock);
-EXPORT_SYMBOL(set_auxio);
-EXPORT_SYMBOL(get_auxio);
-EXPORT_SYMBOL(io_remap_pfn_range);
+/* from head_32.S */
+EXPORT_SYMBOL(__ret_efault);
+EXPORT_SYMBOL(empty_zero_page);
+
+/* Defined using magic */
#ifndef CONFIG_SMP
EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32));
#else
@@ -136,122 +40,7 @@ EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl));
EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_one));
EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_sgl));
EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one));
-
EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached));
-#ifdef CONFIG_SBUS
-EXPORT_SYMBOL(sbus_set_sbus64);
-#endif
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(insl);
-EXPORT_SYMBOL(outsl);
-EXPORT_SYMBOL(pci_alloc_consistent);
-EXPORT_SYMBOL(pci_free_consistent);
-EXPORT_SYMBOL(pci_map_single);
-EXPORT_SYMBOL(pci_unmap_single);
-EXPORT_SYMBOL(pci_dma_sync_single_for_cpu);
-EXPORT_SYMBOL(pci_dma_sync_single_for_device);
-EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu);
-EXPORT_SYMBOL(pci_dma_sync_sg_for_device);
-EXPORT_SYMBOL(pci_map_sg);
-EXPORT_SYMBOL(pci_unmap_sg);
-EXPORT_SYMBOL(pci_map_page);
-EXPORT_SYMBOL(pci_unmap_page);
-/* Actually, ioremap/iounmap are not PCI specific. But it is ok for drivers. */
-EXPORT_SYMBOL(ioremap);
-EXPORT_SYMBOL(iounmap);
-#endif
-
-/* in arch/sparc/mm/highmem.c */
-#ifdef CONFIG_HIGHMEM
-EXPORT_SYMBOL(kmap_atomic);
-EXPORT_SYMBOL(kunmap_atomic);
-#endif
-
-/* prom symbols */
-EXPORT_SYMBOL(idprom);
-EXPORT_SYMBOL(prom_root_node);
-EXPORT_SYMBOL(prom_getchild);
-EXPORT_SYMBOL(prom_getsibling);
-EXPORT_SYMBOL(prom_searchsiblings);
-EXPORT_SYMBOL(prom_firstprop);
-EXPORT_SYMBOL(prom_nextprop);
-EXPORT_SYMBOL(prom_getproplen);
-EXPORT_SYMBOL(prom_getproperty);
-EXPORT_SYMBOL(prom_node_has_property);
-EXPORT_SYMBOL(prom_setprop);
+/* Exporting a symbol from /init/main.c */
EXPORT_SYMBOL(saved_command_line);
-EXPORT_SYMBOL(prom_apply_obio_ranges);
-EXPORT_SYMBOL(prom_feval);
-EXPORT_SYMBOL(prom_getbool);
-EXPORT_SYMBOL(prom_getstring);
-EXPORT_SYMBOL(prom_getint);
-EXPORT_SYMBOL(prom_getintdefault);
-EXPORT_SYMBOL(prom_finddevice);
-EXPORT_SYMBOL(romvec);
-EXPORT_SYMBOL(__prom_getchild);
-EXPORT_SYMBOL(__prom_getsibling);
-
-/* sparc library symbols */
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(page_kernel);
-
-/* Special internal versions of library functions. */
-EXPORT_SYMBOL(__copy_1page);
-EXPORT_SYMBOL(__memcpy);
-EXPORT_SYMBOL(__memset);
-EXPORT_SYMBOL(bzero_1page);
-EXPORT_SYMBOL(__bzero);
-EXPORT_SYMBOL(__memscan_zero);
-EXPORT_SYMBOL(__memscan_generic);
-EXPORT_SYMBOL(__strncmp);
-EXPORT_SYMBOL(__memmove);
-
-/* Moving data to/from userspace. */
-EXPORT_SYMBOL(__copy_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(__strnlen_user);
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(__csum_partial_copy_sparc_generic);
-EXPORT_SYMBOL(csum_partial);
-
-/* Cache flushing. */
-EXPORT_SYMBOL(sparc_flush_page_to_ram);
-
-/* For when serial stuff is built as modules. */
-EXPORT_SYMBOL(sun_do_break);
-
-EXPORT_SYMBOL(__ret_efault);
-
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(__ashrdi3);
-EXPORT_SYMBOL(__ashldi3);
-EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(__muldi3);
-EXPORT_SYMBOL(__divdi3);
-
-EXPORT_SYMBOL(_Rem);
-EXPORT_SYMBOL(_Urem);
-EXPORT_SYMBOL(_Mul);
-EXPORT_SYMBOL(_Umul);
-EXPORT_SYMBOL(_Div);
-EXPORT_SYMBOL(_Udiv);
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-EXPORT_SYMBOL(do_BUG);
-#endif
-
-/* Sun Power Management Idle Handler */
-EXPORT_SYMBOL(pm_idle);
-
-EXPORT_SYMBOL(empty_zero_page);
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c
index 0133211ab634..0f26066a08d9 100644
--- a/arch/sparc/kernel/sparc_ksyms_64.c
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
@@ -5,50 +5,15 @@
* Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
-/* Tell string.h we don't want memcpy etc. as cpp defines */
-#define EXPORT_SYMTAB_STROPS
-#define PROMLIB_INTERNAL
-
#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/in6.h>
#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/fs_struct.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/syscalls.h>
-#include <linux/percpu.h>
#include <linux/init.h>
-#include <linux/rwsem.h>
-#include <net/compat.h>
-#include <asm/oplib.h>
#include <asm/system.h>
-#include <asm/auxio.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/idprom.h>
-#include <asm/elf.h>
-#include <asm/head.h>
-#include <asm/smp.h>
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/checksum.h>
-#include <asm/fpumacro.h>
-#include <asm/pgalloc.h>
-#include <asm/cacheflush.h>
-#ifdef CONFIG_SBUS
-#include <asm/dma.h>
-#endif
-#include <asm/ns87303.h>
-#include <asm/timer.h>
#include <asm/cpudata.h>
-#include <asm/ftrace.h>
+#include <asm/uaccess.h>
+#include <asm/spitfire.h>
+#include <asm/oplib.h>
#include <asm/hypervisor.h>
struct poll {
@@ -57,114 +22,24 @@ struct poll {
short revents;
};
-extern void die_if_kernel(char *str, struct pt_regs *regs);
-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-extern void *__bzero(void *, size_t);
-extern void *__memscan_zero(void *, size_t);
-extern void *__memscan_generic(void *, int, size_t);
-extern __kernel_size_t strlen(const char *);
-extern void sys_sigsuspend(void);
-extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
-extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
-extern long sparc32_open(const char __user * filename, int flags, int mode);
-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
- unsigned long pfn, unsigned long size, pgprot_t prot);
-
-extern int __ashrdi3(int, int);
-
-extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
-
-extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
-extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
- unsigned long *);
-extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *,
- unsigned long *, unsigned long *);
-extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *,
- unsigned long *, unsigned long *, unsigned long *);
-
-extern void xor_niagara_2(unsigned long, unsigned long *, unsigned long *);
-extern void xor_niagara_3(unsigned long, unsigned long *, unsigned long *,
- unsigned long *);
-extern void xor_niagara_4(unsigned long, unsigned long *, unsigned long *,
- unsigned long *, unsigned long *);
-extern void xor_niagara_5(unsigned long, unsigned long *, unsigned long *,
- unsigned long *, unsigned long *, unsigned long *);
-
-/* Per-CPU information table */
-EXPORT_PER_CPU_SYMBOL(__cpu_data);
-
-/* used by various drivers */
-#ifdef CONFIG_SMP
-/* Out of line rw-locking implementation. */
-EXPORT_SYMBOL(__read_lock);
-EXPORT_SYMBOL(__read_unlock);
-EXPORT_SYMBOL(__write_lock);
-EXPORT_SYMBOL(__write_unlock);
-EXPORT_SYMBOL(__write_trylock);
-#endif /* CONFIG_SMP */
-
-#ifdef CONFIG_MCOUNT
-EXPORT_SYMBOL(_mcount);
-#endif
-
-EXPORT_SYMBOL(sparc64_get_clock_tick);
-
-/* RW semaphores */
-EXPORT_SYMBOL(__down_read);
-EXPORT_SYMBOL(__down_read_trylock);
-EXPORT_SYMBOL(__down_write);
-EXPORT_SYMBOL(__down_write_trylock);
-EXPORT_SYMBOL(__up_read);
-EXPORT_SYMBOL(__up_write);
-EXPORT_SYMBOL(__downgrade_write);
-
-/* Atomic counter implementation. */
-EXPORT_SYMBOL(atomic_add);
-EXPORT_SYMBOL(atomic_add_ret);
-EXPORT_SYMBOL(atomic_sub);
-EXPORT_SYMBOL(atomic_sub_ret);
-EXPORT_SYMBOL(atomic64_add);
-EXPORT_SYMBOL(atomic64_add_ret);
-EXPORT_SYMBOL(atomic64_sub);
-EXPORT_SYMBOL(atomic64_sub_ret);
-
-/* Atomic bit operations. */
-EXPORT_SYMBOL(test_and_set_bit);
-EXPORT_SYMBOL(test_and_clear_bit);
-EXPORT_SYMBOL(test_and_change_bit);
-EXPORT_SYMBOL(set_bit);
-EXPORT_SYMBOL(clear_bit);
-EXPORT_SYMBOL(change_bit);
-
+/* from helpers.S */
EXPORT_SYMBOL(__flushw_user);
+EXPORT_SYMBOL_GPL(real_hard_smp_processor_id);
+/* from head_64.S */
+EXPORT_SYMBOL(__ret_efault);
EXPORT_SYMBOL(tlb_type);
EXPORT_SYMBOL(sun4v_chip_type);
-EXPORT_SYMBOL(get_fb_unmapped_area);
-EXPORT_SYMBOL(flush_icache_range);
-
-EXPORT_SYMBOL(flush_dcache_page);
-#ifdef DCACHE_ALIASING_POSSIBLE
-EXPORT_SYMBOL(__flush_dcache_range);
-#endif
+EXPORT_SYMBOL(prom_root_node);
+/* from hvcalls.S */
EXPORT_SYMBOL(sun4v_niagara_getperf);
EXPORT_SYMBOL(sun4v_niagara_setperf);
EXPORT_SYMBOL(sun4v_niagara2_getperf);
EXPORT_SYMBOL(sun4v_niagara2_setperf);
-EXPORT_SYMBOL(auxio_set_led);
-EXPORT_SYMBOL(auxio_set_lte);
-#ifdef CONFIG_SBUS
-EXPORT_SYMBOL(sbus_set_sbus64);
-#endif
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(outsl);
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(insl);
#ifdef CONFIG_PCI
+/* inline functions in asm/pci_64.h */
EXPORT_SYMBOL(pci_alloc_consistent);
EXPORT_SYMBOL(pci_free_consistent);
EXPORT_SYMBOL(pci_map_single);
@@ -173,112 +48,7 @@ EXPORT_SYMBOL(pci_map_sg);
EXPORT_SYMBOL(pci_unmap_sg);
EXPORT_SYMBOL(pci_dma_sync_single_for_cpu);
EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu);
-EXPORT_SYMBOL(pci_dma_supported);
#endif
-/* I/O device mmaping on Sparc64. */
-EXPORT_SYMBOL(io_remap_pfn_range);
-
-EXPORT_SYMBOL(dump_fpu);
-
-/* math-emu wants this */
-EXPORT_SYMBOL(die_if_kernel);
-
-/* Kernel thread creation. */
-EXPORT_SYMBOL(kernel_thread);
-
-/* prom symbols */
-EXPORT_SYMBOL(idprom);
-EXPORT_SYMBOL(prom_root_node);
-EXPORT_SYMBOL(prom_getchild);
-EXPORT_SYMBOL(prom_getsibling);
-EXPORT_SYMBOL(prom_searchsiblings);
-EXPORT_SYMBOL(prom_firstprop);
-EXPORT_SYMBOL(prom_nextprop);
-EXPORT_SYMBOL(prom_getproplen);
-EXPORT_SYMBOL(prom_getproperty);
-EXPORT_SYMBOL(prom_node_has_property);
-EXPORT_SYMBOL(prom_setprop);
+/* Exporting a symbol from /init/main.c */
EXPORT_SYMBOL(saved_command_line);
-EXPORT_SYMBOL(prom_finddevice);
-EXPORT_SYMBOL(prom_feval);
-EXPORT_SYMBOL(prom_getbool);
-EXPORT_SYMBOL(prom_getstring);
-EXPORT_SYMBOL(prom_getint);
-EXPORT_SYMBOL(prom_getintdefault);
-EXPORT_SYMBOL(__prom_getchild);
-EXPORT_SYMBOL(__prom_getsibling);
-
-/* sparc library symbols */
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(__strlen_user);
-EXPORT_SYMBOL(__strnlen_user);
-
-/* Special internal versions of library functions. */
-EXPORT_SYMBOL(_clear_page);
-EXPORT_SYMBOL(clear_user_page);
-EXPORT_SYMBOL(copy_user_page);
-EXPORT_SYMBOL(__bzero);
-EXPORT_SYMBOL(__memscan_zero);
-EXPORT_SYMBOL(__memscan_generic);
-EXPORT_SYMBOL(__memset);
-
-EXPORT_SYMBOL(csum_partial);
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
-EXPORT_SYMBOL(__csum_partial_copy_from_user);
-EXPORT_SYMBOL(__csum_partial_copy_to_user);
-EXPORT_SYMBOL(ip_fast_csum);
-
-/* Moving data to/from/in userspace. */
-EXPORT_SYMBOL(___copy_to_user);
-EXPORT_SYMBOL(___copy_from_user);
-EXPORT_SYMBOL(___copy_in_user);
-EXPORT_SYMBOL(copy_to_user_fixup);
-EXPORT_SYMBOL(copy_from_user_fixup);
-EXPORT_SYMBOL(copy_in_user_fixup);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(__clear_user);
-
-/* Various address conversion macros use this. */
-EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
-
-/* No version information on this, heavily used in inline asm,
- * and will always be 'void __ret_efault(void)'.
- */
-EXPORT_SYMBOL(__ret_efault);
-
-/* No version information on these, as gcc produces such symbols. */
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strncmp);
-
-void VISenter(void);
-/* RAID code needs this */
-EXPORT_SYMBOL(VISenter);
-
-/* for input/keybdev */
-EXPORT_SYMBOL(sun_do_break);
-EXPORT_SYMBOL(stop_a_enabled);
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-EXPORT_SYMBOL(do_BUG);
-#endif
-
-/* for ns8703 */
-EXPORT_SYMBOL(ns87303_lock);
-
-EXPORT_SYMBOL(tick_ops);
-
-EXPORT_SYMBOL(xor_vis_2);
-EXPORT_SYMBOL(xor_vis_3);
-EXPORT_SYMBOL(xor_vis_4);
-EXPORT_SYMBOL(xor_vis_5);
-
-EXPORT_SYMBOL(xor_niagara_2);
-EXPORT_SYMBOL(xor_niagara_3);
-EXPORT_SYMBOL(xor_niagara_4);
-EXPORT_SYMBOL(xor_niagara_5);
-
-EXPORT_SYMBOL_GPL(real_hard_smp_processor_id);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 16ab0cb731c5..50afaed99c8a 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -60,7 +60,7 @@ extern int __smp4d_processor_id(void);
#define SMP_PRINTK(x)
#endif
-static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val)
+static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned long val)
{
__asm__ __volatile__("swap [%1], %0\n\t" :
"=&r" (val), "=&r" (ptr) :
@@ -115,7 +115,7 @@ void __cpuinit smp4d_callin(void)
local_flush_tlb_all();
/* Allow master to continue. */
- swap((unsigned long *)&cpu_callin_map[cpuid], 1);
+ sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
local_flush_cache_all();
local_flush_tlb_all();
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 4f8d60586b07..8040376c4890 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -54,7 +54,8 @@ extern int __smp4m_processor_id(void);
#define SMP_PRINTK(x)
#endif
-static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val)
+static inline unsigned long
+swap_ulong(volatile unsigned long *ptr, unsigned long val)
{
__asm__ __volatile__("swap [%1], %0\n\t" :
"=&r" (val), "=&r" (ptr) :
@@ -90,7 +91,7 @@ void __cpuinit smp4m_callin(void)
* to call the scheduler code.
*/
/* Allow master to continue. */
- swap(&cpu_callin_map[cpuid], 1);
+ swap_ulong(&cpu_callin_map[cpuid], 1);
/* XXX: What's up with all the flushes? */
local_flush_cache_all();
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 39749e32dc7e..e2d102447a43 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -23,6 +23,7 @@
#include <linux/ipc.h>
#include <linux/personality.h>
#include <linux/random.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/utrap.h>
@@ -354,6 +355,7 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
return addr;
}
+EXPORT_SYMBOL(get_fb_unmapped_area);
/* Essentially the same as PowerPC... */
void arch_pick_mmap_layout(struct mm_struct *mm)
@@ -397,7 +399,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
}
}
-asmlinkage unsigned long sparc_brk(unsigned long brk)
+SYSCALL_DEFINE1(sparc_brk, unsigned long, brk)
{
/* People could try to be nasty and use ta 0x6d in 32bit programs */
if (test_thread_flag(TIF_32BIT) && brk >= STACK_TOP32)
@@ -413,7 +415,7 @@ asmlinkage unsigned long sparc_brk(unsigned long brk)
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
*/
-asmlinkage long sparc_pipe(struct pt_regs *regs)
+SYSCALL_DEFINE1(sparc_pipe_real, struct pt_regs *, regs)
{
int fd[2];
int error;
@@ -433,8 +435,8 @@ out:
* This is really horribly ugly.
*/
-asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
- unsigned long third, void __user *ptr, long fifth)
+SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
+ unsigned long, third, void __user *, ptr, long, fifth)
{
long err;
@@ -517,7 +519,7 @@ out:
return err;
}
-asmlinkage long sparc64_newuname(struct new_utsname __user *name)
+SYSCALL_DEFINE1(sparc64_newuname, struct new_utsname __user *, name)
{
int ret = sys_newuname(name);
@@ -528,7 +530,7 @@ asmlinkage long sparc64_newuname(struct new_utsname __user *name)
return ret;
}
-asmlinkage long sparc64_personality(unsigned long personality)
+SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)
{
int ret;
@@ -562,9 +564,9 @@ int sparc_mmap_check(unsigned long addr, unsigned long len)
}
/* Linux version of mmap */
-asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags, unsigned long fd,
- unsigned long off)
+SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
+ unsigned long, prot, unsigned long, flags, unsigned long, fd,
+ unsigned long, off)
{
struct file * file = NULL;
unsigned long retval = -EBADF;
@@ -587,7 +589,7 @@ out:
return retval;
}
-asmlinkage long sys64_munmap(unsigned long addr, size_t len)
+SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len)
{
long ret;
@@ -604,9 +606,9 @@ extern unsigned long do_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, unsigned long new_addr);
-asmlinkage unsigned long sys64_mremap(unsigned long addr,
- unsigned long old_len, unsigned long new_len,
- unsigned long flags, unsigned long new_addr)
+SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len,
+ unsigned long, new_len, unsigned long, flags,
+ unsigned long, new_addr)
{
unsigned long ret = -EINVAL;
@@ -669,7 +671,7 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs)
extern void check_pending(int signum);
-asmlinkage long sys_getdomainname(char __user *name, int len)
+SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len)
{
int nlen, err;
@@ -692,11 +694,10 @@ out:
return err;
}
-asmlinkage long sys_utrap_install(utrap_entry_t type,
- utrap_handler_t new_p,
- utrap_handler_t new_d,
- utrap_handler_t __user *old_p,
- utrap_handler_t __user *old_d)
+SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type,
+ utrap_handler_t, new_p, utrap_handler_t, new_d,
+ utrap_handler_t __user *, old_p,
+ utrap_handler_t __user *, old_d)
{
if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31)
return -EINVAL;
@@ -762,11 +763,9 @@ asmlinkage long sparc_memory_ordering(unsigned long model,
return 0;
}
-asmlinkage long sys_rt_sigaction(int sig,
- const struct sigaction __user *act,
- struct sigaction __user *oact,
- void __user *restorer,
- size_t sigsetsize)
+SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
+ struct sigaction __user *, oact, void __user *, restorer,
+ size_t, sigsetsize)
{
struct k_sigaction new_ka, old_ka;
int ret;
@@ -806,7 +805,8 @@ asmlinkage void update_perfctrs(void)
reset_pic();
}
-asmlinkage long sys_perfctr(int opcode, unsigned long arg0, unsigned long arg1, unsigned long arg2)
+SYSCALL_DEFINE4(perfctr, int, opcode, unsigned long, arg0,
+ unsigned long, arg1, unsigned long, arg2)
{
int err = 0;
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 7a6786a71363..d150c2aa98d2 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -20,8 +20,8 @@ execve_merge:
add %sp, PTREGS_OFF, %o0
.align 32
-sys_pipe:
- ba,pt %xcc, sparc_pipe
+sys_sparc_pipe:
+ ba,pt %xcc, sys_sparc_pipe_real
add %sp, PTREGS_OFF, %o0
sys_nis_syscall:
ba,pt %xcc, c_sys_nis_syscall
diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h
index bc9f5dac4069..15c2d752b2bc 100644
--- a/arch/sparc/kernel/systbls.h
+++ b/arch/sparc/kernel/systbls.h
@@ -16,9 +16,6 @@ extern asmlinkage long sys_ipc(unsigned int call, int first,
void __user *ptr, long fifth);
extern asmlinkage long sparc64_newuname(struct new_utsname __user *name);
extern asmlinkage long sparc64_personality(unsigned long personality);
-extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long off);
extern asmlinkage long sys64_munmap(unsigned long addr, size_t len);
extern asmlinkage unsigned long sys64_mremap(unsigned long addr,
unsigned long old_len,
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S
index 7d0807586442..dccc95df0c7f 100644
--- a/arch/sparc/kernel/systbls_32.S
+++ b/arch/sparc/kernel/systbls_32.S
@@ -24,7 +24,7 @@ sys_call_table:
/*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
/*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
/*35*/ .long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile
-/*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_getuid
+/*40*/ .long sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_getuid
/*45*/ .long sys_umount, sys_setgid16, sys_getgid16, sys_signal, sys_geteuid16
/*50*/ .long sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys_ioctl
/*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve
@@ -56,7 +56,7 @@ sys_call_table:
/*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname
/*190*/ .long sys_init_module, sys_personality, sparc_remap_file_pages, sys_epoll_create, sys_epoll_ctl
/*195*/ .long sys_epoll_wait, sys_ioprio_set, sys_getppid, sparc_sigaction, sys_sgetmask
-/*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
+/*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_old_readdir
/*205*/ .long sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64
/*210*/ .long sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo
/*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_ioprio_get, sys_adjtimex
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 9fc78cf354bd..f93c42a2b522 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -21,12 +21,12 @@ sys_call_table32:
/*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write
/*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod
-/*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek
+/*15*/ .word sys_chmod, sys_lchown16, sys_sparc_brk, sys32_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
/*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
-/*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid
+/*40*/ .word compat_sys_newlstat, sys_dup, sys_sparc_pipe, compat_sys_times, sys_getuid
.word sys32_umount, sys_setgid16, sys_getgid16, sys32_signal, sys_geteuid16
/*50*/ .word sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl
.word sys32_reboot, sys32_mmap2, sys_symlink, sys32_readlink, sys32_execve
@@ -55,8 +55,8 @@ sys_call_table32:
/*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents
.word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr
/*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall
- .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sparc64_newuname
-/*190*/ .word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl
+ .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sys_sparc64_newuname
+/*190*/ .word sys32_init_module, sys_sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl
.word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask
/*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
.word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64
@@ -95,18 +95,18 @@ sys_call_table:
/*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write
/*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link
/*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod
-/*15*/ .word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek
+/*15*/ .word sys_chmod, sys_lchown, sys_sparc_brk, sys_perfctr, sys_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
/*25*/ .word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
/*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
.word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile64
-/*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
+/*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall
.word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
/*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl
.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
.word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall
-/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect
+/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect
.word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups
/*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
.word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
@@ -129,8 +129,8 @@ sys_call_table:
/*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
.word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
/*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall
- .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sparc64_newuname
-/*190*/ .word sys_init_module, sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
+ .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_sparc64_newuname
+/*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
.word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask
/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
.word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64
@@ -142,7 +142,7 @@ sys_call_table:
.word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
-/*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+/*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
.word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep
/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 00f7383c7657..614ac7b4a9dd 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -48,6 +48,8 @@
#include "irq.h"
DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
+
static int set_rtc_mmss(unsigned long);
static int sbus_do_settimeofday(struct timespec *tv);
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index 141da3759091..2db3c2229b95 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -106,7 +106,7 @@ static void tick_init_tick(void)
tick_disable_irq();
}
-static unsigned long tick_get_tick(void)
+static unsigned long long tick_get_tick(void)
{
unsigned long ret;
@@ -176,6 +176,7 @@ static struct sparc64_tick_ops tick_operations __read_mostly = {
};
struct sparc64_tick_ops *tick_ops __read_mostly = &tick_operations;
+EXPORT_SYMBOL(tick_ops);
static void stick_disable_irq(void)
{
@@ -208,7 +209,7 @@ static void stick_init_tick(void)
stick_disable_irq();
}
-static unsigned long stick_get_tick(void)
+static unsigned long long stick_get_tick(void)
{
unsigned long ret;
@@ -352,7 +353,7 @@ static void hbtick_init_tick(void)
hbtick_disable_irq();
}
-static unsigned long hbtick_get_tick(void)
+static unsigned long long hbtick_get_tick(void)
{
return __hbird_read_stick() & ~TICK_PRIV_BIT;
}
@@ -422,7 +423,7 @@ static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *
{
struct resource *r;
- printk(KERN_INFO "%s: RTC regs at 0x%lx\n",
+ printk(KERN_INFO "%s: RTC regs at 0x%llx\n",
op->node->full_name, op->resource[0].start);
/* The CMOS RTC driver only accepts IORESOURCE_IO, so cons
@@ -478,7 +479,7 @@ static struct platform_device rtc_bq4802_device = {
static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match)
{
- printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n",
+ printk(KERN_INFO "%s: BQ4802 regs at 0x%llx\n",
op->node->full_name, op->resource[0].start);
rtc_bq4802_device.resource = &op->resource[0];
@@ -542,7 +543,7 @@ static int __devinit mostek_probe(struct of_device *op, const struct of_device_i
strcmp(dp->parent->parent->name, "central") != 0)
return -ENODEV;
- printk(KERN_INFO "%s: Mostek regs at 0x%lx\n",
+ printk(KERN_INFO "%s: Mostek regs at 0x%llx\n",
dp->full_name, op->resource[0].start);
m48t59_rtc.resource = &op->resource[0];
@@ -639,6 +640,7 @@ unsigned long sparc64_get_clock_tick(unsigned int cpu)
return ft->clock_tick_ref;
return cpu_data(cpu).clock_tick;
}
+EXPORT_SYMBOL(sparc64_get_clock_tick);
#ifdef CONFIG_CPU_FREQ
@@ -763,7 +765,7 @@ void __devinit setup_sparc64_timer(void)
sevt = &__get_cpu_var(sparc64_events);
memcpy(sevt, &sparc64_clockevent, sizeof(*sevt));
- sevt->cpumask = cpumask_of_cpu(smp_processor_id());
+ sevt->cpumask = cpumask_of(smp_processor_id());
clockevents_register_device(sevt);
}
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index 716f3946c494..358283341b47 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -67,7 +67,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
__RESTORE; __RESTORE; __RESTORE; __RESTORE;
{
- struct reg_window *rw = (struct reg_window *)regs->u_regs[UREG_FP];
+ struct reg_window32 *rw = (struct reg_window32 *)regs->u_regs[UREG_FP];
/* Stop the back trace when we hit userland or we
* find some badly aligned kernel stack. Set an upper
@@ -79,7 +79,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
!(((unsigned long) rw) & 0x7)) {
printk("Caller[%08lx]: %pS\n", rw->ins[7],
(void *) rw->ins[7]);
- rw = (struct reg_window *)rw->ins[6];
+ rw = (struct reg_window32 *)rw->ins[6];
}
}
printk("Instruction DUMP:");
@@ -424,6 +424,7 @@ void do_BUG(const char *file, int line)
// bust_spinlocks(1); XXX Not in our original BUG()
printk("kernel BUG at %s:%d!\n", file, line);
}
+EXPORT_SYMBOL(do_BUG);
#endif
/* Since we have our mappings set up, on multiprocessors we can spin them
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index 4638af2f55a0..d809c4ebb48f 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -1,6 +1,6 @@
/* arch/sparc64/kernel/traps.c
*
- * Copyright (C) 1995,1997,2008 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1995,1997,2008,2009 David S. Miller (davem@davemloft.net)
* Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
*/
@@ -128,6 +128,7 @@ void do_BUG(const char *file, int line)
bust_spinlocks(1);
printk("kernel BUG at %s:%d!\n", file, line);
}
+EXPORT_SYMBOL(do_BUG);
#endif
static DEFINE_SPINLOCK(dimm_handler_lock);
@@ -313,6 +314,21 @@ void sun4v_data_access_exception(struct pt_regs *regs, unsigned long addr, unsig
return;
if (regs->tstate & TSTATE_PRIV) {
+ /* Test if this comes from uaccess places. */
+ const struct exception_table_entry *entry;
+
+ entry = search_exception_tables(regs->tpc);
+ if (entry) {
+ /* Ouch, somebody is trying VM hole tricks on us... */
+#ifdef DEBUG_EXCEPTIONS
+ printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
+ printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
+ regs->tpc, entry->fixup);
+#endif
+ regs->tpc = entry->fixup;
+ regs->tnpc = regs->tpc + 4;
+ return;
+ }
printk("sun4v_data_access_exception: ADDR[%016lx] "
"CTX[%04x] TYPE[%04x], going.\n",
addr, ctx, type);
@@ -1168,20 +1184,20 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
}
/* Now dump the cache snapshots. */
- printk("%s" "ERROR(%d): D-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx]\n",
+ printk("%s" "ERROR(%d): D-cache idx[%x] tag[%016llx] utag[%016llx] stag[%016llx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
(int) info->dcache_index,
info->dcache_tag,
info->dcache_utag,
info->dcache_stag);
- printk("%s" "ERROR(%d): D-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n",
+ printk("%s" "ERROR(%d): D-cache data0[%016llx] data1[%016llx] data2[%016llx] data3[%016llx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
info->dcache_data[0],
info->dcache_data[1],
info->dcache_data[2],
info->dcache_data[3]);
- printk("%s" "ERROR(%d): I-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx] "
- "u[%016lx] l[%016lx]\n",
+ printk("%s" "ERROR(%d): I-cache idx[%x] tag[%016llx] utag[%016llx] stag[%016llx] "
+ "u[%016llx] l[%016llx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
(int) info->icache_index,
info->icache_tag,
@@ -1189,22 +1205,22 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in
info->icache_stag,
info->icache_upper,
info->icache_lower);
- printk("%s" "ERROR(%d): I-cache INSN0[%016lx] INSN1[%016lx] INSN2[%016lx] INSN3[%016lx]\n",
+ printk("%s" "ERROR(%d): I-cache INSN0[%016llx] INSN1[%016llx] INSN2[%016llx] INSN3[%016llx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
info->icache_data[0],
info->icache_data[1],
info->icache_data[2],
info->icache_data[3]);
- printk("%s" "ERROR(%d): I-cache INSN4[%016lx] INSN5[%016lx] INSN6[%016lx] INSN7[%016lx]\n",
+ printk("%s" "ERROR(%d): I-cache INSN4[%016llx] INSN5[%016llx] INSN6[%016llx] INSN7[%016llx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
info->icache_data[4],
info->icache_data[5],
info->icache_data[6],
info->icache_data[7]);
- printk("%s" "ERROR(%d): E-cache idx[%x] tag[%016lx]\n",
+ printk("%s" "ERROR(%d): E-cache idx[%x] tag[%016llx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
(int) info->ecache_index, info->ecache_tag);
- printk("%s" "ERROR(%d): E-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n",
+ printk("%s" "ERROR(%d): E-cache data0[%016llx] data1[%016llx] data2[%016llx] data3[%016llx]\n",
(recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(),
info->ecache_data[0],
info->ecache_data[1],
@@ -1794,7 +1810,7 @@ static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent,
int cnt;
printk("%s: Reporting on cpu %d\n", pfx, cpu);
- printk("%s: err_handle[%lx] err_stick[%lx] err_type[%08x:%s]\n",
+ printk("%s: err_handle[%llx] err_stick[%llx] err_type[%08x:%s]\n",
pfx,
ent->err_handle, ent->err_stick,
ent->err_type,
@@ -1818,7 +1834,7 @@ static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent,
"privileged" : ""),
((ent->err_attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL) ?
"queue-full" : ""));
- printk("%s: err_raddr[%016lx] err_size[%u] err_cpu[%u]\n",
+ printk("%s: err_raddr[%016llx] err_size[%u] err_cpu[%u]\n",
pfx,
ent->err_raddr, ent->err_size, ent->err_cpu);
@@ -2261,6 +2277,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
do_exit(SIGKILL);
do_exit(SIGSEGV);
}
+EXPORT_SYMBOL(die_if_kernel);
#define VIS_OPCODE_MASK ((0x3 << 30) | (0x3f << 19))
#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable.S
index ea925503b42e..d9bdfb9d5c18 100644
--- a/arch/sparc/kernel/ttable.S
+++ b/arch/sparc/kernel/ttable.S
@@ -63,7 +63,8 @@ tl0_irq6: TRAP_IRQ(smp_call_function_single_client, 6)
#else
tl0_irq6: BTRAP(0x46)
#endif
-tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
+tl0_irq7: TRAP_IRQ(deferred_pcr_work_irq, 7)
+tl0_irq8: BTRAP(0x48) BTRAP(0x49)
tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
tl0_irq14: TRAP_IRQ(timer_interrupt, 14)
tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15)
diff --git a/arch/sparc/kernel/unaligned_32.c b/arch/sparc/kernel/unaligned_32.c
index c2a28c5ad650..6b1e6cde6fff 100644
--- a/arch/sparc/kernel/unaligned_32.c
+++ b/arch/sparc/kernel/unaligned_32.c
@@ -97,26 +97,26 @@ static inline int sign_extend_imm13(int imm)
static inline unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
if(reg < 16)
return (!reg ? 0 : regs->u_regs[reg]);
/* Ho hum, the slightly complicated case. */
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
return win->locals[reg - 16]; /* yes, I know what this does... */
}
static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *regs)
{
- struct reg_window __user *win;
+ struct reg_window32 __user *win;
unsigned long ret;
if (reg < 16)
return (!reg ? 0 : regs->u_regs[reg]);
/* Ho hum, the slightly complicated case. */
- win = (struct reg_window __user *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 __user *) regs->u_regs[UREG_FP];
if ((unsigned long)win & 3)
return -1;
@@ -129,11 +129,11 @@ static inline unsigned long safe_fetch_reg(unsigned int reg, struct pt_regs *reg
static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
{
- struct reg_window *win;
+ struct reg_window32 *win;
if(reg < 16)
return &regs->u_regs[reg];
- win = (struct reg_window *) regs->u_regs[UREG_FP];
+ win = (struct reg_window32 *) regs->u_regs[UREG_FP];
return &win->locals[reg - 16];
}
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
index 203ddfad9f27..379209982a07 100644
--- a/arch/sparc/kernel/unaligned_64.c
+++ b/arch/sparc/kernel/unaligned_64.c
@@ -589,7 +589,6 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
unsigned long pc = regs->tpc;
unsigned long tstate = regs->tstate;
u32 insn;
- u32 first, second;
u64 value;
u8 freg;
int flag;
@@ -601,15 +600,20 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
pc = (u32)pc;
if (get_user(insn, (u32 __user *) pc) != -EFAULT) {
int asi = decode_asi(insn, regs);
+ u32 first, second;
+ int err;
+
if ((asi > ASI_SNFL) ||
(asi < ASI_P))
goto daex;
- if (get_user(first, (u32 __user *)sfar) ||
- get_user(second, (u32 __user *)(sfar + 4))) {
- if (asi & 0x2) /* NF */ {
- first = 0; second = 0;
- } else
+ first = second = 0;
+ err = get_user(first, (u32 __user *)sfar);
+ if (!err)
+ err = get_user(second, (u32 __user *)(sfar + 4));
+ if (err) {
+ if (!(asi & 0x2))
goto daex;
+ first = second = 0;
}
save_and_clear_fpu();
freg = ((insn >> 25) & 0x1e) | ((insn >> 20) & 0x20);
diff --git a/arch/sparc/kernel/vio.c b/arch/sparc/kernel/vio.c
index 92b1f8ec01de..753d128ed158 100644
--- a/arch/sparc/kernel/vio.c
+++ b/arch/sparc/kernel/vio.c
@@ -263,10 +263,10 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
dev_set_name(&vdev->dev, "%s", bus_id_name);
vdev->dev_no = ~(u64)0;
} else if (!cfg_handle) {
- dev_set_name(&vdev->dev, "%s-%lu", bus_id_name, *id);
+ dev_set_name(&vdev->dev, "%s-%llu", bus_id_name, *id);
vdev->dev_no = *id;
} else {
- dev_set_name(&vdev->dev, "%s-%lu-%lu", bus_id_name,
+ dev_set_name(&vdev->dev, "%s-%llu-%llu", bus_id_name,
*cfg_handle, *id);
vdev->dev_no = *cfg_handle;
}
diff --git a/arch/sparc/kernel/viohs.c b/arch/sparc/kernel/viohs.c
index 708fa1705fbe..aa6ac70d4fd5 100644
--- a/arch/sparc/kernel/viohs.c
+++ b/arch/sparc/kernel/viohs.c
@@ -337,8 +337,10 @@ static int process_ver_nack(struct vio_driver_state *vio,
viodbg(HS, "GOT VERSION NACK maj[%u] min[%u] devclass[%u]\n",
pkt->major, pkt->minor, pkt->dev_class);
- if ((pkt->major == 0 && pkt->minor == 0) ||
- !(nver = find_by_major(vio, pkt->major)))
+ if (pkt->major == 0 && pkt->minor == 0)
+ return handshake_failure(vio);
+ nver = find_by_major(vio, pkt->major);
+ if (!nver)
return handshake_failure(vio);
if (send_version(vio, nver->major, nver->minor) < 0)
diff --git a/arch/sparc/kernel/windows.c b/arch/sparc/kernel/windows.c
index 9cc93eaa4abf..f24d298bda29 100644
--- a/arch/sparc/kernel/windows.c
+++ b/arch/sparc/kernel/windows.c
@@ -42,7 +42,7 @@ static inline void shift_window_buffer(int first_win, int last_win, struct threa
for(i = first_win; i < last_win; i++) {
tp->rwbuf_stkptrs[i] = tp->rwbuf_stkptrs[i+1];
- memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window));
+ memcpy(&tp->reg_window[i], &tp->reg_window[i+1], sizeof(struct reg_window32));
}
}
@@ -70,7 +70,7 @@ void synchronize_user_stack(void)
/* Ok, let it rip. */
if (copy_to_user((char __user *) sp, &tp->reg_window[window],
- sizeof(struct reg_window)))
+ sizeof(struct reg_window32)))
continue;
shift_window_buffer(window, tp->w_saved - 1, tp);
@@ -119,7 +119,7 @@ void try_to_clear_window_buffer(struct pt_regs *regs, int who)
if ((sp & 7) ||
copy_to_user((char __user *) sp, &tp->reg_window[window],
- sizeof(struct reg_window)))
+ sizeof(struct reg_window32)))
do_exit(SIGILL);
}
tp->w_saved = 0;
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 375016e19144..e75faf0e59ae 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -18,7 +18,7 @@ lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
lib-y += rwsem_$(BITS).o
lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
-lib-$(CONFIG_SPARC64) += PeeCeeI.o copy_page.o clear_page.o bzero.o
+lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o
lib-$(CONFIG_SPARC64) += csum_copy.o csum_copy_from_user.o csum_copy_to_user.o
lib-$(CONFIG_SPARC64) += VISsave.o
lib-$(CONFIG_SPARC64) += bitops.o
@@ -42,3 +42,5 @@ lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o
obj-y += iomap.o
obj-$(CONFIG_SPARC32) += atomic32.o
+obj-y += ksyms.o
+obj-$(CONFIG_SPARC64) += PeeCeeI.o
diff --git a/arch/sparc/lib/PeeCeeI.c b/arch/sparc/lib/PeeCeeI.c
index 46053e6ddd7b..6529f8657597 100644
--- a/arch/sparc/lib/PeeCeeI.c
+++ b/arch/sparc/lib/PeeCeeI.c
@@ -4,6 +4,8 @@
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/module.h>
+
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -15,6 +17,7 @@ void outsb(unsigned long __addr, const void *src, unsigned long count)
while (count--)
outb(*p++, addr);
}
+EXPORT_SYMBOL(outsb);
void outsw(unsigned long __addr, const void *src, unsigned long count)
{
@@ -25,6 +28,7 @@ void outsw(unsigned long __addr, const void *src, unsigned long count)
src += sizeof(u16);
}
}
+EXPORT_SYMBOL(outsw);
void outsl(unsigned long __addr, const void *src, unsigned long count)
{
@@ -78,6 +82,7 @@ void outsl(unsigned long __addr, const void *src, unsigned long count)
break;
}
}
+EXPORT_SYMBOL(outsl);
void insb(unsigned long __addr, void *dst, unsigned long count)
{
@@ -105,6 +110,7 @@ void insb(unsigned long __addr, void *dst, unsigned long count)
*pb++ = inb(addr);
}
}
+EXPORT_SYMBOL(insb);
void insw(unsigned long __addr, void *dst, unsigned long count)
{
@@ -132,6 +138,7 @@ void insw(unsigned long __addr, void *dst, unsigned long count)
*ps = le16_to_cpu(inw(addr));
}
}
+EXPORT_SYMBOL(insw);
void insl(unsigned long __addr, void *dst, unsigned long count)
{
@@ -200,4 +207,5 @@ void insl(unsigned long __addr, void *dst, unsigned long count)
}
}
}
+EXPORT_SYMBOL(insl);
diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c
new file mode 100644
index 000000000000..704b12668388
--- /dev/null
+++ b/arch/sparc/lib/ksyms.c
@@ -0,0 +1,196 @@
+/*
+ * Export of symbols defined in assembler
+ */
+
+/* Tell string.h we don't want memcpy etc. as cpp defines */
+#define EXPORT_SYMTAB_STROPS
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/checksum.h>
+#include <asm/uaccess.h>
+#include <asm/ftrace.h>
+
+/* string functions */
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(__strlen_user);
+EXPORT_SYMBOL(__strnlen_user);
+EXPORT_SYMBOL(strncmp);
+
+/* mem* functions */
+extern void *__memscan_zero(void *, size_t);
+extern void *__memscan_generic(void *, int, size_t);
+extern void *__bzero(void *, size_t);
+
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__memscan_zero);
+EXPORT_SYMBOL(__memscan_generic);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(__bzero);
+
+/* Moving data to/from/in userspace. */
+EXPORT_SYMBOL(__strncpy_from_user);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial);
+
+#ifdef CONFIG_MCOUNT
+EXPORT_SYMBOL(_mcount);
+#endif
+
+/*
+ * sparc
+ */
+#ifdef CONFIG_SPARC32
+extern int __ashrdi3(int, int);
+extern int __ashldi3(int, int);
+extern int __lshrdi3(int, int);
+extern int __muldi3(int, int);
+extern int __divdi3(int, int);
+
+extern void (*__copy_1page)(void *, const void *);
+extern void (*bzero_1page)(void *);
+
+extern int __strncmp(const char *, const char *, __kernel_size_t);
+
+extern void ___rw_read_enter(void);
+extern void ___rw_read_try(void);
+extern void ___rw_read_exit(void);
+extern void ___rw_write_enter(void);
+extern void ___atomic24_add(void);
+extern void ___atomic24_sub(void);
+
+/* Alias functions whose names begin with "." and export the aliases.
+ * The module references will be fixed up by module_frob_arch_sections.
+ */
+extern int _Div(int, int);
+extern int _Mul(int, int);
+extern int _Rem(int, int);
+extern unsigned _Udiv(unsigned, unsigned);
+extern unsigned _Umul(unsigned, unsigned);
+extern unsigned _Urem(unsigned, unsigned);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(__csum_partial_copy_sparc_generic);
+
+/* Special internal versions of library functions. */
+EXPORT_SYMBOL(__copy_1page);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(__memmove);
+EXPORT_SYMBOL(bzero_1page);
+
+/* string functions */
+EXPORT_SYMBOL(__strncmp);
+
+/* Moving data to/from/in userspace. */
+EXPORT_SYMBOL(__copy_user);
+
+/* Used by asm/spinlock.h */
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(___rw_read_enter);
+EXPORT_SYMBOL(___rw_read_try);
+EXPORT_SYMBOL(___rw_read_exit);
+EXPORT_SYMBOL(___rw_write_enter);
+#endif
+
+/* Atomic operations. */
+EXPORT_SYMBOL(___atomic24_add);
+EXPORT_SYMBOL(___atomic24_sub);
+
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__divdi3);
+
+EXPORT_SYMBOL(_Rem);
+EXPORT_SYMBOL(_Urem);
+EXPORT_SYMBOL(_Mul);
+EXPORT_SYMBOL(_Umul);
+EXPORT_SYMBOL(_Div);
+EXPORT_SYMBOL(_Udiv);
+#endif
+
+/*
+ * sparc64
+ */
+#ifdef CONFIG_SPARC64
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+EXPORT_SYMBOL(__csum_partial_copy_from_user);
+EXPORT_SYMBOL(__csum_partial_copy_to_user);
+EXPORT_SYMBOL(ip_fast_csum);
+
+/* Moving data to/from/in userspace. */
+EXPORT_SYMBOL(___copy_to_user);
+EXPORT_SYMBOL(___copy_from_user);
+EXPORT_SYMBOL(___copy_in_user);
+EXPORT_SYMBOL(__clear_user);
+
+/* RW semaphores */
+EXPORT_SYMBOL(__down_read);
+EXPORT_SYMBOL(__down_read_trylock);
+EXPORT_SYMBOL(__down_write);
+EXPORT_SYMBOL(__down_write_trylock);
+EXPORT_SYMBOL(__up_read);
+EXPORT_SYMBOL(__up_write);
+EXPORT_SYMBOL(__downgrade_write);
+
+/* Atomic counter implementation. */
+EXPORT_SYMBOL(atomic_add);
+EXPORT_SYMBOL(atomic_add_ret);
+EXPORT_SYMBOL(atomic_sub);
+EXPORT_SYMBOL(atomic_sub_ret);
+EXPORT_SYMBOL(atomic64_add);
+EXPORT_SYMBOL(atomic64_add_ret);
+EXPORT_SYMBOL(atomic64_sub);
+EXPORT_SYMBOL(atomic64_sub_ret);
+
+/* Atomic bit operations. */
+EXPORT_SYMBOL(test_and_set_bit);
+EXPORT_SYMBOL(test_and_clear_bit);
+EXPORT_SYMBOL(test_and_change_bit);
+EXPORT_SYMBOL(set_bit);
+EXPORT_SYMBOL(clear_bit);
+EXPORT_SYMBOL(change_bit);
+
+/* Special internal versions of library functions. */
+EXPORT_SYMBOL(_clear_page);
+EXPORT_SYMBOL(clear_user_page);
+EXPORT_SYMBOL(copy_user_page);
+
+/* RAID code needs this */
+void VISenter(void);
+EXPORT_SYMBOL(VISenter);
+
+extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
+extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *);
+extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *);
+extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *, unsigned long *);
+EXPORT_SYMBOL(xor_vis_2);
+EXPORT_SYMBOL(xor_vis_3);
+EXPORT_SYMBOL(xor_vis_4);
+EXPORT_SYMBOL(xor_vis_5);
+
+extern void xor_niagara_2(unsigned long, unsigned long *, unsigned long *);
+extern void xor_niagara_3(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *);
+extern void xor_niagara_4(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *);
+extern void xor_niagara_5(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *, unsigned long *);
+
+EXPORT_SYMBOL(xor_niagara_2);
+EXPORT_SYMBOL(xor_niagara_3);
+EXPORT_SYMBOL(xor_niagara_4);
+EXPORT_SYMBOL(xor_niagara_5);
+#endif
diff --git a/arch/sparc/lib/user_fixup.c b/arch/sparc/lib/user_fixup.c
index 05a361b0a1a4..ac96ae236709 100644
--- a/arch/sparc/lib/user_fixup.c
+++ b/arch/sparc/lib/user_fixup.c
@@ -7,6 +7,8 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/module.h>
+
#include <asm/uaccess.h>
/* Calculating the exact fault address when using
@@ -40,6 +42,7 @@ unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned l
return size;
}
+EXPORT_SYMBOL(copy_from_user_fixup);
unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned long size)
{
@@ -47,6 +50,7 @@ unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned lon
return compute_size((unsigned long) to, size, &offset);
}
+EXPORT_SYMBOL(copy_to_user_fixup);
unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned long size)
{
@@ -64,3 +68,4 @@ unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned lo
return size;
}
+EXPORT_SYMBOL(copy_in_user_fixup);
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index a507e1174662..12e447fc8542 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -283,7 +283,8 @@ bad_area_nosemaphore:
/* Is this in ex_table? */
no_context:
g2 = regs->u_regs[UREG_G2];
- if (!from_user && (fixup = search_extables_range(regs->pc, &g2))) {
+ if (!from_user) {
+ fixup = search_extables_range(regs->pc, &g2);
if (fixup > 10) { /* Values below are reserved for other things */
extern const unsigned __memset_start[];
extern const unsigned __memset_end[];
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index a9e474bf6385..4ab8993b0863 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/kprobes.h>
#include <linux/kdebug.h>
+#include <linux/percpu.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -224,6 +225,30 @@ cannot_handle:
unhandled_fault (address, current, regs);
}
+static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs)
+{
+ static int times;
+
+ if (times++ < 10)
+ printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports "
+ "64-bit TPC [%lx]\n",
+ current->comm, current->pid,
+ regs->tpc);
+ show_regs(regs);
+}
+
+static void noinline bogus_32bit_fault_address(struct pt_regs *regs,
+ unsigned long addr)
+{
+ static int times;
+
+ if (times++ < 10)
+ printk(KERN_ERR "FAULT[%s:%d]: 32-bit process "
+ "reports 64-bit fault address [%lx]\n",
+ current->comm, current->pid, addr);
+ show_regs(regs);
+}
+
asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
{
struct mm_struct *mm = current->mm;
@@ -244,6 +269,19 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
(fault_code & FAULT_CODE_DTLB))
BUG();
+ if (test_thread_flag(TIF_32BIT)) {
+ if (!(regs->tstate & TSTATE_PRIV)) {
+ if (unlikely((regs->tpc >> 32) != 0)) {
+ bogus_32bit_fault_tpc(regs);
+ goto intr_or_no_mm;
+ }
+ }
+ if (unlikely((address >> 32) != 0)) {
+ bogus_32bit_fault_address(regs, address);
+ goto intr_or_no_mm;
+ }
+ }
+
if (regs->tstate & TSTATE_PRIV) {
unsigned long tpc = regs->tpc;
@@ -264,12 +302,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
if (in_atomic() || !mm)
goto intr_or_no_mm;
- if (test_thread_flag(TIF_32BIT)) {
- if (!(regs->tstate & TSTATE_PRIV))
- regs->tpc &= 0xffffffff;
- address &= 0xffffffff;
- }
-
if (!down_read_trylock(&mm->mmap_sem)) {
if ((regs->tstate & TSTATE_PRIV) &&
!search_exception_tables(regs->tpc)) {
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c
index a289261da9fd..5edcac184eaf 100644
--- a/arch/sparc/mm/generic_32.c
+++ b/arch/sparc/mm/generic_32.c
@@ -95,3 +95,4 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
flush_tlb_range(vma, beg, end);
return error;
}
+EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c
index f362c2037013..04f2bf4cd571 100644
--- a/arch/sparc/mm/generic_64.c
+++ b/arch/sparc/mm/generic_64.c
@@ -161,3 +161,4 @@ int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
flush_tlb_range(vma, beg, end);
return error;
}
+EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c
index 01fc6c254292..752d0c9fb544 100644
--- a/arch/sparc/mm/highmem.c
+++ b/arch/sparc/mm/highmem.c
@@ -62,6 +62,7 @@ void *kmap_atomic(struct page *page, enum km_type type)
return (void*) vaddr;
}
+EXPORT_SYMBOL(kmap_atomic);
void kunmap_atomic(void *kvaddr, enum km_type type)
{
@@ -98,6 +99,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
pagefault_enable();
}
+EXPORT_SYMBOL(kunmap_atomic);
/* We may be fed a pagetable here by ptep_to_xxx and others. */
struct page *kmap_atomic_to_page(void *ptr)
diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
index fec926021f49..cbb282dab5a7 100644
--- a/arch/sparc/mm/init_32.c
+++ b/arch/sparc/mm/init_32.c
@@ -38,11 +38,16 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
unsigned long *sparc_valid_addr_bitmap;
+EXPORT_SYMBOL(sparc_valid_addr_bitmap);
unsigned long phys_base;
+EXPORT_SYMBOL(phys_base);
+
unsigned long pfn_base;
+EXPORT_SYMBOL(pfn_base);
unsigned long page_kernel;
+EXPORT_SYMBOL(page_kernel);
struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
unsigned long sparc_unmapped_base;
@@ -522,3 +527,4 @@ void sparc_flush_page_to_ram(struct page *page)
if (vaddr)
__flush_page_to_ram(vaddr);
}
+EXPORT_SYMBOL(sparc_flush_page_to_ram);
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 6ea73da29312..00373ce2d8fb 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -146,6 +146,7 @@ static void __init read_obp_memory(const char *property,
}
unsigned long *sparc64_valid_addr_bitmap __read_mostly;
+EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
/* Kernel physical address base and size in bytes. */
unsigned long kern_base __read_mostly;
@@ -258,21 +259,16 @@ static inline void tsb_insert(struct tsb *ent, unsigned long tag, unsigned long
unsigned long _PAGE_ALL_SZ_BITS __read_mostly;
unsigned long _PAGE_SZBITS __read_mostly;
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+static void flush_dcache(unsigned long pfn)
{
- struct mm_struct *mm;
- struct tsb *tsb;
- unsigned long tag, flags;
- unsigned long tsb_index, tsb_hash_shift;
+ struct page *page;
- if (tlb_type != hypervisor) {
- unsigned long pfn = pte_pfn(pte);
+ page = pfn_to_page(pfn);
+ if (page && page_mapping(page)) {
unsigned long pg_flags;
- struct page *page;
- if (pfn_valid(pfn) &&
- (page = pfn_to_page(pfn), page_mapping(page)) &&
- ((pg_flags = page->flags) & (1UL << PG_dcache_dirty))) {
+ pg_flags = page->flags;
+ if (pg_flags & (1UL << PG_dcache_dirty)) {
int cpu = ((pg_flags >> PG_dcache_cpu_shift) &
PG_dcache_cpu_mask);
int this_cpu = get_cpu();
@@ -290,6 +286,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t p
put_cpu();
}
}
+}
+
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
+{
+ struct mm_struct *mm;
+ struct tsb *tsb;
+ unsigned long tag, flags;
+ unsigned long tsb_index, tsb_hash_shift;
+
+ if (tlb_type != hypervisor) {
+ unsigned long pfn = pte_pfn(pte);
+
+ if (pfn_valid(pfn))
+ flush_dcache(pfn);
+ }
mm = vma->vm_mm;
@@ -359,6 +370,7 @@ void flush_dcache_page(struct page *page)
out:
put_cpu();
}
+EXPORT_SYMBOL(flush_dcache_page);
void __kprobes flush_icache_range(unsigned long start, unsigned long end)
{
@@ -386,6 +398,7 @@ void __kprobes flush_icache_range(unsigned long start, unsigned long end)
}
}
}
+EXPORT_SYMBOL(flush_icache_range);
void mmu_info(struct seq_file *m)
{
@@ -589,6 +602,7 @@ void __flush_dcache_range(unsigned long start, unsigned long end)
"i" (ASI_DCACHE_INVALIDATE));
}
}
+EXPORT_SYMBOL(__flush_dcache_range);
/* get_new_mmu_context() uses "cache + 1". */
DEFINE_SPINLOCK(ctx_alloc_lock);
@@ -769,8 +783,8 @@ static int find_node(unsigned long addr)
return -1;
}
-static unsigned long nid_range(unsigned long start, unsigned long end,
- int *nid)
+static unsigned long long nid_range(unsigned long long start,
+ unsigned long long end, int *nid)
{
*nid = find_node(start);
start += PAGE_SIZE;
@@ -788,8 +802,8 @@ static unsigned long nid_range(unsigned long start, unsigned long end,
return start;
}
#else
-static unsigned long nid_range(unsigned long start, unsigned long end,
- int *nid)
+static unsigned long long nid_range(unsigned long long start,
+ unsigned long long end, int *nid)
{
*nid = 0;
return end;
@@ -1016,8 +1030,8 @@ static int __init grab_mlgroups(struct mdesc_handle *md)
val = mdesc_get_property(md, node, "address-mask", NULL);
m->mask = *val;
- numadbg("MLGROUP[%d]: node[%lx] latency[%lx] "
- "match[%lx] mask[%lx]\n",
+ numadbg("MLGROUP[%d]: node[%llx] latency[%llx] "
+ "match[%llx] mask[%llx]\n",
count - 1, m->node, m->latency, m->match, m->mask);
}
@@ -1056,7 +1070,7 @@ static int __init grab_mblocks(struct mdesc_handle *md)
"address-congruence-offset", NULL);
m->offset = *val;
- numadbg("MBLOCK[%d]: base[%lx] size[%lx] offset[%lx]\n",
+ numadbg("MBLOCK[%d]: base[%llx] size[%llx] offset[%llx]\n",
count - 1, m->base, m->size, m->offset);
}
@@ -1127,7 +1141,7 @@ static int __init numa_attach_mlgroup(struct mdesc_handle *md, u64 grp,
n->mask = candidate->mask;
n->val = candidate->match;
- numadbg("NUMA NODE[%d]: mask[%lx] val[%lx] (latency[%lx])\n",
+ numadbg("NUMA NODE[%d]: mask[%lx] val[%lx] (latency[%llx])\n",
index, n->mask, n->val, candidate->latency);
return 0;
diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c
index d6e170c074fc..d172f86439b1 100644
--- a/arch/sparc/oprofile/init.c
+++ b/arch/sparc/oprofile/init.c
@@ -13,217 +13,57 @@
#include <linux/init.h>
#ifdef CONFIG_SPARC64
-#include <asm/hypervisor.h>
-#include <asm/spitfire.h>
-#include <asm/cpudata.h>
-#include <asm/irq.h>
+#include <linux/notifier.h>
+#include <linux/rcupdate.h>
+#include <linux/kdebug.h>
+#include <asm/nmi.h>
-static int nmi_enabled;
-
-struct pcr_ops {
- u64 (*read)(void);
- void (*write)(u64);
-};
-static const struct pcr_ops *pcr_ops;
-
-static u64 direct_pcr_read(void)
-{
- u64 val;
-
- read_pcr(val);
- return val;
-}
-
-static void direct_pcr_write(u64 val)
-{
- write_pcr(val);
-}
-
-static const struct pcr_ops direct_pcr_ops = {
- .read = direct_pcr_read,
- .write = direct_pcr_write,
-};
-
-static void n2_pcr_write(u64 val)
+static int profile_timer_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
{
- unsigned long ret;
-
- ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
- if (val != HV_EOK)
- write_pcr(val);
-}
-
-static const struct pcr_ops n2_pcr_ops = {
- .read = direct_pcr_read,
- .write = n2_pcr_write,
-};
-
-/* In order to commonize as much of the implementation as
- * possible, we use PICH as our counter. Mostly this is
- * to accomodate Niagara-1 which can only count insn cycles
- * in PICH.
- */
-static u64 picl_value(void)
-{
- u32 delta = local_cpu_data().clock_tick / HZ;
-
- return ((u64)((0 - delta) & 0xffffffff)) << 32;
-}
-
-#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */
-#define PCR_STRACE 0x00000002 /* Trace supervisor events */
-#define PCR_UTRACE 0x00000004 /* Trace user events */
-#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */
-#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */
-#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */
-#define PCR_N2_MASK0 0x00003fc0
-#define PCR_N2_MASK0_SHIFT 6
-#define PCR_N2_SL0 0x0003c000
-#define PCR_N2_SL0_SHIFT 14
-#define PCR_N2_OV0 0x00040000
-#define PCR_N2_MASK1 0x07f80000
-#define PCR_N2_MASK1_SHIFT 19
-#define PCR_N2_SL1 0x78000000
-#define PCR_N2_SL1_SHIFT 27
-#define PCR_N2_OV1 0x80000000
-
-#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE)
-#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \
- PCR_N2_TOE_OV1 | \
- (2 << PCR_N2_SL1_SHIFT) | \
- (0xff << PCR_N2_MASK1_SHIFT))
-
-static u64 pcr_enable = PCR_SUN4U_ENABLE;
-
-static void nmi_handler(struct pt_regs *regs)
-{
- pcr_ops->write(PCR_PIC_PRIV);
-
- if (nmi_enabled) {
- oprofile_add_sample(regs, 0);
-
- write_pic(picl_value());
- pcr_ops->write(pcr_enable);
- }
-}
-
-/* We count "clock cycle" events in the lower 32-bit PIC.
- * Then configure it such that it overflows every HZ, and thus
- * generates a level 15 interrupt at that frequency.
- */
-static void cpu_nmi_start(void *_unused)
-{
- pcr_ops->write(PCR_PIC_PRIV);
- write_pic(picl_value());
-
- pcr_ops->write(pcr_enable);
-}
+ struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
-static void cpu_nmi_stop(void *_unused)
-{
- pcr_ops->write(PCR_PIC_PRIV);
-}
-
-static int nmi_start(void)
-{
- int err = register_perfctr_intr(nmi_handler);
-
- if (!err) {
- nmi_enabled = 1;
- wmb();
- err = on_each_cpu(cpu_nmi_start, NULL, 1);
- if (err) {
- nmi_enabled = 0;
- wmb();
- on_each_cpu(cpu_nmi_stop, NULL, 1);
- release_perfctr_intr(nmi_handler);
- }
+ switch (val) {
+ case DIE_NMI:
+ oprofile_add_sample(args->regs, 0);
+ ret = NOTIFY_STOP;
+ break;
+ default:
+ break;
}
-
- return err;
-}
-
-static void nmi_stop(void)
-{
- nmi_enabled = 0;
- wmb();
-
- on_each_cpu(cpu_nmi_stop, NULL, 1);
- release_perfctr_intr(nmi_handler);
- synchronize_sched();
+ return ret;
}
-static unsigned long perf_hsvc_group;
-static unsigned long perf_hsvc_major;
-static unsigned long perf_hsvc_minor;
+static struct notifier_block profile_timer_exceptions_nb = {
+ .notifier_call = profile_timer_exceptions_notify,
+};
-static int __init register_perf_hsvc(void)
+static int timer_start(void)
{
- if (tlb_type == hypervisor) {
- switch (sun4v_chip_type) {
- case SUN4V_CHIP_NIAGARA1:
- perf_hsvc_group = HV_GRP_NIAG_PERF;
- break;
-
- case SUN4V_CHIP_NIAGARA2:
- perf_hsvc_group = HV_GRP_N2_CPU;
- break;
-
- default:
- return -ENODEV;
- }
-
-
- perf_hsvc_major = 1;
- perf_hsvc_minor = 0;
- if (sun4v_hvapi_register(perf_hsvc_group,
- perf_hsvc_major,
- &perf_hsvc_minor)) {
- printk("perfmon: Could not register N2 hvapi.\n");
- return -ENODEV;
- }
- }
+ if (register_die_notifier(&profile_timer_exceptions_nb))
+ return 1;
+ nmi_adjust_hz(HZ);
return 0;
}
-static void unregister_perf_hsvc(void)
+
+static void timer_stop(void)
{
- if (tlb_type != hypervisor)
- return;
- sun4v_hvapi_unregister(perf_hsvc_group);
+ nmi_adjust_hz(1);
+ unregister_die_notifier(&profile_timer_exceptions_nb);
+ synchronize_sched(); /* Allow already-started NMIs to complete. */
}
-static int oprofile_nmi_init(struct oprofile_operations *ops)
+static int op_nmi_timer_init(struct oprofile_operations *ops)
{
- int err = register_perf_hsvc();
-
- if (err)
- return err;
-
- switch (tlb_type) {
- case hypervisor:
- pcr_ops = &n2_pcr_ops;
- pcr_enable = PCR_N2_ENABLE;
- break;
-
- case cheetah:
- case cheetah_plus:
- pcr_ops = &direct_pcr_ops;
- break;
-
- default:
+ if (!nmi_usable)
return -ENODEV;
- }
- ops->create_files = NULL;
- ops->setup = NULL;
- ops->shutdown = NULL;
- ops->start = nmi_start;
- ops->stop = nmi_stop;
+ ops->start = timer_start;
+ ops->stop = timer_stop;
ops->cpu_type = "timer";
-
- printk(KERN_INFO "oprofile: Using perfctr based NMI timer interrupt.\n");
-
+ printk(KERN_INFO "oprofile: Using perfctr NMI timer interrupt.\n");
return 0;
}
#endif
@@ -233,7 +73,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
int ret = -ENODEV;
#ifdef CONFIG_SPARC64
- ret = oprofile_nmi_init(ops);
+ ret = op_nmi_timer_init(ops);
if (!ret)
return ret;
#endif
@@ -241,10 +81,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
return ret;
}
-
void oprofile_arch_exit(void)
{
-#ifdef CONFIG_SPARC64
- unregister_perf_hsvc();
-#endif
}
diff --git a/arch/sparc/prom/init_32.c b/arch/sparc/prom/init_32.c
index 873217c6d823..6193c33ed4d4 100644
--- a/arch/sparc/prom/init_32.c
+++ b/arch/sparc/prom/init_32.c
@@ -8,16 +8,20 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
struct linux_romvec *romvec;
+EXPORT_SYMBOL(romvec);
+
enum prom_major_version prom_vers;
unsigned int prom_rev, prom_prev;
/* The root node of the prom device tree. */
int prom_root_node;
+EXPORT_SYMBOL(prom_root_node);
/* Pointer to the device tree operations structure. */
struct linux_nodeops *prom_nodeops;
diff --git a/arch/sparc/prom/misc_32.c b/arch/sparc/prom/misc_32.c
index cf6c3f6d36c3..4d61c540bb3d 100644
--- a/arch/sparc/prom/misc_32.c
+++ b/arch/sparc/prom/misc_32.c
@@ -8,6 +8,8 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/module.h>
+
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/auxio.h>
@@ -44,6 +46,7 @@ prom_feval(char *fstring)
restore_current();
spin_unlock_irqrestore(&prom_lock, flags);
}
+EXPORT_SYMBOL(prom_feval);
/* Drop into the prom, with the chance to continue with the 'go'
* prom command.
diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c
index 9b0c0760901e..eedffb4fec2d 100644
--- a/arch/sparc/prom/misc_64.c
+++ b/arch/sparc/prom/misc_64.c
@@ -11,6 +11,8 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
+#include <linux/module.h>
+
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/system.h>
@@ -54,6 +56,7 @@ void prom_feval(const char *fstring)
p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) |
P1275_INOUT(1, 1), fstring);
}
+EXPORT_SYMBOL(prom_feval);
#ifdef CONFIG_SMP
extern void smp_capture(void);
diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c
index 64579a376419..cd5790853ff6 100644
--- a/arch/sparc/prom/ranges.c
+++ b/arch/sparc/prom/ranges.c
@@ -6,6 +6,8 @@
*/
#include <linux/init.h>
+#include <linux/module.h>
+
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/types.h>
@@ -62,6 +64,7 @@ prom_apply_obio_ranges(struct linux_prom_registers *regs, int nregs)
if(num_obio_ranges)
prom_adjust_regs(regs, nregs, promlib_obio_ranges, num_obio_ranges);
}
+EXPORT_SYMBOL(prom_apply_obio_ranges);
void __init prom_ranges_init(void)
{
diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c
index 6d8187357331..646d244b1fdb 100644
--- a/arch/sparc/prom/tree_32.c
+++ b/arch/sparc/prom/tree_32.c
@@ -5,13 +5,12 @@
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
-#define PROMLIB_INTERNAL
-
#include <linux/string.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ctype.h>
+#include <linux/module.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -50,6 +49,7 @@ int prom_getchild(int node)
return cnode;
}
+EXPORT_SYMBOL(prom_getchild);
/* Internal version of prom_getsibling that does not alter return values. */
int __prom_getsibling(int node)
@@ -81,6 +81,7 @@ int prom_getsibling(int node)
return sibnode;
}
+EXPORT_SYMBOL(prom_getsibling);
/* Return the length in bytes of property 'prop' at node 'node'.
* Return -1 on error.
@@ -99,6 +100,7 @@ int prom_getproplen(int node, const char *prop)
spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
+EXPORT_SYMBOL(prom_getproplen);
/* Acquire a property 'prop' at node 'node' and place it in
* 'buffer' which has a size of 'bufsize'. If the acquisition
@@ -119,6 +121,7 @@ int prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
+EXPORT_SYMBOL(prom_getproperty);
/* Acquire an integer property and return its value. Returns -1
* on failure.
@@ -132,6 +135,7 @@ int prom_getint(int node, char *prop)
return -1;
}
+EXPORT_SYMBOL(prom_getint);
/* Acquire an integer property, upon error return the passed default
* integer.
@@ -145,6 +149,7 @@ int prom_getintdefault(int node, char *property, int deflt)
return retval;
}
+EXPORT_SYMBOL(prom_getintdefault);
/* Acquire a boolean property, 1=TRUE 0=FALSE. */
int prom_getbool(int node, char *prop)
@@ -155,6 +160,7 @@ int prom_getbool(int node, char *prop)
if(retval == -1) return 0;
return 1;
}
+EXPORT_SYMBOL(prom_getbool);
/* Acquire a property whose value is a string, returns a null
* string on error. The char pointer is the user supplied string
@@ -169,6 +175,7 @@ void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
user_buf[0] = 0;
return;
}
+EXPORT_SYMBOL(prom_getstring);
/* Does the device at node 'node' have name 'name'?
@@ -204,6 +211,7 @@ int prom_searchsiblings(int node_start, char *nodename)
return 0;
}
+EXPORT_SYMBOL(prom_searchsiblings);
/* Interal version of nextprop that does not alter return values. */
char * __prom_nextprop(int node, char * oprop)
@@ -228,6 +236,7 @@ char * prom_firstprop(int node, char *bufer)
return __prom_nextprop(node, "");
}
+EXPORT_SYMBOL(prom_firstprop);
/* Return the property type string after property type 'oprop'
* at node 'node' . Returns empty string if no more
@@ -240,6 +249,7 @@ char * prom_nextprop(int node, char *oprop, char *buffer)
return __prom_nextprop(node, oprop);
}
+EXPORT_SYMBOL(prom_nextprop);
int prom_finddevice(char *name)
{
@@ -287,6 +297,7 @@ int prom_finddevice(char *name)
}
return node;
}
+EXPORT_SYMBOL(prom_finddevice);
int prom_node_has_property(int node, char *prop)
{
@@ -299,6 +310,7 @@ int prom_node_has_property(int node, char *prop)
} while (*current_property);
return 0;
}
+EXPORT_SYMBOL(prom_node_has_property);
/* Set property 'pname' at node 'node' to value 'value' which has a length
* of 'size' bytes. Return the number of bytes the prom accepted.
@@ -316,6 +328,7 @@ int prom_setprop(int node, const char *pname, char *value, int size)
spin_unlock_irqrestore(&prom_lock, flags);
return ret;
}
+EXPORT_SYMBOL(prom_setprop);
int prom_inst2pkg(int inst)
{
diff --git a/arch/sparc/prom/tree_64.c b/arch/sparc/prom/tree_64.c
index 281aea44790b..8ea73ddc61dc 100644
--- a/arch/sparc/prom/tree_64.c
+++ b/arch/sparc/prom/tree_64.c
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/module.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -32,6 +33,7 @@ inline int prom_getchild(int node)
if(cnode == -1) return 0;
return (int)cnode;
}
+EXPORT_SYMBOL(prom_getchild);
inline int prom_getparent(int node)
{
@@ -63,6 +65,7 @@ inline int prom_getsibling(int node)
return sibnode;
}
+EXPORT_SYMBOL(prom_getsibling);
/* Return the length in bytes of property 'prop' at node 'node'.
* Return -1 on error.
@@ -75,6 +78,7 @@ inline int prom_getproplen(int node, const char *prop)
P1275_INOUT(2, 1),
node, prop);
}
+EXPORT_SYMBOL(prom_getproplen);
/* Acquire a property 'prop' at node 'node' and place it in
* 'buffer' which has a size of 'bufsize'. If the acquisition
@@ -97,6 +101,7 @@ inline int prom_getproperty(int node, const char *prop,
node, prop, buffer, P1275_SIZE(plen));
}
}
+EXPORT_SYMBOL(prom_getproperty);
/* Acquire an integer property and return its value. Returns -1
* on failure.
@@ -110,6 +115,7 @@ inline int prom_getint(int node, const char *prop)
return -1;
}
+EXPORT_SYMBOL(prom_getint);
/* Acquire an integer property, upon error return the passed default
* integer.
@@ -124,6 +130,7 @@ int prom_getintdefault(int node, const char *property, int deflt)
return retval;
}
+EXPORT_SYMBOL(prom_getintdefault);
/* Acquire a boolean property, 1=TRUE 0=FALSE. */
int prom_getbool(int node, const char *prop)
@@ -134,6 +141,7 @@ int prom_getbool(int node, const char *prop)
if(retval == -1) return 0;
return 1;
}
+EXPORT_SYMBOL(prom_getbool);
/* Acquire a property whose value is a string, returns a null
* string on error. The char pointer is the user supplied string
@@ -148,7 +156,7 @@ void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
user_buf[0] = 0;
return;
}
-
+EXPORT_SYMBOL(prom_getstring);
/* Does the device at node 'node' have name 'name'?
* YES = 1 NO = 0
@@ -181,6 +189,7 @@ int prom_searchsiblings(int node_start, const char *nodename)
return 0;
}
+EXPORT_SYMBOL(prom_searchsiblings);
/* Return the first property type for node 'node'.
* buffer should be at least 32B in length
@@ -194,6 +203,7 @@ inline char *prom_firstprop(int node, char *buffer)
node, (char *) 0x0, buffer);
return buffer;
}
+EXPORT_SYMBOL(prom_firstprop);
/* Return the property type string after property type 'oprop'
* at node 'node' . Returns NULL string if no more
@@ -217,6 +227,7 @@ inline char *prom_nextprop(int node, const char *oprop, char *buffer)
node, oprop, buffer);
return buffer;
}
+EXPORT_SYMBOL(prom_nextprop);
int
prom_finddevice(const char *name)
@@ -228,6 +239,7 @@ prom_finddevice(const char *name)
P1275_INOUT(1, 1),
name);
}
+EXPORT_SYMBOL(prom_finddevice);
int prom_node_has_property(int node, const char *prop)
{
@@ -241,7 +253,8 @@ int prom_node_has_property(int node, const char *prop)
} while (*buf);
return 0;
}
-
+EXPORT_SYMBOL(prom_node_has_property);
+
/* Set property 'pname' at node 'node' to value 'value' which has a length
* of 'size' bytes. Return the number of bytes the prom accepted.
*/
@@ -264,6 +277,7 @@ prom_setprop(int node, const char *pname, char *value, int size)
P1275_INOUT(4, 1),
node, pname, value, P1275_SIZE(size));
}
+EXPORT_SYMBOL(prom_setprop);
inline int prom_inst2pkg(int inst)
{
diff --git a/arch/um/Makefile b/arch/um/Makefile
index d944c343acdb..0728def32234 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -22,10 +22,11 @@ MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/shared/skas
include $(srctree)/$(ARCH_DIR)/Makefile-skas
-ARCH_INCLUDE := -I$(srctree)/$(ARCH_DIR)/include/shared
+SHARED_HEADERS := $(ARCH_DIR)/include/shared
+ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS)
ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared
ifneq ($(KBUILD_SRC),)
-ARCH_INCLUDE += -I$(ARCH_DIR)/include/shared # for two generated files
+ARCH_INCLUDE += -I$(SHARED_HEADERS)
endif
KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)
@@ -85,8 +86,8 @@ endef
KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH)
-archprepare: $(ARCH_DIR)/include/shared/user_constants.h
-prepare: $(ARCH_DIR)/include/shared/kern_constants.h
+archprepare: $(SHARED_HEADERS)/user_constants.h
+archprepare: $(SHARED_HEADERS)/kern_constants.h
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
@@ -119,17 +120,13 @@ endef
# When cleaning we don't include .config, so we don't include
# TT or skas makefiles and don't clean skas_ptregs.h.
CLEAN_FILES += linux x.i gmon.out \
- $(ARCH_DIR)/include/shared/user_constants.h \
- $(ARCH_DIR)/include/shared/kern_constants.h
+ $(SHARED_HEADERS)/user_constants.h \
+ $(SHARED_HEADERS)/kern_constants.h
archclean:
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-o -name '*.gcov' \) -type f -print | xargs rm -f
-$(objtree)/$(ARCH_DIR)/include/shared:
- @echo ' MKDIR $@'
- $(Q)mkdir -p $@
-
# Generated files
$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
@@ -148,11 +145,11 @@ define filechk_gen-asm-offsets
echo ""; )
endef
-$(ARCH_DIR)/include/shared/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
+$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
$(call filechk,gen-asm-offsets)
-$(ARCH_DIR)/include/shared/kern_constants.h: $(objtree)/$(ARCH_DIR)/include/shared
- @echo ' SYMLINK $@'
- $(Q)ln -sf ../../../../include/asm/asm-offsets.h $@
+$(SHARED_HEADERS)/kern_constants.h:
+ $(Q)mkdir -p $(dir $@)
+ $(Q)echo '#include "../../../../include/asm/asm-offsets.h"' >$@
export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH
diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h
index ae5f94d6317d..753346e2cdfd 100644
--- a/arch/um/include/asm/system.h
+++ b/arch/um/include/asm/system.h
@@ -11,21 +11,21 @@ extern int get_signals(void);
extern void block_signals(void);
extern void unblock_signals(void);
-#define raw_local_save_flags(flags) do { typecheck(unsigned long, flags); \
+#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
(flags) = get_signals(); } while(0)
-#define raw_local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
set_signals(flags); } while(0)
-#define raw_local_irq_save(flags) do { raw_local_save_flags(flags); \
- raw_local_irq_disable(); } while(0)
+#define local_irq_save(flags) do { local_save_flags(flags); \
+ local_irq_disable(); } while(0)
-#define raw_local_irq_enable() unblock_signals()
-#define raw_local_irq_disable() block_signals()
+#define local_irq_enable() unblock_signals()
+#define local_irq_disable() block_signals()
#define irqs_disabled() \
({ \
unsigned long flags; \
- raw_local_save_flags(flags); \
+ local_save_flags(flags); \
(flags == 0); \
})
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index 910eda8fca18..806d381947bf 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -10,7 +10,6 @@
#include "linux/mqueue.h"
#include "asm/uaccess.h"
-static struct fs_struct init_fs = INIT_FS;
struct mm_struct init_mm = INIT_MM(init_mm);
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 045772142844..98351c78bc81 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -25,13 +25,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
#include "irq_user.h"
#include "os.h"
-/* CPU online map, set by smp_boot_cpus */
-cpumask_t cpu_online_map = CPU_MASK_NONE;
-cpumask_t cpu_possible_map = CPU_MASK_NONE;
-
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_possible_map);
-
/* Per CPU bogomips and other parameters
* The only piece used here is the ipi pipe, which is set before SMP is
* started and never changed.
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 47f04f4a3464..b13a87a3ec95 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -50,7 +50,7 @@ static int itimer_next_event(unsigned long delta,
static struct clock_event_device itimer_clockevent = {
.name = "itimer",
.rating = 250,
- .cpumask = CPU_MASK_ALL,
+ .cpumask = cpu_all_mask,
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_mode = itimer_set_mode,
.set_next_event = itimer_next_event,
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 44e490419495..7384d8accfe7 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -64,11 +64,10 @@ good_area:
do {
int fault;
-survive:
+
fault = handle_mm_fault(mm, vma, address, is_write);
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM) {
- err = -ENOMEM;
goto out_of_memory;
} else if (fault & VM_FAULT_SIGBUS) {
err = -EACCES;
@@ -104,18 +103,14 @@ out:
out_nosemaphore:
return err;
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
out_of_memory:
- if (is_global_init(current)) {
- up_read(&mm->mmap_sem);
- yield();
- down_read(&mm->mmap_sem);
- goto survive;
- }
- goto out;
+ /*
+ * We ran out of memory, call the OOM killer, and return the userspace
+ * (which will retry the fault, or kill us if we got oom-killed).
+ */
+ up_read(&mm->mmap_sem);
+ pagefault_out_of_memory();
+ return 0;
}
static void bad_segv(struct faultinfo fi, unsigned long ip)
@@ -214,9 +209,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
si.si_addr = (void __user *)address;
current->thread.arch.faultinfo = fi;
force_sig_info(SIGBUS, &si, current);
- } else if (err == -ENOMEM) {
- printk(KERN_INFO "VM: killing process %s\n", current->comm);
- do_exit(SIGKILL);
} else {
BUG_ON(err != -EFAULT);
si.si_signo = SIGSEGV;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0f44add3e0b7..73f7fe8fd4d1 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -27,6 +27,7 @@ config X86
select HAVE_IOREMAP_PROT
select HAVE_KPROBES
select ARCH_WANT_OPTIONAL_GPIOLIB
+ select ARCH_WANT_FRAME_POINTERS
select HAVE_KRETPROBES
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_DYNAMIC_FTRACE
@@ -586,6 +587,16 @@ config AMD_IOMMU
your BIOS for an option to enable it or if you have an IVRS ACPI
table.
+config AMD_IOMMU_STATS
+ bool "Export AMD IOMMU statistics to debugfs"
+ depends on AMD_IOMMU
+ select DEBUG_FS
+ help
+ This option enables code in the AMD IOMMU driver to collect various
+ statistics about whats happening in the driver and exports that
+ information to userspace via debugfs.
+ If unsure, say N.
+
# need this always selected by IOMMU for the VIA workaround
config SWIOTLB
def_bool y if X86_64
@@ -599,21 +610,25 @@ config SWIOTLB
config IOMMU_HELPER
def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU)
+config IOMMU_API
+ def_bool (AMD_IOMMU || DMAR)
+
config MAXSMP
bool "Configure Maximum number of SMP Processors and NUMA Nodes"
- depends on X86_64 && SMP && BROKEN
+ depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL
+ select CPUMASK_OFFSTACK
default n
help
Configure maximum number of CPUS and NUMA Nodes for this architecture.
If unsure, say N.
config NR_CPUS
- int "Maximum number of CPUs (2-512)" if !MAXSMP
- range 2 512
- depends on SMP
+ int "Maximum number of CPUs" if SMP && !MAXSMP
+ range 2 512 if SMP && !MAXSMP
+ default "1" if !SMP
default "4096" if MAXSMP
- default "32" if X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000
- default "8"
+ default "32" if SMP && (X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000)
+ default "8" if SMP
help
This allows you to specify the maximum number of CPUs which this
kernel will support. The maximum supported value is 512 and the
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 85a78575956c..8078955845ae 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -408,7 +408,7 @@ config X86_MINIMUM_CPU_FAMILY
config X86_DEBUGCTLMSR
def_bool y
- depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386)
+ depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) && !UML
menuconfig PROCESSOR_SELECT
bool "Supported processor vendors" if EMBEDDED
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
index 75115849af33..4a58c8ce3f69 100644
--- a/arch/x86/boot/video-vesa.c
+++ b/arch/x86/boot/video-vesa.c
@@ -269,9 +269,8 @@ void vesa_store_edid(void)
we genuinely have to assume all registers are destroyed here. */
asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
- : "+a" (ax), "+b" (bx)
- : "c" (cx), "D" (di)
- : "esi");
+ : "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di)
+ : : "esi", "edx");
if (ax != 0x004f)
return; /* No EDID */
@@ -285,9 +284,9 @@ void vesa_store_edid(void)
dx = 0; /* EDID block number */
di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */
asm(INT10
- : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info)
- : "c" (cx), "D" (di)
- : "esi");
+ : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info),
+ "+c" (cx), "+D" (di)
+ : : "esi");
#endif /* CONFIG_FIRMWARE_EDID */
}
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index b30a08ed8eb4..edba00d98ac3 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -1331,8 +1331,8 @@ CONFIG_I2C_I801=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 0e7dbc0a3e46..322dd2748fc9 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -1311,8 +1311,8 @@ CONFIG_I2C_I801=y
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index b195f85526e3..9dabd00e9805 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -24,15 +24,14 @@
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include <asm/i387.h>
-#include <asm/ia32.h>
#include <asm/ptrace.h>
#include <asm/ia32_unistd.h>
#include <asm/user32.h>
#include <asm/sigcontext32.h>
#include <asm/proto.h>
#include <asm/vdso.h>
-
#include <asm/sigframe.h>
+#include <asm/sys_ia32.h>
#define DEBUG_SIG 0
diff --git a/arch/x86/ia32/ipc32.c b/arch/x86/ia32/ipc32.c
index d21991ce606c..29cdcd02ead3 100644
--- a/arch/x86/ia32/ipc32.c
+++ b/arch/x86/ia32/ipc32.c
@@ -8,6 +8,7 @@
#include <linux/shm.h>
#include <linux/ipc.h>
#include <linux/compat.h>
+#include <asm/sys_ia32.h>
asmlinkage long sys32_ipc(u32 call, int first, int second, int third,
compat_uptr_t ptr, u32 fifth)
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 2e09dcd3c0a6..6c0d7f6231af 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -44,8 +44,8 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
-#include <asm/ia32.h>
#include <asm/vgtod.h>
+#include <asm/sys_ia32.h>
#define AA(__x) ((unsigned long)(__x))
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h
index ac302a2fa339..95c8cd9d22b5 100644
--- a/arch/x86/include/asm/amd_iommu_types.h
+++ b/arch/x86/include/asm/amd_iommu_types.h
@@ -190,16 +190,23 @@
/* FIXME: move this macro to <linux/pci.h> */
#define PCI_BUS(x) (((x) >> 8) & 0xff)
+/* Protection domain flags */
+#define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */
+#define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops
+ domain for an IOMMU */
+
/*
* This structure contains generic data for IOMMU protection domains
* independent of their use.
*/
struct protection_domain {
- spinlock_t lock; /* mostly used to lock the page table*/
- u16 id; /* the domain id written to the device table */
- int mode; /* paging mode (0-6 levels) */
- u64 *pt_root; /* page table root pointer */
- void *priv; /* private data */
+ spinlock_t lock; /* mostly used to lock the page table*/
+ u16 id; /* the domain id written to the device table */
+ int mode; /* paging mode (0-6 levels) */
+ u64 *pt_root; /* page table root pointer */
+ unsigned long flags; /* flags to find out type of domain */
+ unsigned dev_cnt; /* devices assigned to this domain */
+ void *priv; /* private data */
};
/*
@@ -295,7 +302,7 @@ struct amd_iommu {
bool int_enabled;
/* if one, we need to send a completion wait command */
- int need_sync;
+ bool need_sync;
/* default dma_ops domain for that IOMMU */
struct dma_ops_domain *default_dom;
@@ -374,7 +381,7 @@ extern struct protection_domain **amd_iommu_pd_table;
extern unsigned long *amd_iommu_pd_alloc_bitmap;
/* will be 1 if device isolation is enabled */
-extern int amd_iommu_isolate;
+extern bool amd_iommu_isolate;
/*
* If true, the addresses will be flushed on unmap time, not when
@@ -382,18 +389,6 @@ extern int amd_iommu_isolate;
*/
extern bool amd_iommu_unmap_flush;
-/* takes a PCI device id and prints it out in a readable form */
-static inline void print_devid(u16 devid, int nl)
-{
- int bus = devid >> 8;
- int dev = devid >> 3 & 0x1f;
- int fn = devid & 0x07;
-
- printk("%02x:%02x.%x", bus, dev, fn);
- if (nl)
- printk("\n");
-}
-
/* takes bus and device/function and returns the device id
* FIXME: should that be in generic PCI code? */
static inline u16 calc_devid(u8 bus, u8 devfn)
@@ -401,4 +396,32 @@ static inline u16 calc_devid(u8 bus, u8 devfn)
return (((u16)bus) << 8) | devfn;
}
+#ifdef CONFIG_AMD_IOMMU_STATS
+
+struct __iommu_counter {
+ char *name;
+ struct dentry *dent;
+ u64 value;
+};
+
+#define DECLARE_STATS_COUNTER(nm) \
+ static struct __iommu_counter nm = { \
+ .name = #nm, \
+ }
+
+#define INC_STATS_COUNTER(name) name.value += 1
+#define ADD_STATS_COUNTER(name, x) name.value += (x)
+#define SUB_STATS_COUNTER(name, x) name.value -= (x)
+
+#else /* CONFIG_AMD_IOMMU_STATS */
+
+#define DECLARE_STATS_COUNTER(name)
+#define INC_STATS_COUNTER(name)
+#define ADD_STATS_COUNTER(name, x)
+#define SUB_STATS_COUNTER(name, x)
+
+static inline void amd_iommu_stats_init(void) { }
+
+#endif /* CONFIG_AMD_IOMMU_STATS */
+
#endif /* _ASM_X86_AMD_IOMMU_TYPES_H */
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 25caa0738af5..ab1d51a8855e 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -54,7 +54,6 @@ extern int disable_apic;
extern int is_vsmp_box(void);
extern void xapic_wait_icr_idle(void);
extern u32 safe_xapic_wait_icr_idle(void);
-extern u64 xapic_icr_read(void);
extern void xapic_icr_write(u32, u32);
extern int setup_profiling_timer(unsigned int);
@@ -93,7 +92,7 @@ static inline u32 native_apic_msr_read(u32 reg)
}
#ifndef CONFIG_X86_32
-extern int x2apic, x2apic_preenabled;
+extern int x2apic;
extern void check_x2apic(void);
extern void enable_x2apic(void);
extern void enable_IR_x2apic(void);
diff --git a/arch/x86/include/asm/atomic_32.h b/arch/x86/include/asm/atomic_32.h
index ad5b9f6ecddf..85b46fba4229 100644
--- a/arch/x86/include/asm/atomic_32.h
+++ b/arch/x86/include/asm/atomic_32.h
@@ -2,6 +2,7 @@
#define _ASM_X86_ATOMIC_32_H
#include <linux/compiler.h>
+#include <linux/types.h>
#include <asm/processor.h>
#include <asm/cmpxchg.h>
@@ -10,15 +11,6 @@
* resource counting etc..
*/
-/*
- * Make sure gcc doesn't try to be clever and move things around
- * on us. We need to use _exactly_ the address the user gave us,
- * not some alias that contains the same information.
- */
-typedef struct {
- int counter;
-} atomic_t;
-
#define ATOMIC_INIT(i) { (i) }
/**
diff --git a/arch/x86/include/asm/atomic_64.h b/arch/x86/include/asm/atomic_64.h
index 279d2a731f3f..8c21731984da 100644
--- a/arch/x86/include/asm/atomic_64.h
+++ b/arch/x86/include/asm/atomic_64.h
@@ -1,25 +1,15 @@
#ifndef _ASM_X86_ATOMIC_64_H
#define _ASM_X86_ATOMIC_64_H
+#include <linux/types.h>
#include <asm/alternative.h>
#include <asm/cmpxchg.h>
-/* atomic_t should be 32 bit signed type */
-
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
*/
-/*
- * Make sure gcc doesn't try to be clever and move things around
- * on us. We need to use _exactly_ the address the user gave us,
- * not some alias that contains the same information.
- */
-typedef struct {
- int counter;
-} atomic_t;
-
#define ATOMIC_INIT(i) { (i) }
/**
@@ -191,11 +181,7 @@ static inline int atomic_sub_return(int i, atomic_t *v)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
-/* An 64bit atomic type */
-
-typedef struct {
- long counter;
-} atomic64_t;
+/* The 64-bit atomic type */
#define ATOMIC64_INIT(i) { (i) }
diff --git a/arch/x86/include/asm/bigsmp/apic.h b/arch/x86/include/asm/bigsmp/apic.h
index ce547f24a1cd..d8dd9f537911 100644
--- a/arch/x86/include/asm/bigsmp/apic.h
+++ b/arch/x86/include/asm/bigsmp/apic.h
@@ -9,12 +9,12 @@ static inline int apic_id_registered(void)
return (1);
}
-static inline cpumask_t target_cpus(void)
+static inline const cpumask_t *target_cpus(void)
{
#ifdef CONFIG_SMP
- return cpu_online_map;
+ return &cpu_online_map;
#else
- return cpumask_of_cpu(0);
+ return &cpumask_of_cpu(0);
#endif
}
@@ -79,7 +79,7 @@ static inline int apicid_to_node(int logical_apicid)
static inline int cpu_present_to_apicid(int mps_cpu)
{
- if (mps_cpu < NR_CPUS)
+ if (mps_cpu < nr_cpu_ids)
return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
return BAD_APICID;
@@ -94,7 +94,7 @@ extern u8 cpu_2_logical_apicid[];
/* Mapping from cpu number to logical apicid */
static inline int cpu_to_logical_apicid(int cpu)
{
- if (cpu >= NR_CPUS)
+ if (cpu >= nr_cpu_ids)
return BAD_APICID;
return cpu_physical_id(cpu);
}
@@ -119,16 +119,34 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
}
/* As we are using single CPU as destination, pick only one CPU here */
-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
{
int cpu;
int apicid;
- cpu = first_cpu(cpumask);
+ cpu = first_cpu(*cpumask);
apicid = cpu_to_logical_apicid(cpu);
return apicid;
}
+static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
+{
+ int cpu;
+
+ /*
+ * We're using fixed IRQ delivery, can only return one phys APIC ID.
+ * May as well be the first.
+ */
+ for_each_cpu_and(cpu, cpumask, andmask)
+ if (cpumask_test_cpu(cpu, cpu_online_mask))
+ break;
+ if (cpu < nr_cpu_ids)
+ return cpu_to_logical_apicid(cpu);
+
+ return BAD_APICID;
+}
+
static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
{
return cpuid_apic >> index_msb;
diff --git a/arch/x86/include/asm/bigsmp/ipi.h b/arch/x86/include/asm/bigsmp/ipi.h
index 9404c535b7ec..27fcd01b3ae6 100644
--- a/arch/x86/include/asm/bigsmp/ipi.h
+++ b/arch/x86/include/asm/bigsmp/ipi.h
@@ -1,25 +1,22 @@
#ifndef __ASM_MACH_IPI_H
#define __ASM_MACH_IPI_H
-void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(const struct cpumask *mask, int vector);
+void send_IPI_mask_allbutself(const struct cpumask *mask, int vector);
-static inline void send_IPI_mask(cpumask_t mask, int vector)
+static inline void send_IPI_mask(const struct cpumask *mask, int vector)
{
send_IPI_mask_sequence(mask, vector);
}
static inline void send_IPI_allbutself(int vector)
{
- cpumask_t mask = cpu_online_map;
- cpu_clear(smp_processor_id(), mask);
-
- if (!cpus_empty(mask))
- send_IPI_mask(mask, vector);
+ send_IPI_mask_allbutself(cpu_online_mask, vector);
}
static inline void send_IPI_all(int vector)
{
- send_IPI_mask(cpu_online_map, vector);
+ send_IPI_mask(cpu_online_mask, vector);
}
#endif /* __ASM_MACH_IPI_H */
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 9fa9dcdf344b..02b47a603fc8 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -3,6 +3,9 @@
/*
* Copyright 1992, Linus Torvalds.
+ *
+ * Note: inlines with more than a single statement should be marked
+ * __always_inline to avoid problems with older gcc's inlining heuristics.
*/
#ifndef _LINUX_BITOPS_H
@@ -53,7 +56,8 @@
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
*/
-static inline void set_bit(unsigned int nr, volatile unsigned long *addr)
+static __always_inline void
+set_bit(unsigned int nr, volatile unsigned long *addr)
{
if (IS_IMMEDIATE(nr)) {
asm volatile(LOCK_PREFIX "orb %1,%0"
@@ -90,7 +94,8 @@ static inline void __set_bit(int nr, volatile unsigned long *addr)
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
* in order to ensure changes are visible on other processors.
*/
-static inline void clear_bit(int nr, volatile unsigned long *addr)
+static __always_inline void
+clear_bit(int nr, volatile unsigned long *addr)
{
if (IS_IMMEDIATE(nr)) {
asm volatile(LOCK_PREFIX "andb %1,%0"
@@ -204,7 +209,8 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
*
* This is the same as test_and_set_bit on x86.
*/
-static inline int test_and_set_bit_lock(int nr, volatile unsigned long *addr)
+static __always_inline int
+test_and_set_bit_lock(int nr, volatile unsigned long *addr)
{
return test_and_set_bit(nr, addr);
}
@@ -300,7 +306,7 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
return oldbit;
}
-static inline int constant_test_bit(int nr, const volatile unsigned long *addr)
+static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr)
{
return ((1UL << (nr % BITS_PER_LONG)) &
(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
diff --git a/arch/x86/include/asm/byteorder.h b/arch/x86/include/asm/byteorder.h
index f110ad417df3..b13a7a88f3eb 100644
--- a/arch/x86/include/asm/byteorder.h
+++ b/arch/x86/include/asm/byteorder.h
@@ -1,65 +1,6 @@
#ifndef _ASM_X86_BYTEORDER_H
#define _ASM_X86_BYTEORDER_H
-#include <asm/types.h>
-#include <linux/compiler.h>
-
-#define __LITTLE_ENDIAN
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-#ifdef __i386__
-# ifdef CONFIG_X86_BSWAP
- asm("bswap %0" : "=r" (val) : "0" (val));
-# else
- asm("xchgb %b0,%h0\n\t" /* swap lower bytes */
- "rorl $16,%0\n\t" /* swap words */
- "xchgb %b0,%h0" /* swap higher bytes */
- : "=q" (val)
- : "0" (val));
-# endif
-
-#else /* __i386__ */
- asm("bswapl %0"
- : "=r" (val)
- : "0" (val));
-#endif
- return val;
-}
-#define __arch_swab32 __arch_swab32
-
-static inline __attribute_const__ __u64 __arch_swab64(__u64 val)
-{
-#ifdef __i386__
- union {
- struct {
- __u32 a;
- __u32 b;
- } s;
- __u64 u;
- } v;
- v.u = val;
-# ifdef CONFIG_X86_BSWAP
- asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
- : "=r" (v.s.a), "=r" (v.s.b)
- : "0" (v.s.a), "1" (v.s.b));
-# else
- v.s.a = __arch_swab32(v.s.a);
- v.s.b = __arch_swab32(v.s.b);
- asm("xchgl %0,%1"
- : "=r" (v.s.a), "=r" (v.s.b)
- : "0" (v.s.a), "1" (v.s.b));
-# endif
- return v.u;
-#else /* __i386__ */
- asm("bswapq %0"
- : "=r" (val)
- : "0" (val));
- return val;
-#endif
-}
-#define __arch_swab64 __arch_swab64
-
-#include <linux/byteorder.h>
+#include <linux/byteorder/little_endian.h>
#endif /* _ASM_X86_BYTEORDER_H */
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index e6b82b17b072..dc27705f5443 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -320,16 +320,14 @@ static inline void set_intr_gate(unsigned int n, void *addr)
_set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
}
-#define SYS_VECTOR_FREE 0
-#define SYS_VECTOR_ALLOCED 1
-
extern int first_system_vector;
-extern char system_vectors[];
+/* used_vectors is BITMAP for irq is not managed by percpu vector_irq */
+extern unsigned long used_vectors[];
static inline void alloc_system_vector(int vector)
{
- if (system_vectors[vector] == SYS_VECTOR_FREE) {
- system_vectors[vector] = SYS_VECTOR_ALLOCED;
+ if (!test_bit(vector, used_vectors)) {
+ set_bit(vector, used_vectors);
if (first_system_vector > vector)
first_system_vector = vector;
} else
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 4035357f5b9d..132a134d12f2 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -2,8 +2,8 @@
#define _ASM_X86_DMA_MAPPING_H
/*
- * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
- * documentation.
+ * IOMMU interface. See Documentation/PCI/PCI-DMA-mapping.txt and
+ * Documentation/DMA-API.txt for documentation.
*/
#include <linux/scatterlist.h>
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 3d8ceddbd407..00d41ce4c844 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -49,6 +49,7 @@
#define E820_RESERVED_KERN 128
#ifndef __ASSEMBLY__
+#include <linux/types.h>
struct e820entry {
__u64 addr; /* start of memory segment */
__u64 size; /* size of memory segment */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index a2e545c91c35..ca5ffb2856b6 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -90,6 +90,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size);
#endif /* CONFIG_X86_32 */
+extern int add_efi_memmap;
extern void efi_reserve_early(void);
extern void efi_call_phys_prelog(void);
extern void efi_call_phys_epilog(void);
diff --git a/arch/x86/include/asm/es7000/apic.h b/arch/x86/include/asm/es7000/apic.h
index e24ef876915f..c58b9cc74465 100644
--- a/arch/x86/include/asm/es7000/apic.h
+++ b/arch/x86/include/asm/es7000/apic.h
@@ -1,6 +1,8 @@
#ifndef __ASM_ES7000_APIC_H
#define __ASM_ES7000_APIC_H
+#include <linux/gfp.h>
+
#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu)
#define esr_disable (1)
@@ -9,14 +11,14 @@ static inline int apic_id_registered(void)
return (1);
}
-static inline cpumask_t target_cpus_cluster(void)
+static inline const cpumask_t *target_cpus_cluster(void)
{
- return CPU_MASK_ALL;
+ return &CPU_MASK_ALL;
}
-static inline cpumask_t target_cpus(void)
+static inline const cpumask_t *target_cpus(void)
{
- return cpumask_of_cpu(smp_processor_id());
+ return &cpumask_of_cpu(smp_processor_id());
}
#define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER)
@@ -80,9 +82,10 @@ extern int apic_version [MAX_APICS];
static inline void setup_apic_routing(void)
{
int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
- printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
+ printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
(apic_version[apic] == 0x14) ?
- "Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(target_cpus())[0]);
+ "Physical Cluster" : "Logical Cluster",
+ nr_ioapics, cpus_addr(*target_cpus())[0]);
}
static inline int multi_timer_check(int apic, int irq)
@@ -100,7 +103,7 @@ static inline int cpu_present_to_apicid(int mps_cpu)
{
if (!mps_cpu)
return boot_cpu_physical_apicid;
- else if (mps_cpu < NR_CPUS)
+ else if (mps_cpu < nr_cpu_ids)
return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
else
return BAD_APICID;
@@ -120,9 +123,9 @@ extern u8 cpu_2_logical_apicid[];
static inline int cpu_to_logical_apicid(int cpu)
{
#ifdef CONFIG_SMP
- if (cpu >= NR_CPUS)
- return BAD_APICID;
- return (int)cpu_2_logical_apicid[cpu];
+ if (cpu >= nr_cpu_ids)
+ return BAD_APICID;
+ return (int)cpu_2_logical_apicid[cpu];
#else
return logical_smp_processor_id();
#endif
@@ -146,25 +149,26 @@ static inline int check_phys_apicid_present(int cpu_physical_apicid)
return (1);
}
-static inline unsigned int cpu_mask_to_apicid_cluster(cpumask_t cpumask)
+static inline unsigned int
+cpu_mask_to_apicid_cluster(const struct cpumask *cpumask)
{
int num_bits_set;
int cpus_found = 0;
int cpu;
int apicid;
- num_bits_set = cpus_weight(cpumask);
+ num_bits_set = cpumask_weight(cpumask);
/* Return id to all */
- if (num_bits_set == NR_CPUS)
+ if (num_bits_set == nr_cpu_ids)
return 0xFF;
/*
* The cpus in the mask must all be on the apic cluster. If are not
* on the same apicid cluster return default value of TARGET_CPUS.
*/
- cpu = first_cpu(cpumask);
+ cpu = cpumask_first(cpumask);
apicid = cpu_to_logical_apicid(cpu);
while (cpus_found < num_bits_set) {
- if (cpu_isset(cpu, cpumask)) {
+ if (cpumask_test_cpu(cpu, cpumask)) {
int new_apicid = cpu_to_logical_apicid(cpu);
if (apicid_cluster(apicid) !=
apicid_cluster(new_apicid)){
@@ -179,25 +183,25 @@ static inline unsigned int cpu_mask_to_apicid_cluster(cpumask_t cpumask)
return apicid;
}
-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
{
int num_bits_set;
int cpus_found = 0;
int cpu;
int apicid;
- num_bits_set = cpus_weight(cpumask);
+ num_bits_set = cpus_weight(*cpumask);
/* Return id to all */
- if (num_bits_set == NR_CPUS)
+ if (num_bits_set == nr_cpu_ids)
return cpu_to_logical_apicid(0);
/*
* The cpus in the mask must all be on the apic cluster. If are not
* on the same apicid cluster return default value of TARGET_CPUS.
*/
- cpu = first_cpu(cpumask);
+ cpu = first_cpu(*cpumask);
apicid = cpu_to_logical_apicid(cpu);
while (cpus_found < num_bits_set) {
- if (cpu_isset(cpu, cpumask)) {
+ if (cpu_isset(cpu, *cpumask)) {
int new_apicid = cpu_to_logical_apicid(cpu);
if (apicid_cluster(apicid) !=
apicid_cluster(new_apicid)){
@@ -212,6 +216,24 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
return apicid;
}
+
+static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask,
+ const struct cpumask *andmask)
+{
+ int apicid = cpu_to_logical_apicid(0);
+ cpumask_var_t cpumask;
+
+ if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
+ return apicid;
+
+ cpumask_and(cpumask, inmask, andmask);
+ cpumask_and(cpumask, cpumask, cpu_online_mask);
+ apicid = cpu_mask_to_apicid(cpumask);
+
+ free_cpumask_var(cpumask);
+ return apicid;
+}
+
static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
{
return cpuid_apic >> index_msb;
diff --git a/arch/x86/include/asm/es7000/ipi.h b/arch/x86/include/asm/es7000/ipi.h
index 632a955fcc0a..7e8ed24d4b8a 100644
--- a/arch/x86/include/asm/es7000/ipi.h
+++ b/arch/x86/include/asm/es7000/ipi.h
@@ -1,24 +1,22 @@
#ifndef __ASM_ES7000_IPI_H
#define __ASM_ES7000_IPI_H
-void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(const struct cpumask *mask, int vector);
+void send_IPI_mask_allbutself(const struct cpumask *mask, int vector);
-static inline void send_IPI_mask(cpumask_t mask, int vector)
+static inline void send_IPI_mask(const struct cpumask *mask, int vector)
{
send_IPI_mask_sequence(mask, vector);
}
static inline void send_IPI_allbutself(int vector)
{
- cpumask_t mask = cpu_online_map;
- cpu_clear(smp_processor_id(), mask);
- if (!cpus_empty(mask))
- send_IPI_mask(mask, vector);
+ send_IPI_mask_allbutself(cpu_online_mask, vector);
}
static inline void send_IPI_all(int vector)
{
- send_IPI_mask(cpu_online_map, vector);
+ send_IPI_mask(cpu_online_mask, vector);
}
#endif /* __ASM_ES7000_IPI_H */
diff --git a/arch/x86/include/asm/es7000/mpparse.h b/arch/x86/include/asm/es7000/mpparse.h
index ed5a3caae141..c1629b090ec2 100644
--- a/arch/x86/include/asm/es7000/mpparse.h
+++ b/arch/x86/include/asm/es7000/mpparse.h
@@ -10,8 +10,7 @@ extern void setup_unisys(void);
#ifndef CONFIG_X86_GENERICARCH
extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id);
-extern int mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid);
+extern int mps_oem_check(struct mpc_table *mpc, char *oem, char *productid);
#endif
#ifdef CONFIG_ACPI
diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h
index 0ac17d33a8c7..2c05b737ee22 100644
--- a/arch/x86/include/asm/genapic_32.h
+++ b/arch/x86/include/asm/genapic_32.h
@@ -15,16 +15,16 @@
* Copyright 2003 Andi Kleen, SuSE Labs.
*/
-struct mpc_config_bus;
-struct mp_config_table;
-struct mpc_config_processor;
+struct mpc_bus;
+struct mpc_table;
+struct mpc_cpu;
struct genapic {
char *name;
int (*probe)(void);
int (*apic_id_registered)(void);
- cpumask_t (*target_cpus)(void);
+ const struct cpumask *(*target_cpus)(void);
int int_delivery_mode;
int int_dest_mode;
int ESR_DISABLE;
@@ -51,18 +51,22 @@ struct genapic {
/* When one of the next two hooks returns 1 the genapic
is switched to this. Essentially they are additional probe
functions. */
- int (*mps_oem_check)(struct mp_config_table *mpc, char *oem,
+ int (*mps_oem_check)(struct mpc_table *mpc, char *oem,
char *productid);
int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
unsigned (*get_apic_id)(unsigned long x);
unsigned long apic_id_mask;
- unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
- cpumask_t (*vector_allocation_domain)(int cpu);
+ unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask);
+ unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
+ const struct cpumask *andmask);
+ void (*vector_allocation_domain)(int cpu, struct cpumask *retmask);
#ifdef CONFIG_SMP
/* ipi */
- void (*send_IPI_mask)(cpumask_t mask, int vector);
+ void (*send_IPI_mask)(const struct cpumask *mask, int vector);
+ void (*send_IPI_mask_allbutself)(const struct cpumask *mask,
+ int vector);
void (*send_IPI_allbutself)(int vector);
void (*send_IPI_all)(int vector);
#endif
@@ -114,6 +118,7 @@ struct genapic {
APICFUNC(get_apic_id) \
.apic_id_mask = APIC_ID_MASK, \
APICFUNC(cpu_mask_to_apicid) \
+ APICFUNC(cpu_mask_to_apicid_and) \
APICFUNC(vector_allocation_domain) \
APICFUNC(acpi_madt_oem_check) \
IPIFUNC(send_IPI_mask) \
diff --git a/arch/x86/include/asm/genapic_64.h b/arch/x86/include/asm/genapic_64.h
index 2cae011668b7..adf32fb56aa6 100644
--- a/arch/x86/include/asm/genapic_64.h
+++ b/arch/x86/include/asm/genapic_64.h
@@ -1,6 +1,8 @@
#ifndef _ASM_X86_GENAPIC_64_H
#define _ASM_X86_GENAPIC_64_H
+#include <linux/cpumask.h>
+
/*
* Copyright 2004 James Cleverdon, IBM.
* Subject to the GNU Public License, v.2
@@ -18,16 +20,20 @@ struct genapic {
u32 int_delivery_mode;
u32 int_dest_mode;
int (*apic_id_registered)(void);
- cpumask_t (*target_cpus)(void);
- cpumask_t (*vector_allocation_domain)(int cpu);
+ const struct cpumask *(*target_cpus)(void);
+ void (*vector_allocation_domain)(int cpu, struct cpumask *retmask);
void (*init_apic_ldr)(void);
/* ipi */
- void (*send_IPI_mask)(cpumask_t mask, int vector);
+ void (*send_IPI_mask)(const struct cpumask *mask, int vector);
+ void (*send_IPI_mask_allbutself)(const struct cpumask *mask,
+ int vector);
void (*send_IPI_allbutself)(int vector);
void (*send_IPI_all)(int vector);
void (*send_IPI_self)(int vector);
/* */
- unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
+ unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask);
+ unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
+ const struct cpumask *andmask);
unsigned int (*phys_pkg_id)(int index_msb);
unsigned int (*get_apic_id)(unsigned long x);
unsigned long (*set_apic_id)(unsigned int id);
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 05cfed4485fa..1dbbdf4be9b4 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -99,7 +99,6 @@ extern void __iomem *ioremap_wc(unsigned long offset, unsigned long size);
* A boot-time mapping is currently limited to at most 16 pages.
*/
extern void early_ioremap_init(void);
-extern void early_ioremap_clear(void);
extern void early_ioremap_reset(void);
extern void __iomem *early_ioremap(unsigned long offset, unsigned long size);
extern void __iomem *early_memremap(unsigned long offset, unsigned long size);
diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h
index f89dffb28aa9..c745a306f7d3 100644
--- a/arch/x86/include/asm/ipi.h
+++ b/arch/x86/include/asm/ipi.h
@@ -117,7 +117,8 @@ static inline void __send_IPI_dest_field(unsigned int mask, int vector,
native_apic_mem_write(APIC_ICR, cfg);
}
-static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
+static inline void send_IPI_mask_sequence(const struct cpumask *mask,
+ int vector)
{
unsigned long flags;
unsigned long query_cpu;
@@ -128,11 +129,29 @@ static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
* - mbligh
*/
local_irq_save(flags);
- for_each_cpu_mask_nr(query_cpu, mask) {
+ for_each_cpu(query_cpu, mask) {
__send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, query_cpu),
vector, APIC_DEST_PHYSICAL);
}
local_irq_restore(flags);
}
+static inline void send_IPI_mask_allbutself(const struct cpumask *mask,
+ int vector)
+{
+ unsigned long flags;
+ unsigned int query_cpu;
+ unsigned int this_cpu = smp_processor_id();
+
+ /* See Hack comment above */
+
+ local_irq_save(flags);
+ for_each_cpu(query_cpu, mask)
+ if (query_cpu != this_cpu)
+ __send_IPI_dest_field(
+ per_cpu(x86_cpu_to_apicid, query_cpu),
+ vector, APIC_DEST_PHYSICAL);
+ local_irq_restore(flags);
+}
+
#endif /* _ASM_X86_IPI_H */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 28e409fc73f3..592688ed04d3 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -33,7 +33,7 @@ static inline int irq_canonicalize(int irq)
#ifdef CONFIG_HOTPLUG_CPU
#include <linux/cpumask.h>
-extern void fixup_irqs(cpumask_t map);
+extern void fixup_irqs(void);
#endif
extern unsigned int do_IRQ(struct pt_regs *regs);
@@ -42,5 +42,6 @@ extern void native_init_IRQ(void);
/* Interrupt vector management */
extern DECLARE_BITMAP(used_vectors, NR_VECTORS);
+extern int vector_used_by_percpu_irq(unsigned int vector);
#endif /* _ASM_X86_IRQ_H */
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index b95162af0bf6..d2e3bf3608af 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -6,7 +6,7 @@
*
*/
-#include <asm/types.h>
+#include <linux/types.h>
#include <linux/ioctl.h>
/* Architectural interrupt line count. */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 8346be87cfa1..730843d1d2fb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -21,6 +21,7 @@
#include <asm/pvclock-abi.h>
#include <asm/desc.h>
+#include <asm/mtrr.h>
#define KVM_MAX_VCPUS 16
#define KVM_MEMORY_SLOTS 32
@@ -86,6 +87,7 @@
#define KVM_MIN_FREE_MMU_PAGES 5
#define KVM_REFILL_PAGES 25
#define KVM_MAX_CPUID_ENTRIES 40
+#define KVM_NR_FIXED_MTRR_REGION 88
#define KVM_NR_VAR_MTRR 8
extern spinlock_t kvm_lock;
@@ -180,6 +182,8 @@ struct kvm_mmu_page {
struct list_head link;
struct hlist_node hash_link;
+ struct list_head oos_link;
+
/*
* The following two entries are used to key the shadow page in the
* hash table.
@@ -190,13 +194,16 @@ struct kvm_mmu_page {
u64 *spt;
/* hold the gfn of each spte inside spt */
gfn_t *gfns;
- unsigned long slot_bitmap; /* One bit set per slot which has memory
- * in this shadow page.
- */
+ /*
+ * One bit set per slot which has memory
+ * in this shadow page.
+ */
+ DECLARE_BITMAP(slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
int multimapped; /* More than one parent_pte? */
int root_count; /* Currently serving as active root */
bool unsync;
- bool unsync_children;
+ bool global;
+ unsigned int unsync_children;
union {
u64 *parent_pte; /* !multimapped */
struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */
@@ -327,8 +334,10 @@ struct kvm_vcpu_arch {
bool nmi_pending;
bool nmi_injected;
+ bool nmi_window_open;
- u64 mtrr[0x100];
+ struct mtrr_state_type mtrr_state;
+ u32 pat;
};
struct kvm_mem_alias {
@@ -350,11 +359,13 @@ struct kvm_arch{
*/
struct list_head active_mmu_pages;
struct list_head assigned_dev_head;
- struct dmar_domain *intel_iommu_domain;
+ struct list_head oos_global_pages;
+ struct iommu_domain *iommu_domain;
struct kvm_pic *vpic;
struct kvm_ioapic *vioapic;
struct kvm_pit *vpit;
struct hlist_head irq_ack_notifier_list;
+ int vapics_in_nmi_mode;
int round_robin_prev_vcpu;
unsigned int tss_addr;
@@ -378,6 +389,7 @@ struct kvm_vm_stat {
u32 mmu_recycled;
u32 mmu_cache_miss;
u32 mmu_unsync;
+ u32 mmu_unsync_global;
u32 remote_tlb_flush;
u32 lpages;
};
@@ -397,6 +409,7 @@ struct kvm_vcpu_stat {
u32 halt_exits;
u32 halt_wakeup;
u32 request_irq_exits;
+ u32 request_nmi_exits;
u32 irq_exits;
u32 host_state_reload;
u32 efer_reload;
@@ -405,6 +418,7 @@ struct kvm_vcpu_stat {
u32 insn_emulation_fail;
u32 hypercalls;
u32 irq_injections;
+ u32 nmi_injections;
};
struct descriptor_table {
@@ -477,6 +491,7 @@ struct kvm_x86_ops {
int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
int (*get_tdp_level)(void);
+ int (*get_mt_mask_shift)(void);
};
extern struct kvm_x86_ops *kvm_x86_ops;
@@ -490,7 +505,7 @@ int kvm_mmu_setup(struct kvm_vcpu *vcpu);
void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte);
void kvm_mmu_set_base_ptes(u64 base_pte);
void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
- u64 dirty_mask, u64 nx_mask, u64 x_mask);
+ u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 mt_mask);
int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot);
@@ -587,12 +602,14 @@ unsigned long segment_base(u16 selector);
void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu);
void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
- const u8 *new, int bytes);
+ const u8 *new, int bytes,
+ bool guest_initiated);
int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
int kvm_mmu_load(struct kvm_vcpu *vcpu);
void kvm_mmu_unload(struct kvm_vcpu *vcpu);
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
+void kvm_mmu_sync_global(struct kvm_vcpu *vcpu);
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
@@ -607,6 +624,8 @@ void kvm_disable_tdp(void);
int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
int complete_pio(struct kvm_vcpu *vcpu);
+struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn);
+
static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
{
struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT);
@@ -702,18 +721,6 @@ static inline void kvm_inject_gp(struct kvm_vcpu *vcpu, u32 error_code)
kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
}
-#define ASM_VMX_VMCLEAR_RAX ".byte 0x66, 0x0f, 0xc7, 0x30"
-#define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2"
-#define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3"
-#define ASM_VMX_VMPTRLD_RAX ".byte 0x0f, 0xc7, 0x30"
-#define ASM_VMX_VMREAD_RDX_RAX ".byte 0x0f, 0x78, 0xd0"
-#define ASM_VMX_VMWRITE_RAX_RDX ".byte 0x0f, 0x79, 0xd0"
-#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4"
-#define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4"
-#define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30"
-#define ASM_VMX_INVEPT ".byte 0x66, 0x0f, 0x38, 0x80, 0x08"
-#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"
-
#define MSR_IA32_TIME_STAMP_COUNTER 0x010
#define TSS_IOPB_BASE_OFFSET 0x66
diff --git a/arch/x86/include/asm/kvm_x86_emulate.h b/arch/x86/include/asm/kvm_x86_emulate.h
index 25179a29f208..6a159732881a 100644
--- a/arch/x86/include/asm/kvm_x86_emulate.h
+++ b/arch/x86/include/asm/kvm_x86_emulate.h
@@ -123,6 +123,7 @@ struct decode_cache {
u8 ad_bytes;
u8 rex_prefix;
struct operand src;
+ struct operand src2;
struct operand dst;
bool has_seg_override;
u8 seg_override;
@@ -146,22 +147,18 @@ struct x86_emulate_ctxt {
/* Register state before/after emulation. */
struct kvm_vcpu *vcpu;
- /* Linear faulting address (if emulating a page-faulting instruction) */
unsigned long eflags;
-
/* Emulated execution mode, represented by an X86EMUL_MODE value. */
int mode;
-
u32 cs_base;
/* decode cache */
-
struct decode_cache decode;
};
/* Repeat String Operation Prefix */
-#define REPE_PREFIX 1
-#define REPNE_PREFIX 2
+#define REPE_PREFIX 1
+#define REPNE_PREFIX 2
/* Execution mode, passed to the emulator. */
#define X86EMUL_MODE_REAL 0 /* Real mode. */
@@ -170,7 +167,7 @@ struct x86_emulate_ctxt {
#define X86EMUL_MODE_PROT64 8 /* 64-bit (long) mode. */
/* Host execution mode. */
-#if defined(__i386__)
+#if defined(CONFIG_X86_32)
#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32
#elif defined(CONFIG_X86_64)
#define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
diff --git a/arch/x86/include/asm/lguest.h b/arch/x86/include/asm/lguest.h
index d28a507cef39..1caf57628b9c 100644
--- a/arch/x86/include/asm/lguest.h
+++ b/arch/x86/include/asm/lguest.h
@@ -15,7 +15,7 @@
#define SHARED_SWITCHER_PAGES \
DIV_ROUND_UP(end_switcher_text - start_switcher_text, PAGE_SIZE)
/* Pages for switcher itself, then two pages per cpu */
-#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * NR_CPUS)
+#define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * nr_cpu_ids)
/* We map at -4M for ease of mapping into the guest (one PTE page). */
#define SWITCHER_ADDR 0xFFC00000
diff --git a/arch/x86/include/asm/mach-default/mach_apic.h b/arch/x86/include/asm/mach-default/mach_apic.h
index 6cb3a467e067..cc09cbbee27e 100644
--- a/arch/x86/include/asm/mach-default/mach_apic.h
+++ b/arch/x86/include/asm/mach-default/mach_apic.h
@@ -8,12 +8,12 @@
#define APIC_DFR_VALUE (APIC_DFR_FLAT)
-static inline cpumask_t target_cpus(void)
+static inline const struct cpumask *target_cpus(void)
{
#ifdef CONFIG_SMP
- return cpu_online_map;
+ return cpu_online_mask;
#else
- return cpumask_of_cpu(0);
+ return cpumask_of(0);
#endif
}
@@ -28,6 +28,7 @@ static inline cpumask_t target_cpus(void)
#define apic_id_registered (genapic->apic_id_registered)
#define init_apic_ldr (genapic->init_apic_ldr)
#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
+#define cpu_mask_to_apicid_and (genapic->cpu_mask_to_apicid_and)
#define phys_pkg_id (genapic->phys_pkg_id)
#define vector_allocation_domain (genapic->vector_allocation_domain)
#define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID)))
@@ -61,9 +62,19 @@ static inline int apic_id_registered(void)
return physid_isset(read_apic_id(), phys_cpu_present_map);
}
-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+static inline unsigned int cpu_mask_to_apicid(const struct cpumask *cpumask)
{
- return cpus_addr(cpumask)[0];
+ return cpumask_bits(cpumask)[0];
+}
+
+static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
+{
+ unsigned long mask1 = cpumask_bits(cpumask)[0];
+ unsigned long mask2 = cpumask_bits(andmask)[0];
+ unsigned long mask3 = cpumask_bits(cpu_online_mask)[0];
+
+ return (unsigned int)(mask1 & mask2 & mask3);
}
static inline u32 phys_pkg_id(u32 cpuid_apic, int index_msb)
@@ -88,7 +99,7 @@ static inline int apicid_to_node(int logical_apicid)
#endif
}
-static inline cpumask_t vector_allocation_domain(int cpu)
+static inline void vector_allocation_domain(int cpu, struct cpumask *retmask)
{
/* Careful. Some cpus do not strictly honor the set of cpus
* specified in the interrupt destination when using lowest
@@ -98,8 +109,7 @@ static inline cpumask_t vector_allocation_domain(int cpu)
* deliver interrupts to the wrong hyperthread when only one
* hyperthread was specified in the interrupt desitination.
*/
- cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
- return domain;
+ *retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } };
}
#endif
@@ -131,7 +141,7 @@ static inline int cpu_to_logical_apicid(int cpu)
static inline int cpu_present_to_apicid(int mps_cpu)
{
- if (mps_cpu < NR_CPUS && cpu_present(mps_cpu))
+ if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu))
return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
else
return BAD_APICID;
diff --git a/arch/x86/include/asm/mach-default/mach_ipi.h b/arch/x86/include/asm/mach-default/mach_ipi.h
index fabca01ebacf..191312d155da 100644
--- a/arch/x86/include/asm/mach-default/mach_ipi.h
+++ b/arch/x86/include/asm/mach-default/mach_ipi.h
@@ -4,7 +4,8 @@
/* Avoid include hell */
#define NMI_VECTOR 0x02
-void send_IPI_mask_bitmask(cpumask_t mask, int vector);
+void send_IPI_mask_bitmask(const struct cpumask *mask, int vector);
+void send_IPI_mask_allbutself(const struct cpumask *mask, int vector);
void __send_IPI_shortcut(unsigned int shortcut, int vector);
extern int no_broadcast;
@@ -12,28 +13,27 @@ extern int no_broadcast;
#ifdef CONFIG_X86_64
#include <asm/genapic.h>
#define send_IPI_mask (genapic->send_IPI_mask)
+#define send_IPI_mask_allbutself (genapic->send_IPI_mask_allbutself)
#else
-static inline void send_IPI_mask(cpumask_t mask, int vector)
+static inline void send_IPI_mask(const struct cpumask *mask, int vector)
{
send_IPI_mask_bitmask(mask, vector);
}
+void send_IPI_mask_allbutself(const struct cpumask *mask, int vector);
#endif
static inline void __local_send_IPI_allbutself(int vector)
{
- if (no_broadcast || vector == NMI_VECTOR) {
- cpumask_t mask = cpu_online_map;
-
- cpu_clear(smp_processor_id(), mask);
- send_IPI_mask(mask, vector);
- } else
+ if (no_broadcast || vector == NMI_VECTOR)
+ send_IPI_mask_allbutself(cpu_online_mask, vector);
+ else
__send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
}
static inline void __local_send_IPI_all(int vector)
{
if (no_broadcast || vector == NMI_VECTOR)
- send_IPI_mask(cpu_online_map, vector);
+ send_IPI_mask(cpu_online_mask, vector);
else
__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
}
diff --git a/arch/x86/include/asm/mach-default/mach_mpparse.h b/arch/x86/include/asm/mach-default/mach_mpparse.h
index 8c1ea21238a7..c70a263d68cd 100644
--- a/arch/x86/include/asm/mach-default/mach_mpparse.h
+++ b/arch/x86/include/asm/mach-default/mach_mpparse.h
@@ -1,8 +1,8 @@
#ifndef _ASM_X86_MACH_DEFAULT_MACH_MPPARSE_H
#define _ASM_X86_MACH_DEFAULT_MACH_MPPARSE_H
-static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid)
+static inline int
+mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
{
return 0;
}
diff --git a/arch/x86/include/asm/mach-default/mach_wakecpu.h b/arch/x86/include/asm/mach-default/mach_wakecpu.h
index ceb013660146..89897a6a65b9 100644
--- a/arch/x86/include/asm/mach-default/mach_wakecpu.h
+++ b/arch/x86/include/asm/mach-default/mach_wakecpu.h
@@ -24,7 +24,13 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
{
}
+#ifdef CONFIG_SMP
extern void __inquire_remote_apic(int apicid);
+#else /* CONFIG_SMP */
+static inline void __inquire_remote_apic(int apicid)
+{
+}
+#endif /* CONFIG_SMP */
static inline void inquire_remote_apic(int apicid)
{
diff --git a/arch/x86/include/asm/mach-generic/mach_apic.h b/arch/x86/include/asm/mach-generic/mach_apic.h
index e430f47df667..48553e958ad5 100644
--- a/arch/x86/include/asm/mach-generic/mach_apic.h
+++ b/arch/x86/include/asm/mach-generic/mach_apic.h
@@ -24,6 +24,7 @@
#define check_phys_apicid_present (genapic->check_phys_apicid_present)
#define check_apicid_used (genapic->check_apicid_used)
#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
+#define cpu_mask_to_apicid_and (genapic->cpu_mask_to_apicid_and)
#define vector_allocation_domain (genapic->vector_allocation_domain)
#define enable_apic_mode (genapic->enable_apic_mode)
#define phys_pkg_id (genapic->phys_pkg_id)
diff --git a/arch/x86/include/asm/mach-generic/mach_mpparse.h b/arch/x86/include/asm/mach-generic/mach_mpparse.h
index 048f1d468535..9444ab8dca94 100644
--- a/arch/x86/include/asm/mach-generic/mach_mpparse.h
+++ b/arch/x86/include/asm/mach-generic/mach_mpparse.h
@@ -2,9 +2,8 @@
#define _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H
-extern int mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid);
+extern int mps_oem_check(struct mpc_table *, char *, char *);
-extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id);
+extern int acpi_madt_oem_check(char *, char *);
#endif /* _ASM_X86_MACH_GENERIC_MACH_MPPARSE_H */
diff --git a/arch/x86/include/asm/mach-generic/mach_mpspec.h b/arch/x86/include/asm/mach-generic/mach_mpspec.h
index bbab5ccfd4fe..3bc407226578 100644
--- a/arch/x86/include/asm/mach-generic/mach_mpspec.h
+++ b/arch/x86/include/asm/mach-generic/mach_mpspec.h
@@ -7,6 +7,6 @@
/* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */
#define MAX_MP_BUSSES 260
-extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid);
+extern void numaq_mps_oem_check(struct mpc_table *, char *, char *);
+
#endif /* _ASM_X86_MACH_GENERIC_MACH_MPSPEC_H */
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 1d6e17c2f23a..32c6e17b960b 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -3,8 +3,8 @@
#ifdef __x86_64__
+#include <linux/types.h>
#include <asm/ioctls.h>
-#include <asm/types.h>
/*
* Machine Check support for x86
@@ -115,8 +115,6 @@ extern int mce_notify_user(void);
#endif /* !CONFIG_X86_32 */
-
-
#ifdef CONFIG_X86_MCE
extern void mcheck_init(struct cpuinfo_x86 *c);
#else
@@ -126,5 +124,4 @@ extern void stop_mce(void);
extern void restart_mce(void);
#endif /* __KERNEL__ */
-
#endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index 91885c28f66b..62d14ce3cd00 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -6,13 +6,13 @@
#include <asm/mpspec_def.h>
extern int apic_version[MAX_APICS];
+extern int pic_mode;
#ifdef CONFIG_X86_32
#include <mach_mpspec.h>
extern unsigned int def_to_bigsmp;
extern u8 apicid_2_node[];
-extern int pic_mode;
#ifdef CONFIG_X86_NUMAQ
extern int mp_bus_id_to_node[MAX_MP_BUSSES];
diff --git a/arch/x86/include/asm/mpspec_def.h b/arch/x86/include/asm/mpspec_def.h
index e3ace7d1d35d..59568bc4767f 100644
--- a/arch/x86/include/asm/mpspec_def.h
+++ b/arch/x86/include/asm/mpspec_def.h
@@ -39,17 +39,17 @@ struct intel_mp_floating {
#define MPC_SIGNATURE "PCMP"
-struct mp_config_table {
- char mpc_signature[4];
- unsigned short mpc_length; /* Size of table */
- char mpc_spec; /* 0x01 */
- char mpc_checksum;
- char mpc_oem[8];
- char mpc_productid[12];
- unsigned int mpc_oemptr; /* 0 if not present */
- unsigned short mpc_oemsize; /* 0 if not present */
- unsigned short mpc_oemcount;
- unsigned int mpc_lapic; /* APIC address */
+struct mpc_table {
+ char signature[4];
+ unsigned short length; /* Size of table */
+ char spec; /* 0x01 */
+ char checksum;
+ char oem[8];
+ char productid[12];
+ unsigned int oemptr; /* 0 if not present */
+ unsigned short oemsize; /* 0 if not present */
+ unsigned short oemcount;
+ unsigned int lapic; /* APIC address */
unsigned int reserved;
};
@@ -70,20 +70,20 @@ struct mp_config_table {
#define CPU_MODEL_MASK 0x00F0
#define CPU_FAMILY_MASK 0x0F00
-struct mpc_config_processor {
- unsigned char mpc_type;
- unsigned char mpc_apicid; /* Local APIC number */
- unsigned char mpc_apicver; /* Its versions */
- unsigned char mpc_cpuflag;
- unsigned int mpc_cpufeature;
- unsigned int mpc_featureflag; /* CPUID feature value */
- unsigned int mpc_reserved[2];
+struct mpc_cpu {
+ unsigned char type;
+ unsigned char apicid; /* Local APIC number */
+ unsigned char apicver; /* Its versions */
+ unsigned char cpuflag;
+ unsigned int cpufeature;
+ unsigned int featureflag; /* CPUID feature value */
+ unsigned int reserved[2];
};
-struct mpc_config_bus {
- unsigned char mpc_type;
- unsigned char mpc_busid;
- unsigned char mpc_bustype[6];
+struct mpc_bus {
+ unsigned char type;
+ unsigned char busid;
+ unsigned char bustype[6];
};
/* List of Bus Type string values, Intel MP Spec. */
@@ -108,22 +108,22 @@ struct mpc_config_bus {
#define MPC_APIC_USABLE 0x01
-struct mpc_config_ioapic {
- unsigned char mpc_type;
- unsigned char mpc_apicid;
- unsigned char mpc_apicver;
- unsigned char mpc_flags;
- unsigned int mpc_apicaddr;
+struct mpc_ioapic {
+ unsigned char type;
+ unsigned char apicid;
+ unsigned char apicver;
+ unsigned char flags;
+ unsigned int apicaddr;
};
-struct mpc_config_intsrc {
- unsigned char mpc_type;
- unsigned char mpc_irqtype;
- unsigned short mpc_irqflag;
- unsigned char mpc_srcbus;
- unsigned char mpc_srcbusirq;
- unsigned char mpc_dstapic;
- unsigned char mpc_dstirq;
+struct mpc_intsrc {
+ unsigned char type;
+ unsigned char irqtype;
+ unsigned short irqflag;
+ unsigned char srcbus;
+ unsigned char srcbusirq;
+ unsigned char dstapic;
+ unsigned char dstirq;
};
enum mp_irq_source_types {
@@ -139,24 +139,24 @@ enum mp_irq_source_types {
#define MP_APIC_ALL 0xFF
-struct mpc_config_lintsrc {
- unsigned char mpc_type;
- unsigned char mpc_irqtype;
- unsigned short mpc_irqflag;
- unsigned char mpc_srcbusid;
- unsigned char mpc_srcbusirq;
- unsigned char mpc_destapic;
- unsigned char mpc_destapiclint;
+struct mpc_lintsrc {
+ unsigned char type;
+ unsigned char irqtype;
+ unsigned short irqflag;
+ unsigned char srcbusid;
+ unsigned char srcbusirq;
+ unsigned char destapic;
+ unsigned char destapiclint;
};
#define MPC_OEM_SIGNATURE "_OEM"
-struct mp_config_oemtable {
- char oem_signature[4];
- unsigned short oem_length; /* Size of table */
- char oem_rev; /* 0x01 */
- char oem_checksum;
- char mpc_oem[8];
+struct mpc_oemtable {
+ char signature[4];
+ unsigned short length; /* Size of table */
+ char rev; /* 0x01 */
+ char checksum;
+ char mpc[8];
};
/*
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index cb58643947b9..358acc59ae04 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -202,6 +202,35 @@
#define MSR_IA32_THERM_STATUS 0x0000019c
#define MSR_IA32_MISC_ENABLE 0x000001a0
+/* MISC_ENABLE bits: architectural */
+#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0)
+#define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1)
+#define MSR_IA32_MISC_ENABLE_EMON (1ULL << 7)
+#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1ULL << 11)
+#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1ULL << 12)
+#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16)
+#define MSR_IA32_MISC_ENABLE_MWAIT (1ULL << 18)
+#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1ULL << 22)
+#define MSR_IA32_MISC_ENABLE_XTPR_DISABLE (1ULL << 23)
+#define MSR_IA32_MISC_ENABLE_XD_DISABLE (1ULL << 34)
+
+/* MISC_ENABLE bits: model-specific, meaning may vary from core to core */
+#define MSR_IA32_MISC_ENABLE_X87_COMPAT (1ULL << 2)
+#define MSR_IA32_MISC_ENABLE_TM1 (1ULL << 3)
+#define MSR_IA32_MISC_ENABLE_SPLIT_LOCK_DISABLE (1ULL << 4)
+#define MSR_IA32_MISC_ENABLE_L3CACHE_DISABLE (1ULL << 6)
+#define MSR_IA32_MISC_ENABLE_SUPPRESS_LOCK (1ULL << 8)
+#define MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE (1ULL << 9)
+#define MSR_IA32_MISC_ENABLE_FERR (1ULL << 10)
+#define MSR_IA32_MISC_ENABLE_FERR_MULTIPLEX (1ULL << 10)
+#define MSR_IA32_MISC_ENABLE_TM2 (1ULL << 13)
+#define MSR_IA32_MISC_ENABLE_ADJ_PREF_DISABLE (1ULL << 19)
+#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20)
+#define MSR_IA32_MISC_ENABLE_L1D_CONTEXT (1ULL << 24)
+#define MSR_IA32_MISC_ENABLE_DCU_PREF_DISABLE (1ULL << 37)
+#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38)
+#define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE (1ULL << 39)
+
/* Intel Model 6 */
#define MSR_P6_EVNTSEL0 0x00000186
#define MSR_P6_EVNTSEL1 0x00000187
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 7c1e4258b31e..a51ada8467de 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -23,6 +23,7 @@
#ifndef _ASM_X86_MTRR_H
#define _ASM_X86_MTRR_H
+#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/errno.h>
@@ -57,6 +58,31 @@ struct mtrr_gentry {
};
#endif /* !__i386__ */
+struct mtrr_var_range {
+ __u32 base_lo;
+ __u32 base_hi;
+ __u32 mask_lo;
+ __u32 mask_hi;
+};
+
+/* In the Intel processor's MTRR interface, the MTRR type is always held in
+ an 8 bit field: */
+typedef __u8 mtrr_type;
+
+#define MTRR_NUM_FIXED_RANGES 88
+#define MTRR_MAX_VAR_RANGES 256
+
+struct mtrr_state_type {
+ struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES];
+ mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES];
+ unsigned char enabled;
+ unsigned char have_fixed;
+ mtrr_type def_type;
+};
+
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
+#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+
/* These are the various ioctls */
#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry)
#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry)
diff --git a/arch/x86/include/asm/numaq/apic.h b/arch/x86/include/asm/numaq/apic.h
index 0bf2a06b7a4e..bf37bc49bd8e 100644
--- a/arch/x86/include/asm/numaq/apic.h
+++ b/arch/x86/include/asm/numaq/apic.h
@@ -7,9 +7,9 @@
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
-static inline cpumask_t target_cpus(void)
+static inline const cpumask_t *target_cpus(void)
{
- return CPU_MASK_ALL;
+ return &CPU_MASK_ALL;
}
#define NO_BALANCE_IRQ (1)
@@ -63,8 +63,8 @@ static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map)
extern u8 cpu_2_logical_apicid[];
static inline int cpu_to_logical_apicid(int cpu)
{
- if (cpu >= NR_CPUS)
- return BAD_APICID;
+ if (cpu >= nr_cpu_ids)
+ return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu];
}
@@ -122,7 +122,13 @@ static inline void enable_apic_mode(void)
* We use physical apicids here, not logical, so just return the default
* physical broadcast to stop people from breaking us
*/
-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
+{
+ return (int) 0xF;
+}
+
+static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
{
return (int) 0xF;
}
diff --git a/arch/x86/include/asm/numaq/ipi.h b/arch/x86/include/asm/numaq/ipi.h
index 935588d286cf..a8374c652778 100644
--- a/arch/x86/include/asm/numaq/ipi.h
+++ b/arch/x86/include/asm/numaq/ipi.h
@@ -1,25 +1,22 @@
#ifndef __ASM_NUMAQ_IPI_H
#define __ASM_NUMAQ_IPI_H
-void send_IPI_mask_sequence(cpumask_t, int vector);
+void send_IPI_mask_sequence(const struct cpumask *mask, int vector);
+void send_IPI_mask_allbutself(const struct cpumask *mask, int vector);
-static inline void send_IPI_mask(cpumask_t mask, int vector)
+static inline void send_IPI_mask(const struct cpumask *mask, int vector)
{
send_IPI_mask_sequence(mask, vector);
}
static inline void send_IPI_allbutself(int vector)
{
- cpumask_t mask = cpu_online_map;
- cpu_clear(smp_processor_id(), mask);
-
- if (!cpus_empty(mask))
- send_IPI_mask(mask, vector);
+ send_IPI_mask_allbutself(cpu_online_mask, vector);
}
static inline void send_IPI_all(int vector)
{
- send_IPI_mask(cpu_online_map, vector);
+ send_IPI_mask(cpu_online_mask, vector);
}
#endif /* __ASM_NUMAQ_IPI_H */
diff --git a/arch/x86/include/asm/numaq/mpparse.h b/arch/x86/include/asm/numaq/mpparse.h
index 252292e077b6..a2eeefcd1cc7 100644
--- a/arch/x86/include/asm/numaq/mpparse.h
+++ b/arch/x86/include/asm/numaq/mpparse.h
@@ -1,7 +1,6 @@
#ifndef __ASM_NUMAQ_MPPARSE_H
#define __ASM_NUMAQ_MPPARSE_H
-extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid);
+extern void numaq_mps_oem_check(struct mpc_table *, char *, char *);
#endif /* __ASM_NUMAQ_MPPARSE_H */
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 66834c41c049..a977de23cb4d 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -102,9 +102,9 @@ extern void pci_iommu_alloc(void);
#ifdef CONFIG_NUMA
/* Returns the node based on pci bus */
-static inline int __pcibus_to_node(struct pci_bus *bus)
+static inline int __pcibus_to_node(const struct pci_bus *bus)
{
- struct pci_sysdata *sd = bus->sysdata;
+ const struct pci_sysdata *sd = bus->sysdata;
return sd->node;
}
@@ -113,6 +113,12 @@ static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus)
{
return node_to_cpumask(__pcibus_to_node(bus));
}
+
+static inline const struct cpumask *
+cpumask_of_pcibus(const struct pci_bus *bus)
+{
+ return cpumask_of_node(__pcibus_to_node(bus));
+}
#endif
#endif /* _ASM_X86_PCI_H */
diff --git a/arch/x86/pci/pci.h b/arch/x86/include/asm/pci_x86.h
index 1959018aac02..e60fd3e14bdf 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -57,7 +57,8 @@ extern struct pci_ops pci_root_ops;
struct irq_info {
u8 bus, devfn; /* Bus, device and function */
struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
+ u8 link; /* IRQ line ID, chipset dependent,
+ 0 = not routed */
u16 bitmap; /* Available IRQs */
} __attribute__((packed)) irq[4];
u8 slot; /* Slot number, 0=onboard */
@@ -69,11 +70,13 @@ struct irq_routing_table {
u16 version; /* PIRQ_VERSION */
u16 size; /* Table size in bytes */
u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
+ u16 exclusive_irqs; /* IRQs devoted exclusively to
+ PCI usage */
+ u16 rtr_vendor, rtr_device; /* Vendor and device ID of
+ interrupt router */
u32 miniport_data; /* Crap */
u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
+ u8 checksum; /* Modulo 256 checksum must give 0 */
struct irq_info slots[0];
} __attribute__((packed));
@@ -148,15 +151,15 @@ static inline unsigned int mmio_config_readl(void __iomem *pos)
static inline void mmio_config_writeb(void __iomem *pos, u8 val)
{
- asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory");
+ asm volatile("movb %%al,(%1)" : : "a" (val), "r" (pos) : "memory");
}
static inline void mmio_config_writew(void __iomem *pos, u16 val)
{
- asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory");
+ asm volatile("movw %%ax,(%1)" : : "a" (val), "r" (pos) : "memory");
}
static inline void mmio_config_writel(void __iomem *pos, u32 val)
{
- asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory");
+ asm volatile("movl %%eax,(%1)" : : "a" (val), "r" (pos) : "memory");
}
diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h
index cb7c151a8bff..dd14c54ac718 100644
--- a/arch/x86/include/asm/pgalloc.h
+++ b/arch/x86/include/asm/pgalloc.h
@@ -42,6 +42,7 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
static inline void pte_free(struct mm_struct *mm, struct page *pte)
{
+ pgtable_page_dtor(pte);
__free_page(pte);
}
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 83e69f4a37f0..06bbcbd66e9c 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -341,6 +341,25 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
#define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask)
+static inline int is_new_memtype_allowed(unsigned long flags,
+ unsigned long new_flags)
+{
+ /*
+ * Certain new memtypes are not allowed with certain
+ * requested memtype:
+ * - request is uncached, return cannot be write-back
+ * - request is write-combine, return cannot be write-back
+ */
+ if ((flags == _PAGE_CACHE_UC_MINUS &&
+ new_flags == _PAGE_CACHE_WB) ||
+ (flags == _PAGE_CACHE_WC &&
+ new_flags == _PAGE_CACHE_WB)) {
+ return 0;
+ }
+
+ return 1;
+}
+
#ifndef __ASSEMBLY__
/* Indicate that x86 has its own track and untrack pfn vma functions */
#define __HAVE_PFNMAP_TRACKING
diff --git a/arch/x86/include/asm/ptrace-abi.h b/arch/x86/include/asm/ptrace-abi.h
index 25f1bb8fc626..8e0f8d199e05 100644
--- a/arch/x86/include/asm/ptrace-abi.h
+++ b/arch/x86/include/asm/ptrace-abi.h
@@ -83,7 +83,7 @@
#ifdef CONFIG_X86_PTRACE_BTS
#ifndef __ASSEMBLY__
-#include <asm/types.h>
+#include <linux/types.h>
/* configuration/status structure used in PTRACE_BTS_CONFIG and
PTRACE_BTS_STATUS commands.
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 4fcd53fd5f43..ebe858cdc8a3 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -25,9 +25,9 @@ extern int wakeup_secondary_cpu_via_init(int apicid, unsigned long start_eip);
/*
* Any setup quirks to be performed?
*/
-struct mpc_config_processor;
-struct mpc_config_bus;
-struct mp_config_oemtable;
+struct mpc_cpu;
+struct mpc_bus;
+struct mpc_oemtable;
struct x86_quirks {
int (*arch_pre_time_init)(void);
int (*arch_time_init)(void);
@@ -39,10 +39,10 @@ struct x86_quirks {
int (*mach_find_smp_config)(unsigned int reserve);
int *mpc_record;
- int (*mpc_apic_id)(struct mpc_config_processor *m);
- void (*mpc_oem_bus_info)(struct mpc_config_bus *m, char *name);
- void (*mpc_oem_pci_bus)(struct mpc_config_bus *m);
- void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
+ int (*mpc_apic_id)(struct mpc_cpu *m);
+ void (*mpc_oem_bus_info)(struct mpc_bus *m, char *name);
+ void (*mpc_oem_pci_bus)(struct mpc_bus *m);
+ void (*smp_read_mpc_oem)(struct mpc_oemtable *oemtable,
unsigned short oemsize);
int (*setup_ioapic_ids)(void);
int (*update_genapic)(void);
diff --git a/arch/x86/include/asm/sigcontext.h b/arch/x86/include/asm/sigcontext.h
index 0afcb5e58acc..ec666491aaa4 100644
--- a/arch/x86/include/asm/sigcontext.h
+++ b/arch/x86/include/asm/sigcontext.h
@@ -2,7 +2,7 @@
#define _ASM_X86_SIGCONTEXT_H
#include <linux/compiler.h>
-#include <asm/types.h>
+#include <linux/types.h>
#define FP_XSTATE_MAGIC1 0x46505853U
#define FP_XSTATE_MAGIC2 0x46505845U
diff --git a/arch/x86/include/asm/sigcontext32.h b/arch/x86/include/asm/sigcontext32.h
index 6126188cf3a9..ad1478c4ae12 100644
--- a/arch/x86/include/asm/sigcontext32.h
+++ b/arch/x86/include/asm/sigcontext32.h
@@ -1,6 +1,8 @@
#ifndef _ASM_X86_SIGCONTEXT32_H
#define _ASM_X86_SIGCONTEXT32_H
+#include <linux/types.h>
+
/* signal context for 32bit programs. */
#define X86_FXSR_MAGIC 0x0000
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index d12811ce51d9..19953df61c52 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -18,9 +18,26 @@
#include <asm/pda.h>
#include <asm/thread_info.h>
+#ifdef CONFIG_X86_64
+
+extern cpumask_var_t cpu_callin_mask;
+extern cpumask_var_t cpu_callout_mask;
+extern cpumask_var_t cpu_initialized_mask;
+extern cpumask_var_t cpu_sibling_setup_mask;
+
+#else /* CONFIG_X86_32 */
+
+extern cpumask_t cpu_callin_map;
extern cpumask_t cpu_callout_map;
extern cpumask_t cpu_initialized;
-extern cpumask_t cpu_callin_map;
+extern cpumask_t cpu_sibling_setup_map;
+
+#define cpu_callin_mask ((struct cpumask *)&cpu_callin_map)
+#define cpu_callout_mask ((struct cpumask *)&cpu_callout_map)
+#define cpu_initialized_mask ((struct cpumask *)&cpu_initialized)
+#define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map)
+
+#endif /* CONFIG_X86_32 */
extern void (*mtrr_hook)(void);
extern void zap_low_mappings(void);
@@ -29,7 +46,6 @@ extern int __cpuinit get_local_pda(int cpu);
extern int smp_num_siblings;
extern unsigned int num_processors;
-extern cpumask_t cpu_initialized;
DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
DECLARE_PER_CPU(cpumask_t, cpu_core_map);
@@ -38,6 +54,16 @@ DECLARE_PER_CPU(u16, cpu_llc_id);
DECLARE_PER_CPU(int, cpu_number);
#endif
+static inline struct cpumask *cpu_sibling_mask(int cpu)
+{
+ return &per_cpu(cpu_sibling_map, cpu);
+}
+
+static inline struct cpumask *cpu_core_mask(int cpu)
+{
+ return &per_cpu(cpu_core_map, cpu);
+}
+
DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid);
DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
@@ -60,7 +86,7 @@ struct smp_ops {
void (*cpu_die)(unsigned int cpu);
void (*play_dead)(void);
- void (*send_call_func_ipi)(cpumask_t mask);
+ void (*send_call_func_ipi)(const struct cpumask *mask);
void (*send_call_func_single_ipi)(int cpu);
};
@@ -125,7 +151,7 @@ static inline void arch_send_call_function_single_ipi(int cpu)
static inline void arch_send_call_function_ipi(cpumask_t mask)
{
- smp_ops.send_call_func_ipi(mask);
+ smp_ops.send_call_func_ipi(&mask);
}
void cpu_disable_common(void);
@@ -138,7 +164,7 @@ void native_cpu_die(unsigned int cpu);
void native_play_dead(void);
void play_dead_common(void);
-void native_send_call_func_ipi(cpumask_t mask);
+void native_send_call_func_ipi(const struct cpumask *mask);
void native_send_call_func_single_ipi(int cpu);
extern void prefill_possible_map(void);
@@ -149,7 +175,7 @@ void smp_store_cpu_info(int id);
/* We don't mark CPUs online until __cpu_up(), so we need another measure */
static inline int num_booting_cpus(void)
{
- return cpus_weight(cpu_callout_map);
+ return cpumask_weight(cpu_callout_mask);
}
#else
static inline void prefill_possible_map(void)
diff --git a/arch/x86/include/asm/summit/apic.h b/arch/x86/include/asm/summit/apic.h
index 9b3070f1c2ac..93d2c8667cfe 100644
--- a/arch/x86/include/asm/summit/apic.h
+++ b/arch/x86/include/asm/summit/apic.h
@@ -2,6 +2,7 @@
#define __ASM_SUMMIT_APIC_H
#include <asm/smp.h>
+#include <linux/gfp.h>
#define esr_disable (1)
#define NO_BALANCE_IRQ (0)
@@ -14,13 +15,13 @@
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
-static inline cpumask_t target_cpus(void)
+static inline const cpumask_t *target_cpus(void)
{
/* CPU_MASK_ALL (0xff) has undefined behaviour with
* dest_LowestPrio mode logical clustered apic interrupt routing
* Just start on cpu 0. IRQ balancing will spread load
*/
- return cpumask_of_cpu(0);
+ return &cpumask_of_cpu(0);
}
#define INT_DELIVERY_MODE (dest_LowestPrio)
@@ -52,7 +53,7 @@ static inline void init_apic_ldr(void)
int i;
/* Create logical APIC IDs by counting CPUs already in cluster. */
- for (count = 0, i = NR_CPUS; --i >= 0; ) {
+ for (count = 0, i = nr_cpu_ids; --i >= 0; ) {
lid = cpu_2_logical_apicid[i];
if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster)
++count;
@@ -97,8 +98,8 @@ static inline int apicid_to_node(int logical_apicid)
static inline int cpu_to_logical_apicid(int cpu)
{
#ifdef CONFIG_SMP
- if (cpu >= NR_CPUS)
- return BAD_APICID;
+ if (cpu >= nr_cpu_ids)
+ return BAD_APICID;
return (int)cpu_2_logical_apicid[cpu];
#else
return logical_smp_processor_id();
@@ -107,7 +108,7 @@ static inline int cpu_to_logical_apicid(int cpu)
static inline int cpu_present_to_apicid(int mps_cpu)
{
- if (mps_cpu < NR_CPUS)
+ if (mps_cpu < nr_cpu_ids)
return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
else
return BAD_APICID;
@@ -137,25 +138,25 @@ static inline void enable_apic_mode(void)
{
}
-static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
+static inline unsigned int cpu_mask_to_apicid(const cpumask_t *cpumask)
{
int num_bits_set;
int cpus_found = 0;
int cpu;
int apicid;
- num_bits_set = cpus_weight(cpumask);
+ num_bits_set = cpus_weight(*cpumask);
/* Return id to all */
- if (num_bits_set == NR_CPUS)
+ if (num_bits_set >= nr_cpu_ids)
return (int) 0xFF;
/*
* The cpus in the mask must all be on the apic cluster. If are not
* on the same apicid cluster return default value of TARGET_CPUS.
*/
- cpu = first_cpu(cpumask);
+ cpu = first_cpu(*cpumask);
apicid = cpu_to_logical_apicid(cpu);
while (cpus_found < num_bits_set) {
- if (cpu_isset(cpu, cpumask)) {
+ if (cpu_isset(cpu, *cpumask)) {
int new_apicid = cpu_to_logical_apicid(cpu);
if (apicid_cluster(apicid) !=
apicid_cluster(new_apicid)){
@@ -170,6 +171,23 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
return apicid;
}
+static inline unsigned int cpu_mask_to_apicid_and(const struct cpumask *inmask,
+ const struct cpumask *andmask)
+{
+ int apicid = cpu_to_logical_apicid(0);
+ cpumask_var_t cpumask;
+
+ if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
+ return apicid;
+
+ cpumask_and(cpumask, inmask, andmask);
+ cpumask_and(cpumask, cpumask, cpu_online_mask);
+ apicid = cpu_mask_to_apicid(cpumask);
+
+ free_cpumask_var(cpumask);
+ return apicid;
+}
+
/* cpuid returns the value latched in the HW at reset, not the APIC ID
* register's value. For any box whose BIOS changes APIC IDs, like
* clustered APIC systems, we must use hard_smp_processor_id.
diff --git a/arch/x86/include/asm/summit/ipi.h b/arch/x86/include/asm/summit/ipi.h
index 53bd1e7bd7b4..a8a2c24f50cc 100644
--- a/arch/x86/include/asm/summit/ipi.h
+++ b/arch/x86/include/asm/summit/ipi.h
@@ -1,9 +1,10 @@
#ifndef __ASM_SUMMIT_IPI_H
#define __ASM_SUMMIT_IPI_H
-void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(const cpumask_t *mask, int vector);
+void send_IPI_mask_allbutself(const cpumask_t *mask, int vector);
-static inline void send_IPI_mask(cpumask_t mask, int vector)
+static inline void send_IPI_mask(const cpumask_t *mask, int vector)
{
send_IPI_mask_sequence(mask, vector);
}
@@ -14,12 +15,12 @@ static inline void send_IPI_allbutself(int vector)
cpu_clear(smp_processor_id(), mask);
if (!cpus_empty(mask))
- send_IPI_mask(mask, vector);
+ send_IPI_mask(&mask, vector);
}
static inline void send_IPI_all(int vector)
{
- send_IPI_mask(cpu_online_map, vector);
+ send_IPI_mask(&cpu_online_map, vector);
}
#endif /* __ASM_SUMMIT_IPI_H */
diff --git a/arch/x86/include/asm/summit/mpparse.h b/arch/x86/include/asm/summit/mpparse.h
index 013ce6fab2d5..380e86c02363 100644
--- a/arch/x86/include/asm/summit/mpparse.h
+++ b/arch/x86/include/asm/summit/mpparse.h
@@ -11,7 +11,7 @@ extern void setup_summit(void);
#define setup_summit() {}
#endif
-static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
+static inline int mps_oem_check(struct mpc_table *mpc, char *oem,
char *productid)
{
if (!strncmp(oem, "IBM ENSW", 8) &&
diff --git a/arch/x86/kvm/svm.h b/arch/x86/include/asm/svm.h
index 1b8afa78e869..1b8afa78e869 100644
--- a/arch/x86/kvm/svm.h
+++ b/arch/x86/include/asm/svm.h
diff --git a/arch/x86/include/asm/swab.h b/arch/x86/include/asm/swab.h
new file mode 100644
index 000000000000..557cd9f00661
--- /dev/null
+++ b/arch/x86/include/asm/swab.h
@@ -0,0 +1,61 @@
+#ifndef _ASM_X86_SWAB_H
+#define _ASM_X86_SWAB_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+#ifdef __i386__
+# ifdef CONFIG_X86_BSWAP
+ asm("bswap %0" : "=r" (val) : "0" (val));
+# else
+ asm("xchgb %b0,%h0\n\t" /* swap lower bytes */
+ "rorl $16,%0\n\t" /* swap words */
+ "xchgb %b0,%h0" /* swap higher bytes */
+ : "=q" (val)
+ : "0" (val));
+# endif
+
+#else /* __i386__ */
+ asm("bswapl %0"
+ : "=r" (val)
+ : "0" (val));
+#endif
+ return val;
+}
+#define __arch_swab32 __arch_swab32
+
+static inline __attribute_const__ __u64 __arch_swab64(__u64 val)
+{
+#ifdef __i386__
+ union {
+ struct {
+ __u32 a;
+ __u32 b;
+ } s;
+ __u64 u;
+ } v;
+ v.u = val;
+# ifdef CONFIG_X86_BSWAP
+ asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ : "=r" (v.s.a), "=r" (v.s.b)
+ : "0" (v.s.a), "1" (v.s.b));
+# else
+ v.s.a = __arch_swab32(v.s.a);
+ v.s.b = __arch_swab32(v.s.b);
+ asm("xchgl %0,%1"
+ : "=r" (v.s.a), "=r" (v.s.b)
+ : "0" (v.s.a), "1" (v.s.b));
+# endif
+ return v.u;
+#else /* __i386__ */
+ asm("bswapq %0"
+ : "=r" (val)
+ : "0" (val));
+ return val;
+#endif
+}
+#define __arch_swab64 __arch_swab64
+
+#endif /* _ASM_X86_SWAB_H */
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index 51fb2c76ad74..b9e4e20174fb 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -1,46 +1,10 @@
#ifndef _ASM_X86_SWIOTLB_H
#define _ASM_X86_SWIOTLB_H
-#include <asm/dma-mapping.h>
+#include <linux/swiotlb.h>
/* SWIOTLB interface */
-extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr,
- size_t size, int dir);
-extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags);
-extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
- size_t size, int dir);
-extern void swiotlb_sync_single_for_cpu(struct device *hwdev,
- dma_addr_t dev_addr,
- size_t size, int dir);
-extern void swiotlb_sync_single_for_device(struct device *hwdev,
- dma_addr_t dev_addr,
- size_t size, int dir);
-extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev,
- dma_addr_t dev_addr,
- unsigned long offset,
- size_t size, int dir);
-extern void swiotlb_sync_single_range_for_device(struct device *hwdev,
- dma_addr_t dev_addr,
- unsigned long offset,
- size_t size, int dir);
-extern void swiotlb_sync_sg_for_cpu(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- int dir);
-extern void swiotlb_sync_sg_for_device(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- int dir);
-extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction);
-extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
- int nents, int direction);
-extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
-extern void swiotlb_free_coherent(struct device *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
-extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
-extern void swiotlb_init(void);
-
extern int swiotlb_force;
#ifdef CONFIG_SWIOTLB
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
new file mode 100644
index 000000000000..ffb08be2a530
--- /dev/null
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -0,0 +1,101 @@
+/*
+ * sys_ia32.h - Linux ia32 syscall interfaces
+ *
+ * Copyright (c) 2008 Jaswinder Singh Rajput
+ *
+ * This file is released under the GPLv2.
+ * See the file COPYING for more details.
+ */
+
+#ifndef _ASM_X86_SYS_IA32_H
+#define _ASM_X86_SYS_IA32_H
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/signal.h>
+#include <asm/compat.h>
+#include <asm/ia32.h>
+
+/* ia32/sys_ia32.c */
+asmlinkage long sys32_truncate64(char __user *, unsigned long, unsigned long);
+asmlinkage long sys32_ftruncate64(unsigned int, unsigned long, unsigned long);
+
+asmlinkage long sys32_stat64(char __user *, struct stat64 __user *);
+asmlinkage long sys32_lstat64(char __user *, struct stat64 __user *);
+asmlinkage long sys32_fstat64(unsigned int, struct stat64 __user *);
+asmlinkage long sys32_fstatat(unsigned int, char __user *,
+ struct stat64 __user *, int);
+struct mmap_arg_struct;
+asmlinkage long sys32_mmap(struct mmap_arg_struct __user *);
+asmlinkage long sys32_mprotect(unsigned long, size_t, unsigned long);
+
+asmlinkage long sys32_pipe(int __user *);
+struct sigaction32;
+struct old_sigaction32;
+asmlinkage long sys32_rt_sigaction(int, struct sigaction32 __user *,
+ struct sigaction32 __user *, unsigned int);
+asmlinkage long sys32_sigaction(int, struct old_sigaction32 __user *,
+ struct old_sigaction32 __user *);
+asmlinkage long sys32_rt_sigprocmask(int, compat_sigset_t __user *,
+ compat_sigset_t __user *, unsigned int);
+asmlinkage long sys32_alarm(unsigned int);
+
+struct sel_arg_struct;
+asmlinkage long sys32_old_select(struct sel_arg_struct __user *);
+asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int);
+asmlinkage long sys32_sysfs(int, u32, u32);
+
+asmlinkage long sys32_sched_rr_get_interval(compat_pid_t,
+ struct compat_timespec __user *);
+asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *, compat_size_t);
+asmlinkage long sys32_rt_sigqueueinfo(int, int, compat_siginfo_t __user *);
+
+#ifdef CONFIG_SYSCTL_SYSCALL
+struct sysctl_ia32;
+asmlinkage long sys32_sysctl(struct sysctl_ia32 __user *);
+#endif
+
+asmlinkage long sys32_pread(unsigned int, char __user *, u32, u32, u32);
+asmlinkage long sys32_pwrite(unsigned int, char __user *, u32, u32, u32);
+
+asmlinkage long sys32_personality(unsigned long);
+asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
+
+asmlinkage long sys32_mmap2(unsigned long, unsigned long, unsigned long,
+ unsigned long, unsigned long, unsigned long);
+
+struct oldold_utsname;
+struct old_utsname;
+asmlinkage long sys32_olduname(struct oldold_utsname __user *);
+long sys32_uname(struct old_utsname __user *);
+
+long sys32_ustat(unsigned, struct ustat32 __user *);
+
+asmlinkage long sys32_execve(char __user *, compat_uptr_t __user *,
+ compat_uptr_t __user *, struct pt_regs *);
+asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
+
+long sys32_lseek(unsigned int, int, unsigned int);
+long sys32_kill(int, int);
+long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int);
+long sys32_vm86_warning(void);
+long sys32_lookup_dcookie(u32, u32, char __user *, size_t);
+
+asmlinkage ssize_t sys32_readahead(int, unsigned, unsigned, size_t);
+asmlinkage long sys32_sync_file_range(int, unsigned, unsigned,
+ unsigned, unsigned, int);
+asmlinkage long sys32_fadvise64(int, unsigned, unsigned, size_t, int);
+asmlinkage long sys32_fallocate(int, int, unsigned,
+ unsigned, unsigned, unsigned);
+
+/* ia32/ia32_signal.c */
+asmlinkage long sys32_sigsuspend(int, int, old_sigset_t);
+asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *,
+ stack_ia32_t __user *, struct pt_regs *);
+asmlinkage long sys32_sigreturn(struct pt_regs *);
+asmlinkage long sys32_rt_sigreturn(struct pt_regs *);
+
+/* ia32/ipc32.c */
+asmlinkage long sys32_ipc(u32, int, int, int, compat_uptr_t, u32);
+#endif /* _ASM_X86_SYS_IA32_H */
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 9c6797c3e56c..c0b0bda754ee 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -40,7 +40,7 @@ asmlinkage int sys_sigaction(int, const struct old_sigaction __user *,
struct old_sigaction __user *);
asmlinkage int sys_sigaltstack(unsigned long);
asmlinkage unsigned long sys_sigreturn(unsigned long);
-asmlinkage int sys_rt_sigreturn(struct pt_regs);
+asmlinkage int sys_rt_sigreturn(unsigned long);
/* kernel/ioport.c */
asmlinkage long sys_iopl(unsigned long);
diff --git a/arch/x86/include/asm/timex.h b/arch/x86/include/asm/timex.h
index 1287dc1347d6..b5c9d45c981f 100644
--- a/arch/x86/include/asm/timex.h
+++ b/arch/x86/include/asm/timex.h
@@ -1,18 +1,13 @@
-/* x86 architecture timex specifications */
#ifndef _ASM_X86_TIMEX_H
#define _ASM_X86_TIMEX_H
#include <asm/processor.h>
#include <asm/tsc.h>
-#ifdef CONFIG_X86_ELAN
-# define PIT_TICK_RATE 1189200 /* AMD Elan has different frequency! */
-#elif defined(CONFIG_X86_RDC321X)
-# define PIT_TICK_RATE 1041667 /* Underlying HZ for R8610 */
-#else
-# define PIT_TICK_RATE 1193182 /* Underlying HZ */
-#endif
-#define CLOCK_TICK_RATE PIT_TICK_RATE
+/* The PIT ticks at this frequency (in HZ): */
+#define PIT_TICK_RATE 1193182
+
+#define CLOCK_TICK_RATE PIT_TICK_RATE
#define ARCH_HAS_READ_CURRENT_TIMER
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index ff386ff50ed7..4e2f2e0aab27 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -61,13 +61,19 @@ static inline int cpu_to_node(int cpu)
*
* Side note: this function creates the returned cpumask on the stack
* so with a high NR_CPUS count, excessive stack space is used. The
- * node_to_cpumask_ptr function should be used whenever possible.
+ * cpumask_of_node function should be used whenever possible.
*/
static inline cpumask_t node_to_cpumask(int node)
{
return node_to_cpumask_map[node];
}
+/* Returns a bitmask of CPUs on Node 'node'. */
+static inline const struct cpumask *cpumask_of_node(int node)
+{
+ return &node_to_cpumask_map[node];
+}
+
#else /* CONFIG_X86_64 */
/* Mappings between node number and cpus on that node. */
@@ -82,7 +88,7 @@ DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map);
#ifdef CONFIG_DEBUG_PER_CPU_MAPS
extern int cpu_to_node(int cpu);
extern int early_cpu_to_node(int cpu);
-extern const cpumask_t *_node_to_cpumask_ptr(int node);
+extern const cpumask_t *cpumask_of_node(int node);
extern cpumask_t node_to_cpumask(int node);
#else /* !CONFIG_DEBUG_PER_CPU_MAPS */
@@ -103,7 +109,7 @@ static inline int early_cpu_to_node(int cpu)
}
/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
-static inline const cpumask_t *_node_to_cpumask_ptr(int node)
+static inline const cpumask_t *cpumask_of_node(int node)
{
return &node_to_cpumask_map[node];
}
@@ -116,12 +122,15 @@ static inline cpumask_t node_to_cpumask(int node)
#endif /* !CONFIG_DEBUG_PER_CPU_MAPS */
-/* Replace default node_to_cpumask_ptr with optimized version */
+/*
+ * Replace default node_to_cpumask_ptr with optimized version
+ * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)"
+ */
#define node_to_cpumask_ptr(v, node) \
- const cpumask_t *v = _node_to_cpumask_ptr(node)
+ const cpumask_t *v = cpumask_of_node(node)
#define node_to_cpumask_ptr_next(v, node) \
- v = _node_to_cpumask_ptr(node)
+ v = cpumask_of_node(node)
#endif /* CONFIG_X86_64 */
@@ -187,7 +196,7 @@ extern int __node_distance(int, int);
#define cpu_to_node(cpu) 0
#define early_cpu_to_node(cpu) 0
-static inline const cpumask_t *_node_to_cpumask_ptr(int node)
+static inline const cpumask_t *cpumask_of_node(int node)
{
return &cpu_online_map;
}
@@ -200,12 +209,15 @@ static inline int node_to_first_cpu(int node)
return first_cpu(cpu_online_map);
}
-/* Replace default node_to_cpumask_ptr with optimized version */
+/*
+ * Replace default node_to_cpumask_ptr with optimized version
+ * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)"
+ */
#define node_to_cpumask_ptr(v, node) \
- const cpumask_t *v = _node_to_cpumask_ptr(node)
+ const cpumask_t *v = cpumask_of_node(node)
#define node_to_cpumask_ptr_next(v, node) \
- v = _node_to_cpumask_ptr(node)
+ v = cpumask_of_node(node)
#endif
#include <asm-generic/topology.h>
@@ -214,18 +226,20 @@ static inline int node_to_first_cpu(int node)
/* Returns the number of the first CPU on Node 'node'. */
static inline int node_to_first_cpu(int node)
{
- node_to_cpumask_ptr(mask, node);
- return first_cpu(*mask);
+ return cpumask_first(cpumask_of_node(node));
}
#endif
extern cpumask_t cpu_coregroup_map(int cpu);
+extern const struct cpumask *cpu_coregroup_mask(int cpu);
#ifdef ENABLE_TOPO_DEFINES
#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id)
#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
#define topology_core_siblings(cpu) (per_cpu(cpu_core_map, cpu))
#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu))
+#define topology_core_cpumask(cpu) (&per_cpu(cpu_core_map, cpu))
+#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
/* indicates that pointers to the topology cpumask_t maps are valid */
#define arch_provides_topology_pointers yes
diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h
deleted file mode 100644
index 8b064bd9c553..000000000000
--- a/arch/x86/include/asm/unwind.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _ASM_X86_UNWIND_H
-#define _ASM_X86_UNWIND_H
-
-#define UNW_PC(frame) ((void)(frame), 0UL)
-#define UNW_SP(frame) ((void)(frame), 0UL)
-#define UNW_FP(frame) ((void)(frame), 0UL)
-
-static inline int arch_unw_user_mode(const void *info)
-{
- return 0;
-}
-
-#endif /* _ASM_X86_UNWIND_H */
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index e2363253bbbf..50423c7b56b2 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -133,61 +133,61 @@ struct bau_msg_payload {
* see table 4.2.3.0.1 in broacast_assist spec.
*/
struct bau_msg_header {
- int dest_subnodeid:6; /* must be zero */
+ unsigned int dest_subnodeid:6; /* must be zero */
/* bits 5:0 */
- int base_dest_nodeid:15; /* nasid>>1 (pnode) of first bit in node_map */
- /* bits 20:6 */
- int command:8; /* message type */
+ unsigned int base_dest_nodeid:15; /* nasid>>1 (pnode) of */
+ /* bits 20:6 */ /* first bit in node_map */
+ unsigned int command:8; /* message type */
/* bits 28:21 */
/* 0x38: SN3net EndPoint Message */
- int rsvd_1:3; /* must be zero */
+ unsigned int rsvd_1:3; /* must be zero */
/* bits 31:29 */
/* int will align on 32 bits */
- int rsvd_2:9; /* must be zero */
+ unsigned int rsvd_2:9; /* must be zero */
/* bits 40:32 */
/* Suppl_A is 56-41 */
- int payload_2a:8; /* becomes byte 16 of msg */
+ unsigned int payload_2a:8;/* becomes byte 16 of msg */
/* bits 48:41 */ /* not currently using */
- int payload_2b:8; /* becomes byte 17 of msg */
+ unsigned int payload_2b:8;/* becomes byte 17 of msg */
/* bits 56:49 */ /* not currently using */
/* Address field (96:57) is never used as an
address (these are address bits 42:3) */
- int rsvd_3:1; /* must be zero */
+ unsigned int rsvd_3:1; /* must be zero */
/* bit 57 */
/* address bits 27:4 are payload */
/* these 24 bits become bytes 12-14 of msg */
- int replied_to:1; /* sent as 0 by the source to byte 12 */
+ unsigned int replied_to:1;/* sent as 0 by the source to byte 12 */
/* bit 58 */
- int payload_1a:5; /* not currently used */
+ unsigned int payload_1a:5;/* not currently used */
/* bits 63:59 */
- int payload_1b:8; /* not currently used */
+ unsigned int payload_1b:8;/* not currently used */
/* bits 71:64 */
- int payload_1c:8; /* not currently used */
+ unsigned int payload_1c:8;/* not currently used */
/* bits 79:72 */
- int payload_1d:2; /* not currently used */
+ unsigned int payload_1d:2;/* not currently used */
/* bits 81:80 */
- int rsvd_4:7; /* must be zero */
+ unsigned int rsvd_4:7; /* must be zero */
/* bits 88:82 */
- int sw_ack_flag:1; /* software acknowledge flag */
+ unsigned int sw_ack_flag:1;/* software acknowledge flag */
/* bit 89 */
/* INTD trasactions at destination are to
wait for software acknowledge */
- int rsvd_5:6; /* must be zero */
+ unsigned int rsvd_5:6; /* must be zero */
/* bits 95:90 */
- int rsvd_6:5; /* must be zero */
+ unsigned int rsvd_6:5; /* must be zero */
/* bits 100:96 */
- int int_both:1; /* if 1, interrupt both sockets on the blade */
+ unsigned int int_both:1;/* if 1, interrupt both sockets on the blade */
/* bit 101*/
- int fairness:3; /* usually zero */
+ unsigned int fairness:3;/* usually zero */
/* bits 104:102 */
- int multilevel:1; /* multi-level multicast format */
+ unsigned int multilevel:1; /* multi-level multicast format */
/* bit 105 */
/* 0 for TLB: endpoint multi-unicast messages */
- int chaining:1; /* next descriptor is part of this activation*/
+ unsigned int chaining:1;/* next descriptor is part of this activation*/
/* bit 106 */
- int rsvd_7:21; /* must be zero */
+ unsigned int rsvd_7:21; /* must be zero */
/* bits 127:107 */
};
diff --git a/arch/x86/include/asm/virtext.h b/arch/x86/include/asm/virtext.h
new file mode 100644
index 000000000000..593636275238
--- /dev/null
+++ b/arch/x86/include/asm/virtext.h
@@ -0,0 +1,132 @@
+/* CPU virtualization extensions handling
+ *
+ * This should carry the code for handling CPU virtualization extensions
+ * that needs to live in the kernel core.
+ *
+ * Author: Eduardo Habkost <ehabkost@redhat.com>
+ *
+ * Copyright (C) 2008, Red Hat Inc.
+ *
+ * Contains code from KVM, Copyright (C) 2006 Qumranet, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef _ASM_X86_VIRTEX_H
+#define _ASM_X86_VIRTEX_H
+
+#include <asm/processor.h>
+#include <asm/system.h>
+
+#include <asm/vmx.h>
+#include <asm/svm.h>
+
+/*
+ * VMX functions:
+ */
+
+static inline int cpu_has_vmx(void)
+{
+ unsigned long ecx = cpuid_ecx(1);
+ return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */
+}
+
+
+/** Disable VMX on the current CPU
+ *
+ * vmxoff causes a undefined-opcode exception if vmxon was not run
+ * on the CPU previously. Only call this function if you know VMX
+ * is enabled.
+ */
+static inline void cpu_vmxoff(void)
+{
+ asm volatile (ASM_VMX_VMXOFF : : : "cc");
+ write_cr4(read_cr4() & ~X86_CR4_VMXE);
+}
+
+static inline int cpu_vmx_enabled(void)
+{
+ return read_cr4() & X86_CR4_VMXE;
+}
+
+/** Disable VMX if it is enabled on the current CPU
+ *
+ * You shouldn't call this if cpu_has_vmx() returns 0.
+ */
+static inline void __cpu_emergency_vmxoff(void)
+{
+ if (cpu_vmx_enabled())
+ cpu_vmxoff();
+}
+
+/** Disable VMX if it is supported and enabled on the current CPU
+ */
+static inline void cpu_emergency_vmxoff(void)
+{
+ if (cpu_has_vmx())
+ __cpu_emergency_vmxoff();
+}
+
+
+
+
+/*
+ * SVM functions:
+ */
+
+/** Check if the CPU has SVM support
+ *
+ * You can use the 'msg' arg to get a message describing the problem,
+ * if the function returns zero. Simply pass NULL if you are not interested
+ * on the messages; gcc should take care of not generating code for
+ * the messages on this case.
+ */
+static inline int cpu_has_svm(const char **msg)
+{
+ uint32_t eax, ebx, ecx, edx;
+
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
+ if (msg)
+ *msg = "not amd";
+ return 0;
+ }
+
+ cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
+ if (eax < SVM_CPUID_FUNC) {
+ if (msg)
+ *msg = "can't execute cpuid_8000000a";
+ return 0;
+ }
+
+ cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
+ if (!(ecx & (1 << SVM_CPUID_FEATURE_SHIFT))) {
+ if (msg)
+ *msg = "svm not available";
+ return 0;
+ }
+ return 1;
+}
+
+
+/** Disable SVM on the current CPU
+ *
+ * You should call this only if cpu_has_svm() returned true.
+ */
+static inline void cpu_svm_disable(void)
+{
+ uint64_t efer;
+
+ wrmsrl(MSR_VM_HSAVE_PA, 0);
+ rdmsrl(MSR_EFER, efer);
+ wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
+}
+
+/** Makes sure SVM is disabled, if it is supported on the CPU
+ */
+static inline void cpu_emergency_svm_disable(void)
+{
+ if (cpu_has_svm(NULL))
+ cpu_svm_disable();
+}
+
+#endif /* _ASM_X86_VIRTEX_H */
diff --git a/arch/x86/kvm/vmx.h b/arch/x86/include/asm/vmx.h
index ec5edc339da6..d0238e6151d8 100644
--- a/arch/x86/kvm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -63,10 +63,13 @@
#define VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200
#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
+#define VM_EXIT_SAVE_IA32_PAT 0x00040000
+#define VM_EXIT_LOAD_IA32_PAT 0x00080000
#define VM_ENTRY_IA32E_MODE 0x00000200
#define VM_ENTRY_SMM 0x00000400
#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
+#define VM_ENTRY_LOAD_IA32_PAT 0x00004000
/* VMCS Encodings */
enum vmcs_field {
@@ -112,6 +115,8 @@ enum vmcs_field {
VMCS_LINK_POINTER_HIGH = 0x00002801,
GUEST_IA32_DEBUGCTL = 0x00002802,
GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
+ GUEST_IA32_PAT = 0x00002804,
+ GUEST_IA32_PAT_HIGH = 0x00002805,
GUEST_PDPTR0 = 0x0000280a,
GUEST_PDPTR0_HIGH = 0x0000280b,
GUEST_PDPTR1 = 0x0000280c,
@@ -120,6 +125,8 @@ enum vmcs_field {
GUEST_PDPTR2_HIGH = 0x0000280f,
GUEST_PDPTR3 = 0x00002810,
GUEST_PDPTR3_HIGH = 0x00002811,
+ HOST_IA32_PAT = 0x00002c00,
+ HOST_IA32_PAT_HIGH = 0x00002c01,
PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
EXCEPTION_BITMAP = 0x00004004,
@@ -331,8 +338,9 @@ enum vmcs_field {
#define AR_RESERVD_MASK 0xfffe0f00
-#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT 9
-#define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT 10
+#define TSS_PRIVATE_MEMSLOT (KVM_MEMORY_SLOTS + 0)
+#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (KVM_MEMORY_SLOTS + 1)
+#define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT (KVM_MEMORY_SLOTS + 2)
#define VMX_NR_VPIDS (1 << 16)
#define VMX_VPID_EXTENT_SINGLE_CONTEXT 1
@@ -356,4 +364,19 @@ enum vmcs_field {
#define VMX_EPT_IDENTITY_PAGETABLE_ADDR 0xfffbc000ul
+
+#define ASM_VMX_VMCLEAR_RAX ".byte 0x66, 0x0f, 0xc7, 0x30"
+#define ASM_VMX_VMLAUNCH ".byte 0x0f, 0x01, 0xc2"
+#define ASM_VMX_VMRESUME ".byte 0x0f, 0x01, 0xc3"
+#define ASM_VMX_VMPTRLD_RAX ".byte 0x0f, 0xc7, 0x30"
+#define ASM_VMX_VMREAD_RDX_RAX ".byte 0x0f, 0x78, 0xd0"
+#define ASM_VMX_VMWRITE_RAX_RDX ".byte 0x0f, 0x79, 0xd0"
+#define ASM_VMX_VMWRITE_RSP_RDX ".byte 0x0f, 0x79, 0xd4"
+#define ASM_VMX_VMXOFF ".byte 0x0f, 0x01, 0xc4"
+#define ASM_VMX_VMXON_RAX ".byte 0xf3, 0x0f, 0xc7, 0x30"
+#define ASM_VMX_INVEPT ".byte 0x66, 0x0f, 0x38, 0x80, 0x08"
+#define ASM_VMX_INVVPID ".byte 0x66, 0x0f, 0x38, 0x81, 0x08"
+
+
+
#endif
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 65d0b72777ea..d37593c2f438 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -47,7 +47,7 @@
#endif
static int __initdata acpi_force = 0;
-
+u32 acpi_rsdt_forced;
#ifdef CONFIG_ACPI
int acpi_disabled = 0;
#else
@@ -538,9 +538,10 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
struct acpi_madt_local_apic *lapic;
- cpumask_t tmp_map, new_map;
+ cpumask_var_t tmp_map, new_map;
u8 physid;
int cpu;
+ int retval = -ENOMEM;
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
return -EINVAL;
@@ -569,23 +570,37 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
buffer.length = ACPI_ALLOCATE_BUFFER;
buffer.pointer = NULL;
- tmp_map = cpu_present_map;
+ if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
+ goto out;
+
+ if (!alloc_cpumask_var(&new_map, GFP_KERNEL))
+ goto free_tmp_map;
+
+ cpumask_copy(tmp_map, cpu_present_mask);
acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
/*
* If mp_register_lapic successfully generates a new logical cpu
* number, then the following will get us exactly what was mapped
*/
- cpus_andnot(new_map, cpu_present_map, tmp_map);
- if (cpus_empty(new_map)) {
+ cpumask_andnot(new_map, cpu_present_mask, tmp_map);
+ if (cpumask_empty(new_map)) {
printk ("Unable to map lapic to logical cpu number\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto free_new_map;
}
- cpu = first_cpu(new_map);
+ cpu = cpumask_first(new_map);
*pcpu = cpu;
- return 0;
+ retval = 0;
+
+free_new_map:
+ free_cpumask_var(new_map);
+free_tmp_map:
+ free_cpumask_var(tmp_map);
+out:
+ return retval;
}
/* wrapper to silence section mismatch warning */
@@ -598,7 +613,7 @@ EXPORT_SYMBOL(acpi_map_lsapic);
int acpi_unmap_lsapic(int cpu)
{
per_cpu(x86_cpu_to_apicid, cpu) = -1;
- cpu_clear(cpu, cpu_present_map);
+ set_cpu_present(cpu, false);
num_processors--;
return (0);
@@ -1359,6 +1374,17 @@ static void __init acpi_process_madt(void)
"Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
+ } else {
+ /*
+ * ACPI found no MADT, and so ACPI wants UP PIC mode.
+ * In the event an MPS table was found, forget it.
+ * Boot with "acpi=off" to use MPS on such a system.
+ */
+ if (smp_found_config) {
+ printk(KERN_WARNING PREFIX
+ "No APIC-table, disabling MPS\n");
+ smp_found_config = 0;
+ }
}
/*
@@ -1794,6 +1820,10 @@ static int __init parse_acpi(char *arg)
disable_acpi();
acpi_ht = 1;
}
+ /* acpi=rsdt use RSDT instead of XSDT */
+ else if (strcmp(arg, "rsdt") == 0) {
+ acpi_rsdt_forced = 1;
+ }
/* "acpi=noirq" disables ACPI interrupt routing */
else if (strcmp(arg, "noirq") == 0) {
acpi_noirq_set();
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index c2502eb9aa83..bbbe4bbb6f34 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -56,6 +56,7 @@ static struct cstate_entry *cpu_cstate_entry; /* per CPU ptr */
static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
#define MWAIT_SUBSTATE_MASK (0xf)
+#define MWAIT_CSTATE_MASK (0xf)
#define MWAIT_SUBSTATE_SIZE (4)
#define CPUID_MWAIT_LEAF (5)
@@ -66,39 +67,20 @@ static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
#define NATIVE_CSTATE_BEYOND_HALT (2)
-int acpi_processor_ffh_cstate_probe(unsigned int cpu,
- struct acpi_processor_cx *cx, struct acpi_power_register *reg)
+static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
{
- struct cstate_entry *percpu_entry;
- struct cpuinfo_x86 *c = &cpu_data(cpu);
-
- cpumask_t saved_mask;
- int retval;
+ struct acpi_processor_cx *cx = _cx;
+ long retval;
unsigned int eax, ebx, ecx, edx;
unsigned int edx_part;
unsigned int cstate_type; /* C-state type and not ACPI C-state type */
unsigned int num_cstate_subtype;
- if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF )
- return -1;
-
- if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
- return -1;
-
- percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
- percpu_entry->states[cx->index].eax = 0;
- percpu_entry->states[cx->index].ecx = 0;
-
- /* Make sure we are running on right CPU */
- saved_mask = current->cpus_allowed;
- retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (retval)
- return -1;
-
cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
/* Check whether this particular cx_type (in CST) is supported or not */
- cstate_type = (cx->address >> MWAIT_SUBSTATE_SIZE) + 1;
+ cstate_type = ((cx->address >> MWAIT_SUBSTATE_SIZE) &
+ MWAIT_CSTATE_MASK) + 1;
edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
@@ -114,21 +96,45 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu,
retval = -1;
goto out;
}
- percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
-
- /* Use the hint in CST */
- percpu_entry->states[cx->index].eax = cx->address;
if (!mwait_supported[cstate_type]) {
mwait_supported[cstate_type] = 1;
- printk(KERN_DEBUG "Monitor-Mwait will be used to enter C-%d "
- "state\n", cx->type);
+ printk(KERN_DEBUG
+ "Monitor-Mwait will be used to enter C-%d "
+ "state\n", cx->type);
}
- snprintf(cx->desc, ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
- cx->address);
-
+ snprintf(cx->desc,
+ ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
+ cx->address);
out:
- set_cpus_allowed_ptr(current, &saved_mask);
+ return retval;
+}
+
+int acpi_processor_ffh_cstate_probe(unsigned int cpu,
+ struct acpi_processor_cx *cx, struct acpi_power_register *reg)
+{
+ struct cstate_entry *percpu_entry;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+ long retval;
+
+ if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF)
+ return -1;
+
+ if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
+ return -1;
+
+ percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
+ percpu_entry->states[cx->index].eax = 0;
+ percpu_entry->states[cx->index].ecx = 0;
+
+ /* Make sure we are running on right CPU */
+
+ retval = work_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx);
+ if (retval == 0) {
+ /* Use the hint in CST */
+ percpu_entry->states[cx->index].eax = cx->address;
+ percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
+ }
return retval;
}
EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 806b4e9051b4..707c1f6f95fa 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -159,6 +159,8 @@ static int __init acpi_sleep_setup(char *str)
#endif
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
+ if (strncmp(str, "s4_nonvs", 8) == 0)
+ acpi_s4_no_nvs();
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 2e2da717b350..5113c080f0c4 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -20,8 +20,12 @@
#include <linux/pci.h>
#include <linux/gfp.h>
#include <linux/bitops.h>
+#include <linux/debugfs.h>
#include <linux/scatterlist.h>
#include <linux/iommu-helper.h>
+#ifdef CONFIG_IOMMU_API
+#include <linux/iommu.h>
+#endif
#include <asm/proto.h>
#include <asm/iommu.h>
#include <asm/gart.h>
@@ -38,6 +42,10 @@ static DEFINE_RWLOCK(amd_iommu_devtable_lock);
static LIST_HEAD(iommu_pd_list);
static DEFINE_SPINLOCK(iommu_pd_list_lock);
+#ifdef CONFIG_IOMMU_API
+static struct iommu_ops amd_iommu_ops;
+#endif
+
/*
* general struct to manage commands send to an IOMMU
*/
@@ -47,6 +55,68 @@ struct iommu_cmd {
static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
struct unity_map_entry *e);
+static struct dma_ops_domain *find_protection_domain(u16 devid);
+
+
+#ifdef CONFIG_AMD_IOMMU_STATS
+
+/*
+ * Initialization code for statistics collection
+ */
+
+DECLARE_STATS_COUNTER(compl_wait);
+DECLARE_STATS_COUNTER(cnt_map_single);
+DECLARE_STATS_COUNTER(cnt_unmap_single);
+DECLARE_STATS_COUNTER(cnt_map_sg);
+DECLARE_STATS_COUNTER(cnt_unmap_sg);
+DECLARE_STATS_COUNTER(cnt_alloc_coherent);
+DECLARE_STATS_COUNTER(cnt_free_coherent);
+DECLARE_STATS_COUNTER(cross_page);
+DECLARE_STATS_COUNTER(domain_flush_single);
+DECLARE_STATS_COUNTER(domain_flush_all);
+DECLARE_STATS_COUNTER(alloced_io_mem);
+DECLARE_STATS_COUNTER(total_map_requests);
+
+static struct dentry *stats_dir;
+static struct dentry *de_isolate;
+static struct dentry *de_fflush;
+
+static void amd_iommu_stats_add(struct __iommu_counter *cnt)
+{
+ if (stats_dir == NULL)
+ return;
+
+ cnt->dent = debugfs_create_u64(cnt->name, 0444, stats_dir,
+ &cnt->value);
+}
+
+static void amd_iommu_stats_init(void)
+{
+ stats_dir = debugfs_create_dir("amd-iommu", NULL);
+ if (stats_dir == NULL)
+ return;
+
+ de_isolate = debugfs_create_bool("isolation", 0444, stats_dir,
+ (u32 *)&amd_iommu_isolate);
+
+ de_fflush = debugfs_create_bool("fullflush", 0444, stats_dir,
+ (u32 *)&amd_iommu_unmap_flush);
+
+ amd_iommu_stats_add(&compl_wait);
+ amd_iommu_stats_add(&cnt_map_single);
+ amd_iommu_stats_add(&cnt_unmap_single);
+ amd_iommu_stats_add(&cnt_map_sg);
+ amd_iommu_stats_add(&cnt_unmap_sg);
+ amd_iommu_stats_add(&cnt_alloc_coherent);
+ amd_iommu_stats_add(&cnt_free_coherent);
+ amd_iommu_stats_add(&cross_page);
+ amd_iommu_stats_add(&domain_flush_single);
+ amd_iommu_stats_add(&domain_flush_all);
+ amd_iommu_stats_add(&alloced_io_mem);
+ amd_iommu_stats_add(&total_map_requests);
+}
+
+#endif
/* returns !0 if the IOMMU is caching non-present entries in its TLB */
static int iommu_has_npcache(struct amd_iommu *iommu)
@@ -189,13 +259,55 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
spin_lock_irqsave(&iommu->lock, flags);
ret = __iommu_queue_command(iommu, cmd);
if (!ret)
- iommu->need_sync = 1;
+ iommu->need_sync = true;
spin_unlock_irqrestore(&iommu->lock, flags);
return ret;
}
/*
+ * This function waits until an IOMMU has completed a completion
+ * wait command
+ */
+static void __iommu_wait_for_completion(struct amd_iommu *iommu)
+{
+ int ready = 0;
+ unsigned status = 0;
+ unsigned long i = 0;
+
+ INC_STATS_COUNTER(compl_wait);
+
+ while (!ready && (i < EXIT_LOOP_COUNT)) {
+ ++i;
+ /* wait for the bit to become one */
+ status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
+ ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
+ }
+
+ /* set bit back to zero */
+ status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
+ writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
+
+ if (unlikely(i == EXIT_LOOP_COUNT))
+ panic("AMD IOMMU: Completion wait loop failed\n");
+}
+
+/*
+ * This function queues a completion wait command into the command
+ * buffer of an IOMMU
+ */
+static int __iommu_completion_wait(struct amd_iommu *iommu)
+{
+ struct iommu_cmd cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
+ CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
+
+ return __iommu_queue_command(iommu, &cmd);
+}
+
+/*
* This function is called whenever we need to ensure that the IOMMU has
* completed execution of all commands we sent. It sends a
* COMPLETION_WAIT command and waits for it to finish. The IOMMU informs
@@ -204,40 +316,22 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
*/
static int iommu_completion_wait(struct amd_iommu *iommu)
{
- int ret = 0, ready = 0;
- unsigned status = 0;
- struct iommu_cmd cmd;
- unsigned long flags, i = 0;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
- CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
+ int ret = 0;
+ unsigned long flags;
spin_lock_irqsave(&iommu->lock, flags);
if (!iommu->need_sync)
goto out;
- iommu->need_sync = 0;
+ ret = __iommu_completion_wait(iommu);
- ret = __iommu_queue_command(iommu, &cmd);
+ iommu->need_sync = false;
if (ret)
goto out;
- while (!ready && (i < EXIT_LOOP_COUNT)) {
- ++i;
- /* wait for the bit to become one */
- status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
- ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
- }
-
- /* set bit back to zero */
- status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
- writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
-
- if (unlikely(i == EXIT_LOOP_COUNT))
- panic("AMD IOMMU: Completion wait loop failed\n");
+ __iommu_wait_for_completion(iommu);
out:
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -264,6 +358,21 @@ static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid)
return ret;
}
+static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
+ u16 domid, int pde, int s)
+{
+ memset(cmd, 0, sizeof(*cmd));
+ address &= PAGE_MASK;
+ CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
+ cmd->data[1] |= domid;
+ cmd->data[2] = lower_32_bits(address);
+ cmd->data[3] = upper_32_bits(address);
+ if (s) /* size bit - we flush more than one 4kb page */
+ cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
+ if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
+ cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
+}
+
/*
* Generic command send function for invalidaing TLB entries
*/
@@ -273,16 +382,7 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,
struct iommu_cmd cmd;
int ret;
- memset(&cmd, 0, sizeof(cmd));
- address &= PAGE_MASK;
- CMD_SET_TYPE(&cmd, CMD_INV_IOMMU_PAGES);
- cmd.data[1] |= domid;
- cmd.data[2] = lower_32_bits(address);
- cmd.data[3] = upper_32_bits(address);
- if (s) /* size bit - we flush more than one 4kb page */
- cmd.data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
- if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
- cmd.data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
+ __iommu_build_inv_iommu_pages(&cmd, address, domid, pde, s);
ret = iommu_queue_command(iommu, &cmd);
@@ -321,9 +421,35 @@ static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
{
u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS;
+ INC_STATS_COUNTER(domain_flush_single);
+
iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1);
}
+/*
+ * This function is used to flush the IO/TLB for a given protection domain
+ * on every IOMMU in the system
+ */
+static void iommu_flush_domain(u16 domid)
+{
+ unsigned long flags;
+ struct amd_iommu *iommu;
+ struct iommu_cmd cmd;
+
+ INC_STATS_COUNTER(domain_flush_all);
+
+ __iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+ domid, 1, 1);
+
+ list_for_each_entry(iommu, &amd_iommu_list, list) {
+ spin_lock_irqsave(&iommu->lock, flags);
+ __iommu_queue_command(iommu, &cmd);
+ __iommu_completion_wait(iommu);
+ __iommu_wait_for_completion(iommu);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ }
+}
+
/****************************************************************************
*
* The functions below are used the create the page table mappings for
@@ -338,10 +464,10 @@ static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid)
* supporting all features of AMD IOMMU page tables like level skipping
* and full 64 bit address spaces.
*/
-static int iommu_map(struct protection_domain *dom,
- unsigned long bus_addr,
- unsigned long phys_addr,
- int prot)
+static int iommu_map_page(struct protection_domain *dom,
+ unsigned long bus_addr,
+ unsigned long phys_addr,
+ int prot)
{
u64 __pte, *pte, *page;
@@ -388,6 +514,28 @@ static int iommu_map(struct protection_domain *dom,
return 0;
}
+static void iommu_unmap_page(struct protection_domain *dom,
+ unsigned long bus_addr)
+{
+ u64 *pte;
+
+ pte = &dom->pt_root[IOMMU_PTE_L2_INDEX(bus_addr)];
+
+ if (!IOMMU_PTE_PRESENT(*pte))
+ return;
+
+ pte = IOMMU_PTE_PAGE(*pte);
+ pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
+
+ if (!IOMMU_PTE_PRESENT(*pte))
+ return;
+
+ pte = IOMMU_PTE_PAGE(*pte);
+ pte = &pte[IOMMU_PTE_L1_INDEX(bus_addr)];
+
+ *pte = 0;
+}
+
/*
* This function checks if a specific unity mapping entry is needed for
* this specific IOMMU.
@@ -440,7 +588,7 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,
for (addr = e->address_start; addr < e->address_end;
addr += PAGE_SIZE) {
- ret = iommu_map(&dma_dom->domain, addr, addr, e->prot);
+ ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot);
if (ret)
return ret;
/*
@@ -571,6 +719,16 @@ static u16 domain_id_alloc(void)
return id;
}
+static void domain_id_free(int id)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ if (id > 0 && id < MAX_DOMAIN_ID)
+ __clear_bit(id, amd_iommu_pd_alloc_bitmap);
+ write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
/*
* Used to reserve address ranges in the aperture (e.g. for exclusion
* ranges.
@@ -587,12 +745,12 @@ static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
iommu_area_reserve(dom->bitmap, start_page, pages);
}
-static void dma_ops_free_pagetable(struct dma_ops_domain *dma_dom)
+static void free_pagetable(struct protection_domain *domain)
{
int i, j;
u64 *p1, *p2, *p3;
- p1 = dma_dom->domain.pt_root;
+ p1 = domain->pt_root;
if (!p1)
return;
@@ -613,6 +771,8 @@ static void dma_ops_free_pagetable(struct dma_ops_domain *dma_dom)
}
free_page((unsigned long)p1);
+
+ domain->pt_root = NULL;
}
/*
@@ -624,7 +784,7 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)
if (!dom)
return;
- dma_ops_free_pagetable(dom);
+ free_pagetable(&dom->domain);
kfree(dom->pte_pages);
@@ -663,6 +823,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu,
goto free_dma_dom;
dma_dom->domain.mode = PAGE_MODE_3_LEVEL;
dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+ dma_dom->domain.flags = PD_DMA_OPS_MASK;
dma_dom->domain.priv = dma_dom;
if (!dma_dom->domain.pt_root)
goto free_dma_dom;
@@ -725,6 +886,15 @@ free_dma_dom:
}
/*
+ * little helper function to check whether a given protection domain is a
+ * dma_ops domain
+ */
+static bool dma_ops_domain(struct protection_domain *domain)
+{
+ return domain->flags & PD_DMA_OPS_MASK;
+}
+
+/*
* Find out the protection domain structure for a given PCI device. This
* will give us the pointer to the page table root for example.
*/
@@ -744,14 +914,15 @@ static struct protection_domain *domain_for_device(u16 devid)
* If a device is not yet associated with a domain, this function does
* assigns it visible for the hardware
*/
-static void set_device_domain(struct amd_iommu *iommu,
- struct protection_domain *domain,
- u16 devid)
+static void attach_device(struct amd_iommu *iommu,
+ struct protection_domain *domain,
+ u16 devid)
{
unsigned long flags;
-
u64 pte_root = virt_to_phys(domain->pt_root);
+ domain->dev_cnt += 1;
+
pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
<< DEV_ENTRY_MODE_SHIFT;
pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
@@ -767,6 +938,116 @@ static void set_device_domain(struct amd_iommu *iommu,
iommu_queue_inv_dev_entry(iommu, devid);
}
+/*
+ * Removes a device from a protection domain (unlocked)
+ */
+static void __detach_device(struct protection_domain *domain, u16 devid)
+{
+
+ /* lock domain */
+ spin_lock(&domain->lock);
+
+ /* remove domain from the lookup table */
+ amd_iommu_pd_table[devid] = NULL;
+
+ /* remove entry from the device table seen by the hardware */
+ amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
+ amd_iommu_dev_table[devid].data[1] = 0;
+ amd_iommu_dev_table[devid].data[2] = 0;
+
+ /* decrease reference counter */
+ domain->dev_cnt -= 1;
+
+ /* ready */
+ spin_unlock(&domain->lock);
+}
+
+/*
+ * Removes a device from a protection domain (with devtable_lock held)
+ */
+static void detach_device(struct protection_domain *domain, u16 devid)
+{
+ unsigned long flags;
+
+ /* lock device table */
+ write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+ __detach_device(domain, devid);
+ write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
+static int device_change_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ u16 devid = calc_devid(pdev->bus->number, pdev->devfn);
+ struct protection_domain *domain;
+ struct dma_ops_domain *dma_domain;
+ struct amd_iommu *iommu;
+ int order = amd_iommu_aperture_order;
+ unsigned long flags;
+
+ if (devid > amd_iommu_last_bdf)
+ goto out;
+
+ devid = amd_iommu_alias_table[devid];
+
+ iommu = amd_iommu_rlookup_table[devid];
+ if (iommu == NULL)
+ goto out;
+
+ domain = domain_for_device(devid);
+
+ if (domain && !dma_ops_domain(domain))
+ WARN_ONCE(1, "AMD IOMMU WARNING: device %s already bound "
+ "to a non-dma-ops domain\n", dev_name(dev));
+
+ switch (action) {
+ case BUS_NOTIFY_BOUND_DRIVER:
+ if (domain)
+ goto out;
+ dma_domain = find_protection_domain(devid);
+ if (!dma_domain)
+ dma_domain = iommu->default_dom;
+ attach_device(iommu, &dma_domain->domain, devid);
+ printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
+ "device %s\n", dma_domain->domain.id, dev_name(dev));
+ break;
+ case BUS_NOTIFY_UNBIND_DRIVER:
+ if (!domain)
+ goto out;
+ detach_device(domain, devid);
+ break;
+ case BUS_NOTIFY_ADD_DEVICE:
+ /* allocate a protection domain if a device is added */
+ dma_domain = find_protection_domain(devid);
+ if (dma_domain)
+ goto out;
+ dma_domain = dma_ops_domain_alloc(iommu, order);
+ if (!dma_domain)
+ goto out;
+ dma_domain->target_dev = devid;
+
+ spin_lock_irqsave(&iommu_pd_list_lock, flags);
+ list_add_tail(&dma_domain->list, &iommu_pd_list);
+ spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+
+ break;
+ default:
+ goto out;
+ }
+
+ iommu_queue_inv_dev_entry(iommu, devid);
+ iommu_completion_wait(iommu);
+
+out:
+ return 0;
+}
+
+struct notifier_block device_nb = {
+ .notifier_call = device_change_notifier,
+};
+
/*****************************************************************************
*
* The next functions belong to the dma_ops mapping/unmapping code.
@@ -802,7 +1083,6 @@ static struct dma_ops_domain *find_protection_domain(u16 devid)
list_for_each_entry(entry, &iommu_pd_list, list) {
if (entry->target_dev == devid) {
ret = entry;
- list_del(&ret->list);
break;
}
}
@@ -853,14 +1133,13 @@ static int get_device_resources(struct device *dev,
if (!dma_dom)
dma_dom = (*iommu)->default_dom;
*domain = &dma_dom->domain;
- set_device_domain(*iommu, *domain, *bdf);
+ attach_device(*iommu, *domain, *bdf);
printk(KERN_INFO "AMD IOMMU: Using protection domain %d for "
- "device ", (*domain)->id);
- print_devid(_bdf, 1);
+ "device %s\n", (*domain)->id, dev_name(dev));
}
if (domain_for_device(_bdf) == NULL)
- set_device_domain(*iommu, *domain, _bdf);
+ attach_device(*iommu, *domain, _bdf);
return 1;
}
@@ -946,6 +1225,11 @@ static dma_addr_t __map_single(struct device *dev,
pages = iommu_num_pages(paddr, size, PAGE_SIZE);
paddr &= PAGE_MASK;
+ INC_STATS_COUNTER(total_map_requests);
+
+ if (pages > 1)
+ INC_STATS_COUNTER(cross_page);
+
if (align)
align_mask = (1UL << get_order(size)) - 1;
@@ -962,6 +1246,8 @@ static dma_addr_t __map_single(struct device *dev,
}
address += offset;
+ ADD_STATS_COUNTER(alloced_io_mem, size);
+
if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) {
iommu_flush_tlb(iommu, dma_dom->domain.id);
dma_dom->need_flush = false;
@@ -998,6 +1284,8 @@ static void __unmap_single(struct amd_iommu *iommu,
start += PAGE_SIZE;
}
+ SUB_STATS_COUNTER(alloced_io_mem, size);
+
dma_ops_free_addresses(dma_dom, dma_addr, pages);
if (amd_iommu_unmap_flush || dma_dom->need_flush) {
@@ -1019,6 +1307,8 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
dma_addr_t addr;
u64 dma_mask;
+ INC_STATS_COUNTER(cnt_map_single);
+
if (!check_device(dev))
return bad_dma_address;
@@ -1030,6 +1320,9 @@ static dma_addr_t map_single(struct device *dev, phys_addr_t paddr,
/* device not handled by any AMD IOMMU */
return (dma_addr_t)paddr;
+ if (!dma_ops_domain(domain))
+ return bad_dma_address;
+
spin_lock_irqsave(&domain->lock, flags);
addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false,
dma_mask);
@@ -1055,11 +1348,16 @@ static void unmap_single(struct device *dev, dma_addr_t dma_addr,
struct protection_domain *domain;
u16 devid;
+ INC_STATS_COUNTER(cnt_unmap_single);
+
if (!check_device(dev) ||
!get_device_resources(dev, &iommu, &domain, &devid))
/* device not handled by any AMD IOMMU */
return;
+ if (!dma_ops_domain(domain))
+ return;
+
spin_lock_irqsave(&domain->lock, flags);
__unmap_single(iommu, domain->priv, dma_addr, size, dir);
@@ -1104,6 +1402,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
int mapped_elems = 0;
u64 dma_mask;
+ INC_STATS_COUNTER(cnt_map_sg);
+
if (!check_device(dev))
return 0;
@@ -1114,6 +1414,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
if (!iommu || !domain)
return map_sg_no_iommu(dev, sglist, nelems, dir);
+ if (!dma_ops_domain(domain))
+ return 0;
+
spin_lock_irqsave(&domain->lock, flags);
for_each_sg(sglist, s, nelems, i) {
@@ -1163,10 +1466,15 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
u16 devid;
int i;
+ INC_STATS_COUNTER(cnt_unmap_sg);
+
if (!check_device(dev) ||
!get_device_resources(dev, &iommu, &domain, &devid))
return;
+ if (!dma_ops_domain(domain))
+ return;
+
spin_lock_irqsave(&domain->lock, flags);
for_each_sg(sglist, s, nelems, i) {
@@ -1194,6 +1502,8 @@ static void *alloc_coherent(struct device *dev, size_t size,
phys_addr_t paddr;
u64 dma_mask = dev->coherent_dma_mask;
+ INC_STATS_COUNTER(cnt_alloc_coherent);
+
if (!check_device(dev))
return NULL;
@@ -1212,6 +1522,9 @@ static void *alloc_coherent(struct device *dev, size_t size,
return virt_addr;
}
+ if (!dma_ops_domain(domain))
+ goto out_free;
+
if (!dma_mask)
dma_mask = *dev->dma_mask;
@@ -1220,18 +1533,20 @@ static void *alloc_coherent(struct device *dev, size_t size,
*dma_addr = __map_single(dev, iommu, domain->priv, paddr,
size, DMA_BIDIRECTIONAL, true, dma_mask);
- if (*dma_addr == bad_dma_address) {
- free_pages((unsigned long)virt_addr, get_order(size));
- virt_addr = NULL;
- goto out;
- }
+ if (*dma_addr == bad_dma_address)
+ goto out_free;
iommu_completion_wait(iommu);
-out:
spin_unlock_irqrestore(&domain->lock, flags);
return virt_addr;
+
+out_free:
+
+ free_pages((unsigned long)virt_addr, get_order(size));
+
+ return NULL;
}
/*
@@ -1245,6 +1560,8 @@ static void free_coherent(struct device *dev, size_t size,
struct protection_domain *domain;
u16 devid;
+ INC_STATS_COUNTER(cnt_free_coherent);
+
if (!check_device(dev))
return;
@@ -1253,6 +1570,9 @@ static void free_coherent(struct device *dev, size_t size,
if (!iommu || !domain)
goto free_mem;
+ if (!dma_ops_domain(domain))
+ goto free_mem;
+
spin_lock_irqsave(&domain->lock, flags);
__unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL);
@@ -1296,7 +1616,7 @@ static int amd_iommu_dma_supported(struct device *dev, u64 mask)
* we don't need to preallocate the protection domains anymore.
* For now we have to.
*/
-void prealloc_protection_domains(void)
+static void prealloc_protection_domains(void)
{
struct pci_dev *dev = NULL;
struct dma_ops_domain *dma_dom;
@@ -1305,7 +1625,7 @@ void prealloc_protection_domains(void)
u16 devid;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- devid = (dev->bus->number << 8) | dev->devfn;
+ devid = calc_devid(dev->bus->number, dev->devfn);
if (devid > amd_iommu_last_bdf)
continue;
devid = amd_iommu_alias_table[devid];
@@ -1352,6 +1672,7 @@ int __init amd_iommu_init_dma_ops(void)
iommu->default_dom = dma_ops_domain_alloc(iommu, order);
if (iommu->default_dom == NULL)
return -ENOMEM;
+ iommu->default_dom->domain.flags |= PD_DEFAULT_MASK;
ret = iommu_init_unity_mappings(iommu);
if (ret)
goto free_domains;
@@ -1375,6 +1696,12 @@ int __init amd_iommu_init_dma_ops(void)
/* Make the driver finally visible to the drivers */
dma_ops = &amd_iommu_dma_ops;
+ register_iommu(&amd_iommu_ops);
+
+ bus_register_notifier(&pci_bus_type, &device_nb);
+
+ amd_iommu_stats_init();
+
return 0;
free_domains:
@@ -1386,3 +1713,224 @@ free_domains:
return ret;
}
+
+/*****************************************************************************
+ *
+ * The following functions belong to the exported interface of AMD IOMMU
+ *
+ * This interface allows access to lower level functions of the IOMMU
+ * like protection domain handling and assignement of devices to domains
+ * which is not possible with the dma_ops interface.
+ *
+ *****************************************************************************/
+
+static void cleanup_domain(struct protection_domain *domain)
+{
+ unsigned long flags;
+ u16 devid;
+
+ write_lock_irqsave(&amd_iommu_devtable_lock, flags);
+
+ for (devid = 0; devid <= amd_iommu_last_bdf; ++devid)
+ if (amd_iommu_pd_table[devid] == domain)
+ __detach_device(domain, devid);
+
+ write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
+}
+
+static int amd_iommu_domain_init(struct iommu_domain *dom)
+{
+ struct protection_domain *domain;
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain)
+ return -ENOMEM;
+
+ spin_lock_init(&domain->lock);
+ domain->mode = PAGE_MODE_3_LEVEL;
+ domain->id = domain_id_alloc();
+ if (!domain->id)
+ goto out_free;
+ domain->pt_root = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!domain->pt_root)
+ goto out_free;
+
+ dom->priv = domain;
+
+ return 0;
+
+out_free:
+ kfree(domain);
+
+ return -ENOMEM;
+}
+
+static void amd_iommu_domain_destroy(struct iommu_domain *dom)
+{
+ struct protection_domain *domain = dom->priv;
+
+ if (!domain)
+ return;
+
+ if (domain->dev_cnt > 0)
+ cleanup_domain(domain);
+
+ BUG_ON(domain->dev_cnt != 0);
+
+ free_pagetable(domain);
+
+ domain_id_free(domain->id);
+
+ kfree(domain);
+
+ dom->priv = NULL;
+}
+
+static void amd_iommu_detach_device(struct iommu_domain *dom,
+ struct device *dev)
+{
+ struct protection_domain *domain = dom->priv;
+ struct amd_iommu *iommu;
+ struct pci_dev *pdev;
+ u16 devid;
+
+ if (dev->bus != &pci_bus_type)
+ return;
+
+ pdev = to_pci_dev(dev);
+
+ devid = calc_devid(pdev->bus->number, pdev->devfn);
+
+ if (devid > 0)
+ detach_device(domain, devid);
+
+ iommu = amd_iommu_rlookup_table[devid];
+ if (!iommu)
+ return;
+
+ iommu_queue_inv_dev_entry(iommu, devid);
+ iommu_completion_wait(iommu);
+}
+
+static int amd_iommu_attach_device(struct iommu_domain *dom,
+ struct device *dev)
+{
+ struct protection_domain *domain = dom->priv;
+ struct protection_domain *old_domain;
+ struct amd_iommu *iommu;
+ struct pci_dev *pdev;
+ u16 devid;
+
+ if (dev->bus != &pci_bus_type)
+ return -EINVAL;
+
+ pdev = to_pci_dev(dev);
+
+ devid = calc_devid(pdev->bus->number, pdev->devfn);
+
+ if (devid >= amd_iommu_last_bdf ||
+ devid != amd_iommu_alias_table[devid])
+ return -EINVAL;
+
+ iommu = amd_iommu_rlookup_table[devid];
+ if (!iommu)
+ return -EINVAL;
+
+ old_domain = domain_for_device(devid);
+ if (old_domain)
+ return -EBUSY;
+
+ attach_device(iommu, domain, devid);
+
+ iommu_completion_wait(iommu);
+
+ return 0;
+}
+
+static int amd_iommu_map_range(struct iommu_domain *dom,
+ unsigned long iova, phys_addr_t paddr,
+ size_t size, int iommu_prot)
+{
+ struct protection_domain *domain = dom->priv;
+ unsigned long i, npages = iommu_num_pages(paddr, size, PAGE_SIZE);
+ int prot = 0;
+ int ret;
+
+ if (iommu_prot & IOMMU_READ)
+ prot |= IOMMU_PROT_IR;
+ if (iommu_prot & IOMMU_WRITE)
+ prot |= IOMMU_PROT_IW;
+
+ iova &= PAGE_MASK;
+ paddr &= PAGE_MASK;
+
+ for (i = 0; i < npages; ++i) {
+ ret = iommu_map_page(domain, iova, paddr, prot);
+ if (ret)
+ return ret;
+
+ iova += PAGE_SIZE;
+ paddr += PAGE_SIZE;
+ }
+
+ return 0;
+}
+
+static void amd_iommu_unmap_range(struct iommu_domain *dom,
+ unsigned long iova, size_t size)
+{
+
+ struct protection_domain *domain = dom->priv;
+ unsigned long i, npages = iommu_num_pages(iova, size, PAGE_SIZE);
+
+ iova &= PAGE_MASK;
+
+ for (i = 0; i < npages; ++i) {
+ iommu_unmap_page(domain, iova);
+ iova += PAGE_SIZE;
+ }
+
+ iommu_flush_domain(domain->id);
+}
+
+static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom,
+ unsigned long iova)
+{
+ struct protection_domain *domain = dom->priv;
+ unsigned long offset = iova & ~PAGE_MASK;
+ phys_addr_t paddr;
+ u64 *pte;
+
+ pte = &domain->pt_root[IOMMU_PTE_L2_INDEX(iova)];
+
+ if (!IOMMU_PTE_PRESENT(*pte))
+ return 0;
+
+ pte = IOMMU_PTE_PAGE(*pte);
+ pte = &pte[IOMMU_PTE_L1_INDEX(iova)];
+
+ if (!IOMMU_PTE_PRESENT(*pte))
+ return 0;
+
+ pte = IOMMU_PTE_PAGE(*pte);
+ pte = &pte[IOMMU_PTE_L0_INDEX(iova)];
+
+ if (!IOMMU_PTE_PRESENT(*pte))
+ return 0;
+
+ paddr = *pte & IOMMU_PAGE_MASK;
+ paddr |= offset;
+
+ return paddr;
+}
+
+static struct iommu_ops amd_iommu_ops = {
+ .domain_init = amd_iommu_domain_init,
+ .domain_destroy = amd_iommu_domain_destroy,
+ .attach_dev = amd_iommu_attach_device,
+ .detach_dev = amd_iommu_detach_device,
+ .map = amd_iommu_map_range,
+ .unmap = amd_iommu_unmap_range,
+ .iova_to_phys = amd_iommu_iova_to_phys,
+};
+
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index c625800c55ca..42c33cebf00f 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -122,7 +122,8 @@ u16 amd_iommu_last_bdf; /* largest PCI device id we have
LIST_HEAD(amd_iommu_unity_map); /* a list of required unity mappings
we find in ACPI */
unsigned amd_iommu_aperture_order = 26; /* size of aperture in power of 2 */
-int amd_iommu_isolate = 1; /* if 1, device isolation is enabled */
+bool amd_iommu_isolate = true; /* if true, device isolation is
+ enabled */
bool amd_iommu_unmap_flush; /* if true, flush on every unmap */
LIST_HEAD(amd_iommu_list); /* list of all AMD IOMMUs in the
@@ -243,20 +244,16 @@ static void __init iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
}
/* Function to enable the hardware */
-void __init iommu_enable(struct amd_iommu *iommu)
+static void __init iommu_enable(struct amd_iommu *iommu)
{
- printk(KERN_INFO "AMD IOMMU: Enabling IOMMU "
- "at %02x:%02x.%x cap 0x%hx\n",
- iommu->dev->bus->number,
- PCI_SLOT(iommu->dev->devfn),
- PCI_FUNC(iommu->dev->devfn),
- iommu->cap_ptr);
+ printk(KERN_INFO "AMD IOMMU: Enabling IOMMU at %s cap 0x%hx\n",
+ dev_name(&iommu->dev->dev), iommu->cap_ptr);
iommu_feature_enable(iommu, CONTROL_IOMMU_EN);
}
/* Function to enable IOMMU event logging and event interrupts */
-void __init iommu_enable_event_logging(struct amd_iommu *iommu)
+static void __init iommu_enable_event_logging(struct amd_iommu *iommu)
{
iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
@@ -1218,9 +1215,9 @@ static int __init parse_amd_iommu_options(char *str)
{
for (; *str; ++str) {
if (strncmp(str, "isolate", 7) == 0)
- amd_iommu_isolate = 1;
+ amd_iommu_isolate = true;
if (strncmp(str, "share", 5) == 0)
- amd_iommu_isolate = 0;
+ amd_iommu_isolate = false;
if (strncmp(str, "fullflush", 9) == 0)
amd_iommu_unmap_flush = true;
}
diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c
index b5229affb953..115449f869ee 100644
--- a/arch/x86/kernel/apic.c
+++ b/arch/x86/kernel/apic.c
@@ -31,9 +31,11 @@
#include <linux/dmi.h>
#include <linux/dmar.h>
#include <linux/ftrace.h>
+#include <linux/smp.h>
+#include <linux/nmi.h>
+#include <linux/timex.h>
#include <asm/atomic.h>
-#include <asm/smp.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
#include <asm/desc.h>
@@ -41,12 +43,11 @@
#include <asm/hpet.h>
#include <asm/pgalloc.h>
#include <asm/i8253.h>
-#include <asm/nmi.h>
#include <asm/idle.h>
#include <asm/proto.h>
-#include <asm/timex.h>
#include <asm/apic.h>
#include <asm/i8259.h>
+#include <asm/smp.h>
#include <mach_apic.h>
#include <mach_apicdef.h>
@@ -98,8 +99,8 @@ __setup("apicpmtimer", setup_apicpmtimer);
#ifdef HAVE_X2APIC
int x2apic;
/* x2apic enabled before OS handover */
-int x2apic_preenabled;
-int disable_x2apic;
+static int x2apic_preenabled;
+static int disable_x2apic;
static __init int setup_nox2apic(char *str)
{
disable_x2apic = 1;
@@ -119,8 +120,6 @@ EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
int first_system_vector = 0xfe;
-char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};
-
/*
* Debug level, exported for io_apic.c
*/
@@ -142,7 +141,7 @@ static int lapic_next_event(unsigned long delta,
struct clock_event_device *evt);
static void lapic_timer_setup(enum clock_event_mode mode,
struct clock_event_device *evt);
-static void lapic_timer_broadcast(cpumask_t mask);
+static void lapic_timer_broadcast(const struct cpumask *mask);
static void apic_pm_activate(void);
/*
@@ -228,7 +227,7 @@ void xapic_icr_write(u32 low, u32 id)
apic_write(APIC_ICR, low);
}
-u64 xapic_icr_read(void)
+static u64 xapic_icr_read(void)
{
u32 icr1, icr2;
@@ -268,7 +267,7 @@ void x2apic_icr_write(u32 low, u32 id)
wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
}
-u64 x2apic_icr_read(void)
+static u64 x2apic_icr_read(void)
{
unsigned long val;
@@ -455,7 +454,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
/*
* Local APIC timer broadcast function
*/
-static void lapic_timer_broadcast(cpumask_t mask)
+static void lapic_timer_broadcast(const struct cpumask *mask)
{
#ifdef CONFIG_SMP
send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
@@ -471,7 +470,7 @@ static void __cpuinit setup_APIC_timer(void)
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
memcpy(levt, &lapic_clockevent, sizeof(*levt));
- levt->cpumask = cpumask_of_cpu(smp_processor_id());
+ levt->cpumask = cpumask_of(smp_processor_id());
clockevents_register_device(levt);
}
@@ -689,7 +688,7 @@ static int __init calibrate_APIC_clock(void)
local_irq_enable();
if (levt->features & CLOCK_EVT_FEAT_DUMMY) {
- pr_warning("APIC timer disabled due to verification failure.\n");
+ pr_warning("APIC timer disabled due to verification failure\n");
return -1;
}
@@ -896,6 +895,10 @@ void disable_local_APIC(void)
{
unsigned int value;
+ /* APIC hasn't been mapped yet */
+ if (!apic_phys)
+ return;
+
clear_local_APIC();
/*
@@ -1433,7 +1436,7 @@ static int __init detect_init_APIC(void)
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
- (boot_cpu_data.x86 == 15))
+ (boot_cpu_data.x86 >= 15))
break;
goto no_apic;
case X86_VENDOR_INTEL:
@@ -1807,28 +1810,37 @@ void disconnect_bsp_APIC(int virt_wire_setup)
void __cpuinit generic_processor_info(int apicid, int version)
{
int cpu;
- cpumask_t tmp_map;
/*
* Validate version
*/
if (version == 0x0) {
pr_warning("BIOS bug, APIC version is 0 for CPU#%d! "
- "fixing up to 0x10. (tell your hw vendor)\n",
- version);
+ "fixing up to 0x10. (tell your hw vendor)\n",
+ version);
version = 0x10;
}
apic_version[apicid] = version;
- if (num_processors >= NR_CPUS) {
- pr_warning("WARNING: NR_CPUS limit of %i reached."
- " Processor ignored.\n", NR_CPUS);
+ if (num_processors >= nr_cpu_ids) {
+ int max = nr_cpu_ids;
+ int thiscpu = max + disabled_cpus;
+
+ pr_warning(
+ "ACPI: NR_CPUS/possible_cpus limit of %i reached."
+ " Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
+
+ disabled_cpus++;
return;
}
num_processors++;
- cpus_complement(tmp_map, cpu_present_map);
- cpu = first_cpu(tmp_map);
+ cpu = cpumask_next_zero(-1, cpu_present_mask);
+
+ if (version != apic_version[boot_cpu_physical_apicid])
+ WARN_ONCE(1,
+ "ACPI: apic version mismatch, bootcpu: %x cpu %d: %x\n",
+ apic_version[boot_cpu_physical_apicid], cpu, version);
physid_set(apicid, phys_cpu_present_map);
if (apicid == boot_cpu_physical_apicid) {
@@ -1878,8 +1890,8 @@ void __cpuinit generic_processor_info(int apicid, int version)
}
#endif
- cpu_set(cpu, cpu_possible_map);
- cpu_set(cpu, cpu_present_map);
+ set_cpu_possible(cpu, true);
+ set_cpu_present(cpu, true);
}
#ifdef CONFIG_X86_64
@@ -2081,18 +2093,16 @@ __cpuinit int apic_is_clustered_box(void)
bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < nr_cpu_ids; i++) {
/* are we being called early in kernel startup? */
if (bios_cpu_apicid) {
id = bios_cpu_apicid[i];
- }
- else if (i < nr_cpu_ids) {
+ } else if (i < nr_cpu_ids) {
if (cpu_present(i))
id = per_cpu(x86_bios_cpu_apicid, i);
else
continue;
- }
- else
+ } else
break;
if (id != BAD_APICID)
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 3a26525a3f31..98807bb095ad 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -160,9 +160,9 @@
* Work around byte swap bug in one of the Vaio's BIOS's
* (Marc Boucher <marc@mbsi.ca>).
* Exposed the disable flag to dmi so that we can handle known
- * broken APM (Alan Cox <alan@redhat.com>).
+ * broken APM (Alan Cox <alan@lxorguk.ukuu.org.uk>).
* 1.14ac: If the BIOS says "I slowed the CPU down" then don't spin
- * calling it - instead idle. (Alan Cox <alan@redhat.com>)
+ * calling it - instead idle. (Alan Cox <alan@lxorguk.ukuu.org.uk>)
* If an APM idle fails log it and idle sensibly
* 1.15: Don't queue events to clients who open the device O_WRONLY.
* Don't expect replies from clients who open the device O_RDONLY.
diff --git a/arch/x86/kernel/bios_uv.c b/arch/x86/kernel/bios_uv.c
index 2a0a2a3cac26..f63882728d91 100644
--- a/arch/x86/kernel/bios_uv.c
+++ b/arch/x86/kernel/bios_uv.c
@@ -25,7 +25,7 @@
#include <asm/uv/bios.h>
#include <asm/uv/uv_hub.h>
-struct uv_systab uv_systab;
+static struct uv_systab uv_systab;
s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
{
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 42e0853030cb..83492b1f93b1 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -40,6 +40,26 @@
#include "cpu.h"
+#ifdef CONFIG_X86_64
+
+/* all of these masks are initialized in setup_cpu_local_masks() */
+cpumask_var_t cpu_callin_mask;
+cpumask_var_t cpu_callout_mask;
+cpumask_var_t cpu_initialized_mask;
+
+/* representing cpus for which sibling maps can be computed */
+cpumask_var_t cpu_sibling_setup_mask;
+
+#else /* CONFIG_X86_32 */
+
+cpumask_t cpu_callin_map;
+cpumask_t cpu_callout_map;
+cpumask_t cpu_initialized;
+cpumask_t cpu_sibling_setup_map;
+
+#endif /* CONFIG_X86_32 */
+
+
static struct cpu_dev *this_cpu __cpuinitdata;
#ifdef CONFIG_X86_64
@@ -355,7 +375,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c)
printk(KERN_INFO "CPU: Hyper-Threading is disabled\n");
} else if (smp_num_siblings > 1) {
- if (smp_num_siblings > NR_CPUS) {
+ if (smp_num_siblings > nr_cpu_ids) {
printk(KERN_WARNING "CPU: Unsupported number of siblings %d",
smp_num_siblings);
smp_num_siblings = 1;
@@ -856,8 +876,6 @@ static __init int setup_disablecpuid(char *arg)
}
__setup("clearcpuid=", setup_disablecpuid);
-cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
-
#ifdef CONFIG_X86_64
struct x8664_pda **_cpu_pda __read_mostly;
EXPORT_SYMBOL(_cpu_pda);
@@ -976,7 +994,7 @@ void __cpuinit cpu_init(void)
me = current;
- if (cpu_test_and_set(cpu, cpu_initialized))
+ if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask))
panic("CPU#%d already initialized!\n", cpu);
printk(KERN_INFO "Initializing CPU#%d\n", cpu);
@@ -1085,7 +1103,7 @@ void __cpuinit cpu_init(void)
struct tss_struct *t = &per_cpu(init_tss, cpu);
struct thread_struct *thread = &curr->thread;
- if (cpu_test_and_set(cpu, cpu_initialized)) {
+ if (cpumask_test_and_set_cpu(cpu, cpu_initialized_mask)) {
printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
for (;;) local_irq_enable();
}
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
index 88ea02dcb622..4b1c319d30c3 100644
--- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -145,13 +145,14 @@ typedef union {
struct drv_cmd {
unsigned int type;
- cpumask_t mask;
+ const struct cpumask *mask;
drv_addr_union addr;
u32 val;
};
-static void do_drv_read(struct drv_cmd *cmd)
+static long do_drv_read(void *_cmd)
{
+ struct drv_cmd *cmd = _cmd;
u32 h;
switch (cmd->type) {
@@ -166,10 +167,12 @@ static void do_drv_read(struct drv_cmd *cmd)
default:
break;
}
+ return 0;
}
-static void do_drv_write(struct drv_cmd *cmd)
+static long do_drv_write(void *_cmd)
{
+ struct drv_cmd *cmd = _cmd;
u32 lo, hi;
switch (cmd->type) {
@@ -186,48 +189,41 @@ static void do_drv_write(struct drv_cmd *cmd)
default:
break;
}
+ return 0;
}
static void drv_read(struct drv_cmd *cmd)
{
- cpumask_t saved_mask = current->cpus_allowed;
cmd->val = 0;
- set_cpus_allowed_ptr(current, &cmd->mask);
- do_drv_read(cmd);
- set_cpus_allowed_ptr(current, &saved_mask);
+ work_on_cpu(cpumask_any(cmd->mask), do_drv_read, cmd);
}
static void drv_write(struct drv_cmd *cmd)
{
- cpumask_t saved_mask = current->cpus_allowed;
unsigned int i;
- for_each_cpu_mask_nr(i, cmd->mask) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
- do_drv_write(cmd);
+ for_each_cpu(i, cmd->mask) {
+ work_on_cpu(i, do_drv_write, cmd);
}
-
- set_cpus_allowed_ptr(current, &saved_mask);
- return;
}
-static u32 get_cur_val(const cpumask_t *mask)
+static u32 get_cur_val(const struct cpumask *mask)
{
struct acpi_processor_performance *perf;
struct drv_cmd cmd;
- if (unlikely(cpus_empty(*mask)))
+ if (unlikely(cpumask_empty(mask)))
return 0;
- switch (per_cpu(drv_data, first_cpu(*mask))->cpu_feature) {
+ switch (per_cpu(drv_data, cpumask_first(mask))->cpu_feature) {
case SYSTEM_INTEL_MSR_CAPABLE:
cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
break;
case SYSTEM_IO_CAPABLE:
cmd.type = SYSTEM_IO_CAPABLE;
- perf = per_cpu(drv_data, first_cpu(*mask))->acpi_data;
+ perf = per_cpu(drv_data, cpumask_first(mask))->acpi_data;
cmd.addr.io.port = perf->control_register.address;
cmd.addr.io.bit_width = perf->control_register.bit_width;
break;
@@ -235,8 +231,7 @@ static u32 get_cur_val(const cpumask_t *mask)
return 0;
}
- cmd.mask = *mask;
-
+ cmd.mask = mask;
drv_read(&cmd);
dprintk("get_cur_val = %u\n", cmd.val);
@@ -244,6 +239,30 @@ static u32 get_cur_val(const cpumask_t *mask)
return cmd.val;
}
+struct perf_cur {
+ union {
+ struct {
+ u32 lo;
+ u32 hi;
+ } split;
+ u64 whole;
+ } aperf_cur, mperf_cur;
+};
+
+
+static long read_measured_perf_ctrs(void *_cur)
+{
+ struct perf_cur *cur = _cur;
+
+ rdmsr(MSR_IA32_APERF, cur->aperf_cur.split.lo, cur->aperf_cur.split.hi);
+ rdmsr(MSR_IA32_MPERF, cur->mperf_cur.split.lo, cur->mperf_cur.split.hi);
+
+ wrmsr(MSR_IA32_APERF, 0, 0);
+ wrmsr(MSR_IA32_MPERF, 0, 0);
+
+ return 0;
+}
+
/*
* Return the measured active (C0) frequency on this CPU since last call
* to this function.
@@ -260,31 +279,12 @@ static u32 get_cur_val(const cpumask_t *mask)
static unsigned int get_measured_perf(struct cpufreq_policy *policy,
unsigned int cpu)
{
- union {
- struct {
- u32 lo;
- u32 hi;
- } split;
- u64 whole;
- } aperf_cur, mperf_cur;
-
- cpumask_t saved_mask;
+ struct perf_cur cur;
unsigned int perf_percent;
unsigned int retval;
- saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (get_cpu() != cpu) {
- /* We were not able to run on requested processor */
- put_cpu();
+ if (!work_on_cpu(cpu, read_measured_perf_ctrs, &cur))
return 0;
- }
-
- rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi);
- rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi);
-
- wrmsr(MSR_IA32_APERF, 0,0);
- wrmsr(MSR_IA32_MPERF, 0,0);
#ifdef __i386__
/*
@@ -292,37 +292,39 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy,
* Get an approximate value. Return failure in case we cannot get
* an approximate value.
*/
- if (unlikely(aperf_cur.split.hi || mperf_cur.split.hi)) {
+ if (unlikely(cur.aperf_cur.split.hi || cur.mperf_cur.split.hi)) {
int shift_count;
u32 h;
- h = max_t(u32, aperf_cur.split.hi, mperf_cur.split.hi);
+ h = max_t(u32, cur.aperf_cur.split.hi, cur.mperf_cur.split.hi);
shift_count = fls(h);
- aperf_cur.whole >>= shift_count;
- mperf_cur.whole >>= shift_count;
+ cur.aperf_cur.whole >>= shift_count;
+ cur.mperf_cur.whole >>= shift_count;
}
- if (((unsigned long)(-1) / 100) < aperf_cur.split.lo) {
+ if (((unsigned long)(-1) / 100) < cur.aperf_cur.split.lo) {
int shift_count = 7;
- aperf_cur.split.lo >>= shift_count;
- mperf_cur.split.lo >>= shift_count;
+ cur.aperf_cur.split.lo >>= shift_count;
+ cur.mperf_cur.split.lo >>= shift_count;
}
- if (aperf_cur.split.lo && mperf_cur.split.lo)
- perf_percent = (aperf_cur.split.lo * 100) / mperf_cur.split.lo;
+ if (cur.aperf_cur.split.lo && cur.mperf_cur.split.lo)
+ perf_percent = (cur.aperf_cur.split.lo * 100) /
+ cur.mperf_cur.split.lo;
else
perf_percent = 0;
#else
- if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) {
+ if (unlikely(((unsigned long)(-1) / 100) < cur.aperf_cur.whole)) {
int shift_count = 7;
- aperf_cur.whole >>= shift_count;
- mperf_cur.whole >>= shift_count;
+ cur.aperf_cur.whole >>= shift_count;
+ cur.mperf_cur.whole >>= shift_count;
}
- if (aperf_cur.whole && mperf_cur.whole)
- perf_percent = (aperf_cur.whole * 100) / mperf_cur.whole;
+ if (cur.aperf_cur.whole && cur.mperf_cur.whole)
+ perf_percent = (cur.aperf_cur.whole * 100) /
+ cur.mperf_cur.whole;
else
perf_percent = 0;
@@ -330,10 +332,6 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy,
retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100;
- put_cpu();
- set_cpus_allowed_ptr(current, &saved_mask);
-
- dprintk("cpu %d: performance percent %d\n", cpu, perf_percent);
return retval;
}
@@ -351,7 +349,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
}
cached_freq = data->freq_table[data->acpi_data->state].frequency;
- freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
+ freq = extract_freq(get_cur_val(cpumask_of(cpu)), data);
if (freq != cached_freq) {
/*
* The dreaded BIOS frequency change behind our back.
@@ -365,7 +363,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
return freq;
}
-static unsigned int check_freqs(const cpumask_t *mask, unsigned int freq,
+static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
struct acpi_cpufreq_data *data)
{
unsigned int cur_freq;
@@ -386,7 +384,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
struct acpi_processor_performance *perf;
struct cpufreq_freqs freqs;
- cpumask_t online_policy_cpus;
struct drv_cmd cmd;
unsigned int next_state = 0; /* Index into freq_table */
unsigned int next_perf_state = 0; /* Index into perf table */
@@ -406,15 +403,10 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
data->freq_table,
target_freq,
relation, &next_state);
- if (unlikely(result))
- return -ENODEV;
-
-#ifdef CONFIG_HOTPLUG_CPU
- /* cpufreq holds the hotplug lock, so we are safe from here on */
- cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
-#else
- online_policy_cpus = policy->cpus;
-#endif
+ if (unlikely(result)) {
+ result = -ENODEV;
+ goto out;
+ }
next_perf_state = data->freq_table[next_state].index;
if (perf->state == next_perf_state) {
@@ -425,7 +417,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
} else {
dprintk("Already at target state (P%d)\n",
next_perf_state);
- return 0;
+ goto out;
}
}
@@ -444,19 +436,19 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
cmd.val = (u32) perf->states[next_perf_state].control;
break;
default:
- return -ENODEV;
+ result = -ENODEV;
+ goto out;
}
- cpus_clear(cmd.mask);
-
+ /* cpufreq holds the hotplug lock, so we are safe from here on */
if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY)
- cmd.mask = online_policy_cpus;
+ cmd.mask = policy->cpus;
else
- cpu_set(policy->cpu, cmd.mask);
+ cmd.mask = cpumask_of(policy->cpu);
freqs.old = perf->states[perf->state].core_frequency * 1000;
freqs.new = data->freq_table[next_state].frequency;
- for_each_cpu_mask_nr(i, cmd.mask) {
+ for_each_cpu(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -464,19 +456,21 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
drv_write(&cmd);
if (acpi_pstate_strict) {
- if (!check_freqs(&cmd.mask, freqs.new, data)) {
+ if (!check_freqs(cmd.mask, freqs.new, data)) {
dprintk("acpi_cpufreq_target failed (%d)\n",
policy->cpu);
- return -EAGAIN;
+ result = -EAGAIN;
+ goto out;
}
}
- for_each_cpu_mask_nr(i, cmd.mask) {
+ for_each_cpu(i, cmd.mask) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
perf->state = next_perf_state;
+out:
return result;
}
@@ -517,6 +511,17 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
}
}
+static void free_acpi_perf_data(void)
+{
+ unsigned int i;
+
+ /* Freeing a NULL pointer is OK, and alloc_percpu zeroes. */
+ for_each_possible_cpu(i)
+ free_cpumask_var(per_cpu_ptr(acpi_perf_data, i)
+ ->shared_cpu_map);
+ free_percpu(acpi_perf_data);
+}
+
/*
* acpi_cpufreq_early_init - initialize ACPI P-States library
*
@@ -527,6 +532,7 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
*/
static int __init acpi_cpufreq_early_init(void)
{
+ unsigned int i;
dprintk("acpi_cpufreq_early_init\n");
acpi_perf_data = alloc_percpu(struct acpi_processor_performance);
@@ -534,6 +540,16 @@ static int __init acpi_cpufreq_early_init(void)
dprintk("Memory allocation error for acpi_perf_data.\n");
return -ENOMEM;
}
+ for_each_possible_cpu(i) {
+ if (!alloc_cpumask_var_node(
+ &per_cpu_ptr(acpi_perf_data, i)->shared_cpu_map,
+ GFP_KERNEL, cpu_to_node(i))) {
+
+ /* Freeing a NULL pointer is OK: alloc_percpu zeroes. */
+ free_acpi_perf_data();
+ return -ENOMEM;
+ }
+ }
/* Do initialization in ACPI core */
acpi_processor_preregister_performance(acpi_perf_data);
@@ -604,15 +620,15 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
*/
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
- policy->cpus = perf->shared_cpu_map;
+ cpumask_copy(policy->cpus, perf->shared_cpu_map);
}
- policy->related_cpus = perf->shared_cpu_map;
+ cpumask_copy(policy->related_cpus, perf->shared_cpu_map);
#ifdef CONFIG_SMP
dmi_check_system(sw_any_bug_dmi_table);
- if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
+ if (bios_with_sw_any_bug && cpumask_weight(policy->cpus) == 1) {
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
- policy->cpus = per_cpu(cpu_core_map, cpu);
+ cpumask_copy(policy->cpus, cpu_core_mask(cpu));
}
#endif
@@ -795,7 +811,7 @@ static int __init acpi_cpufreq_init(void)
ret = cpufreq_register_driver(&acpi_cpufreq_driver);
if (ret)
- free_percpu(acpi_perf_data);
+ free_acpi_perf_data();
return ret;
}
diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c
index b0461856acfb..a4cff5d6e380 100644
--- a/arch/x86/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c
@@ -982,7 +982,7 @@ static int __init longhaul_init(void)
case 10:
printk(KERN_ERR PFX "Use acpi-cpufreq driver for VIA C7\n");
default:
- ;;
+ ;
}
return -ENODEV;
diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
index b8e05ee4f736..b585e04cbc9e 100644
--- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c
@@ -122,7 +122,7 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
return 0;
/* notifiers */
- for_each_cpu_mask_nr(i, policy->cpus) {
+ for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
@@ -130,11 +130,11 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
/* run on each logical CPU, see section 13.15.3 of IA32 Intel Architecture Software
* Developer's Manual, Volume 3
*/
- for_each_cpu_mask_nr(i, policy->cpus)
+ for_each_cpu(i, policy->cpus)
cpufreq_p4_setdc(i, p4clockmod_table[newstate].index);
/* notifiers */
- for_each_cpu_mask_nr(i, policy->cpus) {
+ for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -160,6 +160,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
switch (c->x86_model) {
case 0x0E: /* Core */
case 0x0F: /* Core Duo */
+ case 0x16: /* Celeron Core */
p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PCORE);
case 0x0D: /* Pentium M (Dothan) */
@@ -171,7 +172,9 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
}
if (c->x86 != 0xF) {
- printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to <cpufreq@vger.kernel.org>\n");
+ if (!cpu_has(c, X86_FEATURE_EST))
+ printk(KERN_WARNING PFX "Unknown p4-clockmod-capable CPU. "
+ "Please send an e-mail to <cpufreq@vger.kernel.org>\n");
return 0;
}
@@ -200,7 +203,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
unsigned int i;
#ifdef CONFIG_SMP
- policy->cpus = per_cpu(cpu_sibling_map, policy->cpu);
+ cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu));
#endif
/* Errata workaround */
@@ -274,6 +277,7 @@ static struct cpufreq_driver p4clockmod_driver = {
.name = "p4-clockmod",
.owner = THIS_MODULE,
.attr = p4clockmod_attr,
+ .hide_interface = 1,
};
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
index 7c7d56b43136..1b446d79a8fd 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k7.c
@@ -310,6 +310,12 @@ static int powernow_acpi_init(void)
goto err0;
}
+ if (!alloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
+ GFP_KERNEL)) {
+ retval = -ENOMEM;
+ goto err05;
+ }
+
if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
retval = -EIO;
goto err1;
@@ -412,6 +418,8 @@ static int powernow_acpi_init(void)
err2:
acpi_processor_unregister_performance(acpi_processor_perf, 0);
err1:
+ free_cpumask_var(acpi_processor_perf->shared_cpu_map);
+err05:
kfree(acpi_processor_perf);
err0:
printk(KERN_WARNING PFX "ACPI perflib can not be used in this platform\n");
@@ -652,6 +660,7 @@ static int powernow_cpu_exit (struct cpufreq_policy *policy) {
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
if (acpi_processor_perf) {
acpi_processor_unregister_performance(acpi_processor_perf, 0);
+ free_cpumask_var(acpi_processor_perf->shared_cpu_map);
kfree(acpi_processor_perf);
}
#endif
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index 7f05f44b97e9..5c28b37dea11 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -766,7 +766,7 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned
static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
{
struct cpufreq_frequency_table *powernow_table;
- int ret_val;
+ int ret_val = -ENODEV;
if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
dprintk("register performance failed: bad ACPI data\n");
@@ -815,6 +815,13 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
+ 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;
+ goto err_out_mem;
+ }
+
return 0;
err_out_mem:
@@ -826,7 +833,7 @@ err_out:
/* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
data->acpi_data.state_count = 0;
- return -ENODEV;
+ return ret_val;
}
static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
@@ -929,6 +936,7 @@ static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
{
if (data->acpi_data.state_count)
acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
+ free_cpumask_var(data->acpi_data.shared_cpu_map);
}
#else
@@ -1134,7 +1142,8 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
data->cpu = pol->cpu;
data->currpstate = HW_PSTATE_INVALID;
- if (powernow_k8_cpu_init_acpi(data)) {
+ rc = powernow_k8_cpu_init_acpi(data);
+ if (rc) {
/*
* Use the PSB BIOS structure. This is only availabe on
* an UP version, and is deprecated by AMD.
@@ -1152,20 +1161,17 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
"ACPI maintainers and complain to your BIOS "
"vendor.\n");
#endif
- kfree(data);
- return -ENODEV;
+ goto err_out;
}
if (pol->cpu != 0) {
printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
"CPU other than CPU0. Complain to your BIOS "
"vendor.\n");
- kfree(data);
- return -ENODEV;
+ goto err_out;
}
rc = find_psb_table(data);
if (rc) {
- kfree(data);
- return -ENODEV;
+ goto err_out;
}
}
@@ -1193,10 +1199,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
set_cpus_allowed_ptr(current, &oldmask);
if (cpu_family == CPU_HW_PSTATE)
- pol->cpus = cpumask_of_cpu(pol->cpu);
+ cpumask_copy(pol->cpus, cpumask_of(pol->cpu));
else
- pol->cpus = per_cpu(cpu_core_map, pol->cpu);
- data->available_cores = &(pol->cpus);
+ cpumask_copy(pol->cpus, &per_cpu(cpu_core_map, pol->cpu));
+ data->available_cores = pol->cpus;
/* Take a crude guess here.
* That guess was in microseconds, so multiply with 1000 */
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
index 65cfb5d7f77f..8ecc75b6c7c3 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h
@@ -53,7 +53,7 @@ struct powernow_k8_data {
/* we need to keep track of associated cores, but let cpufreq
* handle hotplug events - so just point at cpufreq pol->cpus
* structure */
- cpumask_t *available_cores;
+ struct cpumask *available_cores;
};
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
index 3b5f06423e77..f08998278a3a 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -458,13 +458,6 @@ static int centrino_verify (struct cpufreq_policy *policy)
*
* Sets a new CPUFreq policy.
*/
-struct allmasks {
- cpumask_t online_policy_cpus;
- cpumask_t saved_mask;
- cpumask_t set_mask;
- cpumask_t covered_cpus;
-};
-
static int centrino_target (struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -474,14 +467,15 @@ static int centrino_target (struct cpufreq_policy *policy,
struct cpufreq_freqs freqs;
int retval = 0;
unsigned int j, k, first_cpu, tmp;
- CPUMASK_ALLOC(allmasks);
- CPUMASK_PTR(online_policy_cpus, allmasks);
- CPUMASK_PTR(saved_mask, allmasks);
- CPUMASK_PTR(set_mask, allmasks);
- CPUMASK_PTR(covered_cpus, allmasks);
+ cpumask_var_t saved_mask, covered_cpus;
- if (unlikely(allmasks == NULL))
+ if (unlikely(!alloc_cpumask_var(&saved_mask, GFP_KERNEL)))
+ return -ENOMEM;
+ if (unlikely(!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))) {
+ free_cpumask_var(saved_mask);
return -ENOMEM;
+ }
+ cpumask_copy(saved_mask, &current->cpus_allowed);
if (unlikely(per_cpu(centrino_model, cpu) == NULL)) {
retval = -ENODEV;
@@ -497,30 +491,26 @@ static int centrino_target (struct cpufreq_policy *policy,
goto out;
}
-#ifdef CONFIG_HOTPLUG_CPU
- /* cpufreq holds the hotplug lock, so we are safe from here on */
- cpus_and(*online_policy_cpus, cpu_online_map, policy->cpus);
-#else
- *online_policy_cpus = policy->cpus;
-#endif
-
- *saved_mask = current->cpus_allowed;
first_cpu = 1;
- cpus_clear(*covered_cpus);
- for_each_cpu_mask_nr(j, *online_policy_cpus) {
+ for_each_cpu(j, policy->cpus) {
+ const struct cpumask *mask;
+
+ /* cpufreq holds the hotplug lock, so we are safe here */
+ if (!cpu_online(j))
+ continue;
+
/*
* Support for SMP systems.
* Make sure we are running on CPU that wants to change freq
*/
- cpus_clear(*set_mask);
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
- cpus_or(*set_mask, *set_mask, *online_policy_cpus);
+ mask = policy->cpus;
else
- cpu_set(j, *set_mask);
+ mask = cpumask_of(j);
- set_cpus_allowed_ptr(current, set_mask);
+ set_cpus_allowed_ptr(current, mask);
preempt_disable();
- if (unlikely(!cpu_isset(smp_processor_id(), *set_mask))) {
+ if (unlikely(!cpu_isset(smp_processor_id(), *mask))) {
dprintk("couldn't limit to CPUs in this domain\n");
retval = -EAGAIN;
if (first_cpu) {
@@ -548,7 +538,9 @@ static int centrino_target (struct cpufreq_policy *policy,
dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
target_freq, freqs.old, freqs.new, msr);
- for_each_cpu_mask_nr(k, *online_policy_cpus) {
+ for_each_cpu(k, policy->cpus) {
+ if (!cpu_online(k))
+ continue;
freqs.cpu = k;
cpufreq_notify_transition(&freqs,
CPUFREQ_PRECHANGE);
@@ -571,7 +563,9 @@ static int centrino_target (struct cpufreq_policy *policy,
preempt_enable();
}
- for_each_cpu_mask_nr(k, *online_policy_cpus) {
+ for_each_cpu(k, policy->cpus) {
+ if (!cpu_online(k))
+ continue;
freqs.cpu = k;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -584,18 +578,17 @@ static int centrino_target (struct cpufreq_policy *policy,
* Best effort undo..
*/
- if (!cpus_empty(*covered_cpus))
- for_each_cpu_mask_nr(j, *covered_cpus) {
- set_cpus_allowed_ptr(current,
- &cpumask_of_cpu(j));
- wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
- }
+ for_each_cpu_mask_nr(j, *covered_cpus) {
+ set_cpus_allowed_ptr(current, &cpumask_of_cpu(j));
+ wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+ }
tmp = freqs.new;
freqs.new = freqs.old;
freqs.old = tmp;
- for_each_cpu_mask_nr(j, *online_policy_cpus) {
- freqs.cpu = j;
+ for_each_cpu(j, policy->cpus) {
+ if (!cpu_online(j))
+ continue;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -608,7 +601,8 @@ migrate_end:
preempt_enable();
set_cpus_allowed_ptr(current, saved_mask);
out:
- CPUMASK_FREE(allmasks);
+ free_cpumask_var(saved_mask);
+ free_cpumask_var(covered_cpus);
return retval;
}
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
index 04d0376b64b0..dedc1e98f168 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
@@ -229,7 +229,7 @@ static unsigned int speedstep_detect_chipset (void)
return 0;
}
-static unsigned int _speedstep_get(const cpumask_t *cpus)
+static unsigned int _speedstep_get(const struct cpumask *cpus)
{
unsigned int speed;
cpumask_t cpus_allowed;
@@ -244,7 +244,7 @@ static unsigned int _speedstep_get(const cpumask_t *cpus)
static unsigned int speedstep_get(unsigned int cpu)
{
- return _speedstep_get(&cpumask_of_cpu(cpu));
+ return _speedstep_get(cpumask_of(cpu));
}
/**
@@ -267,7 +267,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
return -EINVAL;
- freqs.old = _speedstep_get(&policy->cpus);
+ freqs.old = _speedstep_get(policy->cpus);
freqs.new = speedstep_freqs[newstate].frequency;
freqs.cpu = policy->cpu;
@@ -279,20 +279,20 @@ static int speedstep_target (struct cpufreq_policy *policy,
cpus_allowed = current->cpus_allowed;
- for_each_cpu_mask_nr(i, policy->cpus) {
+ for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
}
/* switch to physical CPU where state is to be changed */
- set_cpus_allowed_ptr(current, &policy->cpus);
+ set_cpus_allowed_ptr(current, policy->cpus);
speedstep_set_state(newstate);
/* allow to be run on all CPUs */
set_cpus_allowed_ptr(current, &cpus_allowed);
- for_each_cpu_mask_nr(i, policy->cpus) {
+ for_each_cpu(i, policy->cpus) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
}
@@ -322,11 +322,11 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
/* only run on CPU to be set, or on its sibling */
#ifdef CONFIG_SMP
- policy->cpus = per_cpu(cpu_sibling_map, policy->cpu);
+ cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu));
#endif
cpus_allowed = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &policy->cpus);
+ set_cpus_allowed_ptr(current, policy->cpus);
/* detect low and high frequency and transition latency */
result = speedstep_get_freqs(speedstep_processor,
@@ -339,7 +339,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
return result;
/* get current speed setting */
- speed = _speedstep_get(&policy->cpus);
+ speed = _speedstep_get(policy->cpus);
if (!speed)
return -EIO;
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
index 98d4fdb7dc04..cdac7d62369b 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c
@@ -139,6 +139,15 @@ static unsigned int pentium_core_get_frequency(void)
case 3:
fsb = 166667;
break;
+ case 2:
+ fsb = 200000;
+ break;
+ case 0:
+ fsb = 266667;
+ break;
+ case 4:
+ fsb = 333333;
+ break;
default:
printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value");
}
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 8ea6929e974c..430e5c38a544 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -29,6 +29,19 @@
static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
{
+ /* Unmask CPUID levels if masked: */
+ if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
+ u64 misc_enable;
+
+ rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+
+ if (misc_enable & MSR_IA32_MISC_ENABLE_LIMIT_CPUID) {
+ misc_enable &= ~MSR_IA32_MISC_ENABLE_LIMIT_CPUID;
+ wrmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
+ c->cpuid_level = cpuid_eax(0);
+ }
+ }
+
if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
(c->x86 == 0x6 && c->x86_model >= 0x0e))
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 68b5d8681cbb..da299eb85fc0 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -36,8 +36,11 @@ static struct _cache_table cache_table[] __cpuinitdata =
{
{ 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
{ 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
+ { 0x09, LVL_1_INST, 32 }, /* 4-way set assoc, 64 byte line size */
{ 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */
{ 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */
+ { 0x0d, LVL_1_DATA, 16 }, /* 4-way set assoc, 64 byte line size */
+ { 0x21, LVL_2, 256 }, /* 8-way set assoc, 64 byte line size */
{ 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */
{ 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */
{ 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */
@@ -85,6 +88,18 @@ static struct _cache_table cache_table[] __cpuinitdata =
{ 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */
{ 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */
{ 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */
+ { 0xd0, LVL_3, 512 }, /* 4-way set assoc, 64 byte line size */
+ { 0xd1, LVL_3, 1024 }, /* 4-way set assoc, 64 byte line size */
+ { 0xd2, LVL_3, 2048 }, /* 4-way set assoc, 64 byte line size */
+ { 0xd6, LVL_3, 1024 }, /* 8-way set assoc, 64 byte line size */
+ { 0xd7, LVL_3, 2038 }, /* 8-way set assoc, 64 byte line size */
+ { 0xd8, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */
+ { 0xdc, LVL_3, 2048 }, /* 12-way set assoc, 64 byte line size */
+ { 0xdd, LVL_3, 4096 }, /* 12-way set assoc, 64 byte line size */
+ { 0xde, LVL_3, 8192 }, /* 12-way set assoc, 64 byte line size */
+ { 0xe2, LVL_3, 2048 }, /* 16-way set assoc, 64 byte line size */
+ { 0xe3, LVL_3, 4096 }, /* 16-way set assoc, 64 byte line size */
+ { 0xe4, LVL_3, 8192 }, /* 16-way set assoc, 64 byte line size */
{ 0x00, 0, 0}
};
@@ -534,31 +549,16 @@ static void __cpuinit free_cache_attributes(unsigned int cpu)
per_cpu(cpuid4_info, cpu) = NULL;
}
-static int __cpuinit detect_cache_attributes(unsigned int cpu)
+static void __cpuinit get_cpu_leaves(void *_retval)
{
- struct _cpuid4_info *this_leaf;
- unsigned long j;
- int retval;
- cpumask_t oldmask;
-
- if (num_cache_leaves == 0)
- return -ENOENT;
-
- per_cpu(cpuid4_info, cpu) = kzalloc(
- sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
- if (per_cpu(cpuid4_info, cpu) == NULL)
- return -ENOMEM;
-
- oldmask = current->cpus_allowed;
- retval = set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
- if (retval)
- goto out;
+ int j, *retval = _retval, cpu = smp_processor_id();
/* Do cpuid and store the results */
for (j = 0; j < num_cache_leaves; j++) {
+ struct _cpuid4_info *this_leaf;
this_leaf = CPUID4_INFO_IDX(cpu, j);
- retval = cpuid4_cache_lookup(j, this_leaf);
- if (unlikely(retval < 0)) {
+ *retval = cpuid4_cache_lookup(j, this_leaf);
+ if (unlikely(*retval < 0)) {
int i;
for (i = 0; i < j; i++)
@@ -567,9 +567,21 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu)
}
cache_shared_cpu_map_setup(cpu, j);
}
- set_cpus_allowed_ptr(current, &oldmask);
+}
+
+static int __cpuinit detect_cache_attributes(unsigned int cpu)
+{
+ int retval;
+
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+ per_cpu(cpuid4_info, cpu) = kzalloc(
+ sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
+ if (per_cpu(cpuid4_info, cpu) == NULL)
+ return -ENOMEM;
-out:
+ smp_call_function_single(cpu, get_cpu_leaves, &retval, true);
if (retval) {
kfree(per_cpu(cpuid4_info, cpu));
per_cpu(cpuid4_info, cpu) = NULL;
@@ -626,8 +638,8 @@ static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
cpumask_t *mask = &this_leaf->shared_cpu_map;
n = type?
- cpulist_scnprintf(buf, len-2, *mask):
- cpumask_scnprintf(buf, len-2, *mask);
+ cpulist_scnprintf(buf, len-2, mask) :
+ cpumask_scnprintf(buf, len-2, mask);
buf[n++] = '\n';
buf[n] = '\0';
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_32.c b/arch/x86/kernel/cpu/mcheck/mce_32.c
index 0ebf3fc6a610..dfaebce3633e 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_32.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_32.c
@@ -1,6 +1,6 @@
/*
* mce.c - x86 Machine Check Exception Reporting
- * (c) 2002 Alan Cox <alan@redhat.com>, Dave Jones <davej@redhat.com>
+ * (c) 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>, Dave Jones <davej@redhat.com>
*/
#include <linux/init.h>
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
index 748c8f9e7a05..8ae8c4ff094d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
@@ -83,34 +83,41 @@ static DEFINE_PER_CPU(unsigned char, bank_map); /* see which banks are on */
* CPU Initialization
*/
+struct thresh_restart {
+ struct threshold_block *b;
+ int reset;
+ u16 old_limit;
+};
+
/* must be called with correct cpu affinity */
-static void threshold_restart_bank(struct threshold_block *b,
- int reset, u16 old_limit)
+static long threshold_restart_bank(void *_tr)
{
+ struct thresh_restart *tr = _tr;
u32 mci_misc_hi, mci_misc_lo;
- rdmsr(b->address, mci_misc_lo, mci_misc_hi);
+ rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
- if (b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
- reset = 1; /* limit cannot be lower than err count */
+ if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
+ tr->reset = 1; /* limit cannot be lower than err count */
- if (reset) { /* reset err count and overflow bit */
+ if (tr->reset) { /* reset err count and overflow bit */
mci_misc_hi =
(mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) |
- (THRESHOLD_MAX - b->threshold_limit);
- } else if (old_limit) { /* change limit w/o reset */
+ (THRESHOLD_MAX - tr->b->threshold_limit);
+ } else if (tr->old_limit) { /* change limit w/o reset */
int new_count = (mci_misc_hi & THRESHOLD_MAX) +
- (old_limit - b->threshold_limit);
+ (tr->old_limit - tr->b->threshold_limit);
mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) |
(new_count & THRESHOLD_MAX);
}
- b->interrupt_enable ?
+ tr->b->interrupt_enable ?
(mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
(mci_misc_hi &= ~MASK_INT_TYPE_HI);
mci_misc_hi |= MASK_COUNT_EN_HI;
- wrmsr(b->address, mci_misc_lo, mci_misc_hi);
+ wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi);
+ return 0;
}
/* cpu init entry point, called from mce.c with preempt off */
@@ -120,6 +127,7 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
unsigned int cpu = smp_processor_id();
u8 lvt_off;
u32 low = 0, high = 0, address = 0;
+ struct thresh_restart tr;
for (bank = 0; bank < NR_BANKS; ++bank) {
for (block = 0; block < NR_BLOCKS; ++block) {
@@ -162,7 +170,10 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
wrmsr(address, low, high);
threshold_defaults.address = address;
- threshold_restart_bank(&threshold_defaults, 0, 0);
+ tr.b = &threshold_defaults;
+ tr.reset = 0;
+ tr.old_limit = 0;
+ threshold_restart_bank(&tr);
}
}
}
@@ -251,20 +262,6 @@ struct threshold_attr {
ssize_t(*store) (struct threshold_block *, const char *, size_t count);
};
-static void affinity_set(unsigned int cpu, cpumask_t *oldmask,
- cpumask_t *newmask)
-{
- *oldmask = current->cpus_allowed;
- cpus_clear(*newmask);
- cpu_set(cpu, *newmask);
- set_cpus_allowed_ptr(current, newmask);
-}
-
-static void affinity_restore(const cpumask_t *oldmask)
-{
- set_cpus_allowed_ptr(current, oldmask);
-}
-
#define SHOW_FIELDS(name) \
static ssize_t show_ ## name(struct threshold_block * b, char *buf) \
{ \
@@ -277,15 +274,16 @@ static ssize_t store_interrupt_enable(struct threshold_block *b,
const char *buf, size_t count)
{
char *end;
- cpumask_t oldmask, newmask;
+ struct thresh_restart tr;
unsigned long new = simple_strtoul(buf, &end, 0);
if (end == buf)
return -EINVAL;
b->interrupt_enable = !!new;
- affinity_set(b->cpu, &oldmask, &newmask);
- threshold_restart_bank(b, 0, 0);
- affinity_restore(&oldmask);
+ tr.b = b;
+ tr.reset = 0;
+ tr.old_limit = 0;
+ work_on_cpu(b->cpu, threshold_restart_bank, &tr);
return end - buf;
}
@@ -294,8 +292,7 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
const char *buf, size_t count)
{
char *end;
- cpumask_t oldmask, newmask;
- u16 old;
+ struct thresh_restart tr;
unsigned long new = simple_strtoul(buf, &end, 0);
if (end == buf)
return -EINVAL;
@@ -303,34 +300,36 @@ static ssize_t store_threshold_limit(struct threshold_block *b,
new = THRESHOLD_MAX;
if (new < 1)
new = 1;
- old = b->threshold_limit;
+ tr.old_limit = b->threshold_limit;
b->threshold_limit = new;
+ tr.b = b;
+ tr.reset = 0;
- affinity_set(b->cpu, &oldmask, &newmask);
- threshold_restart_bank(b, 0, old);
- affinity_restore(&oldmask);
+ work_on_cpu(b->cpu, threshold_restart_bank, &tr);
return end - buf;
}
-static ssize_t show_error_count(struct threshold_block *b, char *buf)
+static long local_error_count(void *_b)
{
- u32 high, low;
- cpumask_t oldmask, newmask;
- affinity_set(b->cpu, &oldmask, &newmask);
+ struct threshold_block *b = _b;
+ u32 low, high;
+
rdmsr(b->address, low, high);
- affinity_restore(&oldmask);
- return sprintf(buf, "%x\n",
- (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit));
+ return (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
+}
+
+static ssize_t show_error_count(struct threshold_block *b, char *buf)
+{
+ return sprintf(buf, "%lx\n", work_on_cpu(b->cpu, local_error_count, b));
}
static ssize_t store_error_count(struct threshold_block *b,
const char *buf, size_t count)
{
- cpumask_t oldmask, newmask;
- affinity_set(b->cpu, &oldmask, &newmask);
- threshold_restart_bank(b, 1, 0);
- affinity_restore(&oldmask);
+ struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
+
+ work_on_cpu(b->cpu, threshold_restart_bank, &tr);
return 1;
}
@@ -463,12 +462,19 @@ out_free:
return err;
}
+static __cpuinit long local_allocate_threshold_blocks(void *_bank)
+{
+ unsigned int *bank = _bank;
+
+ return allocate_threshold_blocks(smp_processor_id(), *bank, 0,
+ MSR_IA32_MC0_MISC + *bank * 4);
+}
+
/* symlinks sibling shared banks to first core. first core owns dir/files. */
static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
{
int i, err = 0;
struct threshold_bank *b = NULL;
- cpumask_t oldmask, newmask;
char name[32];
sprintf(name, "threshold_bank%i", bank);
@@ -519,11 +525,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
per_cpu(threshold_banks, cpu)[bank] = b;
- affinity_set(cpu, &oldmask, &newmask);
- err = allocate_threshold_blocks(cpu, bank, 0,
- MSR_IA32_MC0_MISC + bank * 4);
- affinity_restore(&oldmask);
-
+ err = work_on_cpu(cpu, local_allocate_threshold_blocks, &bank);
if (err)
goto out_free;
diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c
index bfa5817afdda..c9f77ea69edc 100644
--- a/arch/x86/kernel/cpu/mcheck/p5.c
+++ b/arch/x86/kernel/cpu/mcheck/p5.c
@@ -1,6 +1,6 @@
/*
* P5 specific Machine Check Exception Reporting
- * (C) Copyright 2002 Alan Cox <alan@redhat.com>
+ * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>
*/
#include <linux/init.h>
diff --git a/arch/x86/kernel/cpu/mcheck/p6.c b/arch/x86/kernel/cpu/mcheck/p6.c
index 62efc9c2b3af..2ac52d7b434b 100644
--- a/arch/x86/kernel/cpu/mcheck/p6.c
+++ b/arch/x86/kernel/cpu/mcheck/p6.c
@@ -1,6 +1,6 @@
/*
* P6 specific Machine Check Exception Reporting
- * (C) Copyright 2002 Alan Cox <alan@redhat.com>
+ * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>
*/
#include <linux/init.h>
diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c
index f2be3e190c6b..2a043d89811d 100644
--- a/arch/x86/kernel/cpu/mcheck/winchip.c
+++ b/arch/x86/kernel/cpu/mcheck/winchip.c
@@ -1,6 +1,6 @@
/*
* IDT Winchip specific Machine Check Exception Reporting
- * (C) Copyright 2002 Alan Cox <alan@redhat.com>
+ * (C) Copyright 2002 Alan Cox <alan@lxorguk.ukuu.org.uk>
*/
#include <linux/init.h>
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 4e8d77f01eeb..0c0a455fe95c 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -14,14 +14,6 @@
#include <asm/pat.h>
#include "mtrr.h"
-struct mtrr_state {
- struct mtrr_var_range var_ranges[MAX_VAR_RANGES];
- mtrr_type fixed_ranges[NUM_FIXED_RANGES];
- unsigned char enabled;
- unsigned char have_fixed;
- mtrr_type def_type;
-};
-
struct fixed_range_block {
int base_msr; /* start address of an MTRR block */
int ranges; /* number of MTRRs in this block */
@@ -35,15 +27,19 @@ static struct fixed_range_block fixed_range_blocks[] = {
};
static unsigned long smp_changes_mask;
-static struct mtrr_state mtrr_state = {};
static int mtrr_state_set;
u64 mtrr_tom2;
-#undef MODULE_PARAM_PREFIX
-#define MODULE_PARAM_PREFIX "mtrr."
+struct mtrr_state_type mtrr_state = {};
+EXPORT_SYMBOL_GPL(mtrr_state);
-static int mtrr_show;
-module_param_named(show, mtrr_show, bool, 0);
+static int __initdata mtrr_show;
+static int __init mtrr_debug(char *opt)
+{
+ mtrr_show = 1;
+ return 0;
+}
+early_param("mtrr.show", mtrr_debug);
/*
* Returns the effective MTRR type for the region
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
index 1159e269e596..236a401b8259 100644
--- a/arch/x86/kernel/cpu/mtrr/main.c
+++ b/arch/x86/kernel/cpu/mtrr/main.c
@@ -49,7 +49,7 @@
u32 num_var_ranges = 0;
-unsigned int mtrr_usage_table[MAX_VAR_RANGES];
+unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
static DEFINE_MUTEX(mtrr_mutex);
u64 size_or_mask, size_and_mask;
@@ -574,7 +574,7 @@ struct mtrr_value {
unsigned long lsize;
};
-static struct mtrr_value mtrr_state[MAX_VAR_RANGES];
+static struct mtrr_value mtrr_state[MTRR_MAX_VAR_RANGES];
static int mtrr_save(struct sys_device * sysdev, pm_message_t state)
{
@@ -824,16 +824,14 @@ static int enable_mtrr_cleanup __initdata =
static int __init disable_mtrr_cleanup_setup(char *str)
{
- if (enable_mtrr_cleanup != -1)
- enable_mtrr_cleanup = 0;
+ enable_mtrr_cleanup = 0;
return 0;
}
early_param("disable_mtrr_cleanup", disable_mtrr_cleanup_setup);
static int __init enable_mtrr_cleanup_setup(char *str)
{
- if (enable_mtrr_cleanup != -1)
- enable_mtrr_cleanup = 1;
+ enable_mtrr_cleanup = 1;
return 0;
}
early_param("enable_mtrr_cleanup", enable_mtrr_cleanup_setup);
@@ -1596,8 +1594,7 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
/* kvm/qemu doesn't have mtrr set right, don't trim them all */
if (!highest_pfn) {
- WARN(!kvm_para_available(), KERN_WARNING
- "WARNING: strange, CPU MTRRs all blank?\n");
+ printk(KERN_INFO "CPU MTRRs all blank - virtualized system.\n");
return 0;
}
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 2dc4ec656b23..ffd60409cc6d 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -8,11 +8,6 @@
#define MTRRcap_MSR 0x0fe
#define MTRRdefType_MSR 0x2ff
-#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
-#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
-
-#define NUM_FIXED_RANGES 88
-#define MAX_VAR_RANGES 256
#define MTRRfix64K_00000_MSR 0x250
#define MTRRfix16K_80000_MSR 0x258
#define MTRRfix16K_A0000_MSR 0x259
@@ -29,11 +24,7 @@
#define MTRR_CHANGE_MASK_VARIABLE 0x02
#define MTRR_CHANGE_MASK_DEFTYPE 0x04
-/* In the Intel processor's MTRR interface, the MTRR type is always held in
- an 8 bit field: */
-typedef u8 mtrr_type;
-
-extern unsigned int mtrr_usage_table[MAX_VAR_RANGES];
+extern unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
struct mtrr_ops {
u32 vendor;
@@ -70,13 +61,6 @@ struct set_mtrr_context {
u32 ccr3;
};
-struct mtrr_var_range {
- u32 base_lo;
- u32 base_hi;
- u32 mask_lo;
- u32 mask_hi;
-};
-
void set_mtrr_done(struct set_mtrr_context *ctxt);
void set_mtrr_cache_disable(struct set_mtrr_context *ctxt);
void set_mtrr_prepare_save(struct set_mtrr_context *ctxt);
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index 72cefd1e649b..2ac1f0c2beb3 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -39,10 +39,10 @@
#include <linux/device.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
+#include <linux/uaccess.h>
#include <asm/processor.h>
#include <asm/msr.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
static struct class *cpuid_class;
@@ -82,7 +82,7 @@ static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
}
static ssize_t cpuid_read(struct file *file, char __user *buf,
- size_t count, loff_t * ppos)
+ size_t count, loff_t *ppos)
{
char __user *tmp = buf;
struct cpuid_regs cmd;
@@ -117,11 +117,11 @@ static int cpuid_open(struct inode *inode, struct file *file)
unsigned int cpu;
struct cpuinfo_x86 *c;
int ret = 0;
-
+
lock_kernel();
cpu = iminor(file->f_path.dentry->d_inode);
- if (cpu >= NR_CPUS || !cpu_online(cpu)) {
+ if (cpu >= nr_cpu_ids || !cpu_online(cpu)) {
ret = -ENXIO; /* No such CPU */
goto out;
}
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index d84a852e4cd7..c689d19e35ab 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -26,6 +26,7 @@
#include <linux/kdebug.h>
#include <asm/smp.h>
#include <asm/reboot.h>
+#include <asm/virtext.h>
#include <mach_ipi.h>
@@ -49,6 +50,15 @@ static void kdump_nmi_callback(int cpu, struct die_args *args)
#endif
crash_save_cpu(regs, cpu);
+ /* Disable VMX or SVM if needed.
+ *
+ * We need to disable virtualization on all CPUs.
+ * Having VMX or SVM enabled on any CPU may break rebooting
+ * after the kdump kernel has finished its task.
+ */
+ cpu_emergency_vmxoff();
+ cpu_emergency_svm_disable();
+
disable_local_APIC();
}
@@ -80,6 +90,14 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
local_irq_disable();
kdump_nmi_shootdown_cpus();
+
+ /* Booting kdump kernel with VMX or SVM enabled won't work,
+ * because (among other limitations) we can't disable paging
+ * with the virt flags.
+ */
+ cpu_emergency_vmxoff();
+ cpu_emergency_svm_disable();
+
lapic_shutdown();
#if defined(CONFIG_X86_IO_APIC)
disable_IO_APIC();
diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c
index da91701a2348..169a120587be 100644
--- a/arch/x86/kernel/ds.c
+++ b/arch/x86/kernel/ds.c
@@ -15,8 +15,8 @@
* - buffer allocation (memory accounting)
*
*
- * Copyright (C) 2007-2008 Intel Corporation.
- * Markus Metzger <markus.t.metzger@intel.com>, 2007-2008
+ * Copyright (C) 2007-2009 Intel Corporation.
+ * Markus Metzger <markus.t.metzger@intel.com>, 2007-2009
*/
@@ -890,7 +890,7 @@ int ds_set_pebs_reset(struct pebs_tracer *tracer, u64 value)
}
static const struct ds_configuration ds_cfg_netburst = {
- .name = "netburst",
+ .name = "Netburst",
.ctl[dsf_bts] = (1 << 2) | (1 << 3),
.ctl[dsf_bts_kernel] = (1 << 5),
.ctl[dsf_bts_user] = (1 << 6),
@@ -904,7 +904,7 @@ static const struct ds_configuration ds_cfg_netburst = {
#endif
};
static const struct ds_configuration ds_cfg_pentium_m = {
- .name = "pentium m",
+ .name = "Pentium M",
.ctl[dsf_bts] = (1 << 6) | (1 << 7),
.sizeof_field = sizeof(long),
@@ -915,8 +915,8 @@ static const struct ds_configuration ds_cfg_pentium_m = {
.sizeof_rec[ds_pebs] = sizeof(long) * 18,
#endif
};
-static const struct ds_configuration ds_cfg_core2 = {
- .name = "core 2",
+static const struct ds_configuration ds_cfg_core2_atom = {
+ .name = "Core 2/Atom",
.ctl[dsf_bts] = (1 << 6) | (1 << 7),
.ctl[dsf_bts_kernel] = (1 << 9),
.ctl[dsf_bts_user] = (1 << 10),
@@ -949,19 +949,22 @@ void __cpuinit ds_init_intel(struct cpuinfo_x86 *c)
switch (c->x86) {
case 0x6:
switch (c->x86_model) {
- case 0 ... 0xC:
- /* sorry, don't know about them */
- break;
- case 0xD:
- case 0xE: /* Pentium M */
+ case 0x9:
+ case 0xd: /* Pentium M */
ds_configure(&ds_cfg_pentium_m);
break;
- default: /* Core2, Atom, ... */
- ds_configure(&ds_cfg_core2);
+ case 0xf:
+ case 0x17: /* Core2 */
+ case 0x1c: /* Atom */
+ ds_configure(&ds_cfg_core2_atom);
+ break;
+ case 0x1a: /* i7 */
+ default:
+ /* sorry, don't know about them */
break;
}
break;
- case 0xF:
+ case 0xf:
switch (c->x86_model) {
case 0x0:
case 0x1:
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 65a13943e098..e85826829cf2 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -665,6 +665,27 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
}
#endif
+#ifdef CONFIG_HIBERNATION
+/**
+ * Mark ACPI NVS memory region, so that we can save/restore it during
+ * hibernation and the subsequent resume.
+ */
+static int __init e820_mark_nvs_memory(void)
+{
+ int i;
+
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+
+ if (ei->type == E820_NVS)
+ hibernate_nvs_register(ei->addr, ei->size);
+ }
+
+ return 0;
+}
+core_initcall(e820_mark_nvs_memory);
+#endif
+
/*
* Early reserved memory areas.
*/
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 744aa7fc49d5..76b8cd953dee 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -201,6 +201,12 @@ struct chipset {
void (*f)(int num, int slot, int func);
};
+/*
+ * Only works for devices on the root bus. If you add any devices
+ * not on bus 0 readd another loop level in early_quirks(). But
+ * be careful because at least the Nvidia quirk here relies on
+ * only matching on bus 0.
+ */
static struct chipset early_qrk[] __initdata = {
{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs },
@@ -267,17 +273,17 @@ static int __init check_dev_quirk(int num, int slot, int func)
void __init early_quirks(void)
{
- int num, slot, func;
+ int slot, func;
if (!early_pci_allowed())
return;
/* Poor man's PCI discovery */
- for (num = 0; num < 32; num++)
- for (slot = 0; slot < 32; slot++)
- for (func = 0; func < 8; func++) {
- /* Only probe function 0 on single fn devices */
- if (check_dev_quirk(num, slot, func))
- break;
- }
+ /* Only scan the root bus */
+ for (slot = 0; slot < 32; slot++)
+ for (func = 0; func < 8; func++) {
+ /* Only probe function 0 on single fn devices */
+ if (check_dev_quirk(0, slot, func))
+ break;
+ }
}
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 23b138e31e9c..504ad198e4ad 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -886,7 +886,7 @@ asmlinkage void early_printk(const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- n = vscnprintf(buf, 512, fmt, ap);
+ n = vscnprintf(buf, sizeof(buf), fmt, ap);
early_console->write(early_console, buf, n);
va_end(ap);
}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index d6f0490a7391..46469029e9d3 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1203,7 +1203,6 @@ nmi_stack_correct:
pushl %eax
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL
- TRACE_IRQS_OFF
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
@@ -1244,7 +1243,6 @@ nmi_espfix_stack:
pushl %eax
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL
- TRACE_IRQS_OFF
FIXUP_ESPFIX_STACK # %eax == %esp
xorl %edx,%edx # zero error code
call do_nmi
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index e28c7a987793..a1346217e43c 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -346,6 +346,7 @@ ENTRY(save_args)
popq_cfi %rax /* move return address... */
mov %gs:pda_irqstackptr,%rsp
EMPTY_FRAME 0
+ pushq_cfi %rbp /* backlink for unwinder */
pushq_cfi %rax /* ... to the new stack */
/*
* We entered an interrupt context - irqs are off:
diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/genapic_flat_64.c
index c0262791bda4..34185488e4fb 100644
--- a/arch/x86/kernel/genapic_flat_64.c
+++ b/arch/x86/kernel/genapic_flat_64.c
@@ -30,12 +30,12 @@ static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
return 1;
}
-static cpumask_t flat_target_cpus(void)
+static const struct cpumask *flat_target_cpus(void)
{
- return cpu_online_map;
+ return cpu_online_mask;
}
-static cpumask_t flat_vector_allocation_domain(int cpu)
+static void flat_vector_allocation_domain(int cpu, struct cpumask *retmask)
{
/* Careful. Some cpus do not strictly honor the set of cpus
* specified in the interrupt destination when using lowest
@@ -45,8 +45,8 @@ static cpumask_t flat_vector_allocation_domain(int cpu)
* deliver interrupts to the wrong hyperthread when only one
* hyperthread was specified in the interrupt desitination.
*/
- cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
- return domain;
+ cpumask_clear(retmask);
+ cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
}
/*
@@ -69,9 +69,8 @@ static void flat_init_apic_ldr(void)
apic_write(APIC_LDR, val);
}
-static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
+static inline void _flat_send_IPI_mask(unsigned long mask, int vector)
{
- unsigned long mask = cpus_addr(cpumask)[0];
unsigned long flags;
local_irq_save(flags);
@@ -79,20 +78,41 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
local_irq_restore(flags);
}
+static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
+{
+ unsigned long mask = cpumask_bits(cpumask)[0];
+
+ _flat_send_IPI_mask(mask, vector);
+}
+
+static void flat_send_IPI_mask_allbutself(const struct cpumask *cpumask,
+ int vector)
+{
+ unsigned long mask = cpumask_bits(cpumask)[0];
+ int cpu = smp_processor_id();
+
+ if (cpu < BITS_PER_LONG)
+ clear_bit(cpu, &mask);
+ _flat_send_IPI_mask(mask, vector);
+}
+
static void flat_send_IPI_allbutself(int vector)
{
+ int cpu = smp_processor_id();
#ifdef CONFIG_HOTPLUG_CPU
int hotplug = 1;
#else
int hotplug = 0;
#endif
if (hotplug || vector == NMI_VECTOR) {
- cpumask_t allbutme = cpu_online_map;
+ if (!cpumask_equal(cpu_online_mask, cpumask_of(cpu))) {
+ unsigned long mask = cpumask_bits(cpu_online_mask)[0];
- cpu_clear(smp_processor_id(), allbutme);
+ if (cpu < BITS_PER_LONG)
+ clear_bit(cpu, &mask);
- if (!cpus_empty(allbutme))
- flat_send_IPI_mask(allbutme, vector);
+ _flat_send_IPI_mask(mask, vector);
+ }
} else if (num_online_cpus() > 1) {
__send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL);
}
@@ -101,7 +121,7 @@ static void flat_send_IPI_allbutself(int vector)
static void flat_send_IPI_all(int vector)
{
if (vector == NMI_VECTOR)
- flat_send_IPI_mask(cpu_online_map, vector);
+ flat_send_IPI_mask(cpu_online_mask, vector);
else
__send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
}
@@ -135,9 +155,18 @@ static int flat_apic_id_registered(void)
return physid_isset(read_xapic_id(), phys_cpu_present_map);
}
-static unsigned int flat_cpu_mask_to_apicid(cpumask_t cpumask)
+static unsigned int flat_cpu_mask_to_apicid(const struct cpumask *cpumask)
+{
+ return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
+}
+
+static unsigned int flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
{
- return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
+ unsigned long mask1 = cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
+ unsigned long mask2 = cpumask_bits(andmask)[0] & APIC_ALL_CPUS;
+
+ return mask1 & mask2;
}
static unsigned int phys_pkg_id(int index_msb)
@@ -157,8 +186,10 @@ struct genapic apic_flat = {
.send_IPI_all = flat_send_IPI_all,
.send_IPI_allbutself = flat_send_IPI_allbutself,
.send_IPI_mask = flat_send_IPI_mask,
+ .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself,
.send_IPI_self = apic_send_IPI_self,
.cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
+ .cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and,
.phys_pkg_id = phys_pkg_id,
.get_apic_id = get_apic_id,
.set_apic_id = set_apic_id,
@@ -188,35 +219,39 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
return 0;
}
-static cpumask_t physflat_target_cpus(void)
+static const struct cpumask *physflat_target_cpus(void)
{
- return cpu_online_map;
+ return cpu_online_mask;
}
-static cpumask_t physflat_vector_allocation_domain(int cpu)
+static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask)
{
- return cpumask_of_cpu(cpu);
+ cpumask_clear(retmask);
+ cpumask_set_cpu(cpu, retmask);
}
-static void physflat_send_IPI_mask(cpumask_t cpumask, int vector)
+static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector)
{
send_IPI_mask_sequence(cpumask, vector);
}
-static void physflat_send_IPI_allbutself(int vector)
+static void physflat_send_IPI_mask_allbutself(const struct cpumask *cpumask,
+ int vector)
{
- cpumask_t allbutme = cpu_online_map;
+ send_IPI_mask_allbutself(cpumask, vector);
+}
- cpu_clear(smp_processor_id(), allbutme);
- physflat_send_IPI_mask(allbutme, vector);
+static void physflat_send_IPI_allbutself(int vector)
+{
+ send_IPI_mask_allbutself(cpu_online_mask, vector);
}
static void physflat_send_IPI_all(int vector)
{
- physflat_send_IPI_mask(cpu_online_map, vector);
+ physflat_send_IPI_mask(cpu_online_mask, vector);
}
-static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
+static unsigned int physflat_cpu_mask_to_apicid(const struct cpumask *cpumask)
{
int cpu;
@@ -224,13 +259,31 @@ static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
* We're using fixed IRQ delivery, can only return one phys APIC ID.
* May as well be the first.
*/
- cpu = first_cpu(cpumask);
+ cpu = cpumask_first(cpumask);
if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;
}
+static unsigned int
+physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
+{
+ int cpu;
+
+ /*
+ * We're using fixed IRQ delivery, can only return one phys APIC ID.
+ * May as well be the first.
+ */
+ for_each_cpu_and(cpu, cpumask, andmask)
+ if (cpumask_test_cpu(cpu, cpu_online_mask))
+ break;
+ if (cpu < nr_cpu_ids)
+ return per_cpu(x86_cpu_to_apicid, cpu);
+ return BAD_APICID;
+}
+
struct genapic apic_physflat = {
.name = "physical flat",
.acpi_madt_oem_check = physflat_acpi_madt_oem_check,
@@ -243,8 +296,10 @@ struct genapic apic_physflat = {
.send_IPI_all = physflat_send_IPI_all,
.send_IPI_allbutself = physflat_send_IPI_allbutself,
.send_IPI_mask = physflat_send_IPI_mask,
+ .send_IPI_mask_allbutself = physflat_send_IPI_mask_allbutself,
.send_IPI_self = apic_send_IPI_self,
.cpu_mask_to_apicid = physflat_cpu_mask_to_apicid,
+ .cpu_mask_to_apicid_and = physflat_cpu_mask_to_apicid_and,
.phys_pkg_id = phys_pkg_id,
.get_apic_id = get_apic_id,
.set_apic_id = set_apic_id,
diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/genx2apic_cluster.c
index f6a2c8eb48a6..6ce497cc372d 100644
--- a/arch/x86/kernel/genx2apic_cluster.c
+++ b/arch/x86/kernel/genx2apic_cluster.c
@@ -22,19 +22,18 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
-static cpumask_t x2apic_target_cpus(void)
+static const struct cpumask *x2apic_target_cpus(void)
{
- return cpumask_of_cpu(0);
+ return cpumask_of(0);
}
/*
* for now each logical cpu is in its own vector allocation domain.
*/
-static cpumask_t x2apic_vector_allocation_domain(int cpu)
+static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
{
- cpumask_t domain = CPU_MASK_NONE;
- cpu_set(cpu, domain);
- return domain;
+ cpumask_clear(retmask);
+ cpumask_set_cpu(cpu, retmask);
}
static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
@@ -56,32 +55,53 @@ static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
* at once. We have 16 cpu's in a cluster. This will minimize IPI register
* writes.
*/
-static void x2apic_send_IPI_mask(cpumask_t mask, int vector)
+static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
{
unsigned long flags;
unsigned long query_cpu;
local_irq_save(flags);
- for_each_cpu_mask(query_cpu, mask) {
- __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_logical_apicid, query_cpu),
- vector, APIC_DEST_LOGICAL);
- }
+ for_each_cpu(query_cpu, mask)
+ __x2apic_send_IPI_dest(
+ per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+ vector, APIC_DEST_LOGICAL);
local_irq_restore(flags);
}
-static void x2apic_send_IPI_allbutself(int vector)
+static void x2apic_send_IPI_mask_allbutself(const struct cpumask *mask,
+ int vector)
{
- cpumask_t mask = cpu_online_map;
+ unsigned long flags;
+ unsigned long query_cpu;
+ unsigned long this_cpu = smp_processor_id();
- cpu_clear(smp_processor_id(), mask);
+ local_irq_save(flags);
+ for_each_cpu(query_cpu, mask)
+ if (query_cpu != this_cpu)
+ __x2apic_send_IPI_dest(
+ per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+ vector, APIC_DEST_LOGICAL);
+ local_irq_restore(flags);
+}
+
+static void x2apic_send_IPI_allbutself(int vector)
+{
+ unsigned long flags;
+ unsigned long query_cpu;
+ unsigned long this_cpu = smp_processor_id();
- if (!cpus_empty(mask))
- x2apic_send_IPI_mask(mask, vector);
+ local_irq_save(flags);
+ for_each_online_cpu(query_cpu)
+ if (query_cpu != this_cpu)
+ __x2apic_send_IPI_dest(
+ per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+ vector, APIC_DEST_LOGICAL);
+ local_irq_restore(flags);
}
static void x2apic_send_IPI_all(int vector)
{
- x2apic_send_IPI_mask(cpu_online_map, vector);
+ x2apic_send_IPI_mask(cpu_online_mask, vector);
}
static int x2apic_apic_id_registered(void)
@@ -89,21 +109,38 @@ static int x2apic_apic_id_registered(void)
return 1;
}
-static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask)
+static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
{
int cpu;
/*
- * We're using fixed IRQ delivery, can only return one phys APIC ID.
+ * We're using fixed IRQ delivery, can only return one logical APIC ID.
* May as well be the first.
*/
- cpu = first_cpu(cpumask);
- if ((unsigned)cpu < NR_CPUS)
+ cpu = cpumask_first(cpumask);
+ if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_logical_apicid, cpu);
else
return BAD_APICID;
}
+static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
+{
+ int cpu;
+
+ /*
+ * We're using fixed IRQ delivery, can only return one logical APIC ID.
+ * May as well be the first.
+ */
+ for_each_cpu_and(cpu, cpumask, andmask)
+ if (cpumask_test_cpu(cpu, cpu_online_mask))
+ break;
+ if (cpu < nr_cpu_ids)
+ return per_cpu(x86_cpu_to_logical_apicid, cpu);
+ return BAD_APICID;
+}
+
static unsigned int get_apic_id(unsigned long x)
{
unsigned int id;
@@ -150,8 +187,10 @@ struct genapic apic_x2apic_cluster = {
.send_IPI_all = x2apic_send_IPI_all,
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
.send_IPI_mask = x2apic_send_IPI_mask,
+ .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself,
.send_IPI_self = x2apic_send_IPI_self,
.cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid,
+ .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and,
.phys_pkg_id = phys_pkg_id,
.get_apic_id = get_apic_id,
.set_apic_id = set_apic_id,
diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/genx2apic_phys.c
index d042211768b7..21bcc0e098ba 100644
--- a/arch/x86/kernel/genx2apic_phys.c
+++ b/arch/x86/kernel/genx2apic_phys.c
@@ -29,16 +29,15 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
-static cpumask_t x2apic_target_cpus(void)
+static const struct cpumask *x2apic_target_cpus(void)
{
- return cpumask_of_cpu(0);
+ return cpumask_of(0);
}
-static cpumask_t x2apic_vector_allocation_domain(int cpu)
+static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
{
- cpumask_t domain = CPU_MASK_NONE;
- cpu_set(cpu, domain);
- return domain;
+ cpumask_clear(retmask);
+ cpumask_set_cpu(cpu, retmask);
}
static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
@@ -54,32 +53,54 @@ static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
x2apic_icr_write(cfg, apicid);
}
-static void x2apic_send_IPI_mask(cpumask_t mask, int vector)
+static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
{
unsigned long flags;
unsigned long query_cpu;
local_irq_save(flags);
- for_each_cpu_mask(query_cpu, mask) {
+ for_each_cpu(query_cpu, mask) {
__x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
vector, APIC_DEST_PHYSICAL);
}
local_irq_restore(flags);
}
-static void x2apic_send_IPI_allbutself(int vector)
+static void x2apic_send_IPI_mask_allbutself(const struct cpumask *mask,
+ int vector)
{
- cpumask_t mask = cpu_online_map;
+ unsigned long flags;
+ unsigned long query_cpu;
+ unsigned long this_cpu = smp_processor_id();
+
+ local_irq_save(flags);
+ for_each_cpu(query_cpu, mask) {
+ if (query_cpu != this_cpu)
+ __x2apic_send_IPI_dest(
+ per_cpu(x86_cpu_to_apicid, query_cpu),
+ vector, APIC_DEST_PHYSICAL);
+ }
+ local_irq_restore(flags);
+}
- cpu_clear(smp_processor_id(), mask);
+static void x2apic_send_IPI_allbutself(int vector)
+{
+ unsigned long flags;
+ unsigned long query_cpu;
+ unsigned long this_cpu = smp_processor_id();
- if (!cpus_empty(mask))
- x2apic_send_IPI_mask(mask, vector);
+ local_irq_save(flags);
+ for_each_online_cpu(query_cpu)
+ if (query_cpu != this_cpu)
+ __x2apic_send_IPI_dest(
+ per_cpu(x86_cpu_to_apicid, query_cpu),
+ vector, APIC_DEST_PHYSICAL);
+ local_irq_restore(flags);
}
static void x2apic_send_IPI_all(int vector)
{
- x2apic_send_IPI_mask(cpu_online_map, vector);
+ x2apic_send_IPI_mask(cpu_online_mask, vector);
}
static int x2apic_apic_id_registered(void)
@@ -87,7 +108,7 @@ static int x2apic_apic_id_registered(void)
return 1;
}
-static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask)
+static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
{
int cpu;
@@ -95,13 +116,30 @@ static unsigned int x2apic_cpu_mask_to_apicid(cpumask_t cpumask)
* We're using fixed IRQ delivery, can only return one phys APIC ID.
* May as well be the first.
*/
- cpu = first_cpu(cpumask);
- if ((unsigned)cpu < NR_CPUS)
+ cpu = cpumask_first(cpumask);
+ if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;
}
+static unsigned int x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
+{
+ int cpu;
+
+ /*
+ * We're using fixed IRQ delivery, can only return one phys APIC ID.
+ * May as well be the first.
+ */
+ for_each_cpu_and(cpu, cpumask, andmask)
+ if (cpumask_test_cpu(cpu, cpu_online_mask))
+ break;
+ if (cpu < nr_cpu_ids)
+ return per_cpu(x86_cpu_to_apicid, cpu);
+ return BAD_APICID;
+}
+
static unsigned int get_apic_id(unsigned long x)
{
unsigned int id;
@@ -123,12 +161,12 @@ static unsigned int phys_pkg_id(int index_msb)
return current_cpu_data.initial_apicid >> index_msb;
}
-void x2apic_send_IPI_self(int vector)
+static void x2apic_send_IPI_self(int vector)
{
apic_write(APIC_SELF_IPI, vector);
}
-void init_x2apic_ldr(void)
+static void init_x2apic_ldr(void)
{
return;
}
@@ -145,8 +183,10 @@ struct genapic apic_x2apic_phys = {
.send_IPI_all = x2apic_send_IPI_all,
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
.send_IPI_mask = x2apic_send_IPI_mask,
+ .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself,
.send_IPI_self = x2apic_send_IPI_self,
.cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid,
+ .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and,
.phys_pkg_id = phys_pkg_id,
.get_apic_id = get_apic_id,
.set_apic_id = set_apic_id,
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c
index dece17289731..b193e082f6ce 100644
--- a/arch/x86/kernel/genx2apic_uv_x.c
+++ b/arch/x86/kernel/genx2apic_uv_x.c
@@ -79,16 +79,15 @@ EXPORT_SYMBOL(sn_rtc_cycles_per_second);
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
-static cpumask_t uv_target_cpus(void)
+static const struct cpumask *uv_target_cpus(void)
{
- return cpumask_of_cpu(0);
+ return cpumask_of(0);
}
-static cpumask_t uv_vector_allocation_domain(int cpu)
+static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
{
- cpumask_t domain = CPU_MASK_NONE;
- cpu_set(cpu, domain);
- return domain;
+ cpumask_clear(retmask);
+ cpumask_set_cpu(cpu, retmask);
}
int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip)
@@ -127,28 +126,37 @@ static void uv_send_IPI_one(int cpu, int vector)
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
}
-static void uv_send_IPI_mask(cpumask_t mask, int vector)
+static void uv_send_IPI_mask(const struct cpumask *mask, int vector)
{
unsigned int cpu;
- for_each_possible_cpu(cpu)
- if (cpu_isset(cpu, mask))
+ for_each_cpu(cpu, mask)
+ uv_send_IPI_one(cpu, vector);
+}
+
+static void uv_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
+{
+ unsigned int cpu;
+ unsigned int this_cpu = smp_processor_id();
+
+ for_each_cpu(cpu, mask)
+ if (cpu != this_cpu)
uv_send_IPI_one(cpu, vector);
}
static void uv_send_IPI_allbutself(int vector)
{
- cpumask_t mask = cpu_online_map;
-
- cpu_clear(smp_processor_id(), mask);
+ unsigned int cpu;
+ unsigned int this_cpu = smp_processor_id();
- if (!cpus_empty(mask))
- uv_send_IPI_mask(mask, vector);
+ for_each_online_cpu(cpu)
+ if (cpu != this_cpu)
+ uv_send_IPI_one(cpu, vector);
}
static void uv_send_IPI_all(int vector)
{
- uv_send_IPI_mask(cpu_online_map, vector);
+ uv_send_IPI_mask(cpu_online_mask, vector);
}
static int uv_apic_id_registered(void)
@@ -160,7 +168,7 @@ static void uv_init_apic_ldr(void)
{
}
-static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
+static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask)
{
int cpu;
@@ -168,13 +176,30 @@ static unsigned int uv_cpu_mask_to_apicid(cpumask_t cpumask)
* We're using fixed IRQ delivery, can only return one phys APIC ID.
* May as well be the first.
*/
- cpu = first_cpu(cpumask);
+ cpu = cpumask_first(cpumask);
if ((unsigned)cpu < nr_cpu_ids)
return per_cpu(x86_cpu_to_apicid, cpu);
else
return BAD_APICID;
}
+static unsigned int uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
+{
+ int cpu;
+
+ /*
+ * We're using fixed IRQ delivery, can only return one phys APIC ID.
+ * May as well be the first.
+ */
+ for_each_cpu_and(cpu, cpumask, andmask)
+ if (cpumask_test_cpu(cpu, cpu_online_mask))
+ break;
+ if (cpu < nr_cpu_ids)
+ return per_cpu(x86_cpu_to_apicid, cpu);
+ return BAD_APICID;
+}
+
static unsigned int get_apic_id(unsigned long x)
{
unsigned int id;
@@ -222,8 +247,10 @@ struct genapic apic_x2apic_uv_x = {
.send_IPI_all = uv_send_IPI_all,
.send_IPI_allbutself = uv_send_IPI_allbutself,
.send_IPI_mask = uv_send_IPI_mask,
+ .send_IPI_mask_allbutself = uv_send_IPI_mask_allbutself,
.send_IPI_self = uv_send_IPI_self,
.cpu_mask_to_apicid = uv_cpu_mask_to_apicid,
+ .cpu_mask_to_apicid_and = uv_cpu_mask_to_apicid_and,
.phys_pkg_id = phys_pkg_id,
.get_apic_id = get_apic_id,
.set_apic_id = set_apic_id,
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 388e05a5fc17..b9a4d8c4b935 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -27,7 +27,7 @@
#include <asm/trampoline.h>
/* boot cpu pda */
-static struct x8664_pda _boot_cpu_pda __read_mostly;
+static struct x8664_pda _boot_cpu_pda;
#ifdef CONFIG_SMP
/*
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 26cfdc1d7c7f..0e275d495563 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -305,7 +305,7 @@ ENTRY(early_idt_handler)
call dump_stack
#ifdef CONFIG_KALLSYMS
leaq early_idt_ripmsg(%rip),%rdi
- movq 8(%rsp),%rsi # get rip again
+ movq 0(%rsp),%rsi # get rip again
call __print_symbol
#endif
#endif /* EARLY_PRINTK */
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 845ea097383e..64d5ad0b8add 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -248,7 +248,7 @@ static void hpet_legacy_clockevent_register(void)
* Start hpet with the boot cpu mask and make it
* global after the IO_APIC has been initialized.
*/
- hpet_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
+ hpet_clockevent.cpumask = cpumask_of(smp_processor_id());
clockevents_register_device(&hpet_clockevent);
global_clock_event = &hpet_clockevent;
printk(KERN_DEBUG "hpet clockevent registered\n");
@@ -303,7 +303,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
hpet_setup_msi_irq(hdev->irq);
disable_irq(hdev->irq);
- irq_set_affinity(hdev->irq, cpumask_of_cpu(hdev->cpu));
+ irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
enable_irq(hdev->irq);
}
break;
@@ -451,7 +451,7 @@ static int hpet_setup_irq(struct hpet_dev *dev)
return -1;
disable_irq(dev->irq);
- irq_set_affinity(dev->irq, cpumask_of_cpu(dev->cpu));
+ irq_set_affinity(dev->irq, cpumask_of(dev->cpu));
enable_irq(dev->irq);
printk(KERN_DEBUG "hpet: %s irq %d for MSI\n",
@@ -502,7 +502,7 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
/* 5 usec minimum reprogramming delta. */
evt->min_delta_ns = 5000;
- evt->cpumask = cpumask_of_cpu(hdev->cpu);
+ evt->cpumask = cpumask_of(hdev->cpu);
clockevents_register_device(evt);
}
@@ -628,11 +628,12 @@ static int hpet_cpuhp_notify(struct notifier_block *n,
switch (action & 0xf) {
case CPU_ONLINE:
- INIT_DELAYED_WORK(&work.work, hpet_work);
+ INIT_DELAYED_WORK_ON_STACK(&work.work, hpet_work);
init_completion(&work.complete);
/* FIXME: add schedule_work_on() */
schedule_delayed_work_on(cpu, &work.work, 0);
wait_for_completion(&work.complete);
+ destroy_timer_on_stack(&work.work.timer);
break;
case CPU_DEAD:
if (hdev) {
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c
index c1b5e3ece1f2..10f92fb532f3 100644
--- a/arch/x86/kernel/i8253.c
+++ b/arch/x86/kernel/i8253.c
@@ -114,7 +114,7 @@ void __init setup_pit_timer(void)
* Start pit with the boot cpu mask and make it global after the
* IO_APIC has been initialized.
*/
- pit_clockevent.cpumask = cpumask_of_cpu(smp_processor_id());
+ pit_clockevent.cpumask = cpumask_of(smp_processor_id());
pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
pit_clockevent.shift);
pit_clockevent.max_delta_ns =
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 4b8a53d841f7..11d5093eb281 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -11,15 +11,15 @@
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
#include <linux/bitops.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/delay.h>
-#include <asm/acpi.h>
#include <asm/atomic.h>
#include <asm/system.h>
-#include <asm/io.h>
#include <asm/timer.h>
#include <asm/hw_irq.h>
#include <asm/pgtable.h>
-#include <asm/delay.h>
#include <asm/desc.h>
#include <asm/apic.h>
#include <asm/arch_hooks.h>
@@ -323,7 +323,7 @@ void init_8259A(int auto_eoi)
outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
/* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64,
- to 0x20-0x27 on i386 */
+ to 0x20-0x27 on i386 */
outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);
/* 8259A-1 (the master) has a slave on IR2 */
diff --git a/arch/x86/kernel/init_task.c b/arch/x86/kernel/init_task.c
index d39918076bb4..df3bf269beab 100644
--- a/arch/x86/kernel/init_task.c
+++ b/arch/x86/kernel/init_task.c
@@ -10,7 +10,6 @@
#include <asm/pgtable.h>
#include <asm/desc.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/io_apic.c
index f6ea94b74da1..9b0c480c383b 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/io_apic.c
@@ -129,15 +129,14 @@ static struct irq_pin_list *get_one_free_irq_2_pin(int cpu)
node = cpu_to_node(cpu);
pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
- printk(KERN_DEBUG " alloc irq_2_pin on cpu %d node %d\n", cpu, node);
return pin;
}
struct irq_cfg {
struct irq_pin_list *irq_2_pin;
- cpumask_t domain;
- cpumask_t old_domain;
+ cpumask_var_t domain;
+ cpumask_var_t old_domain;
unsigned move_cleanup_count;
u8 vector;
u8 move_in_progress : 1;
@@ -152,25 +151,25 @@ static struct irq_cfg irq_cfgx[] = {
#else
static struct irq_cfg irq_cfgx[NR_IRQS] = {
#endif
- [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, },
- [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, },
- [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, },
- [3] = { .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR, },
- [4] = { .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR, },
- [5] = { .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR, },
- [6] = { .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR, },
- [7] = { .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR, },
- [8] = { .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR, },
- [9] = { .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR, },
- [10] = { .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
- [11] = { .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
- [12] = { .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
- [13] = { .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
- [14] = { .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
- [15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
+ [0] = { .vector = IRQ0_VECTOR, },
+ [1] = { .vector = IRQ1_VECTOR, },
+ [2] = { .vector = IRQ2_VECTOR, },
+ [3] = { .vector = IRQ3_VECTOR, },
+ [4] = { .vector = IRQ4_VECTOR, },
+ [5] = { .vector = IRQ5_VECTOR, },
+ [6] = { .vector = IRQ6_VECTOR, },
+ [7] = { .vector = IRQ7_VECTOR, },
+ [8] = { .vector = IRQ8_VECTOR, },
+ [9] = { .vector = IRQ9_VECTOR, },
+ [10] = { .vector = IRQ10_VECTOR, },
+ [11] = { .vector = IRQ11_VECTOR, },
+ [12] = { .vector = IRQ12_VECTOR, },
+ [13] = { .vector = IRQ13_VECTOR, },
+ [14] = { .vector = IRQ14_VECTOR, },
+ [15] = { .vector = IRQ15_VECTOR, },
};
-void __init arch_early_irq_init(void)
+int __init arch_early_irq_init(void)
{
struct irq_cfg *cfg;
struct irq_desc *desc;
@@ -183,7 +182,13 @@ void __init arch_early_irq_init(void)
for (i = 0; i < count; i++) {
desc = irq_to_desc(i);
desc->chip_data = &cfg[i];
+ alloc_bootmem_cpumask_var(&cfg[i].domain);
+ alloc_bootmem_cpumask_var(&cfg[i].old_domain);
+ if (i < NR_IRQS_LEGACY)
+ cpumask_setall(cfg[i].domain);
}
+
+ return 0;
}
#ifdef CONFIG_SPARSE_IRQ
@@ -207,12 +212,25 @@ static struct irq_cfg *get_one_free_irq_cfg(int cpu)
node = cpu_to_node(cpu);
cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
- printk(KERN_DEBUG " alloc irq_cfg on cpu %d node %d\n", cpu, node);
+ if (cfg) {
+ if (!alloc_cpumask_var_node(&cfg->domain, GFP_ATOMIC, node)) {
+ kfree(cfg);
+ cfg = NULL;
+ } else if (!alloc_cpumask_var_node(&cfg->old_domain,
+ GFP_ATOMIC, node)) {
+ free_cpumask_var(cfg->domain);
+ kfree(cfg);
+ cfg = NULL;
+ } else {
+ cpumask_clear(cfg->domain);
+ cpumask_clear(cfg->old_domain);
+ }
+ }
return cfg;
}
-void arch_init_chip_data(struct irq_desc *desc, int cpu)
+int arch_init_chip_data(struct irq_desc *desc, int cpu)
{
struct irq_cfg *cfg;
@@ -224,6 +242,8 @@ void arch_init_chip_data(struct irq_desc *desc, int cpu)
BUG_ON(1);
}
}
+
+ return 0;
}
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
@@ -329,13 +349,14 @@ void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)
}
}
-static void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask)
+static void
+set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
{
struct irq_cfg *cfg = desc->chip_data;
if (!cfg->move_in_progress) {
/* it means that domain is not changed */
- if (!cpus_intersects(desc->affinity, mask))
+ if (!cpumask_intersects(&desc->affinity, mask))
cfg->move_desc_pending = 1;
}
}
@@ -350,7 +371,8 @@ static struct irq_cfg *irq_cfg(unsigned int irq)
#endif
#ifndef CONFIG_NUMA_MIGRATE_IRQ_DESC
-static inline void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask)
+static inline void
+set_extra_move_desc(struct irq_desc *desc, const struct cpumask *mask)
{
}
#endif
@@ -481,6 +503,26 @@ static void ioapic_mask_entry(int apic, int pin)
}
#ifdef CONFIG_SMP
+static void send_cleanup_vector(struct irq_cfg *cfg)
+{
+ cpumask_var_t cleanup_mask;
+
+ if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+ unsigned int i;
+ cfg->move_cleanup_count = 0;
+ for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+ cfg->move_cleanup_count++;
+ for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+ send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+ } else {
+ cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+ cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+ send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+ free_cpumask_var(cleanup_mask);
+ }
+ cfg->move_in_progress = 0;
+}
+
static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
{
int apic, pin;
@@ -516,41 +558,55 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
}
}
-static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask);
+static int
+assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
-static void set_ioapic_affinity_irq_desc(struct irq_desc *desc, cpumask_t mask)
+/*
+ * Either sets desc->affinity to a valid value, and returns cpu_mask_to_apicid
+ * of that, or returns BAD_APICID and leaves desc->affinity untouched.
+ */
+static unsigned int
+set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
{
struct irq_cfg *cfg;
- unsigned long flags;
- unsigned int dest;
- cpumask_t tmp;
unsigned int irq;
- cpus_and(tmp, mask, cpu_online_map);
- if (cpus_empty(tmp))
- return;
+ if (!cpumask_intersects(mask, cpu_online_mask))
+ return BAD_APICID;
irq = desc->irq;
cfg = desc->chip_data;
if (assign_irq_vector(irq, cfg, mask))
- return;
+ return BAD_APICID;
+ cpumask_and(&desc->affinity, cfg->domain, mask);
set_extra_move_desc(desc, mask);
+ return cpu_mask_to_apicid_and(&desc->affinity, cpu_online_mask);
+}
- cpus_and(tmp, cfg->domain, mask);
- dest = cpu_mask_to_apicid(tmp);
- /*
- * Only the high 8 bits are valid.
- */
- dest = SET_APIC_LOGICAL_ID(dest);
+static void
+set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+{
+ struct irq_cfg *cfg;
+ unsigned long flags;
+ unsigned int dest;
+ unsigned int irq;
+
+ irq = desc->irq;
+ cfg = desc->chip_data;
spin_lock_irqsave(&ioapic_lock, flags);
- __target_IO_APIC_irq(irq, dest, cfg);
- desc->affinity = mask;
+ dest = set_desc_affinity(desc, mask);
+ if (dest != BAD_APICID) {
+ /* Only the high 8 bits are valid. */
+ dest = SET_APIC_LOGICAL_ID(dest);
+ __target_IO_APIC_irq(irq, dest, cfg);
+ }
spin_unlock_irqrestore(&ioapic_lock, flags);
}
-static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+static void
+set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc;
@@ -648,7 +704,7 @@ static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
}
#ifdef CONFIG_X86_64
-void io_apic_sync(struct irq_pin_list *entry)
+static void io_apic_sync(struct irq_pin_list *entry)
{
/*
* Synchronize the IO-APIC and the CPU by doing
@@ -1218,7 +1274,8 @@ void unlock_vector_lock(void)
spin_unlock(&vector_lock);
}
-static int __assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask)
+static int
+__assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
{
/*
* NOTE! The local APIC isn't very good at handling
@@ -1233,49 +1290,49 @@ static int __assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask)
*/
static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
unsigned int old_vector;
- int cpu;
+ int cpu, err;
+ cpumask_var_t tmp_mask;
if ((cfg->move_in_progress) || cfg->move_cleanup_count)
return -EBUSY;
- /* Only try and allocate irqs on cpus that are present */
- cpus_and(mask, mask, cpu_online_map);
+ if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC))
+ return -ENOMEM;
old_vector = cfg->vector;
if (old_vector) {
- cpumask_t tmp;
- cpus_and(tmp, cfg->domain, mask);
- if (!cpus_empty(tmp))
+ cpumask_and(tmp_mask, mask, cpu_online_mask);
+ cpumask_and(tmp_mask, cfg->domain, tmp_mask);
+ if (!cpumask_empty(tmp_mask)) {
+ free_cpumask_var(tmp_mask);
return 0;
+ }
}
- for_each_cpu_mask_nr(cpu, mask) {
- cpumask_t domain, new_mask;
+ /* Only try and allocate irqs on cpus that are present */
+ err = -ENOSPC;
+ for_each_cpu_and(cpu, mask, cpu_online_mask) {
int new_cpu;
int vector, offset;
- domain = vector_allocation_domain(cpu);
- cpus_and(new_mask, domain, cpu_online_map);
+ vector_allocation_domain(cpu, tmp_mask);
vector = current_vector;
offset = current_offset;
next:
vector += 8;
if (vector >= first_system_vector) {
- /* If we run out of vectors on large boxen, must share them. */
+ /* If out of vectors on large boxen, must share them. */
offset = (offset + 1) % 8;
vector = FIRST_DEVICE_VECTOR + offset;
}
if (unlikely(current_vector == vector))
continue;
-#ifdef CONFIG_X86_64
- if (vector == IA32_SYSCALL_VECTOR)
- goto next;
-#else
- if (vector == SYSCALL_VECTOR)
+
+ if (test_bit(vector, used_vectors))
goto next;
-#endif
- for_each_cpu_mask_nr(new_cpu, new_mask)
+
+ for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
if (per_cpu(vector_irq, new_cpu)[vector] != -1)
goto next;
/* Found one! */
@@ -1283,18 +1340,21 @@ next:
current_offset = offset;
if (old_vector) {
cfg->move_in_progress = 1;
- cfg->old_domain = cfg->domain;
+ cpumask_copy(cfg->old_domain, cfg->domain);
}
- for_each_cpu_mask_nr(new_cpu, new_mask)
+ for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask)
per_cpu(vector_irq, new_cpu)[vector] = irq;
cfg->vector = vector;
- cfg->domain = domain;
- return 0;
+ cpumask_copy(cfg->domain, tmp_mask);
+ err = 0;
+ break;
}
- return -ENOSPC;
+ free_cpumask_var(tmp_mask);
+ return err;
}
-static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask)
+static int
+assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
{
int err;
unsigned long flags;
@@ -1307,23 +1367,20 @@ static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask)
static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
{
- cpumask_t mask;
int cpu, vector;
BUG_ON(!cfg->vector);
vector = cfg->vector;
- cpus_and(mask, cfg->domain, cpu_online_map);
- for_each_cpu_mask_nr(cpu, mask)
+ for_each_cpu_and(cpu, cfg->domain, cpu_online_mask)
per_cpu(vector_irq, cpu)[vector] = -1;
cfg->vector = 0;
- cpus_clear(cfg->domain);
+ cpumask_clear(cfg->domain);
if (likely(!cfg->move_in_progress))
return;
- cpus_and(mask, cfg->old_domain, cpu_online_map);
- for_each_cpu_mask_nr(cpu, mask) {
+ for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) {
for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
vector++) {
if (per_cpu(vector_irq, cpu)[vector] != irq)
@@ -1345,10 +1402,8 @@ void __setup_vector_irq(int cpu)
/* Mark the inuse vectors */
for_each_irq_desc(irq, desc) {
- if (!desc)
- continue;
cfg = desc->chip_data;
- if (!cpu_isset(cpu, cfg->domain))
+ if (!cpumask_test_cpu(cpu, cfg->domain))
continue;
vector = cfg->vector;
per_cpu(vector_irq, cpu)[vector] = irq;
@@ -1360,7 +1415,7 @@ void __setup_vector_irq(int cpu)
continue;
cfg = irq_cfg(irq);
- if (!cpu_isset(cpu, cfg->domain))
+ if (!cpumask_test_cpu(cpu, cfg->domain))
per_cpu(vector_irq, cpu)[vector] = -1;
}
}
@@ -1496,18 +1551,17 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_de
{
struct irq_cfg *cfg;
struct IO_APIC_route_entry entry;
- cpumask_t mask;
+ unsigned int dest;
if (!IO_APIC_IRQ(irq))
return;
cfg = desc->chip_data;
- mask = TARGET_CPUS;
- if (assign_irq_vector(irq, cfg, mask))
+ if (assign_irq_vector(irq, cfg, TARGET_CPUS))
return;
- cpus_and(mask, cfg->domain, mask);
+ dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
apic_printk(APIC_VERBOSE,KERN_DEBUG
"IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
@@ -1517,8 +1571,7 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_de
if (setup_ioapic_entry(mp_ioapics[apic].mp_apicid, irq, &entry,
- cpu_mask_to_apicid(mask), trigger, polarity,
- cfg->vector)) {
+ dest, trigger, polarity, cfg->vector)) {
printk("Failed to setup ioapic entry for ioapic %d, pin %d\n",
mp_ioapics[apic].mp_apicid, pin);
__clear_irq_vector(irq, cfg);
@@ -1730,8 +1783,6 @@ __apicdebuginit(void) print_IO_APIC(void)
for_each_irq_desc(irq, desc) {
struct irq_pin_list *entry;
- if (!desc)
- continue;
cfg = desc->chip_data;
entry = cfg->irq_2_pin;
if (!entry)
@@ -2240,7 +2291,7 @@ static int ioapic_retrigger_irq(unsigned int irq)
unsigned long flags;
spin_lock_irqsave(&vector_lock, flags);
- send_IPI_mask(cpumask_of_cpu(first_cpu(cfg->domain)), cfg->vector);
+ send_IPI_mask(cpumask_of(cpumask_first(cfg->domain)), cfg->vector);
spin_unlock_irqrestore(&vector_lock, flags);
return 1;
@@ -2289,18 +2340,17 @@ static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
* as simple as edge triggered migration and we can do the irq migration
* with a simple atomic update to IO-APIC RTE.
*/
-static void migrate_ioapic_irq_desc(struct irq_desc *desc, cpumask_t mask)
+static void
+migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
{
struct irq_cfg *cfg;
- cpumask_t tmp, cleanup_mask;
struct irte irte;
int modify_ioapic_rte;
unsigned int dest;
unsigned long flags;
unsigned int irq;
- cpus_and(tmp, mask, cpu_online_map);
- if (cpus_empty(tmp))
+ if (!cpumask_intersects(mask, cpu_online_mask))
return;
irq = desc->irq;
@@ -2313,8 +2363,7 @@ static void migrate_ioapic_irq_desc(struct irq_desc *desc, cpumask_t mask)
set_extra_move_desc(desc, mask);
- cpus_and(tmp, cfg->domain, mask);
- dest = cpu_mask_to_apicid(tmp);
+ dest = cpu_mask_to_apicid_and(cfg->domain, mask);
modify_ioapic_rte = desc->status & IRQ_LEVEL;
if (modify_ioapic_rte) {
@@ -2331,14 +2380,10 @@ static void migrate_ioapic_irq_desc(struct irq_desc *desc, cpumask_t mask)
*/
modify_irte(irq, &irte);
- if (cfg->move_in_progress) {
- cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
- cfg->move_cleanup_count = cpus_weight(cleanup_mask);
- send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
- cfg->move_in_progress = 0;
- }
+ if (cfg->move_in_progress)
+ send_cleanup_vector(cfg);
- desc->affinity = mask;
+ cpumask_copy(&desc->affinity, mask);
}
static int migrate_irq_remapped_level_desc(struct irq_desc *desc)
@@ -2360,11 +2405,11 @@ static int migrate_irq_remapped_level_desc(struct irq_desc *desc)
}
/* everthing is clear. we have right of way */
- migrate_ioapic_irq_desc(desc, desc->pending_mask);
+ migrate_ioapic_irq_desc(desc, &desc->pending_mask);
ret = 0;
desc->status &= ~IRQ_MOVE_PENDING;
- cpus_clear(desc->pending_mask);
+ cpumask_clear(&desc->pending_mask);
unmask:
unmask_IO_APIC_irq_desc(desc);
@@ -2378,9 +2423,6 @@ static void ir_irq_migration(struct work_struct *work)
struct irq_desc *desc;
for_each_irq_desc(irq, desc) {
- if (!desc)
- continue;
-
if (desc->status & IRQ_MOVE_PENDING) {
unsigned long flags;
@@ -2392,7 +2434,7 @@ static void ir_irq_migration(struct work_struct *work)
continue;
}
- desc->chip->set_affinity(irq, desc->pending_mask);
+ desc->chip->set_affinity(irq, &desc->pending_mask);
spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -2401,18 +2443,20 @@ static void ir_irq_migration(struct work_struct *work)
/*
* Migrates the IRQ destination in the process context.
*/
-static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc, cpumask_t mask)
+static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
+ const struct cpumask *mask)
{
if (desc->status & IRQ_LEVEL) {
desc->status |= IRQ_MOVE_PENDING;
- desc->pending_mask = mask;
+ cpumask_copy(&desc->pending_mask, mask);
migrate_irq_remapped_level_desc(desc);
return;
}
migrate_ioapic_irq_desc(desc, mask);
}
-static void set_ir_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
+static void set_ir_ioapic_affinity_irq(unsigned int irq,
+ const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
@@ -2447,7 +2491,7 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
if (!cfg->move_cleanup_count)
goto unlock;
- if ((vector == cfg->vector) && cpu_isset(me, cfg->domain))
+ if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
goto unlock;
__get_cpu_var(vector_irq)[vector] = -1;
@@ -2484,19 +2528,14 @@ static void irq_complete_move(struct irq_desc **descp)
vector = ~get_irq_regs()->orig_ax;
me = smp_processor_id();
- if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
- cpumask_t cleanup_mask;
+ if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
*descp = desc = move_irq_desc(desc, me);
/* get the new one */
cfg = desc->chip_data;
#endif
-
- cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
- cfg->move_cleanup_count = cpus_weight(cleanup_mask);
- send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
- cfg->move_in_progress = 0;
+ send_cleanup_vector(cfg);
}
}
#else
@@ -2670,9 +2709,6 @@ static inline void init_IO_APIC_traps(void)
* 0x80, because int 0x80 is hm, kind of importantish. ;)
*/
for_each_irq_desc(irq, desc) {
- if (!desc)
- continue;
-
cfg = desc->chip_data;
if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
/*
@@ -3222,16 +3258,13 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
struct irq_cfg *cfg;
int err;
unsigned dest;
- cpumask_t tmp;
cfg = irq_cfg(irq);
- tmp = TARGET_CPUS;
- err = assign_irq_vector(irq, cfg, tmp);
+ err = assign_irq_vector(irq, cfg, TARGET_CPUS);
if (err)
return err;
- cpus_and(tmp, cfg->domain, tmp);
- dest = cpu_mask_to_apicid(tmp);
+ dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
#ifdef CONFIG_INTR_REMAP
if (irq_remapped(irq)) {
@@ -3285,26 +3318,18 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
}
#ifdef CONFIG_SMP
-static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
+static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
struct msi_msg msg;
unsigned int dest;
- cpumask_t tmp;
- cpus_and(tmp, mask, cpu_online_map);
- if (cpus_empty(tmp))
+ dest = set_desc_affinity(desc, mask);
+ if (dest == BAD_APICID)
return;
cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
- return;
-
- set_extra_move_desc(desc, mask);
-
- cpus_and(tmp, cfg->domain, mask);
- dest = cpu_mask_to_apicid(tmp);
read_msi_msg_desc(desc, &msg);
@@ -3314,37 +3339,27 @@ static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
write_msi_msg_desc(desc, &msg);
- desc->affinity = mask;
}
#ifdef CONFIG_INTR_REMAP
/*
* Migrate the MSI irq to another cpumask. This migration is
* done in the process context using interrupt-remapping hardware.
*/
-static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
+static void
+ir_set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
- struct irq_cfg *cfg;
+ struct irq_cfg *cfg = desc->chip_data;
unsigned int dest;
- cpumask_t tmp, cleanup_mask;
struct irte irte;
- cpus_and(tmp, mask, cpu_online_map);
- if (cpus_empty(tmp))
- return;
-
if (get_irte(irq, &irte))
return;
- cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
+ dest = set_desc_affinity(desc, mask);
+ if (dest == BAD_APICID)
return;
- set_extra_move_desc(desc, mask);
-
- cpus_and(tmp, cfg->domain, mask);
- dest = cpu_mask_to_apicid(tmp);
-
irte.vector = cfg->vector;
irte.dest_id = IRTE_DEST(dest);
@@ -3358,14 +3373,8 @@ static void ir_set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
* at the new destination. So, time to cleanup the previous
* vector allocation.
*/
- if (cfg->move_in_progress) {
- cpus_and(cleanup_mask, cfg->old_domain, cpu_online_map);
- cfg->move_cleanup_count = cpus_weight(cleanup_mask);
- send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
- cfg->move_in_progress = 0;
- }
-
- desc->affinity = mask;
+ if (cfg->move_in_progress)
+ send_cleanup_vector(cfg);
}
#endif
@@ -3556,26 +3565,18 @@ void arch_teardown_msi_irq(unsigned int irq)
#ifdef CONFIG_DMAR
#ifdef CONFIG_SMP
-static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
+static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
struct msi_msg msg;
unsigned int dest;
- cpumask_t tmp;
- cpus_and(tmp, mask, cpu_online_map);
- if (cpus_empty(tmp))
+ dest = set_desc_affinity(desc, mask);
+ if (dest == BAD_APICID)
return;
cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
- return;
-
- set_extra_move_desc(desc, mask);
-
- cpus_and(tmp, cfg->domain, mask);
- dest = cpu_mask_to_apicid(tmp);
dmar_msi_read(irq, &msg);
@@ -3585,7 +3586,6 @@ static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
dmar_msi_write(irq, &msg);
- desc->affinity = mask;
}
#endif /* CONFIG_SMP */
@@ -3619,26 +3619,18 @@ int arch_setup_dmar_msi(unsigned int irq)
#ifdef CONFIG_HPET_TIMER
#ifdef CONFIG_SMP
-static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask)
+static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
struct msi_msg msg;
unsigned int dest;
- cpumask_t tmp;
- cpus_and(tmp, mask, cpu_online_map);
- if (cpus_empty(tmp))
+ dest = set_desc_affinity(desc, mask);
+ if (dest == BAD_APICID)
return;
cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
- return;
-
- set_extra_move_desc(desc, mask);
-
- cpus_and(tmp, cfg->domain, mask);
- dest = cpu_mask_to_apicid(tmp);
hpet_msi_read(irq, &msg);
@@ -3648,7 +3640,6 @@ static void hpet_msi_set_affinity(unsigned int irq, cpumask_t mask)
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
hpet_msi_write(irq, &msg);
- desc->affinity = mask;
}
#endif /* CONFIG_SMP */
@@ -3703,28 +3694,19 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
write_ht_irq_msg(irq, &msg);
}
-static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
+static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_cfg *cfg;
unsigned int dest;
- cpumask_t tmp;
- cpus_and(tmp, mask, cpu_online_map);
- if (cpus_empty(tmp))
+ dest = set_desc_affinity(desc, mask);
+ if (dest == BAD_APICID)
return;
cfg = desc->chip_data;
- if (assign_irq_vector(irq, cfg, mask))
- return;
-
- set_extra_move_desc(desc, mask);
-
- cpus_and(tmp, cfg->domain, mask);
- dest = cpu_mask_to_apicid(tmp);
target_ht_irq(irq, dest, cfg->vector);
- desc->affinity = mask;
}
#endif
@@ -3744,17 +3726,14 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
{
struct irq_cfg *cfg;
int err;
- cpumask_t tmp;
cfg = irq_cfg(irq);
- tmp = TARGET_CPUS;
- err = assign_irq_vector(irq, cfg, tmp);
+ err = assign_irq_vector(irq, cfg, TARGET_CPUS);
if (!err) {
struct ht_irq_msg msg;
unsigned dest;
- cpus_and(tmp, cfg->domain, tmp);
- dest = cpu_mask_to_apicid(tmp);
+ dest = cpu_mask_to_apicid_and(cfg->domain, TARGET_CPUS);
msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
@@ -3790,7 +3769,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
unsigned long mmr_offset)
{
- const cpumask_t *eligible_cpu = get_cpu_mask(cpu);
+ const struct cpumask *eligible_cpu = cpumask_of(cpu);
struct irq_cfg *cfg;
int mmr_pnode;
unsigned long mmr_value;
@@ -3800,7 +3779,7 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
cfg = irq_cfg(irq);
- err = assign_irq_vector(irq, cfg, *eligible_cpu);
+ err = assign_irq_vector(irq, cfg, eligible_cpu);
if (err != 0)
return err;
@@ -3819,7 +3798,7 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
entry->polarity = 0;
entry->trigger = 0;
entry->mask = 0;
- entry->dest = cpu_mask_to_apicid(*eligible_cpu);
+ entry->dest = cpu_mask_to_apicid(eligible_cpu);
mmr_pnode = uv_blade_to_pnode(mmr_blade);
uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
@@ -4030,7 +4009,7 @@ void __init setup_ioapic_dest(void)
int pin, ioapic, irq, irq_entry;
struct irq_desc *desc;
struct irq_cfg *cfg;
- cpumask_t mask;
+ const struct cpumask *mask;
if (skip_ioapic_setup == 1)
return;
@@ -4061,7 +4040,7 @@ void __init setup_ioapic_dest(void)
*/
if (desc->status &
(IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
- mask = desc->affinity;
+ mask = &desc->affinity;
else
mask = TARGET_CPUS;
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 191914302744..b12208f4dfee 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -35,8 +35,8 @@ static void set_bitmap(unsigned long *bitmap, unsigned int base,
*/
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
{
- struct thread_struct * t = &current->thread;
- struct tss_struct * tss;
+ struct thread_struct *t = &current->thread;
+ struct tss_struct *tss;
unsigned int i, max_long, bytes, bytes_updated;
if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/ipi.c
index f1c688e46f35..285bbf8831fa 100644
--- a/arch/x86/kernel/ipi.c
+++ b/arch/x86/kernel/ipi.c
@@ -116,18 +116,18 @@ static inline void __send_IPI_dest_field(unsigned long mask, int vector)
/*
* This is only used on smaller machines.
*/
-void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
+void send_IPI_mask_bitmask(const struct cpumask *cpumask, int vector)
{
- unsigned long mask = cpus_addr(cpumask)[0];
+ unsigned long mask = cpumask_bits(cpumask)[0];
unsigned long flags;
local_irq_save(flags);
- WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
+ WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
__send_IPI_dest_field(mask, vector);
local_irq_restore(flags);
}
-void send_IPI_mask_sequence(cpumask_t mask, int vector)
+void send_IPI_mask_sequence(const struct cpumask *mask, int vector)
{
unsigned long flags;
unsigned int query_cpu;
@@ -139,12 +139,24 @@ void send_IPI_mask_sequence(cpumask_t mask, int vector)
*/
local_irq_save(flags);
- for_each_possible_cpu(query_cpu) {
- if (cpu_isset(query_cpu, mask)) {
+ for_each_cpu(query_cpu, mask)
+ __send_IPI_dest_field(cpu_to_logical_apicid(query_cpu), vector);
+ local_irq_restore(flags);
+}
+
+void send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
+{
+ unsigned long flags;
+ unsigned int query_cpu;
+ unsigned int this_cpu = smp_processor_id();
+
+ /* See Hack comment above */
+
+ local_irq_save(flags);
+ for_each_cpu(query_cpu, mask)
+ if (query_cpu != this_cpu)
__send_IPI_dest_field(cpu_to_logical_apicid(query_cpu),
vector);
- }
- }
local_irq_restore(flags);
}
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 3f1d9d18df67..3973e2df7f87 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -5,10 +5,11 @@
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
+#include <linux/smp.h>
#include <asm/apic.h>
#include <asm/io_apic.h>
-#include <asm/smp.h>
+#include <asm/irq.h>
atomic_t irq_err_count;
@@ -190,3 +191,5 @@ u64 arch_irq_stat(void)
#endif
return sum;
}
+
+EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 119fc9c8ff7f..74b9ff7341e9 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -15,9 +15,9 @@
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/delay.h>
+#include <linux/uaccess.h>
#include <asm/apic.h>
-#include <asm/uaccess.h>
DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
EXPORT_PER_CPU_SYMBOL(irq_stat);
@@ -93,7 +93,7 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
return 0;
/* build the stack frame on the IRQ stack */
- isp = (u32 *) ((char*)irqctx + sizeof(*irqctx));
+ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_esp = current_stack_pointer;
@@ -137,7 +137,7 @@ void __cpuinit irq_ctx_init(int cpu)
hardirq_ctx[cpu] = irqctx;
- irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
+ irqctx = (union irq_ctx *) &softirq_stack[cpu*THREAD_SIZE];
irqctx->tinfo.task = NULL;
irqctx->tinfo.exec_domain = NULL;
irqctx->tinfo.cpu = cpu;
@@ -147,7 +147,7 @@ void __cpuinit irq_ctx_init(int cpu)
softirq_ctx[cpu] = irqctx;
printk(KERN_DEBUG "CPU %u irqstacks, hard=%p soft=%p\n",
- cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
+ cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
}
void irq_ctx_exit(int cpu)
@@ -174,7 +174,7 @@ asmlinkage void do_softirq(void)
irqctx->tinfo.previous_esp = current_stack_pointer;
/* build the stack frame on the softirq stack */
- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
+ isp = (u32 *) ((char *)irqctx + sizeof(*irqctx));
call_on_stack(__do_softirq, isp);
/*
@@ -233,27 +233,28 @@ unsigned int do_IRQ(struct pt_regs *regs)
#ifdef CONFIG_HOTPLUG_CPU
#include <mach_apic.h>
-void fixup_irqs(cpumask_t map)
+/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
+void fixup_irqs(void)
{
unsigned int irq;
static int warned;
struct irq_desc *desc;
for_each_irq_desc(irq, desc) {
- cpumask_t mask;
+ const struct cpumask *affinity;
if (!desc)
continue;
if (irq == 2)
continue;
- cpus_and(mask, desc->affinity, map);
- if (any_online_cpu(mask) == NR_CPUS) {
+ affinity = &desc->affinity;
+ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
printk("Breaking affinity for irq %i\n", irq);
- mask = map;
+ affinity = cpu_all_mask;
}
if (desc->chip->set_affinity)
- desc->chip->set_affinity(irq, mask);
+ desc->chip->set_affinity(irq, affinity);
else if (desc->action && !(warned++))
printk("Cannot set affinity for irq %i\n", irq);
}
diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c
index a174a217eb1a..63c88e6ec025 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -14,10 +14,10 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/ftrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <linux/smp.h>
#include <asm/io_apic.h>
#include <asm/idle.h>
-#include <asm/smp.h>
/*
* Probabilistic stack overflow check:
@@ -80,16 +80,17 @@ asmlinkage unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
}
#ifdef CONFIG_HOTPLUG_CPU
-void fixup_irqs(cpumask_t map)
+/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
+void fixup_irqs(void)
{
unsigned int irq;
static int warned;
struct irq_desc *desc;
for_each_irq_desc(irq, desc) {
- cpumask_t mask;
int break_affinity = 0;
int set_affinity = 1;
+ const struct cpumask *affinity;
if (!desc)
continue;
@@ -99,23 +100,23 @@ void fixup_irqs(cpumask_t map)
/* interrupt's are disabled at this point */
spin_lock(&desc->lock);
+ affinity = &desc->affinity;
if (!irq_has_action(irq) ||
- cpus_equal(desc->affinity, map)) {
+ cpumask_equal(affinity, cpu_online_mask)) {
spin_unlock(&desc->lock);
continue;
}
- cpus_and(mask, desc->affinity, map);
- if (cpus_empty(mask)) {
+ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
break_affinity = 1;
- mask = map;
+ affinity = cpu_all_mask;
}
if (desc->chip->mask)
desc->chip->mask(irq);
if (desc->chip->set_affinity)
- desc->chip->set_affinity(irq, mask);
+ desc->chip->set_affinity(irq, affinity);
else if (!(warned++))
set_affinity = 0;
@@ -141,18 +142,18 @@ extern void call_softirq(void);
asmlinkage void do_softirq(void)
{
- __u32 pending;
- unsigned long flags;
+ __u32 pending;
+ unsigned long flags;
- if (in_interrupt())
- return;
+ if (in_interrupt())
+ return;
- local_irq_save(flags);
- pending = local_softirq_pending();
- /* Switch to interrupt stack */
- if (pending) {
+ local_irq_save(flags);
+ pending = local_softirq_pending();
+ /* Switch to interrupt stack */
+ if (pending) {
call_softirq();
WARN_ON_ONCE(softirq_count());
}
- local_irq_restore(flags);
+ local_irq_restore(flags);
}
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c
index 203384ed2b5d..10a09c2f1828 100644
--- a/arch/x86/kernel/irqinit_32.c
+++ b/arch/x86/kernel/irqinit_32.c
@@ -9,18 +9,18 @@
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/delay.h>
#include <asm/atomic.h>
#include <asm/system.h>
-#include <asm/io.h>
#include <asm/timer.h>
#include <asm/pgtable.h>
-#include <asm/delay.h>
#include <asm/desc.h>
#include <asm/apic.h>
#include <asm/arch_hooks.h>
#include <asm/i8259.h>
-
+#include <asm/traps.h>
/*
@@ -34,12 +34,10 @@
* leads to races. IBM designers who came up with it should
* be shot.
*/
-
static irqreturn_t math_error_irq(int cpl, void *dev_id)
{
- extern void math_error(void __user *);
- outb(0,0xF0);
+ outb(0, 0xF0);
if (ignore_fpu_irq || !boot_cpu_data.hard_math)
return IRQ_NONE;
math_error((void __user *)get_irq_regs()->ip);
@@ -56,7 +54,7 @@ static struct irqaction fpu_irq = {
.name = "fpu",
};
-void __init init_ISA_irqs (void)
+void __init init_ISA_irqs(void)
{
int i;
@@ -80,15 +78,6 @@ void __init init_ISA_irqs (void)
}
}
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = {
- .handler = no_action,
- .mask = CPU_MASK_NONE,
- .name = "cascade",
-};
-
DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
[0 ... IRQ0_VECTOR - 1] = -1,
[IRQ0_VECTOR] = 0,
@@ -110,6 +99,18 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
};
+int vector_used_by_percpu_irq(unsigned int vector)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ if (per_cpu(vector_irq, cpu)[vector] != -1)
+ return 1;
+ }
+
+ return 0;
+}
+
/* Overridden in paravirt.c */
void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
@@ -146,10 +147,12 @@ void __init native_init_IRQ(void)
alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
/* IPI for single call function */
- set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt);
+ alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
+ call_function_single_interrupt);
/* Low priority IPI to cleanup after moving an irq */
set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
+ set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
#endif
#ifdef CONFIG_X86_LOCAL_APIC
@@ -166,9 +169,6 @@ void __init native_init_IRQ(void)
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
#endif
- if (!acpi_ioapic)
- setup_irq(2, &irq2);
-
/* setup after call gates are initialised (usually add in
* the architecture specific gates)
*/
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c
index 6190e6ef546c..da481a1e3f30 100644
--- a/arch/x86/kernel/irqinit_64.c
+++ b/arch/x86/kernel/irqinit_64.c
@@ -11,14 +11,14 @@
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
#include <linux/bitops.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/delay.h>
-#include <asm/acpi.h>
#include <asm/atomic.h>
#include <asm/system.h>
-#include <asm/io.h>
#include <asm/hw_irq.h>
#include <asm/pgtable.h>
-#include <asm/delay.h>
#include <asm/desc.h>
#include <asm/apic.h>
#include <asm/i8259.h>
@@ -69,7 +69,19 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
};
-void __init init_ISA_irqs(void)
+int vector_used_by_percpu_irq(unsigned int vector)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ if (per_cpu(vector_irq, cpu)[vector] != -1)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void __init init_ISA_irqs(void)
{
int i;
@@ -121,6 +133,7 @@ static void __init smp_intr_init(void)
/* Low priority IPI to cleanup after moving an irq */
set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
+ set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
#endif
}
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index 6c27679ec6aa..e948b28a5a9a 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -376,9 +376,10 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
void __kprobes arch_remove_kprobe(struct kprobe *p)
{
- mutex_lock(&kprobe_mutex);
- free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
- mutex_unlock(&kprobe_mutex);
+ if (p->ainsn.insn) {
+ free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
+ p->ainsn.insn = NULL;
+ }
}
static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
@@ -445,7 +446,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs,
struct kprobe_ctlblk *kcb)
{
-#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM)
+#if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER)
if (p->ainsn.boostable == 1 && !p->post_handler) {
/* Boost up -- we can execute copied instructions directly */
reset_current_kprobe();
@@ -694,7 +695,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
/*
* It is possible to have multiple instances associated with a given
* task either because multiple functions in the call path have
- * return probes installed on them, and/or more then one
+ * return probes installed on them, and/or more than one
* return probe was registered for a target function.
*
* We can handle this because:
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index e169ae9b6a62..652fce6d2cce 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -89,17 +89,17 @@ static cycle_t kvm_clock_read(void)
*/
static unsigned long kvm_get_tsc_khz(void)
{
- return preset_lpj;
+ struct pvclock_vcpu_time_info *src;
+ src = &per_cpu(hv_clock, 0);
+ return pvclock_tsc_khz(src);
}
static void kvm_get_preset_lpj(void)
{
- struct pvclock_vcpu_time_info *src;
unsigned long khz;
u64 lpj;
- src = &per_cpu(hv_clock, 0);
- khz = pvclock_tsc_khz(src);
+ khz = kvm_get_tsc_khz();
lpj = ((u64)khz * 1000);
do_div(lpj, HZ);
@@ -194,5 +194,7 @@ void __init kvmclock_init(void)
#endif
kvm_get_preset_lpj();
clocksource_register(&kvm_clock);
+ pv_info.paravirt_enabled = 1;
+ pv_info.name = "KVM";
}
}
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index eee32b43fee3..71f1d99a635d 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -12,8 +12,8 @@
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/ldt.h>
#include <asm/desc.h>
@@ -93,7 +93,7 @@ static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
if (err < 0)
return err;
- for(i = 0; i < old->size; i++)
+ for (i = 0; i < old->size; i++)
write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
return 0;
}
diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c
index 3b599518c322..8815f3c7fec7 100644
--- a/arch/x86/kernel/mfgpt_32.c
+++ b/arch/x86/kernel/mfgpt_32.c
@@ -252,7 +252,7 @@ EXPORT_SYMBOL_GPL(geode_mfgpt_alloc_timer);
/*
* The MFPGT timers on the CS5536 provide us with suitable timers to use
* as clock event sources - not as good as a HPET or APIC, but certainly
- * better then the PIT. This isn't a general purpose MFGPT driver, but
+ * better than the PIT. This isn't a general purpose MFGPT driver, but
* a simplified one designed specifically to act as a clock event source.
* For full details about the MFGPT, please consult the CS5536 data sheet.
*/
@@ -287,7 +287,7 @@ static struct clock_event_device mfgpt_clockevent = {
.set_mode = mfgpt_set_mode,
.set_next_event = mfgpt_next_event,
.rating = 250,
- .cpumask = CPU_MASK_ALL,
+ .cpumask = cpu_all_mask,
.shift = 32
};
diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c
index efc2f361fe85..666e43df51f9 100644
--- a/arch/x86/kernel/mmconf-fam10h_64.c
+++ b/arch/x86/kernel/mmconf-fam10h_64.c
@@ -13,8 +13,7 @@
#include <asm/msr.h>
#include <asm/acpi.h>
#include <asm/mmconfig.h>
-
-#include "../pci/pci.h"
+#include <asm/pci_x86.h>
struct pci_hostbridge_probe {
u32 bus;
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 45e3b69808ba..a649a4ccad43 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -2,7 +2,7 @@
* Intel Multiprocessor Specification 1.1 and 1.4
* compliant MP-table parsing routines.
*
- * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ * (c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
* (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
* (c) 2008 Alexey Starikovskiy <astarikovskiy@suse.de>
*/
@@ -16,18 +16,18 @@
#include <linux/bitops.h>
#include <linux/acpi.h>
#include <linux/module.h>
+#include <linux/smp.h>
-#include <asm/smp.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
#include <asm/pgalloc.h>
#include <asm/io_apic.h>
#include <asm/proto.h>
-#include <asm/acpi.h>
#include <asm/bios_ebda.h>
#include <asm/e820.h>
#include <asm/trampoline.h>
#include <asm/setup.h>
+#include <asm/smp.h>
#include <mach_apic.h>
#ifdef CONFIG_X86_32
@@ -49,12 +49,12 @@ static int __init mpf_checksum(unsigned char *mp, int len)
return sum & 0xFF;
}
-static void __init MP_processor_info(struct mpc_config_processor *m)
+static void __init MP_processor_info(struct mpc_cpu *m)
{
int apicid;
char *bootup_cpu = "";
- if (!(m->mpc_cpuflag & CPU_ENABLED)) {
+ if (!(m->cpuflag & CPU_ENABLED)) {
disabled_cpus++;
return;
}
@@ -62,54 +62,54 @@ static void __init MP_processor_info(struct mpc_config_processor *m)
if (x86_quirks->mpc_apic_id)
apicid = x86_quirks->mpc_apic_id(m);
else
- apicid = m->mpc_apicid;
+ apicid = m->apicid;
- if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+ if (m->cpuflag & CPU_BOOTPROCESSOR) {
bootup_cpu = " (Bootup-CPU)";
- boot_cpu_physical_apicid = m->mpc_apicid;
+ boot_cpu_physical_apicid = m->apicid;
}
- printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
- generic_processor_info(apicid, m->mpc_apicver);
+ printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
+ generic_processor_info(apicid, m->apicver);
}
#ifdef CONFIG_X86_IO_APIC
-static void __init MP_bus_info(struct mpc_config_bus *m)
+static void __init MP_bus_info(struct mpc_bus *m)
{
char str[7];
- memcpy(str, m->mpc_bustype, 6);
+ memcpy(str, m->bustype, 6);
str[6] = 0;
if (x86_quirks->mpc_oem_bus_info)
x86_quirks->mpc_oem_bus_info(m, str);
else
- apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->mpc_busid, str);
+ apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str);
#if MAX_MP_BUSSES < 256
- if (m->mpc_busid >= MAX_MP_BUSSES) {
+ if (m->busid >= MAX_MP_BUSSES) {
printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
" is too large, max. supported is %d\n",
- m->mpc_busid, str, MAX_MP_BUSSES - 1);
+ m->busid, str, MAX_MP_BUSSES - 1);
return;
}
#endif
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) {
- set_bit(m->mpc_busid, mp_bus_not_pci);
-#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+ set_bit(m->busid, mp_bus_not_pci);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ mp_bus_id_to_type[m->busid] = MP_BUS_ISA;
#endif
} else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI) - 1) == 0) {
if (x86_quirks->mpc_oem_pci_bus)
x86_quirks->mpc_oem_pci_bus(m);
- clear_bit(m->mpc_busid, mp_bus_not_pci);
-#if defined(CONFIG_EISA) || defined (CONFIG_MCA)
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+ clear_bit(m->busid, mp_bus_not_pci);
+#if defined(CONFIG_EISA) || defined(CONFIG_MCA)
+ mp_bus_id_to_type[m->busid] = MP_BUS_PCI;
} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA) - 1) == 0) {
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
+ mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA) - 1) == 0) {
- mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
+ mp_bus_id_to_type[m->busid] = MP_BUS_MCA;
#endif
} else
printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
@@ -133,32 +133,31 @@ static int bad_ioapic(unsigned long address)
return 0;
}
-static void __init MP_ioapic_info(struct mpc_config_ioapic *m)
+static void __init MP_ioapic_info(struct mpc_ioapic *m)
{
- if (!(m->mpc_flags & MPC_APIC_USABLE))
+ if (!(m->flags & MPC_APIC_USABLE))
return;
printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
- m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+ m->apicid, m->apicver, m->apicaddr);
- if (bad_ioapic(m->mpc_apicaddr))
+ if (bad_ioapic(m->apicaddr))
return;
- mp_ioapics[nr_ioapics].mp_apicaddr = m->mpc_apicaddr;
- mp_ioapics[nr_ioapics].mp_apicid = m->mpc_apicid;
- mp_ioapics[nr_ioapics].mp_type = m->mpc_type;
- mp_ioapics[nr_ioapics].mp_apicver = m->mpc_apicver;
- mp_ioapics[nr_ioapics].mp_flags = m->mpc_flags;
+ mp_ioapics[nr_ioapics].mp_apicaddr = m->apicaddr;
+ mp_ioapics[nr_ioapics].mp_apicid = m->apicid;
+ mp_ioapics[nr_ioapics].mp_type = m->type;
+ mp_ioapics[nr_ioapics].mp_apicver = m->apicver;
+ mp_ioapics[nr_ioapics].mp_flags = m->flags;
nr_ioapics++;
}
-static void print_MP_intsrc_info(struct mpc_config_intsrc *m)
+static void print_MP_intsrc_info(struct mpc_intsrc *m)
{
apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
- m->mpc_irqtype, m->mpc_irqflag & 3,
- (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus,
- m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq);
+ m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbus,
+ m->srcbusirq, m->dstapic, m->dstirq);
}
static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
@@ -170,52 +169,52 @@ static void __init print_mp_irq_info(struct mp_config_intsrc *mp_irq)
mp_irq->mp_srcbusirq, mp_irq->mp_dstapic, mp_irq->mp_dstirq);
}
-static void __init assign_to_mp_irq(struct mpc_config_intsrc *m,
+static void __init assign_to_mp_irq(struct mpc_intsrc *m,
struct mp_config_intsrc *mp_irq)
{
- mp_irq->mp_dstapic = m->mpc_dstapic;
- mp_irq->mp_type = m->mpc_type;
- mp_irq->mp_irqtype = m->mpc_irqtype;
- mp_irq->mp_irqflag = m->mpc_irqflag;
- mp_irq->mp_srcbus = m->mpc_srcbus;
- mp_irq->mp_srcbusirq = m->mpc_srcbusirq;
- mp_irq->mp_dstirq = m->mpc_dstirq;
+ mp_irq->mp_dstapic = m->dstapic;
+ mp_irq->mp_type = m->type;
+ mp_irq->mp_irqtype = m->irqtype;
+ mp_irq->mp_irqflag = m->irqflag;
+ mp_irq->mp_srcbus = m->srcbus;
+ mp_irq->mp_srcbusirq = m->srcbusirq;
+ mp_irq->mp_dstirq = m->dstirq;
}
static void __init assign_to_mpc_intsrc(struct mp_config_intsrc *mp_irq,
- struct mpc_config_intsrc *m)
+ struct mpc_intsrc *m)
{
- m->mpc_dstapic = mp_irq->mp_dstapic;
- m->mpc_type = mp_irq->mp_type;
- m->mpc_irqtype = mp_irq->mp_irqtype;
- m->mpc_irqflag = mp_irq->mp_irqflag;
- m->mpc_srcbus = mp_irq->mp_srcbus;
- m->mpc_srcbusirq = mp_irq->mp_srcbusirq;
- m->mpc_dstirq = mp_irq->mp_dstirq;
+ m->dstapic = mp_irq->mp_dstapic;
+ m->type = mp_irq->mp_type;
+ m->irqtype = mp_irq->mp_irqtype;
+ m->irqflag = mp_irq->mp_irqflag;
+ m->srcbus = mp_irq->mp_srcbus;
+ m->srcbusirq = mp_irq->mp_srcbusirq;
+ m->dstirq = mp_irq->mp_dstirq;
}
static int __init mp_irq_mpc_intsrc_cmp(struct mp_config_intsrc *mp_irq,
- struct mpc_config_intsrc *m)
+ struct mpc_intsrc *m)
{
- if (mp_irq->mp_dstapic != m->mpc_dstapic)
+ if (mp_irq->mp_dstapic != m->dstapic)
return 1;
- if (mp_irq->mp_type != m->mpc_type)
+ if (mp_irq->mp_type != m->type)
return 2;
- if (mp_irq->mp_irqtype != m->mpc_irqtype)
+ if (mp_irq->mp_irqtype != m->irqtype)
return 3;
- if (mp_irq->mp_irqflag != m->mpc_irqflag)
+ if (mp_irq->mp_irqflag != m->irqflag)
return 4;
- if (mp_irq->mp_srcbus != m->mpc_srcbus)
+ if (mp_irq->mp_srcbus != m->srcbus)
return 5;
- if (mp_irq->mp_srcbusirq != m->mpc_srcbusirq)
+ if (mp_irq->mp_srcbusirq != m->srcbusirq)
return 6;
- if (mp_irq->mp_dstirq != m->mpc_dstirq)
+ if (mp_irq->mp_dstirq != m->dstirq)
return 7;
return 0;
}
-static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
+static void __init MP_intsrc_info(struct mpc_intsrc *m)
{
int i;
@@ -233,57 +232,55 @@ static void __init MP_intsrc_info(struct mpc_config_intsrc *m)
#endif
-static void __init MP_lintsrc_info(struct mpc_config_lintsrc *m)
+static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
{
apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
- m->mpc_irqtype, m->mpc_irqflag & 3,
- (m->mpc_irqflag >> 2) & 3, m->mpc_srcbusid,
- m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
+ m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
+ m->srcbusirq, m->destapic, m->destapiclint);
}
/*
* Read/parse the MPC
*/
-static int __init smp_check_mpc(struct mp_config_table *mpc, char *oem,
- char *str)
+static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
{
- if (memcmp(mpc->mpc_signature, MPC_SIGNATURE, 4)) {
+ if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
- mpc->mpc_signature[0], mpc->mpc_signature[1],
- mpc->mpc_signature[2], mpc->mpc_signature[3]);
+ mpc->signature[0], mpc->signature[1],
+ mpc->signature[2], mpc->signature[3]);
return 0;
}
- if (mpf_checksum((unsigned char *)mpc, mpc->mpc_length)) {
+ if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
printk(KERN_ERR "MPTABLE: checksum error!\n");
return 0;
}
- if (mpc->mpc_spec != 0x01 && mpc->mpc_spec != 0x04) {
+ if (mpc->spec != 0x01 && mpc->spec != 0x04) {
printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
- mpc->mpc_spec);
+ mpc->spec);
return 0;
}
- if (!mpc->mpc_lapic) {
+ if (!mpc->lapic) {
printk(KERN_ERR "MPTABLE: null local APIC address!\n");
return 0;
}
- memcpy(oem, mpc->mpc_oem, 8);
+ memcpy(oem, mpc->oem, 8);
oem[8] = 0;
printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
- memcpy(str, mpc->mpc_productid, 12);
+ memcpy(str, mpc->productid, 12);
str[12] = 0;
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
- printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->mpc_lapic);
+ printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
return 1;
}
-static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
+static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
{
char str[16];
char oem[10];
@@ -308,14 +305,14 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
#endif
/* save the local APIC address, it might be non-default */
if (!acpi_lapic)
- mp_lapic_addr = mpc->mpc_lapic;
+ mp_lapic_addr = mpc->lapic;
if (early)
return 1;
- if (mpc->mpc_oemptr && x86_quirks->smp_read_mpc_oem) {
- struct mp_config_oemtable *oem_table = (struct mp_config_oemtable *)(unsigned long)mpc->mpc_oemptr;
- x86_quirks->smp_read_mpc_oem(oem_table, mpc->mpc_oemsize);
+ if (mpc->oemptr && x86_quirks->smp_read_mpc_oem) {
+ struct mpc_oemtable *oem_table = (void *)(long)mpc->oemptr;
+ x86_quirks->smp_read_mpc_oem(oem_table, mpc->oemsize);
}
/*
@@ -324,12 +321,11 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
if (x86_quirks->mpc_record)
*x86_quirks->mpc_record = 0;
- while (count < mpc->mpc_length) {
+ while (count < mpc->length) {
switch (*mpt) {
case MP_PROCESSOR:
{
- struct mpc_config_processor *m =
- (struct mpc_config_processor *)mpt;
+ struct mpc_cpu *m = (struct mpc_cpu *)mpt;
/* ACPI may have already provided this data */
if (!acpi_lapic)
MP_processor_info(m);
@@ -339,8 +335,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
}
case MP_BUS:
{
- struct mpc_config_bus *m =
- (struct mpc_config_bus *)mpt;
+ struct mpc_bus *m = (struct mpc_bus *)mpt;
#ifdef CONFIG_X86_IO_APIC
MP_bus_info(m);
#endif
@@ -351,30 +346,28 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
case MP_IOAPIC:
{
#ifdef CONFIG_X86_IO_APIC
- struct mpc_config_ioapic *m =
- (struct mpc_config_ioapic *)mpt;
+ struct mpc_ioapic *m = (struct mpc_ioapic *)mpt;
MP_ioapic_info(m);
#endif
- mpt += sizeof(struct mpc_config_ioapic);
- count += sizeof(struct mpc_config_ioapic);
+ mpt += sizeof(struct mpc_ioapic);
+ count += sizeof(struct mpc_ioapic);
break;
}
case MP_INTSRC:
{
#ifdef CONFIG_X86_IO_APIC
- struct mpc_config_intsrc *m =
- (struct mpc_config_intsrc *)mpt;
+ struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
MP_intsrc_info(m);
#endif
- mpt += sizeof(struct mpc_config_intsrc);
- count += sizeof(struct mpc_config_intsrc);
+ mpt += sizeof(struct mpc_intsrc);
+ count += sizeof(struct mpc_intsrc);
break;
}
case MP_LINTSRC:
{
- struct mpc_config_lintsrc *m =
- (struct mpc_config_lintsrc *)mpt;
+ struct mpc_lintsrc *m =
+ (struct mpc_lintsrc *)mpt;
MP_lintsrc_info(m);
mpt += sizeof(*m);
count += sizeof(*m);
@@ -385,8 +378,8 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
printk(KERN_ERR "type %x\n", *mpt);
print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
- 1, mpc, mpc->mpc_length, 1);
- count = mpc->mpc_length;
+ 1, mpc, mpc->length, 1);
+ count = mpc->length;
break;
}
if (x86_quirks->mpc_record)
@@ -417,16 +410,16 @@ static int __init ELCR_trigger(unsigned int irq)
static void __init construct_default_ioirq_mptable(int mpc_default_type)
{
- struct mpc_config_intsrc intsrc;
+ struct mpc_intsrc intsrc;
int i;
int ELCR_fallback = 0;
- intsrc.mpc_type = MP_INTSRC;
- intsrc.mpc_irqflag = 0; /* conforming */
- intsrc.mpc_srcbus = 0;
- intsrc.mpc_dstapic = mp_ioapics[0].mp_apicid;
+ intsrc.type = MP_INTSRC;
+ intsrc.irqflag = 0; /* conforming */
+ intsrc.srcbus = 0;
+ intsrc.dstapic = mp_ioapics[0].mp_apicid;
- intsrc.mpc_irqtype = mp_INT;
+ intsrc.irqtype = mp_INT;
/*
* If true, we have an ISA/PCI system with no IRQ entries
@@ -469,30 +462,30 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
* irqflag field (level sensitive, active high polarity).
*/
if (ELCR_trigger(i))
- intsrc.mpc_irqflag = 13;
+ intsrc.irqflag = 13;
else
- intsrc.mpc_irqflag = 0;
+ intsrc.irqflag = 0;
}
- intsrc.mpc_srcbusirq = i;
- intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
+ intsrc.srcbusirq = i;
+ intsrc.dstirq = i ? i : 2; /* IRQ0 to INTIN2 */
MP_intsrc_info(&intsrc);
}
- intsrc.mpc_irqtype = mp_ExtINT;
- intsrc.mpc_srcbusirq = 0;
- intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */
+ intsrc.irqtype = mp_ExtINT;
+ intsrc.srcbusirq = 0;
+ intsrc.dstirq = 0; /* 8259A to INTIN0 */
MP_intsrc_info(&intsrc);
}
static void __init construct_ioapic_table(int mpc_default_type)
{
- struct mpc_config_ioapic ioapic;
- struct mpc_config_bus bus;
+ struct mpc_ioapic ioapic;
+ struct mpc_bus bus;
- bus.mpc_type = MP_BUS;
- bus.mpc_busid = 0;
+ bus.type = MP_BUS;
+ bus.busid = 0;
switch (mpc_default_type) {
default:
printk(KERN_ERR "???\nUnknown standard configuration %d\n",
@@ -500,29 +493,29 @@ static void __init construct_ioapic_table(int mpc_default_type)
/* fall through */
case 1:
case 5:
- memcpy(bus.mpc_bustype, "ISA ", 6);
+ memcpy(bus.bustype, "ISA ", 6);
break;
case 2:
case 6:
case 3:
- memcpy(bus.mpc_bustype, "EISA ", 6);
+ memcpy(bus.bustype, "EISA ", 6);
break;
case 4:
case 7:
- memcpy(bus.mpc_bustype, "MCA ", 6);
+ memcpy(bus.bustype, "MCA ", 6);
}
MP_bus_info(&bus);
if (mpc_default_type > 4) {
- bus.mpc_busid = 1;
- memcpy(bus.mpc_bustype, "PCI ", 6);
+ bus.busid = 1;
+ memcpy(bus.bustype, "PCI ", 6);
MP_bus_info(&bus);
}
- ioapic.mpc_type = MP_IOAPIC;
- ioapic.mpc_apicid = 2;
- ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
- ioapic.mpc_flags = MPC_APIC_USABLE;
- ioapic.mpc_apicaddr = 0xFEC00000;
+ ioapic.type = MP_IOAPIC;
+ ioapic.apicid = 2;
+ ioapic.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+ ioapic.flags = MPC_APIC_USABLE;
+ ioapic.apicaddr = 0xFEC00000;
MP_ioapic_info(&ioapic);
/*
@@ -536,8 +529,8 @@ static inline void __init construct_ioapic_table(int mpc_default_type) { }
static inline void __init construct_default_ISA_mptable(int mpc_default_type)
{
- struct mpc_config_processor processor;
- struct mpc_config_lintsrc lintsrc;
+ struct mpc_cpu processor;
+ struct mpc_lintsrc lintsrc;
int linttypes[2] = { mp_ExtINT, mp_NMI };
int i;
@@ -549,30 +542,30 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
/*
* 2 CPUs, numbered 0 & 1.
*/
- processor.mpc_type = MP_PROCESSOR;
+ processor.type = MP_PROCESSOR;
/* Either an integrated APIC or a discrete 82489DX. */
- processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
- processor.mpc_cpuflag = CPU_ENABLED;
- processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
+ processor.apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+ processor.cpuflag = CPU_ENABLED;
+ processor.cpufeature = (boot_cpu_data.x86 << 8) |
(boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
- processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
- processor.mpc_reserved[0] = 0;
- processor.mpc_reserved[1] = 0;
+ processor.featureflag = boot_cpu_data.x86_capability[0];
+ processor.reserved[0] = 0;
+ processor.reserved[1] = 0;
for (i = 0; i < 2; i++) {
- processor.mpc_apicid = i;
+ processor.apicid = i;
MP_processor_info(&processor);
}
construct_ioapic_table(mpc_default_type);
- lintsrc.mpc_type = MP_LINTSRC;
- lintsrc.mpc_irqflag = 0; /* conforming */
- lintsrc.mpc_srcbusid = 0;
- lintsrc.mpc_srcbusirq = 0;
- lintsrc.mpc_destapic = MP_APIC_ALL;
+ lintsrc.type = MP_LINTSRC;
+ lintsrc.irqflag = 0; /* conforming */
+ lintsrc.srcbusid = 0;
+ lintsrc.srcbusirq = 0;
+ lintsrc.destapic = MP_APIC_ALL;
for (i = 0; i < 2; i++) {
- lintsrc.mpc_irqtype = linttypes[i];
- lintsrc.mpc_destapiclint = i;
+ lintsrc.irqtype = linttypes[i];
+ lintsrc.destapiclint = i;
MP_lintsrc_info(&lintsrc);
}
}
@@ -657,15 +650,15 @@ static void __init __get_smp_config(unsigned int early)
* ISA defaults and hope it will work.
*/
if (!mp_irq_entries) {
- struct mpc_config_bus bus;
+ struct mpc_bus bus;
printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
"using default mptable. "
"(tell your hw vendor)\n");
- bus.mpc_type = MP_BUS;
- bus.mpc_busid = 0;
- memcpy(bus.mpc_bustype, "ISA ", 6);
+ bus.type = MP_BUS;
+ bus.busid = 0;
+ memcpy(bus.bustype, "ISA ", 6);
MP_bus_info(&bus);
construct_default_ioirq_mptable(0);
@@ -803,14 +796,14 @@ void __init find_smp_config(void)
#ifdef CONFIG_X86_IO_APIC
static u8 __initdata irq_used[MAX_IRQ_SOURCES];
-static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
+static int __init get_MP_intsrc_index(struct mpc_intsrc *m)
{
int i;
- if (m->mpc_irqtype != mp_INT)
+ if (m->irqtype != mp_INT)
return 0;
- if (m->mpc_irqflag != 0x0f)
+ if (m->irqflag != 0x0f)
return 0;
/* not legacy */
@@ -822,9 +815,9 @@ static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
if (mp_irqs[i].mp_irqflag != 0x0f)
continue;
- if (mp_irqs[i].mp_srcbus != m->mpc_srcbus)
+ if (mp_irqs[i].mp_srcbus != m->srcbus)
continue;
- if (mp_irqs[i].mp_srcbusirq != m->mpc_srcbusirq)
+ if (mp_irqs[i].mp_srcbusirq != m->srcbusirq)
continue;
if (irq_used[i]) {
/* already claimed */
@@ -840,10 +833,10 @@ static int __init get_MP_intsrc_index(struct mpc_config_intsrc *m)
#define SPARE_SLOT_NUM 20
-static struct mpc_config_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
+static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM];
#endif
-static int __init replace_intsrc_all(struct mp_config_table *mpc,
+static int __init replace_intsrc_all(struct mpc_table *mpc,
unsigned long mpc_new_phys,
unsigned long mpc_new_length)
{
@@ -855,36 +848,33 @@ static int __init replace_intsrc_all(struct mp_config_table *mpc,
int count = sizeof(*mpc);
unsigned char *mpt = ((unsigned char *)mpc) + count;
- printk(KERN_INFO "mpc_length %x\n", mpc->mpc_length);
- while (count < mpc->mpc_length) {
+ printk(KERN_INFO "mpc_length %x\n", mpc->length);
+ while (count < mpc->length) {
switch (*mpt) {
case MP_PROCESSOR:
{
- struct mpc_config_processor *m =
- (struct mpc_config_processor *)mpt;
+ struct mpc_cpu *m = (struct mpc_cpu *)mpt;
mpt += sizeof(*m);
count += sizeof(*m);
break;
}
case MP_BUS:
{
- struct mpc_config_bus *m =
- (struct mpc_config_bus *)mpt;
+ struct mpc_bus *m = (struct mpc_bus *)mpt;
mpt += sizeof(*m);
count += sizeof(*m);
break;
}
case MP_IOAPIC:
{
- mpt += sizeof(struct mpc_config_ioapic);
- count += sizeof(struct mpc_config_ioapic);
+ mpt += sizeof(struct mpc_ioapic);
+ count += sizeof(struct mpc_ioapic);
break;
}
case MP_INTSRC:
{
#ifdef CONFIG_X86_IO_APIC
- struct mpc_config_intsrc *m =
- (struct mpc_config_intsrc *)mpt;
+ struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
printk(KERN_INFO "OLD ");
print_MP_intsrc_info(m);
@@ -905,14 +895,14 @@ static int __init replace_intsrc_all(struct mp_config_table *mpc,
nr_m_spare++;
}
#endif
- mpt += sizeof(struct mpc_config_intsrc);
- count += sizeof(struct mpc_config_intsrc);
+ mpt += sizeof(struct mpc_intsrc);
+ count += sizeof(struct mpc_intsrc);
break;
}
case MP_LINTSRC:
{
- struct mpc_config_lintsrc *m =
- (struct mpc_config_lintsrc *)mpt;
+ struct mpc_lintsrc *m =
+ (struct mpc_lintsrc *)mpt;
mpt += sizeof(*m);
count += sizeof(*m);
break;
@@ -922,7 +912,7 @@ static int __init replace_intsrc_all(struct mp_config_table *mpc,
printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n");
printk(KERN_ERR "type %x\n", *mpt);
print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
- 1, mpc, mpc->mpc_length, 1);
+ 1, mpc, mpc->length, 1);
goto out;
}
}
@@ -944,9 +934,8 @@ static int __init replace_intsrc_all(struct mp_config_table *mpc,
assign_to_mpc_intsrc(&mp_irqs[i], m_spare[nr_m_spare]);
m_spare[nr_m_spare] = NULL;
} else {
- struct mpc_config_intsrc *m =
- (struct mpc_config_intsrc *)mpt;
- count += sizeof(struct mpc_config_intsrc);
+ struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
+ count += sizeof(struct mpc_intsrc);
if (!mpc_new_phys) {
printk(KERN_INFO "No spare slots, try to append...take your risk, new mpc_length %x\n", count);
} else {
@@ -958,17 +947,16 @@ static int __init replace_intsrc_all(struct mp_config_table *mpc,
}
}
assign_to_mpc_intsrc(&mp_irqs[i], m);
- mpc->mpc_length = count;
- mpt += sizeof(struct mpc_config_intsrc);
+ mpc->length = count;
+ mpt += sizeof(struct mpc_intsrc);
}
print_mp_irq_info(&mp_irqs[i]);
}
#endif
out:
/* update checksum */
- mpc->mpc_checksum = 0;
- mpc->mpc_checksum -= mpf_checksum((unsigned char *)mpc,
- mpc->mpc_length);
+ mpc->checksum = 0;
+ mpc->checksum -= mpf_checksum((unsigned char *)mpc, mpc->length);
return 0;
}
@@ -1014,8 +1002,7 @@ static int __init update_mp_table(void)
char str[16];
char oem[10];
struct intel_mp_floating *mpf;
- struct mp_config_table *mpc;
- struct mp_config_table *mpc_new;
+ struct mpc_table *mpc, *mpc_new;
if (!enable_update_mptable)
return 0;
@@ -1041,7 +1028,7 @@ static int __init update_mp_table(void)
printk(KERN_INFO "mpf: %lx\n", virt_to_phys(mpf));
printk(KERN_INFO "mpf_physptr: %x\n", mpf->mpf_physptr);
- if (mpc_new_phys && mpc->mpc_length > mpc_new_length) {
+ if (mpc_new_phys && mpc->length > mpc_new_length) {
mpc_new_phys = 0;
printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
mpc_new_length);
@@ -1050,10 +1037,10 @@ static int __init update_mp_table(void)
if (!mpc_new_phys) {
unsigned char old, new;
/* check if we can change the postion */
- mpc->mpc_checksum = 0;
- old = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
- mpc->mpc_checksum = 0xff;
- new = mpf_checksum((unsigned char *)mpc, mpc->mpc_length);
+ mpc->checksum = 0;
+ old = mpf_checksum((unsigned char *)mpc, mpc->length);
+ mpc->checksum = 0xff;
+ new = mpf_checksum((unsigned char *)mpc, mpc->length);
if (old == new) {
printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
return 0;
@@ -1062,7 +1049,7 @@ static int __init update_mp_table(void)
} else {
mpf->mpf_physptr = mpc_new_phys;
mpc_new = phys_to_virt(mpc_new_phys);
- memcpy(mpc_new, mpc, mpc->mpc_length);
+ memcpy(mpc_new, mpc, mpc->length);
mpc = mpc_new;
/* check if we can modify that */
if (mpc_new_phys - mpf->mpf_physptr) {
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index 82a7c7ed6d45..726266695b2c 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -136,7 +136,7 @@ static int msr_open(struct inode *inode, struct file *file)
lock_kernel();
cpu = iminor(file->f_path.dentry->d_inode);
- if (cpu >= NR_CPUS || !cpu_online(cpu)) {
+ if (cpu >= nr_cpu_ids || !cpu_online(cpu)) {
ret = -ENXIO; /* No such CPU */
goto out;
}
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index 8bd1bf9622a7..7228979f1e7f 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -29,8 +29,6 @@
#include <asm/i8259.h>
#include <asm/io_apic.h>
-#include <asm/smp.h>
-#include <asm/nmi.h>
#include <asm/proto.h>
#include <asm/timer.h>
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/numaq_32.c
index 0deea37a53cf..f2191d4f2717 100644
--- a/arch/x86/kernel/numaq_32.c
+++ b/arch/x86/kernel/numaq_32.c
@@ -117,16 +117,15 @@ static inline int generate_logical_apicid(int quad, int phys_apicid)
}
/* x86_quirks member */
-static int mpc_apic_id(struct mpc_config_processor *m)
+static int mpc_apic_id(struct mpc_cpu *m)
{
int quad = translation_table[mpc_record]->trans_quad;
- int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
+ int logical_apicid = generate_logical_apicid(quad, m->apicid);
printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
- m->mpc_apicid,
- (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
- (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
- m->mpc_apicver, quad, logical_apicid);
+ m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8,
+ (m->cpufeature & CPU_MODEL_MASK) >> 4,
+ m->apicver, quad, logical_apicid);
return logical_apicid;
}
@@ -135,26 +134,26 @@ int mp_bus_id_to_node[MAX_MP_BUSSES];
int mp_bus_id_to_local[MAX_MP_BUSSES];
/* x86_quirks member */
-static void mpc_oem_bus_info(struct mpc_config_bus *m, char *name)
+static void mpc_oem_bus_info(struct mpc_bus *m, char *name)
{
int quad = translation_table[mpc_record]->trans_quad;
int local = translation_table[mpc_record]->trans_local;
- mp_bus_id_to_node[m->mpc_busid] = quad;
- mp_bus_id_to_local[m->mpc_busid] = local;
+ mp_bus_id_to_node[m->busid] = quad;
+ mp_bus_id_to_local[m->busid] = local;
printk(KERN_INFO "Bus #%d is %s (node %d)\n",
- m->mpc_busid, name, quad);
+ m->busid, name, quad);
}
int quad_local_to_mp_bus_id [NR_CPUS/4][4];
/* x86_quirks member */
-static void mpc_oem_pci_bus(struct mpc_config_bus *m)
+static void mpc_oem_pci_bus(struct mpc_bus *m)
{
int quad = translation_table[mpc_record]->trans_quad;
int local = translation_table[mpc_record]->trans_local;
- quad_local_to_mp_bus_id[quad][local] = m->mpc_busid;
+ quad_local_to_mp_bus_id[quad][local] = m->busid;
}
static void __init MP_translation_info(struct mpc_config_translation *m)
@@ -186,7 +185,7 @@ static int __init mpf_checksum(unsigned char *mp, int len)
* Read/parse the MPC oem tables
*/
-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
+static void __init smp_read_mpc_oem(struct mpc_oemtable *oemtable,
unsigned short oemsize)
{
int count = sizeof(*oemtable); /* the header size */
@@ -195,18 +194,18 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
mpc_record = 0;
printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
oemtable);
- if (memcmp(oemtable->oem_signature, MPC_OEM_SIGNATURE, 4)) {
+ if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) {
printk(KERN_WARNING
"SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
- oemtable->oem_signature[0], oemtable->oem_signature[1],
- oemtable->oem_signature[2], oemtable->oem_signature[3]);
+ oemtable->signature[0], oemtable->signature[1],
+ oemtable->signature[2], oemtable->signature[3]);
return;
}
- if (mpf_checksum((unsigned char *)oemtable, oemtable->oem_length)) {
+ if (mpf_checksum((unsigned char *)oemtable, oemtable->length)) {
printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
return;
}
- while (count < oemtable->oem_length) {
+ while (count < oemtable->length) {
switch (*oemptr) {
case MP_TRANSLATION:
{
@@ -260,8 +259,7 @@ static struct x86_quirks numaq_x86_quirks __initdata = {
.update_genapic = numaq_update_genapic,
};
-void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid)
+void numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
{
if (strncmp(oem, "IBM NUMA", 8))
printk("Warning! Not a NUMA-Q system!\n");
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 19a1044a0cd9..b25428533141 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -38,7 +38,7 @@ EXPORT_SYMBOL(bad_dma_address);
be probably a smaller DMA mask, but this is bug-to-bug compatible
to older i386. */
struct device x86_dma_fallback_dev = {
- .bus_id = "fallback device",
+ .init_name = "fallback device",
.coherent_dma_mask = DMA_32BIT_MASK,
.dma_mask = &x86_dma_fallback_dev.coherent_dma_mask,
};
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index a35eaa379ff6..d5768b1af080 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -5,7 +5,7 @@
* This allows to use PCI devices that only support 32bit addresses on systems
* with more than 4GB.
*
- * See Documentation/DMA-mapping.txt for the interface specification.
+ * See Documentation/PCI/PCI-DMA-mapping.txt for the interface specification.
*
* Copyright 2002 Andi Kleen, SuSE Labs.
* Subject to the GNU General Public License v2 only.
@@ -52,7 +52,7 @@ static u32 *iommu_gatt_base; /* Remapping table */
* to trigger bugs with some popular PCI cards, in particular 3ware (but
* has been also also seen with Qlogic at least).
*/
-int iommu_fullflush = 1;
+static int iommu_fullflush = 1;
/* Allocation bitmap for the remapping area: */
static DEFINE_SPINLOCK(iommu_bitmap_lock);
diff --git a/arch/x86/kernel/pci-swiotlb_64.c b/arch/x86/kernel/pci-swiotlb_64.c
index 242c3440687f..d59c91747665 100644
--- a/arch/x86/kernel/pci-swiotlb_64.c
+++ b/arch/x86/kernel/pci-swiotlb_64.c
@@ -13,7 +13,7 @@
int swiotlb __read_mostly;
-void *swiotlb_alloc_boot(size_t size, unsigned long nslabs)
+void * __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
{
return alloc_bootmem_low_pages(size);
}
@@ -23,7 +23,7 @@ void *swiotlb_alloc(unsigned order, unsigned long nslabs)
return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
}
-dma_addr_t swiotlb_phys_to_bus(phys_addr_t paddr)
+dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
{
return paddr;
}
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 3ba155d24884..a546f55c77b4 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -39,11 +39,12 @@
#include <linux/prctl.h>
#include <linux/dmi.h>
#include <linux/ftrace.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/kdebug.h>
-#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
-#include <asm/io.h>
#include <asm/ldt.h>
#include <asm/processor.h>
#include <asm/i387.h>
@@ -56,10 +57,8 @@
#include <asm/tlbflush.h>
#include <asm/cpu.h>
-#include <asm/kdebug.h>
#include <asm/idle.h>
#include <asm/syscalls.h>
-#include <asm/smp.h>
#include <asm/ds.h>
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
@@ -205,7 +204,7 @@ extern void kernel_thread_helper(void);
/*
* Create a kernel thread
*/
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
struct pt_regs regs;
@@ -266,7 +265,7 @@ void flush_thread(void)
tsk->thread.debugreg3 = 0;
tsk->thread.debugreg6 = 0;
tsk->thread.debugreg7 = 0;
- memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
+ memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
clear_tsk_thread_flag(tsk, TIF_DEBUG);
/*
* Forget coprocessor state..
@@ -293,9 +292,9 @@ void prepare_to_copy(struct task_struct *tsk)
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long unused,
- struct task_struct * p, struct pt_regs * regs)
+ struct task_struct *p, struct pt_regs *regs)
{
- struct pt_regs * childregs;
+ struct pt_regs *childregs;
struct task_struct *tsk;
int err;
@@ -347,7 +346,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
void
start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
{
- __asm__("movl %0, %%gs" :: "r"(0));
+ __asm__("movl %0, %%gs" : : "r"(0));
regs->fs = 0;
set_fs(USER_DS);
regs->ds = __USER_DS;
@@ -638,7 +637,7 @@ asmlinkage int sys_vfork(struct pt_regs regs)
asmlinkage int sys_execve(struct pt_regs regs)
{
int error;
- char * filename;
+ char *filename;
filename = getname((char __user *) regs.bx);
error = PTR_ERR(filename);
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 61f718df6eec..2b46eb41643b 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -12,6 +12,8 @@
#include <asm/proto.h>
#include <asm/reboot_fixups.h>
#include <asm/reboot.h>
+#include <asm/pci_x86.h>
+#include <asm/virtext.h>
#ifdef CONFIG_X86_32
# include <linux/dmi.h>
@@ -23,7 +25,6 @@
#include <mach_ipi.h>
-
/*
* Power off function, if any
*/
@@ -39,6 +40,12 @@ int reboot_force;
static int reboot_cpu = -1;
#endif
+/* This is set if we need to go through the 'emergency' path.
+ * When machine_emergency_restart() is called, we may be on
+ * an inconsistent state and won't be able to do a clean cleanup
+ */
+static int reboot_emergency;
+
/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
bool port_cf9_safe = false;
@@ -368,6 +375,48 @@ static inline void kb_wait(void)
}
}
+static void vmxoff_nmi(int cpu, struct die_args *args)
+{
+ cpu_emergency_vmxoff();
+}
+
+/* Use NMIs as IPIs to tell all CPUs to disable virtualization
+ */
+static void emergency_vmx_disable_all(void)
+{
+ /* Just make sure we won't change CPUs while doing this */
+ local_irq_disable();
+
+ /* We need to disable VMX on all CPUs before rebooting, otherwise
+ * we risk hanging up the machine, because the CPU ignore INIT
+ * signals when VMX is enabled.
+ *
+ * We can't take any locks and we may be on an inconsistent
+ * state, so we use NMIs as IPIs to tell the other CPUs to disable
+ * VMX and halt.
+ *
+ * For safety, we will avoid running the nmi_shootdown_cpus()
+ * stuff unnecessarily, but we don't have a way to check
+ * if other CPUs have VMX enabled. So we will call it only if the
+ * CPU we are running on has VMX enabled.
+ *
+ * We will miss cases where VMX is not enabled on all CPUs. This
+ * shouldn't do much harm because KVM always enable VMX on all
+ * CPUs anyway. But we can miss it on the small window where KVM
+ * is still enabling VMX.
+ */
+ if (cpu_has_vmx() && cpu_vmx_enabled()) {
+ /* Disable VMX on this CPU.
+ */
+ cpu_vmxoff();
+
+ /* Halt and disable VMX on the other CPUs */
+ nmi_shootdown_cpus(vmxoff_nmi);
+
+ }
+}
+
+
void __attribute__((weak)) mach_reboot_fixups(void)
{
}
@@ -376,6 +425,9 @@ static void native_machine_emergency_restart(void)
{
int i;
+ if (reboot_emergency)
+ emergency_vmx_disable_all();
+
/* Tell the BIOS if we want cold or warm reboot */
*((unsigned short *)__va(0x472)) = reboot_mode;
@@ -449,7 +501,7 @@ void native_machine_shutdown(void)
#ifdef CONFIG_X86_32
/* See if there has been given a command line override */
- if ((reboot_cpu != -1) && (reboot_cpu < NR_CPUS) &&
+ if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
cpu_online(reboot_cpu))
reboot_cpu_id = reboot_cpu;
#endif
@@ -459,7 +511,7 @@ void native_machine_shutdown(void)
reboot_cpu_id = smp_processor_id();
/* Make certain I only run on the appropriate processor */
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(reboot_cpu_id));
+ set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id));
/* O.K Now that I'm on the appropriate processor,
* stop all of the others.
@@ -482,13 +534,19 @@ void native_machine_shutdown(void)
#endif
}
+static void __machine_emergency_restart(int emergency)
+{
+ reboot_emergency = emergency;
+ machine_ops.emergency_restart();
+}
+
static void native_machine_restart(char *__unused)
{
printk("machine restart\n");
if (!reboot_force)
machine_shutdown();
- machine_emergency_restart();
+ __machine_emergency_restart(0);
}
static void native_machine_halt(void)
@@ -532,7 +590,7 @@ void machine_shutdown(void)
void machine_emergency_restart(void)
{
- machine_ops.emergency_restart();
+ __machine_emergency_restart(1);
}
void machine_restart(char *cmd)
@@ -592,10 +650,7 @@ static int crash_nmi_callback(struct notifier_block *self,
static void smp_send_nmi_allbutself(void)
{
- cpumask_t mask = cpu_online_map;
- cpu_clear(safe_smp_processor_id(), mask);
- if (!cpus_empty(mask))
- send_IPI_mask(mask, NMI_VECTOR);
+ send_IPI_allbutself(NMI_VECTOR);
}
static struct notifier_block crash_nmi_nb = {
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index ae0c0d3bb770..01161077a49c 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -5,12 +5,11 @@
#include <linux/percpu.h>
#include <linux/kexec.h>
#include <linux/crash_dump.h>
-#include <asm/smp.h>
-#include <asm/percpu.h>
+#include <linux/smp.h>
+#include <linux/topology.h>
#include <asm/sections.h>
#include <asm/processor.h>
#include <asm/setup.h>
-#include <asm/topology.h>
#include <asm/mpspec.h>
#include <asm/apicdef.h>
#include <asm/highmem.h>
@@ -20,8 +19,8 @@ unsigned int num_processors;
unsigned disabled_cpus __cpuinitdata;
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
-unsigned int max_physical_apicid;
EXPORT_SYMBOL(boot_cpu_physical_apicid);
+unsigned int max_physical_apicid;
/* Bitmask of physically existing CPUs */
physid_mask_t phys_cpu_present_map;
@@ -131,7 +130,27 @@ static void __init setup_cpu_pda_map(void)
/* point to new pointer table */
_cpu_pda = new_cpu_pda;
}
-#endif
+
+#endif /* CONFIG_SMP && CONFIG_X86_64 */
+
+#ifdef CONFIG_X86_64
+
+/* correctly size the local cpu masks */
+static void __init setup_cpu_local_masks(void)
+{
+ alloc_bootmem_cpumask_var(&cpu_initialized_mask);
+ alloc_bootmem_cpumask_var(&cpu_callin_mask);
+ alloc_bootmem_cpumask_var(&cpu_callout_mask);
+ alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
+}
+
+#else /* CONFIG_X86_32 */
+
+static inline void setup_cpu_local_masks(void)
+{
+}
+
+#endif /* CONFIG_X86_32 */
/*
* Great future plan:
@@ -152,8 +171,11 @@ void __init setup_per_cpu_areas(void)
old_size = PERCPU_ENOUGH_ROOM;
align = max_t(unsigned long, PAGE_SIZE, align);
size = roundup(old_size, align);
- printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",
- size);
+
+ pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n",
+ NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids);
+
+ pr_info("PERCPU: Allocating %zd bytes of per cpu data\n", size);
for_each_possible_cpu(cpu) {
#ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -164,33 +186,29 @@ void __init setup_per_cpu_areas(void)
if (!node_online(node) || !NODE_DATA(node)) {
ptr = __alloc_bootmem(size, align,
__pa(MAX_DMA_ADDRESS));
- printk(KERN_INFO
- "cpu %d has no node %d or node-local memory\n",
+ pr_info("cpu %d has no node %d or node-local memory\n",
cpu, node);
- if (ptr)
- printk(KERN_DEBUG "per cpu data for cpu%d at %016lx\n",
- cpu, __pa(ptr));
- }
- else {
+ pr_debug("per cpu data for cpu%d at %016lx\n",
+ cpu, __pa(ptr));
+ } else {
ptr = __alloc_bootmem_node(NODE_DATA(node), size, align,
__pa(MAX_DMA_ADDRESS));
- if (ptr)
- printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n",
- cpu, node, __pa(ptr));
+ pr_debug("per cpu data for cpu%d on node%d at %016lx\n",
+ cpu, node, __pa(ptr));
}
#endif
per_cpu_offset(cpu) = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
}
- printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n",
- NR_CPUS, nr_cpu_ids, nr_node_ids);
-
/* Setup percpu data maps */
setup_per_cpu_maps();
/* Setup node to cpumask map */
setup_node_to_cpumask_map();
+
+ /* Setup cpu initialized, callin, callout masks */
+ setup_cpu_local_masks();
}
#endif
@@ -282,10 +300,10 @@ static void __cpuinit numa_set_cpumask(int cpu, int enable)
else
cpu_clear(cpu, *mask);
- cpulist_scnprintf(buf, sizeof(buf), *mask);
+ cpulist_scnprintf(buf, sizeof(buf), mask);
printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
- enable? "numa_add_cpu":"numa_remove_cpu", cpu, node, buf);
- }
+ enable ? "numa_add_cpu" : "numa_remove_cpu", cpu, node, buf);
+}
void __cpuinit numa_add_cpu(int cpu)
{
@@ -334,25 +352,25 @@ static const cpumask_t cpu_mask_none;
/*
* Returns a pointer to the bitmask of CPUs on Node 'node'.
*/
-const cpumask_t *_node_to_cpumask_ptr(int node)
+const cpumask_t *cpumask_of_node(int node)
{
if (node_to_cpumask_map == NULL) {
printk(KERN_WARNING
- "_node_to_cpumask_ptr(%d): no node_to_cpumask_map!\n",
+ "cpumask_of_node(%d): no node_to_cpumask_map!\n",
node);
dump_stack();
return (const cpumask_t *)&cpu_online_map;
}
if (node >= nr_node_ids) {
printk(KERN_WARNING
- "_node_to_cpumask_ptr(%d): node > nr_node_ids(%d)\n",
+ "cpumask_of_node(%d): node > nr_node_ids(%d)\n",
node, nr_node_ids);
dump_stack();
return &cpu_mask_none;
}
return &node_to_cpumask_map[node];
}
-EXPORT_SYMBOL(_node_to_cpumask_ptr);
+EXPORT_SYMBOL(cpumask_of_node);
/*
* Returns a bitmask of CPUs on Node 'node'.
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 89bb7668041d..df0587f24c54 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -632,9 +632,16 @@ badframe:
}
#ifdef CONFIG_X86_32
-asmlinkage int sys_rt_sigreturn(struct pt_regs regs)
+/*
+ * Note: do not pass in pt_regs directly as with tail-call optimization
+ * GCC will incorrectly stomp on the caller's frame and corrupt user-space
+ * register state:
+ */
+asmlinkage int sys_rt_sigreturn(unsigned long __unused)
{
- return do_rt_sigreturn(&regs);
+ struct pt_regs *regs = (struct pt_regs *)&__unused;
+
+ return do_rt_sigreturn(regs);
}
#else /* !CONFIG_X86_32 */
asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index 7e558db362c1..e6faa3316bd2 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -1,7 +1,7 @@
/*
* Intel SMP support routines.
*
- * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ * (c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
* (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
* (c) 2002,2003 Andi Kleen, SuSE Labs.
*
@@ -118,26 +118,33 @@ static void native_smp_send_reschedule(int cpu)
WARN_ON(1);
return;
}
- send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
+ send_IPI_mask(cpumask_of(cpu), RESCHEDULE_VECTOR);
}
void native_send_call_func_single_ipi(int cpu)
{
- send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_SINGLE_VECTOR);
+ send_IPI_mask(cpumask_of(cpu), CALL_FUNCTION_SINGLE_VECTOR);
}
-void native_send_call_func_ipi(cpumask_t mask)
+void native_send_call_func_ipi(const struct cpumask *mask)
{
- cpumask_t allbutself;
+ cpumask_var_t allbutself;
- allbutself = cpu_online_map;
- cpu_clear(smp_processor_id(), allbutself);
+ if (!alloc_cpumask_var(&allbutself, GFP_ATOMIC)) {
+ send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+ return;
+ }
- if (cpus_equal(mask, allbutself) &&
- cpus_equal(cpu_online_map, cpu_callout_map))
+ cpumask_copy(allbutself, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), allbutself);
+
+ if (cpumask_equal(mask, allbutself) &&
+ cpumask_equal(cpu_online_mask, cpu_callout_mask))
send_IPI_allbutself(CALL_FUNCTION_VECTOR);
else
send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+
+ free_cpumask_var(allbutself);
}
/*
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index f8500c969442..bb1a3b1fc87f 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1,7 +1,7 @@
/*
* x86 SMP booting functions
*
- * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ * (c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
* (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
* Copyright 2001 Andi Kleen, SuSE Labs.
*
@@ -102,15 +102,6 @@ EXPORT_SYMBOL(smp_num_siblings);
/* Last level cache ID of each logical CPU */
DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID;
-/* bitmap of online cpus */
-cpumask_t cpu_online_map __read_mostly;
-EXPORT_SYMBOL(cpu_online_map);
-
-cpumask_t cpu_callin_map;
-cpumask_t cpu_callout_map;
-cpumask_t cpu_possible_map;
-EXPORT_SYMBOL(cpu_possible_map);
-
/* representing HT siblings of each logical CPU */
DEFINE_PER_CPU(cpumask_t, cpu_sibling_map);
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
@@ -126,9 +117,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
static atomic_t init_deasserted;
-/* representing cpus for which sibling maps can be computed */
-static cpumask_t cpu_sibling_setup_map;
-
/* Set if we find a B stepping CPU */
static int __cpuinitdata smp_b_stepping;
@@ -146,7 +134,7 @@ EXPORT_SYMBOL(cpu_to_node_map);
static void map_cpu_to_node(int cpu, int node)
{
printk(KERN_INFO "Mapping cpu %d to node %d\n", cpu, node);
- cpu_set(cpu, node_to_cpumask_map[node]);
+ cpumask_set_cpu(cpu, &node_to_cpumask_map[node]);
cpu_to_node_map[cpu] = node;
}
@@ -157,7 +145,7 @@ static void unmap_cpu_to_node(int cpu)
printk(KERN_INFO "Unmapping cpu %d from all nodes\n", cpu);
for (node = 0; node < MAX_NUMNODES; node++)
- cpu_clear(cpu, node_to_cpumask_map[node]);
+ cpumask_clear_cpu(cpu, &node_to_cpumask_map[node]);
cpu_to_node_map[cpu] = 0;
}
#else /* !(CONFIG_NUMA && CONFIG_X86_32) */
@@ -215,7 +203,7 @@ static void __cpuinit smp_callin(void)
*/
phys_id = read_apic_id();
cpuid = smp_processor_id();
- if (cpu_isset(cpuid, cpu_callin_map)) {
+ if (cpumask_test_cpu(cpuid, cpu_callin_mask)) {
panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
phys_id, cpuid);
}
@@ -237,7 +225,7 @@ static void __cpuinit smp_callin(void)
/*
* Has the boot CPU finished it's STARTUP sequence?
*/
- if (cpu_isset(cpuid, cpu_callout_map))
+ if (cpumask_test_cpu(cpuid, cpu_callout_mask))
break;
cpu_relax();
}
@@ -280,7 +268,7 @@ static void __cpuinit smp_callin(void)
/*
* Allow the master to continue.
*/
- cpu_set(cpuid, cpu_callin_map);
+ cpumask_set_cpu(cpuid, cpu_callin_mask);
}
static int __cpuinitdata unsafe_smp;
@@ -338,7 +326,7 @@ notrace static void __cpuinit start_secondary(void *unused)
ipi_call_lock();
lock_vector_lock();
__setup_vector_irq(smp_processor_id());
- cpu_set(smp_processor_id(), cpu_online_map);
+ set_cpu_online(smp_processor_id(), true);
unlock_vector_lock();
ipi_call_unlock();
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
@@ -444,50 +432,52 @@ void __cpuinit set_cpu_sibling_map(int cpu)
int i;
struct cpuinfo_x86 *c = &cpu_data(cpu);
- cpu_set(cpu, cpu_sibling_setup_map);
+ cpumask_set_cpu(cpu, cpu_sibling_setup_mask);
if (smp_num_siblings > 1) {
- for_each_cpu_mask_nr(i, cpu_sibling_setup_map) {
- if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
- c->cpu_core_id == cpu_data(i).cpu_core_id) {
- cpu_set(i, per_cpu(cpu_sibling_map, cpu));
- cpu_set(cpu, per_cpu(cpu_sibling_map, i));
- cpu_set(i, per_cpu(cpu_core_map, cpu));
- cpu_set(cpu, per_cpu(cpu_core_map, i));
- cpu_set(i, c->llc_shared_map);
- cpu_set(cpu, cpu_data(i).llc_shared_map);
+ for_each_cpu(i, cpu_sibling_setup_mask) {
+ struct cpuinfo_x86 *o = &cpu_data(i);
+
+ if (c->phys_proc_id == o->phys_proc_id &&
+ c->cpu_core_id == o->cpu_core_id) {
+ cpumask_set_cpu(i, cpu_sibling_mask(cpu));
+ cpumask_set_cpu(cpu, cpu_sibling_mask(i));
+ cpumask_set_cpu(i, cpu_core_mask(cpu));
+ cpumask_set_cpu(cpu, cpu_core_mask(i));
+ cpumask_set_cpu(i, &c->llc_shared_map);
+ cpumask_set_cpu(cpu, &o->llc_shared_map);
}
}
} else {
- cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
+ cpumask_set_cpu(cpu, cpu_sibling_mask(cpu));
}
- cpu_set(cpu, c->llc_shared_map);
+ cpumask_set_cpu(cpu, &c->llc_shared_map);
if (current_cpu_data.x86_max_cores == 1) {
- per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
+ cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu));
c->booted_cores = 1;
return;
}
- for_each_cpu_mask_nr(i, cpu_sibling_setup_map) {
+ for_each_cpu(i, cpu_sibling_setup_mask) {
if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
- cpu_set(i, c->llc_shared_map);
- cpu_set(cpu, cpu_data(i).llc_shared_map);
+ cpumask_set_cpu(i, &c->llc_shared_map);
+ cpumask_set_cpu(cpu, &cpu_data(i).llc_shared_map);
}
if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
- cpu_set(i, per_cpu(cpu_core_map, cpu));
- cpu_set(cpu, per_cpu(cpu_core_map, i));
+ cpumask_set_cpu(i, cpu_core_mask(cpu));
+ cpumask_set_cpu(cpu, cpu_core_mask(i));
/*
* Does this new cpu bringup a new core?
*/
- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) {
+ if (cpumask_weight(cpu_sibling_mask(cpu)) == 1) {
/*
* for each core in package, increment
* the booted_cores for this new cpu
*/
- if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
+ if (cpumask_first(cpu_sibling_mask(i)) == i)
c->booted_cores++;
/*
* increment the core count for all
@@ -502,7 +492,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
}
/* maps the cpu to the sched domain representing multi-core */
-cpumask_t cpu_coregroup_map(int cpu)
+const struct cpumask *cpu_coregroup_mask(int cpu)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
/*
@@ -510,9 +500,14 @@ cpumask_t cpu_coregroup_map(int cpu)
* And for power savings, we return cpu_core_map
*/
if (sched_mc_power_savings || sched_smt_power_savings)
- return per_cpu(cpu_core_map, cpu);
+ return cpu_core_mask(cpu);
else
- return c->llc_shared_map;
+ return &c->llc_shared_map;
+}
+
+cpumask_t cpu_coregroup_map(int cpu)
+{
+ return *cpu_coregroup_mask(cpu);
}
static void impress_friends(void)
@@ -524,7 +519,7 @@ static void impress_friends(void)
*/
pr_debug("Before bogomips.\n");
for_each_possible_cpu(cpu)
- if (cpu_isset(cpu, cpu_callout_map))
+ if (cpumask_test_cpu(cpu, cpu_callout_mask))
bogosum += cpu_data(cpu).loops_per_jiffy;
printk(KERN_INFO
"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
@@ -905,19 +900,19 @@ do_rest:
* allow APs to start initializing.
*/
pr_debug("Before Callout %d.\n", cpu);
- cpu_set(cpu, cpu_callout_map);
+ cpumask_set_cpu(cpu, cpu_callout_mask);
pr_debug("After Callout %d.\n", cpu);
/*
* Wait 5s total for a response
*/
for (timeout = 0; timeout < 50000; timeout++) {
- if (cpu_isset(cpu, cpu_callin_map))
+ if (cpumask_test_cpu(cpu, cpu_callin_mask))
break; /* It has booted */
udelay(100);
}
- if (cpu_isset(cpu, cpu_callin_map)) {
+ if (cpumask_test_cpu(cpu, cpu_callin_mask)) {
/* number CPUs logically, starting from 1 (BSP is 0) */
pr_debug("OK.\n");
printk(KERN_INFO "CPU%d: ", cpu);
@@ -942,9 +937,14 @@ restore_state:
if (boot_error) {
/* Try to put things back the way they were before ... */
numa_remove_cpu(cpu); /* was set by numa_add_cpu */
- cpu_clear(cpu, cpu_callout_map); /* was set by do_boot_cpu() */
- cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
- cpu_clear(cpu, cpu_present_map);
+
+ /* was set by do_boot_cpu() */
+ cpumask_clear_cpu(cpu, cpu_callout_mask);
+
+ /* was set by cpu_init() */
+ cpumask_clear_cpu(cpu, cpu_initialized_mask);
+
+ set_cpu_present(cpu, false);
per_cpu(x86_cpu_to_apicid, cpu) = BAD_APICID;
}
@@ -978,7 +978,7 @@ int __cpuinit native_cpu_up(unsigned int cpu)
/*
* Already booted CPU?
*/
- if (cpu_isset(cpu, cpu_callin_map)) {
+ if (cpumask_test_cpu(cpu, cpu_callin_mask)) {
pr_debug("do_boot_cpu %d Already started\n", cpu);
return -ENOSYS;
}
@@ -1033,8 +1033,9 @@ int __cpuinit native_cpu_up(unsigned int cpu)
*/
static __init void disable_smp(void)
{
- cpu_present_map = cpumask_of_cpu(0);
- cpu_possible_map = cpumask_of_cpu(0);
+ /* use the read/write pointers to the present and possible maps */
+ cpumask_copy(&cpu_present_map, cpumask_of(0));
+ cpumask_copy(&cpu_possible_map, cpumask_of(0));
smpboot_clear_io_apic_irqs();
if (smp_found_config)
@@ -1042,8 +1043,8 @@ static __init void disable_smp(void)
else
physid_set_mask_of_physid(0, &phys_cpu_present_map);
map_cpu_to_logical_apicid();
- cpu_set(0, per_cpu(cpu_sibling_map, 0));
- cpu_set(0, per_cpu(cpu_core_map, 0));
+ cpumask_set_cpu(0, cpu_sibling_mask(0));
+ cpumask_set_cpu(0, cpu_core_mask(0));
}
/*
@@ -1065,14 +1066,14 @@ static int __init smp_sanity_check(unsigned max_cpus)
nr = 0;
for_each_present_cpu(cpu) {
if (nr >= 8)
- cpu_clear(cpu, cpu_present_map);
+ set_cpu_present(cpu, false);
nr++;
}
nr = 0;
for_each_possible_cpu(cpu) {
if (nr >= 8)
- cpu_clear(cpu, cpu_possible_map);
+ set_cpu_possible(cpu, false);
nr++;
}
@@ -1155,7 +1156,7 @@ static void __init smp_cpu_index_default(void)
for_each_possible_cpu(i) {
c = &cpu_data(i);
/* mark all to hotplug */
- c->cpu_index = NR_CPUS;
+ c->cpu_index = nr_cpu_ids;
}
}
@@ -1168,7 +1169,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
preempt_disable();
smp_cpu_index_default();
current_cpu_data = boot_cpu_data;
- cpu_callin_map = cpumask_of_cpu(0);
+ cpumask_copy(cpu_callin_mask, cpumask_of(0));
mb();
/*
* Setup boot CPU information
@@ -1243,8 +1244,8 @@ void __init native_smp_prepare_boot_cpu(void)
init_gdt(me);
#endif
switch_to_new_gdt();
- /* already set me in cpu_online_map in boot_cpu_init() */
- cpu_set(me, cpu_callout_map);
+ /* already set me in cpu_online_mask in boot_cpu_init() */
+ cpumask_set_cpu(me, cpu_callout_mask);
per_cpu(cpu_state, me) = CPU_ONLINE;
}
@@ -1260,6 +1261,15 @@ void __init native_smp_cpus_done(unsigned int max_cpus)
check_nmi_watchdog();
}
+static int __initdata setup_possible_cpus = -1;
+static int __init _setup_possible_cpus(char *str)
+{
+ get_option(&str, &setup_possible_cpus);
+ return 0;
+}
+early_param("possible_cpus", _setup_possible_cpus);
+
+
/*
* cpu_possible_map should be static, it cannot change as cpu's
* are onlined, or offlined. The reason is per-cpu data-structures
@@ -1272,7 +1282,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus)
*
* Three ways to find out the number of additional hotplug CPUs:
* - If the BIOS specified disabled CPUs in ACPI/mptables use that.
- * - The user can overwrite it with additional_cpus=NUM
+ * - The user can overwrite it with possible_cpus=NUM
* - Otherwise don't reserve additional CPUs.
* We do this because additional CPUs waste a lot of memory.
* -AK
@@ -1285,15 +1295,25 @@ __init void prefill_possible_map(void)
if (!num_processors)
num_processors = 1;
- possible = num_processors + disabled_cpus;
- if (possible > NR_CPUS)
- possible = NR_CPUS;
+ if (setup_possible_cpus == -1)
+ possible = num_processors + disabled_cpus;
+ else
+ possible = setup_possible_cpus;
+
+ total_cpus = max_t(int, possible, num_processors + disabled_cpus);
+
+ if (possible > CONFIG_NR_CPUS) {
+ printk(KERN_WARNING
+ "%d Processors exceeds NR_CPUS limit of %d\n",
+ possible, CONFIG_NR_CPUS);
+ possible = CONFIG_NR_CPUS;
+ }
printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
possible, max_t(int, possible - num_processors, 0));
for (i = 0; i < possible; i++)
- cpu_set(i, cpu_possible_map);
+ set_cpu_possible(i, true);
nr_cpu_ids = possible;
}
@@ -1305,31 +1325,31 @@ static void remove_siblinginfo(int cpu)
int sibling;
struct cpuinfo_x86 *c = &cpu_data(cpu);
- for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) {
- cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
+ for_each_cpu(sibling, cpu_core_mask(cpu)) {
+ cpumask_clear_cpu(cpu, cpu_core_mask(sibling));
/*/
* last thread sibling in this cpu core going down
*/
- if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
+ if (cpumask_weight(cpu_sibling_mask(cpu)) == 1)
cpu_data(sibling).booted_cores--;
}
- for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu))
- cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
- cpus_clear(per_cpu(cpu_sibling_map, cpu));
- cpus_clear(per_cpu(cpu_core_map, cpu));
+ for_each_cpu(sibling, cpu_sibling_mask(cpu))
+ cpumask_clear_cpu(cpu, cpu_sibling_mask(sibling));
+ cpumask_clear(cpu_sibling_mask(cpu));
+ cpumask_clear(cpu_core_mask(cpu));
c->phys_proc_id = 0;
c->cpu_core_id = 0;
- cpu_clear(cpu, cpu_sibling_setup_map);
+ cpumask_clear_cpu(cpu, cpu_sibling_setup_mask);
}
static void __ref remove_cpu_from_maps(int cpu)
{
- cpu_clear(cpu, cpu_online_map);
- cpu_clear(cpu, cpu_callout_map);
- cpu_clear(cpu, cpu_callin_map);
+ set_cpu_online(cpu, false);
+ cpumask_clear_cpu(cpu, cpu_callout_mask);
+ cpumask_clear_cpu(cpu, cpu_callin_mask);
/* was set by cpu_init() */
- cpu_clear(cpu, cpu_initialized);
+ cpumask_clear_cpu(cpu, cpu_initialized_mask);
numa_remove_cpu(cpu);
}
@@ -1352,7 +1372,7 @@ void cpu_disable_common(void)
lock_vector_lock();
remove_cpu_from_maps(cpu);
unlock_vector_lock();
- fixup_irqs(cpu_online_map);
+ fixup_irqs();
}
int native_cpu_disable(void)
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index d44395ff34c3..e2e86a08f31d 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -88,7 +88,7 @@ ENTRY(sys_call_table)
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir
+ .long sys_old_readdir
.long old_mmap /* 90 */
.long sys_munmap
.long sys_truncate
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c
index 65309e4cb1c0..3985cac0ed47 100644
--- a/arch/x86/kernel/time_32.c
+++ b/arch/x86/kernel/time_32.c
@@ -105,8 +105,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
high bit of the PPI port B (0x61). Note that some PS/2s,
notably the 55SX, work fine if this is removed. */
- u8 irq_v = inb_p( 0x61 ); /* read the current state */
- outb_p( irq_v|0x80, 0x61 ); /* reset the IRQ */
+ u8 irq_v = inb_p(0x61); /* read the current state */
+ outb_p(irq_v | 0x80, 0x61); /* reset the IRQ */
}
#endif
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c
index 891e7a7c4334..e6e695acd725 100644
--- a/arch/x86/kernel/time_64.c
+++ b/arch/x86/kernel/time_64.c
@@ -17,10 +17,10 @@
#include <linux/module.h>
#include <linux/time.h>
#include <linux/mca.h>
+#include <linux/nmi.h>
#include <asm/i8253.h>
#include <asm/hpet.h>
-#include <asm/nmi.h>
#include <asm/vgtod.h>
#include <asm/time.h>
#include <asm/timer.h>
diff --git a/arch/x86/kernel/tlb_32.c b/arch/x86/kernel/tlb_32.c
index 8da059f949be..ce5054642247 100644
--- a/arch/x86/kernel/tlb_32.c
+++ b/arch/x86/kernel/tlb_32.c
@@ -163,7 +163,7 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
* We have to send the IPI only to
* CPUs affected.
*/
- send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
+ send_IPI_mask(&cpumask, INVALIDATE_TLB_VECTOR);
while (!cpus_empty(flush_cpumask))
/* nothing. lockup detection does not belong here */
diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c
index 29887d7081a9..f8be6f1d2e48 100644
--- a/arch/x86/kernel/tlb_64.c
+++ b/arch/x86/kernel/tlb_64.c
@@ -191,7 +191,7 @@ void native_flush_tlb_others(const cpumask_t *cpumaskp, struct mm_struct *mm,
* We have to send the IPI only to
* CPUs affected.
*/
- send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR_START + sender);
+ send_IPI_mask(&cpumask, INVALIDATE_TLB_VECTOR_START + sender);
while (!cpus_empty(f->flush_cpumask))
cpu_relax();
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index 6a00e5faaa74..6812b829ed83 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -200,6 +200,7 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
destination_timeouts = 0;
}
}
+ cpu_relax();
}
return FLUSH_COMPLETE;
}
@@ -582,7 +583,6 @@ static int __init uv_ptc_init(void)
static struct bau_control * __init uv_table_bases_init(int blade, int node)
{
int i;
- int *ip;
struct bau_msg_status *msp;
struct bau_control *bau_tabp;
@@ -599,13 +599,6 @@ static struct bau_control * __init uv_table_bases_init(int blade, int node)
bau_cpubits_clear(&msp->seen_by, (int)
uv_blade_nr_possible_cpus(blade));
- bau_tabp->watching =
- kmalloc_node(sizeof(int) * DEST_NUM_RESOURCES, GFP_KERNEL, node);
- BUG_ON(!bau_tabp->watching);
-
- for (i = 0, ip = bau_tabp->watching; i < DEST_Q_SIZE; i++, ip++)
- *ip = 0;
-
uv_bau_table_bases[blade] = bau_tabp;
return bau_tabp;
@@ -628,7 +621,6 @@ uv_table_bases_finish(int blade, int node, int cur_cpu,
bcp->bau_msg_head = bau_tablesp->va_queue_first;
bcp->va_queue_first = bau_tablesp->va_queue_first;
bcp->va_queue_last = bau_tablesp->va_queue_last;
- bcp->watching = bau_tablesp->watching;
bcp->msg_statuses = bau_tablesp->msg_statuses;
bcp->descriptor_base = adp;
}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 141907ab6e22..98c2d055284b 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
#include <linux/ptrace.h>
#include <linux/string.h>
-#include <linux/unwind.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kexec.h>
@@ -51,7 +50,6 @@
#include <asm/debugreg.h>
#include <asm/atomic.h>
#include <asm/system.h>
-#include <asm/unwind.h>
#include <asm/traps.h>
#include <asm/desc.h>
#include <asm/i387.h>
@@ -65,16 +63,10 @@
#else
#include <asm/processor-flags.h>
#include <asm/arch_hooks.h>
-#include <asm/nmi.h>
-#include <asm/smp.h>
-#include <asm/io.h>
#include <asm/traps.h>
#include "cpu/mcheck/mce.h"
-DECLARE_BITMAP(used_vectors, NR_VECTORS);
-EXPORT_SYMBOL_GPL(used_vectors);
-
asmlinkage int system_call(void);
/* Do we ignore FPU interrupts ? */
@@ -89,6 +81,9 @@ gate_desc idt_table[256]
__attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };
#endif
+DECLARE_BITMAP(used_vectors, NR_VECTORS);
+EXPORT_SYMBOL_GPL(used_vectors);
+
static int ignore_nmis;
static inline void conditional_sti(struct pt_regs *regs)
@@ -292,8 +287,10 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
tsk->thread.error_code = error_code;
tsk->thread.trap_no = 8;
- /* This is always a kernel trap and never fixable (and thus must
- never return). */
+ /*
+ * This is always a kernel trap and never fixable (and thus must
+ * never return).
+ */
for (;;)
die(str, regs, error_code);
}
@@ -520,9 +517,11 @@ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
}
#ifdef CONFIG_X86_64
-/* Help handler running on IST stack to switch back to user stack
- for scheduling or signal handling. The actual stack switch is done in
- entry.S */
+/*
+ * Help handler running on IST stack to switch back to user stack
+ * for scheduling or signal handling. The actual stack switch is done in
+ * entry.S
+ */
asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
{
struct pt_regs *regs = eregs;
@@ -532,8 +531,10 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
/* Exception from user space */
else if (user_mode(eregs))
regs = task_pt_regs(current);
- /* Exception from kernel and interrupts are enabled. Move to
- kernel process stack. */
+ /*
+ * Exception from kernel and interrupts are enabled. Move to
+ * kernel process stack.
+ */
else if (eregs->flags & X86_EFLAGS_IF)
regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
if (eregs != regs)
@@ -685,12 +686,7 @@ void math_error(void __user *ip)
cwd = get_fpu_cwd(task);
swd = get_fpu_swd(task);
- err = swd & ~cwd & 0x3f;
-
-#ifdef CONFIG_X86_32
- if (!err)
- return;
-#endif
+ err = swd & ~cwd;
if (err & 0x001) { /* Invalid op */
/*
@@ -708,7 +704,11 @@ void math_error(void __user *ip)
} else if (err & 0x020) { /* Precision */
info.si_code = FPE_FLTRES;
} else {
- info.si_code = __SI_FAULT|SI_KERNEL; /* WTF? */
+ /*
+ * If we're using IRQ 13, or supposedly even some trap 16
+ * implementations, it's possible we get a spurious trap...
+ */
+ return; /* Spurious trap, no error */
}
force_sig_info(SIGFPE, &info, task);
}
@@ -941,9 +941,7 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
void __init trap_init(void)
{
-#ifdef CONFIG_X86_32
int i;
-#endif
#ifdef CONFIG_EISA
void __iomem *p = early_ioremap(0x0FFFD9, 4);
@@ -1000,11 +998,15 @@ void __init trap_init(void)
}
set_system_trap_gate(SYSCALL_VECTOR, &system_call);
+#endif
/* Reserve all the builtin and the syscall vector: */
for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
set_bit(i, used_vectors);
+#ifdef CONFIG_X86_64
+ set_bit(IA32_SYSCALL_VECTOR, used_vectors);
+#else
set_bit(SYSCALL_VECTOR, used_vectors);
#endif
/*
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index 0c9667f0752a..d801d06af068 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -176,33 +176,31 @@ static int __init visws_get_smp_config(unsigned int early)
* No problem for Linux.
*/
-static void __init MP_processor_info(struct mpc_config_processor *m)
+static void __init MP_processor_info(struct mpc_cpu *m)
{
int ver, logical_apicid;
physid_mask_t apic_cpus;
- if (!(m->mpc_cpuflag & CPU_ENABLED))
+ if (!(m->cpuflag & CPU_ENABLED))
return;
- logical_apicid = m->mpc_apicid;
+ logical_apicid = m->apicid;
printk(KERN_INFO "%sCPU #%d %u:%u APIC version %d\n",
- m->mpc_cpuflag & CPU_BOOTPROCESSOR ? "Bootup " : "",
- m->mpc_apicid,
- (m->mpc_cpufeature & CPU_FAMILY_MASK) >> 8,
- (m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
- m->mpc_apicver);
+ m->cpuflag & CPU_BOOTPROCESSOR ? "Bootup " : "",
+ m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8,
+ (m->cpufeature & CPU_MODEL_MASK) >> 4, m->apicver);
- if (m->mpc_cpuflag & CPU_BOOTPROCESSOR)
- boot_cpu_physical_apicid = m->mpc_apicid;
+ if (m->cpuflag & CPU_BOOTPROCESSOR)
+ boot_cpu_physical_apicid = m->apicid;
- ver = m->mpc_apicver;
- if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) {
+ ver = m->apicver;
+ if ((ver >= 0x14 && m->apicid >= 0xff) || m->apicid >= 0xf) {
printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
- m->mpc_apicid, MAX_APICS);
+ m->apicid, MAX_APICS);
return;
}
- apic_cpus = apicid_to_cpu_present(m->mpc_apicid);
+ apic_cpus = apicid_to_cpu_present(m->apicid);
physids_or(phys_cpu_present_map, phys_cpu_present_map, apic_cpus);
/*
* Validate version
@@ -210,15 +208,15 @@ static void __init MP_processor_info(struct mpc_config_processor *m)
if (ver == 0x0) {
printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! "
"fixing up to 0x10. (tell your hw vendor)\n",
- m->mpc_apicid);
+ m->apicid);
ver = 0x10;
}
- apic_version[m->mpc_apicid] = ver;
+ apic_version[m->apicid] = ver;
}
static int __init visws_find_smp_config(unsigned int reserve)
{
- struct mpc_config_processor *mp = phys_to_virt(CO_CPU_TAB_PHYS);
+ struct mpc_cpu *mp = phys_to_virt(CO_CPU_TAB_PHYS);
unsigned short ncpus = readw(phys_to_virt(CO_CPU_NUM_PHYS));
if (ncpus > CO_CPU_MAX) {
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 23206ba16874..1d3302cc2ddf 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -858,7 +858,7 @@ void __init vmi_init(void)
#endif
}
-void vmi_activate(void)
+void __init vmi_activate(void)
{
unsigned long flags;
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
index 254ee07f8635..c4c1f9e09402 100644
--- a/arch/x86/kernel/vmiclock_32.c
+++ b/arch/x86/kernel/vmiclock_32.c
@@ -226,7 +226,7 @@ static void __devinit vmi_time_init_clockevent(void)
/* Upper bound is clockevent's use of ulong for cycle deltas. */
evt->max_delta_ns = clockevent_delta2ns(ULONG_MAX, evt);
evt->min_delta_ns = clockevent_delta2ns(1, evt);
- evt->cpumask = cpumask_of_cpu(cpu);
+ evt->cpumask = cpumask_of(cpu);
printk(KERN_WARNING "vmi: registering clock event %s. mult=%lu shift=%u\n",
evt->name, evt->mult, evt->shift);
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 15c3e6999182..2b54fe002e94 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -159,7 +159,7 @@ int save_i387_xstate(void __user *buf)
* Restore the extended state if present. Otherwise, restore the FP/SSE
* state.
*/
-int restore_user_xstate(void __user *buf)
+static int restore_user_xstate(void __user *buf)
{
struct _fpx_sw_bytes fx_sw_user;
u64 mask;
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index c02343594b4d..d3ec292f00f2 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -7,8 +7,8 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
ifeq ($(CONFIG_KVM_TRACE),y)
common-objs += $(addprefix ../../../virt/kvm/, kvm_trace.o)
endif
-ifeq ($(CONFIG_DMAR),y)
-common-objs += $(addprefix ../../../virt/kvm/, vtd.o)
+ifeq ($(CONFIG_IOMMU_API),y)
+common-objs += $(addprefix ../../../virt/kvm/, iommu.o)
endif
EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index 59ebd37ad79e..e665d1c623ca 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -603,10 +603,29 @@ void kvm_free_pit(struct kvm *kvm)
static void __inject_pit_timer_intr(struct kvm *kvm)
{
+ struct kvm_vcpu *vcpu;
+ int i;
+
mutex_lock(&kvm->lock);
kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 1);
kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 0);
mutex_unlock(&kvm->lock);
+
+ /*
+ * Provides NMI watchdog support via Virtual Wire mode.
+ * The route is: PIT -> PIC -> LVT0 in NMI mode.
+ *
+ * Note: Our Virtual Wire implementation is simplified, only
+ * propagating PIT interrupts to all VCPUs when they have set
+ * LVT0 to NMI delivery. Other PIC interrupts are just sent to
+ * VCPU0, and only if its LVT0 is in EXTINT mode.
+ */
+ if (kvm->arch.vapics_in_nmi_mode > 0)
+ for (i = 0; i < KVM_MAX_VCPUS; ++i) {
+ vcpu = kvm->vcpus[i];
+ if (vcpu)
+ kvm_apic_nmi_wd_deliver(vcpu);
+ }
}
void kvm_inject_pit_timer_irqs(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 17e41e165f1a..179dcb0103fd 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -26,10 +26,40 @@
* Port from Qemu.
*/
#include <linux/mm.h>
+#include <linux/bitops.h>
#include "irq.h"
#include <linux/kvm_host.h>
+static void pic_lock(struct kvm_pic *s)
+{
+ spin_lock(&s->lock);
+}
+
+static void pic_unlock(struct kvm_pic *s)
+{
+ struct kvm *kvm = s->kvm;
+ unsigned acks = s->pending_acks;
+ bool wakeup = s->wakeup_needed;
+ struct kvm_vcpu *vcpu;
+
+ s->pending_acks = 0;
+ s->wakeup_needed = false;
+
+ spin_unlock(&s->lock);
+
+ while (acks) {
+ kvm_notify_acked_irq(kvm, __ffs(acks));
+ acks &= acks - 1;
+ }
+
+ if (wakeup) {
+ vcpu = s->kvm->vcpus[0];
+ if (vcpu)
+ kvm_vcpu_kick(vcpu);
+ }
+}
+
static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
{
s->isr &= ~(1 << irq);
@@ -136,17 +166,21 @@ static void pic_update_irq(struct kvm_pic *s)
void kvm_pic_update_irq(struct kvm_pic *s)
{
+ pic_lock(s);
pic_update_irq(s);
+ pic_unlock(s);
}
void kvm_pic_set_irq(void *opaque, int irq, int level)
{
struct kvm_pic *s = opaque;
+ pic_lock(s);
if (irq >= 0 && irq < PIC_NUM_PINS) {
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
pic_update_irq(s);
}
+ pic_unlock(s);
}
/*
@@ -172,6 +206,7 @@ int kvm_pic_read_irq(struct kvm *kvm)
int irq, irq2, intno;
struct kvm_pic *s = pic_irqchip(kvm);
+ pic_lock(s);
irq = pic_get_irq(&s->pics[0]);
if (irq >= 0) {
pic_intack(&s->pics[0], irq);
@@ -196,6 +231,7 @@ int kvm_pic_read_irq(struct kvm *kvm)
intno = s->pics[0].irq_base + irq;
}
pic_update_irq(s);
+ pic_unlock(s);
kvm_notify_acked_irq(kvm, irq);
return intno;
@@ -203,7 +239,7 @@ int kvm_pic_read_irq(struct kvm *kvm)
void kvm_pic_reset(struct kvm_kpic_state *s)
{
- int irq, irqbase;
+ int irq, irqbase, n;
struct kvm *kvm = s->pics_state->irq_request_opaque;
struct kvm_vcpu *vcpu0 = kvm->vcpus[0];
@@ -214,8 +250,10 @@ void kvm_pic_reset(struct kvm_kpic_state *s)
for (irq = 0; irq < PIC_NUM_PINS/2; irq++) {
if (vcpu0 && kvm_apic_accept_pic_intr(vcpu0))
- if (s->irr & (1 << irq) || s->isr & (1 << irq))
- kvm_notify_acked_irq(kvm, irq+irqbase);
+ if (s->irr & (1 << irq) || s->isr & (1 << irq)) {
+ n = irq + irqbase;
+ s->pics_state->pending_acks |= 1 << n;
+ }
}
s->last_irr = 0;
s->irr = 0;
@@ -406,6 +444,7 @@ static void picdev_write(struct kvm_io_device *this,
printk(KERN_ERR "PIC: non byte write\n");
return;
}
+ pic_lock(s);
switch (addr) {
case 0x20:
case 0x21:
@@ -418,6 +457,7 @@ static void picdev_write(struct kvm_io_device *this,
elcr_ioport_write(&s->pics[addr & 1], addr, data);
break;
}
+ pic_unlock(s);
}
static void picdev_read(struct kvm_io_device *this,
@@ -431,6 +471,7 @@ static void picdev_read(struct kvm_io_device *this,
printk(KERN_ERR "PIC: non byte read\n");
return;
}
+ pic_lock(s);
switch (addr) {
case 0x20:
case 0x21:
@@ -444,6 +485,7 @@ static void picdev_read(struct kvm_io_device *this,
break;
}
*(unsigned char *)val = data;
+ pic_unlock(s);
}
/*
@@ -459,7 +501,7 @@ static void pic_irq_request(void *opaque, int level)
s->output = level;
if (vcpu && level && (s->pics[0].isr_ack & (1 << irq))) {
s->pics[0].isr_ack &= ~(1 << irq);
- kvm_vcpu_kick(vcpu);
+ s->wakeup_needed = true;
}
}
@@ -469,6 +511,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
s = kzalloc(sizeof(struct kvm_pic), GFP_KERNEL);
if (!s)
return NULL;
+ spin_lock_init(&s->lock);
+ s->kvm = kvm;
s->pics[0].elcr_mask = 0xf8;
s->pics[1].elcr_mask = 0xde;
s->irq_request = pic_irq_request;
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index f17c8f5bbf31..2bf32a03ceec 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -25,6 +25,7 @@
#include <linux/mm_types.h>
#include <linux/hrtimer.h>
#include <linux/kvm_host.h>
+#include <linux/spinlock.h>
#include "iodev.h"
#include "ioapic.h"
@@ -59,6 +60,10 @@ struct kvm_kpic_state {
};
struct kvm_pic {
+ spinlock_t lock;
+ bool wakeup_needed;
+ unsigned pending_acks;
+ struct kvm *kvm;
struct kvm_kpic_state pics[2]; /* 0 is master pic, 1 is slave pic */
irq_request_func *irq_request;
void *irq_request_opaque;
@@ -87,6 +92,7 @@ void kvm_pic_reset(struct kvm_kpic_state *s);
void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
+void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu);
void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu);
void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu);
void __kvm_migrate_timers(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/kvm_svm.h b/arch/x86/kvm/kvm_svm.h
index 65ef0fc2c036..8e5ee99551f6 100644
--- a/arch/x86/kvm/kvm_svm.h
+++ b/arch/x86/kvm/kvm_svm.h
@@ -7,7 +7,7 @@
#include <linux/kvm_host.h>
#include <asm/msr.h>
-#include "svm.h"
+#include <asm/svm.h>
static const u32 host_save_user_msrs[] = {
#ifdef CONFIG_X86_64
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 0fc3cab48943..afac68c0815c 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -130,6 +130,11 @@ static inline int apic_lvtt_period(struct kvm_lapic *apic)
return apic_get_reg(apic, APIC_LVTT) & APIC_LVT_TIMER_PERIODIC;
}
+static inline int apic_lvt_nmi_mode(u32 lvt_val)
+{
+ return (lvt_val & (APIC_MODE_MASK | APIC_LVT_MASKED)) == APIC_DM_NMI;
+}
+
static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
LVT_MASK | APIC_LVT_TIMER_PERIODIC, /* LVTT */
LVT_MASK | APIC_MODE_MASK, /* LVTTHMR */
@@ -354,6 +359,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
case APIC_DM_NMI:
kvm_inject_nmi(vcpu);
+ kvm_vcpu_kick(vcpu);
break;
case APIC_DM_INIT:
@@ -380,6 +386,14 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
}
break;
+ case APIC_DM_EXTINT:
+ /*
+ * Should only be called by kvm_apic_local_deliver() with LVT0,
+ * before NMI watchdog was enabled. Already handled by
+ * kvm_apic_accept_pic_intr().
+ */
+ break;
+
default:
printk(KERN_ERR "TODO: unsupported delivery mode %x\n",
delivery_mode);
@@ -663,6 +677,20 @@ static void start_apic_timer(struct kvm_lapic *apic)
apic->timer.period)));
}
+static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
+{
+ int nmi_wd_enabled = apic_lvt_nmi_mode(apic_get_reg(apic, APIC_LVT0));
+
+ if (apic_lvt_nmi_mode(lvt0_val)) {
+ if (!nmi_wd_enabled) {
+ apic_debug("Receive NMI setting on APIC_LVT0 "
+ "for cpu %d\n", apic->vcpu->vcpu_id);
+ apic->vcpu->kvm->arch.vapics_in_nmi_mode++;
+ }
+ } else if (nmi_wd_enabled)
+ apic->vcpu->kvm->arch.vapics_in_nmi_mode--;
+}
+
static void apic_mmio_write(struct kvm_io_device *this,
gpa_t address, int len, const void *data)
{
@@ -743,10 +771,11 @@ static void apic_mmio_write(struct kvm_io_device *this,
apic_set_reg(apic, APIC_ICR2, val & 0xff000000);
break;
+ case APIC_LVT0:
+ apic_manage_nmi_watchdog(apic, val);
case APIC_LVTT:
case APIC_LVTTHMR:
case APIC_LVTPC:
- case APIC_LVT0:
case APIC_LVT1:
case APIC_LVTERR:
/* TODO: Check vector */
@@ -961,12 +990,26 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu)
return 0;
}
-static int __inject_apic_timer_irq(struct kvm_lapic *apic)
+static int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
+{
+ u32 reg = apic_get_reg(apic, lvt_type);
+ int vector, mode, trig_mode;
+
+ if (apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) {
+ vector = reg & APIC_VECTOR_MASK;
+ mode = reg & APIC_MODE_MASK;
+ trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
+ return __apic_accept_irq(apic, mode, vector, 1, trig_mode);
+ }
+ return 0;
+}
+
+void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu)
{
- int vector;
+ struct kvm_lapic *apic = vcpu->arch.apic;
- vector = apic_lvt_vector(apic, APIC_LVTT);
- return __apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0);
+ if (apic)
+ kvm_apic_local_deliver(apic, APIC_LVT0);
}
static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
@@ -1061,9 +1104,8 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
{
struct kvm_lapic *apic = vcpu->arch.apic;
- if (apic && apic_lvt_enabled(apic, APIC_LVTT) &&
- atomic_read(&apic->timer.pending) > 0) {
- if (__inject_apic_timer_irq(apic))
+ if (apic && atomic_read(&apic->timer.pending) > 0) {
+ if (kvm_apic_local_deliver(apic, APIC_LVTT))
atomic_dec(&apic->timer.pending);
}
}
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 410ddbc1aa2e..83f11c7474a1 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -17,7 +17,6 @@
*
*/
-#include "vmx.h"
#include "mmu.h"
#include <linux/kvm_host.h>
@@ -33,6 +32,7 @@
#include <asm/page.h>
#include <asm/cmpxchg.h>
#include <asm/io.h>
+#include <asm/vmx.h>
/*
* When setting this variable to true it enables Two-Dimensional-Paging
@@ -168,6 +168,7 @@ static u64 __read_mostly shadow_x_mask; /* mutual exclusive with nx_mask */
static u64 __read_mostly shadow_user_mask;
static u64 __read_mostly shadow_accessed_mask;
static u64 __read_mostly shadow_dirty_mask;
+static u64 __read_mostly shadow_mt_mask;
void kvm_mmu_set_nonpresent_ptes(u64 trap_pte, u64 notrap_pte)
{
@@ -183,13 +184,14 @@ void kvm_mmu_set_base_ptes(u64 base_pte)
EXPORT_SYMBOL_GPL(kvm_mmu_set_base_ptes);
void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
- u64 dirty_mask, u64 nx_mask, u64 x_mask)
+ u64 dirty_mask, u64 nx_mask, u64 x_mask, u64 mt_mask)
{
shadow_user_mask = user_mask;
shadow_accessed_mask = accessed_mask;
shadow_dirty_mask = dirty_mask;
shadow_nx_mask = nx_mask;
shadow_x_mask = x_mask;
+ shadow_mt_mask = mt_mask;
}
EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes);
@@ -384,7 +386,9 @@ static void account_shadowed(struct kvm *kvm, gfn_t gfn)
{
int *write_count;
- write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
+ gfn = unalias_gfn(kvm, gfn);
+ write_count = slot_largepage_idx(gfn,
+ gfn_to_memslot_unaliased(kvm, gfn));
*write_count += 1;
}
@@ -392,16 +396,20 @@ static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
{
int *write_count;
- write_count = slot_largepage_idx(gfn, gfn_to_memslot(kvm, gfn));
+ gfn = unalias_gfn(kvm, gfn);
+ write_count = slot_largepage_idx(gfn,
+ gfn_to_memslot_unaliased(kvm, gfn));
*write_count -= 1;
WARN_ON(*write_count < 0);
}
static int has_wrprotected_page(struct kvm *kvm, gfn_t gfn)
{
- struct kvm_memory_slot *slot = gfn_to_memslot(kvm, gfn);
+ struct kvm_memory_slot *slot;
int *largepage_idx;
+ gfn = unalias_gfn(kvm, gfn);
+ slot = gfn_to_memslot_unaliased(kvm, gfn);
if (slot) {
largepage_idx = slot_largepage_idx(gfn, slot);
return *largepage_idx;
@@ -613,7 +621,7 @@ static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte)
return NULL;
}
-static void rmap_write_protect(struct kvm *kvm, u64 gfn)
+static int rmap_write_protect(struct kvm *kvm, u64 gfn)
{
unsigned long *rmapp;
u64 *spte;
@@ -659,8 +667,7 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
spte = rmap_next(kvm, rmapp, spte);
}
- if (write_protected)
- kvm_flush_remote_tlbs(kvm);
+ return write_protected;
}
static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp)
@@ -786,9 +793,11 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu,
sp->gfns = mmu_memory_cache_alloc(&vcpu->arch.mmu_page_cache, PAGE_SIZE);
set_page_private(virt_to_page(sp->spt), (unsigned long)sp);
list_add(&sp->link, &vcpu->kvm->arch.active_mmu_pages);
+ INIT_LIST_HEAD(&sp->oos_link);
ASSERT(is_empty_shadow_page(sp->spt));
- sp->slot_bitmap = 0;
+ bitmap_zero(sp->slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
sp->multimapped = 0;
+ sp->global = 1;
sp->parent_pte = parent_pte;
--vcpu->kvm->arch.n_free_mmu_pages;
return sp;
@@ -900,8 +909,9 @@ static void kvm_mmu_update_unsync_bitmap(u64 *spte)
struct kvm_mmu_page *sp = page_header(__pa(spte));
index = spte - sp->spt;
- __set_bit(index, sp->unsync_child_bitmap);
- sp->unsync_children = 1;
+ if (!__test_and_set_bit(index, sp->unsync_child_bitmap))
+ sp->unsync_children++;
+ WARN_ON(!sp->unsync_children);
}
static void kvm_mmu_update_parents_unsync(struct kvm_mmu_page *sp)
@@ -928,7 +938,6 @@ static void kvm_mmu_update_parents_unsync(struct kvm_mmu_page *sp)
static int unsync_walk_fn(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
{
- sp->unsync_children = 1;
kvm_mmu_update_parents_unsync(sp);
return 1;
}
@@ -959,38 +968,66 @@ static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
{
}
+#define KVM_PAGE_ARRAY_NR 16
+
+struct kvm_mmu_pages {
+ struct mmu_page_and_offset {
+ struct kvm_mmu_page *sp;
+ unsigned int idx;
+ } page[KVM_PAGE_ARRAY_NR];
+ unsigned int nr;
+};
+
#define for_each_unsync_children(bitmap, idx) \
for (idx = find_first_bit(bitmap, 512); \
idx < 512; \
idx = find_next_bit(bitmap, 512, idx+1))
-static int mmu_unsync_walk(struct kvm_mmu_page *sp,
- struct kvm_unsync_walk *walker)
+int mmu_pages_add(struct kvm_mmu_pages *pvec, struct kvm_mmu_page *sp,
+ int idx)
{
- int i, ret;
+ int i;
- if (!sp->unsync_children)
- return 0;
+ if (sp->unsync)
+ for (i=0; i < pvec->nr; i++)
+ if (pvec->page[i].sp == sp)
+ return 0;
+
+ pvec->page[pvec->nr].sp = sp;
+ pvec->page[pvec->nr].idx = idx;
+ pvec->nr++;
+ return (pvec->nr == KVM_PAGE_ARRAY_NR);
+}
+
+static int __mmu_unsync_walk(struct kvm_mmu_page *sp,
+ struct kvm_mmu_pages *pvec)
+{
+ int i, ret, nr_unsync_leaf = 0;
for_each_unsync_children(sp->unsync_child_bitmap, i) {
u64 ent = sp->spt[i];
- if (is_shadow_present_pte(ent)) {
+ if (is_shadow_present_pte(ent) && !is_large_pte(ent)) {
struct kvm_mmu_page *child;
child = page_header(ent & PT64_BASE_ADDR_MASK);
if (child->unsync_children) {
- ret = mmu_unsync_walk(child, walker);
- if (ret)
+ if (mmu_pages_add(pvec, child, i))
+ return -ENOSPC;
+
+ ret = __mmu_unsync_walk(child, pvec);
+ if (!ret)
+ __clear_bit(i, sp->unsync_child_bitmap);
+ else if (ret > 0)
+ nr_unsync_leaf += ret;
+ else
return ret;
- __clear_bit(i, sp->unsync_child_bitmap);
}
if (child->unsync) {
- ret = walker->entry(child, walker);
- __clear_bit(i, sp->unsync_child_bitmap);
- if (ret)
- return ret;
+ nr_unsync_leaf++;
+ if (mmu_pages_add(pvec, child, i))
+ return -ENOSPC;
}
}
}
@@ -998,7 +1035,17 @@ static int mmu_unsync_walk(struct kvm_mmu_page *sp,
if (find_first_bit(sp->unsync_child_bitmap, 512) == 512)
sp->unsync_children = 0;
- return 0;
+ return nr_unsync_leaf;
+}
+
+static int mmu_unsync_walk(struct kvm_mmu_page *sp,
+ struct kvm_mmu_pages *pvec)
+{
+ if (!sp->unsync_children)
+ return 0;
+
+ mmu_pages_add(pvec, sp, 0);
+ return __mmu_unsync_walk(sp, pvec);
}
static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
@@ -1021,10 +1068,18 @@ static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
return NULL;
}
+static void kvm_unlink_unsync_global(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+ list_del(&sp->oos_link);
+ --kvm->stat.mmu_unsync_global;
+}
+
static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp)
{
WARN_ON(!sp->unsync);
sp->unsync = 0;
+ if (sp->global)
+ kvm_unlink_unsync_global(kvm, sp);
--kvm->stat.mmu_unsync;
}
@@ -1037,7 +1092,8 @@ static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
return 1;
}
- rmap_write_protect(vcpu->kvm, sp->gfn);
+ if (rmap_write_protect(vcpu->kvm, sp->gfn))
+ kvm_flush_remote_tlbs(vcpu->kvm);
kvm_unlink_unsync_page(vcpu->kvm, sp);
if (vcpu->arch.mmu.sync_page(vcpu, sp)) {
kvm_mmu_zap_page(vcpu->kvm, sp);
@@ -1048,30 +1104,89 @@ static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
return 0;
}
-struct sync_walker {
- struct kvm_vcpu *vcpu;
- struct kvm_unsync_walk walker;
+struct mmu_page_path {
+ struct kvm_mmu_page *parent[PT64_ROOT_LEVEL-1];
+ unsigned int idx[PT64_ROOT_LEVEL-1];
};
-static int mmu_sync_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk)
+#define for_each_sp(pvec, sp, parents, i) \
+ for (i = mmu_pages_next(&pvec, &parents, -1), \
+ sp = pvec.page[i].sp; \
+ i < pvec.nr && ({ sp = pvec.page[i].sp; 1;}); \
+ i = mmu_pages_next(&pvec, &parents, i))
+
+int mmu_pages_next(struct kvm_mmu_pages *pvec, struct mmu_page_path *parents,
+ int i)
{
- struct sync_walker *sync_walk = container_of(walk, struct sync_walker,
- walker);
- struct kvm_vcpu *vcpu = sync_walk->vcpu;
+ int n;
- kvm_sync_page(vcpu, sp);
- return (need_resched() || spin_needbreak(&vcpu->kvm->mmu_lock));
+ for (n = i+1; n < pvec->nr; n++) {
+ struct kvm_mmu_page *sp = pvec->page[n].sp;
+
+ if (sp->role.level == PT_PAGE_TABLE_LEVEL) {
+ parents->idx[0] = pvec->page[n].idx;
+ return n;
+ }
+
+ parents->parent[sp->role.level-2] = sp;
+ parents->idx[sp->role.level-1] = pvec->page[n].idx;
+ }
+
+ return n;
}
-static void mmu_sync_children(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
+void mmu_pages_clear_parents(struct mmu_page_path *parents)
{
- struct sync_walker walker = {
- .walker = { .entry = mmu_sync_fn, },
- .vcpu = vcpu,
- };
+ struct kvm_mmu_page *sp;
+ unsigned int level = 0;
+
+ do {
+ unsigned int idx = parents->idx[level];
+
+ sp = parents->parent[level];
+ if (!sp)
+ return;
+
+ --sp->unsync_children;
+ WARN_ON((int)sp->unsync_children < 0);
+ __clear_bit(idx, sp->unsync_child_bitmap);
+ level++;
+ } while (level < PT64_ROOT_LEVEL-1 && !sp->unsync_children);
+}
+
+static void kvm_mmu_pages_init(struct kvm_mmu_page *parent,
+ struct mmu_page_path *parents,
+ struct kvm_mmu_pages *pvec)
+{
+ parents->parent[parent->role.level-1] = NULL;
+ pvec->nr = 0;
+}
+
+static void mmu_sync_children(struct kvm_vcpu *vcpu,
+ struct kvm_mmu_page *parent)
+{
+ int i;
+ struct kvm_mmu_page *sp;
+ struct mmu_page_path parents;
+ struct kvm_mmu_pages pages;
+
+ kvm_mmu_pages_init(parent, &parents, &pages);
+ while (mmu_unsync_walk(parent, &pages)) {
+ int protected = 0;
- while (mmu_unsync_walk(sp, &walker.walker))
+ for_each_sp(pages, sp, parents, i)
+ protected |= rmap_write_protect(vcpu->kvm, sp->gfn);
+
+ if (protected)
+ kvm_flush_remote_tlbs(vcpu->kvm);
+
+ for_each_sp(pages, sp, parents, i) {
+ kvm_sync_page(vcpu, sp);
+ mmu_pages_clear_parents(&parents);
+ }
cond_resched_lock(&vcpu->kvm->mmu_lock);
+ kvm_mmu_pages_init(parent, &parents, &pages);
+ }
}
static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
@@ -1129,7 +1244,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
sp->role = role;
hlist_add_head(&sp->hash_link, bucket);
if (!metaphysical) {
- rmap_write_protect(vcpu->kvm, gfn);
+ if (rmap_write_protect(vcpu->kvm, gfn))
+ kvm_flush_remote_tlbs(vcpu->kvm);
account_shadowed(vcpu->kvm, gfn);
}
if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte)
@@ -1153,6 +1269,8 @@ static int walk_shadow(struct kvm_shadow_walk *walker,
if (level == PT32E_ROOT_LEVEL) {
shadow_addr = vcpu->arch.mmu.pae_root[(addr >> 30) & 3];
shadow_addr &= PT64_BASE_ADDR_MASK;
+ if (!shadow_addr)
+ return 1;
--level;
}
@@ -1237,33 +1355,29 @@ static void kvm_mmu_unlink_parents(struct kvm *kvm, struct kvm_mmu_page *sp)
}
}
-struct zap_walker {
- struct kvm_unsync_walk walker;
- struct kvm *kvm;
- int zapped;
-};
-
-static int mmu_zap_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk)
+static int mmu_zap_unsync_children(struct kvm *kvm,
+ struct kvm_mmu_page *parent)
{
- struct zap_walker *zap_walk = container_of(walk, struct zap_walker,
- walker);
- kvm_mmu_zap_page(zap_walk->kvm, sp);
- zap_walk->zapped = 1;
- return 0;
-}
+ int i, zapped = 0;
+ struct mmu_page_path parents;
+ struct kvm_mmu_pages pages;
-static int mmu_zap_unsync_children(struct kvm *kvm, struct kvm_mmu_page *sp)
-{
- struct zap_walker walker = {
- .walker = { .entry = mmu_zap_fn, },
- .kvm = kvm,
- .zapped = 0,
- };
-
- if (sp->role.level == PT_PAGE_TABLE_LEVEL)
+ if (parent->role.level == PT_PAGE_TABLE_LEVEL)
return 0;
- mmu_unsync_walk(sp, &walker.walker);
- return walker.zapped;
+
+ kvm_mmu_pages_init(parent, &parents, &pages);
+ while (mmu_unsync_walk(parent, &pages)) {
+ struct kvm_mmu_page *sp;
+
+ for_each_sp(pages, sp, parents, i) {
+ kvm_mmu_zap_page(kvm, sp);
+ mmu_pages_clear_parents(&parents);
+ }
+ zapped += pages.nr;
+ kvm_mmu_pages_init(parent, &parents, &pages);
+ }
+
+ return zapped;
}
static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
@@ -1362,7 +1476,7 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
int slot = memslot_id(kvm, gfn_to_memslot(kvm, gfn));
struct kvm_mmu_page *sp = page_header(__pa(pte));
- __set_bit(slot, &sp->slot_bitmap);
+ __set_bit(slot, sp->slot_bitmap);
}
static void mmu_convert_notrap(struct kvm_mmu_page *sp)
@@ -1393,6 +1507,110 @@ struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
return page;
}
+/*
+ * The function is based on mtrr_type_lookup() in
+ * arch/x86/kernel/cpu/mtrr/generic.c
+ */
+static int get_mtrr_type(struct mtrr_state_type *mtrr_state,
+ u64 start, u64 end)
+{
+ int i;
+ u64 base, mask;
+ u8 prev_match, curr_match;
+ int num_var_ranges = KVM_NR_VAR_MTRR;
+
+ if (!mtrr_state->enabled)
+ return 0xFF;
+
+ /* Make end inclusive end, instead of exclusive */
+ end--;
+
+ /* Look in fixed ranges. Just return the type as per start */
+ if (mtrr_state->have_fixed && (start < 0x100000)) {
+ int idx;
+
+ if (start < 0x80000) {
+ idx = 0;
+ idx += (start >> 16);
+ return mtrr_state->fixed_ranges[idx];
+ } else if (start < 0xC0000) {
+ idx = 1 * 8;
+ idx += ((start - 0x80000) >> 14);
+ return mtrr_state->fixed_ranges[idx];
+ } else if (start < 0x1000000) {
+ idx = 3 * 8;
+ idx += ((start - 0xC0000) >> 12);
+ return mtrr_state->fixed_ranges[idx];
+ }
+ }
+
+ /*
+ * Look in variable ranges
+ * Look of multiple ranges matching this address and pick type
+ * as per MTRR precedence
+ */
+ if (!(mtrr_state->enabled & 2))
+ return mtrr_state->def_type;
+
+ prev_match = 0xFF;
+ for (i = 0; i < num_var_ranges; ++i) {
+ unsigned short start_state, end_state;
+
+ if (!(mtrr_state->var_ranges[i].mask_lo & (1 << 11)))
+ continue;
+
+ base = (((u64)mtrr_state->var_ranges[i].base_hi) << 32) +
+ (mtrr_state->var_ranges[i].base_lo & PAGE_MASK);
+ mask = (((u64)mtrr_state->var_ranges[i].mask_hi) << 32) +
+ (mtrr_state->var_ranges[i].mask_lo & PAGE_MASK);
+
+ start_state = ((start & mask) == (base & mask));
+ end_state = ((end & mask) == (base & mask));
+ if (start_state != end_state)
+ return 0xFE;
+
+ if ((start & mask) != (base & mask))
+ continue;
+
+ curr_match = mtrr_state->var_ranges[i].base_lo & 0xff;
+ if (prev_match == 0xFF) {
+ prev_match = curr_match;
+ continue;
+ }
+
+ if (prev_match == MTRR_TYPE_UNCACHABLE ||
+ curr_match == MTRR_TYPE_UNCACHABLE)
+ return MTRR_TYPE_UNCACHABLE;
+
+ if ((prev_match == MTRR_TYPE_WRBACK &&
+ curr_match == MTRR_TYPE_WRTHROUGH) ||
+ (prev_match == MTRR_TYPE_WRTHROUGH &&
+ curr_match == MTRR_TYPE_WRBACK)) {
+ prev_match = MTRR_TYPE_WRTHROUGH;
+ curr_match = MTRR_TYPE_WRTHROUGH;
+ }
+
+ if (prev_match != curr_match)
+ return MTRR_TYPE_UNCACHABLE;
+ }
+
+ if (prev_match != 0xFF)
+ return prev_match;
+
+ return mtrr_state->def_type;
+}
+
+static u8 get_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
+{
+ u8 mtrr;
+
+ mtrr = get_mtrr_type(&vcpu->arch.mtrr_state, gfn << PAGE_SHIFT,
+ (gfn << PAGE_SHIFT) + PAGE_SIZE);
+ if (mtrr == 0xfe || mtrr == 0xff)
+ mtrr = MTRR_TYPE_WRBACK;
+ return mtrr;
+}
+
static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
{
unsigned index;
@@ -1409,9 +1627,15 @@ static int kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
if (s->role.word != sp->role.word)
return 1;
}
- kvm_mmu_mark_parents_unsync(vcpu, sp);
++vcpu->kvm->stat.mmu_unsync;
sp->unsync = 1;
+
+ if (sp->global) {
+ list_add(&sp->oos_link, &vcpu->kvm->arch.oos_global_pages);
+ ++vcpu->kvm->stat.mmu_unsync_global;
+ } else
+ kvm_mmu_mark_parents_unsync(vcpu, sp);
+
mmu_convert_notrap(sp);
return 0;
}
@@ -1437,11 +1661,24 @@ static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,
static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
unsigned pte_access, int user_fault,
int write_fault, int dirty, int largepage,
- gfn_t gfn, pfn_t pfn, bool speculative,
+ int global, gfn_t gfn, pfn_t pfn, bool speculative,
bool can_unsync)
{
u64 spte;
int ret = 0;
+ u64 mt_mask = shadow_mt_mask;
+ struct kvm_mmu_page *sp = page_header(__pa(shadow_pte));
+
+ if (!(vcpu->arch.cr4 & X86_CR4_PGE))
+ global = 0;
+ if (!global && sp->global) {
+ sp->global = 0;
+ if (sp->unsync) {
+ kvm_unlink_unsync_global(vcpu->kvm, sp);
+ kvm_mmu_mark_parents_unsync(vcpu, sp);
+ }
+ }
+
/*
* We don't set the accessed bit, since we sometimes want to see
* whether the guest actually used the pte (in order to detect
@@ -1460,6 +1697,11 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
spte |= shadow_user_mask;
if (largepage)
spte |= PT_PAGE_SIZE_MASK;
+ if (mt_mask) {
+ mt_mask = get_memory_type(vcpu, gfn) <<
+ kvm_x86_ops->get_mt_mask_shift();
+ spte |= mt_mask;
+ }
spte |= (u64)pfn << PAGE_SHIFT;
@@ -1474,6 +1716,15 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
spte |= PT_WRITABLE_MASK;
+ /*
+ * Optimization: for pte sync, if spte was writable the hash
+ * lookup is unnecessary (and expensive). Write protection
+ * is responsibility of mmu_get_page / kvm_sync_page.
+ * Same reasoning can be applied to dirty page accounting.
+ */
+ if (!can_unsync && is_writeble_pte(*shadow_pte))
+ goto set_pte;
+
if (mmu_need_write_protect(vcpu, gfn, can_unsync)) {
pgprintk("%s: found shadow page for %lx, marking ro\n",
__func__, gfn);
@@ -1495,8 +1746,8 @@ set_pte:
static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
unsigned pt_access, unsigned pte_access,
int user_fault, int write_fault, int dirty,
- int *ptwrite, int largepage, gfn_t gfn,
- pfn_t pfn, bool speculative)
+ int *ptwrite, int largepage, int global,
+ gfn_t gfn, pfn_t pfn, bool speculative)
{
int was_rmapped = 0;
int was_writeble = is_writeble_pte(*shadow_pte);
@@ -1529,7 +1780,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
}
}
if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault,
- dirty, largepage, gfn, pfn, speculative, true)) {
+ dirty, largepage, global, gfn, pfn, speculative, true)) {
if (write_fault)
*ptwrite = 1;
kvm_x86_ops->tlb_flush(vcpu);
@@ -1586,7 +1837,7 @@ static int direct_map_entry(struct kvm_shadow_walk *_walk,
|| (walk->largepage && level == PT_DIRECTORY_LEVEL)) {
mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL,
0, walk->write, 1, &walk->pt_write,
- walk->largepage, gfn, walk->pfn, false);
+ walk->largepage, 0, gfn, walk->pfn, false);
++vcpu->stat.pf_fixed;
return 1;
}
@@ -1773,6 +2024,15 @@ static void mmu_sync_roots(struct kvm_vcpu *vcpu)
}
}
+static void mmu_sync_global(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_mmu_page *sp, *n;
+
+ list_for_each_entry_safe(sp, n, &kvm->arch.oos_global_pages, oos_link)
+ kvm_sync_page(vcpu, sp);
+}
+
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
{
spin_lock(&vcpu->kvm->mmu_lock);
@@ -1780,6 +2040,13 @@ void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
spin_unlock(&vcpu->kvm->mmu_lock);
}
+void kvm_mmu_sync_global(struct kvm_vcpu *vcpu)
+{
+ spin_lock(&vcpu->kvm->mmu_lock);
+ mmu_sync_global(vcpu);
+ spin_unlock(&vcpu->kvm->mmu_lock);
+}
+
static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
{
return vaddr;
@@ -2178,7 +2445,8 @@ static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn)
}
void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
- const u8 *new, int bytes)
+ const u8 *new, int bytes,
+ bool guest_initiated)
{
gfn_t gfn = gpa >> PAGE_SHIFT;
struct kvm_mmu_page *sp;
@@ -2204,15 +2472,17 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
kvm_mmu_free_some_pages(vcpu);
++vcpu->kvm->stat.mmu_pte_write;
kvm_mmu_audit(vcpu, "pre pte write");
- if (gfn == vcpu->arch.last_pt_write_gfn
- && !last_updated_pte_accessed(vcpu)) {
- ++vcpu->arch.last_pt_write_count;
- if (vcpu->arch.last_pt_write_count >= 3)
- flooded = 1;
- } else {
- vcpu->arch.last_pt_write_gfn = gfn;
- vcpu->arch.last_pt_write_count = 1;
- vcpu->arch.last_pte_updated = NULL;
+ if (guest_initiated) {
+ if (gfn == vcpu->arch.last_pt_write_gfn
+ && !last_updated_pte_accessed(vcpu)) {
+ ++vcpu->arch.last_pt_write_count;
+ if (vcpu->arch.last_pt_write_count >= 3)
+ flooded = 1;
+ } else {
+ vcpu->arch.last_pt_write_gfn = gfn;
+ vcpu->arch.last_pt_write_count = 1;
+ vcpu->arch.last_pte_updated = NULL;
+ }
}
index = kvm_page_table_hashfn(gfn);
bucket = &vcpu->kvm->arch.mmu_page_hash[index];
@@ -2352,9 +2622,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
{
- spin_lock(&vcpu->kvm->mmu_lock);
vcpu->arch.mmu.invlpg(vcpu, gva);
- spin_unlock(&vcpu->kvm->mmu_lock);
kvm_mmu_flush_tlb(vcpu);
++vcpu->stat.invlpg;
}
@@ -2451,7 +2719,7 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
int i;
u64 *pt;
- if (!test_bit(slot, &sp->slot_bitmap))
+ if (!test_bit(slot, sp->slot_bitmap))
continue;
pt = sp->spt;
@@ -2860,8 +3128,8 @@ static void audit_write_protection(struct kvm_vcpu *vcpu)
if (sp->role.metaphysical)
continue;
- slot = gfn_to_memslot(vcpu->kvm, sp->gfn);
gfn = unalias_gfn(vcpu->kvm, sp->gfn);
+ slot = gfn_to_memslot_unaliased(vcpu->kvm, sp->gfn);
rmapp = &slot->rmap[gfn - slot->base_gfn];
if (*rmapp)
printk(KERN_ERR "%s: (%s) shadow page has writable"
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 84eee43bbe74..9fd78b6e17ad 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -82,6 +82,7 @@ struct shadow_walker {
int *ptwrite;
pfn_t pfn;
u64 *sptep;
+ gpa_t pte_gpa;
};
static gfn_t gpte_to_gfn(pt_element_t gpte)
@@ -222,7 +223,7 @@ walk:
if (ret)
goto walk;
pte |= PT_DIRTY_MASK;
- kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&pte, sizeof(pte));
+ kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&pte, sizeof(pte), 0);
walker->ptes[walker->level - 1] = pte;
}
@@ -274,7 +275,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
return;
kvm_get_pfn(pfn);
mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
- gpte & PT_DIRTY_MASK, NULL, largepage, gpte_to_gfn(gpte),
+ gpte & PT_DIRTY_MASK, NULL, largepage,
+ gpte & PT_GLOBAL_MASK, gpte_to_gfn(gpte),
pfn, true);
}
@@ -301,8 +303,9 @@ static int FNAME(shadow_walk_entry)(struct kvm_shadow_walk *_sw,
mmu_set_spte(vcpu, sptep, access, gw->pte_access & access,
sw->user_fault, sw->write_fault,
gw->ptes[gw->level-1] & PT_DIRTY_MASK,
- sw->ptwrite, sw->largepage, gw->gfn, sw->pfn,
- false);
+ sw->ptwrite, sw->largepage,
+ gw->ptes[gw->level-1] & PT_GLOBAL_MASK,
+ gw->gfn, sw->pfn, false);
sw->sptep = sptep;
return 1;
}
@@ -466,10 +469,22 @@ static int FNAME(shadow_invlpg_entry)(struct kvm_shadow_walk *_sw,
struct kvm_vcpu *vcpu, u64 addr,
u64 *sptep, int level)
{
+ struct shadow_walker *sw =
+ container_of(_sw, struct shadow_walker, walker);
- if (level == PT_PAGE_TABLE_LEVEL) {
- if (is_shadow_present_pte(*sptep))
+ /* FIXME: properly handle invlpg on large guest pages */
+ if (level == PT_PAGE_TABLE_LEVEL ||
+ ((level == PT_DIRECTORY_LEVEL) && is_large_pte(*sptep))) {
+ struct kvm_mmu_page *sp = page_header(__pa(sptep));
+
+ sw->pte_gpa = (sp->gfn << PAGE_SHIFT);
+ sw->pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t);
+
+ if (is_shadow_present_pte(*sptep)) {
rmap_remove(vcpu->kvm, sptep);
+ if (is_large_pte(*sptep))
+ --vcpu->kvm->stat.lpages;
+ }
set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
return 1;
}
@@ -480,11 +495,26 @@ static int FNAME(shadow_invlpg_entry)(struct kvm_shadow_walk *_sw,
static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
{
+ pt_element_t gpte;
struct shadow_walker walker = {
.walker = { .entry = FNAME(shadow_invlpg_entry), },
+ .pte_gpa = -1,
};
+ spin_lock(&vcpu->kvm->mmu_lock);
walk_shadow(&walker.walker, vcpu, gva);
+ spin_unlock(&vcpu->kvm->mmu_lock);
+ if (walker.pte_gpa == -1)
+ return;
+ if (kvm_read_guest_atomic(vcpu->kvm, walker.pte_gpa, &gpte,
+ sizeof(pt_element_t)))
+ return;
+ if (is_present_pte(gpte) && (gpte & PT_ACCESSED_MASK)) {
+ if (mmu_topup_memory_caches(vcpu))
+ return;
+ kvm_mmu_pte_write(vcpu, walker.pte_gpa, (const u8 *)&gpte,
+ sizeof(pt_element_t), 0);
+ }
}
static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
@@ -580,7 +610,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
nr_present++;
pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
set_spte(vcpu, &sp->spt[i], pte_access, 0, 0,
- is_dirty_pte(gpte), 0, gfn,
+ is_dirty_pte(gpte), 0, gpte & PT_GLOBAL_MASK, gfn,
spte_to_pfn(sp->spt[i]), true, false);
}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 9c4ce657d963..1452851ae258 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -28,6 +28,8 @@
#include <asm/desc.h>
+#include <asm/virtext.h>
+
#define __ex(x) __kvm_handle_fault_on_reboot(x)
MODULE_AUTHOR("Qumranet");
@@ -245,34 +247,19 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
static int has_svm(void)
{
- uint32_t eax, ebx, ecx, edx;
-
- if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
- printk(KERN_INFO "has_svm: not amd\n");
- return 0;
- }
+ const char *msg;
- cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
- if (eax < SVM_CPUID_FUNC) {
- printk(KERN_INFO "has_svm: can't execute cpuid_8000000a\n");
+ if (!cpu_has_svm(&msg)) {
+ printk(KERN_INFO "has_svn: %s\n", msg);
return 0;
}
- cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
- if (!(ecx & (1 << SVM_CPUID_FEATURE_SHIFT))) {
- printk(KERN_DEBUG "has_svm: svm not available\n");
- return 0;
- }
return 1;
}
static void svm_hardware_disable(void *garbage)
{
- uint64_t efer;
-
- wrmsrl(MSR_VM_HSAVE_PA, 0);
- rdmsrl(MSR_EFER, efer);
- wrmsrl(MSR_EFER, efer & ~MSR_EFER_SVME_MASK);
+ cpu_svm_disable();
}
static void svm_hardware_enable(void *garbage)
@@ -772,6 +759,22 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1;
+
+ /*
+ * SVM always stores 0 for the 'G' bit in the CS selector in
+ * the VMCB on a VMEXIT. This hurts cross-vendor migration:
+ * Intel's VMENTRY has a check on the 'G' bit.
+ */
+ if (seg == VCPU_SREG_CS)
+ var->g = s->limit > 0xfffff;
+
+ /*
+ * Work around a bug where the busy flag in the tr selector
+ * isn't exposed
+ */
+ if (seg == VCPU_SREG_TR)
+ var->type |= 0x2;
+
var->unusable = !var->present;
}
@@ -1099,6 +1102,7 @@ static int io_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
rep = (io_info & SVM_IOIO_REP_MASK) != 0;
down = (svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0;
+ skip_emulated_instruction(&svm->vcpu);
return kvm_emulate_pio(&svm->vcpu, kvm_run, in, size, port);
}
@@ -1912,6 +1916,11 @@ static int get_npt_level(void)
#endif
}
+static int svm_get_mt_mask_shift(void)
+{
+ return 0;
+}
+
static struct kvm_x86_ops svm_x86_ops = {
.cpu_has_kvm_support = has_svm,
.disabled_by_bios = is_disabled,
@@ -1967,6 +1976,7 @@ static struct kvm_x86_ops svm_x86_ops = {
.set_tss_addr = svm_set_tss_addr,
.get_tdp_level = get_npt_level,
+ .get_mt_mask_shift = svm_get_mt_mask_shift,
};
static int __init svm_init(void)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index a4018b01e1f9..6259d7467648 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -16,7 +16,6 @@
*/
#include "irq.h"
-#include "vmx.h"
#include "mmu.h"
#include <linux/kvm_host.h>
@@ -31,6 +30,8 @@
#include <asm/io.h>
#include <asm/desc.h>
+#include <asm/vmx.h>
+#include <asm/virtext.h>
#define __ex(x) __kvm_handle_fault_on_reboot(x)
@@ -90,6 +91,11 @@ struct vcpu_vmx {
} rmode;
int vpid;
bool emulation_required;
+
+ /* Support for vnmi-less CPUs */
+ int soft_vnmi_blocked;
+ ktime_t entry_time;
+ s64 vnmi_blocked_time;
};
static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -122,7 +128,7 @@ static struct vmcs_config {
u32 vmentry_ctrl;
} vmcs_config;
-struct vmx_capability {
+static struct vmx_capability {
u32 ept;
u32 vpid;
} vmx_capability;
@@ -957,6 +963,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", msr_index, data);
break;
+ case MSR_IA32_CR_PAT:
+ if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+ vmcs_write64(GUEST_IA32_PAT, data);
+ vcpu->arch.pat = data;
+ break;
+ }
+ /* Otherwise falls through to kvm_set_msr_common */
default:
vmx_load_host_state(vmx);
msr = find_msr_entry(vmx, msr_index);
@@ -1032,8 +1045,7 @@ static int vmx_get_irq(struct kvm_vcpu *vcpu)
static __init int cpu_has_kvm_support(void)
{
- unsigned long ecx = cpuid_ecx(1);
- return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */
+ return cpu_has_vmx();
}
static __init int vmx_disabled_by_bios(void)
@@ -1079,13 +1091,22 @@ static void vmclear_local_vcpus(void)
__vcpu_clear(vmx);
}
-static void hardware_disable(void *garbage)
+
+/* Just like cpu_vmxoff(), but with the __kvm_handle_fault_on_reboot()
+ * tricks.
+ */
+static void kvm_cpu_vmxoff(void)
{
- vmclear_local_vcpus();
asm volatile (__ex(ASM_VMX_VMXOFF) : : : "cc");
write_cr4(read_cr4() & ~X86_CR4_VMXE);
}
+static void hardware_disable(void *garbage)
+{
+ vmclear_local_vcpus();
+ kvm_cpu_vmxoff();
+}
+
static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
u32 msr, u32 *result)
{
@@ -1176,12 +1197,13 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
#ifdef CONFIG_X86_64
min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
#endif
- opt = 0;
+ opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT;
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
&_vmexit_control) < 0)
return -EIO;
- min = opt = 0;
+ min = 0;
+ opt = VM_ENTRY_LOAD_IA32_PAT;
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
&_vmentry_control) < 0)
return -EIO;
@@ -2087,8 +2109,9 @@ static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr)
*/
static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
{
- u32 host_sysenter_cs;
+ u32 host_sysenter_cs, msr_low, msr_high;
u32 junk;
+ u64 host_pat;
unsigned long a;
struct descriptor_table dt;
int i;
@@ -2176,6 +2199,20 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
rdmsrl(MSR_IA32_SYSENTER_EIP, a);
vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */
+ if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) {
+ rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
+ host_pat = msr_low | ((u64) msr_high << 32);
+ vmcs_write64(HOST_IA32_PAT, host_pat);
+ }
+ if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
+ rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high);
+ host_pat = msr_low | ((u64) msr_high << 32);
+ /* Write the default value follow host pat */
+ vmcs_write64(GUEST_IA32_PAT, host_pat);
+ /* Keep arch.pat sync with GUEST_IA32_PAT */
+ vmx->vcpu.arch.pat = host_pat;
+ }
+
for (i = 0; i < NR_VMX_MSR; ++i) {
u32 index = vmx_msr_index[i];
u32 data_low, data_high;
@@ -2230,6 +2267,8 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmx->vcpu.arch.rmode.active = 0;
+ vmx->soft_vnmi_blocked = 0;
+
vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
kvm_set_cr8(&vmx->vcpu, 0);
msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
@@ -2335,6 +2374,29 @@ out:
return ret;
}
+static void enable_irq_window(struct kvm_vcpu *vcpu)
+{
+ u32 cpu_based_vm_exec_control;
+
+ cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+}
+
+static void enable_nmi_window(struct kvm_vcpu *vcpu)
+{
+ u32 cpu_based_vm_exec_control;
+
+ if (!cpu_has_virtual_nmis()) {
+ enable_irq_window(vcpu);
+ return;
+ }
+
+ cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_NMI_PENDING;
+ vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+}
+
static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2358,10 +2420,54 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+ if (!cpu_has_virtual_nmis()) {
+ /*
+ * Tracking the NMI-blocked state in software is built upon
+ * finding the next open IRQ window. This, in turn, depends on
+ * well-behaving guests: They have to keep IRQs disabled at
+ * least as long as the NMI handler runs. Otherwise we may
+ * cause NMI nesting, maybe breaking the guest. But as this is
+ * highly unlikely, we can live with the residual risk.
+ */
+ vmx->soft_vnmi_blocked = 1;
+ vmx->vnmi_blocked_time = 0;
+ }
+
+ ++vcpu->stat.nmi_injections;
+ if (vcpu->arch.rmode.active) {
+ vmx->rmode.irq.pending = true;
+ vmx->rmode.irq.vector = NMI_VECTOR;
+ vmx->rmode.irq.rip = kvm_rip_read(vcpu);
+ vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
+ NMI_VECTOR | INTR_TYPE_SOFT_INTR |
+ INTR_INFO_VALID_MASK);
+ vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
+ kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
+ return;
+ }
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
}
+static void vmx_update_window_states(struct kvm_vcpu *vcpu)
+{
+ u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+
+ vcpu->arch.nmi_window_open =
+ !(guest_intr & (GUEST_INTR_STATE_STI |
+ GUEST_INTR_STATE_MOV_SS |
+ GUEST_INTR_STATE_NMI));
+ if (!cpu_has_virtual_nmis() && to_vmx(vcpu)->soft_vnmi_blocked)
+ vcpu->arch.nmi_window_open = 0;
+
+ vcpu->arch.interrupt_window_open =
+ ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+ !(guest_intr & (GUEST_INTR_STATE_STI |
+ GUEST_INTR_STATE_MOV_SS)));
+}
+
static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
{
int word_index = __ffs(vcpu->arch.irq_summary);
@@ -2374,40 +2480,49 @@ static void kvm_do_inject_irq(struct kvm_vcpu *vcpu)
kvm_queue_interrupt(vcpu, irq);
}
-
static void do_interrupt_requests(struct kvm_vcpu *vcpu,
struct kvm_run *kvm_run)
{
- u32 cpu_based_vm_exec_control;
-
- vcpu->arch.interrupt_window_open =
- ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
- (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0);
+ vmx_update_window_states(vcpu);
- if (vcpu->arch.interrupt_window_open &&
- vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending)
- kvm_do_inject_irq(vcpu);
+ if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
+ if (vcpu->arch.interrupt.pending) {
+ enable_nmi_window(vcpu);
+ } else if (vcpu->arch.nmi_window_open) {
+ vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_injected = true;
+ } else {
+ enable_nmi_window(vcpu);
+ return;
+ }
+ }
+ if (vcpu->arch.nmi_injected) {
+ vmx_inject_nmi(vcpu);
+ if (vcpu->arch.nmi_pending)
+ enable_nmi_window(vcpu);
+ else if (vcpu->arch.irq_summary
+ || kvm_run->request_interrupt_window)
+ enable_irq_window(vcpu);
+ return;
+ }
- if (vcpu->arch.interrupt_window_open && vcpu->arch.interrupt.pending)
- vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
+ if (vcpu->arch.interrupt_window_open) {
+ if (vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending)
+ kvm_do_inject_irq(vcpu);
- cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ if (vcpu->arch.interrupt.pending)
+ vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
+ }
if (!vcpu->arch.interrupt_window_open &&
(vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
- /*
- * Interrupts blocked. Wait for unblock.
- */
- cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
- else
- cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+ enable_irq_window(vcpu);
}
static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
{
int ret;
struct kvm_userspace_memory_region tss_mem = {
- .slot = 8,
+ .slot = TSS_PRIVATE_MEMSLOT,
.guest_phys_addr = addr,
.memory_size = PAGE_SIZE * 3,
.flags = 0,
@@ -2492,7 +2607,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
}
- if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
+ if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
return 1; /* already handled by vmx_vcpu_run() */
if (is_no_device(intr_info)) {
@@ -2581,6 +2696,7 @@ static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
rep = (exit_qualification & 32) != 0;
port = exit_qualification >> 16;
+ skip_emulated_instruction(vcpu);
return kvm_emulate_pio(vcpu, kvm_run, in, size, port);
}
@@ -2767,6 +2883,7 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
KVMTRACE_0D(PEND_INTR, vcpu, handler);
+ ++vcpu->stat.irq_window_exits;
/*
* If the user space waits to inject interrupts, exit as soon as
@@ -2775,7 +2892,6 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
if (kvm_run->request_interrupt_window &&
!vcpu->arch.irq_summary) {
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
- ++vcpu->stat.irq_window_exits;
return 0;
}
return 1;
@@ -2832,6 +2948,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
unsigned long exit_qualification;
u16 tss_selector;
int reason;
@@ -2839,6 +2956,15 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
reason = (u32)exit_qualification >> 30;
+ if (reason == TASK_SWITCH_GATE && vmx->vcpu.arch.nmi_injected &&
+ (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
+ (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK)
+ == INTR_TYPE_NMI_INTR) {
+ vcpu->arch.nmi_injected = false;
+ if (cpu_has_virtual_nmis())
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_NMI);
+ }
tss_selector = exit_qualification;
return kvm_task_switch(vcpu, tss_selector, reason);
@@ -2927,16 +3053,12 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
while (!guest_state_valid(vcpu)) {
err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
- switch (err) {
- case EMULATE_DONE:
- break;
- case EMULATE_DO_MMIO:
- kvm_report_emulation_failure(vcpu, "mmio");
- /* TODO: Handle MMIO */
- return;
- default:
- kvm_report_emulation_failure(vcpu, "emulation failure");
- return;
+ if (err == EMULATE_DO_MMIO)
+ break;
+
+ if (err != EMULATE_DONE) {
+ kvm_report_emulation_failure(vcpu, "emulation failure");
+ return;
}
if (signal_pending(current))
@@ -2948,8 +3070,10 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
local_irq_disable();
preempt_disable();
- /* Guest state should be valid now, no more emulation should be needed */
- vmx->emulation_required = 0;
+ /* Guest state should be valid now except if we need to
+ * emulate an MMIO */
+ if (guest_state_valid(vcpu))
+ vmx->emulation_required = 0;
}
/*
@@ -2996,6 +3120,11 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
KVMTRACE_3D(VMEXIT, vcpu, exit_reason, (u32)kvm_rip_read(vcpu),
(u32)((u64)kvm_rip_read(vcpu) >> 32), entryexit);
+ /* If we need to emulate an MMIO from handle_invalid_guest_state
+ * we just return 0 */
+ if (vmx->emulation_required && emulate_invalid_guest_state)
+ return 0;
+
/* Access CR3 don't cause VMExit in paging mode, so we need
* to sync with guest real CR3. */
if (vm_need_ept() && is_paging(vcpu)) {
@@ -3012,9 +3141,32 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
(exit_reason != EXIT_REASON_EXCEPTION_NMI &&
- exit_reason != EXIT_REASON_EPT_VIOLATION))
- printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
- "exit reason is 0x%x\n", __func__, exit_reason);
+ exit_reason != EXIT_REASON_EPT_VIOLATION &&
+ exit_reason != EXIT_REASON_TASK_SWITCH))
+ printk(KERN_WARNING "%s: unexpected, valid vectoring info "
+ "(0x%x) and exit reason is 0x%x\n",
+ __func__, vectoring_info, exit_reason);
+
+ if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) {
+ if (vcpu->arch.interrupt_window_open) {
+ vmx->soft_vnmi_blocked = 0;
+ vcpu->arch.nmi_window_open = 1;
+ } else if (vmx->vnmi_blocked_time > 1000000000LL &&
+ vcpu->arch.nmi_pending) {
+ /*
+ * This CPU don't support us in finding the end of an
+ * NMI-blocked window if the guest runs with IRQs
+ * disabled. So we pull the trigger after 1 s of
+ * futile waiting, but inform the user about this.
+ */
+ printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
+ "state on VCPU %d after 1 s timeout\n",
+ __func__, vcpu->vcpu_id);
+ vmx->soft_vnmi_blocked = 0;
+ vmx->vcpu.arch.nmi_window_open = 1;
+ }
+ }
+
if (exit_reason < kvm_vmx_max_exit_handlers
&& kvm_vmx_exit_handlers[exit_reason])
return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run);
@@ -3042,51 +3194,6 @@ static void update_tpr_threshold(struct kvm_vcpu *vcpu)
vmcs_write32(TPR_THRESHOLD, (max_irr > tpr) ? tpr >> 4 : max_irr >> 4);
}
-static void enable_irq_window(struct kvm_vcpu *vcpu)
-{
- u32 cpu_based_vm_exec_control;
-
- cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
- cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
-}
-
-static void enable_nmi_window(struct kvm_vcpu *vcpu)
-{
- u32 cpu_based_vm_exec_control;
-
- if (!cpu_has_virtual_nmis())
- return;
-
- cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
- cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_NMI_PENDING;
- vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
-}
-
-static int vmx_nmi_enabled(struct kvm_vcpu *vcpu)
-{
- u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
- return !(guest_intr & (GUEST_INTR_STATE_NMI |
- GUEST_INTR_STATE_MOV_SS |
- GUEST_INTR_STATE_STI));
-}
-
-static int vmx_irq_enabled(struct kvm_vcpu *vcpu)
-{
- u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
- return (!(guest_intr & (GUEST_INTR_STATE_MOV_SS |
- GUEST_INTR_STATE_STI)) &&
- (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF));
-}
-
-static void enable_intr_window(struct kvm_vcpu *vcpu)
-{
- if (vcpu->arch.nmi_pending)
- enable_nmi_window(vcpu);
- else if (kvm_cpu_has_interrupt(vcpu))
- enable_irq_window(vcpu);
-}
-
static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
{
u32 exit_intr_info;
@@ -3109,7 +3216,9 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
if (unblock_nmi && vector != DF_VECTOR)
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_NMI);
- }
+ } else if (unlikely(vmx->soft_vnmi_blocked))
+ vmx->vnmi_blocked_time +=
+ ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
idt_vectoring_info = vmx->idt_vectoring_info;
idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
@@ -3147,26 +3256,29 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
{
update_tpr_threshold(vcpu);
- if (cpu_has_virtual_nmis()) {
- if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
- if (vcpu->arch.interrupt.pending) {
- enable_nmi_window(vcpu);
- } else if (vmx_nmi_enabled(vcpu)) {
- vcpu->arch.nmi_pending = false;
- vcpu->arch.nmi_injected = true;
- } else {
- enable_intr_window(vcpu);
- return;
- }
- }
- if (vcpu->arch.nmi_injected) {
- vmx_inject_nmi(vcpu);
- enable_intr_window(vcpu);
+ vmx_update_window_states(vcpu);
+
+ if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
+ if (vcpu->arch.interrupt.pending) {
+ enable_nmi_window(vcpu);
+ } else if (vcpu->arch.nmi_window_open) {
+ vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_injected = true;
+ } else {
+ enable_nmi_window(vcpu);
return;
}
}
+ if (vcpu->arch.nmi_injected) {
+ vmx_inject_nmi(vcpu);
+ if (vcpu->arch.nmi_pending)
+ enable_nmi_window(vcpu);
+ else if (kvm_cpu_has_interrupt(vcpu))
+ enable_irq_window(vcpu);
+ return;
+ }
if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) {
- if (vmx_irq_enabled(vcpu))
+ if (vcpu->arch.interrupt_window_open)
kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
else
enable_irq_window(vcpu);
@@ -3174,6 +3286,8 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
if (vcpu->arch.interrupt.pending) {
vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
kvm_timer_intr_post(vcpu, vcpu->arch.interrupt.nr);
+ if (kvm_cpu_has_interrupt(vcpu))
+ enable_irq_window(vcpu);
}
}
@@ -3213,6 +3327,10 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
struct vcpu_vmx *vmx = to_vmx(vcpu);
u32 intr_info;
+ /* Record the guest's net vcpu time for enforced NMI injections. */
+ if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
+ vmx->entry_time = ktime_get();
+
/* Handle invalid guest state instead of entering VMX */
if (vmx->emulation_required && emulate_invalid_guest_state) {
handle_invalid_guest_state(vcpu, kvm_run);
@@ -3327,9 +3445,7 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vmx->rmode.irq.pending)
fixup_rmode_irq(vmx);
- vcpu->arch.interrupt_window_open =
- (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
- (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS)) == 0;
+ vmx_update_window_states(vcpu);
asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
vmx->launched = 1;
@@ -3337,7 +3453,7 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
/* We need to handle NMIs before interrupts are enabled */
- if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200 &&
+ if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
(intr_info & INTR_INFO_VALID_MASK)) {
KVMTRACE_0D(NMI, vcpu, handler);
asm("int $2");
@@ -3455,6 +3571,11 @@ static int get_ept_level(void)
return VMX_EPT_DEFAULT_GAW + 1;
}
+static int vmx_get_mt_mask_shift(void)
+{
+ return VMX_EPT_MT_EPTE_SHIFT;
+}
+
static struct kvm_x86_ops vmx_x86_ops = {
.cpu_has_kvm_support = cpu_has_kvm_support,
.disabled_by_bios = vmx_disabled_by_bios,
@@ -3510,6 +3631,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
.set_tss_addr = vmx_set_tss_addr,
.get_tdp_level = get_ept_level,
+ .get_mt_mask_shift = vmx_get_mt_mask_shift,
};
static int __init vmx_init(void)
@@ -3566,10 +3688,10 @@ static int __init vmx_init(void)
bypass_guest_pf = 0;
kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
VMX_EPT_WRITABLE_MASK |
- VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT |
VMX_EPT_IGMT_BIT);
kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
- VMX_EPT_EXECUTABLE_MASK);
+ VMX_EPT_EXECUTABLE_MASK,
+ VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
kvm_enable_tdp();
} else
kvm_disable_tdp();
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f1f8ff2f1fa2..cc17546a2406 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -34,11 +34,13 @@
#include <linux/module.h>
#include <linux/mman.h>
#include <linux/highmem.h>
+#include <linux/iommu.h>
#include <linux/intel-iommu.h>
#include <asm/uaccess.h>
#include <asm/msr.h>
#include <asm/desc.h>
+#include <asm/mtrr.h>
#define MAX_IO_MSRS 256
#define CR0_RESERVED_BITS \
@@ -86,6 +88,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
{ "hypercalls", VCPU_STAT(hypercalls) },
{ "request_irq", VCPU_STAT(request_irq_exits) },
+ { "request_nmi", VCPU_STAT(request_nmi_exits) },
{ "irq_exits", VCPU_STAT(irq_exits) },
{ "host_state_reload", VCPU_STAT(host_state_reload) },
{ "efer_reload", VCPU_STAT(efer_reload) },
@@ -93,6 +96,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "insn_emulation", VCPU_STAT(insn_emulation) },
{ "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) },
{ "irq_injections", VCPU_STAT(irq_injections) },
+ { "nmi_injections", VCPU_STAT(nmi_injections) },
{ "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) },
{ "mmu_pte_write", VM_STAT(mmu_pte_write) },
{ "mmu_pte_updated", VM_STAT(mmu_pte_updated) },
@@ -101,6 +105,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "mmu_recycled", VM_STAT(mmu_recycled) },
{ "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
{ "mmu_unsync", VM_STAT(mmu_unsync) },
+ { "mmu_unsync_global", VM_STAT(mmu_unsync_global) },
{ "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
{ "largepages", VM_STAT(lpages) },
{ NULL }
@@ -312,6 +317,7 @@ void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
kvm_x86_ops->set_cr0(vcpu, cr0);
vcpu->arch.cr0 = cr0;
+ kvm_mmu_sync_global(vcpu);
kvm_mmu_reset_context(vcpu);
return;
}
@@ -355,6 +361,7 @@ void kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
}
kvm_x86_ops->set_cr4(vcpu, cr4);
vcpu->arch.cr4 = cr4;
+ kvm_mmu_sync_global(vcpu);
kvm_mmu_reset_context(vcpu);
}
EXPORT_SYMBOL_GPL(kvm_set_cr4);
@@ -449,7 +456,7 @@ static u32 msrs_to_save[] = {
MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR,
#endif
MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
- MSR_IA32_PERF_STATUS,
+ MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT
};
static unsigned num_msrs_to_save;
@@ -648,10 +655,38 @@ static bool msr_mtrr_valid(unsigned msr)
static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
{
+ u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
+
if (!msr_mtrr_valid(msr))
return 1;
- vcpu->arch.mtrr[msr - 0x200] = data;
+ if (msr == MSR_MTRRdefType) {
+ vcpu->arch.mtrr_state.def_type = data;
+ vcpu->arch.mtrr_state.enabled = (data & 0xc00) >> 10;
+ } else if (msr == MSR_MTRRfix64K_00000)
+ p[0] = data;
+ else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000)
+ p[1 + msr - MSR_MTRRfix16K_80000] = data;
+ else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000)
+ p[3 + msr - MSR_MTRRfix4K_C0000] = data;
+ else if (msr == MSR_IA32_CR_PAT)
+ vcpu->arch.pat = data;
+ else { /* Variable MTRRs */
+ int idx, is_mtrr_mask;
+ u64 *pt;
+
+ idx = (msr - 0x200) / 2;
+ is_mtrr_mask = msr - 0x200 - 2 * idx;
+ if (!is_mtrr_mask)
+ pt =
+ (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].base_lo;
+ else
+ pt =
+ (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].mask_lo;
+ *pt = data;
+ }
+
+ kvm_mmu_reset_context(vcpu);
return 0;
}
@@ -747,10 +782,37 @@ int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
static int get_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
{
+ u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
+
if (!msr_mtrr_valid(msr))
return 1;
- *pdata = vcpu->arch.mtrr[msr - 0x200];
+ if (msr == MSR_MTRRdefType)
+ *pdata = vcpu->arch.mtrr_state.def_type +
+ (vcpu->arch.mtrr_state.enabled << 10);
+ else if (msr == MSR_MTRRfix64K_00000)
+ *pdata = p[0];
+ else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000)
+ *pdata = p[1 + msr - MSR_MTRRfix16K_80000];
+ else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000)
+ *pdata = p[3 + msr - MSR_MTRRfix4K_C0000];
+ else if (msr == MSR_IA32_CR_PAT)
+ *pdata = vcpu->arch.pat;
+ else { /* Variable MTRRs */
+ int idx, is_mtrr_mask;
+ u64 *pt;
+
+ idx = (msr - 0x200) / 2;
+ is_mtrr_mask = msr - 0x200 - 2 * idx;
+ if (!is_mtrr_mask)
+ pt =
+ (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].base_lo;
+ else
+ pt =
+ (u64 *)&vcpu->arch.mtrr_state.var_ranges[idx].mask_lo;
+ *pdata = *pt;
+ }
+
return 0;
}
@@ -903,7 +965,6 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_IRQCHIP:
case KVM_CAP_HLT:
case KVM_CAP_MMU_SHADOW_CACHE_CONTROL:
- case KVM_CAP_USER_MEMORY:
case KVM_CAP_SET_TSS_ADDR:
case KVM_CAP_EXT_CPUID:
case KVM_CAP_CLOCKSOURCE:
@@ -929,7 +990,7 @@ int kvm_dev_ioctl_check_extension(long ext)
r = !tdp_enabled;
break;
case KVM_CAP_IOMMU:
- r = intel_iommu_found();
+ r = iommu_found();
break;
default:
r = 0;
@@ -1188,6 +1249,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
int t, times = entry->eax & 0xff;
entry->flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
+ entry->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
for (t = 1; t < times && *nent < maxnent; ++t) {
do_cpuid_1_ent(&entry[t], function, 0);
entry[t].flags |= KVM_CPUID_FLAG_STATEFUL_FUNC;
@@ -1218,7 +1280,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
/* read more entries until level_type is zero */
for (i = 1; *nent < maxnent; ++i) {
- level_type = entry[i - 1].ecx & 0xff;
+ level_type = entry[i - 1].ecx & 0xff00;
if (!level_type)
break;
do_cpuid_1_ent(&entry[i], function, i);
@@ -1318,6 +1380,15 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
return 0;
}
+static int kvm_vcpu_ioctl_nmi(struct kvm_vcpu *vcpu)
+{
+ vcpu_load(vcpu);
+ kvm_inject_nmi(vcpu);
+ vcpu_put(vcpu);
+
+ return 0;
+}
+
static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu,
struct kvm_tpr_access_ctl *tac)
{
@@ -1377,6 +1448,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = 0;
break;
}
+ case KVM_NMI: {
+ r = kvm_vcpu_ioctl_nmi(vcpu);
+ if (r)
+ goto out;
+ r = 0;
+ break;
+ }
case KVM_SET_CPUID: {
struct kvm_cpuid __user *cpuid_arg = argp;
struct kvm_cpuid cpuid;
@@ -1968,7 +2046,7 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
ret = kvm_write_guest(vcpu->kvm, gpa, val, bytes);
if (ret < 0)
return 0;
- kvm_mmu_pte_write(vcpu, gpa, val, bytes);
+ kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
return 1;
}
@@ -2404,8 +2482,6 @@ int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
val = kvm_register_read(vcpu, VCPU_REGS_RAX);
memcpy(vcpu->arch.pio_data, &val, 4);
- kvm_x86_ops->skip_emulated_instruction(vcpu);
-
pio_dev = vcpu_find_pio_dev(vcpu, port, size, !in);
if (pio_dev) {
kernel_pio(pio_dev, vcpu, vcpu->arch.pio_data);
@@ -2541,7 +2617,7 @@ int kvm_arch_init(void *opaque)
kvm_mmu_set_nonpresent_ptes(0ull, 0ull);
kvm_mmu_set_base_ptes(PT_PRESENT_MASK);
kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
- PT_DIRTY_MASK, PT64_NX_MASK, 0);
+ PT_DIRTY_MASK, PT64_NX_MASK, 0, 0);
return 0;
out:
@@ -2729,7 +2805,7 @@ static int move_to_next_stateful_cpuid_entry(struct kvm_vcpu *vcpu, int i)
e->flags &= ~KVM_CPUID_FLAG_STATE_READ_NEXT;
/* when no next entry is found, the current entry[i] is reselected */
- for (j = i + 1; j == i; j = (j + 1) % nent) {
+ for (j = i + 1; ; j = (j + 1) % nent) {
struct kvm_cpuid_entry2 *ej = &vcpu->arch.cpuid_entries[j];
if (ej->function == e->function) {
ej->flags |= KVM_CPUID_FLAG_STATE_READ_NEXT;
@@ -2973,7 +3049,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
pr_debug("vcpu %d received sipi with vector # %x\n",
vcpu->vcpu_id, vcpu->arch.sipi_vector);
kvm_lapic_reset(vcpu);
- r = kvm_x86_ops->vcpu_reset(vcpu);
+ r = kvm_arch_vcpu_reset(vcpu);
if (r)
return r;
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
@@ -3275,9 +3351,9 @@ static void seg_desct_to_kvm_desct(struct desc_struct *seg_desc, u16 selector,
kvm_desct->padding = 0;
}
-static void get_segment_descritptor_dtable(struct kvm_vcpu *vcpu,
- u16 selector,
- struct descriptor_table *dtable)
+static void get_segment_descriptor_dtable(struct kvm_vcpu *vcpu,
+ u16 selector,
+ struct descriptor_table *dtable)
{
if (selector & 1 << 2) {
struct kvm_segment kvm_seg;
@@ -3302,7 +3378,7 @@ static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
struct descriptor_table dtable;
u16 index = selector >> 3;
- get_segment_descritptor_dtable(vcpu, selector, &dtable);
+ get_segment_descriptor_dtable(vcpu, selector, &dtable);
if (dtable.limit < index * 8 + 7) {
kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc);
@@ -3321,7 +3397,7 @@ static int save_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector,
struct descriptor_table dtable;
u16 index = selector >> 3;
- get_segment_descritptor_dtable(vcpu, selector, &dtable);
+ get_segment_descriptor_dtable(vcpu, selector, &dtable);
if (dtable.limit < index * 8 + 7)
return 1;
@@ -3900,6 +3976,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
/* We do fxsave: this must be aligned. */
BUG_ON((unsigned long)&vcpu->arch.host_fx_image & 0xF);
+ vcpu->arch.mtrr_state.have_fixed = 1;
vcpu_load(vcpu);
r = kvm_arch_vcpu_reset(vcpu);
if (r == 0)
@@ -3925,6 +4002,9 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
{
+ vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_injected = false;
+
return kvm_x86_ops->vcpu_reset(vcpu);
}
@@ -4012,6 +4092,7 @@ struct kvm *kvm_arch_create_vm(void)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
+ INIT_LIST_HEAD(&kvm->arch.oos_global_pages);
INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
@@ -4048,8 +4129,8 @@ static void kvm_free_vcpus(struct kvm *kvm)
void kvm_arch_destroy_vm(struct kvm *kvm)
{
- kvm_iommu_unmap_guest(kvm);
kvm_free_all_assigned_devices(kvm);
+ kvm_iommu_unmap_guest(kvm);
kvm_free_pit(kvm);
kfree(kvm->arch.vpic);
kfree(kvm->arch.vioapic);
@@ -4127,7 +4208,8 @@ void kvm_arch_flush_shadow(struct kvm *kvm)
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
return vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE
- || vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED;
+ || vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
+ || vcpu->arch.nmi_pending;
}
static void vcpu_kick_intr(void *info)
diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c
index ea051173b0da..d174db7a3370 100644
--- a/arch/x86/kvm/x86_emulate.c
+++ b/arch/x86/kvm/x86_emulate.c
@@ -58,6 +58,7 @@
#define SrcMem32 (4<<4) /* Memory operand (32-bit). */
#define SrcImm (5<<4) /* Immediate operand. */
#define SrcImmByte (6<<4) /* 8-bit sign-extended immediate operand. */
+#define SrcOne (7<<4) /* Implied '1' */
#define SrcMask (7<<4)
/* Generic ModRM decode. */
#define ModRM (1<<7)
@@ -70,17 +71,23 @@
#define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */
#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
#define GroupMask 0xff /* Group number stored in bits 0:7 */
+/* Source 2 operand type */
+#define Src2None (0<<29)
+#define Src2CL (1<<29)
+#define Src2ImmByte (2<<29)
+#define Src2One (3<<29)
+#define Src2Mask (7<<29)
enum {
Group1_80, Group1_81, Group1_82, Group1_83,
Group1A, Group3_Byte, Group3, Group4, Group5, Group7,
};
-static u16 opcode_table[256] = {
+static u32 opcode_table[256] = {
/* 0x00 - 0x07 */
ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
- 0, 0, 0, 0,
+ ByteOp | DstAcc | SrcImm, DstAcc | SrcImm, 0, 0,
/* 0x08 - 0x0F */
ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM,
ByteOp | DstReg | SrcMem | ModRM, DstReg | SrcMem | ModRM,
@@ -195,7 +202,7 @@ static u16 opcode_table[256] = {
ImplicitOps, ImplicitOps, Group | Group4, Group | Group5,
};
-static u16 twobyte_table[256] = {
+static u32 twobyte_table[256] = {
/* 0x00 - 0x0F */
0, Group | GroupDual | Group7, 0, 0, 0, 0, ImplicitOps, 0,
ImplicitOps, ImplicitOps, 0, 0, 0, ImplicitOps | ModRM, 0, 0,
@@ -230,9 +237,14 @@ static u16 twobyte_table[256] = {
/* 0x90 - 0x9F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xA0 - 0xA7 */
- 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, 0, 0,
+ 0, 0, 0, DstMem | SrcReg | ModRM | BitOp,
+ DstMem | SrcReg | Src2ImmByte | ModRM,
+ DstMem | SrcReg | Src2CL | ModRM, 0, 0,
/* 0xA8 - 0xAF */
- 0, 0, 0, DstMem | SrcReg | ModRM | BitOp, 0, 0, ModRM, 0,
+ 0, 0, 0, DstMem | SrcReg | ModRM | BitOp,
+ DstMem | SrcReg | Src2ImmByte | ModRM,
+ DstMem | SrcReg | Src2CL | ModRM,
+ ModRM, 0,
/* 0xB0 - 0xB7 */
ByteOp | DstMem | SrcReg | ModRM, DstMem | SrcReg | ModRM, 0,
DstMem | SrcReg | ModRM | BitOp,
@@ -253,7 +265,7 @@ static u16 twobyte_table[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static u16 group_table[] = {
+static u32 group_table[] = {
[Group1_80*8] =
ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
ByteOp | DstMem | SrcImm | ModRM, ByteOp | DstMem | SrcImm | ModRM,
@@ -297,9 +309,9 @@ static u16 group_table[] = {
SrcMem16 | ModRM | Mov, SrcMem | ModRM | ByteOp,
};
-static u16 group2_table[] = {
+static u32 group2_table[] = {
[Group7*8] =
- SrcNone | ModRM, 0, 0, 0,
+ SrcNone | ModRM, 0, 0, SrcNone | ModRM,
SrcNone | ModRM | DstMem | Mov, 0,
SrcMem16 | ModRM | Mov, 0,
};
@@ -359,49 +371,48 @@ static u16 group2_table[] = {
"andl %"_msk",%"_LO32 _tmp"; " \
"orl %"_LO32 _tmp",%"_sav"; "
+#ifdef CONFIG_X86_64
+#define ON64(x) x
+#else
+#define ON64(x)
+#endif
+
+#define ____emulate_2op(_op, _src, _dst, _eflags, _x, _y, _suffix) \
+ do { \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0", "4", "2") \
+ _op _suffix " %"_x"3,%1; " \
+ _POST_EFLAGS("0", "4", "2") \
+ : "=m" (_eflags), "=m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : _y ((_src).val), "i" (EFLAGS_MASK)); \
+ } while (0)
+
+
/* Raw emulation: instruction has two explicit operands. */
#define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \
- do { \
- unsigned long _tmp; \
- \
- switch ((_dst).bytes) { \
- case 2: \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "4", "2") \
- _op"w %"_wx"3,%1; " \
- _POST_EFLAGS("0", "4", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), \
- "=&r" (_tmp) \
- : _wy ((_src).val), "i" (EFLAGS_MASK)); \
- break; \
- case 4: \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "4", "2") \
- _op"l %"_lx"3,%1; " \
- _POST_EFLAGS("0", "4", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), \
- "=&r" (_tmp) \
- : _ly ((_src).val), "i" (EFLAGS_MASK)); \
- break; \
- case 8: \
- __emulate_2op_8byte(_op, _src, _dst, \
- _eflags, _qx, _qy); \
- break; \
- } \
+ do { \
+ unsigned long _tmp; \
+ \
+ switch ((_dst).bytes) { \
+ case 2: \
+ ____emulate_2op(_op,_src,_dst,_eflags,_wx,_wy,"w"); \
+ break; \
+ case 4: \
+ ____emulate_2op(_op,_src,_dst,_eflags,_lx,_ly,"l"); \
+ break; \
+ case 8: \
+ ON64(____emulate_2op(_op,_src,_dst,_eflags,_qx,_qy,"q")); \
+ break; \
+ } \
} while (0)
#define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \
do { \
- unsigned long __tmp; \
+ unsigned long _tmp; \
switch ((_dst).bytes) { \
case 1: \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "4", "2") \
- _op"b %"_bx"3,%1; " \
- _POST_EFLAGS("0", "4", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), \
- "=&r" (__tmp) \
- : _by ((_src).val), "i" (EFLAGS_MASK)); \
+ ____emulate_2op(_op,_src,_dst,_eflags,_bx,_by,"b"); \
break; \
default: \
__emulate_2op_nobyte(_op, _src, _dst, _eflags, \
@@ -425,71 +436,68 @@ static u16 group2_table[] = {
__emulate_2op_nobyte(_op, _src, _dst, _eflags, \
"w", "r", _LO32, "r", "", "r")
-/* Instruction has only one explicit operand (no source operand). */
-#define emulate_1op(_op, _dst, _eflags) \
- do { \
- unsigned long _tmp; \
- \
- switch ((_dst).bytes) { \
- case 1: \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "3", "2") \
- _op"b %1; " \
- _POST_EFLAGS("0", "3", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), \
- "=&r" (_tmp) \
- : "i" (EFLAGS_MASK)); \
- break; \
- case 2: \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "3", "2") \
- _op"w %1; " \
- _POST_EFLAGS("0", "3", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), \
- "=&r" (_tmp) \
- : "i" (EFLAGS_MASK)); \
- break; \
- case 4: \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "3", "2") \
- _op"l %1; " \
- _POST_EFLAGS("0", "3", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), \
- "=&r" (_tmp) \
- : "i" (EFLAGS_MASK)); \
- break; \
- case 8: \
- __emulate_1op_8byte(_op, _dst, _eflags); \
- break; \
- } \
+/* Instruction has three operands and one operand is stored in ECX register */
+#define __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, _suffix, _type) \
+ do { \
+ unsigned long _tmp; \
+ _type _clv = (_cl).val; \
+ _type _srcv = (_src).val; \
+ _type _dstv = (_dst).val; \
+ \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0", "5", "2") \
+ _op _suffix " %4,%1 \n" \
+ _POST_EFLAGS("0", "5", "2") \
+ : "=m" (_eflags), "+r" (_dstv), "=&r" (_tmp) \
+ : "c" (_clv) , "r" (_srcv), "i" (EFLAGS_MASK) \
+ ); \
+ \
+ (_cl).val = (unsigned long) _clv; \
+ (_src).val = (unsigned long) _srcv; \
+ (_dst).val = (unsigned long) _dstv; \
} while (0)
-/* Emulate an instruction with quadword operands (x86/64 only). */
-#if defined(CONFIG_X86_64)
-#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) \
- do { \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "4", "2") \
- _op"q %"_qx"3,%1; " \
- _POST_EFLAGS("0", "4", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : _qy ((_src).val), "i" (EFLAGS_MASK)); \
+#define emulate_2op_cl(_op, _cl, _src, _dst, _eflags) \
+ do { \
+ switch ((_dst).bytes) { \
+ case 2: \
+ __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
+ "w", unsigned short); \
+ break; \
+ case 4: \
+ __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
+ "l", unsigned int); \
+ break; \
+ case 8: \
+ ON64(__emulate_2op_cl(_op, _cl, _src, _dst, _eflags, \
+ "q", unsigned long)); \
+ break; \
+ } \
} while (0)
-#define __emulate_1op_8byte(_op, _dst, _eflags) \
- do { \
- __asm__ __volatile__ ( \
- _PRE_EFLAGS("0", "3", "2") \
- _op"q %1; " \
- _POST_EFLAGS("0", "3", "2") \
- : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : "i" (EFLAGS_MASK)); \
+#define __emulate_1op(_op, _dst, _eflags, _suffix) \
+ do { \
+ unsigned long _tmp; \
+ \
+ __asm__ __volatile__ ( \
+ _PRE_EFLAGS("0", "3", "2") \
+ _op _suffix " %1; " \
+ _POST_EFLAGS("0", "3", "2") \
+ : "=m" (_eflags), "+m" ((_dst).val), \
+ "=&r" (_tmp) \
+ : "i" (EFLAGS_MASK)); \
} while (0)
-#elif defined(__i386__)
-#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)
-#define __emulate_1op_8byte(_op, _dst, _eflags)
-#endif /* __i386__ */
+/* Instruction has only one explicit operand (no source operand). */
+#define emulate_1op(_op, _dst, _eflags) \
+ do { \
+ switch ((_dst).bytes) { \
+ case 1: __emulate_1op(_op, _dst, _eflags, "b"); break; \
+ case 2: __emulate_1op(_op, _dst, _eflags, "w"); break; \
+ case 4: __emulate_1op(_op, _dst, _eflags, "l"); break; \
+ case 8: ON64(__emulate_1op(_op, _dst, _eflags, "q")); break; \
+ } \
+ } while (0)
/* Fetch next part of the instruction being emulated. */
#define insn_fetch(_type, _size, _eip) \
@@ -1041,6 +1049,33 @@ done_prefixes:
c->src.bytes = 1;
c->src.val = insn_fetch(s8, 1, c->eip);
break;
+ case SrcOne:
+ c->src.bytes = 1;
+ c->src.val = 1;
+ break;
+ }
+
+ /*
+ * Decode and fetch the second source operand: register, memory
+ * or immediate.
+ */
+ switch (c->d & Src2Mask) {
+ case Src2None:
+ break;
+ case Src2CL:
+ c->src2.bytes = 1;
+ c->src2.val = c->regs[VCPU_REGS_RCX] & 0x8;
+ break;
+ case Src2ImmByte:
+ c->src2.type = OP_IMM;
+ c->src2.ptr = (unsigned long *)c->eip;
+ c->src2.bytes = 1;
+ c->src2.val = insn_fetch(u8, 1, c->eip);
+ break;
+ case Src2One:
+ c->src2.bytes = 1;
+ c->src2.val = 1;
+ break;
}
/* Decode and fetch the destination operand: register or memory. */
@@ -1100,20 +1135,33 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt)
c->regs[VCPU_REGS_RSP]);
}
-static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
- struct x86_emulate_ops *ops)
+static int emulate_pop(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
{
struct decode_cache *c = &ctxt->decode;
int rc;
- rc = ops->read_std(register_address(c, ss_base(ctxt),
- c->regs[VCPU_REGS_RSP]),
- &c->dst.val, c->dst.bytes, ctxt->vcpu);
+ rc = ops->read_emulated(register_address(c, ss_base(ctxt),
+ c->regs[VCPU_REGS_RSP]),
+ &c->src.val, c->src.bytes, ctxt->vcpu);
if (rc != 0)
return rc;
- register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->dst.bytes);
+ register_address_increment(c, &c->regs[VCPU_REGS_RSP], c->src.bytes);
+ return rc;
+}
+
+static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt,
+ struct x86_emulate_ops *ops)
+{
+ struct decode_cache *c = &ctxt->decode;
+ int rc;
+ c->src.bytes = c->dst.bytes;
+ rc = emulate_pop(ctxt, ops);
+ if (rc != 0)
+ return rc;
+ c->dst.val = c->src.val;
return 0;
}
@@ -1415,24 +1463,15 @@ special_insn:
emulate_1op("dec", c->dst, ctxt->eflags);
break;
case 0x50 ... 0x57: /* push reg */
- c->dst.type = OP_MEM;
- c->dst.bytes = c->op_bytes;
- c->dst.val = c->src.val;
- register_address_increment(c, &c->regs[VCPU_REGS_RSP],
- -c->op_bytes);
- c->dst.ptr = (void *) register_address(
- c, ss_base(ctxt), c->regs[VCPU_REGS_RSP]);
+ emulate_push(ctxt);
break;
case 0x58 ... 0x5f: /* pop reg */
pop_instruction:
- if ((rc = ops->read_std(register_address(c, ss_base(ctxt),
- c->regs[VCPU_REGS_RSP]), c->dst.ptr,
- c->op_bytes, ctxt->vcpu)) != 0)
+ c->src.bytes = c->op_bytes;
+ rc = emulate_pop(ctxt, ops);
+ if (rc != 0)
goto done;
-
- register_address_increment(c, &c->regs[VCPU_REGS_RSP],
- c->op_bytes);
- c->dst.type = OP_NONE; /* Disable writeback. */
+ c->dst.val = c->src.val;
break;
case 0x63: /* movsxd */
if (ctxt->mode != X86EMUL_MODE_PROT64)
@@ -1591,7 +1630,9 @@ special_insn:
emulate_push(ctxt);
break;
case 0x9d: /* popf */
+ c->dst.type = OP_REG;
c->dst.ptr = (unsigned long *) &ctxt->eflags;
+ c->dst.bytes = c->op_bytes;
goto pop_instruction;
case 0xa0 ... 0xa1: /* mov */
c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
@@ -1689,7 +1730,9 @@ special_insn:
emulate_grp2(ctxt);
break;
case 0xc3: /* ret */
+ c->dst.type = OP_REG;
c->dst.ptr = &c->eip;
+ c->dst.bytes = c->op_bytes;
goto pop_instruction;
case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
mov:
@@ -1778,7 +1821,7 @@ special_insn:
c->eip = saved_eip;
goto cannot_emulate;
}
- return 0;
+ break;
case 0xf4: /* hlt */
ctxt->vcpu->arch.halt_request = 1;
break;
@@ -1999,12 +2042,20 @@ twobyte_insn:
c->src.val &= (c->dst.bytes << 3) - 1;
emulate_2op_SrcV_nobyte("bt", c->src, c->dst, ctxt->eflags);
break;
+ case 0xa4: /* shld imm8, r, r/m */
+ case 0xa5: /* shld cl, r, r/m */
+ emulate_2op_cl("shld", c->src2, c->src, c->dst, ctxt->eflags);
+ break;
case 0xab:
bts: /* bts */
/* only subword offset */
c->src.val &= (c->dst.bytes << 3) - 1;
emulate_2op_SrcV_nobyte("bts", c->src, c->dst, ctxt->eflags);
break;
+ case 0xac: /* shrd imm8, r, r/m */
+ case 0xad: /* shrd cl, r, r/m */
+ emulate_2op_cl("shrd", c->src2, c->src, c->dst, ctxt->eflags);
+ break;
case 0xae: /* clflush */
break;
case 0xb0 ... 0xb1: /* cmpxchg */
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 50a779264bb1..92f1c6f3e19d 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -738,7 +738,7 @@ static void lguest_time_init(void)
/* We can't set cpumask in the initializer: damn C limitations! Set it
* here and register our timer device. */
- lguest_clockevent.cpumask = cpumask_of_cpu(0);
+ lguest_clockevent.cpumask = cpumask_of(0);
clockevents_register_device(&lguest_clockevent);
/* Finally, we unblock the timer interrupt. */
@@ -931,7 +931,7 @@ static void lguest_restart(char *reason)
* that we can fit comfortably.
*
* First we need assembly templates of each of the patchable Guest operations,
- * and these are in lguest_asm.S. */
+ * and these are in i386_head.S. */
/*G:060 We construct a table from the assembler templates: */
static const struct lguest_insns
@@ -1093,7 +1093,7 @@ __init void lguest_init(void)
acpi_ht = 0;
#endif
- /* We set the perferred console to "hvc". This is the "hypervisor
+ /* We set the preferred console to "hvc". This is the "hypervisor
* virtual console" driver written by the PowerPC people, which we also
* adapted for lguest's use. */
add_preferred_console("hvc", 0, NULL);
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 4a20b2f9a381..7c8ca91bb9ec 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -56,7 +56,7 @@ do { \
" jmp 2b\n" \
".previous\n" \
_ASM_EXTABLE(0b,3b) \
- : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
+ : "=&d"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \
"=&D" (__d2) \
: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
: "memory"); \
@@ -218,7 +218,7 @@ long strnlen_user(const char __user *s, long n)
" .align 4\n"
" .long 0b,2b\n"
".previous"
- :"=r" (n), "=D" (s), "=a" (res), "=c" (tmp)
+ :"=&r" (n), "=&D" (s), "=&a" (res), "=&c" (tmp)
:"0" (n), "1" (s), "2" (0), "3" (mask)
:"cc");
return res & mask;
diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c
index 64d6c84e6353..ec13cb5f17ed 100644
--- a/arch/x86/lib/usercopy_64.c
+++ b/arch/x86/lib/usercopy_64.c
@@ -32,7 +32,7 @@ do { \
" jmp 2b\n" \
".previous\n" \
_ASM_EXTABLE(0b,3b) \
- : "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
+ : "=&r"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \
"=&D" (__d2) \
: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
: "memory"); \
@@ -86,7 +86,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
".previous\n"
_ASM_EXTABLE(0b,3b)
_ASM_EXTABLE(1b,2b)
- : [size8] "=c"(size), [dst] "=&D" (__d0)
+ : [size8] "=&c"(size), [dst] "=&D" (__d0)
: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
[zero] "r" (0UL), [eight] "r" (8UL));
return size;
diff --git a/arch/x86/mach-default/setup.c b/arch/x86/mach-default/setup.c
index 37b9ae4d44c5..a265a7c63190 100644
--- a/arch/x86/mach-default/setup.c
+++ b/arch/x86/mach-default/setup.c
@@ -38,6 +38,15 @@ void __init pre_intr_init_hook(void)
init_ISA_irqs();
}
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
/**
* intr_init_hook - post gate setup interrupt initialisation
*
@@ -53,6 +62,9 @@ void __init intr_init_hook(void)
if (x86_quirks->arch_intr_init())
return;
}
+ if (!acpi_ioapic)
+ setup_irq(2, &irq2);
+
}
/**
@@ -133,29 +145,28 @@ void __init time_init_hook(void)
**/
void mca_nmi_hook(void)
{
- /* If I recall correctly, there's a whole bunch of other things that
+ /*
+ * If I recall correctly, there's a whole bunch of other things that
* we can do to check for NMI problems, but that's all I know about
* at the moment.
*/
-
- printk("NMI generated from unknown source!\n");
+ pr_warning("NMI generated from unknown source!\n");
}
#endif
static __init int no_ipi_broadcast(char *str)
{
get_option(&str, &no_broadcast);
- printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
- "IPI Broadcast");
+ pr_info("Using %s mode\n",
+ no_broadcast ? "No IPI Broadcast" : "IPI Broadcast");
return 1;
}
-
__setup("no_ipi_broadcast=", no_ipi_broadcast);
static int __init print_ipi_mode(void)
{
- printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
- "Shortcut");
+ pr_info("Using IPI %s mode\n",
+ no_broadcast ? "No-Shortcut" : "Shortcut");
return 0;
}
diff --git a/arch/x86/mach-generic/bigsmp.c b/arch/x86/mach-generic/bigsmp.c
index 3624a364b7f3..bc4c7840b2a8 100644
--- a/arch/x86/mach-generic/bigsmp.c
+++ b/arch/x86/mach-generic/bigsmp.c
@@ -42,9 +42,10 @@ static const struct dmi_system_id bigsmp_dmi_table[] = {
{ }
};
-static cpumask_t vector_allocation_domain(int cpu)
+static void vector_allocation_domain(int cpu, cpumask_t *retmask)
{
- return cpumask_of_cpu(cpu);
+ cpus_clear(*retmask);
+ cpu_set(cpu, *retmask);
}
static int probe_bigsmp(void)
diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c
index 7b4e6d0d1690..c2ded1448024 100644
--- a/arch/x86/mach-generic/es7000.c
+++ b/arch/x86/mach-generic/es7000.c
@@ -43,12 +43,12 @@ static void __init enable_apic_mode(void)
return;
}
-static __init int mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid)
+static __init int
+mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
{
- if (mpc->mpc_oemptr) {
- struct mp_config_oemtable *oem_table =
- (struct mp_config_oemtable *)mpc->mpc_oemptr;
+ if (mpc->oemptr) {
+ struct mpc_oemtable *oem_table =
+ (struct mpc_oemtable *)mpc->oemptr;
if (!strncmp(oem, "UNISYS", 6))
return parse_unisys_oem((char *)oem_table);
}
@@ -87,7 +87,7 @@ static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
}
#endif
-static cpumask_t vector_allocation_domain(int cpu)
+static void vector_allocation_domain(int cpu, cpumask_t *retmask)
{
/* Careful. Some cpus do not strictly honor the set of cpus
* specified in the interrupt destination when using lowest
@@ -97,8 +97,7 @@ static cpumask_t vector_allocation_domain(int cpu)
* deliver interrupts to the wrong hyperthread when only one
* hyperthread was specified in the interrupt desitination.
*/
- cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
- return domain;
+ *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } };
}
struct genapic __initdata_refok apic_es7000 = APIC_INIT("es7000", probe_es7000);
diff --git a/arch/x86/mach-generic/numaq.c b/arch/x86/mach-generic/numaq.c
index 71a309b122e6..3679e2255645 100644
--- a/arch/x86/mach-generic/numaq.c
+++ b/arch/x86/mach-generic/numaq.c
@@ -19,8 +19,7 @@
#include <asm/numaq/wakecpu.h>
#include <asm/numaq.h>
-static int mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid)
+static int mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
{
numaq_mps_oem_check(mpc, oem, productid);
return found_numaq;
@@ -38,7 +37,7 @@ static int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
return 0;
}
-static cpumask_t vector_allocation_domain(int cpu)
+static void vector_allocation_domain(int cpu, cpumask_t *retmask)
{
/* Careful. Some cpus do not strictly honor the set of cpus
* specified in the interrupt destination when using lowest
@@ -48,8 +47,7 @@ static cpumask_t vector_allocation_domain(int cpu)
* deliver interrupts to the wrong hyperthread when only one
* hyperthread was specified in the interrupt desitination.
*/
- cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
- return domain;
+ *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } };
}
struct genapic apic_numaq = APIC_INIT("NUMAQ", probe_numaq);
diff --git a/arch/x86/mach-generic/probe.c b/arch/x86/mach-generic/probe.c
index c346d9d0226f..15a38daef1a8 100644
--- a/arch/x86/mach-generic/probe.c
+++ b/arch/x86/mach-generic/probe.c
@@ -110,8 +110,7 @@ void __init generic_apic_probe(void)
/* These functions can switch the APIC even after the initial ->probe() */
-int __init mps_oem_check(struct mp_config_table *mpc, char *oem,
- char *productid)
+int __init mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
{
int i;
for (i = 0; apic_probe[i]; ++i) {
diff --git a/arch/x86/mach-generic/summit.c b/arch/x86/mach-generic/summit.c
index 2c6d234e0009..2821ffc188b5 100644
--- a/arch/x86/mach-generic/summit.c
+++ b/arch/x86/mach-generic/summit.c
@@ -24,7 +24,7 @@ static int probe_summit(void)
return 0;
}
-static cpumask_t vector_allocation_domain(int cpu)
+static void vector_allocation_domain(int cpu, cpumask_t *retmask)
{
/* Careful. Some cpus do not strictly honor the set of cpus
* specified in the interrupt destination when using lowest
@@ -34,8 +34,7 @@ static cpumask_t vector_allocation_domain(int cpu)
* deliver interrupts to the wrong hyperthread when only one
* hyperthread was specified in the interrupt desitination.
*/
- cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
- return domain;
+ *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } };
}
struct genapic apic_summit = APIC_INIT("summit", probe_summit);
diff --git a/arch/x86/mach-voyager/setup.c b/arch/x86/mach-voyager/setup.c
index a580b9562e76..d914a7996a66 100644
--- a/arch/x86/mach-voyager/setup.c
+++ b/arch/x86/mach-voyager/setup.c
@@ -33,13 +33,23 @@ void __init intr_init_hook(void)
setup_irq(2, &irq2);
}
-void __init pre_setup_arch_hook(void)
+static void voyager_disable_tsc(void)
{
/* Voyagers run their CPUs from independent clocks, so disable
* the TSC code because we can't sync them */
setup_clear_cpu_cap(X86_FEATURE_TSC);
}
+void __init pre_setup_arch_hook(void)
+{
+ voyager_disable_tsc();
+}
+
+void __init pre_time_init_hook(void)
+{
+ voyager_disable_tsc();
+}
+
void __init trap_init_hook(void)
{
}
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
index 52145007bd7e..7ffcdeec4631 100644
--- a/arch/x86/mach-voyager/voyager_smp.c
+++ b/arch/x86/mach-voyager/voyager_smp.c
@@ -63,11 +63,6 @@ static int voyager_extended_cpus = 1;
/* Used for the invalidate map that's also checked in the spinlock */
static volatile unsigned long smp_invalidate_needed;
-/* Bitmask of currently online CPUs - used by setup.c for
- /proc/cpuinfo, visible externally but still physical */
-cpumask_t cpu_online_map = CPU_MASK_NONE;
-EXPORT_SYMBOL(cpu_online_map);
-
/* Bitmask of CPUs present in the system - exported by i386_syms.c, used
* by scheduler but indexed physically */
cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
@@ -86,7 +81,7 @@ static void enable_local_vic_irq(unsigned int irq);
static void disable_local_vic_irq(unsigned int irq);
static void before_handle_vic_irq(unsigned int irq);
static void after_handle_vic_irq(unsigned int irq);
-static void set_vic_irq_affinity(unsigned int irq, cpumask_t mask);
+static void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask);
static void ack_vic_irq(unsigned int irq);
static void vic_enable_cpi(void);
static void do_boot_cpu(__u8 cpuid);
@@ -216,10 +211,6 @@ static __u32 cpu_booted_map;
static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
/* This is for the new dynamic CPU boot code */
-cpumask_t cpu_callin_map = CPU_MASK_NONE;
-cpumask_t cpu_callout_map = CPU_MASK_NONE;
-cpumask_t cpu_possible_map = CPU_MASK_NONE;
-EXPORT_SYMBOL(cpu_possible_map);
/* The per processor IRQ masks (these are usually kept in sync) */
static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
@@ -364,9 +355,8 @@ void __init find_smp_config(void)
printk("VOYAGER SMP: Boot cpu is %d\n", boot_cpu_id);
/* initialize the CPU structures (moved from smp_boot_cpus) */
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < nr_cpu_ids; i++)
cpu_irq_affinity[i] = ~0;
- }
cpu_online_map = cpumask_of_cpu(boot_cpu_id);
/* The boot CPU must be extended */
@@ -386,7 +376,7 @@ void __init find_smp_config(void)
cpus_addr(phys_cpu_present_map)[0] |=
voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
3) << 24;
- cpu_possible_map = phys_cpu_present_map;
+ init_cpu_possible(&phys_cpu_present_map);
printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
cpus_addr(phys_cpu_present_map)[0]);
/* Here we set up the VIC to enable SMP */
@@ -679,7 +669,7 @@ void __init smp_boot_cpus(void)
/* loop over all the extended VIC CPUs and boot them. The
* Quad CPUs must be bootstrapped by their extended VIC cpu */
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < nr_cpu_ids; i++) {
if (i == boot_cpu_id || !cpu_isset(i, phys_cpu_present_map))
continue;
do_boot_cpu(i);
@@ -1234,7 +1224,7 @@ int setup_profiling_timer(unsigned int multiplier)
* new values until the next timer interrupt in which they do process
* accounting.
*/
- for (i = 0; i < NR_CPUS; ++i)
+ for (i = 0; i < nr_cpu_ids; ++i)
per_cpu(prof_multiplier, i) = multiplier;
return 0;
@@ -1264,7 +1254,7 @@ void __init voyager_smp_intr_init(void)
int i;
/* initialize the per cpu irq mask to all disabled */
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < nr_cpu_ids; i++)
vic_irq_mask[i] = 0xFFFF;
VIC_SET_GATE(VIC_CPI_LEVEL0, vic_cpi_interrupt);
@@ -1607,16 +1597,16 @@ static void after_handle_vic_irq(unsigned int irq)
* change the mask and then do an interrupt enable CPI to re-enable on
* the selected processors */
-void set_vic_irq_affinity(unsigned int irq, cpumask_t mask)
+void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask)
{
/* Only extended processors handle interrupts */
unsigned long real_mask;
unsigned long irq_mask = 1 << irq;
int cpu;
- real_mask = cpus_addr(mask)[0] & voyager_extended_vic_processors;
+ real_mask = cpus_addr(*mask)[0] & voyager_extended_vic_processors;
- if (cpus_addr(mask)[0] == 0)
+ if (cpus_addr(*mask)[0] == 0)
/* can't have no CPUs to accept the interrupt -- extremely
* bad things will happen */
return;
@@ -1758,10 +1748,11 @@ static void __cpuinit voyager_smp_prepare_boot_cpu(void)
init_gdt(smp_processor_id());
switch_to_new_gdt();
- cpu_set(smp_processor_id(), cpu_online_map);
- cpu_set(smp_processor_id(), cpu_callout_map);
- cpu_set(smp_processor_id(), cpu_possible_map);
- cpu_set(smp_processor_id(), cpu_present_map);
+ cpu_online_map = cpumask_of_cpu(smp_processor_id());
+ cpu_callout_map = cpumask_of_cpu(smp_processor_id());
+ cpu_callin_map = CPU_MASK_NONE;
+ cpu_present_map = cpumask_of_cpu(smp_processor_id());
+
}
static int __cpuinit voyager_cpu_up(unsigned int cpu)
@@ -1791,9 +1782,9 @@ void __init smp_setup_processor_id(void)
x86_write_percpu(cpu_number, hard_smp_processor_id());
}
-static void voyager_send_call_func(cpumask_t callmask)
+static void voyager_send_call_func(const struct cpumask *callmask)
{
- __u32 mask = cpus_addr(callmask)[0] & ~(1 << smp_processor_id());
+ __u32 mask = cpus_addr(*callmask)[0] & ~(1 << smp_processor_id());
send_CPI(mask, VIC_CALL_FUNCTION_CPI);
}
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 57ec8c86a877..90dfae511a41 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -534,7 +534,7 @@ static int vmalloc_fault(unsigned long address)
happen within a race in page table update. In the later
case just flush. */
- pgd = pgd_offset(current->mm ?: &init_mm, address);
+ pgd = pgd_offset(current->active_mm, address);
pgd_ref = pgd_offset_k(address);
if (pgd_none(*pgd_ref))
return -1;
@@ -667,7 +667,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
if (unlikely(in_atomic() || !mm))
goto bad_area_nosemaphore;
-again:
/*
* When running in the kernel we expect faults to occur only to
* addresses in user space. All other faults represent errors in the
@@ -859,25 +858,14 @@ no_context:
oops_end(flags, regs, sig);
#endif
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
out_of_memory:
+ /*
+ * We ran out of memory, call the OOM killer, and return the userspace
+ * (which will retry the fault, or kill us if we got oom-killed).
+ */
up_read(&mm->mmap_sem);
- if (is_global_init(tsk)) {
- yield();
- /*
- * Re-lookup the vma - in theory the vma tree might
- * have changed:
- */
- goto again;
- }
-
- printk("VM: killing process %s\n", tsk->comm);
- if (error_code & PF_USER)
- do_group_exit(SIGKILL);
- goto no_context;
+ pagefault_out_of_memory();
+ return;
do_sigbus:
up_read(&mm->mmap_sem);
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 8655b5bb0963..2cef05074413 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -138,6 +138,47 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
return pte_offset_kernel(pmd, 0);
}
+static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
+ unsigned long vaddr, pte_t *lastpte)
+{
+#ifdef CONFIG_HIGHMEM
+ /*
+ * Something (early fixmap) may already have put a pte
+ * page here, which causes the page table allocation
+ * to become nonlinear. Attempt to fix it, and if it
+ * is still nonlinear then we have to bug.
+ */
+ int pmd_idx_kmap_begin = fix_to_virt(FIX_KMAP_END) >> PMD_SHIFT;
+ int pmd_idx_kmap_end = fix_to_virt(FIX_KMAP_BEGIN) >> PMD_SHIFT;
+
+ if (pmd_idx_kmap_begin != pmd_idx_kmap_end
+ && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
+ && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
+ && ((__pa(pte) >> PAGE_SHIFT) < table_start
+ || (__pa(pte) >> PAGE_SHIFT) >= table_end)) {
+ pte_t *newpte;
+ int i;
+
+ BUG_ON(after_init_bootmem);
+ newpte = alloc_low_page();
+ for (i = 0; i < PTRS_PER_PTE; i++)
+ set_pte(newpte + i, pte[i]);
+
+ paravirt_alloc_pte(&init_mm, __pa(newpte) >> PAGE_SHIFT);
+ set_pmd(pmd, __pmd(__pa(newpte)|_PAGE_TABLE));
+ BUG_ON(newpte != pte_offset_kernel(pmd, 0));
+ __flush_tlb_all();
+
+ paravirt_release_pte(__pa(pte) >> PAGE_SHIFT);
+ pte = newpte;
+ }
+ BUG_ON(vaddr < fix_to_virt(FIX_KMAP_BEGIN - 1)
+ && vaddr > fix_to_virt(FIX_KMAP_END)
+ && lastpte && lastpte + PTRS_PER_PTE != pte);
+#endif
+ return pte;
+}
+
/*
* This function initializes a certain range of kernel virtual memory
* with new bootmem page tables, everywhere page tables are missing in
@@ -154,6 +195,7 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base)
unsigned long vaddr;
pgd_t *pgd;
pmd_t *pmd;
+ pte_t *pte = NULL;
vaddr = start;
pgd_idx = pgd_index(vaddr);
@@ -165,7 +207,8 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base)
pmd = pmd + pmd_index(vaddr);
for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end);
pmd++, pmd_idx++) {
- one_page_table_init(pmd);
+ pte = page_table_kmap_check(one_page_table_init(pmd),
+ pmd, vaddr, pte);
vaddr += PMD_SIZE;
}
@@ -328,6 +371,8 @@ int devmem_is_allowed(unsigned long pagenr)
{
if (pagenr <= 256)
return 1;
+ if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+ return 0;
if (!page_is_ram(pagenr))
return 1;
return 0;
@@ -435,8 +480,12 @@ static void __init set_highmem_pages_init(void)
#endif /* !CONFIG_NUMA */
#else
-# define permanent_kmaps_init(pgd_base) do { } while (0)
-# define set_highmem_pages_init() do { } while (0)
+static inline void permanent_kmaps_init(pgd_t *pgd_base)
+{
+}
+static inline void set_highmem_pages_init(void)
+{
+}
#endif /* CONFIG_HIGHMEM */
void __init native_pagetable_setup_start(pgd_t *base)
@@ -502,7 +551,6 @@ static void __init early_ioremap_page_table_range_init(pgd_t *pgd_base)
* Fixed mappings, only the page table structure has to be
* created - mappings will be set by set_fixmap():
*/
- early_ioremap_clear();
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
page_table_range_init(vaddr, end, pgd_base);
@@ -795,7 +843,7 @@ static void __init find_early_table_space(unsigned long end, int use_pse)
tables += PAGE_ALIGN(ptes * sizeof(pte_t));
/* for fixmap */
- tables += PAGE_SIZE * 2;
+ tables += PAGE_ALIGN(__end_of_fixed_addresses * sizeof(pte_t));
/*
* RED-PEN putting page tables only on node 0 could
@@ -1075,7 +1123,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
- return __add_pages(zone, start_pfn, nr_pages);
+ return __add_pages(nid, zone, start_pfn, nr_pages);
}
#endif
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 9f7a0d24d42a..e6d36b490250 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -596,7 +596,7 @@ static void __init init_gbpages(void)
direct_gbpages = 0;
}
-static unsigned long __init kernel_physical_mapping_init(unsigned long start,
+static unsigned long __meminit kernel_physical_mapping_init(unsigned long start,
unsigned long end,
unsigned long page_size_mask)
{
@@ -857,7 +857,7 @@ int arch_add_memory(int nid, u64 start, u64 size)
if (last_mapped_pfn > max_pfn_mapped)
max_pfn_mapped = last_mapped_pfn;
- ret = __add_pages(zone, start_pfn, nr_pages);
+ ret = __add_pages(nid, zone, start_pfn, nr_pages);
WARN_ON_ONCE(ret);
return ret;
@@ -888,6 +888,8 @@ int devmem_is_allowed(unsigned long pagenr)
{
if (pagenr <= 256)
return 1;
+ if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
+ return 0;
if (!page_is_ram(pagenr))
return 1;
return 0;
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c
index d0151d8ce452..ca53224fc56c 100644
--- a/arch/x86/mm/iomap_32.c
+++ b/arch/x86/mm/iomap_32.c
@@ -17,6 +17,7 @@
*/
#include <asm/iomap.h>
+#include <asm/pat.h>
#include <linux/module.h>
/* Map 'pfn' using fixed map 'type' and protections 'prot'
@@ -29,6 +30,15 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
pagefault_disable();
+ /*
+ * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
+ * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the
+ * MTRR is UC or WC. UC_MINUS gets the real intention, of the
+ * user, which is "WC if the MTRR is WC, UC if you can't do that."
+ */
+ if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
+ prot = PAGE_KERNEL_UC_MINUS;
+
idx = type + KM_TYPE_NR*smp_processor_id();
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
set_pte(kmap_pte-idx, pfn_pte(pfn, prot));
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index bd85d42819e1..af750ab973b6 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -557,34 +557,9 @@ void __init early_ioremap_init(void)
}
}
-void __init early_ioremap_clear(void)
-{
- pmd_t *pmd;
-
- if (early_ioremap_debug)
- printk(KERN_INFO "early_ioremap_clear()\n");
-
- pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
- pmd_clear(pmd);
- paravirt_release_pte(__pa(bm_pte) >> PAGE_SHIFT);
- __flush_tlb_all();
-}
-
void __init early_ioremap_reset(void)
{
- enum fixed_addresses idx;
- unsigned long addr, phys;
- pte_t *pte;
-
after_paging_init = 1;
- for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
- addr = fix_to_virt(idx);
- pte = early_ioremap_pte(addr);
- if (pte_present(*pte)) {
- phys = pte_val(*pte) & PAGE_MASK;
- set_fixmap(idx, phys);
- }
- }
}
static void __init __early_set_fixmap(enum fixed_addresses idx,
diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c
index 41f1b5c00a1d..268f8255280f 100644
--- a/arch/x86/mm/k8topology_64.c
+++ b/arch/x86/mm/k8topology_64.c
@@ -81,7 +81,6 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
unsigned numnodes, cores, bits, apicid_base;
unsigned long prevbase;
struct bootnode nodes[8];
- unsigned char nodeids[8];
int i, j, nb, found = 0;
u32 nodeid, reg;
@@ -110,7 +109,6 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
limit = read_pci_config(0, nb, 1, 0x44 + i*8);
nodeid = limit & 7;
- nodeids[i] = nodeid;
if ((base & 3) == 0) {
if (i < numnodes)
printk("Skipping disabled node %d\n", i);
@@ -179,9 +177,6 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
nodes[nodeid].start = base;
nodes[nodeid].end = limit;
- e820_register_active_regions(nodeid,
- nodes[nodeid].start >> PAGE_SHIFT,
- nodes[nodeid].end >> PAGE_SHIFT);
prevbase = base;
@@ -211,12 +206,15 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
}
for (i = 0; i < 8; i++) {
- if (nodes[i].start != nodes[i].end) {
- nodeid = nodeids[i];
- for (j = apicid_base; j < cores + apicid_base; j++)
- apicid_to_node[(nodeid << bits) + j] = i;
- setup_node_bootmem(i, nodes[i].start, nodes[i].end);
- }
+ if (nodes[i].start == nodes[i].end)
+ continue;
+
+ e820_register_active_regions(i,
+ nodes[i].start >> PAGE_SHIFT,
+ nodes[i].end >> PAGE_SHIFT);
+ for (j = apicid_base; j < cores + apicid_base; j++)
+ apicid_to_node[(i << bits) + j] = i;
+ setup_node_bootmem(i, nodes[i].start, nodes[i].end);
}
numa_init_array();
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 8518c678d83f..d1f7439d173c 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -239,7 +239,7 @@ void resume_map_numa_kva(pgd_t *pgd_base)
start_pfn = node_remap_start_pfn[node];
size = node_remap_size[node];
- printk(KERN_DEBUG "%s: node %d\n", __FUNCTION__, node);
+ printk(KERN_DEBUG "%s: node %d\n", __func__, node);
for (pfn = 0; pfn < size; pfn += PTRS_PER_PTE) {
unsigned long vaddr = start_va + (pfn << PAGE_SHIFT);
@@ -251,7 +251,7 @@ void resume_map_numa_kva(pgd_t *pgd_base)
PAGE_KERNEL_LARGE_EXEC));
printk(KERN_DEBUG "%s: %08lx -> pfn %08lx\n",
- __FUNCTION__, vaddr, start_pfn + pfn);
+ __func__, vaddr, start_pfn + pfn);
}
}
}
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index cebcbf152d46..71a14f89f89e 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -278,7 +278,7 @@ void __init numa_init_array(void)
int rr, i;
rr = first_node(node_online_map);
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < nr_cpu_ids; i++) {
if (early_cpu_to_node(i) != NUMA_NO_NODE)
continue;
numa_set_node(i, rr);
@@ -549,7 +549,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn)
memnodemap[0] = 0;
node_set_online(0);
node_set(0, node_possible_map);
- for (i = 0; i < NR_CPUS; i++)
+ for (i = 0; i < nr_cpu_ids; i++)
numa_set_node(i, 0);
e820_register_active_regions(0, start_pfn, last_pfn);
setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index e89d24815f26..84ba74820ad6 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -534,6 +534,36 @@ out_unlock:
return 0;
}
+static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
+ int primary)
+{
+ /*
+ * Ignore all non primary paths.
+ */
+ if (!primary)
+ return 0;
+
+ /*
+ * Ignore the NULL PTE for kernel identity mapping, as it is expected
+ * to have holes.
+ * Also set numpages to '1' indicating that we processed cpa req for
+ * one virtual address page and its pfn. TBD: numpages can be set based
+ * on the initial value and the level returned by lookup_address().
+ */
+ if (within(vaddr, PAGE_OFFSET,
+ PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))) {
+ cpa->numpages = 1;
+ cpa->pfn = __pa(vaddr) >> PAGE_SHIFT;
+ return 0;
+ } else {
+ WARN(1, KERN_WARNING "CPA: called for zero pte. "
+ "vaddr = %lx cpa->vaddr = %lx\n", vaddr,
+ *cpa->vaddr);
+
+ return -EFAULT;
+ }
+}
+
static int __change_page_attr(struct cpa_data *cpa, int primary)
{
unsigned long address;
@@ -549,17 +579,11 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
repeat:
kpte = lookup_address(address, &level);
if (!kpte)
- return 0;
+ return __cpa_process_fault(cpa, address, primary);
old_pte = *kpte;
- if (!pte_val(old_pte)) {
- if (!primary)
- return 0;
- WARN(1, KERN_WARNING "CPA: called for zero pte. "
- "vaddr = %lx cpa->vaddr = %lx\n", address,
- *cpa->vaddr);
- return -EINVAL;
- }
+ if (!pte_val(old_pte))
+ return __cpa_process_fault(cpa, address, primary);
if (level == PG_LEVEL_4K) {
pte_t new_pte;
@@ -657,12 +681,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
vaddr = *cpa->vaddr;
if (!(within(vaddr, PAGE_OFFSET,
- PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT))
-#ifdef CONFIG_X86_64
- || within(vaddr, PAGE_OFFSET + (1UL<<32),
- PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT))
-#endif
- )) {
+ PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) {
alias_cpa = *cpa;
temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 85cbd3cd3723..7b61036427df 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -333,11 +333,23 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
req_type & _PAGE_CACHE_MASK);
}
- is_range_ram = pagerange_is_ram(start, end);
- if (is_range_ram == 1)
- return reserve_ram_pages_type(start, end, req_type, new_type);
- else if (is_range_ram < 0)
- return -EINVAL;
+ if (new_type)
+ *new_type = actual_type;
+
+ /*
+ * For legacy reasons, some parts of the physical address range in the
+ * legacy 1MB region is treated as non-RAM (even when listed as RAM in
+ * the e820 tables). So we will track the memory attributes of this
+ * legacy 1MB region using the linear memtype_list always.
+ */
+ if (end >= ISA_END_ADDRESS) {
+ is_range_ram = pagerange_is_ram(start, end);
+ if (is_range_ram == 1)
+ return reserve_ram_pages_type(start, end, req_type,
+ new_type);
+ else if (is_range_ram < 0)
+ return -EINVAL;
+ }
new = kmalloc(sizeof(struct memtype), GFP_KERNEL);
if (!new)
@@ -347,9 +359,6 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
new->end = end;
new->type = actual_type;
- if (new_type)
- *new_type = actual_type;
-
spin_lock(&memtype_lock);
if (cached_entry && start >= cached_start)
@@ -437,11 +446,19 @@ int free_memtype(u64 start, u64 end)
if (is_ISA_range(start, end - 1))
return 0;
- is_range_ram = pagerange_is_ram(start, end);
- if (is_range_ram == 1)
- return free_ram_pages_type(start, end);
- else if (is_range_ram < 0)
- return -EINVAL;
+ /*
+ * For legacy reasons, some parts of the physical address range in the
+ * legacy 1MB region is treated as non-RAM (even when listed as RAM in
+ * the e820 tables). So we will track the memory attributes of this
+ * legacy 1MB region using the linear memtype_list always.
+ */
+ if (end >= ISA_END_ADDRESS) {
+ is_range_ram = pagerange_is_ram(start, end);
+ if (is_range_ram == 1)
+ return free_ram_pages_type(start, end);
+ else if (is_range_ram < 0)
+ return -EINVAL;
+ }
spin_lock(&memtype_lock);
list_for_each_entry(entry, &memtype_list, nd) {
@@ -601,12 +618,13 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
* Reserved non RAM regions only and after successful reserve_memtype,
* this func also keeps identity mapping (if any) in sync with this new prot.
*/
-static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t vma_prot)
+static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
+ int strict_prot)
{
int is_ram = 0;
int id_sz, ret;
unsigned long flags;
- unsigned long want_flags = (pgprot_val(vma_prot) & _PAGE_CACHE_MASK);
+ unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
is_ram = pagerange_is_ram(paddr, paddr + size);
@@ -625,15 +643,24 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t vma_prot)
return ret;
if (flags != want_flags) {
- free_memtype(paddr, paddr + size);
- printk(KERN_ERR
- "%s:%d map pfn expected mapping type %s for %Lx-%Lx, got %s\n",
- current->comm, current->pid,
- cattr_name(want_flags),
- (unsigned long long)paddr,
- (unsigned long long)(paddr + size),
- cattr_name(flags));
- return -EINVAL;
+ if (strict_prot || !is_new_memtype_allowed(want_flags, flags)) {
+ free_memtype(paddr, paddr + size);
+ printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
+ " for %Lx-%Lx, got %s\n",
+ current->comm, current->pid,
+ cattr_name(want_flags),
+ (unsigned long long)paddr,
+ (unsigned long long)(paddr + size),
+ cattr_name(flags));
+ return -EINVAL;
+ }
+ /*
+ * We allow returning different type than the one requested in
+ * non strict case.
+ */
+ *vma_prot = __pgprot((pgprot_val(*vma_prot) &
+ (~_PAGE_CACHE_MASK)) |
+ flags);
}
/* Need to keep identity mapping in sync */
@@ -689,6 +716,7 @@ int track_pfn_vma_copy(struct vm_area_struct *vma)
unsigned long vma_start = vma->vm_start;
unsigned long vma_end = vma->vm_end;
unsigned long vma_size = vma_end - vma_start;
+ pgprot_t pgprot;
if (!pat_enabled)
return 0;
@@ -702,7 +730,8 @@ int track_pfn_vma_copy(struct vm_area_struct *vma)
WARN_ON_ONCE(1);
return -EINVAL;
}
- return reserve_pfn_range(paddr, vma_size, __pgprot(prot));
+ pgprot = __pgprot(prot);
+ return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
}
/* reserve entire vma page by page, using pfn and prot from pte */
@@ -710,7 +739,8 @@ int track_pfn_vma_copy(struct vm_area_struct *vma)
if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
continue;
- retval = reserve_pfn_range(paddr, PAGE_SIZE, __pgprot(prot));
+ pgprot = __pgprot(prot);
+ retval = reserve_pfn_range(paddr, PAGE_SIZE, &pgprot, 1);
if (retval)
goto cleanup_ret;
}
@@ -741,7 +771,7 @@ cleanup_ret:
* Note that this function can be called with caller trying to map only a
* subrange/page inside the vma.
*/
-int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t prot,
+int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
unsigned long pfn, unsigned long size)
{
int retval = 0;
@@ -758,14 +788,14 @@ int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t prot,
if (is_linear_pfn_mapping(vma)) {
/* reserve the whole chunk starting from vm_pgoff */
paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
- return reserve_pfn_range(paddr, vma_size, prot);
+ return reserve_pfn_range(paddr, vma_size, prot, 0);
}
/* reserve page by page using pfn and size */
base_paddr = (resource_size_t)pfn << PAGE_SHIFT;
for (i = 0; i < size; i += PAGE_SIZE) {
paddr = base_paddr + i;
- retval = reserve_pfn_range(paddr, PAGE_SIZE, prot);
+ retval = reserve_pfn_range(paddr, PAGE_SIZE, prot, 0);
if (retval)
goto cleanup_ret;
}
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index 51c0a2fc14fe..09737c8af074 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -382,7 +382,7 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end)
if (!node_online(i))
setup_node_bootmem(i, nodes[i].start, nodes[i].end);
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < nr_cpu_ids; i++) {
int node = early_cpu_to_node(i);
if (node == NUMA_NO_NODE)
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
index 98658f25f542..8fdf06e4edf9 100644
--- a/arch/x86/oprofile/op_model_amd.c
+++ b/arch/x86/oprofile/op_model_amd.c
@@ -2,7 +2,7 @@
* @file op_model_amd.c
* athlon / K7 / K8 / Family 10h model-specific MSR operations
*
- * @remark Copyright 2002-2008 OProfile authors
+ * @remark Copyright 2002-2009 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon
@@ -10,7 +10,7 @@
* @author Graydon Hoare
* @author Robert Richter <robert.richter@amd.com>
* @author Barry Kasindorf
-*/
+ */
#include <linux/oprofile.h>
#include <linux/device.h>
@@ -60,53 +60,10 @@ static unsigned long reset_value[NUM_COUNTERS];
#define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */
#define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */
-/* Codes used in cpu_buffer.c */
-/* This produces duplicate code, need to be fixed */
-#define IBS_FETCH_BEGIN 3
-#define IBS_OP_BEGIN 4
-
-/*
- * The function interface needs to be fixed, something like add
- * data. Should then be added to linux/oprofile.h.
- */
-extern void
-oprofile_add_ibs_sample(struct pt_regs * const regs,
- unsigned int * const ibs_sample, int ibs_code);
-
-struct ibs_fetch_sample {
- /* MSRC001_1031 IBS Fetch Linear Address Register */
- unsigned int ibs_fetch_lin_addr_low;
- unsigned int ibs_fetch_lin_addr_high;
- /* MSRC001_1030 IBS Fetch Control Register */
- unsigned int ibs_fetch_ctl_low;
- unsigned int ibs_fetch_ctl_high;
- /* MSRC001_1032 IBS Fetch Physical Address Register */
- unsigned int ibs_fetch_phys_addr_low;
- unsigned int ibs_fetch_phys_addr_high;
-};
-
-struct ibs_op_sample {
- /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */
- unsigned int ibs_op_rip_low;
- unsigned int ibs_op_rip_high;
- /* MSRC001_1035 IBS Op Data Register */
- unsigned int ibs_op_data1_low;
- unsigned int ibs_op_data1_high;
- /* MSRC001_1036 IBS Op Data 2 Register */
- unsigned int ibs_op_data2_low;
- unsigned int ibs_op_data2_high;
- /* MSRC001_1037 IBS Op Data 3 Register */
- unsigned int ibs_op_data3_low;
- unsigned int ibs_op_data3_high;
- /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */
- unsigned int ibs_dc_linear_low;
- unsigned int ibs_dc_linear_high;
- /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */
- unsigned int ibs_dc_phys_low;
- unsigned int ibs_dc_phys_high;
-};
+#define IBS_FETCH_SIZE 6
+#define IBS_OP_SIZE 12
-static int ibs_allowed; /* AMD Family10h and later */
+static int has_ibs; /* AMD Family10h and later */
struct op_ibs_config {
unsigned long op_enabled;
@@ -197,31 +154,29 @@ static inline int
op_amd_handle_ibs(struct pt_regs * const regs,
struct op_msrs const * const msrs)
{
- unsigned int low, high;
- struct ibs_fetch_sample ibs_fetch;
- struct ibs_op_sample ibs_op;
+ u32 low, high;
+ u64 msr;
+ struct op_entry entry;
- if (!ibs_allowed)
+ if (!has_ibs)
return 1;
if (ibs_config.fetch_enabled) {
rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);
if (high & IBS_FETCH_HIGH_VALID_BIT) {
- ibs_fetch.ibs_fetch_ctl_high = high;
- ibs_fetch.ibs_fetch_ctl_low = low;
- rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high);
- ibs_fetch.ibs_fetch_lin_addr_high = high;
- ibs_fetch.ibs_fetch_lin_addr_low = low;
- rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high);
- ibs_fetch.ibs_fetch_phys_addr_high = high;
- ibs_fetch.ibs_fetch_phys_addr_low = low;
-
- oprofile_add_ibs_sample(regs,
- (unsigned int *)&ibs_fetch,
- IBS_FETCH_BEGIN);
+ rdmsrl(MSR_AMD64_IBSFETCHLINAD, msr);
+ oprofile_write_reserve(&entry, regs, msr,
+ IBS_FETCH_CODE, IBS_FETCH_SIZE);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ oprofile_add_data(&entry, low);
+ oprofile_add_data(&entry, high);
+ rdmsrl(MSR_AMD64_IBSFETCHPHYSAD, msr);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ oprofile_write_commit(&entry);
/* reenable the IRQ */
- rdmsr(MSR_AMD64_IBSFETCHCTL, low, high);
high &= ~IBS_FETCH_HIGH_VALID_BIT;
high |= IBS_FETCH_HIGH_ENABLE;
low &= IBS_FETCH_LOW_MAX_CNT_MASK;
@@ -232,30 +187,29 @@ op_amd_handle_ibs(struct pt_regs * const regs,
if (ibs_config.op_enabled) {
rdmsr(MSR_AMD64_IBSOPCTL, low, high);
if (low & IBS_OP_LOW_VALID_BIT) {
- rdmsr(MSR_AMD64_IBSOPRIP, low, high);
- ibs_op.ibs_op_rip_low = low;
- ibs_op.ibs_op_rip_high = high;
- rdmsr(MSR_AMD64_IBSOPDATA, low, high);
- ibs_op.ibs_op_data1_low = low;
- ibs_op.ibs_op_data1_high = high;
- rdmsr(MSR_AMD64_IBSOPDATA2, low, high);
- ibs_op.ibs_op_data2_low = low;
- ibs_op.ibs_op_data2_high = high;
- rdmsr(MSR_AMD64_IBSOPDATA3, low, high);
- ibs_op.ibs_op_data3_low = low;
- ibs_op.ibs_op_data3_high = high;
- rdmsr(MSR_AMD64_IBSDCLINAD, low, high);
- ibs_op.ibs_dc_linear_low = low;
- ibs_op.ibs_dc_linear_high = high;
- rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high);
- ibs_op.ibs_dc_phys_low = low;
- ibs_op.ibs_dc_phys_high = high;
+ rdmsrl(MSR_AMD64_IBSOPRIP, msr);
+ oprofile_write_reserve(&entry, regs, msr,
+ IBS_OP_CODE, IBS_OP_SIZE);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ rdmsrl(MSR_AMD64_IBSOPDATA, msr);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ rdmsrl(MSR_AMD64_IBSOPDATA2, msr);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ rdmsrl(MSR_AMD64_IBSOPDATA3, msr);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ rdmsrl(MSR_AMD64_IBSDCLINAD, msr);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ rdmsrl(MSR_AMD64_IBSDCPHYSAD, msr);
+ oprofile_add_data(&entry, (u32)msr);
+ oprofile_add_data(&entry, (u32)(msr >> 32));
+ oprofile_write_commit(&entry);
/* reenable the IRQ */
- oprofile_add_ibs_sample(regs,
- (unsigned int *)&ibs_op,
- IBS_OP_BEGIN);
- rdmsr(MSR_AMD64_IBSOPCTL, low, high);
high = 0;
low &= ~IBS_OP_LOW_VALID_BIT;
low |= IBS_OP_LOW_ENABLE;
@@ -305,14 +259,14 @@ static void op_amd_start(struct op_msrs const * const msrs)
}
#ifdef CONFIG_OPROFILE_IBS
- if (ibs_allowed && ibs_config.fetch_enabled) {
+ if (has_ibs && ibs_config.fetch_enabled) {
low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF;
high = ((ibs_config.rand_en & 0x1) << 25) /* bit 57 */
+ IBS_FETCH_HIGH_ENABLE;
wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);
}
- if (ibs_allowed && ibs_config.op_enabled) {
+ if (has_ibs && ibs_config.op_enabled) {
low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF)
+ ((ibs_config.dispatched_ops & 0x1) << 19) /* bit 19 */
+ IBS_OP_LOW_ENABLE;
@@ -341,14 +295,14 @@ static void op_amd_stop(struct op_msrs const * const msrs)
}
#ifdef CONFIG_OPROFILE_IBS
- if (ibs_allowed && ibs_config.fetch_enabled) {
+ if (has_ibs && ibs_config.fetch_enabled) {
/* clear max count and enable */
low = 0;
high = 0;
wrmsr(MSR_AMD64_IBSFETCHCTL, low, high);
}
- if (ibs_allowed && ibs_config.op_enabled) {
+ if (has_ibs && ibs_config.op_enabled) {
/* clear max count and enable */
low = 0;
high = 0;
@@ -409,6 +363,7 @@ static int init_ibs_nmi(void)
| IBSCTL_LVTOFFSETVAL);
pci_read_config_dword(cpu_cfg, IBSCTL, &value);
if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) {
+ pci_dev_put(cpu_cfg);
printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
"IBSCTL = 0x%08x", value);
return 1;
@@ -436,20 +391,20 @@ static int init_ibs_nmi(void)
/* uninitialize the APIC for the IBS interrupts if needed */
static void clear_ibs_nmi(void)
{
- if (ibs_allowed)
+ if (has_ibs)
on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1);
}
/* initialize the APIC for the IBS interrupts if available */
static void ibs_init(void)
{
- ibs_allowed = boot_cpu_has(X86_FEATURE_IBS);
+ has_ibs = boot_cpu_has(X86_FEATURE_IBS);
- if (!ibs_allowed)
+ if (!has_ibs)
return;
if (init_ibs_nmi()) {
- ibs_allowed = 0;
+ has_ibs = 0;
return;
}
@@ -458,7 +413,7 @@ static void ibs_init(void)
static void ibs_exit(void)
{
- if (!ibs_allowed)
+ if (!has_ibs)
return;
clear_ibs_nmi();
@@ -478,7 +433,7 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root)
if (ret)
return ret;
- if (!ibs_allowed)
+ if (!has_ibs)
return ret;
/* model specific files */
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 1d88d2b39771..c0ecf250fe51 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -4,7 +4,7 @@
#include <linux/irq.h>
#include <linux/dmi.h>
#include <asm/numa.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
struct pci_root_info {
char *name;
@@ -210,11 +210,10 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
if (bus && node != -1) {
#ifdef CONFIG_ACPI_NUMA
if (pxm >= 0)
- printk(KERN_DEBUG "bus %02x -> pxm %d -> node %d\n",
- busnum, pxm, node);
+ dev_printk(KERN_DEBUG, &bus->dev,
+ "on NUMA node %d (pxm %d)\n", node, pxm);
#else
- printk(KERN_DEBUG "bus %02x -> node %d\n",
- busnum, node);
+ dev_printk(KERN_DEBUG, &bus->dev, "on NUMA node %d\n", node);
#endif
}
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 22e057665e55..9bb09823b362 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -2,7 +2,7 @@
#include <linux/pci.h>
#include <linux/topology.h>
#include <linux/cpu.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
#ifdef CONFIG_X86_64
#include <asm/pci-direct.h>
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index bb1a01f089e2..82d22fc601ae 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -14,8 +14,7 @@
#include <asm/segment.h>
#include <asm/io.h>
#include <asm/smp.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF;
@@ -552,17 +551,25 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
if ((err = pci_enable_resources(dev, mask)) < 0)
return err;
- if (!dev->msi_enabled)
+ if (!pci_dev_msi_enabled(dev))
return pcibios_enable_irq(dev);
return 0;
}
void pcibios_disable_device (struct pci_dev *dev)
{
- if (!dev->msi_enabled && pcibios_disable_irq)
+ if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
pcibios_disable_irq(dev);
}
+int pci_ext_cfg_avail(struct pci_dev *dev)
+{
+ if (raw_pci_ext_ops)
+ return 1;
+ else
+ return 0;
+}
+
struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
{
struct pci_bus *bus = NULL;
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
index 9a5af6c8fbe9..bd13c3e4c6db 100644
--- a/arch/x86/pci/direct.c
+++ b/arch/x86/pci/direct.c
@@ -5,7 +5,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/dmi.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
/*
* Functions for accessing PCI base (first 256 bytes) and extended
diff --git a/arch/x86/pci/early.c b/arch/x86/pci/early.c
index 86631ccbc25a..f6adf2c6d751 100644
--- a/arch/x86/pci/early.c
+++ b/arch/x86/pci/early.c
@@ -2,7 +2,7 @@
#include <linux/pci.h>
#include <asm/pci-direct.h>
#include <asm/io.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
/* Direct PCI access. This is used for PCI accesses in early boot before
the PCI subsystem works. */
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 2051dc96b8e9..7d388d5cf548 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -6,8 +6,7 @@
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/init.h>
-#include "pci.h"
-
+#include <asm/pci_x86.h>
static void __devinit pci_fixup_i450nx(struct pci_dev *d)
{
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 844df0cbbd3e..5ead808dd70c 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -34,8 +34,8 @@
#include <asm/pat.h>
#include <asm/e820.h>
+#include <asm/pci_x86.h>
-#include "pci.h"
static int
skip_isa_ioresource_align(struct pci_dev *dev) {
@@ -129,7 +129,7 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
pr = pci_find_parent_resource(dev, r);
if (!r->start || !pr ||
request_resource(pr, r) < 0) {
- dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx);
+ dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx);
/*
* Something is wrong with the region.
* Invalidate the resource to prevent
@@ -170,7 +170,7 @@ static void __init pcibios_allocate_resources(int pass)
r->flags, disabled, pass);
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) {
- dev_err(&dev->dev, "BAR %d: can't allocate resource\n", idx);
+ dev_info(&dev->dev, "BAR %d: can't allocate resource\n", idx);
/* We'll assign a new address later */
r->end -= r->start;
r->start = 0;
@@ -314,17 +314,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
return retval;
if (flags != new_flags) {
- /*
- * Do not fallback to certain memory types with certain
- * requested type:
- * - request is uncached, return cannot be write-back
- * - request is uncached, return cannot be write-combine
- * - request is write-combine, return cannot be write-back
- */
- if ((flags == _PAGE_CACHE_UC_MINUS &&
- (new_flags == _PAGE_CACHE_WB)) ||
- (flags == _PAGE_CACHE_WC &&
- new_flags == _PAGE_CACHE_WB)) {
+ if (!is_new_memtype_allowed(flags, new_flags)) {
free_memtype(addr, addr+len);
return -EINVAL;
}
diff --git a/arch/x86/pci/init.c b/arch/x86/pci/init.c
index d6c950f81858..25a1f8efed4a 100644
--- a/arch/x86/pci/init.c
+++ b/arch/x86/pci/init.c
@@ -1,6 +1,6 @@
#include <linux/pci.h>
#include <linux/init.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
/* arch_initcall has too random ordering, so call the initializers
in the right sequence from here. */
@@ -12,7 +12,8 @@ static __init int pci_arch_init(void)
type = pci_direct_probe();
#endif
- pci_mmcfg_early_init();
+ if (!(pci_probe & PCI_PROBE_NOEARLY))
+ pci_mmcfg_early_init();
#ifdef CONFIG_PCI_OLPC
if (!pci_olpc_init())
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index bf69dbe08bff..fecbce6e7d7c 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -16,8 +16,7 @@
#include <asm/io_apic.h>
#include <linux/irq.h>
#include <linux/acpi.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
#define PIRQ_VERSION 0x0100
@@ -534,7 +533,7 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
{
struct pci_dev *bridge;
int pin = pci_get_interrupt_pin(dev, &bridge);
- return pcibios_set_irq_routing(bridge, pin, irq);
+ return pcibios_set_irq_routing(bridge, pin - 1, irq);
}
#endif
@@ -573,6 +572,7 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
case PCI_DEVICE_ID_INTEL_ICH7_1:
case PCI_DEVICE_ID_INTEL_ICH7_30:
case PCI_DEVICE_ID_INTEL_ICH7_31:
+ case PCI_DEVICE_ID_INTEL_TGP_LPC:
case PCI_DEVICE_ID_INTEL_ESB2_0:
case PCI_DEVICE_ID_INTEL_ICH8_0:
case PCI_DEVICE_ID_INTEL_ICH8_1:
@@ -888,7 +888,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
dev_dbg(&dev->dev, "no interrupt pin\n");
return 0;
}
- pin = pin - 1;
/* Find IRQ routing entry */
@@ -898,17 +897,17 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
info = pirq_get_info(dev);
if (!info) {
dev_dbg(&dev->dev, "PCI INT %c not found in routing table\n",
- 'A' + pin);
+ 'A' + pin - 1);
return 0;
}
- pirq = info->irq[pin].link;
- mask = info->irq[pin].bitmap;
+ pirq = info->irq[pin - 1].link;
+ mask = info->irq[pin - 1].bitmap;
if (!pirq) {
- dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin);
+ dev_dbg(&dev->dev, "PCI INT %c not routed\n", 'A' + pin - 1);
return 0;
}
dev_dbg(&dev->dev, "PCI INT %c -> PIRQ %02x, mask %04x, excl %04x",
- 'A' + pin, pirq, mask, pirq_table->exclusive_irqs);
+ 'A' + pin - 1, pirq, mask, pirq_table->exclusive_irqs);
mask &= pcibios_irq_mask;
/* Work around broken HP Pavilion Notebooks which assign USB to
@@ -950,7 +949,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
newirq = i;
}
}
- dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin, newirq);
+ dev_dbg(&dev->dev, "PCI INT %c -> newirq %d", 'A' + pin - 1, newirq);
/* Check if it is hardcoded */
if ((pirq & 0xf0) == 0xf0) {
@@ -978,18 +977,18 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
return 0;
}
}
- dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin, irq);
+ dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq);
/* Update IRQ for all devices with the same pirq value */
while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
if (!pin)
continue;
- pin--;
+
info = pirq_get_info(dev2);
if (!info)
continue;
- if (info->irq[pin].link == pirq) {
+ if (info->irq[pin - 1].link == pirq) {
/*
* We refuse to override the dev->irq
* information. Give a warning!
@@ -1043,6 +1042,9 @@ static void __init pcibios_fixup_irqs(void)
dev = NULL;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (!pin)
+ continue;
+
#ifdef CONFIG_X86_IO_APIC
/*
* Recalculate IRQ numbers if we use the I/O APIC.
@@ -1050,15 +1052,11 @@ static void __init pcibios_fixup_irqs(void)
if (io_apic_assign_pci_irqs) {
int irq;
- if (!pin)
- continue;
-
/*
* interrupt pins are numbered starting from 1
*/
- pin--;
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
- PCI_SLOT(dev->devfn), pin);
+ PCI_SLOT(dev->devfn), pin - 1);
/*
* Busses behind bridges are typically not listed in the
* MP-table. In this case we have to look up the IRQ
@@ -1071,22 +1069,22 @@ static void __init pcibios_fixup_irqs(void)
struct pci_dev *bridge = dev->bus->self;
int bus;
- pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+ pin = pci_swizzle_interrupt_pin(dev, pin);
bus = bridge->bus->number;
irq = IO_APIC_get_PCI_irq_vector(bus,
- PCI_SLOT(bridge->devfn), pin);
+ PCI_SLOT(bridge->devfn), pin - 1);
if (irq >= 0)
dev_warn(&dev->dev,
"using bridge %s INT %c to "
"get IRQ %d\n",
pci_name(bridge),
- 'A' + pin, irq);
+ 'A' + pin - 1, irq);
}
if (irq >= 0) {
dev_info(&dev->dev,
"PCI->APIC IRQ transform: INT %c "
"-> IRQ %d\n",
- 'A' + pin, irq);
+ 'A' + pin - 1, irq);
dev->irq = irq;
}
}
@@ -1094,7 +1092,7 @@ static void __init pcibios_fixup_irqs(void)
/*
* Still no IRQ? Try to lookup one...
*/
- if (pin && !dev->irq)
+ if (!dev->irq)
pcibios_lookup_irq(dev, 0);
}
}
@@ -1221,12 +1219,10 @@ static int pirq_enable_irq(struct pci_dev *dev)
if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
char *msg = "";
- pin--; /* interrupt pins are numbered starting from 1 */
-
if (io_apic_assign_pci_irqs) {
int irq;
- irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+ irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
/*
* Busses behind bridges are typically not listed in the MP-table.
* In this case we have to look up the IRQ based on the parent bus,
@@ -1237,20 +1233,20 @@ static int pirq_enable_irq(struct pci_dev *dev)
while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
struct pci_dev *bridge = dev->bus->self;
- pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+ pin = pci_swizzle_interrupt_pin(dev, pin);
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
- PCI_SLOT(bridge->devfn), pin);
+ PCI_SLOT(bridge->devfn), pin - 1);
if (irq >= 0)
dev_warn(&dev->dev, "using bridge %s "
"INT %c to get IRQ %d\n",
- pci_name(bridge), 'A' + pin,
+ pci_name(bridge), 'A' + pin - 1,
irq);
dev = bridge;
}
dev = temp_dev;
if (irq >= 0) {
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
- "INT %c -> IRQ %d\n", 'A' + pin, irq);
+ "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
dev->irq = irq;
return 0;
} else
@@ -1269,7 +1265,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
return 0;
dev_warn(&dev->dev, "can't find IRQ for PCI INT %c%s\n",
- 'A' + pin, msg);
+ 'A' + pin - 1, msg);
}
return 0;
}
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index b722dd481b39..f1065b129e9c 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -3,7 +3,7 @@
*/
#include <linux/init.h>
#include <linux/pci.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
/*
* Discover remaining PCI buses in case there are peer host bridges.
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 654a2234f8f3..89bf9242c80a 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -15,8 +15,7 @@
#include <linux/acpi.h>
#include <linux/bitmap.h>
#include <asm/e820.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
/* aperture is up to 256MB but BIOS may reserve less */
#define MMCONFIG_APER_MIN (2 * 1024*1024)
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index f3c761dce695..8b2d561046a3 100644
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -13,7 +13,7 @@
#include <linux/init.h>
#include <linux/acpi.h>
#include <asm/e820.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
/* Assume systems with more busses have correct MCFG */
#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index a1994163c99d..30007ffc8e11 100644
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -10,8 +10,7 @@
#include <linux/acpi.h>
#include <linux/bitmap.h>
#include <asm/e820.h>
-
-#include "pci.h"
+#include <asm/pci_x86.h>
/* Static virtual mapping of the MMCONFIG aperture */
struct mmcfg_virt {
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c
index 1177845d3186..2089354968a2 100644
--- a/arch/x86/pci/numaq_32.c
+++ b/arch/x86/pci/numaq_32.c
@@ -7,7 +7,7 @@
#include <linux/nodemask.h>
#include <mach_apic.h>
#include <asm/mpspec.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
#define XQUAD_PORTIO_BASE 0xfe400000
#define XQUAD_PORTIO_QUAD 0x40000 /* 256k per quad. */
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c
index e11e9e803d5f..b889d824f7c6 100644
--- a/arch/x86/pci/olpc.c
+++ b/arch/x86/pci/olpc.c
@@ -29,7 +29,7 @@
#include <linux/init.h>
#include <asm/olpc.h>
#include <asm/geode.h>
-#include "pci.h"
+#include <asm/pci_x86.h>
/*
* In the tables below, the first two line (8 longwords) are the
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c
index 37472fc6f729..b82cae970dfd 100644
--- a/arch/x86/pci/pcbios.c
+++ b/arch/x86/pci/pcbios.c
@@ -6,9 +6,8 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/uaccess.h>
-#include "pci.h"
-#include "pci-functions.h"
-
+#include <asm/pci_x86.h>
+#include <asm/mach-default/pci-functions.h>
/* BIOS32 signature: "_32_" */
#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index 42f4cb19faca..bcead7a46871 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -9,11 +9,10 @@
#include <linux/init.h>
#include <asm/setup.h>
+#include <asm/pci_x86.h>
#include <asm/visws/cobalt.h>
#include <asm/visws/lithium.h>
-#include "pci.h"
-
static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
static void pci_visws_disable_irq(struct pci_dev *dev) { }
@@ -25,24 +24,6 @@ static void pci_visws_disable_irq(struct pci_dev *dev) { }
unsigned int pci_bus0, pci_bus1;
-static inline u8 bridge_swizzle(u8 pin, u8 slot)
-{
- return (((pin - 1) + slot) % 4) + 1;
-}
-
-static u8 __init visws_swizzle(struct pci_dev *dev, u8 *pinp)
-{
- u8 pin = *pinp;
-
- while (dev->bus->self) { /* Move up the chain of bridges. */
- pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
- dev = dev->bus->self;
- }
- *pinp = pin;
-
- return PCI_SLOT(dev->devfn);
-}
-
static int __init visws_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
int irq, bus = dev->bus->number;
@@ -107,7 +88,7 @@ int __init pci_visws_init(void)
raw_pci_ops = &pci_direct_conf1;
pci_scan_bus_with_sysdata(pci_bus0);
pci_scan_bus_with_sysdata(pci_bus1);
- pci_fixup_irqs(visws_swizzle, visws_map_irq);
+ pci_fixup_irqs(pci_common_swizzle, visws_map_irq);
pcibios_resource_survey();
return 0;
}
diff --git a/arch/x86/scripts/strip-symbols b/arch/x86/scripts/strip-symbols
deleted file mode 100644
index a2f1ccb827c7..000000000000
--- a/arch/x86/scripts/strip-symbols
+++ /dev/null
@@ -1 +0,0 @@
-__cpu_vendor_dev_X86_VENDOR_*
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 773d68d3e912..503c240e26c7 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1082,7 +1082,7 @@ static void drop_other_mm_ref(void *info)
static void xen_drop_mm_ref(struct mm_struct *mm)
{
- cpumask_t mask;
+ cpumask_var_t mask;
unsigned cpu;
if (current->active_mm == mm) {
@@ -1094,7 +1094,16 @@ static void xen_drop_mm_ref(struct mm_struct *mm)
}
/* Get the "official" set of cpus referring to our pagetable. */
- mask = mm->cpu_vm_mask;
+ if (!alloc_cpumask_var(&mask, GFP_ATOMIC)) {
+ for_each_online_cpu(cpu) {
+ if (!cpumask_test_cpu(cpu, &mm->cpu_vm_mask)
+ && per_cpu(xen_current_cr3, cpu) != __pa(mm->pgd))
+ continue;
+ smp_call_function_single(cpu, drop_other_mm_ref, mm, 1);
+ }
+ return;
+ }
+ cpumask_copy(mask, &mm->cpu_vm_mask);
/* It's possible that a vcpu may have a stale reference to our
cr3, because its in lazy mode, and it hasn't yet flushed
@@ -1103,11 +1112,12 @@ static void xen_drop_mm_ref(struct mm_struct *mm)
if needed. */
for_each_online_cpu(cpu) {
if (per_cpu(xen_current_cr3, cpu) == __pa(mm->pgd))
- cpu_set(cpu, mask);
+ cpumask_set_cpu(cpu, mask);
}
- if (!cpus_empty(mask))
- smp_call_function_mask(mask, drop_other_mm_ref, mm, 1);
+ if (!cpumask_empty(mask))
+ smp_call_function_many(mask, drop_other_mm_ref, mm, 1);
+ free_cpumask_var(mask);
}
#else
static void xen_drop_mm_ref(struct mm_struct *mm)
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h
index 858938241616..fa3e10725d98 100644
--- a/arch/x86/xen/multicalls.h
+++ b/arch/x86/xen/multicalls.h
@@ -19,8 +19,10 @@ DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
paired with xen_mc_issue() */
static inline void xen_mc_batch(void)
{
+ unsigned long flags;
/* need to disable interrupts until this entry is complete */
- local_irq_save(__get_cpu_var(xen_mc_irq_flags));
+ local_irq_save(flags);
+ __get_cpu_var(xen_mc_irq_flags) = flags;
}
static inline struct multicall_space xen_mc_entry(size_t args)
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index acd9b6705e02..c44e2069c7c7 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -33,7 +33,7 @@
#include "xen-ops.h"
#include "mmu.h"
-cpumask_t xen_cpu_initialized_map;
+cpumask_var_t xen_cpu_initialized_map;
static DEFINE_PER_CPU(int, resched_irq);
static DEFINE_PER_CPU(int, callfunc_irq);
@@ -158,7 +158,7 @@ static void __init xen_fill_possible_map(void)
{
int i, rc;
- for (i = 0; i < NR_CPUS; i++) {
+ for (i = 0; i < nr_cpu_ids; i++) {
rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
if (rc >= 0) {
num_processors++;
@@ -192,11 +192,14 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
if (xen_smp_intr_init(0))
BUG();
- xen_cpu_initialized_map = cpumask_of_cpu(0);
+ if (!alloc_cpumask_var(&xen_cpu_initialized_map, GFP_KERNEL))
+ panic("could not allocate xen_cpu_initialized_map\n");
+
+ cpumask_copy(xen_cpu_initialized_map, cpumask_of(0));
/* Restrict the possible_map according to max_cpus. */
while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) {
- for (cpu = NR_CPUS - 1; !cpu_possible(cpu); cpu--)
+ for (cpu = nr_cpu_ids - 1; !cpu_possible(cpu); cpu--)
continue;
cpu_clear(cpu, cpu_possible_map);
}
@@ -221,7 +224,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
struct vcpu_guest_context *ctxt;
struct desc_struct *gdt;
- if (cpu_test_and_set(cpu, xen_cpu_initialized_map))
+ if (cpumask_test_and_set_cpu(cpu, xen_cpu_initialized_map))
return 0;
ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
@@ -408,24 +411,23 @@ static void xen_smp_send_reschedule(int cpu)
xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR);
}
-static void xen_send_IPI_mask(cpumask_t mask, enum ipi_vector vector)
+static void xen_send_IPI_mask(const struct cpumask *mask,
+ enum ipi_vector vector)
{
unsigned cpu;
- cpus_and(mask, mask, cpu_online_map);
-
- for_each_cpu_mask_nr(cpu, mask)
+ for_each_cpu_and(cpu, mask, cpu_online_mask)
xen_send_IPI_one(cpu, vector);
}
-static void xen_smp_send_call_function_ipi(cpumask_t mask)
+static void xen_smp_send_call_function_ipi(const struct cpumask *mask)
{
int cpu;
xen_send_IPI_mask(mask, XEN_CALL_FUNCTION_VECTOR);
/* Make sure other vcpus get a chance to run if they need to. */
- for_each_cpu_mask_nr(cpu, mask) {
+ for_each_cpu(cpu, mask) {
if (xen_vcpu_stolen(cpu)) {
HYPERVISOR_sched_op(SCHEDOP_yield, 0);
break;
@@ -435,7 +437,8 @@ static void xen_smp_send_call_function_ipi(cpumask_t mask)
static void xen_smp_send_call_function_single_ipi(int cpu)
{
- xen_send_IPI_mask(cpumask_of_cpu(cpu), XEN_CALL_FUNCTION_SINGLE_VECTOR);
+ xen_send_IPI_mask(cpumask_of(cpu),
+ XEN_CALL_FUNCTION_SINGLE_VECTOR);
}
static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id)
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 2a234db5949b..212ffe012b76 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -35,7 +35,8 @@ void xen_post_suspend(int suspend_cancelled)
pfn_to_mfn(xen_start_info->console.domU.mfn);
} else {
#ifdef CONFIG_SMP
- xen_cpu_initialized_map = cpu_online_map;
+ BUG_ON(xen_cpu_initialized_map == NULL);
+ cpumask_copy(xen_cpu_initialized_map, cpu_online_mask);
#endif
xen_vcpu_restore();
}
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index c9f7cda48ed7..14f240623497 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -132,8 +132,7 @@ static void do_stolen_accounting(void)
*snap = state;
/* Add the appropriate number of ticks of stolen time,
- including any left-overs from last time. Passing NULL to
- account_steal_time accounts the time as stolen. */
+ including any left-overs from last time. */
stolen = runnable + offline + __get_cpu_var(residual_stolen);
if (stolen < 0)
@@ -141,11 +140,10 @@ static void do_stolen_accounting(void)
ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen);
__get_cpu_var(residual_stolen) = stolen;
- account_steal_time(NULL, ticks);
+ account_steal_ticks(ticks);
/* Add the appropriate number of ticks of blocked time,
- including any left-overs from last time. Passing idle to
- account_steal_time accounts the time as idle/wait. */
+ including any left-overs from last time. */
blocked += __get_cpu_var(residual_blocked);
if (blocked < 0)
@@ -153,7 +151,7 @@ static void do_stolen_accounting(void)
ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked);
__get_cpu_var(residual_blocked) = blocked;
- account_steal_time(idle_task(smp_processor_id()), ticks);
+ account_idle_ticks(ticks);
}
/*
@@ -437,7 +435,7 @@ void xen_setup_timer(int cpu)
evt = &per_cpu(xen_clock_events, cpu);
memcpy(evt, xen_clockevent, sizeof(*evt));
- evt->cpumask = cpumask_of_cpu(cpu);
+ evt->cpumask = cpumask_of(cpu);
evt->irq = irq;
setup_runstate_info(cpu);
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 9e1afae8461f..c1f8faf0a2c5 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -58,7 +58,7 @@ void __init xen_init_spinlocks(void);
__cpuinit void xen_init_lock_cpu(int cpu);
void xen_uninit_lock_cpu(int cpu);
-extern cpumask_t xen_cpu_initialized_map;
+extern cpumask_var_t xen_cpu_initialized_map;
#else
static inline void xen_smp_init(void) {}
#endif
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index 015b6b2a26b9..1da55fe4beff 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -33,6 +33,15 @@ KBUILD_CFLAGS += -ffreestanding
KBUILD_CFLAGS += -pipe -mlongcalls
+vardirs := $(patsubst %,arch/xtensa/variants/%/,$(variant-y))
+plfdirs := $(patsubst %,arch/xtensa/platforms/%/,$(platform-y))
+
+ifeq ($(KBUILD_SRC),)
+KBUILD_CPPFLAGS += $(patsubst %,-I%include,$(vardirs) $(plfdirs))
+else
+KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(vardirs) $(plfdirs))
+endif
+
KBUILD_DEFCONFIG := iss_defconfig
# ramdisk/initrd support
@@ -66,21 +75,6 @@ libs-y += arch/xtensa/lib/ $(LIBGCC)
boot := arch/xtensa/boot
-archinc := include/asm-xtensa
-
-archprepare: $(archinc)/.platform
-
-# Update processor variant and platform symlinks if something which affects
-# them changed.
-
-$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/auto.conf
- @echo ' SYMLINK $(archinc)/variant -> $(archinc)/variant-$(VARIANT)'
- $(Q)mkdir -p $(archinc)
- $(Q)ln -fsn $(srctree)/$(archinc)/variant-$(VARIANT) $(archinc)/variant
- @echo ' SYMLINK $(archinc)/platform -> $(archinc)/platform-$(PLATFORM)'
- $(Q)ln -fsn $(srctree)/$(archinc)/platform-$(PLATFORM) $(archinc)/platform
- @touch $@
-
all: zImage
@@ -89,10 +83,6 @@ bzImage : zImage
zImage zImage.initrd: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $@
-CLEAN_FILES += arch/xtensa/vmlinux.lds \
- $(archinc)/platform $(archinc)/variant \
- $(archinc)/.platform
-
define archhelp
@echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)'
endef
diff --git a/arch/xtensa/boot/boot-elf/boot.lds.S b/arch/xtensa/boot/boot-elf/boot.lds.S
index 849dfcafd518..4e53b74dc44b 100644
--- a/arch/xtensa/boot/boot-elf/boot.lds.S
+++ b/arch/xtensa/boot/boot-elf/boot.lds.S
@@ -1,4 +1,4 @@
-#include <asm/variant/core.h>
+#include <variant/core.h>
OUTPUT_ARCH(xtensa)
ENTRY(_ResetVector)
diff --git a/arch/xtensa/boot/boot-redboot/bootstrap.S b/arch/xtensa/boot/boot-redboot/bootstrap.S
index 84848123e2a8..5582e8cfac8f 100644
--- a/arch/xtensa/boot/boot-redboot/bootstrap.S
+++ b/arch/xtensa/boot/boot-redboot/bootstrap.S
@@ -1,4 +1,4 @@
-#include <asm/variant/core.h>
+#include <variant/core.h>
#include <asm/regs.h>
#include <asm/asmmacro.h>
#include <asm/cacheasm.h>
diff --git a/arch/m68knommu/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index c68e1680da01..c68e1680da01 100644
--- a/arch/m68knommu/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
diff --git a/include/asm-xtensa/asmmacro.h b/arch/xtensa/include/asm/asmmacro.h
index 76915cabad17..755320f6e0bc 100644
--- a/include/asm-xtensa/asmmacro.h
+++ b/arch/xtensa/include/asm/asmmacro.h
@@ -11,7 +11,7 @@
#ifndef _XTENSA_ASMMACRO_H
#define _XTENSA_ASMMACRO_H
-#include <asm/variant/core.h>
+#include <variant/core.h>
/*
* Some little helpers for loops. Use zero-overhead-loops
diff --git a/include/asm-xtensa/atomic.h b/arch/xtensa/include/asm/atomic.h
index b3b23540f14d..67ad67bed8c1 100644
--- a/include/asm-xtensa/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -14,8 +14,7 @@
#define _XTENSA_ATOMIC_H
#include <linux/stringify.h>
-
-typedef struct { volatile int counter; } atomic_t;
+#include <linux/types.h>
#ifdef __KERNEL__
#include <asm/processor.h>
diff --git a/include/asm-xtensa/auxvec.h b/arch/xtensa/include/asm/auxvec.h
index 257dec75c5af..257dec75c5af 100644
--- a/include/asm-xtensa/auxvec.h
+++ b/arch/xtensa/include/asm/auxvec.h
diff --git a/include/asm-xtensa/bitops.h b/arch/xtensa/include/asm/bitops.h
index 23261e8f2e5a..6c3930397bd3 100644
--- a/include/asm-xtensa/bitops.h
+++ b/arch/xtensa/include/asm/bitops.h
@@ -82,6 +82,16 @@ static inline int fls (unsigned int x)
return 32 - __cntlz(x);
}
+/**
+ * __fls - find last (most-significant) set bit in a long word
+ * @word: the word to search
+ *
+ * Undefined if no set bit exists, so code should check against 0 first.
+ */
+static inline unsigned long __fls(unsigned long word)
+{
+ return 31 - __cntlz(word);
+}
#else
/* Use the generic implementation if we don't have the nsa/nsau instructions. */
@@ -90,6 +100,7 @@ static inline int fls (unsigned int x)
# include <asm-generic/bitops/__ffs.h>
# include <asm-generic/bitops/ffz.h>
# include <asm-generic/bitops/fls.h>
+# include <asm-generic/bitops/__fls.h>
#endif
diff --git a/include/asm-xtensa/bootparam.h b/arch/xtensa/include/asm/bootparam.h
index 9983f2c1b7ee..9983f2c1b7ee 100644
--- a/include/asm-xtensa/bootparam.h
+++ b/arch/xtensa/include/asm/bootparam.h
diff --git a/include/asm-xtensa/bug.h b/arch/xtensa/include/asm/bug.h
index 3e52d72712f1..3e52d72712f1 100644
--- a/include/asm-xtensa/bug.h
+++ b/arch/xtensa/include/asm/bug.h
diff --git a/include/asm-xtensa/bugs.h b/arch/xtensa/include/asm/bugs.h
index 69b29d198249..69b29d198249 100644
--- a/include/asm-xtensa/bugs.h
+++ b/arch/xtensa/include/asm/bugs.h
diff --git a/arch/xtensa/include/asm/byteorder.h b/arch/xtensa/include/asm/byteorder.h
new file mode 100644
index 000000000000..54eb6315349c
--- /dev/null
+++ b/arch/xtensa/include/asm/byteorder.h
@@ -0,0 +1,12 @@
+#ifndef _XTENSA_BYTEORDER_H
+#define _XTENSA_BYTEORDER_H
+
+#ifdef __XTENSA_EL__
+#include <linux/byteorder/little_endian.h>
+#elif defined(__XTENSA_EB__)
+#include <linux/byteorder/big_endian.h>
+#else
+# error processor byte order undefined!
+#endif
+
+#endif /* _XTENSA_BYTEORDER_H */
diff --git a/include/asm-xtensa/cache.h b/arch/xtensa/include/asm/cache.h
index 3bba2a540cf0..f04c9891142f 100644
--- a/include/asm-xtensa/cache.h
+++ b/arch/xtensa/include/asm/cache.h
@@ -11,7 +11,7 @@
#ifndef _XTENSA_CACHE_H
#define _XTENSA_CACHE_H
-#include <asm/variant/core.h>
+#include <variant/core.h>
#define L1_CACHE_SHIFT XCHAL_DCACHE_LINEWIDTH
#define L1_CACHE_BYTES XCHAL_DCACHE_LINESIZE
diff --git a/include/asm-xtensa/cacheasm.h b/arch/xtensa/include/asm/cacheasm.h
index 2c20a58f94cd..2c20a58f94cd 100644
--- a/include/asm-xtensa/cacheasm.h
+++ b/arch/xtensa/include/asm/cacheasm.h
diff --git a/include/asm-xtensa/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h
index 94c4c53a099e..94c4c53a099e 100644
--- a/include/asm-xtensa/cacheflush.h
+++ b/arch/xtensa/include/asm/cacheflush.h
diff --git a/include/asm-xtensa/checksum.h b/arch/xtensa/include/asm/checksum.h
index 23534c60b3a4..f84d3f00774a 100644
--- a/include/asm-xtensa/checksum.h
+++ b/arch/xtensa/include/asm/checksum.h
@@ -12,7 +12,7 @@
#define _XTENSA_CHECKSUM_H
#include <linux/in6.h>
-#include <asm/variant/core.h>
+#include <variant/core.h>
/*
* computes the checksum of a memory block at buff, length len,
diff --git a/include/asm-xtensa/coprocessor.h b/arch/xtensa/include/asm/coprocessor.h
index 1cbcf9001a41..65a285d8d3fb 100644
--- a/include/asm-xtensa/coprocessor.h
+++ b/arch/xtensa/include/asm/coprocessor.h
@@ -13,11 +13,11 @@
#define _XTENSA_COPROCESSOR_H
#include <linux/stringify.h>
-#include <asm/variant/tie.h>
+#include <variant/tie.h>
#include <asm/types.h>
#ifdef __ASSEMBLY__
-# include <asm/variant/tie-asm.h>
+# include <variant/tie-asm.h>
.macro xchal_sa_start a b
.set .Lxchal_pofs_, 0
diff --git a/include/asm-xtensa/cpumask.h b/arch/xtensa/include/asm/cpumask.h
index ebeede397db3..ebeede397db3 100644
--- a/include/asm-xtensa/cpumask.h
+++ b/arch/xtensa/include/asm/cpumask.h
diff --git a/include/asm-xtensa/cputime.h b/arch/xtensa/include/asm/cputime.h
index a7fb864a50ae..a7fb864a50ae 100644
--- a/include/asm-xtensa/cputime.h
+++ b/arch/xtensa/include/asm/cputime.h
diff --git a/include/asm-xtensa/current.h b/arch/xtensa/include/asm/current.h
index 8d1eb5d78649..8d1eb5d78649 100644
--- a/include/asm-xtensa/current.h
+++ b/arch/xtensa/include/asm/current.h
diff --git a/include/asm-xtensa/delay.h b/arch/xtensa/include/asm/delay.h
index e1d8c9e010c1..e1d8c9e010c1 100644
--- a/include/asm-xtensa/delay.h
+++ b/arch/xtensa/include/asm/delay.h
diff --git a/include/asm-m68k/device.h b/arch/xtensa/include/asm/device.h
index d8f9872b0e2d..d8f9872b0e2d 100644
--- a/include/asm-m68k/device.h
+++ b/arch/xtensa/include/asm/device.h
diff --git a/include/asm-xtensa/div64.h b/arch/xtensa/include/asm/div64.h
index f35678cb0a9b..f35678cb0a9b 100644
--- a/include/asm-xtensa/div64.h
+++ b/arch/xtensa/include/asm/div64.h
diff --git a/include/asm-xtensa/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
index 51882ae3db4d..51882ae3db4d 100644
--- a/include/asm-xtensa/dma-mapping.h
+++ b/arch/xtensa/include/asm/dma-mapping.h
diff --git a/include/asm-xtensa/dma.h b/arch/xtensa/include/asm/dma.h
index e30f3abf48f0..e30f3abf48f0 100644
--- a/include/asm-xtensa/dma.h
+++ b/arch/xtensa/include/asm/dma.h
diff --git a/include/asm-xtensa/elf.h b/arch/xtensa/include/asm/elf.h
index c3f53e755ca5..c3f53e755ca5 100644
--- a/include/asm-xtensa/elf.h
+++ b/arch/xtensa/include/asm/elf.h
diff --git a/include/asm-m68k/emergency-restart.h b/arch/xtensa/include/asm/emergency-restart.h
index 108d8c48e42e..108d8c48e42e 100644
--- a/include/asm-m68k/emergency-restart.h
+++ b/arch/xtensa/include/asm/emergency-restart.h
diff --git a/include/asm-xtensa/errno.h b/arch/xtensa/include/asm/errno.h
index a0f3b96b79b4..a0f3b96b79b4 100644
--- a/include/asm-xtensa/errno.h
+++ b/arch/xtensa/include/asm/errno.h
diff --git a/include/asm-xtensa/fb.h b/arch/xtensa/include/asm/fb.h
index c7df38030992..c7df38030992 100644
--- a/include/asm-xtensa/fb.h
+++ b/arch/xtensa/include/asm/fb.h
diff --git a/include/asm-xtensa/fcntl.h b/arch/xtensa/include/asm/fcntl.h
index 46ab12db5739..46ab12db5739 100644
--- a/include/asm-xtensa/fcntl.h
+++ b/arch/xtensa/include/asm/fcntl.h
diff --git a/include/asm-xtensa/futex.h b/arch/xtensa/include/asm/futex.h
index 0b745828f42b..0b745828f42b 100644
--- a/include/asm-xtensa/futex.h
+++ b/arch/xtensa/include/asm/futex.h
diff --git a/include/asm-xtensa/hardirq.h b/arch/xtensa/include/asm/hardirq.h
index 87cb19d1b10c..87cb19d1b10c 100644
--- a/include/asm-xtensa/hardirq.h
+++ b/arch/xtensa/include/asm/hardirq.h
diff --git a/include/asm-xtensa/highmem.h b/arch/xtensa/include/asm/highmem.h
index 0a046ca5a687..0a046ca5a687 100644
--- a/include/asm-xtensa/highmem.h
+++ b/arch/xtensa/include/asm/highmem.h
diff --git a/include/asm-xtensa/hw_irq.h b/arch/xtensa/include/asm/hw_irq.h
index 3ddbea759b2b..3ddbea759b2b 100644
--- a/include/asm-xtensa/hw_irq.h
+++ b/arch/xtensa/include/asm/hw_irq.h
diff --git a/include/asm-xtensa/io.h b/arch/xtensa/include/asm/io.h
index 07b7299dab20..07b7299dab20 100644
--- a/include/asm-xtensa/io.h
+++ b/arch/xtensa/include/asm/io.h
diff --git a/include/asm-m68k/ioctl.h b/arch/xtensa/include/asm/ioctl.h
index b279fe06dfe5..b279fe06dfe5 100644
--- a/include/asm-m68k/ioctl.h
+++ b/arch/xtensa/include/asm/ioctl.h
diff --git a/include/asm-xtensa/ioctls.h b/arch/xtensa/include/asm/ioctls.h
index 0ffa942954b9..0ffa942954b9 100644
--- a/include/asm-xtensa/ioctls.h
+++ b/arch/xtensa/include/asm/ioctls.h
diff --git a/include/asm-xtensa/ipcbuf.h b/arch/xtensa/include/asm/ipcbuf.h
index c33aa6a42145..c33aa6a42145 100644
--- a/include/asm-xtensa/ipcbuf.h
+++ b/arch/xtensa/include/asm/ipcbuf.h
diff --git a/include/asm-xtensa/irq.h b/arch/xtensa/include/asm/irq.h
index fc73b7f11aff..1620d1e0e695 100644
--- a/include/asm-xtensa/irq.h
+++ b/arch/xtensa/include/asm/irq.h
@@ -11,8 +11,8 @@
#ifndef _XTENSA_IRQ_H
#define _XTENSA_IRQ_H
-#include <asm/platform/hardware.h>
-#include <asm/variant/core.h>
+#include <platform/hardware.h>
+#include <variant/core.h>
#ifndef PLATFORM_NR_IRQS
# define PLATFORM_NR_IRQS 0
diff --git a/include/asm-m68k/irq_regs.h b/arch/xtensa/include/asm/irq_regs.h
index 3dd9c0b70270..3dd9c0b70270 100644
--- a/include/asm-m68k/irq_regs.h
+++ b/arch/xtensa/include/asm/irq_regs.h
diff --git a/include/asm-m68k/kdebug.h b/arch/xtensa/include/asm/kdebug.h
index 6ece1b037665..6ece1b037665 100644
--- a/include/asm-m68k/kdebug.h
+++ b/arch/xtensa/include/asm/kdebug.h
diff --git a/include/asm-xtensa/kmap_types.h b/arch/xtensa/include/asm/kmap_types.h
index 9e822d2e3bce..9e822d2e3bce 100644
--- a/include/asm-xtensa/kmap_types.h
+++ b/arch/xtensa/include/asm/kmap_types.h
diff --git a/include/asm-xtensa/linkage.h b/arch/xtensa/include/asm/linkage.h
index bf2128a99d79..bf2128a99d79 100644
--- a/include/asm-xtensa/linkage.h
+++ b/arch/xtensa/include/asm/linkage.h
diff --git a/include/asm-xtensa/local.h b/arch/xtensa/include/asm/local.h
index 48723e550d14..48723e550d14 100644
--- a/include/asm-xtensa/local.h
+++ b/arch/xtensa/include/asm/local.h
diff --git a/include/asm-xtensa/mman.h b/arch/xtensa/include/asm/mman.h
index 9b92620c8a1e..9b92620c8a1e 100644
--- a/include/asm-xtensa/mman.h
+++ b/arch/xtensa/include/asm/mman.h
diff --git a/include/asm-xtensa/mmu.h b/arch/xtensa/include/asm/mmu.h
index 44c5bb04c55c..44c5bb04c55c 100644
--- a/include/asm-xtensa/mmu.h
+++ b/arch/xtensa/include/asm/mmu.h
diff --git a/include/asm-xtensa/mmu_context.h b/arch/xtensa/include/asm/mmu_context.h
index c0fd8e5b4513..c0fd8e5b4513 100644
--- a/include/asm-xtensa/mmu_context.h
+++ b/arch/xtensa/include/asm/mmu_context.h
diff --git a/include/asm-xtensa/module.h b/arch/xtensa/include/asm/module.h
index d9b34bee4d42..d9b34bee4d42 100644
--- a/include/asm-xtensa/module.h
+++ b/arch/xtensa/include/asm/module.h
diff --git a/include/asm-xtensa/msgbuf.h b/arch/xtensa/include/asm/msgbuf.h
index 693c96755280..693c96755280 100644
--- a/include/asm-xtensa/msgbuf.h
+++ b/arch/xtensa/include/asm/msgbuf.h
diff --git a/include/asm-m68k/mutex.h b/arch/xtensa/include/asm/mutex.h
index 458c1f7fbc18..458c1f7fbc18 100644
--- a/include/asm-m68k/mutex.h
+++ b/arch/xtensa/include/asm/mutex.h
diff --git a/include/asm-xtensa/page.h b/arch/xtensa/include/asm/page.h
index 11f7dc2dbec7..11f7dc2dbec7 100644
--- a/include/asm-xtensa/page.h
+++ b/arch/xtensa/include/asm/page.h
diff --git a/include/asm-xtensa/param.h b/arch/xtensa/include/asm/param.h
index ba03d5aeab6b..ba03d5aeab6b 100644
--- a/include/asm-xtensa/param.h
+++ b/arch/xtensa/include/asm/param.h
diff --git a/include/asm-xtensa/pci-bridge.h b/arch/xtensa/include/asm/pci-bridge.h
index 00fcbd7c534a..00fcbd7c534a 100644
--- a/include/asm-xtensa/pci-bridge.h
+++ b/arch/xtensa/include/asm/pci-bridge.h
diff --git a/include/asm-xtensa/pci.h b/arch/xtensa/include/asm/pci.h
index 66410acf18b4..66410acf18b4 100644
--- a/include/asm-xtensa/pci.h
+++ b/arch/xtensa/include/asm/pci.h
diff --git a/include/asm-xtensa/percpu.h b/arch/xtensa/include/asm/percpu.h
index 6d2bc2ada9d1..6d2bc2ada9d1 100644
--- a/include/asm-xtensa/percpu.h
+++ b/arch/xtensa/include/asm/percpu.h
diff --git a/include/asm-xtensa/pgalloc.h b/arch/xtensa/include/asm/pgalloc.h
index 4f4a7987eded..4f4a7987eded 100644
--- a/include/asm-xtensa/pgalloc.h
+++ b/arch/xtensa/include/asm/pgalloc.h
diff --git a/include/asm-xtensa/pgtable.h b/arch/xtensa/include/asm/pgtable.h
index 8014d96b21f1..8014d96b21f1 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/arch/xtensa/include/asm/pgtable.h
diff --git a/include/asm-xtensa/platform.h b/arch/xtensa/include/asm/platform.h
index 48135a9718b0..e3d5a48ad495 100644
--- a/include/asm-xtensa/platform.h
+++ b/arch/xtensa/include/asm/platform.h
@@ -1,6 +1,4 @@
/*
- * include/asm-xtensa/platform.h
- *
* Platform specific functions
*
* This file is subject to the terms and conditions of the GNU General
diff --git a/include/asm-xtensa/poll.h b/arch/xtensa/include/asm/poll.h
index 9d2d5993f068..9d2d5993f068 100644
--- a/include/asm-xtensa/poll.h
+++ b/arch/xtensa/include/asm/poll.h
diff --git a/include/asm-xtensa/posix_types.h b/arch/xtensa/include/asm/posix_types.h
index 43f9dd1126a4..43f9dd1126a4 100644
--- a/include/asm-xtensa/posix_types.h
+++ b/arch/xtensa/include/asm/posix_types.h
diff --git a/include/asm-xtensa/processor.h b/arch/xtensa/include/asm/processor.h
index 4918a4e96d42..07387d3b99f4 100644
--- a/include/asm-xtensa/processor.h
+++ b/arch/xtensa/include/asm/processor.h
@@ -11,7 +11,7 @@
#ifndef _XTENSA_PROCESSOR_H
#define _XTENSA_PROCESSOR_H
-#include <asm/variant/core.h>
+#include <variant/core.h>
#include <asm/coprocessor.h>
#include <linux/compiler.h>
diff --git a/include/asm-xtensa/ptrace.h b/arch/xtensa/include/asm/ptrace.h
index 089b0db44816..905e1e619654 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/arch/xtensa/include/asm/ptrace.h
@@ -111,7 +111,7 @@ struct pt_regs {
unsigned long areg[16]; /* 128 (64) */
};
-#include <asm/variant/core.h>
+#include <variant/core.h>
# define task_pt_regs(tsk) ((struct pt_regs*) \
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
diff --git a/include/asm-xtensa/regs.h b/arch/xtensa/include/asm/regs.h
index d4baed246928..d4baed246928 100644
--- a/include/asm-xtensa/regs.h
+++ b/arch/xtensa/include/asm/regs.h
diff --git a/include/asm-xtensa/resource.h b/arch/xtensa/include/asm/resource.h
index 17b5ab311771..17b5ab311771 100644
--- a/include/asm-xtensa/resource.h
+++ b/arch/xtensa/include/asm/resource.h
diff --git a/include/asm-xtensa/rmap.h b/arch/xtensa/include/asm/rmap.h
index 649588b7e9ad..649588b7e9ad 100644
--- a/include/asm-xtensa/rmap.h
+++ b/arch/xtensa/include/asm/rmap.h
diff --git a/include/asm-xtensa/rwsem.h b/arch/xtensa/include/asm/rwsem.h
index e39edf5c86f2..e39edf5c86f2 100644
--- a/include/asm-xtensa/rwsem.h
+++ b/arch/xtensa/include/asm/rwsem.h
diff --git a/include/asm-xtensa/scatterlist.h b/arch/xtensa/include/asm/scatterlist.h
index 810080bb0a2b..810080bb0a2b 100644
--- a/include/asm-xtensa/scatterlist.h
+++ b/arch/xtensa/include/asm/scatterlist.h
diff --git a/include/asm-xtensa/sections.h b/arch/xtensa/include/asm/sections.h
index 40b5191b55a2..40b5191b55a2 100644
--- a/include/asm-xtensa/sections.h
+++ b/arch/xtensa/include/asm/sections.h
diff --git a/include/asm-xtensa/segment.h b/arch/xtensa/include/asm/segment.h
index a2eb547a1a75..a2eb547a1a75 100644
--- a/include/asm-xtensa/segment.h
+++ b/arch/xtensa/include/asm/segment.h
diff --git a/include/asm-xtensa/sembuf.h b/arch/xtensa/include/asm/sembuf.h
index c15870493b33..c15870493b33 100644
--- a/include/asm-xtensa/sembuf.h
+++ b/arch/xtensa/include/asm/sembuf.h
diff --git a/include/asm-xtensa/serial.h b/arch/xtensa/include/asm/serial.h
index ec04114fcf0b..a8a2493260f6 100644
--- a/include/asm-xtensa/serial.h
+++ b/arch/xtensa/include/asm/serial.h
@@ -13,6 +13,6 @@
#ifndef _XTENSA_SERIAL_H
#define _XTENSA_SERIAL_H
-#include <asm/platform/serial.h>
+#include <platform/serial.h>
#endif /* _XTENSA_SERIAL_H */
diff --git a/include/asm-xtensa/setup.h b/arch/xtensa/include/asm/setup.h
index e3636520d8cc..e3636520d8cc 100644
--- a/include/asm-xtensa/setup.h
+++ b/arch/xtensa/include/asm/setup.h
diff --git a/include/asm-xtensa/shmbuf.h b/arch/xtensa/include/asm/shmbuf.h
index ad4b0121782c..ad4b0121782c 100644
--- a/include/asm-xtensa/shmbuf.h
+++ b/arch/xtensa/include/asm/shmbuf.h
diff --git a/include/asm-xtensa/shmparam.h b/arch/xtensa/include/asm/shmparam.h
index c8cc16c3da9e..c8cc16c3da9e 100644
--- a/include/asm-xtensa/shmparam.h
+++ b/arch/xtensa/include/asm/shmparam.h
diff --git a/include/asm-xtensa/sigcontext.h b/arch/xtensa/include/asm/sigcontext.h
index 03383af8c3b7..03383af8c3b7 100644
--- a/include/asm-xtensa/sigcontext.h
+++ b/arch/xtensa/include/asm/sigcontext.h
diff --git a/include/asm-xtensa/siginfo.h b/arch/xtensa/include/asm/siginfo.h
index 6916248295df..6916248295df 100644
--- a/include/asm-xtensa/siginfo.h
+++ b/arch/xtensa/include/asm/siginfo.h
diff --git a/include/asm-xtensa/signal.h b/arch/xtensa/include/asm/signal.h
index 633ba73bc4d2..633ba73bc4d2 100644
--- a/include/asm-xtensa/signal.h
+++ b/arch/xtensa/include/asm/signal.h
diff --git a/include/asm-xtensa/smp.h b/arch/xtensa/include/asm/smp.h
index 83c569e3bdbd..83c569e3bdbd 100644
--- a/include/asm-xtensa/smp.h
+++ b/arch/xtensa/include/asm/smp.h
diff --git a/include/asm-xtensa/socket.h b/arch/xtensa/include/asm/socket.h
index 6100682b1da2..6100682b1da2 100644
--- a/include/asm-xtensa/socket.h
+++ b/arch/xtensa/include/asm/socket.h
diff --git a/include/asm-xtensa/sockios.h b/arch/xtensa/include/asm/sockios.h
index efe0af379f01..efe0af379f01 100644
--- a/include/asm-xtensa/sockios.h
+++ b/arch/xtensa/include/asm/sockios.h
diff --git a/include/asm-xtensa/spinlock.h b/arch/xtensa/include/asm/spinlock.h
index 8ff23649581b..8ff23649581b 100644
--- a/include/asm-xtensa/spinlock.h
+++ b/arch/xtensa/include/asm/spinlock.h
diff --git a/include/asm-xtensa/stat.h b/arch/xtensa/include/asm/stat.h
index c4992038cee0..c4992038cee0 100644
--- a/include/asm-xtensa/stat.h
+++ b/arch/xtensa/include/asm/stat.h
diff --git a/include/asm-xtensa/statfs.h b/arch/xtensa/include/asm/statfs.h
index 9c3d1a213136..9c3d1a213136 100644
--- a/include/asm-xtensa/statfs.h
+++ b/arch/xtensa/include/asm/statfs.h
diff --git a/include/asm-xtensa/string.h b/arch/xtensa/include/asm/string.h
index 5fb8c27cbef5..5fb8c27cbef5 100644
--- a/include/asm-xtensa/string.h
+++ b/arch/xtensa/include/asm/string.h
diff --git a/include/asm-xtensa/byteorder.h b/arch/xtensa/include/asm/swab.h
index 765edf17a9a4..f50b697eb601 100644
--- a/include/asm-xtensa/byteorder.h
+++ b/arch/xtensa/include/asm/swab.h
@@ -1,5 +1,5 @@
/*
- * include/asm-xtensa/byteorder.h
+ * include/asm-xtensa/swab.h
*
* 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
@@ -8,13 +8,15 @@
* Copyright (C) 2001 - 2005 Tensilica Inc.
*/
-#ifndef _XTENSA_BYTEORDER_H
-#define _XTENSA_BYTEORDER_H
+#ifndef _XTENSA_SWAB_H
+#define _XTENSA_SWAB_H
#include <asm/types.h>
#include <linux/compiler.h>
-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+#define __SWAB_64_THRU_32__
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
{
__u32 res;
/* instruction sequence from Xtensa ISA release 2/2000 */
@@ -28,8 +30,9 @@ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
);
return res;
}
+#define __arch_swab32 __arch_swab32
-static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
{
/* Given that 'short' values are signed (i.e., can be negative),
* we cannot assume that the upper 16-bits of the register are
@@ -62,21 +65,6 @@ static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
return res;
}
+#define __arch_swab16 __arch_swab16
-#define __arch__swab32(x) ___arch__swab32(x)
-#define __arch__swab16(x) ___arch__swab16(x)
-
-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
-
-#ifdef __XTENSA_EL__
-# include <linux/byteorder/little_endian.h>
-#elif defined(__XTENSA_EB__)
-# include <linux/byteorder/big_endian.h>
-#else
-# error processor byte order undefined!
-#endif
-
-#endif /* _XTENSA_BYTEORDER_H */
+#endif /* _XTENSA_SWAB_H */
diff --git a/include/asm-xtensa/syscall.h b/arch/xtensa/include/asm/syscall.h
index 05cebf8f62b1..05cebf8f62b1 100644
--- a/include/asm-xtensa/syscall.h
+++ b/arch/xtensa/include/asm/syscall.h
diff --git a/include/asm-xtensa/system.h b/arch/xtensa/include/asm/system.h
index 62b1e8f3c13c..62b1e8f3c13c 100644
--- a/include/asm-xtensa/system.h
+++ b/arch/xtensa/include/asm/system.h
diff --git a/include/asm-xtensa/termbits.h b/arch/xtensa/include/asm/termbits.h
index 85aa6a3c0b6e..85aa6a3c0b6e 100644
--- a/include/asm-xtensa/termbits.h
+++ b/arch/xtensa/include/asm/termbits.h
diff --git a/include/asm-xtensa/termios.h b/arch/xtensa/include/asm/termios.h
index 4673f42f88a7..4673f42f88a7 100644
--- a/include/asm-xtensa/termios.h
+++ b/arch/xtensa/include/asm/termios.h
diff --git a/include/asm-xtensa/thread_info.h b/arch/xtensa/include/asm/thread_info.h
index 0f4fe1faf9ba..0f4fe1faf9ba 100644
--- a/include/asm-xtensa/thread_info.h
+++ b/arch/xtensa/include/asm/thread_info.h
diff --git a/include/asm-xtensa/timex.h b/arch/xtensa/include/asm/timex.h
index b83a8181d448..b83a8181d448 100644
--- a/include/asm-xtensa/timex.h
+++ b/arch/xtensa/include/asm/timex.h
diff --git a/include/asm-xtensa/tlb.h b/arch/xtensa/include/asm/tlb.h
index 31c220faca02..31c220faca02 100644
--- a/include/asm-xtensa/tlb.h
+++ b/arch/xtensa/include/asm/tlb.h
diff --git a/include/asm-xtensa/tlbflush.h b/arch/xtensa/include/asm/tlbflush.h
index 46d240074f74..46d240074f74 100644
--- a/include/asm-xtensa/tlbflush.h
+++ b/arch/xtensa/include/asm/tlbflush.h
diff --git a/include/asm-xtensa/topology.h b/arch/xtensa/include/asm/topology.h
index 7309e38a0ccb..7309e38a0ccb 100644
--- a/include/asm-xtensa/topology.h
+++ b/arch/xtensa/include/asm/topology.h
diff --git a/include/asm-xtensa/types.h b/arch/xtensa/include/asm/types.h
index c89569a8da0c..c89569a8da0c 100644
--- a/include/asm-xtensa/types.h
+++ b/arch/xtensa/include/asm/types.h
diff --git a/include/asm-xtensa/uaccess.h b/arch/xtensa/include/asm/uaccess.h
index b8528426ab1f..b8528426ab1f 100644
--- a/include/asm-xtensa/uaccess.h
+++ b/arch/xtensa/include/asm/uaccess.h
diff --git a/include/asm-xtensa/ucontext.h b/arch/xtensa/include/asm/ucontext.h
index 94c94ed3e00a..94c94ed3e00a 100644
--- a/include/asm-xtensa/ucontext.h
+++ b/arch/xtensa/include/asm/ucontext.h
diff --git a/include/asm-xtensa/unaligned.h b/arch/xtensa/include/asm/unaligned.h
index 8f3424fc5d18..8e7ed046bfed 100644
--- a/include/asm-xtensa/unaligned.h
+++ b/arch/xtensa/include/asm/unaligned.h
@@ -10,20 +10,20 @@
#ifndef _ASM_XTENSA_UNALIGNED_H
#define _ASM_XTENSA_UNALIGNED_H
-#ifdef __XTENSA_EL__
-# include <linux/unaligned/le_memmove.h>
+#include <asm/byteorder.h>
+
+#ifdef __LITTLE_ENDIAN
+# include <linux/unaligned/le_struct.h>
# include <linux/unaligned/be_byteshift.h>
# include <linux/unaligned/generic.h>
# define get_unaligned __get_unaligned_le
# define put_unaligned __put_unaligned_le
-#elif defined(__XTENSA_EB__)
-# include <linux/unaligned/be_memmove.h>
+#else
+# include <linux/unaligned/be_struct.h>
# include <linux/unaligned/le_byteshift.h>
# include <linux/unaligned/generic.h>
# define get_unaligned __get_unaligned_be
# define put_unaligned __put_unaligned_be
-#else
-# error processor byte order undefined!
#endif
#endif /* _ASM_XTENSA_UNALIGNED_H */
diff --git a/include/asm-xtensa/unistd.h b/arch/xtensa/include/asm/unistd.h
index c092c8fbb2cf..c092c8fbb2cf 100644
--- a/include/asm-xtensa/unistd.h
+++ b/arch/xtensa/include/asm/unistd.h
diff --git a/include/asm-xtensa/user.h b/arch/xtensa/include/asm/user.h
index 2c3ed23354a8..2c3ed23354a8 100644
--- a/include/asm-xtensa/user.h
+++ b/arch/xtensa/include/asm/user.h
diff --git a/include/asm-xtensa/vga.h b/arch/xtensa/include/asm/vga.h
index 1fd8cab3a297..1fd8cab3a297 100644
--- a/include/asm-xtensa/vga.h
+++ b/arch/xtensa/include/asm/vga.h
diff --git a/include/asm-xtensa/xor.h b/arch/xtensa/include/asm/xor.h
index e7b1f083991d..e7b1f083991d 100644
--- a/include/asm-xtensa/xor.h
+++ b/arch/xtensa/include/asm/xor.h
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index dfd35dcc1cb5..a51d36a27389 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -25,7 +25,7 @@
#include <asm/page.h>
#include <asm/signal.h>
#include <asm/tlbflush.h>
-#include <asm/variant/tie-asm.h>
+#include <variant/tie-asm.h>
/* Unimplemented features. */
diff --git a/arch/xtensa/kernel/init_task.c b/arch/xtensa/kernel/init_task.c
index 3df469dbe814..e07f5c9fcd35 100644
--- a/arch/xtensa/kernel/init_task.c
+++ b/arch/xtensa/kernel/init_task.c
@@ -21,7 +21,6 @@
#include <asm/uaccess.h>
-static struct fs_struct init_fs = INIT_FS;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 51f4fb6f16f9..d506774f4b05 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -16,7 +16,7 @@
#include <asm-generic/vmlinux.lds.h>
-#include <asm/variant/core.h>
+#include <variant/core.h>
OUTPUT_ARCH(xtensa)
ENTRY(_start)
diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S
index 9d9cd990afa6..df397f932d0e 100644
--- a/arch/xtensa/lib/checksum.S
+++ b/arch/xtensa/lib/checksum.S
@@ -16,7 +16,7 @@
#include <asm/errno.h>
#include <linux/linkage.h>
-#include <asm/variant/core.h>
+#include <variant/core.h>
/*
* computes a partial checksum, e.g. for TCP/UDP fragments
diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S
index ddda8f4bc862..ea59dcd03866 100644
--- a/arch/xtensa/lib/memcopy.S
+++ b/arch/xtensa/lib/memcopy.S
@@ -9,7 +9,7 @@
* Copyright (C) 2002 - 2005 Tensilica Inc.
*/
-#include <asm/variant/core.h>
+#include <variant/core.h>
.macro src_b r, w0, w1
#ifdef __XTENSA_EB__
diff --git a/arch/xtensa/lib/memset.S b/arch/xtensa/lib/memset.S
index 56a17495b2db..10b8c400f175 100644
--- a/arch/xtensa/lib/memset.S
+++ b/arch/xtensa/lib/memset.S
@@ -11,7 +11,7 @@
* Copyright (C) 2002 Tensilica Inc.
*/
-#include <asm/variant/core.h>
+#include <variant/core.h>
/*
* void *memset(void *dst, int c, size_t length)
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
index b2655d94558d..9f603cdaaa68 100644
--- a/arch/xtensa/lib/strncpy_user.S
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -11,7 +11,7 @@
* Copyright (C) 2002 Tensilica Inc.
*/
-#include <asm/variant/core.h>
+#include <variant/core.h>
#include <linux/errno.h>
/* Load or store instructions that may cause exceptions use the EX macro. */
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
index ad3f616322ca..23f2a89816a1 100644
--- a/arch/xtensa/lib/strnlen_user.S
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -11,7 +11,7 @@
* Copyright (C) 2002 Tensilica Inc.
*/
-#include <asm/variant/core.h>
+#include <variant/core.h>
/* Load or store instructions that may cause exceptions use the EX macro. */
diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S
index a8ab1d4fe0ae..46d60314bb16 100644
--- a/arch/xtensa/lib/usercopy.S
+++ b/arch/xtensa/lib/usercopy.S
@@ -53,7 +53,7 @@
* a11/ original length
*/
-#include <asm/variant/core.h>
+#include <variant/core.h>
#ifdef __XTENSA_EB__
#define ALIGN(R, W0, W1) src R, W0, W1
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index 9141e3690731..efed8897bef3 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -1,5 +1,5 @@
/*
- * arch/xtensa/platform-iss/console.c
+ * arch/xtensa/platforms/iss/console.c
*
* 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
@@ -24,7 +24,7 @@
#include <asm/uaccess.h>
#include <asm/irq.h>
-#include <asm/platform/simcall.h>
+#include <platform/simcall.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
diff --git a/include/asm-xtensa/platform-iss/hardware.h b/arch/xtensa/platforms/iss/include/platform/hardware.h
index 6930c12adc16..6930c12adc16 100644
--- a/include/asm-xtensa/platform-iss/hardware.h
+++ b/arch/xtensa/platforms/iss/include/platform/hardware.h
diff --git a/include/asm-xtensa/platform-iss/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h
index b7952c06a2b7..b7952c06a2b7 100644
--- a/include/asm-xtensa/platform-iss/simcall.h
+++ b/arch/xtensa/platforms/iss/include/platform/simcall.h
diff --git a/arch/xtensa/platforms/iss/io.c b/arch/xtensa/platforms/iss/io.c
index 5b161a5cb65f..571d0b24f895 100644
--- a/arch/xtensa/platforms/iss/io.c
+++ b/arch/xtensa/platforms/iss/io.c
@@ -3,7 +3,7 @@
#if 0
#include <asm/io.h>
-#include <xtensa/simcall.h>
+#include <platform/platform-iss/simcall.h>
extern int __simc ();
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index 64f057d89e73..edad4156d89a 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -1,6 +1,6 @@
/*
*
- * arch/xtensa/platform-iss/network.c
+ * arch/xtensa/platforms/iss/network.c
*
* Platform specific initialization.
*
@@ -33,7 +33,7 @@
#include <linux/rtnetlink.h>
#include <linux/platform_device.h>
-#include <asm/platform/simcall.h>
+#include <platform/simcall.h>
#define DRIVER_NAME "iss-netdev"
#define ETH_MAX_PACKET 1500
diff --git a/arch/xtensa/platforms/xt2000/Makefile b/arch/xtensa/platforms/xt2000/Makefile
new file mode 100644
index 000000000000..54d018e45bfc
--- /dev/null
+++ b/arch/xtensa/platforms/xt2000/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Tensilica XT2000 Emulation Board
+#
+
+obj-y = setup.o
diff --git a/arch/xtensa/platforms/xt2000/include/platform/hardware.h b/arch/xtensa/platforms/xt2000/include/platform/hardware.h
new file mode 100644
index 000000000000..41459ad07766
--- /dev/null
+++ b/arch/xtensa/platforms/xt2000/include/platform/hardware.h
@@ -0,0 +1,55 @@
+/*
+ * platform/hardware.h
+ *
+ * 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) 2001 Tensilica Inc.
+ */
+
+/*
+ * This file contains the hardware configuration of the XT2000 board.
+ */
+
+#ifndef _XTENSA_XT2000_HARDWARE_H
+#define _XTENSA_XT2000_HARDWARE_H
+
+#include <variant/core.h>
+#include <asm/io.h>
+
+/*
+ * Memory configuration.
+ */
+
+#define PLATFORM_DEFAULT_MEM_START 0x00000000
+#define PLATFORM_DEFAULT_MEM_SIZE 0x08000000
+
+/*
+ * Number of platform IRQs
+ */
+#define PLATFORM_NR_IRQS 3
+/*
+ * On-board components.
+ */
+
+#define SONIC83934_INTNUM XCHAL_EXTINT3_NUM
+#define SONIC83934_ADDR IOADDR(0x0d030000)
+
+/*
+ * V3-PCI
+ */
+
+/* The XT2000 uses the V3 as a cascaded interrupt controller for the PCI bus */
+
+#define IRQ_PCI_A (XCHAL_NUM_INTERRUPTS + 0)
+#define IRQ_PCI_B (XCHAL_NUM_INTERRUPTS + 1)
+#define IRQ_PCI_C (XCHAL_NUM_INTERRUPTS + 2)
+
+/*
+ * Various other components.
+ */
+
+#define XT2000_LED_ADDR IOADDR(0x0d040000)
+
+#endif /* _XTENSA_XT2000_HARDWARE_H */
diff --git a/arch/xtensa/platforms/xt2000/include/platform/serial.h b/arch/xtensa/platforms/xt2000/include/platform/serial.h
new file mode 100644
index 000000000000..7226cf732b47
--- /dev/null
+++ b/arch/xtensa/platforms/xt2000/include/platform/serial.h
@@ -0,0 +1,28 @@
+/*
+ * platform/serial.h
+ *
+ * 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) 2001 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_XT2000_SERIAL_H
+#define _XTENSA_XT2000_SERIAL_H
+
+#include <variant/core.h>
+#include <asm/io.h>
+
+/* National-Semi PC16552D DUART: */
+
+#define DUART16552_1_INTNUM XCHAL_EXTINT4_NUM
+#define DUART16552_2_INTNUM XCHAL_EXTINT5_NUM
+
+#define DUART16552_1_ADDR IOADDR(0x0d050020) /* channel 1 */
+#define DUART16552_2_ADDR IOADDR(0x0d050000) /* channel 2 */
+
+#define DUART16552_XTAL_FREQ 18432000 /* crystal frequency in Hz */
+#define BASE_BAUD ( DUART16552_XTAL_FREQ / 16 )
+
+#endif /* _XTENSA_XT2000_SERIAL_H */
diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c
new file mode 100644
index 000000000000..9e83940ac265
--- /dev/null
+++ b/arch/xtensa/platforms/xt2000/setup.c
@@ -0,0 +1,181 @@
+/*
+ * arch/xtensa/platforms/xt2000/setup.c
+ *
+ * Platform specific functions for the XT2000 board.
+ *
+ * Authors: Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com>
+ *
+ * Copyright 2001 - 2004 Tensilica Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/stringify.h>
+#include <linux/platform_device.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+
+#include <asm/processor.h>
+#include <asm/platform.h>
+#include <asm/bootparam.h>
+#include <platform/hardware.h>
+#include <platform/serial.h>
+
+/* Assumes s points to an 8-chr string. No checking for NULL. */
+
+static void led_print (int f, char *s)
+{
+ unsigned long* led_addr = (unsigned long*) (XT2000_LED_ADDR + 0xE0) + f;
+ int i;
+ for (i = f; i < 8; i++)
+ if ((*led_addr++ = *s++) == 0)
+ break;
+}
+
+void platform_halt(void)
+{
+ led_print (0, " HALT ");
+ local_irq_disable();
+ while (1);
+}
+
+void platform_power_off(void)
+{
+ led_print (0, "POWEROFF");
+ local_irq_disable();
+ while (1);
+}
+
+void platform_restart(void)
+{
+ /* Flush and reset the mmu, simulate a processor reset, and
+ * jump to the reset vector. */
+
+ __asm__ __volatile__ ("movi a2, 15\n\t"
+ "wsr a2, " __stringify(ICOUNTLEVEL) "\n\t"
+ "movi a2, 0\n\t"
+ "wsr a2, " __stringify(ICOUNT) "\n\t"
+ "wsr a2, " __stringify(IBREAKENABLE) "\n\t"
+ "wsr a2, " __stringify(LCOUNT) "\n\t"
+ "movi a2, 0x1f\n\t"
+ "wsr a2, " __stringify(PS) "\n\t"
+ "isync\n\t"
+ "jx %0\n\t"
+ :
+ : "a" (XCHAL_RESET_VECTOR_VADDR)
+ : "a2"
+ );
+
+ /* control never gets here */
+}
+
+void __init platform_setup(char** cmdline)
+{
+ led_print (0, "LINUX ");
+}
+
+/* early initialization */
+
+extern sysmem_info_t __initdata sysmem;
+
+void platform_init(bp_tag_t* first)
+{
+ /* Set default memory block if not provided by the bootloader. */
+
+ if (sysmem.nr_banks == 0) {
+ sysmem.nr_banks = 1;
+ sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
+ sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
+ + PLATFORM_DEFAULT_MEM_SIZE;
+ }
+}
+
+/* Heartbeat. Let the LED blink. */
+
+void platform_heartbeat(void)
+{
+ static int i=0, t = 0;
+
+ if (--t < 0)
+ {
+ t = 59;
+ led_print(7, i ? ".": " ");
+ i ^= 1;
+ }
+}
+
+//#define RS_TABLE_SIZE 2
+//#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+
+#define _SERIAL_PORT(_base,_irq) \
+{ \
+ .mapbase = (_base), \
+ .membase = (void*)(_base), \
+ .irq = (_irq), \
+ .uartclk = DUART16552_XTAL_FREQ, \
+ .iotype = UPIO_MEM, \
+ .flags = UPF_BOOT_AUTOCONF, \
+ .regshift = 2, \
+}
+
+static struct plat_serial8250_port xt2000_serial_data[] = {
+#if XCHAL_HAVE_BE
+ _SERIAL_PORT(DUART16552_1_ADDR + 3, DUART16552_1_INTNUM),
+ _SERIAL_PORT(DUART16552_2_ADDR + 3, DUART16552_2_INTNUM),
+#else
+ _SERIAL_PORT(DUART16552_1_ADDR, DUART16552_1_INTNUM),
+ _SERIAL_PORT(DUART16552_2_ADDR, DUART16552_2_INTNUM),
+#endif
+ { }
+};
+
+static struct platform_device xt2000_serial8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = xt2000_serial_data,
+ },
+};
+
+static struct resource xt2000_sonic_res[] = {
+ {
+ .start = SONIC83934_ADDR,
+ .end = SONIC83934_ADDR + 0xff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SONIC83934_INTNUM,
+ .end = SONIC83934_INTNUM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device xt2000_sonic_device = {
+ .name = "xtsonic",
+ .num_resources = ARRAY_SIZE(xt2000_sonic_res),
+ .resource = xt2000_sonic_res,
+};
+
+static int __init xt2000_setup_devinit(void)
+{
+ platform_device_register(&xt2000_serial8250_device);
+ platform_device_register(&xt2000_sonic_device);
+
+ return 0;
+}
+
+device_initcall(xt2000_setup_devinit);
diff --git a/include/asm-xtensa/variant-dc232b/core.h b/arch/xtensa/variants/dc232b/include/variant/core.h
index 525bd3d90154..525bd3d90154 100644
--- a/include/asm-xtensa/variant-dc232b/core.h
+++ b/arch/xtensa/variants/dc232b/include/variant/core.h
diff --git a/include/asm-xtensa/variant-dc232b/tie-asm.h b/arch/xtensa/variants/dc232b/include/variant/tie-asm.h
index ed4f53f529db..ed4f53f529db 100644
--- a/include/asm-xtensa/variant-dc232b/tie-asm.h
+++ b/arch/xtensa/variants/dc232b/include/variant/tie-asm.h
diff --git a/include/asm-xtensa/variant-dc232b/tie.h b/arch/xtensa/variants/dc232b/include/variant/tie.h
index 018e81af4393..018e81af4393 100644
--- a/include/asm-xtensa/variant-dc232b/tie.h
+++ b/arch/xtensa/variants/dc232b/include/variant/tie.h
diff --git a/include/asm-xtensa/variant-fsf/core.h b/arch/xtensa/variants/fsf/include/variant/core.h
index 2f337605c744..2f337605c744 100644
--- a/include/asm-xtensa/variant-fsf/core.h
+++ b/arch/xtensa/variants/fsf/include/variant/core.h
diff --git a/include/asm-xtensa/variant-fsf/tie-asm.h b/arch/xtensa/variants/fsf/include/variant/tie-asm.h
index 68a73bf4ffc5..68a73bf4ffc5 100644
--- a/include/asm-xtensa/variant-fsf/tie-asm.h
+++ b/arch/xtensa/variants/fsf/include/variant/tie-asm.h
diff --git a/include/asm-xtensa/variant-fsf/tie.h b/arch/xtensa/variants/fsf/include/variant/tie.h
index bf4020116df5..bf4020116df5 100644
--- a/include/asm-xtensa/variant-fsf/tie.h
+++ b/arch/xtensa/variants/fsf/include/variant/tie.h
diff --git a/block/Kconfig b/block/Kconfig
index ac0956f77785..0cbb3b88b59a 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -36,6 +36,12 @@ config LBD
This option also enables support for single files larger than
2TB.
+ The ext4 filesystem requires that this feature be enabled in
+ order to support filesystems that have the huge_file feature
+ enabled. Otherwise, it will refuse to mount any filesystems
+ that use the huge_file feature, which is enabled by default
+ by mke2fs.ext4. The GFS2 filesystem also requires this feature.
+
If unsure, say N.
config BLK_DEV_IO_TRACE
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index 8eba4e43bb0c..f7dae57e6cab 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -302,7 +302,7 @@ static void bio_end_empty_barrier(struct bio *bio, int err)
* Description:
* Issue a flush for the block device in question. Caller can supply
* room for storing the error offset in case of a flush error, if they
- * wish to. Caller must run wait_for_completion() on its own.
+ * wish to.
*/
int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
{
diff --git a/block/blk-core.c b/block/blk-core.c
index a824e49c0d0a..29bcfac6c688 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -64,11 +64,12 @@ static struct workqueue_struct *kblockd_workqueue;
static void drive_stat_acct(struct request *rq, int new_io)
{
+ struct gendisk *disk = rq->rq_disk;
struct hd_struct *part;
int rw = rq_data_dir(rq);
int cpu;
- if (!blk_fs_request(rq) || !rq->rq_disk)
+ if (!blk_fs_request(rq) || !disk || !blk_do_io_stat(disk->queue))
return;
cpu = part_stat_lock();
@@ -599,8 +600,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
q->request_fn = rfn;
q->prep_rq_fn = NULL;
q->unplug_fn = generic_unplug_device;
- q->queue_flags = (1 << QUEUE_FLAG_CLUSTER |
- 1 << QUEUE_FLAG_STACKABLE);
+ q->queue_flags = QUEUE_FLAG_DEFAULT;
q->queue_lock = lock;
blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
@@ -1125,6 +1125,8 @@ void init_request_from_bio(struct request *req, struct bio *bio)
if (bio_sync(bio))
req->cmd_flags |= REQ_RW_SYNC;
+ if (bio_unplug(bio))
+ req->cmd_flags |= REQ_UNPLUG;
if (bio_rw_meta(bio))
req->cmd_flags |= REQ_RW_META;
@@ -1141,6 +1143,7 @@ static int __make_request(struct request_queue *q, struct bio *bio)
int el_ret, nr_sectors;
const unsigned short prio = bio_prio(bio);
const int sync = bio_sync(bio);
+ const int unplug = bio_unplug(bio);
int rw_flags;
nr_sectors = bio_sectors(bio);
@@ -1244,7 +1247,7 @@ get_rq:
blk_plug_device(q);
add_request(q, req);
out:
- if (sync || blk_queue_nonrot(q))
+ if (unplug || blk_queue_nonrot(q))
__generic_unplug_device(q);
spin_unlock_irq(q->queue_lock);
return 0;
@@ -1448,6 +1451,11 @@ static inline void __generic_make_request(struct bio *bio)
err = -EOPNOTSUPP;
goto end_io;
}
+ if (bio_barrier(bio) && bio_has_data(bio) &&
+ (q->next_ordered == QUEUE_ORDERED_NONE)) {
+ err = -EOPNOTSUPP;
+ goto end_io;
+ }
ret = q->make_request_fn(q, bio);
} while (ret);
@@ -1655,6 +1663,55 @@ void blkdev_dequeue_request(struct request *req)
}
EXPORT_SYMBOL(blkdev_dequeue_request);
+static void blk_account_io_completion(struct request *req, unsigned int bytes)
+{
+ struct gendisk *disk = req->rq_disk;
+
+ if (!disk || !blk_do_io_stat(disk->queue))
+ return;
+
+ if (blk_fs_request(req)) {
+ const int rw = rq_data_dir(req);
+ struct hd_struct *part;
+ int cpu;
+
+ cpu = part_stat_lock();
+ part = disk_map_sector_rcu(req->rq_disk, req->sector);
+ part_stat_add(cpu, part, sectors[rw], bytes >> 9);
+ part_stat_unlock();
+ }
+}
+
+static void blk_account_io_done(struct request *req)
+{
+ struct gendisk *disk = req->rq_disk;
+
+ if (!disk || !blk_do_io_stat(disk->queue))
+ return;
+
+ /*
+ * Account IO completion. bar_rq isn't accounted as a normal
+ * IO on queueing nor completion. Accounting the containing
+ * request is enough.
+ */
+ if (blk_fs_request(req) && req != &req->q->bar_rq) {
+ unsigned long duration = jiffies - req->start_time;
+ const int rw = rq_data_dir(req);
+ struct hd_struct *part;
+ int cpu;
+
+ cpu = part_stat_lock();
+ part = disk_map_sector_rcu(disk, req->sector);
+
+ part_stat_inc(cpu, part, ios[rw]);
+ part_stat_add(cpu, part, ticks[rw], duration);
+ part_round_stats(cpu, part);
+ part_dec_in_flight(part);
+
+ part_stat_unlock();
+ }
+}
+
/**
* __end_that_request_first - end I/O on a request
* @req: the request being processed
@@ -1690,16 +1747,7 @@ static int __end_that_request_first(struct request *req, int error,
(unsigned long long)req->sector);
}
- if (blk_fs_request(req) && req->rq_disk) {
- const int rw = rq_data_dir(req);
- struct hd_struct *part;
- int cpu;
-
- cpu = part_stat_lock();
- part = disk_map_sector_rcu(req->rq_disk, req->sector);
- part_stat_add(cpu, part, sectors[rw], nr_bytes >> 9);
- part_stat_unlock();
- }
+ blk_account_io_completion(req, nr_bytes);
total_bytes = bio_nbytes = 0;
while ((bio = req->bio) != NULL) {
@@ -1779,8 +1827,6 @@ static int __end_that_request_first(struct request *req, int error,
*/
static void end_that_request_last(struct request *req, int error)
{
- struct gendisk *disk = req->rq_disk;
-
if (blk_rq_tagged(req))
blk_queue_end_tag(req->q, req);
@@ -1792,27 +1838,7 @@ static void end_that_request_last(struct request *req, int error)
blk_delete_timer(req);
- /*
- * Account IO completion. bar_rq isn't accounted as a normal
- * IO on queueing nor completion. Accounting the containing
- * request is enough.
- */
- if (disk && blk_fs_request(req) && req != &req->q->bar_rq) {
- unsigned long duration = jiffies - req->start_time;
- const int rw = rq_data_dir(req);
- struct hd_struct *part;
- int cpu;
-
- cpu = part_stat_lock();
- part = disk_map_sector_rcu(disk, req->sector);
-
- part_stat_inc(cpu, part, ios[rw]);
- part_stat_add(cpu, part, ticks[rw], duration);
- part_round_stats(cpu, part);
- part_dec_in_flight(part);
-
- part_stat_unlock();
- }
+ blk_account_io_done(req);
if (req->end_io)
req->end_io(req, error);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 61a8e2f8fdd0..91fa8e06b6a5 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -309,24 +309,24 @@ static struct kobj_type integrity_ktype = {
/**
* blk_integrity_register - Register a gendisk as being integrity-capable
* @disk: struct gendisk pointer to make integrity-aware
- * @template: integrity profile
+ * @template: optional integrity profile to register
*
* Description: When a device needs to advertise itself as being able
* to send/receive integrity metadata it must use this function to
* register the capability with the block layer. The template is a
* blk_integrity struct with values appropriate for the underlying
- * hardware. See Documentation/block/data-integrity.txt.
+ * hardware. If template is NULL the new profile is allocated but
+ * not filled out. See Documentation/block/data-integrity.txt.
*/
int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
{
struct blk_integrity *bi;
BUG_ON(disk == NULL);
- BUG_ON(template == NULL);
if (disk->integrity == NULL) {
bi = kmem_cache_alloc(integrity_cachep,
- GFP_KERNEL | __GFP_ZERO);
+ GFP_KERNEL | __GFP_ZERO);
if (!bi)
return -1;
@@ -346,13 +346,16 @@ int blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
bi = disk->integrity;
/* Use the provided profile as template */
- bi->name = template->name;
- bi->generate_fn = template->generate_fn;
- bi->verify_fn = template->verify_fn;
- bi->tuple_size = template->tuple_size;
- bi->set_tag_fn = template->set_tag_fn;
- bi->get_tag_fn = template->get_tag_fn;
- bi->tag_size = template->tag_size;
+ if (template != NULL) {
+ bi->name = template->name;
+ bi->generate_fn = template->generate_fn;
+ bi->verify_fn = template->verify_fn;
+ bi->tuple_size = template->tuple_size;
+ bi->set_tag_fn = template->set_tag_fn;
+ bi->get_tag_fn = template->get_tag_fn;
+ bi->tag_size = template->tag_size;
+ } else
+ bi->name = "unsupported";
return 0;
}
diff --git a/block/blk-map.c b/block/blk-map.c
index 2990447f45e9..f103729b462f 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -42,7 +42,7 @@ static int __blk_rq_unmap_user(struct bio *bio)
static int __blk_rq_map_user(struct request_queue *q, struct request *rq,
struct rq_map_data *map_data, void __user *ubuf,
- unsigned int len, int null_mapped, gfp_t gfp_mask)
+ unsigned int len, gfp_t gfp_mask)
{
unsigned long uaddr;
struct bio *bio, *orig_bio;
@@ -63,7 +63,7 @@ static int __blk_rq_map_user(struct request_queue *q, struct request *rq,
if (IS_ERR(bio))
return PTR_ERR(bio);
- if (null_mapped)
+ if (map_data && map_data->null_mapped)
bio->bi_flags |= (1 << BIO_NULL_MAPPED);
orig_bio = bio;
@@ -114,17 +114,15 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
{
unsigned long bytes_read = 0;
struct bio *bio = NULL;
- int ret, null_mapped = 0;
+ int ret;
if (len > (q->max_hw_sectors << 9))
return -EINVAL;
if (!len)
return -EINVAL;
- if (!ubuf) {
- if (!map_data || rq_data_dir(rq) != READ)
- return -EINVAL;
- null_mapped = 1;
- }
+
+ if (!ubuf && (!map_data || !map_data->null_mapped))
+ return -EINVAL;
while (bytes_read != len) {
unsigned long map_len, end, start;
@@ -143,13 +141,16 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq,
map_len -= PAGE_SIZE;
ret = __blk_rq_map_user(q, rq, map_data, ubuf, map_len,
- null_mapped, gfp_mask);
+ gfp_mask);
if (ret < 0)
goto unmap_rq;
if (!bio)
bio = rq->bio;
bytes_read += ret;
ubuf += ret;
+
+ if (map_data)
+ map_data->offset += ret;
}
if (!bio_flagged(bio, BIO_USER_MAPPED))
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index a29cb788e408..e29ddfc73cf4 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -130,6 +130,27 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
return queue_var_show(max_hw_sectors_kb, (page));
}
+static ssize_t queue_nonrot_show(struct request_queue *q, char *page)
+{
+ return queue_var_show(!blk_queue_nonrot(q), page);
+}
+
+static ssize_t queue_nonrot_store(struct request_queue *q, const char *page,
+ size_t count)
+{
+ unsigned long nm;
+ ssize_t ret = queue_var_store(&nm, page, count);
+
+ spin_lock_irq(q->queue_lock);
+ if (nm)
+ queue_flag_clear(QUEUE_FLAG_NONROT, q);
+ else
+ queue_flag_set(QUEUE_FLAG_NONROT, q);
+ spin_unlock_irq(q->queue_lock);
+
+ return ret;
+}
+
static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
{
return queue_var_show(blk_queue_nomerges(q), page);
@@ -146,8 +167,8 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
queue_flag_set(QUEUE_FLAG_NOMERGES, q);
else
queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
-
spin_unlock_irq(q->queue_lock);
+
return ret;
}
@@ -176,6 +197,27 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
return ret;
}
+static ssize_t queue_iostats_show(struct request_queue *q, char *page)
+{
+ return queue_var_show(blk_queue_io_stat(q), page);
+}
+
+static ssize_t queue_iostats_store(struct request_queue *q, const char *page,
+ size_t count)
+{
+ unsigned long stats;
+ ssize_t ret = queue_var_store(&stats, page, count);
+
+ spin_lock_irq(q->queue_lock);
+ if (stats)
+ queue_flag_set(QUEUE_FLAG_IO_STAT, q);
+ else
+ queue_flag_clear(QUEUE_FLAG_IO_STAT, q);
+ spin_unlock_irq(q->queue_lock);
+
+ return ret;
+}
+
static struct queue_sysfs_entry queue_requests_entry = {
.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
.show = queue_requests_show,
@@ -210,6 +252,12 @@ static struct queue_sysfs_entry queue_hw_sector_size_entry = {
.show = queue_hw_sector_size_show,
};
+static struct queue_sysfs_entry queue_nonrot_entry = {
+ .attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
+ .show = queue_nonrot_show,
+ .store = queue_nonrot_store,
+};
+
static struct queue_sysfs_entry queue_nomerges_entry = {
.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
.show = queue_nomerges_show,
@@ -222,6 +270,12 @@ static struct queue_sysfs_entry queue_rq_affinity_entry = {
.store = queue_rq_affinity_store,
};
+static struct queue_sysfs_entry queue_iostats_entry = {
+ .attr = {.name = "iostats", .mode = S_IRUGO | S_IWUSR },
+ .show = queue_iostats_show,
+ .store = queue_iostats_store,
+};
+
static struct attribute *default_attrs[] = {
&queue_requests_entry.attr,
&queue_ra_entry.attr,
@@ -229,8 +283,10 @@ static struct attribute *default_attrs[] = {
&queue_max_sectors_entry.attr,
&queue_iosched_entry.attr,
&queue_hw_sector_size_entry.attr,
+ &queue_nonrot_entry.attr,
&queue_nomerges_entry.attr,
&queue_rq_affinity_entry.attr,
+ &queue_iostats_entry.attr,
NULL,
};
diff --git a/block/blk.h b/block/blk.h
index d2e49af90db5..0dce92c37496 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -99,8 +99,8 @@ static inline int queue_congestion_off_threshold(struct request_queue *q)
static inline int blk_cpu_to_group(int cpu)
{
#ifdef CONFIG_SCHED_MC
- cpumask_t mask = cpu_coregroup_map(cpu);
- return first_cpu(mask);
+ const struct cpumask *mask = cpu_coregroup_mask(cpu);
+ return cpumask_first(mask);
#elif defined(CONFIG_SCHED_SMT)
return first_cpu(per_cpu(cpu_sibling_map, cpu));
#else
@@ -108,4 +108,12 @@ static inline int blk_cpu_to_group(int cpu)
#endif
}
+static inline int blk_do_io_stat(struct request_queue *q)
+{
+ if (q)
+ return blk_queue_io_stat(q);
+
+ return 0;
+}
+
#endif
diff --git a/block/blktrace.c b/block/blktrace.c
index b0a2cae886db..39cc3bfe56e4 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -187,59 +187,12 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
static struct dentry *blk_tree_root;
static DEFINE_MUTEX(blk_tree_mutex);
-static unsigned int root_users;
-
-static inline void blk_remove_root(void)
-{
- if (blk_tree_root) {
- debugfs_remove(blk_tree_root);
- blk_tree_root = NULL;
- }
-}
-
-static void blk_remove_tree(struct dentry *dir)
-{
- mutex_lock(&blk_tree_mutex);
- debugfs_remove(dir);
- if (--root_users == 0)
- blk_remove_root();
- mutex_unlock(&blk_tree_mutex);
-}
-
-static struct dentry *blk_create_tree(const char *blk_name)
-{
- struct dentry *dir = NULL;
- int created = 0;
-
- mutex_lock(&blk_tree_mutex);
-
- if (!blk_tree_root) {
- blk_tree_root = debugfs_create_dir("block", NULL);
- if (!blk_tree_root)
- goto err;
- created = 1;
- }
-
- dir = debugfs_create_dir(blk_name, blk_tree_root);
- if (dir)
- root_users++;
- else {
- /* Delete root only if we created it */
- if (created)
- blk_remove_root();
- }
-
-err:
- mutex_unlock(&blk_tree_mutex);
- return dir;
-}
static void blk_trace_cleanup(struct blk_trace *bt)
{
- relay_close(bt->rchan);
debugfs_remove(bt->msg_file);
debugfs_remove(bt->dropped_file);
- blk_remove_tree(bt->dir);
+ relay_close(bt->rchan);
free_percpu(bt->sequence);
free_percpu(bt->msg_data);
kfree(bt);
@@ -346,7 +299,18 @@ static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
static int blk_remove_buf_file_callback(struct dentry *dentry)
{
+ struct dentry *parent = dentry->d_parent;
debugfs_remove(dentry);
+
+ /*
+ * this will fail for all but the last file, but that is ok. what we
+ * care about is the top level buts->name directory going away, when
+ * the last trace file is gone. Then we don't have to rmdir() that
+ * manually on trace stop, so it nicely solves the issue with
+ * force killing of running traces.
+ */
+
+ debugfs_remove(parent);
return 0;
}
@@ -404,7 +368,15 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
goto err;
ret = -ENOENT;
- dir = blk_create_tree(buts->name);
+
+ if (!blk_tree_root) {
+ blk_tree_root = debugfs_create_dir("block", NULL);
+ if (!blk_tree_root)
+ return -ENOMEM;
+ }
+
+ dir = debugfs_create_dir(buts->name, blk_tree_root);
+
if (!dir)
goto err;
@@ -458,8 +430,6 @@ probe_err:
atomic_dec(&blk_probes_ref);
mutex_unlock(&blk_probe_mutex);
err:
- if (dir)
- blk_remove_tree(dir);
if (bt) {
if (bt->msg_file)
debugfs_remove(bt->msg_file);
diff --git a/block/bsg.c b/block/bsg.c
index e73e50daf3d0..d414bb5607e8 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -42,7 +42,7 @@ struct bsg_device {
int done_cmds;
wait_queue_head_t wq_done;
wait_queue_head_t wq_free;
- char name[BUS_ID_SIZE];
+ char name[20];
int max_queue;
unsigned long flags;
};
@@ -781,7 +781,7 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
mutex_lock(&bsg_mutex);
hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));
- strncpy(bd->name, rq->bsg_dev.class_dev->bus_id, sizeof(bd->name) - 1);
+ strncpy(bd->name, dev_name(rq->bsg_dev.class_dev), sizeof(bd->name) - 1);
dprintk("bound to <%s>, max queue %d\n",
format_dev_t(buf, inode->i_rdev), bd->max_queue);
@@ -992,7 +992,7 @@ int bsg_register_queue(struct request_queue *q, struct device *parent,
if (name)
devname = name;
else
- devname = parent->bus_id;
+ devname = dev_name(parent);
/*
* we need a proper transport to send commands, not a stacked device
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index e8525fa72823..664ebfd092ec 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -84,6 +84,11 @@ struct cfq_data {
*/
struct cfq_rb_root service_tree;
unsigned int busy_queues;
+ /*
+ * Used to track any pending rt requests so we can pre-empt current
+ * non-RT cfqq in service when this value is non-zero.
+ */
+ unsigned int busy_rt_queues;
int rq_in_driver;
int sync_flight;
@@ -562,6 +567,8 @@ static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
BUG_ON(cfq_cfqq_on_rr(cfqq));
cfq_mark_cfqq_on_rr(cfqq);
cfqd->busy_queues++;
+ if (cfq_class_rt(cfqq))
+ cfqd->busy_rt_queues++;
cfq_resort_rr_list(cfqd, cfqq);
}
@@ -581,6 +588,8 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
BUG_ON(!cfqd->busy_queues);
cfqd->busy_queues--;
+ if (cfq_class_rt(cfqq))
+ cfqd->busy_rt_queues--;
}
/*
@@ -1005,6 +1014,20 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
goto expire;
/*
+ * If we have a RT cfqq waiting, then we pre-empt the current non-rt
+ * cfqq.
+ */
+ if (!cfq_class_rt(cfqq) && cfqd->busy_rt_queues) {
+ /*
+ * We simulate this as cfqq timed out so that it gets to bank
+ * the remaining of its time slice.
+ */
+ cfq_log_cfqq(cfqd, cfqq, "preempt");
+ cfq_slice_expired(cfqd, 1);
+ goto new_queue;
+ }
+
+ /*
* The active queue has requests and isn't expired, allow it to
* dispatch.
*/
@@ -1067,6 +1090,13 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
if (RB_EMPTY_ROOT(&cfqq->sort_list))
break;
+ /*
+ * If there is a non-empty RT cfqq waiting for current
+ * cfqq's timeslice to complete, pre-empt this cfqq
+ */
+ if (!cfq_class_rt(cfqq) && cfqd->busy_rt_queues)
+ break;
+
} while (dispatched < max_dispatch);
/*
@@ -1801,6 +1831,12 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
if (rq_is_meta(rq) && !cfqq->meta_pending)
return 1;
+ /*
+ * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice.
+ */
+ if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq))
+ return 1;
+
if (!cfqd->active_cic || !cfq_cfqq_wait_request(cfqq))
return 0;
@@ -1870,7 +1906,8 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
/*
* not the active queue - expire current slice if it is
* idle and has expired it's mean thinktime or this new queue
- * has some old slice time left and is of higher priority
+ * has some old slice time left and is of higher priority or
+ * this new queue is RT and the current one is BE
*/
cfq_preempt_queue(cfqd, cfqq);
cfq_mark_cfqq_must_dispatch(cfqq);
diff --git a/block/genhd.c b/block/genhd.c
index d84a7df1e2a0..397960cf26af 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1084,7 +1084,7 @@ dev_t blk_lookup_devt(const char *name, int partno)
struct gendisk *disk = dev_to_disk(dev);
struct hd_struct *part;
- if (strcmp(dev->bus_id, name))
+ if (strcmp(dev_name(dev), name))
continue;
part = disk_get_part(disk, partno);
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index dcbf1be149f3..f21147f3626a 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -28,351 +28,18 @@
#include <linux/async_tx.h>
#ifdef CONFIG_DMA_ENGINE
-static enum dma_state_client
-dma_channel_add_remove(struct dma_client *client,
- struct dma_chan *chan, enum dma_state state);
-
-static struct dma_client async_tx_dma = {
- .event_callback = dma_channel_add_remove,
- /* .cap_mask == 0 defaults to all channels */
-};
-
-/**
- * dma_cap_mask_all - enable iteration over all operation types
- */
-static dma_cap_mask_t dma_cap_mask_all;
-
-/**
- * chan_ref_percpu - tracks channel allocations per core/opertion
- */
-struct chan_ref_percpu {
- struct dma_chan_ref *ref;
-};
-
-static int channel_table_initialized;
-static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END];
-
-/**
- * async_tx_lock - protect modification of async_tx_master_list and serialize
- * rebalance operations
- */
-static spinlock_t async_tx_lock;
-
-static LIST_HEAD(async_tx_master_list);
-
-/* async_tx_issue_pending_all - start all transactions on all channels */
-void async_tx_issue_pending_all(void)
-{
- struct dma_chan_ref *ref;
-
- rcu_read_lock();
- list_for_each_entry_rcu(ref, &async_tx_master_list, node)
- ref->chan->device->device_issue_pending(ref->chan);
- rcu_read_unlock();
-}
-EXPORT_SYMBOL_GPL(async_tx_issue_pending_all);
-
-/* dma_wait_for_async_tx - spin wait for a transcation to complete
- * @tx: transaction to wait on
- */
-enum dma_status
-dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
-{
- enum dma_status status;
- struct dma_async_tx_descriptor *iter;
- struct dma_async_tx_descriptor *parent;
-
- if (!tx)
- return DMA_SUCCESS;
-
- /* poll through the dependency chain, return when tx is complete */
- do {
- iter = tx;
-
- /* find the root of the unsubmitted dependency chain */
- do {
- parent = iter->parent;
- if (!parent)
- break;
- else
- iter = parent;
- } while (parent);
-
- /* there is a small window for ->parent == NULL and
- * ->cookie == -EBUSY
- */
- while (iter->cookie == -EBUSY)
- cpu_relax();
-
- status = dma_sync_wait(iter->chan, iter->cookie);
- } while (status == DMA_IN_PROGRESS || (iter != tx));
-
- return status;
-}
-EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
-
-/* async_tx_run_dependencies - helper routine for dma drivers to process
- * (start) dependent operations on their target channel
- * @tx: transaction with dependencies
- */
-void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
-{
- struct dma_async_tx_descriptor *dep = tx->next;
- struct dma_async_tx_descriptor *dep_next;
- struct dma_chan *chan;
-
- if (!dep)
- return;
-
- chan = dep->chan;
-
- /* keep submitting up until a channel switch is detected
- * in that case we will be called again as a result of
- * processing the interrupt from async_tx_channel_switch
- */
- for (; dep; dep = dep_next) {
- spin_lock_bh(&dep->lock);
- dep->parent = NULL;
- dep_next = dep->next;
- if (dep_next && dep_next->chan == chan)
- dep->next = NULL; /* ->next will be submitted */
- else
- dep_next = NULL; /* submit current dep and terminate */
- spin_unlock_bh(&dep->lock);
-
- dep->tx_submit(dep);
- }
-
- chan->device->device_issue_pending(chan);
-}
-EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
-
-static void
-free_dma_chan_ref(struct rcu_head *rcu)
-{
- struct dma_chan_ref *ref;
- ref = container_of(rcu, struct dma_chan_ref, rcu);
- kfree(ref);
-}
-
-static void
-init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan)
-{
- INIT_LIST_HEAD(&ref->node);
- INIT_RCU_HEAD(&ref->rcu);
- ref->chan = chan;
- atomic_set(&ref->count, 0);
-}
-
-/**
- * get_chan_ref_by_cap - returns the nth channel of the given capability
- * defaults to returning the channel with the desired capability and the
- * lowest reference count if the index can not be satisfied
- * @cap: capability to match
- * @index: nth channel desired, passing -1 has the effect of forcing the
- * default return value
- */
-static struct dma_chan_ref *
-get_chan_ref_by_cap(enum dma_transaction_type cap, int index)
-{
- struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref;
-
- rcu_read_lock();
- list_for_each_entry_rcu(ref, &async_tx_master_list, node)
- if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
- if (!min_ref)
- min_ref = ref;
- else if (atomic_read(&ref->count) <
- atomic_read(&min_ref->count))
- min_ref = ref;
-
- if (index-- == 0) {
- ret_ref = ref;
- break;
- }
- }
- rcu_read_unlock();
-
- if (!ret_ref)
- ret_ref = min_ref;
-
- if (ret_ref)
- atomic_inc(&ret_ref->count);
-
- return ret_ref;
-}
-
-/**
- * async_tx_rebalance - redistribute the available channels, optimize
- * for cpu isolation in the SMP case, and opertaion isolation in the
- * uniprocessor case
- */
-static void async_tx_rebalance(void)
-{
- int cpu, cap, cpu_idx = 0;
- unsigned long flags;
-
- if (!channel_table_initialized)
- return;
-
- spin_lock_irqsave(&async_tx_lock, flags);
-
- /* undo the last distribution */
- for_each_dma_cap_mask(cap, dma_cap_mask_all)
- for_each_possible_cpu(cpu) {
- struct dma_chan_ref *ref =
- per_cpu_ptr(channel_table[cap], cpu)->ref;
- if (ref) {
- atomic_set(&ref->count, 0);
- per_cpu_ptr(channel_table[cap], cpu)->ref =
- NULL;
- }
- }
-
- for_each_dma_cap_mask(cap, dma_cap_mask_all)
- for_each_online_cpu(cpu) {
- struct dma_chan_ref *new;
- if (NR_CPUS > 1)
- new = get_chan_ref_by_cap(cap, cpu_idx++);
- else
- new = get_chan_ref_by_cap(cap, -1);
-
- per_cpu_ptr(channel_table[cap], cpu)->ref = new;
- }
-
- spin_unlock_irqrestore(&async_tx_lock, flags);
-}
-
-static enum dma_state_client
-dma_channel_add_remove(struct dma_client *client,
- struct dma_chan *chan, enum dma_state state)
-{
- unsigned long found, flags;
- struct dma_chan_ref *master_ref, *ref;
- enum dma_state_client ack = DMA_DUP; /* default: take no action */
-
- switch (state) {
- case DMA_RESOURCE_AVAILABLE:
- found = 0;
- rcu_read_lock();
- list_for_each_entry_rcu(ref, &async_tx_master_list, node)
- if (ref->chan == chan) {
- found = 1;
- break;
- }
- rcu_read_unlock();
-
- pr_debug("async_tx: dma resource available [%s]\n",
- found ? "old" : "new");
-
- if (!found)
- ack = DMA_ACK;
- else
- break;
-
- /* add the channel to the generic management list */
- master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL);
- if (master_ref) {
- /* keep a reference until async_tx is unloaded */
- dma_chan_get(chan);
- init_dma_chan_ref(master_ref, chan);
- spin_lock_irqsave(&async_tx_lock, flags);
- list_add_tail_rcu(&master_ref->node,
- &async_tx_master_list);
- spin_unlock_irqrestore(&async_tx_lock,
- flags);
- } else {
- printk(KERN_WARNING "async_tx: unable to create"
- " new master entry in response to"
- " a DMA_RESOURCE_ADDED event"
- " (-ENOMEM)\n");
- return 0;
- }
-
- async_tx_rebalance();
- break;
- case DMA_RESOURCE_REMOVED:
- found = 0;
- spin_lock_irqsave(&async_tx_lock, flags);
- list_for_each_entry(ref, &async_tx_master_list, node)
- if (ref->chan == chan) {
- /* permit backing devices to go away */
- dma_chan_put(ref->chan);
- list_del_rcu(&ref->node);
- call_rcu(&ref->rcu, free_dma_chan_ref);
- found = 1;
- break;
- }
- spin_unlock_irqrestore(&async_tx_lock, flags);
-
- pr_debug("async_tx: dma resource removed [%s]\n",
- found ? "ours" : "not ours");
-
- if (found)
- ack = DMA_ACK;
- else
- break;
-
- async_tx_rebalance();
- break;
- case DMA_RESOURCE_SUSPEND:
- case DMA_RESOURCE_RESUME:
- printk(KERN_WARNING "async_tx: does not support dma channel"
- " suspend/resume\n");
- break;
- default:
- BUG();
- }
-
- return ack;
-}
-
-static int __init
-async_tx_init(void)
+static int __init async_tx_init(void)
{
- enum dma_transaction_type cap;
-
- spin_lock_init(&async_tx_lock);
- bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
-
- /* an interrupt will never be an explicit operation type.
- * clearing this bit prevents allocation to a slot in 'channel_table'
- */
- clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
-
- for_each_dma_cap_mask(cap, dma_cap_mask_all) {
- channel_table[cap] = alloc_percpu(struct chan_ref_percpu);
- if (!channel_table[cap])
- goto err;
- }
-
- channel_table_initialized = 1;
- dma_async_client_register(&async_tx_dma);
- dma_async_client_chan_request(&async_tx_dma);
+ dmaengine_get();
printk(KERN_INFO "async_tx: api initialized (async)\n");
return 0;
-err:
- printk(KERN_ERR "async_tx: initialization failure\n");
-
- while (--cap >= 0)
- free_percpu(channel_table[cap]);
-
- return 1;
}
static void __exit async_tx_exit(void)
{
- enum dma_transaction_type cap;
-
- channel_table_initialized = 0;
-
- for_each_dma_cap_mask(cap, dma_cap_mask_all)
- if (channel_table[cap])
- free_percpu(channel_table[cap]);
-
- dma_async_client_unregister(&async_tx_dma);
+ dmaengine_put();
}
/**
@@ -387,16 +54,9 @@ __async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
{
/* see if we can keep the chain on one channel */
if (depend_tx &&
- dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
+ dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
return depend_tx->chan;
- else if (likely(channel_table_initialized)) {
- struct dma_chan_ref *ref;
- int cpu = get_cpu();
- ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref;
- put_cpu();
- return ref ? ref->chan : NULL;
- } else
- return NULL;
+ return dma_find_channel(tx_type);
}
EXPORT_SYMBOL_GPL(__async_tx_find_channel);
#else
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 40b6e9ec9e3a..5793b64c81a8 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -158,16 +158,19 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
dstp = sg_page(dst);
vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
- sg_init_table(cipher, 2);
- sg_set_buf(cipher, iv, ivsize);
- authenc_chain(cipher, dst, vdst == iv + ivsize);
+ if (ivsize) {
+ sg_init_table(cipher, 2);
+ sg_set_buf(cipher, iv, ivsize);
+ authenc_chain(cipher, dst, vdst == iv + ivsize);
+ dst = cipher;
+ }
cryptlen = req->cryptlen + ivsize;
- hash = crypto_authenc_hash(req, flags, cipher, cryptlen);
+ hash = crypto_authenc_hash(req, flags, dst, cryptlen);
if (IS_ERR(hash))
return PTR_ERR(hash);
- scatterwalk_map_and_copy(hash, cipher, cryptlen,
+ scatterwalk_map_and_copy(hash, dst, cryptlen,
crypto_aead_authsize(authenc), 1);
return 0;
}
@@ -285,11 +288,14 @@ static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
srcp = sg_page(src);
vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
- sg_init_table(cipher, 2);
- sg_set_buf(cipher, iv, ivsize);
- authenc_chain(cipher, src, vsrc == iv + ivsize);
+ if (ivsize) {
+ sg_init_table(cipher, 2);
+ sg_set_buf(cipher, iv, ivsize);
+ authenc_chain(cipher, src, vsrc == iv + ivsize);
+ src = cipher;
+ }
- return crypto_authenc_verify(req, cipher, cryptlen + ivsize);
+ return crypto_authenc_verify(req, src, cryptlen + ivsize);
}
static int crypto_authenc_decrypt(struct aead_request *req)
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 4a7e65c4df4d..d70a41c002df 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -124,6 +124,7 @@ int blkcipher_walk_done(struct blkcipher_desc *desc,
scatterwalk_done(&walk->in, 0, nbytes);
scatterwalk_done(&walk->out, 1, nbytes);
+err:
walk->total = nbytes;
walk->nbytes = nbytes;
@@ -132,7 +133,6 @@ int blkcipher_walk_done(struct blkcipher_desc *desc,
return blkcipher_walk_next(desc, walk);
}
-err:
if (walk->iv != desc->info)
memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm));
if (walk->buffer != walk->page)
diff --git a/crypto/ccm.c b/crypto/ccm.c
index 7cf7e5a6b781..c36d654cf56a 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -266,6 +266,8 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
if (assoclen) {
pctx->ilen = format_adata(idata, assoclen);
get_data_to_compute(cipher, pctx, req->assoc, req->assoclen);
+ } else {
+ pctx->ilen = 0;
}
/* compute plaintext into mac */
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 2f557f570ade..00cf9553f740 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -107,4 +107,6 @@ source "drivers/uio/Kconfig"
source "drivers/xen/Kconfig"
source "drivers/staging/Kconfig"
+
+source "drivers/platform/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index fceb71a741c3..c1bf41737936 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -18,6 +18,9 @@ obj-$(CONFIG_ARM_AMBA) += amba/
obj-$(CONFIG_XEN) += xen/
+# regulators early, since some subsystems rely on them to initialize
+obj-$(CONFIG_REGULATOR) += regulator/
+
# char/ comes before serial/ etc so that the VT console is the boot-time
# default.
obj-y += char/
@@ -57,6 +60,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_UWB) += uwb/
+obj-$(CONFIG_USB_OTG_UTILS) += usb/otg/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/
obj-$(CONFIG_PCI) += usb/
@@ -100,5 +104,5 @@ obj-$(CONFIG_PPC_PS3) += ps3/
obj-$(CONFIG_OF) += of/
obj-$(CONFIG_SSB) += ssb/
obj-$(CONFIG_VIRTIO) += virtio/
-obj-$(CONFIG_REGULATOR) += regulator/
obj-$(CONFIG_STAGING) += staging/
+obj-y += platform/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index b0243fd55ac0..d7f9839ba264 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -196,90 +196,6 @@ config ACPI_NUMA
depends on (X86 || IA64)
default y if IA64_GENERIC || IA64_SGI_SN2
-config ACPI_WMI
- tristate "WMI (EXPERIMENTAL)"
- depends on X86
- depends on EXPERIMENTAL
- help
- This driver adds support for the ACPI-WMI (Windows Management
- Instrumentation) mapper device (PNP0C14) found on some systems.
-
- ACPI-WMI is a proprietary extension to ACPI to expose parts of the
- ACPI firmware to userspace - this is done through various vendor
- defined methods and data blocks in a PNP0C14 device, which are then
- made available for userspace to call.
-
- The implementation of this in Linux currently only exposes this to
- other kernel space drivers.
-
- This driver is a required dependency to build the firmware specific
- drivers needed on many machines, including Acer and HP laptops.
-
- It is safe to enable this driver even if your DSDT doesn't define
- any ACPI-WMI devices.
-
-config ACPI_ASUS
- tristate "ASUS/Medion Laptop Extras"
- depends on X86
- select BACKLIGHT_CLASS_DEVICE
- ---help---
- This driver provides support for extra features of ACPI-compatible
- ASUS laptops. As some of Medion laptops are made by ASUS, it may also
- support some Medion laptops (such as 9675 for example). It makes all
- the extra buttons generate standard ACPI events that go through
- /proc/acpi/events, and (on some models) adds support for changing the
- display brightness and output, switching the LCD backlight on and off,
- and most importantly, allows you to blink those fancy LEDs intended
- for reporting mail and wireless status.
-
- Note: display switching code is currently considered EXPERIMENTAL,
- toying with these values may even lock your machine.
-
- All settings are changed via /proc/acpi/asus directory entries. Owner
- and group for these entries can be set with asus_uid and asus_gid
- parameters.
-
- More information and a userspace daemon for handling the extra buttons
- at <http://sourceforge.net/projects/acpi4asus/>.
-
- If you have an ACPI-compatible ASUS laptop, say Y or M here. This
- driver is still under development, so if your laptop is unsupported or
- something works not quite as expected, please use the mailing list
- available on the above page (acpi4asus-user@lists.sourceforge.net).
-
- NOTE: This driver is deprecated and will probably be removed soon,
- use asus-laptop instead.
-
-config ACPI_TOSHIBA
- tristate "Toshiba Laptop Extras"
- depends on X86 && INPUT
- select INPUT_POLLDEV
- select NET
- select RFKILL
- select BACKLIGHT_CLASS_DEVICE
- ---help---
- This driver adds support for access to certain system settings
- on "legacy free" Toshiba laptops. These laptops can be recognized by
- their lack of a BIOS setup menu and APM support.
-
- On these machines, all system configuration is handled through the
- ACPI. This driver is required for access to controls not covered
- by the general ACPI drivers, such as LCD brightness, video output,
- etc.
-
- This driver differs from the non-ACPI Toshiba laptop driver (located
- under "Processor type and features") in several aspects.
- Configuration is accessed by reading and writing text files in the
- /proc tree instead of by program interface to /dev. Furthermore, no
- power management functions are exposed, as those are handled by the
- general ACPI drivers.
-
- More information about this driver is available at
- <http://memebeam.org/toys/ToshibaAcpiDriver>.
-
- If you have a legacy free Toshiba laptop (such as the Libretto L1
- series), say Y.
-
config ACPI_CUSTOM_DSDT_FILE
string "Custom DSDT Table file to include"
default ""
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 3c0c93300f12..65d90c720b5a 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -2,15 +2,8 @@
# Makefile for the Linux ACPI interpreter
#
-export ACPI_CFLAGS
-
-ACPI_CFLAGS := -Os
-
-ifdef CONFIG_ACPI_DEBUG
- ACPI_CFLAGS += -DACPI_DEBUG_OUTPUT
-endif
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
+ccflags-y := -Os
+ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
#
# ACPI Boot-Time Table Parsing
@@ -22,9 +15,13 @@ obj-$(CONFIG_X86) += blacklist.o
# ACPI Core Subsystem (Interpreter)
#
obj-y += osl.o utils.o reboot.o\
- dispatcher/ events/ executer/ hardware/ \
- namespace/ parser/ resources/ tables/ \
- utilities/
+ acpica/
+
+# sleep related files
+obj-y += wakeup.o
+obj-y += sleep.o
+obj-$(CONFIG_ACPI_SLEEP) += proc.o
+
#
# ACPI Bus and Device Drivers
@@ -35,7 +32,6 @@ ifdef CONFIG_CPU_FREQ
processor-objs += processor_perflib.o
endif
-obj-y += sleep/
obj-y += bus.o glue.o
obj-y += scan.o
# Keep EC driver first. Initialization of others depend on it.
@@ -59,9 +55,6 @@ obj-y += power.o
obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
obj-$(CONFIG_ACPI_DEBUG) += debug.o
obj-$(CONFIG_ACPI_NUMA) += numa.o
-obj-$(CONFIG_ACPI_WMI) += wmi.o
-obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
-obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbshc.o
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 63a17b55b39b..7a0f4aa4fa1e 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -20,7 +20,7 @@
*
*
* ACPI based HotPlug driver that supports Memory Hotplug
- * This driver fields notifications from firmare for memory add
+ * This driver fields notifications from firmware for memory add
* and remove operations and alerts the VM of the affected memory
* ranges.
*/
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
new file mode 100644
index 000000000000..3f23298ee3fd
--- /dev/null
+++ b/drivers/acpi/acpica/Makefile
@@ -0,0 +1,44 @@
+#
+# Makefile for ACPICA Core interpreter
+#
+
+ccflags-y := -Os
+ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
+
+obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \
+ dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \
+ dsinit.o
+
+obj-y += evevent.o evregion.o evsci.o evxfevnt.o \
+ evmisc.o evrgnini.o evxface.o evxfregn.o \
+ evgpe.o evgpeblk.o
+
+obj-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
+ exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\
+ excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \
+ exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o
+
+obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o
+
+obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
+
+obj-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
+ nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
+ nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
+ nsparse.o nspredef.o
+
+obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
+
+obj-y += psargs.o psparse.o psloop.o pstree.o pswalk.o \
+ psopcode.o psscope.o psutils.o psxface.o
+
+obj-y += rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
+ rscalc.o rsirq.o rsmemory.o rsutils.o
+
+obj-$(ACPI_FUTURE_USAGE) += rsdump.o
+
+obj-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
+
+obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
+ utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
+ utstate.o utmutex.o utobject.o utresrc.o
diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h
new file mode 100644
index 000000000000..3b20786cbb0d
--- /dev/null
+++ b/drivers/acpi/acpica/accommon.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ * Name: accommon.h - Common include files for generation of ACPICA source
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef __ACCOMMON_H__
+#define __ACCOMMON_H__
+
+/*
+ * Common set of includes for all ACPICA source files.
+ * We put them here because we don't want to duplicate them
+ * in the the source code again and again.
+ *
+ * Note: The order of these include files is important.
+ */
+#include "acconfig.h" /* Global configuration constants */
+#include "acmacros.h" /* C macros */
+#include "aclocal.h" /* Internal data types */
+#include "acobject.h" /* ACPI internal object */
+#include "acstruct.h" /* Common structures */
+#include "acglobal.h" /* All global variables */
+#include "achware.h" /* Hardware defines and interfaces */
+#include "acutils.h" /* Utility interfaces */
+
+#endif /* __ACCOMMON_H__ */
diff --git a/include/acpi/acconfig.h b/drivers/acpi/acpica/acconfig.h
index 29feee27f0ea..e6777fb883d2 100644
--- a/include/acpi/acconfig.h
+++ b/drivers/acpi/acpica/acconfig.h
@@ -61,10 +61,6 @@
*
*/
-/* Current ACPICA subsystem version in YYYYMMDD format */
-
-#define ACPI_CA_VERSION 0x20080926
-
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
* but there is a large base of ASL/AML code in existing machines that check
@@ -119,6 +115,10 @@
#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4
+/* Maximum number of While() loop iterations before forced abort */
+
+#define ACPI_MAX_LOOP_ITERATIONS 0xFFFF
+
/******************************************************************************
*
* ACPI Specification constants (Do not change unless the specification changes)
diff --git a/include/acpi/acdebug.h b/drivers/acpi/acpica/acdebug.h
index 62c59df3b86c..62c59df3b86c 100644
--- a/include/acpi/acdebug.h
+++ b/drivers/acpi/acpica/acdebug.h
diff --git a/include/acpi/acdispat.h b/drivers/acpi/acpica/acdispat.h
index 6291904be01e..6291904be01e 100644
--- a/include/acpi/acdispat.h
+++ b/drivers/acpi/acpica/acdispat.h
diff --git a/include/acpi/acevents.h b/drivers/acpi/acpica/acevents.h
index d5d099bf349c..07e20135f01b 100644
--- a/include/acpi/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -93,11 +93,13 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
*/
u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info);
-acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback);
+acpi_status
+acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context);
acpi_status
acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+ struct acpi_gpe_block_info *gpe_block,
+ void *context);
acpi_status
acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
diff --git a/include/acpi/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 15dda46b70d1..ddb40f5c68fc 100644
--- a/include/acpi/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -102,6 +102,12 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE);
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
+/*
+ * Optionally use default values for the ACPI register widths. Set this to
+ * TRUE to use the defaults, if an FADT contains incorrect widths/lengths.
+ */
+ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
+
/*****************************************************************************
*
* Debug support
@@ -140,7 +146,7 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags;
*/
ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list;
ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT;
-extern u8 acpi_gbl_permanent_mmap;
+ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS;
/* These addresses are calculated from FADT address values */
@@ -326,6 +332,7 @@ ACPI_EXTERN struct acpi_fixed_event_handler
ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
ACPI_EXTERN struct acpi_gpe_block_info
*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
+ACPI_EXTERN u32 acpi_current_gpe_count;
/*****************************************************************************
*
diff --git a/include/acpi/achware.h b/drivers/acpi/acpica/achware.h
index 97a72b193276..58c69dc49ab4 100644
--- a/include/acpi/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -44,11 +44,7 @@
#ifndef __ACHWARE_H__
#define __ACHWARE_H__
-/* PM Timer ticks per second (HZ) */
-
-#define PM_TIMER_FREQUENCY 3579545
-
-/* Values for the _SST reserved method */
+/* Values for the _SST predefined method */
#define ACPI_SST_INDICATOR_OFF 0
#define ACPI_SST_WORKING 1
@@ -56,8 +52,6 @@
#define ACPI_SST_SLEEPING 3
#define ACPI_SST_SLEEP_CONTEXT 4
-/* Prototypes */
-
/*
* hwacpi - high level functions
*/
@@ -75,13 +69,6 @@ acpi_hw_register_read(u32 register_id, u32 * return_value);
acpi_status acpi_hw_register_write(u32 register_id, u32 value);
-acpi_status
-acpi_hw_low_level_read(u32 width,
- u32 * value, struct acpi_generic_address *reg);
-
-acpi_status
-acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address *reg);
-
acpi_status acpi_hw_clear_acpi_status(void);
/*
@@ -94,13 +81,13 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+ struct acpi_gpe_block_info *gpe_block, void *context);
acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+ struct acpi_gpe_block_info *gpe_block, void *context);
acpi_status
acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
@@ -114,7 +101,8 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void);
acpi_status
acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+ struct acpi_gpe_block_info *gpe_block,
+ void *context);
#ifdef ACPI_FUTURE_USAGE
/*
diff --git a/include/acpi/acinterp.h b/drivers/acpi/acpica/acinterp.h
index e8db7a3143a5..e8db7a3143a5 100644
--- a/include/acpi/acinterp.h
+++ b/drivers/acpi/acpica/acinterp.h
diff --git a/include/acpi/aclocal.h b/drivers/acpi/acpica/aclocal.h
index ecab527cf78e..492d02761bb7 100644
--- a/include/acpi/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -46,8 +46,6 @@
/* acpisrc:struct_defs -- for acpisrc conversion */
-#define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */
-#define ACPI_DO_NOT_WAIT 0
#define ACPI_SERIALIZED 0xFF
typedef u32 acpi_mutex_handle;
@@ -120,11 +118,6 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
#define ACPI_MAX_LOCK 1
#define ACPI_NUM_LOCK ACPI_MAX_LOCK+1
-/* Owner IDs are used to track namespace nodes for selective deletion */
-
-typedef u8 acpi_owner_id;
-#define ACPI_OWNER_ID_MAX 0xFF
-
/* This Thread ID means that the mutex is not in use (unlocked) */
#define ACPI_MUTEX_NOT_ACQUIRED (acpi_thread_id) 0
@@ -165,11 +158,6 @@ typedef enum {
ACPI_IMODE_EXECUTE = 0x03
} acpi_interpreter_mode;
-union acpi_name_union {
- u32 integer;
- char ascii[4];
-};
-
/*
* The Namespace Node describes a named object that appears in the AML.
* descriptor_type is used to differentiate between internal descriptors.
@@ -216,26 +204,6 @@ struct acpi_namespace_node {
#define ANOBJ_IS_BIT_OFFSET 0x40 /* i_aSL only: Reference is a bit offset */
#define ANOBJ_IS_REFERENCED 0x80 /* i_aSL only: Object was referenced */
-/*
- * ACPI Table Descriptor. One per ACPI table
- */
-struct acpi_table_desc {
- acpi_physical_address address;
- struct acpi_table_header *pointer;
- u32 length; /* Length fixed at 32 bits */
- union acpi_name_union signature;
- acpi_owner_id owner_id;
- u8 flags;
-};
-
-/* Flags for above */
-
-#define ACPI_TABLE_ORIGIN_UNKNOWN (0)
-#define ACPI_TABLE_ORIGIN_MAPPED (1)
-#define ACPI_TABLE_ORIGIN_ALLOCATED (2)
-#define ACPI_TABLE_ORIGIN_MASK (3)
-#define ACPI_TABLE_IS_LOADED (4)
-
/* One internal RSDT for table management */
struct acpi_internal_rsdt {
@@ -266,15 +234,6 @@ struct acpi_ns_search_data {
struct acpi_namespace_node *node;
};
-/*
- * Predefined Namespace items
- */
-struct acpi_predefined_names {
- char *name;
- u8 type;
- char *val;
-};
-
/* Object types used during package copies */
#define ACPI_COPY_TYPE_SIMPLE 0
@@ -487,10 +446,15 @@ struct acpi_gpe_walk_info {
struct acpi_gpe_block_info *gpe_block;
};
-typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
- gpe_xrupt_info,
- struct acpi_gpe_block_info *
- gpe_block);
+struct acpi_gpe_device_info {
+ u32 index;
+ u32 next_block_base_index;
+ acpi_status status;
+ struct acpi_namespace_node *gpe_device;
+};
+
+typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block, void *context);
/* Information about each particular fixed event */
@@ -566,6 +530,7 @@ struct acpi_control_state {
union acpi_parse_object *predicate_op;
u8 *aml_predicate_start; /* Start of if/while predicate */
u8 *package_end; /* End of if/while block */
+ u32 loop_count; /* While() loop counter */
};
/*
@@ -671,6 +636,12 @@ union acpi_parse_value {
union acpi_parse_object *arg; /* arguments and contained ops */
};
+#ifdef ACPI_DISASSEMBLER
+#define ACPI_DISASM_ONLY_MEMBERS(a) a;
+#else
+#define ACPI_DISASM_ONLY_MEMBERS(a)
+#endif
+
#define ACPI_PARSE_COMMON \
union acpi_parse_object *parent; /* Parent op */\
u8 descriptor_type; /* To differentiate various internal objs */\
@@ -790,9 +761,6 @@ struct acpi_parse_state {
*
****************************************************************************/
-#define PCI_ROOT_HID_STRING "PNP0A03"
-#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08"
-
struct acpi_bit_register_info {
u8 parent_register;
u8 bit_position;
@@ -1019,26 +987,4 @@ struct acpi_debug_mem_block {
#define ACPI_MEM_LIST_MAX 1
#define ACPI_NUM_MEM_LISTS 2
-struct acpi_memory_list {
- char *list_name;
- void *list_head;
- u16 object_size;
- u16 max_depth;
- u16 current_depth;
- u16 link_offset;
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-
- /* Statistics for debug memory tracking only */
-
- u32 total_allocated;
- u32 total_freed;
- u32 max_occupied;
- u32 total_size;
- u32 current_total_size;
- u32 requests;
- u32 hits;
-#endif
-};
-
#endif /* __ACLOCAL_H__ */
diff --git a/include/acpi/acmacros.h b/drivers/acpi/acpica/acmacros.h
index a597207e2835..9c127e8e2d6d 100644
--- a/include/acpi/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -45,23 +45,6 @@
#define __ACMACROS_H__
/*
- * Data manipulation macros
- */
-#define ACPI_LOWORD(l) ((u16)(u32)(l))
-#define ACPI_HIWORD(l) ((u16)((((u32)(l)) >> 16) & 0xFFFF))
-#define ACPI_LOBYTE(l) ((u8)(u16)(l))
-#define ACPI_HIBYTE(l) ((u8)((((u16)(l)) >> 8) & 0xFF))
-
-#define ACPI_SET_BIT(target,bit) ((target) |= (bit))
-#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit))
-#define ACPI_MIN(a,b) (((a)<(b))?(a):(b))
-#define ACPI_MAX(a,b) (((a)>(b))?(a):(b))
-
-/* Size calculation */
-
-#define ACPI_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
-
-/*
* Extract data using a pointer. Any more than a byte and we
* get into potential aligment issues -- see the STORE macros below.
* Use with care.
@@ -76,39 +59,6 @@
#define ACPI_SET64(ptr) *ACPI_CAST_PTR (u64, ptr)
/*
- * Pointer manipulation
- */
-#define ACPI_CAST_PTR(t, p) ((t *) (acpi_uintptr_t) (p))
-#define ACPI_CAST_INDIRECT_PTR(t, p) ((t **) (acpi_uintptr_t) (p))
-#define ACPI_ADD_PTR(t, a, b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8, (a)) + (acpi_size)(b)))
-#define ACPI_PTR_DIFF(a, b) (acpi_size) (ACPI_CAST_PTR (u8, (a)) - ACPI_CAST_PTR (u8, (b)))
-
-/* Pointer/Integer type conversions */
-
-#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) NULL, (acpi_size) i)
-#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) NULL)
-#define ACPI_OFFSET(d, f) (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f), (void *) NULL)
-#define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i)
-#define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i)
-
-#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
-#define ACPI_COMPARE_NAME(a, b) (*ACPI_CAST_PTR (u32, (a)) == *ACPI_CAST_PTR (u32, (b)))
-#else
-#define ACPI_COMPARE_NAME(a, b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE))
-#endif
-
-/*
- * Full 64-bit integer must be available on both 32-bit and 64-bit platforms
- */
-struct acpi_integer_overlay {
- u32 lo_dword;
- u32 hi_dword;
-};
-
-#define ACPI_LODWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->lo_dword)
-#define ACPI_HIDWORD(integer) (ACPI_CAST_PTR (struct acpi_integer_overlay, &integer)->hi_dword)
-
-/*
* printf() format helpers
*/
@@ -209,7 +159,7 @@ struct acpi_integer_overlay {
/*
* The hardware does not support unaligned transfers. We must move the
* data one byte at a time. These macros work whether the source or
- * the destination (or both) is/are unaligned. (Little-endian move)
+ * the destination (or both) is/are unaligned. (Little-endian move)
*/
/* 16-bit source, 16/32/64 destination */
@@ -333,8 +283,8 @@ struct acpi_integer_overlay {
#define ACPI_INSERT_BITS(target, mask, source) target = ((target & (~(mask))) | (source & mask))
/*
- * An struct acpi_namespace_node can appear in some contexts
- * where a pointer to an union acpi_operand_object can also
+ * A struct acpi_namespace_node can appear in some contexts
+ * where a pointer to a union acpi_operand_object can also
* appear. This macro is used to distinguish them.
*
* The "Descriptor" field is the first field in both structures.
@@ -357,12 +307,6 @@ struct acpi_integer_overlay {
{(u32)(Pargs), (u32)(Iargs), (u32)(flags), obj_type, class, type}
#endif
-#ifdef ACPI_DISASSEMBLER
-#define ACPI_DISASM_ONLY_MEMBERS(a) a;
-#else
-#define ACPI_DISASM_ONLY_MEMBERS(a)
-#endif
-
#define ARG_TYPE_WIDTH 5
#define ARG_1(x) ((u32)(x))
#define ARG_2(x) ((u32)(x) << (1 * ARG_TYPE_WIDTH))
@@ -388,32 +332,16 @@ struct acpi_integer_overlay {
#define GET_CURRENT_ARG_TYPE(list) (list & ((u32) 0x1F))
#define INCREMENT_ARG_LIST(list) (list >>= ((u32) ARG_TYPE_WIDTH))
-#if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES)
-/*
- * Module name is include in both debug and non-debug versions primarily for
- * error messages. The __FILE__ macro is not very useful for this, because it
- * often includes the entire pathname to the module
- */
-#define ACPI_MODULE_NAME(name) static const char ACPI_UNUSED_VAR _acpi_module_name[] = name;
-#else
-#define ACPI_MODULE_NAME(name)
-#endif
-
/*
* Ascii error messages can be configured out
*/
#ifndef ACPI_NO_ERROR_MESSAGES
-#define AE_INFO _acpi_module_name, __LINE__
/*
* Error reporting. Callers module and line number are inserted by AE_INFO,
* the plist contains a set of parens to allow variable-length lists.
* These macros are used for both the debug and non-debug versions of the code.
*/
-#define ACPI_INFO(plist) acpi_ut_info plist
-#define ACPI_WARNING(plist) acpi_ut_warning plist
-#define ACPI_EXCEPTION(plist) acpi_ut_exception plist
-#define ACPI_ERROR(plist) acpi_ut_error plist
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e);
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
@@ -421,13 +349,9 @@ struct acpi_integer_overlay {
/* No error messages */
-#define ACPI_INFO(plist)
-#define ACPI_WARNING(plist)
-#define ACPI_EXCEPTION(plist)
-#define ACPI_ERROR(plist)
#define ACPI_ERROR_NAMESPACE(s, e)
#define ACPI_ERROR_METHOD(s, n, p, e)
-#endif
+#endif /* ACPI_NO_ERROR_MESSAGES */
/*
* Debug macros that are conditionally compiled
@@ -435,36 +359,8 @@ struct acpi_integer_overlay {
#ifdef ACPI_DEBUG_OUTPUT
/*
- * Common parameters used for debug output functions:
- * line number, function name, module(file) name, component ID
- */
-#define ACPI_DEBUG_PARAMETERS __LINE__, ACPI_GET_FUNCTION_NAME, _acpi_module_name, _COMPONENT
-
-/*
* Function entry tracing
*/
-
-/*
- * If ACPI_GET_FUNCTION_NAME was not defined in the compiler-dependent header,
- * define it now. This is the case where there the compiler does not support
- * a __func__ macro or equivalent.
- */
-#ifndef ACPI_GET_FUNCTION_NAME
-#define ACPI_GET_FUNCTION_NAME _acpi_function_name
-/*
- * The Name parameter should be the procedure name as a quoted string.
- * The function name is also used by the function exit macros below.
- * Note: (const char) is used to be compatible with the debug interfaces
- * and macros such as __func__.
- */
-#define ACPI_FUNCTION_NAME(name) static const char _acpi_function_name[] = #name;
-
-#else
-/* Compiler supports __func__ (or equivalent) -- Ignore this macro */
-
-#define ACPI_FUNCTION_NAME(name)
-#endif
-
#ifdef CONFIG_ACPI_DEBUG_FUNC_TRACE
#define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \
@@ -584,15 +480,6 @@ struct acpi_integer_overlay {
#define ACPI_DUMP_RESOURCE_LIST(a) acpi_rs_dump_resource_list(a)
#define ACPI_DUMP_BUFFER(a, b) acpi_ut_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
-/*
- * Master debug print macros
- * Print iff:
- * 1) Debug print for the current component is enabled
- * 2) Debug error level or trace level for the print statement is enabled
- */
-#define ACPI_DEBUG_PRINT(plist) acpi_ut_debug_print plist
-#define ACPI_DEBUG_PRINT_RAW(plist) acpi_ut_debug_print_raw plist
-
#else
/*
* This is the non-debug case -- make everything go away,
@@ -603,7 +490,6 @@ struct acpi_integer_overlay {
#define ACPI_DEBUG_DEFINE(a) do { } while(0)
#define ACPI_DEBUG_ONLY_MEMBERS(a) do { } while(0)
-#define ACPI_FUNCTION_NAME(a) do { } while(0)
#define ACPI_FUNCTION_TRACE(a) do { } while(0)
#define ACPI_FUNCTION_TRACE_PTR(a, b) do { } while(0)
#define ACPI_FUNCTION_TRACE_U32(a, b) do { } while(0)
@@ -619,8 +505,6 @@ struct acpi_integer_overlay {
#define ACPI_DUMP_PATHNAME(a, b, c, d) do { } while(0)
#define ACPI_DUMP_RESOURCE_LIST(a) do { } while(0)
#define ACPI_DUMP_BUFFER(a, b) do { } while(0)
-#define ACPI_DEBUG_PRINT(pl) do { } while(0)
-#define ACPI_DEBUG_PRINT_RAW(pl) do { } while(0)
#define return_VOID return
#define return_ACPI_STATUS(s) return(s)
@@ -629,7 +513,7 @@ struct acpi_integer_overlay {
#define return_UINT32(s) return(s)
#define return_PTR(s) return(s)
-#endif
+#endif /* ACPI_DEBUG_OUTPUT */
/*
* Some code only gets executed when the debugger is built in.
diff --git a/include/acpi/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index db4e6f677855..46cb5b46d280 100644
--- a/include/acpi/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -182,7 +182,9 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
*/
acpi_status
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
- union acpi_operand_object *return_object);
+ u32 user_param_count,
+ acpi_status return_status,
+ union acpi_operand_object **return_object);
const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
acpi_namespace_node
@@ -191,6 +193,7 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
void
acpi_ns_check_parameter_count(char *pathname,
struct acpi_namespace_node *node,
+ u32 user_param_count,
const union acpi_predefined_info *info);
/*
diff --git a/include/acpi/acobject.h b/drivers/acpi/acpica/acobject.h
index eb6f038b03d9..eb6f038b03d9 100644
--- a/include/acpi/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
diff --git a/include/acpi/acopcode.h b/drivers/acpi/acpica/acopcode.h
index dfdf63327885..dfdf63327885 100644
--- a/include/acpi/acopcode.h
+++ b/drivers/acpi/acpica/acopcode.h
diff --git a/include/acpi/acparser.h b/drivers/acpi/acpica/acparser.h
index 23ee0fbf5619..23ee0fbf5619 100644
--- a/include/acpi/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
diff --git a/include/acpi/acpredef.h b/drivers/acpi/acpica/acpredef.h
index 16a9ca9a66e4..16a9ca9a66e4 100644
--- a/include/acpi/acpredef.h
+++ b/drivers/acpi/acpica/acpredef.h
diff --git a/include/acpi/acresrc.h b/drivers/acpi/acpica/acresrc.h
index eef5bd7a59fa..eef5bd7a59fa 100644
--- a/include/acpi/acresrc.h
+++ b/drivers/acpi/acpica/acresrc.h
diff --git a/include/acpi/acstruct.h b/drivers/acpi/acpica/acstruct.h
index 7980a26bad35..7980a26bad35 100644
--- a/include/acpi/acstruct.h
+++ b/drivers/acpi/acpica/acstruct.h
diff --git a/include/acpi/actables.h b/drivers/acpi/acpica/actables.h
index 0cbe1b9ab522..7ce6e33c7f78 100644
--- a/include/acpi/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -94,6 +94,8 @@ void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
/*
* tbutils - table manager utilities
*/
+acpi_status acpi_tb_initialize_facs(void);
+
u8 acpi_tb_tables_loaded(void);
void
diff --git a/include/acpi/acutils.h b/drivers/acpi/acpica/acutils.h
index d8307b2987e3..80d8813484fe 100644
--- a/include/acpi/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -297,42 +297,6 @@ void acpi_ut_report_info(char *module_name, u32 line_number);
void acpi_ut_report_warning(char *module_name, u32 line_number);
-/* Error and message reporting interfaces */
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print(u32 requested_debug_level,
- u32 line_number,
- const char *function_name,
- const char *module_name,
- u32 component_id,
- const char *format, ...) ACPI_PRINTF_LIKE(6);
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print_raw(u32 requested_debug_level,
- u32 line_number,
- const char *function_name,
- const char *module_name,
- u32 component_id,
- const char *format, ...) ACPI_PRINTF_LIKE(6);
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_error(const char *module_name,
- u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_exception(const char *module_name,
- u32 line_number,
- acpi_status status,
- const char *format, ...) ACPI_PRINTF_LIKE(4);
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_warning(const char *module_name,
- u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_info(const char *module_name,
- u32 line_number, const char *format, ...) ACPI_PRINTF_LIKE(3);
-
/*
* utdelete - Object deletion and reference counts
*/
diff --git a/include/acpi/amlcode.h b/drivers/acpi/acpica/amlcode.h
index ff851c5df698..ff851c5df698 100644
--- a/include/acpi/amlcode.h
+++ b/drivers/acpi/acpica/amlcode.h
diff --git a/include/acpi/amlresrc.h b/drivers/acpi/acpica/amlresrc.h
index 7b070e42b7c5..7b070e42b7c5 100644
--- a/include/acpi/amlresrc.h
+++ b/drivers/acpi/acpica/amlresrc.h
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/acpica/dsfield.c
index f988a5e7d2b4..53e27bc5a734 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -42,11 +42,12 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acparser.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsfield")
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/acpica/dsinit.c
index 949f7c75029e..eb144b13d8fa 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/acpica/dsinit.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acdispat.h>
-#include <acpi/acnamesp.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+#include "actables.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsinit")
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 279a5a60a0dd..14b8b8ed8023 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -42,11 +42,14 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#ifdef ACPI_DISASSEMBLER
#include <acpi/acdisasm.h>
+#endif
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsmethod")
@@ -412,6 +415,9 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
status = obj_desc->method.implementation(next_walk_state);
+ if (status == AE_OK) {
+ status = AE_CTRL_TERMINATE;
+ }
}
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c
index d03f81bd1bcb..da0f5468184c 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/acpica/dsmthdat.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acdispat.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsmthdat")
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/acpica/dsobject.c
index 4f08e599d07e..15c628e6aa00 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/acpica/dsobject.c
@@ -42,11 +42,12 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsobject")
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/acpica/dsopcode.c
index 69fae5905bb8..0c3b4dd60e8a 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/acpica/dsopcode.c
@@ -43,13 +43,14 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acevents.h"
+#include "actables.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsopcode")
@@ -1140,10 +1141,29 @@ acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
op->common.aml_opcode, walk_state));
switch (op->common.aml_opcode) {
- case AML_IF_OP:
case AML_WHILE_OP:
/*
+ * If this is an additional iteration of a while loop, continue.
+ * There is no need to allocate a new control state.
+ */
+ if (walk_state->control_state) {
+ if (walk_state->control_state->control.aml_predicate_start
+ == (walk_state->parser_state.aml - 1)) {
+
+ /* Reset the state to start-of-loop */
+
+ walk_state->control_state->common.state =
+ ACPI_CONTROL_CONDITIONAL_EXECUTING;
+ break;
+ }
+ }
+
+ /*lint -fallthrough */
+
+ case AML_IF_OP:
+
+ /*
* IF/WHILE: Create a new control state to manage these
* constructs. We need to manage these as a stack, in order
* to handle nesting.
@@ -1243,13 +1263,36 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
- if (walk_state->control_state->common.value) {
+ control_state = walk_state->control_state;
+ if (control_state->common.value) {
- /* Predicate was true, go back and evaluate it again! */
+ /* Predicate was true, the body of the loop was just executed */
+ /*
+ * This loop counter mechanism allows the interpreter to escape
+ * possibly infinite loops. This can occur in poorly written AML
+ * when the hardware does not respond within a while loop and the
+ * loop does not implement a timeout.
+ */
+ control_state->control.loop_count++;
+ if (control_state->control.loop_count >
+ ACPI_MAX_LOOP_ITERATIONS) {
+ status = AE_AML_INFINITE_LOOP;
+ break;
+ }
+
+ /*
+ * Go back and evaluate the predicate and maybe execute the loop
+ * another time
+ */
status = AE_CTRL_PENDING;
+ walk_state->aml_last_while =
+ control_state->control.aml_predicate_start;
+ break;
}
+ /* Predicate was false, terminate this while loop */
+
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"[WHILE_OP] termination! Op=%p\n", op));
@@ -1257,9 +1300,6 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
control_state =
acpi_ut_pop_generic_state(&walk_state->control_state);
-
- walk_state->aml_last_while =
- control_state->control.aml_predicate_start;
acpi_ut_delete_generic_state(control_state);
break;
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/acpica/dsutils.c
index b398982f0d8b..dabc23a46176 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/acpica/dsutils.c
@@ -42,12 +42,13 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acdebug.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acdebug.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsutils")
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/acpica/dswexec.c
index 396fe12078cd..350e6656bc89 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/acpica/dswexec.c
@@ -43,12 +43,13 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acdebug.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acdebug.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswexec")
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/acpica/dswload.c
index dff7a3e445a8..3023ceaa8d54 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -42,12 +42,13 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acevents.h"
#ifdef ACPI_ASL_COMPILER
#include <acpi/acdisasm.h>
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/acpica/dswscope.c
index 9e6073265873..908645e72f03 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/acpica/dswscope.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acdispat.h>
+#include "accommon.h"
+#include "acdispat.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswscope")
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/acpica/dswstate.c
index b00d4af791aa..40f92bf7dce5 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/acpica/dswstate.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dswstate")
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/acpica/evevent.c
index c56c5c6ea77b..803edd9e3f6a 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/acpica/evevent.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acevents.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evevent")
@@ -72,8 +73,8 @@ acpi_status acpi_ev_initialize_events(void)
/*
* Initialize the Fixed and General Purpose Events. This is done prior to
- * enabling SCIs to prevent interrupts from occurring before the handlers are
- * installed.
+ * enabling SCIs to prevent interrupts from occurring before the handlers
+ * are installed.
*/
status = acpi_ev_fixed_event_initialize();
if (ACPI_FAILURE(status)) {
@@ -192,8 +193,8 @@ static acpi_status acpi_ev_fixed_event_initialize(void)
acpi_status status;
/*
- * Initialize the structure that keeps track of fixed event handlers
- * and enable the fixed events.
+ * Initialize the structure that keeps track of fixed event handlers and
+ * enable the fixed events.
*/
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
acpi_gbl_fixed_event_handlers[i].handler = NULL;
@@ -237,7 +238,7 @@ u32 acpi_ev_fixed_event_detect(void)
/*
* Read the fixed feature status and enable registers, as all the cases
- * depend on their values. Ignore errors here.
+ * depend on their values. Ignore errors here.
*/
(void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
(void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
@@ -291,8 +292,8 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
status_register_id, 1);
/*
- * Make sure we've got a handler. If not, report an error.
- * The event is disabled to prevent further interrupts.
+ * Make sure we've got a handler. If not, report an error. The event is
+ * disabled to prevent further interrupts.
*/
if (NULL == acpi_gbl_fixed_event_handlers[event].handler) {
(void)acpi_set_register(acpi_gbl_fixed_event_info[event].
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/acpica/evgpe.c
index f45c74fe745e..f345ced36477 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpe")
@@ -125,7 +126,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
(1 <<
(gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
- /* 1) Disable case. Simply clear all enable bits */
+ /* 1) Disable case. Simply clear all enable bits */
if (type == ACPI_GPE_DISABLE) {
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
@@ -134,7 +135,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
return_ACPI_STATUS(AE_OK);
}
- /* 2) Enable case. Set/Clear the appropriate enable bits */
+ /* 2) Enable case. Set/Clear the appropriate enable bits */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
@@ -295,7 +296,7 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
*
* FUNCTION: acpi_ev_get_gpe_event_info
*
- * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
+ * PARAMETERS: gpe_device - Device node. NULL for GPE0/GPE1
* gpe_number - Raw GPE number
*
* RETURN: A GPE event_info struct. NULL if not a valid GPE
@@ -372,7 +373,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
- * DESCRIPTION: Detect if any GP events have occurred. This function is
+ * DESCRIPTION: Detect if any GP events have occurred. This function is
* executed at interrupt level.
*
******************************************************************************/
@@ -400,8 +401,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/*
* We need to obtain the GPE lock for both the data structs and registers
- * Note: Not necessary to obtain the hardware lock, since the GPE registers
- * are owned by the gpe_lock.
+ * Note: Not necessary to obtain the hardware lock, since the GPE
+ * registers are owned by the gpe_lock.
*/
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
@@ -410,9 +411,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
gpe_block = gpe_xrupt_list->gpe_block_list_head;
while (gpe_block) {
/*
- * Read all of the 8-bit GPE status and enable registers
- * in this GPE block, saving all of them.
- * Find all currently active GP events.
+ * Read all of the 8-bit GPE status and enable registers in this GPE
+ * block, saving all of them. Find all currently active GP events.
*/
for (i = 0; i < gpe_block->register_count; i++) {
@@ -423,10 +423,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/* Read the Status Register */
status =
- acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
- &status_reg,
- &gpe_register_info->
- status_address);
+ acpi_read(&status_reg,
+ &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -434,10 +432,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/* Read the Enable Register */
status =
- acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH,
- &enable_reg,
- &gpe_register_info->
- enable_address);
+ acpi_read(&enable_reg,
+ &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -527,8 +523,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
(void)acpi_ev_enable_gpe(gpe_event_info, FALSE);
/*
- * Take a snapshot of the GPE info for this level - we copy the
- * info to prevent a race condition with remove_handler/remove_block.
+ * Take a snapshot of the GPE info for this level - we copy the info to
+ * prevent a race condition with remove_handler/remove_block.
*/
ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info,
sizeof(struct acpi_gpe_event_info));
@@ -539,8 +535,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
}
/*
- * Must check for control method type dispatch one more
- * time to avoid race with ev_gpe_install_handler
+ * Must check for control method type dispatch one more time to avoid a
+ * race with ev_gpe_install_handler
*/
if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_METHOD) {
@@ -584,8 +580,8 @@ static void acpi_ev_asynch_enable_gpe(void *context)
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
ACPI_GPE_LEVEL_TRIGGERED) {
/*
- * GPE is level-triggered, we clear the GPE status bit after
- * handling the event.
+ * GPE is level-triggered, we clear the GPE status bit after handling
+ * the event.
*/
status = acpi_hw_clear_gpe(gpe_event_info);
if (ACPI_FAILURE(status)) {
@@ -624,7 +620,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
acpi_os_gpe_count(gpe_number);
/*
- * If edge-triggered, clear the GPE status bit now. Note that
+ * If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced.
*/
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
@@ -650,7 +646,8 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
/*
* Invoke the installed handler (at interrupt level)
- * Ignore return status for now. TBD: leave GPE disabled on error?
+ * Ignore return status for now.
+ * TBD: leave GPE disabled on error?
*/
(void)gpe_event_info->dispatch.handler->address(gpe_event_info->
dispatch.
@@ -708,7 +705,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number)
gpe_number));
/*
- * Disable the GPE. The GPE will remain disabled until the ACPI
+ * Disable the GPE. The GPE will remain disabled until the ACPICA
* Core Subsystem is restarted, or a handler is installed.
*/
status = acpi_ev_disable_gpe(gpe_event_info);
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 73c058e2f5c2..484cc0565d5b 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evgpeblk")
@@ -124,6 +125,7 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
* FUNCTION: acpi_ev_walk_gpe_list
*
* PARAMETERS: gpe_walk_callback - Routine called for each GPE block
+ * Context - Value passed to callback
*
* RETURN: Status
*
@@ -131,7 +133,8 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info)
*
******************************************************************************/
-acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback)
+acpi_status
+acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback, void *context)
{
struct acpi_gpe_block_info *gpe_block;
struct acpi_gpe_xrupt_info *gpe_xrupt_info;
@@ -154,8 +157,13 @@ acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback)
/* One callback per GPE block */
- status = gpe_walk_callback(gpe_xrupt_info, gpe_block);
+ status =
+ gpe_walk_callback(gpe_xrupt_info, gpe_block,
+ context);
if (ACPI_FAILURE(status)) {
+ if (status == AE_CTRL_END) { /* Callback abort */
+ status = AE_OK;
+ }
goto unlock_and_exit;
}
@@ -186,7 +194,8 @@ acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback)
acpi_status
acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+ struct acpi_gpe_block_info *gpe_block,
+ void *context)
{
struct acpi_gpe_event_info *gpe_event_info;
u32 i;
@@ -309,17 +318,17 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
(gpe_block->block_base_number +
(gpe_block->register_count * 8)))) {
/*
- * Not valid for this GPE block, just ignore it
- * However, it may be valid for a different GPE block, since GPE0 and GPE1
- * methods both appear under \_GPE.
+ * Not valid for this GPE block, just ignore it. However, it may be
+ * valid for a different GPE block, since GPE0 and GPE1 methods both
+ * appear under \_GPE.
*/
return_ACPI_STATUS(AE_OK);
}
/*
- * Now we can add this information to the gpe_event_info block
- * for use during dispatch of this GPE. Default type is RUNTIME, although
- * this may change when the _PRW methods are executed later.
+ * Now we can add this information to the gpe_event_info block for use
+ * during dispatch of this GPE. Default type is RUNTIME, although this may
+ * change when the _PRW methods are executed later.
*/
gpe_event_info =
&gpe_block->event_info[gpe_number - gpe_block->block_base_number];
@@ -394,8 +403,8 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
gpe_block = gpe_info->gpe_block;
/*
- * The _PRW object must return a package, we are only interested
- * in the first element
+ * The _PRW object must return a package, we are only interested in the
+ * first element
*/
obj_desc = pkg_desc->package.elements[0];
@@ -434,7 +443,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
/*
* Is this GPE within this block?
*
- * TRUE iff these conditions are true:
+ * TRUE if and only if these conditions are true:
* 1) The GPE devices match.
* 2) The GPE index(number) is within the range of the Gpe Block
* associated with the GPE device.
@@ -457,6 +466,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
if (ACPI_FAILURE(status)) {
goto cleanup;
}
+
status =
acpi_ev_update_gpe_enable_masks(gpe_event_info,
ACPI_GPE_DISABLE);
@@ -476,9 +486,9 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
* RETURN: A GPE interrupt block
*
* DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
- * block per unique interrupt level used for GPEs.
- * Should be called only when the GPE lists are semaphore locked
- * and not subject to change.
+ * block per unique interrupt level used for GPEs. Should be
+ * called only when the GPE lists are semaphore locked and not
+ * subject to change.
*
******************************************************************************/
@@ -608,8 +618,9 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt)
*
* FUNCTION: acpi_ev_install_gpe_block
*
- * PARAMETERS: gpe_block - New GPE block
- * interrupt_number - Xrupt to be associated with this GPE block
+ * PARAMETERS: gpe_block - New GPE block
+ * interrupt_number - Xrupt to be associated with this
+ * GPE block
*
* RETURN: Status
*
@@ -666,7 +677,7 @@ acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
*
* FUNCTION: acpi_ev_delete_gpe_block
*
- * PARAMETERS: gpe_block - Existing GPE block
+ * PARAMETERS: gpe_block - Existing GPE block
*
* RETURN: Status
*
@@ -688,7 +699,8 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
/* Disable all GPEs in this block */
- status = acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block);
+ status =
+ acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL);
if (!gpe_block->previous && !gpe_block->next) {
@@ -715,6 +727,9 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
}
+ acpi_current_gpe_count -=
+ gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH;
+
/* Free the gpe_block */
ACPI_FREE(gpe_block->register_info);
@@ -786,9 +801,9 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
/*
* Initialize the GPE Register and Event structures. A goal of these
- * tables is to hide the fact that there are two separate GPE register sets
- * in a given GPE hardware block, the status registers occupy the first half,
- * and the enable registers occupy the second half.
+ * tables is to hide the fact that there are two separate GPE register
+ * sets in a given GPE hardware block, the status registers occupy the
+ * first half, and the enable registers occupy the second half.
*/
this_register = gpe_register_info;
this_event = gpe_event_info;
@@ -816,10 +831,8 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
ACPI_GPE_REGISTER_WIDTH;
this_register->enable_address.bit_width =
ACPI_GPE_REGISTER_WIDTH;
- this_register->status_address.bit_offset =
- ACPI_GPE_REGISTER_WIDTH;
- this_register->enable_address.bit_offset =
- ACPI_GPE_REGISTER_WIDTH;
+ this_register->status_address.bit_offset = 0;
+ this_register->enable_address.bit_offset = 0;
/* Init the event_info for each GPE within this register */
@@ -832,18 +845,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
/* Disable all GPEs within this register */
- status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0x00,
- &this_register->
- enable_address);
+ status = acpi_write(0x00, &this_register->enable_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
/* Clear any pending GPE events within this register */
- status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, 0xFF,
- &this_register->
- status_address);
+ status = acpi_write(0xFF, &this_register->status_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
@@ -956,6 +965,9 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
gpe_device->name.ascii, gpe_block->register_count,
interrupt_number));
+ /* Update global count of currently available GPEs */
+
+ acpi_current_gpe_count += register_count * ACPI_GPE_REGISTER_WIDTH;
return_ACPI_STATUS(AE_OK);
}
@@ -1055,7 +1067,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
/* Enable all valid runtime GPEs found above */
- status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
+ status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block, NULL);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p",
gpe_block));
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/acpica/evmisc.c
index 1d5670be729a..5f893057bcc6 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/acpica/evmisc.c
@@ -42,18 +42,15 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evmisc")
-/* Pointer to FACS needed for the Global Lock */
-static struct acpi_table_facs *facs = NULL;
-
/* Local prototypes */
-
static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context);
static u32 acpi_ev_global_lock_handler(void *context);
@@ -152,7 +149,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
break;
default:
+
/* All other types are not supported */
+
return (AE_TYPE);
}
}
@@ -193,9 +192,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
acpi_ut_delete_generic_state(notify_info);
}
} else {
- /*
- * There is no notify handler (per-device or system) for this device.
- */
+ /* There is no notify handler (per-device or system) for this device */
+
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No notify handler for Notify (%4.4s, %X) node %p\n",
acpi_ut_get_node_name(node), notify_value,
@@ -229,9 +227,8 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)
ACPI_FUNCTION_ENTRY();
/*
- * We will invoke a global notify handler if installed.
- * This is done _before_ we invoke the per-device handler attached
- * to the device.
+ * We will invoke a global notify handler if installed. This is done
+ * _before_ we invoke the per-device handler attached to the device.
*/
if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) {
@@ -299,7 +296,7 @@ static u32 acpi_ev_global_lock_handler(void *context)
* If we don't get it now, it will be marked pending and we will
* take another interrupt when it becomes free.
*/
- ACPI_ACQUIRE_GLOBAL_LOCK(facs, acquired);
+ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
if (acquired) {
/* Got the lock, now wake all threads waiting for it */
@@ -336,34 +333,27 @@ acpi_status acpi_ev_init_global_lock_handler(void)
ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
- status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
- ACPI_CAST_INDIRECT_PTR(struct
- acpi_table_header,
- &facs));
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
+ /* Attempt installation of the global lock handler */
- acpi_gbl_global_lock_present = TRUE;
status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
acpi_ev_global_lock_handler,
NULL);
/*
- * If the global lock does not exist on this platform, the attempt
- * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)
- * Map to AE_OK, but mark global lock as not present.
- * Any attempt to actually use the global lock will be flagged
- * with an error.
+ * If the global lock does not exist on this platform, the attempt to
+ * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick).
+ * Map to AE_OK, but mark global lock as not present. Any attempt to
+ * actually use the global lock will be flagged with an error.
*/
if (status == AE_NO_HARDWARE_RESPONSE) {
ACPI_ERROR((AE_INFO,
"No response from Global Lock hardware, disabling lock"));
acpi_gbl_global_lock_present = FALSE;
- status = AE_OK;
+ return_ACPI_STATUS(AE_OK);
}
+ acpi_gbl_global_lock_present = TRUE;
return_ACPI_STATUS(status);
}
@@ -462,8 +452,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
}
/*
- * Make sure that a global lock actually exists. If not, just treat
- * the lock as a standard mutex.
+ * Make sure that a global lock actually exists. If not, just treat the
+ * lock as a standard mutex.
*/
if (!acpi_gbl_global_lock_present) {
acpi_gbl_global_lock_acquired = TRUE;
@@ -472,7 +462,7 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout)
/* Attempt to acquire the actual hardware lock */
- ACPI_ACQUIRE_GLOBAL_LOCK(facs, acquired);
+ ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_FACS, acquired);
if (acquired) {
/* We got the lock */
@@ -536,7 +526,7 @@ acpi_status acpi_ev_release_global_lock(void)
/* Allow any thread to release the lock */
- ACPI_RELEASE_GLOBAL_LOCK(facs, pending);
+ ACPI_RELEASE_GLOBAL_LOCK(acpi_gbl_FACS, pending);
/*
* If the pending bit was set, we must write GBL_RLS to the control
@@ -582,8 +572,8 @@ void acpi_ev_terminate(void)
if (acpi_gbl_events_initialized) {
/*
- * Disable all event-related functionality.
- * In all cases, on error, print a message but obviously we don't abort.
+ * Disable all event-related functionality. In all cases, on error,
+ * print a message but obviously we don't abort.
*/
/* Disable all fixed events */
@@ -599,7 +589,7 @@ void acpi_ev_terminate(void)
/* Disable all GPEs in all GPE blocks */
- status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
+ status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
/* Remove SCI handler */
@@ -617,7 +607,7 @@ void acpi_ev_terminate(void)
/* Deallocate all handler objects installed within GPE info structs */
- status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers);
+ status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
/* Return to original mode if necessary */
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/acpica/evregion.c
index 236fbd1ca438..665c0887ab4d 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -42,22 +42,15 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evregion")
-#define ACPI_NUM_DEFAULT_SPACES 4
-static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
- ACPI_ADR_SPACE_SYSTEM_MEMORY,
- ACPI_ADR_SPACE_SYSTEM_IO,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_ADR_SPACE_DATA_TABLE
-};
/* Local prototypes */
-
static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
@@ -66,6 +59,17 @@ static acpi_status
acpi_ev_install_handler(acpi_handle obj_handle,
u32 level, void *context, void **return_value);
+/* These are the address spaces that will get default handlers */
+
+#define ACPI_NUM_DEFAULT_SPACES 4
+
+static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_DATA_TABLE
+};
+
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_region_handlers
@@ -91,18 +95,19 @@ acpi_status acpi_ev_install_region_handlers(void)
}
/*
- * All address spaces (PCI Config, EC, SMBus) are scope dependent
- * and registration must occur for a specific device.
+ * All address spaces (PCI Config, EC, SMBus) are scope dependent and
+ * registration must occur for a specific device.
*
- * In the case of the system memory and IO address spaces there is currently
- * no device associated with the address space. For these we use the root.
+ * In the case of the system memory and IO address spaces there is
+ * currently no device associated with the address space. For these we
+ * use the root.
*
- * We install the default PCI config space handler at the root so
- * that this space is immediately available even though the we have
- * not enumerated all the PCI Root Buses yet. This is to conform
- * to the ACPI specification which states that the PCI config
- * space must be always available -- even though we are nowhere
- * near ready to find the PCI root buses at this point.
+ * We install the default PCI config space handler at the root so that
+ * this space is immediately available even though the we have not
+ * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
+ * specification which states that the PCI config space must be always
+ * available -- even though we are nowhere near ready to find the PCI root
+ * buses at this point.
*
* NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
* has already been installed (via acpi_install_address_space_handler).
@@ -160,12 +165,11 @@ acpi_status acpi_ev_initialize_op_regions(void)
return_ACPI_STATUS(status);
}
- /*
- * Run the _REG methods for op_regions in each default address space
- */
- for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
+ /* Run the _REG methods for op_regions in each default address space */
- /* TBD: Make sure handler is the DEFAULT handler, otherwise
+ for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
+ /*
+ * TBD: Make sure handler is the DEFAULT handler, otherwise
* _REG will have already been run.
*/
status = acpi_ev_execute_reg_methods(acpi_gbl_root_node,
@@ -318,13 +322,13 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
}
/*
- * It may be the case that the region has never been initialized
+ * It may be the case that the region has never been initialized.
* Some types of regions require special init code
*/
if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
- /*
- * This region has not been initialized yet, do it
- */
+
+ /* This region has not been initialized yet, do it */
+
region_setup = handler_desc->address_space.setup;
if (!region_setup) {
@@ -339,9 +343,9 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
}
/*
- * We must exit the interpreter because the region
- * setup will potentially execute control methods
- * (e.g., _REG method for this region)
+ * We must exit the interpreter because the region setup will
+ * potentially execute control methods (for example, the _REG method
+ * for this region)
*/
acpi_ex_exit_interpreter();
@@ -364,9 +368,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
return_ACPI_STATUS(status);
}
- /*
- * Region initialization may have been completed by region_setup
- */
+ /* Region initialization may have been completed by region_setup */
+
if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
@@ -521,8 +524,8 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
}
/*
- * If the region has been activated, call the setup handler
- * with the deactivate notification
+ * If the region has been activated, call the setup handler with
+ * the deactivate notification
*/
if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
region_setup = handler_obj->address_space.setup;
@@ -668,8 +671,8 @@ acpi_ev_install_handler(acpi_handle obj_handle,
}
/*
- * We only care about regions.and objects
- * that are allowed to have address space handlers
+ * We only care about regions and objects that are allowed to have
+ * address space handlers
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
@@ -710,9 +713,9 @@ acpi_ev_install_handler(acpi_handle obj_handle,
/*
* Since the object we found it on was a device, then it
* means that someone has already installed a handler for
- * the branch of the namespace from this device on. Just
+ * the branch of the namespace from this device on. Just
* bail out telling the walk routine to not traverse this
- * branch. This preserves the scoping rule for handlers.
+ * branch. This preserves the scoping rule for handlers.
*/
return (AE_CTRL_DEPTH);
}
@@ -723,9 +726,8 @@ acpi_ev_install_handler(acpi_handle obj_handle,
}
/*
- * As long as the device didn't have a handler for this
- * space we don't care about it. We just ignore it and
- * proceed.
+ * As long as the device didn't have a handler for this space we
+ * don't care about it. We just ignore it and proceed.
*/
return (AE_OK);
}
@@ -733,16 +735,14 @@ acpi_ev_install_handler(acpi_handle obj_handle,
/* Object is a Region */
if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
- /*
- * This region is for a different address space
- * -- just ignore it
- */
+
+ /* This region is for a different address space, just ignore it */
+
return (AE_OK);
}
/*
- * Now we have a region and it is for the handler's address
- * space type.
+ * Now we have a region and it is for the handler's address space type.
*
* First disconnect region for any previous handler (if any)
*/
@@ -786,9 +786,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
ACPI_FUNCTION_TRACE(ev_install_space_handler);
/*
- * This registration is valid for only the types below
- * and the root. This is where the default handlers
- * get placed.
+ * This registration is valid for only the types below and the root. This
+ * is where the default handlers get placed.
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR) &&
@@ -848,8 +847,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/*
- * The attached device object already exists.
- * Make sure the handler is not already installed.
+ * The attached device object already exists. Make sure the handler
+ * is not already installed.
*/
handler_obj = obj_desc->device.handler;
@@ -864,8 +863,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
handler) {
/*
* It is (relatively) OK to attempt to install the SAME
- * handler twice. This can easily happen
- * with PCI_Config space.
+ * handler twice. This can easily happen with the
+ * PCI_Config space.
*/
status = AE_SAME_HANDLER;
goto unlock_and_exit;
@@ -925,9 +924,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node,
/*
* Install the handler
*
- * At this point there is no existing handler.
- * Just allocate the object for the handler and link it
- * into the list.
+ * At this point there is no existing handler. Just allocate the object
+ * for the handler and link it into the list.
*/
handler_obj =
acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
@@ -1000,11 +998,10 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
/*
- * Run all _REG methods for all Operation Regions for this
- * space ID. This is a separate walk in order to handle any
- * interdependencies between regions and _REG methods. (i.e. handlers
- * must be installed for all regions of this Space ID before we
- * can run any _REG methods)
+ * Run all _REG methods for all Operation Regions for this space ID. This
+ * is a separate walk in order to handle any interdependencies between
+ * regions and _REG methods. (i.e. handlers must be installed for all
+ * regions of this Space ID before we can run any _REG methods)
*/
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
@@ -1042,8 +1039,8 @@ acpi_ev_reg_run(acpi_handle obj_handle,
}
/*
- * We only care about regions.and objects
- * that are allowed to have address space handlers
+ * We only care about regions.and objects that are allowed to have address
+ * space handlers
*/
if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
@@ -1062,10 +1059,9 @@ acpi_ev_reg_run(acpi_handle obj_handle,
/* Object is a Region */
if (obj_desc->region.space_id != space_id) {
- /*
- * This region is for a different address space
- * -- just ignore it
- */
+
+ /* This region is for a different address space, just ignore it */
+
return (AE_OK);
}
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 6b94b38df07d..f3f1fb45c3dc 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evrgnini")
@@ -233,9 +234,9 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
if (ACPI_FAILURE(status)) {
if (status == AE_SAME_HANDLER) {
/*
- * It is OK if the handler is already installed on the root
- * bridge. Still need to return a context object for the
- * new PCI_Config operation region, however.
+ * It is OK if the handler is already installed on the
+ * root bridge. Still need to return a context object
+ * for the new PCI_Config operation region, however.
*/
status = AE_OK;
} else {
@@ -272,8 +273,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
}
/*
- * For PCI_Config space access, we need the segment, bus,
- * device and function numbers. Acquire them here.
+ * For PCI_Config space access, we need the segment, bus, device and
+ * function numbers. Acquire them here.
*
* Find the parent device object. (This allows the operation region to be
* within a subscope under the device, such as a control method.)
@@ -289,16 +290,16 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
}
/*
- * Get the PCI device and function numbers from the _ADR object
- * contained in the parent's scope.
+ * Get the PCI device and function numbers from the _ADR object contained
+ * in the parent's scope.
*/
status =
acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node,
&pci_value);
/*
- * The default is zero, and since the allocation above zeroed
- * the data, just do nothing on failure.
+ * The default is zero, and since the allocation above zeroed the data,
+ * just do nothing on failure.
*/
if (ACPI_SUCCESS(status)) {
pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value));
@@ -382,9 +383,8 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
struct acpi_compatible_id_list *cid;
u32 i;
- /*
- * Get the _HID and check for a PCI Root Bridge
- */
+ /* Get the _HID and check for a PCI Root Bridge */
+
status = acpi_ut_execute_HID(node, &hid);
if (ACPI_FAILURE(status)) {
return (FALSE);
@@ -394,10 +394,8 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
return (TRUE);
}
- /*
- * The _HID did not match.
- * Get the _CID and check for a PCI Root Bridge
- */
+ /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */
+
status = acpi_ut_execute_CID(node, &cid);
if (ACPI_FAILURE(status)) {
return (FALSE);
@@ -516,9 +514,9 @@ acpi_ev_default_region_setup(acpi_handle handle,
* Get the appropriate address space handler for a newly
* created region.
*
- * This also performs address space specific initialization. For
+ * This also performs address space specific initialization. For
* example, PCI regions must have an _ADR object that contains
- * a PCI address in the scope of the definition. This address is
+ * a PCI address in the scope of the definition. This address is
* required to perform an access to PCI config space.
*
* MUTEX: Interpreter should be unlocked, because we may run the _REG
@@ -572,7 +570,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
if (ACPI_SUCCESS(status)) {
/*
* The _REG method is optional and there can be only one per region
- * definition. This will be executed when the handler is attached
+ * definition. This will be executed when the handler is attached
* or removed
*/
region_obj2->extra.method_REG = method_node;
@@ -670,10 +668,8 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
}
}
- /*
- * This node does not have the handler we need;
- * Pop up one level
- */
+ /* This node does not have the handler we need; Pop up one level */
+
node = acpi_ns_get_parent_node(node);
}
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/acpica/evsci.c
index 2a8b77877610..567b356c85af 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/acpica/evsci.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acevents.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evsci")
@@ -115,10 +116,8 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
* if this interrupt handler is installed, ACPI is enabled.
*/
- /*
- * GPEs:
- * Check for and dispatch any GPEs that have occurred
- */
+ /* GPEs: Check for and dispatch any GPEs that have occurred */
+
interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
return_UINT32(interrupt_handled);
@@ -158,11 +157,11 @@ u32 acpi_ev_install_sci_handler(void)
* RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not
* installed to begin with
*
- * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
+ * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
* taken.
*
* Note: It doesn't seem important to disable all events or set the event
- * enable registers to their original values. The OS should disable
+ * enable registers to their original values. The OS should disable
* the SCI interrupt level when the handler is removed, so no more
* events will come in.
*
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/acpica/evxface.c
index 94a6efe020be..3aca9010a11e 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acevents.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxface")
@@ -267,7 +268,7 @@ acpi_install_notify_handler(acpi_handle device,
/*
* Root Object:
* Registering a notify handler on the root object indicates that the
- * caller wishes to receive notifications for all objects. Note that
+ * caller wishes to receive notifications for all objects. Note that
* only one <external> global handler can be regsitered (per notify type).
*/
if (device == ACPI_ROOT_OBJECT) {
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 41554f736b68..35485e4b60a6 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -42,13 +42,19 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
-#include <acpi/acnamesp.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "actables.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxfevnt")
+/* Local prototypes */
+acpi_status
+acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block, void *context);
+
/*******************************************************************************
*
* FUNCTION: acpi_enable
@@ -60,6 +66,7 @@ ACPI_MODULE_NAME("evxfevnt")
* DESCRIPTION: Transfers the system into ACPI mode.
*
******************************************************************************/
+
acpi_status acpi_enable(void)
{
acpi_status status = AE_OK;
@@ -161,8 +168,8 @@ acpi_status acpi_enable_event(u32 event, u32 flags)
}
/*
- * Enable the requested fixed event (by writing a one to the
- * enable register bit)
+ * Enable the requested fixed event (by writing a one to the enable
+ * register bit)
*/
status =
acpi_set_register(acpi_gbl_fixed_event_info[event].
@@ -343,8 +350,8 @@ acpi_status acpi_disable_event(u32 event, u32 flags)
}
/*
- * Disable the requested fixed event (by writing a zero to the
- * enable register bit)
+ * Disable the requested fixed event (by writing a zero to the enable
+ * register bit)
*/
status =
acpi_set_register(acpi_gbl_fixed_event_info[event].
@@ -396,8 +403,8 @@ acpi_status acpi_clear_event(u32 event)
}
/*
- * Clear the requested fixed event (By writing a one to the
- * status register bit)
+ * Clear the requested fixed event (By writing a one to the status
+ * register bit)
*/
status =
acpi_set_register(acpi_gbl_fixed_event_info[event].
@@ -717,3 +724,148 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
}
ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_get_gpe_device
+ *
+ * PARAMETERS: Index - System GPE index (0-current_gpe_count)
+ * gpe_device - Where the parent GPE Device is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
+ * gpe device indicates that the gpe number is contained in one of
+ * the FADT-defined gpe blocks. Otherwise, the GPE block device.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
+{
+ struct acpi_gpe_device_info info;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
+
+ if (!gpe_device) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ if (index >= acpi_current_gpe_count) {
+ return_ACPI_STATUS(AE_NOT_EXIST);
+ }
+
+ /* Setup and walk the GPE list */
+
+ info.index = index;
+ info.status = AE_NOT_EXIST;
+ info.gpe_device = NULL;
+ info.next_block_base_index = 0;
+
+ status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ *gpe_device = info.gpe_device;
+ return_ACPI_STATUS(info.status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ev_get_gpe_device
+ *
+ * PARAMETERS: GPE_WALK_CALLBACK
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
+ * block device. NULL if the GPE is one of the FADT-defined GPEs.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block, void *context)
+{
+ struct acpi_gpe_device_info *info = context;
+
+ /* Increment Index by the number of GPEs in this block */
+
+ info->next_block_base_index +=
+ (gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH);
+
+ if (info->index < info->next_block_base_index) {
+ /*
+ * The GPE index is within this block, get the node. Leave the node
+ * NULL for the FADT-defined GPEs
+ */
+ if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
+ info->gpe_device = gpe_block->node;
+ }
+
+ info->status = AE_OK;
+ return (AE_CTRL_END);
+ }
+
+ return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_disable_all_gpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
+ *
+ ******************************************************************************/
+
+acpi_status acpi_disable_all_gpes(void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_hw_disable_all_gpes();
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+ return_ACPI_STATUS(status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_enable_all_runtime_gpes
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
+ *
+ ******************************************************************************/
+
+acpi_status acpi_enable_all_runtime_gpes(void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ status = acpi_hw_enable_all_runtime_gpes();
+ (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+ return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index e8750807e57d..479e7a3721be 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -43,8 +43,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acevents.h"
#define _COMPONENT ACPI_EVENTS
ACPI_MODULE_NAME("evxfregn")
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 74da6fa52ef1..932bbc26aa04 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -42,10 +42,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-#include <acpi/actables.h>
-#include <acpi/acdispat.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "actables.h"
+#include "acdispat.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exconfig")
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/acpica/exconvrt.c
index 1d1f35adddde..0be10188316e 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/acpica/exconvrt.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exconvrt")
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/acpica/excreate.c
index ad09696d5069..a57ad2564ab0 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("excreate")
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/acpica/exdump.c
index d087a7d28aa5..aa313574b0df 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/acpica/exdump.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exdump")
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/acpica/exfield.c
index 3e440d84226a..a352d0233857 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acdispat.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exfield")
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/acpica/exfldio.c
index 9ff9d1f4615d..ef58ac4e687b 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/acpica/exfldio.c
@@ -42,10 +42,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
-#include <acpi/acevents.h>
-#include <acpi/acdispat.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "acevents.h"
+#include "acdispat.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exfldio")
@@ -498,14 +499,13 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
return_ACPI_STATUS(status);
}
- ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "I/O to Data Register: ValuePtr %p\n",
- value));
-
if (read_write == ACPI_READ) {
/* Read the datum from the data_register */
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Read from Data Register\n"));
+
status =
acpi_ex_extract_from_field(obj_desc->index_field.
data_obj, value,
@@ -513,6 +513,10 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
} else {
/* Write the datum to the data_register */
+ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
+ "Write to Data Register: Value %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64(*value)));
+
status =
acpi_ex_insert_into_field(obj_desc->index_field.
data_obj, value,
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/acpica/exmisc.c
index efb191340059..6b0747ac683b 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/acpica/exmisc.c
@@ -43,9 +43,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
-#include <acpi/amlresrc.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "amlresrc.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exmisc")
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/acpica/exmutex.c
index a8bf3d713e28..d301c1f363ef 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -43,8 +43,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "acevents.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exmutex")
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/acpica/exnames.c
index 817e67be3697..ffdae122d94a 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/acpica/exnames.c
@@ -43,8 +43,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exnames")
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/acpica/exoparg1.c
index f622f9eac8a1..b530480cc7d5 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/acpica/exoparg1.c
@@ -43,11 +43,12 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exoparg1")
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/acpica/exoparg2.c
index 368def5dffce..0b4f513ca885 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/acpica/exoparg2.c
@@ -42,10 +42,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acinterp.h>
-#include <acpi/acevents.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acinterp.h"
+#include "acevents.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exoparg2")
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/acpica/exoparg3.c
index 9cb4197681af..c6520bbf882b 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/acpica/exoparg3.c
@@ -43,9 +43,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "acparser.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exoparg3")
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/acpica/exoparg6.c
index 67d48737af53..ae43f7670a6c 100644
--- a/drivers/acpi/executer/exoparg6.c
+++ b/drivers/acpi/acpica/exoparg6.c
@@ -43,9 +43,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "acparser.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exoparg6")
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/acpica/exprep.c
index 5d438c32989d..a226f74d4a5c 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/acpica/exprep.c
@@ -43,9 +43,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exprep")
@@ -404,7 +405,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
*
* RETURN: Status
*
- * DESCRIPTION: Construct an union acpi_operand_object of type def_field and
+ * DESCRIPTION: Construct a union acpi_operand_object of type def_field and
* connect it to the parent Node.
*
******************************************************************************/
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/acpica/exregion.c
index 7a41c409ae4d..76ec8ff903b8 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/drivers/acpi/acpica/exregion.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exregion")
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/acpica/exresnte.c
index 423ad3635f3d..a063a74006f6 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/acpica/exresnte.c
@@ -43,9 +43,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresnte")
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/acpica/exresolv.c
index 89571b92a522..f6105a6d6126 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/acpica/exresolv.c
@@ -43,10 +43,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlcode.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresolv")
@@ -146,7 +147,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
stack_desc = *stack_ptr;
- /* This is an union acpi_operand_object */
+ /* This is a union acpi_operand_object */
switch (ACPI_GET_OBJECT_TYPE(stack_desc)) {
case ACPI_TYPE_LOCAL_REFERENCE:
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/acpica/exresop.c
index 0bb82593da72..3c3802764bfb 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/acpica/exresop.c
@@ -43,10 +43,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlcode.h>
-#include <acpi/acparser.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acparser.h"
+#include "acinterp.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exresop")
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/acpica/exstore.c
index 3318df4cbd98..e35e9b4f6a4e 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/acpica/exstore.c
@@ -43,10 +43,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "amlcode.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exstore")
@@ -274,7 +275,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
*
* PARAMETERS: *source_desc - Value to be stored
* *dest_desc - Where to store it. Must be an NS node
- * or an union acpi_operand_object of type
+ * or a union acpi_operand_object of type
* Reference;
* walk_state - Current walk state
*
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/acpica/exstoren.c
index eef61a00803e..145d15305f70 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/acpica/exstoren.c
@@ -44,8 +44,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exstoren")
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/acpica/exstorob.c
index 9a75ff09fb0c..67340cc70142 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/acpica/exstorob.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exstorob")
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/acpica/exsystem.c
index 68990f1df371..3d00b9357233 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/acpica/exsystem.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exsystem")
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/acpica/exutils.c
index 86c03880b523..32b85d68e756 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/acpica/exutils.c
@@ -59,8 +59,9 @@
#define DEFINE_AML_GLOBALS
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exutils")
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/acpica/hwacpi.c
index 816894ea839e..a9d4fea4167f 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/acpica/hwacpi.c
@@ -43,6 +43,7 @@
*/
#include <acpi/acpi.h>
+#include "accommon.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwacpi")
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index 0b80db9d9197..2013b66745d2 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acevents.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwgpe")
@@ -51,7 +52,8 @@ ACPI_MODULE_NAME("hwgpe")
/* Local prototypes */
static acpi_status
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block);
+ struct acpi_gpe_block_info *gpe_block,
+ void *context);
/******************************************************************************
*
@@ -80,8 +82,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Get current value of the enable register that contains this GPE */
- status = acpi_hw_low_level_read(ACPI_GPE_REGISTER_WIDTH, &enable_mask,
- &gpe_register_info->enable_address);
+ status = acpi_read(&enable_mask, &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@@ -95,9 +96,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Write the updated enable mask */
- status = acpi_hw_low_level_write(ACPI_GPE_REGISTER_WIDTH, enable_mask,
- &gpe_register_info->enable_address);
-
+ status = acpi_write(enable_mask, &gpe_register_info->enable_address);
return (status);
}
@@ -132,8 +131,8 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
/* Write the entire GPE (runtime) enable register */
- status = acpi_hw_low_level_write(8, gpe_register_info->enable_for_run,
- &gpe_register_info->enable_address);
+ status = acpi_write(gpe_register_info->enable_for_run,
+ &gpe_register_info->enable_address);
return (status);
}
@@ -166,9 +165,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
- status = acpi_hw_low_level_write(8, register_bit,
- &gpe_event_info->register_info->
- status_address);
+ status = acpi_write(register_bit,
+ &gpe_event_info->register_info->status_address);
return (status);
}
@@ -227,9 +225,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
/* GPE currently active (status bit == 1)? */
- status =
- acpi_hw_low_level_read(8, &in_byte,
- &gpe_register_info->status_address);
+ status = acpi_read(&in_byte, &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
@@ -260,8 +256,8 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
******************************************************************************/
acpi_status
-acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
- struct acpi_gpe_block_info * gpe_block)
+acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block, void *context)
{
u32 i;
acpi_status status;
@@ -272,9 +268,9 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
/* Disable all GPEs in this register */
- status = acpi_hw_low_level_write(8, 0x00,
- &gpe_block->register_info[i].
- enable_address);
+ status =
+ acpi_write(0x00,
+ &gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@@ -297,8 +293,8 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
******************************************************************************/
acpi_status
-acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
- struct acpi_gpe_block_info * gpe_block)
+acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block, void *context)
{
u32 i;
acpi_status status;
@@ -309,9 +305,9 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
/* Clear status on all GPEs in this register */
- status = acpi_hw_low_level_write(8, 0xFF,
- &gpe_block->register_info[i].
- status_address);
+ status =
+ acpi_write(0xFF,
+ &gpe_block->register_info[i].status_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@@ -335,8 +331,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
******************************************************************************/
acpi_status
-acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
- struct acpi_gpe_block_info * gpe_block)
+acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+ struct acpi_gpe_block_info *gpe_block, void *context)
{
u32 i;
acpi_status status;
@@ -352,12 +348,9 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
/* Enable all "runtime" GPEs in this register */
- status =
- acpi_hw_low_level_write(8,
- gpe_block->register_info[i].
- enable_for_run,
- &gpe_block->register_info[i].
- enable_address);
+ status = acpi_write(gpe_block->register_info[i].enable_for_run,
+ &gpe_block->register_info[i].
+ enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@@ -382,7 +375,8 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,
static acpi_status
acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
- struct acpi_gpe_block_info *gpe_block)
+ struct acpi_gpe_block_info *gpe_block,
+ void *context)
{
u32 i;
acpi_status status;
@@ -396,11 +390,9 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Enable all "wake" GPEs in this register */
- status = acpi_hw_low_level_write(8,
- gpe_block->register_info[i].
- enable_for_wake,
- &gpe_block->register_info[i].
- enable_address);
+ status = acpi_write(gpe_block->register_info[i].enable_for_wake,
+ &gpe_block->register_info[i].
+ enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
@@ -427,8 +419,8 @@ acpi_status acpi_hw_disable_all_gpes(void)
ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
- status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
- status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
+ status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
+ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
return_ACPI_STATUS(status);
}
@@ -450,7 +442,7 @@ acpi_status acpi_hw_enable_all_runtime_gpes(void)
ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
- status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block);
+ status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block, NULL);
return_ACPI_STATUS(status);
}
@@ -472,6 +464,6 @@ acpi_status acpi_hw_enable_all_wakeup_gpes(void)
ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
- status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block);
+ status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block, NULL);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c
new file mode 100644
index 000000000000..4dc43b018517
--- /dev/null
+++ b/drivers/acpi/acpica/hwregs.c
@@ -0,0 +1,353 @@
+
+/*******************************************************************************
+ *
+ * Module Name: hwregs - Read/write access functions for the various ACPI
+ * control and status registers.
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2008, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acevents.h"
+
+#define _COMPONENT ACPI_HARDWARE
+ACPI_MODULE_NAME("hwregs")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_hw_clear_acpi_status
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clears all fixed and general purpose status bits
+ * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
+ *
+ ******************************************************************************/
+acpi_status acpi_hw_clear_acpi_status(void)
+{
+ acpi_status status;
+ acpi_cpu_flags lock_flags = 0;
+
+ ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
+
+ ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
+ ACPI_BITMASK_ALL_FIXED_STATUS,
+ (u16) acpi_gbl_FADT.xpm1a_event_block.address));
+
+ lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
+
+ status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
+ ACPI_BITMASK_ALL_FIXED_STATUS);
+ if (ACPI_FAILURE(status)) {
+ goto unlock_and_exit;
+ }
+
+ /* Clear the fixed events */
+
+ if (acpi_gbl_FADT.xpm1b_event_block.address) {
+ status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS,
+ &acpi_gbl_FADT.xpm1b_event_block);
+ if (ACPI_FAILURE(status)) {
+ goto unlock_and_exit;
+ }
+ }
+
+ /* Clear the GPE Bits in all GPE registers in all GPE blocks */
+
+ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
+
+ unlock_and_exit:
+ acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+ return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_hw_get_register_bit_mask
+ *
+ * PARAMETERS: register_id - Index of ACPI Register to access
+ *
+ * RETURN: The bitmask to be used when accessing the register
+ *
+ * DESCRIPTION: Map register_id into a register bitmask.
+ *
+ ******************************************************************************/
+
+struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
+{
+ ACPI_FUNCTION_ENTRY();
+
+ if (register_id > ACPI_BITREG_MAX) {
+ ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
+ register_id));
+ return (NULL);
+ }
+
+ return (&acpi_gbl_bit_register_info[register_id]);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_hw_register_read
+ *
+ * PARAMETERS: register_id - ACPI Register ID
+ * return_value - Where the register value is returned
+ *
+ * RETURN: Status and the value read.
+ *
+ * DESCRIPTION: Read from the specified ACPI register
+ *
+ ******************************************************************************/
+acpi_status
+acpi_hw_register_read(u32 register_id, u32 * return_value)
+{
+ u32 value1 = 0;
+ u32 value2 = 0;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(hw_register_read);
+
+ switch (register_id) {
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
+
+ status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* PM1B is optional */
+
+ status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block);
+ value1 |= value2;
+ break;
+
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
+
+ status = acpi_read(&value1, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* PM1B is optional */
+
+ status = acpi_read(&value2, &acpi_gbl_xpm1b_enable);
+ value1 |= value2;
+ break;
+
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
+
+ status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block);
+ value1 |= value2;
+ break;
+
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
+
+ status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block);
+ break;
+
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
+
+ status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block);
+ break;
+
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+
+ status =
+ acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
+ break;
+
+ default:
+ ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
+ status = AE_BAD_PARAMETER;
+ break;
+ }
+
+ exit:
+
+ if (ACPI_SUCCESS(status)) {
+ *return_value = value1;
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION: acpi_hw_register_write
+ *
+ * PARAMETERS: register_id - ACPI Register ID
+ * Value - The value to write
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Write to the specified ACPI register
+ *
+ * NOTE: In accordance with the ACPI specification, this function automatically
+ * preserves the value of the following bits, meaning that these bits cannot be
+ * changed via this interface:
+ *
+ * PM1_CONTROL[0] = SCI_EN
+ * PM1_CONTROL[9]
+ * PM1_STATUS[11]
+ *
+ * ACPI References:
+ * 1) Hardware Ignored Bits: When software writes to a register with ignored
+ * bit fields, it preserves the ignored bit fields
+ * 2) SCI_EN: OSPM always preserves this bit position
+ *
+ ******************************************************************************/
+
+acpi_status acpi_hw_register_write(u32 register_id, u32 value)
+{
+ acpi_status status;
+ u32 read_value;
+
+ ACPI_FUNCTION_TRACE(hw_register_write);
+
+ switch (register_id) {
+ case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
+
+ /* Perform a read first to preserve certain bits (per ACPI spec) */
+
+ status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
+ &read_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Insert the bits to be preserved */
+
+ ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
+ read_value);
+
+ /* Now we can write the data */
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* PM1B is optional */
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block);
+ break;
+
+ case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
+
+ status = acpi_write(value, &acpi_gbl_xpm1a_enable);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* PM1B is optional */
+
+ status = acpi_write(value, &acpi_gbl_xpm1b_enable);
+ break;
+
+ case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
+
+ /*
+ * Perform a read first to preserve certain bits (per ACPI spec)
+ */
+ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
+ &read_value);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ /* Insert the bits to be preserved */
+
+ ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
+ read_value);
+
+ /* Now we can write the data */
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block);
+ if (ACPI_FAILURE(status)) {
+ goto exit;
+ }
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block);
+ break;
+
+ case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block);
+ break;
+
+ case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block);
+ break;
+
+ case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block);
+ break;
+
+ case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
+
+ status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block);
+ break;
+
+ case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+
+ /* SMI_CMD is currently always in IO space */
+
+ status =
+ acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
+ break;
+
+ default:
+ status = AE_BAD_PARAMETER;
+ break;
+ }
+
+ exit:
+ return_ACPI_STATUS(status);
+}
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index 25dccdf179b9..a2af2a4f2f26 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "actables.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwsleep")
@@ -52,31 +53,19 @@ ACPI_MODULE_NAME("hwsleep")
*
* FUNCTION: acpi_set_firmware_waking_vector
*
- * PARAMETERS: physical_address - Physical address of ACPI real mode
+ * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode
* entry point.
*
* RETURN: Status
*
- * DESCRIPTION: Access function for the firmware_waking_vector field in FACS
+ * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS
*
******************************************************************************/
acpi_status
-acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
+acpi_set_firmware_waking_vector(u32 physical_address)
{
- struct acpi_table_facs *facs;
- acpi_status status;
-
ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
- /* Get the FACS */
-
- status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
- ACPI_CAST_INDIRECT_PTR(struct
- acpi_table_header,
- &facs));
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
/*
* According to the ACPI specification 2.0c and later, the 64-bit
@@ -85,10 +74,16 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
* Protected Mode. Some systems (for example HP dv5-1004nr) are known
* to fail to resume if the 64-bit vector is used.
*/
- if (facs->version >= 1)
- facs->xfirmware_waking_vector = 0;
- facs->firmware_waking_vector = (u32)physical_address;
+ /* Set the 32-bit vector */
+
+ acpi_gbl_FACS->firmware_waking_vector = physical_address;
+
+ /* Clear the 64-bit vector if it exists */
+
+ if ((acpi_gbl_FACS->length > 32) && (acpi_gbl_FACS->version >= 1)) {
+ acpi_gbl_FACS->xfirmware_waking_vector = 0;
+ }
return_ACPI_STATUS(AE_OK);
}
@@ -97,48 +92,39 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
/*******************************************************************************
*
- * FUNCTION: acpi_get_firmware_waking_vector
+ * FUNCTION: acpi_set_firmware_waking_vector64
*
- * PARAMETERS: *physical_address - Where the contents of
- * the firmware_waking_vector field of
- * the FACS will be returned.
+ * PARAMETERS: physical_address - 64-bit physical address of ACPI protected
+ * mode entry point.
*
- * RETURN: Status, vector
+ * RETURN: Status
*
- * DESCRIPTION: Access function for the firmware_waking_vector field in FACS
+ * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if
+ * it exists in the table.
*
******************************************************************************/
-#ifdef ACPI_FUTURE_USAGE
acpi_status
-acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
+acpi_set_firmware_waking_vector64(u64 physical_address)
{
- struct acpi_table_facs *facs;
- acpi_status status;
+ ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64);
- ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector);
-
- if (!physical_address) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
- /* Get the FACS */
+ /* Determine if the 64-bit vector actually exists */
- status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
- ACPI_CAST_INDIRECT_PTR(struct
- acpi_table_header,
- &facs));
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
+ if ((acpi_gbl_FACS->length <= 32) || (acpi_gbl_FACS->version < 1)) {
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
- /* Get the vector */
- *physical_address = (acpi_physical_address)facs->firmware_waking_vector;
+ /* Clear 32-bit vector, set the 64-bit X_ vector */
+
+ acpi_gbl_FACS->firmware_waking_vector = 0;
+ acpi_gbl_FACS->xfirmware_waking_vector = physical_address;
return_ACPI_STATUS(AE_OK);
}
-ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector)
-#endif
+ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64)
+
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state_prep
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/acpica/hwtimer.c
index b53d575491b9..b7f522c8f023 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/acpica/hwtimer.c
@@ -43,6 +43,7 @@
*/
#include <acpi/acpi.h>
+#include "accommon.h"
#define _COMPONENT ACPI_HARDWARE
ACPI_MODULE_NAME("hwtimer")
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/acpica/hwxface.c
index ddf792adcf96..ae597c0ab53f 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -1,10 +1,9 @@
-/*******************************************************************************
+/******************************************************************************
*
- * Module Name: hwregs - Read/write access functions for the various ACPI
- * control and status registers.
+ * Module Name: hwxface - Public ACPICA hardware interfaces
*
- ******************************************************************************/
+ *****************************************************************************/
/*
* Copyright (C) 2000 - 2008, Intel Corp.
@@ -44,209 +43,208 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_HARDWARE
-ACPI_MODULE_NAME("hwregs")
+ACPI_MODULE_NAME("hwxface")
-/*******************************************************************************
+/******************************************************************************
*
- * FUNCTION: acpi_hw_clear_acpi_status
+ * FUNCTION: acpi_reset
*
* PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
- * DESCRIPTION: Clears all fixed and general purpose status bits
- * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
+ * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
+ * support reset register in PCI config space, this must be
+ * handled separately.
*
******************************************************************************/
-acpi_status acpi_hw_clear_acpi_status(void)
+acpi_status acpi_reset(void)
{
+ struct acpi_generic_address *reset_reg;
acpi_status status;
- acpi_cpu_flags lock_flags = 0;
- ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
+ ACPI_FUNCTION_TRACE(acpi_reset);
- ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
- ACPI_BITMASK_ALL_FIXED_STATUS,
- (u16) acpi_gbl_FADT.xpm1a_event_block.address));
+ reset_reg = &acpi_gbl_FADT.reset_register;
- lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
+ /* Check if the reset register is supported */
- status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
- ACPI_BITMASK_ALL_FIXED_STATUS);
- if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
+ !reset_reg->address) {
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
- /* Clear the fixed events */
-
- if (acpi_gbl_FADT.xpm1b_event_block.address) {
- status =
- acpi_hw_low_level_write(16, ACPI_BITMASK_ALL_FIXED_STATUS,
- &acpi_gbl_FADT.xpm1b_event_block);
- if (ACPI_FAILURE(status)) {
- goto unlock_and_exit;
- }
- }
-
- /* Clear the GPE Bits in all GPE registers in all GPE blocks */
-
- status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
+ /* Write the reset value to the reset register */
- unlock_and_exit:
- acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
+ status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg);
return_ACPI_STATUS(status);
}
-/*******************************************************************************
+ACPI_EXPORT_SYMBOL(acpi_reset)
+
+/******************************************************************************
*
- * FUNCTION: acpi_get_sleep_type_data
+ * FUNCTION: acpi_read
*
- * PARAMETERS: sleep_state - Numeric sleep state
- * *sleep_type_a - Where SLP_TYPa is returned
- * *sleep_type_b - Where SLP_TYPb is returned
+ * PARAMETERS: Value - Where the value is returned
+ * Reg - GAS register structure
*
- * RETURN: Status - ACPI status
+ * RETURN: Status
*
- * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
- * state.
+ * DESCRIPTION: Read from either memory or IO space.
*
******************************************************************************/
-
-acpi_status
-acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
+acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg)
{
- acpi_status status = AE_OK;
- struct acpi_evaluate_info *info;
-
- ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
-
- /* Validate parameters */
-
- if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
+ u32 width;
+ u64 address;
+ acpi_status status;
- /* Allocate the evaluation information block */
+ ACPI_FUNCTION_NAME(acpi_read);
- info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
- if (!info) {
- return_ACPI_STATUS(AE_NO_MEMORY);
+ /*
+ * Must have a valid pointer to a GAS structure, and
+ * a non-zero address within. However, don't return an error
+ * because the PM1A/B code must not fail if B isn't present.
+ */
+ if (!reg) {
+ return (AE_OK);
}
- info->pathname =
- ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
-
- /* Evaluate the namespace object containing the values for this state */
-
- status = acpi_ns_evaluate(info);
- if (ACPI_FAILURE(status)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "%s while evaluating SleepState [%s]\n",
- acpi_format_exception(status),
- info->pathname));
+ /* Get a local copy of the address. Handles possible alignment issues */
- goto cleanup;
+ ACPI_MOVE_64_TO_64(&address, &reg->address);
+ if (!address) {
+ return (AE_OK);
}
- /* Must have a return object */
+ /* Supported widths are 8/16/32 */
- if (!info->return_object) {
- ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
- info->pathname));
- status = AE_NOT_EXIST;
+ width = reg->bit_width;
+ if ((width != 8) && (width != 16) && (width != 32)) {
+ return (AE_SUPPORT);
}
- /* It must be of type Package */
+ /* Initialize entire 32-bit return value to zero */
- else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) {
- ACPI_ERROR((AE_INFO,
- "Sleep State return object is not a Package"));
- status = AE_AML_OPERAND_TYPE;
- }
+ *value = 0;
/*
- * The package must have at least two elements. NOTE (March 2005): This
- * goes against the current ACPI spec which defines this object as a
- * package with one encoded DWORD element. However, existing practice
- * by BIOS vendors seems to be to have 2 or more elements, at least
- * one per sleep type (A/B).
+ * Two address spaces supported: Memory or IO.
+ * PCI_Config is not supported here because the GAS struct is insufficient
*/
- else if (info->return_object->package.count < 2) {
- ACPI_ERROR((AE_INFO,
- "Sleep State return package does not have at least two elements"));
- status = AE_AML_NO_OPERAND;
- }
+ switch (reg->space_id) {
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- /* The first two elements must both be of type Integer */
+ status = acpi_os_read_memory((acpi_physical_address) address,
+ value, width);
+ break;
- else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0])
- != ACPI_TYPE_INTEGER) ||
- (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1])
- != ACPI_TYPE_INTEGER)) {
- ACPI_ERROR((AE_INFO,
- "Sleep State return package elements are not both Integers (%s, %s)",
- acpi_ut_get_object_type_name(info->return_object->
- package.elements[0]),
- acpi_ut_get_object_type_name(info->return_object->
- package.elements[1])));
- status = AE_AML_OPERAND_TYPE;
- } else {
- /* Valid _Sx_ package size, type, and value */
+ case ACPI_ADR_SPACE_SYSTEM_IO:
- *sleep_type_a = (u8)
- (info->return_object->package.elements[0])->integer.value;
- *sleep_type_b = (u8)
- (info->return_object->package.elements[1])->integer.value;
- }
+ status =
+ acpi_os_read_port((acpi_io_address) address, value, width);
+ break;
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "While evaluating SleepState [%s], bad Sleep object %p type %s",
- info->pathname, info->return_object,
- acpi_ut_get_object_type_name(info->
- return_object)));
+ default:
+ ACPI_ERROR((AE_INFO,
+ "Unsupported address space: %X", reg->space_id));
+ return (AE_BAD_PARAMETER);
}
- acpi_ut_remove_reference(info->return_object);
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
+ *value, width, ACPI_FORMAT_UINT64(address),
+ acpi_ut_get_region_name(reg->space_id)));
- cleanup:
- ACPI_FREE(info);
- return_ACPI_STATUS(status);
+ return (status);
}
-ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
+ACPI_EXPORT_SYMBOL(acpi_read)
-/*******************************************************************************
+/******************************************************************************
*
- * FUNCTION: acpi_hw_get_register_bit_mask
+ * FUNCTION: acpi_write
*
- * PARAMETERS: register_id - Index of ACPI Register to access
+ * PARAMETERS: Value - To be written
+ * Reg - GAS register structure
*
- * RETURN: The bitmask to be used when accessing the register
+ * RETURN: Status
*
- * DESCRIPTION: Map register_id into a register bitmask.
+ * DESCRIPTION: Write to either memory or IO space.
*
******************************************************************************/
-struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
+acpi_status acpi_write(u32 value, struct acpi_generic_address *reg)
{
- ACPI_FUNCTION_ENTRY();
+ u32 width;
+ u64 address;
+ acpi_status status;
- if (register_id > ACPI_BITREG_MAX) {
- ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
- register_id));
- return (NULL);
+ ACPI_FUNCTION_NAME(acpi_write);
+
+ /*
+ * Must have a valid pointer to a GAS structure, and
+ * a non-zero address within. However, don't return an error
+ * because the PM1A/B code must not fail if B isn't present.
+ */
+ if (!reg) {
+ return (AE_OK);
}
- return (&acpi_gbl_bit_register_info[register_id]);
+ /* Get a local copy of the address. Handles possible alignment issues */
+
+ ACPI_MOVE_64_TO_64(&address, &reg->address);
+ if (!address) {
+ return (AE_OK);
+ }
+
+ /* Supported widths are 8/16/32 */
+
+ width = reg->bit_width;
+ if ((width != 8) && (width != 16) && (width != 32)) {
+ return (AE_SUPPORT);
+ }
+
+ /*
+ * Two address spaces supported: Memory or IO.
+ * PCI_Config is not supported here because the GAS struct is insufficient
+ */
+ switch (reg->space_id) {
+ case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+
+ status = acpi_os_write_memory((acpi_physical_address) address,
+ value, width);
+ break;
+
+ case ACPI_ADR_SPACE_SYSTEM_IO:
+
+ status = acpi_os_write_port((acpi_io_address) address, value,
+ width);
+ break;
+
+ default:
+ ACPI_ERROR((AE_INFO,
+ "Unsupported address space: %X", reg->space_id));
+ return (AE_BAD_PARAMETER);
+ }
+
+ ACPI_DEBUG_PRINT((ACPI_DB_IO,
+ "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
+ value, width, ACPI_FORMAT_UINT64(address),
+ acpi_ut_get_region_name(reg->space_id)));
+
+ return (status);
}
+ACPI_EXPORT_SYMBOL(acpi_write)
+
/*******************************************************************************
*
- * FUNCTION: acpi_get_register
+ * FUNCTION: acpi_get_register_unlocked
*
* PARAMETERS: register_id - ID of ACPI bit_register to access
* return_value - Value that was read from the register
@@ -254,17 +252,16 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
* RETURN: Status and the value read from specified Register. Value
* returned is normalized to bit0 (is shifted all the way right)
*
- * DESCRIPTION: ACPI bit_register read function.
+ * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock.
*
******************************************************************************/
-
-acpi_status acpi_get_register_unlocked(u32 register_id, u32 * return_value)
+acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value)
{
u32 register_value = 0;
struct acpi_bit_register_info *bit_reg_info;
acpi_status status;
- ACPI_FUNCTION_TRACE(acpi_get_register);
+ ACPI_FUNCTION_TRACE(acpi_get_register_unlocked);
/* Get the info structure corresponding to the requested ACPI Register */
@@ -296,14 +293,31 @@ acpi_status acpi_get_register_unlocked(u32 register_id, u32 * return_value)
return_ACPI_STATUS(status);
}
-acpi_status acpi_get_register(u32 register_id, u32 * return_value)
+ACPI_EXPORT_SYMBOL(acpi_get_register_unlocked)
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_get_register
+ *
+ * PARAMETERS: register_id - ID of ACPI bit_register to access
+ * return_value - Value that was read from the register
+ *
+ * RETURN: Status and the value read from specified Register. Value
+ * returned is normalized to bit0 (is shifted all the way right)
+ *
+ * DESCRIPTION: ACPI bit_register read function.
+ *
+ ******************************************************************************/
+acpi_status acpi_get_register(u32 register_id, u32 *return_value)
{
acpi_status status;
acpi_cpu_flags flags;
+
flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
status = acpi_get_register_unlocked(register_id, return_value);
acpi_os_release_lock(acpi_gbl_hardware_lock, flags);
- return status;
+
+ return (status);
}
ACPI_EXPORT_SYMBOL(acpi_get_register)
@@ -370,8 +384,9 @@ acpi_status acpi_set_register(u32 register_id, u32 value)
bit_reg_info->
access_bit_mask);
if (value) {
- status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
- (u16) value);
+ status =
+ acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
+ (u16) value);
register_value = 0;
}
break;
@@ -459,399 +474,120 @@ acpi_status acpi_set_register(u32 register_id, u32 value)
ACPI_EXPORT_SYMBOL(acpi_set_register)
-/******************************************************************************
+/*******************************************************************************
*
- * FUNCTION: acpi_hw_register_read
+ * FUNCTION: acpi_get_sleep_type_data
*
- * PARAMETERS: register_id - ACPI Register ID
- * return_value - Where the register value is returned
+ * PARAMETERS: sleep_state - Numeric sleep state
+ * *sleep_type_a - Where SLP_TYPa is returned
+ * *sleep_type_b - Where SLP_TYPb is returned
*
- * RETURN: Status and the value read.
+ * RETURN: Status - ACPI status
*
- * DESCRIPTION: Read from the specified ACPI register
+ * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
+ * state.
*
******************************************************************************/
acpi_status
-acpi_hw_register_read(u32 register_id, u32 * return_value)
+acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b)
{
- u32 value1 = 0;
- u32 value2 = 0;
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(hw_register_read);
-
- switch (register_id) {
- case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
-
- status =
- acpi_hw_low_level_read(16, &value1,
- &acpi_gbl_FADT.xpm1a_event_block);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- /* PM1B is optional */
-
- status =
- acpi_hw_low_level_read(16, &value2,
- &acpi_gbl_FADT.xpm1b_event_block);
- value1 |= value2;
- break;
-
- case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
-
- status =
- acpi_hw_low_level_read(16, &value1, &acpi_gbl_xpm1a_enable);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- /* PM1B is optional */
-
- status =
- acpi_hw_low_level_read(16, &value2, &acpi_gbl_xpm1b_enable);
- value1 |= value2;
- break;
-
- case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
-
- status =
- acpi_hw_low_level_read(16, &value1,
- &acpi_gbl_FADT.xpm1a_control_block);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- status =
- acpi_hw_low_level_read(16, &value2,
- &acpi_gbl_FADT.xpm1b_control_block);
- value1 |= value2;
- break;
-
- case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
-
- status =
- acpi_hw_low_level_read(8, &value1,
- &acpi_gbl_FADT.xpm2_control_block);
- break;
-
- case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
-
- status =
- acpi_hw_low_level_read(32, &value1,
- &acpi_gbl_FADT.xpm_timer_block);
- break;
+ acpi_status status = AE_OK;
+ struct acpi_evaluate_info *info;
- case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+ ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
- status =
- acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8);
- break;
+ /* Validate parameters */
- default:
- ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id));
- status = AE_BAD_PARAMETER;
- break;
+ if ((sleep_state > ACPI_S_STATES_MAX) || !sleep_type_a || !sleep_type_b) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
}
- exit:
+ /* Allocate the evaluation information block */
- if (ACPI_SUCCESS(status)) {
- *return_value = value1;
+ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+ if (!info) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- return_ACPI_STATUS(status);
-}
-
-/******************************************************************************
- *
- * FUNCTION: acpi_hw_register_write
- *
- * PARAMETERS: register_id - ACPI Register ID
- * Value - The value to write
- *
- * RETURN: Status
- *
- * DESCRIPTION: Write to the specified ACPI register
- *
- * NOTE: In accordance with the ACPI specification, this function automatically
- * preserves the value of the following bits, meaning that these bits cannot be
- * changed via this interface:
- *
- * PM1_CONTROL[0] = SCI_EN
- * PM1_CONTROL[9]
- * PM1_STATUS[11]
- *
- * ACPI References:
- * 1) Hardware Ignored Bits: When software writes to a register with ignored
- * bit fields, it preserves the ignored bit fields
- * 2) SCI_EN: OSPM always preserves this bit position
- *
- ******************************************************************************/
-
-acpi_status acpi_hw_register_write(u32 register_id, u32 value)
-{
- acpi_status status;
- u32 read_value;
-
- ACPI_FUNCTION_TRACE(hw_register_write);
-
- switch (register_id) {
- case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */
-
- /* Perform a read first to preserve certain bits (per ACPI spec) */
-
- status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS,
- &read_value);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- /* Insert the bits to be preserved */
-
- ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS,
- read_value);
-
- /* Now we can write the data */
-
- status =
- acpi_hw_low_level_write(16, value,
- &acpi_gbl_FADT.xpm1a_event_block);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- /* PM1B is optional */
-
- status =
- acpi_hw_low_level_write(16, value,
- &acpi_gbl_FADT.xpm1b_event_block);
- break;
-
- case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */
-
- status =
- acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1a_enable);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- /* PM1B is optional */
-
- status =
- acpi_hw_low_level_write(16, value, &acpi_gbl_xpm1b_enable);
- break;
-
- case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */
-
- /*
- * Perform a read first to preserve certain bits (per ACPI spec)
- */
- status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
- &read_value);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- /* Insert the bits to be preserved */
-
- ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
- read_value);
-
- /* Now we can write the data */
-
- status =
- acpi_hw_low_level_write(16, value,
- &acpi_gbl_FADT.xpm1a_control_block);
- if (ACPI_FAILURE(status)) {
- goto exit;
- }
-
- status =
- acpi_hw_low_level_write(16, value,
- &acpi_gbl_FADT.xpm1b_control_block);
- break;
-
- case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */
-
- status =
- acpi_hw_low_level_write(16, value,
- &acpi_gbl_FADT.xpm1a_control_block);
- break;
-
- case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */
-
- status =
- acpi_hw_low_level_write(16, value,
- &acpi_gbl_FADT.xpm1b_control_block);
- break;
-
- case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
-
- status =
- acpi_hw_low_level_write(8, value,
- &acpi_gbl_FADT.xpm2_control_block);
- break;
-
- case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
-
- status =
- acpi_hw_low_level_write(32, value,
- &acpi_gbl_FADT.xpm_timer_block);
- break;
-
- case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
+ info->pathname =
+ ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
- /* SMI_CMD is currently always in IO space */
+ /* Evaluate the namespace object containing the values for this state */
- status =
- acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8);
- break;
+ status = acpi_ns_evaluate(info);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "%s while evaluating SleepState [%s]\n",
+ acpi_format_exception(status),
+ info->pathname));
- default:
- status = AE_BAD_PARAMETER;
- break;
+ goto cleanup;
}
- exit:
- return_ACPI_STATUS(status);
-}
-
-/******************************************************************************
- *
- * FUNCTION: acpi_hw_low_level_read
- *
- * PARAMETERS: Width - 8, 16, or 32
- * Value - Where the value is returned
- * Reg - GAS register structure
- *
- * RETURN: Status
- *
- * DESCRIPTION: Read from either memory or IO space.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_hw_low_level_read(u32 width, u32 * value, struct acpi_generic_address *reg)
-{
- u64 address;
- acpi_status status;
-
- ACPI_FUNCTION_NAME(hw_low_level_read);
+ /* Must have a return object */
- /*
- * Must have a valid pointer to a GAS structure, and
- * a non-zero address within. However, don't return an error
- * because the PM1A/B code must not fail if B isn't present.
- */
- if (!reg) {
- return (AE_OK);
+ if (!info->return_object) {
+ ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
+ info->pathname));
+ status = AE_NOT_EXIST;
}
- /* Get a local copy of the address. Handles possible alignment issues */
+ /* It must be of type Package */
- ACPI_MOVE_64_TO_64(&address, &reg->address);
- if (!address) {
- return (AE_OK);
+ else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) {
+ ACPI_ERROR((AE_INFO,
+ "Sleep State return object is not a Package"));
+ status = AE_AML_OPERAND_TYPE;
}
- *value = 0;
/*
- * Two address spaces supported: Memory or IO.
- * PCI_Config is not supported here because the GAS struct is insufficient
+ * The package must have at least two elements. NOTE (March 2005): This
+ * goes against the current ACPI spec which defines this object as a
+ * package with one encoded DWORD element. However, existing practice
+ * by BIOS vendors seems to be to have 2 or more elements, at least
+ * one per sleep type (A/B).
*/
- switch (reg->space_id) {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-
- status = acpi_os_read_memory((acpi_physical_address) address,
- value, width);
- break;
-
- case ACPI_ADR_SPACE_SYSTEM_IO:
-
- status =
- acpi_os_read_port((acpi_io_address) address, value, width);
- break;
-
- default:
+ else if (info->return_object->package.count < 2) {
ACPI_ERROR((AE_INFO,
- "Unsupported address space: %X", reg->space_id));
- return (AE_BAD_PARAMETER);
+ "Sleep State return package does not have at least two elements"));
+ status = AE_AML_NO_OPERAND;
}
- ACPI_DEBUG_PRINT((ACPI_DB_IO,
- "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
- *value, width, ACPI_FORMAT_UINT64(address),
- acpi_ut_get_region_name(reg->space_id)));
-
- return (status);
-}
-
-/******************************************************************************
- *
- * FUNCTION: acpi_hw_low_level_write
- *
- * PARAMETERS: Width - 8, 16, or 32
- * Value - To be written
- * Reg - GAS register structure
- *
- * RETURN: Status
- *
- * DESCRIPTION: Write to either memory or IO space.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_hw_low_level_write(u32 width, u32 value, struct acpi_generic_address * reg)
-{
- u64 address;
- acpi_status status;
-
- ACPI_FUNCTION_NAME(hw_low_level_write);
-
- /*
- * Must have a valid pointer to a GAS structure, and
- * a non-zero address within. However, don't return an error
- * because the PM1A/B code must not fail if B isn't present.
- */
- if (!reg) {
- return (AE_OK);
- }
+ /* The first two elements must both be of type Integer */
- /* Get a local copy of the address. Handles possible alignment issues */
+ else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0])
+ != ACPI_TYPE_INTEGER) ||
+ (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1])
+ != ACPI_TYPE_INTEGER)) {
+ ACPI_ERROR((AE_INFO,
+ "Sleep State return package elements are not both Integers (%s, %s)",
+ acpi_ut_get_object_type_name(info->return_object->
+ package.elements[0]),
+ acpi_ut_get_object_type_name(info->return_object->
+ package.elements[1])));
+ status = AE_AML_OPERAND_TYPE;
+ } else {
+ /* Valid _Sx_ package size, type, and value */
- ACPI_MOVE_64_TO_64(&address, &reg->address);
- if (!address) {
- return (AE_OK);
+ *sleep_type_a = (u8)
+ (info->return_object->package.elements[0])->integer.value;
+ *sleep_type_b = (u8)
+ (info->return_object->package.elements[1])->integer.value;
}
- /*
- * Two address spaces supported: Memory or IO.
- * PCI_Config is not supported here because the GAS struct is insufficient
- */
- switch (reg->space_id) {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-
- status = acpi_os_write_memory((acpi_physical_address) address,
- value, width);
- break;
-
- case ACPI_ADR_SPACE_SYSTEM_IO:
-
- status = acpi_os_write_port((acpi_io_address) address, value,
- width);
- break;
-
- default:
- ACPI_ERROR((AE_INFO,
- "Unsupported address space: %X", reg->space_id));
- return (AE_BAD_PARAMETER);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While evaluating SleepState [%s], bad Sleep object %p type %s",
+ info->pathname, info->return_object,
+ acpi_ut_get_object_type_name(info->
+ return_object)));
}
- ACPI_DEBUG_PRINT((ACPI_DB_IO,
- "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
- value, width, ACPI_FORMAT_UINT64(address),
- acpi_ut_get_region_name(reg->space_id)));
+ acpi_ut_remove_reference(info->return_object);
- return (status);
+ cleanup:
+ ACPI_FREE(info);
+ return_ACPI_STATUS(status);
}
+
+ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index c39a7f68b889..88303ebe924c 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acdispat.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acnamesp.h"
+#include "acdispat.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsaccess")
@@ -165,12 +166,9 @@ acpi_status acpi_ns_root_initialize(void)
obj_desc->method.method_flags =
AML_METHOD_INTERNAL_ONLY;
-
-#ifndef ACPI_DUMP_APP
obj_desc->method.implementation =
acpi_ut_osi_implementation;
#endif
-#endif
break;
case ACPI_TYPE_INTEGER:
@@ -521,11 +519,11 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
}
/*
- * Search namespace for each segment of the name. Loop through and
+ * Search namespace for each segment of the name. Loop through and
* verify (or add to the namespace) each name segment.
*
* The object type is significant only at the last name
- * segment. (We don't care about the types along the path, only
+ * segment. (We don't care about the types along the path, only
* the type of the final target object.)
*/
this_search_type = ACPI_TYPE_ANY;
@@ -591,6 +589,10 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
* segments).
*/
if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) {
+ if (!this_node->object) {
+ return_ACPI_STATUS(AE_NOT_EXIST);
+ }
+
if (acpi_ns_opens_scope
(((struct acpi_namespace_node *)this_node->
object)->type)) {
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/acpica/nsalloc.c
index 3a1740ac2edc..f976d848fe82 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/acpica/nsalloc.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsalloc")
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/acpica/nsdump.c
index cc0ae39440e4..0da33c8e9ba2 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsdump")
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
index 428f50fde11a..41994fe7fbb8 100644
--- a/drivers/acpi/namespace/nsdumpdv.c
+++ b/drivers/acpi/acpica/nsdumpdv.c
@@ -42,6 +42,7 @@
*/
#include <acpi/acpi.h>
+#include "accommon.h"
/* TBD: This entire module is apparently obsolete and should be removed */
@@ -49,7 +50,7 @@
ACPI_MODULE_NAME("nsdumpdv")
#ifdef ACPI_OBSOLETE_FUNCTIONS
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-#include <acpi/acnamesp.h>
+#include "acnamesp.h"
/*******************************************************************************
*
* FUNCTION: acpi_ns_dump_one_device
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/acpica/nseval.c
index 4cdf03ac2b46..0f3d5f9b5966 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acinterp.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nseval")
@@ -89,6 +90,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
/* Initialize the return value to an invalid object */
info->return_object = NULL;
+ info->param_count = 0;
/*
* Get the actual namespace node for the target object. Handles these cases:
@@ -141,41 +143,17 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
return_ACPI_STATUS(AE_NULL_OBJECT);
}
- /*
- * Calculate the number of arguments being passed to the method
- */
+ /* Count the number of arguments being passed to the method */
- info->param_count = 0;
if (info->parameters) {
- while (info->parameters[info->param_count])
+ while (info->parameters[info->param_count]) {
+ if (info->param_count > ACPI_METHOD_MAX_ARG) {
+ return_ACPI_STATUS(AE_LIMIT);
+ }
info->param_count++;
+ }
}
- /*
- * Warning if too few or too many arguments have been passed by the
- * caller. We don't want to abort here with an error because an
- * incorrect number of arguments may not cause the method to fail.
- * However, the method will fail if there are too few arguments passed
- * and the method attempts to use one of the missing ones.
- */
-
- if (info->param_count < info->obj_desc->method.param_count) {
- ACPI_WARNING((AE_INFO,
- "Insufficient arguments - "
- "method [%4.4s] needs %d, found %d",
- acpi_ut_get_node_name(info->resolved_node),
- info->obj_desc->method.param_count,
- info->param_count));
- } else if (info->param_count >
- info->obj_desc->method.param_count) {
- ACPI_WARNING((AE_INFO,
- "Excess arguments - "
- "method [%4.4s] needs %d, found %d",
- acpi_ut_get_node_name(info->
- resolved_node),
- info->obj_desc->method.param_count,
- info->param_count));
- }
ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
ACPI_LV_INFO, _COMPONENT);
@@ -264,32 +242,13 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
}
}
- /* Validation of return values for ACPI-predefined methods and objects */
-
- if ((status == AE_OK) || (status == AE_CTRL_RETURN_VALUE)) {
- /*
- * If this is the first evaluation, check the return value. This
- * ensures that any warnings will only be emitted during the very
- * first evaluation of the object.
- */
- if (!(node->flags & ANOBJ_EVALUATED)) {
- /*
- * Check for a predefined ACPI name. If found, validate the
- * returned object.
- *
- * Note: Ignore return status for now, emit warnings if there are
- * problems with the returned object. May change later to abort
- * the method on invalid return object.
- */
- (void)acpi_ns_check_predefined_names(node,
- info->
- return_object);
- }
-
- /* Mark the node as having been evaluated */
-
- node->flags |= ANOBJ_EVALUATED;
- }
+ /*
+ * Check input argument count against the ASL-defined count for a method.
+ * Also check predefined names: argument count and return value against
+ * the ACPI specification. Some incorrect return value types are repaired.
+ */
+ (void)acpi_ns_check_predefined_names(node, info->param_count,
+ status, &info->return_object);
/* Check if there is a return value that must be dealt with */
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/acpica/nsinit.c
index e4c57510d798..13501cb81863 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/acpica/nsinit.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acdispat.h"
+#include "acinterp.h"
#include <linux/nmi.h>
#define _COMPONENT ACPI_NAMESPACE
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/acpica/nsload.c
index a4a412b7c029..a0ba9e12379e 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/acpica/nsload.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acdispat.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acdispat.h"
+#include "actables.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsload")
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/acpica/nsnames.c
index 42a39a7c96e9..ae3dc10a7e81 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsnames")
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/acpica/nsobject.c
index 15fe09e24f71..08a97a57f8f9 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/acpica/nsobject.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsobject")
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/acpica/nsparse.c
index a82271a9dbb3..b9e8d0070b6f 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/acpica/nsparse.c
@@ -42,10 +42,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "actables.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsparse")
diff --git a/drivers/acpi/namespace/nspredef.c b/drivers/acpi/acpica/nspredef.c
index 0f17cf0898c9..452703290d35 100644
--- a/drivers/acpi/namespace/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -43,8 +43,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acpredef.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acpredef.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nspredef")
@@ -72,7 +73,7 @@ ACPI_MODULE_NAME("nspredef")
/* Local prototypes */
static acpi_status
acpi_ns_check_package(char *pathname,
- union acpi_operand_object *return_object,
+ union acpi_operand_object **return_object_ptr,
const union acpi_predefined_info *predefined);
static acpi_status
@@ -82,13 +83,18 @@ acpi_ns_check_package_elements(char *pathname,
static acpi_status
acpi_ns_check_object_type(char *pathname,
- union acpi_operand_object *return_object,
+ union acpi_operand_object **return_object_ptr,
u32 expected_btypes, u32 package_index);
static acpi_status
acpi_ns_check_reference(char *pathname,
union acpi_operand_object *return_object);
+static acpi_status
+acpi_ns_repair_object(u32 expected_btypes,
+ u32 package_index,
+ union acpi_operand_object **return_object_ptr);
+
/*
* Names for the types that can be returned by the predefined objects.
* Used for warning messages. Must be in the same order as the ACPI_RTYPEs
@@ -108,8 +114,8 @@ static const char *acpi_rtype_names[] = {
* FUNCTION: acpi_ns_check_predefined_names
*
* PARAMETERS: Node - Namespace node for the method/object
- * return_object - Object returned from the evaluation of this
- * method/object
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
*
* RETURN: Status
*
@@ -119,8 +125,11 @@ static const char *acpi_rtype_names[] = {
acpi_status
acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
- union acpi_operand_object *return_object)
+ u32 user_param_count,
+ acpi_status return_status,
+ union acpi_operand_object **return_object_ptr)
{
+ union acpi_operand_object *return_object = *return_object_ptr;
acpi_status status = AE_OK;
const union acpi_predefined_info *predefined;
char *pathname;
@@ -128,12 +137,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
/* Match the name for this method/object against the predefined list */
predefined = acpi_ns_check_for_predefined_name(node);
- if (!predefined) {
-
- /* Name was not one of the predefined names */
-
- return (AE_OK);
- }
/* Get the full pathname to the object, for use in error messages */
@@ -143,10 +146,37 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
}
/*
- * Check that the parameter count for this method is in accordance
- * with the ACPI specification.
+ * Check that the parameter count for this method matches the ASL
+ * definition. For predefined names, ensure that both the caller and
+ * the method itself are in accordance with the ACPI specification.
*/
- acpi_ns_check_parameter_count(pathname, node, predefined);
+ acpi_ns_check_parameter_count(pathname, node, user_param_count,
+ predefined);
+
+ /* If not a predefined name, we cannot validate the return object */
+
+ if (!predefined) {
+ goto exit;
+ }
+
+ /* If the method failed, we cannot validate the return object */
+
+ if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) {
+ goto exit;
+ }
+
+ /*
+ * Only validate the return value on the first successful evaluation of
+ * the method. This ensures that any warnings will only be emitted during
+ * the very first evaluation of the method/object.
+ */
+ if (node->flags & ANOBJ_EVALUATED) {
+ goto exit;
+ }
+
+ /* Mark the node as having been successfully evaluated */
+
+ node->flags |= ANOBJ_EVALUATED;
/*
* If there is no return value, check if we require a return value for
@@ -171,7 +201,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
* We have a return value, but if one wasn't expected, just exit, this is
* not a problem
*
- * For example, if "Implicit return value" is enabled, methods will
+ * For example, if the "Implicit Return" feature is enabled, methods will
* always return a value
*/
if (!predefined->info.expected_btypes) {
@@ -182,7 +212,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
* Check that the type of the return object is what is expected for
* this predefined name
*/
- status = acpi_ns_check_object_type(pathname, return_object,
+ status = acpi_ns_check_object_type(pathname, return_object_ptr,
predefined->info.expected_btypes,
ACPI_NOT_PACKAGE);
if (ACPI_FAILURE(status)) {
@@ -193,11 +223,12 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) {
status =
- acpi_ns_check_package(pathname, return_object, predefined);
+ acpi_ns_check_package(pathname, return_object_ptr,
+ predefined);
}
exit:
- if (pathname) {
+ if (pathname != predefined->info.name) {
ACPI_FREE(pathname);
}
@@ -210,6 +241,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
*
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
* Node - Namespace node for the method/object
+ * user_param_count - Number of args passed in by the caller
* Predefined - Pointer to entry in predefined name table
*
* RETURN: None
@@ -223,32 +255,76 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
void
acpi_ns_check_parameter_count(char *pathname,
struct acpi_namespace_node *node,
+ u32 user_param_count,
const union acpi_predefined_info *predefined)
{
u32 param_count;
u32 required_params_current;
u32 required_params_old;
- /*
- * Check that the ASL-defined parameter count is what is expected for
- * this predefined name.
- *
- * Methods have 0-7 parameters. All other types have zero.
- */
+ /* Methods have 0-7 parameters. All other types have zero. */
+
param_count = 0;
if (node->type == ACPI_TYPE_METHOD) {
param_count = node->object->method.param_count;
}
- /* Validate parameter count - allow two different legal counts (_SCP) */
+ /* Argument count check for non-predefined methods/objects */
+
+ if (!predefined) {
+ /*
+ * Warning if too few or too many arguments have been passed by the
+ * caller. An incorrect number of arguments may not cause the method
+ * to fail. However, the method will fail if there are too few
+ * arguments and the method attempts to use one of the missing ones.
+ */
+ if (user_param_count < param_count) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Insufficient arguments - needs %d, found %d",
+ pathname, param_count, user_param_count));
+ } else if (user_param_count > param_count) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Excess arguments - needs %d, found %d",
+ pathname, param_count, user_param_count));
+ }
+ return;
+ }
+
+ /* Allow two different legal argument counts (_SCP, etc.) */
required_params_current = predefined->info.param_count & 0x0F;
required_params_old = predefined->info.param_count >> 4;
+ if (user_param_count != ACPI_UINT32_MAX) {
+
+ /* Validate the user-supplied parameter count */
+
+ if ((user_param_count != required_params_current) &&
+ (user_param_count != required_params_old)) {
+ ACPI_WARNING((AE_INFO,
+ "%s: Parameter count mismatch - caller passed %d, ACPI requires %d",
+ pathname, user_param_count,
+ required_params_current));
+ }
+ }
+
+ /*
+ * Only validate the argument count on the first successful evaluation of
+ * the method. This ensures that any warnings will only be emitted during
+ * the very first evaluation of the method/object.
+ */
+ if (node->flags & ANOBJ_EVALUATED) {
+ return;
+ }
+
+ /*
+ * Check that the ASL-defined parameter count is what is expected for
+ * this predefined name.
+ */
if ((param_count != required_params_current) &&
(param_count != required_params_old)) {
ACPI_WARNING((AE_INFO,
- "%s: Parameter count mismatch - ASL declared %d, expected %d",
+ "%s: Parameter count mismatch - ASL declared %d, ACPI requires %d",
pathname, param_count, required_params_current));
}
}
@@ -307,8 +383,8 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
* FUNCTION: acpi_ns_check_package
*
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
- * return_object - Object returned from the evaluation of a
- * method or object
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
* Predefined - Pointer to entry in predefined name table
*
* RETURN: Status
@@ -320,9 +396,10 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct
static acpi_status
acpi_ns_check_package(char *pathname,
- union acpi_operand_object *return_object,
+ union acpi_operand_object **return_object_ptr,
const union acpi_predefined_info *predefined)
{
+ union acpi_operand_object *return_object = *return_object_ptr;
const union acpi_predefined_info *package;
union acpi_operand_object *sub_package;
union acpi_operand_object **elements;
@@ -408,7 +485,7 @@ acpi_ns_check_package(char *pathname,
* elements must be of the same type
*/
for (i = 0; i < count; i++) {
- status = acpi_ns_check_object_type(pathname, *elements,
+ status = acpi_ns_check_object_type(pathname, elements,
package->ret_info.
object_type1, i);
if (ACPI_FAILURE(status)) {
@@ -441,7 +518,7 @@ acpi_ns_check_package(char *pathname,
status =
acpi_ns_check_object_type(pathname,
- *elements,
+ elements,
package->
ret_info3.
object_type[i],
@@ -454,7 +531,7 @@ acpi_ns_check_package(char *pathname,
status =
acpi_ns_check_object_type(pathname,
- *elements,
+ elements,
package->
ret_info3.
tail_object_type,
@@ -471,7 +548,7 @@ acpi_ns_check_package(char *pathname,
/* First element is the (Integer) count of sub-packages to follow */
- status = acpi_ns_check_object_type(pathname, *elements,
+ status = acpi_ns_check_object_type(pathname, elements,
ACPI_RTYPE_INTEGER, 0);
if (ACPI_FAILURE(status)) {
return (status);
@@ -509,7 +586,7 @@ acpi_ns_check_package(char *pathname,
/* Each sub-object must be of type Package */
status =
- acpi_ns_check_object_type(pathname, sub_package,
+ acpi_ns_check_object_type(pathname, &sub_package,
ACPI_RTYPE_PACKAGE, i);
if (ACPI_FAILURE(status)) {
return (status);
@@ -567,12 +644,8 @@ acpi_ns_check_package(char *pathname,
for (j = 0; j < expected_count; j++) {
status =
acpi_ns_check_object_type(pathname,
- sub_elements
- [j],
- package->
- ret_info2.
- object_type
- [j], j);
+ &sub_elements[j],
+ package->ret_info2.object_type[j], j);
if (ACPI_FAILURE(status)) {
return (status);
}
@@ -611,7 +684,7 @@ acpi_ns_check_package(char *pathname,
status =
acpi_ns_check_object_type(pathname,
- *sub_elements,
+ sub_elements,
ACPI_RTYPE_INTEGER,
0);
if (ACPI_FAILURE(status)) {
@@ -708,7 +781,7 @@ acpi_ns_check_package_elements(char *pathname,
* The second group can have a count of zero.
*/
for (i = 0; i < count1; i++) {
- status = acpi_ns_check_object_type(pathname, *this_element,
+ status = acpi_ns_check_object_type(pathname, this_element,
type1, i);
if (ACPI_FAILURE(status)) {
return (status);
@@ -717,7 +790,7 @@ acpi_ns_check_package_elements(char *pathname,
}
for (i = 0; i < count2; i++) {
- status = acpi_ns_check_object_type(pathname, *this_element,
+ status = acpi_ns_check_object_type(pathname, this_element,
type2, (i + count1));
if (ACPI_FAILURE(status)) {
return (status);
@@ -733,8 +806,8 @@ acpi_ns_check_package_elements(char *pathname,
* FUNCTION: acpi_ns_check_object_type
*
* PARAMETERS: Pathname - Full pathname to the node (for error msgs)
- * return_object - Object return from the execution of this
- * method/object
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
* expected_btypes - Bitmap of expected return type(s)
* package_index - Index of object within parent package (if
* applicable - ACPI_NOT_PACKAGE otherwise)
@@ -748,9 +821,10 @@ acpi_ns_check_package_elements(char *pathname,
static acpi_status
acpi_ns_check_object_type(char *pathname,
- union acpi_operand_object *return_object,
+ union acpi_operand_object **return_object_ptr,
u32 expected_btypes, u32 package_index)
{
+ union acpi_operand_object *return_object = *return_object_ptr;
acpi_status status = AE_OK;
u32 return_btype;
char type_buffer[48]; /* Room for 5 types */
@@ -814,6 +888,14 @@ acpi_ns_check_object_type(char *pathname,
/* Is the object one of the expected types? */
if (!(return_btype & expected_btypes)) {
+
+ /* Type mismatch -- attempt repair of the returned object */
+
+ status = acpi_ns_repair_object(expected_btypes, package_index,
+ return_object_ptr);
+ if (ACPI_SUCCESS(status)) {
+ return (status);
+ }
goto type_error_exit;
}
@@ -898,3 +980,86 @@ acpi_ns_check_reference(char *pathname,
return (AE_AML_OPERAND_TYPE);
}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_repair_object
+ *
+ * PARAMETERS: Pathname - Full pathname to the node (for error msgs)
+ * package_index - Used to determine if target is in a package
+ * return_object_ptr - Pointer to the object returned from the
+ * evaluation of a method or object
+ *
+ * RETURN: Status. AE_OK if repair was successful.
+ *
+ * DESCRIPTION: Attempt to repair/convert a return object of a type that was
+ * not expected.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_repair_object(u32 expected_btypes,
+ u32 package_index,
+ union acpi_operand_object **return_object_ptr)
+{
+ union acpi_operand_object *return_object = *return_object_ptr;
+ union acpi_operand_object *new_object;
+ acpi_size length;
+
+ switch (ACPI_GET_OBJECT_TYPE(return_object)) {
+ case ACPI_TYPE_BUFFER:
+
+ if (!(expected_btypes & ACPI_RTYPE_STRING)) {
+ return (AE_AML_OPERAND_TYPE);
+ }
+
+ /*
+ * Have a Buffer, expected a String, convert. Use a to_string
+ * conversion, no transform performed on the buffer data. The best
+ * example of this is the _BIF method, where the string data from
+ * the battery is often (incorrectly) returned as buffer object(s).
+ */
+ length = 0;
+ while ((length < return_object->buffer.length) &&
+ (return_object->buffer.pointer[length])) {
+ length++;
+ }
+
+ /* Allocate a new string object */
+
+ new_object = acpi_ut_create_string_object(length);
+ if (!new_object) {
+ return (AE_NO_MEMORY);
+ }
+
+ /*
+ * Copy the raw buffer data with no transform. String is already NULL
+ * terminated at Length+1.
+ */
+ ACPI_MEMCPY(new_object->string.pointer,
+ return_object->buffer.pointer, length);
+
+ /* Install the new return object */
+
+ acpi_ut_remove_reference(return_object);
+ *return_object_ptr = new_object;
+
+ /*
+ * If the object is a package element, we need to:
+ * 1. Decrement the reference count of the orignal object, it was
+ * incremented when building the package
+ * 2. Increment the reference count of the new object, it will be
+ * decremented when releasing the package
+ */
+ if (package_index != ACPI_NOT_PACKAGE) {
+ acpi_ut_remove_reference(return_object);
+ acpi_ut_add_reference(new_object);
+ }
+ return (AE_OK);
+
+ default:
+ break;
+ }
+
+ return (AE_AML_OPERAND_TYPE);
+}
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/acpica/nssearch.c
index a9a80bf811b3..6fea13f3f52d 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/acpica/nssearch.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nssearch")
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/acpica/nsutils.c
index b0817e1127b1..3e1149bf4aa5 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -43,9 +43,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/amlcode.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "amlcode.h"
+#include "actables.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsutils")
@@ -314,9 +315,15 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
*
* strlen() + 1 covers the first name_seg, which has no path separator
*/
- if (acpi_ns_valid_root_prefix(next_external_char[0])) {
+ if (acpi_ns_valid_root_prefix(*next_external_char)) {
info->fully_qualified = TRUE;
next_external_char++;
+
+ /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */
+
+ while (acpi_ns_valid_root_prefix(*next_external_char)) {
+ next_external_char++;
+ }
} else {
/*
* Handle Carat prefixes
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/acpica/nswalk.c
index 3c905ce26d7d..200895fa2728 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/acpica/nswalk.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nswalk")
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index a085cc39c055..22a7171ac1ed 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -43,8 +43,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfeval")
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index 5efa4e7ddb0b..9589fea24997 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfname")
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c
index 2b375ee80cef..1c7efc15225f 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/acpica/nsxfobj.c
@@ -43,7 +43,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfobj")
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/acpica/psargs.c
index d830b29b85b1..b161f3544b51 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/acpica/psargs.c
@@ -42,10 +42,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acdispat.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acnamesp.h"
+#include "acdispat.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psargs")
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/acpica/psloop.c
index 4647039a0d8a..c5f6ce19a401 100644
--- a/drivers/acpi/parser/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -50,9 +50,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psloop")
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/acpica/psopcode.c
index f425ab30eae8..3bc3a60194d6 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/acpica/psopcode.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acopcode.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acopcode.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psopcode")
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/acpica/psparse.c
index 68e932f215ea..70838e9b608c 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/acpica/psparse.c
@@ -51,11 +51,12 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
-#include <acpi/amlcode.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "amlcode.h"
+#include "acnamesp.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psparse")
@@ -447,10 +448,22 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
walk_state, walk_state->parser_state.aml,
walk_state->parser_state.aml_size));
+ if (!walk_state->parser_state.aml) {
+ return_ACPI_STATUS(AE_NULL_OBJECT);
+ }
+
/* Create and initialize a new thread state */
thread = acpi_ut_create_thread_state();
if (!thread) {
+ if (walk_state->method_desc) {
+
+ /* Executing a control method - additional cleanup */
+
+ acpi_ds_terminate_control_method(
+ walk_state->method_desc, walk_state);
+ }
+
acpi_ds_delete_walk_state(walk_state);
return_ACPI_STATUS(AE_NO_MEMORY);
}
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/acpica/psscope.c
index ee50e67c9443..2feca5ca9581 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/acpica/psscope.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
+#include "accommon.h"
+#include "acparser.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psscope")
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/acpica/pstree.c
index 1dd355ddd182..4d3389118ec3 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/acpica/pstree.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("pstree")
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/acpica/psutils.c
index 7cf1f65cd5bb..e636e078ad3d 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/acpica/psutils.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/amlcode.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psutils")
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/acpica/pswalk.c
index 8b86ad5a3201..78b8b791f2ae 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/acpica/pswalk.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
+#include "accommon.h"
+#include "acparser.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("pswalk")
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/acpica/psxface.c
index 270469aae842..ff06032c0f06 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -42,9 +42,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "amlcode.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psxface")
@@ -278,6 +280,38 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
goto cleanup;
}
+ /* Invoke an internal method if necessary */
+
+ if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
+ status = info->obj_desc->method.implementation(walk_state);
+ info->return_object = walk_state->return_desc;
+
+ /* Cleanup states */
+
+ acpi_ds_scope_stack_clear(walk_state);
+ acpi_ps_cleanup_scope(&walk_state->parser_state);
+ acpi_ds_terminate_control_method(walk_state->method_desc,
+ walk_state);
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
+ }
+
+ /*
+ * Start method evaluation with an implicit return of zero.
+ * This is done for Windows compatibility.
+ */
+ if (acpi_gbl_enable_interpreter_slack) {
+ walk_state->implicit_return_obj =
+ acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+ if (!walk_state->implicit_return_obj) {
+ status = AE_NO_MEMORY;
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
+ }
+
+ walk_state->implicit_return_obj->integer.value = 0;
+ }
+
/* Parse the AML */
status = acpi_ps_parse_aml(walk_state);
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/acpica/rsaddr.c
index 7f96332822bf..1e437bfd8db5 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/acpica/rsaddr.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsaddr")
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/acpica/rscalc.c
index 8eaaecf92009..52865ee6bc77 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/acpica/rscalc.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acresrc.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rscalc")
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/acpica/rscreate.c
index c0bbfa2c4193..61566b1a0616 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/acpica/rscreate.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acresrc.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rscreate")
@@ -124,7 +125,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
*
* FUNCTION: acpi_rs_create_pci_routing_table
*
- * PARAMETERS: package_object - Pointer to an union acpi_operand_object
+ * PARAMETERS: package_object - Pointer to a union acpi_operand_object
* package
* output_buffer - Pointer to the user's buffer
*
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/acpica/rsdump.c
index 6bbbb7b8941a..3f0ca5a12d34 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/acpica/rsdump.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsdump")
diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/acpica/rsinfo.c
index 3f0a1fedbe0e..77b25fdb459c 100644
--- a/drivers/acpi/resources/rsinfo.c
+++ b/drivers/acpi/acpica/rsinfo.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsinfo")
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/acpica/rsio.c
index b66d42e7402e..35a49aa95609 100644
--- a/drivers/acpi/resources/rsio.c
+++ b/drivers/acpi/acpica/rsio.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsio")
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/acpica/rsirq.c
index a8805efc0366..2e0256983aa6 100644
--- a/drivers/acpi/resources/rsirq.c
+++ b/drivers/acpi/acpica/rsirq.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsirq")
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/acpica/rslist.c
index b78c7e797a19..1b1dbc69f087 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/acpica/rslist.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rslist")
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/acpica/rsmemory.c
index 63b21abd90bb..ddc76cebdc92 100644
--- a/drivers/acpi/resources/rsmemory.c
+++ b/drivers/acpi/acpica/rsmemory.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsmemory")
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/acpica/rsmisc.c
index 96a6c0353255..5bc49a553284 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/acpica/rsmisc.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsmisc")
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/acpica/rsutils.c
index f7b3bcd59ba7..bc03d5966829 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/acpica/rsutils.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acresrc.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acresrc.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsutils")
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/acpica/rsxface.c
index f59f4c4e034c..69a2aa5b5d83 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acresrc.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acresrc.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_RESOURCES
ACPI_MODULE_NAME("rsxface")
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 2817158fb6a1..3636e4f8fb73 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -42,15 +42,16 @@
*/
#include <acpi/acpi.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbfadt")
/* Local prototypes */
-static void inline
+static inline void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 byte_width, u64 address);
+ u8 space_id, u8 byte_width, u64 address);
static void acpi_tb_convert_fadt(void);
@@ -60,9 +61,10 @@ static void acpi_tb_validate_fadt(void);
typedef struct acpi_fadt_info {
char *name;
- u8 target;
- u8 source;
+ u8 address64;
+ u8 address32;
u8 length;
+ u8 default_length;
u8 type;
} acpi_fadt_info;
@@ -71,37 +73,61 @@ typedef struct acpi_fadt_info {
#define ACPI_FADT_SEPARATE_LENGTH 2
static struct acpi_fadt_info fadt_info_table[] = {
- {"Pm1aEventBlock", ACPI_FADT_OFFSET(xpm1a_event_block),
+ {"Pm1aEventBlock",
+ ACPI_FADT_OFFSET(xpm1a_event_block),
ACPI_FADT_OFFSET(pm1a_event_block),
- ACPI_FADT_OFFSET(pm1_event_length), ACPI_FADT_REQUIRED},
+ ACPI_FADT_OFFSET(pm1_event_length),
+ ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
+ ACPI_FADT_REQUIRED},
- {"Pm1bEventBlock", ACPI_FADT_OFFSET(xpm1b_event_block),
+ {"Pm1bEventBlock",
+ ACPI_FADT_OFFSET(xpm1b_event_block),
ACPI_FADT_OFFSET(pm1b_event_block),
- ACPI_FADT_OFFSET(pm1_event_length), 0},
+ ACPI_FADT_OFFSET(pm1_event_length),
+ ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */
+ 0},
- {"Pm1aControlBlock", ACPI_FADT_OFFSET(xpm1a_control_block),
+ {"Pm1aControlBlock",
+ ACPI_FADT_OFFSET(xpm1a_control_block),
ACPI_FADT_OFFSET(pm1a_control_block),
- ACPI_FADT_OFFSET(pm1_control_length), ACPI_FADT_REQUIRED},
+ ACPI_FADT_OFFSET(pm1_control_length),
+ ACPI_PM1_REGISTER_WIDTH,
+ ACPI_FADT_REQUIRED},
- {"Pm1bControlBlock", ACPI_FADT_OFFSET(xpm1b_control_block),
+ {"Pm1bControlBlock",
+ ACPI_FADT_OFFSET(xpm1b_control_block),
ACPI_FADT_OFFSET(pm1b_control_block),
- ACPI_FADT_OFFSET(pm1_control_length), 0},
+ ACPI_FADT_OFFSET(pm1_control_length),
+ ACPI_PM1_REGISTER_WIDTH,
+ 0},
- {"Pm2ControlBlock", ACPI_FADT_OFFSET(xpm2_control_block),
+ {"Pm2ControlBlock",
+ ACPI_FADT_OFFSET(xpm2_control_block),
ACPI_FADT_OFFSET(pm2_control_block),
- ACPI_FADT_OFFSET(pm2_control_length), ACPI_FADT_SEPARATE_LENGTH},
+ ACPI_FADT_OFFSET(pm2_control_length),
+ ACPI_PM2_REGISTER_WIDTH,
+ ACPI_FADT_SEPARATE_LENGTH},
- {"PmTimerBlock", ACPI_FADT_OFFSET(xpm_timer_block),
+ {"PmTimerBlock",
+ ACPI_FADT_OFFSET(xpm_timer_block),
ACPI_FADT_OFFSET(pm_timer_block),
- ACPI_FADT_OFFSET(pm_timer_length), ACPI_FADT_REQUIRED},
+ ACPI_FADT_OFFSET(pm_timer_length),
+ ACPI_PM_TIMER_WIDTH,
+ ACPI_FADT_REQUIRED},
- {"Gpe0Block", ACPI_FADT_OFFSET(xgpe0_block),
+ {"Gpe0Block",
+ ACPI_FADT_OFFSET(xgpe0_block),
ACPI_FADT_OFFSET(gpe0_block),
- ACPI_FADT_OFFSET(gpe0_block_length), ACPI_FADT_SEPARATE_LENGTH},
+ ACPI_FADT_OFFSET(gpe0_block_length),
+ 0,
+ ACPI_FADT_SEPARATE_LENGTH},
- {"Gpe1Block", ACPI_FADT_OFFSET(xgpe1_block),
+ {"Gpe1Block",
+ ACPI_FADT_OFFSET(xgpe1_block),
ACPI_FADT_OFFSET(gpe1_block),
- ACPI_FADT_OFFSET(gpe1_block_length), ACPI_FADT_SEPARATE_LENGTH}
+ ACPI_FADT_OFFSET(gpe1_block_length),
+ 0,
+ ACPI_FADT_SEPARATE_LENGTH}
};
#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info))
@@ -122,9 +148,9 @@ static struct acpi_fadt_info fadt_info_table[] = {
*
******************************************************************************/
-static void inline
+static inline void
acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
- u8 byte_width, u64 address)
+ u8 space_id, u8 byte_width, u64 address)
{
/*
@@ -135,10 +161,10 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
/* All other fields are byte-wide */
- generic_address->space_id = ACPI_ADR_SPACE_SYSTEM_IO;
- generic_address->bit_width = byte_width << 3;
+ generic_address->space_id = space_id;
+ generic_address->bit_width = (u8)ACPI_MUL_8(byte_width);
generic_address->bit_offset = 0;
- generic_address->access_width = 0;
+ generic_address->access_width = 0; /* Access width ANY */
}
/*******************************************************************************
@@ -225,7 +251,8 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
*/
if (length > sizeof(struct acpi_table_fadt)) {
ACPI_WARNING((AE_INFO,
- "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX",
+ "FADT (revision %u) is longer than ACPI 2.0 version, "
+ "truncating length 0x%X to 0x%zX",
table->revision, (unsigned)length,
sizeof(struct acpi_table_fadt)));
}
@@ -244,7 +271,6 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
* 2) Validate some of the important values within the FADT
*/
acpi_tb_convert_fadt();
- acpi_tb_validate_fadt();
}
/*******************************************************************************
@@ -278,22 +304,36 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
static void acpi_tb_convert_fadt(void)
{
- u8 pm1_register_length;
- struct acpi_generic_address *target;
+ u8 pm1_register_bit_width;
+ u8 pm1_register_byte_width;
+ struct acpi_generic_address *target64;
u32 i;
/* Update the local FADT table header length */
acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
- /* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary */
-
+ /*
+ * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
+ * Later code will always use the X 64-bit field. Also, check for an
+ * address mismatch between the 32-bit and 64-bit address fields
+ * (FIRMWARE_CTRL/X_FIRMWARE_CTRL, DSDT/X_DSDT) which would indicate
+ * the presence of two FACS or two DSDT tables.
+ */
if (!acpi_gbl_FADT.Xfacs) {
acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs;
+ } else if (acpi_gbl_FADT.facs &&
+ (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) {
+ ACPI_WARNING((AE_INFO,
+ "32/64 FACS address mismatch in FADT - two FACS tables!"));
}
if (!acpi_gbl_FADT.Xdsdt) {
acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt;
+ } else if (acpi_gbl_FADT.dsdt &&
+ (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) {
+ ACPI_WARNING((AE_INFO,
+ "32/64 DSDT address mismatch in FADT - two DSDT tables!"));
}
/*
@@ -312,18 +352,23 @@ static void acpi_tb_convert_fadt(void)
}
/*
- * Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X"
- * generic address structures as necessary.
+ * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
+ * generic address structures as necessary. Later code will always use
+ * the 64-bit address structures.
*/
for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
- target =
+ target64 =
ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT,
- fadt_info_table[i].target);
+ fadt_info_table[i].address64);
- /* Expand only if the X target is null */
+ /* Expand only if the 64-bit X target is null */
- if (!target->address) {
- acpi_tb_init_generic_address(target,
+ if (!target64->address) {
+
+ /* The space_id is always I/O for the 32-bit legacy address fields */
+
+ acpi_tb_init_generic_address(target64,
+ ACPI_ADR_SPACE_SYSTEM_IO,
*ACPI_ADD_PTR(u8,
&acpi_gbl_FADT,
fadt_info_table
@@ -332,11 +377,64 @@ static void acpi_tb_convert_fadt(void)
&acpi_gbl_FADT,
fadt_info_table
[i].
- source));
+ address32));
+ }
+ }
+
+ /* Validate FADT values now, before we make any changes */
+
+ acpi_tb_validate_fadt();
+
+ /*
+ * Optionally check all register lengths against the default values and
+ * update them if they are incorrect.
+ */
+ if (acpi_gbl_use_default_register_widths) {
+ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
+ target64 =
+ ACPI_ADD_PTR(struct acpi_generic_address,
+ &acpi_gbl_FADT,
+ fadt_info_table[i].address64);
+
+ /*
+ * If a valid register (Address != 0) and the (default_length > 0)
+ * (Not a GPE register), then check the width against the default.
+ */
+ if ((target64->address) &&
+ (fadt_info_table[i].default_length > 0) &&
+ (fadt_info_table[i].default_length !=
+ target64->bit_width)) {
+ ACPI_WARNING((AE_INFO,
+ "Invalid length for %s: %d, using default %d",
+ fadt_info_table[i].name,
+ target64->bit_width,
+ fadt_info_table[i].
+ default_length));
+
+ /* Incorrect size, set width to the default */
+
+ target64->bit_width =
+ fadt_info_table[i].default_length;
+ }
}
}
/*
+ * Get the length of the individual PM1 registers (enable and status).
+ * Each register is defined to be (event block length / 2).
+ */
+ pm1_register_bit_width =
+ (u8)ACPI_DIV_2(acpi_gbl_FADT.xpm1a_event_block.bit_width);
+ pm1_register_byte_width = (u8)ACPI_DIV_8(pm1_register_bit_width);
+
+ /*
+ * Adjust the lengths of the PM1 Event Blocks so that they can be used to
+ * access the PM1 status register(s). Use (width / 2)
+ */
+ acpi_gbl_FADT.xpm1a_event_block.bit_width = pm1_register_bit_width;
+ acpi_gbl_FADT.xpm1b_event_block.bit_width = pm1_register_bit_width;
+
+ /*
* Calculate separate GAS structs for the PM1 Enable registers.
* These addresses do not appear (directly) in the FADT, so it is
* useful to calculate them once, here.
@@ -356,14 +454,14 @@ static void acpi_tb_convert_fadt(void)
" PM1_EVT_LEN (%u)\n",
acpi_gbl_FADT.xpm1a_event_block.bit_width,
acpi_gbl_FADT.pm1_event_length);
- pm1_register_length = (u8) ACPI_DIV_2(acpi_gbl_FADT.pm1_event_length);
/* The PM1A register block is required */
acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable,
- pm1_register_length,
+ acpi_gbl_FADT.xpm1a_event_block.space_id,
+ pm1_register_byte_width,
(acpi_gbl_FADT.xpm1a_event_block.address +
- pm1_register_length));
+ pm1_register_byte_width));
/* Don't forget to copy space_id of the GAS */
acpi_gbl_xpm1a_enable.space_id =
acpi_gbl_FADT.xpm1a_event_block.space_id;
@@ -379,9 +477,10 @@ static void acpi_tb_convert_fadt(void)
acpi_gbl_FADT.xpm1b_event_block.bit_width,
acpi_gbl_FADT.pm1_event_length);
acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable,
- pm1_register_length,
+ acpi_gbl_FADT.xpm1b_event_block.space_id,
+ pm1_register_byte_width,
(acpi_gbl_FADT.xpm1b_event_block.
- address + pm1_register_length));
+ address + pm1_register_byte_width));
/* Don't forget to copy space_id of the GAS */
acpi_gbl_xpm1b_enable.space_id =
acpi_gbl_FADT.xpm1b_event_block.space_id;
@@ -411,26 +510,63 @@ static void acpi_tb_convert_fadt(void)
static void acpi_tb_validate_fadt(void)
{
+ char *name;
u32 *address32;
struct acpi_generic_address *address64;
u8 length;
u32 i;
- /* Examine all of the 64-bit extended address fields (X fields) */
+ /*
+ * Check for FACS and DSDT address mismatches. An address mismatch between
+ * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
+ * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
+ */
+ if (acpi_gbl_FADT.facs &&
+ (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) {
+ ACPI_WARNING((AE_INFO,
+ "32/64X FACS address mismatch in FADT - "
+ "two FACS tables! %8.8X/%8.8X%8.8X",
+ acpi_gbl_FADT.facs,
+ ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs)));
+ }
- for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
+ if (acpi_gbl_FADT.dsdt &&
+ (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) {
+ ACPI_WARNING((AE_INFO,
+ "32/64X DSDT address mismatch in FADT - "
+ "two DSDT tables! %8.8X/%8.8X%8.8X",
+ acpi_gbl_FADT.dsdt,
+ ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt)));
+ }
- /* Generate pointers to the 32-bit and 64-bit addresses and get the length */
+ /* Examine all of the 64-bit extended address fields (X fields) */
- address64 =
- ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT,
- fadt_info_table[i].target);
+ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
+ /*
+ * Generate pointers to the 32-bit and 64-bit addresses, get the
+ * register length (width), and the register name
+ */
+ address64 = ACPI_ADD_PTR(struct acpi_generic_address,
+ &acpi_gbl_FADT,
+ fadt_info_table[i].address64);
address32 =
ACPI_ADD_PTR(u32, &acpi_gbl_FADT,
- fadt_info_table[i].source);
+ fadt_info_table[i].address32);
length =
*ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
fadt_info_table[i].length);
+ name = fadt_info_table[i].name;
+
+ /*
+ * For each extended field, check for length mismatch between the
+ * legacy length field and the corresponding 64-bit X length field.
+ */
+ if (address64 && (address64->bit_width != ACPI_MUL_8(length))) {
+ ACPI_WARNING((AE_INFO,
+ "32/64X length mismatch in %s: %d/%d",
+ name, ACPI_MUL_8(length),
+ address64->bit_width));
+ }
if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) {
/*
@@ -439,8 +575,8 @@ static void acpi_tb_validate_fadt(void)
*/
if (!address64->address || !length) {
ACPI_ERROR((AE_INFO,
- "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X",
- fadt_info_table[i].name,
+ "Required field %s has zero address and/or length: %8.8X%8.8X/%X",
+ name,
ACPI_FORMAT_UINT64(address64->
address),
length));
@@ -453,8 +589,8 @@ static void acpi_tb_validate_fadt(void)
if ((address64->address && !length)
|| (!address64->address && length)) {
ACPI_WARNING((AE_INFO,
- "Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X",
- fadt_info_table[i].name,
+ "Optional field %s has zero address or length: %8.8X%8.8X/%X",
+ name,
ACPI_FORMAT_UINT64(address64->
address),
length));
@@ -466,8 +602,8 @@ static void acpi_tb_validate_fadt(void)
if (address64->address && *address32 &&
(address64->address != (u64) * address32)) {
ACPI_ERROR((AE_INFO,
- "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X",
- fadt_info_table[i].name, *address32,
+ "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 64X",
+ name, *address32,
ACPI_FORMAT_UINT64(address64->address)));
}
}
diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/acpica/tbfind.c
index 531584defbb8..1054dfd49207 100644
--- a/drivers/acpi/tables/tbfind.c
+++ b/drivers/acpi/acpica/tbfind.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbfind")
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 18747ce8dd2f..37374b21969d 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbinstal")
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 0cc92ef5236f..9684cc827930 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbutils")
@@ -113,6 +114,30 @@ acpi_tb_check_xsdt(acpi_physical_address address)
/*******************************************************************************
*
+ * FUNCTION: acpi_tb_initialize_facs
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
+ * for accessing the Global Lock and Firmware Waking Vector
+ *
+ ******************************************************************************/
+
+acpi_status acpi_tb_initialize_facs(void)
+{
+ acpi_status status;
+
+ status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+ ACPI_CAST_INDIRECT_PTR(struct
+ acpi_table_header,
+ &acpi_gbl_FACS));
+ return status;
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_tb_tables_loaded
*
* PARAMETERS: None
@@ -420,7 +445,8 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
/* Differentiate between RSDT and XSDT root tables */
- if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
+ if (rsdp->revision > 1 && rsdp->xsdt_physical_address
+ && !acpi_rsdt_forced) {
/*
* Root table is an XSDT (64-bit physical addresses). We must use the
* XSDT if the revision is > 1 and the XSDT pointer is present, as per
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/acpica/tbxface.c
index fd7770aa1061..c3e841f3cde9 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -43,8 +43,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbxface")
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 2d157e0f98d2..b7fc8dd43341 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "actables.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbxfroot")
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/acpica/utalloc.c
index 241c535c1753..7580f6b3069e 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/acpica/utalloc.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acdebug.h>
+#include "accommon.h"
+#include "acdebug.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utalloc")
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/acpica/utcopy.c
index 5b2f7c27b705..b0dcfd3c872a 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_UTILITIES
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/acpica/utdebug.c
index fd66ecb6741e..38821f53042c 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/acpica/utdebug.c
@@ -42,6 +42,7 @@
*/
#include <acpi/acpi.h>
+#include "accommon.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utdebug")
@@ -136,7 +137,7 @@ static const char *acpi_ut_trim_function_name(const char *function_name)
/*******************************************************************************
*
- * FUNCTION: acpi_ut_debug_print
+ * FUNCTION: acpi_debug_print
*
* PARAMETERS: requested_debug_level - Requested debug print level
* line_number - Caller's line number (for error output)
@@ -154,11 +155,11 @@ static const char *acpi_ut_trim_function_name(const char *function_name)
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print(u32 requested_debug_level,
- u32 line_number,
- const char *function_name,
- const char *module_name,
- u32 component_id, const char *format, ...)
+acpi_debug_print(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ const char *module_name,
+ u32 component_id, const char *format, ...)
{
acpi_thread_id thread_id;
va_list args;
@@ -205,11 +206,11 @@ acpi_ut_debug_print(u32 requested_debug_level,
va_end(args);
}
-ACPI_EXPORT_SYMBOL(acpi_ut_debug_print)
+ACPI_EXPORT_SYMBOL(acpi_debug_print)
/*******************************************************************************
*
- * FUNCTION: acpi_ut_debug_print_raw
+ * FUNCTION: acpi_debug_print_raw
*
* PARAMETERS: requested_debug_level - Requested debug print level
* line_number - Caller's line number
@@ -226,11 +227,11 @@ ACPI_EXPORT_SYMBOL(acpi_ut_debug_print)
*
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_debug_print_raw(u32 requested_debug_level,
- u32 line_number,
- const char *function_name,
- const char *module_name,
- u32 component_id, const char *format, ...)
+acpi_debug_print_raw(u32 requested_debug_level,
+ u32 line_number,
+ const char *function_name,
+ const char *module_name,
+ u32 component_id, const char *format, ...)
{
va_list args;
@@ -244,7 +245,7 @@ acpi_ut_debug_print_raw(u32 requested_debug_level,
va_end(args);
}
-ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw)
+ACPI_EXPORT_SYMBOL(acpi_debug_print_raw)
/*******************************************************************************
*
@@ -270,9 +271,9 @@ acpi_ut_trace(u32 line_number,
acpi_gbl_nesting_level++;
acpi_ut_track_stack_ptr();
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s\n", acpi_gbl_fn_entry_str);
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name, component_id,
+ "%s\n", acpi_gbl_fn_entry_str);
}
ACPI_EXPORT_SYMBOL(acpi_ut_trace)
@@ -301,10 +302,9 @@ acpi_ut_trace_ptr(u32 line_number,
acpi_gbl_nesting_level++;
acpi_ut_track_stack_ptr();
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s %p\n", acpi_gbl_fn_entry_str,
- pointer);
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name, component_id,
+ "%s %p\n", acpi_gbl_fn_entry_str, pointer);
}
/*******************************************************************************
@@ -333,10 +333,9 @@ acpi_ut_trace_str(u32 line_number,
acpi_gbl_nesting_level++;
acpi_ut_track_stack_ptr();
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s %s\n", acpi_gbl_fn_entry_str,
- string);
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name, component_id,
+ "%s %s\n", acpi_gbl_fn_entry_str, string);
}
/*******************************************************************************
@@ -365,10 +364,9 @@ acpi_ut_trace_u32(u32 line_number,
acpi_gbl_nesting_level++;
acpi_ut_track_stack_ptr();
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s %08X\n", acpi_gbl_fn_entry_str,
- integer);
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name, component_id,
+ "%s %08X\n", acpi_gbl_fn_entry_str, integer);
}
/*******************************************************************************
@@ -393,9 +391,9 @@ acpi_ut_exit(u32 line_number,
const char *module_name, u32 component_id)
{
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s\n", acpi_gbl_fn_exit_str);
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name, component_id,
+ "%s\n", acpi_gbl_fn_exit_str);
acpi_gbl_nesting_level--;
}
@@ -426,17 +424,16 @@ acpi_ut_status_exit(u32 line_number,
{
if (ACPI_SUCCESS(status)) {
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s %s\n",
- acpi_gbl_fn_exit_str,
- acpi_format_exception(status));
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s %s\n", acpi_gbl_fn_exit_str,
+ acpi_format_exception(status));
} else {
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s ****Exception****: %s\n",
- acpi_gbl_fn_exit_str,
- acpi_format_exception(status));
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name,
+ component_id, "%s ****Exception****: %s\n",
+ acpi_gbl_fn_exit_str,
+ acpi_format_exception(status));
}
acpi_gbl_nesting_level--;
@@ -467,10 +464,10 @@ acpi_ut_value_exit(u32 line_number,
u32 component_id, acpi_integer value)
{
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s %8.8X%8.8X\n",
- acpi_gbl_fn_exit_str, ACPI_FORMAT_UINT64(value));
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name, component_id,
+ "%s %8.8X%8.8X\n", acpi_gbl_fn_exit_str,
+ ACPI_FORMAT_UINT64(value));
acpi_gbl_nesting_level--;
}
@@ -499,9 +496,9 @@ acpi_ut_ptr_exit(u32 line_number,
const char *module_name, u32 component_id, u8 *ptr)
{
- acpi_ut_debug_print(ACPI_LV_FUNCTIONS,
- line_number, function_name, module_name,
- component_id, "%s %p\n", acpi_gbl_fn_exit_str, ptr);
+ acpi_debug_print(ACPI_LV_FUNCTIONS,
+ line_number, function_name, module_name, component_id,
+ "%s %p\n", acpi_gbl_fn_exit_str, ptr);
acpi_gbl_nesting_level--;
}
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/acpica/utdelete.c
index d197c6b29e17..a0be9e39531e 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acevents.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utdelete")
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/acpica/uteval.c
index 352747e49c7a..da9450bc60f7 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/acpica/uteval.c
@@ -42,8 +42,9 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acinterp.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acinterp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("uteval")
@@ -129,7 +130,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
/* The interface is supported */
- return_ACPI_STATUS(AE_CTRL_TERMINATE);
+ return_ACPI_STATUS(AE_OK);
}
}
@@ -143,13 +144,13 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
/* The interface is supported */
- return_ACPI_STATUS(AE_CTRL_TERMINATE);
+ return_ACPI_STATUS(AE_OK);
}
/* The interface is not supported */
return_desc->integer.value = 0;
- return_ACPI_STATUS(AE_CTRL_TERMINATE);
+ return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/acpica/utglobal.c
index 17ed5ac840f7..a3ab9d9da299 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -44,11 +44,11 @@
#define DEFINE_ACPI_GLOBALS
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
-ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
#define _COMPONENT ACPI_UTILITIES
- ACPI_MODULE_NAME("utglobal")
+ACPI_MODULE_NAME("utglobal")
/*******************************************************************************
*
@@ -352,7 +352,7 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
"PCI_Config",
"EmbeddedControl",
"SMBus",
- "CMOS",
+ "SystemCMOS",
"PCIBARTarget",
"DataTable"
};
@@ -756,6 +756,7 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_gpe_xrupt_list_head = NULL;
acpi_gbl_gpe_fadt_blocks[0] = NULL;
acpi_gbl_gpe_fadt_blocks[1] = NULL;
+ acpi_current_gpe_count = 0;
/* Global handlers */
@@ -771,6 +772,7 @@ acpi_status acpi_ut_init_globals(void)
acpi_gbl_global_lock_mutex = NULL;
acpi_gbl_global_lock_acquired = FALSE;
acpi_gbl_global_lock_handle = 0;
+ acpi_gbl_global_lock_present = FALSE;
/* Miscellaneous variables */
@@ -815,5 +817,7 @@ acpi_status acpi_ut_init_globals(void)
return_ACPI_STATUS(AE_OK);
}
+ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
ACPI_EXPORT_SYMBOL(acpi_dbg_level)
ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
+ACPI_EXPORT_SYMBOL(acpi_current_gpe_count)
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/acpica/utinit.c
index cae515fc02d3..a54ca84eb362 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -42,9 +42,10 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acevents.h>
-#include <acpi/actables.h>
+#include "accommon.h"
+#include "acnamesp.h"
+#include "acevents.h"
+#include "actables.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utinit")
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/acpica/utmath.c
index c927324fdd26..c9f682d640ef 100644
--- a/drivers/acpi/utilities/utmath.c
+++ b/drivers/acpi/acpica/utmath.c
@@ -42,6 +42,7 @@
*/
#include <acpi/acpi.h>
+#include "accommon.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utmath")
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/acpica/utmisc.c
index 9089a158a874..c1f7f4e1a72d 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/acpica/utmisc.c
@@ -44,7 +44,8 @@
#include <linux/module.h>
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utmisc")
@@ -1016,7 +1017,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
/*******************************************************************************
*
- * FUNCTION: acpi_ut_error, acpi_ut_warning, acpi_ut_info
+ * FUNCTION: acpi_error, acpi_exception, acpi_warning, acpi_info
*
* PARAMETERS: module_name - Caller's module name (for error output)
* line_number - Caller's line number (for error output)
@@ -1029,7 +1030,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
******************************************************************************/
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_error(const char *module_name, u32 line_number, const char *format, ...)
+acpi_error(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
@@ -1042,8 +1043,8 @@ acpi_ut_error(const char *module_name, u32 line_number, const char *format, ...)
}
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_exception(const char *module_name,
- u32 line_number, acpi_status status, const char *format, ...)
+acpi_exception(const char *module_name,
+ u32 line_number, acpi_status status, const char *format, ...)
{
va_list args;
@@ -1056,11 +1057,8 @@ acpi_ut_exception(const char *module_name,
va_end(args);
}
-EXPORT_SYMBOL(acpi_ut_exception);
-
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_warning(const char *module_name,
- u32 line_number, const char *format, ...)
+acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
@@ -1073,7 +1071,7 @@ acpi_ut_warning(const char *module_name,
}
void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_info(const char *module_name, u32 line_number, const char *format, ...)
+acpi_info(const char *module_name, u32 line_number, const char *format, ...)
{
va_list args;
@@ -1088,3 +1086,8 @@ acpi_ut_info(const char *module_name, u32 line_number, const char *format, ...)
acpi_os_printf("\n");
va_end(args);
}
+
+ACPI_EXPORT_SYMBOL(acpi_error)
+ACPI_EXPORT_SYMBOL(acpi_exception)
+ACPI_EXPORT_SYMBOL(acpi_warning)
+ACPI_EXPORT_SYMBOL(acpi_info)
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/acpica/utmutex.c
index 7331dde9e1b3..14eb52c4d647 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/acpica/utmutex.c
@@ -42,6 +42,7 @@
*/
#include <acpi/acpi.h>
+#include "accommon.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utmutex")
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/acpica/utobject.c
index c354e7a42bcd..fd5ea7543e5b 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/acpica/utobject.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
+#include "accommon.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utobject")
@@ -297,7 +298,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
*
* RETURN: TRUE if object is valid, FALSE otherwise
*
- * DESCRIPTION: Validate a pointer to be an union acpi_operand_object
+ * DESCRIPTION: Validate a pointer to be a union acpi_operand_object
*
******************************************************************************/
@@ -389,7 +390,7 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object)
{
ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object);
- /* Object must be an union acpi_operand_object */
+ /* Object must be a union acpi_operand_object */
if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
ACPI_ERROR((AE_INFO,
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/acpica/utresrc.c
index c3e3e1308edc..91b7c00236f4 100644
--- a/drivers/acpi/utilities/utresrc.c
+++ b/drivers/acpi/acpica/utresrc.c
@@ -42,7 +42,8 @@
*/
#include <acpi/acpi.h>
-#include <acpi/amlresrc.h>
+#include "accommon.h"
+#include "amlresrc.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utresrc")
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/acpica/utstate.c
index 63a6d3d77d88..0440c958f5a4 100644
--- a/drivers/acpi/utilities/utstate.c
+++ b/drivers/acpi/acpica/utstate.c
@@ -42,6 +42,7 @@
*/
#include <acpi/acpi.h>
+#include "accommon.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utstate")
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/acpica/utxface.c
index c198a4d40583..078a22728c6b 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -42,9 +42,11 @@
*/
#include <acpi/acpi.h>
-#include <acpi/acevents.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acdebug.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+#include "actables.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utxface")
@@ -148,6 +150,16 @@ acpi_status acpi_enable_subsystem(u32 flags)
}
/*
+ * Obtain a permanent mapping for the FACS. This is required for the
+ * Global Lock and the Firmware Waking Vector
+ */
+ status = acpi_tb_initialize_facs();
+ if (ACPI_FAILURE(status)) {
+ ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
+ return_ACPI_STATUS(status);
+ }
+
+ /*
* Install the default op_region handlers. These are installed unless
* other handlers have already been installed via the
* install_address_space_handler interface.
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 1423b0c0cd2e..65132f920459 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -471,7 +471,7 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
static int acpi_battery_update(struct acpi_battery *battery)
{
- int result;
+ int result, old_present = acpi_battery_present(battery);
result = acpi_battery_get_status(battery);
if (result)
return result;
@@ -482,7 +482,8 @@ static int acpi_battery_update(struct acpi_battery *battery)
return 0;
}
#endif
- if (!battery->update_time) {
+ if (!battery->update_time ||
+ old_present != acpi_battery_present(battery)) {
result = acpi_battery_get_info(battery);
if (result)
return result;
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
index 307963bd1043..332fe4b21708 100644
--- a/drivers/acpi/cm_sbs.c
+++ b/drivers/acpi/cm_sbs.c
@@ -27,9 +27,6 @@
#include <linux/seq_file.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#include <acpi/acmacros.h>
-#include <acpi/actypes.h>
-#include <acpi/acutils.h>
ACPI_MODULE_NAME("cm_sbs");
#define ACPI_AC_CLASS "ac_adapter"
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index c48396892008..20223cbd0d1c 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -9,7 +9,6 @@
#include <linux/moduleparam.h>
#include <asm/uaccess.h>
#include <acpi/acpi_drivers.h>
-#include <acpi/acglobal.h>
#define _COMPONENT ACPI_SYSTEM_COMPONENT
ACPI_MODULE_NAME("debug");
diff --git a/drivers/acpi/dispatcher/Makefile b/drivers/acpi/dispatcher/Makefile
deleted file mode 100644
index eb7e602a83cd..000000000000
--- a/drivers/acpi/dispatcher/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \
- dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \
- dsinit.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 30f3ef236ecb..a2b82c90a683 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -42,7 +42,6 @@
#include <asm/io.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#include <acpi/actypes.h>
#define ACPI_EC_CLASS "embedded_controller"
#define ACPI_EC_DEVICE_NAME "Embedded Controller"
@@ -121,31 +120,6 @@ static struct acpi_ec {
spinlock_t curr_lock;
} *boot_ec, *first_ec;
-/*
- * Some Asus system have exchanged ECDT data/command IO addresses.
- */
-static int print_ecdt_error(const struct dmi_system_id *id)
-{
- printk(KERN_NOTICE PREFIX "%s detected - "
- "ECDT has exchanged control/data I/O address\n",
- id->ident);
- return 0;
-}
-
-static struct dmi_system_id __cpuinitdata ec_dmi_table[] = {
- {
- print_ecdt_error, "Asus L4R", {
- DMI_MATCH(DMI_BIOS_VERSION, "1008.006"),
- DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),
- DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL},
- {
- print_ecdt_error, "Asus M6R", {
- DMI_MATCH(DMI_BIOS_VERSION, "0207"),
- DMI_MATCH(DMI_PRODUCT_NAME, "M6R"),
- DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL},
- {},
-};
-
/* --------------------------------------------------------------------------
Transaction Management
-------------------------------------------------------------------------- */
@@ -370,7 +344,7 @@ unlock:
* Note: samsung nv5000 doesn't work with ec burst mode.
* http://bugzilla.kernel.org/show_bug.cgi?id=4980
*/
-int acpi_ec_burst_enable(struct acpi_ec *ec)
+static int acpi_ec_burst_enable(struct acpi_ec *ec)
{
u8 d;
struct transaction t = {.command = ACPI_EC_BURST_ENABLE,
@@ -380,7 +354,7 @@ int acpi_ec_burst_enable(struct acpi_ec *ec)
return acpi_ec_transaction(ec, &t, 0);
}
-int acpi_ec_burst_disable(struct acpi_ec *ec)
+static int acpi_ec_burst_disable(struct acpi_ec *ec)
{
struct transaction t = {.command = ACPI_EC_BURST_DISABLE,
.wdata = NULL, .rdata = NULL,
@@ -756,10 +730,15 @@ static acpi_status
acpi_ec_register_query_methods(acpi_handle handle, u32 level,
void *context, void **return_value)
{
- struct acpi_namespace_node *node = handle;
+ char node_name[5];
+ struct acpi_buffer buffer = { sizeof(node_name), node_name };
struct acpi_ec *ec = context;
int value = 0;
- if (sscanf(node->name.ascii, "_Q%x", &value) == 1) {
+ acpi_status status;
+
+ status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
+
+ if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1) {
acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
}
return AE_OK;
@@ -978,8 +957,8 @@ static const struct acpi_device_id ec_device_ids[] = {
int __init acpi_ec_ecdt_probe(void)
{
- int ret;
acpi_status status;
+ struct acpi_ec *saved_ec = NULL;
struct acpi_table_ecdt *ecdt_ptr;
boot_ec = make_acpi_ec();
@@ -994,42 +973,55 @@ int __init acpi_ec_ecdt_probe(void)
pr_info(PREFIX "EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address;
- if (dmi_check_system(ec_dmi_table)) {
- /*
- * If the board falls into ec_dmi_table, it means
- * that ECDT table gives the incorrect command/status
- * & data I/O address. Just fix it.
- */
- boot_ec->data_addr = ecdt_ptr->control.address;
- boot_ec->command_addr = ecdt_ptr->data.address;
- }
boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT;
acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
+ /* Don't trust ECDT, which comes from ASUSTek */
+ if (!dmi_name_in_vendors("ASUS"))
+ goto install;
+ saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ if (!saved_ec)
+ return -ENOMEM;
+ memcpy(&saved_ec, boot_ec, sizeof(saved_ec));
+ /* fall through */
+ }
+ /* This workaround is needed only on some broken machines,
+ * which require early EC, but fail to provide ECDT */
+ printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
+ status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
+ boot_ec, NULL);
+ /* Check that acpi_get_devices actually find something */
+ if (ACPI_FAILURE(status) || !boot_ec->handle)
+ goto error;
+ if (saved_ec) {
+ /* try to find good ECDT from ASUSTek */
+ if (saved_ec->command_addr != boot_ec->command_addr ||
+ saved_ec->data_addr != boot_ec->data_addr ||
+ saved_ec->gpe != boot_ec->gpe ||
+ saved_ec->handle != boot_ec->handle)
+ pr_info(PREFIX "ASUSTek keeps feeding us with broken "
+ "ECDT tables, which are very hard to workaround. "
+ "Trying to use DSDT EC info instead. Please send "
+ "output of acpidump to linux-acpi@vger.kernel.org\n");
+ kfree(saved_ec);
+ saved_ec = NULL;
} else {
- /* This workaround is needed only on some broken machines,
- * which require early EC, but fail to provide ECDT */
- acpi_handle x;
- printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
- status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
- boot_ec, NULL);
- /* Check that acpi_get_devices actually find something */
- if (ACPI_FAILURE(status) || !boot_ec->handle)
- goto error;
/* We really need to limit this workaround, the only ASUS,
- * which needs it, has fake EC._INI method, so use it as flag.
- * Keep boot_ec struct as it will be needed soon.
- */
- if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x)))
+ * which needs it, has fake EC._INI method, so use it as flag.
+ * Keep boot_ec struct as it will be needed soon.
+ */
+ acpi_handle dummy;
+ if (!dmi_name_in_vendors("ASUS") ||
+ ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI",
+ &dummy)))
return -ENODEV;
}
-
- ret = ec_install_handlers(boot_ec);
- if (!ret) {
+install:
+ if (!ec_install_handlers(boot_ec)) {
first_ec = boot_ec;
return 0;
}
- error:
+error:
kfree(boot_ec);
boot_ec = NULL;
return -ENODEV;
diff --git a/drivers/acpi/events/Makefile b/drivers/acpi/events/Makefile
deleted file mode 100644
index d29f2ee449cc..000000000000
--- a/drivers/acpi/events/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := evevent.o evregion.o evsci.o evxfevnt.o \
- evmisc.o evrgnini.o evxface.o evxfregn.o \
- evgpe.o evgpeblk.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/executer/Makefile b/drivers/acpi/executer/Makefile
deleted file mode 100644
index e09998aa012f..000000000000
--- a/drivers/acpi/executer/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
- exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\
- excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \
- exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/hardware/Makefile b/drivers/acpi/hardware/Makefile
deleted file mode 100644
index 438ad373b9ad..000000000000
--- a/drivers/acpi/hardware/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := hwacpi.o hwgpe.o hwregs.o hwsleep.o
-
-obj-$(ACPI_FUTURE_USAGE) += hwtimer.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile
deleted file mode 100644
index 371a2daf837f..000000000000
--- a/drivers/acpi/namespace/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \
- nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
- nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
- nsparse.o nspredef.o
-
-obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 25ceae9191ef..c5e292aab0e3 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -29,7 +29,6 @@
#include <linux/errno.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
-#include <acpi/acmacros.h>
#define ACPI_NUMA 0x80000000
#define _COMPONENT ACPI_NUMA
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c8111424dcb8..6729a4992f2b 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -726,7 +726,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
if (!dpc)
- return_ACPI_STATUS(AE_NO_MEMORY);
+ return AE_NO_MEMORY;
dpc->function = function;
dpc->context = context;
@@ -747,7 +747,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
status = AE_ERROR;
kfree(dpc);
}
- return_ACPI_STATUS(status);
+ return status;
}
acpi_status acpi_os_execute(acpi_execute_type type,
diff --git a/drivers/acpi/parser/Makefile b/drivers/acpi/parser/Makefile
deleted file mode 100644
index db24ee09cf11..000000000000
--- a/drivers/acpi/parser/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := psargs.o psparse.o psloop.o pstree.o pswalk.o \
- psopcode.o psscope.o psutils.o psxface.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 4b252ea0e952..95650f83ce2e 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -99,7 +99,7 @@ acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id)
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %s has PCI address %02x:%02x:%02x.%02x\n",
+ "Device %s has PCI address %04x:%02x:%02x.%d\n",
acpi_device_bid(device), id->segment, id->bus,
id->device, id->function));
@@ -111,12 +111,11 @@ EXPORT_SYMBOL(acpi_get_pci_id);
int acpi_pci_bind(struct acpi_device *device)
{
int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- struct acpi_pci_data *pdata = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = { 0, NULL };
- acpi_handle handle = NULL;
+ acpi_status status;
+ struct acpi_pci_data *data;
+ struct acpi_pci_data *pdata;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ acpi_handle handle;
struct pci_dev *dev;
struct pci_bus *bus;
@@ -124,21 +123,18 @@ int acpi_pci_bind(struct acpi_device *device)
if (!device || !device->parent)
return -EINVAL;
- pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
- buffer.length = ACPI_PATHNAME_MAX;
- buffer.pointer = pathname;
-
data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
- if (!data) {
- kfree(pathname);
+ if (!data)
return -ENOMEM;
+
+ status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
+ if (ACPI_FAILURE(status)) {
+ kfree(data);
+ return -ENODEV;
}
- acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n",
- pathname));
+ (char *)buffer.pointer));
/*
* Segment & Bus
@@ -166,7 +162,7 @@ int acpi_pci_bind(struct acpi_device *device)
data->id.device = device->pnp.bus_address >> 16;
data->id.function = device->pnp.bus_address & 0xFFFF;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n",
data->id.segment, data->id.bus, data->id.device,
data->id.function));
@@ -196,7 +192,7 @@ int acpi_pci_bind(struct acpi_device *device)
}
if (!data->dev) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
+ "Device %04x:%02x:%02x.%d not present in PCI namespace\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function));
result = -ENODEV;
@@ -204,7 +200,7 @@ int acpi_pci_bind(struct acpi_device *device)
}
if (!data->dev->bus) {
printk(KERN_ERR PREFIX
- "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n",
+ "Device %04x:%02x:%02x.%d has invalid 'bus' field\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function);
result = -ENODEV;
@@ -219,7 +215,7 @@ int acpi_pci_bind(struct acpi_device *device)
*/
if (data->dev->subordinate) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %02x:%02x:%02x.%02x is a PCI bridge\n",
+ "Device %04x:%02x:%02x.%d is a PCI bridge\n",
data->id.segment, data->id.bus,
data->id.device, data->id.function));
data->bus = data->dev->subordinate;
@@ -262,7 +258,7 @@ int acpi_pci_bind(struct acpi_device *device)
}
end:
- kfree(pathname);
+ kfree(buffer.pointer);
if (result)
kfree(data);
@@ -272,25 +268,21 @@ int acpi_pci_bind(struct acpi_device *device)
static int acpi_pci_unbind(struct acpi_device *device)
{
int result = 0;
- acpi_status status = AE_OK;
- struct acpi_pci_data *data = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = { 0, NULL };
+ acpi_status status;
+ struct acpi_pci_data *data;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
if (!device || !device->parent)
return -EINVAL;
- pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
+ status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
- buffer.length = ACPI_PATHNAME_MAX;
- buffer.pointer = pathname;
- acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n",
- pathname));
- kfree(pathname);
+ (char *) buffer.pointer));
+ kfree(buffer.pointer);
status =
acpi_get_data(device->handle, acpi_pci_data_handler,
@@ -322,50 +314,44 @@ acpi_pci_bind_root(struct acpi_device *device,
struct acpi_pci_id *id, struct pci_bus *bus)
{
int result = 0;
- acpi_status status = AE_OK;
+ acpi_status status;
struct acpi_pci_data *data = NULL;
- char *pathname = NULL;
- struct acpi_buffer buffer = { 0, NULL };
-
- pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
-
- buffer.length = ACPI_PATHNAME_MAX;
- buffer.pointer = pathname;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
if (!device || !id || !bus) {
- kfree(pathname);
return -EINVAL;
}
data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL);
- if (!data) {
- kfree(pathname);
+ if (!data)
return -ENOMEM;
- }
data->id = *id;
data->bus = bus;
device->ops.bind = acpi_pci_bind;
device->ops.unbind = acpi_pci_unbind;
- acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
+ status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer);
+ if (ACPI_FAILURE(status)) {
+ kfree (data);
+ return -ENODEV;
+ }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to "
- "%02x:%02x\n", pathname, id->segment, id->bus));
+ "%04x:%02x\n", (char *)buffer.pointer,
+ id->segment, id->bus));
status = acpi_attach_data(device->handle, acpi_pci_data_handler, data);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"Unable to attach ACPI-PCI context to device %s",
- pathname));
+ (char *)buffer.pointer));
result = -ENODEV;
goto end;
}
end:
- kfree(pathname);
+ kfree(buffer.pointer);
if (result != 0)
kfree(data);
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index bf79d83bdfbb..891bdf6679f3 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -4,6 +4,8 @@
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
+ * (c) Copyright 2008 Hewlett-Packard Development Company, L.P.
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
@@ -41,29 +43,36 @@
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_irq");
-static struct acpi_prt_list acpi_prt;
+struct acpi_prt_entry {
+ struct list_head list;
+ struct acpi_pci_id id;
+ u8 pin;
+ acpi_handle link;
+ u32 index; /* GSI, or link _CRS index */
+};
+
+static LIST_HEAD(acpi_prt_list);
static DEFINE_SPINLOCK(acpi_prt_lock);
+static inline char pin_name(int pin)
+{
+ return 'A' + pin - 1;
+}
+
/* --------------------------------------------------------------------------
PCI IRQ Routing Table (PRT) Support
-------------------------------------------------------------------------- */
-static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
- int bus,
- int device, int pin)
+static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev,
+ int pin)
{
- struct acpi_prt_entry *entry = NULL;
-
- if (!acpi_prt.count)
- return NULL;
+ struct acpi_prt_entry *entry;
+ int segment = pci_domain_nr(dev->bus);
+ int bus = dev->bus->number;
+ int device = PCI_SLOT(dev->devfn);
- /*
- * Parse through all PRT entries looking for a match on the specified
- * PCI device's segment, bus, device, and pin (don't care about func).
- *
- */
spin_lock(&acpi_prt_lock);
- list_for_each_entry(entry, &acpi_prt.entries, node) {
+ list_for_each_entry(entry, &acpi_prt_list, list) {
if ((segment == entry->id.segment)
&& (bus == entry->id.bus)
&& (device == entry->id.device)
@@ -72,7 +81,6 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment,
return entry;
}
}
-
spin_unlock(&acpi_prt_lock);
return NULL;
}
@@ -124,25 +132,27 @@ struct prt_quirk {
char *actual_source;
};
+#define PCI_INTX_PIN(c) (c - 'A' + 1)
+
/*
* These systems have incorrect _PRT entries. The BIOS claims the PCI
* interrupt at the listed segment/bus/device/pin is connected to the first
* link device, but it is actually connected to the second.
*/
static struct prt_quirk prt_quirks[] = {
- { medion_md9580, 0, 0, 9, 'A',
+ { medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'),
"\\_SB_.PCI0.ISA_.LNKA",
"\\_SB_.PCI0.ISA_.LNKB"},
- { dell_optiplex, 0, 0, 0xd, 'A',
+ { dell_optiplex, 0, 0, 0xd, PCI_INTX_PIN('A'),
"\\_SB_.LNKB",
"\\_SB_.LNKA"},
- { hp_t5710, 0, 0, 1, 'A',
+ { hp_t5710, 0, 0, 1, PCI_INTX_PIN('A'),
"\\_SB_.PCI0.LNK1",
"\\_SB_.PCI0.LNK3"},
};
-static void
-do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
+static void do_prt_fixups(struct acpi_prt_entry *entry,
+ struct acpi_pci_routing_table *prt)
{
int i;
struct prt_quirk *quirk;
@@ -158,42 +168,43 @@ do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt)
entry->id.segment == quirk->segment &&
entry->id.bus == quirk->bus &&
entry->id.device == quirk->device &&
- entry->pin + 'A' == quirk->pin &&
+ entry->pin == quirk->pin &&
!strcmp(prt->source, quirk->source) &&
strlen(prt->source) >= strlen(quirk->actual_source)) {
printk(KERN_WARNING PREFIX "firmware reports "
"%04x:%02x:%02x PCI INT %c connected to %s; "
"changing to %s\n",
entry->id.segment, entry->id.bus,
- entry->id.device, 'A' + entry->pin,
+ entry->id.device, pin_name(entry->pin),
prt->source, quirk->actual_source);
strcpy(prt->source, quirk->actual_source);
}
}
}
-static int
-acpi_pci_irq_add_entry(acpi_handle handle,
- int segment, int bus, struct acpi_pci_routing_table *prt)
+static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus,
+ struct acpi_pci_routing_table *prt)
{
- struct acpi_prt_entry *entry = NULL;
-
-
- if (!prt)
- return -EINVAL;
+ struct acpi_prt_entry *entry;
entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
+ /*
+ * Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses
+ * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert
+ * it here.
+ */
entry->id.segment = segment;
entry->id.bus = bus;
entry->id.device = (prt->address >> 16) & 0xFFFF;
- entry->id.function = prt->address & 0xFFFF;
- entry->pin = prt->pin;
+ entry->pin = prt->pin + 1;
do_prt_fixups(entry, prt);
+ entry->index = prt->source_index;
+
/*
* Type 1: Dynamic
* ---------------
@@ -207,10 +218,9 @@ acpi_pci_irq_add_entry(acpi_handle handle,
* (e.g. exists somewhere 'below' this _PRT entry in the ACPI
* namespace).
*/
- if (prt->source[0]) {
- acpi_get_handle(handle, prt->source, &entry->link.handle);
- entry->link.index = prt->source_index;
- }
+ if (prt->source[0])
+ acpi_get_handle(handle, prt->source, &entry->link);
+
/*
* Type 2: Static
* --------------
@@ -218,84 +228,38 @@ acpi_pci_irq_add_entry(acpi_handle handle,
* the IRQ value, which is hardwired to specific interrupt inputs on
* the interrupt controller.
*/
- else
- entry->link.index = prt->source_index;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
- " %02X:%02X:%02X[%c] -> %s[%d]\n",
+ " %04x:%02x:%02x[%c] -> %s[%d]\n",
entry->id.segment, entry->id.bus,
- entry->id.device, ('A' + entry->pin), prt->source,
- entry->link.index));
+ entry->id.device, pin_name(entry->pin),
+ prt->source, entry->index));
spin_lock(&acpi_prt_lock);
- list_add_tail(&entry->node, &acpi_prt.entries);
- acpi_prt.count++;
+ list_add_tail(&entry->list, &acpi_prt_list);
spin_unlock(&acpi_prt_lock);
return 0;
}
-static void
-acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry)
-{
- if (segment == entry->id.segment && bus == entry->id.bus) {
- acpi_prt.count--;
- list_del(&entry->node);
- kfree(entry);
- }
-}
-
int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
{
- acpi_status status = AE_OK;
- char *pathname = NULL;
- struct acpi_buffer buffer = { 0, NULL };
- struct acpi_pci_routing_table *prt = NULL;
- struct acpi_pci_routing_table *entry = NULL;
- static int first_time = 1;
-
-
- pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL);
- if (!pathname)
- return -ENOMEM;
-
- if (first_time) {
- acpi_prt.count = 0;
- INIT_LIST_HEAD(&acpi_prt.entries);
- first_time = 0;
- }
-
- /*
- * NOTE: We're given a 'handle' to the _PRT object's parent device
- * (either a PCI root bridge or PCI-PCI bridge).
- */
+ acpi_status status;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_pci_routing_table *entry;
- buffer.length = ACPI_PATHNAME_MAX;
- buffer.pointer = pathname;
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
+ status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
- pathname);
+ (char *) buffer.pointer);
- /*
- * Evaluate this _PRT and add its entries to our global list (acpi_prt).
- */
+ kfree(buffer.pointer);
- buffer.length = 0;
+ buffer.length = ACPI_ALLOCATE_BUFFER;
buffer.pointer = NULL;
- kfree(pathname);
- status = acpi_get_irq_routing_table(handle, &buffer);
- if (status != AE_BUFFER_OVERFLOW) {
- ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]",
- acpi_format_exception(status)));
- return -ENODEV;
- }
-
- prt = kzalloc(buffer.length, GFP_KERNEL);
- if (!prt) {
- return -ENOMEM;
- }
- buffer.pointer = prt;
status = acpi_get_irq_routing_table(handle, &buffer);
if (ACPI_FAILURE(status)) {
@@ -305,36 +269,30 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus)
return -ENODEV;
}
- entry = prt;
-
+ entry = buffer.pointer;
while (entry && (entry->length > 0)) {
acpi_pci_irq_add_entry(handle, segment, bus, entry);
entry = (struct acpi_pci_routing_table *)
((unsigned long)entry + entry->length);
}
- kfree(prt);
-
+ kfree(buffer.pointer);
return 0;
}
void acpi_pci_irq_del_prt(int segment, int bus)
{
- struct list_head *node = NULL, *n = NULL;
- struct acpi_prt_entry *entry = NULL;
-
- if (!acpi_prt.count) {
- return;
- }
+ struct acpi_prt_entry *entry, *tmp;
printk(KERN_DEBUG
- "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n", segment,
- bus);
+ "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n",
+ segment, bus);
spin_lock(&acpi_prt_lock);
- list_for_each_safe(node, n, &acpi_prt.entries) {
- entry = list_entry(node, struct acpi_prt_entry, node);
-
- acpi_pci_irq_del_entry(segment, bus, entry);
+ list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) {
+ if (segment == entry->id.segment && bus == entry->id.bus) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
}
spin_unlock(&acpi_prt_lock);
}
@@ -342,162 +300,26 @@ void acpi_pci_irq_del_prt(int segment, int bus)
/* --------------------------------------------------------------------------
PCI Interrupt Routing Support
-------------------------------------------------------------------------- */
-typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **);
-
-static int
-acpi_pci_allocate_irq(struct acpi_prt_entry *entry,
- int *triggering, int *polarity, char **link)
-{
- int irq;
-
-
- if (entry->link.handle) {
- irq = acpi_pci_link_allocate_irq(entry->link.handle,
- entry->link.index, triggering,
- polarity, link);
- if (irq < 0) {
- printk(KERN_WARNING PREFIX
- "Invalid IRQ link routing entry\n");
- return -1;
- }
- } else {
- irq = entry->link.index;
- *triggering = ACPI_LEVEL_SENSITIVE;
- *polarity = ACPI_ACTIVE_LOW;
- }
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq));
- return irq;
-}
-
-static int
-acpi_pci_free_irq(struct acpi_prt_entry *entry,
- int *triggering, int *polarity, char **link)
-{
- int irq;
-
- if (entry->link.handle) {
- irq = acpi_pci_link_free_irq(entry->link.handle);
- } else {
- irq = entry->link.index;
- }
- return irq;
-}
-
-#ifdef CONFIG_X86_IO_APIC
-extern int noioapicquirk;
-
-static int bridge_has_boot_interrupt_variant(struct pci_bus *bus)
+static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
{
- struct pci_bus *bus_it;
-
- for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) {
- if (!bus_it->self)
- return 0;
-
- printk(KERN_INFO "vendor=%04x device=%04x\n", bus_it->self->vendor,
- bus_it->self->device);
-
- if (bus_it->self->irq_reroute_variant)
- return bus_it->self->irq_reroute_variant;
- }
- return 0;
-}
-#endif /* CONFIG_X86_IO_APIC */
-
-/*
- * acpi_pci_irq_lookup
- * success: return IRQ >= 0
- * failure: return -1
- */
-static int
-acpi_pci_irq_lookup(struct pci_bus *bus,
- int device,
- int pin,
- int *triggering,
- int *polarity, char **link, irq_lookup_func func)
-{
- struct acpi_prt_entry *entry = NULL;
- int segment = pci_domain_nr(bus);
- int bus_nr = bus->number;
- int ret;
-
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Searching for PRT entry for %02x:%02x:%02x[%c]\n",
- segment, bus_nr, device, ('A' + pin)));
-
- entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
- if (!entry) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n"));
- return -1;
- }
-
- ret = func(entry, triggering, polarity, link);
-
-#ifdef CONFIG_X86_IO_APIC
- /*
- * Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the
- * IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel
- * does during interrupt handling). When this INTx generation cannot be
- * disabled, we reroute these interrupts to their legacy equivalent to
- * get rid of spurious interrupts.
- */
- if (!noioapicquirk) {
- switch (bridge_has_boot_interrupt_variant(bus)) {
- case 0:
- /* no rerouting necessary */
- break;
-
- case INTEL_IRQ_REROUTE_VARIANT:
- /*
- * Remap according to INTx routing table in 6700PXH
- * specs, intel order number 302628-002, section
- * 2.15.2. Other chipsets (80332, ...) have the same
- * mapping and are handled here as well.
- */
- printk(KERN_INFO "pci irq %d -> rerouted to legacy "
- "irq %d\n", ret, (ret % 4) + 16);
- ret = (ret % 4) + 16;
- break;
-
- default:
- printk(KERN_INFO "not rerouting irq %d to legacy irq: "
- "unknown mapping\n", ret);
- break;
- }
+ struct acpi_prt_entry *entry;
+ struct pci_dev *bridge;
+ u8 bridge_pin, orig_pin = pin;
+
+ entry = acpi_pci_irq_find_prt_entry(dev, pin);
+ if (entry) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
+ pci_name(dev), pin_name(pin)));
+ return entry;
}
-#endif /* CONFIG_X86_IO_APIC */
-
- return ret;
-}
-
-/*
- * acpi_pci_irq_derive
- * success: return IRQ >= 0
- * failure: return < 0
- */
-static int
-acpi_pci_irq_derive(struct pci_dev *dev,
- int pin,
- int *triggering,
- int *polarity, char **link, irq_lookup_func func)
-{
- struct pci_dev *bridge = dev;
- int irq = -1;
- u8 bridge_pin = 0, orig_pin = pin;
-
-
- if (!dev)
- return -EINVAL;
/*
* Attempt to derive an IRQ for this device from a parent bridge's
* PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
*/
- while (irq < 0 && bridge->bus->self) {
- pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
- bridge = bridge->bus->self;
+ bridge = dev->bus->self;
+ while (bridge) {
+ pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
/* PC card has the same IRQ as its cardbridge */
@@ -506,50 +328,40 @@ acpi_pci_irq_derive(struct pci_dev *dev,
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n",
pci_name(bridge)));
- return -1;
+ return NULL;
}
- /* Pin is from 0 to 3 */
- bridge_pin--;
pin = bridge_pin;
}
- irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
- pin, triggering, polarity,
- link, func);
- }
+ entry = acpi_pci_irq_find_prt_entry(bridge, pin);
+ if (entry) {
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Derived GSI for %s INT %c from %s\n",
+ pci_name(dev), pin_name(orig_pin),
+ pci_name(bridge)));
+ return entry;
+ }
- if (irq < 0) {
- dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n",
- 'A' + orig_pin);
- return -1;
+ dev = bridge;
+ bridge = dev->bus->self;
}
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
- irq, pci_name(dev), pci_name(bridge)));
-
- return irq;
+ dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n",
+ pin_name(orig_pin));
+ return NULL;
}
-/*
- * acpi_pci_irq_enable
- * success: return 0
- * failure: return < 0
- */
-
int acpi_pci_irq_enable(struct pci_dev *dev)
{
- int irq = 0;
- u8 pin = 0;
+ struct acpi_prt_entry *entry;
+ int gsi;
+ u8 pin;
int triggering = ACPI_LEVEL_SENSITIVE;
int polarity = ACPI_ACTIVE_LOW;
char *link = NULL;
char link_desc[16];
int rc;
-
- if (!dev)
- return -EINVAL;
-
pin = dev->pin;
if (!pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -557,31 +369,9 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
pci_name(dev)));
return 0;
}
- pin--;
-
- if (!dev->bus) {
- dev_err(&dev->dev, "invalid (NULL) 'bus' field\n");
- return -ENODEV;
- }
-
- /*
- * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
- * values override any BIOS-assigned IRQs set during boot.
- */
- irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &triggering, &polarity, &link,
- acpi_pci_allocate_irq);
-
- /*
- * If no PRT entry was found, we'll try to derive an IRQ from the
- * device's parent bridge.
- */
- if (irq < 0)
- irq = acpi_pci_irq_derive(dev, pin, &triggering,
- &polarity, &link,
- acpi_pci_allocate_irq);
- if (irq < 0) {
+ entry = acpi_pci_irq_lookup(dev, pin);
+ if (!entry) {
/*
* IDE legacy mode controller IRQs are magic. Why do compat
* extensions always make such a nasty mess.
@@ -590,12 +380,24 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
(dev->class & 0x05) == 0)
return 0;
}
+
+ if (entry) {
+ if (entry->link)
+ gsi = acpi_pci_link_allocate_irq(entry->link,
+ entry->index,
+ &triggering, &polarity,
+ &link);
+ else
+ gsi = entry->index;
+ } else
+ gsi = -1;
+
/*
* No IRQ known to the ACPI subsystem - maybe the BIOS /
* driver reported one, then use it. Exit in any case.
*/
- if (irq < 0) {
- dev_warn(&dev->dev, "PCI INT %c: no GSI", 'A' + pin);
+ if (gsi < 0) {
+ dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq > 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq);
@@ -608,10 +410,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
}
}
- rc = acpi_register_gsi(irq, triggering, polarity);
+ rc = acpi_register_gsi(gsi, triggering, polarity);
if (rc < 0) {
dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
- 'A' + pin);
+ pin_name(pin));
return rc;
}
dev->irq = rc;
@@ -622,7 +424,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
link_desc[0] = '\0';
dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
- 'A' + pin, link_desc, irq,
+ pin_name(pin), link_desc, gsi,
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
@@ -636,42 +438,28 @@ void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
void acpi_pci_irq_disable(struct pci_dev *dev)
{
- int gsi = 0;
- u8 pin = 0;
- int triggering = ACPI_LEVEL_SENSITIVE;
- int polarity = ACPI_ACTIVE_LOW;
-
-
- if (!dev || !dev->bus)
- return;
+ struct acpi_prt_entry *entry;
+ int gsi;
+ u8 pin;
pin = dev->pin;
if (!pin)
return;
- pin--;
- /*
- * First we check the PCI IRQ routing table (PRT) for an IRQ.
- */
- gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &triggering, &polarity, NULL,
- acpi_pci_free_irq);
- /*
- * If no PRT entry was found, we'll try to derive an IRQ from the
- * device's parent bridge.
- */
- if (gsi < 0)
- gsi = acpi_pci_irq_derive(dev, pin,
- &triggering, &polarity, NULL,
- acpi_pci_free_irq);
- if (gsi < 0)
+ entry = acpi_pci_irq_lookup(dev, pin);
+ if (!entry)
return;
+ if (entry->link)
+ gsi = acpi_pci_link_free_irq(entry->link);
+ else
+ gsi = entry->index;
+
/*
* TBD: It might be worth clearing dev->irq by magic constant
* (e.g. PCI_UNDEFINED_IRQ).
*/
- dev_info(&dev->dev, "PCI INT %c disabled\n", 'A' + pin);
+ dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
acpi_unregister_gsi(gsi);
}
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index e52ad91ce2dc..1c6e73c7865e 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -796,10 +796,6 @@ static int irqrouter_resume(struct sys_device *dev)
struct list_head *node = NULL;
struct acpi_pci_link *link = NULL;
-
- /* Make sure SCI is enabled again (Apple firmware bug?) */
- acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1);
-
list_for_each(node, &acpi_link.entries) {
link = list_entry(node, struct acpi_pci_link, node);
if (!link) {
@@ -912,7 +908,7 @@ static int __init acpi_irq_nobalance_set(char *str)
__setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
-int __init acpi_irq_balance_set(char *str)
+static int __init acpi_irq_balance_set(char *str)
{
acpi_irq_balance = 1;
return 1;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 642554b1b60c..5b38a026d122 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -31,6 +31,7 @@
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/pci.h>
+#include <linux/pci-acpi.h>
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
@@ -193,6 +194,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
unsigned long long value = 0;
acpi_handle handle = NULL;
struct acpi_device *child;
+ u32 flags, base_flags;
if (!device)
@@ -210,6 +212,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
device->ops.bind = acpi_pci_bind;
+ /*
+ * All supported architectures that use ACPI have support for
+ * PCI domains, so we indicate this in _OSC support capabilities.
+ */
+ flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
+ pci_acpi_osc_support(device->handle, flags);
+
/*
* Segment
* -------
@@ -335,6 +344,17 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
list_for_each_entry(child, &device->children, node)
acpi_pci_bridge_scan(child);
+ /* Indicate support for various _OSC capabilities. */
+ if (pci_ext_cfg_avail(root->bus->self))
+ flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
+ if (pcie_aspm_enabled())
+ flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
+ OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
+ if (pci_msi_enabled())
+ flags |= OSC_MSI_SUPPORT;
+ if (flags != base_flags)
+ pci_acpi_osc_support(device->handle, flags);
+
end:
if (result) {
if (!list_empty(&root->node))
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index bb7d50dd2818..c926e7d4a0d6 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -139,6 +139,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state)
{
acpi_status status = AE_OK;
unsigned long long sta = 0;
+ char node_name[5];
+ struct acpi_buffer buffer = { sizeof(node_name), node_name };
if (!handle || !state)
@@ -151,8 +153,10 @@ static int acpi_power_get_state(acpi_handle handle, int *state)
*state = (sta & 0x01)?ACPI_POWER_RESOURCE_STATE_ON:
ACPI_POWER_RESOURCE_STATE_OFF;
+ acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
+
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n",
- acpi_ut_get_node_name(handle),
+ node_name,
*state ? "on" : "off"));
return 0;
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/proc.c
index 4dbc2271acf5..428c911dba08 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/proc.c
@@ -28,8 +28,6 @@ static int acpi_system_sleep_seq_show(struct seq_file *seq, void *offset)
{
int i;
- ACPI_FUNCTION_TRACE("acpi_system_sleep_seq_show");
-
for (i = 0; i <= ACPI_STATE_S5; i++) {
if (sleep_states[i]) {
seq_printf(seq, "S%d ", i);
@@ -86,49 +84,44 @@ acpi_system_write_sleep(struct file *file,
#ifdef HAVE_ACPI_LEGACY_ALARM
+static u32 cmos_bcd_read(int offset, int rtc_control);
+
static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
{
u32 sec, min, hr;
u32 day, mo, yr, cent = 0;
+ u32 today = 0;
unsigned char rtc_control = 0;
unsigned long flags;
- ACPI_FUNCTION_TRACE("acpi_system_alarm_seq_show");
-
spin_lock_irqsave(&rtc_lock, flags);
- sec = CMOS_READ(RTC_SECONDS_ALARM);
- min = CMOS_READ(RTC_MINUTES_ALARM);
- hr = CMOS_READ(RTC_HOURS_ALARM);
rtc_control = CMOS_READ(RTC_CONTROL);
+ sec = cmos_bcd_read(RTC_SECONDS_ALARM, rtc_control);
+ min = cmos_bcd_read(RTC_MINUTES_ALARM, rtc_control);
+ hr = cmos_bcd_read(RTC_HOURS_ALARM, rtc_control);
/* If we ever get an FACP with proper values... */
- if (acpi_gbl_FADT.day_alarm)
+ if (acpi_gbl_FADT.day_alarm) {
/* ACPI spec: only low 6 its should be cared */
day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F;
- else
- day = CMOS_READ(RTC_DAY_OF_MONTH);
+ if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ day = bcd2bin(day);
+ } else
+ day = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
if (acpi_gbl_FADT.month_alarm)
- mo = CMOS_READ(acpi_gbl_FADT.month_alarm);
- else
- mo = CMOS_READ(RTC_MONTH);
+ mo = cmos_bcd_read(acpi_gbl_FADT.month_alarm, rtc_control);
+ else {
+ mo = cmos_bcd_read(RTC_MONTH, rtc_control);
+ today = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
+ }
if (acpi_gbl_FADT.century)
- cent = CMOS_READ(acpi_gbl_FADT.century);
+ cent = cmos_bcd_read(acpi_gbl_FADT.century, rtc_control);
- yr = CMOS_READ(RTC_YEAR);
+ yr = cmos_bcd_read(RTC_YEAR, rtc_control);
spin_unlock_irqrestore(&rtc_lock, flags);
- if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- sec = bcd2bin(sec);
- min = bcd2bin(min);
- hr = bcd2bin(hr);
- day = bcd2bin(day);
- mo = bcd2bin(mo);
- yr = bcd2bin(yr);
- cent = bcd2bin(cent);
- }
-
/* we're trusting the FADT (see above) */
if (!acpi_gbl_FADT.century)
/* If we're not trusting the FADT, we should at least make it
@@ -153,6 +146,20 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
else
yr += cent * 100;
+ /*
+ * Show correct dates for alarms up to a month into the future.
+ * This solves issues for nearly all situations with the common
+ * 30-day alarm clocks in PC hardware.
+ */
+ if (day < today) {
+ if (mo < 12) {
+ mo += 1;
+ } else {
+ mo = 1;
+ yr += 1;
+ }
+ }
+
seq_printf(seq, "%4.4u-", yr);
(mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
(day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
@@ -227,13 +234,11 @@ acpi_system_write_alarm(struct file *file,
int adjust = 0;
unsigned char rtc_control = 0;
- ACPI_FUNCTION_TRACE("acpi_system_write_alarm");
-
if (count > sizeof(alarm_string) - 1)
- return_VALUE(-EINVAL);
+ return -EINVAL;
if (copy_from_user(alarm_string, buffer, count))
- return_VALUE(-EFAULT);
+ return -EFAULT;
alarm_string[count] = '\0';
@@ -334,7 +339,7 @@ acpi_system_write_alarm(struct file *file,
result = 0;
end:
- return_VALUE(result ? result : count);
+ return result ? result : count;
}
#endif /* HAVE_ACPI_LEGACY_ALARM */
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 34948362f41d..0cc2fd31e376 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -826,6 +826,11 @@ static int acpi_processor_add(struct acpi_device *device)
if (!pr)
return -ENOMEM;
+ if (!alloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
+ kfree(pr);
+ return -ENOMEM;
+ }
+
pr->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
@@ -845,10 +850,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
pr = acpi_driver_data(device);
- if (pr->id >= nr_cpu_ids) {
- kfree(pr);
- return 0;
- }
+ if (pr->id >= nr_cpu_ids)
+ goto free;
if (type == ACPI_BUS_REMOVAL_EJECT) {
if (acpi_processor_handle_eject(pr))
@@ -873,6 +876,9 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
per_cpu(processors, pr->id) = NULL;
per_cpu(processor_device_array, pr->id) = NULL;
+
+free:
+ free_cpumask_var(pr->throttling.shared_cpu_map);
kfree(pr);
return 0;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 38aca048e951..66a9d8145562 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -41,6 +41,7 @@
#include <linux/pm_qos_params.h>
#include <linux/clockchips.h>
#include <linux/cpuidle.h>
+#include <linux/irqflags.h>
/*
* Include the apic definitions for x86 to have the APIC timer related defines
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 0d7b772bef50..846e227592d4 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -588,12 +588,15 @@ int acpi_processor_preregister_performance(
int count, count_target;
int retval = 0;
unsigned int i, j;
- cpumask_t covered_cpus;
+ cpumask_var_t covered_cpus;
struct acpi_processor *pr;
struct acpi_psd_package *pdomain;
struct acpi_processor *match_pr;
struct acpi_psd_package *match_pdomain;
+ if (!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))
+ return -ENOMEM;
+
mutex_lock(&performance_mutex);
retval = 0;
@@ -617,7 +620,7 @@ int acpi_processor_preregister_performance(
}
pr->performance = percpu_ptr(performance, i);
- cpu_set(i, pr->performance->shared_cpu_map);
+ cpumask_set_cpu(i, pr->performance->shared_cpu_map);
if (acpi_processor_get_psd(pr)) {
retval = -EINVAL;
continue;
@@ -650,18 +653,18 @@ int acpi_processor_preregister_performance(
}
}
- cpus_clear(covered_cpus);
+ cpumask_clear(covered_cpus);
for_each_possible_cpu(i) {
pr = per_cpu(processors, i);
if (!pr)
continue;
- if (cpu_isset(i, covered_cpus))
+ if (cpumask_test_cpu(i, covered_cpus))
continue;
pdomain = &(pr->performance->domain_info);
- cpu_set(i, pr->performance->shared_cpu_map);
- cpu_set(i, covered_cpus);
+ cpumask_set_cpu(i, pr->performance->shared_cpu_map);
+ cpumask_set_cpu(i, covered_cpus);
if (pdomain->num_processors <= 1)
continue;
@@ -699,8 +702,8 @@ int acpi_processor_preregister_performance(
goto err_ret;
}
- cpu_set(j, covered_cpus);
- cpu_set(j, pr->performance->shared_cpu_map);
+ cpumask_set_cpu(j, covered_cpus);
+ cpumask_set_cpu(j, pr->performance->shared_cpu_map);
count++;
}
@@ -718,8 +721,8 @@ int acpi_processor_preregister_performance(
match_pr->performance->shared_type =
pr->performance->shared_type;
- match_pr->performance->shared_cpu_map =
- pr->performance->shared_cpu_map;
+ cpumask_copy(match_pr->performance->shared_cpu_map,
+ pr->performance->shared_cpu_map);
}
}
@@ -731,14 +734,15 @@ err_ret:
/* Assume no coordination on any error parsing domain info */
if (retval) {
- cpus_clear(pr->performance->shared_cpu_map);
- cpu_set(i, pr->performance->shared_cpu_map);
+ cpumask_clear(pr->performance->shared_cpu_map);
+ cpumask_set_cpu(i, pr->performance->shared_cpu_map);
pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
}
pr->performance = NULL; /* Will be set for real in register */
}
mutex_unlock(&performance_mutex);
+ free_cpumask_var(covered_cpus);
return retval;
}
EXPORT_SYMBOL(acpi_processor_preregister_performance);
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index a0c38c94a8a0..d27838171f4a 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -61,11 +61,14 @@ static int acpi_processor_update_tsd_coord(void)
int count, count_target;
int retval = 0;
unsigned int i, j;
- cpumask_t covered_cpus;
+ cpumask_var_t covered_cpus;
struct acpi_processor *pr, *match_pr;
struct acpi_tsd_package *pdomain, *match_pdomain;
struct acpi_processor_throttling *pthrottling, *match_pthrottling;
+ if (!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))
+ return -ENOMEM;
+
/*
* Now that we have _TSD data from all CPUs, lets setup T-state
* coordination between all CPUs.
@@ -91,19 +94,19 @@ static int acpi_processor_update_tsd_coord(void)
if (retval)
goto err_ret;
- cpus_clear(covered_cpus);
+ cpumask_clear(covered_cpus);
for_each_possible_cpu(i) {
pr = per_cpu(processors, i);
if (!pr)
continue;
- if (cpu_isset(i, covered_cpus))
+ if (cpumask_test_cpu(i, covered_cpus))
continue;
pthrottling = &pr->throttling;
pdomain = &(pthrottling->domain_info);
- cpu_set(i, pthrottling->shared_cpu_map);
- cpu_set(i, covered_cpus);
+ cpumask_set_cpu(i, pthrottling->shared_cpu_map);
+ cpumask_set_cpu(i, covered_cpus);
/*
* If the number of processor in the TSD domain is 1, it is
* unnecessary to parse the coordination for this CPU.
@@ -144,8 +147,8 @@ static int acpi_processor_update_tsd_coord(void)
goto err_ret;
}
- cpu_set(j, covered_cpus);
- cpu_set(j, pthrottling->shared_cpu_map);
+ cpumask_set_cpu(j, covered_cpus);
+ cpumask_set_cpu(j, pthrottling->shared_cpu_map);
count++;
}
for_each_possible_cpu(j) {
@@ -165,12 +168,14 @@ static int acpi_processor_update_tsd_coord(void)
* If some CPUS have the same domain, they
* will have the same shared_cpu_map.
*/
- match_pthrottling->shared_cpu_map =
- pthrottling->shared_cpu_map;
+ cpumask_copy(match_pthrottling->shared_cpu_map,
+ pthrottling->shared_cpu_map);
}
}
err_ret:
+ free_cpumask_var(covered_cpus);
+
for_each_possible_cpu(i) {
pr = per_cpu(processors, i);
if (!pr)
@@ -182,8 +187,8 @@ err_ret:
*/
if (retval) {
pthrottling = &(pr->throttling);
- cpus_clear(pthrottling->shared_cpu_map);
- cpu_set(i, pthrottling->shared_cpu_map);
+ cpumask_clear(pthrottling->shared_cpu_map);
+ cpumask_set_cpu(i, pthrottling->shared_cpu_map);
pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
}
}
@@ -567,7 +572,7 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr)
pthrottling = &pr->throttling;
pthrottling->tsd_valid_flag = 1;
pthrottling->shared_type = pdomain->coord_type;
- cpu_set(pr->id, pthrottling->shared_cpu_map);
+ cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map);
/*
* If the coordination type is not defined in ACPI spec,
* the tsd_valid_flag will be clear and coordination type
@@ -826,7 +831,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
static int acpi_processor_get_throttling(struct acpi_processor *pr)
{
- cpumask_t saved_mask;
+ cpumask_var_t saved_mask;
int ret;
if (!pr)
@@ -834,14 +839,20 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
if (!pr->flags.throttling)
return -ENODEV;
+
+ if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
+ return -ENOMEM;
+
/*
* Migrate task to the cpu pointed by pr.
*/
- saved_mask = current->cpus_allowed;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ cpumask_copy(saved_mask, &current->cpus_allowed);
+ /* FIXME: use work_on_cpu() */
+ set_cpus_allowed_ptr(current, cpumask_of(pr->id));
ret = pr->throttling.acpi_processor_get_throttling(pr);
/* restore the previous state */
- set_cpus_allowed_ptr(current, &saved_mask);
+ set_cpus_allowed_ptr(current, saved_mask);
+ free_cpumask_var(saved_mask);
return ret;
}
@@ -986,13 +997,13 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
{
- cpumask_t saved_mask;
+ cpumask_var_t saved_mask;
int ret = 0;
unsigned int i;
struct acpi_processor *match_pr;
struct acpi_processor_throttling *p_throttling;
struct throttling_tstate t_state;
- cpumask_t online_throttling_cpus;
+ cpumask_var_t online_throttling_cpus;
if (!pr)
return -EINVAL;
@@ -1003,17 +1014,25 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
if ((state < 0) || (state > (pr->throttling.state_count - 1)))
return -EINVAL;
- saved_mask = current->cpus_allowed;
+ if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
+ return -ENOMEM;
+
+ if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
+ free_cpumask_var(saved_mask);
+ return -ENOMEM;
+ }
+
+ cpumask_copy(saved_mask, &current->cpus_allowed);
t_state.target_state = state;
p_throttling = &(pr->throttling);
- cpus_and(online_throttling_cpus, cpu_online_map,
- p_throttling->shared_cpu_map);
+ cpumask_and(online_throttling_cpus, cpu_online_mask,
+ p_throttling->shared_cpu_map);
/*
* The throttling notifier will be called for every
* affected cpu in order to get one proper T-state.
* The notifier event is THROTTLING_PRECHANGE.
*/
- for_each_cpu_mask_nr(i, online_throttling_cpus) {
+ for_each_cpu(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
&t_state);
@@ -1025,7 +1044,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it can be called only for the cpu pointed by pr.
*/
if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(pr->id));
+ /* FIXME: use work_on_cpu() */
+ set_cpus_allowed_ptr(current, cpumask_of(pr->id));
ret = p_throttling->acpi_processor_set_throttling(pr,
t_state.target_state);
} else {
@@ -1034,7 +1054,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* it is necessary to set T-state for every affected
* cpus.
*/
- for_each_cpu_mask_nr(i, online_throttling_cpus) {
+ for_each_cpu(i, online_throttling_cpus) {
match_pr = per_cpu(processors, i);
/*
* If the pointer is invalid, we will report the
@@ -1056,7 +1076,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
continue;
}
t_state.cpu = i;
- set_cpus_allowed_ptr(current, &cpumask_of_cpu(i));
+ /* FIXME: use work_on_cpu() */
+ set_cpus_allowed_ptr(current, cpumask_of(i));
ret = match_pr->throttling.
acpi_processor_set_throttling(
match_pr, t_state.target_state);
@@ -1068,13 +1089,16 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
* affected cpu to update the T-states.
* The notifier event is THROTTLING_POSTCHANGE
*/
- for_each_cpu_mask_nr(i, online_throttling_cpus) {
+ for_each_cpu(i, online_throttling_cpus) {
t_state.cpu = i;
acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
&t_state);
}
/* restore the previous state */
- set_cpus_allowed_ptr(current, &saved_mask);
+ /* FIXME: use work_on_cpu() */
+ set_cpus_allowed_ptr(current, saved_mask);
+ free_cpumask_var(online_throttling_cpus);
+ free_cpumask_var(saved_mask);
return ret;
}
@@ -1120,7 +1144,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
if (acpi_processor_get_tsd(pr)) {
pthrottling = &pr->throttling;
pthrottling->tsd_valid_flag = 0;
- cpu_set(pr->id, pthrottling->shared_cpu_map);
+ cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map);
pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
}
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index a6b662c00b67..93f91142d7ad 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -42,7 +42,7 @@ void acpi_reboot(void)
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
case ACPI_ADR_SPACE_SYSTEM_IO:
printk(KERN_DEBUG "ACPI MEMORY or I/O RESET_REG.\n");
- acpi_hw_low_level_write(8, reset_value, rr);
+ acpi_reset();
break;
}
/* Wait ten seconds */
diff --git a/drivers/acpi/resources/Makefile b/drivers/acpi/resources/Makefile
deleted file mode 100644
index 8de4f69dfa09..000000000000
--- a/drivers/acpi/resources/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := rsaddr.o rscreate.o rsinfo.o rsio.o rslist.o rsmisc.o rsxface.o \
- rscalc.o rsirq.o rsmemory.o rsutils.o
-
-obj-$(ACPI_FUTURE_USAGE) += rsdump.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index e53e590252c0..0619734895b2 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -10,7 +10,6 @@
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#include <acpi/actypes.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 39b7233c3485..c54d7b6c4066 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -10,7 +10,6 @@
#include <linux/kthread.h>
#include <acpi/acpi_drivers.h>
-#include <acpi/acinterp.h> /* for acpi_ex_eisa_id_to_string() */
#define _COMPONENT ACPI_BUS_COMPONENT
ACPI_MODULE_NAME("scan");
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep.c
index 28a691cc625e..7e3c609cbef2 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep.c
@@ -101,13 +101,26 @@ void __init acpi_old_suspend_ordering(void)
* cases.
*/
static bool set_sci_en_on_resume;
+/*
+ * The ACPI specification wants us to save NVS memory regions during hibernation
+ * and to restore them during the subsequent resume. However, it is not certain
+ * if this mechanism is going to work on all machines, so we allow the user to
+ * disable this mechanism using the 'acpi_sleep=s4_nonvs' kernel command line
+ * option.
+ */
+static bool s4_no_nvs;
+
+void __init acpi_s4_no_nvs(void)
+{
+ s4_no_nvs = true;
+}
/**
* acpi_pm_disable_gpes - Disable the GPEs.
*/
static int acpi_pm_disable_gpes(void)
{
- acpi_hw_disable_all_gpes();
+ acpi_disable_all_gpes();
return 0;
}
@@ -135,7 +148,7 @@ static int acpi_pm_prepare(void)
int error = __acpi_pm_prepare();
if (!error)
- acpi_hw_disable_all_gpes();
+ acpi_disable_all_gpes();
return error;
}
@@ -267,7 +280,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
* (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
* acpi_leave_sleep_state will reenable specific GPEs later
*/
- acpi_hw_disable_all_gpes();
+ acpi_disable_all_gpes();
local_irq_restore(flags);
printk(KERN_DEBUG "Back to C!\n");
@@ -394,9 +407,25 @@ void __init acpi_no_s4_hw_signature(void)
static int acpi_hibernation_begin(void)
{
- acpi_target_sleep_state = ACPI_STATE_S4;
- acpi_sleep_tts_switch(acpi_target_sleep_state);
- return 0;
+ int error;
+
+ error = s4_no_nvs ? 0 : hibernate_nvs_alloc();
+ if (!error) {
+ acpi_target_sleep_state = ACPI_STATE_S4;
+ acpi_sleep_tts_switch(acpi_target_sleep_state);
+ }
+
+ return error;
+}
+
+static int acpi_hibernation_pre_snapshot(void)
+{
+ int error = acpi_pm_prepare();
+
+ if (!error)
+ hibernate_nvs_save();
+
+ return error;
}
static int acpi_hibernation_enter(void)
@@ -417,6 +446,12 @@ static int acpi_hibernation_enter(void)
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
+static void acpi_hibernation_finish(void)
+{
+ hibernate_nvs_free();
+ acpi_pm_finish();
+}
+
static void acpi_hibernation_leave(void)
{
/*
@@ -432,18 +467,20 @@ static void acpi_hibernation_leave(void)
"cannot resume!\n");
panic("ACPI S4 hardware signature mismatch");
}
+ /* Restore the NVS memory area */
+ hibernate_nvs_restore();
}
static void acpi_pm_enable_gpes(void)
{
- acpi_hw_enable_all_runtime_gpes();
+ acpi_enable_all_runtime_gpes();
}
static struct platform_hibernation_ops acpi_hibernation_ops = {
.begin = acpi_hibernation_begin,
.end = acpi_pm_end,
- .pre_snapshot = acpi_pm_prepare,
- .finish = acpi_pm_finish,
+ .pre_snapshot = acpi_hibernation_pre_snapshot,
+ .finish = acpi_hibernation_finish,
.prepare = acpi_pm_prepare,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
@@ -469,8 +506,22 @@ static int acpi_hibernation_begin_old(void)
error = acpi_sleep_prepare(ACPI_STATE_S4);
+ if (!error) {
+ if (!s4_no_nvs)
+ error = hibernate_nvs_alloc();
+ if (!error)
+ acpi_target_sleep_state = ACPI_STATE_S4;
+ }
+ return error;
+}
+
+static int acpi_hibernation_pre_snapshot_old(void)
+{
+ int error = acpi_pm_disable_gpes();
+
if (!error)
- acpi_target_sleep_state = ACPI_STATE_S4;
+ hibernate_nvs_save();
+
return error;
}
@@ -481,8 +532,8 @@ static int acpi_hibernation_begin_old(void)
static struct platform_hibernation_ops acpi_hibernation_ops_old = {
.begin = acpi_hibernation_begin_old,
.end = acpi_pm_end,
- .pre_snapshot = acpi_pm_disable_gpes,
- .finish = acpi_pm_finish,
+ .pre_snapshot = acpi_hibernation_pre_snapshot_old,
+ .finish = acpi_hibernation_finish,
.prepare = acpi_pm_disable_gpes,
.enter = acpi_hibernation_enter,
.leave = acpi_hibernation_leave,
@@ -622,7 +673,7 @@ static void acpi_power_off_prepare(void)
{
/* Prepare to power off the system */
acpi_sleep_prepare(ACPI_STATE_S5);
- acpi_hw_disable_all_gpes();
+ acpi_disable_all_gpes();
}
static void acpi_power_off(void)
@@ -671,7 +722,7 @@ int __init acpi_sleep_init(void)
sleep_states[ACPI_STATE_S4] = 1;
printk(" S4");
if (!nosigcheck) {
- acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
+ acpi_get_table(ACPI_SIG_FACS, 1,
(struct acpi_table_header **)&facs);
if (facs)
s4_hardware_signature =
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep.h
index cfaf8f5b0a14..cfaf8f5b0a14 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep.h
diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile
deleted file mode 100644
index f1fb888c2d29..000000000000
--- a/drivers/acpi/sleep/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-obj-y := wakeup.o
-obj-y += main.o
-obj-$(CONFIG_ACPI_SLEEP) += proc.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index 6e4107f82403..391d0358a592 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -192,65 +192,6 @@ static struct attribute_group interrupt_stats_attr_group = {
};
static struct kobj_attribute *counter_attrs;
-static int count_num_gpes(void)
-{
- int count = 0;
- struct acpi_gpe_xrupt_info *gpe_xrupt_info;
- struct acpi_gpe_block_info *gpe_block;
- acpi_cpu_flags flags;
-
- flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
- gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
- while (gpe_xrupt_info) {
- gpe_block = gpe_xrupt_info->gpe_block_list_head;
- while (gpe_block) {
- count += gpe_block->register_count *
- ACPI_GPE_REGISTER_WIDTH;
- gpe_block = gpe_block->next;
- }
- gpe_xrupt_info = gpe_xrupt_info->next;
- }
- acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-
- return count;
-}
-
-static int get_gpe_device(int index, acpi_handle *handle)
-{
- struct acpi_gpe_xrupt_info *gpe_xrupt_info;
- struct acpi_gpe_block_info *gpe_block;
- acpi_cpu_flags flags;
- struct acpi_namespace_node *node;
-
- flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
-
- gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
- while (gpe_xrupt_info) {
- gpe_block = gpe_xrupt_info->gpe_block_list_head;
- node = gpe_block->node;
- while (gpe_block) {
- index -= gpe_block->register_count *
- ACPI_GPE_REGISTER_WIDTH;
- if (index < 0) {
- acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
- /* return NULL if it's FADT GPE */
- if (node->type != ACPI_TYPE_DEVICE)
- *handle = NULL;
- else
- *handle = node;
- return 0;
- }
- node = gpe_block->node;
- gpe_block = gpe_block->next;
- }
- gpe_xrupt_info = gpe_xrupt_info->next;
- }
- acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
-
- return -ENODEV;
-}
-
static void delete_gpe_attr_array(void)
{
struct event_counter *tmp = all_counters;
@@ -309,7 +250,7 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle)
goto end;
if (index < num_gpes) {
- result = get_gpe_device(index, handle);
+ result = acpi_get_gpe_device(index, handle);
if (result) {
ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND,
"Invalid GPE 0x%x\n", index));
@@ -436,7 +377,7 @@ void acpi_irq_stats_init(void)
if (all_counters)
return;
- num_gpes = count_num_gpes();
+ num_gpes = acpi_current_gpe_count;
num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA;
all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1),
diff --git a/drivers/acpi/tables/Makefile b/drivers/acpi/tables/Makefile
deleted file mode 100644
index 7385efa61622..000000000000
--- a/drivers/acpi/tables/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 073ff09218a9..99e6f1f8ea45 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -416,7 +416,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
}
/* Passive (optional) */
- if (flag & ACPI_TRIPS_PASSIVE) {
+ if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
+ (flag == ACPI_TRIPS_INIT)) {
valid = tz->trips.passive.flags.valid;
if (psv == -1) {
status = AE_SUPPORT;
@@ -462,8 +463,11 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
memset(&devices, 0, sizeof(struct acpi_handle_list));
status = acpi_evaluate_reference(tz->device->handle, "_PSL",
NULL, &devices);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_WARNING PREFIX
+ "Invalid passive threshold\n");
tz->trips.passive.flags.valid = 0;
+ }
else
tz->trips.passive.flags.valid = 1;
@@ -487,7 +491,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
if (act == -1)
break; /* disable all active trip points */
- if (flag & ACPI_TRIPS_ACTIVE) {
+ if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
+ tz->trips.active[i].flags.valid)) {
status = acpi_evaluate_integer(tz->device->handle,
name, NULL, &tmp);
if (ACPI_FAILURE(status)) {
@@ -521,8 +526,11 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
memset(&devices, 0, sizeof(struct acpi_handle_list));
status = acpi_evaluate_reference(tz->device->handle,
name, NULL, &devices);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_WARNING PREFIX
+ "Invalid active%d threshold\n", i);
tz->trips.active[i].flags.valid = 0;
+ }
else
tz->trips.active[i].flags.valid = 1;
diff --git a/drivers/acpi/utilities/Makefile b/drivers/acpi/utilities/Makefile
deleted file mode 100644
index 88eff14c4894..000000000000
--- a/drivers/acpi/utilities/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-obj-y := utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
- utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
- utstate.o utmutex.o utobject.o utcache.o utresrc.o
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
deleted file mode 100644
index 245fa80cf600..000000000000
--- a/drivers/acpi/utilities/utcache.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/******************************************************************************
- *
- * Module Name: utcache - local cache allocation routines
- *
- *****************************************************************************/
-
-/*
- * Copyright (C) 2000 - 2008, Intel Corp.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, and the following disclaimer,
- * without modification.
- * 2. Redistributions in binary form must reproduce at minimum a disclaimer
- * substantially similar to the "NO WARRANTY" disclaimer below
- * ("Disclaimer") and any redistribution must be conditioned upon
- * including a substantially similar Disclaimer requirement for further
- * binary redistribution.
- * 3. Neither the names of the above-listed copyright holders nor the names
- * of any contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * NO WARRANTY
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGES.
- */
-
-#include <acpi/acpi.h>
-
-#define _COMPONENT ACPI_UTILITIES
-ACPI_MODULE_NAME("utcache")
-#ifdef ACPI_USE_LOCAL_CACHE
-/*******************************************************************************
- *
- * FUNCTION: acpi_os_create_cache
- *
- * PARAMETERS: cache_name - Ascii name for the cache
- * object_size - Size of each cached object
- * max_depth - Maximum depth of the cache (in objects)
- * return_cache - Where the new cache object is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Create a cache object
- *
- ******************************************************************************/
-acpi_status
-acpi_os_create_cache(char *cache_name,
- u16 object_size,
- u16 max_depth, struct acpi_memory_list ** return_cache)
-{
- struct acpi_memory_list *cache;
-
- ACPI_FUNCTION_ENTRY();
-
- if (!cache_name || !return_cache || (object_size < 16)) {
- return (AE_BAD_PARAMETER);
- }
-
- /* Create the cache object */
-
- cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
- if (!cache) {
- return (AE_NO_MEMORY);
- }
-
- /* Populate the cache object and return it */
-
- ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
- cache->link_offset = 8;
- cache->list_name = cache_name;
- cache->object_size = object_size;
- cache->max_depth = max_depth;
-
- *return_cache = cache;
- return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_os_purge_cache
- *
- * PARAMETERS: Cache - Handle to cache object
- *
- * RETURN: Status
- *
- * DESCRIPTION: Free all objects within the requested cache.
- *
- ******************************************************************************/
-
-acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
-{
- char *next;
-
- ACPI_FUNCTION_ENTRY();
-
- if (!cache) {
- return (AE_BAD_PARAMETER);
- }
-
- /* Walk the list of objects in this cache */
-
- while (cache->list_head) {
-
- /* Delete and unlink one cached state object */
-
- next = *(ACPI_CAST_INDIRECT_PTR(char,
- &(((char *)cache->
- list_head)[cache->
- link_offset])));
- ACPI_FREE(cache->list_head);
-
- cache->list_head = next;
- cache->current_depth--;
- }
-
- return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_os_delete_cache
- *
- * PARAMETERS: Cache - Handle to cache object
- *
- * RETURN: Status
- *
- * DESCRIPTION: Free all objects within the requested cache and delete the
- * cache object.
- *
- ******************************************************************************/
-
-acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
-{
- acpi_status status;
-
- ACPI_FUNCTION_ENTRY();
-
- /* Purge all objects in the cache */
-
- status = acpi_os_purge_cache(cache);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
-
- /* Now we can delete the cache object */
-
- ACPI_FREE(cache);
- return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_os_release_object
- *
- * PARAMETERS: Cache - Handle to cache object
- * Object - The object to be released
- *
- * RETURN: None
- *
- * DESCRIPTION: Release an object to the specified cache. If cache is full,
- * the object is deleted.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_os_release_object(struct acpi_memory_list * cache, void *object)
-{
- acpi_status status;
-
- ACPI_FUNCTION_ENTRY();
-
- if (!cache || !object) {
- return (AE_BAD_PARAMETER);
- }
-
- /* If cache is full, just free this object */
-
- if (cache->current_depth >= cache->max_depth) {
- ACPI_FREE(object);
- ACPI_MEM_TRACKING(cache->total_freed++);
- }
-
- /* Otherwise put this object back into the cache */
-
- else {
- status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
-
- /* Mark the object as cached */
-
- ACPI_MEMSET(object, 0xCA, cache->object_size);
- ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
-
- /* Put the object at the head of the cache list */
-
- *(ACPI_CAST_INDIRECT_PTR(char,
- &(((char *)object)[cache->
- link_offset]))) =
- cache->list_head;
- cache->list_head = object;
- cache->current_depth++;
-
- (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
- }
-
- return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_os_acquire_object
- *
- * PARAMETERS: Cache - Handle to cache object
- *
- * RETURN: the acquired object. NULL on error
- *
- * DESCRIPTION: Get an object from the specified cache. If cache is empty,
- * the object is allocated.
- *
- ******************************************************************************/
-
-void *acpi_os_acquire_object(struct acpi_memory_list *cache)
-{
- acpi_status status;
- void *object;
-
- ACPI_FUNCTION_NAME(os_acquire_object);
-
- if (!cache) {
- return (NULL);
- }
-
- status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
- if (ACPI_FAILURE(status)) {
- return (NULL);
- }
-
- ACPI_MEM_TRACKING(cache->requests++);
-
- /* Check the cache first */
-
- if (cache->list_head) {
-
- /* There is an object available, use it */
-
- object = cache->list_head;
- cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
- &(((char *)
- object)[cache->
- link_offset])));
-
- cache->current_depth--;
-
- ACPI_MEM_TRACKING(cache->hits++);
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Object %p from %s cache\n", object,
- cache->list_name));
-
- status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
- if (ACPI_FAILURE(status)) {
- return (NULL);
- }
-
- /* Clear (zero) the previously used Object */
-
- ACPI_MEMSET(object, 0, cache->object_size);
- } else {
- /* The cache is empty, create a new object */
-
- ACPI_MEM_TRACKING(cache->total_allocated++);
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
- if ((cache->total_allocated - cache->total_freed) >
- cache->max_occupied) {
- cache->max_occupied =
- cache->total_allocated - cache->total_freed;
- }
-#endif
-
- /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
-
- status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
- if (ACPI_FAILURE(status)) {
- return (NULL);
- }
-
- object = ACPI_ALLOCATE_ZEROED(cache->object_size);
- if (!object) {
- return (NULL);
- }
- }
-
- return (object);
-}
-#endif /* ACPI_USE_LOCAL_CACHE */
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index baa441929720..f261737636da 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -36,6 +36,7 @@
#include <linux/backlight.h>
#include <linux/thermal.h>
#include <linux/video_output.h>
+#include <linux/sort.h>
#include <asm/uaccess.h>
#include <acpi/acpi_bus.h>
@@ -481,6 +482,7 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
int status = AE_OK;
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list args = { 1, &arg0 };
+ int state;
arg0.integer.value = level;
@@ -489,6 +491,10 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level)
status = acpi_evaluate_object(device->dev->handle, "_BCM",
&args, NULL);
device->brightness->curr = level;
+ for (state = 2; state < device->brightness->count; state++)
+ if (level == device->brightness->levels[state])
+ device->backlight->props.brightness = state - 2;
+
return status;
}
@@ -626,6 +632,16 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag)
}
/*
+ * Simple comparison function used to sort backlight levels.
+ */
+
+static int
+acpi_video_cmp_level(const void *a, const void *b)
+{
+ return *(int *)a - *(int *)b;
+}
+
+/*
* Arg:
* device : video output device (LCD, CRT, ..)
*
@@ -676,6 +692,10 @@ acpi_video_init_brightness(struct acpi_video_device *device)
count++;
}
+ /* don't sort the first two brightness levels */
+ sort(&br->levels[2], count - 2, sizeof(br->levels[2]),
+ acpi_video_cmp_level, NULL);
+
if (count < 2)
goto out_free_levels;
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index f022eb6f5637..50e3d2dbf3af 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -234,7 +234,7 @@ EXPORT_SYMBOL(acpi_video_display_switch_support);
* To force that backlight or display output switching is processed by vendor
* specific acpi drivers or video.ko driver.
*/
-int __init acpi_backlight(char *str)
+static int __init acpi_backlight(char *str)
{
if (str == NULL || *str == '\0')
return 1;
@@ -250,7 +250,7 @@ int __init acpi_backlight(char *str)
}
__setup("acpi_backlight=", acpi_backlight);
-int __init acpi_display_output(char *str)
+static int __init acpi_display_output(char *str)
{
if (str == NULL || *str == '\0')
return 1;
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/wakeup.c
index dea4c23df764..2d34806d45dd 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/wakeup.c
@@ -8,7 +8,6 @@
#include <acpi/acpi_drivers.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <acpi/acevents.h>
#include "sleep.h"
#define _COMPONENT ACPI_SYSTEM_COMPONENT
@@ -28,8 +27,6 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state)
{
struct list_head *node, *next;
- ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
-
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev = container_of(node,
@@ -61,7 +58,6 @@ void acpi_enable_wakeup_device(u8 sleep_state)
* Caution: this routine must be invoked when interrupt is disabled
* Refer ACPI2.0: P212
*/
- ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev =
@@ -103,8 +99,6 @@ void acpi_disable_wakeup_device(u8 sleep_state)
{
struct list_head *node, *next;
- ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
-
spin_lock(&acpi_device_lock);
list_for_each_safe(node, next, &acpi_wakeup_device_list) {
struct acpi_device *dev =
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 6b94fb7be5f2..00c46e0b40e4 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -12,9 +12,10 @@
#include <linux/device.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/io.h>
#include <linux/amba/bus.h>
-#include <asm/io.h>
+#include <asm/irq.h>
#include <asm/sizes.h>
#define to_amba_device(d) container_of(d, struct amba_device, dev)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 1a7be96d627b..0bcf26464670 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -112,11 +112,11 @@ config ATA_PIIX
If unsure, say N.
config SATA_MV
- tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ tristate "Marvell SATA support"
help
This option enables support for the Marvell Serial ATA family.
- Currently supports 88SX[56]0[48][01] chips.
+ Currently supports 88SX[56]0[48][01] PCI(-X) chips,
+ as well as the newer [67]042 PCI-X/PCIe and SOC devices.
If unsure, say N.
@@ -698,6 +698,15 @@ config PATA_IXP4XX_CF
If unsure, say N.
+config PATA_OCTEON_CF
+ tristate "OCTEON Boot Bus Compact Flash support"
+ depends on CPU_CAVIUM_OCTEON
+ help
+ This option enables a polled compact flash driver for use with
+ compact flash cards attached to the OCTEON boot bus.
+
+ If unsure, say N.
+
config PATA_SCC
tristate "Toshiba's Cell Reference Set IDE support"
depends on PCI && PPC_CELLEB
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 674965fa326d..7f1ecf99528c 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_SCH) += pata_sch.o
obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
+obj-$(CONFIG_PATA_OCTEON_CF) += pata_octeon_cf.o
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 656448c7fef9..a603bbf9b1b7 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -61,9 +61,14 @@
#define EM_MSG_LED_VALUE_ON 0x00010000
static int ahci_skip_host_reset;
+static int ahci_ignore_sss;
+
module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
+module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
+MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
+
static int ahci_enable_alpm(struct ata_port *ap,
enum link_pm policy);
static void ahci_disable_alpm(struct ata_port *ap);
@@ -105,7 +110,7 @@ enum {
board_ahci_ign_iferr = 2,
board_ahci_sb600 = 3,
board_ahci_mv = 4,
- board_ahci_sb700 = 5,
+ board_ahci_sb700 = 5, /* for SB700 and SB800 */
board_ahci_mcp65 = 6,
board_ahci_nopmp = 7,
@@ -439,7 +444,7 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
- /* board_ahci_sb700 */
+ /* board_ahci_sb700, for SB700 and SB800 */
{
AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL),
.flags = AHCI_FLAG_COMMON,
@@ -2446,6 +2451,8 @@ static void ahci_print_info(struct ata_host *host)
speed_s = "1.5";
else if (speed == 2)
speed_s = "3";
+ else if (speed == 3)
+ speed_s = "6";
else
speed_s = "?";
@@ -2546,6 +2553,32 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
}
}
+static bool ahci_broken_system_poweroff(struct pci_dev *pdev)
+{
+ static const struct dmi_system_id broken_systems[] = {
+ {
+ .ident = "HP Compaq nx6310",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6310"),
+ },
+ /* PCI slot number of the controller */
+ .driver_data = (void *)0x1FUL,
+ },
+
+ { } /* terminate list */
+ };
+ const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+ if (dmi) {
+ unsigned long slot = (unsigned long)dmi->driver_data;
+ /* apply the quirk only to on-board controllers */
+ return slot == PCI_SLOT(pdev->devfn);
+ }
+
+ return false;
+}
+
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
@@ -2610,6 +2643,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
(pdev->revision == 0xa1 || pdev->revision == 0xa2))
hpriv->flags |= AHCI_HFLAG_NO_MSI;
+ /* SB800 does NOT need the workaround to ignore SERR_INTERNAL */
+ if (board_id == board_ahci_sb700 && pdev->revision >= 0x40)
+ hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL;
+
if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1);
@@ -2641,6 +2678,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
+ if (ahci_broken_system_poweroff(pdev)) {
+ pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN;
+ dev_info(&pdev->dev,
+ "quirky BIOS, skipping spindown on poweroff\n");
+ }
+
/* CAP.NP sometimes indicate the index of the last enabled
* port, at other times, that of the last possible port, so
* determining the maximum port number requires looking at
@@ -2654,6 +2697,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->iomap = pcim_iomap_table(pdev);
host->private_data = hpriv;
+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
+ host->flags |= ATA_HOST_PARALLEL_SCAN;
+ else
+ printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
+
if (pi.flags & ATA_FLAG_EM)
ahci_reset_em(host);
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 5fdf1678d0cc..54961c0b2c73 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -154,11 +154,13 @@ struct piix_map_db {
struct piix_host_priv {
const int *map;
+ u32 saved_iocfg;
void __iomem *sidpr;
};
static int piix_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent);
+static void piix_remove_one(struct pci_dev *pdev);
static int piix_pata_prereset(struct ata_link *link, unsigned long deadline);
static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
@@ -296,7 +298,7 @@ static struct pci_driver piix_pci_driver = {
.name = DRV_NAME,
.id_table = piix_pci_tbl,
.probe = piix_init_one,
- .remove = ata_pci_remove_one,
+ .remove = piix_remove_one,
#ifdef CONFIG_PM
.suspend = piix_pci_device_suspend,
.resume = piix_pci_device_resume,
@@ -308,7 +310,7 @@ static struct scsi_host_template piix_sht = {
};
static struct ata_port_operations piix_pata_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &ata_bmdma32_port_ops,
.cable_detect = ata_cable_40wire,
.set_piomode = piix_set_piomode,
.set_dmamode = piix_set_dmamode,
@@ -610,8 +612,9 @@ static const struct ich_laptop ich_laptop[] = {
static int ich_pata_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ struct piix_host_priv *hpriv = ap->host->private_data;
const struct ich_laptop *lap = &ich_laptop[0];
- u8 tmp, mask;
+ u8 mask;
/* Check for specials - Acer Aspire 5602WLMi */
while (lap->device) {
@@ -625,8 +628,7 @@ static int ich_pata_cable_detect(struct ata_port *ap)
/* check BIOS cable detect results */
mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
- pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
- if ((tmp & mask) == 0)
+ if ((hpriv->saved_iocfg & mask) == 0)
return ATA_CBL_PATA40;
return ATA_CBL_PATA80;
}
@@ -1350,7 +1352,7 @@ static int __devinit piix_init_sidpr(struct ata_host *host)
return 0;
}
-static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
+static void piix_iocfg_bit18_quirk(struct ata_host *host)
{
static const struct dmi_system_id sysids[] = {
{
@@ -1367,7 +1369,8 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
{ } /* terminate list */
};
- u32 iocfg;
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+ struct piix_host_priv *hpriv = host->private_data;
if (!dmi_check_system(sysids))
return;
@@ -1376,13 +1379,38 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
* seem to use it to disable a channel. Clear the bit on the
* affected systems.
*/
- pci_read_config_dword(pdev, PIIX_IOCFG, &iocfg);
- if (iocfg & (1 << 18)) {
+ if (hpriv->saved_iocfg & (1 << 18)) {
dev_printk(KERN_INFO, &pdev->dev,
"applying IOCFG bit18 quirk\n");
- iocfg &= ~(1 << 18);
- pci_write_config_dword(pdev, PIIX_IOCFG, iocfg);
+ pci_write_config_dword(pdev, PIIX_IOCFG,
+ hpriv->saved_iocfg & ~(1 << 18));
+ }
+}
+
+static bool piix_broken_system_poweroff(struct pci_dev *pdev)
+{
+ static const struct dmi_system_id broken_systems[] = {
+ {
+ .ident = "HP Compaq 2510p",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 2510p"),
+ },
+ /* PCI slot number of the controller */
+ .driver_data = (void *)0x1FUL,
+ },
+
+ { } /* terminate list */
+ };
+ const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+ if (dmi) {
+ unsigned long slot = (unsigned long)dmi->driver_data;
+ /* apply the quirk only to on-board controllers */
+ return slot == PCI_SLOT(pdev->devfn);
}
+
+ return false;
}
/**
@@ -1420,6 +1448,14 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
if (!in_module_init)
return -ENODEV;
+ if (piix_broken_system_poweroff(pdev)) {
+ piix_port_info[ent->driver_data].flags |=
+ ATA_FLAG_NO_POWEROFF_SPINDOWN |
+ ATA_FLAG_NO_HIBERNATE_SPINDOWN;
+ dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
+ "on poweroff and hibernation\n");
+ }
+
port_info[0] = piix_port_info[ent->driver_data];
port_info[1] = piix_port_info[ent->driver_data];
@@ -1430,6 +1466,17 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
if (rc)
return rc;
+ hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+ if (!hpriv)
+ return -ENOMEM;
+
+ /* Save IOCFG, this will be used for cable detection, quirk
+ * detection and restoration on detach. This is necessary
+ * because some ACPI implementations mess up cable related
+ * bits on _STM. Reported on kernel bz#11879.
+ */
+ pci_read_config_dword(pdev, PIIX_IOCFG, &hpriv->saved_iocfg);
+
/* ICH6R may be driven by either ata_piix or ahci driver
* regardless of BIOS configuration. Make sure AHCI mode is
* off.
@@ -1441,10 +1488,6 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
}
/* SATA map init can change port_info, do it before prepping host */
- hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
- if (!hpriv)
- return -ENOMEM;
-
if (port_flags & ATA_FLAG_SATA)
hpriv->map = piix_init_sata_map(pdev, port_info,
piix_map_db_table[ent->driver_data]);
@@ -1463,7 +1506,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
}
/* apply IOCFG bit18 quirk */
- piix_iocfg_bit18_quirk(pdev);
+ piix_iocfg_bit18_quirk(host);
/* On ICH5, some BIOSen disable the interrupt using the
* PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3.
@@ -1488,6 +1531,16 @@ static int __devinit piix_init_one(struct pci_dev *pdev,
return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht);
}
+static void piix_remove_one(struct pci_dev *pdev)
+{
+ struct ata_host *host = dev_get_drvdata(&pdev->dev);
+ struct piix_host_priv *hpriv = host->private_data;
+
+ pci_write_config_dword(pdev, PIIX_IOCFG, hpriv->saved_iocfg);
+
+ ata_pci_remove_one(pdev);
+}
+
static int __init piix_init(void)
{
int rc;
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index ef02e488d468..6273d98d00eb 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -19,12 +19,6 @@
#include "libata.h"
#include <acpi/acpi_bus.h>
-#include <acpi/acnames.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
-#include <acpi/acexcep.h>
-#include <acpi/acmacros.h>
-#include <acpi/actypes.h>
enum {
ATA_ACPI_FILTER_SETXFER = 1 << 0,
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index fecca4223f8e..9fbf0595f3d4 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -56,6 +56,7 @@
#include <linux/workqueue.h>
#include <linux/scatterlist.h>
#include <linux/io.h>
+#include <linux/async.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
@@ -163,6 +164,11 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+static bool ata_sstatus_online(u32 sstatus)
+{
+ return (sstatus & 0xf) == 0x3;
+}
+
/**
* ata_link_next - link iteration helper
* @link: the previous link, NULL to start
@@ -1006,6 +1012,7 @@ static const char *sata_spd_string(unsigned int spd)
static const char * const spd_str[] = {
"1.5 Gbps",
"3.0 Gbps",
+ "6.0 Gbps",
};
if (spd == 0 || (spd - 1) >= ARRAY_SIZE(spd_str))
@@ -1013,18 +1020,6 @@ static const char *sata_spd_string(unsigned int spd)
return spd_str[spd - 1];
}
-void ata_dev_disable(struct ata_device *dev)
-{
- if (ata_dev_enabled(dev)) {
- if (ata_msg_drv(dev->link->ap))
- ata_dev_printk(dev, KERN_WARNING, "disabled\n");
- ata_acpi_on_disable(dev);
- ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
- ATA_DNXFER_QUIET);
- dev->class++;
- }
-}
-
static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy)
{
struct ata_link *link = dev->link;
@@ -1999,6 +1994,10 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
as the caller should know this */
if (adev->link->ap->flags & ATA_FLAG_NO_IORDY)
return 0;
+ /* CF spec. r4.1 Table 22 says no iordy on PIO5 and PIO6. */
+ if (ata_id_is_cfa(adev->id)
+ && (adev->pio_mode == XFER_PIO_5 || adev->pio_mode == XFER_PIO_6))
+ return 0;
/* PIO3 and higher it is mandatory */
if (adev->pio_mode > XFER_PIO_2)
return 1;
@@ -2233,6 +2232,40 @@ retry:
return rc;
}
+static int ata_do_link_spd_horkage(struct ata_device *dev)
+{
+ struct ata_link *plink = ata_dev_phys_link(dev);
+ u32 target, target_limit;
+
+ if (!sata_scr_valid(plink))
+ return 0;
+
+ if (dev->horkage & ATA_HORKAGE_1_5_GBPS)
+ target = 1;
+ else
+ return 0;
+
+ target_limit = (1 << target) - 1;
+
+ /* if already on stricter limit, no need to push further */
+ if (plink->sata_spd_limit <= target_limit)
+ return 0;
+
+ plink->sata_spd_limit = target_limit;
+
+ /* Request another EH round by returning -EAGAIN if link is
+ * going faster than the target speed. Forward progress is
+ * guaranteed by setting sata_spd_limit to target_limit above.
+ */
+ if (plink->sata_spd > target) {
+ ata_dev_printk(dev, KERN_INFO,
+ "applying link speed limit horkage to %s\n",
+ sata_spd_string(target));
+ return -EAGAIN;
+ }
+ return 0;
+}
+
static inline u8 ata_dev_knobble(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
@@ -2323,6 +2356,10 @@ int ata_dev_configure(struct ata_device *dev)
return 0;
}
+ rc = ata_do_link_spd_horkage(dev);
+ if (rc)
+ return rc;
+
/* let ACPI work its magic */
rc = ata_acpi_on_devcfg(dev);
if (rc)
@@ -2778,7 +2815,7 @@ int ata_bus_probe(struct ata_port *ap)
/* This is the last chance, better to slow
* down than lose it.
*/
- sata_down_spd_limit(&ap->link);
+ sata_down_spd_limit(&ap->link, 0);
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
@@ -2874,21 +2911,27 @@ void ata_port_disable(struct ata_port *ap)
/**
* sata_down_spd_limit - adjust SATA spd limit downward
* @link: Link to adjust SATA spd limit for
+ * @spd_limit: Additional limit
*
* Adjust SATA spd limit of @link downward. Note that this
* function only adjusts the limit. The change must be applied
* using sata_set_spd().
*
+ * If @spd_limit is non-zero, the speed is limited to equal to or
+ * lower than @spd_limit if such speed is supported. If
+ * @spd_limit is slower than any supported speed, only the lowest
+ * supported speed is allowed.
+ *
* LOCKING:
* Inherited from caller.
*
* RETURNS:
* 0 on success, negative errno on failure
*/
-int sata_down_spd_limit(struct ata_link *link)
+int sata_down_spd_limit(struct ata_link *link, u32 spd_limit)
{
u32 sstatus, spd, mask;
- int rc, highbit;
+ int rc, bit;
if (!sata_scr_valid(link))
return -EOPNOTSUPP;
@@ -2897,7 +2940,7 @@ int sata_down_spd_limit(struct ata_link *link)
* If not, use cached value in link->sata_spd.
*/
rc = sata_scr_read(link, SCR_STATUS, &sstatus);
- if (rc == 0)
+ if (rc == 0 && ata_sstatus_online(sstatus))
spd = (sstatus >> 4) & 0xf;
else
spd = link->sata_spd;
@@ -2907,8 +2950,8 @@ int sata_down_spd_limit(struct ata_link *link)
return -EINVAL;
/* unconditionally mask off the highest bit */
- highbit = fls(mask) - 1;
- mask &= ~(1 << highbit);
+ bit = fls(mask) - 1;
+ mask &= ~(1 << bit);
/* Mask off all speeds higher than or equal to the current
* one. Force 1.5Gbps if current SPD is not available.
@@ -2922,6 +2965,15 @@ int sata_down_spd_limit(struct ata_link *link)
if (!mask)
return -EINVAL;
+ if (spd_limit) {
+ if (mask & ((1 << spd_limit) - 1))
+ mask &= (1 << spd_limit) - 1;
+ else {
+ bit = ffs(mask) - 1;
+ mask = 1 << bit;
+ }
+ }
+
link->sata_spd_limit = mask;
ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n",
@@ -3023,33 +3075,33 @@ int sata_set_spd(struct ata_link *link)
*/
static const struct ata_timing ata_timing[] = {
-/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960, 0 }, */
- { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0 },
- { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 383, 0 },
- { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 240, 0 },
- { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 },
- { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 },
- { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 },
- { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 },
-
- { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 },
- { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 },
- { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 240, 0 },
-
- { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 },
- { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 },
- { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 },
- { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 },
- { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 },
-
-/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 150 }, */
- { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 },
- { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 },
- { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 },
- { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 },
- { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 },
- { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 },
- { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 },
+/* { XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 0, 960, 0 }, */
+ { XFER_PIO_0, 70, 290, 240, 600, 165, 150, 0, 600, 0 },
+ { XFER_PIO_1, 50, 290, 93, 383, 125, 100, 0, 383, 0 },
+ { XFER_PIO_2, 30, 290, 40, 330, 100, 90, 0, 240, 0 },
+ { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 0, 180, 0 },
+ { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 0, 120, 0 },
+ { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 0, 100, 0 },
+ { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 0, 80, 0 },
+
+ { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 50, 960, 0 },
+ { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 30, 480, 0 },
+ { XFER_SW_DMA_2, 60, 0, 0, 0, 120, 120, 20, 240, 0 },
+
+ { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 20, 480, 0 },
+ { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 5, 150, 0 },
+ { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 5, 120, 0 },
+ { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 5, 100, 0 },
+ { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 5, 80, 0 },
+
+/* { XFER_UDMA_SLOW, 0, 0, 0, 0, 0, 0, 0, 0, 150 }, */
+ { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 0, 120 },
+ { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 0, 80 },
+ { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 0, 60 },
+ { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 0, 45 },
+ { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 0, 30 },
+ { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 0, 20 },
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 0, 15 },
{ 0xFF }
};
@@ -3059,14 +3111,15 @@ static const struct ata_timing ata_timing[] = {
static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
{
- q->setup = EZ(t->setup * 1000, T);
- q->act8b = EZ(t->act8b * 1000, T);
- q->rec8b = EZ(t->rec8b * 1000, T);
- q->cyc8b = EZ(t->cyc8b * 1000, T);
- q->active = EZ(t->active * 1000, T);
- q->recover = EZ(t->recover * 1000, T);
- q->cycle = EZ(t->cycle * 1000, T);
- q->udma = EZ(t->udma * 1000, UT);
+ q->setup = EZ(t->setup * 1000, T);
+ q->act8b = EZ(t->act8b * 1000, T);
+ q->rec8b = EZ(t->rec8b * 1000, T);
+ q->cyc8b = EZ(t->cyc8b * 1000, T);
+ q->active = EZ(t->active * 1000, T);
+ q->recover = EZ(t->recover * 1000, T);
+ q->dmack_hold = EZ(t->dmack_hold * 1000, T);
+ q->cycle = EZ(t->cycle * 1000, T);
+ q->udma = EZ(t->udma * 1000, UT);
}
void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
@@ -3078,6 +3131,7 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
if (what & ATA_TIMING_CYC8B ) m->cyc8b = max(a->cyc8b, b->cyc8b);
if (what & ATA_TIMING_ACTIVE ) m->active = max(a->active, b->active);
if (what & ATA_TIMING_RECOVER) m->recover = max(a->recover, b->recover);
+ if (what & ATA_TIMING_DMACK_HOLD) m->dmack_hold = max(a->dmack_hold, b->dmack_hold);
if (what & ATA_TIMING_CYCLE ) m->cycle = max(a->cycle, b->cycle);
if (what & ATA_TIMING_UDMA ) m->udma = max(a->udma, b->udma);
}
@@ -4207,6 +4261,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices that do not need bridging limits applied */
{ "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, },
+ /* Devices which aren't very happy with higher link speeds */
+ { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
+
/* End Marker */
{ }
};
@@ -4550,7 +4607,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
struct scatterlist *sg = qc->sg;
int dir = qc->dma_dir;
- WARN_ON(sg == NULL);
+ WARN_ON_ONCE(sg == NULL);
VPRINTK("unmapping %u sg elements\n", qc->n_elem);
@@ -4701,8 +4758,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
/**
* ata_qc_new - Request an available ATA command, for queueing
- * @ap: Port associated with device @dev
- * @dev: Device from whom we request an available command structure
+ * @ap: target port
*
* LOCKING:
* None.
@@ -4770,7 +4826,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
unsigned int tag;
- WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
qc->flags = 0;
tag = qc->tag;
@@ -4785,8 +4841,8 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
struct ata_link *link = qc->dev->link;
- WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
- WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
+ WARN_ON_ONCE(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
+ WARN_ON_ONCE(!(qc->flags & ATA_QCFLAG_ACTIVE));
if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
ata_sg_clean(qc);
@@ -4872,7 +4928,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
struct ata_device *dev = qc->dev;
struct ata_eh_info *ehi = &dev->link->eh_info;
- WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
+ WARN_ON_ONCE(ap->pflags & ATA_PFLAG_FROZEN);
if (unlikely(qc->err_mask))
qc->flags |= ATA_QCFLAG_FAILED;
@@ -4994,16 +5050,16 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
* check is skipped for old EH because it reuses active qc to
* request ATAPI sense.
*/
- WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag));
+ WARN_ON_ONCE(ap->ops->error_handler && ata_tag_valid(link->active_tag));
if (ata_is_ncq(prot)) {
- WARN_ON(link->sactive & (1 << qc->tag));
+ WARN_ON_ONCE(link->sactive & (1 << qc->tag));
if (!link->sactive)
ap->nr_active_links++;
link->sactive |= 1 << qc->tag;
} else {
- WARN_ON(link->sactive);
+ WARN_ON_ONCE(link->sactive);
ap->nr_active_links++;
link->active_tag = qc->tag;
@@ -5167,7 +5223,7 @@ bool ata_phys_link_online(struct ata_link *link)
u32 sstatus;
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
- (sstatus & 0xf) == 0x3)
+ ata_sstatus_online(sstatus))
return true;
return false;
}
@@ -5191,7 +5247,7 @@ bool ata_phys_link_offline(struct ata_link *link)
u32 sstatus;
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 &&
- (sstatus & 0xf) != 0x3)
+ !ata_sstatus_online(sstatus))
return true;
return false;
}
@@ -5404,8 +5460,8 @@ void ata_dev_init(struct ata_device *dev)
dev->horkage = 0;
spin_unlock_irqrestore(ap->lock, flags);
- memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
- sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET);
+ memset((void *)dev + ATA_DEVICE_CLEAR_BEGIN, 0,
+ ATA_DEVICE_CLEAR_END - ATA_DEVICE_CLEAR_BEGIN);
dev->pio_mask = UINT_MAX;
dev->mwdma_mask = UINT_MAX;
dev->udma_mask = UINT_MAX;
@@ -5909,6 +5965,65 @@ void ata_host_init(struct ata_host *host, struct device *dev,
host->ops = ops;
}
+
+static void async_port_probe(void *data, async_cookie_t cookie)
+{
+ int rc;
+ struct ata_port *ap = data;
+
+ /*
+ * If we're not allowed to scan this host in parallel,
+ * we need to wait until all previous scans have completed
+ * before going further.
+ * Jeff Garzik says this is only within a controller, so we
+ * don't need to wait for port 0, only for later ports.
+ */
+ if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)
+ async_synchronize_cookie(cookie);
+
+ /* probe */
+ if (ap->ops->error_handler) {
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ unsigned long flags;
+
+ ata_port_probe(ap);
+
+ /* kick EH for boot probing */
+ spin_lock_irqsave(ap->lock, flags);
+
+ ehi->probe_mask |= ATA_ALL_DEVICES;
+ ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
+ ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+
+ ap->pflags &= ~ATA_PFLAG_INITIALIZING;
+ ap->pflags |= ATA_PFLAG_LOADING;
+ ata_port_schedule_eh(ap);
+
+ spin_unlock_irqrestore(ap->lock, flags);
+
+ /* wait for EH to finish */
+ ata_port_wait_eh(ap);
+ } else {
+ DPRINTK("ata%u: bus probe begin\n", ap->print_id);
+ rc = ata_bus_probe(ap);
+ DPRINTK("ata%u: bus probe end\n", ap->print_id);
+
+ if (rc) {
+ /* FIXME: do something useful here?
+ * Current libata behavior will
+ * tear down everything when
+ * the module is removed
+ * or the h/w is unplugged.
+ */
+ }
+ }
+
+ /* in order to keep device order, we need to synchronize at this point */
+ async_synchronize_cookie(cookie);
+
+ ata_scsi_scan_host(ap, 1);
+
+}
/**
* ata_host_register - register initialized ATA host
* @host: ATA host to register
@@ -5988,52 +6103,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
DPRINTK("probe begin\n");
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
-
- /* probe */
- if (ap->ops->error_handler) {
- struct ata_eh_info *ehi = &ap->link.eh_info;
- unsigned long flags;
-
- ata_port_probe(ap);
-
- /* kick EH for boot probing */
- spin_lock_irqsave(ap->lock, flags);
-
- ehi->probe_mask |= ATA_ALL_DEVICES;
- ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
- ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
-
- ap->pflags &= ~ATA_PFLAG_INITIALIZING;
- ap->pflags |= ATA_PFLAG_LOADING;
- ata_port_schedule_eh(ap);
-
- spin_unlock_irqrestore(ap->lock, flags);
-
- /* wait for EH to finish */
- ata_port_wait_eh(ap);
- } else {
- DPRINTK("ata%u: bus probe begin\n", ap->print_id);
- rc = ata_bus_probe(ap);
- DPRINTK("ata%u: bus probe end\n", ap->print_id);
-
- if (rc) {
- /* FIXME: do something useful here?
- * Current libata behavior will
- * tear down everything when
- * the module is removed
- * or the h/w is unplugged.
- */
- }
- }
- }
-
- /* probes are done, now scan each port's disk(s) */
- DPRINTK("host probe begin\n");
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
-
- ata_scsi_scan_host(ap, 1);
+ async_schedule(async_port_probe, ap);
}
+ DPRINTK("probe end\n");
return 0;
}
@@ -6616,7 +6688,6 @@ EXPORT_SYMBOL_GPL(ata_dev_pair);
EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_wait_register);
-EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 8147a8386370..ce2ef0475339 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -82,6 +82,10 @@ enum {
ATA_EH_FASTDRAIN_INTERVAL = 3000,
ATA_EH_UA_TRIES = 5,
+
+ /* probe speed down parameters, see ata_eh_schedule_probe() */
+ ATA_EH_PROBE_TRIAL_INTERVAL = 60000, /* 1 min */
+ ATA_EH_PROBE_TRIALS = 2,
};
/* The following table determines how we sequence resets. Each entry
@@ -1176,6 +1180,32 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc)
}
/**
+ * ata_dev_disable - disable ATA device
+ * @dev: ATA device to disable
+ *
+ * Disable @dev.
+ *
+ * Locking:
+ * EH context.
+ */
+void ata_dev_disable(struct ata_device *dev)
+{
+ if (!ata_dev_enabled(dev))
+ return;
+
+ if (ata_msg_drv(dev->link->ap))
+ ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+ ata_acpi_on_disable(dev);
+ ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET);
+ dev->class++;
+
+ /* From now till the next successful probe, ering is used to
+ * track probe failures. Clear accumulated device error info.
+ */
+ ata_ering_clear(&dev->ering);
+}
+
+/**
* ata_eh_detach_dev - detach ATA device
* @dev: ATA device to detach
*
@@ -1849,7 +1879,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
/* speed down? */
if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
/* speed down SATA link speed if possible */
- if (sata_down_spd_limit(link) == 0) {
+ if (sata_down_spd_limit(link, 0) == 0) {
action |= ATA_EH_RESET;
goto done;
}
@@ -2601,11 +2631,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
}
if (try == max_tries - 1) {
- sata_down_spd_limit(link);
+ sata_down_spd_limit(link, 0);
if (slave)
- sata_down_spd_limit(slave);
+ sata_down_spd_limit(slave, 0);
} else if (rc == -EPIPE)
- sata_down_spd_limit(failed_link);
+ sata_down_spd_limit(failed_link, 0);
if (hardreset)
reset = hardreset;
@@ -2744,6 +2774,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
readid_flags, dev->id);
switch (rc) {
case 0:
+ /* clear error info accumulated during probe */
+ ata_ering_clear(&dev->ering);
new_mask |= 1 << dev->devno;
break;
case -ENOENT:
@@ -2947,9 +2979,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
return 1;
}
+static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+ u64 interval = msecs_to_jiffies(ATA_EH_PROBE_TRIAL_INTERVAL);
+ u64 now = get_jiffies_64();
+ int *trials = void_arg;
+
+ if (ent->timestamp < now - min(now, interval))
+ return -1;
+
+ (*trials)++;
+ return 0;
+}
+
static int ata_eh_schedule_probe(struct ata_device *dev)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
+ struct ata_link *link = ata_dev_phys_link(dev);
+ int trials = 0;
if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
(ehc->did_probe_mask & (1 << dev->devno)))
@@ -2962,6 +3009,25 @@ static int ata_eh_schedule_probe(struct ata_device *dev)
ehc->saved_xfer_mode[dev->devno] = 0;
ehc->saved_ncq_enabled &= ~(1 << dev->devno);
+ /* Record and count probe trials on the ering. The specific
+ * error mask used is irrelevant. Because a successful device
+ * detection clears the ering, this count accumulates only if
+ * there are consecutive failed probes.
+ *
+ * If the count is equal to or higher than ATA_EH_PROBE_TRIALS
+ * in the last ATA_EH_PROBE_TRIAL_INTERVAL, link speed is
+ * forced to 1.5Gbps.
+ *
+ * This is to work around cases where failed link speed
+ * negotiation results in device misdetection leading to
+ * infinite DEVXCHG or PHRDY CHG events.
+ */
+ ata_ering_record(&dev->ering, 0, AC_ERR_OTHER);
+ ata_ering_map(&dev->ering, ata_count_probe_trials_cb, &trials);
+
+ if (trials > ATA_EH_PROBE_TRIALS)
+ sata_down_spd_limit(link, 1);
+
return 1;
}
@@ -2969,7 +3035,11 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
- ehc->tries[dev->devno]--;
+ /* -EAGAIN from EH routine indicates retry without prejudice.
+ * The requester is responsible for ensuring forward progress.
+ */
+ if (err != -EAGAIN)
+ ehc->tries[dev->devno]--;
switch (err) {
case -ENODEV:
@@ -2979,12 +3049,13 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
case -EIO:
- if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) {
+ if (ehc->tries[dev->devno] == 1) {
/* This is the last chance, better to slow
* down than lose it.
*/
- sata_down_spd_limit(ata_dev_phys_link(dev));
- ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+ sata_down_spd_limit(ata_dev_phys_link(dev), 0);
+ if (dev->pio_mode > XFER_PIO_0)
+ ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 98ca07a2db87..619f2c33950e 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -729,7 +729,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
if (tries) {
/* consecutive revalidation failures? speed down */
if (reval_failed)
- sata_down_spd_limit(link);
+ sata_down_spd_limit(link, 0);
else
reval_failed = 1;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 4040d8b53216..b9747fa59e54 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -46,6 +46,7 @@
#include <linux/libata.h>
#include <linux/hdreg.h>
#include <linux/uaccess.h>
+#include <linux/suspend.h>
#include "libata.h"
@@ -414,6 +415,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
/**
* ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
+ * @ap: target port
* @sdev: SCSI device to get identify data for
* @arg: User buffer area for identify data
*
@@ -423,9 +425,9 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
* RETURNS:
* Zero on success, negative errno on error.
*/
-static int ata_get_identity(struct scsi_device *sdev, void __user *arg)
+static int ata_get_identity(struct ata_port *ap, struct scsi_device *sdev,
+ void __user *arg)
{
- struct ata_port *ap = ata_shost_to_port(sdev->host);
struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
u16 __user *dst = arg;
char buf[40];
@@ -645,7 +647,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
return rc;
}
-int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
+ int cmd, void __user *arg)
{
int val = -EINVAL, rc = -EINVAL;
@@ -663,7 +666,7 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
return 0;
case HDIO_GET_IDENTITY:
- return ata_get_identity(scsidev, arg);
+ return ata_get_identity(ap, scsidev, arg);
case HDIO_DRIVE_CMD:
if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
@@ -682,6 +685,14 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
return rc;
}
+EXPORT_SYMBOL_GPL(ata_sas_scsi_ioctl);
+
+int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+ return ata_sas_scsi_ioctl(ata_shost_to_port(scsidev->host),
+ scsidev, cmd, arg);
+}
+EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
/**
* ata_scsi_qc_new - acquire new ata_queued_cmd reference
@@ -1294,6 +1305,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
tf->command = ATA_CMD_VERIFY; /* READ VERIFY */
} else {
+ /* Some odd clown BIOSen issue spindown on power off (ACPI S4
+ * or S5) causing some drives to spin up and down again.
+ */
+ if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
+ system_state == SYSTEM_POWER_OFF)
+ goto skip;
+
+ if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
+ system_entering_hibernation())
+ goto skip;
+
/* XXX: This is for backward compatibility, will be
* removed. Read Documentation/feature-removal-schedule.txt
* for more info.
@@ -1317,8 +1339,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
scmd->scsi_done = qc->scsidone;
qc->scsidone = ata_delayed_done;
}
- scmd->result = SAM_STAT_GOOD;
- return 1;
+ goto skip;
}
/* Issue ATA STANDBY IMMEDIATE command */
@@ -1334,10 +1355,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
return 0;
-invalid_fld:
+ invalid_fld:
ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
/* "Invalid field in cbd" */
return 1;
+ skip:
+ scmd->result = SAM_STAT_GOOD;
+ return 1;
}
@@ -3369,7 +3393,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
if (sdev) {
ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
- sdev->sdev_gendev.bus_id);
+ dev_name(&sdev->sdev_gendev));
scsi_remove_device(sdev);
scsi_device_put(sdev);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 9033d164c4ec..0b299b0f8172 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -66,6 +66,7 @@ const struct ata_port_operations ata_sff_port_ops = {
.port_start = ata_sff_port_start,
};
+EXPORT_SYMBOL_GPL(ata_sff_port_ops);
const struct ata_port_operations ata_bmdma_port_ops = {
.inherits = &ata_sff_port_ops,
@@ -77,6 +78,14 @@ const struct ata_port_operations ata_bmdma_port_ops = {
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
};
+EXPORT_SYMBOL_GPL(ata_bmdma_port_ops);
+
+const struct ata_port_operations ata_bmdma32_port_ops = {
+ .inherits = &ata_bmdma_port_ops,
+
+ .sff_data_xfer = ata_sff_data_xfer32,
+};
+EXPORT_SYMBOL_GPL(ata_bmdma32_port_ops);
/**
* ata_fill_sg - Fill PCI IDE PRD table
@@ -166,8 +175,9 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
blen = len & 0xffff;
ap->prd[pi].addr = cpu_to_le32(addr);
if (blen == 0) {
- /* Some PATA chipsets like the CS5530 can't
- cope with 0x0000 meaning 64K as the spec says */
+ /* Some PATA chipsets like the CS5530 can't
+ cope with 0x0000 meaning 64K as the spec
+ says */
ap->prd[pi].flags_len = cpu_to_le32(0x8000);
blen = 0x8000;
ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
@@ -200,6 +210,7 @@ void ata_sff_qc_prep(struct ata_queued_cmd *qc)
ata_fill_sg(qc);
}
+EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
/**
* ata_sff_dumb_qc_prep - Prepare taskfile for submission
@@ -217,6 +228,7 @@ void ata_sff_dumb_qc_prep(struct ata_queued_cmd *qc)
ata_fill_sg_dumb(qc);
}
+EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
/**
* ata_sff_check_status - Read device status reg & clear interrupt
@@ -233,6 +245,7 @@ u8 ata_sff_check_status(struct ata_port *ap)
{
return ioread8(ap->ioaddr.status_addr);
}
+EXPORT_SYMBOL_GPL(ata_sff_check_status);
/**
* ata_sff_altstatus - Read device alternate status reg
@@ -275,7 +288,7 @@ static u8 ata_sff_irq_status(struct ata_port *ap)
status = ata_sff_altstatus(ap);
/* Not us: We are busy */
if (status & ATA_BUSY)
- return status;
+ return status;
}
/* Clear INTRQ latch */
status = ap->ops->sff_check_status(ap);
@@ -319,6 +332,7 @@ void ata_sff_pause(struct ata_port *ap)
ata_sff_sync(ap);
ndelay(400);
}
+EXPORT_SYMBOL_GPL(ata_sff_pause);
/**
* ata_sff_dma_pause - Pause before commencing DMA
@@ -327,7 +341,7 @@ void ata_sff_pause(struct ata_port *ap)
* Perform I/O fencing and ensure sufficient cycle delays occur
* for the HDMA1:0 transition
*/
-
+
void ata_sff_dma_pause(struct ata_port *ap)
{
if (ap->ops->sff_check_altstatus || ap->ioaddr.altstatus_addr) {
@@ -341,6 +355,7 @@ void ata_sff_dma_pause(struct ata_port *ap)
corruption. */
BUG();
}
+EXPORT_SYMBOL_GPL(ata_sff_dma_pause);
/**
* ata_sff_busy_sleep - sleep until BSY clears, or timeout
@@ -396,6 +411,7 @@ int ata_sff_busy_sleep(struct ata_port *ap,
return 0;
}
+EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
static int ata_sff_check_ready(struct ata_link *link)
{
@@ -422,6 +438,7 @@ int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline)
{
return ata_wait_ready(link, deadline, ata_sff_check_ready);
}
+EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
/**
* ata_sff_dev_select - Select device 0/1 on ATA bus
@@ -449,6 +466,7 @@ void ata_sff_dev_select(struct ata_port *ap, unsigned int device)
iowrite8(tmp, ap->ioaddr.device_addr);
ata_sff_pause(ap); /* needed; also flushes, for mmio */
}
+EXPORT_SYMBOL_GPL(ata_sff_dev_select);
/**
* ata_dev_select - Select device 0/1 on ATA bus
@@ -513,6 +531,7 @@ u8 ata_sff_irq_on(struct ata_port *ap)
return tmp;
}
+EXPORT_SYMBOL_GPL(ata_sff_irq_on);
/**
* ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt.
@@ -534,6 +553,7 @@ void ata_sff_irq_clear(struct ata_port *ap)
iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS);
}
+EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
/**
* ata_sff_tf_load - send taskfile registers to host controller
@@ -558,7 +578,7 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
- WARN_ON(!ioaddr->ctl_addr);
+ WARN_ON_ONCE(!ioaddr->ctl_addr);
iowrite8(tf->hob_feature, ioaddr->feature_addr);
iowrite8(tf->hob_nsect, ioaddr->nsect_addr);
iowrite8(tf->hob_lbal, ioaddr->lbal_addr);
@@ -593,6 +613,7 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
ata_wait_idle(ap);
}
+EXPORT_SYMBOL_GPL(ata_sff_tf_load);
/**
* ata_sff_tf_read - input device's ATA taskfile shadow registers
@@ -630,9 +651,10 @@ void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
iowrite8(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
} else
- WARN_ON(1);
+ WARN_ON_ONCE(1);
}
}
+EXPORT_SYMBOL_GPL(ata_sff_tf_read);
/**
* ata_sff_exec_command - issue ATA command to host controller
@@ -652,6 +674,7 @@ void ata_sff_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
iowrite8(tf->command, ap->ioaddr.command_addr);
ata_sff_pause(ap);
}
+EXPORT_SYMBOL_GPL(ata_sff_exec_command);
/**
* ata_tf_to_host - issue ATA taskfile to host controller
@@ -717,6 +740,53 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
return words << 1;
}
+EXPORT_SYMBOL_GPL(ata_sff_data_xfer);
+
+/**
+ * ata_sff_data_xfer32 - Transfer data by PIO
+ * @dev: device to target
+ * @buf: data buffer
+ * @buflen: buffer length
+ * @rw: read/write
+ *
+ * Transfer data from/to the device data register by PIO using 32bit
+ * I/O operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ *
+ * RETURNS:
+ * Bytes consumed.
+ */
+
+unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
+ unsigned int buflen, int rw)
+{
+ struct ata_port *ap = dev->link->ap;
+ void __iomem *data_addr = ap->ioaddr.data_addr;
+ unsigned int words = buflen >> 2;
+ int slop = buflen & 3;
+
+ /* Transfer multiple of 4 bytes */
+ if (rw == READ)
+ ioread32_rep(data_addr, buf, words);
+ else
+ iowrite32_rep(data_addr, buf, words);
+
+ if (unlikely(slop)) {
+ __le32 pad;
+ if (rw == READ) {
+ pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
+ memcpy(buf + buflen - slop, &pad, slop);
+ } else {
+ memcpy(&pad, buf + buflen - slop, slop);
+ iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ }
+ words++;
+ }
+ return words << 2;
+}
+EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
/**
* ata_sff_data_xfer_noirq - Transfer data by PIO
@@ -746,6 +816,7 @@ unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
return consumed;
}
+EXPORT_SYMBOL_GPL(ata_sff_data_xfer_noirq);
/**
* ata_pio_sector - Transfer a sector of data.
@@ -820,7 +891,7 @@ static void ata_pio_sectors(struct ata_queued_cmd *qc)
/* READ/WRITE MULTIPLE */
unsigned int nsect;
- WARN_ON(qc->dev->multi_count == 0);
+ WARN_ON_ONCE(qc->dev->multi_count == 0);
nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
qc->dev->multi_count);
@@ -847,7 +918,7 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
{
/* send SCSI cdb */
DPRINTK("send cdb\n");
- WARN_ON(qc->dev->cdb_len < 12);
+ WARN_ON_ONCE(qc->dev->cdb_len < 12);
ap->ops->sff_data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
ata_sff_sync(ap);
@@ -922,13 +993,15 @@ next_sg:
buf = kmap_atomic(page, KM_IRQ0);
/* do the actual data transfer */
- consumed = ap->ops->sff_data_xfer(dev, buf + offset, count, rw);
+ consumed = ap->ops->sff_data_xfer(dev, buf + offset,
+ count, rw);
kunmap_atomic(buf, KM_IRQ0);
local_irq_restore(flags);
} else {
buf = page_address(page);
- consumed = ap->ops->sff_data_xfer(dev, buf + offset, count, rw);
+ consumed = ap->ops->sff_data_xfer(dev, buf + offset,
+ count, rw);
}
bytes -= min(bytes, consumed);
@@ -940,9 +1013,12 @@ next_sg:
qc->cursg_ofs = 0;
}
- /* consumed can be larger than count only for the last transfer */
- WARN_ON(qc->cursg && count != consumed);
-
+ /*
+ * There used to be a WARN_ON_ONCE(qc->cursg && count != consumed);
+ * Unfortunately __atapi_pio_bytes doesn't know enough to do the WARN
+ * check correctly as it doesn't know if it is the last request being
+ * made. Somebody should implement a proper sanity check.
+ */
if (bytes)
goto next_sg;
return 0;
@@ -1013,18 +1089,19 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
* RETURNS:
* 1 if ok in workqueue, 0 otherwise.
*/
-static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
+static inline int ata_hsm_ok_in_wq(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
{
if (qc->tf.flags & ATA_TFLAG_POLLING)
return 1;
if (ap->hsm_task_state == HSM_ST_FIRST) {
if (qc->tf.protocol == ATA_PROT_PIO &&
- (qc->tf.flags & ATA_TFLAG_WRITE))
+ (qc->tf.flags & ATA_TFLAG_WRITE))
return 1;
if (ata_is_atapi(qc->tf.protocol) &&
- !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+ !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
return 1;
}
@@ -1098,13 +1175,13 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
unsigned long flags = 0;
int poll_next;
- WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+ WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
/* Make sure ata_sff_qc_issue() does not throw things
* like DMA polling into the workqueue. Notice that
* in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
*/
- WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
+ WARN_ON_ONCE(in_wq != ata_hsm_ok_in_wq(ap, qc));
fsm_start:
DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
@@ -1245,7 +1322,7 @@ fsm_start:
* condition. Mark hint.
*/
ata_ehi_push_desc(ehi, "ST-ATA: "
- "DRQ=1 with device error, "
+ "DRQ=0 without device error, "
"dev_stat 0x%X", status);
qc->err_mask |= AC_ERR_HSM |
AC_ERR_NODEV_HINT;
@@ -1281,6 +1358,16 @@ fsm_start:
qc->err_mask |= AC_ERR_HSM;
}
+ /* There are oddball controllers with
+ * status register stuck at 0x7f and
+ * lbal/m/h at zero which makes it
+ * pass all other presence detection
+ * mechanisms we have. Set NODEV_HINT
+ * for it. Kernel bz#7241.
+ */
+ if (status == 0x7f)
+ qc->err_mask |= AC_ERR_NODEV_HINT;
+
/* ata_pio_sectors() might change the
* state to HSM_ST_LAST. so, the state
* is changed after ata_pio_sectors().
@@ -1313,7 +1400,7 @@ fsm_start:
DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
ap->print_id, qc->dev->devno, status);
- WARN_ON(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
+ WARN_ON_ONCE(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
ap->hsm_task_state = HSM_ST_IDLE;
@@ -1338,6 +1425,7 @@ fsm_start:
return poll_next;
}
+EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
void ata_pio_task(struct work_struct *work)
{
@@ -1348,7 +1436,7 @@ void ata_pio_task(struct work_struct *work)
int poll_next;
fsm_start:
- WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
+ WARN_ON_ONCE(ap->hsm_task_state == HSM_ST_IDLE);
/*
* This is purely heuristic. This is a fast path.
@@ -1437,7 +1525,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
break;
case ATA_PROT_DMA:
- WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+ WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
ap->ops->bmdma_setup(qc); /* set up bmdma */
@@ -1489,7 +1577,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
break;
case ATAPI_PROT_DMA:
- WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+ WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
ap->ops->bmdma_setup(qc); /* set up bmdma */
@@ -1501,12 +1589,13 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
break;
default:
- WARN_ON(1);
+ WARN_ON_ONCE(1);
return AC_ERR_SYSTEM;
}
return 0;
}
+EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
/**
* ata_sff_qc_fill_rtf - fill result TF using ->sff_tf_read
@@ -1526,6 +1615,7 @@ bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
qc->ap->ops->sff_tf_read(qc->ap, &qc->result_tf);
return true;
}
+EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
/**
* ata_sff_host_intr - Handle host interrupt for given (port, task)
@@ -1623,6 +1713,7 @@ idle_irq:
#endif
return 0; /* irq not handled */
}
+EXPORT_SYMBOL_GPL(ata_sff_host_intr);
/**
* ata_sff_interrupt - Default ATA host interrupt handler
@@ -1667,6 +1758,7 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance)
return IRQ_RETVAL(handled);
}
+EXPORT_SYMBOL_GPL(ata_sff_interrupt);
/**
* ata_sff_freeze - Freeze SFF controller port
@@ -1695,6 +1787,7 @@ void ata_sff_freeze(struct ata_port *ap)
ap->ops->sff_irq_clear(ap);
}
+EXPORT_SYMBOL_GPL(ata_sff_freeze);
/**
* ata_sff_thaw - Thaw SFF controller port
@@ -1712,6 +1805,7 @@ void ata_sff_thaw(struct ata_port *ap)
ap->ops->sff_irq_clear(ap);
ap->ops->sff_irq_on(ap);
}
+EXPORT_SYMBOL_GPL(ata_sff_thaw);
/**
* ata_sff_prereset - prepare SFF link for reset
@@ -1753,6 +1847,7 @@ int ata_sff_prereset(struct ata_link *link, unsigned long deadline)
return 0;
}
+EXPORT_SYMBOL_GPL(ata_sff_prereset);
/**
* ata_devchk - PATA device presence detection
@@ -1865,6 +1960,7 @@ unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,
return class;
}
+EXPORT_SYMBOL_GPL(ata_sff_dev_classify);
/**
* ata_sff_wait_after_reset - wait for devices to become ready after reset
@@ -1941,6 +2037,7 @@ int ata_sff_wait_after_reset(struct ata_link *link, unsigned int devmask,
return ret;
}
+EXPORT_SYMBOL_GPL(ata_sff_wait_after_reset);
static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
unsigned long deadline)
@@ -2013,6 +2110,7 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
return 0;
}
+EXPORT_SYMBOL_GPL(ata_sff_softreset);
/**
* sata_sff_hardreset - reset host port via SATA phy reset
@@ -2045,6 +2143,7 @@ int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
DPRINTK("EXIT, class=%u\n", *class);
return rc;
}
+EXPORT_SYMBOL_GPL(sata_sff_hardreset);
/**
* ata_sff_postreset - SFF postreset callback
@@ -2080,6 +2179,7 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes)
if (ap->ioaddr.ctl_addr)
iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
}
+EXPORT_SYMBOL_GPL(ata_sff_postreset);
/**
* ata_sff_error_handler - Stock error handler for BMDMA controller
@@ -2152,6 +2252,7 @@ void ata_sff_error_handler(struct ata_port *ap)
ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
ap->ops->postreset);
}
+EXPORT_SYMBOL_GPL(ata_sff_error_handler);
/**
* ata_sff_post_internal_cmd - Stock post_internal_cmd for SFF controller
@@ -2174,6 +2275,7 @@ void ata_sff_post_internal_cmd(struct ata_queued_cmd *qc)
spin_unlock_irqrestore(ap->lock, flags);
}
+EXPORT_SYMBOL_GPL(ata_sff_post_internal_cmd);
/**
* ata_sff_port_start - Set port up for dma.
@@ -2194,6 +2296,7 @@ int ata_sff_port_start(struct ata_port *ap)
return ata_port_start(ap);
return 0;
}
+EXPORT_SYMBOL_GPL(ata_sff_port_start);
/**
* ata_sff_std_ports - initialize ioaddr with standard port offsets.
@@ -2219,6 +2322,7 @@ void ata_sff_std_ports(struct ata_ioports *ioaddr)
ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
}
+EXPORT_SYMBOL_GPL(ata_sff_std_ports);
unsigned long ata_bmdma_mode_filter(struct ata_device *adev,
unsigned long xfer_mask)
@@ -2230,6 +2334,7 @@ unsigned long ata_bmdma_mode_filter(struct ata_device *adev,
xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
return xfer_mask;
}
+EXPORT_SYMBOL_GPL(ata_bmdma_mode_filter);
/**
* ata_bmdma_setup - Set up PCI IDE BMDMA transaction
@@ -2258,6 +2363,7 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
/* issue r/w command */
ap->ops->sff_exec_command(ap, &qc->tf);
}
+EXPORT_SYMBOL_GPL(ata_bmdma_setup);
/**
* ata_bmdma_start - Start a PCI IDE BMDMA transaction
@@ -2290,6 +2396,7 @@ void ata_bmdma_start(struct ata_queued_cmd *qc)
* unneccessarily delayed for MMIO
*/
}
+EXPORT_SYMBOL_GPL(ata_bmdma_start);
/**
* ata_bmdma_stop - Stop PCI IDE BMDMA transfer
@@ -2314,6 +2421,7 @@ void ata_bmdma_stop(struct ata_queued_cmd *qc)
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_sff_dma_pause(ap);
}
+EXPORT_SYMBOL_GPL(ata_bmdma_stop);
/**
* ata_bmdma_status - Read PCI IDE BMDMA status
@@ -2330,6 +2438,7 @@ u8 ata_bmdma_status(struct ata_port *ap)
{
return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
}
+EXPORT_SYMBOL_GPL(ata_bmdma_status);
/**
* ata_bus_reset - reset host port and associated ATA channel
@@ -2422,6 +2531,7 @@ err_out:
DPRINTK("EXIT\n");
}
+EXPORT_SYMBOL_GPL(ata_bus_reset);
#ifdef CONFIG_PCI
@@ -2449,6 +2559,7 @@ int ata_pci_bmdma_clear_simplex(struct pci_dev *pdev)
return -EOPNOTSUPP;
return 0;
}
+EXPORT_SYMBOL_GPL(ata_pci_bmdma_clear_simplex);
/**
* ata_pci_bmdma_init - acquire PCI BMDMA resources and init ATA host
@@ -2501,11 +2612,12 @@ int ata_pci_bmdma_init(struct ata_host *host)
host->flags |= ATA_HOST_SIMPLEX;
ata_port_desc(ap, "bmdma 0x%llx",
- (unsigned long long)pci_resource_start(pdev, 4) + 8 * i);
+ (unsigned long long)pci_resource_start(pdev, 4) + 8 * i);
}
return 0;
}
+EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
static int ata_resources_present(struct pci_dev *pdev, int port)
{
@@ -2513,7 +2625,7 @@ static int ata_resources_present(struct pci_dev *pdev, int port)
/* Check the PCI resources for this channel are enabled */
port = port * 2;
- for (i = 0; i < 2; i ++) {
+ for (i = 0; i < 2; i++) {
if (pci_resource_start(pdev, port + i) == 0 ||
pci_resource_len(pdev, port + i) == 0)
return 0;
@@ -2598,6 +2710,7 @@ int ata_pci_sff_init_host(struct ata_host *host)
return 0;
}
+EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
/**
* ata_pci_sff_prepare_host - helper to prepare native PCI ATA host
@@ -2615,7 +2728,7 @@ int ata_pci_sff_init_host(struct ata_host *host)
* 0 on success, -errno otherwise.
*/
int ata_pci_sff_prepare_host(struct pci_dev *pdev,
- const struct ata_port_info * const * ppi,
+ const struct ata_port_info * const *ppi,
struct ata_host **r_host)
{
struct ata_host *host;
@@ -2645,17 +2758,18 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev,
*r_host = host;
return 0;
- err_bmdma:
+err_bmdma:
/* This is necessary because PCI and iomap resources are
* merged and releasing the top group won't release the
* acquired resources if some of those have been acquired
* before entering this function.
*/
pcim_iounmap_regions(pdev, 0xf);
- err_out:
+err_out:
devres_release_group(&pdev->dev, NULL);
return rc;
}
+EXPORT_SYMBOL_GPL(ata_pci_sff_prepare_host);
/**
* ata_pci_sff_activate_host - start SFF host, request IRQ and register it
@@ -2741,7 +2855,7 @@ int ata_pci_sff_activate_host(struct ata_host *host,
}
rc = ata_host_register(host, sht);
- out:
+out:
if (rc == 0)
devres_remove_group(dev, NULL);
else
@@ -2749,6 +2863,7 @@ int ata_pci_sff_activate_host(struct ata_host *host,
return rc;
}
+EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
/**
* ata_pci_sff_init_one - Initialize/register PCI IDE host controller
@@ -2776,7 +2891,7 @@ int ata_pci_sff_activate_host(struct ata_host *host,
* Zero on success, negative on errno-based value on error.
*/
int ata_pci_sff_init_one(struct pci_dev *pdev,
- const struct ata_port_info * const * ppi,
+ const struct ata_port_info * const *ppi,
struct scsi_host_template *sht, void *host_priv)
{
struct device *dev = &pdev->dev;
@@ -2815,7 +2930,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
pci_set_master(pdev);
rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
- out:
+out:
if (rc == 0)
devres_remove_group(&pdev->dev, NULL);
else
@@ -2823,54 +2938,7 @@ int ata_pci_sff_init_one(struct pci_dev *pdev,
return rc;
}
+EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
#endif /* CONFIG_PCI */
-EXPORT_SYMBOL_GPL(ata_sff_port_ops);
-EXPORT_SYMBOL_GPL(ata_bmdma_port_ops);
-EXPORT_SYMBOL_GPL(ata_sff_qc_prep);
-EXPORT_SYMBOL_GPL(ata_sff_dumb_qc_prep);
-EXPORT_SYMBOL_GPL(ata_sff_dev_select);
-EXPORT_SYMBOL_GPL(ata_sff_check_status);
-EXPORT_SYMBOL_GPL(ata_sff_dma_pause);
-EXPORT_SYMBOL_GPL(ata_sff_pause);
-EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
-EXPORT_SYMBOL_GPL(ata_sff_wait_ready);
-EXPORT_SYMBOL_GPL(ata_sff_tf_load);
-EXPORT_SYMBOL_GPL(ata_sff_tf_read);
-EXPORT_SYMBOL_GPL(ata_sff_exec_command);
-EXPORT_SYMBOL_GPL(ata_sff_data_xfer);
-EXPORT_SYMBOL_GPL(ata_sff_data_xfer_noirq);
-EXPORT_SYMBOL_GPL(ata_sff_irq_on);
-EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
-EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
-EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
-EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
-EXPORT_SYMBOL_GPL(ata_sff_host_intr);
-EXPORT_SYMBOL_GPL(ata_sff_interrupt);
-EXPORT_SYMBOL_GPL(ata_sff_freeze);
-EXPORT_SYMBOL_GPL(ata_sff_thaw);
-EXPORT_SYMBOL_GPL(ata_sff_prereset);
-EXPORT_SYMBOL_GPL(ata_sff_dev_classify);
-EXPORT_SYMBOL_GPL(ata_sff_wait_after_reset);
-EXPORT_SYMBOL_GPL(ata_sff_softreset);
-EXPORT_SYMBOL_GPL(sata_sff_hardreset);
-EXPORT_SYMBOL_GPL(ata_sff_postreset);
-EXPORT_SYMBOL_GPL(ata_sff_error_handler);
-EXPORT_SYMBOL_GPL(ata_sff_post_internal_cmd);
-EXPORT_SYMBOL_GPL(ata_sff_port_start);
-EXPORT_SYMBOL_GPL(ata_sff_std_ports);
-EXPORT_SYMBOL_GPL(ata_bmdma_mode_filter);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup);
-EXPORT_SYMBOL_GPL(ata_bmdma_start);
-EXPORT_SYMBOL_GPL(ata_bmdma_stop);
-EXPORT_SYMBOL_GPL(ata_bmdma_status);
-EXPORT_SYMBOL_GPL(ata_bus_reset);
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL_GPL(ata_pci_bmdma_clear_simplex);
-EXPORT_SYMBOL_GPL(ata_pci_bmdma_init);
-EXPORT_SYMBOL_GPL(ata_pci_sff_init_host);
-EXPORT_SYMBOL_GPL(ata_pci_sff_prepare_host);
-EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
-EXPORT_SYMBOL_GPL(ata_pci_sff_init_one);
-#endif /* CONFIG_PCI */
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index fe2839e58774..cea8014cd87e 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -79,7 +79,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
unsigned int tag);
extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
-extern void ata_dev_disable(struct ata_device *dev);
extern void ata_pio_queue_task(struct ata_port *ap, void *data,
unsigned long delay);
extern void ata_port_flush_task(struct ata_port *ap);
@@ -100,7 +99,7 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags);
extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
unsigned int readid_flags);
extern int ata_dev_configure(struct ata_device *dev);
-extern int sata_down_spd_limit(struct ata_link *link);
+extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit);
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
extern void ata_sg_clean(struct ata_queued_cmd *qc);
extern void ata_qc_free(struct ata_queued_cmd *qc);
@@ -160,6 +159,7 @@ extern void ata_scsi_error(struct Scsi_Host *host);
extern void ata_port_wait_eh(struct ata_port *ap);
extern void ata_eh_fastdrain_timerfn(unsigned long arg);
extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
+extern void ata_dev_disable(struct ata_device *dev);
extern void ata_eh_detach_dev(struct ata_device *dev);
extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
unsigned int action);
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index e2e332d8ff95..8b77a9802df1 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -13,12 +13,6 @@
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <acpi/acpi_bus.h>
-#include <acpi/acnames.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
-#include <acpi/acexcep.h>
-#include <acpi/acmacros.h>
-#include <acpi/actypes.h>
#include <linux/libata.h>
#include <linux/ata.h>
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 73c466e452ca..eb99dbe78081 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -19,7 +19,9 @@
*
* TODO/CHECK
* Cannot have ATAPI on both master & slave for rev < c2 (???) but
- * otherwise should do atapi DMA.
+ * otherwise should do atapi DMA (For now for old we do PIO only for
+ * ATAPI)
+ * Review Sunblade workaround.
*/
#include <linux/kernel.h>
@@ -33,12 +35,14 @@
#include <linux/dmi.h>
#define DRV_NAME "pata_ali"
-#define DRV_VERSION "0.7.5"
+#define DRV_VERSION "0.7.8"
static int ali_atapi_dma = 0;
module_param_named(atapi_dma, ali_atapi_dma, int, 0644);
MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)");
+static struct pci_dev *ali_isa_bridge;
+
/*
* Cable special cases
*/
@@ -147,8 +151,7 @@ static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int o
pci_read_config_byte(pdev, pio_fifo, &fifo);
fifo &= ~(0x0F << shift);
- if (on)
- fifo |= (on << shift);
+ fifo |= (on << shift);
pci_write_config_byte(pdev, pio_fifo, fifo);
}
@@ -337,6 +340,23 @@ static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
return 0;
}
+static void ali_c2_c3_postreset(struct ata_link *link, unsigned int *classes)
+{
+ u8 r;
+ int port_bit = 4 << link->ap->port_no;
+
+ /* If our bridge is an ALI 1533 then do the extra work */
+ if (ali_isa_bridge) {
+ /* Tristate and re-enable the bus signals */
+ pci_read_config_byte(ali_isa_bridge, 0x58, &r);
+ r &= ~port_bit;
+ pci_write_config_byte(ali_isa_bridge, 0x58, r);
+ r |= port_bit;
+ pci_write_config_byte(ali_isa_bridge, 0x58, r);
+ }
+ ata_sff_postreset(link, classes);
+}
+
static struct scsi_host_template ali_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
@@ -349,10 +369,11 @@ static struct ata_port_operations ali_early_port_ops = {
.inherits = &ata_sff_port_ops,
.cable_detect = ata_cable_40wire,
.set_piomode = ali_set_piomode,
+ .sff_data_xfer = ata_sff_data_xfer32,
};
static const struct ata_port_operations ali_dma_base_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &ata_bmdma32_port_ops,
.set_piomode = ali_set_piomode,
.set_dmamode = ali_set_dmamode,
};
@@ -377,6 +398,17 @@ static struct ata_port_operations ali_c2_port_ops = {
.check_atapi_dma = ali_check_atapi_dma,
.cable_detect = ali_c2_cable_detect,
.dev_config = ali_lock_sectors,
+ .postreset = ali_c2_c3_postreset,
+};
+
+/*
+ * Port operations for DMA capable ALi with cable detect
+ */
+static struct ata_port_operations ali_c4_port_ops = {
+ .inherits = &ali_dma_base_ops,
+ .check_atapi_dma = ali_check_atapi_dma,
+ .cable_detect = ali_c2_cable_detect,
+ .dev_config = ali_lock_sectors,
};
/*
@@ -401,52 +433,49 @@ static struct ata_port_operations ali_c5_port_ops = {
static void ali_init_chipset(struct pci_dev *pdev)
{
u8 tmp;
- struct pci_dev *north, *isa_bridge;
+ struct pci_dev *north;
/*
* The chipset revision selects the driver operations and
* mode data.
*/
- if (pdev->revision >= 0x20 && pdev->revision < 0xC2) {
- /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
- pci_read_config_byte(pdev, 0x4B, &tmp);
- /* Clear CD-ROM DMA write bit */
- tmp &= 0x7F;
- pci_write_config_byte(pdev, 0x4B, tmp);
- } else if (pdev->revision >= 0xC2) {
- /* Enable cable detection logic */
+ if (pdev->revision <= 0x20) {
+ pci_read_config_byte(pdev, 0x53, &tmp);
+ tmp |= 0x03;
+ pci_write_config_byte(pdev, 0x53, tmp);
+ } else {
+ pci_read_config_byte(pdev, 0x4a, &tmp);
+ pci_write_config_byte(pdev, 0x4a, tmp | 0x20);
pci_read_config_byte(pdev, 0x4B, &tmp);
- pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
- }
- north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
- isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
-
- if (north && north->vendor == PCI_VENDOR_ID_AL && isa_bridge) {
- /* Configure the ALi bridge logic. For non ALi rely on BIOS.
- Set the south bridge enable bit */
- pci_read_config_byte(isa_bridge, 0x79, &tmp);
- if (pdev->revision == 0xC2)
- pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
- else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
- pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
- }
- if (pdev->revision >= 0x20) {
+ if (pdev->revision < 0xC2)
+ /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
+ /* Clear CD-ROM DMA write bit */
+ tmp &= 0x7F;
+ /* Cable and UDMA */
+ pci_write_config_byte(pdev, 0x4B, tmp | 0x09);
/*
* CD_ROM DMA on (0x53 bit 0). Enable this even if we want
* to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
* via 0x54/55.
*/
pci_read_config_byte(pdev, 0x53, &tmp);
- if (pdev->revision <= 0x20)
- tmp &= ~0x02;
if (pdev->revision >= 0xc7)
tmp |= 0x03;
else
tmp |= 0x01; /* CD_ROM enable for DMA */
pci_write_config_byte(pdev, 0x53, tmp);
}
- pci_dev_put(isa_bridge);
+ north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+ if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) {
+ /* Configure the ALi bridge logic. For non ALi rely on BIOS.
+ Set the south bridge enable bit */
+ pci_read_config_byte(ali_isa_bridge, 0x79, &tmp);
+ if (pdev->revision == 0xC2)
+ pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x04);
+ else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
+ pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x02);
+ }
pci_dev_put(north);
ata_pci_bmdma_clear_simplex(pdev);
}
@@ -503,7 +532,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA5,
- .port_ops = &ali_c2_port_ops
+ .port_ops = &ali_c4_port_ops
};
/* Revision 0xC5 is UDMA133 with LBA48 DMA */
static const struct ata_port_info info_c5 = {
@@ -516,7 +545,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
const struct ata_port_info *ppi[] = { NULL, NULL };
u8 tmp;
- struct pci_dev *isa_bridge;
int rc;
rc = pcim_enable_device(pdev);
@@ -543,14 +571,12 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
ali_init_chipset(pdev);
- isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
- if (isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
+ if (ali_isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
/* Are we paired with a UDMA capable chip */
- pci_read_config_byte(isa_bridge, 0x5E, &tmp);
+ pci_read_config_byte(ali_isa_bridge, 0x5E, &tmp);
if ((tmp & 0x1E) == 0x12)
ppi[0] = &info_20_udma;
}
- pci_dev_put(isa_bridge);
return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL);
}
@@ -590,13 +616,20 @@ static struct pci_driver ali_pci_driver = {
static int __init ali_init(void)
{
- return pci_register_driver(&ali_pci_driver);
+ int ret;
+ ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+
+ ret = pci_register_driver(&ali_pci_driver);
+ if (ret < 0)
+ pci_dev_put(ali_isa_bridge);
+ return ret;
}
static void __exit ali_exit(void)
{
pci_unregister_driver(&ali_pci_driver);
+ pci_dev_put(ali_isa_bridge);
}
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 0ec9c7d9fe9d..63719ab9ea44 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -24,7 +24,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.3.10"
+#define DRV_VERSION "0.3.11"
/**
* timing_setup - shared timing computation and load
@@ -345,7 +345,7 @@ static struct scsi_host_template amd_sht = {
};
static const struct ata_port_operations amd_base_port_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &ata_bmdma32_port_ops,
.prereset = amd_pre_reset,
};
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 0e2cde8f9973..506adde8ebb3 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -32,21 +32,6 @@ enum {
ATIIXP_IDE_UDMA_MODE = 0x56
};
-static int atiixp_pre_reset(struct ata_link *link, unsigned long deadline)
-{
- struct ata_port *ap = link->ap;
- static const struct pci_bits atiixp_enable_bits[] = {
- { 0x48, 1, 0x01, 0x00 },
- { 0x48, 1, 0x08, 0x00 }
- };
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
- if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
- return -ENOENT;
-
- return ata_sff_prereset(link, deadline);
-}
-
static int atiixp_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -229,10 +214,9 @@ static struct ata_port_operations atiixp_port_ops = {
.cable_detect = atiixp_cable_detect,
.set_piomode = atiixp_set_piomode,
.set_dmamode = atiixp_set_dmamode,
- .prereset = atiixp_pre_reset,
};
-static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.flags = ATA_FLAG_SLAVE_POSS,
@@ -241,8 +225,18 @@ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.udma_mask = 0x3F,
.port_ops = &atiixp_port_ops
};
- const struct ata_port_info *ppi[] = { &info, NULL };
- return ata_pci_sff_init_one(dev, ppi, &atiixp_sht, NULL);
+ static const struct pci_bits atiixp_enable_bits[] = {
+ { 0x48, 1, 0x01, 0x00 },
+ { 0x48, 1, 0x08, 0x00 }
+ };
+ const struct ata_port_info *ppi[] = { &info, &info };
+ int i;
+
+ for (i = 0; i < 2; i++)
+ if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i]))
+ ppi[i] = &ata_dummy_port_info;
+
+ return ata_pci_sff_init_one(pdev, ppi, &atiixp_sht, NULL);
}
static const struct pci_device_id atiixp[] = {
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index e0c4f05d7d57..65c28e5a6cd7 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -30,7 +30,7 @@
#define DRV_VERSION "0.6.2"
struct hpt_clock {
- u8 xfer_speed;
+ u8 xfer_mode;
u32 timing;
};
@@ -189,28 +189,6 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask)
return ata_bmdma_mode_filter(adev, mask);
}
-/**
- * hpt36x_find_mode - reset the hpt36x bus
- * @ap: ATA port
- * @speed: transfer mode
- *
- * Return the 32bit register programming information for this channel
- * that matches the speed provided.
- */
-
-static u32 hpt36x_find_mode(struct ata_port *ap, int speed)
-{
- struct hpt_clock *clocks = ap->host->private_data;
-
- while(clocks->xfer_speed) {
- if (clocks->xfer_speed == speed)
- return clocks->timing;
- clocks++;
- }
- BUG();
- return 0xffffffffU; /* silence compiler warning */
-}
-
static int hpt36x_cable_detect(struct ata_port *ap)
{
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
@@ -226,25 +204,16 @@ static int hpt36x_cable_detect(struct ata_port *ap)
return ATA_CBL_PATA80;
}
-/**
- * hpt366_set_piomode - PIO setup
- * @ap: ATA interface
- * @adev: device on the interface
- *
- * Perform PIO mode setup.
- */
-
-static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void hpt366_set_mode(struct ata_port *ap, struct ata_device *adev,
+ u8 mode)
{
+ struct hpt_clock *clocks = ap->host->private_data;
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- u32 addr1, addr2;
- u32 reg;
- u32 mode;
+ u32 addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
+ u32 addr2 = 0x51 + 4 * ap->port_no;
+ u32 mask, reg;
u8 fast;
- addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
- addr2 = 0x51 + 4 * ap->port_no;
-
/* Fast interrupt prediction disable, hold off interrupt disable */
pci_read_config_byte(pdev, addr2, &fast);
if (fast & 0x80) {
@@ -252,12 +221,43 @@ static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
pci_write_config_byte(pdev, addr2, fast);
}
+ /* determine timing mask and find matching clock entry */
+ if (mode < XFER_MW_DMA_0)
+ mask = 0xc1f8ffff;
+ else if (mode < XFER_UDMA_0)
+ mask = 0x303800ff;
+ else
+ mask = 0x30070000;
+
+ while (clocks->xfer_mode) {
+ if (clocks->xfer_mode == mode)
+ break;
+ clocks++;
+ }
+ if (!clocks->xfer_mode)
+ BUG();
+
+ /*
+ * Combine new mode bits with old config bits and disable
+ * on-chip PIO FIFO/buffer (and PIO MST mode as well) to avoid
+ * problems handling I/O errors later.
+ */
pci_read_config_dword(pdev, addr1, &reg);
- mode = hpt36x_find_mode(ap, adev->pio_mode);
- mode &= ~0x8000000; /* No FIFO in PIO */
- mode &= ~0x30070000; /* Leave config bits alone */
- reg &= 0x30070000; /* Strip timing bits */
- pci_write_config_dword(pdev, addr1, reg | mode);
+ reg = ((reg & ~mask) | (clocks->timing & mask)) & ~0xc0000000;
+ pci_write_config_dword(pdev, addr1, reg);
+}
+
+/**
+ * hpt366_set_piomode - PIO setup
+ * @ap: ATA interface
+ * @adev: device on the interface
+ *
+ * Perform PIO mode setup.
+ */
+
+static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+ hpt366_set_mode(ap, adev, adev->pio_mode);
}
/**
@@ -271,28 +271,7 @@ static void hpt366_set_piomode(struct ata_port *ap, struct ata_device *adev)
static void hpt366_set_dmamode(struct ata_port *ap, struct ata_device *adev)
{
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- u32 addr1, addr2;
- u32 reg;
- u32 mode;
- u8 fast;
-
- addr1 = 0x40 + 4 * (adev->devno + 2 * ap->port_no);
- addr2 = 0x51 + 4 * ap->port_no;
-
- /* Fast interrupt prediction disable, hold off interrupt disable */
- pci_read_config_byte(pdev, addr2, &fast);
- if (fast & 0x80) {
- fast &= ~0x80;
- pci_write_config_byte(pdev, addr2, fast);
- }
-
- pci_read_config_dword(pdev, addr1, &reg);
- mode = hpt36x_find_mode(ap, adev->dma_mode);
- mode |= 0x8000000; /* FIFO in MWDMA or UDMA */
- mode &= ~0xC0000000; /* Leave config bits alone */
- reg &= 0xC0000000; /* Strip timing bits */
- pci_write_config_dword(pdev, addr1, reg | mode);
+ hpt366_set_mode(ap, adev, adev->dma_mode);
}
static struct scsi_host_template hpt36x_sht = {
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index f11a320337c0..f19cc645881a 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -23,7 +23,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt3x3"
-#define DRV_VERSION "0.5.3"
+#define DRV_VERSION "0.6.1"
/**
* hpt3x3_set_piomode - PIO setup
@@ -80,14 +80,48 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */
if (adev->dma_mode >= XFER_UDMA_0)
- r2 |= (0x10 << dn); /* Ultra mode */
+ r2 |= (0x01 << dn); /* Ultra mode */
else
- r2 |= (0x01 << dn); /* MWDMA */
+ r2 |= (0x10 << dn); /* MWDMA */
pci_write_config_dword(pdev, 0x44, r1);
pci_write_config_dword(pdev, 0x48, r2);
}
-#endif /* CONFIG_PATA_HPT3X3_DMA */
+
+/**
+ * hpt3x3_freeze - DMA workaround
+ * @ap: port to freeze
+ *
+ * When freezing an HPT3x3 we must stop any pending DMA before
+ * writing to the control register or the chip will hang
+ */
+
+static void hpt3x3_freeze(struct ata_port *ap)
+{
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
+ iowrite8(ioread8(mmio + ATA_DMA_CMD) & ~ ATA_DMA_START,
+ mmio + ATA_DMA_CMD);
+ ata_sff_dma_pause(ap);
+ ata_sff_freeze(ap);
+}
+
+/**
+ * hpt3x3_bmdma_setup - DMA workaround
+ * @qc: Queued command
+ *
+ * When issuing BMDMA we must clean up the error/active bits in
+ * software on this device
+ */
+
+static void hpt3x3_bmdma_setup(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ u8 r = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ r |= ATA_DMA_INTR | ATA_DMA_ERR;
+ iowrite8(r, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ return ata_bmdma_setup(qc);
+}
/**
* hpt3x3_atapi_dma - ATAPI DMA check
@@ -101,18 +135,23 @@ static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
return 1;
}
+#endif /* CONFIG_PATA_HPT3X3_DMA */
+
static struct scsi_host_template hpt3x3_sht = {
ATA_BMDMA_SHT(DRV_NAME),
};
static struct ata_port_operations hpt3x3_port_ops = {
.inherits = &ata_bmdma_port_ops,
- .check_atapi_dma= hpt3x3_atapi_dma,
.cable_detect = ata_cable_40wire,
.set_piomode = hpt3x3_set_piomode,
#if defined(CONFIG_PATA_HPT3X3_DMA)
.set_dmamode = hpt3x3_set_dmamode,
+ .bmdma_setup = hpt3x3_bmdma_setup,
+ .check_atapi_dma= hpt3x3_atapi_dma,
+ .freeze = hpt3x3_freeze,
#endif
+
};
/**
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index f828a29d7756..f1bb2f9fecbf 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -80,7 +80,7 @@
#define DRV_NAME "pata_it821x"
-#define DRV_VERSION "0.4.0"
+#define DRV_VERSION "0.4.2"
struct it821x_dev
{
@@ -494,8 +494,6 @@ static int it821x_smart_set_mode(struct ata_link *link, struct ata_device **unus
* special. In our case we need to lock the sector count to avoid
* blowing the brains out of the firmware with large LBA48 requests
*
- * FIXME: When FUA appears we need to block FUA too. And SMART and
- * basically we need to filter commands for this chip.
*/
static void it821x_dev_config(struct ata_device *adev)
@@ -890,6 +888,13 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
.flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &it821x_rdc_port_ops
+ };
+ static const struct ata_port_info info_rdc_11 = {
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f,
+ .mwdma_mask = 0x07,
/* No UDMA */
.port_ops = &it821x_rdc_port_ops
};
@@ -903,7 +908,11 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
return rc;
if (pdev->vendor == PCI_VENDOR_ID_RDC) {
- ppi[0] = &info_rdc;
+ /* Deal with Vortex86SX */
+ if (pdev->revision == 0x11)
+ ppi[0] = &info_rdc_11;
+ else
+ ppi[0] = &info_rdc;
} else {
/* Force the card into bypass mode if so requested */
if (it8212_noraid) {
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 7c8faa48b5f3..aa576cac4d17 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -35,7 +35,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_mpiix"
-#define DRV_VERSION "0.7.6"
+#define DRV_VERSION "0.7.7"
enum {
IDETIM = 0x6C, /* IDE control register */
@@ -146,6 +146,7 @@ static struct ata_port_operations mpiix_port_ops = {
.cable_detect = ata_cable_40wire,
.set_piomode = mpiix_set_piomode,
.prereset = mpiix_pre_reset,
+ .sff_data_xfer = ata_sff_data_xfer32,
};
static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
new file mode 100644
index 000000000000..0fe4ef309c62
--- /dev/null
+++ b/drivers/ata/pata_octeon_cf.c
@@ -0,0 +1,965 @@
+/*
+ * Driver for the Octeon bootbus compact flash.
+ *
+ * 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) 2005 - 2009 Cavium Networks
+ * Copyright (C) 2008 Wind River Systems
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/libata.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <scsi/scsi_host.h>
+
+#include <asm/octeon/octeon.h>
+
+/*
+ * The Octeon bootbus compact flash interface is connected in at least
+ * 3 different configurations on various evaluation boards:
+ *
+ * -- 8 bits no irq, no DMA
+ * -- 16 bits no irq, no DMA
+ * -- 16 bits True IDE mode with DMA, but no irq.
+ *
+ * In the last case the DMA engine can generate an interrupt when the
+ * transfer is complete. For the first two cases only PIO is supported.
+ *
+ */
+
+#define DRV_NAME "pata_octeon_cf"
+#define DRV_VERSION "2.1"
+
+
+struct octeon_cf_port {
+ struct workqueue_struct *wq;
+ struct delayed_work delayed_finish;
+ struct ata_port *ap;
+ int dma_finished;
+};
+
+static struct scsi_host_template octeon_cf_sht = {
+ ATA_PIO_SHT(DRV_NAME),
+};
+
+/**
+ * Convert nanosecond based time to setting used in the
+ * boot bus timing register, based on timing multiple
+ */
+static unsigned int ns_to_tim_reg(unsigned int tim_mult, unsigned int nsecs)
+{
+ unsigned int val;
+
+ /*
+ * Compute # of eclock periods to get desired duration in
+ * nanoseconds.
+ */
+ val = DIV_ROUND_UP(nsecs * (octeon_get_clock_rate() / 1000000),
+ 1000 * tim_mult);
+
+ return val;
+}
+
+static void octeon_cf_set_boot_reg_cfg(int cs)
+{
+ union cvmx_mio_boot_reg_cfgx reg_cfg;
+ reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
+ reg_cfg.s.dmack = 0; /* Don't assert DMACK on access */
+ reg_cfg.s.tim_mult = 2; /* Timing mutiplier 2x */
+ reg_cfg.s.rd_dly = 0; /* Sample on falling edge of BOOT_OE */
+ reg_cfg.s.sam = 0; /* Don't combine write and output enable */
+ reg_cfg.s.we_ext = 0; /* No write enable extension */
+ reg_cfg.s.oe_ext = 0; /* No read enable extension */
+ reg_cfg.s.en = 1; /* Enable this region */
+ reg_cfg.s.orbit = 0; /* Don't combine with previous region */
+ reg_cfg.s.ale = 0; /* Don't do address multiplexing */
+ cvmx_write_csr(CVMX_MIO_BOOT_REG_CFGX(cs), reg_cfg.u64);
+}
+
+/**
+ * Called after libata determines the needed PIO mode. This
+ * function programs the Octeon bootbus regions to support the
+ * timing requirements of the PIO mode.
+ *
+ * @ap: ATA port information
+ * @dev: ATA device
+ */
+static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev)
+{
+ struct octeon_cf_data *ocd = ap->dev->platform_data;
+ union cvmx_mio_boot_reg_timx reg_tim;
+ int cs = ocd->base_region;
+ int T;
+ struct ata_timing timing;
+
+ int use_iordy;
+ int trh;
+ int pause;
+ /* These names are timing parameters from the ATA spec */
+ int t1;
+ int t2;
+ int t2i;
+
+ T = (int)(2000000000000LL / octeon_get_clock_rate());
+
+ if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T))
+ BUG();
+
+ t1 = timing.setup;
+ if (t1)
+ t1--;
+ t2 = timing.active;
+ if (t2)
+ t2--;
+ t2i = timing.act8b;
+ if (t2i)
+ t2i--;
+
+ trh = ns_to_tim_reg(2, 20);
+ if (trh)
+ trh--;
+
+ pause = timing.cycle - timing.active - timing.setup - trh;
+ if (pause)
+ pause--;
+
+ octeon_cf_set_boot_reg_cfg(cs);
+ if (ocd->dma_engine >= 0)
+ /* True IDE mode, program both chip selects. */
+ octeon_cf_set_boot_reg_cfg(cs + 1);
+
+
+ use_iordy = ata_pio_need_iordy(dev);
+
+ reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cs));
+ /* Disable page mode */
+ reg_tim.s.pagem = 0;
+ /* Enable dynamic timing */
+ reg_tim.s.waitm = use_iordy;
+ /* Pages are disabled */
+ reg_tim.s.pages = 0;
+ /* We don't use multiplexed address mode */
+ reg_tim.s.ale = 0;
+ /* Not used */
+ reg_tim.s.page = 0;
+ /* Time after IORDY to coninue to assert the data */
+ reg_tim.s.wait = 0;
+ /* Time to wait to complete the cycle. */
+ reg_tim.s.pause = pause;
+ /* How long to hold after a write to de-assert CE. */
+ reg_tim.s.wr_hld = trh;
+ /* How long to wait after a read to de-assert CE. */
+ reg_tim.s.rd_hld = trh;
+ /* How long write enable is asserted */
+ reg_tim.s.we = t2;
+ /* How long read enable is asserted */
+ reg_tim.s.oe = t2;
+ /* Time after CE that read/write starts */
+ reg_tim.s.ce = ns_to_tim_reg(2, 5);
+ /* Time before CE that address is valid */
+ reg_tim.s.adr = 0;
+
+ /* Program the bootbus region timing for the data port chip select. */
+ cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs), reg_tim.u64);
+ if (ocd->dma_engine >= 0)
+ /* True IDE mode, program both chip selects. */
+ cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs + 1), reg_tim.u64);
+}
+
+static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev)
+{
+ struct octeon_cf_data *ocd = dev->link->ap->dev->platform_data;
+ union cvmx_mio_boot_dma_timx dma_tim;
+ unsigned int oe_a;
+ unsigned int oe_n;
+ unsigned int dma_ackh;
+ unsigned int dma_arq;
+ unsigned int pause;
+ unsigned int T0, Tkr, Td;
+ unsigned int tim_mult;
+
+ const struct ata_timing *timing;
+
+ timing = ata_timing_find_mode(dev->dma_mode);
+ T0 = timing->cycle;
+ Td = timing->active;
+ Tkr = timing->recover;
+ dma_ackh = timing->dmack_hold;
+
+ dma_tim.u64 = 0;
+ /* dma_tim.s.tim_mult = 0 --> 4x */
+ tim_mult = 4;
+
+ /* not spec'ed, value in eclocks, not affected by tim_mult */
+ dma_arq = 8;
+ pause = 25 - dma_arq * 1000 /
+ (octeon_get_clock_rate() / 1000000); /* Tz */
+
+ oe_a = Td;
+ /* Tkr from cf spec, lengthened to meet T0 */
+ oe_n = max(T0 - oe_a, Tkr);
+
+ dma_tim.s.dmack_pi = 1;
+
+ dma_tim.s.oe_n = ns_to_tim_reg(tim_mult, oe_n);
+ dma_tim.s.oe_a = ns_to_tim_reg(tim_mult, oe_a);
+
+ /*
+ * This is tI, C.F. spec. says 0, but Sony CF card requires
+ * more, we use 20 nS.
+ */
+ dma_tim.s.dmack_s = ns_to_tim_reg(tim_mult, 20);;
+ dma_tim.s.dmack_h = ns_to_tim_reg(tim_mult, dma_ackh);
+
+ dma_tim.s.dmarq = dma_arq;
+ dma_tim.s.pause = ns_to_tim_reg(tim_mult, pause);
+
+ dma_tim.s.rd_dly = 0; /* Sample right on edge */
+
+ /* writes only */
+ dma_tim.s.we_n = ns_to_tim_reg(tim_mult, oe_n);
+ dma_tim.s.we_a = ns_to_tim_reg(tim_mult, oe_a);
+
+ pr_debug("ns to ticks (mult %d) of %d is: %d\n", tim_mult, 60,
+ ns_to_tim_reg(tim_mult, 60));
+ pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: "
+ "%d, dmarq: %d, pause: %d\n",
+ dma_tim.s.oe_n, dma_tim.s.oe_a, dma_tim.s.dmack_s,
+ dma_tim.s.dmack_h, dma_tim.s.dmarq, dma_tim.s.pause);
+
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_TIMX(ocd->dma_engine),
+ dma_tim.u64);
+
+}
+
+/**
+ * Handle an 8 bit I/O request.
+ *
+ * @dev: Device to access
+ * @buffer: Data buffer
+ * @buflen: Length of the buffer.
+ * @rw: True to write.
+ */
+static unsigned int octeon_cf_data_xfer8(struct ata_device *dev,
+ unsigned char *buffer,
+ unsigned int buflen,
+ int rw)
+{
+ struct ata_port *ap = dev->link->ap;
+ void __iomem *data_addr = ap->ioaddr.data_addr;
+ unsigned long words;
+ int count;
+
+ words = buflen;
+ if (rw) {
+ count = 16;
+ while (words--) {
+ iowrite8(*buffer, data_addr);
+ buffer++;
+ /*
+ * Every 16 writes do a read so the bootbus
+ * FIFO doesn't fill up.
+ */
+ if (--count == 0) {
+ ioread8(ap->ioaddr.altstatus_addr);
+ count = 16;
+ }
+ }
+ } else {
+ ioread8_rep(data_addr, buffer, words);
+ }
+ return buflen;
+}
+
+/**
+ * Handle a 16 bit I/O request.
+ *
+ * @dev: Device to access
+ * @buffer: Data buffer
+ * @buflen: Length of the buffer.
+ * @rw: True to write.
+ */
+static unsigned int octeon_cf_data_xfer16(struct ata_device *dev,
+ unsigned char *buffer,
+ unsigned int buflen,
+ int rw)
+{
+ struct ata_port *ap = dev->link->ap;
+ void __iomem *data_addr = ap->ioaddr.data_addr;
+ unsigned long words;
+ int count;
+
+ words = buflen / 2;
+ if (rw) {
+ count = 16;
+ while (words--) {
+ iowrite16(*(uint16_t *)buffer, data_addr);
+ buffer += sizeof(uint16_t);
+ /*
+ * Every 16 writes do a read so the bootbus
+ * FIFO doesn't fill up.
+ */
+ if (--count == 0) {
+ ioread8(ap->ioaddr.altstatus_addr);
+ count = 16;
+ }
+ }
+ } else {
+ while (words--) {
+ *(uint16_t *)buffer = ioread16(data_addr);
+ buffer += sizeof(uint16_t);
+ }
+ }
+ /* Transfer trailing 1 byte, if any. */
+ if (unlikely(buflen & 0x01)) {
+ __le16 align_buf[1] = { 0 };
+
+ if (rw == READ) {
+ align_buf[0] = cpu_to_le16(ioread16(data_addr));
+ memcpy(buffer, align_buf, 1);
+ } else {
+ memcpy(align_buf, buffer, 1);
+ iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+ }
+ words++;
+ }
+ return buflen;
+}
+
+/**
+ * Read the taskfile for 16bit non-True IDE only.
+ */
+static void octeon_cf_tf_read16(struct ata_port *ap, struct ata_taskfile *tf)
+{
+ u16 blob;
+ /* The base of the registers is at ioaddr.data_addr. */
+ void __iomem *base = ap->ioaddr.data_addr;
+
+ blob = __raw_readw(base + 0xc);
+ tf->feature = blob >> 8;
+
+ blob = __raw_readw(base + 2);
+ tf->nsect = blob & 0xff;
+ tf->lbal = blob >> 8;
+
+ blob = __raw_readw(base + 4);
+ tf->lbam = blob & 0xff;
+ tf->lbah = blob >> 8;
+
+ blob = __raw_readw(base + 6);
+ tf->device = blob & 0xff;
+ tf->command = blob >> 8;
+
+ if (tf->flags & ATA_TFLAG_LBA48) {
+ if (likely(ap->ioaddr.ctl_addr)) {
+ iowrite8(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr);
+
+ blob = __raw_readw(base + 0xc);
+ tf->hob_feature = blob >> 8;
+
+ blob = __raw_readw(base + 2);
+ tf->hob_nsect = blob & 0xff;
+ tf->hob_lbal = blob >> 8;
+
+ blob = __raw_readw(base + 4);
+ tf->hob_lbam = blob & 0xff;
+ tf->hob_lbah = blob >> 8;
+
+ iowrite8(tf->ctl, ap->ioaddr.ctl_addr);
+ ap->last_ctl = tf->ctl;
+ } else {
+ WARN_ON(1);
+ }
+ }
+}
+
+static u8 octeon_cf_check_status16(struct ata_port *ap)
+{
+ u16 blob;
+ void __iomem *base = ap->ioaddr.data_addr;
+
+ blob = __raw_readw(base + 6);
+ return blob >> 8;
+}
+
+static int octeon_cf_softreset16(struct ata_link *link, unsigned int *classes,
+ unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ void __iomem *base = ap->ioaddr.data_addr;
+ int rc;
+ u8 err;
+
+ DPRINTK("about to softreset\n");
+ __raw_writew(ap->ctl, base + 0xe);
+ udelay(20);
+ __raw_writew(ap->ctl | ATA_SRST, base + 0xe);
+ udelay(20);
+ __raw_writew(ap->ctl, base + 0xe);
+
+ rc = ata_sff_wait_after_reset(link, 1, deadline);
+ if (rc) {
+ ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);
+ return rc;
+ }
+
+ /* determine by signature whether we have ATA or ATAPI devices */
+ classes[0] = ata_sff_dev_classify(&link->device[0], 1, &err);
+ DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
+ return 0;
+}
+
+/**
+ * Load the taskfile for 16bit non-True IDE only. The device_addr is
+ * not loaded, we do this as part of octeon_cf_exec_command16.
+ */
+static void octeon_cf_tf_load16(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+ /* The base of the registers is at ioaddr.data_addr. */
+ void __iomem *base = ap->ioaddr.data_addr;
+
+ if (tf->ctl != ap->last_ctl) {
+ iowrite8(tf->ctl, ap->ioaddr.ctl_addr);
+ ap->last_ctl = tf->ctl;
+ ata_wait_idle(ap);
+ }
+ if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+ __raw_writew(tf->hob_feature << 8, base + 0xc);
+ __raw_writew(tf->hob_nsect | tf->hob_lbal << 8, base + 2);
+ __raw_writew(tf->hob_lbam | tf->hob_lbah << 8, base + 4);
+ VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+ tf->hob_feature,
+ tf->hob_nsect,
+ tf->hob_lbal,
+ tf->hob_lbam,
+ tf->hob_lbah);
+ }
+ if (is_addr) {
+ __raw_writew(tf->feature << 8, base + 0xc);
+ __raw_writew(tf->nsect | tf->lbal << 8, base + 2);
+ __raw_writew(tf->lbam | tf->lbah << 8, base + 4);
+ VPRINTK("feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+ tf->feature,
+ tf->nsect,
+ tf->lbal,
+ tf->lbam,
+ tf->lbah);
+ }
+ ata_wait_idle(ap);
+}
+
+
+static void octeon_cf_dev_select(struct ata_port *ap, unsigned int device)
+{
+/* There is only one device, do nothing. */
+ return;
+}
+
+/*
+ * Issue ATA command to host controller. The device_addr is also sent
+ * as it must be written in a combined write with the command.
+ */
+static void octeon_cf_exec_command16(struct ata_port *ap,
+ const struct ata_taskfile *tf)
+{
+ /* The base of the registers is at ioaddr.data_addr. */
+ void __iomem *base = ap->ioaddr.data_addr;
+ u16 blob;
+
+ if (tf->flags & ATA_TFLAG_DEVICE) {
+ VPRINTK("device 0x%X\n", tf->device);
+ blob = tf->device;
+ } else {
+ blob = 0;
+ }
+
+ DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+ blob |= (tf->command << 8);
+ __raw_writew(blob, base + 6);
+
+
+ ata_wait_idle(ap);
+}
+
+static u8 octeon_cf_irq_on(struct ata_port *ap)
+{
+ return 0;
+}
+
+static void octeon_cf_irq_clear(struct ata_port *ap)
+{
+ return;
+}
+
+static void octeon_cf_dma_setup(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct octeon_cf_port *cf_port;
+
+ cf_port = (struct octeon_cf_port *)ap->private_data;
+ DPRINTK("ENTER\n");
+ /* issue r/w command */
+ qc->cursg = qc->sg;
+ cf_port->dma_finished = 0;
+ ap->ops->sff_exec_command(ap, &qc->tf);
+ DPRINTK("EXIT\n");
+}
+
+/**
+ * Start a DMA transfer that was already setup
+ *
+ * @qc: Information about the DMA
+ */
+static void octeon_cf_dma_start(struct ata_queued_cmd *qc)
+{
+ struct octeon_cf_data *ocd = qc->ap->dev->platform_data;
+ union cvmx_mio_boot_dma_cfgx mio_boot_dma_cfg;
+ union cvmx_mio_boot_dma_intx mio_boot_dma_int;
+ struct scatterlist *sg;
+
+ VPRINTK("%d scatterlists\n", qc->n_elem);
+
+ /* Get the scatter list entry we need to DMA into */
+ sg = qc->cursg;
+ BUG_ON(!sg);
+
+ /*
+ * Clear the DMA complete status.
+ */
+ mio_boot_dma_int.u64 = 0;
+ mio_boot_dma_int.s.done = 1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine),
+ mio_boot_dma_int.u64);
+
+ /* Enable the interrupt. */
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine),
+ mio_boot_dma_int.u64);
+
+ /* Set the direction of the DMA */
+ mio_boot_dma_cfg.u64 = 0;
+ mio_boot_dma_cfg.s.en = 1;
+ mio_boot_dma_cfg.s.rw = ((qc->tf.flags & ATA_TFLAG_WRITE) != 0);
+
+ /*
+ * Don't stop the DMA if the device deasserts DMARQ. Many
+ * compact flashes deassert DMARQ for a short time between
+ * sectors. Instead of stopping and restarting the DMA, we'll
+ * let the hardware do it. If the DMA is really stopped early
+ * due to an error condition, a later timeout will force us to
+ * stop.
+ */
+ mio_boot_dma_cfg.s.clr = 0;
+
+ /* Size is specified in 16bit words and minus one notation */
+ mio_boot_dma_cfg.s.size = sg_dma_len(sg) / 2 - 1;
+
+ /* We need to swap the high and low bytes of every 16 bits */
+ mio_boot_dma_cfg.s.swap8 = 1;
+
+ mio_boot_dma_cfg.s.adr = sg_dma_address(sg);
+
+ VPRINTK("%s %d bytes address=%p\n",
+ (mio_boot_dma_cfg.s.rw) ? "write" : "read", sg->length,
+ (void *)(unsigned long)mio_boot_dma_cfg.s.adr);
+
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine),
+ mio_boot_dma_cfg.u64);
+}
+
+/**
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ *
+ */
+static unsigned int octeon_cf_dma_finished(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
+{
+ struct ata_eh_info *ehi = &ap->link.eh_info;
+ struct octeon_cf_data *ocd = ap->dev->platform_data;
+ union cvmx_mio_boot_dma_cfgx dma_cfg;
+ union cvmx_mio_boot_dma_intx dma_int;
+ struct octeon_cf_port *cf_port;
+ u8 status;
+
+ VPRINTK("ata%u: protocol %d task_state %d\n",
+ ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+
+
+ if (ap->hsm_task_state != HSM_ST_LAST)
+ return 0;
+
+ cf_port = (struct octeon_cf_port *)ap->private_data;
+
+ dma_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine));
+ if (dma_cfg.s.size != 0xfffff) {
+ /* Error, the transfer was not complete. */
+ qc->err_mask |= AC_ERR_HOST_BUS;
+ ap->hsm_task_state = HSM_ST_ERR;
+ }
+
+ /* Stop and clear the dma engine. */
+ dma_cfg.u64 = 0;
+ dma_cfg.s.size = -1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine), dma_cfg.u64);
+
+ /* Disable the interrupt. */
+ dma_int.u64 = 0;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine), dma_int.u64);
+
+ /* Clear the DMA complete status */
+ dma_int.s.done = 1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), dma_int.u64);
+
+ status = ap->ops->sff_check_status(ap);
+
+ ata_sff_hsm_move(ap, qc, status, 0);
+
+ if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA))
+ ata_ehi_push_desc(ehi, "DMA stat 0x%x", status);
+
+ return 1;
+}
+
+/*
+ * Check if any queued commands have more DMAs, if so start the next
+ * transfer, else do end of transfer handling.
+ */
+static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance)
+{
+ struct ata_host *host = dev_instance;
+ struct octeon_cf_port *cf_port;
+ int i;
+ unsigned int handled = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ DPRINTK("ENTER\n");
+ for (i = 0; i < host->n_ports; i++) {
+ u8 status;
+ struct ata_port *ap;
+ struct ata_queued_cmd *qc;
+ union cvmx_mio_boot_dma_intx dma_int;
+ union cvmx_mio_boot_dma_cfgx dma_cfg;
+ struct octeon_cf_data *ocd;
+
+ ap = host->ports[i];
+ ocd = ap->dev->platform_data;
+ if (!ap || (ap->flags & ATA_FLAG_DISABLED))
+ continue;
+
+ ocd = ap->dev->platform_data;
+ cf_port = (struct octeon_cf_port *)ap->private_data;
+ dma_int.u64 =
+ cvmx_read_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine));
+ dma_cfg.u64 =
+ cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine));
+
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+
+ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+ (qc->flags & ATA_QCFLAG_ACTIVE)) {
+ if (dma_int.s.done && !dma_cfg.s.en) {
+ if (!sg_is_last(qc->cursg)) {
+ qc->cursg = sg_next(qc->cursg);
+ handled = 1;
+ octeon_cf_dma_start(qc);
+ continue;
+ } else {
+ cf_port->dma_finished = 1;
+ }
+ }
+ if (!cf_port->dma_finished)
+ continue;
+ status = ioread8(ap->ioaddr.altstatus_addr);
+ if (status & (ATA_BUSY | ATA_DRQ)) {
+ /*
+ * We are busy, try to handle it
+ * later. This is the DMA finished
+ * interrupt, and it could take a
+ * little while for the card to be
+ * ready for more commands.
+ */
+ /* Clear DMA irq. */
+ dma_int.u64 = 0;
+ dma_int.s.done = 1;
+ cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine),
+ dma_int.u64);
+
+ queue_delayed_work(cf_port->wq,
+ &cf_port->delayed_finish, 1);
+ handled = 1;
+ } else {
+ handled |= octeon_cf_dma_finished(ap, qc);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+ DPRINTK("EXIT\n");
+ return IRQ_RETVAL(handled);
+}
+
+static void octeon_cf_delayed_finish(struct work_struct *work)
+{
+ struct octeon_cf_port *cf_port = container_of(work,
+ struct octeon_cf_port,
+ delayed_finish.work);
+ struct ata_port *ap = cf_port->ap;
+ struct ata_host *host = ap->host;
+ struct ata_queued_cmd *qc;
+ unsigned long flags;
+ u8 status;
+
+ spin_lock_irqsave(&host->lock, flags);
+
+ /*
+ * If the port is not waiting for completion, it must have
+ * handled it previously. The hsm_task_state is
+ * protected by host->lock.
+ */
+ if (ap->hsm_task_state != HSM_ST_LAST || !cf_port->dma_finished)
+ goto out;
+
+ status = ioread8(ap->ioaddr.altstatus_addr);
+ if (status & (ATA_BUSY | ATA_DRQ)) {
+ /* Still busy, try again. */
+ queue_delayed_work(cf_port->wq,
+ &cf_port->delayed_finish, 1);
+ goto out;
+ }
+ qc = ata_qc_from_tag(ap, ap->link.active_tag);
+ if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+ (qc->flags & ATA_QCFLAG_ACTIVE))
+ octeon_cf_dma_finished(ap, qc);
+out:
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static void octeon_cf_dev_config(struct ata_device *dev)
+{
+ /*
+ * A maximum of 2^20 - 1 16 bit transfers are possible with
+ * the bootbus DMA. So we need to throttle max_sectors to
+ * (2^12 - 1 == 4095) to assure that this can never happen.
+ */
+ dev->max_sectors = min(dev->max_sectors, 4095U);
+}
+
+/*
+ * Trap if driver tries to do standard bmdma commands. They are not
+ * supported.
+ */
+static void unreachable_qc(struct ata_queued_cmd *qc)
+{
+ BUG();
+}
+
+static u8 unreachable_port(struct ata_port *ap)
+{
+ BUG();
+}
+
+/*
+ * We don't do ATAPI DMA so return 0.
+ */
+static int octeon_cf_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ return 0;
+}
+
+static unsigned int octeon_cf_qc_issue(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+ WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+
+ ap->ops->sff_tf_load(ap, &qc->tf); /* load tf registers */
+ octeon_cf_dma_setup(qc); /* set up dma */
+ octeon_cf_dma_start(qc); /* initiate dma */
+ ap->hsm_task_state = HSM_ST_LAST;
+ break;
+
+ case ATAPI_PROT_DMA:
+ dev_err(ap->dev, "Error, ATAPI not supported\n");
+ BUG();
+
+ default:
+ return ata_sff_qc_issue(qc);
+ }
+
+ return 0;
+}
+
+static struct ata_port_operations octeon_cf_ops = {
+ .inherits = &ata_sff_port_ops,
+ .check_atapi_dma = octeon_cf_check_atapi_dma,
+ .qc_prep = ata_noop_qc_prep,
+ .qc_issue = octeon_cf_qc_issue,
+ .sff_dev_select = octeon_cf_dev_select,
+ .sff_irq_on = octeon_cf_irq_on,
+ .sff_irq_clear = octeon_cf_irq_clear,
+ .bmdma_setup = unreachable_qc,
+ .bmdma_start = unreachable_qc,
+ .bmdma_stop = unreachable_qc,
+ .bmdma_status = unreachable_port,
+ .cable_detect = ata_cable_40wire,
+ .set_piomode = octeon_cf_set_piomode,
+ .set_dmamode = octeon_cf_set_dmamode,
+ .dev_config = octeon_cf_dev_config,
+};
+
+static int __devinit octeon_cf_probe(struct platform_device *pdev)
+{
+ struct resource *res_cs0, *res_cs1;
+
+ void __iomem *cs0;
+ void __iomem *cs1 = NULL;
+ struct ata_host *host;
+ struct ata_port *ap;
+ struct octeon_cf_data *ocd;
+ int irq = 0;
+ irq_handler_t irq_handler = NULL;
+ void __iomem *base;
+ struct octeon_cf_port *cf_port;
+
+ res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res_cs0)
+ return -EINVAL;
+
+ ocd = pdev->dev.platform_data;
+
+ cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start,
+ res_cs0->end - res_cs0->start + 1);
+
+ if (!cs0)
+ return -ENOMEM;
+
+ /* Determine from availability of DMA if True IDE mode or not */
+ if (ocd->dma_engine >= 0) {
+ res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res_cs1)
+ return -EINVAL;
+
+ cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start,
+ res_cs0->end - res_cs1->start + 1);
+
+ if (!cs1)
+ return -ENOMEM;
+ }
+
+ cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL);
+ if (!cf_port)
+ return -ENOMEM;
+
+ /* allocate host */
+ host = ata_host_alloc(&pdev->dev, 1);
+ if (!host)
+ goto free_cf_port;
+
+ ap = host->ports[0];
+ ap->private_data = cf_port;
+ cf_port->ap = ap;
+ ap->ops = &octeon_cf_ops;
+ ap->pio_mask = 0x7f; /* Support PIO 0-6 */
+ ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY
+ | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
+
+ base = cs0 + ocd->base_region_bias;
+ if (!ocd->is16bit) {
+ ap->ioaddr.cmd_addr = base;
+ ata_sff_std_ports(&ap->ioaddr);
+
+ ap->ioaddr.altstatus_addr = base + 0xe;
+ ap->ioaddr.ctl_addr = base + 0xe;
+ octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer8;
+ } else if (cs1) {
+ /* Presence of cs1 indicates True IDE mode. */
+ ap->ioaddr.cmd_addr = base + (ATA_REG_CMD << 1) + 1;
+ ap->ioaddr.data_addr = base + (ATA_REG_DATA << 1);
+ ap->ioaddr.error_addr = base + (ATA_REG_ERR << 1) + 1;
+ ap->ioaddr.feature_addr = base + (ATA_REG_FEATURE << 1) + 1;
+ ap->ioaddr.nsect_addr = base + (ATA_REG_NSECT << 1) + 1;
+ ap->ioaddr.lbal_addr = base + (ATA_REG_LBAL << 1) + 1;
+ ap->ioaddr.lbam_addr = base + (ATA_REG_LBAM << 1) + 1;
+ ap->ioaddr.lbah_addr = base + (ATA_REG_LBAH << 1) + 1;
+ ap->ioaddr.device_addr = base + (ATA_REG_DEVICE << 1) + 1;
+ ap->ioaddr.status_addr = base + (ATA_REG_STATUS << 1) + 1;
+ ap->ioaddr.command_addr = base + (ATA_REG_CMD << 1) + 1;
+ ap->ioaddr.altstatus_addr = cs1 + (6 << 1) + 1;
+ ap->ioaddr.ctl_addr = cs1 + (6 << 1) + 1;
+ octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16;
+
+ ap->mwdma_mask = 0x1f; /* Support MWDMA 0-4 */
+ irq = platform_get_irq(pdev, 0);
+ irq_handler = octeon_cf_interrupt;
+
+ /* True IDE mode needs delayed work to poll for not-busy. */
+ cf_port->wq = create_singlethread_workqueue(DRV_NAME);
+ if (!cf_port->wq)
+ goto free_cf_port;
+ INIT_DELAYED_WORK(&cf_port->delayed_finish,
+ octeon_cf_delayed_finish);
+
+ } else {
+ /* 16 bit but not True IDE */
+ octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16;
+ octeon_cf_ops.softreset = octeon_cf_softreset16;
+ octeon_cf_ops.sff_check_status = octeon_cf_check_status16;
+ octeon_cf_ops.sff_tf_read = octeon_cf_tf_read16;
+ octeon_cf_ops.sff_tf_load = octeon_cf_tf_load16;
+ octeon_cf_ops.sff_exec_command = octeon_cf_exec_command16;
+
+ ap->ioaddr.data_addr = base + ATA_REG_DATA;
+ ap->ioaddr.nsect_addr = base + ATA_REG_NSECT;
+ ap->ioaddr.lbal_addr = base + ATA_REG_LBAL;
+ ap->ioaddr.ctl_addr = base + 0xe;
+ ap->ioaddr.altstatus_addr = base + 0xe;
+ }
+
+ ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr);
+
+
+ dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n",
+ (ocd->is16bit) ? 16 : 8,
+ (cs1) ? ", True IDE" : "");
+
+
+ return ata_host_activate(host, irq, irq_handler, 0, &octeon_cf_sht);
+
+free_cf_port:
+ kfree(cf_port);
+ return -ENOMEM;
+}
+
+static struct platform_driver octeon_cf_driver = {
+ .probe = octeon_cf_probe,
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init octeon_cf_init(void)
+{
+ return platform_driver_register(&octeon_cf_driver);
+}
+
+
+MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
+MODULE_DESCRIPTION("low-level driver for Cavium OCTEON Compact Flash PATA");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+MODULE_ALIAS("platform:" DRV_NAME);
+
+module_init(octeon_cf_init);
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 6afa07a37648..d8d743af3225 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -186,7 +186,7 @@ EXPORT_SYMBOL_GPL(__pata_platform_probe);
* A platform bus ATA device has been unplugged. Perform the needed
* cleanup. Also called on module unload for any active devices.
*/
-int __devexit __pata_platform_remove(struct device *dev)
+int __pata_platform_remove(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
index 3080f371222c..f1b26f7c8e4d 100644
--- a/drivers/ata/pata_qdi.c
+++ b/drivers/ata/pata_qdi.c
@@ -12,7 +12,7 @@
*
* Probe code based on drivers/ide/legacy/qd65xx.c
* Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@fnac.net>
+ * Samuel Thibault <samuel.thibault@ens-lyon.org>
*/
#include <linux/kernel.h>
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index c2e6fb9f2ef9..ebfcda26d639 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -63,8 +63,6 @@ static inline void rb532_pata_finish_io(struct ata_port *ap)
ata_sff_sync might be sufficient. */
ata_sff_dma_pause(ap);
ndelay(RB500_CF_IO_DELAY);
-
- set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
}
static void rb532_pata_exec_command(struct ata_port *ap,
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 83580a59db58..9e764e5747e6 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -32,7 +32,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_sil680"
-#define DRV_VERSION "0.4.8"
+#define DRV_VERSION "0.4.9"
#define SIL680_MMIO_BAR 5
@@ -195,7 +195,7 @@ static struct scsi_host_template sil680_sht = {
};
static struct ata_port_operations sil680_port_ops = {
- .inherits = &ata_bmdma_port_ops,
+ .inherits = &ata_bmdma32_port_ops,
.cable_detect = sil680_cable_detect,
.set_piomode = sil680_set_piomode,
.set_dmamode = sil680_set_dmamode,
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 681169c9c640..79a6c9a0b721 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -86,6 +86,10 @@ enum {
VIA_SATA_PATA = 0x800, /* SATA/PATA combined configuration */
};
+enum {
+ VIA_IDFLAG_SINGLE = (1 << 0), /* single channel controller) */
+};
+
/*
* VIA SouthBridge chips.
*/
@@ -97,8 +101,12 @@ static const struct via_isa_bridge {
u8 rev_max;
u16 flags;
} via_isa_bridges[] = {
+ { "vx855", PCI_DEVICE_ID_VIA_VX855, 0x00, 0x2f,
+ VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
{ "vx800", PCI_DEVICE_ID_VIA_VX800, 0x00, 0x2f, VIA_UDMA_133 |
VIA_BAD_AST | VIA_SATA_PATA },
+ { "vt8261", PCI_DEVICE_ID_VIA_8261, 0x00, 0x2f,
+ VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
@@ -122,6 +130,8 @@ static const struct via_isa_bridge {
{ "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
{ "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
{ "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+ { "vtxxxx", PCI_DEVICE_ID_VIA_ANON, 0x00, 0x2f,
+ VIA_UDMA_133 | VIA_BAD_AST },
{ NULL }
};
@@ -460,6 +470,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static int printed_version;
u8 enable;
u32 timing;
+ unsigned long flags = id->driver_data;
int rc;
if (!printed_version++)
@@ -469,9 +480,13 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
+ if (flags & VIA_IDFLAG_SINGLE)
+ ppi[1] = &ata_dummy_port_info;
+
/* To find out how the IDE will behave and what features we
actually have to look at the bridge not the IDE controller */
- for (config = via_isa_bridges; config->id; config++)
+ for (config = via_isa_bridges; config->id != PCI_DEVICE_ID_VIA_ANON;
+ config++)
if ((isa = pci_get_device(PCI_VENDOR_ID_VIA +
!!(config->flags & VIA_BAD_ID),
config->id, NULL))) {
@@ -482,10 +497,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_dev_put(isa);
}
- if (!config->id) {
- printk(KERN_WARNING "via: Unknown VIA SouthBridge, disabling.\n");
- return -ENODEV;
- }
pci_dev_put(isa);
if (!(config->flags & VIA_NO_ENABLES)) {
@@ -587,6 +598,7 @@ static const struct pci_device_id via[] = {
{ PCI_VDEVICE(VIA, 0x1571), },
{ PCI_VDEVICE(VIA, 0x3164), },
{ PCI_VDEVICE(VIA, 0x5324), },
+ { PCI_VDEVICE(VIA, 0xC409), VIA_IDFLAG_SINGLE },
{ },
};
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 1a56db92ff7a..55bc88c1707b 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -1288,7 +1288,7 @@ static const struct ata_port_info sata_fsl_port_info[] = {
static int sata_fsl_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
- int retval = 0;
+ int retval = -ENXIO;
void __iomem *hcr_base = NULL;
void __iomem *ssr_base = NULL;
void __iomem *csr_base = NULL;
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 86918634a4c5..4ae1a4138b47 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -33,10 +33,6 @@
*
* --> ATAPI support (Marvell claims the 60xx/70xx chips can do it).
*
- * --> Investigate problems with PCI Message Signalled Interrupts (MSI).
- *
- * --> Cache frequently-accessed registers in mv_port_priv to reduce overhead.
- *
* --> Develop a low-power-consumption strategy, and implement it.
*
* --> [Experiment, low priority] Investigate interrupt coalescing.
@@ -72,7 +68,7 @@
#include <linux/libata.h>
#define DRV_NAME "sata_mv"
-#define DRV_VERSION "1.24"
+#define DRV_VERSION "1.25"
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -351,8 +347,6 @@ enum {
EDMA_HALTCOND_OFS = 0x60, /* GenIIe halt conditions */
- GEN_II_NCQ_MAX_SECTORS = 256, /* max sects/io on Gen2 w/NCQ */
-
/* Host private flags (hp_flags) */
MV_HP_FLAG_MSI = (1 << 0),
MV_HP_ERRATA_50XXB0 = (1 << 1),
@@ -669,8 +663,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
/* RocketRAID 1720/174x have different identifiers */
{ PCI_VDEVICE(TTI, 0x1720), chip_6042 },
- { PCI_VDEVICE(TTI, 0x1740), chip_508x },
- { PCI_VDEVICE(TTI, 0x1742), chip_508x },
+ { PCI_VDEVICE(TTI, 0x1740), chip_6042 },
+ { PCI_VDEVICE(TTI, 0x1742), chip_6042 },
{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
@@ -883,19 +877,15 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
struct mv_host_priv *hpriv = ap->host->private_data;
int hardport = mv_hardport_from_port(ap->port_no);
void __iomem *hc_mmio = mv_hc_base_from_port(
- mv_host_base(ap->host), hardport);
- u32 hc_irq_cause, ipending;
+ mv_host_base(ap->host), ap->port_no);
+ u32 hc_irq_cause;
/* clear EDMA event indicators, if any */
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
- /* clear EDMA interrupt indicator, if any */
- hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
- ipending = (DEV_IRQ | DMA_IRQ) << hardport;
- if (hc_irq_cause & ipending) {
- writelfl(hc_irq_cause & ~ipending,
- hc_mmio + HC_IRQ_CAUSE_OFS);
- }
+ /* clear pending irq events */
+ hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport);
+ writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
mv_edma_cfg(ap, want_ncq);
@@ -1099,20 +1089,12 @@ static void mv6_dev_config(struct ata_device *adev)
*
* Gen-II does not support NCQ over a port multiplier
* (no FIS-based switching).
- *
- * We don't have hob_nsect when doing NCQ commands on Gen-II.
- * See mv_qc_prep() for more info.
*/
if (adev->flags & ATA_DFLAG_NCQ) {
if (sata_pmp_attached(adev->link->ap)) {
adev->flags &= ~ATA_DFLAG_NCQ;
ata_dev_printk(adev, KERN_INFO,
"NCQ disabled for command-based switching\n");
- } else if (adev->max_sectors > GEN_II_NCQ_MAX_SECTORS) {
- adev->max_sectors = GEN_II_NCQ_MAX_SECTORS;
- ata_dev_printk(adev, KERN_INFO,
- "max_sectors limited to %u for NCQ\n",
- adev->max_sectors);
}
}
}
@@ -1450,7 +1432,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
* only 11 bytes...so we must pick and choose required
* registers based on the command. So, we drop feature and
* hob_feature for [RW] DMA commands, but they are needed for
- * NCQ. NCQ will drop hob_nsect.
+ * NCQ. NCQ will drop hob_nsect, which is not needed there
+ * (nsect is used only for the tag; feat/hob_feat hold true nsect).
*/
switch (tf->command) {
case ATA_CMD_READ:
@@ -2214,9 +2197,15 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
struct ata_host *host = dev_instance;
struct mv_host_priv *hpriv = host->private_data;
unsigned int handled = 0;
+ int using_msi = hpriv->hp_flags & MV_HP_FLAG_MSI;
u32 main_irq_cause, pending_irqs;
spin_lock(&host->lock);
+
+ /* for MSI: block new interrupts while in here */
+ if (using_msi)
+ writel(0, hpriv->main_irq_mask_addr);
+
main_irq_cause = readl(hpriv->main_irq_cause_addr);
pending_irqs = main_irq_cause & hpriv->main_irq_mask;
/*
@@ -2230,6 +2219,11 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
handled = mv_host_intr(host, pending_irqs);
}
spin_unlock(&host->lock);
+
+ /* for MSI: unmask; interrupt cause bits will retrigger now */
+ if (using_msi)
+ writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr);
+
return IRQ_RETVAL(handled);
}
@@ -2821,8 +2815,7 @@ static void mv_eh_thaw(struct ata_port *ap)
writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
/* clear pending irq events */
- hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
- hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
+ hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport);
writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
mv_enable_port_irqs(ap, ERR_IRQ);
@@ -3075,6 +3068,9 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
}
+ /* initialize shadow irq mask with register's value */
+ hpriv->main_irq_mask = readl(hpriv->main_irq_mask_addr);
+
/* global interrupt mask: 0 == mask everything */
mv_set_main_irq_mask(host, ~0, 0);
@@ -3430,9 +3426,9 @@ static int mv_pci_init_one(struct pci_dev *pdev,
if (rc)
return rc;
- /* Enable interrupts */
- if (msi && pci_enable_msi(pdev))
- pci_intx(pdev, 1);
+ /* Enable message-switched interrupts, if requested */
+ if (msi && pci_enable_msi(pdev) == 0)
+ hpriv->hp_flags |= MV_HP_FLAG_MSI;
mv_dump_pci_cfg(pdev, 0x68);
mv_print_info(host);
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 6f1460614325..444af0415ca1 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -305,10 +305,10 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
+static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
static void nv_nf2_freeze(struct ata_port *ap);
static void nv_nf2_thaw(struct ata_port *ap);
-static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline);
static void nv_ck804_freeze(struct ata_port *ap);
static void nv_ck804_thaw(struct ata_port *ap);
static int nv_adma_slave_config(struct scsi_device *sdev);
@@ -352,6 +352,7 @@ enum nv_host_type
NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
CK804,
ADMA,
+ MCP5x,
SWNCQ,
};
@@ -363,10 +364,10 @@ static const struct pci_device_id nv_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), SWNCQ },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), SWNCQ },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), SWNCQ },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), SWNCQ },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), MCP5x },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), MCP5x },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), MCP5x },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), MCP5x },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
@@ -432,14 +433,19 @@ static struct ata_port_operations nv_nf2_ops = {
.inherits = &nv_common_ops,
.freeze = nv_nf2_freeze,
.thaw = nv_nf2_thaw,
- .hardreset = nv_nf2_hardreset,
+ .hardreset = nv_noclassify_hardreset,
};
-/* CK804 finally gets hardreset right */
+/* For initial probing after boot and hot plugging, hardreset mostly
+ * works fine on CK804 but curiously, reprobing on the initial port by
+ * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS
+ * in somewhat undeterministic way. Use noclassify hardreset.
+ */
static struct ata_port_operations nv_ck804_ops = {
.inherits = &nv_common_ops,
.freeze = nv_ck804_freeze,
.thaw = nv_ck804_thaw,
+ .hardreset = nv_noclassify_hardreset,
.host_stop = nv_ck804_host_stop,
};
@@ -467,8 +473,19 @@ static struct ata_port_operations nv_adma_ops = {
.host_stop = nv_adma_host_stop,
};
+/* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to
+ * work, hardreset should be used and hardreset can't report proper
+ * signature, which suggests that mcp5x is closer to nf2 as long as
+ * reset quirkiness is concerned. Define separate ops for mcp5x with
+ * nv_noclassify_hardreset().
+ */
+static struct ata_port_operations nv_mcp5x_ops = {
+ .inherits = &nv_common_ops,
+ .hardreset = nv_noclassify_hardreset,
+};
+
static struct ata_port_operations nv_swncq_ops = {
- .inherits = &nv_generic_ops,
+ .inherits = &nv_mcp5x_ops,
.qc_defer = ata_std_qc_defer,
.qc_prep = nv_swncq_qc_prep,
@@ -531,6 +548,15 @@ static const struct ata_port_info nv_port_info[] = {
.port_ops = &nv_adma_ops,
.private_data = NV_PI_PRIV(nv_adma_interrupt, &nv_adma_sht),
},
+ /* MCP5x */
+ {
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+ .pio_mask = NV_PIO_MASK,
+ .mwdma_mask = NV_MWDMA_MASK,
+ .udma_mask = NV_UDMA_MASK,
+ .port_ops = &nv_mcp5x_ops,
+ .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht),
+ },
/* SWNCQ */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
@@ -1530,6 +1556,17 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
return 0;
}
+static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ bool online;
+ int rc;
+
+ rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
+ &online, NULL);
+ return online ? -EAGAIN : rc;
+}
+
static void nv_nf2_freeze(struct ata_port *ap)
{
void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
@@ -1554,17 +1591,6 @@ static void nv_nf2_thaw(struct ata_port *ap)
iowrite8(mask, scr_addr + NV_INT_ENABLE);
}
-static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
- unsigned long deadline)
-{
- bool online;
- int rc;
-
- rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
- &online, NULL);
- return online ? -EAGAIN : rc;
-}
-
static void nv_ck804_freeze(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
@@ -2355,14 +2381,9 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (type == CK804 && adma_enabled) {
dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
type = ADMA;
- }
-
- if (type == SWNCQ) {
- if (swncq_enabled)
- dev_printk(KERN_NOTICE, &pdev->dev,
- "Using SWNCQ mode\n");
- else
- type = GENERIC;
+ } else if (type == MCP5x && swncq_enabled) {
+ dev_printk(KERN_NOTICE, &pdev->dev, "Using SWNCQ mode\n");
+ type = SWNCQ;
}
ppi[0] = &nv_port_info[type];
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 564c142b03b0..d0091609e210 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -44,6 +44,7 @@
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <linux/libata.h>
+#include <linux/dmi.h>
#define DRV_NAME "sata_sil"
#define DRV_VERSION "2.4"
@@ -323,7 +324,7 @@ static void sil_fill_sg(struct ata_queued_cmd *qc)
prd->addr = cpu_to_le32(addr);
prd->flags_len = cpu_to_le32(sg_len);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, sg_len);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len);
last_prd = prd;
prd++;
@@ -695,11 +696,38 @@ static void sil_init_controller(struct ata_host *host)
}
}
+static bool sil_broken_system_poweroff(struct pci_dev *pdev)
+{
+ static const struct dmi_system_id broken_systems[] = {
+ {
+ .ident = "HP Compaq nx6325",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"),
+ },
+ /* PCI slot number of the controller */
+ .driver_data = (void *)0x12UL,
+ },
+
+ { } /* terminate list */
+ };
+ const struct dmi_system_id *dmi = dmi_first_match(broken_systems);
+
+ if (dmi) {
+ unsigned long slot = (unsigned long)dmi->driver_data;
+ /* apply the quirk only to on-board controllers */
+ return slot == PCI_SLOT(pdev->devfn);
+ }
+
+ return false;
+}
+
static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version;
int board_id = ent->driver_data;
- const struct ata_port_info *ppi[] = { &sil_port_info[board_id], NULL };
+ struct ata_port_info pi = sil_port_info[board_id];
+ const struct ata_port_info *ppi[] = { &pi, NULL };
struct ata_host *host;
void __iomem *mmio_base;
int n_ports, rc;
@@ -713,6 +741,13 @@ static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (board_id == sil_3114)
n_ports = 4;
+ if (sil_broken_system_poweroff(pdev)) {
+ pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN |
+ ATA_FLAG_NO_HIBERNATE_SPINDOWN;
+ dev_info(&pdev->dev, "quirky BIOS, skipping spindown "
+ "on poweroff and hibernation\n");
+ }
+
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
if (!host)
return -ENOMEM;
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index ccee930f1e12..2590c2279fa7 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -51,13 +51,6 @@ struct sil24_sge {
__le32 flags;
};
-/*
- * Port multiplier
- */
-struct sil24_port_multiplier {
- __le32 diag;
- __le32 sactive;
-};
enum {
SIL24_HOST_BAR = 0,
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index c18935f0bda2..5c62da9cd491 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -92,6 +92,8 @@ static const struct pci_device_id svia_pci_tbl[] = {
{ PCI_VDEVICE(VIA, 0x5372), vt6420 },
{ PCI_VDEVICE(VIA, 0x7372), vt6420 },
{ PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */
+ { PCI_VDEVICE(VIA, 0x9000), vt8251 },
+ { PCI_VDEVICE(VIA, 0x9040), vt8251 },
{ } /* terminate list */
};
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index 088885ed51b9..e1c7611e9144 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -64,7 +64,7 @@
#include <linux/jiffies.h>
#include "iphase.h"
#include "suni.h"
-#define swap(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
+#define swap_byte_order(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
#define PRIV(dev) ((struct suni_priv *) dev->phy_data)
@@ -1306,7 +1306,7 @@ static void rx_dle_intr(struct atm_dev *dev)
// get real pkt length pwang_test
trailer = (struct cpcs_trailer*)((u_char *)skb->data +
skb->len - sizeof(*trailer));
- length = swap(trailer->length);
+ length = swap_byte_order(trailer->length);
if ((length > iadev->rx_buf_sz) || (length >
(skb->len - sizeof(struct cpcs_trailer))))
{
@@ -2995,7 +2995,7 @@ static int ia_pkt_tx (struct atm_vcc *vcc, struct sk_buff *skb) {
skb->len, PCI_DMA_TODEVICE);
wr_ptr->local_pkt_addr = (buf_desc_ptr->buf_start_hi << 16) |
buf_desc_ptr->buf_start_lo;
- /* wr_ptr->bytes = swap(total_len); didn't seem to affect ?? */
+ /* wr_ptr->bytes = swap_byte_order(total_len); didn't seem to affect?? */
wr_ptr->bytes = skb->len;
/* hw bug - DLEs of 0x2d, 0x2e, 0x2f cause DMA lockup */
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index d8e8c49c0cbd..8f006f96ff53 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -54,7 +54,7 @@ config FIRMWARE_IN_KERNEL
such firmware, and do not wish to use an initrd.
This single option controls the inclusion of firmware for
- every driver which uses request_firmare() and ships its
+ every driver which uses request_firmware() and ships its
firmware in the kernel source tree, to avoid a proliferation
of 'Include firmware for xxx device' options.
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index c66637392bbc..b5b8ba512b28 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
obj-$(CONFIG_SMP) += topology.o
+obj-$(CONFIG_IOMMU_API) += iommu.o
ifeq ($(CONFIG_SYSFS),y)
obj-$(CONFIG_MODULES) += module.o
endif
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index f57652db0a2a..b9cda053d3c0 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -167,7 +167,7 @@ attribute_container_add_device(struct device *dev,
ic->classdev.parent = get_device(dev);
ic->classdev.class = cont->class;
cont->class->dev_release = attribute_container_release;
- strcpy(ic->classdev.bus_id, dev->bus_id);
+ dev_set_name(&ic->classdev, dev_name(dev));
if (fn)
fn(cont, dev, &ic->classdev);
else
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 5aee1c0169ea..83f32b891fa9 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -333,7 +333,7 @@ static int match_name(struct device *dev, void *data)
{
const char *name = data;
- return sysfs_streq(name, dev->bus_id);
+ return sysfs_streq(name, dev_name(dev));
}
/**
@@ -461,12 +461,12 @@ int bus_add_device(struct device *dev)
int error = 0;
if (bus) {
- pr_debug("bus: '%s': add device %s\n", bus->name, dev->bus_id);
+ pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
error = device_add_attrs(bus, dev);
if (error)
goto out_put;
error = sysfs_create_link(&bus->p->devices_kset->kobj,
- &dev->kobj, dev->bus_id);
+ &dev->kobj, dev_name(dev));
if (error)
goto out_id;
error = sysfs_create_link(&dev->kobj,
@@ -482,7 +482,7 @@ int bus_add_device(struct device *dev)
out_deprecated:
sysfs_remove_link(&dev->kobj, "subsystem");
out_subsys:
- sysfs_remove_link(&bus->p->devices_kset->kobj, dev->bus_id);
+ sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));
out_id:
device_remove_attrs(bus, dev);
out_put:
@@ -526,13 +526,13 @@ void bus_remove_device(struct device *dev)
sysfs_remove_link(&dev->kobj, "subsystem");
remove_deprecated_bus_links(dev);
sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
- dev->bus_id);
+ dev_name(dev));
device_remove_attrs(dev->bus, dev);
if (klist_node_attached(&dev->knode_bus))
klist_del(&dev->knode_bus);
pr_debug("bus: '%s': remove device %s\n",
- dev->bus->name, dev->bus_id);
+ dev->bus->name, dev_name(dev));
device_release_driver(dev);
bus_put(dev->bus);
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8c2cc2648f5a..f3eae630e589 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -119,7 +119,7 @@ static void device_release(struct kobject *kobj)
else
WARN(1, KERN_ERR "Device '%s' does not have a release() "
"function, it is broken and must be fixed.\n",
- dev->bus_id);
+ dev_name(dev));
}
static struct kobj_type device_ktype = {
@@ -209,7 +209,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
retval = dev->bus->uevent(dev, env);
if (retval)
pr_debug("device: '%s': %s: bus uevent() returned %d\n",
- dev->bus_id, __func__, retval);
+ dev_name(dev), __func__, retval);
}
/* have the class specific function add its stuff */
@@ -217,7 +217,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
retval = dev->class->dev_uevent(dev, env);
if (retval)
pr_debug("device: '%s': %s: class uevent() "
- "returned %d\n", dev->bus_id,
+ "returned %d\n", dev_name(dev),
__func__, retval);
}
@@ -226,7 +226,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
retval = dev->type->uevent(dev, env);
if (retval)
pr_debug("device: '%s': %s: dev_type uevent() "
- "returned %d\n", dev->bus_id,
+ "returned %d\n", dev_name(dev),
__func__, retval);
}
@@ -672,7 +672,7 @@ static int device_add_class_symlinks(struct device *dev)
if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev)) {
error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
- &dev->kobj, dev->bus_id);
+ &dev->kobj, dev_name(dev));
if (error)
goto out_subsys;
}
@@ -712,11 +712,11 @@ out_busid:
if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev))
sysfs_remove_link(&dev->class->p->class_subsys.kobj,
- dev->bus_id);
+ dev_name(dev));
#else
/* link in the class directory pointing to the device */
error = sysfs_create_link(&dev->class->p->class_subsys.kobj,
- &dev->kobj, dev->bus_id);
+ &dev->kobj, dev_name(dev));
if (error)
goto out_subsys;
@@ -729,7 +729,7 @@ out_busid:
return 0;
out_busid:
- sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev_name(dev));
#endif
out_subsys:
@@ -758,12 +758,12 @@ static void device_remove_class_symlinks(struct device *dev)
if (dev->kobj.parent != &dev->class->p->class_subsys.kobj &&
device_is_not_partition(dev))
sysfs_remove_link(&dev->class->p->class_subsys.kobj,
- dev->bus_id);
+ dev_name(dev));
#else
if (dev->parent && device_is_not_partition(dev))
sysfs_remove_link(&dev->kobj, "device");
- sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id);
+ sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev_name(dev));
#endif
sysfs_remove_link(&dev->kobj, "subsystem");
@@ -777,10 +777,16 @@ static void device_remove_class_symlinks(struct device *dev)
int dev_set_name(struct device *dev, const char *fmt, ...)
{
va_list vargs;
+ char *s;
va_start(vargs, fmt);
vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs);
va_end(vargs);
+
+ /* ewww... some of these buggers have / in the name... */
+ while ((s = strchr(dev->bus_id, '/')))
+ *s = '!';
+
return 0;
}
EXPORT_SYMBOL_GPL(dev_set_name);
@@ -866,7 +872,7 @@ int device_add(struct device *dev)
if (!strlen(dev->bus_id))
goto done;
- pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
parent = get_device(dev->parent);
setup_parent(dev, parent);
@@ -876,7 +882,7 @@ int device_add(struct device *dev)
set_dev_node(dev, dev_to_node(parent));
/* first, register with generic layer. */
- error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);
+ error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev_name(dev));
if (error)
goto Error;
@@ -884,11 +890,6 @@ int device_add(struct device *dev)
if (platform_notify)
platform_notify(dev);
- /* notify clients of device entry (new way) */
- if (dev->bus)
- blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- BUS_NOTIFY_ADD_DEVICE, dev);
-
error = device_create_file(dev, &uevent_attr);
if (error)
goto attrError;
@@ -916,6 +917,14 @@ int device_add(struct device *dev)
if (error)
goto DPMError;
device_pm_add(dev);
+
+ /* Notify clients of device addition. This call must come
+ * after dpm_sysf_add() and before kobject_uevent().
+ */
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ BUS_NOTIFY_ADD_DEVICE, dev);
+
kobject_uevent(&dev->kobj, KOBJ_ADD);
bus_attach_device(dev);
if (parent)
@@ -940,9 +949,6 @@ done:
DPMError:
bus_remove_device(dev);
BusError:
- if (dev->bus)
- blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- BUS_NOTIFY_DEL_DEVICE, dev);
device_remove_attrs(dev);
AttrsError:
device_remove_class_symlinks(dev);
@@ -1027,6 +1033,12 @@ void device_del(struct device *dev)
struct device *parent = dev->parent;
struct class_interface *class_intf;
+ /* Notify clients of device removal. This call must come
+ * before dpm_sysfs_remove().
+ */
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ BUS_NOTIFY_DEL_DEVICE, dev);
device_pm_remove(dev);
dpm_sysfs_remove(dev);
if (parent)
@@ -1064,9 +1076,6 @@ void device_del(struct device *dev)
*/
if (platform_notify_remove)
platform_notify_remove(dev);
- if (dev->bus)
- blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- BUS_NOTIFY_DEL_DEVICE, dev);
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
cleanup_device_parent(dev);
kobject_del(&dev->kobj);
@@ -1086,7 +1095,7 @@ void device_del(struct device *dev)
*/
void device_unregister(struct device *dev)
{
- pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
device_del(dev);
put_device(dev);
}
@@ -1196,10 +1205,101 @@ EXPORT_SYMBOL_GPL(put_device);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
+struct root_device
+{
+ struct device dev;
+ struct module *owner;
+};
+
+#define to_root_device(dev) container_of(dev, struct root_device, dev)
+
+static void root_device_release(struct device *dev)
+{
+ kfree(to_root_device(dev));
+}
+
+/**
+ * __root_device_register - allocate and register a root device
+ * @name: root device name
+ * @owner: owner module of the root device, usually THIS_MODULE
+ *
+ * This function allocates a root device and registers it
+ * using device_register(). In order to free the returned
+ * device, use root_device_unregister().
+ *
+ * Root devices are dummy devices which allow other devices
+ * to be grouped under /sys/devices. Use this function to
+ * allocate a root device and then use it as the parent of
+ * any device which should appear under /sys/devices/{name}
+ *
+ * The /sys/devices/{name} directory will also contain a
+ * 'module' symlink which points to the @owner directory
+ * in sysfs.
+ *
+ * Note: You probably want to use root_device_register().
+ */
+struct device *__root_device_register(const char *name, struct module *owner)
+{
+ struct root_device *root;
+ int err = -ENOMEM;
+
+ root = kzalloc(sizeof(struct root_device), GFP_KERNEL);
+ if (!root)
+ return ERR_PTR(err);
+
+ err = dev_set_name(&root->dev, name);
+ if (err) {
+ kfree(root);
+ return ERR_PTR(err);
+ }
+
+ root->dev.release = root_device_release;
+
+ err = device_register(&root->dev);
+ if (err) {
+ put_device(&root->dev);
+ return ERR_PTR(err);
+ }
+
+#ifdef CONFIG_MODULE /* gotta find a "cleaner" way to do this */
+ if (owner) {
+ struct module_kobject *mk = &owner->mkobj;
+
+ err = sysfs_create_link(&root->dev.kobj, &mk->kobj, "module");
+ if (err) {
+ device_unregister(&root->dev);
+ return ERR_PTR(err);
+ }
+ root->owner = owner;
+ }
+#endif
+
+ return &root->dev;
+}
+EXPORT_SYMBOL_GPL(__root_device_register);
+
+/**
+ * root_device_unregister - unregister and free a root device
+ * @dev: device going away
+ *
+ * This function unregisters and cleans up a device that was created by
+ * root_device_register().
+ */
+void root_device_unregister(struct device *dev)
+{
+ struct root_device *root = to_root_device(dev);
+
+ if (root->owner)
+ sysfs_remove_link(&root->dev.kobj, "module");
+
+ device_unregister(dev);
+}
+EXPORT_SYMBOL_GPL(root_device_unregister);
+
static void device_create_release(struct device *dev)
{
- pr_debug("device: '%s': %s\n", dev->bus_id, __func__);
+ pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
kfree(dev);
}
@@ -1344,7 +1444,7 @@ int device_rename(struct device *dev, char *new_name)
if (!dev)
return -EINVAL;
- pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
+ pr_debug("device: '%s': %s: renaming to '%s'\n", dev_name(dev),
__func__, new_name);
#ifdef CONFIG_SYSFS_DEPRECATED
@@ -1381,7 +1481,7 @@ int device_rename(struct device *dev, char *new_name)
#else
if (dev->class) {
error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj,
- &dev->kobj, dev->bus_id);
+ &dev->kobj, dev_name(dev));
if (error)
goto out;
sysfs_remove_link(&dev->class->p->class_subsys.kobj,
@@ -1459,8 +1559,8 @@ int device_move(struct device *dev, struct device *new_parent)
new_parent = get_device(new_parent);
new_parent_kobj = get_device_parent(dev, new_parent);
- pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
- __func__, new_parent ? new_parent->bus_id : "<NULL>");
+ pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev),
+ __func__, new_parent ? dev_name(new_parent) : "<NULL>");
error = kobject_move(&dev->kobj, new_parent_kobj);
if (error) {
cleanup_glue_dir(dev, new_parent_kobj);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 64f5d54f7edc..719ee5c1c8d9 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -109,7 +109,7 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
*/
static ssize_t print_cpus_map(char *buf, cpumask_t *map)
{
- int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *map);
+ int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map);
buf[n++] = '\n';
buf[n] = '\0';
@@ -128,10 +128,54 @@ print_cpus_func(online);
print_cpus_func(possible);
print_cpus_func(present);
+/*
+ * Print values for NR_CPUS and offlined cpus
+ */
+static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf)
+{
+ int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
+ return n;
+}
+static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
+
+/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
+unsigned int total_cpus;
+
+static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
+{
+ int n = 0, len = PAGE_SIZE-2;
+ cpumask_var_t offline;
+
+ /* display offline cpus < nr_cpu_ids */
+ if (!alloc_cpumask_var(&offline, GFP_KERNEL))
+ return -ENOMEM;
+ cpumask_complement(offline, cpu_online_mask);
+ n = cpulist_scnprintf(buf, len, offline);
+ free_cpumask_var(offline);
+
+ /* display offline cpus >= nr_cpu_ids */
+ if (total_cpus && nr_cpu_ids < total_cpus) {
+ if (n && n < len)
+ buf[n++] = ',';
+
+ if (nr_cpu_ids == total_cpus-1)
+ n += snprintf(&buf[n], len - n, "%d", nr_cpu_ids);
+ else
+ n += snprintf(&buf[n], len - n, "%d-%d",
+ nr_cpu_ids, total_cpus-1);
+ }
+
+ n += snprintf(&buf[n], len - n, "\n");
+ return n;
+}
+static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
+
static struct sysdev_class_attribute *cpu_state_attr[] = {
&attr_online_map,
&attr_possible_map,
&attr_present_map,
+ &attr_kernel_max,
+ &attr_offline,
};
static int cpu_states_init(void)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 20febc00a525..315bed8d5e7f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -34,7 +34,7 @@ static void driver_bound(struct device *dev)
return;
}
- pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->bus_id,
+ pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev),
__func__, dev->driver->name);
if (dev->bus)
@@ -104,13 +104,13 @@ static int really_probe(struct device *dev, struct device_driver *drv)
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
- drv->bus->name, __func__, drv->name, dev->bus_id);
+ drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
- __func__, dev->bus_id);
+ __func__, dev_name(dev));
goto probe_failed;
}
@@ -127,7 +127,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
- drv->bus->name, __func__, dev->bus_id, drv->name);
+ drv->bus->name, __func__, dev_name(dev), drv->name);
goto done;
probe_failed:
@@ -139,7 +139,7 @@ probe_failed:
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
- drv->name, dev->bus_id, ret);
+ drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
@@ -194,7 +194,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
goto done;
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
- drv->bus->name, __func__, dev->bus_id, drv->name);
+ drv->bus->name, __func__, dev_name(dev), drv->name);
ret = really_probe(dev, drv);
@@ -298,7 +298,6 @@ static void __device_release_driver(struct device *dev)
drv = dev->driver;
if (drv) {
driver_sysfs_remove(dev);
- sysfs_remove_link(&dev->kobj, "driver");
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index b7e571031ecd..44699d9dd85c 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -291,12 +291,6 @@ firmware_class_timeout(u_long data)
fw_load_abort(fw_priv);
}
-static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
-{
- /* XXX warning we should watch out for name collisions */
- strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
-}
-
static int fw_register_device(struct device **dev_p, const char *fw_name,
struct device *device)
{
@@ -321,7 +315,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
fw_priv->timeout.data = (u_long) fw_priv;
init_timer(&fw_priv->timeout);
- fw_setup_device_id(f_dev, device);
+ dev_set_name(f_dev, dev_name(device));
f_dev->parent = device;
f_dev->class = &firmware_class;
dev_set_drvdata(f_dev, fw_priv);
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c
new file mode 100644
index 000000000000..5e039d4f877c
--- /dev/null
+++ b/drivers/base/iommu.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2007-2008 Advanced Micro Devices, Inc.
+ * Author: Joerg Roedel <joerg.roedel@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bug.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/iommu.h>
+
+static struct iommu_ops *iommu_ops;
+
+void register_iommu(struct iommu_ops *ops)
+{
+ if (iommu_ops)
+ BUG();
+
+ iommu_ops = ops;
+}
+
+bool iommu_found()
+{
+ return iommu_ops != NULL;
+}
+EXPORT_SYMBOL_GPL(iommu_found);
+
+struct iommu_domain *iommu_domain_alloc(void)
+{
+ struct iommu_domain *domain;
+ int ret;
+
+ domain = kmalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain)
+ return NULL;
+
+ ret = iommu_ops->domain_init(domain);
+ if (ret)
+ goto out_free;
+
+ return domain;
+
+out_free:
+ kfree(domain);
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(iommu_domain_alloc);
+
+void iommu_domain_free(struct iommu_domain *domain)
+{
+ iommu_ops->domain_destroy(domain);
+ kfree(domain);
+}
+EXPORT_SYMBOL_GPL(iommu_domain_free);
+
+int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
+{
+ return iommu_ops->attach_dev(domain, dev);
+}
+EXPORT_SYMBOL_GPL(iommu_attach_device);
+
+void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
+{
+ iommu_ops->detach_dev(domain, dev);
+}
+EXPORT_SYMBOL_GPL(iommu_detach_device);
+
+int iommu_map_range(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, size_t size, int prot)
+{
+ return iommu_ops->map(domain, iova, paddr, size, prot);
+}
+EXPORT_SYMBOL_GPL(iommu_map_range);
+
+void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova,
+ size_t size)
+{
+ iommu_ops->unmap(domain, iova, size);
+}
+EXPORT_SYMBOL_GPL(iommu_unmap_range);
+
+phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,
+ unsigned long iova)
+{
+ return iommu_ops->iova_to_phys(domain, iova);
+}
+EXPORT_SYMBOL_GPL(iommu_iova_to_phys);
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
index efd577574948..479694b6cbe3 100644
--- a/drivers/base/isa.c
+++ b/drivers/base/isa.c
@@ -11,7 +11,7 @@
#include <linux/isa.h>
static struct device isa_bus = {
- .bus_id = "isa"
+ .init_name = "isa"
};
struct isa_dev {
@@ -135,9 +135,8 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
isa_dev->dev.parent = &isa_bus;
isa_dev->dev.bus = &isa_bus_type;
- snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u",
- isa_driver->driver.name, id);
-
+ dev_set_name(&isa_dev->dev, "%s.%u",
+ isa_driver->driver.name, id);
isa_dev->dev.platform_data = isa_driver;
isa_dev->dev.release = isa_dev_release;
isa_dev->id = id;
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 5260e9e0df48..989429cfed88 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -347,8 +347,9 @@ static inline int memory_probe_init(void)
* section belongs to...
*/
-static int add_memory_block(unsigned long node_id, struct mem_section *section,
- unsigned long state, int phys_device)
+static int add_memory_block(int nid, struct mem_section *section,
+ unsigned long state, int phys_device,
+ enum mem_add_context context)
{
struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
int ret = 0;
@@ -370,6 +371,10 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
ret = mem_create_simple_file(mem, phys_device);
if (!ret)
ret = mem_create_simple_file(mem, removable);
+ if (!ret) {
+ if (context == HOTPLUG)
+ ret = register_mem_sect_under_node(mem, nid);
+ }
return ret;
}
@@ -382,7 +387,7 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section,
*
* This could be made generic for all sysdev classes.
*/
-static struct memory_block *find_memory_block(struct mem_section *section)
+struct memory_block *find_memory_block(struct mem_section *section)
{
struct kobject *kobj;
struct sys_device *sysdev;
@@ -411,6 +416,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
struct memory_block *mem;
mem = find_memory_block(section);
+ unregister_mem_sect_under_nodes(mem);
mem_remove_simple_file(mem, phys_index);
mem_remove_simple_file(mem, state);
mem_remove_simple_file(mem, phys_device);
@@ -424,9 +430,9 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
* need an interface for the VM to add new memory regions,
* but without onlining it.
*/
-int register_new_memory(struct mem_section *section)
+int register_new_memory(int nid, struct mem_section *section)
{
- return add_memory_block(0, section, MEM_OFFLINE, 0);
+ return add_memory_block(nid, section, MEM_OFFLINE, 0, HOTPLUG);
}
int unregister_memory_section(struct mem_section *section)
@@ -458,7 +464,8 @@ int __init memory_dev_init(void)
for (i = 0; i < NR_MEM_SECTIONS; i++) {
if (!present_section_nr(i))
continue;
- err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE, 0);
+ err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
+ 0, BOOT);
if (!ret)
ret = err;
}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index f5207090885a..43fa90b837ee 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
+#include <linux/memory.h>
#include <linux/node.h>
#include <linux/hugetlb.h>
#include <linux/cpumask.h>
@@ -30,8 +31,8 @@ static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf)
BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
len = type?
- cpulist_scnprintf(buf, PAGE_SIZE-2, *mask):
- cpumask_scnprintf(buf, PAGE_SIZE-2, *mask);
+ cpulist_scnprintf(buf, PAGE_SIZE-2, mask) :
+ cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
buf[len++] = '\n';
buf[len] = '\0';
return len;
@@ -248,6 +249,105 @@ int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
return 0;
}
+#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
+#define page_initialized(page) (page->lru.next)
+
+static int get_nid_for_pfn(unsigned long pfn)
+{
+ struct page *page;
+
+ if (!pfn_valid_within(pfn))
+ return -1;
+ page = pfn_to_page(pfn);
+ if (!page_initialized(page))
+ return -1;
+ return pfn_to_nid(pfn);
+}
+
+/* register memory section under specified node if it spans that node */
+int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
+{
+ unsigned long pfn, sect_start_pfn, sect_end_pfn;
+
+ if (!mem_blk)
+ return -EFAULT;
+ if (!node_online(nid))
+ return 0;
+ sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
+ sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
+ for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
+ int page_nid;
+
+ page_nid = get_nid_for_pfn(pfn);
+ if (page_nid < 0)
+ continue;
+ if (page_nid != nid)
+ continue;
+ return sysfs_create_link_nowarn(&node_devices[nid].sysdev.kobj,
+ &mem_blk->sysdev.kobj,
+ kobject_name(&mem_blk->sysdev.kobj));
+ }
+ /* mem section does not span the specified node */
+ return 0;
+}
+
+/* unregister memory section under all nodes that it spans */
+int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
+{
+ nodemask_t unlinked_nodes;
+ unsigned long pfn, sect_start_pfn, sect_end_pfn;
+
+ if (!mem_blk)
+ return -EFAULT;
+ nodes_clear(unlinked_nodes);
+ sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
+ sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
+ for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
+ unsigned int nid;
+
+ nid = get_nid_for_pfn(pfn);
+ if (nid < 0)
+ continue;
+ if (!node_online(nid))
+ continue;
+ if (node_test_and_set(nid, unlinked_nodes))
+ continue;
+ sysfs_remove_link(&node_devices[nid].sysdev.kobj,
+ kobject_name(&mem_blk->sysdev.kobj));
+ }
+ return 0;
+}
+
+static int link_mem_sections(int nid)
+{
+ unsigned long start_pfn = NODE_DATA(nid)->node_start_pfn;
+ unsigned long end_pfn = start_pfn + NODE_DATA(nid)->node_spanned_pages;
+ unsigned long pfn;
+ int err = 0;
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ unsigned long section_nr = pfn_to_section_nr(pfn);
+ struct mem_section *mem_sect;
+ struct memory_block *mem_blk;
+ int ret;
+
+ if (!present_section_nr(section_nr))
+ continue;
+ mem_sect = __nr_to_section(section_nr);
+ mem_blk = find_memory_block(mem_sect);
+ ret = register_mem_sect_under_node(mem_blk, nid);
+ if (!err)
+ err = ret;
+
+ /* discard ref obtained in find_memory_block() */
+ kobject_put(&mem_blk->sysdev.kobj);
+ }
+ return err;
+}
+#else
+static int link_mem_sections(int nid) { return 0; }
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
int register_one_node(int nid)
{
int error = 0;
@@ -267,6 +367,9 @@ int register_one_node(int nid)
if (cpu_to_node(cpu) == nid)
register_cpu_under_node(cpu, nid);
}
+
+ /* link memory sections under this node */
+ error = link_mem_sections(nid);
}
return error;
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index dfcbfe504867..349a1013603f 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -24,7 +24,7 @@
driver))
struct device platform_bus = {
- .bus_id = "platform",
+ .init_name = "platform",
};
EXPORT_SYMBOL_GPL(platform_bus);
@@ -242,16 +242,15 @@ int platform_device_add(struct platform_device *pdev)
pdev->dev.bus = &platform_bus_type;
if (pdev->id != -1)
- snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,
- pdev->id);
+ dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
else
- strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
+ dev_set_name(&pdev->dev, pdev->name);
for (i = 0; i < pdev->num_resources; i++) {
struct resource *p, *r = &pdev->resource[i];
if (r->name == NULL)
- r->name = pdev->dev.bus_id;
+ r->name = dev_name(&pdev->dev);
p = r->parent;
if (!p) {
@@ -264,14 +263,14 @@ int platform_device_add(struct platform_device *pdev)
if (p && insert_resource(p, r)) {
printk(KERN_ERR
"%s: failed to claim resource %d\n",
- pdev->dev.bus_id, i);
+ dev_name(&pdev->dev), i);
ret = -EBUSY;
goto failed;
}
}
pr_debug("Registering platform device '%s'. Parent at %s\n",
- pdev->dev.bus_id, pdev->dev.parent->bus_id);
+ dev_name(&pdev->dev), dev_name(pdev->dev.parent));
ret = device_add(&pdev->dev);
if (ret == 0)
@@ -503,8 +502,6 @@ int platform_driver_register(struct platform_driver *drv)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
drv->driver.resume = platform_drv_resume;
- if (drv->pm)
- drv->driver.pm = &drv->pm->base;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -609,7 +606,7 @@ static int platform_match(struct device *dev, struct device_driver *drv)
struct platform_device *pdev;
pdev = container_of(dev, struct platform_device, dev);
- return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
+ return (strcmp(pdev->name, drv->name) == 0);
}
#ifdef CONFIG_PM_SLEEP
@@ -686,7 +683,10 @@ static int platform_pm_suspend(struct device *dev)
struct device_driver *drv = dev->driver;
int ret = 0;
- if (drv && drv->pm) {
+ if (!drv)
+ return 0;
+
+ if (drv->pm) {
if (drv->pm->suspend)
ret = drv->pm->suspend(dev);
} else {
@@ -698,16 +698,15 @@ static int platform_pm_suspend(struct device *dev)
static int platform_pm_suspend_noirq(struct device *dev)
{
- struct platform_driver *pdrv;
+ struct device_driver *drv = dev->driver;
int ret = 0;
- if (!dev->driver)
+ if (!drv)
return 0;
- pdrv = to_platform_driver(dev->driver);
- if (pdrv->pm) {
- if (pdrv->pm->suspend_noirq)
- ret = pdrv->pm->suspend_noirq(dev);
+ if (drv->pm) {
+ if (drv->pm->suspend_noirq)
+ ret = drv->pm->suspend_noirq(dev);
} else {
ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND);
}
@@ -720,7 +719,10 @@ static int platform_pm_resume(struct device *dev)
struct device_driver *drv = dev->driver;
int ret = 0;
- if (drv && drv->pm) {
+ if (!drv)
+ return 0;
+
+ if (drv->pm) {
if (drv->pm->resume)
ret = drv->pm->resume(dev);
} else {
@@ -732,16 +734,15 @@ static int platform_pm_resume(struct device *dev)
static int platform_pm_resume_noirq(struct device *dev)
{
- struct platform_driver *pdrv;
+ struct device_driver *drv = dev->driver;
int ret = 0;
- if (!dev->driver)
+ if (!drv)
return 0;
- pdrv = to_platform_driver(dev->driver);
- if (pdrv->pm) {
- if (pdrv->pm->resume_noirq)
- ret = pdrv->pm->resume_noirq(dev);
+ if (drv->pm) {
+ if (drv->pm->resume_noirq)
+ ret = drv->pm->resume_noirq(dev);
} else {
ret = platform_legacy_resume_early(dev);
}
@@ -780,16 +781,15 @@ static int platform_pm_freeze(struct device *dev)
static int platform_pm_freeze_noirq(struct device *dev)
{
- struct platform_driver *pdrv;
+ struct device_driver *drv = dev->driver;
int ret = 0;
- if (!dev->driver)
+ if (!drv)
return 0;
- pdrv = to_platform_driver(dev->driver);
- if (pdrv->pm) {
- if (pdrv->pm->freeze_noirq)
- ret = pdrv->pm->freeze_noirq(dev);
+ if (drv->pm) {
+ if (drv->pm->freeze_noirq)
+ ret = drv->pm->freeze_noirq(dev);
} else {
ret = platform_legacy_suspend_late(dev, PMSG_FREEZE);
}
@@ -802,7 +802,10 @@ static int platform_pm_thaw(struct device *dev)
struct device_driver *drv = dev->driver;
int ret = 0;
- if (drv && drv->pm) {
+ if (!drv)
+ return 0;
+
+ if (drv->pm) {
if (drv->pm->thaw)
ret = drv->pm->thaw(dev);
} else {
@@ -814,16 +817,15 @@ static int platform_pm_thaw(struct device *dev)
static int platform_pm_thaw_noirq(struct device *dev)
{
- struct platform_driver *pdrv;
+ struct device_driver *drv = dev->driver;
int ret = 0;
- if (!dev->driver)
+ if (!drv)
return 0;
- pdrv = to_platform_driver(dev->driver);
- if (pdrv->pm) {
- if (pdrv->pm->thaw_noirq)
- ret = pdrv->pm->thaw_noirq(dev);
+ if (drv->pm) {
+ if (drv->pm->thaw_noirq)
+ ret = drv->pm->thaw_noirq(dev);
} else {
ret = platform_legacy_resume_early(dev);
}
@@ -836,7 +838,10 @@ static int platform_pm_poweroff(struct device *dev)
struct device_driver *drv = dev->driver;
int ret = 0;
- if (drv && drv->pm) {
+ if (!drv)
+ return 0;
+
+ if (drv->pm) {
if (drv->pm->poweroff)
ret = drv->pm->poweroff(dev);
} else {
@@ -848,16 +853,15 @@ static int platform_pm_poweroff(struct device *dev)
static int platform_pm_poweroff_noirq(struct device *dev)
{
- struct platform_driver *pdrv;
+ struct device_driver *drv = dev->driver;
int ret = 0;
- if (!dev->driver)
+ if (!drv)
return 0;
- pdrv = to_platform_driver(dev->driver);
- if (pdrv->pm) {
- if (pdrv->pm->poweroff_noirq)
- ret = pdrv->pm->poweroff_noirq(dev);
+ if (drv->pm) {
+ if (drv->pm->poweroff_noirq)
+ ret = drv->pm->poweroff_noirq(dev);
} else {
ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE);
}
@@ -870,7 +874,10 @@ static int platform_pm_restore(struct device *dev)
struct device_driver *drv = dev->driver;
int ret = 0;
- if (drv && drv->pm) {
+ if (!drv)
+ return 0;
+
+ if (drv->pm) {
if (drv->pm->restore)
ret = drv->pm->restore(dev);
} else {
@@ -882,16 +889,15 @@ static int platform_pm_restore(struct device *dev)
static int platform_pm_restore_noirq(struct device *dev)
{
- struct platform_driver *pdrv;
+ struct device_driver *drv = dev->driver;
int ret = 0;
- if (!dev->driver)
+ if (!drv)
return 0;
- pdrv = to_platform_driver(dev->driver);
- if (pdrv->pm) {
- if (pdrv->pm->restore_noirq)
- ret = pdrv->pm->restore_noirq(dev);
+ if (drv->pm) {
+ if (drv->pm->restore_noirq)
+ ret = drv->pm->restore_noirq(dev);
} else {
ret = platform_legacy_resume_early(dev);
}
@@ -912,17 +918,15 @@ static int platform_pm_restore_noirq(struct device *dev)
#endif /* !CONFIG_HIBERNATION */
-static struct pm_ext_ops platform_pm_ops = {
- .base = {
- .prepare = platform_pm_prepare,
- .complete = platform_pm_complete,
- .suspend = platform_pm_suspend,
- .resume = platform_pm_resume,
- .freeze = platform_pm_freeze,
- .thaw = platform_pm_thaw,
- .poweroff = platform_pm_poweroff,
- .restore = platform_pm_restore,
- },
+static struct dev_pm_ops platform_dev_pm_ops = {
+ .prepare = platform_pm_prepare,
+ .complete = platform_pm_complete,
+ .suspend = platform_pm_suspend,
+ .resume = platform_pm_resume,
+ .freeze = platform_pm_freeze,
+ .thaw = platform_pm_thaw,
+ .poweroff = platform_pm_poweroff,
+ .restore = platform_pm_restore,
.suspend_noirq = platform_pm_suspend_noirq,
.resume_noirq = platform_pm_resume_noirq,
.freeze_noirq = platform_pm_freeze_noirq,
@@ -931,7 +935,7 @@ static struct pm_ext_ops platform_pm_ops = {
.restore_noirq = platform_pm_restore_noirq,
};
-#define PLATFORM_PM_OPS_PTR &platform_pm_ops
+#define PLATFORM_PM_OPS_PTR (&platform_dev_pm_ops)
#else /* !CONFIG_PM_SLEEP */
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 692c20ba5144..670c9d6c1407 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -76,7 +76,7 @@ void device_pm_add(struct device *dev)
if (dev->parent) {
if (dev->parent->power.status >= DPM_SUSPENDING)
dev_warn(dev, "parent %s should not be sleeping\n",
- dev->parent->bus_id);
+ dev_name(dev->parent));
} else if (transition_started) {
/*
* We refuse to register parentless devices while a PM
@@ -112,7 +112,8 @@ void device_pm_remove(struct device *dev)
* @ops: PM operations to choose from.
* @state: PM transition of the system being carried out.
*/
-static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state)
+static int pm_op(struct device *dev, struct dev_pm_ops *ops,
+ pm_message_t state)
{
int error = 0;
@@ -174,7 +175,7 @@ static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state)
* The operation is executed with interrupts disabled by the only remaining
* functional CPU in the system.
*/
-static int pm_noirq_op(struct device *dev, struct pm_ext_ops *ops,
+static int pm_noirq_op(struct device *dev, struct dev_pm_ops *ops,
pm_message_t state)
{
int error = 0;
@@ -354,7 +355,7 @@ static int resume_device(struct device *dev, pm_message_t state)
if (dev->bus) {
if (dev->bus->pm) {
pm_dev_dbg(dev, state, "");
- error = pm_op(dev, &dev->bus->pm->base, state);
+ error = pm_op(dev, dev->bus->pm, state);
} else if (dev->bus->resume) {
pm_dev_dbg(dev, state, "legacy ");
error = dev->bus->resume(dev);
@@ -451,9 +452,9 @@ static void complete_device(struct device *dev, pm_message_t state)
dev->type->pm->complete(dev);
}
- if (dev->bus && dev->bus->pm && dev->bus->pm->base.complete) {
+ if (dev->bus && dev->bus->pm && dev->bus->pm->complete) {
pm_dev_dbg(dev, state, "completing ");
- dev->bus->pm->base.complete(dev);
+ dev->bus->pm->complete(dev);
}
up(&dev->sem);
@@ -624,7 +625,7 @@ static int suspend_device(struct device *dev, pm_message_t state)
if (dev->bus) {
if (dev->bus->pm) {
pm_dev_dbg(dev, state, "");
- error = pm_op(dev, &dev->bus->pm->base, state);
+ error = pm_op(dev, dev->bus->pm, state);
} else if (dev->bus->suspend) {
pm_dev_dbg(dev, state, "legacy ");
error = dev->bus->suspend(dev, state);
@@ -685,10 +686,10 @@ static int prepare_device(struct device *dev, pm_message_t state)
down(&dev->sem);
- if (dev->bus && dev->bus->pm && dev->bus->pm->base.prepare) {
+ if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
pm_dev_dbg(dev, state, "preparing ");
- error = dev->bus->pm->base.prepare(dev);
- suspend_report_result(dev->bus->pm->base.prepare, error);
+ error = dev->bus->pm->prepare(dev);
+ suspend_report_result(dev->bus->pm->prepare, error);
if (error)
goto End;
}
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 2aa6e8fc4def..0a1a2c4dbc6e 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -140,7 +140,7 @@ static unsigned int hash_string(unsigned int seed, const char *data, unsigned in
void set_trace_device(struct device *dev)
{
- dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH);
+ dev_hash_value = hash_string(DEVSEED, dev_name(dev), DEVHASH);
}
EXPORT_SYMBOL(set_trace_device);
@@ -192,7 +192,7 @@ static int show_dev_hash(unsigned int value)
while (entry != &dpm_list) {
struct device * dev = to_device(entry);
- unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
+ unsigned int hash = hash_string(DEVSEED, dev_name(dev), DEVHASH);
if (hash == value) {
dev_info(dev, "hash matches\n");
match++;
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 199cd97e32e6..a778fb52b11f 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -28,6 +28,7 @@
#include <linux/mm.h>
#include <linux/cpu.h>
#include <linux/module.h>
+#include <linux/hardirq.h>
#include <linux/topology.h>
#define define_one_ro(_name) \
@@ -49,8 +50,8 @@ static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf)
if (len > 1) {
n = type?
- cpulist_scnprintf(buf, len-2, *mask):
- cpumask_scnprintf(buf, len-2, *mask);
+ cpulist_scnprintf(buf, len-2, mask) :
+ cpumask_scnprintf(buf, len-2, mask);
buf[n++] = '\n';
buf[n] = '\0';
}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 4b1d4ac960f1..8df436ff7068 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -156,7 +156,7 @@ static volatile int fdc_busy = -1;
static volatile int fdc_nested;
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
-static DECLARE_WAIT_QUEUE_HEAD(motor_wait);
+static DECLARE_COMPLETION(motor_on_completion);
static volatile int selected = -1; /* currently selected drive */
@@ -184,8 +184,7 @@ static unsigned char mfmencode[16]={
static unsigned char mfmdecode[128];
/* floppy internal millisecond timer stuff */
-static volatile int ms_busy = -1;
-static DECLARE_WAIT_QUEUE_HEAD(ms_wait);
+static DECLARE_COMPLETION(ms_wait_completion);
#define MS_TICKS ((amiga_eclock+50)/1000)
/*
@@ -211,8 +210,7 @@ static int fd_device[4] = { 0, 0, 0, 0 };
static irqreturn_t ms_isr(int irq, void *dummy)
{
- ms_busy = -1;
- wake_up(&ms_wait);
+ complete(&ms_wait_completion);
return IRQ_HANDLED;
}
@@ -220,19 +218,17 @@ static irqreturn_t ms_isr(int irq, void *dummy)
A more generic routine would do a schedule a la timer.device */
static void ms_delay(int ms)
{
- unsigned long flags;
int ticks;
+ static DEFINE_MUTEX(mutex);
+
if (ms > 0) {
- local_irq_save(flags);
- while (ms_busy == 0)
- sleep_on(&ms_wait);
- ms_busy = 0;
- local_irq_restore(flags);
+ mutex_lock(&mutex);
ticks = MS_TICKS*ms-1;
ciaa.tblo=ticks%256;
ciaa.tbhi=ticks/256;
ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */
- sleep_on(&ms_wait);
+ wait_for_completion(&ms_wait_completion);
+ mutex_unlock(&mutex);
}
}
@@ -254,8 +250,7 @@ static void get_fdc(int drive)
printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
#endif
local_irq_save(flags);
- while (!try_fdc(drive))
- sleep_on(&fdc_wait);
+ wait_event(fdc_wait, try_fdc(drive));
fdc_busy = drive;
fdc_nested++;
local_irq_restore(flags);
@@ -330,7 +325,7 @@ static void fd_deselect (int drive)
static void motor_on_callback(unsigned long nr)
{
if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
- wake_up (&motor_wait);
+ complete_all(&motor_on_completion);
} else {
motor_on_timer.expires = jiffies + HZ/10;
add_timer(&motor_on_timer);
@@ -347,11 +342,12 @@ static int fd_motor_on(int nr)
unit[nr].motor = 1;
fd_select(nr);
+ INIT_COMPLETION(motor_on_completion);
motor_on_timer.data = nr;
mod_timer(&motor_on_timer, jiffies + HZ/2);
on_attempts = 10;
- sleep_on (&motor_wait);
+ wait_for_completion(&motor_on_completion);
fd_deselect(nr);
}
@@ -582,8 +578,7 @@ static void raw_read(int drive)
{
drive&=3;
get_fdc(drive);
- while (block_flag)
- sleep_on(&wait_fd_block);
+ wait_event(wait_fd_block, !block_flag);
fd_select(drive);
/* setup adkcon bits correctly */
custom.adkcon = ADK_MSBSYNC;
@@ -598,8 +593,7 @@ static void raw_read(int drive)
block_flag = 1;
- while (block_flag)
- sleep_on (&wait_fd_block);
+ wait_event(wait_fd_block, !block_flag);
custom.dsklen = 0;
fd_deselect(drive);
@@ -616,8 +610,7 @@ static int raw_write(int drive)
rel_fdc();
return 0;
}
- while (block_flag)
- sleep_on(&wait_fd_block);
+ wait_event(wait_fd_block, !block_flag);
fd_select(drive);
/* clear adkcon bits */
custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
@@ -1294,8 +1287,7 @@ static int non_int_flush_track (unsigned long nr)
writepending = 0;
return 0;
}
- while (block_flag == 2)
- sleep_on (&wait_fd_block);
+ wait_event(wait_fd_block, block_flag != 2);
}
else {
local_irq_restore(flags);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7bcc1d8bc967..34f80fa6fed1 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -406,6 +406,7 @@ static int nbd_do_it(struct nbd_device *lo)
ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
if (ret) {
printk(KERN_ERR "nbd: sysfs_create_file failed!");
+ lo->pid = 0;
return ret;
}
@@ -413,6 +414,7 @@ static int nbd_do_it(struct nbd_device *lo)
nbd_end_request(req);
sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr);
+ lo->pid = 0;
return 0;
}
@@ -648,6 +650,8 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_DO_IT:
+ if (lo->pid)
+ return -EBUSY;
if (!lo->file)
return -EINVAL;
thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 936466f62afd..bccc42bb9212 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -141,7 +141,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
start_sector = req->sector * priv->blocking_factor;
sectors = req->nr_sectors * priv->blocking_factor;
- dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+ dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
__func__, __LINE__, op, sectors, start_sector);
if (write) {
@@ -178,7 +178,7 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
LV1_STORAGE_ATA_HDDOUT, 0, 0, 0,
0, &dev->tag);
if (res) {
- dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n",
+ dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
__func__, __LINE__, res);
end_request(req, 0);
return 0;
@@ -238,11 +238,11 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
if (tag != dev->tag)
dev_err(&dev->sbd.core,
- "%s:%u: tag mismatch, got %lx, expected %lx\n",
+ "%s:%u: tag mismatch, got %llx, expected %llx\n",
__func__, __LINE__, tag, dev->tag);
if (res) {
- dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
+ dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
__func__, __LINE__, res, status);
return IRQ_HANDLED;
}
@@ -269,7 +269,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
op = read ? "read" : "write";
}
if (status) {
- dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+ dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
__LINE__, op, status);
error = -EIO;
} else {
@@ -297,7 +297,7 @@ static int ps3disk_sync_cache(struct ps3_storage_device *dev)
res = ps3stor_send_command(dev, LV1_STORAGE_ATA_HDDOUT, 0, 0, 0, 0);
if (res) {
- dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n",
+ dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n",
__func__, __LINE__, res);
return -EIO;
}
@@ -388,7 +388,7 @@ static int ps3disk_identify(struct ps3_storage_device *dev)
sizeof(ata_cmnd), ata_cmnd.buffer,
ata_cmnd.arglen);
if (res) {
- dev_err(&dev->sbd.core, "%s:%u: identify disk failed 0x%lx\n",
+ dev_err(&dev->sbd.core, "%s:%u: identify disk failed 0x%llx\n",
__func__, __LINE__, res);
return -EIO;
}
@@ -426,7 +426,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
if (dev->blk_size < 512) {
dev_err(&dev->sbd.core,
- "%s:%u: cannot handle block size %lu\n", __func__,
+ "%s:%u: cannot handle block size %llu\n", __func__,
__LINE__, dev->blk_size);
return -EINVAL;
}
@@ -512,7 +512,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
dev->regions[dev->region_idx].size*priv->blocking_factor);
dev_info(&dev->sbd.core,
- "%s is a %s (%lu MiB total, %lu MiB for OtherOS)\n",
+ "%s is a %s (%llu MiB total, %lu MiB for OtherOS)\n",
gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
get_capacity(gendisk) >> 11);
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 953c0b83d758..5861e33efe63 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -153,7 +153,7 @@ static int vdc_send_attr(struct vio_driver_state *vio)
pkt.vdisk_block_size = port->vdisk_block_size;
pkt.max_xfer_size = port->max_xfer_size;
- viodbg(HS, "SEND ATTR xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+ viodbg(HS, "SEND ATTR xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n",
pkt.xfer_mode, pkt.vdisk_block_size, pkt.max_xfer_size);
return vio_ldc_send(&port->vio, &pkt, sizeof(pkt));
@@ -164,8 +164,8 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
struct vdc_port *port = to_vdc_port(vio);
struct vio_disk_attr_info *pkt = arg;
- viodbg(HS, "GOT ATTR stype[0x%x] ops[%lx] disk_size[%lu] disk_type[%x] "
- "xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+ viodbg(HS, "GOT ATTR stype[0x%x] ops[%llx] disk_size[%llu] disk_type[%x] "
+ "xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n",
pkt->tag.stype, pkt->operations,
pkt->vdisk_size, pkt->vdisk_type,
pkt->xfer_mode, pkt->vdisk_block_size,
@@ -753,7 +753,7 @@ static int __devinit vdc_port_probe(struct vio_dev *vdev,
err = -ENODEV;
if ((vdev->dev_no << PARTITION_SHIFT) & ~(u64)MINORMASK) {
- printk(KERN_ERR PFX "Port id [%lu] too large.\n",
+ printk(KERN_ERR PFX "Port id [%llu] too large.\n",
vdev->dev_no);
goto err_out_release_mdesc;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 048d71d244d7..12fb816db7b0 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1579,7 +1579,7 @@ static void ub_reset_task(struct work_struct *work)
struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
unsigned long flags;
struct ub_lun *lun;
- int lkr, rc;
+ int rc;
if (!sc->reset) {
printk(KERN_WARNING "%s: Running reset unrequested\n",
@@ -1597,10 +1597,11 @@ static void ub_reset_task(struct work_struct *work)
} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
;
} else {
- if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) {
+ rc = usb_lock_device_for_reset(sc->dev, sc->intf);
+ if (rc < 0) {
printk(KERN_NOTICE
"%s: usb_lock_device_for_reset failed (%d)\n",
- sc->name, lkr);
+ sc->name, rc);
} else {
rc = usb_reset_device(sc->dev);
if (rc < 0) {
@@ -1608,9 +1609,7 @@ static void ub_reset_task(struct work_struct *work)
"usb_lock_device_for_reset failed (%d)\n",
sc->name, rc);
}
-
- if (lkr)
- usb_unlock_device(sc->dev);
+ usb_unlock_device(sc->dev);
}
}
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 29e1dfafb7c6..381d686fc1a3 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -1206,6 +1206,7 @@ static struct of_device_id ace_of_match[] __devinitdata = {
{ .compatible = "xlnx,opb-sysace-1.00.b", },
{ .compatible = "xlnx,opb-sysace-1.00.c", },
{ .compatible = "xlnx,xps-sysace-1.00.a", },
+ { .compatible = "xlnx,sysace", },
{},
};
MODULE_DEVICE_TABLE(of, ace_of_match);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index c602b547cc6e..735bbe2be51a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -190,7 +190,7 @@ config DIGIEPCA
config ESPSERIAL
tristate "Hayes ESP serial port support"
- depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API
+ depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN
help
This is a driver which supports Hayes ESP serial ports. Both single
port cards and multiport cards are supported. Make sure to read
@@ -443,6 +443,17 @@ config UNIX98_PTYS
All modern Linux systems use the Unix98 ptys. Say Y unless
you're on an embedded system and want to conserve memory.
+config DEVPTS_MULTIPLE_INSTANCES
+ bool "Support multiple instances of devpts"
+ depends on UNIX98_PTYS
+ default n
+ ---help---
+ Enable support for multiple instances of devpts filesystem.
+ If you want to have isolated PTY namespaces (eg: in containers),
+ say Y here. Otherwise, say N. If enabled, each mount of devpts
+ filesystem with the '-o newinstance' option will create an
+ independent PTY namespace.
+
config LEGACY_PTYS
bool "Legacy (BSD) PTY support"
default y
@@ -605,6 +616,7 @@ config HVC_ISERIES
default y
select HVC_DRIVER
select HVC_IRQ
+ select VIOPATH
help
iSeries machines support a hypervisor virtual console.
@@ -749,7 +761,7 @@ source "drivers/char/hw_random/Kconfig"
config NVRAM
tristate "/dev/nvram support"
- depends on ATARI || X86 || ARM || GENERIC_NVRAM
+ depends on ATARI || X86 || (ARM && RTC_DRV_CMOS) || GENERIC_NVRAM
---help---
If you say Y here and create a character special file /dev/nvram
with major number 10 and minor number 144 using mknod ("man mknod"),
@@ -830,7 +842,7 @@ config JS_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32
+ depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index b97aebd7aeb8..a58869ea8513 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -170,7 +170,7 @@ static __inline__ void rtsdtr_ctrl(int bits)
*/
static void rs_stop(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_stop"))
@@ -190,7 +190,7 @@ static void rs_stop(struct tty_struct *tty)
static void rs_start(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_start"))
@@ -861,7 +861,7 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
static void rs_flush_chars(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
@@ -934,7 +934,7 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count
static int rs_write_room(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_write_room"))
return 0;
@@ -943,7 +943,7 @@ static int rs_write_room(struct tty_struct *tty)
static int rs_chars_in_buffer(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
return 0;
@@ -952,7 +952,7 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
static void rs_flush_buffer(struct tty_struct *tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
@@ -969,7 +969,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
*/
static void rs_send_xchar(struct tty_struct *tty, char ch)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_send_char"))
@@ -1004,7 +1004,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
*/
static void rs_throttle(struct tty_struct * tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
@@ -1029,7 +1029,7 @@ static void rs_throttle(struct tty_struct * tty)
static void rs_unthrottle(struct tty_struct * tty)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_THROTTLE
char buf[64];
@@ -1194,7 +1194,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
static int rs_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_struct * info = tty->driver_data;
unsigned char control, status;
unsigned long flags;
@@ -1217,7 +1217,7 @@ static int rs_tiocmget(struct tty_struct *tty, struct file *file)
static int rs_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_struct * info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
@@ -1244,7 +1244,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
*/
static int rs_break(struct tty_struct *tty, int break_state)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_struct * info = tty->driver_data;
unsigned long flags;
if (serial_paranoia_check(info, tty->name, "rs_break"))
@@ -1264,7 +1264,7 @@ static int rs_break(struct tty_struct *tty, int break_state)
static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_struct * info = tty->driver_data;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct icount;
void __user *argp = (void __user *)arg;
@@ -1368,7 +1368,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info = tty->driver_data;
unsigned long flags;
unsigned int cflag = tty->termios->c_cflag;
@@ -1428,7 +1428,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
*/
static void rs_close(struct tty_struct *tty, struct file * filp)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_struct * info = tty->driver_data;
struct serial_state *state;
unsigned long flags;
@@ -1523,7 +1523,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
*/
static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_struct * info = tty->driver_data;
unsigned long orig_jiffies, char_time;
int lsr;
@@ -1587,7 +1587,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
*/
static void rs_hangup(struct tty_struct *tty)
{
- struct async_struct * info = (struct async_struct *)tty->driver_data;
+ struct async_struct * info = tty->driver_data;
struct serial_state *state = info->state;
if (serial_paranoia_check(info, tty->name, "rs_hangup"))
@@ -1963,6 +1963,7 @@ static int __init rs_init(void)
{
unsigned long flags;
struct serial_state * state;
+ int error;
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL))
return -ENODEV;
@@ -1975,8 +1976,11 @@ static int __init rs_init(void)
* We request SERDAT and SERPER only, because the serial registers are
* too spreaded over the custom register space
*/
- if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, "amiserial [Paula]"))
- return -EBUSY;
+ if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4,
+ "amiserial [Paula]")) {
+ error = -EBUSY;
+ goto fail_put_tty_driver;
+ }
IRQ_ports = NULL;
@@ -1997,8 +2001,9 @@ static int __init rs_init(void)
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &serial_ops);
- if (tty_register_driver(serial_driver))
- panic("Couldn't register serial driver\n");
+ error = tty_register_driver(serial_driver);
+ if (error)
+ goto fail_release_mem_region;
state = rs_table;
state->magic = SSTATE_MAGIC;
@@ -2024,8 +2029,14 @@ static int __init rs_init(void)
local_irq_save(flags);
/* set ISRs, and then disable the rx interrupts */
- request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
- request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED, "serial RX", state);
+ error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
+ if (error)
+ goto fail_unregister;
+
+ error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED,
+ "serial RX", state);
+ if (error)
+ goto fail_free_irq;
/* turn off Rx and Tx interrupts */
custom.intena = IF_RBF | IF_TBE;
@@ -2045,6 +2056,16 @@ static int __init rs_init(void)
ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */
return 0;
+
+fail_free_irq:
+ free_irq(IRQ_AMIGA_TBE, state);
+fail_unregister:
+ tty_unregister_driver(serial_driver);
+fail_release_mem_region:
+ release_mem_region(CUSTOM_PHYSADDR+0x30, 4);
+fail_put_tty_driver:
+ put_tty_driver(serial_driver);
+ return error;
}
static __exit void rs_exit(void)
@@ -2064,6 +2085,9 @@ static __exit void rs_exit(void)
kfree(info);
}
+ free_irq(IRQ_AMIGA_TBE, rs_table);
+ free_irq(IRQ_AMIGA_RBF, rs_table);
+
release_mem_region(CUSTOM_PHYSADDR+0x30, 4);
}
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 977dfb1096a0..f6094ae0ef33 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -103,7 +103,7 @@ static ssize_t
bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct bsr_dev *bsr_dev = dev_get_drvdata(dev);
- return sprintf(buf, "%lu\n", bsr_dev->bsr_len);
+ return sprintf(buf, "%llu\n", bsr_dev->bsr_len);
}
static struct device_attribute bsr_dev_attrs[] = {
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 4246b8e36cb3..45d3e80156d4 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -554,7 +554,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
__get_user(fontpos, &list->fontpos);
if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
err = err1;
- list++;
+ list++;
}
if (con_unify_unimap(vc, p))
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 5e5b1dc1a0a7..6a59f72a9c21 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -5010,7 +5010,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
if (nchan == 0) {
dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
"Serial-Modules\n");
- return -EIO;
+ goto err_unmap;
}
} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
struct RUNTIME_9060 __iomem *ctl_addr;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index cf2461d34e5f..af7c13ca9493 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -69,7 +69,9 @@ static int invalid_lilo_config;
/*
* The ISA boards do window flipping into the same spaces so its only sane with
- * a single lock. It's still pretty efficient.
+ * a single lock. It's still pretty efficient. This lock guards the hardware
+ * and the tty_port lock guards the kernel side stuff like use counts. Take
+ * this lock inside the port lock if you must take both.
*/
static DEFINE_SPINLOCK(epca_lock);
@@ -156,14 +158,12 @@ static struct channel *verifyChannel(struct tty_struct *);
static void pc_sched_event(struct channel *, int);
static void epca_error(int, char *);
static void pc_close(struct tty_struct *, struct file *);
-static void shutdown(struct channel *);
+static void shutdown(struct channel *, struct tty_struct *tty);
static void pc_hangup(struct tty_struct *);
static int pc_write_room(struct tty_struct *);
static int pc_chars_in_buffer(struct tty_struct *);
static void pc_flush_buffer(struct tty_struct *);
static void pc_flush_chars(struct tty_struct *);
-static int block_til_ready(struct tty_struct *, struct file *,
- struct channel *);
static int pc_open(struct tty_struct *, struct file *);
static void post_fep_init(unsigned int crd);
static void epcapoll(unsigned long);
@@ -173,7 +173,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned);
static unsigned termios2digi_i(struct channel *ch, unsigned);
static unsigned termios2digi_c(struct channel *ch, unsigned);
static void epcaparam(struct tty_struct *, struct channel *);
-static void receive_data(struct channel *);
+static void receive_data(struct channel *, struct tty_struct *tty);
static int pc_ioctl(struct tty_struct *, struct file *,
unsigned int, unsigned long);
static int info_ioctl(struct tty_struct *, struct file *,
@@ -392,7 +392,7 @@ static struct channel *verifyChannel(struct tty_struct *tty)
* through tty->driver_data this should catch it.
*/
if (tty) {
- struct channel *ch = (struct channel *)tty->driver_data;
+ struct channel *ch = tty->driver_data;
if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
if (ch->magic == EPCA_MAGIC)
return ch;
@@ -419,76 +419,34 @@ static void epca_error(int line, char *msg)
static void pc_close(struct tty_struct *tty, struct file *filp)
{
struct channel *ch;
- unsigned long flags;
+ struct tty_port *port;
/*
* verifyChannel returns the channel from the tty struct if it is
* valid. This serves as a sanity check.
*/
ch = verifyChannel(tty);
- if (ch != NULL) {
- spin_lock_irqsave(&epca_lock, flags);
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&epca_lock, flags);
- return;
- }
- if (ch->port.count-- > 1) {
- /* Begin channel is open more than once */
- /*
- * Return without doing anything. Someone might still
- * be using the channel.
- */
- spin_unlock_irqrestore(&epca_lock, flags);
- return;
- }
- /* Port open only once go ahead with shutdown & reset */
- BUG_ON(ch->port.count < 0);
-
- /*
- * Let the rest of the driver know the channel is being closed.
- * This becomes important if an open is attempted before close
- * is finished.
- */
- ch->port.flags |= ASYNC_CLOSING;
- tty->closing = 1;
-
- spin_unlock_irqrestore(&epca_lock, flags);
-
- if (ch->port.flags & ASYNC_INITIALIZED) {
- /* Setup an event to indicate when the
- transmit buffer empties */
- setup_empty_event(tty, ch);
- /* 30 seconds timeout */
- tty_wait_until_sent(tty, 3000);
- }
- pc_flush_buffer(tty);
+ if (ch == NULL)
+ return;
+ port = &ch->port;
- tty_ldisc_flush(tty);
- shutdown(ch);
+ if (tty_port_close_start(port, tty, filp) == 0)
+ return;
- spin_lock_irqsave(&epca_lock, flags);
- tty->closing = 0;
- ch->event = 0;
- ch->port.tty = NULL;
- spin_unlock_irqrestore(&epca_lock, flags);
+ pc_flush_buffer(tty);
+ shutdown(ch, tty);
- if (ch->port.blocked_open) {
- if (ch->close_delay)
- msleep_interruptible(jiffies_to_msecs(ch->close_delay));
- wake_up_interruptible(&ch->port.open_wait);
- }
- ch->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
- ASYNC_CLOSING);
- wake_up_interruptible(&ch->port.close_wait);
- }
+ tty_port_close_end(port, tty);
+ ch->event = 0; /* FIXME: review ch->event locking */
+ tty_port_tty_set(port, NULL);
}
-static void shutdown(struct channel *ch)
+static void shutdown(struct channel *ch, struct tty_struct *tty)
{
unsigned long flags;
- struct tty_struct *tty;
struct board_chan __iomem *bc;
+ struct tty_port *port = &ch->port;
- if (!(ch->port.flags & ASYNC_INITIALIZED))
+ if (!(port->flags & ASYNC_INITIALIZED))
return;
spin_lock_irqsave(&epca_lock, flags);
@@ -503,7 +461,6 @@ static void shutdown(struct channel *ch)
*/
if (bc)
writeb(0, &bc->idata);
- tty = ch->port.tty;
/* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
if (tty->termios->c_cflag & HUPCL) {
@@ -517,32 +474,26 @@ static void shutdown(struct channel *ch)
* will have to reinitialized. Set a flag to indicate this.
*/
/* Prevent future Digi programmed interrupts from coming active */
- ch->port.flags &= ~ASYNC_INITIALIZED;
+ port->flags &= ~ASYNC_INITIALIZED;
spin_unlock_irqrestore(&epca_lock, flags);
}
static void pc_hangup(struct tty_struct *tty)
{
struct channel *ch;
+
/*
* verifyChannel returns the channel from the tty struct if it is
* valid. This serves as a sanity check.
*/
ch = verifyChannel(tty);
if (ch != NULL) {
- unsigned long flags;
-
pc_flush_buffer(tty);
tty_ldisc_flush(tty);
- shutdown(ch);
+ shutdown(ch, tty);
- spin_lock_irqsave(&epca_lock, flags);
- ch->port.tty = NULL;
- ch->event = 0;
- ch->port.count = 0;
- ch->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED);
- spin_unlock_irqrestore(&epca_lock, flags);
- wake_up_interruptible(&ch->port.open_wait);
+ ch->event = 0; /* FIXME: review locking of ch->event */
+ tty_port_hangup(&ch->port);
}
}
@@ -786,100 +737,22 @@ static void pc_flush_chars(struct tty_struct *tty)
}
}
-static int block_til_ready(struct tty_struct *tty,
- struct file *filp, struct channel *ch)
+static int epca_carrier_raised(struct tty_port *port)
{
- DECLARE_WAITQUEUE(wait, current);
- int retval, do_clocal = 0;
- unsigned long flags;
-
- if (tty_hung_up_p(filp)) {
- if (ch->port.flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- return retval;
- }
-
- /*
- * If the device is in the middle of being closed, then block until
- * it's done, and then try again.
- */
- if (ch->port.flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&ch->port.close_wait);
-
- if (ch->port.flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
- }
-
- if (filp->f_flags & O_NONBLOCK) {
- /*
- * If non-blocking mode is set, then make the check up front
- * and then exit.
- */
- ch->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
- /* Block waiting for the carrier detect and the line to become free */
-
- retval = 0;
- add_wait_queue(&ch->port.open_wait, &wait);
-
- spin_lock_irqsave(&epca_lock, flags);
- /* We dec count so that pc_close will know when to free things */
- if (!tty_hung_up_p(filp))
- ch->port.count--;
- ch->port.blocked_open++;
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(ch->port.flags & ASYNC_INITIALIZED)) {
- if (ch->port.flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(ch->port.flags & ASYNC_CLOSING) &&
- (do_clocal || (ch->imodem & ch->dcd)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- spin_unlock_irqrestore(&epca_lock, flags);
- /*
- * Allow someone else to be scheduled. We will occasionally go
- * through this loop until one of the above conditions change.
- * The below schedule call will allow other processes to enter
- * and prevent this loop from hogging the cpu.
- */
- schedule();
- spin_lock_irqsave(&epca_lock, flags);
- }
-
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&ch->port.open_wait, &wait);
- if (!tty_hung_up_p(filp))
- ch->port.count++;
- ch->port.blocked_open--;
-
- spin_unlock_irqrestore(&epca_lock, flags);
-
- if (retval)
- return retval;
-
- ch->port.flags |= ASYNC_NORMAL_ACTIVE;
+ struct channel *ch = container_of(port, struct channel, port);
+ if (ch->imodem & ch->dcd)
+ return 1;
return 0;
}
+static void epca_raise_dtr_rts(struct tty_port *port)
+{
+}
+
static int pc_open(struct tty_struct *tty, struct file *filp)
{
struct channel *ch;
+ struct tty_port *port;
unsigned long flags;
int line, retval, boardnum;
struct board_chan __iomem *bc;
@@ -890,12 +763,13 @@ static int pc_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
ch = &digi_channels[line];
+ port = &ch->port;
boardnum = ch->boardnum;
/* Check status of board configured in system. */
/*
- * I check to see if the epca_setup routine detected an user error. It
+ * I check to see if the epca_setup routine detected a user error. It
* might be better to put this in pc_init, but for the moment it goes
* here.
*/
@@ -926,22 +800,24 @@ static int pc_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
}
- spin_lock_irqsave(&epca_lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
/*
* Every time a channel is opened, increment a counter. This is
* necessary because we do not wish to flush and shutdown the channel
* until the last app holding the channel open, closes it.
*/
- ch->port.count++;
+ port->count++;
/*
* Set a kernel structures pointer to our local channel structure. This
* way we can get to it when passed only a tty struct.
*/
tty->driver_data = ch;
+ port->tty = tty;
/*
* If this is the first time the channel has been opened, initialize
* the tty->termios struct otherwise let pc_close handle it.
*/
+ spin_lock(&epca_lock);
globalwinon(ch);
ch->statusflags = 0;
@@ -956,31 +832,33 @@ static int pc_open(struct tty_struct *tty, struct file *filp)
writew(head, &bc->rout);
/* Set the channels associated tty structure */
- ch->port.tty = tty;
/*
* The below routine generally sets up parity, baud, flow control
* issues, etc.... It effect both control flags and input flags.
*/
epcaparam(tty, ch);
- ch->port.flags |= ASYNC_INITIALIZED;
memoff(ch);
- spin_unlock_irqrestore(&epca_lock, flags);
+ spin_unlock(&epca_lock);
+ port->flags |= ASYNC_INITIALIZED;
+ spin_unlock_irqrestore(&port->lock, flags);
- retval = block_til_ready(tty, filp, ch);
+ retval = tty_port_block_til_ready(port, tty, filp);
if (retval)
return retval;
/*
* Set this again in case a hangup set it to zero while this open() was
* waiting for the line...
*/
- spin_lock_irqsave(&epca_lock, flags);
- ch->port.tty = tty;
+ spin_lock_irqsave(&port->lock, flags);
+ port->tty = tty;
+ spin_lock(&epca_lock);
globalwinon(ch);
/* Enable Digi Data events */
writeb(1, &bc->idata);
memoff(ch);
- spin_unlock_irqrestore(&epca_lock, flags);
+ spin_unlock(&epca_lock);
+ spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
@@ -1016,8 +894,11 @@ static void __exit epca_module_exit(void)
}
ch = card_ptr[crd];
for (count = 0; count < bd->numports; count++, ch++) {
- if (ch && ch->port.tty)
- tty_hangup(ch->port.tty);
+ struct tty_struct *tty = tty_port_tty_get(&ch->port);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
}
}
pci_unregister_driver(&epca_driver);
@@ -1042,6 +923,11 @@ static const struct tty_operations pc_ops = {
.break_ctl = pc_send_break
};
+static const struct tty_port_operations epca_port_ops = {
+ .carrier_raised = epca_carrier_raised,
+ .raise_dtr_rts = epca_raise_dtr_rts,
+};
+
static int info_open(struct tty_struct *tty, struct file *filp)
{
return 0;
@@ -1377,6 +1263,7 @@ static void post_fep_init(unsigned int crd)
u16 tseg, rseg;
tty_port_init(&ch->port);
+ ch->port.ops = &epca_port_ops;
ch->brdchan = bc;
ch->mailbox = gd;
INIT_WORK(&ch->tqueue, do_softint);
@@ -1428,7 +1315,7 @@ static void post_fep_init(unsigned int crd)
ch->boardnum = crd;
ch->channelnum = i;
ch->magic = EPCA_MAGIC;
- ch->port.tty = NULL;
+ tty_port_tty_set(&ch->port, NULL);
if (shrinkmem) {
fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
@@ -1510,7 +1397,7 @@ static void post_fep_init(unsigned int crd)
ch->fepstartca = 0;
ch->fepstopca = 0;
- ch->close_delay = 50;
+ ch->port.close_delay = 50;
spin_unlock_irqrestore(&epca_lock, flags);
}
@@ -1622,15 +1509,16 @@ static void doevent(int crd)
if (bc == NULL)
goto next;
+ tty = tty_port_tty_get(&ch->port);
if (event & DATA_IND) { /* Begin DATA_IND */
- receive_data(ch);
+ receive_data(ch, tty);
assertgwinon(ch);
} /* End DATA_IND */
/* else *//* Fix for DCD transition missed bug */
if (event & MODEMCHG_IND) {
/* A modem signal change has been indicated */
ch->imodem = mstat;
- if (ch->port.flags & ASYNC_CHECK_CD) {
+ if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) {
/* We are now receiving dcd */
if (mstat & ch->dcd)
wake_up_interruptible(&ch->port.open_wait);
@@ -1638,7 +1526,6 @@ static void doevent(int crd)
pc_sched_event(ch, EPCA_EVENT_HANGUP);
}
}
- tty = ch->port.tty;
if (tty) {
if (event & BREAK_IND) {
/* A break has been indicated */
@@ -1658,6 +1545,7 @@ static void doevent(int crd)
tty_wakeup(tty);
}
}
+ tty_kref_put(tty);
}
next:
globalwinon(ch);
@@ -1877,9 +1765,9 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
* that the driver will wait on carrier detect.
*/
if (ts->c_cflag & CLOCAL)
- ch->port.flags &= ~ASYNC_CHECK_CD;
+ clear_bit(ASYNC_CHECK_CD, &ch->port.flags);
else
- ch->port.flags |= ASYNC_CHECK_CD;
+ set_bit(ASYNC_CHECK_CD, &ch->port.flags);
mval = ch->m_dtr | ch->m_rts;
} /* End CBAUD not detected */
iflag = termios2digi_i(ch, ts->c_iflag);
@@ -1952,11 +1840,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
}
/* Caller holds lock */
-static void receive_data(struct channel *ch)
+static void receive_data(struct channel *ch, struct tty_struct *tty)
{
unchar *rptr;
struct ktermios *ts = NULL;
- struct tty_struct *tty;
struct board_chan __iomem *bc;
int dataToRead, wrapgap, bytesAvailable;
unsigned int tail, head;
@@ -1969,7 +1856,6 @@ static void receive_data(struct channel *ch)
globalwinon(ch);
if (ch->statusflags & RXSTOPPED)
return;
- tty = ch->port.tty;
if (tty)
ts = tty->termios;
bc = ch->brdchan;
@@ -2029,7 +1915,7 @@ static void receive_data(struct channel *ch)
globalwinon(ch);
writew(tail, &bc->rout);
/* Must be called with global data */
- tty_schedule_flip(ch->port.tty);
+ tty_schedule_flip(tty);
}
static int info_ioctl(struct tty_struct *tty, struct file *file,
@@ -2097,7 +1983,7 @@ static int info_ioctl(struct tty_struct *tty, struct file *file,
static int pc_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct channel *ch = (struct channel *) tty->driver_data;
+ struct channel *ch = tty->driver_data;
struct board_chan __iomem *bc;
unsigned int mstat, mflag = 0;
unsigned long flags;
@@ -2131,7 +2017,7 @@ static int pc_tiocmget(struct tty_struct *tty, struct file *file)
static int pc_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct channel *ch = (struct channel *) tty->driver_data;
+ struct channel *ch = tty->driver_data;
unsigned long flags;
if (!ch)
@@ -2178,7 +2064,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
unsigned int mflag, mstat;
unsigned char startc, stopc;
struct board_chan __iomem *bc;
- struct channel *ch = (struct channel *) tty->driver_data;
+ struct channel *ch = tty->driver_data;
void __user *argp = (void __user *)arg;
if (ch)
@@ -2352,15 +2238,16 @@ static void do_softint(struct work_struct *work)
struct channel *ch = container_of(work, struct channel, tqueue);
/* Called in response to a modem change event */
if (ch && ch->magic == EPCA_MAGIC) {
- struct tty_struct *tty = ch->port.tty;
+ struct tty_struct *tty = tty_port_tty_get(&ch->port);;
if (tty && tty->driver_data) {
if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
tty_hangup(tty);
wake_up_interruptible(&ch->port.open_wait);
- ch->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+ clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags);
}
}
+ tty_kref_put(tty);
}
}
@@ -2473,7 +2360,7 @@ static void pc_unthrottle(struct tty_struct *tty)
static int pc_send_break(struct tty_struct *tty, int msec)
{
- struct channel *ch = (struct channel *) tty->driver_data;
+ struct channel *ch = tty->driver_data;
unsigned long flags;
if (msec == -1)
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 7f077c0097f6..45ec263ec012 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -2054,6 +2054,15 @@ static void esp_hangup(struct tty_struct *tty)
wake_up_interruptible(&info->port.open_wait);
}
+static int esp_carrier_raised(struct tty_port *port)
+{
+ struct esp_struct *info = container_of(port, struct esp_struct, port);
+ serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
+ if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD)
+ return 1;
+ return 0;
+}
+
/*
* ------------------------------------------------------------
* esp_open() and friends
@@ -2066,17 +2075,19 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
int retval;
int do_clocal = 0;
unsigned long flags;
+ int cd;
+ struct tty_port *port = &info->port;
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
*/
if (tty_hung_up_p(filp) ||
- (info->port.flags & ASYNC_CLOSING)) {
- if (info->port.flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->port.close_wait);
+ (port->flags & ASYNC_CLOSING)) {
+ if (port->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&port->close_wait);
#ifdef SERIAL_DO_RESTART
- if (info->port.flags & ASYNC_HUP_NOTIFY)
+ if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
@@ -2091,7 +2102,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -2101,20 +2112,20 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/*
* Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, info->port.count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* rs_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&info->port.open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
#ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n",
- info->line, info->port.count);
+ info->line, port->count);
#endif
spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp))
- info->port.count--;
- info->port.blocked_open++;
+ port->count--;
+ port->blocked_open++;
while (1) {
if ((tty->termios->c_cflag & CBAUD)) {
unsigned int scratch;
@@ -2129,9 +2140,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
- !(info->port.flags & ASYNC_INITIALIZED)) {
+ !(port->flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
- if (info->port.flags & ASYNC_HUP_NOTIFY)
+ if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
@@ -2141,11 +2152,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
break;
}
- serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
- if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD)
- do_clocal = 1;
+ cd = tty_port_carrier_raised(port);
- if (!(info->port.flags & ASYNC_CLOSING) &&
+ if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal))
break;
if (signal_pending(current)) {
@@ -2154,25 +2163,25 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
#ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n",
- info->line, info->port.count);
+ info->line, port->count);
#endif
spin_unlock_irqrestore(&info->lock, flags);
schedule();
spin_lock_irqsave(&info->lock, flags);
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->port.open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
if (!tty_hung_up_p(filp))
- info->port.count++;
- info->port.blocked_open--;
+ port->count++;
+ port->blocked_open--;
spin_unlock_irqrestore(&info->lock, flags);
#ifdef SERIAL_DEBUG_OPEN
printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n",
- info->line, info->port.count);
+ info->line, port->count);
#endif
if (retval)
return retval;
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -2329,6 +2338,10 @@ static const struct tty_operations esp_ops = {
.tiocmset = esp_tiocmset,
};
+static const struct tty_port_operations esp_port_ops = {
+ .esp_carrier_raised,
+};
+
/*
* The serial driver boot-time initialization code!
*/
@@ -2415,6 +2428,8 @@ static int __init espserial_init(void)
offset = 0;
do {
+ tty_port_init(&info->port);
+ info->port.ops = &esp_port_ops;
info->io_port = esp[i] + offset;
info->irq = irq[i];
info->line = (i * 8) + (offset / 8);
@@ -2437,8 +2452,6 @@ static int __init espserial_init(void)
info->config.flow_off = flow_off;
info->config.pio_threshold = pio_threshold;
info->next_port = ports;
- init_waitqueue_head(&info->port.open_wait);
- init_waitqueue_head(&info->port.close_wait);
init_waitqueue_head(&info->delta_msr_wait);
init_waitqueue_head(&info->break_wait);
ports = info;
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index c6090f84a2e4..9e4e569dc00d 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -376,7 +376,8 @@ static void gs_shutdown_port (struct gs_port *port)
void gs_hangup(struct tty_struct *tty)
{
- struct gs_port *port;
+ struct gs_port *port;
+ unsigned long flags;
func_enter ();
@@ -386,9 +387,11 @@ void gs_hangup(struct tty_struct *tty)
return;
gs_shutdown_port (port);
+ spin_lock_irqsave(&port->port.lock, flags);
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
port->port.tty = NULL;
port->port.count = 0;
+ spin_unlock_irqrestore(&port->port.lock, flags);
wake_up_interruptible(&port->port.open_wait);
func_exit ();
@@ -397,7 +400,8 @@ void gs_hangup(struct tty_struct *tty)
int gs_block_til_ready(void *port_, struct file * filp)
{
- struct gs_port *port = port_;
+ struct gs_port *gp = port_;
+ struct tty_port *port = &gp->port;
DECLARE_WAITQUEUE(wait, current);
int retval;
int do_clocal = 0;
@@ -409,16 +413,16 @@ int gs_block_til_ready(void *port_, struct file * filp)
if (!port) return 0;
- tty = port->port.tty;
+ tty = port->tty;
gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n");
/*
* If the device is in the middle of being closed, then block
* until it's done, and then try again.
*/
- if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&port->port.close_wait);
- if (port->port.flags & ASYNC_HUP_NOTIFY)
+ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
+ interruptible_sleep_on(&port->close_wait);
+ if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
@@ -432,7 +436,7 @@ int gs_block_til_ready(void *port_, struct file * filp)
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -444,34 +448,34 @@ int gs_block_til_ready(void *port_, struct file * filp)
/*
* Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, port->port.count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* rs_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&port->port.open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n");
- spin_lock_irqsave(&port->driver_lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) {
- port->port.count--;
+ port->count--;
}
- spin_unlock_irqrestore(&port->driver_lock, flags);
- port->port.blocked_open++;
+ port->blocked_open++;
+ spin_unlock_irqrestore(&port->lock, flags);
while (1) {
- CD = port->rd->get_CD (port);
+ CD = tty_port_carrier_raised(port);
gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
set_current_state (TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
- !(port->port.flags & ASYNC_INITIALIZED)) {
- if (port->port.flags & ASYNC_HUP_NOTIFY)
+ !(port->flags & ASYNC_INITIALIZED)) {
+ if (port->flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
break;
}
- if (!(port->port.flags & ASYNC_CLOSING) &&
+ if (!(port->flags & ASYNC_CLOSING) &&
(do_clocal || CD))
break;
gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n",
@@ -483,19 +487,20 @@ int gs_block_til_ready(void *port_, struct file * filp)
schedule();
}
gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
- port->port.blocked_open);
+ port->blocked_open);
set_current_state (TASK_RUNNING);
- remove_wait_queue(&port->port.open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
+
+ spin_lock_irqsave(&port->lock, flags);
if (!tty_hung_up_p(filp)) {
- port->port.count++;
+ port->count++;
}
- port->port.blocked_open--;
- if (retval)
- return retval;
-
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->blocked_open--;
+ if (retval == 0)
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ spin_unlock_irqrestore(&port->lock, flags);
func_exit ();
- return 0;
+ return retval;
}
@@ -506,7 +511,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
func_enter ();
- port = (struct gs_port *) tty->driver_data;
+ port = tty->driver_data;
if (!port) return;
@@ -516,10 +521,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
port->port.tty = tty;
}
- spin_lock_irqsave(&port->driver_lock, flags);
+ spin_lock_irqsave(&port->port.lock, flags);
if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&port->driver_lock, flags);
+ spin_unlock_irqrestore(&port->port.lock, flags);
if (port->rd->hungup)
port->rd->hungup (port);
func_exit ();
@@ -538,7 +543,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
if (port->port.count) {
gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
- spin_unlock_irqrestore(&port->driver_lock, flags);
+ spin_unlock_irqrestore(&port->port.lock, flags);
func_exit ();
return;
}
@@ -559,8 +564,10 @@ void gs_close(struct tty_struct * tty, struct file * filp)
* line status register.
*/
+ spin_lock_irqsave(&port->driver_lock, flags);
port->rd->disable_rx_interrupts (port);
spin_unlock_irqrestore(&port->driver_lock, flags);
+ spin_unlock_irqrestore(&port->port.lock, flags);
/* close has no way of returning "EINTR", so discard return value */
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
@@ -573,20 +580,25 @@ void gs_close(struct tty_struct * tty, struct file * filp)
tty_ldisc_flush(tty);
tty->closing = 0;
+ spin_lock_irqsave(&port->driver_lock, flags);
port->event = 0;
port->rd->close (port);
port->rd->shutdown_port (port);
+ spin_unlock_irqrestore(&port->driver_lock, flags);
+
+ spin_lock_irqsave(&port->port.lock, flags);
port->port.tty = NULL;
if (port->port.blocked_open) {
if (port->close_delay) {
- spin_unlock_irqrestore(&port->driver_lock, flags);
+ spin_unlock_irqrestore(&port->port.lock, flags);
msleep_interruptible(jiffies_to_msecs(port->close_delay));
- spin_lock_irqsave(&port->driver_lock, flags);
+ spin_lock_irqsave(&port->port.lock, flags);
}
wake_up_interruptible(&port->port.open_wait);
}
port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
+ spin_unlock_irqrestore(&port->port.lock, flags);
wake_up_interruptible(&port->port.close_wait);
func_exit ();
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c
index 91cdb35a9204..0afc8b82212e 100644
--- a/drivers/char/hvc_beat.c
+++ b/drivers/char/hvc_beat.c
@@ -44,7 +44,7 @@ static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt)
static unsigned char q[sizeof(unsigned long) * 2]
__attribute__((aligned(sizeof(unsigned long))));
static int qlen = 0;
- unsigned long got;
+ u64 got;
again:
if (qlen) {
@@ -63,7 +63,7 @@ again:
}
}
if (beat_get_term_char(vtermno, &got,
- ((unsigned long *)q), ((unsigned long *)q) + 1) == 0) {
+ ((u64 *)q), ((u64 *)q) + 1) == 0) {
qlen = got;
goto again;
}
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 0587b66d6fc7..94e7e3c8c05a 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -318,7 +318,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
} /* else count == 0 */
tty->driver_data = hp;
- tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */
hp->tty = tty;
@@ -529,7 +528,7 @@ static void hvc_set_winsz(struct work_struct *work)
tty = tty_kref_get(hp->tty);
spin_unlock_irqrestore(&hp->lock, hvc_flags);
- tty_do_resize(tty, tty, &ws);
+ tty_do_resize(tty, &ws);
tty_kref_put(tty);
}
@@ -764,13 +763,11 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data,
return ERR_PTR(err);
}
- hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
+ hp = kzalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
GFP_KERNEL);
if (!hp)
return ERR_PTR(-ENOMEM);
- memset(hp, 0x00, sizeof(*hp));
-
hp->vtermno = vtermno;
hp->data = data;
hp->ops = ops;
@@ -876,8 +873,11 @@ static int hvc_init(void)
goto stop_thread;
}
- /* FIXME: This mb() seems completely random. Remove it. */
- mb();
+ /*
+ * Make sure tty is fully registered before allowing it to be
+ * found by hvc_console_device.
+ */
+ smp_mb();
hvc_driver = drv;
return 0;
diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c
index d09e5688d449..2623e177e8d6 100644
--- a/drivers/char/hvc_irq.c
+++ b/drivers/char/hvc_irq.c
@@ -37,7 +37,7 @@ int notifier_add_irq(struct hvc_struct *hp, int irq)
void notifier_del_irq(struct hvc_struct *hp, int irq)
{
- if (!irq)
+ if (!hp->irq_requested)
return;
free_irq(irq, hp);
hp->irq_requested = 0;
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c
index 5ea7d7713fca..a53496828b76 100644
--- a/drivers/char/hvc_iucv.c
+++ b/drivers/char/hvc_iucv.c
@@ -1,26 +1,30 @@
/*
- * hvc_iucv.c - z/VM IUCV back-end for the Hypervisor Console (HVC)
+ * hvc_iucv.c - z/VM IUCV hypervisor console (HVC) device driver
*
- * This back-end for HVC provides terminal access via
+ * This HVC device driver provides terminal access using
* z/VM IUCV communication paths.
*
- * Copyright IBM Corp. 2008.
+ * Copyright IBM Corp. 2008
*
* Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
*/
#define KMSG_COMPONENT "hvc_iucv"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/types.h>
#include <asm/ebcdic.h>
+#include <linux/delay.h>
+#include <linux/init.h>
#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/tty.h>
+#include <linux/wait.h>
#include <net/iucv/iucv.h>
#include "hvc_console.h"
-/* HVC backend for z/VM IUCV */
+/* General device driver settings */
#define HVC_IUCV_MAGIC 0xc9e4c3e5
#define MAX_HVC_IUCV_LINES HVC_ALLOC_TTY_ADAPTERS
#define MEMPOOL_MIN_NR (PAGE_SIZE / sizeof(struct iucv_tty_buffer)/4)
@@ -33,14 +37,14 @@
#define MSG_TYPE_WINSIZE 0x08 /* Terminal window size update */
#define MSG_TYPE_DATA 0x10 /* Terminal data */
-#define MSG_SIZE(s) ((s) + offsetof(struct iucv_tty_msg, data))
struct iucv_tty_msg {
u8 version; /* Message version */
u8 type; /* Message type */
-#define MSG_MAX_DATALEN (~(u16)0)
+#define MSG_MAX_DATALEN ((u16)(~0))
u16 datalen; /* Payload length */
u8 data[]; /* Payload buffer */
} __attribute__((packed));
+#define MSG_SIZE(s) ((s) + offsetof(struct iucv_tty_msg, data))
enum iucv_state_t {
IUCV_DISCONN = 0,
@@ -54,19 +58,26 @@ enum tty_state_t {
};
struct hvc_iucv_private {
- struct hvc_struct *hvc; /* HVC console struct reference */
+ struct hvc_struct *hvc; /* HVC struct reference */
u8 srv_name[8]; /* IUCV service name (ebcdic) */
+ unsigned char is_console; /* Linux console usage flag */
enum iucv_state_t iucv_state; /* IUCV connection status */
enum tty_state_t tty_state; /* TTY status */
struct iucv_path *path; /* IUCV path pointer */
spinlock_t lock; /* hvc_iucv_private lock */
+#define SNDBUF_SIZE (PAGE_SIZE) /* must be < MSG_MAX_DATALEN */
+ void *sndbuf; /* send buffer */
+ size_t sndbuf_len; /* length of send buffer */
+#define QUEUE_SNDBUF_DELAY (HZ / 25)
+ struct delayed_work sndbuf_work; /* work: send iucv msg(s) */
+ wait_queue_head_t sndbuf_waitq; /* wait for send completion */
struct list_head tty_outqueue; /* outgoing IUCV messages */
struct list_head tty_inqueue; /* incoming IUCV messages */
};
struct iucv_tty_buffer {
struct list_head list; /* list pointer */
- struct iucv_message msg; /* store an incoming IUCV message */
+ struct iucv_message msg; /* store an IUCV message */
size_t offset; /* data buffer offset */
struct iucv_tty_msg *mbuf; /* buffer to store input/output data */
};
@@ -78,11 +89,12 @@ static void hvc_iucv_msg_pending(struct iucv_path *, struct iucv_message *);
static void hvc_iucv_msg_complete(struct iucv_path *, struct iucv_message *);
-/* Kernel module parameters */
-static unsigned long hvc_iucv_devices;
+/* Kernel module parameter: use one terminal device as default */
+static unsigned long hvc_iucv_devices = 1;
/* Array of allocated hvc iucv tty lines... */
static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES];
+#define IUCV_HVC_CON_IDX (0)
/* Kmem cache and mempool for iucv_tty_buffer elements */
static struct kmem_cache *hvc_iucv_buffer_cache;
@@ -112,7 +124,7 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
}
/**
- * alloc_tty_buffer() - Returns a new struct iucv_tty_buffer element.
+ * alloc_tty_buffer() - Return a new struct iucv_tty_buffer element.
* @size: Size of the internal buffer used to store data.
* @flags: Memory allocation flags passed to mempool.
*
@@ -120,7 +132,6 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
* allocates an internal data buffer with the specified size @size.
* Note: The total message size arises from the internal buffer size and the
* members of the iucv_tty_msg structure.
- *
* The function returns NULL if memory allocation has failed.
*/
static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
@@ -130,7 +141,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
bufp = mempool_alloc(hvc_iucv_mempool, flags);
if (!bufp)
return NULL;
- memset(bufp, 0, sizeof(struct iucv_tty_buffer));
+ memset(bufp, 0, sizeof(*bufp));
if (size > 0) {
bufp->msg.length = MSG_SIZE(size);
@@ -149,9 +160,6 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
/**
* destroy_tty_buffer() - destroy struct iucv_tty_buffer element.
* @bufp: Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL.
- *
- * The destroy_tty_buffer() function frees the internal data buffer and returns
- * the struct iucv_tty_buffer element back to the mempool for freeing.
*/
static void destroy_tty_buffer(struct iucv_tty_buffer *bufp)
{
@@ -161,11 +169,7 @@ static void destroy_tty_buffer(struct iucv_tty_buffer *bufp)
/**
* destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element.
- * @list: List head pointer to a list containing struct iucv_tty_buffer
- * elements.
- *
- * Calls destroy_tty_buffer() for each struct iucv_tty_buffer element in the
- * list @list.
+ * @list: List containing struct iucv_tty_buffer elements.
*/
static void destroy_tty_buffer_list(struct list_head *list)
{
@@ -178,24 +182,24 @@ static void destroy_tty_buffer_list(struct list_head *list)
}
/**
- * hvc_iucv_write() - Receive IUCV message write data to HVC console buffer.
- * @priv: Pointer to hvc_iucv_private structure.
- * @buf: HVC console buffer for writing received terminal data.
- * @count: HVC console buffer size.
+ * hvc_iucv_write() - Receive IUCV message & write data to HVC buffer.
+ * @priv: Pointer to struct hvc_iucv_private
+ * @buf: HVC buffer for writing received terminal data.
+ * @count: HVC buffer size.
* @has_more_data: Pointer to an int variable.
*
* The function picks up pending messages from the input queue and receives
* the message data that is then written to the specified buffer @buf.
- * If the buffer size @count is less than the data message size, then the
+ * If the buffer size @count is less than the data message size, the
* message is kept on the input queue and @has_more_data is set to 1.
- * If the message data has been entirely written, the message is removed from
+ * If all message data has been written, the message is removed from
* the input queue.
*
* The function returns the number of bytes written to the terminal, zero if
* there are no pending data messages available or if there is no established
* IUCV path.
* If the IUCV path has been severed, then -EPIPE is returned to cause a
- * hang up (that is issued by the HVC console layer).
+ * hang up (that is issued by the HVC layer).
*/
static int hvc_iucv_write(struct hvc_iucv_private *priv,
char *buf, int count, int *has_more_data)
@@ -204,12 +208,12 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv,
int written;
int rc;
- /* Immediately return if there is no IUCV connection */
+ /* immediately return if there is no IUCV connection */
if (priv->iucv_state == IUCV_DISCONN)
return 0;
- /* If the IUCV path has been severed, return -EPIPE to inform the
- * hvc console layer to hang up the tty device. */
+ /* if the IUCV path has been severed, return -EPIPE to inform the
+ * HVC layer to hang up the tty device. */
if (priv->iucv_state == IUCV_SEVERED)
return -EPIPE;
@@ -217,7 +221,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv,
if (list_empty(&priv->tty_inqueue))
return 0;
- /* receive a iucv message and flip data to the tty (ldisc) */
+ /* receive an iucv message and flip data to the tty (ldisc) */
rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list);
written = 0;
@@ -260,7 +264,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv,
case MSG_TYPE_WINSIZE:
if (rb->mbuf->datalen != sizeof(struct winsize))
break;
- hvc_resize(priv->hvc, *((struct winsize *)rb->mbuf->data));
+ hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data));
break;
case MSG_TYPE_ERROR: /* ignored ... */
@@ -284,10 +288,9 @@ out_written:
* @buf: Pointer to a buffer to store data
* @count: Size of buffer available for writing
*
- * The hvc_console thread calls this method to read characters from
- * the terminal backend. If an IUCV communication path has been established,
- * pending IUCV messages are received and data is copied into buffer @buf
- * up to @count bytes.
+ * The HVC thread calls this method to read characters from the back-end.
+ * If an IUCV communication path has been established, pending IUCV messages
+ * are received and data is copied into buffer @buf up to @count bytes.
*
* Locking: The routine gets called under an irqsave() spinlock; and
* the routine locks the struct hvc_iucv_private->lock to call
@@ -318,66 +321,122 @@ static int hvc_iucv_get_chars(uint32_t vtermno, char *buf, int count)
}
/**
- * hvc_iucv_send() - Send an IUCV message containing terminal data.
+ * hvc_iucv_queue() - Buffer terminal data for sending.
* @priv: Pointer to struct hvc_iucv_private instance.
* @buf: Buffer containing data to send.
- * @size: Size of buffer and amount of data to send.
+ * @count: Size of buffer and amount of data to send.
+ *
+ * The function queues data for sending. To actually send the buffered data,
+ * a work queue function is scheduled (with QUEUE_SNDBUF_DELAY).
+ * The function returns the number of data bytes that has been buffered.
*
- * If an IUCV communication path is established, the function copies the buffer
- * data to a newly allocated struct iucv_tty_buffer element, sends the data and
- * puts the element to the outqueue.
+ * If the device is not connected, data is ignored and the function returns
+ * @count.
+ * If the buffer is full, the function returns 0.
+ * If an existing IUCV communicaton path has been severed, -EPIPE is returned
+ * (that can be passed to HVC layer to cause a tty hangup).
+ */
+static int hvc_iucv_queue(struct hvc_iucv_private *priv, const char *buf,
+ int count)
+{
+ size_t len;
+
+ if (priv->iucv_state == IUCV_DISCONN)
+ return count; /* ignore data */
+
+ if (priv->iucv_state == IUCV_SEVERED)
+ return -EPIPE;
+
+ len = min_t(size_t, count, SNDBUF_SIZE - priv->sndbuf_len);
+ if (!len)
+ return 0;
+
+ memcpy(priv->sndbuf + priv->sndbuf_len, buf, len);
+ priv->sndbuf_len += len;
+
+ if (priv->iucv_state == IUCV_CONNECTED)
+ schedule_delayed_work(&priv->sndbuf_work, QUEUE_SNDBUF_DELAY);
+
+ return len;
+}
+
+/**
+ * hvc_iucv_send() - Send an IUCV message containing terminal data.
+ * @priv: Pointer to struct hvc_iucv_private instance.
*
- * If there is no IUCV communication path established, the function returns 0.
- * If an existing IUCV communicaton path has been severed, the function returns
- * -EPIPE (can be passed to HVC layer to cause a tty hangup).
+ * If an IUCV communication path has been established, the buffered output data
+ * is sent via an IUCV message and the number of bytes sent is returned.
+ * Returns 0 if there is no established IUCV communication path or
+ * -EPIPE if an existing IUCV communicaton path has been severed.
*/
-static int hvc_iucv_send(struct hvc_iucv_private *priv, const char *buf,
- int count)
+static int hvc_iucv_send(struct hvc_iucv_private *priv)
{
struct iucv_tty_buffer *sb;
- int rc;
- u16 len;
+ int rc, len;
if (priv->iucv_state == IUCV_SEVERED)
return -EPIPE;
if (priv->iucv_state == IUCV_DISCONN)
- return 0;
+ return -EIO;
- len = min_t(u16, MSG_MAX_DATALEN, count);
+ if (!priv->sndbuf_len)
+ return 0;
/* allocate internal buffer to store msg data and also compute total
* message length */
- sb = alloc_tty_buffer(len, GFP_ATOMIC);
+ sb = alloc_tty_buffer(priv->sndbuf_len, GFP_ATOMIC);
if (!sb)
return -ENOMEM;
- sb->mbuf->datalen = len;
- memcpy(sb->mbuf->data, buf, len);
+ memcpy(sb->mbuf->data, priv->sndbuf, priv->sndbuf_len);
+ sb->mbuf->datalen = (u16) priv->sndbuf_len;
+ sb->msg.length = MSG_SIZE(sb->mbuf->datalen);
list_add_tail(&sb->list, &priv->tty_outqueue);
rc = __iucv_message_send(priv->path, &sb->msg, 0, 0,
(void *) sb->mbuf, sb->msg.length);
if (rc) {
+ /* drop the message here; however we might want to handle
+ * 0x03 (msg limit reached) by trying again... */
list_del(&sb->list);
destroy_tty_buffer(sb);
- len = 0;
}
+ len = priv->sndbuf_len;
+ priv->sndbuf_len = 0;
return len;
}
/**
+ * hvc_iucv_sndbuf_work() - Send buffered data over IUCV
+ * @work: Work structure.
+ *
+ * This work queue function sends buffered output data over IUCV and,
+ * if not all buffered data could be sent, reschedules itself.
+ */
+static void hvc_iucv_sndbuf_work(struct work_struct *work)
+{
+ struct hvc_iucv_private *priv;
+
+ priv = container_of(work, struct hvc_iucv_private, sndbuf_work.work);
+ if (!priv)
+ return;
+
+ spin_lock_bh(&priv->lock);
+ hvc_iucv_send(priv);
+ spin_unlock_bh(&priv->lock);
+}
+
+/**
* hvc_iucv_put_chars() - HVC put_chars operation.
* @vtermno: HVC virtual terminal number.
* @buf: Pointer to an buffer to read data from
* @count: Size of buffer available for reading
*
- * The hvc_console thread calls this method to write characters from
- * to the terminal backend.
- * The function calls hvc_iucv_send() under the lock of the
- * struct hvc_iucv_private instance that corresponds to the tty @vtermno.
+ * The HVC thread calls this method to write characters to the back-end.
+ * The function calls hvc_iucv_queue() to queue terminal data for sending.
*
* Locking: The method gets called under an irqsave() spinlock; and
* locks struct hvc_iucv_private->lock.
@@ -385,7 +444,7 @@ static int hvc_iucv_send(struct hvc_iucv_private *priv, const char *buf,
static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count)
{
struct hvc_iucv_private *priv = hvc_iucv_get_private(vtermno);
- int sent;
+ int queued;
if (count <= 0)
return 0;
@@ -394,10 +453,10 @@ static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count)
return -ENODEV;
spin_lock(&priv->lock);
- sent = hvc_iucv_send(priv, buf, count);
+ queued = hvc_iucv_queue(priv, buf, count);
spin_unlock(&priv->lock);
- return sent;
+ return queued;
}
/**
@@ -406,7 +465,7 @@ static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count)
* @id: Additional data (originally passed to hvc_alloc): the index of an struct
* hvc_iucv_private instance.
*
- * The function sets the tty state to TTY_OPEN for the struct hvc_iucv_private
+ * The function sets the tty state to TTY_OPENED for the struct hvc_iucv_private
* instance that is derived from @id. Always returns 0.
*
* Locking: struct hvc_iucv_private->lock, spin_lock_bh
@@ -427,12 +486,8 @@ static int hvc_iucv_notifier_add(struct hvc_struct *hp, int id)
}
/**
- * hvc_iucv_cleanup() - Clean up function if the tty portion is finally closed.
+ * hvc_iucv_cleanup() - Clean up and reset a z/VM IUCV HVC instance.
* @priv: Pointer to the struct hvc_iucv_private instance.
- *
- * The functions severs the established IUCV communication path (if any), and
- * destroy struct iucv_tty_buffer elements from the in- and outqueue. Finally,
- * the functions resets the states to TTY_CLOSED and IUCV_DISCONN.
*/
static void hvc_iucv_cleanup(struct hvc_iucv_private *priv)
{
@@ -441,25 +496,62 @@ static void hvc_iucv_cleanup(struct hvc_iucv_private *priv)
priv->tty_state = TTY_CLOSED;
priv->iucv_state = IUCV_DISCONN;
+
+ priv->sndbuf_len = 0;
}
/**
- * hvc_iucv_notifier_hangup() - HVC notifier for tty hangups.
- * @hp: Pointer to the HVC device (struct hvc_struct)
- * @id: Additional data (originally passed to hvc_alloc): the index of an struct
- * hvc_iucv_private instance.
+ * tty_outqueue_empty() - Test if the tty outq is empty
+ * @priv: Pointer to struct hvc_iucv_private instance.
+ */
+static inline int tty_outqueue_empty(struct hvc_iucv_private *priv)
+{
+ int rc;
+
+ spin_lock_bh(&priv->lock);
+ rc = list_empty(&priv->tty_outqueue);
+ spin_unlock_bh(&priv->lock);
+
+ return rc;
+}
+
+/**
+ * flush_sndbuf_sync() - Flush send buffer and wait for completion
+ * @priv: Pointer to struct hvc_iucv_private instance.
*
- * This routine notifies the HVC backend that a tty hangup (carrier loss,
- * virtual or otherwise) has occured.
+ * The routine cancels a pending sndbuf work, calls hvc_iucv_send()
+ * to flush any buffered terminal output data and waits for completion.
+ */
+static void flush_sndbuf_sync(struct hvc_iucv_private *priv)
+{
+ int sync_wait;
+
+ cancel_delayed_work_sync(&priv->sndbuf_work);
+
+ spin_lock_bh(&priv->lock);
+ hvc_iucv_send(priv); /* force sending buffered data */
+ sync_wait = !list_empty(&priv->tty_outqueue); /* anything queued ? */
+ spin_unlock_bh(&priv->lock);
+
+ if (sync_wait)
+ wait_event_timeout(priv->sndbuf_waitq,
+ tty_outqueue_empty(priv), HZ);
+}
+
+/**
+ * hvc_iucv_notifier_hangup() - HVC notifier for TTY hangups.
+ * @hp: Pointer to the HVC device (struct hvc_struct)
+ * @id: Additional data (originally passed to hvc_alloc):
+ * the index of an struct hvc_iucv_private instance.
*
- * The HVC backend for z/VM IUCV ignores virtual hangups (vhangup()), to keep
- * an existing IUCV communication path established.
+ * This routine notifies the HVC back-end that a tty hangup (carrier loss,
+ * virtual or otherwise) has occured.
+ * The z/VM IUCV HVC device driver ignores virtual hangups (vhangup())
+ * to keep an existing IUCV communication path established.
* (Background: vhangup() is called from user space (by getty or login) to
* disable writing to the tty by other applications).
- *
- * If the tty has been opened (e.g. getty) and an established IUCV path has been
- * severed (we caused the tty hangup in that case), then the functions invokes
- * hvc_iucv_cleanup() to clean up.
+ * If the tty has been opened and an established IUCV path has been severed
+ * (we caused the tty hangup), the function calls hvc_iucv_cleanup().
*
* Locking: struct hvc_iucv_private->lock
*/
@@ -471,12 +563,12 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id)
if (!priv)
return;
+ flush_sndbuf_sync(priv);
+
spin_lock_bh(&priv->lock);
/* NOTE: If the hangup was scheduled by ourself (from the iucv
- * path_servered callback [IUCV_SEVERED]), then we have to
- * finally clean up the tty backend structure and set state to
- * TTY_CLOSED.
- *
+ * path_servered callback [IUCV_SEVERED]), we have to clean up
+ * our structure and to set state to TTY_CLOSED.
* If the tty was hung up otherwise (e.g. vhangup()), then we
* ignore this hangup and keep an established IUCV path open...
* (...the reason is that we are not able to connect back to the
@@ -494,10 +586,9 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id)
* @id: Additional data (originally passed to hvc_alloc):
* the index of an struct hvc_iucv_private instance.
*
- * This routine notifies the HVC backend that the last tty device file
- * descriptor has been closed.
- * The function calls hvc_iucv_cleanup() to clean up the struct hvc_iucv_private
- * instance.
+ * This routine notifies the HVC back-end that the last tty device fd has been
+ * closed. The function calls hvc_iucv_cleanup() to clean up the struct
+ * hvc_iucv_private instance.
*
* Locking: struct hvc_iucv_private->lock
*/
@@ -510,6 +601,8 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
if (!priv)
return;
+ flush_sndbuf_sync(priv);
+
spin_lock_bh(&priv->lock);
path = priv->path; /* save reference to IUCV path */
priv->path = NULL;
@@ -527,20 +620,18 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
/**
* hvc_iucv_path_pending() - IUCV handler to process a connection request.
* @path: Pending path (struct iucv_path)
- * @ipvmid: Originator z/VM system identifier
+ * @ipvmid: z/VM system identifier of originator
* @ipuser: User specified data for this path
* (AF_IUCV: port/service name and originator port)
*
- * The function uses the @ipuser data to check to determine if the pending
- * path belongs to a terminal managed by this HVC backend.
- * If the check is successful, then an additional check is done to ensure
- * that a terminal cannot be accessed multiple times (only one connection
- * to a terminal is allowed). In that particular case, the pending path is
- * severed. If it is the first connection, the pending path is accepted and
- * associated to the struct hvc_iucv_private. The iucv state is updated to
- * reflect that a communication path has been established.
+ * The function uses the @ipuser data to determine if the pending path belongs
+ * to a terminal managed by this device driver.
+ * If the path belongs to this driver, ensure that the terminal is not accessed
+ * multiple times (only one connection to a terminal is allowed).
+ * If the terminal is not yet connected, the pending path is accepted and is
+ * associated to the appropriate struct hvc_iucv_private instance.
*
- * Returns 0 if the path belongs to a terminal managed by the this HVC backend;
+ * Returns 0 if @path belongs to a terminal managed by the this device driver;
* otherwise returns -ENODEV in order to dispatch this path to other handlers.
*
* Locking: struct hvc_iucv_private->lock
@@ -559,7 +650,6 @@ static int hvc_iucv_path_pending(struct iucv_path *path,
priv = hvc_iucv_table[i];
break;
}
-
if (!priv)
return -ENODEV;
@@ -588,6 +678,9 @@ static int hvc_iucv_path_pending(struct iucv_path *path,
priv->path = path;
priv->iucv_state = IUCV_CONNECTED;
+ /* flush buffered output data... */
+ schedule_delayed_work(&priv->sndbuf_work, 5);
+
out_path_handled:
spin_unlock(&priv->lock);
return 0;
@@ -603,8 +696,7 @@ out_path_handled:
* sets the iucv state to IUCV_SEVERED for the associated struct
* hvc_iucv_private instance. Later, the IUCV_SEVERED state triggers a tty
* hangup (hvc_iucv_get_chars() / hvc_iucv_write()).
- *
- * If tty portion of the HVC is closed then clean up the outqueue in addition.
+ * If tty portion of the HVC is closed, clean up the outqueue.
*
* Locking: struct hvc_iucv_private->lock
*/
@@ -615,15 +707,25 @@ static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
spin_lock(&priv->lock);
priv->iucv_state = IUCV_SEVERED;
- /* NOTE: If the tty has not yet been opened by a getty program
- * (e.g. to see console messages), then cleanup the
- * hvc_iucv_private structure to allow re-connects.
+ /* If the tty has not yet been opened, clean up the hvc_iucv_private
+ * structure to allow re-connects.
+ * This is also done for our console device because console hangups
+ * are handled specially and no notifier is called by HVC.
+ * The tty session is active (TTY_OPEN) and ready for re-connects...
*
- * If the tty has been opened, the get_chars() callback returns
- * -EPIPE to signal the hvc console layer to hang up the tty. */
+ * If it has been opened, let get_chars() return -EPIPE to signal the
+ * HVC layer to hang up the tty.
+ * If so, we need to wake up the HVC thread to call get_chars()...
+ */
priv->path = NULL;
if (priv->tty_state == TTY_CLOSED)
hvc_iucv_cleanup(priv);
+ else
+ if (priv->is_console) {
+ hvc_iucv_cleanup(priv);
+ priv->tty_state = TTY_OPENED;
+ } else
+ hvc_kick();
spin_unlock(&priv->lock);
/* finally sever path (outside of priv->lock due to lock ordering) */
@@ -636,9 +738,9 @@ static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
* @path: Pending path (struct iucv_path)
* @msg: Pointer to the IUCV message
*
- * The function stores an incoming message on the input queue for later
+ * The function puts an incoming message on the input queue for later
* processing (by hvc_iucv_get_chars() / hvc_iucv_write()).
- * However, if the tty has not yet been opened, the message is rejected.
+ * If the tty has not yet been opened, the message is rejected.
*
* Locking: struct hvc_iucv_private->lock
*/
@@ -648,6 +750,12 @@ static void hvc_iucv_msg_pending(struct iucv_path *path,
struct hvc_iucv_private *priv = path->private;
struct iucv_tty_buffer *rb;
+ /* reject messages that exceed max size of iucv_tty_msg->datalen */
+ if (msg->length > MSG_SIZE(MSG_MAX_DATALEN)) {
+ iucv_message_reject(path, msg);
+ return;
+ }
+
spin_lock(&priv->lock);
/* reject messages if tty has not yet been opened */
@@ -656,7 +764,7 @@ static void hvc_iucv_msg_pending(struct iucv_path *path,
goto unlock_return;
}
- /* allocate buffer an empty buffer element */
+ /* allocate tty buffer to save iucv msg only */
rb = alloc_tty_buffer(0, GFP_ATOMIC);
if (!rb) {
iucv_message_reject(path, msg);
@@ -666,7 +774,7 @@ static void hvc_iucv_msg_pending(struct iucv_path *path,
list_add_tail(&rb->list, &priv->tty_inqueue);
- hvc_kick(); /* wakup hvc console thread */
+ hvc_kick(); /* wake up hvc thread */
unlock_return:
spin_unlock(&priv->lock);
@@ -677,10 +785,10 @@ unlock_return:
* @path: Pending path (struct iucv_path)
* @msg: Pointer to the IUCV message
*
- * The function is called upon completion of message delivery and the
- * message is removed from the outqueue. Additional delivery information
- * can be found in msg->audit: rejected messages (0x040000 (IPADRJCT)) and
- * purged messages (0x010000 (IPADPGNR)).
+ * The function is called upon completion of message delivery to remove the
+ * message from the outqueue. Additional delivery information can be found
+ * msg->audit: rejected messages (0x040000 (IPADRJCT)), and
+ * purged messages (0x010000 (IPADPGNR)).
*
* Locking: struct hvc_iucv_private->lock
*/
@@ -697,6 +805,7 @@ static void hvc_iucv_msg_complete(struct iucv_path *path,
list_move(&ent->list, &list_remove);
break;
}
+ wake_up(&priv->sndbuf_waitq);
spin_unlock(&priv->lock);
destroy_tty_buffer_list(&list_remove);
}
@@ -713,13 +822,14 @@ static struct hv_ops hvc_iucv_ops = {
/**
* hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance
- * @id: hvc_iucv_table index
+ * @id: hvc_iucv_table index
+ * @is_console: Flag if the instance is used as Linux console
*
- * This function allocates a new hvc_iucv_private struct and put the
- * instance into hvc_iucv_table at index @id.
+ * This function allocates a new hvc_iucv_private structure and stores
+ * the instance in hvc_iucv_table at index @id.
* Returns 0 on success; otherwise non-zero.
*/
-static int __init hvc_iucv_alloc(int id)
+static int __init hvc_iucv_alloc(int id, unsigned int is_console)
{
struct hvc_iucv_private *priv;
char name[9];
@@ -732,18 +842,33 @@ static int __init hvc_iucv_alloc(int id)
spin_lock_init(&priv->lock);
INIT_LIST_HEAD(&priv->tty_outqueue);
INIT_LIST_HEAD(&priv->tty_inqueue);
+ INIT_DELAYED_WORK(&priv->sndbuf_work, hvc_iucv_sndbuf_work);
+ init_waitqueue_head(&priv->sndbuf_waitq);
+
+ priv->sndbuf = (void *) get_zeroed_page(GFP_KERNEL);
+ if (!priv->sndbuf) {
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ /* set console flag */
+ priv->is_console = is_console;
- /* Finally allocate hvc */
- priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id,
- HVC_IUCV_MAGIC + id, &hvc_iucv_ops, PAGE_SIZE);
+ /* finally allocate hvc */
+ priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /* PAGE_SIZE */
+ HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256);
if (IS_ERR(priv->hvc)) {
rc = PTR_ERR(priv->hvc);
+ free_page((unsigned long) priv->sndbuf);
kfree(priv);
return rc;
}
+ /* notify HVC thread instead of using polling */
+ priv->hvc->irq_requested = 1;
+
/* setup iucv related information */
- snprintf(name, 9, "ihvc%-4d", id);
+ snprintf(name, 9, "lnxhvc%-2d", id);
memcpy(priv->srv_name, name, 8);
ASCEBC(priv->srv_name, 8);
@@ -752,15 +877,16 @@ static int __init hvc_iucv_alloc(int id)
}
/**
- * hvc_iucv_init() - Initialization of HVC backend for z/VM IUCV
+ * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
*/
static int __init hvc_iucv_init(void)
{
- int rc, i;
+ int rc;
+ unsigned int i;
if (!MACHINE_IS_VM) {
- pr_warning("The z/VM IUCV Hypervisor console cannot be "
- "used without z/VM.\n");
+ pr_info("The z/VM IUCV HVC device driver cannot "
+ "be used without z/VM\n");
return -ENODEV;
}
@@ -774,26 +900,33 @@ static int __init hvc_iucv_init(void)
sizeof(struct iucv_tty_buffer),
0, 0, NULL);
if (!hvc_iucv_buffer_cache) {
- pr_err("Not enough memory for driver initialization "
- "(rs=%d).\n", 1);
+ pr_err("Allocating memory failed with reason code=%d\n", 1);
return -ENOMEM;
}
hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR,
hvc_iucv_buffer_cache);
if (!hvc_iucv_mempool) {
- pr_err("Not enough memory for driver initialization "
- "(rs=%d).\n", 2);
+ pr_err("Allocating memory failed with reason code=%d\n", 2);
kmem_cache_destroy(hvc_iucv_buffer_cache);
return -ENOMEM;
}
+ /* register the first terminal device as console
+ * (must be done before allocating hvc terminal devices) */
+ rc = hvc_instantiate(HVC_IUCV_MAGIC, IUCV_HVC_CON_IDX, &hvc_iucv_ops);
+ if (rc) {
+ pr_err("Registering HVC terminal device as "
+ "Linux console failed\n");
+ goto out_error_memory;
+ }
+
/* allocate hvc_iucv_private structs */
for (i = 0; i < hvc_iucv_devices; i++) {
- rc = hvc_iucv_alloc(i);
+ rc = hvc_iucv_alloc(i, (i == IUCV_HVC_CON_IDX) ? 1 : 0);
if (rc) {
- pr_err("Could not create new z/VM IUCV HVC backend "
- "rc=%d.\n", rc);
+ pr_err("Creating a new HVC terminal device "
+ "failed with error code=%d\n", rc);
goto out_error_hvc;
}
}
@@ -801,7 +934,8 @@ static int __init hvc_iucv_init(void)
/* register IUCV callback handler */
rc = iucv_register(&hvc_iucv_handler, 0);
if (rc) {
- pr_err("Could not register iucv handler (rc=%d).\n", rc);
+ pr_err("Registering IUCV handlers failed with error code=%d\n",
+ rc);
goto out_error_iucv;
}
@@ -816,22 +950,13 @@ out_error_hvc:
hvc_remove(hvc_iucv_table[i]->hvc);
kfree(hvc_iucv_table[i]);
}
+out_error_memory:
mempool_destroy(hvc_iucv_mempool);
kmem_cache_destroy(hvc_iucv_buffer_cache);
return rc;
}
/**
- * hvc_iucv_console_init() - Early console initialization
- */
-static int __init hvc_iucv_console_init(void)
-{
- if (!MACHINE_IS_VM || !hvc_iucv_devices)
- return -ENODEV;
- return hvc_instantiate(HVC_IUCV_MAGIC, 0, &hvc_iucv_ops);
-}
-
-/**
* hvc_iucv_config() - Parsing of hvc_iucv= kernel command line parameter
* @val: Parameter value (numeric)
*/
@@ -841,10 +966,5 @@ static int __init hvc_iucv_config(char *val)
}
-module_init(hvc_iucv_init);
-console_initcall(hvc_iucv_console_init);
+device_initcall(hvc_iucv_init);
__setup("hvc_iucv=", hvc_iucv_config);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("HVC back-end for z/VM IUCV.");
-MODULE_AUTHOR("Hendrik Brueckner <brueckner@linux.vnet.ibm.com>");
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index af055287271a..406f8742a260 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -997,14 +997,14 @@ out:
static int hvsi_write_room(struct tty_struct *tty)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+ struct hvsi_struct *hp = tty->driver_data;
return N_OUTBUF - hp->n_outbuf;
}
static int hvsi_chars_in_buffer(struct tty_struct *tty)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+ struct hvsi_struct *hp = tty->driver_data;
return hp->n_outbuf;
}
@@ -1070,7 +1070,7 @@ out:
*/
static void hvsi_throttle(struct tty_struct *tty)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+ struct hvsi_struct *hp = tty->driver_data;
pr_debug("%s\n", __func__);
@@ -1079,7 +1079,7 @@ static void hvsi_throttle(struct tty_struct *tty)
static void hvsi_unthrottle(struct tty_struct *tty)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+ struct hvsi_struct *hp = tty->driver_data;
unsigned long flags;
int shouldflip = 0;
@@ -1100,7 +1100,7 @@ static void hvsi_unthrottle(struct tty_struct *tty)
static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+ struct hvsi_struct *hp = tty->driver_data;
hvsi_get_mctrl(hp);
return hp->mctrl;
@@ -1109,7 +1109,7 @@ static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
static int hvsi_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
+ struct hvsi_struct *hp = tty->driver_data;
unsigned long flags;
uint16_t new_mctrl;
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index 8859aeac2d25..9b3e09cd41f9 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -482,7 +482,7 @@ static void n2rng_dump_test_buffer(struct n2rng *np)
int i;
for (i = 0; i < SELFTEST_BUFFER_WORDS; i++)
- dev_err(&np->op->dev, "Test buffer slot %d [0x%016lx]\n",
+ dev_err(&np->op->dev, "Test buffer slot %d [0x%016llx]\n",
i, np->test_buffer[i]);
}
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index d4e7dca06e4f..ba68a4671cb5 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -102,7 +102,7 @@ static int __init omap_rng_probe(struct platform_device *pdev)
return -EBUSY;
if (cpu_is_omap24xx()) {
- rng_ick = clk_get(NULL, "rng_ick");
+ rng_ick = clk_get(&pdev->dev, "rng_ick");
if (IS_ERR(rng_ick)) {
dev_err(&pdev->dev, "Could not get rng_ick\n");
ret = PTR_ERR(rng_ick);
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index b60d425ce8d1..fc8cf7ac7f2b 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -485,7 +485,21 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "MP061"),
},
},
- { }
+ {
+ .ident = "Dell Precision",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Precision"),
+ },
+ },
+ {
+ .ident = "Dell Vostro",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
+ },
+ },
+ { }
};
/*
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 04e4549299ba..24aa6e88e223 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -328,11 +328,13 @@ static inline void drop_rts(struct isi_port *port)
}
/* card->lock MUST NOT be held */
-static inline void raise_dtr_rts(struct isi_port *port)
+
+static void isicom_raise_dtr_rts(struct tty_port *port)
{
- struct isi_board *card = port->card;
+ struct isi_port *ip = container_of(port, struct isi_port, port);
+ struct isi_board *card = ip->card;
unsigned long base = card->base;
- u16 channel = port->channel;
+ u16 channel = ip->channel;
if (!lock_card(card))
return;
@@ -340,7 +342,7 @@ static inline void raise_dtr_rts(struct isi_port *port)
outw(0x8000 | (channel << card->shift_count) | 0x02, base);
outw(0x0f04, base);
InterruptTheCard(base);
- port->status |= (ISI_DTR | ISI_RTS);
+ ip->status |= (ISI_DTR | ISI_RTS);
unlock_card(card);
}
@@ -830,80 +832,10 @@ static int isicom_setup_port(struct tty_struct *tty)
return 0;
}
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
- struct isi_port *port)
+static int isicom_carrier_raised(struct tty_port *port)
{
- struct isi_board *card = port->card;
- int do_clocal = 0, retval;
- unsigned long flags;
- DECLARE_WAITQUEUE(wait, current);
-
- /* block if port is in the process of being closed */
-
- if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
- pr_dbg("block_til_ready: close in progress.\n");
- interruptible_sleep_on(&port->port.close_wait);
- if (port->port.flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
- }
-
- /* if non-blocking mode is set ... */
-
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- pr_dbg("block_til_ready: non-block mode.\n");
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (C_CLOCAL(tty))
- do_clocal = 1;
-
- /* block waiting for DCD to be asserted, and while
- callout dev is busy */
- retval = 0;
- add_wait_queue(&port->port.open_wait, &wait);
-
- spin_lock_irqsave(&card->card_lock, flags);
- if (!tty_hung_up_p(filp))
- port->port.count--;
- port->port.blocked_open++;
- spin_unlock_irqrestore(&card->card_lock, flags);
-
- while (1) {
- raise_dtr_rts(port);
-
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) {
- if (port->port.flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(port->port.flags & ASYNC_CLOSING) &&
- (do_clocal || (port->status & ISI_DCD))) {
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->port.open_wait, &wait);
- spin_lock_irqsave(&card->card_lock, flags);
- if (!tty_hung_up_p(filp))
- port->port.count++;
- port->port.blocked_open--;
- spin_unlock_irqrestore(&card->card_lock, flags);
- if (retval)
- return retval;
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
+ struct isi_port *ip = container_of(port, struct isi_port, port);
+ return (ip->status & ISI_DCD)?1 : 0;
}
static int isicom_open(struct tty_struct *tty, struct file *filp)
@@ -932,12 +864,13 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
isicom_setup_board(card);
+ /* FIXME: locking on port.count etc */
port->port.count++;
tty->driver_data = port;
tty_port_tty_set(&port->port, tty);
error = isicom_setup_port(tty);
if (error == 0)
- error = block_til_ready(tty, filp, port);
+ error = tty_port_block_til_ready(&port->port, tty, filp);
return error;
}
@@ -1012,76 +945,30 @@ static void isicom_flush_buffer(struct tty_struct *tty)
static void isicom_close(struct tty_struct *tty, struct file *filp)
{
- struct isi_port *port = tty->driver_data;
+ struct isi_port *ip = tty->driver_data;
+ struct tty_port *port = &ip->port;
struct isi_board *card;
unsigned long flags;
- if (!port)
- return;
- card = port->card;
- if (isicom_paranoia_check(port, tty->name, "isicom_close"))
- return;
-
- pr_dbg("Close start!!!.\n");
-
- spin_lock_irqsave(&card->card_lock, flags);
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&card->card_lock, flags);
- return;
- }
-
- if (tty->count == 1 && port->port.count != 1) {
- printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
- "count tty->count = 1 port count = %d.\n",
- card->base, port->port.count);
- port->port.count = 1;
- }
- if (--port->port.count < 0) {
- printk(KERN_WARNING "ISICOM:(0x%lx) isicom_close: bad port "
- "count for channel%d = %d", card->base, port->channel,
- port->port.count);
- port->port.count = 0;
- }
+ BUG_ON(!ip);
- if (port->port.count) {
- spin_unlock_irqrestore(&card->card_lock, flags);
+ card = ip->card;
+ if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
return;
- }
- port->port.flags |= ASYNC_CLOSING;
- tty->closing = 1;
- spin_unlock_irqrestore(&card->card_lock, flags);
- if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, port->port.closing_wait);
/* indicate to the card that no more data can be received
on this port */
spin_lock_irqsave(&card->card_lock, flags);
- if (port->port.flags & ASYNC_INITIALIZED) {
- card->port_status &= ~(1 << port->channel);
+ if (port->flags & ASYNC_INITIALIZED) {
+ card->port_status &= ~(1 << ip->channel);
outw(card->port_status, card->base + 0x02);
}
- isicom_shutdown_port(port);
+ isicom_shutdown_port(ip);
spin_unlock_irqrestore(&card->card_lock, flags);
isicom_flush_buffer(tty);
- tty_ldisc_flush(tty);
-
- spin_lock_irqsave(&card->card_lock, flags);
- tty->closing = 0;
-
- if (port->port.blocked_open) {
- spin_unlock_irqrestore(&card->card_lock, flags);
- if (port->port.close_delay) {
- pr_dbg("scheduling until time out.\n");
- msleep_interruptible(
- jiffies_to_msecs(port->port.close_delay));
- }
- spin_lock_irqsave(&card->card_lock, flags);
- wake_up_interruptible(&port->port.open_wait);
- }
- port->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
- wake_up_interruptible(&port->port.close_wait);
- spin_unlock_irqrestore(&card->card_lock, flags);
+
+ tty_port_close_end(port, tty);
}
/* write et all */
@@ -1420,10 +1307,7 @@ static void isicom_hangup(struct tty_struct *tty)
isicom_shutdown_port(port);
spin_unlock_irqrestore(&port->card->card_lock, flags);
- port->port.count = 0;
- port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- tty_port_tty_set(&port->port, NULL);
- wake_up_interruptible(&port->port.open_wait);
+ tty_port_hangup(&port->port);
}
@@ -1452,6 +1336,11 @@ static const struct tty_operations isicom_ops = {
.break_ctl = isicom_send_break,
};
+static const struct tty_port_operations isicom_port_ops = {
+ .carrier_raised = isicom_carrier_raised,
+ .raise_dtr_rts = isicom_raise_dtr_rts,
+};
+
static int __devinit reset_card(struct pci_dev *pdev,
const unsigned int card, unsigned int *signature)
{
@@ -1794,6 +1683,7 @@ static int __init isicom_init(void)
spin_lock_init(&isi_card[idx].card_lock);
for (channel = 0; channel < 16; channel++, port++) {
tty_port_init(&port->port);
+ port->port.ops = &isicom_port_ops;
port->magic = ISICOM_MAGIC;
port->card = &isi_card[idx];
port->channel = channel;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 4b10770fa937..5c3dc6b8411c 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -151,7 +151,7 @@ static char *stli_drvversion = "5.6.0";
static char *stli_serialname = "ttyE";
static struct tty_driver *stli_serial;
-
+static const struct tty_port_operations stli_port_ops;
#define STLI_TXBUFSIZE 4096
@@ -626,8 +626,6 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
- struct stliport *portp, struct file *filp);
static int stli_setport(struct tty_struct *tty);
static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
@@ -769,7 +767,7 @@ static int stli_parsebrd(struct stlconf *confp, char **argp)
break;
}
if (i == ARRAY_SIZE(stli_brdstr)) {
- printk("STALLION: unknown board name, %s?\n", argp[0]);
+ printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]);
return 0;
}
@@ -787,6 +785,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
{
struct stlibrd *brdp;
struct stliport *portp;
+ struct tty_port *port;
unsigned int minordev, brdnr, portnr;
int rc;
@@ -808,30 +807,19 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
if (portp->devnr < 1)
return -ENODEV;
-
-
-/*
- * Check if this port is in the middle of closing. If so then wait
- * until it is closed then return error status based on flag settings.
- * The sleep here does not need interrupt protection since the wakeup
- * for it is done with the same context.
- */
- if (portp->port.flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&portp->port.close_wait);
- if (portp->port.flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- return -ERESTARTSYS;
- }
+ port = &portp->port;
/*
* On the first open of the device setup the port hardware, and
* initialize the per port data structure. Since initializing the port
* requires several commands to the board we will need to wait for any
* other open that is already initializing the port.
+ *
+ * Review - locking
*/
- tty_port_tty_set(&portp->port, tty);
+ tty_port_tty_set(port, tty);
tty->driver_data = portp;
- portp->port.count++;
+ port->count++;
wait_event_interruptible(portp->raw_wait,
!test_bit(ST_INITIALIZING, &portp->state));
@@ -841,7 +829,8 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
set_bit(ST_INITIALIZING, &portp->state);
if ((rc = stli_initopen(tty, brdp, portp)) >= 0) {
- portp->port.flags |= ASYNC_INITIALIZED;
+ /* Locking */
+ port->flags |= ASYNC_INITIALIZED;
clear_bit(TTY_IO_ERROR, &tty->flags);
}
clear_bit(ST_INITIALIZING, &portp->state);
@@ -849,31 +838,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
if (rc < 0)
return rc;
}
-
-/*
- * Check if this port is in the middle of closing. If so then wait
- * until it is closed then return error status, based on flag settings.
- * The sleep here does not need interrupt protection since the wakeup
- * for it is done with the same context.
- */
- if (portp->port.flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&portp->port.close_wait);
- if (portp->port.flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- return -ERESTARTSYS;
- }
-
-/*
- * Based on type of open being done check if it can overlap with any
- * previous opens still in effect. If we are a normal serial device
- * then also we might have to wait for carrier.
- */
- if (!(filp->f_flags & O_NONBLOCK)) {
- if ((rc = stli_waitcarrier(tty, brdp, portp, filp)) != 0)
- return rc;
- }
- portp->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
+ return tty_port_block_til_ready(&portp->port, tty, filp);
}
/*****************************************************************************/
@@ -882,25 +847,16 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
{
struct stlibrd *brdp;
struct stliport *portp;
+ struct tty_port *port;
unsigned long flags;
portp = tty->driver_data;
if (portp == NULL)
return;
+ port = &portp->port;
- spin_lock_irqsave(&stli_lock, flags);
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&stli_lock, flags);
- return;
- }
- if ((tty->count == 1) && (portp->port.count != 1))
- portp->port.count = 1;
- if (portp->port.count-- > 1) {
- spin_unlock_irqrestore(&stli_lock, flags);
+ if (tty_port_close_start(port, tty, filp) == 0)
return;
- }
-
- portp->port.flags |= ASYNC_CLOSING;
/*
* May want to wait for data to drain before closing. The BUSY flag
@@ -908,15 +864,19 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
* updated by messages from the slave - indicating when all chars
* really have drained.
*/
+ spin_lock_irqsave(&stli_lock, flags);
if (tty == stli_txcooktty)
stli_flushchars(tty);
- tty->closing = 1;
spin_unlock_irqrestore(&stli_lock, flags);
+ /* We end up doing this twice for the moment. This needs looking at
+ eventually. Note we still use portp->closing_wait as a result */
if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, portp->closing_wait);
- portp->port.flags &= ~ASYNC_INITIALIZED;
+ /* FIXME: port locking here needs attending to */
+ port->flags &= ~ASYNC_INITIALIZED;
+
brdp = stli_brds[portp->brdnr];
stli_rawclose(brdp, portp, 0, 0);
if (tty->termios->c_cflag & HUPCL) {
@@ -934,17 +894,8 @@ static void stli_close(struct tty_struct *tty, struct file *filp)
set_bit(ST_DOFLUSHRX, &portp->state);
stli_flushbuffer(tty);
- tty->closing = 0;
- tty_port_tty_set(&portp->port, NULL);
-
- if (portp->openwaitcnt) {
- if (portp->close_delay)
- msleep_interruptible(jiffies_to_msecs(portp->close_delay));
- wake_up_interruptible(&portp->port.open_wait);
- }
-
- portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&portp->port.close_wait);
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
}
/*****************************************************************************/
@@ -1183,62 +1134,23 @@ static int stli_setport(struct tty_struct *tty)
/*****************************************************************************/
-/*
- * Possibly need to wait for carrier (DCD signal) to come high. Say
- * maybe because if we are clocal then we don't need to wait...
- */
-
-static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp,
- struct stliport *portp, struct file *filp)
+static int stli_carrier_raised(struct tty_port *port)
{
- unsigned long flags;
- int rc, doclocal;
-
- rc = 0;
- doclocal = 0;
-
- if (tty->termios->c_cflag & CLOCAL)
- doclocal++;
-
- spin_lock_irqsave(&stli_lock, flags);
- portp->openwaitcnt++;
- if (! tty_hung_up_p(filp))
- portp->port.count--;
- spin_unlock_irqrestore(&stli_lock, flags);
-
- for (;;) {
- stli_mkasysigs(&portp->asig, 1, 1);
- if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,
- &portp->asig, sizeof(asysigs_t), 0)) < 0)
- break;
- if (tty_hung_up_p(filp) ||
- ((portp->port.flags & ASYNC_INITIALIZED) == 0)) {
- if (portp->port.flags & ASYNC_HUP_NOTIFY)
- rc = -EBUSY;
- else
- rc = -ERESTARTSYS;
- break;
- }
- if (((portp->port.flags & ASYNC_CLOSING) == 0) &&
- (doclocal || (portp->sigs & TIOCM_CD))) {
- break;
- }
- if (signal_pending(current)) {
- rc = -ERESTARTSYS;
- break;
- }
- interruptible_sleep_on(&portp->port.open_wait);
- }
-
- spin_lock_irqsave(&stli_lock, flags);
- if (! tty_hung_up_p(filp))
- portp->port.count++;
- portp->openwaitcnt--;
- spin_unlock_irqrestore(&stli_lock, flags);
+ struct stliport *portp = container_of(port, struct stliport, port);
+ return (portp->sigs & TIOCM_CD) ? 1 : 0;
+}
- return rc;
+static void stli_raise_dtr_rts(struct tty_port *port)
+{
+ struct stliport *portp = container_of(port, struct stliport, port);
+ struct stlibrd *brdp = stli_brds[portp->brdnr];
+ stli_mkasysigs(&portp->asig, 1, 1);
+ if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
+ sizeof(asysigs_t), 0) < 0)
+ printk(KERN_WARNING "istallion: dtr raise failed.\n");
}
+
/*****************************************************************************/
/*
@@ -1550,7 +1462,7 @@ static int stli_getserial(struct stliport *portp, struct serial_struct __user *s
sio.irq = 0;
sio.flags = portp->port.flags;
sio.baud_base = portp->baud_base;
- sio.close_delay = portp->close_delay;
+ sio.close_delay = portp->port.close_delay;
sio.closing_wait = portp->closing_wait;
sio.custom_divisor = portp->custom_divisor;
sio.xmit_fifo_size = 0;
@@ -1582,7 +1494,7 @@ static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *s
return -EFAULT;
if (!capable(CAP_SYS_ADMIN)) {
if ((sio.baud_base != portp->baud_base) ||
- (sio.close_delay != portp->close_delay) ||
+ (sio.close_delay != portp->port.close_delay) ||
((sio.flags & ~ASYNC_USR_MASK) !=
(portp->port.flags & ~ASYNC_USR_MASK)))
return -EPERM;
@@ -1591,7 +1503,7 @@ static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *s
portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
(sio.flags & ASYNC_USR_MASK);
portp->baud_base = sio.baud_base;
- portp->close_delay = sio.close_delay;
+ portp->port.close_delay = sio.close_delay;
portp->closing_wait = sio.closing_wait;
portp->custom_divisor = sio.custom_divisor;
@@ -1821,6 +1733,7 @@ static void stli_hangup(struct tty_struct *tty)
{
struct stliport *portp;
struct stlibrd *brdp;
+ struct tty_port *port;
unsigned long flags;
portp = tty->driver_data;
@@ -1831,8 +1744,11 @@ static void stli_hangup(struct tty_struct *tty)
brdp = stli_brds[portp->brdnr];
if (brdp == NULL)
return;
+ port = &portp->port;
- portp->port.flags &= ~ASYNC_INITIALIZED;
+ spin_lock_irqsave(&port->lock, flags);
+ port->flags &= ~ASYNC_INITIALIZED;
+ spin_unlock_irqrestore(&port->lock, flags);
if (!test_bit(ST_CLOSING, &portp->state))
stli_rawclose(brdp, portp, 0, 0);
@@ -1853,12 +1769,9 @@ static void stli_hangup(struct tty_struct *tty)
clear_bit(ST_TXBUSY, &portp->state);
clear_bit(ST_RXSTOP, &portp->state);
set_bit(TTY_IO_ERROR, &tty->flags);
- tty_port_tty_set(&portp->port, NULL);
- portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- portp->port.count = 0;
spin_unlock_irqrestore(&stli_lock, flags);
- wake_up_interruptible(&portp->port.open_wait);
+ tty_port_hangup(port);
}
/*****************************************************************************/
@@ -2132,7 +2045,7 @@ static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigne
unsigned char __iomem *bits;
if (test_bit(ST_CMDING, &portp->state)) {
- printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",
+ printk(KERN_ERR "istallion: command already busy, cmd=%x!\n",
(int) cmd);
return;
}
@@ -2692,16 +2605,17 @@ static int stli_initports(struct stlibrd *brdp)
for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
if (!portp) {
- printk("STALLION: failed to allocate port structure\n");
+ printk(KERN_WARNING "istallion: failed to allocate port structure\n");
continue;
}
tty_port_init(&portp->port);
+ portp->port.ops = &stli_port_ops;
portp->magic = STLI_PORTMAGIC;
portp->portnr = i;
portp->brdnr = brdp->brdnr;
portp->panelnr = panelnr;
portp->baud_base = STL_BAUDBASE;
- portp->close_delay = STL_CLOSEDELAY;
+ portp->port.close_delay = STL_CLOSEDELAY;
portp->closing_wait = 30 * HZ;
init_waitqueue_head(&portp->port.open_wait);
init_waitqueue_head(&portp->port.close_wait);
@@ -2758,7 +2672,7 @@ static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offse
unsigned char val;
if (offset > brdp->memsize) {
- printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+ printk(KERN_ERR "istallion: shared memory pointer=%x out of "
"range at line=%d(%d), brd=%d\n",
(int) offset, line, __LINE__, brdp->brdnr);
ptr = NULL;
@@ -2832,7 +2746,7 @@ static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long off
unsigned char val;
if (offset > brdp->memsize) {
- printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+ printk(KERN_ERR "istallion: shared memory pointer=%x out of "
"range at line=%d(%d), brd=%d\n",
(int) offset, line, __LINE__, brdp->brdnr);
ptr = NULL;
@@ -2884,7 +2798,7 @@ static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long off
unsigned char val;
if (offset > brdp->memsize) {
- printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+ printk(KERN_ERR "istallion: shared memory pointer=%x out of "
"range at line=%d(%d), brd=%d\n",
(int) offset, line, __LINE__, brdp->brdnr);
ptr = NULL;
@@ -2929,7 +2843,7 @@ static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long of
unsigned char val;
if (offset > brdp->memsize) {
- printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+ printk(KERN_ERR "istallion: shared memory pointer=%x out of "
"range at line=%d(%d), board=%d\n",
(int) offset, line, __LINE__, brdp->brdnr);
ptr = NULL;
@@ -2994,7 +2908,7 @@ static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offse
void __iomem *ptr;
if (offset > brdp->memsize) {
- printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+ printk(KERN_ERR "istallion: shared memory pointer=%x out of "
"range at line=%d(%d), brd=%d\n",
(int) offset, line, __LINE__, brdp->brdnr);
ptr = NULL;
@@ -3060,7 +2974,7 @@ static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offs
unsigned char val;
if (offset > brdp->memsize) {
- printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+ printk(KERN_ERR "istallion: shared memory pointer=%x out of "
"range at line=%d(%d), brd=%d\n",
(int) offset, line, __LINE__, brdp->brdnr);
ptr = NULL;
@@ -3499,7 +3413,7 @@ static int stli_startbrd(struct stlibrd *brdp)
#endif
if (nrdevs < (brdp->nrports + 1)) {
- printk(KERN_ERR "STALLION: slave failed to allocate memory for "
+ printk(KERN_ERR "istallion: slave failed to allocate memory for "
"all devices, devices=%d\n", nrdevs);
brdp->nrports = nrdevs - 1;
}
@@ -3509,13 +3423,13 @@ static int stli_startbrd(struct stlibrd *brdp)
brdp->bitsize = (nrdevs + 7) / 8;
memoff = readl(&hdrp->memp);
if (memoff > brdp->memsize) {
- printk(KERN_ERR "STALLION: corrupted shared memory region?\n");
+ printk(KERN_ERR "istallion: corrupted shared memory region?\n");
rc = -EIO;
goto stli_donestartup;
}
memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff);
if (readw(&memp->dtype) != TYP_ASYNCTRL) {
- printk(KERN_ERR "STALLION: no slave control device found\n");
+ printk(KERN_ERR "istallion: no slave control device found\n");
goto stli_donestartup;
}
memp++;
@@ -3600,7 +3514,7 @@ static int __devinit stli_brdinit(struct stlibrd *brdp)
retval = stli_initonb(brdp);
break;
default:
- printk(KERN_ERR "STALLION: board=%d is unknown board "
+ printk(KERN_ERR "istallion: board=%d is unknown board "
"type=%d\n", brdp->brdnr, brdp->brdtype);
retval = -ENODEV;
}
@@ -3609,7 +3523,7 @@ static int __devinit stli_brdinit(struct stlibrd *brdp)
return retval;
stli_initports(brdp);
- printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x "
+ printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x "
"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
brdp->nrpanels, brdp->nrports);
@@ -3703,7 +3617,7 @@ static int stli_eisamemprobe(struct stlibrd *brdp)
if (! foundit) {
brdp->memaddr = 0;
brdp->membase = NULL;
- printk(KERN_ERR "STALLION: failed to probe shared memory "
+ printk(KERN_ERR "istallion: failed to probe shared memory "
"region for %s in EISA slot=%d\n",
stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
return -ENODEV;
@@ -3848,7 +3762,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev,
mutex_lock(&stli_brdslock);
brdnr = stli_getbrdnr();
if (brdnr < 0) {
- printk(KERN_INFO "STALLION: too many boards found, "
+ printk(KERN_INFO "istallion: too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
mutex_unlock(&stli_brdslock);
retval = -EIO;
@@ -3920,7 +3834,7 @@ static struct stlibrd *stli_allocbrd(void)
brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
if (!brdp) {
- printk(KERN_ERR "STALLION: failed to allocate memory "
+ printk(KERN_ERR "istallion: failed to allocate memory "
"(size=%Zd)\n", sizeof(struct stlibrd));
return NULL;
}
@@ -4518,6 +4432,11 @@ static const struct tty_operations stli_ops = {
.tiocmset = stli_tiocmset,
};
+static const struct tty_port_operations stli_port_ops = {
+ .carrier_raised = stli_carrier_raised,
+ .raise_dtr_rts = stli_raise_dtr_rts,
+};
+
/*****************************************************************************/
/*
* Loadable module initialization stuff.
@@ -4554,7 +4473,7 @@ static int __init istallion_module_init(void)
stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
if (!stli_txcookbuf) {
- printk(KERN_ERR "STALLION: failed to allocate memory "
+ printk(KERN_ERR "istallion: failed to allocate memory "
"(size=%d)\n", STLI_TXBUFSIZE);
retval = -ENOMEM;
goto err;
@@ -4579,7 +4498,7 @@ static int __init istallion_module_init(void)
retval = tty_register_driver(stli_serial);
if (retval) {
- printk(KERN_ERR "STALLION: failed to register serial driver\n");
+ printk(KERN_ERR "istallion: failed to register serial driver\n");
goto err_ttyput;
}
@@ -4593,7 +4512,7 @@ static int __init istallion_module_init(void)
*/
retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
if (retval) {
- printk(KERN_ERR "STALLION: failed to register serial memory "
+ printk(KERN_ERR "istallion: failed to register serial memory "
"device\n");
goto err_deinit;
}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 6431f6921a67..3586b3b3df3f 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -425,9 +425,6 @@ static ssize_t read_oldmem(struct file *file, char __user *buf,
}
#endif
-extern long vread(char *buf, char *addr, unsigned long count);
-extern long vwrite(char *buf, char *addr, unsigned long count);
-
#ifdef CONFIG_DEVKMEM
/*
* This function reads the *virtual* memory as seen by the kernel.
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 12d327a2c9ba..8b0da97d5293 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -206,6 +206,7 @@ static void moxa_poll(unsigned long);
static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
static void moxa_setup_empty_event(struct tty_struct *);
static void moxa_shut_down(struct tty_struct *);
+static int moxa_carrier_raised(struct tty_port *);
/*
* moxa board interface functions:
*/
@@ -405,6 +406,10 @@ static const struct tty_operations moxa_ops = {
.tiocmset = moxa_tiocmset,
};
+static const struct tty_port_operations moxa_port_ops = {
+ .carrier_raised = moxa_carrier_raised,
+};
+
static struct tty_driver *moxaDriver;
static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
static DEFINE_SPINLOCK(moxa_lock);
@@ -826,6 +831,7 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
tty_port_init(&p->port);
+ p->port.ops = &moxa_port_ops;
p->type = PORT_16550A;
p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
}
@@ -1115,15 +1121,27 @@ static void moxa_close_port(struct tty_struct *tty)
tty_port_tty_set(&ch->port, NULL);
}
+static int moxa_carrier_raised(struct tty_port *port)
+{
+ struct moxa_port *ch = container_of(port, struct moxa_port, port);
+ int dcd;
+
+ spin_lock_bh(&moxa_lock);
+ dcd = ch->DCDState;
+ spin_unlock_bh(&moxa_lock);
+ return dcd;
+}
+
static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
struct moxa_port *ch)
{
+ struct tty_port *port = &ch->port;
DEFINE_WAIT(wait);
int retval = 0;
u8 dcd;
while (1) {
- prepare_to_wait(&ch->port.open_wait, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp)) {
#ifdef SERIAL_DO_RESTART
retval = -ERESTARTSYS;
@@ -1132,9 +1150,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
#endif
break;
}
- spin_lock_bh(&moxa_lock);
- dcd = ch->DCDState;
- spin_unlock_bh(&moxa_lock);
+ dcd = tty_port_carrier_raised(port);
if (dcd)
break;
@@ -1144,7 +1160,7 @@ static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
}
schedule();
}
- finish_wait(&ch->port.open_wait, &wait);
+ finish_wait(&port->open_wait, &wait);
return retval;
}
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 4f8d67fed292..94ad2c3bfc4a 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -663,7 +663,7 @@ static int __init mwave_init(void)
#if 0
/* sysfs */
memset(&mwave_device, 0, sizeof (struct device));
- snprintf(mwave_device.bus_id, BUS_ID_SIZE, "mwave");
+ dev_set_name(&mwave_device, "mwave");
if (device_register(&mwave_device))
goto cleanup_error;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 047766915411..402c9f217f83 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -541,74 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
return status;
}
-static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
- struct mxser_port *port)
+static int mxser_carrier_raised(struct tty_port *port)
{
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0;
- unsigned long flags;
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- test_bit(TTY_IO_ERROR, &tty->flags)) {
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
+ struct mxser_port *mp = container_of(port, struct mxser_port, port);
+ return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
+}
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
+static void mxser_raise_dtr_rts(struct tty_port *port)
+{
+ struct mxser_port *mp = container_of(port, struct mxser_port, port);
+ unsigned long flags;
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, port->port.count is dropped by one, so that
- * mxser_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&port->port.open_wait, &wait);
-
- spin_lock_irqsave(&port->slock, flags);
- if (!tty_hung_up_p(filp))
- port->port.count--;
- spin_unlock_irqrestore(&port->slock, flags);
- port->port.blocked_open++;
- while (1) {
- spin_lock_irqsave(&port->slock, flags);
- outb(inb(port->ioaddr + UART_MCR) |
- UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR);
- spin_unlock_irqrestore(&port->slock, flags);
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) {
- if (port->port.flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(port->port.flags & ASYNC_CLOSING) &&
- (do_clocal ||
- (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->port.open_wait, &wait);
- if (!tty_hung_up_p(filp))
- port->port.count++;
- port->port.blocked_open--;
- if (retval)
- return retval;
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
+ spin_lock_irqsave(&mp->slock, flags);
+ outb(inb(mp->ioaddr + UART_MCR) |
+ UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+ spin_unlock_irqrestore(&mp->slock, flags);
}
static int mxser_set_baud(struct tty_struct *tty, long newspd)
@@ -1087,14 +1034,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
/*
* Start up serial port
*/
- spin_lock_irqsave(&info->slock, flags);
+ spin_lock_irqsave(&info->port.lock, flags);
info->port.count++;
- spin_unlock_irqrestore(&info->slock, flags);
+ spin_unlock_irqrestore(&info->port.lock, flags);
retval = mxser_startup(tty);
if (retval)
return retval;
- retval = mxser_block_til_ready(tty, filp, info);
+ retval = tty_port_block_til_ready(&info->port, tty, filp);
if (retval)
return retval;
@@ -1133,58 +1080,27 @@ static void mxser_flush_buffer(struct tty_struct *tty)
static void mxser_close(struct tty_struct *tty, struct file *filp)
{
struct mxser_port *info = tty->driver_data;
+ struct tty_port *port = &info->port;
unsigned long timeout;
- unsigned long flags;
if (tty->index == MXSER_PORTS)
return;
if (!info)
return;
- spin_lock_irqsave(&info->slock, flags);
-
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&info->slock, flags);
- return;
- }
- if ((tty->count == 1) && (info->port.count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. Info->port.count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk(KERN_ERR "mxser_close: bad serial port count; "
- "tty->count is 1, info->port.count is %d\n", info->port.count);
- info->port.count = 1;
- }
- if (--info->port.count < 0) {
- printk(KERN_ERR "mxser_close: bad serial port count for "
- "ttys%d: %d\n", tty->index, info->port.count);
- info->port.count = 0;
- }
- if (info->port.count) {
- spin_unlock_irqrestore(&info->slock, flags);
+ if (tty_port_close_start(port, tty, filp) == 0)
return;
- }
- info->port.flags |= ASYNC_CLOSING;
- spin_unlock_irqrestore(&info->slock, flags);
+
/*
* Save the termios structure, since this port may have
* separate termios for callout and dialin.
+ *
+ * FIXME: Can this go ?
*/
if (info->port.flags & ASYNC_NORMAL_ACTIVE)
info->normal_termios = *tty->termios;
/*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->port.closing_wait);
- /*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
* interrupt driver to stop checking the data ready bit in the
@@ -1209,19 +1125,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
}
}
mxser_shutdown(tty);
-
mxser_flush_buffer(tty);
- tty_ldisc_flush(tty);
-
- tty->closing = 0;
- tty_port_tty_set(&info->port, NULL);
- if (info->port.blocked_open) {
- if (info->port.close_delay)
- schedule_timeout_interruptible(info->port.close_delay);
- wake_up_interruptible(&info->port.open_wait);
- }
- info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+ /* Right now the tty_port set is done outside of the close_end helper
+ as we don't yet have everyone using refcounts */
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
}
static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
@@ -2146,10 +2055,7 @@ static void mxser_hangup(struct tty_struct *tty)
mxser_flush_buffer(tty);
mxser_shutdown(tty);
- info->port.count = 0;
- info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- tty_port_tty_set(&info->port, NULL);
- wake_up_interruptible(&info->port.open_wait);
+ tty_port_hangup(&info->port);
}
/*
@@ -2449,6 +2355,11 @@ static const struct tty_operations mxser_ops = {
.tiocmset = mxser_tiocmset,
};
+struct tty_port_operations mxser_port_ops = {
+ .carrier_raised = mxser_carrier_raised,
+ .raise_dtr_rts = mxser_raise_dtr_rts,
+};
+
/*
* The MOXA Smartio/Industio serial driver boot-time initialization code!
*/
@@ -2482,6 +2393,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
for (i = 0; i < brd->info->nports; i++) {
info = &brd->ports[i];
tty_port_init(&info->port);
+ info->port.ops = &mxser_port_ops;
info->board = brd;
info->stop_rx = 0;
info->ldisc_stop_rx = 0;
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 4a8215a89ad3..d2e93e343226 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1003,7 +1003,7 @@ static int r3964_open(struct tty_struct *tty)
static void r3964_close(struct tty_struct *tty)
{
- struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+ struct r3964_info *pInfo = tty->disc_data;
struct r3964_client_info *pClient, *pNext;
struct r3964_message *pMsg;
struct r3964_block_header *pHeader, *pNextHeader;
@@ -1058,7 +1058,7 @@ static void r3964_close(struct tty_struct *tty)
static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
unsigned char __user * buf, size_t nr)
{
- struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+ struct r3964_info *pInfo = tty->disc_data;
struct r3964_client_info *pClient;
struct r3964_message *pMsg;
struct r3964_client_message theMsg;
@@ -1113,7 +1113,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
const unsigned char *data, size_t count)
{
- struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+ struct r3964_info *pInfo = tty->disc_data;
struct r3964_block_header *pHeader;
struct r3964_client_info *pClient;
unsigned char *new_data;
@@ -1182,7 +1182,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
static int r3964_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+ struct r3964_info *pInfo = tty->disc_data;
if (pInfo == NULL)
return -EINVAL;
switch (cmd) {
@@ -1216,7 +1216,7 @@ static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
struct poll_table_struct *wait)
{
- struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+ struct r3964_info *pInfo = tty->disc_data;
struct r3964_client_info *pClient;
struct r3964_message *pMsg = NULL;
unsigned long flags;
@@ -1241,7 +1241,7 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,
static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
- struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data;
+ struct r3964_info *pInfo = tty->disc_data;
const unsigned char *p;
char *f, flags = 0;
int i;
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index efbfe9612658..f6f0e4ec2b51 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -47,8 +47,8 @@
#include <linux/bitops.h>
#include <linux/audit.h>
#include <linux/file.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
/* number of characters left in xmit buffer before select has we have room */
@@ -62,6 +62,17 @@
#define TTY_THRESHOLD_THROTTLE 128 /* now based on remaining room */
#define TTY_THRESHOLD_UNTHROTTLE 128
+/*
+ * Special byte codes used in the echo buffer to represent operations
+ * or special handling of characters. Bytes in the echo buffer that
+ * are not part of such special blocks are treated as normal character
+ * codes.
+ */
+#define ECHO_OP_START 0xff
+#define ECHO_OP_MOVE_BACK_COL 0x80
+#define ECHO_OP_SET_CANON_COL 0x81
+#define ECHO_OP_ERASE_TAB 0x82
+
static inline unsigned char *alloc_buf(void)
{
gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
@@ -169,6 +180,7 @@ static void check_unthrottle(struct tty_struct *tty)
*
* Locking: tty_read_lock for read fields.
*/
+
static void reset_buffer_flags(struct tty_struct *tty)
{
unsigned long flags;
@@ -176,6 +188,11 @@ static void reset_buffer_flags(struct tty_struct *tty)
spin_lock_irqsave(&tty->read_lock, flags);
tty->read_head = tty->read_tail = tty->read_cnt = 0;
spin_unlock_irqrestore(&tty->read_lock, flags);
+
+ mutex_lock(&tty->echo_lock);
+ tty->echo_pos = tty->echo_cnt = tty->echo_overrun = 0;
+ mutex_unlock(&tty->echo_lock);
+
tty->canon_head = tty->canon_data = tty->erasing = 0;
memset(&tty->read_flags, 0, sizeof tty->read_flags);
n_tty_set_room(tty);
@@ -266,89 +283,118 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
}
/**
- * opost - output post processor
+ * do_output_char - output one character
* @c: character (or partial unicode symbol)
* @tty: terminal device
+ * @space: space available in tty driver write buffer
*
- * Perform OPOST processing. Returns -1 when the output device is
- * full and the character must be retried. Note that Linux currently
- * ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY. They simply aren't
- * relevant in the world today. If you ever need them, add them here.
+ * This is a helper function that handles one output character
+ * (including special characters like TAB, CR, LF, etc.),
+ * putting the results in the tty driver's write buffer.
+ *
+ * Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY
+ * and NLDLY. They simply aren't relevant in the world today.
+ * If you ever need them, add them here.
+ *
+ * Returns the number of bytes of buffer space used or -1 if
+ * no space left.
*
- * Called from both the receive and transmit sides and can be called
- * re-entrantly. Relies on lock_kernel() for tty->column state.
+ * Locking: should be called under the output_lock to protect
+ * the column state and space left in the buffer
*/
-static int opost(unsigned char c, struct tty_struct *tty)
+static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
{
- int space, spaces;
+ int spaces;
- space = tty_write_room(tty);
if (!space)
return -1;
- lock_kernel();
- if (O_OPOST(tty)) {
- switch (c) {
- case '\n':
- if (O_ONLRET(tty))
- tty->column = 0;
- if (O_ONLCR(tty)) {
- if (space < 2) {
- unlock_kernel();
- return -1;
- }
- tty_put_char(tty, '\r');
- tty->column = 0;
- }
- tty->canon_column = tty->column;
- break;
- case '\r':
- if (O_ONOCR(tty) && tty->column == 0) {
- unlock_kernel();
- return 0;
- }
- if (O_OCRNL(tty)) {
- c = '\n';
- if (O_ONLRET(tty))
- tty->canon_column = tty->column = 0;
- break;
- }
+ switch (c) {
+ case '\n':
+ if (O_ONLRET(tty))
+ tty->column = 0;
+ if (O_ONLCR(tty)) {
+ if (space < 2)
+ return -1;
tty->canon_column = tty->column = 0;
+ tty_put_char(tty, '\r');
+ tty_put_char(tty, c);
+ return 2;
+ }
+ tty->canon_column = tty->column;
+ break;
+ case '\r':
+ if (O_ONOCR(tty) && tty->column == 0)
+ return 0;
+ if (O_OCRNL(tty)) {
+ c = '\n';
+ if (O_ONLRET(tty))
+ tty->canon_column = tty->column = 0;
break;
- case '\t':
- spaces = 8 - (tty->column & 7);
- if (O_TABDLY(tty) == XTABS) {
- if (space < spaces) {
- unlock_kernel();
- return -1;
- }
- tty->column += spaces;
- tty->ops->write(tty, " ", spaces);
- unlock_kernel();
- return 0;
- }
+ }
+ tty->canon_column = tty->column = 0;
+ break;
+ case '\t':
+ spaces = 8 - (tty->column & 7);
+ if (O_TABDLY(tty) == XTABS) {
+ if (space < spaces)
+ return -1;
tty->column += spaces;
- break;
- case '\b':
- if (tty->column > 0)
- tty->column--;
- break;
- default:
+ tty->ops->write(tty, " ", spaces);
+ return spaces;
+ }
+ tty->column += spaces;
+ break;
+ case '\b':
+ if (tty->column > 0)
+ tty->column--;
+ break;
+ default:
+ if (!iscntrl(c)) {
if (O_OLCUC(tty))
c = toupper(c);
- if (!iscntrl(c) && !is_continuation(c, tty))
+ if (!is_continuation(c, tty))
tty->column++;
- break;
}
+ break;
}
+
tty_put_char(tty, c);
- unlock_kernel();
- return 0;
+ return 1;
}
/**
- * opost_block - block postprocess
+ * process_output - output post processor
+ * @c: character (or partial unicode symbol)
+ * @tty: terminal device
+ *
+ * Perform OPOST processing. Returns -1 when the output device is
+ * full and the character must be retried.
+ *
+ * Locking: output_lock to protect column state and space left
+ * (also, this is called from n_tty_write under the
+ * tty layer write lock)
+ */
+
+static int process_output(unsigned char c, struct tty_struct *tty)
+{
+ int space, retval;
+
+ mutex_lock(&tty->output_lock);
+
+ space = tty_write_room(tty);
+ retval = do_output_char(c, tty, space);
+
+ mutex_unlock(&tty->output_lock);
+ if (retval < 0)
+ return -1;
+ else
+ return 0;
+}
+
+/**
+ * process_output_block - block post processor
* @tty: terminal device
* @inbuf: user buffer
* @nr: number of bytes
@@ -358,26 +404,32 @@ static int opost(unsigned char c, struct tty_struct *tty)
* the simple cases normally found and helps to generate blocks of
* symbols for the console driver and thus improve performance.
*
- * Called from n_tty_write under the tty layer write lock. Relies
- * on lock_kernel for the tty->column state.
+ * Locking: output_lock to protect column state and space left
+ * (also, this is called from n_tty_write under the
+ * tty layer write lock)
*/
-static ssize_t opost_block(struct tty_struct *tty,
- const unsigned char *buf, unsigned int nr)
+static ssize_t process_output_block(struct tty_struct *tty,
+ const unsigned char *buf, unsigned int nr)
{
int space;
int i;
const unsigned char *cp;
+ mutex_lock(&tty->output_lock);
+
space = tty_write_room(tty);
- if (!space)
+ if (!space) {
+ mutex_unlock(&tty->output_lock);
return 0;
+ }
if (nr > space)
nr = space;
- lock_kernel();
for (i = 0, cp = buf; i < nr; i++, cp++) {
- switch (*cp) {
+ unsigned char c = *cp;
+
+ switch (c) {
case '\n':
if (O_ONLRET(tty))
tty->column = 0;
@@ -399,54 +451,403 @@ static ssize_t opost_block(struct tty_struct *tty,
tty->column--;
break;
default:
- if (O_OLCUC(tty))
- goto break_out;
- if (!iscntrl(*cp))
- tty->column++;
+ if (!iscntrl(c)) {
+ if (O_OLCUC(tty))
+ goto break_out;
+ if (!is_continuation(c, tty))
+ tty->column++;
+ }
break;
}
}
break_out:
- if (tty->ops->flush_chars)
- tty->ops->flush_chars(tty);
i = tty->ops->write(tty, buf, i);
- unlock_kernel();
+
+ mutex_unlock(&tty->output_lock);
return i;
}
+/**
+ * process_echoes - write pending echo characters
+ * @tty: terminal device
+ *
+ * Write previously buffered echo (and other ldisc-generated)
+ * characters to the tty.
+ *
+ * Characters generated by the ldisc (including echoes) need to
+ * be buffered because the driver's write buffer can fill during
+ * heavy program output. Echoing straight to the driver will
+ * often fail under these conditions, causing lost characters and
+ * resulting mismatches of ldisc state information.
+ *
+ * Since the ldisc state must represent the characters actually sent
+ * to the driver at the time of the write, operations like certain
+ * changes in column state are also saved in the buffer and executed
+ * here.
+ *
+ * A circular fifo buffer is used so that the most recent characters
+ * are prioritized. Also, when control characters are echoed with a
+ * prefixed "^", the pair is treated atomically and thus not separated.
+ *
+ * Locking: output_lock to protect column state and space left,
+ * echo_lock to protect the echo buffer
+ */
+
+static void process_echoes(struct tty_struct *tty)
+{
+ int space, nr;
+ unsigned char c;
+ unsigned char *cp, *buf_end;
+
+ if (!tty->echo_cnt)
+ return;
+
+ mutex_lock(&tty->output_lock);
+ mutex_lock(&tty->echo_lock);
+
+ space = tty_write_room(tty);
+
+ buf_end = tty->echo_buf + N_TTY_BUF_SIZE;
+ cp = tty->echo_buf + tty->echo_pos;
+ nr = tty->echo_cnt;
+ while (nr > 0) {
+ c = *cp;
+ if (c == ECHO_OP_START) {
+ unsigned char op;
+ unsigned char *opp;
+ int no_space_left = 0;
+
+ /*
+ * If the buffer byte is the start of a multi-byte
+ * operation, get the next byte, which is either the
+ * op code or a control character value.
+ */
+ opp = cp + 1;
+ if (opp == buf_end)
+ opp -= N_TTY_BUF_SIZE;
+ op = *opp;
+
+ switch (op) {
+ unsigned int num_chars, num_bs;
+
+ case ECHO_OP_ERASE_TAB:
+ if (++opp == buf_end)
+ opp -= N_TTY_BUF_SIZE;
+ num_chars = *opp;
+
+ /*
+ * Determine how many columns to go back
+ * in order to erase the tab.
+ * This depends on the number of columns
+ * used by other characters within the tab
+ * area. If this (modulo 8) count is from
+ * the start of input rather than from a
+ * previous tab, we offset by canon column.
+ * Otherwise, tab spacing is normal.
+ */
+ if (!(num_chars & 0x80))
+ num_chars += tty->canon_column;
+ num_bs = 8 - (num_chars & 7);
+
+ if (num_bs > space) {
+ no_space_left = 1;
+ break;
+ }
+ space -= num_bs;
+ while (num_bs--) {
+ tty_put_char(tty, '\b');
+ if (tty->column > 0)
+ tty->column--;
+ }
+ cp += 3;
+ nr -= 3;
+ break;
+
+ case ECHO_OP_SET_CANON_COL:
+ tty->canon_column = tty->column;
+ cp += 2;
+ nr -= 2;
+ break;
+
+ case ECHO_OP_MOVE_BACK_COL:
+ if (tty->column > 0)
+ tty->column--;
+ cp += 2;
+ nr -= 2;
+ break;
+
+ case ECHO_OP_START:
+ /* This is an escaped echo op start code */
+ if (!space) {
+ no_space_left = 1;
+ break;
+ }
+ tty_put_char(tty, ECHO_OP_START);
+ tty->column++;
+ space--;
+ cp += 2;
+ nr -= 2;
+ break;
+
+ default:
+ if (iscntrl(op)) {
+ if (L_ECHOCTL(tty)) {
+ /*
+ * Ensure there is enough space
+ * for the whole ctrl pair.
+ */
+ if (space < 2) {
+ no_space_left = 1;
+ break;
+ }
+ tty_put_char(tty, '^');
+ tty_put_char(tty, op ^ 0100);
+ tty->column += 2;
+ space -= 2;
+ } else {
+ if (!space) {
+ no_space_left = 1;
+ break;
+ }
+ tty_put_char(tty, op);
+ space--;
+ }
+ }
+ /*
+ * If above falls through, this was an
+ * undefined op.
+ */
+ cp += 2;
+ nr -= 2;
+ }
+
+ if (no_space_left)
+ break;
+ } else {
+ int retval;
+
+ retval = do_output_char(c, tty, space);
+ if (retval < 0)
+ break;
+ space -= retval;
+ cp += 1;
+ nr -= 1;
+ }
+
+ /* When end of circular buffer reached, wrap around */
+ if (cp >= buf_end)
+ cp -= N_TTY_BUF_SIZE;
+ }
+
+ if (nr == 0) {
+ tty->echo_pos = 0;
+ tty->echo_cnt = 0;
+ tty->echo_overrun = 0;
+ } else {
+ int num_processed = tty->echo_cnt - nr;
+ tty->echo_pos += num_processed;
+ tty->echo_pos &= N_TTY_BUF_SIZE - 1;
+ tty->echo_cnt = nr;
+ if (num_processed > 0)
+ tty->echo_overrun = 0;
+ }
+
+ mutex_unlock(&tty->echo_lock);
+ mutex_unlock(&tty->output_lock);
+
+ if (tty->ops->flush_chars)
+ tty->ops->flush_chars(tty);
+}
/**
- * echo_char - echo characters
+ * add_echo_byte - add a byte to the echo buffer
+ * @c: unicode byte to echo
+ * @tty: terminal device
+ *
+ * Add a character or operation byte to the echo buffer.
+ *
+ * Should be called under the echo lock to protect the echo buffer.
+ */
+
+static void add_echo_byte(unsigned char c, struct tty_struct *tty)
+{
+ int new_byte_pos;
+
+ if (tty->echo_cnt == N_TTY_BUF_SIZE) {
+ /* Circular buffer is already at capacity */
+ new_byte_pos = tty->echo_pos;
+
+ /*
+ * Since the buffer start position needs to be advanced,
+ * be sure to step by a whole operation byte group.
+ */
+ if (tty->echo_buf[tty->echo_pos] == ECHO_OP_START) {
+ if (tty->echo_buf[(tty->echo_pos + 1) &
+ (N_TTY_BUF_SIZE - 1)] ==
+ ECHO_OP_ERASE_TAB) {
+ tty->echo_pos += 3;
+ tty->echo_cnt -= 2;
+ } else {
+ tty->echo_pos += 2;
+ tty->echo_cnt -= 1;
+ }
+ } else {
+ tty->echo_pos++;
+ }
+ tty->echo_pos &= N_TTY_BUF_SIZE - 1;
+
+ tty->echo_overrun = 1;
+ } else {
+ new_byte_pos = tty->echo_pos + tty->echo_cnt;
+ new_byte_pos &= N_TTY_BUF_SIZE - 1;
+ tty->echo_cnt++;
+ }
+
+ tty->echo_buf[new_byte_pos] = c;
+}
+
+/**
+ * echo_move_back_col - add operation to move back a column
+ * @tty: terminal device
+ *
+ * Add an operation to the echo buffer to move back one column.
+ *
+ * Locking: echo_lock to protect the echo buffer
+ */
+
+static void echo_move_back_col(struct tty_struct *tty)
+{
+ mutex_lock(&tty->echo_lock);
+
+ add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_MOVE_BACK_COL, tty);
+
+ mutex_unlock(&tty->echo_lock);
+}
+
+/**
+ * echo_set_canon_col - add operation to set the canon column
+ * @tty: terminal device
+ *
+ * Add an operation to the echo buffer to set the canon column
+ * to the current column.
+ *
+ * Locking: echo_lock to protect the echo buffer
+ */
+
+static void echo_set_canon_col(struct tty_struct *tty)
+{
+ mutex_lock(&tty->echo_lock);
+
+ add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_SET_CANON_COL, tty);
+
+ mutex_unlock(&tty->echo_lock);
+}
+
+/**
+ * echo_erase_tab - add operation to erase a tab
+ * @num_chars: number of character columns already used
+ * @after_tab: true if num_chars starts after a previous tab
+ * @tty: terminal device
+ *
+ * Add an operation to the echo buffer to erase a tab.
+ *
+ * Called by the eraser function, which knows how many character
+ * columns have been used since either a previous tab or the start
+ * of input. This information will be used later, along with
+ * canon column (if applicable), to go back the correct number
+ * of columns.
+ *
+ * Locking: echo_lock to protect the echo buffer
+ */
+
+static void echo_erase_tab(unsigned int num_chars, int after_tab,
+ struct tty_struct *tty)
+{
+ mutex_lock(&tty->echo_lock);
+
+ add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_ERASE_TAB, tty);
+
+ /* We only need to know this modulo 8 (tab spacing) */
+ num_chars &= 7;
+
+ /* Set the high bit as a flag if num_chars is after a previous tab */
+ if (after_tab)
+ num_chars |= 0x80;
+
+ add_echo_byte(num_chars, tty);
+
+ mutex_unlock(&tty->echo_lock);
+}
+
+/**
+ * echo_char_raw - echo a character raw
* @c: unicode byte to echo
* @tty: terminal device
*
* Echo user input back onto the screen. This must be called only when
* L_ECHO(tty) is true. Called from the driver receive_buf path.
*
- * Relies on BKL for tty column locking
+ * This variant does not treat control characters specially.
+ *
+ * Locking: echo_lock to protect the echo buffer
+ */
+
+static void echo_char_raw(unsigned char c, struct tty_struct *tty)
+{
+ mutex_lock(&tty->echo_lock);
+
+ if (c == ECHO_OP_START) {
+ add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_START, tty);
+ } else {
+ add_echo_byte(c, tty);
+ }
+
+ mutex_unlock(&tty->echo_lock);
+}
+
+/**
+ * echo_char - echo a character
+ * @c: unicode byte to echo
+ * @tty: terminal device
+ *
+ * Echo user input back onto the screen. This must be called only when
+ * L_ECHO(tty) is true. Called from the driver receive_buf path.
+ *
+ * This variant tags control characters to be possibly echoed as
+ * as "^X" (where X is the letter representing the control char).
+ *
+ * Locking: echo_lock to protect the echo buffer
*/
static void echo_char(unsigned char c, struct tty_struct *tty)
{
- if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
- tty_put_char(tty, '^');
- tty_put_char(tty, c ^ 0100);
- tty->column += 2;
- } else
- opost(c, tty);
+ mutex_lock(&tty->echo_lock);
+
+ if (c == ECHO_OP_START) {
+ add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_START, tty);
+ } else {
+ if (iscntrl(c) && c != '\t')
+ add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(c, tty);
+ }
+
+ mutex_unlock(&tty->echo_lock);
}
/**
- * finsh_erasing - complete erase
+ * finish_erasing - complete erase
* @tty: tty doing the erase
- *
- * Relies on BKL for tty column locking
*/
+
static inline void finish_erasing(struct tty_struct *tty)
{
if (tty->erasing) {
- tty_put_char(tty, '/');
- tty->column++;
+ echo_char_raw('/', tty);
tty->erasing = 0;
}
}
@@ -460,7 +861,7 @@ static inline void finish_erasing(struct tty_struct *tty)
* present in the stream from the driver layer. Handles the complexities
* of UTF-8 multibyte symbols.
*
- * Locking: read_lock for tty buffers, BKL for column/erasing state
+ * Locking: read_lock for tty buffers
*/
static void eraser(unsigned char c, struct tty_struct *tty)
@@ -471,7 +872,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
/* FIXME: locking needed ? */
if (tty->read_head == tty->canon_head) {
- /* opost('\a', tty); */ /* what do you think? */
+ /* process_output('\a', tty); */ /* what do you think? */
return;
}
if (c == ERASE_CHAR(tty))
@@ -497,7 +898,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
echo_char(KILL_CHAR(tty), tty);
/* Add a newline if ECHOK is on and ECHOKE is off. */
if (L_ECHOK(tty))
- opost('\n', tty);
+ echo_char_raw('\n', tty);
return;
}
kill_type = KILL;
@@ -533,67 +934,61 @@ static void eraser(unsigned char c, struct tty_struct *tty)
if (L_ECHO(tty)) {
if (L_ECHOPRT(tty)) {
if (!tty->erasing) {
- tty_put_char(tty, '\\');
- tty->column++;
+ echo_char_raw('\\', tty);
tty->erasing = 1;
}
/* if cnt > 1, output a multi-byte character */
echo_char(c, tty);
while (--cnt > 0) {
head = (head+1) & (N_TTY_BUF_SIZE-1);
- tty_put_char(tty, tty->read_buf[head]);
+ echo_char_raw(tty->read_buf[head], tty);
+ echo_move_back_col(tty);
}
} else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty);
} else if (c == '\t') {
- unsigned int col = tty->canon_column;
- unsigned long tail = tty->canon_head;
-
- /* Find the column of the last char. */
- while (tail != tty->read_head) {
+ unsigned int num_chars = 0;
+ int after_tab = 0;
+ unsigned long tail = tty->read_head;
+
+ /*
+ * Count the columns used for characters
+ * since the start of input or after a
+ * previous tab.
+ * This info is used to go back the correct
+ * number of columns.
+ */
+ while (tail != tty->canon_head) {
+ tail = (tail-1) & (N_TTY_BUF_SIZE-1);
c = tty->read_buf[tail];
- if (c == '\t')
- col = (col | 7) + 1;
- else if (iscntrl(c)) {
+ if (c == '\t') {
+ after_tab = 1;
+ break;
+ } else if (iscntrl(c)) {
if (L_ECHOCTL(tty))
- col += 2;
- } else if (!is_continuation(c, tty))
- col++;
- tail = (tail+1) & (N_TTY_BUF_SIZE-1);
- }
-
- /* should never happen */
- if (tty->column > 0x80000000)
- tty->column = 0;
-
- /* Now backup to that column. */
- while (tty->column > col) {
- /* Can't use opost here. */
- tty_put_char(tty, '\b');
- if (tty->column > 0)
- tty->column--;
+ num_chars += 2;
+ } else if (!is_continuation(c, tty)) {
+ num_chars++;
+ }
}
+ echo_erase_tab(num_chars, after_tab, tty);
} else {
if (iscntrl(c) && L_ECHOCTL(tty)) {
- tty_put_char(tty, '\b');
- tty_put_char(tty, ' ');
- tty_put_char(tty, '\b');
- if (tty->column > 0)
- tty->column--;
+ echo_char_raw('\b', tty);
+ echo_char_raw(' ', tty);
+ echo_char_raw('\b', tty);
}
if (!iscntrl(c) || L_ECHOCTL(tty)) {
- tty_put_char(tty, '\b');
- tty_put_char(tty, ' ');
- tty_put_char(tty, '\b');
- if (tty->column > 0)
- tty->column--;
+ echo_char_raw('\b', tty);
+ echo_char_raw(' ', tty);
+ echo_char_raw('\b', tty);
}
}
}
if (kill_type == ERASE)
break;
}
- if (tty->read_head == tty->canon_head)
+ if (tty->read_head == tty->canon_head && L_ECHO(tty))
finish_erasing(tty);
}
@@ -712,6 +1107,7 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
unsigned long flags;
+ int parmrk;
if (tty->raw) {
put_tty_queue(c, tty);
@@ -721,18 +1117,21 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
if (I_ISTRIP(tty))
c &= 0x7f;
if (I_IUCLC(tty) && L_IEXTEN(tty))
- c=tolower(c);
+ c = tolower(c);
if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
- ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) ||
- c == INTR_CHAR(tty) || c == QUIT_CHAR(tty) || c == SUSP_CHAR(tty)))
+ I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) &&
+ c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) {
start_tty(tty);
+ process_echoes(tty);
+ }
if (tty->closing) {
if (I_IXON(tty)) {
- if (c == START_CHAR(tty))
+ if (c == START_CHAR(tty)) {
start_tty(tty);
- else if (c == STOP_CHAR(tty))
+ process_echoes(tty);
+ } else if (c == STOP_CHAR(tty))
stop_tty(tty);
}
return;
@@ -745,19 +1144,23 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
* up.
*/
if (!test_bit(c, tty->process_char_map) || tty->lnext) {
- finish_erasing(tty);
tty->lnext = 0;
+ parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
+ if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+ /* beep if no space */
+ if (L_ECHO(tty))
+ process_output('\a', tty);
+ return;
+ }
if (L_ECHO(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
- tty_put_char(tty, '\a'); /* beep if no space */
- return;
- }
+ finish_erasing(tty);
/* Record the column of first canon char. */
if (tty->canon_head == tty->read_head)
- tty->canon_column = tty->column;
+ echo_set_canon_col(tty);
echo_char(c, tty);
+ process_echoes(tty);
}
- if (I_PARMRK(tty) && c == (unsigned char) '\377')
+ if (parmrk)
put_tty_queue(c, tty);
put_tty_queue(c, tty);
return;
@@ -766,6 +1169,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
if (I_IXON(tty)) {
if (c == START_CHAR(tty)) {
start_tty(tty);
+ process_echoes(tty);
return;
}
if (c == STOP_CHAR(tty)) {
@@ -786,7 +1190,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
if (c == SUSP_CHAR(tty)) {
send_signal:
/*
- * Echo character, and then send the signal.
* Note that we do not use isig() here because we want
* the order to be:
* 1) flush, 2) echo, 3) signal
@@ -795,8 +1198,12 @@ send_signal:
n_tty_flush_buffer(tty);
tty_driver_flush_buffer(tty);
}
- if (L_ECHO(tty))
+ if (I_IXON(tty))
+ start_tty(tty);
+ if (L_ECHO(tty)) {
echo_char(c, tty);
+ process_echoes(tty);
+ }
if (tty->pgrp)
kill_pgrp(tty->pgrp, signal, 1);
return;
@@ -815,6 +1222,7 @@ send_signal:
if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
(c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
eraser(c, tty);
+ process_echoes(tty);
return;
}
if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
@@ -822,8 +1230,9 @@ send_signal:
if (L_ECHO(tty)) {
finish_erasing(tty);
if (L_ECHOCTL(tty)) {
- tty_put_char(tty, '^');
- tty_put_char(tty, '\b');
+ echo_char_raw('^', tty);
+ echo_char_raw('\b', tty);
+ process_echoes(tty);
}
}
return;
@@ -834,22 +1243,29 @@ send_signal:
finish_erasing(tty);
echo_char(c, tty);
- opost('\n', tty);
+ echo_char_raw('\n', tty);
while (tail != tty->read_head) {
echo_char(tty->read_buf[tail], tty);
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
}
+ process_echoes(tty);
return;
}
if (c == '\n') {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE) {
+ if (L_ECHO(tty))
+ process_output('\a', tty);
+ return;
+ }
if (L_ECHO(tty) || L_ECHONL(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
- tty_put_char(tty, '\a');
- opost('\n', tty);
+ echo_char_raw('\n', tty);
+ process_echoes(tty);
}
goto handle_newline;
}
if (c == EOF_CHAR(tty)) {
+ if (tty->read_cnt >= N_TTY_BUF_SIZE)
+ return;
if (tty->canon_head != tty->read_head)
set_bit(TTY_PUSH, &tty->flags);
c = __DISABLED_CHAR;
@@ -857,22 +1273,28 @@ send_signal:
}
if ((c == EOL_CHAR(tty)) ||
(c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
+ parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
+ ? 1 : 0;
+ if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
+ if (L_ECHO(tty))
+ process_output('\a', tty);
+ return;
+ }
/*
* XXX are EOL_CHAR and EOL2_CHAR echoed?!?
*/
if (L_ECHO(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
- tty_put_char(tty, '\a');
/* Record the column of first canon char. */
if (tty->canon_head == tty->read_head)
- tty->canon_column = tty->column;
+ echo_set_canon_col(tty);
echo_char(c, tty);
+ process_echoes(tty);
}
/*
* XXX does PARMRK doubling happen for
* EOL_CHAR and EOL2_CHAR?
*/
- if (I_PARMRK(tty) && c == (unsigned char) '\377')
+ if (parmrk)
put_tty_queue(c, tty);
handle_newline:
@@ -889,23 +1311,27 @@ handle_newline:
}
}
- finish_erasing(tty);
+ parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
+ if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+ /* beep if no space */
+ if (L_ECHO(tty))
+ process_output('\a', tty);
+ return;
+ }
if (L_ECHO(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
- tty_put_char(tty, '\a'); /* beep if no space */
- return;
- }
+ finish_erasing(tty);
if (c == '\n')
- opost('\n', tty);
+ echo_char_raw('\n', tty);
else {
/* Record the column of first canon char. */
if (tty->canon_head == tty->read_head)
- tty->canon_column = tty->column;
+ echo_set_canon_col(tty);
echo_char(c, tty);
}
+ process_echoes(tty);
}
- if (I_PARMRK(tty) && c == (unsigned char) '\377')
+ if (parmrk)
put_tty_queue(c, tty);
put_tty_queue(c, tty);
@@ -923,10 +1349,11 @@ handle_newline:
static void n_tty_write_wakeup(struct tty_struct *tty)
{
- if (tty->fasync) {
- set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ /* Write out any echoed characters that are still pending */
+ process_echoes(tty);
+
+ if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
- }
}
/**
@@ -1134,6 +1561,10 @@ static void n_tty_close(struct tty_struct *tty)
free_buf(tty->read_buf);
tty->read_buf = NULL;
}
+ if (tty->echo_buf) {
+ free_buf(tty->echo_buf);
+ tty->echo_buf = NULL;
+ }
}
/**
@@ -1151,13 +1582,19 @@ static int n_tty_open(struct tty_struct *tty)
if (!tty)
return -EINVAL;
- /* This one is ugly. Currently a malloc failure here can panic */
+ /* These are ugly. Currently a malloc failure here can panic */
if (!tty->read_buf) {
tty->read_buf = alloc_buf();
if (!tty->read_buf)
return -ENOMEM;
}
+ if (!tty->echo_buf) {
+ tty->echo_buf = alloc_buf();
+ if (!tty->echo_buf)
+ return -ENOMEM;
+ }
memset(tty->read_buf, 0, N_TTY_BUF_SIZE);
+ memset(tty->echo_buf, 0, N_TTY_BUF_SIZE);
reset_buffer_flags(tty);
tty->column = 0;
n_tty_set_termios(tty, NULL);
@@ -1487,16 +1924,23 @@ do_it_again:
* @buf: userspace buffer pointer
* @nr: size of I/O
*
- * Write function of the terminal device. This is serialized with
+ * Write function of the terminal device. This is serialized with
* respect to other write callers but not to termios changes, reads
- * and other such events. We must be careful with N_TTY as the receive
- * code will echo characters, thus calling driver write methods.
+ * and other such events. Since the receive code will echo characters,
+ * thus calling driver write methods, the output_lock is used in
+ * the output processing functions called here as well as in the
+ * echo processing function to protect the column state and space
+ * left in the buffer.
*
* This code must be sure never to sleep through a hangup.
+ *
+ * Locking: output_lock to protect column state and space left
+ * (note that the process_output*() functions take this
+ * lock themselves)
*/
static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
- const unsigned char *buf, size_t nr)
+ const unsigned char *buf, size_t nr)
{
const unsigned char *b = buf;
DECLARE_WAITQUEUE(wait, current);
@@ -1510,6 +1954,9 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
return retval;
}
+ /* Write out any echoed characters that are still pending */
+ process_echoes(tty);
+
add_wait_queue(&tty->write_wait, &wait);
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -1523,7 +1970,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
}
if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) {
while (nr > 0) {
- ssize_t num = opost_block(tty, b, nr);
+ ssize_t num = process_output_block(tty, b, nr);
if (num < 0) {
if (num == -EAGAIN)
break;
@@ -1535,7 +1982,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
if (nr == 0)
break;
c = *b;
- if (opost(c, tty) < 0)
+ if (process_output(c, tty) < 0)
break;
b++; nr--;
}
@@ -1565,6 +2012,8 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,
break_out:
__set_current_state(TASK_RUNNING);
remove_wait_queue(&tty->write_wait, &wait);
+ if (b - buf != nr && tty->fasync)
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
return (b - buf) ? b - buf : retval;
}
@@ -1663,4 +2112,3 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = {
.receive_buf = n_tty_receive_buf,
.write_wakeup = n_tty_write_wakeup
};
-
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 9a34a1935283..d6102b644b55 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -353,6 +353,7 @@ struct ctrl_ul {
/* This holds all information that is needed regarding a port */
struct port {
+ struct tty_port port;
u8 update_flow_control;
struct ctrl_ul ctrl_ul;
struct ctrl_dl ctrl_dl;
@@ -365,8 +366,6 @@ struct port {
u8 toggle_ul;
u16 token_dl;
- struct tty_struct *tty;
- int tty_open_count;
/* mutex to ensure one access patch to this port */
struct mutex tty_sem;
wait_queue_head_t tty_wait;
@@ -788,14 +787,14 @@ static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
* Return 1 - send buffer to card and ack.
* Return 0 - don't ack, don't send buffer to card.
*/
-static int send_data(enum port_type index, const struct nozomi *dc)
+static int send_data(enum port_type index, struct nozomi *dc)
{
u32 size = 0;
- const struct port *port = &dc->port[index];
+ struct port *port = &dc->port[index];
const u8 toggle = port->toggle_ul;
void __iomem *addr = port->ul_addr[toggle];
const u32 ul_size = port->ul_size[toggle];
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
/* Get data from tty and place in buf for now */
size = __kfifo_get(port->fifo_ul, dc->send_buf,
@@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc)
if (size == 0) {
DBG4("No more data to send, disable link:");
+ tty_kref_put(tty);
return 0;
}
@@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc)
if (tty)
tty_wakeup(tty);
+ tty_kref_put(tty);
return 1;
}
@@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
u32 offset = 4;
struct port *port = &dc->port[index];
void __iomem *addr = port->dl_addr[port->toggle_dl];
- struct tty_struct *tty = port->tty;
+ struct tty_struct *tty = tty_port_tty_get(&port->port);
int i;
if (unlikely(!tty)) {
@@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
}
set_bit(index, &dc->flip);
-
+ tty_kref_put(tty);
return 1;
}
@@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id)
exit_handler:
spin_unlock(&dc->spin_mutex);
- for (a = 0; a < NOZOMI_MAX_PORTS; a++)
- if (test_and_clear_bit(a, &dc->flip))
- tty_flip_buffer_push(dc->port[a].tty);
+ for (a = 0; a < NOZOMI_MAX_PORTS; a++) {
+ struct tty_struct *tty;
+ if (test_and_clear_bit(a, &dc->flip)) {
+ tty = tty_port_tty_get(&dc->port[a].port);
+ if (tty)
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ }
+ }
return IRQ_HANDLED;
none:
spin_unlock(&dc->spin_mutex);
@@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
for (i = 0; i < MAX_PORT; i++) {
mutex_init(&dc->port[i].tty_sem);
- dc->port[i].tty_open_count = 0;
- dc->port[i].tty = NULL;
+ tty_port_init(&dc->port[i].port);
tty_register_device(ntty_driver, dc->index_start + i,
&pdev->dev);
}
-
return 0;
err_free_sbuf:
@@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc)
flush_scheduled_work();
- for (i = 0; i < MAX_PORT; ++i)
- if (dc->port[i].tty && \
- list_empty(&dc->port[i].tty->hangup_work.entry))
- tty_hangup(dc->port[i].tty);
-
+ for (i = 0; i < MAX_PORT; ++i) {
+ struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port);
+ if (tty && list_empty(&tty->hangup_work.entry))
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
+ /* Racy below - surely should wait for scheduled work to be done or
+ complete off a hangup method ? */
while (dc->open_ttys)
msleep(1);
-
for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
tty_unregister_device(ntty_driver, i);
}
@@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
if (mutex_lock_interruptible(&port->tty_sem))
return -ERESTARTSYS;
- port->tty_open_count++;
+ port->port.count++;
dc->open_ttys++;
/* Enable interrupt downlink for channel */
- if (port->tty_open_count == 1) {
+ if (port->port.count == 1) {
+ /* FIXME: is this needed now ? */
tty->low_latency = 1;
tty->driver_data = port;
- port->tty = tty;
+ tty_port_tty_set(&port->port, tty);
DBG1("open: %d", port->token_dl);
spin_lock_irqsave(&dc->spin_mutex, flags);
dc->last_ier = dc->last_ier | port->token_dl;
writew(dc->last_ier, dc->reg_ier);
spin_unlock_irqrestore(&dc->spin_mutex, flags);
}
-
mutex_unlock(&port->tty_sem);
-
return 0;
}
@@ -1606,31 +1612,30 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
static void ntty_close(struct tty_struct *tty, struct file *file)
{
struct nozomi *dc = get_dc_by_tty(tty);
- struct port *port = tty->driver_data;
+ struct port *nport = tty->driver_data;
+ struct tty_port *port = &nport->port;
unsigned long flags;
- if (!dc || !port)
+ if (!dc || !nport)
return;
- if (mutex_lock_interruptible(&port->tty_sem))
- return;
+ /* Users cannot interrupt a close */
+ mutex_lock(&nport->tty_sem);
- if (!port->tty_open_count)
- goto exit;
+ WARN_ON(!port->count);
dc->open_ttys--;
- port->tty_open_count--;
+ port->count--;
+ tty_port_tty_set(port, NULL);
- if (port->tty_open_count == 0) {
- DBG1("close: %d", port->token_dl);
+ if (port->count == 0) {
+ DBG1("close: %d", nport->token_dl);
spin_lock_irqsave(&dc->spin_mutex, flags);
- dc->last_ier &= ~(port->token_dl);
+ dc->last_ier &= ~(nport->token_dl);
writew(dc->last_ier, dc->reg_ier);
spin_unlock_irqrestore(&dc->spin_mutex, flags);
}
-
-exit:
- mutex_unlock(&port->tty_sem);
+ mutex_unlock(&nport->tty_sem);
}
/*
@@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
return -EAGAIN;
}
- if (unlikely(!port->tty_open_count)) {
+ if (unlikely(!port->port.count)) {
DBG1(" ");
goto exit;
}
@@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty)
if (!mutex_trylock(&port->tty_sem))
return 0;
- if (!port->tty_open_count)
+ if (!port->port.count)
goto exit;
room = port->fifo_ul->size - __kfifo_len(port->fifo_ul);
@@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
goto exit_in_buffer;
}
- if (unlikely(!port->tty_open_count)) {
+ if (unlikely(!port->port.count)) {
dev_err(&dc->pdev->dev, "No tty open?\n");
rval = -ENODEV;
goto exit_in_buffer;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 4d64a02612a4..dc073e167abc 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -138,20 +138,15 @@ struct _input_signal_events {
*/
typedef struct _mgslpc_info {
+ struct tty_port port;
void *if_ptr; /* General purpose pointer (used by SPPP) */
int magic;
- int flags;
- int count; /* count of opens */
int line;
- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
struct mgsl_icount icount;
- struct tty_struct *tty;
int timeout;
int x_char; /* xon/xoff character */
- int blocked_open; /* # of blocked opens */
unsigned char read_status_mask;
unsigned char ignore_status_mask;
@@ -170,9 +165,6 @@ typedef struct _mgslpc_info {
int rx_buf_count; /* total number of rx buffers */
int rx_frame_count; /* number of full rx buffers */
- wait_queue_head_t open_wait;
- wait_queue_head_t close_wait;
-
wait_queue_head_t status_event_wait_q;
wait_queue_head_t event_wait_q;
struct timer_list tx_timer; /* HDLC transmit timeout timer */
@@ -375,7 +367,7 @@ static void irq_enable(MGSLPC_INFO *info, unsigned char channel, unsigned short
static void rx_start(MGSLPC_INFO *info);
static void rx_stop(MGSLPC_INFO *info);
-static void tx_start(MGSLPC_INFO *info);
+static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty);
static void tx_stop(MGSLPC_INFO *info);
static void tx_set_idle(MGSLPC_INFO *info);
@@ -389,7 +381,8 @@ static void async_mode(MGSLPC_INFO *info);
static void tx_timeout(unsigned long context);
-static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg);
+static int carrier_raised(struct tty_port *port);
+static void raise_dtr_rts(struct tty_port *port);
#if SYNCLINK_GENERIC_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -410,7 +403,7 @@ static void release_resources(MGSLPC_INFO *info);
static void mgslpc_add_device(MGSLPC_INFO *info);
static void mgslpc_remove_device(MGSLPC_INFO *info);
-static bool rx_get_frame(MGSLPC_INFO *info);
+static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty);
static void rx_reset_buffers(MGSLPC_INFO *info);
static int rx_alloc_buffers(MGSLPC_INFO *info);
static void rx_free_buffers(MGSLPC_INFO *info);
@@ -421,7 +414,7 @@ static irqreturn_t mgslpc_isr(int irq, void *dev_id);
* Bottom half interrupt handlers
*/
static void bh_handler(struct work_struct *work);
-static void bh_transmit(MGSLPC_INFO *info);
+static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty);
static void bh_status(MGSLPC_INFO *info);
/*
@@ -432,10 +425,10 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount);
static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params);
-static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params);
+static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params, struct tty_struct *tty);
static int get_txidle(MGSLPC_INFO *info, int __user *idle_mode);
static int set_txidle(MGSLPC_INFO *info, int idle_mode);
-static int set_txenable(MGSLPC_INFO *info, int enable);
+static int set_txenable(MGSLPC_INFO *info, int enable, struct tty_struct *tty);
static int tx_abort(MGSLPC_INFO *info);
static int set_rxenable(MGSLPC_INFO *info, int enable);
static int wait_events(MGSLPC_INFO *info, int __user *mask);
@@ -474,7 +467,7 @@ static struct tty_driver *serial_driver;
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
-static void mgslpc_change_params(MGSLPC_INFO *info);
+static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty);
static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
/* PCMCIA prototypes */
@@ -517,6 +510,11 @@ static void ldisc_receive_buf(struct tty_struct *tty,
}
}
+static const struct tty_port_operations mgslpc_port_ops = {
+ .carrier_raised = carrier_raised,
+ .raise_dtr_rts = raise_dtr_rts
+};
+
static int mgslpc_probe(struct pcmcia_device *link)
{
MGSLPC_INFO *info;
@@ -532,12 +530,12 @@ static int mgslpc_probe(struct pcmcia_device *link)
}
info->magic = MGSLPC_MAGIC;
+ tty_port_init(&info->port);
+ info->port.ops = &mgslpc_port_ops;
INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096;
- info->close_delay = 5*HZ/10;
- info->closing_wait = 30*HZ;
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
+ info->port.close_delay = 5*HZ/10;
+ info->port.closing_wait = 30*HZ;
init_waitqueue_head(&info->status_event_wait_q);
init_waitqueue_head(&info->event_wait_q);
spin_lock_init(&info->lock);
@@ -784,7 +782,7 @@ static void tx_release(struct tty_struct *tty)
spin_lock_irqsave(&info->lock,flags);
if (!info->tx_enabled)
- tx_start(info);
+ tx_start(info, tty);
spin_unlock_irqrestore(&info->lock,flags);
}
@@ -823,6 +821,7 @@ static int bh_action(MGSLPC_INFO *info)
static void bh_handler(struct work_struct *work)
{
MGSLPC_INFO *info = container_of(work, MGSLPC_INFO, task);
+ struct tty_struct *tty;
int action;
if (!info)
@@ -833,6 +832,7 @@ static void bh_handler(struct work_struct *work)
__FILE__,__LINE__,info->device_name);
info->bh_running = true;
+ tty = tty_port_tty_get(&info->port);
while((action = bh_action(info)) != 0) {
@@ -844,10 +844,10 @@ static void bh_handler(struct work_struct *work)
switch (action) {
case BH_RECEIVE:
- while(rx_get_frame(info));
+ while(rx_get_frame(info, tty));
break;
case BH_TRANSMIT:
- bh_transmit(info);
+ bh_transmit(info, tty);
break;
case BH_STATUS:
bh_status(info);
@@ -859,14 +859,14 @@ static void bh_handler(struct work_struct *work)
}
}
+ tty_kref_put(tty);
if (debug_level >= DEBUG_LEVEL_BH)
printk( "%s(%d):bh_handler(%s) exit\n",
__FILE__,__LINE__,info->device_name);
}
-static void bh_transmit(MGSLPC_INFO *info)
+static void bh_transmit(MGSLPC_INFO *info, struct tty_struct *tty)
{
- struct tty_struct *tty = info->tty;
if (debug_level >= DEBUG_LEVEL_BH)
printk("bh_transmit() entry on %s\n", info->device_name);
@@ -945,12 +945,11 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
issue_command(info, CHA, CMD_RXFIFO);
}
-static void rx_ready_async(MGSLPC_INFO *info, int tcd)
+static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty)
{
unsigned char data, status, flag;
int fifo_count;
int work = 0;
- struct tty_struct *tty = info->tty;
struct mgsl_icount *icount = &info->icount;
if (tcd) {
@@ -1013,7 +1012,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd)
}
-static void tx_done(MGSLPC_INFO *info)
+static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty)
{
if (!info->tx_active)
return;
@@ -1042,7 +1041,7 @@ static void tx_done(MGSLPC_INFO *info)
else
#endif
{
- if (info->tty->stopped || info->tty->hw_stopped) {
+ if (tty->stopped || tty->hw_stopped) {
tx_stop(info);
return;
}
@@ -1050,7 +1049,7 @@ static void tx_done(MGSLPC_INFO *info)
}
}
-static void tx_ready(MGSLPC_INFO *info)
+static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty)
{
unsigned char fifo_count = 32;
int c;
@@ -1062,7 +1061,7 @@ static void tx_ready(MGSLPC_INFO *info)
if (!info->tx_active)
return;
} else {
- if (info->tty->stopped || info->tty->hw_stopped) {
+ if (tty->stopped || tty->hw_stopped) {
tx_stop(info);
return;
}
@@ -1099,7 +1098,7 @@ static void tx_ready(MGSLPC_INFO *info)
}
}
-static void cts_change(MGSLPC_INFO *info)
+static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
{
get_signals(info);
if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
@@ -1112,14 +1111,14 @@ static void cts_change(MGSLPC_INFO *info)
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
- if (info->flags & ASYNC_CTS_FLOW) {
- if (info->tty->hw_stopped) {
+ if (info->port.flags & ASYNC_CTS_FLOW) {
+ if (tty->hw_stopped) {
if (info->serial_signals & SerialSignal_CTS) {
if (debug_level >= DEBUG_LEVEL_ISR)
printk("CTS tx start...");
- if (info->tty)
- info->tty->hw_stopped = 0;
- tx_start(info);
+ if (tty)
+ tty->hw_stopped = 0;
+ tx_start(info, tty);
info->pending_bh |= BH_TRANSMIT;
return;
}
@@ -1127,8 +1126,8 @@ static void cts_change(MGSLPC_INFO *info)
if (!(info->serial_signals & SerialSignal_CTS)) {
if (debug_level >= DEBUG_LEVEL_ISR)
printk("CTS tx stop...");
- if (info->tty)
- info->tty->hw_stopped = 1;
+ if (tty)
+ tty->hw_stopped = 1;
tx_stop(info);
}
}
@@ -1136,7 +1135,7 @@ static void cts_change(MGSLPC_INFO *info)
info->pending_bh |= BH_STATUS;
}
-static void dcd_change(MGSLPC_INFO *info)
+static void dcd_change(MGSLPC_INFO *info, struct tty_struct *tty)
{
get_signals(info);
if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
@@ -1158,17 +1157,17 @@ static void dcd_change(MGSLPC_INFO *info)
wake_up_interruptible(&info->status_event_wait_q);
wake_up_interruptible(&info->event_wait_q);
- if (info->flags & ASYNC_CHECK_CD) {
+ if (info->port.flags & ASYNC_CHECK_CD) {
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s CD now %s...", info->device_name,
(info->serial_signals & SerialSignal_DCD) ? "on" : "off");
if (info->serial_signals & SerialSignal_DCD)
- wake_up_interruptible(&info->open_wait);
+ wake_up_interruptible(&info->port.open_wait);
else {
if (debug_level >= DEBUG_LEVEL_ISR)
printk("doing serial hangup...");
- if (info->tty)
- tty_hangup(info->tty);
+ if (tty)
+ tty_hangup(tty);
}
}
info->pending_bh |= BH_STATUS;
@@ -1214,6 +1213,7 @@ static void ri_change(MGSLPC_INFO *info)
static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
{
MGSLPC_INFO *info = dev_id;
+ struct tty_struct *tty;
unsigned short isr;
unsigned char gis, pis;
int count=0;
@@ -1224,6 +1224,8 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
if (!(info->p_dev->_locked))
return IRQ_HANDLED;
+ tty = tty_port_tty_get(&info->port);
+
spin_lock(&info->lock);
while ((gis = read_reg(info, CHA + GIS))) {
@@ -1239,9 +1241,9 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
if (gis & (BIT1 + BIT0)) {
isr = read_reg16(info, CHB + ISR);
if (isr & IRQ_DCD)
- dcd_change(info);
+ dcd_change(info, tty);
if (isr & IRQ_CTS)
- cts_change(info);
+ cts_change(info, tty);
}
if (gis & (BIT3 + BIT2))
{
@@ -1258,8 +1260,8 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
}
if (isr & IRQ_BREAK_ON) {
info->icount.brk++;
- if (info->flags & ASYNC_SAK)
- do_SAK(info->tty);
+ if (info->port.flags & ASYNC_SAK)
+ do_SAK(tty);
}
if (isr & IRQ_RXTIME) {
issue_command(info, CHA, CMD_RXFIFO_READ);
@@ -1268,7 +1270,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
if (info->params.mode == MGSL_MODE_HDLC)
rx_ready_hdlc(info, isr & IRQ_RXEOM);
else
- rx_ready_async(info, isr & IRQ_RXEOM);
+ rx_ready_async(info, isr & IRQ_RXEOM, tty);
}
/* transmit IRQs */
@@ -1277,14 +1279,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
info->icount.txabort++;
else
info->icount.txunder++;
- tx_done(info);
+ tx_done(info, tty);
}
else if (isr & IRQ_ALLSENT) {
info->icount.txok++;
- tx_done(info);
+ tx_done(info, tty);
}
else if (isr & IRQ_TXFIFO)
- tx_ready(info);
+ tx_ready(info, tty);
}
if (gis & BIT7) {
pis = read_reg(info, CHA + PIS);
@@ -1308,6 +1310,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
}
spin_unlock(&info->lock);
+ tty_kref_put(tty);
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):mgslpc_isr(%d)exit.\n",
@@ -1318,14 +1321,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
/* Initialize and start device.
*/
-static int startup(MGSLPC_INFO * info)
+static int startup(MGSLPC_INFO * info, struct tty_struct *tty)
{
int retval = 0;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):startup(%s)\n",__FILE__,__LINE__,info->device_name);
- if (info->flags & ASYNC_INITIALIZED)
+ if (info->port.flags & ASYNC_INITIALIZED)
return 0;
if (!info->tx_buf) {
@@ -1352,30 +1355,30 @@ static int startup(MGSLPC_INFO * info)
retval = adapter_test(info);
if ( retval ) {
- if (capable(CAP_SYS_ADMIN) && info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (capable(CAP_SYS_ADMIN) && tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
release_resources(info);
return retval;
}
/* program hardware for current parameters */
- mgslpc_change_params(info);
+ mgslpc_change_params(info, tty);
- if (info->tty)
- clear_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (tty)
+ clear_bit(TTY_IO_ERROR, &tty->flags);
- info->flags |= ASYNC_INITIALIZED;
+ info->port.flags |= ASYNC_INITIALIZED;
return 0;
}
/* Called by mgslpc_close() and mgslpc_hangup() to shutdown hardware
*/
-static void shutdown(MGSLPC_INFO * info)
+static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty)
{
unsigned long flags;
- if (!(info->flags & ASYNC_INITIALIZED))
+ if (!(info->port.flags & ASYNC_INITIALIZED))
return;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1402,7 +1405,7 @@ static void shutdown(MGSLPC_INFO * info)
/* TODO:disable interrupts instead of reset to preserve signal states */
reset_device(info);
- if (!info->tty || info->tty->termios->c_cflag & HUPCL) {
+ if (!tty || tty->termios->c_cflag & HUPCL) {
info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
set_signals(info);
}
@@ -1411,13 +1414,13 @@ static void shutdown(MGSLPC_INFO * info)
release_resources(info);
- if (info->tty)
- set_bit(TTY_IO_ERROR, &info->tty->flags);
+ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
- info->flags &= ~ASYNC_INITIALIZED;
+ info->port.flags &= ~ASYNC_INITIALIZED;
}
-static void mgslpc_program_hw(MGSLPC_INFO *info)
+static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty)
{
unsigned long flags;
@@ -1443,7 +1446,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info)
port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);
get_signals(info);
- if (info->netcount || info->tty->termios->c_cflag & CREAD)
+ if (info->netcount || (tty && (tty->termios->c_cflag & CREAD)))
rx_start(info);
spin_unlock_irqrestore(&info->lock,flags);
@@ -1451,19 +1454,19 @@ static void mgslpc_program_hw(MGSLPC_INFO *info)
/* Reconfigure adapter based on new parameters
*/
-static void mgslpc_change_params(MGSLPC_INFO *info)
+static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
{
unsigned cflag;
int bits_per_char;
- if (!info->tty || !info->tty->termios)
+ if (!tty || !tty->termios)
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_change_params(%s)\n",
__FILE__,__LINE__, info->device_name );
- cflag = info->tty->termios->c_cflag;
+ cflag = tty->termios->c_cflag;
/* if B0 rate (hangup) specified then negate DTR and RTS */
/* otherwise assert DTR and RTS */
@@ -1510,7 +1513,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
* current data rate.
*/
if (info->params.data_rate <= 460800) {
- info->params.data_rate = tty_get_baud_rate(info->tty);
+ info->params.data_rate = tty_get_baud_rate(tty);
}
if ( info->params.data_rate ) {
@@ -1520,24 +1523,24 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
info->timeout += HZ/50; /* Add .02 seconds of slop */
if (cflag & CRTSCTS)
- info->flags |= ASYNC_CTS_FLOW;
+ info->port.flags |= ASYNC_CTS_FLOW;
else
- info->flags &= ~ASYNC_CTS_FLOW;
+ info->port.flags &= ~ASYNC_CTS_FLOW;
if (cflag & CLOCAL)
- info->flags &= ~ASYNC_CHECK_CD;
+ info->port.flags &= ~ASYNC_CHECK_CD;
else
- info->flags |= ASYNC_CHECK_CD;
+ info->port.flags |= ASYNC_CHECK_CD;
/* process tty input control flags */
info->read_status_mask = 0;
- if (I_INPCK(info->tty))
+ if (I_INPCK(tty))
info->read_status_mask |= BIT7 | BIT6;
- if (I_IGNPAR(info->tty))
+ if (I_IGNPAR(tty))
info->ignore_status_mask |= BIT7 | BIT6;
- mgslpc_program_hw(info);
+ mgslpc_program_hw(info, tty);
}
/* Add a character to the transmit buffer
@@ -1597,7 +1600,7 @@ static void mgslpc_flush_chars(struct tty_struct *tty)
spin_lock_irqsave(&info->lock,flags);
if (!info->tx_active)
- tx_start(info);
+ tx_start(info, tty);
spin_unlock_irqrestore(&info->lock,flags);
}
@@ -1659,7 +1662,7 @@ start:
if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
spin_lock_irqsave(&info->lock,flags);
if (!info->tx_active)
- tx_start(info);
+ tx_start(info, tty);
spin_unlock_irqrestore(&info->lock,flags);
}
cleanup:
@@ -1764,7 +1767,7 @@ static void mgslpc_send_xchar(struct tty_struct *tty, char ch)
if (ch) {
spin_lock_irqsave(&info->lock,flags);
if (!info->tx_enabled)
- tx_start(info);
+ tx_start(info, tty);
spin_unlock_irqrestore(&info->lock,flags);
}
}
@@ -1862,7 +1865,7 @@ static int get_params(MGSLPC_INFO * info, MGSL_PARAMS __user *user_params)
*
* Returns: 0 if success, otherwise error code
*/
-static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params)
+static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params, struct tty_struct *tty)
{
unsigned long flags;
MGSL_PARAMS tmp_params;
@@ -1883,7 +1886,7 @@ static int set_params(MGSLPC_INFO * info, MGSL_PARAMS __user *new_params)
memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
spin_unlock_irqrestore(&info->lock,flags);
- mgslpc_change_params(info);
+ mgslpc_change_params(info, tty);
return 0;
}
@@ -1944,7 +1947,7 @@ static int set_interface(MGSLPC_INFO * info, int if_mode)
return 0;
}
-static int set_txenable(MGSLPC_INFO * info, int enable)
+static int set_txenable(MGSLPC_INFO * info, int enable, struct tty_struct *tty)
{
unsigned long flags;
@@ -1954,7 +1957,7 @@ static int set_txenable(MGSLPC_INFO * info, int enable)
spin_lock_irqsave(&info->lock,flags);
if (enable) {
if (!info->tx_enabled)
- tx_start(info);
+ tx_start(info, tty);
} else {
if (info->tx_enabled)
tx_stop(info);
@@ -2263,6 +2266,11 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
+ int error;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ struct serial_icounter_struct __user *p_cuser; /* user space */
+ void __user *argp = (void __user *)arg;
+ unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2277,22 +2285,11 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return -EIO;
}
- return ioctl_common(info, cmd, arg);
-}
-
-static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
-{
- int error;
- struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
- void __user *argp = (void __user *)arg;
- unsigned long flags;
-
switch (cmd) {
case MGSL_IOCGPARAMS:
return get_params(info, argp);
case MGSL_IOCSPARAMS:
- return set_params(info, argp);
+ return set_params(info, argp, tty);
case MGSL_IOCGTXIDLE:
return get_txidle(info, argp);
case MGSL_IOCSTXIDLE:
@@ -2302,7 +2299,7 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
case MGSL_IOCSIF:
return set_interface(info,(int)arg);
case MGSL_IOCTXENABLE:
- return set_txenable(info,(int)arg);
+ return set_txenable(info,(int)arg, tty);
case MGSL_IOCRXENABLE:
return set_rxenable(info,(int)arg);
case MGSL_IOCTXABORT:
@@ -2369,7 +2366,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
== RELEVANT_IFLAG(old_termios->c_iflag)))
return;
- mgslpc_change_params(info);
+ mgslpc_change_params(info, tty);
/* Handle transition to B0 status */
if (old_termios->c_cflag & CBAUD &&
@@ -2404,81 +2401,34 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
static void mgslpc_close(struct tty_struct *tty, struct file * filp)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
+ struct tty_port *port = &info->port;
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
- __FILE__,__LINE__, info->device_name, info->count);
-
- if (!info->count)
- return;
+ __FILE__,__LINE__, info->device_name, port->count);
- if (tty_hung_up_p(filp))
- goto cleanup;
-
- if ((tty->count == 1) && (info->count != 1)) {
- /*
- * tty->count is 1 and the tty structure will be freed.
- * info->count should be one in this case.
- * if it's not, correct it so that the port is shutdown.
- */
- printk("mgslpc_close: bad refcount; tty->count is 1, "
- "info->count is %d\n", info->count);
- info->count = 1;
- }
+ WARN_ON(!port->count);
- info->count--;
-
- /* if at least one open remaining, leave hardware active */
- if (info->count)
+ if (tty_port_close_start(port, tty, filp) == 0)
goto cleanup;
- info->flags |= ASYNC_CLOSING;
-
- /* set tty->closing to notify line discipline to
- * only process XON/XOFF characters. Only the N_TTY
- * discipline appears to use this (ppp does not).
- */
- tty->closing = 1;
-
- /* wait for transmit data to clear all layers */
-
- if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):mgslpc_close(%s) calling tty_wait_until_sent\n",
- __FILE__,__LINE__, info->device_name );
- tty_wait_until_sent(tty, info->closing_wait);
- }
-
- if (info->flags & ASYNC_INITIALIZED)
+ if (port->flags & ASYNC_INITIALIZED)
mgslpc_wait_until_sent(tty, info->timeout);
mgslpc_flush_buffer(tty);
tty_ldisc_flush(tty);
-
- shutdown(info);
-
- tty->closing = 0;
- info->tty = NULL;
-
- if (info->blocked_open) {
- if (info->close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->close_delay));
- }
- wake_up_interruptible(&info->open_wait);
- }
-
- info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-
- wake_up_interruptible(&info->close_wait);
-
+ shutdown(info, tty);
+
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
cleanup:
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_close(%s) exit, count=%d\n", __FILE__,__LINE__,
- tty->driver->name, info->count);
+ tty->driver->name, port->count);
}
/* Wait until the transmitter is empty.
@@ -2498,7 +2448,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout)
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent"))
return;
- if (!(info->flags & ASYNC_INITIALIZED))
+ if (!(info->port.flags & ASYNC_INITIALIZED))
goto exit;
orig_jiffies = jiffies;
@@ -2559,120 +2509,40 @@ static void mgslpc_hangup(struct tty_struct *tty)
return;
mgslpc_flush_buffer(tty);
- shutdown(info);
-
- info->count = 0;
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
- info->tty = NULL;
-
- wake_up_interruptible(&info->open_wait);
+ shutdown(info, tty);
+ tty_port_hangup(&info->port);
}
-/* Block the current process until the specified port
- * is ready to be opened.
- */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
- MGSLPC_INFO *info)
+static int carrier_raised(struct tty_port *port)
{
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- bool do_clocal = false;
- bool extra_count = false;
- unsigned long flags;
-
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):block_til_ready on %s\n",
- __FILE__,__LINE__, tty->driver->name );
-
- if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
- /* nonblock mode is set or port is not enabled */
- /* just verify that callout device is not active */
- info->flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = true;
-
- /* Wait for carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * mgslpc_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
-
- retval = 0;
- add_wait_queue(&info->open_wait, &wait);
-
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):block_til_ready before block on %s count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->count );
-
- spin_lock_irqsave(&info->lock, flags);
- if (!tty_hung_up_p(filp)) {
- extra_count = true;
- info->count--;
- }
- spin_unlock_irqrestore(&info->lock, flags);
- info->blocked_open++;
-
- while (1) {
- if ((tty->termios->c_cflag & CBAUD)) {
- spin_lock_irqsave(&info->lock,flags);
- info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
- set_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
- }
-
- set_current_state(TASK_INTERRUPTIBLE);
-
- if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){
- retval = (info->flags & ASYNC_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS;
- break;
- }
-
- spin_lock_irqsave(&info->lock,flags);
- get_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
-
- if (!(info->flags & ASYNC_CLOSING) &&
- (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) {
- break;
- }
-
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):block_til_ready blocking on %s count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->count );
-
- schedule();
- }
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->open_wait, &wait);
+ MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);
+ unsigned long flags;
- if (extra_count)
- info->count++;
- info->blocked_open--;
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->count );
+ if (info->serial_signals & SerialSignal_DCD)
+ return 1;
+ return 0;
+}
- if (!retval)
- info->flags |= ASYNC_NORMAL_ACTIVE;
+static void raise_dtr_rts(struct tty_port *port)
+{
+ MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port);
+ unsigned long flags;
- return retval;
+ spin_lock_irqsave(&info->lock,flags);
+ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
}
+
static int mgslpc_open(struct tty_struct *tty, struct file * filp)
{
MGSLPC_INFO *info;
+ struct tty_port *port;
int retval, line;
unsigned long flags;
@@ -2691,23 +2561,24 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open"))
return -ENODEV;
+ port = &info->port;
tty->driver_data = info;
- info->tty = tty;
+ tty_port_tty_set(port, tty);
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
- __FILE__,__LINE__,tty->driver->name, info->count);
+ __FILE__,__LINE__,tty->driver->name, port->count);
/* If port is closing, signal caller to try again */
- if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){
- if (info->flags & ASYNC_CLOSING)
- interruptible_sleep_on(&info->close_wait);
- retval = ((info->flags & ASYNC_HUP_NOTIFY) ?
+ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
+ if (port->flags & ASYNC_CLOSING)
+ interruptible_sleep_on(&port->close_wait);
+ retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
goto cleanup;
}
- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
if (info->netcount) {
@@ -2715,17 +2586,19 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
spin_unlock_irqrestore(&info->netlock, flags);
goto cleanup;
}
- info->count++;
+ spin_lock(&port->lock);
+ port->count++;
+ spin_unlock(&port->lock);
spin_unlock_irqrestore(&info->netlock, flags);
- if (info->count == 1) {
+ if (port->count == 1) {
/* 1st open on this device, init hardware */
- retval = startup(info);
+ retval = startup(info, tty);
if (retval < 0)
goto cleanup;
}
- retval = block_til_ready(tty, filp, info);
+ retval = tty_port_block_til_ready(&info->port, tty, filp);
if (retval) {
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready(%s) returned %d\n",
@@ -2739,13 +2612,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
retval = 0;
cleanup:
- if (retval) {
- if (tty->count == 1)
- info->tty = NULL; /* tty layer will release tty struct */
- if(info->count)
- info->count--;
- }
-
return retval;
}
@@ -3500,7 +3366,7 @@ static void rx_start(MGSLPC_INFO *info)
info->rx_enabled = true;
}
-static void tx_start(MGSLPC_INFO *info)
+static void tx_start(MGSLPC_INFO *info, struct tty_struct *tty)
{
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):tx_start(%s)\n",
@@ -3524,11 +3390,11 @@ static void tx_start(MGSLPC_INFO *info)
if (info->params.mode == MGSL_MODE_ASYNC) {
if (!info->tx_active) {
info->tx_active = true;
- tx_ready(info);
+ tx_ready(info, tty);
}
} else {
info->tx_active = true;
- tx_ready(info);
+ tx_ready(info, tty);
mod_timer(&info->tx_timer, jiffies +
msecs_to_jiffies(5000));
}
@@ -3849,13 +3715,12 @@ static void rx_reset_buffers(MGSLPC_INFO *info)
*
* Returns true if frame returned, otherwise false
*/
-static bool rx_get_frame(MGSLPC_INFO *info)
+static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty)
{
unsigned short status;
RXBUF *buf;
unsigned int framesize = 0;
unsigned long flags;
- struct tty_struct *tty = info->tty;
bool return_frame = false;
if (info->rx_frame_count == 0)
@@ -4075,7 +3940,11 @@ static void tx_timeout(unsigned long context)
hdlcdev_tx_done(info);
else
#endif
- bh_transmit(info);
+ {
+ struct tty_struct *tty = tty_port_tty_get(&info->port);
+ bh_transmit(info, tty);
+ tty_kref_put(tty);
+ }
}
#if SYNCLINK_GENERIC_HDLC
@@ -4094,11 +3963,12 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
unsigned short parity)
{
MGSLPC_INFO *info = dev_to_port(dev);
+ struct tty_struct *tty;
unsigned char new_encoding;
unsigned short new_crctype;
/* return error if TTY interface open */
- if (info->count)
+ if (info->port.count)
return -EBUSY;
switch (encoding)
@@ -4123,8 +3993,11 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
info->params.crc_type = new_crctype;
/* if network interface up, reprogram hardware */
- if (info->netcount)
- mgslpc_program_hw(info);
+ if (info->netcount) {
+ tty = tty_port_tty_get(&info->port);
+ mgslpc_program_hw(info, tty);
+ tty_kref_put(tty);
+ }
return 0;
}
@@ -4165,8 +4038,11 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
/* start hardware transmitter if necessary */
spin_lock_irqsave(&info->lock,flags);
- if (!info->tx_active)
- tx_start(info);
+ if (!info->tx_active) {
+ struct tty_struct *tty = tty_port_tty_get(&info->port);
+ tx_start(info, tty);
+ tty_kref_put(tty);
+ }
spin_unlock_irqrestore(&info->lock,flags);
return 0;
@@ -4183,6 +4059,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
static int hdlcdev_open(struct net_device *dev)
{
MGSLPC_INFO *info = dev_to_port(dev);
+ struct tty_struct *tty;
int rc;
unsigned long flags;
@@ -4195,7 +4072,7 @@ static int hdlcdev_open(struct net_device *dev)
/* arbitrate between network and tty opens */
spin_lock_irqsave(&info->netlock, flags);
- if (info->count != 0 || info->netcount != 0) {
+ if (info->port.count != 0 || info->netcount != 0) {
printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
spin_unlock_irqrestore(&info->netlock, flags);
return -EBUSY;
@@ -4203,17 +4080,19 @@ static int hdlcdev_open(struct net_device *dev)
info->netcount=1;
spin_unlock_irqrestore(&info->netlock, flags);
+ tty = tty_port_tty_get(&info->port);
/* claim resources and init adapter */
- if ((rc = startup(info)) != 0) {
+ if ((rc = startup(info, tty)) != 0) {
+ tty_kref_put(tty);
spin_lock_irqsave(&info->netlock, flags);
info->netcount=0;
spin_unlock_irqrestore(&info->netlock, flags);
return rc;
}
-
/* assert DTR and RTS, apply hardware settings */
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
- mgslpc_program_hw(info);
+ mgslpc_program_hw(info, tty);
+ tty_kref_put(tty);
/* enable network layer transmit */
dev->trans_start = jiffies;
@@ -4241,6 +4120,7 @@ static int hdlcdev_open(struct net_device *dev)
static int hdlcdev_close(struct net_device *dev)
{
MGSLPC_INFO *info = dev_to_port(dev);
+ struct tty_struct *tty = tty_port_tty_get(&info->port);
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -4249,8 +4129,8 @@ static int hdlcdev_close(struct net_device *dev)
netif_stop_queue(dev);
/* shutdown adapter and release resources */
- shutdown(info);
-
+ shutdown(info, tty);
+ tty_kref_put(tty);
hdlc_close(dev);
spin_lock_irqsave(&info->netlock, flags);
@@ -4281,7 +4161,7 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
/* return error if TTY interface open */
- if (info->count)
+ if (info->port.count)
return -EBUSY;
if (cmd != SIOCWANDEV)
@@ -4354,8 +4234,11 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
info->params.clock_speed = 0;
/* if network interface up, reprogram hardware */
- if (info->netcount)
- mgslpc_program_hw(info);
+ if (info->netcount) {
+ struct tty_struct *tty = tty_port_tty_get(&info->port);
+ mgslpc_program_hw(info, tty);
+ tty_kref_put(tty);
+ }
return 0;
default:
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index 79b6f461be75..afbe45676d71 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -44,7 +44,7 @@ static ssize_t ps3flash_read_write_sectors(struct ps3_storage_device *dev,
u64 res = ps3stor_read_write_sectors(dev, lpar, start_sector, sectors,
write);
if (res) {
- dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+ dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
__LINE__, write ? "write" : "read", res);
return -EIO;
}
@@ -59,7 +59,7 @@ static ssize_t ps3flash_read_sectors(struct ps3_storage_device *dev,
max_sectors = dev->bounce_size / dev->blk_size;
if (sectors > max_sectors) {
- dev_dbg(&dev->sbd.core, "%s:%u Limiting sectors to %lu\n",
+ dev_dbg(&dev->sbd.core, "%s:%u Limiting sectors to %llu\n",
__func__, __LINE__, max_sectors);
sectors = max_sectors;
}
@@ -144,7 +144,7 @@ static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
goto fail;
}
- n = min(remaining, sectors_read*dev->blk_size-offset);
+ n = min_t(u64, remaining, sectors_read*dev->blk_size-offset);
dev_dbg(&dev->sbd.core,
"%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
__func__, __LINE__, n, dev->bounce_buf+offset, buf);
@@ -225,7 +225,7 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf,
if (end_read_sector >= start_read_sector) {
/* Merge head and tail */
dev_dbg(&dev->sbd.core,
- "Merged head and tail: %lu sectors at %lu\n",
+ "Merged head and tail: %llu sectors at %llu\n",
chunk_sectors, start_write_sector);
res = ps3flash_read_sectors(dev, start_write_sector,
chunk_sectors, 0);
@@ -235,7 +235,7 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf,
if (head) {
/* Read head */
dev_dbg(&dev->sbd.core,
- "head: %lu sectors at %lu\n", head,
+ "head: %llu sectors at %llu\n", head,
start_write_sector);
res = ps3flash_read_sectors(dev,
start_write_sector,
@@ -247,7 +247,7 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf,
start_write_sector+chunk_sectors) {
/* Read tail */
dev_dbg(&dev->sbd.core,
- "tail: %lu sectors at %lu\n", tail,
+ "tail: %llu sectors at %llu\n", tail,
start_read_sector);
sec_off = start_read_sector-start_write_sector;
res = ps3flash_read_sectors(dev,
@@ -258,7 +258,7 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf,
}
}
- n = min(remaining, dev->bounce_size-offset);
+ n = min_t(u64, remaining, dev->bounce_size-offset);
dev_dbg(&dev->sbd.core,
"%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
__func__, __LINE__, n, buf, dev->bounce_buf+offset);
@@ -299,11 +299,11 @@ static irqreturn_t ps3flash_interrupt(int irq, void *data)
if (tag != dev->tag)
dev_err(&dev->sbd.core,
- "%s:%u: tag mismatch, got %lx, expected %lx\n",
+ "%s:%u: tag mismatch, got %llx, expected %llx\n",
__func__, __LINE__, tag, dev->tag);
if (res) {
- dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
+ dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
__func__, __LINE__, res, status);
} else {
dev->lv1_status = status;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 6d4582712b1f..31038a0052a2 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -5,8 +5,6 @@
*
* Added support for a Unix98-style ptmx device.
* -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
- * Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to
- * waiting writers -- Sapan Bhatia <sapan@corewars.org>
*
* When reading this code see also fs/devpts. In particular note that the
* driver_data field is used by the devpts side as a binding to the devpts
@@ -34,7 +32,7 @@
/* These are global because they are accessed in tty_io.c */
#ifdef CONFIG_UNIX98_PTYS
-struct tty_driver *ptm_driver;
+static struct tty_driver *ptm_driver;
static struct tty_driver *pts_driver;
#endif
@@ -217,7 +215,6 @@ static int pty_open(struct tty_struct *tty, struct file *filp)
clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
set_bit(TTY_THROTTLED, &tty->flags);
- set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
retval = 0;
out:
return retval;
@@ -230,6 +227,53 @@ static void pty_set_termios(struct tty_struct *tty,
tty->termios->c_cflag |= (CS8 | CREAD);
}
+/**
+ * pty_do_resize - resize event
+ * @tty: tty being resized
+ * @ws: window size being set.
+ *
+ * Update the termios variables and send the neccessary signals to
+ * peform a terminal resize correctly
+ */
+
+int pty_resize(struct tty_struct *tty, struct winsize *ws)
+{
+ struct pid *pgrp, *rpgrp;
+ unsigned long flags;
+ struct tty_struct *pty = tty->link;
+
+ /* For a PTY we need to lock the tty side */
+ mutex_lock(&tty->termios_mutex);
+ if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
+ goto done;
+
+ /* Get the PID values and reference them so we can
+ avoid holding the tty ctrl lock while sending signals.
+ We need to lock these individually however. */
+
+ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ pgrp = get_pid(tty->pgrp);
+ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
+ spin_lock_irqsave(&pty->ctrl_lock, flags);
+ rpgrp = get_pid(pty->pgrp);
+ spin_unlock_irqrestore(&pty->ctrl_lock, flags);
+
+ if (pgrp)
+ kill_pgrp(pgrp, SIGWINCH, 1);
+ if (rpgrp != pgrp && rpgrp)
+ kill_pgrp(rpgrp, SIGWINCH, 1);
+
+ put_pid(pgrp);
+ put_pid(rpgrp);
+
+ tty->winsize = *ws;
+ pty->winsize = *ws; /* Never used so will go away soon */
+done:
+ mutex_unlock(&tty->termios_mutex);
+ return 0;
+}
+
static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
{
struct tty_struct *o_tty;
@@ -290,6 +334,7 @@ static const struct tty_operations pty_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
+ .resize = pty_resize
};
/* Traditional BSD devices */
@@ -319,6 +364,7 @@ static const struct tty_operations pty_ops_bsd = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_bsd_ioctl,
+ .resize = pty_resize
};
static void __init legacy_pty_init(void)
@@ -561,7 +607,8 @@ static const struct tty_operations ptm_unix98_ops = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
- .shutdown = pty_unix98_shutdown
+ .shutdown = pty_unix98_shutdown,
+ .resize = pty_resize
};
static const struct tty_operations pty_unix98_ops = {
diff --git a/drivers/char/random.c b/drivers/char/random.c
index d26891bfcd41..7c13581ca9cd 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -407,7 +407,7 @@ struct entropy_store {
/* read-write data: */
spinlock_t lock;
unsigned add_ptr;
- int entropy_count; /* Must at no time exceed ->POOLBITS! */
+ int entropy_count;
int input_rotate;
};
@@ -559,7 +559,40 @@ struct timer_rand_state {
};
#ifndef CONFIG_SPARSE_IRQ
-struct timer_rand_state *irq_timer_state[NR_IRQS];
+
+static struct timer_rand_state *irq_timer_state[NR_IRQS];
+
+static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+{
+ return irq_timer_state[irq];
+}
+
+static void set_timer_rand_state(unsigned int irq,
+ struct timer_rand_state *state)
+{
+ irq_timer_state[irq] = state;
+}
+
+#else
+
+static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+{
+ struct irq_desc *desc;
+
+ desc = irq_to_desc(irq);
+
+ return desc->timer_rand_state;
+}
+
+static void set_timer_rand_state(unsigned int irq,
+ struct timer_rand_state *state)
+{
+ struct irq_desc *desc;
+
+ desc = irq_to_desc(irq);
+
+ desc->timer_rand_state = state;
+}
#endif
static struct timer_rand_state input_timer_state;
@@ -734,11 +767,10 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
{
unsigned long flags;
- BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
-
/* Hold lock while accounting */
spin_lock_irqsave(&r->lock, flags);
+ BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
DEBUG_ENT("trying to extract %d bits from %s\n",
nbytes * 8, r->name);
@@ -919,11 +951,6 @@ void rand_initialize_irq(int irq)
{
struct timer_rand_state *state;
-#ifndef CONFIG_SPARSE_IRQ
- if (irq >= nr_irqs)
- return;
-#endif
-
state = get_timer_rand_state(irq);
if (state)
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index a8f68a3f14dd..2e8a6eed34be 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -173,7 +173,7 @@ static void rio_disable_tx_interrupts(void *ptr);
static void rio_enable_tx_interrupts(void *ptr);
static void rio_disable_rx_interrupts(void *ptr);
static void rio_enable_rx_interrupts(void *ptr);
-static int rio_get_CD(void *ptr);
+static int rio_carrier_raised(struct tty_port *port);
static void rio_shutdown_port(void *ptr);
static int rio_set_real_termios(void *ptr);
static void rio_hungup(void *ptr);
@@ -224,7 +224,6 @@ static struct real_driver rio_real_driver = {
rio_enable_tx_interrupts,
rio_disable_rx_interrupts,
rio_enable_rx_interrupts,
- rio_get_CD,
rio_shutdown_port,
rio_set_real_termios,
rio_chars_in_buffer,
@@ -476,9 +475,9 @@ static void rio_enable_rx_interrupts(void *ptr)
/* Jeez. Isn't this simple? */
-static int rio_get_CD(void *ptr)
+static int rio_carrier_raised(struct tty_port *port)
{
- struct Port *PortP = ptr;
+ struct Port *PortP = container_of(port, struct Port, gs.port);
int rv;
func_enter();
@@ -797,16 +796,9 @@ static int rio_init_drivers(void)
return 1;
}
-
-static void *ckmalloc(int size)
-{
- void *p;
-
- p = kzalloc(size, GFP_KERNEL);
- return p;
-}
-
-
+static const struct tty_port_operations rio_port_ops = {
+ .carrier_raised = rio_carrier_raised,
+};
static int rio_init_datastructures(void)
{
@@ -826,33 +818,30 @@ static int rio_init_datastructures(void)
#define TMIO_SZ sizeof(struct termios *)
rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
- if (!(p = ckmalloc(RI_SZ)))
+ if (!(p = kzalloc(RI_SZ, GFP_KERNEL)))
goto free0;
- if (!(p->RIOHosts = ckmalloc(RIO_HOSTS * HOST_SZ)))
+ if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL)))
goto free1;
- if (!(p->RIOPortp = ckmalloc(RIO_PORTS * PORT_SZ)))
+ if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL)))
goto free2;
p->RIOConf = RIOConf;
rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
#if 1
for (i = 0; i < RIO_PORTS; i++) {
- port = p->RIOPortp[i] = ckmalloc(sizeof(struct Port));
+ port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL);
if (!port) {
goto free6;
}
rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
+ tty_port_init(&port->gs.port);
+ port->gs.port.ops = &rio_port_ops;
port->PortNum = i;
port->gs.magic = RIO_MAGIC;
port->gs.close_delay = HZ / 2;
port->gs.closing_wait = 30 * HZ;
port->gs.rd = &rio_real_driver;
spin_lock_init(&port->portSem);
- /*
- * Initializing wait queue
- */
- init_waitqueue_head(&port->gs.port.open_wait);
- init_waitqueue_head(&port->gs.port.close_wait);
}
#else
/* We could postpone initializing them to when they are configured. */
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 2c6c8f33d6b4..9af8d74875bc 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -857,98 +857,21 @@ static void rc_shutdown_port(struct tty_struct *tty,
rc_shutdown_board(bp);
}
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
- struct riscom_port *port)
+static int carrier_raised(struct tty_port *port)
{
- DECLARE_WAITQUEUE(wait, current);
- struct riscom_board *bp = port_Board(port);
- int retval;
- int do_clocal = 0;
- int CD;
+ struct riscom_port *p = container_of(port, struct riscom_port, port);
+ struct riscom_board *bp = port_Board(p);
unsigned long flags;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&port->port.close_wait);
- if (port->port.flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- else
- return -ERESTARTSYS;
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (tty->flags & (1 << TTY_IO_ERROR))) {
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
- }
-
- if (C_CLOCAL(tty))
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become
- * free (i.e., not in use by the callout). While we are in
- * this loop, info->count is dropped by one, so that
- * rs_close() knows when to free things. We restore it upon
- * exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&port->port.open_wait, &wait);
-
+ int CD;
+
spin_lock_irqsave(&riscom_lock, flags);
-
- if (!tty_hung_up_p(filp))
- port->port.count--;
-
+ rc_out(bp, CD180_CAR, port_No(p));
+ CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
+ rc_out(bp, CD180_MSVR, MSVR_RTS);
+ bp->DTR &= ~(1u << port_No(p));
+ rc_out(bp, RC_DTR, bp->DTR);
spin_unlock_irqrestore(&riscom_lock, flags);
-
- port->port.blocked_open++;
- while (1) {
- spin_lock_irqsave(&riscom_lock, flags);
-
- rc_out(bp, CD180_CAR, port_No(port));
- CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
- rc_out(bp, CD180_MSVR, MSVR_RTS);
- bp->DTR &= ~(1u << port_No(port));
- rc_out(bp, RC_DTR, bp->DTR);
-
- spin_unlock_irqrestore(&riscom_lock, flags);
-
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) ||
- !(port->port.flags & ASYNC_INITIALIZED)) {
- if (port->port.flags & ASYNC_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(port->port.flags & ASYNC_CLOSING) &&
- (do_clocal || CD))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&port->port.open_wait, &wait);
- if (!tty_hung_up_p(filp))
- port->port.count++;
- port->port.blocked_open--;
- if (retval)
- return retval;
-
- port->port.flags |= ASYNC_NORMAL_ACTIVE;
- return 0;
+ return CD;
}
static int rc_open(struct tty_struct *tty, struct file *filp)
@@ -977,13 +900,13 @@ static int rc_open(struct tty_struct *tty, struct file *filp)
error = rc_setup_port(bp, port);
if (error == 0)
- error = block_til_ready(tty, filp, port);
+ error = tty_port_block_til_ready(&port->port, tty, filp);
return error;
}
static void rc_flush_buffer(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
unsigned long flags;
if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
@@ -998,7 +921,7 @@ static void rc_flush_buffer(struct tty_struct *tty)
static void rc_close(struct tty_struct *tty, struct file *filp)
{
- struct riscom_port *port = (struct riscom_port *) tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned long flags;
unsigned long timeout;
@@ -1006,40 +929,19 @@ static void rc_close(struct tty_struct *tty, struct file *filp)
if (!port || rc_paranoia_check(port, tty->name, "close"))
return;
- spin_lock_irqsave(&riscom_lock, flags);
-
- if (tty_hung_up_p(filp))
- goto out;
-
bp = port_Board(port);
- if ((tty->count == 1) && (port->port.count != 1)) {
- printk(KERN_INFO "rc%d: rc_close: bad port count;"
- " tty->count is 1, port count is %d\n",
- board_No(bp), port->port.count);
- port->port.count = 1;
- }
- if (--port->port.count < 0) {
- printk(KERN_INFO "rc%d: rc_close: bad port count "
- "for tty%d: %d\n",
- board_No(bp), port_No(port), port->port.count);
- port->port.count = 0;
- }
- if (port->port.count)
- goto out;
- port->port.flags |= ASYNC_CLOSING;
- /*
- * Now we wait for the transmit buffer to clear; and we notify
- * the line discipline to only process XON/XOFF characters.
- */
- tty->closing = 1;
- if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, port->port.closing_wait);
+
+ if (tty_port_close_start(&port->port, tty, filp) == 0)
+ return;
+
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
* interrupt driver to stop checking the data ready bit in the
* line status register.
*/
+
+ spin_lock_irqsave(&riscom_lock, flags);
port->IER &= ~IER_RXD;
if (port->port.flags & ASYNC_INITIALIZED) {
port->IER &= ~IER_TXRDY;
@@ -1053,33 +955,24 @@ static void rc_close(struct tty_struct *tty, struct file *filp)
*/
timeout = jiffies + HZ;
while (port->IER & IER_TXEMPTY) {
+ spin_unlock_irqrestore(&riscom_lock, flags);
msleep_interruptible(jiffies_to_msecs(port->timeout));
+ spin_lock_irqsave(&riscom_lock, flags);
if (time_after(jiffies, timeout))
break;
}
}
rc_shutdown_port(tty, bp, port);
rc_flush_buffer(tty);
- tty_ldisc_flush(tty);
-
- tty->closing = 0;
- port->port.tty = NULL;
- if (port->port.blocked_open) {
- if (port->port.close_delay)
- msleep_interruptible(jiffies_to_msecs(port->port.close_delay));
- wake_up_interruptible(&port->port.open_wait);
- }
- port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&port->port.close_wait);
-
-out:
spin_unlock_irqrestore(&riscom_lock, flags);
+
+ tty_port_close_end(&port->port, tty);
}
static int rc_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
int c, total = 0;
unsigned long flags;
@@ -1122,7 +1015,7 @@ static int rc_write(struct tty_struct *tty,
static int rc_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
unsigned long flags;
int ret = 0;
@@ -1146,7 +1039,7 @@ out:
static void rc_flush_chars(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
unsigned long flags;
if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
@@ -1166,7 +1059,7 @@ static void rc_flush_chars(struct tty_struct *tty)
static int rc_write_room(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
int ret;
if (rc_paranoia_check(port, tty->name, "rc_write_room"))
@@ -1180,7 +1073,7 @@ static int rc_write_room(struct tty_struct *tty)
static int rc_chars_in_buffer(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
return 0;
@@ -1190,7 +1083,7 @@ static int rc_chars_in_buffer(struct tty_struct *tty)
static int rc_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned char status;
unsigned int result;
@@ -1220,7 +1113,7 @@ static int rc_tiocmget(struct tty_struct *tty, struct file *file)
static int rc_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
unsigned long flags;
struct riscom_board *bp;
@@ -1252,7 +1145,7 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
static int rc_send_break(struct tty_struct *tty, int length)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp = port_Board(port);
unsigned long flags;
@@ -1345,7 +1238,7 @@ static int rc_get_serial_info(struct riscom_port *port,
static int rc_ioctl(struct tty_struct *tty, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
int retval;
@@ -1371,7 +1264,7 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp,
static void rc_throttle(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned long flags;
@@ -1393,7 +1286,7 @@ static void rc_throttle(struct tty_struct *tty)
static void rc_unthrottle(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned long flags;
@@ -1415,7 +1308,7 @@ static void rc_unthrottle(struct tty_struct *tty)
static void rc_stop(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned long flags;
@@ -1433,7 +1326,7 @@ static void rc_stop(struct tty_struct *tty)
static void rc_start(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned long flags;
@@ -1454,8 +1347,9 @@ static void rc_start(struct tty_struct *tty)
static void rc_hangup(struct tty_struct *tty)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
+ unsigned long flags;
if (rc_paranoia_check(port, tty->name, "rc_hangup"))
return;
@@ -1463,16 +1357,18 @@ static void rc_hangup(struct tty_struct *tty)
bp = port_Board(port);
rc_shutdown_port(tty, bp, port);
+ spin_lock_irqsave(&port->port.lock, flags);
port->port.count = 0;
port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
port->port.tty = NULL;
wake_up_interruptible(&port->port.open_wait);
+ spin_unlock_irqrestore(&port->port.lock, flags);
}
static void rc_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
- struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+ struct riscom_port *port = tty->driver_data;
unsigned long flags;
if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
@@ -1510,6 +1406,11 @@ static const struct tty_operations riscom_ops = {
.break_ctl = rc_send_break,
};
+static const struct tty_port_operations riscom_port_ops = {
+ .carrier_raised = carrier_raised,
+};
+
+
static int __init rc_init_drivers(void)
{
int error;
@@ -1541,6 +1442,7 @@ static int __init rc_init_drivers(void)
memset(rc_port, 0, sizeof(rc_port));
for (i = 0; i < RC_NPORT * RC_NBOARD; i++) {
tty_port_init(&rc_port[i].port);
+ rc_port[i].port.ops = &riscom_port_ops;
rc_port[i].magic = RISCOM8_MAGIC;
}
return 0;
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 584d791e84a6..f59fc5cea067 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -135,6 +135,7 @@ static int rcktpt_type[NUM_BOARDS];
static int is_PCI[NUM_BOARDS];
static rocketModel_t rocketModel[NUM_BOARDS];
static int max_board;
+static const struct tty_port_operations rocket_port_ops;
/*
* The following arrays define the interrupt bits corresponding to each AIOP.
@@ -435,15 +436,15 @@ static void rp_do_transmit(struct r_port *info)
#endif
if (!info)
return;
- if (!info->port.tty) {
- printk(KERN_WARNING "rp: WARNING %s called with "
- "info->port.tty==NULL\n", __func__);
+ tty = tty_port_tty_get(&info->port);
+
+ if (tty == NULL) {
+ printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__);
clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
return;
}
spin_lock_irqsave(&info->slock, flags);
- tty = info->port.tty;
info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
/* Loop sending data to FIFO until done or FIFO full */
@@ -477,6 +478,7 @@ static void rp_do_transmit(struct r_port *info)
}
spin_unlock_irqrestore(&info->slock, flags);
+ tty_kref_put(tty);
#ifdef ROCKET_DEBUG_INTR
printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head,
@@ -498,18 +500,18 @@ static void rp_handle_port(struct r_port *info)
if (!info)
return;
- if ((info->flags & ROCKET_INITIALIZED) == 0) {
+ if ((info->port.flags & ASYNC_INITIALIZED) == 0) {
printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
"info->flags & NOT_INIT\n");
return;
}
- if (!info->port.tty) {
+ tty = tty_port_tty_get(&info->port);
+ if (!tty) {
printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
- "info->port.tty==NULL\n");
+ "tty==NULL\n");
return;
}
cp = &info->channel;
- tty = info->port.tty;
IntMask = sGetChanIntID(cp) & info->intmask;
#ifdef ROCKET_DEBUG_INTR
@@ -541,6 +543,7 @@ static void rp_handle_port(struct r_port *info)
printk(KERN_INFO "DSR change...\n");
}
#endif
+ tty_kref_put(tty);
}
/*
@@ -649,9 +652,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
info->board = board;
info->aiop = aiop;
info->chan = chan;
- info->port.closing_wait = 3000;
- info->port.close_delay = 50;
- init_waitqueue_head(&info->port.open_wait);
+ tty_port_init(&info->port);
+ info->port.ops = &rocket_port_ops;
init_completion(&info->close_wait);
info->flags &= ~ROCKET_MODE_MASK;
switch (pc104[board][line]) {
@@ -710,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
* Configures a rocketport port according to its termio settings. Called from
* user mode into the driver (exception handler). *info CD manipulation is spinlock protected.
*/
-static void configure_r_port(struct r_port *info,
+static void configure_r_port(struct tty_struct *tty, struct r_port *info,
struct ktermios *old_termios)
{
unsigned cflag;
@@ -718,7 +720,7 @@ static void configure_r_port(struct r_port *info,
unsigned rocketMode;
int bits, baud, divisor;
CHANNEL_t *cp;
- struct ktermios *t = info->port.tty->termios;
+ struct ktermios *t = tty->termios;
cp = &info->channel;
cflag = t->c_cflag;
@@ -751,7 +753,7 @@ static void configure_r_port(struct r_port *info,
}
/* baud rate */
- baud = tty_get_baud_rate(info->port.tty);
+ baud = tty_get_baud_rate(tty);
if (!baud)
baud = 9600;
divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
@@ -769,7 +771,7 @@ static void configure_r_port(struct r_port *info,
sSetBaud(cp, divisor);
/* FIXME: Should really back compute a baud rate from the divisor */
- tty_encode_baud_rate(info->port.tty, baud, baud);
+ tty_encode_baud_rate(tty, baud, baud);
if (cflag & CRTSCTS) {
info->intmask |= DELTA_CTS;
@@ -794,15 +796,15 @@ static void configure_r_port(struct r_port *info,
* Handle software flow control in the board
*/
#ifdef ROCKET_SOFT_FLOW
- if (I_IXON(info->port.tty)) {
+ if (I_IXON(tty)) {
sEnTxSoftFlowCtl(cp);
- if (I_IXANY(info->port.tty)) {
+ if (I_IXANY(tty)) {
sEnIXANY(cp);
} else {
sDisIXANY(cp);
}
- sSetTxXONChar(cp, START_CHAR(info->port.tty));
- sSetTxXOFFChar(cp, STOP_CHAR(info->port.tty));
+ sSetTxXONChar(cp, START_CHAR(tty));
+ sSetTxXOFFChar(cp, STOP_CHAR(tty));
} else {
sDisTxSoftFlowCtl(cp);
sDisIXANY(cp);
@@ -814,24 +816,24 @@ static void configure_r_port(struct r_port *info,
* Set up ignore/read mask words
*/
info->read_status_mask = STMRCVROVRH | 0xFF;
- if (I_INPCK(info->port.tty))
+ if (I_INPCK(tty))
info->read_status_mask |= STMFRAMEH | STMPARITYH;
- if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
+ if (I_BRKINT(tty) || I_PARMRK(tty))
info->read_status_mask |= STMBREAKH;
/*
* Characters to ignore
*/
info->ignore_status_mask = 0;
- if (I_IGNPAR(info->port.tty))
+ if (I_IGNPAR(tty))
info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
- if (I_IGNBRK(info->port.tty)) {
+ if (I_IGNBRK(tty)) {
info->ignore_status_mask |= STMBREAKH;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too. (For real raw support).
*/
- if (I_IGNPAR(info->port.tty))
+ if (I_IGNPAR(tty))
info->ignore_status_mask |= STMRCVROVRH;
}
@@ -864,106 +866,17 @@ static void configure_r_port(struct r_port *info,
}
}
-/* info->port.count is considered critical, protected by spinlocks. */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
- struct r_port *info)
+static int carrier_raised(struct tty_port *port)
{
- DECLARE_WAITQUEUE(wait, current);
- int retval;
- int do_clocal = 0, extra_count = 0;
- unsigned long flags;
-
- /*
- * If the device is in the middle of being closed, then block
- * until it's done, and then try again.
- */
- if (tty_hung_up_p(filp))
- return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
- if (info->flags & ROCKET_CLOSING) {
- if (wait_for_completion_interruptible(&info->close_wait))
- return -ERESTARTSYS;
- return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
- }
-
- /*
- * If non-blocking mode is set, or the port is not enabled,
- * then make the check up front and then exit.
- */
- if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
- info->flags |= ROCKET_NORMAL_ACTIVE;
- return 0;
- }
- if (tty->termios->c_cflag & CLOCAL)
- do_clocal = 1;
-
- /*
- * Block waiting for the carrier detect and the line to become free. While we are in
- * this loop, info->port.count is dropped by one, so that rp_close() knows when to free things.
- * We restore it upon exit, either normal or abnormal.
- */
- retval = 0;
- add_wait_queue(&info->port.open_wait, &wait);
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "block_til_ready before block: ttyR%d, count = %d\n", info->line, info->port.count);
-#endif
- spin_lock_irqsave(&info->slock, flags);
-
-#ifdef ROCKET_DISABLE_SIMUSAGE
- info->flags |= ROCKET_NORMAL_ACTIVE;
-#else
- if (!tty_hung_up_p(filp)) {
- extra_count = 1;
- info->port.count--;
- }
-#endif
- info->port.blocked_open++;
-
- spin_unlock_irqrestore(&info->slock, flags);
-
- while (1) {
- if (tty->termios->c_cflag & CBAUD) {
- sSetDTR(&info->channel);
- sSetRTS(&info->channel);
- }
- set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(info->flags & ROCKET_INITIALIZED)) {
- if (info->flags & ROCKET_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
- break;
- }
- if (!(info->flags & ROCKET_CLOSING) && (do_clocal || (sGetChanStatusLo(&info->channel) & CD_ACT)))
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "block_til_ready blocking: ttyR%d, count = %d, flags=0x%0x\n",
- info->line, info->port.count, info->flags);
-#endif
- schedule(); /* Don't hold spinlock here, will hang PC */
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->port.open_wait, &wait);
-
- spin_lock_irqsave(&info->slock, flags);
-
- if (extra_count)
- info->port.count++;
- info->port.blocked_open--;
-
- spin_unlock_irqrestore(&info->slock, flags);
+ struct r_port *info = container_of(port, struct r_port, port);
+ return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
+}
-#ifdef ROCKET_DEBUG_OPEN
- printk(KERN_INFO "block_til_ready after blocking: ttyR%d, count = %d\n",
- info->line, info->port.count);
-#endif
- if (retval)
- return retval;
- info->flags |= ROCKET_NORMAL_ACTIVE;
- return 0;
+static void raise_dtr_rts(struct tty_port *port)
+{
+ struct r_port *info = container_of(port, struct r_port, port);
+ sSetDTR(&info->channel);
+ sSetRTS(&info->channel);
}
/*
@@ -973,24 +886,26 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
static int rp_open(struct tty_struct *tty, struct file *filp)
{
struct r_port *info;
+ struct tty_port *port;
int line = 0, retval;
CHANNEL_t *cp;
unsigned long page;
line = tty->index;
- if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL))
+ if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL))
return -ENXIO;
-
+ port = &info->port;
+
page = __get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
- if (info->flags & ROCKET_CLOSING) {
+ if (port->flags & ASYNC_CLOSING) {
retval = wait_for_completion_interruptible(&info->close_wait);
free_page(page);
if (retval)
return retval;
- return ((info->flags & ROCKET_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
+ return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
}
/*
@@ -1002,9 +917,9 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
info->xmit_buf = (unsigned char *) page;
tty->driver_data = info;
- info->port.tty = tty;
+ tty_port_tty_set(port, tty);
- if (info->port.count++ == 0) {
+ if (port->count++ == 0) {
atomic_inc(&rp_num_ports_open);
#ifdef ROCKET_DEBUG_OPEN
@@ -1019,7 +934,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
/*
* Info->count is now 1; so it's safe to sleep now.
*/
- if ((info->flags & ROCKET_INITIALIZED) == 0) {
+ if (!test_bit(ASYNC_INITIALIZED, &port->flags)) {
cp = &info->channel;
sSetRxTrigger(cp, TRIG_1);
if (sGetChanStatus(cp) & CD_ACT)
@@ -1043,21 +958,21 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
sEnRxFIFO(cp);
sEnTransmit(cp);
- info->flags |= ROCKET_INITIALIZED;
+ set_bit(ASYNC_INITIALIZED, &info->port.flags);
/*
* Set up the tty->alt_speed kludge
*/
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
- info->port.tty->alt_speed = 57600;
+ tty->alt_speed = 57600;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
- info->port.tty->alt_speed = 115200;
+ tty->alt_speed = 115200;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
- info->port.tty->alt_speed = 230400;
+ tty->alt_speed = 230400;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
- info->port.tty->alt_speed = 460800;
+ tty->alt_speed = 460800;
- configure_r_port(info, NULL);
+ configure_r_port(tty, info, NULL);
if (tty->termios->c_cflag & CBAUD) {
sSetDTR(cp);
sSetRTS(cp);
@@ -1066,7 +981,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
/* Starts (or resets) the maint polling loop */
mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
- retval = block_til_ready(tty, filp, info);
+ retval = tty_port_block_til_ready(port, tty, filp);
if (retval) {
#ifdef ROCKET_DEBUG_OPEN
printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
@@ -1081,8 +996,8 @@ static int rp_open(struct tty_struct *tty, struct file *filp)
*/
static void rp_close(struct tty_struct *tty, struct file *filp)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
- unsigned long flags;
+ struct r_port *info = tty->driver_data;
+ struct tty_port *port = &info->port;
int timeout;
CHANNEL_t *cp;
@@ -1093,53 +1008,10 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count);
#endif
- if (tty_hung_up_p(filp))
- return;
- spin_lock_irqsave(&info->slock, flags);
-
- if ((tty->count == 1) && (info->port.count != 1)) {
- /*
- * Uh, oh. tty->count is 1, which means that the tty
- * structure will be freed. Info->count should always
- * be one in these conditions. If it's greater than
- * one, we've got real problems, since it means the
- * serial port won't be shutdown.
- */
- printk(KERN_WARNING "rp_close: bad serial port count; "
- "tty->count is 1, info->port.count is %d\n", info->port.count);
- info->port.count = 1;
- }
- if (--info->port.count < 0) {
- printk(KERN_WARNING "rp_close: bad serial port count for "
- "ttyR%d: %d\n", info->line, info->port.count);
- info->port.count = 0;
- }
- if (info->port.count) {
- spin_unlock_irqrestore(&info->slock, flags);
+ if (tty_port_close_start(port, tty, filp) == 0)
return;
- }
- info->flags |= ROCKET_CLOSING;
- spin_unlock_irqrestore(&info->slock, flags);
cp = &info->channel;
-
- /*
- * Notify the line discpline to only process XON/XOFF characters
- */
- tty->closing = 1;
-
- /*
- * If transmission was throttled by the application request,
- * just flush the xmit buffer.
- */
- if (tty->flow_stopped)
- rp_flush_buffer(tty);
-
- /*
- * Wait for the transmit buffer to clear
- */
- if (info->port.closing_wait != ROCKET_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, info->port.closing_wait);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
@@ -1168,19 +1040,24 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
- if (info->port.blocked_open) {
- if (info->port.close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->port.close_delay));
+ /* We can't yet use tty_port_close_end as the buffer handling in this
+ driver is a bit different to the usual */
+
+ if (port->blocked_open) {
+ if (port->close_delay) {
+ msleep_interruptible(jiffies_to_msecs(port->close_delay));
}
- wake_up_interruptible(&info->port.open_wait);
+ wake_up_interruptible(&port->open_wait);
} else {
if (info->xmit_buf) {
free_page((unsigned long) info->xmit_buf);
info->xmit_buf = NULL;
}
}
- info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING | ROCKET_NORMAL_ACTIVE);
+ info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE);
tty->closing = 0;
+ tty_port_tty_set(port, NULL);
+ wake_up_interruptible(&port->close_wait);
complete_all(&info->close_wait);
atomic_dec(&rp_num_ports_open);
@@ -1195,7 +1072,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
static void rp_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
unsigned cflag;
@@ -1213,7 +1090,7 @@ static void rp_set_termios(struct tty_struct *tty,
/* Or CMSPAR */
tty->termios->c_cflag &= ~CMSPAR;
- configure_r_port(info, old_termios);
+ configure_r_port(tty, info, old_termios);
cp = &info->channel;
@@ -1238,7 +1115,7 @@ static void rp_set_termios(struct tty_struct *tty,
static int rp_break(struct tty_struct *tty, int break_state)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
unsigned long flags;
if (rocket_paranoia_check(info, "rp_break"))
@@ -1284,7 +1161,7 @@ static int sGetChanRI(CHANNEL_T * ChP)
*/
static int rp_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct r_port *info = (struct r_port *)tty->driver_data;
+ struct r_port *info = tty->driver_data;
unsigned int control, result, ChanStatus;
ChanStatus = sGetChanStatusLo(&info->channel);
@@ -1305,7 +1182,7 @@ static int rp_tiocmget(struct tty_struct *tty, struct file *file)
static int rp_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct r_port *info = (struct r_port *)tty->driver_data;
+ struct r_port *info = tty->driver_data;
if (set & TIOCM_RTS)
info->channel.TxControl[3] |= SET_RTS;
@@ -1338,7 +1215,8 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
return 0;
}
-static int set_config(struct r_port *info, struct rocket_config __user *new_info)
+static int set_config(struct tty_struct *tty, struct r_port *info,
+ struct rocket_config __user *new_info)
{
struct rocket_config new_serial;
@@ -1350,7 +1228,7 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info
if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
return -EPERM;
info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
- configure_r_port(info, NULL);
+ configure_r_port(tty, info, NULL);
return 0;
}
@@ -1359,15 +1237,15 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info
info->port.closing_wait = new_serial.closing_wait;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
- info->port.tty->alt_speed = 57600;
+ tty->alt_speed = 57600;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
- info->port.tty->alt_speed = 115200;
+ tty->alt_speed = 115200;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
- info->port.tty->alt_speed = 230400;
+ tty->alt_speed = 230400;
if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
- info->port.tty->alt_speed = 460800;
+ tty->alt_speed = 460800;
- configure_r_port(info, NULL);
+ configure_r_port(tty, info, NULL);
return 0;
}
@@ -1434,7 +1312,7 @@ static int get_version(struct r_port *info, struct rocket_version __user *retver
static int rp_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
void __user *argp = (void __user *)arg;
int ret = 0;
@@ -1452,7 +1330,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
ret = get_config(info, argp);
break;
case RCKP_SET_CONFIG:
- ret = set_config(info, argp);
+ ret = set_config(tty, info, argp);
break;
case RCKP_GET_PORTS:
ret = get_ports(info, argp);
@@ -1472,7 +1350,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
static void rp_send_xchar(struct tty_struct *tty, char ch)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
if (rocket_paranoia_check(info, "rp_send_xchar"))
@@ -1487,7 +1365,7 @@ static void rp_send_xchar(struct tty_struct *tty, char ch)
static void rp_throttle(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
#ifdef ROCKET_DEBUG_THROTTLE
@@ -1507,7 +1385,7 @@ static void rp_throttle(struct tty_struct *tty)
static void rp_unthrottle(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
#ifdef ROCKET_DEBUG_THROTTLE
printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
@@ -1534,7 +1412,7 @@ static void rp_unthrottle(struct tty_struct *tty)
*/
static void rp_stop(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
#ifdef ROCKET_DEBUG_FLOW
printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
@@ -1550,7 +1428,7 @@ static void rp_stop(struct tty_struct *tty)
static void rp_start(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
#ifdef ROCKET_DEBUG_FLOW
printk(KERN_INFO "start %s: %d %d....\n", tty->name,
@@ -1570,7 +1448,7 @@ static void rp_start(struct tty_struct *tty)
*/
static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
unsigned long orig_jiffies;
int check_time, exit_time;
@@ -1627,7 +1505,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
static void rp_hangup(struct tty_struct *tty)
{
CHANNEL_t *cp;
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
if (rocket_paranoia_check(info, "rp_hangup"))
return;
@@ -1636,15 +1514,13 @@ static void rp_hangup(struct tty_struct *tty)
printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
#endif
rp_flush_buffer(tty);
- if (info->flags & ROCKET_CLOSING)
+ if (info->port.flags & ASYNC_CLOSING)
return;
if (info->port.count)
atomic_dec(&rp_num_ports_open);
clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
- info->port.count = 0;
- info->flags &= ~ROCKET_NORMAL_ACTIVE;
- info->port.tty = NULL;
+ tty_port_hangup(&info->port);
cp = &info->channel;
sDisRxFIFO(cp);
@@ -1653,7 +1529,7 @@ static void rp_hangup(struct tty_struct *tty)
sDisCTSFlowCtl(cp);
sDisTxSoftFlowCtl(cp);
sClrTxXOFF(cp);
- info->flags &= ~ROCKET_INITIALIZED;
+ info->port.flags &= ~ASYNC_INITIALIZED;
wake_up_interruptible(&info->port.open_wait);
}
@@ -1667,7 +1543,7 @@ static void rp_hangup(struct tty_struct *tty)
*/
static int rp_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
unsigned long flags;
@@ -1714,7 +1590,7 @@ static int rp_put_char(struct tty_struct *tty, unsigned char ch)
static int rp_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
const unsigned char *b;
int c, retval = 0;
@@ -1764,7 +1640,8 @@ static int rp_write(struct tty_struct *tty,
/* Write remaining data into the port's xmit_buf */
while (1) {
- if (!info->port.tty) /* Seemingly obligatory check... */
+ /* Hung up ? */
+ if (!test_bit(ASYNC_NORMAL_ACTIVE, &info->port.flags))
goto end;
c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
c = min(c, XMIT_BUF_SIZE - info->xmit_head);
@@ -1806,7 +1683,7 @@ end:
*/
static int rp_write_room(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
int ret;
if (rocket_paranoia_check(info, "rp_write_room"))
@@ -1827,7 +1704,7 @@ static int rp_write_room(struct tty_struct *tty)
*/
static int rp_chars_in_buffer(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
@@ -1848,7 +1725,7 @@ static int rp_chars_in_buffer(struct tty_struct *tty)
*/
static void rp_flush_buffer(struct tty_struct *tty)
{
- struct r_port *info = (struct r_port *) tty->driver_data;
+ struct r_port *info = tty->driver_data;
CHANNEL_t *cp;
unsigned long flags;
@@ -2371,6 +2248,11 @@ static const struct tty_operations rocket_ops = {
.tiocmset = rp_tiocmset,
};
+static const struct tty_port_operations rocket_port_ops = {
+ .carrier_raised = carrier_raised,
+ .raise_dtr_rts = raise_dtr_rts,
+};
+
/*
* The module "startup" routine; it's run when the module is loaded.
*/
diff --git a/drivers/char/rocket.h b/drivers/char/rocket.h
index a8b09195ebba..ec863f35f1a9 100644
--- a/drivers/char/rocket.h
+++ b/drivers/char/rocket.h
@@ -39,7 +39,7 @@ struct rocket_version {
/*
* Rocketport flags
*/
-#define ROCKET_CALLOUT_NOHUP 0x00000001
+/*#define ROCKET_CALLOUT_NOHUP 0x00000001 */
#define ROCKET_FORCE_CD 0x00000002
#define ROCKET_HUP_NOTIFY 0x00000004
#define ROCKET_SPLIT_TERMIOS 0x00000008
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 21f3ff53ba32..67e0f1e778a2 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1162,11 +1162,6 @@ struct r_port {
/* number of characters left in xmit buffer before we ask for more */
#define WAKEUP_CHARS 256
-/* Internal flags used only by the rocketport driver */
-#define ROCKET_INITIALIZED 0x80000000 /* Port is active */
-#define ROCKET_CLOSING 0x40000000 /* Serial port is closing */
-#define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */
-
/*
* Assigned major numbers for the Comtrol Rocketport
*/
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 20d6efb6324e..e0d0f8b2696b 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -48,9 +48,10 @@
* CONFIG_HPET_EMULATE_RTC
* 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly.
* 1.12ac Alan Cox: Allow read access to the day of week register
+ * 1.12b David John: Remove calls to the BKL.
*/
-#define RTC_VERSION "1.12ac"
+#define RTC_VERSION "1.12b"
/*
* Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
@@ -73,7 +74,6 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <linux/sysctl.h>
#include <linux/wait.h>
#include <linux/bcd.h>
@@ -182,8 +182,8 @@ static int rtc_proc_open(struct inode *inode, struct file *file);
/*
* rtc_status is never changed by rtc_interrupt, and ioctl/open/close is
- * protected by the big kernel lock. However, ioctl can still disable the timer
- * in rtc_status and then with del_timer after the interrupt has read
+ * protected by the spin lock rtc_lock. However, ioctl can still disable the
+ * timer in rtc_status and then with del_timer after the interrupt has read
* rtc_status but before mod_timer is called, which would then reenable the
* timer (but you would need to have an awful timing before you'd trip on it)
*/
@@ -720,9 +720,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
ret = rtc_do_ioctl(cmd, arg, 0);
- unlock_kernel();
return ret;
}
@@ -731,12 +729,8 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
* Also clear the previous interrupt data on an open, and clean
* up things on a close.
*/
-
-/* We use rtc_lock to protect against concurrent opens. So the BKL is not
- * needed here. Or anywhere else in this driver. */
static int rtc_open(struct inode *inode, struct file *file)
{
- lock_kernel();
spin_lock_irq(&rtc_lock);
if (rtc_status & RTC_IS_OPEN)
@@ -746,12 +740,10 @@ static int rtc_open(struct inode *inode, struct file *file)
rtc_irq_data = 0;
spin_unlock_irq(&rtc_lock);
- unlock_kernel();
return 0;
out_busy:
spin_unlock_irq(&rtc_lock);
- unlock_kernel();
return -EBUSY;
}
@@ -800,7 +792,6 @@ no_irq:
}
#ifdef RTC_IRQ
-/* Called without the kernel lock - fine */
static unsigned int rtc_poll(struct file *file, poll_table *wait)
{
unsigned long l;
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 2978a49a172b..cb8ca5698963 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -268,7 +268,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
/* Allocate a new buffer before freeing the old one ... */
multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */
- bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL);
+ bp = kmalloc(((sel_end-sel_start)/2+1)*multiplier, GFP_KERNEL);
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
@@ -306,7 +306,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
*/
int paste_selection(struct tty_struct *tty)
{
- struct vc_data *vc = (struct vc_data *)tty->driver_data;
+ struct vc_data *vc = tty->driver_data;
int pasted = 0;
unsigned int count;
struct tty_ldisc *ld;
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 7b0c35207d9b..33a2b531802e 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -122,7 +122,7 @@ static void a2232_disable_tx_interrupts(void *ptr);
static void a2232_enable_tx_interrupts(void *ptr);
static void a2232_disable_rx_interrupts(void *ptr);
static void a2232_enable_rx_interrupts(void *ptr);
-static int a2232_get_CD(void *ptr);
+static int a2232_carrier_raised(struct tty_port *port);
static void a2232_shutdown_port(void *ptr);
static int a2232_set_real_termios(void *ptr);
static int a2232_chars_in_buffer(void *ptr);
@@ -148,7 +148,6 @@ static struct real_driver a2232_real_driver = {
a2232_enable_tx_interrupts,
a2232_disable_rx_interrupts,
a2232_enable_rx_interrupts,
- a2232_get_CD,
a2232_shutdown_port,
a2232_set_real_termios,
a2232_chars_in_buffer,
@@ -260,9 +259,10 @@ static void a2232_enable_rx_interrupts(void *ptr)
port->disable_rx = 0;
}
-static int a2232_get_CD(void *ptr)
+static int a2232_carrier_raised(struct tty_port *port)
{
- return ((struct a2232_port *) ptr)->cd_status;
+ struct a2232_port *ap = container_of(port, struct a2232_port, gs.port);
+ return ap->cd_status;
}
static void a2232_shutdown_port(void *ptr)
@@ -460,14 +460,14 @@ static void a2232_throttle(struct tty_struct *tty)
if switched on. So the only thing we can do at this
layer here is not taking any characters out of the
A2232 buffer any more. */
- struct a2232_port *port = (struct a2232_port *) tty->driver_data;
+ struct a2232_port *port = tty->driver_data;
port->throttle_input = -1;
}
static void a2232_unthrottle(struct tty_struct *tty)
{
/* Unthrottle: dual to "throttle()" above. */
- struct a2232_port *port = (struct a2232_port *) tty->driver_data;
+ struct a2232_port *port = tty->driver_data;
port->throttle_input = 0;
}
@@ -638,6 +638,10 @@ int ch, err, n, p;
return IRQ_HANDLED;
}
+static const struct tty_port_operations a2232_port_ops = {
+ .carrier_raised = a2232_carrier_raised,
+};
+
static void a2232_init_portstructs(void)
{
struct a2232_port *port;
@@ -645,6 +649,8 @@ static void a2232_init_portstructs(void)
for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {
port = a2232_ports + i;
+ tty_port_init(&port->gs.port);
+ port->gs.port.ops = &a2232_port_ops;
port->which_a2232 = i/NUMLINES;
port->which_port_on_a2232 = i%NUMLINES;
port->disable_rx = port->throttle_input = port->cd_status = 0;
@@ -652,11 +658,6 @@ static void a2232_init_portstructs(void)
port->gs.close_delay = HZ/2;
port->gs.closing_wait = 30 * HZ;
port->gs.rd = &a2232_real_driver;
-#ifdef NEW_WRITE_LOCKING
- mutex_init(&(port->gs.port_write_mutex));
-#endif
- init_waitqueue_head(&port->gs.port.open_wait);
- init_waitqueue_head(&port->gs.port.close_wait);
}
}
@@ -717,6 +718,7 @@ static int __init a2232board_init(void)
u_char *from;
volatile u_char *to;
volatile struct a2232memory *mem;
+ int error, i;
#ifdef CONFIG_SMP
return -ENODEV; /* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */
@@ -796,8 +798,15 @@ static int __init a2232board_init(void)
*/
if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?
- request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0, "A2232 serial VBL", a2232_driver_ID);
- return 0;
+ error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0,
+ "A2232 serial VBL", a2232_driver_ID);
+ if (error) {
+ for (i = 0; i < nr_a2232; i++)
+ zorro_release_device(zd_a2232[i]);
+ tty_unregister_driver(a2232_driver);
+ put_tty_driver(a2232_driver);
+ }
+ return error;
}
static void __exit a2232board_exit(void)
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index a8f15e6be594..f1f24f0ee26f 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -315,7 +315,7 @@ u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
static void cy_stop(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
int channel;
unsigned long flags;
@@ -337,7 +337,7 @@ static void cy_stop(struct tty_struct *tty)
static void cy_start(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
int channel;
unsigned long flags;
@@ -1062,7 +1062,7 @@ static void config_setup(struct cyclades_port *info)
static int cy_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_IO
@@ -1090,7 +1090,7 @@ static int cy_put_char(struct tty_struct *tty, unsigned char ch)
static void cy_flush_chars(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
unsigned long flags;
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
int channel;
@@ -1122,7 +1122,7 @@ static void cy_flush_chars(struct tty_struct *tty)
*/
static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
unsigned long flags;
int c, total = 0;
@@ -1166,7 +1166,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
static int cy_write_room(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
int ret;
#ifdef SERIAL_DEBUG_IO
@@ -1183,7 +1183,7 @@ static int cy_write_room(struct tty_struct *tty)
static int cy_chars_in_buffer(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
#ifdef SERIAL_DEBUG_IO
printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt); /* */
@@ -1197,7 +1197,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
static void cy_flush_buffer(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
unsigned long flags;
#ifdef SERIAL_DEBUG_IO
@@ -1218,7 +1218,7 @@ static void cy_flush_buffer(struct tty_struct *tty)
*/
static void cy_throttle(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
unsigned long flags;
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
int channel;
@@ -1250,7 +1250,7 @@ static void cy_throttle(struct tty_struct *tty)
static void cy_unthrottle(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
unsigned long flags;
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
int channel;
@@ -1345,7 +1345,7 @@ check_and_exit:
static int cy_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
int channel;
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
unsigned long flags;
@@ -1369,7 +1369,7 @@ static int
cy_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
int channel;
volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
unsigned long flags;
@@ -1532,7 +1532,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
unsigned long val;
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
int ret_val = 0;
void __user *argp = (void __user *)arg;
@@ -1607,7 +1607,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
#ifdef SERIAL_DEBUG_OTHER
printk("cy_set_termios %s\n", tty->name);
@@ -1631,7 +1631,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
static void cy_close(struct tty_struct *tty, struct file *filp)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
/* CP('C'); */
#ifdef SERIAL_DEBUG_OTHER
@@ -1698,7 +1698,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
*/
void cy_hangup(struct tty_struct *tty)
{
- struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
+ struct cyclades_port *info = tty->driver_data;
#ifdef SERIAL_DEBUG_OTHER
printk("cy_hangup %s\n", tty->name); /* */
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index a16b94f12eb2..3c67c3d83de9 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1450,7 +1450,7 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
static void sx_flush_buffer(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
unsigned long flags;
struct specialix_board *bp;
@@ -1472,7 +1472,7 @@ static void sx_flush_buffer(struct tty_struct *tty)
static void sx_close(struct tty_struct *tty, struct file *filp)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
unsigned long timeout;
@@ -1585,7 +1585,7 @@ static void sx_close(struct tty_struct *tty, struct file *filp)
static int sx_write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
int c, total = 0;
unsigned long flags;
@@ -1637,7 +1637,7 @@ static int sx_write(struct tty_struct *tty,
static int sx_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
unsigned long flags;
struct specialix_board *bp;
@@ -1676,7 +1676,7 @@ static int sx_put_char(struct tty_struct *tty, unsigned char ch)
static void sx_flush_chars(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
unsigned long flags;
struct specialix_board *bp = port_Board(port);
@@ -1703,7 +1703,7 @@ static void sx_flush_chars(struct tty_struct *tty)
static int sx_write_room(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
int ret;
func_enter();
@@ -1724,7 +1724,7 @@ static int sx_write_room(struct tty_struct *tty)
static int sx_chars_in_buffer(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
func_enter();
@@ -1738,7 +1738,7 @@ static int sx_chars_in_buffer(struct tty_struct *tty)
static int sx_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
unsigned char status;
unsigned int result;
@@ -1780,7 +1780,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
static int sx_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
unsigned long flags;
struct specialix_board *bp;
@@ -1820,7 +1820,7 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
static int sx_send_break(struct tty_struct *tty, int length)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp = port_Board(port);
unsigned long flags;
@@ -1931,7 +1931,7 @@ static int sx_get_serial_info(struct specialix_port *port,
static int sx_ioctl(struct tty_struct *tty, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
func_enter();
@@ -1959,7 +1959,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
static void sx_throttle(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
@@ -2004,7 +2004,7 @@ static void sx_throttle(struct tty_struct *tty)
static void sx_unthrottle(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
@@ -2045,7 +2045,7 @@ static void sx_unthrottle(struct tty_struct *tty)
static void sx_stop(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
@@ -2072,7 +2072,7 @@ static void sx_stop(struct tty_struct *tty)
static void sx_start(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
@@ -2100,7 +2100,7 @@ static void sx_start(struct tty_struct *tty)
static void sx_hangup(struct tty_struct *tty)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
struct specialix_board *bp;
unsigned long flags;
@@ -2135,7 +2135,7 @@ static void sx_hangup(struct tty_struct *tty)
static void sx_set_termios(struct tty_struct *tty,
struct ktermios *old_termios)
{
- struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+ struct specialix_port *port = tty->driver_data;
unsigned long flags;
struct specialix_board *bp;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 963b03fb29e5..e1e0dd89ac9a 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -130,6 +130,8 @@ static char stl_unwanted[SC26198_RXFIFOSIZE];
static DEFINE_MUTEX(stl_brdslock);
static struct stlbrd *stl_brds[STL_MAXBRDS];
+static const struct tty_port_operations stl_port_ops;
+
/*
* Per board state flags. Used with the state field of the board struct.
* Not really much here!
@@ -407,7 +409,6 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
static int stl_brdinit(struct stlbrd *brdp);
static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
-static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp);
/*
* CD1400 uart specific handling functions.
@@ -703,8 +704,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
{
struct stlport *portp;
struct stlbrd *brdp;
+ struct tty_port *port;
unsigned int minordev, brdnr, panelnr;
- int portnr, rc;
+ int portnr;
pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
@@ -715,6 +717,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
brdp = stl_brds[brdnr];
if (brdp == NULL)
return -ENODEV;
+
minordev = MINOR2PORT(minordev);
for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
if (brdp->panels[panelnr] == NULL)
@@ -731,16 +734,17 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
portp = brdp->panels[panelnr]->ports[portnr];
if (portp == NULL)
return -ENODEV;
+ port = &portp->port;
/*
* On the first open of the device setup the port hardware, and
* initialize the per port data structure.
*/
- tty_port_tty_set(&portp->port, tty);
+ tty_port_tty_set(port, tty);
tty->driver_data = portp;
- portp->port.count++;
+ port->count++;
- if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
+ if ((port->flags & ASYNC_INITIALIZED) == 0) {
if (!portp->tx.buf) {
portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
if (!portp->tx.buf)
@@ -754,91 +758,24 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
stl_enablerxtx(portp, 1, 1);
stl_startrxtx(portp, 1, 0);
clear_bit(TTY_IO_ERROR, &tty->flags);
- portp->port.flags |= ASYNC_INITIALIZED;
- }
-
-/*
- * Check if this port is in the middle of closing. If so then wait
- * until it is closed then return error status, based on flag settings.
- * The sleep here does not need interrupt protection since the wakeup
- * for it is done with the same context.
- */
- if (portp->port.flags & ASYNC_CLOSING) {
- interruptible_sleep_on(&portp->port.close_wait);
- if (portp->port.flags & ASYNC_HUP_NOTIFY)
- return -EAGAIN;
- return -ERESTARTSYS;
+ port->flags |= ASYNC_INITIALIZED;
}
-
-/*
- * Based on type of open being done check if it can overlap with any
- * previous opens still in effect. If we are a normal serial device
- * then also we might have to wait for carrier.
- */
- if (!(filp->f_flags & O_NONBLOCK))
- if ((rc = stl_waitcarrier(tty, portp, filp)) != 0)
- return rc;
-
- portp->port.flags |= ASYNC_NORMAL_ACTIVE;
-
- return 0;
+ return tty_port_block_til_ready(port, tty, filp);
}
/*****************************************************************************/
-/*
- * Possibly need to wait for carrier (DCD signal) to come high. Say
- * maybe because if we are clocal then we don't need to wait...
- */
-
-static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp,
- struct file *filp)
+static int stl_carrier_raised(struct tty_port *port)
{
- unsigned long flags;
- int rc, doclocal;
-
- pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
-
- rc = 0;
- doclocal = 0;
-
- spin_lock_irqsave(&stallion_lock, flags);
-
- if (tty->termios->c_cflag & CLOCAL)
- doclocal++;
-
- portp->openwaitcnt++;
- if (! tty_hung_up_p(filp))
- portp->port.count--;
-
- for (;;) {
- /* Takes brd_lock internally */
- stl_setsignals(portp, 1, 1);
- if (tty_hung_up_p(filp) ||
- ((portp->port.flags & ASYNC_INITIALIZED) == 0)) {
- if (portp->port.flags & ASYNC_HUP_NOTIFY)
- rc = -EBUSY;
- else
- rc = -ERESTARTSYS;
- break;
- }
- if (((portp->port.flags & ASYNC_CLOSING) == 0) &&
- (doclocal || (portp->sigs & TIOCM_CD)))
- break;
- if (signal_pending(current)) {
- rc = -ERESTARTSYS;
- break;
- }
- /* FIXME */
- interruptible_sleep_on(&portp->port.open_wait);
- }
-
- if (! tty_hung_up_p(filp))
- portp->port.count++;
- portp->openwaitcnt--;
- spin_unlock_irqrestore(&stallion_lock, flags);
+ struct stlport *portp = container_of(port, struct stlport, port);
+ return (portp->sigs & TIOCM_CD) ? 1 : 0;
+}
- return rc;
+static void stl_raise_dtr_rts(struct tty_port *port)
+{
+ struct stlport *portp = container_of(port, struct stlport, port);
+ /* Takes brd_lock internally */
+ stl_setsignals(portp, 1, 1);
}
/*****************************************************************************/
@@ -890,47 +827,29 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
static void stl_close(struct tty_struct *tty, struct file *filp)
{
struct stlport *portp;
+ struct tty_port *port;
unsigned long flags;
pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
portp = tty->driver_data;
- if (portp == NULL)
- return;
+ BUG_ON(portp == NULL);
- spin_lock_irqsave(&stallion_lock, flags);
- if (tty_hung_up_p(filp)) {
- spin_unlock_irqrestore(&stallion_lock, flags);
- return;
- }
- if ((tty->count == 1) && (portp->port.count != 1))
- portp->port.count = 1;
- if (portp->port.count-- > 1) {
- spin_unlock_irqrestore(&stallion_lock, flags);
- return;
- }
-
- portp->port.count = 0;
- portp->port.flags |= ASYNC_CLOSING;
+ port = &portp->port;
+ if (tty_port_close_start(port, tty, filp) == 0)
+ return;
/*
* May want to wait for any data to drain before closing. The BUSY
* flag keeps track of whether we are still sending or not - it is
* very accurate for the cd1400, not quite so for the sc26198.
* (The sc26198 has no "end-of-data" interrupt only empty FIFO)
*/
- tty->closing = 1;
-
- spin_unlock_irqrestore(&stallion_lock, flags);
-
- if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
- tty_wait_until_sent(tty, portp->closing_wait);
stl_waituntilsent(tty, (HZ / 2));
-
- spin_lock_irqsave(&stallion_lock, flags);
+ spin_lock_irqsave(&port->lock, flags);
portp->port.flags &= ~ASYNC_INITIALIZED;
- spin_unlock_irqrestore(&stallion_lock, flags);
+ spin_unlock_irqrestore(&port->lock, flags);
stl_disableintrs(portp);
if (tty->termios->c_cflag & HUPCL)
@@ -944,20 +863,9 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
portp->tx.head = NULL;
portp->tx.tail = NULL;
}
- set_bit(TTY_IO_ERROR, &tty->flags);
- tty_ldisc_flush(tty);
- tty->closing = 0;
- tty_port_tty_set(&portp->port, NULL);
-
- if (portp->openwaitcnt) {
- if (portp->close_delay)
- msleep_interruptible(jiffies_to_msecs(portp->close_delay));
- wake_up_interruptible(&portp->port.open_wait);
- }
-
- portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
- wake_up_interruptible(&portp->port.close_wait);
+ tty_port_close_end(port, tty);
+ tty_port_tty_set(port, NULL);
}
/*****************************************************************************/
@@ -1405,14 +1313,20 @@ static void stl_stop(struct tty_struct *tty)
static void stl_hangup(struct tty_struct *tty)
{
struct stlport *portp;
+ struct tty_port *port;
+ unsigned long flags;
pr_debug("stl_hangup(tty=%p)\n", tty);
portp = tty->driver_data;
if (portp == NULL)
return;
+ port = &portp->port;
+
+ spin_lock_irqsave(&port->lock, flags);
+ port->flags &= ~ASYNC_INITIALIZED;
+ spin_unlock_irqrestore(&port->lock, flags);
- portp->port.flags &= ~ASYNC_INITIALIZED;
stl_disableintrs(portp);
if (tty->termios->c_cflag & HUPCL)
stl_setsignals(portp, 0, 0);
@@ -1426,10 +1340,7 @@ static void stl_hangup(struct tty_struct *tty)
portp->tx.head = NULL;
portp->tx.tail = NULL;
}
- tty_port_tty_set(&portp->port, NULL);
- portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
- portp->port.count = 0;
- wake_up_interruptible(&portp->port.open_wait);
+ tty_port_hangup(port);
}
/*****************************************************************************/
@@ -1776,6 +1687,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
break;
}
tty_port_init(&portp->port);
+ portp->port.ops = &stl_port_ops;
portp->magic = STL_PORTMAGIC;
portp->portnr = i;
portp->brdnr = panelp->brdnr;
@@ -2659,6 +2571,11 @@ static const struct tty_operations stl_ops = {
.tiocmset = stl_tiocmset,
};
+static const struct tty_port_operations stl_port_ops = {
+ .carrier_raised = stl_carrier_raised,
+ .raise_dtr_rts = stl_raise_dtr_rts,
+};
+
/*****************************************************************************/
/* CD1400 HARDWARE FUNCTIONS */
/*****************************************************************************/
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index ba4e86281fbf..f146e90404fa 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -279,7 +279,7 @@ static void sx_disable_tx_interrupts(void *ptr);
static void sx_enable_tx_interrupts(void *ptr);
static void sx_disable_rx_interrupts(void *ptr);
static void sx_enable_rx_interrupts(void *ptr);
-static int sx_get_CD(void *ptr);
+static int sx_carrier_raised(struct tty_port *port);
static void sx_shutdown_port(void *ptr);
static int sx_set_real_termios(void *ptr);
static void sx_close(void *ptr);
@@ -360,7 +360,6 @@ static struct real_driver sx_real_driver = {
sx_enable_tx_interrupts,
sx_disable_rx_interrupts,
sx_enable_rx_interrupts,
- sx_get_CD,
sx_shutdown_port,
sx_set_real_termios,
sx_chars_in_buffer,
@@ -791,7 +790,7 @@ static int sx_getsignals(struct sx_port *port)
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d (%d/%d) "
"%02x/%02x\n",
(o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
- port->c_dcd, sx_get_CD(port),
+ port->c_dcd, tty_port_carrier_raised(&port->gs.port),
sx_read_channel_byte(port, hi_ip),
sx_read_channel_byte(port, hi_state));
@@ -1190,7 +1189,7 @@ static inline void sx_check_modem_signals(struct sx_port *port)
hi_state = sx_read_channel_byte(port, hi_state);
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
- port->c_dcd, sx_get_CD(port));
+ port->c_dcd, tty_port_carrier_raised(&port->gs.port));
if (hi_state & ST_BREAK) {
hi_state &= ~ST_BREAK;
@@ -1202,11 +1201,11 @@ static inline void sx_check_modem_signals(struct sx_port *port)
hi_state &= ~ST_DCD;
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
sx_write_channel_byte(port, hi_state, hi_state);
- c_dcd = sx_get_CD(port);
+ c_dcd = tty_port_carrier_raised(&port->gs.port);
sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
if (c_dcd != port->c_dcd) {
port->c_dcd = c_dcd;
- if (sx_get_CD(port)) {
+ if (tty_port_carrier_raised(&port->gs.port)) {
/* DCD went UP */
if ((sx_read_channel_byte(port, hi_hstat) !=
HS_IDLE_CLOSED) &&
@@ -1415,13 +1414,10 @@ static void sx_enable_rx_interrupts(void *ptr)
}
/* Jeez. Isn't this simple? */
-static int sx_get_CD(void *ptr)
+static int sx_carrier_raised(struct tty_port *port)
{
- struct sx_port *port = ptr;
- func_enter2();
-
- func_exit();
- return ((sx_read_channel_byte(port, hi_ip) & IP_DCD) != 0);
+ struct sx_port *sp = container_of(port, struct sx_port, gs.port);
+ return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
}
/* Jeez. Isn't this simple? */
@@ -1536,7 +1532,7 @@ static int sx_open(struct tty_struct *tty, struct file *filp)
}
/* tty->low_latency = 1; */
- port->c_dcd = sx_get_CD(port);
+ port->c_dcd = sx_carrier_raised(&port->gs.port);
sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
func_exit();
@@ -1717,8 +1713,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
for (i = 0; i < SX_NBOARDS; i++)
sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
- unlock_kernel();
- return -EIO;
+ rc = -EIO;
+ goto out;
}
switch (cmd) {
@@ -1751,7 +1747,8 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
break;
case SXIO_DO_RAMTEST:
if (sx_initialized) /* Already initialized: better not ramtest the board. */
- return -EPERM;
+ rc = -EPERM;
+ break;
if (IS_SX_BOARD(board)) {
rc = do_memtest(board, 0, 0x7000);
if (!rc)
@@ -1848,6 +1845,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
rc = -ENOTTY;
break;
}
+out:
unlock_kernel();
func_exit();
return rc;
@@ -1945,7 +1943,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
static void sx_throttle(struct tty_struct *tty)
{
- struct sx_port *port = (struct sx_port *)tty->driver_data;
+ struct sx_port *port = tty->driver_data;
func_enter2();
/* If the port is using any type of input flow
@@ -1959,7 +1957,7 @@ static void sx_throttle(struct tty_struct *tty)
static void sx_unthrottle(struct tty_struct *tty)
{
- struct sx_port *port = (struct sx_port *)tty->driver_data;
+ struct sx_port *port = tty->driver_data;
func_enter2();
/* Always unthrottle even if flow control is not enabled on
@@ -2354,6 +2352,10 @@ static const struct tty_operations sx_ops = {
.tiocmset = sx_tiocmset,
};
+static const struct tty_port_operations sx_port_ops = {
+ .carrier_raised = sx_carrier_raised,
+};
+
static int sx_init_drivers(void)
{
int error;
@@ -2410,6 +2412,7 @@ static int sx_init_portstructs(int nboards, int nports)
for (j = 0; j < boards[i].nports; j++) {
sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
tty_port_init(&port->gs.port);
+ port->gs.port.ops = &sx_port_ops;
port->gs.magic = SX_MAGIC;
port->gs.close_delay = HZ / 2;
port->gs.closing_wait = 30 * HZ;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 500f5176b6ba..b8063d4cad32 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -977,7 +977,7 @@ static void ldisc_receive_buf(struct tty_struct *tty,
*/
static void mgsl_stop(struct tty_struct *tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (mgsl_paranoia_check(info, tty->name, "mgsl_stop"))
@@ -1000,7 +1000,7 @@ static void mgsl_stop(struct tty_struct *tty)
*/
static void mgsl_start(struct tty_struct *tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (mgsl_paranoia_check(info, tty->name, "mgsl_start"))
@@ -2057,7 +2057,7 @@ static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
*/
static void mgsl_flush_chars(struct tty_struct *tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if ( debug_level >= DEBUG_LEVEL_INFO )
@@ -2109,7 +2109,7 @@ static int mgsl_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
int c, ret = 0;
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if ( debug_level >= DEBUG_LEVEL_INFO )
@@ -2232,7 +2232,7 @@ cleanup:
*/
static int mgsl_write_room(struct tty_struct *tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
int ret;
if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room"))
@@ -2267,7 +2267,7 @@ static int mgsl_write_room(struct tty_struct *tty)
*/
static int mgsl_chars_in_buffer(struct tty_struct *tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_chars_in_buffer(%s)\n",
@@ -2301,7 +2301,7 @@ static int mgsl_chars_in_buffer(struct tty_struct *tty)
*/
static void mgsl_flush_buffer(struct tty_struct *tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -2329,7 +2329,7 @@ static void mgsl_flush_buffer(struct tty_struct *tty)
*/
static void mgsl_send_xchar(struct tty_struct *tty, char ch)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -2358,7 +2358,7 @@ static void mgsl_send_xchar(struct tty_struct *tty, char ch)
*/
static void mgsl_throttle(struct tty_struct * tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -2388,7 +2388,7 @@ static void mgsl_throttle(struct tty_struct * tty)
*/
static void mgsl_unthrottle(struct tty_struct * tty)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -2841,7 +2841,7 @@ static int modem_input_wait(struct mgsl_struct *info,int arg)
*/
static int tiocmget(struct tty_struct *tty, struct file *file)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned int result;
unsigned long flags;
@@ -2867,7 +2867,7 @@ static int tiocmget(struct tty_struct *tty, struct file *file)
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -2898,7 +2898,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
*/
static int mgsl_break(struct tty_struct *tty, int break_state)
{
- struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct * info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -2932,7 +2932,7 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct * info = tty->driver_data;
int ret;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -3042,7 +3042,7 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
*/
static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
- struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -3096,7 +3096,7 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio
*/
static void mgsl_close(struct tty_struct *tty, struct file * filp)
{
- struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct * info = tty->driver_data;
if (mgsl_paranoia_check(info, tty->name, "mgsl_close"))
return;
@@ -3104,70 +3104,18 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
__FILE__,__LINE__, info->device_name, info->port.count);
-
- if (!info->port.count)
- return;
- if (tty_hung_up_p(filp))
+ if (tty_port_close_start(&info->port, tty, filp) == 0)
goto cleanup;
- if ((tty->count == 1) && (info->port.count != 1)) {
- /*
- * tty->count is 1 and the tty structure will be freed.
- * info->port.count should be one in this case.
- * if it's not, correct it so that the port is shutdown.
- */
- printk("mgsl_close: bad refcount; tty->count is 1, "
- "info->port.count is %d\n", info->port.count);
- info->port.count = 1;
- }
-
- info->port.count--;
-
- /* if at least one open remaining, leave hardware active */
- if (info->port.count)
- goto cleanup;
-
- info->port.flags |= ASYNC_CLOSING;
-
- /* set tty->closing to notify line discipline to
- * only process XON/XOFF characters. Only the N_TTY
- * discipline appears to use this (ppp does not).
- */
- tty->closing = 1;
-
- /* wait for transmit data to clear all layers */
-
- if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) {
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):mgsl_close(%s) calling tty_wait_until_sent\n",
- __FILE__,__LINE__, info->device_name );
- tty_wait_until_sent(tty, info->port.closing_wait);
- }
-
if (info->port.flags & ASYNC_INITIALIZED)
mgsl_wait_until_sent(tty, info->timeout);
-
mgsl_flush_buffer(tty);
-
tty_ldisc_flush(tty);
-
shutdown(info);
-
- tty->closing = 0;
+
+ tty_port_close_end(&info->port, tty);
info->port.tty = NULL;
-
- if (info->port.blocked_open) {
- if (info->port.close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->port.close_delay));
- }
- wake_up_interruptible(&info->port.open_wait);
- }
-
- info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-
- wake_up_interruptible(&info->port.close_wait);
-
cleanup:
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__,
@@ -3188,7 +3136,7 @@ cleanup:
*/
static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct * info = tty->driver_data;
unsigned long orig_jiffies, char_time;
if (!info )
@@ -3261,7 +3209,7 @@ exit:
*/
static void mgsl_hangup(struct tty_struct *tty)
{
- struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
+ struct mgsl_struct * info = tty->driver_data;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_hangup(%s)\n",
@@ -3281,6 +3229,35 @@ static void mgsl_hangup(struct tty_struct *tty)
} /* end of mgsl_hangup() */
+/*
+ * carrier_raised()
+ *
+ * Return true if carrier is raised
+ */
+
+static int carrier_raised(struct tty_port *port)
+{
+ unsigned long flags;
+ struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
+
+ spin_lock_irqsave(&info->irq_spinlock, flags);
+ usc_get_serial_signals(info);
+ spin_unlock_irqrestore(&info->irq_spinlock, flags);
+ return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
+}
+
+static void raise_dtr_rts(struct tty_port *port)
+{
+ struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ usc_set_serial_signals(info);
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+}
+
+
/* block_til_ready()
*
* Block the current process until the specified port
@@ -3302,6 +3279,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
bool do_clocal = false;
bool extra_count = false;
unsigned long flags;
+ int dcd;
+ struct tty_port *port = &info->port;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready on %s\n",
@@ -3309,7 +3288,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -3318,50 +3297,42 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
/* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, info->port.count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* mgsl_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&info->port.open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready before block on %s count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->port.count );
+ __FILE__,__LINE__, tty->driver->name, port->count );
spin_lock_irqsave(&info->irq_spinlock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = true;
- info->port.count--;
+ port->count--;
}
spin_unlock_irqrestore(&info->irq_spinlock, flags);
- info->port.blocked_open++;
+ port->blocked_open++;
while (1) {
- if (tty->termios->c_cflag & CBAUD) {
- spin_lock_irqsave(&info->irq_spinlock,flags);
- info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
- usc_set_serial_signals(info);
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
- }
+ if (tty->termios->c_cflag & CBAUD)
+ tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){
- retval = (info->port.flags & ASYNC_HUP_NOTIFY) ?
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
+ retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
- spin_lock_irqsave(&info->irq_spinlock,flags);
- usc_get_serial_signals(info);
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ dcd = tty_port_carrier_raised(&info->port);
- if (!(info->port.flags & ASYNC_CLOSING) &&
- (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) {
+ if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
break;
- }
if (signal_pending(current)) {
retval = -ERESTARTSYS;
@@ -3370,24 +3341,25 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready blocking on %s count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->port.count );
+ __FILE__,__LINE__, tty->driver->name, port->count );
schedule();
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->port.open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
+ /* FIXME: Racy on hangup during close wait */
if (extra_count)
- info->port.count++;
- info->port.blocked_open--;
+ port->count++;
+ port->blocked_open--;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->port.count );
+ __FILE__,__LINE__, tty->driver->name, port->count );
if (!retval)
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return retval;
@@ -4304,6 +4276,12 @@ static void mgsl_add_device( struct mgsl_struct *info )
} /* end of mgsl_add_device() */
+static const struct tty_port_operations mgsl_port_ops = {
+ .carrier_raised = carrier_raised,
+ .raise_dtr_rts = raise_dtr_rts,
+};
+
+
/* mgsl_allocate_device()
*
* Allocate and initialize a device instance structure
@@ -4322,6 +4300,7 @@ static struct mgsl_struct* mgsl_allocate_device(void)
printk("Error can't allocate device instance data\n");
} else {
tty_port_init(&info->port);
+ info->port.ops = &mgsl_port_ops;
info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, mgsl_bh_handler);
info->max_frame_size = 4096;
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 08911ed66494..f329f459817c 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1,6 +1,4 @@
/*
- * $Id: synclink_gt.c,v 4.50 2007/07/25 19:29:25 paulkf Exp $
- *
* Device driver for Microgate SyncLink GT serial adapters.
*
* written by Paul Fulghum for Microgate Corporation
@@ -91,7 +89,6 @@
* module identification
*/
static char *driver_name = "SyncLink GT";
-static char *driver_version = "$Revision: 4.50 $";
static char *tty_driver_name = "synclink_gt";
static char *tty_dev_prefix = "ttySLG";
MODULE_LICENSE("GPL");
@@ -720,44 +717,9 @@ static void close(struct tty_struct *tty, struct file *filp)
return;
DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count));
- if (!info->port.count)
- return;
-
- if (tty_hung_up_p(filp))
- goto cleanup;
-
- if ((tty->count == 1) && (info->port.count != 1)) {
- /*
- * tty->count is 1 and the tty structure will be freed.
- * info->port.count should be one in this case.
- * if it's not, correct it so that the port is shutdown.
- */
- DBGERR(("%s close: bad refcount; tty->count=1, "
- "info->port.count=%d\n", info->device_name, info->port.count));
- info->port.count = 1;
- }
-
- info->port.count--;
-
- /* if at least one open remaining, leave hardware active */
- if (info->port.count)
+ if (tty_port_close_start(&info->port, tty, filp) == 0)
goto cleanup;
- info->port.flags |= ASYNC_CLOSING;
-
- /* set tty->closing to notify line discipline to
- * only process XON/XOFF characters. Only the N_TTY
- * discipline appears to use this (ppp does not).
- */
- tty->closing = 1;
-
- /* wait for transmit data to clear all layers */
-
- if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) {
- DBGINFO(("%s call tty_wait_until_sent\n", info->device_name));
- tty_wait_until_sent(tty, info->port.closing_wait);
- }
-
if (info->port.flags & ASYNC_INITIALIZED)
wait_until_sent(tty, info->timeout);
flush_buffer(tty);
@@ -765,20 +727,8 @@ static void close(struct tty_struct *tty, struct file *filp)
shutdown(info);
- tty->closing = 0;
+ tty_port_close_end(&info->port, tty);
info->port.tty = NULL;
-
- if (info->port.blocked_open) {
- if (info->port.close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->port.close_delay));
- }
- wake_up_interruptible(&info->port.open_wait);
- }
-
- info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-
- wake_up_interruptible(&info->port.close_wait);
-
cleanup:
DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count));
}
@@ -1356,7 +1306,7 @@ static int read_proc(char *page, char **start, off_t off, int count,
off_t begin = 0;
struct slgt_info *info;
- len += sprintf(page, "synclink_gt driver:%s\n", driver_version);
+ len += sprintf(page, "synclink_gt driver\n");
info = slgt_device_list;
while( info ) {
@@ -2488,7 +2438,7 @@ static void program_hw(struct slgt_info *info)
info->ri_chkcount = 0;
info->dsr_chkcount = 0;
- slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR);
+ slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI);
get_signals(info);
if (info->netcount ||
@@ -3132,6 +3082,29 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
+static int carrier_raised(struct tty_port *port)
+{
+ unsigned long flags;
+ struct slgt_info *info = container_of(port, struct slgt_info, port);
+
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return (info->signals & SerialSignal_DCD) ? 1 : 0;
+}
+
+static void raise_dtr_rts(struct tty_port *port)
+{
+ unsigned long flags;
+ struct slgt_info *info = container_of(port, struct slgt_info, port);
+
+ spin_lock_irqsave(&info->lock,flags);
+ info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+}
+
+
/*
* block current process until the device is ready to open
*/
@@ -3143,12 +3116,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
bool do_clocal = false;
bool extra_count = false;
unsigned long flags;
+ int cd;
+ struct tty_port *port = &info->port;
DBGINFO(("%s block_til_ready\n", tty->driver->name));
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -3157,46 +3132,38 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, info->port.count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&info->port.open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = true;
- info->port.count--;
+ port->count--;
}
spin_unlock_irqrestore(&info->lock, flags);
- info->port.blocked_open++;
+ port->blocked_open++;
while (1) {
- if ((tty->termios->c_cflag & CBAUD)) {
- spin_lock_irqsave(&info->lock,flags);
- info->signals |= SerialSignal_RTS + SerialSignal_DTR;
- set_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
- }
+ if ((tty->termios->c_cflag & CBAUD))
+ tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){
- retval = (info->port.flags & ASYNC_HUP_NOTIFY) ?
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
+ retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
- spin_lock_irqsave(&info->lock,flags);
- get_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
+ cd = tty_port_carrier_raised(port);
- if (!(info->port.flags & ASYNC_CLOSING) &&
- (do_clocal || (info->signals & SerialSignal_DCD)) ) {
+ if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
break;
- }
if (signal_pending(current)) {
retval = -ERESTARTSYS;
@@ -3208,14 +3175,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->port.open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
if (extra_count)
- info->port.count++;
- info->port.blocked_open--;
+ port->count++;
+ port->blocked_open--;
if (!retval)
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
return retval;
@@ -3444,6 +3411,11 @@ static void add_device(struct slgt_info *info)
#endif
}
+static const struct tty_port_operations slgt_port_ops = {
+ .carrier_raised = carrier_raised,
+ .raise_dtr_rts = raise_dtr_rts,
+};
+
/*
* allocate device instance structure, return NULL on failure
*/
@@ -3458,6 +3430,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
driver_name, adapter_num, port_num));
} else {
tty_port_init(&info->port);
+ info->port.ops = &slgt_port_ops;
info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096;
@@ -3600,7 +3573,7 @@ static void slgt_cleanup(void)
struct slgt_info *info;
struct slgt_info *tmp;
- printk("unload %s %s\n", driver_name, driver_version);
+ printk(KERN_INFO "unload %s\n", driver_name);
if (serial_driver) {
for (info=slgt_device_list ; info != NULL ; info=info->next_device)
@@ -3643,7 +3616,7 @@ static int __init slgt_init(void)
{
int rc;
- printk("%s %s\n", driver_name, driver_version);
+ printk(KERN_INFO "%s\n", driver_name);
serial_driver = alloc_tty_driver(MAX_DEVICES);
if (!serial_driver) {
@@ -3674,9 +3647,8 @@ static int __init slgt_init(void)
goto error;
}
- printk("%s %s, tty major#%d\n",
- driver_name, driver_version,
- serial_driver->major);
+ printk(KERN_INFO "%s, tty major#%d\n",
+ driver_name, serial_driver->major);
slgt_device_count = 0;
if ((rc = pci_register_driver(&pci_driver)) < 0) {
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 6bdb44f7bec2..7b0c5b2dd263 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -558,6 +558,7 @@ static void release_resources(SLMP_INFO *info);
static int startup(SLMP_INFO *info);
static int block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info);
+static int carrier_raised(struct tty_port *port);
static void shutdown(SLMP_INFO *info);
static void program_hw(SLMP_INFO *info);
static void change_params(SLMP_INFO *info);
@@ -800,7 +801,7 @@ cleanup:
*/
static void close(struct tty_struct *tty, struct file *filp)
{
- SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO * info = tty->driver_data;
if (sanity_check(info, tty->name, "close"))
return;
@@ -809,70 +810,18 @@ static void close(struct tty_struct *tty, struct file *filp)
printk("%s(%d):%s close() entry, count=%d\n",
__FILE__,__LINE__, info->device_name, info->port.count);
- if (!info->port.count)
- return;
-
- if (tty_hung_up_p(filp))
- goto cleanup;
-
- if ((tty->count == 1) && (info->port.count != 1)) {
- /*
- * tty->count is 1 and the tty structure will be freed.
- * info->port.count should be one in this case.
- * if it's not, correct it so that the port is shutdown.
- */
- printk("%s(%d):%s close: bad refcount; tty->count is 1, "
- "info->port.count is %d\n",
- __FILE__,__LINE__, info->device_name, info->port.count);
- info->port.count = 1;
- }
-
- info->port.count--;
-
- /* if at least one open remaining, leave hardware active */
- if (info->port.count)
+ if (tty_port_close_start(&info->port, tty, filp) == 0)
goto cleanup;
-
- info->port.flags |= ASYNC_CLOSING;
-
- /* set tty->closing to notify line discipline to
- * only process XON/XOFF characters. Only the N_TTY
- * discipline appears to use this (ppp does not).
- */
- tty->closing = 1;
-
- /* wait for transmit data to clear all layers */
-
- if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) {
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):%s close() calling tty_wait_until_sent\n",
- __FILE__,__LINE__, info->device_name );
- tty_wait_until_sent(tty, info->port.closing_wait);
- }
-
+
if (info->port.flags & ASYNC_INITIALIZED)
wait_until_sent(tty, info->timeout);
flush_buffer(tty);
-
tty_ldisc_flush(tty);
-
shutdown(info);
- tty->closing = 0;
+ tty_port_close_end(&info->port, tty);
info->port.tty = NULL;
-
- if (info->port.blocked_open) {
- if (info->port.close_delay) {
- msleep_interruptible(jiffies_to_msecs(info->port.close_delay));
- }
- wake_up_interruptible(&info->port.open_wait);
- }
-
- info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-
- wake_up_interruptible(&info->port.close_wait);
-
cleanup:
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__,
@@ -884,7 +833,7 @@ cleanup:
*/
static void hangup(struct tty_struct *tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s hangup()\n",
@@ -907,7 +856,7 @@ static void hangup(struct tty_struct *tty)
*/
static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -960,7 +909,7 @@ static int write(struct tty_struct *tty,
const unsigned char *buf, int count)
{
int c, ret = 0;
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1038,7 +987,7 @@ cleanup:
*/
static int put_char(struct tty_struct *tty, unsigned char ch)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
int ret = 0;
@@ -1075,7 +1024,7 @@ static int put_char(struct tty_struct *tty, unsigned char ch)
*/
static void send_xchar(struct tty_struct *tty, char ch)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1099,7 +1048,7 @@ static void send_xchar(struct tty_struct *tty, char ch)
*/
static void wait_until_sent(struct tty_struct *tty, int timeout)
{
- SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO * info = tty->driver_data;
unsigned long orig_jiffies, char_time;
if (!info )
@@ -1166,7 +1115,7 @@ exit:
*/
static int write_room(struct tty_struct *tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
int ret;
if (sanity_check(info, tty->name, "write_room"))
@@ -1193,7 +1142,7 @@ static int write_room(struct tty_struct *tty)
*/
static void flush_chars(struct tty_struct *tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if ( debug_level >= DEBUG_LEVEL_INFO )
@@ -1232,7 +1181,7 @@ static void flush_chars(struct tty_struct *tty)
*/
static void flush_buffer(struct tty_struct *tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1254,7 +1203,7 @@ static void flush_buffer(struct tty_struct *tty)
*/
static void tx_hold(struct tty_struct *tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (sanity_check(info, tty->name, "tx_hold"))
@@ -1274,7 +1223,7 @@ static void tx_hold(struct tty_struct *tty)
*/
static void tx_release(struct tty_struct *tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (sanity_check(info, tty->name, "tx_release"))
@@ -1304,7 +1253,7 @@ static void tx_release(struct tty_struct *tty)
static int do_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
int error;
struct mgsl_icount cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser; /* user space */
@@ -1515,7 +1464,7 @@ done:
*/
static int chars_in_buffer(struct tty_struct *tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
if (sanity_check(info, tty->name, "chars_in_buffer"))
return 0;
@@ -1531,7 +1480,7 @@ static int chars_in_buffer(struct tty_struct *tty)
*/
static void throttle(struct tty_struct * tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1556,7 +1505,7 @@ static void throttle(struct tty_struct * tty)
*/
static void unthrottle(struct tty_struct * tty)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1587,7 +1536,7 @@ static void unthrottle(struct tty_struct * tty)
static int set_break(struct tty_struct *tty, int break_state)
{
unsigned char RegValue;
- SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO * info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -3269,7 +3218,7 @@ static int modem_input_wait(SLMP_INFO *info,int arg)
*/
static int tiocmget(struct tty_struct *tty, struct file *file)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned int result;
unsigned long flags;
@@ -3295,7 +3244,7 @@ static int tiocmget(struct tty_struct *tty, struct file *file)
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
- SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
+ SLMP_INFO *info = tty->driver_data;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -3318,7 +3267,28 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
return 0;
}
+static int carrier_raised(struct tty_port *port)
+{
+ SLMP_INFO *info = container_of(port, SLMP_INFO, port);
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ get_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+ return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
+}
+
+static void raise_dtr_rts(struct tty_port *port)
+{
+ SLMP_INFO *info = container_of(port, SLMP_INFO, port);
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+ set_signals(info);
+ spin_unlock_irqrestore(&info->lock,flags);
+}
/* Block the current process until the specified port is ready to open.
*/
@@ -3330,6 +3300,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
bool do_clocal = false;
bool extra_count = false;
unsigned long flags;
+ int cd;
+ struct tty_port *port = &info->port;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready()\n",
@@ -3338,7 +3310,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
/* nonblock mode is set or port is not enabled */
/* just verify that callout device is not active */
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@@ -3347,50 +3319,42 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
/* Wait for carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
- * this loop, info->port.count is dropped by one, so that
+ * this loop, port->count is dropped by one, so that
* close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
- add_wait_queue(&info->port.open_wait, &wait);
+ add_wait_queue(&port->open_wait, &wait);
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready() before block, count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->port.count );
+ __FILE__,__LINE__, tty->driver->name, port->count );
spin_lock_irqsave(&info->lock, flags);
if (!tty_hung_up_p(filp)) {
extra_count = true;
- info->port.count--;
+ port->count--;
}
spin_unlock_irqrestore(&info->lock, flags);
- info->port.blocked_open++;
+ port->blocked_open++;
while (1) {
- if ((tty->termios->c_cflag & CBAUD)) {
- spin_lock_irqsave(&info->lock,flags);
- info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
- set_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
- }
+ if (tty->termios->c_cflag & CBAUD)
+ tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);
- if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){
- retval = (info->port.flags & ASYNC_HUP_NOTIFY) ?
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
+ retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
break;
}
- spin_lock_irqsave(&info->lock,flags);
- get_signals(info);
- spin_unlock_irqrestore(&info->lock,flags);
+ cd = tty_port_carrier_raised(port);
- if (!(info->port.flags & ASYNC_CLOSING) &&
- (do_clocal || (info->serial_signals & SerialSignal_DCD)) ) {
+ if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
break;
- }
if (signal_pending(current)) {
retval = -ERESTARTSYS;
@@ -3399,24 +3363,24 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready() count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->port.count );
+ __FILE__,__LINE__, tty->driver->name, port->count );
schedule();
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&info->port.open_wait, &wait);
+ remove_wait_queue(&port->open_wait, &wait);
if (extra_count)
- info->port.count++;
- info->port.blocked_open--;
+ port->count++;
+ port->blocked_open--;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s block_til_ready() after, count=%d\n",
- __FILE__,__LINE__, tty->driver->name, info->port.count );
+ __FILE__,__LINE__, tty->driver->name, port->count );
if (!retval)
- info->port.flags |= ASYNC_NORMAL_ACTIVE;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
return retval;
}
@@ -3782,6 +3746,11 @@ static void add_device(SLMP_INFO *info)
#endif
}
+static const struct tty_port_operations port_ops = {
+ .carrier_raised = carrier_raised,
+ .raise_dtr_rts = raise_dtr_rts,
+};
+
/* Allocate and initialize a device instance structure
*
* Return Value: pointer to SLMP_INFO if success, otherwise NULL
@@ -3798,6 +3767,7 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
__FILE__,__LINE__, adapter_num, port_num);
} else {
tty_port_init(&info->port);
+ info->port.ops = &port_ops;
info->magic = MGSL_MAGIC;
INIT_WORK(&info->task, bh_handler);
info->max_frame_size = 4096;
@@ -3940,6 +3910,7 @@ static const struct tty_operations ops = {
.tiocmset = tiocmset,
};
+
static void synclinkmp_cleanup(void)
{
int rc;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 94966edfb44d..33a9351c896d 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -82,7 +82,7 @@ static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_loglevel_op = {
.handler = sysrq_handle_loglevel,
- .help_msg = "loglevel0-8",
+ .help_msg = "loglevel(0-9)",
.action_msg = "Changing Loglevel",
.enable_mask = SYSRQ_ENABLE_LOG,
};
@@ -233,7 +233,7 @@ static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
static struct sysrq_key_op sysrq_showallcpus_op = {
.handler = sysrq_handle_showallcpus,
- .help_msg = "aLlcpus",
+ .help_msg = "show-backtrace-all-active-cpus(L)",
.action_msg = "Show backtrace of all active CPUs",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -247,7 +247,7 @@ static void sysrq_handle_showregs(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_showregs_op = {
.handler = sysrq_handle_showregs,
- .help_msg = "showPc",
+ .help_msg = "show-registers(P)",
.action_msg = "Show Regs",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -258,7 +258,7 @@ static void sysrq_handle_showstate(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_showstate_op = {
.handler = sysrq_handle_showstate,
- .help_msg = "showTasks",
+ .help_msg = "show-task-states(T)",
.action_msg = "Show State",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -269,7 +269,7 @@ static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_showstate_blocked_op = {
.handler = sysrq_handle_showstate_blocked,
- .help_msg = "shoW-blocked-tasks",
+ .help_msg = "show-blocked-tasks(W)",
.action_msg = "Show Blocked State",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -297,7 +297,7 @@ static void sysrq_handle_showmem(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_showmem_op = {
.handler = sysrq_handle_showmem,
- .help_msg = "showMem",
+ .help_msg = "show-memory-usage(M)",
.action_msg = "Show Memory",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@@ -323,7 +323,7 @@ static void sysrq_handle_term(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_term_op = {
.handler = sysrq_handle_term,
- .help_msg = "tErm",
+ .help_msg = "terminate-all-tasks(E)",
.action_msg = "Terminate All Tasks",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
@@ -341,7 +341,7 @@ static void sysrq_handle_moom(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_moom_op = {
.handler = sysrq_handle_moom,
- .help_msg = "Full",
+ .help_msg = "memory-full-oom-kill(F)",
.action_msg = "Manual OOM execution",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
@@ -353,7 +353,7 @@ static void sysrq_handle_kill(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_kill_op = {
.handler = sysrq_handle_kill,
- .help_msg = "kIll",
+ .help_msg = "kill-all-tasks(I)",
.action_msg = "Kill All Tasks",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
@@ -364,7 +364,7 @@ static void sysrq_handle_unrt(int key, struct tty_struct *tty)
}
static struct sysrq_key_op sysrq_unrt_op = {
.handler = sysrq_handle_unrt,
- .help_msg = "Nice",
+ .help_msg = "nice-all-RT-tasks(N)",
.action_msg = "Nice All RT Tasks",
.enable_mask = SYSRQ_ENABLE_RTNICE,
};
@@ -473,6 +473,12 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
unsigned long flags;
spin_lock_irqsave(&sysrq_key_table_lock, flags);
+ /*
+ * Raise the apparent loglevel to maximum so that the sysrq header
+ * is shown to provide the user with positive feedback. We do not
+ * simply emit this at KERN_EMERG as that would change message
+ * routing in the consumers of /proc/kmsg.
+ */
orig_log_level = console_loglevel;
console_loglevel = 7;
printk(KERN_INFO "SysRq : ");
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
index 68f052b42ed7..ed306eb1057f 100644
--- a/drivers/char/tpm/tpm_bios.c
+++ b/drivers/char/tpm/tpm_bios.c
@@ -23,8 +23,6 @@
#include <linux/security.h>
#include <linux/module.h>
#include <acpi/acpi.h>
-#include <acpi/actypes.h>
-#include <acpi/actbl.h>
#include "tpm.h"
#define TCG_EVENT_NAME_LEN_MAX 255
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index ab18c1e7b115..70efba2ee053 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -273,12 +273,23 @@ static void tpm_nsc_remove(struct device *dev)
}
}
-static struct device_driver nsc_drv = {
- .name = "tpm_nsc",
- .bus = &platform_bus_type,
- .owner = THIS_MODULE,
- .suspend = tpm_pm_suspend,
- .resume = tpm_pm_resume,
+static int tpm_nsc_suspend(struct platform_device *dev, pm_message_t msg)
+{
+ return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_nsc_resume(struct platform_device *dev)
+{
+ return tpm_pm_resume(&dev->dev);
+}
+
+static struct platform_driver nsc_drv = {
+ .suspend = tpm_nsc_suspend,
+ .resume = tpm_nsc_resume,
+ .driver = {
+ .name = "tpm_nsc",
+ .owner = THIS_MODULE,
+ },
};
static int __init init_nsc(void)
@@ -297,7 +308,7 @@ static int __init init_nsc(void)
return -ENODEV;
}
- err = driver_register(&nsc_drv);
+ err = platform_driver_register(&nsc_drv);
if (err)
return err;
@@ -308,17 +319,15 @@ static int __init init_nsc(void)
/* enable the DPM module */
tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
- pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ pdev = platform_device_alloc("tpm_nscl0", -1);
if (!pdev) {
rc = -ENOMEM;
goto err_unreg_drv;
}
- pdev->name = "tpm_nscl0";
- pdev->id = -1;
pdev->num_resources = 0;
+ pdev->dev.driver = &nsc_drv.driver;
pdev->dev.release = tpm_nsc_remove;
- pdev->dev.driver = &nsc_drv;
if ((rc = platform_device_register(pdev)) < 0)
goto err_free_dev;
@@ -377,7 +386,7 @@ err_unreg_dev:
err_free_dev:
kfree(pdev);
err_unreg_drv:
- driver_unregister(&nsc_drv);
+ platform_driver_unregister(&nsc_drv);
return rc;
}
@@ -390,7 +399,7 @@ static void __exit cleanup_nsc(void)
pdev = NULL;
}
- driver_unregister(&nsc_drv);
+ platform_driver_unregister(&nsc_drv);
}
module_init(init_nsc);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index db15f9ba7c0b..bc84e125c6bc 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1111,9 +1111,7 @@ void tty_write_message(struct tty_struct *tty, char *msg)
* Locks the line discipline as required
* Writes to the tty driver are serialized by the atomic_write_lock
* and are then processed in chunks to the device. The line discipline
- * write method will not be involked in parallel for each device
- * The line discipline write method is called under the big
- * kernel lock for historical reasons. New code should not rely on this.
+ * write method will not be invoked in parallel for each device.
*/
static ssize_t tty_write(struct file *file, const char __user *buf,
@@ -1213,7 +1211,7 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p)
* be held until the 'fast-open' is also done. Will change once we
* have refcounting in the driver and per driver locking
*/
-struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
+static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver,
struct inode *inode, int idx)
{
struct tty_struct *tty;
@@ -1819,8 +1817,10 @@ got_driver:
/* check whether we're reopening an existing tty */
tty = tty_driver_lookup_tty(driver, inode, index);
- if (IS_ERR(tty))
+ if (IS_ERR(tty)) {
+ mutex_unlock(&tty_mutex);
return PTR_ERR(tty);
+ }
}
if (tty) {
@@ -2050,7 +2050,6 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
/**
* tty_do_resize - resize event
* @tty: tty being resized
- * @real_tty: real tty (not the same as tty if using a pty/tty pair)
* @rows: rows (character)
* @cols: cols (character)
*
@@ -2058,41 +2057,34 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
* peform a terminal resize correctly
*/
-int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
- struct winsize *ws)
+int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
{
- struct pid *pgrp, *rpgrp;
+ struct pid *pgrp;
unsigned long flags;
- /* For a PTY we need to lock the tty side */
- mutex_lock(&real_tty->termios_mutex);
- if (!memcmp(ws, &real_tty->winsize, sizeof(*ws)))
+ /* Lock the tty */
+ mutex_lock(&tty->termios_mutex);
+ if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;
/* Get the PID values and reference them so we can
avoid holding the tty ctrl lock while sending signals */
spin_lock_irqsave(&tty->ctrl_lock, flags);
pgrp = get_pid(tty->pgrp);
- rpgrp = get_pid(real_tty->pgrp);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
if (pgrp)
kill_pgrp(pgrp, SIGWINCH, 1);
- if (rpgrp != pgrp && rpgrp)
- kill_pgrp(rpgrp, SIGWINCH, 1);
-
put_pid(pgrp);
- put_pid(rpgrp);
tty->winsize = *ws;
- real_tty->winsize = *ws;
done:
- mutex_unlock(&real_tty->termios_mutex);
+ mutex_unlock(&tty->termios_mutex);
return 0;
}
/**
* tiocswinsz - implement window size set ioctl
- * @tty; tty
+ * @tty; tty side of tty
* @arg: user buffer for result
*
* Copies the user idea of the window size to the kernel. Traditionally
@@ -2105,17 +2097,16 @@ done:
* then calls into the default method.
*/
-static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
- struct winsize __user *arg)
+static int tiocswinsz(struct tty_struct *tty, struct winsize __user *arg)
{
struct winsize tmp_ws;
if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
return -EFAULT;
if (tty->ops->resize)
- return tty->ops->resize(tty, real_tty, &tmp_ws);
+ return tty->ops->resize(tty, &tmp_ws);
else
- return tty_do_resize(tty, real_tty, &tmp_ws);
+ return tty_do_resize(tty, &tmp_ws);
}
/**
@@ -2540,7 +2531,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCGWINSZ:
return tiocgwinsz(real_tty, p);
case TIOCSWINSZ:
- return tiocswinsz(tty, real_tty, p);
+ return tiocswinsz(real_tty, p);
case TIOCCONS:
return real_tty != tty ? -EINVAL : tioccons(file);
case FIONBIO:
@@ -2785,6 +2776,8 @@ void initialize_tty_struct(struct tty_struct *tty,
INIT_WORK(&tty->hangup_work, do_tty_hangup);
mutex_init(&tty->atomic_read_lock);
mutex_init(&tty->atomic_write_lock);
+ mutex_init(&tty->output_lock);
+ mutex_init(&tty->echo_lock);
spin_lock_init(&tty->read_lock);
spin_lock_init(&tty->ctrl_lock);
INIT_LIST_HEAD(&tty->tty_files);
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index a408c8e487ec..6f4c7d0a53bf 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -1057,7 +1057,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
if (retval)
return retval;
- ld = tty_ldisc_ref(tty);
+ ld = tty_ldisc_ref_wait(tty);
switch (arg) {
case TCIFLUSH:
if (ld && ld->ops->flush_buffer)
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index f307f135cbfb..7a84b406a952 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -316,8 +316,7 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
{
/* wait_event is a macro */
wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
- if (tty->ldisc.refcount == 0)
- printk(KERN_ERR "tty_ldisc_ref_wait\n");
+ WARN_ON(tty->ldisc.refcount == 0);
return &tty->ldisc;
}
@@ -376,15 +375,17 @@ EXPORT_SYMBOL_GPL(tty_ldisc_deref);
* @tty: terminal to activate ldisc on
*
* Set the TTY_LDISC flag when the line discipline can be called
- * again. Do necessary wakeups for existing sleepers.
+ * again. Do necessary wakeups for existing sleepers. Clear the LDISC
+ * changing flag to indicate any ldisc change is now over.
*
- * Note: nobody should set this bit except via this function. Clearing
- * directly is allowed.
+ * Note: nobody should set the TTY_LDISC bit except via this function.
+ * Clearing directly is allowed.
*/
void tty_ldisc_enable(struct tty_struct *tty)
{
set_bit(TTY_LDISC, &tty->flags);
+ clear_bit(TTY_LDISC_CHANGING, &tty->flags);
wake_up(&tty_ldisc_wait);
}
@@ -496,7 +497,14 @@ restart:
* reference to the line discipline. The TTY_LDISC bit
* prevents anyone taking a reference once it is clear.
* We need the lock to avoid racing reference takers.
+ *
+ * We must clear the TTY_LDISC bit here to avoid a livelock
+ * with a userspace app continually trying to use the tty in
+ * parallel to the change and re-referencing the tty.
*/
+ clear_bit(TTY_LDISC, &tty->flags);
+ if (o_tty)
+ clear_bit(TTY_LDISC, &o_tty->flags);
spin_lock_irqsave(&tty_ldisc_lock, flags);
if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) {
@@ -528,7 +536,7 @@ restart:
* If the TTY_LDISC bit is set, then we are racing against
* another ldisc change
*/
- if (!test_bit(TTY_LDISC, &tty->flags)) {
+ if (test_bit(TTY_LDISC_CHANGING, &tty->flags)) {
struct tty_ldisc *ld;
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
tty_ldisc_put(new_ldisc.ops);
@@ -536,10 +544,14 @@ restart:
tty_ldisc_deref(ld);
goto restart;
}
-
- clear_bit(TTY_LDISC, &tty->flags);
+ /*
+ * This flag is used to avoid two parallel ldisc changes. Once
+ * open and close are fine grained locked this may work better
+ * as a mutex shared with the open/close/hup paths
+ */
+ set_bit(TTY_LDISC_CHANGING, &tty->flags);
if (o_tty)
- clear_bit(TTY_LDISC, &o_tty->flags);
+ set_bit(TTY_LDISC_CHANGING, &o_tty->flags);
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
/*
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index c8f8024cb40e..9b8004c72686 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -7,6 +7,7 @@
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
+#include <linux/serial.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/slab.h>
@@ -94,3 +95,227 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL(tty_port_tty_set);
+
+/**
+ * tty_port_hangup - hangup helper
+ * @port: tty port
+ *
+ * Perform port level tty hangup flag and count changes. Drop the tty
+ * reference.
+ */
+
+void tty_port_hangup(struct tty_port *port)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ port->count = 0;
+ port->flags &= ~ASYNC_NORMAL_ACTIVE;
+ if (port->tty)
+ tty_kref_put(port->tty);
+ port->tty = NULL;
+ spin_unlock_irqrestore(&port->lock, flags);
+ wake_up_interruptible(&port->open_wait);
+}
+EXPORT_SYMBOL(tty_port_hangup);
+
+/**
+ * tty_port_carrier_raised - carrier raised check
+ * @port: tty port
+ *
+ * Wrapper for the carrier detect logic. For the moment this is used
+ * to hide some internal details. This will eventually become entirely
+ * internal to the tty port.
+ */
+
+int tty_port_carrier_raised(struct tty_port *port)
+{
+ if (port->ops->carrier_raised == NULL)
+ return 1;
+ return port->ops->carrier_raised(port);
+}
+EXPORT_SYMBOL(tty_port_carrier_raised);
+
+/**
+ * tty_port_raise_dtr_rts - Riase DTR/RTS
+ * @port: tty port
+ *
+ * Wrapper for the DTR/RTS raise logic. For the moment this is used
+ * to hide some internal details. This will eventually become entirely
+ * internal to the tty port.
+ */
+
+void tty_port_raise_dtr_rts(struct tty_port *port)
+{
+ if (port->ops->raise_dtr_rts)
+ port->ops->raise_dtr_rts(port);
+}
+EXPORT_SYMBOL(tty_port_raise_dtr_rts);
+
+/**
+ * tty_port_block_til_ready - Waiting logic for tty open
+ * @port: the tty port being opened
+ * @tty: the tty device being bound
+ * @filp: the file pointer of the opener
+ *
+ * Implement the core POSIX/SuS tty behaviour when opening a tty device.
+ * Handles:
+ * - hangup (both before and during)
+ * - non blocking open
+ * - rts/dtr/dcd
+ * - signals
+ * - port flags and counts
+ *
+ * The passed tty_port must implement the carrier_raised method if it can
+ * do carrier detect and the raise_dtr_rts method if it supports software
+ * management of these lines. Note that the dtr/rts raise is done each
+ * iteration as a hangup may have previously dropped them while we wait.
+ */
+
+int tty_port_block_til_ready(struct tty_port *port,
+ struct tty_struct *tty, struct file *filp)
+{
+ int do_clocal = 0, retval;
+ unsigned long flags;
+ DECLARE_WAITQUEUE(wait, current);
+ int cd;
+
+ /* block if port is in the process of being closed */
+ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
+ interruptible_sleep_on(&port->close_wait);
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ return -EAGAIN;
+ else
+ return -ERESTARTSYS;
+ }
+
+ /* if non-blocking mode is set we can pass directly to open unless
+ the port has just hung up or is in another error state */
+ if ((filp->f_flags & O_NONBLOCK) ||
+ (tty->flags & (1 << TTY_IO_ERROR))) {
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (C_CLOCAL(tty))
+ do_clocal = 1;
+
+ /* Block waiting until we can proceed. We may need to wait for the
+ carrier, but we must also wait for any close that is in progress
+ before the next open may complete */
+
+ retval = 0;
+ add_wait_queue(&port->open_wait, &wait);
+
+ /* The port lock protects the port counts */
+ spin_lock_irqsave(&port->lock, flags);
+ if (!tty_hung_up_p(filp))
+ port->count--;
+ port->blocked_open++;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ while (1) {
+ /* Indicate we are open */
+ if (tty->termios->c_cflag & CBAUD)
+ tty_port_raise_dtr_rts(port);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ /* Check for a hangup or uninitialised port. Return accordingly */
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+ break;
+ }
+ /* Probe the carrier. For devices with no carrier detect this
+ will always return true */
+ cd = tty_port_carrier_raised(port);
+ if (!(port->flags & ASYNC_CLOSING) &&
+ (do_clocal || cd))
+ break;
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&port->open_wait, &wait);
+
+ /* Update counts. A parallel hangup will have set count to zero and
+ we must not mess that up further */
+ spin_lock_irqsave(&port->lock, flags);
+ if (!tty_hung_up_p(filp))
+ port->count++;
+ port->blocked_open--;
+ if (retval == 0)
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ spin_unlock_irqrestore(&port->lock, flags);
+ return 0;
+
+}
+EXPORT_SYMBOL(tty_port_block_til_ready);
+
+int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (tty_hung_up_p(filp)) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ return 0;
+ }
+
+ if( tty->count == 1 && port->count != 1) {
+ printk(KERN_WARNING
+ "tty_port_close_start: tty->count = 1 port count = %d.\n",
+ port->count);
+ port->count = 1;
+ }
+ if (--port->count < 0) {
+ printk(KERN_WARNING "tty_port_close_start: count = %d\n",
+ port->count);
+ port->count = 0;
+ }
+
+ if (port->count) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ return 0;
+ }
+ port->flags |= ASYNC_CLOSING;
+ tty->closing = 1;
+ spin_unlock_irqrestore(&port->lock, flags);
+ /* Don't block on a stalled port, just pull the chain */
+ if (tty->flow_stopped)
+ tty_driver_flush_buffer(tty);
+ if (port->flags & ASYNC_INITIALIZED &&
+ port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, port->closing_wait);
+ return 1;
+}
+EXPORT_SYMBOL(tty_port_close_start);
+
+void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
+{
+ unsigned long flags;
+
+ tty_ldisc_flush(tty);
+
+ spin_lock_irqsave(&port->lock, flags);
+ tty->closing = 0;
+
+ if (port->blocked_open) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ if (port->close_delay) {
+ msleep_interruptible(
+ jiffies_to_msecs(port->close_delay));
+ }
+ spin_lock_irqsave(&port->lock, flags);
+ wake_up_interruptible(&port->open_wait);
+ }
+ port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+ wake_up_interruptible(&port->close_wait);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+EXPORT_SYMBOL(tty_port_close_end);
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 1718b3c481db..994e1a58b987 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -69,7 +69,7 @@ static void scc_disable_tx_interrupts(void * ptr);
static void scc_enable_tx_interrupts(void * ptr);
static void scc_disable_rx_interrupts(void * ptr);
static void scc_enable_rx_interrupts(void * ptr);
-static int scc_get_CD(void * ptr);
+static int scc_carrier_raised(struct tty_port *port);
static void scc_shutdown_port(void * ptr);
static int scc_set_real_termios(void *ptr);
static void scc_hungup(void *ptr);
@@ -100,7 +100,6 @@ static struct real_driver scc_real_driver = {
scc_enable_tx_interrupts,
scc_disable_rx_interrupts,
scc_enable_rx_interrupts,
- scc_get_CD,
scc_shutdown_port,
scc_set_real_termios,
scc_chars_in_buffer,
@@ -129,6 +128,10 @@ static const struct tty_operations scc_ops = {
.break_ctl = scc_break_ctl,
};
+static const struct tty_port_operations scc_port_ops = {
+ .carrier_raised = scc_carrier_raised,
+};
+
/*----------------------------------------------------------------------------
* vme_scc_init() and support functions
*---------------------------------------------------------------------------*/
@@ -176,6 +179,8 @@ static void scc_init_portstructs(void)
for (i = 0; i < 2; i++) {
port = scc_ports + i;
+ tty_port_init(&port->gs.port);
+ port->gs.port.ops = &scc_port_ops;
port->gs.magic = SCC_MAGIC;
port->gs.close_delay = HZ/2;
port->gs.closing_wait = 30 * HZ;
@@ -193,6 +198,7 @@ static void scc_init_portstructs(void)
static int mvme147_scc_init(void)
{
struct scc_port *port;
+ int error;
printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
/* Init channel A */
@@ -202,14 +208,23 @@ static int mvme147_scc_init(void)
port->datap = port->ctrlp + 1;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
"SCC-A TX", port);
- request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail;
+ error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-A status", port);
- request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_tx;
+ error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
"SCC-A RX", port);
- request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_stat;
+ error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -229,14 +244,23 @@ static int mvme147_scc_init(void)
port->datap = port->ctrlp + 1;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
"SCC-B TX", port);
- request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_spcond;
+ error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-B status", port);
- request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_b_tx;
+ error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
"SCC-B RX", port);
- request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_stat;
+ error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -252,6 +276,23 @@ static int mvme147_scc_init(void)
scc_init_drivers();
return 0;
+
+fail_free_b_rx:
+ free_irq(MVME147_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+ free_irq(MVME147_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+ free_irq(MVME147_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+ free_irq(MVME147_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+ free_irq(MVME147_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+ free_irq(MVME147_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+ free_irq(MVME147_IRQ_SCCA_TX, port);
+fail:
+ return error;
}
#endif
@@ -260,6 +301,7 @@ static int mvme147_scc_init(void)
static int mvme162_scc_init(void)
{
struct scc_port *port;
+ int error;
if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
return (-ENODEV);
@@ -272,14 +314,23 @@ static int mvme162_scc_init(void)
port->datap = port->ctrlp + 2;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
"SCC-A TX", port);
- request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail;
+ error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-A status", port);
- request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_tx;
+ error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
"SCC-A RX", port);
- request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_stat;
+ error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -299,14 +350,22 @@ static int mvme162_scc_init(void)
port->datap = port->ctrlp + 2;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
"SCC-B TX", port);
- request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_spcond;
+ error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-B status", port);
- request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_b_tx;
+ error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
"SCC-B RX", port);
- request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_stat;
+ error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_rx;
{
SCC_ACCESS_INIT(port); /* Either channel will do */
@@ -323,6 +382,23 @@ static int mvme162_scc_init(void)
scc_init_drivers();
return 0;
+
+fail_free_b_rx:
+ free_irq(MVME162_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+ free_irq(MVME162_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+ free_irq(MVME162_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+ free_irq(MVME162_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+ free_irq(MVME162_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+ free_irq(MVME162_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+ free_irq(MVME162_IRQ_SCCA_TX, port);
+fail:
+ return error;
}
#endif
@@ -331,6 +407,7 @@ static int mvme162_scc_init(void)
static int bvme6000_scc_init(void)
{
struct scc_port *port;
+ int error;
printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
/* Init channel A */
@@ -340,14 +417,23 @@ static int bvme6000_scc_init(void)
port->datap = port->ctrlp + 4;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
"SCC-A TX", port);
- request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail;
+ error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-A status", port);
- request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_tx;
+ error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
"SCC-A RX", port);
- request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_stat;
+ error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-A special cond", port);
+ if (error)
+ goto fail_free_a_rx;
+
{
SCC_ACCESS_INIT(port);
@@ -367,14 +453,22 @@ static int bvme6000_scc_init(void)
port->datap = port->ctrlp + 4;
port->port_a = &scc_ports[0];
port->port_b = &scc_ports[1];
- request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+ error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
"SCC-B TX", port);
- request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_a_spcond;
+ error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
"SCC-B status", port);
- request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+ if (error)
+ goto fail_free_b_tx;
+ error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
"SCC-B RX", port);
- request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, IRQF_DISABLED,
- "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_stat;
+ error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
+ IRQF_DISABLED, "SCC-B special cond", port);
+ if (error)
+ goto fail_free_b_rx;
{
SCC_ACCESS_INIT(port); /* Either channel will do */
@@ -388,6 +482,23 @@ static int bvme6000_scc_init(void)
scc_init_drivers();
return 0;
+
+fail:
+ free_irq(BVME_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+ free_irq(BVME_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+ free_irq(BVME_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+ free_irq(BVME_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+ free_irq(BVME_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+ free_irq(BVME_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+ free_irq(BVME_IRQ_SCCB_SPCOND, port);
+fail_free_b_rx:
+ return error;
}
#endif
@@ -624,10 +735,10 @@ static void scc_enable_rx_interrupts(void *ptr)
}
-static int scc_get_CD(void *ptr)
+static int scc_carrier_raised(struct tty_port *port)
{
- struct scc_port *port = ptr;
- unsigned channel = port->channel;
+ struct scc_port *sc = container_of(port, struct scc_port, gs.port);
+ unsigned channel = sc->channel;
return !!(scc_last_status_reg[channel] & SR_DCD);
}
@@ -638,7 +749,7 @@ static void scc_shutdown_port(void *ptr)
struct scc_port *port = ptr;
port->gs.port.flags &= ~ GS_ACTIVE;
- if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) {
+ if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
scc_setsignals (port, 0, 0);
}
}
@@ -779,7 +890,7 @@ static void scc_setsignals(struct scc_port *port, int dtr, int rts)
static void scc_send_xchar(struct tty_struct *tty, char ch)
{
- struct scc_port *port = (struct scc_port *)tty->driver_data;
+ struct scc_port *port = tty->driver_data;
port->x_char = ch;
if (ch)
@@ -896,7 +1007,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
return retval;
}
- port->c_dcd = scc_get_CD (port);
+ port->c_dcd = tty_port_carrier_raised(&port->gs.port);
scc_enable_rx_interrupts(port);
@@ -906,7 +1017,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
static void scc_throttle (struct tty_struct * tty)
{
- struct scc_port *port = (struct scc_port *)tty->driver_data;
+ struct scc_port *port = tty->driver_data;
unsigned long flags;
SCC_ACCESS_INIT(port);
@@ -922,7 +1033,7 @@ static void scc_throttle (struct tty_struct * tty)
static void scc_unthrottle (struct tty_struct * tty)
{
- struct scc_port *port = (struct scc_port *)tty->driver_data;
+ struct scc_port *port = tty->driver_data;
unsigned long flags;
SCC_ACCESS_INIT(port);
@@ -945,7 +1056,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file,
static int scc_break_ctl(struct tty_struct *tty, int break_state)
{
- struct scc_port *port = (struct scc_port *)tty->driver_data;
+ struct scc_port *port = tty->driver_data;
unsigned long flags;
SCC_ACCESS_INIT(port);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 008176edbd64..7900bd63b36d 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -819,8 +819,8 @@ static inline int resize_screen(struct vc_data *vc, int width, int height,
* ctrl_lock of the tty IFF a tty is passed.
*/
-static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
- struct vc_data *vc, unsigned int cols, unsigned int lines)
+static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
+ unsigned int cols, unsigned int lines)
{
unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
unsigned int old_cols, old_rows, old_row_size, old_screen_size;
@@ -932,7 +932,7 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
ws.ws_row = vc->vc_rows;
ws.ws_col = vc->vc_cols;
ws.ws_ypixel = vc->vc_scan_lines;
- tty_do_resize(tty, real_tty, &ws);
+ tty_do_resize(tty, &ws);
}
if (CON_IS_VISIBLE(vc))
@@ -954,13 +954,12 @@ static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
{
- return vc_do_resize(vc->vc_tty, vc->vc_tty, vc, cols, rows);
+ return vc_do_resize(vc->vc_tty, vc, cols, rows);
}
/**
* vt_resize - resize a VT
* @tty: tty to resize
- * @real_tty: tty if a pty/tty pair
* @ws: winsize attributes
*
* Resize a virtual terminal. This is called by the tty layer as we
@@ -970,15 +969,13 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
* Takes the console sem and the called methods then take the tty
* termios_mutex and the tty ctrl_lock in that order.
*/
-
-int vt_resize(struct tty_struct *tty, struct tty_struct *real_tty,
- struct winsize *ws)
+static int vt_resize(struct tty_struct *tty, struct winsize *ws)
{
struct vc_data *vc = tty->driver_data;
int ret;
acquire_console_sem();
- ret = vc_do_resize(tty, real_tty, vc, ws->ws_col, ws->ws_row);
+ ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row);
release_console_sem();
return ret;
}
@@ -2679,7 +2676,7 @@ static int con_write_room(struct tty_struct *tty)
{
if (tty->stopped)
return 0;
- return 4096; /* No limit, really; we're not buffering */
+ return 32768; /* No limit, really; we're not buffering */
}
static int con_chars_in_buffer(struct tty_struct *tty)
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 8944ce508e2f..a2dee0eb6dad 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -366,7 +366,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
int vt_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
- struct vc_data *vc = (struct vc_data *)tty->driver_data;
+ struct vc_data *vc = tty->driver_data;
struct console_font_op op; /* used in multiple places here */
struct kbd_struct * kbd;
unsigned int console;
diff --git a/drivers/clocksource/tcb_clksrc.c b/drivers/clocksource/tcb_clksrc.c
index f450588e5858..254f1064d973 100644
--- a/drivers/clocksource/tcb_clksrc.c
+++ b/drivers/clocksource/tcb_clksrc.c
@@ -154,7 +154,6 @@ static struct tc_clkevt_device clkevt = {
.shift = 32,
/* Should be lower than at91rm9200's system timer */
.rating = 125,
- .cpumask = CPU_MASK_CPU0,
.set_next_event = tc_next_event,
.set_mode = tc_mode,
},
@@ -195,6 +194,7 @@ static void __init setup_clkevents(struct atmel_tc *tc, int clk32k_divisor_idx)
clkevt.clkevt.max_delta_ns
= clockevent_delta2ns(0xffff, &clkevt.clkevt);
clkevt.clkevt.min_delta_ns = clockevent_delta2ns(1, &clkevt.clkevt) + 1;
+ clkevt.clkevt.cpumask = cpumask_of(0);
setup_irq(irq, &tc_irqaction);
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 5f076aef74fa..a8c8d9c19d74 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -83,7 +83,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE
select CPU_FREQ_GOV_USERSPACE
help
Use the CPUFreq governor 'userspace' as default. This allows
- you to set the CPU frequency manually or when an userspace
+ you to set the CPU frequency manually or when a userspace
program shall be able to set the CPU dynamically without having
to enable the userspace governor manually.
@@ -138,7 +138,7 @@ config CPU_FREQ_GOV_USERSPACE
tristate "'userspace' governor for userspace frequency scaling"
help
Enable this cpufreq governor when you either want to set the
- CPU frequency manually or when an userspace program shall
+ CPU frequency manually or when a userspace program shall
be able to set the CPU dynamically, like on LART
<http://www.lartmaker.nl/>.
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 31d6f535a79d..b55cb67435bd 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -584,12 +584,12 @@ out:
return i;
}
-static ssize_t show_cpus(cpumask_t mask, char *buf)
+static ssize_t show_cpus(const struct cpumask *mask, char *buf)
{
ssize_t i = 0;
unsigned int cpu;
- for_each_cpu_mask_nr(cpu, mask) {
+ for_each_cpu(cpu, mask) {
if (i)
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
@@ -606,7 +606,7 @@ static ssize_t show_cpus(cpumask_t mask, char *buf)
*/
static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
{
- if (cpus_empty(policy->related_cpus))
+ if (cpumask_empty(policy->related_cpus))
return show_cpus(policy->cpus, buf);
return show_cpus(policy->related_cpus, buf);
}
@@ -754,6 +754,11 @@ static struct kobj_type ktype_cpufreq = {
.release = cpufreq_sysfs_release,
};
+static struct kobj_type ktype_empty_cpufreq = {
+ .sysfs_ops = &sysfs_ops,
+ .release = cpufreq_sysfs_release,
+};
+
/**
* cpufreq_add_dev - add a CPU device
@@ -801,9 +806,20 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
ret = -ENOMEM;
goto nomem_out;
}
+ if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) {
+ kfree(policy);
+ ret = -ENOMEM;
+ goto nomem_out;
+ }
+ if (!alloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) {
+ free_cpumask_var(policy->cpus);
+ kfree(policy);
+ ret = -ENOMEM;
+ goto nomem_out;
+ }
policy->cpu = cpu;
- policy->cpus = cpumask_of_cpu(cpu);
+ cpumask_copy(policy->cpus, cpumask_of(cpu));
/* Initially set CPU itself as the policy_cpu */
per_cpu(policy_cpu, cpu) = cpu;
@@ -822,8 +838,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
dprintk("initialization failed\n");
goto err_out;
}
- policy->user_policy.min = policy->cpuinfo.min_freq;
- policy->user_policy.max = policy->cpuinfo.max_freq;
+ policy->user_policy.min = policy->min;
+ policy->user_policy.max = policy->max;
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
CPUFREQ_START, policy);
@@ -838,7 +854,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
}
#endif
- for_each_cpu_mask_nr(j, policy->cpus) {
+ for_each_cpu(j, policy->cpus) {
if (cpu == j)
continue;
@@ -856,7 +872,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
goto err_out_driver_exit;
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- managed_policy->cpus = policy->cpus;
+ cpumask_copy(managed_policy->cpus, policy->cpus);
per_cpu(cpufreq_cpu_data, cpu) = managed_policy;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -876,39 +892,49 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
/* prepare interface data */
- ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
- "cpufreq");
- if (ret)
- goto err_out_driver_exit;
-
- /* set up files for this cpu device */
- drv_attr = cpufreq_driver->attr;
- while ((drv_attr) && (*drv_attr)) {
- ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+ if (!cpufreq_driver->hide_interface) {
+ ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
+ &sys_dev->kobj, "cpufreq");
if (ret)
goto err_out_driver_exit;
- drv_attr++;
- }
- if (cpufreq_driver->get) {
- ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
- if (ret)
- goto err_out_driver_exit;
- }
- if (cpufreq_driver->target) {
- ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+
+ /* set up files for this cpu device */
+ drv_attr = cpufreq_driver->attr;
+ while ((drv_attr) && (*drv_attr)) {
+ ret = sysfs_create_file(&policy->kobj,
+ &((*drv_attr)->attr));
+ if (ret)
+ goto err_out_driver_exit;
+ drv_attr++;
+ }
+ if (cpufreq_driver->get) {
+ ret = sysfs_create_file(&policy->kobj,
+ &cpuinfo_cur_freq.attr);
+ if (ret)
+ goto err_out_driver_exit;
+ }
+ if (cpufreq_driver->target) {
+ ret = sysfs_create_file(&policy->kobj,
+ &scaling_cur_freq.attr);
+ if (ret)
+ goto err_out_driver_exit;
+ }
+ } else {
+ ret = kobject_init_and_add(&policy->kobj, &ktype_empty_cpufreq,
+ &sys_dev->kobj, "cpufreq");
if (ret)
goto err_out_driver_exit;
}
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- for_each_cpu_mask_nr(j, policy->cpus) {
+ for_each_cpu(j, policy->cpus) {
per_cpu(cpufreq_cpu_data, j) = policy;
per_cpu(policy_cpu, j) = policy->cpu;
}
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
/* symlink affected CPUs */
- for_each_cpu_mask_nr(j, policy->cpus) {
+ for_each_cpu(j, policy->cpus) {
if (j == cpu)
continue;
if (!cpu_online(j))
@@ -948,7 +974,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
err_out_unregister:
spin_lock_irqsave(&cpufreq_driver_lock, flags);
- for_each_cpu_mask_nr(j, policy->cpus)
+ for_each_cpu(j, policy->cpus)
per_cpu(cpufreq_cpu_data, j) = NULL;
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -1009,7 +1035,7 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
*/
if (unlikely(cpu != data->cpu)) {
dprintk("removing link\n");
- cpu_clear(cpu, data->cpus);
+ cpumask_clear_cpu(cpu, data->cpus);
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
sysfs_remove_link(&sys_dev->kobj, "cpufreq");
cpufreq_cpu_put(data);
@@ -1030,8 +1056,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
* per_cpu(cpufreq_cpu_data) while holding the lock, and remove
* the sysfs links afterwards.
*/
- if (unlikely(cpus_weight(data->cpus) > 1)) {
- for_each_cpu_mask_nr(j, data->cpus) {
+ if (unlikely(cpumask_weight(data->cpus) > 1)) {
+ for_each_cpu(j, data->cpus) {
if (j == cpu)
continue;
per_cpu(cpufreq_cpu_data, j) = NULL;
@@ -1040,8 +1066,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
- if (unlikely(cpus_weight(data->cpus) > 1)) {
- for_each_cpu_mask_nr(j, data->cpus) {
+ if (unlikely(cpumask_weight(data->cpus) > 1)) {
+ for_each_cpu(j, data->cpus) {
if (j == cpu)
continue;
dprintk("removing link for cpu %u\n", j);
@@ -1075,7 +1101,10 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
if (cpufreq_driver->exit)
cpufreq_driver->exit(data);
+ free_cpumask_var(data->related_cpus);
+ free_cpumask_var(data->cpus);
kfree(data);
+ per_cpu(cpufreq_cpu_data, cpu) = NULL;
cpufreq_debug_enable_ratelimit();
return 0;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index e2657837d954..0320962c4ec5 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -498,7 +498,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
- for_each_cpu_mask_nr(j, policy->cpus) {
+ for_each_cpu(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 2ab3c12b88af..6a2b036c9389 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -400,7 +400,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
/* Get Absolute Load - in terms of freq */
max_load_freq = 0;
- for_each_cpu_mask_nr(j, policy->cpus) {
+ for_each_cpu(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
cputime64_t cur_wall_time, cur_idle_time;
unsigned int idle_time, wall_time;
@@ -568,7 +568,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return rc;
}
- for_each_cpu_mask_nr(j, policy->cpus) {
+ for_each_cpu(j, policy->cpus) {
struct cpu_dbs_info_s *j_dbs_info;
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 8d7cf3f31450..f1df59f59a37 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -15,12 +15,14 @@
#include <linux/tick.h>
#define BREAK_FUZZ 4 /* 4 us */
+#define PRED_HISTORY_PCT 50
struct menu_device {
int last_state_idx;
unsigned int expected_us;
unsigned int predicted_us;
+ unsigned int current_predicted_us;
unsigned int last_measured_us;
unsigned int elapsed_us;
};
@@ -47,6 +49,12 @@ static int menu_select(struct cpuidle_device *dev)
data->expected_us =
(u32) ktime_to_ns(tick_nohz_get_sleep_length()) / 1000;
+ /* Recalculate predicted_us based on prediction_history_pct */
+ data->predicted_us *= PRED_HISTORY_PCT;
+ data->predicted_us += (100 - PRED_HISTORY_PCT) *
+ data->current_predicted_us;
+ data->predicted_us /= 100;
+
/* find the deepest idle state that satisfies our constraints */
for (i = CPUIDLE_DRIVER_STATE_START + 1; i < dev->state_count; i++) {
struct cpuidle_state *s = &dev->states[i];
@@ -97,7 +105,7 @@ static void menu_reflect(struct cpuidle_device *dev)
measured_us = -1;
/* Predict time until next break event */
- data->predicted_us = max(measured_us, data->last_measured_us);
+ data->current_predicted_us = max(measured_us, data->last_measured_us);
if (last_idle_us + BREAK_FUZZ <
data->expected_us - target->exit_latency) {
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
index d883e1b8bb8c..33bd75347518 100644
--- a/drivers/dca/dca-core.c
+++ b/drivers/dca/dca-core.c
@@ -28,7 +28,7 @@
#include <linux/device.h>
#include <linux/dca.h>
-#define DCA_VERSION "1.4"
+#define DCA_VERSION "1.8"
MODULE_VERSION(DCA_VERSION);
MODULE_LICENSE("GPL");
@@ -60,16 +60,17 @@ int dca_add_requester(struct device *dev)
{
struct dca_provider *dca;
int err, slot = -ENODEV;
+ unsigned long flags;
if (!dev)
return -EFAULT;
- spin_lock(&dca_lock);
+ spin_lock_irqsave(&dca_lock, flags);
/* check if the requester has not been added already */
dca = dca_find_provider_by_dev(dev);
if (dca) {
- spin_unlock(&dca_lock);
+ spin_unlock_irqrestore(&dca_lock, flags);
return -EEXIST;
}
@@ -78,19 +79,21 @@ int dca_add_requester(struct device *dev)
if (slot >= 0)
break;
}
- if (slot < 0) {
- spin_unlock(&dca_lock);
+
+ spin_unlock_irqrestore(&dca_lock, flags);
+
+ if (slot < 0)
return slot;
- }
err = dca_sysfs_add_req(dca, dev, slot);
if (err) {
- dca->ops->remove_requester(dca, dev);
- spin_unlock(&dca_lock);
+ spin_lock_irqsave(&dca_lock, flags);
+ if (dca == dca_find_provider_by_dev(dev))
+ dca->ops->remove_requester(dca, dev);
+ spin_unlock_irqrestore(&dca_lock, flags);
return err;
}
- spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_add_requester);
@@ -103,25 +106,25 @@ int dca_remove_requester(struct device *dev)
{
struct dca_provider *dca;
int slot;
+ unsigned long flags;
if (!dev)
return -EFAULT;
- spin_lock(&dca_lock);
+ spin_lock_irqsave(&dca_lock, flags);
dca = dca_find_provider_by_dev(dev);
if (!dca) {
- spin_unlock(&dca_lock);
+ spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
slot = dca->ops->remove_requester(dca, dev);
- if (slot < 0) {
- spin_unlock(&dca_lock);
+ spin_unlock_irqrestore(&dca_lock, flags);
+
+ if (slot < 0)
return slot;
- }
dca_sysfs_remove_req(dca, slot);
- spin_unlock(&dca_lock);
return 0;
}
EXPORT_SYMBOL_GPL(dca_remove_requester);
@@ -135,17 +138,18 @@ u8 dca_common_get_tag(struct device *dev, int cpu)
{
struct dca_provider *dca;
u8 tag;
+ unsigned long flags;
- spin_lock(&dca_lock);
+ spin_lock_irqsave(&dca_lock, flags);
dca = dca_find_provider_by_dev(dev);
if (!dca) {
- spin_unlock(&dca_lock);
+ spin_unlock_irqrestore(&dca_lock, flags);
return -ENODEV;
}
tag = dca->ops->get_tag(dca, dev, cpu);
- spin_unlock(&dca_lock);
+ spin_unlock_irqrestore(&dca_lock, flags);
return tag;
}
@@ -217,11 +221,16 @@ static BLOCKING_NOTIFIER_HEAD(dca_provider_chain);
int register_dca_provider(struct dca_provider *dca, struct device *dev)
{
int err;
+ unsigned long flags;
err = dca_sysfs_add_provider(dca, dev);
if (err)
return err;
+
+ spin_lock_irqsave(&dca_lock, flags);
list_add(&dca->node, &dca_providers);
+ spin_unlock_irqrestore(&dca_lock, flags);
+
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_ADD, NULL);
return 0;
@@ -234,9 +243,15 @@ EXPORT_SYMBOL_GPL(register_dca_provider);
*/
void unregister_dca_provider(struct dca_provider *dca)
{
+ unsigned long flags;
+
blocking_notifier_call_chain(&dca_provider_chain,
DCA_PROVIDER_REMOVE, NULL);
+
+ spin_lock_irqsave(&dca_lock, flags);
list_del(&dca->node);
+ spin_unlock_irqrestore(&dca_lock, flags);
+
dca_sysfs_remove_provider(dca);
}
EXPORT_SYMBOL_GPL(unregister_dca_provider);
@@ -270,6 +285,6 @@ static void __exit dca_exit(void)
dca_sysfs_exit();
}
-subsys_initcall(dca_init);
+arch_initcall(dca_init);
module_exit(dca_exit);
diff --git a/drivers/dio/dio-sysfs.c b/drivers/dio/dio-sysfs.c
index f46463038847..ee1a3b59bd4e 100644
--- a/drivers/dio/dio-sysfs.c
+++ b/drivers/dio/dio-sysfs.c
@@ -58,20 +58,25 @@ static ssize_t dio_show_resource(struct device *dev, struct device_attribute *at
struct dio_dev *d = to_dio_dev(dev);
return sprintf(buf, "0x%08lx 0x%08lx 0x%08lx\n",
- dio_resource_start(d), dio_resource_end(d),
+ (unsigned long)dio_resource_start(d),
+ (unsigned long)dio_resource_end(d),
dio_resource_flags(d));
}
static DEVICE_ATTR(resource, S_IRUGO, dio_show_resource, NULL);
-void dio_create_sysfs_dev_files(struct dio_dev *d)
+int dio_create_sysfs_dev_files(struct dio_dev *d)
{
struct device *dev = &d->dev;
+ int error;
/* current configuration's attributes */
- device_create_file(dev, &dev_attr_id);
- device_create_file(dev, &dev_attr_ipl);
- device_create_file(dev, &dev_attr_secid);
- device_create_file(dev, &dev_attr_name);
- device_create_file(dev, &dev_attr_resource);
+ if ((error = device_create_file(dev, &dev_attr_id)) ||
+ (error = device_create_file(dev, &dev_attr_ipl)) ||
+ (error = device_create_file(dev, &dev_attr_secid)) ||
+ (error = device_create_file(dev, &dev_attr_name)) ||
+ (error = device_create_file(dev, &dev_attr_resource)))
+ return error;
+
+ return 0;
}
diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
index 07f274f853d9..10c3c498358c 100644
--- a/drivers/dio/dio.c
+++ b/drivers/dio/dio.c
@@ -173,6 +173,7 @@ static int __init dio_init(void)
mm_segment_t fs;
int i;
struct dio_dev *dev;
+ int error;
if (!MACH_IS_HP300)
return 0;
@@ -182,7 +183,11 @@ static int __init dio_init(void)
/* Initialize the DIO bus */
INIT_LIST_HEAD(&dio_bus.devices);
strcpy(dio_bus.dev.bus_id, "dio");
- device_register(&dio_bus.dev);
+ error = device_register(&dio_bus.dev);
+ if (error) {
+ pr_err("DIO: Error registering dio_bus\n");
+ return error;
+ }
/* Request all resources */
dio_bus.num_resources = (hp300_model == HP_320 ? 1 : 2);
@@ -252,8 +257,15 @@ static int __init dio_init(void)
if (scode >= DIOII_SCBASE)
iounmap(va);
- device_register(&dev->dev);
- dio_create_sysfs_dev_files(dev);
+ error = device_register(&dev->dev);
+ if (error) {
+ pr_err("DIO: Error registering device %s\n",
+ dev->name);
+ continue;
+ }
+ error = dio_create_sysfs_dev_files(dev);
+ if (error)
+ dev_err(&dev->dev, "Error creating sysfs files\n");
}
return 0;
}
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 904e57558bb5..48ea59e79672 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -33,7 +33,6 @@ config INTEL_IOATDMA
config INTEL_IOP_ADMA
tristate "Intel IOP ADMA support"
depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
- select ASYNC_CORE
select DMA_ENGINE
help
Enable support for the Intel(R) IOP Series RAID engines.
@@ -59,11 +58,29 @@ config FSL_DMA
config MV_XOR
bool "Marvell XOR engine support"
depends on PLAT_ORION
- select ASYNC_CORE
select DMA_ENGINE
---help---
Enable support for the Marvell XOR engine.
+config MX3_IPU
+ bool "MX3x Image Processing Unit support"
+ depends on ARCH_MX3
+ select DMA_ENGINE
+ default y
+ help
+ If you plan to use the Image Processing unit in the i.MX3x, say
+ Y here. If unsure, select Y.
+
+config MX3_IPU_IRQS
+ int "Number of dynamically mapped interrupts for IPU"
+ depends on MX3_IPU
+ range 2 137
+ default 4
+ help
+ Out of 137 interrupt sources on i.MX31 IPU only very few are used.
+ To avoid bloating the irq_desc[] array we allocate a sufficient
+ number of IRQ slots and map them dynamically to specific sources.
+
config DMA_ENGINE
bool
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 14f59527d4f6..2e5dc96700d2 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
obj-$(CONFIG_MV_XOR) += mv_xor.o
obj-$(CONFIG_DW_DMAC) += dw_dmac.o
+obj-$(CONFIG_MX3_IPU) += ipu/
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 657996517374..a58993011edb 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -31,32 +31,18 @@
*
* LOCKING:
*
- * The subsystem keeps two global lists, dma_device_list and dma_client_list.
- * Both of these are protected by a mutex, dma_list_mutex.
+ * The subsystem keeps a global list of dma_device structs it is protected by a
+ * mutex, dma_list_mutex.
+ *
+ * A subsystem can get access to a channel by calling dmaengine_get() followed
+ * by dma_find_channel(), or if it has need for an exclusive channel it can call
+ * dma_request_channel(). Once a channel is allocated a reference is taken
+ * against its corresponding driver to disable removal.
*
* Each device has a channels list, which runs unlocked but is never modified
* once the device is registered, it's just setup by the driver.
*
- * Each client is responsible for keeping track of the channels it uses. See
- * the definition of dma_event_callback in dmaengine.h.
- *
- * Each device has a kref, which is initialized to 1 when the device is
- * registered. A kref_get is done for each device registered. When the
- * device is released, the corresponding kref_put is done in the release
- * method. Every time one of the device's channels is allocated to a client,
- * a kref_get occurs. When the channel is freed, the corresponding kref_put
- * happens. The device's release function does a completion, so
- * unregister_device does a remove event, device_unregister, a kref_put
- * for the first reference, then waits on the completion for all other
- * references to finish.
- *
- * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
- * with a kref and a per_cpu local_t. A dma_chan_get is called when a client
- * signals that it wants to use a channel, and dma_chan_put is called when
- * a channel is removed or a client using it is unregistered. A client can
- * take extra references per outstanding transaction, as is the case with
- * the NET DMA client. The release function does a kref_put on the device.
- * -ChrisL, DanW
+ * See Documentation/dmaengine.txt for more details
*/
#include <linux/init.h>
@@ -70,54 +56,85 @@
#include <linux/rcupdate.h>
#include <linux/mutex.h>
#include <linux/jiffies.h>
+#include <linux/rculist.h>
+#include <linux/idr.h>
static DEFINE_MUTEX(dma_list_mutex);
static LIST_HEAD(dma_device_list);
-static LIST_HEAD(dma_client_list);
+static long dmaengine_ref_count;
+static struct idr dma_idr;
/* --- sysfs implementation --- */
+/**
+ * dev_to_dma_chan - convert a device pointer to the its sysfs container object
+ * @dev - device node
+ *
+ * Must be called under dma_list_mutex
+ */
+static struct dma_chan *dev_to_dma_chan(struct device *dev)
+{
+ struct dma_chan_dev *chan_dev;
+
+ chan_dev = container_of(dev, typeof(*chan_dev), device);
+ return chan_dev->chan;
+}
+
static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct dma_chan *chan = to_dma_chan(dev);
+ struct dma_chan *chan;
unsigned long count = 0;
int i;
+ int err;
- for_each_possible_cpu(i)
- count += per_cpu_ptr(chan->local, i)->memcpy_count;
+ mutex_lock(&dma_list_mutex);
+ chan = dev_to_dma_chan(dev);
+ if (chan) {
+ for_each_possible_cpu(i)
+ count += per_cpu_ptr(chan->local, i)->memcpy_count;
+ err = sprintf(buf, "%lu\n", count);
+ } else
+ err = -ENODEV;
+ mutex_unlock(&dma_list_mutex);
- return sprintf(buf, "%lu\n", count);
+ return err;
}
static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct dma_chan *chan = to_dma_chan(dev);
+ struct dma_chan *chan;
unsigned long count = 0;
int i;
+ int err;
- for_each_possible_cpu(i)
- count += per_cpu_ptr(chan->local, i)->bytes_transferred;
+ mutex_lock(&dma_list_mutex);
+ chan = dev_to_dma_chan(dev);
+ if (chan) {
+ for_each_possible_cpu(i)
+ count += per_cpu_ptr(chan->local, i)->bytes_transferred;
+ err = sprintf(buf, "%lu\n", count);
+ } else
+ err = -ENODEV;
+ mutex_unlock(&dma_list_mutex);
- return sprintf(buf, "%lu\n", count);
+ return err;
}
static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct dma_chan *chan = to_dma_chan(dev);
- int in_use = 0;
-
- if (unlikely(chan->slow_ref) &&
- atomic_read(&chan->refcount.refcount) > 1)
- in_use = 1;
- else {
- if (local_read(&(per_cpu_ptr(chan->local,
- get_cpu())->refcount)) > 0)
- in_use = 1;
- put_cpu();
- }
+ struct dma_chan *chan;
+ int err;
- return sprintf(buf, "%d\n", in_use);
+ mutex_lock(&dma_list_mutex);
+ chan = dev_to_dma_chan(dev);
+ if (chan)
+ err = sprintf(buf, "%d\n", chan->client_count);
+ else
+ err = -ENODEV;
+ mutex_unlock(&dma_list_mutex);
+
+ return err;
}
static struct device_attribute dma_attrs[] = {
@@ -127,76 +144,110 @@ static struct device_attribute dma_attrs[] = {
__ATTR_NULL
};
-static void dma_async_device_cleanup(struct kref *kref);
-
-static void dma_dev_release(struct device *dev)
+static void chan_dev_release(struct device *dev)
{
- struct dma_chan *chan = to_dma_chan(dev);
- kref_put(&chan->device->refcount, dma_async_device_cleanup);
+ struct dma_chan_dev *chan_dev;
+
+ chan_dev = container_of(dev, typeof(*chan_dev), device);
+ if (atomic_dec_and_test(chan_dev->idr_ref)) {
+ mutex_lock(&dma_list_mutex);
+ idr_remove(&dma_idr, chan_dev->dev_id);
+ mutex_unlock(&dma_list_mutex);
+ kfree(chan_dev->idr_ref);
+ }
+ kfree(chan_dev);
}
static struct class dma_devclass = {
.name = "dma",
.dev_attrs = dma_attrs,
- .dev_release = dma_dev_release,
+ .dev_release = chan_dev_release,
};
/* --- client and device registration --- */
-#define dma_chan_satisfies_mask(chan, mask) \
- __dma_chan_satisfies_mask((chan), &(mask))
+#define dma_device_satisfies_mask(device, mask) \
+ __dma_device_satisfies_mask((device), &(mask))
static int
-__dma_chan_satisfies_mask(struct dma_chan *chan, dma_cap_mask_t *want)
+__dma_device_satisfies_mask(struct dma_device *device, dma_cap_mask_t *want)
{
dma_cap_mask_t has;
- bitmap_and(has.bits, want->bits, chan->device->cap_mask.bits,
+ bitmap_and(has.bits, want->bits, device->cap_mask.bits,
DMA_TX_TYPE_END);
return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END);
}
+static struct module *dma_chan_to_owner(struct dma_chan *chan)
+{
+ return chan->device->dev->driver->owner;
+}
+
/**
- * dma_client_chan_alloc - try to allocate channels to a client
- * @client: &dma_client
+ * balance_ref_count - catch up the channel reference count
+ * @chan - channel to balance ->client_count versus dmaengine_ref_count
*
- * Called with dma_list_mutex held.
+ * balance_ref_count must be called under dma_list_mutex
*/
-static void dma_client_chan_alloc(struct dma_client *client)
+static void balance_ref_count(struct dma_chan *chan)
{
- struct dma_device *device;
- struct dma_chan *chan;
- int desc; /* allocated descriptor count */
- enum dma_state_client ack;
+ struct module *owner = dma_chan_to_owner(chan);
- /* Find a channel */
- list_for_each_entry(device, &dma_device_list, global_node) {
- /* Does the client require a specific DMA controller? */
- if (client->slave && client->slave->dma_dev
- && client->slave->dma_dev != device->dev)
- continue;
+ while (chan->client_count < dmaengine_ref_count) {
+ __module_get(owner);
+ chan->client_count++;
+ }
+}
- list_for_each_entry(chan, &device->channels, device_node) {
- if (!dma_chan_satisfies_mask(chan, client->cap_mask))
- continue;
+/**
+ * dma_chan_get - try to grab a dma channel's parent driver module
+ * @chan - channel to grab
+ *
+ * Must be called under dma_list_mutex
+ */
+static int dma_chan_get(struct dma_chan *chan)
+{
+ int err = -ENODEV;
+ struct module *owner = dma_chan_to_owner(chan);
+
+ if (chan->client_count) {
+ __module_get(owner);
+ err = 0;
+ } else if (try_module_get(owner))
+ err = 0;
+
+ if (err == 0)
+ chan->client_count++;
+
+ /* allocate upon first client reference */
+ if (chan->client_count == 1 && err == 0) {
+ int desc_cnt = chan->device->device_alloc_chan_resources(chan);
+
+ if (desc_cnt < 0) {
+ err = desc_cnt;
+ chan->client_count = 0;
+ module_put(owner);
+ } else if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask))
+ balance_ref_count(chan);
+ }
- desc = chan->device->device_alloc_chan_resources(
- chan, client);
- if (desc >= 0) {
- ack = client->event_callback(client,
- chan,
- DMA_RESOURCE_AVAILABLE);
+ return err;
+}
- /* we are done once this client rejects
- * an available resource
- */
- if (ack == DMA_ACK) {
- dma_chan_get(chan);
- chan->client_count++;
- } else if (ack == DMA_NAK)
- return;
- }
- }
- }
+/**
+ * dma_chan_put - drop a reference to a dma channel's parent driver module
+ * @chan - channel to release
+ *
+ * Must be called under dma_list_mutex
+ */
+static void dma_chan_put(struct dma_chan *chan)
+{
+ if (!chan->client_count)
+ return; /* this channel failed alloc_chan_resources */
+ chan->client_count--;
+ module_put(dma_chan_to_owner(chan));
+ if (chan->client_count == 0)
+ chan->device->device_free_chan_resources(chan);
}
enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
@@ -218,138 +269,336 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
EXPORT_SYMBOL(dma_sync_wait);
/**
- * dma_chan_cleanup - release a DMA channel's resources
- * @kref: kernel reference structure that contains the DMA channel device
+ * dma_cap_mask_all - enable iteration over all operation types
+ */
+static dma_cap_mask_t dma_cap_mask_all;
+
+/**
+ * dma_chan_tbl_ent - tracks channel allocations per core/operation
+ * @chan - associated channel for this entry
+ */
+struct dma_chan_tbl_ent {
+ struct dma_chan *chan;
+};
+
+/**
+ * channel_table - percpu lookup table for memory-to-memory offload providers
*/
-void dma_chan_cleanup(struct kref *kref)
+static struct dma_chan_tbl_ent *channel_table[DMA_TX_TYPE_END];
+
+static int __init dma_channel_table_init(void)
{
- struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
- chan->device->device_free_chan_resources(chan);
- kref_put(&chan->device->refcount, dma_async_device_cleanup);
+ enum dma_transaction_type cap;
+ int err = 0;
+
+ bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
+
+ /* 'interrupt', 'private', and 'slave' are channel capabilities,
+ * but are not associated with an operation so they do not need
+ * an entry in the channel_table
+ */
+ clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
+ clear_bit(DMA_PRIVATE, dma_cap_mask_all.bits);
+ clear_bit(DMA_SLAVE, dma_cap_mask_all.bits);
+
+ for_each_dma_cap_mask(cap, dma_cap_mask_all) {
+ channel_table[cap] = alloc_percpu(struct dma_chan_tbl_ent);
+ if (!channel_table[cap]) {
+ err = -ENOMEM;
+ break;
+ }
+ }
+
+ if (err) {
+ pr_err("dmaengine: initialization failure\n");
+ for_each_dma_cap_mask(cap, dma_cap_mask_all)
+ if (channel_table[cap])
+ free_percpu(channel_table[cap]);
+ }
+
+ return err;
}
-EXPORT_SYMBOL(dma_chan_cleanup);
+arch_initcall(dma_channel_table_init);
-static void dma_chan_free_rcu(struct rcu_head *rcu)
+/**
+ * dma_find_channel - find a channel to carry out the operation
+ * @tx_type: transaction type
+ */
+struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type)
{
- struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu);
- int bias = 0x7FFFFFFF;
- int i;
- for_each_possible_cpu(i)
- bias -= local_read(&per_cpu_ptr(chan->local, i)->refcount);
- atomic_sub(bias, &chan->refcount.refcount);
- kref_put(&chan->refcount, dma_chan_cleanup);
+ struct dma_chan *chan;
+ int cpu;
+
+ cpu = get_cpu();
+ chan = per_cpu_ptr(channel_table[tx_type], cpu)->chan;
+ put_cpu();
+
+ return chan;
}
+EXPORT_SYMBOL(dma_find_channel);
-static void dma_chan_release(struct dma_chan *chan)
+/**
+ * dma_issue_pending_all - flush all pending operations across all channels
+ */
+void dma_issue_pending_all(void)
{
- atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
- chan->slow_ref = 1;
- call_rcu(&chan->rcu, dma_chan_free_rcu);
+ struct dma_device *device;
+ struct dma_chan *chan;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(device, &dma_device_list, global_node) {
+ if (dma_has_cap(DMA_PRIVATE, device->cap_mask))
+ continue;
+ list_for_each_entry(chan, &device->channels, device_node)
+ if (chan->client_count)
+ device->device_issue_pending(chan);
+ }
+ rcu_read_unlock();
}
+EXPORT_SYMBOL(dma_issue_pending_all);
/**
- * dma_chans_notify_available - broadcast available channels to the clients
+ * nth_chan - returns the nth channel of the given capability
+ * @cap: capability to match
+ * @n: nth channel desired
+ *
+ * Defaults to returning the channel with the desired capability and the
+ * lowest reference count when 'n' cannot be satisfied. Must be called
+ * under dma_list_mutex.
*/
-static void dma_clients_notify_available(void)
+static struct dma_chan *nth_chan(enum dma_transaction_type cap, int n)
{
- struct dma_client *client;
+ struct dma_device *device;
+ struct dma_chan *chan;
+ struct dma_chan *ret = NULL;
+ struct dma_chan *min = NULL;
- mutex_lock(&dma_list_mutex);
+ list_for_each_entry(device, &dma_device_list, global_node) {
+ if (!dma_has_cap(cap, device->cap_mask) ||
+ dma_has_cap(DMA_PRIVATE, device->cap_mask))
+ continue;
+ list_for_each_entry(chan, &device->channels, device_node) {
+ if (!chan->client_count)
+ continue;
+ if (!min)
+ min = chan;
+ else if (chan->table_count < min->table_count)
+ min = chan;
+
+ if (n-- == 0) {
+ ret = chan;
+ break; /* done */
+ }
+ }
+ if (ret)
+ break; /* done */
+ }
- list_for_each_entry(client, &dma_client_list, global_node)
- dma_client_chan_alloc(client);
+ if (!ret)
+ ret = min;
- mutex_unlock(&dma_list_mutex);
+ if (ret)
+ ret->table_count++;
+
+ return ret;
}
/**
- * dma_chans_notify_available - tell the clients that a channel is going away
- * @chan: channel on its way out
+ * dma_channel_rebalance - redistribute the available channels
+ *
+ * Optimize for cpu isolation (each cpu gets a dedicated channel for an
+ * operation type) in the SMP case, and operation isolation (avoid
+ * multi-tasking channels) in the non-SMP case. Must be called under
+ * dma_list_mutex.
*/
-static void dma_clients_notify_removed(struct dma_chan *chan)
+static void dma_channel_rebalance(void)
{
- struct dma_client *client;
- enum dma_state_client ack;
+ struct dma_chan *chan;
+ struct dma_device *device;
+ int cpu;
+ int cap;
+ int n;
- mutex_lock(&dma_list_mutex);
+ /* undo the last distribution */
+ for_each_dma_cap_mask(cap, dma_cap_mask_all)
+ for_each_possible_cpu(cpu)
+ per_cpu_ptr(channel_table[cap], cpu)->chan = NULL;
- list_for_each_entry(client, &dma_client_list, global_node) {
- ack = client->event_callback(client, chan,
- DMA_RESOURCE_REMOVED);
+ list_for_each_entry(device, &dma_device_list, global_node) {
+ if (dma_has_cap(DMA_PRIVATE, device->cap_mask))
+ continue;
+ list_for_each_entry(chan, &device->channels, device_node)
+ chan->table_count = 0;
+ }
- /* client was holding resources for this channel so
- * free it
- */
- if (ack == DMA_ACK) {
- dma_chan_put(chan);
- chan->client_count--;
+ /* don't populate the channel_table if no clients are available */
+ if (!dmaengine_ref_count)
+ return;
+
+ /* redistribute available channels */
+ n = 0;
+ for_each_dma_cap_mask(cap, dma_cap_mask_all)
+ for_each_online_cpu(cpu) {
+ if (num_possible_cpus() > 1)
+ chan = nth_chan(cap, n++);
+ else
+ chan = nth_chan(cap, -1);
+
+ per_cpu_ptr(channel_table[cap], cpu)->chan = chan;
+ }
+}
+
+static struct dma_chan *private_candidate(dma_cap_mask_t *mask, struct dma_device *dev,
+ dma_filter_fn fn, void *fn_param)
+{
+ struct dma_chan *chan;
+
+ if (!__dma_device_satisfies_mask(dev, mask)) {
+ pr_debug("%s: wrong capabilities\n", __func__);
+ return NULL;
+ }
+ /* devices with multiple channels need special handling as we need to
+ * ensure that all channels are either private or public.
+ */
+ if (dev->chancnt > 1 && !dma_has_cap(DMA_PRIVATE, dev->cap_mask))
+ list_for_each_entry(chan, &dev->channels, device_node) {
+ /* some channels are already publicly allocated */
+ if (chan->client_count)
+ return NULL;
+ }
+
+ list_for_each_entry(chan, &dev->channels, device_node) {
+ if (chan->client_count) {
+ pr_debug("%s: %s busy\n",
+ __func__, dma_chan_name(chan));
+ continue;
+ }
+ if (fn && !fn(chan, fn_param)) {
+ pr_debug("%s: %s filter said false\n",
+ __func__, dma_chan_name(chan));
+ continue;
}
+ return chan;
}
- mutex_unlock(&dma_list_mutex);
+ return NULL;
}
/**
- * dma_async_client_register - register a &dma_client
- * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask'
+ * dma_request_channel - try to allocate an exclusive channel
+ * @mask: capabilities that the channel must satisfy
+ * @fn: optional callback to disposition available channels
+ * @fn_param: opaque parameter to pass to dma_filter_fn
*/
-void dma_async_client_register(struct dma_client *client)
+struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param)
{
- /* validate client data */
- BUG_ON(dma_has_cap(DMA_SLAVE, client->cap_mask) &&
- !client->slave);
+ struct dma_device *device, *_d;
+ struct dma_chan *chan = NULL;
+ int err;
+
+ /* Find a channel */
+ mutex_lock(&dma_list_mutex);
+ list_for_each_entry_safe(device, _d, &dma_device_list, global_node) {
+ chan = private_candidate(mask, device, fn, fn_param);
+ if (chan) {
+ /* Found a suitable channel, try to grab, prep, and
+ * return it. We first set DMA_PRIVATE to disable
+ * balance_ref_count as this channel will not be
+ * published in the general-purpose allocator
+ */
+ dma_cap_set(DMA_PRIVATE, device->cap_mask);
+ err = dma_chan_get(chan);
+
+ if (err == -ENODEV) {
+ pr_debug("%s: %s module removed\n", __func__,
+ dma_chan_name(chan));
+ list_del_rcu(&device->global_node);
+ } else if (err)
+ pr_err("dmaengine: failed to get %s: (%d)\n",
+ dma_chan_name(chan), err);
+ else
+ break;
+ chan = NULL;
+ }
+ }
+ mutex_unlock(&dma_list_mutex);
+
+ pr_debug("%s: %s (%s)\n", __func__, chan ? "success" : "fail",
+ chan ? dma_chan_name(chan) : NULL);
+ return chan;
+}
+EXPORT_SYMBOL_GPL(__dma_request_channel);
+
+void dma_release_channel(struct dma_chan *chan)
+{
mutex_lock(&dma_list_mutex);
- list_add_tail(&client->global_node, &dma_client_list);
+ WARN_ONCE(chan->client_count != 1,
+ "chan reference count %d != 1\n", chan->client_count);
+ dma_chan_put(chan);
mutex_unlock(&dma_list_mutex);
}
-EXPORT_SYMBOL(dma_async_client_register);
+EXPORT_SYMBOL_GPL(dma_release_channel);
/**
- * dma_async_client_unregister - unregister a client and free the &dma_client
- * @client: &dma_client to free
- *
- * Force frees any allocated DMA channels, frees the &dma_client memory
+ * dmaengine_get - register interest in dma_channels
*/
-void dma_async_client_unregister(struct dma_client *client)
+void dmaengine_get(void)
{
- struct dma_device *device;
+ struct dma_device *device, *_d;
struct dma_chan *chan;
- enum dma_state_client ack;
-
- if (!client)
- return;
+ int err;
mutex_lock(&dma_list_mutex);
- /* free all channels the client is holding */
- list_for_each_entry(device, &dma_device_list, global_node)
- list_for_each_entry(chan, &device->channels, device_node) {
- ack = client->event_callback(client, chan,
- DMA_RESOURCE_REMOVED);
+ dmaengine_ref_count++;
- if (ack == DMA_ACK) {
- dma_chan_put(chan);
- chan->client_count--;
- }
+ /* try to grab channels */
+ list_for_each_entry_safe(device, _d, &dma_device_list, global_node) {
+ if (dma_has_cap(DMA_PRIVATE, device->cap_mask))
+ continue;
+ list_for_each_entry(chan, &device->channels, device_node) {
+ err = dma_chan_get(chan);
+ if (err == -ENODEV) {
+ /* module removed before we could use it */
+ list_del_rcu(&device->global_node);
+ break;
+ } else if (err)
+ pr_err("dmaengine: failed to get %s: (%d)\n",
+ dma_chan_name(chan), err);
}
+ }
- list_del(&client->global_node);
+ /* if this is the first reference and there were channels
+ * waiting we need to rebalance to get those channels
+ * incorporated into the channel table
+ */
+ if (dmaengine_ref_count == 1)
+ dma_channel_rebalance();
mutex_unlock(&dma_list_mutex);
}
-EXPORT_SYMBOL(dma_async_client_unregister);
+EXPORT_SYMBOL(dmaengine_get);
/**
- * dma_async_client_chan_request - send all available channels to the
- * client that satisfy the capability mask
- * @client - requester
+ * dmaengine_put - let dma drivers be removed when ref_count == 0
*/
-void dma_async_client_chan_request(struct dma_client *client)
+void dmaengine_put(void)
{
+ struct dma_device *device;
+ struct dma_chan *chan;
+
mutex_lock(&dma_list_mutex);
- dma_client_chan_alloc(client);
+ dmaengine_ref_count--;
+ BUG_ON(dmaengine_ref_count < 0);
+ /* drop channel references */
+ list_for_each_entry(device, &dma_device_list, global_node) {
+ if (dma_has_cap(DMA_PRIVATE, device->cap_mask))
+ continue;
+ list_for_each_entry(chan, &device->channels, device_node)
+ dma_chan_put(chan);
+ }
mutex_unlock(&dma_list_mutex);
}
-EXPORT_SYMBOL(dma_async_client_chan_request);
+EXPORT_SYMBOL(dmaengine_put);
/**
* dma_async_device_register - registers DMA devices found
@@ -357,9 +606,9 @@ EXPORT_SYMBOL(dma_async_client_chan_request);
*/
int dma_async_device_register(struct dma_device *device)
{
- static int id;
int chancnt = 0, rc;
struct dma_chan* chan;
+ atomic_t *idr_ref;
if (!device)
return -ENODEV;
@@ -386,57 +635,83 @@ int dma_async_device_register(struct dma_device *device)
BUG_ON(!device->device_issue_pending);
BUG_ON(!device->dev);
- init_completion(&device->done);
- kref_init(&device->refcount);
-
+ idr_ref = kmalloc(sizeof(*idr_ref), GFP_KERNEL);
+ if (!idr_ref)
+ return -ENOMEM;
+ atomic_set(idr_ref, 0);
+ idr_retry:
+ if (!idr_pre_get(&dma_idr, GFP_KERNEL))
+ return -ENOMEM;
mutex_lock(&dma_list_mutex);
- device->dev_id = id++;
+ rc = idr_get_new(&dma_idr, NULL, &device->dev_id);
mutex_unlock(&dma_list_mutex);
+ if (rc == -EAGAIN)
+ goto idr_retry;
+ else if (rc != 0)
+ return rc;
/* represent channels in sysfs. Probably want devs too */
list_for_each_entry(chan, &device->channels, device_node) {
chan->local = alloc_percpu(typeof(*chan->local));
if (chan->local == NULL)
continue;
+ chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL);
+ if (chan->dev == NULL) {
+ free_percpu(chan->local);
+ continue;
+ }
chan->chan_id = chancnt++;
- chan->dev.class = &dma_devclass;
- chan->dev.parent = device->dev;
- dev_set_name(&chan->dev, "dma%dchan%d",
+ chan->dev->device.class = &dma_devclass;
+ chan->dev->device.parent = device->dev;
+ chan->dev->chan = chan;
+ chan->dev->idr_ref = idr_ref;
+ chan->dev->dev_id = device->dev_id;
+ atomic_inc(idr_ref);
+ dev_set_name(&chan->dev->device, "dma%dchan%d",
device->dev_id, chan->chan_id);
- rc = device_register(&chan->dev);
+ rc = device_register(&chan->dev->device);
if (rc) {
- chancnt--;
free_percpu(chan->local);
chan->local = NULL;
goto err_out;
}
-
- /* One for the channel, one of the class device */
- kref_get(&device->refcount);
- kref_get(&device->refcount);
- kref_init(&chan->refcount);
chan->client_count = 0;
- chan->slow_ref = 0;
- INIT_RCU_HEAD(&chan->rcu);
}
+ device->chancnt = chancnt;
mutex_lock(&dma_list_mutex);
- list_add_tail(&device->global_node, &dma_device_list);
+ /* take references on public channels */
+ if (dmaengine_ref_count && !dma_has_cap(DMA_PRIVATE, device->cap_mask))
+ list_for_each_entry(chan, &device->channels, device_node) {
+ /* if clients are already waiting for channels we need
+ * to take references on their behalf
+ */
+ if (dma_chan_get(chan) == -ENODEV) {
+ /* note we can only get here for the first
+ * channel as the remaining channels are
+ * guaranteed to get a reference
+ */
+ rc = -ENODEV;
+ mutex_unlock(&dma_list_mutex);
+ goto err_out;
+ }
+ }
+ list_add_tail_rcu(&device->global_node, &dma_device_list);
+ dma_channel_rebalance();
mutex_unlock(&dma_list_mutex);
- dma_clients_notify_available();
-
return 0;
err_out:
list_for_each_entry(chan, &device->channels, device_node) {
if (chan->local == NULL)
continue;
- kref_put(&device->refcount, dma_async_device_cleanup);
- device_unregister(&chan->dev);
- chancnt--;
+ mutex_lock(&dma_list_mutex);
+ chan->dev->chan = NULL;
+ mutex_unlock(&dma_list_mutex);
+ device_unregister(&chan->dev->device);
free_percpu(chan->local);
}
return rc;
@@ -444,37 +719,30 @@ err_out:
EXPORT_SYMBOL(dma_async_device_register);
/**
- * dma_async_device_cleanup - function called when all references are released
- * @kref: kernel reference object
- */
-static void dma_async_device_cleanup(struct kref *kref)
-{
- struct dma_device *device;
-
- device = container_of(kref, struct dma_device, refcount);
- complete(&device->done);
-}
-
-/**
- * dma_async_device_unregister - unregisters DMA devices
+ * dma_async_device_unregister - unregister a DMA device
* @device: &dma_device
+ *
+ * This routine is called by dma driver exit routines, dmaengine holds module
+ * references to prevent it being called while channels are in use.
*/
void dma_async_device_unregister(struct dma_device *device)
{
struct dma_chan *chan;
mutex_lock(&dma_list_mutex);
- list_del(&device->global_node);
+ list_del_rcu(&device->global_node);
+ dma_channel_rebalance();
mutex_unlock(&dma_list_mutex);
list_for_each_entry(chan, &device->channels, device_node) {
- dma_clients_notify_removed(chan);
- device_unregister(&chan->dev);
- dma_chan_release(chan);
+ WARN_ONCE(chan->client_count,
+ "%s called while %d clients hold a reference\n",
+ __func__, chan->client_count);
+ mutex_lock(&dma_list_mutex);
+ chan->dev->chan = NULL;
+ mutex_unlock(&dma_list_mutex);
+ device_unregister(&chan->dev->device);
}
-
- kref_put(&device->refcount, dma_async_device_cleanup);
- wait_for_completion(&device->done);
}
EXPORT_SYMBOL(dma_async_device_unregister);
@@ -626,10 +894,98 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
}
EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+/* dma_wait_for_async_tx - spin wait for a transaction to complete
+ * @tx: in-flight transaction to wait on
+ *
+ * This routine assumes that tx was obtained from a call to async_memcpy,
+ * async_xor, async_memset, etc which ensures that tx is "in-flight" (prepped
+ * and submitted). Walking the parent chain is only meant to cover for DMA
+ * drivers that do not implement the DMA_INTERRUPT capability and may race with
+ * the driver's descriptor cleanup routine.
+ */
+enum dma_status
+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+{
+ enum dma_status status;
+ struct dma_async_tx_descriptor *iter;
+ struct dma_async_tx_descriptor *parent;
+
+ if (!tx)
+ return DMA_SUCCESS;
+
+ WARN_ONCE(tx->parent, "%s: speculatively walking dependency chain for"
+ " %s\n", __func__, dma_chan_name(tx->chan));
+
+ /* poll through the dependency chain, return when tx is complete */
+ do {
+ iter = tx;
+
+ /* find the root of the unsubmitted dependency chain */
+ do {
+ parent = iter->parent;
+ if (!parent)
+ break;
+ else
+ iter = parent;
+ } while (parent);
+
+ /* there is a small window for ->parent == NULL and
+ * ->cookie == -EBUSY
+ */
+ while (iter->cookie == -EBUSY)
+ cpu_relax();
+
+ status = dma_sync_wait(iter->chan, iter->cookie);
+ } while (status == DMA_IN_PROGRESS || (iter != tx));
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
+
+/* dma_run_dependencies - helper routine for dma drivers to process
+ * (start) dependent operations on their target channel
+ * @tx: transaction with dependencies
+ */
+void dma_run_dependencies(struct dma_async_tx_descriptor *tx)
+{
+ struct dma_async_tx_descriptor *dep = tx->next;
+ struct dma_async_tx_descriptor *dep_next;
+ struct dma_chan *chan;
+
+ if (!dep)
+ return;
+
+ /* we'll submit tx->next now, so clear the link */
+ tx->next = NULL;
+ chan = dep->chan;
+
+ /* keep submitting up until a channel switch is detected
+ * in that case we will be called again as a result of
+ * processing the interrupt from async_tx_channel_switch
+ */
+ for (; dep; dep = dep_next) {
+ spin_lock_bh(&dep->lock);
+ dep->parent = NULL;
+ dep_next = dep->next;
+ if (dep_next && dep_next->chan == chan)
+ dep->next = NULL; /* ->next will be submitted */
+ else
+ dep_next = NULL; /* submit current dep and terminate */
+ spin_unlock_bh(&dep->lock);
+
+ dep->tx_submit(dep);
+ }
+
+ chan->device->device_issue_pending(chan);
+}
+EXPORT_SYMBOL_GPL(dma_run_dependencies);
+
static int __init dma_bus_init(void)
{
+ idr_init(&dma_idr);
mutex_init(&dma_list_mutex);
return class_register(&dma_devclass);
}
-subsys_initcall(dma_bus_init);
+arch_initcall(dma_bus_init);
+
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index ed9636bfb54a..732fa1ec36ab 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -35,7 +35,7 @@ MODULE_PARM_DESC(threads_per_chan,
static unsigned int max_channels;
module_param(max_channels, uint, S_IRUGO);
-MODULE_PARM_DESC(nr_channels,
+MODULE_PARM_DESC(max_channels,
"Maximum number of channels to use (default: all)");
/*
@@ -71,7 +71,7 @@ struct dmatest_chan {
/*
* These are protected by dma_list_mutex since they're only used by
- * the DMA client event callback
+ * the DMA filter function callback
*/
static LIST_HEAD(dmatest_channels);
static unsigned int nr_channels;
@@ -80,7 +80,7 @@ static bool dmatest_match_channel(struct dma_chan *chan)
{
if (test_channel[0] == '\0')
return true;
- return strcmp(dev_name(&chan->dev), test_channel) == 0;
+ return strcmp(dma_chan_name(chan), test_channel) == 0;
}
static bool dmatest_match_device(struct dma_device *device)
@@ -215,9 +215,12 @@ static int dmatest_func(void *data)
smp_rmb();
chan = thread->chan;
- dma_chan_get(chan);
while (!kthread_should_stop()) {
+ struct dma_device *dev = chan->device;
+ struct dma_async_tx_descriptor *tx;
+ dma_addr_t dma_src, dma_dest;
+
total_tests++;
len = dmatest_random() % test_buf_size + 1;
@@ -227,10 +230,30 @@ static int dmatest_func(void *data)
dmatest_init_srcbuf(thread->srcbuf, src_off, len);
dmatest_init_dstbuf(thread->dstbuf, dst_off, len);
- cookie = dma_async_memcpy_buf_to_buf(chan,
- thread->dstbuf + dst_off,
- thread->srcbuf + src_off,
- len);
+ dma_src = dma_map_single(dev->dev, thread->srcbuf + src_off,
+ len, DMA_TO_DEVICE);
+ /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
+ dma_dest = dma_map_single(dev->dev, thread->dstbuf,
+ test_buf_size, DMA_BIDIRECTIONAL);
+
+ tx = dev->device_prep_dma_memcpy(chan, dma_dest + dst_off,
+ dma_src, len,
+ DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP);
+ if (!tx) {
+ dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+ dma_unmap_single(dev->dev, dma_dest,
+ test_buf_size, DMA_BIDIRECTIONAL);
+ pr_warning("%s: #%u: prep error with src_off=0x%x "
+ "dst_off=0x%x len=0x%x\n",
+ thread_name, total_tests - 1,
+ src_off, dst_off, len);
+ msleep(100);
+ failed_tests++;
+ continue;
+ }
+ tx->callback = NULL;
+ cookie = tx->tx_submit(tx);
+
if (dma_submit_error(cookie)) {
pr_warning("%s: #%u: submit error %d with src_off=0x%x "
"dst_off=0x%x len=0x%x\n",
@@ -254,6 +277,9 @@ static int dmatest_func(void *data)
failed_tests++;
continue;
}
+ /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
+ dma_unmap_single(dev->dev, dma_dest,
+ test_buf_size, DMA_BIDIRECTIONAL);
error_count = 0;
@@ -293,7 +319,6 @@ static int dmatest_func(void *data)
}
ret = 0;
- dma_chan_put(chan);
kfree(thread->dstbuf);
err_dstbuf:
kfree(thread->srcbuf);
@@ -319,21 +344,16 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
kfree(dtc);
}
-static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
+static int dmatest_add_channel(struct dma_chan *chan)
{
struct dmatest_chan *dtc;
struct dmatest_thread *thread;
unsigned int i;
- /* Have we already been told about this channel? */
- list_for_each_entry(dtc, &dmatest_channels, node)
- if (dtc->chan == chan)
- return DMA_DUP;
-
dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
if (!dtc) {
- pr_warning("dmatest: No memory for %s\n", dev_name(&chan->dev));
- return DMA_NAK;
+ pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan));
+ return -ENOMEM;
}
dtc->chan = chan;
@@ -343,16 +363,16 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
if (!thread) {
pr_warning("dmatest: No memory for %s-test%u\n",
- dev_name(&chan->dev), i);
+ dma_chan_name(chan), i);
break;
}
thread->chan = dtc->chan;
smp_wmb();
thread->task = kthread_run(dmatest_func, thread, "%s-test%u",
- dev_name(&chan->dev), i);
+ dma_chan_name(chan), i);
if (IS_ERR(thread->task)) {
pr_warning("dmatest: Failed to run thread %s-test%u\n",
- dev_name(&chan->dev), i);
+ dma_chan_name(chan), i);
kfree(thread);
break;
}
@@ -362,86 +382,62 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan)
list_add_tail(&thread->node, &dtc->threads);
}
- pr_info("dmatest: Started %u threads using %s\n", i, dev_name(&chan->dev));
+ pr_info("dmatest: Started %u threads using %s\n", i, dma_chan_name(chan));
list_add_tail(&dtc->node, &dmatest_channels);
nr_channels++;
- return DMA_ACK;
-}
-
-static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan)
-{
- struct dmatest_chan *dtc, *_dtc;
-
- list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
- if (dtc->chan == chan) {
- list_del(&dtc->node);
- dmatest_cleanup_channel(dtc);
- pr_debug("dmatest: lost channel %s\n",
- dev_name(&chan->dev));
- return DMA_ACK;
- }
- }
-
- return DMA_DUP;
+ return 0;
}
-/*
- * Start testing threads as new channels are assigned to us, and kill
- * them when the channels go away.
- *
- * When we unregister the client, all channels are removed so this
- * will also take care of cleaning things up when the module is
- * unloaded.
- */
-static enum dma_state_client
-dmatest_event(struct dma_client *client, struct dma_chan *chan,
- enum dma_state state)
+static bool filter(struct dma_chan *chan, void *param)
{
- enum dma_state_client ack = DMA_NAK;
-
- switch (state) {
- case DMA_RESOURCE_AVAILABLE:
- if (!dmatest_match_channel(chan)
- || !dmatest_match_device(chan->device))
- ack = DMA_DUP;
- else if (max_channels && nr_channels >= max_channels)
- ack = DMA_NAK;
- else
- ack = dmatest_add_channel(chan);
- break;
-
- case DMA_RESOURCE_REMOVED:
- ack = dmatest_remove_channel(chan);
- break;
-
- default:
- pr_info("dmatest: Unhandled event %u (%s)\n",
- state, dev_name(&chan->dev));
- break;
- }
-
- return ack;
+ if (!dmatest_match_channel(chan) || !dmatest_match_device(chan->device))
+ return false;
+ else
+ return true;
}
-static struct dma_client dmatest_client = {
- .event_callback = dmatest_event,
-};
-
static int __init dmatest_init(void)
{
- dma_cap_set(DMA_MEMCPY, dmatest_client.cap_mask);
- dma_async_client_register(&dmatest_client);
- dma_async_client_chan_request(&dmatest_client);
+ dma_cap_mask_t mask;
+ struct dma_chan *chan;
+ int err = 0;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_MEMCPY, mask);
+ for (;;) {
+ chan = dma_request_channel(mask, filter, NULL);
+ if (chan) {
+ err = dmatest_add_channel(chan);
+ if (err == 0)
+ continue;
+ else {
+ dma_release_channel(chan);
+ break; /* add_channel failed, punt */
+ }
+ } else
+ break; /* no more channels available */
+ if (max_channels && nr_channels >= max_channels)
+ break; /* we have all we need */
+ }
- return 0;
+ return err;
}
-module_init(dmatest_init);
+/* when compiled-in wait for drivers to load first */
+late_initcall(dmatest_init);
static void __exit dmatest_exit(void)
{
- dma_async_client_unregister(&dmatest_client);
+ struct dmatest_chan *dtc, *_dtc;
+
+ list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
+ list_del(&dtc->node);
+ dmatest_cleanup_channel(dtc);
+ pr_debug("dmatest: dropped channel %s\n",
+ dma_chan_name(dtc->chan));
+ dma_release_channel(dtc->chan);
+ }
}
module_exit(dmatest_exit);
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 0778d99aea7c..6b702cc46b3d 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -70,6 +70,15 @@
* the controller, though.
*/
+static struct device *chan2dev(struct dma_chan *chan)
+{
+ return &chan->dev->device;
+}
+static struct device *chan2parent(struct dma_chan *chan)
+{
+ return chan->dev->device.parent;
+}
+
static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
{
return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
@@ -93,12 +102,12 @@ static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
ret = desc;
break;
}
- dev_dbg(&dwc->chan.dev, "desc %p not ACKed\n", desc);
+ dev_dbg(chan2dev(&dwc->chan), "desc %p not ACKed\n", desc);
i++;
}
spin_unlock_bh(&dwc->lock);
- dev_vdbg(&dwc->chan.dev, "scanned %u descriptors on freelist\n", i);
+ dev_vdbg(chan2dev(&dwc->chan), "scanned %u descriptors on freelist\n", i);
return ret;
}
@@ -108,10 +117,10 @@ static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc)
struct dw_desc *child;
list_for_each_entry(child, &desc->txd.tx_list, desc_node)
- dma_sync_single_for_cpu(dwc->chan.dev.parent,
+ dma_sync_single_for_cpu(chan2parent(&dwc->chan),
child->txd.phys, sizeof(child->lli),
DMA_TO_DEVICE);
- dma_sync_single_for_cpu(dwc->chan.dev.parent,
+ dma_sync_single_for_cpu(chan2parent(&dwc->chan),
desc->txd.phys, sizeof(desc->lli),
DMA_TO_DEVICE);
}
@@ -129,11 +138,11 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
spin_lock_bh(&dwc->lock);
list_for_each_entry(child, &desc->txd.tx_list, desc_node)
- dev_vdbg(&dwc->chan.dev,
+ dev_vdbg(chan2dev(&dwc->chan),
"moving child desc %p to freelist\n",
child);
list_splice_init(&desc->txd.tx_list, &dwc->free_list);
- dev_vdbg(&dwc->chan.dev, "moving desc %p to freelist\n", desc);
+ dev_vdbg(chan2dev(&dwc->chan), "moving desc %p to freelist\n", desc);
list_add(&desc->desc_node, &dwc->free_list);
spin_unlock_bh(&dwc->lock);
}
@@ -163,9 +172,9 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
/* ASSERT: channel is idle */
if (dma_readl(dw, CH_EN) & dwc->mask) {
- dev_err(&dwc->chan.dev,
+ dev_err(chan2dev(&dwc->chan),
"BUG: Attempted to start non-idle channel\n");
- dev_err(&dwc->chan.dev,
+ dev_err(chan2dev(&dwc->chan),
" SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n",
channel_readl(dwc, SAR),
channel_readl(dwc, DAR),
@@ -193,7 +202,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
void *param;
struct dma_async_tx_descriptor *txd = &desc->txd;
- dev_vdbg(&dwc->chan.dev, "descriptor %u complete\n", txd->cookie);
+ dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);
dwc->completed = txd->cookie;
callback = txd->callback;
@@ -208,11 +217,11 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
* mapped before they were submitted...
*/
if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP))
- dma_unmap_page(dwc->chan.dev.parent, desc->lli.dar, desc->len,
- DMA_FROM_DEVICE);
+ dma_unmap_page(chan2parent(&dwc->chan), desc->lli.dar,
+ desc->len, DMA_FROM_DEVICE);
if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP))
- dma_unmap_page(dwc->chan.dev.parent, desc->lli.sar, desc->len,
- DMA_TO_DEVICE);
+ dma_unmap_page(chan2parent(&dwc->chan), desc->lli.sar,
+ desc->len, DMA_TO_DEVICE);
/*
* The API requires that no submissions are done from a
@@ -228,7 +237,7 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
LIST_HEAD(list);
if (dma_readl(dw, CH_EN) & dwc->mask) {
- dev_err(&dwc->chan.dev,
+ dev_err(chan2dev(&dwc->chan),
"BUG: XFER bit set, but channel not idle!\n");
/* Try to continue after resetting the channel... */
@@ -273,7 +282,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
return;
}
- dev_vdbg(&dwc->chan.dev, "scan_descriptors: llp=0x%x\n", llp);
+ dev_vdbg(chan2dev(&dwc->chan), "scan_descriptors: llp=0x%x\n", llp);
list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
if (desc->lli.llp == llp)
@@ -292,7 +301,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
dwc_descriptor_complete(dwc, desc);
}
- dev_err(&dwc->chan.dev,
+ dev_err(chan2dev(&dwc->chan),
"BUG: All descriptors done, but channel not idle!\n");
/* Try to continue after resetting the channel... */
@@ -308,7 +317,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
static void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli)
{
- dev_printk(KERN_CRIT, &dwc->chan.dev,
+ dev_printk(KERN_CRIT, chan2dev(&dwc->chan),
" desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
lli->sar, lli->dar, lli->llp,
lli->ctlhi, lli->ctllo);
@@ -342,9 +351,9 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
* controller flagged an error instead of scribbling over
* random memory locations.
*/
- dev_printk(KERN_CRIT, &dwc->chan.dev,
+ dev_printk(KERN_CRIT, chan2dev(&dwc->chan),
"Bad descriptor submitted for DMA!\n");
- dev_printk(KERN_CRIT, &dwc->chan.dev,
+ dev_printk(KERN_CRIT, chan2dev(&dwc->chan),
" cookie: %d\n", bad_desc->txd.cookie);
dwc_dump_lli(dwc, &bad_desc->lli);
list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
@@ -442,12 +451,12 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
* for DMA. But this is hard to do in a race-free manner.
*/
if (list_empty(&dwc->active_list)) {
- dev_vdbg(&tx->chan->dev, "tx_submit: started %u\n",
+ dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
desc->txd.cookie);
dwc_dostart(dwc, desc);
list_add_tail(&desc->desc_node, &dwc->active_list);
} else {
- dev_vdbg(&tx->chan->dev, "tx_submit: queued %u\n",
+ dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
desc->txd.cookie);
list_add_tail(&desc->desc_node, &dwc->queue);
@@ -472,11 +481,11 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
unsigned int dst_width;
u32 ctllo;
- dev_vdbg(&chan->dev, "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n",
+ dev_vdbg(chan2dev(chan), "prep_dma_memcpy d0x%x s0x%x l0x%zx f0x%lx\n",
dest, src, len, flags);
if (unlikely(!len)) {
- dev_dbg(&chan->dev, "prep_dma_memcpy: length is zero!\n");
+ dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
return NULL;
}
@@ -516,7 +525,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
first = desc;
} else {
prev->lli.llp = desc->txd.phys;
- dma_sync_single_for_device(chan->dev.parent,
+ dma_sync_single_for_device(chan2parent(chan),
prev->txd.phys, sizeof(prev->lli),
DMA_TO_DEVICE);
list_add_tail(&desc->desc_node,
@@ -531,7 +540,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
prev->lli.ctllo |= DWC_CTLL_INT_EN;
prev->lli.llp = 0;
- dma_sync_single_for_device(chan->dev.parent,
+ dma_sync_single_for_device(chan2parent(chan),
prev->txd.phys, sizeof(prev->lli),
DMA_TO_DEVICE);
@@ -562,15 +571,15 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
struct scatterlist *sg;
size_t total_len = 0;
- dev_vdbg(&chan->dev, "prep_dma_slave\n");
+ dev_vdbg(chan2dev(chan), "prep_dma_slave\n");
if (unlikely(!dws || !sg_len))
return NULL;
- reg_width = dws->slave.reg_width;
+ reg_width = dws->reg_width;
prev = first = NULL;
- sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction);
+ sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction);
switch (direction) {
case DMA_TO_DEVICE:
@@ -579,7 +588,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
| DWC_CTLL_DST_FIX
| DWC_CTLL_SRC_INC
| DWC_CTLL_FC_M2P);
- reg = dws->slave.tx_reg;
+ reg = dws->tx_reg;
for_each_sg(sgl, sg, sg_len, i) {
struct dw_desc *desc;
u32 len;
@@ -587,7 +596,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
desc = dwc_desc_get(dwc);
if (!desc) {
- dev_err(&chan->dev,
+ dev_err(chan2dev(chan),
"not enough descriptors available\n");
goto err_desc_get;
}
@@ -607,7 +616,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
first = desc;
} else {
prev->lli.llp = desc->txd.phys;
- dma_sync_single_for_device(chan->dev.parent,
+ dma_sync_single_for_device(chan2parent(chan),
prev->txd.phys,
sizeof(prev->lli),
DMA_TO_DEVICE);
@@ -625,7 +634,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
| DWC_CTLL_SRC_FIX
| DWC_CTLL_FC_P2M);
- reg = dws->slave.rx_reg;
+ reg = dws->rx_reg;
for_each_sg(sgl, sg, sg_len, i) {
struct dw_desc *desc;
u32 len;
@@ -633,7 +642,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
desc = dwc_desc_get(dwc);
if (!desc) {
- dev_err(&chan->dev,
+ dev_err(chan2dev(chan),
"not enough descriptors available\n");
goto err_desc_get;
}
@@ -653,7 +662,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
first = desc;
} else {
prev->lli.llp = desc->txd.phys;
- dma_sync_single_for_device(chan->dev.parent,
+ dma_sync_single_for_device(chan2parent(chan),
prev->txd.phys,
sizeof(prev->lli),
DMA_TO_DEVICE);
@@ -673,7 +682,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
prev->lli.ctllo |= DWC_CTLL_INT_EN;
prev->lli.llp = 0;
- dma_sync_single_for_device(chan->dev.parent,
+ dma_sync_single_for_device(chan2parent(chan),
prev->txd.phys, sizeof(prev->lli),
DMA_TO_DEVICE);
@@ -758,29 +767,21 @@ static void dwc_issue_pending(struct dma_chan *chan)
spin_unlock_bh(&dwc->lock);
}
-static int dwc_alloc_chan_resources(struct dma_chan *chan,
- struct dma_client *client)
+static int dwc_alloc_chan_resources(struct dma_chan *chan)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
struct dw_dma *dw = to_dw_dma(chan->device);
struct dw_desc *desc;
- struct dma_slave *slave;
struct dw_dma_slave *dws;
int i;
u32 cfghi;
u32 cfglo;
- dev_vdbg(&chan->dev, "alloc_chan_resources\n");
-
- /* Channels doing slave DMA can only handle one client. */
- if (dwc->dws || client->slave) {
- if (chan->client_count)
- return -EBUSY;
- }
+ dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
/* ASSERT: channel is idle */
if (dma_readl(dw, CH_EN) & dwc->mask) {
- dev_dbg(&chan->dev, "DMA channel not idle?\n");
+ dev_dbg(chan2dev(chan), "DMA channel not idle?\n");
return -EIO;
}
@@ -789,23 +790,17 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan,
cfghi = DWC_CFGH_FIFO_MODE;
cfglo = 0;
- slave = client->slave;
- if (slave) {
+ dws = dwc->dws;
+ if (dws) {
/*
* We need controller-specific data to set up slave
* transfers.
*/
- BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev);
-
- dws = container_of(slave, struct dw_dma_slave, slave);
+ BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
- dwc->dws = dws;
cfghi = dws->cfg_hi;
cfglo = dws->cfg_lo;
- } else {
- dwc->dws = NULL;
}
-
channel_writel(dwc, CFG_LO, cfglo);
channel_writel(dwc, CFG_HI, cfghi);
@@ -822,7 +817,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan,
desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL);
if (!desc) {
- dev_info(&chan->dev,
+ dev_info(chan2dev(chan),
"only allocated %d descriptors\n", i);
spin_lock_bh(&dwc->lock);
break;
@@ -832,7 +827,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan,
desc->txd.tx_submit = dwc_tx_submit;
desc->txd.flags = DMA_CTRL_ACK;
INIT_LIST_HEAD(&desc->txd.tx_list);
- desc->txd.phys = dma_map_single(chan->dev.parent, &desc->lli,
+ desc->txd.phys = dma_map_single(chan2parent(chan), &desc->lli,
sizeof(desc->lli), DMA_TO_DEVICE);
dwc_desc_put(dwc, desc);
@@ -847,7 +842,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan,
spin_unlock_bh(&dwc->lock);
- dev_dbg(&chan->dev,
+ dev_dbg(chan2dev(chan),
"alloc_chan_resources allocated %d descriptors\n", i);
return i;
@@ -860,7 +855,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
struct dw_desc *desc, *_desc;
LIST_HEAD(list);
- dev_dbg(&chan->dev, "free_chan_resources (descs allocated=%u)\n",
+ dev_dbg(chan2dev(chan), "free_chan_resources (descs allocated=%u)\n",
dwc->descs_allocated);
/* ASSERT: channel is idle */
@@ -881,13 +876,13 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
spin_unlock_bh(&dwc->lock);
list_for_each_entry_safe(desc, _desc, &list, desc_node) {
- dev_vdbg(&chan->dev, " freeing descriptor %p\n", desc);
- dma_unmap_single(chan->dev.parent, desc->txd.phys,
+ dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc);
+ dma_unmap_single(chan2parent(chan), desc->txd.phys,
sizeof(desc->lli), DMA_TO_DEVICE);
kfree(desc);
}
- dev_vdbg(&chan->dev, "free_chan_resources done\n");
+ dev_vdbg(chan2dev(chan), "free_chan_resources done\n");
}
/*----------------------------------------------------------------------*/
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 0b95dcce447e..70126a606239 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -366,8 +366,7 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
*
* Return - The number of descriptors allocated.
*/
-static int fsl_dma_alloc_chan_resources(struct dma_chan *chan,
- struct dma_client *client)
+static int fsl_dma_alloc_chan_resources(struct dma_chan *chan)
{
struct fsl_dma_chan *fsl_chan = to_fsl_chan(chan);
@@ -823,7 +822,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
*/
WARN_ON(fdev->feature != new_fsl_chan->feature);
- new_fsl_chan->dev = &new_fsl_chan->common.dev;
+ new_fsl_chan->dev = fdev->dev;
new_fsl_chan->reg_base = ioremap(new_fsl_chan->reg.start,
new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1);
@@ -876,7 +875,8 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
}
dev_info(fdev->dev, "#%d (%s), irq %d\n", new_fsl_chan->id,
- compatible, new_fsl_chan->irq);
+ compatible,
+ new_fsl_chan->irq != NO_IRQ ? new_fsl_chan->irq : fdev->irq);
return 0;
@@ -891,7 +891,8 @@ err_no_reg:
static void fsl_dma_chan_remove(struct fsl_dma_chan *fchan)
{
- free_irq(fchan->irq, fchan);
+ if (fchan->irq != NO_IRQ)
+ free_irq(fchan->irq, fchan);
list_del(&fchan->common.device_node);
iounmap(fchan->reg_base);
kfree(fchan);
diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c
index 9b16a3af9a0a..4105d6575b64 100644
--- a/drivers/dma/ioat.c
+++ b/drivers/dma/ioat.c
@@ -75,60 +75,10 @@ static int ioat_dca_enabled = 1;
module_param(ioat_dca_enabled, int, 0644);
MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)");
-static int ioat_setup_functionality(struct pci_dev *pdev, void __iomem *iobase)
-{
- struct ioat_device *device = pci_get_drvdata(pdev);
- u8 version;
- int err = 0;
-
- version = readb(iobase + IOAT_VER_OFFSET);
- switch (version) {
- case IOAT_VER_1_2:
- device->dma = ioat_dma_probe(pdev, iobase);
- if (device->dma && ioat_dca_enabled)
- device->dca = ioat_dca_init(pdev, iobase);
- break;
- case IOAT_VER_2_0:
- device->dma = ioat_dma_probe(pdev, iobase);
- if (device->dma && ioat_dca_enabled)
- device->dca = ioat2_dca_init(pdev, iobase);
- break;
- case IOAT_VER_3_0:
- device->dma = ioat_dma_probe(pdev, iobase);
- if (device->dma && ioat_dca_enabled)
- device->dca = ioat3_dca_init(pdev, iobase);
- break;
- default:
- err = -ENODEV;
- break;
- }
- if (!device->dma)
- err = -ENODEV;
- return err;
-}
-
-static void ioat_shutdown_functionality(struct pci_dev *pdev)
-{
- struct ioat_device *device = pci_get_drvdata(pdev);
-
- dev_err(&pdev->dev, "Removing dma and dca services\n");
- if (device->dca) {
- unregister_dca_provider(device->dca);
- free_dca_provider(device->dca);
- device->dca = NULL;
- }
-
- if (device->dma) {
- ioat_dma_remove(device->dma);
- device->dma = NULL;
- }
-}
-
static struct pci_driver ioat_pci_driver = {
.name = "ioatdma",
.id_table = ioat_pci_tbl,
.probe = ioat_probe,
- .shutdown = ioat_shutdown_functionality,
.remove = __devexit_p(ioat_remove),
};
@@ -179,7 +129,29 @@ static int __devinit ioat_probe(struct pci_dev *pdev,
pci_set_master(pdev);
- err = ioat_setup_functionality(pdev, iobase);
+ switch (readb(iobase + IOAT_VER_OFFSET)) {
+ case IOAT_VER_1_2:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat_dca_init(pdev, iobase);
+ break;
+ case IOAT_VER_2_0:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat2_dca_init(pdev, iobase);
+ break;
+ case IOAT_VER_3_0:
+ device->dma = ioat_dma_probe(pdev, iobase);
+ if (device->dma && ioat_dca_enabled)
+ device->dca = ioat3_dca_init(pdev, iobase);
+ break;
+ default:
+ err = -ENODEV;
+ break;
+ }
+ if (!device->dma)
+ err = -ENODEV;
+
if (err)
goto err_version;
@@ -198,17 +170,21 @@ err_enable_device:
return err;
}
-/*
- * It is unsafe to remove this module: if removed while a requested
- * dma is outstanding, esp. from tcp, it is possible to hang while
- * waiting for something that will never finish. However, if you're
- * feeling lucky, this usually works just fine.
- */
static void __devexit ioat_remove(struct pci_dev *pdev)
{
struct ioat_device *device = pci_get_drvdata(pdev);
- ioat_shutdown_functionality(pdev);
+ dev_err(&pdev->dev, "Removing dma and dca services\n");
+ if (device->dca) {
+ unregister_dca_provider(device->dca);
+ free_dca_provider(device->dca);
+ device->dca = NULL;
+ }
+
+ if (device->dma) {
+ ioat_dma_remove(device->dma);
+ device->dma = NULL;
+ }
kfree(device);
}
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index 6607fdd00b1c..b3759c4b6536 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -734,8 +734,7 @@ static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)
* ioat_dma_alloc_chan_resources - returns the number of allocated descriptors
* @chan: the channel to be filled out
*/
-static int ioat_dma_alloc_chan_resources(struct dma_chan *chan,
- struct dma_client *client)
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
struct ioat_desc_sw *desc;
@@ -1341,12 +1340,11 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
*/
#define IOAT_TEST_SIZE 2000
-DECLARE_COMPLETION(test_completion);
static void ioat_dma_test_callback(void *dma_async_param)
{
- printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n",
- dma_async_param);
- complete(&test_completion);
+ struct completion *cmp = dma_async_param;
+
+ complete(cmp);
}
/**
@@ -1363,6 +1361,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
dma_addr_t dma_dest, dma_src;
dma_cookie_t cookie;
int err = 0;
+ struct completion cmp;
src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
if (!src)
@@ -1381,7 +1380,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (device->common.device_alloc_chan_resources(dma_chan, NULL) < 1) {
+ if (device->common.device_alloc_chan_resources(dma_chan) < 1) {
dev_err(&device->pdev->dev,
"selftest cannot allocate chan resource\n");
err = -ENODEV;
@@ -1402,8 +1401,9 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
}
async_tx_ack(tx);
+ init_completion(&cmp);
tx->callback = ioat_dma_test_callback;
- tx->callback_param = (void *)0x8086;
+ tx->callback_param = &cmp;
cookie = tx->tx_submit(tx);
if (cookie < 0) {
dev_err(&device->pdev->dev,
@@ -1413,7 +1413,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
}
device->common.device_issue_pending(dma_chan);
- wait_for_completion_timeout(&test_completion, msecs_to_jiffies(3000));
+ wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
!= DMA_SUCCESS) {
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 6be317262200..ea5440dd10dc 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -24,7 +24,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/async_tx.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
@@ -116,7 +115,7 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
}
/* run dependent operations */
- async_tx_run_dependencies(&desc->async_tx);
+ dma_run_dependencies(&desc->async_tx);
return cookie;
}
@@ -270,8 +269,6 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
break;
}
- BUG_ON(!seen_current);
-
if (cookie > 0) {
iop_chan->completed_cookie = cookie;
pr_debug("\tcompleted cookie %d\n", cookie);
@@ -471,8 +468,7 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
* greater than 2x the number slots needed to satisfy a device->max_xor
* request.
* */
-static int iop_adma_alloc_chan_resources(struct dma_chan *chan,
- struct dma_client *client)
+static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
{
char *hw_desc;
int idx;
@@ -866,7 +862,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
+ if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
err = -ENODEV;
goto out;
}
@@ -964,7 +960,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) {
+ if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
err = -ENODEV;
goto out;
}
@@ -1115,26 +1111,13 @@ static int __devexit iop_adma_remove(struct platform_device *dev)
struct iop_adma_device *device = platform_get_drvdata(dev);
struct dma_chan *chan, *_chan;
struct iop_adma_chan *iop_chan;
- int i;
struct iop_adma_platform_data *plat_data = dev->dev.platform_data;
dma_async_device_unregister(&device->common);
- for (i = 0; i < 3; i++) {
- unsigned int irq;
- irq = platform_get_irq(dev, i);
- free_irq(irq, device);
- }
-
dma_free_coherent(&dev->dev, plat_data->pool_size,
device->dma_desc_pool_virt, device->dma_desc_pool);
- do {
- struct resource *res;
- res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, res->end - res->start);
- } while (0);
-
list_for_each_entry_safe(chan, _chan, &device->common.channels,
device_node) {
iop_chan = to_iop_adma_chan(chan);
@@ -1255,7 +1238,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
spin_lock_init(&iop_chan->lock);
INIT_LIST_HEAD(&iop_chan->chain);
INIT_LIST_HEAD(&iop_chan->all_slots);
- INIT_RCU_HEAD(&iop_chan->common.rcu);
iop_chan->common.device = dma_dev;
list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
@@ -1431,16 +1413,12 @@ static int __init iop_adma_init (void)
return platform_driver_register(&iop_adma_driver);
}
-/* it's currently unsafe to unload this module */
-#if 0
static void __exit iop_adma_exit (void)
{
platform_driver_unregister(&iop_adma_driver);
return;
}
module_exit(iop_adma_exit);
-#endif
-
module_init(iop_adma_init);
MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/dma/ipu/Makefile b/drivers/dma/ipu/Makefile
new file mode 100644
index 000000000000..6704cf48326d
--- /dev/null
+++ b/drivers/dma/ipu/Makefile
@@ -0,0 +1 @@
+obj-y += ipu_irq.o ipu_idmac.o
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
new file mode 100644
index 000000000000..1f154d08e98f
--- /dev/null
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -0,0 +1,1740 @@
+/*
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * Copyright (C) 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <mach/ipu.h>
+
+#include "ipu_intern.h"
+
+#define FS_VF_IN_VALID 0x00000002
+#define FS_ENC_IN_VALID 0x00000001
+
+/*
+ * There can be only one, we could allocate it dynamically, but then we'd have
+ * to add an extra parameter to some functions, and use something as ugly as
+ * struct ipu *ipu = to_ipu(to_idmac(ichan->dma_chan.device));
+ * in the ISR
+ */
+static struct ipu ipu_data;
+
+#define to_ipu(id) container_of(id, struct ipu, idmac)
+
+static u32 __idmac_read_icreg(struct ipu *ipu, unsigned long reg)
+{
+ return __raw_readl(ipu->reg_ic + reg);
+}
+
+#define idmac_read_icreg(ipu, reg) __idmac_read_icreg(ipu, reg - IC_CONF)
+
+static void __idmac_write_icreg(struct ipu *ipu, u32 value, unsigned long reg)
+{
+ __raw_writel(value, ipu->reg_ic + reg);
+}
+
+#define idmac_write_icreg(ipu, v, reg) __idmac_write_icreg(ipu, v, reg - IC_CONF)
+
+static u32 idmac_read_ipureg(struct ipu *ipu, unsigned long reg)
+{
+ return __raw_readl(ipu->reg_ipu + reg);
+}
+
+static void idmac_write_ipureg(struct ipu *ipu, u32 value, unsigned long reg)
+{
+ __raw_writel(value, ipu->reg_ipu + reg);
+}
+
+/*****************************************************************************
+ * IPU / IC common functions
+ */
+static void dump_idmac_reg(struct ipu *ipu)
+{
+ dev_dbg(ipu->dev, "IDMAC_CONF 0x%x, IC_CONF 0x%x, IDMAC_CHA_EN 0x%x, "
+ "IDMAC_CHA_PRI 0x%x, IDMAC_CHA_BUSY 0x%x\n",
+ idmac_read_icreg(ipu, IDMAC_CONF),
+ idmac_read_icreg(ipu, IC_CONF),
+ idmac_read_icreg(ipu, IDMAC_CHA_EN),
+ idmac_read_icreg(ipu, IDMAC_CHA_PRI),
+ idmac_read_icreg(ipu, IDMAC_CHA_BUSY));
+ dev_dbg(ipu->dev, "BUF0_RDY 0x%x, BUF1_RDY 0x%x, CUR_BUF 0x%x, "
+ "DB_MODE 0x%x, TASKS_STAT 0x%x\n",
+ idmac_read_ipureg(ipu, IPU_CHA_BUF0_RDY),
+ idmac_read_ipureg(ipu, IPU_CHA_BUF1_RDY),
+ idmac_read_ipureg(ipu, IPU_CHA_CUR_BUF),
+ idmac_read_ipureg(ipu, IPU_CHA_DB_MODE_SEL),
+ idmac_read_ipureg(ipu, IPU_TASKS_STAT));
+}
+
+static uint32_t bytes_per_pixel(enum pixel_fmt fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_GENERIC: /* generic data */
+ case IPU_PIX_FMT_RGB332:
+ case IPU_PIX_FMT_YUV420P:
+ case IPU_PIX_FMT_YUV422P:
+ default:
+ return 1;
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_YUYV:
+ case IPU_PIX_FMT_UYVY:
+ return 2;
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ return 3;
+ case IPU_PIX_FMT_GENERIC_32: /* generic data */
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_RGB32:
+ case IPU_PIX_FMT_ABGR32:
+ return 4;
+ }
+}
+
+/* Enable / disable direct write to memory by the Camera Sensor Interface */
+static void ipu_ic_enable_task(struct ipu *ipu, enum ipu_channel channel)
+{
+ uint32_t ic_conf, mask;
+
+ switch (channel) {
+ case IDMAC_IC_0:
+ mask = IC_CONF_PRPENC_EN;
+ break;
+ case IDMAC_IC_7:
+ mask = IC_CONF_RWS_EN | IC_CONF_PRPENC_EN;
+ break;
+ default:
+ return;
+ }
+ ic_conf = idmac_read_icreg(ipu, IC_CONF) | mask;
+ idmac_write_icreg(ipu, ic_conf, IC_CONF);
+}
+
+static void ipu_ic_disable_task(struct ipu *ipu, enum ipu_channel channel)
+{
+ uint32_t ic_conf, mask;
+
+ switch (channel) {
+ case IDMAC_IC_0:
+ mask = IC_CONF_PRPENC_EN;
+ break;
+ case IDMAC_IC_7:
+ mask = IC_CONF_RWS_EN | IC_CONF_PRPENC_EN;
+ break;
+ default:
+ return;
+ }
+ ic_conf = idmac_read_icreg(ipu, IC_CONF) & ~mask;
+ idmac_write_icreg(ipu, ic_conf, IC_CONF);
+}
+
+static uint32_t ipu_channel_status(struct ipu *ipu, enum ipu_channel channel)
+{
+ uint32_t stat = TASK_STAT_IDLE;
+ uint32_t task_stat_reg = idmac_read_ipureg(ipu, IPU_TASKS_STAT);
+
+ switch (channel) {
+ case IDMAC_IC_7:
+ stat = (task_stat_reg & TSTAT_CSI2MEM_MASK) >>
+ TSTAT_CSI2MEM_OFFSET;
+ break;
+ case IDMAC_IC_0:
+ case IDMAC_SDC_0:
+ case IDMAC_SDC_1:
+ default:
+ break;
+ }
+ return stat;
+}
+
+struct chan_param_mem_planar {
+ /* Word 0 */
+ u32 xv:10;
+ u32 yv:10;
+ u32 xb:12;
+
+ u32 yb:12;
+ u32 res1:2;
+ u32 nsb:1;
+ u32 lnpb:6;
+ u32 ubo_l:11;
+
+ u32 ubo_h:15;
+ u32 vbo_l:17;
+
+ u32 vbo_h:9;
+ u32 res2:3;
+ u32 fw:12;
+ u32 fh_l:8;
+
+ u32 fh_h:4;
+ u32 res3:28;
+
+ /* Word 1 */
+ u32 eba0;
+
+ u32 eba1;
+
+ u32 bpp:3;
+ u32 sl:14;
+ u32 pfs:3;
+ u32 bam:3;
+ u32 res4:2;
+ u32 npb:6;
+ u32 res5:1;
+
+ u32 sat:2;
+ u32 res6:30;
+} __attribute__ ((packed));
+
+struct chan_param_mem_interleaved {
+ /* Word 0 */
+ u32 xv:10;
+ u32 yv:10;
+ u32 xb:12;
+
+ u32 yb:12;
+ u32 sce:1;
+ u32 res1:1;
+ u32 nsb:1;
+ u32 lnpb:6;
+ u32 sx:10;
+ u32 sy_l:1;
+
+ u32 sy_h:9;
+ u32 ns:10;
+ u32 sm:10;
+ u32 sdx_l:3;
+
+ u32 sdx_h:2;
+ u32 sdy:5;
+ u32 sdrx:1;
+ u32 sdry:1;
+ u32 sdr1:1;
+ u32 res2:2;
+ u32 fw:12;
+ u32 fh_l:8;
+
+ u32 fh_h:4;
+ u32 res3:28;
+
+ /* Word 1 */
+ u32 eba0;
+
+ u32 eba1;
+
+ u32 bpp:3;
+ u32 sl:14;
+ u32 pfs:3;
+ u32 bam:3;
+ u32 res4:2;
+ u32 npb:6;
+ u32 res5:1;
+
+ u32 sat:2;
+ u32 scc:1;
+ u32 ofs0:5;
+ u32 ofs1:5;
+ u32 ofs2:5;
+ u32 ofs3:5;
+ u32 wid0:3;
+ u32 wid1:3;
+ u32 wid2:3;
+
+ u32 wid3:3;
+ u32 dec_sel:1;
+ u32 res6:28;
+} __attribute__ ((packed));
+
+union chan_param_mem {
+ struct chan_param_mem_planar pp;
+ struct chan_param_mem_interleaved ip;
+};
+
+static void ipu_ch_param_set_plane_offset(union chan_param_mem *params,
+ u32 u_offset, u32 v_offset)
+{
+ params->pp.ubo_l = u_offset & 0x7ff;
+ params->pp.ubo_h = u_offset >> 11;
+ params->pp.vbo_l = v_offset & 0x1ffff;
+ params->pp.vbo_h = v_offset >> 17;
+}
+
+static void ipu_ch_param_set_size(union chan_param_mem *params,
+ uint32_t pixel_fmt, uint16_t width,
+ uint16_t height, uint16_t stride)
+{
+ u32 u_offset;
+ u32 v_offset;
+
+ params->pp.fw = width - 1;
+ params->pp.fh_l = height - 1;
+ params->pp.fh_h = (height - 1) >> 8;
+ params->pp.sl = stride - 1;
+
+ switch (pixel_fmt) {
+ case IPU_PIX_FMT_GENERIC:
+ /*Represents 8-bit Generic data */
+ params->pp.bpp = 3;
+ params->pp.pfs = 7;
+ params->pp.npb = 31;
+ params->pp.sat = 2; /* SAT = use 32-bit access */
+ break;
+ case IPU_PIX_FMT_GENERIC_32:
+ /*Represents 32-bit Generic data */
+ params->pp.bpp = 0;
+ params->pp.pfs = 7;
+ params->pp.npb = 7;
+ params->pp.sat = 2; /* SAT = use 32-bit access */
+ break;
+ case IPU_PIX_FMT_RGB565:
+ params->ip.bpp = 2;
+ params->ip.pfs = 4;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ params->ip.ofs0 = 0; /* Red bit offset */
+ params->ip.ofs1 = 5; /* Green bit offset */
+ params->ip.ofs2 = 11; /* Blue bit offset */
+ params->ip.ofs3 = 16; /* Alpha bit offset */
+ params->ip.wid0 = 4; /* Red bit width - 1 */
+ params->ip.wid1 = 5; /* Green bit width - 1 */
+ params->ip.wid2 = 4; /* Blue bit width - 1 */
+ break;
+ case IPU_PIX_FMT_BGR24:
+ params->ip.bpp = 1; /* 24 BPP & RGB PFS */
+ params->ip.pfs = 4;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ params->ip.ofs0 = 0; /* Red bit offset */
+ params->ip.ofs1 = 8; /* Green bit offset */
+ params->ip.ofs2 = 16; /* Blue bit offset */
+ params->ip.ofs3 = 24; /* Alpha bit offset */
+ params->ip.wid0 = 7; /* Red bit width - 1 */
+ params->ip.wid1 = 7; /* Green bit width - 1 */
+ params->ip.wid2 = 7; /* Blue bit width - 1 */
+ break;
+ case IPU_PIX_FMT_RGB24:
+ params->ip.bpp = 1; /* 24 BPP & RGB PFS */
+ params->ip.pfs = 4;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ params->ip.ofs0 = 16; /* Red bit offset */
+ params->ip.ofs1 = 8; /* Green bit offset */
+ params->ip.ofs2 = 0; /* Blue bit offset */
+ params->ip.ofs3 = 24; /* Alpha bit offset */
+ params->ip.wid0 = 7; /* Red bit width - 1 */
+ params->ip.wid1 = 7; /* Green bit width - 1 */
+ params->ip.wid2 = 7; /* Blue bit width - 1 */
+ break;
+ case IPU_PIX_FMT_BGRA32:
+ case IPU_PIX_FMT_BGR32:
+ params->ip.bpp = 0;
+ params->ip.pfs = 4;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ params->ip.ofs0 = 8; /* Red bit offset */
+ params->ip.ofs1 = 16; /* Green bit offset */
+ params->ip.ofs2 = 24; /* Blue bit offset */
+ params->ip.ofs3 = 0; /* Alpha bit offset */
+ params->ip.wid0 = 7; /* Red bit width - 1 */
+ params->ip.wid1 = 7; /* Green bit width - 1 */
+ params->ip.wid2 = 7; /* Blue bit width - 1 */
+ params->ip.wid3 = 7; /* Alpha bit width - 1 */
+ break;
+ case IPU_PIX_FMT_RGBA32:
+ case IPU_PIX_FMT_RGB32:
+ params->ip.bpp = 0;
+ params->ip.pfs = 4;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ params->ip.ofs0 = 24; /* Red bit offset */
+ params->ip.ofs1 = 16; /* Green bit offset */
+ params->ip.ofs2 = 8; /* Blue bit offset */
+ params->ip.ofs3 = 0; /* Alpha bit offset */
+ params->ip.wid0 = 7; /* Red bit width - 1 */
+ params->ip.wid1 = 7; /* Green bit width - 1 */
+ params->ip.wid2 = 7; /* Blue bit width - 1 */
+ params->ip.wid3 = 7; /* Alpha bit width - 1 */
+ break;
+ case IPU_PIX_FMT_ABGR32:
+ params->ip.bpp = 0;
+ params->ip.pfs = 4;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ params->ip.ofs0 = 8; /* Red bit offset */
+ params->ip.ofs1 = 16; /* Green bit offset */
+ params->ip.ofs2 = 24; /* Blue bit offset */
+ params->ip.ofs3 = 0; /* Alpha bit offset */
+ params->ip.wid0 = 7; /* Red bit width - 1 */
+ params->ip.wid1 = 7; /* Green bit width - 1 */
+ params->ip.wid2 = 7; /* Blue bit width - 1 */
+ params->ip.wid3 = 7; /* Alpha bit width - 1 */
+ break;
+ case IPU_PIX_FMT_UYVY:
+ params->ip.bpp = 2;
+ params->ip.pfs = 6;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ break;
+ case IPU_PIX_FMT_YUV420P2:
+ case IPU_PIX_FMT_YUV420P:
+ params->ip.bpp = 3;
+ params->ip.pfs = 3;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ u_offset = stride * height;
+ v_offset = u_offset + u_offset / 4;
+ ipu_ch_param_set_plane_offset(params, u_offset, v_offset);
+ break;
+ case IPU_PIX_FMT_YVU422P:
+ params->ip.bpp = 3;
+ params->ip.pfs = 2;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ v_offset = stride * height;
+ u_offset = v_offset + v_offset / 2;
+ ipu_ch_param_set_plane_offset(params, u_offset, v_offset);
+ break;
+ case IPU_PIX_FMT_YUV422P:
+ params->ip.bpp = 3;
+ params->ip.pfs = 2;
+ params->ip.npb = 7;
+ params->ip.sat = 2; /* SAT = 32-bit access */
+ u_offset = stride * height;
+ v_offset = u_offset + u_offset / 2;
+ ipu_ch_param_set_plane_offset(params, u_offset, v_offset);
+ break;
+ default:
+ dev_err(ipu_data.dev,
+ "mxc ipu: unimplemented pixel format %d\n", pixel_fmt);
+ break;
+ }
+
+ params->pp.nsb = 1;
+}
+
+static void ipu_ch_param_set_burst_size(union chan_param_mem *params,
+ uint16_t burst_pixels)
+{
+ params->pp.npb = burst_pixels - 1;
+};
+
+static void ipu_ch_param_set_buffer(union chan_param_mem *params,
+ dma_addr_t buf0, dma_addr_t buf1)
+{
+ params->pp.eba0 = buf0;
+ params->pp.eba1 = buf1;
+};
+
+static void ipu_ch_param_set_rotation(union chan_param_mem *params,
+ enum ipu_rotate_mode rotate)
+{
+ params->pp.bam = rotate;
+};
+
+static void ipu_write_param_mem(uint32_t addr, uint32_t *data,
+ uint32_t num_words)
+{
+ for (; num_words > 0; num_words--) {
+ dev_dbg(ipu_data.dev,
+ "write param mem - addr = 0x%08X, data = 0x%08X\n",
+ addr, *data);
+ idmac_write_ipureg(&ipu_data, addr, IPU_IMA_ADDR);
+ idmac_write_ipureg(&ipu_data, *data++, IPU_IMA_DATA);
+ addr++;
+ if ((addr & 0x7) == 5) {
+ addr &= ~0x7; /* set to word 0 */
+ addr += 8; /* increment to next row */
+ }
+ }
+}
+
+static int calc_resize_coeffs(uint32_t in_size, uint32_t out_size,
+ uint32_t *resize_coeff,
+ uint32_t *downsize_coeff)
+{
+ uint32_t temp_size;
+ uint32_t temp_downsize;
+
+ *resize_coeff = 1 << 13;
+ *downsize_coeff = 1 << 13;
+
+ /* Cannot downsize more than 8:1 */
+ if (out_size << 3 < in_size)
+ return -EINVAL;
+
+ /* compute downsizing coefficient */
+ temp_downsize = 0;
+ temp_size = in_size;
+ while (temp_size >= out_size * 2 && temp_downsize < 2) {
+ temp_size >>= 1;
+ temp_downsize++;
+ }
+ *downsize_coeff = temp_downsize;
+
+ /*
+ * compute resizing coefficient using the following formula:
+ * resize_coeff = M*(SI -1)/(SO - 1)
+ * where M = 2^13, SI - input size, SO - output size
+ */
+ *resize_coeff = (8192L * (temp_size - 1)) / (out_size - 1);
+ if (*resize_coeff >= 16384L) {
+ dev_err(ipu_data.dev, "Warning! Overflow on resize coeff.\n");
+ *resize_coeff = 0x3FFF;
+ }
+
+ dev_dbg(ipu_data.dev, "resizing from %u -> %u pixels, "
+ "downsize=%u, resize=%u.%lu (reg=%u)\n", in_size, out_size,
+ *downsize_coeff, *resize_coeff >= 8192L ? 1 : 0,
+ ((*resize_coeff & 0x1FFF) * 10000L) / 8192L, *resize_coeff);
+
+ return 0;
+}
+
+static enum ipu_color_space format_to_colorspace(enum pixel_fmt fmt)
+{
+ switch (fmt) {
+ case IPU_PIX_FMT_RGB565:
+ case IPU_PIX_FMT_BGR24:
+ case IPU_PIX_FMT_RGB24:
+ case IPU_PIX_FMT_BGR32:
+ case IPU_PIX_FMT_RGB32:
+ return IPU_COLORSPACE_RGB;
+ default:
+ return IPU_COLORSPACE_YCBCR;
+ }
+}
+
+static int ipu_ic_init_prpenc(struct ipu *ipu,
+ union ipu_channel_param *params, bool src_is_csi)
+{
+ uint32_t reg, ic_conf;
+ uint32_t downsize_coeff, resize_coeff;
+ enum ipu_color_space in_fmt, out_fmt;
+
+ /* Setup vertical resizing */
+ calc_resize_coeffs(params->video.in_height,
+ params->video.out_height,
+ &resize_coeff, &downsize_coeff);
+ reg = (downsize_coeff << 30) | (resize_coeff << 16);
+
+ /* Setup horizontal resizing */
+ calc_resize_coeffs(params->video.in_width,
+ params->video.out_width,
+ &resize_coeff, &downsize_coeff);
+ reg |= (downsize_coeff << 14) | resize_coeff;
+
+ /* Setup color space conversion */
+ in_fmt = format_to_colorspace(params->video.in_pixel_fmt);
+ out_fmt = format_to_colorspace(params->video.out_pixel_fmt);
+
+ /*
+ * Colourspace conversion unsupported yet - see _init_csc() in
+ * Freescale sources
+ */
+ if (in_fmt != out_fmt) {
+ dev_err(ipu->dev, "Colourspace conversion unsupported!\n");
+ return -EOPNOTSUPP;
+ }
+
+ idmac_write_icreg(ipu, reg, IC_PRP_ENC_RSC);
+
+ ic_conf = idmac_read_icreg(ipu, IC_CONF);
+
+ if (src_is_csi)
+ ic_conf &= ~IC_CONF_RWS_EN;
+ else
+ ic_conf |= IC_CONF_RWS_EN;
+
+ idmac_write_icreg(ipu, ic_conf, IC_CONF);
+
+ return 0;
+}
+
+static uint32_t dma_param_addr(uint32_t dma_ch)
+{
+ /* Channel Parameter Memory */
+ return 0x10000 | (dma_ch << 4);
+};
+
+static void ipu_channel_set_priority(struct ipu *ipu, enum ipu_channel channel,
+ bool prio)
+{
+ u32 reg = idmac_read_icreg(ipu, IDMAC_CHA_PRI);
+
+ if (prio)
+ reg |= 1UL << channel;
+ else
+ reg &= ~(1UL << channel);
+
+ idmac_write_icreg(ipu, reg, IDMAC_CHA_PRI);
+
+ dump_idmac_reg(ipu);
+}
+
+static uint32_t ipu_channel_conf_mask(enum ipu_channel channel)
+{
+ uint32_t mask;
+
+ switch (channel) {
+ case IDMAC_IC_0:
+ case IDMAC_IC_7:
+ mask = IPU_CONF_CSI_EN | IPU_CONF_IC_EN;
+ break;
+ case IDMAC_SDC_0:
+ case IDMAC_SDC_1:
+ mask = IPU_CONF_SDC_EN | IPU_CONF_DI_EN;
+ break;
+ default:
+ mask = 0;
+ break;
+ }
+
+ return mask;
+}
+
+/**
+ * ipu_enable_channel() - enable an IPU channel.
+ * @channel: channel ID.
+ * @return: 0 on success or negative error code on failure.
+ */
+static int ipu_enable_channel(struct idmac *idmac, struct idmac_channel *ichan)
+{
+ struct ipu *ipu = to_ipu(idmac);
+ enum ipu_channel channel = ichan->dma_chan.chan_id;
+ uint32_t reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipu->lock, flags);
+
+ /* Reset to buffer 0 */
+ idmac_write_ipureg(ipu, 1UL << channel, IPU_CHA_CUR_BUF);
+ ichan->active_buffer = 0;
+ ichan->status = IPU_CHANNEL_ENABLED;
+
+ switch (channel) {
+ case IDMAC_SDC_0:
+ case IDMAC_SDC_1:
+ case IDMAC_IC_7:
+ ipu_channel_set_priority(ipu, channel, true);
+ default:
+ break;
+ }
+
+ reg = idmac_read_icreg(ipu, IDMAC_CHA_EN);
+
+ idmac_write_icreg(ipu, reg | (1UL << channel), IDMAC_CHA_EN);
+
+ ipu_ic_enable_task(ipu, channel);
+
+ spin_unlock_irqrestore(&ipu->lock, flags);
+ return 0;
+}
+
+/**
+ * ipu_init_channel_buffer() - initialize a buffer for logical IPU channel.
+ * @channel: channel ID.
+ * @pixel_fmt: pixel format of buffer. Pixel format is a FOURCC ASCII code.
+ * @width: width of buffer in pixels.
+ * @height: height of buffer in pixels.
+ * @stride: stride length of buffer in pixels.
+ * @rot_mode: rotation mode of buffer. A rotation setting other than
+ * IPU_ROTATE_VERT_FLIP should only be used for input buffers of
+ * rotation channels.
+ * @phyaddr_0: buffer 0 physical address.
+ * @phyaddr_1: buffer 1 physical address. Setting this to a value other than
+ * NULL enables double buffering mode.
+ * @return: 0 on success or negative error code on failure.
+ */
+static int ipu_init_channel_buffer(struct idmac_channel *ichan,
+ enum pixel_fmt pixel_fmt,
+ uint16_t width, uint16_t height,
+ uint32_t stride,
+ enum ipu_rotate_mode rot_mode,
+ dma_addr_t phyaddr_0, dma_addr_t phyaddr_1)
+{
+ enum ipu_channel channel = ichan->dma_chan.chan_id;
+ struct idmac *idmac = to_idmac(ichan->dma_chan.device);
+ struct ipu *ipu = to_ipu(idmac);
+ union chan_param_mem params = {};
+ unsigned long flags;
+ uint32_t reg;
+ uint32_t stride_bytes;
+
+ stride_bytes = stride * bytes_per_pixel(pixel_fmt);
+
+ if (stride_bytes % 4) {
+ dev_err(ipu->dev,
+ "Stride length must be 32-bit aligned, stride = %d, bytes = %d\n",
+ stride, stride_bytes);
+ return -EINVAL;
+ }
+
+ /* IC channel's stride must be a multiple of 8 pixels */
+ if ((channel <= 13) && (stride % 8)) {
+ dev_err(ipu->dev, "Stride must be 8 pixel multiple\n");
+ return -EINVAL;
+ }
+
+ /* Build parameter memory data for DMA channel */
+ ipu_ch_param_set_size(&params, pixel_fmt, width, height, stride_bytes);
+ ipu_ch_param_set_buffer(&params, phyaddr_0, phyaddr_1);
+ ipu_ch_param_set_rotation(&params, rot_mode);
+ /* Some channels (rotation) have restriction on burst length */
+ switch (channel) {
+ case IDMAC_IC_7: /* Hangs with burst 8, 16, other values
+ invalid - Table 44-30 */
+/*
+ ipu_ch_param_set_burst_size(&params, 8);
+ */
+ break;
+ case IDMAC_SDC_0:
+ case IDMAC_SDC_1:
+ /* In original code only IPU_PIX_FMT_RGB565 was setting burst */
+ ipu_ch_param_set_burst_size(&params, 16);
+ break;
+ case IDMAC_IC_0:
+ default:
+ break;
+ }
+
+ spin_lock_irqsave(&ipu->lock, flags);
+
+ ipu_write_param_mem(dma_param_addr(channel), (uint32_t *)&params, 10);
+
+ reg = idmac_read_ipureg(ipu, IPU_CHA_DB_MODE_SEL);
+
+ if (phyaddr_1)
+ reg |= 1UL << channel;
+ else
+ reg &= ~(1UL << channel);
+
+ idmac_write_ipureg(ipu, reg, IPU_CHA_DB_MODE_SEL);
+
+ ichan->status = IPU_CHANNEL_READY;
+
+ spin_unlock_irqrestore(ipu->lock, flags);
+
+ return 0;
+}
+
+/**
+ * ipu_select_buffer() - mark a channel's buffer as ready.
+ * @channel: channel ID.
+ * @buffer_n: buffer number to mark ready.
+ */
+static void ipu_select_buffer(enum ipu_channel channel, int buffer_n)
+{
+ /* No locking - this is a write-one-to-set register, cleared by IPU */
+ if (buffer_n == 0)
+ /* Mark buffer 0 as ready. */
+ idmac_write_ipureg(&ipu_data, 1UL << channel, IPU_CHA_BUF0_RDY);
+ else
+ /* Mark buffer 1 as ready. */
+ idmac_write_ipureg(&ipu_data, 1UL << channel, IPU_CHA_BUF1_RDY);
+}
+
+/**
+ * ipu_update_channel_buffer() - update physical address of a channel buffer.
+ * @channel: channel ID.
+ * @buffer_n: buffer number to update.
+ * 0 or 1 are the only valid values.
+ * @phyaddr: buffer physical address.
+ * @return: Returns 0 on success or negative error code on failure. This
+ * function will fail if the buffer is set to ready.
+ */
+/* Called under spin_lock(_irqsave)(&ichan->lock) */
+static int ipu_update_channel_buffer(enum ipu_channel channel,
+ int buffer_n, dma_addr_t phyaddr)
+{
+ uint32_t reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ipu_data.lock, flags);
+
+ if (buffer_n == 0) {
+ reg = idmac_read_ipureg(&ipu_data, IPU_CHA_BUF0_RDY);
+ if (reg & (1UL << channel)) {
+ spin_unlock_irqrestore(&ipu_data.lock, flags);
+ return -EACCES;
+ }
+
+ /* 44.3.3.1.9 - Row Number 1 (WORD1, offset 0) */
+ idmac_write_ipureg(&ipu_data, dma_param_addr(channel) +
+ 0x0008UL, IPU_IMA_ADDR);
+ idmac_write_ipureg(&ipu_data, phyaddr, IPU_IMA_DATA);
+ } else {
+ reg = idmac_read_ipureg(&ipu_data, IPU_CHA_BUF1_RDY);
+ if (reg & (1UL << channel)) {
+ spin_unlock_irqrestore(&ipu_data.lock, flags);
+ return -EACCES;
+ }
+
+ /* Check if double-buffering is already enabled */
+ reg = idmac_read_ipureg(&ipu_data, IPU_CHA_DB_MODE_SEL);
+
+ if (!(reg & (1UL << channel)))
+ idmac_write_ipureg(&ipu_data, reg | (1UL << channel),
+ IPU_CHA_DB_MODE_SEL);
+
+ /* 44.3.3.1.9 - Row Number 1 (WORD1, offset 1) */
+ idmac_write_ipureg(&ipu_data, dma_param_addr(channel) +
+ 0x0009UL, IPU_IMA_ADDR);
+ idmac_write_ipureg(&ipu_data, phyaddr, IPU_IMA_DATA);
+ }
+
+ spin_unlock_irqrestore(&ipu_data.lock, flags);
+
+ return 0;
+}
+
+/* Called under spin_lock_irqsave(&ichan->lock) */
+static int ipu_submit_channel_buffers(struct idmac_channel *ichan,
+ struct idmac_tx_desc *desc)
+{
+ struct scatterlist *sg;
+ int i, ret = 0;
+
+ for (i = 0, sg = desc->sg; i < 2 && sg; i++) {
+ if (!ichan->sg[i]) {
+ ichan->sg[i] = sg;
+
+ /*
+ * On first invocation this shouldn't be necessary, the
+ * call to ipu_init_channel_buffer() above will set
+ * addresses for us, so we could make it conditional
+ * on status >= IPU_CHANNEL_ENABLED, but doing it again
+ * shouldn't hurt either.
+ */
+ ret = ipu_update_channel_buffer(ichan->dma_chan.chan_id, i,
+ sg_dma_address(sg));
+ if (ret < 0)
+ return ret;
+
+ ipu_select_buffer(ichan->dma_chan.chan_id, i);
+
+ sg = sg_next(sg);
+ }
+ }
+
+ return ret;
+}
+
+static dma_cookie_t idmac_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct idmac_tx_desc *desc = to_tx_desc(tx);
+ struct idmac_channel *ichan = to_idmac_chan(tx->chan);
+ struct idmac *idmac = to_idmac(tx->chan->device);
+ struct ipu *ipu = to_ipu(idmac);
+ dma_cookie_t cookie;
+ unsigned long flags;
+
+ /* Sanity check */
+ if (!list_empty(&desc->list)) {
+ /* The descriptor doesn't belong to client */
+ dev_err(&ichan->dma_chan.dev->device,
+ "Descriptor %p not prepared!\n", tx);
+ return -EBUSY;
+ }
+
+ mutex_lock(&ichan->chan_mutex);
+
+ if (ichan->status < IPU_CHANNEL_READY) {
+ struct idmac_video_param *video = &ichan->params.video;
+ /*
+ * Initial buffer assignment - the first two sg-entries from
+ * the descriptor will end up in the IDMAC buffers
+ */
+ dma_addr_t dma_1 = sg_is_last(desc->sg) ? 0 :
+ sg_dma_address(&desc->sg[1]);
+
+ WARN_ON(ichan->sg[0] || ichan->sg[1]);
+
+ cookie = ipu_init_channel_buffer(ichan,
+ video->out_pixel_fmt,
+ video->out_width,
+ video->out_height,
+ video->out_stride,
+ IPU_ROTATE_NONE,
+ sg_dma_address(&desc->sg[0]),
+ dma_1);
+ if (cookie < 0)
+ goto out;
+ }
+
+ /* ipu->lock can be taken under ichan->lock, but not v.v. */
+ spin_lock_irqsave(&ichan->lock, flags);
+
+ /* submit_buffers() atomically verifies and fills empty sg slots */
+ cookie = ipu_submit_channel_buffers(ichan, desc);
+
+ spin_unlock_irqrestore(&ichan->lock, flags);
+
+ if (cookie < 0)
+ goto out;
+
+ cookie = ichan->dma_chan.cookie;
+
+ if (++cookie < 0)
+ cookie = 1;
+
+ /* from dmaengine.h: "last cookie value returned to client" */
+ ichan->dma_chan.cookie = cookie;
+ tx->cookie = cookie;
+ spin_lock_irqsave(&ichan->lock, flags);
+ list_add_tail(&desc->list, &ichan->queue);
+ spin_unlock_irqrestore(&ichan->lock, flags);
+
+ if (ichan->status < IPU_CHANNEL_ENABLED) {
+ int ret = ipu_enable_channel(idmac, ichan);
+ if (ret < 0) {
+ cookie = ret;
+ spin_lock_irqsave(&ichan->lock, flags);
+ list_del_init(&desc->list);
+ spin_unlock_irqrestore(&ichan->lock, flags);
+ tx->cookie = cookie;
+ ichan->dma_chan.cookie = cookie;
+ }
+ }
+
+ dump_idmac_reg(ipu);
+
+out:
+ mutex_unlock(&ichan->chan_mutex);
+
+ return cookie;
+}
+
+/* Called with ichan->chan_mutex held */
+static int idmac_desc_alloc(struct idmac_channel *ichan, int n)
+{
+ struct idmac_tx_desc *desc = vmalloc(n * sizeof(struct idmac_tx_desc));
+ struct idmac *idmac = to_idmac(ichan->dma_chan.device);
+
+ if (!desc)
+ return -ENOMEM;
+
+ /* No interrupts, just disable the tasklet for a moment */
+ tasklet_disable(&to_ipu(idmac)->tasklet);
+
+ ichan->n_tx_desc = n;
+ ichan->desc = desc;
+ INIT_LIST_HEAD(&ichan->queue);
+ INIT_LIST_HEAD(&ichan->free_list);
+
+ while (n--) {
+ struct dma_async_tx_descriptor *txd = &desc->txd;
+
+ memset(txd, 0, sizeof(*txd));
+ dma_async_tx_descriptor_init(txd, &ichan->dma_chan);
+ txd->tx_submit = idmac_tx_submit;
+ txd->chan = &ichan->dma_chan;
+ INIT_LIST_HEAD(&txd->tx_list);
+
+ list_add(&desc->list, &ichan->free_list);
+
+ desc++;
+ }
+
+ tasklet_enable(&to_ipu(idmac)->tasklet);
+
+ return 0;
+}
+
+/**
+ * ipu_init_channel() - initialize an IPU channel.
+ * @idmac: IPU DMAC context.
+ * @ichan: pointer to the channel object.
+ * @return 0 on success or negative error code on failure.
+ */
+static int ipu_init_channel(struct idmac *idmac, struct idmac_channel *ichan)
+{
+ union ipu_channel_param *params = &ichan->params;
+ uint32_t ipu_conf;
+ enum ipu_channel channel = ichan->dma_chan.chan_id;
+ unsigned long flags;
+ uint32_t reg;
+ struct ipu *ipu = to_ipu(idmac);
+ int ret = 0, n_desc = 0;
+
+ dev_dbg(ipu->dev, "init channel = %d\n", channel);
+
+ if (channel != IDMAC_SDC_0 && channel != IDMAC_SDC_1 &&
+ channel != IDMAC_IC_7)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ipu->lock, flags);
+
+ switch (channel) {
+ case IDMAC_IC_7:
+ n_desc = 16;
+ reg = idmac_read_icreg(ipu, IC_CONF);
+ idmac_write_icreg(ipu, reg & ~IC_CONF_CSI_MEM_WR_EN, IC_CONF);
+ break;
+ case IDMAC_IC_0:
+ n_desc = 16;
+ reg = idmac_read_ipureg(ipu, IPU_FS_PROC_FLOW);
+ idmac_write_ipureg(ipu, reg & ~FS_ENC_IN_VALID, IPU_FS_PROC_FLOW);
+ ret = ipu_ic_init_prpenc(ipu, params, true);
+ break;
+ case IDMAC_SDC_0:
+ case IDMAC_SDC_1:
+ n_desc = 4;
+ default:
+ break;
+ }
+
+ ipu->channel_init_mask |= 1L << channel;
+
+ /* Enable IPU sub module */
+ ipu_conf = idmac_read_ipureg(ipu, IPU_CONF) |
+ ipu_channel_conf_mask(channel);
+ idmac_write_ipureg(ipu, ipu_conf, IPU_CONF);
+
+ spin_unlock_irqrestore(&ipu->lock, flags);
+
+ if (n_desc && !ichan->desc)
+ ret = idmac_desc_alloc(ichan, n_desc);
+
+ dump_idmac_reg(ipu);
+
+ return ret;
+}
+
+/**
+ * ipu_uninit_channel() - uninitialize an IPU channel.
+ * @idmac: IPU DMAC context.
+ * @ichan: pointer to the channel object.
+ */
+static void ipu_uninit_channel(struct idmac *idmac, struct idmac_channel *ichan)
+{
+ enum ipu_channel channel = ichan->dma_chan.chan_id;
+ unsigned long flags;
+ uint32_t reg;
+ unsigned long chan_mask = 1UL << channel;
+ uint32_t ipu_conf;
+ struct ipu *ipu = to_ipu(idmac);
+
+ spin_lock_irqsave(&ipu->lock, flags);
+
+ if (!(ipu->channel_init_mask & chan_mask)) {
+ dev_err(ipu->dev, "Channel already uninitialized %d\n",
+ channel);
+ spin_unlock_irqrestore(&ipu->lock, flags);
+ return;
+ }
+
+ /* Reset the double buffer */
+ reg = idmac_read_ipureg(ipu, IPU_CHA_DB_MODE_SEL);
+ idmac_write_ipureg(ipu, reg & ~chan_mask, IPU_CHA_DB_MODE_SEL);
+
+ ichan->sec_chan_en = false;
+
+ switch (channel) {
+ case IDMAC_IC_7:
+ reg = idmac_read_icreg(ipu, IC_CONF);
+ idmac_write_icreg(ipu, reg & ~(IC_CONF_RWS_EN | IC_CONF_PRPENC_EN),
+ IC_CONF);
+ break;
+ case IDMAC_IC_0:
+ reg = idmac_read_icreg(ipu, IC_CONF);
+ idmac_write_icreg(ipu, reg & ~(IC_CONF_PRPENC_EN | IC_CONF_PRPENC_CSC1),
+ IC_CONF);
+ break;
+ case IDMAC_SDC_0:
+ case IDMAC_SDC_1:
+ default:
+ break;
+ }
+
+ ipu->channel_init_mask &= ~(1L << channel);
+
+ ipu_conf = idmac_read_ipureg(ipu, IPU_CONF) &
+ ~ipu_channel_conf_mask(channel);
+ idmac_write_ipureg(ipu, ipu_conf, IPU_CONF);
+
+ spin_unlock_irqrestore(&ipu->lock, flags);
+
+ ichan->n_tx_desc = 0;
+ vfree(ichan->desc);
+ ichan->desc = NULL;
+}
+
+/**
+ * ipu_disable_channel() - disable an IPU channel.
+ * @idmac: IPU DMAC context.
+ * @ichan: channel object pointer.
+ * @wait_for_stop: flag to set whether to wait for channel end of frame or
+ * return immediately.
+ * @return: 0 on success or negative error code on failure.
+ */
+static int ipu_disable_channel(struct idmac *idmac, struct idmac_channel *ichan,
+ bool wait_for_stop)
+{
+ enum ipu_channel channel = ichan->dma_chan.chan_id;
+ struct ipu *ipu = to_ipu(idmac);
+ uint32_t reg;
+ unsigned long flags;
+ unsigned long chan_mask = 1UL << channel;
+ unsigned int timeout;
+
+ if (wait_for_stop && channel != IDMAC_SDC_1 && channel != IDMAC_SDC_0) {
+ timeout = 40;
+ /* This waiting always fails. Related to spurious irq problem */
+ while ((idmac_read_icreg(ipu, IDMAC_CHA_BUSY) & chan_mask) ||
+ (ipu_channel_status(ipu, channel) == TASK_STAT_ACTIVE)) {
+ timeout--;
+ msleep(10);
+
+ if (!timeout) {
+ dev_dbg(ipu->dev,
+ "Warning: timeout waiting for channel %u to "
+ "stop: buf0_rdy = 0x%08X, buf1_rdy = 0x%08X, "
+ "busy = 0x%08X, tstat = 0x%08X\n", channel,
+ idmac_read_ipureg(ipu, IPU_CHA_BUF0_RDY),
+ idmac_read_ipureg(ipu, IPU_CHA_BUF1_RDY),
+ idmac_read_icreg(ipu, IDMAC_CHA_BUSY),
+ idmac_read_ipureg(ipu, IPU_TASKS_STAT));
+ break;
+ }
+ }
+ dev_dbg(ipu->dev, "timeout = %d * 10ms\n", 40 - timeout);
+ }
+ /* SDC BG and FG must be disabled before DMA is disabled */
+ if (wait_for_stop && (channel == IDMAC_SDC_0 ||
+ channel == IDMAC_SDC_1)) {
+ for (timeout = 5;
+ timeout && !ipu_irq_status(ichan->eof_irq); timeout--)
+ msleep(5);
+ }
+
+ spin_lock_irqsave(&ipu->lock, flags);
+
+ /* Disable IC task */
+ ipu_ic_disable_task(ipu, channel);
+
+ /* Disable DMA channel(s) */
+ reg = idmac_read_icreg(ipu, IDMAC_CHA_EN);
+ idmac_write_icreg(ipu, reg & ~chan_mask, IDMAC_CHA_EN);
+
+ /*
+ * Problem (observed with channel DMAIC_7): after enabling the channel
+ * and initialising buffers, there comes an interrupt with current still
+ * pointing at buffer 0, whereas it should use buffer 0 first and only
+ * generate an interrupt when it is done, then current should already
+ * point to buffer 1. This spurious interrupt also comes on channel
+ * DMASDC_0. With DMAIC_7 normally, is we just leave the ISR after the
+ * first interrupt, there comes the second with current correctly
+ * pointing to buffer 1 this time. But sometimes this second interrupt
+ * doesn't come and the channel hangs. Clearing BUFx_RDY when disabling
+ * the channel seems to prevent the channel from hanging, but it doesn't
+ * prevent the spurious interrupt. This might also be unsafe. Think
+ * about the IDMAC controller trying to switch to a buffer, when we
+ * clear the ready bit, and re-enable it a moment later.
+ */
+ reg = idmac_read_ipureg(ipu, IPU_CHA_BUF0_RDY);
+ idmac_write_ipureg(ipu, 0, IPU_CHA_BUF0_RDY);
+ idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF0_RDY);
+
+ reg = idmac_read_ipureg(ipu, IPU_CHA_BUF1_RDY);
+ idmac_write_ipureg(ipu, 0, IPU_CHA_BUF1_RDY);
+ idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF1_RDY);
+
+ spin_unlock_irqrestore(&ipu->lock, flags);
+
+ return 0;
+}
+
+/*
+ * We have several possibilities here:
+ * current BUF next BUF
+ *
+ * not last sg next not last sg
+ * not last sg next last sg
+ * last sg first sg from next descriptor
+ * last sg NULL
+ *
+ * Besides, the descriptor queue might be empty or not. We process all these
+ * cases carefully.
+ */
+static irqreturn_t idmac_interrupt(int irq, void *dev_id)
+{
+ struct idmac_channel *ichan = dev_id;
+ unsigned int chan_id = ichan->dma_chan.chan_id;
+ struct scatterlist **sg, *sgnext, *sgnew = NULL;
+ /* Next transfer descriptor */
+ struct idmac_tx_desc *desc = NULL, *descnew;
+ dma_async_tx_callback callback;
+ void *callback_param;
+ bool done = false;
+ u32 ready0 = idmac_read_ipureg(&ipu_data, IPU_CHA_BUF0_RDY),
+ ready1 = idmac_read_ipureg(&ipu_data, IPU_CHA_BUF1_RDY),
+ curbuf = idmac_read_ipureg(&ipu_data, IPU_CHA_CUR_BUF);
+
+ /* IDMAC has cleared the respective BUFx_RDY bit, we manage the buffer */
+
+ pr_debug("IDMAC irq %d\n", irq);
+ /* Other interrupts do not interfere with this channel */
+ spin_lock(&ichan->lock);
+
+ if (unlikely(chan_id != IDMAC_SDC_0 && chan_id != IDMAC_SDC_1 &&
+ ((curbuf >> chan_id) & 1) == ichan->active_buffer)) {
+ int i = 100;
+
+ /* This doesn't help. See comment in ipu_disable_channel() */
+ while (--i) {
+ curbuf = idmac_read_ipureg(&ipu_data, IPU_CHA_CUR_BUF);
+ if (((curbuf >> chan_id) & 1) != ichan->active_buffer)
+ break;
+ cpu_relax();
+ }
+
+ if (!i) {
+ spin_unlock(&ichan->lock);
+ dev_dbg(ichan->dma_chan.device->dev,
+ "IRQ on active buffer on channel %x, active "
+ "%d, ready %x, %x, current %x!\n", chan_id,
+ ichan->active_buffer, ready0, ready1, curbuf);
+ return IRQ_NONE;
+ }
+ }
+
+ if (unlikely((ichan->active_buffer && (ready1 >> chan_id) & 1) ||
+ (!ichan->active_buffer && (ready0 >> chan_id) & 1)
+ )) {
+ spin_unlock(&ichan->lock);
+ dev_dbg(ichan->dma_chan.device->dev,
+ "IRQ with active buffer still ready on channel %x, "
+ "active %d, ready %x, %x!\n", chan_id,
+ ichan->active_buffer, ready0, ready1);
+ return IRQ_NONE;
+ }
+
+ if (unlikely(list_empty(&ichan->queue))) {
+ spin_unlock(&ichan->lock);
+ dev_err(ichan->dma_chan.device->dev,
+ "IRQ without queued buffers on channel %x, active %d, "
+ "ready %x, %x!\n", chan_id,
+ ichan->active_buffer, ready0, ready1);
+ return IRQ_NONE;
+ }
+
+ /*
+ * active_buffer is a software flag, it shows which buffer we are
+ * currently expecting back from the hardware, IDMAC should be
+ * processing the other buffer already
+ */
+ sg = &ichan->sg[ichan->active_buffer];
+ sgnext = ichan->sg[!ichan->active_buffer];
+
+ /*
+ * if sgnext == NULL sg must be the last element in a scatterlist and
+ * queue must be empty
+ */
+ if (unlikely(!sgnext)) {
+ if (unlikely(sg_next(*sg))) {
+ dev_err(ichan->dma_chan.device->dev,
+ "Broken buffer-update locking on channel %x!\n",
+ chan_id);
+ /* We'll let the user catch up */
+ } else {
+ /* Underrun */
+ ipu_ic_disable_task(&ipu_data, chan_id);
+ dev_dbg(ichan->dma_chan.device->dev,
+ "Underrun on channel %x\n", chan_id);
+ ichan->status = IPU_CHANNEL_READY;
+ /* Continue to check for complete descriptor */
+ }
+ }
+
+ desc = list_entry(ichan->queue.next, struct idmac_tx_desc, list);
+
+ /* First calculate and submit the next sg element */
+ if (likely(sgnext))
+ sgnew = sg_next(sgnext);
+
+ if (unlikely(!sgnew)) {
+ /* Start a new scatterlist, if any queued */
+ if (likely(desc->list.next != &ichan->queue)) {
+ descnew = list_entry(desc->list.next,
+ struct idmac_tx_desc, list);
+ sgnew = &descnew->sg[0];
+ }
+ }
+
+ if (unlikely(!sg_next(*sg)) || !sgnext) {
+ /*
+ * Last element in scatterlist done, remove from the queue,
+ * _init for debugging
+ */
+ list_del_init(&desc->list);
+ done = true;
+ }
+
+ *sg = sgnew;
+
+ if (likely(sgnew)) {
+ int ret;
+
+ ret = ipu_update_channel_buffer(chan_id, ichan->active_buffer,
+ sg_dma_address(*sg));
+ if (ret < 0)
+ dev_err(ichan->dma_chan.device->dev,
+ "Failed to update buffer on channel %x buffer %d!\n",
+ chan_id, ichan->active_buffer);
+ else
+ ipu_select_buffer(chan_id, ichan->active_buffer);
+ }
+
+ /* Flip the active buffer - even if update above failed */
+ ichan->active_buffer = !ichan->active_buffer;
+ if (done)
+ ichan->completed = desc->txd.cookie;
+
+ callback = desc->txd.callback;
+ callback_param = desc->txd.callback_param;
+
+ spin_unlock(&ichan->lock);
+
+ if (done && (desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
+ callback(callback_param);
+
+ return IRQ_HANDLED;
+}
+
+static void ipu_gc_tasklet(unsigned long arg)
+{
+ struct ipu *ipu = (struct ipu *)arg;
+ int i;
+
+ for (i = 0; i < IPU_CHANNELS_NUM; i++) {
+ struct idmac_channel *ichan = ipu->channel + i;
+ struct idmac_tx_desc *desc;
+ unsigned long flags;
+ int j;
+
+ for (j = 0; j < ichan->n_tx_desc; j++) {
+ desc = ichan->desc + j;
+ spin_lock_irqsave(&ichan->lock, flags);
+ if (async_tx_test_ack(&desc->txd)) {
+ list_move(&desc->list, &ichan->free_list);
+ async_tx_clear_ack(&desc->txd);
+ }
+ spin_unlock_irqrestore(&ichan->lock, flags);
+ }
+ }
+}
+
+/*
+ * At the time .device_alloc_chan_resources() method is called, we cannot know,
+ * whether the client will accept the channel. Thus we must only check, if we
+ * can satisfy client's request but the only real criterion to verify, whether
+ * the client has accepted our offer is the client_count. That's why we have to
+ * perform the rest of our allocation tasks on the first call to this function.
+ */
+static struct dma_async_tx_descriptor *idmac_prep_slave_sg(struct dma_chan *chan,
+ struct scatterlist *sgl, unsigned int sg_len,
+ enum dma_data_direction direction, unsigned long tx_flags)
+{
+ struct idmac_channel *ichan = to_idmac_chan(chan);
+ struct idmac_tx_desc *desc = NULL;
+ struct dma_async_tx_descriptor *txd = NULL;
+ unsigned long flags;
+
+ /* We only can handle these three channels so far */
+ if (ichan->dma_chan.chan_id != IDMAC_SDC_0 && ichan->dma_chan.chan_id != IDMAC_SDC_1 &&
+ ichan->dma_chan.chan_id != IDMAC_IC_7)
+ return NULL;
+
+ if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE) {
+ dev_err(chan->device->dev, "Invalid DMA direction %d!\n", direction);
+ return NULL;
+ }
+
+ mutex_lock(&ichan->chan_mutex);
+
+ spin_lock_irqsave(&ichan->lock, flags);
+ if (!list_empty(&ichan->free_list)) {
+ desc = list_entry(ichan->free_list.next,
+ struct idmac_tx_desc, list);
+
+ list_del_init(&desc->list);
+
+ desc->sg_len = sg_len;
+ desc->sg = sgl;
+ txd = &desc->txd;
+ txd->flags = tx_flags;
+ }
+ spin_unlock_irqrestore(&ichan->lock, flags);
+
+ mutex_unlock(&ichan->chan_mutex);
+
+ tasklet_schedule(&to_ipu(to_idmac(chan->device))->tasklet);
+
+ return txd;
+}
+
+/* Re-select the current buffer and re-activate the channel */
+static void idmac_issue_pending(struct dma_chan *chan)
+{
+ struct idmac_channel *ichan = to_idmac_chan(chan);
+ struct idmac *idmac = to_idmac(chan->device);
+ struct ipu *ipu = to_ipu(idmac);
+ unsigned long flags;
+
+ /* This is not always needed, but doesn't hurt either */
+ spin_lock_irqsave(&ipu->lock, flags);
+ ipu_select_buffer(ichan->dma_chan.chan_id, ichan->active_buffer);
+ spin_unlock_irqrestore(&ipu->lock, flags);
+
+ /*
+ * Might need to perform some parts of initialisation from
+ * ipu_enable_channel(), but not all, we do not want to reset to buffer
+ * 0, don't need to set priority again either, but re-enabling the task
+ * and the channel might be a good idea.
+ */
+}
+
+static void __idmac_terminate_all(struct dma_chan *chan)
+{
+ struct idmac_channel *ichan = to_idmac_chan(chan);
+ struct idmac *idmac = to_idmac(chan->device);
+ unsigned long flags;
+ int i;
+
+ ipu_disable_channel(idmac, ichan,
+ ichan->status >= IPU_CHANNEL_ENABLED);
+
+ tasklet_disable(&to_ipu(idmac)->tasklet);
+
+ /* ichan->queue is modified in ISR, have to spinlock */
+ spin_lock_irqsave(&ichan->lock, flags);
+ list_splice_init(&ichan->queue, &ichan->free_list);
+
+ if (ichan->desc)
+ for (i = 0; i < ichan->n_tx_desc; i++) {
+ struct idmac_tx_desc *desc = ichan->desc + i;
+ if (list_empty(&desc->list))
+ /* Descriptor was prepared, but not submitted */
+ list_add(&desc->list,
+ &ichan->free_list);
+
+ async_tx_clear_ack(&desc->txd);
+ }
+
+ ichan->sg[0] = NULL;
+ ichan->sg[1] = NULL;
+ spin_unlock_irqrestore(&ichan->lock, flags);
+
+ tasklet_enable(&to_ipu(idmac)->tasklet);
+
+ ichan->status = IPU_CHANNEL_INITIALIZED;
+}
+
+static void idmac_terminate_all(struct dma_chan *chan)
+{
+ struct idmac_channel *ichan = to_idmac_chan(chan);
+
+ mutex_lock(&ichan->chan_mutex);
+
+ __idmac_terminate_all(chan);
+
+ mutex_unlock(&ichan->chan_mutex);
+}
+
+static int idmac_alloc_chan_resources(struct dma_chan *chan)
+{
+ struct idmac_channel *ichan = to_idmac_chan(chan);
+ struct idmac *idmac = to_idmac(chan->device);
+ int ret;
+
+ /* dmaengine.c now guarantees to only offer free channels */
+ BUG_ON(chan->client_count > 1);
+ WARN_ON(ichan->status != IPU_CHANNEL_FREE);
+
+ chan->cookie = 1;
+ ichan->completed = -ENXIO;
+
+ ret = ipu_irq_map(ichan->dma_chan.chan_id);
+ if (ret < 0)
+ goto eimap;
+
+ ichan->eof_irq = ret;
+ ret = request_irq(ichan->eof_irq, idmac_interrupt, 0,
+ ichan->eof_name, ichan);
+ if (ret < 0)
+ goto erirq;
+
+ ret = ipu_init_channel(idmac, ichan);
+ if (ret < 0)
+ goto eichan;
+
+ ichan->status = IPU_CHANNEL_INITIALIZED;
+
+ dev_dbg(&ichan->dma_chan.dev->device, "Found channel 0x%x, irq %d\n",
+ ichan->dma_chan.chan_id, ichan->eof_irq);
+
+ return ret;
+
+eichan:
+ free_irq(ichan->eof_irq, ichan);
+erirq:
+ ipu_irq_unmap(ichan->dma_chan.chan_id);
+eimap:
+ return ret;
+}
+
+static void idmac_free_chan_resources(struct dma_chan *chan)
+{
+ struct idmac_channel *ichan = to_idmac_chan(chan);
+ struct idmac *idmac = to_idmac(chan->device);
+
+ mutex_lock(&ichan->chan_mutex);
+
+ __idmac_terminate_all(chan);
+
+ if (ichan->status > IPU_CHANNEL_FREE) {
+ free_irq(ichan->eof_irq, ichan);
+ ipu_irq_unmap(ichan->dma_chan.chan_id);
+ }
+
+ ichan->status = IPU_CHANNEL_FREE;
+
+ ipu_uninit_channel(idmac, ichan);
+
+ mutex_unlock(&ichan->chan_mutex);
+
+ tasklet_schedule(&to_ipu(idmac)->tasklet);
+}
+
+static enum dma_status idmac_is_tx_complete(struct dma_chan *chan,
+ dma_cookie_t cookie, dma_cookie_t *done, dma_cookie_t *used)
+{
+ struct idmac_channel *ichan = to_idmac_chan(chan);
+
+ if (done)
+ *done = ichan->completed;
+ if (used)
+ *used = chan->cookie;
+ if (cookie != chan->cookie)
+ return DMA_ERROR;
+ return DMA_SUCCESS;
+}
+
+static int __init ipu_idmac_init(struct ipu *ipu)
+{
+ struct idmac *idmac = &ipu->idmac;
+ struct dma_device *dma = &idmac->dma;
+ int i;
+
+ dma_cap_set(DMA_SLAVE, dma->cap_mask);
+ dma_cap_set(DMA_PRIVATE, dma->cap_mask);
+
+ /* Compulsory common fields */
+ dma->dev = ipu->dev;
+ dma->device_alloc_chan_resources = idmac_alloc_chan_resources;
+ dma->device_free_chan_resources = idmac_free_chan_resources;
+ dma->device_is_tx_complete = idmac_is_tx_complete;
+ dma->device_issue_pending = idmac_issue_pending;
+
+ /* Compulsory for DMA_SLAVE fields */
+ dma->device_prep_slave_sg = idmac_prep_slave_sg;
+ dma->device_terminate_all = idmac_terminate_all;
+
+ INIT_LIST_HEAD(&dma->channels);
+ for (i = 0; i < IPU_CHANNELS_NUM; i++) {
+ struct idmac_channel *ichan = ipu->channel + i;
+ struct dma_chan *dma_chan = &ichan->dma_chan;
+
+ spin_lock_init(&ichan->lock);
+ mutex_init(&ichan->chan_mutex);
+
+ ichan->status = IPU_CHANNEL_FREE;
+ ichan->sec_chan_en = false;
+ ichan->completed = -ENXIO;
+ snprintf(ichan->eof_name, sizeof(ichan->eof_name), "IDMAC EOF %d", i);
+
+ dma_chan->device = &idmac->dma;
+ dma_chan->cookie = 1;
+ dma_chan->chan_id = i;
+ list_add_tail(&ichan->dma_chan.device_node, &dma->channels);
+ }
+
+ idmac_write_icreg(ipu, 0x00000070, IDMAC_CONF);
+
+ return dma_async_device_register(&idmac->dma);
+}
+
+static void ipu_idmac_exit(struct ipu *ipu)
+{
+ int i;
+ struct idmac *idmac = &ipu->idmac;
+
+ for (i = 0; i < IPU_CHANNELS_NUM; i++) {
+ struct idmac_channel *ichan = ipu->channel + i;
+
+ idmac_terminate_all(&ichan->dma_chan);
+ idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0);
+ }
+
+ dma_async_device_unregister(&idmac->dma);
+}
+
+/*****************************************************************************
+ * IPU common probe / remove
+ */
+
+static int ipu_probe(struct platform_device *pdev)
+{
+ struct ipu_platform_data *pdata = pdev->dev.platform_data;
+ struct resource *mem_ipu, *mem_ic;
+ int ret;
+
+ spin_lock_init(&ipu_data.lock);
+
+ mem_ipu = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mem_ic = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!pdata || !mem_ipu || !mem_ic)
+ return -EINVAL;
+
+ ipu_data.dev = &pdev->dev;
+
+ platform_set_drvdata(pdev, &ipu_data);
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ goto err_noirq;
+
+ ipu_data.irq_fn = ret;
+ ret = platform_get_irq(pdev, 1);
+ if (ret < 0)
+ goto err_noirq;
+
+ ipu_data.irq_err = ret;
+ ipu_data.irq_base = pdata->irq_base;
+
+ dev_dbg(&pdev->dev, "fn irq %u, err irq %u, irq-base %u\n",
+ ipu_data.irq_fn, ipu_data.irq_err, ipu_data.irq_base);
+
+ /* Remap IPU common registers */
+ ipu_data.reg_ipu = ioremap(mem_ipu->start,
+ mem_ipu->end - mem_ipu->start + 1);
+ if (!ipu_data.reg_ipu) {
+ ret = -ENOMEM;
+ goto err_ioremap_ipu;
+ }
+
+ /* Remap Image Converter and Image DMA Controller registers */
+ ipu_data.reg_ic = ioremap(mem_ic->start,
+ mem_ic->end - mem_ic->start + 1);
+ if (!ipu_data.reg_ic) {
+ ret = -ENOMEM;
+ goto err_ioremap_ic;
+ }
+
+ /* Get IPU clock */
+ ipu_data.ipu_clk = clk_get(&pdev->dev, "ipu_clk");
+ if (IS_ERR(ipu_data.ipu_clk)) {
+ ret = PTR_ERR(ipu_data.ipu_clk);
+ goto err_clk_get;
+ }
+
+ /* Make sure IPU HSP clock is running */
+ clk_enable(ipu_data.ipu_clk);
+
+ /* Disable all interrupts */
+ idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_1);
+ idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_2);
+ idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_3);
+ idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_4);
+ idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_5);
+
+ dev_dbg(&pdev->dev, "%s @ 0x%08lx, fn irq %u, err irq %u\n", pdev->name,
+ (unsigned long)mem_ipu->start, ipu_data.irq_fn, ipu_data.irq_err);
+
+ ret = ipu_irq_attach_irq(&ipu_data, pdev);
+ if (ret < 0)
+ goto err_attach_irq;
+
+ /* Initialize DMA engine */
+ ret = ipu_idmac_init(&ipu_data);
+ if (ret < 0)
+ goto err_idmac_init;
+
+ tasklet_init(&ipu_data.tasklet, ipu_gc_tasklet, (unsigned long)&ipu_data);
+
+ ipu_data.dev = &pdev->dev;
+
+ dev_dbg(ipu_data.dev, "IPU initialized\n");
+
+ return 0;
+
+err_idmac_init:
+err_attach_irq:
+ ipu_irq_detach_irq(&ipu_data, pdev);
+ clk_disable(ipu_data.ipu_clk);
+ clk_put(ipu_data.ipu_clk);
+err_clk_get:
+ iounmap(ipu_data.reg_ic);
+err_ioremap_ic:
+ iounmap(ipu_data.reg_ipu);
+err_ioremap_ipu:
+err_noirq:
+ dev_err(&pdev->dev, "Failed to probe IPU: %d\n", ret);
+ return ret;
+}
+
+static int ipu_remove(struct platform_device *pdev)
+{
+ struct ipu *ipu = platform_get_drvdata(pdev);
+
+ ipu_idmac_exit(ipu);
+ ipu_irq_detach_irq(ipu, pdev);
+ clk_disable(ipu->ipu_clk);
+ clk_put(ipu->ipu_clk);
+ iounmap(ipu->reg_ic);
+ iounmap(ipu->reg_ipu);
+ tasklet_kill(&ipu->tasklet);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+/*
+ * We need two MEM resources - with IPU-common and Image Converter registers,
+ * including PF_CONF and IDMAC_* registers, and two IRQs - function and error
+ */
+static struct platform_driver ipu_platform_driver = {
+ .driver = {
+ .name = "ipu-core",
+ .owner = THIS_MODULE,
+ },
+ .remove = ipu_remove,
+};
+
+static int __init ipu_init(void)
+{
+ return platform_driver_probe(&ipu_platform_driver, ipu_probe);
+}
+subsys_initcall(ipu_init);
+
+MODULE_DESCRIPTION("IPU core driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
+MODULE_ALIAS("platform:ipu-core");
diff --git a/drivers/dma/ipu/ipu_intern.h b/drivers/dma/ipu/ipu_intern.h
new file mode 100644
index 000000000000..545cf11a94ab
--- /dev/null
+++ b/drivers/dma/ipu/ipu_intern.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * Copyright (C) 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _IPU_INTERN_H_
+#define _IPU_INTERN_H_
+
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+/* IPU Common registers */
+#define IPU_CONF 0x00
+#define IPU_CHA_BUF0_RDY 0x04
+#define IPU_CHA_BUF1_RDY 0x08
+#define IPU_CHA_DB_MODE_SEL 0x0C
+#define IPU_CHA_CUR_BUF 0x10
+#define IPU_FS_PROC_FLOW 0x14
+#define IPU_FS_DISP_FLOW 0x18
+#define IPU_TASKS_STAT 0x1C
+#define IPU_IMA_ADDR 0x20
+#define IPU_IMA_DATA 0x24
+#define IPU_INT_CTRL_1 0x28
+#define IPU_INT_CTRL_2 0x2C
+#define IPU_INT_CTRL_3 0x30
+#define IPU_INT_CTRL_4 0x34
+#define IPU_INT_CTRL_5 0x38
+#define IPU_INT_STAT_1 0x3C
+#define IPU_INT_STAT_2 0x40
+#define IPU_INT_STAT_3 0x44
+#define IPU_INT_STAT_4 0x48
+#define IPU_INT_STAT_5 0x4C
+#define IPU_BRK_CTRL_1 0x50
+#define IPU_BRK_CTRL_2 0x54
+#define IPU_BRK_STAT 0x58
+#define IPU_DIAGB_CTRL 0x5C
+
+/* IPU_CONF Register bits */
+#define IPU_CONF_CSI_EN 0x00000001
+#define IPU_CONF_IC_EN 0x00000002
+#define IPU_CONF_ROT_EN 0x00000004
+#define IPU_CONF_PF_EN 0x00000008
+#define IPU_CONF_SDC_EN 0x00000010
+#define IPU_CONF_ADC_EN 0x00000020
+#define IPU_CONF_DI_EN 0x00000040
+#define IPU_CONF_DU_EN 0x00000080
+#define IPU_CONF_PXL_ENDIAN 0x00000100
+
+/* Image Converter Registers */
+#define IC_CONF 0x88
+#define IC_PRP_ENC_RSC 0x8C
+#define IC_PRP_VF_RSC 0x90
+#define IC_PP_RSC 0x94
+#define IC_CMBP_1 0x98
+#define IC_CMBP_2 0x9C
+#define PF_CONF 0xA0
+#define IDMAC_CONF 0xA4
+#define IDMAC_CHA_EN 0xA8
+#define IDMAC_CHA_PRI 0xAC
+#define IDMAC_CHA_BUSY 0xB0
+
+/* Image Converter Register bits */
+#define IC_CONF_PRPENC_EN 0x00000001
+#define IC_CONF_PRPENC_CSC1 0x00000002
+#define IC_CONF_PRPENC_ROT_EN 0x00000004
+#define IC_CONF_PRPVF_EN 0x00000100
+#define IC_CONF_PRPVF_CSC1 0x00000200
+#define IC_CONF_PRPVF_CSC2 0x00000400
+#define IC_CONF_PRPVF_CMB 0x00000800
+#define IC_CONF_PRPVF_ROT_EN 0x00001000
+#define IC_CONF_PP_EN 0x00010000
+#define IC_CONF_PP_CSC1 0x00020000
+#define IC_CONF_PP_CSC2 0x00040000
+#define IC_CONF_PP_CMB 0x00080000
+#define IC_CONF_PP_ROT_EN 0x00100000
+#define IC_CONF_IC_GLB_LOC_A 0x10000000
+#define IC_CONF_KEY_COLOR_EN 0x20000000
+#define IC_CONF_RWS_EN 0x40000000
+#define IC_CONF_CSI_MEM_WR_EN 0x80000000
+
+#define IDMA_CHAN_INVALID 0x000000FF
+#define IDMA_IC_0 0x00000001
+#define IDMA_IC_1 0x00000002
+#define IDMA_IC_2 0x00000004
+#define IDMA_IC_3 0x00000008
+#define IDMA_IC_4 0x00000010
+#define IDMA_IC_5 0x00000020
+#define IDMA_IC_6 0x00000040
+#define IDMA_IC_7 0x00000080
+#define IDMA_IC_8 0x00000100
+#define IDMA_IC_9 0x00000200
+#define IDMA_IC_10 0x00000400
+#define IDMA_IC_11 0x00000800
+#define IDMA_IC_12 0x00001000
+#define IDMA_IC_13 0x00002000
+#define IDMA_SDC_BG 0x00004000
+#define IDMA_SDC_FG 0x00008000
+#define IDMA_SDC_MASK 0x00010000
+#define IDMA_SDC_PARTIAL 0x00020000
+#define IDMA_ADC_SYS1_WR 0x00040000
+#define IDMA_ADC_SYS2_WR 0x00080000
+#define IDMA_ADC_SYS1_CMD 0x00100000
+#define IDMA_ADC_SYS2_CMD 0x00200000
+#define IDMA_ADC_SYS1_RD 0x00400000
+#define IDMA_ADC_SYS2_RD 0x00800000
+#define IDMA_PF_QP 0x01000000
+#define IDMA_PF_BSP 0x02000000
+#define IDMA_PF_Y_IN 0x04000000
+#define IDMA_PF_U_IN 0x08000000
+#define IDMA_PF_V_IN 0x10000000
+#define IDMA_PF_Y_OUT 0x20000000
+#define IDMA_PF_U_OUT 0x40000000
+#define IDMA_PF_V_OUT 0x80000000
+
+#define TSTAT_PF_H264_PAUSE 0x00000001
+#define TSTAT_CSI2MEM_MASK 0x0000000C
+#define TSTAT_CSI2MEM_OFFSET 2
+#define TSTAT_VF_MASK 0x00000600
+#define TSTAT_VF_OFFSET 9
+#define TSTAT_VF_ROT_MASK 0x000C0000
+#define TSTAT_VF_ROT_OFFSET 18
+#define TSTAT_ENC_MASK 0x00000180
+#define TSTAT_ENC_OFFSET 7
+#define TSTAT_ENC_ROT_MASK 0x00030000
+#define TSTAT_ENC_ROT_OFFSET 16
+#define TSTAT_PP_MASK 0x00001800
+#define TSTAT_PP_OFFSET 11
+#define TSTAT_PP_ROT_MASK 0x00300000
+#define TSTAT_PP_ROT_OFFSET 20
+#define TSTAT_PF_MASK 0x00C00000
+#define TSTAT_PF_OFFSET 22
+#define TSTAT_ADCSYS1_MASK 0x03000000
+#define TSTAT_ADCSYS1_OFFSET 24
+#define TSTAT_ADCSYS2_MASK 0x0C000000
+#define TSTAT_ADCSYS2_OFFSET 26
+
+#define TASK_STAT_IDLE 0
+#define TASK_STAT_ACTIVE 1
+#define TASK_STAT_WAIT4READY 2
+
+struct idmac {
+ struct dma_device dma;
+};
+
+struct ipu {
+ void __iomem *reg_ipu;
+ void __iomem *reg_ic;
+ unsigned int irq_fn; /* IPU Function IRQ to the CPU */
+ unsigned int irq_err; /* IPU Error IRQ to the CPU */
+ unsigned int irq_base; /* Beginning of the IPU IRQ range */
+ unsigned long channel_init_mask;
+ spinlock_t lock;
+ struct clk *ipu_clk;
+ struct device *dev;
+ struct idmac idmac;
+ struct idmac_channel channel[IPU_CHANNELS_NUM];
+ struct tasklet_struct tasklet;
+};
+
+#define to_idmac(d) container_of(d, struct idmac, dma)
+
+extern int ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev);
+extern void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev);
+
+extern bool ipu_irq_status(uint32_t irq);
+extern int ipu_irq_map(unsigned int source);
+extern int ipu_irq_unmap(unsigned int source);
+
+#endif
diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c
new file mode 100644
index 000000000000..83f532cc767f
--- /dev/null
+++ b/drivers/dma/ipu/ipu_irq.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2008
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/ipu.h>
+
+#include "ipu_intern.h"
+
+/*
+ * Register read / write - shall be inlined by the compiler
+ */
+static u32 ipu_read_reg(struct ipu *ipu, unsigned long reg)
+{
+ return __raw_readl(ipu->reg_ipu + reg);
+}
+
+static void ipu_write_reg(struct ipu *ipu, u32 value, unsigned long reg)
+{
+ __raw_writel(value, ipu->reg_ipu + reg);
+}
+
+
+/*
+ * IPU IRQ chip driver
+ */
+
+#define IPU_IRQ_NR_FN_BANKS 3
+#define IPU_IRQ_NR_ERR_BANKS 2
+#define IPU_IRQ_NR_BANKS (IPU_IRQ_NR_FN_BANKS + IPU_IRQ_NR_ERR_BANKS)
+
+struct ipu_irq_bank {
+ unsigned int control;
+ unsigned int status;
+ spinlock_t lock;
+ struct ipu *ipu;
+};
+
+static struct ipu_irq_bank irq_bank[IPU_IRQ_NR_BANKS] = {
+ /* 3 groups of functional interrupts */
+ {
+ .control = IPU_INT_CTRL_1,
+ .status = IPU_INT_STAT_1,
+ }, {
+ .control = IPU_INT_CTRL_2,
+ .status = IPU_INT_STAT_2,
+ }, {
+ .control = IPU_INT_CTRL_3,
+ .status = IPU_INT_STAT_3,
+ },
+ /* 2 groups of error interrupts */
+ {
+ .control = IPU_INT_CTRL_4,
+ .status = IPU_INT_STAT_4,
+ }, {
+ .control = IPU_INT_CTRL_5,
+ .status = IPU_INT_STAT_5,
+ },
+};
+
+struct ipu_irq_map {
+ unsigned int irq;
+ int source;
+ struct ipu_irq_bank *bank;
+ struct ipu *ipu;
+};
+
+static struct ipu_irq_map irq_map[CONFIG_MX3_IPU_IRQS];
+/* Protects allocations from the above array of maps */
+static DEFINE_MUTEX(map_lock);
+/* Protects register accesses and individual mappings */
+static DEFINE_SPINLOCK(bank_lock);
+
+static struct ipu_irq_map *src2map(unsigned int src)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++)
+ if (irq_map[i].source == src)
+ return irq_map + i;
+
+ return NULL;
+}
+
+static void ipu_irq_unmask(unsigned int irq)
+{
+ struct ipu_irq_map *map = get_irq_chip_data(irq);
+ struct ipu_irq_bank *bank;
+ uint32_t reg;
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&bank_lock, lock_flags);
+
+ bank = map->bank;
+ if (!bank) {
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+ pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+ return;
+ }
+
+ reg = ipu_read_reg(bank->ipu, bank->control);
+ reg |= (1UL << (map->source & 31));
+ ipu_write_reg(bank->ipu, reg, bank->control);
+
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+}
+
+static void ipu_irq_mask(unsigned int irq)
+{
+ struct ipu_irq_map *map = get_irq_chip_data(irq);
+ struct ipu_irq_bank *bank;
+ uint32_t reg;
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&bank_lock, lock_flags);
+
+ bank = map->bank;
+ if (!bank) {
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+ pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+ return;
+ }
+
+ reg = ipu_read_reg(bank->ipu, bank->control);
+ reg &= ~(1UL << (map->source & 31));
+ ipu_write_reg(bank->ipu, reg, bank->control);
+
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+}
+
+static void ipu_irq_ack(unsigned int irq)
+{
+ struct ipu_irq_map *map = get_irq_chip_data(irq);
+ struct ipu_irq_bank *bank;
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&bank_lock, lock_flags);
+
+ bank = map->bank;
+ if (!bank) {
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+ pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+ return;
+ }
+
+ ipu_write_reg(bank->ipu, 1UL << (map->source & 31), bank->status);
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+}
+
+/**
+ * ipu_irq_status() - returns the current interrupt status of the specified IRQ.
+ * @irq: interrupt line to get status for.
+ * @return: true if the interrupt is pending/asserted or false if the
+ * interrupt is not pending.
+ */
+bool ipu_irq_status(unsigned int irq)
+{
+ struct ipu_irq_map *map = get_irq_chip_data(irq);
+ struct ipu_irq_bank *bank;
+ unsigned long lock_flags;
+ bool ret;
+
+ spin_lock_irqsave(&bank_lock, lock_flags);
+ bank = map->bank;
+ ret = bank && ipu_read_reg(bank->ipu, bank->status) &
+ (1UL << (map->source & 31));
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+
+ return ret;
+}
+
+/**
+ * ipu_irq_map() - map an IPU interrupt source to an IRQ number
+ * @source: interrupt source bit position (see below)
+ * @return: mapped IRQ number or negative error code
+ *
+ * The source parameter has to be explained further. On i.MX31 IPU has 137 IRQ
+ * sources, they are broken down in 5 32-bit registers, like 32, 32, 24, 32, 17.
+ * However, the source argument of this function is not the sequence number of
+ * the possible IRQ, but rather its bit position. So, first interrupt in fourth
+ * register has source number 96, and not 88. This makes calculations easier,
+ * and also provides forward compatibility with any future IPU implementations
+ * with any interrupt bit assignments.
+ */
+int ipu_irq_map(unsigned int source)
+{
+ int i, ret = -ENOMEM;
+ struct ipu_irq_map *map;
+
+ might_sleep();
+
+ mutex_lock(&map_lock);
+ map = src2map(source);
+ if (map) {
+ pr_err("IPU: Source %u already mapped to IRQ %u\n", source, map->irq);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
+ if (irq_map[i].source < 0) {
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&bank_lock, lock_flags);
+ irq_map[i].source = source;
+ irq_map[i].bank = irq_bank + source / 32;
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+
+ ret = irq_map[i].irq;
+ pr_debug("IPU: mapped source %u to IRQ %u\n",
+ source, ret);
+ break;
+ }
+ }
+out:
+ mutex_unlock(&map_lock);
+
+ if (ret < 0)
+ pr_err("IPU: couldn't map source %u: %d\n", source, ret);
+
+ return ret;
+}
+
+/**
+ * ipu_irq_map() - map an IPU interrupt source to an IRQ number
+ * @source: interrupt source bit position (see ipu_irq_map())
+ * @return: 0 or negative error code
+ */
+int ipu_irq_unmap(unsigned int source)
+{
+ int i, ret = -EINVAL;
+
+ might_sleep();
+
+ mutex_lock(&map_lock);
+ for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
+ if (irq_map[i].source == source) {
+ unsigned long lock_flags;
+
+ pr_debug("IPU: unmapped source %u from IRQ %u\n",
+ source, irq_map[i].irq);
+
+ spin_lock_irqsave(&bank_lock, lock_flags);
+ irq_map[i].source = -EINVAL;
+ irq_map[i].bank = NULL;
+ spin_unlock_irqrestore(&bank_lock, lock_flags);
+
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&map_lock);
+
+ return ret;
+}
+
+/* Chained IRQ handler for IPU error interrupt */
+static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
+{
+ struct ipu *ipu = get_irq_data(irq);
+ u32 status;
+ int i, line;
+
+ for (i = IPU_IRQ_NR_FN_BANKS; i < IPU_IRQ_NR_BANKS; i++) {
+ struct ipu_irq_bank *bank = irq_bank + i;
+
+ spin_lock(&bank_lock);
+ status = ipu_read_reg(ipu, bank->status);
+ /*
+ * Don't think we have to clear all interrupts here, they will
+ * be acked by ->handle_irq() (handle_level_irq). However, we
+ * might want to clear unhandled interrupts after the loop...
+ */
+ status &= ipu_read_reg(ipu, bank->control);
+ spin_unlock(&bank_lock);
+ while ((line = ffs(status))) {
+ struct ipu_irq_map *map;
+
+ line--;
+ status &= ~(1UL << line);
+
+ spin_lock(&bank_lock);
+ map = src2map(32 * i + line);
+ if (map)
+ irq = map->irq;
+ spin_unlock(&bank_lock);
+
+ if (!map) {
+ pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
+ line, i);
+ continue;
+ }
+ generic_handle_irq(irq);
+ }
+ }
+}
+
+/* Chained IRQ handler for IPU function interrupt */
+static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc)
+{
+ struct ipu *ipu = get_irq_data(irq);
+ u32 status;
+ int i, line;
+
+ for (i = 0; i < IPU_IRQ_NR_FN_BANKS; i++) {
+ struct ipu_irq_bank *bank = irq_bank + i;
+
+ spin_lock(&bank_lock);
+ status = ipu_read_reg(ipu, bank->status);
+ /* Not clearing all interrupts, see above */
+ status &= ipu_read_reg(ipu, bank->control);
+ spin_unlock(&bank_lock);
+ while ((line = ffs(status))) {
+ struct ipu_irq_map *map;
+
+ line--;
+ status &= ~(1UL << line);
+
+ spin_lock(&bank_lock);
+ map = src2map(32 * i + line);
+ if (map)
+ irq = map->irq;
+ spin_unlock(&bank_lock);
+
+ if (!map) {
+ pr_err("IPU: Interrupt on unmapped source %u bank %d\n",
+ line, i);
+ continue;
+ }
+ generic_handle_irq(irq);
+ }
+ }
+}
+
+static struct irq_chip ipu_irq_chip = {
+ .name = "ipu_irq",
+ .ack = ipu_irq_ack,
+ .mask = ipu_irq_mask,
+ .unmask = ipu_irq_unmask,
+};
+
+/* Install the IRQ handler */
+int ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
+{
+ struct ipu_platform_data *pdata = dev->dev.platform_data;
+ unsigned int irq, irq_base, i;
+
+ irq_base = pdata->irq_base;
+
+ for (i = 0; i < IPU_IRQ_NR_BANKS; i++)
+ irq_bank[i].ipu = ipu;
+
+ for (i = 0; i < CONFIG_MX3_IPU_IRQS; i++) {
+ int ret;
+
+ irq = irq_base + i;
+ ret = set_irq_chip(irq, &ipu_irq_chip);
+ if (ret < 0)
+ return ret;
+ ret = set_irq_chip_data(irq, irq_map + i);
+ if (ret < 0)
+ return ret;
+ irq_map[i].ipu = ipu;
+ irq_map[i].irq = irq;
+ irq_map[i].source = -EINVAL;
+ set_irq_handler(irq, handle_level_irq);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+#endif
+ }
+
+ set_irq_data(ipu->irq_fn, ipu);
+ set_irq_chained_handler(ipu->irq_fn, ipu_irq_fn);
+
+ set_irq_data(ipu->irq_err, ipu);
+ set_irq_chained_handler(ipu->irq_err, ipu_irq_err);
+
+ return 0;
+}
+
+void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev)
+{
+ struct ipu_platform_data *pdata = dev->dev.platform_data;
+ unsigned int irq, irq_base;
+
+ irq_base = pdata->irq_base;
+
+ set_irq_chained_handler(ipu->irq_fn, NULL);
+ set_irq_data(ipu->irq_fn, NULL);
+
+ set_irq_chained_handler(ipu->irq_err, NULL);
+ set_irq_data(ipu->irq_err, NULL);
+
+ for (irq = irq_base; irq < irq_base + CONFIG_MX3_IPU_IRQS; irq++) {
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, 0);
+#endif
+ set_irq_chip(irq, NULL);
+ set_irq_chip_data(irq, NULL);
+ }
+}
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index bcda17426411..d35cbd1ff0b3 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -18,7 +18,6 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/async_tx.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
@@ -340,7 +339,7 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
}
/* run dependent operations */
- async_tx_run_dependencies(&desc->async_tx);
+ dma_run_dependencies(&desc->async_tx);
return cookie;
}
@@ -607,8 +606,7 @@ submit_done:
}
/* returns the number of allocated descriptors */
-static int mv_xor_alloc_chan_resources(struct dma_chan *chan,
- struct dma_client *client)
+static int mv_xor_alloc_chan_resources(struct dma_chan *chan)
{
char *hw_desc;
int idx;
@@ -958,7 +956,7 @@ static int __devinit mv_xor_memcpy_self_test(struct mv_xor_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+ if (mv_xor_alloc_chan_resources(dma_chan) < 1) {
err = -ENODEV;
goto out;
}
@@ -1053,7 +1051,7 @@ mv_xor_xor_self_test(struct mv_xor_device *device)
dma_chan = container_of(device->common.channels.next,
struct dma_chan,
device_node);
- if (mv_xor_alloc_chan_resources(dma_chan, NULL) < 1) {
+ if (mv_xor_alloc_chan_resources(dma_chan) < 1) {
err = -ENODEV;
goto out;
}
@@ -1221,7 +1219,6 @@ static int __devinit mv_xor_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&mv_chan->chain);
INIT_LIST_HEAD(&mv_chan->completed_slots);
INIT_LIST_HEAD(&mv_chan->all_slots);
- INIT_RCU_HEAD(&mv_chan->common.rcu);
mv_chan->common.device = dma_dev;
list_add_tail(&mv_chan->common.device_node, &dma_dev->channels);
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index e2667a8c2997..eee47fd16d79 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -109,6 +109,13 @@ config EDAC_X38
Support for error detection and correction on the Intel
X38 server chipsets.
+config EDAC_I5400
+ tristate "Intel 5400 (Seaburg) chipsets"
+ depends on EDAC_MM_EDAC && PCI && X86
+ help
+ Support for error detection and correction the Intel
+ i5400 MCH chipset (Seaburg).
+
config EDAC_I82860
tristate "Intel 82860"
depends on EDAC_MM_EDAC && PCI && X86_32
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 62c2d9bad8dc..b75196927de3 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -20,6 +20,7 @@ endif
obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
obj-$(CONFIG_EDAC_I5000) += i5000_edac.o
obj-$(CONFIG_EDAC_I5100) += i5100_edac.o
+obj-$(CONFIG_EDAC_I5400) += i5400_edac.o
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index cd2e3b8087e7..24f3ca851523 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -36,7 +36,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
struct csrow_info *csrow = &mci->csrows[0];
unsigned long address, pfn, offset, syndrome;
- dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016lx\n",
+ dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n",
priv->node, chan, ar);
/* Address decoding is likely a bit bogus, to dbl check */
@@ -58,7 +58,7 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
struct csrow_info *csrow = &mci->csrows[0];
unsigned long address, pfn, offset;
- dev_dbg(mci->dev, "ECC UE err on node %d, channel %d, ar = 0x%016lx\n",
+ dev_dbg(mci->dev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n",
priv->node, chan, ar);
/* Address decoding is likely a bit bogus, to dbl check */
@@ -169,7 +169,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev)
/* Get channel population */
reg = in_be64(&regs->mic_mnt_cfg);
- dev_dbg(&pdev->dev, "MIC_MNT_CFG = 0x%016lx\n", reg);
+ dev_dbg(&pdev->dev, "MIC_MNT_CFG = 0x%016llx\n", reg);
chanmask = 0;
if (reg & CBE_MIC_MNT_CFG_CHAN_0_POP)
chanmask |= 0x1;
@@ -180,7 +180,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev)
"Yuck ! No channel populated ? Aborting !\n");
return -ENODEV;
}
- dev_dbg(&pdev->dev, "Initial FIR = 0x%016lx\n",
+ dev_dbg(&pdev->dev, "Initial FIR = 0x%016llx\n",
in_be64(&regs->mic_fir));
/* Allocate & init EDAC MC data structure */
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index 4041e9143283..ca9113e1c106 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -333,7 +333,7 @@ static int add_edac_dev_to_global_list(struct edac_device_ctl_info *edac_dev)
fail0:
edac_printk(KERN_WARNING, EDAC_MC,
"%s (%s) %s %s already assigned %d\n",
- rover->dev->bus_id, edac_dev_name(rover),
+ dev_name(rover->dev), edac_dev_name(rover),
rover->mod_name, rover->ctl_name, rover->dev_idx);
return 1;
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index d110392d48f4..25d66940b4fa 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -401,7 +401,7 @@ static int add_mc_to_global_list(struct mem_ctl_info *mci)
fail0:
edac_printk(KERN_WARNING, EDAC_MC,
- "%s (%s) %s %s already assigned %d\n", p->dev->bus_id,
+ "%s (%s) %s %s already assigned %d\n", dev_name(p->dev),
edac_dev_name(mci), p->mod_name, p->ctl_name, p->mc_idx);
return 1;
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
index 22ec9d5d4312..5d3c8083a40e 100644
--- a/drivers/edac/edac_pci.c
+++ b/drivers/edac/edac_pci.c
@@ -150,7 +150,7 @@ static int add_edac_pci_to_global_list(struct edac_pci_ctl_info *pci)
fail0:
edac_printk(KERN_WARNING, EDAC_PCI,
"%s (%s) %s %s already assigned %d\n",
- rover->dev->bus_id, edac_dev_name(rover),
+ dev_name(rover->dev), edac_dev_name(rover),
rover->mod_name, rover->ctl_name, rover->pci_idx);
return 1;
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index 5c153dccc95e..422728cfe994 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -569,7 +569,7 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
local_irq_restore(flags);
- debugf4("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id);
+ debugf4("PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));
/* check the status reg for errors on boards NOT marked as broken
* if broken, we cannot trust any of the status bits
@@ -600,13 +600,13 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
}
- debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id);
+ debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev_name(&dev->dev));
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
/* On bridges, need to examine secondary status register */
status = get_pci_parity_status(dev, 1);
- debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id);
+ debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));
/* check the secondary status reg for errors,
* on NOT broken boards
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
new file mode 100644
index 000000000000..b08b6d8e2dc7
--- /dev/null
+++ b/drivers/edac/i5400_edac.c
@@ -0,0 +1,1476 @@
+/*
+ * Intel 5400 class Memory Controllers kernel module (Seaburg)
+ *
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Copyright (c) 2008 by:
+ * Ben Woodard <woodard@redhat.com>
+ * Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * Red Hat Inc. http://www.redhat.com
+ *
+ * Forked and adapted from the i5000_edac driver which was
+ * written by Douglas Thompson Linux Networx <norsk5@xmission.com>
+ *
+ * This module is based on the following document:
+ *
+ * Intel 5400 Chipset Memory Controller Hub (MCH) - Datasheet
+ * http://developer.intel.com/design/chipsets/datashts/313070.htm
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/edac.h>
+#include <linux/mmzone.h>
+
+#include "edac_core.h"
+
+/*
+ * Alter this version for the I5400 module when modifications are made
+ */
+#define I5400_REVISION " Ver: 1.0.0 " __DATE__
+
+#define EDAC_MOD_STR "i5400_edac"
+
+#define i5400_printk(level, fmt, arg...) \
+ edac_printk(level, "i5400", fmt, ##arg)
+
+#define i5400_mc_printk(mci, level, fmt, arg...) \
+ edac_mc_chipset_printk(mci, level, "i5400", fmt, ##arg)
+
+/* Limits for i5400 */
+#define NUM_MTRS_PER_BRANCH 4
+#define CHANNELS_PER_BRANCH 2
+#define MAX_CHANNELS 4
+#define MAX_DIMMS (MAX_CHANNELS * 4) /* Up to 4 DIMM's per channel */
+#define MAX_CSROWS (MAX_DIMMS * 2) /* max possible csrows per channel */
+
+/* Device 16,
+ * Function 0: System Address
+ * Function 1: Memory Branch Map, Control, Errors Register
+ * Function 2: FSB Error Registers
+ *
+ * All 3 functions of Device 16 (0,1,2) share the SAME DID and
+ * uses PCI_DEVICE_ID_INTEL_5400_ERR for device 16 (0,1,2),
+ * PCI_DEVICE_ID_INTEL_5400_FBD0 and PCI_DEVICE_ID_INTEL_5400_FBD1
+ * for device 21 (0,1).
+ */
+
+ /* OFFSETS for Function 0 */
+#define AMBASE 0x48 /* AMB Mem Mapped Reg Region Base */
+#define MAXCH 0x56 /* Max Channel Number */
+#define MAXDIMMPERCH 0x57 /* Max DIMM PER Channel Number */
+
+ /* OFFSETS for Function 1 */
+#define TOLM 0x6C
+#define REDMEMB 0x7C
+#define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3fe00) /* bits [17:9] indicate ODD, [8:0] indicate EVEN */
+#define MIR0 0x80
+#define MIR1 0x84
+#define AMIR0 0x8c
+#define AMIR1 0x90
+
+ /* Fatal error registers */
+#define FERR_FAT_FBD 0x98 /* also called as FERR_FAT_FB_DIMM at datasheet */
+#define FERR_FAT_FBDCHAN (3<<28) /* channel index where the highest-order error occurred */
+
+#define NERR_FAT_FBD 0x9c
+#define FERR_NF_FBD 0xa0 /* also called as FERR_NFAT_FB_DIMM at datasheet */
+
+ /* Non-fatal error register */
+#define NERR_NF_FBD 0xa4
+
+ /* Enable error mask */
+#define EMASK_FBD 0xa8
+
+#define ERR0_FBD 0xac
+#define ERR1_FBD 0xb0
+#define ERR2_FBD 0xb4
+#define MCERR_FBD 0xb8
+
+ /* No OFFSETS for Device 16 Function 2 */
+
+/*
+ * Device 21,
+ * Function 0: Memory Map Branch 0
+ *
+ * Device 22,
+ * Function 0: Memory Map Branch 1
+ */
+
+ /* OFFSETS for Function 0 */
+#define AMBPRESENT_0 0x64
+#define AMBPRESENT_1 0x66
+#define MTR0 0x80
+#define MTR1 0x82
+#define MTR2 0x84
+#define MTR3 0x86
+
+ /* OFFSETS for Function 1 */
+#define NRECFGLOG 0x74
+#define RECFGLOG 0x78
+#define NRECMEMA 0xbe
+#define NRECMEMB 0xc0
+#define NRECFB_DIMMA 0xc4
+#define NRECFB_DIMMB 0xc8
+#define NRECFB_DIMMC 0xcc
+#define NRECFB_DIMMD 0xd0
+#define NRECFB_DIMME 0xd4
+#define NRECFB_DIMMF 0xd8
+#define REDMEMA 0xdC
+#define RECMEMA 0xf0
+#define RECMEMB 0xf4
+#define RECFB_DIMMA 0xf8
+#define RECFB_DIMMB 0xec
+#define RECFB_DIMMC 0xf0
+#define RECFB_DIMMD 0xf4
+#define RECFB_DIMME 0xf8
+#define RECFB_DIMMF 0xfC
+
+/*
+ * Error indicator bits and masks
+ * Error masks are according with Table 5-17 of i5400 datasheet
+ */
+
+enum error_mask {
+ EMASK_M1 = 1<<0, /* Memory Write error on non-redundant retry */
+ EMASK_M2 = 1<<1, /* Memory or FB-DIMM configuration CRC read error */
+ EMASK_M3 = 1<<2, /* Reserved */
+ EMASK_M4 = 1<<3, /* Uncorrectable Data ECC on Replay */
+ EMASK_M5 = 1<<4, /* Aliased Uncorrectable Non-Mirrored Demand Data ECC */
+ EMASK_M6 = 1<<5, /* Unsupported on i5400 */
+ EMASK_M7 = 1<<6, /* Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */
+ EMASK_M8 = 1<<7, /* Aliased Uncorrectable Patrol Data ECC */
+ EMASK_M9 = 1<<8, /* Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC */
+ EMASK_M10 = 1<<9, /* Unsupported on i5400 */
+ EMASK_M11 = 1<<10, /* Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC */
+ EMASK_M12 = 1<<11, /* Non-Aliased Uncorrectable Patrol Data ECC */
+ EMASK_M13 = 1<<12, /* Memory Write error on first attempt */
+ EMASK_M14 = 1<<13, /* FB-DIMM Configuration Write error on first attempt */
+ EMASK_M15 = 1<<14, /* Memory or FB-DIMM configuration CRC read error */
+ EMASK_M16 = 1<<15, /* Channel Failed-Over Occurred */
+ EMASK_M17 = 1<<16, /* Correctable Non-Mirrored Demand Data ECC */
+ EMASK_M18 = 1<<17, /* Unsupported on i5400 */
+ EMASK_M19 = 1<<18, /* Correctable Resilver- or Spare-Copy Data ECC */
+ EMASK_M20 = 1<<19, /* Correctable Patrol Data ECC */
+ EMASK_M21 = 1<<20, /* FB-DIMM Northbound parity error on FB-DIMM Sync Status */
+ EMASK_M22 = 1<<21, /* SPD protocol Error */
+ EMASK_M23 = 1<<22, /* Non-Redundant Fast Reset Timeout */
+ EMASK_M24 = 1<<23, /* Refresh error */
+ EMASK_M25 = 1<<24, /* Memory Write error on redundant retry */
+ EMASK_M26 = 1<<25, /* Redundant Fast Reset Timeout */
+ EMASK_M27 = 1<<26, /* Correctable Counter Threshold Exceeded */
+ EMASK_M28 = 1<<27, /* DIMM-Spare Copy Completed */
+ EMASK_M29 = 1<<28, /* DIMM-Isolation Completed */
+};
+
+/*
+ * Names to translate bit error into something useful
+ */
+static const char *error_name[] = {
+ [0] = "Memory Write error on non-redundant retry",
+ [1] = "Memory or FB-DIMM configuration CRC read error",
+ /* Reserved */
+ [3] = "Uncorrectable Data ECC on Replay",
+ [4] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC",
+ /* M6 Unsupported on i5400 */
+ [6] = "Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
+ [7] = "Aliased Uncorrectable Patrol Data ECC",
+ [8] = "Non-Aliased Uncorrectable Non-Mirrored Demand Data ECC",
+ /* M10 Unsupported on i5400 */
+ [10] = "Non-Aliased Uncorrectable Resilver- or Spare-Copy Data ECC",
+ [11] = "Non-Aliased Uncorrectable Patrol Data ECC",
+ [12] = "Memory Write error on first attempt",
+ [13] = "FB-DIMM Configuration Write error on first attempt",
+ [14] = "Memory or FB-DIMM configuration CRC read error",
+ [15] = "Channel Failed-Over Occurred",
+ [16] = "Correctable Non-Mirrored Demand Data ECC",
+ /* M18 Unsupported on i5400 */
+ [18] = "Correctable Resilver- or Spare-Copy Data ECC",
+ [19] = "Correctable Patrol Data ECC",
+ [20] = "FB-DIMM Northbound parity error on FB-DIMM Sync Status",
+ [21] = "SPD protocol Error",
+ [22] = "Non-Redundant Fast Reset Timeout",
+ [23] = "Refresh error",
+ [24] = "Memory Write error on redundant retry",
+ [25] = "Redundant Fast Reset Timeout",
+ [26] = "Correctable Counter Threshold Exceeded",
+ [27] = "DIMM-Spare Copy Completed",
+ [28] = "DIMM-Isolation Completed",
+};
+
+/* Fatal errors */
+#define ERROR_FAT_MASK (EMASK_M1 | \
+ EMASK_M2 | \
+ EMASK_M23)
+
+/* Correctable errors */
+#define ERROR_NF_CORRECTABLE (EMASK_M27 | \
+ EMASK_M20 | \
+ EMASK_M19 | \
+ EMASK_M18 | \
+ EMASK_M17 | \
+ EMASK_M16)
+#define ERROR_NF_DIMM_SPARE (EMASK_M29 | \
+ EMASK_M28)
+#define ERROR_NF_SPD_PROTOCOL (EMASK_M22)
+#define ERROR_NF_NORTH_CRC (EMASK_M21)
+
+/* Recoverable errors */
+#define ERROR_NF_RECOVERABLE (EMASK_M26 | \
+ EMASK_M25 | \
+ EMASK_M24 | \
+ EMASK_M15 | \
+ EMASK_M14 | \
+ EMASK_M13 | \
+ EMASK_M12 | \
+ EMASK_M11 | \
+ EMASK_M9 | \
+ EMASK_M8 | \
+ EMASK_M7 | \
+ EMASK_M5)
+
+/* uncorrectable errors */
+#define ERROR_NF_UNCORRECTABLE (EMASK_M4)
+
+/* mask to all non-fatal errors */
+#define ERROR_NF_MASK (ERROR_NF_CORRECTABLE | \
+ ERROR_NF_UNCORRECTABLE | \
+ ERROR_NF_RECOVERABLE | \
+ ERROR_NF_DIMM_SPARE | \
+ ERROR_NF_SPD_PROTOCOL | \
+ ERROR_NF_NORTH_CRC)
+
+/*
+ * Define error masks for the several registers
+ */
+
+/* Enable all fatal and non fatal errors */
+#define ENABLE_EMASK_ALL (ERROR_FAT_MASK | ERROR_NF_MASK)
+
+/* mask for fatal error registers */
+#define FERR_FAT_MASK ERROR_FAT_MASK
+
+/* masks for non-fatal error register */
+static inline int to_nf_mask(unsigned int mask)
+{
+ return (mask & EMASK_M29) | (mask >> 3);
+};
+
+static inline int from_nf_ferr(unsigned int mask)
+{
+ return (mask & EMASK_M29) | /* Bit 28 */
+ (mask & ((1 << 28) - 1) << 3); /* Bits 0 to 27 */
+};
+
+#define FERR_NF_MASK to_nf_mask(ERROR_NF_MASK)
+#define FERR_NF_CORRECTABLE to_nf_mask(ERROR_NF_CORRECTABLE)
+#define FERR_NF_DIMM_SPARE to_nf_mask(ERROR_NF_DIMM_SPARE)
+#define FERR_NF_SPD_PROTOCOL to_nf_mask(ERROR_NF_SPD_PROTOCOL)
+#define FERR_NF_NORTH_CRC to_nf_mask(ERROR_NF_NORTH_CRC)
+#define FERR_NF_RECOVERABLE to_nf_mask(ERROR_NF_RECOVERABLE)
+#define FERR_NF_UNCORRECTABLE to_nf_mask(ERROR_NF_UNCORRECTABLE)
+
+/* Defines to extract the vaious fields from the
+ * MTRx - Memory Technology Registers
+ */
+#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 10))
+#define MTR_DIMMS_ETHROTTLE(mtr) ((mtr) & (1 << 9))
+#define MTR_DRAM_WIDTH(mtr) (((mtr) & (1 << 8)) ? 8 : 4)
+#define MTR_DRAM_BANKS(mtr) (((mtr) & (1 << 6)) ? 8 : 4)
+#define MTR_DRAM_BANKS_ADDR_BITS(mtr) ((MTR_DRAM_BANKS(mtr) == 8) ? 3 : 2)
+#define MTR_DIMM_RANK(mtr) (((mtr) >> 5) & 0x1)
+#define MTR_DIMM_RANK_ADDR_BITS(mtr) (MTR_DIMM_RANK(mtr) ? 2 : 1)
+#define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3)
+#define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13)
+#define MTR_DIMM_COLS(mtr) ((mtr) & 0x3)
+#define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10)
+
+/* This applies to FERR_NF_FB-DIMM as well as FERR_FAT_FB-DIMM */
+static inline int extract_fbdchan_indx(u32 x)
+{
+ return (x>>28) & 0x3;
+}
+
+#ifdef CONFIG_EDAC_DEBUG
+/* MTR NUMROW */
+static const char *numrow_toString[] = {
+ "8,192 - 13 rows",
+ "16,384 - 14 rows",
+ "32,768 - 15 rows",
+ "65,536 - 16 rows"
+};
+
+/* MTR NUMCOL */
+static const char *numcol_toString[] = {
+ "1,024 - 10 columns",
+ "2,048 - 11 columns",
+ "4,096 - 12 columns",
+ "reserved"
+};
+#endif
+
+/* Device name and register DID (Device ID) */
+struct i5400_dev_info {
+ const char *ctl_name; /* name for this device */
+ u16 fsb_mapping_errors; /* DID for the branchmap,control */
+};
+
+/* Table of devices attributes supported by this driver */
+static const struct i5400_dev_info i5400_devs[] = {
+ {
+ .ctl_name = "I5400",
+ .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_5400_ERR,
+ },
+};
+
+struct i5400_dimm_info {
+ int megabytes; /* size, 0 means not present */
+ int dual_rank;
+};
+
+/* driver private data structure */
+struct i5400_pvt {
+ struct pci_dev *system_address; /* 16.0 */
+ struct pci_dev *branchmap_werrors; /* 16.1 */
+ struct pci_dev *fsb_error_regs; /* 16.2 */
+ struct pci_dev *branch_0; /* 21.0 */
+ struct pci_dev *branch_1; /* 22.0 */
+
+ u16 tolm; /* top of low memory */
+ u64 ambase; /* AMB BAR */
+
+ u16 mir0, mir1;
+
+ u16 b0_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */
+ u16 b0_ambpresent0; /* Branch 0, Channel 0 */
+ u16 b0_ambpresent1; /* Brnach 0, Channel 1 */
+
+ u16 b1_mtr[NUM_MTRS_PER_BRANCH]; /* Memory Technlogy Reg */
+ u16 b1_ambpresent0; /* Branch 1, Channel 8 */
+ u16 b1_ambpresent1; /* Branch 1, Channel 1 */
+
+ /* DIMM information matrix, allocating architecture maximums */
+ struct i5400_dimm_info dimm_info[MAX_CSROWS][MAX_CHANNELS];
+
+ /* Actual values for this controller */
+ int maxch; /* Max channels */
+ int maxdimmperch; /* Max DIMMs per channel */
+};
+
+/* I5400 MCH error information retrieved from Hardware */
+struct i5400_error_info {
+ /* These registers are always read from the MC */
+ u32 ferr_fat_fbd; /* First Errors Fatal */
+ u32 nerr_fat_fbd; /* Next Errors Fatal */
+ u32 ferr_nf_fbd; /* First Errors Non-Fatal */
+ u32 nerr_nf_fbd; /* Next Errors Non-Fatal */
+
+ /* These registers are input ONLY if there was a Recoverable Error */
+ u32 redmemb; /* Recoverable Mem Data Error log B */
+ u16 recmema; /* Recoverable Mem Error log A */
+ u32 recmemb; /* Recoverable Mem Error log B */
+
+ /* These registers are input ONLY if there was a Non-Rec Error */
+ u16 nrecmema; /* Non-Recoverable Mem log A */
+ u16 nrecmemb; /* Non-Recoverable Mem log B */
+
+};
+
+/* note that nrec_rdwr changed from NRECMEMA to NRECMEMB between the 5000 and
+ 5400 better to use an inline function than a macro in this case */
+static inline int nrec_bank(struct i5400_error_info *info)
+{
+ return ((info->nrecmema) >> 12) & 0x7;
+}
+static inline int nrec_rank(struct i5400_error_info *info)
+{
+ return ((info->nrecmema) >> 8) & 0xf;
+}
+static inline int nrec_buf_id(struct i5400_error_info *info)
+{
+ return ((info->nrecmema)) & 0xff;
+}
+static inline int nrec_rdwr(struct i5400_error_info *info)
+{
+ return (info->nrecmemb) >> 31;
+}
+/* This applies to both NREC and REC string so it can be used with nrec_rdwr
+ and rec_rdwr */
+static inline const char *rdwr_str(int rdwr)
+{
+ return rdwr ? "Write" : "Read";
+}
+static inline int nrec_cas(struct i5400_error_info *info)
+{
+ return ((info->nrecmemb) >> 16) & 0x1fff;
+}
+static inline int nrec_ras(struct i5400_error_info *info)
+{
+ return (info->nrecmemb) & 0xffff;
+}
+static inline int rec_bank(struct i5400_error_info *info)
+{
+ return ((info->recmema) >> 12) & 0x7;
+}
+static inline int rec_rank(struct i5400_error_info *info)
+{
+ return ((info->recmema) >> 8) & 0xf;
+}
+static inline int rec_rdwr(struct i5400_error_info *info)
+{
+ return (info->recmemb) >> 31;
+}
+static inline int rec_cas(struct i5400_error_info *info)
+{
+ return ((info->recmemb) >> 16) & 0x1fff;
+}
+static inline int rec_ras(struct i5400_error_info *info)
+{
+ return (info->recmemb) & 0xffff;
+}
+
+static struct edac_pci_ctl_info *i5400_pci;
+
+/*
+ * i5400_get_error_info Retrieve the hardware error information from
+ * the hardware and cache it in the 'info'
+ * structure
+ */
+static void i5400_get_error_info(struct mem_ctl_info *mci,
+ struct i5400_error_info *info)
+{
+ struct i5400_pvt *pvt;
+ u32 value;
+
+ pvt = mci->pvt_info;
+
+ /* read in the 1st FATAL error register */
+ pci_read_config_dword(pvt->branchmap_werrors, FERR_FAT_FBD, &value);
+
+ /* Mask only the bits that the doc says are valid
+ */
+ value &= (FERR_FAT_FBDCHAN | FERR_FAT_MASK);
+
+ /* If there is an error, then read in the
+ NEXT FATAL error register and the Memory Error Log Register A
+ */
+ if (value & FERR_FAT_MASK) {
+ info->ferr_fat_fbd = value;
+
+ /* harvest the various error data we need */
+ pci_read_config_dword(pvt->branchmap_werrors,
+ NERR_FAT_FBD, &info->nerr_fat_fbd);
+ pci_read_config_word(pvt->branchmap_werrors,
+ NRECMEMA, &info->nrecmema);
+ pci_read_config_word(pvt->branchmap_werrors,
+ NRECMEMB, &info->nrecmemb);
+
+ /* Clear the error bits, by writing them back */
+ pci_write_config_dword(pvt->branchmap_werrors,
+ FERR_FAT_FBD, value);
+ } else {
+ info->ferr_fat_fbd = 0;
+ info->nerr_fat_fbd = 0;
+ info->nrecmema = 0;
+ info->nrecmemb = 0;
+ }
+
+ /* read in the 1st NON-FATAL error register */
+ pci_read_config_dword(pvt->branchmap_werrors, FERR_NF_FBD, &value);
+
+ /* If there is an error, then read in the 1st NON-FATAL error
+ * register as well */
+ if (value & FERR_NF_MASK) {
+ info->ferr_nf_fbd = value;
+
+ /* harvest the various error data we need */
+ pci_read_config_dword(pvt->branchmap_werrors,
+ NERR_NF_FBD, &info->nerr_nf_fbd);
+ pci_read_config_word(pvt->branchmap_werrors,
+ RECMEMA, &info->recmema);
+ pci_read_config_dword(pvt->branchmap_werrors,
+ RECMEMB, &info->recmemb);
+ pci_read_config_dword(pvt->branchmap_werrors,
+ REDMEMB, &info->redmemb);
+
+ /* Clear the error bits, by writing them back */
+ pci_write_config_dword(pvt->branchmap_werrors,
+ FERR_NF_FBD, value);
+ } else {
+ info->ferr_nf_fbd = 0;
+ info->nerr_nf_fbd = 0;
+ info->recmema = 0;
+ info->recmemb = 0;
+ info->redmemb = 0;
+ }
+}
+
+/*
+ * i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci,
+ * struct i5400_error_info *info,
+ * int handle_errors);
+ *
+ * handle the Intel FATAL and unrecoverable errors, if any
+ */
+static void i5400_proccess_non_recoverable_info(struct mem_ctl_info *mci,
+ struct i5400_error_info *info,
+ unsigned long allErrors)
+{
+ char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80];
+ int branch;
+ int channel;
+ int bank;
+ int buf_id;
+ int rank;
+ int rdwr;
+ int ras, cas;
+ int errnum;
+ char *type = NULL;
+
+ if (!allErrors)
+ return; /* if no error, return now */
+
+ if (allErrors & ERROR_FAT_MASK)
+ type = "FATAL";
+ else if (allErrors & FERR_NF_UNCORRECTABLE)
+ type = "NON-FATAL uncorrected";
+ else
+ type = "NON-FATAL recoverable";
+
+ /* ONLY ONE of the possible error bits will be set, as per the docs */
+
+ branch = extract_fbdchan_indx(info->ferr_fat_fbd);
+ channel = branch;
+
+ /* Use the NON-Recoverable macros to extract data */
+ bank = nrec_bank(info);
+ rank = nrec_rank(info);
+ buf_id = nrec_buf_id(info);
+ rdwr = nrec_rdwr(info);
+ ras = nrec_ras(info);
+ cas = nrec_cas(info);
+
+ debugf0("\t\tCSROW= %d Channels= %d,%d (Branch= %d "
+ "DRAM Bank= %d Buffer ID = %d rdwr= %s ras= %d cas= %d)\n",
+ rank, channel, channel + 1, branch >> 1, bank,
+ buf_id, rdwr_str(rdwr), ras, cas);
+
+ /* Only 1 bit will be on */
+ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name));
+
+ /* Form out message */
+ snprintf(msg, sizeof(msg),
+ "%s (Branch=%d DRAM-Bank=%d Buffer ID = %d RDWR=%s "
+ "RAS=%d CAS=%d %s Err=0x%lx (%s))",
+ type, branch >> 1, bank, buf_id, rdwr_str(rdwr), ras, cas,
+ type, allErrors, error_name[errnum]);
+
+ /* Call the helper to output message */
+ edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
+}
+
+/*
+ * i5400_process_fatal_error_info(struct mem_ctl_info *mci,
+ * struct i5400_error_info *info,
+ * int handle_errors);
+ *
+ * handle the Intel NON-FATAL errors, if any
+ */
+static void i5400_process_nonfatal_error_info(struct mem_ctl_info *mci,
+ struct i5400_error_info *info)
+{
+ char msg[EDAC_MC_LABEL_LEN + 1 + 90 + 80];
+ unsigned long allErrors;
+ int branch;
+ int channel;
+ int bank;
+ int rank;
+ int rdwr;
+ int ras, cas;
+ int errnum;
+
+ /* mask off the Error bits that are possible */
+ allErrors = from_nf_ferr(info->ferr_nf_fbd & FERR_NF_MASK);
+ if (!allErrors)
+ return; /* if no error, return now */
+
+ /* ONLY ONE of the possible error bits will be set, as per the docs */
+
+ if (allErrors & (ERROR_NF_UNCORRECTABLE | ERROR_NF_RECOVERABLE)) {
+ i5400_proccess_non_recoverable_info(mci, info, allErrors);
+ return;
+ }
+
+ /* Correctable errors */
+ if (allErrors & ERROR_NF_CORRECTABLE) {
+ debugf0("\tCorrected bits= 0x%lx\n", allErrors);
+
+ branch = extract_fbdchan_indx(info->ferr_nf_fbd);
+
+ channel = 0;
+ if (REC_ECC_LOCATOR_ODD(info->redmemb))
+ channel = 1;
+
+ /* Convert channel to be based from zero, instead of
+ * from branch base of 0 */
+ channel += branch;
+
+ bank = rec_bank(info);
+ rank = rec_rank(info);
+ rdwr = rec_rdwr(info);
+ ras = rec_ras(info);
+ cas = rec_cas(info);
+
+ /* Only 1 bit will be on */
+ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name));
+
+ debugf0("\t\tCSROW= %d Channel= %d (Branch %d "
+ "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
+ rank, channel, branch >> 1, bank,
+ rdwr_str(rdwr), ras, cas);
+
+ /* Form out message */
+ snprintf(msg, sizeof(msg),
+ "Corrected error (Branch=%d DRAM-Bank=%d RDWR=%s "
+ "RAS=%d CAS=%d, CE Err=0x%lx (%s))",
+ branch >> 1, bank, rdwr_str(rdwr), ras, cas,
+ allErrors, error_name[errnum]);
+
+ /* Call the helper to output message */
+ edac_mc_handle_fbd_ce(mci, rank, channel, msg);
+
+ return;
+ }
+
+ /* Miscelaneous errors */
+ errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name));
+
+ branch = extract_fbdchan_indx(info->ferr_nf_fbd);
+
+ i5400_mc_printk(mci, KERN_EMERG,
+ "Non-Fatal misc error (Branch=%d Err=%#lx (%s))",
+ branch >> 1, allErrors, error_name[errnum]);
+}
+
+/*
+ * i5400_process_error_info Process the error info that is
+ * in the 'info' structure, previously retrieved from hardware
+ */
+static void i5400_process_error_info(struct mem_ctl_info *mci,
+ struct i5400_error_info *info)
+{ u32 allErrors;
+
+ /* First handle any fatal errors that occurred */
+ allErrors = (info->ferr_fat_fbd & FERR_FAT_MASK);
+ i5400_proccess_non_recoverable_info(mci, info, allErrors);
+
+ /* now handle any non-fatal errors that occurred */
+ i5400_process_nonfatal_error_info(mci, info);
+}
+
+/*
+ * i5400_clear_error Retrieve any error from the hardware
+ * but do NOT process that error.
+ * Used for 'clearing' out of previous errors
+ * Called by the Core module.
+ */
+static void i5400_clear_error(struct mem_ctl_info *mci)
+{
+ struct i5400_error_info info;
+
+ i5400_get_error_info(mci, &info);
+}
+
+/*
+ * i5400_check_error Retrieve and process errors reported by the
+ * hardware. Called by the Core module.
+ */
+static void i5400_check_error(struct mem_ctl_info *mci)
+{
+ struct i5400_error_info info;
+ debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
+ i5400_get_error_info(mci, &info);
+ i5400_process_error_info(mci, &info);
+}
+
+/*
+ * i5400_put_devices 'put' all the devices that we have
+ * reserved via 'get'
+ */
+static void i5400_put_devices(struct mem_ctl_info *mci)
+{
+ struct i5400_pvt *pvt;
+
+ pvt = mci->pvt_info;
+
+ /* Decrement usage count for devices */
+ pci_dev_put(pvt->branch_1);
+ pci_dev_put(pvt->branch_0);
+ pci_dev_put(pvt->fsb_error_regs);
+ pci_dev_put(pvt->branchmap_werrors);
+}
+
+/*
+ * i5400_get_devices Find and perform 'get' operation on the MCH's
+ * device/functions we want to reference for this driver
+ *
+ * Need to 'get' device 16 func 1 and func 2
+ */
+static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
+{
+ struct i5400_pvt *pvt;
+ struct pci_dev *pdev;
+
+ pvt = mci->pvt_info;
+ pvt->branchmap_werrors = NULL;
+ pvt->fsb_error_regs = NULL;
+ pvt->branch_0 = NULL;
+ pvt->branch_1 = NULL;
+
+ /* Attempt to 'get' the MCH register we want */
+ pdev = NULL;
+ while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) {
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
+ if (!pdev) {
+ /* End of list, leave */
+ i5400_printk(KERN_ERR,
+ "'system address,Process Bus' "
+ "device not found:"
+ "vendor 0x%x device 0x%x ERR funcs "
+ "(broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5400_ERR);
+ goto error;
+ }
+
+ /* Store device 16 funcs 1 and 2 */
+ switch (PCI_FUNC(pdev->devfn)) {
+ case 1:
+ pvt->branchmap_werrors = pdev;
+ break;
+ case 2:
+ pvt->fsb_error_regs = pdev;
+ break;
+ }
+ }
+
+ debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n",
+ pci_name(pvt->system_address),
+ pvt->system_address->vendor, pvt->system_address->device);
+ debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n",
+ pci_name(pvt->branchmap_werrors),
+ pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device);
+ debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n",
+ pci_name(pvt->fsb_error_regs),
+ pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device);
+
+ pvt->branch_0 = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5400_FBD0, NULL);
+ if (!pvt->branch_0) {
+ i5400_printk(KERN_ERR,
+ "MC: 'BRANCH 0' device not found:"
+ "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0);
+ goto error;
+ }
+
+ /* If this device claims to have more than 2 channels then
+ * fetch Branch 1's information
+ */
+ if (pvt->maxch < CHANNELS_PER_BRANCH)
+ return 0;
+
+ pvt->branch_1 = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5400_FBD1, NULL);
+ if (!pvt->branch_1) {
+ i5400_printk(KERN_ERR,
+ "MC: 'BRANCH 1' device not found:"
+ "vendor 0x%x device 0x%x Func 0 "
+ "(broken BIOS?)\n",
+ PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_5400_FBD1);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ i5400_put_devices(mci);
+ return -ENODEV;
+}
+
+/*
+ * determine_amb_present
+ *
+ * the information is contained in NUM_MTRS_PER_BRANCH different
+ * registers determining which of the NUM_MTRS_PER_BRANCH requires
+ * knowing which channel is in question
+ *
+ * 2 branches, each with 2 channels
+ * b0_ambpresent0 for channel '0'
+ * b0_ambpresent1 for channel '1'
+ * b1_ambpresent0 for channel '2'
+ * b1_ambpresent1 for channel '3'
+ */
+static int determine_amb_present_reg(struct i5400_pvt *pvt, int channel)
+{
+ int amb_present;
+
+ if (channel < CHANNELS_PER_BRANCH) {
+ if (channel & 0x1)
+ amb_present = pvt->b0_ambpresent1;
+ else
+ amb_present = pvt->b0_ambpresent0;
+ } else {
+ if (channel & 0x1)
+ amb_present = pvt->b1_ambpresent1;
+ else
+ amb_present = pvt->b1_ambpresent0;
+ }
+
+ return amb_present;
+}
+
+/*
+ * determine_mtr(pvt, csrow, channel)
+ *
+ * return the proper MTR register as determine by the csrow and desired channel
+ */
+static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel)
+{
+ int mtr;
+ int n;
+
+ /* There is one MTR for each slot pair of FB-DIMMs,
+ Each slot may have one or two ranks (2 csrows),
+ Each slot pair may be at branch 0 or branch 1.
+ So, csrow should be divided by eight
+ */
+ n = csrow >> 3;
+
+ if (n >= NUM_MTRS_PER_BRANCH) {
+ debugf0("ERROR: trying to access an invalid csrow: %d\n",
+ csrow);
+ return 0;
+ }
+
+ if (channel < CHANNELS_PER_BRANCH)
+ mtr = pvt->b0_mtr[n];
+ else
+ mtr = pvt->b1_mtr[n];
+
+ return mtr;
+}
+
+/*
+ */
+static void decode_mtr(int slot_row, u16 mtr)
+{
+ int ans;
+
+ ans = MTR_DIMMS_PRESENT(mtr);
+
+ debugf2("\tMTR%d=0x%x: DIMMs are %s\n", slot_row, mtr,
+ ans ? "Present" : "NOT Present");
+ if (!ans)
+ return;
+
+ debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
+
+ debugf2("\t\tELECTRICAL THROTTLING is %s\n",
+ MTR_DIMMS_ETHROTTLE(mtr) ? "enabled" : "disabled");
+
+ debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
+ debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single");
+ debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]);
+ debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
+}
+
+static void handle_channel(struct i5400_pvt *pvt, int csrow, int channel,
+ struct i5400_dimm_info *dinfo)
+{
+ int mtr;
+ int amb_present_reg;
+ int addrBits;
+
+ mtr = determine_mtr(pvt, csrow, channel);
+ if (MTR_DIMMS_PRESENT(mtr)) {
+ amb_present_reg = determine_amb_present_reg(pvt, channel);
+
+ /* Determine if there is a DIMM present in this DIMM slot */
+ if (amb_present_reg & (1 << (csrow >> 1))) {
+ dinfo->dual_rank = MTR_DIMM_RANK(mtr);
+
+ if (!((dinfo->dual_rank == 0) &&
+ ((csrow & 0x1) == 0x1))) {
+ /* Start with the number of bits for a Bank
+ * on the DRAM */
+ addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
+ /* Add thenumber of ROW bits */
+ addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
+ /* add the number of COLUMN bits */
+ addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
+
+ addrBits += 6; /* add 64 bits per DIMM */
+ addrBits -= 20; /* divide by 2^^20 */
+ addrBits -= 3; /* 8 bits per bytes */
+
+ dinfo->megabytes = 1 << addrBits;
+ }
+ }
+ }
+}
+
+/*
+ * calculate_dimm_size
+ *
+ * also will output a DIMM matrix map, if debug is enabled, for viewing
+ * how the DIMMs are populated
+ */
+static void calculate_dimm_size(struct i5400_pvt *pvt)
+{
+ struct i5400_dimm_info *dinfo;
+ int csrow, max_csrows;
+ char *p, *mem_buffer;
+ int space, n;
+ int channel;
+
+ /* ================= Generate some debug output ================= */
+ space = PAGE_SIZE;
+ mem_buffer = p = kmalloc(space, GFP_KERNEL);
+ if (p == NULL) {
+ i5400_printk(KERN_ERR, "MC: %s:%s() kmalloc() failed\n",
+ __FILE__, __func__);
+ return;
+ }
+
+ /* Scan all the actual CSROWS (which is # of DIMMS * 2)
+ * and calculate the information for each DIMM
+ * Start with the highest csrow first, to display it first
+ * and work toward the 0th csrow
+ */
+ max_csrows = pvt->maxdimmperch * 2;
+ for (csrow = max_csrows - 1; csrow >= 0; csrow--) {
+
+ /* on an odd csrow, first output a 'boundary' marker,
+ * then reset the message buffer */
+ if (csrow & 0x1) {
+ n = snprintf(p, space, "---------------------------"
+ "--------------------------------");
+ p += n;
+ space -= n;
+ debugf2("%s\n", mem_buffer);
+ p = mem_buffer;
+ space = PAGE_SIZE;
+ }
+ n = snprintf(p, space, "csrow %2d ", csrow);
+ p += n;
+ space -= n;
+
+ for (channel = 0; channel < pvt->maxch; channel++) {
+ dinfo = &pvt->dimm_info[csrow][channel];
+ handle_channel(pvt, csrow, channel, dinfo);
+ n = snprintf(p, space, "%4d MB | ", dinfo->megabytes);
+ p += n;
+ space -= n;
+ }
+ debugf2("%s\n", mem_buffer);
+ p = mem_buffer;
+ space = PAGE_SIZE;
+ }
+
+ /* Output the last bottom 'boundary' marker */
+ n = snprintf(p, space, "---------------------------"
+ "--------------------------------");
+ p += n;
+ space -= n;
+ debugf2("%s\n", mem_buffer);
+ p = mem_buffer;
+ space = PAGE_SIZE;
+
+ /* now output the 'channel' labels */
+ n = snprintf(p, space, " ");
+ p += n;
+ space -= n;
+ for (channel = 0; channel < pvt->maxch; channel++) {
+ n = snprintf(p, space, "channel %d | ", channel);
+ p += n;
+ space -= n;
+ }
+
+ /* output the last message and free buffer */
+ debugf2("%s\n", mem_buffer);
+ kfree(mem_buffer);
+}
+
+/*
+ * i5400_get_mc_regs read in the necessary registers and
+ * cache locally
+ *
+ * Fills in the private data members
+ */
+static void i5400_get_mc_regs(struct mem_ctl_info *mci)
+{
+ struct i5400_pvt *pvt;
+ u32 actual_tolm;
+ u16 limit;
+ int slot_row;
+ int maxch;
+ int maxdimmperch;
+ int way0, way1;
+
+ pvt = mci->pvt_info;
+
+ pci_read_config_dword(pvt->system_address, AMBASE,
+ (u32 *) &pvt->ambase);
+ pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32),
+ ((u32 *) &pvt->ambase) + sizeof(u32));
+
+ maxdimmperch = pvt->maxdimmperch;
+ maxch = pvt->maxch;
+
+ debugf2("AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n",
+ (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch);
+
+ /* Get the Branch Map regs */
+ pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm);
+ pvt->tolm >>= 12;
+ debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm,
+ pvt->tolm);
+
+ actual_tolm = (u32) ((1000l * pvt->tolm) >> (30 - 28));
+ debugf2("Actual TOLM byte addr=%u.%03u GB (0x%x)\n",
+ actual_tolm/1000, actual_tolm % 1000, pvt->tolm << 28);
+
+ pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0);
+ pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1);
+
+ /* Get the MIR[0-1] regs */
+ limit = (pvt->mir0 >> 4) & 0x0fff;
+ way0 = pvt->mir0 & 0x1;
+ way1 = pvt->mir0 & 0x2;
+ debugf2("MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0);
+ limit = (pvt->mir1 >> 4) & 0xfff;
+ way0 = pvt->mir1 & 0x1;
+ way1 = pvt->mir1 & 0x2;
+ debugf2("MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0);
+
+ /* Get the set of MTR[0-3] regs by each branch */
+ for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) {
+ int where = MTR0 + (slot_row * sizeof(u32));
+
+ /* Branch 0 set of MTR registers */
+ pci_read_config_word(pvt->branch_0, where,
+ &pvt->b0_mtr[slot_row]);
+
+ debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where,
+ pvt->b0_mtr[slot_row]);
+
+ if (pvt->maxch < CHANNELS_PER_BRANCH) {
+ pvt->b1_mtr[slot_row] = 0;
+ continue;
+ }
+
+ /* Branch 1 set of MTR registers */
+ pci_read_config_word(pvt->branch_1, where,
+ &pvt->b1_mtr[slot_row]);
+ debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, where,
+ pvt->b1_mtr[slot_row]);
+ }
+
+ /* Read and dump branch 0's MTRs */
+ debugf2("\nMemory Technology Registers:\n");
+ debugf2(" Branch 0:\n");
+ for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++)
+ decode_mtr(slot_row, pvt->b0_mtr[slot_row]);
+
+ pci_read_config_word(pvt->branch_0, AMBPRESENT_0,
+ &pvt->b0_ambpresent0);
+ debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0);
+ pci_read_config_word(pvt->branch_0, AMBPRESENT_1,
+ &pvt->b0_ambpresent1);
+ debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1);
+
+ /* Only if we have 2 branchs (4 channels) */
+ if (pvt->maxch < CHANNELS_PER_BRANCH) {
+ pvt->b1_ambpresent0 = 0;
+ pvt->b1_ambpresent1 = 0;
+ } else {
+ /* Read and dump branch 1's MTRs */
+ debugf2(" Branch 1:\n");
+ for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++)
+ decode_mtr(slot_row, pvt->b1_mtr[slot_row]);
+
+ pci_read_config_word(pvt->branch_1, AMBPRESENT_0,
+ &pvt->b1_ambpresent0);
+ debugf2("\t\tAMB-Branch 1-present0 0x%x:\n",
+ pvt->b1_ambpresent0);
+ pci_read_config_word(pvt->branch_1, AMBPRESENT_1,
+ &pvt->b1_ambpresent1);
+ debugf2("\t\tAMB-Branch 1-present1 0x%x:\n",
+ pvt->b1_ambpresent1);
+ }
+
+ /* Go and determine the size of each DIMM and place in an
+ * orderly matrix */
+ calculate_dimm_size(pvt);
+}
+
+/*
+ * i5400_init_csrows Initialize the 'csrows' table within
+ * the mci control structure with the
+ * addressing of memory.
+ *
+ * return:
+ * 0 success
+ * 1 no actual memory found on this MC
+ */
+static int i5400_init_csrows(struct mem_ctl_info *mci)
+{
+ struct i5400_pvt *pvt;
+ struct csrow_info *p_csrow;
+ int empty, channel_count;
+ int max_csrows;
+ int mtr;
+ int csrow_megs;
+ int channel;
+ int csrow;
+
+ pvt = mci->pvt_info;
+
+ channel_count = pvt->maxch;
+ max_csrows = pvt->maxdimmperch * 2;
+
+ empty = 1; /* Assume NO memory */
+
+ for (csrow = 0; csrow < max_csrows; csrow++) {
+ p_csrow = &mci->csrows[csrow];
+
+ p_csrow->csrow_idx = csrow;
+
+ /* use branch 0 for the basis */
+ mtr = determine_mtr(pvt, csrow, 0);
+
+ /* if no DIMMS on this row, continue */
+ if (!MTR_DIMMS_PRESENT(mtr))
+ continue;
+
+ /* FAKE OUT VALUES, FIXME */
+ p_csrow->first_page = 0 + csrow * 20;
+ p_csrow->last_page = 9 + csrow * 20;
+ p_csrow->page_mask = 0xFFF;
+
+ p_csrow->grain = 8;
+
+ csrow_megs = 0;
+ for (channel = 0; channel < pvt->maxch; channel++)
+ csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
+
+ p_csrow->nr_pages = csrow_megs << 8;
+
+ /* Assume DDR2 for now */
+ p_csrow->mtype = MEM_FB_DDR2;
+
+ /* ask what device type on this row */
+ if (MTR_DRAM_WIDTH(mtr))
+ p_csrow->dtype = DEV_X8;
+ else
+ p_csrow->dtype = DEV_X4;
+
+ p_csrow->edac_mode = EDAC_S8ECD8ED;
+
+ empty = 0;
+ }
+
+ return empty;
+}
+
+/*
+ * i5400_enable_error_reporting
+ * Turn on the memory reporting features of the hardware
+ */
+static void i5400_enable_error_reporting(struct mem_ctl_info *mci)
+{
+ struct i5400_pvt *pvt;
+ u32 fbd_error_mask;
+
+ pvt = mci->pvt_info;
+
+ /* Read the FBD Error Mask Register */
+ pci_read_config_dword(pvt->branchmap_werrors, EMASK_FBD,
+ &fbd_error_mask);
+
+ /* Enable with a '0' */
+ fbd_error_mask &= ~(ENABLE_EMASK_ALL);
+
+ pci_write_config_dword(pvt->branchmap_werrors, EMASK_FBD,
+ fbd_error_mask);
+}
+
+/*
+ * i5400_get_dimm_and_channel_counts(pdev, &num_csrows, &num_channels)
+ *
+ * ask the device how many channels are present and how many CSROWS
+ * as well
+ */
+static void i5400_get_dimm_and_channel_counts(struct pci_dev *pdev,
+ int *num_dimms_per_channel,
+ int *num_channels)
+{
+ u8 value;
+
+ /* Need to retrieve just how many channels and dimms per channel are
+ * supported on this memory controller
+ */
+ pci_read_config_byte(pdev, MAXDIMMPERCH, &value);
+ *num_dimms_per_channel = (int)value * 2;
+
+ pci_read_config_byte(pdev, MAXCH, &value);
+ *num_channels = (int)value;
+}
+
+/*
+ * i5400_probe1 Probe for ONE instance of device to see if it is
+ * present.
+ * return:
+ * 0 for FOUND a device
+ * < 0 for error code
+ */
+static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
+{
+ struct mem_ctl_info *mci;
+ struct i5400_pvt *pvt;
+ int num_channels;
+ int num_dimms_per_channel;
+ int num_csrows;
+
+ if (dev_idx >= ARRAY_SIZE(i5400_devs))
+ return -EINVAL;
+
+ debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n",
+ __func__,
+ pdev->bus->number,
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+ /* We only are looking for func 0 of the set */
+ if (PCI_FUNC(pdev->devfn) != 0)
+ return -ENODEV;
+
+ /* Ask the devices for the number of CSROWS and CHANNELS so
+ * that we can calculate the memory resources, etc
+ *
+ * The Chipset will report what it can handle which will be greater
+ * or equal to what the motherboard manufacturer will implement.
+ *
+ * As we don't have a motherboard identification routine to determine
+ * actual number of slots/dimms per channel, we thus utilize the
+ * resource as specified by the chipset. Thus, we might have
+ * have more DIMMs per channel than actually on the mobo, but this
+ * allows the driver to support upto the chipset max, without
+ * some fancy mobo determination.
+ */
+ i5400_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel,
+ &num_channels);
+ num_csrows = num_dimms_per_channel * 2;
+
+ debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n",
+ __func__, num_channels, num_dimms_per_channel, num_csrows);
+
+ /* allocate a new MC control structure */
+ mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
+
+ if (mci == NULL)
+ return -ENOMEM;
+
+ debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
+
+ mci->dev = &pdev->dev; /* record ptr to the generic device */
+
+ pvt = mci->pvt_info;
+ pvt->system_address = pdev; /* Record this device in our private */
+ pvt->maxch = num_channels;
+ pvt->maxdimmperch = num_dimms_per_channel;
+
+ /* 'get' the pci devices we want to reserve for our use */
+ if (i5400_get_devices(mci, dev_idx))
+ goto fail0;
+
+ /* Time to get serious */
+ i5400_get_mc_regs(mci); /* retrieve the hardware registers */
+
+ mci->mc_idx = 0;
+ mci->mtype_cap = MEM_FLAG_FB_DDR2;
+ mci->edac_ctl_cap = EDAC_FLAG_NONE;
+ mci->edac_cap = EDAC_FLAG_NONE;
+ mci->mod_name = "i5400_edac.c";
+ mci->mod_ver = I5400_REVISION;
+ mci->ctl_name = i5400_devs[dev_idx].ctl_name;
+ mci->dev_name = pci_name(pdev);
+ mci->ctl_page_to_phys = NULL;
+
+ /* Set the function pointer to an actual operation function */
+ mci->edac_check = i5400_check_error;
+
+ /* initialize the MC control structure 'csrows' table
+ * with the mapping and control information */
+ if (i5400_init_csrows(mci)) {
+ debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n"
+ " because i5400_init_csrows() returned nonzero "
+ "value\n");
+ mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */
+ } else {
+ debugf1("MC: Enable error reporting now\n");
+ i5400_enable_error_reporting(mci);
+ }
+
+ /* add this new MC control structure to EDAC's list of MCs */
+ if (edac_mc_add_mc(mci)) {
+ debugf0("MC: " __FILE__
+ ": %s(): failed edac_mc_add_mc()\n", __func__);
+ /* FIXME: perhaps some code should go here that disables error
+ * reporting if we just enabled it
+ */
+ goto fail1;
+ }
+
+ i5400_clear_error(mci);
+
+ /* allocating generic PCI control info */
+ i5400_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
+ if (!i5400_pci) {
+ printk(KERN_WARNING
+ "%s(): Unable to create PCI control\n",
+ __func__);
+ printk(KERN_WARNING
+ "%s(): PCI error report via EDAC not setup\n",
+ __func__);
+ }
+
+ return 0;
+
+ /* Error exit unwinding stack */
+fail1:
+
+ i5400_put_devices(mci);
+
+fail0:
+ edac_mc_free(mci);
+ return -ENODEV;
+}
+
+/*
+ * i5400_init_one constructor for one instance of device
+ *
+ * returns:
+ * negative on error
+ * count (>= 0)
+ */
+static int __devinit i5400_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int rc;
+
+ debugf0("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* wake up device */
+ rc = pci_enable_device(pdev);
+ if (rc == -EIO)
+ return rc;
+
+ /* now probe and enable the device */
+ return i5400_probe1(pdev, id->driver_data);
+}
+
+/*
+ * i5400_remove_one destructor for one instance of device
+ *
+ */
+static void __devexit i5400_remove_one(struct pci_dev *pdev)
+{
+ struct mem_ctl_info *mci;
+
+ debugf0(__FILE__ ": %s()\n", __func__);
+
+ if (i5400_pci)
+ edac_pci_release_generic_ctl(i5400_pci);
+
+ mci = edac_mc_del_mc(&pdev->dev);
+ if (!mci)
+ return;
+
+ /* retrieve references to resources, and free those resources */
+ i5400_put_devices(mci);
+
+ edac_mc_free(mci);
+}
+
+/*
+ * pci_device_id table for which devices we are looking for
+ *
+ * The "E500P" device is the first device supported.
+ */
+static const struct pci_device_id i5400_pci_tbl[] __devinitdata = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR)},
+ {0,} /* 0 terminated list. */
+};
+
+MODULE_DEVICE_TABLE(pci, i5400_pci_tbl);
+
+/*
+ * i5400_driver pci_driver structure for this module
+ *
+ */
+static struct pci_driver i5400_driver = {
+ .name = "i5400_edac",
+ .probe = i5400_init_one,
+ .remove = __devexit_p(i5400_remove_one),
+ .id_table = i5400_pci_tbl,
+};
+
+/*
+ * i5400_init Module entry function
+ * Try to initialize this module for its devices
+ */
+static int __init i5400_init(void)
+{
+ int pci_rc;
+
+ debugf2("MC: " __FILE__ ": %s()\n", __func__);
+
+ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+ opstate_init();
+
+ pci_rc = pci_register_driver(&i5400_driver);
+
+ return (pci_rc < 0) ? pci_rc : 0;
+}
+
+/*
+ * i5400_exit() Module exit function
+ * Unregister the driver
+ */
+static void __exit i5400_exit(void)
+{
+ debugf2("MC: " __FILE__ ": %s()\n", __func__);
+ pci_unregister_driver(&i5400_driver);
+}
+
+module_init(i5400_init);
+module_exit(i5400_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Woodard <woodard@redhat.com>");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("MC Driver for Intel I5400 memory controllers - "
+ I5400_REVISION);
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index ebb037b78758..b2d83b95033d 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -311,9 +311,7 @@ static int i82875p_setup_overfl_dev(struct pci_dev *pdev,
}
/* cache is irrelevant for PCI bus reads/writes */
- window = ioremap_nocache(pci_resource_start(dev, 0),
- pci_resource_len(dev, 0));
-
+ window = pci_ioremap_bar(dev, 0);
if (window == NULL) {
i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n",
__func__);
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 0cfcb2d075a0..853ef37ec006 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -630,27 +630,22 @@ static int mpc85xx_l2_err_remove(struct of_device *op)
}
static struct of_device_id mpc85xx_l2_err_of_match[] = {
- {
- .compatible = "fsl,8540-l2-cache-controller",
- },
- {
- .compatible = "fsl,8541-l2-cache-controller",
- },
- {
- .compatible = "fsl,8544-l2-cache-controller",
- },
- {
- .compatible = "fsl,8548-l2-cache-controller",
- },
- {
- .compatible = "fsl,8555-l2-cache-controller",
- },
- {
- .compatible = "fsl,8568-l2-cache-controller",
- },
- {
- .compatible = "fsl,mpc8572-l2-cache-controller",
- },
+/* deprecate the fsl,85.. forms in the future, 2.6.30? */
+ { .compatible = "fsl,8540-l2-cache-controller", },
+ { .compatible = "fsl,8541-l2-cache-controller", },
+ { .compatible = "fsl,8544-l2-cache-controller", },
+ { .compatible = "fsl,8548-l2-cache-controller", },
+ { .compatible = "fsl,8555-l2-cache-controller", },
+ { .compatible = "fsl,8568-l2-cache-controller", },
+ { .compatible = "fsl,mpc8536-l2-cache-controller", },
+ { .compatible = "fsl,mpc8540-l2-cache-controller", },
+ { .compatible = "fsl,mpc8541-l2-cache-controller", },
+ { .compatible = "fsl,mpc8544-l2-cache-controller", },
+ { .compatible = "fsl,mpc8548-l2-cache-controller", },
+ { .compatible = "fsl,mpc8555-l2-cache-controller", },
+ { .compatible = "fsl,mpc8560-l2-cache-controller", },
+ { .compatible = "fsl,mpc8568-l2-cache-controller", },
+ { .compatible = "fsl,mpc8572-l2-cache-controller", },
{},
};
@@ -967,27 +962,22 @@ static int mpc85xx_mc_err_remove(struct of_device *op)
}
static struct of_device_id mpc85xx_mc_err_of_match[] = {
- {
- .compatible = "fsl,8540-memory-controller",
- },
- {
- .compatible = "fsl,8541-memory-controller",
- },
- {
- .compatible = "fsl,8544-memory-controller",
- },
- {
- .compatible = "fsl,8548-memory-controller",
- },
- {
- .compatible = "fsl,8555-memory-controller",
- },
- {
- .compatible = "fsl,8568-memory-controller",
- },
- {
- .compatible = "fsl,mpc8572-memory-controller",
- },
+/* deprecate the fsl,85.. forms in the future, 2.6.30? */
+ { .compatible = "fsl,8540-memory-controller", },
+ { .compatible = "fsl,8541-memory-controller", },
+ { .compatible = "fsl,8544-memory-controller", },
+ { .compatible = "fsl,8548-memory-controller", },
+ { .compatible = "fsl,8555-memory-controller", },
+ { .compatible = "fsl,8568-memory-controller", },
+ { .compatible = "fsl,mpc8536-memory-controller", },
+ { .compatible = "fsl,mpc8540-memory-controller", },
+ { .compatible = "fsl,mpc8541-memory-controller", },
+ { .compatible = "fsl,mpc8544-memory-controller", },
+ { .compatible = "fsl,mpc8548-memory-controller", },
+ { .compatible = "fsl,mpc8555-memory-controller", },
+ { .compatible = "fsl,mpc8560-memory-controller", },
+ { .compatible = "fsl,mpc8568-memory-controller", },
+ { .compatible = "fsl,mpc8572-memory-controller", },
{},
};
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 418c18f07e9d..7be2cf3514e7 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -75,7 +75,7 @@ generate_config_rom(struct fw_card *card, size_t *config_rom_length)
* controller, block reads to the config rom accesses the host
* memory, but quadlet read access the hardware bus info block
* registers. That's just crack, but it means we should make
- * sure the contents of bus info block in host memory mathces
+ * sure the contents of bus info block in host memory matches
* the version stored in the OHCI registers.
*/
@@ -189,6 +189,17 @@ static const char gap_count_table[] = {
63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
};
+void
+fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
+{
+ int scheduled;
+
+ fw_card_get(card);
+ scheduled = schedule_delayed_work(&card->work, delay);
+ if (!scheduled)
+ fw_card_put(card);
+}
+
static void
fw_card_bm_work(struct work_struct *work)
{
@@ -198,6 +209,8 @@ fw_card_bm_work(struct work_struct *work)
unsigned long flags;
int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode;
bool do_reset = false;
+ bool root_device_is_running;
+ bool root_device_is_cmc;
__be32 lock_data[2];
spin_lock_irqsave(&card->lock, flags);
@@ -206,19 +219,20 @@ fw_card_bm_work(struct work_struct *work)
if (local_node == NULL) {
spin_unlock_irqrestore(&card->lock, flags);
- return;
+ goto out_put_card;
}
fw_node_get(local_node);
fw_node_get(root_node);
generation = card->generation;
root_device = root_node->data;
- if (root_device)
- fw_device_get(root_device);
+ root_device_is_running = root_device &&
+ atomic_read(&root_device->state) == FW_DEVICE_RUNNING;
+ root_device_is_cmc = root_device && root_device->cmc;
root_id = root_node->node_id;
grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10));
- if (card->bm_generation + 1 == generation ||
+ if (is_next_generation(generation, card->bm_generation) ||
(card->bm_generation != generation && grace)) {
/*
* This first step is to figure out who is IRM and
@@ -280,7 +294,7 @@ fw_card_bm_work(struct work_struct *work)
* this task 100ms from now.
*/
spin_unlock_irqrestore(&card->lock, flags);
- schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10));
+ fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 10));
goto out;
}
@@ -297,14 +311,14 @@ fw_card_bm_work(struct work_struct *work)
* config rom. In either case, pick another root.
*/
new_root_id = local_node->node_id;
- } else if (atomic_read(&root_device->state) != FW_DEVICE_RUNNING) {
+ } else if (!root_device_is_running) {
/*
* If we haven't probed this device yet, bail out now
* and let's try again once that's done.
*/
spin_unlock_irqrestore(&card->lock, flags);
goto out;
- } else if (root_device->cmc) {
+ } else if (root_device_is_cmc) {
/*
* FIXME: I suppose we should set the cmstr bit in the
* STATE_CLEAR register of this node, as described in
@@ -351,10 +365,10 @@ fw_card_bm_work(struct work_struct *work)
fw_core_initiate_bus_reset(card, 1);
}
out:
- if (root_device)
- fw_device_put(root_device);
fw_node_put(root_node);
fw_node_put(local_node);
+ out_put_card:
+ fw_card_put(card);
}
static void
@@ -498,7 +512,7 @@ fw_core_remove_card(struct fw_card *card)
fw_core_initiate_bus_reset(card, 1);
mutex_lock(&card_mutex);
- list_del(&card->link);
+ list_del_init(&card->link);
mutex_unlock(&card_mutex);
/* Set up the dummy driver. */
@@ -510,7 +524,6 @@ fw_core_remove_card(struct fw_card *card)
fw_card_put(card);
wait_for_completion(&card->done);
- cancel_delayed_work_sync(&card->work);
WARN_ON(!list_empty(&card->transaction_list));
del_timer_sync(&card->flush_timer);
}
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index 6b9be42c7b98..bf53acb45652 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -25,6 +25,7 @@
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/idr.h>
+#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/rwsem.h>
#include <linux/semaphore.h>
@@ -159,7 +160,8 @@ static void fw_device_release(struct device *dev)
/*
* Take the card lock so we don't set this to NULL while a
- * FW_NODE_UPDATED callback is being handled.
+ * FW_NODE_UPDATED callback is being handled or while the
+ * bus manager work looks at this node.
*/
spin_lock_irqsave(&card->lock, flags);
device->node->data = NULL;
@@ -617,7 +619,7 @@ static int shutdown_unit(struct device *device, void *data)
*/
DECLARE_RWSEM(fw_device_rwsem);
-static DEFINE_IDR(fw_device_idr);
+DEFINE_IDR(fw_device_idr);
int fw_cdev_major;
struct fw_device *fw_device_get_by_devt(dev_t devt)
@@ -633,12 +635,39 @@ struct fw_device *fw_device_get_by_devt(dev_t devt)
return device;
}
+/*
+ * These defines control the retry behavior for reading the config
+ * rom. It shouldn't be necessary to tweak these; if the device
+ * doesn't respond to a config rom read within 10 seconds, it's not
+ * going to respond at all. As for the initial delay, a lot of
+ * devices will be able to respond within half a second after bus
+ * reset. On the other hand, it's not really worth being more
+ * aggressive than that, since it scales pretty well; if 10 devices
+ * are plugged in, they're all getting read within one second.
+ */
+
+#define MAX_RETRIES 10
+#define RETRY_DELAY (3 * HZ)
+#define INITIAL_DELAY (HZ / 2)
+#define SHUTDOWN_DELAY (2 * HZ)
+
static void fw_device_shutdown(struct work_struct *work)
{
struct fw_device *device =
container_of(work, struct fw_device, work.work);
int minor = MINOR(device->device.devt);
+ if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY)
+ && !list_empty(&device->card->link)) {
+ schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
+ return;
+ }
+
+ if (atomic_cmpxchg(&device->state,
+ FW_DEVICE_GONE,
+ FW_DEVICE_SHUTDOWN) != FW_DEVICE_GONE)
+ return;
+
fw_device_cdev_remove(device);
device_for_each_child(&device->device, NULL, shutdown_unit);
device_unregister(&device->device);
@@ -646,6 +675,7 @@ static void fw_device_shutdown(struct work_struct *work)
down_write(&fw_device_rwsem);
idr_remove(&fw_device_idr, minor);
up_write(&fw_device_rwsem);
+
fw_device_put(device);
}
@@ -653,25 +683,63 @@ static struct device_type fw_device_type = {
.release = fw_device_release,
};
+static void fw_device_update(struct work_struct *work);
+
/*
- * These defines control the retry behavior for reading the config
- * rom. It shouldn't be necessary to tweak these; if the device
- * doesn't respond to a config rom read within 10 seconds, it's not
- * going to respond at all. As for the initial delay, a lot of
- * devices will be able to respond within half a second after bus
- * reset. On the other hand, it's not really worth being more
- * aggressive than that, since it scales pretty well; if 10 devices
- * are plugged in, they're all getting read within one second.
+ * If a device was pending for deletion because its node went away but its
+ * bus info block and root directory header matches that of a newly discovered
+ * device, revive the existing fw_device.
+ * The newly allocated fw_device becomes obsolete instead.
*/
+static int lookup_existing_device(struct device *dev, void *data)
+{
+ struct fw_device *old = fw_device(dev);
+ struct fw_device *new = data;
+ struct fw_card *card = new->card;
+ int match = 0;
+
+ down_read(&fw_device_rwsem); /* serialize config_rom access */
+ spin_lock_irq(&card->lock); /* serialize node access */
+
+ if (memcmp(old->config_rom, new->config_rom, 6 * 4) == 0 &&
+ atomic_cmpxchg(&old->state,
+ FW_DEVICE_GONE,
+ FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
+ struct fw_node *current_node = new->node;
+ struct fw_node *obsolete_node = old->node;
+
+ new->node = obsolete_node;
+ new->node->data = new;
+ old->node = current_node;
+ old->node->data = old;
+
+ old->max_speed = new->max_speed;
+ old->node_id = current_node->node_id;
+ smp_wmb(); /* update node_id before generation */
+ old->generation = card->generation;
+ old->config_rom_retries = 0;
+ fw_notify("rediscovered device %s\n", dev_name(dev));
-#define MAX_RETRIES 10
-#define RETRY_DELAY (3 * HZ)
-#define INITIAL_DELAY (HZ / 2)
+ PREPARE_DELAYED_WORK(&old->work, fw_device_update);
+ schedule_delayed_work(&old->work, 0);
+
+ if (current_node == card->root_node)
+ fw_schedule_bm_work(card, 0);
+
+ match = 1;
+ }
+
+ spin_unlock_irq(&card->lock);
+ up_read(&fw_device_rwsem);
+
+ return match;
+}
static void fw_device_init(struct work_struct *work)
{
struct fw_device *device =
container_of(work, struct fw_device, work.work);
+ struct device *revived_dev;
int minor, err;
/*
@@ -689,18 +757,28 @@ static void fw_device_init(struct work_struct *work)
fw_notify("giving up on config rom for node id %x\n",
device->node_id);
if (device->node == device->card->root_node)
- schedule_delayed_work(&device->card->work, 0);
+ fw_schedule_bm_work(device->card, 0);
fw_device_release(&device->device);
}
return;
}
- err = -ENOMEM;
+ revived_dev = device_find_child(device->card->device,
+ device, lookup_existing_device);
+ if (revived_dev) {
+ put_device(revived_dev);
+ fw_device_release(&device->device);
+
+ return;
+ }
+
+ device_initialize(&device->device);
fw_device_get(device);
down_write(&fw_device_rwsem);
- if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
- err = idr_get_new(&fw_device_idr, device, &minor);
+ err = idr_pre_get(&fw_device_idr, GFP_KERNEL) ?
+ idr_get_new(&fw_device_idr, device, &minor) :
+ -ENOMEM;
up_write(&fw_device_rwsem);
if (err < 0)
@@ -732,9 +810,10 @@ static void fw_device_init(struct work_struct *work)
* fw_node_event().
*/
if (atomic_cmpxchg(&device->state,
- FW_DEVICE_INITIALIZING,
- FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
- fw_device_shutdown(work);
+ FW_DEVICE_INITIALIZING,
+ FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
+ PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+ schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
} else {
if (device->config_rom_retries)
fw_notify("created device %s: GUID %08x%08x, S%d00, "
@@ -758,7 +837,7 @@ static void fw_device_init(struct work_struct *work)
* pretty harmless.
*/
if (device->node == device->card->root_node)
- schedule_delayed_work(&device->card->work, 0);
+ fw_schedule_bm_work(device->card, 0);
return;
@@ -845,8 +924,8 @@ static void fw_device_refresh(struct work_struct *work)
case REREAD_BIB_UNCHANGED:
if (atomic_cmpxchg(&device->state,
- FW_DEVICE_INITIALIZING,
- FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
+ FW_DEVICE_INITIALIZING,
+ FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
goto gone;
fw_device_update(work);
@@ -877,8 +956,8 @@ static void fw_device_refresh(struct work_struct *work)
create_units(device);
if (atomic_cmpxchg(&device->state,
- FW_DEVICE_INITIALIZING,
- FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
+ FW_DEVICE_INITIALIZING,
+ FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
goto gone;
fw_notify("refreshed device %s\n", dev_name(&device->device));
@@ -888,11 +967,12 @@ static void fw_device_refresh(struct work_struct *work)
give_up:
fw_notify("giving up on refresh of device %s\n", dev_name(&device->device));
gone:
- atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
- fw_device_shutdown(work);
+ atomic_set(&device->state, FW_DEVICE_GONE);
+ PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+ schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
out:
if (node_id == card->root_node->node_id)
- schedule_delayed_work(&card->work, 0);
+ fw_schedule_bm_work(card, 0);
}
void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
@@ -911,13 +991,14 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
/*
* Do minimal intialization of the device here, the
- * rest will happen in fw_device_init(). We need the
- * card and node so we can read the config rom and we
- * need to do device_initialize() now so
- * device_for_each_child() in FW_NODE_UPDATED is
- * doesn't freak out.
+ * rest will happen in fw_device_init().
+ *
+ * Attention: A lot of things, even fw_device_get(),
+ * cannot be done before fw_device_init() finished!
+ * You can basically just check device->state and
+ * schedule work until then, but only while holding
+ * card->lock.
*/
- device_initialize(&device->device);
atomic_set(&device->state, FW_DEVICE_INITIALIZING);
device->card = fw_card_get(card);
device->node = fw_node_get(node);
@@ -992,9 +1073,10 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
*/
device = node->data;
if (atomic_xchg(&device->state,
- FW_DEVICE_SHUTDOWN) == FW_DEVICE_RUNNING) {
+ FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
- schedule_delayed_work(&device->work, 0);
+ schedule_delayed_work(&device->work,
+ list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
}
break;
}
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index 42305bbac72f..8ef6ec2ca21c 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -21,12 +21,14 @@
#include <linux/fs.h>
#include <linux/cdev.h>
+#include <linux/idr.h>
#include <linux/rwsem.h>
#include <asm/atomic.h>
enum fw_device_state {
FW_DEVICE_INITIALIZING,
FW_DEVICE_RUNNING,
+ FW_DEVICE_GONE,
FW_DEVICE_SHUTDOWN,
};
@@ -99,6 +101,7 @@ void fw_device_cdev_update(struct fw_device *device);
void fw_device_cdev_remove(struct fw_device *device);
extern struct rw_semaphore fw_device_rwsem;
+extern struct idr fw_device_idr;
extern int fw_cdev_major;
/*
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index ab9c01e462ef..6d19828a93a5 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -226,7 +226,7 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
#define CONTEXT_DEAD 0x0800
#define CONTEXT_ACTIVE 0x0400
-#define OHCI1394_MAX_AT_REQ_RETRIES 0x2
+#define OHCI1394_MAX_AT_REQ_RETRIES 0xf
#define OHCI1394_MAX_AT_RESP_RETRIES 0x2
#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
@@ -896,11 +896,11 @@ static void context_stop(struct context *ctx)
for (i = 0; i < 10; i++) {
reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
if ((reg & CONTEXT_ACTIVE) == 0)
- break;
+ return;
- fw_notify("context_stop: still active (0x%08x)\n", reg);
mdelay(1);
}
+ fw_error("Error: DMA context still active (0x%08x)\n", reg);
}
struct driver_data {
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index e54403ee59e7..c71c4419d9e8 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -168,6 +168,7 @@ struct sbp2_target {
int address_high;
unsigned int workarounds;
unsigned int mgt_orb_timeout;
+ unsigned int max_payload;
int dont_block; /* counter for each logical unit */
int blocked; /* ditto */
@@ -310,14 +311,16 @@ struct sbp2_command_orb {
dma_addr_t page_table_bus;
};
+#define SBP2_ROM_VALUE_WILDCARD ~0 /* match all */
+#define SBP2_ROM_VALUE_MISSING 0xff000000 /* not present in the unit dir. */
+
/*
* List of devices with known bugs.
*
* The firmware_revision field, masked with 0xffff00, is the best
* indicator for the type of bridge chip of a device. It yields a few
* false positives but this did not break correctly behaving devices
- * so far. We use ~0 as a wildcard, since the 24 bit values we get
- * from the config rom can never match that.
+ * so far.
*/
static const struct {
u32 firmware_revision;
@@ -339,33 +342,35 @@ static const struct {
},
/* Initio bridges, actually only needed for some older ones */ {
.firmware_revision = 0x000200,
- .model = ~0,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_INQUIRY_36,
},
/* PL-3507 bridge with Prolific firmware */ {
.firmware_revision = 0x012800,
- .model = ~0,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_POWER_CONDITION,
},
/* Symbios bridge */ {
.firmware_revision = 0xa0b800,
- .model = ~0,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_128K_MAX_TRANS,
},
/* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ {
.firmware_revision = 0x002600,
- .model = ~0,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_128K_MAX_TRANS,
},
-
/*
- * There are iPods (2nd gen, 3rd gen) with model_id == 0, but
- * these iPods do not feature the read_capacity bug according
- * to one report. Read_capacity behaviour as well as model_id
- * could change due to Apple-supplied firmware updates though.
+ * iPod 2nd generation: needs 128k max transfer size workaround
+ * iPod 3rd generation: needs fix capacity workaround
*/
-
- /* iPod 4th generation. */ {
+ {
+ .firmware_revision = 0x0a2700,
+ .model = 0x000000,
+ .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS |
+ SBP2_WORKAROUND_FIX_CAPACITY,
+ },
+ /* iPod 4th generation */ {
.firmware_revision = 0x0a2700,
.model = 0x000021,
.workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
@@ -670,17 +675,6 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
&d, sizeof(d), complete_agent_reset_write_no_wait, t);
}
-static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation)
-{
- struct fw_card *card = fw_device(lu->tgt->unit->device.parent)->card;
- unsigned long flags;
-
- /* serialize with comparisons of lu->generation and card->generation */
- spin_lock_irqsave(&card->lock, flags);
- lu->generation = generation;
- spin_unlock_irqrestore(&card->lock, flags);
-}
-
static inline void sbp2_allow_block(struct sbp2_logical_unit *lu)
{
/*
@@ -884,7 +878,7 @@ static void sbp2_login(struct work_struct *work)
goto out;
generation = device->generation;
- smp_rmb(); /* node_id must not be older than generation */
+ smp_rmb(); /* node IDs must not be older than generation */
node_id = device->node_id;
local_node_id = device->card->node_id;
@@ -908,7 +902,8 @@ static void sbp2_login(struct work_struct *work)
tgt->node_id = node_id;
tgt->address_high = local_node_id << 16;
- sbp2_set_generation(lu, generation);
+ smp_wmb(); /* node IDs must not be older than generation */
+ lu->generation = generation;
lu->command_block_agent_address =
((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff)
@@ -1102,7 +1097,7 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
continue;
if (sbp2_workarounds_table[i].model != model &&
- sbp2_workarounds_table[i].model != ~0)
+ sbp2_workarounds_table[i].model != SBP2_ROM_VALUE_WILDCARD)
continue;
w |= sbp2_workarounds_table[i].workarounds;
@@ -1152,20 +1147,28 @@ static int sbp2_probe(struct device *dev)
fw_device_get(device);
fw_unit_get(unit);
- /* Initialize to values that won't match anything in our table. */
- firmware_revision = 0xff000000;
- model = 0xff000000;
-
/* implicit directory ID */
tgt->directory_id = ((unit->directory - device->config_rom) * 4
+ CSR_CONFIG_ROM) & 0xffffff;
+ firmware_revision = SBP2_ROM_VALUE_MISSING;
+ model = SBP2_ROM_VALUE_MISSING;
+
if (sbp2_scan_unit_dir(tgt, unit->directory, &model,
&firmware_revision) < 0)
goto fail_tgt_put;
sbp2_init_workarounds(tgt, model, firmware_revision);
+ /*
+ * At S100 we can do 512 bytes per packet, at S200 1024 bytes,
+ * and so on up to 4096 bytes. The SBP-2 max_payload field
+ * specifies the max payload size as 2 ^ (max_payload + 2), so
+ * if we set this to max_speed + 7, we get the right value.
+ */
+ tgt->max_payload = min(device->max_speed + 7, 10U);
+ tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1);
+
/* Do the login in a workqueue so we can easily reschedule retries. */
list_for_each_entry(lu, &tgt->lu_list, link)
sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
@@ -1201,7 +1204,7 @@ static void sbp2_reconnect(struct work_struct *work)
goto out;
generation = device->generation;
- smp_rmb(); /* node_id must not be older than generation */
+ smp_rmb(); /* node IDs must not be older than generation */
node_id = device->node_id;
local_node_id = device->card->node_id;
@@ -1228,7 +1231,8 @@ static void sbp2_reconnect(struct work_struct *work)
tgt->node_id = node_id;
tgt->address_high = local_node_id << 16;
- sbp2_set_generation(lu, generation);
+ smp_wmb(); /* node IDs must not be older than generation */
+ lu->generation = generation;
fw_notify("%s: reconnected to LUN %04x (%d retries)\n",
tgt->bus_id, lu->lun, lu->retries);
@@ -1282,6 +1286,19 @@ static struct fw_driver sbp2_driver = {
.id_table = sbp2_id_table,
};
+static void sbp2_unmap_scatterlist(struct device *card_device,
+ struct sbp2_command_orb *orb)
+{
+ if (scsi_sg_count(orb->cmd))
+ dma_unmap_sg(card_device, scsi_sglist(orb->cmd),
+ scsi_sg_count(orb->cmd),
+ orb->cmd->sc_data_direction);
+
+ if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT))
+ dma_unmap_single(card_device, orb->page_table_bus,
+ sizeof(orb->page_table), DMA_TO_DEVICE);
+}
+
static unsigned int
sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
{
@@ -1361,15 +1378,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
dma_unmap_single(device->card->device, orb->base.request_bus,
sizeof(orb->request), DMA_TO_DEVICE);
-
- if (scsi_sg_count(orb->cmd) > 0)
- dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd),
- scsi_sg_count(orb->cmd),
- orb->cmd->sc_data_direction);
-
- if (orb->page_table_bus != 0)
- dma_unmap_single(device->card->device, orb->page_table_bus,
- sizeof(orb->page_table), DMA_TO_DEVICE);
+ sbp2_unmap_scatterlist(device->card->device, orb);
orb->cmd->result = result;
orb->done(orb->cmd);
@@ -1443,7 +1452,6 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
struct sbp2_logical_unit *lu = cmd->device->hostdata;
struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct sbp2_command_orb *orb;
- unsigned int max_payload;
int generation, retval = SCSI_MLQUEUE_HOST_BUSY;
/*
@@ -1471,17 +1479,9 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
orb->done = done;
orb->cmd = cmd;
- orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
- /*
- * At speed 100 we can do 512 bytes per packet, at speed 200,
- * 1024 bytes per packet etc. The SBP-2 max_payload field
- * specifies the max payload size as 2 ^ (max_payload + 2), so
- * if we set this to max_speed + 7, we get the right value.
- */
- max_payload = min(device->max_speed + 7,
- device->card->max_receive - 1);
+ orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
orb->request.misc = cpu_to_be32(
- COMMAND_ORB_MAX_PAYLOAD(max_payload) |
+ COMMAND_ORB_MAX_PAYLOAD(lu->tgt->max_payload) |
COMMAND_ORB_SPEED(device->max_speed) |
COMMAND_ORB_NOTIFY);
@@ -1500,8 +1500,10 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
orb->base.request_bus =
dma_map_single(device->card->device, &orb->request,
sizeof(orb->request), DMA_TO_DEVICE);
- if (dma_mapping_error(device->card->device, orb->base.request_bus))
+ if (dma_mapping_error(device->card->device, orb->base.request_bus)) {
+ sbp2_unmap_scatterlist(device->card->device, orb);
goto out;
+ }
sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, generation,
lu->command_block_agent_address + SBP2_ORB_POINTER);
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 5e204713002d..8dd6703b55cd 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -355,6 +355,9 @@ report_lost_node(struct fw_card *card,
{
fw_node_event(card, node, FW_NODE_DESTROYED);
fw_node_put(node);
+
+ /* Topology has changed - reset bus manager retry counter */
+ card->bm_retries = 0;
}
static void
@@ -374,6 +377,9 @@ report_found_node(struct fw_card *card,
}
fw_node_event(card, node, FW_NODE_CREATED);
+
+ /* Topology has changed - reset bus manager retry counter */
+ card->bm_retries = 0;
}
void fw_destroy_nodes(struct fw_card *card)
@@ -512,15 +518,19 @@ fw_core_handle_bus_reset(struct fw_card *card,
struct fw_node *local_node;
unsigned long flags;
- spin_lock_irqsave(&card->lock, flags);
-
/*
- * If the new topology has a different self_id_count the topology
- * changed, either nodes were added or removed. In that case we
- * reset the IRM reset counter.
+ * If the selfID buffer is not the immediate successor of the
+ * previously processed one, we cannot reliably compare the
+ * old and new topologies.
*/
- if (card->self_id_count != self_id_count)
+ if (!is_next_generation(generation, card->generation) &&
+ card->local_node != NULL) {
+ fw_notify("skipped bus generations, destroying all nodes\n");
+ fw_destroy_nodes(card);
card->bm_retries = 0;
+ }
+
+ spin_lock_irqsave(&card->lock, flags);
card->node_id = node_id;
/*
@@ -530,7 +540,7 @@ fw_core_handle_bus_reset(struct fw_card *card,
smp_wmb();
card->generation = generation;
card->reset_jiffies = jiffies;
- schedule_delayed_work(&card->work, 0);
+ fw_schedule_bm_work(card, 0);
local_node = build_tree(card, self_ids, self_id_count);
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
index 2884f876397b..699ac041f39a 100644
--- a/drivers/firewire/fw-transaction.c
+++ b/drivers/firewire/fw-transaction.c
@@ -19,6 +19,7 @@
*/
#include <linux/completion.h>
+#include <linux/idr.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/module.h>
@@ -971,6 +972,7 @@ static void __exit fw_core_cleanup(void)
{
unregister_chrdev(fw_cdev_major, "firewire");
bus_unregister(&fw_bus_type);
+ idr_destroy(&fw_device_idr);
}
module_init(fw_core_init);
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index 839466f0a795..1d78e9cc5940 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -237,14 +237,6 @@ struct fw_card {
int link_speed;
int config_rom_generation;
- /*
- * We need to store up to 4 self ID for a maximum of 63
- * devices plus 3 words for the topology map header.
- */
- int self_id_count;
- u32 topology_map[252 + 3];
- u32 broadcast_channel;
-
spinlock_t lock; /* Take this lock when handling the lists in
* this struct. */
struct fw_node *local_node;
@@ -262,6 +254,9 @@ struct fw_card {
struct delayed_work work;
int bm_retries;
int bm_generation;
+
+ u32 broadcast_channel;
+ u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4];
};
static inline struct fw_card *fw_card_get(struct fw_card *card)
@@ -278,6 +273,17 @@ static inline void fw_card_put(struct fw_card *card)
kref_put(&card->kref, fw_card_release);
}
+extern void fw_schedule_bm_work(struct fw_card *card, unsigned long delay);
+
+/*
+ * Check whether new_generation is the immediate successor of old_generation.
+ * Take counter roll-over at 255 (as per to OHCI) into account.
+ */
+static inline bool is_next_generation(int new_generation, int old_generation)
+{
+ return (new_generation & 0xff) == ((old_generation + 1) & 0xff);
+}
+
/*
* The iso packet format allows for an immediate header/payload part
* stored in 'header' immediately after the packet info plus an
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 50a071f1c945..777fba48d2d3 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -238,11 +238,11 @@ static ssize_t host_control_on_shutdown_store(struct device *dev,
}
/**
- * smi_request: generate SMI request
+ * dcdbas_smi_request: generate SMI request
*
* Called with smi_data_lock.
*/
-static int smi_request(struct smi_cmd *smi_cmd)
+int dcdbas_smi_request(struct smi_cmd *smi_cmd)
{
cpumask_t old_mask;
int ret = 0;
@@ -309,14 +309,14 @@ static ssize_t smi_request_store(struct device *dev,
switch (val) {
case 2:
/* Raw SMI */
- ret = smi_request(smi_cmd);
+ ret = dcdbas_smi_request(smi_cmd);
if (!ret)
ret = count;
break;
case 1:
/* Calling Interface SMI */
smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer);
- ret = smi_request(smi_cmd);
+ ret = dcdbas_smi_request(smi_cmd);
if (!ret)
ret = count;
break;
@@ -333,6 +333,7 @@ out:
mutex_unlock(&smi_data_lock);
return ret;
}
+EXPORT_SYMBOL(dcdbas_smi_request);
/**
* host_control_smi: generate host control SMI
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
index 87bc3417de27..ca3cb0a54ab6 100644
--- a/drivers/firmware/dcdbas.h
+++ b/drivers/firmware/dcdbas.h
@@ -101,5 +101,7 @@ struct apm_cmd {
} __attribute__ ((packed)) parameters;
} __attribute__ ((packed));
+int dcdbas_smi_request(struct smi_cmd *smi_cmd);
+
#endif /* _DCDBAS_H_ */
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 13946ebd77d6..b4704e150b28 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -576,7 +576,7 @@ static ssize_t read_rbu_image_type(struct kobject *kobj,
{
int size = 0;
if (!pos)
- size = sprintf(buffer, "%s\n", image_type);
+ size = scnprintf(buffer, count, "%s\n", image_type);
return size;
}
@@ -648,7 +648,7 @@ static ssize_t read_rbu_packet_size(struct kobject *kobj,
int size = 0;
if (!pos) {
spin_lock(&rbu_data.lock);
- size = sprintf(buffer, "%lu\n", rbu_data.packetsize);
+ size = scnprintf(buffer, count, "%lu\n", rbu_data.packetsize);
spin_unlock(&rbu_data.lock);
}
return size;
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
index e880d6c8d896..5a76d056b9d0 100644
--- a/drivers/firmware/dmi-id.c
+++ b/drivers/firmware/dmi-id.c
@@ -223,7 +223,7 @@ static int __init dmi_id_init(void)
}
dmi_dev->class = &dmi_class;
- strcpy(dmi_dev->bus_id, "id");
+ dev_set_name(dmi_dev, "id");
dmi_dev->groups = sys_dmi_attribute_groups;
ret = device_register(dmi_dev);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 78b989d202a3..8f0f7c449305 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -415,6 +415,29 @@ void __init dmi_scan_machine(void)
}
/**
+ * dmi_matches - check if dmi_system_id structure matches system DMI data
+ * @dmi: pointer to the dmi_system_id structure to check
+ */
+static bool dmi_matches(const struct dmi_system_id *dmi)
+{
+ int i;
+
+ WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
+
+ for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
+ int s = dmi->matches[i].slot;
+ if (s == DMI_NONE)
+ continue;
+ if (dmi_ident[s]
+ && strstr(dmi_ident[s], dmi->matches[i].substr))
+ continue;
+ /* No match */
+ return false;
+ }
+ return true;
+}
+
+/**
* dmi_check_system - check system DMI data
* @list: array of dmi_system_id structures to match against
* All non-null elements of the list must match
@@ -429,32 +452,45 @@ void __init dmi_scan_machine(void)
*/
int dmi_check_system(const struct dmi_system_id *list)
{
- int i, count = 0;
- const struct dmi_system_id *d = list;
-
- WARN(!dmi_initialized, KERN_ERR "dmi check: not initialized yet.\n");
-
- while (d->ident) {
- for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
- int s = d->matches[i].slot;
- if (s == DMI_NONE)
- continue;
- if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
- continue;
- /* No match */
- goto fail;
+ int count = 0;
+ const struct dmi_system_id *d;
+
+ for (d = list; d->ident; d++)
+ if (dmi_matches(d)) {
+ count++;
+ if (d->callback && d->callback(d))
+ break;
}
- count++;
- if (d->callback && d->callback(d))
- break;
-fail: d++;
- }
return count;
}
EXPORT_SYMBOL(dmi_check_system);
/**
+ * dmi_first_match - find dmi_system_id structure matching system DMI data
+ * @list: array of dmi_system_id structures to match against
+ * All non-null elements of the list must match
+ * their slot's (field index's) data (i.e., each
+ * list string must be a substring of the specified
+ * DMI slot's string data) to be considered a
+ * successful match.
+ *
+ * Walk the blacklist table until the first match is found. Return the
+ * pointer to the matching entry or NULL if there's no match.
+ */
+const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
+{
+ const struct dmi_system_id *d;
+
+ for (d = list; d->ident; d++)
+ if (dmi_matches(d))
+ return d;
+
+ return NULL;
+}
+EXPORT_SYMBOL(dmi_first_match);
+
+/**
* dmi_get_system_info - return DMI data value
* @field: data index (see enum dmi_field)
*
@@ -468,8 +504,8 @@ const char *dmi_get_system_info(int field)
EXPORT_SYMBOL(dmi_get_system_info);
/**
- * dmi_name_in_serial - Check if string is in the DMI product serial
- * information.
+ * dmi_name_in_serial - Check if string is in the DMI product serial information
+ * @str: string to check for
*/
int dmi_name_in_serial(const char *str)
{
@@ -585,6 +621,8 @@ EXPORT_SYMBOL_GPL(dmi_walk);
/**
* dmi_match - compare a string to the dmi field (if exists)
+ * @f: DMI field identifier
+ * @str: string to compare the DMI field to
*
* Returns true if the requested field equals to the str (including NULL).
*/
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 3bf8ee120d42..261b9aa3f248 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -56,9 +56,9 @@ struct memmap_attribute {
ssize_t (*show)(struct firmware_map_entry *entry, char *buf);
};
-struct memmap_attribute memmap_start_attr = __ATTR_RO(start);
-struct memmap_attribute memmap_end_attr = __ATTR_RO(end);
-struct memmap_attribute memmap_type_attr = __ATTR_RO(type);
+static struct memmap_attribute memmap_start_attr = __ATTR_RO(start);
+static struct memmap_attribute memmap_end_attr = __ATTR_RO(end);
+static struct memmap_attribute memmap_type_attr = __ATTR_RO(type);
/*
* These are default attributes that are added for every memmap entry.
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 48f49d93d249..3d2565441b36 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -95,7 +95,7 @@ config GPIO_MAX732X
number for these GPIOs.
config GPIO_PCA953X
- tristate "PCA953x, PCA955x, and MAX7310 I/O ports"
+ tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports"
depends on I2C
help
Say yes here to provide access to several register-oriented
@@ -104,9 +104,10 @@ config GPIO_PCA953X
4 bits: pca9536, pca9537
- 8 bits: max7310, pca9534, pca9538, pca9554, pca9557
+ 8 bits: max7310, pca9534, pca9538, pca9554, pca9557,
+ tca6408
- 16 bits: pca9535, pca9539, pca9555
+ 16 bits: pca9535, pca9539, pca9555, tca6416
This driver can also be built as a module. If so, the module
will be called pca953x.
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 82020abc329e..42fb2fd24c0c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -789,6 +789,7 @@ int gpio_request(unsigned gpio, const char *label)
} else {
status = -EBUSY;
module_put(chip->owner);
+ goto done;
}
if (chip->request) {
@@ -1213,7 +1214,7 @@ static int gpiolib_show(struct seq_file *s, void *unused)
if (dev)
seq_printf(s, ", %s/%s",
dev->bus ? dev->bus->name : "no-bus",
- dev->bus_id);
+ dev_name(dev));
if (chip->label)
seq_printf(s, ", %s", chip->label);
if (chip->can_sleep)
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
index 8b24d784db93..3e7f4e06386e 100644
--- a/drivers/gpio/max7301.c
+++ b/drivers/gpio/max7301.c
@@ -217,8 +217,10 @@ static int __devinit max7301_probe(struct spi_device *spi)
int i, ret;
pdata = spi->dev.platform_data;
- if (!pdata || !pdata->base)
- return -ENODEV;
+ if (!pdata || !pdata->base) {
+ dev_dbg(&spi->dev, "incorrect or missing platform data\n");
+ return -EINVAL;
+ }
/*
* bits_per_word cannot be configured in platform data
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c
index 55ae9a41897a..f7868243af89 100644
--- a/drivers/gpio/max732x.c
+++ b/drivers/gpio/max732x.c
@@ -267,8 +267,10 @@ static int __devinit max732x_probe(struct i2c_client *client,
int ret, nr_port;
pdata = client->dev.platform_data;
- if (pdata == NULL)
- return -ENODEV;
+ if (pdata == NULL) {
+ dev_dbg(&client->dev, "no platform data\n");
+ return -EINVAL;
+ }
chip = kzalloc(sizeof(struct max732x_chip), GFP_KERNEL);
if (chip == NULL)
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
index 89c1d222e9d1..f6fae0e50e65 100644
--- a/drivers/gpio/mcp23s08.c
+++ b/drivers/gpio/mcp23s08.c
@@ -310,8 +310,10 @@ static int mcp23s08_probe(struct spi_device *spi)
unsigned base;
pdata = spi->dev.platform_data;
- if (!pdata || !gpio_is_valid(pdata->base))
- return -ENODEV;
+ if (!pdata || !gpio_is_valid(pdata->base)) {
+ dev_dbg(&spi->dev, "invalid or missing platform data\n");
+ return -EINVAL;
+ }
for (addr = 0; addr < 4; addr++) {
if (!pdata->chip[addr].is_present)
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 9ceeb89f1325..8dc0164bd51e 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -33,7 +33,12 @@ static const struct i2c_device_id pca953x_id[] = {
{ "pca9554", 8, },
{ "pca9555", 16, },
{ "pca9557", 8, },
+
{ "max7310", 8, },
+ { "pca6107", 8, },
+ { "tca6408", 8, },
+ { "tca6416", 16, },
+ /* NYET: { "tca6424", 24, }, */
{ }
};
MODULE_DEVICE_TABLE(i2c, pca953x_id);
@@ -47,9 +52,6 @@ struct pca953x_chip {
struct gpio_chip gpio_chip;
};
-/* NOTE: we can't currently rely on fault codes to come from SMBus
- * calls, so we map all errors to EIO here and return zero otherwise.
- */
static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
{
int ret;
@@ -61,7 +63,7 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
if (ret < 0) {
dev_err(&chip->client->dev, "failed writing register\n");
- return -EIO;
+ return ret;
}
return 0;
@@ -78,7 +80,7 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
if (ret < 0) {
dev_err(&chip->client->dev, "failed reading register\n");
- return -EIO;
+ return ret;
}
*val = (uint16_t)ret;
@@ -200,8 +202,10 @@ static int __devinit pca953x_probe(struct i2c_client *client,
int ret;
pdata = client->dev.platform_data;
- if (pdata == NULL)
- return -ENODEV;
+ if (pdata == NULL) {
+ dev_dbg(&client->dev, "no platform data\n");
+ return -EINVAL;
+ }
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL)
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
index 4bc2070dd4a1..9525724be731 100644
--- a/drivers/gpio/pcf857x.c
+++ b/drivers/gpio/pcf857x.c
@@ -188,8 +188,10 @@ static int pcf857x_probe(struct i2c_client *client,
int status;
pdata = client->dev.platform_data;
- if (!pdata)
- return -ENODEV;
+ if (!pdata) {
+ dev_dbg(&client->dev, "no platform data\n");
+ return -EINVAL;
+ }
/* Allocate, initialize, and register this gpio_chip. */
gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
@@ -248,8 +250,10 @@ static int pcf857x_probe(struct i2c_client *client,
else
status = i2c_read_le16(client);
- } else
- status = -ENODEV;
+ } else {
+ dev_dbg(&client->dev, "unsupported number of gpios\n");
+ status = -EINVAL;
+ }
if (status < 0)
goto fail;
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
index 37d3eec8730a..afad14792141 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -202,37 +202,6 @@ static int twl4030_get_gpio_datain(int gpio)
return ret;
}
-/*
- * Configure debounce timing value for a GPIO pin on TWL4030
- */
-int twl4030_set_gpio_debounce(int gpio, int enable)
-{
- u8 d_bnk = gpio >> 3;
- u8 d_msk = BIT(gpio & 0x7);
- u8 reg = 0;
- u8 base = 0;
- int ret = 0;
-
- if (unlikely((gpio >= TWL4030_GPIO_MAX)
- || !(gpio_usage_count & BIT(gpio))))
- return -EPERM;
-
- base = REG_GPIO_DEBEN1 + d_bnk;
- mutex_lock(&gpio_lock);
- ret = gpio_twl4030_read(base);
- if (ret >= 0) {
- if (enable)
- reg = ret | d_msk;
- else
- reg = ret & ~d_msk;
-
- ret = gpio_twl4030_write(base, reg);
- }
- mutex_unlock(&gpio_lock);
- return ret;
-}
-EXPORT_SYMBOL(twl4030_set_gpio_debounce);
-
/*----------------------------------------------------------------------*/
static int twl_request(struct gpio_chip *chip, unsigned offset)
@@ -405,6 +374,23 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
REG_GPIOPUPDCTR1, 5);
}
+static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
+{
+ u8 message[4];
+
+ /* 30 msec of debouncing is always used for MMC card detect,
+ * and is optional for everything else.
+ */
+ message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
+ debounce >>= 8;
+ message[2] = (debounce & 0xff);
+ debounce >>= 8;
+ message[3] = (debounce & 0x03);
+
+ return twl4030_i2c_write(TWL4030_MODULE_GPIO, message,
+ REG_GPIO_DEBEN1, 3);
+}
+
static int gpio_twl4030_remove(struct platform_device *pdev);
static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
@@ -439,6 +425,12 @@ no_irqs:
pdata->pullups, pdata->pulldowns,
ret);
+ ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+ if (ret)
+ dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+ pdata->debounce, pdata->mmc_cd,
+ ret);
+
twl_gpiochip.base = pdata->gpio_base;
twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
twl_gpiochip.dev = &pdev->dev;
diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c
index 3d33b8252b58..14796594e5d9 100644
--- a/drivers/gpu/drm/drm_agpsupport.c
+++ b/drivers/gpu/drm/drm_agpsupport.c
@@ -33,10 +33,11 @@
#include "drmP.h"
#include <linux/module.h>
-#include <asm/agp.h>
#if __OS_HAS_AGP
+#include <asm/agp.h>
+
/**
* Get AGP information.
*
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 53c87254be4c..bfce0992fefb 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -194,7 +194,6 @@ char *drm_get_connector_status_name(enum drm_connector_status status)
* @type: object type
*
* LOCKING:
- * Caller must hold DRM mode_config lock.
*
* Create a unique identifier based on @ptr in @dev's identifier space. Used
* for tracking modes, CRTCs and connectors.
@@ -209,15 +208,15 @@ static int drm_mode_object_get(struct drm_device *dev,
int new_id = 0;
int ret;
- WARN(!mutex_is_locked(&dev->mode_config.mutex),
- "%s called w/o mode_config lock\n", __FUNCTION__);
again:
if (idr_pre_get(&dev->mode_config.crtc_idr, GFP_KERNEL) == 0) {
DRM_ERROR("Ran out memory getting a mode number\n");
return -EINVAL;
}
+ mutex_lock(&dev->mode_config.idr_mutex);
ret = idr_get_new_above(&dev->mode_config.crtc_idr, obj, 1, &new_id);
+ mutex_unlock(&dev->mode_config.idr_mutex);
if (ret == -EAGAIN)
goto again;
@@ -239,16 +238,20 @@ again:
static void drm_mode_object_put(struct drm_device *dev,
struct drm_mode_object *object)
{
+ mutex_lock(&dev->mode_config.idr_mutex);
idr_remove(&dev->mode_config.crtc_idr, object->id);
+ mutex_unlock(&dev->mode_config.idr_mutex);
}
void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
{
- struct drm_mode_object *obj;
+ struct drm_mode_object *obj = NULL;
+ mutex_lock(&dev->mode_config.idr_mutex);
obj = idr_find(&dev->mode_config.crtc_idr, id);
if (!obj || (obj->type != type) || (obj->id != id))
- return NULL;
+ obj = NULL;
+ mutex_unlock(&dev->mode_config.idr_mutex);
return obj;
}
@@ -786,6 +789,7 @@ EXPORT_SYMBOL(drm_mode_create_dithering_property);
void drm_mode_config_init(struct drm_device *dev)
{
mutex_init(&dev->mode_config.mutex);
+ mutex_init(&dev->mode_config.idr_mutex);
INIT_LIST_HEAD(&dev->mode_config.fb_list);
INIT_LIST_HEAD(&dev->mode_config.fb_kernel_list);
INIT_LIST_HEAD(&dev->mode_config.crtc_list);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index d8a982b71296..964c5eb1fada 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -36,7 +36,7 @@
/*
* Detailed mode info for 800x600@60Hz
*/
-static struct drm_display_mode std_mode[] = {
+static struct drm_display_mode std_modes[] = {
{ DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
@@ -60,15 +60,18 @@ static struct drm_display_mode std_mode[] = {
* changes have occurred.
*
* FIXME: take into account monitor limits
+ *
+ * RETURNS:
+ * Number of modes found on @connector.
*/
-void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
- uint32_t maxX, uint32_t maxY)
+int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
+ uint32_t maxX, uint32_t maxY)
{
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode, *t;
struct drm_connector_helper_funcs *connector_funcs =
connector->helper_private;
- int ret;
+ int count = 0;
DRM_DEBUG("%s\n", drm_get_connector_name(connector));
/* set all modes to the unverified state */
@@ -81,14 +84,14 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
DRM_DEBUG("%s is disconnected\n",
drm_get_connector_name(connector));
/* TODO set EDID to NULL */
- return;
+ return 0;
}
- ret = (*connector_funcs->get_modes)(connector);
+ count = (*connector_funcs->get_modes)(connector);
+ if (!count)
+ return 0;
- if (ret) {
- drm_mode_connector_list_update(connector);
- }
+ drm_mode_connector_list_update(connector);
if (maxX && maxY)
drm_mode_validate_size(dev, &connector->modes, maxX,
@@ -102,25 +105,8 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
drm_mode_prune_invalid(dev, &connector->modes, true);
- if (list_empty(&connector->modes)) {
- struct drm_display_mode *stdmode;
-
- DRM_DEBUG("No valid modes on %s\n",
- drm_get_connector_name(connector));
-
- /* Should we do this here ???
- * When no valid EDID modes are available we end up
- * here and bailed in the past, now we add a standard
- * 640x480@60Hz mode and carry on.
- */
- stdmode = drm_mode_duplicate(dev, &std_mode[0]);
- drm_mode_probed_add(connector, stdmode);
- drm_mode_list_concat(&connector->probed_modes,
- &connector->modes);
-
- DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
- drm_get_connector_name(connector));
- }
+ if (list_empty(&connector->modes))
+ return 0;
drm_mode_sort(&connector->modes);
@@ -131,20 +117,58 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
drm_mode_debug_printmodeline(mode);
}
+
+ return count;
}
EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
-void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
+int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
uint32_t maxY)
{
struct drm_connector *connector;
+ int count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- drm_helper_probe_single_connector_modes(connector, maxX, maxY);
+ count += drm_helper_probe_single_connector_modes(connector,
+ maxX, maxY);
}
+
+ return count;
}
EXPORT_SYMBOL(drm_helper_probe_connector_modes);
+static void drm_helper_add_std_modes(struct drm_device *dev,
+ struct drm_connector *connector)
+{
+ struct drm_display_mode *mode, *t;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
+ struct drm_display_mode *stdmode;
+
+ /*
+ * When no valid EDID modes are available we end up
+ * here and bailed in the past, now we add some standard
+ * modes and move on.
+ */
+ stdmode = drm_mode_duplicate(dev, &std_modes[i]);
+ drm_mode_probed_add(connector, stdmode);
+ drm_mode_list_concat(&connector->probed_modes,
+ &connector->modes);
+
+ DRM_DEBUG("Adding mode %s to %s\n", stdmode->name,
+ drm_get_connector_name(connector));
+ }
+ drm_mode_sort(&connector->modes);
+
+ DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector));
+ list_for_each_entry_safe(mode, t, &connector->modes, head) {
+ mode->vrefresh = drm_mode_vrefresh(mode);
+
+ drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+ drm_mode_debug_printmodeline(mode);
+ }
+}
/**
* drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
@@ -237,6 +261,8 @@ static void drm_enable_connectors(struct drm_device *dev, bool *enabled)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
enabled[i] = drm_connector_enabled(connector, true);
+ DRM_DEBUG("connector %d enabled? %s\n", connector->base.id,
+ enabled[i] ? "yes" : "no");
any_enabled |= enabled[i];
i++;
}
@@ -265,11 +291,17 @@ static bool drm_target_preferred(struct drm_device *dev,
continue;
}
+ DRM_DEBUG("looking for preferred mode on connector %d\n",
+ connector->base.id);
+
modes[i] = drm_has_preferred_mode(connector, width, height);
- if (!modes[i]) {
+ /* No preferred modes, pick one off the list */
+ if (!modes[i] && !list_empty(&connector->modes)) {
list_for_each_entry(modes[i], &connector->modes, head)
break;
}
+ DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name :
+ "none");
i++;
}
return true;
@@ -369,6 +401,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
int width, height;
int i, ret;
+ DRM_DEBUG("\n");
+
width = dev->mode_config.max_width;
height = dev->mode_config.max_height;
@@ -390,6 +424,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
if (!ret)
DRM_ERROR("Unable to find initial modes\n");
+ DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height);
+
drm_pick_crtcs(dev, crtcs, modes, 0, width, height);
i = 0;
@@ -403,6 +439,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
}
if (mode && crtc) {
+ DRM_DEBUG("desired mode %s set on crtc %d\n",
+ mode->name, crtc->base.id);
crtc->desired_mode = mode;
connector->encoder->crtc = crtc;
} else
@@ -442,6 +480,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
int saved_x, saved_y;
struct drm_encoder *encoder;
bool ret = true;
+ bool depth_changed, bpp_changed;
adjusted_mode = drm_mode_duplicate(dev, mode);
@@ -450,6 +489,15 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
if (!crtc->enabled)
return true;
+ if (old_fb && crtc->fb) {
+ depth_changed = (old_fb->depth != crtc->fb->depth);
+ bpp_changed = (old_fb->bits_per_pixel !=
+ crtc->fb->bits_per_pixel);
+ } else {
+ depth_changed = true;
+ bpp_changed = true;
+ }
+
saved_mode = crtc->mode;
saved_x = crtc->x;
saved_y = crtc->y;
@@ -462,7 +510,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
crtc->y = y;
if (drm_mode_equal(&saved_mode, &crtc->mode)) {
- if (saved_x != crtc->x || saved_y != crtc->y) {
+ if (saved_x != crtc->x || saved_y != crtc->y ||
+ depth_changed || bpp_changed) {
crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
old_fb);
goto done;
@@ -568,8 +617,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
struct drm_encoder **save_encoders, *new_encoder;
struct drm_framebuffer *old_fb;
bool save_enabled;
- bool changed = false;
- bool flip_or_move = false;
+ bool mode_changed = false;
+ bool fb_changed = false;
struct drm_connector *connector;
int count = 0, ro, fail = 0;
struct drm_crtc_helper_funcs *crtc_funcs;
@@ -597,7 +646,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
/* save previous config */
save_enabled = set->crtc->enabled;
- /* this is meant to be num_connector not num_crtc */
+ /*
+ * We do mode_config.num_connectors here since we'll look at the
+ * CRTC and encoder associated with each connector later.
+ */
save_crtcs = kzalloc(dev->mode_config.num_connector *
sizeof(struct drm_crtc *), GFP_KERNEL);
if (!save_crtcs)
@@ -613,21 +665,25 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */
if (set->crtc->fb != set->fb) {
- /* if we have no fb then its a change not a flip */
+ /* If we have no fb then treat it as a full mode set */
if (set->crtc->fb == NULL)
- changed = true;
+ mode_changed = true;
+ else if ((set->fb->bits_per_pixel !=
+ set->crtc->fb->bits_per_pixel) ||
+ set->fb->depth != set->crtc->fb->depth)
+ fb_changed = true;
else
- flip_or_move = true;
+ fb_changed = true;
}
if (set->x != set->crtc->x || set->y != set->crtc->y)
- flip_or_move = true;
+ fb_changed = true;
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
DRM_DEBUG("modes are different\n");
drm_mode_debug_printmodeline(&set->crtc->mode);
drm_mode_debug_printmodeline(set->mode);
- changed = true;
+ mode_changed = true;
}
/* a) traverse passed in connector list and get encoders for them */
@@ -650,7 +706,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
}
if (new_encoder != connector->encoder) {
- changed = true;
+ mode_changed = true;
connector->encoder = new_encoder;
}
}
@@ -677,16 +733,16 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
new_crtc = set->crtc;
}
if (new_crtc != connector->encoder->crtc) {
- changed = true;
+ mode_changed = true;
connector->encoder->crtc = new_crtc;
}
}
/* mode_set_base is not a required function */
- if (flip_or_move && !crtc_funcs->mode_set_base)
- changed = true;
+ if (fb_changed && !crtc_funcs->mode_set_base)
+ mode_changed = true;
- if (changed) {
+ if (mode_changed) {
old_fb = set->crtc->fb;
set->crtc->fb = set->fb;
set->crtc->enabled = (set->mode != NULL);
@@ -705,7 +761,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
set->crtc->desired_mode = set->mode;
}
drm_helper_disable_unused_functions(dev);
- } else if (flip_or_move) {
+ } else if (fb_changed) {
old_fb = set->crtc->fb;
if (set->crtc->fb != set->fb)
set->crtc->fb = set->fb;
@@ -764,10 +820,31 @@ bool drm_helper_plugged_event(struct drm_device *dev)
*/
bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
{
- int ret = false;
+ struct drm_connector *connector;
+ int count = 0;
- drm_helper_plugged_event(dev);
- return ret;
+ count = drm_helper_probe_connector_modes(dev,
+ dev->mode_config.max_width,
+ dev->mode_config.max_height);
+
+ /*
+ * None of the available connectors had any modes, so add some
+ * and try to light them up anyway
+ */
+ if (!count) {
+ DRM_ERROR("connectors have no modes, using standard modes\n");
+ list_for_each_entry(connector,
+ &dev->mode_config.connector_list,
+ head)
+ drm_helper_add_std_modes(dev, connector);
+ }
+
+ drm_setup_crtcs(dev);
+
+ /* alert the driver fb layer */
+ dev->mode_config.funcs->fb_changed(dev);
+
+ return 0;
}
EXPORT_SYMBOL(drm_helper_initial_config);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index febb517ee679..14c7a23dc157 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -294,6 +294,7 @@ EXPORT_SYMBOL(drm_init);
*/
static void drm_cleanup(struct drm_device * dev)
{
+ struct drm_map_list *r_list, *list_temp;
DRM_DEBUG("\n");
if (!dev) {
@@ -314,17 +315,20 @@ static void drm_cleanup(struct drm_device * dev)
DRM_DEBUG("mtrr_del=%d\n", retval);
}
+ if (dev->driver->unload)
+ dev->driver->unload(dev);
+
if (drm_core_has_AGP(dev) && dev->agp) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
dev->agp = NULL;
}
- if (dev->driver->unload)
- dev->driver->unload(dev);
-
drm_ht_remove(&dev->map_hash);
drm_ctxbitmap_cleanup(dev);
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
+ drm_rmmap(dev, r_list->map);
+
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0fbb0da342cb..5a4d3244758a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -660,7 +660,7 @@ struct edid *drm_get_edid(struct drm_connector *connector,
edid = (struct edid *)drm_ddc_read(adapter);
if (!edid) {
- dev_warn(&connector->dev->pdev->dev, "%s: no EDID data\n",
+ dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
drm_get_connector_name(connector));
return NULL;
}
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 3733e36d135e..b06a53715853 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -183,6 +183,10 @@ int drm_stub_open(struct inode *inode, struct file *filp)
old_fops = filp->f_op;
filp->f_op = fops_get(&dev->driver->fops);
+ if (filp->f_op == NULL) {
+ filp->f_op = old_fops;
+ goto out;
+ }
if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) {
fops_put(filp->f_op);
filp->f_op = fops_get(old_fops);
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 9da581452874..6915fb82d0b0 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -136,7 +136,7 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
obj = kcalloc(1, sizeof(*obj), GFP_KERNEL);
obj->dev = dev;
- obj->filp = shmem_file_setup("drm mm object", size, 0);
+ obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
if (IS_ERR(obj->filp)) {
kfree(obj);
return NULL;
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 724e505873cf..69aa0ab28403 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -106,8 +106,6 @@ void drm_vblank_cleanup(struct drm_device *dev)
drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
DRM_MEM_DRIVER);
- drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
- DRM_MEM_DRIVER);
drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
dev->num_crtcs, DRM_MEM_DRIVER);
drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
@@ -132,7 +130,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
(unsigned long)dev);
spin_lock_init(&dev->vbl_lock);
- atomic_set(&dev->vbl_signal_pending, 0);
dev->num_crtcs = num_crtcs;
dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
@@ -140,11 +137,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
if (!dev->vbl_queue)
goto err;
- dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
- DRM_MEM_DRIVER);
- if (!dev->vbl_sigs)
- goto err;
-
dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
DRM_MEM_DRIVER);
if (!dev->_vblank_count)
@@ -177,7 +169,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs)
/* Zero per-crtc vblank stuff */
for (i = 0; i < num_crtcs; i++) {
init_waitqueue_head(&dev->vbl_queue[i]);
- INIT_LIST_HEAD(&dev->vbl_sigs[i]);
atomic_set(&dev->_vblank_count[i], 0);
atomic_set(&dev->vblank_refcount[i], 0);
}
@@ -267,7 +258,8 @@ EXPORT_SYMBOL(drm_irq_install);
*/
int drm_irq_uninstall(struct drm_device * dev)
{
- int irq_enabled;
+ unsigned long irqflags;
+ int irq_enabled, i;
if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
return -EINVAL;
@@ -277,6 +269,16 @@ int drm_irq_uninstall(struct drm_device * dev)
dev->irq_enabled = 0;
mutex_unlock(&dev->struct_mutex);
+ /*
+ * Wake up any waiters so they don't hang.
+ */
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+ for (i = 0; i < dev->num_crtcs; i++) {
+ DRM_WAKEUP(&dev->vbl_queue[i]);
+ dev->vblank_enabled[i] = 0;
+ }
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+
if (!irq_enabled)
return -EINVAL;
@@ -529,15 +531,10 @@ out:
* \param data user argument, pointing to a drm_wait_vblank structure.
* \return zero on success or a negative number on failure.
*
- * Verifies the IRQ is installed.
- *
- * If a signal is requested checks if this task has already scheduled the same signal
- * for the same vblank sequence number - nothing to be done in
- * that case. If the number of tasks waiting for the interrupt exceeds 100 the
- * function fails. Otherwise adds a new entry to drm_device::vbl_sigs for this
- * task.
- *
- * If a signal is not requested, then calls vblank_wait().
+ * This function enables the vblank interrupt on the pipe requested, then
+ * sleeps waiting for the requested sequence number to occur, and drops
+ * the vblank interrupt refcount afterwards. (vblank irq disable follows that
+ * after a timeout with no further vblank waits scheduled).
*/
int drm_wait_vblank(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -549,6 +546,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
if ((!dev->pdev->irq) || (!dev->irq_enabled))
return -EINVAL;
+ if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
+ return -EINVAL;
+
if (vblwait->request.type &
~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
@@ -586,88 +586,26 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
vblwait->request.sequence = seq + 1;
}
- if (flags & _DRM_VBLANK_SIGNAL) {
- unsigned long irqflags;
- struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
- struct drm_vbl_sig *vbl_sig;
-
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
-
- /* Check if this task has already scheduled the same signal
- * for the same vblank sequence number; nothing to be done in
- * that case
- */
- list_for_each_entry(vbl_sig, vbl_sigs, head) {
- if (vbl_sig->sequence == vblwait->request.sequence
- && vbl_sig->info.si_signo ==
- vblwait->request.signal
- && vbl_sig->task == current) {
- spin_unlock_irqrestore(&dev->vbl_lock,
- irqflags);
- vblwait->reply.sequence = seq;
- goto done;
- }
- }
-
- if (atomic_read(&dev->vbl_signal_pending) >= 100) {
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- ret = -EBUSY;
- goto done;
- }
-
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
-
- vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
- DRM_MEM_DRIVER);
- if (!vbl_sig) {
- ret = -ENOMEM;
- goto done;
- }
-
- /* Get a refcount on the vblank, which will be released by
- * drm_vbl_send_signals().
- */
- ret = drm_vblank_get(dev, crtc);
- if (ret) {
- drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
- DRM_MEM_DRIVER);
- goto done;
- }
-
- atomic_inc(&dev->vbl_signal_pending);
+ DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
+ vblwait->request.sequence, crtc);
+ dev->last_vblank_wait[crtc] = vblwait->request.sequence;
+ DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
+ (((drm_vblank_count(dev, crtc) -
+ vblwait->request.sequence) <= (1 << 23)) ||
+ !dev->irq_enabled));
- vbl_sig->sequence = vblwait->request.sequence;
- vbl_sig->info.si_signo = vblwait->request.signal;
- vbl_sig->task = current;
+ if (ret != -EINTR) {
+ struct timeval now;
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
-
- list_add_tail(&vbl_sig->head, vbl_sigs);
-
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ do_gettimeofday(&now);
- vblwait->reply.sequence = seq;
+ vblwait->reply.tval_sec = now.tv_sec;
+ vblwait->reply.tval_usec = now.tv_usec;
+ vblwait->reply.sequence = drm_vblank_count(dev, crtc);
+ DRM_DEBUG("returning %d to client\n",
+ vblwait->reply.sequence);
} else {
- DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
- vblwait->request.sequence, crtc);
- dev->last_vblank_wait[crtc] = vblwait->request.sequence;
- DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
- ((drm_vblank_count(dev, crtc)
- - vblwait->request.sequence) <= (1 << 23)));
-
- if (ret != -EINTR) {
- struct timeval now;
-
- do_gettimeofday(&now);
-
- vblwait->reply.tval_sec = now.tv_sec;
- vblwait->reply.tval_usec = now.tv_usec;
- vblwait->reply.sequence = drm_vblank_count(dev, crtc);
- DRM_DEBUG("returning %d to client\n",
- vblwait->reply.sequence);
- } else {
- DRM_DEBUG("vblank wait interrupted by signal\n");
- }
+ DRM_DEBUG("vblank wait interrupted by signal\n");
}
done:
@@ -676,46 +614,6 @@ done:
}
/**
- * Send the VBLANK signals.
- *
- * \param dev DRM device.
- * \param crtc CRTC where the vblank event occurred
- *
- * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
- *
- * If a signal is not requested, then calls vblank_wait().
- */
-static void drm_vbl_send_signals(struct drm_device *dev, int crtc)
-{
- struct drm_vbl_sig *vbl_sig, *tmp;
- struct list_head *vbl_sigs;
- unsigned int vbl_seq;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->vbl_lock, flags);
-
- vbl_sigs = &dev->vbl_sigs[crtc];
- vbl_seq = drm_vblank_count(dev, crtc);
-
- list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
- if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
- vbl_sig->info.si_code = vbl_seq;
- send_sig_info(vbl_sig->info.si_signo,
- &vbl_sig->info, vbl_sig->task);
-
- list_del(&vbl_sig->head);
-
- drm_free(vbl_sig, sizeof(*vbl_sig),
- DRM_MEM_DRIVER);
- atomic_dec(&dev->vbl_signal_pending);
- drm_vblank_put(dev, crtc);
- }
- }
-
- spin_unlock_irqrestore(&dev->vbl_lock, flags);
-}
-
-/**
* drm_handle_vblank - handle a vblank event
* @dev: DRM device
* @crtc: where this event occurred
@@ -727,6 +625,5 @@ void drm_handle_vblank(struct drm_device *dev, int crtc)
{
atomic_inc(&dev->_vblank_count[crtc]);
DRM_WAKEUP(&dev->vbl_queue[crtc]);
- drm_vbl_send_signals(dev, crtc);
}
EXPORT_SYMBOL(drm_handle_vblank);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 5ca132afa4f2..46bb923b097c 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -118,12 +118,20 @@ static void drm_master_destroy(struct kref *kref)
struct drm_master *master = container_of(kref, struct drm_master, refcount);
struct drm_magic_entry *pt, *next;
struct drm_device *dev = master->minor->dev;
+ struct drm_map_list *r_list, *list_temp;
list_del(&master->head);
if (dev->driver->master_destroy)
dev->driver->master_destroy(dev, master);
+ list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
+ if (r_list->master == master) {
+ drm_rmmap_locked(dev, r_list->map);
+ r_list = NULL;
+ }
+ }
+
if (master->unique) {
drm_free(master->unique, master->unique_size, DRM_MEM_DRIVER);
master->unique = NULL;
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 65d72d094c81..5aa6780652aa 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -488,7 +488,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
else
minor_str = "card%d";
- snprintf(minor->kdev.bus_id, BUS_ID_SIZE, minor_str, minor->index);
+ dev_set_name(&minor->kdev, minor_str, minor->index);
err = device_register(&minor->kdev);
if (err) {
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index dd57a5bd4572..793cba39d832 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -13,6 +13,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
intel_crt.o \
intel_lvds.o \
intel_bios.o \
+ intel_hdmi.o \
intel_sdvo.o \
intel_modes.o \
intel_i2c.o \
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 3d7082af5b72..ee64b7301f67 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -177,6 +177,14 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+ master_priv->sarea = drm_getsarea(dev);
+ if (master_priv->sarea) {
+ master_priv->sarea_priv = (drm_i915_sarea_t *)
+ ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
+ } else {
+ DRM_DEBUG("sarea not found assuming DRI2 userspace\n");
+ }
+
if (init->ring_size != 0) {
if (dev_priv->ring.ring_obj != NULL) {
i915_dma_cleanup(dev);
@@ -827,6 +835,7 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
struct pci_dev *bridge_dev;
u16 tmp = 0;
unsigned long overhead;
+ unsigned long stolen;
bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
if (!bridge_dev) {
@@ -866,36 +875,55 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
else
overhead = (*aperture_size / 1024) + 4096;
- switch (tmp & INTEL_855_GMCH_GMS_MASK) {
+ switch (tmp & INTEL_GMCH_GMS_MASK) {
+ case INTEL_855_GMCH_GMS_DISABLED:
+ DRM_ERROR("video memory is disabled\n");
+ return -1;
case INTEL_855_GMCH_GMS_STOLEN_1M:
- break; /* 1M already */
+ stolen = 1 * 1024 * 1024;
+ break;
case INTEL_855_GMCH_GMS_STOLEN_4M:
- *preallocated_size *= 4;
+ stolen = 4 * 1024 * 1024;
break;
case INTEL_855_GMCH_GMS_STOLEN_8M:
- *preallocated_size *= 8;
+ stolen = 8 * 1024 * 1024;
break;
case INTEL_855_GMCH_GMS_STOLEN_16M:
- *preallocated_size *= 16;
+ stolen = 16 * 1024 * 1024;
break;
case INTEL_855_GMCH_GMS_STOLEN_32M:
- *preallocated_size *= 32;
+ stolen = 32 * 1024 * 1024;
break;
case INTEL_915G_GMCH_GMS_STOLEN_48M:
- *preallocated_size *= 48;
+ stolen = 48 * 1024 * 1024;
break;
case INTEL_915G_GMCH_GMS_STOLEN_64M:
- *preallocated_size *= 64;
+ stolen = 64 * 1024 * 1024;
+ break;
+ case INTEL_GMCH_GMS_STOLEN_128M:
+ stolen = 128 * 1024 * 1024;
+ break;
+ case INTEL_GMCH_GMS_STOLEN_256M:
+ stolen = 256 * 1024 * 1024;
+ break;
+ case INTEL_GMCH_GMS_STOLEN_96M:
+ stolen = 96 * 1024 * 1024;
+ break;
+ case INTEL_GMCH_GMS_STOLEN_160M:
+ stolen = 160 * 1024 * 1024;
+ break;
+ case INTEL_GMCH_GMS_STOLEN_224M:
+ stolen = 224 * 1024 * 1024;
+ break;
+ case INTEL_GMCH_GMS_STOLEN_352M:
+ stolen = 352 * 1024 * 1024;
break;
- case INTEL_855_GMCH_GMS_DISABLED:
- DRM_ERROR("video memory is disabled\n");
- return -1;
default:
DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
- tmp & INTEL_855_GMCH_GMS_MASK);
+ tmp & INTEL_GMCH_GMS_MASK);
return -1;
}
- *preallocated_size -= overhead;
+ *preallocated_size = stolen - overhead;
return 0;
}
@@ -916,13 +944,14 @@ static int i915_load_modeset_init(struct drm_device *dev)
dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
0xff000000;
- DRM_DEBUG("*** fb base 0x%08lx\n", dev->mode_config.fb_base);
-
- if (IS_MOBILE(dev) || (IS_I9XX(dev) && !IS_I965G(dev) && !IS_G33(dev)))
+ if (IS_MOBILE(dev) || IS_I9XX(dev))
dev_priv->cursor_needs_physical = true;
else
dev_priv->cursor_needs_physical = false;
+ if (IS_I965G(dev) || IS_G33(dev))
+ dev_priv->cursor_needs_physical = false;
+
ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
if (ret)
goto kfree_devname;
@@ -1132,6 +1161,8 @@ int i915_driver_unload(struct drm_device *dev)
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_modeset_cleanup(dev);
+ i915_gem_free_all_phys_object(dev);
+
mutex_lock(&dev->struct_mutex);
i915_gem_cleanup_ringbuffer(dev);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4756e5cd6b5e..e13518252007 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -72,6 +72,18 @@ enum pipe {
#define WATCH_INACTIVE 0
#define WATCH_PWRITE 0
+#define I915_GEM_PHYS_CURSOR_0 1
+#define I915_GEM_PHYS_CURSOR_1 2
+#define I915_GEM_PHYS_OVERLAY_REGS 3
+#define I915_MAX_PHYS_OBJECT (I915_GEM_PHYS_OVERLAY_REGS)
+
+struct drm_i915_gem_phys_object {
+ int id;
+ struct page **page_list;
+ drm_dma_handle_t *handle;
+ struct drm_gem_object *cur_obj;
+};
+
typedef struct _drm_i915_ring_buffer {
int tail_mask;
unsigned long Size;
@@ -358,6 +370,9 @@ typedef struct drm_i915_private {
uint32_t bit_6_swizzle_x;
/** Bit 6 swizzling required for Y tiling */
uint32_t bit_6_swizzle_y;
+
+ /* storage for physical objects */
+ struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT];
} mm;
} drm_i915_private_t;
@@ -436,6 +451,9 @@ struct drm_i915_gem_object {
/** User space pin count and filp owning the pin */
uint32_t user_pin_count;
struct drm_file *pin_filp;
+
+ /** for phy allocated objects */
+ struct drm_i915_gem_phys_object *phys_obj;
};
/**
@@ -598,6 +616,11 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start,
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
int write);
+int i915_gem_attach_phys_object(struct drm_device *dev,
+ struct drm_gem_object *obj, int id);
+void i915_gem_detach_phys_object(struct drm_device *dev,
+ struct drm_gem_object *obj);
+void i915_gem_free_all_phys_object(struct drm_device *dev);
/* i915_gem_tiling.c */
void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
@@ -664,6 +687,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
writel(upper_32_bits(val), dev_priv->regs + \
(reg) + 4))
#endif
+#define POSTING_READ(reg) (void)I915_READ(reg)
#define I915_VERBOSE 0
@@ -760,6 +784,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))
#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
+#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev))
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index cc2ca5561feb..debad5c04cc0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -55,6 +55,9 @@ static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
static int i915_gem_evict_something(struct drm_device *dev);
+static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+ struct drm_i915_gem_pwrite *args,
+ struct drm_file *file_priv);
int i915_gem_do_init(struct drm_device *dev, unsigned long start,
unsigned long end)
@@ -386,8 +389,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
* pread/pwrite currently are reading and writing from the CPU
* perspective, requiring manual detiling by the client.
*/
- if (obj_priv->tiling_mode == I915_TILING_NONE &&
- dev->gtt_total != 0)
+ if (obj_priv->phys_obj)
+ ret = i915_gem_phys_pwrite(dev, obj, args, file_priv);
+ else if (obj_priv->tiling_mode == I915_TILING_NONE &&
+ dev->gtt_total != 0)
ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
else
ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
@@ -1445,7 +1450,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
(obj_priv->gtt_offset & (obj->size - 1))) {
- WARN(1, "%s: object not 1M or size aligned\n", __FUNCTION__);
+ WARN(1, "%s: object not 1M or size aligned\n", __func__);
return;
}
@@ -1478,7 +1483,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
(obj_priv->gtt_offset & (obj->size - 1))) {
- WARN(1, "%s: object not 1M or size aligned\n", __FUNCTION__);
+ WARN(1, "%s: object not 1M or size aligned\n", __func__);
return;
}
@@ -1623,6 +1628,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
struct drm_mm_node *free_space;
int page_count, ret;
+ if (dev_priv->mm.suspended)
+ return -EBUSY;
if (alignment == 0)
alignment = PAGE_SIZE;
if (alignment & (PAGE_SIZE - 1)) {
@@ -2641,7 +2648,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
if (obj_priv->gtt_space == NULL) {
ret = i915_gem_object_bind_to_gtt(obj, alignment);
if (ret != 0) {
- if (ret != -ERESTARTSYS)
+ if (ret != -EBUSY && ret != -ERESTARTSYS)
DRM_ERROR("Failure to bind: %d", ret);
return ret;
}
@@ -2856,6 +2863,9 @@ void i915_gem_free_object(struct drm_gem_object *obj)
while (obj_priv->pin_count > 0)
i915_gem_object_unpin(obj);
+ if (obj_priv->phys_obj)
+ i915_gem_detach_phys_object(dev, obj);
+
i915_gem_object_unbind(obj);
list = &obj->map_list;
@@ -3219,20 +3229,21 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
dev_priv->mm.wedged = 0;
}
- ret = i915_gem_init_ringbuffer(dev);
- if (ret != 0)
- return ret;
-
dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base,
dev->agp->agp_info.aper_size
* 1024 * 1024);
mutex_lock(&dev->struct_mutex);
+ dev_priv->mm.suspended = 0;
+
+ ret = i915_gem_init_ringbuffer(dev);
+ if (ret != 0)
+ return ret;
+
BUG_ON(!list_empty(&dev_priv->mm.active_list));
BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
BUG_ON(!list_empty(&dev_priv->mm.request_list));
- dev_priv->mm.suspended = 0;
mutex_unlock(&dev->struct_mutex);
drm_irq_install(dev);
@@ -3290,3 +3301,180 @@ i915_gem_load(struct drm_device *dev)
i915_gem_detect_bit_6_swizzle(dev);
}
+
+/*
+ * Create a physically contiguous memory object for this object
+ * e.g. for cursor + overlay regs
+ */
+int i915_gem_init_phys_object(struct drm_device *dev,
+ int id, int size)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_phys_object *phys_obj;
+ int ret;
+
+ if (dev_priv->mm.phys_objs[id - 1] || !size)
+ return 0;
+
+ phys_obj = drm_calloc(1, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
+ if (!phys_obj)
+ return -ENOMEM;
+
+ phys_obj->id = id;
+
+ phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff);
+ if (!phys_obj->handle) {
+ ret = -ENOMEM;
+ goto kfree_obj;
+ }
+#ifdef CONFIG_X86
+ set_memory_wc((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE);
+#endif
+
+ dev_priv->mm.phys_objs[id - 1] = phys_obj;
+
+ return 0;
+kfree_obj:
+ drm_free(phys_obj, sizeof(struct drm_i915_gem_phys_object), DRM_MEM_DRIVER);
+ return ret;
+}
+
+void i915_gem_free_phys_object(struct drm_device *dev, int id)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_phys_object *phys_obj;
+
+ if (!dev_priv->mm.phys_objs[id - 1])
+ return;
+
+ phys_obj = dev_priv->mm.phys_objs[id - 1];
+ if (phys_obj->cur_obj) {
+ i915_gem_detach_phys_object(dev, phys_obj->cur_obj);
+ }
+
+#ifdef CONFIG_X86
+ set_memory_wb((unsigned long)phys_obj->handle->vaddr, phys_obj->handle->size / PAGE_SIZE);
+#endif
+ drm_pci_free(dev, phys_obj->handle);
+ kfree(phys_obj);
+ dev_priv->mm.phys_objs[id - 1] = NULL;
+}
+
+void i915_gem_free_all_phys_object(struct drm_device *dev)
+{
+ int i;
+
+ for (i = I915_GEM_PHYS_CURSOR_0; i <= I915_MAX_PHYS_OBJECT; i++)
+ i915_gem_free_phys_object(dev, i);
+}
+
+void i915_gem_detach_phys_object(struct drm_device *dev,
+ struct drm_gem_object *obj)
+{
+ struct drm_i915_gem_object *obj_priv;
+ int i;
+ int ret;
+ int page_count;
+
+ obj_priv = obj->driver_private;
+ if (!obj_priv->phys_obj)
+ return;
+
+ ret = i915_gem_object_get_page_list(obj);
+ if (ret)
+ goto out;
+
+ page_count = obj->size / PAGE_SIZE;
+
+ for (i = 0; i < page_count; i++) {
+ char *dst = kmap_atomic(obj_priv->page_list[i], KM_USER0);
+ char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
+
+ memcpy(dst, src, PAGE_SIZE);
+ kunmap_atomic(dst, KM_USER0);
+ }
+ drm_clflush_pages(obj_priv->page_list, page_count);
+ drm_agp_chipset_flush(dev);
+out:
+ obj_priv->phys_obj->cur_obj = NULL;
+ obj_priv->phys_obj = NULL;
+}
+
+int
+i915_gem_attach_phys_object(struct drm_device *dev,
+ struct drm_gem_object *obj, int id)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj_priv;
+ int ret = 0;
+ int page_count;
+ int i;
+
+ if (id > I915_MAX_PHYS_OBJECT)
+ return -EINVAL;
+
+ obj_priv = obj->driver_private;
+
+ if (obj_priv->phys_obj) {
+ if (obj_priv->phys_obj->id == id)
+ return 0;
+ i915_gem_detach_phys_object(dev, obj);
+ }
+
+
+ /* create a new object */
+ if (!dev_priv->mm.phys_objs[id - 1]) {
+ ret = i915_gem_init_phys_object(dev, id,
+ obj->size);
+ if (ret) {
+ DRM_ERROR("failed to init phys object %d size: %zu\n", id, obj->size);
+ goto out;
+ }
+ }
+
+ /* bind to the object */
+ obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1];
+ obj_priv->phys_obj->cur_obj = obj;
+
+ ret = i915_gem_object_get_page_list(obj);
+ if (ret) {
+ DRM_ERROR("failed to get page list\n");
+ goto out;
+ }
+
+ page_count = obj->size / PAGE_SIZE;
+
+ for (i = 0; i < page_count; i++) {
+ char *src = kmap_atomic(obj_priv->page_list[i], KM_USER0);
+ char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
+
+ memcpy(dst, src, PAGE_SIZE);
+ kunmap_atomic(src, KM_USER0);
+ }
+
+ return 0;
+out:
+ return ret;
+}
+
+static int
+i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
+ struct drm_i915_gem_pwrite *args,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ void *obj_addr;
+ int ret;
+ char __user *user_data;
+
+ user_data = (char __user *) (uintptr_t) args->data_ptr;
+ obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
+
+ DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size);
+ ret = copy_from_user(obj_addr, user_data, args->size);
+ if (ret)
+ return -EFAULT;
+
+ drm_agp_chipset_flush(dev);
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 0cadafbef411..6290219de6c8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -411,6 +411,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags;
+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+ u32 pipeconf;
+
+ pipeconf = I915_READ(pipeconf_reg);
+ if (!(pipeconf & PIPEACONF_ENABLE))
+ return -EINVAL;
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (IS_I965G(dev))
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 47e6bafeb743..273162579e1b 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -35,7 +35,7 @@
#define INTEL_GMCH_MEM_64M 0x1
#define INTEL_GMCH_MEM_128M 0
-#define INTEL_855_GMCH_GMS_MASK (0x7 << 4)
+#define INTEL_GMCH_GMS_MASK (0xf << 4)
#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4)
#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4)
#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4)
@@ -45,6 +45,12 @@
#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
+#define INTEL_GMCH_GMS_STOLEN_128M (0x8 << 4)
+#define INTEL_GMCH_GMS_STOLEN_256M (0x9 << 4)
+#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
+#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
+#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
+#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
/* PCI config space */
@@ -549,6 +555,8 @@
/** GM965 GM45 render standby register */
#define MCHBAR_RENDER_STANDBY 0x111B8
+#define PEG_BAND_GAP_DATA 0x14d68
+
/*
* Overlay regs
*/
@@ -612,6 +620,9 @@
/* Hotplug control (945+ only) */
#define PORT_HOTPLUG_EN 0x61110
+#define HDMIB_HOTPLUG_INT_EN (1 << 29)
+#define HDMIC_HOTPLUG_INT_EN (1 << 28)
+#define HDMID_HOTPLUG_INT_EN (1 << 27)
#define SDVOB_HOTPLUG_INT_EN (1 << 26)
#define SDVOC_HOTPLUG_INT_EN (1 << 25)
#define TV_HOTPLUG_INT_EN (1 << 18)
@@ -619,6 +630,9 @@
#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
#define PORT_HOTPLUG_STAT 0x61114
+#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
+#define HDMIC_HOTPLUG_INT_STATUS (1 << 28)
+#define HDMID_HOTPLUG_INT_STATUS (1 << 27)
#define CRT_HOTPLUG_INT_STATUS (1 << 11)
#define TV_HOTPLUG_INT_STATUS (1 << 10)
#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
@@ -648,7 +662,16 @@
#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
#define SDVOC_GANG_MODE (1 << 16)
+#define SDVO_ENCODING_SDVO (0x0 << 10)
+#define SDVO_ENCODING_HDMI (0x2 << 10)
+/** Requird for HDMI operation */
+#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9)
#define SDVO_BORDER_ENABLE (1 << 7)
+#define SDVO_AUDIO_ENABLE (1 << 6)
+/** New with 965, default is to be set */
+#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4)
+/** New with 965, default is to be set */
+#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3)
#define SDVOB_PCIE_CONCURRENCY (1 << 3)
#define SDVO_DETECTED (1 << 2)
/* Bits to be preserved when writing */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e5c1c80d1f90..31c3732b7a69 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -401,6 +401,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
I915_WRITE(dspstride, crtc->fb->pitch);
dspcntr = I915_READ(dspcntr_reg);
+ /* Mask out pixel format bits in case we change it */
+ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
switch (crtc->fb->bits_per_pixel) {
case 8:
dspcntr |= DISPPLANE_8BPP;
@@ -751,6 +753,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
is_lvds = true;
break;
case INTEL_OUTPUT_SDVO:
+ case INTEL_OUTPUT_HDMI:
is_sdvo = true;
break;
case INTEL_OUTPUT_DVO:
@@ -986,19 +989,17 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
uint32_t temp;
size_t addr;
+ int ret;
DRM_DEBUG("\n");
/* if we want to turn off the cursor ignore width and height */
if (!handle) {
DRM_DEBUG("cursor off\n");
- /* turn of the cursor */
- temp = 0;
- temp |= CURSOR_MODE_DISABLE;
-
- I915_WRITE(control, temp);
- I915_WRITE(base, 0);
- return 0;
+ temp = CURSOR_MODE_DISABLE;
+ addr = 0;
+ bo = NULL;
+ goto finish;
}
/* Currently we only support 64x64 cursors */
@@ -1015,26 +1016,56 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
if (bo->size < width * height * 4) {
DRM_ERROR("buffer is to small\n");
- drm_gem_object_unreference(bo);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
- if (dev_priv->cursor_needs_physical) {
- addr = dev->agp->base + obj_priv->gtt_offset;
- } else {
+ /* we only need to pin inside GTT if cursor is non-phy */
+ if (!dev_priv->cursor_needs_physical) {
+ ret = i915_gem_object_pin(bo, PAGE_SIZE);
+ if (ret) {
+ DRM_ERROR("failed to pin cursor bo\n");
+ goto fail;
+ }
addr = obj_priv->gtt_offset;
+ } else {
+ ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
+ if (ret) {
+ DRM_ERROR("failed to attach phys object\n");
+ goto fail;
+ }
+ addr = obj_priv->phys_obj->handle->busaddr;
}
- intel_crtc->cursor_addr = addr;
temp = 0;
/* set the pipe for the cursor */
temp |= (pipe << 28);
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+ finish:
I915_WRITE(control, temp);
I915_WRITE(base, addr);
+ if (intel_crtc->cursor_bo) {
+ if (dev_priv->cursor_needs_physical) {
+ if (intel_crtc->cursor_bo != bo)
+ i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
+ } else
+ i915_gem_object_unpin(intel_crtc->cursor_bo);
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(intel_crtc->cursor_bo);
+ mutex_unlock(&dev->struct_mutex);
+ }
+
+ intel_crtc->cursor_addr = addr;
+ intel_crtc->cursor_bo = bo;
+
return 0;
+fail:
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(bo);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
}
static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
@@ -1430,12 +1461,19 @@ static void intel_setup_outputs(struct drm_device *dev)
intel_lvds_init(dev);
if (IS_I9XX(dev)) {
- intel_sdvo_init(dev, SDVOB);
- intel_sdvo_init(dev, SDVOC);
+ int found;
+
+ found = intel_sdvo_init(dev, SDVOB);
+ if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+ intel_hdmi_init(dev, SDVOB);
+
+ found = intel_sdvo_init(dev, SDVOC);
+ if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+ intel_hdmi_init(dev, SDVOC);
} else
intel_dvo_init(dev);
- if (IS_I9XX(dev) && !IS_I915G(dev))
+ if (IS_I9XX(dev) && IS_MOBILE(dev))
intel_tv_init(dev);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -1445,6 +1483,11 @@ static void intel_setup_outputs(struct drm_device *dev)
/* valid crtcs */
switch(intel_output->type) {
+ case INTEL_OUTPUT_HDMI:
+ crtc_mask = ((1 << 0)|
+ (1 << 1));
+ clone_mask = ((1 << INTEL_OUTPUT_HDMI));
+ break;
case INTEL_OUTPUT_DVO:
case INTEL_OUTPUT_SDVO:
crtc_mask = ((1 << 0)|
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 407edd5bf582..8a4cc50c5b4e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -53,6 +53,7 @@
#define INTEL_OUTPUT_SDVO 3
#define INTEL_OUTPUT_LVDS 4
#define INTEL_OUTPUT_TVOUT 5
+#define INTEL_OUTPUT_HDMI 6
#define INTEL_DVO_CHIP_NONE 0
#define INTEL_DVO_CHIP_LVDS 1
@@ -88,6 +89,7 @@ struct intel_crtc {
struct drm_crtc base;
int pipe;
int plane;
+ struct drm_gem_object *cursor_bo;
uint32_t cursor_addr;
u8 lut_r[256], lut_g[256], lut_b[256];
int dpms_mode;
@@ -108,7 +110,8 @@ int intel_ddc_get_modes(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output);
extern void intel_crt_init(struct drm_device *dev);
-extern void intel_sdvo_init(struct drm_device *dev, int output_device);
+extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
+extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
extern void intel_dvo_init(struct drm_device *dev);
extern void intel_tv_init(struct drm_device *dev);
extern void intel_lvds_init(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
new file mode 100644
index 000000000000..b06a4a3ff08d
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2006 Dave Airlie <airlied@linux.ie>
+ * Copyright © 2006-2009 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+
+struct intel_hdmi_priv {
+ u32 sdvox_reg;
+ u32 save_SDVOX;
+ int has_hdmi_sink;
+};
+
+static void intel_hdmi_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_crtc *crtc = encoder->crtc;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+ struct intel_output *intel_output = enc_to_intel_output(encoder);
+ struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
+ u32 sdvox;
+
+ sdvox = SDVO_ENCODING_HDMI |
+ SDVO_BORDER_ENABLE |
+ SDVO_VSYNC_ACTIVE_HIGH |
+ SDVO_HSYNC_ACTIVE_HIGH;
+
+ if (hdmi_priv->has_hdmi_sink)
+ sdvox |= SDVO_AUDIO_ENABLE;
+
+ if (intel_crtc->pipe == 1)
+ sdvox |= SDVO_PIPE_B_SELECT;
+
+ I915_WRITE(hdmi_priv->sdvox_reg, sdvox);
+ POSTING_READ(hdmi_priv->sdvox_reg);
+}
+
+static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_output *intel_output = enc_to_intel_output(encoder);
+ struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
+ u32 temp;
+
+ if (mode != DRM_MODE_DPMS_ON) {
+ temp = I915_READ(hdmi_priv->sdvox_reg);
+ I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE);
+ } else {
+ temp = I915_READ(hdmi_priv->sdvox_reg);
+ I915_WRITE(hdmi_priv->sdvox_reg, temp | SDVO_ENABLE);
+ }
+ POSTING_READ(hdmi_priv->sdvox_reg);
+}
+
+static void intel_hdmi_save(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
+
+ hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg);
+}
+
+static void intel_hdmi_restore(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
+
+ I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX);
+ POSTING_READ(hdmi_priv->sdvox_reg);
+}
+
+static int intel_hdmi_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+ if (mode->clock > 165000)
+ return MODE_CLOCK_HIGH;
+ if (mode->clock < 20000)
+ return MODE_CLOCK_HIGH;
+
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ return MODE_OK;
+}
+
+static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+static enum drm_connector_status
+intel_hdmi_detect(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_output *intel_output = to_intel_output(connector);
+ struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
+ u32 temp, bit;
+
+ temp = I915_READ(PORT_HOTPLUG_EN);
+
+ I915_WRITE(PORT_HOTPLUG_EN,
+ temp |
+ HDMIB_HOTPLUG_INT_EN |
+ HDMIC_HOTPLUG_INT_EN |
+ HDMID_HOTPLUG_INT_EN);
+
+ POSTING_READ(PORT_HOTPLUG_EN);
+
+ switch (hdmi_priv->sdvox_reg) {
+ case SDVOB:
+ bit = HDMIB_HOTPLUG_INT_STATUS;
+ break;
+ case SDVOC:
+ bit = HDMIC_HOTPLUG_INT_STATUS;
+ break;
+ default:
+ return connector_status_unknown;
+ }
+
+ if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0)
+ return connector_status_connected;
+ else
+ return connector_status_disconnected;
+}
+
+static int intel_hdmi_get_modes(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+
+ /* We should parse the EDID data and find out if it's an HDMI sink so
+ * we can send audio to it.
+ */
+
+ return intel_ddc_get_modes(intel_output);
+}
+
+static void intel_hdmi_destroy(struct drm_connector *connector)
+{
+ struct intel_output *intel_output = to_intel_output(connector);
+
+ if (intel_output->i2c_bus)
+ intel_i2c_destroy(intel_output->i2c_bus);
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+ kfree(intel_output);
+}
+
+static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
+ .dpms = intel_hdmi_dpms,
+ .mode_fixup = intel_hdmi_mode_fixup,
+ .prepare = intel_encoder_prepare,
+ .mode_set = intel_hdmi_mode_set,
+ .commit = intel_encoder_commit,
+};
+
+static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
+ .save = intel_hdmi_save,
+ .restore = intel_hdmi_restore,
+ .detect = intel_hdmi_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = intel_hdmi_destroy,
+};
+
+static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
+ .get_modes = intel_hdmi_get_modes,
+ .mode_valid = intel_hdmi_mode_valid,
+ .best_encoder = intel_best_encoder,
+};
+
+static void intel_hdmi_enc_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
+ .destroy = intel_hdmi_enc_destroy,
+};
+
+
+void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_connector *connector;
+ struct intel_output *intel_output;
+ struct intel_hdmi_priv *hdmi_priv;
+
+ intel_output = kcalloc(sizeof(struct intel_output) +
+ sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL);
+ if (!intel_output)
+ return;
+ hdmi_priv = (struct intel_hdmi_priv *)(intel_output + 1);
+
+ connector = &intel_output->base;
+ drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_DVID);
+ drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
+
+ intel_output->type = INTEL_OUTPUT_HDMI;
+
+ connector->interlace_allowed = 0;
+ connector->doublescan_allowed = 0;
+
+ /* Set up the DDC bus. */
+ if (sdvox_reg == SDVOB)
+ intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
+ else
+ intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
+
+ if (!intel_output->ddc_bus)
+ goto err_connector;
+
+ hdmi_priv->sdvox_reg = sdvox_reg;
+ intel_output->dev_priv = hdmi_priv;
+
+ drm_encoder_init(dev, &intel_output->enc, &intel_hdmi_enc_funcs,
+ DRM_MODE_ENCODER_TMDS);
+ drm_encoder_helper_add(&intel_output->enc, &intel_hdmi_helper_funcs);
+
+ drm_mode_connector_attach_encoder(&intel_output->base,
+ &intel_output->enc);
+ drm_sysfs_connector_add(connector);
+
+ /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
+ * 0xd. Failure to do so will result in spurious interrupts being
+ * generated on the port when a cable is not attached.
+ */
+ if (IS_G4X(dev) && !IS_GM45(dev)) {
+ u32 temp = I915_READ(PEG_BAND_GAP_DATA);
+ I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
+ }
+
+ return;
+
+err_connector:
+ drm_connector_cleanup(connector);
+ kfree(intel_output);
+
+ return;
+}
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index a5a2f5339e9e..5ee9d4c25753 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -137,10 +137,6 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
chan->reg = reg;
snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
chan->adapter.owner = THIS_MODULE;
-#ifndef I2C_HW_B_INTELFB
-#define I2C_HW_B_INTELFB I2C_HW_B_I810
-#endif
- chan->adapter.id = I2C_HW_B_INTELFB;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &dev->pdev->dev;
chan->algo.setsda = set_data;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index ccecfaf6307b..b36a5214d8df 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -311,7 +311,7 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
if (dev_priv->panel_fixed_mode != NULL) {
struct drm_display_mode *mode;
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.mutex);
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
drm_mode_probed_add(connector, mode);
mutex_unlock(&dev->mode_config.mutex);
@@ -340,6 +340,18 @@ static void intel_lvds_destroy(struct drm_connector *connector)
kfree(connector);
}
+static int intel_lvds_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t value)
+{
+ struct drm_device *dev = connector->dev;
+
+ if (property == dev->mode_config.dpms_property && connector->encoder)
+ intel_lvds_dpms(connector->encoder, (uint32_t)(value & 0xf));
+
+ return 0;
+}
+
static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
.dpms = intel_lvds_dpms,
.mode_fixup = intel_lvds_mode_fixup,
@@ -359,6 +371,7 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.restore = intel_lvds_restore,
.detect = intel_lvds_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = intel_lvds_set_property,
.destroy = intel_lvds_destroy,
};
@@ -456,6 +469,13 @@ void intel_lvds_init(struct drm_device *dev)
dev_priv->panel_fixed_mode =
drm_mode_duplicate(dev, dev_priv->vbt_mode);
mutex_unlock(&dev->mode_config.mutex);
+ if (dev_priv->panel_fixed_mode) {
+ dev_priv->panel_fixed_mode->type |=
+ DRM_MODE_TYPE_PREFERRED;
+ drm_mode_probed_add(connector,
+ dev_priv->panel_fixed_mode);
+ goto out;
+ }
}
/*
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index fbbaa4f414a0..407215469102 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -978,7 +978,7 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
};
-void intel_sdvo_init(struct drm_device *dev, int output_device)
+bool intel_sdvo_init(struct drm_device *dev, int output_device)
{
struct drm_connector *connector;
struct intel_output *intel_output;
@@ -991,7 +991,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
if (!intel_output) {
- return;
+ return false;
}
connector = &intel_output->base;
@@ -1116,7 +1116,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
intel_output->ddc_bus = i2cbus;
- return;
+ return true;
err_i2c:
intel_i2c_destroy(intel_output->i2c_bus);
@@ -1124,5 +1124,5 @@ err_connector:
drm_connector_cleanup(connector);
kfree(intel_output);
- return;
+ return false;
}
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index b4fd8ca701a4..e85c8fe9ffcf 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -85,14 +85,14 @@ config HID_COMPAT
config HID_A4TECH
tristate "A4 tech" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for A4 tech X5 and WOP-35 / Trust 450L mice.
config HID_APPLE
tristate "Apple" if EMBEDDED
depends on (USB_HID || BT_HIDP)
- default y
+ default !EMBEDDED
---help---
Support for some Apple devices which less or more break
HID specification.
@@ -103,64 +103,49 @@ config HID_APPLE
config HID_BELKIN
tristate "Belkin" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Belkin Flip KVM and Wireless keyboard.
-config HID_BRIGHT
- tristate "Bright" if EMBEDDED
- depends on USB_HID
- default y
- ---help---
- Support for Bright ABNT-2 keyboard.
-
config HID_CHERRY
tristate "Cherry" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Cherry Cymotion keyboard.
config HID_CHICONY
tristate "Chicony" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Chicony Tactical pad.
config HID_CYPRESS
tristate "Cypress" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for cypress mouse and barcode readers.
-config HID_DELL
- tristate "Dell" if EMBEDDED
- depends on USB_HID
- default y
- ---help---
- Support for quirky Dell HID hardware that require
- special LED handling (W7658 and SK8115 models)
-
config HID_EZKEY
tristate "Ezkey" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Ezkey BTC 8193 keyboard.
config HID_GYRATION
tristate "Gyration" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Gyration remote control.
config HID_LOGITECH
tristate "Logitech" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Logitech devices that are not fully compliant with HID standard.
@@ -191,21 +176,28 @@ config LOGIRUMBLEPAD2_FF
config HID_MICROSOFT
tristate "Microsoft" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Microsoft devices that are not fully compliant with HID standard.
config HID_MONTEREY
tristate "Monterey" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Monterey Genius KB29E.
+config HID_NTRIG
+ tristate "NTrig" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Support for N-Trig touch screen.
+
config HID_PANTHERLORD
tristate "Pantherlord devices support" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for PantherLord/GreenAsia based device support.
@@ -220,31 +212,47 @@ config PANTHERLORD_FF
config HID_PETALYNX
tristate "Petalynx" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Petalynx Maxter remote control.
config HID_SAMSUNG
tristate "Samsung" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Samsung InfraRed remote control.
config HID_SONY
tristate "Sony" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Sony PS3 controller.
config HID_SUNPLUS
tristate "Sunplus" if EMBEDDED
depends on USB_HID
- default y
+ default !EMBEDDED
---help---
Support for Sunplus wireless desktop.
+config GREENASIA_FF
+ tristate "GreenAsia (Product ID 0x12) force feedback support"
+ depends on USB_HID
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
+ (like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter
+ and want to enable force feedback support for it.
+
+config HID_TOPSEED
+ tristate "TopSeed Cyberlink remote control support" if EMBEDDED
+ depends on USB_HID
+ default !EMBEDDED
+ ---help---
+ Say Y if you have a TopSeed Cyberlink remote control.
+
config THRUSTMASTER_FF
tristate "ThrustMaster devices support"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index b09e43e7413e..fbd021f153f1 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -23,22 +23,23 @@ endif
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
obj-$(CONFIG_HID_APPLE) += hid-apple.o
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
-obj-$(CONFIG_HID_BRIGHT) += hid-bright.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
-obj-$(CONFIG_HID_DELL) += hid-dell.o
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
+obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SONY) += hid-sony.o
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
+obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
+obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
obj-$(CONFIG_USB_HID) += usbhid/
diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c
deleted file mode 100644
index 38517a117dfd..000000000000
--- a/drivers/hid/hid-bright.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * HID driver for some bright "special" devices
- *
- * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * Based on hid-dell driver
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-
-#include "hid-ids.h"
-
-static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
- int ret;
-
- ret = hid_parse(hdev);
- if (ret) {
- dev_err(&hdev->dev, "parse failed\n");
- goto err_free;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
- dev_err(&hdev->dev, "hw start failed\n");
- goto err_free;
- }
-
- usbhid_set_leds(hdev);
-
- return 0;
-err_free:
- return ret;
-}
-
-static const struct hid_device_id bright_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
- { }
-};
-MODULE_DEVICE_TABLE(hid, bright_devices);
-
-static struct hid_driver bright_driver = {
- .name = "bright",
- .id_table = bright_devices,
- .probe = bright_probe,
-};
-
-static int bright_init(void)
-{
- return hid_register_driver(&bright_driver);
-}
-
-static void bright_exit(void)
-{
- hid_unregister_driver(&bright_driver);
-}
-
-module_init(bright_init);
-module_exit(bright_exit);
-MODULE_LICENSE("GPL");
-
-HID_COMPAT_LOAD_DRIVER(bright);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 40df3e1b4bd1..6cad69ed21c5 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1218,6 +1218,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
}
EXPORT_SYMBOL_GPL(hid_connect);
+/* a list of devices for which there is a specialized driver on HID bus */
static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
@@ -1256,19 +1257,16 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
- { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
@@ -1279,7 +1277,6 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
@@ -1297,23 +1294,105 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
{ }
};
+struct hid_dynid {
+ struct list_head list;
+ struct hid_device_id id;
+};
+
+/**
+ * store_new_id - add a new HID device ID to this driver and re-probe devices
+ * @driver: target device driver
+ * @buf: buffer for scanning device ID data
+ * @count: input size
+ *
+ * Adds a new dynamic hid device ID to this driver,
+ * and causes the driver to probe for all devices again.
+ */
+static ssize_t store_new_id(struct device_driver *drv, const char *buf,
+ size_t count)
+{
+ struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
+ struct hid_dynid *dynid;
+ __u32 bus, vendor, product;
+ unsigned long driver_data = 0;
+ int ret;
+
+ ret = sscanf(buf, "%x %x %x %lx",
+ &bus, &vendor, &product, &driver_data);
+ if (ret < 3)
+ return -EINVAL;
+
+ dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+ if (!dynid)
+ return -ENOMEM;
+
+ dynid->id.bus = bus;
+ dynid->id.vendor = vendor;
+ dynid->id.product = product;
+ dynid->id.driver_data = driver_data;
+
+ spin_lock(&hdrv->dyn_lock);
+ list_add_tail(&dynid->list, &hdrv->dyn_list);
+ spin_unlock(&hdrv->dyn_lock);
+
+ ret = 0;
+ if (get_driver(&hdrv->driver)) {
+ ret = driver_attach(&hdrv->driver);
+ put_driver(&hdrv->driver);
+ }
+
+ return ret ? : count;
+}
+static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
+
+static void hid_free_dynids(struct hid_driver *hdrv)
+{
+ struct hid_dynid *dynid, *n;
+
+ spin_lock(&hdrv->dyn_lock);
+ list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) {
+ list_del(&dynid->list);
+ kfree(dynid);
+ }
+ spin_unlock(&hdrv->dyn_lock);
+}
+
+static const struct hid_device_id *hid_match_device(struct hid_device *hdev,
+ struct hid_driver *hdrv)
+{
+ struct hid_dynid *dynid;
+
+ spin_lock(&hdrv->dyn_lock);
+ list_for_each_entry(dynid, &hdrv->dyn_list, list) {
+ if (hid_match_one_id(hdev, &dynid->id)) {
+ spin_unlock(&hdrv->dyn_lock);
+ return &dynid->id;
+ }
+ }
+ spin_unlock(&hdrv->dyn_lock);
+
+ return hid_match_id(hdev, hdrv->id_table);
+}
+
static int hid_bus_match(struct device *dev, struct device_driver *drv)
{
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
- if (!hid_match_id(hdev, hdrv->id_table))
+ if (!hid_match_device(hdev, hdrv))
return 0;
/* generic wants all non-blacklisted */
@@ -1332,7 +1411,7 @@ static int hid_device_probe(struct device *dev)
int ret = 0;
if (!hdev->driver) {
- id = hid_match_id(hdev, hdrv->id_table);
+ id = hid_match_device(hdev, hdrv);
if (id == NULL)
return -ENODEV;
@@ -1398,6 +1477,7 @@ static struct bus_type hid_bus_type = {
.uevent = hid_uevent,
};
+/* a list of devices that shouldn't be handled by HID core at all */
static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302) },
@@ -1420,6 +1500,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
@@ -1527,6 +1608,8 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD4) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
@@ -1577,6 +1660,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ }
@@ -1618,9 +1704,10 @@ int hid_add_device(struct hid_device *hdev)
if (hid_ignore(hdev))
return -ENODEV;
- /* XXX hack, any other cleaner solution < 20 bus_id bytes? */
- sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus,
- hdev->vendor, hdev->product, atomic_inc_return(&id));
+ /* XXX hack, any other cleaner solution after the driver core
+ * is converted to allow more than 20 bytes as the device name? */
+ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
+ hdev->vendor, hdev->product, atomic_inc_return(&id));
ret = device_add(&hdev->dev);
if (!ret)
@@ -1695,18 +1782,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device);
int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
const char *mod_name)
{
+ int ret;
+
hdrv->driver.name = hdrv->name;
hdrv->driver.bus = &hid_bus_type;
hdrv->driver.owner = owner;
hdrv->driver.mod_name = mod_name;
- return driver_register(&hdrv->driver);
+ INIT_LIST_HEAD(&hdrv->dyn_list);
+ spin_lock_init(&hdrv->dyn_lock);
+
+ ret = driver_register(&hdrv->driver);
+ if (ret)
+ return ret;
+
+ ret = driver_create_file(&hdrv->driver, &driver_attr_new_id);
+ if (ret)
+ driver_unregister(&hdrv->driver);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(__hid_register_driver);
void hid_unregister_driver(struct hid_driver *hdrv)
{
+ driver_remove_file(&hdrv->driver, &driver_attr_new_id);
driver_unregister(&hdrv->driver);
+ hid_free_dynids(hdrv);
}
EXPORT_SYMBOL_GPL(hid_unregister_driver);
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c
deleted file mode 100644
index f5474300b83a..000000000000
--- a/drivers/hid/hid-dell.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * HID driver for some dell "special" devices
- *
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
- * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
- * Copyright (c) 2007 Paul Walmsley
- * Copyright (c) 2008 Jiri Slaby
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-
-#include "hid-ids.h"
-
-static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
- int ret;
-
- ret = hid_parse(hdev);
- if (ret) {
- dev_err(&hdev->dev, "parse failed\n");
- goto err_free;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret) {
- dev_err(&hdev->dev, "hw start failed\n");
- goto err_free;
- }
-
- usbhid_set_leds(hdev);
-
- return 0;
-err_free:
- return ret;
-}
-
-static const struct hid_device_id dell_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
- { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
- { }
-};
-MODULE_DEVICE_TABLE(hid, dell_devices);
-
-static struct hid_driver dell_driver = {
- .name = "dell",
- .id_table = dell_devices,
- .probe = dell_probe,
-};
-
-static int dell_init(void)
-{
- return hid_register_driver(&dell_driver);
-}
-
-static void dell_exit(void)
-{
- hid_unregister_driver(&dell_driver);
-}
-
-module_init(dell_init);
-module_exit(dell_exit);
-MODULE_LICENSE("GPL");
-
-HID_COMPAT_LOAD_DRIVER(dell);
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c
index e148f86fb58e..b4cc0f743d63 100644
--- a/drivers/hid/hid-dummy.c
+++ b/drivers/hid/hid-dummy.c
@@ -43,6 +43,9 @@ static int __init hid_dummy_init(void)
#ifdef CONFIG_HID_MONTEREY_MODULE
HID_COMPAT_CALL_DRIVER(monterey);
#endif
+#ifdef CONFIG_HID_NTRIG_MODULE
+ HID_COMPAT_CALL_DRIVER(ntrig);
+#endif
#ifdef CONFIG_HID_PANTHERLORD_MODULE
HID_COMPAT_CALL_DRIVER(pantherlord);
#endif
@@ -58,6 +61,9 @@ static int __init hid_dummy_init(void)
#ifdef CONFIG_HID_SUNPLUS_MODULE
HID_COMPAT_CALL_DRIVER(sunplus);
#endif
+#ifdef CONFIG_GREENASIA_FF_MODULE
+ HID_COMPAT_CALL_DRIVER(greenasia);
+#endif
#ifdef CONFIG_THRUSTMASTER_FF_MODULE
HID_COMPAT_CALL_DRIVER(thrustmaster);
#endif
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c
new file mode 100644
index 000000000000..71211f6a4f02
--- /dev/null
+++ b/drivers/hid/hid-gaff.c
@@ -0,0 +1,185 @@
+/*
+ * Force feedback support for GreenAsia (Product ID 0x12) based devices
+ *
+ * The devices are distributed under various names and the same USB device ID
+ * can be used in many game controllers.
+ *
+ *
+ * 0e8f:0012 "GreenAsia Inc. USB Joystick "
+ * - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635.
+ *
+ * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
+ */
+
+/*
+ * 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
+ */
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+
+struct gaff_device {
+ struct hid_report *report;
+};
+
+static int hid_gaff_play(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct hid_device *hid = input_get_drvdata(dev);
+ struct gaff_device *gaff = data;
+ int left, right;
+
+ left = effect->u.rumble.strong_magnitude;
+ right = effect->u.rumble.weak_magnitude;
+
+ dbg_hid("called with 0x%04x 0x%04x", left, right);
+
+ left = left * 0xfe / 0xffff;
+ right = right * 0xfe / 0xffff;
+
+ gaff->report->field[0]->value[0] = 0x51;
+ gaff->report->field[0]->value[1] = 0x0;
+ gaff->report->field[0]->value[2] = right;
+ gaff->report->field[0]->value[3] = 0;
+ gaff->report->field[0]->value[4] = left;
+ gaff->report->field[0]->value[5] = 0;
+ dbg_hid("running with 0x%02x 0x%02x", left, right);
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ gaff->report->field[0]->value[0] = 0xfa;
+ gaff->report->field[0]->value[1] = 0xfe;
+ gaff->report->field[0]->value[2] = 0x0;
+ gaff->report->field[0]->value[4] = 0x0;
+
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ return 0;
+}
+
+static int gaff_init(struct hid_device *hid)
+{
+ struct gaff_device *gaff;
+ struct hid_report *report;
+ struct hid_input *hidinput = list_entry(hid->inputs.next,
+ struct hid_input, list);
+ struct list_head *report_list =
+ &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+ struct list_head *report_ptr = report_list;
+ struct input_dev *dev = hidinput->input;
+ int error;
+
+ if (list_empty(report_list)) {
+ dev_err(&hid->dev, "no output reports found\n");
+ return -ENODEV;
+ }
+
+ report_ptr = report_ptr->next;
+
+ report = list_entry(report_ptr, struct hid_report, list);
+ if (report->maxfield < 1) {
+ dev_err(&hid->dev, "no fields in the report\n");
+ return -ENODEV;
+ }
+
+ if (report->field[0]->report_count < 6) {
+ dev_err(&hid->dev, "not enough values in the field\n");
+ return -ENODEV;
+ }
+
+ gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL);
+ if (!gaff)
+ return -ENOMEM;
+
+ set_bit(FF_RUMBLE, dev->ffbit);
+
+ error = input_ff_create_memless(dev, gaff, hid_gaff_play);
+ if (error) {
+ kfree(gaff);
+ return error;
+ }
+
+ gaff->report = report;
+ gaff->report->field[0]->value[0] = 0x51;
+ gaff->report->field[0]->value[1] = 0x00;
+ gaff->report->field[0]->value[2] = 0x00;
+ gaff->report->field[0]->value[3] = 0x00;
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ gaff->report->field[0]->value[0] = 0xfa;
+ gaff->report->field[0]->value[1] = 0xfe;
+
+ usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+
+ dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12"
+ " devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
+
+ return 0;
+}
+
+static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+
+ dev_dbg(&hdev->dev, "Greenasia HID hardware probe...");
+
+ ret = hid_parse(hdev);
+ if (ret) {
+ dev_err(&hdev->dev, "parse failed\n");
+ goto err;
+ }
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if (ret) {
+ dev_err(&hdev->dev, "hw start failed\n");
+ goto err;
+ }
+
+ gaff_init(hdev);
+
+ return 0;
+err:
+ return ret;
+}
+
+static const struct hid_device_id ga_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ga_devices);
+
+static struct hid_driver ga_driver = {
+ .name = "greenasia",
+ .id_table = ga_devices,
+ .probe = ga_probe,
+};
+
+static int __init ga_init(void)
+{
+ return hid_register_driver(&ga_driver);
+}
+
+static void __exit ga_exit(void)
+{
+ hid_unregister_driver(&ga_driver);
+}
+
+module_init(ga_init);
+module_exit(ga_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(greenasia);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 39289699c32f..e899f510ebeb 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -107,9 +107,6 @@
#define USB_VENDOR_ID_BELKIN 0x050d
#define USB_DEVICE_ID_FLIP_KVM 0x3201
-#define USB_VENDOR_ID_BRIGHT 0x1241
-#define USB_DEVICE_ID_BRIGHT_ABNT2 0x1503
-
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
@@ -141,9 +138,8 @@
#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
-#define USB_VENDOR_ID_DELL 0x413c
-#define USB_DEVICE_ID_DELL_W7658 0x2005
-#define USB_DEVICE_ID_DELL_SK8115 0x2105
+#define USB_VENDOR_ID_DEALEXTREAME 0x10c5
+#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a
#define USB_VENDOR_ID_DELORME 0x1163
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
@@ -167,9 +163,6 @@
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
-#define USB_VENDOR_ID_GENERIC_13BA 0x13ba
-#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017
-
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -292,7 +285,6 @@
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
-#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
@@ -339,6 +331,9 @@
#define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
+#define USB_VENDOR_ID_NTRIG 0x1b96
+#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
+
#define USB_VENDOR_ID_ONTRAK 0x0a07
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
@@ -367,6 +362,8 @@
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2 0x0036
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3 0x0034
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD4 0x0044
+#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5 0x0045
#define USB_VENDOR_ID_SUN 0x0430
#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
@@ -383,9 +380,15 @@
#define USB_VENDOR_ID_TOPMAX 0x0663
#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
+#define USB_VENDOR_ID_TOPSEED 0x0766
+#define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204
+
#define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
+#define USB_VENDOR_ID_UCLOGIC 0x5543
+#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042
+
#define USB_VENDOR_ID_VERNIER 0x08f7
#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index 2bae340eafe2..83e07c9f4144 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -26,7 +26,6 @@
#define LG_RDESC 0x001
#define LG_BAD_RELATIVE_KEYS 0x002
#define LG_DUPLICATE_USAGES 0x004
-#define LG_RESET_LEDS 0x008
#define LG_EXPANDED_KEYMAP 0x010
#define LG_IGNORE_DOUBLED_WHEEL 0x020
#define LG_WIRELESS 0x040
@@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_free;
}
- if (quirks & LG_RESET_LEDS)
- usbhid_set_leds(hdev);
-
if (quirks & LG_FF)
lgff_init(hdev);
if (quirks & LG_FF2)
@@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
.driver_data = LG_DUPLICATE_USAGES },
- { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
- .driver_data = LG_RESET_LEDS },
-
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index d718b1607d0f..25b10dcad90d 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -30,7 +30,7 @@
#define MS_NOGET 0x10
/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has several
+ * Microsoft Wireless Desktop Receiver (Model 1028) has
* 'Usage Min/Max' where it ought to have 'Physical Min/Max'
*/
static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
@@ -38,17 +38,12 @@ static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
- if ((quirks & MS_RDESC) && rsize == 571 && rdesc[284] == 0x19 &&
- rdesc[286] == 0x2a && rdesc[304] == 0x19 &&
- rdesc[306] == 0x29 && rdesc[352] == 0x1a &&
- rdesc[355] == 0x2a && rdesc[557] == 0x19 &&
+ if ((quirks & MS_RDESC) && rsize == 571 && rdesc[557] == 0x19 &&
rdesc[559] == 0x29) {
dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver "
"Model 1028 report descriptor\n");
- rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
- rdesc[352] = 0x36;
- rdesc[286] = rdesc[355] = 0x46;
- rdesc[306] = rdesc[559] = 0x45;
+ rdesc[557] = 0x35;
+ rdesc[559] = 0x45;
}
}
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
new file mode 100644
index 000000000000..db44fbd7bdf6
--- /dev/null
+++ b/drivers/hid/hid-ntrig.c
@@ -0,0 +1,82 @@
+/*
+ * HID driver for some ntrig "special" devices
+ *
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2007 Paul Walmsley
+ * Copyright (c) 2008 Jiri Slaby
+ * Copyright (c) 2008 Rafi Rubin
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define NTRIG_DUPLICATE_USAGES 0x001
+
+#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+
+static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
+ (usage->hid & 0xff) == 0x47) {
+ nt_map_key_clear(BTN_TOOL_DOUBLETAP);
+ return 1;
+ }
+ return 0;
+}
+
+static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (usage->type == EV_KEY || usage->type == EV_REL
+ || usage->type == EV_ABS)
+ clear_bit(usage->code, *bit);
+
+ return 0;
+}
+static const struct hid_device_id ntrig_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
+ .driver_data = NTRIG_DUPLICATE_USAGES },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ntrig_devices);
+
+static struct hid_driver ntrig_driver = {
+ .name = "ntrig",
+ .id_table = ntrig_devices,
+ .input_mapping = ntrig_input_mapping,
+ .input_mapped = ntrig_input_mapped,
+};
+
+static int ntrig_init(void)
+{
+ return hid_register_driver(&ntrig_driver);
+}
+
+static void ntrig_exit(void)
+{
+ hid_unregister_driver(&ntrig_driver);
+}
+
+module_init(ntrig_init);
+module_exit(ntrig_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(ntrig);
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 86e563b8d644..dd5a3979a4de 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
ret = sony_set_operational(hdev);
- if (ret)
+ if (ret < 0)
goto err_stop;
return 0;
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c
new file mode 100644
index 000000000000..cca64a0564a9
--- /dev/null
+++ b/drivers/hid/hid-topseed.c
@@ -0,0 +1,77 @@
+/*
+ * HID driver for TopSeed Cyberlink remote
+ *
+ * Copyright (c) 2008 Lev Babiev
+ * based on hid-cherry driver
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
+ EV_KEY, (c))
+static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x00d: ts_map_key_clear(KEY_HOME); break;
+ case 0x024: ts_map_key_clear(KEY_MENU); break;
+ case 0x025: ts_map_key_clear(KEY_TV); break;
+ case 0x048: ts_map_key_clear(KEY_RED); break;
+ case 0x047: ts_map_key_clear(KEY_GREEN); break;
+ case 0x049: ts_map_key_clear(KEY_YELLOW); break;
+ case 0x04a: ts_map_key_clear(KEY_BLUE); break;
+ case 0x04b: ts_map_key_clear(KEY_ANGLE); break;
+ case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break;
+ case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break;
+ case 0x031: ts_map_key_clear(KEY_AUDIO); break;
+ case 0x032: ts_map_key_clear(KEY_TEXT); break;
+ case 0x033: ts_map_key_clear(KEY_CHANNEL); break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static const struct hid_device_id ts_devices[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+ { }
+};
+MODULE_DEVICE_TABLE(hid, ts_devices);
+
+static struct hid_driver ts_driver = {
+ .name = "topseed",
+ .id_table = ts_devices,
+ .input_mapping = ts_input_mapping,
+};
+
+static int ts_init(void)
+{
+ return hid_register_driver(&ts_driver);
+}
+
+static void ts_exit(void)
+{
+ hid_unregister_driver(&ts_driver);
+}
+
+module_init(ts_init);
+module_exit(ts_exit);
+MODULE_LICENSE("GPL");
+
+HID_COMPAT_LOAD_DRIVER(topseed);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 7685ae6808c4..732449628971 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
list_del(&list->node);
dev = hidraw_table[minor];
- if (!dev->open--) {
+ if (!--dev->open) {
if (list->hidraw->exist)
dev->hid->ll_driver->close(dev->hid);
else
@@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
break;
}
default:
+ {
+ struct hid_device *hid = dev->hid;
+ if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
+ return -EINVAL;
+
+ if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
+ int len;
+ if (!hid->name)
+ return 0;
+ len = strlen(hid->name) + 1;
+ if (len > _IOC_SIZE(cmd))
+ len = _IOC_SIZE(cmd);
+ return copy_to_user(user_arg, hid->name, len) ?
+ -EFAULT : len;
+ }
+
+ if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
+ int len;
+ if (!hid->phys)
+ return 0;
+ len = strlen(hid->phys) + 1;
+ if (len > _IOC_SIZE(cmd))
+ len = _IOC_SIZE(cmd);
+ return copy_to_user(user_arg, hid->phys, len) ?
+ -EFAULT : len;
+ }
+ }
+
ret = -ENOTTY;
}
unlock_kernel();
@@ -329,7 +357,7 @@ int hidraw_connect(struct hid_device *hid)
goto out;
}
- dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
+ dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
NULL, "%s%d", "hidraw", minor);
if (IS_ERR(dev->dev)) {
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 5d9aa95fc3ef..4edb3bef94a6 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -45,7 +45,7 @@ config USB_HIDDEV
If unsure, say Y.
menu "USB HID Boot Protocol drivers"
- depends on USB!=n && USB_HID!=y
+ depends on USB!=n && USB_HID!=y && EMBEDDED
config USB_KBD
tristate "USB HIDBP Keyboard (simple Boot) support"
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 606369ea24ca..f0a0f72238ab 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -4,7 +4,7 @@
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- * Copyright (c) 2006-2007 Jiri Kosina
+ * Copyright (c) 2006-2008 Jiri Kosina
*/
/*
@@ -102,7 +102,7 @@ static void hid_reset(struct work_struct *work)
struct usbhid_device *usbhid =
container_of(work, struct usbhid_device, reset_work);
struct hid_device *hid = usbhid->hid;
- int rc_lock, rc = 0;
+ int rc = 0;
if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
dev_dbg(&usbhid->intf->dev, "clear halt\n");
@@ -113,11 +113,10 @@ static void hid_reset(struct work_struct *work)
else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
dev_dbg(&usbhid->intf->dev, "resetting device\n");
- rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
- if (rc_lock >= 0) {
+ rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
+ if (rc == 0) {
rc = usb_reset_device(hid_to_usb_dev(hid));
- if (rc_lock)
- usb_unlock_device(hid_to_usb_dev(hid));
+ usb_unlock_device(hid_to_usb_dev(hid));
}
clear_bit(HID_RESET_PENDING, &usbhid->iofl);
}
@@ -641,9 +640,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type,
unsigned int size;
list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
- size = ((report->size - 1) >> 3) + 1;
- if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
- size++;
+ size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered;
if (*max < size)
*max = size;
}
@@ -653,13 +650,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
- if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
- return -1;
- if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
- return -1;
- if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
- return -1;
- if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
+ usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ &usbhid->inbuf_dma);
+ usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ &usbhid->outbuf_dma);
+ usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
+ &usbhid->cr_dma);
+ usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
+ &usbhid->ctrlbuf_dma);
+ if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
+ !usbhid->ctrlbuf)
return -1;
return 0;
@@ -807,7 +807,7 @@ static int usbhid_start(struct hid_device *hid)
int interval;
endpoint = &interface->endpoint[n].desc;
- if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
+ if (!usb_endpoint_xfer_int(endpoint))
continue;
interval = endpoint->bInterval;
@@ -876,6 +876,15 @@ static int usbhid_start(struct hid_device *hid)
set_bit(HID_STARTED, &usbhid->iofl);
+ /* Some keyboards don't work until their LEDs have been set.
+ * Since BIOSes do set the LEDs, it must be safe for any device
+ * that supports the keyboard boot protocol.
+ */
+ if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
+ interface->desc.bInterfaceProtocol ==
+ USB_INTERFACE_PROTOCOL_KEYBOARD)
+ usbhid_set_leds(hid);
+
return 0;
fail:
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 47ebe045f9b5..4391717d2519 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -54,6 +54,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 83e851a5ed30..4940e4d70c2d 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -49,6 +49,7 @@
struct hiddev {
int exist;
int open;
+ struct mutex existancelock;
wait_queue_head_t wait;
struct hid_device *hid;
struct list_head list;
@@ -63,6 +64,7 @@ struct hiddev_list {
struct fasync_struct *fasync;
struct hiddev *hiddev;
struct list_head node;
+ struct mutex thread_lock;
};
static struct hiddev *hiddev_table[HIDDEV_MINORS];
@@ -264,29 +266,48 @@ static int hiddev_release(struct inode * inode, struct file * file)
static int hiddev_open(struct inode *inode, struct file *file)
{
struct hiddev_list *list;
- unsigned long flags;
+ int res;
int i = iminor(inode) - HIDDEV_MINOR_BASE;
- if (i >= HIDDEV_MINORS || !hiddev_table[i])
+ if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i])
return -ENODEV;
if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
return -ENOMEM;
+ mutex_init(&list->thread_lock);
list->hiddev = hiddev_table[i];
- spin_lock_irqsave(&list->hiddev->list_lock, flags);
- list_add_tail(&list->node, &hiddev_table[i]->list);
- spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
file->private_data = list;
- if (!list->hiddev->open++)
- if (list->hiddev->exist)
- usbhid_open(hiddev_table[i]->hid);
+ /*
+ * no need for locking because the USB major number
+ * is shared which usbcore guards against disconnect
+ */
+ if (list->hiddev->exist) {
+ if (!list->hiddev->open++) {
+ res = usbhid_open(hiddev_table[i]->hid);
+ if (res < 0) {
+ res = -EIO;
+ goto bail;
+ }
+ }
+ } else {
+ res = -ENODEV;
+ goto bail;
+ }
+
+ spin_lock_irq(&list->hiddev->list_lock);
+ list_add_tail(&list->node, &hiddev_table[i]->list);
+ spin_unlock_irq(&list->hiddev->list_lock);
return 0;
+bail:
+ file->private_data = NULL;
+ kfree(list->hiddev);
+ return res;
}
/*
@@ -305,7 +326,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data;
int event_size;
- int retval = 0;
+ int retval;
event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
@@ -313,10 +334,14 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
if (count < event_size)
return 0;
+ /* lock against other threads */
+ retval = mutex_lock_interruptible(&list->thread_lock);
+ if (retval)
+ return -ERESTARTSYS;
+
while (retval == 0) {
if (list->head == list->tail) {
- add_wait_queue(&list->hiddev->wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
+ prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) {
@@ -332,35 +357,45 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
break;
}
+ /* let O_NONBLOCK tasks run */
+ mutex_unlock(&list->thread_lock);
schedule();
+ if (mutex_lock_interruptible(&list->thread_lock))
+ return -EINTR;
set_current_state(TASK_INTERRUPTIBLE);
}
+ finish_wait(&list->hiddev->wait, &wait);
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&list->hiddev->wait, &wait);
}
- if (retval)
+ if (retval) {
+ mutex_unlock(&list->thread_lock);
return retval;
+ }
while (list->head != list->tail &&
retval + event_size <= count) {
if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
- if (list->buffer[list->tail].field_index !=
- HID_FIELD_INDEX_NONE) {
+ if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) {
struct hiddev_event event;
+
event.hid = list->buffer[list->tail].usage_code;
event.value = list->buffer[list->tail].value;
- if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
+ if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) {
+ mutex_unlock(&list->thread_lock);
return -EFAULT;
+ }
retval += sizeof(struct hiddev_event);
}
} else {
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
- if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
+
+ if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) {
+ mutex_unlock(&list->thread_lock);
return -EFAULT;
+ }
retval += sizeof(struct hiddev_usage_ref);
}
}
@@ -368,6 +403,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
}
}
+ mutex_unlock(&list->thread_lock);
return retval;
}
@@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct hid_field *field;
struct usbhid_device *usbhid = hid->driver_data;
void __user *user_arg = (void __user *)arg;
- int i;
+ int i, r;
/* Called without BKL by compat methods so no BKL taken */
@@ -619,10 +655,22 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
case HIDIOCGSTRING:
- return hiddev_ioctl_string(hiddev, cmd, user_arg);
+ mutex_lock(&hiddev->existancelock);
+ if (hiddev->exist)
+ r = hiddev_ioctl_string(hiddev, cmd, user_arg);
+ else
+ r = -ENODEV;
+ mutex_unlock(&hiddev->existancelock);
+ return r;
case HIDIOCINITREPORT:
+ mutex_lock(&hiddev->existancelock);
+ if (!hiddev->exist) {
+ mutex_unlock(&hiddev->existancelock);
+ return -ENODEV;
+ }
usbhid_init_reports(hid);
+ mutex_unlock(&hiddev->existancelock);
return 0;
@@ -636,8 +684,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- usbhid_submit_report(hid, report, USB_DIR_IN);
- usbhid_wait_io(hid);
+ mutex_lock(&hiddev->existancelock);
+ if (hiddev->exist) {
+ usbhid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_wait_io(hid);
+ }
+ mutex_unlock(&hiddev->existancelock);
return 0;
@@ -651,8 +703,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- usbhid_submit_report(hid, report, USB_DIR_OUT);
- usbhid_wait_io(hid);
+ mutex_lock(&hiddev->existancelock);
+ if (hiddev->exist) {
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_wait_io(hid);
+ }
+ mutex_unlock(&hiddev->existancelock);
return 0;
@@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case HIDIOCGUSAGES:
case HIDIOCSUSAGES:
case HIDIOCGCOLLECTIONINDEX:
- return hiddev_ioctl_usage(hiddev, cmd, user_arg);
+ mutex_lock(&hiddev->existancelock);
+ if (hiddev->exist)
+ r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
+ else
+ r = -ENODEV;
+ mutex_unlock(&hiddev->existancelock);
+ return r;
case HIDIOCGCOLLECTIONINFO:
if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
@@ -808,23 +870,24 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
return -1;
- retval = usb_register_dev(usbhid->intf, &hiddev_class);
- if (retval) {
- err_hid("Not able to get a minor for this device.");
- kfree(hiddev);
- return -1;
- }
-
init_waitqueue_head(&hiddev->wait);
INIT_LIST_HEAD(&hiddev->list);
spin_lock_init(&hiddev->list_lock);
+ mutex_init(&hiddev->existancelock);
+ hid->hiddev = hiddev;
hiddev->hid = hid;
hiddev->exist = 1;
- hid->minor = usbhid->intf->minor;
- hid->hiddev = hiddev;
-
- hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+ retval = usb_register_dev(usbhid->intf, &hiddev_class);
+ if (retval) {
+ err_hid("Not able to get a minor for this device.");
+ hid->hiddev = NULL;
+ kfree(hiddev);
+ return -1;
+ } else {
+ hid->minor = usbhid->intf->minor;
+ hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+ }
return 0;
}
@@ -839,7 +902,9 @@ void hiddev_disconnect(struct hid_device *hid)
struct hiddev *hiddev = hid->hiddev;
struct usbhid_device *usbhid = hid->driver_data;
+ mutex_lock(&hiddev->existancelock);
hiddev->exist = 0;
+ mutex_unlock(&hiddev->existancelock);
hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
usb_deregister_dev(usbhid->intf, &hiddev_class);
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 332abcdf9956..9eb30564be9c 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -40,6 +40,16 @@ int usbhid_open(struct hid_device *hid);
void usbhid_init_reports(struct hid_device *hid);
void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
+/* iofl flags */
+#define HID_CTRL_RUNNING 1
+#define HID_OUT_RUNNING 2
+#define HID_IN_RUNNING 3
+#define HID_RESET_PENDING 4
+#define HID_SUSPENDED 5
+#define HID_CLEAR_HALT 6
+#define HID_DISCONNECTED 7
+#define HID_STARTED 8
+
/*
* USB-specific HID struct, to be pointed to
* from struct hid_device->driver_data
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index c709e821f04b..b84bf066879b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -189,6 +189,16 @@ config SENSORS_ADT7473
This driver can also be built as a module. If so, the module
will be called adt7473.
+config SENSORS_ADT7475
+ tristate "Analog Devices ADT7475"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Analog Devices
+ ADT7475 hardware monitoring chips.
+
+ This driver can also be build as a module. If so, the module
+ will be called adt7475.
+
config SENSORS_K8TEMP
tristate "AMD Athlon64/FX or Opteron temperature sensor"
depends on X86 && PCI && EXPERIMENTAL
@@ -284,11 +294,12 @@ config SENSORS_F71805F
will be called f71805f.
config SENSORS_F71882FG
- tristate "Fintek F71882FG and F71883FG"
+ tristate "Fintek F71862FG, F71882FG and F8000"
depends on EXPERIMENTAL
help
If you say yes here you get support for hardware monitoring
- features of the Fintek F71882FG and F71883FG Super-I/O chips.
+ features of the Fintek F71882FG/F71883FG, F71862FG/71863FG
+ and F8000 Super-I/O chips.
This driver can also be built as a module. If so, the module
will be called f71882fg.
@@ -304,9 +315,13 @@ config SENSORS_F75375S
will be called f75375s.
config SENSORS_FSCHER
- tristate "FSC Hermes"
+ tristate "FSC Hermes (DEPRECATED)"
depends on X86 && I2C
help
+ This driver is DEPRECATED please use the new merged fschmd
+ ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver
+ instead.
+
If you say yes here you get support for Fujitsu Siemens
Computers Hermes sensor chips.
@@ -314,9 +329,13 @@ config SENSORS_FSCHER
will be called fscher.
config SENSORS_FSCPOS
- tristate "FSC Poseidon"
+ tristate "FSC Poseidon (DEPRECATED)"
depends on X86 && I2C
help
+ This driver is DEPRECATED please use the new merged fschmd
+ ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver
+ instead.
+
If you say yes here you get support for Fujitsu Siemens
Computers Poseidon sensor chips.
@@ -325,14 +344,15 @@ config SENSORS_FSCPOS
config SENSORS_FSCHMD
tristate "FSC Poseidon, Scylla, Hermes, Heimdall and Heracles"
- depends on X86 && I2C && EXPERIMENTAL
+ depends on X86 && I2C
help
If you say yes here you get support for various Fujitsu Siemens
- Computers sensor chips.
+ Computers sensor chips, including support for the integrated
+ watchdog.
- This is a new merged driver for FSC sensor chips which is intended
- as a replacment for the fscpos, fscscy and fscher drivers and adds
- support for several other FCS sensor chips.
+ This is a merged driver for FSC sensor chips replacing the fscpos,
+ fscscy and fscher drivers and adding support for several other FSC
+ sensor chips.
This driver can also be built as a module. If so, the module
will be called fschmd.
@@ -399,7 +419,8 @@ config SENSORS_IT87
select HWMON_VID
help
If you say yes here you get support for ITE IT8705F, IT8712F,
- IT8716F, IT8718F and IT8726F sensor chips, and the SiS960 clone.
+ IT8716F, IT8718F, IT8720F and IT8726F sensor chips, and the
+ SiS960 clone.
This driver can also be built as a module. If so, the module
will be called it87.
@@ -417,11 +438,12 @@ config SENSORS_LM63
will be called lm63.
config SENSORS_LM70
- tristate "National Semiconductor LM70"
+ tristate "National Semiconductor LM70 / Texas Instruments TMP121"
depends on SPI_MASTER && EXPERIMENTAL
help
If you say yes here you get support for the National Semiconductor
- LM70 digital temperature sensor chip.
+ LM70 and Texas Instruments TMP121/TMP123 digital temperature
+ sensor chips.
This driver can also be built as a module. If so, the module
will be called lm70.
@@ -548,6 +570,17 @@ config SENSORS_LM93
This driver can also be built as a module. If so, the module
will be called lm93.
+config SENSORS_LTC4245
+ tristate "Linear Technology LTC4245"
+ depends on I2C && EXPERIMENTAL
+ default n
+ help
+ If you say yes here you get support for Linear Technology LTC4245
+ Multiple Supply Hot Swap Controller I2C interface.
+
+ This driver can also be built as a module. If so, the module will
+ be called ltc4245.
+
config SENSORS_MAX1111
tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
depends on SPI_MASTER
@@ -838,6 +871,8 @@ config SENSORS_HDAPS
config SENSORS_LIS3LV02D
tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
depends on ACPI && INPUT
+ select NEW_LEDS
+ select LEDS_CLASS
default n
help
This driver provides support for the LIS3LV02Dx accelerometer. In
@@ -849,10 +884,16 @@ config SENSORS_LIS3LV02D
/sys/devices/platform/lis3lv02d.
This driver also provides an absolute input class device, allowing
- the laptop to act as a pinball machine-esque joystick.
+ the laptop to act as a pinball machine-esque joystick. On HP laptops,
+ if the led infrastructure is activated, support for a led indicating
+ disk protection will be provided as hp:red:hddprotection.
- This driver can also be built as a module. If so, the module
- will be called lis3lv02d.
+ This driver can also be built as modules. If so, the core module
+ will be called lis3lv02d and a specific module for HP laptops will be
+ called hp_accel.
+
+ Say Y here if you have an applicable laptop and want to experience
+ the awesome power of lis3lv02d.
config SENSORS_APPLESMC
tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 58fc5be5355d..2e80f37f39eb 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -28,6 +28,8 @@ obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o
obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o
obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o
+obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
+
obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
obj-$(CONFIG_SENSORS_AMS) += ams/
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
@@ -49,7 +51,7 @@ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
obj-$(CONFIG_SENSORS_IT87) += it87.o
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
-obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o
+obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
obj-$(CONFIG_SENSORS_LM63) += lm63.o
obj-$(CONFIG_SENSORS_LM70) += lm70.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o
@@ -62,6 +64,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_LM93) += lm93.o
+obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o
obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 70bb854086df..e52b38806d03 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -279,7 +279,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "OTES1 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0011, "AT8 32X(ATI RD580-ULI M1575)", {
+ { 0x0011, "AT8 32X", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR", 1, 0, 20, 1, 0 },
{ "DDR VTT", 2, 0, 10, 1, 0 },
@@ -402,7 +402,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0016, "AW9D-MAX (Intel i975-ICH7)", {
+ { 0x0016, "AW9D-MAX", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -482,7 +482,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 Fan", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x0019, NULL /* Unknown, need DMI string */, {
+ { 0x0019, "IN9 32X MAX", {
{ "CPU Core", 7, 0, 10, 1, 0 },
{ "DDR2", 13, 0, 20, 1, 0 },
{ "DDR2 VTT", 14, 0, 10, 1, 0 },
@@ -509,7 +509,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
{ "AUX3 FAN", 36, 2, 60, 1, 0 },
{ NULL, 0, 0, 0, 0, 0 } }
},
- { 0x001A, "IP35 Pro(Intel P35-ICH9R)", {
+ { 0x001A, "IP35 Pro", {
{ "CPU Core", 0, 0, 10, 1, 0 },
{ "DDR2", 1, 0, 20, 1, 0 },
{ "DDR2 VTT", 2, 0, 10, 1, 0 },
@@ -1128,6 +1128,7 @@ static int __init abituguru3_dmi_detect(void)
{
const char *board_vendor, *board_name;
int i, err = (force) ? 1 : -ENODEV;
+ size_t sublen;
board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/"))
@@ -1137,9 +1138,20 @@ static int __init abituguru3_dmi_detect(void)
if (!board_name)
return err;
+ /* At the moment, we don't care about the part of the vendor
+ * DMI string contained in brackets. Truncate the string at
+ * the first occurrence of a bracket. Trim any trailing space
+ * from the substring.
+ */
+ sublen = strcspn(board_name, "(");
+ while (sublen > 0 && board_name[sublen - 1] == ' ')
+ sublen--;
+
for (i = 0; abituguru3_motherboards[i].id; i++) {
const char *dmi_name = abituguru3_motherboards[i].dmi_name;
- if (dmi_name && !strcmp(dmi_name, board_name))
+ if (!dmi_name || strlen(dmi_name) != sublen)
+ continue;
+ if (!strncasecmp(board_name, dmi_name, sublen))
break;
}
@@ -1153,7 +1165,7 @@ static int __init abituguru3_dmi_detect(void)
static inline int abituguru3_dmi_detect(void)
{
- return -ENODEV;
+ return 1;
}
#endif /* CONFIG_DMI */
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index 66107b4dc12a..1852f27bac51 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -204,8 +204,6 @@ I2C_CLIENT_INSMOD_1(adt7462);
#define MASK_AND_SHIFT(value, prefix) \
(((value) & prefix##_MASK) >> prefix##_SHIFT)
-#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor))
-
struct adt7462_data {
struct device *hwmon_dev;
struct attribute_group attrs;
@@ -840,7 +838,7 @@ static ssize_t set_temp_min(struct device *dev,
if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000) + 64;
+ temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
@@ -878,7 +876,7 @@ static ssize_t set_temp_max(struct device *dev,
if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000) + 64;
+ temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
@@ -943,7 +941,7 @@ static ssize_t set_volt_max(struct device *dev,
return -EINVAL;
temp *= 1000; /* convert mV to uV */
- temp = ROUND_DIV(temp, x);
+ temp = DIV_ROUND_CLOSEST(temp, x);
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
@@ -985,7 +983,7 @@ static ssize_t set_volt_min(struct device *dev,
return -EINVAL;
temp *= 1000; /* convert mV to uV */
- temp = ROUND_DIV(temp, x);
+ temp = DIV_ROUND_CLOSEST(temp, x);
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
@@ -1250,7 +1248,7 @@ static ssize_t set_pwm_hyst(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = SENSORS_LIMIT(temp, 0, 15);
/* package things up */
@@ -1337,7 +1335,7 @@ static ssize_t set_pwm_tmin(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000) + 64;
+ temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 1311a595147e..633e1a1e9d79 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -28,6 +28,7 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/log2.h>
+#include <linux/kthread.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };
@@ -74,6 +75,7 @@ I2C_CLIENT_INSMOD_1(adt7470);
#define ADT7470_REG_PWM12_CFG 0x68
#define ADT7470_PWM2_AUTO_MASK 0x40
#define ADT7470_PWM1_AUTO_MASK 0x80
+#define ADT7470_PWM_AUTO_MASK 0xC0
#define ADT7470_REG_PWM34_CFG 0x69
#define ADT7470_PWM3_AUTO_MASK 0x40
#define ADT7470_PWM4_AUTO_MASK 0x80
@@ -128,8 +130,11 @@ I2C_CLIENT_INSMOD_1(adt7470);
/* How often do we reread sensor limit values? (In jiffies) */
#define LIMIT_REFRESH_INTERVAL (60 * HZ)
-/* sleep 1s while gathering temperature data */
-#define TEMP_COLLECTION_TIME 1000
+/* Wait at least 200ms per sensor for 10 sensors */
+#define TEMP_COLLECTION_TIME 2000
+
+/* auto update thing won't fire more than every 2s */
+#define AUTO_UPDATE_INTERVAL 2000
/* datasheet says to divide this number by the fan reading to get fan rpm */
#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x))
@@ -137,8 +142,6 @@ I2C_CLIENT_INSMOD_1(adt7470);
#define FAN_PERIOD_INVALID 65535
#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
-#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor))
-
struct adt7470_data {
struct device *hwmon_dev;
struct attribute_group attrs;
@@ -148,6 +151,9 @@ struct adt7470_data {
unsigned long sensors_last_updated; /* In jiffies */
unsigned long limits_last_updated; /* In jiffies */
+ int num_temp_sensors; /* -1 = probe */
+ int temperatures_probed;
+
s8 temp[ADT7470_TEMP_COUNT];
s8 temp_min[ADT7470_TEMP_COUNT];
s8 temp_max[ADT7470_TEMP_COUNT];
@@ -163,6 +169,10 @@ struct adt7470_data {
u8 pwm_min[ADT7470_PWM_COUNT];
s8 pwm_tmin[ADT7470_PWM_COUNT];
u8 pwm_auto_temp[ADT7470_PWM_COUNT];
+
+ struct task_struct *auto_update;
+ struct completion auto_update_stop;
+ unsigned int auto_update_interval;
};
static int adt7470_probe(struct i2c_client *client,
@@ -220,40 +230,126 @@ static void adt7470_init_client(struct i2c_client *client)
}
}
-static struct adt7470_data *adt7470_update_device(struct device *dev)
+/* Probe for temperature sensors. Assumes lock is held */
+static int adt7470_read_temperatures(struct i2c_client *client,
+ struct adt7470_data *data)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7470_data *data = i2c_get_clientdata(client);
- unsigned long local_jiffies = jiffies;
- u8 cfg;
+ unsigned long res;
int i;
+ u8 cfg, pwm[4], pwm_cfg[2];
- mutex_lock(&data->lock);
- if (time_before(local_jiffies, data->sensors_last_updated +
- SENSOR_REFRESH_INTERVAL)
- && data->sensors_valid)
- goto no_sensor_update;
+ /* save pwm[1-4] config register */
+ pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0));
+ pwm_cfg[1] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(2));
+
+ /* set manual pwm to whatever it is set to now */
+ for (i = 0; i < ADT7470_FAN_COUNT; i++)
+ pwm[i] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM(i));
+
+ /* put pwm in manual mode */
+ i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0),
+ pwm_cfg[0] & ~(ADT7470_PWM_AUTO_MASK));
+ i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2),
+ pwm_cfg[1] & ~(ADT7470_PWM_AUTO_MASK));
+
+ /* write pwm control to whatever it was */
+ for (i = 0; i < ADT7470_FAN_COUNT; i++)
+ i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(i), pwm[i]);
/* start reading temperature sensors */
cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
cfg |= 0x80;
i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);
- /*
- * Delay is 200ms * number of tmp05 sensors. Too bad
- * there's no way to figure out how many are connected.
- * For now, assume 1s will work.
- */
- msleep(TEMP_COLLECTION_TIME);
+ /* Delay is 200ms * number of temp sensors. */
+ res = msleep_interruptible((data->num_temp_sensors >= 0 ?
+ data->num_temp_sensors * 200 :
+ TEMP_COLLECTION_TIME));
/* done reading temperature sensors */
cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG);
cfg &= ~0x80;
i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg);
- for (i = 0; i < ADT7470_TEMP_COUNT; i++)
+ /* restore pwm[1-4] config registers */
+ i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]);
+ i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]);
+
+ if (res) {
+ printk(KERN_ERR "ha ha, interrupted");
+ return -EAGAIN;
+ }
+
+ /* Only count fans if we have to */
+ if (data->num_temp_sensors >= 0)
+ return 0;
+
+ for (i = 0; i < ADT7470_TEMP_COUNT; i++) {
data->temp[i] = i2c_smbus_read_byte_data(client,
ADT7470_TEMP_REG(i));
+ if (data->temp[i])
+ data->num_temp_sensors = i + 1;
+ }
+ data->temperatures_probed = 1;
+ return 0;
+}
+
+static int adt7470_update_thread(void *p)
+{
+ struct i2c_client *client = p;
+ struct adt7470_data *data = i2c_get_clientdata(client);
+
+ while (!kthread_should_stop()) {
+ mutex_lock(&data->lock);
+ adt7470_read_temperatures(client, data);
+ mutex_unlock(&data->lock);
+ if (kthread_should_stop())
+ break;
+ msleep_interruptible(data->auto_update_interval);
+ }
+
+ complete_all(&data->auto_update_stop);
+ return 0;
+}
+
+static struct adt7470_data *adt7470_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7470_data *data = i2c_get_clientdata(client);
+ unsigned long local_jiffies = jiffies;
+ u8 cfg;
+ int i;
+ int need_sensors = 1;
+ int need_limits = 1;
+
+ /*
+ * Figure out if we need to update the shadow registers.
+ * Lockless means that we may occasionally report out of
+ * date data.
+ */
+ if (time_before(local_jiffies, data->sensors_last_updated +
+ SENSOR_REFRESH_INTERVAL) &&
+ data->sensors_valid)
+ need_sensors = 0;
+
+ if (time_before(local_jiffies, data->limits_last_updated +
+ LIMIT_REFRESH_INTERVAL) &&
+ data->limits_valid)
+ need_limits = 0;
+
+ if (!need_sensors && !need_limits)
+ return data;
+
+ mutex_lock(&data->lock);
+ if (!need_sensors)
+ goto no_sensor_update;
+
+ if (!data->temperatures_probed)
+ adt7470_read_temperatures(client, data);
+ else
+ for (i = 0; i < ADT7470_TEMP_COUNT; i++)
+ data->temp[i] = i2c_smbus_read_byte_data(client,
+ ADT7470_TEMP_REG(i));
for (i = 0; i < ADT7470_FAN_COUNT; i++)
data->fan[i] = adt7470_read_word_data(client,
@@ -302,9 +398,7 @@ static struct adt7470_data *adt7470_update_device(struct device *dev)
data->sensors_valid = 1;
no_sensor_update:
- if (time_before(local_jiffies, data->limits_last_updated +
- LIMIT_REFRESH_INTERVAL)
- && data->limits_valid)
+ if (!need_limits)
goto out;
for (i = 0; i < ADT7470_TEMP_COUNT; i++) {
@@ -338,6 +432,66 @@ out:
return data;
}
+static ssize_t show_auto_update_interval(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct adt7470_data *data = adt7470_update_device(dev);
+ return sprintf(buf, "%d\n", data->auto_update_interval);
+}
+
+static ssize_t set_auto_update_interval(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7470_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, 0, 60000);
+
+ mutex_lock(&data->lock);
+ data->auto_update_interval = temp;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_num_temp_sensors(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ struct adt7470_data *data = adt7470_update_device(dev);
+ return sprintf(buf, "%d\n", data->num_temp_sensors);
+}
+
+static ssize_t set_num_temp_sensors(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7470_data *data = i2c_get_clientdata(client);
+ long temp;
+
+ if (strict_strtol(buf, 10, &temp))
+ return -EINVAL;
+
+ temp = SENSORS_LIMIT(temp, -1, 10);
+
+ mutex_lock(&data->lock);
+ data->num_temp_sensors = temp;
+ if (temp < 0)
+ data->temperatures_probed = 0;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
static ssize_t show_temp_min(struct device *dev,
struct device_attribute *devattr,
char *buf)
@@ -360,7 +514,7 @@ static ssize_t set_temp_min(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
@@ -394,7 +548,7 @@ static ssize_t set_temp_max(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
@@ -671,7 +825,7 @@ static ssize_t set_pwm_tmin(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = SENSORS_LIMIT(temp, 0, 255);
mutex_lock(&data->lock);
@@ -804,6 +958,10 @@ static ssize_t show_alarm(struct device *dev,
}
static DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarm_mask, NULL);
+static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors,
+ set_num_temp_sensors);
+static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO,
+ show_auto_update_interval, set_auto_update_interval);
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
set_temp_max, 0);
@@ -976,6 +1134,8 @@ static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
static struct attribute *adt7470_attr[] =
{
&dev_attr_alarm_mask.attr,
+ &dev_attr_num_temp_sensors.attr,
+ &dev_attr_auto_update_interval.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr,
@@ -1108,6 +1268,9 @@ static int adt7470_probe(struct i2c_client *client,
goto exit;
}
+ data->num_temp_sensors = -1;
+ data->auto_update_interval = AUTO_UPDATE_INTERVAL;
+
i2c_set_clientdata(client, data);
mutex_init(&data->lock);
@@ -1127,8 +1290,16 @@ static int adt7470_probe(struct i2c_client *client,
goto exit_remove;
}
+ init_completion(&data->auto_update_stop);
+ data->auto_update = kthread_run(adt7470_update_thread, client,
+ dev_name(data->hwmon_dev));
+ if (IS_ERR(data->auto_update))
+ goto exit_unregister;
+
return 0;
+exit_unregister:
+ hwmon_device_unregister(data->hwmon_dev);
exit_remove:
sysfs_remove_group(&client->dev.kobj, &data->attrs);
exit_free:
@@ -1141,6 +1312,8 @@ static int adt7470_remove(struct i2c_client *client)
{
struct adt7470_data *data = i2c_get_clientdata(client);
+ kthread_stop(data->auto_update);
+ wait_for_completion(&data->auto_update_stop);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &data->attrs);
kfree(data);
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c
index 18aa30866a6c..0a6ce2367b42 100644
--- a/drivers/hwmon/adt7473.c
+++ b/drivers/hwmon/adt7473.c
@@ -129,8 +129,6 @@ I2C_CLIENT_INSMOD_1(adt7473);
#define FAN_PERIOD_INVALID 65535
#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
-#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor))
-
struct adt7473_data {
struct device *hwmon_dev;
struct attribute_group attrs;
@@ -459,7 +457,7 @@ static ssize_t set_temp_min(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
@@ -495,7 +493,7 @@ static ssize_t set_temp_max(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
@@ -720,7 +718,7 @@ static ssize_t set_temp_tmax(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
@@ -756,7 +754,7 @@ static ssize_t set_temp_tmin(struct device *dev,
if (strict_strtol(buf, 10, &temp))
return -EINVAL;
- temp = ROUND_DIV(temp, 1000);
+ temp = DIV_ROUND_CLOSEST(temp, 1000);
temp = encode_temp(data->temp_twos_complement, temp);
mutex_lock(&data->lock);
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
new file mode 100644
index 000000000000..d39877a7da63
--- /dev/null
+++ b/drivers/hwmon/adt7475.c
@@ -0,0 +1,1221 @@
+/*
+ * adt7475 - Thermal sensor driver for the ADT7475 chip and derivatives
+ * Copyright (C) 2007-2008, Advanced Micro Devices, Inc.
+ * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
+ * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
+
+ * Derived from the lm83 driver by Jean Delvare
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+
+/* Indexes for the sysfs hooks */
+
+#define INPUT 0
+#define MIN 1
+#define MAX 2
+#define CONTROL 3
+#define OFFSET 3
+#define AUTOMIN 4
+#define THERM 5
+#define HYSTERSIS 6
+
+/* These are unique identifiers for the sysfs functions - unlike the
+ numbers above, these are not also indexes into an array
+*/
+
+#define ALARM 9
+#define FAULT 10
+
+/* 7475 Common Registers */
+
+#define REG_VOLTAGE_BASE 0x21
+#define REG_TEMP_BASE 0x25
+#define REG_TACH_BASE 0x28
+#define REG_PWM_BASE 0x30
+#define REG_PWM_MAX_BASE 0x38
+
+#define REG_DEVID 0x3D
+#define REG_VENDID 0x3E
+
+#define REG_STATUS1 0x41
+#define REG_STATUS2 0x42
+
+#define REG_VOLTAGE_MIN_BASE 0x46
+#define REG_VOLTAGE_MAX_BASE 0x47
+
+#define REG_TEMP_MIN_BASE 0x4E
+#define REG_TEMP_MAX_BASE 0x4F
+
+#define REG_TACH_MIN_BASE 0x54
+
+#define REG_PWM_CONFIG_BASE 0x5C
+
+#define REG_TEMP_TRANGE_BASE 0x5F
+
+#define REG_PWM_MIN_BASE 0x64
+
+#define REG_TEMP_TMIN_BASE 0x67
+#define REG_TEMP_THERM_BASE 0x6A
+
+#define REG_REMOTE1_HYSTERSIS 0x6D
+#define REG_REMOTE2_HYSTERSIS 0x6E
+
+#define REG_TEMP_OFFSET_BASE 0x70
+
+#define REG_EXTEND1 0x76
+#define REG_EXTEND2 0x77
+#define REG_CONFIG5 0x7C
+
+#define CONFIG5_TWOSCOMP 0x01
+#define CONFIG5_TEMPOFFSET 0x02
+
+/* ADT7475 Settings */
+
+#define ADT7475_VOLTAGE_COUNT 2
+#define ADT7475_TEMP_COUNT 3
+#define ADT7475_TACH_COUNT 4
+#define ADT7475_PWM_COUNT 3
+
+/* Macro to read the registers */
+
+#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg))
+
+/* Macros to easily index the registers */
+
+#define TACH_REG(idx) (REG_TACH_BASE + ((idx) * 2))
+#define TACH_MIN_REG(idx) (REG_TACH_MIN_BASE + ((idx) * 2))
+
+#define PWM_REG(idx) (REG_PWM_BASE + (idx))
+#define PWM_MAX_REG(idx) (REG_PWM_MAX_BASE + (idx))
+#define PWM_MIN_REG(idx) (REG_PWM_MIN_BASE + (idx))
+#define PWM_CONFIG_REG(idx) (REG_PWM_CONFIG_BASE + (idx))
+
+#define VOLTAGE_REG(idx) (REG_VOLTAGE_BASE + (idx))
+#define VOLTAGE_MIN_REG(idx) (REG_VOLTAGE_MIN_BASE + ((idx) * 2))
+#define VOLTAGE_MAX_REG(idx) (REG_VOLTAGE_MAX_BASE + ((idx) * 2))
+
+#define TEMP_REG(idx) (REG_TEMP_BASE + (idx))
+#define TEMP_MIN_REG(idx) (REG_TEMP_MIN_BASE + ((idx) * 2))
+#define TEMP_MAX_REG(idx) (REG_TEMP_MAX_BASE + ((idx) * 2))
+#define TEMP_TMIN_REG(idx) (REG_TEMP_TMIN_BASE + (idx))
+#define TEMP_THERM_REG(idx) (REG_TEMP_THERM_BASE + (idx))
+#define TEMP_OFFSET_REG(idx) (REG_TEMP_OFFSET_BASE + (idx))
+#define TEMP_TRANGE_REG(idx) (REG_TEMP_TRANGE_BASE + (idx))
+
+static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD_1(adt7475);
+
+static const struct i2c_device_id adt7475_id[] = {
+ { "adt7475", adt7475 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adt7475_id);
+
+struct adt7475_data {
+ struct device *hwmon_dev;
+ struct mutex lock;
+
+ unsigned long measure_updated;
+ unsigned long limits_updated;
+ char valid;
+
+ u8 config5;
+ u16 alarms;
+ u16 voltage[3][3];
+ u16 temp[7][3];
+ u16 tach[2][4];
+ u8 pwm[4][3];
+ u8 range[3];
+ u8 pwmctl[3];
+ u8 pwmchan[3];
+};
+
+static struct i2c_driver adt7475_driver;
+static struct adt7475_data *adt7475_update_device(struct device *dev);
+static void adt7475_read_hystersis(struct i2c_client *client);
+static void adt7475_read_pwm(struct i2c_client *client, int index);
+
+/* Given a temp value, convert it to register value */
+
+static inline u16 temp2reg(struct adt7475_data *data, long val)
+{
+ u16 ret;
+
+ if (!(data->config5 & CONFIG5_TWOSCOMP)) {
+ val = SENSORS_LIMIT(val, -64000, 191000);
+ ret = (val + 64500) / 1000;
+ } else {
+ val = SENSORS_LIMIT(val, -128000, 127000);
+ if (val < -500)
+ ret = (256500 + val) / 1000;
+ else
+ ret = (val + 500) / 1000;
+ }
+
+ return ret << 2;
+}
+
+/* Given a register value, convert it to a real temp value */
+
+static inline int reg2temp(struct adt7475_data *data, u16 reg)
+{
+ if (data->config5 & CONFIG5_TWOSCOMP) {
+ if (reg >= 512)
+ return (reg - 1024) * 250;
+ else
+ return reg * 250;
+ } else
+ return (reg - 256) * 250;
+}
+
+static inline int tach2rpm(u16 tach)
+{
+ if (tach == 0 || tach == 0xFFFF)
+ return 0;
+
+ return (90000 * 60) / tach;
+}
+
+static inline u16 rpm2tach(unsigned long rpm)
+{
+ if (rpm == 0)
+ return 0;
+
+ return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF);
+}
+
+static inline int reg2vcc(u16 reg)
+{
+ return (4296 * reg) / 1000;
+}
+
+static inline int reg2vccp(u16 reg)
+{
+ return (2929 * reg) / 1000;
+}
+
+static inline u16 vcc2reg(long vcc)
+{
+ vcc = SENSORS_LIMIT(vcc, 0, 4396);
+ return (vcc * 1000) / 4296;
+}
+
+static inline u16 vccp2reg(long vcc)
+{
+ vcc = SENSORS_LIMIT(vcc, 0, 2998);
+ return (vcc * 1000) / 2929;
+}
+
+static u16 adt7475_read_word(struct i2c_client *client, int reg)
+{
+ u16 val;
+
+ val = i2c_smbus_read_byte_data(client, reg);
+ val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8);
+
+ return val;
+}
+
+static void adt7475_write_word(struct i2c_client *client, int reg, u16 val)
+{
+ i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
+ i2c_smbus_write_byte_data(client, reg, val & 0xFF);
+}
+
+/* Find the nearest value in a table - used for pwm frequency and
+ auto temp range */
+static int find_nearest(long val, const int *array, int size)
+{
+ int i;
+
+ if (val < array[0])
+ return 0;
+
+ if (val > array[size - 1])
+ return size - 1;
+
+ for (i = 0; i < size - 1; i++) {
+ int a, b;
+
+ if (val > array[i + 1])
+ continue;
+
+ a = val - array[i];
+ b = array[i + 1] - val;
+
+ return (a <= b) ? i : i + 1;
+ }
+
+ return 0;
+}
+
+static ssize_t show_voltage(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ unsigned short val;
+
+ switch (sattr->nr) {
+ case ALARM:
+ return sprintf(buf, "%d\n",
+ (data->alarms >> (sattr->index + 1)) & 1);
+ default:
+ val = data->voltage[sattr->nr][sattr->index];
+ return sprintf(buf, "%d\n",
+ sattr->index ==
+ 0 ? reg2vccp(val) : reg2vcc(val));
+ }
+}
+
+static ssize_t set_voltage(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned char reg;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ data->voltage[sattr->nr][sattr->index] =
+ sattr->index ? vcc2reg(val) : vccp2reg(val);
+
+ if (sattr->nr == MIN)
+ reg = VOLTAGE_MIN_REG(sattr->index);
+ else
+ reg = VOLTAGE_MAX_REG(sattr->index);
+
+ i2c_smbus_write_byte_data(client, reg,
+ data->voltage[sattr->nr][sattr->index] >> 2);
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int out;
+
+ switch (sattr->nr) {
+ case HYSTERSIS:
+ mutex_lock(&data->lock);
+ out = data->temp[sattr->nr][sattr->index];
+ if (sattr->index != 1)
+ out = (out >> 4) & 0xF;
+ else
+ out = (out & 0xF);
+ /* Show the value as an absolute number tied to
+ * THERM */
+ out = reg2temp(data, data->temp[THERM][sattr->index]) -
+ out * 1000;
+ mutex_unlock(&data->lock);
+ break;
+
+ case OFFSET:
+ /* Offset is always 2's complement, regardless of the
+ * setting in CONFIG5 */
+ mutex_lock(&data->lock);
+ out = (s8)data->temp[sattr->nr][sattr->index];
+ if (data->config5 & CONFIG5_TEMPOFFSET)
+ out *= 1000;
+ else
+ out *= 500;
+ mutex_unlock(&data->lock);
+ break;
+
+ case ALARM:
+ out = (data->alarms >> (sattr->index + 4)) & 1;
+ break;
+
+ case FAULT:
+ /* Note - only for remote1 and remote2 */
+ out = data->alarms & (sattr->index ? 0x8000 : 0x4000);
+ out = out ? 0 : 1;
+ break;
+
+ default:
+ /* All other temp values are in the configured format */
+ out = reg2temp(data, data->temp[sattr->nr][sattr->index]);
+ }
+
+ return sprintf(buf, "%d\n", out);
+}
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned char reg = 0;
+ u8 out;
+ int temp;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ /* We need the config register in all cases for temp <-> reg conv. */
+ data->config5 = adt7475_read(REG_CONFIG5);
+
+ switch (sattr->nr) {
+ case OFFSET:
+ if (data->config5 & CONFIG5_TEMPOFFSET) {
+ val = SENSORS_LIMIT(val, -63000, 127000);
+ out = data->temp[OFFSET][sattr->index] = val / 1000;
+ } else {
+ val = SENSORS_LIMIT(val, -63000, 64000);
+ out = data->temp[OFFSET][sattr->index] = val / 500;
+ }
+ break;
+
+ case HYSTERSIS:
+ /* The value will be given as an absolute value, turn it
+ into an offset based on THERM */
+
+ /* Read fresh THERM and HYSTERSIS values from the chip */
+ data->temp[THERM][sattr->index] =
+ adt7475_read(TEMP_THERM_REG(sattr->index)) << 2;
+ adt7475_read_hystersis(client);
+
+ temp = reg2temp(data, data->temp[THERM][sattr->index]);
+ val = SENSORS_LIMIT(val, temp - 15000, temp);
+ val = (temp - val) / 1000;
+
+ if (sattr->index != 1) {
+ data->temp[HYSTERSIS][sattr->index] &= 0xF0;
+ data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4;
+ } else {
+ data->temp[HYSTERSIS][sattr->index] &= 0x0F;
+ data->temp[HYSTERSIS][sattr->index] |= (val & 0xF);
+ }
+
+ out = data->temp[HYSTERSIS][sattr->index];
+ break;
+
+ default:
+ data->temp[sattr->nr][sattr->index] = temp2reg(data, val);
+
+ /* We maintain an extra 2 digits of precision for simplicity
+ * - shift those back off before writing the value */
+ out = (u8) (data->temp[sattr->nr][sattr->index] >> 2);
+ }
+
+ switch (sattr->nr) {
+ case MIN:
+ reg = TEMP_MIN_REG(sattr->index);
+ break;
+ case MAX:
+ reg = TEMP_MAX_REG(sattr->index);
+ break;
+ case OFFSET:
+ reg = TEMP_OFFSET_REG(sattr->index);
+ break;
+ case AUTOMIN:
+ reg = TEMP_TMIN_REG(sattr->index);
+ break;
+ case THERM:
+ reg = TEMP_THERM_REG(sattr->index);
+ break;
+ case HYSTERSIS:
+ if (sattr->index != 2)
+ reg = REG_REMOTE1_HYSTERSIS;
+ else
+ reg = REG_REMOTE2_HYSTERSIS;
+
+ break;
+ }
+
+ i2c_smbus_write_byte_data(client, reg, out);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+/* Table of autorange values - the user will write the value in millidegrees,
+ and we'll convert it */
+static const int autorange_table[] = {
+ 2000, 2500, 3330, 4000, 5000, 6670, 8000,
+ 10000, 13330, 16000, 20000, 26670, 32000, 40000,
+ 53330, 80000
+};
+
+static ssize_t show_point2(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int out, val;
+
+ mutex_lock(&data->lock);
+ out = (data->range[sattr->index] >> 4) & 0x0F;
+ val = reg2temp(data, data->temp[AUTOMIN][sattr->index]);
+ mutex_unlock(&data->lock);
+
+ return sprintf(buf, "%d\n", val + autorange_table[out]);
+}
+
+static ssize_t set_point2(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int temp;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ /* Get a fresh copy of the needed registers */
+ data->config5 = adt7475_read(REG_CONFIG5);
+ data->temp[AUTOMIN][sattr->index] =
+ adt7475_read(TEMP_TMIN_REG(sattr->index)) << 2;
+ data->range[sattr->index] =
+ adt7475_read(TEMP_TRANGE_REG(sattr->index));
+
+ /* The user will write an absolute value, so subtract the start point
+ to figure the range */
+ temp = reg2temp(data, data->temp[AUTOMIN][sattr->index]);
+ val = SENSORS_LIMIT(val, temp + autorange_table[0],
+ temp + autorange_table[ARRAY_SIZE(autorange_table) - 1]);
+ val -= temp;
+
+ /* Find the nearest table entry to what the user wrote */
+ val = find_nearest(val, autorange_table, ARRAY_SIZE(autorange_table));
+
+ data->range[sattr->index] &= ~0xF0;
+ data->range[sattr->index] |= val << 4;
+
+ i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index),
+ data->range[sattr->index]);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+static ssize_t show_tach(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ int out;
+
+ if (sattr->nr == ALARM)
+ out = (data->alarms >> (sattr->index + 10)) & 1;
+ else
+ out = tach2rpm(data->tach[sattr->nr][sattr->index]);
+
+ return sprintf(buf, "%d\n", out);
+}
+
+static ssize_t set_tach(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ data->tach[MIN][sattr->index] = rpm2tach(val);
+
+ adt7475_write_word(client, TACH_MIN_REG(sattr->index),
+ data->tach[MIN][sattr->index]);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n", data->pwm[sattr->nr][sattr->index]);
+}
+
+static ssize_t show_pwmchan(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n", data->pwmchan[sattr->index]);
+}
+
+static ssize_t show_pwmctrl(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n", data->pwmctl[sattr->index]);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned char reg = 0;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+
+ switch (sattr->nr) {
+ case INPUT:
+ /* Get a fresh value for CONTROL */
+ data->pwm[CONTROL][sattr->index] =
+ adt7475_read(PWM_CONFIG_REG(sattr->index));
+
+ /* If we are not in manual mode, then we shouldn't allow
+ * the user to set the pwm speed */
+ if (((data->pwm[CONTROL][sattr->index] >> 5) & 7) != 7) {
+ mutex_unlock(&data->lock);
+ return count;
+ }
+
+ reg = PWM_REG(sattr->index);
+ break;
+
+ case MIN:
+ reg = PWM_MIN_REG(sattr->index);
+ break;
+
+ case MAX:
+ reg = PWM_MAX_REG(sattr->index);
+ break;
+ }
+
+ data->pwm[sattr->nr][sattr->index] = SENSORS_LIMIT(val, 0, 0xFF);
+ i2c_smbus_write_byte_data(client, reg,
+ data->pwm[sattr->nr][sattr->index]);
+
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+/* Called by set_pwmctrl and set_pwmchan */
+
+static int hw_set_pwm(struct i2c_client *client, int index,
+ unsigned int pwmctl, unsigned int pwmchan)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ long val = 0;
+
+ switch (pwmctl) {
+ case 0:
+ val = 0x03; /* Run at full speed */
+ break;
+ case 1:
+ val = 0x07; /* Manual mode */
+ break;
+ case 2:
+ switch (pwmchan) {
+ case 1:
+ /* Remote1 controls PWM */
+ val = 0x00;
+ break;
+ case 2:
+ /* local controls PWM */
+ val = 0x01;
+ break;
+ case 4:
+ /* remote2 controls PWM */
+ val = 0x02;
+ break;
+ case 6:
+ /* local/remote2 control PWM */
+ val = 0x05;
+ break;
+ case 7:
+ /* All three control PWM */
+ val = 0x06;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ data->pwmctl[index] = pwmctl;
+ data->pwmchan[index] = pwmchan;
+
+ data->pwm[CONTROL][index] &= ~0xE0;
+ data->pwm[CONTROL][index] |= (val & 7) << 5;
+
+ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+ data->pwm[CONTROL][index]);
+
+ return 0;
+}
+
+static ssize_t set_pwmchan(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ int r;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ /* Read Modify Write PWM values */
+ adt7475_read_pwm(client, sattr->index);
+ r = hw_set_pwm(client, sattr->index, data->pwmctl[sattr->index], val);
+ if (r)
+ count = r;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+static ssize_t set_pwmctrl(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ int r;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ mutex_lock(&data->lock);
+ /* Read Modify Write PWM values */
+ adt7475_read_pwm(client, sattr->index);
+ r = hw_set_pwm(client, sattr->index, val, data->pwmchan[sattr->index]);
+ if (r)
+ count = r;
+ mutex_unlock(&data->lock);
+
+ return count;
+}
+
+/* List of frequencies for the PWM */
+static const int pwmfreq_table[] = {
+ 11, 14, 22, 29, 35, 44, 58, 88
+};
+
+static ssize_t show_pwmfreq(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct adt7475_data *data = adt7475_update_device(dev);
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ return sprintf(buf, "%d\n",
+ pwmfreq_table[data->range[sattr->index] & 7]);
+}
+
+static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ int out;
+ long val;
+
+ if (strict_strtol(buf, 10, &val))
+ return -EINVAL;
+
+ out = find_nearest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table));
+
+ mutex_lock(&data->lock);
+
+ data->range[sattr->index] =
+ adt7475_read(TEMP_TRANGE_REG(sattr->index));
+ data->range[sattr->index] &= ~7;
+ data->range[sattr->index] |= out;
+
+ i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index),
+ data->range[sattr->index]);
+
+ mutex_unlock(&data->lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MAX, 0);
+static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MIN, 0);
+static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0);
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MAX, 1);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage,
+ set_voltage, MIN, 1);
+static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MAX, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MIN, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, OFFSET, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO | S_IWUSR,
+ show_temp, set_temp, AUTOMIN, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IRUGO | S_IWUSR,
+ show_point2, set_point2, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ THERM, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_crit_hyst, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, HYSTERSIS, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_alarm, S_IRUGO, show_temp, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MAX, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MIN, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, OFFSET, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IRUGO | S_IWUSR,
+ show_temp, set_temp, AUTOMIN, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IRUGO | S_IWUSR,
+ show_point2, set_point2, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ THERM, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_crit_hyst, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, HYSTERSIS, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_alarm, S_IRUGO, show_temp, NULL, ALARM, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_temp, NULL, FAULT, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MAX, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ MIN, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, OFFSET, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_point1_temp, S_IRUGO | S_IWUSR,
+ show_temp, set_temp, AUTOMIN, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_point2_temp, S_IRUGO | S_IWUSR,
+ show_point2, set_point2, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp,
+ THERM, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_crit_hyst, S_IRUGO | S_IWUSR, show_temp,
+ set_temp, HYSTERSIS, 2);
+static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_tach, NULL, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 0);
+static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, show_tach, NULL, ALARM, 0);
+static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_tach, NULL, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 1);
+static SENSOR_DEVICE_ATTR_2(fan2_alarm, S_IRUGO, show_tach, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_tach, NULL, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 2);
+static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_tach, NULL, ALARM, 2);
+static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_tach, NULL, INPUT, 3);
+static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_tach, set_tach,
+ MIN, 3);
+static SENSOR_DEVICE_ATTR_2(fan4_alarm, S_IRUGO, show_tach, NULL, ALARM, 3);
+static SENSOR_DEVICE_ATTR_2(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT,
+ 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_freq, S_IRUGO | S_IWUSR, show_pwmfreq,
+ set_pwmfreq, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_enable, S_IRUGO | S_IWUSR, show_pwmctrl,
+ set_pwmctrl, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_channel_temp, S_IRUGO | S_IWUSR,
+ show_pwmchan, set_pwmchan, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MIN, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MAX, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT,
+ 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_freq, S_IRUGO | S_IWUSR, show_pwmfreq,
+ set_pwmfreq, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_enable, S_IRUGO | S_IWUSR, show_pwmctrl,
+ set_pwmctrl, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_channel_temp, S_IRUGO | S_IWUSR,
+ show_pwmchan, set_pwmchan, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MIN, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MAX, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT,
+ 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_freq, S_IRUGO | S_IWUSR, show_pwmfreq,
+ set_pwmfreq, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_enable, S_IRUGO | S_IWUSR, show_pwmctrl,
+ set_pwmctrl, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_channel_temp, S_IRUGO | S_IWUSR,
+ show_pwmchan, set_pwmchan, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MIN, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
+ set_pwm, MAX, 2);
+
+static struct attribute *adt7475_attrs[] = {
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in1_max.dev_attr.attr,
+ &sensor_dev_attr_in1_min.dev_attr.attr,
+ &sensor_dev_attr_in1_alarm.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in2_max.dev_attr.attr,
+ &sensor_dev_attr_in2_min.dev_attr.attr,
+ &sensor_dev_attr_in2_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp1_fault.dev_attr.attr,
+ &sensor_dev_attr_temp1_max.dev_attr.attr,
+ &sensor_dev_attr_temp1_min.dev_attr.attr,
+ &sensor_dev_attr_temp1_offset.dev_attr.attr,
+ &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp1_crit.dev_attr.attr,
+ &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp2_max.dev_attr.attr,
+ &sensor_dev_attr_temp2_min.dev_attr.attr,
+ &sensor_dev_attr_temp2_offset.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp2_crit.dev_attr.attr,
+ &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
+ &sensor_dev_attr_temp3_fault.dev_attr.attr,
+ &sensor_dev_attr_temp3_alarm.dev_attr.attr,
+ &sensor_dev_attr_temp3_max.dev_attr.attr,
+ &sensor_dev_attr_temp3_min.dev_attr.attr,
+ &sensor_dev_attr_temp3_offset.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_temp3_crit.dev_attr.attr,
+ &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr,
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_min.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan3_input.dev_attr.attr,
+ &sensor_dev_attr_fan3_min.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ &sensor_dev_attr_fan4_input.dev_attr.attr,
+ &sensor_dev_attr_fan4_min.dev_attr.attr,
+ &sensor_dev_attr_fan4_alarm.dev_attr.attr,
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm1_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_channel_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm2_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_channel_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm3_freq.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_channel_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
+ NULL,
+};
+
+struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
+
+static int adt7475_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ if (kind <= 0) {
+ if (adt7475_read(REG_VENDID) != 0x41 ||
+ adt7475_read(REG_DEVID) != 0x75) {
+ dev_err(&adapter->dev,
+ "Couldn't detect a adt7475 part at 0x%02x\n",
+ (unsigned int)client->addr);
+ return -ENODEV;
+ }
+ }
+
+ strlcpy(info->type, adt7475_id[0].name, I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int adt7475_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adt7475_data *data;
+ int i, ret = 0;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ mutex_init(&data->lock);
+ i2c_set_clientdata(client, data);
+
+ /* Call adt7475_read_pwm for all pwm's as this will reprogram any
+ pwm's which are disabled to manual mode with 0% duty cycle */
+ for (i = 0; i < ADT7475_PWM_COUNT; i++)
+ adt7475_read_pwm(client, i);
+
+ ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group);
+ if (ret)
+ goto efree;
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ ret = PTR_ERR(data->hwmon_dev);
+ goto eremove;
+ }
+
+ return 0;
+
+eremove:
+ sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
+efree:
+ kfree(data);
+ return ret;
+}
+
+static int adt7475_remove(struct i2c_client *client)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
+ kfree(data);
+
+ return 0;
+}
+
+static struct i2c_driver adt7475_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "adt7475",
+ },
+ .probe = adt7475_probe,
+ .remove = adt7475_remove,
+ .id_table = adt7475_id,
+ .detect = adt7475_detect,
+ .address_data = &addr_data,
+};
+
+static void adt7475_read_hystersis(struct i2c_client *client)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+
+ data->temp[HYSTERSIS][0] = (u16) adt7475_read(REG_REMOTE1_HYSTERSIS);
+ data->temp[HYSTERSIS][1] = data->temp[HYSTERSIS][0];
+ data->temp[HYSTERSIS][2] = (u16) adt7475_read(REG_REMOTE2_HYSTERSIS);
+}
+
+static void adt7475_read_pwm(struct i2c_client *client, int index)
+{
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ unsigned int v;
+
+ data->pwm[CONTROL][index] = adt7475_read(PWM_CONFIG_REG(index));
+
+ /* Figure out the internal value for pwmctrl and pwmchan
+ based on the current settings */
+ v = (data->pwm[CONTROL][index] >> 5) & 7;
+
+ if (v == 3)
+ data->pwmctl[index] = 0;
+ else if (v == 7)
+ data->pwmctl[index] = 1;
+ else if (v == 4) {
+ /* The fan is disabled - we don't want to
+ support that, so change to manual mode and
+ set the duty cycle to 0 instead
+ */
+ data->pwm[INPUT][index] = 0;
+ data->pwm[CONTROL][index] &= ~0xE0;
+ data->pwm[CONTROL][index] |= (7 << 5);
+
+ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+ data->pwm[INPUT][index]);
+
+ i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+ data->pwm[CONTROL][index]);
+
+ data->pwmctl[index] = 1;
+ } else {
+ data->pwmctl[index] = 2;
+
+ switch (v) {
+ case 0:
+ data->pwmchan[index] = 1;
+ break;
+ case 1:
+ data->pwmchan[index] = 2;
+ break;
+ case 2:
+ data->pwmchan[index] = 4;
+ break;
+ case 5:
+ data->pwmchan[index] = 6;
+ break;
+ case 6:
+ data->pwmchan[index] = 7;
+ break;
+ }
+ }
+}
+
+static struct adt7475_data *adt7475_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7475_data *data = i2c_get_clientdata(client);
+ u8 ext;
+ int i;
+
+ mutex_lock(&data->lock);
+
+ /* Measurement values update every 2 seconds */
+ if (time_after(jiffies, data->measure_updated + HZ * 2) ||
+ !data->valid) {
+ data->alarms = adt7475_read(REG_STATUS2) << 8;
+ data->alarms |= adt7475_read(REG_STATUS1);
+
+ ext = adt7475_read(REG_EXTEND1);
+ for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++)
+ data->voltage[INPUT][i] =
+ (adt7475_read(VOLTAGE_REG(i)) << 2) |
+ ((ext >> ((i + 1) * 2)) & 3);
+
+ ext = adt7475_read(REG_EXTEND2);
+ for (i = 0; i < ADT7475_TEMP_COUNT; i++)
+ data->temp[INPUT][i] =
+ (adt7475_read(TEMP_REG(i)) << 2) |
+ ((ext >> ((i + 1) * 2)) & 3);
+
+ for (i = 0; i < ADT7475_TACH_COUNT; i++)
+ data->tach[INPUT][i] =
+ adt7475_read_word(client, TACH_REG(i));
+
+ /* Updated by hw when in auto mode */
+ for (i = 0; i < ADT7475_PWM_COUNT; i++)
+ data->pwm[INPUT][i] = adt7475_read(PWM_REG(i));
+
+ data->measure_updated = jiffies;
+ }
+
+ /* Limits and settings, should never change update every 60 seconds */
+ if (time_after(jiffies, data->limits_updated + HZ * 2) ||
+ !data->valid) {
+ data->config5 = adt7475_read(REG_CONFIG5);
+
+ for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
+ /* Adjust values so they match the input precision */
+ data->voltage[MIN][i] =
+ adt7475_read(VOLTAGE_MIN_REG(i)) << 2;
+ data->voltage[MAX][i] =
+ adt7475_read(VOLTAGE_MAX_REG(i)) << 2;
+ }
+
+ for (i = 0; i < ADT7475_TEMP_COUNT; i++) {
+ /* Adjust values so they match the input precision */
+ data->temp[MIN][i] =
+ adt7475_read(TEMP_MIN_REG(i)) << 2;
+ data->temp[MAX][i] =
+ adt7475_read(TEMP_MAX_REG(i)) << 2;
+ data->temp[AUTOMIN][i] =
+ adt7475_read(TEMP_TMIN_REG(i)) << 2;
+ data->temp[THERM][i] =
+ adt7475_read(TEMP_THERM_REG(i)) << 2;
+ data->temp[OFFSET][i] =
+ adt7475_read(TEMP_OFFSET_REG(i));
+ }
+ adt7475_read_hystersis(client);
+
+ for (i = 0; i < ADT7475_TACH_COUNT; i++)
+ data->tach[MIN][i] =
+ adt7475_read_word(client, TACH_MIN_REG(i));
+
+ for (i = 0; i < ADT7475_PWM_COUNT; i++) {
+ data->pwm[MAX][i] = adt7475_read(PWM_MAX_REG(i));
+ data->pwm[MIN][i] = adt7475_read(PWM_MIN_REG(i));
+ /* Set the channel and control information */
+ adt7475_read_pwm(client, i);
+ }
+
+ data->range[0] = adt7475_read(TEMP_TRANGE_REG(0));
+ data->range[1] = adt7475_read(TEMP_TRANGE_REG(1));
+ data->range[2] = adt7475_read(TEMP_TRANGE_REG(2));
+
+ data->limits_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->lock);
+
+ return data;
+}
+
+static int __init sensors_adt7475_init(void)
+{
+ return i2c_add_driver(&adt7475_driver);
+}
+
+static void __exit sensors_adt7475_exit(void)
+{
+ i2c_del_driver(&adt7475_driver);
+}
+
+MODULE_AUTHOR("Advanced Micro Devices, Inc");
+MODULE_DESCRIPTION("adt7475 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_adt7475_init);
+module_exit(sensors_adt7475_exit);
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index 086c2a5cef0b..678e34b01e52 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -83,7 +83,7 @@
/*
* Temperature sensors keys (sp78 - 2 bytes).
*/
-static const char* temperature_sensors_sets[][36] = {
+static const char *temperature_sensors_sets[][41] = {
/* Set 0: Macbook Pro */
{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
"Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
@@ -131,6 +131,17 @@ static const char* temperature_sensors_sets[][36] = {
/* Set 14: iMac 6,1 */
{ "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
"TO0P", "Tp0P", NULL },
+/* Set 15: MacBook Air 2,1 */
+ { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TN0D", "TTF0",
+ "TV0P", "TVFP", "TW0P", "Th0P", "Tp0P", "Tp1P", "TpFP", "Ts0P",
+ "Ts0S", NULL },
+/* Set 16: Mac Pro 3,1 (2 x Quad-Core) */
+ { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", "TC0C", "TC0D", "TC0P",
+ "TC1C", "TC1D", "TC2C", "TC2D", "TC3C", "TC3D", "TH0P", "TH1P",
+ "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S", "TM1P",
+ "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P", "TM9S",
+ "TN0C", "TN0D", "TN0H", "TS0C", "Tp0C", "Tp1C", "Tv0S", "Tv1S",
+ NULL },
};
/* List of keys used to read/write fan speeds */
@@ -586,6 +597,11 @@ static ssize_t applesmc_light_show(struct device *dev,
}
ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
+ /* newer macbooks report a single 10-bit bigendian value */
+ if (data_length == 10) {
+ left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
+ goto out;
+ }
left = buffer[2];
if (ret)
goto out;
@@ -1144,6 +1160,16 @@ static SENSOR_DEVICE_ATTR(temp34_input, S_IRUGO,
applesmc_show_temperature, NULL, 33);
static SENSOR_DEVICE_ATTR(temp35_input, S_IRUGO,
applesmc_show_temperature, NULL, 34);
+static SENSOR_DEVICE_ATTR(temp36_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 35);
+static SENSOR_DEVICE_ATTR(temp37_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 36);
+static SENSOR_DEVICE_ATTR(temp38_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 37);
+static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 38);
+static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO,
+ applesmc_show_temperature, NULL, 39);
static struct attribute *temperature_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -1181,6 +1207,11 @@ static struct attribute *temperature_attributes[] = {
&sensor_dev_attr_temp33_input.dev_attr.attr,
&sensor_dev_attr_temp34_input.dev_attr.attr,
&sensor_dev_attr_temp35_input.dev_attr.attr,
+ &sensor_dev_attr_temp36_input.dev_attr.attr,
+ &sensor_dev_attr_temp37_input.dev_attr.attr,
+ &sensor_dev_attr_temp38_input.dev_attr.attr,
+ &sensor_dev_attr_temp39_input.dev_attr.attr,
+ &sensor_dev_attr_temp40_input.dev_attr.attr,
NULL
};
@@ -1301,11 +1332,19 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
{ .accelerometer = 0, .light = 0, .temperature_set = 13 },
/* iMac 6: light sensor only, temperature set 14 */
{ .accelerometer = 0, .light = 0, .temperature_set = 14 },
+/* MacBook Air 2,1: accelerometer, backlight and temperature set 15 */
+ { .accelerometer = 1, .light = 1, .temperature_set = 15 },
+/* MacPro3,1: temperature set 16 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 16 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
* So we need to put "Apple MacBook Pro" before "Apple MacBook". */
static __initdata struct dmi_system_id applesmc_whitelist[] = {
+ { applesmc_dmi_match, "Apple MacBook Air 2", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2") },
+ &applesmc_dmi_data[15]},
{ applesmc_dmi_match, "Apple MacBook Air", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
@@ -1354,6 +1393,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
&applesmc_dmi_data[4]},
+ { applesmc_dmi_match, "Apple MacPro3", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacPro3") },
+ &applesmc_dmi_data[16]},
{ applesmc_dmi_match, "Apple MacPro", {
DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") },
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 8a45a2e6ba8a..8acf82977e7b 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -53,7 +53,10 @@ static const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(asb100);
-I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+
+static unsigned short force_subclients[4];
+module_param_array(force_subclients, short, NULL, 0);
+MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
/* Voltage IN registers 0-6 */
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 27a5d397f9a1..3df202a9ad72 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -34,6 +34,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/acpi.h>
#include <asm/io.h>
/* ISA device, if found */
@@ -2361,6 +2362,10 @@ static int __init dme1737_isa_device_add(unsigned short addr)
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
if (!(pdev = platform_device_alloc("dme1737", addr))) {
printk(KERN_ERR "dme1737: Failed to allocate device.\n");
err = -ENOMEM;
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 7a14a2dbb752..899876579253 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -39,6 +39,7 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/ioport.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static unsigned short force_id;
@@ -1455,6 +1456,10 @@ static int __init f71805f_device_add(unsigned short address,
}
res.name = pdev->name;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit_device_put;
+
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 67067e9a323e..609cafff86bc 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> *
- * Copyright (C) 2007 by Hans de Goede <j.w.r.degoede@hhs.nl> *
+ * Copyright (C) 2007,2008 by Hans de Goede <hdegoede@redhat.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 *
@@ -27,11 +27,12 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
-#include <asm/io.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
#define DRVNAME "f71882fg"
-#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device*/
+#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */
#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */
#define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */
@@ -43,7 +44,9 @@
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */
+#define SIO_F71862_ID 0x0601 /* Chipset ID */
#define SIO_F71882_ID 0x0541 /* Chipset ID */
+#define SIO_F8000_ID 0x0581 /* Chipset ID */
#define REGION_LENGTH 8
#define ADDR_REG_OFFSET 5
@@ -51,25 +54,36 @@
#define F71882FG_REG_PECI 0x0A
-#define F71882FG_REG_IN_STATUS 0x12
-#define F71882FG_REG_IN_BEEP 0x13
+#define F71882FG_REG_IN_STATUS 0x12 /* f71882fg only */
+#define F71882FG_REG_IN_BEEP 0x13 /* f71882fg only */
#define F71882FG_REG_IN(nr) (0x20 + (nr))
-#define F71882FG_REG_IN1_HIGH 0x32
+#define F71882FG_REG_IN1_HIGH 0x32 /* f71882fg only */
#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr)))
+#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr)))
+#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr)))
#define F71882FG_REG_FAN_STATUS 0x92
#define F71882FG_REG_FAN_BEEP 0x93
-#define F71882FG_REG_TEMP(nr) (0x72 + 2 * (nr))
-#define F71882FG_REG_TEMP_OVT(nr) (0x82 + 2 * (nr))
-#define F71882FG_REG_TEMP_HIGH(nr) (0x83 + 2 * (nr))
+#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr))
+#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr))
+#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr))
#define F71882FG_REG_TEMP_STATUS 0x62
#define F71882FG_REG_TEMP_BEEP 0x63
-#define F71882FG_REG_TEMP_HYST1 0x6C
-#define F71882FG_REG_TEMP_HYST23 0x6D
+#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr))
#define F71882FG_REG_TEMP_TYPE 0x6B
#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F
+#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr)))
+#define F71882FG_REG_PWM_TYPE 0x94
+#define F71882FG_REG_PWM_ENABLE 0x96
+
+#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr))
+
+#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm)))
+#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm)))
+#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr))
+
#define F71882FG_REG_START 0x01
#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */
@@ -78,7 +92,15 @@ static unsigned short force_id;
module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID");
-static struct platform_device *f71882fg_pdev = NULL;
+enum chips { f71862fg, f71882fg, f8000 };
+
+static const char *f71882fg_names[] = {
+ "f71862fg",
+ "f71882fg",
+ "f8000",
+};
+
+static struct platform_device *f71882fg_pdev;
/* Super-I/O Function prototypes */
static inline int superio_inb(int base, int reg);
@@ -87,8 +109,13 @@ static inline void superio_enter(int base);
static inline void superio_select(int base, int ld);
static inline void superio_exit(int base);
+struct f71882fg_sio_data {
+ enum chips type;
+};
+
struct f71882fg_data {
unsigned short addr;
+ enum chips type;
struct device *hwmon_dev;
struct mutex update_lock;
@@ -102,19 +129,30 @@ struct f71882fg_data {
u8 in_status;
u8 in_beep;
u16 fan[4];
+ u16 fan_target[4];
+ u16 fan_full_speed[4];
u8 fan_status;
u8 fan_beep;
- u8 temp[3];
- u8 temp_ovt[3];
- u8 temp_high[3];
- u8 temp_hyst[3];
- u8 temp_type[3];
+ /* Note: all models have only 3 temperature channels, but on some
+ they are addressed as 0-2 and on others as 1-3, so for coding
+ convenience we reserve space for 4 channels */
+ u8 temp[4];
+ u8 temp_ovt[4];
+ u8 temp_high[4];
+ u8 temp_hyst[2]; /* 2 hysts stored per reg */
+ u8 temp_type[4];
u8 temp_status;
u8 temp_beep;
u8 temp_diode_open;
+ u8 pwm[4];
+ u8 pwm_enable;
+ u8 pwm_auto_point_hyst[2];
+ u8 pwm_auto_point_mapping[4];
+ u8 pwm_auto_point_pwm[4][5];
+ u8 pwm_auto_point_temp[4][4];
};
-/* Sysfs in*/
+/* Sysfs in */
static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
char *buf);
static ssize_t show_in_max(struct device *dev, struct device_attribute
@@ -130,6 +168,10 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute
/* Sysfs Fan */
static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
char *buf);
+static ssize_t show_fan_full_speed(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t store_fan_full_speed(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
static ssize_t show_fan_beep(struct device *dev, struct device_attribute
*devattr, char *buf);
static ssize_t store_fan_beep(struct device *dev, struct device_attribute
@@ -163,16 +205,41 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
*devattr, char *buf);
static ssize_t show_temp_fault(struct device *dev, struct device_attribute
*devattr, char *buf);
+/* PWM and Auto point control */
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+ char *buf);
+static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count);
+static ssize_t show_pwm_enable(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t store_pwm_enable(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
+static ssize_t show_pwm_interpolate(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t store_pwm_interpolate(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
+static ssize_t show_pwm_auto_point_channel(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t store_pwm_auto_point_channel(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
+static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
+static ssize_t show_pwm_auto_point_pwm(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t store_pwm_auto_point_pwm(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
+static ssize_t show_pwm_auto_point_temp(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t store_pwm_auto_point_temp(struct device *dev,
+ struct device_attribute *devattr, const char *buf, size_t count);
/* Sysfs misc */
static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
char *buf);
static int __devinit f71882fg_probe(struct platform_device * pdev);
-static int __devexit f71882fg_remove(struct platform_device *pdev);
-static int __init f71882fg_init(void);
-static int __init f71882fg_find(int sioaddr, unsigned short *address);
-static int __init f71882fg_device_add(unsigned short address);
-static void __exit f71882fg_exit(void);
+static int f71882fg_remove(struct platform_device *pdev);
static struct platform_driver f71882fg_driver = {
.driver = {
@@ -183,86 +250,531 @@ static struct platform_driver f71882fg_driver = {
.remove = __devexit_p(f71882fg_remove),
};
-static struct device_attribute f71882fg_dev_attr[] =
-{
- __ATTR( name, S_IRUGO, show_name, NULL ),
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+/* Temp and in attr common to both the f71862fg and f71882fg */
+static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = {
+ SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
+ SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
+ SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
+ SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
+ SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
+ SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
+ SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
+ SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
+ SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
+ SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
+ SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 0, 1),
+ SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+ store_temp_max_hyst, 0, 1),
+ /* Should really be temp1_max_alarm, but older versions did not handle
+ the max and crit alarms separately and lm_sensors v2 depends on the
+ presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
+ SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
+ SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 0, 1),
+ SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 0, 1),
+ SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
+ 0, 1),
+ SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
+ SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 0, 5),
+ SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
+ SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
+ SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
+ SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 0, 2),
+ SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+ store_temp_max_hyst, 0, 2),
+ /* Should be temp2_max_alarm, see temp1_alarm note */
+ SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
+ SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 0, 2),
+ SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 0, 2),
+ SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
+ 0, 2),
+ SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
+ SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 0, 6),
+ SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
+ SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
+ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
+ SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 0, 3),
+ SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
+ store_temp_max_hyst, 0, 3),
+ /* Should be temp3_max_alarm, see temp1_alarm note */
+ SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
+ SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 0, 3),
+ SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 0, 3),
+ SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
+ 0, 3),
+ SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
+ SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+ store_temp_beep, 0, 7),
+ SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
+ SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
+};
+
+/* Temp and in attr found only on the f71882fg */
+static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
+ SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
+ 0, 1),
+ SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
+ 0, 1),
+ SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
+};
+
+/* Temp and in attr for the f8000
+ Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
+ is used as hysteresis value to clear alarms
+ */
+static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
+ SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
+ SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
+ SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
+ SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
+ SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 0, 0),
+ SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 0, 0),
+ SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4),
+ SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1),
+ SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 0, 1),
+ SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 0, 1),
+ SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
+ SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
+ SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
+ SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
+ store_temp_crit, 0, 2),
+ SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
+ store_temp_max, 0, 2),
+ SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
+};
+
+/* Fan / PWM attr common to all models */
+static struct sensor_device_attribute_2 fxxxx_fan_attr[] = {
+ SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
+ SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
+ show_fan_full_speed,
+ store_fan_full_speed, 0, 0),
+ SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
+ SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
+ SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
+ show_fan_full_speed,
+ store_fan_full_speed, 0, 1),
+ SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
+ SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
+ SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
+ show_fan_full_speed,
+ store_fan_full_speed, 0, 2),
+ SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
+
+ SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
+ SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 0, 0),
+ SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
+ show_pwm_interpolate, store_pwm_interpolate, 0, 0),
+ SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_channel,
+ store_pwm_auto_point_channel, 0, 0),
+
+ SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
+ SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 0, 1),
+ SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
+ show_pwm_interpolate, store_pwm_interpolate, 0, 1),
+ SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_channel,
+ store_pwm_auto_point_channel, 0, 1),
+
+ SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
+ show_pwm_interpolate, store_pwm_interpolate, 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_channel,
+ store_pwm_auto_point_channel, 0, 2),
};
-static struct sensor_device_attribute f71882fg_in_temp_attr[] =
-{
- SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
- SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
- SENSOR_ATTR(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, 1),
- SENSOR_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, 1),
- SENSOR_ATTR(in1_alarm, S_IRUGO, show_in_alarm, NULL, 1),
- SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
- SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
- SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
- SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
- SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
- SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
- SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
- SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
- SENSOR_ATTR(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
- store_temp_max, 0),
- SENSOR_ATTR(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
- store_temp_max_hyst, 0),
- SENSOR_ATTR(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
- store_temp_crit, 0),
- SENSOR_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 0),
- SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
- SENSOR_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep,
- store_temp_beep, 0),
- SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0),
- SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0),
- SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
- SENSOR_ATTR(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
- store_temp_max, 1),
- SENSOR_ATTR(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
- store_temp_max_hyst, 1),
- SENSOR_ATTR(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
- store_temp_crit, 1),
- SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1),
- SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
- SENSOR_ATTR(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep,
- store_temp_beep, 1),
- SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1),
- SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1),
- SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
- SENSOR_ATTR(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
- store_temp_max, 2),
- SENSOR_ATTR(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst,
- store_temp_max_hyst, 2),
- SENSOR_ATTR(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
- store_temp_crit, 2),
- SENSOR_ATTR(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 2),
- SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
- SENSOR_ATTR(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep,
- store_temp_beep, 2),
- SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2),
- SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2)
+/* Fan / PWM attr for the f71862fg, less pwms and less zones per pwm than the
+ f71882fg */
+static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
+ SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 0, 0),
+ SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 0, 1),
+ SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 0, 2),
+
+ SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 0),
+ SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 0),
+ SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 0),
+ SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 0),
+ SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 0),
+ SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 0),
+
+ SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 1),
+ SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 1),
+ SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 1),
+ SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 1),
+ SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 1),
+ SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 1),
+
+ SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
+ SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 2),
+ SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 2),
+ SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 2),
+ SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 2),
};
-static struct sensor_device_attribute f71882fg_fan_attr[] =
-{
- SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
- SENSOR_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
- store_fan_beep, 0),
- SENSOR_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0),
- SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
- SENSOR_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
- store_fan_beep, 1),
- SENSOR_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1),
- SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
- SENSOR_ATTR(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
- store_fan_beep, 2),
- SENSOR_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2),
- SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
- SENSOR_ATTR(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
- store_fan_beep, 3),
- SENSOR_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3)
+/* Fan / PWM attr for the f71882fg */
+static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
+ SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 0, 0),
+ SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 0, 1),
+ SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 0, 2),
+ SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
+ SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
+ show_fan_full_speed,
+ store_fan_full_speed, 0, 3),
+ SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+ store_fan_beep, 0, 3),
+ SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
+
+ SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 0),
+ SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 0),
+ SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 0),
+ SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 0),
+ SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 0),
+ SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 0),
+ SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 0),
+ SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 0),
+ SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 0),
+ SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 0),
+ SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 1, 0),
+ SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 2, 0),
+ SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 0),
+
+ SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 1),
+ SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 1),
+ SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 1),
+ SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 1),
+ SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 1),
+ SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 1),
+ SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 1),
+ SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 1),
+ SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 1),
+ SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 1),
+ SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 1, 1),
+ SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 2, 1),
+ SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 1),
+
+ SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
+ SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 2),
+ SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 2),
+ SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 2),
+ SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 2),
+ SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 2),
+ SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 2),
+ SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 2),
+ SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 2),
+ SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 1, 2),
+ SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 2, 2),
+ SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 2),
+
+ SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
+ SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+ store_pwm_enable, 0, 3),
+ SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
+ show_pwm_interpolate, store_pwm_interpolate, 0, 3),
+ SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_channel,
+ store_pwm_auto_point_channel, 0, 3),
+ SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 3),
+ SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 3),
+ SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 3),
+ SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 3),
+ SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 3),
+ SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 3),
+ SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 3),
+ SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 3),
+ SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 3),
+ SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 3),
+ SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 1, 3),
+ SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 2, 3),
+ SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 3),
};
+/* Fan / PWM attr for the f8000, zones mapped to temp instead of to pwm!
+ Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
+ F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
+static struct sensor_device_attribute_2 f8000_fan_attr[] = {
+ SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
+
+ SENSOR_ATTR_2(pwm3, S_IRUGO, show_pwm, NULL, 0, 2),
+
+ SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 2),
+ SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 2),
+ SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 2),
+ SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 2),
+ SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 2),
+ SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 2),
+ SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 2),
+ SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 2),
+ SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 2),
+ SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 2),
+ SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 1, 2),
+ SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 2, 2),
+ SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 2),
+
+ SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 0),
+ SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 0),
+ SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 0),
+ SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 0),
+ SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 0),
+ SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 0),
+ SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 0),
+ SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 0),
+ SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 0),
+ SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 0),
+ SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 1, 0),
+ SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 2, 0),
+ SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 0),
+
+ SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 0, 1),
+ SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 1, 1),
+ SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 2, 1),
+ SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 3, 1),
+ SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+ 4, 1),
+ SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 0, 1),
+ SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 1, 1),
+ SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 2, 1),
+ SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+ 3, 1),
+ SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+ show_pwm_auto_point_temp_hyst,
+ store_pwm_auto_point_temp_hyst,
+ 0, 1),
+ SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 1, 1),
+ SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 2, 1),
+ SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO,
+ show_pwm_auto_point_temp_hyst, NULL, 3, 1),
+};
/* Super I/O functions */
static inline int superio_inb(int base, int reg)
@@ -299,11 +811,16 @@ static inline void superio_exit(int base)
outb(SIO_LOCK_KEY, base);
}
-static inline u16 fan_from_reg(u16 reg)
+static inline int fan_from_reg(u16 reg)
{
return reg ? (1500000 / reg) : 0;
}
+static inline u16 fan_to_reg(int fan)
+{
+ return fan ? (1500000 / fan) : 0;
+}
+
static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg)
{
u8 val;
@@ -332,52 +849,111 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val)
outb(val, data->addr + DATA_REG_OFFSET);
}
-static struct f71882fg_data *f71882fg_update_device(struct device * dev)
+static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val)
+{
+ outb(reg++, data->addr + ADDR_REG_OFFSET);
+ outb(val >> 8, data->addr + DATA_REG_OFFSET);
+ outb(reg, data->addr + ADDR_REG_OFFSET);
+ outb(val & 255, data->addr + DATA_REG_OFFSET);
+}
+
+static struct f71882fg_data *f71882fg_update_device(struct device *dev)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int nr, reg, reg2;
+ int nr, reg = 0, reg2;
+ int nr_fans = (data->type == f71882fg) ? 4 : 3;
+ int nr_ins = (data->type == f8000) ? 3 : 9;
+ int temp_start = (data->type == f8000) ? 0 : 1;
mutex_lock(&data->update_lock);
/* Update once every 60 seconds */
if ( time_after(jiffies, data->last_limits + 60 * HZ ) ||
!data->valid) {
- data->in1_max = f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
- data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+ if (data->type == f71882fg) {
+ data->in1_max =
+ f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
+ data->in_beep =
+ f71882fg_read8(data, F71882FG_REG_IN_BEEP);
+ }
/* Get High & boundary temps*/
- for (nr = 0; nr < 3; nr++) {
+ for (nr = temp_start; nr < 3 + temp_start; nr++) {
data->temp_ovt[nr] = f71882fg_read8(data,
F71882FG_REG_TEMP_OVT(nr));
data->temp_high[nr] = f71882fg_read8(data,
F71882FG_REG_TEMP_HIGH(nr));
}
- /* Have to hardcode hyst*/
- data->temp_hyst[0] = f71882fg_read8(data,
- F71882FG_REG_TEMP_HYST1) >> 4;
- /* Hyst temps 2 & 3 stored in same register */
- reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23);
- data->temp_hyst[1] = reg & 0x0F;
- data->temp_hyst[2] = reg >> 4;
-
- /* Have to hardcode type, because temp1 is special */
- reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
+ if (data->type != f8000) {
+ data->fan_beep = f71882fg_read8(data,
+ F71882FG_REG_FAN_BEEP);
+ data->temp_beep = f71882fg_read8(data,
+ F71882FG_REG_TEMP_BEEP);
+ data->temp_hyst[0] = f71882fg_read8(data,
+ F71882FG_REG_TEMP_HYST(0));
+ data->temp_hyst[1] = f71882fg_read8(data,
+ F71882FG_REG_TEMP_HYST(1));
+ /* Have to hardcode type, because temp1 is special */
+ reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
+ data->temp_type[2] = (reg & 0x04) ? 2 : 4;
+ data->temp_type[3] = (reg & 0x08) ? 2 : 4;
+ }
reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
if ((reg2 & 0x03) == 0x01)
- data->temp_type[0] = 6 /* PECI */;
+ data->temp_type[1] = 6 /* PECI */;
else if ((reg2 & 0x03) == 0x02)
- data->temp_type[0] = 5 /* AMDSI */;
+ data->temp_type[1] = 5 /* AMDSI */;
+ else if (data->type != f8000)
+ data->temp_type[1] = (reg & 0x02) ? 2 : 4;
else
- data->temp_type[0] = (reg & 0x02) ? 2 : 4;
-
- data->temp_type[1] = (reg & 0x04) ? 2 : 4;
- data->temp_type[2] = (reg & 0x08) ? 2 : 4;
-
- data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
-
- data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
-
+ data->temp_type[1] = 2; /* F8000 only supports BJT */
+
+ data->pwm_enable = f71882fg_read8(data,
+ F71882FG_REG_PWM_ENABLE);
+ data->pwm_auto_point_hyst[0] =
+ f71882fg_read8(data, F71882FG_REG_FAN_HYST(0));
+ data->pwm_auto_point_hyst[1] =
+ f71882fg_read8(data, F71882FG_REG_FAN_HYST(1));
+
+ for (nr = 0; nr < nr_fans; nr++) {
+ data->pwm_auto_point_mapping[nr] =
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_MAPPING(nr));
+
+ if (data->type != f71862fg) {
+ int point;
+ for (point = 0; point < 5; point++) {
+ data->pwm_auto_point_pwm[nr][point] =
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_PWM
+ (nr, point));
+ }
+ for (point = 0; point < 4; point++) {
+ data->pwm_auto_point_temp[nr][point] =
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_TEMP
+ (nr, point));
+ }
+ } else {
+ data->pwm_auto_point_pwm[nr][1] =
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_PWM
+ (nr, 1));
+ data->pwm_auto_point_pwm[nr][4] =
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_PWM
+ (nr, 4));
+ data->pwm_auto_point_temp[nr][0] =
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_TEMP
+ (nr, 0));
+ data->pwm_auto_point_temp[nr][3] =
+ f71882fg_read8(data,
+ F71882FG_REG_POINT_TEMP
+ (nr, 3));
+ }
+ }
data->last_limits = jiffies;
}
@@ -387,19 +963,32 @@ static struct f71882fg_data *f71882fg_update_device(struct device * dev)
F71882FG_REG_TEMP_STATUS);
data->temp_diode_open = f71882fg_read8(data,
F71882FG_REG_TEMP_DIODE_OPEN);
- for (nr = 0; nr < 3; nr++)
+ for (nr = temp_start; nr < 3 + temp_start; nr++)
data->temp[nr] = f71882fg_read8(data,
F71882FG_REG_TEMP(nr));
data->fan_status = f71882fg_read8(data,
F71882FG_REG_FAN_STATUS);
- for (nr = 0; nr < 4; nr++)
+ for (nr = 0; nr < nr_fans; nr++) {
data->fan[nr] = f71882fg_read16(data,
F71882FG_REG_FAN(nr));
+ data->fan_target[nr] =
+ f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr));
+ data->fan_full_speed[nr] =
+ f71882fg_read16(data,
+ F71882FG_REG_FAN_FULL_SPEED(nr));
+ data->pwm[nr] =
+ f71882fg_read8(data, F71882FG_REG_PWM(nr));
+ }
- data->in_status = f71882fg_read8(data,
+ /* The f8000 can monitor 1 more fan, but has no pwm for it */
+ if (data->type == f8000)
+ data->fan[3] = f71882fg_read16(data,
+ F71882FG_REG_FAN(3));
+ if (data->type == f71882fg)
+ data->in_status = f71882fg_read8(data,
F71882FG_REG_IN_STATUS);
- for (nr = 0; nr < 9; nr++)
+ for (nr = 0; nr < nr_ins; nr++)
data->in[nr] = f71882fg_read8(data,
F71882FG_REG_IN(nr));
@@ -417,7 +1006,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
int speed = fan_from_reg(data->fan[nr]);
if (speed == FAN_MIN_DETECT)
@@ -426,11 +1015,39 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%d\n", speed);
}
+static ssize_t show_fan_full_speed(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ int speed = fan_from_reg(data->fan_full_speed[nr]);
+ return sprintf(buf, "%d\n", speed);
+}
+
+static ssize_t store_fan_full_speed(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ val = SENSORS_LIMIT(val, 23, 1500000);
+ val = fan_to_reg(val);
+
+ mutex_lock(&data->update_lock);
+ f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val);
+ data->fan_full_speed[nr] = val;
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
static ssize_t show_fan_beep(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
if (data->fan_beep & (1 << nr))
return sprintf(buf, "1\n");
@@ -442,10 +1059,11 @@ static ssize_t store_fan_beep(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
- int val = simple_strtoul(buf, NULL, 10);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock);
+ data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP);
if (val)
data->fan_beep |= 1 << nr;
else
@@ -461,7 +1079,7 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
if (data->fan_status & (1 << nr))
return sprintf(buf, "1\n");
@@ -473,7 +1091,7 @@ static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
return sprintf(buf, "%d\n", data->in[nr] * 8);
}
@@ -490,10 +1108,8 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int val = simple_strtoul(buf, NULL, 10) / 8;
-
- if (val > 255)
- val = 255;
+ long val = simple_strtol(buf, NULL, 10) / 8;
+ val = SENSORS_LIMIT(val, 0, 255);
mutex_lock(&data->update_lock);
f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val);
@@ -507,7 +1123,7 @@ static ssize_t show_in_beep(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
if (data->in_beep & (1 << nr))
return sprintf(buf, "1\n");
@@ -519,10 +1135,11 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
- int val = simple_strtoul(buf, NULL, 10);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock);
+ data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP);
if (val)
data->in_beep |= 1 << nr;
else
@@ -538,7 +1155,7 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
if (data->in_status & (1 << nr))
return sprintf(buf, "1\n");
@@ -550,7 +1167,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
return sprintf(buf, "%d\n", data->temp[nr] * 1000);
}
@@ -559,7 +1176,7 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
return sprintf(buf, "%d\n", data->temp_high[nr] * 1000);
}
@@ -568,11 +1185,9 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
- int val = simple_strtoul(buf, NULL, 10) / 1000;
-
- if (val > 255)
- val = 255;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ long val = simple_strtol(buf, NULL, 10) / 1000;
+ val = SENSORS_LIMIT(val, 0, 255);
mutex_lock(&data->update_lock);
f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val);
@@ -586,48 +1201,46 @@ static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ int temp_max_hyst;
+
+ mutex_lock(&data->update_lock);
+ if (nr & 1)
+ temp_max_hyst = data->temp_hyst[nr / 2] >> 4;
+ else
+ temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f;
+ temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000;
+ mutex_unlock(&data->update_lock);
- return sprintf(buf, "%d\n",
- (data->temp_high[nr] - data->temp_hyst[nr]) * 1000);
+ return sprintf(buf, "%d\n", temp_max_hyst);
}
static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
- int val = simple_strtoul(buf, NULL, 10) / 1000;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ long val = simple_strtol(buf, NULL, 10) / 1000;
ssize_t ret = count;
+ u8 reg;
mutex_lock(&data->update_lock);
/* convert abs to relative and check */
+ data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr));
+ val = SENSORS_LIMIT(val, data->temp_high[nr] - 15,
+ data->temp_high[nr]);
val = data->temp_high[nr] - val;
- if (val < 0 || val > 15) {
- ret = -EINVAL;
- goto store_temp_max_hyst_exit;
- }
-
- data->temp_hyst[nr] = val;
/* convert value to register contents */
- switch (nr) {
- case 0:
- val = val << 4;
- break;
- case 1:
- val = val | (data->temp_hyst[2] << 4);
- break;
- case 2:
- val = data->temp_hyst[1] | (val << 4);
- break;
- }
-
- f71882fg_write8(data, nr ? F71882FG_REG_TEMP_HYST23 :
- F71882FG_REG_TEMP_HYST1, val);
+ reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2));
+ if (nr & 1)
+ reg = (reg & 0x0f) | (val << 4);
+ else
+ reg = (reg & 0xf0) | val;
+ f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg);
+ data->temp_hyst[nr / 2] = reg;
-store_temp_max_hyst_exit:
mutex_unlock(&data->update_lock);
return ret;
}
@@ -636,7 +1249,7 @@ static ssize_t show_temp_crit(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000);
}
@@ -645,11 +1258,9 @@ static ssize_t store_temp_crit(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
- int val = simple_strtoul(buf, NULL, 10) / 1000;
-
- if (val > 255)
- val = 255;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ long val = simple_strtol(buf, NULL, 10) / 1000;
+ val = SENSORS_LIMIT(val, 0, 255);
mutex_lock(&data->update_lock);
f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val);
@@ -663,17 +1274,25 @@ static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ int temp_crit_hyst;
+
+ mutex_lock(&data->update_lock);
+ if (nr & 1)
+ temp_crit_hyst = data->temp_hyst[nr / 2] >> 4;
+ else
+ temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f;
+ temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000;
+ mutex_unlock(&data->update_lock);
- return sprintf(buf, "%d\n",
- (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000);
+ return sprintf(buf, "%d\n", temp_crit_hyst);
}
static ssize_t show_temp_type(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
return sprintf(buf, "%d\n", data->temp_type[nr]);
}
@@ -682,9 +1301,9 @@ static ssize_t show_temp_beep(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
- if (data->temp_beep & (1 << (nr + 1)))
+ if (data->temp_beep & (1 << nr))
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
@@ -694,14 +1313,15 @@ static ssize_t store_temp_beep(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct f71882fg_data *data = dev_get_drvdata(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
- int val = simple_strtoul(buf, NULL, 10);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
mutex_lock(&data->update_lock);
+ data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP);
if (val)
- data->temp_beep |= 1 << (nr + 1);
+ data->temp_beep |= 1 << nr;
else
- data->temp_beep &= ~(1 << (nr + 1));
+ data->temp_beep &= ~(1 << nr);
f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep);
mutex_unlock(&data->update_lock);
@@ -713,9 +1333,9 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
- if (data->temp_status & (1 << (nr + 1)))
+ if (data->temp_status & (1 << nr))
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
@@ -725,113 +1345,528 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct f71882fg_data *data = f71882fg_update_device(dev);
- int nr = to_sensor_dev_attr(devattr)->index;
+ int nr = to_sensor_dev_attr_2(devattr)->index;
- if (data->temp_diode_open & (1 << (nr + 1)))
+ if (data->temp_diode_open & (1 << nr))
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
}
+static ssize_t show_pwm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int val, nr = to_sensor_dev_attr_2(devattr)->index;
+ mutex_lock(&data->update_lock);
+ if (data->pwm_enable & (1 << (2 * nr)))
+ /* PWM mode */
+ val = data->pwm[nr];
+ else {
+ /* RPM mode */
+ val = 255 * fan_from_reg(data->fan_target[nr])
+ / fan_from_reg(data->fan_full_speed[nr]);
+ }
+ mutex_unlock(&data->update_lock);
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t store_pwm(struct device *dev,
+ struct device_attribute *devattr, const char *buf,
+ size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ long val = simple_strtol(buf, NULL, 10);
+ val = SENSORS_LIMIT(val, 0, 255);
+
+ mutex_lock(&data->update_lock);
+ data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
+ if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) ||
+ (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) {
+ count = -EROFS;
+ goto leave;
+ }
+ if (data->pwm_enable & (1 << (2 * nr))) {
+ /* PWM mode */
+ f71882fg_write8(data, F71882FG_REG_PWM(nr), val);
+ data->pwm[nr] = val;
+ } else {
+ /* RPM mode */
+ int target, full_speed;
+ full_speed = f71882fg_read16(data,
+ F71882FG_REG_FAN_FULL_SPEED(nr));
+ target = fan_to_reg(val * fan_from_reg(full_speed) / 255);
+ f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target);
+ data->fan_target[nr] = target;
+ data->fan_full_speed[nr] = full_speed;
+ }
+leave:
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ int result = 0;
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+
+ switch ((data->pwm_enable >> 2 * nr) & 3) {
+ case 0:
+ case 1:
+ result = 2; /* Normal auto mode */
+ break;
+ case 2:
+ result = 1; /* Manual mode */
+ break;
+ case 3:
+ if (data->type == f8000)
+ result = 3; /* Thermostat mode */
+ else
+ result = 1; /* Manual mode */
+ break;
+ }
+
+ return sprintf(buf, "%d\n", result);
+}
+
+static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
+ *devattr, const char *buf, size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ long val = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
+ /* Special case for F8000 auto PWM mode / Thermostat mode */
+ if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) {
+ switch (val) {
+ case 2:
+ data->pwm_enable &= ~(2 << (2 * nr));
+ break; /* Normal auto mode */
+ case 3:
+ data->pwm_enable |= 2 << (2 * nr);
+ break; /* Thermostat mode */
+ default:
+ count = -EINVAL;
+ goto leave;
+ }
+ } else {
+ switch (val) {
+ case 1:
+ data->pwm_enable |= 2 << (2 * nr);
+ break; /* Manual */
+ case 2:
+ data->pwm_enable &= ~(2 << (2 * nr));
+ break; /* Normal auto mode */
+ default:
+ count = -EINVAL;
+ goto leave;
+ }
+ }
+ f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable);
+leave:
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_auto_point_pwm(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ int result;
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int pwm = to_sensor_dev_attr_2(devattr)->index;
+ int point = to_sensor_dev_attr_2(devattr)->nr;
+
+ mutex_lock(&data->update_lock);
+ if (data->pwm_enable & (1 << (2 * pwm))) {
+ /* PWM mode */
+ result = data->pwm_auto_point_pwm[pwm][point];
+ } else {
+ /* RPM mode */
+ result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]);
+ }
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n", result);
+}
+
+static ssize_t store_pwm_auto_point_pwm(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int pwm = to_sensor_dev_attr_2(devattr)->index;
+ int point = to_sensor_dev_attr_2(devattr)->nr;
+ long val = simple_strtol(buf, NULL, 10);
+ val = SENSORS_LIMIT(val, 0, 255);
+
+ mutex_lock(&data->update_lock);
+ data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
+ if (data->pwm_enable & (1 << (2 * pwm))) {
+ /* PWM mode */
+ } else {
+ /* RPM mode */
+ if (val < 29) /* Prevent negative numbers */
+ val = 255;
+ else
+ val = (255 - val) * 32 / val;
+ }
+ f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val);
+ data->pwm_auto_point_pwm[pwm][point] = val;
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ int result = 0;
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ int point = to_sensor_dev_attr_2(devattr)->nr;
+
+ mutex_lock(&data->update_lock);
+ if (nr & 1)
+ result = data->pwm_auto_point_hyst[nr / 2] >> 4;
+ else
+ result = data->pwm_auto_point_hyst[nr / 2] & 0x0f;
+ result = 1000 * (data->pwm_auto_point_temp[nr][point] - result);
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n", result);
+}
+
+static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ int point = to_sensor_dev_attr_2(devattr)->nr;
+ long val = simple_strtol(buf, NULL, 10) / 1000;
+ u8 reg;
+
+ mutex_lock(&data->update_lock);
+ data->pwm_auto_point_temp[nr][point] =
+ f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point));
+ val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15,
+ data->pwm_auto_point_temp[nr][point]);
+ val = data->pwm_auto_point_temp[nr][point] - val;
+
+ reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2));
+ if (nr & 1)
+ reg = (reg & 0x0f) | (val << 4);
+ else
+ reg = (reg & 0xf0) | val;
+
+ f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg);
+ data->pwm_auto_point_hyst[nr / 2] = reg;
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_interpolate(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ int result;
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+
+ result = (data->pwm_auto_point_mapping[nr] >> 4) & 1;
+
+ return sprintf(buf, "%d\n", result);
+}
+
+static ssize_t store_pwm_interpolate(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ data->pwm_auto_point_mapping[nr] =
+ f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
+ if (val)
+ val = data->pwm_auto_point_mapping[nr] | (1 << 4);
+ else
+ val = data->pwm_auto_point_mapping[nr] & (~(1 << 4));
+ f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
+ data->pwm_auto_point_mapping[nr] = val;
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_auto_point_channel(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ int result;
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ int temp_start = (data->type == f8000) ? 0 : 1;
+
+ result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - temp_start);
+
+ return sprintf(buf, "%d\n", result);
+}
+
+static ssize_t store_pwm_auto_point_channel(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int nr = to_sensor_dev_attr_2(devattr)->index;
+ int temp_start = (data->type == f8000) ? 0 : 1;
+ long val = simple_strtol(buf, NULL, 10);
+
+ switch (val) {
+ case 1:
+ val = 0;
+ break;
+ case 2:
+ val = 1;
+ break;
+ case 4:
+ val = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ val += temp_start;
+ mutex_lock(&data->update_lock);
+ data->pwm_auto_point_mapping[nr] =
+ f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr));
+ val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val;
+ f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val);
+ data->pwm_auto_point_mapping[nr] = val;
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_pwm_auto_point_temp(struct device *dev,
+ struct device_attribute *devattr,
+ char *buf)
+{
+ int result;
+ struct f71882fg_data *data = f71882fg_update_device(dev);
+ int pwm = to_sensor_dev_attr_2(devattr)->index;
+ int point = to_sensor_dev_attr_2(devattr)->nr;
+
+ result = data->pwm_auto_point_temp[pwm][point];
+ return sprintf(buf, "%d\n", 1000 * result);
+}
+
+static ssize_t store_pwm_auto_point_temp(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ int pwm = to_sensor_dev_attr_2(devattr)->index;
+ int point = to_sensor_dev_attr_2(devattr)->nr;
+ long val = simple_strtol(buf, NULL, 10) / 1000;
+ val = SENSORS_LIMIT(val, 0, 255);
+
+ mutex_lock(&data->update_lock);
+ f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
+ data->pwm_auto_point_temp[pwm][point] = val;
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
char *buf)
{
- return sprintf(buf, DRVNAME "\n");
+ struct f71882fg_data *data = dev_get_drvdata(dev);
+ return sprintf(buf, "%s\n", f71882fg_names[data->type]);
}
+static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
+ struct sensor_device_attribute_2 *attr, int count)
+{
+ int err, i;
+
+ for (i = 0; i < count; i++) {
+ err = device_create_file(&pdev->dev, &attr[i].dev_attr);
+ if (err)
+ return err;
+ }
+ return 0;
+}
-static int __devinit f71882fg_probe(struct platform_device * pdev)
+static int __devinit f71882fg_probe(struct platform_device *pdev)
{
struct f71882fg_data *data;
- int err, i;
+ struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
+ int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3;
u8 start_reg;
- if (!(data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL)))
+ data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
+ if (!data)
return -ENOMEM;
data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+ data->type = sio_data->type;
mutex_init(&data->update_lock);
platform_set_drvdata(pdev, data);
- /* Register sysfs interface files */
- for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) {
- err = device_create_file(&pdev->dev, &f71882fg_dev_attr[i]);
- if (err)
- goto exit_unregister_sysfs;
+ start_reg = f71882fg_read8(data, F71882FG_REG_START);
+ if (start_reg & 0x04) {
+ dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
+ err = -ENODEV;
+ goto exit_free;
+ }
+ if (!(start_reg & 0x03)) {
+ dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
+ err = -ENODEV;
+ goto exit_free;
}
- start_reg = f71882fg_read8(data, F71882FG_REG_START);
+ data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
+ /* If it is a 71862 and the fan / pwm part is enabled sanity check
+ the pwm settings */
+ if (data->type == f71862fg && (start_reg & 0x02)) {
+ if ((data->pwm_enable & 0x15) != 0x15) {
+ dev_err(&pdev->dev,
+ "Invalid (reserved) pwm settings: 0x%02x\n",
+ (unsigned int)data->pwm_enable);
+ err = -ENODEV;
+ goto exit_free;
+ }
+ }
+
+ /* Register sysfs interface files */
+ err = device_create_file(&pdev->dev, &dev_attr_name);
+ if (err)
+ goto exit_unregister_sysfs;
+
if (start_reg & 0x01) {
- for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) {
- err = device_create_file(&pdev->dev,
- &f71882fg_in_temp_attr[i].dev_attr);
+ switch (data->type) {
+ case f71882fg:
+ err = f71882fg_create_sysfs_files(pdev,
+ f71882fg_in_temp_attr,
+ ARRAY_SIZE(f71882fg_in_temp_attr));
if (err)
goto exit_unregister_sysfs;
+ /* fall through! */
+ case f71862fg:
+ err = f71882fg_create_sysfs_files(pdev,
+ f718x2fg_in_temp_attr,
+ ARRAY_SIZE(f718x2fg_in_temp_attr));
+ break;
+ case f8000:
+ err = f71882fg_create_sysfs_files(pdev,
+ f8000_in_temp_attr,
+ ARRAY_SIZE(f8000_in_temp_attr));
+ break;
}
+ if (err)
+ goto exit_unregister_sysfs;
}
if (start_reg & 0x02) {
- for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) {
- err = device_create_file(&pdev->dev,
- &f71882fg_fan_attr[i].dev_attr);
- if (err)
- goto exit_unregister_sysfs;
+ err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr,
+ ARRAY_SIZE(fxxxx_fan_attr));
+ if (err)
+ goto exit_unregister_sysfs;
+
+ switch (data->type) {
+ case f71862fg:
+ err = f71882fg_create_sysfs_files(pdev,
+ f71862fg_fan_attr,
+ ARRAY_SIZE(f71862fg_fan_attr));
+ break;
+ case f71882fg:
+ err = f71882fg_create_sysfs_files(pdev,
+ f71882fg_fan_attr,
+ ARRAY_SIZE(f71882fg_fan_attr));
+ break;
+ case f8000:
+ err = f71882fg_create_sysfs_files(pdev,
+ f8000_fan_attr,
+ ARRAY_SIZE(f8000_fan_attr));
+ break;
}
+ if (err)
+ goto exit_unregister_sysfs;
+
+ for (i = 0; i < nr_fans; i++)
+ dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
+ (data->pwm_enable & (1 << 2 * i)) ?
+ "duty-cycle" : "RPM");
}
data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
+ data->hwmon_dev = NULL;
goto exit_unregister_sysfs;
}
return 0;
exit_unregister_sysfs:
- for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++)
- device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]);
-
- for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++)
- device_remove_file(&pdev->dev,
- &f71882fg_in_temp_attr[i].dev_attr);
-
- for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++)
- device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr);
-
+ f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
+ return err; /* f71882fg_remove() also frees our data */
+exit_free:
kfree(data);
-
return err;
}
-static int __devexit f71882fg_remove(struct platform_device *pdev)
+static int f71882fg_remove(struct platform_device *pdev)
{
int i;
struct f71882fg_data *data = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
- hwmon_device_unregister(data->hwmon_dev);
+ if (data->hwmon_dev)
+ hwmon_device_unregister(data->hwmon_dev);
+
+ /* Note we are not looping over all attr arrays we have as the ones
+ below are supersets of the ones skipped. */
+ device_remove_file(&pdev->dev, &dev_attr_name);
- for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++)
- device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]);
+ for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++)
+ device_remove_file(&pdev->dev,
+ &f718x2fg_in_temp_attr[i].dev_attr);
for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++)
device_remove_file(&pdev->dev,
&f71882fg_in_temp_attr[i].dev_attr);
+ for (i = 0; i < ARRAY_SIZE(fxxxx_fan_attr); i++)
+ device_remove_file(&pdev->dev, &fxxxx_fan_attr[i].dev_attr);
+
for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++)
device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr);
+ for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++)
+ device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr);
+
kfree(data);
return 0;
}
-static int __init f71882fg_find(int sioaddr, unsigned short *address)
+static int __init f71882fg_find(int sioaddr, unsigned short *address,
+ struct f71882fg_sio_data *sio_data)
{
int err = -ENODEV;
u16 devid;
- u8 start_reg;
- struct f71882fg_data data;
superio_enter(sioaddr);
@@ -842,7 +1877,17 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address)
}
devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
- if (devid != SIO_F71882_ID) {
+ switch (devid) {
+ case SIO_F71862_ID:
+ sio_data->type = f71862fg;
+ break;
+ case SIO_F71882_ID:
+ sio_data->type = f71882fg;
+ break;
+ case SIO_F8000_ID:
+ sio_data->type = f8000;
+ break;
+ default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n");
goto exit;
}
@@ -861,24 +1906,17 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address)
}
*address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
- data.addr = *address;
- start_reg = f71882fg_read8(&data, F71882FG_REG_START);
- if (!(start_reg & 0x03)) {
- printk(KERN_WARNING DRVNAME
- ": Hardware monitoring not activated\n");
- goto exit;
- }
-
err = 0;
- printk(KERN_INFO DRVNAME ": Found F71882FG chip at %#x, revision %d\n",
- (unsigned int)*address,
+ printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n",
+ f71882fg_names[sio_data->type], (unsigned int)*address,
(int)superio_inb(sioaddr, SIO_REG_DEVREV));
exit:
superio_exit(sioaddr);
return err;
}
-static int __init f71882fg_device_add(unsigned short address)
+static int __init f71882fg_device_add(unsigned short address,
+ const struct f71882fg_sio_data *sio_data)
{
struct resource res = {
.start = address,
@@ -892,12 +1930,23 @@ static int __init f71882fg_device_add(unsigned short address)
return -ENOMEM;
res.name = f71882fg_pdev->name;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ return err;
+
err = platform_device_add_resources(f71882fg_pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed\n");
goto exit_device_put;
}
+ err = platform_device_add_data(f71882fg_pdev, sio_data,
+ sizeof(struct f71882fg_sio_data));
+ if (err) {
+ printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+ goto exit_device_put;
+ }
+
err = platform_device_add(f71882fg_pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed\n");
@@ -916,14 +1965,20 @@ static int __init f71882fg_init(void)
{
int err = -ENODEV;
unsigned short address;
+ struct f71882fg_sio_data sio_data;
+
+ memset(&sio_data, 0, sizeof(sio_data));
- if (f71882fg_find(0x2e, &address) && f71882fg_find(0x4e, &address))
+ if (f71882fg_find(0x2e, &address, &sio_data) &&
+ f71882fg_find(0x4e, &address, &sio_data))
goto exit;
- if ((err = platform_driver_register(&f71882fg_driver)))
+ err = platform_driver_register(&f71882fg_driver);
+ if (err)
goto exit;
- if ((err = f71882fg_device_add(address)))
+ err = f71882fg_device_add(address, &sio_data);
+ if (err)
goto exit_driver;
return 0;
@@ -941,7 +1996,7 @@ static void __exit f71882fg_exit(void)
}
MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
-MODULE_AUTHOR("Hans Edgington (hans@edgington.nl)");
+MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
MODULE_LICENSE("GPL");
module_init(f71882fg_init);
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index 967170368933..d07f4ef75092 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -1,6 +1,6 @@
/* fschmd.c
*
- * Copyright (C) 2007 Hans de Goede <j.w.r.degoede@hhs.nl>
+ * Copyright (C) 2007,2008 Hans de Goede <hdegoede@redhat.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
@@ -42,11 +42,20 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/dmi.h>
+#include <linux/fs.h>
+#include <linux/watchdog.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/kref.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
/* Insmod parameters */
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd);
/*
@@ -63,19 +72,26 @@ I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd);
#define FSCHMD_REG_EVENT_STATE 0x04
#define FSCHMD_REG_CONTROL 0x05
-#define FSCHMD_CONTROL_ALERT_LED_MASK 0x01
+#define FSCHMD_CONTROL_ALERT_LED 0x01
-/* watchdog (support to be implemented) */
+/* watchdog */
#define FSCHMD_REG_WDOG_PRESET 0x28
#define FSCHMD_REG_WDOG_STATE 0x23
#define FSCHMD_REG_WDOG_CONTROL 0x21
+#define FSCHMD_WDOG_CONTROL_TRIGGER 0x10
+#define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */
+#define FSCHMD_WDOG_CONTROL_STOP 0x20
+#define FSCHMD_WDOG_CONTROL_RESOLUTION 0x40
+
+#define FSCHMD_WDOG_STATE_CARDRESET 0x02
+
/* voltages, weird order is to keep the same order as the old drivers */
static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 };
/* minimum pwm at which the fan is driven (pwm can by increased depending on
the temp. Notice that for the scy some fans share there minimum speed.
- Also notice that with the scy the sensor order is different then with the
+ Also notice that with the scy the sensor order is different than with the
other chips, this order was in the 2.4 driver and kept for consistency. */
static const u8 FSCHMD_REG_FAN_MIN[5][6] = {
{ 0x55, 0x65 }, /* pos */
@@ -115,8 +131,8 @@ static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = {
static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 };
/* Fan status register bitmasks */
-#define FSCHMD_FAN_ALARM_MASK 0x04 /* called fault by FSC! */
-#define FSCHMD_FAN_NOT_PRESENT_MASK 0x08 /* not documented */
+#define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */
+#define FSCHMD_FAN_NOT_PRESENT 0x08 /* not documented */
/* actual temperature registers */
@@ -158,14 +174,11 @@ static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */
static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 };
/* temp status register bitmasks */
-#define FSCHMD_TEMP_WORKING_MASK 0x01
-#define FSCHMD_TEMP_ALERT_MASK 0x02
+#define FSCHMD_TEMP_WORKING 0x01
+#define FSCHMD_TEMP_ALERT 0x02
/* there only really is an alarm if the sensor is working and alert == 1 */
#define FSCHMD_TEMP_ALARM_MASK \
- (FSCHMD_TEMP_WORKING_MASK | FSCHMD_TEMP_ALERT_MASK)
-
-/* our driver name */
-#define FSCHMD_NAME "fschmd"
+ (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT)
/*
* Functions declarations
@@ -195,7 +208,7 @@ MODULE_DEVICE_TABLE(i2c, fschmd_id);
static struct i2c_driver fschmd_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
- .name = FSCHMD_NAME,
+ .name = "fschmd",
},
.probe = fschmd_probe,
.remove = fschmd_remove,
@@ -209,14 +222,26 @@ static struct i2c_driver fschmd_driver = {
*/
struct fschmd_data {
+ struct i2c_client *client;
struct device *hwmon_dev;
struct mutex update_lock;
+ struct mutex watchdog_lock;
+ struct list_head list; /* member of the watchdog_data_list */
+ struct kref kref;
+ struct miscdevice watchdog_miscdev;
int kind;
+ unsigned long watchdog_is_open;
+ char watchdog_expect_close;
+ char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
/* register values */
+ u8 revision; /* chip revision */
u8 global_control; /* global control register */
+ u8 watchdog_control; /* watchdog control register */
+ u8 watchdog_state; /* watchdog status register */
+ u8 watchdog_preset; /* watchdog counter preset on trigger val */
u8 volt[3]; /* 12, 5, battery voltage */
u8 temp_act[5]; /* temperature */
u8 temp_status[5]; /* status of sensor */
@@ -228,11 +253,28 @@ struct fschmd_data {
};
/* Global variables to hold information read from special DMI tables, which are
- available on FSC machines with an fscher or later chip. */
+ available on FSC machines with an fscher or later chip. There is no need to
+ protect these with a lock as they are only modified from our attach function
+ which always gets called with the i2c-core lock held and never accessed
+ before the attach function is done with them. */
static int dmi_mult[3] = { 490, 200, 100 };
static int dmi_offset[3] = { 0, 0, 0 };
static int dmi_vref = -1;
+/* Somewhat ugly :( global data pointer list with all fschmd devices, so that
+ we can find our device data as when using misc_register there is no other
+ method to get to ones device data from the open fop. */
+static LIST_HEAD(watchdog_data_list);
+/* Note this lock not only protect list access, but also data.kref access */
+static DEFINE_MUTEX(watchdog_data_mutex);
+
+/* Release our data struct when we're detached from the i2c client *and* all
+ references to our watchdog device are released */
+static void fschmd_release_resources(struct kref *ref)
+{
+ struct fschmd_data *data = container_of(ref, struct fschmd_data, kref);
+ kfree(data);
+}
/*
* Sysfs attr show / store functions
@@ -300,7 +342,7 @@ static ssize_t show_temp_fault(struct device *dev,
struct fschmd_data *data = fschmd_update_device(dev);
/* bit 0 set means sensor working ok, so no fault! */
- if (data->temp_status[index] & FSCHMD_TEMP_WORKING_MASK)
+ if (data->temp_status[index] & FSCHMD_TEMP_WORKING)
return sprintf(buf, "0\n");
else
return sprintf(buf, "1\n");
@@ -385,7 +427,7 @@ static ssize_t show_fan_alarm(struct device *dev,
int index = to_sensor_dev_attr(devattr)->index;
struct fschmd_data *data = fschmd_update_device(dev);
- if (data->fan_status[index] & FSCHMD_FAN_ALARM_MASK)
+ if (data->fan_status[index] & FSCHMD_FAN_ALARM)
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
@@ -397,7 +439,7 @@ static ssize_t show_fan_fault(struct device *dev,
int index = to_sensor_dev_attr(devattr)->index;
struct fschmd_data *data = fschmd_update_device(dev);
- if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT_MASK)
+ if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT)
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
@@ -449,7 +491,7 @@ static ssize_t show_alert_led(struct device *dev,
{
struct fschmd_data *data = fschmd_update_device(dev);
- if (data->global_control & FSCHMD_CONTROL_ALERT_LED_MASK)
+ if (data->global_control & FSCHMD_CONTROL_ALERT_LED)
return sprintf(buf, "1\n");
else
return sprintf(buf, "0\n");
@@ -467,9 +509,9 @@ static ssize_t store_alert_led(struct device *dev,
reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL);
if (v)
- reg |= FSCHMD_CONTROL_ALERT_LED_MASK;
+ reg |= FSCHMD_CONTROL_ALERT_LED;
else
- reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK;
+ reg &= ~FSCHMD_CONTROL_ALERT_LED;
i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg);
@@ -551,7 +593,265 @@ static struct sensor_device_attribute fschmd_fan_attr[] = {
/*
- * Real code
+ * Watchdog routines
+ */
+
+static int watchdog_set_timeout(struct fschmd_data *data, int timeout)
+{
+ int ret, resolution;
+ int kind = data->kind + 1; /* 0-x array index -> 1-x module param */
+
+ /* 2 second or 60 second resolution? */
+ if (timeout <= 510 || kind == fscpos || kind == fscscy)
+ resolution = 2;
+ else
+ resolution = 60;
+
+ if (timeout < resolution || timeout > (resolution * 255))
+ return -EINVAL;
+
+ mutex_lock(&data->watchdog_lock);
+ if (!data->client) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ if (resolution == 2)
+ data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_RESOLUTION;
+ else
+ data->watchdog_control |= FSCHMD_WDOG_CONTROL_RESOLUTION;
+
+ data->watchdog_preset = DIV_ROUND_UP(timeout, resolution);
+
+ /* Write new timeout value */
+ i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_PRESET,
+ data->watchdog_preset);
+ /* Write new control register, do not trigger! */
+ i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL,
+ data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER);
+
+ ret = data->watchdog_preset * resolution;
+
+leave:
+ mutex_unlock(&data->watchdog_lock);
+ return ret;
+}
+
+static int watchdog_get_timeout(struct fschmd_data *data)
+{
+ int timeout;
+
+ mutex_lock(&data->watchdog_lock);
+ if (data->watchdog_control & FSCHMD_WDOG_CONTROL_RESOLUTION)
+ timeout = data->watchdog_preset * 60;
+ else
+ timeout = data->watchdog_preset * 2;
+ mutex_unlock(&data->watchdog_lock);
+
+ return timeout;
+}
+
+static int watchdog_trigger(struct fschmd_data *data)
+{
+ int ret = 0;
+
+ mutex_lock(&data->watchdog_lock);
+ if (!data->client) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER;
+ i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL,
+ data->watchdog_control);
+leave:
+ mutex_unlock(&data->watchdog_lock);
+ return ret;
+}
+
+static int watchdog_stop(struct fschmd_data *data)
+{
+ int ret = 0;
+
+ mutex_lock(&data->watchdog_lock);
+ if (!data->client) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED;
+ /* Don't store the stop flag in our watchdog control register copy, as
+ its a write only bit (read always returns 0) */
+ i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL,
+ data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP);
+leave:
+ mutex_unlock(&data->watchdog_lock);
+ return ret;
+}
+
+static int watchdog_open(struct inode *inode, struct file *filp)
+{
+ struct fschmd_data *pos, *data = NULL;
+
+ /* We get called from drivers/char/misc.c with misc_mtx hold, and we
+ call misc_register() from fschmd_probe() with watchdog_data_mutex
+ hold, as misc_register() takes the misc_mtx lock, this is a possible
+ deadlock, so we use mutex_trylock here. */
+ if (!mutex_trylock(&watchdog_data_mutex))
+ return -ERESTARTSYS;
+ list_for_each_entry(pos, &watchdog_data_list, list) {
+ if (pos->watchdog_miscdev.minor == iminor(inode)) {
+ data = pos;
+ break;
+ }
+ }
+ /* Note we can never not have found data, so we don't check for this */
+ kref_get(&data->kref);
+ mutex_unlock(&watchdog_data_mutex);
+
+ if (test_and_set_bit(0, &data->watchdog_is_open))
+ return -EBUSY;
+
+ /* Start the watchdog */
+ watchdog_trigger(data);
+ filp->private_data = data;
+
+ return nonseekable_open(inode, filp);
+}
+
+static int watchdog_release(struct inode *inode, struct file *filp)
+{
+ struct fschmd_data *data = filp->private_data;
+
+ if (data->watchdog_expect_close) {
+ watchdog_stop(data);
+ data->watchdog_expect_close = 0;
+ } else {
+ watchdog_trigger(data);
+ dev_crit(&data->client->dev,
+ "unexpected close, not stopping watchdog!\n");
+ }
+
+ clear_bit(0, &data->watchdog_is_open);
+
+ mutex_lock(&watchdog_data_mutex);
+ kref_put(&data->kref, fschmd_release_resources);
+ mutex_unlock(&watchdog_data_mutex);
+
+ return 0;
+}
+
+static ssize_t watchdog_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ size_t ret;
+ struct fschmd_data *data = filp->private_data;
+
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* Clear it in case it was set with a previous write */
+ data->watchdog_expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ data->watchdog_expect_close = 1;
+ }
+ }
+ ret = watchdog_trigger(data);
+ if (ret < 0)
+ return ret;
+ }
+ return count;
+}
+
+static int watchdog_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+ WDIOF_CARDRESET,
+ .identity = "FSC watchdog"
+ };
+ int i, ret = 0;
+ struct fschmd_data *data = filp->private_data;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ident.firmware_version = data->revision;
+ if (!nowayout)
+ ident.options |= WDIOF_MAGICCLOSE;
+ if (copy_to_user((void __user *)arg, &ident, sizeof(ident)))
+ ret = -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ ret = put_user(0, (int __user *)arg);
+ break;
+
+ case WDIOC_GETBOOTSTATUS:
+ if (data->watchdog_state & FSCHMD_WDOG_STATE_CARDRESET)
+ ret = put_user(WDIOF_CARDRESET, (int __user *)arg);
+ else
+ ret = put_user(0, (int __user *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ ret = watchdog_trigger(data);
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ i = watchdog_get_timeout(data);
+ ret = put_user(i, (int __user *)arg);
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(i, (int __user *)arg)) {
+ ret = -EFAULT;
+ break;
+ }
+ ret = watchdog_set_timeout(data, i);
+ if (ret > 0)
+ ret = put_user(ret, (int __user *)arg);
+ break;
+
+ case WDIOC_SETOPTIONS:
+ if (get_user(i, (int __user *)arg)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ if (i & WDIOS_DISABLECARD)
+ ret = watchdog_stop(data);
+ else if (i & WDIOS_ENABLECARD)
+ ret = watchdog_trigger(data);
+ else
+ ret = -EINVAL;
+
+ break;
+ default:
+ ret = -ENOTTY;
+ }
+
+ return ret;
+}
+
+static struct file_operations watchdog_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = watchdog_open,
+ .release = watchdog_release,
+ .write = watchdog_write,
+ .ioctl = watchdog_ioctl,
+};
+
+
+/*
+ * Detect, register, unregister and update device functions
*/
/* DMI decode routine to read voltage scaling factors from special DMI tables,
@@ -661,9 +961,9 @@ static int fschmd_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct fschmd_data *data;
- u8 revision;
const char * const names[5] = { "Poseidon", "Hermes", "Scylla",
"Heracles", "Heimdall" };
+ const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
int i, err;
enum chips kind = id->driver_data;
@@ -673,6 +973,13 @@ static int fschmd_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
+ mutex_init(&data->watchdog_lock);
+ INIT_LIST_HEAD(&data->list);
+ kref_init(&data->kref);
+ /* Store client pointer in our data struct for watchdog usage
+ (where the client is found through a data ptr instead of the
+ otherway around) */
+ data->client = client;
if (kind == fscpos) {
/* The Poseidon has hardwired temp limits, fill these
@@ -683,16 +990,27 @@ static int fschmd_probe(struct i2c_client *client,
}
/* Read the special DMI table for fscher and newer chips */
- if (kind == fscher || kind >= fschrc) {
+ if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) {
dmi_walk(fschmd_dmi_decode);
if (dmi_vref == -1) {
- printk(KERN_WARNING FSCHMD_NAME
- ": Couldn't get voltage scaling factors from "
+ dev_warn(&client->dev,
+ "Couldn't get voltage scaling factors from "
"BIOS DMI table, using builtin defaults\n");
dmi_vref = 33;
}
}
+ /* Read in some never changing registers */
+ data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
+ data->global_control = i2c_smbus_read_byte_data(client,
+ FSCHMD_REG_CONTROL);
+ data->watchdog_control = i2c_smbus_read_byte_data(client,
+ FSCHMD_REG_WDOG_CONTROL);
+ data->watchdog_state = i2c_smbus_read_byte_data(client,
+ FSCHMD_REG_WDOG_STATE);
+ data->watchdog_preset = i2c_smbus_read_byte_data(client,
+ FSCHMD_REG_WDOG_PRESET);
+
/* i2c kind goes from 1-5, we want from 0-4 to address arrays */
data->kind = kind - 1;
@@ -735,9 +1053,43 @@ static int fschmd_probe(struct i2c_client *client,
goto exit_detach;
}
- revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
- printk(KERN_INFO FSCHMD_NAME ": Detected FSC %s chip, revision: %d\n",
- names[data->kind], (int) revision);
+ /* We take the data_mutex lock early so that watchdog_open() cannot
+ run when misc_register() has completed, but we've not yet added
+ our data to the watchdog_data_list (and set the default timeout) */
+ mutex_lock(&watchdog_data_mutex);
+ for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) {
+ /* Register our watchdog part */
+ snprintf(data->watchdog_name, sizeof(data->watchdog_name),
+ "watchdog%c", (i == 0) ? '\0' : ('0' + i));
+ data->watchdog_miscdev.name = data->watchdog_name;
+ data->watchdog_miscdev.fops = &watchdog_fops;
+ data->watchdog_miscdev.minor = watchdog_minors[i];
+ err = misc_register(&data->watchdog_miscdev);
+ if (err == -EBUSY)
+ continue;
+ if (err) {
+ data->watchdog_miscdev.minor = 0;
+ dev_err(&client->dev,
+ "Registering watchdog chardev: %d\n", err);
+ break;
+ }
+
+ list_add(&data->list, &watchdog_data_list);
+ watchdog_set_timeout(data, 60);
+ dev_info(&client->dev,
+ "Registered watchdog chardev major 10, minor: %d\n",
+ watchdog_minors[i]);
+ break;
+ }
+ if (i == ARRAY_SIZE(watchdog_minors)) {
+ data->watchdog_miscdev.minor = 0;
+ dev_warn(&client->dev, "Couldn't register watchdog chardev "
+ "(due to no free minor)\n");
+ }
+ mutex_unlock(&watchdog_data_mutex);
+
+ dev_info(&client->dev, "Detected FSC %s chip, revision: %d\n",
+ names[data->kind], (int) data->revision);
return 0;
@@ -751,6 +1103,24 @@ static int fschmd_remove(struct i2c_client *client)
struct fschmd_data *data = i2c_get_clientdata(client);
int i;
+ /* Unregister the watchdog (if registered) */
+ if (data->watchdog_miscdev.minor) {
+ misc_deregister(&data->watchdog_miscdev);
+ if (data->watchdog_is_open) {
+ dev_warn(&client->dev,
+ "i2c client detached with watchdog open! "
+ "Stopping watchdog.\n");
+ watchdog_stop(data);
+ }
+ mutex_lock(&watchdog_data_mutex);
+ list_del(&data->list);
+ mutex_unlock(&watchdog_data_mutex);
+ /* Tell the watchdog code the client is gone */
+ mutex_lock(&data->watchdog_lock);
+ data->client = NULL;
+ mutex_unlock(&data->watchdog_lock);
+ }
+
/* Check if registered in case we're called from fschmd_detect
to cleanup after an error */
if (data->hwmon_dev)
@@ -765,7 +1135,10 @@ static int fschmd_remove(struct i2c_client *client)
device_remove_file(&client->dev,
&fschmd_fan_attr[i].dev_attr);
- kfree(data);
+ mutex_lock(&watchdog_data_mutex);
+ kref_put(&data->kref, fschmd_release_resources);
+ mutex_unlock(&watchdog_data_mutex);
+
return 0;
}
@@ -798,7 +1171,7 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
data->temp_act[i] < data->temp_max[i])
i2c_smbus_write_byte_data(client,
FSCHMD_REG_TEMP_STATE[data->kind][i],
- FSCHMD_TEMP_ALERT_MASK);
+ FSCHMD_TEMP_ALERT);
}
for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) {
@@ -816,28 +1189,17 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
FSCHMD_REG_FAN_MIN[data->kind][i]);
/* reset fan status if speed is back to > 0 */
- if ((data->fan_status[i] & FSCHMD_FAN_ALARM_MASK) &&
+ if ((data->fan_status[i] & FSCHMD_FAN_ALARM) &&
data->fan_act[i])
i2c_smbus_write_byte_data(client,
FSCHMD_REG_FAN_STATE[data->kind][i],
- FSCHMD_FAN_ALARM_MASK);
+ FSCHMD_FAN_ALARM);
}
for (i = 0; i < 3; i++)
data->volt[i] = i2c_smbus_read_byte_data(client,
FSCHMD_REG_VOLT[i]);
- data->global_control = i2c_smbus_read_byte_data(client,
- FSCHMD_REG_CONTROL);
-
- /* To be implemented in the future
- data->watchdog[0] = i2c_smbus_read_byte_data(client,
- FSCHMD_REG_WDOG_PRESET);
- data->watchdog[1] = i2c_smbus_read_byte_data(client,
- FSCHMD_REG_WDOG_STATE);
- data->watchdog[2] = i2c_smbus_read_byte_data(client,
- FSCHMD_REG_WDOG_CONTROL); */
-
data->last_updated = jiffies;
data->valid = 1;
}
@@ -857,7 +1219,7 @@ static void __exit fschmd_exit(void)
i2c_del_driver(&fschmd_driver);
}
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and "
"Heimdall driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
new file mode 100644
index 000000000000..abf4dfc8ec22
--- /dev/null
+++ b/drivers/hwmon/hp_accel.c
@@ -0,0 +1,339 @@
+/*
+ * hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
+ *
+ * Copyright (C) 2007-2008 Yan Burman
+ * Copyright (C) 2008 Eric Piel
+ * Copyright (C) 2008-2009 Pavel Machek
+ *
+ * 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
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/kthread.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/freezer.h>
+#include <linux/version.h>
+#include <linux/uaccess.h>
+#include <linux/leds.h>
+#include <acpi/acpi_drivers.h>
+#include <asm/atomic.h>
+#include "lis3lv02d.h"
+
+#define DRIVER_NAME "lis3lv02d"
+#define ACPI_MDPS_CLASS "accelerometer"
+
+/* Delayed LEDs infrastructure ------------------------------------ */
+
+/* Special LED class that can defer work */
+struct delayed_led_classdev {
+ struct led_classdev led_classdev;
+ struct work_struct work;
+ enum led_brightness new_brightness;
+
+ unsigned int led; /* For driver */
+ void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
+};
+
+static inline void delayed_set_status_worker(struct work_struct *work)
+{
+ struct delayed_led_classdev *data =
+ container_of(work, struct delayed_led_classdev, work);
+
+ data->set_brightness(data, data->new_brightness);
+}
+
+static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct delayed_led_classdev *data = container_of(led_cdev,
+ struct delayed_led_classdev, led_classdev);
+ data->new_brightness = brightness;
+ schedule_work(&data->work);
+}
+
+/* HP-specific accelerometer driver ------------------------------------ */
+
+/* For automatic insertion of the module */
+static struct acpi_device_id lis3lv02d_device_ids[] = {
+ {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+ {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
+
+
+/**
+ * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
+ * @handle: the handle of the device
+ *
+ * Returns AE_OK on success.
+ */
+acpi_status lis3lv02d_acpi_init(acpi_handle handle)
+{
+ return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL);
+}
+
+/**
+ * lis3lv02d_acpi_read - ACPI ALRD method: read a register
+ * @handle: the handle of the device
+ * @reg: the register to read
+ * @ret: result of the operation
+ *
+ * Returns AE_OK on success.
+ */
+acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret)
+{
+ union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+ struct acpi_object_list args = { 1, &arg0 };
+ unsigned long long lret;
+ acpi_status status;
+
+ arg0.integer.value = reg;
+
+ status = acpi_evaluate_integer(handle, "ALRD", &args, &lret);
+ *ret = lret;
+ return status;
+}
+
+/**
+ * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
+ * @handle: the handle of the device
+ * @reg: the register to write to
+ * @val: the value to write
+ *
+ * Returns AE_OK on success.
+ */
+acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val)
+{
+ unsigned long long ret; /* Not used when writting */
+ union acpi_object in_obj[2];
+ struct acpi_object_list args = { 2, in_obj };
+
+ in_obj[0].type = ACPI_TYPE_INTEGER;
+ in_obj[0].integer.value = reg;
+ in_obj[1].type = ACPI_TYPE_INTEGER;
+ in_obj[1].integer.value = val;
+
+ return acpi_evaluate_integer(handle, "ALWR", &args, &ret);
+}
+
+static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
+{
+ adev.ac = *((struct axis_conversion *)dmi->driver_data);
+ printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
+
+ return 1;
+}
+
+/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
+ * If the value is negative, the opposite of the hw value is used. */
+static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
+static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
+static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
+static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
+static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3};
+static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
+
+#define AXIS_DMI_MATCH(_ident, _name, _axis) { \
+ .ident = _ident, \
+ .callback = lis3lv02d_dmi_matched, \
+ .matches = { \
+ DMI_MATCH(DMI_PRODUCT_NAME, _name) \
+ }, \
+ .driver_data = &lis3lv02d_axis_##_axis \
+}
+static struct dmi_system_id lis3lv02d_dmi_ids[] = {
+ /* product names are truncated to match all kinds of a same model */
+ AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
+ AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
+ AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
+ AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
+ AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
+ AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
+ AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
+ AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
+ AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
+ AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
+ AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
+ { NULL, }
+/* Laptop models without axis info (yet):
+ * "NC6910" "HP Compaq 6910"
+ * HP Compaq 8710x Notebook PC / Mobile Workstation
+ * "NC2400" "HP Compaq nc2400"
+ * "NX74x0" "HP Compaq nx74"
+ * "NX6325" "HP Compaq nx6325"
+ * "NC4400" "HP Compaq nc4400"
+ */
+};
+
+static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
+{
+ acpi_handle handle = adev.device->handle;
+ unsigned long long ret; /* Not used when writing */
+ union acpi_object in_obj[1];
+ struct acpi_object_list args = { 1, in_obj };
+
+ in_obj[0].type = ACPI_TYPE_INTEGER;
+ in_obj[0].integer.value = !!value;
+
+ acpi_evaluate_integer(handle, "ALED", &args, &ret);
+}
+
+static struct delayed_led_classdev hpled_led = {
+ .led_classdev = {
+ .name = "hp::hddprotect",
+ .default_trigger = "none",
+ .brightness_set = delayed_sysfs_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+ },
+ .set_brightness = hpled_set,
+};
+
+static int lis3lv02d_add(struct acpi_device *device)
+{
+ u8 val;
+ int ret;
+
+ if (!device)
+ return -EINVAL;
+
+ adev.device = device;
+ adev.init = lis3lv02d_acpi_init;
+ adev.read = lis3lv02d_acpi_read;
+ adev.write = lis3lv02d_acpi_write;
+ strcpy(acpi_device_name(device), DRIVER_NAME);
+ strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
+ device->driver_data = &adev;
+
+ lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val);
+ if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) {
+ printk(KERN_ERR DRIVER_NAME
+ ": Accelerometer chip not LIS3LV02D{L,Q}\n");
+ }
+
+ /* If possible use a "standard" axes order */
+ if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+ printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
+ "using default axes configuration\n");
+ adev.ac = lis3lv02d_axis_normal;
+ }
+
+ INIT_WORK(&hpled_led.work, delayed_set_status_worker);
+ ret = led_classdev_register(NULL, &hpled_led.led_classdev);
+ if (ret)
+ return ret;
+
+ ret = lis3lv02d_init_device(&adev);
+ if (ret) {
+ flush_work(&hpled_led.work);
+ led_classdev_unregister(&hpled_led.led_classdev);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int lis3lv02d_remove(struct acpi_device *device, int type)
+{
+ if (!device)
+ return -EINVAL;
+
+ lis3lv02d_joystick_disable();
+ lis3lv02d_poweroff(device->handle);
+
+ flush_work(&hpled_led.work);
+ led_classdev_unregister(&hpled_led.led_classdev);
+
+ return lis3lv02d_remove_fs();
+}
+
+
+#ifdef CONFIG_PM
+static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
+{
+ /* make sure the device is off when we suspend */
+ lis3lv02d_poweroff(device->handle);
+ return 0;
+}
+
+static int lis3lv02d_resume(struct acpi_device *device)
+{
+ /* put back the device in the right state (ACPI might turn it on) */
+ mutex_lock(&adev.lock);
+ if (adev.usage > 0)
+ lis3lv02d_poweron(device->handle);
+ else
+ lis3lv02d_poweroff(device->handle);
+ mutex_unlock(&adev.lock);
+ return 0;
+}
+#else
+#define lis3lv02d_suspend NULL
+#define lis3lv02d_resume NULL
+#endif
+
+/* For the HP MDPS aka 3D Driveguard */
+static struct acpi_driver lis3lv02d_driver = {
+ .name = DRIVER_NAME,
+ .class = ACPI_MDPS_CLASS,
+ .ids = lis3lv02d_device_ids,
+ .ops = {
+ .add = lis3lv02d_add,
+ .remove = lis3lv02d_remove,
+ .suspend = lis3lv02d_suspend,
+ .resume = lis3lv02d_resume,
+ }
+};
+
+static int __init lis3lv02d_init_module(void)
+{
+ int ret;
+
+ if (acpi_disabled)
+ return -ENODEV;
+
+ ret = acpi_bus_register_driver(&lis3lv02d_driver);
+ if (ret < 0)
+ return ret;
+
+ printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
+
+ return 0;
+}
+
+static void __exit lis3lv02d_exit_module(void)
+{
+ acpi_bus_unregister_driver(&lis3lv02d_driver);
+}
+
+MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init_module);
+module_exit(lis3lv02d_exit_module);
+
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 076a59cdabe9..e15c3e7b07e9 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -76,7 +76,7 @@ void hwmon_device_unregister(struct device *dev)
{
int id;
- if (likely(sscanf(dev->bus_id, HWMON_ID_FORMAT, &id) == 1)) {
+ if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) {
device_unregister(dev);
spin_lock(&idr_lock);
idr_remove(&hwmon_idr, id);
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index 2ede9388096b..27d7f72a5f11 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -490,6 +490,13 @@ static unsigned long chipset_ids[] = {
0
};
+static struct pci_device_id i5k_amb_ids[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, i5k_amb_ids);
+
static int __devinit i5k_amb_probe(struct platform_device *pdev)
{
struct i5k_amb_data *data;
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index 537d9fb2ff88..a36363312f2f 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -40,7 +40,7 @@
static inline u16 extract_value(const char *data, int offset)
{
- return be16_to_cpup((u16 *)&data[offset]);
+ return be16_to_cpup((__be16 *)&data[offset]);
}
#define TEMP_SENSOR 1
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index b74c95735f95..95a99c590da2 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -14,6 +14,7 @@
IT8712F Super I/O chip w/LPC interface
IT8716F Super I/O chip w/LPC interface
IT8718F Super I/O chip w/LPC interface
+ IT8720F Super I/O chip w/LPC interface
IT8726F Super I/O chip w/LPC interface
Sis950 A clone of the IT8705F
@@ -48,11 +49,12 @@
#include <linux/sysfs.h>
#include <linux/string.h>
#include <linux/dmi.h>
+#include <linux/acpi.h>
#include <asm/io.h>
#define DRVNAME "it87"
-enum chips { it87, it8712, it8716, it8718 };
+enum chips { it87, it8712, it8716, it8718, it8720 };
static unsigned short force_id;
module_param(force_id, ushort, 0);
@@ -64,7 +66,10 @@ static struct platform_device *pdev;
#define DEV 0x07 /* Register: Logical device select */
#define VAL 0x2f /* The value to read/write */
#define PME 0x04 /* The device with the fan registers in it */
-#define GPIO 0x07 /* The device with the IT8718F VID value in it */
+
+/* The device with the IT8718F/IT8720F VID value in it */
+#define GPIO 0x07
+
#define DEVID 0x20 /* Register: Device ID */
#define DEVREV 0x22 /* Register: Device Revision */
@@ -113,6 +118,7 @@ superio_exit(void)
#define IT8705F_DEVID 0x8705
#define IT8716F_DEVID 0x8716
#define IT8718F_DEVID 0x8718
+#define IT8720F_DEVID 0x8720
#define IT8726F_DEVID 0x8726
#define IT87_ACT_REG 0x30
#define IT87_BASE_REG 0x60
@@ -150,8 +156,8 @@ static int fix_pwm_polarity;
#define IT87_REG_ALARM2 0x02
#define IT87_REG_ALARM3 0x03
-/* The IT8718F has the VID value in a different register, in Super-I/O
- configuration space. */
+/* The IT8718F and IT8720F have the VID value in a different register, in
+ Super-I/O configuration space. */
#define IT87_REG_VID 0x0a
/* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b
for fan divisors. Later IT8712F revisions must use 16-bit tachometer
@@ -282,7 +288,8 @@ static inline int has_16bit_fans(const struct it87_data *data)
return (data->type == it87 && data->revision >= 0x03)
|| (data->type == it8712 && data->revision >= 0x08)
|| data->type == it8716
- || data->type == it8718;
+ || data->type == it8718
+ || data->type == it8720;
}
static int it87_probe(struct platform_device *pdev);
@@ -992,6 +999,9 @@ static int __init it87_find(unsigned short *address,
case IT8718F_DEVID:
sio_data->type = it8718;
break;
+ case IT8720F_DEVID:
+ sio_data->type = it8720;
+ break;
case 0xffff: /* No device at all */
goto exit;
default:
@@ -1022,7 +1032,8 @@ static int __init it87_find(unsigned short *address,
int reg;
superio_select(GPIO);
- if (chip_type == it8718)
+ if ((chip_type == it8718) ||
+ (chip_type == it8720))
sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
reg = superio_inb(IT87_SIO_PINX2_REG);
@@ -1068,6 +1079,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
"it8712",
"it8716",
"it8718",
+ "it8720",
};
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1226,7 +1238,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
}
if (data->type == it8712 || data->type == it8716
- || data->type == it8718) {
+ || data->type == it8718 || data->type == it8720) {
data->vrm = vid_which_vrm();
/* VID reading from Super-I/O config space if available */
data->vid = sio_data->vid_value;
@@ -1374,7 +1386,7 @@ static void __devinit it87_init_device(struct platform_device *pdev)
it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127);
}
- /* Check if temperature channnels are reset manually or by some reason */
+ /* Check if temperature channels are reset manually or by some reason */
tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE);
if ((tmp & 0x3f) == 0) {
/* Temp1,Temp3=thermistor; Temp2=thermal diode */
@@ -1513,7 +1525,8 @@ static struct it87_data *it87_update_device(struct device *dev)
data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
/* The 8705 does not have VID capability.
- The 8718 does not use IT87_REG_VID for the same purpose. */
+ The 8718 and the 8720 don't use IT87_REG_VID for the
+ same purpose. */
if (data->type == it8712 || data->type == it8716) {
data->vid = it87_read_value(data, IT87_REG_VID);
/* The older IT8712F revisions had only 5 VID pins,
@@ -1540,6 +1553,10 @@ static int __init it87_device_add(unsigned short address,
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
@@ -1608,7 +1625,7 @@ static void __exit sm_it87_exit(void)
MODULE_AUTHOR("Chris Gauthron, "
"Jean Delvare <khali@linux-fr.org>");
-MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8726F, SiS950 driver");
+MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F, SiS950 driver");
module_param(update_vbat, bool, 0);
MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
module_param(fix_pwm_polarity, bool, 0);
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index bd2bde0ef95e..1fe995111841 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -31,6 +31,7 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <asm/processor.h>
#define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000)
#define REG_TEMP 0xe4
@@ -47,6 +48,8 @@ struct k8temp_data {
/* registers values */
u8 sensorsp; /* sensor presence bits - SEL_CORE & SEL_PLACE */
u32 temp[2][2]; /* core, place */
+ u8 swap_core_select; /* meaning of SEL_CORE is inverted */
+ u32 temp_offset;
};
static struct k8temp_data *k8temp_update_device(struct device *dev)
@@ -114,10 +117,15 @@ static ssize_t show_temp(struct device *dev,
to_sensor_dev_attr_2(devattr);
int core = attr->nr;
int place = attr->index;
+ int temp;
struct k8temp_data *data = k8temp_update_device(dev);
- return sprintf(buf, "%d\n",
- TEMP_FROM_REG(data->temp[core][place]));
+ if (data->swap_core_select)
+ core = core ? 0 : 1;
+
+ temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
+
+ return sprintf(buf, "%d\n", temp);
}
/* core, place */
@@ -141,20 +149,49 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
int err;
u8 scfg;
u32 temp;
+ u8 model, stepping;
struct k8temp_data *data;
- u32 cpuid = cpuid_eax(1);
-
- /* this feature should be available since SH-C0 core */
- if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) {
- err = -ENODEV;
- goto exit;
- }
if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
+ model = boot_cpu_data.x86_model;
+ stepping = boot_cpu_data.x86_mask;
+
+ switch (boot_cpu_data.x86) {
+ case 0xf:
+ /* feature available since SH-C0, exclude older revisions */
+ if (((model == 4) && (stepping == 0)) ||
+ ((model == 5) && (stepping <= 1))) {
+ err = -ENODEV;
+ goto exit_free;
+ }
+
+ /*
+ * AMD NPT family 0fh, i.e. RevF and RevG:
+ * meaning of SEL_CORE bit is inverted
+ */
+ if (model >= 0x40) {
+ data->swap_core_select = 1;
+ dev_warn(&pdev->dev, "Temperature readouts might be "
+ "wrong - check erratum #141\n");
+ }
+
+ if ((model >= 0x69) &&
+ !(model == 0xc1 || model == 0x6c || model == 0x7c)) {
+ /*
+ * RevG desktop CPUs (i.e. no socket S1G1 parts)
+ * need additional offset, otherwise reported
+ * temperature is below ambient temperature
+ */
+ data->temp_offset = 21000;
+ }
+
+ break;
+ }
+
pci_read_config_byte(pdev, REG_TEMP, &scfg);
scfg &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */
pci_write_config_byte(pdev, REG_TEMP, scfg);
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index c002144c76bc..219d2d0d5a62 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2007-2008 Yan Burman
* Copyright (C) 2008 Eric Piel
+ * Copyright (C) 2008 Pavel Machek
*
* 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
@@ -39,7 +40,6 @@
#include "lis3lv02d.h"
#define DRIVER_NAME "lis3lv02d"
-#define ACPI_MDPS_CLASS "accelerometer"
/* joystick device poll interval in milliseconds */
#define MDPS_POLL_INTERVAL 50
@@ -55,100 +55,17 @@
/* Maximum value our axis may get for the input device (signed 12 bits) */
#define MDPS_MAX_VAL 2048
-struct axis_conversion {
- s8 x;
- s8 y;
- s8 z;
-};
-
-struct acpi_lis3lv02d {
- struct acpi_device *device; /* The ACPI device */
- struct input_dev *idev; /* input device */
- struct task_struct *kthread; /* kthread for input */
- struct mutex lock;
- struct platform_device *pdev; /* platform device */
- atomic_t count; /* interrupt count after last read */
- int xcalib; /* calibrated null value for x */
- int ycalib; /* calibrated null value for y */
- int zcalib; /* calibrated null value for z */
- unsigned char is_on; /* whether the device is on or off */
- unsigned char usage; /* usage counter */
- struct axis_conversion ac; /* hw -> logical axis */
-};
+struct acpi_lis3lv02d adev;
+EXPORT_SYMBOL_GPL(adev);
-static struct acpi_lis3lv02d adev;
-
-static int lis3lv02d_remove_fs(void);
static int lis3lv02d_add_fs(struct acpi_device *device);
-/* For automatic insertion of the module */
-static struct acpi_device_id lis3lv02d_device_ids[] = {
- {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
- {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
-
-/**
- * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
- * @handle: the handle of the device
- *
- * Returns AE_OK on success.
- */
-static inline acpi_status lis3lv02d_acpi_init(acpi_handle handle)
-{
- return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL);
-}
-
-/**
- * lis3lv02d_acpi_read - ACPI ALRD method: read a register
- * @handle: the handle of the device
- * @reg: the register to read
- * @ret: result of the operation
- *
- * Returns AE_OK on success.
- */
-static acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret)
-{
- union acpi_object arg0 = { ACPI_TYPE_INTEGER };
- struct acpi_object_list args = { 1, &arg0 };
- unsigned long long lret;
- acpi_status status;
-
- arg0.integer.value = reg;
-
- status = acpi_evaluate_integer(handle, "ALRD", &args, &lret);
- *ret = lret;
- return status;
-}
-
-/**
- * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
- * @handle: the handle of the device
- * @reg: the register to write to
- * @val: the value to write
- *
- * Returns AE_OK on success.
- */
-static acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val)
-{
- unsigned long long ret; /* Not used when writting */
- union acpi_object in_obj[2];
- struct acpi_object_list args = { 2, in_obj };
-
- in_obj[0].type = ACPI_TYPE_INTEGER;
- in_obj[0].integer.value = reg;
- in_obj[1].type = ACPI_TYPE_INTEGER;
- in_obj[1].integer.value = val;
-
- return acpi_evaluate_integer(handle, "ALWR", &args, &ret);
-}
-
static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
{
u8 lo, hi;
- lis3lv02d_acpi_read(handle, reg, &lo);
- lis3lv02d_acpi_read(handle, reg + 1, &hi);
+ adev.read(handle, reg, &lo);
+ adev.read(handle, reg + 1, &hi);
/* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
return (s16)((hi << 8) | lo);
}
@@ -190,54 +107,31 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
*z = lis3lv02d_get_axis(adev.ac.z, position);
}
-static inline void lis3lv02d_poweroff(acpi_handle handle)
+void lis3lv02d_poweroff(acpi_handle handle)
{
adev.is_on = 0;
/* disable X,Y,Z axis and power down */
- lis3lv02d_acpi_write(handle, CTRL_REG1, 0x00);
+ adev.write(handle, CTRL_REG1, 0x00);
}
+EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
-static void lis3lv02d_poweron(acpi_handle handle)
+void lis3lv02d_poweron(acpi_handle handle)
{
u8 val;
adev.is_on = 1;
- lis3lv02d_acpi_init(handle);
- lis3lv02d_acpi_write(handle, FF_WU_CFG, 0);
+ adev.init(handle);
+ adev.write(handle, FF_WU_CFG, 0);
/*
* BDU: LSB and MSB values are not updated until both have been read.
* So the value read will always be correct.
* IEN: Interrupt for free-fall and DD, not for data-ready.
*/
- lis3lv02d_acpi_read(handle, CTRL_REG2, &val);
+ adev.read(handle, CTRL_REG2, &val);
val |= CTRL2_BDU | CTRL2_IEN;
- lis3lv02d_acpi_write(handle, CTRL_REG2, val);
-}
-
-#ifdef CONFIG_PM
-static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
-{
- /* make sure the device is off when we suspend */
- lis3lv02d_poweroff(device->handle);
- return 0;
-}
-
-static int lis3lv02d_resume(struct acpi_device *device)
-{
- /* put back the device in the right state (ACPI might turn it on) */
- mutex_lock(&adev.lock);
- if (adev.usage > 0)
- lis3lv02d_poweron(device->handle);
- else
- lis3lv02d_poweroff(device->handle);
- mutex_unlock(&adev.lock);
- return 0;
+ adev.write(handle, CTRL_REG2, val);
}
-#else
-#define lis3lv02d_suspend NULL
-#define lis3lv02d_resume NULL
-#endif
-
+EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
/*
* To be called before starting to use the device. It makes sure that the
@@ -315,7 +209,7 @@ static inline void lis3lv02d_calibrate_joystick(void)
lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib);
}
-static int lis3lv02d_joystick_enable(void)
+int lis3lv02d_joystick_enable(void)
{
int err;
@@ -349,8 +243,9 @@ static int lis3lv02d_joystick_enable(void)
return err;
}
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
-static void lis3lv02d_joystick_disable(void)
+void lis3lv02d_joystick_disable(void)
{
if (!adev.idev)
return;
@@ -358,13 +253,13 @@ static void lis3lv02d_joystick_disable(void)
input_unregister_device(adev.idev);
adev.idev = NULL;
}
-
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
/*
* Initialise the accelerometer and the various subsystems.
* Should be rather independant of the bus system.
*/
-static int lis3lv02d_init_device(struct acpi_lis3lv02d *dev)
+int lis3lv02d_init_device(struct acpi_lis3lv02d *dev)
{
mutex_init(&dev->lock);
lis3lv02d_add_fs(dev->device);
@@ -376,93 +271,7 @@ static int lis3lv02d_init_device(struct acpi_lis3lv02d *dev)
lis3lv02d_decrease_use(dev);
return 0;
}
-
-static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
-{
- adev.ac = *((struct axis_conversion *)dmi->driver_data);
- printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
-
- return 1;
-}
-
-/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
- * If the value is negative, the opposite of the hw value is used. */
-static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
-static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
-
-#define AXIS_DMI_MATCH(_ident, _name, _axis) { \
- .ident = _ident, \
- .callback = lis3lv02d_dmi_matched, \
- .matches = { \
- DMI_MATCH(DMI_PRODUCT_NAME, _name) \
- }, \
- .driver_data = &lis3lv02d_axis_##_axis \
-}
-static struct dmi_system_id lis3lv02d_dmi_ids[] = {
- /* product names are truncated to match all kinds of a same model */
- AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
- AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
- AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
- AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
- AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
- AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
- AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
- { NULL, }
-/* Laptop models without axis info (yet):
- * "NC651xx" "HP Compaq 651"
- * "NC671xx" "HP Compaq 671"
- * "NC6910" "HP Compaq 6910"
- * HP Compaq 8710x Notebook PC / Mobile Workstation
- * "NC2400" "HP Compaq nc2400"
- * "NX74x0" "HP Compaq nx74"
- * "NX6325" "HP Compaq nx6325"
- * "NC4400" "HP Compaq nc4400"
- */
-};
-
-static int lis3lv02d_add(struct acpi_device *device)
-{
- u8 val;
-
- if (!device)
- return -EINVAL;
-
- adev.device = device;
- strcpy(acpi_device_name(device), DRIVER_NAME);
- strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
- device->driver_data = &adev;
-
- lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val);
- if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) {
- printk(KERN_ERR DRIVER_NAME
- ": Accelerometer chip not LIS3LV02D{L,Q}\n");
- }
-
- /* If possible use a "standard" axes order */
- if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
- printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
- "using default axes configuration\n");
- adev.ac = lis3lv02d_axis_normal;
- }
-
- return lis3lv02d_init_device(&adev);
-}
-
-static int lis3lv02d_remove(struct acpi_device *device, int type)
-{
- if (!device)
- return -EINVAL;
-
- lis3lv02d_joystick_disable();
- lis3lv02d_poweroff(device->handle);
-
- return lis3lv02d_remove_fs();
-}
-
+EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
/* Sysfs stuff */
static ssize_t lis3lv02d_position_show(struct device *dev,
@@ -501,7 +310,7 @@ static ssize_t lis3lv02d_rate_show(struct device *dev,
int val;
lis3lv02d_increase_use(&adev);
- lis3lv02d_acpi_read(adev.device->handle, CTRL_REG1, &ctrl);
+ adev.read(adev.device->handle, CTRL_REG1, &ctrl);
lis3lv02d_decrease_use(&adev);
val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4;
return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]);
@@ -523,6 +332,7 @@ static struct attribute_group lis3lv02d_attribute_group = {
.attrs = lis3lv02d_attributes
};
+
static int lis3lv02d_add_fs(struct acpi_device *device)
{
adev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
@@ -532,50 +342,15 @@ static int lis3lv02d_add_fs(struct acpi_device *device)
return sysfs_create_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group);
}
-static int lis3lv02d_remove_fs(void)
+int lis3lv02d_remove_fs(void)
{
sysfs_remove_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group);
platform_device_unregister(adev.pdev);
return 0;
}
-
-/* For the HP MDPS aka 3D Driveguard */
-static struct acpi_driver lis3lv02d_driver = {
- .name = DRIVER_NAME,
- .class = ACPI_MDPS_CLASS,
- .ids = lis3lv02d_device_ids,
- .ops = {
- .add = lis3lv02d_add,
- .remove = lis3lv02d_remove,
- .suspend = lis3lv02d_suspend,
- .resume = lis3lv02d_resume,
- }
-};
-
-static int __init lis3lv02d_init_module(void)
-{
- int ret;
-
- if (acpi_disabled)
- return -ENODEV;
-
- ret = acpi_bus_register_driver(&lis3lv02d_driver);
- if (ret < 0)
- return ret;
-
- printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
-
- return 0;
-}
-
-static void __exit lis3lv02d_exit_module(void)
-{
- acpi_bus_unregister_driver(&lis3lv02d_driver);
-}
+EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
MODULE_AUTHOR("Yan Burman and Eric Piel");
MODULE_LICENSE("GPL");
-module_init(lis3lv02d_init_module);
-module_exit(lis3lv02d_exit_module);
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 330cfc60e948..223f1c0763bb 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -23,7 +23,7 @@
* The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
* be connected via SPI. There exists also several similar chips (such as LIS302DL or
* LIS3L02DQ) but not in the HP laptops and they have slightly different registers.
- * They can also be connected via I²C.
+ * They can also be connected via I²C.
*/
#define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */
@@ -147,3 +147,36 @@ enum lis3lv02d_dd_src {
DD_SRC_IA = 0x40,
};
+struct axis_conversion {
+ s8 x;
+ s8 y;
+ s8 z;
+};
+
+struct acpi_lis3lv02d {
+ struct acpi_device *device; /* The ACPI device */
+ acpi_status (*init) (acpi_handle handle);
+ acpi_status (*write) (acpi_handle handle, int reg, u8 val);
+ acpi_status (*read) (acpi_handle handle, int reg, u8 *ret);
+
+ struct input_dev *idev; /* input device */
+ struct task_struct *kthread; /* kthread for input */
+ struct mutex lock;
+ struct platform_device *pdev; /* platform device */
+ atomic_t count; /* interrupt count after last read */
+ int xcalib; /* calibrated null value for x */
+ int ycalib; /* calibrated null value for y */
+ int zcalib; /* calibrated null value for z */
+ unsigned char is_on; /* whether the device is on or off */
+ unsigned char usage; /* usage counter */
+ struct axis_conversion ac; /* hw -> logical axis */
+};
+
+int lis3lv02d_init_device(struct acpi_lis3lv02d *dev);
+int lis3lv02d_joystick_enable(void);
+void lis3lv02d_joystick_disable(void);
+void lis3lv02d_poweroff(acpi_handle handle);
+void lis3lv02d_poweron(acpi_handle handle);
+int lis3lv02d_remove_fs(void);
+
+extern struct acpi_lis3lv02d adev;
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index d435f003292d..ae6204f33214 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -37,9 +37,13 @@
#define DRVNAME "lm70"
+#define LM70_CHIP_LM70 0 /* original NS LM70 */
+#define LM70_CHIP_TMP121 1 /* TI TMP121/TMP123 */
+
struct lm70 {
struct device *hwmon_dev;
struct mutex lock;
+ unsigned int chip;
};
/* sysfs hook function */
@@ -47,7 +51,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct spi_device *spi = to_spi_device(dev);
- int status, val;
+ int status, val = 0;
u8 rxbuf[2];
s16 raw=0;
struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
@@ -65,12 +69,12 @@ static ssize_t lm70_sense_temp(struct device *dev,
"spi_write_then_read failed with status %d\n", status);
goto out;
}
- dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]);
-
- raw = (rxbuf[1] << 8) + rxbuf[0];
- dev_dbg(dev, "raw=0x%x\n", raw);
+ raw = (rxbuf[0] << 8) + rxbuf[1];
+ dev_dbg(dev, "rxbuf[0] : 0x%02x rxbuf[1] : 0x%02x raw=0x%04x\n",
+ rxbuf[0], rxbuf[1], raw);
/*
+ * LM70:
* The "raw" temperature read into rxbuf[] is a 16-bit signed 2's
* complement value. Only the MSB 11 bits (1 sign + 10 temperature
* bits) are meaningful; the LSB 5 bits are to be discarded.
@@ -80,8 +84,21 @@ static ssize_t lm70_sense_temp(struct device *dev,
* by 0.25. Also multiply by 1000 to represent in millidegrees
* Celsius.
* So it's equivalent to multiplying by 0.25 * 1000 = 250.
+ *
+ * TMP121/TMP123:
+ * 13 bits of 2's complement data, discard LSB 3 bits,
+ * resolution 0.0625 degrees celsius.
*/
- val = ((int)raw/32) * 250;
+ switch (p_lm70->chip) {
+ case LM70_CHIP_LM70:
+ val = ((int)raw / 32) * 250;
+ break;
+
+ case LM70_CHIP_TMP121:
+ val = ((int)raw / 8) * 625 / 10;
+ break;
+ }
+
status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */
out:
mutex_unlock(&p_lm70->lock);
@@ -93,27 +110,39 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL);
static ssize_t lm70_show_name(struct device *dev, struct device_attribute
*devattr, char *buf)
{
- return sprintf(buf, "lm70\n");
+ struct lm70 *p_lm70 = dev_get_drvdata(dev);
+ int ret;
+
+ switch (p_lm70->chip) {
+ case LM70_CHIP_LM70:
+ ret = sprintf(buf, "lm70\n");
+ break;
+ case LM70_CHIP_TMP121:
+ ret = sprintf(buf, "tmp121\n");
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
}
static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL);
/*----------------------------------------------------------------------*/
-static int __devinit lm70_probe(struct spi_device *spi)
+static int __devinit common_probe(struct spi_device *spi, int chip)
{
struct lm70 *p_lm70;
int status;
- /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */
- if ((spi->mode & (SPI_CPOL|SPI_CPHA)) || !(spi->mode & SPI_3WIRE))
- return -EINVAL;
+ /* NOTE: we assume 8-bit words, and convert to 16 bits manually */
p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
if (!p_lm70)
return -ENOMEM;
mutex_init(&p_lm70->lock);
+ p_lm70->chip = chip;
/* sysfs hook */
p_lm70->hwmon_dev = hwmon_device_register(&spi->dev);
@@ -141,6 +170,24 @@ out_dev_reg_failed:
return status;
}
+static int __devinit lm70_probe(struct spi_device *spi)
+{
+ /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */
+ if ((spi->mode & (SPI_CPOL | SPI_CPHA)) || !(spi->mode & SPI_3WIRE))
+ return -EINVAL;
+
+ return common_probe(spi, LM70_CHIP_LM70);
+}
+
+static int __devinit tmp121_probe(struct spi_device *spi)
+{
+ /* signaling is SPI_MODE_0 with only MISO connected */
+ if (spi->mode & (SPI_CPOL | SPI_CPHA))
+ return -EINVAL;
+
+ return common_probe(spi, LM70_CHIP_TMP121);
+}
+
static int __devexit lm70_remove(struct spi_device *spi)
{
struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
@@ -154,6 +201,15 @@ static int __devexit lm70_remove(struct spi_device *spi)
return 0;
}
+static struct spi_driver tmp121_driver = {
+ .driver = {
+ .name = "tmp121",
+ .owner = THIS_MODULE,
+ },
+ .probe = tmp121_probe,
+ .remove = __devexit_p(lm70_remove),
+};
+
static struct spi_driver lm70_driver = {
.driver = {
.name = "lm70",
@@ -165,17 +221,26 @@ static struct spi_driver lm70_driver = {
static int __init init_lm70(void)
{
- return spi_register_driver(&lm70_driver);
+ int ret = spi_register_driver(&lm70_driver);
+ if (ret)
+ return ret;
+
+ ret = spi_register_driver(&tmp121_driver);
+ if (ret)
+ spi_unregister_driver(&lm70_driver);
+
+ return ret;
}
static void __exit cleanup_lm70(void)
{
spi_unregister_driver(&lm70_driver);
+ spi_unregister_driver(&tmp121_driver);
}
module_init(init_lm70);
module_exit(cleanup_lm70);
MODULE_AUTHOR("Kaiwan N Billimoria");
-MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver");
+MODULE_DESCRIPTION("NS LM70 / TI TMP121/TMP123 Linux driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 8f9595f2fb53..55bd87c15c9a 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -190,7 +190,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
dev_info(&client->dev, "%s: sensor '%s'\n",
- data->hwmon_dev->bus_id, client->name);
+ dev_name(data->hwmon_dev), client->name);
return 0;
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
new file mode 100644
index 000000000000..034b2c515848
--- /dev/null
+++ b/drivers/hwmon/ltc4245.c
@@ -0,0 +1,567 @@
+/*
+ * Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller
+ *
+ * Copyright (C) 2008 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This driver is based on the ds1621 and ina209 drivers.
+ *
+ * Datasheet:
+ * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/* Valid addresses are 0x20 - 0x3f
+ *
+ * For now, we do not probe, since some of these addresses
+ * are known to be unfriendly to probing */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(ltc4245);
+
+/* Here are names of the chip's registers (a.k.a. commands) */
+enum ltc4245_cmd {
+ LTC4245_STATUS = 0x00, /* readonly */
+ LTC4245_ALERT = 0x01,
+ LTC4245_CONTROL = 0x02,
+ LTC4245_ON = 0x03,
+ LTC4245_FAULT1 = 0x04,
+ LTC4245_FAULT2 = 0x05,
+ LTC4245_GPIO = 0x06,
+ LTC4245_ADCADR = 0x07,
+
+ LTC4245_12VIN = 0x10,
+ LTC4245_12VSENSE = 0x11,
+ LTC4245_12VOUT = 0x12,
+ LTC4245_5VIN = 0x13,
+ LTC4245_5VSENSE = 0x14,
+ LTC4245_5VOUT = 0x15,
+ LTC4245_3VIN = 0x16,
+ LTC4245_3VSENSE = 0x17,
+ LTC4245_3VOUT = 0x18,
+ LTC4245_VEEIN = 0x19,
+ LTC4245_VEESENSE = 0x1a,
+ LTC4245_VEEOUT = 0x1b,
+ LTC4245_GPIOADC1 = 0x1c,
+ LTC4245_GPIOADC2 = 0x1d,
+ LTC4245_GPIOADC3 = 0x1e,
+};
+
+struct ltc4245_data {
+ struct device *hwmon_dev;
+
+ struct mutex update_lock;
+ bool valid;
+ unsigned long last_updated; /* in jiffies */
+
+ /* Control registers */
+ u8 cregs[0x08];
+
+ /* Voltage registers */
+ u8 vregs[0x0f];
+};
+
+static struct ltc4245_data *ltc4245_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ltc4245_data *data = i2c_get_clientdata(client);
+ s32 val;
+ int i;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+
+ dev_dbg(&client->dev, "Starting ltc4245 update\n");
+
+ /* Read control registers -- 0x00 to 0x07 */
+ for (i = 0; i < ARRAY_SIZE(data->cregs); i++) {
+ val = i2c_smbus_read_byte_data(client, i);
+ if (unlikely(val < 0))
+ data->cregs[i] = 0;
+ else
+ data->cregs[i] = val;
+ }
+
+ /* Read voltage registers -- 0x10 to 0x1f */
+ for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
+ val = i2c_smbus_read_byte_data(client, i+0x10);
+ if (unlikely(val < 0))
+ data->vregs[i] = 0;
+ else
+ data->vregs[i] = val;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+/* Return the voltage from the given register in millivolts */
+static int ltc4245_get_voltage(struct device *dev, u8 reg)
+{
+ struct ltc4245_data *data = ltc4245_update_device(dev);
+ const u8 regval = data->vregs[reg - 0x10];
+ u32 voltage = 0;
+
+ switch (reg) {
+ case LTC4245_12VIN:
+ case LTC4245_12VOUT:
+ voltage = regval * 55;
+ break;
+ case LTC4245_5VIN:
+ case LTC4245_5VOUT:
+ voltage = regval * 22;
+ break;
+ case LTC4245_3VIN:
+ case LTC4245_3VOUT:
+ voltage = regval * 15;
+ break;
+ case LTC4245_VEEIN:
+ case LTC4245_VEEOUT:
+ voltage = regval * -55;
+ break;
+ case LTC4245_GPIOADC1:
+ case LTC4245_GPIOADC2:
+ case LTC4245_GPIOADC3:
+ voltage = regval * 10;
+ break;
+ default:
+ /* If we get here, the developer messed up */
+ WARN_ON_ONCE(1);
+ break;
+ }
+
+ return voltage;
+}
+
+/* Return the current in the given sense register in milliAmperes */
+static unsigned int ltc4245_get_current(struct device *dev, u8 reg)
+{
+ struct ltc4245_data *data = ltc4245_update_device(dev);
+ const u8 regval = data->vregs[reg - 0x10];
+ unsigned int voltage;
+ unsigned int curr;
+
+ /* The strange looking conversions that follow are fixed-point
+ * math, since we cannot do floating point in the kernel.
+ *
+ * Step 1: convert sense register to microVolts
+ * Step 2: convert voltage to milliAmperes
+ *
+ * If you play around with the V=IR equation, you come up with
+ * the following: X uV / Y mOhm == Z mA
+ *
+ * With the resistors that are fractions of a milliOhm, we multiply
+ * the voltage and resistance by 10, to shift the decimal point.
+ * Now we can use the normal division operator again.
+ */
+
+ switch (reg) {
+ case LTC4245_12VSENSE:
+ voltage = regval * 250; /* voltage in uV */
+ curr = voltage / 50; /* sense resistor 50 mOhm */
+ break;
+ case LTC4245_5VSENSE:
+ voltage = regval * 125; /* voltage in uV */
+ curr = (voltage * 10) / 35; /* sense resistor 3.5 mOhm */
+ break;
+ case LTC4245_3VSENSE:
+ voltage = regval * 125; /* voltage in uV */
+ curr = (voltage * 10) / 25; /* sense resistor 2.5 mOhm */
+ break;
+ case LTC4245_VEESENSE:
+ voltage = regval * 250; /* voltage in uV */
+ curr = voltage / 100; /* sense resistor 100 mOhm */
+ break;
+ default:
+ /* If we get here, the developer messed up */
+ WARN_ON_ONCE(1);
+ curr = 0;
+ break;
+ }
+
+ return curr;
+}
+
+static ssize_t ltc4245_show_voltage(struct device *dev,
+ struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ const int voltage = ltc4245_get_voltage(dev, attr->index);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", voltage);
+}
+
+static ssize_t ltc4245_show_current(struct device *dev,
+ struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ const unsigned int curr = ltc4245_get_current(dev, attr->index);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", curr);
+}
+
+static ssize_t ltc4245_show_power(struct device *dev,
+ struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ const unsigned int curr = ltc4245_get_current(dev, attr->index);
+ const int output_voltage = ltc4245_get_voltage(dev, attr->index+1);
+
+ /* current in mA * voltage in mV == power in uW */
+ const unsigned int power = abs(output_voltage * curr);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", power);
+}
+
+static ssize_t ltc4245_show_alarm(struct device *dev,
+ struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
+ struct ltc4245_data *data = ltc4245_update_device(dev);
+ const u8 reg = data->cregs[attr->index];
+ const u32 mask = attr->nr;
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
+}
+
+/* These macros are used below in constructing device attribute objects
+ * for use with sysfs_create_group() to make a sysfs device file
+ * for each register.
+ */
+
+#define LTC4245_VOLTAGE(name, ltc4245_cmd_idx) \
+ static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+ ltc4245_show_voltage, NULL, ltc4245_cmd_idx)
+
+#define LTC4245_CURRENT(name, ltc4245_cmd_idx) \
+ static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+ ltc4245_show_current, NULL, ltc4245_cmd_idx)
+
+#define LTC4245_POWER(name, ltc4245_cmd_idx) \
+ static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+ ltc4245_show_power, NULL, ltc4245_cmd_idx)
+
+#define LTC4245_ALARM(name, mask, reg) \
+ static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \
+ ltc4245_show_alarm, NULL, (mask), reg)
+
+/* Construct a sensor_device_attribute structure for each register */
+
+/* Input voltages */
+LTC4245_VOLTAGE(in1_input, LTC4245_12VIN);
+LTC4245_VOLTAGE(in2_input, LTC4245_5VIN);
+LTC4245_VOLTAGE(in3_input, LTC4245_3VIN);
+LTC4245_VOLTAGE(in4_input, LTC4245_VEEIN);
+
+/* Input undervoltage alarms */
+LTC4245_ALARM(in1_min_alarm, (1 << 0), LTC4245_FAULT1);
+LTC4245_ALARM(in2_min_alarm, (1 << 1), LTC4245_FAULT1);
+LTC4245_ALARM(in3_min_alarm, (1 << 2), LTC4245_FAULT1);
+LTC4245_ALARM(in4_min_alarm, (1 << 3), LTC4245_FAULT1);
+
+/* Currents (via sense resistor) */
+LTC4245_CURRENT(curr1_input, LTC4245_12VSENSE);
+LTC4245_CURRENT(curr2_input, LTC4245_5VSENSE);
+LTC4245_CURRENT(curr3_input, LTC4245_3VSENSE);
+LTC4245_CURRENT(curr4_input, LTC4245_VEESENSE);
+
+/* Overcurrent alarms */
+LTC4245_ALARM(curr1_max_alarm, (1 << 4), LTC4245_FAULT1);
+LTC4245_ALARM(curr2_max_alarm, (1 << 5), LTC4245_FAULT1);
+LTC4245_ALARM(curr3_max_alarm, (1 << 6), LTC4245_FAULT1);
+LTC4245_ALARM(curr4_max_alarm, (1 << 7), LTC4245_FAULT1);
+
+/* Output voltages */
+LTC4245_VOLTAGE(in5_input, LTC4245_12VOUT);
+LTC4245_VOLTAGE(in6_input, LTC4245_5VOUT);
+LTC4245_VOLTAGE(in7_input, LTC4245_3VOUT);
+LTC4245_VOLTAGE(in8_input, LTC4245_VEEOUT);
+
+/* Power Bad alarms */
+LTC4245_ALARM(in5_min_alarm, (1 << 0), LTC4245_FAULT2);
+LTC4245_ALARM(in6_min_alarm, (1 << 1), LTC4245_FAULT2);
+LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2);
+LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2);
+
+/* GPIO voltages */
+LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC1);
+LTC4245_VOLTAGE(in10_input, LTC4245_GPIOADC2);
+LTC4245_VOLTAGE(in11_input, LTC4245_GPIOADC3);
+
+/* Power Consumption (virtual) */
+LTC4245_POWER(power1_input, LTC4245_12VSENSE);
+LTC4245_POWER(power2_input, LTC4245_5VSENSE);
+LTC4245_POWER(power3_input, LTC4245_3VSENSE);
+LTC4245_POWER(power4_input, LTC4245_VEESENSE);
+
+/* Finally, construct an array of pointers to members of the above objects,
+ * as required for sysfs_create_group()
+ */
+static struct attribute *ltc4245_attributes[] = {
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+
+ &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+ &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
+ &sensor_dev_attr_in3_min_alarm.dev_attr.attr,
+ &sensor_dev_attr_in4_min_alarm.dev_attr.attr,
+
+ &sensor_dev_attr_curr1_input.dev_attr.attr,
+ &sensor_dev_attr_curr2_input.dev_attr.attr,
+ &sensor_dev_attr_curr3_input.dev_attr.attr,
+ &sensor_dev_attr_curr4_input.dev_attr.attr,
+
+ &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+ &sensor_dev_attr_curr2_max_alarm.dev_attr.attr,
+ &sensor_dev_attr_curr3_max_alarm.dev_attr.attr,
+ &sensor_dev_attr_curr4_max_alarm.dev_attr.attr,
+
+ &sensor_dev_attr_in5_input.dev_attr.attr,
+ &sensor_dev_attr_in6_input.dev_attr.attr,
+ &sensor_dev_attr_in7_input.dev_attr.attr,
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+
+ &sensor_dev_attr_in5_min_alarm.dev_attr.attr,
+ &sensor_dev_attr_in6_min_alarm.dev_attr.attr,
+ &sensor_dev_attr_in7_min_alarm.dev_attr.attr,
+ &sensor_dev_attr_in8_min_alarm.dev_attr.attr,
+
+ &sensor_dev_attr_in9_input.dev_attr.attr,
+ &sensor_dev_attr_in10_input.dev_attr.attr,
+ &sensor_dev_attr_in11_input.dev_attr.attr,
+
+ &sensor_dev_attr_power1_input.dev_attr.attr,
+ &sensor_dev_attr_power2_input.dev_attr.attr,
+ &sensor_dev_attr_power3_input.dev_attr.attr,
+ &sensor_dev_attr_power4_input.dev_attr.attr,
+
+ NULL,
+};
+
+static const struct attribute_group ltc4245_group = {
+ .attrs = ltc4245_attributes,
+};
+
+static int ltc4245_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ltc4245_data *data;
+ int ret;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto out_kzalloc;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ /* Initialize the LTC4245 chip */
+ /* TODO */
+
+ /* Register sysfs hooks */
+ ret = sysfs_create_group(&client->dev.kobj, &ltc4245_group);
+ if (ret)
+ goto out_sysfs_create_group;
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ ret = PTR_ERR(data->hwmon_dev);
+ goto out_hwmon_device_register;
+ }
+
+ return 0;
+
+out_hwmon_device_register:
+ sysfs_remove_group(&client->dev.kobj, &ltc4245_group);
+out_sysfs_create_group:
+ kfree(data);
+out_kzalloc:
+ return ret;
+}
+
+static int ltc4245_remove(struct i2c_client *client)
+{
+ struct ltc4245_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &ltc4245_group);
+
+ kfree(data);
+
+ return 0;
+}
+
+/* Check that some bits in a control register appear at all possible
+ * locations without changing value
+ *
+ * @client: the i2c client to use
+ * @reg: the register to read
+ * @bits: the bits to check (0xff checks all bits,
+ * 0x03 checks only the last two bits)
+ *
+ * return -ERRNO if the register read failed
+ * return -ENODEV if the register value doesn't stay constant at all
+ * possible addresses
+ *
+ * return 0 for success
+ */
+static int ltc4245_check_control_reg(struct i2c_client *client, u8 reg, u8 bits)
+{
+ int i;
+ s32 v, voff1, voff2;
+
+ /* Read register and check for error */
+ v = i2c_smbus_read_byte_data(client, reg);
+ if (v < 0)
+ return v;
+
+ v &= bits;
+
+ for (i = 0x00; i < 0xff; i += 0x20) {
+
+ voff1 = i2c_smbus_read_byte_data(client, reg + i);
+ if (voff1 < 0)
+ return voff1;
+
+ voff2 = i2c_smbus_read_byte_data(client, reg + i + 0x08);
+ if (voff2 < 0)
+ return voff2;
+
+ voff1 &= bits;
+ voff2 &= bits;
+
+ if (v != voff1 || v != voff2)
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int ltc4245_detect(struct i2c_client *client,
+ int kind,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ if (kind < 0) { /* probed detection - check the chip type */
+ s32 v; /* 8 bits from the chip, or -ERRNO */
+
+ /* Chip registers 0x00-0x07 are control registers
+ * Chip registers 0x10-0x1f are data registers
+ *
+ * Address bits b7-b5 are ignored. This makes the chip "repeat"
+ * in steps of 0x20. Any control registers should appear with
+ * the same values across all duplicated addresses.
+ *
+ * Register 0x02 bit b2 is reserved, expect 0
+ * Register 0x07 bits b7 to b4 are reserved, expect 0
+ *
+ * Registers 0x01, 0x02 are control registers and should not
+ * change on their own.
+ *
+ * Register 0x06 bits b6 and b7 are control bits, and should
+ * not change on their own.
+ *
+ * Register 0x07 bits b3 to b0 are control bits, and should
+ * not change on their own.
+ */
+
+ /* read register 0x02 reserved bit, expect 0 */
+ v = i2c_smbus_read_byte_data(client, LTC4245_CONTROL);
+ if (v < 0 || (v & 0x04) != 0)
+ return -ENODEV;
+
+ /* read register 0x07 reserved bits, expect 0 */
+ v = i2c_smbus_read_byte_data(client, LTC4245_ADCADR);
+ if (v < 0 || (v & 0xf0) != 0)
+ return -ENODEV;
+
+ /* check that the alert register appears at all locations */
+ if (ltc4245_check_control_reg(client, LTC4245_ALERT, 0xff))
+ return -ENODEV;
+
+ /* check that the control register appears at all locations */
+ if (ltc4245_check_control_reg(client, LTC4245_CONTROL, 0xff))
+ return -ENODEV;
+
+ /* check that register 0x06 bits b6 and b7 stay constant */
+ if (ltc4245_check_control_reg(client, LTC4245_GPIO, 0xc0))
+ return -ENODEV;
+
+ /* check that register 0x07 bits b3-b0 stay constant */
+ if (ltc4245_check_control_reg(client, LTC4245_ADCADR, 0x0f))
+ return -ENODEV;
+ }
+
+ strlcpy(info->type, "ltc4245", I2C_NAME_SIZE);
+ dev_info(&adapter->dev, "ltc4245 %s at address 0x%02x\n",
+ kind < 0 ? "probed" : "forced",
+ client->addr);
+
+ return 0;
+}
+
+static const struct i2c_device_id ltc4245_id[] = {
+ { "ltc4245", ltc4245 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ltc4245_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc4245_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "ltc4245",
+ },
+ .probe = ltc4245_probe,
+ .remove = ltc4245_remove,
+ .id_table = ltc4245_id,
+ .detect = ltc4245_detect,
+ .address_data = &addr_data,
+};
+
+static int __init ltc4245_init(void)
+{
+ return i2c_add_driver(&ltc4245_driver);
+}
+
+static void __exit ltc4245_exit(void)
+{
+ i2c_del_driver(&ltc4245_driver);
+}
+
+MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
+MODULE_DESCRIPTION("LTC4245 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ltc4245_init);
+module_exit(ltc4245_exit);
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 5fbfa34c110e..fb052fea3744 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -43,6 +43,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static u8 devid;
@@ -1627,6 +1628,11 @@ static int __init pc87360_device_add(unsigned short address)
continue;
res.start = extra_isa[i];
res.end = extra_isa[i] + PC87360_EXTENT - 1;
+
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit_device_put;
+
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR "pc87360: Device resource[%d] "
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index 7265f22ae5cd..3a8a0f7a7736 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -32,6 +32,7 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/ioport.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static unsigned short force_id;
@@ -524,6 +525,10 @@ static int __init pc87427_device_add(unsigned short address)
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index a276806f3d53..aa2e8318f167 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -62,6 +62,7 @@
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/acpi.h>
#include <asm/io.h>
@@ -727,6 +728,10 @@ static int __devinit sis5595_device_add(unsigned short address)
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc("sis5595", address);
if (!pdev) {
err = -ENOMEM;
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index eb03544c731c..6f6d52b4fb64 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -36,6 +36,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mutex.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static unsigned short force_id;
@@ -303,6 +304,10 @@ static int __init smsc47b397_device_add(unsigned short address)
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index d1b498548736..a92dbb97ee99 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static unsigned short force_id;
@@ -705,6 +706,10 @@ static int __init smsc47m1_device_add(unsigned short address,
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index f1ee5e731968..a022aedcaacb 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -41,6 +41,7 @@
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/acpi.h>
#include <asm/io.h>
@@ -783,6 +784,10 @@ static int __devinit via686a_device_add(unsigned short address)
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc("via686a", address);
if (!pdev) {
err = -ENOMEM;
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index 12b43590fa53..b0ce37852281 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -32,6 +32,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/ioport.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static int uch_config = -1;
@@ -1259,6 +1260,10 @@ static int __init vt1211_device_add(unsigned short address)
}
res.name = pdev->name;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto EXIT;
+
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 5bc57275cae8..9982b45fbb14 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -35,6 +35,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/acpi.h>
#include <asm/io.h>
static int force_addr;
@@ -894,6 +895,10 @@ static int __devinit vt8231_device_add(unsigned short address)
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc("vt8231", address);
if (!pdev) {
err = -ENOMEM;
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 075164dd65a7..cb808d015361 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -48,6 +48,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/acpi.h>
#include <asm/io.h>
#include "lm75.h"
@@ -502,7 +503,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
}
for (i = 0; i < 4; i++) {
- /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */
+ /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
if (i != 1) {
pwmcfg = w83627ehf_read_value(data,
W83627EHF_REG_PWM_ENABLE[i]);
@@ -1544,6 +1545,11 @@ static int __init sensors_w83627ehf_init(void)
res.start = address + IOREGION_OFFSET;
res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
res.flags = IORESOURCE_IO;
+
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index b30e5796cb26..389150ba30d3 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -50,6 +50,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/ioport.h>
+#include <linux/acpi.h>
#include <asm/io.h>
#include "lm75.h"
@@ -1793,6 +1794,10 @@ static int __init w83627hf_device_add(unsigned short address,
};
int err;
+ err = acpi_check_resource_conflict(&res);
+ if (err)
+ goto exit;
+
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index fc12bd412e3a..dbfb30c588d8 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -58,7 +58,10 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
0x2e, 0x2f, I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f);
-I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+
+static unsigned short force_subclients[4];
+module_param_array(force_subclients, short, NULL, 0);
+MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
static int reset;
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 5768def8a4f2..97851c5ba3a3 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -53,7 +53,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(w83791d);
-I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+
+static unsigned short force_subclients[4];
+module_param_array(force_subclients, short, NULL, 0);
+MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
static int reset;
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index cf94c5b0c879..2be16194ddf3 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -51,7 +51,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(w83792d);
-I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+
+static unsigned short force_subclients[4];
+module_param_array(force_subclients, short, NULL, 0);
+MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
static int init;
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 0a739f1c69be..47dd398f7258 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -42,7 +42,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(w83793);
-I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+
+static unsigned short force_subclients[4];
+module_param_array(force_subclients, short, NULL, 0);
+MODULE_PARM_DESC(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
static int reset;
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 75089febbc13..9fee3ca17344 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -83,7 +83,6 @@ static struct i2c_algo_bit_data ioc_data = {
};
static struct i2c_adapter ioc_ops = {
- .id = I2C_HW_B_IOC,
.algo_data = &ioc_data,
};
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index 9cead9b9458e..981e080b32ae 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -476,7 +476,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali1535_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_ALI1535,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index fc3e5b026423..f70f46582c6c 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -386,7 +386,6 @@ static const struct i2c_algorithm ali1563_algorithm = {
static struct i2c_adapter ali1563_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_ALI1563,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &ali1563_algorithm,
};
@@ -399,8 +398,8 @@ static int __devinit ali1563_probe(struct pci_dev * dev,
if ((error = ali1563_setup(dev)))
goto exit;
ali1563_adapter.dev.parent = &dev->dev;
- sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x",
- ali1563_smba);
+ snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name),
+ "SMBus ALi 1563 Adapter @ %04x", ali1563_smba);
if ((error = i2c_add_adapter(&ali1563_adapter)))
goto exit_shutdown;
return 0;
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 234fdde7d40e..39066dee46e3 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -473,7 +473,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_ALI15X3,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 8ba2bcf727d3..378fcb5d5783 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -197,8 +197,8 @@ static int __init amd756_s4882_init(void)
for (i = 1; i < 5; i++) {
s4882_algo[i] = *(amd756_smbus.algo);
s4882_adapter[i] = amd756_smbus;
- sprintf(s4882_adapter[i].name,
- "SMBus 8111 adapter (CPU%d)", i-1);
+ snprintf(s4882_adapter[i].name, sizeof(s4882_adapter[i].name),
+ "SMBus 8111 adapter (CPU%d)", i-1);
s4882_adapter[i].algo = s4882_algo+i;
s4882_adapter[i].dev.parent = amd756_smbus.dev.parent;
}
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 424dad6f18d8..220f4a1eee1d 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -298,7 +298,6 @@ static const struct i2c_algorithm smbus_algorithm = {
struct i2c_adapter amd756_smbus = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_AMD756,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -380,8 +379,9 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
/* set up the sysfs linkage to our parent device */
amd756_smbus.dev.parent = &pdev->dev;
- sprintf(amd756_smbus.name, "SMBus %s adapter at %04x",
- chipname[id->driver_data], amd756_ioport);
+ snprintf(amd756_smbus.name, sizeof(amd756_smbus.name),
+ "SMBus %s adapter at %04x", chipname[id->driver_data],
+ amd756_ioport);
error = i2c_add_adapter(&amd756_smbus);
if (error) {
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 3972208876b3..edab51973bf5 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -387,7 +387,6 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"SMBus2 AMD8111 adapter at %04x", smbus->base);
- smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index 9efb02137254..67d9dc5b351b 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -222,7 +222,7 @@ static int __devinit at91_i2c_probe(struct platform_device *pdev)
rc = -ENOMEM;
goto fail2;
}
- sprintf(adapter->name, "AT91");
+ snprintf(adapter->name, sizeof(adapter->name), "AT91");
adapter->algo = &at91_algorithm;
adapter->class = I2C_CLASS_HWMON;
adapter->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 66a04c2c660f..f78ce523e3db 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -400,7 +400,6 @@ i2c_au1550_probe(struct platform_device *pdev)
priv->xfer_timeout = 200;
priv->ack_timeout = 200;
- priv->adap.id = I2C_HW_AU1550_PSC;
priv->adap.nr = pdev->id;
priv->adap.algo = &au1550_algo;
priv->adap.algo_data = priv;
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 3c855ff2992f..fc548b3d002e 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -651,12 +651,11 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev)
iface->timeout_timer.data = (unsigned long)iface;
p_adap = &iface->adap;
- p_adap->id = I2C_HW_BLACKFIN;
p_adap->nr = pdev->id;
strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
p_adap->algo = &bfin_twi_algorithm;
p_adap->algo_data = iface;
- p_adap->class = I2C_CLASS_ALL;
+ p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
p_adap->dev.parent = &pdev->dev;
rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 0ed3ccb81b63..448b4bf35eb7 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -202,7 +202,6 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
static struct i2c_adapter pcf_isa_ops = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- .id = I2C_HW_P_ELEK,
.algo_data = &pcf_isa_data,
.name = "i2c-elektor",
};
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 648aa7baff83..bec9b845dd16 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -102,7 +102,6 @@ static struct i2c_algo_bit_data hydra_bit_data = {
static struct i2c_adapter hydra_adap = {
.owner = THIS_MODULE,
.name = "Hydra i2c",
- .id = I2C_HW_B_HYDRA,
.algo_data = &hydra_bit_data,
};
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 5123eb69a971..230238df56c4 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -64,7 +64,7 @@
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
/* I801 SMBus address offsets */
#define SMBHSTSTS (0 + i801_smba)
@@ -556,7 +556,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_I801,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -583,6 +582,40 @@ static struct pci_device_id i801_ids[] = {
MODULE_DEVICE_TABLE (pci, i801_ids);
+#if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE
+static unsigned char apanel_addr;
+
+/* Scan the system ROM for the signature "FJKEYINF" */
+static __init const void __iomem *bios_signature(const void __iomem *bios)
+{
+ ssize_t offset;
+ const unsigned char signature[] = "FJKEYINF";
+
+ for (offset = 0; offset < 0x10000; offset += 0x10) {
+ if (check_signature(bios + offset, signature,
+ sizeof(signature)-1))
+ return bios + offset;
+ }
+ return NULL;
+}
+
+static void __init input_apanel_init(void)
+{
+ void __iomem *bios;
+ const void __iomem *p;
+
+ bios = ioremap(0xF0000, 0x10000); /* Can't fail */
+ p = bios_signature(bios);
+ if (p) {
+ /* just use the first address */
+ apanel_addr = readb(p + 8 + 3) >> 1;
+ }
+ iounmap(bios);
+}
+#else
+static void __init input_apanel_init(void) {}
+#endif
+
static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
unsigned char temp;
@@ -667,6 +700,19 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
dev_err(&dev->dev, "Failed to add SMBus adapter\n");
goto exit_release;
}
+
+ /* Register optional slaves */
+#if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE
+ if (apanel_addr) {
+ struct i2c_board_info info;
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = apanel_addr;
+ strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE);
+ i2c_new_device(&i801_adapter, &info);
+ }
+#endif
+
return 0;
exit_release:
@@ -717,6 +763,7 @@ static struct pci_driver i801_driver = {
static int __init i2c_i801_init(void)
{
+ input_apanel_init();
return pci_register_driver(&i801_driver);
}
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 651f2f1ae5b7..88f0db73b364 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -746,7 +746,6 @@ static int __devinit iic_probe(struct of_device *ofdev,
adap->dev.parent = &ofdev->dev;
strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
i2c_set_adapdata(adap, dev);
- adap->id = I2C_HW_OCP;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->algo = &iic_algo;
adap->timeout = 1;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index fc2714ac0c0f..3190690c26ce 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -480,7 +480,6 @@ iop3xx_i2c_probe(struct platform_device *pdev)
}
memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
- new_adapter->id = I2C_HW_IOP3XX;
new_adapter->owner = THIS_MODULE;
new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
new_adapter->dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 05d72e981353..8e8467970481 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -116,7 +116,6 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
drv_data->algo_data.udelay = 6;
drv_data->algo_data.timeout = 100;
- drv_data->adapter.id = I2C_HW_B_IXP2000,
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
sizeof(drv_data->adapter.name));
drv_data->adapter.algo_data = &drv_data->algo_data,
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index a9a45fcc8544..aedbbe6618db 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -310,7 +310,6 @@ static const struct i2c_algorithm mpc_algo = {
static struct i2c_adapter mpc_ops = {
.owner = THIS_MODULE,
.name = "MPC adapter",
- .id = I2C_HW_MPC107,
.algo = &mpc_algo,
.timeout = 1,
};
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 9e8118d2fe64..eeda276f8f16 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -527,7 +527,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
goto exit_unmap_regs;
}
drv_data->adapter.dev.parent = &pd->dev;
- drv_data->adapter.id = I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
drv_data->adapter.owner = THIS_MODULE;
drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 3b19bc41a60b..05af6cd7f270 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -355,7 +355,6 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
return -EBUSY;
}
smbus->adapter.owner = THIS_MODULE;
- smbus->adapter.id = I2C_HW_SMBUS_NFORCE2;
smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 608038d64f81..be8ee2cac8bb 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -2,13 +2,16 @@
* TI OMAP I2C master mode driver
*
* Copyright (C) 2003 MontaVista Software, Inc.
- * Copyright (C) 2004 Texas Instruments.
- *
- * Updated to work with multiple I2C interfaces on 24xx by
- * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
+ * Copyright (C) 2004 - 2007 Texas Instruments.
*
- * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.com>
+ * Originally written by MontaVista Software, Inc.
+ * Additional contributions by:
+ * Tony Lindgren <tony@atomide.com>
+ * Imre Deak <imre.deak@nokia.com>
+ * Juha Yrjölä <juha.yrjola@solidboot.com>
+ * Syed Khasim <x0khasim@ti.com>
+ * Nishant Menon <nm@ti.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
@@ -33,8 +36,14 @@
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/io.h>
+
+/* I2C controller revisions */
+#define OMAP_I2C_REV_2 0x20
-#include <asm/io.h>
+/* I2C controller revisions present on specific hardware */
+#define OMAP_I2C_REV_ON_2430 0x36
+#define OMAP_I2C_REV_ON_3430 0x3C
/* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -43,6 +52,8 @@
#define OMAP_I2C_IE_REG 0x04
#define OMAP_I2C_STAT_REG 0x08
#define OMAP_I2C_IV_REG 0x0c
+/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
+#define OMAP_I2C_WE_REG 0x0c
#define OMAP_I2C_SYSS_REG 0x10
#define OMAP_I2C_BUF_REG 0x14
#define OMAP_I2C_CNT_REG 0x18
@@ -55,8 +66,11 @@
#define OMAP_I2C_SCLL_REG 0x34
#define OMAP_I2C_SCLH_REG 0x38
#define OMAP_I2C_SYSTEST_REG 0x3c
+#define OMAP_I2C_BUFSTAT_REG 0x40
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
+#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */
#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */
#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */
@@ -64,7 +78,8 @@
#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */
/* I2C Status Register (OMAP_I2C_STAT): */
-#define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */
+#define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */
+#define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */
#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */
#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */
#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */
@@ -76,13 +91,34 @@
#define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */
#define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */
+/* I2C WE wakeup enable register */
+#define OMAP_I2C_WE_XDR_WE (1 << 14) /* TX drain wakup */
+#define OMAP_I2C_WE_RDR_WE (1 << 13) /* RX drain wakeup */
+#define OMAP_I2C_WE_AAS_WE (1 << 9) /* Address as slave wakeup*/
+#define OMAP_I2C_WE_BF_WE (1 << 8) /* Bus free wakeup */
+#define OMAP_I2C_WE_STC_WE (1 << 6) /* Start condition wakeup */
+#define OMAP_I2C_WE_GC_WE (1 << 5) /* General call wakeup */
+#define OMAP_I2C_WE_DRDY_WE (1 << 3) /* TX/RX data ready wakeup */
+#define OMAP_I2C_WE_ARDY_WE (1 << 2) /* Reg access ready wakeup */
+#define OMAP_I2C_WE_NACK_WE (1 << 1) /* No acknowledgment wakeup */
+#define OMAP_I2C_WE_AL_WE (1 << 0) /* Arbitration lost wakeup */
+
+#define OMAP_I2C_WE_ALL (OMAP_I2C_WE_XDR_WE | OMAP_I2C_WE_RDR_WE | \
+ OMAP_I2C_WE_AAS_WE | OMAP_I2C_WE_BF_WE | \
+ OMAP_I2C_WE_STC_WE | OMAP_I2C_WE_GC_WE | \
+ OMAP_I2C_WE_DRDY_WE | OMAP_I2C_WE_ARDY_WE | \
+ OMAP_I2C_WE_NACK_WE | OMAP_I2C_WE_AL_WE)
+
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
+#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */
#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */
+#define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
+#define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */
#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@@ -91,6 +127,10 @@
#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */
#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */
+/* I2C SCL time value when Master */
+#define OMAP_I2C_SCLL_HSSCLL 8
+#define OMAP_I2C_SCLH_HSSCLH 8
+
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
#ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */
@@ -103,17 +143,19 @@
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
#endif
-/* I2C System Status register (OMAP_I2C_SYSS): */
-#define OMAP_I2C_SYSS_RDONE (1 << 0) /* Reset Done */
+/* OCP_SYSSTATUS bit definitions */
+#define SYSS_RESETDONE_MASK (1 << 0)
+
+/* OCP_SYSCONFIG bit definitions */
+#define SYSC_CLOCKACTIVITY_MASK (0x3 << 8)
+#define SYSC_SIDLEMODE_MASK (0x3 << 3)
+#define SYSC_ENAWAKEUP_MASK (1 << 2)
+#define SYSC_SOFTRESET_MASK (1 << 1)
+#define SYSC_AUTOIDLE_MASK (1 << 0)
-/* I2C System Configuration Register (OMAP_I2C_SYSC): */
-#define OMAP_I2C_SYSC_SRST (1 << 1) /* Soft Reset */
+#define SYSC_IDLEMODE_SMART 0x2
+#define SYSC_CLOCKACTIVITY_FCLK 0x2
-/* REVISIT: Use platform_data instead of module parameters */
-/* Fast Mode = 400 kHz, Standard = 100 kHz */
-static int clock = 100; /* Default: 100 kHz */
-module_param(clock, int, 0);
-MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
struct omap_i2c_dev {
struct device *dev;
@@ -123,11 +165,17 @@ struct omap_i2c_dev {
struct clk *fclk; /* Functional clock */
struct completion cmd_complete;
struct resource *ioarea;
+ u32 speed; /* Speed of bus in Khz */
u16 cmd_err;
u8 *buf;
size_t buf_len;
struct i2c_adapter adapter;
- unsigned rev1:1;
+ u8 fifo_size; /* use as flag and value
+ * fifo_size==0 implies no fifo
+ * if set, should be trsh+1
+ */
+ u8 rev;
+ unsigned b_hw:1; /* bad h/w fixes */
unsigned idle:1;
u16 iestate; /* Saved interrupt register */
};
@@ -143,9 +191,9 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
return __raw_readw(i2c_dev->base + reg);
}
-static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
{
- if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
dev->iclk = clk_get(dev->dev, "i2c_ick");
if (IS_ERR(dev->iclk)) {
dev->iclk = NULL;
@@ -178,25 +226,33 @@ static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
static void omap_i2c_unidle(struct omap_i2c_dev *dev)
{
+ WARN_ON(!dev->idle);
+
if (dev->iclk != NULL)
clk_enable(dev->iclk);
clk_enable(dev->fclk);
+ dev->idle = 0;
if (dev->iestate)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
- dev->idle = 0;
}
static void omap_i2c_idle(struct omap_i2c_dev *dev)
{
u16 iv;
- dev->idle = 1;
+ WARN_ON(dev->idle);
+
dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0);
- if (dev->rev1)
- iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
- else
+ if (dev->rev < OMAP_I2C_REV_2) {
+ iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
+ } else {
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate);
+
+ /* Flush posted write before the dev->idle store occurs */
+ omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+ }
+ dev->idle = 1;
clk_disable(dev->fclk);
if (dev->iclk != NULL)
clk_disable(dev->iclk);
@@ -204,18 +260,20 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
static int omap_i2c_init(struct omap_i2c_dev *dev)
{
- u16 psc = 0;
+ u16 psc = 0, scll = 0, sclh = 0;
+ u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
unsigned long fclk_rate = 12000000;
unsigned long timeout;
+ unsigned long internal_clk = 0;
- if (!dev->rev1) {
- omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+ if (dev->rev >= OMAP_I2C_REV_2) {
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
/* For some reason we need to set the EN bit before the
* reset done bit gets set. */
timeout = jiffies + OMAP_I2C_TIMEOUT;
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
- OMAP_I2C_SYSS_RDONE)) {
+ SYSS_RESETDONE_MASK)) {
if (time_after(jiffies, timeout)) {
dev_warn(dev->dev, "timeout waiting "
"for controller reset\n");
@@ -223,6 +281,33 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
}
msleep(1);
}
+
+ /* SYSC register is cleared by the reset; rewrite it */
+ if (dev->rev == OMAP_I2C_REV_ON_2430) {
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+ SYSC_AUTOIDLE_MASK);
+
+ } else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
+ u32 v;
+
+ v = SYSC_AUTOIDLE_MASK;
+ v |= SYSC_ENAWAKEUP_MASK;
+ v |= (SYSC_IDLEMODE_SMART <<
+ __ffs(SYSC_SIDLEMODE_MASK));
+ v |= (SYSC_CLOCKACTIVITY_FCLK <<
+ __ffs(SYSC_CLOCKACTIVITY_MASK));
+
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+ /*
+ * Enabling all wakup sources to stop I2C freezing on
+ * WFI instruction.
+ * REVISIT: Some wkup sources might not be needed.
+ */
+ omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
+ OMAP_I2C_WE_ALL);
+
+ }
}
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
@@ -249,27 +334,65 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc = fclk_rate / 12000000;
}
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+
+ /* HSI2C controller internal clk rate should be 19.2 Mhz */
+ internal_clk = 19200;
+ fclk_rate = clk_get_rate(dev->fclk) / 1000;
+
+ /* Compute prescaler divisor */
+ psc = fclk_rate / internal_clk;
+ psc = psc - 1;
+
+ /* If configured for High Speed */
+ if (dev->speed > 400) {
+ /* For first phase of HS mode */
+ fsscll = internal_clk / (400 * 2) - 6;
+ fssclh = internal_clk / (400 * 2) - 6;
+
+ /* For second phase of HS mode */
+ hsscll = fclk_rate / (dev->speed * 2) - 6;
+ hssclh = fclk_rate / (dev->speed * 2) - 6;
+ } else {
+ /* To handle F/S modes */
+ fsscll = internal_clk / (dev->speed * 2) - 6;
+ fssclh = internal_clk / (dev->speed * 2) - 6;
+ }
+ scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll;
+ sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh;
+ } else {
+ /* Program desired operating rate */
+ fclk_rate /= (psc + 1) * 1000;
+ if (psc > 2)
+ psc = 2;
+ scll = fclk_rate / (dev->speed * 2) - 7 + psc;
+ sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
+ }
+
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
- /* Program desired operating rate */
- fclk_rate /= (psc + 1) * 1000;
- if (psc > 2)
- psc = 2;
+ /* SCL low and high time values */
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
- omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
- fclk_rate / (clock * 2) - 7 + psc);
- omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
- fclk_rate / (clock * 2) - 7 + psc);
+ if (dev->fifo_size)
+ /* Note: setup required fifo size - 1 */
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
+ (dev->fifo_size - 1) << 8 | /* RTRSH */
+ OMAP_I2C_BUF_RXFIF_CLR |
+ (dev->fifo_size - 1) | /* XTRSH */
+ OMAP_I2C_BUF_TXFIF_CLR);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/* Enable interrupts */
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
- (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
- OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
- OMAP_I2C_IE_AL));
+ (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+ OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+ OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
+ (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
return 0;
}
@@ -316,20 +439,59 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+ /* Clear the FIFO Buffers */
+ w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+ w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
+
init_completion(&dev->cmd_complete);
dev->cmd_err = 0;
w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+
+ /* High speed configuration */
+ if (dev->speed > 400)
+ w |= OMAP_I2C_CON_OPMODE_HS;
+
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
w |= OMAP_I2C_CON_TRX;
- if (stop)
+
+ if (!dev->b_hw && stop)
w |= OMAP_I2C_CON_STP;
+
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
- r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
- OMAP_I2C_TIMEOUT);
+ /*
+ * Don't write stt and stp together on some hardware.
+ */
+ if (dev->b_hw && stop) {
+ unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
+ u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+ while (con & OMAP_I2C_CON_STT) {
+ con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+
+ /* Let the user know if i2c is in a bad state */
+ if (time_after(jiffies, delay)) {
+ dev_err(dev->dev, "controller timed out "
+ "waiting for start condition to finish\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
+
+ w |= OMAP_I2C_CON_STP;
+ w &= ~OMAP_I2C_CON_STT;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+ }
+
+ /*
+ * REVISIT: We should abort the transfer on signals, but the bus goes
+ * into arbitration and we're currently unable to recover from it.
+ */
+ r = wait_for_completion_timeout(&dev->cmd_complete,
+ OMAP_I2C_TIMEOUT);
dev->buf_len = 0;
if (r < 0)
return r;
@@ -376,7 +538,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
omap_i2c_unidle(dev);
- if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+ r = omap_i2c_wait_for_bb(dev);
+ if (r < 0)
goto out;
for (i = 0; i < num; i++) {
@@ -411,6 +574,9 @@ omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
}
+/* rev1 devices are apparently only on some 15xx */
+#ifdef CONFIG_ARCH_OMAP15XX
+
static irqreturn_t
omap_i2c_rev1_isr(int this_irq, void *dev_id)
{
@@ -465,6 +631,9 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
+#else
+#define omap_i2c_rev1_isr NULL
+#endif
static irqreturn_t
omap_i2c_isr(int this_irq, void *dev_id)
@@ -472,7 +641,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
struct omap_i2c_dev *dev = dev_id;
u16 bits;
u16 stat, w;
- int count = 0;
+ int err, count = 0;
if (dev->idle)
return IRQ_NONE;
@@ -487,39 +656,96 @@ omap_i2c_isr(int this_irq, void *dev_id)
omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
- if (stat & OMAP_I2C_STAT_ARDY) {
- omap_i2c_complete_cmd(dev, 0);
- continue;
+ err = 0;
+ if (stat & OMAP_I2C_STAT_NACK) {
+ err |= OMAP_I2C_STAT_NACK;
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+ OMAP_I2C_CON_STP);
}
- if (stat & OMAP_I2C_STAT_RRDY) {
- w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
- if (dev->buf_len) {
- *dev->buf++ = w;
- dev->buf_len--;
+ if (stat & OMAP_I2C_STAT_AL) {
+ dev_err(dev->dev, "Arbitration lost\n");
+ err |= OMAP_I2C_STAT_AL;
+ }
+ if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
+ OMAP_I2C_STAT_AL))
+ omap_i2c_complete_cmd(dev, err);
+ if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
if (dev->buf_len) {
- *dev->buf++ = w >> 8;
+ *dev->buf++ = w;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
+ if (dev->buf_len) {
+ *dev->buf++ = w >> 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_RRDY)
+ dev_err(dev->dev,
+ "RRDY IRQ while no data"
+ " requested\n");
+ if (stat & OMAP_I2C_STAT_RDR)
+ dev_err(dev->dev,
+ "RDR IRQ while no data"
+ " requested\n");
+ break;
}
- } else
- dev_err(dev->dev, "RRDY IRQ while no data "
- "requested\n");
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
continue;
}
- if (stat & OMAP_I2C_STAT_XRDY) {
- w = 0;
- if (dev->buf_len) {
- w = *dev->buf++;
- dev->buf_len--;
+ if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+ u8 num_bytes = 1;
+ if (dev->fifo_size) {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ num_bytes = dev->fifo_size;
+ else
+ num_bytes = omap_i2c_read_reg(dev,
+ OMAP_I2C_BUFSTAT_REG);
+ }
+ while (num_bytes) {
+ num_bytes--;
+ w = 0;
if (dev->buf_len) {
- w |= *dev->buf++ << 8;
+ w = *dev->buf++;
dev->buf_len--;
+ /* Data reg from 2430 is 8 bit wide */
+ if (!cpu_is_omap2430() &&
+ !cpu_is_omap34xx()) {
+ if (dev->buf_len) {
+ w |= *dev->buf++ << 8;
+ dev->buf_len--;
+ }
+ }
+ } else {
+ if (stat & OMAP_I2C_STAT_XRDY)
+ dev_err(dev->dev,
+ "XRDY IRQ while no "
+ "data to send\n");
+ if (stat & OMAP_I2C_STAT_XDR)
+ dev_err(dev->dev,
+ "XDR IRQ while no "
+ "data to send\n");
+ break;
}
- } else
- dev_err(dev->dev, "XRDY IRQ while no "
- "data to send\n");
- omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
- omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+ omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+ }
+ omap_i2c_ack_stat(dev,
+ stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
continue;
}
if (stat & OMAP_I2C_STAT_ROVR) {
@@ -527,18 +753,9 @@ omap_i2c_isr(int this_irq, void *dev_id)
dev->cmd_err |= OMAP_I2C_STAT_ROVR;
}
if (stat & OMAP_I2C_STAT_XUDF) {
- dev_err(dev->dev, "Transmit overflow\n");
+ dev_err(dev->dev, "Transmit underflow\n");
dev->cmd_err |= OMAP_I2C_STAT_XUDF;
}
- if (stat & OMAP_I2C_STAT_NACK) {
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
- omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
- OMAP_I2C_CON_STP);
- }
- if (stat & OMAP_I2C_STAT_AL) {
- dev_err(dev->dev, "Arbitration lost\n");
- omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
- }
}
return count ? IRQ_HANDLED : IRQ_NONE;
@@ -549,13 +766,15 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func,
};
-static int
+static int __init
omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *dev;
struct i2c_adapter *adap;
struct resource *mem, *irq, *ioarea;
+ irq_handler_t isr;
int r;
+ u32 speed = 0;
/* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -576,17 +795,19 @@ omap_i2c_probe(struct platform_device *pdev)
return -EBUSY;
}
- if (clock > 200)
- clock = 400; /* Fast mode */
- else
- clock = 100; /* Standard mode */
-
dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
if (!dev) {
r = -ENOMEM;
goto err_release_region;
}
+ if (pdev->dev.platform_data != NULL)
+ speed = *(u32 *)pdev->dev.platform_data;
+ else
+ speed = 100; /* Defualt speed */
+
+ dev->speed = speed;
+ dev->idle = 1;
dev->dev = &pdev->dev;
dev->irq = irq->start;
dev->base = ioremap(mem->start, mem->end - mem->start + 1);
@@ -602,22 +823,39 @@ omap_i2c_probe(struct platform_device *pdev)
omap_i2c_unidle(dev);
- if (cpu_is_omap15xx())
- dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+ dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+
+ if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ u16 s;
+
+ /* Set up the fifo size - Get total size */
+ s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
+ dev->fifo_size = 0x8 << s;
+
+ /*
+ * Set up notification threshold as half the total available
+ * size. This is to ensure that we can handle the status on int
+ * call back latencies.
+ */
+ dev->fifo_size = (dev->fifo_size / 2);
+ dev->b_hw = 1; /* Enable hardware fixes */
+ }
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
- r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
- 0, pdev->name, dev);
+ isr = (dev->rev < OMAP_I2C_REV_2) ? omap_i2c_rev1_isr : omap_i2c_isr;
+ r = request_irq(dev->irq, isr, 0, pdev->name, dev);
if (r) {
dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
goto err_unuse_clocks;
}
- r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+
dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
- pdev->id, r >> 4, r & 0xf, clock);
+ pdev->id, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+
+ omap_i2c_idle(dev);
adap = &dev->adapter;
i2c_set_adapdata(adap, dev);
@@ -635,8 +873,6 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_free_irq;
}
- omap_i2c_idle(dev);
-
return 0;
err_free_irq:
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index b2b8380f6602..322c5691e38e 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -115,7 +115,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
static struct i2c_adapter parport_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
- .id = I2C_HW_B_LP,
.algo_data = &parport_algo_data,
.name = "Parallel port adapter (light)",
};
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index a257cd5cd134..0d8998610c74 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -164,7 +164,6 @@ static void i2c_parport_attach (struct parport *port)
/* Fill the rest of the structure */
adapter->adapter.owner = THIS_MODULE;
adapter->adapter.class = I2C_CLASS_HWMON;
- adapter->adapter.id = I2C_HW_B_LP;
strlcpy(adapter->adapter.name, "Parallel port adapter",
sizeof(adapter->adapter.name));
adapter->algo_data = parport_algo_data;
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 9eb76268ec78..4aa8138cb0a9 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -101,7 +101,6 @@ static struct i2c_algo_pca_data pca_isa_data = {
static struct i2c_adapter pca_isa_ops = {
.owner = THIS_MODULE,
- .id = I2C_HW_A_ISA,
.algo_data = &pca_isa_data,
.name = "PCA9564 ISA Adapter",
.timeout = 100,
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index eaa9b387543e..761f9dd53620 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -403,7 +403,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_PIIX4,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 587f5b2380d4..6af68146c342 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -1076,10 +1076,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
#ifdef CONFIG_I2C_PXA_SLAVE
printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n",
- i2c->adap.dev.bus_id, i2c->slave_addr);
+ dev_name(&i2c->adap.dev), i2c->slave_addr);
#else
printk(KERN_INFO "I2C: %s: PXA I2C adapter\n",
- i2c->adap.dev.bus_id);
+ dev_name(&i2c->adap.dev));
#endif
return 0;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index c39079f9c73f..5b7f95641ba4 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -35,11 +35,9 @@
#include <linux/clk.h>
#include <linux/cpufreq.h>
-#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <mach/regs-gpio.h>
#include <plat/regs-iic.h>
#include <plat/iic.h>
@@ -64,6 +62,7 @@ struct s3c24xx_i2c {
unsigned int msg_ptr;
unsigned int tx_setup;
+ unsigned int irq;
enum s3c24xx_i2c_state state;
unsigned long clkrate;
@@ -71,7 +70,6 @@ struct s3c24xx_i2c {
void __iomem *regs;
struct clk *clk;
struct device *dev;
- struct resource *irq;
struct resource *ioarea;
struct i2c_adapter adap;
@@ -80,16 +78,7 @@ struct s3c24xx_i2c {
#endif
};
-/* default platform data to use if not supplied in the platform_device
-*/
-
-static struct s3c2410_platform_i2c s3c24xx_i2c_default_platform = {
- .flags = 0,
- .slave_addr = 0x10,
- .bus_freq = 100*1000,
- .max_freq = 400*1000,
- .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
-};
+/* default platform data removed, dev should always carry data. */
/* s3c24xx_i2c_is2440()
*
@@ -103,21 +92,6 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
return !strcmp(pdev->name, "s3c2440-i2c");
}
-
-/* s3c24xx_i2c_get_platformdata
- *
- * get the platform data associated with the given device, or return
- * the default if there is none
-*/
-
-static inline struct s3c2410_platform_i2c *s3c24xx_i2c_get_platformdata(struct device *dev)
-{
- if (dev->platform_data != NULL)
- return (struct s3c2410_platform_i2c *)dev->platform_data;
-
- return &s3c24xx_i2c_default_platform;
-}
-
/* s3c24xx_i2c_master_complete
*
* complete the message and wake up the caller, using the given return code,
@@ -130,7 +104,7 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
i2c->msg_ptr = 0;
i2c->msg = NULL;
- i2c->msg_idx ++;
+ i2c->msg_idx++;
i2c->msg_num = 0;
if (ret)
i2c->msg_idx = ret;
@@ -141,19 +115,17 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
-
}
static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON);
-
}
/* irq enable/disable functions */
@@ -161,7 +133,7 @@ static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
@@ -169,7 +141,7 @@ static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
{
unsigned long tmp;
-
+
tmp = readl(i2c->regs + S3C2410_IICCON);
writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
}
@@ -177,10 +149,10 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_message_start
*
- * put the start of a message onto the bus
+ * put the start of a message onto the bus
*/
-static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
+static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
struct i2c_msg *msg)
{
unsigned int addr = (msg->addr & 0x7f) << 1;
@@ -199,15 +171,15 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
- // todo - check for wether ack wanted or not
+ /* todo - check for wether ack wanted or not */
s3c24xx_i2c_enable_ack(i2c);
iiccon = readl(i2c->regs + S3C2410_IICCON);
writel(stat, i2c->regs + S3C2410_IICSTAT);
-
+
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
writeb(addr, i2c->regs + S3C2410_IICDS);
-
+
/* delay here to ensure the data byte has gotten onto the bus
* before the transaction is started */
@@ -215,8 +187,8 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
writel(iiccon, i2c->regs + S3C2410_IICCON);
-
- stat |= S3C2410_IICSTAT_START;
+
+ stat |= S3C2410_IICSTAT_START;
writel(stat, i2c->regs + S3C2410_IICSTAT);
}
@@ -227,11 +199,11 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
dev_dbg(i2c->dev, "STOP\n");
/* stop the transfer */
- iicstat &= ~ S3C2410_IICSTAT_START;
+ iicstat &= ~S3C2410_IICSTAT_START;
writel(iicstat, i2c->regs + S3C2410_IICSTAT);
-
+
i2c->state = STATE_STOP;
-
+
s3c24xx_i2c_master_complete(i2c, ret);
s3c24xx_i2c_disable_irq(i2c);
}
@@ -241,7 +213,7 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
/* is_lastmsg()
*
- * returns TRUE if the current message is the last in the set
+ * returns TRUE if the current message is the last in the set
*/
static inline int is_lastmsg(struct s3c24xx_i2c *i2c)
@@ -289,14 +261,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
case STATE_STOP:
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
- s3c24xx_i2c_disable_irq(i2c);
+ s3c24xx_i2c_disable_irq(i2c);
goto out_ack;
case STATE_START:
/* last thing we did was send a start condition on the
* bus, or started a new i2c message
*/
-
+
if (iicstat & S3C2410_IICSTAT_LASTBIT &&
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
/* ack was not received... */
@@ -322,7 +294,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
if (i2c->state == STATE_READ)
goto prepare_read;
- /* fall through to the write state, as we will need to
+ /* fall through to the write state, as we will need to
* send a byte as well */
case STATE_WRITE:
@@ -339,7 +311,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
}
}
- retry_write:
+ retry_write:
if (!is_msgend(i2c)) {
byte = i2c->msg->buf[i2c->msg_ptr++];
@@ -359,9 +331,9 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
dev_dbg(i2c->dev, "WRITE: Next Message\n");
i2c->msg_ptr = 0;
- i2c->msg_idx ++;
+ i2c->msg_idx++;
i2c->msg++;
-
+
/* check to see if we need to do another message */
if (i2c->msg->flags & I2C_M_NOSTART) {
@@ -375,7 +347,6 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
goto retry_write;
} else {
-
/* send the new start */
s3c24xx_i2c_message_start(i2c, i2c->msg);
i2c->state = STATE_START;
@@ -389,7 +360,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
break;
case STATE_READ:
- /* we have a byte of data in the data register, do
+ /* we have a byte of data in the data register, do
* something with it, and then work out wether we are
* going to do any more read/write
*/
@@ -397,13 +368,13 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
byte = readb(i2c->regs + S3C2410_IICDS);
i2c->msg->buf[i2c->msg_ptr++] = byte;
- prepare_read:
+ prepare_read:
if (is_msglast(i2c)) {
/* last byte of buffer */
if (is_lastmsg(i2c))
s3c24xx_i2c_disable_ack(i2c);
-
+
} else if (is_msgend(i2c)) {
/* ok, we've read the entire buffer, see if there
* is anything else we need to do */
@@ -429,7 +400,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
/* acknowlegde the IRQ and get back on with the work */
out_ack:
- tmp = readl(i2c->regs + S3C2410_IICCON);
+ tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON);
out:
@@ -450,19 +421,19 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
status = readl(i2c->regs + S3C2410_IICSTAT);
if (status & S3C2410_IICSTAT_ARBITR) {
- // deal with arbitration loss
+ /* deal with arbitration loss */
dev_err(i2c->dev, "deal with arbitration loss\n");
}
if (i2c->state == STATE_IDLE) {
dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n");
- tmp = readl(i2c->regs + S3C2410_IICCON);
+ tmp = readl(i2c->regs + S3C2410_IICCON);
tmp &= ~S3C2410_IICCON_IRQPEND;
writel(tmp, i2c->regs + S3C2410_IICCON);
goto out;
}
-
+
/* pretty much this leaves us with the fact that we've
* transmitted or received whatever byte we last sent */
@@ -485,16 +456,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
while (timeout-- > 0) {
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
-
+
if (!(iicstat & S3C2410_IICSTAT_BUSBUSY))
return 0;
msleep(1);
}
- dev_dbg(i2c->dev, "timeout: GPEDAT is %08x\n",
- __raw_readl(S3C2410_GPEDAT));
-
return -ETIMEDOUT;
}
@@ -503,7 +471,8 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
* this starts an i2c transfer
*/
-static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num)
+static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
+ struct i2c_msg *msgs, int num)
{
unsigned long timeout;
int ret;
@@ -529,12 +498,12 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
s3c24xx_i2c_enable_irq(i2c);
s3c24xx_i2c_message_start(i2c, msgs);
spin_unlock_irq(&i2c->lock);
-
+
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
ret = i2c->msg_idx;
- /* having these next two as dev_err() makes life very
+ /* having these next two as dev_err() makes life very
* noisy when doing an i2cdetect */
if (timeout == 0)
@@ -591,19 +560,6 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
.functionality = s3c24xx_i2c_func,
};
-static struct s3c24xx_i2c s3c24xx_i2c = {
- .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
- .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
- .tx_setup = 50,
- .adap = {
- .name = "s3c2410-i2c",
- .owner = THIS_MODULE,
- .algo = &s3c24xx_i2c_algorithm,
- .retries = 2,
- .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- },
-};
-
/* s3c24xx_i2c_calcdivisor
*
* return the divisor settings for a given frequency
@@ -643,7 +599,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
{
int diff = freq - wanted;
- return (diff >= -2 && diff <= 2);
+ return diff >= -2 && diff <= 2;
}
/* s3c24xx_i2c_clockrate
@@ -655,7 +611,7 @@ static inline int freq_acceptable(unsigned int freq, unsigned int wanted)
static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
{
- struct s3c2410_platform_i2c *pdata;
+ struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data;
unsigned long clkin = clk_get_rate(i2c->clk);
unsigned int divs, div1;
u32 iiccon;
@@ -663,10 +619,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
int start, end;
i2c->clkrate = clkin;
-
- pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
clkin /= 1000; /* clkin now in KHz */
-
+
dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n",
pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq);
@@ -774,7 +728,7 @@ static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c)
/* s3c24xx_i2c_init
*
- * initialise the controller, set the IO lines and frequency
+ * initialise the controller, set the IO lines and frequency
*/
static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
@@ -785,15 +739,15 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
/* get the plafrom data */
- pdata = s3c24xx_i2c_get_platformdata(i2c->adap.dev.parent);
+ pdata = i2c->dev->platform_data;
/* inititalise the gpio */
- s3c2410_gpio_cfgpin(S3C2410_GPE15, S3C2410_GPE15_IICSDA);
- s3c2410_gpio_cfgpin(S3C2410_GPE14, S3C2410_GPE14_IICSCL);
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(to_platform_device(i2c->dev));
/* write slave address */
-
+
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr);
@@ -831,12 +785,32 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
static int s3c24xx_i2c_probe(struct platform_device *pdev)
{
- struct s3c24xx_i2c *i2c = &s3c24xx_i2c;
+ struct s3c24xx_i2c *i2c;
struct s3c2410_platform_i2c *pdata;
struct resource *res;
int ret;
- pdata = s3c24xx_i2c_get_platformdata(&pdev->dev);
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -EINVAL;
+ }
+
+ i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
+ if (!i2c) {
+ dev_err(&pdev->dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
+ i2c->adap.owner = THIS_MODULE;
+ i2c->adap.algo = &s3c24xx_i2c_algorithm;
+ i2c->adap.retries = 2;
+ i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ i2c->tx_setup = 50;
+
+ spin_lock_init(&i2c->lock);
+ init_waitqueue_head(&i2c->wait);
/* find the clock and enable it */
@@ -878,7 +852,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_ioarea;
}
- dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
+ dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+ i2c->regs, i2c->ioarea, res);
/* setup info block for the i2c core */
@@ -892,29 +867,23 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_iomap;
/* find the IRQ for this unit (note, this relies on the init call to
- * ensure no current IRQs pending
+ * ensure no current IRQs pending
*/
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (res == NULL) {
+ i2c->irq = ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
dev_err(&pdev->dev, "cannot find IRQ\n");
- ret = -ENOENT;
goto err_iomap;
}
- ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
- pdev->name, i2c);
+ ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED,
+ dev_name(&pdev->dev), i2c);
if (ret != 0) {
- dev_err(&pdev->dev, "cannot claim IRQ\n");
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
goto err_iomap;
}
- i2c->irq = res;
-
- dev_dbg(&pdev->dev, "irq resource %p (%lu)\n", res,
- (unsigned long)res->start);
-
ret = s3c24xx_i2c_register_cpufreq(i2c);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register cpufreq notifier\n");
@@ -937,14 +906,14 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2c);
- dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
+ dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
return 0;
err_cpufreq:
s3c24xx_i2c_deregister_cpufreq(i2c);
err_irq:
- free_irq(i2c->irq->start, i2c);
+ free_irq(i2c->irq, i2c);
err_iomap:
iounmap(i2c->regs);
@@ -958,6 +927,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
clk_put(i2c->clk);
err_noclk:
+ kfree(i2c);
return ret;
}
@@ -973,7 +943,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
s3c24xx_i2c_deregister_cpufreq(i2c);
i2c_del_adapter(&i2c->adap);
- free_irq(i2c->irq->start, i2c);
+ free_irq(i2c->irq, i2c);
clk_disable(i2c->clk);
clk_put(i2c->clk);
@@ -982,6 +952,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
+ kfree(i2c);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c
index 5e0e254976de..baa28b73ae42 100644
--- a/drivers/i2c/busses/i2c-sh7760.c
+++ b/drivers/i2c/busses/i2c-sh7760.c
@@ -475,7 +475,7 @@ static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
id->adap.nr = pdev->id;
id->adap.algo = &sh7760_i2c_algo;
- id->adap.class = I2C_CLASS_ALL;
+ id->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
id->adap.retries = 3;
id->adap.algo_data = id;
id->adap.dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 6c3d60b939bf..1c01083b01b5 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -500,7 +500,7 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
for (n = res->start; hook && n <= res->end; n++) {
if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
- dev->dev.bus_id, dev))
+ dev_name(&dev->dev), dev))
goto rollback;
}
k++;
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index 4ddefbf238e9..98b1ec489159 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -155,7 +155,6 @@ static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
static struct i2c_adapter sibyte_board_adapter[2] = {
{
.owner = THIS_MODULE,
- .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL,
.algo_data = &sibyte_board_data[0],
@@ -164,7 +163,6 @@ static struct i2c_adapter sibyte_board_adapter[2] = {
},
{
.owner = THIS_MODULE,
- .id = I2C_HW_SIBYTE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = NULL,
.algo_data = &sibyte_board_data[1],
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index dfc2d5eb6a68..f320ab27da46 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -365,7 +365,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis5595_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_SIS5595,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -389,8 +388,8 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_
/* set up the sysfs linkage to our parent device */
sis5595_adapter.dev.parent = &dev->dev;
- sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
- sis5595_base + SMB_INDEX);
+ snprintf(sis5595_adapter.name, sizeof(sis5595_adapter.name),
+ "SMBus SIS5595 adapter at %04x", sis5595_base + SMB_INDEX);
err = i2c_add_adapter(&sis5595_adapter);
if (err) {
release_region(sis5595_base + SMB_INDEX, 2);
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index e7c4b790da54..50c3610e6028 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -464,7 +464,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis630_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_SIS630,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
@@ -487,8 +486,8 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i
/* set up the sysfs linkage to our parent device */
sis630_adapter.dev.parent = &dev->dev;
- sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
- acpi_base + SMB_STS);
+ snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
+ "SMBus SIS630 adapter at %04x", acpi_base + SMB_STS);
return i2c_add_adapter(&sis630_adapter);
}
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index f1bba6396641..7e1594b40579 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -241,7 +241,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter sis96x_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_SIS96X,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 29cef0433f34..8b24f192103a 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -83,7 +83,6 @@ static struct i2c_algo_bit_data bit_data = {
static struct i2c_adapter vt586b_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_B_VIA,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.name = "VIA i2c",
.algo_data = &bit_data,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 9f194d9efd91..02e6f724b05f 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -321,7 +321,6 @@ static const struct i2c_algorithm smbus_algorithm = {
static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_SMBUS_VIA2,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
};
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 1d4ae26ba73d..1a474acc0ddd 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -163,7 +163,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
static struct i2c_adapter voodoo3_i2c_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_B_VOO,
.class = I2C_CLASS_TV_ANALOG,
.name = "I2C Voodoo3/Banshee adapter",
.algo_data = &voo_i2c_bit_data,
@@ -180,7 +179,6 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
static struct i2c_adapter voodoo3_ddc_adapter = {
.owner = THIS_MODULE,
- .id = I2C_HW_B_VOO,
.class = I2C_CLASS_DDC,
.name = "DDC Voodoo3/Banshee adapter",
.algo_data = &voo_ddc_bit_data,
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index ed794b145a11..648ecc6f60e6 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -440,7 +440,6 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
i2c_set_adapdata(adapter, iface);
snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
adapter->owner = THIS_MODULE;
- adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm;
adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adapter->dev.parent = dev;
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index e4c98539c517..162b74a04886 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -82,7 +82,6 @@ static struct i2c_algo_bit_data scx200_i2c_data = {
static struct i2c_adapter scx200_i2c_ops = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
- .id = I2C_HW_B_SCX200,
.algo_data = &scx200_i2c_data,
.name = "NatSemi SCx200 I2C",
};
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 4c35702830ce..c80312c1f382 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -16,43 +16,6 @@ config DS1682
This driver can also be built as a module. If so, the module
will be called ds1682.
-config AT24
- tristate "EEPROMs from most vendors"
- depends on SYSFS && EXPERIMENTAL
- help
- Enable this driver to get read/write support to most I2C EEPROMs,
- after you configure the driver to know about each EEPROM on
- your target board. Use these generic chip names, instead of
- vendor-specific ones like at24c64 or 24lc02:
-
- 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
- 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
-
- Unless you like data loss puzzles, always be sure that any chip
- you configure as a 24c32 (32 kbit) or larger is NOT really a
- 24c16 (16 kbit) or smaller, and vice versa. Marking the chip
- as read-only won't help recover from this. Also, if your chip
- has any software write-protect mechanism you may want to review the
- code to make sure this driver won't turn it on by accident.
-
- If you use this with an SMBus adapter instead of an I2C adapter,
- full functionality is not available. Only smaller devices are
- supported (24c16 and below, max 4 kByte).
-
- This driver can also be built as a module. If so, the module
- will be called at24.
-
-config SENSORS_EEPROM
- tristate "EEPROM reader"
- depends on EXPERIMENTAL
- help
- If you say yes here you get read-only access to the EEPROM data
- available on modern memory DIMMs and Sony Vaio laptops. Such
- EEPROMs could theoretically be available on other devices as well.
-
- This driver can also be built as a module. If so, the module
- will be called eeprom.
-
config SENSORS_PCF8574
tristate "Philips PCF8574 and PCF8574A (DEPRECATED)"
depends on EXPERIMENTAL && GPIO_PCF857X = "n"
@@ -114,31 +77,6 @@ config SENSORS_PCF8591
These devices are hard to detect and rarely found on mainstream
hardware. If unsure, say N.
-config ISP1301_OMAP
- tristate "Philips ISP1301 with OMAP OTG"
- depends on ARCH_OMAP_OTG
- help
- If you say yes here you get support for the Philips ISP1301
- USB-On-The-Go transceiver working with the OMAP OTG controller.
- The ISP1301 is used in products including H2 and H3 development
- boards for Texas Instruments OMAP processors.
-
- This driver can also be built as a module. If so, the module
- will be called isp1301_omap.
-
-config TPS65010
- tristate "TPS6501x Power Management chips"
- depends on GPIOLIB
- default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
- help
- If you say yes here you get support for the TPS6501x series of
- Power Management chips. These include voltage regulators,
- lithium ion/polymer battery charging, and other features that
- are often used in portable devices like cell phones and cameras.
-
- This driver can also be built as a module. If so, the module
- will be called tps65010.
-
config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor"
depends on EXPERIMENTAL
@@ -164,25 +102,4 @@ config SENSORS_TSL2550
This driver can also be built as a module. If so, the module
will be called tsl2550.
-config MENELAUS
- bool "TWL92330/Menelaus PM chip"
- depends on I2C=y && ARCH_OMAP24XX
- help
- If you say yes here you get support for the Texas Instruments
- TWL92330/Menelaus Power Management chip. This include voltage
- regulators, Dual slot memory card tranceivers, real-time clock
- and other features that are often used in portable devices like
- cell phones and PDAs.
-
-config MCU_MPC8349EMITX
- tristate "MPC8349E-mITX MCU driver"
- depends on I2C && PPC_83xx
- select GENERIC_GPIO
- select ARCH_REQUIRE_GPIOLIB
- help
- Say Y here to enable soft power-off functionality on the Freescale
- boards with the MPC8349E-mITX-compatible MCU chips. This driver will
- also register MCU GPIOs with the generic GPIO API, so you'll able
- to use MCU pins as GPIOs.
-
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 23d2a31b0a64..d142f238a2de 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -11,18 +11,12 @@
#
obj-$(CONFIG_DS1682) += ds1682.o
-obj-$(CONFIG_AT24) += at24.o
-obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
-obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
-obj-$(CONFIG_TPS65010) += tps65010.o
-obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
-obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index c6a63f46bc15..b1c9abe24c7b 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -459,7 +459,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
pr_debug("I2C adapter driver [%s] forgot to specify "
"physical device\n", adap->name);
}
- sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
+ dev_set_name(&adap->dev, "i2c-%d", adap->nr);
adap->dev.release = &i2c_adapter_dev_release;
adap->dev.class = &i2c_adapter_class;
res = device_register(&adap->dev);
@@ -845,8 +845,8 @@ int i2c_attach_client(struct i2c_client *client)
} else
client->dev.release = i2c_client_dev_release;
- snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
- "%d-%04x", i2c_adapter_id(adapter), client->addr);
+ dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adapter),
+ client->addr);
res = device_register(&client->dev);
if (res)
goto out_err;
@@ -856,7 +856,7 @@ int i2c_attach_client(struct i2c_client *client)
mutex_unlock(&adapter->clist_lock);
dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
- client->name, client->dev.bus_id);
+ client->name, dev_name(&client->dev));
if (adapter->client_register) {
if (adapter->client_register(client)) {
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index c9f21e3d4ead..3dad2299d9c5 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -137,6 +137,7 @@ config BLK_DEV_DELKIN
config BLK_DEV_IDECD
tristate "Include IDE/ATAPI CDROM support"
+ select IDE_ATAPI
---help---
If you have a CD-ROM drive using the ATAPI protocol, say Y. ATAPI is
a newer protocol used by IDE CD-ROM and TAPE drives, similar to the
@@ -185,23 +186,6 @@ config BLK_DEV_IDETAPE
To compile this driver as a module, choose M here: the
module will be called ide-tape.
-config BLK_DEV_IDESCSI
- tristate "SCSI emulation support (DEPRECATED)"
- depends on SCSI
- select IDE_ATAPI
- ---help---
- WARNING: ide-scsi is no longer needed for cd writing applications!
- The 2.6 kernel supports direct writing to ide-cd, which eliminates
- the need for ide-scsi + the entire scsi stack just for writing a
- cd. The new method is more efficient in every way.
-
- This will provide SCSI host adapter emulation for IDE ATAPI devices,
- and will allow you to use a SCSI device driver instead of a native
- ATAPI driver.
-
- If both this SCSI emulation and native ATAPI support are compiled
- into the kernel, the native support will be used.
-
config BLK_DEV_IDEACPI
bool "IDE ACPI support"
depends on ACPI
@@ -481,6 +465,16 @@ config BLK_DEV_CS5535
It is safe to say Y to this question.
+config BLK_DEV_CS5536
+ tristate "CS5536 chipset support"
+ depends on X86_32
+ select BLK_DEV_IDEDMA_PCI
+ help
+ This option enables support for the AMD CS5536
+ companion chip used with the Geode LX processor family.
+
+ If unsure, say N.
+
config BLK_DEV_HPT366
tristate "HPT36X/37X chipset support"
select BLK_DEV_IDEDMA_PCI
@@ -527,6 +521,13 @@ config BLK_DEV_PIIX
This allows the kernel to change PIO, DMA and UDMA speeds and to
configure the chip to optimum performance.
+config BLK_DEV_IT8172
+ tristate "IT8172 IDE support"
+ select BLK_DEV_IDEDMA_PCI
+ help
+ This driver adds support for the IDE controller on the
+ IT8172 System Controller.
+
config BLK_DEV_IT8213
tristate "IT8213 IDE support"
select BLK_DEV_IDEDMA_PCI
@@ -710,11 +711,6 @@ config BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
depends on SOC_AU1200 && BLK_DEV_IDE_AU1XXX
endchoice
-config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
- int "Maximum transfer size (KB) per request (up to 128)"
- default "128"
- depends on BLK_DEV_IDE_AU1XXX
-
config BLK_DEV_IDE_TX4938
tristate "TX4938 internal IDE support"
depends on SOC_TX4938
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 177e3f8523ed..d0e3d7d5b467 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -5,7 +5,7 @@
EXTRA_CFLAGS += -Idrivers/ide
ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
- ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o
+ ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o
# core IDE code
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
@@ -43,10 +43,12 @@ obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o
obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o
obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o
+obj-$(CONFIG_BLK_DEV_CS5536) += cs5536.o
obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o
obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o
obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o
obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o
+obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o
obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o
obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o
obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index 4142c698e0d3..4485b9c6f0e6 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -83,7 +83,7 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr
static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_host *host = pci_get_drvdata(dev);
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
@@ -111,7 +111,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_host *host = pci_get_drvdata(dev);
struct chipset_bus_clock_list_entry *bus_clock = host->host_priv;
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index 45d2356bb725..66f43083408b 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -68,7 +68,7 @@ static struct pci_dev *isa_dev;
static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
int s_time = t->setup, a_time = t->active, c_time = t->cycle;
@@ -150,7 +150,7 @@ static u8 ali_udma_filter(ide_drive_t *drive)
static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 speed1 = speed;
u8 unit = drive->dn & 1;
@@ -198,7 +198,7 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
static int ali15x3_dma_setup(ide_drive_t *drive)
{
if (m5229_revision < 0xC2 && drive->media != ide_disk) {
- if (rq_data_dir(drive->hwif->hwgroup->rq))
+ if (rq_data_dir(drive->hwif->rq))
return 1; /* try PIO instead of DMA */
}
return ide_dma_setup(drive);
@@ -490,8 +490,6 @@ static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- hwif->dma_ops = &sff_dma_ops;
-
return 0;
}
@@ -511,6 +509,7 @@ static const struct ide_dma_ops ali_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info ali15x3_chipset __devinitdata = {
@@ -519,6 +518,7 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = {
.init_hwif = init_hwif_ali15x3,
.init_dma = init_dma_ali15x3,
.port_ops = &ali_port_ops,
+ .dma_ops = &sff_dma_ops,
.pio_mask = ATA_PIO5,
.swdma_mask = ATA_SWDMA2,
.mwdma_mask = ATA_MWDMA2,
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index c6bcd3014a29..69660a431cd9 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -82,7 +82,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
- ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+ ide_drive_t *peer = ide_get_pair_dev(drive);
struct ide_timing t, p;
int T, UT;
u8 udma_mask = hwif->ultra_mask;
@@ -92,7 +92,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
ide_timing_compute(drive, speed, &t, T, UT);
- if (peer->dev_flags & IDE_DFLAG_PRESENT) {
+ if (peer) {
ide_timing_compute(peer, peer->current_speed, &p, T, UT);
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
index 0ec8fd1e4dcb..79a2dfed8eb7 100644
--- a/drivers/ide/au1xxx-ide.c
+++ b/drivers/ide/au1xxx-ide.c
@@ -212,8 +212,8 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
static int auide_build_dmatable(ide_drive_t *drive)
{
int i, iswrite, count = 0;
- ide_hwif_t *hwif = HWIF(drive);
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->rq;
_auide_hwif *ahwif = &auide_hwif;
struct scatterlist *sg;
@@ -286,7 +286,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
static int auide_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
if (hwif->sg_nents) {
ide_destroy_dmatable(drive);
@@ -309,8 +309,8 @@ static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command)
}
static int auide_dma_setup(ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
+{
+ struct request *rq = drive->hwif->rq;
if (!auide_build_dmatable(drive)) {
ide_map_sg(drive, rq);
@@ -502,7 +502,6 @@ static const struct ide_tp_ops au1xxx_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
index e4306647d00d..8890276fef7f 100644
--- a/drivers/ide/cmd640.c
+++ b/drivers/ide/cmd640.c
@@ -467,11 +467,10 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index)
* so we merge the timings, using the slowest value for each timing.
*/
if (index > 1) {
- ide_hwif_t *hwif = drive->hwif;
- ide_drive_t *peer = &hwif->drives[!(drive->dn & 1)];
+ ide_drive_t *peer = ide_get_pair_dev(drive);
unsigned int mate = index ^ 1;
- if (peer->dev_flags & IDE_DFLAG_PRESENT) {
+ if (peer) {
if (setup_count < setup_counts[mate])
setup_count = setup_counts[mate];
if (active_count < active_counts[mate])
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 3623bf013bcf..2f9688d87ecd 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -115,7 +115,7 @@ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_
*/
static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
unsigned int cycle_time;
@@ -138,10 +138,12 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
* the slowest address setup timing ourselves.
*/
if (hwif->channel) {
- ide_drive_t *drives = hwif->drives;
+ ide_drive_t *pair = ide_get_pair_dev(drive);
drive->drive_data = setup_count;
- setup_count = max(drives[0].drive_data, drives[1].drive_data);
+
+ if (pair)
+ setup_count = max_t(u8, setup_count, pair->drive_data);
}
if (setup_count > 5) /* shouldn't actually happen... */
@@ -180,7 +182,7 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 unit = drive->dn & 0x01;
u8 regU = 0, pciU = hwif->channel ? UDIDETCR1 : UDIDETCR0;
@@ -226,7 +228,7 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
static int cmd648_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long base = hwif->dma_base - (hwif->channel * 8);
int err = ide_dma_end(drive);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
@@ -242,7 +244,7 @@ static int cmd648_dma_end(ide_drive_t *drive)
static int cmd64x_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
@@ -259,7 +261,7 @@ static int cmd64x_dma_end(ide_drive_t *drive)
static int cmd648_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long base = hwif->dma_base - (hwif->channel * 8);
u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
MRDMODE_INTR_CH0;
@@ -282,7 +284,7 @@ static int cmd648_dma_test_irq(ide_drive_t *drive)
static int cmd64x_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
@@ -313,7 +315,7 @@ static int cmd64x_dma_test_irq(ide_drive_t *drive)
static int cmd646_1_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u8 dma_stat = 0, dma_cmd = 0;
drive->waiting_for_dma = 0;
@@ -383,6 +385,7 @@ static const struct ide_dma_ops cmd64x_dma_ops = {
.dma_test_irq = cmd64x_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_dma_ops cmd646_rev1_dma_ops = {
@@ -394,6 +397,7 @@ static const struct ide_dma_ops cmd646_rev1_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_dma_ops cmd648_dma_ops = {
@@ -405,6 +409,7 @@ static const struct ide_dma_ops cmd648_dma_ops = {
.dma_test_irq = cmd648_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c
index 5efb467f8fa0..d003bec56ff9 100644
--- a/drivers/ide/cs5520.c
+++ b/drivers/ide/cs5520.c
@@ -59,7 +59,7 @@ static struct pio_clocks cs5520_pio_clocks[]={
static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *pdev = to_pci_dev(hwif->dev);
int controller = drive->dn > 1 ? 1 : 0;
diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c
new file mode 100644
index 000000000000..7a62db719a46
--- /dev/null
+++ b/drivers/ide/cs5536.c
@@ -0,0 +1,308 @@
+/*
+ * CS5536 PATA support
+ * (C) 2007 Martin K. Petersen <mkp@mkp.net>
+ * (C) 2009 Bartlomiej Zolnierkiewicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Documentation:
+ * Available from AMD web site.
+ *
+ * The IDE timing registers for the CS5536 live in the Geode Machine
+ * Specific Register file and not PCI config space. Most BIOSes
+ * virtualize the PCI registers so the chip looks like a standard IDE
+ * controller. Unfortunately not all implementations get this right.
+ * In particular some have problems with unaligned accesses to the
+ * virtualized PCI registers. This driver always does full dword
+ * writes to work around the issue. Also, in case of a bad BIOS this
+ * driver can be loaded with the "msr=1" parameter which forces using
+ * the Machine Specific Registers to configure the device.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <asm/msr.h>
+
+#define DRV_NAME "cs5536"
+
+enum {
+ MSR_IDE_CFG = 0x51300010,
+ PCI_IDE_CFG = 0x40,
+
+ CFG = 0,
+ DTC = 2,
+ CAST = 3,
+ ETC = 4,
+
+ IDE_CFG_CHANEN = (1 << 1),
+ IDE_CFG_CABLE = (1 << 17) | (1 << 16),
+
+ IDE_D0_SHIFT = 24,
+ IDE_D1_SHIFT = 16,
+ IDE_DRV_MASK = 0xff,
+
+ IDE_CAST_D0_SHIFT = 6,
+ IDE_CAST_D1_SHIFT = 4,
+ IDE_CAST_DRV_MASK = 0x3,
+
+ IDE_CAST_CMD_SHIFT = 24,
+ IDE_CAST_CMD_MASK = 0xff,
+
+ IDE_ETC_UDMA_MASK = 0xc0,
+};
+
+static int use_msr;
+
+static int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
+{
+ if (unlikely(use_msr)) {
+ u32 dummy;
+
+ rdmsr(MSR_IDE_CFG + reg, *val, dummy);
+ return 0;
+ }
+
+ return pci_read_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
+}
+
+static int cs5536_write(struct pci_dev *pdev, int reg, int val)
+{
+ if (unlikely(use_msr)) {
+ wrmsr(MSR_IDE_CFG + reg, val, 0);
+ return 0;
+ }
+
+ return pci_write_config_dword(pdev, PCI_IDE_CFG + reg * 4, val);
+}
+
+static void cs5536_program_dtc(ide_drive_t *drive, u8 tim)
+{
+ struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
+ int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
+ u32 dtc;
+
+ cs5536_read(pdev, DTC, &dtc);
+ dtc &= ~(IDE_DRV_MASK << dshift);
+ dtc |= tim << dshift;
+ cs5536_write(pdev, DTC, dtc);
+}
+
+/**
+ * cs5536_cable_detect - detect cable type
+ * @hwif: Port to detect on
+ *
+ * Perform cable detection for ATA66 capable cable.
+ *
+ * Returns a cable type.
+ */
+
+static u8 cs5536_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ u32 cfg;
+
+ cs5536_read(pdev, CFG, &cfg);
+
+ if (cfg & IDE_CFG_CABLE)
+ return ATA_CBL_PATA80;
+ else
+ return ATA_CBL_PATA40;
+}
+
+/**
+ * cs5536_set_pio_mode - PIO timing setup
+ * @drive: ATA device
+ * @pio: PIO mode number
+ */
+
+static void cs5536_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+ static const u8 drv_timings[5] = {
+ 0x98, 0x55, 0x32, 0x21, 0x20,
+ };
+
+ static const u8 addr_timings[5] = {
+ 0x2, 0x1, 0x0, 0x0, 0x0,
+ };
+
+ static const u8 cmd_timings[5] = {
+ 0x99, 0x92, 0x90, 0x22, 0x20,
+ };
+
+ struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
+ ide_drive_t *pair = ide_get_pair_dev(drive);
+ int cshift = (drive->dn & 1) ? IDE_CAST_D1_SHIFT : IDE_CAST_D0_SHIFT;
+ u32 cast;
+ u8 cmd_pio = pio;
+
+ if (pair)
+ cmd_pio = min(pio, ide_get_best_pio_mode(pair, 255, 4));
+
+ drive->drive_data &= (IDE_DRV_MASK << 8);
+ drive->drive_data |= drv_timings[pio];
+
+ cs5536_program_dtc(drive, drv_timings[pio]);
+
+ cs5536_read(pdev, CAST, &cast);
+
+ cast &= ~(IDE_CAST_DRV_MASK << cshift);
+ cast |= addr_timings[pio] << cshift;
+
+ cast &= ~(IDE_CAST_CMD_MASK << IDE_CAST_CMD_SHIFT);
+ cast |= cmd_timings[cmd_pio] << IDE_CAST_CMD_SHIFT;
+
+ cs5536_write(pdev, CAST, cast);
+}
+
+/**
+ * cs5536_set_dma_mode - DMA timing setup
+ * @drive: ATA device
+ * @mode: DMA mode
+ */
+
+static void cs5536_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+ static const u8 udma_timings[6] = {
+ 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6,
+ };
+
+ static const u8 mwdma_timings[3] = {
+ 0x67, 0x21, 0x20,
+ };
+
+ struct pci_dev *pdev = to_pci_dev(drive->hwif->dev);
+ int dshift = (drive->dn & 1) ? IDE_D1_SHIFT : IDE_D0_SHIFT;
+ u32 etc;
+
+ cs5536_read(pdev, ETC, &etc);
+
+ if (mode >= XFER_UDMA_0) {
+ etc &= ~(IDE_DRV_MASK << dshift);
+ etc |= udma_timings[mode - XFER_UDMA_0] << dshift;
+ } else { /* MWDMA */
+ etc &= ~(IDE_ETC_UDMA_MASK << dshift);
+ drive->drive_data &= IDE_DRV_MASK;
+ drive->drive_data |= mwdma_timings[mode - XFER_MW_DMA_0] << 8;
+ }
+
+ cs5536_write(pdev, ETC, etc);
+}
+
+static void cs5536_dma_start(ide_drive_t *drive)
+{
+ if (drive->current_speed < XFER_UDMA_0 &&
+ (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK))
+ cs5536_program_dtc(drive, drive->drive_data >> 8);
+
+ ide_dma_start(drive);
+}
+
+static int cs5536_dma_end(ide_drive_t *drive)
+{
+ int ret = ide_dma_end(drive);
+
+ if (drive->current_speed < XFER_UDMA_0 &&
+ (drive->drive_data >> 8) != (drive->drive_data & IDE_DRV_MASK))
+ cs5536_program_dtc(drive, drive->drive_data & IDE_DRV_MASK);
+
+ return ret;
+}
+
+static const struct ide_port_ops cs5536_port_ops = {
+ .set_pio_mode = cs5536_set_pio_mode,
+ .set_dma_mode = cs5536_set_dma_mode,
+ .cable_detect = cs5536_cable_detect,
+};
+
+static const struct ide_dma_ops cs5536_dma_ops = {
+ .dma_host_set = ide_dma_host_set,
+ .dma_setup = ide_dma_setup,
+ .dma_exec_cmd = ide_dma_exec_cmd,
+ .dma_start = cs5536_dma_start,
+ .dma_end = cs5536_dma_end,
+ .dma_test_irq = ide_dma_test_irq,
+ .dma_lost_irq = ide_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
+};
+
+static const struct ide_port_info cs5536_info = {
+ .name = DRV_NAME,
+ .port_ops = &cs5536_port_ops,
+ .dma_ops = &cs5536_dma_ops,
+ .host_flags = IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+};
+
+/**
+ * cs5536_init_one
+ * @dev: PCI device
+ * @id: Entry in match table
+ */
+
+static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ u32 cfg;
+
+ if (use_msr)
+ printk(KERN_INFO DRV_NAME ": Using MSR regs instead of PCI\n");
+
+ cs5536_read(dev, CFG, &cfg);
+
+ if ((cfg & IDE_CFG_CHANEN) == 0) {
+ printk(KERN_ERR DRV_NAME ": disabled by BIOS\n");
+ return -ENODEV;
+ }
+
+ return ide_pci_init_one(dev, &cs5536_info, NULL);
+}
+
+static const struct pci_device_id cs5536_pci_tbl[] = {
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), },
+ { },
+};
+
+static struct pci_driver cs5536_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = cs5536_pci_tbl,
+ .probe = cs5536_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
+};
+
+static int __init cs5536_init(void)
+{
+ return pci_register_driver(&cs5536_pci_driver);
+}
+
+static void __exit cs5536_exit(void)
+{
+ pci_unregister_driver(&cs5536_pci_driver);
+}
+
+MODULE_AUTHOR("Martin K. Petersen, Bartlomiej Zolnierkiewicz");
+MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, cs5536_pci_tbl);
+
+module_param_named(msr, use_msr, int, 0644);
+MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
+
+module_init(cs5536_init);
+module_exit(cs5536_exit);
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
index d37baf8ecc5f..74fc5401f407 100644
--- a/drivers/ide/cy82c693.c
+++ b/drivers/ide/cy82c693.c
@@ -203,7 +203,7 @@ static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
pio_clocks_t pclk;
unsigned int addrCtrl;
diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c
index 39d500d84b07..a638e952d67a 100644
--- a/drivers/ide/falconide.c
+++ b/drivers/ide/falconide.c
@@ -70,7 +70,6 @@ static const struct ide_tp_ops falconide_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
@@ -83,7 +82,7 @@ static const struct ide_tp_ops falconide_tp_ops = {
static const struct ide_port_info falconide_port_info = {
.tp_ops = &falconide_tp_ops,
- .host_flags = IDE_HFLAG_NO_DMA,
+ .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_SERIALIZE,
};
static void __init falconide_setup_ports(hw_regs_t *hw)
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index b18e10d99d2e..3eb9b5c63a0f 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -626,7 +626,7 @@ static struct hpt_info *hpt3xx_get_info(struct device *dev)
static u8 hpt3xx_udma_filter(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct hpt_info *info = hpt3xx_get_info(hwif->dev);
u8 mask = hwif->ultra_mask;
@@ -665,7 +665,7 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct hpt_info *info = hpt3xx_get_info(hwif->dev);
switch (info->chip_type) {
@@ -743,7 +743,7 @@ static void hpt3xx_quirkproc(ide_drive_t *drive)
static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct hpt_info *info = hpt3xx_get_info(hwif->dev);
@@ -788,7 +788,7 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive)
static void hpt370_clear_engine(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
pci_write_config_byte(dev, hwif->select_data, 0x37);
@@ -797,7 +797,7 @@ static void hpt370_clear_engine(ide_drive_t *drive)
static void hpt370_irq_timeout(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 bfifo = 0;
u8 dma_cmd;
@@ -822,7 +822,7 @@ static void hpt370_dma_start(ide_drive_t *drive)
static int hpt370_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
if (dma_stat & 0x01) {
@@ -844,7 +844,7 @@ static void hpt370_dma_timeout(ide_drive_t *drive)
/* returns 1 if DMA IRQ issued, 0 otherwise */
static int hpt374_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 bfifo = 0;
u8 dma_stat;
@@ -865,7 +865,7 @@ static int hpt374_dma_test_irq(ide_drive_t *drive)
static int hpt374_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 mcr = 0, mcr_addr = hwif->select_data;
u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01;
@@ -927,7 +927,7 @@ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
{
- hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21);
+ hpt3xxn_set_clock(drive->hwif, rq_data_dir(rq) ? 0x23 : 0x21);
}
/**
@@ -1349,8 +1349,6 @@ static int __devinit init_dma_hpt366(ide_hwif_t *hwif,
if (ide_allocate_dma_engine(hwif))
return -1;
- hwif->dma_ops = &sff_dma_ops;
-
return 0;
}
@@ -1426,6 +1424,7 @@ static const struct ide_dma_ops hpt37x_dma_ops = {
.dma_test_irq = hpt374_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_dma_ops hpt370_dma_ops = {
@@ -1437,6 +1436,7 @@ static const struct ide_dma_ops hpt370_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = hpt370_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_dma_ops hpt36x_dma_ops = {
@@ -1448,6 +1448,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = hpt366_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 81f70caeb40f..415d7e24f2b6 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -166,7 +166,7 @@ static const expansioncard_ops_t icside_ops_arcin_v6 = {
*/
static void icside_maskproc(ide_drive_t *drive, int mask)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct expansion_card *ec = ECARD_DEV(hwif->dev);
struct icside_state *state = ecard_get_drvdata(ec);
unsigned long flags;
@@ -284,7 +284,7 @@ static void icside_dma_host_set(ide_drive_t *drive, int on)
static int icside_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct expansion_card *ec = ECARD_DEV(hwif->dev);
drive->waiting_for_dma = 0;
@@ -299,7 +299,7 @@ static int icside_dma_end(ide_drive_t *drive)
static void icside_dma_start(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct expansion_card *ec = ECARD_DEV(hwif->dev);
/* We can not enable DMA on both channels simultaneously. */
@@ -309,10 +309,10 @@ static void icside_dma_start(ide_drive_t *drive)
static int icside_dma_setup(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct expansion_card *ec = ECARD_DEV(hwif->dev);
struct icside_state *state = ecard_get_drvdata(ec);
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
unsigned int dma_mode;
if (rq_data_dir(rq))
@@ -362,7 +362,7 @@ static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
static int icside_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct expansion_card *ec = ECARD_DEV(hwif->dev);
struct icside_state *state = ecard_get_drvdata(ec);
@@ -534,7 +534,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
d.dma_ops = NULL;
}
- ret = ide_host_register(host, NULL, hws);
+ ret = ide_host_register(host, &d, hws);
if (ret)
goto err_free;
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index fd4a36433050..ec7d07fa570a 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -18,12 +18,6 @@
#include <linux/dmi.h>
#include <acpi/acpi_bus.h>
-#include <acpi/acnames.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acparser.h>
-#include <acpi/acexcep.h>
-#include <acpi/acmacros.h>
-#include <acpi/actypes.h>
#define REGS_PER_GTF 7
struct taskfile_array {
@@ -218,7 +212,7 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
*/
static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
int port;
acpi_handle drive_handle;
@@ -263,7 +257,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
acpi_status status;
struct acpi_buffer output;
union acpi_object *out_obj;
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct device *dev = hwif->gendev.parent;
int err = -ENODEV;
int port;
@@ -288,7 +282,7 @@ static int do_drive_get_GTF(ide_drive_t *drive,
port = hwif->channel ? drive->dn - 2: drive->dn;
DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
- hwif->name, dev->bus_id, port, hwif->channel);
+ hwif->name, dev_name(dev), port, hwif->channel);
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) {
DEBPRINT("%s drive %d:%d not present\n",
@@ -641,7 +635,8 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
*/
void ide_acpi_set_state(ide_hwif_t *hwif, int on)
{
- int unit;
+ ide_drive_t *drive;
+ int i;
if (ide_noacpi || ide_noacpi_psx)
return;
@@ -655,9 +650,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
/* channel first and then drives for power on and verse versa for power off */
if (on)
acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
+ ide_port_for_each_dev(i, drive, hwif) {
if (!drive->acpidata->obj_handle)
drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
@@ -711,15 +705,13 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
* for both drives, regardless whether they are connected
* or not.
*/
- hwif->drives[0].acpidata = &hwif->acpidata->master;
- hwif->drives[1].acpidata = &hwif->acpidata->slave;
+ hwif->devices[0]->acpidata = &hwif->acpidata->master;
+ hwif->devices[1]->acpidata = &hwif->acpidata->slave;
/*
* Send IDENTIFY for each drive
*/
- for (i = 0; i < MAX_DRIVES; i++) {
- drive = &hwif->drives[i];
-
+ ide_port_for_each_dev(i, drive, hwif) {
memset(drive->acpidata, 0, sizeof(*drive->acpidata));
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
@@ -744,9 +736,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
ide_acpi_get_timing(hwif);
ide_acpi_push_timing(hwif);
- for (i = 0; i < MAX_DRIVES; i++) {
- drive = &hwif->drives[i];
-
+ ide_port_for_each_dev(i, drive, hwif) {
if (drive->dev_flags & IDE_DFLAG_PRESENT)
/* Execute ACPI startup code */
ide_acpi_exec_tfs(drive);
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 4e58b9e7a58a..e96c01260598 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -3,6 +3,7 @@
*/
#include <linux/kernel.h>
+#include <linux/cdrom.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <scsi/scsi.h>
@@ -14,6 +15,13 @@
#define debug_log(fmt, args...) do {} while (0)
#endif
+#define ATAPI_MIN_CDB_BYTES 12
+
+static inline int dev_is_idecd(ide_drive_t *drive)
+{
+ return drive->media == ide_cdrom || drive->media == ide_optical;
+}
+
/*
* Check whether we can support a device,
* based on the ATAPI IDENTIFY command results.
@@ -233,18 +241,49 @@ void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
}
EXPORT_SYMBOL_GPL(ide_retry_pc);
-int ide_scsi_expiry(ide_drive_t *drive)
+int ide_cd_expiry(ide_drive_t *drive)
{
- struct ide_atapi_pc *pc = drive->pc;
+ struct request *rq = drive->hwif->rq;
+ unsigned long wait = 0;
- debug_log("%s called for %lu at %lu\n", __func__,
- pc->scsi_cmd->serial_number, jiffies);
+ debug_log("%s: rq->cmd[0]: 0x%x\n", __func__, rq->cmd[0]);
- pc->flags |= PC_FLAG_TIMEDOUT;
+ /*
+ * Some commands are *slow* and normally take a long time to complete.
+ * Usually we can use the ATAPI "disconnect" to bypass this, but not all
+ * commands/drives support that. Let ide_timer_expiry keep polling us
+ * for these.
+ */
+ switch (rq->cmd[0]) {
+ case GPCMD_BLANK:
+ case GPCMD_FORMAT_UNIT:
+ case GPCMD_RESERVE_RZONE_TRACK:
+ case GPCMD_CLOSE_TRACK:
+ case GPCMD_FLUSH_CACHE:
+ wait = ATAPI_WAIT_PC;
+ break;
+ default:
+ if (!(rq->cmd_flags & REQ_QUIET))
+ printk(KERN_INFO "cmd 0x%x timed out\n",
+ rq->cmd[0]);
+ wait = 0;
+ break;
+ }
+ return wait;
+}
+EXPORT_SYMBOL_GPL(ide_cd_expiry);
- return 0; /* we do not want the IDE subsystem to retry */
+int ide_cd_get_xferlen(struct request *rq)
+{
+ if (blk_fs_request(rq))
+ return 32768;
+ else if (blk_sense_request(rq) || blk_pc_request(rq) ||
+ rq->cmd_type == REQ_TYPE_ATA_PC)
+ return rq->data_len;
+ else
+ return 0;
}
-EXPORT_SYMBOL_GPL(ide_scsi_expiry);
+EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
/*
* This is the usual interrupt handler which will be called during a packet
@@ -255,24 +294,17 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
{
struct ide_atapi_pc *pc = drive->pc;
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
xfer_func_t *xferfunc;
- ide_expiry_t *expiry;
unsigned int timeout, temp;
u16 bcount;
- u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;
+ u8 stat, ireason, dsc = 0;
debug_log("Enter %s - interrupt handler\n", __func__);
- if (scsi) {
- timeout = ide_scsi_get_timeout(pc);
- expiry = ide_scsi_expiry;
- } else {
- timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
- : WAIT_TAPE_CMD;
- expiry = NULL;
- }
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
if (pc->flags & PC_FLAG_TIMEDOUT) {
drive->pc_callback(drive, 0);
@@ -284,8 +316,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
if (hwif->dma_ops->dma_end(drive) ||
- (drive->media == ide_tape && !scsi && (stat & ATA_ERR))) {
- if (drive->media == ide_floppy && !scsi)
+ (drive->media == ide_tape && (stat & ATA_ERR))) {
+ if (drive->media == ide_floppy)
printk(KERN_ERR "%s: DMA %s error\n",
drive->name, rq_data_dir(pc->rq)
? "write" : "read");
@@ -307,7 +339,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
local_irq_enable_in_hardirq();
- if (drive->media == ide_tape && !scsi &&
+ if (drive->media == ide_tape &&
(stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
stat &= ~ATA_ERR;
@@ -315,11 +347,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
/* Error detected */
debug_log("%s: I/O error\n", drive->name);
- if (drive->media != ide_tape || scsi) {
+ if (drive->media != ide_tape)
pc->rq->errors++;
- if (scsi)
- goto cmd_finished;
- }
if (rq->cmd[0] == REQUEST_SENSE) {
printk(KERN_ERR "%s: I/O error in request sense"
@@ -335,7 +364,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
/* queued, but not started */
return ide_stopped;
}
-cmd_finished:
pc->error = 0;
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
@@ -382,25 +410,8 @@ cmd_finished:
"us more data than expected - "
"discarding data\n",
drive->name);
- if (scsi)
- temp = pc->buf_size - pc->xferred;
- else
- temp = 0;
- if (temp) {
- if (pc->sg)
- drive->pc_io_buffers(drive, pc,
- temp, 0);
- else
- tp_ops->input_data(drive, NULL,
- pc->cur_pos, temp);
- printk(KERN_ERR "%s: transferred %d of "
- "%d bytes\n",
- drive->name,
- temp, bcount);
- }
- pc->xferred += temp;
- pc->cur_pos += temp;
- ide_pad_transfer(drive, 0, bcount - temp);
+
+ ide_pad_transfer(drive, 0, bcount);
goto next_irq;
}
debug_log("The device wants to send us more data than "
@@ -410,14 +421,13 @@ cmd_finished:
} else
xferfunc = tp_ops->output_data;
- if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
- (drive->media == ide_tape && !scsi && pc->bh) ||
- (scsi && pc->sg)) {
+ if ((drive->media == ide_floppy && !pc->buf) ||
+ (drive->media == ide_tape && pc->bh)) {
int done = drive->pc_io_buffers(drive, pc, bcount,
!!(pc->flags & PC_FLAG_WRITING));
/* FIXME: don't do partial completions */
- if (drive->media == ide_floppy && !scsi)
+ if (drive->media == ide_floppy)
ide_end_request(drive, 1, done >> 9);
} else
xferfunc(drive, NULL, pc->cur_pos, bcount);
@@ -430,7 +440,7 @@ cmd_finished:
rq->cmd[0], bcount);
next_irq:
/* And set the interrupt handler again */
- ide_set_handler(drive, ide_pc_intr, timeout, expiry);
+ ide_set_handler(drive, ide_pc_intr, timeout, NULL);
return ide_started;
}
@@ -479,11 +489,12 @@ static int ide_delayed_transfer_pc(ide_drive_t *drive)
static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
{
- struct ide_atapi_pc *pc = drive->pc;
+ struct ide_atapi_pc *uninitialized_var(pc);
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
ide_expiry_t *expiry;
unsigned int timeout;
+ int cmd_len;
ide_startstop_t startstop;
u8 ireason;
@@ -493,101 +504,127 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
return startstop;
}
- ireason = ide_read_ireason(drive);
- if (drive->media == ide_tape &&
- (drive->dev_flags & IDE_DFLAG_SCSI) == 0)
- ireason = ide_wait_ireason(drive, ireason);
-
- if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
- printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
- "a packet command\n", drive->name);
- return ide_do_reset(drive);
+ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
+ if (drive->dma)
+ drive->waiting_for_dma = 1;
}
- /*
- * If necessary schedule the packet transfer to occur 'timeout'
- * miliseconds later in ide_delayed_transfer_pc() after the device
- * says it's ready for a packet.
- */
- if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
- timeout = drive->pc_delay;
- expiry = &ide_delayed_transfer_pc;
+ if (dev_is_idecd(drive)) {
+ /* ATAPI commands get padded out to 12 bytes minimum */
+ cmd_len = COMMAND_SIZE(rq->cmd[0]);
+ if (cmd_len < ATAPI_MIN_CDB_BYTES)
+ cmd_len = ATAPI_MIN_CDB_BYTES;
+
+ timeout = rq->timeout;
+ expiry = ide_cd_expiry;
} else {
- if (drive->dev_flags & IDE_DFLAG_SCSI) {
- timeout = ide_scsi_get_timeout(pc);
- expiry = ide_scsi_expiry;
+ pc = drive->pc;
+
+ cmd_len = ATAPI_MIN_CDB_BYTES;
+
+ /*
+ * If necessary schedule the packet transfer to occur 'timeout'
+ * miliseconds later in ide_delayed_transfer_pc() after the
+ * device says it's ready for a packet.
+ */
+ if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
+ timeout = drive->pc_delay;
+ expiry = &ide_delayed_transfer_pc;
} else {
timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
: WAIT_TAPE_CMD;
expiry = NULL;
}
+
+ ireason = ide_read_ireason(drive);
+ if (drive->media == ide_tape)
+ ireason = ide_wait_ireason(drive, ireason);
+
+ if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
+ printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
+ "a packet command\n", drive->name);
+
+ return ide_do_reset(drive);
+ }
}
/* Set the interrupt routine */
- ide_set_handler(drive, ide_pc_intr, timeout, expiry);
+ ide_set_handler(drive,
+ (dev_is_idecd(drive) ? drive->irq_handler
+ : ide_pc_intr),
+ timeout, expiry);
/* Begin DMA, if necessary */
- if (pc->flags & PC_FLAG_DMA_OK) {
- pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
- hwif->dma_ops->dma_start(drive);
+ if (dev_is_idecd(drive)) {
+ if (drive->dma)
+ hwif->dma_ops->dma_start(drive);
+ } else {
+ if (pc->flags & PC_FLAG_DMA_OK) {
+ pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
+ hwif->dma_ops->dma_start(drive);
+ }
}
/* Send the actual packet */
if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
- hwif->tp_ops->output_data(drive, NULL, rq->cmd, 12);
+ hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
return ide_started;
}
-ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,
- ide_expiry_t *expiry)
+ide_startstop_t ide_issue_pc(ide_drive_t *drive)
{
- struct ide_atapi_pc *pc = drive->pc;
+ struct ide_atapi_pc *pc;
ide_hwif_t *hwif = drive->hwif;
+ ide_expiry_t *expiry = NULL;
+ unsigned int timeout;
u32 tf_flags;
u16 bcount;
- u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI);
- /* We haven't transferred any data yet */
- pc->xferred = 0;
- pc->cur_pos = pc->buf;
+ if (dev_is_idecd(drive)) {
+ tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
+ bcount = ide_cd_get_xferlen(hwif->rq);
+ expiry = ide_cd_expiry;
+ timeout = ATAPI_WAIT_PC;
- /* Request to transfer the entire buffer at once */
- if (drive->media == ide_tape && scsi == 0)
- bcount = pc->req_xfer;
- else
- bcount = min(pc->req_xfer, 63 * 1024);
+ if (drive->dma)
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
+ } else {
+ pc = drive->pc;
- if (pc->flags & PC_FLAG_DMA_ERROR) {
- pc->flags &= ~PC_FLAG_DMA_ERROR;
- ide_dma_off(drive);
- }
+ /* We haven't transferred any data yet */
+ pc->xferred = 0;
+ pc->cur_pos = pc->buf;
- if ((pc->flags & PC_FLAG_DMA_OK) &&
- (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
- if (scsi)
- hwif->sg_mapped = 1;
- drive->dma = !hwif->dma_ops->dma_setup(drive);
- if (scsi)
- hwif->sg_mapped = 0;
- }
+ tf_flags = IDE_TFLAG_OUT_DEVICE;
+ bcount = ((drive->media == ide_tape) ?
+ pc->req_xfer :
+ min(pc->req_xfer, 63 * 1024));
- if (!drive->dma)
- pc->flags &= ~PC_FLAG_DMA_OK;
+ if (pc->flags & PC_FLAG_DMA_ERROR) {
+ pc->flags &= ~PC_FLAG_DMA_ERROR;
+ ide_dma_off(drive);
+ }
- if (scsi)
- tf_flags = 0;
- else if (drive->media == ide_cdrom || drive->media == ide_optical)
- tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
- else
- tf_flags = IDE_TFLAG_OUT_DEVICE;
+ if ((pc->flags & PC_FLAG_DMA_OK) &&
+ (drive->dev_flags & IDE_DFLAG_USING_DMA))
+ drive->dma = !hwif->dma_ops->dma_setup(drive);
+
+ if (!drive->dma)
+ pc->flags &= ~PC_FLAG_DMA_OK;
+
+ timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+ : WAIT_TAPE_CMD;
+ }
ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
/* Issue the packet command */
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
+ if (drive->dma)
+ drive->waiting_for_dma = 0;
ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
- timeout, NULL);
+ timeout, expiry);
return ide_started;
} else {
ide_execute_pkt_cmd(drive);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 5daa4dd1b018..0bfeb0c79d6e 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -53,14 +53,6 @@
#include "ide-cd.h"
-#define IDECD_DEBUG_LOG 1
-
-#if IDECD_DEBUG_LOG
-#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
-#else
-#define ide_debug_log(lvl, fmt, args...) do {} while (0)
-#endif
-
static DEFINE_MUTEX(idecd_ref_mutex);
static void ide_cd_release(struct kref *);
@@ -247,7 +239,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
static void cdrom_end_request(ide_drive_t *drive, int uptodate)
{
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = drive->hwif->rq;
int nsectors = rq->hard_cur_sectors;
ide_debug_log(IDE_DBG_FUNC, "Call %s, cmd: 0x%x, uptodate: 0x%x, "
@@ -314,8 +306,7 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st)
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
- struct request *rq = hwgroup->rq;
+ struct request *rq = hwif->rq;
int stat, err, sense_key;
/* check for errors */
@@ -510,7 +501,7 @@ end_request:
blkdev_dequeue_request(rq);
spin_unlock_irqrestore(q->queue_lock, flags);
- hwgroup->rq = NULL;
+ hwif->rq = NULL;
cdrom_queue_request_sense(drive, rq->sense, rq);
} else
@@ -519,133 +510,6 @@ end_request:
return 1;
}
-static int cdrom_timer_expiry(ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
- unsigned long wait = 0;
-
- ide_debug_log(IDE_DBG_RQ, "Call %s: rq->cmd[0]: 0x%x\n", __func__,
- rq->cmd[0]);
-
- /*
- * Some commands are *slow* and normally take a long time to complete.
- * Usually we can use the ATAPI "disconnect" to bypass this, but not all
- * commands/drives support that. Let ide_timer_expiry keep polling us
- * for these.
- */
- switch (rq->cmd[0]) {
- case GPCMD_BLANK:
- case GPCMD_FORMAT_UNIT:
- case GPCMD_RESERVE_RZONE_TRACK:
- case GPCMD_CLOSE_TRACK:
- case GPCMD_FLUSH_CACHE:
- wait = ATAPI_WAIT_PC;
- break;
- default:
- if (!(rq->cmd_flags & REQ_QUIET))
- printk(KERN_INFO PFX "cmd 0x%x timed out\n",
- rq->cmd[0]);
- wait = 0;
- break;
- }
- return wait;
-}
-
-/*
- * Set up the device registers for transferring a packet command on DEV,
- * expecting to later transfer XFERLEN bytes. HANDLER is the routine
- * which actually transfers the command to the drive. If this is a
- * drq_interrupt device, this routine will arrange for HANDLER to be
- * called when the interrupt from the drive arrives. Otherwise, HANDLER
- * will be called immediately after the drive is prepared for the transfer.
- */
-static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
- int xferlen,
- ide_handler_t *handler)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- ide_debug_log(IDE_DBG_PC, "Call %s, xferlen: %d\n", __func__, xferlen);
-
- /* FIXME: for Virtual DMA we must check harder */
- if (drive->dma)
- drive->dma = !hwif->dma_ops->dma_setup(drive);
-
- /* set up the controller registers */
- ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL,
- xferlen, drive->dma);
-
- if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
- /* waiting for CDB interrupt, not DMA yet. */
- if (drive->dma)
- drive->waiting_for_dma = 0;
-
- /* packet command */
- ide_execute_command(drive, ATA_CMD_PACKET, handler,
- ATAPI_WAIT_PC, cdrom_timer_expiry);
- return ide_started;
- } else {
- ide_execute_pkt_cmd(drive);
-
- return (*handler) (drive);
- }
-}
-
-/*
- * Send a packet command to DRIVE described by CMD_BUF and CMD_LEN. The device
- * registers must have already been prepared by cdrom_start_packet_command.
- * HANDLER is the interrupt handler to call when the command completes or
- * there's data ready.
- */
-#define ATAPI_MIN_CDB_BYTES 12
-static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
- struct request *rq,
- ide_handler_t *handler)
-{
- ide_hwif_t *hwif = drive->hwif;
- int cmd_len;
- ide_startstop_t startstop;
-
- ide_debug_log(IDE_DBG_PC, "Call %s\n", __func__);
-
- if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
- /*
- * Here we should have been called after receiving an interrupt
- * from the device. DRQ should how be set.
- */
-
- /* check for errors */
- if (cdrom_decode_status(drive, ATA_DRQ, NULL))
- return ide_stopped;
-
- /* ok, next interrupt will be DMA interrupt */
- if (drive->dma)
- drive->waiting_for_dma = 1;
- } else {
- /* otherwise, we must wait for DRQ to get set */
- if (ide_wait_stat(&startstop, drive, ATA_DRQ,
- ATA_BUSY, WAIT_READY))
- return startstop;
- }
-
- /* arm the interrupt handler */
- ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry);
-
- /* ATAPI commands get padded out to 12 bytes minimum */
- cmd_len = COMMAND_SIZE(rq->cmd[0]);
- if (cmd_len < ATAPI_MIN_CDB_BYTES)
- cmd_len = ATAPI_MIN_CDB_BYTES;
-
- /* send the command to the device */
- hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
-
- /* start the DMA if need be */
- if (drive->dma)
- hwif->dma_ops->dma_start(drive);
-
- return ide_started;
-}
-
/*
* Check the contents of the interrupt reason register from the cdrom
* and attempt to recover if there are problems. Returns 0 if everything's
@@ -717,8 +581,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
return 1;
}
-static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
-
static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
struct request *rq)
{
@@ -761,20 +623,6 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
}
/*
- * Routine to send a read/write packet command to the drive. This is usually
- * called directly from cdrom_start_{read,write}(). However, for drq_interrupt
- * devices, it is called from an interrupt when the drive is ready to accept
- * the command.
- */
-static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
-{
- struct request *rq = drive->hwif->hwgroup->rq;
-
- /* send the command to the drive and return */
- return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
-}
-
-/*
* Fix up a possibly partially-processed request so that we can start it over
* entirely, or even put it back on the request queue.
*/
@@ -905,8 +753,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
- struct request *rq = hwgroup->rq;
+ struct request *rq = hwif->rq;
xfer_func_t *xferfunc;
ide_expiry_t *expiry = NULL;
int dma_error = 0, dma, stat, thislen, uptodate = 0;
@@ -940,6 +787,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (blk_fs_request(rq)) {
ide_end_request(drive, 1, rq->nr_sectors);
return ide_stopped;
+ } else if (rq->cmd_type == REQ_TYPE_ATA_PC && !rq->bio) {
+ ide_end_request(drive, 1, 1);
+ return ide_stopped;
}
goto end_request;
}
@@ -1096,7 +946,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
} else {
timeout = ATAPI_WAIT_PC;
if (!blk_fs_request(rq))
- expiry = cdrom_timer_expiry;
+ expiry = ide_cd_expiry;
}
ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
@@ -1112,7 +962,7 @@ end_request:
if (blk_end_request(rq, 0, dlen))
BUG();
- hwgroup->rq = NULL;
+ hwif->rq = NULL;
} else {
if (!uptodate)
rq->cmd_flags |= REQ_FAILED;
@@ -1163,13 +1013,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
return ide_started;
}
-static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
-{
- struct request *rq = HWGROUP(drive)->rq;
-
- return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
-}
-
static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
@@ -1214,18 +1057,12 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
sector_t block)
{
- ide_handler_t *fn;
- int xferlen;
-
ide_debug_log(IDE_DBG_RQ, "Call %s, rq->cmd[0]: 0x%x, "
"rq->cmd_type: 0x%x, block: %llu\n",
__func__, rq->cmd[0], rq->cmd_type,
(unsigned long long)block);
if (blk_fs_request(rq)) {
- xferlen = 32768;
- fn = cdrom_start_rw_cont;
-
if (cdrom_start_rw(drive, rq) == ide_stopped)
return ide_stopped;
@@ -1233,9 +1070,6 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
return ide_stopped;
} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
rq->cmd_type == REQ_TYPE_ATA_PC) {
- xferlen = rq->data_len;
- fn = cdrom_do_newpc_cont;
-
if (!rq->timeout)
rq->timeout = ATAPI_WAIT_PC;
@@ -1250,7 +1084,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
return ide_stopped;
}
- return cdrom_start_packet_command(drive, xferlen, fn);
+ return ide_issue_pc(drive);
}
/*
@@ -1983,7 +1817,7 @@ static void ide_cd_release(struct kref *kref)
static int ide_cd_probe(ide_drive_t *);
-static ide_driver_t ide_cdrom_driver = {
+static struct ide_driver ide_cdrom_driver = {
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-cdrom",
@@ -1994,7 +1828,6 @@ static ide_driver_t ide_cdrom_driver = {
.version = IDECD_VERSION,
.do_request = ide_cd_do_request,
.end_request = ide_end_request,
- .error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
.proc_entries = ide_cd_proc_entries,
.proc_devsets = ide_cd_proc_devsets,
@@ -2149,6 +1982,7 @@ static int ide_cd_probe(ide_drive_t *drive)
}
drive->debug_mask = debug_mask;
+ drive->irq_handler = cdrom_newpc_intr;
info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index d5ce3362dbd1..ac40d6cb90a2 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -8,10 +8,14 @@
#include <linux/cdrom.h>
#include <asm/byteorder.h>
-/*
- * typical timeout for packet command
- */
-#define ATAPI_WAIT_PC (60 * HZ)
+#define IDECD_DEBUG_LOG 0
+
+#if IDECD_DEBUG_LOG
+#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
+#else
+#define ide_debug_log(lvl, fmt, args...) do {} while (0)
+#endif
+
#define ATAPI_WAIT_WRITE_BUSY (10 * HZ)
/************************************************************************/
@@ -29,33 +33,33 @@
/* Structure of a MSF cdrom address. */
struct atapi_msf {
- byte reserved;
- byte minute;
- byte second;
- byte frame;
+ u8 reserved;
+ u8 minute;
+ u8 second;
+ u8 frame;
};
/* Space to hold the disk TOC. */
#define MAX_TRACKS 99
struct atapi_toc_header {
unsigned short toc_length;
- byte first_track;
- byte last_track;
+ u8 first_track;
+ u8 last_track;
};
struct atapi_toc_entry {
- byte reserved1;
+ u8 reserved1;
#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 adr : 4;
- __u8 control : 4;
+ u8 adr : 4;
+ u8 control : 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
- __u8 control : 4;
- __u8 adr : 4;
+ u8 control : 4;
+ u8 adr : 4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
- byte track;
- byte reserved2;
+ u8 track;
+ u8 reserved2;
union {
unsigned lba;
struct atapi_msf msf;
@@ -73,10 +77,10 @@ struct atapi_toc {
/* Extra per-device info for cdrom drives. */
struct cdrom_info {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
+ ide_drive_t *drive;
+ struct ide_driver *driver;
+ struct gendisk *disk;
+ struct kref kref;
/* Buffer for table of contents. NULL if we haven't allocated
a TOC buffer for this device yet. */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index eb9fac4d0f0c..806760d24cef 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -89,7 +89,7 @@ static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
sector_t block)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u16 nsectors = (u16)rq->nr_sectors;
u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
@@ -187,7 +187,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
sector_t block)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
@@ -633,7 +633,7 @@ static void ide_disk_setup(ide_drive_t *drive)
printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
q->max_sectors / 2);
- if (ata_id_is_ssd(id) || ata_id_is_cfa(id))
+ if (ata_id_is_ssd(id))
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
/* calculate drive capacity, and select LBA if possible */
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c
index f6d2d44d8a9a..123d393658af 100644
--- a/drivers/ide/ide-dma-sff.c
+++ b/drivers/ide/ide-dma-sff.c
@@ -50,6 +50,27 @@ int config_drive_for_dma(ide_drive_t *drive)
return 0;
}
+u8 ide_dma_sff_read_status(ide_hwif_t *hwif)
+{
+ unsigned long addr = hwif->dma_base + ATA_DMA_STATUS;
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ return readb((void __iomem *)addr);
+ else
+ return inb(addr);
+}
+EXPORT_SYMBOL_GPL(ide_dma_sff_read_status);
+
+static void ide_dma_sff_write_status(ide_hwif_t *hwif, u8 val)
+{
+ unsigned long addr = hwif->dma_base + ATA_DMA_STATUS;
+
+ if (hwif->host_flags & IDE_HFLAG_MMIO)
+ writeb(val, (void __iomem *)addr);
+ else
+ outb(val, addr);
+}
+
/**
* ide_dma_host_set - Enable/disable DMA on a host
* @drive: drive to control
@@ -62,18 +83,14 @@ void ide_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = drive->hwif;
u8 unit = drive->dn & 1;
- u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
if (on)
dma_stat |= (1 << (5 + unit));
else
dma_stat &= ~(1 << (5 + unit));
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- writeb(dma_stat,
- (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
- else
- outb(dma_stat, hwif->dma_base + ATA_DMA_STATUS);
+ ide_dma_sff_write_status(hwif, dma_stat);
}
EXPORT_SYMBOL_GPL(ide_dma_host_set);
@@ -175,7 +192,7 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
int ide_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
unsigned int reading = rq_data_dir(rq) ? 0 : ATA_DMA_WR;
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 dma_stat;
@@ -187,7 +204,7 @@ int ide_dma_setup(ide_drive_t *drive)
}
/* PRD table */
- if (hwif->host_flags & IDE_HFLAG_MMIO)
+ if (mmio)
writel(hwif->dmatable_dma,
(void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
else
@@ -200,15 +217,10 @@ int ide_dma_setup(ide_drive_t *drive)
outb(reading, hwif->dma_base + ATA_DMA_CMD);
/* read DMA status for INTR & ERROR flags */
- dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
/* clear INTR & ERROR flags */
- if (mmio)
- writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
- (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
- else
- outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
- hwif->dma_base + ATA_DMA_STATUS);
+ ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR);
drive->waiting_for_dma = 1;
return 0;
@@ -232,7 +244,7 @@ EXPORT_SYMBOL_GPL(ide_dma_setup);
static int dma_timer_expiry(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n",
drive->name, __func__, dma_stat);
@@ -240,7 +252,7 @@ static int dma_timer_expiry(ide_drive_t *drive)
if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */
return WAIT_CMD;
- hwif->hwgroup->expiry = NULL; /* one free ride for now */
+ hwif->expiry = NULL; /* one free ride for now */
if (dma_stat & ATA_DMA_ERR) /* ERROR */
return -1;
@@ -289,13 +301,12 @@ EXPORT_SYMBOL_GPL(ide_dma_start);
int ide_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 dma_stat = 0, dma_cmd = 0, mask;
drive->waiting_for_dma = 0;
/* stop DMA */
- if (mmio) {
+ if (hwif->host_flags & IDE_HFLAG_MMIO) {
dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
writeb(dma_cmd & ~ATA_DMA_START,
(void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
@@ -305,15 +316,10 @@ int ide_dma_end(ide_drive_t *drive)
}
/* get DMA status */
- dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
- if (mmio)
- /* clear the INTR & ERROR bits */
- writeb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
- (void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
- else
- outb(dma_stat | ATA_DMA_ERR | ATA_DMA_INTR,
- hwif->dma_base + ATA_DMA_STATUS);
+ /* clear INTR & ERROR bits */
+ ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR);
/* purge DMA mappings */
ide_destroy_dmatable(drive);
@@ -331,7 +337,7 @@ EXPORT_SYMBOL_GPL(ide_dma_end);
int ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- u8 dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
return (dma_stat & ATA_DMA_INTR) ? 1 : 0;
}
@@ -346,5 +352,6 @@ const struct ide_dma_ops sff_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
EXPORT_SYMBOL_GPL(sff_dma_ops);
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index fffd11717b2d..72ebab0bc755 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -96,7 +96,7 @@ ide_startstop_t ide_dma_intr(ide_drive_t *drive)
if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
if (!dma_stat) {
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
task_end_request(drive, rq, stat);
return ide_stopped;
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index aeb1ad782f54..3eab1c6c9b31 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -71,7 +71,7 @@
static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = drive->hwif->rq;
int error;
ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
@@ -197,7 +197,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
pc->retries++;
- return ide_issue_pc(drive, WAIT_FLOPPY_CMD, NULL);
+ return ide_issue_pc(drive);
}
void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *pc)
@@ -342,38 +342,38 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
* Look at the flexible disk page parameters. We ignore the CHS capacity
* parameters and use the LBA parameters instead.
*/
-static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
+static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive,
+ struct ide_atapi_pc *pc)
{
struct ide_disk_obj *floppy = drive->driver_data;
struct gendisk *disk = floppy->disk;
- struct ide_atapi_pc pc;
u8 *page;
int capacity, lba_capacity;
u16 transfer_rate, sector_size, cyls, rpm;
u8 heads, sectors;
- ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
+ ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE);
- if (ide_queue_pc_tail(drive, disk, &pc)) {
+ if (ide_queue_pc_tail(drive, disk, pc)) {
printk(KERN_ERR PFX "Can't get flexible disk page params\n");
return 1;
}
- if (pc.buf[3] & 0x80)
+ if (pc->buf[3] & 0x80)
drive->dev_flags |= IDE_DFLAG_WP;
else
drive->dev_flags &= ~IDE_DFLAG_WP;
set_disk_ro(disk, !!(drive->dev_flags & IDE_DFLAG_WP));
- page = &pc.buf[8];
+ page = &pc->buf[8];
- transfer_rate = be16_to_cpup((__be16 *)&pc.buf[8 + 2]);
- sector_size = be16_to_cpup((__be16 *)&pc.buf[8 + 6]);
- cyls = be16_to_cpup((__be16 *)&pc.buf[8 + 8]);
- rpm = be16_to_cpup((__be16 *)&pc.buf[8 + 28]);
- heads = pc.buf[8 + 4];
- sectors = pc.buf[8 + 5];
+ transfer_rate = be16_to_cpup((__be16 *)&pc->buf[8 + 2]);
+ sector_size = be16_to_cpup((__be16 *)&pc->buf[8 + 6]);
+ cyls = be16_to_cpup((__be16 *)&pc->buf[8 + 8]);
+ rpm = be16_to_cpup((__be16 *)&pc->buf[8 + 28]);
+ heads = pc->buf[8 + 4];
+ sectors = pc->buf[8 + 5];
capacity = cyls * heads * sectors * sector_size;
@@ -499,7 +499,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
/* Clik! disk does not support get_flexible_disk_page */
if (!(drive->atapi_flags & IDE_AFLAG_CLIK_DRIVE))
- (void) ide_floppy_get_flexible_disk_page(drive);
+ (void) ide_floppy_get_flexible_disk_page(drive, &pc);
return rc;
}
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index 2bc51ff73fee..8f8be8546038 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -31,10 +31,11 @@
* On exit we set nformats to the number of records we've actually initialized.
*/
-static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+static int ide_floppy_get_format_capacities(ide_drive_t *drive,
+ struct ide_atapi_pc *pc,
+ int __user *arg)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
u8 header_len, desc_cnt;
int i, blocks, length, u_array_size, u_index;
int __user *argp;
@@ -45,13 +46,13 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
if (u_array_size <= 0)
return -EINVAL;
- ide_floppy_create_read_capacity_cmd(&pc);
- if (ide_queue_pc_tail(drive, floppy->disk, &pc)) {
+ ide_floppy_create_read_capacity_cmd(pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, pc)) {
printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
return -EIO;
}
- header_len = pc.buf[3];
+ header_len = pc->buf[3];
desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
u_index = 0;
@@ -68,8 +69,8 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
if (u_index >= u_array_size)
break; /* User-supplied buffer too small */
- blocks = be32_to_cpup((__be32 *)&pc.buf[desc_start]);
- length = be16_to_cpup((__be16 *)&pc.buf[desc_start + 6]);
+ blocks = be32_to_cpup((__be32 *)&pc->buf[desc_start]);
+ length = be16_to_cpup((__be16 *)&pc->buf[desc_start + 6]);
if (put_user(blocks, argp))
return -EFAULT;
@@ -111,29 +112,28 @@ static void ide_floppy_create_format_unit_cmd(struct ide_atapi_pc *pc, int b,
pc->flags |= PC_FLAG_WRITING;
}
-static int ide_floppy_get_sfrp_bit(ide_drive_t *drive)
+static int ide_floppy_get_sfrp_bit(ide_drive_t *drive, struct ide_atapi_pc *pc)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
drive->atapi_flags &= ~IDE_AFLAG_SRFP;
- ide_floppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE);
- pc.flags |= PC_FLAG_SUPPRESS_ERROR;
+ ide_floppy_create_mode_sense_cmd(pc, IDEFLOPPY_CAPABILITIES_PAGE);
+ pc->flags |= PC_FLAG_SUPPRESS_ERROR;
- if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ if (ide_queue_pc_tail(drive, floppy->disk, pc))
return 1;
- if (pc.buf[8 + 2] & 0x40)
+ if (pc->buf[8 + 2] & 0x40)
drive->atapi_flags |= IDE_AFLAG_SRFP;
return 0;
}
-static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
+static int ide_floppy_format_unit(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ int __user *arg)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
int blocks, length, flags, err = 0;
if (floppy->openers > 1) {
@@ -166,10 +166,10 @@ static int ide_floppy_format_unit(ide_drive_t *drive, int __user *arg)
goto out;
}
- (void)ide_floppy_get_sfrp_bit(drive);
- ide_floppy_create_format_unit_cmd(&pc, blocks, length, flags);
+ ide_floppy_get_sfrp_bit(drive, pc);
+ ide_floppy_create_format_unit_cmd(pc, blocks, length, flags);
- if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ if (ide_queue_pc_tail(drive, floppy->disk, pc))
err = -EIO;
out:
@@ -188,15 +188,16 @@ out:
* the dsc bit, and return either 0 or 65536.
*/
-static int ide_floppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+static int ide_floppy_get_format_progress(ide_drive_t *drive,
+ struct ide_atapi_pc *pc,
+ int __user *arg)
{
struct ide_disk_obj *floppy = drive->driver_data;
- struct ide_atapi_pc pc;
int progress_indication = 0x10000;
if (drive->atapi_flags & IDE_AFLAG_SRFP) {
- ide_create_request_sense_cmd(drive, &pc);
- if (ide_queue_pc_tail(drive, floppy->disk, &pc))
+ ide_create_request_sense_cmd(drive, pc);
+ if (ide_queue_pc_tail(drive, floppy->disk, pc))
return -EIO;
if (floppy->sense_key == 2 &&
@@ -241,20 +242,21 @@ static int ide_floppy_lockdoor(ide_drive_t *drive, struct ide_atapi_pc *pc,
return 0;
}
-static int ide_floppy_format_ioctl(ide_drive_t *drive, fmode_t mode,
- unsigned int cmd, void __user *argp)
+static int ide_floppy_format_ioctl(ide_drive_t *drive, struct ide_atapi_pc *pc,
+ fmode_t mode, unsigned int cmd,
+ void __user *argp)
{
switch (cmd) {
case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
return 0;
case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
- return ide_floppy_get_format_capacities(drive, argp);
+ return ide_floppy_get_format_capacities(drive, pc, argp);
case IDEFLOPPY_IOCTL_FORMAT_START:
if (!(mode & FMODE_WRITE))
return -EPERM;
- return ide_floppy_format_unit(drive, (int __user *)argp);
+ return ide_floppy_format_unit(drive, pc, (int __user *)argp);
case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
- return ide_floppy_get_format_progress(drive, argp);
+ return ide_floppy_get_format_progress(drive, pc, argp);
default:
return -ENOTTY;
}
@@ -270,7 +272,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
if (cmd == CDROMEJECT || cmd == CDROM_LOCKDOOR)
return ide_floppy_lockdoor(drive, &pc, arg, cmd);
- err = ide_floppy_format_ioctl(drive, mode, cmd, argp);
+ err = ide_floppy_format_ioctl(drive, &pc, mode, cmd, argp);
if (err != -ENOTTY)
return err;
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index b8078b3231f7..7857b209c6df 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -149,7 +149,7 @@ static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs)
return drive->disk_ops->end_request(drive, uptodate, nrsecs);
}
-static ide_driver_t ide_gd_driver = {
+static struct ide_driver ide_gd_driver = {
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-gd",
@@ -162,7 +162,6 @@ static ide_driver_t ide_gd_driver = {
.version = IDE_GD_VERSION,
.do_request = ide_gd_do_request,
.end_request = ide_gd_end_request,
- .error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
.proc_entries = ide_disk_proc_entries,
.proc_devsets = ide_disk_proc_devsets,
diff --git a/drivers/ide/ide-gd.h b/drivers/ide/ide-gd.h
index 7d3d101713e0..a86779f0756b 100644
--- a/drivers/ide/ide-gd.h
+++ b/drivers/ide/ide-gd.h
@@ -14,11 +14,11 @@
#endif
struct ide_disk_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
- unsigned int openers; /* protected by BKL for now */
+ ide_drive_t *drive;
+ struct ide_driver *driver;
+ struct gendisk *disk;
+ struct kref kref;
+ unsigned int openers; /* protected by BKL for now */
/* Last failed packet command */
struct ide_atapi_pc *failed_pc;
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c
index e2cdd2e9cdec..9270d3255ee0 100644
--- a/drivers/ide/ide-h8300.c
+++ b/drivers/ide/ide-h8300.c
@@ -159,7 +159,6 @@ static const struct ide_tp_ops h8300_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ecacc008fdaf..9ee51adf567f 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -88,7 +88,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
ret = 0;
if (ret == 0 && dequeue)
- drive->hwif->hwgroup->rq = NULL;
+ drive->hwif->rq = NULL;
return ret;
}
@@ -107,7 +107,7 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
{
unsigned int nr_bytes = nr_sectors << 9;
- struct request *rq = drive->hwif->hwgroup->rq;
+ struct request *rq = drive->hwif->rq;
if (!nr_bytes) {
if (blk_pc_request(rq))
@@ -160,8 +160,8 @@ EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
{
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
- struct request *rq = hwgroup->rq;
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->rq;
if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
ide_task_t *task = (ide_task_t *)rq->special;
@@ -186,7 +186,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
return;
}
- hwgroup->rq = NULL;
+ hwif->rq = NULL;
rq->errors = err;
@@ -199,9 +199,9 @@ EXPORT_SYMBOL(ide_end_drive_cmd);
static void ide_kill_rq(ide_drive_t *drive, struct request *rq)
{
if (rq->rq_disk) {
- ide_driver_t *drv;
+ struct ide_driver *drv;
- drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ drv = *(struct ide_driver **)rq->rq_disk->private_data;
drv->end_request(drive, 0, 0);
} else
ide_end_request(drive, 0, 0);
@@ -291,7 +291,7 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
return ide_stopped;
}
-ide_startstop_t
+static ide_startstop_t
__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
if (drive->media == ide_disk)
@@ -299,8 +299,6 @@ __ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
return ide_atapi_error(drive, rq, stat, err);
}
-EXPORT_SYMBOL_GPL(__ide_error);
-
/**
* ide_error - handle an error on the IDE
* @drive: drive the error occurred on
@@ -321,7 +319,8 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
err = ide_dump_status(drive, msg, stat);
- if ((rq = HWGROUP(drive)->rq) == NULL)
+ rq = drive->hwif->rq;
+ if (rq == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
@@ -331,15 +330,8 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
return ide_stopped;
}
- if (rq->rq_disk) {
- ide_driver_t *drv;
-
- drv = *(ide_driver_t **)rq->rq_disk->private_data;
- return drv->error(drive, rq, stat, err);
- } else
- return __ide_error(drive, rq, stat, err);
+ return __ide_error(drive, rq, stat, err);
}
-
EXPORT_SYMBOL_GPL(ide_error);
static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
@@ -426,14 +418,14 @@ void ide_map_sg(ide_drive_t *drive, struct request *rq)
ide_hwif_t *hwif = drive->hwif;
struct scatterlist *sg = hwif->sg_table;
- if (hwif->sg_mapped) /* needed by ide-scsi */
- return;
-
- if (rq->cmd_type != REQ_TYPE_ATA_TASKFILE) {
- hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
- } else {
+ if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
hwif->sg_nents = 1;
+ } else if (!rq->bio) {
+ sg_init_one(sg, rq->data, rq->data_len);
+ hwif->sg_nents = 1;
+ } else {
+ hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
}
}
@@ -465,7 +457,7 @@ EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
struct request *rq)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
ide_task_t *task = rq->special;
if (task) {
@@ -589,7 +581,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
#ifdef DEBUG
printk("%s: start_request: current=0x%08lx\n",
- HWIF(drive)->name, (unsigned long) rq);
+ drive->hwif->name, (unsigned long) rq);
#endif
/* bail early if we've exceeded max_failures */
@@ -608,7 +600,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
return startstop;
}
if (!drive->special.all) {
- ide_driver_t *drv;
+ struct ide_driver *drv;
/*
* We reset the drive so we need to issue a SETFEATURES.
@@ -641,7 +633,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
*/
return ide_special_rq(drive, rq);
- drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ drv = *(struct ide_driver **)rq->rq_disk->private_data;
return drv->do_request(drive, rq, rq->sector);
}
@@ -657,7 +649,7 @@ kill_rq:
* @timeout: time to stall for (jiffies)
*
* ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
+ * to the port by sleeping for timeout jiffies.
*/
void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
@@ -667,201 +659,117 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
drive->sleep = timeout + jiffies;
drive->dev_flags |= IDE_DFLAG_SLEEPING;
}
-
EXPORT_SYMBOL(ide_stall_queue);
-#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time)
+static inline int ide_lock_port(ide_hwif_t *hwif)
+{
+ if (hwif->busy)
+ return 1;
-/**
- * choose_drive - select a drive to service
- * @hwgroup: hardware group to select on
- *
- * choose_drive() selects the next drive which will be serviced.
- * This is necessary because the IDE layer can't issue commands
- * to both drives on the same cable, unlike SCSI.
- */
-
-static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
+ hwif->busy = 1;
+
+ return 0;
+}
+
+static inline void ide_unlock_port(ide_hwif_t *hwif)
+{
+ hwif->busy = 0;
+}
+
+static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif)
+{
+ int rc = 0;
+
+ if (host->host_flags & IDE_HFLAG_SERIALIZE) {
+ rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy);
+ if (rc == 0) {
+ /* for atari only */
+ ide_get_lock(ide_intr, hwif);
+ }
+ }
+ return rc;
+}
+
+static inline void ide_unlock_host(struct ide_host *host)
{
- ide_drive_t *drive, *best;
+ if (host->host_flags & IDE_HFLAG_SERIALIZE) {
+ /* for atari only */
+ ide_release_lock();
+ clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy);
+ }
+}
-repeat:
- best = NULL;
- drive = hwgroup->drive;
+/*
+ * Issue a new request to a device.
+ */
+void do_ide_request(struct request_queue *q)
+{
+ ide_drive_t *drive = q->queuedata;
+ ide_hwif_t *hwif = drive->hwif;
+ struct ide_host *host = hwif->host;
+ struct request *rq = NULL;
+ ide_startstop_t startstop;
/*
* drive is doing pre-flush, ordered write, post-flush sequence. even
* though that is 3 requests, it must be seen as a single transaction.
* we must not preempt this drive until that is complete
*/
- if (blk_queue_flushing(drive->queue)) {
+ if (blk_queue_flushing(q))
/*
* small race where queue could get replugged during
* the 3-request flush cycle, just yank the plug since
* we want it to finish asap
*/
- blk_remove_plug(drive->queue);
- return drive;
- }
+ blk_remove_plug(q);
- do {
- u8 dev_s = !!(drive->dev_flags & IDE_DFLAG_SLEEPING);
- u8 best_s = (best && !!(best->dev_flags & IDE_DFLAG_SLEEPING));
-
- if ((dev_s == 0 || time_after_eq(jiffies, drive->sleep)) &&
- !elv_queue_empty(drive->queue)) {
- if (best == NULL ||
- (dev_s && (best_s == 0 || time_before(drive->sleep, best->sleep))) ||
- (best_s == 0 && time_before(WAKEUP(drive), WAKEUP(best)))) {
- if (!blk_queue_plugged(drive->queue))
- best = drive;
- }
- }
- } while ((drive = drive->next) != hwgroup->drive);
+ spin_unlock_irq(q->queue_lock);
- if (best && (best->dev_flags & IDE_DFLAG_NICE1) &&
- (best->dev_flags & IDE_DFLAG_SLEEPING) == 0 &&
- best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
- long t = (signed long)(WAKEUP(best) - jiffies);
- if (t >= WAIT_MIN_SLEEP) {
- /*
- * We *may* have some time to spare, but first let's see if
- * someone can potentially benefit from our nice mood today..
- */
- drive = best->next;
- do {
- if ((drive->dev_flags & IDE_DFLAG_SLEEPING) == 0
- && time_before(jiffies - best->service_time, WAKEUP(drive))
- && time_before(WAKEUP(drive), jiffies + t))
- {
- ide_stall_queue(best, min_t(long, t, 10 * WAIT_MIN_SLEEP));
- goto repeat;
- }
- } while ((drive = drive->next) != best);
- }
- }
- return best;
-}
+ if (ide_lock_host(host, hwif))
+ goto plug_device_2;
-/*
- * Issue a new request to a drive from hwgroup
- * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..);
- *
- * A hwgroup is a serialized group of IDE interfaces. Usually there is
- * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
- * may have both interfaces in a single hwgroup to "serialize" access.
- * Or possibly multiple ISA interfaces can share a common IRQ by being grouped
- * together into one hwgroup for serialized access.
- *
- * Note also that several hwgroups can end up sharing a single IRQ,
- * possibly along with many other devices. This is especially common in
- * PCI-based systems with off-board IDE controller cards.
- *
- * The IDE driver uses a per-hwgroup spinlock to protect
- * access to the request queues, and to protect the hwgroup->busy flag.
- *
- * The first thread into the driver for a particular hwgroup sets the
- * hwgroup->busy flag to indicate that this hwgroup is now active,
- * and then initiates processing of the top request from the request queue.
- *
- * Other threads attempting entry notice the busy setting, and will simply
- * queue their new requests and exit immediately. Note that hwgroup->busy
- * remains set even when the driver is merely awaiting the next interrupt.
- * Thus, the meaning is "this hwgroup is busy processing a request".
- *
- * When processing of a request completes, the completing thread or IRQ-handler
- * will start the next request from the queue. If no more work remains,
- * the driver will clear the hwgroup->busy flag and exit.
- *
- * The per-hwgroup spinlock is used to protect all access to the
- * hwgroup->busy flag, but is otherwise not needed for most processing in
- * the driver. This makes the driver much more friendlier to shared IRQs
- * than previous designs, while remaining 100% (?) SMP safe and capable.
- */
-static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
-{
- ide_drive_t *drive;
- ide_hwif_t *hwif;
- struct request *rq;
- ide_startstop_t startstop;
- int loops = 0;
+ spin_lock_irq(&hwif->lock);
- /* caller must own hwgroup->lock */
- BUG_ON(!irqs_disabled());
+ if (!ide_lock_port(hwif)) {
+ ide_hwif_t *prev_port;
+repeat:
+ prev_port = hwif->host->cur_port;
+ hwif->rq = NULL;
- while (!hwgroup->busy) {
- hwgroup->busy = 1;
- /* for atari only */
- ide_get_lock(ide_intr, hwgroup);
- drive = choose_drive(hwgroup);
- if (drive == NULL) {
- int sleeping = 0;
- unsigned long sleep = 0; /* shut up, gcc */
- hwgroup->rq = NULL;
- drive = hwgroup->drive;
- do {
- if ((drive->dev_flags & IDE_DFLAG_SLEEPING) &&
- (sleeping == 0 ||
- time_before(drive->sleep, sleep))) {
- sleeping = 1;
- sleep = drive->sleep;
- }
- } while ((drive = drive->next) != hwgroup->drive);
- if (sleeping) {
- /*
- * Take a short snooze, and then wake up this hwgroup again.
- * This gives other hwgroups on the same a chance to
- * play fairly with us, just in case there are big differences
- * in relative throughputs.. don't want to hog the cpu too much.
- */
- if (time_before(sleep, jiffies + WAIT_MIN_SLEEP))
- sleep = jiffies + WAIT_MIN_SLEEP;
-#if 1
- if (timer_pending(&hwgroup->timer))
- printk(KERN_CRIT "ide_set_handler: timer already active\n");
-#endif
- /* so that ide_timer_expiry knows what to do */
- hwgroup->sleeping = 1;
- hwgroup->req_gen_timer = hwgroup->req_gen;
- mod_timer(&hwgroup->timer, sleep);
- /* we purposely leave hwgroup->busy==1
- * while sleeping */
- } else {
- /* Ugly, but how can we sleep for the lock
- * otherwise? perhaps from tq_disk?
- */
-
- /* for atari only */
- ide_release_lock();
- hwgroup->busy = 0;
+ if (drive->dev_flags & IDE_DFLAG_SLEEPING) {
+ if (time_before(drive->sleep, jiffies)) {
+ ide_unlock_port(hwif);
+ goto plug_device;
}
-
- /* no more work for this hwgroup (for now) */
- return;
}
- again:
- hwif = HWIF(drive);
- if (hwif != hwgroup->hwif) {
+
+ if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) &&
+ hwif != prev_port) {
/*
- * set nIEN for previous hwif, drives in the
+ * set nIEN for previous port, drives in the
* quirk_list may not like intr setups/cleanups
*/
- if (drive->quirk_list == 0)
- hwif->tp_ops->set_irq(hwif, 0);
+ if (prev_port && prev_port->cur_dev->quirk_list == 0)
+ prev_port->tp_ops->set_irq(prev_port, 0);
+
+ hwif->host->cur_port = hwif;
}
- hwgroup->hwif = hwif;
- hwgroup->drive = drive;
+ hwif->cur_dev = drive;
drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
- drive->service_start = jiffies;
+ spin_unlock_irq(&hwif->lock);
+ spin_lock_irq(q->queue_lock);
/*
* we know that the queue isn't empty, but this can happen
* if the q->prep_rq_fn() decides to kill a request
*/
rq = elv_next_request(drive->queue);
+ spin_unlock_irq(q->queue_lock);
+ spin_lock_irq(&hwif->lock);
+
if (!rq) {
- hwgroup->busy = 0;
- break;
+ ide_unlock_port(hwif);
+ goto out;
}
/*
@@ -876,63 +784,50 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
* though. I hope that doesn't happen too much, hopefully not
* unless the subdriver triggers such a thing in its own PM
* state machine.
- *
- * We count how many times we loop here to make sure we service
- * all drives in the hwgroup without looping for ever
*/
if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
blk_pm_request(rq) == 0 &&
(rq->cmd_flags & REQ_PREEMPT) == 0) {
- drive = drive->next ? drive->next : hwgroup->drive;
- if (loops++ < 4 && !blk_queue_plugged(drive->queue))
- goto again;
- /* We clear busy, there should be no pending ATA command at this point. */
- hwgroup->busy = 0;
- break;
+ /* there should be no pending command at this point */
+ ide_unlock_port(hwif);
+ goto plug_device;
}
- hwgroup->rq = rq;
+ hwif->rq = rq;
- /*
- * Some systems have trouble with IDE IRQs arriving while
- * the driver is still setting things up. So, here we disable
- * the IRQ used by this interface while the request is being started.
- * This may look bad at first, but pretty much the same thing
- * happens anyway when any interrupt comes in, IDE or otherwise
- * -- the kernel masks the IRQ while it is being handled.
- */
- if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
- disable_irq_nosync(hwif->irq);
- spin_unlock(&hwgroup->lock);
- local_irq_enable_in_hardirq();
- /* allow other IRQs while we start this request */
+ spin_unlock_irq(&hwif->lock);
startstop = start_request(drive, rq);
- spin_lock_irq(&hwgroup->lock);
- if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
- enable_irq(hwif->irq);
- if (startstop == ide_stopped)
- hwgroup->busy = 0;
- }
-}
-
-/*
- * Passes the stuff to ide_do_request
- */
-void do_ide_request(struct request_queue *q)
-{
- ide_drive_t *drive = q->queuedata;
+ spin_lock_irq(&hwif->lock);
- ide_do_request(HWGROUP(drive), IDE_NO_IRQ);
+ if (startstop == ide_stopped)
+ goto repeat;
+ } else
+ goto plug_device;
+out:
+ spin_unlock_irq(&hwif->lock);
+ if (rq == NULL)
+ ide_unlock_host(host);
+ spin_lock_irq(q->queue_lock);
+ return;
+
+plug_device:
+ spin_unlock_irq(&hwif->lock);
+ ide_unlock_host(host);
+plug_device_2:
+ spin_lock_irq(q->queue_lock);
+
+ if (!elv_queue_empty(q))
+ blk_plug_device(q);
}
/*
- * un-busy the hwgroup etc, and clear any pending DMA status. we want to
+ * un-busy the port etc, and clear any pending DMA status. we want to
* retry the current request in pio mode instead of risking tossing it
* all away
*/
static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct request *rq;
ide_startstop_t ret = ide_stopped;
@@ -960,15 +855,14 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
ide_dma_off_quietly(drive);
/*
- * un-busy drive etc (hwgroup->busy is cleared on return) and
- * make sure request is sane
+ * un-busy drive etc and make sure request is sane
*/
- rq = HWGROUP(drive)->rq;
+ rq = hwif->rq;
if (!rq)
goto out;
- HWGROUP(drive)->rq = NULL;
+ hwif->rq = NULL;
rq->errors = 0;
@@ -983,9 +877,20 @@ out:
return ret;
}
+static void ide_plug_device(ide_drive_t *drive)
+{
+ struct request_queue *q = drive->queue;
+ unsigned long flags;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ if (!elv_queue_empty(q))
+ blk_plug_device(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
/**
* ide_timer_expiry - handle lack of an IDE interrupt
- * @data: timer callback magic (hwgroup)
+ * @data: timer callback magic (hwif)
*
* An IDE command has timed out before the expected drive return
* occurred. At this point we attempt to clean up the current
@@ -999,93 +904,87 @@ out:
void ide_timer_expiry (unsigned long data)
{
- ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
+ ide_hwif_t *hwif = (ide_hwif_t *)data;
+ ide_drive_t *uninitialized_var(drive);
ide_handler_t *handler;
- ide_expiry_t *expiry;
unsigned long flags;
unsigned long wait = -1;
+ int plug_device = 0;
+
+ spin_lock_irqsave(&hwif->lock, flags);
- spin_lock_irqsave(&hwgroup->lock, flags);
+ handler = hwif->handler;
- if (((handler = hwgroup->handler) == NULL) ||
- (hwgroup->req_gen != hwgroup->req_gen_timer)) {
+ if (handler == NULL || hwif->req_gen != hwif->req_gen_timer) {
/*
* Either a marginal timeout occurred
* (got the interrupt just as timer expired),
* or we were "sleeping" to give other devices a chance.
* Either way, we don't really want to complain about anything.
*/
- if (hwgroup->sleeping) {
- hwgroup->sleeping = 0;
- hwgroup->busy = 0;
- }
} else {
- ide_drive_t *drive = hwgroup->drive;
- if (!drive) {
- printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n");
- hwgroup->handler = NULL;
- } else {
- ide_hwif_t *hwif;
- ide_startstop_t startstop = ide_stopped;
- if (!hwgroup->busy) {
- hwgroup->busy = 1; /* paranoia */
- printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);
- }
- if ((expiry = hwgroup->expiry) != NULL) {
- /* continue */
- if ((wait = expiry(drive)) > 0) {
- /* reset timer */
- hwgroup->timer.expires = jiffies + wait;
- hwgroup->req_gen_timer = hwgroup->req_gen;
- add_timer(&hwgroup->timer);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
- return;
- }
- }
- hwgroup->handler = NULL;
- /*
- * We need to simulate a real interrupt when invoking
- * the handler() function, which means we need to
- * globally mask the specific IRQ:
- */
- spin_unlock(&hwgroup->lock);
- hwif = HWIF(drive);
- /* disable_irq_nosync ?? */
- disable_irq(hwif->irq);
- /* local CPU only,
- * as if we were handling an interrupt */
- local_irq_disable();
- if (hwgroup->polling) {
- startstop = handler(drive);
- } else if (drive_is_ready(drive)) {
- if (drive->waiting_for_dma)
- hwif->dma_ops->dma_lost_irq(drive);
- (void)ide_ack_intr(hwif);
- printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
- startstop = handler(drive);
- } else {
- if (drive->waiting_for_dma) {
- startstop = ide_dma_timeout_retry(drive, wait);
- } else
- startstop =
- ide_error(drive, "irq timeout",
- hwif->tp_ops->read_status(hwif));
+ ide_expiry_t *expiry = hwif->expiry;
+ ide_startstop_t startstop = ide_stopped;
+
+ drive = hwif->cur_dev;
+
+ if (expiry) {
+ wait = expiry(drive);
+ if (wait > 0) { /* continue */
+ /* reset timer */
+ hwif->timer.expires = jiffies + wait;
+ hwif->req_gen_timer = hwif->req_gen;
+ add_timer(&hwif->timer);
+ spin_unlock_irqrestore(&hwif->lock, flags);
+ return;
}
- drive->service_time = jiffies - drive->service_start;
- spin_lock_irq(&hwgroup->lock);
- enable_irq(hwif->irq);
- if (startstop == ide_stopped)
- hwgroup->busy = 0;
}
+ hwif->handler = NULL;
+ /*
+ * We need to simulate a real interrupt when invoking
+ * the handler() function, which means we need to
+ * globally mask the specific IRQ:
+ */
+ spin_unlock(&hwif->lock);
+ /* disable_irq_nosync ?? */
+ disable_irq(hwif->irq);
+ /* local CPU only, as if we were handling an interrupt */
+ local_irq_disable();
+ if (hwif->polling) {
+ startstop = handler(drive);
+ } else if (drive_is_ready(drive)) {
+ if (drive->waiting_for_dma)
+ hwif->dma_ops->dma_lost_irq(drive);
+ (void)ide_ack_intr(hwif);
+ printk(KERN_WARNING "%s: lost interrupt\n",
+ drive->name);
+ startstop = handler(drive);
+ } else {
+ if (drive->waiting_for_dma)
+ startstop = ide_dma_timeout_retry(drive, wait);
+ else
+ startstop = ide_error(drive, "irq timeout",
+ hwif->tp_ops->read_status(hwif));
+ }
+ spin_lock_irq(&hwif->lock);
+ enable_irq(hwif->irq);
+ if (startstop == ide_stopped) {
+ ide_unlock_port(hwif);
+ plug_device = 1;
+ }
+ }
+ spin_unlock_irqrestore(&hwif->lock, flags);
+
+ if (plug_device) {
+ ide_unlock_host(hwif->host);
+ ide_plug_device(drive);
}
- ide_do_request(hwgroup, IDE_NO_IRQ);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
}
/**
* unexpected_intr - handle an unexpected IDE interrupt
* @irq: interrupt line
- * @hwgroup: hwgroup being processed
+ * @hwif: port being processed
*
* There's nothing really useful we can do with an unexpected interrupt,
* other than reading the status register (to clear it), and logging it.
@@ -1109,52 +1008,38 @@ void ide_timer_expiry (unsigned long data)
* before completing the issuance of any new drive command, so we will not
* be accidentally invoked as a result of any valid command completion
* interrupt.
- *
- * Note that we must walk the entire hwgroup here. We know which hwif
- * is doing the current command, but we don't know which hwif burped
- * mysteriously.
*/
-
-static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
-{
- u8 stat;
- ide_hwif_t *hwif = hwgroup->hwif;
- /*
- * handle the unexpected interrupt
- */
- do {
- if (hwif->irq == irq) {
- stat = hwif->tp_ops->read_status(hwif);
-
- if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
- /* Try to not flood the console with msgs */
- static unsigned long last_msgtime, count;
- ++count;
- if (time_after(jiffies, last_msgtime + HZ)) {
- last_msgtime = jiffies;
- printk(KERN_ERR "%s%s: unexpected interrupt, "
- "status=0x%02x, count=%ld\n",
- hwif->name,
- (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count);
- }
- }
+static void unexpected_intr(int irq, ide_hwif_t *hwif)
+{
+ u8 stat = hwif->tp_ops->read_status(hwif);
+
+ if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
+ /* Try to not flood the console with msgs */
+ static unsigned long last_msgtime, count;
+ ++count;
+
+ if (time_after(jiffies, last_msgtime + HZ)) {
+ last_msgtime = jiffies;
+ printk(KERN_ERR "%s: unexpected interrupt, "
+ "status=0x%02x, count=%ld\n",
+ hwif->name, stat, count);
}
- } while ((hwif = hwif->next) != hwgroup->hwif);
+ }
}
/**
* ide_intr - default IDE interrupt handler
* @irq: interrupt number
- * @dev_id: hwif group
+ * @dev_id: hwif
* @regs: unused weirdness from the kernel irq layer
*
* This is the default IRQ handler for the IDE layer. You should
* not need to override it. If you do be aware it is subtle in
* places
*
- * hwgroup->hwif is the interface in the group currently performing
- * a command. hwgroup->drive is the drive and hwgroup->handler is
+ * hwif is the interface in the group currently performing
+ * a command. hwif->cur_dev is the drive and hwif->handler is
* the IRQ handler to call. As we issue a command the handlers
* step through multiple states, reassigning the handler to the
* next step in the process. Unlike a smart SCSI controller IDE
@@ -1165,25 +1050,32 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
*
* The handler eventually returns ide_stopped to indicate the
* request completed. At this point we issue the next request
- * on the hwgroup and the process begins again.
+ * on the port and the process begins again.
*/
-
+
irqreturn_t ide_intr (int irq, void *dev_id)
{
- unsigned long flags;
- ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
- ide_hwif_t *hwif = hwgroup->hwif;
- ide_drive_t *drive;
+ ide_hwif_t *hwif = (ide_hwif_t *)dev_id;
+ ide_drive_t *uninitialized_var(drive);
ide_handler_t *handler;
+ unsigned long flags;
ide_startstop_t startstop;
irqreturn_t irq_ret = IRQ_NONE;
+ int plug_device = 0;
- spin_lock_irqsave(&hwgroup->lock, flags);
+ if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
+ if (hwif != hwif->host->cur_port)
+ goto out_early;
+ }
+
+ spin_lock_irqsave(&hwif->lock, flags);
if (!ide_ack_intr(hwif))
goto out;
- if ((handler = hwgroup->handler) == NULL || hwgroup->polling) {
+ handler = hwif->handler;
+
+ if (handler == NULL || hwif->polling) {
/*
* Not expecting an interrupt from this drive.
* That means this could be:
@@ -1207,7 +1099,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* Probably not a shared PCI interrupt,
* so we can safely try to do something about it:
*/
- unexpected_intr(irq, hwgroup);
+ unexpected_intr(irq, hwif);
#ifdef CONFIG_BLK_DEV_IDEPCI
} else {
/*
@@ -1220,16 +1112,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
goto out;
}
- drive = hwgroup->drive;
- if (!drive) {
- /*
- * This should NEVER happen, and there isn't much
- * we could do about it here.
- *
- * [Note - this can occur if the drive is hot unplugged]
- */
- goto out_handled;
- }
+ drive = hwif->cur_dev;
if (!drive_is_ready(drive))
/*
@@ -1241,14 +1124,10 @@ irqreturn_t ide_intr (int irq, void *dev_id)
*/
goto out;
- if (!hwgroup->busy) {
- hwgroup->busy = 1; /* paranoia */
- printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
- }
- hwgroup->handler = NULL;
- hwgroup->req_gen++;
- del_timer(&hwgroup->timer);
- spin_unlock(&hwgroup->lock);
+ hwif->handler = NULL;
+ hwif->req_gen++;
+ del_timer(&hwif->timer);
+ spin_unlock(&hwif->lock);
if (hwif->port_ops && hwif->port_ops->clear_irq)
hwif->port_ops->clear_irq(drive);
@@ -1259,7 +1138,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
/* service this interrupt, may set handler for next interrupt */
startstop = handler(drive);
- spin_lock_irq(&hwgroup->lock);
+ spin_lock_irq(&hwif->lock);
/*
* Note that handler() may have set things up for another
* interrupt to occur soon, but it cannot happen until
@@ -1267,20 +1146,20 @@ irqreturn_t ide_intr (int irq, void *dev_id)
* same irq as is currently being serviced here, and Linux
* won't allow another of the same (on any CPU) until we return.
*/
- drive->service_time = jiffies - drive->service_start;
if (startstop == ide_stopped) {
- if (hwgroup->handler == NULL) { /* paranoia */
- hwgroup->busy = 0;
- ide_do_request(hwgroup, hwif->irq);
- } else {
- printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler "
- "on exit\n", drive->name);
- }
+ BUG_ON(hwif->handler);
+ ide_unlock_port(hwif);
+ plug_device = 1;
}
-out_handled:
irq_ret = IRQ_HANDLED;
out:
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
+out_early:
+ if (plug_device) {
+ ide_unlock_host(hwif->host);
+ ide_plug_device(drive);
+ }
+
return irq_ret;
}
@@ -1301,15 +1180,13 @@ out:
void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq)
{
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
struct request_queue *q = drive->queue;
unsigned long flags;
- hwgroup->rq = NULL;
+ drive->hwif->rq = NULL;
spin_lock_irqsave(q->queue_lock, flags);
__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
- blk_start_queueing(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
EXPORT_SYMBOL(ide_do_drive_cmd);
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index 28232c64c346..1be263eb9c07 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -95,8 +95,7 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
return -EPERM;
if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
- (drive->media != ide_tape ||
- (drive->dev_flags & IDE_DFLAG_SCSI)))
+ (drive->media != ide_tape))
return -EPERM;
if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index ad8bd6539283..753b92ebe0ae 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -105,15 +105,6 @@ u8 ide_read_altstatus(ide_hwif_t *hwif)
}
EXPORT_SYMBOL_GPL(ide_read_altstatus);
-u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
-{
- if (hwif->host_flags & IDE_HFLAG_MMIO)
- return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
- else
- return inb(hwif->dma_base + ATA_DMA_STATUS);
-}
-EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
-
void ide_set_irq(ide_hwif_t *hwif, int on)
{
u8 ctl = ATA_DEVCTL_OBS;
@@ -388,7 +379,6 @@ const struct ide_tp_ops default_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
@@ -451,7 +441,7 @@ EXPORT_SYMBOL(ide_fixstring);
*/
int drive_is_ready (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u8 stat = 0;
if (drive->waiting_for_dma)
@@ -503,7 +493,8 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
stat = tp_ops->read_status(hwif);
if (stat & ATA_BUSY) {
- local_irq_set(flags);
+ local_save_flags(flags);
+ local_irq_enable_in_hardirq();
timeout += jiffies;
while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) {
if (time_after(jiffies, timeout)) {
@@ -822,25 +813,25 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
unsigned int timeout, ide_expiry_t *expiry)
{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
-
- BUG_ON(hwgroup->handler);
- hwgroup->handler = handler;
- hwgroup->expiry = expiry;
- hwgroup->timer.expires = jiffies + timeout;
- hwgroup->req_gen_timer = hwgroup->req_gen;
- add_timer(&hwgroup->timer);
+ ide_hwif_t *hwif = drive->hwif;
+
+ BUG_ON(hwif->handler);
+ hwif->handler = handler;
+ hwif->expiry = expiry;
+ hwif->timer.expires = jiffies + timeout;
+ hwif->req_gen_timer = hwif->req_gen;
+ add_timer(&hwif->timer);
}
void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
unsigned int timeout, ide_expiry_t *expiry)
{
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ ide_hwif_t *hwif = drive->hwif;
unsigned long flags;
- spin_lock_irqsave(&hwgroup->lock, flags);
+ spin_lock_irqsave(&hwif->lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
}
EXPORT_SYMBOL(ide_set_handler);
@@ -863,10 +854,9 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
unsigned timeout, ide_expiry_t *expiry)
{
ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
unsigned long flags;
- spin_lock_irqsave(&hwgroup->lock, flags);
+ spin_lock_irqsave(&hwif->lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
hwif->tp_ops->exec_command(hwif, cmd);
/*
@@ -876,26 +866,25 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
* FIXME: we could skip this delay with care on non shared devices
*/
ndelay(400);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
}
EXPORT_SYMBOL(ide_execute_command);
void ide_execute_pkt_cmd(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
unsigned long flags;
- spin_lock_irqsave(&hwgroup->lock, flags);
+ spin_lock_irqsave(&hwif->lock, flags);
hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET);
ndelay(400);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
{
- struct request *rq = drive->hwif->hwgroup->rq;
+ struct request *rq = drive->hwif->rq;
if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
ide_end_request(drive, err ? err : 1, 0);
@@ -913,7 +902,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *, int);
static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
u8 stat;
SELECT_DRIVE(drive);
@@ -923,20 +911,20 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
if (OK_STAT(stat, 0, ATA_BUSY))
printk("%s: ATAPI reset complete\n", drive->name);
else {
- if (time_before(jiffies, hwgroup->poll_timeout)) {
+ if (time_before(jiffies, hwif->poll_timeout)) {
ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
/* continue polling */
return ide_started;
}
/* end of polling */
- hwgroup->polling = 0;
+ hwif->polling = 0;
printk("%s: ATAPI reset timed-out, status=0x%02x\n",
drive->name, stat);
/* do it the old fashioned way */
return do_reset1(drive, 1);
}
/* done polling */
- hwgroup->polling = 0;
+ hwif->polling = 0;
ide_complete_drive_reset(drive, 0);
return ide_stopped;
}
@@ -968,8 +956,7 @@ static void ide_reset_report_error(ide_hwif_t *hwif, u8 err)
*/
static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
{
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
const struct ide_port_ops *port_ops = hwif->port_ops;
u8 tmp;
int err = 0;
@@ -986,7 +973,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
tmp = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(tmp, 0, ATA_BUSY)) {
- if (time_before(jiffies, hwgroup->poll_timeout)) {
+ if (time_before(jiffies, hwif->poll_timeout)) {
ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
/* continue polling */
return ide_started;
@@ -1007,7 +994,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
}
out:
- hwgroup->polling = 0; /* done polling */
+ hwif->polling = 0; /* done polling */
ide_complete_drive_reset(drive, err);
return ide_stopped;
}
@@ -1081,18 +1068,18 @@ static void pre_reset(ide_drive_t *drive)
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
{
ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
struct ide_io_ports *io_ports = &hwif->io_ports;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
const struct ide_port_ops *port_ops;
+ ide_drive_t *tdrive;
unsigned long flags, timeout;
- unsigned int unit;
+ int i;
DEFINE_WAIT(wait);
- spin_lock_irqsave(&hwgroup->lock, flags);
+ spin_lock_irqsave(&hwif->lock, flags);
/* We must not reset with running handlers */
- BUG_ON(hwgroup->handler != NULL);
+ BUG_ON(hwif->handler != NULL);
/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->media != ide_disk && !do_not_try_atapi) {
@@ -1101,10 +1088,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
udelay (20);
tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET);
ndelay(400);
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- hwgroup->polling = 1;
+ hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+ hwif->polling = 1;
__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
return ide_started;
}
@@ -1114,9 +1101,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE);
timeout = jiffies;
- for (unit = 0; unit < MAX_DRIVES; unit++) {
- ide_drive_t *tdrive = &hwif->drives[unit];
-
+ ide_port_for_each_dev(i, tdrive, hwif) {
if (tdrive->dev_flags & IDE_DFLAG_PRESENT &&
tdrive->dev_flags & IDE_DFLAG_PARKED &&
time_after(tdrive->sleep, timeout))
@@ -1127,9 +1112,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (time_before_eq(timeout, now))
break;
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
timeout = schedule_timeout_uninterruptible(timeout - now);
- spin_lock_irqsave(&hwgroup->lock, flags);
+ spin_lock_irqsave(&hwif->lock, flags);
} while (timeout);
finish_wait(&ide_park_wq, &wait);
@@ -1137,11 +1122,11 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* First, reset any device state data we were maintaining
* for any of the drives on this interface.
*/
- for (unit = 0; unit < MAX_DRIVES; ++unit)
- pre_reset(&hwif->drives[unit]);
+ ide_port_for_each_dev(i, tdrive, hwif)
+ pre_reset(tdrive);
if (io_ports->ctl_addr == 0) {
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
ide_complete_drive_reset(drive, -ENXIO);
return ide_stopped;
}
@@ -1164,8 +1149,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
tp_ops->set_irq(hwif, drive->quirk_list == 2);
/* more than enough time */
udelay(10);
- hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- hwgroup->polling = 1;
+ hwif->poll_timeout = jiffies + WAIT_WORSTCASE;
+ hwif->polling = 1;
__ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
/*
@@ -1177,7 +1162,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (port_ops && port_ops->resetproc)
port_ops->resetproc(drive);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
return ide_started;
}
@@ -1221,6 +1206,3 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
}
return -EBUSY;
}
-
-EXPORT_SYMBOL_GPL(ide_wait_not_busy);
-
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 9f6e33d8a8b2..09526a0de734 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -273,7 +273,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
static void ide_dump_opcode(ide_drive_t *drive)
{
- struct request *rq = drive->hwif->hwgroup->rq;
+ struct request *rq = drive->hwif->rq;
ide_task_t *task = NULL;
if (!rq)
@@ -346,10 +346,13 @@ static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
printk(KERN_CONT "}");
if ((err & (ATA_BBK | ATA_ABORTED)) == ATA_BBK ||
(err & (ATA_UNC | ATA_IDNF | ATA_AMNF))) {
+ struct request *rq = drive->hwif->rq;
+
ide_dump_sector(drive);
- if (HWGROUP(drive) && HWGROUP(drive)->rq)
+
+ if (rq)
printk(KERN_CONT ", sector=%llu",
- (unsigned long long)HWGROUP(drive)->rq->sector);
+ (unsigned long long)rq->sector);
}
printk(KERN_CONT "\n");
}
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c
index 63d01c55f865..c875a957596c 100644
--- a/drivers/ide/ide-park.c
+++ b/drivers/ide/ide-park.c
@@ -7,28 +7,31 @@ DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
{
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ ide_hwif_t *hwif = drive->hwif;
struct request_queue *q = drive->queue;
struct request *rq;
int rc;
timeout += jiffies;
- spin_lock_irq(&hwgroup->lock);
+ spin_lock_irq(&hwif->lock);
if (drive->dev_flags & IDE_DFLAG_PARKED) {
int reset_timer = time_before(timeout, drive->sleep);
+ int start_queue = 0;
drive->sleep = timeout;
wake_up_all(&ide_park_wq);
- if (reset_timer && hwgroup->sleeping &&
- del_timer(&hwgroup->timer)) {
- hwgroup->sleeping = 0;
- hwgroup->busy = 0;
+ if (reset_timer && del_timer(&hwif->timer))
+ start_queue = 1;
+ spin_unlock_irq(&hwif->lock);
+
+ if (start_queue) {
+ spin_lock_irq(q->queue_lock);
blk_start_queueing(q);
+ spin_unlock_irq(q->queue_lock);
}
- spin_unlock_irq(&hwgroup->lock);
return;
}
- spin_unlock_irq(&hwgroup->lock);
+ spin_unlock_irq(&hwif->lock);
rq = blk_get_request(q, READ, __GFP_WAIT);
rq->cmd[0] = REQ_PARK_HEADS;
@@ -61,21 +64,21 @@ ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ide_drive_t *drive = to_ide_device(dev);
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ ide_hwif_t *hwif = drive->hwif;
unsigned long now;
unsigned int msecs;
if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
return -EOPNOTSUPP;
- spin_lock_irq(&hwgroup->lock);
+ spin_lock_irq(&hwif->lock);
now = jiffies;
if (drive->dev_flags & IDE_DFLAG_PARKED &&
time_after(drive->sleep, now))
msecs = jiffies_to_msecs(drive->sleep - now);
else
msecs = 0;
- spin_unlock_irq(&hwgroup->lock);
+ spin_unlock_irq(&hwif->lock);
return snprintf(buf, 20, "%u\n", msecs);
}
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c
index 8282c6086e6a..60538d9c84ee 100644
--- a/drivers/ide/ide-pm.c
+++ b/drivers/ide/ide-pm.c
@@ -5,7 +5,7 @@
int generic_ide_suspend(struct device *dev, pm_message_t mesg)
{
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct request *rq;
struct request_pm_state rqpm;
ide_task_t args;
@@ -39,7 +39,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
int generic_ide_resume(struct device *dev)
{
ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive);
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct request *rq;
struct request_pm_state rqpm;
ide_task_t args;
@@ -67,7 +67,7 @@ int generic_ide_resume(struct device *dev)
blk_put_request(rq);
if (err == 0 && dev->driver) {
- ide_driver_t *drv = to_ide_driver(dev->driver);
+ struct ide_driver *drv = to_ide_driver(dev->driver);
if (drv->resume)
drv->resume(drive);
@@ -186,15 +186,13 @@ void ide_complete_pm_request(ide_drive_t *drive, struct request *rq)
blk_pm_suspend_request(rq) ? "suspend" : "resume");
#endif
spin_lock_irqsave(q->queue_lock, flags);
- if (blk_pm_suspend_request(rq)) {
+ if (blk_pm_suspend_request(rq))
blk_stop_queue(q);
- } else {
+ else
drive->dev_flags &= ~IDE_DFLAG_BLOCKED;
- blk_start_queue(q);
- }
spin_unlock_irqrestore(q->queue_lock, flags);
- drive->hwif->hwgroup->rq = NULL;
+ drive->hwif->rq = NULL;
if (blk_end_request(rq, 0, 0))
BUG();
@@ -219,6 +217,8 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
* point.
*/
ide_hwif_t *hwif = drive->hwif;
+ struct request_queue *q = drive->queue;
+ unsigned long flags;
int rc;
#ifdef DEBUG_PM
printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
@@ -231,5 +231,9 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
rc = ide_wait_not_busy(hwif, 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_start_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
}
}
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index a64ec259f3d1..ce0818a993f6 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -101,6 +101,82 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
}
}
+static void ide_classify_ata_dev(ide_drive_t *drive)
+{
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
+ int is_cfa = ata_id_is_cfa(id);
+
+ /* CF devices are *not* removable in Linux definition of the term */
+ if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+
+ drive->media = ide_disk;
+
+ if (!ata_id_has_unload(drive->id))
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+
+ printk(KERN_INFO "%s: %s, %s DISK drive\n", drive->name, m,
+ is_cfa ? "CFA" : "ATA");
+}
+
+static void ide_classify_atapi_dev(ide_drive_t *drive)
+{
+ u16 *id = drive->id;
+ char *m = (char *)&id[ATA_ID_PROD];
+ u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
+
+ printk(KERN_INFO "%s: %s, ATAPI ", drive->name, m);
+ switch (type) {
+ case ide_floppy:
+ if (!strstr(m, "CD-ROM")) {
+ if (!strstr(m, "oppy") &&
+ !strstr(m, "poyp") &&
+ !strstr(m, "ZIP"))
+ printk(KERN_CONT "cdrom or floppy?, assuming ");
+ if (drive->media != ide_cdrom) {
+ printk(KERN_CONT "FLOPPY");
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+ break;
+ }
+ }
+ /* Early cdrom models used zero */
+ type = ide_cdrom;
+ case ide_cdrom:
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+#ifdef CONFIG_PPC
+ /* kludge for Apple PowerBook internal zip */
+ if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
+ printk(KERN_CONT "FLOPPY");
+ type = ide_floppy;
+ break;
+ }
+#endif
+ printk(KERN_CONT "CD/DVD-ROM");
+ break;
+ case ide_tape:
+ printk(KERN_CONT "TAPE");
+ break;
+ case ide_optical:
+ printk(KERN_CONT "OPTICAL");
+ drive->dev_flags |= IDE_DFLAG_REMOVABLE;
+ break;
+ default:
+ printk(KERN_CONT "UNKNOWN (type %d)", type);
+ break;
+ }
+
+ printk(KERN_CONT " drive\n");
+ drive->media = type;
+ /* an ATAPI device ignores DRDY */
+ drive->ready_stat = 0;
+ if (ata_id_cdb_intr(id))
+ drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
+ drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
+ /* we don't do head unloading on ATAPI devices */
+ drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
+}
+
/**
* do_identify - identify a drive
* @drive: drive to identify
@@ -113,11 +189,11 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
static void do_identify(ide_drive_t *drive, u8 cmd)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u16 *id = drive->id;
char *m = (char *)&id[ATA_ID_PROD];
unsigned long flags;
- int bswap = 1, is_cfa;
+ int bswap = 1;
/* local CPU only; some systems need this */
local_irq_save(flags);
@@ -154,91 +230,23 @@ static void do_identify(ide_drive_t *drive, u8 cmd)
if (strstr(m, "E X A B Y T E N E S T"))
goto err_misc;
- printk(KERN_INFO "%s: %s, ", drive->name, m);
-
drive->dev_flags |= IDE_DFLAG_PRESENT;
drive->dev_flags &= ~IDE_DFLAG_DEAD;
/*
* Check for an ATAPI device
*/
- if (cmd == ATA_CMD_ID_ATAPI) {
- u8 type = (id[ATA_ID_CONFIG] >> 8) & 0x1f;
-
- printk(KERN_CONT "ATAPI ");
- switch (type) {
- case ide_floppy:
- if (!strstr(m, "CD-ROM")) {
- if (!strstr(m, "oppy") &&
- !strstr(m, "poyp") &&
- !strstr(m, "ZIP"))
- printk(KERN_CONT "cdrom or floppy?, assuming ");
- if (drive->media != ide_cdrom) {
- printk(KERN_CONT "FLOPPY");
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
- break;
- }
- }
- /* Early cdrom models used zero */
- type = ide_cdrom;
- case ide_cdrom:
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
-#ifdef CONFIG_PPC
- /* kludge for Apple PowerBook internal zip */
- if (!strstr(m, "CD-ROM") && strstr(m, "ZIP")) {
- printk(KERN_CONT "FLOPPY");
- type = ide_floppy;
- break;
- }
-#endif
- printk(KERN_CONT "CD/DVD-ROM");
- break;
- case ide_tape:
- printk(KERN_CONT "TAPE");
- break;
- case ide_optical:
- printk(KERN_CONT "OPTICAL");
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
- break;
- default:
- printk(KERN_CONT "UNKNOWN (type %d)", type);
- break;
- }
- printk(KERN_CONT " drive\n");
- drive->media = type;
- /* an ATAPI device ignores DRDY */
- drive->ready_stat = 0;
- if (ata_id_cdb_intr(id))
- drive->atapi_flags |= IDE_AFLAG_DRQ_INTERRUPT;
- drive->dev_flags |= IDE_DFLAG_DOORLOCKING;
- /* we don't do head unloading on ATAPI devices */
- drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
- return;
- }
-
+ if (cmd == ATA_CMD_ID_ATAPI)
+ ide_classify_atapi_dev(drive);
+ else
/*
* Not an ATAPI device: looks like a "regular" hard disk
*/
-
- is_cfa = ata_id_is_cfa(id);
-
- /* CF devices are *not* removable in Linux definition of the term */
- if (is_cfa == 0 && (id[ATA_ID_CONFIG] & (1 << 7)))
- drive->dev_flags |= IDE_DFLAG_REMOVABLE;
-
- drive->media = ide_disk;
-
- if (!ata_id_has_unload(drive->id))
- drive->dev_flags |= IDE_DFLAG_NO_UNLOAD;
-
- printk(KERN_CONT "%s DISK drive\n", is_cfa ? "CFA" : "ATA");
-
+ ide_classify_ata_dev(drive);
return;
-
err_misc:
kfree(id);
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
- return;
}
/**
@@ -258,7 +266,7 @@ err_misc:
static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int use_altstatus = 0, rc;
@@ -333,7 +341,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
static int try_to_identify (ide_drive_t *drive, u8 cmd)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int retval;
int autoprobe = 0;
@@ -430,7 +438,7 @@ static u8 ide_read_device(ide_drive_t *drive)
static int do_probe (ide_drive_t *drive, u8 cmd)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
int rc;
u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat;
@@ -455,7 +463,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
if (ide_read_device(drive) != drive->select && present == 0) {
if (drive->dn & 1) {
/* exit with drive0 selected */
- SELECT_DRIVE(&hwif->drives[0]);
+ SELECT_DRIVE(hwif->devices[0]);
/* allow ATA_BUSY to assert & clear */
msleep(50);
}
@@ -501,7 +509,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
}
if (drive->dn & 1) {
/* exit with drive0 selected */
- SELECT_DRIVE(&hwif->drives[0]);
+ SELECT_DRIVE(hwif->devices[0]);
msleep(50);
/* ensure drive irq is clear */
(void)tp_ops->read_status(hwif);
@@ -514,7 +522,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
*/
static void enable_nest (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
u8 stat;
@@ -641,14 +649,10 @@ static int ide_register_port(ide_hwif_t *hwif)
/* register with global device tree */
dev_set_name(&hwif->gendev, hwif->name);
hwif->gendev.driver_data = hwif;
- if (hwif->gendev.parent == NULL) {
- if (hwif->dev)
- hwif->gendev.parent = hwif->dev;
- else
- /* Would like to do = &device_legacy */
- hwif->gendev.parent = NULL;
- }
+ if (hwif->gendev.parent == NULL)
+ hwif->gendev.parent = hwif->dev;
hwif->gendev.release = hwif_release_dev;
+
ret = device_register(&hwif->gendev);
if (ret < 0) {
printk(KERN_WARNING "IDE: %s: device_register error: %d\n",
@@ -694,7 +698,8 @@ out:
static int ide_port_wait_ready(ide_hwif_t *hwif)
{
- int unit, rc;
+ ide_drive_t *drive;
+ int i, rc;
printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name);
@@ -711,9 +716,7 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
return rc;
/* Now make sure both master & slave are ready */
- for (unit = 0; unit < MAX_DRIVES; unit++) {
- ide_drive_t *drive = &hwif->drives[unit];
-
+ ide_port_for_each_dev(i, drive, hwif) {
/* Ignore disks that we will not probe for later. */
if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 ||
(drive->dev_flags & IDE_DFLAG_PRESENT)) {
@@ -729,8 +732,8 @@ static int ide_port_wait_ready(ide_hwif_t *hwif)
}
out:
/* Exit function with master reselected (let's be sane) */
- if (unit)
- SELECT_DRIVE(&hwif->drives[0]);
+ if (i)
+ SELECT_DRIVE(hwif->devices[0]);
return rc;
}
@@ -746,7 +749,7 @@ out:
void ide_undecoded_slave(ide_drive_t *dev1)
{
- ide_drive_t *dev0 = &dev1->hwif->drives[0];
+ ide_drive_t *dev0 = dev1->hwif->devices[0];
if ((dev1->dn & 1) == 0 || (dev0->dev_flags & IDE_DFLAG_PRESENT) == 0)
return;
@@ -775,14 +778,15 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave);
static int ide_probe_port(ide_hwif_t *hwif)
{
+ ide_drive_t *drive;
unsigned long flags;
unsigned int irqd;
- int unit, rc = -ENODEV;
+ int i, rc = -ENODEV;
BUG_ON(hwif->present);
- if ((hwif->drives[0].dev_flags & IDE_DFLAG_NOPROBE) &&
- (hwif->drives[1].dev_flags & IDE_DFLAG_NOPROBE))
+ if ((hwif->devices[0]->dev_flags & IDE_DFLAG_NOPROBE) &&
+ (hwif->devices[1]->dev_flags & IDE_DFLAG_NOPROBE))
return -EACCES;
/*
@@ -793,7 +797,8 @@ static int ide_probe_port(ide_hwif_t *hwif)
if (irqd)
disable_irq(hwif->irq);
- local_irq_set(flags);
+ local_save_flags(flags);
+ local_irq_enable_in_hardirq();
if (ide_port_wait_ready(hwif) == -EBUSY)
printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
@@ -802,9 +807,7 @@ static int ide_probe_port(ide_hwif_t *hwif)
* Second drive should only exist if first drive was found,
* but a lot of cdrom drives are configured as single slaves.
*/
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-
+ ide_port_for_each_dev(i, drive, hwif) {
(void) probe_for_drive(drive);
if (drive->dev_flags & IDE_DFLAG_PRESENT)
rc = 0;
@@ -825,20 +828,17 @@ static int ide_probe_port(ide_hwif_t *hwif)
static void ide_port_tune_devices(ide_hwif_t *hwif)
{
const struct ide_port_ops *port_ops = hwif->port_ops;
- int unit;
-
- for (unit = 0; unit < MAX_DRIVES; unit++) {
- ide_drive_t *drive = &hwif->drives[unit];
+ ide_drive_t *drive;
+ int i;
+ ide_port_for_each_dev(i, drive, hwif) {
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
if (port_ops && port_ops->quirkproc)
port_ops->quirkproc(drive);
}
}
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-
+ ide_port_for_each_dev(i, drive, hwif) {
if (drive->dev_flags & IDE_DFLAG_PRESENT) {
ide_set_max_pio(drive);
@@ -849,11 +849,8 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
}
}
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
-
- if ((hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) ||
- drive->id[ATA_ID_DWORD_IO])
+ ide_port_for_each_dev(i, drive, hwif) {
+ if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT;
else
drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT;
@@ -866,7 +863,7 @@ static void ide_port_tune_devices(ide_hwif_t *hwif)
static int ide_init_queue(ide_drive_t *drive)
{
struct request_queue *q;
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
int max_sectors = 256;
int max_sg_entries = PRD_ENTRIES;
@@ -878,8 +875,7 @@ static int ide_init_queue(ide_drive_t *drive)
* do not.
*/
- q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock,
- hwif_to_node(hwif));
+ q = blk_init_queue_node(do_ide_request, NULL, hwif_to_node(hwif));
if (!q)
return 1;
@@ -916,36 +912,19 @@ static int ide_init_queue(ide_drive_t *drive)
return 0;
}
-static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
-
- spin_lock_irq(&hwgroup->lock);
- if (!hwgroup->drive) {
- /* first drive for hwgroup. */
- drive->next = drive;
- hwgroup->drive = drive;
- hwgroup->hwif = HWIF(hwgroup->drive);
- } else {
- drive->next = hwgroup->drive->next;
- hwgroup->drive->next = drive;
- }
- spin_unlock_irq(&hwgroup->lock);
-}
+static DEFINE_MUTEX(ide_cfg_mtx);
/*
* For any present drive:
* - allocate the block device queue
- * - link drive into the hwgroup
*/
static int ide_port_setup_devices(ide_hwif_t *hwif)
{
+ ide_drive_t *drive;
int i, j = 0;
mutex_lock(&ide_cfg_mtx);
- for (i = 0; i < MAX_DRIVES; i++) {
- ide_drive_t *drive = &hwif->drives[i];
-
+ ide_port_for_each_dev(i, drive, hwif) {
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
continue;
@@ -959,139 +938,39 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
}
j++;
-
- ide_add_drive_to_hwgroup(drive);
}
mutex_unlock(&ide_cfg_mtx);
return j;
}
-static ide_hwif_t *ide_ports[MAX_HWIFS];
-
-void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
-{
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
-
- ide_ports[hwif->index] = NULL;
-
- spin_lock_irq(&hwgroup->lock);
- /*
- * Remove us from the hwgroup, and free
- * the hwgroup if we were the only member
- */
- if (hwif->next == hwif) {
- BUG_ON(hwgroup->hwif != hwif);
- kfree(hwgroup);
- } else {
- /* There is another interface in hwgroup.
- * Unlink us, and set hwgroup->drive and ->hwif to
- * something sane.
- */
- ide_hwif_t *g = hwgroup->hwif;
-
- while (g->next != hwif)
- g = g->next;
- g->next = hwif->next;
- if (hwgroup->hwif == hwif) {
- /* Chose a random hwif for hwgroup->hwif.
- * It's guaranteed that there are no drives
- * left in the hwgroup.
- */
- BUG_ON(hwgroup->drive != NULL);
- hwgroup->hwif = g;
- }
- BUG_ON(hwgroup->hwif == hwif);
- }
- spin_unlock_irq(&hwgroup->lock);
-}
-
/*
- * This routine sets up the irq for an ide interface, and creates a new
- * hwgroup for the irq/hwif if none was previously assigned.
- *
- * Much of the code is for correctly detecting/handling irq sharing
- * and irq serialization situations. This is somewhat complex because
- * it handles static as well as dynamic (PCMCIA) IDE interfaces.
+ * This routine sets up the IRQ for an IDE interface.
*/
static int init_irq (ide_hwif_t *hwif)
{
struct ide_io_ports *io_ports = &hwif->io_ports;
- unsigned int index;
- ide_hwgroup_t *hwgroup;
- ide_hwif_t *match = NULL;
+ int sa = 0;
mutex_lock(&ide_cfg_mtx);
- hwif->hwgroup = NULL;
-
- for (index = 0; index < MAX_HWIFS; index++) {
- ide_hwif_t *h = ide_ports[index];
+ spin_lock_init(&hwif->lock);
- if (h && h->hwgroup) { /* scan only initialized ports */
- if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
- if (hwif->host == h->host)
- match = h;
- }
- }
- }
-
- /*
- * If we are still without a hwgroup, then form a new one
- */
- if (match) {
- hwgroup = match->hwgroup;
- hwif->hwgroup = hwgroup;
- /*
- * Link us into the hwgroup.
- * This must be done early, do ensure that unexpected_intr
- * can find the hwif and prevent irq storms.
- * No drives are attached to the new hwif, choose_drive
- * can't do anything stupid (yet).
- * Add ourself as the 2nd entry to the hwgroup->hwif
- * linked list, the first entry is the hwif that owns
- * hwgroup->handler - do not change that.
- */
- spin_lock_irq(&hwgroup->lock);
- hwif->next = hwgroup->hwif->next;
- hwgroup->hwif->next = hwif;
- BUG_ON(hwif->next == hwif);
- spin_unlock_irq(&hwgroup->lock);
- } else {
- hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
- hwif_to_node(hwif));
- if (hwgroup == NULL)
- goto out_up;
+ init_timer(&hwif->timer);
+ hwif->timer.function = &ide_timer_expiry;
+ hwif->timer.data = (unsigned long)hwif;
- spin_lock_init(&hwgroup->lock);
-
- hwif->hwgroup = hwgroup;
- hwgroup->hwif = hwif->next = hwif;
-
- init_timer(&hwgroup->timer);
- hwgroup->timer.function = &ide_timer_expiry;
- hwgroup->timer.data = (unsigned long) hwgroup;
- }
-
- ide_ports[hwif->index] = hwif;
-
- /*
- * Allocate the irq, if not already obtained for another hwif
- */
- if (!match || match->irq != hwif->irq) {
- int sa = 0;
#if defined(__mc68000__)
- sa = IRQF_SHARED;
+ sa = IRQF_SHARED;
#endif /* __mc68000__ */
- if (hwif->chipset == ide_pci)
- sa = IRQF_SHARED;
+ if (hwif->chipset == ide_pci)
+ sa = IRQF_SHARED;
- if (io_ports->ctl_addr)
- hwif->tp_ops->set_irq(hwif, 1);
+ if (io_ports->ctl_addr)
+ hwif->tp_ops->set_irq(hwif, 1);
- if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup))
- goto out_unlink;
- }
+ if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif))
+ goto out_up;
if (!hwif->rqsize) {
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
@@ -1109,14 +988,12 @@ static int init_irq (ide_hwif_t *hwif)
printk(KERN_INFO "%s at 0x%08lx on irq %d", hwif->name,
io_ports->data_addr, hwif->irq);
#endif /* __mc68000__ */
- if (match)
- printk(KERN_CONT " (serialized with %s)", match->name);
+ if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE)
+ printk(KERN_CONT " (serialized)");
printk(KERN_CONT "\n");
mutex_unlock(&ide_cfg_mtx);
return 0;
-out_unlink:
- ide_remove_port_from_hwgroup(hwif);
out_up:
mutex_unlock(&ide_cfg_mtx);
return 1;
@@ -1132,15 +1009,13 @@ static struct kobject *ata_probe(dev_t dev, int *part, void *data)
{
ide_hwif_t *hwif = data;
int unit = *part >> PARTN_BITS;
- ide_drive_t *drive = &hwif->drives[unit];
+ ide_drive_t *drive = hwif->devices[unit];
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
return NULL;
if (drive->media == ide_disk)
request_module("ide-disk");
- if (drive->dev_flags & IDE_DFLAG_SCSI)
- request_module("ide-scsi");
if (drive->media == ide_cdrom || drive->media == ide_optical)
request_module("ide-cd");
if (drive->media == ide_tape)
@@ -1196,47 +1071,23 @@ void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
EXPORT_SYMBOL_GPL(ide_init_disk);
-static void ide_remove_drive_from_hwgroup(ide_drive_t *drive)
-{
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
-
- if (drive == drive->next) {
- /* special case: last drive from hwgroup. */
- BUG_ON(hwgroup->drive != drive);
- hwgroup->drive = NULL;
- } else {
- ide_drive_t *walk;
-
- walk = hwgroup->drive;
- while (walk->next != drive)
- walk = walk->next;
- walk->next = drive->next;
- if (hwgroup->drive == drive) {
- hwgroup->drive = drive->next;
- hwgroup->hwif = hwgroup->drive->hwif;
- }
- }
- BUG_ON(hwgroup->drive == drive);
-}
-
static void drive_release_dev (struct device *dev)
{
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
- ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+ ide_hwif_t *hwif = drive->hwif;
ide_proc_unregister_device(drive);
- spin_lock_irq(&hwgroup->lock);
- ide_remove_drive_from_hwgroup(drive);
+ spin_lock_irq(&hwif->lock);
kfree(drive->id);
drive->id = NULL;
drive->dev_flags &= ~IDE_DFLAG_PRESENT;
/* Messed up locking ... */
- spin_unlock_irq(&hwgroup->lock);
+ spin_unlock_irq(&hwif->lock);
blk_cleanup_queue(drive->queue);
- spin_lock_irq(&hwgroup->lock);
+ spin_lock_irq(&hwif->lock);
drive->queue = NULL;
- spin_unlock_irq(&hwgroup->lock);
+ spin_unlock_irq(&hwif->lock);
complete(&drive->gendev_rel_comp);
}
@@ -1302,10 +1153,10 @@ out:
static void hwif_register_devices(ide_hwif_t *hwif)
{
+ ide_drive_t *drive;
unsigned int i;
- for (i = 0; i < MAX_DRIVES; i++) {
- ide_drive_t *drive = &hwif->drives[i];
+ ide_port_for_each_dev(i, drive, hwif) {
struct device *dev = &drive->gendev;
int ret;
@@ -1328,11 +1179,10 @@ static void hwif_register_devices(ide_hwif_t *hwif)
static void ide_port_init_devices(ide_hwif_t *hwif)
{
const struct ide_port_ops *port_ops = hwif->port_ops;
+ ide_drive_t *drive;
int i;
- for (i = 0; i < MAX_DRIVES; i++) {
- ide_drive_t *drive = &hwif->drives[i];
-
+ ide_port_for_each_dev(i, drive, hwif) {
drive->dn = i + hwif->channel * 2;
if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
@@ -1380,6 +1230,8 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
int rc;
+ hwif->dma_ops = d->dma_ops;
+
if (d->init_dma)
rc = d->init_dma(hwif, d);
else
@@ -1387,12 +1239,13 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
if (rc < 0) {
printk(KERN_INFO "%s: DMA disabled\n", hwif->name);
+
+ hwif->dma_ops = NULL;
hwif->dma_base = 0;
hwif->swdma_mask = 0;
hwif->mwdma_mask = 0;
hwif->ultra_mask = 0;
- } else if (d->dma_ops)
- hwif->dma_ops = d->dma_ops;
+ }
}
if ((d->host_flags & IDE_HFLAG_SERIALIZE) ||
@@ -1417,56 +1270,64 @@ static void ide_port_cable_detect(ide_hwif_t *hwif)
}
}
-static ssize_t store_delete_devices(struct device *portdev,
- struct device_attribute *attr,
- const char *buf, size_t n)
-{
- ide_hwif_t *hwif = dev_get_drvdata(portdev);
+static const u8 ide_hwif_to_major[] =
+ { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR,
+ IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR };
- if (strncmp(buf, "1", n))
- return -EINVAL;
-
- ide_port_unregister_devices(hwif);
-
- return n;
-};
+static void ide_port_init_devices_data(ide_hwif_t *hwif)
+{
+ ide_drive_t *drive;
+ int i;
-static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
+ ide_port_for_each_dev(i, drive, hwif) {
+ u8 j = (hwif->index * MAX_DRIVES) + i;
+
+ memset(drive, 0, sizeof(*drive));
+
+ drive->media = ide_disk;
+ drive->select = (i << 4) | ATA_DEVICE_OBS;
+ drive->hwif = hwif;
+ drive->ready_stat = ATA_DRDY;
+ drive->bad_wstat = BAD_W_STAT;
+ drive->special.b.recalibrate = 1;
+ drive->special.b.set_geometry = 1;
+ drive->name[0] = 'h';
+ drive->name[1] = 'd';
+ drive->name[2] = 'a' + j;
+ drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
+
+ INIT_LIST_HEAD(&drive->list);
+ init_completion(&drive->gendev_rel_comp);
+ }
+}
-static ssize_t store_scan(struct device *portdev,
- struct device_attribute *attr,
- const char *buf, size_t n)
+static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
{
- ide_hwif_t *hwif = dev_get_drvdata(portdev);
-
- if (strncmp(buf, "1", n))
- return -EINVAL;
+ /* fill in any non-zero initial values */
+ hwif->index = index;
+ hwif->major = ide_hwif_to_major[index];
- ide_port_unregister_devices(hwif);
- ide_port_scan(hwif);
+ hwif->name[0] = 'i';
+ hwif->name[1] = 'd';
+ hwif->name[2] = 'e';
+ hwif->name[3] = '0' + index;
- return n;
-};
+ init_completion(&hwif->gendev_rel_comp);
-static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
+ hwif->tp_ops = &default_tp_ops;
-static struct device_attribute *ide_port_attrs[] = {
- &dev_attr_delete_devices,
- &dev_attr_scan,
- NULL
-};
+ ide_port_init_devices_data(hwif);
+}
-static int ide_sysfs_register_port(ide_hwif_t *hwif)
+static void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
{
- int i, uninitialized_var(rc);
-
- for (i = 0; ide_port_attrs[i]; i++) {
- rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
- if (rc)
- break;
- }
-
- return rc;
+ memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
+ hwif->irq = hw->irq;
+ hwif->chipset = hw->chipset;
+ hwif->dev = hw->dev;
+ hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
+ hwif->ack_intr = hw->ack_intr;
+ hwif->config_data = hw->config;
}
static unsigned int ide_indexes;
@@ -1518,12 +1379,43 @@ static void ide_free_port_slot(int idx)
mutex_unlock(&ide_cfg_mtx);
}
+static void ide_port_free_devices(ide_hwif_t *hwif)
+{
+ ide_drive_t *drive;
+ int i;
+
+ ide_port_for_each_dev(i, drive, hwif)
+ kfree(drive);
+}
+
+static int ide_port_alloc_devices(ide_hwif_t *hwif, int node)
+{
+ int i;
+
+ for (i = 0; i < MAX_DRIVES; i++) {
+ ide_drive_t *drive;
+
+ drive = kzalloc_node(sizeof(*drive), GFP_KERNEL, node);
+ if (drive == NULL)
+ goto out_nomem;
+
+ hwif->devices[i] = drive;
+ }
+ return 0;
+
+out_nomem:
+ ide_port_free_devices(hwif);
+ return -ENOMEM;
+}
+
struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
{
struct ide_host *host;
+ struct device *dev = hws[0] ? hws[0]->dev : NULL;
+ int node = dev ? dev_to_node(dev) : -1;
int i;
- host = kzalloc(sizeof(*host), GFP_KERNEL);
+ host = kzalloc_node(sizeof(*host), GFP_KERNEL, node);
if (host == NULL)
return NULL;
@@ -1534,10 +1426,15 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
if (hws[i] == NULL)
continue;
- hwif = kzalloc(sizeof(*hwif), GFP_KERNEL);
+ hwif = kzalloc_node(sizeof(*hwif), GFP_KERNEL, node);
if (hwif == NULL)
continue;
+ if (ide_port_alloc_devices(hwif, node) < 0) {
+ kfree(hwif);
+ continue;
+ }
+
idx = ide_find_port_slot(d);
if (idx < 0) {
printk(KERN_ERR "%s: no free slot for interface\n",
@@ -1559,8 +1456,7 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
return NULL;
}
- if (hws[0])
- host->dev[0] = hws[0]->dev;
+ host->dev[0] = dev;
if (d) {
host->init_chipset = d->init_chipset;
@@ -1571,15 +1467,37 @@ struct ide_host *ide_host_alloc(const struct ide_port_info *d, hw_regs_t **hws)
}
EXPORT_SYMBOL_GPL(ide_host_alloc);
+static void ide_port_free(ide_hwif_t *hwif)
+{
+ ide_port_free_devices(hwif);
+ ide_free_port_slot(hwif->index);
+ kfree(hwif);
+}
+
+static void ide_disable_port(ide_hwif_t *hwif)
+{
+ struct ide_host *host = hwif->host;
+ int i;
+
+ printk(KERN_INFO "%s: disabling port\n", hwif->name);
+
+ for (i = 0; i < MAX_HOST_PORTS; i++) {
+ if (host->ports[i] == hwif) {
+ host->ports[i] = NULL;
+ host->n_ports--;
+ }
+ }
+
+ ide_port_free(hwif);
+}
+
int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
hw_regs_t **hws)
{
ide_hwif_t *hwif, *mate = NULL;
int i, j = 0;
- for (i = 0; i < MAX_HOST_PORTS; i++) {
- hwif = host->ports[i];
-
+ ide_host_for_each_port(i, hwif, host) {
if (hwif == NULL) {
mate = NULL;
continue;
@@ -1605,9 +1523,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
ide_port_init_devices(hwif);
}
- for (i = 0; i < MAX_HOST_PORTS; i++) {
- hwif = host->ports[i];
-
+ ide_host_for_each_port(i, hwif, host) {
if (hwif == NULL)
continue;
@@ -1615,23 +1531,26 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
hwif->present = 1;
if (hwif->chipset != ide_4drives || !hwif->mate ||
- !hwif->mate->present)
- ide_register_port(hwif);
+ !hwif->mate->present) {
+ if (ide_register_port(hwif)) {
+ ide_disable_port(hwif);
+ continue;
+ }
+ }
if (hwif->present)
ide_port_tune_devices(hwif);
}
- for (i = 0; i < MAX_HOST_PORTS; i++) {
- hwif = host->ports[i];
-
+ ide_host_for_each_port(i, hwif, host) {
if (hwif == NULL)
continue;
if (hwif_init(hwif) == 0) {
printk(KERN_INFO "%s: failed to initialize IDE "
"interface\n", hwif->name);
- hwif->present = 0;
+ device_unregister(&hwif->gendev);
+ ide_disable_port(hwif);
continue;
}
@@ -1649,22 +1568,15 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
ide_acpi_port_init_devices(hwif);
}
- for (i = 0; i < MAX_HOST_PORTS; i++) {
- hwif = host->ports[i];
-
+ ide_host_for_each_port(i, hwif, host) {
if (hwif == NULL)
continue;
- if (hwif->chipset == ide_unknown)
- hwif->chipset = ide_generic;
-
if (hwif->present)
hwif_register_devices(hwif);
}
- for (i = 0; i < MAX_HOST_PORTS; i++) {
- hwif = host->ports[i];
-
+ ide_host_for_each_port(i, hwif, host) {
if (hwif == NULL)
continue;
@@ -1702,19 +1614,83 @@ int ide_host_add(const struct ide_port_info *d, hw_regs_t **hws,
}
EXPORT_SYMBOL_GPL(ide_host_add);
-void ide_host_free(struct ide_host *host)
+static void __ide_port_unregister_devices(ide_hwif_t *hwif)
{
- ide_hwif_t *hwif;
+ ide_drive_t *drive;
int i;
- for (i = 0; i < MAX_HOST_PORTS; i++) {
- hwif = host->ports[i];
+ ide_port_for_each_dev(i, drive, hwif) {
+ if (drive->dev_flags & IDE_DFLAG_PRESENT) {
+ device_unregister(&drive->gendev);
+ wait_for_completion(&drive->gendev_rel_comp);
+ }
+ }
+}
- if (hwif == NULL)
- continue;
+void ide_port_unregister_devices(ide_hwif_t *hwif)
+{
+ mutex_lock(&ide_cfg_mtx);
+ __ide_port_unregister_devices(hwif);
+ hwif->present = 0;
+ ide_port_init_devices_data(hwif);
+ mutex_unlock(&ide_cfg_mtx);
+}
+EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
+
+/**
+ * ide_unregister - free an IDE interface
+ * @hwif: IDE interface
+ *
+ * Perform the final unregister of an IDE interface.
+ *
+ * Locking:
+ * The caller must not hold the IDE locks.
+ *
+ * It is up to the caller to be sure there is no pending I/O here,
+ * and that the interface will not be reopened (present/vanishing
+ * locking isn't yet done BTW).
+ */
+
+static void ide_unregister(ide_hwif_t *hwif)
+{
+ BUG_ON(in_interrupt());
+ BUG_ON(irqs_disabled());
+
+ mutex_lock(&ide_cfg_mtx);
- ide_free_port_slot(hwif->index);
- kfree(hwif);
+ if (hwif->present) {
+ __ide_port_unregister_devices(hwif);
+ hwif->present = 0;
+ }
+
+ ide_proc_unregister_port(hwif);
+
+ free_irq(hwif->irq, hwif);
+
+ device_unregister(hwif->portdev);
+ device_unregister(&hwif->gendev);
+ wait_for_completion(&hwif->gendev_rel_comp);
+
+ /*
+ * Remove us from the kernel's knowledge
+ */
+ blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
+ kfree(hwif->sg_table);
+ unregister_blkdev(hwif->major, hwif->name);
+
+ ide_release_dma_engine(hwif);
+
+ mutex_unlock(&ide_cfg_mtx);
+}
+
+void ide_host_free(struct ide_host *host)
+{
+ ide_hwif_t *hwif;
+ int i;
+
+ ide_host_for_each_port(i, hwif, host) {
+ if (hwif)
+ ide_port_free(hwif);
}
kfree(host);
@@ -1723,11 +1699,12 @@ EXPORT_SYMBOL_GPL(ide_host_free);
void ide_host_remove(struct ide_host *host)
{
+ ide_hwif_t *hwif;
int i;
- for (i = 0; i < MAX_HOST_PORTS; i++) {
- if (host->ports[i])
- ide_unregister(host->ports[i]);
+ ide_host_for_each_port(i, hwif, host) {
+ if (hwif)
+ ide_unregister(hwif);
}
ide_host_free(host);
@@ -1746,8 +1723,8 @@ void ide_port_scan(ide_hwif_t *hwif)
hwif->present = 1;
ide_port_tune_devices(hwif);
- ide_acpi_port_init_devices(hwif);
ide_port_setup_devices(hwif);
+ ide_acpi_port_init_devices(hwif);
hwif_register_devices(hwif);
ide_proc_port_register_devices(hwif);
}
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index a14e2938e4f3..1d8978b3314a 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -439,13 +439,13 @@ static int proc_ide_read_dmodel
static int proc_ide_read_driver
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
- ide_drive_t *drive = (ide_drive_t *) data;
- struct device *dev = &drive->gendev;
- ide_driver_t *ide_drv;
- int len;
+ ide_drive_t *drive = (ide_drive_t *)data;
+ struct device *dev = &drive->gendev;
+ struct ide_driver *ide_drv;
+ int len;
if (dev->driver) {
- ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
+ ide_drv = to_ide_driver(dev->driver);
len = sprintf(page, "%s version %s\n",
dev->driver->name, ide_drv->version);
} else
@@ -555,7 +555,7 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
}
}
-void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
+void ide_proc_register_driver(ide_drive_t *drive, struct ide_driver *driver)
{
mutex_lock(&ide_setting_mtx);
drive->settings = driver->proc_devsets(drive);
@@ -577,7 +577,7 @@ EXPORT_SYMBOL(ide_proc_register_driver);
* Takes ide_setting_mtx.
*/
-void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
+void ide_proc_unregister_driver(ide_drive_t *drive, struct ide_driver *driver)
{
ide_remove_proc_entries(drive->proc, driver->proc_entries(drive));
@@ -593,14 +593,13 @@ EXPORT_SYMBOL(ide_proc_unregister_driver);
void ide_proc_port_register_devices(ide_hwif_t *hwif)
{
- int d;
struct proc_dir_entry *ent;
struct proc_dir_entry *parent = hwif->proc;
+ ide_drive_t *drive;
char name[64];
+ int i;
- for (d = 0; d < MAX_DRIVES; d++) {
- ide_drive_t *drive = &hwif->drives[d];
-
+ ide_port_for_each_dev(i, drive, hwif) {
if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc)
continue;
@@ -653,7 +652,7 @@ void ide_proc_unregister_port(ide_hwif_t *hwif)
static int proc_print_driver(struct device_driver *drv, void *data)
{
- ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver);
+ struct ide_driver *ide_drv = to_ide_driver(drv);
struct seq_file *s = data;
seq_printf(s, "%s version %s\n", drv->name, ide_drv->version);
diff --git a/drivers/ide/ide-sysfs.c b/drivers/ide/ide-sysfs.c
new file mode 100644
index 000000000000..883ffacaf45a
--- /dev/null
+++ b/drivers/ide/ide-sysfs.c
@@ -0,0 +1,125 @@
+#include <linux/kernel.h>
+#include <linux/ide.h>
+
+char *ide_media_string(ide_drive_t *drive)
+{
+ switch (drive->media) {
+ case ide_disk:
+ return "disk";
+ case ide_cdrom:
+ return "cdrom";
+ case ide_tape:
+ return "tape";
+ case ide_floppy:
+ return "floppy";
+ case ide_optical:
+ return "optical";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static ssize_t media_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", ide_media_string(drive));
+}
+
+static ssize_t drivename_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", drive->name);
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "ide:m-%s\n", ide_media_string(drive));
+}
+
+static ssize_t model_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
+}
+
+static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);
+}
+
+static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ide_drive_t *drive = to_ide_device(dev);
+ return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
+}
+
+struct device_attribute ide_dev_attrs[] = {
+ __ATTR_RO(media),
+ __ATTR_RO(drivename),
+ __ATTR_RO(modalias),
+ __ATTR_RO(model),
+ __ATTR_RO(firmware),
+ __ATTR(serial, 0400, serial_show, NULL),
+ __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
+ __ATTR_NULL
+};
+
+static ssize_t store_delete_devices(struct device *portdev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ ide_hwif_t *hwif = dev_get_drvdata(portdev);
+
+ if (strncmp(buf, "1", n))
+ return -EINVAL;
+
+ ide_port_unregister_devices(hwif);
+
+ return n;
+};
+
+static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices);
+
+static ssize_t store_scan(struct device *portdev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ ide_hwif_t *hwif = dev_get_drvdata(portdev);
+
+ if (strncmp(buf, "1", n))
+ return -EINVAL;
+
+ ide_port_unregister_devices(hwif);
+ ide_port_scan(hwif);
+
+ return n;
+};
+
+static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan);
+
+static struct device_attribute *ide_port_attrs[] = {
+ &dev_attr_delete_devices,
+ &dev_attr_scan,
+ NULL
+};
+
+int ide_sysfs_register_port(ide_hwif_t *hwif)
+{
+ int i, uninitialized_var(rc);
+
+ for (i = 0; ide_port_attrs[i]; i++) {
+ rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
+ if (rc)
+ break;
+ }
+
+ return rc;
+}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index a2d470eb2b55..d7ecd3c79757 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -166,10 +166,10 @@ struct idetape_bh {
* to an interrupt or a timer event is stored in the struct defined below.
*/
typedef struct ide_tape_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct kref kref;
+ ide_drive_t *drive;
+ struct ide_driver *driver;
+ struct gendisk *disk;
+ struct kref kref;
/*
* failed_pc points to the last failed packet command, or contains
@@ -479,7 +479,7 @@ static void ide_tape_kfree_buffer(idetape_tape_t *tape)
static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
{
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = drive->hwif->rq;
idetape_tape_t *tape = drive->driver_data;
unsigned long flags;
int error;
@@ -531,7 +531,7 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc)
printk(KERN_ERR "ide-tape: Error in REQUEST SENSE "
"itself - Aborting request!\n");
} else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
- struct request *rq = drive->hwif->hwgroup->rq;
+ struct request *rq = drive->hwif->rq;
int blocks = pc->xferred / tape->blk_size;
tape->avg_size += blocks * tape->blk_size;
@@ -576,7 +576,7 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc)
/*
* Postpone the current request so that ide.c will be able to service requests
- * from another device on the same hwgroup while we are polling for DSC.
+ * from another device on the same port while we are polling for DSC.
*/
static void idetape_postpone_request(ide_drive_t *drive)
{
@@ -584,7 +584,8 @@ static void idetape_postpone_request(ide_drive_t *drive)
debug_log(DBG_PROCS, "Enter %s\n", __func__);
- tape->postponed_rq = HWGROUP(drive)->rq;
+ tape->postponed_rq = drive->hwif->rq;
+
ide_stall_queue(drive, tape->dsc_poll_freq);
}
@@ -694,7 +695,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
pc->retries++;
- return ide_issue_pc(drive, WAIT_TAPE_CMD, NULL);
+ return ide_issue_pc(drive);
}
/* A mode sense command is used to "sense" tape parameters. */
@@ -2312,7 +2313,7 @@ static const struct ide_proc_devset *ide_tape_proc_devsets(ide_drive_t *drive)
static int ide_tape_probe(ide_drive_t *);
-static ide_driver_t idetape_driver = {
+static struct ide_driver idetape_driver = {
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-tape",
@@ -2323,7 +2324,6 @@ static ide_driver_t idetape_driver = {
.version = IDETAPE_VERSION,
.do_request = idetape_do_request,
.end_request = idetape_end_request,
- .error = __ide_error,
#ifdef CONFIG_IDE_PROC_FS
.proc_entries = ide_tape_proc_entries,
.proc_devsets = ide_tape_proc_devsets,
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index bf4fb9d8d176..16138bce84a7 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -58,7 +58,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *);
ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct ide_taskfile *tf = &task->tf;
ide_handler_t *handler = NULL;
const struct ide_tp_ops *tp_ops = hwif->tp_ops;
@@ -309,9 +309,9 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
}
if (sectors > 0) {
- ide_driver_t *drv;
+ struct ide_driver *drv;
- drv = *(ide_driver_t **)rq->rq_disk->private_data;
+ drv = *(struct ide_driver **)rq->rq_disk->private_data;
drv->end_request(drive, 1, sectors);
}
}
@@ -328,9 +328,9 @@ void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
}
if (rq->rq_disk) {
- ide_driver_t *drv;
+ struct ide_driver *drv;
- drv = *(ide_driver_t **)rq->rq_disk->private_data;;
+ drv = *(struct ide_driver **)rq->rq_disk->private_data;;
drv->end_request(drive, 1, rq->nr_sectors);
} else
ide_end_request(drive, 1, rq->nr_sectors);
@@ -361,7 +361,7 @@ static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq
static ide_startstop_t task_in_intr(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
u8 stat = hwif->tp_ops->read_status(hwif);
/* Error? */
@@ -395,7 +395,7 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive)
static ide_startstop_t task_out_intr (ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = hwif->rq;
u8 stat = hwif->tp_ops->read_status(hwif);
if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index f0f09f702e9c..258805da15c3 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -60,179 +60,8 @@
#include <linux/completion.h>
#include <linux/device.h>
-
-/* default maximum number of failures */
-#define IDE_DEFAULT_MAX_FAILURES 1
-
struct class *ide_port_class;
-static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
- IDE2_MAJOR, IDE3_MAJOR,
- IDE4_MAJOR, IDE5_MAJOR,
- IDE6_MAJOR, IDE7_MAJOR,
- IDE8_MAJOR, IDE9_MAJOR };
-
-DEFINE_MUTEX(ide_cfg_mtx);
-
-static void ide_port_init_devices_data(ide_hwif_t *);
-
-/*
- * Do not even *think* about calling this!
- */
-void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
-{
- /* bulk initialize hwif & drive info with zeros */
- memset(hwif, 0, sizeof(ide_hwif_t));
-
- /* fill in any non-zero initial values */
- hwif->index = index;
- hwif->major = ide_hwif_to_major[index];
-
- hwif->name[0] = 'i';
- hwif->name[1] = 'd';
- hwif->name[2] = 'e';
- hwif->name[3] = '0' + index;
-
- init_completion(&hwif->gendev_rel_comp);
-
- hwif->tp_ops = &default_tp_ops;
-
- ide_port_init_devices_data(hwif);
-}
-
-static void ide_port_init_devices_data(ide_hwif_t *hwif)
-{
- int unit;
-
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- ide_drive_t *drive = &hwif->drives[unit];
- u8 j = (hwif->index * MAX_DRIVES) + unit;
-
- memset(drive, 0, sizeof(*drive));
-
- drive->media = ide_disk;
- drive->select = (unit << 4) | ATA_DEVICE_OBS;
- drive->hwif = hwif;
- drive->ready_stat = ATA_DRDY;
- drive->bad_wstat = BAD_W_STAT;
- drive->special.b.recalibrate = 1;
- drive->special.b.set_geometry = 1;
- drive->name[0] = 'h';
- drive->name[1] = 'd';
- drive->name[2] = 'a' + j;
- drive->max_failures = IDE_DEFAULT_MAX_FAILURES;
-
- INIT_LIST_HEAD(&drive->list);
- init_completion(&drive->gendev_rel_comp);
- }
-}
-
-static void __ide_port_unregister_devices(ide_hwif_t *hwif)
-{
- int i;
-
- for (i = 0; i < MAX_DRIVES; i++) {
- ide_drive_t *drive = &hwif->drives[i];
-
- if (drive->dev_flags & IDE_DFLAG_PRESENT) {
- device_unregister(&drive->gendev);
- wait_for_completion(&drive->gendev_rel_comp);
- }
- }
-}
-
-void ide_port_unregister_devices(ide_hwif_t *hwif)
-{
- mutex_lock(&ide_cfg_mtx);
- __ide_port_unregister_devices(hwif);
- hwif->present = 0;
- ide_port_init_devices_data(hwif);
- mutex_unlock(&ide_cfg_mtx);
-}
-EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
-
-/**
- * ide_unregister - free an IDE interface
- * @hwif: IDE interface
- *
- * Perform the final unregister of an IDE interface. At the moment
- * we don't refcount interfaces so this will also get split up.
- *
- * Locking:
- * The caller must not hold the IDE locks
- * The drive present/vanishing is not yet properly locked
- * Take care with the callbacks. These have been split to avoid
- * deadlocking the IDE layer. The shutdown callback is called
- * before we take the lock and free resources. It is up to the
- * caller to be sure there is no pending I/O here, and that
- * the interface will not be reopened (present/vanishing locking
- * isn't yet done BTW). After we commit to the final kill we
- * call the cleanup callback with the ide locks held.
- *
- * Unregister restores the hwif structures to the default state.
- * This is raving bonkers.
- */
-
-void ide_unregister(ide_hwif_t *hwif)
-{
- ide_hwif_t *g;
- ide_hwgroup_t *hwgroup;
- int irq_count = 0;
-
- BUG_ON(in_interrupt());
- BUG_ON(irqs_disabled());
-
- mutex_lock(&ide_cfg_mtx);
-
- if (hwif->present) {
- __ide_port_unregister_devices(hwif);
- hwif->present = 0;
- }
-
- ide_proc_unregister_port(hwif);
-
- hwgroup = hwif->hwgroup;
- /*
- * free the irq if we were the only hwif using it
- */
- g = hwgroup->hwif;
- do {
- if (g->irq == hwif->irq)
- ++irq_count;
- g = g->next;
- } while (g != hwgroup->hwif);
- if (irq_count == 1)
- free_irq(hwif->irq, hwgroup);
-
- ide_remove_port_from_hwgroup(hwif);
-
- device_unregister(hwif->portdev);
- device_unregister(&hwif->gendev);
- wait_for_completion(&hwif->gendev_rel_comp);
-
- /*
- * Remove us from the kernel's knowledge
- */
- blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
- kfree(hwif->sg_table);
- unregister_blkdev(hwif->major, hwif->name);
-
- ide_release_dma_engine(hwif);
-
- mutex_unlock(&ide_cfg_mtx);
-}
-
-void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
-{
- memcpy(&hwif->io_ports, &hw->io_ports, sizeof(hwif->io_ports));
- hwif->irq = hw->irq;
- hwif->chipset = hw->chipset;
- hwif->dev = hw->dev;
- hwif->gendev.parent = hw->parent ? hw->parent : hw->dev;
- hwif->ack_intr = hw->ack_intr;
- hwif->config_data = hw->config;
-}
-
/*
* Locks for IDE setting functionality
*/
@@ -330,7 +159,6 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio)
static int set_pio_mode(ide_drive_t *drive, int arg)
{
ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *hwgroup = hwif->hwgroup;
const struct ide_port_ops *port_ops = hwif->port_ops;
if (arg < 0 || arg > 255)
@@ -345,9 +173,9 @@ static int set_pio_mode(ide_drive_t *drive, int arg)
unsigned long flags;
/* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */
- spin_lock_irqsave(&hwgroup->lock, flags);
+ spin_lock_irqsave(&hwif->lock, flags);
port_ops->set_pio_mode(drive, arg);
- spin_unlock_irqrestore(&hwgroup->lock, flags);
+ spin_unlock_irqrestore(&hwif->lock, flags);
} else
port_ops->set_pio_mode(drive, arg);
} else {
@@ -440,88 +268,20 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv)
return 1;
}
-static char *media_string(ide_drive_t *drive)
-{
- switch (drive->media) {
- case ide_disk:
- return "disk";
- case ide_cdrom:
- return "cdrom";
- case ide_tape:
- return "tape";
- case ide_floppy:
- return "floppy";
- case ide_optical:
- return "optical";
- default:
- return "UNKNOWN";
- }
-}
-
-static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", media_string(drive));
-}
-
-static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", drive->name);
-}
-
-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "ide:m-%s\n", media_string(drive));
-}
-
-static ssize_t model_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_PROD]);
-}
-
-static ssize_t firmware_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_FW_REV]);
-}
-
-static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- ide_drive_t *drive = to_ide_device(dev);
- return sprintf(buf, "%s\n", (char *)&drive->id[ATA_ID_SERNO]);
-}
-
-static struct device_attribute ide_dev_attrs[] = {
- __ATTR_RO(media),
- __ATTR_RO(drivename),
- __ATTR_RO(modalias),
- __ATTR_RO(model),
- __ATTR_RO(firmware),
- __ATTR(serial, 0400, serial_show, NULL),
- __ATTR(unload_heads, 0644, ide_park_show, ide_park_store),
- __ATTR_NULL
-};
-
static int ide_uevent(struct device *dev, struct kobj_uevent_env *env)
{
ide_drive_t *drive = to_ide_device(dev);
- add_uevent_var(env, "MEDIA=%s", media_string(drive));
+ add_uevent_var(env, "MEDIA=%s", ide_media_string(drive));
add_uevent_var(env, "DRIVENAME=%s", drive->name);
- add_uevent_var(env, "MODALIAS=ide:m-%s", media_string(drive));
+ add_uevent_var(env, "MODALIAS=ide:m-%s", ide_media_string(drive));
return 0;
}
static int generic_ide_probe(struct device *dev)
{
ide_drive_t *drive = to_ide_device(dev);
- ide_driver_t *drv = to_ide_driver(dev->driver);
+ struct ide_driver *drv = to_ide_driver(dev->driver);
return drv->probe ? drv->probe(drive) : -ENODEV;
}
@@ -529,7 +289,7 @@ static int generic_ide_probe(struct device *dev)
static int generic_ide_remove(struct device *dev)
{
ide_drive_t *drive = to_ide_device(dev);
- ide_driver_t *drv = to_ide_driver(dev->driver);
+ struct ide_driver *drv = to_ide_driver(dev->driver);
if (drv->remove)
drv->remove(drive);
@@ -540,7 +300,7 @@ static int generic_ide_remove(struct device *dev)
static void generic_ide_shutdown(struct device *dev)
{
ide_drive_t *drive = to_ide_device(dev);
- ide_driver_t *drv = to_ide_driver(dev->driver);
+ struct ide_driver *drv = to_ide_driver(dev->driver);
if (dev->driver && drv->shutdown)
drv->shutdown(drive);
@@ -728,6 +488,7 @@ MODULE_PARM_DESC(ignore_cable, "ignore cable detection");
void ide_port_apply_params(ide_hwif_t *hwif)
{
+ ide_drive_t *drive;
int i;
if (ide_ignore_cable & (1 << hwif->index)) {
@@ -736,8 +497,8 @@ void ide_port_apply_params(ide_hwif_t *hwif)
hwif->cbl = ATA_CBL_PATA40_SHORT;
}
- for (i = 0; i < MAX_DRIVES; i++)
- ide_dev_apply_params(&hwif->drives[i], i);
+ ide_port_for_each_dev(i, drive, hwif)
+ ide_dev_apply_params(drive, i);
}
/*
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c
new file mode 100644
index 000000000000..e021078cd06b
--- /dev/null
+++ b/drivers/ide/it8172.c
@@ -0,0 +1,166 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * IT8172 IDE controller support
+ *
+ * Copyright (C) 2000 MontaVista Software Inc.
+ * Copyright (C) 2008 Shane McDonald
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#define DRV_NAME "IT8172"
+
+static void it8172_set_pio_mode(ide_drive_t *drive, const u8 pio)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ u16 drive_enables;
+ u32 drive_timing;
+
+ /*
+ * The highest value of DIOR/DIOW pulse width and recovery time
+ * that can be set in the IT8172 is 8 PCI clock cycles. As a result,
+ * it cannot be configured for PIO mode 0. This table sets these
+ * parameters to the maximum supported by the IT8172.
+ */
+ static const u8 timings[] = { 0x3f, 0x3c, 0x1b, 0x12, 0x0a };
+
+ pci_read_config_word(dev, 0x40, &drive_enables);
+ pci_read_config_dword(dev, 0x44, &drive_timing);
+
+ /*
+ * Enable port 0x44. The IT8172 spec is confused; it calls
+ * this register the "Slave IDE Timing Register", but in fact,
+ * it controls timing for both master and slave drives.
+ */
+ drive_enables |= 0x4000;
+
+ drive_enables &= drive->dn ? 0xc006 : 0xc060;
+ if (drive->media == ide_disk)
+ /* enable prefetch */
+ drive_enables |= 0x0004 << (drive->dn * 4);
+ if (ata_id_has_iordy(drive->id))
+ /* enable IORDY sample-point */
+ drive_enables |= 0x0002 << (drive->dn * 4);
+
+ drive_timing &= drive->dn ? 0x00003f00 : 0x000fc000;
+ drive_timing |= timings[pio] << (drive->dn * 6 + 8);
+
+ pci_write_config_word(dev, 0x40, drive_enables);
+ pci_write_config_dword(dev, 0x44, drive_timing);
+}
+
+static void it8172_set_dma_mode(ide_drive_t *drive, const u8 speed)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct pci_dev *dev = to_pci_dev(hwif->dev);
+ int a_speed = 3 << (drive->dn * 4);
+ int u_flag = 1 << drive->dn;
+ int u_speed = 0;
+ u8 reg48, reg4a;
+
+ pci_read_config_byte(dev, 0x48, &reg48);
+ pci_read_config_byte(dev, 0x4a, &reg4a);
+
+ if (speed >= XFER_UDMA_0) {
+ u8 udma = speed - XFER_UDMA_0;
+ u_speed = udma << (drive->dn * 4);
+
+ pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+ reg4a &= ~a_speed;
+ pci_write_config_byte(dev, 0x4a, reg4a | u_speed);
+ } else {
+ const u8 mwdma_to_pio[] = { 0, 3, 4 };
+ u8 pio;
+
+ pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+ pci_write_config_byte(dev, 0x4a, reg4a & ~a_speed);
+
+ pio = mwdma_to_pio[speed - XFER_MW_DMA_0];
+
+ it8172_set_pio_mode(drive, pio);
+ }
+}
+
+
+static const struct ide_port_ops it8172_port_ops = {
+ .set_pio_mode = it8172_set_pio_mode,
+ .set_dma_mode = it8172_set_dma_mode,
+};
+
+static const struct ide_port_info it8172_port_info __devinitdata = {
+ .name = DRV_NAME,
+ .port_ops = &it8172_port_ops,
+ .enablebits = { {0x41, 0x80, 0x80}, {0x00, 0x00, 0x00} },
+ .host_flags = IDE_HFLAG_SINGLE,
+ .pio_mask = ATA_PIO4 & ~ATA_PIO0,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA2,
+};
+
+static int __devinit it8172_init_one(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+ return -ENODEV; /* IT8172 is more than an IDE controller */
+ return ide_pci_init_one(dev, &it8172_port_info, NULL);
+}
+
+static struct pci_device_id it8172_pci_tbl[] = {
+ { PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8172), 0 },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, it8172_pci_tbl);
+
+static struct pci_driver it8172_pci_driver = {
+ .name = "IT8172_IDE",
+ .id_table = it8172_pci_tbl,
+ .probe = it8172_init_one,
+ .remove = ide_pci_remove,
+ .suspend = ide_pci_suspend,
+ .resume = ide_pci_resume,
+};
+
+static int __init it8172_ide_init(void)
+{
+ return ide_pci_register_driver(&it8172_pci_driver);
+}
+
+static void __exit it8172_ide_exit(void)
+{
+ pci_unregister_driver(&it8172_pci_driver);
+}
+
+module_init(it8172_ide_init);
+module_exit(it8172_ide_exit);
+
+MODULE_AUTHOR("Steve Longerbeam");
+MODULE_DESCRIPTION("PCI driver module for ITE 8172 IDE");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/it8213.c b/drivers/ide/it8213.c
index 7c2feeb3c5ec..d7969b6d139e 100644
--- a/drivers/ide/it8213.c
+++ b/drivers/ide/it8213.c
@@ -25,7 +25,7 @@
static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
int is_slave = drive->dn & 1;
int master_port = 0x40;
@@ -82,7 +82,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 maslave = 0x40;
int a_speed = 3 << (drive->dn * 4);
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index ef004089761b..e1c4f5437396 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -68,6 +68,8 @@
#define DRV_NAME "it821x"
+#define QUIRK_VORTEX86 1
+
struct it821x_dev
{
unsigned int smart:1, /* Are we in smart raid mode */
@@ -79,6 +81,7 @@ struct it821x_dev
u16 pio[2]; /* Cached PIO values */
u16 mwdma[2]; /* Cached MWDMA values */
u16 udma[2]; /* Cached UDMA values (per drive) */
+ u16 quirks;
};
#define ATA_66 0
@@ -167,12 +170,10 @@ static void it821x_clock_strategy(ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- ide_drive_t *pair;
+ ide_drive_t *pair = ide_get_pair_dev(drive);
int clock, altclock, sel = 0;
u8 unit = drive->dn & 1, v;
- pair = &hwif->drives[1 - unit];
-
if(itdev->want[0][0] > itdev->want[1][0]) {
clock = itdev->want[0][1];
altclock = itdev->want[1][1];
@@ -239,15 +240,13 @@ static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
ide_hwif_t *hwif = drive->hwif;
struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- ide_drive_t *pair;
+ ide_drive_t *pair = ide_get_pair_dev(drive);
u8 unit = drive->dn & 1, set_pio = pio;
/* Spec says 89 ref driver uses 88 */
static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
- pair = &hwif->drives[1 - unit];
-
/*
* Compute the best PIO mode we can for a given device. We must
* pick a speed that does not cause problems with the other device
@@ -279,7 +278,7 @@ static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
* the shared MWDMA/PIO timing register.
*/
-static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
+static void it821x_tune_mwdma(ide_drive_t *drive, u8 mode_wanted)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -316,7 +315,7 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
* controller when doing UDMA modes in pass through.
*/
-static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
+static void it821x_tune_udma(ide_drive_t *drive, u8 mode_wanted)
{
ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
@@ -516,6 +515,7 @@ static struct ide_dma_ops it821x_pass_through_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
/**
@@ -560,8 +560,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
* this is necessary.
*/
- pci_read_config_byte(dev, 0x08, &conf);
- if (conf == 0x10) {
+ if (dev->revision == 0x10) {
idev->timing10 = 1;
hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
if (idev->smart == 0)
@@ -580,6 +579,12 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
hwif->ultra_mask = ATA_UDMA6;
hwif->mwdma_mask = ATA_MWDMA2;
+
+ /* Vortex86SX quirk: prevent Ultra-DMA mode to fix BadCRC issue */
+ if (idev->quirks & QUIRK_VORTEX86) {
+ if (dev->revision == 0x11)
+ hwif->ultra_mask = 0;
+ }
}
static void it8212_disable_raid(struct pci_dev *dev)
@@ -652,6 +657,8 @@ static int __devinit it821x_init_one(struct pci_dev *dev, const struct pci_devic
return -ENOMEM;
}
+ itdevs->quirks = id->driver_data;
+
rc = ide_pci_init_one(dev, &it821x_chipset, itdevs);
if (rc)
kfree(itdevs);
@@ -671,6 +678,7 @@ static void __devexit it821x_remove(struct pci_dev *dev)
static const struct pci_device_id it821x_pci_tbl[] = {
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), 0 },
{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), 0 },
+ { PCI_VDEVICE(RDC, PCI_DEVICE_ID_RDC_D1010), QUIRK_VORTEX86 },
{ 0, },
};
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
index 13789060f407..83643ed9a426 100644
--- a/drivers/ide/ns87415.c
+++ b/drivers/ide/ns87415.c
@@ -56,7 +56,7 @@ static u8 superio_read_status(ide_hwif_t *hwif)
return superio_ide_inb(hwif->io_ports.status_addr);
}
-static u8 superio_read_sff_dma_status(ide_hwif_t *hwif)
+static u8 superio_dma_sff_read_status(ide_hwif_t *hwif)
{
return superio_ide_inb(hwif->dma_base + ATA_DMA_STATUS);
}
@@ -109,7 +109,6 @@ static const struct ide_tp_ops superio_tp_ops = {
.exec_command = ide_exec_command,
.read_status = superio_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = superio_read_sff_dma_status,
.set_irq = ide_set_irq,
@@ -132,18 +131,20 @@ static void __devinit superio_init_iops(struct hwif_s *hwif)
tmp = superio_ide_inb(dma_stat);
outb(tmp | 0x66, dma_stat);
}
+#else
+#define superio_dma_sff_read_status ide_dma_sff_read_status
#endif
static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
/*
* This routine either enables/disables (according to IDE_DFLAG_PRESENT)
- * the IRQ associated with the port (HWIF(drive)),
+ * the IRQ associated with the port,
* and selects either PIO or DMA handshaking for the next I/O operation.
*/
static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
unsigned long flags;
@@ -197,11 +198,11 @@ static void ns87415_selectproc (ide_drive_t *drive)
static int ns87415_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u8 dma_stat = 0, dma_cmd = 0;
drive->waiting_for_dma = 0;
- dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
/* get DMA command mode */
dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
/* stop DMA */
@@ -308,6 +309,7 @@ static const struct ide_dma_ops ns87415_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = superio_dma_sff_read_status,
};
static const struct ide_port_info ns87415_chipset __devinitdata = {
diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c
index 122ed3c072fd..f38aac78044c 100644
--- a/drivers/ide/palm_bk3710.c
+++ b/drivers/ide/palm_bk3710.c
@@ -324,8 +324,6 @@ static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif,
hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET;
- hwif->dma_ops = &sff_dma_ops;
-
return 0;
}
@@ -338,6 +336,7 @@ static const struct ide_port_ops palm_bk3710_ports_ops = {
static struct ide_port_info __devinitdata palm_bk3710_port_info = {
.init_dma = palm_bk3710_init_dma,
.port_ops = &palm_bk3710_ports_ops,
+ .dma_ops = &sff_dma_ops,
.host_flags = IDE_HFLAG_MMIO,
.pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2,
@@ -347,7 +346,8 @@ static int __init palm_bk3710_probe(struct platform_device *pdev)
{
struct clk *clk;
struct resource *mem, *irq;
- unsigned long base, rate;
+ void __iomem *base;
+ unsigned long rate;
int i, rc;
hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL };
@@ -383,11 +383,13 @@ static int __init palm_bk3710_probe(struct platform_device *pdev)
base = IO_ADDRESS(mem->start);
/* Configure the Palm Chip controller */
- palm_bk3710_chipinit((void __iomem *)base);
+ palm_bk3710_chipinit(base);
for (i = 0; i < IDE_NR_PORTS - 2; i++)
- hw.io_ports_array[i] = base + IDE_PALM_ATA_PRI_REG_OFFSET + i;
- hw.io_ports.ctl_addr = base + IDE_PALM_ATA_PRI_CTL_OFFSET;
+ hw.io_ports_array[i] = (unsigned long)
+ (base + IDE_PALM_ATA_PRI_REG_OFFSET + i);
+ hw.io_ports.ctl_addr = (unsigned long)
+ (base + IDE_PALM_ATA_PRI_CTL_OFFSET);
hw.irq = irq->start;
hw.dev = &pdev->dev;
hw.chipset = ide_palm3710;
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
index 211ae46e3e0c..f21290c4b447 100644
--- a/drivers/ide/pdc202xx_new.c
+++ b/drivers/ide/pdc202xx_new.c
@@ -143,7 +143,7 @@ static struct udma_timing {
static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
@@ -219,7 +219,7 @@ static void pdcnew_reset(ide_drive_t *drive)
* Deleted this because it is redundant from the caller.
*/
printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n",
- HWIF(drive)->channel ? "Secondary" : "Primary");
+ drive->hwif->channel ? "Secondary" : "Primary");
}
/**
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index 624e62e5cc9a..97193323aebf 100644
--- a/drivers/ide/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
@@ -39,7 +39,7 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 drive_pci = 0x60 + (drive->dn << 2);
@@ -169,8 +169,8 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
if (drive->current_speed > XFER_UDMA_2)
pdc_old_enable_66MHz_clock(drive->hwif);
if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
- struct request *rq = HWGROUP(drive)->rq;
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
+ struct request *rq = hwif->rq;
unsigned long high_16 = hwif->extra_base - 16;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u32 word_count = 0;
@@ -189,7 +189,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive)
static int pdc202xx_dma_end(ide_drive_t *drive)
{
if (drive->media != ide_disk || (drive->dev_flags & IDE_DFLAG_LBA48)) {
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long high_16 = hwif->extra_base - 16;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u8 clock = 0;
@@ -205,7 +205,7 @@ static int pdc202xx_dma_end(ide_drive_t *drive)
static int pdc202xx_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long high_16 = hwif->extra_base - 16;
u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
u8 sc1d = inb(high_16 + 0x001d);
@@ -243,7 +243,7 @@ static void pdc202xx_reset_host (ide_hwif_t *hwif)
static void pdc202xx_reset (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
ide_hwif_t *mate = hwif->mate;
pdc202xx_reset_host(hwif);
@@ -337,6 +337,7 @@ static const struct ide_dma_ops pdc20246_dma_ops = {
.dma_test_irq = pdc202xx_dma_test_irq,
.dma_lost_irq = pdc202xx_dma_lost_irq,
.dma_timeout = pdc202xx_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_dma_ops pdc2026x_dma_ops = {
@@ -348,6 +349,7 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
.dma_test_irq = pdc202xx_dma_test_irq,
.dma_lost_irq = pdc202xx_dma_lost_irq,
.dma_timeout = pdc202xx_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
#define DECLARE_PDC2026X_DEV(udma, sectors) \
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index 61d2d920a5cd..f1e2e4ef0d71 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -67,7 +67,7 @@ static int no_piix_dma;
static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
int is_slave = drive->dn & 1;
int master_port = hwif->channel ? 0x42 : 0x40;
@@ -136,7 +136,7 @@ static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 maslave = hwif->channel ? 0x42 : 0x40;
int a_speed = 3 << (drive->dn * 4);
@@ -224,7 +224,7 @@ static unsigned int init_chipset_ich(struct pci_dev *dev)
*/
static void ich_clear_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u8 dma_stat;
/*
@@ -260,6 +260,8 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
{ 0x27DF, 0x1071, 0xD221 }, /* ICH7 on Hercules EC-900 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
+ { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */
+ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
/* end marker */
{ 0, }
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c
index 7c481bb56fab..74625e821a43 100644
--- a/drivers/ide/pmac.c
+++ b/drivers/ide/pmac.c
@@ -955,7 +955,6 @@ static const struct ide_tp_ops pmac_tp_ops = {
.exec_command = pmac_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = pmac_set_irq,
@@ -1513,10 +1512,10 @@ use_pio_instead:
static int
pmac_ide_dma_setup(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
pmac_ide_hwif_t *pmif =
(pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = hwif->rq;
u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4);
if (!pmac_ide_build_dmatable(drive, rq)) {
@@ -1637,7 +1636,7 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
break;
if (++timeout > 100) {
printk(KERN_WARNING "ide%d, ide_dma_test_irq \
- timeout flushing channel\n", HWIF(drive)->index);
+ timeout flushing channel\n", hwif->index);
break;
}
}
diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c
index 4af4a8ce4cdf..9f9c0b3cc3a3 100644
--- a/drivers/ide/q40ide.c
+++ b/drivers/ide/q40ide.c
@@ -99,7 +99,6 @@ static const struct ide_tp_ops q40ide_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index bc27c7aba936..08c4fa35e9b1 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -16,7 +16,7 @@
/*
* Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
- * Samuel Thibault <samuel.thibault@fnac.net>
+ * Samuel Thibault <samuel.thibault@ens-lyon.org>
*/
#include <linux/module.h>
@@ -202,7 +202,8 @@ static void qd6500_set_pio_mode(ide_drive_t *drive, const u8 pio)
recovery_time = drive->id[ATA_ID_EIDE_PIO] - 120;
}
- qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time));
+ qd_set_timing(drive, qd6500_compute_timing(drive->hwif,
+ active_time, recovery_time));
}
static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
@@ -245,11 +246,11 @@ static void qd6580_set_pio_mode(ide_drive_t *drive, const u8 pio)
printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio);
}
- if (!HWIF(drive)->channel && drive->media != ide_disk) {
+ if (!hwif->channel && drive->media != ide_disk) {
outb(0x5f, QD_CONTROL_PORT);
printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO "
"and post-write buffer on %s.\n",
- drive->name, HWIF(drive)->name);
+ drive->name, hwif->name);
}
qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time));
diff --git a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h
index c83dea85e621..d7e67a1a1dcc 100644
--- a/drivers/ide/qd65xx.h
+++ b/drivers/ide/qd65xx.h
@@ -4,7 +4,7 @@
/*
* Authors: Petr Soucek <petr@ryston.cz>
- * Samuel Thibault <samuel.thibault@fnac.net>
+ * Samuel Thibault <samuel.thibault@ens-lyon.org>
*/
/* truncates a in [b,c] */
@@ -31,8 +31,8 @@
#define QD_CONFIG(hwif) ((hwif)->config_data & 0x00ff)
-#define QD_TIMING(drive) (byte)(((drive)->drive_data) & 0x00ff)
-#define QD_TIMREG(drive) (byte)((((drive)->drive_data) & 0xff00) >> 8)
+#define QD_TIMING(drive) (u8)(((drive)->drive_data) & 0x00ff)
+#define QD_TIMREG(drive) (u8)((((drive)->drive_data) & 0xff00) >> 8)
#define QD6500_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0c : 0x08))
#define QD6580_DEF_DATA ((QD_TIM1_PORT<<8) | (QD_ID3 ? 0x0a : 0x00))
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c
index ec7f766ef5e4..dbdd2985a0d8 100644
--- a/drivers/ide/sc1200.c
+++ b/drivers/ide/sc1200.c
@@ -125,7 +125,7 @@ out:
static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned int reg, timings;
unsigned short pci_clock;
@@ -170,9 +170,9 @@ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
*/
static int sc1200_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long dma_base = hwif->dma_base;
- byte dma_stat;
+ u8 dma_stat;
dma_stat = inb(dma_base+2); /* get DMA status */
@@ -199,7 +199,7 @@ static int sc1200_dma_end(ide_drive_t *drive)
static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
int mode = -1;
/*
@@ -292,6 +292,7 @@ static const struct ide_dma_ops sc1200_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info sc1200_chipset __devinitdata = {
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c
index 0f48f9dacfa5..8d2314b6327c 100644
--- a/drivers/ide/scc_pata.c
+++ b/drivers/ide/scc_pata.c
@@ -143,7 +143,7 @@ static u8 scc_read_altstatus(ide_hwif_t *hwif)
return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
}
-static u8 scc_read_sff_dma_status(ide_hwif_t *hwif)
+static u8 scc_dma_sff_read_status(ide_hwif_t *hwif)
{
return (u8)in_be32((void *)(hwif->dma_base + 4));
}
@@ -217,7 +217,7 @@ scc_ide_outsl(unsigned long port, void *addr, u32 count)
static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct scc_ports *ports = ide_get_hwifdata(hwif);
unsigned long ctl_base = ports->ctl;
unsigned long cckctrl_port = ctl_base + 0xff0;
@@ -249,7 +249,7 @@ static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct scc_ports *ports = ide_get_hwifdata(hwif);
unsigned long ctl_base = ports->ctl;
unsigned long cckctrl_port = ctl_base + 0xff0;
@@ -259,7 +259,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
unsigned long scrcst_port = ctl_base + 0x014;
unsigned long udenvt_port = ctl_base + 0x018;
unsigned long tdvhsel_port = ctl_base + 0x020;
- int is_slave = (&hwif->drives[1] == drive);
+ int is_slave = drive->dn & 1;
int offset, idx;
unsigned long reg;
unsigned long jcactsel;
@@ -292,7 +292,7 @@ static void scc_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = drive->hwif;
u8 unit = drive->dn & 1;
- u8 dma_stat = scc_ide_inb(hwif->dma_base + 4);
+ u8 dma_stat = scc_dma_sff_read_status(hwif);
if (on)
dma_stat |= (1 << (5 + unit));
@@ -316,7 +316,7 @@ static void scc_dma_host_set(ide_drive_t *drive, int on)
static int scc_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = hwif->rq;
unsigned int reading;
u8 dma_stat;
@@ -338,7 +338,7 @@ static int scc_dma_setup(ide_drive_t *drive)
out_be32((void __iomem *)hwif->dma_base, reading);
/* read DMA status for INTR & ERROR flags */
- dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));
+ dma_stat = scc_dma_sff_read_status(hwif);
/* clear INTR & ERROR flags */
out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
@@ -367,7 +367,7 @@ static int __scc_dma_end(ide_drive_t *drive)
/* stop DMA */
scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
/* get DMA status */
- dma_stat = scc_ide_inb(hwif->dma_base + 4);
+ dma_stat = scc_dma_sff_read_status(hwif);
/* clear the INTR & ERROR bits */
scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
/* purge DMA mappings */
@@ -387,7 +387,7 @@ static int __scc_dma_end(ide_drive_t *drive)
static int scc_dma_end(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
void __iomem *dma_base = (void __iomem *)hwif->dma_base;
unsigned long intsts_port = hwif->dma_base + 0x014;
u32 reg;
@@ -405,17 +405,18 @@ static int scc_dma_end(ide_drive_t *drive)
drive->name);
data_loss = 1;
if (retry++) {
- struct request *rq = HWGROUP(drive)->rq;
- int unit;
+ struct request *rq = hwif->rq;
+ ide_drive_t *drive;
+ int i;
+
/* ERROR_RESET and drive->crc_count are needed
* to reduce DMA transfer mode in retry process.
*/
if (rq)
rq->errors |= ERROR_RESET;
- for (unit = 0; unit < MAX_DRIVES; unit++) {
- ide_drive_t *drive = &hwif->drives[unit];
+
+ ide_port_for_each_dev(i, drive, hwif)
drive->crc_count++;
- }
}
}
}
@@ -496,7 +497,7 @@ static int scc_dma_end(ide_drive_t *drive)
/* returns 1 if dma irq issued, 0 otherwise */
static int scc_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
/* SCC errata A252,A308 workaround: Step4 */
@@ -852,7 +853,6 @@ static const struct ide_tp_ops scc_tp_ops = {
.exec_command = scc_exec_command,
.read_status = scc_read_status,
.read_altstatus = scc_read_altstatus,
- .read_sff_dma_status = scc_read_sff_dma_status,
.set_irq = scc_set_irq,
@@ -879,6 +879,7 @@ static const struct ide_dma_ops scc_dma_ops = {
.dma_test_irq = scc_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = scc_dma_sff_read_status,
};
#define DECLARE_SCC_DEV(name_str) \
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index 437bc919dafd..382102ba467b 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -151,7 +151,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
static const u8 dma_modes[] = { 0x77, 0x21, 0x20 };
static const u8 drive_pci2[] = { 0x45, 0x44, 0x47, 0x46 };
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 unit = drive->dn & 1;
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 9f1f9163a136..e85d1ed29c2a 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -130,7 +130,7 @@ int ide_pci_check_simplex(ide_hwif_t *hwif, const struct ide_port_info *d)
* we tune the drive then try to grab DMA ownership if we want to be
* the DMA end. This has to be become dynamic to handle hot-plug.
*/
- dma_stat = hwif->tp_ops->read_sff_dma_status(hwif);
+ dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
printk(KERN_INFO "%s %s: simplex device: DMA disabled\n",
d->name, pci_name(dev));
@@ -377,6 +377,9 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
hwif->dma_base = base;
+ if (hwif->dma_ops == NULL)
+ hwif->dma_ops = &sff_dma_ops;
+
if (ide_pci_check_simplex(hwif, d) < 0)
return -1;
@@ -393,8 +396,6 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
if (ide_allocate_dma_engine(hwif))
return -1;
-
- hwif->dma_ops = &sff_dma_ops;
}
return 0;
@@ -471,7 +472,7 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d,
*/
for (port = 0; port < channels; ++port) {
- const ide_pci_enablebit_t *e = &(d->enablebits[port]);
+ const struct ide_pci_enablebit *e = &d->enablebits[port];
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
(tmp & e->mask) != e->val)) {
@@ -519,8 +520,7 @@ static int do_ide_setup_pci_device(struct pci_dev *dev,
if (ret < 0)
goto out;
- /* Is it an "IDE storage" device in non-PCI mode? */
- if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5) {
+ if (ide_pci_is_in_compatibility_mode(dev)) {
if (noisy)
printk(KERN_INFO "%s %s: not 100%% native mode: will "
"probe irqs later\n", d->name, pci_name(dev));
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c
index a687a7dfea6f..fdb9d7037694 100644
--- a/drivers/ide/sgiioc4.c
+++ b/drivers/ide/sgiioc4.c
@@ -123,7 +123,7 @@ static int
sgiioc4_clearirq(ide_drive_t * drive)
{
u32 intr_reg;
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
unsigned long other_ir = io_ports->irq_addr + (IOC4_INTR_REG << 2);
@@ -181,7 +181,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
static void sgiioc4_dma_start(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long ioc4_dma_addr = hwif->dma_base + IOC4_DMA_CTRL * 4;
unsigned int reg = readl((void __iomem *)ioc4_dma_addr);
unsigned int temp_reg = reg | IOC4_S_DMA_START;
@@ -209,7 +209,7 @@ sgiioc4_ide_dma_stop(ide_hwif_t *hwif, u64 dma_base)
static int sgiioc4_dma_end(ide_drive_t *drive)
{
u32 ioc4_dma, bc_dev, bc_mem, num, valid = 0, cnt = 0;
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long dma_base = hwif->dma_base;
int dma_stat = 0;
unsigned long *ending_dma = ide_get_hwifdata(hwif);
@@ -271,7 +271,7 @@ static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
/* returns 1 if dma irq issued, 0 otherwise */
static int sgiioc4_dma_test_irq(ide_drive_t *drive)
{
- return sgiioc4_checkirq(HWIF(drive));
+ return sgiioc4_checkirq(drive->hwif);
}
static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
@@ -367,7 +367,7 @@ static void
sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
{
u32 ioc4_dma;
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long dma_base = hwif->dma_base;
unsigned long ioc4_dma_addr = dma_base + IOC4_DMA_CTRL * 4;
u32 dma_addr, ending_dma_addr;
@@ -427,7 +427,7 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive)
static unsigned int
sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned int *table = hwif->dmatable_cpu;
unsigned int count = 0, i = 1;
struct scatterlist *sg;
@@ -492,7 +492,7 @@ use_pio_instead:
static int sgiioc4_dma_setup(ide_drive_t *drive)
{
- struct request *rq = HWGROUP(drive)->rq;
+ struct request *rq = drive->hwif->rq;
unsigned int count = 0;
int ddir;
@@ -523,7 +523,6 @@ static const struct ide_tp_ops sgiioc4_tp_ops = {
.exec_command = ide_exec_command,
.read_status = sgiioc4_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
index 7d622d20bc4c..cb2b352b876b 100644
--- a/drivers/ide/siimage.c
+++ b/drivers/ide/siimage.c
@@ -114,7 +114,7 @@ static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long base = (unsigned long)hwif->hwif_data;
u8 unit = drive->dn & 1;
@@ -243,7 +243,7 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
ide_drive_t *pair = ide_get_pair_dev(drive);
u32 speedt = 0;
@@ -300,7 +300,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
static const u16 dma[] = { 0x2208, 0x10C2, 0x10C1 };
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = (unsigned long)hwif->hwif_data;
u16 ultra = 0, multi = 0;
@@ -340,7 +340,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
/* returns 1 if dma irq issued, 0 otherwise */
static int siimage_io_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 dma_altstat = 0;
unsigned long addr = siimage_selreg(hwif, 1);
@@ -367,7 +367,7 @@ static int siimage_io_dma_test_irq(ide_drive_t *drive)
static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long addr = siimage_selreg(hwif, 0x1);
void __iomem *sata_error_addr
= (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
@@ -717,6 +717,7 @@ static const struct ide_dma_ops sil_dma_ops = {
.dma_test_irq = siimage_dma_test_irq,
.dma_timeout = ide_dma_timeout,
.dma_lost_irq = ide_dma_lost_irq,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
#define DECLARE_SII_DEV(p_ops) \
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index ad32e18c5ba3..9ec1a4a4432c 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -274,7 +274,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
static void config_drive_art_rwp(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 reg4bh = 0;
u8 rw_prefetch = 0;
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index 84dc33602ff8..6297956507c0 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -140,7 +140,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
*/
static void sl82c105_dma_lost_irq(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u32 val, mask = hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
u8 dma_cmd;
@@ -177,7 +177,7 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
*/
static void sl82c105_dma_start(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
int reg = 0x44 + drive->dn * 4;
@@ -299,6 +299,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = sl82c105_dma_lost_irq,
.dma_timeout = sl82c105_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info sl82c105_chipset __devinitdata = {
@@ -309,10 +310,6 @@ static const struct ide_port_info sl82c105_chipset __devinitdata = {
.dma_ops = &sl82c105_dma_ops,
.host_flags = IDE_HFLAG_IO_32BIT |
IDE_HFLAG_UNMASK_IRQS |
-/* FIXME: check for Compatibility mode in generic IDE PCI code */
-#if defined(CONFIG_LOPEC) || defined(CONFIG_SANDPOINT)
- IDE_HFLAG_FORCE_LEGACY_IRQS |
-#endif
IDE_HFLAG_SERIALIZE_DMA |
IDE_HFLAG_NO_AUTODMA,
.pio_mask = ATA_PIO5,
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
index 0f759e4ed779..40b4b94a4288 100644
--- a/drivers/ide/slc90e66.c
+++ b/drivers/ide/slc90e66.c
@@ -20,7 +20,7 @@ static DEFINE_SPINLOCK(slc90e66_lock);
static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
int is_slave = drive->dn & 1;
int master_port = hwif->channel ? 0x42 : 0x40;
@@ -73,7 +73,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u8 maslave = hwif->channel ? 0x42 : 0x40;
int sitre = 0, a_speed = 7 << (drive->dn * 4);
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c
index 93e2cce4b296..84109f5a1632 100644
--- a/drivers/ide/tc86c001.c
+++ b/drivers/ide/tc86c001.c
@@ -15,7 +15,7 @@
static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00);
u16 mode, scr = inw(scr_port);
@@ -62,13 +62,12 @@ static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio)
*/
static int tc86c001_timer_expiry(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
ide_expiry_t *expiry = ide_get_hwifdata(hwif);
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
u8 dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
/* Restore a higher level driver's expiry handler first. */
- hwgroup->expiry = expiry;
+ hwif->expiry = expiry;
if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */
unsigned long sc_base = hwif->config_data;
@@ -110,11 +109,10 @@ static int tc86c001_timer_expiry(ide_drive_t *drive)
static void tc86c001_dma_start(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ ide_hwif_t *hwif = drive->hwif;
unsigned long sc_base = hwif->config_data;
unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04);
- unsigned long nsectors = hwgroup->rq->nr_sectors;
+ unsigned long nsectors = hwif->rq->nr_sectors;
/*
* We have to manually load the sector count and size into
@@ -125,8 +123,8 @@ static void tc86c001_dma_start(ide_drive_t *drive)
outw(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */
/* Install our timeout expiry hook, saving the current handler... */
- ide_set_hwifdata(hwif, hwgroup->expiry);
- hwgroup->expiry = &tc86c001_timer_expiry;
+ ide_set_hwifdata(hwif, hwif->expiry);
+ hwif->expiry = &tc86c001_timer_expiry;
ide_dma_start(drive);
}
@@ -190,6 +188,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
.dma_test_irq = ide_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq,
.dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = ide_dma_sff_read_status,
};
static const struct ide_port_info tc86c001_chipset __devinitdata = {
diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c
index b6ff40336aa9..8773c3ba7462 100644
--- a/drivers/ide/triflex.c
+++ b/drivers/ide/triflex.c
@@ -36,7 +36,7 @@
static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev);
u32 triflex_timings = 0;
u16 timing = 0;
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
index 2a5ea90cf8b8..b6a1285a4021 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -144,7 +144,7 @@
static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
{
- ide_hwif_t *hwif = HWIF(drive);
+ ide_hwif_t *hwif = drive->hwif;
u16 reg = 0;
unsigned long flags;
@@ -184,7 +184,7 @@ static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
static int trm290_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
unsigned int count, rw;
if (rq_data_dir(rq)) {
@@ -222,15 +222,15 @@ static int trm290_dma_end(ide_drive_t *drive)
drive->waiting_for_dma = 0;
/* purge DMA mappings */
ide_destroy_dmatable(drive);
- status = inw(HWIF(drive)->dma_base + 2);
+ status = inw(drive->hwif->dma_base + 2);
+
return status != 0x00ff;
}
static int trm290_dma_test_irq(ide_drive_t *drive)
{
- u16 status;
+ u16 status = inw(drive->hwif->dma_base + 2);
- status = inw(HWIF(drive)->dma_base + 2);
return status == 0x00ff;
}
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index 13b63e7fa353..d9095345f7ca 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -202,7 +202,6 @@ static const struct ide_tp_ops tx4938ide_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
@@ -216,16 +215,17 @@ static const struct ide_tp_ops tx4938ide_tp_ops = {
#endif /* __BIG_ENDIAN */
static const struct ide_port_ops tx4938ide_port_ops = {
- .set_pio_mode = tx4938ide_set_pio_mode,
+ .set_pio_mode = tx4938ide_set_pio_mode,
};
static const struct ide_port_info tx4938ide_port_info __initdata = {
- .port_ops = &tx4938ide_port_ops,
+ .port_ops = &tx4938ide_port_ops,
#ifdef __BIG_ENDIAN
- .tp_ops = &tx4938ide_tp_ops,
+ .tp_ops = &tx4938ide_tp_ops,
#endif
- .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
- .pio_mask = ATA_PIO5,
+ .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
+ .pio_mask = ATA_PIO5,
+ .chipset = ide_generic,
};
static int __init tx4938ide_probe(struct platform_device *pdev)
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index 97cd9e0f66f6..40b0812a045c 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -261,9 +261,9 @@ static int tx4939ide_build_dmatable(ide_drive_t *drive, struct request *rq)
bcount = cur_len;
/*
* This workaround for zero count seems required.
- * (standard ide_build_dmatable do it too)
+ * (standard ide_build_dmatable does it too)
*/
- if ((bcount & 0xffff) == 0x0000)
+ if (bcount == 0x10000)
bcount = 0x8000;
*table++ = bcount & 0xffff;
*table++ = cur_addr;
@@ -293,7 +293,7 @@ static int tx4939ide_dma_setup(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
void __iomem *base = TX4939IDE_BASE(hwif);
- struct request *rq = hwif->hwgroup->rq;
+ struct request *rq = hwif->rq;
u8 reading;
int nent;
@@ -397,6 +397,17 @@ static int tx4939ide_dma_test_irq(ide_drive_t *drive)
return found;
}
+#ifdef __BIG_ENDIAN
+static u8 tx4939ide_dma_sff_read_status(ide_hwif_t *hwif)
+{
+ void __iomem *base = TX4939IDE_BASE(hwif);
+
+ return tx4939ide_readb(base, TX4939IDE_DMA_Stat);
+}
+#else
+#define tx4939ide_dma_sff_read_status ide_dma_sff_read_status
+#endif
+
static void tx4939ide_init_hwif(ide_hwif_t *hwif)
{
void __iomem *base = TX4939IDE_BASE(hwif);
@@ -443,13 +454,6 @@ static void tx4939ide_tf_load_fixup(ide_drive_t *drive, ide_task_t *task)
#ifdef __BIG_ENDIAN
-static u8 tx4939ide_read_sff_dma_status(ide_hwif_t *hwif)
-{
- void __iomem *base = TX4939IDE_BASE(hwif);
-
- return tx4939ide_readb(base, TX4939IDE_DMA_Stat);
-}
-
/* custom iops (independent from SWAP_IO_SPACE) */
static u8 tx4939ide_inb(unsigned long port)
{
@@ -585,7 +589,6 @@ static const struct ide_tp_ops tx4939ide_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = tx4939ide_read_sff_dma_status,
.set_irq = ide_set_irq,
@@ -609,7 +612,6 @@ static const struct ide_tp_ops tx4939ide_tp_ops = {
.exec_command = ide_exec_command,
.read_status = ide_read_status,
.read_altstatus = ide_read_altstatus,
- .read_sff_dma_status = ide_read_sff_dma_status,
.set_irq = ide_set_irq,
@@ -623,33 +625,35 @@ static const struct ide_tp_ops tx4939ide_tp_ops = {
#endif /* __LITTLE_ENDIAN */
static const struct ide_port_ops tx4939ide_port_ops = {
- .set_pio_mode = tx4939ide_set_pio_mode,
- .set_dma_mode = tx4939ide_set_dma_mode,
- .clear_irq = tx4939ide_clear_irq,
- .cable_detect = tx4939ide_cable_detect,
+ .set_pio_mode = tx4939ide_set_pio_mode,
+ .set_dma_mode = tx4939ide_set_dma_mode,
+ .clear_irq = tx4939ide_clear_irq,
+ .cable_detect = tx4939ide_cable_detect,
};
static const struct ide_dma_ops tx4939ide_dma_ops = {
- .dma_host_set = tx4939ide_dma_host_set,
- .dma_setup = tx4939ide_dma_setup,
- .dma_exec_cmd = ide_dma_exec_cmd,
- .dma_start = ide_dma_start,
- .dma_end = tx4939ide_dma_end,
- .dma_test_irq = tx4939ide_dma_test_irq,
- .dma_lost_irq = ide_dma_lost_irq,
- .dma_timeout = ide_dma_timeout,
+ .dma_host_set = tx4939ide_dma_host_set,
+ .dma_setup = tx4939ide_dma_setup,
+ .dma_exec_cmd = ide_dma_exec_cmd,
+ .dma_start = ide_dma_start,
+ .dma_end = tx4939ide_dma_end,
+ .dma_test_irq = tx4939ide_dma_test_irq,
+ .dma_lost_irq = ide_dma_lost_irq,
+ .dma_timeout = ide_dma_timeout,
+ .dma_sff_read_status = tx4939ide_dma_sff_read_status,
};
static const struct ide_port_info tx4939ide_port_info __initdata = {
- .init_hwif = tx4939ide_init_hwif,
- .init_dma = tx4939ide_init_dma,
- .port_ops = &tx4939ide_port_ops,
- .dma_ops = &tx4939ide_dma_ops,
- .tp_ops = &tx4939ide_tp_ops,
- .host_flags = IDE_HFLAG_MMIO,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = ATA_MWDMA2,
- .udma_mask = ATA_UDMA5,
+ .init_hwif = tx4939ide_init_hwif,
+ .init_dma = tx4939ide_init_dma,
+ .port_ops = &tx4939ide_port_ops,
+ .dma_ops = &tx4939ide_dma_ops,
+ .tp_ops = &tx4939ide_tp_ops,
+ .host_flags = IDE_HFLAG_MMIO,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA5,
+ .chipset = ide_generic,
};
static int __init tx4939ide_probe(struct platform_device *pdev)
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
index e29978cf6197..0608d41fb6d0 100644
--- a/drivers/ide/umc8672.c
+++ b/drivers/ide/umc8672.c
@@ -106,22 +106,21 @@ static void umc_set_speeds(u8 speeds[])
static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
{
- ide_hwif_t *hwif = drive->hwif;
- ide_hwgroup_t *mate_hwgroup = hwif->mate ? hwif->mate->hwgroup : NULL;
+ ide_hwif_t *hwif = drive->hwif, *mate = hwif->mate;
unsigned long uninitialized_var(flags);
printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
drive->name, pio, pio_to_umc[pio]);
- if (mate_hwgroup)
- spin_lock_irqsave(&mate_hwgroup->lock, flags);
- if (mate_hwgroup && mate_hwgroup->handler) {
+ if (mate)
+ spin_lock_irqsave(&mate->lock, flags);
+ if (mate && mate->handler) {
printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
} else {
current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
umc_set_speeds(current_speeds);
}
- if (mate_hwgroup)
- spin_unlock_irqrestore(&mate_hwgroup->lock, flags);
+ if (mate)
+ spin_unlock_irqrestore(&mate->lock, flags);
}
static const struct ide_port_ops umc8672_port_ops = {
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index 2a812d3207e9..6092fe3f409d 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -178,7 +178,7 @@ static void via_set_drive(ide_drive_t *drive, const u8 speed)
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
- via_set_speed(HWIF(drive), drive->dn, &t);
+ via_set_speed(hwif, drive->dn, &t);
}
/**
@@ -432,8 +432,6 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
if (via_clock < 20000 || via_clock > 50000) {
printk(KERN_WARNING DRV_NAME ": User given PCI clock speed "
"impossible (%d), using 33 MHz instead.\n", via_clock);
- printk(KERN_WARNING DRV_NAME ": Use ide0=ata66 if you want "
- "to assume 80-wire cable.\n");
via_clock = 33333;
}
@@ -450,6 +448,11 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i
d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
#endif
+#ifdef CONFIG_AMIGAONE
+ if (machine_is(amigaone))
+ d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS;
+#endif
+
d.udma_mask = via_config->udma_mask;
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
index fb176f6ef9f8..17e8ddd01334 100644
--- a/drivers/idle/i7300_idle.c
+++ b/drivers/idle/i7300_idle.c
@@ -177,7 +177,7 @@ static int __init i7300_idle_ioat_selftest(u8 *ctl,
}
static struct device dummy_dma_dev = {
- .bus_id = "fallback device",
+ .init_name = "fallback device",
.coherent_dma_mask = DMA_64BIT_MASK,
.dma_mask = &dummy_dma_dev.coherent_dma_mask,
};
diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c
index c90be4070e40..31400c8ae051 100644
--- a/drivers/ieee1394/csr.c
+++ b/drivers/ieee1394/csr.c
@@ -68,22 +68,22 @@ static struct hpsb_highlevel csr_highlevel = {
.host_reset = host_reset,
};
-static struct hpsb_address_ops map_ops = {
+const static struct hpsb_address_ops map_ops = {
.read = read_maps,
};
-static struct hpsb_address_ops fcp_ops = {
+const static struct hpsb_address_ops fcp_ops = {
.write = write_fcp,
};
-static struct hpsb_address_ops reg_ops = {
+const static struct hpsb_address_ops reg_ops = {
.read = read_regs,
.write = write_regs,
.lock = lock_regs,
.lock64 = lock64_regs,
};
-static struct hpsb_address_ops config_rom_ops = {
+const static struct hpsb_address_ops config_rom_ops = {
.read = read_config_rom,
};
@@ -217,7 +217,7 @@ static void add_host(struct hpsb_host *host)
host->csr.generation = 2;
- bus_info[1] = __constant_cpu_to_be32(0x31333934);
+ bus_info[1] = IEEE1394_BUSID_MAGIC;
bus_info[2] = cpu_to_be32((hpsb_disable_irm ? 0 : 1 << CSR_IRMC_SHIFT) |
(1 << CSR_CMC_SHIFT) |
(1 << CSR_ISC_SHIFT) |
@@ -250,7 +250,7 @@ static void remove_host(struct hpsb_host *host)
{
quadlet_t bus_info[CSR_BUS_INFO_SIZE];
- bus_info[1] = __constant_cpu_to_be32(0x31333934);
+ bus_info[1] = IEEE1394_BUSID_MAGIC;
bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) |
(0 << CSR_CMC_SHIFT) |
(0 << CSR_ISC_SHIFT) |
diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h
index f11546550d84..90fb3f2192c3 100644
--- a/drivers/ieee1394/csr.h
+++ b/drivers/ieee1394/csr.h
@@ -50,11 +50,11 @@
#define CSR_MAX_ROM_SHIFT 8
#define CSR_GENERATION_SHIFT 4
-#define CSR_SET_BUS_INFO_GENERATION(csr, gen) \
- ((csr)->bus_info_data[2] = \
- cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) & \
- ~(0xf << CSR_GENERATION_SHIFT)) | \
- (gen) << CSR_GENERATION_SHIFT))
+static inline void csr_set_bus_info_generation(struct csr1212_csr *csr, u8 gen)
+{
+ csr->bus_info_data[2] &= ~cpu_to_be32(0xf << CSR_GENERATION_SHIFT);
+ csr->bus_info_data[2] |= cpu_to_be32((u32)gen << CSR_GENERATION_SHIFT);
+}
struct csr_control {
spinlock_t lock;
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 5e38a68b8af2..a6dfeb0b3372 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -1077,15 +1077,10 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
int i;
int ret;
- /* IEEE 1212 says that the entire bus info block should be readable in
- * a single transaction regardless of the max_rom value.
- * Unfortunately, many IEEE 1394 devices do not abide by that, so the
- * bus info block will be read 1 quadlet at a time. The rest of the
- * ConfigROM will be read according to the max_rom field. */
for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) {
ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
- sizeof(u32), &csr->cache_head->data[bytes_to_quads(i)],
- csr->private);
+ &csr->cache_head->data[bytes_to_quads(i)],
+ csr->private);
if (ret != CSR1212_SUCCESS)
return ret;
@@ -1104,8 +1099,8 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
* a time. */
for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) {
ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
- sizeof(u32), &csr->cache_head->data[bytes_to_quads(i)],
- csr->private);
+ &csr->cache_head->data[bytes_to_quads(i)],
+ csr->private);
if (ret != CSR1212_SUCCESS)
return ret;
}
@@ -1289,7 +1284,7 @@ csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
if (csr->ops->bus_read(csr,
CSR1212_REGISTER_SPACE_BASE + kv->offset,
- sizeof(u32), &q, csr->private))
+ &q, csr->private))
return -EIO;
kv->value.leaf.len = be32_to_cpu(q) >> 16;
@@ -1372,17 +1367,8 @@ csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
cr->offset_end) & ~(csr->max_rom - 1);
- if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
- csr->private)) {
- if (csr->max_rom == 4)
- /* We've got problems! */
- return -EIO;
-
- /* Apperently the max_rom value was a lie, set it to
- * do quadlet reads and try again. */
- csr->max_rom = 4;
- continue;
- }
+ if (csr->ops->bus_read(csr, addr, cache_ptr, csr->private))
+ return -EIO;
cr->offset_end += csr->max_rom - (cr->offset_end &
(csr->max_rom - 1));
@@ -1433,7 +1419,6 @@ csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
int csr1212_parse_csr(struct csr1212_csr *csr)
{
- static const int mr_map[] = { 4, 64, 1024, 0 };
struct csr1212_dentry *dentry;
int ret;
@@ -1443,15 +1428,13 @@ int csr1212_parse_csr(struct csr1212_csr *csr)
if (ret != CSR1212_SUCCESS)
return ret;
- if (!csr->ops->get_max_rom) {
- csr->max_rom = mr_map[0]; /* default value */
- } else {
- int i = csr->ops->get_max_rom(csr->bus_info_data,
- csr->private);
- if (i & ~0x3)
- return -EINVAL;
- csr->max_rom = mr_map[i];
- }
+ /*
+ * There has been a buggy firmware with bus_info_block.max_rom > 0
+ * spotted which actually only supported quadlet read requests to the
+ * config ROM. Therefore read everything quadlet by quadlet regardless
+ * of what the bus info block says.
+ */
+ csr->max_rom = 4;
csr->cache_head->layout_head = csr->root_kv;
csr->cache_head->layout_tail = csr->root_kv;
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
index 043039fc63ec..a892d922dbc9 100644
--- a/drivers/ieee1394/csr1212.h
+++ b/drivers/ieee1394/csr1212.h
@@ -181,7 +181,7 @@ struct csr1212_csr_rom_cache {
struct csr1212_csr {
size_t bus_info_len; /* bus info block length in bytes */
size_t crc_len; /* crc length in bytes */
- u32 *bus_info_data; /* bus info data incl bus name and EUI */
+ __be32 *bus_info_data; /* bus info data incl bus name and EUI */
void *private; /* private, bus specific data */
struct csr1212_bus_ops *ops;
@@ -200,7 +200,7 @@ struct csr1212_bus_ops {
* entries located in the Units Space. Must return 0 on success
* anything else indicates an error. */
int (*bus_read) (struct csr1212_csr *csr, u64 addr,
- u16 length, void *buffer, void *private);
+ void *buffer, void *private);
/* This function is used by csr1212 to allocate a region in units space
* in the event that Config ROM entries don't all fit in the predefined
@@ -211,11 +211,6 @@ struct csr1212_bus_ops {
/* This function is used by csr1212 to release a region in units space
* that is no longer needed. */
void (*release_addr) (u64 addr, void *private);
-
- /* This function is used by csr1212 to determine the max read request
- * supported by a remote node when reading the ConfigROM space. Must
- * return 0, 1, or 2 per IEEE 1212. */
- int (*get_max_rom) (u32 *bus_info, void *private);
};
diff --git a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h
index 7d1d2845b420..18b92cbf4a9f 100644
--- a/drivers/ieee1394/dv1394-private.h
+++ b/drivers/ieee1394/dv1394-private.h
@@ -77,11 +77,11 @@ static inline void fill_cip_header(struct CIP_header *cip,
See the Texas Instruments OHCI 1394 chipset documentation.
*/
-struct output_more_immediate { u32 q[8]; };
-struct output_more { u32 q[4]; };
-struct output_last { u32 q[4]; };
-struct input_more { u32 q[4]; };
-struct input_last { u32 q[4]; };
+struct output_more_immediate { __le32 q[8]; };
+struct output_more { __le32 q[4]; };
+struct output_last { __le32 q[4]; };
+struct input_more { __le32 q[4]; };
+struct input_last { __le32 q[4]; };
/* outputs */
@@ -92,9 +92,9 @@ static inline void fill_output_more_immediate(struct output_more_immediate *omi,
unsigned int payload_size)
{
omi->q[0] = cpu_to_le32(0x02000000 | 8); /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */
- omi->q[1] = 0;
- omi->q[2] = 0;
- omi->q[3] = 0;
+ omi->q[1] = cpu_to_le32(0);
+ omi->q[2] = cpu_to_le32(0);
+ omi->q[3] = cpu_to_le32(0);
/* IT packet header */
omi->q[4] = cpu_to_le32( (0x0 << 16) /* IEEE1394_SPEED_100 */
@@ -106,8 +106,8 @@ static inline void fill_output_more_immediate(struct output_more_immediate *omi,
/* reserved field; mimic behavior of my Sony DSR-40 */
omi->q[5] = cpu_to_le32((payload_size << 16) | (0x7F << 8) | 0xA0);
- omi->q[6] = 0;
- omi->q[7] = 0;
+ omi->q[6] = cpu_to_le32(0);
+ omi->q[7] = cpu_to_le32(0);
}
static inline void fill_output_more(struct output_more *om,
@@ -116,8 +116,8 @@ static inline void fill_output_more(struct output_more *om,
{
om->q[0] = cpu_to_le32(data_size);
om->q[1] = cpu_to_le32(data_phys_addr);
- om->q[2] = 0;
- om->q[3] = 0;
+ om->q[2] = cpu_to_le32(0);
+ om->q[3] = cpu_to_le32(0);
}
static inline void fill_output_last(struct output_last *ol,
@@ -140,8 +140,8 @@ static inline void fill_output_last(struct output_last *ol,
ol->q[0] = cpu_to_le32(temp);
ol->q[1] = cpu_to_le32(data_phys_addr);
- ol->q[2] = 0;
- ol->q[3] = 0;
+ ol->q[2] = cpu_to_le32(0);
+ ol->q[3] = cpu_to_le32(0);
}
/* inputs */
@@ -161,8 +161,8 @@ static inline void fill_input_more(struct input_more *im,
im->q[0] = cpu_to_le32(temp);
im->q[1] = cpu_to_le32(data_phys_addr);
- im->q[2] = 0; /* branchAddress and Z not use in packet-per-buffer mode */
- im->q[3] = 0; /* xferStatus & resCount, resCount must be initialize to data_size */
+ im->q[2] = cpu_to_le32(0); /* branchAddress and Z not use in packet-per-buffer mode */
+ im->q[3] = cpu_to_le32(0); /* xferStatus & resCount, resCount must be initialize to data_size */
}
static inline void fill_input_last(struct input_last *il,
@@ -331,7 +331,7 @@ struct frame {
/* points to status/timestamp field of first DMA packet */
/* (we'll check it later to monitor timestamp accuracy) */
- u32 *frame_begin_timestamp;
+ __le32 *frame_begin_timestamp;
/* the timestamp we assigned to the first packet in the frame */
u32 assigned_timestamp;
@@ -348,15 +348,15 @@ struct frame {
that can cause interrupts. We'll check these from the
interrupt handler.
*/
- u32 *mid_frame_timestamp;
- u32 *frame_end_timestamp;
+ __le32 *mid_frame_timestamp;
+ __le32 *frame_end_timestamp;
/* branch address field of final packet. This is effectively
the "tail" in the chain of DMA descriptor blocks.
We will fill it with the address of the first DMA descriptor
block in the subsequent frame, once it is ready.
*/
- u32 *frame_end_branch;
+ __le32 *frame_end_branch;
/* the number of descriptors in the first descriptor block
of the frame. Needed to start DMA */
@@ -365,10 +365,10 @@ struct frame {
struct packet {
- u16 timestamp;
+ __le16 timestamp;
u16 invalid;
u16 iso_header;
- u16 data_length;
+ __le16 data_length;
u32 cip_h1;
u32 cip_h2;
unsigned char data[480];
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index c19f23267157..a329e6bd5d2d 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -265,7 +265,7 @@ static void frame_prepare(struct video_card *video, unsigned int this_frame)
/* these flags denote packets that need special attention */
int empty_packet, first_packet, last_packet, mid_packet;
- u32 *branch_address, *last_branch_address = NULL;
+ __le32 *branch_address, *last_branch_address = NULL;
unsigned long data_p;
int first_packet_empty = 0;
u32 cycleTimer, ct_sec, ct_cyc, ct_off;
@@ -848,7 +848,7 @@ static void receive_packets(struct video_card *video)
dma_addr_t block_dma = 0;
struct packet *data = NULL;
dma_addr_t data_dma = 0;
- u32 *last_branch_address = NULL;
+ __le32 *last_branch_address = NULL;
unsigned long irq_flags;
int want_interrupt = 0;
struct frame *f = NULL;
@@ -2110,17 +2110,17 @@ static void ir_tasklet_func(unsigned long data)
f = video->frames[next_i / MAX_PACKETS];
next = &(f->descriptor_pool[next_i % MAX_PACKETS]);
next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;
- next->u.in.il.q[0] |= 3 << 20; /* enable interrupt */
- next->u.in.il.q[2] = 0; /* disable branch */
+ next->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */
+ next->u.in.il.q[2] = cpu_to_le32(0); /* disable branch */
/* link previous to next */
prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1);
f = video->frames[prev_i / MAX_PACKETS];
prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]);
if (prev_i % (MAX_PACKETS/2)) {
- prev->u.in.il.q[0] &= ~(3 << 20); /* no interrupt */
+ prev->u.in.il.q[0] &= ~cpu_to_le32(3 << 20); /* no interrupt */
} else {
- prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */
+ prev->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */
}
prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */
wmb();
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 20128692b339..1a919df809f8 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -92,7 +92,7 @@ struct partial_datagram {
struct list_head list;
u16 dgl;
u16 dg_size;
- u16 ether_type;
+ __be16 ether_type;
struct sk_buff *skb;
char *pbuf;
struct list_head frag_info;
@@ -181,7 +181,7 @@ static void ether1394_remove_host(struct hpsb_host *host);
static void ether1394_host_reset(struct hpsb_host *host);
/* Function for incoming 1394 packets */
-static struct hpsb_address_ops addr_ops = {
+const static struct hpsb_address_ops addr_ops = {
.write = ether1394_write,
};
@@ -245,12 +245,6 @@ static int ether1394_stop(struct net_device *dev)
return 0;
}
-/* Return statistics to the caller */
-static struct net_device_stats *ether1394_stats(struct net_device *dev)
-{
- return &(((struct eth1394_priv *)netdev_priv(dev))->stats);
-}
-
/* FIXME: What to do if we timeout? I think a host reset is probably in order,
* so that's what we do. Should we increment the stat counters too? */
static void ether1394_tx_timeout(struct net_device *dev)
@@ -516,16 +510,19 @@ static const struct header_ops ether1394_header_ops = {
.parse = ether1394_header_parse,
};
+static const struct net_device_ops ether1394_netdev_ops = {
+ .ndo_open = ether1394_open,
+ .ndo_stop = ether1394_stop,
+ .ndo_start_xmit = ether1394_tx,
+ .ndo_tx_timeout = ether1394_tx_timeout,
+ .ndo_change_mtu = ether1394_change_mtu,
+};
+
static void ether1394_init_dev(struct net_device *dev)
{
- dev->open = ether1394_open;
- dev->stop = ether1394_stop;
- dev->hard_start_xmit = ether1394_tx;
- dev->get_stats = ether1394_stats;
- dev->tx_timeout = ether1394_tx_timeout;
- dev->change_mtu = ether1394_change_mtu;
dev->header_ops = &ether1394_header_ops;
+ dev->netdev_ops = &ether1394_netdev_ops;
SET_ETHTOOL_OPS(dev, &ethtool_ops);
@@ -767,7 +764,7 @@ static int ether1394_header_parse(const struct sk_buff *skb,
static int ether1394_header_cache(const struct neighbour *neigh,
struct hh_cache *hh)
{
- unsigned short type = hh->hh_type;
+ __be16 type = hh->hh_type;
struct net_device *dev = neigh->dev;
struct eth1394hdr *eth =
(struct eth1394hdr *)((u8 *)hh->hh_data + 16 - ETH1394_HLEN);
@@ -795,7 +792,7 @@ static void ether1394_header_cache_update(struct hh_cache *hh,
******************************************/
/* Copied from net/ethernet/eth.c */
-static u16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
+static __be16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct eth1394hdr *eth;
unsigned char *rawp;
@@ -829,17 +826,17 @@ static u16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
/* Parse an encapsulated IP1394 header into an ethernet frame packet.
* We also perform ARP translation here, if need be. */
-static u16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev,
+static __be16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev,
nodeid_t srcid, nodeid_t destid,
- u16 ether_type)
+ __be16 ether_type)
{
struct eth1394_priv *priv = netdev_priv(dev);
- u64 dest_hw;
- unsigned short ret = 0;
+ __be64 dest_hw;
+ __be16 ret = 0;
/* Setup our hw addresses. We use these to build the ethernet header. */
if (destid == (LOCAL_BUS | ALL_NODES))
- dest_hw = ~0ULL; /* broadcast */
+ dest_hw = ~cpu_to_be64(0); /* broadcast */
else
dest_hw = cpu_to_be64((u64)priv->host->csr.guid_hi << 32 |
priv->host->csr.guid_lo);
@@ -873,7 +870,7 @@ static u16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev,
node = eth1394_find_node_guid(&priv->ip_node_list,
be64_to_cpu(guid));
if (!node)
- return 0;
+ return cpu_to_be16(0);
node_info =
(struct eth1394_node_info *)node->ud->device.driver_data;
@@ -1063,7 +1060,7 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
unsigned long flags;
struct eth1394_priv *priv = netdev_priv(dev);
union eth1394_hdr *hdr = (union eth1394_hdr *)buf;
- u16 ether_type = 0; /* initialized to clear warning */
+ __be16 ether_type = cpu_to_be16(0); /* initialized to clear warning */
int hdr_len;
struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)];
struct eth1394_node_info *node_info;
@@ -1075,7 +1072,7 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
HPSB_PRINT(KERN_ERR, "ether1394 rx: sender nodeid "
"lookup failure: " NODE_BUS_FMT,
NODE_BUS_ARGS(priv->host, srcid));
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
return -1;
}
ud = node->ud;
@@ -1098,7 +1095,7 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
skb = dev_alloc_skb(len + dev->hard_header_len + 15);
if (unlikely(!skb)) {
ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
return -1;
}
skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
@@ -1217,15 +1214,15 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
spin_lock_irqsave(&priv->lock, flags);
if (!skb->protocol) {
- priv->stats.rx_errors++;
- priv->stats.rx_dropped++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else if (netif_rx(skb) == NET_RX_DROP) {
- priv->stats.rx_errors++;
- priv->stats.rx_dropped++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
} else {
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += skb->len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1234,8 +1231,6 @@ bad_proto:
if (netif_queue_stopped(dev))
netif_wake_queue(dev);
- dev->last_rx = jiffies;
-
return 0;
}
@@ -1259,7 +1254,7 @@ static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
static void ether1394_iso(struct hpsb_iso *iso)
{
- quadlet_t *data;
+ __be32 *data;
char *buf;
struct eth1394_host_info *hi;
struct net_device *dev;
@@ -1283,7 +1278,7 @@ static void ether1394_iso(struct hpsb_iso *iso)
for (i = 0; i < nready; i++) {
struct hpsb_iso_packet_info *info =
&iso->infos[(iso->first_packet + i) % iso->buf_packets];
- data = (quadlet_t *)(iso->data_buf.kvirt + info->offset);
+ data = (__be32 *)(iso->data_buf.kvirt + info->offset);
/* skip over GASP header */
buf = (char *)data + 8;
@@ -1509,17 +1504,18 @@ static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len)
static void ether1394_dg_complete(struct packet_task *ptask, int fail)
{
struct sk_buff *skb = ptask->skb;
- struct eth1394_priv *priv = netdev_priv(skb->dev);
+ struct net_device *dev = skb->dev;
+ struct eth1394_priv *priv = netdev_priv(dev);
unsigned long flags;
/* Statistics */
spin_lock_irqsave(&priv->lock, flags);
if (fail) {
- priv->stats.tx_dropped++;
- priv->stats.tx_errors++;
+ dev->stats.tx_dropped++;
+ dev->stats.tx_errors++;
} else {
- priv->stats.tx_bytes += skb->len;
- priv->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ dev->stats.tx_packets++;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1614,7 +1610,7 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
priv->bc_dgl++;
} else {
- __be64 guid = get_unaligned((u64 *)hdr_buf.h_dest);
+ __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest);
node = eth1394_find_node_guid(&priv->ip_node_list,
be64_to_cpu(guid));
@@ -1696,8 +1692,8 @@ fail:
dev_kfree_skb(skb);
spin_lock_irqsave(&priv->lock, flags);
- priv->stats.tx_dropped++;
- priv->stats.tx_errors++;
+ dev->stats.tx_dropped++;
+ dev->stats.tx_errors++;
spin_unlock_irqrestore(&priv->lock, flags);
/*
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
index 4f3e2dd46f00..d53bac47b86f 100644
--- a/drivers/ieee1394/eth1394.h
+++ b/drivers/ieee1394/eth1394.h
@@ -54,7 +54,6 @@ enum eth1394_bc_states { ETHER1394_BC_ERROR,
/* Private structure for our ethernet driver */
struct eth1394_priv {
- struct net_device_stats stats; /* Device stats */
struct hpsb_host *host; /* The card for this dev */
u16 bc_maxpayload; /* Max broadcast payload */
u8 bc_sspd; /* Max broadcast speed */
@@ -82,7 +81,7 @@ struct eth1394_priv {
struct eth1394hdr {
unsigned char h_dest[ETH1394_ALEN]; /* destination eth1394 addr */
- unsigned short h_proto; /* packet type ID field */
+ __be16 h_proto; /* packet type ID field */
} __attribute__((packed));
static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
@@ -99,13 +98,13 @@ typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
struct eth1394_uf_hdr {
u16 lf:2;
u16 res:14;
- u16 ether_type; /* Ethernet packet type */
+ __be16 ether_type; /* Ethernet packet type */
} __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD
struct eth1394_uf_hdr {
u16 res:14;
u16 lf:2;
- u16 ether_type;
+ __be16 ether_type;
} __attribute__((packed));
#else
#error Unknown bit field type
@@ -117,7 +116,7 @@ struct eth1394_ff_hdr {
u16 lf:2;
u16 res1:2;
u16 dg_size:12; /* Datagram size */
- u16 ether_type; /* Ethernet packet type */
+ __be16 ether_type; /* Ethernet packet type */
u16 dgl; /* Datagram label */
u16 res2;
} __attribute__((packed));
@@ -126,7 +125,7 @@ struct eth1394_ff_hdr {
u16 dg_size:12;
u16 res1:2;
u16 lf:2;
- u16 ether_type;
+ __be16 ether_type;
u16 dgl;
u16 res2;
} __attribute__((packed));
@@ -207,11 +206,11 @@ struct eth1394_arp {
u16 opcode; /* ARP Opcode */
/* Above is exactly the same format as struct arphdr */
- u64 s_uniq_id; /* Sender's 64bit EUI */
+ __be64 s_uniq_id; /* Sender's 64bit EUI */
u8 max_rec; /* Sender's max packet size */
u8 sspd; /* Sender's max speed */
- u16 fifo_hi; /* hi 16bits of sender's FIFO addr */
- u32 fifo_lo; /* lo 32bits of sender's FIFO addr */
+ __be16 fifo_hi; /* hi 16bits of sender's FIFO addr */
+ __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
u32 sip; /* Sender's IP Address */
u32 tip; /* IP Address of requested hw addr */
};
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 272543a42a43..600e391c8fe7 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -320,7 +320,7 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
*/
u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host,
- struct hpsb_address_ops *ops,
+ const struct hpsb_address_ops *ops,
u64 size, u64 alignment,
u64 start, u64 end)
{
@@ -407,7 +407,8 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
* are automatically deallocated together with the hpsb_highlevel @hl.
*/
int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
- struct hpsb_address_ops *ops, u64 start, u64 end)
+ const struct hpsb_address_ops *ops,
+ u64 start, u64 end)
{
struct hpsb_address_serve *as;
struct list_head *lh;
@@ -420,7 +421,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return 0;
}
- as = kmalloc(sizeof(*as), GFP_ATOMIC);
+ as = kmalloc(sizeof(*as), GFP_KERNEL);
if (!as)
return 0;
@@ -477,7 +478,7 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval;
}
-static struct hpsb_address_ops dummy_ops;
+const static struct hpsb_address_ops dummy_ops;
/* dummy address spaces as lower and upper bounds of the host's a.s. list */
static void init_hpsb_highlevel(struct hpsb_host *host)
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
index bc5d0854c17e..9dba89fc60ad 100644
--- a/drivers/ieee1394/highlevel.h
+++ b/drivers/ieee1394/highlevel.h
@@ -15,7 +15,7 @@ struct hpsb_host;
struct hpsb_address_serve {
struct list_head host_list; /* per host list */
struct list_head hl_list; /* hpsb_highlevel list */
- struct hpsb_address_ops *op;
+ const struct hpsb_address_ops *op;
struct hpsb_host *host;
u64 start; /* first address handled, quadlet aligned */
u64 end; /* first address behind, quadlet aligned */
@@ -119,11 +119,12 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host,
- struct hpsb_address_ops *ops,
+ const struct hpsb_address_ops *ops,
u64 size, u64 alignment,
u64 start, u64 end);
int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
- struct hpsb_address_ops *ops, u64 start, u64 end);
+ const struct hpsb_address_ops *ops,
+ u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start);
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index 237d0c9d69c6..e947d8ffac85 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -34,18 +34,18 @@ static void delayed_reset_bus(struct work_struct *work)
{
struct hpsb_host *host =
container_of(work, struct hpsb_host, delayed_reset.work);
- int generation = host->csr.generation + 1;
+ u8 generation = host->csr.generation + 1;
/* The generation field rolls over to 2 rather than 0 per IEEE
* 1394a-2000. */
if (generation > 0xf || generation < 2)
generation = 2;
- CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation);
+ csr_set_bus_info_generation(host->csr.rom, generation);
if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
/* CSR image creation failed.
* Reset generation field and do not issue a bus reset. */
- CSR_SET_BUS_INFO_GENERATION(host->csr.rom,
+ csr_set_bus_info_generation(host->csr.rom,
host->csr.generation);
return;
}
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index dd229950acca..49c359022c54 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -154,7 +154,7 @@ struct hpsb_host_driver {
* to set the hardware ConfigROM if the hardware supports handling
* reads to the ConfigROM on its own. */
void (*set_hw_config_rom)(struct hpsb_host *host,
- quadlet_t *config_rom);
+ __be32 *config_rom);
/* This function shall implement packet transmission based on
* packet->type. It shall CRC both parts of the packet (unless
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
index 40492074c013..af320e2c5079 100644
--- a/drivers/ieee1394/ieee1394.h
+++ b/drivers/ieee1394/ieee1394.h
@@ -54,9 +54,7 @@
#define IEEE1394_SPEED_800 0x03
#define IEEE1394_SPEED_1600 0x04
#define IEEE1394_SPEED_3200 0x05
-
-/* The current highest tested speed supported by the subsystem */
-#define IEEE1394_SPEED_MAX IEEE1394_SPEED_800
+#define IEEE1394_SPEED_MAX IEEE1394_SPEED_3200
/* Maps speed values above to a string representation */
extern const char *hpsb_speedto_str[];
@@ -121,6 +119,9 @@ extern const char *hpsb_speedto_str[];
#include <asm/byteorder.h>
+/* '1' '3' '9' '4' in ASCII */
+#define IEEE1394_BUSID_MAGIC cpu_to_be32(0x31333934)
+
#ifdef __BIG_ENDIAN_BITFIELD
struct selfid {
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index dcdb71a7718d..2beb8d94f7bd 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -338,6 +338,7 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
u8 cldcnt[nodecount];
u8 *map = host->speed_map;
u8 *speedcap = host->speed;
+ u8 local_link_speed = host->csr.lnk_spd;
struct selfid *sid;
struct ext_selfid *esid;
int i, j, n;
@@ -373,8 +374,8 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
speedcap[n] = sid->speed;
- if (speedcap[n] > host->csr.lnk_spd)
- speedcap[n] = host->csr.lnk_spd;
+ if (speedcap[n] > local_link_speed)
+ speedcap[n] = local_link_speed;
n--;
}
}
@@ -407,12 +408,11 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
}
}
-#if SELFID_SPEED_UNKNOWN != IEEE1394_SPEED_MAX
- /* assume maximum speed for 1394b PHYs, nodemgr will correct it */
- for (n = 0; n < nodecount; n++)
- if (speedcap[n] == SELFID_SPEED_UNKNOWN)
- speedcap[n] = IEEE1394_SPEED_MAX;
-#endif
+ /* assume a maximum speed for 1394b PHYs, nodemgr will correct it */
+ if (local_link_speed > SELFID_SPEED_UNKNOWN)
+ for (i = 0; i < nodecount; i++)
+ if (speedcap[i] == SELFID_SPEED_UNKNOWN)
+ speedcap[i] = local_link_speed;
}
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 79ef5fd928ae..906c5a98d814 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -67,7 +67,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
*speed = i;
error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
- &q, sizeof(quadlet_t));
+ &q, 4);
if (error)
break;
*buffer = q;
@@ -85,7 +85,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
return error;
}
-static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
+static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr,
void *buffer, void *__ci)
{
struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
@@ -93,7 +93,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
for (i = 1; ; i++) {
error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
- buffer, length);
+ buffer, 4);
if (!error) {
ci->speed_unverified = 0;
break;
@@ -104,7 +104,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
/* The ieee1394_core guessed the node's speed capability from
* the self ID. Check whether a lower speed works. */
- if (ci->speed_unverified && length == sizeof(quadlet_t)) {
+ if (ci->speed_unverified) {
error = nodemgr_check_speed(ci, addr, buffer);
if (!error)
break;
@@ -115,20 +115,8 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
return error;
}
-#define OUI_FREECOM_TECHNOLOGIES_GMBH 0x0001db
-
-static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
-{
- /* Freecom FireWire Hard Drive firmware bug */
- if (be32_to_cpu(bus_info_data[3]) >> 8 == OUI_FREECOM_TECHNOLOGIES_GMBH)
- return 0;
-
- return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3;
-}
-
static struct csr1212_bus_ops nodemgr_csr_ops = {
.bus_read = nodemgr_bus_read,
- .get_max_rom = nodemgr_get_max_rom
};
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index 4f287a3561ba..15ea09733e84 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -31,9 +31,6 @@ struct csr1212_keyval;
struct hpsb_host;
struct ieee1394_device_id;
-/* '1' '3' '9' '4' in ASCII */
-#define IEEE1394_BUSID_MAGIC __constant_cpu_to_be32(0x31333934)
-
/* This is the start of a Node entry structure. It should be a stable API
* for which to gather info from the Node Manager about devices attached
* to the bus. */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index e509e13cb7a7..65c1429e4129 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -2973,7 +2973,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
return 0;
}
-static void ohci_set_hw_config_rom(struct hpsb_host *host, quadlet_t *config_rom)
+static void ohci_set_hw_config_rom(struct hpsb_host *host, __be32 *config_rom)
{
struct ti_ohci *ohci = host->hostdata;
@@ -3199,15 +3199,16 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
/* Now enable LPS, which we need in order to start accessing
* most of the registers. In fact, on some cards (ALI M5251),
* accessing registers in the SClk domain without LPS enabled
- * will lock up the machine. Wait 50msec to make sure we have
- * full link enabled. */
+ * will lock up the machine. */
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
/* Disable and clear interrupts */
reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
- mdelay(50);
+ /* Flush MMIO writes and wait to make sure we have full link enabled. */
+ reg_read(ohci, OHCI1394_Version);
+ msleep(50);
/* Determine the number of available IR and IT contexts. */
ohci->nb_iso_rcv_ctx =
@@ -3233,8 +3234,9 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
* we need to get to that "no event", so enough should be initialized
* by that point.
*/
- if (request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
- OHCI1394_DRIVER_NAME, ohci)) {
+ err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
+ OHCI1394_DRIVER_NAME, ohci);
+ if (err) {
PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
goto err;
}
@@ -3381,6 +3383,7 @@ static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state)
ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
ohci_soft_reset(ohci);
+ free_irq(dev->irq, ohci);
err = pci_save_state(dev);
if (err) {
PRINT(KERN_ERR, "pci_save_state failed with %d", err);
@@ -3420,7 +3423,16 @@ static int ohci1394_pci_resume(struct pci_dev *dev)
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
- mdelay(50);
+ reg_read(ohci, OHCI1394_Version);
+ msleep(50);
+
+ err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
+ OHCI1394_DRIVER_NAME, ohci);
+ if (err) {
+ PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
+ return err;
+ }
+
ohci_initialize(ohci);
hpsb_resume_host(ohci->host);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index 4320bf010495..7fb8ab9780ae 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -26,7 +26,7 @@
#define OHCI1394_DRIVER_NAME "ohci1394"
-#define OHCI1394_MAX_AT_REQ_RETRIES 0x2
+#define OHCI1394_MAX_AT_REQ_RETRIES 0xf
#define OHCI1394_MAX_AT_RESP_RETRIES 0x2
#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
#define OHCI1394_MAX_SELF_ID_ERRORS 16
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 7aee1ac97c80..38f712036201 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1419,7 +1419,6 @@ static int __devinit add_card(struct pci_dev *dev,
i2c_ad = kzalloc(sizeof(*i2c_ad), GFP_KERNEL);
if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
- i2c_ad->id = I2C_HW_B_PCILYNX;
strlcpy(i2c_ad->name, "PCILynx I2C", sizeof(i2c_ad->name));
i2c_adapter_data = bit_data;
i2c_ad->algo_data = &i2c_adapter_data;
@@ -1463,7 +1462,7 @@ static int __devinit add_card(struct pci_dev *dev,
/* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */
if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) &&
- (lynx->bus_info_block[1] == __constant_cpu_to_be32(0x31333934)))
+ (lynx->bus_info_block[1] == IEEE1394_BUSID_MAGIC))
{
PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");
} else {
diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h
index ec27321f6724..693a169acea3 100644
--- a/drivers/ieee1394/pcilynx.h
+++ b/drivers/ieee1394/pcilynx.h
@@ -52,7 +52,7 @@ struct ti_lynx {
void __iomem *local_rom;
void __iomem *local_ram;
void __iomem *aux_port;
- quadlet_t bus_info_block[5];
+ __be32 bus_info_block[5];
/*
* use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index bf7e761c12b1..bad66c65b0d6 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -90,7 +90,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
-static struct hpsb_address_ops arm_ops = {
+const static struct hpsb_address_ops arm_ops = {
.read = arm_read,
.write = arm_write,
.lock = arm_lock,
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index a373c18cf7b8..f3fd8657ce4b 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -115,8 +115,8 @@
*/
static int sbp2_max_speed = IEEE1394_SPEED_MAX;
module_param_named(max_speed, sbp2_max_speed, int, 0644);
-MODULE_PARM_DESC(max_speed, "Force max speed "
- "(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
+MODULE_PARM_DESC(max_speed, "Limit data transfer speed (5 <= 3200, "
+ "4 <= 1600, 3 <= 800, 2 <= 400, 1 <= 200, 0 = 100 Mb/s)");
/*
* Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
@@ -256,7 +256,7 @@ static int sbp2_set_busy_timeout(struct sbp2_lu *);
static int sbp2_max_speed_and_size(struct sbp2_lu *);
-static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
+static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xa, 0xa, 0xa };
static DEFINE_RWLOCK(sbp2_hi_logical_units_lock);
@@ -265,7 +265,7 @@ static struct hpsb_highlevel sbp2_highlevel = {
.host_reset = sbp2_host_reset,
};
-static struct hpsb_address_ops sbp2_ops = {
+const static struct hpsb_address_ops sbp2_ops = {
.write = sbp2_handle_status_write
};
@@ -275,7 +275,7 @@ static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *,
static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64,
size_t, u16);
-static struct hpsb_address_ops sbp2_physdma_ops = {
+const static struct hpsb_address_ops sbp2_physdma_ops = {
.read = sbp2_handle_physdma_read,
.write = sbp2_handle_physdma_write,
};
@@ -347,8 +347,8 @@ static struct scsi_host_template sbp2_shost_template = {
.sdev_attrs = sbp2_sysfs_sdev_attrs,
};
-/* for match-all entries in sbp2_workarounds_table */
-#define SBP2_ROM_VALUE_WILDCARD 0x1000000
+#define SBP2_ROM_VALUE_WILDCARD ~0 /* match all */
+#define SBP2_ROM_VALUE_MISSING 0xff000000 /* not present in the unit dir. */
/*
* List of devices with known bugs.
@@ -359,60 +359,70 @@ static struct scsi_host_template sbp2_shost_template = {
*/
static const struct {
u32 firmware_revision;
- u32 model_id;
+ u32 model;
unsigned workarounds;
} sbp2_workarounds_table[] = {
/* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
.firmware_revision = 0x002800,
- .model_id = 0x001010,
+ .model = 0x001010,
.workarounds = SBP2_WORKAROUND_INQUIRY_36 |
SBP2_WORKAROUND_MODE_SENSE_8 |
SBP2_WORKAROUND_POWER_CONDITION,
},
/* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
.firmware_revision = 0x002800,
- .model_id = 0x000000,
+ .model = 0x000000,
.workarounds = SBP2_WORKAROUND_DELAY_INQUIRY |
SBP2_WORKAROUND_POWER_CONDITION,
},
/* Initio bridges, actually only needed for some older ones */ {
.firmware_revision = 0x000200,
- .model_id = SBP2_ROM_VALUE_WILDCARD,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_INQUIRY_36,
},
/* PL-3507 bridge with Prolific firmware */ {
.firmware_revision = 0x012800,
- .model_id = SBP2_ROM_VALUE_WILDCARD,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_POWER_CONDITION,
},
/* Symbios bridge */ {
.firmware_revision = 0xa0b800,
- .model_id = SBP2_ROM_VALUE_WILDCARD,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_128K_MAX_TRANS,
},
/* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ {
.firmware_revision = 0x002600,
- .model_id = SBP2_ROM_VALUE_WILDCARD,
+ .model = SBP2_ROM_VALUE_WILDCARD,
.workarounds = SBP2_WORKAROUND_128K_MAX_TRANS,
},
+ /*
+ * iPod 2nd generation: needs 128k max transfer size workaround
+ * iPod 3rd generation: needs fix capacity workaround
+ */
+ {
+ .firmware_revision = 0x0a2700,
+ .model = 0x000000,
+ .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS |
+ SBP2_WORKAROUND_FIX_CAPACITY,
+ },
/* iPod 4th generation */ {
.firmware_revision = 0x0a2700,
- .model_id = 0x000021,
+ .model = 0x000021,
.workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
},
/* iPod mini */ {
.firmware_revision = 0x0a2700,
- .model_id = 0x000022,
+ .model = 0x000022,
.workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
},
/* iPod mini */ {
.firmware_revision = 0x0a2700,
- .model_id = 0x000023,
+ .model = 0x000023,
.workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
},
/* iPod Photo */ {
.firmware_revision = 0x0a2700,
- .model_id = 0x00007e,
+ .model = 0x00007e,
.workarounds = SBP2_WORKAROUND_FIX_CAPACITY,
}
};
@@ -1341,13 +1351,15 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu,
struct csr1212_keyval *kv;
struct csr1212_dentry *dentry;
u64 management_agent_addr;
- u32 unit_characteristics, firmware_revision;
+ u32 unit_characteristics, firmware_revision, model;
unsigned workarounds;
int i;
management_agent_addr = 0;
unit_characteristics = 0;
- firmware_revision = 0;
+ firmware_revision = SBP2_ROM_VALUE_MISSING;
+ model = ud->flags & UNIT_DIRECTORY_MODEL_ID ?
+ ud->model_id : SBP2_ROM_VALUE_MISSING;
csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) {
switch (kv->key.id) {
@@ -1388,9 +1400,9 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu,
sbp2_workarounds_table[i].firmware_revision !=
(firmware_revision & 0xffff00))
continue;
- if (sbp2_workarounds_table[i].model_id !=
+ if (sbp2_workarounds_table[i].model !=
SBP2_ROM_VALUE_WILDCARD &&
- sbp2_workarounds_table[i].model_id != ud->model_id)
+ sbp2_workarounds_table[i].model != model)
continue;
workarounds |= sbp2_workarounds_table[i].workarounds;
break;
@@ -1403,7 +1415,7 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu,
NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
workarounds, firmware_revision,
ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id,
- ud->model_id);
+ model);
/* We would need one SCSI host template for each target to adjust
* max_sectors on the fly, therefore warn only. */
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 4f4d1bb9f069..b43f7d3682d3 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -778,7 +778,7 @@ int ib_device_register_sysfs(struct ib_device *device)
class_dev->class = &ib_class;
class_dev->driver_data = device;
class_dev->parent = device->dma_device;
- strlcpy(class_dev->bus_id, device->name, BUS_ID_SIZE);
+ dev_set_name(class_dev, device->name);
INIT_LIST_HEAD(&device->port_list);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index e603736682bf..51bd9669cb1f 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1266,8 +1266,7 @@ static void ib_ucm_add_one(struct ib_device *device)
ucm_dev->dev.parent = device->dma_device;
ucm_dev->dev.devt = ucm_dev->cdev.dev;
ucm_dev->dev.release = ib_ucm_release_dev;
- snprintf(ucm_dev->dev.bus_id, BUS_ID_SIZE, "ucm%d",
- ucm_dev->devnum);
+ dev_set_name(&ucm_dev->dev, "ucm%d", ucm_dev->devnum);
if (device_register(&ucm_dev->dev))
goto err_cdev;
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 2f4c28a30271..97e4b231cdc4 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -196,7 +196,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if (h_ret != H_SUCCESS) {
ehca_err(device, "hipz_h_alloc_resource_cq() failed "
- "h_ret=%li device=%p", h_ret, device);
+ "h_ret=%lli device=%p", h_ret, device);
cq = ERR_PTR(ehca2ib_return_code(h_ret));
goto create_cq_exit2;
}
@@ -232,7 +232,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if (h_ret < H_SUCCESS) {
ehca_err(device, "hipz_h_register_rpage_cq() failed "
- "ehca_cq=%p cq_num=%x h_ret=%li counter=%i "
+ "ehca_cq=%p cq_num=%x h_ret=%lli counter=%i "
"act_pages=%i", my_cq, my_cq->cq_number,
h_ret, counter, param.act_pages);
cq = ERR_PTR(-EINVAL);
@@ -244,7 +244,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if ((h_ret != H_SUCCESS) || vpage) {
ehca_err(device, "Registration of pages not "
"complete ehca_cq=%p cq_num=%x "
- "h_ret=%li", my_cq, my_cq->cq_number,
+ "h_ret=%lli", my_cq, my_cq->cq_number,
h_ret);
cq = ERR_PTR(-EAGAIN);
goto create_cq_exit4;
@@ -252,7 +252,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
} else {
if (h_ret != H_PAGE_REGISTERED) {
ehca_err(device, "Registration of page failed "
- "ehca_cq=%p cq_num=%x h_ret=%li "
+ "ehca_cq=%p cq_num=%x h_ret=%lli "
"counter=%i act_pages=%i",
my_cq, my_cq->cq_number,
h_ret, counter, param.act_pages);
@@ -266,7 +266,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
gal = my_cq->galpas.kernel;
cqx_fec = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_fec));
- ehca_dbg(device, "ehca_cq=%p cq_num=%x CQX_FEC=%lx",
+ ehca_dbg(device, "ehca_cq=%p cq_num=%x CQX_FEC=%llx",
my_cq, my_cq->cq_number, cqx_fec);
my_cq->ib_cq.cqe = my_cq->nr_of_entries =
@@ -307,7 +307,7 @@ create_cq_exit3:
h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1);
if (h_ret != H_SUCCESS)
ehca_err(device, "hipz_h_destroy_cq() failed ehca_cq=%p "
- "cq_num=%x h_ret=%li", my_cq, my_cq->cq_number, h_ret);
+ "cq_num=%x h_ret=%lli", my_cq, my_cq->cq_number, h_ret);
create_cq_exit2:
write_lock_irqsave(&ehca_cq_idr_lock, flags);
@@ -355,7 +355,7 @@ int ehca_destroy_cq(struct ib_cq *cq)
h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
if (h_ret == H_R_STATE) {
/* cq in err: read err data and destroy it forcibly */
- ehca_dbg(device, "ehca_cq=%p cq_num=%x ressource=%lx in err "
+ ehca_dbg(device, "ehca_cq=%p cq_num=%x resource=%llx in err "
"state. Try to delete it forcibly.",
my_cq, cq_num, my_cq->ipz_cq_handle.handle);
ehca_error_data(shca, my_cq, my_cq->ipz_cq_handle.handle);
@@ -365,7 +365,7 @@ int ehca_destroy_cq(struct ib_cq *cq)
cq_num);
}
if (h_ret != H_SUCCESS) {
- ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%li "
+ ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%lli "
"ehca_cq=%p cq_num=%x", h_ret, my_cq, cq_num);
return ehca2ib_return_code(h_ret);
}
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index 46288220cfbb..9209c5332dfe 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -393,7 +393,7 @@ int ehca_modify_port(struct ib_device *ibdev,
hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
cap, props->init_type, port_modify_mask);
if (hret != H_SUCCESS) {
- ehca_err(&shca->ib_device, "Modify port failed h_ret=%li",
+ ehca_err(&shca->ib_device, "Modify port failed h_ret=%lli",
hret);
ret = -EINVAL;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 757035ea246f..99bcbd7ffb0a 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -99,7 +99,7 @@ static void print_error_data(struct ehca_shca *shca, void *data,
return;
ehca_err(&shca->ib_device,
- "QP 0x%x (resource=%lx) has errors.",
+ "QP 0x%x (resource=%llx) has errors.",
qp->ib_qp.qp_num, resource);
break;
}
@@ -108,21 +108,21 @@ static void print_error_data(struct ehca_shca *shca, void *data,
struct ehca_cq *cq = (struct ehca_cq *)data;
ehca_err(&shca->ib_device,
- "CQ 0x%x (resource=%lx) has errors.",
+ "CQ 0x%x (resource=%llx) has errors.",
cq->cq_number, resource);
break;
}
default:
ehca_err(&shca->ib_device,
- "Unknown error type: %lx on %s.",
+ "Unknown error type: %llx on %s.",
type, shca->ib_device.name);
break;
}
- ehca_err(&shca->ib_device, "Error data is available: %lx.", resource);
+ ehca_err(&shca->ib_device, "Error data is available: %llx.", resource);
ehca_err(&shca->ib_device, "EHCA ----- error data begin "
"---------------------------------------------------");
- ehca_dmp(rblock, length, "resource=%lx", resource);
+ ehca_dmp(rblock, length, "resource=%llx", resource);
ehca_err(&shca->ib_device, "EHCA ----- error data end "
"----------------------------------------------------");
@@ -152,7 +152,7 @@ int ehca_error_data(struct ehca_shca *shca, void *data,
if (ret == H_R_STATE)
ehca_err(&shca->ib_device,
- "No error data is available: %lx.", resource);
+ "No error data is available: %llx.", resource);
else if (ret == H_SUCCESS) {
int length;
@@ -164,7 +164,7 @@ int ehca_error_data(struct ehca_shca *shca, void *data,
print_error_data(shca, data, rblock, length);
} else
ehca_err(&shca->ib_device,
- "Error data could not be fetched: %lx", resource);
+ "Error data could not be fetched: %llx", resource);
ehca_free_fw_ctrlblock(rblock);
@@ -514,7 +514,7 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
struct ehca_cq *cq;
eqe_value = eqe->entry;
- ehca_dbg(&shca->ib_device, "eqe_value=%lx", eqe_value);
+ ehca_dbg(&shca->ib_device, "eqe_value=%llx", eqe_value);
if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
ehca_dbg(&shca->ib_device, "Got completion event");
token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
@@ -603,7 +603,7 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
ret = hipz_h_eoi(eq->ist);
if (ret != H_SUCCESS)
ehca_err(&shca->ib_device,
- "bad return code EOI -rc = %ld\n", ret);
+ "bad return code EOI -rc = %lld\n", ret);
ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt);
}
if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE))
@@ -659,12 +659,12 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
WARN_ON_ONCE(!in_interrupt());
if (ehca_debug_level >= 3)
- ehca_dmp(&cpu_online_map, sizeof(cpumask_t), "");
+ ehca_dmp(cpu_online_mask, cpumask_size(), "");
spin_lock_irqsave(&pool->last_cpu_lock, flags);
- cpu = next_cpu_nr(pool->last_cpu, cpu_online_map);
+ cpu = cpumask_next(pool->last_cpu, cpu_online_mask);
if (cpu >= nr_cpu_ids)
- cpu = first_cpu(cpu_online_map);
+ cpu = cpumask_first(cpu_online_mask);
pool->last_cpu = cpu;
spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
@@ -855,7 +855,7 @@ static int __cpuinit comp_pool_callback(struct notifier_block *nfb,
case CPU_UP_CANCELED_FROZEN:
ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu);
cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
- kthread_bind(cct->task, any_online_cpu(cpu_online_map));
+ kthread_bind(cct->task, cpumask_any(cpu_online_mask));
destroy_comp_task(pool, cpu);
break;
case CPU_ONLINE:
@@ -902,7 +902,7 @@ int ehca_create_comp_pool(void)
return -ENOMEM;
spin_lock_init(&pool->last_cpu_lock);
- pool->last_cpu = any_online_cpu(cpu_online_map);
+ pool->last_cpu = cpumask_any(cpu_online_mask);
pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task);
if (pool->cpu_comp_tasks == NULL) {
@@ -934,10 +934,9 @@ void ehca_destroy_comp_pool(void)
unregister_hotcpu_notifier(&comp_pool_callback_nb);
- for (i = 0; i < NR_CPUS; i++) {
- if (cpu_online(i))
- destroy_comp_task(pool, i);
- }
+ for_each_online_cpu(i)
+ destroy_comp_task(pool, i);
+
free_percpu(pool->cpu_comp_tasks);
kfree(pool);
}
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 3b77b674cbf6..368311ce332b 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -304,7 +304,7 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
h_ret = hipz_h_query_hca(shca->ipz_hca_handle, rblock);
if (h_ret != H_SUCCESS) {
- ehca_gen_err("Cannot query device properties. h_ret=%li",
+ ehca_gen_err("Cannot query device properties. h_ret=%lli",
h_ret);
ret = -EPERM;
goto sense_attributes1;
@@ -391,7 +391,7 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
port = (struct hipz_query_port *)rblock;
h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
if (h_ret != H_SUCCESS) {
- ehca_gen_err("Cannot query port properties. h_ret=%li",
+ ehca_gen_err("Cannot query port properties. h_ret=%lli",
h_ret);
ret = -EPERM;
goto sense_attributes1;
@@ -682,7 +682,7 @@ static ssize_t ehca_show_adapter_handle(struct device *dev,
{
struct ehca_shca *shca = dev->driver_data;
- return sprintf(buf, "%lx\n", shca->ipz_hca_handle.handle);
+ return sprintf(buf, "%llx\n", shca->ipz_hca_handle.handle);
}
static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
@@ -955,7 +955,7 @@ void ehca_poll_eqs(unsigned long data)
struct ehca_eq *eq = &shca->eq;
int max = 3;
volatile u64 q_ofs, q_ofs2;
- u64 flags;
+ unsigned long flags;
spin_lock_irqsave(&eq->spinlock, flags);
q_ofs = eq->ipz_queue.current_q_offset;
spin_unlock_irqrestore(&eq->spinlock, flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_mcast.c b/drivers/infiniband/hw/ehca/ehca_mcast.c
index e3ef0264ccc6..120aedf9f989 100644
--- a/drivers/infiniband/hw/ehca/ehca_mcast.c
+++ b/drivers/infiniband/hw/ehca/ehca_mcast.c
@@ -88,7 +88,7 @@ int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (h_ret != H_SUCCESS)
ehca_err(ibqp->device,
"ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed "
- "h_ret=%li", my_qp, ibqp->qp_num, h_ret);
+ "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
return ehca2ib_return_code(h_ret);
}
@@ -125,7 +125,7 @@ int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
if (h_ret != H_SUCCESS)
ehca_err(ibqp->device,
"ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed "
- "h_ret=%li", my_qp, ibqp->qp_num, h_ret);
+ "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
return ehca2ib_return_code(h_ret);
}
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index f974367cad40..72f83f7df614 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -204,7 +204,7 @@ struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
}
if ((size == 0) ||
(((u64)iova_start + size) < (u64)iova_start)) {
- ehca_err(pd->device, "bad input values: size=%lx iova_start=%p",
+ ehca_err(pd->device, "bad input values: size=%llx iova_start=%p",
size, iova_start);
ib_mr = ERR_PTR(-EINVAL);
goto reg_phys_mr_exit0;
@@ -309,8 +309,8 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
}
if (length == 0 || virt + length < virt) {
- ehca_err(pd->device, "bad input values: length=%lx "
- "virt_base=%lx", length, virt);
+ ehca_err(pd->device, "bad input values: length=%llx "
+ "virt_base=%llx", length, virt);
ib_mr = ERR_PTR(-EINVAL);
goto reg_user_mr_exit0;
}
@@ -373,7 +373,7 @@ reg_user_mr_fallback:
&e_mr->ib.ib_mr.rkey);
if (ret == -EINVAL && pginfo.hwpage_size > PAGE_SIZE) {
ehca_warn(pd->device, "failed to register mr "
- "with hwpage_size=%lx", hwpage_size);
+ "with hwpage_size=%llx", hwpage_size);
ehca_info(pd->device, "try to register mr with "
"kpage_size=%lx", PAGE_SIZE);
/*
@@ -509,7 +509,7 @@ int ehca_rereg_phys_mr(struct ib_mr *mr,
goto rereg_phys_mr_exit1;
if ((new_size == 0) ||
(((u64)iova_start + new_size) < (u64)iova_start)) {
- ehca_err(mr->device, "bad input values: new_size=%lx "
+ ehca_err(mr->device, "bad input values: new_size=%llx "
"iova_start=%p", new_size, iova_start);
ret = -EINVAL;
goto rereg_phys_mr_exit1;
@@ -580,8 +580,8 @@ int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
h_ret = hipz_h_query_mr(shca->ipz_hca_handle, e_mr, &hipzout);
if (h_ret != H_SUCCESS) {
- ehca_err(mr->device, "hipz_mr_query failed, h_ret=%li mr=%p "
- "hca_hndl=%lx mr_hndl=%lx lkey=%x",
+ ehca_err(mr->device, "hipz_mr_query failed, h_ret=%lli mr=%p "
+ "hca_hndl=%llx mr_hndl=%llx lkey=%x",
h_ret, mr, shca->ipz_hca_handle.handle,
e_mr->ipz_mr_handle.handle, mr->lkey);
ret = ehca2ib_return_code(h_ret);
@@ -630,8 +630,8 @@ int ehca_dereg_mr(struct ib_mr *mr)
/* TODO: BUSY: MR still has bound window(s) */
h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
if (h_ret != H_SUCCESS) {
- ehca_err(mr->device, "hipz_free_mr failed, h_ret=%li shca=%p "
- "e_mr=%p hca_hndl=%lx mr_hndl=%lx mr->lkey=%x",
+ ehca_err(mr->device, "hipz_free_mr failed, h_ret=%lli shca=%p "
+ "e_mr=%p hca_hndl=%llx mr_hndl=%llx mr->lkey=%x",
h_ret, shca, e_mr, shca->ipz_hca_handle.handle,
e_mr->ipz_mr_handle.handle, mr->lkey);
ret = ehca2ib_return_code(h_ret);
@@ -671,8 +671,8 @@ struct ib_mw *ehca_alloc_mw(struct ib_pd *pd)
h_ret = hipz_h_alloc_resource_mw(shca->ipz_hca_handle, e_mw,
e_pd->fw_pd, &hipzout);
if (h_ret != H_SUCCESS) {
- ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%li "
- "shca=%p hca_hndl=%lx mw=%p",
+ ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%lli "
+ "shca=%p hca_hndl=%llx mw=%p",
h_ret, shca, shca->ipz_hca_handle.handle, e_mw);
ib_mw = ERR_PTR(ehca2ib_return_code(h_ret));
goto alloc_mw_exit1;
@@ -713,8 +713,8 @@ int ehca_dealloc_mw(struct ib_mw *mw)
h_ret = hipz_h_free_resource_mw(shca->ipz_hca_handle, e_mw);
if (h_ret != H_SUCCESS) {
- ehca_err(mw->device, "hipz_free_mw failed, h_ret=%li shca=%p "
- "mw=%p rkey=%x hca_hndl=%lx mw_hndl=%lx",
+ ehca_err(mw->device, "hipz_free_mw failed, h_ret=%lli shca=%p "
+ "mw=%p rkey=%x hca_hndl=%llx mw_hndl=%llx",
h_ret, shca, mw, mw->rkey, shca->ipz_hca_handle.handle,
e_mw->ipz_mw_handle.handle);
return ehca2ib_return_code(h_ret);
@@ -840,7 +840,7 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
goto map_phys_fmr_exit0;
if (iova % e_fmr->fmr_page_size) {
/* only whole-numbered pages */
- ehca_err(fmr->device, "bad iova, iova=%lx fmr_page_size=%x",
+ ehca_err(fmr->device, "bad iova, iova=%llx fmr_page_size=%x",
iova, e_fmr->fmr_page_size);
ret = -EINVAL;
goto map_phys_fmr_exit0;
@@ -878,7 +878,7 @@ int ehca_map_phys_fmr(struct ib_fmr *fmr,
map_phys_fmr_exit0:
if (ret)
ehca_err(fmr->device, "ret=%i fmr=%p page_list=%p list_len=%x "
- "iova=%lx", ret, fmr, page_list, list_len, iova);
+ "iova=%llx", ret, fmr, page_list, list_len, iova);
return ret;
} /* end ehca_map_phys_fmr() */
@@ -964,8 +964,8 @@ int ehca_dealloc_fmr(struct ib_fmr *fmr)
h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
if (h_ret != H_SUCCESS) {
- ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%li e_fmr=%p "
- "hca_hndl=%lx fmr_hndl=%lx fmr->lkey=%x",
+ ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%lli e_fmr=%p "
+ "hca_hndl=%llx fmr_hndl=%llx fmr->lkey=%x",
h_ret, e_fmr, shca->ipz_hca_handle.handle,
e_fmr->ipz_mr_handle.handle, fmr->lkey);
ret = ehca2ib_return_code(h_ret);
@@ -1007,8 +1007,8 @@ int ehca_reg_mr(struct ehca_shca *shca,
(u64)iova_start, size, hipz_acl,
e_pd->fw_pd, &hipzout);
if (h_ret != H_SUCCESS) {
- ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%li "
- "hca_hndl=%lx", h_ret, shca->ipz_hca_handle.handle);
+ ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%lli "
+ "hca_hndl=%llx", h_ret, shca->ipz_hca_handle.handle);
ret = ehca2ib_return_code(h_ret);
goto ehca_reg_mr_exit0;
}
@@ -1033,9 +1033,9 @@ int ehca_reg_mr(struct ehca_shca *shca,
ehca_reg_mr_exit1:
h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
if (h_ret != H_SUCCESS) {
- ehca_err(&shca->ib_device, "h_ret=%li shca=%p e_mr=%p "
- "iova_start=%p size=%lx acl=%x e_pd=%p lkey=%x "
- "pginfo=%p num_kpages=%lx num_hwpages=%lx ret=%i",
+ ehca_err(&shca->ib_device, "h_ret=%lli shca=%p e_mr=%p "
+ "iova_start=%p size=%llx acl=%x e_pd=%p lkey=%x "
+ "pginfo=%p num_kpages=%llx num_hwpages=%llx ret=%i",
h_ret, shca, e_mr, iova_start, size, acl, e_pd,
hipzout.lkey, pginfo, pginfo->num_kpages,
pginfo->num_hwpages, ret);
@@ -1045,8 +1045,8 @@ ehca_reg_mr_exit1:
ehca_reg_mr_exit0:
if (ret)
ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p "
- "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p "
- "num_kpages=%lx num_hwpages=%lx",
+ "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p "
+ "num_kpages=%llx num_hwpages=%llx",
ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo,
pginfo->num_kpages, pginfo->num_hwpages);
return ret;
@@ -1116,8 +1116,8 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
*/
if (h_ret != H_SUCCESS) {
ehca_err(&shca->ib_device, "last "
- "hipz_reg_rpage_mr failed, h_ret=%li "
- "e_mr=%p i=%x hca_hndl=%lx mr_hndl=%lx"
+ "hipz_reg_rpage_mr failed, h_ret=%lli "
+ "e_mr=%p i=%x hca_hndl=%llx mr_hndl=%llx"
" lkey=%x", h_ret, e_mr, i,
shca->ipz_hca_handle.handle,
e_mr->ipz_mr_handle.handle,
@@ -1128,8 +1128,8 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
ret = 0;
} else if (h_ret != H_PAGE_REGISTERED) {
ehca_err(&shca->ib_device, "hipz_reg_rpage_mr failed, "
- "h_ret=%li e_mr=%p i=%x lkey=%x hca_hndl=%lx "
- "mr_hndl=%lx", h_ret, e_mr, i,
+ "h_ret=%lli e_mr=%p i=%x lkey=%x hca_hndl=%llx "
+ "mr_hndl=%llx", h_ret, e_mr, i,
e_mr->ib.ib_mr.lkey,
shca->ipz_hca_handle.handle,
e_mr->ipz_mr_handle.handle);
@@ -1145,7 +1145,7 @@ ehca_reg_mr_rpages_exit1:
ehca_reg_mr_rpages_exit0:
if (ret)
ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p pginfo=%p "
- "num_kpages=%lx num_hwpages=%lx", ret, shca, e_mr,
+ "num_kpages=%llx num_hwpages=%llx", ret, shca, e_mr,
pginfo, pginfo->num_kpages, pginfo->num_hwpages);
return ret;
} /* end ehca_reg_mr_rpages() */
@@ -1184,7 +1184,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage);
if (ret) {
ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p "
- "pginfo=%p type=%x num_kpages=%lx num_hwpages=%lx "
+ "pginfo=%p type=%x num_kpages=%llx num_hwpages=%llx "
"kpage=%p", e_mr, pginfo, pginfo->type,
pginfo->num_kpages, pginfo->num_hwpages, kpage);
goto ehca_rereg_mr_rereg1_exit1;
@@ -1205,13 +1205,13 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
* (MW bound or MR is shared)
*/
ehca_warn(&shca->ib_device, "hipz_h_reregister_pmr failed "
- "(Rereg1), h_ret=%li e_mr=%p", h_ret, e_mr);
+ "(Rereg1), h_ret=%lli e_mr=%p", h_ret, e_mr);
*pginfo = pginfo_save;
ret = -EAGAIN;
} else if ((u64 *)hipzout.vaddr != iova_start) {
ehca_err(&shca->ib_device, "PHYP changed iova_start in "
- "rereg_pmr, iova_start=%p iova_start_out=%lx e_mr=%p "
- "mr_handle=%lx lkey=%x lkey_out=%x", iova_start,
+ "rereg_pmr, iova_start=%p iova_start_out=%llx e_mr=%p "
+ "mr_handle=%llx lkey=%x lkey_out=%x", iova_start,
hipzout.vaddr, e_mr, e_mr->ipz_mr_handle.handle,
e_mr->ib.ib_mr.lkey, hipzout.lkey);
ret = -EFAULT;
@@ -1235,7 +1235,7 @@ ehca_rereg_mr_rereg1_exit1:
ehca_rereg_mr_rereg1_exit0:
if ( ret && (ret != -EAGAIN) )
ehca_err(&shca->ib_device, "ret=%i lkey=%x rkey=%x "
- "pginfo=%p num_kpages=%lx num_hwpages=%lx",
+ "pginfo=%p num_kpages=%llx num_hwpages=%llx",
ret, *lkey, *rkey, pginfo, pginfo->num_kpages,
pginfo->num_hwpages);
return ret;
@@ -1263,7 +1263,7 @@ int ehca_rereg_mr(struct ehca_shca *shca,
(e_mr->num_hwpages > MAX_RPAGES) ||
(pginfo->num_hwpages > e_mr->num_hwpages)) {
ehca_dbg(&shca->ib_device, "Rereg3 case, "
- "pginfo->num_hwpages=%lx e_mr->num_hwpages=%x",
+ "pginfo->num_hwpages=%llx e_mr->num_hwpages=%x",
pginfo->num_hwpages, e_mr->num_hwpages);
rereg_1_hcall = 0;
rereg_3_hcall = 1;
@@ -1295,7 +1295,7 @@ int ehca_rereg_mr(struct ehca_shca *shca,
h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
if (h_ret != H_SUCCESS) {
ehca_err(&shca->ib_device, "hipz_free_mr failed, "
- "h_ret=%li e_mr=%p hca_hndl=%lx mr_hndl=%lx "
+ "h_ret=%lli e_mr=%p hca_hndl=%llx mr_hndl=%llx "
"mr->lkey=%x",
h_ret, e_mr, shca->ipz_hca_handle.handle,
e_mr->ipz_mr_handle.handle,
@@ -1328,8 +1328,8 @@ int ehca_rereg_mr(struct ehca_shca *shca,
ehca_rereg_mr_exit0:
if (ret)
ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p "
- "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p "
- "num_kpages=%lx lkey=%x rkey=%x rereg_1_hcall=%x "
+ "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p "
+ "num_kpages=%llx lkey=%x rkey=%x rereg_1_hcall=%x "
"rereg_3_hcall=%x", ret, shca, e_mr, iova_start, size,
acl, e_pd, pginfo, pginfo->num_kpages, *lkey, *rkey,
rereg_1_hcall, rereg_3_hcall);
@@ -1371,8 +1371,8 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
* FMRs are not shared and no MW bound to FMRs
*/
ehca_err(&shca->ib_device, "hipz_reregister_pmr failed "
- "(Rereg1), h_ret=%li e_fmr=%p hca_hndl=%lx "
- "mr_hndl=%lx lkey=%x lkey_out=%x",
+ "(Rereg1), h_ret=%lli e_fmr=%p hca_hndl=%llx "
+ "mr_hndl=%llx lkey=%x lkey_out=%x",
h_ret, e_fmr, shca->ipz_hca_handle.handle,
e_fmr->ipz_mr_handle.handle,
e_fmr->ib.ib_fmr.lkey, hipzout.lkey);
@@ -1383,7 +1383,7 @@ int ehca_unmap_one_fmr(struct ehca_shca *shca,
h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
if (h_ret != H_SUCCESS) {
ehca_err(&shca->ib_device, "hipz_free_mr failed, "
- "h_ret=%li e_fmr=%p hca_hndl=%lx mr_hndl=%lx "
+ "h_ret=%lli e_fmr=%p hca_hndl=%llx mr_hndl=%llx "
"lkey=%x",
h_ret, e_fmr, shca->ipz_hca_handle.handle,
e_fmr->ipz_mr_handle.handle,
@@ -1447,9 +1447,9 @@ int ehca_reg_smr(struct ehca_shca *shca,
(u64)iova_start, hipz_acl, e_pd->fw_pd,
&hipzout);
if (h_ret != H_SUCCESS) {
- ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%li "
+ ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli "
"shca=%p e_origmr=%p e_newmr=%p iova_start=%p acl=%x "
- "e_pd=%p hca_hndl=%lx mr_hndl=%lx lkey=%x",
+ "e_pd=%p hca_hndl=%llx mr_hndl=%llx lkey=%x",
h_ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd,
shca->ipz_hca_handle.handle,
e_origmr->ipz_mr_handle.handle,
@@ -1527,7 +1527,7 @@ int ehca_reg_internal_maxmr(
&e_mr->ib.ib_mr.rkey);
if (ret) {
ehca_err(&shca->ib_device, "reg of internal max MR failed, "
- "e_mr=%p iova_start=%p size_maxmr=%lx num_kpages=%x "
+ "e_mr=%p iova_start=%p size_maxmr=%llx num_kpages=%x "
"num_hwpages=%x", e_mr, iova_start, size_maxmr,
num_kpages, num_hwpages);
goto ehca_reg_internal_maxmr_exit1;
@@ -1573,8 +1573,8 @@ int ehca_reg_maxmr(struct ehca_shca *shca,
(u64)iova_start, hipz_acl, e_pd->fw_pd,
&hipzout);
if (h_ret != H_SUCCESS) {
- ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%li "
- "e_origmr=%p hca_hndl=%lx mr_hndl=%lx lkey=%x",
+ ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli "
+ "e_origmr=%p hca_hndl=%llx mr_hndl=%llx lkey=%x",
h_ret, e_origmr, shca->ipz_hca_handle.handle,
e_origmr->ipz_mr_handle.handle,
e_origmr->ib.ib_mr.lkey);
@@ -1651,28 +1651,28 @@ int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array,
/* check first buffer */
if (((u64)iova_start & ~PAGE_MASK) != (pbuf->addr & ~PAGE_MASK)) {
ehca_gen_err("iova_start/addr mismatch, iova_start=%p "
- "pbuf->addr=%lx pbuf->size=%lx",
+ "pbuf->addr=%llx pbuf->size=%llx",
iova_start, pbuf->addr, pbuf->size);
return -EINVAL;
}
if (((pbuf->addr + pbuf->size) % PAGE_SIZE) &&
(num_phys_buf > 1)) {
- ehca_gen_err("addr/size mismatch in 1st buf, pbuf->addr=%lx "
- "pbuf->size=%lx", pbuf->addr, pbuf->size);
+ ehca_gen_err("addr/size mismatch in 1st buf, pbuf->addr=%llx "
+ "pbuf->size=%llx", pbuf->addr, pbuf->size);
return -EINVAL;
}
for (i = 0; i < num_phys_buf; i++) {
if ((i > 0) && (pbuf->addr % PAGE_SIZE)) {
- ehca_gen_err("bad address, i=%x pbuf->addr=%lx "
- "pbuf->size=%lx",
+ ehca_gen_err("bad address, i=%x pbuf->addr=%llx "
+ "pbuf->size=%llx",
i, pbuf->addr, pbuf->size);
return -EINVAL;
}
if (((i > 0) && /* not 1st */
(i < (num_phys_buf - 1)) && /* not last */
(pbuf->size % PAGE_SIZE)) || (pbuf->size == 0)) {
- ehca_gen_err("bad size, i=%x pbuf->size=%lx",
+ ehca_gen_err("bad size, i=%x pbuf->size=%llx",
i, pbuf->size);
return -EINVAL;
}
@@ -1705,7 +1705,7 @@ int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,
page = page_list;
for (i = 0; i < list_len; i++) {
if (*page % e_fmr->fmr_page_size) {
- ehca_gen_err("bad page, i=%x *page=%lx page=%p fmr=%p "
+ ehca_gen_err("bad page, i=%x *page=%llx page=%p fmr=%p "
"fmr_page_size=%x", i, *page, page, e_fmr,
e_fmr->fmr_page_size);
return -EINVAL;
@@ -1743,9 +1743,9 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
(pginfo->next_hwpage *
pginfo->hwpage_size));
if ( !(*kpage) ) {
- ehca_gen_err("pgaddr=%lx "
- "chunk->page_list[i]=%lx "
- "i=%x next_hwpage=%lx",
+ ehca_gen_err("pgaddr=%llx "
+ "chunk->page_list[i]=%llx "
+ "i=%x next_hwpage=%llx",
pgaddr, (u64)sg_dma_address(
&chunk->page_list[i]),
i, pginfo->next_hwpage);
@@ -1795,11 +1795,11 @@ static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
for (t = start_idx; t <= end_idx; t++) {
u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
if (ehca_debug_level >= 3)
- ehca_gen_dbg("chunk_page=%lx value=%016lx", pgaddr,
+ ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr,
*(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
- ehca_gen_err("uncontiguous page found pgaddr=%lx "
- "prev_pgaddr=%lx page_list_i=%x",
+ ehca_gen_err("uncontiguous page found pgaddr=%llx "
+ "prev_pgaddr=%llx page_list_i=%x",
pgaddr, *prev_pgaddr, t);
return -EINVAL;
}
@@ -1833,7 +1833,7 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
<< PAGE_SHIFT );
*kpage = phys_to_abs(pgaddr);
if ( !(*kpage) ) {
- ehca_gen_err("pgaddr=%lx i=%x",
+ ehca_gen_err("pgaddr=%llx i=%x",
pgaddr, i);
ret = -EFAULT;
return ret;
@@ -1846,8 +1846,8 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
if (pginfo->hwpage_cnt) {
ehca_gen_err(
"invalid alignment "
- "pgaddr=%lx i=%x "
- "mr_pgsize=%lx",
+ "pgaddr=%llx i=%x "
+ "mr_pgsize=%llx",
pgaddr, i,
pginfo->hwpage_size);
ret = -EFAULT;
@@ -1866,8 +1866,8 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
if (ehca_debug_level >= 3) {
u64 val = *(u64 *)abs_to_virt(
phys_to_abs(pgaddr));
- ehca_gen_dbg("kpage=%lx chunk_page=%lx "
- "value=%016lx",
+ ehca_gen_dbg("kpage=%llx chunk_page=%llx "
+ "value=%016llx",
*kpage, pgaddr, val);
}
prev_pgaddr = pgaddr;
@@ -1944,9 +1944,9 @@ static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
(pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
ehca_gen_err("kpage_cnt >= num_kpages, "
- "kpage_cnt=%lx num_kpages=%lx "
- "hwpage_cnt=%lx "
- "num_hwpages=%lx i=%x",
+ "kpage_cnt=%llx num_kpages=%llx "
+ "hwpage_cnt=%llx "
+ "num_hwpages=%llx i=%x",
pginfo->kpage_cnt,
pginfo->num_kpages,
pginfo->hwpage_cnt,
@@ -1957,8 +1957,8 @@ static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
(pbuf->addr & ~(pginfo->hwpage_size - 1)) +
(pginfo->next_hwpage * pginfo->hwpage_size));
if ( !(*kpage) && pbuf->addr ) {
- ehca_gen_err("pbuf->addr=%lx pbuf->size=%lx "
- "next_hwpage=%lx", pbuf->addr,
+ ehca_gen_err("pbuf->addr=%llx pbuf->size=%llx "
+ "next_hwpage=%llx", pbuf->addr,
pbuf->size, pginfo->next_hwpage);
return -EFAULT;
}
@@ -1996,8 +1996,8 @@ static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
*kpage = phys_to_abs((*fmrlist & ~(pginfo->hwpage_size - 1)) +
pginfo->next_hwpage * pginfo->hwpage_size);
if ( !(*kpage) ) {
- ehca_gen_err("*fmrlist=%lx fmrlist=%p "
- "next_listelem=%lx next_hwpage=%lx",
+ ehca_gen_err("*fmrlist=%llx fmrlist=%p "
+ "next_listelem=%llx next_hwpage=%llx",
*fmrlist, fmrlist,
pginfo->u.fmr.next_listelem,
pginfo->next_hwpage);
@@ -2025,7 +2025,7 @@ static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
~(pginfo->hwpage_size - 1));
if (prev + pginfo->u.fmr.fmr_pgsize != p) {
ehca_gen_err("uncontiguous fmr pages "
- "found prev=%lx p=%lx "
+ "found prev=%llx p=%llx "
"idx=%x", prev, p, i + j);
return -EINVAL;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index f161cf173dbe..00c108159714 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -331,7 +331,7 @@ static inline int init_qp_queue(struct ehca_shca *shca,
if (cnt == (nr_q_pages - 1)) { /* last page! */
if (h_ret != expected_hret) {
ehca_err(ib_dev, "hipz_qp_register_rpage() "
- "h_ret=%li", h_ret);
+ "h_ret=%lli", h_ret);
ret = ehca2ib_return_code(h_ret);
goto init_qp_queue1;
}
@@ -345,7 +345,7 @@ static inline int init_qp_queue(struct ehca_shca *shca,
} else {
if (h_ret != H_PAGE_REGISTERED) {
ehca_err(ib_dev, "hipz_qp_register_rpage() "
- "h_ret=%li", h_ret);
+ "h_ret=%lli", h_ret);
ret = ehca2ib_return_code(h_ret);
goto init_qp_queue1;
}
@@ -709,7 +709,7 @@ static struct ehca_qp *internal_create_qp(
h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);
if (h_ret != H_SUCCESS) {
- ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%li",
+ ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli",
h_ret);
ret = ehca2ib_return_code(h_ret);
goto create_qp_exit1;
@@ -1010,7 +1010,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
mqpcb, my_qp->galpas.kernel);
if (hret != H_SUCCESS) {
ehca_err(pd->device, "Could not modify SRQ to INIT "
- "ehca_qp=%p qp_num=%x h_ret=%li",
+ "ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, my_qp->real_qp_num, hret);
goto create_srq2;
}
@@ -1024,7 +1024,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
mqpcb, my_qp->galpas.kernel);
if (hret != H_SUCCESS) {
ehca_err(pd->device, "Could not enable SRQ "
- "ehca_qp=%p qp_num=%x h_ret=%li",
+ "ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, my_qp->real_qp_num, hret);
goto create_srq2;
}
@@ -1038,7 +1038,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
mqpcb, my_qp->galpas.kernel);
if (hret != H_SUCCESS) {
ehca_err(pd->device, "Could not modify SRQ to RTR "
- "ehca_qp=%p qp_num=%x h_ret=%li",
+ "ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, my_qp->real_qp_num, hret);
goto create_srq2;
}
@@ -1078,7 +1078,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
&bad_send_wqe_p, NULL, 2);
if (h_ret != H_SUCCESS) {
ehca_err(&shca->ib_device, "hipz_h_disable_and_get_wqe() failed"
- " ehca_qp=%p qp_num=%x h_ret=%li",
+ " ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, qp_num, h_ret);
return ehca2ib_return_code(h_ret);
}
@@ -1134,7 +1134,7 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) {
ehca_gen_err("Invalid offset for calculating left cqes "
- "wqe_p=%#lx wqe_v=%p\n", wqe_p, wqe_v);
+ "wqe_p=%#llx wqe_v=%p\n", wqe_p, wqe_v);
return -EFAULT;
}
@@ -1168,7 +1168,7 @@ static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca)
&send_wqe_p, &recv_wqe_p, 4);
if (h_ret != H_SUCCESS) {
ehca_err(&shca->ib_device, "disable_and_get_wqe() "
- "failed ehca_qp=%p qp_num=%x h_ret=%li",
+ "failed ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, qp_num, h_ret);
return ehca2ib_return_code(h_ret);
}
@@ -1261,7 +1261,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
mqpcb, my_qp->galpas.kernel);
if (h_ret != H_SUCCESS) {
ehca_err(ibqp->device, "hipz_h_query_qp() failed "
- "ehca_qp=%p qp_num=%x h_ret=%li",
+ "ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, ibqp->qp_num, h_ret);
ret = ehca2ib_return_code(h_ret);
goto modify_qp_exit1;
@@ -1690,7 +1690,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
if (h_ret != H_SUCCESS) {
ret = ehca2ib_return_code(h_ret);
- ehca_err(ibqp->device, "hipz_h_modify_qp() failed h_ret=%li "
+ ehca_err(ibqp->device, "hipz_h_modify_qp() failed h_ret=%lli "
"ehca_qp=%p qp_num=%x", h_ret, my_qp, ibqp->qp_num);
goto modify_qp_exit2;
}
@@ -1723,7 +1723,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
ret = ehca2ib_return_code(h_ret);
ehca_err(ibqp->device, "ENABLE in context of "
"RESET_2_INIT failed! Maybe you didn't get "
- "a LID h_ret=%li ehca_qp=%p qp_num=%x",
+ "a LID h_ret=%lli ehca_qp=%p qp_num=%x",
h_ret, my_qp, ibqp->qp_num);
goto modify_qp_exit2;
}
@@ -1909,7 +1909,7 @@ int ehca_query_qp(struct ib_qp *qp,
if (h_ret != H_SUCCESS) {
ret = ehca2ib_return_code(h_ret);
ehca_err(qp->device, "hipz_h_query_qp() failed "
- "ehca_qp=%p qp_num=%x h_ret=%li",
+ "ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, qp->qp_num, h_ret);
goto query_qp_exit1;
}
@@ -2074,7 +2074,7 @@ int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
if (h_ret != H_SUCCESS) {
ret = ehca2ib_return_code(h_ret);
- ehca_err(ibsrq->device, "hipz_h_modify_qp() failed h_ret=%li "
+ ehca_err(ibsrq->device, "hipz_h_modify_qp() failed h_ret=%lli "
"ehca_qp=%p qp_num=%x",
h_ret, my_qp, my_qp->real_qp_num);
}
@@ -2108,7 +2108,7 @@ int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
if (h_ret != H_SUCCESS) {
ret = ehca2ib_return_code(h_ret);
ehca_err(srq->device, "hipz_h_query_qp() failed "
- "ehca_qp=%p qp_num=%x h_ret=%li",
+ "ehca_qp=%p qp_num=%x h_ret=%lli",
my_qp, my_qp->real_qp_num, h_ret);
goto query_srq_exit1;
}
@@ -2179,7 +2179,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
if (h_ret != H_SUCCESS) {
- ehca_err(dev, "hipz_h_destroy_qp() failed h_ret=%li "
+ ehca_err(dev, "hipz_h_destroy_qp() failed h_ret=%lli "
"ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num);
return ehca2ib_return_code(h_ret);
}
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index c7112686782f..5a3d96f84c79 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -822,7 +822,7 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq,
offset = qmap->next_wqe_idx * ipz_queue->qe_size;
wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset);
if (!wqe) {
- ehca_err(cq->device, "Invalid wqe offset=%#lx on "
+ ehca_err(cq->device, "Invalid wqe offset=%#llx on "
"qp_num=%#x", offset, my_qp->real_qp_num);
return nr;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c
index 706d97ad5555..44447aaa5501 100644
--- a/drivers/infiniband/hw/ehca/ehca_sqp.c
+++ b/drivers/infiniband/hw/ehca/ehca_sqp.c
@@ -85,7 +85,7 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
if (ret != H_SUCCESS) {
ehca_err(&shca->ib_device,
- "Can't define AQP1 for port %x. h_ret=%li",
+ "Can't define AQP1 for port %x. h_ret=%lli",
port, ret);
return ret;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index 21f7d06f14ad..f09914cccf53 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -116,7 +116,7 @@ extern int ehca_debug_level;
unsigned char *deb = (unsigned char *)(adr); \
for (x = 0; x < l; x += 16) { \
printk(KERN_INFO "EHCA_DMP:%s " format \
- " adr=%p ofs=%04x %016lx %016lx\n", \
+ " adr=%p ofs=%04x %016llx %016llx\n", \
__func__, ##args, deb, x, \
*((u64 *)&deb[0]), *((u64 *)&deb[8])); \
deb += 16; \
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index e43ed8f8a0c8..3cb688d29131 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -114,7 +114,7 @@ static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
physical = galpas->user.fw_handle;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- ehca_gen_dbg("vsize=%lx physical=%lx", vsize, physical);
+ ehca_gen_dbg("vsize=%llx physical=%llx", vsize, physical);
/* VM_IO | VM_RESERVED are set by remap_pfn_range() */
ret = remap_4k_pfn(vma, vma->vm_start, physical >> EHCA_PAGESHIFT,
vma->vm_page_prot);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 415d3a465de6..d0ab0c0d5e91 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -226,7 +226,7 @@ u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
u32 *eq_ist)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
u64 allocate_controls;
/* resource type */
@@ -249,7 +249,7 @@ u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
*eq_ist = (u32)outs[5];
if (ret == H_NOT_ENOUGH_RESOURCES)
- ehca_gen_err("Not enough resource - ret=%li ", ret);
+ ehca_gen_err("Not enough resource - ret=%lli ", ret);
return ret;
}
@@ -270,7 +270,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
struct ehca_alloc_cq_parms *param)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
adapter_handle.handle, /* r4 */
@@ -287,7 +287,7 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]);
if (ret == H_NOT_ENOUGH_RESOURCES)
- ehca_gen_err("Not enough resources. ret=%li", ret);
+ ehca_gen_err("Not enough resources. ret=%lli", ret);
return ret;
}
@@ -297,7 +297,7 @@ u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
{
u64 ret;
u64 allocate_controls, max_r10_reg, r11, r12;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
allocate_controls =
EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
@@ -362,7 +362,7 @@ u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
if (ret == H_NOT_ENOUGH_RESOURCES)
- ehca_gen_err("Not enough resources. ret=%li", ret);
+ ehca_gen_err("Not enough resources. ret=%lli", ret);
return ret;
}
@@ -454,7 +454,7 @@ u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
const u64 count)
{
if (count != 1) {
- ehca_gen_err("Ppage counter=%lx", count);
+ ehca_gen_err("Ppage counter=%llx", count);
return H_PARAMETER;
}
return hipz_h_register_rpage(adapter_handle,
@@ -489,7 +489,7 @@ u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
const struct h_galpa gal)
{
if (count != 1) {
- ehca_gen_err("Page counter=%lx", count);
+ ehca_gen_err("Page counter=%llx", count);
return H_PARAMETER;
}
@@ -508,7 +508,7 @@ u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
const struct h_galpa galpa)
{
if (count > 1) {
- ehca_gen_err("Page counter=%lx", count);
+ ehca_gen_err("Page counter=%llx", count);
return H_PARAMETER;
}
@@ -525,7 +525,7 @@ u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
int dis_and_get_function_code)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
adapter_handle.handle, /* r4 */
@@ -548,7 +548,7 @@ u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
struct h_galpa gal)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
adapter_handle.handle, /* r4 */
qp_handle.handle, /* r5 */
@@ -557,7 +557,7 @@ u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
0, 0, 0, 0, 0);
if (ret == H_NOT_ENOUGH_RESOURCES)
- ehca_gen_err("Insufficient resources ret=%li", ret);
+ ehca_gen_err("Insufficient resources ret=%lli", ret);
return ret;
}
@@ -579,7 +579,7 @@ u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
struct ehca_qp *qp)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = hcp_galpas_dtor(&qp->galpas);
if (ret) {
@@ -593,7 +593,7 @@ u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
qp->ipz_qp_handle.handle, /* r6 */
0, 0, 0, 0, 0, 0);
if (ret == H_HARDWARE)
- ehca_gen_err("HCA not operational. ret=%li", ret);
+ ehca_gen_err("HCA not operational. ret=%lli", ret);
ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
adapter_handle.handle, /* r4 */
@@ -601,7 +601,7 @@ u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
0, 0, 0, 0, 0);
if (ret == H_RESOURCE)
- ehca_gen_err("Resource still in use. ret=%li", ret);
+ ehca_gen_err("Resource still in use. ret=%lli", ret);
return ret;
}
@@ -625,7 +625,7 @@ u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
u32 * bma_qp_nr)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
adapter_handle.handle, /* r4 */
@@ -636,7 +636,7 @@ u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
*bma_qp_nr = (u32)outs[1];
if (ret == H_ALIAS_EXIST)
- ehca_gen_err("AQP1 already exists. ret=%li", ret);
+ ehca_gen_err("AQP1 already exists. ret=%lli", ret);
return ret;
}
@@ -658,7 +658,7 @@ u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
0, 0);
if (ret == H_NOT_ENOUGH_RESOURCES)
- ehca_gen_err("Not enough resources. ret=%li", ret);
+ ehca_gen_err("Not enough resources. ret=%lli", ret);
return ret;
}
@@ -697,7 +697,7 @@ u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
0, 0, 0, 0);
if (ret == H_RESOURCE)
- ehca_gen_err("H_FREE_RESOURCE failed ret=%li ", ret);
+ ehca_gen_err("H_FREE_RESOURCE failed ret=%lli ", ret);
return ret;
}
@@ -719,7 +719,7 @@ u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
0, 0, 0, 0, 0);
if (ret == H_RESOURCE)
- ehca_gen_err("Resource in use. ret=%li ", ret);
+ ehca_gen_err("Resource in use. ret=%lli ", ret);
return ret;
}
@@ -733,7 +733,7 @@ u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
struct ehca_mr_hipzout_parms *outparms)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
adapter_handle.handle, /* r4 */
@@ -774,9 +774,9 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
ehca_gen_err("logical_address_of_page not on a 4k boundary "
- "adapter_handle=%lx mr=%p mr_handle=%lx "
+ "adapter_handle=%llx mr=%p mr_handle=%llx "
"pagesize=%x queue_type=%x "
- "logical_address_of_page=%lx count=%lx",
+ "logical_address_of_page=%llx count=%llx",
adapter_handle.handle, mr,
mr->ipz_mr_handle.handle, pagesize, queue_type,
logical_address_of_page, count);
@@ -794,7 +794,7 @@ u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
struct ehca_mr_hipzout_parms *outparms)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
adapter_handle.handle, /* r4 */
@@ -828,7 +828,7 @@ u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
struct ehca_mr_hipzout_parms *outparms)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
adapter_handle.handle, /* r4 */
@@ -855,7 +855,7 @@ u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
struct ehca_mr_hipzout_parms *outparms)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
adapter_handle.handle, /* r4 */
@@ -877,7 +877,7 @@ u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
struct ehca_mw_hipzout_parms *outparms)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
adapter_handle.handle, /* r4 */
@@ -895,7 +895,7 @@ u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
struct ehca_mw_hipzout_parms *outparms)
{
u64 ret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
adapter_handle.handle, /* r4 */
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 239d4e8068ac..23173982b32c 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -1679,7 +1679,7 @@ static int find_best_unit(struct file *fp,
* InfiniPath chip to that processor (we assume reasonable connectivity,
* for now). This code assumes that if affinity has been set
* before this point, that at most one cpu is set; for now this
- * is reasonable. I check for both cpus_empty() and cpus_full(),
+ * is reasonable. I check for both cpumask_empty() and cpumask_full(),
* in case some kernel variant sets none of the bits when no
* affinity is set. 2.6.11 and 12 kernels have all present
* cpus set. Some day we'll have to fix it up further to handle
@@ -1688,11 +1688,11 @@ static int find_best_unit(struct file *fp,
* information. There may be some issues with dual core numbering
* as well. This needs more work prior to release.
*/
- if (!cpus_empty(current->cpus_allowed) &&
- !cpus_full(current->cpus_allowed)) {
+ if (!cpumask_empty(&current->cpus_allowed) &&
+ !cpumask_full(&current->cpus_allowed)) {
int ncpus = num_online_cpus(), curcpu = -1, nset = 0;
for (i = 0; i < ncpus; i++)
- if (cpu_isset(i, current->cpus_allowed)) {
+ if (cpumask_test_cpu(i, &current->cpus_allowed)) {
ipath_cdbg(PROC, "%s[%u] affinity set for "
"cpu %d/%d\n", current->comm,
current->pid, i, ncpus);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 53912c327bfe..8dc2bb781605 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -57,9 +57,6 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
}
inode->i_mode = mode;
- inode->i_uid = 0;
- inode->i_gid = 0;
- inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_private = data;
if ((mode & S_IFMT) == S_IFDIR) {
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index a3c5af1d7ec0..de5263beab4a 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -367,7 +367,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
if (err)
goto out;
} else {
- /* Can't be smaller then the number of outstanding CQEs */
+ /* Can't be smaller than the number of outstanding CQEs */
outst_cqe = mlx4_ib_get_outstanding_cqes(cq);
if (entries < outst_cqe + 1) {
err = 0;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index dcefe1fceb5c..61588bd273bd 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -543,14 +543,21 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
{
static int mlx4_ib_version_printed;
struct mlx4_ib_dev *ibdev;
+ int num_ports = 0;
int i;
-
if (!mlx4_ib_version_printed) {
printk(KERN_INFO "%s", mlx4_ib_version);
++mlx4_ib_version_printed;
}
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+ num_ports++;
+
+ /* No point in registering a device with no ports... */
+ if (num_ports == 0)
+ return NULL;
+
ibdev = (struct mlx4_ib_dev *) ib_alloc_device(sizeof *ibdev);
if (!ibdev) {
dev_err(&dev->pdev->dev, "Device struct alloc failed\n");
@@ -574,9 +581,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.owner = THIS_MODULE;
ibdev->ib_dev.node_type = RDMA_NODE_IB_CA;
ibdev->ib_dev.local_dma_lkey = dev->caps.reserved_lkey;
- ibdev->num_ports = 0;
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
- ibdev->num_ports++;
+ ibdev->num_ports = num_ports;
ibdev->ib_dev.phys_port_cnt = ibdev->num_ports;
ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors;
ibdev->ib_dev.dma_device = &dev->pdev->dev;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 39167a797f99..a91cb4c3fa5c 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1462,7 +1462,8 @@ static void __set_data_seg(struct mlx4_wqe_data_seg *dseg, struct ib_sge *sg)
}
static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
- struct mlx4_ib_qp *qp, unsigned *lso_seg_len)
+ struct mlx4_ib_qp *qp, unsigned *lso_seg_len,
+ __be32 *lso_hdr_sz)
{
unsigned halign = ALIGN(sizeof *wqe + wr->wr.ud.hlen, 16);
@@ -1479,12 +1480,8 @@ static int build_lso_seg(struct mlx4_wqe_lso_seg *wqe, struct ib_send_wr *wr,
memcpy(wqe->header, wr->wr.ud.header, wr->wr.ud.hlen);
- /* make sure LSO header is written before overwriting stamping */
- wmb();
-
- wqe->mss_hdr_size = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
- wr->wr.ud.hlen);
-
+ *lso_hdr_sz = cpu_to_be32((wr->wr.ud.mss - wr->wr.ud.hlen) << 16 |
+ wr->wr.ud.hlen);
*lso_seg_len = halign;
return 0;
}
@@ -1518,6 +1515,9 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
int uninitialized_var(stamp);
int uninitialized_var(size);
unsigned uninitialized_var(seglen);
+ __be32 dummy;
+ __be32 *lso_wqe;
+ __be32 uninitialized_var(lso_hdr_sz);
int i;
spin_lock_irqsave(&qp->sq.lock, flags);
@@ -1525,6 +1525,8 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
ind = qp->sq_next_wqe;
for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ lso_wqe = &dummy;
+
if (mlx4_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
err = -ENOMEM;
*bad_wr = wr;
@@ -1606,11 +1608,12 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
if (wr->opcode == IB_WR_LSO) {
- err = build_lso_seg(wqe, wr, qp, &seglen);
+ err = build_lso_seg(wqe, wr, qp, &seglen, &lso_hdr_sz);
if (unlikely(err)) {
*bad_wr = wr;
goto out;
}
+ lso_wqe = (__be32 *) wqe;
wqe += seglen;
size += seglen / 16;
}
@@ -1652,6 +1655,14 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
for (i = wr->num_sge - 1; i >= 0; --i, --dseg)
set_data_seg(dseg, wr->sg_list + i);
+ /*
+ * Possibly overwrite stamping in cacheline with LSO
+ * segment only after making sure all data segments
+ * are written.
+ */
+ wmb();
+ *lso_wqe = lso_hdr_sz;
+
ctrl->fence_size = (wr->send_flags & IB_SEND_FENCE ?
MLX4_WQE_CTRL_FENCE : 0) | size;
@@ -1686,7 +1697,6 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
stamp_send_wqe(qp, stamp, size * 16);
ind = pad_wraparound(qp, ind);
}
-
}
out:
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index a812db243477..a01b4488208b 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -778,12 +778,13 @@ static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
unsigned long flags;
struct list_head *hte;
struct nes_cm_node *cm_node;
+ __be32 tmp_addr = cpu_to_be32(loc_addr);
/* get a handle on the hte */
hte = &cm_core->connected_nodes;
nes_debug(NES_DBG_CM, "Searching for an owner node: %pI4:%x from core %p->%p\n",
- &loc_addr, loc_port, cm_core, hte);
+ &tmp_addr, loc_port, cm_core, hte);
/* walk list and find cm_node associated with this session ID */
spin_lock_irqsave(&cm_core->ht_lock, flags);
@@ -816,6 +817,7 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
{
unsigned long flags;
struct nes_cm_listener *listen_node;
+ __be32 tmp_addr = cpu_to_be32(dst_addr);
/* walk list and find cm_node associated with this session ID */
spin_lock_irqsave(&cm_core->listen_list_lock, flags);
@@ -833,7 +835,7 @@ static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
nes_debug(NES_DBG_CM, "Unable to find listener for %pI4:%x\n",
- &dst_addr, dst_port);
+ &tmp_addr, dst_port);
/* no listener */
return NULL;
@@ -2059,6 +2061,7 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
struct tcphdr *tcph;
struct nes_cm_info nfo;
int skb_handled = 1;
+ __be32 tmp_daddr, tmp_saddr;
if (!skb)
return 0;
@@ -2074,8 +2077,11 @@ static int mini_cm_recv_pkt(struct nes_cm_core *cm_core,
nfo.rem_addr = ntohl(iph->saddr);
nfo.rem_port = ntohs(tcph->source);
+ tmp_daddr = cpu_to_be32(iph->daddr);
+ tmp_saddr = cpu_to_be32(iph->saddr);
+
nes_debug(NES_DBG_CM, "Received packet: dest=%pI4:0x%04X src=%pI4:0x%04X\n",
- &iph->daddr, tcph->dest, &iph->saddr, tcph->source);
+ &tmp_daddr, tcph->dest, &tmp_saddr, tcph->source);
do {
cm_node = find_node(cm_core,
@@ -2705,7 +2711,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
sizeof(struct ietf_mpa_frame));
- /* notify OF layer that accept event was successfull */
+ /* notify OF layer that accept event was successful */
cm_id->add_ref(cm_id);
cm_event.event = IW_CM_EVENT_ESTABLISHED;
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index aa9b7348c728..6f3bc1b6bf22 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -655,6 +655,7 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti
struct nes_adapter *nesadapter = nesdev->nesadapter;
int arp_index;
int err = 0;
+ __be32 tmp_addr;
for (arp_index = 0; (u32) arp_index < nesadapter->arp_table_size; arp_index++) {
if (nesadapter->arp_table[arp_index].ip_addr == ip_addr)
@@ -682,8 +683,9 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti
/* DELETE or RESOLVE */
if (arp_index == nesadapter->arp_table_size) {
+ tmp_addr = cpu_to_be32(ip_addr);
nes_debug(NES_DBG_NETDEV, "MAC for %pI4 not in ARP table - cannot %s\n",
- &ip_addr, action == NES_ARP_RESOLVE ? "resolve" : "delete");
+ &tmp_addr, action == NES_ARP_RESOLVE ? "resolve" : "delete");
return -1;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 19e06bc38b39..0bd2a4ff0842 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -106,23 +106,17 @@ int ipoib_open(struct net_device *dev)
ipoib_dbg(priv, "bringing up interface\n");
- set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
+ if (!test_and_set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
+ napi_enable(&priv->napi);
if (ipoib_pkey_dev_delay_open(dev))
return 0;
- napi_enable(&priv->napi);
+ if (ipoib_ib_dev_open(dev))
+ goto err_disable;
- if (ipoib_ib_dev_open(dev)) {
- napi_disable(&priv->napi);
- return -EINVAL;
- }
-
- if (ipoib_ib_dev_up(dev)) {
- ipoib_ib_dev_stop(dev, 1);
- napi_disable(&priv->napi);
- return -EINVAL;
- }
+ if (ipoib_ib_dev_up(dev))
+ goto err_stop;
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
struct ipoib_dev_priv *cpriv;
@@ -144,6 +138,15 @@ int ipoib_open(struct net_device *dev)
netif_start_queue(dev);
return 0;
+
+err_stop:
+ ipoib_ib_dev_stop(dev, 1);
+
+err_disable:
+ napi_disable(&priv->napi);
+ clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
+
+ return -EINVAL;
}
static int ipoib_stop(struct net_device *dev)
@@ -711,26 +714,26 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
neigh = *to_ipoib_neigh(skb->dst->neighbour);
- if (neigh->ah)
- if (unlikely((memcmp(&neigh->dgid.raw,
- skb->dst->neighbour->ha + 4,
- sizeof(union ib_gid))) ||
- (neigh->dev != dev))) {
- spin_lock_irqsave(&priv->lock, flags);
- /*
- * It's safe to call ipoib_put_ah() inside
- * priv->lock here, because we know that
- * path->ah will always hold one more reference,
- * so ipoib_put_ah() will never do more than
- * decrement the ref count.
- */
+ if (unlikely((memcmp(&neigh->dgid.raw,
+ skb->dst->neighbour->ha + 4,
+ sizeof(union ib_gid))) ||
+ (neigh->dev != dev))) {
+ spin_lock_irqsave(&priv->lock, flags);
+ /*
+ * It's safe to call ipoib_put_ah() inside
+ * priv->lock here, because we know that
+ * path->ah will always hold one more reference,
+ * so ipoib_put_ah() will never do more than
+ * decrement the ref count.
+ */
+ if (neigh->ah)
ipoib_put_ah(neigh->ah);
- list_del(&neigh->list);
- ipoib_neigh_free(dev, neigh);
- spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_path_lookup(skb, dev);
- return NETDEV_TX_OK;
- }
+ list_del(&neigh->list);
+ ipoib_neigh_free(dev, neigh);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ ipoib_path_lookup(skb, dev);
+ return NETDEV_TX_OK;
+ }
if (ipoib_cm_get(neigh)) {
if (ipoib_cm_up(neigh)) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index a2eb3b9789eb..425e31112ed7 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -409,7 +409,7 @@ static int ipoib_mcast_join_complete(int status,
}
if (mcast->logcount++ < 20) {
- if (status == -ETIMEDOUT) {
+ if (status == -ETIMEDOUT || status == -EAGAIN) {
ipoib_dbg_mcast(priv, "multicast join failed for %pI6, status %d\n",
mcast->mcmember.mgid.raw, status);
} else {
@@ -529,6 +529,9 @@ void ipoib_mcast_join_task(struct work_struct *work)
if (!priv->broadcast) {
struct ipoib_mcast *broadcast;
+ if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
+ return;
+
broadcast = ipoib_mcast_alloc(dev, 1);
if (!broadcast) {
ipoib_warn(priv, "failed to allocate broadcast group\n");
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 2cf1a4088718..5a76a5510350 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -61,6 +61,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
ppriv = netdev_priv(pdev);
+ rtnl_lock();
mutex_lock(&ppriv->vlan_mutex);
/*
@@ -111,7 +112,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
goto device_init_failed;
}
- result = register_netdev(priv->dev);
+ result = register_netdevice(priv->dev);
if (result) {
ipoib_warn(priv, "failed to initialize; error %i", result);
goto register_failed;
@@ -134,12 +135,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
list_add_tail(&priv->list, &ppriv->child_intfs);
mutex_unlock(&ppriv->vlan_mutex);
+ rtnl_unlock();
return 0;
sysfs_failed:
ipoib_delete_debug_files(priv->dev);
- unregister_netdev(priv->dev);
+ unregister_netdevice(priv->dev);
register_failed:
ipoib_dev_cleanup(priv->dev);
@@ -149,6 +151,7 @@ device_init_failed:
err:
mutex_unlock(&ppriv->vlan_mutex);
+ rtnl_unlock();
return result;
}
@@ -162,10 +165,11 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
ppriv = netdev_priv(pdev);
+ rtnl_lock();
mutex_lock(&ppriv->vlan_mutex);
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
if (priv->pkey == pkey) {
- unregister_netdev(priv->dev);
+ unregister_netdevice(priv->dev);
ipoib_dev_cleanup(priv->dev);
list_del(&priv->list);
free_netdev(priv->dev);
@@ -175,6 +179,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
}
}
mutex_unlock(&ppriv->vlan_mutex);
+ rtnl_unlock();
return ret;
}
diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig
index 77dedba829e6..b411c51842da 100644
--- a/drivers/infiniband/ulp/iser/Kconfig
+++ b/drivers/infiniband/ulp/iser/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_ISER
tristate "iSCSI Extensions for RDMA (iSER)"
- depends on SCSI && INET
+ depends on SCSI && INET && INFINIBAND_ADDR_TRANS
select SCSI_ISCSI_ATTRS
---help---
Support for the iSCSI Extensions for RDMA (iSER) Protocol
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 7c13db885bf6..54c8fe25c423 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1949,8 +1949,7 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
host->dev.class = &srp_class;
host->dev.parent = device->dev->dma_device;
- snprintf(host->dev.bus_id, BUS_ID_SIZE, "srp-%s-%d",
- device->dev->name, port);
+ dev_set_name(&host->dev, "srp-%s-%d", device->dev->name, port);
if (device_register(&host->dev))
goto free_host;
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 98c4f9a77876..4c9c745a7020 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -5,7 +5,7 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_INPUT) += input-core.o
-input-core-objs := input.o ff-core.o
+input-core-objs := input.o input-compat.o ff-core.o
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c
index 0353601ac3b5..f7c5c14ec12a 100644
--- a/drivers/input/evbug.c
+++ b/drivers/input/evbug.c
@@ -39,7 +39,7 @@ MODULE_LICENSE("GPL");
static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
{
printk(KERN_DEBUG "evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n",
- handle->dev->dev.bus_id, type, code, value);
+ dev_name(&handle->dev->dev), type, code, value);
}
static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
@@ -65,7 +65,7 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
goto err_unregister_handle;
printk(KERN_DEBUG "evbug.c: Connected device: %s (%s at %s)\n",
- dev->dev.bus_id,
+ dev_name(&dev->dev),
dev->name ?: "unknown",
dev->phys ?: "unknown");
@@ -81,7 +81,7 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
static void evbug_disconnect(struct input_handle *handle)
{
printk(KERN_DEBUG "evbug.c: Disconnected device: %s\n",
- handle->dev->dev.bus_id);
+ dev_name(&handle->dev->dev));
input_close_device(handle);
input_unregister_handle(handle);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 1070db330d35..ed8baa0aec3c 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -19,7 +19,7 @@
#include <linux/input.h>
#include <linux/major.h>
#include <linux/device.h>
-#include <linux/compat.h>
+#include "input-compat.h"
struct evdev {
int exist;
@@ -290,187 +290,6 @@ static int evdev_open(struct inode *inode, struct file *file)
return error;
}
-#ifdef CONFIG_COMPAT
-
-struct input_event_compat {
- struct compat_timeval time;
- __u16 type;
- __u16 code;
- __s32 value;
-};
-
-struct ff_periodic_effect_compat {
- __u16 waveform;
- __u16 period;
- __s16 magnitude;
- __s16 offset;
- __u16 phase;
-
- struct ff_envelope envelope;
-
- __u32 custom_len;
- compat_uptr_t custom_data;
-};
-
-struct ff_effect_compat {
- __u16 type;
- __s16 id;
- __u16 direction;
- struct ff_trigger trigger;
- struct ff_replay replay;
-
- union {
- struct ff_constant_effect constant;
- struct ff_ramp_effect ramp;
- struct ff_periodic_effect_compat periodic;
- struct ff_condition_effect condition[2]; /* One for each axis */
- struct ff_rumble_effect rumble;
- } u;
-};
-
-/* Note to the author of this code: did it ever occur to
- you why the ifdefs are needed? Think about it again. -AK */
-#ifdef CONFIG_X86_64
-# define COMPAT_TEST is_compat_task()
-#elif defined(CONFIG_IA64)
-# define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
-#elif defined(CONFIG_S390)
-# define COMPAT_TEST test_thread_flag(TIF_31BIT)
-#elif defined(CONFIG_MIPS)
-# define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
-#else
-# define COMPAT_TEST test_thread_flag(TIF_32BIT)
-#endif
-
-static inline size_t evdev_event_size(void)
-{
- return COMPAT_TEST ?
- sizeof(struct input_event_compat) : sizeof(struct input_event);
-}
-
-static int evdev_event_from_user(const char __user *buffer,
- struct input_event *event)
-{
- if (COMPAT_TEST) {
- struct input_event_compat compat_event;
-
- if (copy_from_user(&compat_event, buffer,
- sizeof(struct input_event_compat)))
- return -EFAULT;
-
- event->time.tv_sec = compat_event.time.tv_sec;
- event->time.tv_usec = compat_event.time.tv_usec;
- event->type = compat_event.type;
- event->code = compat_event.code;
- event->value = compat_event.value;
-
- } else {
- if (copy_from_user(event, buffer, sizeof(struct input_event)))
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int evdev_event_to_user(char __user *buffer,
- const struct input_event *event)
-{
- if (COMPAT_TEST) {
- struct input_event_compat compat_event;
-
- compat_event.time.tv_sec = event->time.tv_sec;
- compat_event.time.tv_usec = event->time.tv_usec;
- compat_event.type = event->type;
- compat_event.code = event->code;
- compat_event.value = event->value;
-
- if (copy_to_user(buffer, &compat_event,
- sizeof(struct input_event_compat)))
- return -EFAULT;
-
- } else {
- if (copy_to_user(buffer, event, sizeof(struct input_event)))
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
- struct ff_effect *effect)
-{
- if (COMPAT_TEST) {
- struct ff_effect_compat *compat_effect;
-
- if (size != sizeof(struct ff_effect_compat))
- return -EINVAL;
-
- /*
- * It so happens that the pointer which needs to be changed
- * is the last field in the structure, so we can copy the
- * whole thing and replace just the pointer.
- */
-
- compat_effect = (struct ff_effect_compat *)effect;
-
- if (copy_from_user(compat_effect, buffer,
- sizeof(struct ff_effect_compat)))
- return -EFAULT;
-
- if (compat_effect->type == FF_PERIODIC &&
- compat_effect->u.periodic.waveform == FF_CUSTOM)
- effect->u.periodic.custom_data =
- compat_ptr(compat_effect->u.periodic.custom_data);
- } else {
- if (size != sizeof(struct ff_effect))
- return -EINVAL;
-
- if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
- return -EFAULT;
- }
-
- return 0;
-}
-
-#else
-
-static inline size_t evdev_event_size(void)
-{
- return sizeof(struct input_event);
-}
-
-static int evdev_event_from_user(const char __user *buffer,
- struct input_event *event)
-{
- if (copy_from_user(event, buffer, sizeof(struct input_event)))
- return -EFAULT;
-
- return 0;
-}
-
-static int evdev_event_to_user(char __user *buffer,
- const struct input_event *event)
-{
- if (copy_to_user(buffer, event, sizeof(struct input_event)))
- return -EFAULT;
-
- return 0;
-}
-
-static int evdev_ff_effect_from_user(const char __user *buffer, size_t size,
- struct ff_effect *effect)
-{
- if (size != sizeof(struct ff_effect))
- return -EINVAL;
-
- if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
- return -EFAULT;
-
- return 0;
-}
-
-#endif /* CONFIG_COMPAT */
-
static ssize_t evdev_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
@@ -490,14 +309,14 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
while (retval < count) {
- if (evdev_event_from_user(buffer + retval, &event)) {
+ if (input_event_from_user(buffer + retval, &event)) {
retval = -EFAULT;
goto out;
}
input_inject_event(&evdev->handle,
event.type, event.code, event.value);
- retval += evdev_event_size();
+ retval += input_event_size();
}
out:
@@ -531,7 +350,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
struct input_event event;
int retval;
- if (count < evdev_event_size())
+ if (count < input_event_size())
return -EINVAL;
if (client->head == client->tail && evdev->exist &&
@@ -546,13 +365,13 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
if (!evdev->exist)
return -ENODEV;
- while (retval + evdev_event_size() <= count &&
+ while (retval + input_event_size() <= count &&
evdev_fetch_next_event(client, &event)) {
- if (evdev_event_to_user(buffer + retval, &event))
+ if (input_event_to_user(buffer + retval, &event))
return -EFAULT;
- retval += evdev_event_size();
+ retval += input_event_size();
}
return retval;
@@ -823,7 +642,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
- if (evdev_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
+ if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
return -EFAULT;
error = input_ff_upload(dev, &effect, file);
@@ -1000,7 +819,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev->handle.handler = handler;
evdev->handle.private = evdev;
- strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id));
+ dev_set_name(&evdev->dev, evdev->name);
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 2880eaae157a..ebf4be5b7c4e 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -530,8 +530,7 @@ static void gameport_init_port(struct gameport *gameport)
mutex_init(&gameport->drv_mutex);
device_initialize(&gameport->dev);
- snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
- "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
+ dev_set_name(&gameport->dev, "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
gameport->dev.bus = &gameport_bus;
gameport->dev.release = gameport_release_port;
if (gameport->parent)
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index 2b282cde4b89..db556b71ddda 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -226,7 +226,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
ns558->gameport = port;
gameport_set_name(port, "NS558 PnP Gameport");
- gameport_set_phys(port, "pnp%s/gameport0", dev->dev.bus_id);
+ gameport_set_phys(port, "pnp%s/gameport0", dev_name(&dev->dev));
port->dev.parent = &dev->dev;
port->io = ioport;
diff --git a/drivers/input/input-compat.c b/drivers/input/input-compat.c
new file mode 100644
index 000000000000..1accb89ae66f
--- /dev/null
+++ b/drivers/input/input-compat.c
@@ -0,0 +1,135 @@
+/*
+ * 32bit compatibility wrappers for the input subsystem.
+ *
+ * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <asm/uaccess.h>
+#include "input-compat.h"
+
+#ifdef CONFIG_COMPAT
+
+int input_event_from_user(const char __user *buffer,
+ struct input_event *event)
+{
+ if (INPUT_COMPAT_TEST) {
+ struct input_event_compat compat_event;
+
+ if (copy_from_user(&compat_event, buffer,
+ sizeof(struct input_event_compat)))
+ return -EFAULT;
+
+ event->time.tv_sec = compat_event.time.tv_sec;
+ event->time.tv_usec = compat_event.time.tv_usec;
+ event->type = compat_event.type;
+ event->code = compat_event.code;
+ event->value = compat_event.value;
+
+ } else {
+ if (copy_from_user(event, buffer, sizeof(struct input_event)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int input_event_to_user(char __user *buffer,
+ const struct input_event *event)
+{
+ if (INPUT_COMPAT_TEST) {
+ struct input_event_compat compat_event;
+
+ compat_event.time.tv_sec = event->time.tv_sec;
+ compat_event.time.tv_usec = event->time.tv_usec;
+ compat_event.type = event->type;
+ compat_event.code = event->code;
+ compat_event.value = event->value;
+
+ if (copy_to_user(buffer, &compat_event,
+ sizeof(struct input_event_compat)))
+ return -EFAULT;
+
+ } else {
+ if (copy_to_user(buffer, event, sizeof(struct input_event)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int input_ff_effect_from_user(const char __user *buffer, size_t size,
+ struct ff_effect *effect)
+{
+ if (INPUT_COMPAT_TEST) {
+ struct ff_effect_compat *compat_effect;
+
+ if (size != sizeof(struct ff_effect_compat))
+ return -EINVAL;
+
+ /*
+ * It so happens that the pointer which needs to be changed
+ * is the last field in the structure, so we can retrieve the
+ * whole thing and replace just the pointer.
+ */
+ compat_effect = (struct ff_effect_compat *)effect;
+
+ if (copy_from_user(compat_effect, buffer,
+ sizeof(struct ff_effect_compat)))
+ return -EFAULT;
+
+ if (compat_effect->type == FF_PERIODIC &&
+ compat_effect->u.periodic.waveform == FF_CUSTOM)
+ effect->u.periodic.custom_data =
+ compat_ptr(compat_effect->u.periodic.custom_data);
+ } else {
+ if (size != sizeof(struct ff_effect))
+ return -EINVAL;
+
+ if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#else
+
+int input_event_from_user(const char __user *buffer,
+ struct input_event *event)
+{
+ if (copy_from_user(event, buffer, sizeof(struct input_event)))
+ return -EFAULT;
+
+ return 0;
+}
+
+int input_event_to_user(char __user *buffer,
+ const struct input_event *event)
+{
+ if (copy_to_user(buffer, event, sizeof(struct input_event)))
+ return -EFAULT;
+
+ return 0;
+}
+
+int input_ff_effect_from_user(const char __user *buffer, size_t size,
+ struct ff_effect *effect)
+{
+ if (size != sizeof(struct ff_effect))
+ return -EINVAL;
+
+ if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
+ return -EFAULT;
+
+ return 0;
+}
+
+#endif /* CONFIG_COMPAT */
+
+EXPORT_SYMBOL_GPL(input_event_from_user);
+EXPORT_SYMBOL_GPL(input_event_to_user);
+EXPORT_SYMBOL_GPL(input_ff_effect_from_user);
diff --git a/drivers/input/input-compat.h b/drivers/input/input-compat.h
new file mode 100644
index 000000000000..47cd9eaee66a
--- /dev/null
+++ b/drivers/input/input-compat.h
@@ -0,0 +1,94 @@
+#ifndef _INPUT_COMPAT_H
+#define _INPUT_COMPAT_H
+
+/*
+ * 32bit compatibility wrappers for the input subsystem.
+ *
+ * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/compiler.h>
+#include <linux/compat.h>
+#include <linux/input.h>
+
+#ifdef CONFIG_COMPAT
+
+/* Note to the author of this code: did it ever occur to
+ you why the ifdefs are needed? Think about it again. -AK */
+#ifdef CONFIG_X86_64
+# define INPUT_COMPAT_TEST is_compat_task()
+#elif defined(CONFIG_IA64)
+# define INPUT_COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
+#elif defined(CONFIG_S390)
+# define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT)
+#elif defined(CONFIG_MIPS)
+# define INPUT_COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
+#else
+# define INPUT_COMPAT_TEST test_thread_flag(TIF_32BIT)
+#endif
+
+struct input_event_compat {
+ struct compat_timeval time;
+ __u16 type;
+ __u16 code;
+ __s32 value;
+};
+
+struct ff_periodic_effect_compat {
+ __u16 waveform;
+ __u16 period;
+ __s16 magnitude;
+ __s16 offset;
+ __u16 phase;
+
+ struct ff_envelope envelope;
+
+ __u32 custom_len;
+ compat_uptr_t custom_data;
+};
+
+struct ff_effect_compat {
+ __u16 type;
+ __s16 id;
+ __u16 direction;
+ struct ff_trigger trigger;
+ struct ff_replay replay;
+
+ union {
+ struct ff_constant_effect constant;
+ struct ff_ramp_effect ramp;
+ struct ff_periodic_effect_compat periodic;
+ struct ff_condition_effect condition[2]; /* One for each axis */
+ struct ff_rumble_effect rumble;
+ } u;
+};
+
+static inline size_t input_event_size(void)
+{
+ return INPUT_COMPAT_TEST ?
+ sizeof(struct input_event_compat) : sizeof(struct input_event);
+}
+
+#else
+
+static inline size_t input_event_size(void)
+{
+ return sizeof(struct input_event);
+}
+
+#endif /* CONFIG_COMPAT */
+
+int input_event_from_user(const char __user *buffer,
+ struct input_event *event);
+
+int input_event_to_user(char __user *buffer,
+ const struct input_event *event);
+
+int input_ff_effect_from_user(const char __user *buffer, size_t size,
+ struct ff_effect *effect);
+
+#endif /* _INPUT_COMPAT_H */
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c13ced3e0d3d..1730d7331a5d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1389,8 +1389,8 @@ int input_register_device(struct input_dev *dev)
if (!dev->setkeycode)
dev->setkeycode = input_default_setkeycode;
- snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
- "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+ dev_set_name(&dev->dev, "input%ld",
+ (unsigned long) atomic_inc_return(&input_no) - 1);
error = device_add(&dev->dev);
if (error)
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index a85b1485e774..6f2366220a50 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -800,7 +800,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
}
}
- strlcpy(joydev->dev.bus_id, joydev->name, sizeof(joydev->dev.bus_id));
+ dev_set_name(&joydev->dev, joydev->name);
joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
joydev->dev.class = &input_class;
joydev->dev.parent = &dev->dev;
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index be5c14a5a0a4..b11419590cfe 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -294,4 +294,28 @@ config JOYSTICK_XPAD_LEDS
This option enables support for the LED which surrounds the Big X on
XBox 360 controller.
+config JOYSTICK_WALKERA0701
+ tristate "Walkera WK-0701 RC transmitter"
+ depends on HIGH_RES_TIMERS && PARPORT
+ help
+ Say Y or M here if you have a Walkera WK-0701 transmitter which is
+ supplied with a ready to fly Walkera helicopters such as HM36,
+ HM37, HM60 and want to use it via parport as a joystick. More
+ information is available: <file:Documentation/input/walkera0701.txt>
+
+ To compile this driver as a module, choose M here: the
+ module will be called walkera0701.
+
+config JOYSTICK_MAPLE
+ tristate "Dreamcast control pad"
+ depends on MAPLE
+ help
+ Say Y here if you have a SEGA Dreamcast and want to use your
+ controller as a joystick.
+
+ Most Dreamcast users will say Y.
+
+ To compile this as a module choose M here: the module will be called
+ maplecontrol.
+
endif
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
index fdbf8c4c2876..f3a8cbe2abb6 100644
--- a/drivers/input/joystick/Makefile
+++ b/drivers/input/joystick/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
+obj-$(CONFIG_JOYSTICK_MAPLE) += maplecontrol.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
@@ -29,4 +30,5 @@ obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o
obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o
+obj-$(CONFIG_JOYSTICK_WALKERA0701) += walkera0701.o
diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
new file mode 100644
index 000000000000..e50047bfe938
--- /dev/null
+++ b/drivers/input/joystick/maplecontrol.c
@@ -0,0 +1,193 @@
+/*
+ * SEGA Dreamcast controller driver
+ * Based on drivers/usb/iforce.c
+ *
+ * Copyright Yaegashi Takeshi, 2001
+ * Adrian McMenamin, 2008
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/maple.h>
+
+MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>");
+MODULE_DESCRIPTION("SEGA Dreamcast controller driver");
+MODULE_LICENSE("GPL");
+
+struct dc_pad {
+ struct input_dev *dev;
+ struct maple_device *mdev;
+};
+
+static void dc_pad_callback(struct mapleq *mq)
+{
+ unsigned short buttons;
+ struct maple_device *mapledev = mq->dev;
+ struct dc_pad *pad = maple_get_drvdata(mapledev);
+ struct input_dev *dev = pad->dev;
+ unsigned char *res = mq->recvbuf;
+
+ buttons = ~le16_to_cpup((__le16 *)(res + 8));
+
+ input_report_abs(dev, ABS_HAT0Y,
+ (buttons & 0x0010 ? -1 : 0) + (buttons & 0x0020 ? 1 : 0));
+ input_report_abs(dev, ABS_HAT0X,
+ (buttons & 0x0040 ? -1 : 0) + (buttons & 0x0080 ? 1 : 0));
+ input_report_abs(dev, ABS_HAT1Y,
+ (buttons & 0x1000 ? -1 : 0) + (buttons & 0x2000 ? 1 : 0));
+ input_report_abs(dev, ABS_HAT1X,
+ (buttons & 0x4000 ? -1 : 0) + (buttons & 0x8000 ? 1 : 0));
+
+ input_report_key(dev, BTN_C, buttons & 0x0001);
+ input_report_key(dev, BTN_B, buttons & 0x0002);
+ input_report_key(dev, BTN_A, buttons & 0x0004);
+ input_report_key(dev, BTN_START, buttons & 0x0008);
+ input_report_key(dev, BTN_Z, buttons & 0x0100);
+ input_report_key(dev, BTN_Y, buttons & 0x0200);
+ input_report_key(dev, BTN_X, buttons & 0x0400);
+ input_report_key(dev, BTN_SELECT, buttons & 0x0800);
+
+ input_report_abs(dev, ABS_GAS, res[10]);
+ input_report_abs(dev, ABS_BRAKE, res[11]);
+ input_report_abs(dev, ABS_X, res[12]);
+ input_report_abs(dev, ABS_Y, res[13]);
+ input_report_abs(dev, ABS_RX, res[14]);
+ input_report_abs(dev, ABS_RY, res[15]);
+}
+
+static int dc_pad_open(struct input_dev *dev)
+{
+ struct dc_pad *pad = dev->dev.platform_data;
+
+ maple_getcond_callback(pad->mdev, dc_pad_callback, HZ/20,
+ MAPLE_FUNC_CONTROLLER);
+
+ return 0;
+}
+
+static void dc_pad_close(struct input_dev *dev)
+{
+ struct dc_pad *pad = dev->dev.platform_data;
+
+ maple_getcond_callback(pad->mdev, dc_pad_callback, 0,
+ MAPLE_FUNC_CONTROLLER);
+}
+
+/* allow the controller to be used */
+static int __devinit probe_maple_controller(struct device *dev)
+{
+ static const short btn_bit[32] = {
+ BTN_C, BTN_B, BTN_A, BTN_START, -1, -1, -1, -1,
+ BTN_Z, BTN_Y, BTN_X, BTN_SELECT, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+ static const short abs_bit[32] = {
+ -1, -1, -1, -1, ABS_HAT0Y, ABS_HAT0Y, ABS_HAT0X, ABS_HAT0X,
+ -1, -1, -1, -1, ABS_HAT1Y, ABS_HAT1Y, ABS_HAT1X, ABS_HAT1X,
+ ABS_GAS, ABS_BRAKE, ABS_X, ABS_Y, ABS_RX, ABS_RY, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+ struct maple_device *mdev = to_maple_dev(dev);
+ struct maple_driver *mdrv = to_maple_driver(dev->driver);
+ int i, error;
+ struct dc_pad *pad;
+ struct input_dev *idev;
+ unsigned long data = be32_to_cpu(mdev->devinfo.function_data[0]);
+
+ pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+ idev = input_allocate_device();
+ if (!pad || !idev) {
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ pad->dev = idev;
+ pad->mdev = mdev;
+
+ idev->open = dc_pad_open;
+ idev->close = dc_pad_close;
+
+ for (i = 0; i < 32; i++) {
+ if (data & (1 << i)) {
+ if (btn_bit[i] >= 0)
+ __set_bit(btn_bit[i], idev->keybit);
+ else if (abs_bit[i] >= 0)
+ __set_bit(abs_bit[i], idev->absbit);
+ }
+ }
+
+ if (idev->keybit[BIT_WORD(BTN_JOYSTICK)])
+ idev->evbit[0] |= BIT_MASK(EV_KEY);
+
+ if (idev->absbit[0])
+ idev->evbit[0] |= BIT_MASK(EV_ABS);
+
+ for (i = ABS_X; i <= ABS_BRAKE; i++)
+ input_set_abs_params(idev, i, 0, 255, 0, 0);
+
+ for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++)
+ input_set_abs_params(idev, i, 1, -1, 0, 0);
+
+ idev->dev.platform_data = pad;
+ idev->dev.parent = &mdev->dev;
+ idev->name = mdev->product_name;
+ idev->id.bustype = BUS_HOST;
+ input_set_drvdata(idev, pad);
+
+ error = input_register_device(idev);
+ if (error)
+ goto fail;
+
+ mdev->driver = mdrv;
+ maple_set_drvdata(mdev, pad);
+
+ return 0;
+
+fail:
+ input_free_device(idev);
+ kfree(pad);
+ maple_set_drvdata(mdev, NULL);
+ return error;
+}
+
+static int __devexit remove_maple_controller(struct device *dev)
+{
+ struct maple_device *mdev = to_maple_dev(dev);
+ struct dc_pad *pad = maple_get_drvdata(mdev);
+
+ mdev->callback = NULL;
+ input_unregister_device(pad->dev);
+ maple_set_drvdata(mdev, NULL);
+ kfree(pad);
+
+ return 0;
+}
+
+static struct maple_driver dc_pad_driver = {
+ .function = MAPLE_FUNC_CONTROLLER,
+ .drv = {
+ .name = "Dreamcast_controller",
+ .probe = probe_maple_controller,
+ .remove = __devexit_p(remove_maple_controller),
+ },
+};
+
+static int __init dc_pad_init(void)
+{
+ return maple_driver_register(&dc_pad_driver);
+}
+
+static void __exit dc_pad_exit(void)
+{
+ maple_driver_unregister(&dc_pad_driver);
+}
+
+module_init(dc_pad_init);
+module_exit(dc_pad_exit);
diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c
new file mode 100644
index 000000000000..4dfa1eed4b7c
--- /dev/null
+++ b/drivers/input/joystick/walkera0701.c
@@ -0,0 +1,292 @@
+/*
+ * Parallel port to Walkera WK-0701 TX joystick
+ *
+ * Copyright (c) 2008 Peter Popovec
+ *
+ * More about driver: <file:Documentation/input/walkera0701.txt>
+ */
+
+/*
+ * 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.
+*/
+
+/* #define WK0701_DEBUG */
+
+#define RESERVE 20000
+#define SYNC_PULSE 1306000
+#define BIN0_PULSE 288000
+#define BIN1_PULSE 438000
+
+#define ANALOG_MIN_PULSE 318000
+#define ANALOG_MAX_PULSE 878000
+#define ANALOG_DELTA 80000
+
+#define BIN_SAMPLE ((BIN0_PULSE + BIN1_PULSE) / 2)
+
+#define NO_SYNC 25
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/parport.h>
+#include <linux/input.h>
+#include <linux/hrtimer.h>
+
+MODULE_AUTHOR("Peter Popovec <popovec@fei.tuke.sk>");
+MODULE_DESCRIPTION("Walkera WK-0701 TX as joystick");
+MODULE_LICENSE("GPL");
+
+static unsigned int walkera0701_pp_no;
+module_param_named(port, walkera0701_pp_no, int, 0);
+MODULE_PARM_DESC(port,
+ "Parallel port adapter for Walkera WK-0701 TX (default is 0)");
+
+/*
+ * For now, only one device is supported, if somebody need more devices, code
+ * can be expanded, one struct walkera_dev per device must be allocated and
+ * set up by walkera0701_connect (release of device by walkera0701_disconnect)
+ */
+
+struct walkera_dev {
+ unsigned char buf[25];
+ u64 irq_time, irq_lasttime;
+ int counter;
+ int ack;
+
+ struct input_dev *input_dev;
+ struct hrtimer timer;
+
+ struct parport *parport;
+ struct pardevice *pardevice;
+};
+
+static struct walkera_dev w_dev;
+
+static inline void walkera0701_parse_frame(struct walkera_dev *w)
+{
+ int i;
+ int val1, val2, val3, val4, val5, val6, val7, val8;
+ int crc1, crc2;
+
+ for (crc1 = crc2 = i = 0; i < 10; i++) {
+ crc1 += w->buf[i] & 7;
+ crc2 += (w->buf[i] & 8) >> 3;
+ }
+ if ((w->buf[10] & 7) != (crc1 & 7))
+ return;
+ if (((w->buf[10] & 8) >> 3) != (((crc1 >> 3) + crc2) & 1))
+ return;
+ for (crc1 = crc2 = 0, i = 11; i < 23; i++) {
+ crc1 += w->buf[i] & 7;
+ crc2 += (w->buf[i] & 8) >> 3;
+ }
+ if ((w->buf[23] & 7) != (crc1 & 7))
+ return;
+ if (((w->buf[23] & 8) >> 3) != (((crc1 >> 3) + crc2) & 1))
+ return;
+ val1 = ((w->buf[0] & 7) * 256 + w->buf[1] * 16 + w->buf[2]) >> 2;
+ val1 *= ((w->buf[0] >> 2) & 2) - 1; /* sign */
+ val2 = (w->buf[2] & 1) << 8 | (w->buf[3] << 4) | w->buf[4];
+ val2 *= (w->buf[2] & 2) - 1; /* sign */
+ val3 = ((w->buf[5] & 7) * 256 + w->buf[6] * 16 + w->buf[7]) >> 2;
+ val3 *= ((w->buf[5] >> 2) & 2) - 1; /* sign */
+ val4 = (w->buf[7] & 1) << 8 | (w->buf[8] << 4) | w->buf[9];
+ val4 *= (w->buf[7] & 2) - 1; /* sign */
+ val5 = ((w->buf[11] & 7) * 256 + w->buf[12] * 16 + w->buf[13]) >> 2;
+ val5 *= ((w->buf[11] >> 2) & 2) - 1; /* sign */
+ val6 = (w->buf[13] & 1) << 8 | (w->buf[14] << 4) | w->buf[15];
+ val6 *= (w->buf[13] & 2) - 1; /* sign */
+ val7 = ((w->buf[16] & 7) * 256 + w->buf[17] * 16 + w->buf[18]) >> 2;
+ val7 *= ((w->buf[16] >> 2) & 2) - 1; /*sign */
+ val8 = (w->buf[18] & 1) << 8 | (w->buf[19] << 4) | w->buf[20];
+ val8 *= (w->buf[18] & 2) - 1; /*sign */
+
+#ifdef WK0701_DEBUG
+ {
+ int magic, magic_bit;
+ magic = (w->buf[21] << 4) | w->buf[22];
+ magic_bit = (w->buf[24] & 8) >> 3;
+ printk(KERN_DEBUG
+ "walkera0701: %4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)\n",
+ val1, val2, val3, val4, val5, val6, val7, val8, magic,
+ magic_bit);
+ }
+#endif
+ input_report_abs(w->input_dev, ABS_X, val2);
+ input_report_abs(w->input_dev, ABS_Y, val1);
+ input_report_abs(w->input_dev, ABS_Z, val6);
+ input_report_abs(w->input_dev, ABS_THROTTLE, val3);
+ input_report_abs(w->input_dev, ABS_RUDDER, val4);
+ input_report_abs(w->input_dev, ABS_MISC, val7);
+ input_report_key(w->input_dev, BTN_GEAR_DOWN, val5 > 0);
+}
+
+static inline int read_ack(struct pardevice *p)
+{
+ return parport_read_status(p->port) & 0x40;
+}
+
+/* falling edge, prepare to BIN value calculation */
+static void walkera0701_irq_handler(void *handler_data)
+{
+ u64 pulse_time;
+ struct walkera_dev *w = handler_data;
+
+ w->irq_time = ktime_to_ns(ktime_get());
+ pulse_time = w->irq_time - w->irq_lasttime;
+ w->irq_lasttime = w->irq_time;
+
+ /* cancel timer, if in handler or active do resync */
+ if (unlikely(0 != hrtimer_try_to_cancel(&w->timer))) {
+ w->counter = NO_SYNC;
+ return;
+ }
+
+ if (w->counter < NO_SYNC) {
+ if (w->ack) {
+ pulse_time -= BIN1_PULSE;
+ w->buf[w->counter] = 8;
+ } else {
+ pulse_time -= BIN0_PULSE;
+ w->buf[w->counter] = 0;
+ }
+ if (w->counter == 24) { /* full frame */
+ walkera0701_parse_frame(w);
+ w->counter = NO_SYNC;
+ if (abs(pulse_time - SYNC_PULSE) < RESERVE) /* new frame sync */
+ w->counter = 0;
+ } else {
+ if ((pulse_time > (ANALOG_MIN_PULSE - RESERVE)
+ && (pulse_time < (ANALOG_MAX_PULSE + RESERVE)))) {
+ pulse_time -= (ANALOG_MIN_PULSE - RESERVE);
+ pulse_time = (u32) pulse_time / ANALOG_DELTA; /* overtiping is safe, pulsetime < s32.. */
+ w->buf[w->counter++] |= (pulse_time & 7);
+ } else
+ w->counter = NO_SYNC;
+ }
+ } else if (abs(pulse_time - SYNC_PULSE - BIN0_PULSE) <
+ RESERVE + BIN1_PULSE - BIN0_PULSE) /* frame sync .. */
+ w->counter = 0;
+
+ hrtimer_start(&w->timer, ktime_set(0, BIN_SAMPLE), HRTIMER_MODE_REL);
+}
+
+static enum hrtimer_restart timer_handler(struct hrtimer
+ *handle)
+{
+ struct walkera_dev *w;
+
+ w = container_of(handle, struct walkera_dev, timer);
+ w->ack = read_ack(w->pardevice);
+
+ return HRTIMER_NORESTART;
+}
+
+static int walkera0701_open(struct input_dev *dev)
+{
+ struct walkera_dev *w = input_get_drvdata(dev);
+
+ parport_enable_irq(w->parport);
+ return 0;
+}
+
+static void walkera0701_close(struct input_dev *dev)
+{
+ struct walkera_dev *w = input_get_drvdata(dev);
+
+ parport_disable_irq(w->parport);
+}
+
+static int walkera0701_connect(struct walkera_dev *w, int parport)
+{
+ int err = -ENODEV;
+
+ w->parport = parport_find_number(parport);
+ if (w->parport == NULL)
+ return -ENODEV;
+
+ if (w->parport->irq == -1) {
+ printk(KERN_ERR "walkera0701: parport without interrupt\n");
+ goto init_err;
+ }
+
+ err = -EBUSY;
+ w->pardevice = parport_register_device(w->parport, "walkera0701",
+ NULL, NULL, walkera0701_irq_handler,
+ PARPORT_DEV_EXCL, w);
+ if (!w->pardevice)
+ goto init_err;
+
+ if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT))
+ goto init_err1;
+
+ if (parport_claim(w->pardevice))
+ goto init_err1;
+
+ w->input_dev = input_allocate_device();
+ if (!w->input_dev)
+ goto init_err2;
+
+ input_set_drvdata(w->input_dev, w);
+ w->input_dev->name = "Walkera WK-0701 TX";
+ w->input_dev->phys = w->parport->name;
+ w->input_dev->id.bustype = BUS_PARPORT;
+
+ /* TODO what id vendor/product/version ? */
+ w->input_dev->id.vendor = 0x0001;
+ w->input_dev->id.product = 0x0001;
+ w->input_dev->id.version = 0x0100;
+ w->input_dev->open = walkera0701_open;
+ w->input_dev->close = walkera0701_close;
+
+ w->input_dev->evbit[0] = BIT(EV_ABS) | BIT_MASK(EV_KEY);
+ w->input_dev->keybit[BIT_WORD(BTN_GEAR_DOWN)] = BIT_MASK(BTN_GEAR_DOWN);
+
+ input_set_abs_params(w->input_dev, ABS_X, -512, 512, 0, 0);
+ input_set_abs_params(w->input_dev, ABS_Y, -512, 512, 0, 0);
+ input_set_abs_params(w->input_dev, ABS_Z, -512, 512, 0, 0);
+ input_set_abs_params(w->input_dev, ABS_THROTTLE, -512, 512, 0, 0);
+ input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0);
+ input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0);
+
+ err = input_register_device(w->input_dev);
+ if (err)
+ goto init_err3;
+
+ hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ w->timer.function = timer_handler;
+ return 0;
+
+ init_err3:
+ input_free_device(w->input_dev);
+ init_err2:
+ parport_release(w->pardevice);
+ init_err1:
+ parport_unregister_device(w->pardevice);
+ init_err:
+ parport_put_port(w->parport);
+ return err;
+}
+
+static void walkera0701_disconnect(struct walkera_dev *w)
+{
+ hrtimer_cancel(&w->timer);
+ input_unregister_device(w->input_dev);
+ parport_release(w->pardevice);
+ parport_unregister_device(w->pardevice);
+ parport_put_port(w->parport);
+}
+
+static int __init walkera0701_init(void)
+{
+ return walkera0701_connect(&w_dev, walkera0701_pp_no);
+}
+
+static void __exit walkera0701_exit(void)
+{
+ walkera0701_disconnect(&w_dev);
+}
+
+module_init(walkera0701_init);
+module_exit(walkera0701_exit);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index efd70a974591..35561689ff38 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -268,6 +268,15 @@ config KEYBOARD_PXA27x
To compile this driver as a module, choose M here: the
module will be called pxa27x_keypad.
+config KEYBOARD_PXA930_ROTARY
+ tristate "PXA930/PXA935 Enhanced Rotary Controller Support"
+ depends on CPU_PXA930 || CPU_PXA935
+ help
+ Enable support for PXA930/PXA935 Enhanced Rotary Controller.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pxa930_rotary.
+
config KEYBOARD_AAED2000
tristate "AAED-2000 keyboard"
depends on MACH_AAED2000
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 0edc8f285d1c..36351e1190f9 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
+obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o
obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 379b7ff354ec..c3c8b9bc40ae 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and
/*
* Scancode to keycode tables. These are just the default setting, and
- * are loadable via an userland utility.
+ * are loadable via a userland utility.
*/
static const unsigned short atkbd_set2_keycode[512] = {
@@ -884,6 +884,39 @@ static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd)
}
/*
+ * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release
+ * for its volume buttons
+ */
+static void atkbd_hp_zv6100_keymap_fixup(struct atkbd *atkbd)
+{
+ const unsigned int forced_release_keys[] = {
+ 0xae, 0xb0,
+ };
+ int i;
+
+ if (atkbd->set == 2)
+ for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
+ __set_bit(forced_release_keys[i],
+ atkbd->force_release_mask);
+}
+
+/*
+ * Samsung NC10 with Fn+F? key release not working
+ */
+static void atkbd_samsung_keymap_fixup(struct atkbd *atkbd)
+{
+ const unsigned int forced_release_keys[] = {
+ 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9,
+ };
+ int i;
+
+ if (atkbd->set == 2)
+ for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
+ __set_bit(forced_release_keys[i],
+ atkbd->force_release_mask);
+}
+
+/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
*/
@@ -1476,6 +1509,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_dell_laptop_keymap_fixup,
},
{
+ .ident = "Dell Laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
+ },
+ .callback = atkbd_setup_fixup,
+ .driver_data = atkbd_dell_laptop_keymap_fixup,
+ },
+ {
.ident = "HP 2133",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -1485,6 +1527,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_hp_keymap_fixup,
},
{
+ .ident = "HP Pavilion ZV6100",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"),
+ },
+ .callback = atkbd_setup_fixup,
+ .driver_data = atkbd_hp_zv6100_keymap_fixup,
+ },
+ {
.ident = "Inventec Symphony",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"),
@@ -1493,6 +1544,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.callback = atkbd_setup_fixup,
.driver_data = atkbd_inventec_keymap_fixup,
},
+ {
+ .ident = "Samsung NC10",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
+ },
+ .callback = atkbd_setup_fixup,
+ .driver_data = atkbd_samsung_keymap_fixup,
+ },
{ }
};
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 05f3f43582c2..ad67d763fdbd 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -98,6 +98,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
input->id.product = 0x0001;
input->id.version = 0x0100;
+ /* Enable auto repeat feature of Linux input subsystem */
+ if (pdata->rep)
+ __set_bit(EV_REP, input->evbit);
+
ddata->input = input;
for (i = 0; i < pdata->nbuttons; i++) {
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 71c1971abf80..6f356705ee3b 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -47,6 +47,7 @@
MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("serio:ty03pr25id00ex*");
#define HIL_KBD_MAX_LENGTH 16
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index db22fd9b4cf2..3f3d1198cdb1 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -122,14 +122,10 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
/* read the keypad status */
if (cpu_is_omap24xx()) {
- int i;
- for (i = 0; i < omap_kp->rows; i++)
- disable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
-
/* read the keypad status */
for (col = 0; col < omap_kp->cols; col++) {
set_col_gpio_val(omap_kp, ~(1 << col));
- state[col] = ~(get_row_gpio_val(omap_kp)) & 0x3f;
+ state[col] = ~(get_row_gpio_val(omap_kp)) & 0xff;
}
set_col_gpio_val(omap_kp, 0);
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
new file mode 100644
index 000000000000..95fbba470e65
--- /dev/null
+++ b/drivers/input/keyboard/pxa930_rotary.c
@@ -0,0 +1,212 @@
+/*
+ * Driver for the enhanced rotary controller on pxa930 and pxa935
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/pxa930_rotary.h>
+
+#define SBCR (0x04)
+#define ERCR (0x0c)
+
+#define SBCR_ERSB (1 << 5)
+
+struct pxa930_rotary {
+ struct input_dev *input_dev;
+ void __iomem *mmio_base;
+ int last_ercr;
+
+ struct pxa930_rotary_platform_data *pdata;
+};
+
+static void clear_sbcr(struct pxa930_rotary *r)
+{
+ uint32_t sbcr = __raw_readl(r->mmio_base + SBCR);
+
+ __raw_writel(sbcr | SBCR_ERSB, r->mmio_base + SBCR);
+ __raw_writel(sbcr & ~SBCR_ERSB, r->mmio_base + SBCR);
+}
+
+static irqreturn_t rotary_irq(int irq, void *dev_id)
+{
+ struct pxa930_rotary *r = dev_id;
+ struct pxa930_rotary_platform_data *pdata = r->pdata;
+ int ercr, delta, key;
+
+ ercr = __raw_readl(r->mmio_base + ERCR) & 0xf;
+ clear_sbcr(r);
+
+ delta = ercr - r->last_ercr;
+ if (delta == 0)
+ return IRQ_HANDLED;
+
+ r->last_ercr = ercr;
+
+ if (pdata->up_key && pdata->down_key) {
+ key = (delta > 0) ? pdata->up_key : pdata->down_key;
+ input_report_key(r->input_dev, key, 1);
+ input_sync(r->input_dev);
+ input_report_key(r->input_dev, key, 0);
+ } else
+ input_report_rel(r->input_dev, pdata->rel_code, delta);
+
+ input_sync(r->input_dev);
+
+ return IRQ_HANDLED;
+}
+
+static int pxa930_rotary_open(struct input_dev *dev)
+{
+ struct pxa930_rotary *r = input_get_drvdata(dev);
+
+ clear_sbcr(r);
+
+ return 0;
+}
+
+static void pxa930_rotary_close(struct input_dev *dev)
+{
+ struct pxa930_rotary *r = input_get_drvdata(dev);
+
+ clear_sbcr(r);
+}
+
+static int __devinit pxa930_rotary_probe(struct platform_device *pdev)
+{
+ struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data;
+ struct pxa930_rotary *r;
+ struct input_dev *input_dev;
+ struct resource *res;
+ int irq;
+ int err;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "no irq for rotary controller\n");
+ return -ENXIO;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "no I/O memory defined\n");
+ return -ENXIO;
+ }
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ return -EINVAL;
+ }
+
+ r = kzalloc(sizeof(struct pxa930_rotary), GFP_KERNEL);
+ if (!r)
+ return -ENOMEM;
+
+ r->mmio_base = ioremap_nocache(res->start, resource_size(res));
+ if (r->mmio_base == NULL) {
+ dev_err(&pdev->dev, "failed to remap IO memory\n");
+ err = -ENXIO;
+ goto failed_free;
+ }
+
+ r->pdata = pdata;
+ platform_set_drvdata(pdev, r);
+
+ /* allocate and register the input device */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(&pdev->dev, "failed to allocate input device\n");
+ err = -ENOMEM;
+ goto failed_free_io;
+ }
+
+ input_dev->name = pdev->name;
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->open = pxa930_rotary_open;
+ input_dev->close = pxa930_rotary_close;
+ input_dev->dev.parent = &pdev->dev;
+
+ if (pdata->up_key && pdata->down_key) {
+ __set_bit(pdata->up_key, input_dev->keybit);
+ __set_bit(pdata->down_key, input_dev->keybit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ } else {
+ __set_bit(pdata->rel_code, input_dev->relbit);
+ __set_bit(EV_REL, input_dev->evbit);
+ }
+
+ r->input_dev = input_dev;
+ input_set_drvdata(input_dev, r);
+
+ err = request_irq(irq, rotary_irq, IRQF_DISABLED,
+ "enhanced rotary", r);
+ if (err) {
+ dev_err(&pdev->dev, "failed to request IRQ\n");
+ goto failed_free_input;
+ }
+
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register input device\n");
+ goto failed_free_irq;
+ }
+
+ return 0;
+
+failed_free_irq:
+ free_irq(irq, r);
+failed_free_input:
+ input_free_device(input_dev);
+failed_free_io:
+ iounmap(r->mmio_base);
+failed_free:
+ kfree(r);
+ return err;
+}
+
+static int __devexit pxa930_rotary_remove(struct platform_device *pdev)
+{
+ struct pxa930_rotary *r = platform_get_drvdata(pdev);
+
+ free_irq(platform_get_irq(pdev, 0), r);
+ input_unregister_device(r->input_dev);
+ iounmap(r->mmio_base);
+ platform_set_drvdata(pdev, NULL);
+ kfree(r);
+
+ return 0;
+}
+
+static struct platform_driver pxa930_rotary_driver = {
+ .driver = {
+ .name = "pxa930-rotary",
+ .owner = THIS_MODULE,
+ },
+ .probe = pxa930_rotary_probe,
+ .remove = __devexit_p(pxa930_rotary_remove),
+};
+
+static int __init pxa930_rotary_init(void)
+{
+ return platform_driver_register(&pxa930_rotary_driver);
+}
+module_init(pxa930_rotary_init);
+
+static void __exit pxa930_rotary_exit(void)
+{
+ platform_driver_unregister(&pxa930_rotary_driver);
+}
+module_exit(pxa930_rotary_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for PXA93x Enhanced Rotary Controller");
+MODULE_AUTHOR("Yao Yong <yaoyong@marvell.com>");
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 199055db5082..67e5553f699a 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -220,4 +220,11 @@ config HP_SDC_RTC
Say Y here if you want to support the built-in real time clock
of the HP SDC controller.
+config INPUT_PCF50633_PMU
+ tristate "PCF50633 PMU events"
+ depends on MFD_PCF50633
+ help
+ Say Y to include support for delivering PMU events via input
+ layer on NXP PCF50633.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index d7db2aeb8a98..bb62e6efacf3 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
+obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c
index d82f7f727f7a..71b82434264d 100644
--- a/drivers/input/misc/apanel.c
+++ b/drivers/input/misc/apanel.c
@@ -57,7 +57,7 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX];
struct apanel {
struct input_polled_dev *ipdev;
- struct i2c_client client;
+ struct i2c_client *client;
unsigned short keymap[MAX_PANEL_KEYS];
u16 nkeys;
u16 led_bits;
@@ -66,16 +66,7 @@ struct apanel {
};
-static int apanel_probe(struct i2c_adapter *, int, int);
-
-/* for now, we only support one address */
-static unsigned short normal_i2c[] = {0, I2C_CLIENT_END};
-static unsigned short ignore = I2C_CLIENT_END;
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
+static int apanel_probe(struct i2c_client *, const struct i2c_device_id *);
static void report_key(struct input_dev *input, unsigned keycode)
{
@@ -103,12 +94,12 @@ static void apanel_poll(struct input_polled_dev *ipdev)
s32 data;
int i;
- data = i2c_smbus_read_word_data(&ap->client, cmd);
+ data = i2c_smbus_read_word_data(ap->client, cmd);
if (data < 0)
return; /* ignore errors (due to ACPI??) */
/* write back to clear latch */
- i2c_smbus_write_word_data(&ap->client, cmd, 0);
+ i2c_smbus_write_word_data(ap->client, cmd, 0);
if (!data)
return;
@@ -124,7 +115,7 @@ static void led_update(struct work_struct *work)
{
struct apanel *ap = container_of(work, struct apanel, led_work);
- i2c_smbus_write_word_data(&ap->client, 0x10, ap->led_bits);
+ i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits);
}
static void mail_led_set(struct led_classdev *led,
@@ -140,7 +131,7 @@ static void mail_led_set(struct led_classdev *led,
schedule_work(&ap->led_work);
}
-static int apanel_detach_client(struct i2c_client *client)
+static int apanel_remove(struct i2c_client *client)
{
struct apanel *ap = i2c_get_clientdata(client);
@@ -148,43 +139,33 @@ static int apanel_detach_client(struct i2c_client *client)
led_classdev_unregister(&ap->mail_led);
input_unregister_polled_device(ap->ipdev);
- i2c_detach_client(&ap->client);
input_free_polled_device(ap->ipdev);
return 0;
}
-/* Function is invoked for every i2c adapter. */
-static int apanel_attach_adapter(struct i2c_adapter *adap)
-{
- dev_dbg(&adap->dev, APANEL ": attach adapter id=%d\n", adap->id);
-
- /* Our device is connected only to i801 on laptop */
- if (adap->id != I2C_HW_SMBUS_I801)
- return -ENODEV;
-
- return i2c_probe(adap, &addr_data, apanel_probe);
-}
-
static void apanel_shutdown(struct i2c_client *client)
{
- apanel_detach_client(client);
+ apanel_remove(client);
}
+static struct i2c_device_id apanel_id[] = {
+ { "fujitsu_apanel", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, apanel_id);
+
static struct i2c_driver apanel_driver = {
.driver = {
.name = APANEL,
},
- .attach_adapter = &apanel_attach_adapter,
- .detach_client = &apanel_detach_client,
+ .probe = &apanel_probe,
+ .remove = &apanel_remove,
.shutdown = &apanel_shutdown,
+ .id_table = apanel_id,
};
static struct apanel apanel = {
- .client = {
- .driver = &apanel_driver,
- .name = APANEL,
- },
.keymap = {
[0] = KEY_MAIL,
[1] = KEY_WWW,
@@ -204,7 +185,8 @@ static struct apanel apanel = {
};
/* NB: Only one panel on the i2c. */
-static int apanel_probe(struct i2c_adapter *bus, int address, int kind)
+static int apanel_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct apanel *ap;
struct input_polled_dev *ipdev;
@@ -212,9 +194,6 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind)
u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
int i, err = -ENOMEM;
- dev_dbg(&bus->dev, APANEL ": probe adapter %p addr %d kind %d\n",
- bus, address, kind);
-
ap = &apanel;
ipdev = input_allocate_polled_device();
@@ -222,18 +201,13 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind)
goto out1;
ap->ipdev = ipdev;
- ap->client.adapter = bus;
- ap->client.addr = address;
-
- i2c_set_clientdata(&ap->client, ap);
+ ap->client = client;
- err = i2c_attach_client(&ap->client);
- if (err)
- goto out2;
+ i2c_set_clientdata(client, ap);
- err = i2c_smbus_write_word_data(&ap->client, cmd, 0);
+ err = i2c_smbus_write_word_data(client, cmd, 0);
if (err) {
- dev_warn(&ap->client.dev, APANEL ": smbus write error %d\n",
+ dev_warn(&client->dev, APANEL ": smbus write error %d\n",
err);
goto out3;
}
@@ -246,7 +220,7 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind)
idev->name = APANEL_NAME " buttons";
idev->phys = "apanel/input0";
idev->id.bustype = BUS_HOST;
- idev->dev.parent = &ap->client.dev;
+ idev->dev.parent = &client->dev;
set_bit(EV_KEY, idev->evbit);
@@ -264,7 +238,7 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind)
INIT_WORK(&ap->led_work, led_update);
if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
- err = led_classdev_register(&ap->client.dev, &ap->mail_led);
+ err = led_classdev_register(&client->dev, &ap->mail_led);
if (err)
goto out4;
}
@@ -273,8 +247,6 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind)
out4:
input_unregister_polled_device(ipdev);
out3:
- i2c_detach_client(&ap->client);
-out2:
input_free_polled_device(ipdev);
out1:
return err;
@@ -301,6 +273,7 @@ static int __init apanel_init(void)
void __iomem *bios;
const void __iomem *p;
u8 devno;
+ unsigned char i2c_addr;
int found = 0;
bios = ioremap(0xF0000, 0x10000); /* Can't fail */
@@ -313,7 +286,7 @@ static int __init apanel_init(void)
/* just use the first address */
p += 8;
- normal_i2c[0] = readb(p+3) >> 1;
+ i2c_addr = readb(p + 3) >> 1;
for ( ; (devno = readb(p)) & 0x7f; p += 4) {
unsigned char method, slave, chip;
@@ -322,7 +295,7 @@ static int __init apanel_init(void)
chip = readb(p + 2);
slave = readb(p + 3) >> 1;
- if (slave != normal_i2c[0]) {
+ if (slave != i2c_addr) {
pr_notice(APANEL ": only one SMBus slave "
"address supported, skiping device...\n");
continue;
diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c
new file mode 100644
index 000000000000..039dcb00ebd9
--- /dev/null
+++ b/drivers/input/misc/pcf50633-input.c
@@ -0,0 +1,132 @@
+/* NXP PCF50633 Input Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+
+#include <linux/mfd/pcf50633/core.h>
+
+#define PCF50633_OOCSTAT_ONKEY 0x01
+#define PCF50633_REG_OOCSTAT 0x12
+#define PCF50633_REG_OOCMODE 0x10
+
+struct pcf50633_input {
+ struct pcf50633 *pcf;
+ struct input_dev *input_dev;
+};
+
+static void
+pcf50633_input_irq(int irq, void *data)
+{
+ struct pcf50633_input *input;
+ int onkey_released;
+
+ input = data;
+
+ /* We report only one event depending on the key press status */
+ onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)
+ & PCF50633_OOCSTAT_ONKEY;
+
+ if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)
+ input_report_key(input->input_dev, KEY_POWER, 1);
+ else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)
+ input_report_key(input->input_dev, KEY_POWER, 0);
+
+ input_sync(input->input_dev);
+}
+
+static int __devinit pcf50633_input_probe(struct platform_device *pdev)
+{
+ struct pcf50633_input *input;
+ struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
+ struct input_dev *input_dev;
+ int ret;
+
+
+ input = kzalloc(sizeof(*input), GFP_KERNEL);
+ if (!input)
+ return -ENOMEM;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ kfree(input);
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, input);
+ input->pcf = pdata->pcf;
+ input->input_dev = input_dev;
+
+ input_dev->name = "PCF50633 PMU events";
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
+ set_bit(KEY_POWER, input_dev->keybit);
+
+ ret = input_register_device(input_dev);
+ if (ret) {
+ input_free_device(input_dev);
+ kfree(input);
+ return ret;
+ }
+ pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYR,
+ pcf50633_input_irq, input);
+ pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYF,
+ pcf50633_input_irq, input);
+
+ return 0;
+}
+
+static int __devexit pcf50633_input_remove(struct platform_device *pdev)
+{
+ struct pcf50633_input *input = platform_get_drvdata(pdev);
+
+ pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);
+ pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);
+
+ input_unregister_device(input->input_dev);
+ kfree(input);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_input_driver = {
+ .driver = {
+ .name = "pcf50633-input",
+ },
+ .probe = pcf50633_input_probe,
+ .remove = __devexit_p(pcf50633_input_remove),
+};
+
+static int __init pcf50633_input_init(void)
+{
+ return platform_driver_register(&pcf50633_input_driver);
+}
+module_init(pcf50633_input_init);
+
+static void __exit pcf50633_input_exit(void)
+{
+ platform_driver_unregister(&pcf50633_input_driver);
+}
+module_exit(pcf50633_input_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 input driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-input");
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
index 43aaa5cebd12..d6a30cee7bc7 100644
--- a/drivers/input/misc/pcspkr.c
+++ b/drivers/input/misc/pcspkr.c
@@ -52,13 +52,13 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
spin_lock_irqsave(&i8253_lock, flags);
if (count) {
- /* enable counter 2 */
- outb_p(inb_p(0x61) | 3, 0x61);
/* set command for counter 2, 2 byte write */
outb_p(0xB6, 0x43);
/* select desired HZ */
outb_p(count & 0xff, 0x42);
outb((count >> 8) & 0xff, 0x42);
+ /* enable counter 2 */
+ outb_p(inb_p(0x61) | 3, 0x61);
} else {
/* disable counter 2 */
outb(inb_p(0x61) & 0xFC, 0x61);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 223d56d5555b..46b7caeb2817 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -37,6 +37,7 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uinput.h>
+#include "../input-compat.h"
static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
@@ -78,6 +79,7 @@ static struct uinput_request* uinput_request_find(struct uinput_device *udev, in
/* Find an input request, by ID. Returns NULL if the ID isn't valid. */
if (id >= UINPUT_NUM_REQUESTS || id < 0)
return NULL;
+
return udev->requests[id];
}
@@ -127,6 +129,17 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff
struct uinput_request request;
int retval;
+ /*
+ * uinput driver does not currently support periodic effects with
+ * custom waveform since it does not have a way to pass buffer of
+ * samples (custom_data) to userspace. If ever there is a device
+ * supporting custom waveforms we would need to define an additional
+ * ioctl (UI_UPLOAD_SAMPLES) but for now we just bail out.
+ */
+ if (effect->type == FF_PERIODIC &&
+ effect->u.periodic.waveform == FF_CUSTOM)
+ return -EINVAL;
+
request.id = -1;
init_completion(&request.done);
request.code = UI_FF_UPLOAD;
@@ -353,15 +366,15 @@ static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char
{
struct input_event ev;
- if (count != sizeof(struct input_event))
+ if (count < input_event_size())
return -EINVAL;
- if (copy_from_user(&ev, buffer, sizeof(struct input_event)))
+ if (input_event_from_user(buffer, &ev))
return -EFAULT;
input_event(udev->dev, ev.type, ev.code, ev.value);
- return sizeof(struct input_event);
+ return input_event_size();
}
static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -407,13 +420,13 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
goto out;
}
- while (udev->head != udev->tail && retval + sizeof(struct input_event) <= count) {
- if (copy_to_user(buffer + retval, &udev->buff[udev->tail], sizeof(struct input_event))) {
+ while (udev->head != udev->tail && retval + input_event_size() <= count) {
+ if (input_event_to_user(buffer + retval, &udev->buff[udev->tail])) {
retval = -EFAULT;
goto out;
}
udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
- retval += sizeof(struct input_event);
+ retval += input_event_size();
}
out:
@@ -444,6 +457,93 @@ static int uinput_release(struct inode *inode, struct file *file)
return 0;
}
+#ifdef CONFIG_COMPAT
+struct uinput_ff_upload_compat {
+ int request_id;
+ int retval;
+ struct ff_effect_compat effect;
+ struct ff_effect_compat old;
+};
+
+static int uinput_ff_upload_to_user(char __user *buffer,
+ const struct uinput_ff_upload *ff_up)
+{
+ if (INPUT_COMPAT_TEST) {
+ struct uinput_ff_upload_compat ff_up_compat;
+
+ ff_up_compat.request_id = ff_up->request_id;
+ ff_up_compat.retval = ff_up->retval;
+ /*
+ * It so happens that the pointer that gives us the trouble
+ * is the last field in the structure. Since we don't support
+ * custom waveforms in uinput anyway we can just copy the whole
+ * thing (to the compat size) and ignore the pointer.
+ */
+ memcpy(&ff_up_compat.effect, &ff_up->effect,
+ sizeof(struct ff_effect_compat));
+ memcpy(&ff_up_compat.old, &ff_up->old,
+ sizeof(struct ff_effect_compat));
+
+ if (copy_to_user(buffer, &ff_up_compat,
+ sizeof(struct uinput_ff_upload_compat)))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(buffer, ff_up,
+ sizeof(struct uinput_ff_upload)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int uinput_ff_upload_from_user(const char __user *buffer,
+ struct uinput_ff_upload *ff_up)
+{
+ if (INPUT_COMPAT_TEST) {
+ struct uinput_ff_upload_compat ff_up_compat;
+
+ if (copy_from_user(&ff_up_compat, buffer,
+ sizeof(struct uinput_ff_upload_compat)))
+ return -EFAULT;
+
+ ff_up->request_id = ff_up_compat.request_id;
+ ff_up->retval = ff_up_compat.retval;
+ memcpy(&ff_up->effect, &ff_up_compat.effect,
+ sizeof(struct ff_effect_compat));
+ memcpy(&ff_up->old, &ff_up_compat.old,
+ sizeof(struct ff_effect_compat));
+
+ } else {
+ if (copy_from_user(ff_up, buffer,
+ sizeof(struct uinput_ff_upload)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#else
+
+static int uinput_ff_upload_to_user(char __user *buffer,
+ const struct uinput_ff_upload *ff_up)
+{
+ if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int uinput_ff_upload_from_user(const char __user *buffer,
+ struct uinput_ff_upload *ff_up)
+{
+ if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload)))
+ return -EFAULT;
+
+ return 0;
+}
+
+#endif
+
#define uinput_set_bit(_arg, _bit, _max) \
({ \
int __ret = 0; \
@@ -455,19 +555,17 @@ static int uinput_release(struct inode *inode, struct file *file)
__ret; \
})
-static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
+ unsigned long arg, void __user *p)
{
int retval;
- struct uinput_device *udev;
- void __user *p = (void __user *)arg;
+ struct uinput_device *udev = file->private_data;
struct uinput_ff_upload ff_up;
struct uinput_ff_erase ff_erase;
struct uinput_request *req;
int length;
char *phys;
- udev = file->private_data;
-
retval = mutex_lock_interruptible(&udev->mutex);
if (retval)
return retval;
@@ -549,26 +647,24 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case UI_BEGIN_FF_UPLOAD:
- if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
- retval = -EFAULT;
+ retval = uinput_ff_upload_from_user(p, &ff_up);
+ if (retval)
break;
- }
+
req = uinput_request_find(udev, ff_up.request_id);
- if (!(req && req->code == UI_FF_UPLOAD && req->u.upload.effect)) {
+ if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) {
retval = -EINVAL;
break;
}
+
ff_up.retval = 0;
- memcpy(&ff_up.effect, req->u.upload.effect, sizeof(struct ff_effect));
+ ff_up.effect = *req->u.upload.effect;
if (req->u.upload.old)
- memcpy(&ff_up.old, req->u.upload.old, sizeof(struct ff_effect));
+ ff_up.old = *req->u.upload.old;
else
memset(&ff_up.old, 0, sizeof(struct ff_effect));
- if (copy_to_user(p, &ff_up, sizeof(ff_up))) {
- retval = -EFAULT;
- break;
- }
+ retval = uinput_ff_upload_to_user(p, &ff_up);
break;
case UI_BEGIN_FF_ERASE:
@@ -576,29 +672,34 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
+
req = uinput_request_find(udev, ff_erase.request_id);
- if (!(req && req->code == UI_FF_ERASE)) {
+ if (!req || req->code != UI_FF_ERASE) {
retval = -EINVAL;
break;
}
+
ff_erase.retval = 0;
ff_erase.effect_id = req->u.effect_id;
if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
retval = -EFAULT;
break;
}
+
break;
case UI_END_FF_UPLOAD:
- if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
- retval = -EFAULT;
+ retval = uinput_ff_upload_from_user(p, &ff_up);
+ if (retval)
break;
- }
+
req = uinput_request_find(udev, ff_up.request_id);
- if (!(req && req->code == UI_FF_UPLOAD && req->u.upload.effect)) {
+ if (!req || req->code != UI_FF_UPLOAD ||
+ !req->u.upload.effect) {
retval = -EINVAL;
break;
}
+
req->retval = ff_up.retval;
uinput_request_done(udev, req);
break;
@@ -608,11 +709,13 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
retval = -EFAULT;
break;
}
+
req = uinput_request_find(udev, ff_erase.request_id);
- if (!(req && req->code == UI_FF_ERASE)) {
+ if (!req || req->code != UI_FF_ERASE) {
retval = -EINVAL;
break;
}
+
req->retval = ff_erase.retval;
uinput_request_done(udev, req);
break;
@@ -626,6 +729,18 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return retval;
}
+static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return uinput_ioctl_handler(file, cmd, arg, (void __user *)arg);
+}
+
+#ifdef CONFIG_COMPAT
+static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
+}
+#endif
+
static const struct file_operations uinput_fops = {
.owner = THIS_MODULE,
.open = uinput_open,
@@ -634,6 +749,9 @@ static const struct file_operations uinput_fops = {
.write = uinput_write,
.poll = uinput_poll,
.unlocked_ioctl = uinput_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = uinput_compat_ioctl,
+#endif
};
static struct miscdevice uinput_misc = {
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 4e9934259775..093c8c1bca74 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -286,4 +286,10 @@ config MOUSE_GPIO
To compile this driver as a module, choose M here: the
module will be called gpio_mouse.
+config MOUSE_PXA930_TRKBALL
+ tristate "PXA930 Trackball mouse"
+ depends on CPU_PXA930 || CPU_PXA935
+ help
+ Say Y here to support PXA930 Trackball mouse.
+
endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 96f1dd8037f8..8c8a1f236e28 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -4,19 +4,20 @@
# Each configuration option enables a list of files.
-obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
-obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
-obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
-obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
-obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
-obj-$(CONFIG_MOUSE_INPORT) += inport.o
-obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
-obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
-obj-$(CONFIG_MOUSE_PS2) += psmouse.o
-obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
-obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
-obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
-obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
+obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o
+obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
+obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
+obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
+obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o
+obj-$(CONFIG_MOUSE_INPORT) += inport.o
+obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
+obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
+obj-$(CONFIG_MOUSE_PS2) += psmouse.o
+obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o
+obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
+obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
+obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
+obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
psmouse-objs := psmouse-base.o synaptics.o
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 079816e6b23b..454b96112f03 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2005-2008 Johannes Berg (johannes@sipsolutions.net)
- * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ * Copyright (C) 2005-2008 Stelian Pop (stelian@popies.net)
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
* Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
@@ -35,16 +35,74 @@
#include <linux/module.h>
#include <linux/usb/input.h>
-/* Type of touchpad */
-enum atp_touchpad_type {
- ATP_FOUNTAIN,
- ATP_GEYSER1,
- ATP_GEYSER2,
- ATP_GEYSER3,
- ATP_GEYSER4
+/*
+ * Note: We try to keep the touchpad aspect ratio while still doing only
+ * simple arithmetics:
+ * 0 <= x <= (xsensors - 1) * xfact
+ * 0 <= y <= (ysensors - 1) * yfact
+ */
+struct atp_info {
+ int xsensors; /* number of X sensors */
+ int xsensors_17; /* 17" models have more sensors */
+ int ysensors; /* number of Y sensors */
+ int xfact; /* X multiplication factor */
+ int yfact; /* Y multiplication factor */
+ int datalen; /* size of USB transfers */
+ void (*callback)(struct urb *); /* callback function */
+};
+
+static void atp_complete_geyser_1_2(struct urb *urb);
+static void atp_complete_geyser_3_4(struct urb *urb);
+
+static const struct atp_info fountain_info = {
+ .xsensors = 16,
+ .xsensors_17 = 26,
+ .ysensors = 16,
+ .xfact = 64,
+ .yfact = 43,
+ .datalen = 81,
+ .callback = atp_complete_geyser_1_2,
+};
+
+static const struct atp_info geyser1_info = {
+ .xsensors = 16,
+ .xsensors_17 = 26,
+ .ysensors = 16,
+ .xfact = 64,
+ .yfact = 43,
+ .datalen = 81,
+ .callback = atp_complete_geyser_1_2,
+};
+
+static const struct atp_info geyser2_info = {
+ .xsensors = 15,
+ .xsensors_17 = 20,
+ .ysensors = 9,
+ .xfact = 64,
+ .yfact = 43,
+ .datalen = 64,
+ .callback = atp_complete_geyser_1_2,
+};
+
+static const struct atp_info geyser3_info = {
+ .xsensors = 20,
+ .ysensors = 10,
+ .xfact = 64,
+ .yfact = 64,
+ .datalen = 64,
+ .callback = atp_complete_geyser_3_4,
};
-#define ATP_DEVICE(prod, type) \
+static const struct atp_info geyser4_info = {
+ .xsensors = 20,
+ .ysensors = 10,
+ .xfact = 64,
+ .yfact = 64,
+ .datalen = 64,
+ .callback = atp_complete_geyser_3_4,
+};
+
+#define ATP_DEVICE(prod, info) \
{ \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
@@ -53,7 +111,7 @@ enum atp_touchpad_type {
.idProduct = (prod), \
.bInterfaceClass = 0x03, \
.bInterfaceProtocol = 0x02, \
- .driver_info = ATP_ ## type, \
+ .driver_info = (unsigned long) &info, \
}
/*
@@ -62,43 +120,39 @@ enum atp_touchpad_type {
* According to Info.plist Geyser IV is the same as Geyser III.)
*/
-static struct usb_device_id atp_table [] = {
+static struct usb_device_id atp_table[] = {
/* PowerBooks Feb 2005, iBooks G4 */
- ATP_DEVICE(0x020e, FOUNTAIN), /* FOUNTAIN ANSI */
- ATP_DEVICE(0x020f, FOUNTAIN), /* FOUNTAIN ISO */
- ATP_DEVICE(0x030a, FOUNTAIN), /* FOUNTAIN TP ONLY */
- ATP_DEVICE(0x030b, GEYSER1), /* GEYSER 1 TP ONLY */
+ ATP_DEVICE(0x020e, fountain_info), /* FOUNTAIN ANSI */
+ ATP_DEVICE(0x020f, fountain_info), /* FOUNTAIN ISO */
+ ATP_DEVICE(0x030a, fountain_info), /* FOUNTAIN TP ONLY */
+ ATP_DEVICE(0x030b, geyser1_info), /* GEYSER 1 TP ONLY */
/* PowerBooks Oct 2005 */
- ATP_DEVICE(0x0214, GEYSER2), /* GEYSER 2 ANSI */
- ATP_DEVICE(0x0215, GEYSER2), /* GEYSER 2 ISO */
- ATP_DEVICE(0x0216, GEYSER2), /* GEYSER 2 JIS */
+ ATP_DEVICE(0x0214, geyser2_info), /* GEYSER 2 ANSI */
+ ATP_DEVICE(0x0215, geyser2_info), /* GEYSER 2 ISO */
+ ATP_DEVICE(0x0216, geyser2_info), /* GEYSER 2 JIS */
/* Core Duo MacBook & MacBook Pro */
- ATP_DEVICE(0x0217, GEYSER3), /* GEYSER 3 ANSI */
- ATP_DEVICE(0x0218, GEYSER3), /* GEYSER 3 ISO */
- ATP_DEVICE(0x0219, GEYSER3), /* GEYSER 3 JIS */
+ ATP_DEVICE(0x0217, geyser3_info), /* GEYSER 3 ANSI */
+ ATP_DEVICE(0x0218, geyser3_info), /* GEYSER 3 ISO */
+ ATP_DEVICE(0x0219, geyser3_info), /* GEYSER 3 JIS */
/* Core2 Duo MacBook & MacBook Pro */
- ATP_DEVICE(0x021a, GEYSER4), /* GEYSER 4 ANSI */
- ATP_DEVICE(0x021b, GEYSER4), /* GEYSER 4 ISO */
- ATP_DEVICE(0x021c, GEYSER4), /* GEYSER 4 JIS */
+ ATP_DEVICE(0x021a, geyser4_info), /* GEYSER 4 ANSI */
+ ATP_DEVICE(0x021b, geyser4_info), /* GEYSER 4 ISO */
+ ATP_DEVICE(0x021c, geyser4_info), /* GEYSER 4 JIS */
/* Core2 Duo MacBook3,1 */
- ATP_DEVICE(0x0229, GEYSER4), /* GEYSER 4 HF ANSI */
- ATP_DEVICE(0x022a, GEYSER4), /* GEYSER 4 HF ISO */
- ATP_DEVICE(0x022b, GEYSER4), /* GEYSER 4 HF JIS */
+ ATP_DEVICE(0x0229, geyser4_info), /* GEYSER 4 HF ANSI */
+ ATP_DEVICE(0x022a, geyser4_info), /* GEYSER 4 HF ISO */
+ ATP_DEVICE(0x022b, geyser4_info), /* GEYSER 4 HF JIS */
/* Terminating entry */
{ }
};
MODULE_DEVICE_TABLE(usb, atp_table);
-/*
- * number of sensors. Note that only 16 instead of 26 X (horizontal)
- * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
- * (vertical) sensors.
- */
+/* maximum number of sensors */
#define ATP_XSENSORS 26
#define ATP_YSENSORS 16
@@ -107,21 +161,6 @@ MODULE_DEVICE_TABLE(usb, atp_table);
/* maximum pressure this driver will report */
#define ATP_PRESSURE 300
-/*
- * multiplication factor for the X and Y coordinates.
- * We try to keep the touchpad aspect ratio while still doing only simple
- * arithmetics.
- * The factors below give coordinates like:
- *
- * 0 <= x < 960 on 12" and 15" Powerbooks
- * 0 <= x < 1600 on 17" Powerbooks and 17" MacBook Pro
- * 0 <= x < 1216 on MacBooks and 15" MacBook Pro
- *
- * 0 <= y < 646 on all Powerbooks
- * 0 <= y < 774 on all MacBooks
- */
-#define ATP_XFACT 64
-#define ATP_YFACT 43
/*
* Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
@@ -159,7 +198,7 @@ struct atp {
struct urb *urb; /* usb request block */
u8 *data; /* transferred data */
struct input_dev *input; /* input dev */
- enum atp_touchpad_type type; /* type of touchpad */
+ const struct atp_info *info; /* touchpad model */
bool open;
bool valid; /* are the samples valid? */
bool size_detect_done;
@@ -169,7 +208,6 @@ struct atp {
signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS];
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
- int datalen; /* size of USB transfer */
int idlecount; /* number of empty packets */
struct work_struct work;
};
@@ -359,7 +397,7 @@ static int atp_status_check(struct urb *urb)
if (!dev->overflow_warned) {
printk(KERN_WARNING "appletouch: OVERFLOW with data "
"length %d, actual length is %d\n",
- dev->datalen, dev->urb->actual_length);
+ dev->info->datalen, dev->urb->actual_length);
dev->overflow_warned = true;
}
case -ECONNRESET:
@@ -377,7 +415,7 @@ static int atp_status_check(struct urb *urb)
}
/* drop incomplete datasets */
- if (dev->urb->actual_length != dev->datalen) {
+ if (dev->urb->actual_length != dev->info->datalen) {
dprintk("appletouch: incomplete data package"
" (first byte: %d, length: %d).\n",
dev->data[0], dev->urb->actual_length);
@@ -387,6 +425,25 @@ static int atp_status_check(struct urb *urb)
return ATP_URB_STATUS_SUCCESS;
}
+static void atp_detect_size(struct atp *dev)
+{
+ int i;
+
+ /* 17" Powerbooks have extra X sensors */
+ for (i = dev->info->xsensors; i < ATP_XSENSORS; i++) {
+ if (dev->xy_cur[i]) {
+
+ printk(KERN_INFO "appletouch: 17\" model detected.\n");
+
+ input_set_abs_params(dev->input, ABS_X, 0,
+ (dev->info->xsensors_17 - 1) *
+ dev->info->xfact - 1,
+ ATP_FUZZ, 0);
+ break;
+ }
+ }
+}
+
/*
* USB interrupt callback functions
*/
@@ -407,7 +464,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
goto exit;
/* reorder the sensors values */
- if (dev->type == ATP_GEYSER2) {
+ if (dev->info == &geyser2_info) {
memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
/*
@@ -437,8 +494,8 @@ static void atp_complete_geyser_1_2(struct urb *urb)
dev->xy_cur[i + 24] = dev->data[5 * i + 44];
/* Y values */
- dev->xy_cur[i + 26] = dev->data[5 * i + 1];
- dev->xy_cur[i + 34] = dev->data[5 * i + 3];
+ dev->xy_cur[ATP_XSENSORS + i] = dev->data[5 * i + 1];
+ dev->xy_cur[ATP_XSENSORS + i + 8] = dev->data[5 * i + 3];
}
}
@@ -453,32 +510,8 @@ static void atp_complete_geyser_1_2(struct urb *urb)
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
/* Perform size detection, if not done already */
- if (!dev->size_detect_done) {
-
- /* 17" Powerbooks have extra X sensors */
- for (i = (dev->type == ATP_GEYSER2 ? 15 : 16);
- i < ATP_XSENSORS; i++) {
- if (!dev->xy_cur[i])
- continue;
-
- printk(KERN_INFO
- "appletouch: 17\" model detected.\n");
-
- if (dev->type == ATP_GEYSER2)
- input_set_abs_params(dev->input, ABS_X,
- 0,
- (20 - 1) *
- ATP_XFACT - 1,
- ATP_FUZZ, 0);
- else
- input_set_abs_params(dev->input, ABS_X,
- 0,
- (26 - 1) *
- ATP_XFACT - 1,
- ATP_FUZZ, 0);
- break;
- }
-
+ if (unlikely(!dev->size_detect_done)) {
+ atp_detect_size(dev);
dev->size_detect_done = 1;
goto exit;
}
@@ -499,10 +532,10 @@ static void atp_complete_geyser_1_2(struct urb *urb)
dbg_dump("accumulator", dev->xy_acc);
x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
- ATP_XFACT, &x_z, &x_f);
+ dev->info->xfact, &x_z, &x_f);
y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
- ATP_YFACT, &y_z, &y_f);
- key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
+ dev->info->yfact, &y_z, &y_f);
+ key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;
if (x && y) {
if (dev->x_old != -1) {
@@ -583,7 +616,7 @@ static void atp_complete_geyser_3_4(struct urb *urb)
dbg_dump("sample", dev->xy_cur);
/* Just update the base values (i.e. touchpad in untouched state) */
- if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) {
+ if (dev->data[dev->info->datalen - 1] & ATP_STATUS_BASE_UPDATE) {
dprintk(KERN_DEBUG "appletouch: updated base values\n");
@@ -610,10 +643,10 @@ static void atp_complete_geyser_3_4(struct urb *urb)
dbg_dump("accumulator", dev->xy_acc);
x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
- ATP_XFACT, &x_z, &x_f);
+ dev->info->xfact, &x_z, &x_f);
y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
- ATP_YFACT, &y_z, &y_f);
- key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
+ dev->info->yfact, &y_z, &y_f);
+ key = dev->data[dev->info->datalen - 1] & ATP_STATUS_BUTTON;
if (x && y) {
if (dev->x_old != -1) {
@@ -705,7 +738,7 @@ static int atp_handle_geyser(struct atp *dev)
{
struct usb_device *udev = dev->udev;
- if (dev->type != ATP_FOUNTAIN) {
+ if (dev->info != &fountain_info) {
/* switch to raw sensor mode */
if (atp_geyser_init(udev))
return -EIO;
@@ -726,6 +759,7 @@ static int atp_probe(struct usb_interface *iface,
struct usb_endpoint_descriptor *endpoint;
int int_in_endpointAddr = 0;
int i, error = -ENOMEM;
+ const struct atp_info *info = (const struct atp_info *)id->driver_info;
/* set up the endpoint information */
/* use only the first interrupt-in endpoint */
@@ -753,35 +787,22 @@ static int atp_probe(struct usb_interface *iface,
dev->udev = udev;
dev->input = input_dev;
- dev->type = id->driver_info;
+ dev->info = info;
dev->overflow_warned = false;
- if (dev->type == ATP_FOUNTAIN || dev->type == ATP_GEYSER1)
- dev->datalen = 81;
- else
- dev->datalen = 64;
dev->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->urb)
goto err_free_devs;
- dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
+ dev->data = usb_buffer_alloc(dev->udev, dev->info->datalen, GFP_KERNEL,
&dev->urb->transfer_dma);
if (!dev->data)
goto err_free_urb;
- /* Select the USB complete (callback) function */
- if (dev->type == ATP_FOUNTAIN ||
- dev->type == ATP_GEYSER1 ||
- dev->type == ATP_GEYSER2)
- usb_fill_int_urb(dev->urb, udev,
- usb_rcvintpipe(udev, int_in_endpointAddr),
- dev->data, dev->datalen,
- atp_complete_geyser_1_2, dev, 1);
- else
- usb_fill_int_urb(dev->urb, udev,
- usb_rcvintpipe(udev, int_in_endpointAddr),
- dev->data, dev->datalen,
- atp_complete_geyser_3_4, dev, 1);
+ usb_fill_int_urb(dev->urb, udev,
+ usb_rcvintpipe(udev, int_in_endpointAddr),
+ dev->data, dev->info->datalen,
+ dev->info->callback, dev, 1);
error = atp_handle_geyser(dev);
if (error)
@@ -802,35 +823,12 @@ static int atp_probe(struct usb_interface *iface,
set_bit(EV_ABS, input_dev->evbit);
- if (dev->type == ATP_GEYSER3 || dev->type == ATP_GEYSER4) {
- /*
- * MacBook have 20 X sensors, 10 Y sensors
- */
- input_set_abs_params(input_dev, ABS_X, 0,
- ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
- input_set_abs_params(input_dev, ABS_Y, 0,
- ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
- } else if (dev->type == ATP_GEYSER2) {
- /*
- * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
- * later.
- */
- input_set_abs_params(input_dev, ABS_X, 0,
- ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
- input_set_abs_params(input_dev, ABS_Y, 0,
- ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
- } else {
- /*
- * 12" and 15" Powerbooks only have 16 x sensors,
- * 17" models are detected later.
- */
- input_set_abs_params(input_dev, ABS_X, 0,
- (16 - 1) * ATP_XFACT - 1,
- ATP_FUZZ, 0);
- input_set_abs_params(input_dev, ABS_Y, 0,
- (ATP_YSENSORS - 1) * ATP_YFACT - 1,
- ATP_FUZZ, 0);
- }
+ input_set_abs_params(input_dev, ABS_X, 0,
+ (dev->info->xsensors - 1) * dev->info->xfact - 1,
+ ATP_FUZZ, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0,
+ (dev->info->ysensors - 1) * dev->info->yfact - 1,
+ ATP_FUZZ, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
set_bit(EV_KEY, input_dev->evbit);
@@ -852,7 +850,7 @@ static int atp_probe(struct usb_interface *iface,
return 0;
err_free_buffer:
- usb_buffer_free(dev->udev, dev->datalen,
+ usb_buffer_free(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
err_free_urb:
usb_free_urb(dev->urb);
@@ -871,7 +869,7 @@ static void atp_disconnect(struct usb_interface *iface)
if (dev) {
usb_kill_urb(dev->urb);
input_unregister_device(dev->input);
- usb_buffer_free(dev->udev, dev->datalen,
+ usb_buffer_free(dev->udev, dev->info->datalen,
dev->data, dev->urb->transfer_dma);
usb_free_urb(dev->urb);
kfree(dev);
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
index 72cf5e33790e..0db8d16c5edd 100644
--- a/drivers/input/mouse/gpio_mouse.c
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -173,7 +173,7 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:gpio_mouse");
-struct platform_driver gpio_mouse_device_driver = {
+static struct platform_driver gpio_mouse_device_driver = {
.remove = __devexit_p(gpio_mouse_remove),
.driver = {
.name = "gpio_mouse",
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index 88f04bf2ad6c..81e6ebf323e9 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -48,6 +48,30 @@ module_param(recalib_delta, int, 0644);
MODULE_PARM_DESC(recalib_delta,
"packets containing a delta this large will cause a recalibration.");
+static int jumpy_delay = 1000;
+module_param(jumpy_delay, int, 0644);
+MODULE_PARM_DESC(jumpy_delay,
+ "delay (ms) before recal after jumpiness detected");
+
+static int spew_delay = 1000;
+module_param(spew_delay, int, 0644);
+MODULE_PARM_DESC(spew_delay,
+ "delay (ms) before recal after packet spew detected");
+
+static int recal_guard_time = 2000;
+module_param(recal_guard_time, int, 0644);
+MODULE_PARM_DESC(recal_guard_time,
+ "interval (ms) during which recal will be restarted if packet received");
+
+static int post_interrupt_delay = 1000;
+module_param(post_interrupt_delay, int, 0644);
+MODULE_PARM_DESC(post_interrupt_delay,
+ "delay (ms) before recal after recal interrupt detected");
+
+static int autorecal = 1;
+module_param(autorecal, int, 0644);
+MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
+
/*
* When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
* above the pad and still have it send packets. This causes a jump cursor
@@ -66,7 +90,7 @@ static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y)
/* My car gets forty rods to the hogshead and that's the
* way I likes it! */
psmouse_queue_work(psmouse, &priv->recalib_wq,
- msecs_to_jiffies(1000));
+ msecs_to_jiffies(jumpy_delay));
}
}
@@ -103,7 +127,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n",
priv->x_tally, priv->y_tally);
psmouse_queue_work(psmouse, &priv->recalib_wq,
- msecs_to_jiffies(1000));
+ msecs_to_jiffies(spew_delay));
}
/* reset every 100 packets */
priv->count = 0;
@@ -181,7 +205,7 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
"packet inside calibration window, "
"queueing another recalibration\n");
psmouse_queue_work(psmouse, &priv->recalib_wq,
- msecs_to_jiffies(1000));
+ msecs_to_jiffies(post_interrupt_delay));
}
priv->recalib_window = 0;
}
@@ -231,7 +255,7 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse)
* If someone's finger *was* on the touchpad, it's probably
* miscalibrated. So, we should schedule another recalibration
*/
- priv->recalib_window = jiffies + msecs_to_jiffies(2000);
+ priv->recalib_window = jiffies + msecs_to_jiffies(recal_guard_time);
return 0;
}
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
index e532c48410ea..3263ce083bf0 100644
--- a/drivers/input/mouse/hil_ptr.c
+++ b/drivers/input/mouse/hil_ptr.c
@@ -46,7 +46,7 @@
MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
MODULE_LICENSE("Dual BSD/GPL");
-
+MODULE_ALIAS("serio:ty03pr25id0Fex*");
#define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */
#undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
new file mode 100644
index 000000000000..d297accf9a7f
--- /dev/null
+++ b/drivers/input/mouse/pxa930_trkball.c
@@ -0,0 +1,269 @@
+/*
+ * PXA930 track ball mouse driver
+ *
+ * Copyright (C) 2007 Marvell International Ltd.
+ * 2008-02-28: Yong Yao <yaoyong@marvell.com>
+ * initial version
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/pxa930_trkball.h>
+
+/* Trackball Controller Register Definitions */
+#define TBCR (0x000C)
+#define TBCNTR (0x0010)
+#define TBSBC (0x0014)
+
+#define TBCR_TBRST (1 << 1)
+#define TBCR_TBSB (1 << 10)
+
+#define TBCR_Y_FLT(n) (((n) & 0xf) << 6)
+#define TBCR_X_FLT(n) (((n) & 0xf) << 2)
+
+#define TBCNTR_YM(n) (((n) >> 24) & 0xff)
+#define TBCNTR_YP(n) (((n) >> 16) & 0xff)
+#define TBCNTR_XM(n) (((n) >> 8) & 0xff)
+#define TBCNTR_XP(n) ((n) & 0xff)
+
+#define TBSBC_TBSBC (0x1)
+
+struct pxa930_trkball {
+ struct pxa930_trkball_platform_data *pdata;
+
+ /* Memory Mapped Register */
+ struct resource *mem;
+ void __iomem *mmio_base;
+
+ struct input_dev *input;
+};
+
+static irqreturn_t pxa930_trkball_interrupt(int irq, void *dev_id)
+{
+ struct pxa930_trkball *trkball = dev_id;
+ struct input_dev *input = trkball->input;
+ int tbcntr, x, y;
+
+ /* According to the spec software must read TBCNTR twice:
+ * if the read value is the same, the reading is valid
+ */
+ tbcntr = __raw_readl(trkball->mmio_base + TBCNTR);
+
+ if (tbcntr == __raw_readl(trkball->mmio_base + TBCNTR)) {
+ x = (TBCNTR_XP(tbcntr) - TBCNTR_XM(tbcntr)) / 2;
+ y = (TBCNTR_YP(tbcntr) - TBCNTR_YM(tbcntr)) / 2;
+
+ input_report_rel(input, REL_X, x);
+ input_report_rel(input, REL_Y, y);
+ input_sync(input);
+ }
+
+ __raw_writel(TBSBC_TBSBC, trkball->mmio_base + TBSBC);
+ __raw_writel(0, trkball->mmio_base + TBSBC);
+
+ return IRQ_HANDLED;
+}
+
+/* For TBCR, we need to wait for a while to make sure it has been modified. */
+static int write_tbcr(struct pxa930_trkball *trkball, int v)
+{
+ int i = 100;
+
+ __raw_writel(v, trkball->mmio_base + TBCR);
+
+ while (i--) {
+ if (__raw_readl(trkball->mmio_base + TBCR) == v)
+ break;
+ msleep(1);
+ }
+
+ if (i == 0) {
+ pr_err("%s: timed out writing TBCR(%x)!\n", __func__, v);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static void pxa930_trkball_config(struct pxa930_trkball *trkball)
+{
+ uint32_t tbcr;
+
+ /* According to spec, need to write the filters of x,y to 0xf first! */
+ tbcr = __raw_readl(trkball->mmio_base + TBCR);
+ write_tbcr(trkball, tbcr | TBCR_X_FLT(0xf) | TBCR_Y_FLT(0xf));
+ write_tbcr(trkball, TBCR_X_FLT(trkball->pdata->x_filter) |
+ TBCR_Y_FLT(trkball->pdata->y_filter));
+
+ /* According to spec, set TBCR_TBRST first, before clearing it! */
+ tbcr = __raw_readl(trkball->mmio_base + TBCR);
+ write_tbcr(trkball, tbcr | TBCR_TBRST);
+ write_tbcr(trkball, tbcr & ~TBCR_TBRST);
+
+ __raw_writel(TBSBC_TBSBC, trkball->mmio_base + TBSBC);
+ __raw_writel(0, trkball->mmio_base + TBSBC);
+
+ pr_debug("%s: final TBCR=%x!\n", __func__,
+ __raw_readl(trkball->mmio_base + TBCR));
+}
+
+static int pxa930_trkball_open(struct input_dev *dev)
+{
+ struct pxa930_trkball *trkball = input_get_drvdata(dev);
+
+ pxa930_trkball_config(trkball);
+
+ return 0;
+}
+
+static void pxa930_trkball_disable(struct pxa930_trkball *trkball)
+{
+ uint32_t tbcr = __raw_readl(trkball->mmio_base + TBCR);
+
+ /* Held in reset, gate the 32-KHz input clock off */
+ write_tbcr(trkball, tbcr | TBCR_TBRST);
+}
+
+static void pxa930_trkball_close(struct input_dev *dev)
+{
+ struct pxa930_trkball *trkball = input_get_drvdata(dev);
+
+ pxa930_trkball_disable(trkball);
+}
+
+static int __devinit pxa930_trkball_probe(struct platform_device *pdev)
+{
+ struct pxa930_trkball *trkball;
+ struct input_dev *input;
+ struct resource *res;
+ int irq, error;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "failed to get trkball irq\n");
+ return -ENXIO;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get register memory\n");
+ return -ENXIO;
+ }
+
+ trkball = kzalloc(sizeof(struct pxa930_trkball), GFP_KERNEL);
+ if (!trkball)
+ return -ENOMEM;
+
+ trkball->pdata = pdev->dev.platform_data;
+ if (!trkball->pdata) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ error = -EINVAL;
+ goto failed;
+ }
+
+ trkball->mmio_base = ioremap_nocache(res->start, resource_size(res));
+ if (!trkball->mmio_base) {
+ dev_err(&pdev->dev, "failed to ioremap registers\n");
+ error = -ENXIO;
+ goto failed;
+ }
+
+ /* held the module in reset, will be enabled in open() */
+ pxa930_trkball_disable(trkball);
+
+ error = request_irq(irq, pxa930_trkball_interrupt, IRQF_DISABLED,
+ pdev->name, trkball);
+ if (error) {
+ dev_err(&pdev->dev, "failed to request irq: %d\n", error);
+ goto failed_free_io;
+ }
+
+ platform_set_drvdata(pdev, trkball);
+
+ input = input_allocate_device();
+ if (!input) {
+ dev_err(&pdev->dev, "failed to allocate input device\n");
+ error = -ENOMEM;
+ goto failed_free_irq;
+ }
+
+ input->name = pdev->name;
+ input->id.bustype = BUS_HOST;
+ input->open = pxa930_trkball_open;
+ input->close = pxa930_trkball_close;
+ input->dev.parent = &pdev->dev;
+ input_set_drvdata(input, trkball);
+
+ trkball->input = input;
+
+ input_set_capability(input, EV_REL, REL_X);
+ input_set_capability(input, EV_REL, REL_Y);
+
+ error = input_register_device(input);
+ if (error) {
+ dev_err(&pdev->dev, "unable to register input device\n");
+ goto failed_free_input;
+ }
+
+ return 0;
+
+failed_free_input:
+ input_free_device(input);
+failed_free_irq:
+ free_irq(irq, trkball);
+failed_free_io:
+ iounmap(trkball->mmio_base);
+failed:
+ kfree(trkball);
+ return error;
+}
+
+static int __devexit pxa930_trkball_remove(struct platform_device *pdev)
+{
+ struct pxa930_trkball *trkball = platform_get_drvdata(pdev);
+ int irq = platform_get_irq(pdev, 0);
+
+ input_unregister_device(trkball->input);
+ free_irq(irq, trkball);
+ iounmap(trkball->mmio_base);
+ kfree(trkball);
+
+ return 0;
+}
+
+static struct platform_driver pxa930_trkball_driver = {
+ .driver = {
+ .name = "pxa930-trkball",
+ },
+ .probe = pxa930_trkball_probe,
+ .remove = __devexit_p(pxa930_trkball_remove),
+};
+
+static int __init pxa930_trkball_init(void)
+{
+ return platform_driver_register(&pxa930_trkball_driver);
+}
+
+static void __exit pxa930_trkball_exit(void)
+{
+ platform_driver_unregister(&pxa930_trkball_driver);
+}
+
+module_init(pxa930_trkball_init);
+module_exit(pxa930_trkball_exit);
+
+MODULE_AUTHOR("Yong Yao <yaoyong@marvell.com>");
+MODULE_DESCRIPTION("PXA930 Trackball Mouse Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index d349c4a5e3e8..865fc69e9bc3 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -445,12 +445,14 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_abs(dev, ABS_TOOL_WIDTH, finger_width);
input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1);
- input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
- input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
-
input_report_key(dev, BTN_LEFT, hw.left);
input_report_key(dev, BTN_RIGHT, hw.right);
+ if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
+ input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
+ input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
+ }
+
if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
input_report_key(dev, BTN_MIDDLE, hw.middle);
@@ -543,12 +545,14 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
set_bit(EV_KEY, dev->evbit);
set_bit(BTN_TOUCH, dev->keybit);
set_bit(BTN_TOOL_FINGER, dev->keybit);
- set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
- set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
-
set_bit(BTN_LEFT, dev->keybit);
set_bit(BTN_RIGHT, dev->keybit);
+ if (SYN_CAP_MULTIFINGER(priv->capabilities)) {
+ set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
+ set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
+ }
+
if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
set_bit(BTN_MIDDLE, dev->keybit);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index d8c056fe7e98..ef99a7e6d40c 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -878,8 +878,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
- strlcpy(mousedev->dev.bus_id, mousedev->name,
- sizeof(mousedev->dev.bus_id));
+ dev_set_name(&mousedev->dev, mousedev->name);
mousedev->dev.class = &input_class;
if (dev)
mousedev->dev.parent = &dev->dev;
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 37586a68d345..7ba9f2b2c041 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -934,6 +934,7 @@ int hil_mlc_register(hil_mlc *mlc)
snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i);
snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i);
mlc_serio->id = hil_mlc_serio_id;
+ mlc_serio->id.id = i; /* HIL port no. */
mlc_serio->write = hil_mlc_serio_write;
mlc_serio->open = hil_mlc_serio_open;
mlc_serio->close = hil_mlc_serio_close;
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 29e686388a2c..6fa2deff7446 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -143,6 +143,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "M606"),
},
},
+ {
+ .ident = "Gigabyte M912",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "M912"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "01"),
+ },
+ },
{ }
};
@@ -351,6 +359,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
},
},
+ {
+ .ident = "Dell Vostro 1510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
+ },
+ },
{ }
};
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 2b304c22c200..67248c31e19a 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -262,9 +262,17 @@ int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
break;
case PS2_RET_NAK:
- ps2dev->nak = 1;
+ ps2dev->flags |= PS2_FLAG_NAK;
+ ps2dev->nak = PS2_RET_NAK;
break;
+ case PS2_RET_ERR:
+ if (ps2dev->flags & PS2_FLAG_NAK) {
+ ps2dev->flags &= ~PS2_FLAG_NAK;
+ ps2dev->nak = PS2_RET_ERR;
+ break;
+ }
+
/*
* Workaround for mice which don't ACK the Get ID command.
* These are valid mouse IDs that we recognize.
@@ -282,8 +290,11 @@ int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
}
- if (!ps2dev->nak && ps2dev->cmdcnt)
- ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
+ if (!ps2dev->nak) {
+ ps2dev->flags &= ~PS2_FLAG_NAK;
+ if (ps2dev->cmdcnt)
+ ps2dev->flags |= PS2_FLAG_CMD | PS2_FLAG_CMD1;
+ }
ps2dev->flags &= ~PS2_FLAG_ACK;
wake_up(&ps2dev->wait);
@@ -329,6 +340,7 @@ void ps2_cmd_aborted(struct ps2dev *ps2dev)
if (ps2dev->flags & (PS2_FLAG_ACK | PS2_FLAG_CMD))
wake_up(&ps2dev->wait);
- ps2dev->flags = 0;
+ /* reset all flags except last nack */
+ ps2dev->flags &= PS2_FLAG_NAK;
}
EXPORT_SYMBOL(ps2_cmd_aborted);
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
index 1b404f9e3bff..1dacbe0d9348 100644
--- a/drivers/input/serio/pcips2.c
+++ b/drivers/input/serio/pcips2.c
@@ -153,7 +153,7 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i
serio->open = pcips2_open;
serio->close = pcips2_close;
strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
- strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+ strlcpy(serio->phys, dev_name(&dev->dev), sizeof(serio->phys));
serio->port_data = ps2if;
serio->dev.parent = &dev->dev;
ps2if->io = serio;
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 2f12d60eee3b..bc033250dfcd 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -546,8 +546,8 @@ static void serio_init_port(struct serio *serio)
spin_lock_init(&serio->lock);
mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev);
- snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
- "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
+ dev_set_name(&serio->dev, "serio%ld",
+ (long)atomic_inc_return(&serio_no) - 1);
serio->dev.bus = &serio_bus;
serio->dev.release = serio_release_port;
if (serio->parent) {
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index 765007899d9a..ebb22f88c842 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -58,23 +58,20 @@
/* Mask for all the Receive Interrupts */
#define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \
- XPS2_IPIXR_RX_FULL)
+ XPS2_IPIXR_RX_FULL)
/* Mask for all the Interrupts */
#define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \
- XPS2_IPIXR_WDT_TOUT)
+ XPS2_IPIXR_WDT_TOUT)
/* Global Interrupt Enable mask */
#define XPS2_GIER_GIE_MASK 0x80000000
struct xps2data {
int irq;
- u32 phys_addr;
- u32 remap_size;
spinlock_t lock;
- u8 rxb; /* Rx buffer */
void __iomem *base_address; /* virt. address of control registers */
- unsigned int dfl;
+ unsigned int flags;
struct serio serio; /* serio */
};
@@ -82,8 +79,13 @@ struct xps2data {
/* XPS PS/2 data transmission calls */
/************************************/
-/*
- * xps2_recv() will attempt to receive a byte of data from the PS/2 port.
+/**
+ * xps2_recv() - attempts to receive a byte from the PS/2 port.
+ * @drvdata: pointer to ps2 device private data structure
+ * @byte: address where the read data will be copied
+ *
+ * If there is any data available in the PS/2 receiver, this functions reads
+ * the data, otherwise it returns error.
*/
static int xps2_recv(struct xps2data *drvdata, u8 *byte)
{
@@ -116,33 +118,27 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
/* Check which interrupt is active */
if (intr_sr & XPS2_IPIXR_RX_OVF)
- printk(KERN_WARNING "%s: receive overrun error\n",
- drvdata->serio.name);
+ dev_warn(drvdata->serio.dev.parent, "receive overrun error\n");
if (intr_sr & XPS2_IPIXR_RX_ERR)
- drvdata->dfl |= SERIO_PARITY;
+ drvdata->flags |= SERIO_PARITY;
if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT))
- drvdata->dfl |= SERIO_TIMEOUT;
+ drvdata->flags |= SERIO_TIMEOUT;
if (intr_sr & XPS2_IPIXR_RX_FULL) {
- status = xps2_recv(drvdata, &drvdata->rxb);
+ status = xps2_recv(drvdata, &c);
/* Error, if a byte is not received */
if (status) {
- printk(KERN_ERR
- "%s: wrong rcvd byte count (%d)\n",
- drvdata->serio.name, status);
+ dev_err(drvdata->serio.dev.parent,
+ "wrong rcvd byte count (%d)\n", status);
} else {
- c = drvdata->rxb;
- serio_interrupt(&drvdata->serio, c, drvdata->dfl);
- drvdata->dfl = 0;
+ serio_interrupt(&drvdata->serio, c, drvdata->flags);
+ drvdata->flags = 0;
}
}
- if (intr_sr & XPS2_IPIXR_TX_ACK)
- drvdata->dfl = 0;
-
return IRQ_HANDLED;
}
@@ -150,8 +146,15 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
/* serio callbacks */
/*******************/
-/*
- * sxps2_write() sends a byte out through the PS/2 interface.
+/**
+ * sxps2_write() - sends a byte out through the PS/2 port.
+ * @pserio: pointer to the serio structure of the PS/2 port
+ * @c: data that needs to be written to the PS/2 port
+ *
+ * This function checks if the PS/2 transmitter is empty and sends a byte.
+ * Otherwise it returns error. Transmission fails only when nothing is connected
+ * to the PS/2 port. Thats why, we do not try to resend the data in case of a
+ * failure.
*/
static int sxps2_write(struct serio *pserio, unsigned char c)
{
@@ -174,33 +177,39 @@ static int sxps2_write(struct serio *pserio, unsigned char c)
return status;
}
-/*
- * sxps2_open() is called when a port is open by the higher layer.
+/**
+ * sxps2_open() - called when a port is opened by the higher layer.
+ * @pserio: pointer to the serio structure of the PS/2 device
+ *
+ * This function requests irq and enables interrupts for the PS/2 device.
*/
static int sxps2_open(struct serio *pserio)
{
struct xps2data *drvdata = pserio->port_data;
- int retval;
+ int error;
+ u8 c;
- retval = request_irq(drvdata->irq, &xps2_interrupt, 0,
+ error = request_irq(drvdata->irq, &xps2_interrupt, 0,
DRIVER_NAME, drvdata);
- if (retval) {
- printk(KERN_ERR
- "%s: Couldn't allocate interrupt %d\n",
- drvdata->serio.name, drvdata->irq);
- return retval;
+ if (error) {
+ dev_err(drvdata->serio.dev.parent,
+ "Couldn't allocate interrupt %d\n", drvdata->irq);
+ return error;
}
/* start reception by enabling the interrupts */
out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK);
out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL);
- (void)xps2_recv(drvdata, &drvdata->rxb);
+ (void)xps2_recv(drvdata, &c);
return 0; /* success */
}
-/*
- * sxps2_close() frees the interrupt.
+/**
+ * sxps2_close() - frees the interrupt.
+ * @pserio: pointer to the serio structure of the PS/2 device
+ *
+ * This function frees the irq and disables interrupts for the PS/2 device.
*/
static void sxps2_close(struct serio *pserio)
{
@@ -212,24 +221,41 @@ static void sxps2_close(struct serio *pserio)
free_irq(drvdata->irq, drvdata);
}
-/*********************/
-/* Device setup code */
-/*********************/
-
-static int xps2_setup(struct device *dev, struct resource *regs_res,
- struct resource *irq_res)
+/**
+ * xps2_of_probe - probe method for the PS/2 device.
+ * @of_dev: pointer to OF device structure
+ * @match: pointer to the stucture used for matching a device
+ *
+ * This function probes the PS/2 device in the device tree.
+ * It initializes the driver data structure and the hardware.
+ * It returns 0, if the driver is bound to the PS/2 device, or a negative
+ * value if there is an error.
+ */
+static int __devinit xps2_of_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
+ struct resource r_irq; /* Interrupt resources */
+ struct resource r_mem; /* IO mem resources */
struct xps2data *drvdata;
struct serio *serio;
- unsigned long remap_size;
- int retval;
+ struct device *dev = &ofdev->dev;
+ resource_size_t remap_size, phys_addr;
+ int error;
+
+ dev_info(dev, "Device Tree Probing \'%s\'\n",
+ ofdev->node->name);
- if (!dev)
- return -EINVAL;
+ /* Get iospace for the device */
+ error = of_address_to_resource(ofdev->node, 0, &r_mem);
+ if (error) {
+ dev_err(dev, "invalid address\n");
+ return error;
+ }
- if (!regs_res || !irq_res) {
- dev_err(dev, "IO resource(s) not found\n");
- return -EINVAL;
+ /* Get IRQ for the device */
+ if (of_irq_to_resource(ofdev->node, 0, &r_irq) == NO_IRQ) {
+ dev_err(dev, "no IRQ found\n");
+ return -ENODEV;
}
drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL);
@@ -241,24 +267,23 @@ static int xps2_setup(struct device *dev, struct resource *regs_res,
dev_set_drvdata(dev, drvdata);
spin_lock_init(&drvdata->lock);
- drvdata->irq = irq_res->start;
-
- remap_size = regs_res->end - regs_res->start + 1;
- if (!request_mem_region(regs_res->start, remap_size, DRIVER_NAME)) {
- dev_err(dev, "Couldn't lock memory region at 0x%08X\n",
- (unsigned int)regs_res->start);
- retval = -EBUSY;
+ drvdata->irq = r_irq.start;
+
+ phys_addr = r_mem.start;
+ remap_size = r_mem.end - r_mem.start + 1;
+ if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) {
+ dev_err(dev, "Couldn't lock memory region at 0x%08llX\n",
+ (unsigned long long)phys_addr);
+ error = -EBUSY;
goto failed1;
}
/* Fill in configuration data and add them to the list */
- drvdata->phys_addr = regs_res->start;
- drvdata->remap_size = remap_size;
- drvdata->base_address = ioremap(regs_res->start, remap_size);
+ drvdata->base_address = ioremap(phys_addr, remap_size);
if (drvdata->base_address == NULL) {
- dev_err(dev, "Couldn't ioremap memory at 0x%08X\n",
- (unsigned int)regs_res->start);
- retval = -EFAULT;
+ dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n",
+ (unsigned long long)phys_addr);
+ error = -EFAULT;
goto failed2;
}
@@ -269,8 +294,9 @@ static int xps2_setup(struct device *dev, struct resource *regs_res,
* we have the PS2 in a good state */
out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET);
- dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%p, irq=%d\n",
- drvdata->phys_addr, drvdata->base_address, drvdata->irq);
+ dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n",
+ (unsigned long long)phys_addr, drvdata->base_address,
+ drvdata->irq);
serio = &drvdata->serio;
serio->id.type = SERIO_8042;
@@ -280,71 +306,51 @@ static int xps2_setup(struct device *dev, struct resource *regs_res,
serio->port_data = drvdata;
serio->dev.parent = dev;
snprintf(serio->name, sizeof(serio->name),
- "Xilinx XPS PS/2 at %08X", drvdata->phys_addr);
+ "Xilinx XPS PS/2 at %08llX", (unsigned long long)phys_addr);
snprintf(serio->phys, sizeof(serio->phys),
- "xilinxps2/serio at %08X", drvdata->phys_addr);
+ "xilinxps2/serio at %08llX", (unsigned long long)phys_addr);
+
serio_register_port(serio);
return 0; /* success */
failed2:
- release_mem_region(regs_res->start, remap_size);
+ release_mem_region(phys_addr, remap_size);
failed1:
kfree(drvdata);
dev_set_drvdata(dev, NULL);
- return retval;
-}
-
-/***************************/
-/* OF Platform Bus Support */
-/***************************/
-
-static int __devinit xps2_of_probe(struct of_device *ofdev, const struct
- of_device_id * match)
-{
- struct resource r_irq; /* Interrupt resources */
- struct resource r_mem; /* IO mem resources */
- int rc = 0;
-
- printk(KERN_INFO "Device Tree Probing \'%s\'\n",
- ofdev->node->name);
-
- /* Get iospace for the device */
- rc = of_address_to_resource(ofdev->node, 0, &r_mem);
- if (rc) {
- dev_err(&ofdev->dev, "invalid address\n");
- return rc;
- }
-
- /* Get IRQ for the device */
- rc = of_irq_to_resource(ofdev->node, 0, &r_irq);
- if (rc == NO_IRQ) {
- dev_err(&ofdev->dev, "no IRQ found\n");
- return rc;
- }
-
- return xps2_setup(&ofdev->dev, &r_mem, &r_irq);
+ return error;
}
+/**
+ * xps2_of_remove - unbinds the driver from the PS/2 device.
+ * @of_dev: pointer to OF device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees any resources allocated to
+ * the device.
+ */
static int __devexit xps2_of_remove(struct of_device *of_dev)
{
struct device *dev = &of_dev->dev;
- struct xps2data *drvdata;
-
- if (!dev)
- return -EINVAL;
-
- drvdata = dev_get_drvdata(dev);
+ struct xps2data *drvdata = dev_get_drvdata(dev);
+ struct resource r_mem; /* IO mem resources */
serio_unregister_port(&drvdata->serio);
iounmap(drvdata->base_address);
- release_mem_region(drvdata->phys_addr, drvdata->remap_size);
+
+ /* Get iospace of the device */
+ if (of_address_to_resource(of_dev->node, 0, &r_mem))
+ dev_err(dev, "invalid address\n");
+ else
+ release_mem_region(r_mem.start, r_mem.end - r_mem.start + 1);
+
kfree(drvdata);
dev_set_drvdata(dev, NULL);
- return 0; /* success */
+ return 0;
}
/* Match table for of_platform binding */
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index 5524e01dbb1a..2e18a1c0c351 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -877,7 +877,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
dbg("num endpoints: %d", usbinterface->cur_altsetting->desc.bNumEndpoints);
dbg("interface class: %d", usbinterface->cur_altsetting->desc.bInterfaceClass);
dbg("endpoint: attribute:0x%x type:0x%x", endpoint->bmAttributes, endpoint->bDescriptorType);
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ if (usb_endpoint_xfer_int(endpoint))
dbg("endpoint: we have interrupt endpoint\n");
dbg("endpoint extra len:%d ", usbinterface->altsetting[0].extralen);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 8dc8d1e59bea..2638811c61ac 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -535,7 +535,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
return 1;
}
-int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
+static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
{
char *data = wacom->data;
int prox = 0, pressure;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3d1ab8fa9acc..bb6486a8c070 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -58,6 +58,14 @@ config TOUCHSCREEN_CORGI
NOTE: this driver is deprecated, try enable SPI and generic
ADS7846-based touchscreen driver.
+config TOUCHSCREEN_DA9034
+ tristate "Touchscreen support for Dialog Semiconductor DA9034"
+ depends on PMIC_DA903X
+ default y
+ help
+ Say Y here to enable the support for the touchscreen found
+ on Dialog Semiconductor DA9034 PMIC.
+
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
@@ -95,6 +103,19 @@ config TOUCHSCREEN_ELO
To compile this driver as a module, choose M here: the
module will be called elo.
+config TOUCHSCREEN_WACOM_W8001
+ tristate "Wacom W8001 penabled serial touchscreen"
+ select SERIO
+ help
+ Say Y here if you have an Wacom W8001 penabled serial touchscreen
+ connected to your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called wacom_w8001.
+
+
config TOUCHSCREEN_MTOUCH
tristate "MicroTouch serial touchscreens"
select SERIO
@@ -376,4 +397,15 @@ config TOUCHSCREEN_TOUCHIT213
To compile this driver as a module, choose M here: the
module will be called touchit213.
+config TOUCHSCREEN_TSC2007
+ tristate "TSC2007 based touchscreens"
+ depends on I2C
+ help
+ Say Y here if you have a TSC2007 based touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called tsc2007.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 15cf29079489..d3375aff46fe 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -25,8 +25,11 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
+obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
+obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index e1ece89fe922..7c27c8b9b6d0 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -472,7 +472,7 @@ static ssize_t ads7846_disable_store(struct device *dev,
const char *buf, size_t count)
{
struct ads7846 *ts = dev_get_drvdata(dev);
- long i;
+ unsigned long i;
if (strict_strtoul(buf, 10, &i))
return -EINVAL;
@@ -559,7 +559,7 @@ static void ads7846_rx(void *ads)
if (packet->tc.ignore || Rt > ts->pressure_max) {
#ifdef VERBOSE
pr_debug("%s: ignored %d pressure %d\n",
- ts->spi->dev.bus_id, packet->tc.ignore, Rt);
+ dev_name(&ts->spi->dev), packet->tc.ignore, Rt);
#endif
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
HRTIMER_MODE_REL);
@@ -947,7 +947,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->penirq_recheck_delay_usecs =
pdata->penirq_recheck_delay_usecs;
- snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
+ snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
input_dev->name = "ADS784x Touchscreen";
input_dev->phys = ts->phys;
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c
new file mode 100644
index 000000000000..fa67d782c3c3
--- /dev/null
+++ b/drivers/input/touchscreen/da9034-ts.c
@@ -0,0 +1,390 @@
+/*
+ * Touchscreen driver for Dialog Semiconductor DA9034
+ *
+ * Copyright (C) 2006-2008 Marvell International Ltd.
+ * Fengwei Yin <fengwei.yin@marvell.com>
+ * Eric Miao <eric.miao@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/mfd/da903x.h>
+
+#define DA9034_MANUAL_CTRL 0x50
+#define DA9034_LDO_ADC_EN (1 << 4)
+
+#define DA9034_AUTO_CTRL1 0x51
+
+#define DA9034_AUTO_CTRL2 0x52
+#define DA9034_AUTO_TSI_EN (1 << 3)
+#define DA9034_PEN_DETECT (1 << 4)
+
+#define DA9034_TSI_CTRL1 0x53
+#define DA9034_TSI_CTRL2 0x54
+#define DA9034_TSI_X_MSB 0x6c
+#define DA9034_TSI_Y_MSB 0x6d
+#define DA9034_TSI_XY_LSB 0x6e
+
+enum {
+ STATE_IDLE, /* wait for pendown */
+ STATE_BUSY, /* TSI busy sampling */
+ STATE_STOP, /* sample available */
+ STATE_WAIT, /* Wait to start next sample */
+};
+
+enum {
+ EVENT_PEN_DOWN,
+ EVENT_PEN_UP,
+ EVENT_TSI_READY,
+ EVENT_TIMEDOUT,
+};
+
+struct da9034_touch {
+ struct device *da9034_dev;
+ struct input_dev *input_dev;
+
+ struct delayed_work tsi_work;
+ struct notifier_block notifier;
+
+ int state;
+
+ int interval_ms;
+ int x_inverted;
+ int y_inverted;
+
+ int last_x;
+ int last_y;
+};
+
+static inline int is_pen_down(struct da9034_touch *touch)
+{
+ return da903x_query_status(touch->da9034_dev, DA9034_STATUS_PEN_DOWN);
+}
+
+static inline int detect_pen_down(struct da9034_touch *touch, int on)
+{
+ if (on)
+ return da903x_set_bits(touch->da9034_dev,
+ DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
+ else
+ return da903x_clr_bits(touch->da9034_dev,
+ DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
+}
+
+static int read_tsi(struct da9034_touch *touch)
+{
+ uint8_t _x, _y, _v;
+ int ret;
+
+ ret = da903x_read(touch->da9034_dev, DA9034_TSI_X_MSB, &_x);
+ if (ret)
+ return ret;
+
+ ret = da903x_read(touch->da9034_dev, DA9034_TSI_Y_MSB, &_y);
+ if (ret)
+ return ret;
+
+ ret = da903x_read(touch->da9034_dev, DA9034_TSI_XY_LSB, &_v);
+ if (ret)
+ return ret;
+
+ touch->last_x = ((_x << 2) & 0x3fc) | (_v & 0x3);
+ touch->last_y = ((_y << 2) & 0x3fc) | ((_v & 0xc) >> 2);
+
+ return 0;
+}
+
+static inline int start_tsi(struct da9034_touch *touch)
+{
+ return da903x_set_bits(touch->da9034_dev,
+ DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
+}
+
+static inline int stop_tsi(struct da9034_touch *touch)
+{
+ return da903x_clr_bits(touch->da9034_dev,
+ DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
+}
+
+static inline void report_pen_down(struct da9034_touch *touch)
+{
+ int x = touch->last_x;
+ int y = touch->last_y;
+
+ x &= 0xfff;
+ if (touch->x_inverted)
+ x = 1024 - x;
+ y &= 0xfff;
+ if (touch->y_inverted)
+ y = 1024 - y;
+
+ input_report_abs(touch->input_dev, ABS_X, x);
+ input_report_abs(touch->input_dev, ABS_Y, y);
+ input_report_key(touch->input_dev, BTN_TOUCH, 1);
+
+ input_sync(touch->input_dev);
+}
+
+static inline void report_pen_up(struct da9034_touch *touch)
+{
+ input_report_key(touch->input_dev, BTN_TOUCH, 0);
+ input_sync(touch->input_dev);
+}
+
+static void da9034_event_handler(struct da9034_touch *touch, int event)
+{
+ int err;
+
+ switch (touch->state) {
+ case STATE_IDLE:
+ if (event != EVENT_PEN_DOWN)
+ break;
+
+ /* Enable auto measurement of the TSI, this will
+ * automatically disable pen down detection
+ */
+ err = start_tsi(touch);
+ if (err)
+ goto err_reset;
+
+ touch->state = STATE_BUSY;
+ break;
+
+ case STATE_BUSY:
+ if (event != EVENT_TSI_READY)
+ break;
+
+ err = read_tsi(touch);
+ if (err)
+ goto err_reset;
+
+ /* Disable auto measurement of the TSI, so that
+ * pen down status will be available
+ */
+ err = stop_tsi(touch);
+ if (err)
+ goto err_reset;
+
+ touch->state = STATE_STOP;
+ break;
+
+ case STATE_STOP:
+ if (event == EVENT_PEN_DOWN) {
+ report_pen_down(touch);
+ schedule_delayed_work(&touch->tsi_work,
+ msecs_to_jiffies(touch->interval_ms));
+ touch->state = STATE_WAIT;
+ }
+
+ if (event == EVENT_PEN_UP) {
+ report_pen_up(touch);
+ touch->state = STATE_IDLE;
+ }
+
+ input_sync(touch->input_dev);
+ break;
+
+ case STATE_WAIT:
+ if (event != EVENT_TIMEDOUT)
+ break;
+
+ if (is_pen_down(touch)) {
+ start_tsi(touch);
+ touch->state = STATE_BUSY;
+ } else
+ touch->state = STATE_IDLE;
+ break;
+ }
+ return;
+
+err_reset:
+ touch->state = STATE_IDLE;
+ stop_tsi(touch);
+ detect_pen_down(touch, 1);
+}
+
+static void da9034_tsi_work(struct work_struct *work)
+{
+ struct da9034_touch *touch =
+ container_of(work, struct da9034_touch, tsi_work.work);
+
+ da9034_event_handler(touch, EVENT_TIMEDOUT);
+}
+
+static int da9034_touch_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct da9034_touch *touch =
+ container_of(nb, struct da9034_touch, notifier);
+
+ if (event & DA9034_EVENT_PEN_DOWN) {
+ if (is_pen_down(touch))
+ da9034_event_handler(touch, EVENT_PEN_DOWN);
+ else
+ da9034_event_handler(touch, EVENT_PEN_UP);
+ }
+
+ if (event & DA9034_EVENT_TSI_READY)
+ da9034_event_handler(touch, EVENT_TSI_READY);
+
+ return 0;
+}
+
+static int da9034_touch_open(struct input_dev *dev)
+{
+ struct da9034_touch *touch = input_get_drvdata(dev);
+ int ret;
+
+ ret = da903x_register_notifier(touch->da9034_dev, &touch->notifier,
+ DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
+ if (ret)
+ return -EBUSY;
+
+ /* Enable ADC LDO */
+ ret = da903x_set_bits(touch->da9034_dev,
+ DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
+ if (ret)
+ return ret;
+
+ /* TSI_DELAY: 3 slots, TSI_SKIP: 3 slots */
+ ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL1, 0x1b);
+ if (ret)
+ return ret;
+
+ ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL2, 0x00);
+ if (ret)
+ return ret;
+
+ touch->state = STATE_IDLE;
+ detect_pen_down(touch, 1);
+
+ return 0;
+}
+
+static void da9034_touch_close(struct input_dev *dev)
+{
+ struct da9034_touch *touch = input_get_drvdata(dev);
+
+ da903x_unregister_notifier(touch->da9034_dev, &touch->notifier,
+ DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
+
+ cancel_delayed_work_sync(&touch->tsi_work);
+
+ touch->state = STATE_IDLE;
+ stop_tsi(touch);
+ detect_pen_down(touch, 0);
+
+ /* Disable ADC LDO */
+ da903x_clr_bits(touch->da9034_dev,
+ DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
+}
+
+
+static int __devinit da9034_touch_probe(struct platform_device *pdev)
+{
+ struct da9034_touch_pdata *pdata = pdev->dev.platform_data;
+ struct da9034_touch *touch;
+ struct input_dev *input_dev;
+ int ret;
+
+ touch = kzalloc(sizeof(struct da9034_touch), GFP_KERNEL);
+ if (touch == NULL) {
+ dev_err(&pdev->dev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ touch->da9034_dev = pdev->dev.parent;
+
+ if (pdata) {
+ touch->interval_ms = pdata->interval_ms;
+ touch->x_inverted = pdata->x_inverted;
+ touch->y_inverted = pdata->y_inverted;
+ } else
+ /* fallback into default */
+ touch->interval_ms = 10;
+
+ INIT_DELAYED_WORK(&touch->tsi_work, da9034_tsi_work);
+ touch->notifier.notifier_call = da9034_touch_notifier;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(&pdev->dev, "failed to allocate input device\n");
+ ret = -ENOMEM;
+ goto err_free_touch;
+ }
+
+ input_dev->name = pdev->name;
+ input_dev->open = da9034_touch_open;
+ input_dev->close = da9034_touch_close;
+ input_dev->dev.parent = &pdev->dev;
+
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(ABS_X, input_dev->absbit);
+ __set_bit(ABS_Y, input_dev->absbit);
+ input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0);
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+
+ touch->input_dev = input_dev;
+ input_set_drvdata(input_dev, touch);
+
+ ret = input_register_device(input_dev);
+ if (ret)
+ goto err_free_input;
+
+ platform_set_drvdata(pdev, touch);
+ return 0;
+
+err_free_input:
+ input_free_device(input_dev);
+err_free_touch:
+ kfree(touch);
+ return ret;
+}
+
+static int __devexit da9034_touch_remove(struct platform_device *pdev)
+{
+ struct da9034_touch *touch = platform_get_drvdata(pdev);
+
+ input_unregister_device(touch->input_dev);
+ kfree(touch);
+
+ return 0;
+}
+
+static struct platform_driver da9034_touch_driver = {
+ .driver = {
+ .name = "da9034-touch",
+ .owner = THIS_MODULE,
+ },
+ .probe = da9034_touch_probe,
+ .remove = __devexit_p(da9034_touch_remove),
+};
+
+static int __init da9034_touch_init(void)
+{
+ return platform_driver_register(&da9034_touch_driver);
+}
+module_init(da9034_touch_init);
+
+static void __exit da9034_touch_exit(void)
+{
+ platform_driver_unregister(&da9034_touch_driver);
+}
+module_exit(da9034_touch_exit);
+
+MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034");
+MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9034-touch");
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
new file mode 100644
index 000000000000..b75dc2990574
--- /dev/null
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -0,0 +1,381 @@
+/*
+ * drivers/input/touchscreen/tsc2007.c
+ *
+ * Copyright (c) 2008 MtekVision Co., Ltd.
+ * Kwangwoo Lee <kwlee@mtekvision.com>
+ *
+ * Using code from:
+ * - ads7846.c
+ * Copyright (c) 2005 David Brownell
+ * Copyright (c) 2006 Nokia Corporation
+ * - corgi_ts.c
+ * Copyright (C) 2004-2005 Richard Purdie
+ * - omap_ts.[hc], ads7846.h, ts_osk.c
+ * Copyright (C) 2002 MontaVista Software
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2005 Dirk Behme
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/hrtimer.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
+
+#define TS_POLL_DELAY (10 * 1000) /* ns delay before the first sample */
+#define TS_POLL_PERIOD (5 * 1000) /* ns delay between samples */
+
+#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
+#define TSC2007_MEASURE_AUX (0x2 << 4)
+#define TSC2007_MEASURE_TEMP1 (0x4 << 4)
+#define TSC2007_ACTIVATE_XN (0x8 << 4)
+#define TSC2007_ACTIVATE_YN (0x9 << 4)
+#define TSC2007_ACTIVATE_YP_XN (0xa << 4)
+#define TSC2007_SETUP (0xb << 4)
+#define TSC2007_MEASURE_X (0xc << 4)
+#define TSC2007_MEASURE_Y (0xd << 4)
+#define TSC2007_MEASURE_Z1 (0xe << 4)
+#define TSC2007_MEASURE_Z2 (0xf << 4)
+
+#define TSC2007_POWER_OFF_IRQ_EN (0x0 << 2)
+#define TSC2007_ADC_ON_IRQ_DIS0 (0x1 << 2)
+#define TSC2007_ADC_OFF_IRQ_EN (0x2 << 2)
+#define TSC2007_ADC_ON_IRQ_DIS1 (0x3 << 2)
+
+#define TSC2007_12BIT (0x0 << 1)
+#define TSC2007_8BIT (0x1 << 1)
+
+#define MAX_12BIT ((1 << 12) - 1)
+
+#define ADC_ON_12BIT (TSC2007_12BIT | TSC2007_ADC_ON_IRQ_DIS0)
+
+#define READ_Y (ADC_ON_12BIT | TSC2007_MEASURE_Y)
+#define READ_Z1 (ADC_ON_12BIT | TSC2007_MEASURE_Z1)
+#define READ_Z2 (ADC_ON_12BIT | TSC2007_MEASURE_Z2)
+#define READ_X (ADC_ON_12BIT | TSC2007_MEASURE_X)
+#define PWRDOWN (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN)
+
+struct ts_event {
+ u16 x;
+ u16 y;
+ u16 z1, z2;
+};
+
+struct tsc2007 {
+ struct input_dev *input;
+ char phys[32];
+ struct hrtimer timer;
+ struct ts_event tc;
+
+ struct i2c_client *client;
+
+ spinlock_t lock;
+
+ u16 model;
+ u16 x_plate_ohms;
+
+ unsigned pendown;
+ int irq;
+
+ int (*get_pendown_state)(void);
+ void (*clear_penirq)(void);
+};
+
+static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
+{
+ s32 data;
+ u16 val;
+
+ data = i2c_smbus_read_word_data(tsc->client, cmd);
+ if (data < 0) {
+ dev_err(&tsc->client->dev, "i2c io error: %d\n", data);
+ return data;
+ }
+
+ /* The protocol and raw data format from i2c interface:
+ * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
+ * Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit].
+ */
+ val = swab16(data) >> 4;
+
+ dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data, val);
+
+ return val;
+}
+
+static void tsc2007_send_event(void *tsc)
+{
+ struct tsc2007 *ts = tsc;
+ u32 rt;
+ u16 x, y, z1, z2;
+
+ x = ts->tc.x;
+ y = ts->tc.y;
+ z1 = ts->tc.z1;
+ z2 = ts->tc.z2;
+
+ /* range filtering */
+ if (x == MAX_12BIT)
+ x = 0;
+
+ if (likely(x && z1)) {
+ /* compute touch pressure resistance using equation #1 */
+ rt = z2;
+ rt -= z1;
+ rt *= x;
+ rt *= ts->x_plate_ohms;
+ rt /= z1;
+ rt = (rt + 2047) >> 12;
+ } else
+ rt = 0;
+
+ /* Sample found inconsistent by debouncing or pressure is beyond
+ * the maximum. Don't report it to user space, repeat at least
+ * once more the measurement
+ */
+ if (rt > MAX_12BIT) {
+ dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
+
+ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
+ HRTIMER_MODE_REL);
+ return;
+ }
+
+ /* NOTE: We can't rely on the pressure to determine the pen down
+ * state, even this controller has a pressure sensor. The pressure
+ * value can fluctuate for quite a while after lifting the pen and
+ * in some cases may not even settle at the expected value.
+ *
+ * The only safe way to check for the pen up condition is in the
+ * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
+ */
+ if (rt) {
+ struct input_dev *input = ts->input;
+
+ if (!ts->pendown) {
+ dev_dbg(&ts->client->dev, "DOWN\n");
+
+ input_report_key(input, BTN_TOUCH, 1);
+ ts->pendown = 1;
+ }
+
+ input_report_abs(input, ABS_X, x);
+ input_report_abs(input, ABS_Y, y);
+ input_report_abs(input, ABS_PRESSURE, rt);
+
+ input_sync(input);
+
+ dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
+ x, y, rt);
+ }
+
+ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
+ HRTIMER_MODE_REL);
+}
+
+static int tsc2007_read_values(struct tsc2007 *tsc)
+{
+ /* y- still on; turn on only y+ (and ADC) */
+ tsc->tc.y = tsc2007_xfer(tsc, READ_Y);
+
+ /* turn y- off, x+ on, then leave in lowpower */
+ tsc->tc.x = tsc2007_xfer(tsc, READ_X);
+
+ /* turn y+ off, x- on; we'll use formula #1 */
+ tsc->tc.z1 = tsc2007_xfer(tsc, READ_Z1);
+ tsc->tc.z2 = tsc2007_xfer(tsc, READ_Z2);
+
+ /* power down */
+ tsc2007_xfer(tsc, PWRDOWN);
+
+ return 0;
+}
+
+static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle)
+{
+ struct tsc2007 *ts = container_of(handle, struct tsc2007, timer);
+
+ spin_lock_irq(&ts->lock);
+
+ if (unlikely(!ts->get_pendown_state() && ts->pendown)) {
+ struct input_dev *input = ts->input;
+
+ dev_dbg(&ts->client->dev, "UP\n");
+
+ input_report_key(input, BTN_TOUCH, 0);
+ input_report_abs(input, ABS_PRESSURE, 0);
+ input_sync(input);
+
+ ts->pendown = 0;
+ enable_irq(ts->irq);
+ } else {
+ /* pen is still down, continue with the measurement */
+ dev_dbg(&ts->client->dev, "pen is still down\n");
+
+ tsc2007_read_values(ts);
+ tsc2007_send_event(ts);
+ }
+
+ spin_unlock_irq(&ts->lock);
+
+ return HRTIMER_NORESTART;
+}
+
+static irqreturn_t tsc2007_irq(int irq, void *handle)
+{
+ struct tsc2007 *ts = handle;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ts->lock, flags);
+
+ if (likely(ts->get_pendown_state())) {
+ disable_irq(ts->irq);
+ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
+ HRTIMER_MODE_REL);
+ }
+
+ if (ts->clear_penirq)
+ ts->clear_penirq();
+
+ spin_unlock_irqrestore(&ts->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int tsc2007_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tsc2007 *ts;
+ struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data;
+ struct input_dev *input_dev;
+ int err;
+
+ if (!pdata) {
+ dev_err(&client->dev, "platform data is required!\n");
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_WORD_DATA))
+ return -EIO;
+
+ ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!ts || !input_dev) {
+ err = -ENOMEM;
+ goto err_free_mem;
+ }
+
+ ts->client = client;
+ i2c_set_clientdata(client, ts);
+
+ ts->input = input_dev;
+
+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ts->timer.function = tsc2007_timer;
+
+ spin_lock_init(&ts->lock);
+
+ ts->model = pdata->model;
+ ts->x_plate_ohms = pdata->x_plate_ohms;
+ ts->get_pendown_state = pdata->get_pendown_state;
+ ts->clear_penirq = pdata->clear_penirq;
+
+ pdata->init_platform_hw();
+
+ snprintf(ts->phys, sizeof(ts->phys), "%s/input0", client->dev.bus_id);
+
+ input_dev->name = "TSC2007 Touchscreen";
+ input_dev->phys = ts->phys;
+ input_dev->id.bustype = BUS_I2C;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
+
+ tsc2007_read_values(ts);
+
+ ts->irq = client->irq;
+
+ err = request_irq(ts->irq, tsc2007_irq, 0,
+ client->dev.driver->name, ts);
+ if (err < 0) {
+ dev_err(&client->dev, "irq %d busy?\n", ts->irq);
+ goto err_free_mem;
+ }
+
+ err = input_register_device(input_dev);
+ if (err)
+ goto err_free_irq;
+
+ dev_info(&client->dev, "registered with irq (%d)\n", ts->irq);
+
+ return 0;
+
+ err_free_irq:
+ free_irq(ts->irq, ts);
+ hrtimer_cancel(&ts->timer);
+ err_free_mem:
+ input_free_device(input_dev);
+ kfree(ts);
+ return err;
+}
+
+static int tsc2007_remove(struct i2c_client *client)
+{
+ struct tsc2007 *ts = i2c_get_clientdata(client);
+ struct tsc2007_platform_data *pdata;
+
+ pdata = client->dev.platform_data;
+ pdata->exit_platform_hw();
+
+ free_irq(ts->irq, ts);
+ hrtimer_cancel(&ts->timer);
+ input_unregister_device(ts->input);
+ kfree(ts);
+
+ return 0;
+}
+
+static struct i2c_device_id tsc2007_idtable[] = {
+ { "tsc2007", 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
+
+static struct i2c_driver tsc2007_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tsc2007"
+ },
+ .id_table = tsc2007_idtable,
+ .probe = tsc2007_probe,
+ .remove = tsc2007_remove,
+};
+
+static int __init tsc2007_init(void)
+{
+ return i2c_add_driver(&tsc2007_driver);
+}
+
+static void __exit tsc2007_exit(void)
+{
+ i2c_del_driver(&tsc2007_driver);
+}
+
+module_init(tsc2007_init);
+module_exit(tsc2007_exit);
+
+MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>");
+MODULE_DESCRIPTION("TSC2007 TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index fdd645c214a2..5080b26ba160 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -424,7 +424,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
if (ret < 0)
goto err_out;
- if (buf[0] != 0x06 || buf[1] != 0x00) {
+ if (buf[0] != 0x06) {
ret = -ENODEV;
goto err_out;
}
@@ -437,8 +437,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
if (ret < 0)
goto err_out;
- if ((buf[0] != 0x06 || buf[1] != 0x00) &&
- (buf[0] != 0x15 || buf[1] != 0x01)) {
+ if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) {
ret = -ENODEV;
goto err_out;
}
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
new file mode 100644
index 000000000000..2f33a0167644
--- /dev/null
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -0,0 +1,325 @@
+/*
+ * Wacom W8001 penabled serial touchscreen driver
+ *
+ * Copyright (c) 2008 Jaya Kumar
+ *
+ * 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.
+ *
+ * Layout based on Elo serial touchscreen driver by Vojtech Pavlik
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+
+#define DRIVER_DESC "Wacom W8001 serial touchscreen driver"
+
+MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define W8001_MAX_LENGTH 11
+#define W8001_PACKET_LEN 11
+#define W8001_LEAD_MASK 0x80
+#define W8001_LEAD_BYTE 0x80
+#define W8001_TAB_MASK 0x40
+#define W8001_TAB_BYTE 0x40
+
+#define W8001_QUERY_PACKET 0x20
+
+struct w8001_coord {
+ u8 rdy;
+ u8 tsw;
+ u8 f1;
+ u8 f2;
+ u16 x;
+ u16 y;
+ u16 pen_pressure;
+ u8 tilt_x;
+ u8 tilt_y;
+};
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct w8001 {
+ struct input_dev *dev;
+ struct serio *serio;
+ struct mutex cmd_mutex;
+ struct completion cmd_done;
+ int id;
+ int idx;
+ unsigned char expected_packet;
+ unsigned char data[W8001_MAX_LENGTH];
+ unsigned char response[W8001_PACKET_LEN];
+ char phys[32];
+};
+
+static int parse_data(u8 *data, struct w8001_coord *coord)
+{
+ coord->rdy = data[0] & 0x20;
+ coord->tsw = data[0] & 0x01;
+ coord->f1 = data[0] & 0x02;
+ coord->f2 = data[0] & 0x04;
+
+ coord->x = (data[1] & 0x7F) << 9;
+ coord->x |= (data[2] & 0x7F) << 2;
+ coord->x |= (data[6] & 0x60) >> 5;
+
+ coord->y = (data[3] & 0x7F) << 9;
+ coord->y |= (data[4] & 0x7F) << 2;
+ coord->y |= (data[6] & 0x18) >> 3;
+
+ coord->pen_pressure = data[5] & 0x7F;
+ coord->pen_pressure |= (data[6] & 0x07) << 7 ;
+
+ coord->tilt_x = data[7] & 0x7F;
+ coord->tilt_y = data[8] & 0x7F;
+
+ return 0;
+}
+
+static void w8001_process_data(struct w8001 *w8001, unsigned char data)
+{
+ struct input_dev *dev = w8001->dev;
+ u8 tmp;
+ struct w8001_coord coord;
+
+ w8001->data[w8001->idx] = data;
+ switch (w8001->idx++) {
+ case 0:
+ if ((data & W8001_LEAD_MASK) != W8001_LEAD_BYTE) {
+ pr_debug("w8001: unsynchronized data: 0x%02x\n", data);
+ w8001->idx = 0;
+ }
+ break;
+ case 8:
+ tmp = w8001->data[0] & W8001_TAB_MASK;
+ if (unlikely(tmp == W8001_TAB_BYTE))
+ break;
+ w8001->idx = 0;
+ memset(&coord, 0, sizeof(coord));
+ parse_data(w8001->data, &coord);
+ input_report_abs(dev, ABS_X, coord.x);
+ input_report_abs(dev, ABS_Y, coord.y);
+ input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure);
+ input_report_key(dev, BTN_TOUCH, coord.tsw);
+ input_sync(dev);
+ break;
+ case 10:
+ w8001->idx = 0;
+ memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN);
+ w8001->expected_packet = W8001_QUERY_PACKET;
+ complete(&w8001->cmd_done);
+ break;
+ }
+}
+
+
+static irqreturn_t w8001_interrupt(struct serio *serio,
+ unsigned char data, unsigned int flags)
+{
+ struct w8001 *w8001 = serio_get_drvdata(serio);
+
+ w8001_process_data(w8001, data);
+
+ return IRQ_HANDLED;
+}
+
+static int w8001_async_command(struct w8001 *w8001, unsigned char *packet,
+ int len)
+{
+ int rc = -1;
+ int i;
+
+ mutex_lock(&w8001->cmd_mutex);
+
+ for (i = 0; i < len; i++) {
+ if (serio_write(w8001->serio, packet[i]))
+ goto out;
+ }
+ rc = 0;
+
+out:
+ mutex_unlock(&w8001->cmd_mutex);
+ return rc;
+}
+
+static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len)
+{
+ int rc = -1;
+ int i;
+
+ mutex_lock(&w8001->cmd_mutex);
+
+ serio_pause_rx(w8001->serio);
+ init_completion(&w8001->cmd_done);
+ serio_continue_rx(w8001->serio);
+
+ for (i = 0; i < len; i++) {
+ if (serio_write(w8001->serio, packet[i]))
+ goto out;
+ }
+
+ wait_for_completion_timeout(&w8001->cmd_done, HZ);
+
+ if (w8001->expected_packet == W8001_QUERY_PACKET) {
+ /* We are back in reporting mode, the query was ACKed */
+ memcpy(packet, w8001->response, W8001_PACKET_LEN);
+ rc = 0;
+ }
+
+out:
+ mutex_unlock(&w8001->cmd_mutex);
+ return rc;
+}
+
+static int w8001_setup(struct w8001 *w8001)
+{
+ struct w8001_coord coord;
+ struct input_dev *dev = w8001->dev;
+ unsigned char start[1] = { '1' };
+ unsigned char query[11] = { '*' };
+
+ if (w8001_command(w8001, query, 1))
+ return -1;
+
+ memset(&coord, 0, sizeof(coord));
+ parse_data(query, &coord);
+
+ input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
+ input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
+ input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
+ input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
+ input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
+
+ if (w8001_async_command(w8001, start, 1))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * w8001_disconnect() is the opposite of w8001_connect()
+ */
+
+static void w8001_disconnect(struct serio *serio)
+{
+ struct w8001 *w8001 = serio_get_drvdata(serio);
+
+ input_get_device(w8001->dev);
+ input_unregister_device(w8001->dev);
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ input_put_device(w8001->dev);
+ kfree(w8001);
+}
+
+/*
+ * w8001_connect() is the routine that is called when someone adds a
+ * new serio device that supports the w8001 protocol and registers it as
+ * an input device.
+ */
+
+static int w8001_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct w8001 *w8001;
+ struct input_dev *input_dev;
+ int err;
+
+ w8001 = kzalloc(sizeof(struct w8001), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!w8001 || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ w8001->serio = serio;
+ w8001->id = serio->id.id;
+ w8001->dev = input_dev;
+ mutex_init(&w8001->cmd_mutex);
+ init_completion(&w8001->cmd_done);
+ snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
+
+ input_dev->name = "Wacom W8001 Penabled Serial TouchScreen";
+ input_dev->phys = w8001->phys;
+ input_dev->id.bustype = BUS_RS232;
+ input_dev->id.vendor = SERIO_W8001;
+ input_dev->id.product = w8001->id;
+ input_dev->id.version = 0x0100;
+ input_dev->dev.parent = &serio->dev;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ serio_set_drvdata(serio, w8001);
+ err = serio_open(serio, drv);
+ if (err)
+ goto fail2;
+
+ if (w8001_setup(w8001))
+ goto fail3;
+
+ err = input_register_device(w8001->dev);
+ if (err)
+ goto fail3;
+
+ return 0;
+
+fail3:
+ serio_close(serio);
+fail2:
+ serio_set_drvdata(serio, NULL);
+fail1:
+ input_free_device(input_dev);
+ kfree(w8001);
+ return err;
+}
+
+static struct serio_device_id w8001_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_W8001,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, w8001_serio_ids);
+
+static struct serio_driver w8001_drv = {
+ .driver = {
+ .name = "w8001",
+ },
+ .description = DRIVER_DESC,
+ .id_table = w8001_serio_ids,
+ .interrupt = w8001_interrupt,
+ .connect = w8001_connect,
+ .disconnect = w8001_disconnect,
+};
+
+static int __init w8001_init(void)
+{
+ return serio_register_driver(&w8001_drv);
+}
+
+static void __exit w8001_exit(void)
+{
+ serio_unregister_driver(&w8001_drv);
+}
+
+module_init(w8001_init);
+module_exit(w8001_exit);
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index d5b4cc357a3c..650120261abf 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -1519,7 +1519,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
int digit2 = 0;
if (!isdigit(*s)) return -3;
while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
- if (digit1 <= 0 && digit1 > 30) return -4;
+ if (digit1 <= 0 || digit1 > 30) return -4;
if (*s == 0 || *s == ',' || *s == ' ') {
bmask |= (1 << digit1);
digit1 = 0;
@@ -1530,7 +1530,7 @@ static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
s++;
if (!isdigit(*s)) return -3;
while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
- if (digit2 <= 0 && digit2 > 30) return -4;
+ if (digit2 <= 0 || digit2 > 30) return -4;
if (*s == 0 || *s == ',' || *s == ' ') {
if (digit1 > digit2)
for (i = digit2; i <= digit1 ; i++)
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 0aa66ec4cbdd..b129409925af 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -111,8 +111,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent)
goto fail;
inode->i_ino = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_blocks = 0;
- inode->i_uid = inode->i_gid = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h
index 016410cf2273..8ea587783e14 100644
--- a/drivers/isdn/hardware/eicon/debuglib.h
+++ b/drivers/isdn/hardware/eicon/debuglib.h
@@ -235,7 +235,7 @@ typedef void ( * DbgOld) (unsigned short, char *, va_list) ;
typedef void ( * DbgEv) (unsigned short, unsigned long, va_list) ;
typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ;
typedef struct _DbgHandle_
-{ char Registered ; /* driver successfull registered */
+{ char Registered ; /* driver successfully registered */
#define DBG_HANDLE_REG_NEW 0x01 /* this (new) structure */
#define DBG_HANDLE_REG_OLD 0x7f /* old structure (see below) */
char Version; /* version of this structure */
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c
index 7b4ec3f60dbf..c964b8d91ada 100644
--- a/drivers/isdn/hardware/eicon/os_4bri.c
+++ b/drivers/isdn/hardware/eicon/os_4bri.c
@@ -997,7 +997,7 @@ diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
diva_xdi_display_adapter_features(IoAdapter->ANum);
for (i = 0; i < IoAdapter->tasks; i++) {
- DBG_LOG(("A(%d) %s adapter successfull started",
+ DBG_LOG(("A(%d) %s adapter successfully started",
IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
(IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c
index f31bba5b16ff..08f01993f46b 100644
--- a/drivers/isdn/hardware/eicon/os_bri.c
+++ b/drivers/isdn/hardware/eicon/os_bri.c
@@ -736,7 +736,7 @@ diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
IoAdapter->Properties.Features = (word) features;
diva_xdi_display_adapter_features(IoAdapter->ANum);
- DBG_LOG(("A(%d) BRI adapter successfull started", IoAdapter->ANum))
+ DBG_LOG(("A(%d) BRI adapter successfully started", IoAdapter->ANum))
/*
Register with DIDD
*/
diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c
index 903356547b79..5d65405c75f4 100644
--- a/drivers/isdn/hardware/eicon/os_pri.c
+++ b/drivers/isdn/hardware/eicon/os_pri.c
@@ -513,7 +513,7 @@ diva_pri_start_adapter(PISDN_ADAPTER IoAdapter,
diva_xdi_display_adapter_features(IoAdapter->ANum);
- DBG_LOG(("A(%d) PRI adapter successfull started", IoAdapter->ANum))
+ DBG_LOG(("A(%d) PRI adapter successfully started", IoAdapter->ANum))
/*
Register with DIDD
*/
diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig
index 14793480c453..fd112ae252cf 100644
--- a/drivers/isdn/hardware/mISDN/Kconfig
+++ b/drivers/isdn/hardware/mISDN/Kconfig
@@ -23,3 +23,10 @@ config MISDN_HFCMULTI
* HFC-8S (8 S/T interfaces on one chip)
* HFC-E1 (E1 interface for 2Mbit ISDN)
+config MISDN_HFCUSB
+ tristate "Support for HFC-S USB based TAs"
+ depends on USB
+ help
+ Enable support for USB ISDN TAs with Cologne Chip AG's
+ HFC-S USB ISDN Controller
+
diff --git a/drivers/isdn/hardware/mISDN/Makefile b/drivers/isdn/hardware/mISDN/Makefile
index 1e7ca5332ad7..b0403526bbba 100644
--- a/drivers/isdn/hardware/mISDN/Makefile
+++ b/drivers/isdn/hardware/mISDN/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_MISDN_HFCPCI) += hfcpci.o
obj-$(CONFIG_MISDN_HFCMULTI) += hfcmulti.o
+obj-$(CONFIG_MISDN_HFCUSB) += hfcsusb.o
diff --git a/drivers/isdn/hardware/mISDN/hfc_multi.h b/drivers/isdn/hardware/mISDN/hfc_multi.h
index 7bbf7300593d..663b77f578be 100644
--- a/drivers/isdn/hardware/mISDN/hfc_multi.h
+++ b/drivers/isdn/hardware/mISDN/hfc_multi.h
@@ -2,10 +2,6 @@
* see notice in hfc_multi.c
*/
-extern void ztdummy_extern_interrupt(void);
-extern void ztdummy_register_interrupt(void);
-extern int ztdummy_unregister_interrupt(void);
-
#define DEBUG_HFCMULTI_FIFO 0x00010000
#define DEBUG_HFCMULTI_CRC 0x00020000
#define DEBUG_HFCMULTI_INIT 0x00040000
@@ -13,6 +9,7 @@ extern int ztdummy_unregister_interrupt(void);
#define DEBUG_HFCMULTI_MODE 0x00100000
#define DEBUG_HFCMULTI_MSG 0x00200000
#define DEBUG_HFCMULTI_STATE 0x00400000
+#define DEBUG_HFCMULTI_FILL 0x00800000
#define DEBUG_HFCMULTI_SYNC 0x01000000
#define DEBUG_HFCMULTI_DTMF 0x02000000
#define DEBUG_HFCMULTI_LOCK 0x80000000
@@ -170,6 +167,8 @@ struct hfc_multi {
u_long chip; /* chip configuration */
int masterclk; /* port that provides master clock -1=off */
+ unsigned char silence;/* silence byte */
+ unsigned char silence_data[128];/* silence block */
int dtmf; /* flag that dtmf is currently in process */
int Flen; /* F-buffer size */
int Zlen; /* Z-buffer size (must be int for calculation)*/
@@ -198,6 +197,9 @@ struct hfc_multi {
spinlock_t lock; /* the lock */
+ struct mISDNclock *iclock; /* isdn clock support */
+ int iclock_on;
+
/*
* the channel index is counted from 0, regardless where the channel
* is located on the hfc-channel.
diff --git a/drivers/isdn/hardware/mISDN/hfc_pci.h b/drivers/isdn/hardware/mISDN/hfc_pci.h
index 5783d22a18fe..3132ddc99fcd 100644
--- a/drivers/isdn/hardware/mISDN/hfc_pci.h
+++ b/drivers/isdn/hardware/mISDN/hfc_pci.h
@@ -26,7 +26,7 @@
* change mask and threshold simultaneously
*/
#define HFCPCI_BTRANS_THRESHOLD 128
-#define HFCPCI_BTRANS_MAX 256
+#define HFCPCI_FILLEMPTY 64
#define HFCPCI_BTRANS_THRESMASK 0x00
/* defines for PCI config */
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c
index c63e2f49da8a..595ba8eb4a07 100644
--- a/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ b/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -133,6 +133,12 @@
* Give the value of the clock control register (A_ST_CLK_DLY)
* of the S/T interfaces in TE mode.
* This register is needed for the TBR3 certification, so don't change it.
+ *
+ * clock:
+ * NOTE: only one clock value must be given once
+ * Selects interface with clock source for mISDN and applications.
+ * Set to card number starting with 1. Set to -1 to disable.
+ * By default, the first card is used as clock source.
*/
/*
@@ -140,7 +146,7 @@
* #define HFC_REGISTER_DEBUG
*/
-static const char *hfcmulti_revision = "2.02";
+#define HFC_MULTI_VERSION "2.03"
#include <linux/module.h>
#include <linux/pci.h>
@@ -165,10 +171,6 @@ static LIST_HEAD(HFClist);
static spinlock_t HFClock; /* global hfc list lock */
static void ph_state_change(struct dchannel *);
-static void (*hfc_interrupt)(void);
-static void (*register_interrupt)(void);
-static int (*unregister_interrupt)(void);
-static int interrupt_registered;
static struct hfc_multi *syncmaster;
static int plxsd_master; /* if we have a master card (yet) */
@@ -184,7 +186,6 @@ static int nt_t1_count[] = { 3840, 1920, 960, 480, 240, 120, 60, 30 };
#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
#define CLKDEL_NT 0x6c /* CLKDEL in NT mode
(0x60 MUST be included!) */
-static u_char silence = 0xff; /* silence by LAW */
#define DIP_4S 0x1 /* DIP Switches for Beronet 1S/2S/4S cards */
#define DIP_8S 0x2 /* DIP Switches for Beronet 8S+ cards */
@@ -195,12 +196,13 @@ static u_char silence = 0xff; /* silence by LAW */
*/
static uint type[MAX_CARDS];
-static uint pcm[MAX_CARDS];
-static uint dslot[MAX_CARDS];
+static int pcm[MAX_CARDS];
+static int dslot[MAX_CARDS];
static uint iomode[MAX_CARDS];
static uint port[MAX_PORTS];
static uint debug;
static uint poll;
+static int clock;
static uint timer;
static uint clockdelay_te = CLKDEL_TE;
static uint clockdelay_nt = CLKDEL_NT;
@@ -209,14 +211,16 @@ static int HFC_cnt, Port_cnt, PCM_cnt = 99;
MODULE_AUTHOR("Andreas Eversberg");
MODULE_LICENSE("GPL");
+MODULE_VERSION(HFC_MULTI_VERSION);
module_param(debug, uint, S_IRUGO | S_IWUSR);
module_param(poll, uint, S_IRUGO | S_IWUSR);
+module_param(clock, int, S_IRUGO | S_IWUSR);
module_param(timer, uint, S_IRUGO | S_IWUSR);
module_param(clockdelay_te, uint, S_IRUGO | S_IWUSR);
module_param(clockdelay_nt, uint, S_IRUGO | S_IWUSR);
module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR);
-module_param_array(pcm, uint, NULL, S_IRUGO | S_IWUSR);
-module_param_array(dslot, uint, NULL, S_IRUGO | S_IWUSR);
+module_param_array(pcm, int, NULL, S_IRUGO | S_IWUSR);
+module_param_array(dslot, int, NULL, S_IRUGO | S_IWUSR);
module_param_array(iomode, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR);
@@ -1419,19 +1423,6 @@ controller_fail:
HFC_outb(hc, R_TI_WD, poll_timer);
hc->hw.r_irqmsk_misc |= V_TI_IRQMSK;
- /*
- * set up 125us interrupt, only if function pointer is available
- * and module parameter timer is set
- */
- if (timer && hfc_interrupt && register_interrupt) {
- /* only one chip should use this interrupt */
- timer = 0;
- interrupt_registered = 1;
- hc->hw.r_irqmsk_misc |= V_PROC_IRQMSK;
- /* deactivate other interrupts in ztdummy */
- register_interrupt();
- }
-
/* set E1 state machine IRQ */
if (hc->type == 1)
hc->hw.r_irqmsk_misc |= V_STA_IRQMSK;
@@ -1991,6 +1982,17 @@ next_frame:
return; /* no data */
}
+ /* "fill fifo if empty" feature */
+ if (bch && test_bit(FLG_FILLEMPTY, &bch->Flags)
+ && !test_bit(FLG_HDLC, &bch->Flags) && z2 == z1) {
+ if (debug & DEBUG_HFCMULTI_FILL)
+ printk(KERN_DEBUG "%s: buffer empty, so we have "
+ "underrun\n", __func__);
+ /* fill buffer, to prevent future underrun */
+ hc->write_fifo(hc, hc->silence_data, poll >> 1);
+ Zspace -= (poll >> 1);
+ }
+
/* if audio data and connected slot */
if (bch && (!test_bit(FLG_HDLC, &bch->Flags)) && (!*txpending)
&& slot_tx >= 0) {
@@ -2027,7 +2029,6 @@ next_frame:
__func__, hc->id + 1, ch, Zspace, z1, z2, ii-i, len-i,
temp ? "HDLC":"TRANS");
-
/* Have to prep the audio data */
hc->write_fifo(hc, d, ii - i);
*idxp = ii;
@@ -2066,7 +2067,7 @@ next_frame:
* no more data at all. this prevents sending an undefined value.
*/
if (bch && test_bit(FLG_TRANSPARENT, &bch->Flags))
- HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
+ HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
}
@@ -2583,7 +2584,6 @@ hfcmulti_interrupt(int intno, void *dev_id)
static int iq1 = 0, iq2 = 0, iq3 = 0, iq4 = 0,
iq5 = 0, iq6 = 0, iqcnt = 0;
#endif
- static int count;
struct hfc_multi *hc = dev_id;
struct dchannel *dch;
u_char r_irq_statech, status, r_irq_misc, r_irq_oview;
@@ -2637,6 +2637,7 @@ hfcmulti_interrupt(int intno, void *dev_id)
iqcnt = 0;
}
#endif
+
if (!r_irq_statech &&
!(status & (V_DTMF_STA | V_LOST_STA | V_EXT_IRQSTA |
V_MISC_IRQSTA | V_FR_IRQSTA))) {
@@ -2657,6 +2658,7 @@ hfcmulti_interrupt(int intno, void *dev_id)
if (status & V_MISC_IRQSTA) {
/* misc IRQ */
r_irq_misc = HFC_inb_nodebug(hc, R_IRQ_MISC);
+ r_irq_misc &= hc->hw.r_irqmsk_misc; /* ignore disabled irqs */
if (r_irq_misc & V_STA_IRQ) {
if (hc->type == 1) {
/* state machine */
@@ -2691,23 +2693,20 @@ hfcmulti_interrupt(int intno, void *dev_id)
plxsd_checksync(hc, 0);
}
}
- if (r_irq_misc & V_TI_IRQ)
+ if (r_irq_misc & V_TI_IRQ) {
+ if (hc->iclock_on)
+ mISDN_clock_update(hc->iclock, poll, NULL);
handle_timer_irq(hc);
+ }
if (r_irq_misc & V_DTMF_IRQ) {
- /* -> DTMF IRQ */
hfcmulti_dtmf(hc);
}
- /* TODO: REPLACE !!!! 125 us Interrupts are not acceptable */
if (r_irq_misc & V_IRQ_PROC) {
- /* IRQ every 125us */
- count++;
- /* generate 1kHz signal */
- if (count == 8) {
- if (hfc_interrupt)
- hfc_interrupt();
- count = 0;
- }
+ static int irq_proc_cnt;
+ if (!irq_proc_cnt++)
+ printk(KERN_WARNING "%s: got V_IRQ_PROC -"
+ " this should not happen\n", __func__);
}
}
@@ -2954,7 +2953,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
HFC_wait(hc);
/* tx silence */
- HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
+ HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
HFC_outb(hc, R_SLOT, (((ch / 4) * 8) +
((ch % 4) * 4)) << 1);
HFC_outb(hc, A_SL_CFG, 0x80 | 0x20 | (ch << 1));
@@ -2969,7 +2968,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx,
HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
HFC_wait(hc);
/* tx silence */
- HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, silence);
+ HFC_outb_nodebug(hc, A_FIFO_DATA0_NOINC, hc->silence);
/* enable RX fifo */
HFC_outb(hc, R_FIFO, (ch<<1)|1);
HFC_wait(hc);
@@ -3461,7 +3460,7 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
cq->op = MISDN_CTRL_HFC_OP | MISDN_CTRL_HW_FEATURES_OP
- | MISDN_CTRL_RX_OFF;
+ | MISDN_CTRL_RX_OFF | MISDN_CTRL_FILL_EMPTY;
break;
case MISDN_CTRL_RX_OFF: /* turn off / on rx stream */
hc->chan[bch->slot].rx_off = !!cq->p1;
@@ -3476,6 +3475,12 @@ channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
printk(KERN_DEBUG "%s: RX_OFF request (nr=%d off=%d)\n",
__func__, bch->nr, hc->chan[bch->slot].rx_off);
break;
+ case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
+ test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
+ if (debug & DEBUG_HFCMULTI_MSG)
+ printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
+ "off=%d)\n", __func__, bch->nr, !!cq->p1);
+ break;
case MISDN_CTRL_HW_FEATURES: /* fill features structure */
if (debug & DEBUG_HFCMULTI_MSG)
printk(KERN_DEBUG "%s: HW_FEATURE request\n",
@@ -3610,7 +3615,7 @@ hfcm_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
static void
ph_state_change(struct dchannel *dch)
{
- struct hfc_multi *hc = dch->hw;
+ struct hfc_multi *hc;
int ch, i;
if (!dch) {
@@ -3618,6 +3623,7 @@ ph_state_change(struct dchannel *dch)
__func__);
return;
}
+ hc = dch->hw;
ch = dch->slot;
if (hc->type == 1) {
@@ -3992,6 +3998,7 @@ open_bchannel(struct hfc_multi *hc, struct dchannel *dch,
}
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
hc->chan[ch].rx_off = 0;
rq->ch = &bch->ch;
@@ -4081,6 +4088,15 @@ hfcm_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
return err;
}
+static int
+clockctl(void *priv, int enable)
+{
+ struct hfc_multi *hc = priv;
+
+ hc->iclock_on = enable;
+ return 0;
+}
+
/*
* initialize the card
*/
@@ -4495,10 +4511,14 @@ release_card(struct hfc_multi *hc)
printk(KERN_WARNING "%s: release card (%d) entered\n",
__func__, hc->id);
+ /* unregister clock source */
+ if (hc->iclock)
+ mISDN_unregister_clock(hc->iclock);
+
+ /* disable irq */
spin_lock_irqsave(&hc->lock, flags);
disable_hwirq(hc);
spin_unlock_irqrestore(&hc->lock, flags);
-
udelay(1000);
/* dimm leds */
@@ -4699,7 +4719,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m)
} else
hc->chan[hc->dslot].jitter = 2; /* default */
snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-e1.%d", HFC_cnt + 1);
- ret = mISDN_register_device(&dch->dev, name);
+ ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
if (ret)
goto free_chan;
hc->created[0] = 1;
@@ -4807,9 +4827,9 @@ init_multi_port(struct hfc_multi *hc, int pt)
test_and_set_bit(HFC_CFG_DIS_ECHANNEL,
&hc->chan[i + 2].cfg);
}
- snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d/%d",
+ snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-%ds.%d-%d",
hc->type, HFC_cnt + 1, pt + 1);
- ret = mISDN_register_device(&dch->dev, name);
+ ret = mISDN_register_device(&dch->dev, &hc->pci_dev->dev, name);
if (ret)
goto free_chan;
hc->created[pt] = 1;
@@ -4828,6 +4848,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
struct hfc_multi *hc;
u_long flags;
u_char dips = 0, pmj = 0; /* dip settings, port mode Jumpers */
+ int i;
if (HFC_cnt >= MAX_CARDS) {
printk(KERN_ERR "too many cards (max=%d).\n",
@@ -4861,11 +4882,11 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
hc->id = HFC_cnt;
hc->pcm = pcm[HFC_cnt];
hc->io_mode = iomode[HFC_cnt];
- if (dslot[HFC_cnt] < 0) {
+ if (dslot[HFC_cnt] < 0 && hc->type == 1) {
hc->dslot = 0;
printk(KERN_INFO "HFC-E1 card has disabled D-channel, but "
"31 B-channels\n");
- } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32) {
+ } if (dslot[HFC_cnt] > 0 && dslot[HFC_cnt] < 32 && hc->type == 1) {
hc->dslot = dslot[HFC_cnt];
printk(KERN_INFO "HFC-E1 card has alternating D-channel on "
"time slot %d\n", dslot[HFC_cnt]);
@@ -4876,9 +4897,17 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
hc->masterclk = -1;
if (type[HFC_cnt] & 0x100) {
test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
- silence = 0xff; /* ulaw silence */
+ hc->silence = 0xff; /* ulaw silence */
} else
- silence = 0x2a; /* alaw silence */
+ hc->silence = 0x2a; /* alaw silence */
+ if ((poll >> 1) > sizeof(hc->silence_data)) {
+ printk(KERN_ERR "HFCMULTI error: silence_data too small, "
+ "please fix\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < (poll >> 1); i++)
+ hc->silence_data[i] = hc->silence;
+
if (!(type[HFC_cnt] & 0x200))
test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
@@ -4945,9 +4974,7 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
switch (m->dip_type) {
case DIP_4S:
/*
- * get DIP Setting for beroNet 1S/2S/4S cards
- * check if Port Jumper config matches
- * module param 'protocol'
+ * Get DIP setting for beroNet 1S/2S/4S cards
* DIP Setting: (collect GPIO 13/14/15 (R_GPIO_IN1) +
* GPI 19/23 (R_GPI_IN2))
*/
@@ -4966,9 +4993,8 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
case DIP_8S:
/*
- * get DIP Setting for beroNet 8S0+ cards
- *
- * enable PCI auxbridge function
+ * Get DIP Setting for beroNet 8S0+ cards
+ * Enable PCI auxbridge function
*/
HFC_outb(hc, R_BRG_PCM_CFG, 1 | V_PCM_CLK);
/* prepare access to auxport */
@@ -5003,6 +5029,10 @@ hfcmulti_init(struct pci_dev *pdev, const struct pci_device_id *ent)
list_add_tail(&hc->list, &HFClist);
spin_unlock_irqrestore(&HFClock, flags);
+ /* use as clock source */
+ if (clock == HFC_cnt + 1)
+ hc->iclock = mISDN_register_clock("HFCMulti", 0, clockctl, hc);
+
/* initialize hardware */
ret_err = init_card(hc);
if (ret_err) {
@@ -5137,8 +5167,7 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = {
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
PCI_DEVICE_ID_CCD_HFC8S, 0, 0, H(14)}, /* old Eval */
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
- PCI_SUBDEVICE_ID_CCD_IOB8STR, 0, 0, H(15)},
- /* IOB8ST Recording */
+ PCI_SUBDEVICE_ID_CCD_IOB8STR, 0, 0, H(15)}, /* IOB8ST Recording */
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
PCI_SUBDEVICE_ID_CCD_IOB8ST, 0, 0, H(16)}, /* IOB8ST */
{ PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
@@ -5188,18 +5217,16 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct hm_map *m = (struct hm_map *)ent->driver_data;
int ret;
- if (m == NULL) {
- if (ent->vendor == PCI_VENDOR_ID_CCD)
- if (ent->device == PCI_DEVICE_ID_CCD_HFC4S ||
- ent->device == PCI_DEVICE_ID_CCD_HFC8S ||
- ent->device == PCI_DEVICE_ID_CCD_HFCE1)
- printk(KERN_ERR
- "unknown HFC multiport controller "
- "(vendor:%x device:%x subvendor:%x "
- "subdevice:%x) Please contact the "
- "driver maintainer for support.\n",
- ent->vendor, ent->device,
- ent->subvendor, ent->subdevice);
+ if (m == NULL && ent->vendor == PCI_VENDOR_ID_CCD && (
+ ent->device == PCI_DEVICE_ID_CCD_HFC4S ||
+ ent->device == PCI_DEVICE_ID_CCD_HFC8S ||
+ ent->device == PCI_DEVICE_ID_CCD_HFCE1)) {
+ printk(KERN_ERR
+ "Unknown HFC multiport controller (vendor:%x device:%x "
+ "subvendor:%x subdevice:%x)\n", ent->vendor, ent->device,
+ ent->subvendor, ent->subdevice);
+ printk(KERN_ERR
+ "Please contact the driver maintainer for support.\n");
return -ENODEV;
}
ret = hfcmulti_init(pdev, ent);
@@ -5222,22 +5249,9 @@ HFCmulti_cleanup(void)
{
struct hfc_multi *card, *next;
- /* unload interrupt function symbol */
- if (hfc_interrupt)
- symbol_put(ztdummy_extern_interrupt);
- if (register_interrupt)
- symbol_put(ztdummy_register_interrupt);
- if (unregister_interrupt) {
- if (interrupt_registered) {
- interrupt_registered = 0;
- unregister_interrupt();
- }
- symbol_put(ztdummy_unregister_interrupt);
- }
-
+ /* get rid of all devices of this driver */
list_for_each_entry_safe(card, next, &HFClist, list)
release_card(card);
- /* get rid of all devices of this driver */
pci_unregister_driver(&hfcmultipci_driver);
}
@@ -5246,8 +5260,10 @@ HFCmulti_init(void)
{
int err;
+ printk(KERN_INFO "mISDN: HFC-multi driver %s\n", HFC_MULTI_VERSION);
+
#ifdef IRQ_DEBUG
- printk(KERN_ERR "%s: IRQ_DEBUG IS ENABLED!\n", __func__);
+ printk(KERN_DEBUG "%s: IRQ_DEBUG IS ENABLED!\n", __func__);
#endif
spin_lock_init(&HFClock);
@@ -5256,22 +5272,11 @@ HFCmulti_init(void)
if (debug & DEBUG_HFCMULTI_INIT)
printk(KERN_DEBUG "%s: init entered\n", __func__);
- hfc_interrupt = symbol_get(ztdummy_extern_interrupt);
- register_interrupt = symbol_get(ztdummy_register_interrupt);
- unregister_interrupt = symbol_get(ztdummy_unregister_interrupt);
- printk(KERN_INFO "mISDN: HFC-multi driver %s\n",
- hfcmulti_revision);
-
switch (poll) {
case 0:
poll_timer = 6;
poll = 128;
break;
- /*
- * wenn dieses break nochmal verschwindet,
- * gibt es heisse ohren :-)
- * "without the break you will get hot ears ???"
- */
case 8:
poll_timer = 2;
break;
@@ -5298,20 +5303,12 @@ HFCmulti_init(void)
}
+ if (!clock)
+ clock = 1;
+
err = pci_register_driver(&hfcmultipci_driver);
if (err < 0) {
printk(KERN_ERR "error registering pci driver: %x\n", err);
- if (hfc_interrupt)
- symbol_put(ztdummy_extern_interrupt);
- if (register_interrupt)
- symbol_put(ztdummy_register_interrupt);
- if (unregister_interrupt) {
- if (interrupt_registered) {
- interrupt_registered = 0;
- unregister_interrupt();
- }
- symbol_put(ztdummy_unregister_interrupt);
- }
return err;
}
return 0;
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index cd8302af40eb..f0e14dfcf71d 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -23,6 +23,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Module options:
+ *
+ * debug:
+ * NOTE: only one poll value must be given for all cards
+ * See hfc_pci.h for debug flags.
+ *
+ * poll:
+ * NOTE: only one poll value must be given for all cards
+ * Give the number of samples for each fifo process.
+ * By default 128 is used. Decrease to reduce delay, increase to
+ * reduce cpu load. If unsure, don't mess with it!
+ * A value of 128 will use controller's interrupt. Other values will
+ * use kernel timer, because the controller will not allow lower values
+ * than 128.
+ * Also note that the value depends on the kernel timer frequency.
+ * If kernel uses a frequency of 1000 Hz, steps of 8 samples are possible.
+ * If the kernel uses 100 Hz, steps of 80 samples are possible.
+ * If the kernel uses 300 Hz, steps of about 26 samples are possible.
+ *
*/
#include <linux/module.h>
@@ -34,16 +53,16 @@
static const char *hfcpci_revision = "2.0";
-#define MAX_CARDS 8
static int HFC_cnt;
static uint debug;
+static uint poll, tics;
+struct timer_list hfc_tl;
+u32 hfc_jiffies;
MODULE_AUTHOR("Karsten Keil");
MODULE_LICENSE("GPL");
-module_param(debug, uint, 0);
-
-static LIST_HEAD(HFClist);
-static DEFINE_RWLOCK(HFClock);
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+module_param(poll, uint, S_IRUGO | S_IWUSR);
enum {
HFC_CCD_2BD0,
@@ -114,7 +133,6 @@ struct hfcPCI_hw {
struct hfc_pci {
- struct list_head list;
u_char subtype;
u_char chanlimit;
u_char initdone;
@@ -520,9 +538,9 @@ receive_dmsg(struct hfc_pci *hc)
}
/*
- * check for transparent receive data and read max one threshold size if avail
+ * check for transparent receive data and read max one 'poll' size if avail
*/
-static int
+static void
hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
{
__le16 *z1r, *z2r;
@@ -534,17 +552,19 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r);
if (!fcnt)
- return 0; /* no data avail */
+ return; /* no data avail */
if (fcnt <= 0)
fcnt += B_FIFO_SIZE; /* bytes actually buffered */
- if (fcnt > HFCPCI_BTRANS_THRESHOLD)
- fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */
-
new_z2 = le16_to_cpu(*z2r) + fcnt; /* new position in fifo */
if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
new_z2 -= B_FIFO_SIZE; /* buffer wrap */
+ if (fcnt > MAX_DATA_SIZE) { /* flush, if oversized */
+ *z2r = cpu_to_le16(new_z2); /* new position */
+ return;
+ }
+
bch->rx_skb = mI_alloc_skb(fcnt, GFP_ATOMIC);
if (bch->rx_skb) {
ptr = skb_put(bch->rx_skb, fcnt);
@@ -569,7 +589,6 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *bz, u_char *bdata)
printk(KERN_WARNING "HFCPCI: receive out of memory\n");
*z2r = cpu_to_le16(new_z2); /* new position */
- return 1;
}
/*
@@ -580,12 +599,11 @@ main_rec_hfcpci(struct bchannel *bch)
{
struct hfc_pci *hc = bch->hw;
int rcnt, real_fifo;
- int receive, count = 5;
+ int receive = 0, count = 5;
struct bzfifo *bz;
u_char *bdata;
struct zt *zp;
-
if ((bch->nr & 2) && (!hc->hw.bswapped)) {
bz = &((union fifo_area *)(hc->hw.fifos))->b_chans.rxbz_b2;
bdata = ((union fifo_area *)(hc->hw.fifos))->b_chans.rxdat_b2;
@@ -625,9 +643,10 @@ Begin:
receive = 1;
else
receive = 0;
- } else if (test_bit(FLG_TRANSPARENT, &bch->Flags))
- receive = hfcpci_empty_fifo_trans(bch, bz, bdata);
- else
+ } else if (test_bit(FLG_TRANSPARENT, &bch->Flags)) {
+ hfcpci_empty_fifo_trans(bch, bz, bdata);
+ return;
+ } else
receive = 0;
if (count && receive)
goto Begin;
@@ -751,11 +770,41 @@ hfcpci_fill_fifo(struct bchannel *bch)
/* fcnt contains available bytes in fifo */
fcnt = B_FIFO_SIZE - fcnt;
/* remaining bytes to send (bytes in fifo) */
+
+ /* "fill fifo if empty" feature */
+ if (test_bit(FLG_FILLEMPTY, &bch->Flags) && !fcnt) {
+ /* printk(KERN_DEBUG "%s: buffer empty, so we have "
+ "underrun\n", __func__); */
+ /* fill buffer, to prevent future underrun */
+ count = HFCPCI_FILLEMPTY;
+ new_z1 = le16_to_cpu(*z1t) + count;
+ /* new buffer Position */
+ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+ new_z1 -= B_FIFO_SIZE; /* buffer wrap */
+ dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL);
+ maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t);
+ /* end of fifo */
+ if (bch->debug & DEBUG_HW_BFIFO)
+ printk(KERN_DEBUG "hfcpci_FFt fillempty "
+ "fcnt(%d) maxl(%d) nz1(%x) dst(%p)\n",
+ fcnt, maxlen, new_z1, dst);
+ fcnt += count;
+ if (maxlen > count)
+ maxlen = count; /* limit size */
+ memset(dst, 0x2a, maxlen); /* first copy */
+ count -= maxlen; /* remaining bytes */
+ if (count) {
+ dst = bdata; /* start of buffer */
+ memset(dst, 0x2a, count);
+ }
+ *z1t = cpu_to_le16(new_z1); /* now send data */
+ }
+
next_t_frame:
count = bch->tx_skb->len - bch->tx_idx;
- /* maximum fill shall be HFCPCI_BTRANS_MAX */
- if (count > HFCPCI_BTRANS_MAX - fcnt)
- count = HFCPCI_BTRANS_MAX - fcnt;
+ /* maximum fill shall be poll*2 */
+ if (count > (poll << 1) - fcnt)
+ count = (poll << 1) - fcnt;
if (count <= 0)
return;
/* data is suitable for fifo */
@@ -1135,37 +1184,37 @@ hfcpci_int(int intno, void *dev_id)
val &= ~0x80;
Write_hfc(hc, HFCPCI_CTMT, hc->hw.ctmt | HFCPCI_CLTIMER);
}
- if (val & 0x08) {
+ if (val & 0x08) { /* B1 rx */
bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
if (bch)
main_rec_hfcpci(bch);
else if (hc->dch.debug)
printk(KERN_DEBUG "hfcpci spurious 0x08 IRQ\n");
}
- if (val & 0x10) {
+ if (val & 0x10) { /* B2 rx */
bch = Sel_BCS(hc, 2);
if (bch)
main_rec_hfcpci(bch);
else if (hc->dch.debug)
printk(KERN_DEBUG "hfcpci spurious 0x10 IRQ\n");
}
- if (val & 0x01) {
+ if (val & 0x01) { /* B1 tx */
bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
if (bch)
tx_birq(bch);
else if (hc->dch.debug)
printk(KERN_DEBUG "hfcpci spurious 0x01 IRQ\n");
}
- if (val & 0x02) {
+ if (val & 0x02) { /* B2 tx */
bch = Sel_BCS(hc, 2);
if (bch)
tx_birq(bch);
else if (hc->dch.debug)
printk(KERN_DEBUG "hfcpci spurious 0x02 IRQ\n");
}
- if (val & 0x20)
+ if (val & 0x20) /* D rx */
receive_dmsg(hc);
- if (val & 0x04) { /* dframe transmitted */
+ if (val & 0x04) { /* D tx */
if (test_and_clear_bit(FLG_BUSY_TIMER, &hc->dch.Flags))
del_timer(&hc->dch.timer);
tx_dirq(&hc->dch);
@@ -1283,14 +1332,16 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol)
}
if (fifo2 & 2) {
hc->hw.fifo_en |= HFCPCI_FIFOEN_B2;
- hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
- HFCPCI_INTS_B2REC);
+ if (!tics)
+ hc->hw.int_m1 |= (HFCPCI_INTS_B2TRANS +
+ HFCPCI_INTS_B2REC);
hc->hw.ctmt |= 2;
hc->hw.conn &= ~0x18;
} else {
hc->hw.fifo_en |= HFCPCI_FIFOEN_B1;
- hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
- HFCPCI_INTS_B1REC);
+ if (!tics)
+ hc->hw.int_m1 |= (HFCPCI_INTS_B1TRANS +
+ HFCPCI_INTS_B1REC);
hc->hw.ctmt |= 1;
hc->hw.conn &= ~0x03;
}
@@ -1398,7 +1449,8 @@ set_hfcpci_rxtest(struct bchannel *bch, int protocol, int chan)
if (chan & 2) {
hc->hw.sctrl_r |= SCTRL_B2_ENA;
hc->hw.fifo_en |= HFCPCI_FIFOEN_B2RX;
- hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
+ if (!tics)
+ hc->hw.int_m1 |= HFCPCI_INTS_B2REC;
hc->hw.ctmt |= 2;
hc->hw.conn &= ~0x18;
#ifdef REVERSE_BITORDER
@@ -1407,7 +1459,8 @@ set_hfcpci_rxtest(struct bchannel *bch, int protocol, int chan)
} else {
hc->hw.sctrl_r |= SCTRL_B1_ENA;
hc->hw.fifo_en |= HFCPCI_FIFOEN_B1RX;
- hc->hw.int_m1 |= HFCPCI_INTS_B1REC;
+ if (!tics)
+ hc->hw.int_m1 |= HFCPCI_INTS_B1REC;
hc->hw.ctmt |= 1;
hc->hw.conn &= ~0x03;
#ifdef REVERSE_BITORDER
@@ -1481,11 +1534,17 @@ deactivate_bchannel(struct bchannel *bch)
static int
channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
{
- int ret = 0;
+ int ret = 0;
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = 0;
+ cq->op = MISDN_CTRL_FILL_EMPTY;
+ break;
+ case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
+ test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
+ if (debug & DEBUG_HW_OPEN)
+ printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
+ "off=%d)\n", __func__, bch->nr, !!cq->p1);
break;
default:
printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
@@ -1859,6 +1918,10 @@ open_dchannel(struct hfc_pci *hc, struct mISDNchannel *ch,
hc->dch.dev.id, __builtin_return_address(0));
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
+ if (rq->adr.channel == 1) {
+ /* TODO: E-Channel */
+ return -EINVAL;
+ }
if (!hc->initdone) {
if (rq->protocol == ISDN_P_TE_S0) {
err = create_l1(&hc->dch, hfc_l1callback);
@@ -1874,6 +1937,11 @@ open_dchannel(struct hfc_pci *hc, struct mISDNchannel *ch,
if (rq->protocol != ch->protocol) {
if (hc->hw.protocol == ISDN_P_TE_S0)
l1_event(hc->dch.l1, CLOSE_CHANNEL);
+ if (rq->protocol == ISDN_P_TE_S0) {
+ err = create_l1(&hc->dch, hfc_l1callback);
+ if (err)
+ return err;
+ }
hc->hw.protocol = rq->protocol;
ch->protocol = rq->protocol;
hfcpci_setmode(hc);
@@ -1903,6 +1971,7 @@ open_bchannel(struct hfc_pci *hc, struct channel_req *rq)
bch = &hc->bch[rq->adr.channel - 1];
if (test_and_set_bit(FLG_OPEN, &bch->Flags))
return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
bch->ch.protocol = rq->protocol;
rq->ch = &bch->ch; /* TODO: E-channel */
if (!try_module_get(THIS_MODULE))
@@ -1928,7 +1997,8 @@ hfc_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
switch (cmd) {
case OPEN_CHANNEL:
rq = arg;
- if (rq->adr.channel == 0)
+ if ((rq->protocol == ISDN_P_TE_S0) ||
+ (rq->protocol == ISDN_P_NT_S0))
err = open_dchannel(hc, ch, rq);
else
err = open_bchannel(hc, rq);
@@ -2027,7 +2097,6 @@ release_card(struct hfc_pci *hc) {
mISDN_freebchannel(&hc->bch[1]);
mISDN_freebchannel(&hc->bch[0]);
mISDN_freedchannel(&hc->dch);
- list_del(&hc->list);
pci_set_drvdata(hc->pdev, NULL);
kfree(hc);
}
@@ -2037,12 +2106,8 @@ setup_card(struct hfc_pci *card)
{
int err = -EINVAL;
u_int i;
- u_long flags;
char name[MISDN_MAX_IDLEN];
- if (HFC_cnt >= MAX_CARDS)
- return -EINVAL; /* maybe better value */
-
card->dch.debug = debug;
spin_lock_init(&card->lock);
mISDN_initdchannel(&card->dch, MAX_DFRAME_LEN_L1, ph_state);
@@ -2068,13 +2133,10 @@ setup_card(struct hfc_pci *card)
if (err)
goto error;
snprintf(name, MISDN_MAX_IDLEN - 1, "hfc-pci.%d", HFC_cnt + 1);
- err = mISDN_register_device(&card->dch.dev, name);
+ err = mISDN_register_device(&card->dch.dev, &card->pdev->dev, name);
if (err)
goto error;
HFC_cnt++;
- write_lock_irqsave(&HFClock, flags);
- list_add_tail(&card->list, &HFClist);
- write_unlock_irqrestore(&HFClock, flags);
printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt);
return 0;
error:
@@ -2210,15 +2272,12 @@ static void __devexit
hfc_remove_pci(struct pci_dev *pdev)
{
struct hfc_pci *card = pci_get_drvdata(pdev);
- u_long flags;
- if (card) {
- write_lock_irqsave(&HFClock, flags);
+ if (card)
release_card(card);
- write_unlock_irqrestore(&HFClock, flags);
- } else
+ else
if (debug)
- printk(KERN_WARNING "%s: drvdata allready removed\n",
+ printk(KERN_WARNING "%s: drvdata already removed\n",
__func__);
}
@@ -2230,25 +2289,97 @@ static struct pci_driver hfc_driver = {
.id_table = hfc_ids,
};
+static int
+_hfcpci_softirq(struct device *dev, void *arg)
+{
+ struct hfc_pci *hc = dev_get_drvdata(dev);
+ struct bchannel *bch;
+ if (hc == NULL)
+ return 0;
+
+ if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
+ spin_lock(&hc->lock);
+ bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
+ if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
+ main_rec_hfcpci(bch);
+ tx_birq(bch);
+ }
+ bch = Sel_BCS(hc, hc->hw.bswapped ? 1 : 2);
+ if (bch && bch->state == ISDN_P_B_RAW) { /* B2 rx&tx */
+ main_rec_hfcpci(bch);
+ tx_birq(bch);
+ }
+ spin_unlock(&hc->lock);
+ }
+ return 0;
+}
+
+static void
+hfcpci_softirq(void *arg)
+{
+ (void) driver_for_each_device(&hfc_driver.driver, NULL, arg,
+ _hfcpci_softirq);
+
+ /* if next event would be in the past ... */
+ if ((s32)(hfc_jiffies + tics - jiffies) <= 0)
+ hfc_jiffies = jiffies + 1;
+ else
+ hfc_jiffies += tics;
+ hfc_tl.expires = hfc_jiffies;
+ add_timer(&hfc_tl);
+}
+
static int __init
HFC_init(void)
{
int err;
+ if (!poll)
+ poll = HFCPCI_BTRANS_THRESHOLD;
+
+ if (poll != HFCPCI_BTRANS_THRESHOLD) {
+ tics = (poll * HZ) / 8000;
+ if (tics < 1)
+ tics = 1;
+ poll = (tics * 8000) / HZ;
+ if (poll > 256 || poll < 8) {
+ printk(KERN_ERR "%s: Wrong poll value %d not in range "
+ "of 8..256.\n", __func__, poll);
+ err = -EINVAL;
+ return err;
+ }
+ }
+ if (poll != HFCPCI_BTRANS_THRESHOLD) {
+ printk(KERN_INFO "%s: Using alternative poll value of %d\n",
+ __func__, poll);
+ hfc_tl.function = (void *)hfcpci_softirq;
+ hfc_tl.data = 0;
+ init_timer(&hfc_tl);
+ hfc_tl.expires = jiffies + tics;
+ hfc_jiffies = hfc_tl.expires;
+ add_timer(&hfc_tl);
+ } else
+ tics = 0; /* indicate the use of controller's timer */
+
err = pci_register_driver(&hfc_driver);
+ if (err) {
+ if (timer_pending(&hfc_tl))
+ del_timer(&hfc_tl);
+ }
+
return err;
}
static void __exit
HFC_cleanup(void)
{
- struct hfc_pci *card, *next;
+ if (timer_pending(&hfc_tl))
+ del_timer(&hfc_tl);
- list_for_each_entry_safe(card, next, &HFClist, list) {
- release_card(card);
- }
pci_unregister_driver(&hfc_driver);
}
module_init(HFC_init);
module_exit(HFC_cleanup);
+
+MODULE_DEVICE_TABLE(pci, hfc_ids);
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
new file mode 100644
index 000000000000..ba6925fbf38a
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -0,0 +1,2196 @@
+/* hfcsusb.c
+ * mISDN driver for Colognechip HFC-S USB chip
+ *
+ * Copyright 2001 by Peter Sprenger (sprenger@moving-bytes.de)
+ * Copyright 2008 by Martin Bachem (info@bachem-it.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * module params
+ * debug=<n>, default=0, with n=0xHHHHGGGG
+ * H - l1 driver flags described in hfcsusb.h
+ * G - common mISDN debug flags described at mISDNhw.h
+ *
+ * poll=<n>, default 128
+ * n : burst size of PH_DATA_IND at transparent rx data
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/usb.h>
+#include <linux/mISDNhw.h>
+#include "hfcsusb.h"
+
+const char *hfcsusb_rev = "Revision: 0.3.3 (socket), 2008-11-05";
+
+static unsigned int debug;
+static int poll = DEFAULT_TRANSP_BURST_SZ;
+
+static LIST_HEAD(HFClist);
+static DEFINE_RWLOCK(HFClock);
+
+
+MODULE_AUTHOR("Martin Bachem");
+MODULE_LICENSE("GPL");
+module_param(debug, uint, S_IRUGO | S_IWUSR);
+module_param(poll, int, 0);
+
+static int hfcsusb_cnt;
+
+/* some function prototypes */
+static void hfcsusb_ph_command(struct hfcsusb *hw, u_char command);
+static void release_hw(struct hfcsusb *hw);
+static void reset_hfcsusb(struct hfcsusb *hw);
+static void setPortMode(struct hfcsusb *hw);
+static void hfcsusb_start_endpoint(struct hfcsusb *hw, int channel);
+static void hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel);
+static int hfcsusb_setup_bch(struct bchannel *bch, int protocol);
+static void deactivate_bchannel(struct bchannel *bch);
+static void hfcsusb_ph_info(struct hfcsusb *hw);
+
+/* start next background transfer for control channel */
+static void
+ctrl_start_transfer(struct hfcsusb *hw)
+{
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+
+ if (hw->ctrl_cnt) {
+ hw->ctrl_urb->pipe = hw->ctrl_out_pipe;
+ hw->ctrl_urb->setup_packet = (u_char *)&hw->ctrl_write;
+ hw->ctrl_urb->transfer_buffer = NULL;
+ hw->ctrl_urb->transfer_buffer_length = 0;
+ hw->ctrl_write.wIndex =
+ cpu_to_le16(hw->ctrl_buff[hw->ctrl_out_idx].hfcs_reg);
+ hw->ctrl_write.wValue =
+ cpu_to_le16(hw->ctrl_buff[hw->ctrl_out_idx].reg_val);
+
+ usb_submit_urb(hw->ctrl_urb, GFP_ATOMIC);
+ }
+}
+
+/*
+ * queue a control transfer request to write HFC-S USB
+ * chip register using CTRL resuest queue
+ */
+static int write_reg(struct hfcsusb *hw, __u8 reg, __u8 val)
+{
+ struct ctrl_buf *buf;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s reg(0x%02x) val(0x%02x)\n",
+ hw->name, __func__, reg, val);
+
+ spin_lock(&hw->ctrl_lock);
+ if (hw->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+ return 1;
+ buf = &hw->ctrl_buff[hw->ctrl_in_idx];
+ buf->hfcs_reg = reg;
+ buf->reg_val = val;
+ if (++hw->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
+ hw->ctrl_in_idx = 0;
+ if (++hw->ctrl_cnt == 1)
+ ctrl_start_transfer(hw);
+ spin_unlock(&hw->ctrl_lock);
+
+ return 0;
+}
+
+/* control completion routine handling background control cmds */
+static void
+ctrl_complete(struct urb *urb)
+{
+ struct hfcsusb *hw = (struct hfcsusb *) urb->context;
+ struct ctrl_buf *buf;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+
+ urb->dev = hw->dev;
+ if (hw->ctrl_cnt) {
+ buf = &hw->ctrl_buff[hw->ctrl_out_idx];
+ hw->ctrl_cnt--; /* decrement actual count */
+ if (++hw->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
+ hw->ctrl_out_idx = 0; /* pointer wrap */
+
+ ctrl_start_transfer(hw); /* start next transfer */
+ }
+}
+
+/* handle LED bits */
+static void
+set_led_bit(struct hfcsusb *hw, signed short led_bits, int set_on)
+{
+ if (set_on) {
+ if (led_bits < 0)
+ hw->led_state &= ~abs(led_bits);
+ else
+ hw->led_state |= led_bits;
+ } else {
+ if (led_bits < 0)
+ hw->led_state |= abs(led_bits);
+ else
+ hw->led_state &= ~led_bits;
+ }
+}
+
+/* handle LED requests */
+static void
+handle_led(struct hfcsusb *hw, int event)
+{
+ struct hfcsusb_vdata *driver_info = (struct hfcsusb_vdata *)
+ hfcsusb_idtab[hw->vend_idx].driver_info;
+ __u8 tmpled;
+
+ if (driver_info->led_scheme == LED_OFF)
+ return;
+ tmpled = hw->led_state;
+
+ switch (event) {
+ case LED_POWER_ON:
+ set_led_bit(hw, driver_info->led_bits[0], 1);
+ set_led_bit(hw, driver_info->led_bits[1], 0);
+ set_led_bit(hw, driver_info->led_bits[2], 0);
+ set_led_bit(hw, driver_info->led_bits[3], 0);
+ break;
+ case LED_POWER_OFF:
+ set_led_bit(hw, driver_info->led_bits[0], 0);
+ set_led_bit(hw, driver_info->led_bits[1], 0);
+ set_led_bit(hw, driver_info->led_bits[2], 0);
+ set_led_bit(hw, driver_info->led_bits[3], 0);
+ break;
+ case LED_S0_ON:
+ set_led_bit(hw, driver_info->led_bits[1], 1);
+ break;
+ case LED_S0_OFF:
+ set_led_bit(hw, driver_info->led_bits[1], 0);
+ break;
+ case LED_B1_ON:
+ set_led_bit(hw, driver_info->led_bits[2], 1);
+ break;
+ case LED_B1_OFF:
+ set_led_bit(hw, driver_info->led_bits[2], 0);
+ break;
+ case LED_B2_ON:
+ set_led_bit(hw, driver_info->led_bits[3], 1);
+ break;
+ case LED_B2_OFF:
+ set_led_bit(hw, driver_info->led_bits[3], 0);
+ break;
+ }
+
+ if (hw->led_state != tmpled) {
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s reg(0x%02x) val(x%02x)\n",
+ hw->name, __func__,
+ HFCUSB_P_DATA, hw->led_state);
+
+ write_reg(hw, HFCUSB_P_DATA, hw->led_state);
+ }
+}
+
+/*
+ * Layer2 -> Layer 1 Bchannel data
+ */
+static int
+hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ struct hfcsusb *hw = bch->hw;
+ int ret = -EINVAL;
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ u_long flags;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ spin_lock_irqsave(&hw->lock, flags);
+ ret = bchannel_senddata(bch, skb);
+ spin_unlock_irqrestore(&hw->lock, flags);
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s PH_DATA_REQ ret(%i)\n",
+ hw->name, __func__, ret);
+ if (ret > 0) {
+ /*
+ * other l1 drivers don't send early confirms on
+ * transp data, but hfcsusb does because tx_next
+ * skb is needed in tx_iso_complete()
+ */
+ queue_ch_frame(ch, PH_DATA_CNF, hh->id, NULL);
+ ret = 0;
+ }
+ return ret;
+ case PH_ACTIVATE_REQ:
+ if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
+ hfcsusb_start_endpoint(hw, bch->nr);
+ ret = hfcsusb_setup_bch(bch, ch->protocol);
+ } else
+ ret = 0;
+ if (!ret)
+ _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
+ 0, NULL, GFP_KERNEL);
+ break;
+ case PH_DEACTIVATE_REQ:
+ deactivate_bchannel(bch);
+ _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY,
+ 0, NULL, GFP_KERNEL);
+ ret = 0;
+ break;
+ }
+ if (!ret)
+ dev_kfree_skb(skb);
+ return ret;
+}
+
+/*
+ * send full D/B channel status information
+ * as MPH_INFORMATION_IND
+ */
+static void
+hfcsusb_ph_info(struct hfcsusb *hw)
+{
+ struct ph_info *phi;
+ struct dchannel *dch = &hw->dch;
+ int i;
+
+ phi = kzalloc(sizeof(struct ph_info) +
+ dch->dev.nrbchan * sizeof(struct ph_info_ch), GFP_ATOMIC);
+ phi->dch.ch.protocol = hw->protocol;
+ phi->dch.ch.Flags = dch->Flags;
+ phi->dch.state = dch->state;
+ phi->dch.num_bch = dch->dev.nrbchan;
+ for (i = 0; i < dch->dev.nrbchan; i++) {
+ phi->bch[i].protocol = hw->bch[i].ch.protocol;
+ phi->bch[i].Flags = hw->bch[i].Flags;
+ }
+ _queue_data(&dch->dev.D, MPH_INFORMATION_IND, MISDN_ID_ANY,
+ sizeof(struct ph_info_dch) + dch->dev.nrbchan *
+ sizeof(struct ph_info_ch), phi, GFP_ATOMIC);
+}
+
+/*
+ * Layer2 -> Layer 1 Dchannel data
+ */
+static int
+hfcusb_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct mISDNhead *hh = mISDN_HEAD_P(skb);
+ struct hfcsusb *hw = dch->hw;
+ int ret = -EINVAL;
+ u_long flags;
+
+ switch (hh->prim) {
+ case PH_DATA_REQ:
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s: PH_DATA_REQ\n",
+ hw->name, __func__);
+
+ spin_lock_irqsave(&hw->lock, flags);
+ ret = dchannel_senddata(dch, skb);
+ spin_unlock_irqrestore(&hw->lock, flags);
+ if (ret > 0) {
+ ret = 0;
+ queue_ch_frame(ch, PH_DATA_CNF, hh->id, NULL);
+ }
+ break;
+
+ case PH_ACTIVATE_REQ:
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s: PH_ACTIVATE_REQ %s\n",
+ hw->name, __func__,
+ (hw->protocol == ISDN_P_NT_S0) ? "NT" : "TE");
+
+ if (hw->protocol == ISDN_P_NT_S0) {
+ ret = 0;
+ if (test_bit(FLG_ACTIVE, &dch->Flags)) {
+ _queue_data(&dch->dev.D,
+ PH_ACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_ATOMIC);
+ } else {
+ hfcsusb_ph_command(hw,
+ HFC_L1_ACTIVATE_NT);
+ test_and_set_bit(FLG_L2_ACTIVATED,
+ &dch->Flags);
+ }
+ } else {
+ hfcsusb_ph_command(hw, HFC_L1_ACTIVATE_TE);
+ ret = l1_event(dch->l1, hh->prim);
+ }
+ break;
+
+ case PH_DEACTIVATE_REQ:
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s: PH_DEACTIVATE_REQ\n",
+ hw->name, __func__);
+ test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
+
+ if (hw->protocol == ISDN_P_NT_S0) {
+ hfcsusb_ph_command(hw, HFC_L1_DEACTIVATE_NT);
+ spin_lock_irqsave(&hw->lock, flags);
+ skb_queue_purge(&dch->squeue);
+ if (dch->tx_skb) {
+ dev_kfree_skb(dch->tx_skb);
+ dch->tx_skb = NULL;
+ }
+ dch->tx_idx = 0;
+ if (dch->rx_skb) {
+ dev_kfree_skb(dch->rx_skb);
+ dch->rx_skb = NULL;
+ }
+ test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+ spin_unlock_irqrestore(&hw->lock, flags);
+#ifdef FIXME
+ if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
+ dchannel_sched_event(&hc->dch, D_CLEARBUSY);
+#endif
+ ret = 0;
+ } else
+ ret = l1_event(dch->l1, hh->prim);
+ break;
+ case MPH_INFORMATION_REQ:
+ hfcsusb_ph_info(hw);
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Layer 1 callback function
+ */
+static int
+hfc_l1callback(struct dchannel *dch, u_int cmd)
+{
+ struct hfcsusb *hw = dch->hw;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s cmd 0x%x\n",
+ hw->name, __func__, cmd);
+
+ switch (cmd) {
+ case INFO3_P8:
+ case INFO3_P10:
+ case HW_RESET_REQ:
+ case HW_POWERUP_REQ:
+ break;
+
+ case HW_DEACT_REQ:
+ skb_queue_purge(&dch->squeue);
+ if (dch->tx_skb) {
+ dev_kfree_skb(dch->tx_skb);
+ dch->tx_skb = NULL;
+ }
+ dch->tx_idx = 0;
+ if (dch->rx_skb) {
+ dev_kfree_skb(dch->rx_skb);
+ dch->rx_skb = NULL;
+ }
+ test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
+ break;
+ case PH_ACTIVATE_IND:
+ test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+ GFP_ATOMIC);
+ break;
+ case PH_DEACTIVATE_IND:
+ test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, cmd, MISDN_ID_ANY, 0, NULL,
+ GFP_ATOMIC);
+ break;
+ default:
+ if (dch->debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: unknown cmd %x\n",
+ hw->name, __func__, cmd);
+ return -1;
+ }
+ hfcsusb_ph_info(hw);
+ return 0;
+}
+
+static int
+open_dchannel(struct hfcsusb *hw, struct mISDNchannel *ch,
+ struct channel_req *rq)
+{
+ int err = 0;
+
+ if (debug & DEBUG_HW_OPEN)
+ printk(KERN_DEBUG "%s: %s: dev(%d) open addr(%i) from %p\n",
+ hw->name, __func__, hw->dch.dev.id, rq->adr.channel,
+ __builtin_return_address(0));
+ if (rq->protocol == ISDN_P_NONE)
+ return -EINVAL;
+
+ test_and_clear_bit(FLG_ACTIVE, &hw->dch.Flags);
+ test_and_clear_bit(FLG_ACTIVE, &hw->ech.Flags);
+ hfcsusb_start_endpoint(hw, HFC_CHAN_D);
+
+ /* E-Channel logging */
+ if (rq->adr.channel == 1) {
+ if (hw->fifos[HFCUSB_PCM_RX].pipe) {
+ hfcsusb_start_endpoint(hw, HFC_CHAN_E);
+ set_bit(FLG_ACTIVE, &hw->ech.Flags);
+ _queue_data(&hw->ech.dev.D, PH_ACTIVATE_IND,
+ MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+ } else
+ return -EINVAL;
+ }
+
+ if (!hw->initdone) {
+ hw->protocol = rq->protocol;
+ if (rq->protocol == ISDN_P_TE_S0) {
+ err = create_l1(&hw->dch, hfc_l1callback);
+ if (err)
+ return err;
+ }
+ setPortMode(hw);
+ ch->protocol = rq->protocol;
+ hw->initdone = 1;
+ } else {
+ if (rq->protocol != ch->protocol)
+ return -EPROTONOSUPPORT;
+ }
+
+ if (((ch->protocol == ISDN_P_NT_S0) && (hw->dch.state == 3)) ||
+ ((ch->protocol == ISDN_P_TE_S0) && (hw->dch.state == 7)))
+ _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY,
+ 0, NULL, GFP_KERNEL);
+ rq->ch = ch;
+ if (!try_module_get(THIS_MODULE))
+ printk(KERN_WARNING "%s: %s: cannot get module\n",
+ hw->name, __func__);
+ return 0;
+}
+
+static int
+open_bchannel(struct hfcsusb *hw, struct channel_req *rq)
+{
+ struct bchannel *bch;
+
+ if (rq->adr.channel > 2)
+ return -EINVAL;
+ if (rq->protocol == ISDN_P_NONE)
+ return -EINVAL;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s B%i\n",
+ hw->name, __func__, rq->adr.channel);
+
+ bch = &hw->bch[rq->adr.channel - 1];
+ if (test_and_set_bit(FLG_OPEN, &bch->Flags))
+ return -EBUSY; /* b-channel can be only open once */
+ test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags);
+ bch->ch.protocol = rq->protocol;
+ rq->ch = &bch->ch;
+
+ /* start USB endpoint for bchannel */
+ if (rq->adr.channel == 1)
+ hfcsusb_start_endpoint(hw, HFC_CHAN_B1);
+ else
+ hfcsusb_start_endpoint(hw, HFC_CHAN_B2);
+
+ if (!try_module_get(THIS_MODULE))
+ printk(KERN_WARNING "%s: %s:cannot get module\n",
+ hw->name, __func__);
+ return 0;
+}
+
+static int
+channel_ctrl(struct hfcsusb *hw, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s op(0x%x) channel(0x%x)\n",
+ hw->name, __func__, (cq->op), (cq->channel));
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_CONNECT |
+ MISDN_CTRL_DISCONNECT;
+ break;
+ default:
+ printk(KERN_WARNING "%s: %s: unknown Op %x\n",
+ hw->name, __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+/*
+ * device control function
+ */
+static int
+hfc_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+ struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
+ struct dchannel *dch = container_of(dev, struct dchannel, dev);
+ struct hfcsusb *hw = dch->hw;
+ struct channel_req *rq;
+ int err = 0;
+
+ if (dch->debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: cmd:%x %p\n",
+ hw->name, __func__, cmd, arg);
+ switch (cmd) {
+ case OPEN_CHANNEL:
+ rq = arg;
+ if ((rq->protocol == ISDN_P_TE_S0) ||
+ (rq->protocol == ISDN_P_NT_S0))
+ err = open_dchannel(hw, ch, rq);
+ else
+ err = open_bchannel(hw, rq);
+ if (!err)
+ hw->open++;
+ break;
+ case CLOSE_CHANNEL:
+ hw->open--;
+ if (debug & DEBUG_HW_OPEN)
+ printk(KERN_DEBUG
+ "%s: %s: dev(%d) close from %p (open %d)\n",
+ hw->name, __func__, hw->dch.dev.id,
+ __builtin_return_address(0), hw->open);
+ if (!hw->open) {
+ hfcsusb_stop_endpoint(hw, HFC_CHAN_D);
+ if (hw->fifos[HFCUSB_PCM_RX].pipe)
+ hfcsusb_stop_endpoint(hw, HFC_CHAN_E);
+ handle_led(hw, LED_POWER_ON);
+ }
+ module_put(THIS_MODULE);
+ break;
+ case CONTROL_CHANNEL:
+ err = channel_ctrl(hw, arg);
+ break;
+ default:
+ if (dch->debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: unknown command %x\n",
+ hw->name, __func__, cmd);
+ return -EINVAL;
+ }
+ return err;
+}
+
+/*
+ * S0 TE state change event handler
+ */
+static void
+ph_state_te(struct dchannel *dch)
+{
+ struct hfcsusb *hw = dch->hw;
+
+ if (debug & DEBUG_HW) {
+ if (dch->state <= HFC_MAX_TE_LAYER1_STATE)
+ printk(KERN_DEBUG "%s: %s: %s\n", hw->name, __func__,
+ HFC_TE_LAYER1_STATES[dch->state]);
+ else
+ printk(KERN_DEBUG "%s: %s: TE F%d\n",
+ hw->name, __func__, dch->state);
+ }
+
+ switch (dch->state) {
+ case 0:
+ l1_event(dch->l1, HW_RESET_IND);
+ break;
+ case 3:
+ l1_event(dch->l1, HW_DEACT_IND);
+ break;
+ case 5:
+ case 8:
+ l1_event(dch->l1, ANYSIGNAL);
+ break;
+ case 6:
+ l1_event(dch->l1, INFO2);
+ break;
+ case 7:
+ l1_event(dch->l1, INFO4_P8);
+ break;
+ }
+ if (dch->state == 7)
+ handle_led(hw, LED_S0_ON);
+ else
+ handle_led(hw, LED_S0_OFF);
+}
+
+/*
+ * S0 NT state change event handler
+ */
+static void
+ph_state_nt(struct dchannel *dch)
+{
+ struct hfcsusb *hw = dch->hw;
+
+ if (debug & DEBUG_HW) {
+ if (dch->state <= HFC_MAX_NT_LAYER1_STATE)
+ printk(KERN_DEBUG "%s: %s: %s\n",
+ hw->name, __func__,
+ HFC_NT_LAYER1_STATES[dch->state]);
+
+ else
+ printk(KERN_INFO DRIVER_NAME "%s: %s: NT G%d\n",
+ hw->name, __func__, dch->state);
+ }
+
+ switch (dch->state) {
+ case (1):
+ test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+ test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
+ hw->nt_timer = 0;
+ hw->timers &= ~NT_ACTIVATION_TIMER;
+ handle_led(hw, LED_S0_OFF);
+ break;
+
+ case (2):
+ if (hw->nt_timer < 0) {
+ hw->nt_timer = 0;
+ hw->timers &= ~NT_ACTIVATION_TIMER;
+ hfcsusb_ph_command(dch->hw, HFC_L1_DEACTIVATE_NT);
+ } else {
+ hw->timers |= NT_ACTIVATION_TIMER;
+ hw->nt_timer = NT_T1_COUNT;
+ /* allow G2 -> G3 transition */
+ write_reg(hw, HFCUSB_STATES, 2 | HFCUSB_NT_G2_G3);
+ }
+ break;
+ case (3):
+ hw->nt_timer = 0;
+ hw->timers &= ~NT_ACTIVATION_TIMER;
+ test_and_set_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, PH_ACTIVATE_IND,
+ MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+ handle_led(hw, LED_S0_ON);
+ break;
+ case (4):
+ hw->nt_timer = 0;
+ hw->timers &= ~NT_ACTIVATION_TIMER;
+ break;
+ default:
+ break;
+ }
+ hfcsusb_ph_info(hw);
+}
+
+static void
+ph_state(struct dchannel *dch)
+{
+ struct hfcsusb *hw = dch->hw;
+
+ if (hw->protocol == ISDN_P_NT_S0)
+ ph_state_nt(dch);
+ else if (hw->protocol == ISDN_P_TE_S0)
+ ph_state_te(dch);
+}
+
+/*
+ * disable/enable BChannel for desired protocoll
+ */
+static int
+hfcsusb_setup_bch(struct bchannel *bch, int protocol)
+{
+ struct hfcsusb *hw = bch->hw;
+ __u8 conhdlc, sctrl, sctrl_r;
+
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: protocol %x-->%x B%d\n",
+ hw->name, __func__, bch->state, protocol,
+ bch->nr);
+
+ /* setup val for CON_HDLC */
+ conhdlc = 0;
+ if (protocol > ISDN_P_NONE)
+ conhdlc = 8; /* enable FIFO */
+
+ switch (protocol) {
+ case (-1): /* used for init */
+ bch->state = -1;
+ /* fall trough */
+ case (ISDN_P_NONE):
+ if (bch->state == ISDN_P_NONE)
+ return 0; /* already in idle state */
+ bch->state = ISDN_P_NONE;
+ clear_bit(FLG_HDLC, &bch->Flags);
+ clear_bit(FLG_TRANSPARENT, &bch->Flags);
+ break;
+ case (ISDN_P_B_RAW):
+ conhdlc |= 2;
+ bch->state = protocol;
+ set_bit(FLG_TRANSPARENT, &bch->Flags);
+ break;
+ case (ISDN_P_B_HDLC):
+ bch->state = protocol;
+ set_bit(FLG_HDLC, &bch->Flags);
+ break;
+ default:
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: prot not known %x\n",
+ hw->name, __func__, protocol);
+ return -ENOPROTOOPT;
+ }
+
+ if (protocol >= ISDN_P_NONE) {
+ write_reg(hw, HFCUSB_FIFO, (bch->nr == 1) ? 0 : 2);
+ write_reg(hw, HFCUSB_CON_HDLC, conhdlc);
+ write_reg(hw, HFCUSB_INC_RES_F, 2);
+ write_reg(hw, HFCUSB_FIFO, (bch->nr == 1) ? 1 : 3);
+ write_reg(hw, HFCUSB_CON_HDLC, conhdlc);
+ write_reg(hw, HFCUSB_INC_RES_F, 2);
+
+ sctrl = 0x40 + ((hw->protocol == ISDN_P_TE_S0) ? 0x00 : 0x04);
+ sctrl_r = 0x0;
+ if (test_bit(FLG_ACTIVE, &hw->bch[0].Flags)) {
+ sctrl |= 1;
+ sctrl_r |= 1;
+ }
+ if (test_bit(FLG_ACTIVE, &hw->bch[1].Flags)) {
+ sctrl |= 2;
+ sctrl_r |= 2;
+ }
+ write_reg(hw, HFCUSB_SCTRL, sctrl);
+ write_reg(hw, HFCUSB_SCTRL_R, sctrl_r);
+
+ if (protocol > ISDN_P_NONE)
+ handle_led(hw, (bch->nr == 1) ? LED_B1_ON : LED_B2_ON);
+ else
+ handle_led(hw, (bch->nr == 1) ? LED_B1_OFF :
+ LED_B2_OFF);
+ }
+ hfcsusb_ph_info(hw);
+ return 0;
+}
+
+static void
+hfcsusb_ph_command(struct hfcsusb *hw, u_char command)
+{
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: %x\n",
+ hw->name, __func__, command);
+
+ switch (command) {
+ case HFC_L1_ACTIVATE_TE:
+ /* force sending sending INFO1 */
+ write_reg(hw, HFCUSB_STATES, 0x14);
+ /* start l1 activation */
+ write_reg(hw, HFCUSB_STATES, 0x04);
+ break;
+
+ case HFC_L1_FORCE_DEACTIVATE_TE:
+ write_reg(hw, HFCUSB_STATES, 0x10);
+ write_reg(hw, HFCUSB_STATES, 0x03);
+ break;
+
+ case HFC_L1_ACTIVATE_NT:
+ if (hw->dch.state == 3)
+ _queue_data(&hw->dch.dev.D, PH_ACTIVATE_IND,
+ MISDN_ID_ANY, 0, NULL, GFP_ATOMIC);
+ else
+ write_reg(hw, HFCUSB_STATES, HFCUSB_ACTIVATE |
+ HFCUSB_DO_ACTION | HFCUSB_NT_G2_G3);
+ break;
+
+ case HFC_L1_DEACTIVATE_NT:
+ write_reg(hw, HFCUSB_STATES,
+ HFCUSB_DO_ACTION);
+ break;
+ }
+}
+
+/*
+ * Layer 1 B-channel hardware access
+ */
+static int
+channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq)
+{
+ int ret = 0;
+
+ switch (cq->op) {
+ case MISDN_CTRL_GETOP:
+ cq->op = MISDN_CTRL_FILL_EMPTY;
+ break;
+ case MISDN_CTRL_FILL_EMPTY: /* fill fifo, if empty */
+ test_and_set_bit(FLG_FILLEMPTY, &bch->Flags);
+ if (debug & DEBUG_HW_OPEN)
+ printk(KERN_DEBUG "%s: FILL_EMPTY request (nr=%d "
+ "off=%d)\n", __func__, bch->nr, !!cq->p1);
+ break;
+ default:
+ printk(KERN_WARNING "%s: unknown Op %x\n", __func__, cq->op);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+/* collect data from incoming interrupt or isochron USB data */
+static void
+hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len,
+ int finish)
+{
+ struct hfcsusb *hw = fifo->hw;
+ struct sk_buff *rx_skb = NULL;
+ int maxlen = 0;
+ int fifon = fifo->fifonum;
+ int i;
+ int hdlc = 0;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s: fifo(%i) len(%i) "
+ "dch(%p) bch(%p) ech(%p)\n",
+ hw->name, __func__, fifon, len,
+ fifo->dch, fifo->bch, fifo->ech);
+
+ if (!len)
+ return;
+
+ if ((!!fifo->dch + !!fifo->bch + !!fifo->ech) != 1) {
+ printk(KERN_DEBUG "%s: %s: undefined channel\n",
+ hw->name, __func__);
+ return;
+ }
+
+ spin_lock(&hw->lock);
+ if (fifo->dch) {
+ rx_skb = fifo->dch->rx_skb;
+ maxlen = fifo->dch->maxlen;
+ hdlc = 1;
+ }
+ if (fifo->bch) {
+ rx_skb = fifo->bch->rx_skb;
+ maxlen = fifo->bch->maxlen;
+ hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
+ }
+ if (fifo->ech) {
+ rx_skb = fifo->ech->rx_skb;
+ maxlen = fifo->ech->maxlen;
+ hdlc = 1;
+ }
+
+ if (!rx_skb) {
+ rx_skb = mI_alloc_skb(maxlen, GFP_ATOMIC);
+ if (rx_skb) {
+ if (fifo->dch)
+ fifo->dch->rx_skb = rx_skb;
+ if (fifo->bch)
+ fifo->bch->rx_skb = rx_skb;
+ if (fifo->ech)
+ fifo->ech->rx_skb = rx_skb;
+ skb_trim(rx_skb, 0);
+ } else {
+ printk(KERN_DEBUG "%s: %s: No mem for rx_skb\n",
+ hw->name, __func__);
+ spin_unlock(&hw->lock);
+ return;
+ }
+ }
+
+ if (fifo->dch || fifo->ech) {
+ /* D/E-Channel SKB range check */
+ if ((rx_skb->len + len) >= MAX_DFRAME_LEN_L1) {
+ printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
+ "for fifo(%d) HFCUSB_D_RX\n",
+ hw->name, __func__, fifon);
+ skb_trim(rx_skb, 0);
+ spin_unlock(&hw->lock);
+ return;
+ }
+ } else if (fifo->bch) {
+ /* B-Channel SKB range check */
+ if ((rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) {
+ printk(KERN_DEBUG "%s: %s: sbk mem exceeded "
+ "for fifo(%d) HFCUSB_B_RX\n",
+ hw->name, __func__, fifon);
+ skb_trim(rx_skb, 0);
+ spin_unlock(&hw->lock);
+ return;
+ }
+ }
+
+ memcpy(skb_put(rx_skb, len), data, len);
+
+ if (hdlc) {
+ /* we have a complete hdlc packet */
+ if (finish) {
+ if ((rx_skb->len > 3) &&
+ (!(rx_skb->data[rx_skb->len - 1]))) {
+ if (debug & DBG_HFC_FIFO_VERBOSE) {
+ printk(KERN_DEBUG "%s: %s: fifon(%i)"
+ " new RX len(%i): ",
+ hw->name, __func__, fifon,
+ rx_skb->len);
+ i = 0;
+ while (i < rx_skb->len)
+ printk("%02x ",
+ rx_skb->data[i++]);
+ printk("\n");
+ }
+
+ /* remove CRC & status */
+ skb_trim(rx_skb, rx_skb->len - 3);
+
+ if (fifo->dch)
+ recv_Dchannel(fifo->dch);
+ if (fifo->bch)
+ recv_Bchannel(fifo->bch);
+ if (fifo->ech)
+ recv_Echannel(fifo->ech,
+ &hw->dch);
+ } else {
+ if (debug & DBG_HFC_FIFO_VERBOSE) {
+ printk(KERN_DEBUG
+ "%s: CRC or minlen ERROR fifon(%i) "
+ "RX len(%i): ",
+ hw->name, fifon, rx_skb->len);
+ i = 0;
+ while (i < rx_skb->len)
+ printk("%02x ",
+ rx_skb->data[i++]);
+ printk("\n");
+ }
+ skb_trim(rx_skb, 0);
+ }
+ }
+ } else {
+ /* deliver transparent data to layer2 */
+ if (rx_skb->len >= poll)
+ recv_Bchannel(fifo->bch);
+ }
+ spin_unlock(&hw->lock);
+}
+
+void
+fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
+ void *buf, int num_packets, int packet_size, int interval,
+ usb_complete_t complete, void *context)
+{
+ int k;
+
+ usb_fill_bulk_urb(urb, dev, pipe, buf, packet_size * num_packets,
+ complete, context);
+
+ urb->number_of_packets = num_packets;
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->actual_length = 0;
+ urb->interval = interval;
+
+ for (k = 0; k < num_packets; k++) {
+ urb->iso_frame_desc[k].offset = packet_size * k;
+ urb->iso_frame_desc[k].length = packet_size;
+ urb->iso_frame_desc[k].actual_length = 0;
+ }
+}
+
+/* receive completion routine for all ISO tx fifos */
+static void
+rx_iso_complete(struct urb *urb)
+{
+ struct iso_urb *context_iso_urb = (struct iso_urb *) urb->context;
+ struct usb_fifo *fifo = context_iso_urb->owner_fifo;
+ struct hfcsusb *hw = fifo->hw;
+ int k, len, errcode, offset, num_isoc_packets, fifon, maxlen,
+ status, iso_status, i;
+ __u8 *buf;
+ static __u8 eof[8];
+ __u8 s0_state;
+
+ fifon = fifo->fifonum;
+ status = urb->status;
+
+ spin_lock(&hw->lock);
+ if (fifo->stop_gracefull) {
+ fifo->stop_gracefull = 0;
+ fifo->active = 0;
+ spin_unlock(&hw->lock);
+ return;
+ }
+ spin_unlock(&hw->lock);
+
+ /*
+ * ISO transfer only partially completed,
+ * look at individual frame status for details
+ */
+ if (status == -EXDEV) {
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: with -EXDEV "
+ "urb->status %d, fifonum %d\n",
+ hw->name, __func__, status, fifon);
+
+ /* clear status, so go on with ISO transfers */
+ status = 0;
+ }
+
+ s0_state = 0;
+ if (fifo->active && !status) {
+ num_isoc_packets = iso_packets[fifon];
+ maxlen = fifo->usb_packet_maxlen;
+
+ for (k = 0; k < num_isoc_packets; ++k) {
+ len = urb->iso_frame_desc[k].actual_length;
+ offset = urb->iso_frame_desc[k].offset;
+ buf = context_iso_urb->buffer + offset;
+ iso_status = urb->iso_frame_desc[k].status;
+
+ if (iso_status && (debug & DBG_HFC_FIFO_VERBOSE)) {
+ printk(KERN_DEBUG "%s: %s: "
+ "ISO packet %i, status: %i\n",
+ hw->name, __func__, k, iso_status);
+ }
+
+ /* USB data log for every D ISO in */
+ if ((fifon == HFCUSB_D_RX) &&
+ (debug & DBG_HFC_USB_VERBOSE)) {
+ printk(KERN_DEBUG
+ "%s: %s: %d (%d/%d) len(%d) ",
+ hw->name, __func__, urb->start_frame,
+ k, num_isoc_packets-1,
+ len);
+ for (i = 0; i < len; i++)
+ printk("%x ", buf[i]);
+ printk("\n");
+ }
+
+ if (!iso_status) {
+ if (fifo->last_urblen != maxlen) {
+ /*
+ * save fifo fill-level threshold bits
+ * to use them later in TX ISO URB
+ * completions
+ */
+ hw->threshold_mask = buf[1];
+
+ if (fifon == HFCUSB_D_RX)
+ s0_state = (buf[0] >> 4);
+
+ eof[fifon] = buf[0] & 1;
+ if (len > 2)
+ hfcsusb_rx_frame(fifo, buf + 2,
+ len - 2, (len < maxlen)
+ ? eof[fifon] : 0);
+ } else
+ hfcsusb_rx_frame(fifo, buf, len,
+ (len < maxlen) ?
+ eof[fifon] : 0);
+ fifo->last_urblen = len;
+ }
+ }
+
+ /* signal S0 layer1 state change */
+ if ((s0_state) && (hw->initdone) &&
+ (s0_state != hw->dch.state)) {
+ hw->dch.state = s0_state;
+ schedule_event(&hw->dch, FLG_PHCHANGE);
+ }
+
+ fill_isoc_urb(urb, fifo->hw->dev, fifo->pipe,
+ context_iso_urb->buffer, num_isoc_packets,
+ fifo->usb_packet_maxlen, fifo->intervall,
+ (usb_complete_t)rx_iso_complete, urb->context);
+ errcode = usb_submit_urb(urb, GFP_ATOMIC);
+ if (errcode < 0) {
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: error submitting "
+ "ISO URB: %d\n",
+ hw->name, __func__, errcode);
+ }
+ } else {
+ if (status && (debug & DBG_HFC_URB_INFO))
+ printk(KERN_DEBUG "%s: %s: rx_iso_complete : "
+ "urb->status %d, fifonum %d\n",
+ hw->name, __func__, status, fifon);
+ }
+}
+
+/* receive completion routine for all interrupt rx fifos */
+static void
+rx_int_complete(struct urb *urb)
+{
+ int len, status, i;
+ __u8 *buf, maxlen, fifon;
+ struct usb_fifo *fifo = (struct usb_fifo *) urb->context;
+ struct hfcsusb *hw = fifo->hw;
+ static __u8 eof[8];
+
+ spin_lock(&hw->lock);
+ if (fifo->stop_gracefull) {
+ fifo->stop_gracefull = 0;
+ fifo->active = 0;
+ spin_unlock(&hw->lock);
+ return;
+ }
+ spin_unlock(&hw->lock);
+
+ fifon = fifo->fifonum;
+ if ((!fifo->active) || (urb->status)) {
+ if (debug & DBG_HFC_URB_ERROR)
+ printk(KERN_DEBUG
+ "%s: %s: RX-Fifo %i is going down (%i)\n",
+ hw->name, __func__, fifon, urb->status);
+
+ fifo->urb->interval = 0; /* cancel automatic rescheduling */
+ return;
+ }
+ len = urb->actual_length;
+ buf = fifo->buffer;
+ maxlen = fifo->usb_packet_maxlen;
+
+ /* USB data log for every D INT in */
+ if ((fifon == HFCUSB_D_RX) && (debug & DBG_HFC_USB_VERBOSE)) {
+ printk(KERN_DEBUG "%s: %s: D RX INT len(%d) ",
+ hw->name, __func__, len);
+ for (i = 0; i < len; i++)
+ printk("%02x ", buf[i]);
+ printk("\n");
+ }
+
+ if (fifo->last_urblen != fifo->usb_packet_maxlen) {
+ /* the threshold mask is in the 2nd status byte */
+ hw->threshold_mask = buf[1];
+
+ /* signal S0 layer1 state change */
+ if (hw->initdone && ((buf[0] >> 4) != hw->dch.state)) {
+ hw->dch.state = (buf[0] >> 4);
+ schedule_event(&hw->dch, FLG_PHCHANGE);
+ }
+
+ eof[fifon] = buf[0] & 1;
+ /* if we have more than the 2 status bytes -> collect data */
+ if (len > 2)
+ hfcsusb_rx_frame(fifo, buf + 2,
+ urb->actual_length - 2,
+ (len < maxlen) ? eof[fifon] : 0);
+ } else {
+ hfcsusb_rx_frame(fifo, buf, urb->actual_length,
+ (len < maxlen) ? eof[fifon] : 0);
+ }
+ fifo->last_urblen = urb->actual_length;
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: error resubmitting USB\n",
+ hw->name, __func__);
+ }
+}
+
+/* transmit completion routine for all ISO tx fifos */
+static void
+tx_iso_complete(struct urb *urb)
+{
+ struct iso_urb *context_iso_urb = (struct iso_urb *) urb->context;
+ struct usb_fifo *fifo = context_iso_urb->owner_fifo;
+ struct hfcsusb *hw = fifo->hw;
+ struct sk_buff *tx_skb;
+ int k, tx_offset, num_isoc_packets, sink, remain, current_len,
+ errcode, hdlc, i;
+ int *tx_idx;
+ int frame_complete, fifon, status;
+ __u8 threshbit;
+
+ spin_lock(&hw->lock);
+ if (fifo->stop_gracefull) {
+ fifo->stop_gracefull = 0;
+ fifo->active = 0;
+ spin_unlock(&hw->lock);
+ return;
+ }
+
+ if (fifo->dch) {
+ tx_skb = fifo->dch->tx_skb;
+ tx_idx = &fifo->dch->tx_idx;
+ hdlc = 1;
+ } else if (fifo->bch) {
+ tx_skb = fifo->bch->tx_skb;
+ tx_idx = &fifo->bch->tx_idx;
+ hdlc = test_bit(FLG_HDLC, &fifo->bch->Flags);
+ } else {
+ printk(KERN_DEBUG "%s: %s: neither BCH nor DCH\n",
+ hw->name, __func__);
+ spin_unlock(&hw->lock);
+ return;
+ }
+
+ fifon = fifo->fifonum;
+ status = urb->status;
+
+ tx_offset = 0;
+
+ /*
+ * ISO transfer only partially completed,
+ * look at individual frame status for details
+ */
+ if (status == -EXDEV) {
+ if (debug & DBG_HFC_URB_ERROR)
+ printk(KERN_DEBUG "%s: %s: "
+ "-EXDEV (%i) fifon (%d)\n",
+ hw->name, __func__, status, fifon);
+
+ /* clear status, so go on with ISO transfers */
+ status = 0;
+ }
+
+ if (fifo->active && !status) {
+ /* is FifoFull-threshold set for our channel? */
+ threshbit = (hw->threshold_mask & (1 << fifon));
+ num_isoc_packets = iso_packets[fifon];
+
+ /* predict dataflow to avoid fifo overflow */
+ if (fifon >= HFCUSB_D_TX)
+ sink = (threshbit) ? SINK_DMIN : SINK_DMAX;
+ else
+ sink = (threshbit) ? SINK_MIN : SINK_MAX;
+ fill_isoc_urb(urb, fifo->hw->dev, fifo->pipe,
+ context_iso_urb->buffer, num_isoc_packets,
+ fifo->usb_packet_maxlen, fifo->intervall,
+ (usb_complete_t)tx_iso_complete, urb->context);
+ memset(context_iso_urb->buffer, 0,
+ sizeof(context_iso_urb->buffer));
+ frame_complete = 0;
+
+ for (k = 0; k < num_isoc_packets; ++k) {
+ /* analyze tx success of previous ISO packets */
+ if (debug & DBG_HFC_URB_ERROR) {
+ errcode = urb->iso_frame_desc[k].status;
+ if (errcode) {
+ printk(KERN_DEBUG "%s: %s: "
+ "ISO packet %i, status: %i\n",
+ hw->name, __func__, k, errcode);
+ }
+ }
+
+ /* Generate next ISO Packets */
+ if (tx_skb)
+ remain = tx_skb->len - *tx_idx;
+ else
+ remain = 0;
+
+ if (remain > 0) {
+ fifo->bit_line -= sink;
+ current_len = (0 - fifo->bit_line) / 8;
+ if (current_len > 14)
+ current_len = 14;
+ if (current_len < 0)
+ current_len = 0;
+ if (remain < current_len)
+ current_len = remain;
+
+ /* how much bit do we put on the line? */
+ fifo->bit_line += current_len * 8;
+
+ context_iso_urb->buffer[tx_offset] = 0;
+ if (current_len == remain) {
+ if (hdlc) {
+ /* signal frame completion */
+ context_iso_urb->
+ buffer[tx_offset] = 1;
+ /* add 2 byte flags and 16bit
+ * CRC at end of ISDN frame */
+ fifo->bit_line += 32;
+ }
+ frame_complete = 1;
+ }
+
+ /* copy tx data to iso-urb buffer */
+ memcpy(context_iso_urb->buffer + tx_offset + 1,
+ (tx_skb->data + *tx_idx), current_len);
+ *tx_idx += current_len;
+
+ urb->iso_frame_desc[k].offset = tx_offset;
+ urb->iso_frame_desc[k].length = current_len + 1;
+
+ /* USB data log for every D ISO out */
+ if ((fifon == HFCUSB_D_RX) &&
+ (debug & DBG_HFC_USB_VERBOSE)) {
+ printk(KERN_DEBUG
+ "%s: %s (%d/%d) offs(%d) len(%d) ",
+ hw->name, __func__,
+ k, num_isoc_packets-1,
+ urb->iso_frame_desc[k].offset,
+ urb->iso_frame_desc[k].length);
+
+ for (i = urb->iso_frame_desc[k].offset;
+ i < (urb->iso_frame_desc[k].offset
+ + urb->iso_frame_desc[k].length);
+ i++)
+ printk("%x ",
+ context_iso_urb->buffer[i]);
+
+ printk(" skb->len(%i) tx-idx(%d)\n",
+ tx_skb->len, *tx_idx);
+ }
+
+ tx_offset += (current_len + 1);
+ } else {
+ urb->iso_frame_desc[k].offset = tx_offset++;
+ urb->iso_frame_desc[k].length = 1;
+ /* we lower data margin every msec */
+ fifo->bit_line -= sink;
+ if (fifo->bit_line < BITLINE_INF)
+ fifo->bit_line = BITLINE_INF;
+ }
+
+ if (frame_complete) {
+ frame_complete = 0;
+
+ if (debug & DBG_HFC_FIFO_VERBOSE) {
+ printk(KERN_DEBUG "%s: %s: "
+ "fifon(%i) new TX len(%i): ",
+ hw->name, __func__,
+ fifon, tx_skb->len);
+ i = 0;
+ while (i < tx_skb->len)
+ printk("%02x ",
+ tx_skb->data[i++]);
+ printk("\n");
+ }
+
+ dev_kfree_skb(tx_skb);
+ tx_skb = NULL;
+ if (fifo->dch && get_next_dframe(fifo->dch))
+ tx_skb = fifo->dch->tx_skb;
+ else if (fifo->bch &&
+ get_next_bframe(fifo->bch)) {
+ if (test_bit(FLG_TRANSPARENT,
+ &fifo->bch->Flags))
+ confirm_Bsend(fifo->bch);
+ tx_skb = fifo->bch->tx_skb;
+ }
+ }
+ }
+ errcode = usb_submit_urb(urb, GFP_ATOMIC);
+ if (errcode < 0) {
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG
+ "%s: %s: error submitting ISO URB: %d \n",
+ hw->name, __func__, errcode);
+ }
+
+ /*
+ * abuse DChannel tx iso completion to trigger NT mode state
+ * changes tx_iso_complete is assumed to be called every
+ * fifo->intervall (ms)
+ */
+ if ((fifon == HFCUSB_D_TX) && (hw->protocol == ISDN_P_NT_S0)
+ && (hw->timers & NT_ACTIVATION_TIMER)) {
+ if ((--hw->nt_timer) < 0)
+ schedule_event(&hw->dch, FLG_PHCHANGE);
+ }
+
+ } else {
+ if (status && (debug & DBG_HFC_URB_ERROR))
+ printk(KERN_DEBUG "%s: %s: urb->status %s (%i)"
+ "fifonum=%d\n",
+ hw->name, __func__,
+ symbolic(urb_errlist, status), status, fifon);
+ }
+ spin_unlock(&hw->lock);
+}
+
+/*
+ * allocs urbs and start isoc transfer with two pending urbs to avoid
+ * gaps in the transfer chain
+ */
+static int
+start_isoc_chain(struct usb_fifo *fifo, int num_packets_per_urb,
+ usb_complete_t complete, int packet_size)
+{
+ struct hfcsusb *hw = fifo->hw;
+ int i, k, errcode;
+
+ if (debug)
+ printk(KERN_DEBUG "%s: %s: fifo %i\n",
+ hw->name, __func__, fifo->fifonum);
+
+ /* allocate Memory for Iso out Urbs */
+ for (i = 0; i < 2; i++) {
+ if (!(fifo->iso[i].urb)) {
+ fifo->iso[i].urb =
+ usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);
+ if (!(fifo->iso[i].urb)) {
+ printk(KERN_DEBUG
+ "%s: %s: alloc urb for fifo %i failed",
+ hw->name, __func__, fifo->fifonum);
+ }
+ fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
+ fifo->iso[i].indx = i;
+
+ /* Init the first iso */
+ if (ISO_BUFFER_SIZE >=
+ (fifo->usb_packet_maxlen *
+ num_packets_per_urb)) {
+ fill_isoc_urb(fifo->iso[i].urb,
+ fifo->hw->dev, fifo->pipe,
+ fifo->iso[i].buffer,
+ num_packets_per_urb,
+ fifo->usb_packet_maxlen,
+ fifo->intervall, complete,
+ &fifo->iso[i]);
+ memset(fifo->iso[i].buffer, 0,
+ sizeof(fifo->iso[i].buffer));
+
+ for (k = 0; k < num_packets_per_urb; k++) {
+ fifo->iso[i].urb->
+ iso_frame_desc[k].offset =
+ k * packet_size;
+ fifo->iso[i].urb->
+ iso_frame_desc[k].length =
+ packet_size;
+ }
+ } else {
+ printk(KERN_DEBUG
+ "%s: %s: ISO Buffer size to small!\n",
+ hw->name, __func__);
+ }
+ }
+ fifo->bit_line = BITLINE_INF;
+
+ errcode = usb_submit_urb(fifo->iso[i].urb, GFP_KERNEL);
+ fifo->active = (errcode >= 0) ? 1 : 0;
+ fifo->stop_gracefull = 0;
+ if (errcode < 0) {
+ printk(KERN_DEBUG "%s: %s: %s URB nr:%d\n",
+ hw->name, __func__,
+ symbolic(urb_errlist, errcode), i);
+ }
+ }
+ return fifo->active;
+}
+
+static void
+stop_iso_gracefull(struct usb_fifo *fifo)
+{
+ struct hfcsusb *hw = fifo->hw;
+ int i, timeout;
+ u_long flags;
+
+ for (i = 0; i < 2; i++) {
+ spin_lock_irqsave(&hw->lock, flags);
+ if (debug)
+ printk(KERN_DEBUG "%s: %s for fifo %i.%i\n",
+ hw->name, __func__, fifo->fifonum, i);
+ fifo->stop_gracefull = 1;
+ spin_unlock_irqrestore(&hw->lock, flags);
+ }
+
+ for (i = 0; i < 2; i++) {
+ timeout = 3;
+ while (fifo->stop_gracefull && timeout--)
+ schedule_timeout_interruptible((HZ/1000)*16);
+ if (debug && fifo->stop_gracefull)
+ printk(KERN_DEBUG "%s: ERROR %s for fifo %i.%i\n",
+ hw->name, __func__, fifo->fifonum, i);
+ }
+}
+
+static void
+stop_int_gracefull(struct usb_fifo *fifo)
+{
+ struct hfcsusb *hw = fifo->hw;
+ int timeout;
+ u_long flags;
+
+ spin_lock_irqsave(&hw->lock, flags);
+ if (debug)
+ printk(KERN_DEBUG "%s: %s for fifo %i\n",
+ hw->name, __func__, fifo->fifonum);
+ fifo->stop_gracefull = 1;
+ spin_unlock_irqrestore(&hw->lock, flags);
+
+ timeout = 3;
+ while (fifo->stop_gracefull && timeout--)
+ schedule_timeout_interruptible((HZ/1000)*3);
+ if (debug && fifo->stop_gracefull)
+ printk(KERN_DEBUG "%s: ERROR %s for fifo %i\n",
+ hw->name, __func__, fifo->fifonum);
+}
+
+/* start the interrupt transfer for the given fifo */
+static void
+start_int_fifo(struct usb_fifo *fifo)
+{
+ struct hfcsusb *hw = fifo->hw;
+ int errcode;
+
+ if (debug)
+ printk(KERN_DEBUG "%s: %s: INT IN fifo:%d\n",
+ hw->name, __func__, fifo->fifonum);
+
+ if (!fifo->urb) {
+ fifo->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!fifo->urb)
+ return;
+ }
+ usb_fill_int_urb(fifo->urb, fifo->hw->dev, fifo->pipe,
+ fifo->buffer, fifo->usb_packet_maxlen,
+ (usb_complete_t)rx_int_complete, fifo, fifo->intervall);
+ fifo->active = 1;
+ fifo->stop_gracefull = 0;
+ errcode = usb_submit_urb(fifo->urb, GFP_KERNEL);
+ if (errcode) {
+ printk(KERN_DEBUG "%s: %s: submit URB: status:%i\n",
+ hw->name, __func__, errcode);
+ fifo->active = 0;
+ }
+}
+
+static void
+setPortMode(struct hfcsusb *hw)
+{
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s %s\n", hw->name, __func__,
+ (hw->protocol == ISDN_P_TE_S0) ? "TE" : "NT");
+
+ if (hw->protocol == ISDN_P_TE_S0) {
+ write_reg(hw, HFCUSB_SCTRL, 0x40);
+ write_reg(hw, HFCUSB_SCTRL_E, 0x00);
+ write_reg(hw, HFCUSB_CLKDEL, CLKDEL_TE);
+ write_reg(hw, HFCUSB_STATES, 3 | 0x10);
+ write_reg(hw, HFCUSB_STATES, 3);
+ } else {
+ write_reg(hw, HFCUSB_SCTRL, 0x44);
+ write_reg(hw, HFCUSB_SCTRL_E, 0x09);
+ write_reg(hw, HFCUSB_CLKDEL, CLKDEL_NT);
+ write_reg(hw, HFCUSB_STATES, 1 | 0x10);
+ write_reg(hw, HFCUSB_STATES, 1);
+ }
+}
+
+static void
+reset_hfcsusb(struct hfcsusb *hw)
+{
+ struct usb_fifo *fifo;
+ int i;
+
+ if (debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+
+ /* do Chip reset */
+ write_reg(hw, HFCUSB_CIRM, 8);
+
+ /* aux = output, reset off */
+ write_reg(hw, HFCUSB_CIRM, 0x10);
+
+ /* set USB_SIZE to match the wMaxPacketSize for INT or BULK transfers */
+ write_reg(hw, HFCUSB_USB_SIZE, (hw->packet_size / 8) |
+ ((hw->packet_size / 8) << 4));
+
+ /* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */
+ write_reg(hw, HFCUSB_USB_SIZE_I, hw->iso_packet_size);
+
+ /* enable PCM/GCI master mode */
+ write_reg(hw, HFCUSB_MST_MODE1, 0); /* set default values */
+ write_reg(hw, HFCUSB_MST_MODE0, 1); /* enable master mode */
+
+ /* init the fifos */
+ write_reg(hw, HFCUSB_F_THRES,
+ (HFCUSB_TX_THRESHOLD / 8) | ((HFCUSB_RX_THRESHOLD / 8) << 4));
+
+ fifo = hw->fifos;
+ for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
+ write_reg(hw, HFCUSB_FIFO, i); /* select the desired fifo */
+ fifo[i].max_size =
+ (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
+ fifo[i].last_urblen = 0;
+
+ /* set 2 bit for D- & E-channel */
+ write_reg(hw, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2));
+
+ /* enable all fifos */
+ if (i == HFCUSB_D_TX)
+ write_reg(hw, HFCUSB_CON_HDLC,
+ (hw->protocol == ISDN_P_NT_S0) ? 0x08 : 0x09);
+ else
+ write_reg(hw, HFCUSB_CON_HDLC, 0x08);
+ write_reg(hw, HFCUSB_INC_RES_F, 2); /* reset the fifo */
+ }
+
+ write_reg(hw, HFCUSB_SCTRL_R, 0); /* disable both B receivers */
+ handle_led(hw, LED_POWER_ON);
+}
+
+/* start USB data pipes dependand on device's endpoint configuration */
+static void
+hfcsusb_start_endpoint(struct hfcsusb *hw, int channel)
+{
+ /* quick check if endpoint already running */
+ if ((channel == HFC_CHAN_D) && (hw->fifos[HFCUSB_D_RX].active))
+ return;
+ if ((channel == HFC_CHAN_B1) && (hw->fifos[HFCUSB_B1_RX].active))
+ return;
+ if ((channel == HFC_CHAN_B2) && (hw->fifos[HFCUSB_B2_RX].active))
+ return;
+ if ((channel == HFC_CHAN_E) && (hw->fifos[HFCUSB_PCM_RX].active))
+ return;
+
+ /* start rx endpoints using USB INT IN method */
+ if (hw->cfg_used == CNF_3INT3ISO || hw->cfg_used == CNF_4INT3ISO)
+ start_int_fifo(hw->fifos + channel*2 + 1);
+
+ /* start rx endpoints using USB ISO IN method */
+ if (hw->cfg_used == CNF_3ISO3ISO || hw->cfg_used == CNF_4ISO3ISO) {
+ switch (channel) {
+ case HFC_CHAN_D:
+ start_isoc_chain(hw->fifos + HFCUSB_D_RX,
+ ISOC_PACKETS_D,
+ (usb_complete_t)rx_iso_complete,
+ 16);
+ break;
+ case HFC_CHAN_E:
+ start_isoc_chain(hw->fifos + HFCUSB_PCM_RX,
+ ISOC_PACKETS_D,
+ (usb_complete_t)rx_iso_complete,
+ 16);
+ break;
+ case HFC_CHAN_B1:
+ start_isoc_chain(hw->fifos + HFCUSB_B1_RX,
+ ISOC_PACKETS_B,
+ (usb_complete_t)rx_iso_complete,
+ 16);
+ break;
+ case HFC_CHAN_B2:
+ start_isoc_chain(hw->fifos + HFCUSB_B2_RX,
+ ISOC_PACKETS_B,
+ (usb_complete_t)rx_iso_complete,
+ 16);
+ break;
+ }
+ }
+
+ /* start tx endpoints using USB ISO OUT method */
+ switch (channel) {
+ case HFC_CHAN_D:
+ start_isoc_chain(hw->fifos + HFCUSB_D_TX,
+ ISOC_PACKETS_B,
+ (usb_complete_t)tx_iso_complete, 1);
+ break;
+ case HFC_CHAN_B1:
+ start_isoc_chain(hw->fifos + HFCUSB_B1_TX,
+ ISOC_PACKETS_D,
+ (usb_complete_t)tx_iso_complete, 1);
+ break;
+ case HFC_CHAN_B2:
+ start_isoc_chain(hw->fifos + HFCUSB_B2_TX,
+ ISOC_PACKETS_B,
+ (usb_complete_t)tx_iso_complete, 1);
+ break;
+ }
+}
+
+/* stop USB data pipes dependand on device's endpoint configuration */
+static void
+hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel)
+{
+ /* quick check if endpoint currently running */
+ if ((channel == HFC_CHAN_D) && (!hw->fifos[HFCUSB_D_RX].active))
+ return;
+ if ((channel == HFC_CHAN_B1) && (!hw->fifos[HFCUSB_B1_RX].active))
+ return;
+ if ((channel == HFC_CHAN_B2) && (!hw->fifos[HFCUSB_B2_RX].active))
+ return;
+ if ((channel == HFC_CHAN_E) && (!hw->fifos[HFCUSB_PCM_RX].active))
+ return;
+
+ /* rx endpoints using USB INT IN method */
+ if (hw->cfg_used == CNF_3INT3ISO || hw->cfg_used == CNF_4INT3ISO)
+ stop_int_gracefull(hw->fifos + channel*2 + 1);
+
+ /* rx endpoints using USB ISO IN method */
+ if (hw->cfg_used == CNF_3ISO3ISO || hw->cfg_used == CNF_4ISO3ISO)
+ stop_iso_gracefull(hw->fifos + channel*2 + 1);
+
+ /* tx endpoints using USB ISO OUT method */
+ if (channel != HFC_CHAN_E)
+ stop_iso_gracefull(hw->fifos + channel*2);
+}
+
+
+/* Hardware Initialization */
+int
+setup_hfcsusb(struct hfcsusb *hw)
+{
+ int err;
+ u_char b;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+
+ /* check the chip id */
+ if (read_reg_atomic(hw, HFCUSB_CHIP_ID, &b) != 1) {
+ printk(KERN_DEBUG "%s: %s: cannot read chip id\n",
+ hw->name, __func__);
+ return 1;
+ }
+ if (b != HFCUSB_CHIPID) {
+ printk(KERN_DEBUG "%s: %s: Invalid chip id 0x%02x\n",
+ hw->name, __func__, b);
+ return 1;
+ }
+
+ /* first set the needed config, interface and alternate */
+ err = usb_set_interface(hw->dev, hw->if_used, hw->alt_used);
+
+ hw->led_state = 0;
+
+ /* init the background machinery for control requests */
+ hw->ctrl_read.bRequestType = 0xc0;
+ hw->ctrl_read.bRequest = 1;
+ hw->ctrl_read.wLength = cpu_to_le16(1);
+ hw->ctrl_write.bRequestType = 0x40;
+ hw->ctrl_write.bRequest = 0;
+ hw->ctrl_write.wLength = 0;
+ usb_fill_control_urb(hw->ctrl_urb, hw->dev, hw->ctrl_out_pipe,
+ (u_char *)&hw->ctrl_write, NULL, 0,
+ (usb_complete_t)ctrl_complete, hw);
+
+ reset_hfcsusb(hw);
+ return 0;
+}
+
+static void
+release_hw(struct hfcsusb *hw)
+{
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+
+ /*
+ * stop all endpoints gracefully
+ * TODO: mISDN_core should generate CLOSE_CHANNEL
+ * signals after calling mISDN_unregister_device()
+ */
+ hfcsusb_stop_endpoint(hw, HFC_CHAN_D);
+ hfcsusb_stop_endpoint(hw, HFC_CHAN_B1);
+ hfcsusb_stop_endpoint(hw, HFC_CHAN_B2);
+ if (hw->fifos[HFCUSB_PCM_RX].pipe)
+ hfcsusb_stop_endpoint(hw, HFC_CHAN_E);
+ if (hw->protocol == ISDN_P_TE_S0)
+ l1_event(hw->dch.l1, CLOSE_CHANNEL);
+
+ mISDN_unregister_device(&hw->dch.dev);
+ mISDN_freebchannel(&hw->bch[1]);
+ mISDN_freebchannel(&hw->bch[0]);
+ mISDN_freedchannel(&hw->dch);
+
+ if (hw->ctrl_urb) {
+ usb_kill_urb(hw->ctrl_urb);
+ usb_free_urb(hw->ctrl_urb);
+ hw->ctrl_urb = NULL;
+ }
+
+ if (hw->intf)
+ usb_set_intfdata(hw->intf, NULL);
+ list_del(&hw->list);
+ kfree(hw);
+ hw = NULL;
+}
+
+static void
+deactivate_bchannel(struct bchannel *bch)
+{
+ struct hfcsusb *hw = bch->hw;
+ u_long flags;
+
+ if (bch->debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: %s: bch->nr(%i)\n",
+ hw->name, __func__, bch->nr);
+
+ spin_lock_irqsave(&hw->lock, flags);
+ if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
+ dev_kfree_skb(bch->next_skb);
+ bch->next_skb = NULL;
+ }
+ if (bch->tx_skb) {
+ dev_kfree_skb(bch->tx_skb);
+ bch->tx_skb = NULL;
+ }
+ bch->tx_idx = 0;
+ if (bch->rx_skb) {
+ dev_kfree_skb(bch->rx_skb);
+ bch->rx_skb = NULL;
+ }
+ clear_bit(FLG_ACTIVE, &bch->Flags);
+ clear_bit(FLG_TX_BUSY, &bch->Flags);
+ spin_unlock_irqrestore(&hw->lock, flags);
+ hfcsusb_setup_bch(bch, ISDN_P_NONE);
+ hfcsusb_stop_endpoint(hw, bch->nr);
+}
+
+/*
+ * Layer 1 B-channel hardware access
+ */
+static int
+hfc_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg)
+{
+ struct bchannel *bch = container_of(ch, struct bchannel, ch);
+ int ret = -EINVAL;
+
+ if (bch->debug & DEBUG_HW)
+ printk(KERN_DEBUG "%s: cmd:%x %p\n", __func__, cmd, arg);
+
+ switch (cmd) {
+ case HW_TESTRX_RAW:
+ case HW_TESTRX_HDLC:
+ case HW_TESTRX_OFF:
+ ret = -EINVAL;
+ break;
+
+ case CLOSE_CHANNEL:
+ test_and_clear_bit(FLG_OPEN, &bch->Flags);
+ if (test_bit(FLG_ACTIVE, &bch->Flags))
+ deactivate_bchannel(bch);
+ ch->protocol = ISDN_P_NONE;
+ ch->peer = NULL;
+ module_put(THIS_MODULE);
+ ret = 0;
+ break;
+ case CONTROL_CHANNEL:
+ ret = channel_bctrl(bch, arg);
+ break;
+ default:
+ printk(KERN_WARNING "%s: unknown prim(%x)\n",
+ __func__, cmd);
+ }
+ return ret;
+}
+
+static int
+setup_instance(struct hfcsusb *hw, struct device *parent)
+{
+ u_long flags;
+ int err, i;
+
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_DEBUG "%s: %s\n", hw->name, __func__);
+
+ spin_lock_init(&hw->ctrl_lock);
+ spin_lock_init(&hw->lock);
+
+ mISDN_initdchannel(&hw->dch, MAX_DFRAME_LEN_L1, ph_state);
+ hw->dch.debug = debug & 0xFFFF;
+ hw->dch.hw = hw;
+ hw->dch.dev.Dprotocols = (1 << ISDN_P_TE_S0) | (1 << ISDN_P_NT_S0);
+ hw->dch.dev.D.send = hfcusb_l2l1D;
+ hw->dch.dev.D.ctrl = hfc_dctrl;
+
+ /* enable E-Channel logging */
+ if (hw->fifos[HFCUSB_PCM_RX].pipe)
+ mISDN_initdchannel(&hw->ech, MAX_DFRAME_LEN_L1, NULL);
+
+ hw->dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) |
+ (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK));
+ hw->dch.dev.nrbchan = 2;
+ for (i = 0; i < 2; i++) {
+ hw->bch[i].nr = i + 1;
+ set_channelmap(i + 1, hw->dch.dev.channelmap);
+ hw->bch[i].debug = debug;
+ mISDN_initbchannel(&hw->bch[i], MAX_DATA_MEM);
+ hw->bch[i].hw = hw;
+ hw->bch[i].ch.send = hfcusb_l2l1B;
+ hw->bch[i].ch.ctrl = hfc_bctrl;
+ hw->bch[i].ch.nr = i + 1;
+ list_add(&hw->bch[i].ch.list, &hw->dch.dev.bchannels);
+ }
+
+ hw->fifos[HFCUSB_B1_TX].bch = &hw->bch[0];
+ hw->fifos[HFCUSB_B1_RX].bch = &hw->bch[0];
+ hw->fifos[HFCUSB_B2_TX].bch = &hw->bch[1];
+ hw->fifos[HFCUSB_B2_RX].bch = &hw->bch[1];
+ hw->fifos[HFCUSB_D_TX].dch = &hw->dch;
+ hw->fifos[HFCUSB_D_RX].dch = &hw->dch;
+ hw->fifos[HFCUSB_PCM_RX].ech = &hw->ech;
+ hw->fifos[HFCUSB_PCM_TX].ech = &hw->ech;
+
+ err = setup_hfcsusb(hw);
+ if (err)
+ goto out;
+
+ snprintf(hw->name, MISDN_MAX_IDLEN - 1, "%s.%d", DRIVER_NAME,
+ hfcsusb_cnt + 1);
+ printk(KERN_INFO "%s: registered as '%s'\n",
+ DRIVER_NAME, hw->name);
+
+ err = mISDN_register_device(&hw->dch.dev, parent, hw->name);
+ if (err)
+ goto out;
+
+ hfcsusb_cnt++;
+ write_lock_irqsave(&HFClock, flags);
+ list_add_tail(&hw->list, &HFClist);
+ write_unlock_irqrestore(&HFClock, flags);
+ return 0;
+
+out:
+ mISDN_freebchannel(&hw->bch[1]);
+ mISDN_freebchannel(&hw->bch[0]);
+ mISDN_freedchannel(&hw->dch);
+ kfree(hw);
+ return err;
+}
+
+static int
+hfcsusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct hfcsusb *hw;
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_host_interface *iface = intf->cur_altsetting;
+ struct usb_host_interface *iface_used = NULL;
+ struct usb_host_endpoint *ep;
+ struct hfcsusb_vdata *driver_info;
+ int ifnum = iface->desc.bInterfaceNumber, i, idx, alt_idx,
+ probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found,
+ ep_addr, cmptbl[16], small_match, iso_packet_size, packet_size,
+ alt_used = 0;
+
+ vend_idx = 0xffff;
+ for (i = 0; hfcsusb_idtab[i].idVendor; i++) {
+ if ((le16_to_cpu(dev->descriptor.idVendor)
+ == hfcsusb_idtab[i].idVendor) &&
+ (le16_to_cpu(dev->descriptor.idProduct)
+ == hfcsusb_idtab[i].idProduct)) {
+ vend_idx = i;
+ continue;
+ }
+ }
+
+ printk(KERN_DEBUG
+ "%s: interface(%d) actalt(%d) minor(%d) vend_idx(%d)\n",
+ __func__, ifnum, iface->desc.bAlternateSetting,
+ intf->minor, vend_idx);
+
+ if (vend_idx == 0xffff) {
+ printk(KERN_WARNING
+ "%s: no valid vendor found in USB descriptor\n",
+ __func__);
+ return -EIO;
+ }
+ /* if vendor and product ID is OK, start probing alternate settings */
+ alt_idx = 0;
+ small_match = -1;
+
+ /* default settings */
+ iso_packet_size = 16;
+ packet_size = 64;
+
+ while (alt_idx < intf->num_altsetting) {
+ iface = intf->altsetting + alt_idx;
+ probe_alt_setting = iface->desc.bAlternateSetting;
+ cfg_used = 0;
+
+ while (validconf[cfg_used][0]) {
+ cfg_found = 1;
+ vcf = validconf[cfg_used];
+ ep = iface->endpoint;
+ memcpy(cmptbl, vcf, 16 * sizeof(int));
+
+ /* check for all endpoints in this alternate setting */
+ for (i = 0; i < iface->desc.bNumEndpoints; i++) {
+ ep_addr = ep->desc.bEndpointAddress;
+
+ /* get endpoint base */
+ idx = ((ep_addr & 0x7f) - 1) * 2;
+ if (ep_addr & 0x80)
+ idx++;
+ attr = ep->desc.bmAttributes;
+
+ if (cmptbl[idx] != EP_NOP) {
+ if (cmptbl[idx] == EP_NUL)
+ cfg_found = 0;
+ if (attr == USB_ENDPOINT_XFER_INT
+ && cmptbl[idx] == EP_INT)
+ cmptbl[idx] = EP_NUL;
+ if (attr == USB_ENDPOINT_XFER_BULK
+ && cmptbl[idx] == EP_BLK)
+ cmptbl[idx] = EP_NUL;
+ if (attr == USB_ENDPOINT_XFER_ISOC
+ && cmptbl[idx] == EP_ISO)
+ cmptbl[idx] = EP_NUL;
+
+ if (attr == USB_ENDPOINT_XFER_INT &&
+ ep->desc.bInterval < vcf[17]) {
+ cfg_found = 0;
+ }
+ }
+ ep++;
+ }
+
+ for (i = 0; i < 16; i++)
+ if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL)
+ cfg_found = 0;
+
+ if (cfg_found) {
+ if (small_match < cfg_used) {
+ small_match = cfg_used;
+ alt_used = probe_alt_setting;
+ iface_used = iface;
+ }
+ }
+ cfg_used++;
+ }
+ alt_idx++;
+ } /* (alt_idx < intf->num_altsetting) */
+
+ /* not found a valid USB Ta Endpoint config */
+ if (small_match == -1)
+ return -EIO;
+
+ iface = iface_used;
+ hw = kzalloc(sizeof(struct hfcsusb), GFP_KERNEL);
+ if (!hw)
+ return -ENOMEM; /* got no mem */
+ snprintf(hw->name, MISDN_MAX_IDLEN - 1, "%s", DRIVER_NAME);
+
+ ep = iface->endpoint;
+ vcf = validconf[small_match];
+
+ for (i = 0; i < iface->desc.bNumEndpoints; i++) {
+ struct usb_fifo *f;
+
+ ep_addr = ep->desc.bEndpointAddress;
+ /* get endpoint base */
+ idx = ((ep_addr & 0x7f) - 1) * 2;
+ if (ep_addr & 0x80)
+ idx++;
+ f = &hw->fifos[idx & 7];
+
+ /* init Endpoints */
+ if (vcf[idx] == EP_NOP || vcf[idx] == EP_NUL) {
+ ep++;
+ continue;
+ }
+ switch (ep->desc.bmAttributes) {
+ case USB_ENDPOINT_XFER_INT:
+ f->pipe = usb_rcvintpipe(dev,
+ ep->desc.bEndpointAddress);
+ f->usb_transfer_mode = USB_INT;
+ packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (ep_addr & 0x80)
+ f->pipe = usb_rcvbulkpipe(dev,
+ ep->desc.bEndpointAddress);
+ else
+ f->pipe = usb_sndbulkpipe(dev,
+ ep->desc.bEndpointAddress);
+ f->usb_transfer_mode = USB_BULK;
+ packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (ep_addr & 0x80)
+ f->pipe = usb_rcvisocpipe(dev,
+ ep->desc.bEndpointAddress);
+ else
+ f->pipe = usb_sndisocpipe(dev,
+ ep->desc.bEndpointAddress);
+ f->usb_transfer_mode = USB_ISOC;
+ iso_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
+ break;
+ default:
+ f->pipe = 0;
+ }
+
+ if (f->pipe) {
+ f->fifonum = idx & 7;
+ f->hw = hw;
+ f->usb_packet_maxlen =
+ le16_to_cpu(ep->desc.wMaxPacketSize);
+ f->intervall = ep->desc.bInterval;
+ }
+ ep++;
+ }
+ hw->dev = dev; /* save device */
+ hw->if_used = ifnum; /* save used interface */
+ hw->alt_used = alt_used; /* and alternate config */
+ hw->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */
+ hw->cfg_used = vcf[16]; /* store used config */
+ hw->vend_idx = vend_idx; /* store found vendor */
+ hw->packet_size = packet_size;
+ hw->iso_packet_size = iso_packet_size;
+
+ /* create the control pipes needed for register access */
+ hw->ctrl_in_pipe = usb_rcvctrlpipe(hw->dev, 0);
+ hw->ctrl_out_pipe = usb_sndctrlpipe(hw->dev, 0);
+ hw->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ driver_info =
+ (struct hfcsusb_vdata *)hfcsusb_idtab[vend_idx].driver_info;
+ printk(KERN_DEBUG "%s: %s: detected \"%s\" (%s, if=%d alt=%d)\n",
+ hw->name, __func__, driver_info->vend_name,
+ conf_str[small_match], ifnum, alt_used);
+
+ if (setup_instance(hw, dev->dev.parent))
+ return -EIO;
+
+ hw->intf = intf;
+ usb_set_intfdata(hw->intf, hw);
+ return 0;
+}
+
+/* function called when an active device is removed */
+static void
+hfcsusb_disconnect(struct usb_interface *intf)
+{
+ struct hfcsusb *hw = usb_get_intfdata(intf);
+ struct hfcsusb *next;
+ int cnt = 0;
+
+ printk(KERN_INFO "%s: device disconnected\n", hw->name);
+
+ handle_led(hw, LED_POWER_OFF);
+ release_hw(hw);
+
+ list_for_each_entry_safe(hw, next, &HFClist, list)
+ cnt++;
+ if (!cnt)
+ hfcsusb_cnt = 0;
+
+ usb_set_intfdata(intf, NULL);
+}
+
+static struct usb_driver hfcsusb_drv = {
+ .name = DRIVER_NAME,
+ .id_table = hfcsusb_idtab,
+ .probe = hfcsusb_probe,
+ .disconnect = hfcsusb_disconnect,
+};
+
+static int __init
+hfcsusb_init(void)
+{
+ printk(KERN_INFO DRIVER_NAME " driver Rev. %s debug(0x%x) poll(%i)\n",
+ hfcsusb_rev, debug, poll);
+
+ if (usb_register(&hfcsusb_drv)) {
+ printk(KERN_INFO DRIVER_NAME
+ ": Unable to register hfcsusb module at usb stack\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit
+hfcsusb_cleanup(void)
+{
+ if (debug & DBG_HFC_CALL_TRACE)
+ printk(KERN_INFO DRIVER_NAME ": %s\n", __func__);
+
+ /* unregister Hardware */
+ usb_deregister(&hfcsusb_drv); /* release our driver */
+}
+
+module_init(hfcsusb_init);
+module_exit(hfcsusb_cleanup);
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.h b/drivers/isdn/hardware/mISDN/hfcsusb.h
new file mode 100644
index 000000000000..098486b8e8d2
--- /dev/null
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.h
@@ -0,0 +1,418 @@
+/*
+ * hfcsusb.h, HFC-S USB mISDN driver
+ */
+
+#ifndef __HFCSUSB_H__
+#define __HFCSUSB_H__
+
+
+#define DRIVER_NAME "HFC-S_USB"
+
+#define DBG_HFC_CALL_TRACE 0x00010000
+#define DBG_HFC_FIFO_VERBOSE 0x00020000
+#define DBG_HFC_USB_VERBOSE 0x00100000
+#define DBG_HFC_URB_INFO 0x00200000
+#define DBG_HFC_URB_ERROR 0x00400000
+
+#define DEFAULT_TRANSP_BURST_SZ 128
+
+#define HFC_CTRL_TIMEOUT 20 /* 5ms timeout writing/reading regs */
+#define CLKDEL_TE 0x0f /* CLKDEL in TE mode */
+#define CLKDEL_NT 0x6c /* CLKDEL in NT mode */
+
+/* hfcsusb Layer1 commands */
+#define HFC_L1_ACTIVATE_TE 1
+#define HFC_L1_ACTIVATE_NT 2
+#define HFC_L1_DEACTIVATE_NT 3
+#define HFC_L1_FORCE_DEACTIVATE_TE 4
+
+/* cmd FLAGS in HFCUSB_STATES register */
+#define HFCUSB_LOAD_STATE 0x10
+#define HFCUSB_ACTIVATE 0x20
+#define HFCUSB_DO_ACTION 0x40
+#define HFCUSB_NT_G2_G3 0x80
+
+/* timers */
+#define NT_ACTIVATION_TIMER 0x01 /* enables NT mode activation Timer */
+#define NT_T1_COUNT 10
+
+#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */
+
+#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */
+#define HFCUSB_TX_THRESHOLD 96 /* threshold for fifo report bit tx */
+
+#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */
+#define HFCUSB_CIRM 0x00 /* cirm register index */
+#define HFCUSB_USB_SIZE 0x07 /* int length register */
+#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */
+#define HFCUSB_F_CROSS 0x0b /* bit order register */
+#define HFCUSB_CLKDEL 0x37 /* bit delay register */
+#define HFCUSB_CON_HDLC 0xfa /* channel connect register */
+#define HFCUSB_HDLC_PAR 0xfb
+#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */
+#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */
+#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */
+#define HFCUSB_F_THRES 0x0c /* threshold register */
+#define HFCUSB_FIFO 0x0f /* fifo select register */
+#define HFCUSB_F_USAGE 0x1a /* fifo usage register */
+#define HFCUSB_MST_MODE0 0x14
+#define HFCUSB_MST_MODE1 0x15
+#define HFCUSB_P_DATA 0x1f
+#define HFCUSB_INC_RES_F 0x0e
+#define HFCUSB_B1_SSL 0x20
+#define HFCUSB_B2_SSL 0x21
+#define HFCUSB_B1_RSL 0x24
+#define HFCUSB_B2_RSL 0x25
+#define HFCUSB_STATES 0x30
+
+
+#define HFCUSB_CHIPID 0x40 /* ID value of HFC-S USB */
+
+/* fifo registers */
+#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */
+#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */
+#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */
+#define HFCUSB_B2_TX 2
+#define HFCUSB_B2_RX 3
+#define HFCUSB_D_TX 4
+#define HFCUSB_D_RX 5
+#define HFCUSB_PCM_TX 6
+#define HFCUSB_PCM_RX 7
+
+
+#define USB_INT 0
+#define USB_BULK 1
+#define USB_ISOC 2
+
+#define ISOC_PACKETS_D 8
+#define ISOC_PACKETS_B 8
+#define ISO_BUFFER_SIZE 128
+
+/* defines how much ISO packets are handled in one URB */
+static int iso_packets[8] =
+ { ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B,
+ ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D
+};
+
+
+/* Fifo flow Control for TX ISO */
+#define SINK_MAX 68
+#define SINK_MIN 48
+#define SINK_DMIN 12
+#define SINK_DMAX 18
+#define BITLINE_INF (-96*8)
+
+/* HFC-S USB register access by Control-URSs */
+#define write_reg_atomic(a, b, c) \
+ usb_control_msg((a)->dev, (a)->ctrl_out_pipe, 0, 0x40, (c), (b), \
+ 0, 0, HFC_CTRL_TIMEOUT)
+#define read_reg_atomic(a, b, c) \
+ usb_control_msg((a)->dev, (a)->ctrl_in_pipe, 1, 0xC0, 0, (b), (c), \
+ 1, HFC_CTRL_TIMEOUT)
+#define HFC_CTRL_BUFSIZE 64
+
+struct ctrl_buf {
+ __u8 hfcs_reg; /* register number */
+ __u8 reg_val; /* value to be written (or read) */
+};
+
+/*
+ * URB error codes
+ * Used to represent a list of values and their respective symbolic names
+ */
+struct hfcusb_symbolic_list {
+ const int num;
+ const char *name;
+};
+
+static struct hfcusb_symbolic_list urb_errlist[] = {
+ {-ENOMEM, "No memory for allocation of internal structures"},
+ {-ENOSPC, "The host controller's bandwidth is already consumed"},
+ {-ENOENT, "URB was canceled by unlink_urb"},
+ {-EXDEV, "ISO transfer only partially completed"},
+ {-EAGAIN, "Too match scheduled for the future"},
+ {-ENXIO, "URB already queued"},
+ {-EFBIG, "Too much ISO frames requested"},
+ {-ENOSR, "Buffer error (overrun)"},
+ {-EPIPE, "Specified endpoint is stalled (device not responding)"},
+ {-EOVERFLOW, "Babble (bad cable?)"},
+ {-EPROTO, "Bit-stuff error (bad cable?)"},
+ {-EILSEQ, "CRC/Timeout"},
+ {-ETIMEDOUT, "NAK (device does not respond)"},
+ {-ESHUTDOWN, "Device unplugged"},
+ {-1, NULL}
+};
+
+static inline const char *
+symbolic(struct hfcusb_symbolic_list list[], const int num)
+{
+ int i;
+ for (i = 0; list[i].name != NULL; i++)
+ if (list[i].num == num)
+ return list[i].name;
+ return "<unkown USB Error>";
+}
+
+/* USB descriptor need to contain one of the following EndPoint combination: */
+#define CNF_4INT3ISO 1 /* 4 INT IN, 3 ISO OUT */
+#define CNF_3INT3ISO 2 /* 3 INT IN, 3 ISO OUT */
+#define CNF_4ISO3ISO 3 /* 4 ISO IN, 3 ISO OUT */
+#define CNF_3ISO3ISO 4 /* 3 ISO IN, 3 ISO OUT */
+
+#define EP_NUL 1 /* Endpoint at this position not allowed */
+#define EP_NOP 2 /* all type of endpoints allowed at this position */
+#define EP_ISO 3 /* Isochron endpoint mandatory at this position */
+#define EP_BLK 4 /* Bulk endpoint mandatory at this position */
+#define EP_INT 5 /* Interrupt endpoint mandatory at this position */
+
+#define HFC_CHAN_B1 0
+#define HFC_CHAN_B2 1
+#define HFC_CHAN_D 2
+#define HFC_CHAN_E 3
+
+
+/*
+ * List of all supported enpoints configiration sets, used to find the
+ * best matching endpoint configuration within a devices' USB descriptor.
+ * We need at least 3 RX endpoints, and 3 TX endpoints, either
+ * INT-in and ISO-out, or ISO-in and ISO-out)
+ * with 4 RX endpoints even E-Channel logging is possible
+ */
+static int
+validconf[][19] = {
+ /* INT in, ISO out config */
+ {EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NOP, EP_INT,
+ EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
+ CNF_4INT3ISO, 2, 1},
+ {EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_NUL,
+ EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
+ CNF_3INT3ISO, 2, 0},
+ /* ISO in, ISO out config */
+ {EP_NOP, EP_NOP, EP_NOP, EP_NOP, EP_NOP, EP_NOP, EP_NOP, EP_NOP,
+ EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NOP, EP_ISO,
+ CNF_4ISO3ISO, 2, 1},
+ {EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL,
+ EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NUL, EP_NUL,
+ CNF_3ISO3ISO, 2, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* EOL element */
+};
+
+/* string description of chosen config */
+char *conf_str[] = {
+ "4 Interrupt IN + 3 Isochron OUT",
+ "3 Interrupt IN + 3 Isochron OUT",
+ "4 Isochron IN + 3 Isochron OUT",
+ "3 Isochron IN + 3 Isochron OUT"
+};
+
+
+#define LED_OFF 0 /* no LED support */
+#define LED_SCHEME1 1 /* LED standard scheme */
+#define LED_SCHEME2 2 /* not used yet... */
+
+#define LED_POWER_ON 1
+#define LED_POWER_OFF 2
+#define LED_S0_ON 3
+#define LED_S0_OFF 4
+#define LED_B1_ON 5
+#define LED_B1_OFF 6
+#define LED_B1_DATA 7
+#define LED_B2_ON 8
+#define LED_B2_OFF 9
+#define LED_B2_DATA 10
+
+#define LED_NORMAL 0 /* LEDs are normal */
+#define LED_INVERTED 1 /* LEDs are inverted */
+
+/* time in ms to perform a Flashing LED when B-Channel has traffic */
+#define LED_TIME 250
+
+
+
+struct hfcsusb;
+struct usb_fifo;
+
+/* structure defining input+output fifos (interrupt/bulk mode) */
+struct iso_urb {
+ struct urb *urb;
+ __u8 buffer[ISO_BUFFER_SIZE]; /* buffer rx/tx USB URB data */
+ struct usb_fifo *owner_fifo; /* pointer to owner fifo */
+ __u8 indx; /* Fifos's ISO double buffer 0 or 1 ? */
+#ifdef ISO_FRAME_START_DEBUG
+ int start_frames[ISO_FRAME_START_RING_COUNT];
+ __u8 iso_frm_strt_pos; /* index in start_frame[] */
+#endif
+};
+
+struct usb_fifo {
+ int fifonum; /* fifo index attached to this structure */
+ int active; /* fifo is currently active */
+ struct hfcsusb *hw; /* pointer to main structure */
+ int pipe; /* address of endpoint */
+ __u8 usb_packet_maxlen; /* maximum length for usb transfer */
+ unsigned int max_size; /* maximum size of receive/send packet */
+ __u8 intervall; /* interrupt interval */
+ struct urb *urb; /* transfer structure for usb routines */
+ __u8 buffer[128]; /* buffer USB INT OUT URB data */
+ int bit_line; /* how much bits are in the fifo? */
+
+ __u8 usb_transfer_mode; /* switched between ISO and INT */
+ struct iso_urb iso[2]; /* two urbs to have one always
+ one pending */
+
+ struct dchannel *dch; /* link to hfcsusb_t->dch */
+ struct bchannel *bch; /* link to hfcsusb_t->bch */
+ struct dchannel *ech; /* link to hfcsusb_t->ech, TODO: E-CHANNEL */
+ int last_urblen; /* remember length of last packet */
+ __u8 stop_gracefull; /* stops URB retransmission */
+};
+
+struct hfcsusb {
+ struct list_head list;
+ struct dchannel dch;
+ struct bchannel bch[2];
+ struct dchannel ech; /* TODO : wait for struct echannel ;) */
+
+ struct usb_device *dev; /* our device */
+ struct usb_interface *intf; /* used interface */
+ int if_used; /* used interface number */
+ int alt_used; /* used alternate config */
+ int cfg_used; /* configuration index used */
+ int vend_idx; /* index in hfcsusb_idtab */
+ int packet_size;
+ int iso_packet_size;
+ struct usb_fifo fifos[HFCUSB_NUM_FIFOS];
+
+ /* control pipe background handling */
+ struct ctrl_buf ctrl_buff[HFC_CTRL_BUFSIZE];
+ int ctrl_in_idx, ctrl_out_idx, ctrl_cnt;
+ struct urb *ctrl_urb;
+ struct usb_ctrlrequest ctrl_write;
+ struct usb_ctrlrequest ctrl_read;
+ int ctrl_paksize;
+ int ctrl_in_pipe, ctrl_out_pipe;
+ spinlock_t ctrl_lock; /* lock for ctrl */
+ spinlock_t lock;
+
+ __u8 threshold_mask;
+ __u8 led_state;
+
+ __u8 protocol;
+ int nt_timer;
+ int open;
+ __u8 timers;
+ __u8 initdone;
+ char name[MISDN_MAX_IDLEN];
+};
+
+/* private vendor specific data */
+struct hfcsusb_vdata {
+ __u8 led_scheme; /* led display scheme */
+ signed short led_bits[8]; /* array of 8 possible LED bitmask */
+ char *vend_name; /* device name */
+};
+
+
+#define HFC_MAX_TE_LAYER1_STATE 8
+#define HFC_MAX_NT_LAYER1_STATE 4
+
+const char *HFC_TE_LAYER1_STATES[HFC_MAX_TE_LAYER1_STATE + 1] = {
+ "TE F0 - Reset",
+ "TE F1 - Reset",
+ "TE F2 - Sensing",
+ "TE F3 - Deactivated",
+ "TE F4 - Awaiting signal",
+ "TE F5 - Identifying input",
+ "TE F6 - Synchronized",
+ "TE F7 - Activated",
+ "TE F8 - Lost framing",
+};
+
+const char *HFC_NT_LAYER1_STATES[HFC_MAX_NT_LAYER1_STATE + 1] = {
+ "NT G0 - Reset",
+ "NT G1 - Deactive",
+ "NT G2 - Pending activation",
+ "NT G3 - Active",
+ "NT G4 - Pending deactivation",
+};
+
+/* supported devices */
+static struct usb_device_id hfcsusb_idtab[] = {
+ {
+ USB_DEVICE(0x0959, 0x2bd0),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_OFF, {4, 0, 2, 1},
+ "ISDN USB TA (Cologne Chip HFC-S USB based)"}),
+ },
+ {
+ USB_DEVICE(0x0675, 0x1688),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {1, 2, 0, 0},
+ "DrayTek miniVigor 128 USB ISDN TA"}),
+ },
+ {
+ USB_DEVICE(0x07b0, 0x0007),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Billion tiny USB ISDN TA 128"}),
+ },
+ {
+ USB_DEVICE(0x0742, 0x2008),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {4, 0, 2, 1},
+ "Stollmann USB TA"}),
+ },
+ {
+ USB_DEVICE(0x0742, 0x2009),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {4, 0, 2, 1},
+ "Aceex USB ISDN TA"}),
+ },
+ {
+ USB_DEVICE(0x0742, 0x200A),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {4, 0, 2, 1},
+ "OEM USB ISDN TA"}),
+ },
+ {
+ USB_DEVICE(0x08e3, 0x0301),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {2, 0, 1, 4},
+ "Olitec USB RNIS"}),
+ },
+ {
+ USB_DEVICE(0x07fa, 0x0846),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Bewan Modem RNIS USB"}),
+ },
+ {
+ USB_DEVICE(0x07fa, 0x0847),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Djinn Numeris USB"}),
+ },
+ {
+ USB_DEVICE(0x07b0, 0x0006),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Twister ISDN TA"}),
+ },
+ {
+ USB_DEVICE(0x071d, 0x1005),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {0x02, 0, 0x01, 0x04},
+ "Eicon DIVA USB 4.0"}),
+ },
+ {
+ USB_DEVICE(0x0586, 0x0102),
+ .driver_info = (unsigned long) &((struct hfcsusb_vdata)
+ {LED_SCHEME1, {0x88, -64, -32, -16},
+ "ZyXEL OMNI.NET USB II"}),
+ },
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, hfcsusb_idtab);
+
+#endif /* __HFCSUSB_H__ */
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
index 7ee5bd9f2bb4..579974cf4c9a 100644
--- a/drivers/isdn/hysdn/hysdn_net.c
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -38,16 +38,12 @@ char *hysdn_net_revision = "$Revision: 1.8.6.4 $";
/* inside the definition. */
/****************************************************************************/
struct net_local {
- struct net_device netdev; /* the network device */
- struct net_device_stats stats;
- /* additional vars may be added here */
- char dev_name[9]; /* our own device name */
-
/* Tx control lock. This protects the transmit buffer ring
* state along with the "tx full" state of the driver. This
* means all netif_queue flow control actions are protected
* by this lock as well.
*/
+ struct net_device *dev;
spinlock_t lock;
struct sk_buff *skbs[MAX_SKB_BUFFERS]; /* pointers to tx-skbs */
int in_idx, out_idx; /* indexes to buffer ring */
@@ -55,15 +51,6 @@ struct net_local {
}; /* net_local */
-/*****************************************************/
-/* Get the current statistics for this card. */
-/* This may be called with the card open or closed ! */
-/*****************************************************/
-static struct net_device_stats *
-net_get_stats(struct net_device *dev)
-{
- return (&((struct net_local *) dev)->stats);
-} /* net_device_stats */
/*********************************************************************/
/* Open/initialize the board. This is called (in the current kernel) */
@@ -182,8 +169,8 @@ hysdn_tx_netack(hysdn_card * card)
if (!lp->sk_count)
return; /* error condition */
- lp->stats.tx_packets++;
- lp->stats.tx_bytes += lp->skbs[lp->out_idx]->len;
+ lp->dev->stats.tx_packets++;
+ lp->dev->stats.tx_bytes += lp->skbs[lp->out_idx]->len;
dev_kfree_skb(lp->skbs[lp->out_idx++]); /* free skb */
if (lp->out_idx >= MAX_SKB_BUFFERS)
@@ -200,29 +187,30 @@ void
hysdn_rx_netpkt(hysdn_card * card, unsigned char *buf, unsigned short len)
{
struct net_local *lp = card->netif;
+ struct net_device *dev = lp->dev;
struct sk_buff *skb;
if (!lp)
return; /* non existing device */
- lp->stats.rx_bytes += len;
+ dev->stats.rx_bytes += len;
skb = dev_alloc_skb(len);
if (skb == NULL) {
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
- lp->netdev.name);
- lp->stats.rx_dropped++;
+ dev->name);
+ dev->stats.rx_dropped++;
return;
}
/* copy the data */
memcpy(skb_put(skb, len), buf, len);
/* determine the used protocol */
- skb->protocol = eth_type_trans(skb, &lp->netdev);
+ skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- lp->stats.rx_packets++; /* adjust packet count */
+ dev->stats.rx_packets++; /* adjust packet count */
+ netif_rx(skb);
} /* hysdn_rx_netpkt */
/*****************************************************/
@@ -242,24 +230,15 @@ hysdn_tx_netget(hysdn_card * card)
return (lp->skbs[lp->out_idx]); /* next packet to send */
} /* hysdn_tx_netget */
+static const struct net_device_ops hysdn_netdev_ops = {
+ .ndo_open = net_open,
+ .ndo_stop = net_close,
+ .ndo_start_xmit = net_send_packet,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
-/*******************************************/
-/* init function called by register device */
-/*******************************************/
-static int
-net_init(struct net_device *dev)
-{
- /* setup the function table */
- dev->open = net_open;
- dev->stop = net_close;
- dev->hard_start_xmit = net_send_packet;
- dev->get_stats = net_get_stats;
-
- /* Fill in the fields of the device structure with ethernet values. */
- ether_setup(dev);
-
- return (0); /* success */
-} /* net_init */
/*****************************************************************************/
/* hysdn_net_create creates a new net device for the given card. If a device */
@@ -271,28 +250,34 @@ hysdn_net_create(hysdn_card * card)
{
struct net_device *dev;
int i;
+ struct net_local *lp;
+
if(!card) {
printk(KERN_WARNING "No card-pt in hysdn_net_create!\n");
return (-ENOMEM);
}
hysdn_net_release(card); /* release an existing net device */
- if ((dev = kzalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
+
+ dev = alloc_etherdev(sizeof(struct net_local));
+ if (!dev) {
printk(KERN_WARNING "HYSDN: unable to allocate mem\n");
return (-ENOMEM);
}
+ lp = netdev_priv(dev);
+ lp->dev = dev;
+
+ dev->netdev_ops = &hysdn_netdev_ops;
spin_lock_init(&((struct net_local *) dev)->lock);
/* initialise necessary or informing fields */
dev->base_addr = card->iobase; /* IO address */
dev->irq = card->irq; /* irq */
- dev->init = net_init; /* the init function of the device */
- if(dev->name) {
- strcpy(dev->name, ((struct net_local *) dev)->dev_name);
- }
+
+ dev->netdev_ops = &hysdn_netdev_ops;
if ((i = register_netdev(dev))) {
printk(KERN_WARNING "HYSDN: unable to create network device\n");
- kfree(dev);
+ free_netdev(dev);
return (i);
}
dev->ml_priv = card; /* remember pointer to own data structure */
@@ -316,7 +301,7 @@ hysdn_net_release(hysdn_card * card)
return (0); /* non existing */
card->netif = NULL; /* clear out pointer */
- dev->stop(dev); /* close the device */
+ net_close(dev);
flush_tx_buffers((struct net_local *) dev); /* empty buffers */
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 023ea11d2f9e..cb8943da4f12 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -292,7 +292,9 @@ isdn_net_unbind_channel(isdn_net_local * lp)
lp->dialstate = 0;
dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
- isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
+ if (lp->isdn_device != -1 && lp->isdn_channel != -1)
+ isdn_free_channel(lp->isdn_device, lp->isdn_channel,
+ ISDN_USAGE_NET);
lp->flags &= ~ISDN_NET_CONNECTED;
lp->isdn_device = -1;
lp->isdn_channel = -1;
@@ -1485,6 +1487,24 @@ isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return (rc);
}
+
+static int isdn_net_ioctl(struct net_device *dev,
+ struct ifreq *ifr, int cmd)
+{
+ isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
+
+ switch (lp->p_encap) {
+#ifdef CONFIG_ISDN_PPP
+ case ISDN_NET_ENCAP_SYNCPPP:
+ return isdn_ppp_dev_ioctl(dev, ifr, cmd);
+#endif
+ case ISDN_NET_ENCAP_CISCOHDLCK:
+ return isdn_ciscohdlck_dev_ioctl(dev, ifr, cmd);
+ default:
+ return -EINVAL;
+ }
+}
+
/* called via cisco_timer.function */
static void
isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
@@ -1998,23 +2018,6 @@ isdn_net_init(struct net_device *ndev)
ushort max_hlhdr_len = 0;
int drvidx;
- ether_setup(ndev);
- ndev->header_ops = NULL;
-
- /* Setup the generic properties */
- ndev->mtu = 1500;
- ndev->flags = IFF_NOARP|IFF_POINTOPOINT;
- ndev->type = ARPHRD_ETHER;
- ndev->addr_len = ETH_ALEN;
- ndev->validate_addr = NULL;
-
- /* for clients with MPPP maybe higher values better */
- ndev->tx_queue_len = 30;
-
- /* The ISDN-specific entries in the device structure. */
- ndev->open = &isdn_net_open;
- ndev->hard_start_xmit = &isdn_net_start_xmit;
-
/*
* up till binding we ask the protocol layer to reserve as much
* as we might need for HL layer
@@ -2026,9 +2029,6 @@ isdn_net_init(struct net_device *ndev)
max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
- ndev->stop = &isdn_net_close;
- ndev->get_stats = &isdn_net_get_stats;
- ndev->do_ioctl = NULL;
return 0;
}
@@ -2508,6 +2508,18 @@ isdn_net_force_dial(char *name)
return (isdn_net_force_dial_lp(p->local));
}
+/* The ISDN-specific entries in the device structure. */
+static const struct net_device_ops isdn_netdev_ops = {
+ .ndo_init = isdn_net_init,
+ .ndo_open = isdn_net_open,
+ .ndo_stop = isdn_net_close,
+ .ndo_do_ioctl = isdn_net_ioctl,
+
+ .ndo_start_xmit = isdn_net_start_xmit,
+ .ndo_get_stats = isdn_net_get_stats,
+ .ndo_tx_timeout = isdn_net_tx_timeout,
+};
+
/*
* Helper for alloc_netdev()
*/
@@ -2515,7 +2527,16 @@ static void _isdn_setup(struct net_device *dev)
{
isdn_net_local *lp = netdev_priv(dev);
- dev->flags = IFF_NOARP | IFF_POINTOPOINT;
+ ether_setup(dev);
+
+ /* Setup the generic properties */
+ dev->flags = IFF_NOARP|IFF_POINTOPOINT;
+ dev->header_ops = NULL;
+ dev->netdev_ops = &isdn_netdev_ops;
+
+ /* for clients with MPPP maybe higher values better */
+ dev->tx_queue_len = 30;
+
lp->p_encap = ISDN_NET_ENCAP_RAWIP;
lp->magic = ISDN_NET_MAGIC;
lp->last = lp;
@@ -2570,7 +2591,7 @@ isdn_net_new(char *name, struct net_device *master)
return NULL;
}
netdev->local = netdev_priv(netdev->dev);
- netdev->dev->init = isdn_net_init;
+
if (master) {
/* Device shall be a slave */
struct net_device *p = MASTER_TO_SLAVE(master);
@@ -2588,7 +2609,6 @@ isdn_net_new(char *name, struct net_device *master)
/*
* Watchdog timer (currently) for master only.
*/
- netdev->dev->tx_timeout = isdn_net_tx_timeout;
netdev->dev->watchdog_timeo = ISDN_NET_TX_TIMEOUT;
if (register_netdev(netdev->dev) != 0) {
printk(KERN_WARNING "isdn_net: Could not register net-device\n");
@@ -2704,7 +2724,6 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
#else
p->dev->type = ARPHRD_PPP; /* change ARP type */
p->dev->addr_len = 0;
- p->dev->do_ioctl = isdn_ppp_dev_ioctl;
#endif
break;
case ISDN_NET_ENCAP_X25IFACE:
@@ -2718,7 +2737,6 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
#endif
break;
case ISDN_NET_ENCAP_CISCOHDLCK:
- p->dev->do_ioctl = isdn_ciscohdlck_dev_ioctl;
break;
default:
if( cfg->p_encap >= 0 &&
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index a3551dd0324d..aa30b5cb3513 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -431,6 +431,7 @@ set_arg(void __user *b, void *val,int len)
return 0;
}
+#ifdef CONFIG_IPPP_FILTER
static int get_filter(void __user *arg, struct sock_filter **p)
{
struct sock_fprog uprog;
@@ -465,6 +466,7 @@ static int get_filter(void __user *arg, struct sock_filter **p)
*p = code;
return uprog.len;
}
+#endif /* CONFIG_IPPP_FILTER */
/*
* ippp device ioctl
diff --git a/drivers/isdn/mISDN/Makefile b/drivers/isdn/mISDN/Makefile
index 1cb5e633cf75..0a6bd2a9e730 100644
--- a/drivers/isdn/mISDN/Makefile
+++ b/drivers/isdn/mISDN/Makefile
@@ -8,6 +8,6 @@ obj-$(CONFIG_MISDN_L1OIP) += l1oip.o
# multi objects
-mISDN_core-objs := core.o fsm.o socket.o hwchannel.o stack.o layer1.o layer2.o tei.o timerdev.o
+mISDN_core-objs := core.o fsm.o socket.o clock.o hwchannel.o stack.o layer1.o layer2.o tei.o timerdev.o
mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o
l1oip-objs := l1oip_core.o l1oip_codec.o
diff --git a/drivers/isdn/mISDN/clock.c b/drivers/isdn/mISDN/clock.c
new file mode 100644
index 000000000000..44d9c3d5d33d
--- /dev/null
+++ b/drivers/isdn/mISDN/clock.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2008 by Andreas Eversberg <andreas@eversberg.eu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Quick API description:
+ *
+ * A clock source registers using mISDN_register_clock:
+ * name = text string to name clock source
+ * priority = value to priorize clock sources (0 = default)
+ * ctl = callback function to enable/disable clock source
+ * priv = private pointer of clock source
+ * return = pointer to clock source structure;
+ *
+ * Note: Callback 'ctl' can be called before mISDN_register_clock returns!
+ * Also it can be called during mISDN_unregister_clock.
+ *
+ * A clock source calls mISDN_clock_update with given samples elapsed, if
+ * enabled. If function call is delayed, tv must be set with the timestamp
+ * of the actual event.
+ *
+ * A clock source unregisters using mISDN_unregister_clock.
+ *
+ * To get current clock, call mISDN_clock_get. The signed short value
+ * counts the number of samples since. Time since last clock event is added.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/spinlock.h>
+#include <linux/mISDNif.h>
+#include "core.h"
+
+static u_int *debug;
+static LIST_HEAD(iclock_list);
+DEFINE_RWLOCK(iclock_lock);
+u16 iclock_count; /* counter of last clock */
+struct timeval iclock_tv; /* time stamp of last clock */
+int iclock_tv_valid; /* already received one timestamp */
+struct mISDNclock *iclock_current;
+
+void
+mISDN_init_clock(u_int *dp)
+{
+ debug = dp;
+ do_gettimeofday(&iclock_tv);
+}
+
+static void
+select_iclock(void)
+{
+ struct mISDNclock *iclock, *bestclock = NULL, *lastclock = NULL;
+ int pri = -128;
+
+ list_for_each_entry(iclock, &iclock_list, list) {
+ if (iclock->pri > pri) {
+ pri = iclock->pri;
+ bestclock = iclock;
+ }
+ if (iclock_current == iclock)
+ lastclock = iclock;
+ }
+ if (lastclock && bestclock != lastclock) {
+ /* last used clock source still exists but changes, disable */
+ if (*debug & DEBUG_CLOCK)
+ printk(KERN_DEBUG "Old clock source '%s' disable.\n",
+ lastclock->name);
+ lastclock->ctl(lastclock->priv, 0);
+ }
+ if (bestclock && bestclock != iclock_current) {
+ /* new clock source selected, enable */
+ if (*debug & DEBUG_CLOCK)
+ printk(KERN_DEBUG "New clock source '%s' enable.\n",
+ bestclock->name);
+ bestclock->ctl(bestclock->priv, 1);
+ }
+ if (bestclock != iclock_current) {
+ /* no clock received yet */
+ iclock_tv_valid = 0;
+ }
+ iclock_current = bestclock;
+}
+
+struct mISDNclock
+*mISDN_register_clock(char *name, int pri, clockctl_func_t *ctl, void *priv)
+{
+ u_long flags;
+ struct mISDNclock *iclock;
+
+ if (*debug & (DEBUG_CORE | DEBUG_CLOCK))
+ printk(KERN_DEBUG "%s: %s %d\n", __func__, name, pri);
+ iclock = kzalloc(sizeof(struct mISDNclock), GFP_ATOMIC);
+ if (!iclock) {
+ printk(KERN_ERR "%s: No memory for clock entry.\n", __func__);
+ return NULL;
+ }
+ strncpy(iclock->name, name, sizeof(iclock->name)-1);
+ iclock->pri = pri;
+ iclock->priv = priv;
+ iclock->ctl = ctl;
+ write_lock_irqsave(&iclock_lock, flags);
+ list_add_tail(&iclock->list, &iclock_list);
+ select_iclock();
+ write_unlock_irqrestore(&iclock_lock, flags);
+ return iclock;
+}
+EXPORT_SYMBOL(mISDN_register_clock);
+
+void
+mISDN_unregister_clock(struct mISDNclock *iclock)
+{
+ u_long flags;
+
+ if (*debug & (DEBUG_CORE | DEBUG_CLOCK))
+ printk(KERN_DEBUG "%s: %s %d\n", __func__, iclock->name,
+ iclock->pri);
+ write_lock_irqsave(&iclock_lock, flags);
+ if (iclock_current == iclock) {
+ if (*debug & DEBUG_CLOCK)
+ printk(KERN_DEBUG
+ "Current clock source '%s' unregisters.\n",
+ iclock->name);
+ iclock->ctl(iclock->priv, 0);
+ }
+ list_del(&iclock->list);
+ select_iclock();
+ write_unlock_irqrestore(&iclock_lock, flags);
+}
+EXPORT_SYMBOL(mISDN_unregister_clock);
+
+void
+mISDN_clock_update(struct mISDNclock *iclock, int samples, struct timeval *tv)
+{
+ u_long flags;
+ struct timeval tv_now;
+ time_t elapsed_sec;
+ int elapsed_8000th;
+
+ write_lock_irqsave(&iclock_lock, flags);
+ if (iclock_current != iclock) {
+ printk(KERN_ERR "%s: '%s' sends us clock updates, but we do "
+ "listen to '%s'. This is a bug!\n", __func__,
+ iclock->name,
+ iclock_current ? iclock_current->name : "nothing");
+ iclock->ctl(iclock->priv, 0);
+ write_unlock_irqrestore(&iclock_lock, flags);
+ return;
+ }
+ if (iclock_tv_valid) {
+ /* increment sample counter by given samples */
+ iclock_count += samples;
+ if (tv) { /* tv must be set, if function call is delayed */
+ iclock_tv.tv_sec = tv->tv_sec;
+ iclock_tv.tv_usec = tv->tv_usec;
+ } else
+ do_gettimeofday(&iclock_tv);
+ } else {
+ /* calc elapsed time by system clock */
+ if (tv) { /* tv must be set, if function call is delayed */
+ tv_now.tv_sec = tv->tv_sec;
+ tv_now.tv_usec = tv->tv_usec;
+ } else
+ do_gettimeofday(&tv_now);
+ elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec;
+ elapsed_8000th = (tv_now.tv_usec / 125)
+ - (iclock_tv.tv_usec / 125);
+ if (elapsed_8000th < 0) {
+ elapsed_sec -= 1;
+ elapsed_8000th += 8000;
+ }
+ /* add elapsed time to counter and set new timestamp */
+ iclock_count += elapsed_sec * 8000 + elapsed_8000th;
+ iclock_tv.tv_sec = tv_now.tv_sec;
+ iclock_tv.tv_usec = tv_now.tv_usec;
+ iclock_tv_valid = 1;
+ if (*debug & DEBUG_CLOCK)
+ printk("Received first clock from source '%s'.\n",
+ iclock_current ? iclock_current->name : "nothing");
+ }
+ write_unlock_irqrestore(&iclock_lock, flags);
+}
+EXPORT_SYMBOL(mISDN_clock_update);
+
+unsigned short
+mISDN_clock_get(void)
+{
+ u_long flags;
+ struct timeval tv_now;
+ time_t elapsed_sec;
+ int elapsed_8000th;
+ u16 count;
+
+ read_lock_irqsave(&iclock_lock, flags);
+ /* calc elapsed time by system clock */
+ do_gettimeofday(&tv_now);
+ elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec;
+ elapsed_8000th = (tv_now.tv_usec / 125) - (iclock_tv.tv_usec / 125);
+ if (elapsed_8000th < 0) {
+ elapsed_sec -= 1;
+ elapsed_8000th += 8000;
+ }
+ /* add elapsed time to counter */
+ count = iclock_count + elapsed_sec * 8000 + elapsed_8000th;
+ read_unlock_irqrestore(&iclock_lock, flags);
+ return count;
+}
+EXPORT_SYMBOL(mISDN_clock_get);
+
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index 751665c448d0..9426c9827e47 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -25,39 +25,183 @@ MODULE_AUTHOR("Karsten Keil");
MODULE_LICENSE("GPL");
module_param(debug, uint, S_IRUGO | S_IWUSR);
-static LIST_HEAD(devices);
-static DEFINE_RWLOCK(device_lock);
static u64 device_ids;
#define MAX_DEVICE_ID 63
static LIST_HEAD(Bprotocols);
static DEFINE_RWLOCK(bp_lock);
+static void mISDN_dev_release(struct device *dev)
+{
+ /* nothing to do: the device is part of its parent's data structure */
+}
+
+static ssize_t _show_id(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+
+ if (!mdev)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", mdev->id);
+}
+
+static ssize_t _show_nrbchan(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+
+ if (!mdev)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", mdev->nrbchan);
+}
+
+static ssize_t _show_d_protocols(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+
+ if (!mdev)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", mdev->Dprotocols);
+}
+
+static ssize_t _show_b_protocols(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+
+ if (!mdev)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols());
+}
+
+static ssize_t _show_protocol(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+
+ if (!mdev)
+ return -ENODEV;
+ return sprintf(buf, "%d\n", mdev->D.protocol);
+}
+
+static ssize_t _show_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ strcpy(buf, dev_name(dev));
+ return strlen(buf);
+}
+
+#if 0 /* hangs */
+static ssize_t _set_name(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int err = 0;
+ char *out = kmalloc(count + 1, GFP_KERNEL);
+
+ if (!out)
+ return -ENOMEM;
+
+ memcpy(out, buf, count);
+ if (count && out[count - 1] == '\n')
+ out[--count] = 0;
+ if (count)
+ err = device_rename(dev, out);
+ kfree(out);
+
+ return (err < 0) ? err : count;
+}
+#endif
+
+static ssize_t _show_channelmap(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+ char *bp = buf;
+ int i;
+
+ for (i = 0; i <= mdev->nrbchan; i++)
+ *bp++ = test_channelmap(i, mdev->channelmap) ? '1' : '0';
+
+ return bp - buf;
+}
+
+static struct device_attribute mISDN_dev_attrs[] = {
+ __ATTR(id, S_IRUGO, _show_id, NULL),
+ __ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL),
+ __ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL),
+ __ATTR(protocol, S_IRUGO, _show_protocol, NULL),
+ __ATTR(channelmap, S_IRUGO, _show_channelmap, NULL),
+ __ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL),
+ __ATTR(name, S_IRUGO, _show_name, NULL),
+/* __ATTR(name, S_IRUGO|S_IWUSR, _show_name, _set_name), */
+ {}
+};
+
+#ifdef CONFIG_HOTPLUG
+static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+
+ if (!mdev)
+ return 0;
+
+ if (add_uevent_var(env, "nchans=%d", mdev->nrbchan))
+ return -ENOMEM;
+
+ return 0;
+}
+#endif
+
+static void mISDN_class_release(struct class *cls)
+{
+ /* do nothing, it's static */
+}
+
+static struct class mISDN_class = {
+ .name = "mISDN",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_HOTPLUG
+ .dev_uevent = mISDN_uevent,
+#endif
+ .dev_attrs = mISDN_dev_attrs,
+ .dev_release = mISDN_dev_release,
+ .class_release = mISDN_class_release,
+};
+
+static int
+_get_mdevice(struct device *dev, void *id)
+{
+ struct mISDNdevice *mdev = dev_to_mISDN(dev);
+
+ if (!mdev)
+ return 0;
+ if (mdev->id != *(u_int *)id)
+ return 0;
+ return 1;
+}
+
struct mISDNdevice
*get_mdevice(u_int id)
{
- struct mISDNdevice *dev;
+ return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id,
+ _get_mdevice));
+}
- read_lock(&device_lock);
- list_for_each_entry(dev, &devices, D.list)
- if (dev->id == id) {
- read_unlock(&device_lock);
- return dev;
- }
- read_unlock(&device_lock);
- return NULL;
+static int
+_get_mdevice_count(struct device *dev, void *cnt)
+{
+ *(int *)cnt += 1;
+ return 0;
}
int
get_mdevice_count(void)
{
- struct mISDNdevice *dev;
- int cnt = 0;
+ int cnt = 0;
- read_lock(&device_lock);
- list_for_each_entry(dev, &devices, D.list)
- cnt++;
- read_unlock(&device_lock);
+ class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count);
return cnt;
}
@@ -68,48 +212,66 @@ get_free_devid(void)
for (i = 0; i <= MAX_DEVICE_ID; i++)
if (!test_and_set_bit(i, (u_long *)&device_ids))
- return i;
- return -1;
+ break;
+ if (i > MAX_DEVICE_ID)
+ return -1;
+ return i;
}
int
-mISDN_register_device(struct mISDNdevice *dev, char *name)
+mISDN_register_device(struct mISDNdevice *dev,
+ struct device *parent, char *name)
{
- u_long flags;
int err;
dev->id = get_free_devid();
+ err = -EBUSY;
if (dev->id < 0)
- return -EBUSY;
+ goto error1;
+
+ device_initialize(&dev->dev);
if (name && name[0])
- strcpy(dev->name, name);
+ dev_set_name(&dev->dev, "%s", name);
else
- sprintf(dev->name, "mISDN%d", dev->id);
+ dev_set_name(&dev->dev, "mISDN%d", dev->id);
if (debug & DEBUG_CORE)
printk(KERN_DEBUG "mISDN_register %s %d\n",
- dev->name, dev->id);
+ dev_name(&dev->dev), dev->id);
err = create_stack(dev);
if (err)
- return err;
- write_lock_irqsave(&device_lock, flags);
- list_add_tail(&dev->D.list, &devices);
- write_unlock_irqrestore(&device_lock, flags);
+ goto error1;
+
+ dev->dev.class = &mISDN_class;
+ dev->dev.platform_data = dev;
+ dev->dev.parent = parent;
+ dev_set_drvdata(&dev->dev, dev);
+
+ err = device_add(&dev->dev);
+ if (err)
+ goto error3;
return 0;
+
+error3:
+ delete_stack(dev);
+ return err;
+error1:
+ return err;
+
}
EXPORT_SYMBOL(mISDN_register_device);
void
mISDN_unregister_device(struct mISDNdevice *dev) {
- u_long flags;
-
if (debug & DEBUG_CORE)
printk(KERN_DEBUG "mISDN_unregister %s %d\n",
- dev->name, dev->id);
- write_lock_irqsave(&device_lock, flags);
- list_del(&dev->D.list);
- write_unlock_irqrestore(&device_lock, flags);
+ dev_name(&dev->dev), dev->id);
+ /* sysfs_remove_link(&dev->dev.kobj, "device"); */
+ device_del(&dev->dev);
+ dev_set_drvdata(&dev->dev, NULL);
+
test_and_clear_bit(dev->id, (u_long *)&device_ids);
delete_stack(dev);
+ put_device(&dev->dev);
}
EXPORT_SYMBOL(mISDN_unregister_device);
@@ -199,43 +361,45 @@ mISDNInit(void)
printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n",
MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE);
+ mISDN_init_clock(&debug);
mISDN_initstack(&debug);
+ err = class_register(&mISDN_class);
+ if (err)
+ goto error1;
err = mISDN_inittimer(&debug);
if (err)
- goto error;
+ goto error2;
err = l1_init(&debug);
- if (err) {
- mISDN_timer_cleanup();
- goto error;
- }
+ if (err)
+ goto error3;
err = Isdnl2_Init(&debug);
- if (err) {
- mISDN_timer_cleanup();
- l1_cleanup();
- goto error;
- }
+ if (err)
+ goto error4;
err = misdn_sock_init(&debug);
- if (err) {
- mISDN_timer_cleanup();
- l1_cleanup();
- Isdnl2_cleanup();
- }
-error:
+ if (err)
+ goto error5;
+ return 0;
+
+error5:
+ Isdnl2_cleanup();
+error4:
+ l1_cleanup();
+error3:
+ mISDN_timer_cleanup();
+error2:
+ class_unregister(&mISDN_class);
+error1:
return err;
}
static void mISDN_cleanup(void)
{
misdn_sock_cleanup();
- mISDN_timer_cleanup();
- l1_cleanup();
Isdnl2_cleanup();
+ l1_cleanup();
+ mISDN_timer_cleanup();
+ class_unregister(&mISDN_class);
- if (!list_empty(&devices))
- printk(KERN_ERR "%s devices still registered\n", __func__);
-
- if (!list_empty(&Bprotocols))
- printk(KERN_ERR "%s Bprotocols still registered\n", __func__);
printk(KERN_DEBUG "mISDNcore unloaded\n");
}
diff --git a/drivers/isdn/mISDN/core.h b/drivers/isdn/mISDN/core.h
index 7da7233b4c1a..7ac2f81a812b 100644
--- a/drivers/isdn/mISDN/core.h
+++ b/drivers/isdn/mISDN/core.h
@@ -74,4 +74,6 @@ extern void l1_cleanup(void);
extern int Isdnl2_Init(u_int *);
extern void Isdnl2_cleanup(void);
+extern void mISDN_init_clock(u_int *);
+
#endif
diff --git a/drivers/isdn/mISDN/dsp.h b/drivers/isdn/mISDN/dsp.h
index 6c3fed6b8d4f..98a33c58f091 100644
--- a/drivers/isdn/mISDN/dsp.h
+++ b/drivers/isdn/mISDN/dsp.h
@@ -15,6 +15,7 @@
#define DEBUG_DSP_TONE 0x0020
#define DEBUG_DSP_BLOWFISH 0x0040
#define DEBUG_DSP_DELAY 0x0100
+#define DEBUG_DSP_CLOCK 0x0200
#define DEBUG_DSP_DTMFCOEFF 0x8000 /* heavy output */
/* options may be:
@@ -198,6 +199,7 @@ struct dsp {
/* hardware stuff */
struct dsp_features features;
int features_rx_off; /* set if rx_off is featured */
+ int features_fill_empty; /* set if fill_empty is featured */
int pcm_slot_rx; /* current PCM slot (or -1) */
int pcm_bank_rx;
int pcm_slot_tx;
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c
index c884511e2d49..58c43e429f73 100644
--- a/drivers/isdn/mISDN/dsp_cmx.c
+++ b/drivers/isdn/mISDN/dsp_cmx.c
@@ -137,6 +137,7 @@
/* #define CMX_CONF_DEBUG */
/*#define CMX_DEBUG * massive read/write pointer output */
+/*#define CMX_DELAY_DEBUG * gives rx-buffer delay overview */
/*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */
static inline int
@@ -744,11 +745,11 @@ conf_software:
if (dsp->pcm_slot_rx >= 0 &&
dsp->pcm_slot_rx <
sizeof(freeslots))
- freeslots[dsp->pcm_slot_tx] = 0;
+ freeslots[dsp->pcm_slot_rx] = 0;
if (dsp->pcm_slot_tx >= 0 &&
dsp->pcm_slot_tx <
sizeof(freeslots))
- freeslots[dsp->pcm_slot_rx] = 0;
+ freeslots[dsp->pcm_slot_tx] = 0;
}
}
i = 0;
@@ -836,11 +837,11 @@ conf_software:
if (dsp->pcm_slot_rx >= 0 &&
dsp->pcm_slot_rx <
sizeof(freeslots))
- freeslots[dsp->pcm_slot_tx] = 0;
+ freeslots[dsp->pcm_slot_rx] = 0;
if (dsp->pcm_slot_tx >= 0 &&
dsp->pcm_slot_tx <
sizeof(freeslots))
- freeslots[dsp->pcm_slot_rx] = 0;
+ freeslots[dsp->pcm_slot_tx] = 0;
}
}
i1 = 0;
@@ -926,10 +927,6 @@ conf_software:
/* for more than two members.. */
- /* in case of hdlc, we change to software */
- if (dsp->hdlc)
- goto conf_software;
-
/* if all members already have the same conference */
if (all_conf)
return;
@@ -940,6 +937,9 @@ conf_software:
if (current_conf >= 0) {
join_members:
list_for_each_entry(member, &conf->mlist, list) {
+ /* in case of hdlc, change to software */
+ if (member->dsp->hdlc)
+ goto conf_software;
/* join to current conference */
if (member->dsp->hfc_conf == current_conf)
continue;
@@ -1135,6 +1135,25 @@ dsp_cmx_conf(struct dsp *dsp, u32 conf_id)
return 0;
}
+#ifdef CMX_DELAY_DEBUG
+int delaycount;
+static void
+showdelay(struct dsp *dsp, int samples, int delay)
+{
+ char bar[] = "--------------------------------------------------|";
+ int sdelay;
+
+ delaycount += samples;
+ if (delaycount < 8000)
+ return;
+ delaycount = 0;
+
+ sdelay = delay * 50 / (dsp_poll << 2);
+
+ printk(KERN_DEBUG "DELAY (%s) %3d >%s\n", dsp->name, delay,
+ sdelay > 50 ? "..." : bar + 50 - sdelay);
+}
+#endif
/*
* audio data is received from card
@@ -1168,11 +1187,18 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
dsp->rx_init = 0;
if (dsp->features.unordered) {
dsp->rx_R = (hh->id & CMX_BUFF_MASK);
- dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
- & CMX_BUFF_MASK;
+ if (dsp->cmx_delay)
+ dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
+ & CMX_BUFF_MASK;
+ else
+ dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
+ & CMX_BUFF_MASK;
} else {
dsp->rx_R = 0;
- dsp->rx_W = dsp->cmx_delay;
+ if (dsp->cmx_delay)
+ dsp->rx_W = dsp->cmx_delay;
+ else
+ dsp->rx_W = dsp_poll >> 1;
}
}
/* if frame contains time code, write directly */
@@ -1185,19 +1211,25 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
* we set our new read pointer, and write silence to buffer
*/
if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
- if (dsp_debug & DEBUG_DSP_CMX)
+ if (dsp_debug & DEBUG_DSP_CLOCK)
printk(KERN_DEBUG
"cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
"maximum delay), adjusting read pointer! "
"(inst %s)\n", (u_long)dsp, dsp->name);
- /* flush buffer */
+ /* flush rx buffer and set delay to dsp_poll / 2 */
if (dsp->features.unordered) {
dsp->rx_R = (hh->id & CMX_BUFF_MASK);
- dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
- & CMX_BUFF_MASK;
+ if (dsp->cmx_delay)
+ dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
+ & CMX_BUFF_MASK;
+ dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
+ & CMX_BUFF_MASK;
} else {
dsp->rx_R = 0;
- dsp->rx_W = dsp->cmx_delay;
+ if (dsp->cmx_delay)
+ dsp->rx_W = dsp->cmx_delay;
+ else
+ dsp->rx_W = dsp_poll >> 1;
}
memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
}
@@ -1205,7 +1237,7 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
if (dsp->cmx_delay)
if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >=
(dsp->cmx_delay << 1)) {
- if (dsp_debug & DEBUG_DSP_CMX)
+ if (dsp_debug & DEBUG_DSP_CLOCK)
printk(KERN_DEBUG
"cmx_receive(dsp=%lx): OVERRUN (because "
"twice the delay is reached), adjusting "
@@ -1243,6 +1275,9 @@ dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
/* increase write-pointer */
dsp->rx_W = ((dsp->rx_W+len) & CMX_BUFF_MASK);
+#ifdef CMX_DELAY_DEBUG
+ showdelay(dsp, len, (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK);
+#endif
}
@@ -1360,8 +1395,12 @@ dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
t = (t+1) & CMX_BUFF_MASK;
r = (r+1) & CMX_BUFF_MASK;
}
- if (r != rr)
+ if (r != rr) {
+ if (dsp_debug & DEBUG_DSP_CLOCK)
+ printk(KERN_DEBUG "%s: RX empty\n",
+ __func__);
memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK);
+ }
/* -> if echo is enabled */
} else {
/*
@@ -1540,13 +1579,11 @@ send_packet:
schedule_work(&dsp->workq);
}
-static u32 samplecount;
+static u32 jittercount; /* counter for jitter check */
struct timer_list dsp_spl_tl;
u32 dsp_spl_jiffies; /* calculate the next time to fire */
-#ifdef UNUSED
-static u32 dsp_start_jiffies; /* jiffies at the time, the calculation begins */
-#endif /* UNUSED */
-static struct timeval dsp_start_tv; /* time at start of calculation */
+static u16 dsp_count; /* last sample count */
+static int dsp_count_valid ; /* if we have last sample count */
void
dsp_cmx_send(void *arg)
@@ -1560,38 +1597,32 @@ dsp_cmx_send(void *arg)
int r, rr;
int jittercheck = 0, delay, i;
u_long flags;
- struct timeval tv;
- u32 elapsed;
- s16 length;
+ u16 length, count;
/* lock */
spin_lock_irqsave(&dsp_lock, flags);
- if (!dsp_start_tv.tv_sec) {
- do_gettimeofday(&dsp_start_tv);
+ if (!dsp_count_valid) {
+ dsp_count = mISDN_clock_get();
length = dsp_poll;
+ dsp_count_valid = 1;
} else {
- do_gettimeofday(&tv);
- elapsed = ((tv.tv_sec - dsp_start_tv.tv_sec) * 8000)
- + ((s32)(tv.tv_usec / 125) - (dsp_start_tv.tv_usec / 125));
- dsp_start_tv.tv_sec = tv.tv_sec;
- dsp_start_tv.tv_usec = tv.tv_usec;
- length = elapsed;
+ count = mISDN_clock_get();
+ length = count - dsp_count;
+ dsp_count = count;
}
if (length > MAX_POLL + 100)
length = MAX_POLL + 100;
-/* printk(KERN_DEBUG "len=%d dsp_count=0x%x.%04x dsp_poll_diff=0x%x.%04x\n",
- length, dsp_count >> 16, dsp_count & 0xffff, dsp_poll_diff >> 16,
- dsp_poll_diff & 0xffff);
- */
+ /* printk(KERN_DEBUG "len=%d dsp_count=0x%x\n", length, dsp_count); */
/*
- * check if jitter needs to be checked
- * (this is about every second = 8192 samples)
+ * check if jitter needs to be checked (this is every second)
*/
- samplecount += length;
- if ((samplecount & 8191) < length)
+ jittercount += length;
+ if (jittercount >= 8000) {
+ jittercount -= 8000;
jittercheck = 1;
+ }
/* loop all members that do not require conference mixing */
list_for_each_entry(dsp, &dsp_ilist, list) {
@@ -1704,17 +1735,19 @@ dsp_cmx_send(void *arg)
}
/*
* remove rx_delay only if we have delay AND we
- * have not preset cmx_delay
+ * have not preset cmx_delay AND
+ * the delay is greater dsp_poll
*/
- if (delay && !dsp->cmx_delay) {
- if (dsp_debug & DEBUG_DSP_CMX)
+ if (delay > dsp_poll && !dsp->cmx_delay) {
+ if (dsp_debug & DEBUG_DSP_CLOCK)
printk(KERN_DEBUG
"%s lowest rx_delay of %d bytes for"
" dsp %s are now removed.\n",
__func__, delay,
dsp->name);
r = dsp->rx_R;
- rr = (r + delay) & CMX_BUFF_MASK;
+ rr = (r + delay - (dsp_poll >> 1))
+ & CMX_BUFF_MASK;
/* delete rx-data */
while (r != rr) {
p[r] = dsp_silence;
@@ -1736,15 +1769,16 @@ dsp_cmx_send(void *arg)
* remove delay only if we have delay AND we
* have enabled tx_dejitter
*/
- if (delay && dsp->tx_dejitter) {
- if (dsp_debug & DEBUG_DSP_CMX)
+ if (delay > dsp_poll && dsp->tx_dejitter) {
+ if (dsp_debug & DEBUG_DSP_CLOCK)
printk(KERN_DEBUG
"%s lowest tx_delay of %d bytes for"
" dsp %s are now removed.\n",
__func__, delay,
dsp->name);
r = dsp->tx_R;
- rr = (r + delay) & CMX_BUFF_MASK;
+ rr = (r + delay - (dsp_poll >> 1))
+ & CMX_BUFF_MASK;
/* delete tx-data */
while (r != rr) {
q[r] = dsp_silence;
@@ -1797,14 +1831,16 @@ dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
ww = dsp->tx_R;
p = dsp->tx_buff;
d = skb->data;
- space = ww-w;
- if (space <= 0)
- space += CMX_BUFF_SIZE;
+ space = (ww - w - 1) & CMX_BUFF_MASK;
/* write-pointer should not overrun nor reach read pointer */
- if (space-1 < skb->len)
+ if (space < skb->len) {
/* write to the space we have left */
- ww = (ww - 1) & CMX_BUFF_MASK;
- else
+ ww = (ww - 1) & CMX_BUFF_MASK; /* end one byte prior tx_R */
+ if (dsp_debug & DEBUG_DSP_CLOCK)
+ printk(KERN_DEBUG "%s: TX overflow space=%d skb->len="
+ "%d, w=0x%04x, ww=0x%04x\n", __func__, space,
+ skb->len, w, ww);
+ } else
/* write until all byte are copied */
ww = (w + skb->len) & CMX_BUFF_MASK;
dsp->tx_W = ww;
@@ -1857,7 +1893,7 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
/* in case of hardware (echo) */
if (dsp->pcm_slot_tx >= 0)
return;
- if (dsp->echo)
+ if (dsp->echo) {
nskb = skb_clone(skb, GFP_ATOMIC);
if (nskb) {
hh = mISDN_HEAD_P(nskb);
@@ -1866,6 +1902,7 @@ dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
skb_queue_tail(&dsp->sendq, nskb);
schedule_work(&dsp->workq);
}
+ }
return;
}
/* in case of hardware conference */
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c
index 1dc21d803410..3083338716b2 100644
--- a/drivers/isdn/mISDN/dsp_core.c
+++ b/drivers/isdn/mISDN/dsp_core.c
@@ -191,6 +191,8 @@ dsp_rx_off_member(struct dsp *dsp)
struct mISDN_ctrl_req cq;
int rx_off = 1;
+ memset(&cq, 0, sizeof(cq));
+
if (!dsp->features_rx_off)
return;
@@ -249,6 +251,32 @@ dsp_rx_off(struct dsp *dsp)
}
}
+/* enable "fill empty" feature */
+static void
+dsp_fill_empty(struct dsp *dsp)
+{
+ struct mISDN_ctrl_req cq;
+
+ memset(&cq, 0, sizeof(cq));
+
+ if (!dsp->ch.peer) {
+ if (dsp_debug & DEBUG_DSP_CORE)
+ printk(KERN_DEBUG "%s: no peer, no fill_empty\n",
+ __func__);
+ return;
+ }
+ cq.op = MISDN_CTRL_FILL_EMPTY;
+ cq.p1 = 1;
+ if (dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq)) {
+ printk(KERN_DEBUG "%s: CONTROL_CHANNEL failed\n",
+ __func__);
+ return;
+ }
+ if (dsp_debug & DEBUG_DSP_CORE)
+ printk(KERN_DEBUG "%s: %s set fill_empty = 1\n",
+ __func__, dsp->name);
+}
+
static int
dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
{
@@ -273,8 +301,9 @@ dsp_control_req(struct dsp *dsp, struct mISDNhead *hh, struct sk_buff *skb)
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: start dtmf\n", __func__);
if (len == sizeof(int)) {
- printk(KERN_NOTICE "changing DTMF Threshold "
- "to %d\n", *((int *)data));
+ if (dsp_debug & DEBUG_DSP_CORE)
+ printk(KERN_NOTICE "changing DTMF Threshold "
+ "to %d\n", *((int *)data));
dsp->dtmf.treshold = (*(int *)data) * 10000;
}
/* init goertzel */
@@ -593,8 +622,6 @@ get_features(struct mISDNchannel *ch)
struct dsp *dsp = container_of(ch, struct dsp, ch);
struct mISDN_ctrl_req cq;
- if (dsp_options & DSP_OPT_NOHARDWARE)
- return;
if (!ch->peer) {
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: no peer, no features\n",
@@ -610,6 +637,10 @@ get_features(struct mISDNchannel *ch)
}
if (cq.op & MISDN_CTRL_RX_OFF)
dsp->features_rx_off = 1;
+ if (cq.op & MISDN_CTRL_FILL_EMPTY)
+ dsp->features_fill_empty = 1;
+ if (dsp_options & DSP_OPT_NOHARDWARE)
+ return;
if ((cq.op & MISDN_CTRL_HW_FEATURES_OP)) {
cq.op = MISDN_CTRL_HW_FEATURES;
*((u_long *)&cq.p1) = (u_long)&dsp->features;
@@ -837,11 +868,14 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
}
if (dsp->hdlc) {
/* hdlc */
- spin_lock_irqsave(&dsp_lock, flags);
- if (dsp->b_active) {
- skb_queue_tail(&dsp->sendq, skb);
- schedule_work(&dsp->workq);
+ if (!dsp->b_active) {
+ ret = -EIO;
+ break;
}
+ hh->prim = PH_DATA_REQ;
+ spin_lock_irqsave(&dsp_lock, flags);
+ skb_queue_tail(&dsp->sendq, skb);
+ schedule_work(&dsp->workq);
spin_unlock_irqrestore(&dsp_lock, flags);
return 0;
}
@@ -865,6 +899,9 @@ dsp_function(struct mISDNchannel *ch, struct sk_buff *skb)
if (dsp->dtmf.hardware || dsp->dtmf.software)
dsp_dtmf_goertzel_init(dsp);
get_features(ch);
+ /* enable fill_empty feature */
+ if (dsp->features_fill_empty)
+ dsp_fill_empty(dsp);
/* send ph_activate */
hh->prim = PH_ACTIVATE_REQ;
if (ch->peer)
@@ -1105,7 +1142,7 @@ static int dsp_init(void)
} else {
poll = 8;
while (poll <= MAX_POLL) {
- tics = poll * HZ / 8000;
+ tics = (poll * HZ) / 8000;
if (tics * 8000 == poll * HZ) {
dsp_tics = tics;
dsp_poll = poll;
diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c
index 5ee6651b45b9..18cf87c113e7 100644
--- a/drivers/isdn/mISDN/dsp_pipeline.c
+++ b/drivers/isdn/mISDN/dsp_pipeline.c
@@ -75,6 +75,15 @@ static struct device_attribute element_attributes[] = {
__ATTR(args, 0444, attr_show_args, NULL),
};
+static void
+mISDN_dsp_dev_release(struct device *dev)
+{
+ struct dsp_element_entry *entry =
+ container_of(dev, struct dsp_element_entry, dev);
+ list_del(&entry->list);
+ kfree(entry);
+}
+
int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
{
struct dsp_element_entry *entry;
@@ -83,24 +92,25 @@ int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
if (!elem)
return -EINVAL;
- entry = kzalloc(sizeof(struct dsp_element_entry), GFP_KERNEL);
+ entry = kzalloc(sizeof(struct dsp_element_entry), GFP_ATOMIC);
if (!entry)
return -ENOMEM;
entry->elem = elem;
entry->dev.class = elements_class;
+ entry->dev.release = mISDN_dsp_dev_release;
dev_set_drvdata(&entry->dev, elem);
- snprintf(entry->dev.bus_id, BUS_ID_SIZE, elem->name);
+ dev_set_name(&entry->dev, elem->name);
ret = device_register(&entry->dev);
if (ret) {
printk(KERN_ERR "%s: failed to register %s\n",
__func__, elem->name);
goto err1;
}
+ list_add_tail(&entry->list, &dsp_elements);
- for (i = 0; i < (sizeof(element_attributes)
- / sizeof(struct device_attribute)); ++i)
+ for (i = 0; i < ARRAY_SIZE(element_attributes); ++i) {
ret = device_create_file(&entry->dev,
&element_attributes[i]);
if (ret) {
@@ -108,15 +118,17 @@ int mISDN_dsp_element_register(struct mISDN_dsp_element *elem)
__func__);
goto err2;
}
+ }
- list_add_tail(&entry->list, &dsp_elements);
-
+#ifdef PIPELINE_DEBUG
printk(KERN_DEBUG "%s: %s registered\n", __func__, elem->name);
+#endif
return 0;
err2:
device_unregister(&entry->dev);
+ return ret;
err1:
kfree(entry);
return ret;
@@ -132,11 +144,11 @@ void mISDN_dsp_element_unregister(struct mISDN_dsp_element *elem)
list_for_each_entry_safe(entry, n, &dsp_elements, list)
if (entry->elem == elem) {
- list_del(&entry->list);
device_unregister(&entry->dev);
- kfree(entry);
+#ifdef PIPELINE_DEBUG
printk(KERN_DEBUG "%s: %s unregistered\n",
__func__, elem->name);
+#endif
return;
}
printk(KERN_ERR "%s: element %s not in list.\n", __func__, elem->name);
@@ -173,7 +185,9 @@ void dsp_pipeline_module_exit(void)
kfree(entry);
}
+#ifdef PIPELINE_DEBUG
printk(KERN_DEBUG "%s: dsp pipeline module exited\n", __func__);
+#endif
}
int dsp_pipeline_init(struct dsp_pipeline *pipeline)
@@ -239,7 +253,7 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
if (!len)
return 0;
- dup = kmalloc(len + 1, GFP_KERNEL);
+ dup = kmalloc(len + 1, GFP_ATOMIC);
if (!dup)
return 0;
strcpy(dup, cfg);
@@ -256,9 +270,9 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
elem = entry->elem;
pipeline_entry = kmalloc(sizeof(struct
- dsp_pipeline_entry), GFP_KERNEL);
+ dsp_pipeline_entry), GFP_ATOMIC);
if (!pipeline_entry) {
- printk(KERN_DEBUG "%s: failed to add "
+ printk(KERN_ERR "%s: failed to add "
"entry to pipeline: %s (out of "
"memory)\n", __func__, elem->name);
incomplete = 1;
@@ -286,7 +300,7 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
args : "");
#endif
} else {
- printk(KERN_DEBUG "%s: failed "
+ printk(KERN_ERR "%s: failed "
"to add entry to pipeline: "
"%s (new() returned NULL)\n",
__func__, elem->name);
@@ -301,7 +315,7 @@ int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
if (found)
found = 0;
else {
- printk(KERN_DEBUG "%s: element not found, skipping: "
+ printk(KERN_ERR "%s: element not found, skipping: "
"%s\n", __func__, name);
incomplete = 1;
}
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 2596fba4e614..ab1168a110ae 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -50,9 +50,6 @@ bchannel_bh(struct work_struct *ws)
if (test_and_clear_bit(FLG_RECVQUEUE, &bch->Flags)) {
while ((skb = skb_dequeue(&bch->rqueue))) {
- if (bch->rcount >= 64)
- printk(KERN_WARNING "B-channel %p receive "
- "queue if full, but empties...\n", bch);
bch->rcount--;
if (likely(bch->ch.peer)) {
err = bch->ch.recv(bch->ch.peer, skb);
@@ -169,6 +166,25 @@ recv_Dchannel(struct dchannel *dch)
EXPORT_SYMBOL(recv_Dchannel);
void
+recv_Echannel(struct dchannel *ech, struct dchannel *dch)
+{
+ struct mISDNhead *hh;
+
+ if (ech->rx_skb->len < 2) { /* at least 2 for sapi / tei */
+ dev_kfree_skb(ech->rx_skb);
+ ech->rx_skb = NULL;
+ return;
+ }
+ hh = mISDN_HEAD_P(ech->rx_skb);
+ hh->prim = PH_DATA_E_IND;
+ hh->id = get_sapi_tei(ech->rx_skb->data);
+ skb_queue_tail(&dch->rqueue, ech->rx_skb);
+ ech->rx_skb = NULL;
+ schedule_event(dch, FLG_RECVQUEUE);
+}
+EXPORT_SYMBOL(recv_Echannel);
+
+void
recv_Bchannel(struct bchannel *bch)
{
struct mISDNhead *hh;
@@ -177,8 +193,10 @@ recv_Bchannel(struct bchannel *bch)
hh->prim = PH_DATA_IND;
hh->id = MISDN_ID_ANY;
if (bch->rcount >= 64) {
- dev_kfree_skb(bch->rx_skb);
- bch->rx_skb = NULL;
+ printk(KERN_WARNING "B-channel %p receive queue overflow, "
+ "fushing!\n", bch);
+ skb_queue_purge(&bch->rqueue);
+ bch->rcount = 0;
return;
}
bch->rcount++;
@@ -200,8 +218,10 @@ void
recv_Bchannel_skb(struct bchannel *bch, struct sk_buff *skb)
{
if (bch->rcount >= 64) {
- dev_kfree_skb(skb);
- return;
+ printk(KERN_WARNING "B-channel %p receive queue overflow, "
+ "fushing!\n", bch);
+ skb_queue_purge(&bch->rqueue);
+ bch->rcount = 0;
}
bch->rcount++;
skb_queue_tail(&bch->rqueue, skb);
@@ -245,8 +265,12 @@ confirm_Bsend(struct bchannel *bch)
{
struct sk_buff *skb;
- if (bch->rcount >= 64)
- return;
+ if (bch->rcount >= 64) {
+ printk(KERN_WARNING "B-channel %p receive queue overflow, "
+ "fushing!\n", bch);
+ skb_queue_purge(&bch->rqueue);
+ bch->rcount = 0;
+ }
skb = _alloc_mISDN_skb(PH_DATA_CNF, mISDN_HEAD_ID(bch->tx_skb),
0, NULL, GFP_ATOMIC);
if (!skb) {
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c
index 0884dd6892f8..abe574989572 100644
--- a/drivers/isdn/mISDN/l1oip_core.c
+++ b/drivers/isdn/mISDN/l1oip_core.c
@@ -777,6 +777,8 @@ fail:
static void
l1oip_socket_close(struct l1oip *hc)
{
+ struct dchannel *dch = hc->chan[hc->d_idx].dch;
+
/* kill thread */
if (hc->socket_thread) {
if (debug & DEBUG_L1OIP_SOCKET)
@@ -785,6 +787,16 @@ l1oip_socket_close(struct l1oip *hc)
send_sig(SIGTERM, hc->socket_thread, 0);
wait_for_completion(&hc->socket_complete);
}
+
+ /* if active, we send up a PH_DEACTIVATE and deactivate */
+ if (test_bit(FLG_ACTIVE, &dch->Flags)) {
+ if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET))
+ printk(KERN_DEBUG "%s: interface become deactivated "
+ "due to timeout\n", __func__);
+ test_and_clear_bit(FLG_ACTIVE, &dch->Flags);
+ _queue_data(&dch->dev.D, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0,
+ NULL, GFP_ATOMIC);
+ }
}
static int
@@ -944,7 +956,8 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
switch (cq->op) {
case MISDN_CTRL_GETOP:
- cq->op = MISDN_CTRL_SETPEER | MISDN_CTRL_UNSETPEER;
+ cq->op = MISDN_CTRL_SETPEER | MISDN_CTRL_UNSETPEER
+ | MISDN_CTRL_GETPEER;
break;
case MISDN_CTRL_SETPEER:
hc->remoteip = (u32)cq->p1;
@@ -964,6 +977,13 @@ channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq)
hc->remoteip = 0;
l1oip_socket_open(hc);
break;
+ case MISDN_CTRL_GETPEER:
+ if (debug & DEBUG_L1OIP_SOCKET)
+ printk(KERN_DEBUG "%s: getting ip address.\n",
+ __func__);
+ cq->p1 = hc->remoteip;
+ cq->p2 = hc->remoteport | (hc->localport << 16);
+ break;
default:
printk(KERN_WARNING "%s: unknown Op %x\n",
__func__, cq->op);
@@ -1413,7 +1433,8 @@ init_card(struct l1oip *hc, int pri, int bundle)
hc->chan[i + ch].bch = bch;
set_channelmap(bch->nr, dch->dev.channelmap);
}
- ret = mISDN_register_device(&dch->dev, hc->name);
+ /* TODO: create a parent device for this driver */
+ ret = mISDN_register_device(&dch->dev, NULL, hc->name);
if (ret)
return ret;
hc->registered = 1;
diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c
index b73e952d12cf..e826eeb1ecec 100644
--- a/drivers/isdn/mISDN/layer1.c
+++ b/drivers/isdn/mISDN/layer1.c
@@ -101,7 +101,7 @@ l1m_debug(struct FsmInst *fi, char *fmt, ...)
va_list va;
va_start(va, fmt);
- printk(KERN_DEBUG "%s: ", l1->dch->dev.name);
+ printk(KERN_DEBUG "%s: ", dev_name(&l1->dch->dev.dev));
vprintk(fmt, va);
printk("\n");
va_end(va);
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 37a2de18cfd0..508945d1b9c1 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -381,7 +381,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
memcpy(di.channelmap, dev->channelmap,
sizeof(di.channelmap));
di.nrbchan = dev->nrbchan;
- strcpy(di.name, dev->name);
+ strcpy(di.name, dev_name(&dev->dev));
if (copy_to_user((void __user *)arg, &di, sizeof(di)))
err = -EFAULT;
} else
@@ -460,6 +460,8 @@ data_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
struct sockaddr_mISDN *maddr = (struct sockaddr_mISDN *) addr;
struct sock *sk = sock->sk;
+ struct hlist_node *node;
+ struct sock *csk;
int err = 0;
if (*debug & DEBUG_SOCKET)
@@ -480,6 +482,26 @@ data_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
err = -ENODEV;
goto done;
}
+
+ if (sk->sk_protocol < ISDN_P_B_START) {
+ read_lock_bh(&data_sockets.lock);
+ sk_for_each(csk, node, &data_sockets.head) {
+ if (sk == csk)
+ continue;
+ if (_pms(csk)->dev != _pms(sk)->dev)
+ continue;
+ if (csk->sk_protocol >= ISDN_P_B_START)
+ continue;
+ if (IS_ISDN_P_TE(csk->sk_protocol)
+ == IS_ISDN_P_TE(sk->sk_protocol))
+ continue;
+ read_unlock_bh(&data_sockets.lock);
+ err = -EBUSY;
+ goto done;
+ }
+ read_unlock_bh(&data_sockets.lock);
+ }
+
_pms(sk)->ch.send = mISDN_send;
_pms(sk)->ch.ctrl = mISDN_ctrl;
@@ -639,12 +661,27 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
memcpy(di.channelmap, dev->channelmap,
sizeof(di.channelmap));
di.nrbchan = dev->nrbchan;
- strcpy(di.name, dev->name);
+ strcpy(di.name, dev_name(&dev->dev));
if (copy_to_user((void __user *)arg, &di, sizeof(di)))
err = -EFAULT;
} else
err = -ENODEV;
break;
+ case IMSETDEVNAME:
+ {
+ struct mISDN_devrename dn;
+ if (copy_from_user(&dn, (void __user *)arg,
+ sizeof(dn))) {
+ err = -EFAULT;
+ break;
+ }
+ dev = get_mdevice(dn.id);
+ if (dev)
+ err = device_rename(&dev->dev, dn.name);
+ else
+ err = -ENODEV;
+ }
+ break;
default:
err = -EINVAL;
}
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c
index d55b14ae4e99..e2f45019ebf0 100644
--- a/drivers/isdn/mISDN/stack.c
+++ b/drivers/isdn/mISDN/stack.c
@@ -172,7 +172,8 @@ send_msg_to_layer(struct mISDNstack *st, struct sk_buff *skb)
else
printk(KERN_WARNING
"%s: dev(%s) prim(%x) id(%x) no channel\n",
- __func__, st->dev->name, hh->prim, hh->id);
+ __func__, dev_name(&st->dev->dev), hh->prim,
+ hh->id);
} else if (lm == 0x8) {
WARN_ON(lm == 0x8);
ch = get_channel4id(st, hh->id);
@@ -181,11 +182,12 @@ send_msg_to_layer(struct mISDNstack *st, struct sk_buff *skb)
else
printk(KERN_WARNING
"%s: dev(%s) prim(%x) id(%x) no channel\n",
- __func__, st->dev->name, hh->prim, hh->id);
+ __func__, dev_name(&st->dev->dev), hh->prim,
+ hh->id);
} else {
/* broadcast not handled yet */
printk(KERN_WARNING "%s: dev(%s) prim %x not delivered\n",
- __func__, st->dev->name, hh->prim);
+ __func__, dev_name(&st->dev->dev), hh->prim);
}
return -ESRCH;
}
@@ -209,7 +211,8 @@ mISDNStackd(void *data)
unlock_kernel();
#endif
if (*debug & DEBUG_MSG_THREAD)
- printk(KERN_DEBUG "mISDNStackd %s started\n", st->dev->name);
+ printk(KERN_DEBUG "mISDNStackd %s started\n",
+ dev_name(&st->dev->dev));
if (st->notify != NULL) {
complete(st->notify);
@@ -245,7 +248,7 @@ mISDNStackd(void *data)
printk(KERN_DEBUG
"%s: %s prim(%x) id(%x) "
"send call(%d)\n",
- __func__, st->dev->name,
+ __func__, dev_name(&st->dev->dev),
mISDN_HEAD_PRIM(skb),
mISDN_HEAD_ID(skb), err);
dev_kfree_skb(skb);
@@ -288,7 +291,7 @@ mISDNStackd(void *data)
mISDN_STACK_ACTION_MASK));
if (*debug & DEBUG_MSG_THREAD)
printk(KERN_DEBUG "%s: %s wake status %08lx\n",
- __func__, st->dev->name, st->status);
+ __func__, dev_name(&st->dev->dev), st->status);
test_and_set_bit(mISDN_STACK_ACTIVE, &st->status);
test_and_clear_bit(mISDN_STACK_WAKEUP, &st->status);
@@ -303,15 +306,16 @@ mISDNStackd(void *data)
#ifdef MISDN_MSG_STATS
printk(KERN_DEBUG "mISDNStackd daemon for %s proceed %d "
"msg %d sleep %d stopped\n",
- st->dev->name, st->msg_cnt, st->sleep_cnt, st->stopped_cnt);
+ dev_name(&st->dev->dev), st->msg_cnt, st->sleep_cnt,
+ st->stopped_cnt);
printk(KERN_DEBUG
"mISDNStackd daemon for %s utime(%ld) stime(%ld)\n",
- st->dev->name, st->thread->utime, st->thread->stime);
+ dev_name(&st->dev->dev), st->thread->utime, st->thread->stime);
printk(KERN_DEBUG
"mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n",
- st->dev->name, st->thread->nvcsw, st->thread->nivcsw);
+ dev_name(&st->dev->dev), st->thread->nvcsw, st->thread->nivcsw);
printk(KERN_DEBUG "mISDNStackd daemon for %s killed now\n",
- st->dev->name);
+ dev_name(&st->dev->dev));
#endif
test_and_set_bit(mISDN_STACK_KILLED, &st->status);
test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
@@ -401,15 +405,16 @@ create_stack(struct mISDNdevice *dev)
newst->own.send = mISDN_queue_message;
newst->own.recv = mISDN_queue_message;
if (*debug & DEBUG_CORE_FUNC)
- printk(KERN_DEBUG "%s: st(%s)\n", __func__, newst->dev->name);
+ printk(KERN_DEBUG "%s: st(%s)\n", __func__,
+ dev_name(&newst->dev->dev));
newst->notify = &done;
newst->thread = kthread_run(mISDNStackd, (void *)newst, "mISDN_%s",
- newst->dev->name);
+ dev_name(&newst->dev->dev));
if (IS_ERR(newst->thread)) {
err = PTR_ERR(newst->thread);
printk(KERN_ERR
"mISDN:cannot create kernel thread for %s (%d)\n",
- newst->dev->name, err);
+ dev_name(&newst->dev->dev), err);
delete_teimanager(dev->teimgr);
kfree(newst);
} else
@@ -428,29 +433,21 @@ connect_layer1(struct mISDNdevice *dev, struct mISDNchannel *ch,
if (*debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
- __func__, dev->name, protocol, adr->dev, adr->channel,
- adr->sapi, adr->tei);
+ __func__, dev_name(&dev->dev), protocol, adr->dev,
+ adr->channel, adr->sapi, adr->tei);
switch (protocol) {
case ISDN_P_NT_S0:
case ISDN_P_NT_E1:
case ISDN_P_TE_S0:
case ISDN_P_TE_E1:
-#ifdef PROTOCOL_CHECK
- /* this should be enhanced */
- if (!list_empty(&dev->D.st->layer2)
- && dev->D.protocol != protocol)
- return -EBUSY;
- if (!hlist_empty(&dev->D.st->l1sock.head)
- && dev->D.protocol != protocol)
- return -EBUSY;
-#endif
ch->recv = mISDN_queue_message;
ch->peer = &dev->D.st->own;
ch->st = dev->D.st;
rq.protocol = protocol;
- rq.adr.channel = 0;
+ rq.adr.channel = adr->channel;
err = dev->D.ctrl(&dev->D, OPEN_CHANNEL, &rq);
- printk(KERN_DEBUG "%s: ret 1 %d\n", __func__, err);
+ printk(KERN_DEBUG "%s: ret %d (dev %d)\n", __func__, err,
+ dev->id);
if (err)
return err;
write_lock_bh(&dev->D.st->l1sock.lock);
@@ -473,7 +470,7 @@ connect_Bstack(struct mISDNdevice *dev, struct mISDNchannel *ch,
if (*debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
- __func__, dev->name, protocol,
+ __func__, dev_name(&dev->dev), protocol,
adr->dev, adr->channel, adr->sapi,
adr->tei);
ch->st = dev->D.st;
@@ -529,7 +526,7 @@ create_l2entity(struct mISDNdevice *dev, struct mISDNchannel *ch,
if (*debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
- __func__, dev->name, protocol,
+ __func__, dev_name(&dev->dev), protocol,
adr->dev, adr->channel, adr->sapi,
adr->tei);
rq.protocol = ISDN_P_TE_S0;
@@ -541,15 +538,6 @@ create_l2entity(struct mISDNdevice *dev, struct mISDNchannel *ch,
if (dev->Dprotocols & (1 << ISDN_P_NT_E1))
rq.protocol = ISDN_P_NT_E1;
case ISDN_P_LAPD_TE:
-#ifdef PROTOCOL_CHECK
- /* this should be enhanced */
- if (!list_empty(&dev->D.st->layer2)
- && dev->D.protocol != protocol)
- return -EBUSY;
- if (!hlist_empty(&dev->D.st->l1sock.head)
- && dev->D.protocol != protocol)
- return -EBUSY;
-#endif
ch->recv = mISDN_queue_message;
ch->peer = &dev->D.st->own;
ch->st = dev->D.st;
@@ -590,7 +578,7 @@ delete_channel(struct mISDNchannel *ch)
}
if (*debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: st(%s) protocol(%x)\n", __func__,
- ch->st->dev->name, ch->protocol);
+ dev_name(&ch->st->dev->dev), ch->protocol);
if (ch->protocol >= ISDN_P_B_START) {
if (ch->peer) {
ch->peer->ctrl(ch->peer, CLOSE_CHANNEL, NULL);
@@ -643,7 +631,7 @@ delete_stack(struct mISDNdevice *dev)
if (*debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: st(%s)\n", __func__,
- st->dev->name);
+ dev_name(&st->dev->dev));
if (dev->teimgr)
delete_teimanager(dev->teimgr);
if (st->thread) {
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c
index 5c43d19e7c11..b452dead8fd0 100644
--- a/drivers/isdn/mISDN/tei.c
+++ b/drivers/isdn/mISDN/tei.c
@@ -968,9 +968,9 @@ create_teimgr(struct manager *mgr, struct channel_req *crq)
if (*debug & DEBUG_L2_TEI)
printk(KERN_DEBUG "%s: %s proto(%x) adr(%d %d %d %d)\n",
- __func__, mgr->ch.st->dev->name, crq->protocol,
- crq->adr.dev, crq->adr.channel, crq->adr.sapi,
- crq->adr.tei);
+ __func__, dev_name(&mgr->ch.st->dev->dev),
+ crq->protocol, crq->adr.dev, crq->adr.channel,
+ crq->adr.sapi, crq->adr.tei);
if (crq->adr.sapi != 0) /* not supported yet */
return -EINVAL;
if (crq->adr.tei > GROUP_TEI)
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e7fb7d2fcbfc..742713611bc5 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -63,6 +63,12 @@ config LEDS_WRAP
help
This option enables support for the PCEngines WRAP programmable LEDs.
+config LEDS_ALIX2
+ tristate "LED Support for ALIX.2 and ALIX.3 series"
+ depends on LEDS_CLASS && X86 && EXPERIMENTAL
+ help
+ This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
+
config LEDS_H1940
tristate "LED Support for iPAQ H1940 device"
depends on LEDS_CLASS && ARCH_H1940
@@ -77,7 +83,7 @@ config LEDS_COBALT_QUBE
config LEDS_COBALT_RAQ
bool "LED Support for the Cobalt Raq series"
- depends on LEDS_CLASS && MIPS_COBALT
+ depends on LEDS_CLASS=y && MIPS_COBALT
select LEDS_TRIGGERS
help
This option enables support for the Cobalt Raq series LEDs.
@@ -113,13 +119,6 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines.
-config LEDS_HP_DISK
- tristate "LED Support for disk protection LED on HP notebooks"
- depends on LEDS_CLASS && ACPI
- help
- This option enable support for disk protection LED, found on
- newer HP notebooks.
-
config LEDS_CLEVO_MAIL
tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI && EXPERIMENTAL
@@ -158,6 +157,13 @@ config LEDS_PCA955X
LED driver chips accessed via the I2C bus. Supported
devices include PCA9550, PCA9551, PCA9552, and PCA9553.
+config LEDS_WM8350
+ tristate "LED Support for WM8350 AudioPlus PMIC"
+ depends on LEDS_CLASS && MFD_WM8350
+ help
+ This option enables support for LEDs driven by the Wolfson
+ Microelectronics WM8350 AudioPlus PMIC.
+
config LEDS_DA903X
tristate "LED Support for DA9030/DA9034 PMIC"
depends on LEDS_CLASS && PMIC_DA903X
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e1967a29850e..9d76f0f160a4 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
+obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
@@ -22,7 +23,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
-obj-$(CONFIG_LEDS_HP_DISK) += leds-hp-disk.o
+obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 6c4a326176d7..52f82e3ea13a 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -91,9 +91,29 @@ void led_classdev_resume(struct led_classdev *led_cdev)
}
EXPORT_SYMBOL_GPL(led_classdev_resume);
+static int led_suspend(struct device *dev, pm_message_t state)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+ if (led_cdev->flags & LED_CORE_SUSPENDRESUME)
+ led_classdev_suspend(led_cdev);
+
+ return 0;
+}
+
+static int led_resume(struct device *dev)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+ if (led_cdev->flags & LED_CORE_SUSPENDRESUME)
+ led_classdev_resume(led_cdev);
+
+ return 0;
+}
+
/**
* led_classdev_register - register a new object of led_classdev class.
- * @dev: The device to register.
+ * @parent: The device to register.
* @led_cdev: the led_classdev structure for this device.
*/
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
@@ -174,6 +194,8 @@ static int __init leds_init(void)
leds_class = class_create(THIS_MODULE, "leds");
if (IS_ERR(leds_class))
return PTR_ERR(leds_class);
+ leds_class->suspend = led_suspend;
+ leds_class->resume = led_resume;
return 0;
}
diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c
new file mode 100644
index 000000000000..ddbd7730dfc8
--- /dev/null
+++ b/drivers/leds/leds-alix2.c
@@ -0,0 +1,181 @@
+/*
+ * LEDs driver for PCEngines ALIX.2 and ALIX.3
+ *
+ * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+
+static int force = 0;
+module_param(force, bool, 0444);
+MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs");
+
+struct alix_led {
+ struct led_classdev cdev;
+ unsigned short port;
+ unsigned int on_value;
+ unsigned int off_value;
+};
+
+static void alix_led_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct alix_led *led_dev =
+ container_of(led_cdev, struct alix_led, cdev);
+
+ if (brightness)
+ outl(led_dev->on_value, led_dev->port);
+ else
+ outl(led_dev->off_value, led_dev->port);
+}
+
+static struct alix_led alix_leds[] = {
+ {
+ .cdev = {
+ .name = "alix:1",
+ .brightness_set = alix_led_set,
+ },
+ .port = 0x6100,
+ .on_value = 1 << 22,
+ .off_value = 1 << 6,
+ },
+ {
+ .cdev = {
+ .name = "alix:2",
+ .brightness_set = alix_led_set,
+ },
+ .port = 0x6180,
+ .on_value = 1 << 25,
+ .off_value = 1 << 9,
+ },
+ {
+ .cdev = {
+ .name = "alix:3",
+ .brightness_set = alix_led_set,
+ },
+ .port = 0x6180,
+ .on_value = 1 << 27,
+ .off_value = 1 << 11,
+ },
+};
+
+static int __init alix_led_probe(struct platform_device *pdev)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(alix_leds); i++) {
+ alix_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
+ ret = led_classdev_register(&pdev->dev, &alix_leds[i].cdev);
+ if (ret < 0)
+ goto fail;
+ }
+ return 0;
+
+fail:
+ while (--i >= 0)
+ led_classdev_unregister(&alix_leds[i].cdev);
+ return ret;
+}
+
+static int alix_led_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(alix_leds); i++)
+ led_classdev_unregister(&alix_leds[i].cdev);
+ return 0;
+}
+
+static struct platform_driver alix_led_driver = {
+ .remove = alix_led_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init alix_present(void)
+{
+ const unsigned long bios_phys = 0x000f0000;
+ const size_t bios_len = 0x00010000;
+ const char alix_sig[] = "PC Engines ALIX.";
+ const size_t alix_sig_len = sizeof(alix_sig) - 1;
+
+ const char *bios_virt;
+ const char *scan_end;
+ const char *p;
+ int ret = 0;
+
+ if (force) {
+ printk(KERN_NOTICE "%s: forced to skip BIOS test, "
+ "assume system has ALIX.2 style LEDs\n",
+ KBUILD_MODNAME);
+ ret = 1;
+ goto out;
+ }
+
+ bios_virt = phys_to_virt(bios_phys);
+ scan_end = bios_virt + bios_len - (alix_sig_len + 2);
+ for (p = bios_virt; p < scan_end; p++) {
+ const char *tail;
+
+ if (memcmp(p, alix_sig, alix_sig_len) != 0) {
+ continue;
+ }
+
+ tail = p + alix_sig_len;
+ if ((tail[0] == '2' || tail[0] == '3') && tail[1] == '\0') {
+ printk(KERN_INFO
+ "%s: system is recognized as \"%s\"\n",
+ KBUILD_MODNAME, p);
+ ret = 1;
+ break;
+ }
+ }
+
+out:
+ return ret;
+}
+
+static struct platform_device *pdev;
+
+static int __init alix_led_init(void)
+{
+ int ret;
+
+ if (!alix_present()) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
+ if (!IS_ERR(pdev)) {
+ ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
+ if (ret)
+ platform_device_unregister(pdev);
+ } else
+ ret = PTR_ERR(pdev);
+
+out:
+ return ret;
+}
+
+static void __exit alix_led_exit(void)
+{
+ platform_device_unregister(pdev);
+ platform_driver_unregister(&alix_led_driver);
+}
+
+module_init(alix_led_init);
+module_exit(alix_led_exit);
+
+MODULE_AUTHOR("Constantin Baranov <const@mimas.ru>");
+MODULE_DESCRIPTION("PCEngines ALIX.2 and ALIX.3 LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c
index 1bd590bb3a6e..446050759b4d 100644
--- a/drivers/leds/leds-ams-delta.c
+++ b/drivers/leds/leds-ams-delta.c
@@ -79,37 +79,12 @@ static struct ams_delta_led ams_delta_leds[] = {
},
};
-#ifdef CONFIG_PM
-static int ams_delta_led_suspend(struct platform_device *dev,
- pm_message_t state)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
- led_classdev_suspend(&ams_delta_leds[i].cdev);
-
- return 0;
-}
-
-static int ams_delta_led_resume(struct platform_device *dev)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
- led_classdev_resume(&ams_delta_leds[i].cdev);
-
- return 0;
-}
-#else
-#define ams_delta_led_suspend NULL
-#define ams_delta_led_resume NULL
-#endif
-
static int ams_delta_led_probe(struct platform_device *pdev)
{
int i, ret;
for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) {
+ ams_delta_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME;
ret = led_classdev_register(&pdev->dev,
&ams_delta_leds[i].cdev);
if (ret < 0)
@@ -127,7 +102,7 @@ static int ams_delta_led_remove(struct platform_device *pdev)
{
int i;
- for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i--)
+ for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
led_classdev_unregister(&ams_delta_leds[i].cdev);
return 0;
@@ -136,8 +111,6 @@ static int ams_delta_led_remove(struct platform_device *pdev)
static struct platform_driver ams_delta_led_driver = {
.probe = ams_delta_led_probe,
.remove = ams_delta_led_remove,
- .suspend = ams_delta_led_suspend,
- .resume = ams_delta_led_resume,
.driver = {
.name = "ams-delta-led",
.owner = THIS_MODULE,
@@ -151,7 +124,7 @@ static int __init ams_delta_led_init(void)
static void __exit ams_delta_led_exit(void)
{
- return platform_driver_unregister(&ams_delta_led_driver);
+ platform_driver_unregister(&ams_delta_led_driver);
}
module_init(ams_delta_led_init);
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index eb3415e88f43..1813c84ea5fc 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -142,6 +142,7 @@ static struct led_classdev clevo_mail_led = {
.name = "clevo::mail",
.brightness_set = clevo_mail_led_set,
.blink_set = clevo_mail_led_blink,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static int __init clevo_mail_led_probe(struct platform_device *pdev)
@@ -155,29 +156,9 @@ static int clevo_mail_led_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int clevo_mail_led_suspend(struct platform_device *dev,
- pm_message_t state)
-{
- led_classdev_suspend(&clevo_mail_led);
- return 0;
-}
-
-static int clevo_mail_led_resume(struct platform_device *dev)
-{
- led_classdev_resume(&clevo_mail_led);
- return 0;
-}
-#else
-#define clevo_mail_led_suspend NULL
-#define clevo_mail_led_resume NULL
-#endif
-
static struct platform_driver clevo_mail_led_driver = {
.probe = clevo_mail_led_probe,
.remove = clevo_mail_led_remove,
- .suspend = clevo_mail_led_suspend,
- .resume = clevo_mail_led_resume,
.driver = {
.name = KBUILD_MODNAME,
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
index 34935155c1c0..5f7c9c5c09b1 100644
--- a/drivers/leds/leds-fsg.c
+++ b/drivers/leds/leds-fsg.c
@@ -99,64 +99,43 @@ static void fsg_led_ring_set(struct led_classdev *led_cdev,
}
-
static struct led_classdev fsg_wlan_led = {
.name = "fsg:blue:wlan",
.brightness_set = fsg_led_wlan_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev fsg_wan_led = {
.name = "fsg:blue:wan",
.brightness_set = fsg_led_wan_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev fsg_sata_led = {
.name = "fsg:blue:sata",
.brightness_set = fsg_led_sata_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev fsg_usb_led = {
.name = "fsg:blue:usb",
.brightness_set = fsg_led_usb_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev fsg_sync_led = {
.name = "fsg:blue:sync",
.brightness_set = fsg_led_sync_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev fsg_ring_led = {
.name = "fsg:blue:ring",
.brightness_set = fsg_led_ring_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
-
-#ifdef CONFIG_PM
-static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
-{
- led_classdev_suspend(&fsg_wlan_led);
- led_classdev_suspend(&fsg_wan_led);
- led_classdev_suspend(&fsg_sata_led);
- led_classdev_suspend(&fsg_usb_led);
- led_classdev_suspend(&fsg_sync_led);
- led_classdev_suspend(&fsg_ring_led);
- return 0;
-}
-
-static int fsg_led_resume(struct platform_device *dev)
-{
- led_classdev_resume(&fsg_wlan_led);
- led_classdev_resume(&fsg_wan_led);
- led_classdev_resume(&fsg_sata_led);
- led_classdev_resume(&fsg_usb_led);
- led_classdev_resume(&fsg_sync_led);
- led_classdev_resume(&fsg_ring_led);
- return 0;
-}
-#endif
-
-
static int fsg_led_probe(struct platform_device *pdev)
{
int ret;
@@ -232,10 +211,6 @@ static int fsg_led_remove(struct platform_device *pdev)
static struct platform_driver fsg_led_driver = {
.probe = fsg_led_probe,
.remove = fsg_led_remove,
-#ifdef CONFIG_PM
- .suspend = fsg_led_suspend,
- .resume = fsg_led_resume,
-#endif
.driver = {
.name = "fsg-led",
},
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index b13bd2950e95..2e3df08b649b 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -105,6 +105,7 @@ static int gpio_led_probe(struct platform_device *pdev)
}
led_dat->cdev.brightness_set = gpio_led_set;
led_dat->cdev.brightness = LED_OFF;
+ led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
gpio_direction_output(led_dat->gpio, led_dat->active_low);
@@ -154,44 +155,9 @@ static int __devexit gpio_led_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int gpio_led_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
- struct gpio_led_data *leds_data;
- int i;
-
- leds_data = platform_get_drvdata(pdev);
-
- for (i = 0; i < pdata->num_leds; i++)
- led_classdev_suspend(&leds_data[i].cdev);
-
- return 0;
-}
-
-static int gpio_led_resume(struct platform_device *pdev)
-{
- struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
- struct gpio_led_data *leds_data;
- int i;
-
- leds_data = platform_get_drvdata(pdev);
-
- for (i = 0; i < pdata->num_leds; i++)
- led_classdev_resume(&leds_data[i].cdev);
-
- return 0;
-}
-#else
-#define gpio_led_suspend NULL
-#define gpio_led_resume NULL
-#endif
-
static struct platform_driver gpio_led_driver = {
.probe = gpio_led_probe,
.remove = __devexit_p(gpio_led_remove),
- .suspend = gpio_led_suspend,
- .resume = gpio_led_resume,
.driver = {
.name = "leds-gpio",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-hp-disk.c b/drivers/leds/leds-hp-disk.c
deleted file mode 100644
index 44fa757d8254..000000000000
--- a/drivers/leds/leds-hp-disk.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * leds-hp-disk.c - driver for HP "hard disk protection" LED
- *
- * Copyright (C) 2008 Pavel Machek
- *
- * 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
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/kthread.h>
-#include <linux/leds.h>
-#include <acpi/acpi_drivers.h>
-
-#define DRIVER_NAME "leds-hp-disk"
-#define ACPI_MDPS_CLASS "led"
-
-/* For automatic insertion of the module */
-static struct acpi_device_id hpled_device_ids[] = {
- {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
- {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, hpled_device_ids);
-
-struct acpi_hpled {
- struct acpi_device *device; /* The ACPI device */
-};
-
-static struct acpi_hpled adev;
-
-static acpi_status hpled_acpi_write(acpi_handle handle, int reg)
-{
- unsigned long long ret; /* Not used when writing */
- union acpi_object in_obj[1];
- struct acpi_object_list args = { 1, in_obj };
-
- in_obj[0].type = ACPI_TYPE_INTEGER;
- in_obj[0].integer.value = reg;
-
- return acpi_evaluate_integer(handle, "ALED", &args, &ret);
-}
-
-static void hpled_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- hpled_acpi_write(adev.device->handle, !!value);
-}
-
-static struct led_classdev hpled_led = {
- .name = "hp:red:hddprotection",
- .default_trigger = "heartbeat",
- .brightness_set = hpled_set,
-};
-
-#ifdef CONFIG_PM
-static int hpled_suspend(struct acpi_device *dev, pm_message_t state)
-{
- led_classdev_suspend(&hpled_led);
- return 0;
-}
-
-static int hpled_resume(struct acpi_device *dev)
-{
- led_classdev_resume(&hpled_led);
- return 0;
-}
-#else
-#define hpled_suspend NULL
-#define hpled_resume NULL
-#endif
-
-static int hpled_add(struct acpi_device *device)
-{
- int ret;
-
- if (!device)
- return -EINVAL;
-
- adev.device = device;
- strcpy(acpi_device_name(device), DRIVER_NAME);
- strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
- device->driver_data = &adev;
-
- ret = led_classdev_register(NULL, &hpled_led);
- return ret;
-}
-
-static int hpled_remove(struct acpi_device *device, int type)
-{
- if (!device)
- return -EINVAL;
-
- led_classdev_unregister(&hpled_led);
- return 0;
-}
-
-
-
-static struct acpi_driver leds_hp_driver = {
- .name = DRIVER_NAME,
- .class = ACPI_MDPS_CLASS,
- .ids = hpled_device_ids,
- .ops = {
- .add = hpled_add,
- .remove = hpled_remove,
- .suspend = hpled_suspend,
- .resume = hpled_resume,
- }
-};
-
-static int __init hpled_init_module(void)
-{
- int ret;
-
- if (acpi_disabled)
- return -ENODEV;
-
- ret = acpi_bus_register_driver(&leds_hp_driver);
- if (ret < 0)
- return ret;
-
- printk(KERN_INFO DRIVER_NAME " driver loaded.\n");
-
- return 0;
-}
-
-static void __exit hpled_exit_module(void)
-{
- acpi_bus_unregister_driver(&leds_hp_driver);
-}
-
-MODULE_DESCRIPTION("Driver for HP disk protection LED");
-MODULE_AUTHOR("Pavel Machek <pavel@suse.cz>");
-MODULE_LICENSE("GPL");
-
-module_init(hpled_init_module);
-module_exit(hpled_exit_module);
diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c
index e8fb1baf8a50..e4ce1fd46338 100644
--- a/drivers/leds/leds-hp6xx.c
+++ b/drivers/leds/leds-hp6xx.c
@@ -45,30 +45,16 @@ static struct led_classdev hp6xx_red_led = {
.name = "hp6xx:red",
.default_trigger = "hp6xx-charge",
.brightness_set = hp6xxled_red_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev hp6xx_green_led = {
.name = "hp6xx:green",
.default_trigger = "ide-disk",
.brightness_set = hp6xxled_green_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
-#ifdef CONFIG_PM
-static int hp6xxled_suspend(struct platform_device *dev, pm_message_t state)
-{
- led_classdev_suspend(&hp6xx_red_led);
- led_classdev_suspend(&hp6xx_green_led);
- return 0;
-}
-
-static int hp6xxled_resume(struct platform_device *dev)
-{
- led_classdev_resume(&hp6xx_red_led);
- led_classdev_resume(&hp6xx_green_led);
- return 0;
-}
-#endif
-
static int hp6xxled_probe(struct platform_device *pdev)
{
int ret;
@@ -98,10 +84,6 @@ MODULE_ALIAS("platform:hp6xx-led");
static struct platform_driver hp6xxled_driver = {
.probe = hp6xxled_probe,
.remove = hp6xxled_remove,
-#ifdef CONFIG_PM
- .suspend = hp6xxled_suspend,
- .resume = hp6xxled_resume,
-#endif
.driver = {
.name = "hp6xx-led",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c
index 054360473c94..93987a12da49 100644
--- a/drivers/leds/leds-net48xx.c
+++ b/drivers/leds/leds-net48xx.c
@@ -33,26 +33,9 @@ static void net48xx_error_led_set(struct led_classdev *led_cdev,
static struct led_classdev net48xx_error_led = {
.name = "net48xx::error",
.brightness_set = net48xx_error_led_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
-#ifdef CONFIG_PM
-static int net48xx_led_suspend(struct platform_device *dev,
- pm_message_t state)
-{
- led_classdev_suspend(&net48xx_error_led);
- return 0;
-}
-
-static int net48xx_led_resume(struct platform_device *dev)
-{
- led_classdev_resume(&net48xx_error_led);
- return 0;
-}
-#else
-#define net48xx_led_suspend NULL
-#define net48xx_led_resume NULL
-#endif
-
static int net48xx_led_probe(struct platform_device *pdev)
{
return led_classdev_register(&pdev->dev, &net48xx_error_led);
@@ -67,8 +50,6 @@ static int net48xx_led_remove(struct platform_device *pdev)
static struct platform_driver net48xx_led_driver = {
.probe = net48xx_led_probe,
.remove = net48xx_led_remove,
- .suspend = net48xx_led_suspend,
- .resume = net48xx_led_resume,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 4064d4f6b33b..76ec7498e2d5 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -16,6 +16,7 @@
#include <linux/leds.h>
#include <linux/input.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include <linux/leds-pca9532.h>
static const unsigned short normal_i2c[] = { /*0x60,*/ I2C_CLIENT_END};
@@ -34,6 +35,7 @@ struct pca9532_data {
struct pca9532_led leds[16];
struct mutex update_lock;
struct input_dev *idev;
+ struct work_struct work;
u8 pwm[2];
u8 psc[2];
};
@@ -63,7 +65,7 @@ static struct i2c_driver pca9532_driver = {
* as a compromise we average one pwm to the values requested by all
* leds that are not ON/OFF.
* */
-static int pca9532_setpwm(struct i2c_client *client, int pwm, int blink,
+static int pca9532_calcpwm(struct i2c_client *client, int pwm, int blink,
enum led_brightness value)
{
int a = 0, b = 0, i = 0;
@@ -84,11 +86,17 @@ static int pca9532_setpwm(struct i2c_client *client, int pwm, int blink,
b = b/a;
if (b > 0xFF)
return -EINVAL;
- mutex_lock(&data->update_lock);
data->pwm[pwm] = b;
+ data->psc[pwm] = blink;
+ return 0;
+}
+
+static int pca9532_setpwm(struct i2c_client *client, int pwm)
+{
+ struct pca9532_data *data = i2c_get_clientdata(client);
+ mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm),
data->pwm[pwm]);
- data->psc[pwm] = blink;
i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm),
data->psc[pwm]);
mutex_unlock(&data->update_lock);
@@ -124,11 +132,11 @@ static void pca9532_set_brightness(struct led_classdev *led_cdev,
led->state = PCA9532_ON;
else {
led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
- err = pca9532_setpwm(led->client, 0, 0, value);
+ err = pca9532_calcpwm(led->client, 0, 0, value);
if (err)
return; /* XXX: led api doesn't allow error code? */
}
- pca9532_setled(led);
+ schedule_work(&led->work);
}
static int pca9532_set_blink(struct led_classdev *led_cdev,
@@ -137,6 +145,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev,
struct pca9532_led *led = ldev_to_led(led_cdev);
struct i2c_client *client = led->client;
int psc;
+ int err = 0;
if (*delay_on == 0 && *delay_off == 0) {
/* led subsystem ask us for a blink rate */
@@ -148,11 +157,15 @@ static int pca9532_set_blink(struct led_classdev *led_cdev,
/* Thecus specific: only use PSC/PWM 0 */
psc = (*delay_on * 152-1)/1000;
- return pca9532_setpwm(client, 0, psc, led_cdev->brightness);
+ err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness);
+ if (err)
+ return err;
+ schedule_work(&led->work);
+ return 0;
}
-int pca9532_event(struct input_dev *dev, unsigned int type, unsigned int code,
- int value)
+static int pca9532_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
{
struct pca9532_data *data = input_get_drvdata(dev);
@@ -165,13 +178,28 @@ int pca9532_event(struct input_dev *dev, unsigned int type, unsigned int code,
else
data->pwm[1] = 0;
- dev_info(&dev->dev, "setting beep to %d \n", data->pwm[1]);
+ schedule_work(&data->work);
+
+ return 0;
+}
+
+static void pca9532_input_work(struct work_struct *work)
+{
+ struct pca9532_data *data;
+ data = container_of(work, struct pca9532_data, work);
mutex_lock(&data->update_lock);
i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1),
data->pwm[1]);
mutex_unlock(&data->update_lock);
+}
- return 0;
+static void pca9532_led_work(struct work_struct *work)
+{
+ struct pca9532_led *led;
+ led = container_of(work, struct pca9532_led, work);
+ if (led->state == PCA9532_PWM0)
+ pca9532_setpwm(led->client, 0);
+ pca9532_setled(led);
}
static int pca9532_configure(struct i2c_client *client,
@@ -204,8 +232,9 @@ static int pca9532_configure(struct i2c_client *client,
led->ldev.brightness = LED_OFF;
led->ldev.brightness_set = pca9532_set_brightness;
led->ldev.blink_set = pca9532_set_blink;
- if (led_classdev_register(&client->dev,
- &led->ldev) < 0) {
+ INIT_WORK(&led->work, pca9532_led_work);
+ err = led_classdev_register(&client->dev, &led->ldev);
+ if (err < 0) {
dev_err(&client->dev,
"couldn't register LED %s\n",
led->name);
@@ -233,9 +262,11 @@ static int pca9532_configure(struct i2c_client *client,
BIT_MASK(SND_TONE);
data->idev->event = pca9532_event;
input_set_drvdata(data->idev, data);
+ INIT_WORK(&data->work, pca9532_input_work);
err = input_register_device(data->idev);
if (err) {
input_free_device(data->idev);
+ cancel_work_sync(&data->work);
data->idev = NULL;
goto exit;
}
@@ -252,18 +283,19 @@ exit:
break;
case PCA9532_TYPE_LED:
led_classdev_unregister(&data->leds[i].ldev);
+ cancel_work_sync(&data->leds[i].work);
break;
case PCA9532_TYPE_N2100_BEEP:
if (data->idev != NULL) {
input_unregister_device(data->idev);
input_free_device(data->idev);
+ cancel_work_sync(&data->work);
data->idev = NULL;
}
break;
}
return err;
-
}
static int pca9532_probe(struct i2c_client *client,
@@ -271,12 +303,16 @@ static int pca9532_probe(struct i2c_client *client,
{
struct pca9532_data *data = i2c_get_clientdata(client);
struct pca9532_platform_data *pca9532_pdata = client->dev.platform_data;
+ int err;
+
+ if (!pca9532_pdata)
+ return -EIO;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
- data = kzalloc(sizeof(struct pca9532_data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -285,12 +321,13 @@ static int pca9532_probe(struct i2c_client *client,
data->client = client;
mutex_init(&data->update_lock);
- if (pca9532_pdata == NULL)
- return -EIO;
-
- pca9532_configure(client, data, pca9532_pdata);
- return 0;
+ err = pca9532_configure(client, data, pca9532_pdata);
+ if (err) {
+ kfree(data);
+ i2c_set_clientdata(client, NULL);
+ }
+ return err;
}
static int pca9532_remove(struct i2c_client *client)
@@ -303,11 +340,13 @@ static int pca9532_remove(struct i2c_client *client)
break;
case PCA9532_TYPE_LED:
led_classdev_unregister(&data->leds[i].ldev);
+ cancel_work_sync(&data->leds[i].work);
break;
case PCA9532_TYPE_N2100_BEEP:
if (data->idev != NULL) {
input_unregister_device(data->idev);
input_free_device(data->idev);
+ cancel_work_sync(&data->work);
data->idev = NULL;
}
break;
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 25a07f2643ad..4d81131542ae 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -82,6 +82,7 @@ static int s3c24xx_led_probe(struct platform_device *dev)
led->cdev.brightness_set = s3c24xx_led_set;
led->cdev.default_trigger = pdata->def_trigger;
led->cdev.name = pdata->name;
+ led->cdev.flags |= LED_CORE_SUSPENDRESUME;
led->pdata = pdata;
@@ -111,33 +112,9 @@ static int s3c24xx_led_probe(struct platform_device *dev)
return ret;
}
-
-#ifdef CONFIG_PM
-static int s3c24xx_led_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
-
- led_classdev_suspend(&led->cdev);
- return 0;
-}
-
-static int s3c24xx_led_resume(struct platform_device *dev)
-{
- struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
-
- led_classdev_resume(&led->cdev);
- return 0;
-}
-#else
-#define s3c24xx_led_suspend NULL
-#define s3c24xx_led_resume NULL
-#endif
-
static struct platform_driver s3c24xx_led_driver = {
.probe = s3c24xx_led_probe,
.remove = s3c24xx_led_remove,
- .suspend = s3c24xx_led_suspend,
- .resume = s3c24xx_led_resume,
.driver = {
.name = "s3c24xx_led",
.owner = THIS_MODULE,
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
new file mode 100644
index 000000000000..38c6bcb07e6c
--- /dev/null
+++ b/drivers/leds/leds-wm8350.c
@@ -0,0 +1,311 @@
+/*
+ * LED driver for WM8350 driven LEDS.
+ *
+ * Copyright(C) 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/mfd/wm8350/pmic.h>
+#include <linux/regulator/consumer.h>
+
+/* Microamps */
+static const int isink_cur[] = {
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 10,
+ 11,
+ 14,
+ 16,
+ 19,
+ 23,
+ 27,
+ 32,
+ 39,
+ 46,
+ 54,
+ 65,
+ 77,
+ 92,
+ 109,
+ 130,
+ 154,
+ 183,
+ 218,
+ 259,
+ 308,
+ 367,
+ 436,
+ 518,
+ 616,
+ 733,
+ 872,
+ 1037,
+ 1233,
+ 1466,
+ 1744,
+ 2073,
+ 2466,
+ 2933,
+ 3487,
+ 4147,
+ 4932,
+ 5865,
+ 6975,
+ 8294,
+ 9864,
+ 11730,
+ 13949,
+ 16589,
+ 19728,
+ 23460,
+ 27899,
+ 33178,
+ 39455,
+ 46920,
+ 55798,
+ 66355,
+ 78910,
+ 93840,
+ 111596,
+ 132710,
+ 157820,
+ 187681,
+ 223191
+};
+
+#define to_wm8350_led(led_cdev) \
+ container_of(led_cdev, struct wm8350_led, cdev)
+
+static void wm8350_led_enable(struct wm8350_led *led)
+{
+ int ret;
+
+ if (led->enabled)
+ return;
+
+ ret = regulator_enable(led->isink);
+ if (ret != 0) {
+ dev_err(led->cdev.dev, "Failed to enable ISINK: %d\n", ret);
+ return;
+ }
+
+ ret = regulator_enable(led->dcdc);
+ if (ret != 0) {
+ dev_err(led->cdev.dev, "Failed to enable DCDC: %d\n", ret);
+ regulator_disable(led->isink);
+ return;
+ }
+
+ led->enabled = 1;
+}
+
+static void wm8350_led_disable(struct wm8350_led *led)
+{
+ int ret;
+
+ if (!led->enabled)
+ return;
+
+ ret = regulator_disable(led->dcdc);
+ if (ret != 0) {
+ dev_err(led->cdev.dev, "Failed to disable DCDC: %d\n", ret);
+ return;
+ }
+
+ ret = regulator_disable(led->isink);
+ if (ret != 0) {
+ dev_err(led->cdev.dev, "Failed to disable ISINK: %d\n", ret);
+ regulator_enable(led->dcdc);
+ return;
+ }
+
+ led->enabled = 0;
+}
+
+static void led_work(struct work_struct *work)
+{
+ struct wm8350_led *led = container_of(work, struct wm8350_led, work);
+ int ret;
+ int uA;
+ unsigned long flags;
+
+ mutex_lock(&led->mutex);
+
+ spin_lock_irqsave(&led->value_lock, flags);
+
+ if (led->value == LED_OFF) {
+ spin_unlock_irqrestore(&led->value_lock, flags);
+ wm8350_led_disable(led);
+ goto out;
+ }
+
+ /* This scales linearly into the index of valid current
+ * settings which results in a linear scaling of perceived
+ * brightness due to the non-linear current settings provided
+ * by the hardware.
+ */
+ uA = (led->max_uA_index * led->value) / LED_FULL;
+ spin_unlock_irqrestore(&led->value_lock, flags);
+ BUG_ON(uA >= ARRAY_SIZE(isink_cur));
+
+ ret = regulator_set_current_limit(led->isink, isink_cur[uA],
+ isink_cur[uA]);
+ if (ret != 0)
+ dev_err(led->cdev.dev, "Failed to set %duA: %d\n",
+ isink_cur[uA], ret);
+
+ wm8350_led_enable(led);
+
+out:
+ mutex_unlock(&led->mutex);
+}
+
+static void wm8350_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct wm8350_led *led = to_wm8350_led(led_cdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&led->value_lock, flags);
+ led->value = value;
+ schedule_work(&led->work);
+ spin_unlock_irqrestore(&led->value_lock, flags);
+}
+
+static void wm8350_led_shutdown(struct platform_device *pdev)
+{
+ struct wm8350_led *led = platform_get_drvdata(pdev);
+
+ mutex_lock(&led->mutex);
+ led->value = LED_OFF;
+ wm8350_led_disable(led);
+ mutex_unlock(&led->mutex);
+}
+
+static int wm8350_led_probe(struct platform_device *pdev)
+{
+ struct regulator *isink, *dcdc;
+ struct wm8350_led *led;
+ struct wm8350_led_platform_data *pdata = pdev->dev.platform_data;
+ int ret, i;
+
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "no platform data\n");
+ return -ENODEV;
+ }
+
+ if (pdata->max_uA < isink_cur[0]) {
+ dev_err(&pdev->dev, "Invalid maximum current %duA\n",
+ pdata->max_uA);
+ return -EINVAL;
+ }
+
+ isink = regulator_get(&pdev->dev, "led_isink");
+ if (IS_ERR(isink)) {
+ printk(KERN_ERR "%s: cant get ISINK\n", __func__);
+ return PTR_ERR(isink);
+ }
+
+ dcdc = regulator_get(&pdev->dev, "led_vcc");
+ if (IS_ERR(dcdc)) {
+ printk(KERN_ERR "%s: cant get DCDC\n", __func__);
+ ret = PTR_ERR(dcdc);
+ goto err_isink;
+ }
+
+ led = kzalloc(sizeof(*led), GFP_KERNEL);
+ if (led == NULL) {
+ ret = -ENOMEM;
+ goto err_dcdc;
+ }
+
+ led->cdev.brightness_set = wm8350_led_set;
+ led->cdev.default_trigger = pdata->default_trigger;
+ led->cdev.name = pdata->name;
+ led->cdev.flags |= LED_CORE_SUSPENDRESUME;
+ led->enabled = regulator_is_enabled(isink);
+ led->isink = isink;
+ led->dcdc = dcdc;
+
+ for (i = 0; i < ARRAY_SIZE(isink_cur) - 1; i++)
+ if (isink_cur[i] >= pdata->max_uA)
+ break;
+ led->max_uA_index = i;
+ if (pdata->max_uA != isink_cur[i])
+ dev_warn(&pdev->dev,
+ "Maximum current %duA is not directly supported,"
+ " check platform data\n",
+ pdata->max_uA);
+
+ spin_lock_init(&led->value_lock);
+ mutex_init(&led->mutex);
+ INIT_WORK(&led->work, led_work);
+ led->value = LED_OFF;
+ platform_set_drvdata(pdev, led);
+
+ ret = led_classdev_register(&pdev->dev, &led->cdev);
+ if (ret < 0)
+ goto err_led;
+
+ return 0;
+
+ err_led:
+ kfree(led);
+ err_dcdc:
+ regulator_put(dcdc);
+ err_isink:
+ regulator_put(isink);
+ return ret;
+}
+
+static int wm8350_led_remove(struct platform_device *pdev)
+{
+ struct wm8350_led *led = platform_get_drvdata(pdev);
+
+ led_classdev_unregister(&led->cdev);
+ flush_scheduled_work();
+ wm8350_led_disable(led);
+ regulator_put(led->dcdc);
+ regulator_put(led->isink);
+ kfree(led);
+ return 0;
+}
+
+static struct platform_driver wm8350_led_driver = {
+ .driver = {
+ .name = "wm8350-led",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8350_led_probe,
+ .remove = wm8350_led_remove,
+ .shutdown = wm8350_led_shutdown,
+};
+
+static int __devinit wm8350_led_init(void)
+{
+ return platform_driver_register(&wm8350_led_driver);
+}
+module_init(wm8350_led_init);
+
+static void wm8350_led_exit(void)
+{
+ platform_driver_unregister(&wm8350_led_driver);
+}
+module_exit(wm8350_led_exit);
+
+MODULE_AUTHOR("Mark Brown");
+MODULE_DESCRIPTION("WM8350 LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-led");
diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c
index 2f3aa87f2a1f..2982c86ac4cf 100644
--- a/drivers/leds/leds-wrap.c
+++ b/drivers/leds/leds-wrap.c
@@ -56,40 +56,21 @@ static struct led_classdev wrap_power_led = {
.name = "wrap::power",
.brightness_set = wrap_power_led_set,
.default_trigger = "default-on",
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev wrap_error_led = {
.name = "wrap::error",
.brightness_set = wrap_error_led_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
static struct led_classdev wrap_extra_led = {
.name = "wrap::extra",
.brightness_set = wrap_extra_led_set,
+ .flags = LED_CORE_SUSPENDRESUME,
};
-#ifdef CONFIG_PM
-static int wrap_led_suspend(struct platform_device *dev,
- pm_message_t state)
-{
- led_classdev_suspend(&wrap_power_led);
- led_classdev_suspend(&wrap_error_led);
- led_classdev_suspend(&wrap_extra_led);
- return 0;
-}
-
-static int wrap_led_resume(struct platform_device *dev)
-{
- led_classdev_resume(&wrap_power_led);
- led_classdev_resume(&wrap_error_led);
- led_classdev_resume(&wrap_extra_led);
- return 0;
-}
-#else
-#define wrap_led_suspend NULL
-#define wrap_led_resume NULL
-#endif
-
static int wrap_led_probe(struct platform_device *pdev)
{
int ret;
@@ -127,8 +108,6 @@ static int wrap_led_remove(struct platform_device *pdev)
static struct platform_driver wrap_led_driver = {
.probe = wrap_led_probe,
.remove = wrap_led_remove,
- .suspend = wrap_led_suspend,
- .resume = wrap_led_resume,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c
index db681962d7bb..3d6531396dda 100644
--- a/drivers/leds/ledtrig-timer.c
+++ b/drivers/leds/ledtrig-timer.c
@@ -199,6 +199,7 @@ err_out:
static void timer_trig_deactivate(struct led_classdev *led_cdev)
{
struct timer_trig_data *timer_data = led_cdev->trigger_data;
+ unsigned long on = 0, off = 0;
if (timer_data) {
device_remove_file(led_cdev->dev, &dev_attr_delay_on);
@@ -206,6 +207,10 @@ static void timer_trig_deactivate(struct led_classdev *led_cdev)
del_timer_sync(&timer_data->timer);
kfree(timer_data);
}
+
+ /* If there is hardware support for blinking, stop it */
+ if (led_cdev->blink_set)
+ led_cdev->blink_set(led_cdev, &on, &off);
}
static struct led_trigger timer_led_trigger = {
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 90663e01a56e..60156dfdc608 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -224,7 +224,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
break;
/* If the Guest asked to be stopped, we sleep. The Guest's
- * clock timer or LHCALL_BREAK from the Waker will wake us. */
+ * clock timer or LHREQ_BREAK from the Waker will wake us. */
if (cpu->halted) {
set_current_state(TASK_INTERRUPTIBLE);
schedule();
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c
index a1039068f95c..415fab0125ac 100644
--- a/drivers/lguest/interrupts_and_traps.c
+++ b/drivers/lguest/interrupts_and_traps.c
@@ -222,11 +222,16 @@ bool check_syscall_vector(struct lguest *lg)
int init_interrupts(void)
{
/* If they want some strange system call vector, reserve it now */
- if (syscall_vector != SYSCALL_VECTOR
- && test_and_set_bit(syscall_vector, used_vectors)) {
- printk("lg: couldn't reserve syscall %u\n", syscall_vector);
- return -EBUSY;
+ if (syscall_vector != SYSCALL_VECTOR) {
+ if (test_bit(syscall_vector, used_vectors) ||
+ vector_used_by_percpu_irq(syscall_vector)) {
+ printk(KERN_ERR "lg: couldn't reserve syscall %u\n",
+ syscall_vector);
+ return -EBUSY;
+ }
+ set_bit(syscall_vector, used_vectors);
}
+
return 0;
}
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 915da6b8c924..b4d44e571d76 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -321,10 +321,7 @@ static struct virtio_config_ops lguest_config_ops = {
/* The root device for the lguest virtio devices. This makes them appear as
* /sys/devices/lguest/0,1,2 not /sys/devices/0,1,2. */
-static struct device lguest_root = {
- .parent = NULL,
- .bus_id = "lguest",
-};
+static struct device *lguest_root;
/*D:120 This is the core of the lguest bus: actually adding a new device.
* It's a separate function because it's neater that way, and because an
@@ -351,7 +348,7 @@ static void add_lguest_device(struct lguest_device_desc *d,
}
/* This devices' parent is the lguest/ dir. */
- ldev->vdev.dev.parent = &lguest_root;
+ ldev->vdev.dev.parent = lguest_root;
/* We have a unique device index thanks to the dev_index counter. */
ldev->vdev.id.device = d->type;
/* We have a simple set of routines for querying the device's
@@ -407,7 +404,8 @@ static int __init lguest_devices_init(void)
if (strcmp(pv_info.name, "lguest") != 0)
return 0;
- if (device_register(&lguest_root) != 0)
+ lguest_root = root_device_register("lguest");
+ if (IS_ERR(lguest_root))
panic("Could not register lguest root");
/* Devices are in a single page above top of "normal" mem */
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
index 34bc017b8b3c..b8ee103eed5f 100644
--- a/drivers/lguest/lguest_user.c
+++ b/drivers/lguest/lguest_user.c
@@ -307,9 +307,8 @@ static int close(struct inode *inode, struct file *file)
* kmalloc()ed string, either of which is ok to hand to kfree(). */
if (!IS_ERR(lg->dead))
kfree(lg->dead);
- /* We clear the entire structure, which also marks it as free for the
- * next user. */
- memset(lg, 0, sizeof(*lg));
+ /* Free the memory allocated to the lguest_struct */
+ kfree(lg);
/* Release lock and exit. */
mutex_unlock(&lguest_lock);
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index b52659620d50..173cf55c64d0 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -138,7 +138,7 @@ config PMAC_BACKLIGHT
Say Y here to enable Macintosh specific extensions of the generic
backlight code. With this enabled, the brightness keys on older
PowerBooks will be enabled so you can change the screen brightness.
- Newer models should use an userspace daemon like pbbuttonsd.
+ Newer models should use a userspace daemon like pbbuttonsd.
config PMAC_BACKLIGHT_LEGACY
bool "Provide legacy ioctl's on /dev/pmu for the backlight"
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index ec9e5f32f0ae..6e149f4a1fff 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -33,7 +33,7 @@
#undef DEBUG
-#define MAX_NODE_NAME_SIZE (BUS_ID_SIZE - 12)
+#define MAX_NODE_NAME_SIZE (20 - 12)
static struct macio_chip *macio_on_hold;
@@ -240,7 +240,7 @@ static void macio_create_fixup_irq(struct macio_dev *dev, int index,
if (irq != NO_IRQ) {
dev->interrupt[index].start = irq;
dev->interrupt[index].flags = IORESOURCE_IRQ;
- dev->interrupt[index].name = dev->ofdev.dev.bus_id;
+ dev->interrupt[index].name = dev_name(&dev->ofdev.dev);
}
if (dev->n_interrupts <= index)
dev->n_interrupts = index + 1;
@@ -303,7 +303,7 @@ static void macio_setup_interrupts(struct macio_dev *dev)
break;
res->start = irq;
res->flags = IORESOURCE_IRQ;
- res->name = dev->ofdev.dev.bus_id;
+ res->name = dev_name(&dev->ofdev.dev);
if (macio_resource_quirks(np, res, i - 1)) {
memset(res, 0, sizeof(struct resource));
continue;
@@ -325,7 +325,7 @@ static void macio_setup_resources(struct macio_dev *dev,
if (index >= MACIO_DEV_COUNT_RESOURCES)
break;
*res = r;
- res->name = dev->ofdev.dev.bus_id;
+ res->name = dev_name(&dev->ofdev.dev);
if (macio_resource_quirks(np, res, index)) {
memset(res, 0, sizeof(struct resource));
@@ -338,7 +338,7 @@ static void macio_setup_resources(struct macio_dev *dev,
if (insert_resource(parent_res, res)) {
printk(KERN_WARNING "Can't request resource "
"%d for MacIO device %s\n",
- index, dev->ofdev.dev.bus_id);
+ index, dev_name(&dev->ofdev.dev));
}
}
dev->n_resources = index;
@@ -385,8 +385,8 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
/* MacIO itself has a different reg, we use it's PCI base */
if (np == chip->of_node) {
- sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s",
- chip->lbus.index,
+ dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s",
+ chip->lbus.index,
#ifdef CONFIG_PCI
(unsigned int)pci_resource_start(chip->lbus.pdev, 0),
#else
@@ -395,9 +395,9 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
MAX_NODE_NAME_SIZE, np->name);
} else {
reg = of_get_property(np, "reg", NULL);
- sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s",
- chip->lbus.index,
- reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name);
+ dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s",
+ chip->lbus.index,
+ reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name);
}
/* Setup interrupts & resources */
@@ -408,7 +408,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
/* Register with core */
if (of_device_register(&dev->ofdev) != 0) {
printk(KERN_DEBUG"macio: device registration error for %s!\n",
- dev->ofdev.dev.bus_id);
+ dev_name(&dev->ofdev.dev));
kfree(dev);
return NULL;
}
@@ -558,7 +558,7 @@ err_out:
resource_no,
macio_resource_len(dev, resource_no),
macio_resource_start(dev, resource_no),
- dev->ofdev.dev.bus_id);
+ dev_name(&dev->ofdev.dev));
return -EBUSY;
}
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 22bf981d393b..82607add69a9 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -554,7 +554,7 @@ thermostat_init(void)
const u32 *prop;
int i = 0, offset = 0;
int err;
-
+
np = of_find_node_by_name(NULL, "fan");
if (!np)
return -ENODEV;
@@ -613,13 +613,13 @@ thermostat_init(void)
}
of_dev = of_platform_device_create(np, "temperatures", NULL);
-
+ of_node_put(np);
+
if (of_dev == NULL) {
printk(KERN_ERR "Can't register temperatures device !\n");
- of_node_put(np);
return -ENODEV;
}
-
+
err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature);
err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature);
err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit);
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 1c615804ea76..72880b7e28d9 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -3,9 +3,10 @@
#
dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
- dm-ioctl.o dm-io.o dm-kcopyd.o
+ dm-ioctl.o dm-io.o dm-kcopyd.o dm-sysfs.o
dm-multipath-objs := dm-path-selector.o dm-mpath.o
-dm-snapshot-objs := dm-snap.o dm-exception-store.o
+dm-snapshot-objs := dm-snap.o dm-exception-store.o dm-snap-transient.o \
+ dm-snap-persistent.o
dm-mirror-objs := dm-raid1.o
md-mod-objs := md.o bitmap.o
raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index ab7c8e4a61f9..719943763391 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -215,7 +215,6 @@ static struct page *read_sb_page(mddev_t *mddev, long offset,
/* choose a good rdev and read the page from there */
mdk_rdev_t *rdev;
- struct list_head *tmp;
sector_t target;
if (!page)
@@ -223,7 +222,7 @@ static struct page *read_sb_page(mddev_t *mddev, long offset,
if (!page)
return ERR_PTR(-ENOMEM);
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
if (! test_bit(In_sync, &rdev->flags)
|| test_bit(Faulty, &rdev->flags))
continue;
@@ -964,9 +963,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
*/
page = bitmap->sb_page;
offset = sizeof(bitmap_super_t);
- read_sb_page(bitmap->mddev, bitmap->offset,
- page,
- index, count);
+ if (!file)
+ read_sb_page(bitmap->mddev,
+ bitmap->offset,
+ page,
+ index, count);
} else if (file) {
page = read_page(file, index, bitmap, count);
offset = 0;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 3326750ec02c..35bda49796fb 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1322,11 +1322,7 @@ static int __init dm_crypt_init(void)
static void __exit dm_crypt_exit(void)
{
- int r = dm_unregister_target(&crypt_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
-
+ dm_unregister_target(&crypt_target);
kmem_cache_destroy(_crypt_io_pool);
}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 848b381f1173..59ee1b015d2d 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -364,11 +364,7 @@ bad_queue:
static void __exit dm_delay_exit(void)
{
- int r = dm_unregister_target(&delay_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
-
+ dm_unregister_target(&delay_target);
kmem_cache_destroy(delayed_cache);
destroy_workqueue(kdelayd_wq);
}
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 01590f3e0009..dccbfb0e010f 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -1,756 +1,45 @@
/*
- * dm-exception-store.c
- *
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
- * Copyright (C) 2006 Red Hat GmbH
+ * Copyright (C) 2006-2008 Red Hat GmbH
*
* This file is released under the GPL.
*/
-#include "dm-snap.h"
+#include "dm-exception-store.h"
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
-#include <linux/dm-io.h>
-#include <linux/dm-kcopyd.h>
-
-#define DM_MSG_PREFIX "snapshots"
-#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
-
-/*-----------------------------------------------------------------
- * Persistent snapshots, by persistent we mean that the snapshot
- * will survive a reboot.
- *---------------------------------------------------------------*/
-
-/*
- * We need to store a record of which parts of the origin have
- * been copied to the snapshot device. The snapshot code
- * requires that we copy exception chunks to chunk aligned areas
- * of the COW store. It makes sense therefore, to store the
- * metadata in chunk size blocks.
- *
- * There is no backward or forward compatibility implemented,
- * snapshots with different disk versions than the kernel will
- * not be usable. It is expected that "lvcreate" will blank out
- * the start of a fresh COW device before calling the snapshot
- * constructor.
- *
- * The first chunk of the COW device just contains the header.
- * After this there is a chunk filled with exception metadata,
- * followed by as many exception chunks as can fit in the
- * metadata areas.
- *
- * All on disk structures are in little-endian format. The end
- * of the exceptions info is indicated by an exception with a
- * new_chunk of 0, which is invalid since it would point to the
- * header chunk.
- */
-
-/*
- * Magic for persistent snapshots: "SnAp" - Feeble isn't it.
- */
-#define SNAP_MAGIC 0x70416e53
-
-/*
- * The on-disk version of the metadata.
- */
-#define SNAPSHOT_DISK_VERSION 1
-
-struct disk_header {
- uint32_t magic;
-
- /*
- * Is this snapshot valid. There is no way of recovering
- * an invalid snapshot.
- */
- uint32_t valid;
-
- /*
- * Simple, incrementing version. no backward
- * compatibility.
- */
- uint32_t version;
-
- /* In sectors */
- uint32_t chunk_size;
-};
-
-struct disk_exception {
- uint64_t old_chunk;
- uint64_t new_chunk;
-};
-
-struct commit_callback {
- void (*callback)(void *, int success);
- void *context;
-};
-
-/*
- * The top level structure for a persistent exception store.
- */
-struct pstore {
- struct dm_snapshot *snap; /* up pointer to my snapshot */
- int version;
- int valid;
- uint32_t exceptions_per_area;
-
- /*
- * Now that we have an asynchronous kcopyd there is no
- * need for large chunk sizes, so it wont hurt to have a
- * whole chunks worth of metadata in memory at once.
- */
- void *area;
-
- /*
- * An area of zeros used to clear the next area.
- */
- void *zero_area;
-
- /*
- * Used to keep track of which metadata area the data in
- * 'chunk' refers to.
- */
- chunk_t current_area;
-
- /*
- * The next free chunk for an exception.
- */
- chunk_t next_free;
-
- /*
- * The index of next free exception in the current
- * metadata area.
- */
- uint32_t current_committed;
-
- atomic_t pending_count;
- uint32_t callback_count;
- struct commit_callback *callbacks;
- struct dm_io_client *io_client;
-
- struct workqueue_struct *metadata_wq;
-};
-
-static unsigned sectors_to_pages(unsigned sectors)
-{
- return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
-}
-
-static int alloc_area(struct pstore *ps)
-{
- int r = -ENOMEM;
- size_t len;
-
- len = ps->snap->chunk_size << SECTOR_SHIFT;
-
- /*
- * Allocate the chunk_size block of memory that will hold
- * a single metadata area.
- */
- ps->area = vmalloc(len);
- if (!ps->area)
- return r;
-
- ps->zero_area = vmalloc(len);
- if (!ps->zero_area) {
- vfree(ps->area);
- return r;
- }
- memset(ps->zero_area, 0, len);
-
- return 0;
-}
-
-static void free_area(struct pstore *ps)
-{
- vfree(ps->area);
- ps->area = NULL;
- vfree(ps->zero_area);
- ps->zero_area = NULL;
-}
-
-struct mdata_req {
- struct dm_io_region *where;
- struct dm_io_request *io_req;
- struct work_struct work;
- int result;
-};
-
-static void do_metadata(struct work_struct *work)
-{
- struct mdata_req *req = container_of(work, struct mdata_req, work);
-
- req->result = dm_io(req->io_req, 1, req->where, NULL);
-}
-
-/*
- * Read or write a chunk aligned and sized block of data from a device.
- */
-static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
-{
- struct dm_io_region where = {
- .bdev = ps->snap->cow->bdev,
- .sector = ps->snap->chunk_size * chunk,
- .count = ps->snap->chunk_size,
- };
- struct dm_io_request io_req = {
- .bi_rw = rw,
- .mem.type = DM_IO_VMA,
- .mem.ptr.vma = ps->area,
- .client = ps->io_client,
- .notify.fn = NULL,
- };
- struct mdata_req req;
-
- if (!metadata)
- return dm_io(&io_req, 1, &where, NULL);
-
- req.where = &where;
- req.io_req = &io_req;
-
- /*
- * Issue the synchronous I/O from a different thread
- * to avoid generic_make_request recursion.
- */
- INIT_WORK(&req.work, do_metadata);
- queue_work(ps->metadata_wq, &req.work);
- flush_workqueue(ps->metadata_wq);
-
- return req.result;
-}
-
-/*
- * Convert a metadata area index to a chunk index.
- */
-static chunk_t area_location(struct pstore *ps, chunk_t area)
-{
- return 1 + ((ps->exceptions_per_area + 1) * area);
-}
-
-/*
- * Read or write a metadata area. Remembering to skip the first
- * chunk which holds the header.
- */
-static int area_io(struct pstore *ps, int rw)
-{
- int r;
- chunk_t chunk;
-
- chunk = area_location(ps, ps->current_area);
-
- r = chunk_io(ps, chunk, rw, 0);
- if (r)
- return r;
-
- return 0;
-}
-
-static void zero_memory_area(struct pstore *ps)
-{
- memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
-}
-
-static int zero_disk_area(struct pstore *ps, chunk_t area)
-{
- struct dm_io_region where = {
- .bdev = ps->snap->cow->bdev,
- .sector = ps->snap->chunk_size * area_location(ps, area),
- .count = ps->snap->chunk_size,
- };
- struct dm_io_request io_req = {
- .bi_rw = WRITE,
- .mem.type = DM_IO_VMA,
- .mem.ptr.vma = ps->zero_area,
- .client = ps->io_client,
- .notify.fn = NULL,
- };
-
- return dm_io(&io_req, 1, &where, NULL);
-}
-
-static int read_header(struct pstore *ps, int *new_snapshot)
-{
- int r;
- struct disk_header *dh;
- chunk_t chunk_size;
- int chunk_size_supplied = 1;
-
- /*
- * Use default chunk size (or hardsect_size, if larger) if none supplied
- */
- if (!ps->snap->chunk_size) {
- ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
- bdev_hardsect_size(ps->snap->cow->bdev) >> 9);
- ps->snap->chunk_mask = ps->snap->chunk_size - 1;
- ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1;
- chunk_size_supplied = 0;
- }
-
- ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
- chunk_size));
- if (IS_ERR(ps->io_client))
- return PTR_ERR(ps->io_client);
-
- r = alloc_area(ps);
- if (r)
- return r;
-
- r = chunk_io(ps, 0, READ, 1);
- if (r)
- goto bad;
-
- dh = (struct disk_header *) ps->area;
-
- if (le32_to_cpu(dh->magic) == 0) {
- *new_snapshot = 1;
- return 0;
- }
-
- if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
- DMWARN("Invalid or corrupt snapshot");
- r = -ENXIO;
- goto bad;
- }
-
- *new_snapshot = 0;
- ps->valid = le32_to_cpu(dh->valid);
- ps->version = le32_to_cpu(dh->version);
- chunk_size = le32_to_cpu(dh->chunk_size);
-
- if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size)
- return 0;
-
- DMWARN("chunk size %llu in device metadata overrides "
- "table chunk size of %llu.",
- (unsigned long long)chunk_size,
- (unsigned long long)ps->snap->chunk_size);
-
- /* We had a bogus chunk_size. Fix stuff up. */
- free_area(ps);
-
- ps->snap->chunk_size = chunk_size;
- ps->snap->chunk_mask = chunk_size - 1;
- ps->snap->chunk_shift = ffs(chunk_size) - 1;
-
- r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
- ps->io_client);
- if (r)
- return r;
-
- r = alloc_area(ps);
- return r;
-
-bad:
- free_area(ps);
- return r;
-}
-
-static int write_header(struct pstore *ps)
-{
- struct disk_header *dh;
-
- memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
-
- dh = (struct disk_header *) ps->area;
- dh->magic = cpu_to_le32(SNAP_MAGIC);
- dh->valid = cpu_to_le32(ps->valid);
- dh->version = cpu_to_le32(ps->version);
- dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
-
- return chunk_io(ps, 0, WRITE, 1);
-}
-
-/*
- * Access functions for the disk exceptions, these do the endian conversions.
- */
-static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
-{
- BUG_ON(index >= ps->exceptions_per_area);
-
- return ((struct disk_exception *) ps->area) + index;
-}
-static void read_exception(struct pstore *ps,
- uint32_t index, struct disk_exception *result)
-{
- struct disk_exception *e = get_exception(ps, index);
-
- /* copy it */
- result->old_chunk = le64_to_cpu(e->old_chunk);
- result->new_chunk = le64_to_cpu(e->new_chunk);
-}
-
-static void write_exception(struct pstore *ps,
- uint32_t index, struct disk_exception *de)
-{
- struct disk_exception *e = get_exception(ps, index);
-
- /* copy it */
- e->old_chunk = cpu_to_le64(de->old_chunk);
- e->new_chunk = cpu_to_le64(de->new_chunk);
-}
+#define DM_MSG_PREFIX "snapshot exception stores"
-/*
- * Registers the exceptions that are present in the current area.
- * 'full' is filled in to indicate if the area has been
- * filled.
- */
-static int insert_exceptions(struct pstore *ps, int *full)
+int dm_exception_store_init(void)
{
int r;
- unsigned int i;
- struct disk_exception de;
-
- /* presume the area is full */
- *full = 1;
-
- for (i = 0; i < ps->exceptions_per_area; i++) {
- read_exception(ps, i, &de);
-
- /*
- * If the new_chunk is pointing at the start of
- * the COW device, where the first metadata area
- * is we know that we've hit the end of the
- * exceptions. Therefore the area is not full.
- */
- if (de.new_chunk == 0LL) {
- ps->current_committed = i;
- *full = 0;
- break;
- }
-
- /*
- * Keep track of the start of the free chunks.
- */
- if (ps->next_free <= de.new_chunk)
- ps->next_free = de.new_chunk + 1;
-
- /*
- * Otherwise we add the exception to the snapshot.
- */
- r = dm_add_exception(ps->snap, de.old_chunk, de.new_chunk);
- if (r)
- return r;
- }
-
- return 0;
-}
-
-static int read_exceptions(struct pstore *ps)
-{
- int r, full = 1;
-
- /*
- * Keeping reading chunks and inserting exceptions until
- * we find a partially full area.
- */
- for (ps->current_area = 0; full; ps->current_area++) {
- r = area_io(ps, READ);
- if (r)
- return r;
- r = insert_exceptions(ps, &full);
- if (r)
- return r;
+ r = dm_transient_snapshot_init();
+ if (r) {
+ DMERR("Unable to register transient exception store type.");
+ goto transient_fail;
}
- ps->current_area--;
-
- return 0;
-}
-
-static struct pstore *get_info(struct exception_store *store)
-{
- return (struct pstore *) store->context;
-}
-
-static void persistent_fraction_full(struct exception_store *store,
- sector_t *numerator, sector_t *denominator)
-{
- *numerator = get_info(store)->next_free * store->snap->chunk_size;
- *denominator = get_dev_size(store->snap->cow->bdev);
-}
-
-static void persistent_destroy(struct exception_store *store)
-{
- struct pstore *ps = get_info(store);
-
- destroy_workqueue(ps->metadata_wq);
- dm_io_client_destroy(ps->io_client);
- vfree(ps->callbacks);
- free_area(ps);
- kfree(ps);
-}
-
-static int persistent_read_metadata(struct exception_store *store)
-{
- int r, uninitialized_var(new_snapshot);
- struct pstore *ps = get_info(store);
-
- /*
- * Read the snapshot header.
- */
- r = read_header(ps, &new_snapshot);
- if (r)
- return r;
-
- /*
- * Now we know correct chunk_size, complete the initialisation.
- */
- ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
- sizeof(struct disk_exception);
- ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
- sizeof(*ps->callbacks));
- if (!ps->callbacks)
- return -ENOMEM;
-
- /*
- * Do we need to setup a new snapshot ?
- */
- if (new_snapshot) {
- r = write_header(ps);
- if (r) {
- DMWARN("write_header failed");
- return r;
- }
-
- ps->current_area = 0;
- zero_memory_area(ps);
- r = zero_disk_area(ps, 0);
- if (r) {
- DMWARN("zero_disk_area(0) failed");
- return r;
- }
- } else {
- /*
- * Sanity checks.
- */
- if (ps->version != SNAPSHOT_DISK_VERSION) {
- DMWARN("unable to handle snapshot disk version %d",
- ps->version);
- return -EINVAL;
- }
-
- /*
- * Metadata are valid, but snapshot is invalidated
- */
- if (!ps->valid)
- return 1;
-
- /*
- * Read the metadata.
- */
- r = read_exceptions(ps);
- if (r)
- return r;
+ r = dm_persistent_snapshot_init();
+ if (r) {
+ DMERR("Unable to register persistent exception store type");
+ goto persistent_fail;
}
return 0;
-}
-
-static int persistent_prepare(struct exception_store *store,
- struct dm_snap_exception *e)
-{
- struct pstore *ps = get_info(store);
- uint32_t stride;
- chunk_t next_free;
- sector_t size = get_dev_size(store->snap->cow->bdev);
-
- /* Is there enough room ? */
- if (size < ((ps->next_free + 1) * store->snap->chunk_size))
- return -ENOSPC;
- e->new_chunk = ps->next_free;
-
- /*
- * Move onto the next free pending, making sure to take
- * into account the location of the metadata chunks.
- */
- stride = (ps->exceptions_per_area + 1);
- next_free = ++ps->next_free;
- if (sector_div(next_free, stride) == 1)
- ps->next_free++;
-
- atomic_inc(&ps->pending_count);
- return 0;
-}
-
-static void persistent_commit(struct exception_store *store,
- struct dm_snap_exception *e,
- void (*callback) (void *, int success),
- void *callback_context)
-{
- unsigned int i;
- struct pstore *ps = get_info(store);
- struct disk_exception de;
- struct commit_callback *cb;
-
- de.old_chunk = e->old_chunk;
- de.new_chunk = e->new_chunk;
- write_exception(ps, ps->current_committed++, &de);
-
- /*
- * Add the callback to the back of the array. This code
- * is the only place where the callback array is
- * manipulated, and we know that it will never be called
- * multiple times concurrently.
- */
- cb = ps->callbacks + ps->callback_count++;
- cb->callback = callback;
- cb->context = callback_context;
-
- /*
- * If there are exceptions in flight and we have not yet
- * filled this metadata area there's nothing more to do.
- */
- if (!atomic_dec_and_test(&ps->pending_count) &&
- (ps->current_committed != ps->exceptions_per_area))
- return;
-
- /*
- * If we completely filled the current area, then wipe the next one.
- */
- if ((ps->current_committed == ps->exceptions_per_area) &&
- zero_disk_area(ps, ps->current_area + 1))
- ps->valid = 0;
-
- /*
- * Commit exceptions to disk.
- */
- if (ps->valid && area_io(ps, WRITE))
- ps->valid = 0;
-
- /*
- * Advance to the next area if this one is full.
- */
- if (ps->current_committed == ps->exceptions_per_area) {
- ps->current_committed = 0;
- ps->current_area++;
- zero_memory_area(ps);
- }
-
- for (i = 0; i < ps->callback_count; i++) {
- cb = ps->callbacks + i;
- cb->callback(cb->context, ps->valid);
- }
-
- ps->callback_count = 0;
-}
-
-static void persistent_drop(struct exception_store *store)
-{
- struct pstore *ps = get_info(store);
-
- ps->valid = 0;
- if (write_header(ps))
- DMWARN("write header failed");
-}
-
-int dm_create_persistent(struct exception_store *store)
-{
- struct pstore *ps;
-
- /* allocate the pstore */
- ps = kmalloc(sizeof(*ps), GFP_KERNEL);
- if (!ps)
- return -ENOMEM;
-
- ps->snap = store->snap;
- ps->valid = 1;
- ps->version = SNAPSHOT_DISK_VERSION;
- ps->area = NULL;
- ps->next_free = 2; /* skipping the header and first area */
- ps->current_committed = 0;
-
- ps->callback_count = 0;
- atomic_set(&ps->pending_count, 0);
- ps->callbacks = NULL;
-
- ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
- if (!ps->metadata_wq) {
- kfree(ps);
- DMERR("couldn't start header metadata update thread");
- return -ENOMEM;
- }
-
- store->destroy = persistent_destroy;
- store->read_metadata = persistent_read_metadata;
- store->prepare_exception = persistent_prepare;
- store->commit_exception = persistent_commit;
- store->drop_snapshot = persistent_drop;
- store->fraction_full = persistent_fraction_full;
- store->context = ps;
-
- return 0;
-}
-
-/*-----------------------------------------------------------------
- * Implementation of the store for non-persistent snapshots.
- *---------------------------------------------------------------*/
-struct transient_c {
- sector_t next_free;
-};
-
-static void transient_destroy(struct exception_store *store)
-{
- kfree(store->context);
-}
-
-static int transient_read_metadata(struct exception_store *store)
-{
- return 0;
-}
-
-static int transient_prepare(struct exception_store *store,
- struct dm_snap_exception *e)
-{
- struct transient_c *tc = (struct transient_c *) store->context;
- sector_t size = get_dev_size(store->snap->cow->bdev);
-
- if (size < (tc->next_free + store->snap->chunk_size))
- return -1;
-
- e->new_chunk = sector_to_chunk(store->snap, tc->next_free);
- tc->next_free += store->snap->chunk_size;
-
- return 0;
-}
-
-static void transient_commit(struct exception_store *store,
- struct dm_snap_exception *e,
- void (*callback) (void *, int success),
- void *callback_context)
-{
- /* Just succeed */
- callback(callback_context, 1);
-}
-
-static void transient_fraction_full(struct exception_store *store,
- sector_t *numerator, sector_t *denominator)
-{
- *numerator = ((struct transient_c *) store->context)->next_free;
- *denominator = get_dev_size(store->snap->cow->bdev);
+persistent_fail:
+ dm_persistent_snapshot_exit();
+transient_fail:
+ return r;
}
-int dm_create_transient(struct exception_store *store)
+void dm_exception_store_exit(void)
{
- struct transient_c *tc;
-
- store->destroy = transient_destroy;
- store->read_metadata = transient_read_metadata;
- store->prepare_exception = transient_prepare;
- store->commit_exception = transient_commit;
- store->drop_snapshot = NULL;
- store->fraction_full = transient_fraction_full;
-
- tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
- if (!tc)
- return -ENOMEM;
-
- tc->next_free = 0;
- store->context = tc;
-
- return 0;
+ dm_persistent_snapshot_exit();
+ dm_transient_snapshot_exit();
}
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
new file mode 100644
index 000000000000..bb9f33d5daa2
--- /dev/null
+++ b/drivers/md/dm-exception-store.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+ *
+ * Device-mapper snapshot exception store.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LINUX_DM_EXCEPTION_STORE
+#define _LINUX_DM_EXCEPTION_STORE
+
+#include <linux/blkdev.h>
+#include <linux/device-mapper.h>
+
+/*
+ * The snapshot code deals with largish chunks of the disk at a
+ * time. Typically 32k - 512k.
+ */
+typedef sector_t chunk_t;
+
+/*
+ * An exception is used where an old chunk of data has been
+ * replaced by a new one.
+ * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
+ * of chunks that follow contiguously. Remaining bits hold the number of the
+ * chunk within the device.
+ */
+struct dm_snap_exception {
+ struct list_head hash_list;
+
+ chunk_t old_chunk;
+ chunk_t new_chunk;
+};
+
+/*
+ * Abstraction to handle the meta/layout of exception stores (the
+ * COW device).
+ */
+struct dm_exception_store {
+ /*
+ * Destroys this object when you've finished with it.
+ */
+ void (*destroy) (struct dm_exception_store *store);
+
+ /*
+ * The target shouldn't read the COW device until this is
+ * called. As exceptions are read from the COW, they are
+ * reported back via the callback.
+ */
+ int (*read_metadata) (struct dm_exception_store *store,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context);
+
+ /*
+ * Find somewhere to store the next exception.
+ */
+ int (*prepare_exception) (struct dm_exception_store *store,
+ struct dm_snap_exception *e);
+
+ /*
+ * Update the metadata with this exception.
+ */
+ void (*commit_exception) (struct dm_exception_store *store,
+ struct dm_snap_exception *e,
+ void (*callback) (void *, int success),
+ void *callback_context);
+
+ /*
+ * The snapshot is invalid, note this in the metadata.
+ */
+ void (*drop_snapshot) (struct dm_exception_store *store);
+
+ int (*status) (struct dm_exception_store *store, status_type_t status,
+ char *result, unsigned int maxlen);
+
+ /*
+ * Return how full the snapshot is.
+ */
+ void (*fraction_full) (struct dm_exception_store *store,
+ sector_t *numerator,
+ sector_t *denominator);
+
+ struct dm_snapshot *snap;
+ void *context;
+};
+
+/*
+ * Funtions to manipulate consecutive chunks
+ */
+# if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
+# define DM_CHUNK_CONSECUTIVE_BITS 8
+# define DM_CHUNK_NUMBER_BITS 56
+
+static inline chunk_t dm_chunk_number(chunk_t chunk)
+{
+ return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
+}
+
+static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
+{
+ return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
+}
+
+static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
+{
+ e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
+
+ BUG_ON(!dm_consecutive_chunk_count(e));
+}
+
+# else
+# define DM_CHUNK_CONSECUTIVE_BITS 0
+
+static inline chunk_t dm_chunk_number(chunk_t chunk)
+{
+ return chunk;
+}
+
+static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
+{
+ return 0;
+}
+
+static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
+{
+}
+
+# endif
+
+int dm_exception_store_init(void);
+void dm_exception_store_exit(void);
+
+/*
+ * Two exception store implementations.
+ */
+int dm_persistent_snapshot_init(void);
+void dm_persistent_snapshot_exit(void);
+
+int dm_transient_snapshot_init(void);
+void dm_transient_snapshot_exit(void);
+
+int dm_create_persistent(struct dm_exception_store *store);
+
+int dm_create_transient(struct dm_exception_store *store);
+
+#endif /* _LINUX_DM_EXCEPTION_STORE */
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 777c948180f9..54d0588fc1f6 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -233,7 +233,7 @@ static void __hash_remove(struct hash_cell *hc)
}
if (hc->new_map)
- dm_table_put(hc->new_map);
+ dm_table_destroy(hc->new_map);
dm_put(hc->md);
free_cell(hc);
}
@@ -827,8 +827,8 @@ static int do_resume(struct dm_ioctl *param)
r = dm_swap_table(md, new_map);
if (r) {
+ dm_table_destroy(new_map);
dm_put(md);
- dm_table_put(new_map);
return r;
}
@@ -836,8 +836,6 @@ static int do_resume(struct dm_ioctl *param)
set_disk_ro(dm_disk(md), 0);
else
set_disk_ro(dm_disk(md), 1);
-
- dm_table_put(new_map);
}
if (dm_suspended(md))
@@ -1080,7 +1078,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
}
if (hc->new_map)
- dm_table_put(hc->new_map);
+ dm_table_destroy(hc->new_map);
hc->new_map = t;
up_write(&_hash_lock);
@@ -1109,7 +1107,7 @@ static int table_clear(struct dm_ioctl *param, size_t param_size)
}
if (hc->new_map) {
- dm_table_put(hc->new_map);
+ dm_table_destroy(hc->new_map);
hc->new_map = NULL;
}
@@ -1550,8 +1548,10 @@ int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid)
goto out;
}
- strcpy(name, hc->name);
- strcpy(uuid, hc->uuid ? : "");
+ if (name)
+ strcpy(name, hc->name);
+ if (uuid)
+ strcpy(uuid, hc->uuid ? : "");
out:
up_read(&_hash_lock);
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 44042becad8a..bfa107f59d96 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -142,6 +142,7 @@ static struct target_type linear_target = {
.status = linear_status,
.ioctl = linear_ioctl,
.merge = linear_merge,
+ .features = DM_TARGET_SUPPORTS_BARRIERS,
};
int __init dm_linear_init(void)
@@ -156,8 +157,5 @@ int __init dm_linear_init(void)
void dm_linear_exit(void)
{
- int r = dm_unregister_target(&linear_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
+ dm_unregister_target(&linear_target);
}
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index a8c0fc79ca78..737961f275c1 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -326,8 +326,6 @@ static void header_from_disk(struct log_header *core, struct log_header *disk)
static int rw_header(struct log_c *lc, int rw)
{
lc->io_req.bi_rw = rw;
- lc->io_req.mem.ptr.vma = lc->disk_header;
- lc->io_req.notify.fn = NULL;
return dm_io(&lc->io_req, 1, &lc->header_location, NULL);
}
@@ -362,10 +360,15 @@ static int read_header(struct log_c *log)
return 0;
}
-static inline int write_header(struct log_c *log)
+static int _check_region_size(struct dm_target *ti, uint32_t region_size)
{
- header_to_disk(&log->header, log->disk_header);
- return rw_header(log, WRITE);
+ if (region_size < 2 || region_size > ti->len)
+ return 0;
+
+ if (!is_power_of_2(region_size))
+ return 0;
+
+ return 1;
}
/*----------------------------------------------------------------
@@ -403,8 +406,9 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
}
}
- if (sscanf(argv[0], "%u", &region_size) != 1) {
- DMWARN("invalid region size string");
+ if (sscanf(argv[0], "%u", &region_size) != 1 ||
+ !_check_region_size(ti, region_size)) {
+ DMWARN("invalid region size %s", argv[0]);
return -EINVAL;
}
@@ -453,8 +457,18 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
*/
buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) +
bitset_size, ti->limits.hardsect_size);
+
+ if (buf_size > dev->bdev->bd_inode->i_size) {
+ DMWARN("log device %s too small: need %llu bytes",
+ dev->name, (unsigned long long)buf_size);
+ kfree(lc);
+ return -EINVAL;
+ }
+
lc->header_location.count = buf_size >> SECTOR_SHIFT;
+
lc->io_req.mem.type = DM_IO_VMA;
+ lc->io_req.notify.fn = NULL;
lc->io_req.client = dm_io_client_create(dm_div_up(buf_size,
PAGE_SIZE));
if (IS_ERR(lc->io_req.client)) {
@@ -467,10 +481,12 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
lc->disk_header = vmalloc(buf_size);
if (!lc->disk_header) {
DMWARN("couldn't allocate disk log buffer");
+ dm_io_client_destroy(lc->io_req.client);
kfree(lc);
return -ENOMEM;
}
+ lc->io_req.mem.ptr.vma = lc->disk_header;
lc->clean_bits = (void *)lc->disk_header +
(LOG_OFFSET << SECTOR_SHIFT);
}
@@ -482,6 +498,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
DMWARN("couldn't allocate sync bitset");
if (!dev)
vfree(lc->clean_bits);
+ else
+ dm_io_client_destroy(lc->io_req.client);
vfree(lc->disk_header);
kfree(lc);
return -ENOMEM;
@@ -495,6 +513,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
vfree(lc->sync_bits);
if (!dev)
vfree(lc->clean_bits);
+ else
+ dm_io_client_destroy(lc->io_req.client);
vfree(lc->disk_header);
kfree(lc);
return -ENOMEM;
@@ -631,8 +651,10 @@ static int disk_resume(struct dm_dirty_log *log)
/* set the correct number of regions in the header */
lc->header.nr_regions = lc->region_count;
+ header_to_disk(&lc->header, lc->disk_header);
+
/* write the new header */
- r = write_header(lc);
+ r = rw_header(lc, WRITE);
if (r) {
DMWARN("%s: Failed to write header on dirty region log device",
lc->log_dev->name);
@@ -682,7 +704,7 @@ static int disk_flush(struct dm_dirty_log *log)
if (!lc->touched)
return 0;
- r = write_header(lc);
+ r = rw_header(lc, WRITE);
if (r)
fail_log_device(lc);
else
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 3d7f4923cd13..095f77bf9681 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -889,7 +889,7 @@ static int fail_path(struct pgpath *pgpath)
dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
pgpath->path.dev->name, m->nr_valid_paths);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
queue_work(kmultipathd, &pgpath->deactivate_path);
out:
@@ -932,7 +932,7 @@ static int reinstate_path(struct pgpath *pgpath)
dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,
pgpath->path.dev->name, m->nr_valid_paths);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
out:
spin_unlock_irqrestore(&m->lock, flags);
@@ -976,7 +976,7 @@ static void bypass_pg(struct multipath *m, struct priority_group *pg,
spin_unlock_irqrestore(&m->lock, flags);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
}
/*
@@ -1006,7 +1006,7 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
}
spin_unlock_irqrestore(&m->lock, flags);
- queue_work(kmultipathd, &m->trigger_event);
+ schedule_work(&m->trigger_event);
return 0;
}
@@ -1495,14 +1495,10 @@ static int __init dm_multipath_init(void)
static void __exit dm_multipath_exit(void)
{
- int r;
-
destroy_workqueue(kmpath_handlerd);
destroy_workqueue(kmultipathd);
- r = dm_unregister_target(&multipath_target);
- if (r < 0)
- DMERR("target unregister failed %d", r);
+ dm_unregister_target(&multipath_target);
kmem_cache_destroy(_mpio_cache);
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index ec43f9fa4b2a..4d6bc101962e 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -197,9 +197,6 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
struct mirror_set *ms = m->ms;
struct mirror *new;
- if (!errors_handled(ms))
- return;
-
/*
* error_count is used for nothing more than a
* simple way to tell if a device has encountered
@@ -210,6 +207,9 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
if (test_and_set_bit(error_type, &m->error_type))
return;
+ if (!errors_handled(ms))
+ return;
+
if (m != get_default_mirror(ms))
goto out;
@@ -808,12 +808,6 @@ static void free_context(struct mirror_set *ms, struct dm_target *ti,
kfree(ms);
}
-static inline int _check_region_size(struct dm_target *ti, uint32_t size)
-{
- return !(size % (PAGE_SIZE >> 9) || !is_power_of_2(size) ||
- size > ti->len);
-}
-
static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
unsigned int mirror, char **argv)
{
@@ -872,12 +866,6 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
return NULL;
}
- if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
- ti->error = "Invalid region size";
- dm_dirty_log_destroy(dl);
- return NULL;
- }
-
return dl;
}
@@ -1300,11 +1288,7 @@ static int __init dm_mirror_init(void)
static void __exit dm_mirror_exit(void)
{
- int r;
-
- r = dm_unregister_target(&mirror_target);
- if (r < 0)
- DMERR("unregister failed %d", r);
+ dm_unregister_target(&mirror_target);
}
/* Module hooks */
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
new file mode 100644
index 000000000000..936b34e0959f
--- /dev/null
+++ b/drivers/md/dm-snap-persistent.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2006-2008 Red Hat GmbH
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-exception-store.h"
+#include "dm-snap.h"
+
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/dm-io.h>
+
+#define DM_MSG_PREFIX "persistent snapshot"
+#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */
+
+/*-----------------------------------------------------------------
+ * Persistent snapshots, by persistent we mean that the snapshot
+ * will survive a reboot.
+ *---------------------------------------------------------------*/
+
+/*
+ * We need to store a record of which parts of the origin have
+ * been copied to the snapshot device. The snapshot code
+ * requires that we copy exception chunks to chunk aligned areas
+ * of the COW store. It makes sense therefore, to store the
+ * metadata in chunk size blocks.
+ *
+ * There is no backward or forward compatibility implemented,
+ * snapshots with different disk versions than the kernel will
+ * not be usable. It is expected that "lvcreate" will blank out
+ * the start of a fresh COW device before calling the snapshot
+ * constructor.
+ *
+ * The first chunk of the COW device just contains the header.
+ * After this there is a chunk filled with exception metadata,
+ * followed by as many exception chunks as can fit in the
+ * metadata areas.
+ *
+ * All on disk structures are in little-endian format. The end
+ * of the exceptions info is indicated by an exception with a
+ * new_chunk of 0, which is invalid since it would point to the
+ * header chunk.
+ */
+
+/*
+ * Magic for persistent snapshots: "SnAp" - Feeble isn't it.
+ */
+#define SNAP_MAGIC 0x70416e53
+
+/*
+ * The on-disk version of the metadata.
+ */
+#define SNAPSHOT_DISK_VERSION 1
+
+struct disk_header {
+ uint32_t magic;
+
+ /*
+ * Is this snapshot valid. There is no way of recovering
+ * an invalid snapshot.
+ */
+ uint32_t valid;
+
+ /*
+ * Simple, incrementing version. no backward
+ * compatibility.
+ */
+ uint32_t version;
+
+ /* In sectors */
+ uint32_t chunk_size;
+};
+
+struct disk_exception {
+ uint64_t old_chunk;
+ uint64_t new_chunk;
+};
+
+struct commit_callback {
+ void (*callback)(void *, int success);
+ void *context;
+};
+
+/*
+ * The top level structure for a persistent exception store.
+ */
+struct pstore {
+ struct dm_snapshot *snap; /* up pointer to my snapshot */
+ int version;
+ int valid;
+ uint32_t exceptions_per_area;
+
+ /*
+ * Now that we have an asynchronous kcopyd there is no
+ * need for large chunk sizes, so it wont hurt to have a
+ * whole chunks worth of metadata in memory at once.
+ */
+ void *area;
+
+ /*
+ * An area of zeros used to clear the next area.
+ */
+ void *zero_area;
+
+ /*
+ * Used to keep track of which metadata area the data in
+ * 'chunk' refers to.
+ */
+ chunk_t current_area;
+
+ /*
+ * The next free chunk for an exception.
+ */
+ chunk_t next_free;
+
+ /*
+ * The index of next free exception in the current
+ * metadata area.
+ */
+ uint32_t current_committed;
+
+ atomic_t pending_count;
+ uint32_t callback_count;
+ struct commit_callback *callbacks;
+ struct dm_io_client *io_client;
+
+ struct workqueue_struct *metadata_wq;
+};
+
+static unsigned sectors_to_pages(unsigned sectors)
+{
+ return DIV_ROUND_UP(sectors, PAGE_SIZE >> 9);
+}
+
+static int alloc_area(struct pstore *ps)
+{
+ int r = -ENOMEM;
+ size_t len;
+
+ len = ps->snap->chunk_size << SECTOR_SHIFT;
+
+ /*
+ * Allocate the chunk_size block of memory that will hold
+ * a single metadata area.
+ */
+ ps->area = vmalloc(len);
+ if (!ps->area)
+ return r;
+
+ ps->zero_area = vmalloc(len);
+ if (!ps->zero_area) {
+ vfree(ps->area);
+ return r;
+ }
+ memset(ps->zero_area, 0, len);
+
+ return 0;
+}
+
+static void free_area(struct pstore *ps)
+{
+ vfree(ps->area);
+ ps->area = NULL;
+ vfree(ps->zero_area);
+ ps->zero_area = NULL;
+}
+
+struct mdata_req {
+ struct dm_io_region *where;
+ struct dm_io_request *io_req;
+ struct work_struct work;
+ int result;
+};
+
+static void do_metadata(struct work_struct *work)
+{
+ struct mdata_req *req = container_of(work, struct mdata_req, work);
+
+ req->result = dm_io(req->io_req, 1, req->where, NULL);
+}
+
+/*
+ * Read or write a chunk aligned and sized block of data from a device.
+ */
+static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
+{
+ struct dm_io_region where = {
+ .bdev = ps->snap->cow->bdev,
+ .sector = ps->snap->chunk_size * chunk,
+ .count = ps->snap->chunk_size,
+ };
+ struct dm_io_request io_req = {
+ .bi_rw = rw,
+ .mem.type = DM_IO_VMA,
+ .mem.ptr.vma = ps->area,
+ .client = ps->io_client,
+ .notify.fn = NULL,
+ };
+ struct mdata_req req;
+
+ if (!metadata)
+ return dm_io(&io_req, 1, &where, NULL);
+
+ req.where = &where;
+ req.io_req = &io_req;
+
+ /*
+ * Issue the synchronous I/O from a different thread
+ * to avoid generic_make_request recursion.
+ */
+ INIT_WORK(&req.work, do_metadata);
+ queue_work(ps->metadata_wq, &req.work);
+ flush_workqueue(ps->metadata_wq);
+
+ return req.result;
+}
+
+/*
+ * Convert a metadata area index to a chunk index.
+ */
+static chunk_t area_location(struct pstore *ps, chunk_t area)
+{
+ return 1 + ((ps->exceptions_per_area + 1) * area);
+}
+
+/*
+ * Read or write a metadata area. Remembering to skip the first
+ * chunk which holds the header.
+ */
+static int area_io(struct pstore *ps, int rw)
+{
+ int r;
+ chunk_t chunk;
+
+ chunk = area_location(ps, ps->current_area);
+
+ r = chunk_io(ps, chunk, rw, 0);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static void zero_memory_area(struct pstore *ps)
+{
+ memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
+}
+
+static int zero_disk_area(struct pstore *ps, chunk_t area)
+{
+ struct dm_io_region where = {
+ .bdev = ps->snap->cow->bdev,
+ .sector = ps->snap->chunk_size * area_location(ps, area),
+ .count = ps->snap->chunk_size,
+ };
+ struct dm_io_request io_req = {
+ .bi_rw = WRITE,
+ .mem.type = DM_IO_VMA,
+ .mem.ptr.vma = ps->zero_area,
+ .client = ps->io_client,
+ .notify.fn = NULL,
+ };
+
+ return dm_io(&io_req, 1, &where, NULL);
+}
+
+static int read_header(struct pstore *ps, int *new_snapshot)
+{
+ int r;
+ struct disk_header *dh;
+ chunk_t chunk_size;
+ int chunk_size_supplied = 1;
+
+ /*
+ * Use default chunk size (or hardsect_size, if larger) if none supplied
+ */
+ if (!ps->snap->chunk_size) {
+ ps->snap->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
+ bdev_hardsect_size(ps->snap->cow->bdev) >> 9);
+ ps->snap->chunk_mask = ps->snap->chunk_size - 1;
+ ps->snap->chunk_shift = ffs(ps->snap->chunk_size) - 1;
+ chunk_size_supplied = 0;
+ }
+
+ ps->io_client = dm_io_client_create(sectors_to_pages(ps->snap->
+ chunk_size));
+ if (IS_ERR(ps->io_client))
+ return PTR_ERR(ps->io_client);
+
+ r = alloc_area(ps);
+ if (r)
+ return r;
+
+ r = chunk_io(ps, 0, READ, 1);
+ if (r)
+ goto bad;
+
+ dh = (struct disk_header *) ps->area;
+
+ if (le32_to_cpu(dh->magic) == 0) {
+ *new_snapshot = 1;
+ return 0;
+ }
+
+ if (le32_to_cpu(dh->magic) != SNAP_MAGIC) {
+ DMWARN("Invalid or corrupt snapshot");
+ r = -ENXIO;
+ goto bad;
+ }
+
+ *new_snapshot = 0;
+ ps->valid = le32_to_cpu(dh->valid);
+ ps->version = le32_to_cpu(dh->version);
+ chunk_size = le32_to_cpu(dh->chunk_size);
+
+ if (!chunk_size_supplied || ps->snap->chunk_size == chunk_size)
+ return 0;
+
+ DMWARN("chunk size %llu in device metadata overrides "
+ "table chunk size of %llu.",
+ (unsigned long long)chunk_size,
+ (unsigned long long)ps->snap->chunk_size);
+
+ /* We had a bogus chunk_size. Fix stuff up. */
+ free_area(ps);
+
+ ps->snap->chunk_size = chunk_size;
+ ps->snap->chunk_mask = chunk_size - 1;
+ ps->snap->chunk_shift = ffs(chunk_size) - 1;
+
+ r = dm_io_client_resize(sectors_to_pages(ps->snap->chunk_size),
+ ps->io_client);
+ if (r)
+ return r;
+
+ r = alloc_area(ps);
+ return r;
+
+bad:
+ free_area(ps);
+ return r;
+}
+
+static int write_header(struct pstore *ps)
+{
+ struct disk_header *dh;
+
+ memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
+
+ dh = (struct disk_header *) ps->area;
+ dh->magic = cpu_to_le32(SNAP_MAGIC);
+ dh->valid = cpu_to_le32(ps->valid);
+ dh->version = cpu_to_le32(ps->version);
+ dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
+
+ return chunk_io(ps, 0, WRITE, 1);
+}
+
+/*
+ * Access functions for the disk exceptions, these do the endian conversions.
+ */
+static struct disk_exception *get_exception(struct pstore *ps, uint32_t index)
+{
+ BUG_ON(index >= ps->exceptions_per_area);
+
+ return ((struct disk_exception *) ps->area) + index;
+}
+
+static void read_exception(struct pstore *ps,
+ uint32_t index, struct disk_exception *result)
+{
+ struct disk_exception *e = get_exception(ps, index);
+
+ /* copy it */
+ result->old_chunk = le64_to_cpu(e->old_chunk);
+ result->new_chunk = le64_to_cpu(e->new_chunk);
+}
+
+static void write_exception(struct pstore *ps,
+ uint32_t index, struct disk_exception *de)
+{
+ struct disk_exception *e = get_exception(ps, index);
+
+ /* copy it */
+ e->old_chunk = cpu_to_le64(de->old_chunk);
+ e->new_chunk = cpu_to_le64(de->new_chunk);
+}
+
+/*
+ * Registers the exceptions that are present in the current area.
+ * 'full' is filled in to indicate if the area has been
+ * filled.
+ */
+static int insert_exceptions(struct pstore *ps,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context,
+ int *full)
+{
+ int r;
+ unsigned int i;
+ struct disk_exception de;
+
+ /* presume the area is full */
+ *full = 1;
+
+ for (i = 0; i < ps->exceptions_per_area; i++) {
+ read_exception(ps, i, &de);
+
+ /*
+ * If the new_chunk is pointing at the start of
+ * the COW device, where the first metadata area
+ * is we know that we've hit the end of the
+ * exceptions. Therefore the area is not full.
+ */
+ if (de.new_chunk == 0LL) {
+ ps->current_committed = i;
+ *full = 0;
+ break;
+ }
+
+ /*
+ * Keep track of the start of the free chunks.
+ */
+ if (ps->next_free <= de.new_chunk)
+ ps->next_free = de.new_chunk + 1;
+
+ /*
+ * Otherwise we add the exception to the snapshot.
+ */
+ r = callback(callback_context, de.old_chunk, de.new_chunk);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int read_exceptions(struct pstore *ps,
+ int (*callback)(void *callback_context, chunk_t old,
+ chunk_t new),
+ void *callback_context)
+{
+ int r, full = 1;
+
+ /*
+ * Keeping reading chunks and inserting exceptions until
+ * we find a partially full area.
+ */
+ for (ps->current_area = 0; full; ps->current_area++) {
+ r = area_io(ps, READ);
+ if (r)
+ return r;
+
+ r = insert_exceptions(ps, callback, callback_context, &full);
+ if (r)
+ return r;
+ }
+
+ ps->current_area--;
+
+ return 0;
+}
+
+static struct pstore *get_info(struct dm_exception_store *store)
+{
+ return (struct pstore *) store->context;
+}
+
+static void persistent_fraction_full(struct dm_exception_store *store,
+ sector_t *numerator, sector_t *denominator)
+{
+ *numerator = get_info(store)->next_free * store->snap->chunk_size;
+ *denominator = get_dev_size(store->snap->cow->bdev);
+}
+
+static void persistent_destroy(struct dm_exception_store *store)
+{
+ struct pstore *ps = get_info(store);
+
+ destroy_workqueue(ps->metadata_wq);
+ dm_io_client_destroy(ps->io_client);
+ vfree(ps->callbacks);
+ free_area(ps);
+ kfree(ps);
+}
+
+static int persistent_read_metadata(struct dm_exception_store *store,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context)
+{
+ int r, uninitialized_var(new_snapshot);
+ struct pstore *ps = get_info(store);
+
+ /*
+ * Read the snapshot header.
+ */
+ r = read_header(ps, &new_snapshot);
+ if (r)
+ return r;
+
+ /*
+ * Now we know correct chunk_size, complete the initialisation.
+ */
+ ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
+ sizeof(struct disk_exception);
+ ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
+ sizeof(*ps->callbacks));
+ if (!ps->callbacks)
+ return -ENOMEM;
+
+ /*
+ * Do we need to setup a new snapshot ?
+ */
+ if (new_snapshot) {
+ r = write_header(ps);
+ if (r) {
+ DMWARN("write_header failed");
+ return r;
+ }
+
+ ps->current_area = 0;
+ zero_memory_area(ps);
+ r = zero_disk_area(ps, 0);
+ if (r) {
+ DMWARN("zero_disk_area(0) failed");
+ return r;
+ }
+ } else {
+ /*
+ * Sanity checks.
+ */
+ if (ps->version != SNAPSHOT_DISK_VERSION) {
+ DMWARN("unable to handle snapshot disk version %d",
+ ps->version);
+ return -EINVAL;
+ }
+
+ /*
+ * Metadata are valid, but snapshot is invalidated
+ */
+ if (!ps->valid)
+ return 1;
+
+ /*
+ * Read the metadata.
+ */
+ r = read_exceptions(ps, callback, callback_context);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+static int persistent_prepare_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e)
+{
+ struct pstore *ps = get_info(store);
+ uint32_t stride;
+ chunk_t next_free;
+ sector_t size = get_dev_size(store->snap->cow->bdev);
+
+ /* Is there enough room ? */
+ if (size < ((ps->next_free + 1) * store->snap->chunk_size))
+ return -ENOSPC;
+
+ e->new_chunk = ps->next_free;
+
+ /*
+ * Move onto the next free pending, making sure to take
+ * into account the location of the metadata chunks.
+ */
+ stride = (ps->exceptions_per_area + 1);
+ next_free = ++ps->next_free;
+ if (sector_div(next_free, stride) == 1)
+ ps->next_free++;
+
+ atomic_inc(&ps->pending_count);
+ return 0;
+}
+
+static void persistent_commit_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e,
+ void (*callback) (void *, int success),
+ void *callback_context)
+{
+ unsigned int i;
+ struct pstore *ps = get_info(store);
+ struct disk_exception de;
+ struct commit_callback *cb;
+
+ de.old_chunk = e->old_chunk;
+ de.new_chunk = e->new_chunk;
+ write_exception(ps, ps->current_committed++, &de);
+
+ /*
+ * Add the callback to the back of the array. This code
+ * is the only place where the callback array is
+ * manipulated, and we know that it will never be called
+ * multiple times concurrently.
+ */
+ cb = ps->callbacks + ps->callback_count++;
+ cb->callback = callback;
+ cb->context = callback_context;
+
+ /*
+ * If there are exceptions in flight and we have not yet
+ * filled this metadata area there's nothing more to do.
+ */
+ if (!atomic_dec_and_test(&ps->pending_count) &&
+ (ps->current_committed != ps->exceptions_per_area))
+ return;
+
+ /*
+ * If we completely filled the current area, then wipe the next one.
+ */
+ if ((ps->current_committed == ps->exceptions_per_area) &&
+ zero_disk_area(ps, ps->current_area + 1))
+ ps->valid = 0;
+
+ /*
+ * Commit exceptions to disk.
+ */
+ if (ps->valid && area_io(ps, WRITE))
+ ps->valid = 0;
+
+ /*
+ * Advance to the next area if this one is full.
+ */
+ if (ps->current_committed == ps->exceptions_per_area) {
+ ps->current_committed = 0;
+ ps->current_area++;
+ zero_memory_area(ps);
+ }
+
+ for (i = 0; i < ps->callback_count; i++) {
+ cb = ps->callbacks + i;
+ cb->callback(cb->context, ps->valid);
+ }
+
+ ps->callback_count = 0;
+}
+
+static void persistent_drop_snapshot(struct dm_exception_store *store)
+{
+ struct pstore *ps = get_info(store);
+
+ ps->valid = 0;
+ if (write_header(ps))
+ DMWARN("write header failed");
+}
+
+int dm_create_persistent(struct dm_exception_store *store)
+{
+ struct pstore *ps;
+
+ /* allocate the pstore */
+ ps = kmalloc(sizeof(*ps), GFP_KERNEL);
+ if (!ps)
+ return -ENOMEM;
+
+ ps->snap = store->snap;
+ ps->valid = 1;
+ ps->version = SNAPSHOT_DISK_VERSION;
+ ps->area = NULL;
+ ps->next_free = 2; /* skipping the header and first area */
+ ps->current_committed = 0;
+
+ ps->callback_count = 0;
+ atomic_set(&ps->pending_count, 0);
+ ps->callbacks = NULL;
+
+ ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
+ if (!ps->metadata_wq) {
+ kfree(ps);
+ DMERR("couldn't start header metadata update thread");
+ return -ENOMEM;
+ }
+
+ store->destroy = persistent_destroy;
+ store->read_metadata = persistent_read_metadata;
+ store->prepare_exception = persistent_prepare_exception;
+ store->commit_exception = persistent_commit_exception;
+ store->drop_snapshot = persistent_drop_snapshot;
+ store->fraction_full = persistent_fraction_full;
+ store->context = ps;
+
+ return 0;
+}
+
+int dm_persistent_snapshot_init(void)
+{
+ return 0;
+}
+
+void dm_persistent_snapshot_exit(void)
+{
+}
diff --git a/drivers/md/dm-snap-transient.c b/drivers/md/dm-snap-transient.c
new file mode 100644
index 000000000000..7f6e2e6dcb0d
--- /dev/null
+++ b/drivers/md/dm-snap-transient.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
+ * Copyright (C) 2006-2008 Red Hat GmbH
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm-exception-store.h"
+#include "dm-snap.h"
+
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/dm-io.h>
+
+#define DM_MSG_PREFIX "transient snapshot"
+
+/*-----------------------------------------------------------------
+ * Implementation of the store for non-persistent snapshots.
+ *---------------------------------------------------------------*/
+struct transient_c {
+ sector_t next_free;
+};
+
+static void transient_destroy(struct dm_exception_store *store)
+{
+ kfree(store->context);
+}
+
+static int transient_read_metadata(struct dm_exception_store *store,
+ int (*callback)(void *callback_context,
+ chunk_t old, chunk_t new),
+ void *callback_context)
+{
+ return 0;
+}
+
+static int transient_prepare_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e)
+{
+ struct transient_c *tc = (struct transient_c *) store->context;
+ sector_t size = get_dev_size(store->snap->cow->bdev);
+
+ if (size < (tc->next_free + store->snap->chunk_size))
+ return -1;
+
+ e->new_chunk = sector_to_chunk(store->snap, tc->next_free);
+ tc->next_free += store->snap->chunk_size;
+
+ return 0;
+}
+
+static void transient_commit_exception(struct dm_exception_store *store,
+ struct dm_snap_exception *e,
+ void (*callback) (void *, int success),
+ void *callback_context)
+{
+ /* Just succeed */
+ callback(callback_context, 1);
+}
+
+static void transient_fraction_full(struct dm_exception_store *store,
+ sector_t *numerator, sector_t *denominator)
+{
+ *numerator = ((struct transient_c *) store->context)->next_free;
+ *denominator = get_dev_size(store->snap->cow->bdev);
+}
+
+int dm_create_transient(struct dm_exception_store *store)
+{
+ struct transient_c *tc;
+
+ store->destroy = transient_destroy;
+ store->read_metadata = transient_read_metadata;
+ store->prepare_exception = transient_prepare_exception;
+ store->commit_exception = transient_commit_exception;
+ store->drop_snapshot = NULL;
+ store->fraction_full = transient_fraction_full;
+
+ tc = kmalloc(sizeof(struct transient_c), GFP_KERNEL);
+ if (!tc)
+ return -ENOMEM;
+
+ tc->next_free = 0;
+ store->context = tc;
+
+ return 0;
+}
+
+int dm_transient_snapshot_init(void)
+{
+ return 0;
+}
+
+void dm_transient_snapshot_exit(void)
+{
+}
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 6c96db26b87c..65ff82ff124e 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -9,6 +9,7 @@
#include <linux/blkdev.h>
#include <linux/ctype.h>
#include <linux/device-mapper.h>
+#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
@@ -20,6 +21,7 @@
#include <linux/log2.h>
#include <linux/dm-kcopyd.h>
+#include "dm-exception-store.h"
#include "dm-snap.h"
#include "dm-bio-list.h"
@@ -428,8 +430,13 @@ out:
list_add(&new_e->hash_list, e ? &e->hash_list : l);
}
-int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new)
+/*
+ * Callback used by the exception stores to load exceptions when
+ * initialising.
+ */
+static int dm_add_exception(void *context, chunk_t old, chunk_t new)
{
+ struct dm_snapshot *s = context;
struct dm_snap_exception *e;
e = alloc_exception();
@@ -658,7 +665,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
spin_lock_init(&s->tracked_chunk_lock);
/* Metadata must only be loaded into one table at once */
- r = s->store.read_metadata(&s->store);
+ r = s->store.read_metadata(&s->store, dm_add_exception, (void *)s);
if (r < 0) {
ti->error = "Failed to read snapshot metadata";
goto bad_load_and_register;
@@ -735,7 +742,7 @@ static void snapshot_dtr(struct dm_target *ti)
unregister_snapshot(s);
while (atomic_read(&s->pending_exceptions_count))
- yield();
+ msleep(1);
/*
* Ensure instructions in mempool_destroy aren't reordered
* before atomic_read.
@@ -888,10 +895,10 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
/*
* Check for conflicting reads. This is extremely improbable,
- * so yield() is sufficient and there is no need for a wait queue.
+ * so msleep(1) is sufficient and there is no need for a wait queue.
*/
while (__chunk_is_tracked(s, pe->e.old_chunk))
- yield();
+ msleep(1);
/*
* Add a proper exception, and remove the
@@ -1404,6 +1411,12 @@ static int __init dm_snapshot_init(void)
{
int r;
+ r = dm_exception_store_init();
+ if (r) {
+ DMERR("Failed to initialize exception stores");
+ return r;
+ }
+
r = dm_register_target(&snapshot_target);
if (r) {
DMERR("snapshot target register failed %d", r);
@@ -1452,39 +1465,34 @@ static int __init dm_snapshot_init(void)
return 0;
- bad_pending_pool:
+bad_pending_pool:
kmem_cache_destroy(tracked_chunk_cache);
- bad5:
+bad5:
kmem_cache_destroy(pending_cache);
- bad4:
+bad4:
kmem_cache_destroy(exception_cache);
- bad3:
+bad3:
exit_origin_hash();
- bad2:
+bad2:
dm_unregister_target(&origin_target);
- bad1:
+bad1:
dm_unregister_target(&snapshot_target);
return r;
}
static void __exit dm_snapshot_exit(void)
{
- int r;
-
destroy_workqueue(ksnapd);
- r = dm_unregister_target(&snapshot_target);
- if (r)
- DMERR("snapshot unregister failed %d", r);
-
- r = dm_unregister_target(&origin_target);
- if (r)
- DMERR("origin unregister failed %d", r);
+ dm_unregister_target(&snapshot_target);
+ dm_unregister_target(&origin_target);
exit_origin_hash();
kmem_cache_destroy(pending_cache);
kmem_cache_destroy(exception_cache);
kmem_cache_destroy(tracked_chunk_cache);
+
+ dm_exception_store_exit();
}
/* Module hooks */
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 99c0106ede2d..d9e62b43cf85 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -1,6 +1,4 @@
/*
- * dm-snapshot.c
- *
* Copyright (C) 2001-2002 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
@@ -10,6 +8,7 @@
#define DM_SNAPSHOT_H
#include <linux/device-mapper.h>
+#include "dm-exception-store.h"
#include "dm-bio-list.h"
#include <linux/blkdev.h>
#include <linux/workqueue.h>
@@ -20,116 +19,6 @@ struct exception_table {
struct list_head *table;
};
-/*
- * The snapshot code deals with largish chunks of the disk at a
- * time. Typically 32k - 512k.
- */
-typedef sector_t chunk_t;
-
-/*
- * An exception is used where an old chunk of data has been
- * replaced by a new one.
- * If chunk_t is 64 bits in size, the top 8 bits of new_chunk hold the number
- * of chunks that follow contiguously. Remaining bits hold the number of the
- * chunk within the device.
- */
-struct dm_snap_exception {
- struct list_head hash_list;
-
- chunk_t old_chunk;
- chunk_t new_chunk;
-};
-
-/*
- * Funtions to manipulate consecutive chunks
- */
-# if defined(CONFIG_LBD) || (BITS_PER_LONG == 64)
-# define DM_CHUNK_CONSECUTIVE_BITS 8
-# define DM_CHUNK_NUMBER_BITS 56
-
-static inline chunk_t dm_chunk_number(chunk_t chunk)
-{
- return chunk & (chunk_t)((1ULL << DM_CHUNK_NUMBER_BITS) - 1ULL);
-}
-
-static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
-{
- return e->new_chunk >> DM_CHUNK_NUMBER_BITS;
-}
-
-static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
-{
- e->new_chunk += (1ULL << DM_CHUNK_NUMBER_BITS);
-
- BUG_ON(!dm_consecutive_chunk_count(e));
-}
-
-# else
-# define DM_CHUNK_CONSECUTIVE_BITS 0
-
-static inline chunk_t dm_chunk_number(chunk_t chunk)
-{
- return chunk;
-}
-
-static inline unsigned dm_consecutive_chunk_count(struct dm_snap_exception *e)
-{
- return 0;
-}
-
-static inline void dm_consecutive_chunk_count_inc(struct dm_snap_exception *e)
-{
-}
-
-# endif
-
-/*
- * Abstraction to handle the meta/layout of exception stores (the
- * COW device).
- */
-struct exception_store {
-
- /*
- * Destroys this object when you've finished with it.
- */
- void (*destroy) (struct exception_store *store);
-
- /*
- * The target shouldn't read the COW device until this is
- * called.
- */
- int (*read_metadata) (struct exception_store *store);
-
- /*
- * Find somewhere to store the next exception.
- */
- int (*prepare_exception) (struct exception_store *store,
- struct dm_snap_exception *e);
-
- /*
- * Update the metadata with this exception.
- */
- void (*commit_exception) (struct exception_store *store,
- struct dm_snap_exception *e,
- void (*callback) (void *, int success),
- void *callback_context);
-
- /*
- * The snapshot is invalid, note this in the metadata.
- */
- void (*drop_snapshot) (struct exception_store *store);
-
- /*
- * Return how full the snapshot is.
- */
- void (*fraction_full) (struct exception_store *store,
- sector_t *numerator,
- sector_t *denominator);
-
- struct dm_snapshot *snap;
- void *context;
-};
-
#define DM_TRACKED_CHUNK_HASH_SIZE 16
#define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \
(DM_TRACKED_CHUNK_HASH_SIZE - 1))
@@ -172,7 +61,7 @@ struct dm_snapshot {
spinlock_t pe_lock;
/* The on disk metadata handler */
- struct exception_store store;
+ struct dm_exception_store store;
struct dm_kcopyd_client *kcopyd_client;
@@ -187,20 +76,6 @@ struct dm_snapshot {
};
/*
- * Used by the exception stores to load exceptions hen
- * initialising.
- */
-int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new);
-
-/*
- * Constructor and destructor for the default persistent
- * store.
- */
-int dm_create_persistent(struct exception_store *store);
-
-int dm_create_transient(struct exception_store *store);
-
-/*
* Return the number of sectors in the device.
*/
static inline sector_t get_dev_size(struct block_device *bdev)
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 9e4ef88d421e..41569bc60abc 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -337,9 +337,7 @@ int __init dm_stripe_init(void)
void dm_stripe_exit(void)
{
- if (dm_unregister_target(&stripe_target))
- DMWARN("target unregistration failed");
-
+ dm_unregister_target(&stripe_target);
destroy_workqueue(kstriped);
return;
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c
new file mode 100644
index 000000000000..a2a45e6c7c8b
--- /dev/null
+++ b/drivers/md/dm-sysfs.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/sysfs.h>
+#include <linux/dm-ioctl.h>
+#include "dm.h"
+
+struct dm_sysfs_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct mapped_device *, char *);
+ ssize_t (*store)(struct mapped_device *, char *);
+};
+
+#define DM_ATTR_RO(_name) \
+struct dm_sysfs_attr dm_attr_##_name = \
+ __ATTR(_name, S_IRUGO, dm_attr_##_name##_show, NULL)
+
+static ssize_t dm_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *page)
+{
+ struct dm_sysfs_attr *dm_attr;
+ struct mapped_device *md;
+ ssize_t ret;
+
+ dm_attr = container_of(attr, struct dm_sysfs_attr, attr);
+ if (!dm_attr->show)
+ return -EIO;
+
+ md = dm_get_from_kobject(kobj);
+ if (!md)
+ return -EINVAL;
+
+ ret = dm_attr->show(md, page);
+ dm_put(md);
+
+ return ret;
+}
+
+static ssize_t dm_attr_name_show(struct mapped_device *md, char *buf)
+{
+ if (dm_copy_name_and_uuid(md, buf, NULL))
+ return -EIO;
+
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
+static ssize_t dm_attr_uuid_show(struct mapped_device *md, char *buf)
+{
+ if (dm_copy_name_and_uuid(md, NULL, buf))
+ return -EIO;
+
+ strcat(buf, "\n");
+ return strlen(buf);
+}
+
+static DM_ATTR_RO(name);
+static DM_ATTR_RO(uuid);
+
+static struct attribute *dm_attrs[] = {
+ &dm_attr_name.attr,
+ &dm_attr_uuid.attr,
+ NULL,
+};
+
+static struct sysfs_ops dm_sysfs_ops = {
+ .show = dm_attr_show,
+};
+
+/*
+ * dm kobject is embedded in mapped_device structure
+ * no need to define release function here
+ */
+static struct kobj_type dm_ktype = {
+ .sysfs_ops = &dm_sysfs_ops,
+ .default_attrs = dm_attrs,
+};
+
+/*
+ * Initialize kobj
+ * because nobody using md yet, no need to call explicit dm_get/put
+ */
+int dm_sysfs_init(struct mapped_device *md)
+{
+ return kobject_init_and_add(dm_kobject(md), &dm_ktype,
+ &disk_to_dev(dm_disk(md))->kobj,
+ "%s", "dm");
+}
+
+/*
+ * Remove kobj, called after all references removed
+ */
+void dm_sysfs_exit(struct mapped_device *md)
+{
+ kobject_put(dm_kobject(md));
+}
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 04e5fd742c2c..2fd66c30f7f8 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*
* This file is released under the GPL.
*/
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
+#include <linux/delay.h>
#include <asm/atomic.h>
#define DM_MSG_PREFIX "table"
@@ -24,6 +25,19 @@
#define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t))
#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
+/*
+ * The table has always exactly one reference from either mapped_device->map
+ * or hash_cell->new_map. This reference is not counted in table->holders.
+ * A pair of dm_create_table/dm_destroy_table functions is used for table
+ * creation/destruction.
+ *
+ * Temporary references from the other code increase table->holders. A pair
+ * of dm_table_get/dm_table_put functions is used to manipulate it.
+ *
+ * When the table is about to be destroyed, we wait for table->holders to
+ * drop to zero.
+ */
+
struct dm_table {
struct mapped_device *md;
atomic_t holders;
@@ -38,6 +52,8 @@ struct dm_table {
sector_t *highs;
struct dm_target *targets;
+ unsigned barriers_supported:1;
+
/*
* Indicates the rw permissions for the new logical
* device. This should be a combination of FMODE_READ
@@ -226,7 +242,8 @@ int dm_table_create(struct dm_table **result, fmode_t mode,
return -ENOMEM;
INIT_LIST_HEAD(&t->devices);
- atomic_set(&t->holders, 1);
+ atomic_set(&t->holders, 0);
+ t->barriers_supported = 1;
if (!num_targets)
num_targets = KEYS_PER_NODE;
@@ -256,10 +273,14 @@ static void free_devices(struct list_head *devices)
}
}
-static void table_destroy(struct dm_table *t)
+void dm_table_destroy(struct dm_table *t)
{
unsigned int i;
+ while (atomic_read(&t->holders))
+ msleep(1);
+ smp_mb();
+
/* free the indexes (see dm_table_complete) */
if (t->depth >= 2)
vfree(t->index[t->depth - 2]);
@@ -297,8 +318,8 @@ void dm_table_put(struct dm_table *t)
if (!t)
return;
- if (atomic_dec_and_test(&t->holders))
- table_destroy(t);
+ smp_mb__before_atomic_dec();
+ atomic_dec(&t->holders);
}
/*
@@ -728,6 +749,10 @@ int dm_table_add_target(struct dm_table *t, const char *type,
/* FIXME: the plan is to combine high here and then have
* the merge fn apply the target level restrictions. */
combine_restrictions_low(&t->limits, &tgt->limits);
+
+ if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
+ t->barriers_supported = 0;
+
return 0;
bad:
@@ -772,6 +797,12 @@ int dm_table_complete(struct dm_table *t)
check_for_valid_limits(&t->limits);
+ /*
+ * We only support barriers if there is exactly one underlying device.
+ */
+ if (!list_is_singular(&t->devices))
+ t->barriers_supported = 0;
+
/* how many indexes will the btree have ? */
leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
@@ -986,6 +1017,12 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
return t->md;
}
+int dm_table_barrier_ok(struct dm_table *t)
+{
+ return t->barriers_supported;
+}
+EXPORT_SYMBOL(dm_table_barrier_ok);
+
EXPORT_SYMBOL(dm_vcalloc);
EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device);
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index 835cf95b857f..7decf10006e4 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -130,26 +130,26 @@ int dm_register_target(struct target_type *t)
return rv;
}
-int dm_unregister_target(struct target_type *t)
+void dm_unregister_target(struct target_type *t)
{
struct tt_internal *ti;
down_write(&_lock);
if (!(ti = __find_target_type(t->name))) {
- up_write(&_lock);
- return -EINVAL;
+ DMCRIT("Unregistering unrecognised target: %s", t->name);
+ BUG();
}
if (ti->use) {
- up_write(&_lock);
- return -ETXTBSY;
+ DMCRIT("Attempt to unregister target still in use: %s",
+ t->name);
+ BUG();
}
list_del(&ti->list);
kfree(ti);
up_write(&_lock);
- return 0;
}
/*
@@ -187,8 +187,7 @@ int __init dm_target_init(void)
void dm_target_exit(void)
{
- if (dm_unregister_target(&error_target))
- DMWARN("error target unregistration failed");
+ dm_unregister_target(&error_target);
}
EXPORT_SYMBOL(dm_register_target);
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index cdbf126ec106..bbc97030c0c2 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -69,10 +69,7 @@ static int __init dm_zero_init(void)
static void __exit dm_zero_exit(void)
{
- int r = dm_unregister_target(&zero_target);
-
- if (r < 0)
- DMERR("unregister failed %d", r);
+ dm_unregister_target(&zero_target);
}
module_init(dm_zero_init)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 421c9f02d8ca..51ba1db4b3e7 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
*
* This file is released under the GPL.
*/
@@ -32,6 +32,7 @@ static unsigned int _major = 0;
static DEFINE_SPINLOCK(_minor_lock);
/*
+ * For bio-based dm.
* One of these is allocated per bio.
*/
struct dm_io {
@@ -43,6 +44,7 @@ struct dm_io {
};
/*
+ * For bio-based dm.
* One of these is allocated per target within a bio. Hopefully
* this will be simplified out one day.
*/
@@ -54,6 +56,27 @@ struct dm_target_io {
DEFINE_TRACE(block_bio_complete);
+/*
+ * For request-based dm.
+ * One of these is allocated per request.
+ */
+struct dm_rq_target_io {
+ struct mapped_device *md;
+ struct dm_target *ti;
+ struct request *orig, clone;
+ int error;
+ union map_info info;
+};
+
+/*
+ * For request-based dm.
+ * One of these is allocated per bio.
+ */
+struct dm_rq_clone_bio_info {
+ struct bio *orig;
+ struct request *rq;
+};
+
union map_info *dm_get_mapinfo(struct bio *bio)
{
if (bio && bio->bi_private)
@@ -144,11 +167,16 @@ struct mapped_device {
/* forced geometry settings */
struct hd_geometry geometry;
+
+ /* sysfs handle */
+ struct kobject kobj;
};
#define MIN_IOS 256
static struct kmem_cache *_io_cache;
static struct kmem_cache *_tio_cache;
+static struct kmem_cache *_rq_tio_cache;
+static struct kmem_cache *_rq_bio_info_cache;
static int __init local_init(void)
{
@@ -164,9 +192,17 @@ static int __init local_init(void)
if (!_tio_cache)
goto out_free_io_cache;
+ _rq_tio_cache = KMEM_CACHE(dm_rq_target_io, 0);
+ if (!_rq_tio_cache)
+ goto out_free_tio_cache;
+
+ _rq_bio_info_cache = KMEM_CACHE(dm_rq_clone_bio_info, 0);
+ if (!_rq_bio_info_cache)
+ goto out_free_rq_tio_cache;
+
r = dm_uevent_init();
if (r)
- goto out_free_tio_cache;
+ goto out_free_rq_bio_info_cache;
_major = major;
r = register_blkdev(_major, _name);
@@ -180,6 +216,10 @@ static int __init local_init(void)
out_uevent_exit:
dm_uevent_exit();
+out_free_rq_bio_info_cache:
+ kmem_cache_destroy(_rq_bio_info_cache);
+out_free_rq_tio_cache:
+ kmem_cache_destroy(_rq_tio_cache);
out_free_tio_cache:
kmem_cache_destroy(_tio_cache);
out_free_io_cache:
@@ -190,6 +230,8 @@ out_free_io_cache:
static void local_exit(void)
{
+ kmem_cache_destroy(_rq_bio_info_cache);
+ kmem_cache_destroy(_rq_tio_cache);
kmem_cache_destroy(_tio_cache);
kmem_cache_destroy(_io_cache);
unregister_blkdev(_major, _name);
@@ -796,7 +838,11 @@ static int __split_bio(struct mapped_device *md, struct bio *bio)
ci.map = dm_get_table(md);
if (unlikely(!ci.map))
return -EIO;
-
+ if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
+ dm_table_put(ci.map);
+ bio_endio(bio, -EOPNOTSUPP);
+ return 0;
+ }
ci.md = md;
ci.bio = bio;
ci.io = alloc_io(md);
@@ -880,15 +926,6 @@ static int dm_request(struct request_queue *q, struct bio *bio)
struct mapped_device *md = q->queuedata;
int cpu;
- /*
- * There is no use in forwarding any barrier request since we can't
- * guarantee it is (or can be) handled by the targets correctly.
- */
- if (unlikely(bio_barrier(bio))) {
- bio_endio(bio, -EOPNOTSUPP);
- return 0;
- }
-
down_read(&md->io_lock);
cpu = part_stat_lock();
@@ -943,8 +980,6 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
struct mapped_device *md = congested_data;
struct dm_table *map;
- atomic_inc(&md->pending);
-
if (!test_bit(DMF_BLOCK_IO, &md->flags)) {
map = dm_get_table(md);
if (map) {
@@ -953,10 +988,6 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
}
}
- if (!atomic_dec_return(&md->pending))
- /* nudge anyone waiting on suspend queue */
- wake_up(&md->wait);
-
return r;
}
@@ -1216,10 +1247,12 @@ static int __bind(struct mapped_device *md, struct dm_table *t)
if (md->suspended_bdev)
__set_size(md, size);
- if (size == 0)
+
+ if (!size) {
+ dm_table_destroy(t);
return 0;
+ }
- dm_table_get(t);
dm_table_event_callback(t, event_callback, md);
write_lock(&md->map_lock);
@@ -1241,7 +1274,7 @@ static void __unbind(struct mapped_device *md)
write_lock(&md->map_lock);
md->map = NULL;
write_unlock(&md->map_lock);
- dm_table_put(map);
+ dm_table_destroy(map);
}
/*
@@ -1255,6 +1288,8 @@ int dm_create(int minor, struct mapped_device **result)
if (!md)
return -ENXIO;
+ dm_sysfs_init(md);
+
*result = md;
return 0;
}
@@ -1330,8 +1365,9 @@ void dm_put(struct mapped_device *md)
dm_table_presuspend_targets(map);
dm_table_postsuspend_targets(map);
}
- __unbind(md);
+ dm_sysfs_exit(md);
dm_table_put(map);
+ __unbind(md);
free_dev(md);
}
}
@@ -1669,6 +1705,27 @@ struct gendisk *dm_disk(struct mapped_device *md)
return md->disk;
}
+struct kobject *dm_kobject(struct mapped_device *md)
+{
+ return &md->kobj;
+}
+
+/*
+ * struct mapped_device should not be exported outside of dm.c
+ * so use this check to verify that kobj is part of md structure
+ */
+struct mapped_device *dm_get_from_kobject(struct kobject *kobj)
+{
+ struct mapped_device *md;
+
+ md = container_of(kobj, struct mapped_device, kobj);
+ if (&md->kobj != kobj)
+ return NULL;
+
+ dm_get(md);
+ return md;
+}
+
int dm_suspended(struct mapped_device *md)
{
return test_bit(DMF_SUSPENDED, &md->flags);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 0ade60cdef42..20194e000c5a 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -36,6 +36,7 @@ struct dm_table;
/*-----------------------------------------------------------------
* Internal table functions.
*---------------------------------------------------------------*/
+void dm_table_destroy(struct dm_table *t);
void dm_table_event_callback(struct dm_table *t,
void (*fn)(void *), void *context);
struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
@@ -51,6 +52,7 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits);
* To check the return value from dm_table_find_target().
*/
#define dm_target_is_valid(t) ((t)->table)
+int dm_table_barrier_ok(struct dm_table *t);
/*-----------------------------------------------------------------
* A registry of target types.
@@ -72,6 +74,14 @@ int dm_interface_init(void);
void dm_interface_exit(void);
/*
+ * sysfs interface
+ */
+int dm_sysfs_init(struct mapped_device *md);
+void dm_sysfs_exit(struct mapped_device *md);
+struct kobject *dm_kobject(struct mapped_device *md);
+struct mapped_device *dm_get_from_kobject(struct kobject *kobj);
+
+/*
* Targets for linear and striped mappings
*/
int dm_linear_init(void);
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index f26c1f9a475b..86d9adf90e79 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -283,7 +283,6 @@ static int reconfig(mddev_t *mddev, int layout, int chunk_size)
static int run(mddev_t *mddev)
{
mdk_rdev_t *rdev;
- struct list_head *tmp;
int i;
conf_t *conf = kmalloc(sizeof(*conf), GFP_KERNEL);
@@ -296,7 +295,7 @@ static int run(mddev_t *mddev)
}
conf->nfaults = 0;
- rdev_for_each(rdev, tmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
conf->rdev = rdev;
mddev->array_sectors = mddev->size * 2;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 3b90c5c924ec..1e3aea9eecf1 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -105,7 +105,6 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
int i, nb_zone, cnt;
sector_t min_sectors;
sector_t curr_sector;
- struct list_head *tmp;
conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
GFP_KERNEL);
@@ -115,7 +114,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
cnt = 0;
conf->array_sectors = 0;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
int j = rdev->raid_disk;
dev_info_t *disk = conf->disks + j;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1b1d32694f6f..41e2509bf896 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -214,20 +214,33 @@ static inline mddev_t *mddev_get(mddev_t *mddev)
return mddev;
}
+static void mddev_delayed_delete(struct work_struct *ws)
+{
+ mddev_t *mddev = container_of(ws, mddev_t, del_work);
+ kobject_del(&mddev->kobj);
+ kobject_put(&mddev->kobj);
+}
+
static void mddev_put(mddev_t *mddev)
{
if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock))
return;
- if (!mddev->raid_disks && list_empty(&mddev->disks)) {
+ if (!mddev->raid_disks && list_empty(&mddev->disks) &&
+ !mddev->hold_active) {
list_del(&mddev->all_mddevs);
- spin_unlock(&all_mddevs_lock);
- blk_cleanup_queue(mddev->queue);
- if (mddev->sysfs_state)
- sysfs_put(mddev->sysfs_state);
- mddev->sysfs_state = NULL;
- kobject_put(&mddev->kobj);
- } else
- spin_unlock(&all_mddevs_lock);
+ if (mddev->gendisk) {
+ /* we did a probe so need to clean up.
+ * Call schedule_work inside the spinlock
+ * so that flush_scheduled_work() after
+ * mddev_find will succeed in waiting for the
+ * work to be done.
+ */
+ INIT_WORK(&mddev->del_work, mddev_delayed_delete);
+ schedule_work(&mddev->del_work);
+ } else
+ kfree(mddev);
+ }
+ spin_unlock(&all_mddevs_lock);
}
static mddev_t * mddev_find(dev_t unit)
@@ -236,15 +249,50 @@ static mddev_t * mddev_find(dev_t unit)
retry:
spin_lock(&all_mddevs_lock);
- list_for_each_entry(mddev, &all_mddevs, all_mddevs)
- if (mddev->unit == unit) {
- mddev_get(mddev);
+
+ if (unit) {
+ list_for_each_entry(mddev, &all_mddevs, all_mddevs)
+ if (mddev->unit == unit) {
+ mddev_get(mddev);
+ spin_unlock(&all_mddevs_lock);
+ kfree(new);
+ return mddev;
+ }
+
+ if (new) {
+ list_add(&new->all_mddevs, &all_mddevs);
spin_unlock(&all_mddevs_lock);
- kfree(new);
- return mddev;
+ new->hold_active = UNTIL_IOCTL;
+ return new;
}
-
- if (new) {
+ } else if (new) {
+ /* find an unused unit number */
+ static int next_minor = 512;
+ int start = next_minor;
+ int is_free = 0;
+ int dev = 0;
+ while (!is_free) {
+ dev = MKDEV(MD_MAJOR, next_minor);
+ next_minor++;
+ if (next_minor > MINORMASK)
+ next_minor = 0;
+ if (next_minor == start) {
+ /* Oh dear, all in use. */
+ spin_unlock(&all_mddevs_lock);
+ kfree(new);
+ return NULL;
+ }
+
+ is_free = 1;
+ list_for_each_entry(mddev, &all_mddevs, all_mddevs)
+ if (mddev->unit == dev) {
+ is_free = 0;
+ break;
+ }
+ }
+ new->unit = dev;
+ new->md_minor = MINOR(dev);
+ new->hold_active = UNTIL_STOP;
list_add(&new->all_mddevs, &all_mddevs);
spin_unlock(&all_mddevs_lock);
return new;
@@ -275,16 +323,6 @@ static mddev_t * mddev_find(dev_t unit)
new->resync_max = MaxSector;
new->level = LEVEL_NONE;
- new->queue = blk_alloc_queue(GFP_KERNEL);
- if (!new->queue) {
- kfree(new);
- return NULL;
- }
- /* Can be unlocked because the queue is new: no concurrency */
- queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, new->queue);
-
- blk_queue_make_request(new->queue, md_fail_request);
-
goto retry;
}
@@ -307,25 +345,23 @@ static inline void mddev_unlock(mddev_t * mddev)
static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr)
{
- mdk_rdev_t * rdev;
- struct list_head *tmp;
+ mdk_rdev_t *rdev;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->desc_nr == nr)
return rdev;
- }
+
return NULL;
}
static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
{
- struct list_head *tmp;
mdk_rdev_t *rdev;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->bdev->bd_dev == dev)
return rdev;
- }
+
return NULL;
}
@@ -861,7 +897,6 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
{
mdp_super_t *sb;
- struct list_head *tmp;
mdk_rdev_t *rdev2;
int next_spare = mddev->raid_disks;
@@ -933,7 +968,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->state |= (1<<MD_SB_BITMAP_PRESENT);
sb->disks[0].state = (1<<MD_DISK_REMOVED);
- rdev_for_each(rdev2, tmp, mddev) {
+ list_for_each_entry(rdev2, &mddev->disks, same_set) {
mdp_disk_t *d;
int desc_nr;
if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags)
@@ -1259,7 +1294,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
{
struct mdp_superblock_1 *sb;
- struct list_head *tmp;
mdk_rdev_t *rdev2;
int max_dev, i;
/* make rdev->sb match mddev and rdev data. */
@@ -1307,7 +1341,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
}
max_dev = 0;
- rdev_for_each(rdev2, tmp, mddev)
+ list_for_each_entry(rdev2, &mddev->disks, same_set)
if (rdev2->desc_nr+1 > max_dev)
max_dev = rdev2->desc_nr+1;
@@ -1316,7 +1350,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
for (i=0; i<max_dev;i++)
sb->dev_roles[i] = cpu_to_le16(0xfffe);
- rdev_for_each(rdev2, tmp, mddev) {
+ list_for_each_entry(rdev2, &mddev->disks, same_set) {
i = rdev2->desc_nr;
if (test_bit(Faulty, &rdev2->flags))
sb->dev_roles[i] = cpu_to_le16(0xfffe);
@@ -1466,6 +1500,9 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
list_add_rcu(&rdev->same_set, &mddev->disks);
bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
+
+ /* May as well allow recovery to be retried once */
+ mddev->recovery_disabled = 0;
return 0;
fail:
@@ -1571,8 +1608,7 @@ static void kick_rdev_from_array(mdk_rdev_t * rdev)
static void export_array(mddev_t *mddev)
{
- struct list_head *tmp;
- mdk_rdev_t *rdev;
+ mdk_rdev_t *rdev, *tmp;
rdev_for_each(rdev, tmp, mddev) {
if (!rdev->mddev) {
@@ -1593,7 +1629,7 @@ static void print_desc(mdp_disk_t *desc)
desc->major,desc->minor,desc->raid_disk,desc->state);
}
-static void print_sb(mdp_super_t *sb)
+static void print_sb_90(mdp_super_t *sb)
{
int i;
@@ -1624,10 +1660,57 @@ static void print_sb(mdp_super_t *sb)
}
printk(KERN_INFO "md: THIS: ");
print_desc(&sb->this_disk);
-
}
-static void print_rdev(mdk_rdev_t *rdev)
+static void print_sb_1(struct mdp_superblock_1 *sb)
+{
+ __u8 *uuid;
+
+ uuid = sb->set_uuid;
+ printk(KERN_INFO "md: SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x"
+ ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n"
+ KERN_INFO "md: Name: \"%s\" CT:%llu\n",
+ le32_to_cpu(sb->major_version),
+ le32_to_cpu(sb->feature_map),
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15],
+ sb->set_name,
+ (unsigned long long)le64_to_cpu(sb->ctime)
+ & MD_SUPERBLOCK_1_TIME_SEC_MASK);
+
+ uuid = sb->device_uuid;
+ printk(KERN_INFO "md: L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu"
+ " RO:%llu\n"
+ KERN_INFO "md: Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+ ":%02x%02x%02x%02x%02x%02x\n"
+ KERN_INFO "md: (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n"
+ KERN_INFO "md: (MaxDev:%u) \n",
+ le32_to_cpu(sb->level),
+ (unsigned long long)le64_to_cpu(sb->size),
+ le32_to_cpu(sb->raid_disks),
+ le32_to_cpu(sb->layout),
+ le32_to_cpu(sb->chunksize),
+ (unsigned long long)le64_to_cpu(sb->data_offset),
+ (unsigned long long)le64_to_cpu(sb->data_size),
+ (unsigned long long)le64_to_cpu(sb->super_offset),
+ (unsigned long long)le64_to_cpu(sb->recovery_offset),
+ le32_to_cpu(sb->dev_number),
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15],
+ sb->devflags,
+ (unsigned long long)le64_to_cpu(sb->utime) & MD_SUPERBLOCK_1_TIME_SEC_MASK,
+ (unsigned long long)le64_to_cpu(sb->events),
+ (unsigned long long)le64_to_cpu(sb->resync_offset),
+ le32_to_cpu(sb->sb_csum),
+ le32_to_cpu(sb->max_dev)
+ );
+}
+
+static void print_rdev(mdk_rdev_t *rdev, int major_version)
{
char b[BDEVNAME_SIZE];
printk(KERN_INFO "md: rdev %s, SZ:%08llu F:%d S:%d DN:%u\n",
@@ -1635,15 +1718,22 @@ static void print_rdev(mdk_rdev_t *rdev)
test_bit(Faulty, &rdev->flags), test_bit(In_sync, &rdev->flags),
rdev->desc_nr);
if (rdev->sb_loaded) {
- printk(KERN_INFO "md: rdev superblock:\n");
- print_sb((mdp_super_t*)page_address(rdev->sb_page));
+ printk(KERN_INFO "md: rdev superblock (MJ:%d):\n", major_version);
+ switch (major_version) {
+ case 0:
+ print_sb_90((mdp_super_t*)page_address(rdev->sb_page));
+ break;
+ case 1:
+ print_sb_1((struct mdp_superblock_1 *)page_address(rdev->sb_page));
+ break;
+ }
} else
printk(KERN_INFO "md: no rdev superblock!\n");
}
static void md_print_devices(void)
{
- struct list_head *tmp, *tmp2;
+ struct list_head *tmp;
mdk_rdev_t *rdev;
mddev_t *mddev;
char b[BDEVNAME_SIZE];
@@ -1658,12 +1748,12 @@ static void md_print_devices(void)
bitmap_print_sb(mddev->bitmap);
else
printk("%s: ", mdname(mddev));
- rdev_for_each(rdev, tmp2, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
printk("<%s>", bdevname(rdev->bdev,b));
printk("\n");
- rdev_for_each(rdev, tmp2, mddev)
- print_rdev(rdev);
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ print_rdev(rdev, mddev->major_version);
}
printk("md: **********************************\n");
printk("\n");
@@ -1679,9 +1769,8 @@ static void sync_sbs(mddev_t * mddev, int nospares)
* with the rest of the array)
*/
mdk_rdev_t *rdev;
- struct list_head *tmp;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->sb_events == mddev->events ||
(nospares &&
rdev->raid_disk < 0 &&
@@ -1699,7 +1788,6 @@ static void sync_sbs(mddev_t * mddev, int nospares)
static void md_update_sb(mddev_t * mddev, int force_change)
{
- struct list_head *tmp;
mdk_rdev_t *rdev;
int sync_req;
int nospares = 0;
@@ -1790,7 +1878,7 @@ repeat:
mdname(mddev),mddev->in_sync);
bitmap_update_sb(mddev->bitmap);
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
char b[BDEVNAME_SIZE];
dprintk(KERN_INFO "md: ");
if (rdev->sb_loaded != 1)
@@ -1999,7 +2087,6 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
md_wakeup_thread(rdev->mddev->thread);
} else if (rdev->mddev->pers) {
mdk_rdev_t *rdev2;
- struct list_head *tmp;
/* Activating a spare .. or possibly reactivating
* if we every get bitmaps working here.
*/
@@ -2010,7 +2097,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
if (rdev->mddev->pers->hot_add_disk == NULL)
return -EINVAL;
- rdev_for_each(rdev2, tmp, rdev->mddev)
+ list_for_each_entry(rdev2, &rdev->mddev->disks, same_set)
if (rdev2->raid_disk == slot)
return -EEXIST;
@@ -2125,14 +2212,14 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
*/
mddev_t *mddev;
int overlap = 0;
- struct list_head *tmp, *tmp2;
+ struct list_head *tmp;
mddev_unlock(my_mddev);
for_each_mddev(mddev, tmp) {
mdk_rdev_t *rdev2;
mddev_lock(mddev);
- rdev_for_each(rdev2, tmp2, mddev)
+ list_for_each_entry(rdev2, &mddev->disks, same_set)
if (test_bit(AllReserved, &rdev2->flags) ||
(rdev->bdev == rdev2->bdev &&
rdev != rdev2 &&
@@ -2328,8 +2415,7 @@ abort_free:
static void analyze_sbs(mddev_t * mddev)
{
int i;
- struct list_head *tmp;
- mdk_rdev_t *rdev, *freshest;
+ mdk_rdev_t *rdev, *freshest, *tmp;
char b[BDEVNAME_SIZE];
freshest = NULL;
@@ -3046,7 +3132,7 @@ action_store(mddev_t *mddev, const char *page, size_t len)
}
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
- sysfs_notify(&mddev->kobj, NULL, "sync_action");
+ sysfs_notify_dirent(mddev->sysfs_action);
return len;
}
@@ -3404,6 +3490,8 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
rv = mddev_lock(mddev);
+ if (mddev->hold_active == UNTIL_IOCTL)
+ mddev->hold_active = 0;
if (!rv) {
rv = entry->store(mddev, page, length);
mddev_unlock(mddev);
@@ -3414,6 +3502,17 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
static void md_free(struct kobject *ko)
{
mddev_t *mddev = container_of(ko, mddev_t, kobj);
+
+ if (mddev->sysfs_state)
+ sysfs_put(mddev->sysfs_state);
+
+ if (mddev->gendisk) {
+ del_gendisk(mddev->gendisk);
+ put_disk(mddev->gendisk);
+ }
+ if (mddev->queue)
+ blk_cleanup_queue(mddev->queue);
+
kfree(mddev);
}
@@ -3429,34 +3528,74 @@ static struct kobj_type md_ktype = {
int mdp_major = 0;
-static struct kobject *md_probe(dev_t dev, int *part, void *data)
+static int md_alloc(dev_t dev, char *name)
{
static DEFINE_MUTEX(disks_mutex);
mddev_t *mddev = mddev_find(dev);
struct gendisk *disk;
- int partitioned = (MAJOR(dev) != MD_MAJOR);
- int shift = partitioned ? MdpMinorShift : 0;
- int unit = MINOR(dev) >> shift;
+ int partitioned;
+ int shift;
+ int unit;
int error;
if (!mddev)
- return NULL;
+ return -ENODEV;
+
+ partitioned = (MAJOR(mddev->unit) != MD_MAJOR);
+ shift = partitioned ? MdpMinorShift : 0;
+ unit = MINOR(mddev->unit) >> shift;
+
+ /* wait for any previous instance if this device
+ * to be completed removed (mddev_delayed_delete).
+ */
+ flush_scheduled_work();
mutex_lock(&disks_mutex);
if (mddev->gendisk) {
mutex_unlock(&disks_mutex);
mddev_put(mddev);
- return NULL;
+ return -EEXIST;
+ }
+
+ if (name) {
+ /* Need to ensure that 'name' is not a duplicate.
+ */
+ mddev_t *mddev2;
+ spin_lock(&all_mddevs_lock);
+
+ list_for_each_entry(mddev2, &all_mddevs, all_mddevs)
+ if (mddev2->gendisk &&
+ strcmp(mddev2->gendisk->disk_name, name) == 0) {
+ spin_unlock(&all_mddevs_lock);
+ return -EEXIST;
+ }
+ spin_unlock(&all_mddevs_lock);
+ }
+
+ mddev->queue = blk_alloc_queue(GFP_KERNEL);
+ if (!mddev->queue) {
+ mutex_unlock(&disks_mutex);
+ mddev_put(mddev);
+ return -ENOMEM;
}
+ /* Can be unlocked because the queue is new: no concurrency */
+ queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue);
+
+ blk_queue_make_request(mddev->queue, md_fail_request);
+
disk = alloc_disk(1 << shift);
if (!disk) {
mutex_unlock(&disks_mutex);
+ blk_cleanup_queue(mddev->queue);
+ mddev->queue = NULL;
mddev_put(mddev);
- return NULL;
+ return -ENOMEM;
}
- disk->major = MAJOR(dev);
+ disk->major = MAJOR(mddev->unit);
disk->first_minor = unit << shift;
- if (partitioned)
+ if (name)
+ strcpy(disk->disk_name, name);
+ else if (partitioned)
sprintf(disk->disk_name, "md_d%d", unit);
else
sprintf(disk->disk_name, "md%d", unit);
@@ -3464,7 +3603,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
disk->private_data = mddev;
disk->queue = mddev->queue;
/* Allow extended partitions. This makes the
- * 'mdp' device redundant, but we can really
+ * 'mdp' device redundant, but we can't really
* remove it now.
*/
disk->flags |= GENHD_FL_EXT_DEVT;
@@ -3480,9 +3619,35 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
kobject_uevent(&mddev->kobj, KOBJ_ADD);
mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state");
}
+ mddev_put(mddev);
+ return 0;
+}
+
+static struct kobject *md_probe(dev_t dev, int *part, void *data)
+{
+ md_alloc(dev, NULL);
return NULL;
}
+static int add_named_array(const char *val, struct kernel_param *kp)
+{
+ /* val must be "md_*" where * is not all digits.
+ * We allocate an array with a large free minor number, and
+ * set the name to val. val must not already be an active name.
+ */
+ int len = strlen(val);
+ char buf[DISK_NAME_LEN];
+
+ while (len && val[len-1] == '\n')
+ len--;
+ if (len >= DISK_NAME_LEN)
+ return -E2BIG;
+ strlcpy(buf, val, len+1);
+ if (strncmp(buf, "md_", 3) != 0)
+ return -EINVAL;
+ return md_alloc(0, buf);
+}
+
static void md_safemode_timeout(unsigned long data)
{
mddev_t *mddev = (mddev_t *) data;
@@ -3501,7 +3666,6 @@ static int do_md_run(mddev_t * mddev)
{
int err;
int chunk_size;
- struct list_head *tmp;
mdk_rdev_t *rdev;
struct gendisk *disk;
struct mdk_personality *pers;
@@ -3540,7 +3704,7 @@ static int do_md_run(mddev_t * mddev)
}
/* devices must have minimum size of one chunk */
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
if (test_bit(Faulty, &rdev->flags))
continue;
if (rdev->size < chunk_size / 1024) {
@@ -3565,7 +3729,7 @@ static int do_md_run(mddev_t * mddev)
* the only valid external interface is through the md
* device.
*/
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
if (test_bit(Faulty, &rdev->flags))
continue;
sync_blockdev(rdev->bdev);
@@ -3630,10 +3794,10 @@ static int do_md_run(mddev_t * mddev)
*/
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
mdk_rdev_t *rdev2;
- struct list_head *tmp2;
int warned = 0;
- rdev_for_each(rdev, tmp, mddev) {
- rdev_for_each(rdev2, tmp2, mddev) {
+
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ list_for_each_entry(rdev2, &mddev->disks, same_set) {
if (rdev < rdev2 &&
rdev->bdev->bd_contains ==
rdev2->bdev->bd_contains) {
@@ -3647,7 +3811,7 @@ static int do_md_run(mddev_t * mddev)
warned = 1;
}
}
- }
+
if (warned)
printk(KERN_WARNING
"True protection against single-disk"
@@ -3684,6 +3848,7 @@ static int do_md_run(mddev_t * mddev)
printk(KERN_WARNING
"md: cannot register extra attributes for %s\n",
mdname(mddev));
+ mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action");
} else if (mddev->ro == 2) /* auto-readonly not meaningful */
mddev->ro = 0;
@@ -3694,7 +3859,7 @@ static int do_md_run(mddev_t * mddev)
mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
mddev->in_sync = 1;
- rdev_for_each(rdev, tmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0) {
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
@@ -3725,9 +3890,8 @@ static int do_md_run(mddev_t * mddev)
* it will remove the drives and not do the right thing
*/
if (mddev->degraded && !mddev->sync_thread) {
- struct list_head *rtmp;
int spares = 0;
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags))
@@ -3754,7 +3918,8 @@ static int do_md_run(mddev_t * mddev)
mddev->changed = 1;
md_new_event(mddev);
sysfs_notify_dirent(mddev->sysfs_state);
- sysfs_notify(&mddev->kobj, NULL, "sync_action");
+ if (mddev->sysfs_action)
+ sysfs_notify_dirent(mddev->sysfs_action);
sysfs_notify(&mddev->kobj, NULL, "degraded");
kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
return 0;
@@ -3854,9 +4019,12 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
mddev->queue->merge_bvec_fn = NULL;
mddev->queue->unplug_fn = NULL;
mddev->queue->backing_dev_info.congested_fn = NULL;
- if (mddev->pers->sync_request)
+ if (mddev->pers->sync_request) {
sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
-
+ if (mddev->sysfs_action)
+ sysfs_put(mddev->sysfs_action);
+ mddev->sysfs_action = NULL;
+ }
module_put(mddev->pers->owner);
mddev->pers = NULL;
/* tell userspace to handle 'inactive' */
@@ -3883,7 +4051,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
*/
if (mode == 0) {
mdk_rdev_t *rdev;
- struct list_head *tmp;
printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
@@ -3895,7 +4062,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
}
mddev->bitmap_offset = 0;
- rdev_for_each(rdev, tmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0) {
char nm[20];
sprintf(nm, "rd%d", rdev->raid_disk);
@@ -3941,6 +4108,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
mddev->barriers_work = 0;
mddev->safemode = 0;
kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
+ if (mddev->hold_active == UNTIL_STOP)
+ mddev->hold_active = 0;
} else if (mddev->pers)
printk(KERN_INFO "md: %s switched to read-only mode.\n",
@@ -3956,7 +4125,6 @@ out:
static void autorun_array(mddev_t *mddev)
{
mdk_rdev_t *rdev;
- struct list_head *tmp;
int err;
if (list_empty(&mddev->disks))
@@ -3964,7 +4132,7 @@ static void autorun_array(mddev_t *mddev)
printk(KERN_INFO "md: running: ");
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
char b[BDEVNAME_SIZE];
printk("<%s>", bdevname(rdev->bdev,b));
}
@@ -3991,8 +4159,7 @@ static void autorun_array(mddev_t *mddev)
*/
static void autorun_devices(int part)
{
- struct list_head *tmp;
- mdk_rdev_t *rdev0, *rdev;
+ mdk_rdev_t *rdev0, *rdev, *tmp;
mddev_t *mddev;
char b[BDEVNAME_SIZE];
@@ -4007,7 +4174,7 @@ static void autorun_devices(int part)
printk(KERN_INFO "md: considering %s ...\n",
bdevname(rdev0->bdev,b));
INIT_LIST_HEAD(&candidates);
- rdev_for_each_list(rdev, tmp, pending_raid_disks)
+ rdev_for_each_list(rdev, tmp, &pending_raid_disks)
if (super_90_load(rdev, rdev0, 0) >= 0) {
printk(KERN_INFO "md: adding %s ...\n",
bdevname(rdev->bdev,b));
@@ -4053,7 +4220,7 @@ static void autorun_devices(int part)
} else {
printk(KERN_INFO "md: created %s\n", mdname(mddev));
mddev->persistent = 1;
- rdev_for_each_list(rdev, tmp, candidates) {
+ rdev_for_each_list(rdev, tmp, &candidates) {
list_del_init(&rdev->same_set);
if (bind_rdev_to_array(rdev, mddev))
export_rdev(rdev);
@@ -4064,7 +4231,7 @@ static void autorun_devices(int part)
/* on success, candidates will be empty, on error
* it won't...
*/
- rdev_for_each_list(rdev, tmp, candidates) {
+ rdev_for_each_list(rdev, tmp, &candidates) {
list_del_init(&rdev->same_set);
export_rdev(rdev);
}
@@ -4093,10 +4260,9 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
mdu_array_info_t info;
int nr,working,active,failed,spare;
mdk_rdev_t *rdev;
- struct list_head *tmp;
nr=working=active=failed=spare=0;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
nr++;
if (test_bit(Faulty, &rdev->flags))
failed++;
@@ -4614,9 +4780,8 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
static int update_size(mddev_t *mddev, sector_t num_sectors)
{
- mdk_rdev_t * rdev;
+ mdk_rdev_t *rdev;
int rv;
- struct list_head *tmp;
int fit = (num_sectors == 0);
if (mddev->pers->resize == NULL)
@@ -4638,7 +4803,7 @@ static int update_size(mddev_t *mddev, sector_t num_sectors)
* grow, and re-add.
*/
return -EBUSY;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
sector_t avail;
avail = rdev->size * 2;
@@ -5000,6 +5165,9 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
done_unlock:
abort_unlock:
+ if (mddev->hold_active == UNTIL_IOCTL &&
+ err != -EINVAL)
+ mddev->hold_active = 0;
mddev_unlock(mddev);
return err;
@@ -5016,14 +5184,25 @@ static int md_open(struct block_device *bdev, fmode_t mode)
* Succeed if we can lock the mddev, which confirms that
* it isn't being stopped right now.
*/
- mddev_t *mddev = bdev->bd_disk->private_data;
+ mddev_t *mddev = mddev_find(bdev->bd_dev);
int err;
+ if (mddev->gendisk != bdev->bd_disk) {
+ /* we are racing with mddev_put which is discarding this
+ * bd_disk.
+ */
+ mddev_put(mddev);
+ /* Wait until bdev->bd_disk is definitely gone */
+ flush_scheduled_work();
+ /* Then retry the open from the top */
+ return -ERESTARTSYS;
+ }
+ BUG_ON(mddev != bdev->bd_disk->private_data);
+
if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
goto out;
err = 0;
- mddev_get(mddev);
atomic_inc(&mddev->openers);
mddev_unlock(mddev);
@@ -5187,11 +5366,10 @@ static void status_unused(struct seq_file *seq)
{
int i = 0;
mdk_rdev_t *rdev;
- struct list_head *tmp;
seq_printf(seq, "unused devices: ");
- rdev_for_each_list(rdev, tmp, pending_raid_disks) {
+ list_for_each_entry(rdev, &pending_raid_disks, same_set) {
char b[BDEVNAME_SIZE];
i++;
seq_printf(seq, "%s ",
@@ -5350,7 +5528,6 @@ static int md_seq_show(struct seq_file *seq, void *v)
{
mddev_t *mddev = v;
sector_t size;
- struct list_head *tmp2;
mdk_rdev_t *rdev;
struct mdstat_info *mi = seq->private;
struct bitmap *bitmap;
@@ -5387,7 +5564,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
}
size = 0;
- rdev_for_each(rdev, tmp2, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
char b[BDEVNAME_SIZE];
seq_printf(seq, " %s[%d]",
bdevname(rdev->bdev,b), rdev->desc_nr);
@@ -5694,7 +5871,6 @@ void md_do_sync(mddev_t *mddev)
struct list_head *tmp;
sector_t last_check;
int skipped = 0;
- struct list_head *rtmp;
mdk_rdev_t *rdev;
char *desc;
@@ -5799,7 +5975,7 @@ void md_do_sync(mddev_t *mddev)
/* recovery follows the physical size of devices */
max_sectors = mddev->size << 1;
j = MaxSector;
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
@@ -5949,7 +6125,7 @@ void md_do_sync(mddev_t *mddev)
} else {
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery))
mddev->curr_resync = MaxSector;
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
@@ -5985,10 +6161,9 @@ EXPORT_SYMBOL_GPL(md_do_sync);
static int remove_and_add_spares(mddev_t *mddev)
{
mdk_rdev_t *rdev;
- struct list_head *rtmp;
int spares = 0;
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk >= 0 &&
!test_bit(Blocked, &rdev->flags) &&
(test_bit(Faulty, &rdev->flags) ||
@@ -6003,8 +6178,8 @@ static int remove_and_add_spares(mddev_t *mddev)
}
}
- if (mddev->degraded && ! mddev->ro) {
- rdev_for_each(rdev, rtmp, mddev) {
+ if (mddev->degraded && ! mddev->ro && !mddev->recovery_disabled) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk >= 0 &&
!test_bit(In_sync, &rdev->flags) &&
!test_bit(Blocked, &rdev->flags))
@@ -6056,7 +6231,6 @@ static int remove_and_add_spares(mddev_t *mddev)
void md_check_recovery(mddev_t *mddev)
{
mdk_rdev_t *rdev;
- struct list_head *rtmp;
if (mddev->bitmap)
@@ -6120,7 +6294,7 @@ void md_check_recovery(mddev_t *mddev)
if (mddev->flags)
md_update_sb(mddev, 0);
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (test_and_clear_bit(StateChanged, &rdev->flags))
sysfs_notify_dirent(rdev->sysfs_state);
@@ -6149,13 +6323,13 @@ void md_check_recovery(mddev_t *mddev)
* information must be scrapped
*/
if (!mddev->degraded)
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
rdev->saved_raid_disk = -1;
mddev->recovery = 0;
/* flag recovery needed just to double check */
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
- sysfs_notify(&mddev->kobj, NULL, "sync_action");
+ sysfs_notify_dirent(mddev->sysfs_action);
md_new_event(mddev);
goto unlock;
}
@@ -6216,7 +6390,7 @@ void md_check_recovery(mddev_t *mddev)
mddev->recovery = 0;
} else
md_wakeup_thread(mddev->sync_thread);
- sysfs_notify(&mddev->kobj, NULL, "sync_action");
+ sysfs_notify_dirent(mddev->sysfs_action);
md_new_event(mddev);
}
unlock:
@@ -6224,7 +6398,8 @@ void md_check_recovery(mddev_t *mddev)
clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
if (test_and_clear_bit(MD_RECOVERY_RECOVER,
&mddev->recovery))
- sysfs_notify(&mddev->kobj, NULL, "sync_action");
+ if (mddev->sysfs_action)
+ sysfs_notify_dirent(mddev->sysfs_action);
}
mddev_unlock(mddev);
}
@@ -6386,14 +6561,8 @@ static __exit void md_exit(void)
unregister_sysctl_table(raid_table_header);
remove_proc_entry("mdstat", NULL);
for_each_mddev(mddev, tmp) {
- struct gendisk *disk = mddev->gendisk;
- if (!disk)
- continue;
export_array(mddev);
- del_gendisk(disk);
- put_disk(disk);
- mddev->gendisk = NULL;
- mddev_put(mddev);
+ mddev->hold_active = 0;
}
}
@@ -6418,6 +6587,7 @@ static int set_ro(const char *val, struct kernel_param *kp)
module_param_call(start_ro, set_ro, get_ro, NULL, S_IRUSR|S_IWUSR);
module_param(start_dirty_degraded, int, S_IRUGO|S_IWUSR);
+module_param_call(new_array, add_named_array, NULL, NULL, S_IWUSR);
EXPORT_SYMBOL(register_md_personality);
EXPORT_SYMBOL(unregister_md_personality);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index d4ac47d11279..f6d08f241671 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -408,7 +408,6 @@ static int multipath_run (mddev_t *mddev)
int disk_idx;
struct multipath_info *disk;
mdk_rdev_t *rdev;
- struct list_head *tmp;
if (mddev->level != LEVEL_MULTIPATH) {
printk("multipath: %s: raid level not set to multipath IO (%d)\n",
@@ -441,7 +440,7 @@ static int multipath_run (mddev_t *mddev)
}
conf->working_disks = 0;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
disk_idx = rdev->raid_disk;
if (disk_idx < 0 ||
disk_idx >= mddev->raid_disks)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 8ac6488ad0dc..c605ba805586 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -53,11 +53,10 @@ static int raid0_congested(void *data, int bits)
static int create_strip_zones (mddev_t *mddev)
{
int i, c, j;
- sector_t current_offset, curr_zone_offset;
+ sector_t current_start, curr_zone_start;
sector_t min_spacing;
raid0_conf_t *conf = mddev_to_conf(mddev);
mdk_rdev_t *smallest, *rdev1, *rdev2, *rdev;
- struct list_head *tmp1, *tmp2;
struct strip_zone *zone;
int cnt;
char b[BDEVNAME_SIZE];
@@ -67,19 +66,19 @@ static int create_strip_zones (mddev_t *mddev)
*/
conf->nr_strip_zones = 0;
- rdev_for_each(rdev1, tmp1, mddev) {
- printk("raid0: looking at %s\n",
+ list_for_each_entry(rdev1, &mddev->disks, same_set) {
+ printk(KERN_INFO "raid0: looking at %s\n",
bdevname(rdev1->bdev,b));
c = 0;
- rdev_for_each(rdev2, tmp2, mddev) {
- printk("raid0: comparing %s(%llu)",
+ list_for_each_entry(rdev2, &mddev->disks, same_set) {
+ printk(KERN_INFO "raid0: comparing %s(%llu)",
bdevname(rdev1->bdev,b),
(unsigned long long)rdev1->size);
- printk(" with %s(%llu)\n",
+ printk(KERN_INFO " with %s(%llu)\n",
bdevname(rdev2->bdev,b),
(unsigned long long)rdev2->size);
if (rdev2 == rdev1) {
- printk("raid0: END\n");
+ printk(KERN_INFO "raid0: END\n");
break;
}
if (rdev2->size == rdev1->size)
@@ -88,19 +87,20 @@ static int create_strip_zones (mddev_t *mddev)
* Not unique, don't count it as a new
* group
*/
- printk("raid0: EQUAL\n");
+ printk(KERN_INFO "raid0: EQUAL\n");
c = 1;
break;
}
- printk("raid0: NOT EQUAL\n");
+ printk(KERN_INFO "raid0: NOT EQUAL\n");
}
if (!c) {
- printk("raid0: ==> UNIQUE\n");
+ printk(KERN_INFO "raid0: ==> UNIQUE\n");
conf->nr_strip_zones++;
- printk("raid0: %d zones\n", conf->nr_strip_zones);
+ printk(KERN_INFO "raid0: %d zones\n",
+ conf->nr_strip_zones);
}
}
- printk("raid0: FINAL %d zones\n", conf->nr_strip_zones);
+ printk(KERN_INFO "raid0: FINAL %d zones\n", conf->nr_strip_zones);
conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
conf->nr_strip_zones, GFP_KERNEL);
@@ -119,16 +119,17 @@ static int create_strip_zones (mddev_t *mddev)
cnt = 0;
smallest = NULL;
zone->dev = conf->devlist;
- rdev_for_each(rdev1, tmp1, mddev) {
+ list_for_each_entry(rdev1, &mddev->disks, same_set) {
int j = rdev1->raid_disk;
if (j < 0 || j >= mddev->raid_disks) {
- printk("raid0: bad disk number %d - aborting!\n", j);
+ printk(KERN_ERR "raid0: bad disk number %d - "
+ "aborting!\n", j);
goto abort;
}
if (zone->dev[j]) {
- printk("raid0: multiple devices for %d - aborting!\n",
- j);
+ printk(KERN_ERR "raid0: multiple devices for %d - "
+ "aborting!\n", j);
goto abort;
}
zone->dev[j] = rdev1;
@@ -149,16 +150,16 @@ static int create_strip_zones (mddev_t *mddev)
cnt++;
}
if (cnt != mddev->raid_disks) {
- printk("raid0: too few disks (%d of %d) - aborting!\n",
- cnt, mddev->raid_disks);
+ printk(KERN_ERR "raid0: too few disks (%d of %d) - "
+ "aborting!\n", cnt, mddev->raid_disks);
goto abort;
}
zone->nb_dev = cnt;
- zone->size = smallest->size * cnt;
- zone->zone_offset = 0;
+ zone->sectors = smallest->size * cnt * 2;
+ zone->zone_start = 0;
- current_offset = smallest->size;
- curr_zone_offset = zone->size;
+ current_start = smallest->size * 2;
+ curr_zone_start = zone->sectors;
/* now do the other zones */
for (i = 1; i < conf->nr_strip_zones; i++)
@@ -166,40 +167,41 @@ static int create_strip_zones (mddev_t *mddev)
zone = conf->strip_zone + i;
zone->dev = conf->strip_zone[i-1].dev + mddev->raid_disks;
- printk("raid0: zone %d\n", i);
- zone->dev_offset = current_offset;
+ printk(KERN_INFO "raid0: zone %d\n", i);
+ zone->dev_start = current_start;
smallest = NULL;
c = 0;
for (j=0; j<cnt; j++) {
char b[BDEVNAME_SIZE];
rdev = conf->strip_zone[0].dev[j];
- printk("raid0: checking %s ...", bdevname(rdev->bdev,b));
- if (rdev->size > current_offset)
- {
- printk(" contained as device %d\n", c);
+ printk(KERN_INFO "raid0: checking %s ...",
+ bdevname(rdev->bdev, b));
+ if (rdev->size > current_start / 2) {
+ printk(KERN_INFO " contained as device %d\n",
+ c);
zone->dev[c] = rdev;
c++;
if (!smallest || (rdev->size <smallest->size)) {
smallest = rdev;
- printk(" (%llu) is smallest!.\n",
+ printk(KERN_INFO " (%llu) is smallest!.\n",
(unsigned long long)rdev->size);
}
} else
- printk(" nope.\n");
+ printk(KERN_INFO " nope.\n");
}
zone->nb_dev = c;
- zone->size = (smallest->size - current_offset) * c;
- printk("raid0: zone->nb_dev: %d, size: %llu\n",
- zone->nb_dev, (unsigned long long)zone->size);
+ zone->sectors = (smallest->size * 2 - current_start) * c;
+ printk(KERN_INFO "raid0: zone->nb_dev: %d, sectors: %llu\n",
+ zone->nb_dev, (unsigned long long)zone->sectors);
- zone->zone_offset = curr_zone_offset;
- curr_zone_offset += zone->size;
+ zone->zone_start = curr_zone_start;
+ curr_zone_start += zone->sectors;
- current_offset = smallest->size;
- printk("raid0: current zone offset: %llu\n",
- (unsigned long long)current_offset);
+ current_start = smallest->size * 2;
+ printk(KERN_INFO "raid0: current zone start: %llu\n",
+ (unsigned long long)current_start);
}
/* Now find appropriate hash spacing.
@@ -210,16 +212,16 @@ static int create_strip_zones (mddev_t *mddev)
* strip though as it's size has no bearing on the efficacy of the hash
* table.
*/
- conf->hash_spacing = curr_zone_offset;
- min_spacing = curr_zone_offset;
+ conf->spacing = curr_zone_start;
+ min_spacing = curr_zone_start;
sector_div(min_spacing, PAGE_SIZE/sizeof(struct strip_zone*));
for (i=0; i < conf->nr_strip_zones-1; i++) {
- sector_t sz = 0;
- for (j=i; j<conf->nr_strip_zones-1 &&
- sz < min_spacing ; j++)
- sz += conf->strip_zone[j].size;
- if (sz >= min_spacing && sz < conf->hash_spacing)
- conf->hash_spacing = sz;
+ sector_t s = 0;
+ for (j = i; j < conf->nr_strip_zones - 1 &&
+ s < min_spacing; j++)
+ s += conf->strip_zone[j].sectors;
+ if (s >= min_spacing && s < conf->spacing)
+ conf->spacing = s;
}
mddev->queue->unplug_fn = raid0_unplug;
@@ -227,7 +229,7 @@ static int create_strip_zones (mddev_t *mddev)
mddev->queue->backing_dev_info.congested_fn = raid0_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
- printk("raid0: done.\n");
+ printk(KERN_INFO "raid0: done.\n");
return 0;
abort:
return 1;
@@ -262,10 +264,9 @@ static int raid0_mergeable_bvec(struct request_queue *q,
static int raid0_run (mddev_t *mddev)
{
unsigned cur=0, i=0, nb_zone;
- s64 size;
+ s64 sectors;
raid0_conf_t *conf;
mdk_rdev_t *rdev;
- struct list_head *tmp;
if (mddev->chunk_size == 0) {
printk(KERN_ERR "md/raid0: non-zero chunk size required.\n");
@@ -291,54 +292,54 @@ static int raid0_run (mddev_t *mddev)
/* calculate array device size */
mddev->array_sectors = 0;
- rdev_for_each(rdev, tmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
mddev->array_sectors += rdev->size * 2;
- printk("raid0 : md_size is %llu blocks.\n",
- (unsigned long long)mddev->array_sectors / 2);
- printk("raid0 : conf->hash_spacing is %llu blocks.\n",
- (unsigned long long)conf->hash_spacing);
+ printk(KERN_INFO "raid0 : md_size is %llu sectors.\n",
+ (unsigned long long)mddev->array_sectors);
+ printk(KERN_INFO "raid0 : conf->spacing is %llu sectors.\n",
+ (unsigned long long)conf->spacing);
{
- sector_t s = mddev->array_sectors / 2;
- sector_t space = conf->hash_spacing;
+ sector_t s = mddev->array_sectors;
+ sector_t space = conf->spacing;
int round;
- conf->preshift = 0;
+ conf->sector_shift = 0;
if (sizeof(sector_t) > sizeof(u32)) {
/*shift down space and s so that sector_div will work */
while (space > (sector_t) (~(u32)0)) {
s >>= 1;
space >>= 1;
s += 1; /* force round-up */
- conf->preshift++;
+ conf->sector_shift++;
}
}
round = sector_div(s, (u32)space) ? 1 : 0;
nb_zone = s + round;
}
- printk("raid0 : nb_zone is %d.\n", nb_zone);
+ printk(KERN_INFO "raid0 : nb_zone is %d.\n", nb_zone);
- printk("raid0 : Allocating %Zd bytes for hash.\n",
+ printk(KERN_INFO "raid0 : Allocating %zu bytes for hash.\n",
nb_zone*sizeof(struct strip_zone*));
conf->hash_table = kmalloc (sizeof (struct strip_zone *)*nb_zone, GFP_KERNEL);
if (!conf->hash_table)
goto out_free_conf;
- size = conf->strip_zone[cur].size;
+ sectors = conf->strip_zone[cur].sectors;
conf->hash_table[0] = conf->strip_zone + cur;
for (i=1; i< nb_zone; i++) {
- while (size <= conf->hash_spacing) {
+ while (sectors <= conf->spacing) {
cur++;
- size += conf->strip_zone[cur].size;
+ sectors += conf->strip_zone[cur].sectors;
}
- size -= conf->hash_spacing;
+ sectors -= conf->spacing;
conf->hash_table[i] = conf->strip_zone + cur;
}
- if (conf->preshift) {
- conf->hash_spacing >>= conf->preshift;
- /* round hash_spacing up so when we divide by it, we
+ if (conf->sector_shift) {
+ conf->spacing >>= conf->sector_shift;
+ /* round spacing up so when we divide by it, we
* err on the side of too-low, which is safest
*/
- conf->hash_spacing++;
+ conf->spacing++;
}
/* calculate the max read-ahead size.
@@ -387,12 +388,12 @@ static int raid0_stop (mddev_t *mddev)
static int raid0_make_request (struct request_queue *q, struct bio *bio)
{
mddev_t *mddev = q->queuedata;
- unsigned int sect_in_chunk, chunksize_bits, chunk_size, chunk_sects;
+ unsigned int sect_in_chunk, chunksect_bits, chunk_sects;
raid0_conf_t *conf = mddev_to_conf(mddev);
struct strip_zone *zone;
mdk_rdev_t *tmp_dev;
sector_t chunk;
- sector_t block, rsect;
+ sector_t sector, rsect;
const int rw = bio_data_dir(bio);
int cpu;
@@ -407,11 +408,9 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio)
bio_sectors(bio));
part_stat_unlock();
- chunk_size = mddev->chunk_size >> 10;
chunk_sects = mddev->chunk_size >> 9;
- chunksize_bits = ffz(~chunk_size);
- block = bio->bi_sector >> 1;
-
+ chunksect_bits = ffz(~chunk_sects);
+ sector = bio->bi_sector;
if (unlikely(chunk_sects < (bio->bi_sector & (chunk_sects - 1)) + (bio->bi_size >> 9))) {
struct bio_pair *bp;
@@ -434,28 +433,27 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio)
{
- sector_t x = block >> conf->preshift;
- sector_div(x, (u32)conf->hash_spacing);
+ sector_t x = sector >> conf->sector_shift;
+ sector_div(x, (u32)conf->spacing);
zone = conf->hash_table[x];
}
-
- while (block >= (zone->zone_offset + zone->size))
+
+ while (sector >= zone->zone_start + zone->sectors)
zone++;
-
- sect_in_chunk = bio->bi_sector & ((chunk_size<<1) -1);
+
+ sect_in_chunk = bio->bi_sector & (chunk_sects - 1);
{
- sector_t x = (block - zone->zone_offset) >> chunksize_bits;
+ sector_t x = (sector - zone->zone_start) >> chunksect_bits;
sector_div(x, zone->nb_dev);
chunk = x;
- x = block >> chunksize_bits;
+ x = sector >> chunksect_bits;
tmp_dev = zone->dev[sector_div(x, zone->nb_dev)];
}
- rsect = (((chunk << chunksize_bits) + zone->dev_offset)<<1)
- + sect_in_chunk;
+ rsect = (chunk << chunksect_bits) + zone->dev_start + sect_in_chunk;
bio->bi_bdev = tmp_dev->bdev;
bio->bi_sector = rsect + tmp_dev->data_offset;
@@ -467,7 +465,7 @@ static int raid0_make_request (struct request_queue *q, struct bio *bio)
bad_map:
printk("raid0_make_request bug: can't convert block across chunks"
- " or bigger than %dk %llu %d\n", chunk_size,
+ " or bigger than %dk %llu %d\n", chunk_sects / 2,
(unsigned long long)bio->bi_sector, bio->bi_size >> 10);
bio_io_error(bio);
@@ -492,10 +490,10 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev)
seq_printf(seq, "%s/", bdevname(
conf->strip_zone[j].dev[k]->bdev,b));
- seq_printf(seq, "] zo=%d do=%d s=%d\n",
- conf->strip_zone[j].zone_offset,
- conf->strip_zone[j].dev_offset,
- conf->strip_zone[j].size);
+ seq_printf(seq, "] zs=%d ds=%d s=%d\n",
+ conf->strip_zone[j].zone_start,
+ conf->strip_zone[j].dev_start,
+ conf->strip_zone[j].sectors);
}
#endif
seq_printf(seq, " %dk chunks", mddev->chunk_size/1024);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 9c788e2489b1..7b4f5f7155d8 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1016,12 +1016,16 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
* else mark the drive as failed
*/
if (test_bit(In_sync, &rdev->flags)
- && (conf->raid_disks - mddev->degraded) == 1)
+ && (conf->raid_disks - mddev->degraded) == 1) {
/*
* Don't fail the drive, act as though we were just a
- * normal single drive
+ * normal single drive.
+ * However don't try a recovery from this drive as
+ * it is very likely to fail.
*/
+ mddev->recovery_disabled = 1;
return;
+ }
if (test_and_clear_bit(In_sync, &rdev->flags)) {
unsigned long flags;
spin_lock_irqsave(&conf->device_lock, flags);
@@ -1919,7 +1923,6 @@ static int run(mddev_t *mddev)
int i, j, disk_idx;
mirror_info_t *disk;
mdk_rdev_t *rdev;
- struct list_head *tmp;
if (mddev->level != 1) {
printk("raid1: %s: raid level not set to mirroring (%d)\n",
@@ -1964,7 +1967,7 @@ static int run(mddev_t *mddev)
spin_lock_init(&conf->device_lock);
mddev->queue->queue_lock = &conf->device_lock;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
disk_idx = rdev->raid_disk;
if (disk_idx >= mddev->raid_disks
|| disk_idx < 0)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 970a96ef9b18..6736d6dff981 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -2025,7 +2025,6 @@ static int run(mddev_t *mddev)
int i, disk_idx;
mirror_info_t *disk;
mdk_rdev_t *rdev;
- struct list_head *tmp;
int nc, fc, fo;
sector_t stride, size;
@@ -2108,7 +2107,7 @@ static int run(mddev_t *mddev)
spin_lock_init(&conf->device_lock);
mddev->queue->queue_lock = &conf->device_lock;
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
disk_idx = rdev->raid_disk;
if (disk_idx >= mddev->raid_disks
|| disk_idx < 0)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index a36a7435edf5..a5ba080d303b 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3998,7 +3998,6 @@ static int run(mddev_t *mddev)
int raid_disk, memory;
mdk_rdev_t *rdev;
struct disk_info *disk;
- struct list_head *tmp;
int working_disks = 0;
if (mddev->level != 5 && mddev->level != 4 && mddev->level != 6) {
@@ -4108,7 +4107,7 @@ static int run(mddev_t *mddev)
pr_debug("raid5: run(%s) called.\n", mdname(mddev));
- rdev_for_each(rdev, tmp, mddev) {
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
raid_disk = rdev->raid_disk;
if (raid_disk >= conf->raid_disks
|| raid_disk < 0)
@@ -4533,7 +4532,6 @@ static int raid5_start_reshape(mddev_t *mddev)
{
raid5_conf_t *conf = mddev_to_conf(mddev);
mdk_rdev_t *rdev;
- struct list_head *rtmp;
int spares = 0;
int added_devices = 0;
unsigned long flags;
@@ -4541,7 +4539,7 @@ static int raid5_start_reshape(mddev_t *mddev)
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
return -EBUSY;
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags))
spares++;
@@ -4563,7 +4561,7 @@ static int raid5_start_reshape(mddev_t *mddev)
/* Add some new drives, as many as will fit.
* We know there are enough to make the newly sized array work.
*/
- rdev_for_each(rdev, rtmp, mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set)
if (rdev->raid_disk < 0 &&
!test_bit(Faulty, &rdev->flags)) {
if (raid5_add_disk(mddev, rdev) == 0) {
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 7d844af88384..cf06f4d10ad4 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -192,9 +192,9 @@ void saa7146_buffer_timeout(unsigned long data)
/********************************************************************************/
/* file operations */
-static int fops_open(struct inode *inode, struct file *file)
+static int fops_open(struct file *file)
{
- unsigned int minor = iminor(inode);
+ unsigned int minor = video_devdata(file)->minor;
struct saa7146_dev *h = NULL, *dev = NULL;
struct list_head *list;
struct saa7146_fh *fh = NULL;
@@ -202,7 +202,7 @@ static int fops_open(struct inode *inode, struct file *file)
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- DEB_EE(("inode:%p, file:%p, minor:%d\n",inode,file,minor));
+ DEB_EE(("file:%p, minor:%d\n", file, minor));
if (mutex_lock_interruptible(&saa7146_devices_lock))
return -ERESTARTSYS;
@@ -255,7 +255,7 @@ static int fops_open(struct inode *inode, struct file *file)
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
result = saa7146_vbi_uops.open(dev,file);
if (dev->ext_vv_data->vbi_fops.open)
- dev->ext_vv_data->vbi_fops.open(inode, file);
+ dev->ext_vv_data->vbi_fops.open(file);
} else {
DEB_S(("initializing video...\n"));
result = saa7146_video_uops.open(dev,file);
@@ -280,12 +280,12 @@ out:
return result;
}
-static int fops_release(struct inode *inode, struct file *file)
+static int fops_release(struct file *file)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
- DEB_EE(("inode:%p, file:%p\n",inode,file));
+ DEB_EE(("file:%p\n", file));
if (mutex_lock_interruptible(&saa7146_devices_lock))
return -ERESTARTSYS;
@@ -294,7 +294,7 @@ static int fops_release(struct inode *inode, struct file *file)
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
saa7146_vbi_uops.release(dev,file);
if (dev->ext_vv_data->vbi_fops.release)
- dev->ext_vv_data->vbi_fops.release(inode, file);
+ dev->ext_vv_data->vbi_fops.release(file);
} else {
saa7146_video_uops.release(dev,file);
}
@@ -308,10 +308,10 @@ static int fops_release(struct inode *inode, struct file *file)
return 0;
}
-static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
/*
- DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg));
+ DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg));
*/
return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
}
@@ -416,7 +416,7 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou
}
}
-static const struct file_operations video_fops =
+static const struct v4l2_file_operations video_fops =
{
.owner = THIS_MODULE,
.open = fops_open,
@@ -426,7 +426,6 @@ static const struct file_operations video_fops =
.poll = fops_poll,
.mmap = fops_mmap,
.ioctl = fops_ioctl,
- .llseek = no_llseek,
};
static void vv_callback(struct saa7146_dev *dev, unsigned long status)
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 101b01dbb8ea..47fee05eaefb 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -576,6 +576,7 @@ static int set_control(struct saa7146_fh *fh, struct v4l2_control *c)
vv->vflip = c->value;
break;
default: {
+ mutex_unlock(&dev->lock);
return -EINVAL;
}
}
@@ -834,13 +835,14 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
* copying is done already, arg is a kernel pointer.
*/
-int saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+long saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
struct saa7146_vv *vv = dev->vv_data;
- int err = 0, result = 0, ee = 0;
+ long err = 0;
+ int result = 0, ee = 0;
struct saa7146_use_ops *ops;
struct videobuf_queue *q;
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
index 64379f2bf237..3ec28945c26f 100644
--- a/drivers/media/common/tuners/mxl5007t.c
+++ b/drivers/media/common/tuners/mxl5007t.c
@@ -657,7 +657,7 @@ static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
{
struct mxl5007t_state *state = fe->tuner_priv;
int rf_locked, ref_locked;
- s32 rf_input_level;
+ s32 rf_input_level = 0;
int ret;
if (fe->ops.i2c_gate_ctrl)
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c
index 0ee79fd7c7a9..4b8662edb7cb 100644
--- a/drivers/media/common/tuners/tda8290.c
+++ b/drivers/media/common/tuners/tda8290.c
@@ -150,7 +150,7 @@ static void set_audio(struct dvb_frontend *fe,
}
}
-struct {
+static struct {
unsigned char seq[2];
} fm_mode[] = {
{ { 0x01, 0x81} }, /* Put device into expert mode */
@@ -207,7 +207,6 @@ static void tda8290_set_params(struct dvb_frontend *fe,
msleep(1);
if (params->mode == V4L2_TUNER_RADIO) {
- int i;
unsigned char deemphasis[] = { 0x13, 1 };
/* FIXME: allow using a different deemphasis */
@@ -767,7 +766,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
fe->ops.analog_ops.info.name = name;
if (priv->ver & TDA8290) {
- tda8290_init_tuner(fe);
+ if (priv->ver & (TDA8275 | TDA8275A))
+ tda8290_init_tuner(fe);
tda8290_init_if(fe);
} else if (priv->ver & TDA8295)
tda8295_init_if(fe);
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index fb3f3b3adaba..de7adaf5fa5b 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -820,6 +820,15 @@ static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
int ret;
unsigned frequency = params->frequency / 62500;
+ if (!tun->stepsize) {
+ /* tuner-core was loaded before the digital tuner was
+ * configured and somehow picked the wrong tuner type */
+ tuner_err("attempt to treat tuner %d (%s) as digital tuner "
+ "without stepsize defined.\n",
+ priv->type, priv->tun->name);
+ return 0; /* failure */
+ }
+
t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
if (ret < 0)
@@ -1059,7 +1068,12 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
sizeof(struct dvb_tuner_ops));
- tuner_info("type set to %d (%s)\n", type, priv->tun->name);
+ if (type != priv->type)
+ tuner_warn("couldn't set type to %d. Using %d (%s) instead\n",
+ type, priv->type, priv->tun->name);
+ else
+ tuner_info("type set to %d (%s)\n",
+ priv->type, priv->tun->name);
if ((debug) || ((atv_input[priv->nr] > 0) ||
(dtv_input[priv->nr] > 0))) {
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
index 1332301ef3ae..43f4d44edca6 100644
--- a/drivers/media/dvb/dm1105/Kconfig
+++ b/drivers/media/dvb/dm1105/Kconfig
@@ -1,6 +1,7 @@
config DVB_DM1105
tristate "SDMC DM1105 based PCI cards"
depends on DVB_CORE && PCI && I2C
+ depends on INPUT
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_STV0288 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 98ee16773ff2..7e3aeaa7370f 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -93,6 +93,9 @@ struct dvb_ca_slot {
/* current state of the CAM */
int slot_state;
+ /* mutex used for serializing access to one CI slot */
+ struct mutex slot_lock;
+
/* Number of CAMCHANGES that have occurred since last processing */
atomic_t camchange_count;
@@ -711,14 +714,20 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
dprintk("%s\n", __func__);
- // sanity check
+ /* sanity check */
if (bytes_write > ca->slot_info[slot].link_buf_size)
return -EINVAL;
- /* check if interface is actually waiting for us to read from it, or if a read is in progress */
+ /* it is possible we are dealing with a single buffer implementation,
+ thus if there is data available for read or if there is even a read
+ already in progress, we do nothing but awake the kernel thread to
+ process the data if necessary. */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
goto exitnowrite;
if (status & (STATUSREG_DA | STATUSREG_RE)) {
+ if (status & STATUSREG_DA)
+ dvb_ca_en50221_thread_wakeup(ca);
+
status = -EAGAIN;
goto exitnowrite;
}
@@ -987,6 +996,8 @@ static int dvb_ca_en50221_thread(void *data)
/* go through all the slots processing them */
for (slot = 0; slot < ca->slot_count; slot++) {
+ mutex_lock(&ca->slot_info[slot].slot_lock);
+
// check the cam status + deal with CAMCHANGEs
while (dvb_ca_en50221_check_camstatus(ca, slot)) {
/* clear down an old CI slot if necessary */
@@ -1122,7 +1133,7 @@ static int dvb_ca_en50221_thread(void *data)
case DVB_CA_SLOTSTATE_RUNNING:
if (!ca->open)
- continue;
+ break;
// poll slots for data
pktcount = 0;
@@ -1146,6 +1157,8 @@ static int dvb_ca_en50221_thread(void *data)
}
break;
}
+
+ mutex_unlock(&ca->slot_info[slot].slot_lock);
}
}
@@ -1181,6 +1194,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case CA_RESET:
for (slot = 0; slot < ca->slot_count; slot++) {
+ mutex_lock(&ca->slot_info[slot].slot_lock);
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
dvb_ca_en50221_slot_shutdown(ca, slot);
if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
@@ -1188,6 +1202,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
slot,
DVB_CA_EN50221_CAMCHANGE_INSERTED);
}
+ mutex_unlock(&ca->slot_info[slot].slot_lock);
}
ca->next_read_slot = 0;
dvb_ca_en50221_thread_wakeup(ca);
@@ -1308,7 +1323,9 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
goto exit;
}
+ mutex_lock(&ca->slot_info[slot].slot_lock);
status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
+ mutex_unlock(&ca->slot_info[slot].slot_lock);
if (status == (fraglen + 2)) {
written = 1;
break;
@@ -1664,6 +1681,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
atomic_set(&ca->slot_info[i].camchange_count, 0);
ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
+ mutex_init(&ca->slot_info[i].slot_lock);
}
if (signal_pending(current)) {
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
index 8467e63ddc0d..7df2e141187a 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
@@ -45,8 +45,10 @@ struct dvb_ca_en50221 {
/* the module owning this structure */
struct module* owner;
- /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as
- * they may be called from several threads at once */
+ /* NOTE: the read_*, write_* and poll_slot_status functions will be
+ * called for different slots concurrently and need to use locks where
+ * and if appropriate. There will be no concurrent access to one slot.
+ */
/* functions for accessing attribute memory on the CAM */
int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 171f9ca124f7..843407785083 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -824,7 +824,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
return 0;
}
-struct dtv_cmds_h dtv_cmds[] = {
+static struct dtv_cmds_h dtv_cmds[] = {
[DTV_TUNE] = {
.name = "DTV_TUNE",
.cmd = DTV_TUNE,
@@ -962,7 +962,7 @@ struct dtv_cmds_h dtv_cmds[] = {
},
};
-void dtv_property_dump(struct dtv_property *tvp)
+static void dtv_property_dump(struct dtv_property *tvp)
{
int i;
@@ -993,7 +993,7 @@ void dtv_property_dump(struct dtv_property *tvp)
dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
}
-int is_legacy_delivery_system(fe_delivery_system_t s)
+static int is_legacy_delivery_system(fe_delivery_system_t s)
{
if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) ||
(s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) ||
@@ -1007,7 +1007,8 @@ int is_legacy_delivery_system(fe_delivery_system_t s)
* drivers can use a single set_frontend tuning function, regardless of whether
* it's being used for the legacy or new API, reducing code and complexity.
*/
-void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+static void dtv_property_cache_sync(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1059,7 +1060,7 @@ void dtv_property_cache_sync(struct dvb_frontend *fe, struct dvb_frontend_parame
/* Ensure the cached values are set correctly in the frontend
* legacy tuning structures, for the advanced tuning API.
*/
-void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
+static void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -1114,7 +1115,7 @@ void dtv_property_legacy_params_sync(struct dvb_frontend *fe)
/* Ensure the cached values are set correctly in the frontend
* legacy tuning structures, for the legacy tuning API.
*/
-void dtv_property_adv_params_sync(struct dvb_frontend *fe)
+static void dtv_property_adv_params_sync(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -1149,7 +1150,7 @@ void dtv_property_adv_params_sync(struct dvb_frontend *fe)
}
}
-void dtv_property_cache_submit(struct dvb_frontend *fe)
+static void dtv_property_cache_submit(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -1180,8 +1181,9 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
unsigned int cmd, void *parg);
-int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp,
- struct inode *inode, struct file *file)
+static int dtv_property_process_get(struct dvb_frontend *fe,
+ struct dtv_property *tvp,
+ struct inode *inode, struct file *file)
{
int r = 0;
@@ -1253,8 +1255,10 @@ int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp,
return r;
}
-int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp,
- struct inode *inode, struct file *file)
+static int dtv_property_process_set(struct dvb_frontend *fe,
+ struct dtv_property *tvp,
+ struct inode *inode,
+ struct file *file)
{
int r = 0;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 03fd9dd5c685..f6ba8468858e 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -125,7 +125,6 @@ static void hexdump( const unsigned char *buf, unsigned short len )
struct dvb_net_priv {
int in_use;
- struct net_device_stats stats;
u16 pid;
struct net_device *net;
struct dvb_net *host;
@@ -384,8 +383,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb );
/* Prepare for next SNDU. */
- priv->stats.rx_errors++;
- priv->stats.rx_frame_errors++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_frame_errors++;
}
reset_ule(priv);
priv->need_pusi = 1;
@@ -438,8 +437,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
dev_kfree_skb( priv->ule_skb );
/* Prepare for next SNDU. */
// reset_ule(priv); moved to below.
- priv->stats.rx_errors++;
- priv->stats.rx_frame_errors++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_frame_errors++;
}
reset_ule(priv);
/* skip to next PUSI. */
@@ -460,8 +459,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) {
dev_kfree_skb( priv->ule_skb );
- priv->stats.rx_errors++;
- priv->stats.rx_frame_errors++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_frame_errors++;
}
reset_ule(priv);
priv->need_pusi = 1;
@@ -477,8 +476,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_sndu_remain > 183) {
/* Current SNDU lacks more data than there could be available in the
* current TS cell. */
- priv->stats.rx_errors++;
- priv->stats.rx_length_errors++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
"got PUSI (pf %d, ts_remain %d). Flushing incomplete payload.\n",
priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
@@ -520,8 +519,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_sndu_len < 5) {
printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
"Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
- priv->stats.rx_errors++;
- priv->stats.rx_length_errors++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
priv->ule_sndu_len = 0;
priv->need_pusi = 1;
new_ts = 1;
@@ -573,7 +572,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
if (priv->ule_skb == NULL) {
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
dev->name);
- priv->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
return;
}
@@ -637,8 +636,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
ule_dump = 1;
#endif
- priv->stats.rx_errors++;
- priv->stats.rx_crc_errors++;
+ dev->stats.rx_errors++;
+ dev->stats.rx_crc_errors++;
dev_kfree_skb(priv->ule_skb);
} else {
/* CRC32 verified OK. */
@@ -744,8 +743,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
* receive the packet anyhow. */
/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
priv->ule_skb->pkt_type = PACKET_HOST; */
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += priv->ule_skb->len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += priv->ule_skb->len;
netif_rx(priv->ule_skb);
}
sndu_done:
@@ -800,8 +799,7 @@ static void dvb_net_sec(struct net_device *dev,
{
u8 *eth;
struct sk_buff *skb;
- struct net_device_stats *stats =
- &((struct dvb_net_priv *) netdev_priv(dev))->stats;
+ struct net_device_stats *stats = &dev->stats;
int snap = 0;
/* note: pkt_len includes a 32bit checksum */
@@ -1216,28 +1214,29 @@ static int dvb_net_stop(struct net_device *dev)
return dvb_net_feed_stop(dev);
}
-static struct net_device_stats * dvb_net_get_stats(struct net_device *dev)
-{
- return &((struct dvb_net_priv *) netdev_priv(dev))->stats;
-}
-
static const struct header_ops dvb_header_ops = {
.create = eth_header,
.parse = eth_header_parse,
.rebuild = eth_rebuild_header,
};
+
+static const struct net_device_ops dvb_netdev_ops = {
+ .ndo_open = dvb_net_open,
+ .ndo_stop = dvb_net_stop,
+ .ndo_start_xmit = dvb_net_tx,
+ .ndo_set_multicast_list = dvb_net_set_multicast_list,
+ .ndo_set_mac_address = dvb_net_set_mac,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static void dvb_net_setup(struct net_device *dev)
{
ether_setup(dev);
dev->header_ops = &dvb_header_ops;
- dev->open = dvb_net_open;
- dev->stop = dvb_net_stop;
- dev->hard_start_xmit = dvb_net_tx;
- dev->get_stats = dvb_net_get_stats;
- dev->set_multicast_list = dvb_net_set_multicast_list;
- dev->set_mac_address = dvb_net_set_mac;
+ dev->netdev_ops = &dvb_netdev_ops;
dev->mtu = 4096;
dev->mc_count = 0;
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 6c571d9f011c..6a32680dbb1b 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -79,6 +79,10 @@ static int dvb_device_open(struct inode *inode, struct file *file)
file->private_data = dvbdev;
old_fops = file->f_op;
file->f_op = fops_get(dvbdev->fops);
+ if (file->f_op == NULL) {
+ file->f_op = old_fops;
+ goto fail;
+ }
if(file->f_op->open)
err = file->f_op->open(inode,file);
if (err) {
@@ -90,6 +94,7 @@ static int dvb_device_open(struct inode *inode, struct file *file)
unlock_kernel();
return err;
}
+fail:
up_read(&minor_rwsem);
unlock_kernel();
return -ENODEV;
@@ -436,8 +441,9 @@ static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct dvb_device *dvbdev = dev_get_drvdata(dev);
- add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
+ add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
+ add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
return 0;
}
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c
index b1a9c4cdec93..199ece0d4883 100644
--- a/drivers/media/dvb/dvb-usb/af9005-fe.c
+++ b/drivers/media/dvb/dvb-usb/af9005-fe.c
@@ -220,7 +220,7 @@ static int af9005_get_post_vit_ber(struct dvb_frontend *fe,
u16 * abort_count)
{
u32 loc_cw_count = 0, loc_err_count;
- u16 loc_abort_count;
+ u16 loc_abort_count = 0;
int ret;
ret =
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index e1e9aa5c6b84..6a97a40d3dfb 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -694,7 +694,12 @@ static int af9015_read_config(struct usb_device *udev)
/* IR remote controller */
req.addr = AF9015_EEPROM_IR_MODE;
- ret = af9015_rw_udev(udev, &req);
+ /* first message will timeout often due to possible hw bug */
+ for (i = 0; i < 4; i++) {
+ ret = af9015_rw_udev(udev, &req);
+ if (!ret)
+ break;
+ }
if (ret)
goto error;
deb_info("%s: IR mode:%d\n", __func__, val);
@@ -835,18 +840,19 @@ static int af9015_read_config(struct usb_device *udev)
if (!dvb_usb_af9015_dual_mode)
af9015_config.dual_mode = 0;
- /* set buffer size according to USB port speed */
+ /* Set adapter0 buffer size according to USB port speed, adapter1 buffer
+ size can be static because it is enabled only USB2.0 */
for (i = 0; i < af9015_properties_count; i++) {
/* USB1.1 set smaller buffersize and disable 2nd adapter */
if (udev->speed == USB_SPEED_FULL) {
- af9015_properties[i].adapter->stream.u.bulk.buffersize =
- TS_USB11_MAX_PACKET_SIZE;
+ af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+ = TS_USB11_MAX_PACKET_SIZE;
/* disable 2nd adapter because we don't have
PID-filters */
af9015_config.dual_mode = 0;
} else {
- af9015_properties[i].adapter->stream.u.bulk.buffersize =
- TS_USB20_MAX_PACKET_SIZE;
+ af9015_properties[i].adapter[0].stream.u.bulk.buffersize
+ = TS_USB20_MAX_PACKET_SIZE;
}
}
@@ -1254,6 +1260,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.type = USB_BULK,
.count = 6,
.endpoint = 0x85,
+ .u = {
+ .bulk = {
+ .buffersize =
+ TS_USB20_MAX_PACKET_SIZE,
+ }
+ }
},
}
},
@@ -1353,6 +1365,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
.type = USB_BULK,
.count = 6,
.endpoint = 0x85,
+ .u = {
+ .bulk = {
+ .buffersize =
+ TS_USB20_MAX_PACKET_SIZE,
+ }
+ }
},
}
},
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index 5017f08b14a6..c6e7b4215d6b 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -41,7 +41,7 @@
static int dvb_usb_anysee_debug;
module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-int dvb_usb_anysee_delsys;
+static int dvb_usb_anysee_delsys;
module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644);
MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index 391732788911..635d30a55078 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -1393,6 +1393,9 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000H) },
/* 40 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E) },
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV801E_SE) },
+ { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) },
+ { USB_DEVICE(USB_VID_TERRATEC,
+ USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1537,7 +1540,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "DiBcom STK7700D reference design",
{ &dib0700_usb_id_table[14], NULL },
{ NULL },
- }
+ },
+
},
.rc_interval = DEFAULT_RC_INTERVAL,
@@ -1557,7 +1561,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
- .num_device_descs = 2,
+ .num_device_descs = 3,
.devices = {
{ "ASUS My Cinema U3000 Mini DVBT Tuner",
{ &dib0700_usb_id_table[23], NULL },
@@ -1566,6 +1570,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Yuan EC372S",
{ &dib0700_usb_id_table[31], NULL },
{ NULL },
+ },
+ { "Terratec Cinergy T Express",
+ { &dib0700_usb_id_table[42], NULL },
+ { NULL },
}
},
@@ -1653,7 +1661,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}
},
- .num_device_descs = 4,
+ .num_device_descs = 5,
.devices = {
{ "DiBcom STK7070PD reference design",
{ &dib0700_usb_id_table[17], NULL },
@@ -1670,6 +1678,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Hauppauge Nova-TD-500 (84xxx)",
{ &dib0700_usb_id_table[36], NULL },
{ NULL },
+ },
+ { "Terratec Cinergy DT USB XS Diversity",
+ { &dib0700_usb_id_table[43], NULL },
+ { NULL },
}
}
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index a4fca3fca5ee..0db0c06ee6f2 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -162,8 +162,10 @@
#define USB_PID_AVERMEDIA_A309 0xa309
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
+#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS 0x0060
+#define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062
#define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078
#define USB_PID_PINNACLE_EXPRESSCARD_320CX 0x022e
#define USB_PID_PINNACLE_PCTV2000E 0x022c
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index c1da962cc886..3dd6843864ed 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -187,7 +187,7 @@ int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
/* load BCM4500 firmware */
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
if (gp8psk_load_bcm4500fw(d))
- return EINVAL;
+ return -EINVAL;
return 0;
}
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
index 9b6c89e93f16..28ad609e73f4 100644
--- a/drivers/media/dvb/frontends/cx24116.c
+++ b/drivers/media/dvb/frontends/cx24116.c
@@ -369,7 +369,7 @@ static int cx24116_set_inversion(struct cx24116_state *state,
* Not all S2 mmodulation schemes are support and not all rates with
* a scheme are support. Especially, no auto detect when in S2 mode.
*/
-struct cx24116_modfec {
+static struct cx24116_modfec {
fe_delivery_system_t delivery_system;
fe_modulation_t modulation;
fe_code_rate_t fec;
@@ -1463,6 +1463,7 @@ static struct dvb_frontend_ops cx24116_ops = {
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_2G_MODULATION |
FE_CAN_QPSK | FE_CAN_RECOVER
},
diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h
index 4cb3ddd6c626..b1b76b47a14c 100644
--- a/drivers/media/dvb/frontends/cx24116.h
+++ b/drivers/media/dvb/frontends/cx24116.h
@@ -37,7 +37,8 @@ struct cx24116_config {
u8 mpg_clk_pos_pol:0x02;
};
-#if defined(CONFIG_DVB_CX24116) || defined(CONFIG_DVB_CX24116_MODULE)
+#if defined(CONFIG_DVB_CX24116) || \
+ (defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE))
extern struct dvb_frontend *cx24116_attach(
const struct cx24116_config *config,
struct i2c_adapter *i2c);
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c
index ec4e08dbc699..1e81e713df63 100644
--- a/drivers/media/dvb/frontends/drx397xD.c
+++ b/drivers/media/dvb/frontends/drx397xD.c
@@ -646,7 +646,7 @@ static int drx_tune(struct drx397xD_state *s,
u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
- int rc, df_tuner;
+ int rc, df_tuner = 0;
int a, b, c, d;
pr_debug("%s %d\n", __func__, s->config.d60);
diff --git a/drivers/media/dvb/frontends/lgdt3304.c b/drivers/media/dvb/frontends/lgdt3304.c
index 469ace5692c6..3bb0c4394f8a 100644
--- a/drivers/media/dvb/frontends/lgdt3304.c
+++ b/drivers/media/dvb/frontends/lgdt3304.c
@@ -42,7 +42,7 @@ static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len)
for (i=0; i<len-1; i+=3){
if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
- printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
+ printk("%s i2c_transfer error %d\n", __func__, err);
if (err < 0)
return err;
else
@@ -73,7 +73,7 @@ static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg)
i2cmsgs[1].buf = &buf;
if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) {
- printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
+ printk("%s i2c_transfer error %d\n", __func__, ret);
return ret;
}
@@ -94,7 +94,7 @@ static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val)
};
ret = i2c_transfer(state->i2c, &i2cmsgs, 1);
if (ret != 1) {
- printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
+ printk("%s i2c_transfer error %d\n", __func__, ret);
return ret;
}
@@ -238,7 +238,7 @@ static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_
}
if (err) {
- printk("%s error setting modulation\n", __FUNCTION__);
+ printk("%s error setting modulation\n", __func__);
} else {
state->current_modulation = param->u.vsb.modulation;
}
@@ -305,7 +305,7 @@ static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status)
}
break;
default:
- printk("%s unhandled modulation\n", __FUNCTION__);
+ printk("%s unhandled modulation\n", __func__);
}
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index cf4d8936bb83..3e08d985d6e5 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -545,9 +545,6 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
s5h1409_enable_modulation(fe, p->u.vsb.modulation);
- /* Allow the demod to settle */
- msleep(100);
-
if (fe->ops.tuner_ops.set_params) {
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -562,6 +559,10 @@ static int s5h1409_set_frontend(struct dvb_frontend *fe,
s5h1409_set_qam_interleave_mode(fe);
}
+ /* Issue a reset to the demod so it knows to resync against the
+ newly tuned frequency */
+ s5h1409_softreset(fe);
+
return 0;
}
diff --git a/drivers/media/dvb/frontends/s921_module.c b/drivers/media/dvb/frontends/s921_module.c
index 3cbb9cb2cf47..892af8c9ed57 100644
--- a/drivers/media/dvb/frontends/s921_module.c
+++ b/drivers/media/dvb/frontends/s921_module.c
@@ -136,7 +136,7 @@ static int s921_write(void *dev, u8 reg, u8 val) {
};
if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
- printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
+ printk("%s i2c_transfer error %d\n", __func__, err);
if (err < 0)
return err;
else
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c
index ced9b7ae7d50..a67d1775a43c 100644
--- a/drivers/media/dvb/frontends/stb0899_algo.c
+++ b/drivers/media/dvb/frontends/stb0899_algo.c
@@ -31,6 +31,8 @@ inline u32 stb0899_do_div(u64 n, u32 d)
return n;
}
+#if 0
+/* These functions are currently unused */
/*
* stb0899_calc_srate
* Compute symbol rate
@@ -54,7 +56,7 @@ static u32 stb0899_calc_srate(u32 master_clk, u8 *sfr)
* stb0899_get_srate
* Get the current symbol rate
*/
-u32 stb0899_get_srate(struct stb0899_state *state)
+static u32 stb0899_get_srate(struct stb0899_state *state)
{
struct stb0899_internal *internal = &state->internal;
u8 sfr[3];
@@ -63,6 +65,7 @@ u32 stb0899_get_srate(struct stb0899_state *state)
return stb0899_calc_srate(internal->master_clk, sfr);
}
+#endif
/*
* stb0899_set_srate
@@ -763,7 +766,7 @@ static void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state)
stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg);
}
-long Log2Int(int number)
+static long Log2Int(int number)
{
int i;
diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
index 528820170228..10613acf18f5 100644
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ b/drivers/media/dvb/frontends/stb0899_drv.c
@@ -134,7 +134,7 @@ static const struct stb0899_tab stb0899_dvbs2rf_tab[] = {
};
/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/
-struct stb0899_tab stb0899_quant_tab[] = {
+static struct stb0899_tab stb0899_quant_tab[] = {
{ 0, 0 },
{ 0, 100 },
{ 600, 200 },
@@ -177,7 +177,7 @@ struct stb0899_tab stb0899_quant_tab[] = {
};
/* DVB-S2 Es/N0 estimate in dB/100 vs read value */
-struct stb0899_tab stb0899_est_tab[] = {
+static struct stb0899_tab stb0899_est_tab[] = {
{ 0, 0 },
{ 0, 1 },
{ 301, 2 },
@@ -217,7 +217,7 @@ struct stb0899_tab stb0899_est_tab[] = {
{ 5721, 526017 },
};
-int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+static int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
{
int ret;
@@ -1618,6 +1618,7 @@ static struct dvb_frontend_ops stb0899_ops = {
.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_AUTO |
+ FE_CAN_2G_MODULATION |
FE_CAN_QPSK
},
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index 5506f80e180e..170720b02815 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -587,8 +587,15 @@ static int zl10353_init(struct dvb_frontend *fe)
static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
+ struct zl10353_state *state = fe->demodulator_priv;
u8 val = 0x0a;
+ if (state->config.no_tuner) {
+ /* No tuner attached to the internal I2C bus */
+ /* If set enable I2C bridge, the main I2C bus stopped hardly */
+ return 0;
+ }
+
if (enable)
val |= 0x10;
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index fd62e0b85621..4307e4e8aa34 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -120,7 +120,7 @@ static struct sms_board sms_boards[] = {
.name = "Hauppauge WinTV MiniCard",
.type = SMS_NOVA_B0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
- .lna_ctrl = 1,
+ .lna_ctrl = -1,
},
};
@@ -131,9 +131,10 @@ struct sms_board *sms_get_board(int id)
return &sms_boards[id];
}
-static int sms_set_gpio(struct smscore_device_t *coredev, u32 pin, int enable)
+static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
{
- int ret;
+ int lvl, ret;
+ u32 gpio;
struct smscore_gpio_config gpioconfig = {
.direction = SMS_GPIO_DIRECTION_OUTPUT,
.pullupdown = SMS_GPIO_PULLUPDOWN_NONE,
@@ -145,12 +146,20 @@ static int sms_set_gpio(struct smscore_device_t *coredev, u32 pin, int enable)
if (pin == 0)
return -EINVAL;
- ret = smscore_configure_gpio(coredev, pin, &gpioconfig);
+ if (pin < 0) {
+ /* inverted gpio */
+ gpio = pin * -1;
+ lvl = enable ? 0 : 1;
+ } else {
+ gpio = pin;
+ lvl = enable ? 1 : 0;
+ }
+ ret = smscore_configure_gpio(coredev, gpio, &gpioconfig);
if (ret < 0)
return ret;
- return smscore_set_gpio(coredev, pin, enable);
+ return smscore_set_gpio(coredev, gpio, lvl);
}
int sms_board_setup(struct smscore_device_t *coredev)
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index b4a0cc5dc935..c5b9c70563dc 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -316,7 +316,7 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh)
return 0;
}
-static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
@@ -567,7 +567,7 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return 0;
}
-static int av7110_vbi_reset(struct inode *inode, struct file *file)
+static int av7110_vbi_reset(struct file *file)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index f996cef79ec1..4182121d7e5d 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1493,7 +1493,7 @@ static struct saa7146_extension_ioctls ioctls[] = {
{0, 0}
};
-static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 3507463fdac9..bcbc5d41a0fe 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1337,7 +1337,7 @@ static struct stb0899_config tt3200_config = {
.tuner_set_rfsiggain = NULL
};
-struct stb6100_config tt3200_stb6100_config = {
+static struct stb6100_config tt3200_stb6100_config = {
.tuner_address = 0x60,
.refclock = 27000000,
};
@@ -1450,7 +1450,7 @@ static void frontend_init(struct budget_ci *budget_ci)
if (budget_ci->budget.dvb_frontend) {
if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
- printk("%s: No LNBP21 found!\n", __FUNCTION__);
+ printk("%s: No LNBP21 found!\n", __func__);
dvb_frontend_detach(budget_ci->budget.dvb_frontend);
budget_ci->budget.dvb_frontend = NULL;
}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 1638e1d9f538..83e9e7750c8c 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -470,6 +470,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+ budget->dvb_frontend->tuner_priv = NULL;
break;
}
break;
diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
index f546bccdb997..2663ae39b886 100644
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ b/drivers/media/dvb/ttusb-budget/Kconfig
@@ -1,6 +1,6 @@
config DVB_TTUSB_BUDGET
tristate "Technotrend/Hauppauge Nova-USB devices"
- depends on DVB_CORE && USB && I2C
+ depends on DVB_CORE && USB && I2C && PCI
select DVB_CX22700 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select DVB_VES1820 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
index d5f48a3102bd..290254ab06db 100644
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ b/drivers/media/dvb/ttusb-dec/Kconfig
@@ -1,6 +1,6 @@
config DVB_TTUSB_DEC
tristate "Technotrend/Hauppauge USB DEC devices"
- depends on DVB_CORE && USB && INPUT
+ depends on DVB_CORE && USB && INPUT && PCI
select CRC32
help
Support for external USB adapters designed by Technotrend and
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 0aa96df80fc2..d91e0638448f 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1384,7 +1384,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
static int ttusb_dec_init_stb(struct ttusb_dec *dec)
{
int result;
- unsigned int mode, model, version;
+ unsigned int mode = 0, model = 0, version = 0;
dprintk("%s\n", __func__);
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 5189c4eb439f..3315cac875e5 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -387,4 +387,23 @@ config USB_MR800
To compile this driver as a module, choose M here: the
module will be called radio-mr800.
+config RADIO_TEA5764
+ tristate "TEA5764 I2C FM radio support"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ Say Y here if you want to use the TEA5764 FM chip found in
+ EZX phones. This FM chip is present in EZX phones from Motorola,
+ connected to internal pxa I2C bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-tea5764.
+
+config RADIO_TEA5764_XTAL
+ bool "TEA5764 crystal reference"
+ depends on RADIO_TEA5764=y
+ default y
+ help
+ Say Y here if TEA5764 have a 32768 Hz crystal in circuit, say N
+ here if TEA5764 reference frequency is connected in FREQIN.
+
endif # RADIO_ADAPTERS
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index 240ec63cdafc..0f2b35b3e560 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -19,5 +19,6 @@ obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_SI470X) += radio-si470x.o
obj-$(CONFIG_USB_MR800) += radio-mr800.o
+obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 5474a22c1b22..2014ebc4e984 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -154,8 +154,8 @@ devices, that would be 76 and 91. */
static int usb_dsbr100_probe(struct usb_interface *intf,
const struct usb_device_id *id);
static void usb_dsbr100_disconnect(struct usb_interface *intf);
-static int usb_dsbr100_open(struct inode *inode, struct file *file);
-static int usb_dsbr100_close(struct inode *inode, struct file *file);
+static int usb_dsbr100_open(struct file *file);
+static int usb_dsbr100_close(struct file *file);
static int usb_dsbr100_suspend(struct usb_interface *intf,
pm_message_t message);
static int usb_dsbr100_resume(struct usb_interface *intf);
@@ -566,7 +566,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
return 0;
}
-static int usb_dsbr100_open(struct inode *inode, struct file *file)
+static int usb_dsbr100_open(struct file *file)
{
struct dsbr100_device *radio = video_drvdata(file);
int retval;
@@ -593,7 +593,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file)
return 0;
}
-static int usb_dsbr100_close(struct inode *inode, struct file *file)
+static int usb_dsbr100_close(struct file *file)
{
struct dsbr100_device *radio = video_drvdata(file);
int retval;
@@ -653,15 +653,11 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev)
}
/* File system interface */
-static const struct file_operations usb_dsbr100_fops = {
+static const struct v4l2_file_operations usb_dsbr100_fops = {
.owner = THIS_MODULE,
.open = usb_dsbr100_open,
.release = usb_dsbr100_close,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index dd6d3dfcd7d2..bfa13b8b3043 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -374,26 +374,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct rt_device rtrack_unit;
-static int rtrack_exclusive_open(struct inode *inode, struct file *file)
+static int rtrack_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &rtrack_unit.in_use) ? -EBUSY : 0;
}
-static int rtrack_exclusive_release(struct inode *inode, struct file *file)
+static int rtrack_exclusive_release(struct file *file)
{
clear_bit(0, &rtrack_unit.in_use);
return 0;
}
-static const struct file_operations rtrack_fops = {
+static const struct v4l2_file_operations rtrack_fops = {
.owner = THIS_MODULE,
.open = rtrack_exclusive_open,
.release = rtrack_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index d78489573230..5604e881e96c 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -338,26 +338,22 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
static struct az_device aztech_unit;
-static int aztech_exclusive_open(struct inode *inode, struct file *file)
+static int aztech_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &aztech_unit.in_use) ? -EBUSY : 0;
}
-static int aztech_exclusive_release(struct inode *inode, struct file *file)
+static int aztech_exclusive_release(struct file *file)
{
clear_bit(0, &aztech_unit.in_use);
return 0;
}
-static const struct file_operations aztech_fops = {
+static const struct v4l2_file_operations aztech_fops = {
.owner = THIS_MODULE,
.open = aztech_exclusive_open,
.release = aztech_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index bfd37f38b9ab..cb3075ac104c 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -529,7 +529,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
}
static int
-cadet_open(struct inode *inode, struct file *file)
+cadet_open(struct file *file)
{
users++;
if (1 == users) init_waitqueue_head(&read_queue);
@@ -537,7 +537,7 @@ cadet_open(struct inode *inode, struct file *file)
}
static int
-cadet_release(struct inode *inode, struct file *file)
+cadet_release(struct file *file)
{
users--;
if (0 == users){
@@ -557,17 +557,13 @@ cadet_poll(struct file *file, struct poll_table_struct *wait)
}
-static const struct file_operations cadet_fops = {
+static const struct v4l2_file_operations cadet_fops = {
.owner = THIS_MODULE,
.open = cadet_open,
.release = cadet_release,
.read = cadet_read,
.ioctl = video_ioctl2,
.poll = cadet_poll,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops cadet_ioctl_ops = {
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index e15bee6d7cfc..0c96bf8525b0 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -358,26 +358,22 @@ MODULE_DEVICE_TABLE( pci, gemtek_pci_id );
static int mx = 1;
-static int gemtek_pci_exclusive_open(struct inode *inode, struct file *file)
+static int gemtek_pci_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
}
-static int gemtek_pci_exclusive_release(struct inode *inode, struct file *file)
+static int gemtek_pci_exclusive_release(struct file *file)
{
clear_bit(0, &in_use);
return 0;
}
-static const struct file_operations gemtek_pci_fops = {
+static const struct v4l2_file_operations gemtek_pci_fops = {
.owner = THIS_MODULE,
.open = gemtek_pci_exclusive_open,
.release = gemtek_pci_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index e13118da307b..2b68be773f13 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -394,26 +394,22 @@ static struct v4l2_queryctrl radio_qctrl[] = {
}
};
-static int gemtek_exclusive_open(struct inode *inode, struct file *file)
+static int gemtek_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
}
-static int gemtek_exclusive_release(struct inode *inode, struct file *file)
+static int gemtek_exclusive_release(struct file *file)
{
clear_bit(0, &in_use);
return 0;
}
-static const struct file_operations gemtek_fops = {
+static const struct v4l2_file_operations gemtek_fops = {
.owner = THIS_MODULE,
.open = gemtek_exclusive_open,
.release = gemtek_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek
};
static int vidioc_querycap(struct file *file, void *priv,
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index 4bf4d007bcfa..ba3a13a90013 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -79,12 +79,12 @@ static unsigned long in_use;
static int maestro_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int maestro_exclusive_open(struct inode *inode, struct file *file)
+static int maestro_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
}
-static int maestro_exclusive_release(struct inode *inode, struct file *file)
+static int maestro_exclusive_release(struct file *file)
{
clear_bit(0, &in_use);
return 0;
@@ -110,15 +110,11 @@ static struct pci_driver maestro_r_driver = {
.remove = __devexit_p(maestro_remove),
};
-static const struct file_operations maestro_fops = {
+static const struct v4l2_file_operations maestro_fops = {
.owner = THIS_MODULE,
.open = maestro_exclusive_open,
.release = maestro_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
struct radio_device {
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index c777a17b00bc..c5dc00aa9c9f 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -100,26 +100,22 @@ static unsigned long in_use;
#define BITS2FREQ(x) ((x) * FREQ_STEP - FREQ_IF)
-static int maxiradio_exclusive_open(struct inode *inode, struct file *file)
+static int maxiradio_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
}
-static int maxiradio_exclusive_release(struct inode *inode, struct file *file)
+static int maxiradio_exclusive_release(struct file *file)
{
clear_bit(0, &in_use);
return 0;
}
-static const struct file_operations maxiradio_fops = {
+static const struct v4l2_file_operations maxiradio_fops = {
.owner = THIS_MODULE,
.open = maxiradio_exclusive_open,
.release = maxiradio_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct radio_device
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index e730eddb2bb5..fdfc7bf86b9e 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -127,8 +127,8 @@ static struct v4l2_queryctrl radio_qctrl[] = {
static int usb_amradio_probe(struct usb_interface *intf,
const struct usb_device_id *id);
static void usb_amradio_disconnect(struct usb_interface *intf);
-static int usb_amradio_open(struct inode *inode, struct file *file);
-static int usb_amradio_close(struct inode *inode, struct file *file);
+static int usb_amradio_open(struct file *file);
+static int usb_amradio_close(struct file *file);
static int usb_amradio_suspend(struct usb_interface *intf,
pm_message_t message);
static int usb_amradio_resume(struct usb_interface *intf);
@@ -194,10 +194,10 @@ static int amradio_start(struct amradio_device *radio)
return retval;
}
- mutex_unlock(&radio->lock);
-
radio->muted = 0;
+ mutex_unlock(&radio->lock);
+
return retval;
}
@@ -230,10 +230,10 @@ static int amradio_stop(struct amradio_device *radio)
return retval;
}
- mutex_unlock(&radio->lock);
-
radio->muted = 1;
+ mutex_unlock(&radio->lock);
+
return retval;
}
@@ -284,10 +284,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
return retval;
}
- mutex_unlock(&radio->lock);
-
radio->stereo = 0;
+ mutex_unlock(&radio->lock);
+
return retval;
}
@@ -500,7 +500,7 @@ static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
}
/* open device - amradio_start() and amradio_setfreq() */
-static int usb_amradio_open(struct inode *inode, struct file *file)
+static int usb_amradio_open(struct file *file)
{
struct amradio_device *radio = video_get_drvdata(video_devdata(file));
@@ -525,7 +525,7 @@ static int usb_amradio_open(struct inode *inode, struct file *file)
}
/*close device */
-static int usb_amradio_close(struct inode *inode, struct file *file)
+static int usb_amradio_close(struct file *file)
{
struct amradio_device *radio = video_get_drvdata(video_devdata(file));
int retval;
@@ -572,15 +572,11 @@ static int usb_amradio_resume(struct usb_interface *intf)
}
/* File system interface */
-static const struct file_operations usb_amradio_fops = {
+static const struct v4l2_file_operations usb_amradio_fops = {
.owner = THIS_MODULE,
.open = usb_amradio_open,
.release = usb_amradio_close,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 7704f243b6f0..2587227214bf 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -280,26 +280,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct rt_device rtrack2_unit;
-static int rtrack2_exclusive_open(struct inode *inode, struct file *file)
+static int rtrack2_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &rtrack2_unit.in_use) ? -EBUSY : 0;
}
-static int rtrack2_exclusive_release(struct inode *inode, struct file *file)
+static int rtrack2_exclusive_release(struct file *file)
{
clear_bit(0, &rtrack2_unit.in_use);
return 0;
}
-static const struct file_operations rtrack2_fops = {
+static const struct v4l2_file_operations rtrack2_fops = {
.owner = THIS_MODULE,
.open = rtrack2_exclusive_open,
.release = rtrack2_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 834d43651c70..d358e48c2422 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -280,26 +280,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct fmi_device fmi_unit;
-static int fmi_exclusive_open(struct inode *inode, struct file *file)
+static int fmi_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &fmi_unit.in_use) ? -EBUSY : 0;
}
-static int fmi_exclusive_release(struct inode *inode, struct file *file)
+static int fmi_exclusive_release(struct file *file)
{
clear_bit(0, &fmi_unit.in_use);
return 0;
}
-static const struct file_operations fmi_fops = {
+static const struct v4l2_file_operations fmi_fops = {
.owner = THIS_MODULE,
.open = fmi_exclusive_open,
.release = fmi_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index b1f47c322e02..92f17a347fa7 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -396,26 +396,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct fmr2_device fmr2_unit;
-static int fmr2_exclusive_open(struct inode *inode, struct file *file)
+static int fmr2_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &fmr2_unit.in_use) ? -EBUSY : 0;
}
-static int fmr2_exclusive_release(struct inode *inode, struct file *file)
+static int fmr2_exclusive_release(struct file *file)
{
clear_bit(0, &fmr2_unit.in_use);
return 0;
}
-static const struct file_operations fmr2_fops = {
+static const struct v4l2_file_operations fmr2_fops = {
.owner = THIS_MODULE,
.open = fmr2_exclusive_open,
.release = fmr2_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 3e1830293de5..67cbce82cb91 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -96,6 +96,8 @@
* 2008-10-20 Alexey Klimov <klimov.linux@gmail.com>
* - add support for KWorld USB FM Radio FM700
* - blacklisted KWorld radio in hid-core.c and hid-ids.h
+ * 2008-12-03 Mark Lord <mlord@pobox.com>
+ * - add support for DealExtreme USB Radio
*
* ToDo:
* - add firmware download/update support
@@ -138,6 +140,8 @@ static struct usb_device_id si470x_usb_driver_id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
/* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) },
+ /* DealExtreme USB Radio */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x10c5, 0x819a, USB_CLASS_HID, 0, 0) },
/* Terminating entry */
{ }
};
@@ -1075,7 +1079,7 @@ static unsigned int si470x_fops_poll(struct file *file,
/*
* si470x_fops_open - file open
*/
-static int si470x_fops_open(struct inode *inode, struct file *file)
+static int si470x_fops_open(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval;
@@ -1105,7 +1109,7 @@ done:
/*
* si470x_fops_release - file release
*/
-static int si470x_fops_release(struct inode *inode, struct file *file)
+static int si470x_fops_release(struct file *file)
{
struct si470x_device *radio = video_drvdata(file);
int retval = 0;
@@ -1147,15 +1151,11 @@ done:
/*
* si470x_fops - file operations interface
*/
-static const struct file_operations si470x_fops = {
+static const struct v4l2_file_operations si470x_fops = {
.owner = THIS_MODULE,
- .llseek = no_llseek,
.read = si470x_fops_read,
.poll = si470x_fops_poll,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.open = si470x_fops_open,
.release = si470x_fops_release,
};
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
new file mode 100644
index 000000000000..4d35308fc1ff
--- /dev/null
+++ b/drivers/media/radio/radio-tea5764.c
@@ -0,0 +1,634 @@
+/*
+ * driver/media/radio/radio-tea5764.c
+ *
+ * Driver for TEA5764 radio chip for linux 2.6.
+ * This driver is for TEA5764 chip from NXP, used in EZX phones from Motorola.
+ * The I2C protocol is used for communicate with chip.
+ *
+ * Based in radio-tea5761.c Copyright (C) 2005 Nokia Corporation
+ *
+ * Copyright (c) 2008 Fabio Belavenuto <belavenuto@gmail.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
+ *
+ * History:
+ * 2008-12-06 Fabio Belavenuto <belavenuto@gmail.com>
+ * initial code
+ *
+ * TODO:
+ * add platform_data support for IRQs platform dependencies
+ * add RDS support
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h> /* Initdata */
+#include <linux/videodev2.h> /* kernel radio structs */
+#include <linux/i2c.h> /* I2C */
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/version.h> /* for KERNEL_VERSION MACRO */
+
+#define DRIVER_VERSION "v0.01"
+#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
+
+#define DRIVER_AUTHOR "Fabio Belavenuto <belavenuto@gmail.com>"
+#define DRIVER_DESC "A driver for the TEA5764 radio chip for EZX Phones."
+
+#define PINFO(format, ...)\
+ printk(KERN_INFO KBUILD_MODNAME ": "\
+ DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
+#define PWARN(format, ...)\
+ printk(KERN_WARNING KBUILD_MODNAME ": "\
+ DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
+# define PDEBUG(format, ...)\
+ printk(KERN_DEBUG KBUILD_MODNAME ": "\
+ DRIVER_VERSION ": " format "\n", ## __VA_ARGS__)
+
+/* Frequency limits in MHz -- these are European values. For Japanese
+devices, that would be 76000 and 91000. */
+#define FREQ_MIN 87500
+#define FREQ_MAX 108000
+#define FREQ_MUL 16
+
+/* TEA5764 registers */
+#define TEA5764_MANID 0x002b
+#define TEA5764_CHIPID 0x5764
+
+#define TEA5764_INTREG_BLMSK 0x0001
+#define TEA5764_INTREG_FRRMSK 0x0002
+#define TEA5764_INTREG_LEVMSK 0x0008
+#define TEA5764_INTREG_IFMSK 0x0010
+#define TEA5764_INTREG_BLMFLAG 0x0100
+#define TEA5764_INTREG_FRRFLAG 0x0200
+#define TEA5764_INTREG_LEVFLAG 0x0800
+#define TEA5764_INTREG_IFFLAG 0x1000
+
+#define TEA5764_FRQSET_SUD 0x8000
+#define TEA5764_FRQSET_SM 0x4000
+
+#define TEA5764_TNCTRL_PUPD1 0x8000
+#define TEA5764_TNCTRL_PUPD0 0x4000
+#define TEA5764_TNCTRL_BLIM 0x2000
+#define TEA5764_TNCTRL_SWPM 0x1000
+#define TEA5764_TNCTRL_IFCTC 0x0800
+#define TEA5764_TNCTRL_AFM 0x0400
+#define TEA5764_TNCTRL_SMUTE 0x0200
+#define TEA5764_TNCTRL_SNC 0x0100
+#define TEA5764_TNCTRL_MU 0x0080
+#define TEA5764_TNCTRL_SSL1 0x0040
+#define TEA5764_TNCTRL_SSL0 0x0020
+#define TEA5764_TNCTRL_HLSI 0x0010
+#define TEA5764_TNCTRL_MST 0x0008
+#define TEA5764_TNCTRL_SWP 0x0004
+#define TEA5764_TNCTRL_DTC 0x0002
+#define TEA5764_TNCTRL_AHLSI 0x0001
+
+#define TEA5764_TUNCHK_LEVEL(x) (((x) & 0x00F0) >> 4)
+#define TEA5764_TUNCHK_IFCNT(x) (((x) & 0xFE00) >> 9)
+#define TEA5764_TUNCHK_TUNTO 0x0100
+#define TEA5764_TUNCHK_LD 0x0008
+#define TEA5764_TUNCHK_STEREO 0x0004
+
+#define TEA5764_TESTREG_TRIGFR 0x0800
+
+struct tea5764_regs {
+ u16 intreg; /* INTFLAG & INTMSK */
+ u16 frqset; /* FRQSETMSB & FRQSETLSB */
+ u16 tnctrl; /* TNCTRL1 & TNCTRL2 */
+ u16 frqchk; /* FRQCHKMSB & FRQCHKLSB */
+ u16 tunchk; /* IFCHK & LEVCHK */
+ u16 testreg; /* TESTBITS & TESTMODE */
+ u16 rdsstat; /* RDSSTAT1 & RDSSTAT2 */
+ u16 rdslb; /* RDSLBMSB & RDSLBLSB */
+ u16 rdspb; /* RDSPBMSB & RDSPBLSB */
+ u16 rdsbc; /* RDSBBC & RDSGBC */
+ u16 rdsctrl; /* RDSCTRL1 & RDSCTRL2 */
+ u16 rdsbbl; /* PAUSEDET & RDSBBL */
+ u16 manid; /* MANID1 & MANID2 */
+ u16 chipid; /* CHIPID1 & CHIPID2 */
+} __attribute__ ((packed));
+
+struct tea5764_write_regs {
+ u8 intreg; /* INTMSK */
+ u16 frqset; /* FRQSETMSB & FRQSETLSB */
+ u16 tnctrl; /* TNCTRL1 & TNCTRL2 */
+ u16 testreg; /* TESTBITS & TESTMODE */
+ u16 rdsctrl; /* RDSCTRL1 & RDSCTRL2 */
+ u16 rdsbbl; /* PAUSEDET & RDSBBL */
+} __attribute__ ((packed));
+
+#ifndef RADIO_TEA5764_XTAL
+#define RADIO_TEA5764_XTAL 1
+#endif
+
+static int radio_nr = -1;
+static int use_xtal = RADIO_TEA5764_XTAL;
+
+struct tea5764_device {
+ struct i2c_client *i2c_client;
+ struct video_device *videodev;
+ struct tea5764_regs regs;
+ struct mutex mutex;
+ int users;
+};
+
+/* I2C code related */
+int tea5764_i2c_read(struct tea5764_device *radio)
+{
+ int i;
+ u16 *p = (u16 *) &radio->regs;
+
+ struct i2c_msg msgs[1] = {
+ { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs),
+ (void *)&radio->regs },
+ };
+ if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
+ return -EIO;
+ for (i = 0; i < sizeof(struct tea5764_regs) / sizeof(u16); i++)
+ p[i] = __be16_to_cpu(p[i]);
+
+ return 0;
+}
+
+int tea5764_i2c_write(struct tea5764_device *radio)
+{
+ struct tea5764_write_regs wr;
+ struct tea5764_regs *r = &radio->regs;
+ struct i2c_msg msgs[1] = {
+ { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr },
+ };
+ wr.intreg = r->intreg & 0xff;
+ wr.frqset = __cpu_to_be16(r->frqset);
+ wr.tnctrl = __cpu_to_be16(r->tnctrl);
+ wr.testreg = __cpu_to_be16(r->testreg);
+ wr.rdsctrl = __cpu_to_be16(r->rdsctrl);
+ wr.rdsbbl = __cpu_to_be16(r->rdsbbl);
+ if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+/* V4L2 code related */
+static struct v4l2_queryctrl radio_qctrl[] = {
+ {
+ .id = V4L2_CID_AUDIO_MUTE,
+ .name = "Mute",
+ .minimum = 0,
+ .maximum = 1,
+ .default_value = 1,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ }
+};
+
+static void tea5764_power_up(struct tea5764_device *radio)
+{
+ struct tea5764_regs *r = &radio->regs;
+
+ if (!(r->tnctrl & TEA5764_TNCTRL_PUPD0)) {
+ r->tnctrl &= ~(TEA5764_TNCTRL_AFM | TEA5764_TNCTRL_MU |
+ TEA5764_TNCTRL_HLSI);
+ if (!use_xtal)
+ r->testreg |= TEA5764_TESTREG_TRIGFR;
+ else
+ r->testreg &= ~TEA5764_TESTREG_TRIGFR;
+
+ r->tnctrl |= TEA5764_TNCTRL_PUPD0;
+ tea5764_i2c_write(radio);
+ }
+}
+
+static void tea5764_power_down(struct tea5764_device *radio)
+{
+ struct tea5764_regs *r = &radio->regs;
+
+ if (r->tnctrl & TEA5764_TNCTRL_PUPD0) {
+ r->tnctrl &= ~TEA5764_TNCTRL_PUPD0;
+ tea5764_i2c_write(radio);
+ }
+}
+
+static void tea5764_set_freq(struct tea5764_device *radio, int freq)
+{
+ struct tea5764_regs *r = &radio->regs;
+
+ /* formula: (freq [+ or -] 225000) / 8192 */
+ if (r->tnctrl & TEA5764_TNCTRL_HLSI)
+ r->frqset = (freq + 225000) / 8192;
+ else
+ r->frqset = (freq - 225000) / 8192;
+}
+
+static int tea5764_get_freq(struct tea5764_device *radio)
+{
+ struct tea5764_regs *r = &radio->regs;
+
+ if (r->tnctrl & TEA5764_TNCTRL_HLSI)
+ return (r->frqchk * 8192) - 225000;
+ else
+ return (r->frqchk * 8192) + 225000;
+}
+
+/* tune an frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
+static void tea5764_tune(struct tea5764_device *radio, int freq)
+{
+ tea5764_set_freq(radio, freq);
+ if (tea5764_i2c_write(radio))
+ PWARN("Could not set frequency!");
+}
+
+static void tea5764_set_audout_mode(struct tea5764_device *radio, int audmode)
+{
+ struct tea5764_regs *r = &radio->regs;
+ int tnctrl = r->tnctrl;
+
+ if (audmode == V4L2_TUNER_MODE_MONO)
+ r->tnctrl |= TEA5764_TNCTRL_MST;
+ else
+ r->tnctrl &= ~TEA5764_TNCTRL_MST;
+ if (tnctrl != r->tnctrl)
+ tea5764_i2c_write(radio);
+}
+
+static int tea5764_get_audout_mode(struct tea5764_device *radio)
+{
+ struct tea5764_regs *r = &radio->regs;
+
+ if (r->tnctrl & TEA5764_TNCTRL_MST)
+ return V4L2_TUNER_MODE_MONO;
+ else
+ return V4L2_TUNER_MODE_STEREO;
+}
+
+static void tea5764_mute(struct tea5764_device *radio, int on)
+{
+ struct tea5764_regs *r = &radio->regs;
+ int tnctrl = r->tnctrl;
+
+ if (on)
+ r->tnctrl |= TEA5764_TNCTRL_MU;
+ else
+ r->tnctrl &= ~TEA5764_TNCTRL_MU;
+ if (tnctrl != r->tnctrl)
+ tea5764_i2c_write(radio);
+}
+
+static int tea5764_is_muted(struct tea5764_device *radio)
+{
+ return radio->regs.tnctrl & TEA5764_TNCTRL_MU;
+}
+
+/* V4L2 vidioc */
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+ struct video_device *dev = radio->videodev;
+
+ strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
+ strlcpy(v->card, dev->name, sizeof(v->card));
+ snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id);
+ v->version = RADIO_VERSION;
+ v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+ struct tea5764_regs *r = &radio->regs;
+
+ if (v->index > 0)
+ return -EINVAL;
+
+ memset(v, 0, sizeof(v));
+ strcpy(v->name, "FM");
+ v->type = V4L2_TUNER_RADIO;
+ tea5764_i2c_read(radio);
+ v->rangelow = FREQ_MIN * FREQ_MUL;
+ v->rangehigh = FREQ_MAX * FREQ_MUL;
+ v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+ if (r->tunchk & TEA5764_TUNCHK_STEREO)
+ v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ v->audmode = tea5764_get_audout_mode(radio);
+ v->signal = TEA5764_TUNCHK_LEVEL(r->tunchk) * 0xffff / 0xf;
+ v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk);
+
+ return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *v)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+
+ if (v->index > 0)
+ return -EINVAL;
+
+ tea5764_set_audout_mode(radio, v->audmode);
+ return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+
+ if (f->tuner != 0)
+ return -EINVAL;
+ if (f->frequency == 0) {
+ /* We special case this as a power down control. */
+ tea5764_power_down(radio);
+ }
+ if (f->frequency < (FREQ_MIN * FREQ_MUL))
+ return -EINVAL;
+ if (f->frequency > (FREQ_MAX * FREQ_MUL))
+ return -EINVAL;
+ tea5764_power_up(radio);
+ tea5764_tune(radio, (f->frequency * 125) / 2);
+ return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+ struct tea5764_regs *r = &radio->regs;
+
+ tea5764_i2c_read(radio);
+ memset(f, 0, sizeof(f));
+ f->type = V4L2_TUNER_RADIO;
+ if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
+ f->frequency = (tea5764_get_freq(radio) * 2) / 125;
+ else
+ f->frequency = 0;
+
+ return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+ if (qc->id && qc->id == radio_qctrl[i].id) {
+ memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ tea5764_i2c_read(radio);
+ ctrl->value = tea5764_is_muted(radio) ? 1 : 0;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUDIO_MUTE:
+ tea5764_mute(radio, ctrl->value);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+ if (i != 0)
+ return -EINVAL;
+ return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ if (a->index > 1)
+ return -EINVAL;
+
+ strcpy(a->name, "Radio");
+ a->capability = V4L2_AUDCAP_STEREO;
+ return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv,
+ struct v4l2_audio *a)
+{
+ if (a->index != 0)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int tea5764_open(struct file *file)
+{
+ /* Currently we support only one device */
+ int minor = video_devdata(file)->minor;
+ struct tea5764_device *radio = video_drvdata(file);
+
+ if (radio->videodev->minor != minor)
+ return -ENODEV;
+
+ mutex_lock(&radio->mutex);
+ /* Only exclusive access */
+ if (radio->users) {
+ mutex_unlock(&radio->mutex);
+ return -EBUSY;
+ }
+ radio->users++;
+ mutex_unlock(&radio->mutex);
+ file->private_data = radio;
+ return 0;
+}
+
+static int tea5764_close(struct file *file)
+{
+ struct tea5764_device *radio = video_drvdata(file);
+
+ if (!radio)
+ return -ENODEV;
+ mutex_lock(&radio->mutex);
+ radio->users--;
+ mutex_unlock(&radio->mutex);
+ return 0;
+}
+
+/* File system interface */
+static const struct v4l2_file_operations tea5764_fops = {
+ .owner = THIS_MODULE,
+ .open = tea5764_open,
+ .release = tea5764_close,
+ .ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+};
+
+/* V4L2 interface */
+static struct video_device tea5764_radio_template = {
+ .name = "TEA5764 FM-Radio",
+ .fops = &tea5764_fops,
+ .ioctl_ops = &tea5764_ioctl_ops,
+ .release = video_device_release,
+};
+
+/* I2C probe: check if the device exists and register with v4l if it is */
+static int __devinit tea5764_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct tea5764_device *radio;
+ struct tea5764_regs *r;
+ int ret;
+
+ PDEBUG("probe");
+ radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL);
+ if (!radio)
+ return -ENOMEM;
+
+ mutex_init(&radio->mutex);
+ radio->i2c_client = client;
+ ret = tea5764_i2c_read(radio);
+ if (ret)
+ goto errfr;
+ r = &radio->regs;
+ PDEBUG("chipid = %04X, manid = %04X", r->chipid, r->manid);
+ if (r->chipid != TEA5764_CHIPID ||
+ (r->manid & 0x0fff) != TEA5764_MANID) {
+ PWARN("This chip is not a TEA5764!");
+ ret = -EINVAL;
+ goto errfr;
+ }
+
+ radio->videodev = video_device_alloc();
+ if (!(radio->videodev)) {
+ ret = -ENOMEM;
+ goto errfr;
+ }
+ memcpy(radio->videodev, &tea5764_radio_template,
+ sizeof(tea5764_radio_template));
+
+ i2c_set_clientdata(client, radio);
+ video_set_drvdata(radio->videodev, radio);
+
+ ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+ if (ret < 0) {
+ PWARN("Could not register video device!");
+ goto errrel;
+ }
+
+ /* initialize and power off the chip */
+ tea5764_i2c_read(radio);
+ tea5764_set_audout_mode(radio, V4L2_TUNER_MODE_STEREO);
+ tea5764_mute(radio, 1);
+ tea5764_power_down(radio);
+
+ PINFO("registered.");
+ return 0;
+errrel:
+ video_device_release(radio->videodev);
+errfr:
+ kfree(radio);
+ return ret;
+}
+
+static int __devexit tea5764_i2c_remove(struct i2c_client *client)
+{
+ struct tea5764_device *radio = i2c_get_clientdata(client);
+
+ PDEBUG("remove");
+ if (radio) {
+ tea5764_power_down(radio);
+ video_unregister_device(radio->videodev);
+ kfree(radio);
+ }
+ return 0;
+}
+
+/* I2C subsystem interface */
+static const struct i2c_device_id tea5764_id[] = {
+ { "radio-tea5764", 0 },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(i2c, tea5764_id);
+
+static struct i2c_driver tea5764_i2c_driver = {
+ .driver = {
+ .name = "radio-tea5764",
+ .owner = THIS_MODULE,
+ },
+ .probe = tea5764_i2c_probe,
+ .remove = __devexit_p(tea5764_i2c_remove),
+ .id_table = tea5764_id,
+};
+
+/* init the driver */
+static int __init tea5764_init(void)
+{
+ int ret = i2c_add_driver(&tea5764_i2c_driver);
+
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": "
+ DRIVER_DESC "\n");
+ return ret;
+}
+
+/* cleanup the driver */
+static void __exit tea5764_exit(void)
+{
+ i2c_del_driver(&tea5764_i2c_driver);
+}
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(use_xtal, int, 1);
+MODULE_PARM_DESC(use_xtal, "Chip have a xtal connected in board");
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "video4linux device number to use");
+
+module_init(tea5764_init);
+module_exit(tea5764_exit);
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 0abb186a9473..0798d71abd00 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -352,26 +352,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct tt_device terratec_unit;
-static int terratec_exclusive_open(struct inode *inode, struct file *file)
+static int terratec_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &terratec_unit.in_use) ? -EBUSY : 0;
}
-static int terratec_exclusive_release(struct inode *inode, struct file *file)
+static int terratec_exclusive_release(struct file *file)
{
clear_bit(0, &terratec_unit.in_use);
return 0;
}
-static const struct file_operations terratec_fops = {
+static const struct v4l2_file_operations terratec_fops = {
.owner = THIS_MODULE,
.open = terratec_exclusive_open,
.release = terratec_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index e7b111fcd105..bdf9cb6a75f4 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -337,26 +337,22 @@ static int vidioc_s_audio(struct file *file, void *priv,
return 0;
}
-static int trust_exclusive_open(struct inode *inode, struct file *file)
+static int trust_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &in_use) ? -EBUSY : 0;
}
-static int trust_exclusive_release(struct inode *inode, struct file *file)
+static int trust_exclusive_release(struct file *file)
{
clear_bit(0, &in_use);
return 0;
}
-static const struct file_operations trust_fops = {
+static const struct v4l2_file_operations trust_fops = {
.owner = THIS_MODULE,
.open = trust_exclusive_open,
.release = trust_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops trust_ioctl_ops = {
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index 952ec35a8415..5c3b319dab37 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -330,26 +330,22 @@ static struct typhoon_device typhoon_unit =
.mutefreq = CONFIG_RADIO_TYPHOON_MUTEFREQ,
};
-static int typhoon_exclusive_open(struct inode *inode, struct file *file)
+static int typhoon_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &typhoon_unit.in_use) ? -EBUSY : 0;
}
-static int typhoon_exclusive_release(struct inode *inode, struct file *file)
+static int typhoon_exclusive_release(struct file *file)
{
clear_bit(0, &typhoon_unit.in_use);
return 0;
}
-static const struct file_operations typhoon_fops = {
+static const struct v4l2_file_operations typhoon_fops = {
.owner = THIS_MODULE,
.open = typhoon_exclusive_open,
.release = typhoon_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 15b10bad6796..d2ac17eeec5f 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -401,27 +401,23 @@ static int vidioc_s_audio(struct file *file, void *priv,
static struct zol_device zoltrix_unit;
-static int zoltrix_exclusive_open(struct inode *inode, struct file *file)
+static int zoltrix_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &zoltrix_unit.in_use) ? -EBUSY : 0;
}
-static int zoltrix_exclusive_release(struct inode *inode, struct file *file)
+static int zoltrix_exclusive_release(struct file *file)
{
clear_bit(0, &zoltrix_unit.in_use);
return 0;
}
-static const struct file_operations zoltrix_fops =
+static const struct v4l2_file_operations zoltrix_fops =
{
.owner = THIS_MODULE,
.open = zoltrix_exclusive_open,
.release = zoltrix_exclusive_release,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 1611c33b1aee..72f6d03d2d8f 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -12,7 +12,10 @@ omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-subdev.o
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-compat-ioctl32.o v4l2-int-device.o
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
+ifeq ($(CONFIG_COMPAT),y)
+ obj-$(CONFIG_VIDEO_DEV) += v4l2-compat-ioctl32.o
+endif
obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 2ba6abd92b6f..d137bac84511 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -396,7 +396,7 @@ out_up:
return ret;
}
-static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct ar_device *ar = video_get_drvdata(dev);
@@ -539,7 +539,7 @@ static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int ar_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+static long ar_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
return video_usercopy(file, cmd, arg, ar_do_ioctl);
@@ -744,27 +744,23 @@ void ar_release(struct video_device *vfd)
****************************************************************************/
static struct ar_device ardev;
-static int ar_exclusive_open(struct inode *inode, struct file *file)
+static int ar_exclusive_open(struct file *file)
{
return test_and_set_bit(0, &ardev.in_use) ? -EBUSY : 0;
}
-static int ar_exclusive_release(struct inode *inode, struct file *file)
+static int ar_exclusive_release(struct file *file)
{
clear_bit(0, &ardev.in_use);
return 0;
}
-static const struct file_operations ar_fops = {
+static const struct v4l2_file_operations ar_fops = {
.owner = THIS_MODULE,
.open = ar_exclusive_open,
.release = ar_exclusive_release,
.read = ar_read,
.ioctl = ar_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device ar_template = {
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 9ec4cec2e52d..c71f394fc0ea 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -2039,7 +2039,7 @@ static int bttv_log_status(struct file *file, void *f)
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int bttv_g_register(struct file *file, void *f,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
@@ -2047,18 +2047,19 @@ static int bttv_g_register(struct file *file, void *f,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
/* bt848 has a 12-bit register space */
reg->reg &= 0xfff;
reg->val = btread(reg->reg);
+ reg->size = 1;
return 0;
}
static int bttv_s_register(struct file *file, void *f,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
@@ -2066,7 +2067,7 @@ static int bttv_s_register(struct file *file, void *f,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
/* bt848 has a 12-bit register space */
@@ -3208,9 +3209,9 @@ err:
return POLLERR;
}
-static int bttv_open(struct inode *inode, struct file *file)
+static int bttv_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct bttv *btv = NULL;
struct bttv_fh *fh;
enum v4l2_buf_type type = 0;
@@ -3291,7 +3292,7 @@ static int bttv_open(struct inode *inode, struct file *file)
return 0;
}
-static int bttv_release(struct inode *inode, struct file *file)
+static int bttv_release(struct file *file)
{
struct bttv_fh *fh = file->private_data;
struct bttv *btv = fh->btv;
@@ -3346,14 +3347,12 @@ bttv_mmap(struct file *file, struct vm_area_struct *vma)
return videobuf_mmap_mapper(bttv_queue(fh),vma);
}
-static const struct file_operations bttv_fops =
+static const struct v4l2_file_operations bttv_fops =
{
.owner = THIS_MODULE,
.open = bttv_open,
.release = bttv_release,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
.read = bttv_read,
.mmap = bttv_mmap,
.poll = bttv_poll,
@@ -3422,9 +3421,9 @@ static struct video_device bttv_video_template = {
/* ----------------------------------------------------------------------- */
/* radio interface */
-static int radio_open(struct inode *inode, struct file *file)
+static int radio_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct bttv *btv = NULL;
struct bttv_fh *fh;
unsigned int i;
@@ -3467,12 +3466,13 @@ static int radio_open(struct inode *inode, struct file *file)
return 0;
}
-static int radio_release(struct inode *inode, struct file *file)
+static int radio_release(struct file *file)
{
struct bttv_fh *fh = file->private_data;
struct bttv *btv = fh->btv;
struct rds_command cmd;
+ v4l2_prio_close(&btv->prio,&fh->prio);
file->private_data = NULL;
kfree(fh);
@@ -3633,15 +3633,13 @@ static unsigned int radio_poll(struct file *file, poll_table *wait)
return cmd.result;
}
-static const struct file_operations radio_fops =
+static const struct v4l2_file_operations radio_fops =
{
.owner = THIS_MODULE,
.open = radio_open,
.read = radio_read,
.release = radio_release,
- .compat_ioctl = v4l_compat_ioctl32,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
.poll = radio_poll,
};
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index 17f80d03f38e..10dbd4a11b30 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -706,7 +706,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
* Video4linux interfacing
*/
-static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -863,7 +863,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int qcam_ioctl(struct inode *inode, struct file *file,
+static long qcam_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, qcam_do_ioctl);
@@ -893,7 +893,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
return len;
}
-static int qcam_exclusive_open(struct inode *inode, struct file *file)
+static int qcam_exclusive_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -901,7 +901,7 @@ static int qcam_exclusive_open(struct inode *inode, struct file *file)
return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
}
-static int qcam_exclusive_release(struct inode *inode, struct file *file)
+static int qcam_exclusive_release(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -910,16 +910,12 @@ static int qcam_exclusive_release(struct inode *inode, struct file *file)
return 0;
}
-static const struct file_operations qcam_fops = {
+static const struct v4l2_file_operations qcam_fops = {
.owner = THIS_MODULE,
.open = qcam_exclusive_open,
.release = qcam_exclusive_release,
.ioctl = qcam_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = qcam_read,
- .llseek = no_llseek,
};
static struct video_device qcam_template=
{
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 21c71eb085db..85cf1778827a 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -500,7 +500,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
* Video4linux interfacing
*/
-static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -665,7 +665,7 @@ static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int qcam_ioctl(struct inode *inode, struct file *file,
+static long qcam_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, qcam_do_ioctl);
@@ -687,7 +687,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
return len;
}
-static int qcam_exclusive_open(struct inode *inode, struct file *file)
+static int qcam_exclusive_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -695,7 +695,7 @@ static int qcam_exclusive_open(struct inode *inode, struct file *file)
return test_and_set_bit(0, &qcam->in_use) ? -EBUSY : 0;
}
-static int qcam_exclusive_release(struct inode *inode, struct file *file)
+static int qcam_exclusive_release(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct qcam_device *qcam = (struct qcam_device *)dev;
@@ -705,16 +705,12 @@ static int qcam_exclusive_release(struct inode *inode, struct file *file)
}
/* video device template */
-static const struct file_operations qcam_fops = {
+static const struct v4l2_file_operations qcam_fops = {
.owner = THIS_MODULE,
.open = qcam_exclusive_open,
.release = qcam_exclusive_release,
.ioctl = qcam_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = qcam_read,
- .llseek = no_llseek,
};
static struct video_device qcam_template=
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 1740b9ebdcef..46fd573a4f15 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -569,7 +569,6 @@ static int cafe_smbus_setup(struct cafe_camera *cam)
cafe_smbus_enable_irq(cam);
adap->id = I2C_HW_SMBUS_CAFE;
- adap->class = I2C_CLASS_CAM_DIGITAL;
adap->owner = THIS_MODULE;
adap->client_register = cafe_smbus_attach;
adap->client_unregister = cafe_smbus_detach;
@@ -859,7 +858,7 @@ static int __cafe_cam_reset(struct cafe_camera *cam)
*/
static int cafe_cam_init(struct cafe_camera *cam)
{
- struct v4l2_chip_ident chip = { V4L2_CHIP_MATCH_I2C_ADDR, 0, 0, 0 };
+ struct v4l2_dbg_chip_ident chip;
int ret;
mutex_lock(&cam->s_mutex);
@@ -869,8 +868,9 @@ static int cafe_cam_init(struct cafe_camera *cam)
ret = __cafe_cam_reset(cam);
if (ret)
goto out;
- chip.match_chip = cam->sensor->addr;
- ret = __cafe_cam_cmd(cam, VIDIOC_G_CHIP_IDENT, &chip);
+ chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
+ chip.match.addr = cam->sensor->addr;
+ ret = __cafe_cam_cmd(cam, VIDIOC_DBG_G_CHIP_IDENT, &chip);
if (ret)
goto out;
cam->sensor_type = chip.ident;
@@ -1472,11 +1472,11 @@ static int cafe_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
-static int cafe_v4l_open(struct inode *inode, struct file *filp)
+static int cafe_v4l_open(struct file *filp)
{
struct cafe_camera *cam;
- cam = cafe_find_dev(iminor(inode));
+ cam = cafe_find_dev(video_devdata(filp)->minor);
if (cam == NULL)
return -ENODEV;
filp->private_data = cam;
@@ -1494,7 +1494,7 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp)
}
-static int cafe_v4l_release(struct inode *inode, struct file *filp)
+static int cafe_v4l_release(struct file *filp)
{
struct cafe_camera *cam = filp->private_data;
@@ -1759,7 +1759,7 @@ static void cafe_v4l_dev_release(struct video_device *vd)
* clone it for specific real devices.
*/
-static const struct file_operations cafe_v4l_fops = {
+static const struct v4l2_file_operations cafe_v4l_fops = {
.owner = THIS_MODULE,
.open = cafe_v4l_open,
.release = cafe_v4l_release,
@@ -1767,7 +1767,6 @@ static const struct file_operations cafe_v4l_fops = {
.poll = cafe_v4l_poll,
.mmap = cafe_v4l_mmap,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 028a400d2453..c3b0c8c63c76 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -3148,7 +3148,7 @@ static void put_cam(struct cpia_camera_ops* ops)
}
/* ------------------------- V4L interface --------------------- */
-static int cpia_open(struct inode *inode, struct file *file)
+static int cpia_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct cam_data *cam = video_get_drvdata(dev);
@@ -3225,7 +3225,7 @@ static int cpia_open(struct inode *inode, struct file *file)
return err;
}
-static int cpia_close(struct inode *inode, struct file *file)
+static int cpia_close(struct file *file)
{
struct video_device *dev = file->private_data;
struct cam_data *cam = video_get_drvdata(dev);
@@ -3333,7 +3333,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
return cam->decompressed_frame.count;
}
-static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = file->private_data;
struct cam_data *cam = video_get_drvdata(dev);
@@ -3720,7 +3720,7 @@ static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return retval;
}
-static int cpia_ioctl(struct inode *inode, struct file *file,
+static long cpia_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, cpia_do_ioctl);
@@ -3780,17 +3780,13 @@ static int cpia_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
-static const struct file_operations cpia_fops = {
+static const struct v4l2_file_operations cpia_fops = {
.owner = THIS_MODULE,
.open = cpia_open,
.release = cpia_close,
.read = cpia_read,
.mmap = cpia_mmap,
.ioctl = cpia_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device cpia_template = {
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 3c2d7eac1197..9c25894fdd8e 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -239,7 +239,7 @@ static struct v4l2_queryctrl controls[] = {
* cpia2_open
*
*****************************************************************************/
-static int cpia2_open(struct inode *inode, struct file *file)
+static int cpia2_open(struct file *file)
{
struct camera_data *cam = video_drvdata(file);
int retval = 0;
@@ -302,7 +302,7 @@ err_return:
* cpia2_close
*
*****************************************************************************/
-static int cpia2_close(struct inode *inode, struct file *file)
+static int cpia2_close(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct camera_data *cam = video_get_drvdata(dev);
@@ -1572,10 +1572,10 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
* cpia2_ioctl
*
*****************************************************************************/
-static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct camera_data *cam = video_drvdata(file);
- int retval = 0;
+ long retval = 0;
if (!cam)
return -ENOTTY;
@@ -1841,7 +1841,7 @@ static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return retval;
}
-static int cpia2_ioctl(struct inode *inode, struct file *file,
+static long cpia2_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, cpia2_do_ioctl);
@@ -1912,17 +1912,13 @@ static void reset_camera_struct_v4l(struct camera_data *cam)
/***
* The v4l video device structure initialized for this device
***/
-static const struct file_operations fops_template = {
+static const struct v4l2_file_operations fops_template = {
.owner = THIS_MODULE,
.open = cpia2_open,
.release = cpia2_close,
.read = cpia2_v4l_read,
.poll = cpia2_v4l_poll,
.ioctl = cpia2_ioctl,
- .llseek = no_llseek,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.mmap = cpia2_mmap,
};
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c
index 70fcd0d5de13..87e91072627a 100644
--- a/drivers/media/video/cs5345.c
+++ b/drivers/media/video/cs5345.c
@@ -18,7 +18,6 @@
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
@@ -95,25 +94,24 @@ static int cs5345_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cs5345_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ reg->size = 1;
reg->val = cs5345_read(sd, reg->reg & 0x1f);
return 0;
}
-static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -122,7 +120,7 @@ static int cs5345_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
}
#endif
-static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int cs5345_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index cb65d519cf78..7292a6316e63 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -102,7 +102,7 @@ static int cs53l32a_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
return 0;
}
-static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 425271a29517..055f6e004b2d 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -552,7 +552,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
}
}
-int cx18_v4l2_close(struct inode *inode, struct file *filp)
+int cx18_v4l2_close(struct file *filp)
{
struct cx18_open_id *id = filp->private_data;
struct cx18 *cx = id->cx;
@@ -650,12 +650,12 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
return 0;
}
-int cx18_v4l2_open(struct inode *inode, struct file *filp)
+int cx18_v4l2_open(struct file *filp)
{
int res, x, y = 0;
struct cx18 *cx = NULL;
struct cx18_stream *s = NULL;
- int minor = iminor(inode);
+ int minor = video_devdata(filp)->minor;
/* Find which card this open was on */
spin_lock(&cx18_cards_lock);
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h
index 46da0282fc7d..92e2d5dab936 100644
--- a/drivers/media/video/cx18/cx18-fileops.h
+++ b/drivers/media/video/cx18/cx18-fileops.h
@@ -22,12 +22,12 @@
*/
/* Testing/Debugging */
-int cx18_v4l2_open(struct inode *inode, struct file *filp);
+int cx18_v4l2_open(struct file *filp);
ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
loff_t *pos);
ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
loff_t *pos);
-int cx18_v4l2_close(struct inode *inode, struct file *filp);
+int cx18_v4l2_close(struct file *filp);
unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
int cx18_start_capture(struct cx18_open_id *id);
void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 8941f58bed7f..83e1c6333126 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -242,7 +242,7 @@ int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg)
return retval;
}
}
- if (cmd != VIDIOC_G_CHIP_IDENT)
+ if (cmd != VIDIOC_DBG_G_CHIP_IDENT)
CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n",
addr, cmd);
return -ENODEV;
@@ -268,17 +268,6 @@ static int cx18_i2c_id_addr(struct cx18 *cx, u32 id)
return retval;
}
-/* Find the i2c device name matching the DRIVERID */
-static const char *cx18_i2c_id_name(u32 id)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
- if (hw_driverids[i] == id)
- return hw_devicenames[i];
- return "unknown device";
-}
-
/* Find the i2c device name matching the CX18_HW_ flag */
static const char *cx18_i2c_hw_name(u32 hw)
{
@@ -326,21 +315,6 @@ int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
return cx18_call_i2c_client(cx, addr, cmd, arg);
}
-/* Calls i2c device based on I2C driver ID. */
-int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg)
-{
- int addr;
-
- addr = cx18_i2c_id_addr(cx, id);
- if (addr < 0) {
- if (cmd != VIDIOC_G_CHIP_IDENT)
- CX18_ERR("i2c ID 0x%08x (%s) not found for cmd 0x%x!\n",
- id, cx18_i2c_id_name(id), cmd);
- return addr;
- }
- return cx18_call_i2c_client(cx, addr, cmd, arg);
-}
-
/* broadcast cmd for all I2C clients and for the gpio subsystem */
void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
{
diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h
index 113c3f9a2cc0..4869739013bd 100644
--- a/drivers/media/video/cx18/cx18-i2c.h
+++ b/drivers/media/video/cx18/cx18-i2c.h
@@ -23,7 +23,6 @@
int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw);
int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg);
-int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg);
int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg);
void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg);
int cx18_i2c_register(struct cx18 *cx, unsigned idx);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index e6087486f889..7086aaba77d6 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -254,30 +254,24 @@ static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
}
static int cx18_g_chip_ident(struct file *file, void *fh,
- struct v4l2_chip_ident *chip)
+ struct v4l2_dbg_chip_ident *chip)
{
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
chip->ident = V4L2_IDENT_NONE;
chip->revision = 0;
- if (chip->match_type == V4L2_CHIP_MATCH_HOST) {
- if (v4l2_chip_match_host(chip->match_type, chip->match_chip))
- chip->ident = V4L2_IDENT_CX23418;
+ if (v4l2_chip_match_host(&chip->match)) {
+ chip->ident = V4L2_IDENT_CX23418;
return 0;
}
- if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
- return cx18_i2c_id(cx, chip->match_chip, VIDIOC_G_CHIP_IDENT,
- chip);
- if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
- return cx18_call_i2c_client(cx, chip->match_chip,
- VIDIOC_G_CHIP_IDENT, chip);
- return -EINVAL;
+ cx18_call_i2c_clients(cx, VIDIOC_DBG_G_CHIP_IDENT, chip);
+ return 0;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
{
- struct v4l2_register *regs = arg;
+ struct v4l2_dbg_register *regs = arg;
unsigned long flags;
if (!capable(CAP_SYS_ADMIN))
@@ -286,6 +280,7 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
return -EINVAL;
spin_lock_irqsave(&cx18_cards_lock, flags);
+ regs->size = 4;
if (cmd == VIDIOC_DBG_G_REGISTER)
regs->val = cx18_read_enc(cx, regs->reg);
else
@@ -295,31 +290,25 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
}
static int cx18_g_register(struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
- if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (v4l2_chip_match_host(&reg->match))
return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
- if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
- return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER,
- reg);
- return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER,
- reg);
+ cx18_call_i2c_clients(cx, VIDIOC_DBG_G_REGISTER, reg);
+ return 0;
}
static int cx18_s_register(struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
- if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (v4l2_chip_match_host(&reg->match))
return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
- if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
- return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER,
- reg);
- return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER,
- reg);
+ cx18_call_i2c_clients(cx, VIDIOC_DBG_S_REGISTER, reg);
+ return 0;
}
#endif
@@ -755,7 +744,7 @@ static int cx18_log_status(struct file *file, void *fh)
return 0;
}
-static int cx18_default(struct file *file, void *fh, int cmd, void *arg)
+static long cx18_default(struct file *file, void *fh, int cmd, void *arg)
{
struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
@@ -783,19 +772,19 @@ static int cx18_default(struct file *file, void *fh, int cmd, void *arg)
return 0;
}
-int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct video_device *vfd = video_devdata(filp);
struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
struct cx18 *cx = id->cx;
- int res;
+ long res;
mutex_lock(&cx->serialize_lock);
if (cx18_debug & CX18_DBGFLG_IOCTL)
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
- res = video_ioctl2(inode, filp, cmd, arg);
+ res = video_ioctl2(filp, cmd, arg);
vfd->debug = 0;
mutex_unlock(&cx->serialize_lock);
return res;
diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h
index 08fe24e9510e..e2ca0d152116 100644
--- a/drivers/media/video/cx18/cx18-ioctl.h
+++ b/drivers/media/video/cx18/cx18-ioctl.h
@@ -29,5 +29,5 @@ void cx18_set_funcs(struct video_device *vdev);
int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
int cx18_s_input(struct file *file, void *fh, unsigned int inp);
-int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 63c336c95ff5..89c1ec94f335 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -37,13 +37,12 @@
#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
-static struct file_operations cx18_v4l2_enc_fops = {
+static struct v4l2_file_operations cx18_v4l2_enc_fops = {
.owner = THIS_MODULE,
.read = cx18_v4l2_read,
.open = cx18_v4l2_open,
/* FIXME change to video_ioctl2 if serialization lock can be removed */
.ioctl = cx18_v4l2_ioctl,
- .compat_ioctl = v4l_compat_ioctl32,
.release = cx18_v4l2_close,
.poll = cx18_v4l2_enc_poll,
};
@@ -61,49 +60,41 @@ static struct {
int num_offset;
int dma;
enum v4l2_buf_type buf_type;
- struct file_operations *fops;
} cx18_stream_info[] = {
{ /* CX18_ENC_STREAM_TYPE_MPG */
"encoder MPEG",
VFL_TYPE_GRABBER, 0,
PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
- &cx18_v4l2_enc_fops
},
{ /* CX18_ENC_STREAM_TYPE_TS */
"TS",
VFL_TYPE_GRABBER, -1,
PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
- &cx18_v4l2_enc_fops
},
{ /* CX18_ENC_STREAM_TYPE_YUV */
"encoder YUV",
VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
- &cx18_v4l2_enc_fops
},
{ /* CX18_ENC_STREAM_TYPE_VBI */
"encoder VBI",
VFL_TYPE_VBI, 0,
PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
- &cx18_v4l2_enc_fops
},
{ /* CX18_ENC_STREAM_TYPE_PCM */
"encoder PCM audio",
VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
- &cx18_v4l2_enc_fops
},
{ /* CX18_ENC_STREAM_TYPE_IDX */
"encoder IDX",
VFL_TYPE_GRABBER, -1,
PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
- &cx18_v4l2_enc_fops
},
{ /* CX18_ENC_STREAM_TYPE_RAD */
"encoder radio",
VFL_TYPE_RADIO, 0,
PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
- &cx18_v4l2_enc_fops
},
};
@@ -184,7 +175,7 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
s->v4l2dev->num = num;
s->v4l2dev->parent = &cx->dev->dev;
- s->v4l2dev->fops = cx18_stream_info[type].fops;
+ s->v4l2dev->fops = &cx18_v4l2_enc_fops;
s->v4l2dev->release = video_device_release;
s->v4l2dev->tvnorms = V4L2_STD_ALL;
cx18_set_funcs(s->v4l2dev);
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index 798d24024353..bfe25841dbf4 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -1027,12 +1027,13 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev)
printk(KERN_ERR "%s() f/w load failed\n", __func__);
return retval;
}
- dev->cx23417_mailbox = cx23885_find_mailbox(dev);
- if (dev->cx23417_mailbox < 0) {
+ retval = cx23885_find_mailbox(dev);
+ if (retval < 0) {
printk(KERN_ERR "%s() mailbox < 0, error\n",
__func__);
return -1;
}
+ dev->cx23417_mailbox = retval;
retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
if (retval < 0) {
printk(KERN_ERR
@@ -1573,9 +1574,9 @@ static int vidioc_queryctrl(struct file *file, void *priv,
return cx23885_queryctrl(dev, c);
}
-static int mpeg_open(struct inode *inode, struct file *file)
+static int mpeg_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct cx23885_dev *h, *dev = NULL;
struct list_head *list;
struct cx23885_fh *fh;
@@ -1585,7 +1586,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
lock_kernel();
list_for_each(list, &cx23885_devlist) {
h = list_entry(list, struct cx23885_dev, devlist);
- if (h->v4l_device->minor == minor) {
+ if (h->v4l_device &&
+ h->v4l_device->minor == minor) {
dev = h;
break;
}
@@ -1617,7 +1619,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
return 0;
}
-static int mpeg_release(struct inode *inode, struct file *file)
+static int mpeg_release(struct file *file)
{
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
@@ -1694,15 +1696,13 @@ static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
return videobuf_mmap_mapper(&fh->mpegq, vma);
}
-static struct file_operations mpeg_fops = {
+static struct v4l2_file_operations mpeg_fops = {
.owner = THIS_MODULE,
.open = mpeg_open,
.release = mpeg_release,
.read = mpeg_read,
.poll = mpeg_poll,
.mmap = mpeg_mmap,
- .ioctl = video_ioctl2,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index c742a10be5cb..eaa11893bfe9 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -718,9 +718,9 @@ static int get_resource(struct cx23885_fh *fh)
}
}
-static int video_open(struct inode *inode, struct file *file)
+static int video_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct cx23885_dev *h, *dev = NULL;
struct cx23885_fh *fh;
struct list_head *list;
@@ -730,12 +730,13 @@ static int video_open(struct inode *inode, struct file *file)
lock_kernel();
list_for_each(list, &cx23885_devlist) {
h = list_entry(list, struct cx23885_dev, devlist);
- if (h->video_dev->minor == minor) {
+ if (h->video_dev &&
+ h->video_dev->minor == minor) {
dev = h;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
}
if (h->vbi_dev &&
- h->vbi_dev->minor == minor) {
+ h->vbi_dev->minor == minor) {
dev = h;
type = V4L2_BUF_TYPE_VBI_CAPTURE;
}
@@ -834,7 +835,7 @@ static unsigned int video_poll(struct file *file,
return 0;
}
-static int video_release(struct inode *inode, struct file *file)
+static int video_release(struct file *file)
{
struct cx23885_fh *fh = file->private_data;
struct cx23885_dev *dev = fh->dev;
@@ -1326,11 +1327,11 @@ static int vidioc_s_frequency(struct file *file, void *priv,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register(struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_G_REGISTER, reg);
@@ -1339,11 +1340,11 @@ static int vidioc_g_register(struct file *file, void *fh,
}
static int vidioc_s_register(struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_DBG_S_REGISTER, reg);
@@ -1422,7 +1423,7 @@ int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
/* ----------------------------------------------------------- */
/* exported stuff */
-static const struct file_operations video_fops = {
+static const struct v4l2_file_operations video_fops = {
.owner = THIS_MODULE,
.open = video_open,
.release = video_release,
@@ -1430,8 +1431,6 @@ static const struct file_operations video_fops = {
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1479,13 +1478,11 @@ static struct video_device cx23885_video_template = {
.current_norm = V4L2_STD_NTSC_M,
};
-static const struct file_operations radio_fops = {
+static const struct v4l2_file_operations radio_fops = {
.owner = THIS_MODULE,
.open = video_open,
.release = video_release,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
};
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 2ad277189da8..25eb3bec9e5d 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -1120,25 +1120,24 @@ static int cx25840_init(struct v4l2_subdev *sd, u32 val)
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cx25840_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
+ reg->size = 1;
reg->val = cx25840_read(client, reg->reg & 0x0fff);
return 0;
}
-static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int cx25840_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -1362,7 +1361,7 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
return 0;
}
-static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct cx25840_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -1383,6 +1382,14 @@ static int cx25840_log_status(struct v4l2_subdev *sd)
static int cx25840_command(struct i2c_client *client, unsigned cmd, void *arg)
{
+ /* ignore this command */
+ if (cmd == TUNER_SET_TYPE_ADDR || cmd == TUNER_SET_CONFIG)
+ return 0;
+
+ /* Old-style drivers rely on initialization on first use, so
+ call the init whenever a command is issued to this driver.
+ New-style drivers using v4l2_subdev should call init explicitly. */
+ cx25840_init(i2c_get_clientdata(client), 0);
return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
}
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index b0f837588e01..2d250a2a7bc3 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -69,6 +69,11 @@ config VIDEO_CX88_DVB
To compile this driver as a module, choose M here: the
module will be called cx88-dvb.
+config VIDEO_CX88_MPEG
+ tristate
+ depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
+ default y
+
config VIDEO_CX88_VP3054
tristate "VP-3054 Secondary I2C Bus Support"
default m
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 6ec30f242578..b06b1275a9ec 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -3,7 +3,8 @@ cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
cx8800-objs := cx88-video.o cx88-vbi.o
cx8802-objs := cx88-mpeg.o
-obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o
+obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o
+obj-$(CONFIG_VIDEO_CX88_MPEG) += cx8802.o
obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index e162a70748c5..7f5b8bfd08ac 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1049,16 +1049,16 @@ static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
/* FIXME: cx88_ioctl_hook not implemented */
-static int mpeg_open(struct inode *inode, struct file *file)
+static int mpeg_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct cx8802_dev *dev = NULL;
struct cx8802_fh *fh;
struct cx8802_driver *drv = NULL;
int err;
lock_kernel();
- dev = cx8802_get_device(inode);
+ dev = cx8802_get_device(minor);
dprintk( 1, "%s\n", __func__);
@@ -1114,7 +1114,7 @@ static int mpeg_open(struct inode *inode, struct file *file)
return 0;
}
-static int mpeg_release(struct inode *inode, struct file *file)
+static int mpeg_release(struct file *file)
{
struct cx8802_fh *fh = file->private_data;
struct cx8802_dev *dev = fh->dev;
@@ -1132,7 +1132,7 @@ static int mpeg_release(struct inode *inode, struct file *file)
kfree(fh);
/* Make sure we release the hardware */
- dev = cx8802_get_device(inode);
+ dev = cx8802_get_device(video_devdata(file)->minor);
if (dev == NULL)
return -ENODEV;
@@ -1178,7 +1178,7 @@ mpeg_mmap(struct file *file, struct vm_area_struct * vma)
return videobuf_mmap_mapper(&fh->mpegq, vma);
}
-static const struct file_operations mpeg_fops =
+static const struct v4l2_file_operations mpeg_fops =
{
.owner = THIS_MODULE,
.open = mpeg_open,
@@ -1187,7 +1187,6 @@ static const struct file_operations mpeg_fops =
.poll = mpeg_poll,
.mmap = mpeg_mmap,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index da4dd4913d9f..aef5297534af 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -138,6 +138,28 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
return ret;
}
+static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open)
+{
+ struct videobuf_dvb_frontends *f;
+ struct videobuf_dvb_frontend *fe;
+
+ if (!core->dvbdev)
+ return;
+
+ f = &core->dvbdev->frontends;
+
+ if (!f)
+ return;
+
+ if (f->gate <= 1) /* undefined or fe0 */
+ fe = videobuf_dvb_get_frontend(f, 1);
+ else
+ fe = videobuf_dvb_get_frontend(f, f->gate);
+
+ if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+ fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+}
+
/* ------------------------------------------------------------------ */
static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
@@ -592,6 +614,31 @@ static struct stv0288_config tevii_tuner_earda_config = {
.set_ts_params = cx24116_set_ts_param,
};
+static int cx8802_alloc_frontends(struct cx8802_dev *dev)
+{
+ struct cx88_core *core = dev->core;
+ struct videobuf_dvb_frontend *fe = NULL;
+ int i;
+
+ mutex_init(&dev->frontends.lock);
+ INIT_LIST_HEAD(&dev->frontends.felist);
+
+ if (!core->board.num_frontends)
+ return -ENODEV;
+
+ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+ core->board.num_frontends);
+ for (i = 1; i <= core->board.num_frontends; i++) {
+ fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
+ if (!fe) {
+ printk(KERN_ERR "%s() failed to alloc\n", __func__);
+ videobuf_dvb_dealloc_frontends(&dev->frontends);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
static int dvb_register(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
@@ -611,6 +658,9 @@ static int dvb_register(struct cx8802_dev *dev)
/* multi-frontend gate control is undefined or defaults to fe0 */
dev->frontends.gate = 0;
+ /* Sets the gate control callback to be used by i2c command calls */
+ core->gate_ctrl = cx88_dvb_gate_ctrl;
+
/* init frontend(s) */
switch (core->boardnr) {
case CX88_BOARD_HAUPPAUGE_DVB_T1:
@@ -1109,6 +1159,7 @@ static int dvb_register(struct cx8802_dev *dev)
&dev->pci->dev, adapter_nr, mfe_shared);
frontend_detach:
+ core->gate_ctrl = NULL;
videobuf_dvb_dealloc_frontends(&dev->frontends);
return -EINVAL;
}
@@ -1199,6 +1250,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
int err;
+ struct videobuf_dvb_frontend *fe;
+ int i;
dprintk( 1, "%s\n", __func__);
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
@@ -1214,39 +1267,34 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv)
/* If vp3054 isn't enabled, a stub will just return 0 */
err = vp3054_i2c_probe(dev);
if (0 != err)
- goto fail_probe;
+ goto fail_core;
/* dvb stuff */
printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
dev->ts_gen_cntrl = 0x0c;
+ err = cx8802_alloc_frontends(dev);
+ if (err)
+ goto fail_core;
+
err = -ENODEV;
- if (core->board.num_frontends) {
- struct videobuf_dvb_frontend *fe;
- int i;
-
- for (i = 1; i <= core->board.num_frontends; i++) {
- fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
- if (fe == NULL) {
- printk(KERN_ERR "%s() failed to get frontend(%d)\n",
+ for (i = 1; i <= core->board.num_frontends; i++) {
+ fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+ if (fe == NULL) {
+ printk(KERN_ERR "%s() failed to get frontend(%d)\n",
__func__, i);
- goto fail_probe;
- }
- videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
+ goto fail_probe;
+ }
+ videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
&dev->pci->dev, &dev->slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_TOP,
sizeof(struct cx88_buffer),
dev);
- /* init struct videobuf_dvb */
- fe->dvb.name = dev->core->name;
- }
- } else {
- /* no frontends allocated */
- printk(KERN_ERR "%s/2 .num_frontends should be non-zero\n",
- core->name);
- goto fail_core;
+ /* init struct videobuf_dvb */
+ fe->dvb.name = dev->core->name;
}
+
err = dvb_register(dev);
if (err)
/* frontends/adapter de-allocated in dvb_register */
@@ -1270,6 +1318,8 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv)
vp3054_i2c_remove(dev);
+ core->gate_ctrl = NULL;
+
return 0;
}
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 1ab691d20692..c0ff2305d804 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -116,30 +116,16 @@ static int detach_inform(struct i2c_client *client)
void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
{
-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
- struct videobuf_dvb_frontends *f = &core->dvbdev->frontends;
- struct videobuf_dvb_frontend *fe = NULL;
-#endif
if (0 != core->i2c_rc)
return;
-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
- if (core->dvbdev && f) {
- if(f->gate <= 1) /* undefined or fe0 */
- fe = videobuf_dvb_get_frontend(f, 1);
- else
- fe = videobuf_dvb_get_frontend(f, f->gate);
+ if (core->gate_ctrl)
+ core->gate_ctrl(core, 1);
- if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
- fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 1);
+ i2c_clients_command(&core->i2c_adap, cmd, arg);
- i2c_clients_command(&core->i2c_adap, cmd, arg);
-
- if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
- fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 0);
- } else
-#endif
- i2c_clients_command(&core->i2c_adap, cmd, arg);
+ if (core->gate_ctrl)
+ core->gate_ctrl(core, 0);
}
static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index a04fee235db6..b295b76737e3 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -578,9 +578,8 @@ static int cx8802_resume_common(struct pci_dev *pci_dev)
#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
-struct cx8802_dev * cx8802_get_device(struct inode *inode)
+struct cx8802_dev *cx8802_get_device(int minor)
{
- int minor = iminor(inode);
struct cx8802_dev *dev;
list_for_each_entry(dev, &cx8802_devlist, devlist)
@@ -788,6 +787,9 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
dev->pci = pci_dev;
dev->core = core;
+ /* Maintain a reference so cx88-video can query the 8802 device. */
+ core->dvbdev = dev;
+
err = cx8802_init_common(dev);
if (err != 0)
goto fail_free;
@@ -795,32 +797,6 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
INIT_LIST_HEAD(&dev->drvlist);
list_add_tail(&dev->devlist,&cx8802_devlist);
-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
- mutex_init(&dev->frontends.lock);
- INIT_LIST_HEAD(&dev->frontends.felist);
-
- if (core->board.num_frontends) {
- struct videobuf_dvb_frontend *fe;
- int i;
-
- printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
- core->board.num_frontends);
- for (i = 1; i <= core->board.num_frontends; i++) {
- fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
- if(fe == NULL) {
- printk(KERN_ERR "%s() failed to alloc\n",
- __func__);
- videobuf_dvb_dealloc_frontends(&dev->frontends);
- err = -ENOMEM;
- goto fail_free;
- }
- }
- }
-#endif
-
- /* Maintain a reference so cx88-video can query the 8802 device. */
- core->dvbdev = dev;
-
/* now autoload cx88-dvb or cx88-blackbird */
request_modules(dev);
return 0;
@@ -828,6 +804,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev,
fail_free:
kfree(dev);
fail_core:
+ core->dvbdev = NULL;
cx88_core_put(core,pci_dev);
return err;
}
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index b96ce991d968..791e69d804f9 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -757,9 +757,9 @@ static int get_ressource(struct cx8800_fh *fh)
}
}
-static int video_open(struct inode *inode, struct file *file)
+static int video_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct cx8800_dev *h,*dev = NULL;
struct cx88_core *core;
struct cx8800_fh *fh;
@@ -904,7 +904,7 @@ video_poll(struct file *file, struct poll_table_struct *wait)
return 0;
}
-static int video_release(struct inode *inode, struct file *file)
+static int video_release(struct file *file)
{
struct cx8800_fh *fh = file->private_data;
struct cx8800_dev *dev = fh->dev;
@@ -1447,25 +1447,26 @@ static int vidioc_s_frequency (struct file *file, void *priv,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register (struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
/* cx2388x has a 24-bit register space */
- reg->val = cx_read(reg->reg&0xffffff);
+ reg->val = cx_read(reg->reg & 0xffffff);
+ reg->size = 4;
return 0;
}
static int vidioc_s_register (struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
- cx_write(reg->reg&0xffffff, reg->val);
+ cx_write(reg->reg & 0xffffff, reg->val);
return 0;
}
#endif
@@ -1693,7 +1694,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id)
/* ----------------------------------------------------------- */
/* exported stuff */
-static const struct file_operations video_fops =
+static const struct v4l2_file_operations video_fops =
{
.owner = THIS_MODULE,
.open = video_open,
@@ -1702,8 +1703,6 @@ static const struct file_operations video_fops =
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1752,14 +1751,12 @@ static struct video_device cx8800_video_template = {
.current_norm = V4L2_STD_NTSC_M,
};
-static const struct file_operations radio_fops =
+static const struct v4l2_file_operations radio_fops =
{
.owner = THIS_MODULE,
.open = video_open,
.release = video_release,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops radio_ioctl_ops = {
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 20649b25f7ba..6025fdd23344 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -302,6 +302,7 @@ struct cx88_dmaqueue {
struct btcx_riscmem stopper;
u32 count;
};
+struct cx88_core;
struct cx88_core {
struct list_head devlist;
@@ -334,8 +335,9 @@ struct cx88_core {
/* config info -- dvb */
#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
- int (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+ int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
#endif
+ void (*gate_ctrl)(struct cx88_core *core, int open);
/* state info */
struct task_struct *kthread;
@@ -643,7 +645,7 @@ int cx88_audio_thread(void *data);
int cx8802_register_driver(struct cx8802_driver *drv);
int cx8802_unregister_driver(struct cx8802_driver *drv);
-struct cx8802_dev * cx8802_get_device(struct inode *inode);
+struct cx8802_dev *cx8802_get_device(int minor);
struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
/* ----------------------------------------------------------- */
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index 15c03f0e69ad..5d882a44e3ee 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -62,9 +62,15 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev)
dprintk("Stopping isoc\n");
for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
- usb_unlink_urb(dev->adev->urb[i]);
- usb_free_urb(dev->adev->urb[i]);
- dev->adev->urb[i] = NULL;
+ if (!irqs_disabled())
+ usb_kill_urb(dev->adev.urb[i]);
+ else
+ usb_unlink_urb(dev->adev.urb[i]);
+ usb_free_urb(dev->adev.urb[i]);
+ dev->adev.urb[i] = NULL;
+
+ kfree(dev->adev.transfer_buffer[i]);
+ dev->adev.transfer_buffer[i] = NULL;
}
return 0;
@@ -81,8 +87,8 @@ static void em28xx_audio_isocirq(struct urb *urb)
unsigned int stride;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
- if (dev->adev->capture_pcm_substream) {
- substream = dev->adev->capture_pcm_substream;
+ if (dev->adev.capture_pcm_substream) {
+ substream = dev->adev.capture_pcm_substream;
runtime = substream->runtime;
stride = runtime->frame_bits >> 3;
@@ -95,7 +101,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
if (!length)
continue;
- oldptr = dev->adev->hwptr_done_capture;
+ oldptr = dev->adev.hwptr_done_capture;
if (oldptr + length >= runtime->buffer_size) {
unsigned int cnt =
runtime->buffer_size - oldptr;
@@ -110,16 +116,16 @@ static void em28xx_audio_isocirq(struct urb *urb)
snd_pcm_stream_lock(substream);
- dev->adev->hwptr_done_capture += length;
- if (dev->adev->hwptr_done_capture >=
+ dev->adev.hwptr_done_capture += length;
+ if (dev->adev.hwptr_done_capture >=
runtime->buffer_size)
- dev->adev->hwptr_done_capture -=
+ dev->adev.hwptr_done_capture -=
runtime->buffer_size;
- dev->adev->capture_transfer_done += length;
- if (dev->adev->capture_transfer_done >=
+ dev->adev.capture_transfer_done += length;
+ if (dev->adev.capture_transfer_done >=
runtime->period_size) {
- dev->adev->capture_transfer_done -=
+ dev->adev.capture_transfer_done -=
runtime->period_size;
period_elapsed = 1;
}
@@ -131,7 +137,7 @@ static void em28xx_audio_isocirq(struct urb *urb)
}
urb->status = 0;
- if (dev->adev->shutdown)
+ if (dev->adev.shutdown)
return;
status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -154,17 +160,17 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
struct urb *urb;
int j, k;
- dev->adev->transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
- if (!dev->adev->transfer_buffer[i])
+ dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
+ if (!dev->adev.transfer_buffer[i])
return -ENOMEM;
- memset(dev->adev->transfer_buffer[i], 0x80, sb_size);
+ memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
if (!urb) {
em28xx_errdev("usb_alloc_urb failed!\n");
for (j = 0; j < i; j++) {
- usb_free_urb(dev->adev->urb[j]);
- kfree(dev->adev->transfer_buffer[j]);
+ usb_free_urb(dev->adev.urb[j]);
+ kfree(dev->adev.transfer_buffer[j]);
}
return -ENOMEM;
}
@@ -173,7 +179,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
urb->context = dev;
urb->pipe = usb_rcvisocpipe(dev->udev, 0x83);
urb->transfer_flags = URB_ISO_ASAP;
- urb->transfer_buffer = dev->adev->transfer_buffer[i];
+ urb->transfer_buffer = dev->adev.transfer_buffer[i];
urb->interval = 1;
urb->complete = em28xx_audio_isocirq;
urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
@@ -185,11 +191,11 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
urb->iso_frame_desc[j].length =
EM28XX_AUDIO_MAX_PACKET_SIZE;
}
- dev->adev->urb[i] = urb;
+ dev->adev.urb[i] = urb;
}
for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
- errCode = usb_submit_urb(dev->adev->urb[i], GFP_ATOMIC);
+ errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
if (errCode) {
em28xx_isoc_audio_deinit(dev);
@@ -202,16 +208,16 @@ static int em28xx_init_audio_isoc(struct em28xx *dev)
static int em28xx_cmd(struct em28xx *dev, int cmd, int arg)
{
- dprintk("%s transfer\n", (dev->adev->capture_stream == STREAM_ON)?
+ dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ?
"stop" : "start");
switch (cmd) {
case EM28XX_CAPTURE_STREAM_EN:
- if (dev->adev->capture_stream == STREAM_OFF && arg == 1) {
- dev->adev->capture_stream = STREAM_ON;
+ if (dev->adev.capture_stream == STREAM_OFF && arg == 1) {
+ dev->adev.capture_stream = STREAM_ON;
em28xx_init_audio_isoc(dev);
- } else if (dev->adev->capture_stream == STREAM_ON && arg == 0) {
- dev->adev->capture_stream = STREAM_OFF;
+ } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) {
+ dev->adev.capture_stream = STREAM_OFF;
em28xx_isoc_audio_deinit(dev);
} else {
printk(KERN_ERR "An underrun very likely occurred. "
@@ -289,17 +295,17 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
goto err;
runtime->hw = snd_em28xx_hw_capture;
- if (dev->alt == 0 && dev->adev->users == 0) {
+ if (dev->alt == 0 && dev->adev.users == 0) {
int errCode;
dev->alt = 7;
errCode = usb_set_interface(dev->udev, 0, 7);
dprintk("changing alternate number to 7\n");
}
- dev->adev->users++;
+ dev->adev.users++;
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
- dev->adev->capture_pcm_substream = substream;
+ dev->adev.capture_pcm_substream = substream;
runtime->private_data = dev;
return 0;
@@ -311,7 +317,7 @@ err:
static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
{
struct em28xx *dev = snd_pcm_substream_chip(substream);
- dev->adev->users--;
+ dev->adev.users--;
dprintk("closing device\n");
@@ -320,10 +326,10 @@ static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
em28xx_audio_analog_set(dev);
mutex_unlock(&dev->lock);
- if (dev->adev->users == 0 && dev->adev->shutdown == 1) {
- dprintk("audio users: %d\n", dev->adev->users);
+ if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
+ dprintk("audio users: %d\n", dev->adev.users);
dprintk("disabling audio stream!\n");
- dev->adev->shutdown = 0;
+ dev->adev.shutdown = 0;
dprintk("released lock\n");
em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
}
@@ -356,7 +362,7 @@ static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
dprintk("Stop capture, if needed\n");
- if (dev->adev->capture_stream == STREAM_ON)
+ if (dev->adev.capture_stream == STREAM_ON)
em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 0);
return 0;
@@ -379,7 +385,7 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
em28xx_cmd(dev, EM28XX_CAPTURE_STREAM_EN, 1);
return 0;
case SNDRV_PCM_TRIGGER_STOP:
- dev->adev->shutdown = 1;
+ dev->adev.shutdown = 1;
return 0;
default:
return -EINVAL;
@@ -389,11 +395,15 @@ static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
*substream)
{
- struct em28xx *dev;
+ unsigned long flags;
+ struct em28xx *dev;
snd_pcm_uframes_t hwptr_done;
+
dev = snd_pcm_substream_chip(substream);
- hwptr_done = dev->adev->hwptr_done_capture;
+ spin_lock_irqsave(&dev->adev.slock, flags);
+ hwptr_done = dev->adev.hwptr_done_capture;
+ spin_unlock_irqrestore(&dev->adev.slock, flags);
return hwptr_done;
}
@@ -420,7 +430,7 @@ static struct snd_pcm_ops snd_em28xx_pcm_capture = {
static int em28xx_audio_init(struct em28xx *dev)
{
- struct em28xx_audio *adev;
+ struct em28xx_audio *adev = &dev->adev;
struct snd_pcm *pcm;
struct snd_card *card;
static int devnr;
@@ -438,16 +448,9 @@ static int em28xx_audio_init(struct em28xx *dev)
printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
"Rechberger\n");
- adev = kzalloc(sizeof(*adev), GFP_KERNEL);
- if (!adev) {
- printk(KERN_ERR "em28xx-audio.c: out of memory\n");
- return -1;
- }
card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0);
- if (card == NULL) {
- kfree(adev);
+ if (card == NULL)
return -ENOMEM;
- }
spin_lock_init(&adev->slock);
err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
@@ -471,7 +474,6 @@ static int em28xx_audio_init(struct em28xx *dev)
}
adev->sndcard = card;
adev->udev = dev->udev;
- dev->adev = adev;
return 0;
}
@@ -488,10 +490,9 @@ static int em28xx_audio_fini(struct em28xx *dev)
return 0;
}
- if (dev->adev) {
- snd_card_free(dev->adev->sndcard);
- kfree(dev->adev);
- dev->adev = NULL;
+ if (dev->adev.sndcard) {
+ snd_card_free(dev->adev.sndcard);
+ dev->adev.sndcard = NULL;
}
return 0;
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index e776699b62f9..3b3ca3f46d52 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -102,6 +102,18 @@ static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
/* Board - EM2870 Kworld 355u
Analog - No input analog */
+static struct em28xx_reg_seq kworld_330u_analog[] = {
+ {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10},
+ {EM2880_R04_GPO, 0x00, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+
+static struct em28xx_reg_seq kworld_330u_digital[] = {
+ {EM28XX_R08_GPIO, 0x6e, ~EM_GPIO_4, 10},
+ {EM2880_R04_GPO, 0x08, 0xff, 10},
+ { -1, -1, -1, -1},
+};
+
/* Callback for the most boards */
static struct em28xx_reg_seq default_tuner_gpio[] = {
{EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10},
@@ -1177,29 +1189,33 @@ struct em28xx_board em28xx_boards[] = {
.gpio = hauppauge_wintv_hvr_900_analog,
} },
},
- [EM2883_BOARD_KWORLD_HYBRID_A316] = {
+ [EM2883_BOARD_KWORLD_HYBRID_330U] = {
.name = "Kworld PlusTV HD Hybrid 330",
.tuner_type = TUNER_XC2028,
.tuner_gpio = default_tuner_gpio,
.decoder = EM28XX_TVP5150,
.mts_firmware = 1,
.has_dvb = 1,
- .dvb_gpio = default_digital,
+ .dvb_gpio = kworld_330u_digital,
+ .xclk = EM28XX_XCLK_FREQUENCY_12MHZ,
+ .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_EEPROM_ON_BOARD | EM28XX_I2C_EEPROM_KEY_VALID,
.input = { {
.type = EM28XX_VMUX_TELEVISION,
.vmux = TVP5150_COMPOSITE0,
.amux = EM28XX_AMUX_VIDEO,
- .gpio = default_analog,
+ .gpio = kworld_330u_analog,
+ .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
}, {
.type = EM28XX_VMUX_COMPOSITE1,
.vmux = TVP5150_COMPOSITE1,
.amux = EM28XX_AMUX_LINE_IN,
- .gpio = hauppauge_wintv_hvr_900_analog,
+ .gpio = kworld_330u_analog,
+ .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
}, {
.type = EM28XX_VMUX_SVIDEO,
.vmux = TVP5150_SVIDEO,
.amux = EM28XX_AMUX_LINE_IN,
- .gpio = hauppauge_wintv_hvr_900_analog,
+ .gpio = kworld_330u_analog,
} },
},
[EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
@@ -1249,7 +1265,7 @@ struct usb_device_id em28xx_id_table [] = {
{ USB_DEVICE(0xeb1a, 0xe310),
.driver_info = EM2880_BOARD_MSI_DIGIVOX_AD },
{ USB_DEVICE(0xeb1a, 0xa316),
- .driver_info = EM2883_BOARD_KWORLD_HYBRID_A316 },
+ .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U },
{ USB_DEVICE(0xeb1a, 0xe320),
.driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II },
{ USB_DEVICE(0xeb1a, 0xe323),
@@ -1526,6 +1542,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
/* FIXME: Better to specify the needed IF */
ctl->demod = XC3028_FE_DEFAULT;
break;
+ case EM2883_BOARD_KWORLD_HYBRID_330U:
+ ctl->demod = XC3028_FE_CHINA;
+ ctl->fname = XC2028_DEFAULT_FIRMWARE;
+ break;
default:
ctl->demod = XC3028_FE_OREN538;
}
@@ -1842,7 +1862,7 @@ void em28xx_release_resources(struct em28xx *dev)
* em28xx_init_dev()
* allocates and inits the device structs, registers i2c bus and v4l device
*/
-int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
+static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
int minor)
{
struct em28xx *dev = *devhandle;
@@ -1990,8 +2010,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
int check_interface = 1;
isoc_pipe = 1;
endpoint = &interface->cur_altsetting->endpoint[1].desc;
- if (usb_endpoint_type(endpoint) !=
- USB_ENDPOINT_XFER_ISOC)
+ if (!usb_endpoint_xfer_isoc(endpoint))
check_interface = 0;
if (usb_endpoint_dir_out(endpoint))
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index f8504518586a..94fb1b639a2e 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -393,7 +393,7 @@ static int em28xx_set_audio_source(struct em28xx *dev)
return ret;
}
-struct em28xx_vol_table outputs[] = {
+static const struct em28xx_vol_table outputs[] = {
{ EM28XX_AOUT_MASTER, AC97_MASTER_VOL },
{ EM28XX_AOUT_LINE, AC97_LINE_LEVEL_VOL },
{ EM28XX_AOUT_MONO, AC97_MASTER_MONO_VOL },
@@ -438,6 +438,10 @@ int em28xx_audio_analog_set(struct em28xx *dev)
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
int vol;
+ em28xx_write_ac97(dev, AC97_POWER_DOWN_CTRL, 0x4200);
+ em28xx_write_ac97(dev, AC97_EXT_AUD_CTRL, 0x0031);
+ em28xx_write_ac97(dev, AC97_PCM_IN_SRATE, 0xbb80);
+
/* LSB: left channel - both channels with the same level */
vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
@@ -454,6 +458,15 @@ int em28xx_audio_analog_set(struct em28xx *dev)
em28xx_warn("couldn't setup AC97 register %d\n",
outputs[i].reg);
}
+
+ if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
+ int sel = ac97_return_record_select(dev->ctl_aoutput);
+
+ /* Use the same input for both left and right channels */
+ sel |= (sel << 8);
+
+ em28xx_write_ac97(dev, AC97_RECORD_SELECT, sel);
+ }
}
return ret;
@@ -847,8 +860,11 @@ void em28xx_uninit_isoc(struct em28xx *dev)
for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
urb = dev->isoc_ctl.urb[i];
if (urb) {
- usb_kill_urb(urb);
- usb_unlink_urb(urb);
+ if (!irqs_disabled())
+ usb_kill_urb(urb);
+ else
+ usb_unlink_urb(urb);
+
if (dev->isoc_ctl.transfer_buffer[i]) {
usb_buffer_free(dev->udev,
urb->transfer_buffer_length,
@@ -1000,12 +1016,11 @@ void em28xx_wake_i2c(struct em28xx *dev)
static LIST_HEAD(em28xx_devlist);
static DEFINE_MUTEX(em28xx_devlist_mutex);
-struct em28xx *em28xx_get_device(struct inode *inode,
+struct em28xx *em28xx_get_device(int minor,
enum v4l2_buf_type *fh_type,
int *has_radio)
{
struct em28xx *h, *dev = NULL;
- int minor = iminor(inode);
*fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
*has_radio = 0;
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index d38cb21834d9..9ad8527b3fda 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -28,6 +28,7 @@
#include "lgdt330x.h"
#include "zl10353.h"
+#include "s5h1409.h"
#ifdef EM28XX_DRX397XD_SUPPORT
#include "drx397xD.h"
#endif
@@ -232,6 +233,15 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = {
.if2 = 45600,
};
+static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
+ .demod_address = 0x32 >> 1,
+ .output_mode = S5H1409_PARALLEL_OUTPUT,
+ .gpio = S5H1409_GPIO_OFF,
+ .inversion = S5H1409_INVERSION_OFF,
+ .status_mode = S5H1409_DEMODLOCKING,
+ .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
+};
+
#ifdef EM28XX_DRX397XD_SUPPORT
/* [TODO] djh - not sure yet what the device config needs to contain */
static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
@@ -412,7 +422,6 @@ static int dvb_init(struct em28xx *dev)
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
- case EM2883_BOARD_KWORLD_HYBRID_A316:
case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
dvb->frontend = dvb_attach(lgdt330x_attach,
&em2880_lgdt3303_dev,
@@ -433,6 +442,15 @@ static int dvb_init(struct em28xx *dev)
goto out_free;
}
break;
+ case EM2883_BOARD_KWORLD_HYBRID_330U:
+ dvb->frontend = dvb_attach(s5h1409_attach,
+ &em28xx_s5h1409_with_xc3028,
+ &dev->i2c_adap);
+ if (attach_xc3028(0x61, dev) < 0) {
+ result = -EINVAL;
+ goto out_free;
+ }
+ break;
case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
#ifdef EM28XX_DRX397XD_SUPPORT
/* We don't have the config structure properly populated, so
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 42bbaf64aceb..0443afe09ff8 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -307,7 +307,7 @@ static void em28xx_ir_work(struct work_struct *work)
mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
}
-void em28xx_ir_start(struct em28xx_IR *ir)
+static void em28xx_ir_start(struct em28xx_IR *ir)
{
setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
INIT_WORK(&ir->work, em28xx_ir_work);
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
index 65dcb91bdcc2..24e39c56811e 100644
--- a/drivers/media/video/em28xx/em28xx-reg.h
+++ b/drivers/media/video/em28xx/em28xx-reg.h
@@ -160,7 +160,7 @@
/* FIXME: Need to be populated with the other chip ID's */
enum em28xx_chip_id {
- CHIP_ID_EM2820 = 18,
+ CHIP_ID_EM2820 = 18, /* Also used by em2710 */
CHIP_ID_EM2840 = 20,
CHIP_ID_EM2750 = 33,
CHIP_ID_EM2860 = 34,
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 53527536481e..8e61b2ca9167 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -886,10 +886,10 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
if (0 == INPUT(i)->type)
return -EINVAL;
- mutex_lock(&dev->lock);
-
- video_mux(dev, i);
+ dev->ctl_input = i;
+ mutex_lock(&dev->lock);
+ video_mux(dev, dev->ctl_input);
mutex_unlock(&dev->lock);
return 0;
}
@@ -939,6 +939,12 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
+
+ if (a->index >= MAX_EM28XX_INPUT)
+ return -EINVAL;
+ if (0 == INPUT(a->index)->type)
+ return -EINVAL;
+
mutex_lock(&dev->lock);
dev->ctl_ainput = INPUT(a->index)->amux;
@@ -1154,7 +1160,7 @@ static int em28xx_reg_len(int reg)
}
static int vidioc_g_chip_ident(struct file *file, void *priv,
- struct v4l2_chip_ident *chip)
+ struct v4l2_dbg_chip_ident *chip)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
@@ -1162,20 +1168,20 @@ static int vidioc_g_chip_ident(struct file *file, void *priv,
chip->ident = V4L2_IDENT_NONE;
chip->revision = 0;
- em28xx_i2c_call_clients(dev, VIDIOC_G_CHIP_IDENT, chip);
+ em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
return 0;
}
static int vidioc_g_register(struct file *file, void *priv,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
int ret;
- switch (reg->match_type) {
+ switch (reg->match.type) {
case V4L2_CHIP_MATCH_AC97:
mutex_lock(&dev->lock);
ret = em28xx_read_ac97(dev, reg->reg);
@@ -1184,6 +1190,7 @@ static int vidioc_g_register(struct file *file, void *priv,
return ret;
reg->val = ret;
+ reg->size = 1;
return 0;
case V4L2_CHIP_MATCH_I2C_DRIVER:
em28xx_i2c_call_clients(dev, VIDIOC_DBG_G_REGISTER, reg);
@@ -1192,12 +1199,13 @@ static int vidioc_g_register(struct file *file, void *priv,
/* Not supported yet */
return -EINVAL;
default:
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
}
/* Match host */
- if (em28xx_reg_len(reg->reg) == 1) {
+ reg->size = em28xx_reg_len(reg->reg);
+ if (reg->size == 1) {
mutex_lock(&dev->lock);
ret = em28xx_read_reg(dev, reg->reg);
mutex_unlock(&dev->lock);
@@ -1207,7 +1215,7 @@ static int vidioc_g_register(struct file *file, void *priv,
reg->val = ret;
} else {
- __le64 val = 0;
+ __le16 val = 0;
mutex_lock(&dev->lock);
ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
reg->reg, (char *)&val, 2);
@@ -1215,21 +1223,21 @@ static int vidioc_g_register(struct file *file, void *priv,
if (ret < 0)
return ret;
- reg->val = le64_to_cpu(val);
+ reg->val = le16_to_cpu(val);
}
return 0;
}
static int vidioc_s_register(struct file *file, void *priv,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct em28xx_fh *fh = priv;
struct em28xx *dev = fh->dev;
- __le64 buf;
+ __le16 buf;
int rc;
- switch (reg->match_type) {
+ switch (reg->match.type) {
case V4L2_CHIP_MATCH_AC97:
mutex_lock(&dev->lock);
rc = em28xx_write_ac97(dev, reg->reg, reg->val);
@@ -1243,12 +1251,12 @@ static int vidioc_s_register(struct file *file, void *priv,
/* Not supported yet */
return -EINVAL;
default:
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
}
/* Match host */
- buf = cpu_to_le64(reg->val);
+ buf = cpu_to_le16(reg->val);
mutex_lock(&dev->lock);
rc = em28xx_write_regs(dev, reg->reg, (char *)&buf,
@@ -1582,15 +1590,15 @@ static int radio_queryctrl(struct file *file, void *priv,
* em28xx_v4l2_open()
* inits the device and starts isoc transfer
*/
-static int em28xx_v4l2_open(struct inode *inode, struct file *filp)
+static int em28xx_v4l2_open(struct file *filp)
{
- int minor = iminor(inode);
+ int minor = video_devdata(filp)->minor;
int errCode = 0, radio;
struct em28xx *dev;
enum v4l2_buf_type fh_type;
struct em28xx_fh *fh;
- dev = em28xx_get_device(inode, &fh_type, &radio);
+ dev = em28xx_get_device(minor, &fh_type, &radio);
if (NULL == dev)
return -ENODEV;
@@ -1686,7 +1694,7 @@ void em28xx_release_analog_resources(struct em28xx *dev)
* stops streaming and deallocates all resources allocated by the v4l2
* calls and ioctls
*/
-static int em28xx_v4l2_close(struct inode *inode, struct file *filp)
+static int em28xx_v4l2_close(struct file *filp)
{
struct em28xx_fh *fh = filp->private_data;
struct em28xx *dev = fh->dev;
@@ -1826,7 +1834,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
return rc;
}
-static const struct file_operations em28xx_v4l_fops = {
+static const struct v4l2_file_operations em28xx_v4l_fops = {
.owner = THIS_MODULE,
.open = em28xx_v4l2_open,
.release = em28xx_v4l2_close,
@@ -1834,8 +1842,6 @@ static const struct file_operations em28xx_v4l_fops = {
.poll = em28xx_v4l2_poll,
.mmap = em28xx_v4l2_mmap,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
- .compat_ioctl = v4l_compat_ioctl32,
};
static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1890,13 +1896,11 @@ static const struct video_device em28xx_video_template = {
.current_norm = V4L2_STD_PAL,
};
-static const struct file_operations radio_fops = {
+static const struct v4l2_file_operations radio_fops = {
.owner = THIS_MODULE,
.open = em28xx_v4l2_open,
.release = em28xx_v4l2_close,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops radio_ioctl_ops = {
@@ -1952,6 +1956,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
int em28xx_register_analog_devices(struct em28xx *dev)
{
+ u8 val;
int ret;
printk(KERN_INFO "%s: v4l2 driver version %d.%d.%d\n",
@@ -1959,34 +1964,34 @@ int em28xx_register_analog_devices(struct em28xx *dev)
(EM28XX_VERSION_CODE >> 16) & 0xff,
(EM28XX_VERSION_CODE >> 8) & 0xff, EM28XX_VERSION_CODE & 0xff);
+ /* set default norm */
+ dev->norm = em28xx_video_template.current_norm;
+ dev->width = norm_maxw(dev);
+ dev->height = norm_maxh(dev);
+ dev->interlaced = EM28XX_INTERLACED_DEFAULT;
+ dev->hscale = 0;
+ dev->vscale = 0;
+ dev->ctl_input = 0;
+
/* Analog specific initialization */
dev->format = &format[0];
- video_mux(dev, 0);
+ video_mux(dev, dev->ctl_input);
+
+ /* Audio defaults */
+ dev->mute = 1;
+ dev->volume = 0x1f;
/* enable vbi capturing */
/* em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
-/* em28xx_write_reg(dev, EM28XX_R0F_XCLK, 0x80); clk register */
+ val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
+ em28xx_write_reg(dev, EM28XX_R0F_XCLK, (EM28XX_XCLK_AUDIO_UNMUTE | val));
em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51);
- dev->mute = 1; /* maybe not the right place... */
- dev->volume = 0x1f;
-
em28xx_set_outfmt(dev);
em28xx_colorlevels_set_default(dev);
em28xx_compression_disable(dev);
- /* set default norm */
- dev->norm = em28xx_video_template.current_norm;
- dev->width = norm_maxw(dev);
- dev->height = norm_maxh(dev);
- dev->interlaced = EM28XX_INTERLACED_DEFAULT;
- dev->hscale = 0;
- dev->vscale = 0;
-
- /* FIXME: This is a very bad hack! Not all devices have TV on input 2 */
- dev->ctl_input = 2;
-
/* allocate and fill video video_device struct */
dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
if (!dev->vdev) {
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index b5eddc26388e..dd2cd36fb1bb 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -94,7 +94,7 @@
#define EM2882_BOARD_KWORLD_VS_DVBT 54
#define EM2882_BOARD_TERRATEC_HYBRID_XS 55
#define EM2882_BOARD_PINNACLE_HYBRID_PRO 56
-#define EM2883_BOARD_KWORLD_HYBRID_A316 57
+#define EM2883_BOARD_KWORLD_HYBRID_330U 57
#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58
#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60
#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61
@@ -300,13 +300,32 @@ enum em28xx_amux {
};
enum em28xx_aout {
+ /* AC97 outputs */
EM28XX_AOUT_MASTER = 1 << 0,
EM28XX_AOUT_LINE = 1 << 1,
EM28XX_AOUT_MONO = 1 << 2,
EM28XX_AOUT_LFE = 1 << 3,
EM28XX_AOUT_SURR = 1 << 4,
+
+ /* PCM IN Mixer - used by AC97_RECORD_SELECT register */
+ EM28XX_AOUT_PCM_IN = 1 << 7,
+
+ /* Bits 10-8 are used to indicate the PCM IN record select */
+ EM28XX_AOUT_PCM_MIC_PCM = 0 << 8,
+ EM28XX_AOUT_PCM_CD = 1 << 8,
+ EM28XX_AOUT_PCM_VIDEO = 2 << 8,
+ EM28XX_AOUT_PCM_AUX = 3 << 8,
+ EM28XX_AOUT_PCM_LINE = 4 << 8,
+ EM28XX_AOUT_PCM_STEREO = 5 << 8,
+ EM28XX_AOUT_PCM_MONO = 6 << 8,
+ EM28XX_AOUT_PCM_PHONE = 7 << 8,
};
+static inline int ac97_return_record_select(int a_out)
+{
+ return (a_out & 0x700) >> 8;
+}
+
struct em28xx_reg_seq {
int reg;
unsigned char val, mask;
@@ -473,7 +492,7 @@ struct em28xx {
unsigned long i2c_hash; /* i2c devicelist hash -
for boards with generic ID */
- struct em28xx_audio *adev;
+ struct em28xx_audio adev;
/* states */
enum em28xx_dev_state state;
@@ -583,7 +602,7 @@ int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
void em28xx_wake_i2c(struct em28xx *dev);
void em28xx_remove_from_devlist(struct em28xx *dev);
void em28xx_add_into_devlist(struct em28xx *dev);
-struct em28xx *em28xx_get_device(struct inode *inode,
+struct em28xx *em28xx_get_device(int minor,
enum v4l2_buf_type *fh_type,
int *has_radio);
int em28xx_register_extension(struct em28xx_ops *dev);
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index 83c07112c59d..d1c1e457f0b9 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -1206,7 +1206,7 @@ static void et61x251_release_resources(struct kref *kref)
}
-static int et61x251_open(struct inode* inode, struct file* filp)
+static int et61x251_open(struct file *filp)
{
struct et61x251_device* cam;
int err = 0;
@@ -1291,7 +1291,7 @@ out:
}
-static int et61x251_release(struct inode* inode, struct file* filp)
+static int et61x251_release(struct file *filp)
{
struct et61x251_device* cam;
@@ -2392,8 +2392,8 @@ et61x251_vidioc_s_parm(struct et61x251_device* cam, void __user * arg)
}
-static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+static long et61x251_ioctl_v4l2(struct file *filp,
+ unsigned int cmd, void __user *arg)
{
struct et61x251_device *cam = video_drvdata(filp);
@@ -2487,11 +2487,11 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
}
-static int et61x251_ioctl(struct inode* inode, struct file* filp,
+static long et61x251_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct et61x251_device *cam = video_drvdata(filp);
- int err = 0;
+ long err = 0;
if (mutex_lock_interruptible(&cam->fileop_mutex))
return -ERESTARTSYS;
@@ -2511,7 +2511,7 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp,
V4LDBG(3, "et61x251", cmd);
- err = et61x251_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+ err = et61x251_ioctl_v4l2(filp, cmd, (void __user *)arg);
mutex_unlock(&cam->fileop_mutex);
@@ -2519,18 +2519,14 @@ static int et61x251_ioctl(struct inode* inode, struct file* filp,
}
-static const struct file_operations et61x251_fops = {
+static const struct v4l2_file_operations et61x251_fops = {
.owner = THIS_MODULE,
.open = et61x251_open,
.release = et61x251_release,
.ioctl = et61x251_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = et61x251_read,
.poll = et61x251_poll,
.mmap = et61x251_mmap,
- .llseek = no_llseek,
};
/*****************************************************************************/
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 8b9f3bde5740..2ed24527ecd6 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -423,7 +423,8 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
break;
gspca_dev->urb[i] = NULL;
- usb_kill_urb(urb);
+ if (!gspca_dev->present)
+ usb_kill_urb(urb);
if (urb->transfer_buffer != NULL)
usb_buffer_free(gspca_dev->dev,
urb->transfer_buffer_length,
@@ -875,7 +876,7 @@ static void gspca_release(struct video_device *vfd)
kfree(gspca_dev);
}
-static int dev_open(struct inode *inode, struct file *file)
+static int dev_open(struct file *file)
{
struct gspca_dev *gspca_dev;
int ret;
@@ -922,7 +923,7 @@ out:
return ret;
}
-static int dev_close(struct inode *inode, struct file *file)
+static int dev_close(struct file *file)
{
struct gspca_dev *gspca_dev = file->private_data;
@@ -1802,17 +1803,13 @@ out:
return ret;
}
-static struct file_operations dev_fops = {
+static struct v4l2_file_operations dev_fops = {
.owner = THIS_MODULE,
.open = dev_open,
.release = dev_close,
.read = dev_read,
.mmap = dev_mmap,
- .unlocked_ioctl = __video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
+ .unlocked_ioctl = video_ioctl2,
.poll = dev_poll,
};
@@ -1954,7 +1951,6 @@ void gspca_disconnect(struct usb_interface *intf)
struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
gspca_dev->present = 0;
- gspca_dev->streaming = 0;
usb_set_intfdata(intf, NULL);
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
index af3f2dc2c702..ccea4a758464 100644
--- a/drivers/media/video/gspca/m5602/m5602_s5k83a.c
+++ b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
@@ -113,7 +113,7 @@ int s5k83a_power_down(struct sd *sd)
return 0;
}
-void s5k83a_dump_registers(struct sd *sd)
+static void s5k83a_dump_registers(struct sd *sd)
{
int address;
u8 page, old_page;
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c
index 352f84d440fb..79393d1772e4 100644
--- a/drivers/media/video/hexium_gemini.c
+++ b/drivers/media/video/hexium_gemini.c
@@ -306,7 +306,7 @@ static int hexium_detach(struct saa7146_dev *dev)
return 0;
}
-static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c
index 8d3c1482e7ea..074bec711fe0 100644
--- a/drivers/media/video/hexium_orion.c
+++ b/drivers/media/video/hexium_orion.c
@@ -370,7 +370,7 @@ static int hexium_detach(struct saa7146_dev *dev)
return 0;
}
-static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct hexium *hexium = (struct hexium *) dev->ext_priv;
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 08b762951759..c46c990987f9 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -902,18 +902,19 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
}
if (hw & IVTV_HW_SAA711X) {
- struct v4l2_chip_ident v = { V4L2_CHIP_MATCH_I2C_DRIVER, I2C_DRIVERID_SAA711X };
+ struct v4l2_dbg_chip_ident v;
/* determine the exact saa711x model */
itv->hw_flags &= ~IVTV_HW_SAA711X;
+ v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER;
+ strlcpy(v.match.name, "saa7115", sizeof(v.match.name));
ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v);
if (v.ident == V4L2_IDENT_SAA7114) {
itv->hw_flags |= IVTV_HW_SAA7114;
/* VBI is not yet supported by the saa7114 driver. */
itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE);
- }
- else {
+ } else {
itv->hw_flags |= IVTV_HW_SAA7115;
}
itv->vbi.raw_decoder_line_size = 1443;
@@ -948,8 +949,10 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
itv->instance = atomic_inc_return(&ivtv_instance) - 1;
retval = v4l2_device_register(&dev->dev, &itv->device);
- if (retval)
+ if (retval) {
+ kfree(itv);
return retval;
+ }
/* "ivtv + PCI ID" is a bit of a mouthful, so use
"ivtv + instance" instead. */
snprintf(itv->device.name, sizeof(itv->device.name),
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 5eb587592e9d..d594bc29f07f 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -831,7 +831,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
ivtv_release_stream(s);
}
-int ivtv_v4l2_close(struct inode *inode, struct file *filp)
+int ivtv_v4l2_close(struct file *filp)
{
struct ivtv_open_id *id = filp->private_data;
struct ivtv *itv = id->itv;
@@ -978,7 +978,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
return 0;
}
-int ivtv_v4l2_open(struct inode *inode, struct file *filp)
+int ivtv_v4l2_open(struct file *filp)
{
int res;
struct ivtv *itv = NULL;
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h
index df81e790147f..049a2923965d 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.h
+++ b/drivers/media/video/ivtv/ivtv-fileops.h
@@ -22,12 +22,12 @@
#define IVTV_FILEOPS_H
/* Testing/Debugging */
-int ivtv_v4l2_open(struct inode *inode, struct file *filp);
+int ivtv_v4l2_open(struct file *filp);
ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count,
loff_t * pos);
ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count,
loff_t * pos);
-int ivtv_v4l2_close(struct inode *inode, struct file *filp);
+int ivtv_v4l2_close(struct file *filp);
unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait);
unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait);
int ivtv_start_capture(struct ivtv_open_id *id);
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index cd990a4b81a9..f6b3ef6e691b 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -674,19 +674,19 @@ static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_f
return ret;
}
-static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident *chip)
+static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
chip->ident = V4L2_IDENT_NONE;
chip->revision = 0;
- if (chip->match_type == V4L2_CHIP_MATCH_HOST) {
- if (v4l2_chip_match_host(chip->match_type, chip->match_chip))
+ if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
+ if (v4l2_chip_match_host(&chip->match))
chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
return 0;
}
- if (chip->match_type != V4L2_CHIP_MATCH_I2C_DRIVER &&
- chip->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+ if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+ chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
/* TODO: is this correct? */
return ivtv_call_all_err(itv, core, g_chip_ident, chip);
@@ -695,7 +695,7 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
{
- struct v4l2_register *regs = arg;
+ struct v4l2_dbg_register *regs = arg;
volatile u8 __iomem *reg_start;
if (!capable(CAP_SYS_ADMIN))
@@ -710,6 +710,7 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
else
return -EINVAL;
+ regs->size = 4;
if (cmd == VIDIOC_DBG_G_REGISTER)
regs->val = readl(regs->reg + reg_start);
else
@@ -717,11 +718,11 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
return 0;
}
-static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg)
+static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
- if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (v4l2_chip_match_host(&reg->match))
return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
/* TODO: subdev errors should not be ignored, this should become a
subdev helper function. */
@@ -729,11 +730,11 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *re
return 0;
}
-static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg)
+static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
- if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (v4l2_chip_match_host(&reg->match))
return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
/* TODO: subdev errors should not be ignored, this should become a
subdev helper function. */
@@ -1725,7 +1726,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
return 0;
}
-static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
+static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
{
struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
@@ -1827,7 +1828,7 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
if (ivtv_debug & IVTV_DBGFLG_IOCTL)
vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
- ret = __video_ioctl2(filp, cmd, arg);
+ ret = video_ioctl2(filp, cmd, arg);
vfd->debug = 0;
return ret;
}
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index f77d764707b2..854a950af78c 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -43,24 +43,22 @@
#include "ivtv-cards.h"
#include "ivtv-streams.h"
-static const struct file_operations ivtv_v4l2_enc_fops = {
+static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
.owner = THIS_MODULE,
.read = ivtv_v4l2_read,
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
.unlocked_ioctl = ivtv_v4l2_ioctl,
- .compat_ioctl = v4l_compat_ioctl32,
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_enc_poll,
};
-static const struct file_operations ivtv_v4l2_dec_fops = {
+static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
.owner = THIS_MODULE,
.read = ivtv_v4l2_read,
.write = ivtv_v4l2_write,
.open = ivtv_v4l2_open,
.unlocked_ioctl = ivtv_v4l2_ioctl,
- .compat_ioctl = v4l_compat_ioctl32,
.release = ivtv_v4l2_close,
.poll = ivtv_v4l2_dec_poll,
};
@@ -78,7 +76,7 @@ static struct {
int num_offset;
int dma, pio;
enum v4l2_buf_type buf_type;
- const struct file_operations *fops;
+ const struct v4l2_file_operations *fops;
} ivtv_stream_info[] = {
{ /* IVTV_ENC_STREAM_TYPE_MPG */
"encoder MPG",
diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c
index 07be14a9fe7b..de397ef57b44 100644
--- a/drivers/media/video/m52790.c
+++ b/drivers/media/video/m52790.c
@@ -80,29 +80,28 @@ static int m52790_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *r
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct m52790_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (reg->reg != 0)
return -EINVAL;
+ reg->size = 1;
reg->val = state->input | state->output;
return 0;
}
-static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct m52790_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -115,7 +114,7 @@ static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
}
#endif
-static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int m52790_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 6418f4a78f2a..b76e33d5c867 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -841,7 +841,7 @@ again:
/* video4linux integration */
/****************************************************************************/
-static int meye_open(struct inode *inode, struct file *file)
+static int meye_open(struct file *file)
{
int i;
@@ -863,7 +863,7 @@ static int meye_open(struct inode *inode, struct file *file)
return 0;
}
-static int meye_release(struct inode *inode, struct file *file)
+static int meye_release(struct file *file)
{
mchip_hic_stop();
mchip_dma_free();
@@ -1577,7 +1577,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
return 0;
}
-static int vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
{
switch (cmd) {
case MEYEIOC_G_PARAMS:
@@ -1684,17 +1684,13 @@ static int meye_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
-static const struct file_operations meye_fops = {
+static const struct v4l2_file_operations meye_fops = {
.owner = THIS_MODULE,
.open = meye_open,
.release = meye_release,
.mmap = meye_mmap,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.poll = meye_poll,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops meye_ioctl_ops = {
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index a622dbb72ed8..4d7a91852117 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -483,7 +483,7 @@ static int msp_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
}
#ifdef CONFIG_VIDEO_ALLOW_V4L1
-static int msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+static long msp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct msp_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -733,7 +733,7 @@ static int msp_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
return 0;
}
-static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct msp_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 1a1a12453672..c1bf75ef2741 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -343,14 +343,14 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
}
static int mt9m001_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match_chip != mt9m001->client->addr)
+ if (id->match.addr != mt9m001->client->addr)
return -ENODEV;
id->ident = mt9m001->model;
@@ -361,16 +361,17 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9m001_get_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match_chip != mt9m001->client->addr)
+ if (reg->match.addr != mt9m001->client->addr)
return -ENODEV;
+ reg->size = 2;
reg->val = reg_read(icd, reg->reg);
if (reg->val > 0xffff)
@@ -380,14 +381,14 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
}
static int mt9m001_set_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match_chip != mt9m001->client->addr)
+ if (reg->match.addr != mt9m001->client->addr)
return -ENODEV;
if (reg_write(icd, reg->reg, reg->val) < 0)
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index c89ea41fe259..5b8e20979cce 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -514,14 +514,14 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
}
static int mt9m111_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match_chip != mt9m111->client->addr)
+ if (id->match.addr != mt9m111->client->addr)
return -ENODEV;
id->ident = mt9m111->model;
@@ -532,18 +532,19 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9m111_get_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
int val;
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
- if (reg->match_chip != mt9m111->client->addr)
+ if (reg->match.addr != mt9m111->client->addr)
return -ENODEV;
val = mt9m111_reg_read(icd, reg->reg);
+ reg->size = 2;
reg->val = (u64)val;
if (reg->val > 0xffff)
@@ -553,14 +554,14 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
}
static int mt9m111_set_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
- if (reg->match_chip != mt9m111->client->addr)
+ if (reg->match.addr != mt9m111->client->addr)
return -ENODEV;
if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0)
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 1a9d53966d06..349d8e365530 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -326,14 +326,14 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
}
static int mt9t031_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match_chip != mt9t031->client->addr)
+ if (id->match.addr != mt9t031->client->addr)
return -ENODEV;
id->ident = mt9t031->model;
@@ -344,14 +344,14 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9t031_get_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match_chip != mt9t031->client->addr)
+ if (reg->match.addr != mt9t031->client->addr)
return -ENODEV;
reg->val = reg_read(icd, reg->reg);
@@ -363,14 +363,14 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
}
static int mt9t031_set_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match_chip != mt9t031->client->addr)
+ if (reg->match.addr != mt9t031->client->addr)
return -ENODEV;
if (reg_write(icd, reg->reg, reg->val) < 0)
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 14a5f9c21ffa..b04c8cb1644d 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -422,14 +422,14 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
}
static int mt9v022_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- if (id->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
+ if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match_chip != mt9v022->client->addr)
+ if (id->match.addr != mt9v022->client->addr)
return -ENODEV;
id->ident = mt9v022->model;
@@ -440,16 +440,17 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int mt9v022_get_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match_chip != mt9v022->client->addr)
+ if (reg->match.addr != mt9v022->client->addr)
return -ENODEV;
+ reg->size = 2;
reg->val = reg_read(icd, reg->reg);
if (reg->val > 0xffff)
@@ -459,14 +460,14 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
}
static int mt9v022_set_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- if (reg->match_type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+ if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match_chip != mt9v022->client->addr)
+ if (reg->match.addr != mt9v022->client->addr)
return -ENODEV;
if (reg_write(icd, reg->reg, reg->val) < 0)
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
index 7f130284b5c7..e3cbe14c349a 100644
--- a/drivers/media/video/mxb.c
+++ b/drivers/media/video/mxb.c
@@ -489,7 +489,7 @@ static int mxb_detach(struct saa7146_dev *dev)
return 0;
}
-static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+static long mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
{
struct saa7146_dev *dev = fh->dev;
struct mxb *mxb = (struct mxb *)dev->ext_priv;
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index 85c3c7c92af1..73eb656acfe3 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1454,9 +1454,9 @@ static int omap24xxcam_mmap(struct file *file, struct vm_area_struct *vma)
return rval;
}
-static int omap24xxcam_open(struct inode *inode, struct file *file)
+static int omap24xxcam_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct omap24xxcam_device *cam = omap24xxcam.priv;
struct omap24xxcam_fh *fh;
struct v4l2_format format;
@@ -1511,7 +1511,7 @@ out_try_module_get:
return -ENODEV;
}
-static int omap24xxcam_release(struct inode *inode, struct file *file)
+static int omap24xxcam_release(struct file *file)
{
struct omap24xxcam_fh *fh = file->private_data;
struct omap24xxcam_device *cam = fh->cam;
@@ -1559,8 +1559,7 @@ static int omap24xxcam_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations omap24xxcam_fops = {
- .llseek = no_llseek,
+static struct v4l2_file_operations omap24xxcam_fops = {
.ioctl = video_ioctl2,
.poll = omap24xxcam_poll,
.mmap = omap24xxcam_mmap,
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index 6ee9b69cc4a9..9af5532db142 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -3915,7 +3915,7 @@ ov51x_dealloc(struct usb_ov511 *ov)
***************************************************************************/
static int
-ov51x_v4l1_open(struct inode *inode, struct file *file)
+ov51x_v4l1_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct usb_ov511 *ov = video_get_drvdata(vdev);
@@ -3972,7 +3972,7 @@ out:
}
static int
-ov51x_v4l1_close(struct inode *inode, struct file *file)
+ov51x_v4l1_close(struct file *file)
{
struct video_device *vdev = file->private_data;
struct usb_ov511 *ov = video_get_drvdata(vdev);
@@ -4010,7 +4010,7 @@ ov51x_v4l1_close(struct inode *inode, struct file *file)
}
/* Do not call this function directly! */
-static int
+static long
ov51x_v4l1_ioctl_internal(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = file->private_data;
@@ -4449,8 +4449,8 @@ redo:
return 0;
}
-static int
-ov51x_v4l1_ioctl(struct inode *inode, struct file *file,
+static long
+ov51x_v4l1_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct video_device *vdev = file->private_data;
@@ -4661,17 +4661,13 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
-static const struct file_operations ov511_fops = {
+static const struct v4l2_file_operations ov511_fops = {
.owner = THIS_MODULE,
.open = ov51x_v4l1_open,
.release = ov51x_v4l1_close,
.read = ov51x_v4l1_read,
.mmap = ov51x_v4l1_mmap,
.ioctl = ov51x_v4l1_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device vdev_template = {
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index ea032f5f2f41..05c14a29375a 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -1310,7 +1310,7 @@ static int ov7670_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
switch (cmd) {
- case VIDIOC_G_CHIP_IDENT:
+ case VIDIOC_DBG_G_CHIP_IDENT:
return v4l2_chip_ident_i2c_client(client, arg, V4L2_IDENT_OV7670, 0);
case VIDIOC_INT_RESET:
@@ -1347,7 +1347,6 @@ static struct i2c_driver ov7670_driver = {
.name = "ov7670",
},
.id = I2C_DRIVERID_OV7670,
- .class = I2C_CLASS_CAM_DIGITAL,
.attach_adapter = ov7670_attach,
.detach_client = ov7670_detach,
.command = ov7670_command,
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 54b736fcc07a..3c9e0ba974e9 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -724,7 +724,7 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
}
static int ov772x_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
@@ -736,11 +736,12 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int ov772x_get_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
int ret;
+ reg->size = 1;
if (reg->reg > 0xff)
return -EINVAL;
@@ -754,7 +755,7 @@ static int ov772x_get_register(struct soc_camera_device *icd,
}
static int ov772x_set_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 2c4acbf5a4fe..c841f4e4fbe4 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -405,7 +405,6 @@ static struct i2c_driver driver = {
.name = "ovcamchip",
},
.id = I2C_DRIVERID_OVCAMCHIP,
- .class = I2C_CLASS_CAM_DIGITAL,
.attach_adapter = ovcamchip_attach,
.detach_client = ovcamchip_detach,
.command = ovcamchip_command,
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 45730fac1570..a1ad38fc49c1 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -680,7 +680,7 @@ static int pms_capture(struct pms_device *dev, char __user *buf, int rgb555, int
* Video4linux interfacing
*/
-static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long pms_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *dev = video_devdata(file);
struct pms_device *pd=(struct pms_device *)dev;
@@ -862,7 +862,7 @@ static int pms_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int pms_ioctl(struct inode *inode, struct file *file,
+static long pms_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, pms_do_ioctl);
@@ -881,7 +881,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
return len;
}
-static int pms_exclusive_open(struct inode *inode, struct file *file)
+static int pms_exclusive_open(struct file *file)
{
struct video_device *v = video_devdata(file);
struct pms_device *pd = (struct pms_device *)v;
@@ -889,7 +889,7 @@ static int pms_exclusive_open(struct inode *inode, struct file *file)
return test_and_set_bit(0, &pd->in_use) ? -EBUSY : 0;
}
-static int pms_exclusive_release(struct inode *inode, struct file *file)
+static int pms_exclusive_release(struct file *file)
{
struct video_device *v = video_devdata(file);
struct pms_device *pd = (struct pms_device *)v;
@@ -898,16 +898,12 @@ static int pms_exclusive_release(struct inode *inode, struct file *file)
return 0;
}
-static const struct file_operations pms_fops = {
+static const struct v4l2_file_operations pms_fops = {
.owner = THIS_MODULE,
.open = pms_exclusive_open,
.release = pms_exclusive_release,
.ioctl = pms_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = pms_read,
- .llseek = no_llseek,
};
static struct video_device pms_template=
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 4358079f1966..fa304e5f252a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -3655,7 +3655,7 @@ void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
int ret;
pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
ret = usb_lock_device_for_reset(hdw->usb_dev,NULL);
- if (ret == 1) {
+ if (ret == 0) {
ret = usb_reset_device(hdw->usb_dev);
usb_unlock_device(hdw->usb_dev);
} else {
@@ -4732,26 +4732,25 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
- u32 match_type, u32 match_chip, u64 reg_id,
- int setFl,u64 *val_ptr)
+ struct v4l2_dbg_match *match, u64 reg_id,
+ int setFl, u64 *val_ptr)
{
#ifdef CONFIG_VIDEO_ADV_DEBUG
struct pvr2_i2c_client *cp;
- struct v4l2_register req;
+ struct v4l2_dbg_register req;
int stat = 0;
int okFl = 0;
if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- req.match_type = match_type;
- req.match_chip = match_chip;
+ req.match = *match;
req.reg = reg_id;
if (setFl) req.val = *val_ptr;
mutex_lock(&hdw->i2c_list_lock); do {
list_for_each_entry(cp, &hdw->i2c_clients, list) {
if (!v4l2_chip_match_i2c_client(
cp->client,
- req.match_type, req.match_chip)) {
+ &req.match)) {
continue;
}
stat = pvr2_i2c_client_cmd(
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 49482d1f2b28..1b4fec337c6b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -242,8 +242,8 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
setFl - true to set the register, false to read it
val_ptr - storage location for source / result. */
int pvr2_hdw_register_access(struct pvr2_hdw *,
- u32 match_type, u32 match_chip,u64 reg_id,
- int setFl,u64 *val_ptr);
+ struct v4l2_dbg_match *match, u64 reg_id,
+ int setFl, u64 *val_ptr);
/* The following entry points are all lower level things you normally don't
want to worry about. */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 52af1c435965..878fd52a73b3 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -168,13 +168,13 @@ static const char *get_v4l_name(int v4l_type)
* This is part of Video 4 Linux API. The procedure handles ioctl() calls.
*
*/
-static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct pvr2_v4l2_fh *fh = file->private_data;
struct pvr2_v4l2 *vp = fh->vhead;
struct pvr2_v4l2_dev *dev_info = fh->dev_info;
struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
- int ret = -EINVAL;
+ long ret = -EINVAL;
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
@@ -851,11 +851,11 @@ static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_DBG_G_REGISTER:
{
u64 val;
- struct v4l2_register *req = (struct v4l2_register *)arg;
+ struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg;
if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
ret = pvr2_hdw_register_access(
- hdw,req->match_type,req->match_chip,req->reg,
- cmd == VIDIOC_DBG_S_REGISTER,&val);
+ hdw, &req->match, req->reg,
+ cmd == VIDIOC_DBG_S_REGISTER, &val);
if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
break;
}
@@ -871,20 +871,20 @@ static int pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
if (ret < 0) {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
- "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
+ "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
} else {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
- "pvr2_v4l2_do_ioctl failure, ret=%d"
- " command was:",ret);
+ "pvr2_v4l2_do_ioctl failure, ret=%ld"
+ " command was:", ret);
v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
cmd);
}
}
} else {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
- "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
- ret,ret);
+ "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
+ ret, ret);
}
return ret;
}
@@ -948,7 +948,7 @@ static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
}
-static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
+static long pvr2_v4l2_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -960,7 +960,7 @@ static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
}
-static int pvr2_v4l2_release(struct inode *inode, struct file *file)
+static int pvr2_v4l2_release(struct file *file)
{
struct pvr2_v4l2_fh *fhp = file->private_data;
struct pvr2_v4l2 *vp = fhp->vhead;
@@ -1008,7 +1008,7 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
}
-static int pvr2_v4l2_open(struct inode *inode, struct file *file)
+static int pvr2_v4l2_open(struct file *file)
{
struct pvr2_v4l2_dev *dip; /* Our own context pointer */
struct pvr2_v4l2_fh *fhp;
@@ -1235,13 +1235,12 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
}
-static const struct file_operations vdev_fops = {
+static const struct v4l2_file_operations vdev_fops = {
.owner = THIS_MODULE,
.open = pvr2_v4l2_open,
.release = pvr2_v4l2_release,
.read = pvr2_v4l2_read,
.ioctl = pvr2_v4l2_ioctl,
- .llseek = no_llseek,
.poll = pvr2_v4l2_poll,
};
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index c66530210192..f9fbe02e0f69 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -1266,9 +1266,9 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
/* copy local variable to arg */
#define ARG_OUT(ARG_name) /* nothing */
-int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
+long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
{
- int ret = 0;
+ long ret = 0;
switch(cmd) {
case VIDIOCPWCRUSER:
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 1ce9da167b7e..0d810189dd87 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -62,7 +62,6 @@
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <linux/version.h>
#include <asm/io.h>
#include "pwc.h"
@@ -142,16 +141,16 @@ static struct {
/***/
-static int pwc_video_open(struct inode *inode, struct file *file);
-static int pwc_video_close(struct inode *inode, struct file *file);
+static int pwc_video_open(struct file *file);
+static int pwc_video_close(struct file *file);
static ssize_t pwc_video_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
-static int pwc_video_ioctl(struct inode *inode, struct file *file,
+static long pwc_video_ioctl(struct file *file,
unsigned int ioctlnr, unsigned long arg);
static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
-static const struct file_operations pwc_fops = {
+static const struct v4l2_file_operations pwc_fops = {
.owner = THIS_MODULE,
.open = pwc_video_open,
.release = pwc_video_close,
@@ -159,10 +158,6 @@ static const struct file_operations pwc_fops = {
.poll = pwc_video_poll,
.mmap = pwc_video_mmap,
.ioctl = pwc_video_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device pwc_template = {
.name = "Philips Webcam", /* Filled in later */
@@ -1104,7 +1099,7 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
/***************************************************************************/
/* Video4Linux functions */
-static int pwc_video_open(struct inode *inode, struct file *file)
+static int pwc_video_open(struct file *file)
{
int i, ret;
struct video_device *vdev = video_devdata(file);
@@ -1224,7 +1219,7 @@ static void pwc_cleanup(struct pwc_device *pdev)
}
/* Note that all cleanup is done in the reverse order as in _open */
-static int pwc_video_close(struct inode *inode, struct file *file)
+static int pwc_video_close(struct file *file)
{
struct video_device *vdev = file->private_data;
struct pwc_device *pdev;
@@ -1399,12 +1394,12 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
return 0;
}
-static int pwc_video_ioctl(struct inode *inode, struct file *file,
+static long pwc_video_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct video_device *vdev = file->private_data;
struct pwc_device *pdev;
- int r = -ENODEV;
+ long r = -ENODEV;
if (!vdev)
goto out;
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index d7c147328e35..bc0a464295c5 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -337,7 +337,7 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
}
-int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct pwc_device *pdev;
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index c046a2535668..01411fb2337a 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -337,10 +337,10 @@ extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
extern int pwc_camera_power(struct pwc_device *pdev, int power);
/* Private ioctl()s; see pwc-ioctl.h */
-extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
+extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
/** Functions in pwc-v4l.c */
-extern int pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
+extern long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
/** pwc-uncompress.c */
/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 9d33de22cc48..a1d6008efcbb 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -34,12 +34,10 @@
#include <linux/videodev2.h>
-#include <asm/dma.h>
+#include <mach/dma.h>
#include <mach/pxa-regs.h>
#include <mach/camera.h>
-#include "pxa_camera.h"
-
#define PXA_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
#define PXA_CAM_DRV_NAME "pxa27x-camera"
diff --git a/drivers/media/video/pxa_camera.h b/drivers/media/video/pxa_camera.h
deleted file mode 100644
index 89cbfc9a35c5..000000000000
--- a/drivers/media/video/pxa_camera.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Camera Interface */
-#define CICR0 __REG(0x50000000)
-#define CICR1 __REG(0x50000004)
-#define CICR2 __REG(0x50000008)
-#define CICR3 __REG(0x5000000C)
-#define CICR4 __REG(0x50000010)
-#define CISR __REG(0x50000014)
-#define CIFR __REG(0x50000018)
-#define CITOR __REG(0x5000001C)
-#define CIBR0 __REG(0x50000028)
-#define CIBR1 __REG(0x50000030)
-#define CIBR2 __REG(0x50000038)
-
-#define CICR0_DMAEN (1 << 31) /* DMA request enable */
-#define CICR0_PAR_EN (1 << 30) /* Parity enable */
-#define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */
-#define CICR0_ENB (1 << 28) /* Camera interface enable */
-#define CICR0_DIS (1 << 27) /* Camera interface disable */
-#define CICR0_SIM (0x7 << 24) /* Sensor interface mode mask */
-#define CICR0_TOM (1 << 9) /* Time-out mask */
-#define CICR0_RDAVM (1 << 8) /* Receive-data-available mask */
-#define CICR0_FEM (1 << 7) /* FIFO-empty mask */
-#define CICR0_EOLM (1 << 6) /* End-of-line mask */
-#define CICR0_PERRM (1 << 5) /* Parity-error mask */
-#define CICR0_QDM (1 << 4) /* Quick-disable mask */
-#define CICR0_CDM (1 << 3) /* Disable-done mask */
-#define CICR0_SOFM (1 << 2) /* Start-of-frame mask */
-#define CICR0_EOFM (1 << 1) /* End-of-frame mask */
-#define CICR0_FOM (1 << 0) /* FIFO-overrun mask */
-
-#define CICR1_TBIT (1 << 31) /* Transparency bit */
-#define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */
-#define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */
-#define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */
-#define CICR1_RGB_F (1 << 11) /* RGB format */
-#define CICR1_YCBCR_F (1 << 10) /* YCbCr format */
-#define CICR1_RGB_BPP (0x7 << 7) /* RGB bis per pixel mask */
-#define CICR1_RAW_BPP (0x3 << 5) /* Raw bis per pixel mask */
-#define CICR1_COLOR_SP (0x3 << 3) /* Color space mask */
-#define CICR1_DW (0x7 << 0) /* Data width mask */
-
-#define CICR2_BLW (0xff << 24) /* Beginning-of-line pixel clock
- wait count mask */
-#define CICR2_ELW (0xff << 16) /* End-of-line pixel clock
- wait count mask */
-#define CICR2_HSW (0x3f << 10) /* Horizontal sync pulse width mask */
-#define CICR2_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock
- wait count mask */
-#define CICR2_FSW (0x7 << 0) /* Frame stabilization
- wait count mask */
-
-#define CICR3_BFW (0xff << 24) /* Beginning-of-frame line clock
- wait count mask */
-#define CICR3_EFW (0xff << 16) /* End-of-frame line clock
- wait count mask */
-#define CICR3_VSW (0x3f << 10) /* Vertical sync pulse width mask */
-#define CICR3_BFPW (0x3f << 3) /* Beginning-of-frame pixel clock
- wait count mask */
-#define CICR3_LPF (0x7ff << 0) /* Lines per frame mask */
-
-#define CICR4_MCLK_DLY (0x3 << 24) /* MCLK Data Capture Delay mask */
-#define CICR4_PCLK_EN (1 << 23) /* Pixel clock enable */
-#define CICR4_PCP (1 << 22) /* Pixel clock polarity */
-#define CICR4_HSP (1 << 21) /* Horizontal sync polarity */
-#define CICR4_VSP (1 << 20) /* Vertical sync polarity */
-#define CICR4_MCLK_EN (1 << 19) /* MCLK enable */
-#define CICR4_FR_RATE (0x7 << 8) /* Frame rate mask */
-#define CICR4_DIV (0xff << 0) /* Clock divisor mask */
-
-#define CISR_FTO (1 << 15) /* FIFO time-out */
-#define CISR_RDAV_2 (1 << 14) /* Channel 2 receive data available */
-#define CISR_RDAV_1 (1 << 13) /* Channel 1 receive data available */
-#define CISR_RDAV_0 (1 << 12) /* Channel 0 receive data available */
-#define CISR_FEMPTY_2 (1 << 11) /* Channel 2 FIFO empty */
-#define CISR_FEMPTY_1 (1 << 10) /* Channel 1 FIFO empty */
-#define CISR_FEMPTY_0 (1 << 9) /* Channel 0 FIFO empty */
-#define CISR_EOL (1 << 8) /* End of line */
-#define CISR_PAR_ERR (1 << 7) /* Parity error */
-#define CISR_CQD (1 << 6) /* Camera interface quick disable */
-#define CISR_CDD (1 << 5) /* Camera interface disable done */
-#define CISR_SOF (1 << 4) /* Start of frame */
-#define CISR_EOF (1 << 3) /* End of frame */
-#define CISR_IFO_2 (1 << 2) /* FIFO overrun for Channel 2 */
-#define CISR_IFO_1 (1 << 1) /* FIFO overrun for Channel 1 */
-#define CISR_IFO_0 (1 << 0) /* FIFO overrun for Channel 0 */
-
-#define CIFR_FLVL2 (0x7f << 23) /* FIFO 2 level mask */
-#define CIFR_FLVL1 (0x7f << 16) /* FIFO 1 level mask */
-#define CIFR_FLVL0 (0xff << 8) /* FIFO 0 level mask */
-#define CIFR_THL_0 (0x3 << 4) /* Threshold Level for Channel 0 FIFO */
-#define CIFR_RESET_F (1 << 3) /* Reset input FIFOs */
-#define CIFR_FEN2 (1 << 2) /* FIFO enable for channel 2 */
-#define CIFR_FEN1 (1 << 1) /* FIFO enable for channel 1 */
-#define CIFR_FEN0 (1 << 0) /* FIFO enable for channel 0 */
-
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 3c3f8cf73108..13f85ad363cd 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -1502,9 +1502,9 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv,
dprintk(2, "setting jpeg quality %d\n", jc->quality);
return 0;
}
-static int s2255_open(struct inode *inode, struct file *file)
+static int s2255_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct s2255_dev *h, *dev = NULL;
struct s2255_fh *fh;
struct list_head *list;
@@ -1711,11 +1711,11 @@ static void s2255_destroy(struct kref *kref)
mutex_unlock(&dev->open_lock);
}
-static int s2255_close(struct inode *inode, struct file *file)
+static int s2255_close(struct file *file)
{
struct s2255_fh *fh = file->private_data;
struct s2255_dev *dev = fh->dev;
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
if (!dev)
return -ENODEV;
@@ -1759,15 +1759,13 @@ static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma)
return ret;
}
-static const struct file_operations s2255_fops_v4l = {
+static const struct v4l2_file_operations s2255_fops_v4l = {
.owner = THIS_MODULE,
.open = s2255_open,
.release = s2255_close,
.poll = s2255_poll,
.ioctl = video_ioctl2, /* V4L2 ioctl handler */
- .compat_ioctl = v4l_compat_ioctl32,
.mmap = s2255_mmap_v4l,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops s2255_ioctl_ops = {
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index f159441e9375..e637e440b6d5 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -804,7 +804,7 @@ static inline int saa5246a_stop_dau(struct saa5246a_device *t,
*
* Returns 0 if successful
*/
-static int do_saa5246a_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long do_saa5246a_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct saa5246a_device *t = video_drvdata(file);
@@ -944,11 +944,11 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
/*
* Handle the locking
*/
-static int saa5246a_ioctl(struct inode *inode, struct file *file,
+static long saa5246a_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct saa5246a_device *t = video_drvdata(file);
- int err;
+ long err;
cmd = vtx_fix_command(cmd);
mutex_lock(&t->lock);
@@ -957,7 +957,7 @@ static int saa5246a_ioctl(struct inode *inode, struct file *file,
return err;
}
-static int saa5246a_open(struct inode *inode, struct file *file)
+static int saa5246a_open(struct file *file)
{
struct saa5246a_device *t = video_drvdata(file);
@@ -999,7 +999,7 @@ static int saa5246a_open(struct inode *inode, struct file *file)
return 0;
}
-static int saa5246a_release(struct inode *inode, struct file *file)
+static int saa5246a_release(struct file *file)
{
struct saa5246a_device *t = video_drvdata(file);
@@ -1018,12 +1018,11 @@ static int saa5246a_release(struct inode *inode, struct file *file)
return 0;
}
-static const struct file_operations saa_fops = {
+static const struct v4l2_file_operations saa_fops = {
.owner = THIS_MODULE,
.open = saa5246a_open,
.release = saa5246a_release,
.ioctl = saa5246a_ioctl,
- .llseek = no_llseek,
};
static struct video_device saa_template =
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 6ef3affb97f1..e29765192469 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -190,7 +190,7 @@ static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
* Standard character-device-driver functions
*/
-static int do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg)
{
static int virtual_mode = false;
struct saa5249_device *t = video_drvdata(file);
@@ -479,11 +479,11 @@ static inline unsigned int vtx_fix_command(unsigned int cmd)
* Handle the locking
*/
-static int saa5249_ioctl(struct inode *inode, struct file *file,
+static long saa5249_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct saa5249_device *t = video_drvdata(file);
- int err;
+ long err;
cmd = vtx_fix_command(cmd);
mutex_lock(&t->lock);
@@ -492,7 +492,7 @@ static int saa5249_ioctl(struct inode *inode, struct file *file,
return err;
}
-static int saa5249_open(struct inode *inode, struct file *file)
+static int saa5249_open(struct file *file)
{
struct saa5249_device *t = video_drvdata(file);
int pgbuf;
@@ -529,7 +529,7 @@ static int saa5249_open(struct inode *inode, struct file *file)
-static int saa5249_release(struct inode *inode, struct file *file)
+static int saa5249_release(struct file *file)
{
struct saa5249_device *t = video_drvdata(file);
@@ -539,15 +539,11 @@ static int saa5249_release(struct inode *inode, struct file *file)
return 0;
}
-static const struct file_operations saa_fops = {
+static const struct v4l2_file_operations saa_fops = {
.owner = THIS_MODULE,
.open = saa5249_open,
.release = saa5249_release,
.ioctl = saa5249_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device saa_template =
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 22708ecdf1bb..46c796c3fec8 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1371,25 +1371,24 @@ static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_dat
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = saa711x_read(sd, reg->reg & 0xff);
+ reg->size = 1;
return 0;
}
-static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -1398,7 +1397,7 @@ static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
}
#endif
-static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct saa711x_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index bfc85654795e..05221d47dd4c 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -149,7 +149,7 @@ static const struct i2c_reg_value saa7127_init_config_common[] = {
{ SAA7127_REG_COPYGEN_0, 0x77 },
{ SAA7127_REG_COPYGEN_1, 0x41 },
{ SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */
- { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e },
+ { SAA7127_REG_OUTPUT_PORT_CONTROL, 0xbf },
{ SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 },
{ SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 },
{ SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */
@@ -488,12 +488,18 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
break;
case SAA7127_OUTPUT_TYPE_COMPOSITE:
- state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
+ if (state->ident == V4L2_IDENT_SAA7129)
+ state->reg_2d = 0x20; /* CVBS only */
+ else
+ state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
break;
case SAA7127_OUTPUT_TYPE_SVIDEO:
- state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */
+ if (state->ident == V4L2_IDENT_SAA7129)
+ state->reg_2d = 0x18; /* Y + C */
+ else
+ state->reg_2d = 0xff; /*11111111 croma -> R, luma -> CVBS + G + B */
state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
break;
@@ -508,7 +514,10 @@ static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
break;
case SAA7127_OUTPUT_TYPE_BOTH:
- state->reg_2d = 0xbf;
+ if (state->ident == V4L2_IDENT_SAA7129)
+ state->reg_2d = 0x38;
+ else
+ state->reg_2d = 0xbf;
state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
break;
@@ -623,25 +632,24 @@ static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_v
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = saa7127_read(sd, reg->reg & 0xff);
+ reg->size = 1;
return 0;
}
-static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -650,7 +658,7 @@ static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
}
#endif
-static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct saa7127_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -732,24 +740,6 @@ static int saa7127_probe(struct i2c_client *client,
return -ENODEV;
}
- /* Configure Encoder */
-
- v4l2_dbg(1, debug, sd, "Configuring encoder\n");
- saa7127_write_inittab(sd, saa7127_init_config_common);
- saa7127_set_std(sd, V4L2_STD_NTSC);
- saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
- saa7127_set_vps(sd, &vbi);
- saa7127_set_wss(sd, &vbi);
- saa7127_set_cc(sd, &vbi);
- saa7127_set_xds(sd, &vbi);
- if (test_image == 1)
- /* The Encoder has an internal Colorbar generator */
- /* This can be used for debugging */
- saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
- else
- saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
- saa7127_set_video_enable(sd, 1);
-
if (id->driver_data) { /* Chip type is already known */
state->ident = id->driver_data;
} else { /* Needs detection */
@@ -771,6 +761,23 @@ static int saa7127_probe(struct i2c_client *client,
v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
client->addr << 1, client->adapter->name);
+
+ v4l2_dbg(1, debug, sd, "Configuring encoder\n");
+ saa7127_write_inittab(sd, saa7127_init_config_common);
+ saa7127_set_std(sd, V4L2_STD_NTSC);
+ saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
+ saa7127_set_vps(sd, &vbi);
+ saa7127_set_wss(sd, &vbi);
+ saa7127_set_cc(sd, &vbi);
+ saa7127_set_xds(sd, &vbi);
+ if (test_image == 1)
+ /* The Encoder has an internal Colorbar generator */
+ /* This can be used for debugging */
+ saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
+ else
+ saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
+ saa7127_set_video_enable(sd, 1);
+
if (state->ident == V4L2_IDENT_SAA7129)
saa7127_write_inittab(sd, saa7129_init_config_extra);
return 0;
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 1fb6eccdade3..1fee6e84a512 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -838,7 +838,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
h->standard = *((v4l2_std_id *) arg);
break;
- case VIDIOC_G_CHIP_IDENT:
+ case VIDIOC_DBG_G_CHIP_IDENT:
return v4l2_chip_ident_i2c_client(client,
arg, h->chip, h->revision);
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 26194a0ce927..c750d3dd57d2 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -1089,7 +1089,11 @@ static int saa7134_alsa_init(void)
list_for_each(list,&saa7134_devlist) {
dev = list_entry(list, struct saa7134_dev, devlist);
- alsa_device_init(dev);
+ if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
+ printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n",
+ dev->name, saa7134_boards[dev->board].name);
+ else
+ alsa_device_init(dev);
}
if (dev == NULL)
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index a2e3f6729c5b..e2febcd6e529 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -4462,6 +4462,7 @@ struct saa7134_board saa7134_boards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
+ .mpeg = SAA7134_MPEG_DVB,
.inputs = {{
.name = name_tv,
.vmux = 3,
@@ -4480,8 +4481,6 @@ struct saa7134_board saa7134_boards[] = {
.name = name_radio,
.amux = LINE2,
},
- /* no DVB support for now */
- /* .mpeg = SAA7134_MPEG_DVB, */
},
[SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = {
.name = "Asus Tiger 3in1",
@@ -4643,6 +4642,38 @@ struct saa7134_board saa7134_boards[] = {
.amux = 2,
},
},
+ [SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = {
+ .name = "Avermedia AVerTV GO 007 FM Plus",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .gpiomask = 0x00300003,
+ /* .gpiomask = 0x8c240003, */
+ .inputs = { {
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x01,
+ }, {
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE1,
+ .gpio = 0x02,
+ } },
+ .radio = {
+ .name = name_radio,
+ .amux = TV,
+ .gpio = 0x00300001,
+ },
+ .mute = {
+ .name = name_mute,
+ .amux = TV,
+ .gpio = 0x01,
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -5702,6 +5733,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x7128,
.driver_data = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG,
}, {
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xf31d,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS,
+
+ }, {
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5930,6 +5968,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
case SAA7134_BOARD_REAL_ANGEL_220:
case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
+ case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
dev->has_remote = SAA7134_REMOTE_GPIO;
break;
case SAA7134_BOARD_FLYDVBS_LR300:
@@ -6025,6 +6064,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_BEHOLD_M6:
case SAA7134_BOARD_BEHOLD_M63:
case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+ case SAA7134_BOARD_BEHOLD_H6:
dev->has_remote = SAA7134_REMOTE_I2C;
break;
case SAA7134_BOARD_AVERMEDIA_A169_B:
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index dfbe08a9ad9b..99221d726edb 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -660,6 +660,10 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, 0);
+
+ /* Clear any stale IRQ reports */
+ saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT));
+
mutex_init(&dev->lock);
spin_lock_init(&dev->slock);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index d9a5652595b5..0776ecf56d27 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -49,6 +49,8 @@
#include "lnbp21.h"
#include "tuner-simple.h"
+#include "zl10353.h"
+
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
MODULE_LICENSE("GPL");
@@ -854,6 +856,12 @@ static struct tda1004x_config ads_tech_duo_config = {
.request_firmware = philips_tda1004x_request_firmware
};
+static struct zl10353_config behold_h6_config = {
+ .demod_address = 0x1e>>1,
+ .no_tuner = 1,
+ .parallel_ts = 1,
+};
+
/* ==================================================================
* tda10086 based DVB-S cards, helper functions
*/
@@ -1357,6 +1365,16 @@ static int dvb_init(struct saa7134_dev *dev)
&tda827x_cfg_0) < 0)
goto dettach_frontend;
break;
+ case SAA7134_BOARD_BEHOLD_H6:
+ fe0->dvb.frontend = dvb_attach(zl10353_attach,
+ &behold_h6_config,
+ &dev->i2c_adap);
+ if (fe0->dvb.frontend) {
+ dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+ &dev->i2c_adap, 0x61,
+ TUNER_PHILIPS_FMD1216ME_MK3);
+ }
+ break;
default:
wprintk("Huh? unknown DVB card?\n");
break;
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 7f40511bcc04..c9d8beb87a60 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -83,9 +83,9 @@ static int ts_init_encoder(struct saa7134_dev* dev)
/* ------------------------------------------------------------------ */
-static int ts_open(struct inode *inode, struct file *file)
+static int ts_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct saa7134_dev *dev;
int err;
@@ -119,7 +119,7 @@ done:
return err;
}
-static int ts_release(struct inode *inode, struct file *file)
+static int ts_release(struct file *file)
{
struct saa7134_dev *dev = file->private_data;
@@ -405,7 +405,7 @@ static int empress_querymenu(struct file *file, void *priv,
}
static int empress_g_chip_ident(struct file *file, void *fh,
- struct v4l2_chip_ident *chip)
+ struct v4l2_dbg_chip_ident *chip)
{
struct saa7134_dev *dev = file->private_data;
@@ -413,12 +413,12 @@ static int empress_g_chip_ident(struct file *file, void *fh,
chip->revision = 0;
if (dev->mpeg_i2c_client == NULL)
return -EINVAL;
- if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER &&
- chip->match_chip == I2C_DRIVERID_SAA6752HS)
- return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
- if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR &&
- chip->match_chip == dev->mpeg_i2c_client->addr)
- return saa7134_i2c_call_saa6752(dev, VIDIOC_G_CHIP_IDENT, chip);
+ if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
+ !strcmp(chip->match.name, "saa6752hs"))
+ return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
+ if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR &&
+ chip->match.addr == dev->mpeg_i2c_client->addr)
+ return saa7134_i2c_call_saa6752(dev, VIDIOC_DBG_G_CHIP_IDENT, chip);
return -EINVAL;
}
@@ -437,7 +437,7 @@ static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
return 0;
}
-static const struct file_operations ts_fops =
+static const struct v4l2_file_operations ts_fops =
{
.owner = THIS_MODULE,
.open = ts_open,
@@ -446,7 +446,6 @@ static const struct file_operations ts_fops =
.poll = ts_poll,
.mmap = ts_mmap,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops ts_ioctl_ops = {
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index d2124f64e4e2..8a106d36e723 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -449,6 +449,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
case SAA7134_BOARD_AVERMEDIA_M102:
+ case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
ir_codes = ir_codes_avermedia;
mask_keycode = 0x0007C8;
mask_keydown = 0x000010;
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 02bb6747a39c..a1f7e351f572 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1326,9 +1326,9 @@ static int saa7134_resource(struct saa7134_fh *fh)
return 0;
}
-static int video_open(struct inode *inode, struct file *file)
+static int video_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct saa7134_dev *dev;
struct saa7134_fh *fh;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1462,7 +1462,7 @@ err:
return POLLERR;
}
-static int video_release(struct inode *inode, struct file *file)
+static int video_release(struct file *file)
{
struct saa7134_fh *fh = file->private_data;
struct saa7134_dev *dev = fh->dev;
@@ -2247,24 +2247,25 @@ static int saa7134_g_parm(struct file *file, void *fh,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register (struct file *file, void *priv,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct saa7134_fh *fh = priv;
struct saa7134_dev *dev = fh->dev;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
reg->val = saa_readb(reg->reg);
+ reg->size = 1;
return 0;
}
static int vidioc_s_register (struct file *file, void *priv,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct saa7134_fh *fh = priv;
struct saa7134_dev *dev = fh->dev;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
saa_writeb(reg->reg&0xffffff, reg->val);
return 0;
@@ -2377,7 +2378,7 @@ static int radio_queryctrl(struct file *file, void *priv,
return 0;
}
-static const struct file_operations video_fops =
+static const struct v4l2_file_operations video_fops =
{
.owner = THIS_MODULE,
.open = video_open,
@@ -2386,8 +2387,6 @@ static const struct file_operations video_fops =
.poll = video_poll,
.mmap = video_mmap,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -2441,13 +2440,11 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
#endif
};
-static const struct file_operations radio_fops = {
+static const struct v4l2_file_operations radio_fops = {
.owner = THIS_MODULE,
.open = video_open,
.release = video_release,
.ioctl = video_ioctl2,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops radio_ioctl_ops = {
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index f6c1fcc72070..14ee265f3374 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -276,6 +276,7 @@ struct saa7134_format {
#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI 151
#define SAA7134_BOARD_ASUSTeK_TIGER 152
#define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
+#define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
#define SAA7134_MAXBOARDS 32
#define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c
index 9befca65905e..88c5e942f751 100644
--- a/drivers/media/video/saa717x.c
+++ b/drivers/media/video/saa717x.c
@@ -30,7 +30,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -1171,25 +1170,26 @@ static int saa717x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa717x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = saa717x_read(sd, reg->reg);
+ reg->size = 1;
return 0;
}
-static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
u16 addr = reg->reg & 0xffff;
u8 val = reg->val & 0xff;
- if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
diff --git a/drivers/media/video/se401.c b/drivers/media/video/se401.c
index d652f25eef0e..5990ab38a124 100644
--- a/drivers/media/video/se401.c
+++ b/drivers/media/video/se401.c
@@ -932,7 +932,7 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401)
***************************************************************************/
-static int se401_open(struct inode *inode, struct file *file)
+static int se401_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct usb_se401 *se401 = (struct usb_se401 *)dev;
@@ -954,7 +954,7 @@ static int se401_open(struct inode *inode, struct file *file)
return err;
}
-static int se401_close(struct inode *inode, struct file *file)
+static int se401_close(struct file *file)
{
struct video_device *dev = file->private_data;
struct usb_se401 *se401 = (struct usb_se401 *)dev;
@@ -975,7 +975,7 @@ static int se401_close(struct inode *inode, struct file *file)
return 0;
}
-static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = file->private_data;
struct usb_se401 *se401 = (struct usb_se401 *)vdev;
@@ -1138,7 +1138,7 @@ static int se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int se401_ioctl(struct inode *inode, struct file *file,
+static long se401_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, se401_do_ioctl);
@@ -1222,17 +1222,13 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
-static const struct file_operations se401_fops = {
+static const struct v4l2_file_operations se401_fops = {
.owner = THIS_MODULE,
.open = se401_open,
.release = se401_close,
.read = se401_read,
.mmap = se401_mmap,
.ioctl = se401_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device se401_template = {
.name = "se401 USB camera",
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index 01a8efb8deb1..23edfdc4d4bc 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -1746,7 +1746,7 @@ static void sn9c102_release_resources(struct kref *kref)
}
-static int sn9c102_open(struct inode* inode, struct file* filp)
+static int sn9c102_open(struct file *filp)
{
struct sn9c102_device* cam;
int err = 0;
@@ -1857,7 +1857,7 @@ out:
}
-static int sn9c102_release(struct inode* inode, struct file* filp)
+static int sn9c102_release(struct file *filp)
{
struct sn9c102_device* cam;
@@ -3092,8 +3092,8 @@ sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
}
-static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+static long sn9c102_ioctl_v4l2(struct file *filp,
+ unsigned int cmd, void __user *arg)
{
struct sn9c102_device *cam = video_drvdata(filp);
@@ -3196,7 +3196,7 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
}
-static int sn9c102_ioctl(struct inode* inode, struct file* filp,
+static long sn9c102_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct sn9c102_device *cam = video_drvdata(filp);
@@ -3220,7 +3220,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
V4LDBG(3, "sn9c102", cmd);
- err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+ err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
mutex_unlock(&cam->fileop_mutex);
@@ -3229,18 +3229,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
/*****************************************************************************/
-static const struct file_operations sn9c102_fops = {
+static const struct v4l2_file_operations sn9c102_fops = {
.owner = THIS_MODULE,
.open = sn9c102_open,
.release = sn9c102_release,
.ioctl = sn9c102_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = sn9c102_read,
.poll = sn9c102_poll,
.mmap = sn9c102_mmap,
- .llseek = no_llseek,
};
/*****************************************************************************/
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 90077cb4fe66..fcb05f06de8f 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -256,7 +256,7 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
vfree(icd->user_formats);
}
-static int soc_camera_open(struct inode *inode, struct file *file)
+static int soc_camera_open(struct file *file)
{
struct video_device *vdev;
struct soc_camera_device *icd;
@@ -330,7 +330,7 @@ emgd:
return ret;
}
-static int soc_camera_close(struct inode *inode, struct file *file)
+static int soc_camera_close(struct file *file)
{
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
@@ -400,7 +400,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
return ici->ops->poll(file, pt);
}
-static struct file_operations soc_camera_fops = {
+static struct v4l2_file_operations soc_camera_fops = {
.owner = THIS_MODULE,
.open = soc_camera_open,
.release = soc_camera_close,
@@ -408,7 +408,6 @@ static struct file_operations soc_camera_fops = {
.read = soc_camera_read,
.mmap = soc_camera_mmap,
.poll = soc_camera_poll,
- .llseek = no_llseek,
};
static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
@@ -700,7 +699,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
}
static int soc_camera_g_chip_ident(struct file *file, void *fh,
- struct v4l2_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
@@ -713,7 +712,7 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int soc_camera_g_register(struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
@@ -725,7 +724,7 @@ static int soc_camera_g_register(struct file *file, void *fh,
}
static int soc_camera_s_register(struct file *file, void *fh,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd;
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index f9516d0f3c11..26378cf390fc 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -664,7 +664,7 @@ static void stk_free_buffers(struct stk_camera *dev)
/* v4l file operations */
-static int v4l_stk_open(struct inode *inode, struct file *fp)
+static int v4l_stk_open(struct file *fp)
{
struct stk_camera *dev;
struct video_device *vdev;
@@ -684,7 +684,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
return 0;
}
-static int v4l_stk_release(struct inode *inode, struct file *fp)
+static int v4l_stk_release(struct file *fp)
{
struct stk_camera *dev = fp->private_data;
@@ -1281,7 +1281,7 @@ static int stk_vidioc_enum_framesizes(struct file *filp,
}
}
-static struct file_operations v4l_stk_fops = {
+static struct v4l2_file_operations v4l_stk_fops = {
.owner = THIS_MODULE,
.open = v4l_stk_open,
.release = v4l_stk_release,
@@ -1289,10 +1289,6 @@ static struct file_operations v4l_stk_fops = {
.poll = v4l_stk_poll,
.mmap = v4l_stk_mmap,
.ioctl = video_ioctl2,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek
};
static const struct v4l2_ioctl_ops v4l_stk_ioctl_ops = {
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index bbad54f85c83..0eb313082c97 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -1275,7 +1275,7 @@ static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr)
clip_draw_rectangle(clipmap, 0, 0, 1024, -saa->win.y);
}
-static int saa_ioctl(struct inode *inode, struct file *file,
+static long saa_ioctl(struct file *file,
unsigned int cmd, unsigned long argl)
{
struct saa7146 *saa = file->private_data;
@@ -1877,7 +1877,7 @@ static ssize_t saa_write(struct file *file, const char __user * buf,
return count;
}
-static int saa_open(struct inode *inode, struct file *file)
+static int saa_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct saa7146 *saa = container_of(vdev, struct saa7146, video_dev);
@@ -1895,7 +1895,7 @@ static int saa_open(struct inode *inode, struct file *file)
return 0;
}
-static int saa_release(struct inode *inode, struct file *file)
+static int saa_release(struct file *file)
{
struct saa7146 *saa = file->private_data;
saa->user--;
@@ -1906,16 +1906,12 @@ static int saa_release(struct inode *inode, struct file *file)
return 0;
}
-static const struct file_operations saa_fops = {
+static const struct v4l2_file_operations saa_fops = {
.owner = THIS_MODULE,
.open = saa_open,
.release = saa_release,
.ioctl = saa_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = saa_read,
- .llseek = no_llseek,
.write = saa_write,
.mmap = saa_mmap,
};
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index 42acc92c182d..75f286f7a2e9 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -1080,7 +1080,7 @@ static int stv680_newframe (struct usb_stv *stv680, int framenr)
* Video4Linux
*********************************************************************/
-static int stv_open (struct inode *inode, struct file *file)
+static int stv_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct usb_stv *stv680 = video_get_drvdata(dev);
@@ -1106,7 +1106,7 @@ static int stv_open (struct inode *inode, struct file *file)
return err;
}
-static int stv_close (struct inode *inode, struct file *file)
+static int stv_close(struct file *file)
{
struct video_device *dev = file->private_data;
struct usb_stv *stv680 = video_get_drvdata(dev);
@@ -1132,7 +1132,7 @@ static int stv_close (struct inode *inode, struct file *file)
return 0;
}
-static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = file->private_data;
struct usb_stv *stv680 = video_get_drvdata(vdev);
@@ -1299,7 +1299,7 @@ static int stv680_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int stv680_ioctl(struct inode *inode, struct file *file,
+static long stv680_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, stv680_do_ioctl);
@@ -1391,17 +1391,13 @@ static ssize_t stv680_read (struct file *file, char __user *buf,
return realcount;
} /* stv680_read */
-static const struct file_operations stv680_fops = {
+static const struct v4l2_file_operations stv680_fops = {
.owner = THIS_MODULE,
.open = stv_open,
.release = stv_close,
.read = stv680_read,
.mmap = stv680_mmap,
.ioctl = stv680_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device stv680_template = {
.name = "STV0680 USB camera",
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 2644e0dc9251..6afb7059502d 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -137,7 +137,7 @@ static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
return 0;
}
-static int tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static long tda9840_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
{
int byte;
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 56f0c0eb500f..00c6cbe06ab0 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -242,7 +242,7 @@ static int tda9875_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
static int tda9875_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct tda9875 *t = to_state(sd);
- int chvol=0, volume, balance, left, right;
+ int chvol = 0, volume = 0, balance = 0, left, right;
switch (ctrl->id) {
case V4L2_CID_AUDIO_VOLUME:
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 31dde86f2df4..7519fd1f57ef 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -122,7 +122,7 @@ static int switch_matrix(struct i2c_client *client, int i, int o)
return ret;
}
-static int tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static long tea6415c_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
{
if (cmd == TEA6415C_SWITCH) {
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 38e519f04bde..081e74fa3b2e 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -90,7 +90,7 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
return 0;
}
-static int tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
+static long tea6420_ioctl(struct v4l2_subdev *sd, unsigned cmd, void *arg)
{
if (cmd == TEA6420_SWITCH) {
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 97d7509d212f..30640fbfd0f9 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -800,7 +800,7 @@ static int tuner_s_standby(struct v4l2_subdev *sd, u32 standby)
}
#ifdef CONFIG_VIDEO_ALLOW_V4L1
-static int tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+static long tuner_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
struct tuner *t = to_tuner(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index d0c794da735b..5aeccb301cea 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1762,7 +1762,7 @@ static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *fr
return 0;
}
-static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int tvaudio_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index 3b0b84c2e451..78277abb733b 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -427,6 +427,9 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
memset(tvee, 0, sizeof(*tvee));
+ tvee->tuner_type = TUNER_ABSENT;
+ tvee->tuner2_type = TUNER_ABSENT;
+
done = len = beenhere = 0;
/* Different eeprom start offsets for em28xx, cx2388x and cx23418 */
diff --git a/drivers/media/video/tvp514x.c b/drivers/media/video/tvp514x.c
index ac9aa40d09f6..8e23aa53c29a 100644
--- a/drivers/media/video/tvp514x.c
+++ b/drivers/media/video/tvp514x.c
@@ -1401,7 +1401,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
decoder->pdata = client->dev.platform_data;
if (!decoder->pdata) {
- v4l_err(client, "No platform data\n!!");
+ v4l_err(client, "No platform data!!\n");
return -ENODEV;
}
/*
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index a388a9f0cb18..2cd64ef27b95 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -963,7 +963,7 @@ static int tvp5150_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
- struct v4l2_chip_ident *chip)
+ struct v4l2_dbg_chip_ident *chip)
{
int rev;
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -977,25 +977,24 @@ static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = tvp5150_read(sd, reg->reg & 0xff);
+ reg->size = 1;
return 0;
}
-static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int tvp5150_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index d5cdc4be1a35..52c0357faa5d 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -575,7 +575,7 @@ static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
}
static int tw9910_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
id->ident = V4L2_IDENT_TW9910;
id->revision = 0;
@@ -606,7 +606,7 @@ static int tw9910_enum_input(struct soc_camera_device *icd,
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int tw9910_get_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
int ret;
@@ -627,7 +627,7 @@ static int tw9910_get_register(struct soc_camera_device *icd,
}
static int tw9910_set_register(struct soc_camera_device *icd,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c
index 7a609a3a6dbe..f4522bb08916 100644
--- a/drivers/media/video/upd64031a.c
+++ b/drivers/media/video/upd64031a.c
@@ -21,7 +21,6 @@
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
@@ -147,7 +146,7 @@ static int upd64031a_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing
return upd64031a_s_frequency(sd, NULL);
}
-static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int upd64031a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -162,25 +161,24 @@ static int upd64031a_log_status(struct v4l2_subdev *sd)
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = upd64031a_read(sd, reg->reg & 0xff);
+ reg->size = 1;
return 0;
}
-static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64031a_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c
index 58412cb9c01a..a5fb74bf2407 100644
--- a/drivers/media/video/upd64083.c
+++ b/drivers/media/video/upd64083.c
@@ -21,7 +21,6 @@
* 02110-1301, USA.
*/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
@@ -120,25 +119,24 @@ static int upd64083_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing
}
#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64083_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = upd64083_read(sd, reg->reg & 0xff);
+ reg->size = 1;
return 0;
}
-static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
+static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
- if (!v4l2_chip_match_i2c_client(client,
- reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -147,7 +145,7 @@ static int upd64083_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg
}
#endif
-static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int upd64083_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
index f8d85ddb4804..b08549661781 100644
--- a/drivers/media/video/usbvideo/ibmcam.c
+++ b/drivers/media/video/usbvideo/ibmcam.c
@@ -3779,7 +3779,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
err("Alternate settings have different endpoint addresses!");
return -ENODEV;
}
- if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) {
+ if (!usb_endpoint_xfer_isoc(endpoint)) {
err("Interface %d. has non-ISO endpoint!", ifnum);
return -ENODEV;
}
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index 90f0ce6a26bc..900ec2129ca1 100644
--- a/drivers/media/video/usbvideo/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -823,7 +823,7 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
err("Alternate settings have different endpoint addresses!");
return -ENODEV;
}
- if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) {
+ if (!usb_endpoint_xfer_isoc(endpoint)) {
err("Interface %d. has non-ISO endpoint!",
interface->desc.bInterfaceNumber);
return -ENODEV;
diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
index 839a08240c25..fbd1b6392290 100644
--- a/drivers/media/video/usbvideo/ultracam.c
+++ b/drivers/media/video/usbvideo/ultracam.c
@@ -556,7 +556,7 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
err("Alternate settings have different endpoint addresses!");
return -ENODEV;
}
- if (usb_endpoint_type(endpoint) != USB_ENDPOINT_XFER_ISOC) {
+ if (!usb_endpoint_xfer_isoc(endpoint)) {
err("Interface %d. has non-ISO endpoint!",
interface->desc.bInterfaceNumber);
return -ENODEV;
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
index 148a1f98c70f..dea8b321fb4a 100644
--- a/drivers/media/video/usbvideo/usbvideo.c
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -41,13 +41,13 @@ module_param(video_nr, int, 0);
static void usbvideo_Disconnect(struct usb_interface *intf);
static void usbvideo_CameraRelease(struct uvd *uvd);
-static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
+static long usbvideo_v4l_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
-static int usbvideo_v4l_open(struct inode *inode, struct file *file);
+static int usbvideo_v4l_open(struct file *file);
static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
-static int usbvideo_v4l_close(struct inode *inode, struct file *file);
+static int usbvideo_v4l_close(struct file *file);
static int usbvideo_StartDataPump(struct uvd *uvd);
static void usbvideo_StopDataPump(struct uvd *uvd);
@@ -942,17 +942,13 @@ static int usbvideo_find_struct(struct usbvideo *cams)
return rv;
}
-static const struct file_operations usbvideo_fops = {
+static const struct v4l2_file_operations usbvideo_fops = {
.owner = THIS_MODULE,
.open = usbvideo_v4l_open,
.release =usbvideo_v4l_close,
.read = usbvideo_v4l_read,
.mmap = usbvideo_v4l_mmap,
.ioctl = usbvideo_v4l_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static const struct video_device usbvideo_template = {
.fops = &usbvideo_fops,
@@ -1113,7 +1109,7 @@ static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
* 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
* 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
*/
-static int usbvideo_v4l_open(struct inode *inode, struct file *file)
+static int usbvideo_v4l_open(struct file *file)
{
struct video_device *dev = video_devdata(file);
struct uvd *uvd = (struct uvd *) dev;
@@ -1233,7 +1229,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
* 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
* 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep.
*/
-static int usbvideo_v4l_close(struct inode *inode, struct file *file)
+static int usbvideo_v4l_close(struct file *file)
{
struct video_device *dev = file->private_data;
struct uvd *uvd = (struct uvd *) dev;
@@ -1281,7 +1277,7 @@ static int usbvideo_v4l_close(struct inode *inode, struct file *file)
* History:
* 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
*/
-static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct uvd *uvd = file->private_data;
@@ -1501,7 +1497,7 @@ static int usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
+static long usbvideo_v4l_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, usbvideo_v4l_do_ioctl);
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
index 4602597ed8d1..2f1106338c08 100644
--- a/drivers/media/video/usbvideo/vicam.c
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -229,12 +229,12 @@ set_camera_power(struct vicam_camera *cam, int state)
return 0;
}
-static int
-vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
+static long
+vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
{
void __user *user_arg = (void __user *)arg;
struct vicam_camera *cam = file->private_data;
- int retval = 0;
+ long retval = 0;
if (!cam)
return -ENODEV;
@@ -470,7 +470,7 @@ vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsign
}
static int
-vicam_open(struct inode *inode, struct file *file)
+vicam_open(struct file *file)
{
struct vicam_camera *cam = video_drvdata(file);
@@ -536,7 +536,7 @@ vicam_open(struct inode *inode, struct file *file)
}
static int
-vicam_close(struct inode *inode, struct file *file)
+vicam_close(struct file *file)
{
struct vicam_camera *cam = file->private_data;
int open_count;
@@ -783,17 +783,13 @@ vicam_mmap(struct file *file, struct vm_area_struct *vma)
return 0;
}
-static const struct file_operations vicam_fops = {
+static const struct v4l2_file_operations vicam_fops = {
.owner = THIS_MODULE,
.open = vicam_open,
.release = vicam_close,
.read = vicam_read,
.mmap = vicam_mmap,
.ioctl = vicam_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
};
static struct video_device vicam_template = {
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 9907b9aff2b9..6b66ae4f430f 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -157,7 +157,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
struct i2c_msg *pmsg;
struct usb_usbvision *usbvision;
int i, ret;
- unsigned char addr;
+ unsigned char addr = 0;
usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 85661b1848fe..2622de003a45 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -355,7 +355,7 @@ static void usbvision_remove_sysfs(struct video_device *vdev)
* then allocates buffers needed for video processing.
*
*/
-static int usbvision_v4l2_open(struct inode *inode, struct file *file)
+static int usbvision_v4l2_open(struct file *file)
{
struct usb_usbvision *usbvision = video_drvdata(file);
int errCode = 0;
@@ -432,7 +432,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
* allocated in usbvision_v4l2_open().
*
*/
-static int usbvision_v4l2_close(struct inode *inode, struct file *file)
+static int usbvision_v4l2_close(struct file *file)
{
struct usb_usbvision *usbvision = video_drvdata(file);
@@ -477,12 +477,12 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
*/
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int vidioc_g_register (struct file *file, void *priv,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct usb_usbvision *usbvision = video_drvdata(file);
int errCode;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
/* NT100x has a 8-bit register space */
errCode = usbvision_read_reg(usbvision, reg->reg&0xff);
@@ -492,16 +492,17 @@ static int vidioc_g_register (struct file *file, void *priv,
return errCode;
}
reg->val = errCode;
+ reg->size = 1;
return 0;
}
static int vidioc_s_register (struct file *file, void *priv,
- struct v4l2_register *reg)
+ struct v4l2_dbg_register *reg)
{
struct usb_usbvision *usbvision = video_drvdata(file);
int errCode;
- if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
+ if (!v4l2_chip_match_host(&reg->match))
return -EINVAL;
/* NT100x has a 8-bit register space */
errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val);
@@ -1178,7 +1179,7 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
* Here comes the stuff for radio on usbvision based devices
*
*/
-static int usbvision_radio_open(struct inode *inode, struct file *file)
+static int usbvision_radio_open(struct file *file)
{
struct usb_usbvision *usbvision = video_drvdata(file);
int errCode = 0;
@@ -1228,7 +1229,7 @@ out:
}
-static int usbvision_radio_close(struct inode *inode, struct file *file)
+static int usbvision_radio_close(struct file *file)
{
struct usb_usbvision *usbvision = video_drvdata(file);
int errCode = 0;
@@ -1266,26 +1267,26 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
* Here comes the stuff for vbi on usbvision based devices
*
*/
-static int usbvision_vbi_open(struct inode *inode, struct file *file)
+static int usbvision_vbi_open(struct file *file)
{
/* TODO */
return -ENODEV;
}
-static int usbvision_vbi_close(struct inode *inode, struct file *file)
+static int usbvision_vbi_close(struct file *file)
{
/* TODO */
return -ENODEV;
}
-static int usbvision_do_vbi_ioctl(struct file *file,
+static long usbvision_do_vbi_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
/* TODO */
return -ENOIOCTLCMD;
}
-static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
+static long usbvision_vbi_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, usbvision_do_vbi_ioctl);
@@ -1297,16 +1298,14 @@ static int usbvision_vbi_ioctl(struct inode *inode, struct file *file,
//
// Video template
-static const struct file_operations usbvision_fops = {
+static const struct v4l2_file_operations usbvision_fops = {
.owner = THIS_MODULE,
.open = usbvision_v4l2_open,
.release = usbvision_v4l2_close,
.read = usbvision_v4l2_read,
.mmap = usbvision_v4l2_mmap,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
/* .poll = video_poll, */
- .compat_ioctl = v4l_compat_ioctl32,
};
static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
@@ -1355,13 +1354,11 @@ static struct video_device usbvision_video_template = {
// Radio template
-static const struct file_operations usbvision_radio_fops = {
+static const struct v4l2_file_operations usbvision_radio_fops = {
.owner = THIS_MODULE,
.open = usbvision_radio_open,
.release = usbvision_radio_close,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
- .compat_ioctl = v4l_compat_ioctl32,
};
static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
@@ -1392,13 +1389,11 @@ static struct video_device usbvision_radio_template = {
};
// vbi template
-static const struct file_operations usbvision_vbi_fops = {
+static const struct v4l2_file_operations usbvision_vbi_fops = {
.owner = THIS_MODULE,
.open = usbvision_vbi_open,
.release = usbvision_vbi_close,
.ioctl = usbvision_vbi_ioctl,
- .llseek = no_llseek,
- .compat_ioctl = v4l_compat_ioctl32,
};
static struct video_device usbvision_vbi_template=
@@ -1679,8 +1674,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
interface = &dev->actconfig->interface[ifnum]->altsetting[0];
}
endpoint = &interface->endpoint[1].desc;
- if (usb_endpoint_type(endpoint) !=
- USB_ENDPOINT_XFER_ISOC) {
+ if (!usb_endpoint_xfer_isoc(endpoint)) {
err("%s: interface %d. has non-ISO endpoint!",
__func__, ifnum);
err("%s: Endpoint attributes %d",
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index 2208165aa6f0..d2576f6391c0 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1,7 +1,7 @@
/*
* uvc_ctrl.c -- USB Video Class driver - Controls
*
- * Copyright (C) 2005-2008
+ * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be)
*
* This program is free software; you can redistribute it and/or modify
@@ -12,7 +12,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/uaccess.h>
@@ -29,7 +28,7 @@
#define UVC_CTRL_DATA_BACKUP 1
/* ------------------------------------------------------------------------
- * Control, formats, ...
+ * Controls
*/
static struct uvc_control_info uvc_ctrls[] = {
@@ -635,7 +634,7 @@ static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
mask = (1 << bits) - 1;
}
- /* Sign-extend the value if needed */
+ /* Sign-extend the value if needed. */
if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
value |= -(value & (1 << (mapping->size - 1)));
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 89d8bd10a852..b12873265cc5 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1,7 +1,7 @@
/*
* uvc_driver.c -- USB Video Class driver
*
- * Copyright (C) 2005-2008
+ * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be)
*
* This program is free software; you can redistribute it and/or modify
@@ -24,7 +24,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
@@ -49,7 +48,7 @@ static unsigned int uvc_quirks_param;
unsigned int uvc_trace_param;
/* ------------------------------------------------------------------------
- * Control, formats, ...
+ * Video formats
*/
static struct uvc_format_desc uvc_fmts[] = {
@@ -474,7 +473,7 @@ static int uvc_parse_format(struct uvc_device *dev,
/* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
* completely. Observed behaviours range from setting the
- * value to 1.1x the actual frame size of hardwiring the
+ * value to 1.1x the actual frame size to hardwiring the
* 16 low bits to 0. This results in a higher than necessary
* memory usage as well as a wrong image size information. For
* uncompressed formats this can be fixed by computing the
@@ -487,7 +486,7 @@ static int uvc_parse_format(struct uvc_device *dev,
/* Some bogus devices report dwMinFrameInterval equal to
* dwMaxFrameInterval and have dwFrameIntervalStep set to
* zero. Setting all null intervals to 1 fixes the problem and
- * some other divisions by zero which could happen.
+ * some other divisions by zero that could happen.
*/
for (i = 0; i < n; ++i) {
interval = get_unaligned_le32(&buffer[26+4*i]);
@@ -1200,13 +1199,13 @@ static void uvc_unregister_video(struct uvc_device *dev)
* Scan the UVC descriptors to locate a chain starting at an Output Terminal
* and containing the following units:
*
- * - a USB Streaming Output Terminal
+ * - one Output Terminal (USB Streaming or Display)
* - zero or one Processing Unit
* - zero, one or mode single-input Selector Units
* - zero or one multiple-input Selector Units, provided all inputs are
* connected to input terminals
* - zero, one or mode single-input Extension Units
- * - one Camera Input Terminal, or one or more External terminals.
+ * - one or more Input Terminals (Camera, External or USB Streaming)
*
* A side forward scan is made on each detected entity to check for additional
* extension units.
@@ -1531,10 +1530,6 @@ static int uvc_register_video(struct uvc_device *dev)
/* Set the driver data before calling video_register_device, otherwise
* uvc_v4l2_open might race us.
- *
- * FIXME: usb_set_intfdata hasn't been called so far. Is that a
- * problem ? Does any function which could be called here get
- * a pointer to the usb_interface ?
*/
dev->video.vdev = vdev;
video_set_drvdata(vdev, &dev->video);
@@ -1569,7 +1564,7 @@ void uvc_delete(struct kref *kref)
struct uvc_device *dev = container_of(kref, struct uvc_device, kref);
struct list_head *p, *n;
- /* Unregister the video device */
+ /* Unregister the video device. */
uvc_unregister_video(dev);
usb_put_intf(dev->intf);
usb_put_dev(dev->udev);
@@ -1612,7 +1607,7 @@ static int uvc_probe(struct usb_interface *intf,
uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
udev->devpath);
- /* Allocate memory for the device and initialize it */
+ /* Allocate memory for the device and initialize it. */
if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -1633,14 +1628,14 @@ static int uvc_probe(struct usb_interface *intf,
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));
- /* Parse the Video Class control descriptor */
+ /* Parse the Video Class control descriptor. */
if (uvc_parse_control(dev) < 0) {
uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
"descriptors.\n");
goto error;
}
- uvc_printk(KERN_INFO, "Found UVC %u.%02u device %s (%04x:%04x)\n",
+ uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
dev->uvc_version >> 8, dev->uvc_version & 0xff,
udev->product ? udev->product : "<unnamed>",
le16_to_cpu(udev->descriptor.idVendor),
@@ -1653,18 +1648,18 @@ static int uvc_probe(struct usb_interface *intf,
"linux-uvc-devel mailing list.\n");
}
- /* Initialize controls */
+ /* Initialize controls. */
if (uvc_ctrl_init_device(dev) < 0)
goto error;
- /* Register the video devices */
+ /* Register the video devices. */
if (uvc_register_video(dev) < 0)
goto error;
- /* Save our data pointer in the interface data */
+ /* Save our data pointer in the interface data. */
usb_set_intfdata(intf, dev);
- /* Initialize the interrupt URB */
+ /* Initialize the interrupt URB. */
if ((ret = uvc_status_init(dev)) < 0) {
uvc_printk(KERN_INFO, "Unable to initialize the status "
"endpoint (%d), status interrupt will not be "
@@ -1839,24 +1834,24 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0 },
/* Apple Built-In iSight */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x05ac,
.idProduct = 0x8501,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_BUILTIN_ISIGHT },
/* Genesys Logic USB 2.0 PC Camera */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x05e3,
- .idProduct = 0x0505,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_STREAM_NO_FID },
+ .idVendor = 0x05e3,
+ .idProduct = 0x0505,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_QUIRK_STREAM_NO_FID },
/* MT6227 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c
index 37bdefdbead5..436f462685a0 100644
--- a/drivers/media/video/uvc/uvc_isight.c
+++ b/drivers/media/video/uvc/uvc_isight.c
@@ -3,6 +3,8 @@
*
* Copyright (C) 2006-2007
* Ivan N. Zlatev <contact@i-nz.net>
+ * Copyright (C) 2008-2009
+ * Laurent Pinchart <laurent.pinchart@skynet.be>
*
* 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
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 42546342e97d..0155752e4a5a 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -1,7 +1,7 @@
/*
* uvc_queue.c -- USB Video Class driver - Buffers management
*
- * Copyright (C) 2005-2008
+ * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be)
*
* This program is free software; you can redistribute it and/or modify
@@ -12,7 +12,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/module.h>
@@ -37,22 +36,22 @@
* to user space will return -EBUSY.
*
* Video buffers are managed using two queues. However, unlike most USB video
- * drivers which use an in queue and an out queue, we use a main queue which
- * holds all queued buffers (both 'empty' and 'done' buffers), and an irq
- * queue which holds empty buffers. This design (copied from video-buf)
- * minimizes locking in interrupt, as only one queue is shared between
- * interrupt and user contexts.
+ * drivers that use an in queue and an out queue, we use a main queue to hold
+ * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
+ * hold empty buffers. This design (copied from video-buf) minimizes locking
+ * in interrupt, as only one queue is shared between interrupt and user
+ * contexts.
*
* Use cases
* ---------
*
- * Unless stated otherwise, all operations which modify the irq buffers queue
+ * Unless stated otherwise, all operations that modify the irq buffers queue
* are protected by the irq spinlock.
*
* 1. The user queues the buffers, starts streaming and dequeues a buffer.
*
* The buffers are added to the main and irq queues. Both operations are
- * protected by the queue lock, and the latert is protected by the irq
+ * protected by the queue lock, and the later is protected by the irq
* spinlock as well.
*
* The completion handler fetches a buffer from the irq queue and fills it
@@ -60,7 +59,7 @@
* returns immediately.
*
* When the buffer is full, the completion handler removes it from the irq
- * queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue.
+ * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
* At that point, any process waiting on the buffer will be woken up. If a
* process tries to dequeue a buffer after it has been marked ready, the
* dequeing will succeed immediately.
@@ -91,8 +90,8 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
/*
* Allocate the video buffers.
*
- * Pages are reserved to make sure they will not be swaped, as they will be
- * filled in URB completion handler.
+ * Pages are reserved to make sure they will not be swapped, as they will be
+ * filled in the URB completion handler.
*
* Buffers will be individually mapped, so they must all be page aligned.
*/
@@ -210,8 +209,8 @@ int uvc_query_buffer(struct uvc_video_queue *queue,
__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
done:
- mutex_unlock(&queue->mutex);
- return ret;
+ mutex_unlock(&queue->mutex);
+ return ret;
}
/*
@@ -236,7 +235,7 @@ int uvc_queue_buffer(struct uvc_video_queue *queue,
}
mutex_lock(&queue->mutex);
- if (v4l2_buf->index >= queue->count) {
+ if (v4l2_buf->index >= queue->count) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
ret = -EINVAL;
goto done;
@@ -429,7 +428,7 @@ done:
* Cancel the video buffers queue.
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
- * wakes them up and remove them from the queue.
+ * wakes them up and removes them from the queue.
*
* If the disconnect parameter is set, further calls to uvc_queue_buffer will
* fail with -ENODEV.
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c
index 5d60b264d59a..c1e4ae27c613 100644
--- a/drivers/media/video/uvc/uvc_status.c
+++ b/drivers/media/video/uvc/uvc_status.c
@@ -1,7 +1,7 @@
/*
* uvc_status.c -- USB Video Class driver - Status endpoint
*
- * Copyright (C) 2007-2008
+ * Copyright (C) 2007-2009
* Laurent Pinchart (laurent.pinchart@skynet.be)
*
* This program is free software; you can redistribute it and/or modify
@@ -12,7 +12,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index afcc6934559e..d681519d0c8a 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -1,7 +1,7 @@
/*
* uvc_v4l2.c -- USB Video Class driver - V4L2 API
*
- * Copyright (C) 2005-2008
+ * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be)
*
* This program is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@
* must be grouped (for instance the Red Balance, Blue Balance and Do White
* Balance V4L2 controls use the White Balance Component UVC control) or
* otherwise translated. The approach we take here is to use a translation
- * table for the controls which can be mapped directly, and handle the others
+ * table for the controls that can be mapped directly, and handle the others
* manually.
*/
static int uvc_v4l2_query_menu(struct uvc_video_device *video,
@@ -189,7 +189,7 @@ static int uvc_v4l2_try_format(struct uvc_video_device *video,
probe->dwMaxVideoFrameSize =
video->streaming->ctrl.dwMaxVideoFrameSize;
- /* Probe the device */
+ /* Probe the device. */
if ((ret = uvc_probe_video(video, probe)) < 0)
goto done;
@@ -354,11 +354,11 @@ static int uvc_v4l2_set_streamparm(struct uvc_video_device *video,
*
* Each open instance of a UVC device can either be in a privileged or
* unprivileged state. Only a single instance can be in a privileged state at
- * a given time. Trying to perform an operation which requires privileges will
+ * a given time. Trying to perform an operation that requires privileges will
* automatically acquire the required privileges if possible, or return -EBUSY
* otherwise. Privileges are dismissed when closing the instance.
*
- * Operations which require privileges are:
+ * Operations that require privileges are:
*
* - VIDIOC_S_INPUT
* - VIDIOC_S_PARM
@@ -406,7 +406,7 @@ static int uvc_has_privileges(struct uvc_fh *handle)
* V4L2 file operations
*/
-static int uvc_v4l2_open(struct inode *inode, struct file *file)
+static int uvc_v4l2_open(struct file *file)
{
struct uvc_video_device *video;
struct uvc_fh *handle;
@@ -444,7 +444,7 @@ done:
return ret;
}
-static int uvc_v4l2_release(struct inode *inode, struct file *file)
+static int uvc_v4l2_release(struct file *file)
{
struct uvc_video_device *video = video_drvdata(file);
struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
@@ -472,12 +472,12 @@ static int uvc_v4l2_release(struct inode *inode, struct file *file)
return 0;
}
-static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct uvc_video_device *video = video_get_drvdata(vdev);
struct uvc_fh *handle = (struct uvc_fh *)file->private_data;
- int ret = 0;
+ long ret = 0;
switch (cmd) {
/* Query capabilities */
@@ -996,7 +996,7 @@ static int uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return ret;
}
-static int uvc_v4l2_ioctl(struct inode *inode, struct file *file,
+static long uvc_v4l2_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
if (uvc_trace_param & UVC_TRACE_IOCTL) {
@@ -1097,13 +1097,11 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
return uvc_queue_poll(&video->queue, file, wait);
}
-struct file_operations uvc_fops = {
+const struct v4l2_file_operations uvc_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
.ioctl = uvc_v4l2_ioctl,
- .compat_ioctl = v4l_compat_ioctl32,
- .llseek = no_llseek,
.read = uvc_v4l2_read,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll,
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index e7c31995527f..9bc4705be78d 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -1,7 +1,7 @@
/*
* uvc_video.c -- USB Video Class driver - Video handling
*
- * Copyright (C) 2005-2008
+ * Copyright (C) 2005-2009
* Laurent Pinchart (laurent.pinchart@skynet.be)
*
* This program is free software; you can redistribute it and/or modify
@@ -12,7 +12,6 @@
*/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/usb.h>
@@ -115,7 +114,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
ret = 0;
goto out;
- } else if (query == GET_DEF && probe == 1) {
+ } else if (query == GET_DEF && probe == 1 && ret != size) {
/* Many cameras don't support the GET_DEF request on their
* video probe control. Warn once and return, the caller will
* fall back to GET_CUR.
@@ -160,7 +159,7 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
}
/* Some broken devices return a null or wrong dwMaxVideoFrameSize.
- * Try to get the value from the format and frame descriptor.
+ * Try to get the value from the format and frame descriptors.
*/
uvc_fixup_buffer_size(video, ctrl);
ret = 0;
@@ -191,9 +190,6 @@ static int uvc_set_video_ctrl(struct uvc_video_device *video,
*(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality);
*(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize);
*(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay);
- /* Note: Some of the fields below are not required for IN devices (see
- * UVC spec, 4.3.1.1), but we still copy them in case support for OUT
- * devices is added in the future. */
put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]);
put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]);
@@ -400,7 +396,7 @@ static int uvc_video_decode_start(struct uvc_video_device *video,
*
* Empty buffers (bytesused == 0) don't trigger end of frame detection
* as it doesn't make sense to return an empty buffer. This also
- * avoids detecting and of frame conditions at FID toggling if the
+ * avoids detecting end of frame conditions at FID toggling if the
* previous payload had the EOF bit set.
*/
if (fid != video->last_fid && buf->buf.bytesused != 0) {
@@ -453,6 +449,17 @@ static void uvc_video_decode_end(struct uvc_video_device *video,
}
}
+/* Video payload encoding is handled by uvc_video_encode_header() and
+ * uvc_video_encode_data(). Only bulk transfers are currently supported.
+ *
+ * uvc_video_encode_header is called at the start of a payload. It adds header
+ * data to the transfer buffer and returns the header size. As the only known
+ * UVC output device transfers a whole frame in a single payload, the EOF bit
+ * is always set in the header.
+ *
+ * uvc_video_encode_data is called for every URB and copies the data from the
+ * video buffer to the transfer buffer.
+ */
static int uvc_video_encode_header(struct uvc_video_device *video,
struct uvc_buffer *buf, __u8 *data, int len)
{
@@ -953,7 +960,7 @@ int uvc_video_suspend(struct uvc_video_device *video)
}
/*
- * Reconfigure the video interface and restart streaming if it was enable
+ * Reconfigure the video interface and restart streaming if it was enabled
* before suspend.
*
* If an error occurs, disable the video queue. This will wake all pending
@@ -985,8 +992,8 @@ int uvc_video_resume(struct uvc_video_device *video)
*/
/*
- * Initialize the UVC video device by retrieving the default format and
- * committing it.
+ * Initialize the UVC video device by switching to alternate setting 0 and
+ * retrieve the default format.
*
* Some cameras (namely the Fuji Finepix) set the format and frame
* indexes to zero. The UVC standard doesn't clearly make this a spec
@@ -1014,7 +1021,7 @@ int uvc_video_init(struct uvc_video_device *video)
*/
usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
- /* Some webcams don't suport GET_DEF request on the probe control. We
+ /* Some webcams don't suport GET_DEF requests on the probe control. We
* fall back to GET_CUR if GET_DEF fails.
*/
if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 &&
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 896b791ece15..027947ea9b6e 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -72,149 +72,149 @@ struct uvc_xu_control {
* UVC constants
*/
-#define SC_UNDEFINED 0x00
-#define SC_VIDEOCONTROL 0x01
-#define SC_VIDEOSTREAMING 0x02
-#define SC_VIDEO_INTERFACE_COLLECTION 0x03
+#define SC_UNDEFINED 0x00
+#define SC_VIDEOCONTROL 0x01
+#define SC_VIDEOSTREAMING 0x02
+#define SC_VIDEO_INTERFACE_COLLECTION 0x03
-#define PC_PROTOCOL_UNDEFINED 0x00
+#define PC_PROTOCOL_UNDEFINED 0x00
-#define CS_UNDEFINED 0x20
-#define CS_DEVICE 0x21
-#define CS_CONFIGURATION 0x22
-#define CS_STRING 0x23
-#define CS_INTERFACE 0x24
-#define CS_ENDPOINT 0x25
+#define CS_UNDEFINED 0x20
+#define CS_DEVICE 0x21
+#define CS_CONFIGURATION 0x22
+#define CS_STRING 0x23
+#define CS_INTERFACE 0x24
+#define CS_ENDPOINT 0x25
/* VideoControl class specific interface descriptor */
-#define VC_DESCRIPTOR_UNDEFINED 0x00
-#define VC_HEADER 0x01
-#define VC_INPUT_TERMINAL 0x02
-#define VC_OUTPUT_TERMINAL 0x03
-#define VC_SELECTOR_UNIT 0x04
-#define VC_PROCESSING_UNIT 0x05
-#define VC_EXTENSION_UNIT 0x06
+#define VC_DESCRIPTOR_UNDEFINED 0x00
+#define VC_HEADER 0x01
+#define VC_INPUT_TERMINAL 0x02
+#define VC_OUTPUT_TERMINAL 0x03
+#define VC_SELECTOR_UNIT 0x04
+#define VC_PROCESSING_UNIT 0x05
+#define VC_EXTENSION_UNIT 0x06
/* VideoStreaming class specific interface descriptor */
-#define VS_UNDEFINED 0x00
-#define VS_INPUT_HEADER 0x01
-#define VS_OUTPUT_HEADER 0x02
-#define VS_STILL_IMAGE_FRAME 0x03
-#define VS_FORMAT_UNCOMPRESSED 0x04
-#define VS_FRAME_UNCOMPRESSED 0x05
-#define VS_FORMAT_MJPEG 0x06
-#define VS_FRAME_MJPEG 0x07
-#define VS_FORMAT_MPEG2TS 0x0a
-#define VS_FORMAT_DV 0x0c
-#define VS_COLORFORMAT 0x0d
-#define VS_FORMAT_FRAME_BASED 0x10
-#define VS_FRAME_FRAME_BASED 0x11
-#define VS_FORMAT_STREAM_BASED 0x12
+#define VS_UNDEFINED 0x00
+#define VS_INPUT_HEADER 0x01
+#define VS_OUTPUT_HEADER 0x02
+#define VS_STILL_IMAGE_FRAME 0x03
+#define VS_FORMAT_UNCOMPRESSED 0x04
+#define VS_FRAME_UNCOMPRESSED 0x05
+#define VS_FORMAT_MJPEG 0x06
+#define VS_FRAME_MJPEG 0x07
+#define VS_FORMAT_MPEG2TS 0x0a
+#define VS_FORMAT_DV 0x0c
+#define VS_COLORFORMAT 0x0d
+#define VS_FORMAT_FRAME_BASED 0x10
+#define VS_FRAME_FRAME_BASED 0x11
+#define VS_FORMAT_STREAM_BASED 0x12
/* Endpoint type */
-#define EP_UNDEFINED 0x00
-#define EP_GENERAL 0x01
-#define EP_ENDPOINT 0x02
-#define EP_INTERRUPT 0x03
+#define EP_UNDEFINED 0x00
+#define EP_GENERAL 0x01
+#define EP_ENDPOINT 0x02
+#define EP_INTERRUPT 0x03
/* Request codes */
-#define RC_UNDEFINED 0x00
-#define SET_CUR 0x01
-#define GET_CUR 0x81
-#define GET_MIN 0x82
-#define GET_MAX 0x83
-#define GET_RES 0x84
-#define GET_LEN 0x85
-#define GET_INFO 0x86
-#define GET_DEF 0x87
+#define RC_UNDEFINED 0x00
+#define SET_CUR 0x01
+#define GET_CUR 0x81
+#define GET_MIN 0x82
+#define GET_MAX 0x83
+#define GET_RES 0x84
+#define GET_LEN 0x85
+#define GET_INFO 0x86
+#define GET_DEF 0x87
/* VideoControl interface controls */
-#define VC_CONTROL_UNDEFINED 0x00
-#define VC_VIDEO_POWER_MODE_CONTROL 0x01
-#define VC_REQUEST_ERROR_CODE_CONTROL 0x02
+#define VC_CONTROL_UNDEFINED 0x00
+#define VC_VIDEO_POWER_MODE_CONTROL 0x01
+#define VC_REQUEST_ERROR_CODE_CONTROL 0x02
/* Terminal controls */
-#define TE_CONTROL_UNDEFINED 0x00
+#define TE_CONTROL_UNDEFINED 0x00
/* Selector Unit controls */
-#define SU_CONTROL_UNDEFINED 0x00
-#define SU_INPUT_SELECT_CONTROL 0x01
+#define SU_CONTROL_UNDEFINED 0x00
+#define SU_INPUT_SELECT_CONTROL 0x01
/* Camera Terminal controls */
-#define CT_CONTROL_UNDEFINED 0x00
-#define CT_SCANNING_MODE_CONTROL 0x01
-#define CT_AE_MODE_CONTROL 0x02
-#define CT_AE_PRIORITY_CONTROL 0x03
-#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04
-#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05
-#define CT_FOCUS_ABSOLUTE_CONTROL 0x06
-#define CT_FOCUS_RELATIVE_CONTROL 0x07
-#define CT_FOCUS_AUTO_CONTROL 0x08
-#define CT_IRIS_ABSOLUTE_CONTROL 0x09
-#define CT_IRIS_RELATIVE_CONTROL 0x0a
-#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b
-#define CT_ZOOM_RELATIVE_CONTROL 0x0c
-#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d
-#define CT_PANTILT_RELATIVE_CONTROL 0x0e
-#define CT_ROLL_ABSOLUTE_CONTROL 0x0f
-#define CT_ROLL_RELATIVE_CONTROL 0x10
-#define CT_PRIVACY_CONTROL 0x11
+#define CT_CONTROL_UNDEFINED 0x00
+#define CT_SCANNING_MODE_CONTROL 0x01
+#define CT_AE_MODE_CONTROL 0x02
+#define CT_AE_PRIORITY_CONTROL 0x03
+#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04
+#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05
+#define CT_FOCUS_ABSOLUTE_CONTROL 0x06
+#define CT_FOCUS_RELATIVE_CONTROL 0x07
+#define CT_FOCUS_AUTO_CONTROL 0x08
+#define CT_IRIS_ABSOLUTE_CONTROL 0x09
+#define CT_IRIS_RELATIVE_CONTROL 0x0a
+#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b
+#define CT_ZOOM_RELATIVE_CONTROL 0x0c
+#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d
+#define CT_PANTILT_RELATIVE_CONTROL 0x0e
+#define CT_ROLL_ABSOLUTE_CONTROL 0x0f
+#define CT_ROLL_RELATIVE_CONTROL 0x10
+#define CT_PRIVACY_CONTROL 0x11
/* Processing Unit controls */
-#define PU_CONTROL_UNDEFINED 0x00
-#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01
-#define PU_BRIGHTNESS_CONTROL 0x02
-#define PU_CONTRAST_CONTROL 0x03
-#define PU_GAIN_CONTROL 0x04
-#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05
-#define PU_HUE_CONTROL 0x06
-#define PU_SATURATION_CONTROL 0x07
-#define PU_SHARPNESS_CONTROL 0x08
-#define PU_GAMMA_CONTROL 0x09
-#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a
-#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b
-#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c
-#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d
-#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e
-#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f
-#define PU_HUE_AUTO_CONTROL 0x10
-#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
-#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12
+#define PU_CONTROL_UNDEFINED 0x00
+#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01
+#define PU_BRIGHTNESS_CONTROL 0x02
+#define PU_CONTRAST_CONTROL 0x03
+#define PU_GAIN_CONTROL 0x04
+#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05
+#define PU_HUE_CONTROL 0x06
+#define PU_SATURATION_CONTROL 0x07
+#define PU_SHARPNESS_CONTROL 0x08
+#define PU_GAMMA_CONTROL 0x09
+#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a
+#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b
+#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c
+#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d
+#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e
+#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f
+#define PU_HUE_AUTO_CONTROL 0x10
+#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11
+#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12
#define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01
#define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02
#define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03
/* VideoStreaming interface controls */
-#define VS_CONTROL_UNDEFINED 0x00
-#define VS_PROBE_CONTROL 0x01
-#define VS_COMMIT_CONTROL 0x02
-#define VS_STILL_PROBE_CONTROL 0x03
-#define VS_STILL_COMMIT_CONTROL 0x04
-#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05
-#define VS_STREAM_ERROR_CODE_CONTROL 0x06
-#define VS_GENERATE_KEY_FRAME_CONTROL 0x07
-#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
-#define VS_SYNC_DELAY_CONTROL 0x09
-
-#define TT_VENDOR_SPECIFIC 0x0100
-#define TT_STREAMING 0x0101
+#define VS_CONTROL_UNDEFINED 0x00
+#define VS_PROBE_CONTROL 0x01
+#define VS_COMMIT_CONTROL 0x02
+#define VS_STILL_PROBE_CONTROL 0x03
+#define VS_STILL_COMMIT_CONTROL 0x04
+#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05
+#define VS_STREAM_ERROR_CODE_CONTROL 0x06
+#define VS_GENERATE_KEY_FRAME_CONTROL 0x07
+#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08
+#define VS_SYNC_DELAY_CONTROL 0x09
+
+#define TT_VENDOR_SPECIFIC 0x0100
+#define TT_STREAMING 0x0101
/* Input Terminal types */
-#define ITT_VENDOR_SPECIFIC 0x0200
-#define ITT_CAMERA 0x0201
-#define ITT_MEDIA_TRANSPORT_INPUT 0x0202
+#define ITT_VENDOR_SPECIFIC 0x0200
+#define ITT_CAMERA 0x0201
+#define ITT_MEDIA_TRANSPORT_INPUT 0x0202
/* Output Terminal types */
-#define OTT_VENDOR_SPECIFIC 0x0300
-#define OTT_DISPLAY 0x0301
-#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302
+#define OTT_VENDOR_SPECIFIC 0x0300
+#define OTT_DISPLAY 0x0301
+#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302
/* External Terminal types */
-#define EXTERNAL_VENDOR_SPECIFIC 0x0400
-#define COMPOSITE_CONNECTOR 0x0401
-#define SVIDEO_CONNECTOR 0x0402
-#define COMPONENT_CONNECTOR 0x0403
+#define EXTERNAL_VENDOR_SPECIFIC 0x0400
+#define COMPOSITE_CONNECTOR 0x0401
+#define SVIDEO_CONNECTOR 0x0402
+#define COMPONENT_CONNECTOR 0x0403
#define UVC_TERM_INPUT 0x0000
#define UVC_TERM_OUTPUT 0x8000
@@ -541,11 +541,11 @@ struct uvc_streaming {
};
enum uvc_buffer_state {
- UVC_BUF_STATE_IDLE = 0,
- UVC_BUF_STATE_QUEUED = 1,
- UVC_BUF_STATE_ACTIVE = 2,
- UVC_BUF_STATE_DONE = 3,
- UVC_BUF_STATE_ERROR = 4,
+ UVC_BUF_STATE_IDLE = 0,
+ UVC_BUF_STATE_QUEUED = 1,
+ UVC_BUF_STATE_ACTIVE = 2,
+ UVC_BUF_STATE_DONE = 3,
+ UVC_BUF_STATE_ERROR = 4,
};
struct uvc_buffer {
@@ -753,7 +753,7 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
}
/* V4L2 interface */
-extern struct file_operations uvc_fops;
+extern const struct v4l2_file_operations uvc_fops;
/* Video */
extern int uvc_video_init(struct uvc_video_device *video);
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index f13c0a9d684f..b617bf05e2d7 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -203,7 +203,6 @@ static int poll_one(struct file *file, struct poll_wqueues *pwq)
table = &pwq->pt;
for (;;) {
int mask;
- set_current_state(TASK_INTERRUPTIBLE);
mask = file->f_op->poll(file, table);
if (mask & POLLIN)
break;
@@ -212,9 +211,8 @@ static int poll_one(struct file *file, struct poll_wqueues *pwq)
retval = -ERESTARTSYS;
break;
}
- schedule();
+ poll_schedule(pwq, TASK_INTERRUPTIBLE);
}
- set_current_state(TASK_RUNNING);
poll_freewait(pwq);
return retval;
}
@@ -267,12 +265,12 @@ done:
/* ----------------------------------------------------------------- */
-static noinline int v4l1_compat_get_capabilities(
+static noinline long v4l1_compat_get_capabilities(
struct video_capability *cap,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_framebuffer fbuf;
struct v4l2_capability *cap2;
@@ -286,13 +284,13 @@ static noinline int v4l1_compat_get_capabilities(
err = drv(file, VIDIOC_QUERYCAP, cap2);
if (err < 0) {
- dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n", err);
+ dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %ld\n", err);
goto done;
}
if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
err = drv(file, VIDIOC_G_FBUF, &fbuf);
if (err < 0) {
- dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n", err);
+ dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %ld\n", err);
memset(&fbuf, 0, sizeof(fbuf));
}
err = 0;
@@ -324,12 +322,12 @@ done:
return err;
}
-static noinline int v4l1_compat_get_frame_buffer(
+static noinline long v4l1_compat_get_frame_buffer(
struct video_buffer *buffer,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_framebuffer fbuf;
memset(buffer, 0, sizeof(*buffer));
@@ -337,7 +335,7 @@ static noinline int v4l1_compat_get_frame_buffer(
err = drv(file, VIDIOC_G_FBUF, &fbuf);
if (err < 0) {
- dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n", err);
+ dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %ld\n", err);
goto done;
}
buffer->base = fbuf.base;
@@ -378,12 +376,12 @@ done:
return err;
}
-static noinline int v4l1_compat_set_frame_buffer(
+static noinline long v4l1_compat_set_frame_buffer(
struct video_buffer *buffer,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_framebuffer fbuf;
memset(&fbuf, 0, sizeof(fbuf));
@@ -410,16 +408,16 @@ static noinline int v4l1_compat_set_frame_buffer(
fbuf.fmt.bytesperline = buffer->bytesperline;
err = drv(file, VIDIOC_S_FBUF, &fbuf);
if (err < 0)
- dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n", err);
+ dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %ld\n", err);
return err;
}
-static noinline int v4l1_compat_get_win_cap_dimensions(
+static noinline long v4l1_compat_get_win_cap_dimensions(
struct video_window *win,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_format *fmt;
fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
@@ -432,7 +430,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0)
- dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n", err);
+ dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %ld\n", err);
if (err == 0) {
win->x = fmt->fmt.win.w.left;
win->y = fmt->fmt.win.w.top;
@@ -447,7 +445,7 @@ static noinline int v4l1_compat_get_win_cap_dimensions(
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
- dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n", err);
+ dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %ld\n", err);
goto done;
}
win->x = 0;
@@ -462,12 +460,12 @@ done:
return err;
}
-static noinline int v4l1_compat_set_win_cap_dimensions(
+static noinline long v4l1_compat_set_win_cap_dimensions(
struct video_window *win,
struct file *file,
v4l2_kioctl drv)
{
- int err, err1, err2;
+ long err, err1, err2;
struct v4l2_format *fmt;
fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
@@ -479,7 +477,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
drv(file, VIDIOC_STREAMOFF, &fmt->type);
err1 = drv(file, VIDIOC_G_FMT, fmt);
if (err1 < 0)
- dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n", err1);
+ dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %ld\n", err1);
if (err1 == 0) {
fmt->fmt.pix.width = win->width;
fmt->fmt.pix.height = win->height;
@@ -487,7 +485,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
fmt->fmt.pix.bytesperline = 0;
err = drv(file, VIDIOC_S_FMT, fmt);
if (err < 0)
- dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
+ dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %ld\n",
err);
win->width = fmt->fmt.pix.width;
win->height = fmt->fmt.pix.height;
@@ -504,7 +502,7 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
fmt->fmt.win.clipcount = win->clipcount;
err2 = drv(file, VIDIOC_S_FMT, fmt);
if (err2 < 0)
- dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n", err2);
+ dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %ld\n", err2);
if (err1 != 0 && err2 != 0)
err = err1;
@@ -514,12 +512,12 @@ static noinline int v4l1_compat_set_win_cap_dimensions(
return err;
}
-static noinline int v4l1_compat_turn_preview_on_off(
+static noinline long v4l1_compat_turn_preview_on_off(
int *on,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (0 == *on) {
@@ -530,16 +528,16 @@ static noinline int v4l1_compat_turn_preview_on_off(
}
err = drv(file, VIDIOC_OVERLAY, on);
if (err < 0)
- dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n", err);
+ dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %ld\n", err);
return err;
}
-static noinline int v4l1_compat_get_input_info(
+static noinline long v4l1_compat_get_input_info(
struct video_channel *chan,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_input input2;
v4l2_std_id sid;
@@ -548,7 +546,7 @@ static noinline int v4l1_compat_get_input_info(
err = drv(file, VIDIOC_ENUMINPUT, &input2);
if (err < 0) {
dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
- "channel=%d err=%d\n", chan->channel, err);
+ "channel=%d err=%ld\n", chan->channel, err);
goto done;
}
chan->channel = input2.index;
@@ -569,7 +567,7 @@ static noinline int v4l1_compat_get_input_info(
chan->norm = 0;
err = drv(file, VIDIOC_G_STD, &sid);
if (err < 0)
- dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n", err);
+ dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %ld\n", err);
if (err == 0) {
if (sid & V4L2_STD_PAL)
chan->norm = VIDEO_MODE_PAL;
@@ -582,17 +580,17 @@ done:
return err;
}
-static noinline int v4l1_compat_set_input(
+static noinline long v4l1_compat_set_input(
struct video_channel *chan,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
v4l2_std_id sid = 0;
err = drv(file, VIDIOC_S_INPUT, &chan->channel);
if (err < 0)
- dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n", err);
+ dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %ld\n", err);
switch (chan->norm) {
case VIDEO_MODE_PAL:
sid = V4L2_STD_PAL;
@@ -607,17 +605,17 @@ static noinline int v4l1_compat_set_input(
if (0 != sid) {
err = drv(file, VIDIOC_S_STD, &sid);
if (err < 0)
- dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n", err);
+ dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %ld\n", err);
}
return err;
}
-static noinline int v4l1_compat_get_picture(
+static noinline long v4l1_compat_get_picture(
struct video_picture *pict,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_format *fmt;
fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
@@ -640,7 +638,7 @@ static noinline int v4l1_compat_get_picture(
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
- dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n", err);
+ dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %ld\n", err);
goto done;
}
@@ -654,12 +652,12 @@ done:
return err;
}
-static noinline int v4l1_compat_set_picture(
+static noinline long v4l1_compat_set_picture(
struct video_picture *pict,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_framebuffer fbuf;
int mem_err = 0, ovl_err = 0;
struct v4l2_format *fmt;
@@ -694,7 +692,7 @@ static noinline int v4l1_compat_set_picture(
support memory capture. Trying to set the memory capture
parameters would be pointless. */
if (err < 0) {
- dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n", err);
+ dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %ld\n", err);
mem_err = -1000; /* didn't even try */
} else if (fmt->fmt.pix.pixelformat !=
palette_to_pixelformat(pict->palette)) {
@@ -711,7 +709,7 @@ static noinline int v4l1_compat_set_picture(
support overlay. Trying to set the overlay parameters
would be quite pointless. */
if (err < 0) {
- dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n", err);
+ dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %ld\n", err);
ovl_err = -1000; /* didn't even try */
} else if (fbuf.fmt.pixelformat !=
palette_to_pixelformat(pict->palette)) {
@@ -736,12 +734,13 @@ static noinline int v4l1_compat_set_picture(
return err;
}
-static noinline int v4l1_compat_get_tuner(
+static noinline long v4l1_compat_get_tuner(
struct video_tuner *tun,
struct file *file,
v4l2_kioctl drv)
{
- int err, i;
+ long err;
+ int i;
struct v4l2_tuner tun2;
struct v4l2_standard std2;
v4l2_std_id sid;
@@ -749,7 +748,7 @@ static noinline int v4l1_compat_get_tuner(
memset(&tun2, 0, sizeof(tun2));
err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0) {
- dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n", err);
+ dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %ld\n", err);
goto done;
}
memcpy(tun->name, tun2.name,
@@ -775,7 +774,7 @@ static noinline int v4l1_compat_get_tuner(
err = drv(file, VIDIOC_G_STD, &sid);
if (err < 0)
- dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n", err);
+ dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %ld\n", err);
if (err == 0) {
if (sid & V4L2_STD_PAL)
tun->mode = VIDEO_MODE_PAL;
@@ -794,12 +793,12 @@ done:
return err;
}
-static noinline int v4l1_compat_select_tuner(
+static noinline long v4l1_compat_select_tuner(
struct video_tuner *tun,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_tuner t;/*84 bytes on x86_64*/
memset(&t, 0, sizeof(t));
@@ -807,34 +806,34 @@ static noinline int v4l1_compat_select_tuner(
err = drv(file, VIDIOC_S_INPUT, &t);
if (err < 0)
- dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n", err);
+ dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %ld\n", err);
return err;
}
-static noinline int v4l1_compat_get_frequency(
+static noinline long v4l1_compat_get_frequency(
unsigned long *freq,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_frequency freq2;
memset(&freq2, 0, sizeof(freq2));
freq2.tuner = 0;
err = drv(file, VIDIOC_G_FREQUENCY, &freq2);
if (err < 0)
- dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n", err);
+ dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %ld\n", err);
if (0 == err)
*freq = freq2.frequency;
return err;
}
-static noinline int v4l1_compat_set_frequency(
+static noinline long v4l1_compat_set_frequency(
unsigned long *freq,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_frequency freq2;
memset(&freq2, 0, sizeof(freq2));
@@ -842,16 +841,17 @@ static noinline int v4l1_compat_set_frequency(
freq2.frequency = *freq;
err = drv(file, VIDIOC_S_FREQUENCY, &freq2);
if (err < 0)
- dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n", err);
+ dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %ld\n", err);
return err;
}
-static noinline int v4l1_compat_get_audio(
+static noinline long v4l1_compat_get_audio(
struct video_audio *aud,
struct file *file,
v4l2_kioctl drv)
{
- int err, i;
+ long err;
+ int i;
struct v4l2_queryctrl qctrl2;
struct v4l2_audio aud2;
struct v4l2_tuner tun2;
@@ -859,7 +859,7 @@ static noinline int v4l1_compat_get_audio(
err = drv(file, VIDIOC_G_AUDIO, &aud2);
if (err < 0) {
- dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n", err);
+ dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %ld\n", err);
goto done;
}
memcpy(aud->name, aud2.name,
@@ -903,7 +903,7 @@ static noinline int v4l1_compat_get_audio(
memset(&tun2, 0, sizeof(tun2));
err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0) {
- dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n", err);
+ dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %ld\n", err);
err = 0;
goto done;
}
@@ -918,12 +918,12 @@ done:
return err;
}
-static noinline int v4l1_compat_set_audio(
+static noinline long v4l1_compat_set_audio(
struct video_audio *aud,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_audio aud2;
struct v4l2_tuner tun2;
@@ -933,7 +933,7 @@ static noinline int v4l1_compat_set_audio(
aud2.index = aud->audio;
err = drv(file, VIDIOC_S_AUDIO, &aud2);
if (err < 0) {
- dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n", err);
+ dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %ld\n", err);
goto done;
}
@@ -950,7 +950,7 @@ static noinline int v4l1_compat_set_audio(
err = drv(file, VIDIOC_G_TUNER, &tun2);
if (err < 0)
- dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n", err);
+ dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %ld\n", err);
if (err == 0) {
switch (aud->mode) {
default:
@@ -967,19 +967,19 @@ static noinline int v4l1_compat_set_audio(
}
err = drv(file, VIDIOC_S_TUNER, &tun2);
if (err < 0)
- dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n", err);
+ dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %ld\n", err);
}
err = 0;
done:
return err;
}
-static noinline int v4l1_compat_capture_frame(
+static noinline long v4l1_compat_capture_frame(
struct video_mmap *mm,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
struct v4l2_buffer buf;
struct v4l2_format *fmt;
@@ -994,7 +994,7 @@ static noinline int v4l1_compat_capture_frame(
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(file, VIDIOC_G_FMT, fmt);
if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n", err);
+ dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %ld\n", err);
goto done;
}
if (mm->width != fmt->fmt.pix.width ||
@@ -1010,7 +1010,7 @@ static noinline int v4l1_compat_capture_frame(
fmt->fmt.pix.bytesperline = 0;
err = drv(file, VIDIOC_S_FMT, fmt);
if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n", err);
+ dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %ld\n", err);
goto done;
}
}
@@ -1018,28 +1018,28 @@ static noinline int v4l1_compat_capture_frame(
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n", err);
+ dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %ld\n", err);
goto done;
}
err = drv(file, VIDIOC_QBUF, &buf);
if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n", err);
+ dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %ld\n", err);
goto done;
}
err = drv(file, VIDIOC_STREAMON, &captype);
if (err < 0)
- dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n", err);
+ dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %ld\n", err);
done:
kfree(fmt);
return err;
}
-static noinline int v4l1_compat_sync(
+static noinline long v4l1_compat_sync(
int *i,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
struct v4l2_buffer buf;
struct poll_wqueues *pwq;
@@ -1050,7 +1050,7 @@ static noinline int v4l1_compat_sync(
err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0) {
/* No such buffer */
- dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+ dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
goto done;
}
if (!(buf.flags & V4L2_BUF_FLAG_MAPPED)) {
@@ -1062,7 +1062,7 @@ static noinline int v4l1_compat_sync(
/* make sure capture actually runs so we don't block forever */
err = drv(file, VIDIOC_STREAMON, &captype);
if (err < 0) {
- dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n", err);
+ dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %ld\n", err);
goto done;
}
@@ -1076,7 +1076,7 @@ static noinline int v4l1_compat_sync(
break;
err = drv(file, VIDIOC_QUERYBUF, &buf);
if (err < 0)
- dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n", err);
+ dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %ld\n", err);
}
kfree(pwq);
if (!(buf.flags & V4L2_BUF_FLAG_DONE)) /* not done */
@@ -1084,18 +1084,18 @@ static noinline int v4l1_compat_sync(
do {
err = drv(file, VIDIOC_DQBUF, &buf);
if (err < 0)
- dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n", err);
+ dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %ld\n", err);
} while (err == 0 && buf.index != *i);
done:
return err;
}
-static noinline int v4l1_compat_get_vbi_format(
+static noinline long v4l1_compat_get_vbi_format(
struct vbi_format *fmt,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_format *fmt2;
fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
@@ -1107,7 +1107,7 @@ static noinline int v4l1_compat_get_vbi_format(
err = drv(file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
- dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
+ dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %ld\n", err);
goto done;
}
if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
@@ -1128,12 +1128,12 @@ done:
return err;
}
-static noinline int v4l1_compat_set_vbi_format(
+static noinline long v4l1_compat_set_vbi_format(
struct vbi_format *fmt,
struct file *file,
v4l2_kioctl drv)
{
- int err;
+ long err;
struct v4l2_format *fmt2 = NULL;
if (VIDEO_PALETTE_RAW != fmt->sample_format) {
@@ -1157,7 +1157,7 @@ static noinline int v4l1_compat_set_vbi_format(
fmt2->fmt.vbi.flags = fmt->flags;
err = drv(file, VIDIOC_TRY_FMT, fmt2);
if (err < 0) {
- dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
+ dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %ld\n", err);
goto done;
}
@@ -1174,7 +1174,7 @@ static noinline int v4l1_compat_set_vbi_format(
}
err = drv(file, VIDIOC_S_FMT, fmt2);
if (err < 0)
- dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
+ dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %ld\n", err);
done:
kfree(fmt2);
return err;
@@ -1183,13 +1183,13 @@ done:
/*
* This function is exported.
*/
-int
+long
v4l_compat_translate_ioctl(struct file *file,
int cmd,
void *arg,
v4l2_kioctl drv)
{
- int err;
+ long err;
switch (cmd) {
case VIDIOCGCAP: /* capability */
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index c676b0b0f708..b8f2be8d5c0e 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -797,11 +797,11 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
}
EXPORT_SYMBOL(v4l2_ctrl_next);
-int v4l2_chip_match_host(u32 match_type, u32 match_chip)
+int v4l2_chip_match_host(const struct v4l2_dbg_match *match)
{
- switch (match_type) {
+ switch (match->type) {
case V4L2_CHIP_MATCH_HOST:
- return match_chip == 0;
+ return match->addr == 0;
default:
return 0;
}
@@ -809,23 +809,34 @@ int v4l2_chip_match_host(u32 match_type, u32 match_chip)
EXPORT_SYMBOL(v4l2_chip_match_host);
#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip)
+int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match)
{
- switch (match_type) {
+ int len;
+
+ if (c == NULL || match == NULL)
+ return 0;
+
+ switch (match->type) {
case V4L2_CHIP_MATCH_I2C_DRIVER:
- return (c != NULL && c->driver != NULL && c->driver->id == match_chip);
+ if (c->driver == NULL || c->driver->driver.name == NULL)
+ return 0;
+ len = strlen(c->driver->driver.name);
+ /* legacy drivers have a ' suffix, don't try to match that */
+ if (len && c->driver->driver.name[len - 1] == '\'')
+ len--;
+ return len && !strncmp(c->driver->driver.name, match->name, len);
case V4L2_CHIP_MATCH_I2C_ADDR:
- return (c != NULL && c->addr == match_chip);
+ return c->addr == match->addr;
default:
return 0;
}
}
EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
-int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_chip_ident *chip,
+int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip,
u32 ident, u32 revision)
{
- if (!v4l2_chip_match_i2c_client(c, chip->match_type, chip->match_chip))
+ if (!v4l2_chip_match_i2c_client(c, &chip->match))
return 0;
if (chip->ident == V4L2_IDENT_NONE) {
chip->ident = ident;
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index d0e1bd3ace6a..110376be5d2b 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -222,9 +222,9 @@ static int get_microcode32(struct video_code *kp, struct video_code32 __user *up
#endif
-static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- int ret = -ENOIOCTLCMD;
+ long ret = -ENOIOCTLCMD;
if (file->f_op->unlocked_ioctl)
ret = file->f_op->unlocked_ioctl(file, cmd, arg);
@@ -705,7 +705,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
#define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
#define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
-static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
union {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -726,7 +726,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
} karg;
void __user *up = compat_ptr(arg);
int compatible_arg = 1;
- int err = 0;
+ long err = 0;
/* First, convert the command. */
switch (cmd) {
@@ -937,9 +937,9 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
return err;
}
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
{
- int ret = -ENOIOCTLCMD;
+ long ret = -ENOIOCTLCMD;
if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
return ret;
@@ -1046,7 +1046,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
case VIDIOC_TRY_ENCODER_CMD:
case VIDIOC_DBG_S_REGISTER:
case VIDIOC_DBG_G_REGISTER:
- case VIDIOC_G_CHIP_IDENT:
+ case VIDIOC_DBG_G_CHIP_IDENT:
+ case VIDIOC_G_CHIP_IDENT_OLD:
case VIDIOC_S_HW_FREQ_SEEK:
ret = do_video_ioctl(file, cmd, arg);
break;
@@ -1065,18 +1066,14 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
break;
#endif
default:
- v4l_print_ioctl("compat_ioctl32", cmd);
- printk(KERN_CONT "\n");
+ printk(KERN_WARNING "compat_ioctl32: "
+ "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
+ _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
break;
}
return ret;
}
-#else
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return -ENOIOCTLCMD;
-}
+EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
#endif
-EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 7ad6711ee327..13f87c22e78d 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -31,6 +31,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
#define VIDEO_NUM_DEVICES 256
#define VIDEO_NAME "video4linux"
@@ -182,7 +183,7 @@ static int v4l2_ioctl(struct inode *inode, struct file *filp,
return -ENOTTY;
/* Allow ioctl to continue even if the device was unregistered.
Things like dequeueing buffers might still be useful. */
- return vdev->fops->ioctl(inode, filp, cmd, arg);
+ return vdev->fops->ioctl(filp, cmd, arg);
}
static long v4l2_unlocked_ioctl(struct file *filp,
@@ -197,20 +198,6 @@ static long v4l2_unlocked_ioctl(struct file *filp,
return vdev->fops->unlocked_ioctl(filp, cmd, arg);
}
-#ifdef CONFIG_COMPAT
-static long v4l2_compat_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- struct video_device *vdev = video_devdata(filp);
-
- if (!vdev->fops->compat_ioctl)
- return -ENOIOCTLCMD;
- /* Allow ioctl to continue even if the device was unregistered.
- Things like dequeueing buffers might still be useful. */
- return vdev->fops->compat_ioctl(filp, cmd, arg);
-}
-#endif
-
static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
{
struct video_device *vdev = video_devdata(filp);
@@ -239,7 +226,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
/* and increase the device refcount */
video_get(vdev);
mutex_unlock(&videodev_lock);
- ret = vdev->fops->open(inode, filp);
+ ret = vdev->fops->open(filp);
/* decrease the refcount in case of an error */
if (ret)
video_put(vdev);
@@ -250,7 +237,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
static int v4l2_release(struct inode *inode, struct file *filp)
{
struct video_device *vdev = video_devdata(filp);
- int ret = vdev->fops->release(inode, filp);
+ int ret = vdev->fops->release(filp);
/* decrease the refcount unconditionally since the release()
return value is ignored. */
@@ -266,7 +253,7 @@ static const struct file_operations v4l2_unlocked_fops = {
.mmap = v4l2_mmap,
.unlocked_ioctl = v4l2_unlocked_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l2_compat_ioctl,
+ .compat_ioctl = v4l2_compat_ioctl32,
#endif
.release = v4l2_release,
.poll = v4l2_poll,
@@ -281,7 +268,7 @@ static const struct file_operations v4l2_fops = {
.mmap = v4l2_mmap,
.ioctl = v4l2_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l2_compat_ioctl,
+ .compat_ioctl = v4l2_compat_ioctl32,
#endif
.release = v4l2_release,
.poll = v4l2_poll,
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 9eefde031597..cf9d4c7f571a 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -29,7 +29,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
if (dev == NULL || v4l2_dev == NULL)
return -EINVAL;
/* Warn if we apparently re-register a device */
- WARN_ON(dev_get_drvdata(dev));
+ WARN_ON(dev_get_drvdata(dev) != NULL);
INIT_LIST_HEAD(&v4l2_dev->subdevs);
spin_lock_init(&v4l2_dev->lock);
v4l2_dev->dev = dev;
@@ -61,7 +61,7 @@ int v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd)
if (dev == NULL || sd == NULL || !sd->name[0])
return -EINVAL;
/* Warn if we apparently re-register a subdev */
- WARN_ON(sd->dev);
+ WARN_ON(sd->dev != NULL);
if (!try_module_get(sd->owner))
return -ENODEV;
sd->dev = dev;
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index b063381f4b3b..52d687b165e0 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -266,7 +266,7 @@ static const char *v4l2_ioctls[] = {
[_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
[_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
- [_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT",
+ [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
[_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
#endif
};
@@ -392,14 +392,14 @@ video_fix_command(unsigned int cmd)
/*
* Obsolete usercopy function - Should be removed soon
*/
-int
+long
video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
v4l2_kioctl func)
{
char sbuf[128];
void *mbuf = NULL;
void *parg = NULL;
- int err = -EINVAL;
+ long err = -EINVAL;
int is_ext_ctrl;
size_t ctrls_size = 0;
void __user *user_ptr = NULL;
@@ -623,13 +623,13 @@ static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
return -EINVAL;
}
-static int __video_do_ioctl(struct file *file,
+static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
struct video_device *vfd = video_devdata(file);
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
void *fh = file->private_data;
- int ret = -EINVAL;
+ long ret = -EINVAL;
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
@@ -1720,7 +1720,7 @@ static int __video_do_ioctl(struct file *file,
#ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_DBG_G_REGISTER:
{
- struct v4l2_register *p = arg;
+ struct v4l2_dbg_register *p = arg;
if (!capable(CAP_SYS_ADMIN))
ret = -EPERM;
@@ -1730,7 +1730,7 @@ static int __video_do_ioctl(struct file *file,
}
case VIDIOC_DBG_S_REGISTER:
{
- struct v4l2_register *p = arg;
+ struct v4l2_dbg_register *p = arg;
if (!capable(CAP_SYS_ADMIN))
ret = -EPERM;
@@ -1739,9 +1739,9 @@ static int __video_do_ioctl(struct file *file,
break;
}
#endif
- case VIDIOC_G_CHIP_IDENT:
+ case VIDIOC_DBG_G_CHIP_IDENT:
{
- struct v4l2_chip_ident *p = arg;
+ struct v4l2_dbg_chip_ident *p = arg;
if (!ops->vidioc_g_chip_ident)
break;
@@ -1750,6 +1750,11 @@ static int __video_do_ioctl(struct file *file,
dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
break;
}
+ case VIDIOC_G_CHIP_IDENT_OLD:
+ printk(KERN_ERR "VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30.\n");
+ printk(KERN_ERR "It is a debugging ioctl and must not be used in applications!\n");
+ return -EINVAL;
+
case VIDIOC_S_HW_FREQ_SEEK:
{
struct v4l2_hw_freq_seek *p = arg;
@@ -1845,20 +1850,20 @@ static int __video_do_ioctl(struct file *file,
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
if (ret < 0) {
v4l_print_ioctl(vfd->name, cmd);
- printk(KERN_CONT " error %d\n", ret);
+ printk(KERN_CONT " error %ld\n", ret);
}
}
return ret;
}
-long __video_ioctl2(struct file *file,
+long video_ioctl2(struct file *file,
unsigned int cmd, unsigned long arg)
{
char sbuf[128];
void *mbuf = NULL;
void *parg = NULL;
- int err = -EINVAL;
+ long err = -EINVAL;
int is_ext_ctrl;
size_t ctrls_size = 0;
void __user *user_ptr = NULL;
@@ -1944,11 +1949,4 @@ out:
kfree(mbuf);
return err;
}
-EXPORT_SYMBOL(__video_ioctl2);
-
-int video_ioctl2(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return __video_ioctl2(file, cmd, arg);
-}
EXPORT_SYMBOL(video_ioctl2);
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index e3612f29d0df..21208805ea9b 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -28,16 +28,16 @@ int v4l2_subdev_command(struct v4l2_subdev *sd, unsigned cmd, void *arg)
{
switch (cmd) {
case VIDIOC_QUERYCTRL:
- return v4l2_subdev_call(sd, core, querymenu, arg);
+ return v4l2_subdev_call(sd, core, queryctrl, arg);
case VIDIOC_G_CTRL:
return v4l2_subdev_call(sd, core, g_ctrl, arg);
case VIDIOC_S_CTRL:
return v4l2_subdev_call(sd, core, s_ctrl, arg);
case VIDIOC_QUERYMENU:
- return v4l2_subdev_call(sd, core, queryctrl, arg);
+ return v4l2_subdev_call(sd, core, querymenu, arg);
case VIDIOC_LOG_STATUS:
return v4l2_subdev_call(sd, core, log_status);
- case VIDIOC_G_CHIP_IDENT:
+ case VIDIOC_DBG_G_CHIP_IDENT:
return v4l2_subdev_call(sd, core, g_chip_ident, arg);
case VIDIOC_INT_S_STANDBY:
return v4l2_subdev_call(sd, core, s_standby, arg ? (*(u32 *)arg) : 0);
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
index bc6d5aba0fe6..da1790e57a86 100644
--- a/drivers/media/video/videobuf-dma-sg.c
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -388,8 +388,7 @@ videobuf_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
page = alloc_page(GFP_USER | __GFP_DMA32);
if (!page)
return VM_FAULT_OOM;
- clear_user_page(page_address(page), (unsigned long)vmf->virtual_address,
- page);
+ clear_user_highpage(page, (unsigned long)vmf->virtual_address);
vmf->page = page;
return 0;
}
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index a72a361daade..88bf845a3d56 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -4019,7 +4019,7 @@ out:
/* File operations */
-static int vino_open(struct inode *inode, struct file *file)
+static int vino_open(struct file *file)
{
struct vino_channel_settings *vcs = video_drvdata(file);
int ret = 0;
@@ -4050,7 +4050,7 @@ static int vino_open(struct inode *inode, struct file *file)
return ret;
}
-static int vino_close(struct inode *inode, struct file *file)
+static int vino_close(struct file *file)
{
struct vino_channel_settings *vcs = video_drvdata(file);
dprintk("close():\n");
@@ -4237,7 +4237,7 @@ error:
return ret;
}
-static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct vino_channel_settings *vcs = video_drvdata(file);
@@ -4343,11 +4343,11 @@ static int vino_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int vino_ioctl(struct inode *inode, struct file *file,
+static long vino_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct vino_channel_settings *vcs = video_drvdata(file);
- int ret;
+ long ret;
if (mutex_lock_interruptible(&vcs->mutex))
return -EINTR;
@@ -4364,14 +4364,13 @@ static int vino_ioctl(struct inode *inode, struct file *file,
/* __initdata */
static int vino_init_stage;
-static const struct file_operations vino_fops = {
+static const struct v4l2_file_operations vino_fops = {
.owner = THIS_MODULE,
.open = vino_open,
.release = vino_close,
.ioctl = vino_ioctl,
.mmap = vino_mmap,
.poll = vino_poll,
- .llseek = no_llseek,
};
static struct video_device v4l_device_template = {
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index e15e48f04be7..81d5aa5cf331 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -1024,9 +1024,9 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
File operations for the device
------------------------------------------------------------------*/
-static int vivi_open(struct inode *inode, struct file *file)
+static int vivi_open(struct file *file)
{
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
struct vivi_dev *dev;
struct vivi_fh *fh = NULL;
int i;
@@ -1127,13 +1127,13 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
return videobuf_poll_stream(file, q, wait);
}
-static int vivi_close(struct inode *inode, struct file *file)
+static int vivi_close(struct file *file)
{
struct vivi_fh *fh = file->private_data;
struct vivi_dev *dev = fh->dev;
struct vivi_dmaqueue *vidq = &dev->vidq;
- int minor = iminor(inode);
+ int minor = video_devdata(file)->minor;
vivi_stop_thread(vidq);
videobuf_stop(&fh->vb_vidq);
@@ -1195,16 +1195,14 @@ static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
return ret;
}
-static const struct file_operations vivi_fops = {
+static const struct v4l2_file_operations vivi_fops = {
.owner = THIS_MODULE,
.open = vivi_open,
.release = vivi_close,
.read = vivi_read,
.poll = vivi_poll,
.ioctl = video_ioctl2, /* V4L2 ioctl handler */
- .compat_ioctl = v4l_compat_ioctl32,
.mmap = vivi_mmap,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c
index f72b859486ad..5d73f66d9f55 100644
--- a/drivers/media/video/vp27smpx.c
+++ b/drivers/media/video/vp27smpx.c
@@ -113,7 +113,7 @@ static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
return 0;
}
-static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int vp27smpx_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 56c570c267ea..038ff32b01b8 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -180,19 +180,19 @@ static int w9966_i2c_wbyte(struct w9966_dev* cam, int data);
static int w9966_i2c_rbyte(struct w9966_dev* cam);
#endif
-static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
+static long w9966_v4l_ioctl(struct file *file,
unsigned int cmd, unsigned long arg);
static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
-static int w9966_exclusive_open(struct inode *inode, struct file *file)
+static int w9966_exclusive_open(struct file *file)
{
struct w9966_dev *cam = video_drvdata(file);
return test_and_set_bit(0, &cam->in_use) ? -EBUSY : 0;
}
-static int w9966_exclusive_release(struct inode *inode, struct file *file)
+static int w9966_exclusive_release(struct file *file)
{
struct w9966_dev *cam = video_drvdata(file);
@@ -200,16 +200,12 @@ static int w9966_exclusive_release(struct inode *inode, struct file *file)
return 0;
}
-static const struct file_operations w9966_fops = {
+static const struct v4l2_file_operations w9966_fops = {
.owner = THIS_MODULE,
.open = w9966_exclusive_open,
.release = w9966_exclusive_release,
.ioctl = w9966_v4l_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = w9966_v4l_read,
- .llseek = no_llseek,
};
static struct video_device w9966_template = {
.name = W9966_DRIVERNAME,
@@ -727,7 +723,7 @@ static int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data)
* Video4linux interfacing
*/
-static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct w9966_dev *cam = video_drvdata(file);
@@ -877,7 +873,7 @@ static int w9966_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg)
return 0;
}
-static int w9966_v4l_ioctl(struct inode *inode, struct file *file,
+static long w9966_v4l_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
return video_usercopy(file, cmd, arg, w9966_v4l_do_ioctl);
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 4dfb43bd1846..105a832531f2 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -399,13 +399,13 @@ MODULE_PARM_DESC(specific_debug,
****************************************************************************/
/* Video4linux interface */
-static const struct file_operations w9968cf_fops;
-static int w9968cf_open(struct inode*, struct file*);
-static int w9968cf_release(struct inode*, struct file*);
-static int w9968cf_mmap(struct file*, struct vm_area_struct*);
-static int w9968cf_ioctl(struct inode*, struct file*, unsigned, unsigned long);
-static ssize_t w9968cf_read(struct file*, char __user *, size_t, loff_t*);
-static int w9968cf_v4l_ioctl(struct inode*, struct file*, unsigned int,
+static const struct v4l2_file_operations w9968cf_fops;
+static int w9968cf_open(struct file *);
+static int w9968cf_release(struct file *);
+static int w9968cf_mmap(struct file *, struct vm_area_struct *);
+static long w9968cf_ioctl(struct file *, unsigned, unsigned long);
+static ssize_t w9968cf_read(struct file *, char __user *, size_t, loff_t *);
+static long w9968cf_v4l_ioctl(struct file *, unsigned int,
void __user *);
/* USB-specific */
@@ -1553,7 +1553,6 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam)
static struct i2c_adapter adap = {
.id = I2C_HW_SMBUS_W9968CF,
- .class = I2C_CLASS_CAM_DIGITAL,
.owner = THIS_MODULE,
.client_register = w9968cf_i2c_attach_inform,
.client_unregister = w9968cf_i2c_detach_inform,
@@ -2662,7 +2661,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam)
* Video4Linux interface *
****************************************************************************/
-static int w9968cf_open(struct inode* inode, struct file* filp)
+static int w9968cf_open(struct file *filp)
{
struct w9968cf_device* cam;
int err;
@@ -2748,7 +2747,7 @@ deallocate_memory:
}
-static int w9968cf_release(struct inode* inode, struct file* filp)
+static int w9968cf_release(struct file *filp)
{
struct w9968cf_device* cam;
@@ -2885,12 +2884,12 @@ static int w9968cf_mmap(struct file* filp, struct vm_area_struct *vma)
}
-static int
-w9968cf_ioctl(struct inode* inode, struct file* filp,
+static long
+w9968cf_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct w9968cf_device* cam;
- int err;
+ long err;
cam = (struct w9968cf_device*)video_get_drvdata(video_devdata(filp));
@@ -2909,15 +2908,15 @@ w9968cf_ioctl(struct inode* inode, struct file* filp,
return -EIO;
}
- err = w9968cf_v4l_ioctl(inode, filp, cmd, (void __user *)arg);
+ err = w9968cf_v4l_ioctl(filp, cmd, (void __user *)arg);
mutex_unlock(&cam->fileop_mutex);
return err;
}
-static int w9968cf_v4l_ioctl(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+static long w9968cf_v4l_ioctl(struct file *filp,
+ unsigned int cmd, void __user *arg)
{
struct w9968cf_device* cam;
const char* v4l1_ioctls[] = {
@@ -3456,17 +3455,13 @@ ioctl_fail:
}
-static const struct file_operations w9968cf_fops = {
+static const struct v4l2_file_operations w9968cf_fops = {
.owner = THIS_MODULE,
.open = w9968cf_open,
.release = w9968cf_release,
.read = w9968cf_read,
.ioctl = w9968cf_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.mmap = w9968cf_mmap,
- .llseek = no_llseek,
};
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index 12a31e7a5f6d..f2864d5cd180 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -233,7 +233,7 @@ static int wm8739_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
return -EINVAL;
}
-static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int wm8739_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index d0220b0ec0bc..53fcd42843e0 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -130,7 +130,7 @@ static int wm8775_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
return 0;
}
-static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
+static int wm8775_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 9d00e6056491..96971044fc78 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -649,7 +649,7 @@ static void zc0301_release_resources(struct kref *kref)
}
-static int zc0301_open(struct inode* inode, struct file* filp)
+static int zc0301_open(struct file *filp)
{
struct zc0301_device* cam;
int err = 0;
@@ -733,7 +733,7 @@ out:
}
-static int zc0301_release(struct inode* inode, struct file* filp)
+static int zc0301_release(struct file *filp)
{
struct zc0301_device* cam;
@@ -1793,8 +1793,8 @@ zc0301_vidioc_s_parm(struct zc0301_device* cam, void __user * arg)
}
-static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
- unsigned int cmd, void __user * arg)
+static long zc0301_ioctl_v4l2(struct file *filp,
+ unsigned int cmd, void __user *arg)
{
struct zc0301_device *cam = video_drvdata(filp);
@@ -1888,7 +1888,7 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
}
-static int zc0301_ioctl(struct inode* inode, struct file* filp,
+static long zc0301_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
struct zc0301_device *cam = video_drvdata(filp);
@@ -1912,7 +1912,7 @@ static int zc0301_ioctl(struct inode* inode, struct file* filp,
V4LDBG(3, "zc0301", cmd);
- err = zc0301_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
+ err = zc0301_ioctl_v4l2(filp, cmd, (void __user *)arg);
mutex_unlock(&cam->fileop_mutex);
@@ -1920,18 +1920,14 @@ static int zc0301_ioctl(struct inode* inode, struct file* filp,
}
-static const struct file_operations zc0301_fops = {
+static const struct v4l2_file_operations zc0301_fops = {
.owner = THIS_MODULE,
.open = zc0301_open,
.release = zc0301_release,
.ioctl = zc0301_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
.read = zc0301_read,
.poll = zc0301_poll,
.mmap = zc0301_mmap,
- .llseek = no_llseek,
};
/*****************************************************************************/
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h
index 46b7ad477ceb..e873a916250f 100644
--- a/drivers/media/video/zoran/zoran.h
+++ b/drivers/media/video/zoran/zoran.h
@@ -349,7 +349,6 @@ struct card_info {
u16 i2c_decoder, i2c_encoder; /* I2C types */
u16 video_vfe, video_codec; /* videocodec types */
u16 audio_chip; /* audio type */
- u16 vendor_id, device_id; /* subsystem vendor/device ID */
int inputs; /* number of video inputs */
struct input {
@@ -401,7 +400,6 @@ struct zoran {
char name[32]; /* name of this device */
struct pci_dev *pci_dev; /* PCI device */
unsigned char revision; /* revision of zr36057 */
- unsigned int zr36057_adr; /* bus address of IO mem returned by PCI BIOS */
unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */
spinlock_t spinlock; /* Spinlock */
@@ -490,16 +488,10 @@ struct zoran {
wait_queue_head_t test_q;
};
-/*The following should be done in more portable way. It depends on define
- of _ALPHA_BUZ in the Makefile.*/
-
-#ifdef _ALPHA_BUZ
-#define btwrite(dat,adr) writel((dat), zr->zr36057_adr+(adr))
-#define btread(adr) readl(zr->zr36057_adr+(adr))
-#else
+/* There was something called _ALPHA_BUZ that used the PCI address instead of
+ * the kernel iomapped address for btread/btwrite. */
#define btwrite(dat,adr) writel((dat), zr->zr36057_mem+(adr))
#define btread(adr) readl(zr->zr36057_mem+(adr))
-#endif
#define btand(dat,adr) btwrite((dat) & btread(adr), adr)
#define btor(dat,adr) btwrite((dat) | btread(adr), adr)
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
index 05f39195372e..5d2f090aa0f8 100644
--- a/drivers/media/video/zoran/zoran_card.c
+++ b/drivers/media/video/zoran/zoran_card.c
@@ -61,17 +61,17 @@
extern const struct zoran_format zoran_formats[];
-static int card[BUZ_MAX] = { -1, -1, -1, -1 };
+static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
module_param_array(card, int, NULL, 0444);
-MODULE_PARM_DESC(card, "The type of card");
+MODULE_PARM_DESC(card, "Card type");
-static int encoder[BUZ_MAX] = { -1, -1, -1, -1 };
+static int encoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
module_param_array(encoder, int, NULL, 0444);
-MODULE_PARM_DESC(encoder, "i2c TV encoder");
+MODULE_PARM_DESC(encoder, "Video encoder chip");
-static int decoder[BUZ_MAX] = { -1, -1, -1, -1 };
+static int decoder[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
module_param_array(decoder, int, NULL, 0444);
-MODULE_PARM_DESC(decoder, "i2c TV decoder");
+MODULE_PARM_DESC(decoder, "Video decoder chip");
/*
The video mem address of the video card.
@@ -104,9 +104,9 @@ module_param(default_norm, int, 0444);
MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
/* /dev/videoN, -1 for autodetect */
-static int video_nr[BUZ_MAX] = {-1, -1, -1, -1};
+static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
module_param_array(video_nr, int, NULL, 0444);
-MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
+MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
/*
Number and size of grab buffers for Video 4 Linux
@@ -153,9 +153,21 @@ MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
MODULE_AUTHOR("Serguei Miridonov");
MODULE_LICENSE("GPL");
+#define ZR_DEVICE(subven, subdev, data) { \
+ .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \
+ .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) }
+
+static struct pci_device_id zr36067_pci_tbl[] = {
+ ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10plus),
+ ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30plus),
+ ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10),
+ ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ),
+ ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS),
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
-int zoran_num; /* number of Buzs in use */
-struct zoran *zoran[BUZ_MAX];
+static unsigned int zoran_num; /* number of cards found */
/* videocodec bus functions ZR36060 */
static u32
@@ -472,8 +484,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
}, {
.type = DC10plus,
.name = "DC10plus",
- .vendor_id = PCI_VENDOR_ID_MIRO,
- .device_id = PCI_DEVICE_ID_MIRO_DC10PLUS,
.i2c_decoder = I2C_DRIVERID_SAA7110,
.i2c_encoder = I2C_DRIVERID_ADV7175,
.video_codec = CODEC_TYPE_ZR36060,
@@ -531,8 +541,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
}, {
.type = DC30plus,
.name = "DC30plus",
- .vendor_id = PCI_VENDOR_ID_MIRO,
- .device_id = PCI_DEVICE_ID_MIRO_DC30PLUS,
.i2c_decoder = I2C_DRIVERID_VPX3220,
.i2c_encoder = I2C_DRIVERID_ADV7175,
.video_codec = CODEC_TYPE_ZR36050,
@@ -589,8 +597,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
}, {
.type = LML33R10,
.name = "LML33R10",
- .vendor_id = PCI_VENDOR_ID_ELECTRONICDESIGNGMBH,
- .device_id = PCI_DEVICE_ID_LML_33R10,
.i2c_decoder = I2C_DRIVERID_SAA7114,
.i2c_encoder = I2C_DRIVERID_ADV7170,
.video_codec = CODEC_TYPE_ZR36060,
@@ -618,8 +624,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
}, {
.type = BUZ,
.name = "Buz",
- .vendor_id = PCI_VENDOR_ID_IOMEGA,
- .device_id = PCI_DEVICE_ID_IOMEGA_BUZ,
.i2c_decoder = I2C_DRIVERID_SAA7111A,
.i2c_encoder = I2C_DRIVERID_SAA7185B,
.video_codec = CODEC_TYPE_ZR36060,
@@ -649,8 +653,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
.name = "6-Eyes",
/* AverMedia chose not to brand the 6-Eyes. Thus it
can't be autodetected, and requires card=x. */
- .vendor_id = -1,
- .device_id = -1,
.i2c_decoder = I2C_DRIVERID_KS0127,
.i2c_encoder = I2C_DRIVERID_BT866,
.video_codec = CODEC_TYPE_ZR36060,
@@ -1138,7 +1140,8 @@ zr36057_init (struct zoran *zr)
strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
if (err < 0)
- goto exit_unregister;
+ goto exit_free;
+ video_set_drvdata(zr->video_dev, zr);
zoran_init_hardware(zr);
if (zr36067_debug > 2)
@@ -1153,19 +1156,19 @@ zr36057_init (struct zoran *zr)
zr->initialized = 1;
return 0;
-exit_unregister:
- zoran_unregister_i2c(zr);
exit_free:
kfree(zr->stat_com);
kfree(zr->video_dev);
return err;
}
-static void
-zoran_release (struct zoran *zr)
+static void __devexit zoran_remove(struct pci_dev *pdev)
{
+ struct zoran *zr = pci_get_drvdata(pdev);
+
if (!zr->initialized)
goto exit_free;
+
/* unregister videocodec bus */
if (zr->codec) {
struct videocodec_master *master = zr->codec->master_data;
@@ -1194,6 +1197,7 @@ zoran_release (struct zoran *zr)
pci_disable_device(zr->pci_dev);
video_unregister_device(zr->video_dev);
exit_free:
+ pci_set_drvdata(pdev, NULL);
kfree(zr);
}
@@ -1256,338 +1260,329 @@ zoran_setup_videocodec (struct zoran *zr,
* Scan for a Buz card (actually for the PCI controller ZR36057),
* request the irq and map the io memory
*/
-static int __devinit
-find_zr36057 (void)
+static int __devinit zoran_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
unsigned char latency, need_latency;
struct zoran *zr;
- struct pci_dev *dev = NULL;
int result;
struct videocodec_master *master_vfe = NULL;
struct videocodec_master *master_codec = NULL;
int card_num;
char *i2c_enc_name, *i2c_dec_name, *codec_name, *vfe_name;
+ unsigned int nr;
- zoran_num = 0;
- while (zoran_num < BUZ_MAX &&
- (dev = pci_get_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36057, dev)) != NULL) {
- card_num = card[zoran_num];
- zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
- if (!zr) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - kzalloc failed\n",
- ZORAN_NAME);
- continue;
- }
- zr->pci_dev = dev;
- //zr->zr36057_mem = NULL;
- zr->id = zoran_num;
- snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
- spin_lock_init(&zr->spinlock);
- mutex_init(&zr->resource_lock);
- if (pci_enable_device(dev))
- goto zr_free_mem;
- zr->zr36057_adr = pci_resource_start(zr->pci_dev, 0);
- pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION,
- &zr->revision);
- if (zr->revision < 2) {
- dprintk(1,
- KERN_INFO
- "%s: Zoran ZR36057 (rev %d) irq: %d, memory: 0x%08x.\n",
- ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
- zr->zr36057_adr);
- if (card_num == -1) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - no card specified, please use the card=X insmod option\n",
- ZR_DEVNAME(zr));
- goto zr_free_mem;
- }
- } else {
- int i;
- unsigned short ss_vendor, ss_device;
+ nr = zoran_num++;
+ if (nr >= BUZ_MAX) {
+ dprintk(1,
+ KERN_ERR
+ "%s: driver limited to %d card(s) maximum\n",
+ ZORAN_NAME, BUZ_MAX);
+ return -ENOENT;
+ }
- ss_vendor = zr->pci_dev->subsystem_vendor;
- ss_device = zr->pci_dev->subsystem_device;
+ zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
+ if (!zr) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - kzalloc failed\n",
+ ZORAN_NAME);
+ return -ENOMEM;
+ }
+ zr->pci_dev = pdev;
+ zr->id = nr;
+ snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
+ spin_lock_init(&zr->spinlock);
+ mutex_init(&zr->resource_lock);
+ if (pci_enable_device(pdev))
+ goto zr_free_mem;
+ pci_read_config_byte(zr->pci_dev, PCI_CLASS_REVISION, &zr->revision);
+
+ dprintk(1,
+ KERN_INFO
+ "%s: Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n",
+ ZR_DEVNAME(zr), zr->revision < 2 ? '5' : '6', zr->revision,
+ zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0));
+ if (zr->revision >= 2) {
+ dprintk(1,
+ KERN_INFO
+ "%s: Subsystem vendor=0x%04x id=0x%04x\n",
+ ZR_DEVNAME(zr), zr->pci_dev->subsystem_vendor,
+ zr->pci_dev->subsystem_device);
+ }
+
+ /* Use auto-detected card type? */
+ if (card[nr] == -1) {
+ if (zr->revision < 2) {
dprintk(1,
- KERN_INFO
- "%s: Zoran ZR36067 (rev %d) irq: %d, memory: 0x%08x\n",
- ZR_DEVNAME(zr), zr->revision, zr->pci_dev->irq,
- zr->zr36057_adr);
+ KERN_ERR
+ "%s: No card type specified, please use the card=X module parameter\n",
+ ZR_DEVNAME(zr));
dprintk(1,
- KERN_INFO
- "%s: subsystem vendor=0x%04x id=0x%04x\n",
- ZR_DEVNAME(zr), ss_vendor, ss_device);
- if (card_num == -1) {
- dprintk(3,
- KERN_DEBUG
- "%s: find_zr36057() - trying to autodetect card type\n",
- ZR_DEVNAME(zr));
- for (i=0;i<NUM_CARDS;i++) {
- if (ss_vendor == zoran_cards[i].vendor_id &&
- ss_device == zoran_cards[i].device_id) {
- dprintk(3,
- KERN_DEBUG
- "%s: find_zr36057() - card %s detected\n",
- ZR_DEVNAME(zr),
- zoran_cards[i].name);
- card_num = i;
- break;
- }
- }
- if (i == NUM_CARDS) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - unknown card\n",
- ZR_DEVNAME(zr));
- goto zr_free_mem;
- }
- }
- }
-
- if (card_num < 0 || card_num >= NUM_CARDS) {
- dprintk(2,
KERN_ERR
- "%s: find_zr36057() - invalid cardnum %d\n",
- ZR_DEVNAME(zr), card_num);
+ "%s: It is not possible to auto-detect ZR36057 based cards\n",
+ ZR_DEVNAME(zr));
goto zr_free_mem;
}
- /* even though we make this a non pointer and thus
- * theoretically allow for making changes to this struct
- * on a per-individual card basis at runtime, this is
- * strongly discouraged. This structure is intended to
- * keep general card information, no settings or anything */
- zr->card = zoran_cards[card_num];
- snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
- "%s[%u]", zr->card.name, zr->id);
-
- zr->zr36057_mem = ioremap_nocache(zr->zr36057_adr, 0x1000);
- if (!zr->zr36057_mem) {
+ card_num = ent->driver_data;
+ if (card_num >= NUM_CARDS) {
dprintk(1,
KERN_ERR
- "%s: find_zr36057() - ioremap failed\n",
+ "%s: Unknown card, try specifying card=X module parameter\n",
ZR_DEVNAME(zr));
goto zr_free_mem;
}
-
- result = request_irq(zr->pci_dev->irq,
- zoran_irq,
- IRQF_SHARED | IRQF_DISABLED,
- ZR_DEVNAME(zr),
- (void *) zr);
- if (result < 0) {
- if (result == -EINVAL) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - bad irq number or handler\n",
- ZR_DEVNAME(zr));
- } else if (result == -EBUSY) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n",
- ZR_DEVNAME(zr), zr->pci_dev->irq);
- } else {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - can't assign irq, error code %d\n",
- ZR_DEVNAME(zr), result);
- }
- goto zr_unmap;
- }
-
- /* set PCI latency timer */
- pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
- &latency);
- need_latency = zr->revision > 1 ? 32 : 48;
- if (latency != need_latency) {
- dprintk(2,
- KERN_INFO
- "%s: Changing PCI latency from %d to %d.\n",
- ZR_DEVNAME(zr), latency, need_latency);
- pci_write_config_byte(zr->pci_dev,
- PCI_LATENCY_TIMER,
- need_latency);
+ dprintk(3,
+ KERN_DEBUG
+ "%s: %s() - card %s detected\n",
+ ZR_DEVNAME(zr), __func__, zoran_cards[card_num].name);
+ } else {
+ card_num = card[nr];
+ if (card_num >= NUM_CARDS || card_num < 0) {
+ dprintk(1,
+ KERN_ERR
+ "%s: User specified card type %d out of range (0 .. %d)\n",
+ ZR_DEVNAME(zr), card_num, NUM_CARDS - 1);
+ goto zr_free_mem;
}
+ }
- zr36057_restart(zr);
- /* i2c */
- dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
- ZR_DEVNAME(zr));
+ /* even though we make this a non pointer and thus
+ * theoretically allow for making changes to this struct
+ * on a per-individual card basis at runtime, this is
+ * strongly discouraged. This structure is intended to
+ * keep general card information, no settings or anything */
+ zr->card = zoran_cards[card_num];
+ snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
+ "%s[%u]", zr->card.name, zr->id);
+
+ zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0);
+ if (!zr->zr36057_mem) {
+ dprintk(1,
+ KERN_ERR
+ "%s: %s() - ioremap failed\n",
+ ZR_DEVNAME(zr), __func__);
+ goto zr_free_mem;
+ }
- /* i2c decoder */
- if (decoder[zr->id] != -1) {
- i2c_dec_name = i2cid_to_modulename(decoder[zr->id]);
- zr->card.i2c_decoder = decoder[zr->id];
- } else if (zr->card.i2c_decoder != 0) {
- i2c_dec_name =
- i2cid_to_modulename(zr->card.i2c_decoder);
+ result = request_irq(zr->pci_dev->irq, zoran_irq,
+ IRQF_SHARED | IRQF_DISABLED, ZR_DEVNAME(zr), zr);
+ if (result < 0) {
+ if (result == -EINVAL) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - bad irq number or handler\n",
+ ZR_DEVNAME(zr));
+ } else if (result == -EBUSY) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - IRQ %d busy, change your PnP config in BIOS\n",
+ ZR_DEVNAME(zr), zr->pci_dev->irq);
} else {
- i2c_dec_name = NULL;
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - can't assign irq, error code %d\n",
+ ZR_DEVNAME(zr), result);
}
+ goto zr_unmap;
+ }
- if (i2c_dec_name) {
- if ((result = request_module(i2c_dec_name)) < 0) {
- dprintk(1,
- KERN_ERR
- "%s: failed to load module %s: %d\n",
- ZR_DEVNAME(zr), i2c_dec_name, result);
- }
- }
+ /* set PCI latency timer */
+ pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
+ &latency);
+ need_latency = zr->revision > 1 ? 32 : 48;
+ if (latency != need_latency) {
+ dprintk(2,
+ KERN_INFO
+ "%s: Changing PCI latency from %d to %d\n",
+ ZR_DEVNAME(zr), latency, need_latency);
+ pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
+ need_latency);
+ }
- /* i2c encoder */
- if (encoder[zr->id] != -1) {
- i2c_enc_name = i2cid_to_modulename(encoder[zr->id]);
- zr->card.i2c_encoder = encoder[zr->id];
- } else if (zr->card.i2c_encoder != 0) {
- i2c_enc_name =
- i2cid_to_modulename(zr->card.i2c_encoder);
- } else {
- i2c_enc_name = NULL;
- }
+ zr36057_restart(zr);
+ /* i2c */
+ dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
+ ZR_DEVNAME(zr));
+
+ /* i2c decoder */
+ if (decoder[zr->id] != -1) {
+ i2c_dec_name = i2cid_to_modulename(decoder[zr->id]);
+ zr->card.i2c_decoder = decoder[zr->id];
+ } else if (zr->card.i2c_decoder != 0) {
+ i2c_dec_name = i2cid_to_modulename(zr->card.i2c_decoder);
+ } else {
+ i2c_dec_name = NULL;
+ }
- if (i2c_enc_name) {
- if ((result = request_module(i2c_enc_name)) < 0) {
- dprintk(1,
- KERN_ERR
- "%s: failed to load module %s: %d\n",
- ZR_DEVNAME(zr), i2c_enc_name, result);
- }
+ if (i2c_dec_name) {
+ result = request_module(i2c_dec_name);
+ if (result < 0) {
+ dprintk(1,
+ KERN_ERR
+ "%s: failed to load module %s: %d\n",
+ ZR_DEVNAME(zr), i2c_dec_name, result);
}
+ }
+
+ /* i2c encoder */
+ if (encoder[zr->id] != -1) {
+ i2c_enc_name = i2cid_to_modulename(encoder[zr->id]);
+ zr->card.i2c_encoder = encoder[zr->id];
+ } else if (zr->card.i2c_encoder != 0) {
+ i2c_enc_name = i2cid_to_modulename(zr->card.i2c_encoder);
+ } else {
+ i2c_enc_name = NULL;
+ }
- if (zoran_register_i2c(zr) < 0) {
+ if (i2c_enc_name) {
+ result = request_module(i2c_enc_name);
+ if (result < 0) {
dprintk(1,
KERN_ERR
- "%s: find_zr36057() - can't initialize i2c bus\n",
- ZR_DEVNAME(zr));
- goto zr_free_irq;
+ "%s: failed to load module %s: %d\n",
+ ZR_DEVNAME(zr), i2c_enc_name, result);
}
+ }
- dprintk(2,
- KERN_INFO "%s: Initializing videocodec bus...\n",
+ if (zoran_register_i2c(zr) < 0) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - can't initialize i2c bus\n",
ZR_DEVNAME(zr));
+ goto zr_free_irq;
+ }
- if (zr->card.video_codec != 0 &&
- (codec_name =
- codecid_to_modulename(zr->card.video_codec)) != NULL) {
- if ((result = request_module(codec_name)) < 0) {
+ dprintk(2,
+ KERN_INFO "%s: Initializing videocodec bus...\n",
+ ZR_DEVNAME(zr));
+
+ if (zr->card.video_codec) {
+ codec_name = codecid_to_modulename(zr->card.video_codec);
+ if (codec_name) {
+ result = request_module(codec_name);
+ if (result) {
dprintk(1,
KERN_ERR
"%s: failed to load modules %s: %d\n",
ZR_DEVNAME(zr), codec_name, result);
}
}
- if (zr->card.video_vfe != 0 &&
- (vfe_name =
- codecid_to_modulename(zr->card.video_vfe)) != NULL) {
- if ((result = request_module(vfe_name)) < 0) {
+ }
+ if (zr->card.video_vfe) {
+ vfe_name = codecid_to_modulename(zr->card.video_vfe);
+ if (vfe_name) {
+ result = request_module(vfe_name);
+ if (result < 0) {
dprintk(1,
KERN_ERR
"%s: failed to load modules %s: %d\n",
ZR_DEVNAME(zr), vfe_name, result);
}
}
+ }
- /* reset JPEG codec */
- jpeg_codec_sleep(zr, 1);
- jpeg_codec_reset(zr);
- /* video bus enabled */
- /* display codec revision */
- if (zr->card.video_codec != 0) {
- master_codec = zoran_setup_videocodec(zr,
- zr->card.video_codec);
- if (!master_codec)
- goto zr_unreg_i2c;
- zr->codec = videocodec_attach(master_codec);
- if (!zr->codec) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - no codec found\n",
- ZR_DEVNAME(zr));
- goto zr_free_codec;
- }
- if (zr->codec->type != zr->card.video_codec) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - wrong codec\n",
- ZR_DEVNAME(zr));
- goto zr_detach_codec;
- }
+ /* reset JPEG codec */
+ jpeg_codec_sleep(zr, 1);
+ jpeg_codec_reset(zr);
+ /* video bus enabled */
+ /* display codec revision */
+ if (zr->card.video_codec != 0) {
+ master_codec = zoran_setup_videocodec(zr, zr->card.video_codec);
+ if (!master_codec)
+ goto zr_unreg_i2c;
+ zr->codec = videocodec_attach(master_codec);
+ if (!zr->codec) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - no codec found\n",
+ ZR_DEVNAME(zr));
+ goto zr_free_codec;
}
- if (zr->card.video_vfe != 0) {
- master_vfe = zoran_setup_videocodec(zr,
- zr->card.video_vfe);
- if (!master_vfe)
- goto zr_detach_codec;
- zr->vfe = videocodec_attach(master_vfe);
- if (!zr->vfe) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() - no VFE found\n",
- ZR_DEVNAME(zr));
- goto zr_free_vfe;
- }
- if (zr->vfe->type != zr->card.video_vfe) {
- dprintk(1,
- KERN_ERR
- "%s: find_zr36057() = wrong VFE\n",
- ZR_DEVNAME(zr));
- goto zr_detach_vfe;
- }
+ if (zr->codec->type != zr->card.video_codec) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - wrong codec\n",
+ ZR_DEVNAME(zr));
+ goto zr_detach_codec;
+ }
+ }
+ if (zr->card.video_vfe != 0) {
+ master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe);
+ if (!master_vfe)
+ goto zr_detach_codec;
+ zr->vfe = videocodec_attach(master_vfe);
+ if (!zr->vfe) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() - no VFE found\n",
+ ZR_DEVNAME(zr));
+ goto zr_free_vfe;
+ }
+ if (zr->vfe->type != zr->card.video_vfe) {
+ dprintk(1,
+ KERN_ERR
+ "%s: find_zr36057() = wrong VFE\n",
+ ZR_DEVNAME(zr));
+ goto zr_detach_vfe;
}
- /* Success so keep the pci_dev referenced */
- pci_dev_get(zr->pci_dev);
- zoran[zoran_num++] = zr;
- continue;
-
- // Init errors
- zr_detach_vfe:
- videocodec_detach(zr->vfe);
- zr_free_vfe:
- kfree(master_vfe);
- zr_detach_codec:
- videocodec_detach(zr->codec);
- zr_free_codec:
- kfree(master_codec);
- zr_unreg_i2c:
- zoran_unregister_i2c(zr);
- zr_free_irq:
- btwrite(0, ZR36057_SPGPPCR);
- free_irq(zr->pci_dev->irq, zr);
- zr_unmap:
- iounmap(zr->zr36057_mem);
- zr_free_mem:
- kfree(zr);
- continue;
}
- if (dev) /* Clean up ref count on early exit */
- pci_dev_put(dev);
- if (zoran_num == 0) {
- dprintk(1, KERN_INFO "No known MJPEG cards found.\n");
+ /* take care of Natoma chipset and a revision 1 zr36057 */
+ if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
+ zr->jpg_buffers.need_contiguous = 1;
+ dprintk(1,
+ KERN_INFO
+ "%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
+ ZR_DEVNAME(zr));
}
- return zoran_num;
+
+ if (zr36057_init(zr) < 0)
+ goto zr_detach_vfe;
+
+ zoran_proc_init(zr);
+
+ pci_set_drvdata(pdev, zr);
+
+ return 0;
+
+zr_detach_vfe:
+ videocodec_detach(zr->vfe);
+zr_free_vfe:
+ kfree(master_vfe);
+zr_detach_codec:
+ videocodec_detach(zr->codec);
+zr_free_codec:
+ kfree(master_codec);
+zr_unreg_i2c:
+ zoran_unregister_i2c(zr);
+zr_free_irq:
+ btwrite(0, ZR36057_SPGPPCR);
+ free_irq(zr->pci_dev->irq, zr);
+zr_unmap:
+ iounmap(zr->zr36057_mem);
+zr_free_mem:
+ kfree(zr);
+
+ return -ENODEV;
}
-static int __init
-init_dc10_cards (void)
+static struct pci_driver zoran_driver = {
+ .name = "zr36067",
+ .id_table = zr36067_pci_tbl,
+ .probe = zoran_probe,
+ .remove = zoran_remove,
+};
+
+static int __init zoran_init(void)
{
- int i;
+ int res;
- memset(zoran, 0, sizeof(zoran));
printk(KERN_INFO "Zoran MJPEG board driver version %d.%d.%d\n",
MAJOR_VERSION, MINOR_VERSION, RELEASE_VERSION);
- /* Look for cards */
- if (find_zr36057() < 0) {
- return -EIO;
- }
- if (zoran_num == 0)
- return -ENODEV;
- dprintk(1, KERN_INFO "%s: %d card(s) found\n", ZORAN_NAME,
- zoran_num);
/* check the parameters we have been given, adjust if necessary */
if (v4l_nbufs < 2)
v4l_nbufs = 2;
@@ -1629,37 +1624,22 @@ init_dc10_cards (void)
ZORAN_NAME);
}
- /* take care of Natoma chipset and a revision 1 zr36057 */
- for (i = 0; i < zoran_num; i++) {
- struct zoran *zr = zoran[i];
-
- if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
- zr->jpg_buffers.need_contiguous = 1;
- dprintk(1,
- KERN_INFO
- "%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
- ZR_DEVNAME(zr));
- }
-
- if (zr36057_init(zr) < 0) {
- for (i = 0; i < zoran_num; i++)
- zoran_release(zoran[i]);
- return -EIO;
- }
- zoran_proc_init(zr);
+ res = pci_register_driver(&zoran_driver);
+ if (res) {
+ dprintk(1,
+ KERN_ERR
+ "%s: Unable to register ZR36057 driver\n",
+ ZORAN_NAME);
+ return res;
}
return 0;
}
-static void __exit
-unload_dc10_cards (void)
+static void __exit zoran_exit(void)
{
- int i;
-
- for (i = 0; i < zoran_num; i++)
- zoran_release(zoran[i]);
+ pci_unregister_driver(&zoran_driver);
}
-module_init(init_dc10_cards);
-module_exit(unload_dc10_cards);
+module_init(zoran_init);
+module_exit(zoran_exit);
diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/video/zoran/zoran_card.h
index e4dc9d29b404..4507bdc5e338 100644
--- a/drivers/media/video/zoran/zoran_card.h
+++ b/drivers/media/video/zoran/zoran_card.h
@@ -40,8 +40,6 @@ extern int zr36067_debug;
/* Anybody who uses more than four? */
#define BUZ_MAX 4
-extern int zoran_num;
-extern struct zoran *zoran[BUZ_MAX];
extern struct video_device zoran_template;
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
index 00b97d97aeaa..120ef235e63d 100644
--- a/drivers/media/video/zoran/zoran_driver.c
+++ b/drivers/media/video/zoran/zoran_driver.c
@@ -1196,84 +1196,54 @@ zoran_close_end_session (struct file *file)
* Open a zoran card. Right now the flags stuff is just playing
*/
-static int
-zoran_open (struct inode *inode,
- struct file *file)
+static int zoran_open(struct file *file)
{
- unsigned int minor = iminor(inode);
- struct zoran *zr = NULL;
+ struct zoran *zr = video_drvdata(file);
struct zoran_fh *fh;
- int i, res, first_open = 0, have_module_locks = 0;
+ int res, first_open = 0;
- lock_kernel();
- /* find the device */
- for (i = 0; i < zoran_num; i++) {
- if (zoran[i]->video_dev->minor == minor) {
- zr = zoran[i];
- break;
- }
- }
+ dprintk(2, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
+ ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user + 1);
- if (!zr) {
- dprintk(1, KERN_ERR "%s: device not found!\n", ZORAN_NAME);
- res = -ENODEV;
- goto open_unlock_and_return;
- }
+ lock_kernel();
/* see fs/device.c - the kernel already locks during open(),
* so locking ourselves only causes deadlocks */
/*mutex_lock(&zr->resource_lock);*/
+ if (zr->user >= 2048) {
+ dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
+ ZR_DEVNAME(zr), zr->user);
+ res = -EBUSY;
+ goto fail_unlock;
+ }
+
if (!zr->decoder) {
dprintk(1,
KERN_ERR "%s: no TV decoder loaded for device!\n",
ZR_DEVNAME(zr));
res = -EIO;
- goto open_unlock_and_return;
+ goto fail_unlock;
}
- /* try to grab a module lock */
- if (!try_module_get(THIS_MODULE)) {
- dprintk(1,
- KERN_ERR
- "%s: failed to acquire my own lock! PANIC!\n",
- ZR_DEVNAME(zr));
- res = -ENODEV;
- goto open_unlock_and_return;
- }
if (!try_module_get(zr->decoder->driver->driver.owner)) {
dprintk(1,
KERN_ERR
- "%s: failed to grab ownership of i2c decoder\n",
+ "%s: failed to grab ownership of video decoder\n",
ZR_DEVNAME(zr));
res = -EIO;
- module_put(THIS_MODULE);
- goto open_unlock_and_return;
+ goto fail_unlock;
}
if (zr->encoder &&
!try_module_get(zr->encoder->driver->driver.owner)) {
dprintk(1,
KERN_ERR
- "%s: failed to grab ownership of i2c encoder\n",
+ "%s: failed to grab ownership of video encoder\n",
ZR_DEVNAME(zr));
res = -EIO;
- module_put(zr->decoder->driver->driver.owner);
- module_put(THIS_MODULE);
- goto open_unlock_and_return;
+ goto fail_decoder;
}
- have_module_locks = 1;
-
- if (zr->user >= 2048) {
- dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
- ZR_DEVNAME(zr), zr->user);
- res = -EBUSY;
- goto open_unlock_and_return;
- }
-
- dprintk(1, KERN_INFO "%s: zoran_open(%s, pid=[%d]), users(-)=%d\n",
- ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
-
/* now, create the open()-specific file_ops struct */
fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
if (!fh) {
@@ -1282,7 +1252,7 @@ zoran_open (struct inode *inode,
"%s: zoran_open() - allocation of zoran_fh failed\n",
ZR_DEVNAME(zr));
res = -ENOMEM;
- goto open_unlock_and_return;
+ goto fail_encoder;
}
/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
* on norm-change! */
@@ -1293,9 +1263,8 @@ zoran_open (struct inode *inode,
KERN_ERR
"%s: zoran_open() - allocation of overlay_mask failed\n",
ZR_DEVNAME(zr));
- kfree(fh);
res = -ENOMEM;
- goto open_unlock_and_return;
+ goto fail_fh;
}
if (zr->user++ == 0)
@@ -1320,34 +1289,30 @@ zoran_open (struct inode *inode,
return 0;
-open_unlock_and_return:
- /* if we grabbed locks, release them accordingly */
- if (have_module_locks) {
- module_put(zr->decoder->driver->driver.owner);
- if (zr->encoder) {
- module_put(zr->encoder->driver->driver.owner);
- }
- module_put(THIS_MODULE);
- }
-
- /* if there's no device found, we didn't obtain the lock either */
- if (zr) {
- /*mutex_unlock(&zr->resource_lock);*/
- }
+fail_fh:
+ kfree(fh);
+fail_encoder:
+ if (zr->encoder)
+ module_put(zr->encoder->driver->driver.owner);
+fail_decoder:
+ module_put(zr->decoder->driver->driver.owner);
+fail_unlock:
unlock_kernel();
+ dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n",
+ ZR_DEVNAME(zr), res, zr->user);
+
return res;
}
static int
-zoran_close (struct inode *inode,
- struct file *file)
+zoran_close(struct file *file)
{
struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr;
- dprintk(1, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
- ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user);
+ dprintk(2, KERN_INFO "%s: zoran_close(%s, pid=[%d]), users(+)=%d\n",
+ ZR_DEVNAME(zr), current->comm, task_pid_nr(current), zr->user - 1);
/* kernel locks (fs/device.c), so don't do that ourselves
* (prevents deadlocks) */
@@ -1393,10 +1358,8 @@ zoran_close (struct inode *inode,
/* release locks on the i2c modules */
module_put(zr->decoder->driver->driver.owner);
- if (zr->encoder) {
- module_put(zr->encoder->driver->driver.owner);
- }
- module_put(THIS_MODULE);
+ if (zr->encoder)
+ module_put(zr->encoder->driver->driver.owner);
/*mutex_unlock(&zr->resource_lock);*/
@@ -1940,7 +1903,7 @@ zoran_set_input (struct zoran *zr,
* ioctl routine
*/
-static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static long zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct zoran_fh *fh = file->private_data;
struct zoran *zr = fh->zr;
@@ -4191,11 +4154,10 @@ static int zoran_do_ioctl(struct file *file, unsigned int cmd, void *arg)
}
-static int
-zoran_ioctl (struct inode *inode,
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
+static long
+zoran_ioctl(struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
{
return video_usercopy(file, cmd, arg, zoran_do_ioctl);
}
@@ -4620,15 +4582,11 @@ zoran_mmap (struct file *file,
return 0;
}
-static const struct file_operations zoran_fops = {
+static const struct v4l2_file_operations zoran_fops = {
.owner = THIS_MODULE,
.open = zoran_open,
.release = zoran_close,
.ioctl = zoran_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = v4l_compat_ioctl32,
-#endif
- .llseek = no_llseek,
.read = zoran_read,
.write = zoran_write,
.mmap = zoran_mmap,
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index a1d81ed44c7c..93023560f324 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -634,7 +634,7 @@ static int zr364xx_vidioc_streamoff(struct file *file, void *priv,
/* open the camera */
-static int zr364xx_open(struct inode *inode, struct file *file)
+static int zr364xx_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct zr364xx_camera *cam = video_get_drvdata(vdev);
@@ -688,7 +688,7 @@ out:
/* release the camera */
-static int zr364xx_release(struct inode *inode, struct file *file)
+static int zr364xx_release(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct zr364xx_camera *cam;
@@ -761,14 +761,13 @@ static int zr364xx_mmap(struct file *file, struct vm_area_struct *vma)
}
-static const struct file_operations zr364xx_fops = {
+static const struct v4l2_file_operations zr364xx_fops = {
.owner = THIS_MODULE,
.open = zr364xx_open,
.release = zr364xx_release,
.read = zr364xx_read,
.mmap = zr364xx_mmap,
.ioctl = video_ioctl2,
- .llseek = no_llseek,
};
static const struct v4l2_ioctl_ops zr364xx_ioctl_ops = {
@@ -894,7 +893,6 @@ static void zr364xx_disconnect(struct usb_interface *intf)
{
struct zr364xx_camera *cam = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
- dev_set_drvdata(&intf->dev, NULL);
dev_info(&intf->dev, DRIVER_DESC " webcam unplugged\n");
if (cam->vdev)
video_unregister_device(cam->vdev);
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index cea46906408e..a5b448ea4eab 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -385,8 +385,7 @@ static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)
if (card) {
card->host = host;
- snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
- "%s", host->dev.bus_id);
+ dev_set_name(&card->dev, "%s", dev_name(&host->dev));
card->dev.parent = &host->dev;
card->dev.bus = &memstick_bus_type;
card->dev.release = memstick_free_card;
@@ -519,7 +518,7 @@ int memstick_add_host(struct memstick_host *host)
if (rc)
return rc;
- snprintf(host->dev.bus_id, BUS_ID_SIZE, "memstick%u", host->id);
+ dev_set_name(&host->dev, "memstick%u", host->id);
rc = device_add(&host->dev);
if (rc) {
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index 7911151e56a3..de143deb06f0 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -52,14 +52,14 @@ struct mspro_sys_attr {
};
struct mspro_attr_entry {
- unsigned int address;
- unsigned int size;
+ __be32 address;
+ __be32 size;
unsigned char id;
unsigned char reserved[3];
} __attribute__((packed));
struct mspro_attribute {
- unsigned short signature;
+ __be16 signature;
unsigned short version;
unsigned char count;
unsigned char reserved[11];
@@ -69,28 +69,28 @@ struct mspro_attribute {
struct mspro_sys_info {
unsigned char class;
unsigned char reserved0;
- unsigned short block_size;
- unsigned short block_count;
- unsigned short user_block_count;
- unsigned short page_size;
+ __be16 block_size;
+ __be16 block_count;
+ __be16 user_block_count;
+ __be16 page_size;
unsigned char reserved1[2];
unsigned char assembly_date[8];
- unsigned int serial_number;
+ __be32 serial_number;
unsigned char assembly_maker_code;
unsigned char assembly_model_code[3];
- unsigned short memory_maker_code;
- unsigned short memory_model_code;
+ __be16 memory_maker_code;
+ __be16 memory_model_code;
unsigned char reserved2[4];
unsigned char vcc;
unsigned char vpp;
- unsigned short controller_number;
- unsigned short controller_function;
- unsigned short start_sector;
- unsigned short unit_size;
+ __be16 controller_number;
+ __be16 controller_function;
+ __be16 start_sector;
+ __be16 unit_size;
unsigned char ms_sub_class;
unsigned char reserved3[4];
unsigned char interface_type;
- unsigned short controller_code;
+ __be16 controller_code;
unsigned char format_type;
unsigned char reserved4;
unsigned char device_type;
@@ -124,11 +124,11 @@ struct mspro_specfile {
} __attribute__((packed));
struct mspro_devinfo {
- unsigned short cylinders;
- unsigned short heads;
- unsigned short bytes_per_track;
- unsigned short bytes_per_sector;
- unsigned short sectors_per_track;
+ __be16 cylinders;
+ __be16 heads;
+ __be16 bytes_per_track;
+ __be16 bytes_per_sector;
+ __be16 sectors_per_track;
unsigned char reserved[6];
} __attribute__((packed));
@@ -338,8 +338,7 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: "
"GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n",
date_tz, date_tz_f,
- be16_to_cpu(*(unsigned short *)
- &x_sys->assembly_date[1]),
+ be16_to_cpup((__be16 *)&x_sys->assembly_date[1]),
x_sys->assembly_date[3], x_sys->assembly_date[4],
x_sys->assembly_date[5], x_sys->assembly_date[6],
x_sys->assembly_date[7]);
@@ -887,14 +886,14 @@ try_again:
if (rc) {
printk(KERN_WARNING
"%s: could not switch to 4-bit mode, error %d\n",
- card->dev.bus_id, rc);
+ dev_name(&card->dev), rc);
return 0;
}
msb->system = MEMSTICK_SYS_PAR4;
host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
printk(KERN_INFO "%s: switching to 4-bit parallel mode\n",
- card->dev.bus_id);
+ dev_name(&card->dev));
if (msb->caps & MEMSTICK_CAP_PAR8) {
rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8);
@@ -905,11 +904,11 @@ try_again:
MEMSTICK_PAR8);
printk(KERN_INFO
"%s: switching to 8-bit parallel mode\n",
- card->dev.bus_id);
+ dev_name(&card->dev));
} else
printk(KERN_WARNING
"%s: could not switch to 8-bit mode, error %d\n",
- card->dev.bus_id, rc);
+ dev_name(&card->dev), rc);
}
card->next_request = h_mspro_block_req_init;
@@ -922,7 +921,7 @@ try_again:
if (rc) {
printk(KERN_WARNING
"%s: interface error, trying to fall back to serial\n",
- card->dev.bus_id);
+ dev_name(&card->dev));
msb->system = MEMSTICK_SYS_SERIAL;
host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
msleep(10);
@@ -992,14 +991,14 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
if (be16_to_cpu(attr->signature) != MSPRO_BLOCK_SIGNATURE) {
printk(KERN_ERR "%s: unrecognized device signature %x\n",
- card->dev.bus_id, be16_to_cpu(attr->signature));
+ dev_name(&card->dev), be16_to_cpu(attr->signature));
rc = -ENODEV;
goto out_free_attr;
}
if (attr->count > MSPRO_BLOCK_MAX_ATTRIBUTES) {
printk(KERN_WARNING "%s: way too many attribute entries\n",
- card->dev.bus_id);
+ dev_name(&card->dev));
attr_count = MSPRO_BLOCK_MAX_ATTRIBUTES;
} else
attr_count = attr->count;
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index d32d6ad8f3fc..03f71a431c82 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -546,7 +546,7 @@ static void tifm_ms_abort(unsigned long data)
printk(KERN_ERR
"%s : card failed to respond for a long period of time "
"(%x, %x)\n",
- host->dev->dev.bus_id, host->req ? host->req->tpc : 0,
+ dev_name(&host->dev->dev), host->req ? host->req->tpc : 0,
host->cmd_flags);
tifm_eject(host->dev);
@@ -561,7 +561,7 @@ static int tifm_ms_probe(struct tifm_dev *sock)
if (!(TIFM_SOCK_STATE_OCCUPIED
& readl(sock->addr + SOCK_PRESENT_STATE))) {
printk(KERN_WARNING "%s : card gone, unexpectedly\n",
- sock->dev.bus_id);
+ dev_name(&sock->dev));
return rc;
}
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 10b6ef758725..11c0f461320e 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -6,7 +6,7 @@
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
- * mpi.h Version: 01.05.13
+ * mpi.h Version: 01.05.16
*
* Version History
* ---------------
@@ -79,6 +79,9 @@
* 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT.
* 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT.
* 05-24-07 01.05.13 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-07-07 01.05.14 Bumped MPI_HEADER_VERSION_UNIT.
+ * 01-15-08 01.05.15 Bumped MPI_HEADER_VERSION_UNIT.
+ * 03-28-08 01.05.16 Bumped MPI_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
@@ -109,7 +112,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x10)
+#define MPI_HEADER_VERSION_UNIT (0x13)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index b2db3330c591..013c7d881948 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -6,7 +6,7 @@
* Title: MPI Config message, structures, and Pages
* Creation Date: July 27, 2000
*
- * mpi_cnfg.h Version: 01.05.15
+ * mpi_cnfg.h Version: 01.05.18
*
* Version History
* ---------------
@@ -308,6 +308,20 @@
* Expander Page 0 Flags field.
* Fixed define for
* MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
+ * 08-07-07 01.05.16 Added MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT
+ * define.
+ * Added BIOS Page 4 structure.
+ * Added MPI_RAID_PHYS_DISK1_PATH_MAX define for RAID
+ * Physcial Disk Page 1.
+ * 01-15-07 01.05.17 Added additional bit defines for ExtFlags field of
+ * Manufacturing Page 4.
+ * Added Solid State Drives Supported bit to IOC Page 6
+ * Capabilities Flags.
+ * Added new value for AccessStatus field of SAS Device
+ * Page 0 (_SATA_NEEDS_INITIALIZATION).
+ * 03-28-08 01.05.18 Defined new bits in Manufacturing Page 4 ExtFlags field
+ * to control coercion size and the mixing of SAS and SATA
+ * SSD drives.
* --------------------------------------------------------------------------
*/
@@ -686,6 +700,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
/* defines for the ExtFlags field */
+#define MPI_MANPAGE4_EXTFLAGS_MASK_COERCION_SIZE (0x0180)
+#define MPI_MANPAGE4_EXTFLAGS_SHIFT_COERCION_SIZE (7)
+#define MPI_MANPAGE4_EXTFLAGS_1GB_COERCION_SIZE (0)
+#define MPI_MANPAGE4_EXTFLAGS_128MB_COERCION_SIZE (1)
+
+#define MPI_MANPAGE4_EXTFLAGS_NO_MIX_SSD_SAS_SATA (0x0040)
+#define MPI_MANPAGE4_EXTFLAGS_MIX_SSD_AND_NON_SSD (0x0020)
+#define MPI_MANPAGE4_EXTFLAGS_DUAL_PORT_SUPPORT (0x0010)
#define MPI_MANPAGE4_EXTFLAGS_HIDE_NON_IR_METADATA (0x0008)
#define MPI_MANPAGE4_EXTFLAGS_SAS_CACHE_DISABLE (0x0004)
#define MPI_MANPAGE4_EXTFLAGS_SATA_CACHE_DISABLE (0x0002)
@@ -1159,6 +1181,8 @@ typedef struct _CONFIG_PAGE_IOC_6
/* IOC Page 6 Capabilities Flags */
+#define MPI_IOCPAGE6_CAP_FLAGS_SSD_SUPPORT (0x00000020)
+#define MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT (0x00000010)
#define MPI_IOCPAGE6_CAP_FLAGS_DISABLE_SMART_POLLING (0x00000008)
#define MPI_IOCPAGE6_CAP_FLAGS_MASK_METADATA_SIZE (0x00000006)
@@ -1428,6 +1452,15 @@ typedef struct _CONFIG_PAGE_BIOS_2
#define MPI_BIOSPAGE2_FORM_SAS_WWN (0x05)
#define MPI_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06)
+typedef struct _CONFIG_PAGE_BIOS_4
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U64 ReassignmentBaseWWID; /* 04h */
+} CONFIG_PAGE_BIOS_4, MPI_POINTER PTR_CONFIG_PAGE_BIOS_4,
+ BIOSPage4_t, MPI_POINTER pBIOSPage4_t;
+
+#define MPI_BIOSPAGE4_PAGEVERSION (0x00)
+
/****************************************************************************
* SCSI Port Config Pages
@@ -2419,6 +2452,15 @@ typedef struct _RAID_PHYS_DISK1_PATH
#define MPI_RAID_PHYSDISK1_FLAG_BROKEN (0x0002)
#define MPI_RAID_PHYSDISK1_FLAG_INVALID (0x0001)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumPhysDiskPaths at runtime.
+ */
+#ifndef MPI_RAID_PHYS_DISK1_PATH_MAX
+#define MPI_RAID_PHYS_DISK1_PATH_MAX (1)
+#endif
+
typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1
{
CONFIG_PAGE_HEADER Header; /* 00h */
@@ -2426,7 +2468,7 @@ typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1
U8 PhysDiskNum; /* 05h */
U16 Reserved2; /* 06h */
U32 Reserved1; /* 08h */
- RAID_PHYS_DISK1_PATH Path[1]; /* 0Ch */
+ RAID_PHYS_DISK1_PATH Path[MPI_RAID_PHYS_DISK1_PATH_MAX];/* 0Ch */
} CONFIG_PAGE_RAID_PHYS_DISK_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_1,
RaidPhysDiskPage1_t, MPI_POINTER pRaidPhysDiskPage1_t;
@@ -2844,6 +2886,7 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_0
#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
#define MPI_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04)
/* specific values for SATA Init failures */
#define MPI_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10)
#define MPI_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11)
diff --git a/drivers/message/fusion/lsi/mpi_fc.h b/drivers/message/fusion/lsi/mpi_fc.h
index 627acfbb8623..7d663ce76f8c 100644
--- a/drivers/message/fusion/lsi/mpi_fc.h
+++ b/drivers/message/fusion/lsi/mpi_fc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 LSI Corporation.
+ * Copyright (c) 2000-2008 LSI Corporation.
*
*
* Name: mpi_fc.h
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 3f15fcfe4a2e..693e4b511354 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -3,28 +3,28 @@
MPI Header File Change History
==============================
- Copyright (c) 2000-2007 LSI Corporation.
+ Copyright (c) 2000-2008 LSI Corporation.
---------------------------------------
- Header Set Release Version: 01.05.16
- Header Set Release Date: 05-24-07
+ Header Set Release Version: 01.05.19
+ Header Set Release Date: 03-28-08
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- mpi.h 01.05.13 01.05.12
- mpi_ioc.h 01.05.14 01.05.13
- mpi_cnfg.h 01.05.15 01.05.14
+ mpi.h 01.05.16 01.05.15
+ mpi_ioc.h 01.05.16 01.05.15
+ mpi_cnfg.h 01.05.18 01.05.17
mpi_init.h 01.05.09 01.05.09
mpi_targ.h 01.05.06 01.05.06
mpi_fc.h 01.05.01 01.05.01
mpi_lan.h 01.05.01 01.05.01
- mpi_raid.h 01.05.03 01.05.03
+ mpi_raid.h 01.05.05 01.05.05
mpi_tool.h 01.05.03 01.05.03
mpi_inb.h 01.05.01 01.05.01
- mpi_sas.h 01.05.04 01.05.04
+ mpi_sas.h 01.05.05 01.05.05
mpi_type.h 01.05.02 01.05.02
- mpi_history.txt 01.05.14 01.05.14
+ mpi_history.txt 01.05.19 01.05.18
* Date Version Description
@@ -96,6 +96,9 @@ mpi.h
* 03-27-06 01.05.11 Bumped MPI_HEADER_VERSION_UNIT.
* 10-11-06 01.05.12 Bumped MPI_HEADER_VERSION_UNIT.
* 05-24-07 01.05.13 Bumped MPI_HEADER_VERSION_UNIT.
+ * 08-07-07 01.05.14 Bumped MPI_HEADER_VERSION_UNIT.
+ * 01-15-08 01.05.15 Bumped MPI_HEADER_VERSION_UNIT.
+ * 03-28-08 01.05.16 Bumped MPI_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -127,7 +130,7 @@ mpi_ioc.h
* 08-08-01 01.02.01 Original release for v1.2 work.
* New format for FWVersion and ProductId in
* MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
- * 08-31-01 01.02.02 Added event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
+ * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
* related structure and defines.
* Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
* Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
@@ -187,7 +190,7 @@ mpi_ioc.h
* 10-11-06 01.05.12 Added MPI_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED.
* Added MaxInitiators field to PortFacts reply.
* Added SAS Device Status Change ReasonCode for
- * asynchronous notification.
+ * asynchronous notificaiton.
* Added MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE and event
* data structure.
* Added new ImageType values for FWDownload and FWUpload
@@ -199,6 +202,16 @@ mpi_ioc.h
* added _MULTI_PORT_DOMAIN.
* 05-24-07 01.05.14 Added Common Boot Block type to FWDownload Request.
* Added Common Boot Block type to FWUpload Request.
+ * 08-07-07 01.05.15 Added MPI_EVENT_SAS_INIT_RC_REMOVED define.
+ * Added MPI_EVENT_IR2_RC_DUAL_PORT_ADDED and
+ * MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED for IR2 event data.
+ * Added SASAddress field to SAS Initiator Device Table
+ * Overflow event data structure.
+ * 03-28-08 01.05.16 Added two new ReasonCode values to SAS Device Status
+ * Change Event data to indicate completion of internally
+ * generated task management.
+ * Added MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE define.
+ * Added MPI_EVENT_SAS_INIT_RC_INACCESSIBLE define.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -213,7 +226,7 @@ mpi_cnfg.h
* Added _RESPONSE_ID_MASK definition to SCSI_PORT_1
* page and updated the page version.
* Added Information field and _INFO_PARAMS_NEGOTIATED
- * definition to SCSI_DEVICE_0 page.
+ * definitionto SCSI_DEVICE_0 page.
* 06-22-00 01.00.03 Removed batch controls from LAN_0 page and updated the
* page version.
* Added BucketsRemaining to LAN_1 page, redefined the
@@ -496,6 +509,20 @@ mpi_cnfg.h
* Expander Page 0 Flags field.
* Fixed define for
* MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED.
+ * 08-07-07 01.05.16 Added MPI_IOCPAGE6_CAP_FLAGS_MULTIPORT_DRIVE_SUPPORT
+ * define.
+ * Added BIOS Page 4 structure.
+ * Added MPI_RAID_PHYS_DISK1_PATH_MAX define for RAID
+ * Physcial Disk Page 1.
+ * 01-15-07 01.05.17 Added additional bit defines for ExtFlags field of
+ * Manufacturing Page 4.
+ * Added Solid State Drives Supported bit to IOC Page 6
+ * Capabilities Flags.
+ * Added new value for AccessStatus field of SAS Device
+ * Page 0 (_SATA_NEEDS_INITIALIZATION).
+ * 03-28-08 01.05.18 Defined new bits in Manufacturing Page 4 ExtFlags field
+ * to control coercion size and the mixing of SAS and SATA
+ * SSD drives.
* --------------------------------------------------------------------------
mpi_init.h
@@ -661,6 +688,9 @@ mpi_raid.h
* _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
* 02-28-07 01.05.03 Added new RAID Action, Device FW Update Mode, and
* associated defines.
+ * 08-07-07 01.05.04 Added Disable Full Rebuild bit to the ActionDataWord
+ * for the RAID Action MPI_RAID_ACTION_DISABLE_VOLUME.
+ * 01-15-08 01.05.05 Added define for MPI_RAID_ACTION_SET_VOLUME_NAME.
* --------------------------------------------------------------------------
mpi_tool.h
@@ -694,6 +724,10 @@ mpi_sas.h
* reply.
* 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO
* Unit Control request.
+ * 01-15-08 01.05.05 Added support for MPI_SAS_OP_SET_IOC_PARAMETER,
+ * including adding IOCParameter and IOCParameter value
+ * fields to SAS IO Unit Control Request.
+ * Added MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC define.
* --------------------------------------------------------------------------
mpi_type.h
@@ -709,20 +743,20 @@ mpi_type.h
mpi_history.txt Parts list history
-Filename 01.05.15 01.05.15
----------- -------- --------
-mpi.h 01.05.12 01.05.13
-mpi_ioc.h 01.05.13 01.05.14
-mpi_cnfg.h 01.05.14 01.05.15
-mpi_init.h 01.05.09 01.05.09
-mpi_targ.h 01.05.06 01.05.06
-mpi_fc.h 01.05.01 01.05.01
-mpi_lan.h 01.05.01 01.05.01
-mpi_raid.h 01.05.03 01.05.03
-mpi_tool.h 01.05.03 01.05.03
-mpi_inb.h 01.05.01 01.05.01
-mpi_sas.h 01.05.04 01.05.04
-mpi_type.h 01.05.02 01.05.02
+Filename 01.05.19 01.05.18 01.05.17 01.05.16 01.05.15
+---------- -------- -------- -------- -------- --------
+mpi.h 01.05.16 01.05.15 01.05.14 01.05.13 01.05.12
+mpi_ioc.h 01.05.16 01.05.15 01.05.15 01.05.14 01.05.13
+mpi_cnfg.h 01.05.18 01.05.17 01.05.16 01.05.15 01.05.14
+mpi_init.h 01.05.09 01.05.09 01.05.09 01.05.09 01.05.09
+mpi_targ.h 01.05.06 01.05.06 01.05.06 01.05.06 01.05.06
+mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_raid.h 01.05.05 01.05.05 01.05.04 01.05.03 01.05.03
+mpi_tool.h 01.05.03 01.05.03 01.05.03 01.05.03 01.05.03
+mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_sas.h 01.05.05 01.05.05 01.05.04 01.05.04 01.05.04
+mpi_type.h 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
Filename 01.05.14 01.05.13 01.05.12 01.05.11 01.05.10 01.05.09
---------- -------- -------- -------- -------- -------- --------
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index a9e3693601a7..4295d062caa7 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2007 LSI Corporation.
+ * Copyright (c) 2000-2008 LSI Corporation.
*
*
* Name: mpi_init.h
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 5cbb6bd048e1..8faa4fab7b89 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2007 LSI Corporation.
+ * Copyright (c) 2000-2008 LSI Corporation.
*
*
* Name: mpi_ioc.h
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.14
+ * mpi_ioc.h Version: 01.05.16
*
* Version History
* ---------------
@@ -113,6 +113,16 @@
* added _MULTI_PORT_DOMAIN.
* 05-24-07 01.05.14 Added Common Boot Block type to FWDownload Request.
* Added Common Boot Block type to FWUpload Request.
+ * 08-07-07 01.05.15 Added MPI_EVENT_SAS_INIT_RC_REMOVED define.
+ * Added MPI_EVENT_IR2_RC_DUAL_PORT_ADDED and
+ * MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED for IR2 event data.
+ * Added SASAddress field to SAS Initiator Device Table
+ * Overflow event data structure.
+ * 03-28-08 01.05.16 Added two new ReasonCode values to SAS Device Status
+ * Change Event data to indicate completion of internally
+ * generated task management.
+ * Added MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE define.
+ * Added MPI_EVENT_SAS_INIT_RC_INACCESSIBLE define.
* --------------------------------------------------------------------------
*/
@@ -612,6 +622,8 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
#define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
+#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET (0x0E)
+#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_TASK_ABORT_INTERNAL (0x0F)
/* SCSI Event data for Queue Full event */
@@ -708,6 +720,8 @@ typedef struct _MPI_EVENT_DATA_IR2
#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05)
#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06)
#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07)
+#define MPI_EVENT_IR2_RC_DUAL_PORT_ADDED (0x08)
+#define MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED (0x09)
/* defines for logical disk states */
#define MPI_LD_STATE_OPTIMAL (0x00)
@@ -867,6 +881,7 @@ typedef struct _EVENT_DATA_DISCOVERY_ERROR
#define MPI_EVENT_DSCVRY_ERR_DS_UNSUPPORTED_DEVICE (0x00000800)
#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS (0x00001000)
#define MPI_EVENT_DSCVRY_ERR_DS_MULTI_PORT_DOMAIN (0x00002000)
+#define MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE (0x00004000)
/* SAS SMP Error Event data */
@@ -902,6 +917,8 @@ typedef struct _EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
/* defines for the ReasonCode field of the SAS Initiator Device Status Change event */
#define MPI_EVENT_SAS_INIT_RC_ADDED (0x01)
+#define MPI_EVENT_SAS_INIT_RC_REMOVED (0x02)
+#define MPI_EVENT_SAS_INIT_RC_INACCESSIBLE (0x03)
/* SAS Initiator Device Table Overflow Event data */
@@ -910,6 +927,7 @@ typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
U8 MaxInit; /* 00h */
U8 CurrentInit; /* 01h */
U16 Reserved1; /* 02h */
+ U64 SASAddress; /* 04h */
} EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
MPI_POINTER PTR_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
MpiEventDataSasInitTableOverflow_t,
diff --git a/drivers/message/fusion/lsi/mpi_lan.h b/drivers/message/fusion/lsi/mpi_lan.h
index 03253b53b785..f41fcb69b359 100644
--- a/drivers/message/fusion/lsi/mpi_lan.h
+++ b/drivers/message/fusion/lsi/mpi_lan.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 LSI Corporation.
+ * Copyright (c) 2000-2008 LSI Corporation.
*
*
* Name: mpi_lan.h
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h
index e4dafcefeecd..face6e7acc72 100644
--- a/drivers/message/fusion/lsi/mpi_log_fc.h
+++ b/drivers/message/fusion/lsi/mpi_log_fc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2001 LSI Corporation. All rights reserved.
+ * Copyright (c) 2000-2008 LSI Corporation. All rights reserved.
*
* NAME: fc_log.h
* SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
index af9da03e95e5..691620dbedd2 100644
--- a/drivers/message/fusion/lsi/mpi_log_sas.h
+++ b/drivers/message/fusion/lsi/mpi_log_sas.h
@@ -1,6 +1,6 @@
/***************************************************************************
* *
- * Copyright 2003 LSI Corporation. All rights reserved. *
+ * Copyright (c) 2000-2008 LSI Corporation. All rights reserved. *
* *
* Description *
* ------------ *
@@ -73,6 +73,8 @@
#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO (0x00070004)
#define IOP_LOGINFO_CODE_TARGET_MODE_ABORT_EXACT_IO_REQ (0x00070005)
+#define IOP_LOGINFO_CODE_LOG_TIMESTAMP_EVENT (0x00080000)
+
/****************************************************************************/
/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL */
/****************************************************************************/
@@ -92,7 +94,7 @@
#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_OPEN_TIMEOUT_EXP (0x0000000C)
#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_UNUSED_0D (0x0000000D)
#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_DVTBLE_ACCSS_FAIL (0x0000000E)
-#define PL_LOGINFO_SUB CODE_OPEN_FAIL_BAD_DEST (0x00000011)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_BAD_DEST (0x00000011)
#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RATE_NOT_SUPP (0x00000012)
#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_PROT_NOT_SUPP (0x00000013)
#define PL_LOGINFO_SUB_CODE_OPEN_FAIL_RESERVED_ABANDON0 (0x00000014)
@@ -159,10 +161,11 @@
#define PL_LOGINFO_SUB_CODE_INVALID_SGL (0x00000200)
#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH (0x00000300)
-#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */
- /* Bit 0 is Status Bit 0: FrameXferErr */
- /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */
- /* Bit 3 is Status Bit 18 WriteDataLengthGTDataLengthErr */
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR (0x00000400)
+/* Bits 0-3 encode Transport Status Register (offset 0x08) */
+/* Bit 0 is Status Bit 0: FrameXferErr */
+/* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */
+/* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */
#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW (0x00000500)
#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET (0x00000600)
@@ -177,6 +180,11 @@
#define PL_LOGINFO_SUB_CODE_DISCOVERY_REMOTE_SEP_RESET (0x00000E01)
#define PL_LOGINFO_SUB_CODE_SECOND_OPEN (0x00000F00)
#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT (0x00001000)
+#define PL_LOGINFO_SUB_CODE_BREAK_ON_SATA_CONNECTION (0x00002000)
+/* not currently used in mainline */
+#define PL_LOGINFO_SUB_CODE_BREAK_ON_STUCK_LINK (0x00003000)
+#define PL_LOGINFO_SUB_CODE_BREAK_ON_STUCK_LINK_AIP (0x00004000)
+#define PL_LOGINFO_SUB_CODE_BREAK_ON_INCOMPLETE_BREAK_RCVD (0x00005000)
#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE (0x00200000) /* Can't get SMP Frame */
#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR (0x00200010) /* Error occured on SMP Read */
@@ -243,6 +251,8 @@
#define IR_LOGINFO_VOLUME_ACTIVATE_VOLUME_FAILED (0x00010014)
/* Activation failed trying to import the volume */
#define IR_LOGINFO_VOLUME_ACTIVATING_IMPORT_VOLUME_FAILED (0x00010015)
+/* Activation failed trying to import the volume */
+#define IR_LOGINFO_VOLUME_ACTIVATING_TOO_MANY_PHYS_DISKS (0x00010016)
/* Phys Disk failed, too many phys disks */
#define IR_LOGINFO_PHYSDISK_CREATE_TOO_MANY_DISKS (0x00010020)
@@ -285,6 +295,21 @@
/* Compatibility Error : IME size limited to < 2TB */
#define IR_LOGINFO_COMPAT_ERROR_IME_VOL_NOT_CURRENTLY_SUPPORTED (0x0001003D)
+/* Device Firmware Update: DFU can only be started once */
+#define IR_LOGINFO_DEV_FW_UPDATE_ERR_DFU_IN_PROGRESS (0x00010050)
+/* Device Firmware Update: Volume must be Optimal/Active/non-Quiesced */
+#define IR_LOGINFO_DEV_FW_UPDATE_ERR_DEVICE_IN_INVALID_STATE (0x00010051)
+/* Device Firmware Update: DFU Timeout cannot be zero */
+#define IR_LOGINFO_DEV_FW_UPDATE_ERR_INVALID_TIMEOUT (0x00010052)
+/* Device Firmware Update: CREATE TIMER FAILED */
+#define IR_LOGINFO_DEV_FW_UPDATE_ERR_NO_TIMERS (0x00010053)
+/* Device Firmware Update: Failed to read SAS_IO_UNIT_PG_1 */
+#define IR_LOGINFO_DEV_FW_UPDATE_ERR_READING_CFG_PAGE (0x00010054)
+/* Device Firmware Update: Invalid SAS_IO_UNIT_PG_1 value(s) */
+#define IR_LOGINFO_DEV_FW_UPDATE_ERR_PORT_IO_TIMEOUTS_REQUIRED (0x00010055)
+/* Device Firmware Update: Unable to allocate memory for page */
+#define IR_LOGINFO_DEV_FW_UPDATE_ERR_ALLOC_CFG_PAGE (0x00010056)
+
/****************************************************************************/
/* Defines for convenience */
diff --git a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h
index 2856108421d7..add60cc85be1 100644
--- a/drivers/message/fusion/lsi/mpi_raid.h
+++ b/drivers/message/fusion/lsi/mpi_raid.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2001-2007 LSI Corporation.
+ * Copyright (c) 2001-2008 LSI Corporation.
*
*
* Name: mpi_raid.h
* Title: MPI RAID message and structures
* Creation Date: February 27, 2001
*
- * mpi_raid.h Version: 01.05.03
+ * mpi_raid.h Version: 01.05.05
*
* Version History
* ---------------
@@ -34,6 +34,9 @@
* _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
* 02-28-07 01.05.03 Added new RAID Action, Device FW Update Mode, and
* associated defines.
+ * 08-07-07 01.05.04 Added Disable Full Rebuild bit to the ActionDataWord
+ * for the RAID Action MPI_RAID_ACTION_DISABLE_VOLUME.
+ * 01-15-08 01.05.05 Added define for MPI_RAID_ACTION_SET_VOLUME_NAME.
* --------------------------------------------------------------------------
*/
@@ -93,6 +96,7 @@ typedef struct _MSG_RAID_ACTION
#define MPI_RAID_ACTION_SET_RESYNC_RATE (0x13)
#define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE (0x14)
#define MPI_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15)
+#define MPI_RAID_ACTION_SET_VOLUME_NAME (0x16)
/* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
#define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC (0x00000001)
@@ -105,6 +109,9 @@ typedef struct _MSG_RAID_ACTION
#define MPI_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000)
#define MPI_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000002)
+/* ActionDataWord defines for use with MPI_RAID_ACTION_DISABLE_VOLUME action */
+#define MPI_RAID_ACTION_ADATA_DISABLE_FULL_REBUILD (0x00000001)
+
/* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */
#define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL (0x00000001)
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index 33fca83cefc2..ab410036bbfc 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2004-2006 LSI Corporation.
+ * Copyright (c) 2004-2008 LSI Corporation.
*
*
* Name: mpi_sas.h
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: August 19, 2004
*
- * mpi_sas.h Version: 01.05.04
+ * mpi_sas.h Version: 01.05.05
*
* Version History
* ---------------
@@ -23,6 +23,10 @@
* reply.
* 10-11-06 01.05.04 Fixed the name of a define for Operation field of SAS IO
* Unit Control request.
+ * 01-15-08 01.05.05 Added support for MPI_SAS_OP_SET_IOC_PARAMETER,
+ * including adding IOCParameter and IOCParameter value
+ * fields to SAS IO Unit Control Request.
+ * Added MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC define.
* --------------------------------------------------------------------------
*/
@@ -60,6 +64,8 @@
* Values for the SAS DeviceInfo field used in SAS Device Status Change Event
* data and SAS IO Unit Configuration pages.
*/
+#define MPI_SAS_DEVICE_INFO_PRODUCT_SPECIFIC (0xF0000000)
+
#define MPI_SAS_DEVICE_INFO_SEP (0x00004000)
#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
@@ -216,7 +222,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U16 DevHandle; /* 04h */
- U8 Reserved3; /* 06h */
+ U8 IOCParameter; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U8 TargetID; /* 0Ch */
@@ -225,7 +231,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
U8 PrimFlags; /* 0Fh */
U32 Primitive; /* 10h */
U64 SASAddress; /* 14h */
- U32 Reserved4; /* 1Ch */
+ U32 IOCParameterValue; /* 1Ch */
} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
@@ -241,6 +247,8 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
#define MPI_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
#define MPI_SAS_OP_TRANSMIT_REMOVE_DEVICE (0x0D) /* obsolete name */
#define MPI_SAS_OP_REMOVE_DEVICE (0x0D)
+#define MPI_SAS_OP_SET_IOC_PARAMETER (0x0E)
+#define MPI_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80)
/* values for the PrimFlags field */
#define MPI_SAS_PRIMFLAGS_SINGLE (0x08)
@@ -256,7 +264,7 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REPLY
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
U16 DevHandle; /* 04h */
- U8 Reserved3; /* 06h */
+ U8 IOCParameter; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U16 Reserved4; /* 0Ch */
diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h
index ff8c37d3fdcb..c3dea7f6909d 100644
--- a/drivers/message/fusion/lsi/mpi_targ.h
+++ b/drivers/message/fusion/lsi/mpi_targ.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 LSI Corporation.
+ * Copyright (c) 2000-2008 LSI Corporation.
*
*
* Name: mpi_targ.h
diff --git a/drivers/message/fusion/lsi/mpi_tool.h b/drivers/message/fusion/lsi/mpi_tool.h
index 8834ae6ce0f2..53cd715aa7e4 100644
--- a/drivers/message/fusion/lsi/mpi_tool.h
+++ b/drivers/message/fusion/lsi/mpi_tool.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2005 LSI Corporation.
+ * Copyright (c) 2001-2008 LSI Corporation.
*
*
* Name: mpi_tool.h
diff --git a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h
index 08dad9c1e446..888b26dbc413 100644
--- a/drivers/message/fusion/lsi/mpi_type.h
+++ b/drivers/message/fusion/lsi/mpi_type.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2004 LSI Corporation.
+ * Copyright (c) 2000-2008 LSI Corporation.
*
*
* Name: mpi_type.h
* Title: MPI Basic type definitions
* Creation Date: June 6, 2000
*
- * mpi_type.h Version: 01.05.01
+ * mpi_type.h Version: 01.05.02
*
* Version History
* ---------------
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index c4e8b9aa3827..96ac88317b8e 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -79,9 +79,22 @@ MODULE_VERSION(my_VERSION);
/*
* cmd line parameters
*/
-static int mpt_msi_enable = -1;
-module_param(mpt_msi_enable, int, 0);
-MODULE_PARM_DESC(mpt_msi_enable, " MSI Support Enable (default=0)");
+
+static int mpt_msi_enable_spi;
+module_param(mpt_msi_enable_spi, int, 0);
+MODULE_PARM_DESC(mpt_msi_enable_spi, " Enable MSI Support for SPI \
+ controllers (default=0)");
+
+static int mpt_msi_enable_fc;
+module_param(mpt_msi_enable_fc, int, 0);
+MODULE_PARM_DESC(mpt_msi_enable_fc, " Enable MSI Support for FC \
+ controllers (default=0)");
+
+static int mpt_msi_enable_sas;
+module_param(mpt_msi_enable_sas, int, 1);
+MODULE_PARM_DESC(mpt_msi_enable_sas, " Enable MSI Support for SAS \
+ controllers (default=1)");
+
static int mpt_channel_mapping;
module_param(mpt_channel_mapping, int, 0);
@@ -91,7 +104,17 @@ static int mpt_debug_level;
static int mpt_set_debug_level(const char *val, struct kernel_param *kp);
module_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int,
&mpt_debug_level, 0600);
-MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h - (default=0)");
+MODULE_PARM_DESC(mpt_debug_level, " debug level - refer to mptdebug.h \
+ - (default=0)");
+
+int mpt_fwfault_debug;
+EXPORT_SYMBOL(mpt_fwfault_debug);
+module_param_call(mpt_fwfault_debug, param_set_int, param_get_int,
+ &mpt_fwfault_debug, 0600);
+MODULE_PARM_DESC(mpt_fwfault_debug, "Enable detection of Firmware fault"
+ " and halt Firmware on fault - (default=0)");
+
+
#ifdef MFCNT
static int mfcounter = 0;
@@ -1751,16 +1774,25 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->bus_type = SAS;
}
- if (mpt_msi_enable == -1) {
- /* Enable on SAS, disable on FC and SPI */
- if (ioc->bus_type == SAS)
- ioc->msi_enable = 1;
- else
- ioc->msi_enable = 0;
- } else
- /* follow flag: 0 - disable; 1 - enable */
- ioc->msi_enable = mpt_msi_enable;
+ switch (ioc->bus_type) {
+
+ case SAS:
+ ioc->msi_enable = mpt_msi_enable_sas;
+ break;
+
+ case SPI:
+ ioc->msi_enable = mpt_msi_enable_spi;
+ break;
+
+ case FC:
+ ioc->msi_enable = mpt_msi_enable_fc;
+ break;
+
+ default:
+ ioc->msi_enable = 0;
+ break;
+ }
if (ioc->errata_flag_1064)
pci_disable_io_access(pdev);
@@ -6313,6 +6345,33 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int sh
*size = y;
}
+
+/**
+ * mpt_halt_firmware - Halts the firmware if it is operational and panic
+ * the kernel
+ * @ioc: Pointer to MPT_ADAPTER structure
+ *
+ **/
+void
+mpt_halt_firmware(MPT_ADAPTER *ioc)
+{
+ u32 ioc_raw_state;
+
+ ioc_raw_state = mpt_GetIocState(ioc, 0);
+
+ if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) {
+ printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n",
+ ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK);
+ panic("%s: IOC Fault (%04xh)!!!\n", ioc->name,
+ ioc_raw_state & MPI_DOORBELL_DATA_MASK);
+ } else {
+ CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00);
+ panic("%s: Firmware is halted due to command timeout\n",
+ ioc->name);
+ }
+}
+EXPORT_SYMBOL(mpt_halt_firmware);
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* Reset Handling
@@ -6345,6 +6404,8 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag)
printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name);
printk("MF count 0x%x !\n", ioc->mfcnt);
#endif
+ if (mpt_fwfault_debug)
+ mpt_halt_firmware(ioc);
/* Reset the adapter. Prevent more than 1 call to
* mpt_do_ioc_recovery at any instant in time.
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index dff048cfa101..b3e981d2a506 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -922,11 +922,14 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc);
extern int mpt_findImVolumes(MPT_ADAPTER *ioc);
extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhysDiskPage0_t phys_disk);
+extern void mpt_halt_firmware(MPT_ADAPTER *ioc);
+
/*
* Public data decl's...
*/
extern struct list_head ioc_list;
+extern int mpt_fwfault_debug;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#endif /* } __KERNEL__ */
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index b89f476cd0a9..c63817117c0a 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -308,10 +308,11 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl)
{
int rc = 1;
- dctlprintk(ioctl->ioc, printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n",
- ioctl->ioc->name, ioctl->ioc->id));
if (ioctl == NULL)
return;
+ dctlprintk(ioctl->ioc,
+ printk(MYIOC_s_DEBUG_FMT ": Timeout Expired! Host %d\n",
+ ioctl->ioc->name, ioctl->ioc->id));
ioctl->wait_done = 0;
if (ioctl->reset & MPTCTL_RESET_OK)
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index a13f6eecd25b..c2804f26cb44 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -106,7 +106,6 @@ struct mpt_lan_priv {
u32 total_posted;
u32 total_received;
- struct net_device_stats stats; /* Per device statistics */
struct delayed_work post_buckets_task;
struct net_device *dev;
@@ -548,15 +547,6 @@ mpt_lan_close(struct net_device *dev)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static struct net_device_stats *
-mpt_lan_get_stats(struct net_device *dev)
-{
- struct mpt_lan_priv *priv = netdev_priv(dev);
-
- return (struct net_device_stats *) &priv->stats;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static int
mpt_lan_change_mtu(struct net_device *dev, int new_mtu)
{
@@ -594,8 +584,8 @@ mpt_lan_send_turbo(struct net_device *dev, u32 tmsg)
ctx = GET_LAN_BUFFER_CONTEXT(tmsg);
sent = priv->SendCtl[ctx].skb;
- priv->stats.tx_packets++;
- priv->stats.tx_bytes += sent->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += sent->len;
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
IOC_AND_NETDEV_NAMES_s_s(dev),
@@ -636,7 +626,7 @@ mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep)
switch (le16_to_cpu(pSendRep->IOCStatus) & MPI_IOCSTATUS_MASK) {
case MPI_IOCSTATUS_SUCCESS:
- priv->stats.tx_packets += count;
+ dev->stats.tx_packets += count;
break;
case MPI_IOCSTATUS_LAN_CANCELED:
@@ -644,13 +634,13 @@ mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep)
break;
case MPI_IOCSTATUS_INVALID_SGL:
- priv->stats.tx_errors += count;
+ dev->stats.tx_errors += count;
printk (KERN_ERR MYNAM ": %s/%s: ERROR - Invalid SGL sent to IOC!\n",
IOC_AND_NETDEV_NAMES_s_s(dev));
goto out;
default:
- priv->stats.tx_errors += count;
+ dev->stats.tx_errors += count;
break;
}
@@ -661,7 +651,7 @@ mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep)
ctx = GET_LAN_BUFFER_CONTEXT(le32_to_cpu(*pContext));
sent = priv->SendCtl[ctx].skb;
- priv->stats.tx_bytes += sent->len;
+ dev->stats.tx_bytes += sent->len;
dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n",
IOC_AND_NETDEV_NAMES_s_s(dev),
@@ -842,8 +832,8 @@ mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb)
"delivered to upper level.\n",
IOC_AND_NETDEV_NAMES_s_s(dev), skb->len));
- priv->stats.rx_bytes += skb->len;
- priv->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ dev->stats.rx_packets++;
skb->dev = dev;
netif_rx(skb);
@@ -1308,6 +1298,14 @@ mpt_lan_post_receive_buckets_work(struct work_struct *work)
post_buckets_task.work));
}
+static const struct net_device_ops mpt_netdev_ops = {
+ .ndo_open = mpt_lan_open,
+ .ndo_stop = mpt_lan_close,
+ .ndo_start_xmit = mpt_lan_sdu_send,
+ .ndo_change_mtu = mpt_lan_change_mtu,
+ .ndo_tx_timeout = mpt_lan_tx_timeout,
+};
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
static struct net_device *
mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
@@ -1372,15 +1370,7 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
priv->tx_max_out = (tx_max_out_p <= MPT_TX_MAX_OUT_LIM) ?
tx_max_out_p : MPT_TX_MAX_OUT_LIM;
- dev->open = mpt_lan_open;
- dev->stop = mpt_lan_close;
- dev->get_stats = mpt_lan_get_stats;
- dev->set_multicast_list = NULL;
- dev->change_mtu = mpt_lan_change_mtu;
- dev->hard_start_xmit = mpt_lan_sdu_send;
-
-/* Not in 2.3.42. Need 2.3.45+ */
- dev->tx_timeout = mpt_lan_tx_timeout;
+ dev->netdev_ops = &mpt_netdev_ops;
dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT;
dlprintk((KERN_INFO MYNAM ": Finished registering dev "
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index ee090413e598..e62c6bc4ad33 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1846,6 +1846,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
if (hd->timeouts < -1)
hd->timeouts++;
+ if (mpt_fwfault_debug)
+ mpt_halt_firmware(ioc);
+
/* Most important! Set TaskMsgContext to SCpnt's MsgContext!
* (the IO to be ABORT'd)
*
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 54c2e9ae23e5..0ee4264f5db7 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -52,7 +52,6 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
/**
* i2o_device_claim - claim a device for use by an OSM
* @dev: I2O device to claim
- * @drv: I2O driver which wants to claim the device
*
* Do the leg work to assign a device to a given OSM. If the claim succeeds,
* the owner is the primary. If the attempt fails a negative errno code
@@ -80,7 +79,6 @@ int i2o_device_claim(struct i2o_device *dev)
/**
* i2o_device_claim_release - release a device that the OSM is using
* @dev: device to release
- * @drv: driver which claimed the device
*
* Drop a claim by an OSM on a given I2O device.
*
@@ -134,7 +132,7 @@ static void i2o_device_release(struct device *dev)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
- pr_debug("i2o: device %s released\n", dev->bus_id);
+ pr_debug("i2o: device %s released\n", dev_name(dev));
kfree(i2o_dev);
}
@@ -229,8 +227,8 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
i2o_dev->lct_data = *entry;
- snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit,
- i2o_dev->lct_data.tid);
+ dev_set_name(&i2o_dev->device, "%d:%03x", c->unit,
+ i2o_dev->lct_data.tid);
i2o_dev->iop = c;
i2o_dev->device.parent = &c->device;
@@ -281,7 +279,7 @@ static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
i2o_driver_notify_device_add_all(i2o_dev);
- pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id);
+ pr_debug("i2o: device %s added\n", dev_name(&i2o_dev->device));
return 0;
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index e0d474b17433..a0421efe04ca 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -173,7 +173,6 @@ void i2o_driver_unregister(struct i2o_driver *drv)
* i2o_driver_dispatch - dispatch an I2O reply message
* @c: I2O controller of the message
* @m: I2O message number
- * @msg: I2O message to be delivered
*
* The reply is delivered to the driver from which the original message
* was. This function is only called from interrupt context.
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 56faef1a1d55..06c655c55587 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -19,7 +19,7 @@
* Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
* Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- * Alan Cox <alan@redhat.com>:
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>:
* Ported to Linux 2.5.
* Markus Lidel <Markus.Lidel@shadowconnect.com>:
* Minor fixes for 2.6.
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index f3384c32b9a1..efba7021948a 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -19,7 +19,7 @@
* Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
* Deepak Saxena (11/18/1999):
* Added event managmenet support
- * Alan Cox <alan@redhat.com>:
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>:
* 2.4 rewrite ported to 2.5
* Markus Lidel <Markus.Lidel@shadowconnect.com>:
* Added pass-thru support for Adaptec's raidutils
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index 54a3016ff45d..9a36b5a7de57 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -1300,7 +1300,7 @@ static int i2o_seq_show_dev_name(struct seq_file *seq, void *v)
{
struct i2o_device *d = (struct i2o_device *)seq->private;
- seq_printf(seq, "%s\n", d->device.bus_id);
+ seq_printf(seq, "%s\n", dev_name(&d->device));
return 0;
}
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 1bcdbbb9e7d3..3d45817e6dcd 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -390,7 +390,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
* @i2o_dev: the I2O device which was added
*
* If a I2O device is added we catch the notification, because I2O classes
- * other then SCSI peripheral will not be received through
+ * other than SCSI peripheral will not be received through
* i2o_scsi_probe().
*/
static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 6e53a30bfd38..27cf4af0e13d 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -19,7 +19,7 @@
* Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
* Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- * Alan Cox <alan@redhat.com>:
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>:
* Ported to Linux 2.5.
* Markus Lidel <Markus.Lidel@shadowconnect.com>:
* Minor fixes for 2.6.
@@ -1072,7 +1072,7 @@ struct i2o_controller *i2o_iop_alloc(void)
c->device.release = &i2o_iop_release;
- snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
+ dev_set_name(&c->device, "iop%d", c->unit);
#if BITS_PER_LONG == 64
spin_lock_init(&c->context_list_lock);
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index 610ef1204e68..25d6f2341983 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -19,7 +19,7 @@
* Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
* Deepak Saxena <deepak@plexity.net>
* Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- * Alan Cox <alan@redhat.com>:
+ * Alan Cox <alan@lxorguk.ukuu.org.uk>:
* Ported to Linux 2.5.
* Markus Lidel <Markus.Lidel@shadowconnect.com>:
* Minor fixes for 2.6.
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 257277394f8c..06a2b0f7737c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -34,6 +34,14 @@ config MFD_ASIC3
This driver supports the ASIC3 multifunction chip found on many
PDAs (mainly iPAQ and HTC based ones)
+config MFD_DM355EVM_MSP
+ bool "DaVinci DM355 EVM microcontroller"
+ depends on I2C && MACH_DAVINCI_DM355_EVM
+ help
+ This driver supports the MSP430 microcontroller used on these
+ boards. MSP430 firmware manages resets and power sequencing,
+ inputs from buttons and the IR remote, LEDs, an RTC, and more.
+
config HTC_EGPIO
bool "HTC EGPIO support"
depends on GENERIC_HARDIRQS && GPIOLIB && ARM
@@ -61,9 +69,32 @@ config UCB1400_CORE
To compile this driver as a module, choose M here: the
module will be called ucb1400_core.
+config TPS65010
+ tristate "TPS6501x Power Management chips"
+ depends on I2C && GPIOLIB
+ default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+ help
+ If you say yes here you get support for the TPS6501x series of
+ Power Management chips. These include voltage regulators,
+ lithium ion/polymer battery charging, and other features that
+ are often used in portable devices like cell phones and cameras.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps65010.
+
+config MENELAUS
+ bool "Texas Instruments TWL92330/Menelaus PM chip"
+ depends on I2C=y && ARCH_OMAP24XX
+ help
+ If you say yes here you get support for the Texas Instruments
+ TWL92330/Menelaus Power Management chip. This include voltage
+ regulators, Dual slot memory card tranceivers, real-time clock
+ and other features that are often used in portable devices like
+ cell phones and PDAs.
+
config TWL4030_CORE
bool "Texas Instruments TWL4030/TPS659x0 Support"
- depends on I2C=y && GENERIC_HARDIRQS && (ARCH_OMAP2 || ARCH_OMAP3)
+ depends on I2C=y && GENERIC_HARDIRQS
help
Say yes here if you have TWL4030 family chip on your board.
This core driver provides register access and IRQ handling
@@ -116,6 +147,7 @@ config PMIC_DA903X
config MFD_WM8400
tristate "Support Wolfson Microelectronics WM8400"
+ select MFD_CORE
depends on I2C
help
Support for the Wolfson Microelecronics WM8400 PMIC and audio
@@ -142,6 +174,38 @@ config MFD_WM8350_CONFIG_MODE_3
bool
depends on MFD_WM8350
+config MFD_WM8351_CONFIG_MODE_0
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8351_CONFIG_MODE_1
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8351_CONFIG_MODE_2
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8351_CONFIG_MODE_3
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_0
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_1
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_2
+ bool
+ depends on MFD_WM8350
+
+config MFD_WM8352_CONFIG_MODE_3
+ bool
+ depends on MFD_WM8350
+
config MFD_WM8350_I2C
tristate "Support Wolfson Microelectronics WM8350 with I2C"
select MFD_WM8350
@@ -153,6 +217,29 @@ config MFD_WM8350_I2C
I2C as the control interface. Additional options must be
selected to enable support for the functionality of the chip.
+config MFD_PCF50633
+ tristate "Support for NXP PCF50633"
+ depends on I2C
+ help
+ Say yes here if you have NXP PCF50633 chip on your board.
+ This core driver provides register access and IRQ handling
+ facilities, and registers devices for the various functions
+ so that function-specific drivers can bind to them.
+
+config PCF50633_ADC
+ tristate "Support for NXP PCF50633 ADC"
+ depends on MFD_PCF50633
+ help
+ Say yes here if you want to include support for ADC in the
+ NXP PCF50633 chip.
+
+config PCF50633_GPIO
+ tristate "Support for NXP PCF50633 GPIO"
+ depends on MFD_PCF50633
+ help
+ Say yes here if you want to include support GPIO for pins on
+ the PCF50633 chip.
+
endmenu
menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 9a5ad8af9116..3afb5192e4da 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -8,6 +8,8 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
+obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
+
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
@@ -17,6 +19,9 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
+obj-$(CONFIG_TPS65010) += tps65010.o
+obj-$(CONFIG_MENELAUS) += menelaus.o
+
obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o
obj-$(CONFIG_MFD_CORE) += mfd-core.o
@@ -31,4 +36,8 @@ obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
endif
obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
-obj-$(CONFIG_PMIC_DA903X) += da903x.o \ No newline at end of file
+obj-$(CONFIG_PMIC_DA903X) += da903x.o
+
+obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o
+obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
+obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o \ No newline at end of file
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c
index 0b5bd85dfcec..99f8dcfe3d98 100644
--- a/drivers/mfd/da903x.c
+++ b/drivers/mfd/da903x.c
@@ -151,12 +151,24 @@ int da903x_write(struct device *dev, int reg, uint8_t val)
}
EXPORT_SYMBOL_GPL(da903x_write);
+int da903x_writes(struct device *dev, int reg, int len, uint8_t *val)
+{
+ return __da903x_writes(to_i2c_client(dev), reg, len, val);
+}
+EXPORT_SYMBOL_GPL(da903x_writes);
+
int da903x_read(struct device *dev, int reg, uint8_t *val)
{
return __da903x_read(to_i2c_client(dev), reg, val);
}
EXPORT_SYMBOL_GPL(da903x_read);
+int da903x_reads(struct device *dev, int reg, int len, uint8_t *val)
+{
+ return __da903x_reads(to_i2c_client(dev), reg, len, val);
+}
+EXPORT_SYMBOL_GPL(da903x_reads);
+
int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
{
struct da903x_chip *chip = dev_get_drvdata(dev);
@@ -435,13 +447,13 @@ static const struct i2c_device_id da903x_id_table[] = {
};
MODULE_DEVICE_TABLE(i2c, da903x_id_table);
-static int __devexit __remove_subdev(struct device *dev, void *unused)
+static int __remove_subdev(struct device *dev, void *unused)
{
platform_device_unregister(to_platform_device(dev));
return 0;
}
-static int __devexit da903x_remove_subdevs(struct da903x_chip *chip)
+static int da903x_remove_subdevs(struct da903x_chip *chip)
{
return device_for_each_child(chip->dev, NULL, __remove_subdev);
}
diff --git a/drivers/mfd/dm355evm_msp.c b/drivers/mfd/dm355evm_msp.c
new file mode 100644
index 000000000000..7ac12cb0be4a
--- /dev/null
+++ b/drivers/mfd/dm355evm_msp.c
@@ -0,0 +1,430 @@
+/*
+ * dm355evm_msp.c - driver for MSP430 firmware on DM355EVM board
+ *
+ * Copyright (C) 2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/i2c.h>
+#include <linux/i2c/dm355evm_msp.h>
+
+
+/*
+ * The DM355 is a DaVinci chip with video support but no C64+ DSP. Its
+ * EVM board has an MSP430 programmed with firmware for various board
+ * support functions. This driver exposes some of them directly, and
+ * supports other drivers (e.g. RTC, input) for more complex access.
+ *
+ * Because this firmware is entirely board-specific, this file embeds
+ * knowledge that would be passed as platform_data in a generic driver.
+ *
+ * This driver was tested with firmware revision A4.
+ */
+
+#if defined(CONFIG_KEYBOARD_DM355EVM) \
+ || defined(CONFIG_KEYBOARD_DM355EVM_MODULE)
+#define msp_has_keyboard() true
+#else
+#define msp_has_keyboard() false
+#endif
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#define msp_has_leds() true
+#else
+#define msp_has_leds() false
+#endif
+
+#if defined(CONFIG_RTC_DRV_DM355EVM) || defined(CONFIG_RTC_DRV_DM355EVM_MODULE)
+#define msp_has_rtc() true
+#else
+#define msp_has_rtc() false
+#endif
+
+#if defined(CONFIG_VIDEO_TVP514X) || defined(CONFIG_VIDEO_TVP514X_MODULE)
+#define msp_has_tvp() true
+#else
+#define msp_has_tvp() false
+#endif
+
+
+/*----------------------------------------------------------------------*/
+
+/* REVISIT for paranoia's sake, retry reads/writes on error */
+
+static struct i2c_client *msp430;
+
+/**
+ * dm355evm_msp_write - Writes a register in dm355evm_msp
+ * @value: the value to be written
+ * @reg: register address
+ *
+ * Returns result of operation - 0 is success, else negative errno
+ */
+int dm355evm_msp_write(u8 value, u8 reg)
+{
+ return i2c_smbus_write_byte_data(msp430, reg, value);
+}
+EXPORT_SYMBOL(dm355evm_msp_write);
+
+/**
+ * dm355evm_msp_read - Reads a register from dm355evm_msp
+ * @reg: register address
+ *
+ * Returns result of operation - value, or negative errno
+ */
+int dm355evm_msp_read(u8 reg)
+{
+ return i2c_smbus_read_byte_data(msp430, reg);
+}
+EXPORT_SYMBOL(dm355evm_msp_read);
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Many of the msp430 pins are just used as fixed-direction GPIOs.
+ * We could export a few more of them this way, if we wanted.
+ */
+#define MSP_GPIO(bit,reg) ((DM355EVM_MSP_ ## reg) << 3 | (bit))
+
+static const u8 msp_gpios[] = {
+ /* eight leds */
+ MSP_GPIO(0, LED), MSP_GPIO(1, LED),
+ MSP_GPIO(2, LED), MSP_GPIO(3, LED),
+ MSP_GPIO(4, LED), MSP_GPIO(5, LED),
+ MSP_GPIO(6, LED), MSP_GPIO(7, LED),
+ /* SW6 and the NTSC/nPAL jumper */
+ MSP_GPIO(0, SWITCH1), MSP_GPIO(1, SWITCH1),
+ MSP_GPIO(2, SWITCH1), MSP_GPIO(3, SWITCH1),
+ MSP_GPIO(4, SWITCH1),
+ /* switches on MMC/SD sockets */
+ MSP_GPIO(1, SDMMC), MSP_GPIO(2, SDMMC), /* mmc0 WP, nCD */
+ MSP_GPIO(3, SDMMC), MSP_GPIO(4, SDMMC), /* mmc1 WP, nCD */
+};
+
+#define MSP_GPIO_REG(offset) (msp_gpios[(offset)] >> 3)
+#define MSP_GPIO_MASK(offset) BIT(msp_gpios[(offset)] & 0x07)
+
+static int msp_gpio_in(struct gpio_chip *chip, unsigned offset)
+{
+ switch (MSP_GPIO_REG(offset)) {
+ case DM355EVM_MSP_SWITCH1:
+ case DM355EVM_MSP_SWITCH2:
+ case DM355EVM_MSP_SDMMC:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static u8 msp_led_cache;
+
+static int msp_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ int reg, status;
+
+ reg = MSP_GPIO_REG(offset);
+ status = dm355evm_msp_read(reg);
+ if (status < 0)
+ return status;
+ if (reg == DM355EVM_MSP_LED)
+ msp_led_cache = status;
+ return status & MSP_GPIO_MASK(offset);
+}
+
+static int msp_gpio_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+ int mask, bits;
+
+ /* NOTE: there are some other signals that could be
+ * packaged as output GPIOs, but they aren't as useful
+ * as the LEDs ... so for now we don't.
+ */
+ if (MSP_GPIO_REG(offset) != DM355EVM_MSP_LED)
+ return -EINVAL;
+
+ mask = MSP_GPIO_MASK(offset);
+ bits = msp_led_cache;
+
+ bits &= ~mask;
+ if (value)
+ bits |= mask;
+ msp_led_cache = bits;
+
+ return dm355evm_msp_write(bits, DM355EVM_MSP_LED);
+}
+
+static void msp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ msp_gpio_out(chip, offset, value);
+}
+
+static struct gpio_chip dm355evm_msp_gpio = {
+ .label = "dm355evm_msp",
+ .owner = THIS_MODULE,
+ .direction_input = msp_gpio_in,
+ .get = msp_gpio_get,
+ .direction_output = msp_gpio_out,
+ .set = msp_gpio_set,
+ .base = -EINVAL, /* dynamic assignment */
+ .ngpio = ARRAY_SIZE(msp_gpios),
+ .can_sleep = true,
+};
+
+/*----------------------------------------------------------------------*/
+
+static struct device *add_child(struct i2c_client *client, const char *name,
+ void *pdata, unsigned pdata_len,
+ bool can_wakeup, int irq)
+{
+ struct platform_device *pdev;
+ int status;
+
+ pdev = platform_device_alloc(name, -1);
+ if (!pdev) {
+ dev_dbg(&client->dev, "can't alloc dev\n");
+ status = -ENOMEM;
+ goto err;
+ }
+
+ device_init_wakeup(&pdev->dev, can_wakeup);
+ pdev->dev.parent = &client->dev;
+
+ if (pdata) {
+ status = platform_device_add_data(pdev, pdata, pdata_len);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add platform_data\n");
+ goto err;
+ }
+ }
+
+ if (irq) {
+ struct resource r = {
+ .start = irq,
+ .flags = IORESOURCE_IRQ,
+ };
+
+ status = platform_device_add_resources(pdev, &r, 1);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add irq\n");
+ goto err;
+ }
+ }
+
+ status = platform_device_add(pdev);
+
+err:
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_err(&client->dev, "can't add %s dev\n", name);
+ return ERR_PTR(status);
+ }
+ return &pdev->dev;
+}
+
+static int add_children(struct i2c_client *client)
+{
+ static const struct {
+ int offset;
+ char *label;
+ } config_inputs[] = {
+ /* 8 == right after the LEDs */
+ { 8 + 0, "sw6_1", },
+ { 8 + 1, "sw6_2", },
+ { 8 + 2, "sw6_3", },
+ { 8 + 3, "sw6_4", },
+ { 8 + 4, "NTSC/nPAL", },
+ };
+
+ struct device *child;
+ int status;
+ int i;
+
+ /* GPIO-ish stuff */
+ dm355evm_msp_gpio.dev = &client->dev;
+ status = gpiochip_add(&dm355evm_msp_gpio);
+ if (status < 0)
+ return status;
+
+ /* LED output */
+ if (msp_has_leds()) {
+#define GPIO_LED(l) .name = l, .active_low = true
+ static struct gpio_led evm_leds[] = {
+ { GPIO_LED("dm355evm::ds14"),
+ .default_trigger = "heartbeat", },
+ { GPIO_LED("dm355evm::ds15"),
+ .default_trigger = "mmc0", },
+ { GPIO_LED("dm355evm::ds16"),
+ /* could also be a CE-ATA drive */
+ .default_trigger = "mmc1", },
+ { GPIO_LED("dm355evm::ds17"),
+ .default_trigger = "nand-disk", },
+ { GPIO_LED("dm355evm::ds18"), },
+ { GPIO_LED("dm355evm::ds19"), },
+ { GPIO_LED("dm355evm::ds20"), },
+ { GPIO_LED("dm355evm::ds21"), },
+ };
+#undef GPIO_LED
+
+ struct gpio_led_platform_data evm_led_data = {
+ .num_leds = ARRAY_SIZE(evm_leds),
+ .leds = evm_leds,
+ };
+
+ for (i = 0; i < ARRAY_SIZE(evm_leds); i++)
+ evm_leds[i].gpio = i + dm355evm_msp_gpio.base;
+
+ /* NOTE: these are the only fully programmable LEDs
+ * on the board, since GPIO-61/ds22 (and many signals
+ * going to DC7) must be used for AEMIF address lines
+ * unless the top 1 GB of NAND is unused...
+ */
+ child = add_child(client, "leds-gpio",
+ &evm_led_data, sizeof(evm_led_data),
+ false, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ /* configuration inputs */
+ for (i = 0; i < ARRAY_SIZE(config_inputs); i++) {
+ int gpio = dm355evm_msp_gpio.base + config_inputs[i].offset;
+
+ gpio_request(gpio, config_inputs[i].label);
+ gpio_direction_input(gpio);
+
+ /* make it easy for userspace to see these */
+ gpio_export(gpio, false);
+ }
+
+ /* MMC/SD inputs -- right after the last config input */
+ if (client->dev.platform_data) {
+ void (*mmcsd_setup)(unsigned) = client->dev.platform_data;
+
+ mmcsd_setup(dm355evm_msp_gpio.base + 8 + 5);
+ }
+
+ /* RTC is a 32 bit counter, no alarm */
+ if (msp_has_rtc()) {
+ child = add_child(client, "rtc-dm355evm",
+ NULL, 0, false, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ /* input from buttons and IR remote (uses the IRQ) */
+ if (msp_has_keyboard()) {
+ child = add_child(client, "dm355evm_keys",
+ NULL, 0, true, client->irq);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------*/
+
+static void dm355evm_command(unsigned command)
+{
+ int status;
+
+ status = dm355evm_msp_write(command, DM355EVM_MSP_COMMAND);
+ if (status < 0)
+ dev_err(&msp430->dev, "command %d failure %d\n",
+ command, status);
+}
+
+static void dm355evm_power_off(void)
+{
+ dm355evm_command(MSP_COMMAND_POWEROFF);
+}
+
+static int dm355evm_msp_remove(struct i2c_client *client)
+{
+ pm_power_off = NULL;
+ msp430 = NULL;
+ return 0;
+}
+
+static int
+dm355evm_msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int status;
+ const char *video = msp_has_tvp() ? "TVP5146" : "imager";
+
+ if (msp430)
+ return -EBUSY;
+ msp430 = client;
+
+ /* display revision status; doubles as sanity check */
+ status = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
+ if (status < 0)
+ goto fail;
+ dev_info(&client->dev, "firmware v.%02X, %s as video-in\n",
+ status, video);
+
+ /* mux video input: either tvp5146 or some external imager */
+ status = dm355evm_msp_write(msp_has_tvp() ? 0 : MSP_VIDEO_IMAGER,
+ DM355EVM_MSP_VIDEO_IN);
+ if (status < 0)
+ dev_warn(&client->dev, "error %d muxing %s as video-in\n",
+ status, video);
+
+ /* init LED cache, and turn off the LEDs */
+ msp_led_cache = 0xff;
+ dm355evm_msp_write(msp_led_cache, DM355EVM_MSP_LED);
+
+ /* export capabilities we support */
+ status = add_children(client);
+ if (status < 0)
+ goto fail;
+
+ /* PM hookup */
+ pm_power_off = dm355evm_power_off;
+
+ return 0;
+
+fail:
+ /* FIXME remove children ... */
+ dm355evm_msp_remove(client);
+ return status;
+}
+
+static const struct i2c_device_id dm355evm_msp_ids[] = {
+ { "dm355evm_msp", 0 },
+ { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(i2c, dm355evm_msp_ids);
+
+static struct i2c_driver dm355evm_msp_driver = {
+ .driver.name = "dm355evm_msp",
+ .id_table = dm355evm_msp_ids,
+ .probe = dm355evm_msp_probe,
+ .remove = dm355evm_msp_remove,
+};
+
+static int __init dm355evm_msp_init(void)
+{
+ return i2c_add_driver(&dm355evm_msp_driver);
+}
+subsys_initcall(dm355evm_msp_init);
+
+static void __exit dm355evm_msp_exit(void)
+{
+ i2c_del_driver(&dm355evm_msp_driver);
+}
+module_exit(dm355evm_msp_exit);
+
+MODULE_DESCRIPTION("Interface to MSP430 firmware on DM355EVM");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/menelaus.c b/drivers/mfd/menelaus.c
index 4b364bae6b3e..4b364bae6b3e 100644
--- a/drivers/i2c/chips/menelaus.c
+++ b/drivers/mfd/menelaus.c
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 6c0d1bec4b76..54ddf3772e0c 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -34,6 +34,7 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_device;
pdev->dev.parent = parent;
+ platform_set_drvdata(pdev, cell->driver_data);
ret = platform_device_add_data(pdev,
cell->platform_data, cell->data_size);
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
new file mode 100644
index 000000000000..c2d05becfa97
--- /dev/null
+++ b/drivers/mfd/pcf50633-adc.c
@@ -0,0 +1,277 @@
+/* NXP PCF50633 ADC Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * 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.
+ *
+ * NOTE: This driver does not yet support subtractive ADC mode, which means
+ * you can do only one measurement per read request.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/adc.h>
+
+struct pcf50633_adc_request {
+ int mux;
+ int avg;
+ int result;
+ void (*callback)(struct pcf50633 *, void *, int);
+ void *callback_param;
+
+ /* Used in case of sync requests */
+ struct completion completion;
+
+};
+
+#define PCF50633_MAX_ADC_FIFO_DEPTH 8
+
+struct pcf50633_adc {
+ struct pcf50633 *pcf;
+
+ /* Private stuff */
+ struct pcf50633_adc_request *queue[PCF50633_MAX_ADC_FIFO_DEPTH];
+ int queue_head;
+ int queue_tail;
+ struct mutex queue_mutex;
+};
+
+static inline struct pcf50633_adc *__to_adc(struct pcf50633 *pcf)
+{
+ return platform_get_drvdata(pcf->adc_pdev);
+}
+
+static void adc_setup(struct pcf50633 *pcf, int channel, int avg)
+{
+ channel &= PCF50633_ADCC1_ADCMUX_MASK;
+
+ /* kill ratiometric, but enable ACCSW biasing */
+ pcf50633_reg_write(pcf, PCF50633_REG_ADCC2, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_ADCC3, 0x01);
+
+ /* start ADC conversion on selected channel */
+ pcf50633_reg_write(pcf, PCF50633_REG_ADCC1, channel | avg |
+ PCF50633_ADCC1_ADCSTART | PCF50633_ADCC1_RES_10BIT);
+}
+
+static void trigger_next_adc_job_if_any(struct pcf50633 *pcf)
+{
+ struct pcf50633_adc *adc = __to_adc(pcf);
+ int head;
+
+ mutex_lock(&adc->queue_mutex);
+
+ head = adc->queue_head;
+
+ if (!adc->queue[head]) {
+ mutex_unlock(&adc->queue_mutex);
+ return;
+ }
+ mutex_unlock(&adc->queue_mutex);
+
+ adc_setup(pcf, adc->queue[head]->mux, adc->queue[head]->avg);
+}
+
+static int
+adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req)
+{
+ struct pcf50633_adc *adc = __to_adc(pcf);
+ int head, tail;
+
+ mutex_lock(&adc->queue_mutex);
+
+ head = adc->queue_head;
+ tail = adc->queue_tail;
+
+ if (adc->queue[tail]) {
+ mutex_unlock(&adc->queue_mutex);
+ return -EBUSY;
+ }
+
+ adc->queue[tail] = req;
+ adc->queue_tail = (tail + 1) & (PCF50633_MAX_ADC_FIFO_DEPTH - 1);
+
+ mutex_unlock(&adc->queue_mutex);
+
+ trigger_next_adc_job_if_any(pcf);
+
+ return 0;
+}
+
+static void
+pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result)
+{
+ struct pcf50633_adc_request *req = param;
+
+ req->result = result;
+ complete(&req->completion);
+}
+
+int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
+{
+ struct pcf50633_adc_request *req;
+
+ /* req is freed when the result is ready, in interrupt handler */
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->mux = mux;
+ req->avg = avg;
+ req->callback = pcf50633_adc_sync_read_callback;
+ req->callback_param = req;
+
+ init_completion(&req->completion);
+ adc_enqueue_request(pcf, req);
+ wait_for_completion(&req->completion);
+
+ return req->result;
+}
+EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
+
+int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg,
+ void (*callback)(struct pcf50633 *, void *, int),
+ void *callback_param)
+{
+ struct pcf50633_adc_request *req;
+
+ /* req is freed when the result is ready, in interrupt handler */
+ req = kmalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->mux = mux;
+ req->avg = avg;
+ req->callback = callback;
+ req->callback_param = callback_param;
+
+ adc_enqueue_request(pcf, req);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcf50633_adc_async_read);
+
+static int adc_result(struct pcf50633 *pcf)
+{
+ u8 adcs1, adcs3;
+ u16 result;
+
+ adcs1 = pcf50633_reg_read(pcf, PCF50633_REG_ADCS1);
+ adcs3 = pcf50633_reg_read(pcf, PCF50633_REG_ADCS3);
+ result = (adcs1 << 2) | (adcs3 & PCF50633_ADCS3_ADCDAT1L_MASK);
+
+ dev_dbg(pcf->dev, "adc result = %d\n", result);
+
+ return result;
+}
+
+static void pcf50633_adc_irq(int irq, void *data)
+{
+ struct pcf50633_adc *adc = data;
+ struct pcf50633 *pcf = adc->pcf;
+ struct pcf50633_adc_request *req;
+ int head;
+
+ mutex_lock(&adc->queue_mutex);
+ head = adc->queue_head;
+
+ req = adc->queue[head];
+ if (WARN_ON(!req)) {
+ dev_err(pcf->dev, "pcf50633-adc irq: ADC queue empty!\n");
+ mutex_unlock(&adc->queue_mutex);
+ return;
+ }
+ adc->queue[head] = NULL;
+ adc->queue_head = (head + 1) &
+ (PCF50633_MAX_ADC_FIFO_DEPTH - 1);
+
+ mutex_unlock(&adc->queue_mutex);
+
+ req->callback(pcf, req->callback_param, adc_result(pcf));
+ kfree(req);
+
+ trigger_next_adc_job_if_any(pcf);
+}
+
+static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
+{
+ struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
+ struct pcf50633_adc *adc;
+
+ adc = kzalloc(sizeof(*adc), GFP_KERNEL);
+ if (!adc)
+ return -ENOMEM;
+
+ adc->pcf = pdata->pcf;
+ platform_set_drvdata(pdev, adc);
+
+ pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ADCRDY,
+ pcf50633_adc_irq, adc);
+
+ mutex_init(&adc->queue_mutex);
+
+ return 0;
+}
+
+static int __devexit pcf50633_adc_remove(struct platform_device *pdev)
+{
+ struct pcf50633_adc *adc = platform_get_drvdata(pdev);
+ int i, head;
+
+ pcf50633_free_irq(adc->pcf, PCF50633_IRQ_ADCRDY);
+
+ mutex_lock(&adc->queue_mutex);
+ head = adc->queue_head;
+
+ if (WARN_ON(adc->queue[head]))
+ dev_err(adc->pcf->dev,
+ "adc driver removed with request pending\n");
+
+ for (i = 0; i < PCF50633_MAX_ADC_FIFO_DEPTH; i++)
+ kfree(adc->queue[i]);
+
+ mutex_unlock(&adc->queue_mutex);
+ kfree(adc);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_adc_driver = {
+ .driver = {
+ .name = "pcf50633-adc",
+ },
+ .probe = pcf50633_adc_probe,
+ .remove = __devexit_p(pcf50633_adc_remove),
+};
+
+static int __init pcf50633_adc_init(void)
+{
+ return platform_driver_register(&pcf50633_adc_driver);
+}
+module_init(pcf50633_adc_init);
+
+static void __exit pcf50633_adc_exit(void)
+{
+ platform_driver_unregister(&pcf50633_adc_driver);
+}
+module_exit(pcf50633_adc_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 adc driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-adc");
+
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
new file mode 100644
index 000000000000..ea9488e7ad6d
--- /dev/null
+++ b/drivers/mfd/pcf50633-core.c
@@ -0,0 +1,709 @@
+/* NXP PCF50633 Power Management Unit (PMU) driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Harald Welte <laforge@openmoko.org>
+ * Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+
+#include <linux/mfd/pcf50633/core.h>
+
+/* Two MBCS registers used during cold start */
+#define PCF50633_REG_MBCS1 0x4b
+#define PCF50633_REG_MBCS2 0x4c
+#define PCF50633_MBCS1_USBPRES 0x01
+#define PCF50633_MBCS1_ADAPTPRES 0x01
+
+static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
+{
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg,
+ num, data);
+ if (ret < 0)
+ dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg);
+
+ return ret;
+}
+
+static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
+{
+ int ret;
+
+ ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg,
+ num, data);
+ if (ret < 0)
+ dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg);
+
+ return ret;
+
+}
+
+/* Read a block of upto 32 regs */
+int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
+ int nr_regs, u8 *data)
+{
+ int ret;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_read(pcf, reg, nr_regs, data);
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_read_block);
+
+/* Write a block of upto 32 regs */
+int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
+ int nr_regs, u8 *data)
+{
+ int ret;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_write(pcf, reg, nr_regs, data);
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_write_block);
+
+u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg)
+{
+ u8 val;
+
+ mutex_lock(&pcf->lock);
+ __pcf50633_read(pcf, reg, 1, &val);
+ mutex_unlock(&pcf->lock);
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_read);
+
+int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val)
+{
+ int ret;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_write(pcf, reg, 1, &val);
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_write);
+
+int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val)
+{
+ int ret;
+ u8 tmp;
+
+ val &= mask;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp &= ~mask;
+ tmp |= val;
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+
+out:
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask);
+
+int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val)
+{
+ int ret;
+ u8 tmp;
+
+ mutex_lock(&pcf->lock);
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp &= ~val;
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+
+out:
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits);
+
+/* sysfs attributes */
+static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pcf50633 *pcf = dev_get_drvdata(dev);
+ u8 dump[16];
+ int n, n1, idx = 0;
+ char *buf1 = buf;
+ static u8 address_no_read[] = { /* must be ascending */
+ PCF50633_REG_INT1,
+ PCF50633_REG_INT2,
+ PCF50633_REG_INT3,
+ PCF50633_REG_INT4,
+ PCF50633_REG_INT5,
+ 0 /* terminator */
+ };
+
+ for (n = 0; n < 256; n += sizeof(dump)) {
+ for (n1 = 0; n1 < sizeof(dump); n1++)
+ if (n == address_no_read[idx]) {
+ idx++;
+ dump[n1] = 0x00;
+ } else
+ dump[n1] = pcf50633_reg_read(pcf, n + n1);
+
+ hex_dump_to_buffer(dump, sizeof(dump), 16, 1, buf1, 128, 0);
+ buf1 += strlen(buf1);
+ *buf1++ = '\n';
+ *buf1 = '\0';
+ }
+
+ return buf1 - buf;
+}
+static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL);
+
+static ssize_t show_resume_reason(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pcf50633 *pcf = dev_get_drvdata(dev);
+ int n;
+
+ n = sprintf(buf, "%02x%02x%02x%02x%02x\n",
+ pcf->resume_reason[0],
+ pcf->resume_reason[1],
+ pcf->resume_reason[2],
+ pcf->resume_reason[3],
+ pcf->resume_reason[4]);
+
+ return n;
+}
+static DEVICE_ATTR(resume_reason, 0400, show_resume_reason, NULL);
+
+static struct attribute *pcf_sysfs_entries[] = {
+ &dev_attr_dump_regs.attr,
+ &dev_attr_resume_reason.attr,
+ NULL,
+};
+
+static struct attribute_group pcf_attr_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = pcf_sysfs_entries,
+};
+
+int pcf50633_register_irq(struct pcf50633 *pcf, int irq,
+ void (*handler) (int, void *), void *data)
+{
+ if (irq < 0 || irq > PCF50633_NUM_IRQ || !handler)
+ return -EINVAL;
+
+ if (WARN_ON(pcf->irq_handler[irq].handler))
+ return -EBUSY;
+
+ mutex_lock(&pcf->lock);
+ pcf->irq_handler[irq].handler = handler;
+ pcf->irq_handler[irq].data = data;
+ mutex_unlock(&pcf->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcf50633_register_irq);
+
+int pcf50633_free_irq(struct pcf50633 *pcf, int irq)
+{
+ if (irq < 0 || irq > PCF50633_NUM_IRQ)
+ return -EINVAL;
+
+ mutex_lock(&pcf->lock);
+ pcf->irq_handler[irq].handler = NULL;
+ mutex_unlock(&pcf->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcf50633_free_irq);
+
+static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask)
+{
+ u8 reg, bits, tmp;
+ int ret = 0, idx;
+
+ idx = irq >> 3;
+ reg = PCF50633_REG_INT1M + idx;
+ bits = 1 << (irq & 0x07);
+
+ mutex_lock(&pcf->lock);
+
+ if (mask) {
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp |= bits;
+
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ pcf->mask_regs[idx] &= ~bits;
+ pcf->mask_regs[idx] |= bits;
+ } else {
+ ret = __pcf50633_read(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ tmp &= ~bits;
+
+ ret = __pcf50633_write(pcf, reg, 1, &tmp);
+ if (ret < 0)
+ goto out;
+
+ pcf->mask_regs[idx] &= ~bits;
+ }
+out:
+ mutex_unlock(&pcf->lock);
+
+ return ret;
+}
+
+int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
+{
+ dev_info(pcf->dev, "Masking IRQ %d\n", irq);
+
+ return __pcf50633_irq_mask_set(pcf, irq, 1);
+}
+EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
+
+int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
+{
+ dev_info(pcf->dev, "Unmasking IRQ %d\n", irq);
+
+ return __pcf50633_irq_mask_set(pcf, irq, 0);
+}
+EXPORT_SYMBOL_GPL(pcf50633_irq_unmask);
+
+int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq)
+{
+ u8 reg, bits;
+
+ reg = irq >> 3;
+ bits = 1 << (irq & 0x07);
+
+ return pcf->mask_regs[reg] & bits;
+}
+EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get);
+
+static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq)
+{
+ if (pcf->irq_handler[irq].handler)
+ pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
+}
+
+/* Maximum amount of time ONKEY is held before emergency action is taken */
+#define PCF50633_ONKEY1S_TIMEOUT 8
+
+static void pcf50633_irq_worker(struct work_struct *work)
+{
+ struct pcf50633 *pcf;
+ int ret, i, j;
+ u8 pcf_int[5], chgstat;
+
+ pcf = container_of(work, struct pcf50633, irq_work);
+
+ /* Read the 5 INT regs in one transaction */
+ ret = pcf50633_read_block(pcf, PCF50633_REG_INT1,
+ ARRAY_SIZE(pcf_int), pcf_int);
+ if (ret != ARRAY_SIZE(pcf_int)) {
+ dev_err(pcf->dev, "Error reading INT registers\n");
+
+ /*
+ * If this doesn't ACK the interrupt to the chip, we'll be
+ * called once again as we're level triggered.
+ */
+ goto out;
+ }
+
+ /* We immediately read the usb and adapter status. We thus make sure
+ * only of USBINS/USBREM IRQ handlers are called */
+ if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
+ chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
+ if (chgstat & (0x3 << 4))
+ pcf_int[0] &= ~(1 << PCF50633_INT1_USBREM);
+ else
+ pcf_int[0] &= ~(1 << PCF50633_INT1_USBINS);
+ }
+
+ /* Make sure only one of ADPINS or ADPREM is set */
+ if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) {
+ chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
+ if (chgstat & (0x3 << 4))
+ pcf_int[0] &= ~(1 << PCF50633_INT1_ADPREM);
+ else
+ pcf_int[0] &= ~(1 << PCF50633_INT1_ADPINS);
+ }
+
+ dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
+ "INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
+ pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
+
+ /* Some revisions of the chip don't have a 8s standby mode on
+ * ONKEY1S press. We try to manually do it in such cases. */
+ if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) {
+ dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
+ pcf->onkey1s_held);
+ if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT)
+ if (pcf->pdata->force_shutdown)
+ pcf->pdata->force_shutdown(pcf);
+ }
+
+ if (pcf_int[2] & PCF50633_INT3_ONKEY1S) {
+ dev_info(pcf->dev, "ONKEY1S held\n");
+ pcf->onkey1s_held = 1 ;
+
+ /* Unmask IRQ_SECOND */
+ pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M,
+ PCF50633_INT1_SECOND);
+
+ /* Unmask IRQ_ONKEYR */
+ pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M,
+ PCF50633_INT2_ONKEYR);
+ }
+
+ if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) {
+ pcf->onkey1s_held = 0;
+
+ /* Mask SECOND and ONKEYR interrupts */
+ if (pcf->mask_regs[0] & PCF50633_INT1_SECOND)
+ pcf50633_reg_set_bit_mask(pcf,
+ PCF50633_REG_INT1M,
+ PCF50633_INT1_SECOND,
+ PCF50633_INT1_SECOND);
+
+ if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR)
+ pcf50633_reg_set_bit_mask(pcf,
+ PCF50633_REG_INT2M,
+ PCF50633_INT2_ONKEYR,
+ PCF50633_INT2_ONKEYR);
+ }
+
+ /* Have we just resumed ? */
+ if (pcf->is_suspended) {
+ pcf->is_suspended = 0;
+
+ /* Set the resume reason filtering out non resumers */
+ for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
+ pcf->resume_reason[i] = pcf_int[i] &
+ pcf->pdata->resumers[i];
+
+ /* Make sure we don't pass on any ONKEY events to
+ * userspace now */
+ pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
+ /* Unset masked interrupts */
+ pcf_int[i] &= ~pcf->mask_regs[i];
+
+ for (j = 0; j < 8 ; j++)
+ if (pcf_int[i] & (1 << j))
+ pcf50633_irq_call_handler(pcf, (i * 8) + j);
+ }
+
+out:
+ put_device(pcf->dev);
+ enable_irq(pcf->irq);
+}
+
+static irqreturn_t pcf50633_irq(int irq, void *data)
+{
+ struct pcf50633 *pcf = data;
+
+ dev_dbg(pcf->dev, "pcf50633_irq\n");
+
+ get_device(pcf->dev);
+ disable_irq(pcf->irq);
+ schedule_work(&pcf->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static void
+pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
+ struct platform_device **pdev)
+{
+ struct pcf50633_subdev_pdata *subdev_pdata;
+ int ret;
+
+ *pdev = platform_device_alloc(name, -1);
+ if (!*pdev) {
+ dev_err(pcf->dev, "Falied to allocate %s\n", name);
+ return;
+ }
+
+ subdev_pdata = kmalloc(sizeof(*subdev_pdata), GFP_KERNEL);
+ if (!subdev_pdata) {
+ dev_err(pcf->dev, "Error allocating subdev pdata\n");
+ platform_device_put(*pdev);
+ }
+
+ subdev_pdata->pcf = pcf;
+ platform_device_add_data(*pdev, subdev_pdata, sizeof(*subdev_pdata));
+
+ (*pdev)->dev.parent = pcf->dev;
+
+ ret = platform_device_add(*pdev);
+ if (ret) {
+ dev_err(pcf->dev, "Failed to register %s: %d\n", name, ret);
+ platform_device_put(*pdev);
+ *pdev = NULL;
+ }
+}
+
+#ifdef CONFIG_PM
+static int pcf50633_suspend(struct device *dev, pm_message_t state)
+{
+ struct pcf50633 *pcf;
+ int ret = 0, i;
+ u8 res[5];
+
+ pcf = dev_get_drvdata(dev);
+
+ /* Make sure our interrupt handlers are not called
+ * henceforth */
+ disable_irq(pcf->irq);
+
+ /* Make sure that any running IRQ worker has quit */
+ cancel_work_sync(&pcf->irq_work);
+
+ /* Save the masks */
+ ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M,
+ ARRAY_SIZE(pcf->suspend_irq_masks),
+ pcf->suspend_irq_masks);
+ if (ret < 0) {
+ dev_err(pcf->dev, "error saving irq masks\n");
+ goto out;
+ }
+
+ /* Write wakeup irq masks */
+ for (i = 0; i < ARRAY_SIZE(res); i++)
+ res[i] = ~pcf->pdata->resumers[i];
+
+ ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
+ ARRAY_SIZE(res), &res[0]);
+ if (ret < 0) {
+ dev_err(pcf->dev, "error writing wakeup irq masks\n");
+ goto out;
+ }
+
+ pcf->is_suspended = 1;
+
+out:
+ return ret;
+}
+
+static int pcf50633_resume(struct device *dev)
+{
+ struct pcf50633 *pcf;
+ int ret;
+
+ pcf = dev_get_drvdata(dev);
+
+ /* Write the saved mask registers */
+ ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M,
+ ARRAY_SIZE(pcf->suspend_irq_masks),
+ pcf->suspend_irq_masks);
+ if (ret < 0)
+ dev_err(pcf->dev, "Error restoring saved suspend masks\n");
+
+ /* Restore regulators' state */
+
+
+ get_device(pcf->dev);
+
+ /*
+ * Clear any pending interrupts and set resume reason if any.
+ * This will leave with enable_irq()
+ */
+ pcf50633_irq_worker(&pcf->irq_work);
+
+ return 0;
+}
+#else
+#define pcf50633_suspend NULL
+#define pcf50633_resume NULL
+#endif
+
+static int __devinit pcf50633_probe(struct i2c_client *client,
+ const struct i2c_device_id *ids)
+{
+ struct pcf50633 *pcf;
+ struct pcf50633_platform_data *pdata = client->dev.platform_data;
+ int i, ret = 0;
+ int version, variant;
+
+ pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
+ if (!pcf)
+ return -ENOMEM;
+
+ pcf->pdata = pdata;
+
+ mutex_init(&pcf->lock);
+
+ i2c_set_clientdata(client, pcf);
+ pcf->dev = &client->dev;
+ pcf->i2c_client = client;
+ pcf->irq = client->irq;
+
+ INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
+
+ version = pcf50633_reg_read(pcf, 0);
+ variant = pcf50633_reg_read(pcf, 1);
+ if (version < 0 || variant < 0) {
+ dev_err(pcf->dev, "Unable to probe pcf50633\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ dev_info(pcf->dev, "Probed device version %d variant %d\n",
+ version, variant);
+
+ /* Enable all interrupts except RTC SECOND */
+ pcf->mask_regs[0] = 0x80;
+ pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00);
+ pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00);
+
+ /* Create sub devices */
+ pcf50633_client_dev_register(pcf, "pcf50633-input",
+ &pcf->input_pdev);
+ pcf50633_client_dev_register(pcf, "pcf50633-rtc",
+ &pcf->rtc_pdev);
+ pcf50633_client_dev_register(pcf, "pcf50633-mbc",
+ &pcf->mbc_pdev);
+ pcf50633_client_dev_register(pcf, "pcf50633-adc",
+ &pcf->adc_pdev);
+
+ for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("pcf50633-regltr", i);
+ if (!pdev) {
+ dev_err(pcf->dev, "Cannot create regulator\n");
+ continue;
+ }
+
+ pdev->dev.parent = pcf->dev;
+ pdev->dev.platform_data = &pdata->reg_init_data[i];
+ pdev->dev.driver_data = pcf;
+ pcf->regulator_pdev[i] = pdev;
+
+ platform_device_add(pdev);
+ }
+
+ if (client->irq) {
+ ret = request_irq(client->irq, pcf50633_irq,
+ IRQF_TRIGGER_LOW, "pcf50633", pcf);
+
+ if (ret) {
+ dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
+ goto err;
+ }
+ } else {
+ dev_err(pcf->dev, "No IRQ configured\n");
+ goto err;
+ }
+
+ if (enable_irq_wake(client->irq) < 0)
+ dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
+ "in this hardware revision", client->irq);
+
+ ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
+ if (ret)
+ dev_err(pcf->dev, "error creating sysfs entries\n");
+
+ if (pdata->probe_done)
+ pdata->probe_done(pcf);
+
+ return 0;
+
+err:
+ kfree(pcf);
+ return ret;
+}
+
+static int __devexit pcf50633_remove(struct i2c_client *client)
+{
+ struct pcf50633 *pcf = i2c_get_clientdata(client);
+ int i;
+
+ free_irq(pcf->irq, pcf);
+
+ platform_device_unregister(pcf->input_pdev);
+ platform_device_unregister(pcf->rtc_pdev);
+ platform_device_unregister(pcf->mbc_pdev);
+ platform_device_unregister(pcf->adc_pdev);
+
+ for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
+ platform_device_unregister(pcf->regulator_pdev[i]);
+
+ kfree(pcf);
+
+ return 0;
+}
+
+static struct i2c_device_id pcf50633_id_table[] = {
+ {"pcf50633", 0x73},
+};
+
+static struct i2c_driver pcf50633_driver = {
+ .driver = {
+ .name = "pcf50633",
+ .suspend = pcf50633_suspend,
+ .resume = pcf50633_resume,
+ },
+ .id_table = pcf50633_id_table,
+ .probe = pcf50633_probe,
+ .remove = __devexit_p(pcf50633_remove),
+};
+
+static int __init pcf50633_init(void)
+{
+ return i2c_add_driver(&pcf50633_driver);
+}
+
+static void __exit pcf50633_exit(void)
+{
+ i2c_del_driver(&pcf50633_driver);
+}
+
+MODULE_DESCRIPTION("I2C chip driver for NXP PCF50633 PMU");
+MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
+MODULE_LICENSE("GPL");
+
+module_init(pcf50633_init);
+module_exit(pcf50633_exit);
diff --git a/drivers/mfd/pcf50633-gpio.c b/drivers/mfd/pcf50633-gpio.c
new file mode 100644
index 000000000000..2fa2eca5c9cc
--- /dev/null
+++ b/drivers/mfd/pcf50633-gpio.c
@@ -0,0 +1,118 @@
+/* NXP PCF50633 GPIO Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/gpio.h>
+
+enum pcf50633_regulator_id {
+ PCF50633_REGULATOR_AUTO,
+ PCF50633_REGULATOR_DOWN1,
+ PCF50633_REGULATOR_DOWN2,
+ PCF50633_REGULATOR_LDO1,
+ PCF50633_REGULATOR_LDO2,
+ PCF50633_REGULATOR_LDO3,
+ PCF50633_REGULATOR_LDO4,
+ PCF50633_REGULATOR_LDO5,
+ PCF50633_REGULATOR_LDO6,
+ PCF50633_REGULATOR_HCLDO,
+ PCF50633_REGULATOR_MEMLDO,
+};
+
+#define PCF50633_REG_AUTOOUT 0x1a
+#define PCF50633_REG_DOWN1OUT 0x1e
+#define PCF50633_REG_DOWN2OUT 0x22
+#define PCF50633_REG_MEMLDOOUT 0x26
+#define PCF50633_REG_LDO1OUT 0x2d
+#define PCF50633_REG_LDO2OUT 0x2f
+#define PCF50633_REG_LDO3OUT 0x31
+#define PCF50633_REG_LDO4OUT 0x33
+#define PCF50633_REG_LDO5OUT 0x35
+#define PCF50633_REG_LDO6OUT 0x37
+#define PCF50633_REG_HCLDOOUT 0x39
+
+static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
+ [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT,
+ [PCF50633_REGULATOR_DOWN1] = PCF50633_REG_DOWN1OUT,
+ [PCF50633_REGULATOR_DOWN2] = PCF50633_REG_DOWN2OUT,
+ [PCF50633_REGULATOR_MEMLDO] = PCF50633_REG_MEMLDOOUT,
+ [PCF50633_REGULATOR_LDO1] = PCF50633_REG_LDO1OUT,
+ [PCF50633_REGULATOR_LDO2] = PCF50633_REG_LDO2OUT,
+ [PCF50633_REGULATOR_LDO3] = PCF50633_REG_LDO3OUT,
+ [PCF50633_REGULATOR_LDO4] = PCF50633_REG_LDO4OUT,
+ [PCF50633_REGULATOR_LDO5] = PCF50633_REG_LDO5OUT,
+ [PCF50633_REGULATOR_LDO6] = PCF50633_REG_LDO6OUT,
+ [PCF50633_REGULATOR_HCLDO] = PCF50633_REG_HCLDOOUT,
+};
+
+int pcf50633_gpio_set(struct pcf50633 *pcf, int gpio, u8 val)
+{
+ u8 reg;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+
+ return pcf50633_reg_set_bit_mask(pcf, reg, 0x07, val);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_set);
+
+u8 pcf50633_gpio_get(struct pcf50633 *pcf, int gpio)
+{
+ u8 reg, val;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+ val = pcf50633_reg_read(pcf, reg) & 0x07;
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_get);
+
+int pcf50633_gpio_invert_set(struct pcf50633 *pcf, int gpio, int invert)
+{
+ u8 val, reg;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+ val = !!invert << 3;
+
+ return pcf50633_reg_set_bit_mask(pcf, reg, 1 << 3, val);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_invert_set);
+
+int pcf50633_gpio_invert_get(struct pcf50633 *pcf, int gpio)
+{
+ u8 reg, val;
+
+ reg = gpio - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG;
+ val = pcf50633_reg_read(pcf, reg);
+
+ return val & (1 << 3);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_invert_get);
+
+int pcf50633_gpio_power_supply_set(struct pcf50633 *pcf,
+ int gpio, int regulator, int on)
+{
+ u8 reg, val, mask;
+
+ /* the *ENA register is always one after the *OUT register */
+ reg = pcf50633_regulator_registers[regulator] + 1;
+
+ val = !!on << (gpio - PCF50633_GPIO1);
+ mask = 1 << (gpio - PCF50633_GPIO1);
+
+ return pcf50633_reg_set_bit_mask(pcf, reg, mask, val);
+}
+EXPORT_SYMBOL_GPL(pcf50633_gpio_power_supply_set);
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 170f9d47c2f9..0e5761f12634 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -41,6 +41,7 @@ struct sm501_gpio_chip {
struct gpio_chip gpio;
struct sm501_gpio *ourgpio; /* to get back to parent. */
void __iomem *regbase;
+ void __iomem *control; /* address of control reg. */
};
struct sm501_gpio {
@@ -908,6 +909,25 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
return result & 1UL;
}
+static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
+ unsigned long bit)
+{
+ unsigned long ctrl;
+
+ /* check and modify if this pin is not set as gpio. */
+
+ if (readl(smchip->control) & bit) {
+ dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
+ "changing mode of gpio, bit %08lx\n", bit);
+
+ ctrl = readl(smchip->control);
+ ctrl &= ~bit;
+ writel(ctrl, smchip->control);
+
+ sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
+ }
+}
+
static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
@@ -929,6 +949,8 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
writel(val, regs);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ sm501_gpio_ensure_gpio(smchip, bit);
+
spin_unlock_irqrestore(&smgpio->lock, save);
}
@@ -941,8 +963,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
unsigned long save;
unsigned long ddr;
- dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
- __func__, chip, offset);
+ dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n",
+ __func__, chip, offset);
spin_lock_irqsave(&smgpio->lock, save);
@@ -950,6 +972,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
+ sm501_gpio_ensure_gpio(smchip, bit);
+
spin_unlock_irqrestore(&smgpio->lock, save);
return 0;
@@ -1012,9 +1036,11 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
if (base > 0)
base += 32;
chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH;
+ chip->control = sm->regs + SM501_GPIO63_32_CONTROL;
gchip->label = "SM501-HIGH";
} else {
chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW;
+ chip->control = sm->regs + SM501_GPIO31_0_CONTROL;
gchip->label = "SM501-LOW";
}
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/mfd/tps65010.c
index acf8b9d5f575..acf8b9d5f575 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/mfd/tps65010.c
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index dd843c4fbcc7..e7ab0035d305 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -33,9 +33,14 @@
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/regulator/machine.h>
+
#include <linux/i2c.h>
#include <linux/i2c/twl4030.h>
+#ifdef CONFIG_ARM
+#include <mach/cpu.h>
+#endif
/*
* The TWL4030 "Triton 2" is one of a family of a multi-function "Power
@@ -71,6 +76,13 @@
#define twl_has_gpio() false
#endif
+#if defined(CONFIG_REGULATOR_TWL4030) \
+ || defined(CONFIG_REGULATOR_TWL4030_MODULE)
+#define twl_has_regulator() true
+#else
+#define twl_has_regulator() false
+#endif
+
#if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE)
#define twl_has_madc() true
#else
@@ -149,6 +161,10 @@
#define HIGH_PERF_SQ (1 << 3)
+/* chip-specific feature flags, for i2c_device_id.driver_data */
+#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */
+#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */
+
/*----------------------------------------------------------------------*/
/* is driver active, bound to a chip? */
@@ -225,7 +241,7 @@ static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
*
* Returns the result of operation - 0 is success
*/
-int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
+int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
int ret;
int sid;
@@ -274,7 +290,7 @@ EXPORT_SYMBOL(twl4030_i2c_write);
*
* Returns result of operation - num_bytes is success else failure.
*/
-int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, u8 num_bytes)
+int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
int ret;
u8 val;
@@ -352,258 +368,258 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8);
/*----------------------------------------------------------------------*/
-/*
- * NOTE: We know the first 8 IRQs after pdata->base_irq are
- * for the PIH, and the next are for the PWR_INT SIH, since
- * that's how twl_init_irq() sets things up.
- */
-
-static int add_children(struct twl4030_platform_data *pdata)
+static struct device *
+add_numbered_child(unsigned chip, const char *name, int num,
+ void *pdata, unsigned pdata_len,
+ bool can_wakeup, int irq0, int irq1)
{
- struct platform_device *pdev = NULL;
- struct twl4030_client *twl = NULL;
- int status = 0;
+ struct platform_device *pdev;
+ struct twl4030_client *twl = &twl4030_modules[chip];
+ int status;
+
+ pdev = platform_device_alloc(name, num);
+ if (!pdev) {
+ dev_dbg(&twl->client->dev, "can't alloc dev\n");
+ status = -ENOMEM;
+ goto err;
+ }
- if (twl_has_bci() && pdata->bci) {
- twl = &twl4030_modules[3];
+ device_init_wakeup(&pdev->dev, can_wakeup);
+ pdev->dev.parent = &twl->client->dev;
- pdev = platform_device_alloc("twl4030_bci", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc bci dev\n", DRIVER_NAME);
- status = -ENOMEM;
+ if (pdata) {
+ status = platform_device_add_data(pdev, pdata, pdata_len);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "can't add platform_data\n");
goto err;
}
+ }
- if (status == 0) {
- pdev->dev.parent = &twl->client->dev;
- status = platform_device_add_data(pdev, pdata->bci,
- sizeof(*pdata->bci));
- if (status < 0) {
- dev_dbg(&twl->client->dev,
- "can't add bci data, %d\n",
- status);
- goto err;
- }
- }
-
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 8 + 1,
- .flags = IORESOURCE_IRQ,
- };
-
- status = platform_device_add_resources(pdev, &r, 1);
- }
-
- if (status == 0)
- status = platform_device_add(pdev);
+ if (irq0) {
+ struct resource r[2] = {
+ { .start = irq0, .flags = IORESOURCE_IRQ, },
+ { .start = irq1, .flags = IORESOURCE_IRQ, },
+ };
+ status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create bci dev, %d\n",
- status);
+ dev_dbg(&pdev->dev, "can't add irqs\n");
goto err;
}
}
- if (twl_has_gpio() && pdata->gpio) {
- twl = &twl4030_modules[1];
+ status = platform_device_add(pdev);
- pdev = platform_device_alloc("twl4030_gpio", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc gpio dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
+err:
+ if (status < 0) {
+ platform_device_put(pdev);
+ dev_err(&twl->client->dev, "can't add %s dev\n", name);
+ return ERR_PTR(status);
+ }
+ return &pdev->dev;
+}
- /* more driver model init */
- if (status == 0) {
- pdev->dev.parent = &twl->client->dev;
- /* device_init_wakeup(&pdev->dev, 1); */
-
- status = platform_device_add_data(pdev, pdata->gpio,
- sizeof(*pdata->gpio));
- if (status < 0) {
- dev_dbg(&twl->client->dev,
- "can't add gpio data, %d\n",
- status);
- goto err;
- }
- }
+static inline struct device *add_child(unsigned chip, const char *name,
+ void *pdata, unsigned pdata_len,
+ bool can_wakeup, int irq0, int irq1)
+{
+ return add_numbered_child(chip, name, -1, pdata, pdata_len,
+ can_wakeup, irq0, irq1);
+}
- /* GPIO module IRQ */
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 0,
- .flags = IORESOURCE_IRQ,
- };
+static struct device *
+add_regulator_linked(int num, struct regulator_init_data *pdata,
+ struct regulator_consumer_supply *consumers,
+ unsigned num_consumers)
+{
+ /* regulator framework demands init_data ... */
+ if (!pdata)
+ return NULL;
- status = platform_device_add_resources(pdev, &r, 1);
- }
+ if (consumers) {
+ pdata->consumer_supplies = consumers;
+ pdata->num_consumer_supplies = num_consumers;
+ }
- if (status == 0)
- status = platform_device_add(pdev);
+ /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
+ return add_numbered_child(3, "twl4030_reg", num,
+ pdata, sizeof(*pdata), false, 0, 0);
+}
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create gpio dev, %d\n",
- status);
- goto err;
- }
+static struct device *
+add_regulator(int num, struct regulator_init_data *pdata)
+{
+ return add_regulator_linked(num, pdata, NULL, 0);
+}
+
+/*
+ * NOTE: We know the first 8 IRQs after pdata->base_irq are
+ * for the PIH, and the next are for the PWR_INT SIH, since
+ * that's how twl_init_irq() sets things up.
+ */
+
+static int
+add_children(struct twl4030_platform_data *pdata, unsigned long features)
+{
+ struct device *child;
+ struct device *usb_transceiver = NULL;
+
+ if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) {
+ child = add_child(3, "twl4030_bci",
+ pdata->bci, sizeof(*pdata->bci),
+ false,
+ /* irq0 = CHG_PRES, irq1 = BCI */
+ pdata->irq_base + 8 + 1, pdata->irq_base + 2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ if (twl_has_gpio() && pdata->gpio) {
+ child = add_child(1, "twl4030_gpio",
+ pdata->gpio, sizeof(*pdata->gpio),
+ false, pdata->irq_base + 0, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_keypad() && pdata->keypad) {
- pdev = platform_device_alloc("twl4030_keypad", -1);
- if (pdev) {
- twl = &twl4030_modules[2];
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->keypad,
- sizeof(*pdata->keypad));
- if (status < 0) {
- dev_dbg(&twl->client->dev,
- "can't add keypad data, %d\n",
- status);
- platform_device_put(pdev);
- goto err;
- }
- status = platform_device_add(pdev);
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create keypad dev, %d\n",
- status);
- goto err;
- }
- } else {
- pr_debug("%s: can't alloc keypad dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
+ child = add_child(2, "twl4030_keypad",
+ pdata->keypad, sizeof(*pdata->keypad),
+ true, pdata->irq_base + 1, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_madc() && pdata->madc) {
- pdev = platform_device_alloc("twl4030_madc", -1);
- if (pdev) {
- twl = &twl4030_modules[2];
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->madc,
- sizeof(*pdata->madc));
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't add madc data, %d\n",
- status);
- goto err;
- }
- status = platform_device_add(pdev);
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create madc dev, %d\n",
- status);
- goto err;
- }
- } else {
- pr_debug("%s: can't alloc madc dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
+ child = add_child(2, "twl4030_madc",
+ pdata->madc, sizeof(*pdata->madc),
+ true, pdata->irq_base + 3, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_rtc()) {
- twl = &twl4030_modules[3];
-
- pdev = platform_device_alloc("twl4030_rtc", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc rtc dev\n", DRIVER_NAME);
- status = -ENOMEM;
- } else {
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- }
-
/*
- * REVISIT platform_data here currently might use of
+ * REVISIT platform_data here currently might expose the
* "msecure" line ... but for now we just expect board
- * setup to tell the chip "we are secure" at all times.
+ * setup to tell the chip "it's always ok to SET_TIME".
* Eventually, Linux might become more aware of such
* HW security concerns, and "least privilege".
*/
-
- /* RTC module IRQ */
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 8 + 3,
- .flags = IORESOURCE_IRQ,
- };
-
- status = platform_device_add_resources(pdev, &r, 1);
- }
-
- if (status == 0)
- status = platform_device_add(pdev);
-
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create rtc dev, %d\n",
- status);
- goto err;
- }
+ child = add_child(3, "twl4030_rtc",
+ NULL, 0,
+ true, pdata->irq_base + 8 + 3, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
if (twl_has_usb() && pdata->usb) {
- twl = &twl4030_modules[0];
-
- pdev = platform_device_alloc("twl4030_usb", -1);
- if (!pdev) {
- pr_debug("%s: can't alloc usb dev\n", DRIVER_NAME);
- status = -ENOMEM;
- goto err;
- }
-
- if (status == 0) {
- pdev->dev.parent = &twl->client->dev;
- device_init_wakeup(&pdev->dev, 1);
- status = platform_device_add_data(pdev, pdata->usb,
- sizeof(*pdata->usb));
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't add usb data, %d\n",
- status);
- goto err;
- }
- }
-
- if (status == 0) {
- struct resource r = {
- .start = pdata->irq_base + 8 + 2,
- .flags = IORESOURCE_IRQ,
- };
+ child = add_child(0, "twl4030_usb",
+ pdata->usb, sizeof(*pdata->usb),
+ true,
+ /* irq0 = USB_PRES, irq1 = USB */
+ pdata->irq_base + 8 + 2, pdata->irq_base + 4);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ /* we need to connect regulators to this transceiver */
+ usb_transceiver = child;
+ }
- status = platform_device_add_resources(pdev, &r, 1);
- }
+ if (twl_has_regulator()) {
+ /*
+ child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ */
+
+ child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VDAC, pdata->vdac);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator((features & TWL4030_VAUX2)
+ ? TWL4030_REG_VAUX2_4030
+ : TWL4030_REG_VAUX2,
+ pdata->vaux2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
- if (status == 0)
- status = platform_device_add(pdev);
+ if (twl_has_regulator() && usb_transceiver) {
+ static struct regulator_consumer_supply usb1v5 = {
+ .supply = "usb1v5",
+ };
+ static struct regulator_consumer_supply usb1v8 = {
+ .supply = "usb1v8",
+ };
+ static struct regulator_consumer_supply usb3v1 = {
+ .supply = "usb3v1",
+ };
+
+ /* this is a template that gets copied */
+ struct regulator_init_data usb_fixed = {
+ .constraints.valid_modes_mask =
+ REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .constraints.valid_ops_mask =
+ REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ };
+
+ usb1v5.dev = usb_transceiver;
+ usb1v8.dev = usb_transceiver;
+ usb3v1.dev = usb_transceiver;
+
+ child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed,
+ &usb1v5, 1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed,
+ &usb1v8, 1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed,
+ &usb3v1, 1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
- if (status < 0) {
- platform_device_put(pdev);
- dev_dbg(&twl->client->dev,
- "can't create usb dev, %d\n",
- status);
- }
+ /* maybe add LDOs that are omitted on cost-reduced parts */
+ if (twl_has_regulator() && !(features & TPS_SUBSET)) {
+ /*
+ child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ */
+
+ child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VSIM, pdata->vsim);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+
+ child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
}
-err:
- if (status)
- pr_err("failed to add twl4030's children (status %d)\n", status);
- return status;
+ return 0;
}
/*----------------------------------------------------------------------*/
@@ -633,7 +649,7 @@ static inline int __init unprotect_pm_master(void)
return e;
}
-static void __init clocks_init(void)
+static void __init clocks_init(struct device *dev)
{
int e = 0;
struct clk *osc;
@@ -642,15 +658,10 @@ static void __init clocks_init(void)
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
if (cpu_is_omap2430())
- osc = clk_get(NULL, "osc_ck");
+ osc = clk_get(dev, "osc_ck");
else
- osc = clk_get(NULL, "osc_sys_ck");
-#else
- /* REVISIT for non-OMAP systems, pass the clock rate from
- * board init code, using platform_data.
- */
- osc = ERR_PTR(-EIO);
-#endif
+ osc = clk_get(dev, "osc_sys_ck");
+
if (IS_ERR(osc)) {
printk(KERN_WARNING "Skipping twl4030 internal clock init and "
"using bootloader value (unknown osc rate)\n");
@@ -660,6 +671,18 @@ static void __init clocks_init(void)
rate = clk_get_rate(osc);
clk_put(osc);
+#else
+ /* REVISIT for non-OMAP systems, pass the clock rate from
+ * board init code, using platform_data.
+ */
+ osc = ERR_PTR(-EIO);
+
+ printk(KERN_WARNING "Skipping twl4030 internal clock init and "
+ "using bootloader value (unknown osc rate)\n");
+
+ return;
+#endif
+
switch (rate) {
case 19200000:
ctrl = HFCLK_FREQ_19p2_MHZ;
@@ -753,7 +776,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
inuse = true;
/* setup clock framework */
- clocks_init();
+ clocks_init(&client->dev);
/* Maybe init the T2 Interrupt subsystem */
if (client->irq
@@ -764,7 +787,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto fail;
}
- status = add_children(pdata);
+ status = add_children(pdata, id->driver_data);
fail:
if (status < 0)
twl4030_remove(client);
@@ -772,11 +795,11 @@ fail:
}
static const struct i2c_device_id twl4030_ids[] = {
- { "twl4030", 0 }, /* "Triton 2" */
- { "tps65950", 0 }, /* catalog version of twl4030 */
- { "tps65930", 0 }, /* fewer LDOs and DACs; no charger */
- { "tps65920", 0 }, /* fewer LDOs; no codec or charger */
- { "twl5030", 0 }, /* T2 updated */
+ { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */
+ { "twl5030", 0 }, /* T2 updated */
+ { "tps65950", 0 }, /* catalog version of twl5030 */
+ { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
+ { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
{ /* end of list */ },
};
MODULE_DEVICE_TABLE(i2c, twl4030_ids);
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index fae868a8d499..b10876036983 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -180,10 +180,15 @@ static struct completion irq_event;
static int twl4030_irq_thread(void *data)
{
long irq = (long)data;
- irq_desc_t *desc = irq_desc + irq;
+ struct irq_desc *desc = irq_to_desc(irq);
static unsigned i2c_errors;
const static unsigned max_i2c_errors = 100;
+ if (!desc) {
+ pr_err("twl4030: Invalid IRQ: %ld\n", irq);
+ return -EINVAL;
+ }
+
current->flags |= PF_NOFREEZE;
while (!kthread_should_stop()) {
@@ -215,7 +220,13 @@ static int twl4030_irq_thread(void *data)
pih_isr;
pih_isr >>= 1, module_irq++) {
if (pih_isr & 0x1) {
- irq_desc_t *d = irq_desc + module_irq;
+ struct irq_desc *d = irq_to_desc(module_irq);
+
+ if (!d) {
+ pr_err("twl4030: Invalid SIH IRQ: %d\n",
+ module_irq);
+ return -EINVAL;
+ }
/* These can't be masked ... always warn
* if we get any surprises.
@@ -452,10 +463,16 @@ static void twl4030_sih_do_edge(struct work_struct *work)
/* Modify only the bits we know must change */
while (edge_change) {
int i = fls(edge_change) - 1;
- struct irq_desc *d = irq_desc + i + agent->irq_base;
+ struct irq_desc *d = irq_to_desc(i + agent->irq_base);
int byte = 1 + (i >> 2);
int off = (i & 0x3) * 2;
+ if (!d) {
+ pr_err("twl4030: Invalid IRQ: %d\n",
+ i + agent->irq_base);
+ return;
+ }
+
bytes[byte] &= ~(0x03 << off);
spin_lock_irq(&d->lock);
@@ -512,9 +529,14 @@ static void twl4030_sih_unmask(unsigned irq)
static int twl4030_sih_set_type(unsigned irq, unsigned trigger)
{
struct sih_agent *sih = get_irq_chip_data(irq);
- struct irq_desc *desc = irq_desc + irq;
+ struct irq_desc *desc = irq_to_desc(irq);
unsigned long flags;
+ if (!desc) {
+ pr_err("twl4030: Invalid IRQ: %d\n", irq);
+ return -EINVAL;
+ }
+
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
return -EINVAL;
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 0d47fb9e4b3b..f92595c8f165 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -63,7 +63,6 @@
*/
static DEFINE_MUTEX(io_mutex);
static DEFINE_MUTEX(reg_lock_mutex);
-static DEFINE_MUTEX(auxadc_mutex);
/* Perform a physical read from the device.
*/
@@ -299,6 +298,13 @@ int wm8350_block_write(struct wm8350 *wm8350, int start_reg, int regs,
}
EXPORT_SYMBOL_GPL(wm8350_block_write);
+/**
+ * wm8350_reg_lock()
+ *
+ * The WM8350 has a hardware lock which can be used to prevent writes to
+ * some registers (generally those which can cause particularly serious
+ * problems if misused). This function enables that lock.
+ */
int wm8350_reg_lock(struct wm8350 *wm8350)
{
u16 key = WM8350_LOCK_KEY;
@@ -314,6 +320,15 @@ int wm8350_reg_lock(struct wm8350 *wm8350)
}
EXPORT_SYMBOL_GPL(wm8350_reg_lock);
+/**
+ * wm8350_reg_unlock()
+ *
+ * The WM8350 has a hardware lock which can be used to prevent writes to
+ * some registers (generally those which can cause particularly serious
+ * problems if misused). This function disables that lock so updates
+ * can be performed. For maximum safety this should be done only when
+ * required.
+ */
int wm8350_reg_unlock(struct wm8350 *wm8350)
{
u16 key = WM8350_UNLOCK_KEY;
@@ -1066,38 +1081,158 @@ int wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
}
EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
+int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
+{
+ u16 reg, result = 0;
+ int tries = 5;
+
+ if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
+ return -EINVAL;
+ if (channel >= WM8350_AUXADC_USB && channel <= WM8350_AUXADC_TEMP
+ && (scale != 0 || vref != 0))
+ return -EINVAL;
+
+ mutex_lock(&wm8350->auxadc_mutex);
+
+ /* Turn on the ADC */
+ reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, reg | WM8350_AUXADC_ENA);
+
+ if (scale || vref) {
+ reg = scale << 13;
+ reg |= vref << 12;
+ wm8350_reg_write(wm8350, WM8350_AUX1_READBACK + channel, reg);
+ }
+
+ reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
+ reg |= 1 << channel | WM8350_AUXADC_POLL;
+ wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
+
+ do {
+ schedule_timeout_interruptible(1);
+ reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
+ } while (tries-- && (reg & WM8350_AUXADC_POLL));
+
+ if (!tries)
+ dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
+ else
+ result = wm8350_reg_read(wm8350,
+ WM8350_AUX1_READBACK + channel);
+
+ /* Turn off the ADC */
+ reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
+ wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5,
+ reg & ~WM8350_AUXADC_ENA);
+
+ mutex_unlock(&wm8350->auxadc_mutex);
+
+ return result & WM8350_AUXADC_DATA1_MASK;
+}
+EXPORT_SYMBOL_GPL(wm8350_read_auxadc);
+
/*
* Cache is always host endian.
*/
-static int wm8350_create_cache(struct wm8350 *wm8350, int mode)
+static int wm8350_create_cache(struct wm8350 *wm8350, int type, int mode)
{
int i, ret = 0;
u16 value;
const u16 *reg_map;
- switch (mode) {
-#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+ switch (type) {
case 0:
- reg_map = wm8350_mode0_defaults;
- break;
+ switch (mode) {
+#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_0
+ case 0:
+ reg_map = wm8350_mode0_defaults;
+ break;
#endif
#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_1
- case 1:
- reg_map = wm8350_mode1_defaults;
- break;
+ case 1:
+ reg_map = wm8350_mode1_defaults;
+ break;
#endif
#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_2
- case 2:
- reg_map = wm8350_mode2_defaults;
- break;
+ case 2:
+ reg_map = wm8350_mode2_defaults;
+ break;
#endif
#ifdef CONFIG_MFD_WM8350_CONFIG_MODE_3
- case 3:
- reg_map = wm8350_mode3_defaults;
+ case 3:
+ reg_map = wm8350_mode3_defaults;
+ break;
+#endif
+ default:
+ dev_err(wm8350->dev,
+ "WM8350 configuration mode %d not supported\n",
+ mode);
+ return -EINVAL;
+ }
break;
+
+ case 1:
+ switch (mode) {
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0
+ case 0:
+ reg_map = wm8351_mode0_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1
+ case 1:
+ reg_map = wm8351_mode1_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2
+ case 2:
+ reg_map = wm8351_mode2_defaults;
+ break;
#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3
+ case 3:
+ reg_map = wm8351_mode3_defaults;
+ break;
+#endif
+ default:
+ dev_err(wm8350->dev,
+ "WM8351 configuration mode %d not supported\n",
+ mode);
+ return -EINVAL;
+ }
+ break;
+
+ case 2:
+ switch (mode) {
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0
+ case 0:
+ reg_map = wm8352_mode0_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1
+ case 1:
+ reg_map = wm8352_mode1_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2
+ case 2:
+ reg_map = wm8352_mode2_defaults;
+ break;
+#endif
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3
+ case 3:
+ reg_map = wm8352_mode3_defaults;
+ break;
+#endif
+ default:
+ dev_err(wm8350->dev,
+ "WM8352 configuration mode %d not supported\n",
+ mode);
+ return -EINVAL;
+ }
+ break;
+
default:
- dev_err(wm8350->dev, "Configuration mode %d not supported\n",
+ dev_err(wm8350->dev,
+ "WM835x configuration mode %d not supported\n",
mode);
return -EINVAL;
}
@@ -1163,53 +1298,113 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
struct wm8350_platform_data *pdata)
{
int ret = -EINVAL;
- u16 id1, id2, mask, mode;
+ u16 id1, id2, mask_rev;
+ u16 cust_id, mode, chip_rev;
/* get WM8350 revision and config mode */
wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
+ wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), &mask_rev);
id1 = be16_to_cpu(id1);
id2 = be16_to_cpu(id2);
+ mask_rev = be16_to_cpu(mask_rev);
- if (id1 == 0x6143) {
- switch ((id2 & WM8350_CHIP_REV_MASK) >> 12) {
+ if (id1 != 0x6143) {
+ dev_err(wm8350->dev,
+ "Device with ID %x is not a WM8350\n", id1);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ mode = id2 & WM8350_CONF_STS_MASK >> 10;
+ cust_id = id2 & WM8350_CUST_ID_MASK;
+ chip_rev = (id2 & WM8350_CHIP_REV_MASK) >> 12;
+ dev_info(wm8350->dev,
+ "CONF_STS %d, CUST_ID %d, MASK_REV %d, CHIP_REV %d\n",
+ mode, cust_id, mask_rev, chip_rev);
+
+ if (cust_id != 0) {
+ dev_err(wm8350->dev, "Unsupported CUST_ID\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ switch (mask_rev) {
+ case 0:
+ wm8350->pmic.max_dcdc = WM8350_DCDC_6;
+ wm8350->pmic.max_isink = WM8350_ISINK_B;
+
+ switch (chip_rev) {
case WM8350_REV_E:
- dev_info(wm8350->dev, "Found Rev E device\n");
- wm8350->rev = WM8350_REV_E;
+ dev_info(wm8350->dev, "WM8350 Rev E\n");
break;
case WM8350_REV_F:
- dev_info(wm8350->dev, "Found Rev F device\n");
- wm8350->rev = WM8350_REV_F;
+ dev_info(wm8350->dev, "WM8350 Rev F\n");
break;
case WM8350_REV_G:
- dev_info(wm8350->dev, "Found Rev G device\n");
- wm8350->rev = WM8350_REV_G;
+ dev_info(wm8350->dev, "WM8350 Rev G\n");
+ wm8350->power.rev_g_coeff = 1;
+ break;
+ case WM8350_REV_H:
+ dev_info(wm8350->dev, "WM8350 Rev H\n");
+ wm8350->power.rev_g_coeff = 1;
break;
default:
/* For safety we refuse to run on unknown hardware */
- dev_info(wm8350->dev, "Found unknown rev\n");
+ dev_err(wm8350->dev, "Unknown WM8350 CHIP_REV\n");
ret = -ENODEV;
goto err;
}
- } else {
- dev_info(wm8350->dev, "Device with ID %x is not a WM8350\n",
- id1);
+ break;
+
+ case 1:
+ wm8350->pmic.max_dcdc = WM8350_DCDC_4;
+ wm8350->pmic.max_isink = WM8350_ISINK_A;
+
+ switch (chip_rev) {
+ case 0:
+ dev_info(wm8350->dev, "WM8351 Rev A\n");
+ wm8350->power.rev_g_coeff = 1;
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ break;
+
+ case 2:
+ wm8350->pmic.max_dcdc = WM8350_DCDC_6;
+ wm8350->pmic.max_isink = WM8350_ISINK_B;
+
+ switch (chip_rev) {
+ case 0:
+ dev_info(wm8350->dev, "WM8352 Rev A\n");
+ wm8350->power.rev_g_coeff = 1;
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown WM8352 CHIP_REV\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown MASK_REV\n");
ret = -ENODEV;
goto err;
}
- mode = id2 & WM8350_CONF_STS_MASK >> 10;
- mask = id2 & WM8350_CUST_ID_MASK;
- dev_info(wm8350->dev, "Config mode %d, ROM mask %d\n", mode, mask);
-
- ret = wm8350_create_cache(wm8350, mode);
+ ret = wm8350_create_cache(wm8350, mask_rev, mode);
if (ret < 0) {
- printk(KERN_ERR "wm8350: failed to create register cache\n");
+ dev_err(wm8350->dev, "Failed to create register cache\n");
return ret;
}
- if (pdata->init) {
+ if (pdata && pdata->init) {
ret = pdata->init(wm8350);
if (ret != 0) {
dev_err(wm8350->dev, "Platform init() failed: %d\n",
@@ -1218,6 +1413,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
}
}
+ mutex_init(&wm8350->auxadc_mutex);
mutex_init(&wm8350->irq_mutex);
INIT_WORK(&wm8350->irq_work, wm8350_irq_worker);
if (irq) {
@@ -1257,6 +1453,9 @@ void wm8350_device_exit(struct wm8350 *wm8350)
{
int i;
+ for (i = 0; i < ARRAY_SIZE(wm8350->pmic.led); i++)
+ platform_device_unregister(wm8350->pmic.led[i].pdev);
+
for (i = 0; i < ARRAY_SIZE(wm8350->pmic.pdev); i++)
platform_device_unregister(wm8350->pmic.pdev[i]);
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c
index 3e0ce0e50ea2..8d8c93217572 100644
--- a/drivers/mfd/wm8350-i2c.c
+++ b/drivers/mfd/wm8350-i2c.c
@@ -1,8 +1,6 @@
/*
* wm8350-i2c.c -- Generic I2C driver for Wolfson WM8350 PMIC
*
- * This driver defines and configures the WM8350 for the Freescale i.MX32ADS.
- *
* Copyright 2007, 2008 Wolfson Microelectronics PLC.
*
* Author: Liam Girdwood
@@ -99,6 +97,8 @@ static int wm8350_i2c_remove(struct i2c_client *i2c)
static const struct i2c_device_id wm8350_i2c_id[] = {
{ "wm8350", 0 },
+ { "wm8351", 0 },
+ { "wm8352", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8350_i2c_id);
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
index 974678db22cd..68887b817d17 100644
--- a/drivers/mfd/wm8350-regmap.c
+++ b/drivers/mfd/wm8350-regmap.c
@@ -1074,6 +1074,2102 @@ const u16 wm8350_mode3_defaults[] = {
};
#endif
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_0
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode0_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0004, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0FFC, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFC, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0013, /* R140 - GPIO Function Select 1 */
+ 0x0000, /* R141 - GPIO Function Select 2 */
+ 0x0000, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0000, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0000, /* R186 - DCDC3 Control */
+ 0x0000, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0000, /* R189 - DCDC4 Control */
+ 0x0000, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x0000, /* R195 */
+ 0x0000, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001B, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001B, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001B, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_1
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode1_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0CFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0C1F, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0300, /* R140 - GPIO Function Select 1 */
+ 0x1110, /* R141 - GPIO Function Select 2 */
+ 0x0013, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0C00, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0026, /* R186 - DCDC3 Control */
+ 0x0400, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0062, /* R189 - DCDC4 Control */
+ 0x0800, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x000A, /* R195 */
+ 0x1000, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x0006, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0010, /* R203 - LDO2 Control */
+ 0x0C00, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001F, /* R206 - LDO3 Control */
+ 0x0800, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x000A, /* R209 - LDO4 Control */
+ 0x0800, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x1000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_2
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode2_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0214, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0110, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x09FA, /* R134 - GPIO Configuration (i/o) */
+ 0x0DF6, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x1310, /* R140 - GPIO Function Select 1 */
+ 0x0003, /* R141 - GPIO Function Select 2 */
+ 0x2000, /* R142 - GPIO Function Select 3 */
+ 0x0000, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x001A, /* R180 - DCDC1 Control */
+ 0x0800, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0056, /* R186 - DCDC3 Control */
+ 0x0400, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0026, /* R189 - DCDC4 Control */
+ 0x0C00, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 */
+ 0x0C00, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0400, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0010, /* R203 - LDO2 Control */
+ 0x0C00, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x0015, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001A, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8351_CONFIG_MODE_3
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8351_mode3_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0001, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0010, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0BFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFD, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0310, /* R140 - GPIO Function Select 1 */
+ 0x0001, /* R141 - GPIO Function Select 2 */
+ 0x2300, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 */
+ 0x0000, /* R175 */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0026, /* R186 - DCDC3 Control */
+ 0x0800, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0062, /* R189 - DCDC4 Control */
+ 0x1400, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 */
+ 0x0000, /* R193 */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 */
+ 0x0400, /* R196 */
+ 0x0006, /* R197 */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x0006, /* R200 - LDO1 Control */
+ 0x0C00, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0016, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x0019, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001A, /* R209 - LDO4 Control */
+ 0x1000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 - FLL Test 1 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x1000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_0
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode0_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0004, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0FFC, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFC, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0013, /* R140 - GPIO Function Select 1 */
+ 0x0000, /* R141 - GPIO Function Select 2 */
+ 0x0000, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0000, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0000, /* R186 - DCDC3 Control */
+ 0x0000, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0000, /* R189 - DCDC4 Control */
+ 0x0000, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0000, /* R195 - DCDC6 Control */
+ 0x0000, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001B, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001B, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001B, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_1
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode1_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0BFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFF, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0300, /* R140 - GPIO Function Select 1 */
+ 0x0000, /* R141 - GPIO Function Select 2 */
+ 0x2300, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x0062, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0006, /* R186 - DCDC3 Control */
+ 0x0800, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x0006, /* R189 - DCDC4 Control */
+ 0x0C00, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 - DCDC6 Control */
+ 0x1000, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x0002, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x001A, /* R203 - LDO2 Control */
+ 0x0000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001F, /* R206 - LDO3 Control */
+ 0x0000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001F, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_2
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode2_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0000, /* R129 - GPIO Pin pull up Control */
+ 0x0110, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x09DA, /* R134 - GPIO Configuration (i/o) */
+ 0x0DD6, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x1310, /* R140 - GPIO Function Select 1 */
+ 0x0033, /* R141 - GPIO Function Select 2 */
+ 0x2000, /* R142 - GPIO Function Select 3 */
+ 0x0000, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x000E, /* R180 - DCDC1 Control */
+ 0x0800, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0056, /* R186 - DCDC3 Control */
+ 0x1800, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x000E, /* R189 - DCDC4 Control */
+ 0x1000, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0026, /* R195 - DCDC6 Control */
+ 0x0C00, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001C, /* R200 - LDO1 Control */
+ 0x0000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0006, /* R203 - LDO2 Control */
+ 0x0400, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x001C, /* R206 - LDO3 Control */
+ 0x1400, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x001A, /* R209 - LDO4 Control */
+ 0x0000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
+#ifdef CONFIG_MFD_WM8352_CONFIG_MODE_3
+
+#undef WM8350_HAVE_CONFIG_MODE
+#define WM8350_HAVE_CONFIG_MODE
+
+const u16 wm8352_mode3_defaults[] = {
+ 0x6143, /* R0 - Reset/ID */
+ 0x0000, /* R1 - ID */
+ 0x0002, /* R2 - Revision */
+ 0x1C02, /* R3 - System Control 1 */
+ 0x0204, /* R4 - System Control 2 */
+ 0x0000, /* R5 - System Hibernate */
+ 0x8A00, /* R6 - Interface Control */
+ 0x0000, /* R7 */
+ 0x8000, /* R8 - Power mgmt (1) */
+ 0x0000, /* R9 - Power mgmt (2) */
+ 0x0000, /* R10 - Power mgmt (3) */
+ 0x2000, /* R11 - Power mgmt (4) */
+ 0x0E00, /* R12 - Power mgmt (5) */
+ 0x0000, /* R13 - Power mgmt (6) */
+ 0x0000, /* R14 - Power mgmt (7) */
+ 0x0000, /* R15 */
+ 0x0000, /* R16 - RTC Seconds/Minutes */
+ 0x0100, /* R17 - RTC Hours/Day */
+ 0x0101, /* R18 - RTC Date/Month */
+ 0x1400, /* R19 - RTC Year */
+ 0x0000, /* R20 - Alarm Seconds/Minutes */
+ 0x0000, /* R21 - Alarm Hours/Day */
+ 0x0000, /* R22 - Alarm Date/Month */
+ 0x0320, /* R23 - RTC Time Control */
+ 0x0000, /* R24 - System Interrupts */
+ 0x0000, /* R25 - Interrupt Status 1 */
+ 0x0000, /* R26 - Interrupt Status 2 */
+ 0x0000, /* R27 */
+ 0x0000, /* R28 - Under Voltage Interrupt status */
+ 0x0000, /* R29 - Over Current Interrupt status */
+ 0x0000, /* R30 - GPIO Interrupt Status */
+ 0x0000, /* R31 - Comparator Interrupt Status */
+ 0x3FFF, /* R32 - System Interrupts Mask */
+ 0x0000, /* R33 - Interrupt Status 1 Mask */
+ 0x0000, /* R34 - Interrupt Status 2 Mask */
+ 0x0000, /* R35 */
+ 0x0000, /* R36 - Under Voltage Interrupt status Mask */
+ 0x0000, /* R37 - Over Current Interrupt status Mask */
+ 0x0000, /* R38 - GPIO Interrupt Status Mask */
+ 0x0000, /* R39 - Comparator Interrupt Status Mask */
+ 0x0040, /* R40 - Clock Control 1 */
+ 0x0000, /* R41 - Clock Control 2 */
+ 0x3A00, /* R42 - FLL Control 1 */
+ 0x7086, /* R43 - FLL Control 2 */
+ 0xC226, /* R44 - FLL Control 3 */
+ 0x0000, /* R45 - FLL Control 4 */
+ 0x0000, /* R46 */
+ 0x0000, /* R47 */
+ 0x0000, /* R48 - DAC Control */
+ 0x0000, /* R49 */
+ 0x00C0, /* R50 - DAC Digital Volume L */
+ 0x00C0, /* R51 - DAC Digital Volume R */
+ 0x0000, /* R52 */
+ 0x0040, /* R53 - DAC LR Rate */
+ 0x0000, /* R54 - DAC Clock Control */
+ 0x0000, /* R55 */
+ 0x0000, /* R56 */
+ 0x0000, /* R57 */
+ 0x4000, /* R58 - DAC Mute */
+ 0x0000, /* R59 - DAC Mute Volume */
+ 0x0000, /* R60 - DAC Side */
+ 0x0000, /* R61 */
+ 0x0000, /* R62 */
+ 0x0000, /* R63 */
+ 0x8000, /* R64 - ADC Control */
+ 0x0000, /* R65 */
+ 0x00C0, /* R66 - ADC Digital Volume L */
+ 0x00C0, /* R67 - ADC Digital Volume R */
+ 0x0000, /* R68 - ADC Divider */
+ 0x0000, /* R69 */
+ 0x0040, /* R70 - ADC LR Rate */
+ 0x0000, /* R71 */
+ 0x0303, /* R72 - Input Control */
+ 0x0000, /* R73 - IN3 Input Control */
+ 0x0000, /* R74 - Mic Bias Control */
+ 0x0000, /* R75 */
+ 0x0000, /* R76 - Output Control */
+ 0x0000, /* R77 - Jack Detect */
+ 0x0000, /* R78 - Anti Pop Control */
+ 0x0000, /* R79 */
+ 0x0040, /* R80 - Left Input Volume */
+ 0x0040, /* R81 - Right Input Volume */
+ 0x0000, /* R82 */
+ 0x0000, /* R83 */
+ 0x0000, /* R84 */
+ 0x0000, /* R85 */
+ 0x0000, /* R86 */
+ 0x0000, /* R87 */
+ 0x0800, /* R88 - Left Mixer Control */
+ 0x1000, /* R89 - Right Mixer Control */
+ 0x0000, /* R90 */
+ 0x0000, /* R91 */
+ 0x0000, /* R92 - OUT3 Mixer Control */
+ 0x0000, /* R93 - OUT4 Mixer Control */
+ 0x0000, /* R94 */
+ 0x0000, /* R95 */
+ 0x0000, /* R96 - Output Left Mixer Volume */
+ 0x0000, /* R97 - Output Right Mixer Volume */
+ 0x0000, /* R98 - Input Mixer Volume L */
+ 0x0000, /* R99 - Input Mixer Volume R */
+ 0x0000, /* R100 - Input Mixer Volume */
+ 0x0000, /* R101 */
+ 0x0000, /* R102 */
+ 0x0000, /* R103 */
+ 0x00E4, /* R104 - OUT1L Volume */
+ 0x00E4, /* R105 - OUT1R Volume */
+ 0x00E4, /* R106 - OUT2L Volume */
+ 0x02E4, /* R107 - OUT2R Volume */
+ 0x0000, /* R108 */
+ 0x0000, /* R109 */
+ 0x0000, /* R110 */
+ 0x0000, /* R111 - BEEP Volume */
+ 0x0A00, /* R112 - AI Formating */
+ 0x0000, /* R113 - ADC DAC COMP */
+ 0x0020, /* R114 - AI ADC Control */
+ 0x0020, /* R115 - AI DAC Control */
+ 0x0000, /* R116 */
+ 0x0000, /* R117 */
+ 0x0000, /* R118 */
+ 0x0000, /* R119 */
+ 0x0000, /* R120 */
+ 0x0000, /* R121 */
+ 0x0000, /* R122 */
+ 0x0000, /* R123 */
+ 0x0000, /* R124 */
+ 0x0000, /* R125 */
+ 0x0000, /* R126 */
+ 0x0000, /* R127 */
+ 0x1FFF, /* R128 - GPIO Debounce */
+ 0x0010, /* R129 - GPIO Pin pull up Control */
+ 0x0000, /* R130 - GPIO Pull down Control */
+ 0x0000, /* R131 - GPIO Interrupt Mode */
+ 0x0000, /* R132 */
+ 0x0000, /* R133 - GPIO Control */
+ 0x0BFB, /* R134 - GPIO Configuration (i/o) */
+ 0x0FFD, /* R135 - GPIO Pin Polarity / Type */
+ 0x0000, /* R136 */
+ 0x0000, /* R137 */
+ 0x0000, /* R138 */
+ 0x0000, /* R139 */
+ 0x0310, /* R140 - GPIO Function Select 1 */
+ 0x0001, /* R141 - GPIO Function Select 2 */
+ 0x2300, /* R142 - GPIO Function Select 3 */
+ 0x0003, /* R143 - GPIO Function Select 4 */
+ 0x0000, /* R144 - Digitiser Control (1) */
+ 0x0002, /* R145 - Digitiser Control (2) */
+ 0x0000, /* R146 */
+ 0x0000, /* R147 */
+ 0x0000, /* R148 */
+ 0x0000, /* R149 */
+ 0x0000, /* R150 */
+ 0x0000, /* R151 */
+ 0x7000, /* R152 - AUX1 Readback */
+ 0x7000, /* R153 - AUX2 Readback */
+ 0x7000, /* R154 - AUX3 Readback */
+ 0x7000, /* R155 - AUX4 Readback */
+ 0x0000, /* R156 - USB Voltage Readback */
+ 0x0000, /* R157 - LINE Voltage Readback */
+ 0x0000, /* R158 - BATT Voltage Readback */
+ 0x0000, /* R159 - Chip Temp Readback */
+ 0x0000, /* R160 */
+ 0x0000, /* R161 */
+ 0x0000, /* R162 */
+ 0x0000, /* R163 - Generic Comparator Control */
+ 0x0000, /* R164 - Generic comparator 1 */
+ 0x0000, /* R165 - Generic comparator 2 */
+ 0x0000, /* R166 - Generic comparator 3 */
+ 0x0000, /* R167 - Generic comparator 4 */
+ 0xA00F, /* R168 - Battery Charger Control 1 */
+ 0x0B06, /* R169 - Battery Charger Control 2 */
+ 0x0000, /* R170 - Battery Charger Control 3 */
+ 0x0000, /* R171 */
+ 0x0000, /* R172 - Current Sink Driver A */
+ 0x0000, /* R173 - CSA Flash control */
+ 0x0000, /* R174 - Current Sink Driver B */
+ 0x0000, /* R175 - CSB Flash control */
+ 0x0000, /* R176 - DCDC/LDO requested */
+ 0x032D, /* R177 - DCDC Active options */
+ 0x0000, /* R178 - DCDC Sleep options */
+ 0x0025, /* R179 - Power-check comparator */
+ 0x0006, /* R180 - DCDC1 Control */
+ 0x0400, /* R181 - DCDC1 Timeouts */
+ 0x1006, /* R182 - DCDC1 Low Power */
+ 0x0018, /* R183 - DCDC2 Control */
+ 0x0000, /* R184 - DCDC2 Timeouts */
+ 0x0000, /* R185 */
+ 0x0050, /* R186 - DCDC3 Control */
+ 0x0C00, /* R187 - DCDC3 Timeouts */
+ 0x0006, /* R188 - DCDC3 Low Power */
+ 0x000E, /* R189 - DCDC4 Control */
+ 0x0400, /* R190 - DCDC4 Timeouts */
+ 0x0006, /* R191 - DCDC4 Low Power */
+ 0x0008, /* R192 - DCDC5 Control */
+ 0x0000, /* R193 - DCDC5 Timeouts */
+ 0x0000, /* R194 */
+ 0x0029, /* R195 - DCDC6 Control */
+ 0x0800, /* R196 - DCDC6 Timeouts */
+ 0x0006, /* R197 - DCDC6 Low Power */
+ 0x0000, /* R198 */
+ 0x0003, /* R199 - Limit Switch Control */
+ 0x001D, /* R200 - LDO1 Control */
+ 0x1000, /* R201 - LDO1 Timeouts */
+ 0x001C, /* R202 - LDO1 Low Power */
+ 0x0017, /* R203 - LDO2 Control */
+ 0x1000, /* R204 - LDO2 Timeouts */
+ 0x001C, /* R205 - LDO2 Low Power */
+ 0x0006, /* R206 - LDO3 Control */
+ 0x1000, /* R207 - LDO3 Timeouts */
+ 0x001C, /* R208 - LDO3 Low Power */
+ 0x0010, /* R209 - LDO4 Control */
+ 0x1000, /* R210 - LDO4 Timeouts */
+ 0x001C, /* R211 - LDO4 Low Power */
+ 0x0000, /* R212 */
+ 0x0000, /* R213 */
+ 0x0000, /* R214 */
+ 0x0000, /* R215 - VCC_FAULT Masks */
+ 0x001F, /* R216 - Main Bandgap Control */
+ 0x0000, /* R217 - OSC Control */
+ 0x9000, /* R218 - RTC Tick Control */
+ 0x0000, /* R219 - Security1 */
+ 0x4000, /* R220 */
+ 0x0000, /* R221 */
+ 0x0000, /* R222 */
+ 0x0000, /* R223 */
+ 0x0000, /* R224 - Signal overrides */
+ 0x0000, /* R225 - DCDC/LDO status */
+ 0x0000, /* R226 - Charger Overides/status */
+ 0x0000, /* R227 - misc overrides */
+ 0x0000, /* R228 - Supply overrides/status 1 */
+ 0x0000, /* R229 - Supply overrides/status 2 */
+ 0xE000, /* R230 - GPIO Pin Status */
+ 0x0000, /* R231 - comparotor overrides */
+ 0x0000, /* R232 */
+ 0x0000, /* R233 - State Machine status */
+ 0x1200, /* R234 */
+ 0x0000, /* R235 */
+ 0x8000, /* R236 */
+ 0x0000, /* R237 */
+ 0x0000, /* R238 */
+ 0x0000, /* R239 */
+ 0x0003, /* R240 */
+ 0x0000, /* R241 */
+ 0x0000, /* R242 */
+ 0x0004, /* R243 */
+ 0x0300, /* R244 */
+ 0x0000, /* R245 */
+ 0x0200, /* R246 */
+ 0x0000, /* R247 */
+ 0x1000, /* R248 - DCDC1 Test Controls */
+ 0x5000, /* R249 */
+ 0x1000, /* R250 - DCDC3 Test Controls */
+ 0x1000, /* R251 - DCDC4 Test Controls */
+ 0x5100, /* R252 */
+ 0x1000, /* R253 - DCDC6 Test Controls */
+};
+#endif
+
/* The register defaults for the config mode used must be compiled in but
* due to the impact on kernel size it is possible to disable
*/
@@ -1307,14 +3403,14 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
{ 0xFF3F, 0xE03F, 0x0000 }, /* R216 - Main Bandgap Control */
{ 0xEF2F, 0xE02F, 0x0000 }, /* R217 - OSC Control */
{ 0xF3FF, 0xB3FF, 0xc000 }, /* R218 - RTC Tick Control */
- { 0xFFFF, 0xFFFF, 0xFFFF }, /* R219 */
+ { 0xFFFF, 0xFFFF, 0x0000 }, /* R219 - Security */
{ 0x09FF, 0x01FF, 0x0000 }, /* R220 - RAM BIST 1 */
{ 0x0000, 0x0000, 0x0000 }, /* R221 */
{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R222 */
{ 0xFFFF, 0xFFFF, 0xFFFF }, /* R223 */
{ 0x0000, 0x0000, 0x0000 }, /* R224 */
{ 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */
- { 0x0000, 0x0000, 0x0000 }, /* R226 */
+ { 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */
{ 0x0000, 0x0000, 0xFFFF }, /* R227 */
{ 0x0000, 0x0000, 0x0000 }, /* R228 */
{ 0x0000, 0x0000, 0x0000 }, /* R229 */
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c
index 6a0cedb5bb8a..cf30d06a0104 100644
--- a/drivers/mfd/wm8400-core.c
+++ b/drivers/mfd/wm8400-core.c
@@ -15,6 +15,7 @@
#include <linux/bug.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
+#include <linux/mfd/core.h>
#include <linux/mfd/wm8400-private.h>
#include <linux/mfd/wm8400-audio.h>
@@ -239,6 +240,16 @@ void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
}
EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache);
+static int wm8400_register_codec(struct wm8400 *wm8400)
+{
+ struct mfd_cell cell = {
+ .name = "wm8400-codec",
+ .driver_data = wm8400,
+ };
+
+ return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
+}
+
/*
* wm8400_init - Generic initialisation
*
@@ -296,24 +307,32 @@ static int wm8400_init(struct wm8400 *wm8400,
reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT;
dev_info(wm8400->dev, "WM8400 revision %x\n", reg);
+ ret = wm8400_register_codec(wm8400);
+ if (ret != 0) {
+ dev_err(wm8400->dev, "Failed to register codec\n");
+ goto err_children;
+ }
+
if (pdata && pdata->platform_init) {
ret = pdata->platform_init(wm8400->dev);
- if (ret != 0)
+ if (ret != 0) {
dev_err(wm8400->dev, "Platform init failed: %d\n",
ret);
+ goto err_children;
+ }
} else
dev_warn(wm8400->dev, "No platform initialisation supplied\n");
+ return 0;
+
+err_children:
+ mfd_remove_devices(wm8400->dev);
return ret;
}
static void wm8400_release(struct wm8400 *wm8400)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(wm8400->regulators); i++)
- if (wm8400->regulators[i].name)
- platform_device_unregister(&wm8400->regulators[i]);
+ mfd_remove_devices(wm8400->dev);
}
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index fee7304102af..c64e6798878a 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -87,14 +87,6 @@ config PHANTOM
If you choose to build module, its name will be phantom. If unsure,
say N here.
-config EEPROM_93CX6
- tristate "EEPROM 93CX6 support"
- ---help---
- This is a driver for the EEPROM chipsets 93c46 and 93c66.
- The driver supports both read as well as write commands.
-
- If unsure, say N.
-
config SGI_IOC4
tristate "SGI IOC4 Base IO support"
depends on PCI
@@ -120,7 +112,7 @@ config TIFM_CORE
cards are supported via 'MMC/SD Card support: TI Flash Media MMC/SD
Interface support (MMC_TIFM_SD)'.
- To compile this driver as a module, choose M here: the module will
+ To compile this driver as a module, choose M here: the module will
be called tifm_core.
config TIFM_7XX1
@@ -133,100 +125,9 @@ config TIFM_7XX1
To make actual use of the device, you will have to select some
flash card format drivers, as outlined in the TIFM_CORE Help.
- To compile this driver as a module, choose M here: the module will
+ To compile this driver as a module, choose M here: the module will
be called tifm_7xx1.
-config ACER_WMI
- tristate "Acer WMI Laptop Extras (EXPERIMENTAL)"
- depends on X86
- depends on EXPERIMENTAL
- depends on ACPI
- depends on LEDS_CLASS
- depends on NEW_LEDS
- depends on BACKLIGHT_CLASS_DEVICE
- depends on SERIO_I8042
- depends on RFKILL
- select ACPI_WMI
- ---help---
- This is a driver for newer Acer (and Wistron) laptops. It adds
- wireless radio and bluetooth control, and on some laptops,
- exposes the mail LED and LCD backlight.
-
- For more information about this driver see
- <file:Documentation/laptops/acer-wmi.txt>
-
- If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
- here.
-
-config ASUS_LAPTOP
- tristate "Asus Laptop Extras (EXPERIMENTAL)"
- depends on X86
- depends on ACPI
- depends on EXPERIMENTAL && !ACPI_ASUS
- depends on LEDS_CLASS
- depends on NEW_LEDS
- depends on BACKLIGHT_CLASS_DEVICE
- ---help---
- This is the new Linux driver for Asus laptops. It may also support some
- MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
- standard ACPI events that go through /proc/acpi/events. It also adds
- support for video output switching, LCD backlight control, Bluetooth and
- Wlan control, and most importantly, allows you to blink those fancy LEDs.
-
- For more information and a userspace daemon for handling the extra
- buttons see <http://acpi4asus.sf.net/>.
-
- If you have an ACPI-compatible ASUS laptop, say Y or M here.
-
-config FUJITSU_LAPTOP
- tristate "Fujitsu Laptop Extras"
- depends on X86
- depends on ACPI
- depends on INPUT
- depends on BACKLIGHT_CLASS_DEVICE
- ---help---
- This is a driver for laptops built by Fujitsu:
-
- * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
- * Possibly other Fujitsu laptop models
- * Tested with S6410 and S7020
-
- It adds support for LCD brightness control and some hotkeys.
-
- If you have a Fujitsu laptop, say Y or M here.
-
-config FUJITSU_LAPTOP_DEBUG
- bool "Verbose debug mode for Fujitsu Laptop Extras"
- depends on FUJITSU_LAPTOP
- default n
- ---help---
- Enables extra debug output from the fujitsu extras driver, at the
- expense of a slight increase in driver size.
-
- If you are not sure, say N here.
-
-config TC1100_WMI
- tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
- depends on X86 && !X86_64
- depends on EXPERIMENTAL
- depends on ACPI
- select ACPI_WMI
- ---help---
- This is a driver for the WMI extensions (wireless and bluetooth power
- control) of the HP Compaq TC1100 tablet.
-
-config HP_WMI
- tristate "HP WMI extras"
- depends on ACPI_WMI
- depends on INPUT
- depends on RFKILL
- help
- Say Y here if you want to support WMI-based hotkeys on HP laptops and
- to read data from WMI such as docking or ambient light sensor state.
-
- To compile this driver as a module, choose M here: the module will
- be called hp-wmi.
-
config ICS932S401
tristate "Integrated Circuits ICS932S401"
depends on I2C && EXPERIMENTAL
@@ -237,170 +138,6 @@ config ICS932S401
This driver can also be built as a module. If so, the module
will be called ics932s401.
-config MSI_LAPTOP
- tristate "MSI Laptop Extras"
- depends on X86
- depends on ACPI
- depends on BACKLIGHT_CLASS_DEVICE
- ---help---
- This is a driver for laptops built by MSI (MICRO-STAR
- INTERNATIONAL):
-
- MSI MegaBook S270 (MS-1013)
- Cytron/TCM/Medion/Tchibo MD96100/SAM2000
-
- It adds support for Bluetooth, WLAN and LCD brightness control.
-
- More information about this driver is available at
- <http://0pointer.de/lennart/tchibo.html>.
-
- If you have an MSI S270 laptop, say Y or M here.
-
-config PANASONIC_LAPTOP
- tristate "Panasonic Laptop Extras"
- depends on X86 && INPUT && ACPI
- depends on BACKLIGHT_CLASS_DEVICE
- ---help---
- This driver adds support for access to backlight control and hotkeys
- on Panasonic Let's Note laptops.
-
- If you have a Panasonic Let's note laptop (such as the R1(N variant),
- R2, R3, R5, T2, W2 and Y2 series), say Y.
-
-config COMPAL_LAPTOP
- tristate "Compal Laptop Extras"
- depends on X86
- depends on ACPI
- depends on BACKLIGHT_CLASS_DEVICE
- ---help---
- This is a driver for laptops built by Compal:
-
- Compal FL90/IFL90
- Compal FL91/IFL91
- Compal FL92/JFL92
- Compal FT00/IFT00
-
- It adds support for Bluetooth, WLAN and LCD brightness control.
-
- If you have an Compal FL9x/IFL9x/FT00 laptop, say Y or M here.
-
-config SONY_LAPTOP
- tristate "Sony Laptop Extras"
- depends on X86 && ACPI
- select BACKLIGHT_CLASS_DEVICE
- depends on INPUT
- ---help---
- This mini-driver drives the SNC and SPIC devices present in the ACPI
- BIOS of the Sony Vaio laptops.
-
- It gives access to some extra laptop functionalities like Bluetooth,
- screen brightness control, Fn keys and allows powering on/off some
- devices.
-
- Read <file:Documentation/laptops/sony-laptop.txt> for more information.
-
-config SONYPI_COMPAT
- bool "Sonypi compatibility"
- depends on SONY_LAPTOP
- ---help---
- Build the sonypi driver compatibility code into the sony-laptop driver.
-
-config THINKPAD_ACPI
- tristate "ThinkPad ACPI Laptop Extras"
- depends on X86 && ACPI
- select BACKLIGHT_LCD_SUPPORT
- select BACKLIGHT_CLASS_DEVICE
- select HWMON
- select NVRAM
- select INPUT
- select NEW_LEDS
- select LEDS_CLASS
- select NET
- select RFKILL
- ---help---
- This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
- support for Fn-Fx key combinations, Bluetooth control, video
- output switching, ThinkLight control, UltraBay eject and more.
- For more information about this driver see
- <file:Documentation/laptops/thinkpad-acpi.txt> and
- <http://ibm-acpi.sf.net/> .
-
- This driver was formerly known as ibm-acpi.
-
- If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
-
-config THINKPAD_ACPI_DEBUG
- bool "Verbose debug mode"
- depends on THINKPAD_ACPI
- default n
- ---help---
- Enables extra debugging information, at the expense of a slightly
- increase in driver size.
-
- If you are not sure, say N here.
-
-config THINKPAD_ACPI_DOCK
- bool "Legacy Docking Station Support"
- depends on THINKPAD_ACPI
- depends on ACPI_DOCK=n
- default n
- ---help---
- Allows the thinkpad_acpi driver to handle docking station events.
- This support was made obsolete by the generic ACPI docking station
- support (CONFIG_ACPI_DOCK). It will allow locking and removing the
- laptop from the docking station, but will not properly connect PCI
- devices.
-
- If you are not sure, say N here.
-
-config THINKPAD_ACPI_BAY
- bool "Legacy Removable Bay Support"
- depends on THINKPAD_ACPI
- default y
- ---help---
- Allows the thinkpad_acpi driver to handle removable bays. It will
- electrically disable the device in the bay, and also generate
- notifications when the bay lever is ejected or inserted.
-
- If you are not sure, say Y here.
-
-config THINKPAD_ACPI_VIDEO
- bool "Video output control support"
- depends on THINKPAD_ACPI
- default y
- ---help---
- Allows the thinkpad_acpi driver to provide an interface to control
- the various video output ports.
-
- This feature often won't work well, depending on ThinkPad model,
- display state, video output devices in use, whether there is a X
- server running, phase of the moon, and the current mood of
- Schroedinger's cat. If you can use X.org's RandR to control
- your ThinkPad's video output ports instead of this feature,
- don't think twice: do it and say N here to save some memory.
-
- If you are not sure, say Y here.
-
-config THINKPAD_ACPI_HOTKEY_POLL
- bool "Support NVRAM polling for hot keys"
- depends on THINKPAD_ACPI
- default y
- ---help---
- Some thinkpad models benefit from NVRAM polling to detect a few of
- the hot key press events. If you know your ThinkPad model does not
- need to do NVRAM polling to support any of the hot keys you use,
- unselecting this option will save about 1kB of memory.
-
- ThinkPads T40 and newer, R52 and newer, and X31 and newer are
- unlikely to need NVRAM polling in their latest BIOS versions.
-
- NVRAM polling can detect at most the following keys: ThinkPad/Access
- IBM, Zoom, Switch Display (fn+F7), ThinkLight, Volume up/down/mute,
- Brightness up/down, Display Expand (fn+F8), Hibernate (fn+F12).
-
- If you are not sure, say Y here. The driver enables polling only if
- it is strictly necessary to do so.
-
config ATMEL_SSC
tristate "Device driver for Atmel SSC peripheral"
depends on AVR32 || ARCH_AT91
@@ -413,31 +150,6 @@ config ATMEL_SSC
If unsure, say N.
-config INTEL_MENLOW
- tristate "Thermal Management driver for Intel menlow platform"
- depends on ACPI_THERMAL
- select THERMAL
- depends on X86
- ---help---
- ACPI thermal management enhancement driver on
- Intel Menlow platform.
-
- If unsure, say N.
-
-config EEEPC_LAPTOP
- tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
- depends on X86
- depends on ACPI
- depends on BACKLIGHT_CLASS_DEVICE
- depends on HWMON
- depends on EXPERIMENTAL
- depends on RFKILL
- ---help---
- This driver supports the Fn-Fx keys on Eee PC laptops.
- It also adds the ability to switch camera/wlan on/off.
-
- If you have an Eee PC laptop, say Y or M here.
-
config ENCLOSURE_SERVICES
tristate "Enclosure Services"
default n
@@ -498,6 +210,20 @@ config SGI_GRU_DEBUG
This option enables addition debugging code for the SGI GRU driver. If
you are unsure, say N.
+config DELL_LAPTOP
+ tristate "Dell Laptop Extras (EXPERIMENTAL)"
+ depends on X86
+ depends on DCDBAS
+ depends on EXPERIMENTAL
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on RFKILL
+ depends on POWER_SUPPLY
+ default n
+ ---help---
+ This driver adds support for rfkill and backlight control to Dell
+ laptops.
+
source "drivers/misc/c2port/Kconfig"
+source "drivers/misc/eeprom/Kconfig"
endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 817f7f5ab3bd..bc1199830554 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -1,35 +1,22 @@
#
# Makefile for misc devices that really don't fit anywhere else.
#
-obj- := misc.o # Dummy rule to force built-in.o to be made
obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
-obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
-obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
-obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
-obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
-obj-$(CONFIG_ACER_WMI) += acer-wmi.o
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
-obj-$(CONFIG_HP_WMI) += hp-wmi.o
obj-$(CONFIG_ICS932S401) += ics932s401.o
-obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
-obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
-obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
-obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
-obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
-obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
-obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
obj-$(CONFIG_KGDB_TESTS) += kgdbts.o
obj-$(CONFIG_SGI_XP) += sgi-xp/
obj-$(CONFIG_SGI_GRU) += sgi-gru/
obj-$(CONFIG_HP_ILO) += hpilo.o
obj-$(CONFIG_C2PORT) += c2port/
+obj-y += eeprom/
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index bf5e4d065436..558bf3f2c276 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -35,7 +35,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
if (!ssc_valid) {
spin_unlock(&user_lock);
- dev_dbg(&ssc->pdev->dev, "could not find requested device\n");
+ pr_err("ssc: ssc%d platform device is missing\n", ssc_num);
return ERR_PTR(-ENODEV);
}
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
new file mode 100644
index 000000000000..c76df8cda5ef
--- /dev/null
+++ b/drivers/misc/eeprom/Kconfig
@@ -0,0 +1,59 @@
+menu "EEPROM support"
+
+config EEPROM_AT24
+ tristate "I2C EEPROMs from most vendors"
+ depends on I2C && SYSFS && EXPERIMENTAL
+ help
+ Enable this driver to get read/write support to most I2C EEPROMs,
+ after you configure the driver to know about each EEPROM on
+ your target board. Use these generic chip names, instead of
+ vendor-specific ones like at24c64 or 24lc02:
+
+ 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
+ 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
+
+ Unless you like data loss puzzles, always be sure that any chip
+ you configure as a 24c32 (32 kbit) or larger is NOT really a
+ 24c16 (16 kbit) or smaller, and vice versa. Marking the chip
+ as read-only won't help recover from this. Also, if your chip
+ has any software write-protect mechanism you may want to review the
+ code to make sure this driver won't turn it on by accident.
+
+ If you use this with an SMBus adapter instead of an I2C adapter,
+ full functionality is not available. Only smaller devices are
+ supported (24c16 and below, max 4 kByte).
+
+ This driver can also be built as a module. If so, the module
+ will be called at24.
+
+config EEPROM_AT25
+ tristate "SPI EEPROMs from most vendors"
+ depends on SPI && SYSFS
+ help
+ Enable this driver to get read/write support to most SPI EEPROMs,
+ after you configure the board init code to know about each eeprom
+ on your target board.
+
+ This driver can also be built as a module. If so, the module
+ will be called at25.
+
+config EEPROM_LEGACY
+ tristate "Old I2C EEPROM reader"
+ depends on I2C && SYSFS
+ help
+ If you say yes here you get read-only access to the EEPROM data
+ available on modern memory DIMMs and Sony Vaio laptops via I2C. Such
+ EEPROMs could theoretically be available on other devices as well.
+
+ This driver can also be built as a module. If so, the module
+ will be called eeprom.
+
+config EEPROM_93CX6
+ tristate "EEPROM 93CX6 support"
+ help
+ This is a driver for the EEPROM chipsets 93c46 and 93c66.
+ The driver supports both read as well as write commands.
+
+ If unsure, say N.
+
+endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
new file mode 100644
index 000000000000..539dd8f88128
--- /dev/null
+++ b/drivers/misc/eeprom/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_EEPROM_AT24) += at24.o
+obj-$(CONFIG_EEPROM_AT25) += at25.o
+obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
+obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/i2c/chips/at24.c b/drivers/misc/eeprom/at24.c
index d4775528abc6..d4775528abc6 100644
--- a/drivers/i2c/chips/at24.c
+++ b/drivers/misc/eeprom/at24.c
diff --git a/drivers/spi/at25.c b/drivers/misc/eeprom/at25.c
index 290dbe99647a..290dbe99647a 100644
--- a/drivers/spi/at25.c
+++ b/drivers/misc/eeprom/at25.c
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/misc/eeprom/eeprom.c
index 2c27193aeaa0..2c27193aeaa0 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/misc/eeprom/eeprom.c
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c
index 15b1780025c8..15b1780025c8 100644
--- a/drivers/misc/eeprom_93cx6.c
+++ b/drivers/misc/eeprom/eeprom_93cx6.c
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 0736cff9d97a..3cf61ece71d7 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -119,7 +119,7 @@ enclosure_register(struct device *dev, const char *name, int components,
edev->edev.class = &enclosure_class;
edev->edev.parent = get_device(dev);
edev->cb = cb;
- snprintf(edev->edev.bus_id, BUS_ID_SIZE, "%s", name);
+ dev_set_name(&edev->edev, name);
err = device_register(&edev->edev);
if (err)
goto err;
@@ -170,7 +170,7 @@ EXPORT_SYMBOL_GPL(enclosure_unregister);
static void enclosure_link_name(struct enclosure_component *cdev, char *name)
{
strcpy(name, "enclosure_device:");
- strcat(name, cdev->cdev.bus_id);
+ strcat(name, dev_name(&cdev->cdev));
}
static void enclosure_remove_links(struct enclosure_component *cdev)
@@ -256,9 +256,9 @@ enclosure_component_register(struct enclosure_device *edev,
cdev = &ecomp->cdev;
cdev->parent = get_device(&edev->edev);
if (name)
- snprintf(cdev->bus_id, BUS_ID_SIZE, "%s", name);
+ dev_set_name(cdev, name);
else
- snprintf(cdev->bus_id, BUS_ID_SIZE, "%u", number);
+ dev_set_name(cdev, "%u", number);
cdev->release = enclosure_component_release;
cdev->groups = enclosure_groups;
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c
index 05e298289238..f26667a7abf7 100644
--- a/drivers/misc/hpilo.c
+++ b/drivers/misc/hpilo.c
@@ -207,7 +207,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data)
&device_ccb->recv_ctrl);
/* give iLO some time to process stop request */
- for (retries = 1000; retries > 0; retries--) {
+ for (retries = MAX_WAIT; retries > 0; retries--) {
doorbell_set(driver_ccb);
udelay(1);
if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A))
@@ -309,7 +309,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
doorbell_clr(driver_ccb);
/* make sure iLO is really handling requests */
- for (i = 1000; i > 0; i--) {
+ for (i = MAX_WAIT; i > 0; i--) {
if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL))
break;
udelay(1);
@@ -326,7 +326,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot)
return 0;
free:
- pci_free_consistent(pdev, data->dma_size, data->dma_va, data->dma_pa);
+ ilo_ccb_close(pdev, data);
out:
return error;
}
@@ -758,7 +758,7 @@ static void __exit ilo_exit(void)
class_destroy(ilo_class);
}
-MODULE_VERSION("0.05");
+MODULE_VERSION("0.06");
MODULE_ALIAS(ILO_NAME);
MODULE_DESCRIPTION(ILO_NAME);
MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>");
diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h
index a281207696c1..b64a20ef07e3 100644
--- a/drivers/misc/hpilo.h
+++ b/drivers/misc/hpilo.h
@@ -19,6 +19,8 @@
#define MAX_ILO_DEV 1
/* max number of files */
#define MAX_OPEN (MAX_CCB * MAX_ILO_DEV)
+/* spin counter for open/close delay */
+#define MAX_WAIT 10000
/*
* Per device, used to track global memory allocations.
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c
index fda6a4d3bf23..68a0a5b94795 100644
--- a/drivers/misc/ibmasm/event.c
+++ b/drivers/misc/ibmasm/event.c
@@ -50,7 +50,7 @@ static void wake_up_event_readers(struct service_processor *sp)
* Store the event in the circular event buffer, wake up any sleeping
* event readers.
* There is no reader marker in the buffer, therefore readers are
- * responsible for keeping up with the writer, or they will loose events.
+ * responsible for keeping up with the writer, or they will lose events.
*/
void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size)
{
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 22a7e8ba211d..de966a6fb7e6 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -146,8 +146,6 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
if (ret) {
ret->i_mode = mode;
- ret->i_uid = ret->i_gid = 0;
- ret->i_blocks = 0;
ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
}
return ret;
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index b5f6add34b0b..dc14b0b9cbfa 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -104,8 +104,7 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
}
sp->irq = pdev->irq;
- sp->base_address = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+ sp->base_address = pci_ioremap_bar(pdev, 0);
if (!sp->base_address) {
dev_err(sp->dev, "Failed to ioremap pci memory\n");
result = -ENODEV;
diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c
index 6f76573e7c8a..60b0b1a4fb3a 100644
--- a/drivers/misc/ioc4.c
+++ b/drivers/misc/ioc4.c
@@ -269,6 +269,16 @@ ioc4_variant(struct ioc4_driver_data *idd)
return IOC4_VARIANT_PCI_RT;
}
+static void
+ioc4_load_modules(struct work_struct *work)
+{
+ /* arg just has to be freed */
+
+ request_module("sgiioc4");
+
+ kfree(work);
+}
+
/* Adds a new instance of an IOC4 card */
static int
ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
@@ -378,6 +388,30 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
}
mutex_unlock(&ioc4_mutex);
+ /* Request sgiioc4 IDE driver on boards that bring that functionality
+ * off of IOC4. The root filesystem may be hosted on a drive connected
+ * to IOC4, so we need to make sure the sgiioc4 driver is loaded as it
+ * won't be picked up by modprobes due to the ioc4 module owning the
+ * PCI device.
+ */
+ if (idd->idd_variant != IOC4_VARIANT_PCI_RT) {
+ struct work_struct *work;
+ work = kzalloc(sizeof(struct work_struct), GFP_KERNEL);
+ if (!work) {
+ printk(KERN_WARNING
+ "%s: IOC4 unable to allocate memory for "
+ "load of sub-modules.\n", __func__);
+ } else {
+ /* Request the module from a work procedure as the
+ * modprobe goes out to a userland helper and that
+ * will hang if done directly from ioc4_probe().
+ */
+ printk(KERN_INFO "IOC4 loading sgiioc4 submodule\n");
+ INIT_WORK(work, ioc4_load_modules);
+ schedule_work(work);
+ }
+ }
+
return 0;
out_misc_region:
@@ -462,6 +496,8 @@ ioc4_init(void)
static void __devexit
ioc4_exit(void)
{
+ /* Ensure ioc4_load_modules() has completed before exiting */
+ flush_scheduled_work();
pci_unregister_driver(&ioc4_driver);
}
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index abdebe347383..fa57b67593ae 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- * You need an userspace library to cooperate with this driver. It (and other
+ * You need a userspace library to cooperate with this driver. It (and other
* info) may be obtained here:
* http://www.fi.muni.cz/~xslaby/phantom.html
* or alternatively, you might use OpenHaptics provided by Sensable.
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index e11e1ac50900..3d2fc216bae5 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -29,7 +29,7 @@ static struct device_driver gru_driver = {
};
static struct device gru_device = {
- .bus_id = {0},
+ .init_name = "",
.driver = &gru_driver,
};
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index 9a2e77172d94..16f8dcab2da4 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -25,7 +25,7 @@ struct device_driver xp_dbg_name = {
};
struct device xp_dbg_subname = {
- .bus_id = {0}, /* set to "" */
+ .init_name = "", /* set to "" */
.driver = &xp_dbg_name
};
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
index a5bd658c2e83..275b78896a73 100644
--- a/drivers/misc/sgi-xp/xpc.h
+++ b/drivers/misc/sgi-xp/xpc.h
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved.
*/
/*
@@ -514,7 +514,8 @@ struct xpc_channel_uv {
/* partition's notify mq */
struct xpc_send_msg_slot_uv *send_msg_slots;
- struct xpc_notify_mq_msg_uv *recv_msg_slots;
+ void *recv_msg_slots; /* each slot will hold a xpc_notify_mq_msg_uv */
+ /* structure plus the user's payload */
struct xpc_fifo_head_uv msg_slot_free_list;
struct xpc_fifo_head_uv recv_msg_list; /* deliverable payloads */
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
index 9cd2ebe2a3b6..45fd653dbe31 100644
--- a/drivers/misc/sgi-xp/xpc_channel.c
+++ b/drivers/misc/sgi-xp/xpc_channel.c
@@ -49,9 +49,6 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING))
return;
-
- DBUG_ON(ch->local_msgqueue == NULL);
- DBUG_ON(ch->remote_msgqueue == NULL);
}
if (!(ch->flags & XPC_C_OPENREPLY)) {
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index e8d5cfbd32c2..89218f7cfaa7 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -59,12 +59,12 @@ struct device_driver xpc_dbg_name = {
};
struct device xpc_part_dbg_subname = {
- .bus_id = {0}, /* set to "part" at xpc_init() time */
+ .init_name = "", /* set to "part" at xpc_init() time */
.driver = &xpc_dbg_name
};
struct device xpc_chan_dbg_subname = {
- .bus_id = {0}, /* set to "chan" at xpc_init() time */
+ .init_name = "", /* set to "chan" at xpc_init() time */
.driver = &xpc_dbg_name
};
@@ -1258,8 +1258,8 @@ xpc_init(void)
int ret;
struct task_struct *kthread;
- snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
- snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
+ dev_set_name(xpc_part, "part");
+ dev_set_name(xpc_chan, "chan");
if (is_shub()) {
/*
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index 73b7fb8de47a..2e975762c32b 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -899,7 +899,7 @@ xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",
part_sn2->remote_vars_pa);
- part->last_heartbeat = remote_vars->heartbeat;
+ part->last_heartbeat = remote_vars->heartbeat - 1;
dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",
part->last_heartbeat);
@@ -1106,8 +1106,6 @@ xpc_process_activate_IRQ_rcvd_sn2(void)
int n_IRQs_expected;
int n_IRQs_detected;
- DBUG_ON(xpc_activate_IRQ_rcvd == 0);
-
spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
n_IRQs_expected = xpc_activate_IRQ_rcvd;
xpc_activate_IRQ_rcvd = 0;
@@ -1726,6 +1724,7 @@ xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch)
msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue +
(get % ch->local_nentries) *
ch->entry_size);
+ DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
msg->flags = 0;
} while (++get < ch_sn2->remote_GP.get);
}
@@ -1740,11 +1739,18 @@ xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch)
struct xpc_msg_sn2 *msg;
s64 put;
- put = ch_sn2->w_remote_GP.put;
+ /* flags are zeroed when the buffer is allocated */
+ if (ch_sn2->remote_GP.put < ch->remote_nentries)
+ return;
+
+ put = max(ch_sn2->w_remote_GP.put, ch->remote_nentries);
do {
msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
(put % ch->remote_nentries) *
ch->entry_size);
+ DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
+ DBUG_ON(!(msg->flags & XPC_M_SN2_DONE));
+ DBUG_ON(msg->number != put - ch->remote_nentries);
msg->flags = 0;
} while (++put < ch_sn2->remote_GP.put);
}
@@ -1836,6 +1842,7 @@ xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
*/
xpc_clear_remote_msgqueue_flags_sn2(ch);
+ smp_wmb(); /* ensure flags have been cleared before bte_copy */
ch_sn2->w_remote_GP.put = ch_sn2->remote_GP.put;
dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
@@ -1934,7 +1941,7 @@ xpc_get_deliverable_payload_sn2(struct xpc_channel *ch)
break;
get = ch_sn2->w_local_GP.get;
- rmb(); /* guarantee that .get loads before .put */
+ smp_rmb(); /* guarantee that .get loads before .put */
if (get == ch_sn2->w_remote_GP.put)
break;
@@ -1956,11 +1963,13 @@ xpc_get_deliverable_payload_sn2(struct xpc_channel *ch)
msg = xpc_pull_remote_msg_sn2(ch, get);
- DBUG_ON(msg != NULL && msg->number != get);
- DBUG_ON(msg != NULL && (msg->flags & XPC_M_SN2_DONE));
- DBUG_ON(msg != NULL && !(msg->flags & XPC_M_SN2_READY));
+ if (msg != NULL) {
+ DBUG_ON(msg->number != get);
+ DBUG_ON(msg->flags & XPC_M_SN2_DONE);
+ DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
- payload = &msg->payload;
+ payload = &msg->payload;
+ }
break;
}
@@ -2053,7 +2062,7 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
while (1) {
put = ch_sn2->w_local_GP.put;
- rmb(); /* guarantee that .put loads before .get */
+ smp_rmb(); /* guarantee that .put loads before .get */
if (put - ch_sn2->w_remote_GP.get < ch->local_nentries) {
/* There are available message entries. We need to try
@@ -2186,7 +2195,7 @@ xpc_send_payload_sn2(struct xpc_channel *ch, u32 flags, void *payload,
* The preceding store of msg->flags must occur before the following
* load of local_GP->put.
*/
- mb();
+ smp_mb();
/* see if the message is next in line to be sent, if so send it */
@@ -2277,8 +2286,9 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
(void *)msg, msg_number, ch->partid, ch->number);
- DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->entry_size) !=
+ DBUG_ON((((u64)msg - (u64)ch->sn.sn2.remote_msgqueue) / ch->entry_size) !=
msg_number % ch->remote_nentries);
+ DBUG_ON(!(msg->flags & XPC_M_SN2_READY));
DBUG_ON(msg->flags & XPC_M_SN2_DONE);
msg->flags |= XPC_M_SN2_DONE;
@@ -2287,7 +2297,7 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
* The preceding store of msg->flags must occur before the following
* load of local_GP->get.
*/
- mb();
+ smp_mb();
/*
* See if this message is next in line to be acknowledged as having
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 91a55b1b1037..29c0502a96b2 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved.
*/
/*
@@ -1010,8 +1010,8 @@ xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
continue;
for (entry = 0; entry < nentries; entry++) {
- msg_slot = ch_uv->recv_msg_slots + entry *
- ch->entry_size;
+ msg_slot = ch_uv->recv_msg_slots +
+ entry * ch->entry_size;
msg_slot->hdr.msg_slot_number = entry;
}
@@ -1308,9 +1308,8 @@ xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
/* we're dealing with a normal message sent via the notify_mq */
ch_uv = &ch->sn.uv;
- msg_slot = (struct xpc_notify_mq_msg_uv *)((u64)ch_uv->recv_msg_slots +
- (msg->hdr.msg_slot_number % ch->remote_nentries) *
- ch->entry_size);
+ msg_slot = ch_uv->recv_msg_slots +
+ (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
BUG_ON(msg_slot->hdr.size != 0);
@@ -1423,7 +1422,7 @@ xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload,
atomic_inc(&ch->n_to_notify);
msg_slot->key = key;
- wmb(); /* a non-NULL func must hit memory after the key */
+ smp_wmb(); /* a non-NULL func must hit memory after the key */
msg_slot->func = func;
if (ch->flags & XPC_C_DISCONNECTING) {
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 8e6aa9508f46..6faefcffcb53 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 1999-2008 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1999-2009 Silicon Graphics, Inc. All rights reserved.
*/
/*
@@ -95,11 +95,6 @@ struct xpnet_pending_msg {
atomic_t use_count;
};
-/* driver specific structure pointed to by the device structure */
-struct xpnet_dev_private {
- struct net_device_stats stats;
-};
-
struct net_device *xpnet_device;
/*
@@ -138,7 +133,7 @@ struct device_driver xpnet_dbg_name = {
};
struct device xpnet_dbg_subname = {
- .bus_id = {0}, /* set to "" */
+ .init_name = "", /* set to "" */
.driver = &xpnet_dbg_name
};
@@ -153,7 +148,6 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
struct sk_buff *skb;
void *dst;
enum xp_retval ret;
- struct xpnet_dev_private *priv = netdev_priv(xpnet_device);
if (!XPNET_VALID_MSG(msg)) {
/*
@@ -161,7 +155,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
*/
xpc_received(partid, channel, (void *)msg);
- priv->stats.rx_errors++;
+ xpnet_device->stats.rx_errors++;
return;
}
@@ -176,7 +170,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
xpc_received(partid, channel, (void *)msg);
- priv->stats.rx_errors++;
+ xpnet_device->stats.rx_errors++;
return;
}
@@ -226,7 +220,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
xpc_received(partid, channel, (void *)msg);
- priv->stats.rx_errors++;
+ xpnet_device->stats.rx_errors++;
return;
}
@@ -247,8 +241,8 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
skb_end_pointer(skb), skb->len);
xpnet_device->last_rx = jiffies;
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += skb->len + ETH_HLEN;
+ xpnet_device->stats.rx_packets++;
+ xpnet_device->stats.rx_bytes += skb->len + ETH_HLEN;
netif_rx_ni(skb);
xpc_received(partid, channel, (void *)msg);
@@ -353,26 +347,6 @@ xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
}
/*
- * Required for the net_device structure.
- */
-static int
-xpnet_dev_set_config(struct net_device *dev, struct ifmap *new_map)
-{
- return 0;
-}
-
-/*
- * Return statistics to the caller.
- */
-static struct net_device_stats *
-xpnet_dev_get_stats(struct net_device *dev)
-{
- struct xpnet_dev_private *priv = netdev_priv(dev);
-
- return &priv->stats;
-}
-
-/*
* Notification that the other end has received the message and
* DMA'd the skb information. At this point, they are done with
* our side. When all recipients are done processing, we
@@ -453,7 +427,6 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct xpnet_pending_msg *queued_msg;
u64 start_addr, end_addr;
short dest_partid;
- struct xpnet_dev_private *priv = netdev_priv(dev);
u16 embedded_bytes = 0;
dev_dbg(xpnet, ">skb->head=0x%p skb->data=0x%p skb->tail=0x%p "
@@ -476,7 +449,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_warn(xpnet, "failed to kmalloc %ld bytes; dropping "
"packet\n", sizeof(struct xpnet_pending_msg));
- priv->stats.tx_errors++;
+ dev->stats.tx_errors++;
return -ENOMEM;
}
@@ -526,8 +499,8 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
kfree(queued_msg);
}
- priv->stats.tx_packets++;
- priv->stats.tx_bytes += skb->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
return 0;
}
@@ -538,12 +511,19 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
static void
xpnet_dev_tx_timeout(struct net_device *dev)
{
- struct xpnet_dev_private *priv = netdev_priv(dev);
-
- priv->stats.tx_errors++;
- return;
+ dev->stats.tx_errors++;
}
+static const struct net_device_ops xpnet_netdev_ops = {
+ .ndo_open = xpnet_dev_open,
+ .ndo_stop = xpnet_dev_stop,
+ .ndo_start_xmit = xpnet_dev_hard_start_xmit,
+ .ndo_change_mtu = xpnet_dev_change_mtu,
+ .ndo_tx_timeout = xpnet_dev_tx_timeout,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __init
xpnet_init(void)
{
@@ -563,8 +543,7 @@ xpnet_init(void)
* use ether_setup() to init the majority of our device
* structure and then override the necessary pieces.
*/
- xpnet_device = alloc_netdev(sizeof(struct xpnet_dev_private),
- XPNET_DEVICE_NAME, ether_setup);
+ xpnet_device = alloc_netdev(0, XPNET_DEVICE_NAME, ether_setup);
if (xpnet_device == NULL) {
kfree(xpnet_broadcast_partitions);
return -ENOMEM;
@@ -572,14 +551,8 @@ xpnet_init(void)
netif_carrier_off(xpnet_device);
+ xpnet_device->netdev_ops = &xpnet_netdev_ops;
xpnet_device->mtu = XPNET_DEF_MTU;
- xpnet_device->change_mtu = xpnet_dev_change_mtu;
- xpnet_device->open = xpnet_dev_open;
- xpnet_device->get_stats = xpnet_dev_get_stats;
- xpnet_device->stop = xpnet_dev_stop;
- xpnet_device->hard_start_xmit = xpnet_dev_hard_start_xmit;
- xpnet_device->tx_timeout = xpnet_dev_tx_timeout;
- xpnet_device->set_config = xpnet_dev_set_config;
/*
* Multicast assumes the LSB of the first octet is set for multicast
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 67503ea71d21..be5672a98702 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -164,7 +164,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work)
if (sock) {
printk(KERN_INFO
"%s : demand removing card from socket %u:%u\n",
- fm->dev.bus_id, fm->id, cnt);
+ dev_name(&fm->dev), fm->id, cnt);
fm->sockets[cnt] = NULL;
sock_addr = sock->addr;
spin_unlock_irqrestore(&fm->lock, flags);
@@ -354,8 +354,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
fm->has_ms_pif = tifm_7xx1_has_ms_pif;
pci_set_drvdata(dev, fm);
- fm->addr = ioremap(pci_resource_start(dev, 0),
- pci_resource_len(dev, 0));
+ fm->addr = pci_ioremap_bar(dev, 0);
if (!fm->addr)
goto err_out_free;
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index 82dc72a1484f..98bcba521da2 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -203,7 +203,7 @@ int tifm_add_adapter(struct tifm_adapter *fm)
if (rc)
return rc;
- snprintf(fm->dev.bus_id, BUS_ID_SIZE, "tifm%u", fm->id);
+ dev_set_name(&fm->dev, "tifm%u", fm->id);
rc = device_add(&fm->dev);
if (rc) {
spin_lock(&tifm_adapter_lock);
@@ -266,9 +266,8 @@ struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
sock->dev.dma_mask = fm->dev.parent->dma_mask;
sock->dev.release = tifm_free_device;
- snprintf(sock->dev.bus_id, BUS_ID_SIZE,
- "tifm_%s%u:%u", tifm_media_type_name(type, 2),
- fm->id, id);
+ dev_set_name(&sock->dev, "tifm_%s%u:%u",
+ tifm_media_type_name(type, 2), fm->id, id);
printk(KERN_INFO DRIVER_NAME
": %s card detected in socket %u:%u\n",
tifm_media_type_name(type, 0), fm->id, id);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 3d067c35185d..45b1f430685f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -145,7 +145,7 @@ struct mmc_blk_request {
static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
{
int err;
- u32 blocks;
+ __be32 blocks;
struct mmc_request mrq;
struct mmc_command cmd;
@@ -204,9 +204,24 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
if (cmd.error || data.error)
return (u32)-1;
- blocks = ntohl(blocks);
+ return ntohl(blocks);
+}
+
+static u32 get_card_status(struct mmc_card *card, struct request *req)
+{
+ struct mmc_command cmd;
+ int err;
- return blocks;
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ cmd.opcode = MMC_SEND_STATUS;
+ if (!mmc_host_is_spi(card->host))
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+ err = mmc_wait_for_cmd(card->host, &cmd, 0);
+ if (err)
+ printk(KERN_ERR "%s: error %d sending status comand",
+ req->rq_disk->disk_name, err);
+ return cmd.resp[0];
}
static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
@@ -214,13 +229,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
struct mmc_blk_request brq;
- int ret = 1;
+ int ret = 1, disable_multi = 0;
mmc_claim_host(card->host);
do {
struct mmc_command cmd;
- u32 readcmd, writecmd;
+ u32 readcmd, writecmd, status = 0;
memset(&brq, 0, sizeof(struct mmc_blk_request));
brq.mrq.cmd = &brq.cmd;
@@ -236,6 +251,14 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
brq.data.blocks = req->nr_sectors;
+ /*
+ * After a read error, we redo the request one sector at a time
+ * in order to accurately determine which sectors can be read
+ * successfully.
+ */
+ if (disable_multi && brq.data.blocks > 1)
+ brq.data.blocks = 1;
+
if (brq.data.blocks > 1) {
/* SPI multiblock writes terminate using a special
* token, not a STOP_TRANSMISSION request.
@@ -264,6 +287,25 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.data.sg = mq->sg;
brq.data.sg_len = mmc_queue_map_sg(mq);
+ /*
+ * Adjust the sg list so it is the same size as the
+ * request.
+ */
+ if (brq.data.blocks != req->nr_sectors) {
+ int i, data_size = brq.data.blocks << 9;
+ struct scatterlist *sg;
+
+ for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) {
+ data_size -= sg->length;
+ if (data_size <= 0) {
+ sg->length += data_size;
+ i++;
+ break;
+ }
+ }
+ brq.data.sg_len = i;
+ }
+
mmc_queue_bounce_pre(mq);
mmc_wait_for_req(card->host, &brq.mrq);
@@ -275,19 +317,40 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
* until later as we need to wait for the card to leave
* programming mode even when things go wrong.
*/
+ if (brq.cmd.error || brq.data.error || brq.stop.error) {
+ if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
+ /* Redo read one sector at a time */
+ printk(KERN_WARNING "%s: retrying using single "
+ "block read\n", req->rq_disk->disk_name);
+ disable_multi = 1;
+ continue;
+ }
+ status = get_card_status(card, req);
+ }
+
if (brq.cmd.error) {
- printk(KERN_ERR "%s: error %d sending read/write command\n",
- req->rq_disk->disk_name, brq.cmd.error);
+ printk(KERN_ERR "%s: error %d sending read/write "
+ "command, response %#x, card status %#x\n",
+ req->rq_disk->disk_name, brq.cmd.error,
+ brq.cmd.resp[0], status);
}
if (brq.data.error) {
- printk(KERN_ERR "%s: error %d transferring data\n",
- req->rq_disk->disk_name, brq.data.error);
+ if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
+ /* 'Stop' response contains card status */
+ status = brq.mrq.stop->resp[0];
+ printk(KERN_ERR "%s: error %d transferring data,"
+ " sector %u, nr %u, card status %#x\n",
+ req->rq_disk->disk_name, brq.data.error,
+ (unsigned)req->sector,
+ (unsigned)req->nr_sectors, status);
}
if (brq.stop.error) {
- printk(KERN_ERR "%s: error %d sending stop command\n",
- req->rq_disk->disk_name, brq.stop.error);
+ printk(KERN_ERR "%s: error %d sending stop command, "
+ "response %#x, card status %#x\n",
+ req->rq_disk->disk_name, brq.stop.error,
+ brq.stop.resp[0], status);
}
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
@@ -320,8 +383,20 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
#endif
}
- if (brq.cmd.error || brq.data.error || brq.stop.error)
+ if (brq.cmd.error || brq.stop.error || brq.data.error) {
+ if (rq_data_dir(req) == READ) {
+ /*
+ * After an error, we redo I/O one sector at a
+ * time, so we only reach here after trying to
+ * read a single sector.
+ */
+ spin_lock_irq(&md->lock);
+ ret = __blk_end_request(req, -EIO, brq.data.blksz);
+ spin_unlock_irq(&md->lock);
+ continue;
+ }
goto cmd_err;
+ }
/*
* A block was successfully transferred.
@@ -343,25 +418,20 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
* If the card is not SD, we can still ok written sectors
* as reported by the controller (which might be less than
* the real number of written sectors, but never more).
- *
- * For reads we just fail the entire chunk as that should
- * be safe in all cases.
*/
- if (rq_data_dir(req) != READ) {
- if (mmc_card_sd(card)) {
- u32 blocks;
+ if (mmc_card_sd(card)) {
+ u32 blocks;
- blocks = mmc_sd_num_wr_blocks(card);
- if (blocks != (u32)-1) {
- spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, blocks << 9);
- spin_unlock_irq(&md->lock);
- }
- } else {
+ blocks = mmc_sd_num_wr_blocks(card);
+ if (blocks != (u32)-1) {
spin_lock_irq(&md->lock);
- ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
+ ret = __blk_end_request(req, 0, blocks << 9);
spin_unlock_irq(&md->lock);
}
+ } else {
+ spin_lock_irq(&md->lock);
+ ret = __blk_end_request(req, 0, brq.data.bytes_xfered);
+ spin_unlock_irq(&md->lock);
}
mmc_release_host(card->host);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f7284b905eb3..df6ce4a06cf3 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -20,6 +20,7 @@
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/scatterlist.h>
+#include <linux/log2.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -448,6 +449,80 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
mmc_set_ios(host);
}
+/**
+ * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
+ * @vdd: voltage (mV)
+ * @low_bits: prefer low bits in boundary cases
+ *
+ * This function returns the OCR bit number according to the provided @vdd
+ * value. If conversion is not possible a negative errno value returned.
+ *
+ * Depending on the @low_bits flag the function prefers low or high OCR bits
+ * on boundary voltages. For example,
+ * with @low_bits = true, 3300 mV translates to ilog2(MMC_VDD_32_33);
+ * with @low_bits = false, 3300 mV translates to ilog2(MMC_VDD_33_34);
+ *
+ * Any value in the [1951:1999] range translates to the ilog2(MMC_VDD_20_21).
+ */
+static int mmc_vdd_to_ocrbitnum(int vdd, bool low_bits)
+{
+ const int max_bit = ilog2(MMC_VDD_35_36);
+ int bit;
+
+ if (vdd < 1650 || vdd > 3600)
+ return -EINVAL;
+
+ if (vdd >= 1650 && vdd <= 1950)
+ return ilog2(MMC_VDD_165_195);
+
+ if (low_bits)
+ vdd -= 1;
+
+ /* Base 2000 mV, step 100 mV, bit's base 8. */
+ bit = (vdd - 2000) / 100 + 8;
+ if (bit > max_bit)
+ return max_bit;
+ return bit;
+}
+
+/**
+ * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
+ * @vdd_min: minimum voltage value (mV)
+ * @vdd_max: maximum voltage value (mV)
+ *
+ * This function returns the OCR mask bits according to the provided @vdd_min
+ * and @vdd_max values. If conversion is not possible the function returns 0.
+ *
+ * Notes wrt boundary cases:
+ * This function sets the OCR bits for all boundary voltages, for example
+ * [3300:3400] range is translated to MMC_VDD_32_33 | MMC_VDD_33_34 |
+ * MMC_VDD_34_35 mask.
+ */
+u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
+{
+ u32 mask = 0;
+
+ if (vdd_max < vdd_min)
+ return 0;
+
+ /* Prefer high bits for the boundary vdd_max values. */
+ vdd_max = mmc_vdd_to_ocrbitnum(vdd_max, false);
+ if (vdd_max < 0)
+ return 0;
+
+ /* Prefer low bits for the boundary vdd_min values. */
+ vdd_min = mmc_vdd_to_ocrbitnum(vdd_min, true);
+ if (vdd_min < 0)
+ return 0;
+
+ /* Fill the mask, from max bit to min bit. */
+ while (vdd_max >= vdd_min)
+ mask |= 1 << vdd_max--;
+
+ return mask;
+}
+EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
+
/*
* Mask off any voltages we don't support and select
* the lowest voltage
@@ -467,6 +542,8 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
host->ios.vdd = bit;
mmc_set_ios(host);
} else {
+ pr_warning("%s: host doesn't support card's voltages\n",
+ mmc_hostname(host));
ocr = 0;
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index fdd7c760be8c..c232d11a7ed4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -434,13 +434,24 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
* Activate wide bus (if supported).
*/
if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
- (host->caps & MMC_CAP_4_BIT_DATA)) {
+ (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
+ unsigned ext_csd_bit, bus_width;
+
+ if (host->caps & MMC_CAP_8_BIT_DATA) {
+ ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
+ bus_width = MMC_BUS_WIDTH_8;
+ } else {
+ ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
+ bus_width = MMC_BUS_WIDTH_4;
+ }
+
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4);
+ EXT_CSD_BUS_WIDTH, ext_csd_bit);
+
if (err)
goto free_card;
- mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
+ mmc_set_bus_width(card->host, bus_width);
}
if (!oldcard)
@@ -624,4 +635,3 @@ err:
return err;
}
-
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index dfa585f7feaf..99d4b28d52ed 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -76,6 +76,16 @@ config MMC_OMAP
If unsure, say N.
+config MMC_OMAP_HS
+ tristate "TI OMAP High Speed Multimedia Card Interface support"
+ depends on ARCH_OMAP2430 || ARCH_OMAP3
+ help
+ This selects the TI OMAP High Speed Multimedia card Interface.
+ If you have an OMAP2430 or OMAP3 board with a Multimedia Card slot,
+ say Y or M here.
+
+ If unsure, say N.
+
config MMC_WBSD
tristate "Winbond W83L51xD SD/MMC Card Interface support"
depends on ISA_DMA_API
@@ -135,6 +145,16 @@ config MMC_IMX
If unsure, say N.
+config MMC_MXC
+ tristate "Freescale i.MX2/3 Multimedia Card Interface support"
+ depends on ARCH_MXC
+ help
+ This selects the Freescale i.MX2/3 Multimedia card Interface.
+ If you have a i.MX platform with a Multimedia Card slot,
+ say Y or M here.
+
+ If unsure, say N.
+
config MMC_TIFM_SD
tristate "TI Flash Media MMC/SD Interface support (EXPERIMENTAL)"
depends on EXPERIMENTAL && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c794cc5ce442..dedec55861d9 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,16 +9,21 @@ endif
obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
obj-$(CONFIG_MMC_PXA) += pxamci.o
obj-$(CONFIG_MMC_IMX) += imxmmc.o
+obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_OMAP) += omap.o
+obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o
obj-$(CONFIG_MMC_AT91) += at91_mci.o
obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o
obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
+ifeq ($(CONFIG_OF),y)
+obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o
+endif
obj-$(CONFIG_MMC_S3C) += s3cmci.o
obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o
obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 1f8b5b36222c..e556d42cc45a 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -1088,6 +1088,8 @@ static int __init at91_mci_probe(struct platform_device *pdev)
goto fail0;
}
+ setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
+
platform_set_drvdata(pdev, mmc);
/*
@@ -1101,8 +1103,6 @@ static int __init at91_mci_probe(struct platform_device *pdev)
mmc_add_host(mmc);
- setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
-
/*
* monitor card insertion/removal if we can
*/
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 7a3f2436b011..76bfe16c09b1 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -25,8 +25,8 @@
#include <linux/stat.h>
#include <linux/mmc/host.h>
+#include <linux/atmel-mci.h>
-#include <asm/atmel-mci.h>
#include <asm/io.h>
#include <asm/unaligned.h>
@@ -55,7 +55,6 @@ enum atmel_mci_state {
struct atmel_mci_dma {
#ifdef CONFIG_MMC_ATMELMCI_DMA
- struct dma_client client;
struct dma_chan *chan;
struct dma_async_tx_descriptor *data_desc;
#endif
@@ -593,10 +592,8 @@ atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data)
/* If we don't have a channel, we can't do DMA */
chan = host->dma.chan;
- if (chan) {
- dma_chan_get(chan);
+ if (chan)
host->data_chan = chan;
- }
if (!chan)
return -ENODEV;
@@ -1443,60 +1440,6 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-#ifdef CONFIG_MMC_ATMELMCI_DMA
-
-static inline struct atmel_mci *
-dma_client_to_atmel_mci(struct dma_client *client)
-{
- return container_of(client, struct atmel_mci, dma.client);
-}
-
-static enum dma_state_client atmci_dma_event(struct dma_client *client,
- struct dma_chan *chan, enum dma_state state)
-{
- struct atmel_mci *host;
- enum dma_state_client ret = DMA_NAK;
-
- host = dma_client_to_atmel_mci(client);
-
- switch (state) {
- case DMA_RESOURCE_AVAILABLE:
- spin_lock_bh(&host->lock);
- if (!host->dma.chan) {
- host->dma.chan = chan;
- ret = DMA_ACK;
- }
- spin_unlock_bh(&host->lock);
-
- if (ret == DMA_ACK)
- dev_info(&host->pdev->dev,
- "Using %s for DMA transfers\n",
- chan->dev.bus_id);
- break;
-
- case DMA_RESOURCE_REMOVED:
- spin_lock_bh(&host->lock);
- if (host->dma.chan == chan) {
- host->dma.chan = NULL;
- ret = DMA_ACK;
- }
- spin_unlock_bh(&host->lock);
-
- if (ret == DMA_ACK)
- dev_info(&host->pdev->dev,
- "Lost %s, falling back to PIO\n",
- chan->dev.bus_id);
- break;
-
- default:
- break;
- }
-
-
- return ret;
-}
-#endif /* CONFIG_MMC_ATMELMCI_DMA */
-
static int __init atmci_init_slot(struct atmel_mci *host,
struct mci_slot_pdata *slot_data, unsigned int id,
u32 sdc_reg)
@@ -1600,6 +1543,18 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot,
mmc_free_host(slot->mmc);
}
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+static bool filter(struct dma_chan *chan, void *slave)
+{
+ struct dw_dma_slave *dws = slave;
+
+ if (dws->dma_dev == chan->device->dev)
+ return true;
+ else
+ return false;
+}
+#endif
+
static int __init atmci_probe(struct platform_device *pdev)
{
struct mci_platform_data *pdata;
@@ -1652,22 +1607,20 @@ static int __init atmci_probe(struct platform_device *pdev)
goto err_request_irq;
#ifdef CONFIG_MMC_ATMELMCI_DMA
- if (pdata->dma_slave) {
- struct dma_slave *slave = pdata->dma_slave;
+ if (pdata->dma_slave.dma_dev) {
+ struct dw_dma_slave *dws = &pdata->dma_slave;
+ dma_cap_mask_t mask;
- slave->tx_reg = regs->start + MCI_TDR;
- slave->rx_reg = regs->start + MCI_RDR;
+ dws->tx_reg = regs->start + MCI_TDR;
+ dws->rx_reg = regs->start + MCI_RDR;
/* Try to grab a DMA channel */
- host->dma.client.event_callback = atmci_dma_event;
- dma_cap_set(DMA_SLAVE, host->dma.client.cap_mask);
- host->dma.client.slave = slave;
-
- dma_async_client_register(&host->dma.client);
- dma_async_client_chan_request(&host->dma.client);
- } else {
- dev_notice(&pdev->dev, "DMA not available, using PIO\n");
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ host->dma.chan = dma_request_channel(mask, filter, dws);
}
+ if (!host->dma.chan)
+ dev_notice(&pdev->dev, "DMA not available, using PIO\n");
#endif /* CONFIG_MMC_ATMELMCI_DMA */
platform_set_drvdata(pdev, host);
@@ -1699,8 +1652,8 @@ static int __init atmci_probe(struct platform_device *pdev)
err_init_slot:
#ifdef CONFIG_MMC_ATMELMCI_DMA
- if (pdata->dma_slave)
- dma_async_client_unregister(&host->dma.client);
+ if (host->dma.chan)
+ dma_release_channel(host->dma.chan);
#endif
free_irq(irq, host);
err_request_irq:
@@ -1731,8 +1684,8 @@ static int __exit atmci_remove(struct platform_device *pdev)
clk_disable(host->mck);
#ifdef CONFIG_MMC_ATMELMCI_DMA
- if (host->dma.client.slave)
- dma_async_client_unregister(&host->dma.client);
+ if (host->dma.chan)
+ dma_release_channel(host->dma.chan);
#endif
free_irq(platform_get_irq(pdev, 0), host);
@@ -1761,7 +1714,7 @@ static void __exit atmci_exit(void)
platform_driver_unregister(&atmci_driver);
}
-module_init(atmci_init);
+late_initcall(atmci_init); /* try to load after dma driver when built-in */
module_exit(atmci_exit);
MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index ad00e1632317..87e211df68ac 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1285,7 +1285,7 @@ static int mmc_spi_probe(struct spi_device *spi)
/* Platform data is used to hook up things like card sensing
* and power switching gpios.
*/
- host->pdata = spi->dev.platform_data;
+ host->pdata = mmc_spi_get_pdata(spi);
if (host->pdata)
mmc->ocr_avail = host->pdata->ocr_mask;
if (!mmc->ocr_avail) {
@@ -1368,6 +1368,7 @@ fail_glue_init:
fail_nobuf1:
mmc_free_host(mmc);
+ mmc_spi_put_pdata(spi);
dev_set_drvdata(&spi->dev, NULL);
nomem:
@@ -1402,6 +1403,7 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
spi->max_speed_hz = mmc->f_max;
mmc_free_host(mmc);
+ mmc_spi_put_pdata(spi);
dev_set_drvdata(&spi->dev, NULL);
}
return 0;
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 1bcbdd6763ac..2909bbc8ad00 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -430,6 +430,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
clk = 255;
host->cclk = host->mclk / (2 * (clk + 1));
}
+ if (host->hw_designer == 0x80)
+ clk |= MCI_FCEN; /* Bug fix in ST IP block */
clk |= MCI_CLK_ENABLE;
}
@@ -440,15 +442,27 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_OFF:
break;
case MMC_POWER_UP:
- pwr |= MCI_PWR_UP;
- break;
+ /* The ST version does not have this, fall through to POWER_ON */
+ if (host->hw_designer != 0x80) {
+ pwr |= MCI_PWR_UP;
+ break;
+ }
case MMC_POWER_ON:
pwr |= MCI_PWR_ON;
break;
}
- if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
- pwr |= MCI_ROD;
+ if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+ if (host->hw_designer != 0x80)
+ pwr |= MCI_ROD;
+ else {
+ /*
+ * The ST Micro variant use the ROD bit for something
+ * else and only has OD (Open Drain).
+ */
+ pwr |= MCI_OD;
+ }
+ }
writel(clk, host->base + MMCICLOCK);
@@ -500,6 +514,12 @@ static int mmci_probe(struct amba_device *dev, void *id)
}
host = mmc_priv(mmc);
+ /* Bits 12 thru 19 is the designer */
+ host->hw_designer = (dev->periphid >> 12) & 0xff;
+ /* Bits 20 thru 23 is the revison */
+ host->hw_revision = (dev->periphid >> 20) & 0xf;
+ DBG(host, "designer ID = 0x%02x\n", host->hw_designer);
+ DBG(host, "revision = 0x%01x\n", host->hw_revision);
host->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(host->clk)) {
ret = PTR_ERR(host->clk);
@@ -693,6 +713,15 @@ static struct amba_id mmci_ids[] = {
.id = 0x00041181,
.mask = 0x000fffff,
},
+ /* ST Micro variants */
+ {
+ .id = 0x00180180,
+ .mask = 0x00ffffff,
+ },
+ {
+ .id = 0x00280180,
+ .mask = 0x00ffffff,
+ },
{ 0, 0 },
};
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 0f39c490f022..0441bac1c0ec 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -11,13 +11,23 @@
#define MCI_PWR_OFF 0x00
#define MCI_PWR_UP 0x02
#define MCI_PWR_ON 0x03
+#define MCI_DATA2DIREN (1 << 2)
+#define MCI_CMDDIREN (1 << 3)
+#define MCI_DATA0DIREN (1 << 4)
+#define MCI_DATA31DIREN (1 << 5)
#define MCI_OD (1 << 6)
#define MCI_ROD (1 << 7)
+/* The ST Micro version does not have ROD */
+#define MCI_FBCLKEN (1 << 7)
+#define MCI_DATA74DIREN (1 << 8)
#define MMCICLOCK 0x004
#define MCI_CLK_ENABLE (1 << 8)
#define MCI_CLK_PWRSAVE (1 << 9)
#define MCI_CLK_BYPASS (1 << 10)
+#define MCI_WIDE_BUS (1 << 11)
+/* HW flow control on the ST Micro version */
+#define MCI_FCEN (1 << 13)
#define MMCIARGUMENT 0x008
#define MMCICOMMAND 0x00c
@@ -26,6 +36,10 @@
#define MCI_CPSM_INTERRUPT (1 << 8)
#define MCI_CPSM_PENDING (1 << 9)
#define MCI_CPSM_ENABLE (1 << 10)
+#define MCI_SDIO_SUSP (1 << 11)
+#define MCI_ENCMD_COMPL (1 << 12)
+#define MCI_NIEN (1 << 13)
+#define MCI_CE_ATACMD (1 << 14)
#define MMCIRESPCMD 0x010
#define MMCIRESPONSE0 0x014
@@ -39,6 +53,11 @@
#define MCI_DPSM_DIRECTION (1 << 1)
#define MCI_DPSM_MODE (1 << 2)
#define MCI_DPSM_DMAENABLE (1 << 3)
+#define MCI_DPSM_BLOCKSIZE (1 << 4)
+#define MCI_DPSM_RWSTART (1 << 8)
+#define MCI_DPSM_RWSTOP (1 << 9)
+#define MCI_DPSM_RWMOD (1 << 10)
+#define MCI_DPSM_SDIOEN (1 << 11)
#define MMCIDATACNT 0x030
#define MMCISTATUS 0x034
@@ -63,6 +82,8 @@
#define MCI_RXFIFOEMPTY (1 << 19)
#define MCI_TXDATAAVLBL (1 << 20)
#define MCI_RXDATAAVLBL (1 << 21)
+#define MCI_SDIOIT (1 << 22)
+#define MCI_CEATAEND (1 << 23)
#define MMCICLEAR 0x038
#define MCI_CMDCRCFAILCLR (1 << 0)
@@ -75,6 +96,8 @@
#define MCI_CMDSENTCLR (1 << 7)
#define MCI_DATAENDCLR (1 << 8)
#define MCI_DATABLOCKENDCLR (1 << 10)
+#define MCI_SDIOITC (1 << 22)
+#define MCI_CEATAENDC (1 << 23)
#define MMCIMASK0 0x03c
#define MCI_CMDCRCFAILMASK (1 << 0)
@@ -98,6 +121,8 @@
#define MCI_RXFIFOEMPTYMASK (1 << 19)
#define MCI_TXDATAAVLBLMASK (1 << 20)
#define MCI_RXDATAAVLBLMASK (1 << 21)
+#define MCI_SDIOITMASK (1 << 22)
+#define MCI_CEATAENDMASK (1 << 23)
#define MMCIMASK1 0x040
#define MMCIFIFOCNT 0x048
@@ -136,6 +161,9 @@ struct mmci_host {
u32 pwr;
struct mmc_platform_data *plat;
+ u8 hw_designer;
+ u8 hw_revision:4;
+
struct timer_list timer;
unsigned int oldstat;
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
new file mode 100644
index 000000000000..dda0be4e25dc
--- /dev/null
+++ b/drivers/mmc/host/mxcmmc.c
@@ -0,0 +1,880 @@
+/*
+ * linux/drivers/mmc/host/mxcmmc.c - Freescale i.MX MMCI driver
+ *
+ * This is a driver for the SDHC controller found in Freescale MX2/MX3
+ * SoCs. It is basically the same hardware as found on MX1 (imxmmc.c).
+ * Unlike the hardware found on MX1, this hardware just works and does
+ * not need all the quirks found in imxmmc.c, hence the seperate driver.
+ *
+ * Copyright (C) 2008 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2006 Pavel Pisa, PiKRON <ppisa@pikron.com>
+ *
+ * derived from pxamci.c by Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/blkdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/sizes.h>
+#include <mach/mmc.h>
+
+#ifdef CONFIG_ARCH_MX2
+#include <mach/dma-mx1-mx2.h>
+#define HAS_DMA
+#endif
+
+#define DRIVER_NAME "imx-mmc"
+
+#define MMC_REG_STR_STP_CLK 0x00
+#define MMC_REG_STATUS 0x04
+#define MMC_REG_CLK_RATE 0x08
+#define MMC_REG_CMD_DAT_CONT 0x0C
+#define MMC_REG_RES_TO 0x10
+#define MMC_REG_READ_TO 0x14
+#define MMC_REG_BLK_LEN 0x18
+#define MMC_REG_NOB 0x1C
+#define MMC_REG_REV_NO 0x20
+#define MMC_REG_INT_CNTR 0x24
+#define MMC_REG_CMD 0x28
+#define MMC_REG_ARG 0x2C
+#define MMC_REG_RES_FIFO 0x34
+#define MMC_REG_BUFFER_ACCESS 0x38
+
+#define STR_STP_CLK_RESET (1 << 3)
+#define STR_STP_CLK_START_CLK (1 << 1)
+#define STR_STP_CLK_STOP_CLK (1 << 0)
+
+#define STATUS_CARD_INSERTION (1 << 31)
+#define STATUS_CARD_REMOVAL (1 << 30)
+#define STATUS_YBUF_EMPTY (1 << 29)
+#define STATUS_XBUF_EMPTY (1 << 28)
+#define STATUS_YBUF_FULL (1 << 27)
+#define STATUS_XBUF_FULL (1 << 26)
+#define STATUS_BUF_UND_RUN (1 << 25)
+#define STATUS_BUF_OVFL (1 << 24)
+#define STATUS_SDIO_INT_ACTIVE (1 << 14)
+#define STATUS_END_CMD_RESP (1 << 13)
+#define STATUS_WRITE_OP_DONE (1 << 12)
+#define STATUS_DATA_TRANS_DONE (1 << 11)
+#define STATUS_READ_OP_DONE (1 << 11)
+#define STATUS_WR_CRC_ERROR_CODE_MASK (3 << 10)
+#define STATUS_CARD_BUS_CLK_RUN (1 << 8)
+#define STATUS_BUF_READ_RDY (1 << 7)
+#define STATUS_BUF_WRITE_RDY (1 << 6)
+#define STATUS_RESP_CRC_ERR (1 << 5)
+#define STATUS_CRC_READ_ERR (1 << 3)
+#define STATUS_CRC_WRITE_ERR (1 << 2)
+#define STATUS_TIME_OUT_RESP (1 << 1)
+#define STATUS_TIME_OUT_READ (1 << 0)
+#define STATUS_ERR_MASK 0x2f
+
+#define CMD_DAT_CONT_CMD_RESP_LONG_OFF (1 << 12)
+#define CMD_DAT_CONT_STOP_READWAIT (1 << 11)
+#define CMD_DAT_CONT_START_READWAIT (1 << 10)
+#define CMD_DAT_CONT_BUS_WIDTH_4 (2 << 8)
+#define CMD_DAT_CONT_INIT (1 << 7)
+#define CMD_DAT_CONT_WRITE (1 << 4)
+#define CMD_DAT_CONT_DATA_ENABLE (1 << 3)
+#define CMD_DAT_CONT_RESPONSE_48BIT_CRC (1 << 0)
+#define CMD_DAT_CONT_RESPONSE_136BIT (2 << 0)
+#define CMD_DAT_CONT_RESPONSE_48BIT (3 << 0)
+
+#define INT_SDIO_INT_WKP_EN (1 << 18)
+#define INT_CARD_INSERTION_WKP_EN (1 << 17)
+#define INT_CARD_REMOVAL_WKP_EN (1 << 16)
+#define INT_CARD_INSERTION_EN (1 << 15)
+#define INT_CARD_REMOVAL_EN (1 << 14)
+#define INT_SDIO_IRQ_EN (1 << 13)
+#define INT_DAT0_EN (1 << 12)
+#define INT_BUF_READ_EN (1 << 4)
+#define INT_BUF_WRITE_EN (1 << 3)
+#define INT_END_CMD_RES_EN (1 << 2)
+#define INT_WRITE_OP_DONE_EN (1 << 1)
+#define INT_READ_OP_EN (1 << 0)
+
+struct mxcmci_host {
+ struct mmc_host *mmc;
+ struct resource *res;
+ void __iomem *base;
+ int irq;
+ int detect_irq;
+ int dma;
+ int do_dma;
+ unsigned int power_mode;
+ struct imxmmc_platform_data *pdata;
+
+ struct mmc_request *req;
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+
+ unsigned int dma_nents;
+ unsigned int datasize;
+ unsigned int dma_dir;
+
+ u16 rev_no;
+ unsigned int cmdat;
+
+ struct clk *clk;
+
+ int clock;
+
+ struct work_struct datawork;
+};
+
+static inline int mxcmci_use_dma(struct mxcmci_host *host)
+{
+ return host->do_dma;
+}
+
+static void mxcmci_softreset(struct mxcmci_host *host)
+{
+ int i;
+
+ /* reset sequence */
+ writew(STR_STP_CLK_RESET, host->base + MMC_REG_STR_STP_CLK);
+ writew(STR_STP_CLK_RESET | STR_STP_CLK_START_CLK,
+ host->base + MMC_REG_STR_STP_CLK);
+
+ for (i = 0; i < 8; i++)
+ writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK);
+
+ writew(0xff, host->base + MMC_REG_RES_TO);
+}
+
+static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
+{
+ unsigned int nob = data->blocks;
+ unsigned int blksz = data->blksz;
+ unsigned int datasize = nob * blksz;
+#ifdef HAS_DMA
+ struct scatterlist *sg;
+ int i;
+#endif
+ if (data->flags & MMC_DATA_STREAM)
+ nob = 0xffff;
+
+ host->data = data;
+ data->bytes_xfered = 0;
+
+ writew(nob, host->base + MMC_REG_NOB);
+ writew(blksz, host->base + MMC_REG_BLK_LEN);
+ host->datasize = datasize;
+
+#ifdef HAS_DMA
+ for_each_sg(data->sg, sg, data->sg_len, i) {
+ if (sg->offset & 3 || sg->length & 3) {
+ host->do_dma = 0;
+ return;
+ }
+ }
+
+ if (data->flags & MMC_DATA_READ) {
+ host->dma_dir = DMA_FROM_DEVICE;
+ host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma_dir);
+
+ imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize,
+ host->res->start + MMC_REG_BUFFER_ACCESS,
+ DMA_MODE_READ);
+ } else {
+ host->dma_dir = DMA_TO_DEVICE;
+ host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma_dir);
+
+ imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize,
+ host->res->start + MMC_REG_BUFFER_ACCESS,
+ DMA_MODE_WRITE);
+ }
+
+ wmb();
+
+ imx_dma_enable(host->dma);
+#endif /* HAS_DMA */
+}
+
+static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd,
+ unsigned int cmdat)
+{
+ WARN_ON(host->cmd != NULL);
+ host->cmd = cmd;
+
+ switch (mmc_resp_type(cmd)) {
+ case MMC_RSP_R1: /* short CRC, OPCODE */
+ case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */
+ cmdat |= CMD_DAT_CONT_RESPONSE_48BIT_CRC;
+ break;
+ case MMC_RSP_R2: /* long 136 bit + CRC */
+ cmdat |= CMD_DAT_CONT_RESPONSE_136BIT;
+ break;
+ case MMC_RSP_R3: /* short */
+ cmdat |= CMD_DAT_CONT_RESPONSE_48BIT;
+ break;
+ case MMC_RSP_NONE:
+ break;
+ default:
+ dev_err(mmc_dev(host->mmc), "unhandled response type 0x%x\n",
+ mmc_resp_type(cmd));
+ cmd->error = -EINVAL;
+ return -EINVAL;
+ }
+
+ if (mxcmci_use_dma(host))
+ writel(INT_READ_OP_EN | INT_WRITE_OP_DONE_EN |
+ INT_END_CMD_RES_EN,
+ host->base + MMC_REG_INT_CNTR);
+ else
+ writel(INT_END_CMD_RES_EN, host->base + MMC_REG_INT_CNTR);
+
+ writew(cmd->opcode, host->base + MMC_REG_CMD);
+ writel(cmd->arg, host->base + MMC_REG_ARG);
+ writew(cmdat, host->base + MMC_REG_CMD_DAT_CONT);
+
+ return 0;
+}
+
+static void mxcmci_finish_request(struct mxcmci_host *host,
+ struct mmc_request *req)
+{
+ writel(0, host->base + MMC_REG_INT_CNTR);
+
+ host->req = NULL;
+ host->cmd = NULL;
+ host->data = NULL;
+
+ mmc_request_done(host->mmc, req);
+}
+
+static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
+{
+ struct mmc_data *data = host->data;
+ int data_error;
+
+#ifdef HAS_DMA
+ if (mxcmci_use_dma(host)) {
+ imx_dma_disable(host->dma);
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+ host->dma_dir);
+ }
+#endif
+
+ if (stat & STATUS_ERR_MASK) {
+ dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
+ stat);
+ if (stat & STATUS_CRC_READ_ERR) {
+ data->error = -EILSEQ;
+ } else if (stat & STATUS_CRC_WRITE_ERR) {
+ u32 err_code = (stat >> 9) & 0x3;
+ if (err_code == 2) /* No CRC response */
+ data->error = -ETIMEDOUT;
+ else
+ data->error = -EILSEQ;
+ } else if (stat & STATUS_TIME_OUT_READ) {
+ data->error = -ETIMEDOUT;
+ } else {
+ data->error = -EIO;
+ }
+ } else {
+ data->bytes_xfered = host->datasize;
+ }
+
+ data_error = data->error;
+
+ host->data = NULL;
+
+ return data_error;
+}
+
+static void mxcmci_read_response(struct mxcmci_host *host, unsigned int stat)
+{
+ struct mmc_command *cmd = host->cmd;
+ int i;
+ u32 a, b, c;
+
+ if (!cmd)
+ return;
+
+ if (stat & STATUS_TIME_OUT_RESP) {
+ dev_dbg(mmc_dev(host->mmc), "CMD TIMEOUT\n");
+ cmd->error = -ETIMEDOUT;
+ } else if (stat & STATUS_RESP_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
+ dev_dbg(mmc_dev(host->mmc), "cmd crc error\n");
+ cmd->error = -EILSEQ;
+ }
+
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136) {
+ for (i = 0; i < 4; i++) {
+ a = readw(host->base + MMC_REG_RES_FIFO);
+ b = readw(host->base + MMC_REG_RES_FIFO);
+ cmd->resp[i] = a << 16 | b;
+ }
+ } else {
+ a = readw(host->base + MMC_REG_RES_FIFO);
+ b = readw(host->base + MMC_REG_RES_FIFO);
+ c = readw(host->base + MMC_REG_RES_FIFO);
+ cmd->resp[0] = a << 24 | b << 8 | c >> 8;
+ }
+ }
+}
+
+static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask)
+{
+ u32 stat;
+ unsigned long timeout = jiffies + HZ;
+
+ do {
+ stat = readl(host->base + MMC_REG_STATUS);
+ if (stat & STATUS_ERR_MASK)
+ return stat;
+ if (time_after(jiffies, timeout))
+ return STATUS_TIME_OUT_READ;
+ if (stat & mask)
+ return 0;
+ cpu_relax();
+ } while (1);
+}
+
+static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes)
+{
+ unsigned int stat;
+ u32 *buf = _buf;
+
+ while (bytes > 3) {
+ stat = mxcmci_poll_status(host,
+ STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE);
+ if (stat)
+ return stat;
+ *buf++ = readl(host->base + MMC_REG_BUFFER_ACCESS);
+ bytes -= 4;
+ }
+
+ if (bytes) {
+ u8 *b = (u8 *)buf;
+ u32 tmp;
+
+ stat = mxcmci_poll_status(host,
+ STATUS_BUF_READ_RDY | STATUS_READ_OP_DONE);
+ if (stat)
+ return stat;
+ tmp = readl(host->base + MMC_REG_BUFFER_ACCESS);
+ memcpy(b, &tmp, bytes);
+ }
+
+ return 0;
+}
+
+static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes)
+{
+ unsigned int stat;
+ u32 *buf = _buf;
+
+ while (bytes > 3) {
+ stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
+ if (stat)
+ return stat;
+ writel(*buf++, host->base + MMC_REG_BUFFER_ACCESS);
+ bytes -= 4;
+ }
+
+ if (bytes) {
+ u8 *b = (u8 *)buf;
+ u32 tmp;
+
+ stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
+ if (stat)
+ return stat;
+
+ memcpy(&tmp, b, bytes);
+ writel(tmp, host->base + MMC_REG_BUFFER_ACCESS);
+ }
+
+ stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
+ if (stat)
+ return stat;
+
+ return 0;
+}
+
+static int mxcmci_transfer_data(struct mxcmci_host *host)
+{
+ struct mmc_data *data = host->req->data;
+ struct scatterlist *sg;
+ int stat, i;
+
+ host->datasize = 0;
+
+ host->data = data;
+ host->datasize = 0;
+
+ if (data->flags & MMC_DATA_READ) {
+ for_each_sg(data->sg, sg, data->sg_len, i) {
+ stat = mxcmci_pull(host, sg_virt(sg), sg->length);
+ if (stat)
+ return stat;
+ host->datasize += sg->length;
+ }
+ } else {
+ for_each_sg(data->sg, sg, data->sg_len, i) {
+ stat = mxcmci_push(host, sg_virt(sg), sg->length);
+ if (stat)
+ return stat;
+ host->datasize += sg->length;
+ }
+ stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE);
+ if (stat)
+ return stat;
+ }
+ return 0;
+}
+
+static void mxcmci_datawork(struct work_struct *work)
+{
+ struct mxcmci_host *host = container_of(work, struct mxcmci_host,
+ datawork);
+ int datastat = mxcmci_transfer_data(host);
+ mxcmci_finish_data(host, datastat);
+
+ if (host->req->stop) {
+ if (mxcmci_start_cmd(host, host->req->stop, 0)) {
+ mxcmci_finish_request(host, host->req);
+ return;
+ }
+ } else {
+ mxcmci_finish_request(host, host->req);
+ }
+}
+
+#ifdef HAS_DMA
+static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
+{
+ struct mmc_data *data = host->data;
+ int data_error;
+
+ if (!data)
+ return;
+
+ data_error = mxcmci_finish_data(host, stat);
+
+ mxcmci_read_response(host, stat);
+ host->cmd = NULL;
+
+ if (host->req->stop) {
+ if (mxcmci_start_cmd(host, host->req->stop, 0)) {
+ mxcmci_finish_request(host, host->req);
+ return;
+ }
+ } else {
+ mxcmci_finish_request(host, host->req);
+ }
+}
+#endif /* HAS_DMA */
+
+static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
+{
+ mxcmci_read_response(host, stat);
+ host->cmd = NULL;
+
+ if (!host->data && host->req) {
+ mxcmci_finish_request(host, host->req);
+ return;
+ }
+
+ /* For the DMA case the DMA engine handles the data transfer
+ * automatically. For non DMA we have to to it ourselves.
+ * Don't do it in interrupt context though.
+ */
+ if (!mxcmci_use_dma(host) && host->data)
+ schedule_work(&host->datawork);
+
+}
+
+static irqreturn_t mxcmci_irq(int irq, void *devid)
+{
+ struct mxcmci_host *host = devid;
+ u32 stat;
+
+ stat = readl(host->base + MMC_REG_STATUS);
+ writel(stat, host->base + MMC_REG_STATUS);
+
+ dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
+
+ if (stat & STATUS_END_CMD_RESP)
+ mxcmci_cmd_done(host, stat);
+#ifdef HAS_DMA
+ if (mxcmci_use_dma(host) &&
+ (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
+ mxcmci_data_done(host, stat);
+#endif
+ return IRQ_HANDLED;
+}
+
+static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+ struct mxcmci_host *host = mmc_priv(mmc);
+ unsigned int cmdat = host->cmdat;
+
+ WARN_ON(host->req != NULL);
+
+ host->req = req;
+ host->cmdat &= ~CMD_DAT_CONT_INIT;
+#ifdef HAS_DMA
+ host->do_dma = 1;
+#endif
+ if (req->data) {
+ mxcmci_setup_data(host, req->data);
+
+ cmdat |= CMD_DAT_CONT_DATA_ENABLE;
+
+ if (req->data->flags & MMC_DATA_WRITE)
+ cmdat |= CMD_DAT_CONT_WRITE;
+ }
+
+ if (mxcmci_start_cmd(host, req->cmd, cmdat))
+ mxcmci_finish_request(host, req);
+}
+
+static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
+{
+ unsigned int divider;
+ int prescaler = 0;
+ unsigned int clk_in = clk_get_rate(host->clk);
+
+ while (prescaler <= 0x800) {
+ for (divider = 1; divider <= 0xF; divider++) {
+ int x;
+
+ x = (clk_in / (divider + 1));
+
+ if (prescaler)
+ x /= (prescaler * 2);
+
+ if (x <= clk_ios)
+ break;
+ }
+ if (divider < 0x10)
+ break;
+
+ if (prescaler == 0)
+ prescaler = 1;
+ else
+ prescaler <<= 1;
+ }
+
+ writew((prescaler << 4) | divider, host->base + MMC_REG_CLK_RATE);
+
+ dev_dbg(mmc_dev(host->mmc), "scaler: %d divider: %d in: %d out: %d\n",
+ prescaler, divider, clk_in, clk_ios);
+}
+
+static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct mxcmci_host *host = mmc_priv(mmc);
+#ifdef HAS_DMA
+ unsigned int blen;
+ /*
+ * use burstlen of 64 in 4 bit mode (--> reg value 0)
+ * use burstlen of 16 in 1 bit mode (--> reg value 16)
+ */
+ if (ios->bus_width == MMC_BUS_WIDTH_4)
+ blen = 0;
+ else
+ blen = 16;
+
+ imx_dma_config_burstlen(host->dma, blen);
+#endif
+ if (ios->bus_width == MMC_BUS_WIDTH_4)
+ host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
+ else
+ host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4;
+
+ if (host->power_mode != ios->power_mode) {
+ if (host->pdata && host->pdata->setpower)
+ host->pdata->setpower(mmc_dev(mmc), ios->vdd);
+ host->power_mode = ios->power_mode;
+ if (ios->power_mode == MMC_POWER_ON)
+ host->cmdat |= CMD_DAT_CONT_INIT;
+ }
+
+ if (ios->clock) {
+ mxcmci_set_clk_rate(host, ios->clock);
+ writew(STR_STP_CLK_START_CLK, host->base + MMC_REG_STR_STP_CLK);
+ } else {
+ writew(STR_STP_CLK_STOP_CLK, host->base + MMC_REG_STR_STP_CLK);
+ }
+
+ host->clock = ios->clock;
+}
+
+static irqreturn_t mxcmci_detect_irq(int irq, void *data)
+{
+ struct mmc_host *mmc = data;
+
+ dev_dbg(mmc_dev(mmc), "%s\n", __func__);
+
+ mmc_detect_change(mmc, msecs_to_jiffies(250));
+ return IRQ_HANDLED;
+}
+
+static int mxcmci_get_ro(struct mmc_host *mmc)
+{
+ struct mxcmci_host *host = mmc_priv(mmc);
+
+ if (host->pdata && host->pdata->get_ro)
+ return !!host->pdata->get_ro(mmc_dev(mmc));
+ /*
+ * Board doesn't support read only detection; let the mmc core
+ * decide what to do.
+ */
+ return -ENOSYS;
+}
+
+
+static const struct mmc_host_ops mxcmci_ops = {
+ .request = mxcmci_request,
+ .set_ios = mxcmci_set_ios,
+ .get_ro = mxcmci_get_ro,
+};
+
+static int mxcmci_probe(struct platform_device *pdev)
+{
+ struct mmc_host *mmc;
+ struct mxcmci_host *host = NULL;
+ struct resource *r;
+ int ret = 0, irq;
+
+ printk(KERN_INFO "i.MX SDHC driver\n");
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (!r || irq < 0)
+ return -EINVAL;
+
+ r = request_mem_region(r->start, resource_size(r), pdev->name);
+ if (!r)
+ return -EBUSY;
+
+ mmc = mmc_alloc_host(sizeof(struct mxcmci_host), &pdev->dev);
+ if (!mmc) {
+ ret = -ENOMEM;
+ goto out_release_mem;
+ }
+
+ mmc->ops = &mxcmci_ops;
+ mmc->caps = MMC_CAP_4_BIT_DATA;
+
+ /* MMC core transfer sizes tunable parameters */
+ mmc->max_hw_segs = 64;
+ mmc->max_phys_segs = 64;
+ mmc->max_blk_size = 2048;
+ mmc->max_blk_count = 65535;
+ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+ mmc->max_seg_size = mmc->max_seg_size;
+
+ host = mmc_priv(mmc);
+ host->base = ioremap(r->start, resource_size(r));
+ if (!host->base) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ host->mmc = mmc;
+ host->pdata = pdev->dev.platform_data;
+
+ if (host->pdata && host->pdata->ocr_avail)
+ mmc->ocr_avail = host->pdata->ocr_avail;
+ else
+ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ host->res = r;
+ host->irq = irq;
+
+ host->clk = clk_get(&pdev->dev, "sdhc_clk");
+ if (IS_ERR(host->clk)) {
+ ret = PTR_ERR(host->clk);
+ goto out_iounmap;
+ }
+ clk_enable(host->clk);
+
+ mxcmci_softreset(host);
+
+ host->rev_no = readw(host->base + MMC_REG_REV_NO);
+ if (host->rev_no != 0x400) {
+ ret = -ENODEV;
+ dev_err(mmc_dev(host->mmc), "wrong rev.no. 0x%08x. aborting.\n",
+ host->rev_no);
+ goto out_clk_put;
+ }
+
+ mmc->f_min = clk_get_rate(host->clk) >> 7;
+ mmc->f_max = clk_get_rate(host->clk) >> 1;
+
+ /* recommended in data sheet */
+ writew(0x2db4, host->base + MMC_REG_READ_TO);
+
+ writel(0, host->base + MMC_REG_INT_CNTR);
+
+#ifdef HAS_DMA
+ host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW);
+ if (host->dma < 0) {
+ dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
+ ret = -EBUSY;
+ goto out_clk_put;
+ }
+
+ r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!r) {
+ ret = -EINVAL;
+ goto out_free_dma;
+ }
+
+ ret = imx_dma_config_channel(host->dma,
+ IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO,
+ IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+ r->start, 0);
+ if (ret) {
+ dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n");
+ goto out_free_dma;
+ }
+#endif
+ INIT_WORK(&host->datawork, mxcmci_datawork);
+
+ ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host);
+ if (ret)
+ goto out_free_dma;
+
+ platform_set_drvdata(pdev, mmc);
+
+ if (host->pdata && host->pdata->init) {
+ ret = host->pdata->init(&pdev->dev, mxcmci_detect_irq,
+ host->mmc);
+ if (ret)
+ goto out_free_irq;
+ }
+
+ mmc_add_host(mmc);
+
+ return 0;
+
+out_free_irq:
+ free_irq(host->irq, host);
+out_free_dma:
+#ifdef HAS_DMA
+ imx_dma_free(host->dma);
+#endif
+out_clk_put:
+ clk_disable(host->clk);
+ clk_put(host->clk);
+out_iounmap:
+ iounmap(host->base);
+out_free:
+ mmc_free_host(mmc);
+out_release_mem:
+ release_mem_region(host->res->start, resource_size(host->res));
+ return ret;
+}
+
+static int mxcmci_remove(struct platform_device *pdev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(pdev);
+ struct mxcmci_host *host = mmc_priv(mmc);
+
+ platform_set_drvdata(pdev, NULL);
+
+ mmc_remove_host(mmc);
+
+ if (host->pdata && host->pdata->exit)
+ host->pdata->exit(&pdev->dev, mmc);
+
+ free_irq(host->irq, host);
+ iounmap(host->base);
+#ifdef HAS_DMA
+ imx_dma_free(host->dma);
+#endif
+ clk_disable(host->clk);
+ clk_put(host->clk);
+
+ release_mem_region(host->res->start, resource_size(host->res));
+ release_resource(host->res);
+
+ mmc_free_host(mmc);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxcmci_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ int ret = 0;
+
+ if (mmc)
+ ret = mmc_suspend_host(mmc, state);
+
+ return ret;
+}
+
+static int mxcmci_resume(struct platform_device *dev)
+{
+ struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mxcmci_host *host;
+ int ret = 0;
+
+ if (mmc) {
+ host = mmc_priv(mmc);
+ ret = mmc_resume_host(mmc);
+ }
+
+ return ret;
+}
+#else
+#define mxcmci_suspend NULL
+#define mxcmci_resume NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver mxcmci_driver = {
+ .probe = mxcmci_probe,
+ .remove = mxcmci_remove,
+ .suspend = mxcmci_suspend,
+ .resume = mxcmci_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init mxcmci_init(void)
+{
+ return platform_driver_register(&mxcmci_driver);
+}
+
+static void __exit mxcmci_exit(void)
+{
+ platform_driver_unregister(&mxcmci_driver);
+}
+
+module_init(mxcmci_init);
+module_exit(mxcmci_exit);
+
+MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx-mmc");
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
new file mode 100644
index 000000000000..fb2921f8099d
--- /dev/null
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -0,0 +1,149 @@
+/*
+ * OpenFirmware bindings for the MMC-over-SPI driver
+ *
+ * Copyright (c) MontaVista Software, Inc. 2008.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mmc_spi.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/host.h>
+
+enum {
+ CD_GPIO = 0,
+ WP_GPIO,
+ NUM_GPIOS,
+};
+
+struct of_mmc_spi {
+ int gpios[NUM_GPIOS];
+ bool alow_gpios[NUM_GPIOS];
+ struct mmc_spi_platform_data pdata;
+};
+
+static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
+{
+ return container_of(dev->platform_data, struct of_mmc_spi, pdata);
+}
+
+static int of_mmc_spi_read_gpio(struct device *dev, int gpio_num)
+{
+ struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+ bool active_low = oms->alow_gpios[gpio_num];
+ bool value = gpio_get_value(oms->gpios[gpio_num]);
+
+ return active_low ^ value;
+}
+
+static int of_mmc_spi_get_cd(struct device *dev)
+{
+ return of_mmc_spi_read_gpio(dev, CD_GPIO);
+}
+
+static int of_mmc_spi_get_ro(struct device *dev)
+{
+ return of_mmc_spi_read_gpio(dev, WP_GPIO);
+}
+
+struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct device_node *np = dev_archdata_get_node(&dev->archdata);
+ struct of_mmc_spi *oms;
+ const u32 *voltage_ranges;
+ int num_ranges;
+ int i;
+ int ret = -EINVAL;
+
+ if (dev->platform_data || !np)
+ return dev->platform_data;
+
+ oms = kzalloc(sizeof(*oms), GFP_KERNEL);
+ if (!oms)
+ return NULL;
+
+ voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges);
+ num_ranges = num_ranges / sizeof(*voltage_ranges) / 2;
+ if (!voltage_ranges || !num_ranges) {
+ dev_err(dev, "OF: voltage-ranges unspecified\n");
+ goto err_ocr;
+ }
+
+ for (i = 0; i < num_ranges; i++) {
+ const int j = i * 2;
+ u32 mask;
+
+ mask = mmc_vddrange_to_ocrmask(voltage_ranges[j],
+ voltage_ranges[j + 1]);
+ if (!mask) {
+ ret = -EINVAL;
+ dev_err(dev, "OF: voltage-range #%d is invalid\n", i);
+ goto err_ocr;
+ }
+ oms->pdata.ocr_mask |= mask;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
+ enum of_gpio_flags gpio_flags;
+
+ oms->gpios[i] = of_get_gpio_flags(np, i, &gpio_flags);
+ if (!gpio_is_valid(oms->gpios[i]))
+ continue;
+
+ ret = gpio_request(oms->gpios[i], dev->bus_id);
+ if (ret < 0) {
+ oms->gpios[i] = -EINVAL;
+ continue;
+ }
+
+ if (gpio_flags & OF_GPIO_ACTIVE_LOW)
+ oms->alow_gpios[i] = true;
+ }
+
+ if (gpio_is_valid(oms->gpios[CD_GPIO]))
+ oms->pdata.get_cd = of_mmc_spi_get_cd;
+ if (gpio_is_valid(oms->gpios[WP_GPIO]))
+ oms->pdata.get_ro = of_mmc_spi_get_ro;
+
+ /* We don't support interrupts yet, let's poll. */
+ oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
+
+ dev->platform_data = &oms->pdata;
+ return dev->platform_data;
+err_ocr:
+ kfree(oms);
+ return NULL;
+}
+EXPORT_SYMBOL(mmc_spi_get_pdata);
+
+void mmc_spi_put_pdata(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct device_node *np = dev_archdata_get_node(&dev->archdata);
+ struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+ int i;
+
+ if (!dev->platform_data || !np)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(oms->gpios); i++) {
+ if (gpio_is_valid(oms->gpios[i]))
+ gpio_free(oms->gpios[i]);
+ }
+ kfree(oms);
+ dev->platform_data = NULL;
+}
+EXPORT_SYMBOL(mmc_spi_put_pdata);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
new file mode 100644
index 000000000000..db37490f67ec
--- /dev/null
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -0,0 +1,1242 @@
+/*
+ * drivers/mmc/host/omap_hsmmc.c
+ *
+ * Driver for OMAP2430/3430 MMC controller.
+ *
+ * Copyright (C) 2007 Texas Instruments.
+ *
+ * Authors:
+ * Syed Mohammed Khasim <x0khasim@ti.com>
+ * Madhusudhan <madhu.cr@ti.com>
+ * Mohit Jalori <mjalori@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/io.h>
+#include <linux/semaphore.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+#include <mach/board.h>
+#include <mach/mmc.h>
+#include <mach/cpu.h>
+
+/* OMAP HSMMC Host Controller Registers */
+#define OMAP_HSMMC_SYSCONFIG 0x0010
+#define OMAP_HSMMC_CON 0x002C
+#define OMAP_HSMMC_BLK 0x0104
+#define OMAP_HSMMC_ARG 0x0108
+#define OMAP_HSMMC_CMD 0x010C
+#define OMAP_HSMMC_RSP10 0x0110
+#define OMAP_HSMMC_RSP32 0x0114
+#define OMAP_HSMMC_RSP54 0x0118
+#define OMAP_HSMMC_RSP76 0x011C
+#define OMAP_HSMMC_DATA 0x0120
+#define OMAP_HSMMC_HCTL 0x0128
+#define OMAP_HSMMC_SYSCTL 0x012C
+#define OMAP_HSMMC_STAT 0x0130
+#define OMAP_HSMMC_IE 0x0134
+#define OMAP_HSMMC_ISE 0x0138
+#define OMAP_HSMMC_CAPA 0x0140
+
+#define VS18 (1 << 26)
+#define VS30 (1 << 25)
+#define SDVS18 (0x5 << 9)
+#define SDVS30 (0x6 << 9)
+#define SDVSCLR 0xFFFFF1FF
+#define SDVSDET 0x00000400
+#define AUTOIDLE 0x1
+#define SDBP (1 << 8)
+#define DTO 0xe
+#define ICE 0x1
+#define ICS 0x2
+#define CEN (1 << 2)
+#define CLKD_MASK 0x0000FFC0
+#define CLKD_SHIFT 6
+#define DTO_MASK 0x000F0000
+#define DTO_SHIFT 16
+#define INT_EN_MASK 0x307F0033
+#define INIT_STREAM (1 << 1)
+#define DP_SELECT (1 << 21)
+#define DDIR (1 << 4)
+#define DMA_EN 0x1
+#define MSBS (1 << 5)
+#define BCE (1 << 1)
+#define FOUR_BIT (1 << 1)
+#define CC 0x1
+#define TC 0x02
+#define OD 0x1
+#define ERR (1 << 15)
+#define CMD_TIMEOUT (1 << 16)
+#define DATA_TIMEOUT (1 << 20)
+#define CMD_CRC (1 << 17)
+#define DATA_CRC (1 << 21)
+#define CARD_ERR (1 << 28)
+#define STAT_CLEAR 0xFFFFFFFF
+#define INIT_STREAM_CMD 0x00000000
+#define DUAL_VOLT_OCR_BIT 7
+#define SRC (1 << 25)
+#define SRD (1 << 26)
+
+/*
+ * FIXME: Most likely all the data using these _DEVID defines should come
+ * from the platform_data, or implemented in controller and slot specific
+ * functions.
+ */
+#define OMAP_MMC1_DEVID 0
+#define OMAP_MMC2_DEVID 1
+
+#define OMAP_MMC_DATADIR_NONE 0
+#define OMAP_MMC_DATADIR_READ 1
+#define OMAP_MMC_DATADIR_WRITE 2
+#define MMC_TIMEOUT_MS 20
+#define OMAP_MMC_MASTER_CLOCK 96000000
+#define DRIVER_NAME "mmci-omap-hs"
+
+/*
+ * One controller can have multiple slots, like on some omap boards using
+ * omap.c controller driver. Luckily this is not currently done on any known
+ * omap_hsmmc.c device.
+ */
+#define mmc_slot(host) (host->pdata->slots[host->slot_id])
+
+/*
+ * MMC Host controller read/write API's
+ */
+#define OMAP_HSMMC_READ(base, reg) \
+ __raw_readl((base) + OMAP_HSMMC_##reg)
+
+#define OMAP_HSMMC_WRITE(base, reg, val) \
+ __raw_writel((val), (base) + OMAP_HSMMC_##reg)
+
+struct mmc_omap_host {
+ struct device *dev;
+ struct mmc_host *mmc;
+ struct mmc_request *mrq;
+ struct mmc_command *cmd;
+ struct mmc_data *data;
+ struct clk *fclk;
+ struct clk *iclk;
+ struct clk *dbclk;
+ struct semaphore sem;
+ struct work_struct mmc_carddetect_work;
+ void __iomem *base;
+ resource_size_t mapbase;
+ unsigned int id;
+ unsigned int dma_len;
+ unsigned int dma_dir;
+ unsigned char bus_mode;
+ unsigned char datadir;
+ u32 *buffer;
+ u32 bytesleft;
+ int suspended;
+ int irq;
+ int carddetect;
+ int use_dma, dma_ch;
+ int initstr;
+ int slot_id;
+ int dbclk_enabled;
+ struct omap_mmc_platform_data *pdata;
+};
+
+/*
+ * Stop clock to the card
+ */
+static void omap_mmc_stop_clock(struct mmc_omap_host *host)
+{
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN);
+ if ((OMAP_HSMMC_READ(host->base, SYSCTL) & CEN) != 0x0)
+ dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n");
+}
+
+/*
+ * Send init stream sequence to card
+ * before sending IDLE command
+ */
+static void send_init_stream(struct mmc_omap_host *host)
+{
+ int reg = 0;
+ unsigned long timeout;
+
+ disable_irq(host->irq);
+ OMAP_HSMMC_WRITE(host->base, CON,
+ OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
+ OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
+
+ timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
+ while ((reg != CC) && time_before(jiffies, timeout))
+ reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
+
+ OMAP_HSMMC_WRITE(host->base, CON,
+ OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
+ enable_irq(host->irq);
+}
+
+static inline
+int mmc_omap_cover_is_closed(struct mmc_omap_host *host)
+{
+ int r = 1;
+
+ if (host->pdata->slots[host->slot_id].get_cover_state)
+ r = host->pdata->slots[host->slot_id].get_cover_state(host->dev,
+ host->slot_id);
+ return r;
+}
+
+static ssize_t
+mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
+ struct mmc_omap_host *host = mmc_priv(mmc);
+
+ return sprintf(buf, "%s\n", mmc_omap_cover_is_closed(host) ? "closed" :
+ "open");
+}
+
+static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL);
+
+static ssize_t
+mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
+ struct mmc_omap_host *host = mmc_priv(mmc);
+ struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id];
+
+ return sprintf(buf, "slot:%s\n", slot.name);
+}
+
+static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL);
+
+/*
+ * Configure the response type and send the cmd.
+ */
+static void
+mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
+ struct mmc_data *data)
+{
+ int cmdreg = 0, resptype = 0, cmdtype = 0;
+
+ dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
+ mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
+ host->cmd = cmd;
+
+ /*
+ * Clear status bits and enable interrupts
+ */
+ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
+ OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
+
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136)
+ resptype = 1;
+ else
+ resptype = 2;
+ }
+
+ /*
+ * Unlike OMAP1 controller, the cmdtype does not seem to be based on
+ * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
+ * a val of 0x3, rest 0x0.
+ */
+ if (cmd == host->mrq->stop)
+ cmdtype = 0x3;
+
+ cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
+
+ if (data) {
+ cmdreg |= DP_SELECT | MSBS | BCE;
+ if (data->flags & MMC_DATA_READ)
+ cmdreg |= DDIR;
+ else
+ cmdreg &= ~(DDIR);
+ }
+
+ if (host->use_dma)
+ cmdreg |= DMA_EN;
+
+ OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg);
+ OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
+}
+
+/*
+ * Notify the transfer complete to MMC core
+ */
+static void
+mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
+{
+ host->data = NULL;
+
+ if (host->use_dma && host->dma_ch != -1)
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+ host->dma_dir);
+
+ host->datadir = OMAP_MMC_DATADIR_NONE;
+
+ if (!data->error)
+ data->bytes_xfered += data->blocks * (data->blksz);
+ else
+ data->bytes_xfered = 0;
+
+ if (!data->stop) {
+ host->mrq = NULL;
+ mmc_request_done(host->mmc, data->mrq);
+ return;
+ }
+ mmc_omap_start_command(host, data->stop, NULL);
+}
+
+/*
+ * Notify the core about command completion
+ */
+static void
+mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
+{
+ host->cmd = NULL;
+
+ if (cmd->flags & MMC_RSP_PRESENT) {
+ if (cmd->flags & MMC_RSP_136) {
+ /* response type 2 */
+ cmd->resp[3] = OMAP_HSMMC_READ(host->base, RSP10);
+ cmd->resp[2] = OMAP_HSMMC_READ(host->base, RSP32);
+ cmd->resp[1] = OMAP_HSMMC_READ(host->base, RSP54);
+ cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP76);
+ } else {
+ /* response types 1, 1b, 3, 4, 5, 6 */
+ cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
+ }
+ }
+ if (host->data == NULL || cmd->error) {
+ host->mrq = NULL;
+ mmc_request_done(host->mmc, cmd->mrq);
+ }
+}
+
+/*
+ * DMA clean up for command errors
+ */
+static void mmc_dma_cleanup(struct mmc_omap_host *host)
+{
+ host->data->error = -ETIMEDOUT;
+
+ if (host->use_dma && host->dma_ch != -1) {
+ dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
+ host->dma_dir);
+ omap_free_dma(host->dma_ch);
+ host->dma_ch = -1;
+ up(&host->sem);
+ }
+ host->data = NULL;
+ host->datadir = OMAP_MMC_DATADIR_NONE;
+}
+
+/*
+ * Readable error output
+ */
+#ifdef CONFIG_MMC_DEBUG
+static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
+{
+ /* --- means reserved bit without definition at documentation */
+ static const char *mmc_omap_status_bits[] = {
+ "CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ",
+ "OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC",
+ "CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---",
+ "---", "---", "---", "CERR", "CERR", "BADA", "---", "---", "---"
+ };
+ char res[256];
+ char *buf = res;
+ int len, i;
+
+ len = sprintf(buf, "MMC IRQ 0x%x :", status);
+ buf += len;
+
+ for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++)
+ if (status & (1 << i)) {
+ len = sprintf(buf, " %s", mmc_omap_status_bits[i]);
+ buf += len;
+ }
+
+ dev_dbg(mmc_dev(host->mmc), "%s\n", res);
+}
+#endif /* CONFIG_MMC_DEBUG */
+
+
+/*
+ * MMC controller IRQ handler
+ */
+static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
+{
+ struct mmc_omap_host *host = dev_id;
+ struct mmc_data *data;
+ int end_cmd = 0, end_trans = 0, status;
+
+ if (host->cmd == NULL && host->data == NULL) {
+ OMAP_HSMMC_WRITE(host->base, STAT,
+ OMAP_HSMMC_READ(host->base, STAT));
+ return IRQ_HANDLED;
+ }
+
+ data = host->data;
+ status = OMAP_HSMMC_READ(host->base, STAT);
+ dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
+
+ if (status & ERR) {
+#ifdef CONFIG_MMC_DEBUG
+ mmc_omap_report_irq(host, status);
+#endif
+ if ((status & CMD_TIMEOUT) ||
+ (status & CMD_CRC)) {
+ if (host->cmd) {
+ if (status & CMD_TIMEOUT) {
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base,
+ SYSCTL) | SRC);
+ while (OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRC)
+ ;
+
+ host->cmd->error = -ETIMEDOUT;
+ } else {
+ host->cmd->error = -EILSEQ;
+ }
+ end_cmd = 1;
+ }
+ if (host->data)
+ mmc_dma_cleanup(host);
+ }
+ if ((status & DATA_TIMEOUT) ||
+ (status & DATA_CRC)) {
+ if (host->data) {
+ if (status & DATA_TIMEOUT)
+ mmc_dma_cleanup(host);
+ else
+ host->data->error = -EILSEQ;
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base,
+ SYSCTL) | SRD);
+ while (OMAP_HSMMC_READ(host->base,
+ SYSCTL) & SRD)
+ ;
+ end_trans = 1;
+ }
+ }
+ if (status & CARD_ERR) {
+ dev_dbg(mmc_dev(host->mmc),
+ "Ignoring card err CMD%d\n", host->cmd->opcode);
+ if (host->cmd)
+ end_cmd = 1;
+ if (host->data)
+ end_trans = 1;
+ }
+ }
+
+ OMAP_HSMMC_WRITE(host->base, STAT, status);
+
+ if (end_cmd || (status & CC))
+ mmc_omap_cmd_done(host, host->cmd);
+ if (end_trans || (status & TC))
+ mmc_omap_xfer_done(host, data);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Switch MMC operating voltage
+ */
+static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
+{
+ u32 reg_val = 0;
+ int ret;
+
+ /* Disable the clocks */
+ clk_disable(host->fclk);
+ clk_disable(host->iclk);
+ clk_disable(host->dbclk);
+
+ /* Turn the power off */
+ ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
+ if (ret != 0)
+ goto err;
+
+ /* Turn the power ON with given VDD 1.8 or 3.0v */
+ ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd);
+ if (ret != 0)
+ goto err;
+
+ clk_enable(host->fclk);
+ clk_enable(host->iclk);
+ clk_enable(host->dbclk);
+
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
+ reg_val = OMAP_HSMMC_READ(host->base, HCTL);
+ /*
+ * If a MMC dual voltage card is detected, the set_ios fn calls
+ * this fn with VDD bit set for 1.8V. Upon card removal from the
+ * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
+ *
+ * Only MMC1 supports 3.0V. MMC2 will not function if SDVS30 is
+ * set in HCTL.
+ */
+ if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
+ ((1 << vdd) == MMC_VDD_33_34)))
+ reg_val |= SDVS30;
+ if ((1 << vdd) == MMC_VDD_165_195)
+ reg_val |= SDVS18;
+
+ OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
+
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+
+ return 0;
+err:
+ dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
+ return ret;
+}
+
+/*
+ * Work Item to notify the core about card insertion/removal
+ */
+static void mmc_omap_detect(struct work_struct *work)
+{
+ struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
+ mmc_carddetect_work);
+
+ sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
+ if (host->carddetect) {
+ mmc_detect_change(host->mmc, (HZ * 200) / 1000);
+ } else {
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
+ while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
+ ;
+
+ mmc_detect_change(host->mmc, (HZ * 50) / 1000);
+ }
+}
+
+/*
+ * ISR for handling card insertion and removal
+ */
+static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
+{
+ struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
+
+ host->carddetect = mmc_slot(host).card_detect(irq);
+ schedule_work(&host->mmc_carddetect_work);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * DMA call back function
+ */
+static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
+{
+ struct mmc_omap_host *host = data;
+
+ if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ)
+ dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n");
+
+ if (host->dma_ch < 0)
+ return;
+
+ omap_free_dma(host->dma_ch);
+ host->dma_ch = -1;
+ /*
+ * DMA Callback: run in interrupt context.
+ * mutex_unlock will through a kernel warning if used.
+ */
+ up(&host->sem);
+}
+
+/*
+ * Configure dma src and destination parameters
+ */
+static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
+ struct mmc_data *data)
+{
+ if (sync_dir == 0) {
+ omap_set_dma_dest_params(host->dma_ch, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+ omap_set_dma_src_params(host->dma_ch, 0,
+ OMAP_DMA_AMODE_POST_INC,
+ sg_dma_address(&data->sg[0]), 0, 0);
+ } else {
+ omap_set_dma_src_params(host->dma_ch, 0,
+ OMAP_DMA_AMODE_CONSTANT,
+ (host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+ omap_set_dma_dest_params(host->dma_ch, 0,
+ OMAP_DMA_AMODE_POST_INC,
+ sg_dma_address(&data->sg[0]), 0, 0);
+ }
+ return 0;
+}
+/*
+ * Routine to configure and start DMA for the MMC card
+ */
+static int
+mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
+{
+ int sync_dev, sync_dir = 0;
+ int dma_ch = 0, ret = 0, err = 1;
+ struct mmc_data *data = req->data;
+
+ /*
+ * If for some reason the DMA transfer is still active,
+ * we wait for timeout period and free the dma
+ */
+ if (host->dma_ch != -1) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(100);
+ if (down_trylock(&host->sem)) {
+ omap_free_dma(host->dma_ch);
+ host->dma_ch = -1;
+ up(&host->sem);
+ return err;
+ }
+ } else {
+ if (down_trylock(&host->sem))
+ return err;
+ }
+
+ if (!(data->flags & MMC_DATA_WRITE)) {
+ host->dma_dir = DMA_FROM_DEVICE;
+ if (host->id == OMAP_MMC1_DEVID)
+ sync_dev = OMAP24XX_DMA_MMC1_RX;
+ else
+ sync_dev = OMAP24XX_DMA_MMC2_RX;
+ } else {
+ host->dma_dir = DMA_TO_DEVICE;
+ if (host->id == OMAP_MMC1_DEVID)
+ sync_dev = OMAP24XX_DMA_MMC1_TX;
+ else
+ sync_dev = OMAP24XX_DMA_MMC2_TX;
+ }
+
+ ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
+ host, &dma_ch);
+ if (ret != 0) {
+ dev_dbg(mmc_dev(host->mmc),
+ "%s: omap_request_dma() failed with %d\n",
+ mmc_hostname(host->mmc), ret);
+ return ret;
+ }
+
+ host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
+ data->sg_len, host->dma_dir);
+ host->dma_ch = dma_ch;
+
+ if (!(data->flags & MMC_DATA_WRITE))
+ mmc_omap_config_dma_param(1, host, data);
+ else
+ mmc_omap_config_dma_param(0, host, data);
+
+ if ((data->blksz % 4) == 0)
+ omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
+ (data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
+ sync_dev, sync_dir);
+ else
+ /* REVISIT: The MMC buffer increments only when MSB is written.
+ * Return error for blksz which is non multiple of four.
+ */
+ return -EINVAL;
+
+ omap_start_dma(dma_ch);
+ return 0;
+}
+
+static void set_data_timeout(struct mmc_omap_host *host,
+ struct mmc_request *req)
+{
+ unsigned int timeout, cycle_ns;
+ uint32_t reg, clkd, dto = 0;
+
+ reg = OMAP_HSMMC_READ(host->base, SYSCTL);
+ clkd = (reg & CLKD_MASK) >> CLKD_SHIFT;
+ if (clkd == 0)
+ clkd = 1;
+
+ cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
+ timeout = req->data->timeout_ns / cycle_ns;
+ timeout += req->data->timeout_clks;
+ if (timeout) {
+ while ((timeout & 0x80000000) == 0) {
+ dto += 1;
+ timeout <<= 1;
+ }
+ dto = 31 - dto;
+ timeout <<= 1;
+ if (timeout && dto)
+ dto += 1;
+ if (dto >= 13)
+ dto -= 13;
+ else
+ dto = 0;
+ if (dto > 14)
+ dto = 14;
+ }
+
+ reg &= ~DTO_MASK;
+ reg |= dto << DTO_SHIFT;
+ OMAP_HSMMC_WRITE(host->base, SYSCTL, reg);
+}
+
+/*
+ * Configure block length for MMC/SD cards and initiate the transfer.
+ */
+static int
+mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
+{
+ int ret;
+ host->data = req->data;
+
+ if (req->data == NULL) {
+ host->datadir = OMAP_MMC_DATADIR_NONE;
+ OMAP_HSMMC_WRITE(host->base, BLK, 0);
+ return 0;
+ }
+
+ OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz)
+ | (req->data->blocks << 16));
+ set_data_timeout(host, req);
+
+ host->datadir = (req->data->flags & MMC_DATA_WRITE) ?
+ OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
+
+ if (host->use_dma) {
+ ret = mmc_omap_start_dma_transfer(host, req);
+ if (ret != 0) {
+ dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Request function. for read/write operation
+ */
+static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+ struct mmc_omap_host *host = mmc_priv(mmc);
+
+ WARN_ON(host->mrq != NULL);
+ host->mrq = req;
+ mmc_omap_prepare_data(host, req);
+ mmc_omap_start_command(host, req->cmd, req->data);
+}
+
+
+/* Routine to configure clock values. Exposed API to core */
+static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct mmc_omap_host *host = mmc_priv(mmc);
+ u16 dsor = 0;
+ unsigned long regval;
+ unsigned long timeout;
+
+ switch (ios->power_mode) {
+ case MMC_POWER_OFF:
+ mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
+ /*
+ * Reset bus voltage to 3V if it got set to 1.8V earlier.
+ * REVISIT: If we are able to detect cards after unplugging
+ * a 1.8V card, this code should not be needed.
+ */
+ if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+ int vdd = fls(host->mmc->ocr_avail) - 1;
+ if (omap_mmc_switch_opcond(host, vdd) != 0)
+ host->mmc->ios.vdd = vdd;
+ }
+ break;
+ case MMC_POWER_UP:
+ mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd);
+ break;
+ }
+
+ switch (mmc->ios.bus_width) {
+ case MMC_BUS_WIDTH_4:
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT);
+ break;
+ case MMC_BUS_WIDTH_1:
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT);
+ break;
+ }
+
+ if (host->id == OMAP_MMC1_DEVID) {
+ /* Only MMC1 can operate at 3V/1.8V */
+ if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
+ (ios->vdd == DUAL_VOLT_OCR_BIT)) {
+ /*
+ * The mmc_select_voltage fn of the core does
+ * not seem to set the power_mode to
+ * MMC_POWER_UP upon recalculating the voltage.
+ * vdd 1.8v.
+ */
+ if (omap_mmc_switch_opcond(host, ios->vdd) != 0)
+ dev_dbg(mmc_dev(host->mmc),
+ "Switch operation failed\n");
+ }
+ }
+
+ if (ios->clock) {
+ dsor = OMAP_MMC_MASTER_CLOCK / ios->clock;
+ if (dsor < 1)
+ dsor = 1;
+
+ if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock)
+ dsor++;
+
+ if (dsor > 250)
+ dsor = 250;
+ }
+ omap_mmc_stop_clock(host);
+ regval = OMAP_HSMMC_READ(host->base, SYSCTL);
+ regval = regval & ~(CLKD_MASK);
+ regval = regval | (dsor << 6) | (DTO << 16);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
+
+ /* Wait till the ICS bit is set */
+ timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
+ while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != 0x2
+ && time_before(jiffies, timeout))
+ msleep(1);
+
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | CEN);
+
+ if (ios->power_mode == MMC_POWER_ON)
+ send_init_stream(host);
+
+ if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
+ OMAP_HSMMC_WRITE(host->base, CON,
+ OMAP_HSMMC_READ(host->base, CON) | OD);
+}
+
+static int omap_hsmmc_get_cd(struct mmc_host *mmc)
+{
+ struct mmc_omap_host *host = mmc_priv(mmc);
+ struct omap_mmc_platform_data *pdata = host->pdata;
+
+ if (!pdata->slots[0].card_detect)
+ return -ENOSYS;
+ return pdata->slots[0].card_detect(pdata->slots[0].card_detect_irq);
+}
+
+static int omap_hsmmc_get_ro(struct mmc_host *mmc)
+{
+ struct mmc_omap_host *host = mmc_priv(mmc);
+ struct omap_mmc_platform_data *pdata = host->pdata;
+
+ if (!pdata->slots[0].get_ro)
+ return -ENOSYS;
+ return pdata->slots[0].get_ro(host->dev, 0);
+}
+
+static struct mmc_host_ops mmc_omap_ops = {
+ .request = omap_mmc_request,
+ .set_ios = omap_mmc_set_ios,
+ .get_cd = omap_hsmmc_get_cd,
+ .get_ro = omap_hsmmc_get_ro,
+ /* NYET -- enable_sdio_irq */
+};
+
+static int __init omap_mmc_probe(struct platform_device *pdev)
+{
+ struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
+ struct mmc_host *mmc;
+ struct mmc_omap_host *host = NULL;
+ struct resource *res;
+ int ret = 0, irq;
+ u32 hctl, capa;
+
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "Platform Data is missing\n");
+ return -ENXIO;
+ }
+
+ if (pdata->nr_slots == 0) {
+ dev_err(&pdev->dev, "No Slots\n");
+ return -ENXIO;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (res == NULL || irq < 0)
+ return -ENXIO;
+
+ res = request_mem_region(res->start, res->end - res->start + 1,
+ pdev->name);
+ if (res == NULL)
+ return -EBUSY;
+
+ mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev);
+ if (!mmc) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+ host->pdata = pdata;
+ host->dev = &pdev->dev;
+ host->use_dma = 1;
+ host->dev->dma_mask = &pdata->dma_mask;
+ host->dma_ch = -1;
+ host->irq = irq;
+ host->id = pdev->id;
+ host->slot_id = 0;
+ host->mapbase = res->start;
+ host->base = ioremap(host->mapbase, SZ_4K);
+
+ platform_set_drvdata(pdev, host);
+ INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect);
+
+ mmc->ops = &mmc_omap_ops;
+ mmc->f_min = 400000;
+ mmc->f_max = 52000000;
+
+ sema_init(&host->sem, 1);
+
+ host->iclk = clk_get(&pdev->dev, "mmchs_ick");
+ if (IS_ERR(host->iclk)) {
+ ret = PTR_ERR(host->iclk);
+ host->iclk = NULL;
+ goto err1;
+ }
+ host->fclk = clk_get(&pdev->dev, "mmchs_fck");
+ if (IS_ERR(host->fclk)) {
+ ret = PTR_ERR(host->fclk);
+ host->fclk = NULL;
+ clk_put(host->iclk);
+ goto err1;
+ }
+
+ if (clk_enable(host->fclk) != 0) {
+ clk_put(host->iclk);
+ clk_put(host->fclk);
+ goto err1;
+ }
+
+ if (clk_enable(host->iclk) != 0) {
+ clk_disable(host->fclk);
+ clk_put(host->iclk);
+ clk_put(host->fclk);
+ goto err1;
+ }
+
+ host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
+ /*
+ * MMC can still work without debounce clock.
+ */
+ if (IS_ERR(host->dbclk))
+ dev_warn(mmc_dev(host->mmc), "Failed to get debounce clock\n");
+ else
+ if (clk_enable(host->dbclk) != 0)
+ dev_dbg(mmc_dev(host->mmc), "Enabling debounce"
+ " clk failed\n");
+ else
+ host->dbclk_enabled = 1;
+
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+ mmc->max_phys_segs = 1;
+ mmc->max_hw_segs = 1;
+#endif
+ mmc->max_blk_size = 512; /* Block Length at max can be 1024 */
+ mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */
+ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+ mmc->max_seg_size = mmc->max_req_size;
+
+ mmc->ocr_avail = mmc_slot(host).ocr_mask;
+ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
+
+ if (pdata->slots[host->slot_id].wires >= 4)
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+
+ /* Only MMC1 supports 3.0V */
+ if (host->id == OMAP_MMC1_DEVID) {
+ hctl = SDVS30;
+ capa = VS30 | VS18;
+ } else {
+ hctl = SDVS18;
+ capa = VS18;
+ }
+
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) | hctl);
+
+ OMAP_HSMMC_WRITE(host->base, CAPA,
+ OMAP_HSMMC_READ(host->base, CAPA) | capa);
+
+ /* Set the controller to AUTO IDLE mode */
+ OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
+ OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
+
+ /* Set SD bus power bit */
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+
+ /* Request IRQ for MMC operations */
+ ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED,
+ mmc_hostname(mmc), host);
+ if (ret) {
+ dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
+ goto err_irq;
+ }
+
+ if (pdata->init != NULL) {
+ if (pdata->init(&pdev->dev) != 0) {
+ dev_dbg(mmc_dev(host->mmc),
+ "Unable to configure MMC IRQs\n");
+ goto err_irq_cd_init;
+ }
+ }
+
+ /* Request IRQ for card detect */
+ if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) {
+ ret = request_irq(mmc_slot(host).card_detect_irq,
+ omap_mmc_cd_handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_DISABLED,
+ mmc_hostname(mmc), host);
+ if (ret) {
+ dev_dbg(mmc_dev(host->mmc),
+ "Unable to grab MMC CD IRQ\n");
+ goto err_irq_cd;
+ }
+ }
+
+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
+ OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
+
+ mmc_add_host(mmc);
+
+ if (host->pdata->slots[host->slot_id].name != NULL) {
+ ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name);
+ if (ret < 0)
+ goto err_slot_name;
+ }
+ if (mmc_slot(host).card_detect_irq && mmc_slot(host).card_detect &&
+ host->pdata->slots[host->slot_id].get_cover_state) {
+ ret = device_create_file(&mmc->class_dev,
+ &dev_attr_cover_switch);
+ if (ret < 0)
+ goto err_cover_switch;
+ }
+
+ return 0;
+
+err_cover_switch:
+ device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
+err_slot_name:
+ mmc_remove_host(mmc);
+err_irq_cd:
+ free_irq(mmc_slot(host).card_detect_irq, host);
+err_irq_cd_init:
+ free_irq(host->irq, host);
+err_irq:
+ clk_disable(host->fclk);
+ clk_disable(host->iclk);
+ clk_put(host->fclk);
+ clk_put(host->iclk);
+ if (host->dbclk_enabled) {
+ clk_disable(host->dbclk);
+ clk_put(host->dbclk);
+ }
+
+err1:
+ iounmap(host->base);
+err:
+ dev_dbg(mmc_dev(host->mmc), "Probe Failed\n");
+ release_mem_region(res->start, res->end - res->start + 1);
+ if (host)
+ mmc_free_host(mmc);
+ return ret;
+}
+
+static int omap_mmc_remove(struct platform_device *pdev)
+{
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+ struct resource *res;
+
+ if (host) {
+ mmc_remove_host(host->mmc);
+ if (host->pdata->cleanup)
+ host->pdata->cleanup(&pdev->dev);
+ free_irq(host->irq, host);
+ if (mmc_slot(host).card_detect_irq)
+ free_irq(mmc_slot(host).card_detect_irq, host);
+ flush_scheduled_work();
+
+ clk_disable(host->fclk);
+ clk_disable(host->iclk);
+ clk_put(host->fclk);
+ clk_put(host->iclk);
+ if (host->dbclk_enabled) {
+ clk_disable(host->dbclk);
+ clk_put(host->dbclk);
+ }
+
+ mmc_free_host(host->mmc);
+ iounmap(host->base);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start, res->end - res->start + 1);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret = 0;
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+ if (host && host->suspended)
+ return 0;
+
+ if (host) {
+ ret = mmc_suspend_host(host->mmc, state);
+ if (ret == 0) {
+ host->suspended = 1;
+
+ OMAP_HSMMC_WRITE(host->base, ISE, 0);
+ OMAP_HSMMC_WRITE(host->base, IE, 0);
+
+ if (host->pdata->suspend) {
+ ret = host->pdata->suspend(&pdev->dev,
+ host->slot_id);
+ if (ret)
+ dev_dbg(mmc_dev(host->mmc),
+ "Unable to handle MMC board"
+ " level suspend\n");
+ }
+
+ if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL)
+ & SDVSCLR);
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL)
+ | SDVS30);
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL)
+ | SDBP);
+ }
+
+ clk_disable(host->fclk);
+ clk_disable(host->iclk);
+ clk_disable(host->dbclk);
+ }
+
+ }
+ return ret;
+}
+
+/* Routine to resume the MMC device */
+static int omap_mmc_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct mmc_omap_host *host = platform_get_drvdata(pdev);
+
+ if (host && !host->suspended)
+ return 0;
+
+ if (host) {
+
+ ret = clk_enable(host->fclk);
+ if (ret)
+ goto clk_en_err;
+
+ ret = clk_enable(host->iclk);
+ if (ret) {
+ clk_disable(host->fclk);
+ clk_put(host->fclk);
+ goto clk_en_err;
+ }
+
+ if (clk_enable(host->dbclk) != 0)
+ dev_dbg(mmc_dev(host->mmc),
+ "Enabling debounce clk failed\n");
+
+ if (host->pdata->resume) {
+ ret = host->pdata->resume(&pdev->dev, host->slot_id);
+ if (ret)
+ dev_dbg(mmc_dev(host->mmc),
+ "Unmask interrupt failed\n");
+ }
+
+ /* Notify the core to resume the host */
+ ret = mmc_resume_host(host->mmc);
+ if (ret == 0)
+ host->suspended = 0;
+ }
+
+ return ret;
+
+clk_en_err:
+ dev_dbg(mmc_dev(host->mmc),
+ "Failed to enable MMC clocks during resume\n");
+ return ret;
+}
+
+#else
+#define omap_mmc_suspend NULL
+#define omap_mmc_resume NULL
+#endif
+
+static struct platform_driver omap_mmc_driver = {
+ .probe = omap_mmc_probe,
+ .remove = omap_mmc_remove,
+ .suspend = omap_mmc_suspend,
+ .resume = omap_mmc_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init omap_mmc_init(void)
+{
+ /* Register the MMC driver */
+ return platform_driver_register(&omap_mmc_driver);
+}
+
+static void __exit omap_mmc_cleanup(void)
+{
+ /* Unregister MMC driver */
+ platform_driver_unregister(&omap_mmc_driver);
+}
+
+module_init(omap_mmc_init);
+module_exit(omap_mmc_cleanup);
+
+MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index f88cc7406354..9702ad3774cf 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -180,7 +180,15 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
else
DALGN &= ~(1 << host->dma);
DDADR(host->dma) = host->sg_dma;
- DCSR(host->dma) = DCSR_RUN;
+
+ /*
+ * workaround for erratum #91:
+ * only start DMA now if we are doing a read,
+ * otherwise we wait until CMD/RESP has finished
+ * before starting DMA.
+ */
+ if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ)
+ DCSR(host->dma) = DCSR_RUN;
}
static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat)
@@ -251,23 +259,28 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
if (stat & STAT_TIME_OUT_RESPONSE) {
cmd->error = -ETIMEDOUT;
} else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
-#ifdef CONFIG_PXA27x
/*
* workaround for erratum #42:
* Intel PXA27x Family Processor Specification Update Rev 001
* A bogus CRC error can appear if the msb of a 136 bit
* response is a one.
*/
- if (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000) {
+ if (cpu_is_pxa27x() &&
+ (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000))
pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode);
- } else
-#endif
- cmd->error = -EILSEQ;
+ else
+ cmd->error = -EILSEQ;
}
pxamci_disable_irq(host, END_CMD_RES);
if (host->data && !cmd->error) {
pxamci_enable_irq(host, DATA_TRAN_DONE);
+ /*
+ * workaround for erratum #91, if doing write
+ * enable DMA late
+ */
+ if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE)
+ DCSR(host->dma) = DCSR_RUN;
} else {
pxamci_finish_request(host, host->mrq);
}
@@ -283,7 +296,7 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
return 0;
DCSR(host->dma) = 0;
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
host->dma_dir);
if (stat & STAT_READ_TIME_OUT)
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c
index a16d7609e4ee..f62790513322 100644
--- a/drivers/mmc/host/ricoh_mmc.c
+++ b/drivers/mmc/host/ricoh_mmc.c
@@ -11,9 +11,10 @@
/*
* This is a conceptually ridiculous driver, but it is required by the way
- * the Ricoh multi-function R5C832 works. This chip implements firewire
- * and four different memory card controllers. Two of those controllers are
- * an SDHCI controller and a proprietary MMC controller. The linux SDHCI
+ * the Ricoh multi-function chips (R5CXXX) work. These chips implement
+ * the four main memory card controllers (SD, MMC, MS, xD) and one or both
+ * of cardbus or firewire. It happens that they implement SD and MMC
+ * support as separate controllers (and PCI functions). The linux SDHCI
* driver supports MMC cards but the chip detects MMC cards in hardware
* and directs them to the MMC controller - so the SDHCI driver never sees
* them. To get around this, we must disable the useless MMC controller.
@@ -21,8 +22,10 @@
* a detection event occurs immediately, even if the MMC card is already
* in the reader.
*
- * The relevant registers live on the firewire function, so this is unavoidably
- * ugly. Such is life.
+ * It seems to be the case that the relevant PCI registers to deactivate the
+ * MMC controller live on PCI function 0, which might be the cardbus controller
+ * or the firewire controller, depending on the particular chip in question. As
+ * such, it makes what this driver has to do unavoidably ugly. Such is life.
*/
#include <linux/pci.h>
@@ -143,6 +146,7 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
pci_get_device(PCI_VENDOR_ID_RICOH,
PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) {
if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
+ PCI_FUNC(fw_dev->devfn) == 0 &&
pdev->bus == fw_dev->bus) {
if (ricoh_mmc_disable(fw_dev) != 0)
return -ENODEV;
@@ -160,6 +164,7 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
(fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH,
PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
+ PCI_FUNC(fw_dev->devfn) == 0 &&
pdev->bus == fw_dev->bus) {
if (ricoh_mmc_disable(fw_dev) != 0)
return -ENODEV;
@@ -172,7 +177,7 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
if (!ctrlfound) {
printk(KERN_WARNING DRIVER_NAME
- ": Main firewire function not found. Cannot disable controller.\n");
+ ": Main Ricoh function not found. Cannot disable controller.\n");
return -ENODEV;
}
@@ -191,7 +196,7 @@ static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
-static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state)
+static int ricoh_mmc_suspend_late(struct pci_dev *pdev, pm_message_t state)
{
struct pci_dev *fw_dev = NULL;
@@ -205,7 +210,7 @@ static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
-static int ricoh_mmc_resume(struct pci_dev *pdev)
+static int ricoh_mmc_resume_early(struct pci_dev *pdev)
{
struct pci_dev *fw_dev = NULL;
@@ -224,8 +229,8 @@ static struct pci_driver ricoh_mmc_driver = {
.id_table = pci_ids,
.probe = ricoh_mmc_probe,
.remove = __devexit_p(ricoh_mmc_remove),
- .suspend = ricoh_mmc_suspend,
- .resume = ricoh_mmc_resume,
+ .suspend_late = ricoh_mmc_suspend_late,
+ .resume_early = ricoh_mmc_resume_early,
};
/*****************************************************************************\
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index fcc98a4cce3c..35a98eec7414 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -20,7 +20,7 @@
#include <linux/irq.h>
#include <linux/io.h>
-#include <asm/dma.h>
+#include <mach/dma.h>
#include <mach/regs-sdi.h>
#include <mach/regs-gpio.h>
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 9bd7026b0021..f07255cb17ee 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -545,7 +545,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
}
addr = pci_resource_start(pdev, bar);
- host->ioaddr = ioremap_nocache(addr, pci_resource_len(pdev, bar));
+ host->ioaddr = pci_ioremap_bar(pdev, bar);
if (!host->ioaddr) {
dev_err(&pdev->dev, "failed to remap registers\n");
goto release;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 4d010a984bed..6b2d1f99af67 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -30,6 +30,11 @@
#define DBG(f, x...) \
pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
+#if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \
+ defined(CONFIG_MMC_SDHCI_MODULE))
+#define SDHCI_USE_LEDS_CLASS
+#endif
+
static unsigned int debug_quirks = 0;
static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
@@ -149,7 +154,7 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
}
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
static void sdhci_led_control(struct led_classdev *led,
enum led_brightness brightness)
{
@@ -994,7 +999,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
WARN_ON(host->mrq != NULL);
-#ifndef CONFIG_LEDS_CLASS
+#ifndef SDHCI_USE_LEDS_CLASS
sdhci_activate_led(host);
#endif
@@ -1201,7 +1206,7 @@ static void sdhci_tasklet_finish(unsigned long param)
host->cmd = NULL;
host->data = NULL;
-#ifndef CONFIG_LEDS_CLASS
+#ifndef SDHCI_USE_LEDS_CLASS
sdhci_deactivate_led(host);
#endif
@@ -1717,7 +1722,7 @@ int sdhci_add_host(struct sdhci_host *host)
sdhci_dumpregs(host);
#endif
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
host->led.name = mmc_hostname(mmc);
host->led.brightness = LED_OFF;
host->led.default_trigger = mmc_hostname(mmc);
@@ -1739,7 +1744,7 @@ int sdhci_add_host(struct sdhci_host *host)
return 0;
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
reset:
sdhci_reset(host, SDHCI_RESET_ALL);
free_irq(host->irq, host);
@@ -1775,7 +1780,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
mmc_remove_host(host->mmc);
-#ifdef CONFIG_LEDS_CLASS
+#ifdef SDHCI_USE_LEDS_CLASS
led_classdev_unregister(&host->led);
#endif
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 31f4b1528e76..3efba2363941 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -220,7 +220,7 @@ struct sdhci_host {
struct mmc_host *mmc; /* MMC structure */
u64 dma_mask; /* custom DMA mask */
-#ifdef CONFIG_LEDS_CLASS
+#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
struct led_classdev led; /* LED control */
#endif
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index 1df44d966bdb..cb41e9c3ac07 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -82,6 +82,8 @@ static struct pcmcia_device_id pcmcia_ids[] = {
/* vendor and device strings followed by their crc32 hashes */
PCMCIA_DEVICE_PROD_ID12("RICOH", "Bay1Controller", 0xd9f522ed,
0xc3901202),
+ PCMCIA_DEVICE_PROD_ID12("RICOH", "Bay Controller", 0xd9f522ed,
+ 0xace80909),
PCMCIA_DEVICE_NULL,
};
@@ -463,7 +465,7 @@ static int sdricoh_init_mmc(struct pci_dev *pci_dev,
err:
if (iobase)
- iounmap(iobase);
+ pci_iounmap(pci_dev, iobase);
if (mmc)
mmc_free_host(mmc);
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 95430b81ec11..6a7a61904833 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -224,7 +224,7 @@ static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
{
void __iomem *ctl = host->ctl;
struct mmc_data *data = host->data;
- struct mmc_command *stop = data->stop;
+ struct mmc_command *stop;
host->data = NULL;
@@ -232,6 +232,7 @@ static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
pr_debug("Spurious data end IRQ\n");
return;
}
+ stop = data->stop;
/* FIXME - return correct transfer count on errors */
if (!data->error)
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index a90d50c2c3e5..7d04fb9ddcaa 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -45,6 +45,14 @@ config MTD_PARTITIONS
devices. Partitioning on NFTL 'devices' is a different - that's the
'normal' form of partitioning used on a block device.
+config MTD_TESTS
+ tristate "MTD tests support"
+ depends on m
+ help
+ This option includes various MTD tests into compilation. The tests
+ should normally be compiled as kernel modules. The modules perform
+ various checks and verifications when loaded.
+
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
depends on MTD_PARTITIONS
@@ -316,6 +324,8 @@ source "drivers/mtd/nand/Kconfig"
source "drivers/mtd/onenand/Kconfig"
+source "drivers/mtd/lpddr/Kconfig"
+
source "drivers/mtd/ubi/Kconfig"
endif # MTD
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 4b77335715f0..4521b1ecce45 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -29,6 +29,6 @@ obj-$(CONFIG_MTD_OOPS) += mtdoops.o
nftl-objs := nftlcore.o nftlmount.o
inftl-objs := inftlcore.o inftlmount.o
-obj-y += chips/ maps/ devices/ nand/ onenand/
+obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
obj-$(CONFIG_MTD_UBI) += ubi/
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index c93a8be5d5f1..f5ab6fa1057b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -58,8 +58,8 @@ static int cfi_intelext_write_buffers(struct mtd_info *, loff_t, size_t, size_t
static int cfi_intelext_writev(struct mtd_info *, const struct kvec *, unsigned long, loff_t, size_t *);
static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
static void cfi_intelext_sync (struct mtd_info *);
-static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
-static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
#ifdef CONFIG_MTD_OTP
static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
@@ -558,8 +558,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
}
for (i=0; i<mtd->numeraseregions;i++){
- printk(KERN_DEBUG "erase region %d: offset=0x%x,size=0x%x,blocks=%d\n",
- i,mtd->eraseregions[i].offset,
+ printk(KERN_DEBUG "erase region %d: offset=0x%llx,size=0x%x,blocks=%d\n",
+ i,(unsigned long long)mtd->eraseregions[i].offset,
mtd->eraseregions[i].erasesize,
mtd->eraseregions[i].numblocks);
}
@@ -2058,7 +2058,7 @@ out: put_chip(map, chip, adr);
return ret;
}
-static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret;
@@ -2082,7 +2082,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
return ret;
}
-static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret;
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index d74ec46aa032..94bb61e19047 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -71,8 +71,8 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
#include "fwh_lock.h"
-static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
-static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static struct mtd_chip_driver cfi_amdstd_chipdrv = {
.probe = NULL, /* Not usable directly */
@@ -322,6 +322,14 @@ static struct cfi_fixup fixup_table[] = {
};
+static void cfi_fixup_major_minor(struct cfi_private *cfi,
+ struct cfi_pri_amdstd *extp)
+{
+ if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
+ extp->MajorVersion == '0')
+ extp->MajorVersion = '1';
+}
+
struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
{
struct cfi_private *cfi = map->fldrv_priv;
@@ -363,6 +371,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
return NULL;
}
+ cfi_fixup_major_minor(cfi, extp);
+
if (extp->MajorVersion != '1' ||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
@@ -1774,12 +1784,12 @@ out_unlock:
return ret;
}
-static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL);
}
-static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL);
}
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index d4714dd9f7ab..6c740f346f91 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -42,8 +42,8 @@ static int cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen);
static int cfi_staa_erase_varsize(struct mtd_info *, struct erase_info *);
static void cfi_staa_sync (struct mtd_info *);
-static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
-static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
+static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
static int cfi_staa_suspend (struct mtd_info *);
static void cfi_staa_resume (struct mtd_info *);
@@ -221,8 +221,8 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
}
for (i=0; i<mtd->numeraseregions;i++){
- printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n",
- i,mtd->eraseregions[i].offset,
+ printk(KERN_DEBUG "%d: offset=0x%llx,size=0x%x,blocks=%d\n",
+ i, (unsigned long long)mtd->eraseregions[i].offset,
mtd->eraseregions[i].erasesize,
mtd->eraseregions[i].numblocks);
}
@@ -964,7 +964,7 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,
adr += regions[i].erasesize;
len -= regions[i].erasesize;
- if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+ if (adr % (1<< cfi->chipshift) == (((unsigned long)regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
i++;
if (adr >> cfi->chipshift) {
@@ -1135,7 +1135,7 @@ retry:
spin_unlock_bh(chip->mutex);
return 0;
}
-static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
@@ -1284,7 +1284,7 @@ retry:
spin_unlock_bh(chip->mutex);
return 0;
}
-static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
diff --git a/drivers/mtd/chips/fwh_lock.h b/drivers/mtd/chips/fwh_lock.h
index ab44f2b996f8..57e0e4e921f9 100644
--- a/drivers/mtd/chips/fwh_lock.h
+++ b/drivers/mtd/chips/fwh_lock.h
@@ -77,7 +77,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
}
-static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret;
@@ -88,7 +88,7 @@ static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
}
-static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret;
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 6fde0a2e3567..bc33200535fc 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -120,6 +120,13 @@ config MTD_PHRAM
doesn't have access to, memory beyond the mem=xxx limit, nvram,
memory on the video card, etc...
+config MTD_PS3VRAM
+ tristate "PS3 video RAM"
+ depends on FB_PS3
+ help
+ This driver allows you to use excess PS3 video RAM as volatile
+ storage or system swap.
+
config MTD_LART
tristate "28F160xx flash driver for LART"
depends on SA1100_LART
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 0993d5cf3923..e51521df4e40 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_MTD_LART) += lart.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
+obj-$(CONFIG_MTD_PS3VRAM) += ps3vram.o
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index f4bda4cee495..578de1c67bfe 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -619,7 +619,7 @@ static struct mtd_partition lart_partitions[] = {
};
#endif
-int __init lart_flash_init (void)
+static int __init lart_flash_init (void)
{
int result;
memset (&mtd,0,sizeof (mtd));
@@ -690,7 +690,7 @@ int __init lart_flash_init (void)
return (result);
}
-void __exit lart_flash_exit (void)
+static void __exit lart_flash_exit (void)
{
#ifndef HAVE_PARTITIONS
del_mtd_device (&mtd);
@@ -705,5 +705,3 @@ module_exit (lart_flash_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Abraham vd Merwe <abraham@2d3d.co.za>");
MODULE_DESCRIPTION("MTD driver for Intel 28F160F3 on LART board");
-
-
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 6659b2275c0c..7c3fc766dcf1 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
+#include <linux/math64.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
@@ -169,9 +170,9 @@ static int wait_till_ready(struct m25p *flash)
*/
static int erase_chip(struct m25p *flash)
{
- DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n",
- flash->spi->dev.bus_id, __func__,
- flash->mtd.size / 1024);
+ DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
+ dev_name(&flash->spi->dev), __func__,
+ (long long)(flash->mtd.size >> 10));
/* Wait until finished previous write command. */
if (wait_till_ready(flash))
@@ -197,7 +198,7 @@ static int erase_chip(struct m25p *flash)
static int erase_sector(struct m25p *flash, u32 offset)
{
DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
- flash->spi->dev.bus_id, __func__,
+ dev_name(&flash->spi->dev), __func__,
flash->mtd.erasesize / 1024, offset);
/* Wait until finished previous write command. */
@@ -232,18 +233,18 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct m25p *flash = mtd_to_m25p(mtd);
u32 addr,len;
+ uint32_t rem;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
- flash->spi->dev.bus_id, __func__, "at",
- (u32)instr->addr, instr->len);
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n",
+ dev_name(&flash->spi->dev), __func__, "at",
+ (long long)instr->addr, (long long)instr->len);
/* sanity checks */
if (instr->addr + instr->len > flash->mtd.size)
return -EINVAL;
- if ((instr->addr % mtd->erasesize) != 0
- || (instr->len % mtd->erasesize) != 0) {
+ div_u64_rem(instr->len, mtd->erasesize, &rem);
+ if (rem)
return -EINVAL;
- }
addr = instr->addr;
len = instr->len;
@@ -295,7 +296,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
struct spi_message m;
DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
- flash->spi->dev.bus_id, __func__, "from",
+ dev_name(&flash->spi->dev), __func__, "from",
(u32)from, len);
/* sanity checks */
@@ -367,7 +368,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
struct spi_message m;
DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
- flash->spi->dev.bus_id, __func__, "to",
+ dev_name(&flash->spi->dev), __func__, "to",
(u32)to, len);
if (retlen)
@@ -563,7 +564,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
tmp = spi_write_then_read(spi, &code, 1, id, 5);
if (tmp < 0) {
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
- spi->dev.bus_id, tmp);
+ dev_name(&spi->dev), tmp);
return NULL;
}
jedec = id[0];
@@ -617,7 +618,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
/* unrecognized chip? */
if (i == ARRAY_SIZE(m25p_data)) {
DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
- spi->dev.bus_id, data->type);
+ dev_name(&spi->dev), data->type);
info = NULL;
/* recognized; is that chip really what's there? */
@@ -658,7 +659,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
if (data && data->name)
flash->mtd.name = data->name;
else
- flash->mtd.name = spi->dev.bus_id;
+ flash->mtd.name = dev_name(&spi->dev);
flash->mtd.type = MTD_NORFLASH;
flash->mtd.writesize = 1;
@@ -677,24 +678,24 @@ static int __devinit m25p_probe(struct spi_device *spi)
flash->mtd.erasesize = info->sector_size;
}
- dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
- flash->mtd.size / 1024);
+ dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
+ (long long)flash->mtd.size >> 10);
DEBUG(MTD_DEBUG_LEVEL2,
- "mtd .name = %s, .size = 0x%.8x (%uMiB) "
+ "mtd .name = %s, .size = 0x%llx (%lldMiB) "
".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
flash->mtd.name,
- flash->mtd.size, flash->mtd.size / (1024*1024),
+ (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
flash->mtd.erasesize, flash->mtd.erasesize / 1024,
flash->mtd.numeraseregions);
if (flash->mtd.numeraseregions)
for (i = 0; i < flash->mtd.numeraseregions; i++)
DEBUG(MTD_DEBUG_LEVEL2,
- "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
+ "mtd.eraseregions[%d] = { .offset = 0x%llx, "
".erasesize = 0x%.8x (%uKiB), "
".numblocks = %d }\n",
- i, flash->mtd.eraseregions[i].offset,
+ i, (long long)flash->mtd.eraseregions[i].offset,
flash->mtd.eraseregions[i].erasesize,
flash->mtd.eraseregions[i].erasesize / 1024,
flash->mtd.eraseregions[i].numblocks);
@@ -722,12 +723,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
if (nr_parts > 0) {
for (i = 0; i < nr_parts; i++) {
DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
- "{.name = %s, .offset = 0x%.8x, "
- ".size = 0x%.8x (%uKiB) }\n",
+ "{.name = %s, .offset = 0x%llx, "
+ ".size = 0x%llx (%lldKiB) }\n",
i, parts[i].name,
- parts[i].offset,
- parts[i].size,
- parts[i].size / 1024);
+ (long long)parts[i].offset,
+ (long long)parts[i].size,
+ (long long)(parts[i].size >> 10));
}
flash->partitioned = 1;
return add_mtd_partitions(&flash->mtd, parts, nr_parts);
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 6dd9aff8bb2d..d44f741ae229 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -16,6 +16,7 @@
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/err.h>
+#include <linux/math64.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
@@ -128,7 +129,7 @@ static int dataflash_waitready(struct spi_device *spi)
status = dataflash_status(spi);
if (status < 0) {
DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
- spi->dev.bus_id, status);
+ dev_name(&spi->dev), status);
status = 0;
}
@@ -152,15 +153,20 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
struct spi_message msg;
unsigned blocksize = priv->page_size << 3;
uint8_t *command;
+ uint32_t rem;
- DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n",
- spi->dev.bus_id,
- instr->addr, instr->len);
+ DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n",
+ dev_name(&spi->dev), (long long)instr->addr,
+ (long long)instr->len);
/* Sanity checks */
- if ((instr->addr + instr->len) > mtd->size
- || (instr->len % priv->page_size) != 0
- || (instr->addr % priv->page_size) != 0)
+ if (instr->addr + instr->len > mtd->size)
+ return -EINVAL;
+ div_u64_rem(instr->len, priv->page_size, &rem);
+ if (rem)
+ return -EINVAL;
+ div_u64_rem(instr->addr, priv->page_size, &rem);
+ if (rem)
return -EINVAL;
spi_message_init(&msg);
@@ -178,7 +184,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
/* Calculate flash page address; use block erase (for speed) if
* we're at a block boundary and need to erase the whole block.
*/
- pageaddr = instr->addr / priv->page_size;
+ pageaddr = div_u64(instr->len, priv->page_size);
do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize;
pageaddr = pageaddr << priv->page_offset;
@@ -197,7 +203,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
if (status < 0) {
printk(KERN_ERR "%s: erase %x, err %d\n",
- spi->dev.bus_id, pageaddr, status);
+ dev_name(&spi->dev), pageaddr, status);
/* REVISIT: can retry instr->retries times; or
* giveup and instr->fail_addr = instr->addr;
*/
@@ -239,7 +245,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
int status;
DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
- priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len));
+ dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len));
*retlen = 0;
@@ -288,7 +294,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
status = 0;
} else
DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
- priv->spi->dev.bus_id,
+ dev_name(&priv->spi->dev),
(unsigned)from, (unsigned)(from + len),
status);
return status;
@@ -315,7 +321,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
uint8_t *command;
DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
- spi->dev.bus_id, (unsigned)to, (unsigned)(to + len));
+ dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
*retlen = 0;
@@ -374,7 +380,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
status = spi_sync(spi, &msg);
if (status < 0)
DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
- spi->dev.bus_id, addr, status);
+ dev_name(&spi->dev), addr, status);
(void) dataflash_waitready(priv->spi);
}
@@ -396,7 +402,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
spi_transfer_del(x + 1);
if (status < 0)
DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
- spi->dev.bus_id, addr, writelen, status);
+ dev_name(&spi->dev), addr, writelen, status);
(void) dataflash_waitready(priv->spi);
@@ -416,14 +422,14 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
status = spi_sync(spi, &msg);
if (status < 0)
DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
- spi->dev.bus_id, addr, status);
+ dev_name(&spi->dev), addr, status);
status = dataflash_waitready(priv->spi);
/* Check result of the compare operation */
if (status & (1 << 6)) {
printk(KERN_ERR "%s: compare page %u, err %d\n",
- spi->dev.bus_id, pageaddr, status);
+ dev_name(&spi->dev), pageaddr, status);
remaining = 0;
status = -EIO;
break;
@@ -667,8 +673,8 @@ add_dataflash_otp(struct spi_device *spi, char *name,
if (revision >= 'c')
otp_tag = otp_setup(device, revision);
- dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes%s\n",
- name, DIV_ROUND_UP(device->size, 1024),
+ dev_info(&spi->dev, "%s (%lld KBytes) pagesize %d bytes%s\n",
+ name, (long long)((device->size + 1023) >> 10),
pagesize, otp_tag);
dev_set_drvdata(&spi->dev, priv);
@@ -779,7 +785,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
tmp = spi_write_then_read(spi, &code, 1, id, 3);
if (tmp < 0) {
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
- spi->dev.bus_id, tmp);
+ dev_name(&spi->dev), tmp);
return ERR_PTR(tmp);
}
if (id[0] != 0x1f)
@@ -869,7 +875,7 @@ static int __devinit dataflash_probe(struct spi_device *spi)
status = dataflash_status(spi);
if (status <= 0 || status == 0xff) {
DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
- spi->dev.bus_id, status);
+ dev_name(&spi->dev), status);
if (status == 0 || status == 0xff)
status = -ENODEV;
return status;
@@ -905,13 +911,13 @@ static int __devinit dataflash_probe(struct spi_device *spi)
/* obsolete AT45DB1282 not (yet?) supported */
default:
DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
- spi->dev.bus_id, status & 0x3c);
+ dev_name(&spi->dev), status & 0x3c);
status = -ENODEV;
}
if (status < 0)
DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
- spi->dev.bus_id, status);
+ dev_name(&spi->dev), status);
return status;
}
@@ -921,7 +927,7 @@ static int __devexit dataflash_remove(struct spi_device *spi)
struct dataflash *flash = dev_get_drvdata(&spi->dev);
int status;
- DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id);
+ DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev));
if (mtd_has_partitions() && flash->partitioned)
status = del_mtd_partitions(&flash->mtd);
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index d38bca64bb15..d2fd550f7e09 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -34,7 +34,7 @@
* aperture size, not the dram size, and the V370PDC supplies no
* other method for memory size discovery. This problem is
* mostly only relevant when compiled as a module, as the
- * unloading of the module with an aperture size smaller then
+ * unloading of the module with an aperture size smaller than
* the ram will cause the driver to detect the onboard memory
* size to be equal to the aperture size when the module is
* reloaded. Soooo, to help, the module supports an msize
diff --git a/drivers/mtd/devices/ps3vram.c b/drivers/mtd/devices/ps3vram.c
new file mode 100644
index 000000000000..d21e9beb7ed2
--- /dev/null
+++ b/drivers/mtd/devices/ps3vram.c
@@ -0,0 +1,768 @@
+/**
+ * ps3vram - Use extra PS3 video ram as MTD block device.
+ *
+ * Copyright (c) 2007-2008 Jim Paris <jim@jtan.com>
+ * Added support RSX DMA Vivien Chappelier <vivien.chappelier@free.fr>
+ */
+
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/gfp.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+
+#include <asm/lv1call.h>
+#include <asm/ps3.h>
+
+#define DEVICE_NAME "ps3vram"
+
+#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */
+#define XDR_IOIF 0x0c000000
+
+#define FIFO_BASE XDR_IOIF
+#define FIFO_SIZE (64 * 1024)
+
+#define DMA_PAGE_SIZE (4 * 1024)
+
+#define CACHE_PAGE_SIZE (256 * 1024)
+#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE)
+
+#define CACHE_OFFSET CACHE_PAGE_SIZE
+#define FIFO_OFFSET 0
+
+#define CTRL_PUT 0x10
+#define CTRL_GET 0x11
+#define CTRL_TOP 0x15
+
+#define UPLOAD_SUBCH 1
+#define DOWNLOAD_SUBCH 2
+
+#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c
+#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104
+
+#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601
+
+struct mtd_info ps3vram_mtd;
+
+#define CACHE_PAGE_PRESENT 1
+#define CACHE_PAGE_DIRTY 2
+
+struct ps3vram_tag {
+ unsigned int address;
+ unsigned int flags;
+};
+
+struct ps3vram_cache {
+ unsigned int page_count;
+ unsigned int page_size;
+ struct ps3vram_tag *tags;
+};
+
+struct ps3vram_priv {
+ u64 memory_handle;
+ u64 context_handle;
+ u32 *ctrl;
+ u32 *reports;
+ u8 __iomem *ddr_base;
+ u8 *xdr_buf;
+
+ u32 *fifo_base;
+ u32 *fifo_ptr;
+
+ struct device *dev;
+ struct ps3vram_cache cache;
+
+ /* Used to serialize cache/DMA operations */
+ struct mutex lock;
+};
+
+#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */
+#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */
+#define DMA_NOTIFIER_SIZE 0x40
+#define NOTIFIER 7 /* notifier used for completion report */
+
+/* A trailing '-' means to subtract off ps3fb_videomemory.size */
+char *size = "256M-";
+module_param(size, charp, 0);
+MODULE_PARM_DESC(size, "memory size");
+
+static u32 *ps3vram_get_notifier(u32 *reports, int notifier)
+{
+ return (void *) reports +
+ DMA_NOTIFIER_OFFSET_BASE +
+ DMA_NOTIFIER_SIZE * notifier;
+}
+
+static void ps3vram_notifier_reset(struct mtd_info *mtd)
+{
+ int i;
+
+ struct ps3vram_priv *priv = mtd->priv;
+ u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
+ for (i = 0; i < 4; i++)
+ notify[i] = 0xffffffff;
+}
+
+static int ps3vram_notifier_wait(struct mtd_info *mtd, unsigned int timeout_ms)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER);
+ unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+
+ do {
+ if (!notify[3])
+ return 0;
+ msleep(1);
+ } while (time_before(jiffies, timeout));
+
+ return -ETIMEDOUT;
+}
+
+static void ps3vram_init_ring(struct mtd_info *mtd)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+
+ priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
+ priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET;
+}
+
+static int ps3vram_wait_ring(struct mtd_info *mtd, unsigned int timeout_ms)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+
+ do {
+ if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET])
+ return 0;
+ msleep(1);
+ } while (time_before(jiffies, timeout));
+
+ dev_dbg(priv->dev, "%s:%d: FIFO timeout (%08x/%08x/%08x)\n", __func__,
+ __LINE__, priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET],
+ priv->ctrl[CTRL_TOP]);
+
+ return -ETIMEDOUT;
+}
+
+static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data)
+{
+ *(priv->fifo_ptr)++ = data;
+}
+
+static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan,
+ u32 tag, u32 size)
+{
+ ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag);
+}
+
+static void ps3vram_rewind_ring(struct mtd_info *mtd)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ u64 status;
+
+ ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET));
+
+ priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET;
+
+ /* asking the HV for a blit will kick the fifo */
+ status = lv1_gpu_context_attribute(priv->context_handle,
+ L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
+ 0, 0, 0, 0);
+ if (status)
+ dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n",
+ __func__, __LINE__);
+
+ priv->fifo_ptr = priv->fifo_base;
+}
+
+static void ps3vram_fire_ring(struct mtd_info *mtd)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ u64 status;
+
+ mutex_lock(&ps3_gpu_mutex);
+
+ priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET +
+ (priv->fifo_ptr - priv->fifo_base) * sizeof(u32);
+
+ /* asking the HV for a blit will kick the fifo */
+ status = lv1_gpu_context_attribute(priv->context_handle,
+ L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
+ 0, 0, 0, 0);
+ if (status)
+ dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n",
+ __func__, __LINE__);
+
+ if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) >
+ FIFO_SIZE - 1024) {
+ dev_dbg(priv->dev, "%s:%d: fifo full, rewinding\n", __func__,
+ __LINE__);
+ ps3vram_wait_ring(mtd, 200);
+ ps3vram_rewind_ring(mtd);
+ }
+
+ mutex_unlock(&ps3_gpu_mutex);
+}
+
+static void ps3vram_bind(struct mtd_info *mtd)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+
+ ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1);
+ ps3vram_out_ring(priv, 0x31337303);
+ ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3);
+ ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
+ ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */
+ ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */
+
+ ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1);
+ ps3vram_out_ring(priv, 0x3137c0de);
+ ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3);
+ ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER);
+ ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */
+ ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */
+
+ ps3vram_fire_ring(mtd);
+}
+
+static int ps3vram_upload(struct mtd_info *mtd, unsigned int src_offset,
+ unsigned int dst_offset, int len, int count)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+
+ ps3vram_begin_ring(priv, UPLOAD_SUBCH,
+ NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+ ps3vram_out_ring(priv, XDR_IOIF + src_offset);
+ ps3vram_out_ring(priv, dst_offset);
+ ps3vram_out_ring(priv, len);
+ ps3vram_out_ring(priv, len);
+ ps3vram_out_ring(priv, len);
+ ps3vram_out_ring(priv, count);
+ ps3vram_out_ring(priv, (1 << 8) | 1);
+ ps3vram_out_ring(priv, 0);
+
+ ps3vram_notifier_reset(mtd);
+ ps3vram_begin_ring(priv, UPLOAD_SUBCH,
+ NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
+ ps3vram_out_ring(priv, 0);
+ ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1);
+ ps3vram_out_ring(priv, 0);
+ ps3vram_fire_ring(mtd);
+ if (ps3vram_notifier_wait(mtd, 200) < 0) {
+ dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int ps3vram_download(struct mtd_info *mtd, unsigned int src_offset,
+ unsigned int dst_offset, int len, int count)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+
+ ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
+ NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+ ps3vram_out_ring(priv, src_offset);
+ ps3vram_out_ring(priv, XDR_IOIF + dst_offset);
+ ps3vram_out_ring(priv, len);
+ ps3vram_out_ring(priv, len);
+ ps3vram_out_ring(priv, len);
+ ps3vram_out_ring(priv, count);
+ ps3vram_out_ring(priv, (1 << 8) | 1);
+ ps3vram_out_ring(priv, 0);
+
+ ps3vram_notifier_reset(mtd);
+ ps3vram_begin_ring(priv, DOWNLOAD_SUBCH,
+ NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
+ ps3vram_out_ring(priv, 0);
+ ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1);
+ ps3vram_out_ring(priv, 0);
+ ps3vram_fire_ring(mtd);
+ if (ps3vram_notifier_wait(mtd, 200) < 0) {
+ dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__,
+ __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void ps3vram_cache_evict(struct mtd_info *mtd, int entry)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ struct ps3vram_cache *cache = &priv->cache;
+
+ if (cache->tags[entry].flags & CACHE_PAGE_DIRTY) {
+ dev_dbg(priv->dev, "%s:%d: flushing %d : 0x%08x\n", __func__,
+ __LINE__, entry, cache->tags[entry].address);
+ if (ps3vram_upload(mtd,
+ CACHE_OFFSET + entry * cache->page_size,
+ cache->tags[entry].address,
+ DMA_PAGE_SIZE,
+ cache->page_size / DMA_PAGE_SIZE) < 0) {
+ dev_dbg(priv->dev, "%s:%d: failed to upload from "
+ "0x%x to 0x%x size 0x%x\n", __func__, __LINE__,
+ entry * cache->page_size,
+ cache->tags[entry].address, cache->page_size);
+ }
+ cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY;
+ }
+}
+
+static void ps3vram_cache_load(struct mtd_info *mtd, int entry,
+ unsigned int address)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ struct ps3vram_cache *cache = &priv->cache;
+
+ dev_dbg(priv->dev, "%s:%d: fetching %d : 0x%08x\n", __func__, __LINE__,
+ entry, address);
+ if (ps3vram_download(mtd,
+ address,
+ CACHE_OFFSET + entry * cache->page_size,
+ DMA_PAGE_SIZE,
+ cache->page_size / DMA_PAGE_SIZE) < 0) {
+ dev_err(priv->dev, "%s:%d: failed to download from "
+ "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, address,
+ entry * cache->page_size, cache->page_size);
+ }
+
+ cache->tags[entry].address = address;
+ cache->tags[entry].flags |= CACHE_PAGE_PRESENT;
+}
+
+
+static void ps3vram_cache_flush(struct mtd_info *mtd)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ struct ps3vram_cache *cache = &priv->cache;
+ int i;
+
+ dev_dbg(priv->dev, "%s:%d: FLUSH\n", __func__, __LINE__);
+ for (i = 0; i < cache->page_count; i++) {
+ ps3vram_cache_evict(mtd, i);
+ cache->tags[i].flags = 0;
+ }
+}
+
+static unsigned int ps3vram_cache_match(struct mtd_info *mtd, loff_t address)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ struct ps3vram_cache *cache = &priv->cache;
+ unsigned int base;
+ unsigned int offset;
+ int i;
+ static int counter;
+
+ offset = (unsigned int) (address & (cache->page_size - 1));
+ base = (unsigned int) (address - offset);
+
+ /* fully associative check */
+ for (i = 0; i < cache->page_count; i++) {
+ if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) &&
+ cache->tags[i].address == base) {
+ dev_dbg(priv->dev, "%s:%d: found entry %d : 0x%08x\n",
+ __func__, __LINE__, i, cache->tags[i].address);
+ return i;
+ }
+ }
+
+ /* choose a random entry */
+ i = (jiffies + (counter++)) % cache->page_count;
+ dev_dbg(priv->dev, "%s:%d: using entry %d\n", __func__, __LINE__, i);
+
+ ps3vram_cache_evict(mtd, i);
+ ps3vram_cache_load(mtd, i, base);
+
+ return i;
+}
+
+static int ps3vram_cache_init(struct mtd_info *mtd)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+
+ priv->cache.page_count = CACHE_PAGE_COUNT;
+ priv->cache.page_size = CACHE_PAGE_SIZE;
+ priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) *
+ CACHE_PAGE_COUNT, GFP_KERNEL);
+ if (priv->cache.tags == NULL) {
+ dev_err(priv->dev, "%s:%d: could not allocate cache tags\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ dev_info(priv->dev, "created ram cache: %d entries, %d KiB each\n",
+ CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024);
+
+ return 0;
+}
+
+static void ps3vram_cache_cleanup(struct mtd_info *mtd)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+
+ ps3vram_cache_flush(mtd);
+ kfree(priv->cache.tags);
+}
+
+static int ps3vram_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+
+ if (instr->addr + instr->len > mtd->size)
+ return -EINVAL;
+
+ mutex_lock(&priv->lock);
+
+ ps3vram_cache_flush(mtd);
+
+ /* Set bytes to 0xFF */
+ memset_io(priv->ddr_base + instr->addr, 0xFF, instr->len);
+
+ mutex_unlock(&priv->lock);
+
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+
+ return 0;
+}
+
+static int ps3vram_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ unsigned int cached, count;
+
+ dev_dbg(priv->dev, "%s:%d: from=0x%08x len=0x%zx\n", __func__, __LINE__,
+ (unsigned int)from, len);
+
+ if (from >= mtd->size)
+ return -EINVAL;
+
+ if (len > mtd->size - from)
+ len = mtd->size - from;
+
+ /* Copy from vram to buf */
+ count = len;
+ while (count) {
+ unsigned int offset, avail;
+ unsigned int entry;
+
+ offset = (unsigned int) (from & (priv->cache.page_size - 1));
+ avail = priv->cache.page_size - offset;
+
+ mutex_lock(&priv->lock);
+
+ entry = ps3vram_cache_match(mtd, from);
+ cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
+
+ dev_dbg(priv->dev, "%s:%d: from=%08x cached=%08x offset=%08x "
+ "avail=%08x count=%08x\n", __func__, __LINE__,
+ (unsigned int)from, cached, offset, avail, count);
+
+ if (avail > count)
+ avail = count;
+ memcpy(buf, priv->xdr_buf + cached, avail);
+
+ mutex_unlock(&priv->lock);
+
+ buf += avail;
+ count -= avail;
+ from += avail;
+ }
+
+ *retlen = len;
+ return 0;
+}
+
+static int ps3vram_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct ps3vram_priv *priv = mtd->priv;
+ unsigned int cached, count;
+
+ if (to >= mtd->size)
+ return -EINVAL;
+
+ if (len > mtd->size - to)
+ len = mtd->size - to;
+
+ /* Copy from buf to vram */
+ count = len;
+ while (count) {
+ unsigned int offset, avail;
+ unsigned int entry;
+
+ offset = (unsigned int) (to & (priv->cache.page_size - 1));
+ avail = priv->cache.page_size - offset;
+
+ mutex_lock(&priv->lock);
+
+ entry = ps3vram_cache_match(mtd, to);
+ cached = CACHE_OFFSET + entry * priv->cache.page_size + offset;
+
+ dev_dbg(priv->dev, "%s:%d: to=%08x cached=%08x offset=%08x "
+ "avail=%08x count=%08x\n", __func__, __LINE__,
+ (unsigned int)to, cached, offset, avail, count);
+
+ if (avail > count)
+ avail = count;
+ memcpy(priv->xdr_buf + cached, buf, avail);
+
+ priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY;
+
+ mutex_unlock(&priv->lock);
+
+ buf += avail;
+ count -= avail;
+ to += avail;
+ }
+
+ *retlen = len;
+ return 0;
+}
+
+static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev)
+{
+ struct ps3vram_priv *priv;
+ int status;
+ u64 ddr_lpar;
+ u64 ctrl_lpar;
+ u64 info_lpar;
+ u64 reports_lpar;
+ u64 ddr_size;
+ u64 reports_size;
+ int ret = -ENOMEM;
+ char *rest;
+
+ ret = -EIO;
+ ps3vram_mtd.priv = kzalloc(sizeof(struct ps3vram_priv), GFP_KERNEL);
+ if (!ps3vram_mtd.priv)
+ goto out;
+ priv = ps3vram_mtd.priv;
+
+ mutex_init(&priv->lock);
+ priv->dev = &dev->core;
+
+ /* Allocate XDR buffer (1MiB aligned) */
+ priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL,
+ get_order(XDR_BUF_SIZE));
+ if (priv->xdr_buf == NULL) {
+ dev_dbg(&dev->core, "%s:%d: could not allocate XDR buffer\n",
+ __func__, __LINE__);
+ ret = -ENOMEM;
+ goto out_free_priv;
+ }
+
+ /* Put FIFO at begginning of XDR buffer */
+ priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET);
+ priv->fifo_ptr = priv->fifo_base;
+
+ /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */
+ if (ps3_open_hv_device(dev)) {
+ dev_err(&dev->core, "%s:%d: ps3_open_hv_device failed\n",
+ __func__, __LINE__);
+ ret = -EAGAIN;
+ goto out_close_gpu;
+ }
+
+ /* Request memory */
+ status = -1;
+ ddr_size = memparse(size, &rest);
+ if (*rest == '-')
+ ddr_size -= ps3fb_videomemory.size;
+ ddr_size = ALIGN(ddr_size, 1024*1024);
+ if (ddr_size <= 0) {
+ dev_err(&dev->core, "%s:%d: specified size is too small\n",
+ __func__, __LINE__);
+ ret = -EINVAL;
+ goto out_close_gpu;
+ }
+
+ while (ddr_size > 0) {
+ status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0,
+ &priv->memory_handle,
+ &ddr_lpar);
+ if (!status)
+ break;
+ ddr_size -= 1024*1024;
+ }
+ if (status || ddr_size <= 0) {
+ dev_err(&dev->core, "%s:%d: lv1_gpu_memory_allocate failed\n",
+ __func__, __LINE__);
+ ret = -ENOMEM;
+ goto out_free_xdr_buf;
+ }
+
+ /* Request context */
+ status = lv1_gpu_context_allocate(priv->memory_handle,
+ 0,
+ &priv->context_handle,
+ &ctrl_lpar,
+ &info_lpar,
+ &reports_lpar,
+ &reports_size);
+ if (status) {
+ dev_err(&dev->core, "%s:%d: lv1_gpu_context_allocate failed\n",
+ __func__, __LINE__);
+ ret = -ENOMEM;
+ goto out_free_memory;
+ }
+
+ /* Map XDR buffer to RSX */
+ status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF,
+ ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)),
+ XDR_BUF_SIZE, 0);
+ if (status) {
+ dev_err(&dev->core, "%s:%d: lv1_gpu_context_iomap failed\n",
+ __func__, __LINE__);
+ ret = -ENOMEM;
+ goto out_free_context;
+ }
+
+ priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE);
+
+ if (!priv->ddr_base) {
+ dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__,
+ __LINE__);
+ ret = -ENOMEM;
+ goto out_free_context;
+ }
+
+ priv->ctrl = ioremap(ctrl_lpar, 64 * 1024);
+ if (!priv->ctrl) {
+ dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__,
+ __LINE__);
+ ret = -ENOMEM;
+ goto out_unmap_vram;
+ }
+
+ priv->reports = ioremap(reports_lpar, reports_size);
+ if (!priv->reports) {
+ dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__,
+ __LINE__);
+ ret = -ENOMEM;
+ goto out_unmap_ctrl;
+ }
+
+ mutex_lock(&ps3_gpu_mutex);
+ ps3vram_init_ring(&ps3vram_mtd);
+ mutex_unlock(&ps3_gpu_mutex);
+
+ ps3vram_mtd.name = "ps3vram";
+ ps3vram_mtd.size = ddr_size;
+ ps3vram_mtd.flags = MTD_CAP_RAM;
+ ps3vram_mtd.erase = ps3vram_erase;
+ ps3vram_mtd.point = NULL;
+ ps3vram_mtd.unpoint = NULL;
+ ps3vram_mtd.read = ps3vram_read;
+ ps3vram_mtd.write = ps3vram_write;
+ ps3vram_mtd.owner = THIS_MODULE;
+ ps3vram_mtd.type = MTD_RAM;
+ ps3vram_mtd.erasesize = CACHE_PAGE_SIZE;
+ ps3vram_mtd.writesize = 1;
+
+ ps3vram_bind(&ps3vram_mtd);
+
+ mutex_lock(&ps3_gpu_mutex);
+ ret = ps3vram_wait_ring(&ps3vram_mtd, 100);
+ mutex_unlock(&ps3_gpu_mutex);
+ if (ret < 0) {
+ dev_err(&dev->core, "%s:%d: failed to initialize channels\n",
+ __func__, __LINE__);
+ ret = -ETIMEDOUT;
+ goto out_unmap_reports;
+ }
+
+ ps3vram_cache_init(&ps3vram_mtd);
+
+ if (add_mtd_device(&ps3vram_mtd)) {
+ dev_err(&dev->core, "%s:%d: add_mtd_device failed\n",
+ __func__, __LINE__);
+ ret = -EAGAIN;
+ goto out_cache_cleanup;
+ }
+
+ dev_info(&dev->core, "reserved %u MiB of gpu memory\n",
+ (unsigned int)(ddr_size / 1024 / 1024));
+
+ return 0;
+
+out_cache_cleanup:
+ ps3vram_cache_cleanup(&ps3vram_mtd);
+out_unmap_reports:
+ iounmap(priv->reports);
+out_unmap_ctrl:
+ iounmap(priv->ctrl);
+out_unmap_vram:
+ iounmap(priv->ddr_base);
+out_free_context:
+ lv1_gpu_context_free(priv->context_handle);
+out_free_memory:
+ lv1_gpu_memory_free(priv->memory_handle);
+out_close_gpu:
+ ps3_close_hv_device(dev);
+out_free_xdr_buf:
+ free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
+out_free_priv:
+ kfree(ps3vram_mtd.priv);
+ ps3vram_mtd.priv = NULL;
+out:
+ return ret;
+}
+
+static int ps3vram_shutdown(struct ps3_system_bus_device *dev)
+{
+ struct ps3vram_priv *priv;
+
+ priv = ps3vram_mtd.priv;
+
+ del_mtd_device(&ps3vram_mtd);
+ ps3vram_cache_cleanup(&ps3vram_mtd);
+ iounmap(priv->reports);
+ iounmap(priv->ctrl);
+ iounmap(priv->ddr_base);
+ lv1_gpu_context_free(priv->context_handle);
+ lv1_gpu_memory_free(priv->memory_handle);
+ ps3_close_hv_device(dev);
+ free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE));
+ kfree(priv);
+ return 0;
+}
+
+static struct ps3_system_bus_driver ps3vram_driver = {
+ .match_id = PS3_MATCH_ID_GPU,
+ .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK,
+ .core.name = DEVICE_NAME,
+ .core.owner = THIS_MODULE,
+ .probe = ps3vram_probe,
+ .remove = ps3vram_shutdown,
+ .shutdown = ps3vram_shutdown,
+};
+
+static int __init ps3vram_init(void)
+{
+ return ps3_system_bus_driver_register(&ps3vram_driver);
+}
+
+static void __exit ps3vram_exit(void)
+{
+ ps3_system_bus_driver_unregister(&ps3vram_driver);
+}
+
+module_init(ps3vram_init);
+module_exit(ps3vram_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jim Paris <jim@jtan.com>");
+MODULE_DESCRIPTION("MTD driver for PS3 video RAM");
+MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK);
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index 9bf581c4f740..a790c062af1f 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -109,25 +109,25 @@ module_param(shuffle_freq, int, 0);
/* Each memory region corresponds to a minor device */
typedef struct partition_t {
struct mtd_blktrans_dev mbd;
- u_int32_t state;
- u_int32_t *VirtualBlockMap;
- u_int32_t *VirtualPageMap;
- u_int32_t FreeTotal;
+ uint32_t state;
+ uint32_t *VirtualBlockMap;
+ uint32_t *VirtualPageMap;
+ uint32_t FreeTotal;
struct eun_info_t {
- u_int32_t Offset;
- u_int32_t EraseCount;
- u_int32_t Free;
- u_int32_t Deleted;
+ uint32_t Offset;
+ uint32_t EraseCount;
+ uint32_t Free;
+ uint32_t Deleted;
} *EUNInfo;
struct xfer_info_t {
- u_int32_t Offset;
- u_int32_t EraseCount;
- u_int16_t state;
+ uint32_t Offset;
+ uint32_t EraseCount;
+ uint16_t state;
} *XferInfo;
- u_int16_t bam_index;
- u_int32_t *bam_cache;
- u_int16_t DataUnits;
- u_int32_t BlocksPerUnit;
+ uint16_t bam_index;
+ uint32_t *bam_cache;
+ uint16_t DataUnits;
+ uint32_t BlocksPerUnit;
erase_unit_header_t header;
} partition_t;
@@ -199,8 +199,8 @@ static int scan_header(partition_t *part)
static int build_maps(partition_t *part)
{
erase_unit_header_t header;
- u_int16_t xvalid, xtrans, i;
- u_int blocks, j;
+ uint16_t xvalid, xtrans, i;
+ unsigned blocks, j;
int hdr_ok, ret = -1;
ssize_t retval;
loff_t offset;
@@ -269,14 +269,14 @@ static int build_maps(partition_t *part)
/* Set up virtual page map */
blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
- part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t));
+ part->VirtualBlockMap = vmalloc(blocks * sizeof(uint32_t));
if (!part->VirtualBlockMap)
goto out_XferInfo;
- memset(part->VirtualBlockMap, 0xff, blocks * sizeof(u_int32_t));
+ memset(part->VirtualBlockMap, 0xff, blocks * sizeof(uint32_t));
part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize;
- part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(u_int32_t),
+ part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(uint32_t),
GFP_KERNEL);
if (!part->bam_cache)
goto out_VirtualBlockMap;
@@ -290,7 +290,7 @@ static int build_maps(partition_t *part)
offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
- part->BlocksPerUnit * sizeof(u_int32_t), &retval,
+ part->BlocksPerUnit * sizeof(uint32_t), &retval,
(unsigned char *)part->bam_cache);
if (ret)
@@ -332,7 +332,7 @@ out:
======================================================================*/
static int erase_xfer(partition_t *part,
- u_int16_t xfernum)
+ uint16_t xfernum)
{
int ret;
struct xfer_info_t *xfer;
@@ -408,7 +408,7 @@ static int prepare_xfer(partition_t *part, int i)
erase_unit_header_t header;
struct xfer_info_t *xfer;
int nbam, ret;
- u_int32_t ctl;
+ uint32_t ctl;
ssize_t retlen;
loff_t offset;
@@ -430,15 +430,15 @@ static int prepare_xfer(partition_t *part, int i)
}
/* Write the BAM stub */
- nbam = (part->BlocksPerUnit * sizeof(u_int32_t) +
+ nbam = (part->BlocksPerUnit * sizeof(uint32_t) +
le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE;
offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset);
ctl = cpu_to_le32(BLOCK_CONTROL);
- for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) {
+ for (i = 0; i < nbam; i++, offset += sizeof(uint32_t)) {
- ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t),
&retlen, (u_char *)&ctl);
if (ret)
@@ -461,18 +461,18 @@ static int prepare_xfer(partition_t *part, int i)
======================================================================*/
-static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
- u_int16_t xferunit)
+static int copy_erase_unit(partition_t *part, uint16_t srcunit,
+ uint16_t xferunit)
{
u_char buf[SECTOR_SIZE];
struct eun_info_t *eun;
struct xfer_info_t *xfer;
- u_int32_t src, dest, free, i;
- u_int16_t unit;
+ uint32_t src, dest, free, i;
+ uint16_t unit;
int ret;
ssize_t retlen;
loff_t offset;
- u_int16_t srcunitswap = cpu_to_le16(srcunit);
+ uint16_t srcunitswap = cpu_to_le16(srcunit);
eun = &part->EUNInfo[srcunit];
xfer = &part->XferInfo[xferunit];
@@ -486,7 +486,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
- part->BlocksPerUnit * sizeof(u_int32_t),
+ part->BlocksPerUnit * sizeof(uint32_t),
&retlen, (u_char *) (part->bam_cache));
/* mark the cache bad, in case we get an error later */
@@ -503,7 +503,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
offset = xfer->Offset + 20; /* Bad! */
unit = cpu_to_le16(0x7fff);
- ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t),
+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint16_t),
&retlen, (u_char *) &unit);
if (ret) {
@@ -560,7 +560,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
/* All clear? Then update the LogicalEUN again */
- ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t),
+ ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(uint16_t),
&retlen, (u_char *)&srcunitswap);
if (ret) {
@@ -605,8 +605,8 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
static int reclaim_block(partition_t *part)
{
- u_int16_t i, eun, xfer;
- u_int32_t best;
+ uint16_t i, eun, xfer;
+ uint32_t best;
int queued, ret;
DEBUG(0, "ftl_cs: reclaiming space...\n");
@@ -723,10 +723,10 @@ static void dump_lists(partition_t *part)
}
#endif
-static u_int32_t find_free(partition_t *part)
+static uint32_t find_free(partition_t *part)
{
- u_int16_t stop, eun;
- u_int32_t blk;
+ uint16_t stop, eun;
+ uint32_t blk;
size_t retlen;
int ret;
@@ -749,7 +749,7 @@ static u_int32_t find_free(partition_t *part)
ret = part->mbd.mtd->read(part->mbd.mtd,
part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
- part->BlocksPerUnit * sizeof(u_int32_t),
+ part->BlocksPerUnit * sizeof(uint32_t),
&retlen, (u_char *) (part->bam_cache));
if (ret) {
@@ -786,7 +786,7 @@ static u_int32_t find_free(partition_t *part)
static int ftl_read(partition_t *part, caddr_t buffer,
u_long sector, u_long nblocks)
{
- u_int32_t log_addr, bsize;
+ uint32_t log_addr, bsize;
u_long i;
int ret;
size_t offset, retlen;
@@ -829,14 +829,14 @@ static int ftl_read(partition_t *part, caddr_t buffer,
======================================================================*/
-static int set_bam_entry(partition_t *part, u_int32_t log_addr,
- u_int32_t virt_addr)
+static int set_bam_entry(partition_t *part, uint32_t log_addr,
+ uint32_t virt_addr)
{
- u_int32_t bsize, blk, le_virt_addr;
+ uint32_t bsize, blk, le_virt_addr;
#ifdef PSYCHO_DEBUG
- u_int32_t old_addr;
+ uint32_t old_addr;
#endif
- u_int16_t eun;
+ uint16_t eun;
int ret;
size_t retlen, offset;
@@ -845,11 +845,11 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
bsize = 1 << part->header.EraseUnitSize;
eun = log_addr / bsize;
blk = (log_addr % bsize) / SECTOR_SIZE;
- offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) +
+ offset = (part->EUNInfo[eun].Offset + blk * sizeof(uint32_t) +
le32_to_cpu(part->header.BAMOffset));
#ifdef PSYCHO_DEBUG
- ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t),
+ ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(uint32_t),
&retlen, (u_char *)&old_addr);
if (ret) {
printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret);
@@ -886,7 +886,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
#endif
part->bam_cache[blk] = le_virt_addr;
}
- ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
+ ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t),
&retlen, (u_char *)&le_virt_addr);
if (ret) {
@@ -900,7 +900,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
static int ftl_write(partition_t *part, caddr_t buffer,
u_long sector, u_long nblocks)
{
- u_int32_t bsize, log_addr, virt_addr, old_addr, blk;
+ uint32_t bsize, log_addr, virt_addr, old_addr, blk;
u_long i;
int ret;
size_t retlen, offset;
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 50ce13887f63..73f05227dc8c 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -50,7 +50,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
struct INFTLrecord *inftl;
unsigned long temp;
- if (mtd->type != MTD_NANDFLASH)
+ if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
return;
/* OK, this is moderately ugly. But probably safe. Alternatives? */
if (memcmp(mtd->name, "DiskOnChip", 10))
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index 9113628ed1ef..f751dd97c549 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -63,7 +63,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
* otherwise.
*/
inftl->EraseSize = inftl->mbd.mtd->erasesize;
- inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
+ inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
inftl->MediaUnit = BLOCK_NIL;
@@ -187,7 +187,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
mh->BlockMultiplierBits);
inftl->EraseSize = inftl->mbd.mtd->erasesize <<
mh->BlockMultiplierBits;
- inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
+ inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
block >>= mh->BlockMultiplierBits;
}
diff --git a/drivers/mtd/lpddr/Kconfig b/drivers/mtd/lpddr/Kconfig
new file mode 100644
index 000000000000..acd4ea9b2278
--- /dev/null
+++ b/drivers/mtd/lpddr/Kconfig
@@ -0,0 +1,22 @@
+# drivers/mtd/chips/Kconfig
+
+menu "LPDDR flash memory drivers"
+ depends on MTD!=n
+
+config MTD_LPDDR
+ tristate "Support for LPDDR flash chips"
+ select MTD_QINFO_PROBE
+ help
+ This option enables support of LPDDR (Low power double data rate)
+ flash chips. Synonymous with Mobile-DDR. It is a new standard for
+ DDR memories, intended for battery-operated systems.
+
+config MTD_QINFO_PROBE
+ tristate "Detect flash chips by QINFO probe"
+ help
+ Device Information for LPDDR chips is offered through the Overlay
+ Window QINFO interface, permits software to be used for entire
+ families of devices. This serves similar purpose of CFI on legacy
+ Flash products
+endmenu
+
diff --git a/drivers/mtd/lpddr/Makefile b/drivers/mtd/lpddr/Makefile
new file mode 100644
index 000000000000..da48e46b5812
--- /dev/null
+++ b/drivers/mtd/lpddr/Makefile
@@ -0,0 +1,6 @@
+#
+# linux/drivers/mtd/lpddr/Makefile
+#
+
+obj-$(CONFIG_MTD_QINFO_PROBE) += qinfo_probe.o
+obj-$(CONFIG_MTD_LPDDR) += lpddr_cmds.o
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
new file mode 100644
index 000000000000..e22ca49583e7
--- /dev/null
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -0,0 +1,796 @@
+/*
+ * LPDDR flash memory device operations. This module provides read, write,
+ * erase, lock/unlock support for LPDDR flash memories
+ * (C) 2008 Korolev Alexey <akorolev@infradead.org>
+ * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
+ * Many thanks to Roman Borisov for intial enabling
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ * TODO:
+ * Implement VPP management
+ * Implement XIP support
+ * Implement OTP support
+ */
+#include <linux/mtd/pfow.h>
+#include <linux/mtd/qinfo.h>
+
+static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
+ size_t *retlen, u_char *buf);
+static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to,
+ size_t len, size_t *retlen, const u_char *buf);
+static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen);
+static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr);
+static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
+ size_t *retlen, void **mtdbuf, resource_size_t *phys);
+static void lpddr_unpoint(struct mtd_info *mtd, loff_t adr, size_t len);
+static int get_chip(struct map_info *map, struct flchip *chip, int mode);
+static int chip_ready(struct map_info *map, struct flchip *chip, int mode);
+static void put_chip(struct map_info *map, struct flchip *chip);
+
+struct mtd_info *lpddr_cmdset(struct map_info *map)
+{
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ struct flchip_shared *shared;
+ struct flchip *chip;
+ struct mtd_info *mtd;
+ int numchips;
+ int i, j;
+
+ mtd = kzalloc(sizeof(*mtd), GFP_KERNEL);
+ if (!mtd) {
+ printk(KERN_ERR "Failed to allocate memory for MTD device\n");
+ return NULL;
+ }
+ mtd->priv = map;
+ mtd->type = MTD_NORFLASH;
+
+ /* Fill in the default mtd operations */
+ mtd->read = lpddr_read;
+ mtd->type = MTD_NORFLASH;
+ mtd->flags = MTD_CAP_NORFLASH;
+ mtd->flags &= ~MTD_BIT_WRITEABLE;
+ mtd->erase = lpddr_erase;
+ mtd->write = lpddr_write_buffers;
+ mtd->writev = lpddr_writev;
+ mtd->read_oob = NULL;
+ mtd->write_oob = NULL;
+ mtd->sync = NULL;
+ mtd->lock = lpddr_lock;
+ mtd->unlock = lpddr_unlock;
+ mtd->suspend = NULL;
+ mtd->resume = NULL;
+ if (map_is_linear(map)) {
+ mtd->point = lpddr_point;
+ mtd->unpoint = lpddr_unpoint;
+ }
+ mtd->block_isbad = NULL;
+ mtd->block_markbad = NULL;
+ mtd->size = 1 << lpddr->qinfo->DevSizeShift;
+ mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift;
+ mtd->writesize = 1 << lpddr->qinfo->BufSizeShift;
+
+ shared = kmalloc(sizeof(struct flchip_shared) * lpddr->numchips,
+ GFP_KERNEL);
+ if (!shared) {
+ kfree(lpddr);
+ kfree(mtd);
+ return NULL;
+ }
+
+ chip = &lpddr->chips[0];
+ numchips = lpddr->numchips / lpddr->qinfo->HWPartsNum;
+ for (i = 0; i < numchips; i++) {
+ shared[i].writing = shared[i].erasing = NULL;
+ spin_lock_init(&shared[i].lock);
+ for (j = 0; j < lpddr->qinfo->HWPartsNum; j++) {
+ *chip = lpddr->chips[i];
+ chip->start += j << lpddr->chipshift;
+ chip->oldstate = chip->state = FL_READY;
+ chip->priv = &shared[i];
+ /* those should be reset too since
+ they create memory references. */
+ init_waitqueue_head(&chip->wq);
+ spin_lock_init(&chip->_spinlock);
+ chip->mutex = &chip->_spinlock;
+ chip++;
+ }
+ }
+
+ return mtd;
+}
+EXPORT_SYMBOL(lpddr_cmdset);
+
+static int wait_for_ready(struct map_info *map, struct flchip *chip,
+ unsigned int chip_op_time)
+{
+ unsigned int timeo, reset_timeo, sleep_time;
+ unsigned int dsr;
+ flstate_t chip_state = chip->state;
+ int ret = 0;
+
+ /* set our timeout to 8 times the expected delay */
+ timeo = chip_op_time * 8;
+ if (!timeo)
+ timeo = 500000;
+ reset_timeo = timeo;
+ sleep_time = chip_op_time / 2;
+
+ for (;;) {
+ dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR));
+ if (dsr & DSR_READY_STATUS)
+ break;
+ if (!timeo) {
+ printk(KERN_ERR "%s: Flash timeout error state %d \n",
+ map->name, chip_state);
+ ret = -ETIME;
+ break;
+ }
+
+ /* OK Still waiting. Drop the lock, wait a while and retry. */
+ spin_unlock(chip->mutex);
+ if (sleep_time >= 1000000/HZ) {
+ /*
+ * Half of the normal delay still remaining
+ * can be performed with a sleeping delay instead
+ * of busy waiting.
+ */
+ msleep(sleep_time/1000);
+ timeo -= sleep_time;
+ sleep_time = 1000000/HZ;
+ } else {
+ udelay(1);
+ cond_resched();
+ timeo--;
+ }
+ spin_lock(chip->mutex);
+
+ while (chip->state != chip_state) {
+ /* Someone's suspended the operation: sleep */
+ DECLARE_WAITQUEUE(wait, current);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+ spin_unlock(chip->mutex);
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+ spin_lock(chip->mutex);
+ }
+ if (chip->erase_suspended || chip->write_suspended) {
+ /* Suspend has occured while sleep: reset timeout */
+ timeo = reset_timeo;
+ chip->erase_suspended = chip->write_suspended = 0;
+ }
+ }
+ /* check status for errors */
+ if (dsr & DSR_ERR) {
+ /* Clear DSR*/
+ map_write(map, CMD(~(DSR_ERR)), map->pfow_base + PFOW_DSR);
+ printk(KERN_WARNING"%s: Bad status on wait: 0x%x \n",
+ map->name, dsr);
+ print_drs_error(dsr);
+ ret = -EIO;
+ }
+ chip->state = FL_READY;
+ return ret;
+}
+
+static int get_chip(struct map_info *map, struct flchip *chip, int mode)
+{
+ int ret;
+ DECLARE_WAITQUEUE(wait, current);
+
+ retry:
+ if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING)
+ && chip->state != FL_SYNCING) {
+ /*
+ * OK. We have possibility for contension on the write/erase
+ * operations which are global to the real chip and not per
+ * partition. So let's fight it over in the partition which
+ * currently has authority on the operation.
+ *
+ * The rules are as follows:
+ *
+ * - any write operation must own shared->writing.
+ *
+ * - any erase operation must own _both_ shared->writing and
+ * shared->erasing.
+ *
+ * - contension arbitration is handled in the owner's context.
+ *
+ * The 'shared' struct can be read and/or written only when
+ * its lock is taken.
+ */
+ struct flchip_shared *shared = chip->priv;
+ struct flchip *contender;
+ spin_lock(&shared->lock);
+ contender = shared->writing;
+ if (contender && contender != chip) {
+ /*
+ * The engine to perform desired operation on this
+ * partition is already in use by someone else.
+ * Let's fight over it in the context of the chip
+ * currently using it. If it is possible to suspend,
+ * that other partition will do just that, otherwise
+ * it'll happily send us to sleep. In any case, when
+ * get_chip returns success we're clear to go ahead.
+ */
+ ret = spin_trylock(contender->mutex);
+ spin_unlock(&shared->lock);
+ if (!ret)
+ goto retry;
+ spin_unlock(chip->mutex);
+ ret = chip_ready(map, contender, mode);
+ spin_lock(chip->mutex);
+
+ if (ret == -EAGAIN) {
+ spin_unlock(contender->mutex);
+ goto retry;
+ }
+ if (ret) {
+ spin_unlock(contender->mutex);
+ return ret;
+ }
+ spin_lock(&shared->lock);
+
+ /* We should not own chip if it is already in FL_SYNCING
+ * state. Put contender and retry. */
+ if (chip->state == FL_SYNCING) {
+ put_chip(map, contender);
+ spin_unlock(contender->mutex);
+ goto retry;
+ }
+ spin_unlock(contender->mutex);
+ }
+
+ /* Check if we have suspended erase on this chip.
+ Must sleep in such a case. */
+ if (mode == FL_ERASING && shared->erasing
+ && shared->erasing->oldstate == FL_ERASING) {
+ spin_unlock(&shared->lock);
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+ spin_unlock(chip->mutex);
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+ spin_lock(chip->mutex);
+ goto retry;
+ }
+
+ /* We now own it */
+ shared->writing = chip;
+ if (mode == FL_ERASING)
+ shared->erasing = chip;
+ spin_unlock(&shared->lock);
+ }
+
+ ret = chip_ready(map, chip, mode);
+ if (ret == -EAGAIN)
+ goto retry;
+
+ return ret;
+}
+
+static int chip_ready(struct map_info *map, struct flchip *chip, int mode)
+{
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int ret = 0;
+ DECLARE_WAITQUEUE(wait, current);
+
+ /* Prevent setting state FL_SYNCING for chip in suspended state. */
+ if (FL_SYNCING == mode && FL_READY != chip->oldstate)
+ goto sleep;
+
+ switch (chip->state) {
+ case FL_READY:
+ case FL_JEDEC_QUERY:
+ return 0;
+
+ case FL_ERASING:
+ if (!lpddr->qinfo->SuspEraseSupp ||
+ !(mode == FL_READY || mode == FL_POINT))
+ goto sleep;
+
+ map_write(map, CMD(LPDDR_SUSPEND),
+ map->pfow_base + PFOW_PROGRAM_ERASE_SUSPEND);
+ chip->oldstate = FL_ERASING;
+ chip->state = FL_ERASE_SUSPENDING;
+ ret = wait_for_ready(map, chip, 0);
+ if (ret) {
+ /* Oops. something got wrong. */
+ /* Resume and pretend we weren't here. */
+ map_write(map, CMD(LPDDR_RESUME),
+ map->pfow_base + PFOW_COMMAND_CODE);
+ map_write(map, CMD(LPDDR_START_EXECUTION),
+ map->pfow_base + PFOW_COMMAND_EXECUTE);
+ chip->state = FL_ERASING;
+ chip->oldstate = FL_READY;
+ printk(KERN_ERR "%s: suspend operation failed."
+ "State may be wrong \n", map->name);
+ return -EIO;
+ }
+ chip->erase_suspended = 1;
+ chip->state = FL_READY;
+ return 0;
+ /* Erase suspend */
+ case FL_POINT:
+ /* Only if there's no operation suspended... */
+ if (mode == FL_READY && chip->oldstate == FL_READY)
+ return 0;
+
+ default:
+sleep:
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&chip->wq, &wait);
+ spin_unlock(chip->mutex);
+ schedule();
+ remove_wait_queue(&chip->wq, &wait);
+ spin_lock(chip->mutex);
+ return -EAGAIN;
+ }
+}
+
+static void put_chip(struct map_info *map, struct flchip *chip)
+{
+ if (chip->priv) {
+ struct flchip_shared *shared = chip->priv;
+ spin_lock(&shared->lock);
+ if (shared->writing == chip && chip->oldstate == FL_READY) {
+ /* We own the ability to write, but we're done */
+ shared->writing = shared->erasing;
+ if (shared->writing && shared->writing != chip) {
+ /* give back the ownership */
+ struct flchip *loaner = shared->writing;
+ spin_lock(loaner->mutex);
+ spin_unlock(&shared->lock);
+ spin_unlock(chip->mutex);
+ put_chip(map, loaner);
+ spin_lock(chip->mutex);
+ spin_unlock(loaner->mutex);
+ wake_up(&chip->wq);
+ return;
+ }
+ shared->erasing = NULL;
+ shared->writing = NULL;
+ } else if (shared->erasing == chip && shared->writing != chip) {
+ /*
+ * We own the ability to erase without the ability
+ * to write, which means the erase was suspended
+ * and some other partition is currently writing.
+ * Don't let the switch below mess things up since
+ * we don't have ownership to resume anything.
+ */
+ spin_unlock(&shared->lock);
+ wake_up(&chip->wq);
+ return;
+ }
+ spin_unlock(&shared->lock);
+ }
+
+ switch (chip->oldstate) {
+ case FL_ERASING:
+ chip->state = chip->oldstate;
+ map_write(map, CMD(LPDDR_RESUME),
+ map->pfow_base + PFOW_COMMAND_CODE);
+ map_write(map, CMD(LPDDR_START_EXECUTION),
+ map->pfow_base + PFOW_COMMAND_EXECUTE);
+ chip->oldstate = FL_READY;
+ chip->state = FL_ERASING;
+ break;
+ case FL_READY:
+ break;
+ default:
+ printk(KERN_ERR "%s: put_chip() called with oldstate %d!\n",
+ map->name, chip->oldstate);
+ }
+ wake_up(&chip->wq);
+}
+
+int do_write_buffer(struct map_info *map, struct flchip *chip,
+ unsigned long adr, const struct kvec **pvec,
+ unsigned long *pvec_seek, int len)
+{
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ map_word datum;
+ int ret, wbufsize, word_gap, words;
+ const struct kvec *vec;
+ unsigned long vec_seek;
+ unsigned long prog_buf_ofs;
+
+ wbufsize = 1 << lpddr->qinfo->BufSizeShift;
+
+ spin_lock(chip->mutex);
+ ret = get_chip(map, chip, FL_WRITING);
+ if (ret) {
+ spin_unlock(chip->mutex);
+ return ret;
+ }
+ /* Figure out the number of words to write */
+ word_gap = (-adr & (map_bankwidth(map)-1));
+ words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map);
+ if (!word_gap) {
+ words--;
+ } else {
+ word_gap = map_bankwidth(map) - word_gap;
+ adr -= word_gap;
+ datum = map_word_ff(map);
+ }
+ /* Write data */
+ /* Get the program buffer offset from PFOW register data first*/
+ prog_buf_ofs = map->pfow_base + CMDVAL(map_read(map,
+ map->pfow_base + PFOW_PROGRAM_BUFFER_OFFSET));
+ vec = *pvec;
+ vec_seek = *pvec_seek;
+ do {
+ int n = map_bankwidth(map) - word_gap;
+
+ if (n > vec->iov_len - vec_seek)
+ n = vec->iov_len - vec_seek;
+ if (n > len)
+ n = len;
+
+ if (!word_gap && (len < map_bankwidth(map)))
+ datum = map_word_ff(map);
+
+ datum = map_word_load_partial(map, datum,
+ vec->iov_base + vec_seek, word_gap, n);
+
+ len -= n;
+ word_gap += n;
+ if (!len || word_gap == map_bankwidth(map)) {
+ map_write(map, datum, prog_buf_ofs);
+ prog_buf_ofs += map_bankwidth(map);
+ word_gap = 0;
+ }
+
+ vec_seek += n;
+ if (vec_seek == vec->iov_len) {
+ vec++;
+ vec_seek = 0;
+ }
+ } while (len);
+ *pvec = vec;
+ *pvec_seek = vec_seek;
+
+ /* GO GO GO */
+ send_pfow_command(map, LPDDR_BUFF_PROGRAM, adr, wbufsize, NULL);
+ chip->state = FL_WRITING;
+ ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->ProgBufferTime));
+ if (ret) {
+ printk(KERN_WARNING"%s Buffer program error: %d at %lx; \n",
+ map->name, ret, adr);
+ goto out;
+ }
+
+ out: put_chip(map, chip);
+ spin_unlock(chip->mutex);
+ return ret;
+}
+
+int do_erase_oneblock(struct mtd_info *mtd, loff_t adr)
+{
+ struct map_info *map = mtd->priv;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int chipnum = adr >> lpddr->chipshift;
+ struct flchip *chip = &lpddr->chips[chipnum];
+ int ret;
+
+ spin_lock(chip->mutex);
+ ret = get_chip(map, chip, FL_ERASING);
+ if (ret) {
+ spin_unlock(chip->mutex);
+ return ret;
+ }
+ send_pfow_command(map, LPDDR_BLOCK_ERASE, adr, 0, NULL);
+ chip->state = FL_ERASING;
+ ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->BlockEraseTime)*1000);
+ if (ret) {
+ printk(KERN_WARNING"%s Erase block error %d at : %llx\n",
+ map->name, ret, adr);
+ goto out;
+ }
+ out: put_chip(map, chip);
+ spin_unlock(chip->mutex);
+ return ret;
+}
+
+static int lpddr_read(struct mtd_info *mtd, loff_t adr, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct map_info *map = mtd->priv;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int chipnum = adr >> lpddr->chipshift;
+ struct flchip *chip = &lpddr->chips[chipnum];
+ int ret = 0;
+
+ spin_lock(chip->mutex);
+ ret = get_chip(map, chip, FL_READY);
+ if (ret) {
+ spin_unlock(chip->mutex);
+ return ret;
+ }
+
+ map_copy_from(map, buf, adr, len);
+ *retlen = len;
+
+ put_chip(map, chip);
+ spin_unlock(chip->mutex);
+ return ret;
+}
+
+static int lpddr_point(struct mtd_info *mtd, loff_t adr, size_t len,
+ size_t *retlen, void **mtdbuf, resource_size_t *phys)
+{
+ struct map_info *map = mtd->priv;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int chipnum = adr >> lpddr->chipshift;
+ unsigned long ofs, last_end = 0;
+ struct flchip *chip = &lpddr->chips[chipnum];
+ int ret = 0;
+
+ if (!map->virt || (adr + len > mtd->size))
+ return -EINVAL;
+
+ /* ofs: offset within the first chip that the first read should start */
+ ofs = adr - (chipnum << lpddr->chipshift);
+
+ *mtdbuf = (void *)map->virt + chip->start + ofs;
+ *retlen = 0;
+
+ while (len) {
+ unsigned long thislen;
+
+ if (chipnum >= lpddr->numchips)
+ break;
+
+ /* We cannot point across chips that are virtually disjoint */
+ if (!last_end)
+ last_end = chip->start;
+ else if (chip->start != last_end)
+ break;
+
+ if ((len + ofs - 1) >> lpddr->chipshift)
+ thislen = (1<<lpddr->chipshift) - ofs;
+ else
+ thislen = len;
+ /* get the chip */
+ spin_lock(chip->mutex);
+ ret = get_chip(map, chip, FL_POINT);
+ spin_unlock(chip->mutex);
+ if (ret)
+ break;
+
+ chip->state = FL_POINT;
+ chip->ref_point_counter++;
+ *retlen += thislen;
+ len -= thislen;
+
+ ofs = 0;
+ last_end += 1 << lpddr->chipshift;
+ chipnum++;
+ chip = &lpddr->chips[chipnum];
+ }
+ return 0;
+}
+
+static void lpddr_unpoint (struct mtd_info *mtd, loff_t adr, size_t len)
+{
+ struct map_info *map = mtd->priv;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int chipnum = adr >> lpddr->chipshift;
+ unsigned long ofs;
+
+ /* ofs: offset within the first chip that the first read should start */
+ ofs = adr - (chipnum << lpddr->chipshift);
+
+ while (len) {
+ unsigned long thislen;
+ struct flchip *chip;
+
+ chip = &lpddr->chips[chipnum];
+ if (chipnum >= lpddr->numchips)
+ break;
+
+ if ((len + ofs - 1) >> lpddr->chipshift)
+ thislen = (1<<lpddr->chipshift) - ofs;
+ else
+ thislen = len;
+
+ spin_lock(chip->mutex);
+ if (chip->state == FL_POINT) {
+ chip->ref_point_counter--;
+ if (chip->ref_point_counter == 0)
+ chip->state = FL_READY;
+ } else
+ printk(KERN_WARNING "%s: Warning: unpoint called on non"
+ "pointed region\n", map->name);
+
+ put_chip(map, chip);
+ spin_unlock(chip->mutex);
+
+ len -= thislen;
+ ofs = 0;
+ chipnum++;
+ }
+}
+
+static int lpddr_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct kvec vec;
+
+ vec.iov_base = (void *) buf;
+ vec.iov_len = len;
+
+ return lpddr_writev(mtd, &vec, 1, to, retlen);
+}
+
+
+static int lpddr_writev(struct mtd_info *mtd, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen)
+{
+ struct map_info *map = mtd->priv;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int ret = 0;
+ int chipnum;
+ unsigned long ofs, vec_seek, i;
+ int wbufsize = 1 << lpddr->qinfo->BufSizeShift;
+
+ size_t len = 0;
+
+ for (i = 0; i < count; i++)
+ len += vecs[i].iov_len;
+
+ *retlen = 0;
+ if (!len)
+ return 0;
+
+ chipnum = to >> lpddr->chipshift;
+
+ ofs = to;
+ vec_seek = 0;
+
+ do {
+ /* We must not cross write block boundaries */
+ int size = wbufsize - (ofs & (wbufsize-1));
+
+ if (size > len)
+ size = len;
+
+ ret = do_write_buffer(map, &lpddr->chips[chipnum],
+ ofs, &vecs, &vec_seek, size);
+ if (ret)
+ return ret;
+
+ ofs += size;
+ (*retlen) += size;
+ len -= size;
+
+ /* Be nice and reschedule with the chip in a usable
+ * state for other processes */
+ cond_resched();
+
+ } while (len);
+
+ return 0;
+}
+
+static int lpddr_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ unsigned long ofs, len;
+ int ret;
+ struct map_info *map = mtd->priv;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int size = 1 << lpddr->qinfo->UniformBlockSizeShift;
+
+ ofs = instr->addr;
+ len = instr->len;
+
+ if (ofs > mtd->size || (len + ofs) > mtd->size)
+ return -EINVAL;
+
+ while (len > 0) {
+ ret = do_erase_oneblock(mtd, ofs);
+ if (ret)
+ return ret;
+ ofs += size;
+ len -= size;
+ }
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+
+ return 0;
+}
+
+#define DO_XXLOCK_LOCK 1
+#define DO_XXLOCK_UNLOCK 2
+int do_xxlock(struct mtd_info *mtd, loff_t adr, uint32_t len, int thunk)
+{
+ int ret = 0;
+ struct map_info *map = mtd->priv;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int chipnum = adr >> lpddr->chipshift;
+ struct flchip *chip = &lpddr->chips[chipnum];
+
+ spin_lock(chip->mutex);
+ ret = get_chip(map, chip, FL_LOCKING);
+ if (ret) {
+ spin_unlock(chip->mutex);
+ return ret;
+ }
+
+ if (thunk == DO_XXLOCK_LOCK) {
+ send_pfow_command(map, LPDDR_LOCK_BLOCK, adr, adr + len, NULL);
+ chip->state = FL_LOCKING;
+ } else if (thunk == DO_XXLOCK_UNLOCK) {
+ send_pfow_command(map, LPDDR_UNLOCK_BLOCK, adr, adr + len, NULL);
+ chip->state = FL_UNLOCKING;
+ } else
+ BUG();
+
+ ret = wait_for_ready(map, chip, 1);
+ if (ret) {
+ printk(KERN_ERR "%s: block unlock error status %d \n",
+ map->name, ret);
+ goto out;
+ }
+out: put_chip(map, chip);
+ spin_unlock(chip->mutex);
+ return ret;
+}
+
+static int lpddr_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ return do_xxlock(mtd, ofs, len, DO_XXLOCK_LOCK);
+}
+
+static int lpddr_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ return do_xxlock(mtd, ofs, len, DO_XXLOCK_UNLOCK);
+}
+
+int word_program(struct map_info *map, loff_t adr, uint32_t curval)
+{
+ int ret;
+ struct lpddr_private *lpddr = map->fldrv_priv;
+ int chipnum = adr >> lpddr->chipshift;
+ struct flchip *chip = &lpddr->chips[chipnum];
+
+ spin_lock(chip->mutex);
+ ret = get_chip(map, chip, FL_WRITING);
+ if (ret) {
+ spin_unlock(chip->mutex);
+ return ret;
+ }
+
+ send_pfow_command(map, LPDDR_WORD_PROGRAM, adr, 0x00, (map_word *)&curval);
+
+ ret = wait_for_ready(map, chip, (1<<lpddr->qinfo->SingleWordProgTime));
+ if (ret) {
+ printk(KERN_WARNING"%s word_program error at: %llx; val: %x\n",
+ map->name, adr, curval);
+ goto out;
+ }
+
+out: put_chip(map, chip);
+ spin_unlock(chip->mutex);
+ return ret;
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alexey Korolev <akorolev@infradead.org>");
+MODULE_DESCRIPTION("MTD driver for LPDDR flash chips");
diff --git a/drivers/mtd/lpddr/qinfo_probe.c b/drivers/mtd/lpddr/qinfo_probe.c
new file mode 100644
index 000000000000..79bf40f48b75
--- /dev/null
+++ b/drivers/mtd/lpddr/qinfo_probe.c
@@ -0,0 +1,255 @@
+/*
+ * Probing flash chips with QINFO records.
+ * (C) 2008 Korolev Alexey <akorolev@infradead.org>
+ * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+
+#include <linux/mtd/xip.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/pfow.h>
+#include <linux/mtd/qinfo.h>
+
+static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr);
+struct mtd_info *lpddr_probe(struct map_info *map);
+static struct lpddr_private *lpddr_probe_chip(struct map_info *map);
+static int lpddr_pfow_present(struct map_info *map,
+ struct lpddr_private *lpddr);
+
+static struct qinfo_query_info qinfo_array[] = {
+ /* General device info */
+ {0, 0, "DevSizeShift", "Device size 2^n bytes"},
+ {0, 3, "BufSizeShift", "Program buffer size 2^n bytes"},
+ /* Erase block information */
+ {1, 1, "TotalBlocksNum", "Total number of blocks"},
+ {1, 2, "UniformBlockSizeShift", "Uniform block size 2^n bytes"},
+ /* Partition information */
+ {2, 1, "HWPartsNum", "Number of hardware partitions"},
+ /* Optional features */
+ {5, 1, "SuspEraseSupp", "Suspend erase supported"},
+ /* Operation typical time */
+ {10, 0, "SingleWordProgTime", "Single word program 2^n u-sec"},
+ {10, 1, "ProgBufferTime", "Program buffer write 2^n u-sec"},
+ {10, 2, "BlockEraseTime", "Block erase 2^n m-sec"},
+ {10, 3, "FullChipEraseTime", "Full chip erase 2^n m-sec"},
+};
+
+static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str)
+{
+ int qinfo_lines = sizeof(qinfo_array)/sizeof(struct qinfo_query_info);
+ int i;
+ int bankwidth = map_bankwidth(map) * 8;
+ int major, minor;
+
+ for (i = 0; i < qinfo_lines; i++) {
+ if (strcmp(id_str, qinfo_array[i].id_str) == 0) {
+ major = qinfo_array[i].major & ((1 << bankwidth) - 1);
+ minor = qinfo_array[i].minor & ((1 << bankwidth) - 1);
+ return minor | (major << bankwidth);
+ }
+ }
+ printk(KERN_ERR"%s qinfo id string is wrong! \n", map->name);
+ BUG();
+ return -1;
+}
+
+static uint16_t lpddr_info_query(struct map_info *map, char *id_str)
+{
+ unsigned int dsr, val;
+ int bits_per_chip = map_bankwidth(map) * 8;
+ unsigned long adr = lpddr_get_qinforec_pos(map, id_str);
+ int attempts = 20;
+
+ /* Write a request for the PFOW record */
+ map_write(map, CMD(LPDDR_INFO_QUERY),
+ map->pfow_base + PFOW_COMMAND_CODE);
+ map_write(map, CMD(adr & ((1 << bits_per_chip) - 1)),
+ map->pfow_base + PFOW_COMMAND_ADDRESS_L);
+ map_write(map, CMD(adr >> bits_per_chip),
+ map->pfow_base + PFOW_COMMAND_ADDRESS_H);
+ map_write(map, CMD(LPDDR_START_EXECUTION),
+ map->pfow_base + PFOW_COMMAND_EXECUTE);
+
+ while ((attempts--) > 0) {
+ dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR));
+ if (dsr & DSR_READY_STATUS)
+ break;
+ udelay(10);
+ }
+
+ val = CMDVAL(map_read(map, map->pfow_base + PFOW_COMMAND_DATA));
+ return val;
+}
+
+static int lpddr_pfow_present(struct map_info *map, struct lpddr_private *lpddr)
+{
+ map_word pfow_val[4];
+
+ /* Check identification string */
+ pfow_val[0] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_P);
+ pfow_val[1] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_F);
+ pfow_val[2] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_O);
+ pfow_val[3] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_W);
+
+ if (!map_word_equal(map, CMD('P'), pfow_val[0]))
+ goto out;
+
+ if (!map_word_equal(map, CMD('F'), pfow_val[1]))
+ goto out;
+
+ if (!map_word_equal(map, CMD('O'), pfow_val[2]))
+ goto out;
+
+ if (!map_word_equal(map, CMD('W'), pfow_val[3]))
+ goto out;
+
+ return 1; /* "PFOW" is found */
+out:
+ printk(KERN_WARNING"%s: PFOW string at 0x%lx is not found \n",
+ map->name, map->pfow_base);
+ return 0;
+}
+
+static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr)
+{
+
+ lpddr->qinfo = kmalloc(sizeof(struct qinfo_chip), GFP_KERNEL);
+ if (!lpddr->qinfo) {
+ printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n",
+ map->name);
+ return 0;
+ }
+ memset(lpddr->qinfo, 0, sizeof(struct qinfo_chip));
+
+ /* Get the ManuID */
+ lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID));
+ /* Get the DeviceID */
+ lpddr->DevId = CMDVAL(map_read(map, map->pfow_base + PFOW_DEVICE_ID));
+ /* read parameters from chip qinfo table */
+ lpddr->qinfo->DevSizeShift = lpddr_info_query(map, "DevSizeShift");
+ lpddr->qinfo->TotalBlocksNum = lpddr_info_query(map, "TotalBlocksNum");
+ lpddr->qinfo->BufSizeShift = lpddr_info_query(map, "BufSizeShift");
+ lpddr->qinfo->HWPartsNum = lpddr_info_query(map, "HWPartsNum");
+ lpddr->qinfo->UniformBlockSizeShift =
+ lpddr_info_query(map, "UniformBlockSizeShift");
+ lpddr->qinfo->SuspEraseSupp = lpddr_info_query(map, "SuspEraseSupp");
+ lpddr->qinfo->SingleWordProgTime =
+ lpddr_info_query(map, "SingleWordProgTime");
+ lpddr->qinfo->ProgBufferTime = lpddr_info_query(map, "ProgBufferTime");
+ lpddr->qinfo->BlockEraseTime = lpddr_info_query(map, "BlockEraseTime");
+ return 1;
+}
+static struct lpddr_private *lpddr_probe_chip(struct map_info *map)
+{
+ struct lpddr_private lpddr;
+ struct lpddr_private *retlpddr;
+ int numvirtchips;
+
+
+ if ((map->pfow_base + 0x1000) >= map->size) {
+ printk(KERN_NOTICE"%s Probe at base (0x%08lx) past the end of"
+ "the map(0x%08lx)\n", map->name,
+ (unsigned long)map->pfow_base, map->size - 1);
+ return NULL;
+ }
+ memset(&lpddr, 0, sizeof(struct lpddr_private));
+ if (!lpddr_pfow_present(map, &lpddr))
+ return NULL;
+
+ if (!lpddr_chip_setup(map, &lpddr))
+ return NULL;
+
+ /* Ok so we found a chip */
+ lpddr.chipshift = lpddr.qinfo->DevSizeShift;
+ lpddr.numchips = 1;
+
+ numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum;
+ retlpddr = kmalloc(sizeof(struct lpddr_private) +
+ numvirtchips * sizeof(struct flchip), GFP_KERNEL);
+ if (!retlpddr)
+ return NULL;
+
+ memset(retlpddr, 0, sizeof(struct lpddr_private) +
+ numvirtchips * sizeof(struct flchip));
+ memcpy(retlpddr, &lpddr, sizeof(struct lpddr_private));
+
+ retlpddr->numchips = numvirtchips;
+ retlpddr->chipshift = retlpddr->qinfo->DevSizeShift -
+ __ffs(retlpddr->qinfo->HWPartsNum);
+
+ return retlpddr;
+}
+
+struct mtd_info *lpddr_probe(struct map_info *map)
+{
+ struct mtd_info *mtd = NULL;
+ struct lpddr_private *lpddr;
+
+ /* First probe the map to see if we havecan open PFOW here */
+ lpddr = lpddr_probe_chip(map);
+ if (!lpddr)
+ return NULL;
+
+ map->fldrv_priv = lpddr;
+ mtd = lpddr_cmdset(map);
+ if (mtd) {
+ if (mtd->size > map->size) {
+ printk(KERN_WARNING "Reducing visibility of %ldKiB chip"
+ "to %ldKiB\n", (unsigned long)mtd->size >> 10,
+ (unsigned long)map->size >> 10);
+ mtd->size = map->size;
+ }
+ return mtd;
+ }
+
+ kfree(lpddr->qinfo);
+ kfree(lpddr);
+ map->fldrv_priv = NULL;
+ return NULL;
+}
+
+static struct mtd_chip_driver lpddr_chipdrv = {
+ .probe = lpddr_probe,
+ .name = "qinfo_probe",
+ .module = THIS_MODULE
+};
+
+static int __init lpddr_probe_init(void)
+{
+ register_mtd_chip_driver(&lpddr_chipdrv);
+ return 0;
+}
+
+static void __exit lpddr_probe_exit(void)
+{
+ unregister_mtd_chip_driver(&lpddr_chipdrv);
+}
+
+module_init(lpddr_probe_init);
+module_exit(lpddr_probe_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vasiliy Leonenko <vasiliy.leonenko@gmail.com>");
+MODULE_DESCRIPTION("Driver to probe qinfo flash chips");
+
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 5ea169362164..0225cbbf22de 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -10,8 +10,8 @@ config MTD_COMPLEX_MAPPINGS
paged mappings of flash chips.
config MTD_PHYSMAP
- tristate "CFI Flash device in physical memory map"
- depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM
+ tristate "Flash device in physical memory map"
+ depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM || MTD_LPDDR
help
This provides a 'mapping' driver which allows the NOR Flash and
ROM driver code to communicate with chips which are mapped
@@ -23,9 +23,20 @@ config MTD_PHYSMAP
To compile this driver as a module, choose M here: the
module will be called physmap.
+config MTD_PHYSMAP_COMPAT
+ bool "Physmap compat support"
+ depends on MTD_PHYSMAP
+ default n
+ help
+ Setup a simple mapping via the Kconfig options. Normally the
+ physmap configuration options are done via your board's
+ resource file.
+
+ If unsure, say N here.
+
config MTD_PHYSMAP_START
hex "Physical start address of flash mapping"
- depends on MTD_PHYSMAP
+ depends on MTD_PHYSMAP_COMPAT
default "0x8000000"
help
This is the physical memory location at which the flash chips
@@ -37,7 +48,7 @@ config MTD_PHYSMAP_START
config MTD_PHYSMAP_LEN
hex "Physical length of flash mapping"
- depends on MTD_PHYSMAP
+ depends on MTD_PHYSMAP_COMPAT
default "0"
help
This is the total length of the mapping of the flash chips on
@@ -51,7 +62,7 @@ config MTD_PHYSMAP_LEN
config MTD_PHYSMAP_BANKWIDTH
int "Bank width in octets"
- depends on MTD_PHYSMAP
+ depends on MTD_PHYSMAP_COMPAT
default "2"
help
This is the total width of the data bus of the flash devices
diff --git a/drivers/mtd/maps/alchemy-flash.c b/drivers/mtd/maps/alchemy-flash.c
index 82811bcb0436..845ad4f2a542 100644
--- a/drivers/mtd/maps/alchemy-flash.c
+++ b/drivers/mtd/maps/alchemy-flash.c
@@ -111,7 +111,7 @@ static struct mtd_partition alchemy_partitions[] = {
static struct mtd_info *mymtd;
-int __init alchemy_mtd_init(void)
+static int __init alchemy_mtd_init(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index d1eec7d3243f..237733d094c4 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -232,8 +232,8 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
/* Trim the size if we are larger than the map */
if (map->mtd->size > map->map.size) {
printk(KERN_WARNING MOD_NAME
- " rom(%u) larger than window(%lu). fixing...\n",
- map->mtd->size, map->map.size);
+ " rom(%llu) larger than window(%lu). fixing...\n",
+ (unsigned long long)map->mtd->size, map->map.size);
map->mtd->size = map->map.size;
}
if (window->rsrc.parent) {
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c
index 0ecc3f6d735b..b4ed81611918 100644
--- a/drivers/mtd/maps/cfi_flagadm.c
+++ b/drivers/mtd/maps/cfi_flagadm.c
@@ -88,7 +88,7 @@ struct mtd_partition flagadm_parts[] = {
static struct mtd_info *mymtd;
-int __init init_flagadm(void)
+static int __init init_flagadm(void)
{
printk(KERN_NOTICE "FlagaDM flash device: %x at %x\n",
FLASH_SIZE, FLASH_PHYS_ADDR);
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 1a6feb4474de..5f7a245ed132 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -263,8 +263,8 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
/* Trim the size if we are larger than the map */
if (map->mtd->size > map->map.size) {
printk(KERN_WARNING MOD_NAME
- " rom(%u) larger than window(%lu). fixing...\n",
- map->mtd->size, map->map.size);
+ " rom(%llu) larger than window(%lu). fixing...\n",
+ (unsigned long long)map->mtd->size, map->map.size);
map->mtd->size = map->map.size;
}
if (window->rsrc.parent) {
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c
index e115667bf1d0..cfacfa6f45dd 100644
--- a/drivers/mtd/maps/dbox2-flash.c
+++ b/drivers/mtd/maps/dbox2-flash.c
@@ -69,7 +69,7 @@ struct map_info dbox2_flash_map = {
.phys = WINDOW_ADDR,
};
-int __init init_dbox2_flash(void)
+static int __init init_dbox2_flash(void)
{
printk(KERN_NOTICE "D-Box 2 flash driver (size->0x%X mem->0x%X)\n", WINDOW_SIZE, WINDOW_ADDR);
dbox2_flash_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
index 9433738c1664..be9e90b44587 100644
--- a/drivers/mtd/maps/edb7312.c
+++ b/drivers/mtd/maps/edb7312.c
@@ -71,7 +71,7 @@ static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static int mtd_parts_nb = 0;
static struct mtd_partition *mtd_parts = 0;
-int __init init_edb7312nor(void)
+static int __init init_edb7312nor(void)
{
static const char *rom_probe_types[] = PROBETYPES;
const char **type;
diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c
index bbbcdd4c8d13..11a2f57df9cf 100644
--- a/drivers/mtd/maps/esb2rom.c
+++ b/drivers/mtd/maps/esb2rom.c
@@ -324,8 +324,8 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
/* Trim the size if we are larger than the map */
if (map->mtd->size > map->map.size) {
printk(KERN_WARNING MOD_NAME
- " rom(%u) larger than window(%lu). fixing...\n",
- map->mtd->size, map->map.size);
+ " rom(%llu) larger than window(%lu). fixing...\n",
+ (unsigned long long)map->mtd->size, map->map.size);
map->mtd->size = map->map.size;
}
if (window->rsrc.parent) {
diff --git a/drivers/mtd/maps/fortunet.c b/drivers/mtd/maps/fortunet.c
index a8e3fde4cbd5..1e43124d498b 100644
--- a/drivers/mtd/maps/fortunet.c
+++ b/drivers/mtd/maps/fortunet.c
@@ -181,7 +181,7 @@ __setup("MTD_Partition=", MTD_New_Partition);
/* Backwards-spelling-compatibility */
__setup("MTD_Partion=", MTD_New_Partition);
-int __init init_fortunet(void)
+static int __init init_fortunet(void)
{
int ix,iy;
for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
index 3b959fad1c4e..72c724fa8c27 100644
--- a/drivers/mtd/maps/h720x-flash.c
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -65,7 +65,7 @@ static const char *probes[] = { "cmdlinepart", NULL };
/*
* Initialize FLASH support
*/
-int __init h720x_mtd_init(void)
+static int __init h720x_mtd_init(void)
{
char *part_type = NULL;
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
index aeb6c916e23f..c32bc28920b3 100644
--- a/drivers/mtd/maps/ichxrom.c
+++ b/drivers/mtd/maps/ichxrom.c
@@ -258,8 +258,8 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev,
/* Trim the size if we are larger than the map */
if (map->mtd->size > map->map.size) {
printk(KERN_WARNING MOD_NAME
- " rom(%u) larger than window(%lu). fixing...\n",
- map->mtd->size, map->map.size);
+ " rom(%llu) larger than window(%lu). fixing...\n",
+ (unsigned long long)map->mtd->size, map->map.size);
map->mtd->size = map->map.size;
}
if (window->rsrc.parent) {
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
index 2682ab51a367..998a27da97f3 100644
--- a/drivers/mtd/maps/impa7.c
+++ b/drivers/mtd/maps/impa7.c
@@ -70,7 +70,7 @@ static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
static const char *probes[] = { "cmdlinepart", NULL };
-int __init init_impa7(void)
+static int __init init_impa7(void)
{
static const char *rom_probe_types[] = PROBETYPES;
const char **type;
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index 7100ee3c7b01..d2ec262666c7 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -105,7 +105,7 @@ static int armflash_probe(struct platform_device *dev)
info->map.bankwidth = plat->width;
info->map.phys = res->start;
info->map.virt = base;
- info->map.name = dev->dev.bus_id;
+ info->map.name = dev_name(&dev->dev);
info->map.set_vpp = armflash_set_vpp;
simple_map_init(&info->map);
diff --git a/drivers/mtd/maps/ipaq-flash.c b/drivers/mtd/maps/ipaq-flash.c
index ed58f6a77bd9..748c85f635f1 100644
--- a/drivers/mtd/maps/ipaq-flash.c
+++ b/drivers/mtd/maps/ipaq-flash.c
@@ -202,7 +202,7 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
static int __init h1900_special_case(void);
-int __init ipaq_mtd_init(void)
+static int __init ipaq_mtd_init(void)
{
struct mtd_partition *parts = NULL;
int nb_parts = 0;
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index 3ea1de9be720..d4fb9a3ab4df 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -188,7 +188,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
*/
info->map.map_priv_2 = (unsigned long) ixp_data->bank_setup;
- info->map.name = dev->dev.bus_id;
+ info->map.name = dev_name(&dev->dev);
info->map.read = ixp2000_flash_read8;
info->map.write = ixp2000_flash_write8;
info->map.copy_from = ixp2000_flash_copy_from;
@@ -196,7 +196,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
info->res = request_mem_region(dev->resource->start,
dev->resource->end - dev->resource->start + 1,
- dev->dev.bus_id);
+ dev_name(&dev->dev));
if (!info->res) {
dev_err(&dev->dev, "Could not reserve memory region\n");
err = -ENOMEM;
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 16555cbeaea4..7214b876feba 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -218,7 +218,7 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
* handle that.
*/
info->map.bankwidth = 2;
- info->map.name = dev->dev.bus_id;
+ info->map.name = dev_name(&dev->dev);
info->map.read = ixp4xx_read16,
info->map.write = ixp4xx_probe_write16,
info->map.copy_from = ixp4xx_copy_from,
diff --git a/drivers/mtd/maps/mbx860.c b/drivers/mtd/maps/mbx860.c
index 706f67394b07..0eb5a7c85380 100644
--- a/drivers/mtd/maps/mbx860.c
+++ b/drivers/mtd/maps/mbx860.c
@@ -55,7 +55,7 @@ struct map_info mbx_map = {
.bankwidth = 4,
};
-int __init init_mbx(void)
+static int __init init_mbx(void)
{
printk(KERN_NOTICE "Motorola MBX flash device: 0x%x at 0x%x\n", WINDOW_SIZE*4, WINDOW_ADDR);
mbx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index 965e6c6d6ab0..a97133eb9d70 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -226,7 +226,7 @@ static int __init nettel_init(void)
if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) {
printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n",
- amd_mtd->size>>10);
+ (int)(amd_mtd->size>>10));
amd_mtd->owner = THIS_MODULE;
@@ -357,13 +357,12 @@ static int __init nettel_init(void)
*intel1par = 0;
}
- printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n",
- (intel_mtd->size >> 10));
+ printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %lldKiB\n",
+ (unsigned long long)(intel_mtd->size >> 10));
intel_mtd->owner = THIS_MODULE;
- num_intel_partitions = sizeof(nettel_intel_partitions) /
- sizeof(nettel_intel_partitions[0]);
+ num_intel_partitions = ARRAY_SIZE(nettel_intel_partitions);
if (intelboot) {
/*
diff --git a/drivers/mtd/maps/octagon-5066.c b/drivers/mtd/maps/octagon-5066.c
index 43e04c1d22a9..2b2e45093218 100644
--- a/drivers/mtd/maps/octagon-5066.c
+++ b/drivers/mtd/maps/octagon-5066.c
@@ -184,7 +184,7 @@ void cleanup_oct5066(void)
release_region(PAGE_IO, 1);
}
-int __init init_oct5066(void)
+static int __init init_oct5066(void)
{
int i;
int ret = 0;
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c
index 05f276af15da..7e50e9b1b781 100644
--- a/drivers/mtd/maps/omap_nor.c
+++ b/drivers/mtd/maps/omap_nor.c
@@ -101,7 +101,7 @@ static int __init omapflash_probe(struct platform_device *pdev)
err = -ENOMEM;
goto out_release_mem_region;
}
- info->map.name = pdev->dev.bus_id;
+ info->map.name = dev_name(&pdev->dev);
info->map.phys = res->start;
info->map.size = size;
info->map.bankwidth = pdata->width;
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index dfbf3f270cea..87743661d48e 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -29,7 +29,6 @@ struct physmap_flash_info {
struct map_info map[MAX_RESOURCES];
#ifdef CONFIG_MTD_PARTITIONS
int nr_parts;
- struct mtd_partition *parts;
#endif
};
@@ -56,14 +55,10 @@ static int physmap_flash_remove(struct platform_device *dev)
for (i = 0; i < MAX_RESOURCES; i++) {
if (info->mtd[i] != NULL) {
#ifdef CONFIG_MTD_PARTITIONS
- if (info->nr_parts) {
+ if (info->nr_parts || physmap_data->nr_parts)
del_mtd_partitions(info->mtd[i]);
- kfree(info->parts);
- } else if (physmap_data->nr_parts) {
- del_mtd_partitions(info->mtd[i]);
- } else {
+ else
del_mtd_device(info->mtd[i]);
- }
#else
del_mtd_device(info->mtd[i]);
#endif
@@ -73,7 +68,12 @@ static int physmap_flash_remove(struct platform_device *dev)
return 0;
}
-static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+static const char *rom_probe_types[] = {
+ "cfi_probe",
+ "jedec_probe",
+ "qinfo_probe",
+ "map_rom",
+ NULL };
#ifdef CONFIG_MTD_PARTITIONS
static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
#endif
@@ -86,6 +86,9 @@ static int physmap_flash_probe(struct platform_device *dev)
int err = 0;
int i;
int devices_found = 0;
+#ifdef CONFIG_MTD_PARTITIONS
+ struct mtd_partition *parts;
+#endif
physmap_data = dev->dev.platform_data;
if (physmap_data == NULL)
@@ -108,17 +111,18 @@ static int physmap_flash_probe(struct platform_device *dev)
if (!devm_request_mem_region(&dev->dev,
dev->resource[i].start,
dev->resource[i].end - dev->resource[i].start + 1,
- dev->dev.bus_id)) {
+ dev_name(&dev->dev))) {
dev_err(&dev->dev, "Could not reserve memory region\n");
err = -ENOMEM;
goto err_out;
}
- info->map[i].name = dev->dev.bus_id;
+ info->map[i].name = dev_name(&dev->dev);
info->map[i].phys = dev->resource[i].start;
info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1;
info->map[i].bankwidth = physmap_data->width;
info->map[i].set_vpp = physmap_data->set_vpp;
+ info->map[i].pfow_base = physmap_data->pfow_base;
info->map[i].virt = devm_ioremap(&dev->dev, info->map[i].phys,
info->map[i].size);
@@ -150,7 +154,7 @@ static int physmap_flash_probe(struct platform_device *dev)
* We detected multiple devices. Concatenate them together.
*/
#ifdef CONFIG_MTD_CONCAT
- info->cmtd = mtd_concat_create(info->mtd, devices_found, dev->dev.bus_id);
+ info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev));
if (info->cmtd == NULL)
err = -ENXIO;
#else
@@ -163,9 +167,10 @@ static int physmap_flash_probe(struct platform_device *dev)
goto err_out;
#ifdef CONFIG_MTD_PARTITIONS
- err = parse_mtd_partitions(info->cmtd, part_probe_types, &info->parts, 0);
+ err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0);
if (err > 0) {
- add_mtd_partitions(info->cmtd, info->parts, err);
+ add_mtd_partitions(info->cmtd, parts, err);
+ kfree(parts);
return 0;
}
@@ -251,14 +256,7 @@ static struct platform_driver physmap_flash_driver = {
};
-#ifdef CONFIG_MTD_PHYSMAP_LEN
-#if CONFIG_MTD_PHYSMAP_LEN != 0
-#warning using PHYSMAP compat code
-#define PHYSMAP_COMPAT
-#endif
-#endif
-
-#ifdef PHYSMAP_COMPAT
+#ifdef CONFIG_MTD_PHYSMAP_COMPAT
static struct physmap_flash_data physmap_flash_data = {
.width = CONFIG_MTD_PHYSMAP_BANKWIDTH,
};
@@ -302,7 +300,7 @@ static int __init physmap_init(void)
int err;
err = platform_driver_register(&physmap_flash_driver);
-#ifdef PHYSMAP_COMPAT
+#ifdef CONFIG_MTD_PHYSMAP_COMPAT
if (err == 0)
platform_device_register(&physmap_flash);
#endif
@@ -312,7 +310,7 @@ static int __init physmap_init(void)
static void __exit physmap_exit(void)
{
-#ifdef PHYSMAP_COMPAT
+#ifdef CONFIG_MTD_PHYSMAP_COMPAT
platform_device_unregister(&physmap_flash);
#endif
platform_driver_unregister(&physmap_flash_driver);
@@ -326,8 +324,7 @@ MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_DESCRIPTION("Generic configurable MTD map driver");
/* legacy platform drivers can't hotplug or coldplg */
-#ifndef PHYSMAP_COMPAT
+#ifndef CONFIG_MTD_PHYSMAP_COMPAT
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:physmap-flash");
#endif
-
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 5fcfec034a94..fbf0ca939d72 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -183,7 +183,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
err = -EBUSY;
info->res = request_mem_region(res.start, res.end - res.start + 1,
- dev->dev.bus_id);
+ dev_name(&dev->dev));
if (!info->res)
goto err_out;
@@ -194,7 +194,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
goto err_out;
}
- info->map.name = dev->dev.bus_id;
+ info->map.name = dev_name(&dev->dev);
info->map.phys = res.start;
info->map.size = res.end - res.start + 1;
info->map.bankwidth = *width;
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c
index f43ba2815cbb..4768bd5459d6 100644
--- a/drivers/mtd/maps/pmcmsp-flash.c
+++ b/drivers/mtd/maps/pmcmsp-flash.c
@@ -48,7 +48,7 @@ static int fcnt;
#define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n", __func__, __LINE__)
-int __init init_msp_flash(void)
+static int __init init_msp_flash(void)
{
int i, j;
int offset, coff;
diff --git a/drivers/mtd/maps/redwood.c b/drivers/mtd/maps/redwood.c
index de002eb1a7fe..933c0b63b016 100644
--- a/drivers/mtd/maps/redwood.c
+++ b/drivers/mtd/maps/redwood.c
@@ -122,7 +122,7 @@ struct map_info redwood_flash_map = {
static struct mtd_info *redwood_mtd;
-int __init init_redwood_flash(void)
+static int __init init_redwood_flash(void)
{
int err;
diff --git a/drivers/mtd/maps/rpxlite.c b/drivers/mtd/maps/rpxlite.c
index 14d90edb4430..3e3ef53d4fd4 100644
--- a/drivers/mtd/maps/rpxlite.c
+++ b/drivers/mtd/maps/rpxlite.c
@@ -23,7 +23,7 @@ static struct map_info rpxlite_map = {
.phys = WINDOW_ADDR,
};
-int __init init_rpxlite(void)
+static int __init init_rpxlite(void)
{
printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR);
rpxlite_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE * 4);
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 7df6bbf0e4d9..6f6a0f6dafd6 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -453,7 +453,7 @@ static struct platform_driver sa1100_mtd_driver = {
.resume = sa1100_mtd_resume,
.shutdown = sa1100_mtd_shutdown,
.driver = {
- .name = "flash",
+ .name = "sa1100-mtd",
.owner = THIS_MODULE,
},
};
@@ -474,4 +474,4 @@ module_exit(sa1100_mtd_exit);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("SA1100 CFI map driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:flash");
+MODULE_ALIAS("platform:sa1100-mtd");
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c
index 6e1e99cd2b59..d5374cdcb163 100644
--- a/drivers/mtd/maps/sbc8240.c
+++ b/drivers/mtd/maps/sbc8240.c
@@ -136,7 +136,7 @@ static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
#endif /* CONFIG_MTD_PARTITIONS */
-int __init init_sbc8240_mtd (void)
+static int __init init_sbc8240_mtd (void)
{
static struct _cjs {
u_long addr;
diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c
index 21169e6d646c..7e329f09a548 100644
--- a/drivers/mtd/maps/scb2_flash.c
+++ b/drivers/mtd/maps/scb2_flash.c
@@ -118,7 +118,8 @@ scb2_fixup_mtd(struct mtd_info *mtd)
struct mtd_erase_region_info *region = &mtd->eraseregions[i];
if (region->numblocks * region->erasesize > mtd->size) {
- region->numblocks = (mtd->size / region->erasesize);
+ region->numblocks = ((unsigned long)mtd->size /
+ region->erasesize);
done = 1;
} else {
region->numblocks = 0;
@@ -187,8 +188,9 @@ scb2_flash_probe(struct pci_dev *dev, const struct pci_device_id *ent)
return -ENODEV;
}
- printk(KERN_NOTICE MODNAME ": chip size 0x%x at offset 0x%x\n",
- scb2_mtd->size, SCB2_WINDOW - scb2_mtd->size);
+ printk(KERN_NOTICE MODNAME ": chip size 0x%llx at offset 0x%llx\n",
+ (unsigned long long)scb2_mtd->size,
+ (unsigned long long)(SCB2_WINDOW - scb2_mtd->size));
add_mtd_device(scb2_mtd);
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
index 026eab028189..b392f096c706 100644
--- a/drivers/mtd/maps/sharpsl-flash.c
+++ b/drivers/mtd/maps/sharpsl-flash.c
@@ -47,7 +47,7 @@ static struct mtd_partition sharpsl_partitions[1] = {
}
};
-int __init init_sharpsl(void)
+static int __init init_sharpsl(void)
{
struct mtd_partition *parts;
int nb_parts = 0;
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index a5d3d8531faa..60146984f4be 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -109,7 +109,7 @@ static struct mtd_partition tqm8xxl_fs_partitions[] = {
};
#endif
-int __init init_tqm_mtd(void)
+static int __init init_tqm_mtd(void)
{
int idx = 0, ret = 0;
unsigned long flash_addr, flash_size, mtd_size = 0;
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 0dc645f8152f..81756e397711 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -51,7 +51,7 @@ int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
/****************************************************************************/
-int __init uclinux_mtd_init(void)
+static int __init uclinux_mtd_init(void)
{
struct mtd_info *mtd;
struct map_info *mapp;
@@ -94,7 +94,7 @@ int __init uclinux_mtd_init(void)
/****************************************************************************/
-void __exit uclinux_mtd_cleanup(void)
+static void __exit uclinux_mtd_cleanup(void)
{
if (uclinux_ram_mtdinfo) {
del_mtd_partitions(uclinux_ram_mtdinfo);
diff --git a/drivers/mtd/maps/vmax301.c b/drivers/mtd/maps/vmax301.c
index 5a0c9a353b0f..6d452dcdfe34 100644
--- a/drivers/mtd/maps/vmax301.c
+++ b/drivers/mtd/maps/vmax301.c
@@ -146,7 +146,7 @@ static void __exit cleanup_vmax301(void)
iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START);
}
-int __init init_vmax301(void)
+static int __init init_vmax301(void)
{
int i;
unsigned long iomapadr;
diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c
index 413b0cf9bbd2..933a2b6598b4 100644
--- a/drivers/mtd/maps/wr_sbc82xx_flash.c
+++ b/drivers/mtd/maps/wr_sbc82xx_flash.c
@@ -74,7 +74,7 @@ do { \
} \
} while (0);
-int __init init_sbc82xx_flash(void)
+static int __init init_sbc82xx_flash(void)
{
volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl;
int bigflash;
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index bcffeda2df3d..e9ec59e9a566 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -450,16 +450,20 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
if (!erase)
ret = -ENOMEM;
else {
+ struct erase_info_user einfo;
+
wait_queue_head_t waitq;
DECLARE_WAITQUEUE(wait, current);
init_waitqueue_head(&waitq);
- if (copy_from_user(&erase->addr, argp,
+ if (copy_from_user(&einfo, argp,
sizeof(struct erase_info_user))) {
kfree(erase);
return -EFAULT;
}
+ erase->addr = einfo.start;
+ erase->len = einfo.length;
erase->mtd = mtd;
erase->callback = mtdchar_erase_callback;
erase->priv = (unsigned long)&waitq;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 789842d0e6f2..3dbb1b38db66 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -197,7 +197,7 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
continue;
}
- size = min(total_len, (size_t)(subdev->size - to));
+ size = min_t(uint64_t, total_len, subdev->size - to);
wsize = size; /* store for future use */
entry_high = entry_low;
@@ -385,7 +385,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
struct mtd_concat *concat = CONCAT(mtd);
struct mtd_info *subdev;
int i, err;
- u_int32_t length, offset = 0;
+ uint64_t length, offset = 0;
struct erase_info *erase;
if (!(mtd->flags & MTD_WRITEABLE))
@@ -518,7 +518,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
return 0;
}
-static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_concat *concat = CONCAT(mtd);
int i, err = -EINVAL;
@@ -528,7 +528,7 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
- size_t size;
+ uint64_t size;
if (ofs >= subdev->size) {
size = 0;
@@ -556,7 +556,7 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
return err;
}
-static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_concat *concat = CONCAT(mtd);
int i, err = 0;
@@ -566,7 +566,7 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
for (i = 0; i < concat->num_subdev; i++) {
struct mtd_info *subdev = concat->subdev[i];
- size_t size;
+ uint64_t size;
if (ofs >= subdev->size) {
size = 0;
@@ -691,12 +691,12 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
*/
struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */
int num_devs, /* number of subdevices */
- char *name)
+ const char *name)
{ /* name for the new device */
int i;
size_t size;
struct mtd_concat *concat;
- u_int32_t max_erasesize, curr_erasesize;
+ uint32_t max_erasesize, curr_erasesize;
int num_erase_region;
printk(KERN_NOTICE "Concatenating MTD devices:\n");
@@ -842,12 +842,14 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.erasesize = curr_erasesize;
concat->mtd.numeraseregions = 0;
} else {
+ uint64_t tmp64;
+
/*
* erase block size varies across the subdevices: allocate
* space to store the data describing the variable erase regions
*/
struct mtd_erase_region_info *erase_region_p;
- u_int32_t begin, position;
+ uint64_t begin, position;
concat->mtd.erasesize = max_erasesize;
concat->mtd.numeraseregions = num_erase_region;
@@ -879,8 +881,9 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
erase_region_p->offset = begin;
erase_region_p->erasesize =
curr_erasesize;
- erase_region_p->numblocks =
- (position - begin) / curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
begin = position;
curr_erasesize = subdev[i]->erasesize;
@@ -897,9 +900,9 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
erase_region_p->offset = begin;
erase_region_p->erasesize =
curr_erasesize;
- erase_region_p->numblocks =
- (position -
- begin) / curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
begin = position;
curr_erasesize =
@@ -909,14 +912,16 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
}
position +=
subdev[i]->eraseregions[j].
- numblocks * curr_erasesize;
+ numblocks * (uint64_t)curr_erasesize;
}
}
}
/* Now write the final entry */
erase_region_p->offset = begin;
erase_region_p->erasesize = curr_erasesize;
- erase_region_p->numblocks = (position - begin) / curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
}
return &concat->mtd;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index a9d246949820..76fe0a1e7a5e 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -57,6 +57,19 @@ int add_mtd_device(struct mtd_info *mtd)
mtd->index = i;
mtd->usecount = 0;
+ if (is_power_of_2(mtd->erasesize))
+ mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
+ else
+ mtd->erasesize_shift = 0;
+
+ if (is_power_of_2(mtd->writesize))
+ mtd->writesize_shift = ffs(mtd->writesize) - 1;
+ else
+ mtd->writesize_shift = 0;
+
+ mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
+ mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
+
/* Some chips always power up locked. Unlock them now */
if ((mtd->flags & MTD_WRITEABLE)
&& (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) {
@@ -344,7 +357,8 @@ static inline int mtd_proc_info (char *buf, int i)
if (!this)
return 0;
- return sprintf(buf, "mtd%d: %8.8x %8.8x \"%s\"\n", i, this->size,
+ return sprintf(buf, "mtd%d: %8.8llx %8.8x \"%s\"\n", i,
+ (unsigned long long)this->size,
this->erasesize, this->name);
}
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index aebb3b27edbd..1a6b3beabe8d 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -80,9 +80,9 @@ static int mtdoops_erase_block(struct mtd_info *mtd, int offset)
if (ret) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait);
- printk (KERN_WARNING "mtdoops: erase of region [0x%x, 0x%x] "
+ printk (KERN_WARNING "mtdoops: erase of region [0x%llx, 0x%llx] "
"on \"%s\" failed\n",
- erase.addr, erase.len, mtd->name);
+ (unsigned long long)erase.addr, (unsigned long long)erase.len, mtd->name);
return ret;
}
@@ -289,7 +289,10 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
}
cxt->mtd = mtd;
- cxt->oops_pages = mtd->size / OOPS_PAGE_SIZE;
+ if (mtd->size > INT_MAX)
+ cxt->oops_pages = INT_MAX / OOPS_PAGE_SIZE;
+ else
+ cxt->oops_pages = (int)mtd->size / OOPS_PAGE_SIZE;
find_next_position(cxt);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 3728913fa5fa..144e6b613a77 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -26,7 +26,7 @@ static LIST_HEAD(mtd_partitions);
struct mtd_part {
struct mtd_info mtd;
struct mtd_info *master;
- u_int32_t offset;
+ uint64_t offset;
int index;
struct list_head list;
int registered;
@@ -235,7 +235,7 @@ void mtd_erase_callback(struct erase_info *instr)
}
EXPORT_SYMBOL_GPL(mtd_erase_callback);
-static int part_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_part *part = PART(mtd);
if ((len + ofs) > mtd->size)
@@ -243,7 +243,7 @@ static int part_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
return part->master->lock(part->master, ofs + part->offset, len);
}
-static int part_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_part *part = PART(mtd);
if ((len + ofs) > mtd->size)
@@ -317,7 +317,7 @@ EXPORT_SYMBOL(del_mtd_partitions);
static struct mtd_part *add_one_partition(struct mtd_info *master,
const struct mtd_partition *part, int partno,
- u_int32_t cur_offset)
+ uint64_t cur_offset)
{
struct mtd_part *slave;
@@ -395,19 +395,19 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
slave->offset = cur_offset;
if (slave->offset == MTDPART_OFS_NXTBLK) {
slave->offset = cur_offset;
- if ((cur_offset % master->erasesize) != 0) {
+ if (mtd_mod_by_eb(cur_offset, master) != 0) {
/* Round up to next erasesize */
- slave->offset = ((cur_offset / master->erasesize) + 1) * master->erasesize;
+ slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize;
printk(KERN_NOTICE "Moving partition %d: "
- "0x%08x -> 0x%08x\n", partno,
- cur_offset, slave->offset);
+ "0x%012llx -> 0x%012llx\n", partno,
+ (unsigned long long)cur_offset, (unsigned long long)slave->offset);
}
}
if (slave->mtd.size == MTDPART_SIZ_FULL)
slave->mtd.size = master->size - slave->offset;
- printk(KERN_NOTICE "0x%08x-0x%08x : \"%s\"\n", slave->offset,
- slave->offset + slave->mtd.size, slave->mtd.name);
+ printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
+ (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
/* let's do some sanity checks */
if (slave->offset >= master->size) {
@@ -420,13 +420,13 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
}
if (slave->offset + slave->mtd.size > master->size) {
slave->mtd.size = master->size - slave->offset;
- printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#x\n",
- part->name, master->name, slave->mtd.size);
+ printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n",
+ part->name, master->name, (unsigned long long)slave->mtd.size);
}
if (master->numeraseregions > 1) {
/* Deal with variable erase size stuff */
int i, max = master->numeraseregions;
- u32 end = slave->offset + slave->mtd.size;
+ u64 end = slave->offset + slave->mtd.size;
struct mtd_erase_region_info *regions = master->eraseregions;
/* Find the first erase regions which is part of this
@@ -449,7 +449,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
}
if ((slave->mtd.flags & MTD_WRITEABLE) &&
- (slave->offset % slave->mtd.erasesize)) {
+ mtd_mod_by_eb(slave->offset, &slave->mtd)) {
/* Doesn't start on a boundary of major erase size */
/* FIXME: Let it be writable if it is on a boundary of
* _minor_ erase size though */
@@ -458,7 +458,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
part->name);
}
if ((slave->mtd.flags & MTD_WRITEABLE) &&
- (slave->mtd.size % slave->mtd.erasesize)) {
+ mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
slave->mtd.flags &= ~MTD_WRITEABLE;
printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
part->name);
@@ -466,7 +466,7 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
slave->mtd.ecclayout = master->ecclayout;
if (master->block_isbad) {
- uint32_t offs = 0;
+ uint64_t offs = 0;
while (offs < slave->mtd.size) {
if (master->block_isbad(master,
@@ -501,7 +501,7 @@ int add_mtd_partitions(struct mtd_info *master,
int nbparts)
{
struct mtd_part *slave;
- u_int32_t cur_offset = 0;
+ uint64_t cur_offset = 0;
int i;
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index f8ae0400c49c..8b12e6e109d3 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -163,6 +163,13 @@ config MTD_NAND_S3C2410_HWECC
incorrect ECC generation, and if using these, the default of
software ECC is preferable.
+config MTD_NAND_NDFC
+ tristate "NDFC NanD Flash Controller"
+ depends on 4xx
+ select MTD_NAND_ECC_SMC
+ help
+ NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
+
config MTD_NAND_S3C2410_CLKSTOP
bool "S3C2410 NAND IDLE clock stop"
depends on MTD_NAND_S3C2410
diff --git a/drivers/mtd/nand/alauda.c b/drivers/mtd/nand/alauda.c
index 962380394855..6d9649159a18 100644
--- a/drivers/mtd/nand/alauda.c
+++ b/drivers/mtd/nand/alauda.c
@@ -676,11 +676,11 @@ static int alauda_probe(struct usb_interface *interface,
goto error;
al->write_out = usb_sndbulkpipe(al->dev,
- ep_wr->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ usb_endpoint_num(ep_wr));
al->bulk_in = usb_rcvbulkpipe(al->dev,
- ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ usb_endpoint_num(ep_in));
al->bulk_out = usb_sndbulkpipe(al->dev,
- ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+ usb_endpoint_num(ep_out));
/* second device is identical up to now */
memcpy(al+1, al, sizeof(*al));
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index b8064bf3aee4..22a6b2e50e91 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -90,7 +90,7 @@ static int timing[3];
module_param_array(timing, int, &numtimings, 0644);
#ifdef CONFIG_MTD_PARTITIONS
-static const char *part_probes[] = { "RedBoot", NULL };
+static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
#endif
/* Hrm. Why isn't this already conditional on something in the struct device? */
@@ -805,10 +805,13 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
add_mtd_device(mtd);
#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ mtd->name = "cafe_nand";
+#endif
nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
if (nr_parts > 0) {
cafe->parts = parts;
- dev_info(&cafe->pdev->dev, "%d RedBoot partitions found\n", nr_parts);
+ dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts);
add_mtd_partitions(mtd, parts, nr_parts);
}
#endif
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 4aa5bd6158da..1f6eb2578717 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -676,7 +676,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
chip->numchips);
- dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %ld\n",
+ dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
chip->chipsize);
dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
chip->pagemask);
@@ -703,7 +703,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
chip->ecc.layout);
dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
- dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %d\n", mtd->size);
+ dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
mtd->erasesize);
dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
@@ -777,7 +777,9 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
/* Fill in fsl_elbc_mtd structure */
priv->mtd.priv = chip;
priv->mtd.owner = THIS_MODULE;
- priv->fmr = 0; /* rest filled in later */
+
+ /* Set the ECCM according to the settings in bootloader.*/
+ priv->fmr = in_be32(&lbc->fmr) & FMR_ECCM;
/* fill in nand_chip structure */
/* set up function call table */
@@ -930,8 +932,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
#endif
add_mtd_device(&priv->mtd);
- printk(KERN_INFO "eLBC NAND device at 0x%zx, bank %d\n",
- res.start, priv->bank);
+ printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
+ (unsigned long long)res.start, priv->bank);
return 0;
err:
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index a83192f80eba..7815a404a632 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -222,7 +222,7 @@ static int __devinit fun_probe(struct of_device *ofdev,
fun->rnb_gpio = of_get_gpio(ofdev->node, 0);
if (fun->rnb_gpio >= 0) {
- ret = gpio_request(fun->rnb_gpio, ofdev->dev.bus_id);
+ ret = gpio_request(fun->rnb_gpio, dev_name(&ofdev->dev));
if (ret) {
dev_err(&ofdev->dev, "can't request RNB gpio\n");
goto err2;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 0a9c9cd33f96..0c3afccde8a2 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2014,13 +2014,14 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
int allowbbt)
{
- int page, len, status, pages_per_block, ret, chipnr;
+ int page, status, pages_per_block, ret, chipnr;
struct nand_chip *chip = mtd->priv;
- int rewrite_bbt[NAND_MAX_CHIPS]={0};
+ loff_t rewrite_bbt[NAND_MAX_CHIPS]={0};
unsigned int bbt_masked_page = 0xffffffff;
+ loff_t len;
- DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
- (unsigned int)instr->addr, (unsigned int)instr->len);
+ DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%012llx, len = %llu\n",
+ (unsigned long long)instr->addr, (unsigned long long)instr->len);
/* Start address must align on block boundary */
if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
@@ -2116,7 +2117,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
"Failed erase, page 0x%08x\n", page);
instr->state = MTD_ERASE_FAILED;
- instr->fail_addr = (page << chip->page_shift);
+ instr->fail_addr =
+ ((loff_t)page << chip->page_shift);
goto erase_exit;
}
@@ -2126,7 +2128,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
*/
if (bbt_masked_page != 0xffffffff &&
(page & BBT_PAGE_MASK) == bbt_masked_page)
- rewrite_bbt[chipnr] = (page << chip->page_shift);
+ rewrite_bbt[chipnr] =
+ ((loff_t)page << chip->page_shift);
/* Increment page address and decrement length */
len -= (1 << chip->phys_erase_shift);
@@ -2173,7 +2176,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
continue;
/* update the BBT for chip */
DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
- "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
+ "(%d:0x%0llx 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
chip->bbt_td->pages[chipnr]);
nand_update_bbt(mtd, rewrite_bbt[chipnr]);
}
@@ -2365,7 +2368,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if (!mtd->name)
mtd->name = type->name;
- chip->chipsize = type->chipsize << 20;
+ chip->chipsize = (uint64_t)type->chipsize << 20;
/* Newer devices have all the information in additional id bytes */
if (!type->pagesize) {
@@ -2423,7 +2426,10 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
chip->bbt_erase_shift = chip->phys_erase_shift =
ffs(mtd->erasesize) - 1;
- chip->chip_shift = ffs(chip->chipsize) - 1;
+ if (chip->chipsize & 0xffffffff)
+ chip->chip_shift = ffs((unsigned)chip->chipsize) - 1;
+ else
+ chip->chip_shift = ffs((unsigned)(chip->chipsize >> 32)) + 32 - 1;
/* Set the bad block position */
chip->badblockpos = mtd->writesize > 512 ?
@@ -2517,7 +2523,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
/**
* nand_scan_tail - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
- * @maxchips: Number of chips to scan for
*
* This is the second phase of the normal nand_scan() function. It
* fills out all the uninitialized function pointers with the defaults
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 0b1c48595f12..55c23e5cd210 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -171,16 +171,16 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
if (tmp == msk)
continue;
if (reserved_block_code && (tmp == reserved_block_code)) {
- printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
- ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+ printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n",
+ (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
mtd->ecc_stats.bbtblocks++;
continue;
}
/* Leave it for now, if its matured we can move this
* message to MTD_DEBUG_LEVEL0 */
- printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
- ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+ printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
+ (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
/* Factory marked bad or worn out ? */
if (tmp == 0)
this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
@@ -284,7 +284,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
/* Read the primary version, if available */
if (td->options & NAND_BBT_VERSION) {
- scan_read_raw(mtd, buf, td->pages[0] << this->page_shift,
+ scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
mtd->writesize);
td->version[0] = buf[mtd->writesize + td->veroffs];
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
@@ -293,7 +293,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
/* Read the mirror version, if available */
if (md && (md->options & NAND_BBT_VERSION)) {
- scan_read_raw(mtd, buf, md->pages[0] << this->page_shift,
+ scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
mtd->writesize);
md->version[0] = buf[mtd->writesize + md->veroffs];
printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
@@ -411,7 +411,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
startblock = chip * numblocks;
numblocks += startblock;
- from = startblock << (this->bbt_erase_shift - 1);
+ from = (loff_t)startblock << (this->bbt_erase_shift - 1);
}
for (i = startblock; i < numblocks;) {
@@ -428,8 +428,8 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
if (ret) {
this->bbt[i >> 3] |= 0x03 << (i & 0x6);
- printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
- i >> 1, (unsigned int)from);
+ printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n",
+ i >> 1, (unsigned long long)from);
mtd->ecc_stats.badblocks++;
}
@@ -495,7 +495,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
for (block = 0; block < td->maxblocks; block++) {
int actblock = startblock + dir * block;
- loff_t offs = actblock << this->bbt_erase_shift;
+ loff_t offs = (loff_t)actblock << this->bbt_erase_shift;
/* Read first page */
scan_read_raw(mtd, buf, offs, mtd->writesize);
@@ -719,7 +719,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
memset(&einfo, 0, sizeof(einfo));
einfo.mtd = mtd;
- einfo.addr = (unsigned long)to;
+ einfo.addr = to;
einfo.len = 1 << this->bbt_erase_shift;
res = nand_erase_nand(mtd, &einfo, 1);
if (res < 0)
@@ -729,8 +729,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
if (res < 0)
goto outerr;
- printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
- "0x%02X\n", (unsigned int)to, td->version[chip]);
+ printk(KERN_DEBUG "Bad block table written to 0x%012llx, version "
+ "0x%02X\n", (unsigned long long)to, td->version[chip]);
/* Mark it as used */
td->pages[chip] = page;
@@ -910,7 +910,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
newval = oldval | (0x2 << (block & 0x06));
this->bbt[(block >> 3)] = newval;
if ((oldval != newval) && td->reserved_block_code)
- nand_update_bbt(mtd, block << (this->bbt_erase_shift - 1));
+ nand_update_bbt(mtd, (loff_t)block << (this->bbt_erase_shift - 1));
continue;
}
update = 0;
@@ -931,7 +931,7 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
new ones have been marked, then we need to update the stored
bbts. This should only happen once. */
if (update && td->reserved_block_code)
- nand_update_bbt(mtd, (block - 2) << (this->bbt_erase_shift - 1));
+ nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1));
}
}
@@ -1027,7 +1027,6 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
if (!this->bbt || !td)
return -EINVAL;
- len = mtd->size >> (this->bbt_erase_shift + 2);
/* Allocate a temporary buffer for one eraseblock incl. oob */
len = (1 << this->bbt_erase_shift);
len += (len >> this->page_shift) * mtd->oobsize;
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index ae7c57781a68..cd0711b83ac4 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -38,6 +38,9 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
/* Default simulator parameters values */
#if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE) || \
@@ -100,6 +103,7 @@ static unsigned int bitflips = 0;
static char *gravepages = NULL;
static unsigned int rptwear = 0;
static unsigned int overridesize = 0;
+static char *cache_file = NULL;
module_param(first_id_byte, uint, 0400);
module_param(second_id_byte, uint, 0400);
@@ -122,12 +126,13 @@ module_param(bitflips, uint, 0400);
module_param(gravepages, charp, 0400);
module_param(rptwear, uint, 0400);
module_param(overridesize, uint, 0400);
+module_param(cache_file, charp, 0400);
MODULE_PARM_DESC(first_id_byte, "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)");
MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
MODULE_PARM_DESC(third_id_byte, "The third byte returned by NAND Flash 'read ID' command");
MODULE_PARM_DESC(fourth_id_byte, "The fourth byte returned by NAND Flash 'read ID' command");
-MODULE_PARM_DESC(access_delay, "Initial page access delay (microiseconds)");
+MODULE_PARM_DESC(access_delay, "Initial page access delay (microseconds)");
MODULE_PARM_DESC(programm_delay, "Page programm delay (microseconds");
MODULE_PARM_DESC(erase_delay, "Sector erase delay (milliseconds)");
MODULE_PARM_DESC(output_cycle, "Word output (from flash) time (nanodeconds)");
@@ -153,6 +158,7 @@ MODULE_PARM_DESC(rptwear, "Number of erases inbetween reporting wear, if
MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the ID bytes. "
"The size is specified in erase blocks and as the exponent of a power of two"
" e.g. 5 means a size of 32 erase blocks");
+MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory");
/* The largest possible page size */
#define NS_LARGEST_PAGE_SIZE 2048
@@ -266,6 +272,9 @@ MODULE_PARM_DESC(overridesize, "Specifies the NAND Flash size overriding the I
*/
#define NS_MAX_PREVSTATES 1
+/* Maximum page cache pages needed to read or write a NAND page to the cache_file */
+#define NS_MAX_HELD_PAGES 16
+
/*
* A union to represent flash memory contents and flash buffer.
*/
@@ -295,6 +304,9 @@ struct nandsim {
/* The simulated NAND flash pages array */
union ns_mem *pages;
+ /* Slab allocator for nand pages */
+ struct kmem_cache *nand_pages_slab;
+
/* Internal buffer of page + OOB size bytes */
union ns_mem buf;
@@ -335,6 +347,13 @@ struct nandsim {
int ale; /* address Latch Enable */
int wp; /* write Protect */
} lines;
+
+ /* Fields needed when using a cache file */
+ struct file *cfile; /* Open file */
+ unsigned char *pages_written; /* Which pages have been written */
+ void *file_buf;
+ struct page *held_pages[NS_MAX_HELD_PAGES];
+ int held_cnt;
};
/*
@@ -420,25 +439,69 @@ static struct mtd_info *nsmtd;
static u_char ns_verify_buf[NS_LARGEST_PAGE_SIZE];
/*
- * Allocate array of page pointers and initialize the array to NULL
- * pointers.
+ * Allocate array of page pointers, create slab allocation for an array
+ * and initialize the array by NULL pointers.
*
* RETURNS: 0 if success, -ENOMEM if memory alloc fails.
*/
static int alloc_device(struct nandsim *ns)
{
- int i;
+ struct file *cfile;
+ int i, err;
+
+ if (cache_file) {
+ cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
+ if (IS_ERR(cfile))
+ return PTR_ERR(cfile);
+ if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) {
+ NS_ERR("alloc_device: cache file not readable\n");
+ err = -EINVAL;
+ goto err_close;
+ }
+ if (!cfile->f_op->write && !cfile->f_op->aio_write) {
+ NS_ERR("alloc_device: cache file not writeable\n");
+ err = -EINVAL;
+ goto err_close;
+ }
+ ns->pages_written = vmalloc(ns->geom.pgnum);
+ if (!ns->pages_written) {
+ NS_ERR("alloc_device: unable to allocate pages written array\n");
+ err = -ENOMEM;
+ goto err_close;
+ }
+ ns->file_buf = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
+ if (!ns->file_buf) {
+ NS_ERR("alloc_device: unable to allocate file buf\n");
+ err = -ENOMEM;
+ goto err_free;
+ }
+ ns->cfile = cfile;
+ memset(ns->pages_written, 0, ns->geom.pgnum);
+ return 0;
+ }
ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
if (!ns->pages) {
- NS_ERR("alloc_map: unable to allocate page array\n");
+ NS_ERR("alloc_device: unable to allocate page array\n");
return -ENOMEM;
}
for (i = 0; i < ns->geom.pgnum; i++) {
ns->pages[i].byte = NULL;
}
+ ns->nand_pages_slab = kmem_cache_create("nandsim",
+ ns->geom.pgszoob, 0, 0, NULL);
+ if (!ns->nand_pages_slab) {
+ NS_ERR("cache_create: unable to create kmem_cache\n");
+ return -ENOMEM;
+ }
return 0;
+
+err_free:
+ vfree(ns->pages_written);
+err_close:
+ filp_close(cfile, NULL);
+ return err;
}
/*
@@ -448,11 +511,20 @@ static void free_device(struct nandsim *ns)
{
int i;
+ if (ns->cfile) {
+ kfree(ns->file_buf);
+ vfree(ns->pages_written);
+ filp_close(ns->cfile, NULL);
+ return;
+ }
+
if (ns->pages) {
for (i = 0; i < ns->geom.pgnum; i++) {
if (ns->pages[i].byte)
- kfree(ns->pages[i].byte);
+ kmem_cache_free(ns->nand_pages_slab,
+ ns->pages[i].byte);
}
+ kmem_cache_destroy(ns->nand_pages_slab);
vfree(ns->pages);
}
}
@@ -464,7 +536,7 @@ static char *get_partition_name(int i)
return kstrdup(buf, GFP_KERNEL);
}
-static u_int64_t divide(u_int64_t n, u_int32_t d)
+static uint64_t divide(uint64_t n, uint32_t d)
{
do_div(n, d);
return n;
@@ -480,8 +552,8 @@ static int init_nandsim(struct mtd_info *mtd)
struct nand_chip *chip = (struct nand_chip *)mtd->priv;
struct nandsim *ns = (struct nandsim *)(chip->priv);
int i, ret = 0;
- u_int64_t remains;
- u_int64_t next_offset;
+ uint64_t remains;
+ uint64_t next_offset;
if (NS_IS_INITIALIZED(ns)) {
NS_ERR("init_nandsim: nandsim is already initialized\n");
@@ -548,7 +620,7 @@ static int init_nandsim(struct mtd_info *mtd)
remains = ns->geom.totsz;
next_offset = 0;
for (i = 0; i < parts_num; ++i) {
- u_int64_t part_sz = (u_int64_t)parts[i] * ns->geom.secsz;
+ uint64_t part_sz = (uint64_t)parts[i] * ns->geom.secsz;
if (!part_sz || part_sz > remains) {
NS_ERR("bad partition size.\n");
@@ -1211,6 +1283,97 @@ static int find_operation(struct nandsim *ns, uint32_t flag)
return -1;
}
+static void put_pages(struct nandsim *ns)
+{
+ int i;
+
+ for (i = 0; i < ns->held_cnt; i++)
+ page_cache_release(ns->held_pages[i]);
+}
+
+/* Get page cache pages in advance to provide NOFS memory allocation */
+static int get_pages(struct nandsim *ns, struct file *file, size_t count, loff_t pos)
+{
+ pgoff_t index, start_index, end_index;
+ struct page *page;
+ struct address_space *mapping = file->f_mapping;
+
+ start_index = pos >> PAGE_CACHE_SHIFT;
+ end_index = (pos + count - 1) >> PAGE_CACHE_SHIFT;
+ if (end_index - start_index + 1 > NS_MAX_HELD_PAGES)
+ return -EINVAL;
+ ns->held_cnt = 0;
+ for (index = start_index; index <= end_index; index++) {
+ page = find_get_page(mapping, index);
+ if (page == NULL) {
+ page = find_or_create_page(mapping, index, GFP_NOFS);
+ if (page == NULL) {
+ write_inode_now(mapping->host, 1);
+ page = find_or_create_page(mapping, index, GFP_NOFS);
+ }
+ if (page == NULL) {
+ put_pages(ns);
+ return -ENOMEM;
+ }
+ unlock_page(page);
+ }
+ ns->held_pages[ns->held_cnt++] = page;
+ }
+ return 0;
+}
+
+static int set_memalloc(void)
+{
+ if (current->flags & PF_MEMALLOC)
+ return 0;
+ current->flags |= PF_MEMALLOC;
+ return 1;
+}
+
+static void clear_memalloc(int memalloc)
+{
+ if (memalloc)
+ current->flags &= ~PF_MEMALLOC;
+}
+
+static ssize_t read_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t *pos)
+{
+ mm_segment_t old_fs;
+ ssize_t tx;
+ int err, memalloc;
+
+ err = get_pages(ns, file, count, *pos);
+ if (err)
+ return err;
+ old_fs = get_fs();
+ set_fs(get_ds());
+ memalloc = set_memalloc();
+ tx = vfs_read(file, (char __user *)buf, count, pos);
+ clear_memalloc(memalloc);
+ set_fs(old_fs);
+ put_pages(ns);
+ return tx;
+}
+
+static ssize_t write_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t *pos)
+{
+ mm_segment_t old_fs;
+ ssize_t tx;
+ int err, memalloc;
+
+ err = get_pages(ns, file, count, *pos);
+ if (err)
+ return err;
+ old_fs = get_fs();
+ set_fs(get_ds());
+ memalloc = set_memalloc();
+ tx = vfs_write(file, (char __user *)buf, count, pos);
+ clear_memalloc(memalloc);
+ set_fs(old_fs);
+ put_pages(ns);
+ return tx;
+}
+
/*
* Returns a pointer to the current page.
*/
@@ -1227,6 +1390,38 @@ static inline u_char *NS_PAGE_BYTE_OFF(struct nandsim *ns)
return NS_GET_PAGE(ns)->byte + ns->regs.column + ns->regs.off;
}
+int do_read_error(struct nandsim *ns, int num)
+{
+ unsigned int page_no = ns->regs.row;
+
+ if (read_error(page_no)) {
+ int i;
+ memset(ns->buf.byte, 0xFF, num);
+ for (i = 0; i < num; ++i)
+ ns->buf.byte[i] = random32();
+ NS_WARN("simulating read error in page %u\n", page_no);
+ return 1;
+ }
+ return 0;
+}
+
+void do_bit_flips(struct nandsim *ns, int num)
+{
+ if (bitflips && random32() < (1 << 22)) {
+ int flips = 1;
+ if (bitflips > 1)
+ flips = (random32() % (int) bitflips) + 1;
+ while (flips--) {
+ int pos = random32() % (num * 8);
+ ns->buf.byte[pos / 8] ^= (1 << (pos % 8));
+ NS_WARN("read_page: flipping bit %d in page %d "
+ "reading from %d ecc: corrected=%u failed=%u\n",
+ pos, ns->regs.row, ns->regs.column + ns->regs.off,
+ nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed);
+ }
+ }
+}
+
/*
* Fill the NAND buffer with data read from the specified page.
*/
@@ -1234,36 +1429,40 @@ static void read_page(struct nandsim *ns, int num)
{
union ns_mem *mypage;
+ if (ns->cfile) {
+ if (!ns->pages_written[ns->regs.row]) {
+ NS_DBG("read_page: page %d not written\n", ns->regs.row);
+ memset(ns->buf.byte, 0xFF, num);
+ } else {
+ loff_t pos;
+ ssize_t tx;
+
+ NS_DBG("read_page: page %d written, reading from %d\n",
+ ns->regs.row, ns->regs.column + ns->regs.off);
+ if (do_read_error(ns, num))
+ return;
+ pos = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off;
+ tx = read_file(ns, ns->cfile, ns->buf.byte, num, &pos);
+ if (tx != num) {
+ NS_ERR("read_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx);
+ return;
+ }
+ do_bit_flips(ns, num);
+ }
+ return;
+ }
+
mypage = NS_GET_PAGE(ns);
if (mypage->byte == NULL) {
NS_DBG("read_page: page %d not allocated\n", ns->regs.row);
memset(ns->buf.byte, 0xFF, num);
} else {
- unsigned int page_no = ns->regs.row;
NS_DBG("read_page: page %d allocated, reading from %d\n",
ns->regs.row, ns->regs.column + ns->regs.off);
- if (read_error(page_no)) {
- int i;
- memset(ns->buf.byte, 0xFF, num);
- for (i = 0; i < num; ++i)
- ns->buf.byte[i] = random32();
- NS_WARN("simulating read error in page %u\n", page_no);
+ if (do_read_error(ns, num))
return;
- }
memcpy(ns->buf.byte, NS_PAGE_BYTE_OFF(ns), num);
- if (bitflips && random32() < (1 << 22)) {
- int flips = 1;
- if (bitflips > 1)
- flips = (random32() % (int) bitflips) + 1;
- while (flips--) {
- int pos = random32() % (num * 8);
- ns->buf.byte[pos / 8] ^= (1 << (pos % 8));
- NS_WARN("read_page: flipping bit %d in page %d "
- "reading from %d ecc: corrected=%u failed=%u\n",
- pos, ns->regs.row, ns->regs.column + ns->regs.off,
- nsmtd->ecc_stats.corrected, nsmtd->ecc_stats.failed);
- }
- }
+ do_bit_flips(ns, num);
}
}
@@ -1275,11 +1474,20 @@ static void erase_sector(struct nandsim *ns)
union ns_mem *mypage;
int i;
+ if (ns->cfile) {
+ for (i = 0; i < ns->geom.pgsec; i++)
+ if (ns->pages_written[ns->regs.row + i]) {
+ NS_DBG("erase_sector: freeing page %d\n", ns->regs.row + i);
+ ns->pages_written[ns->regs.row + i] = 0;
+ }
+ return;
+ }
+
mypage = NS_GET_PAGE(ns);
for (i = 0; i < ns->geom.pgsec; i++) {
if (mypage->byte != NULL) {
NS_DBG("erase_sector: freeing page %d\n", ns->regs.row+i);
- kfree(mypage->byte);
+ kmem_cache_free(ns->nand_pages_slab, mypage->byte);
mypage->byte = NULL;
}
mypage++;
@@ -1295,16 +1503,57 @@ static int prog_page(struct nandsim *ns, int num)
union ns_mem *mypage;
u_char *pg_off;
+ if (ns->cfile) {
+ loff_t off, pos;
+ ssize_t tx;
+ int all;
+
+ NS_DBG("prog_page: writing page %d\n", ns->regs.row);
+ pg_off = ns->file_buf + ns->regs.column + ns->regs.off;
+ off = (loff_t)ns->regs.row * ns->geom.pgszoob + ns->regs.column + ns->regs.off;
+ if (!ns->pages_written[ns->regs.row]) {
+ all = 1;
+ memset(ns->file_buf, 0xff, ns->geom.pgszoob);
+ } else {
+ all = 0;
+ pos = off;
+ tx = read_file(ns, ns->cfile, pg_off, num, &pos);
+ if (tx != num) {
+ NS_ERR("prog_page: read error for page %d ret %ld\n", ns->regs.row, (long)tx);
+ return -1;
+ }
+ }
+ for (i = 0; i < num; i++)
+ pg_off[i] &= ns->buf.byte[i];
+ if (all) {
+ pos = (loff_t)ns->regs.row * ns->geom.pgszoob;
+ tx = write_file(ns, ns->cfile, ns->file_buf, ns->geom.pgszoob, &pos);
+ if (tx != ns->geom.pgszoob) {
+ NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx);
+ return -1;
+ }
+ ns->pages_written[ns->regs.row] = 1;
+ } else {
+ pos = off;
+ tx = write_file(ns, ns->cfile, pg_off, num, &pos);
+ if (tx != num) {
+ NS_ERR("prog_page: write error for page %d ret %ld\n", ns->regs.row, (long)tx);
+ return -1;
+ }
+ }
+ return 0;
+ }
+
mypage = NS_GET_PAGE(ns);
if (mypage->byte == NULL) {
NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
/*
* We allocate memory with GFP_NOFS because a flash FS may
* utilize this. If it is holding an FS lock, then gets here,
- * then kmalloc runs writeback which goes to the FS again
- * and deadlocks. This was seen in practice.
+ * then kernel memory alloc runs writeback which goes to the FS
+ * again and deadlocks. This was seen in practice.
*/
- mypage->byte = kmalloc(ns->geom.pgszoob, GFP_NOFS);
+ mypage->byte = kmem_cache_alloc(ns->nand_pages_slab, GFP_NOFS);
if (mypage->byte == NULL) {
NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
return -1;
@@ -1736,13 +1985,17 @@ static void ns_nand_write_byte(struct mtd_info *mtd, u_char byte)
/* Check if chip is expecting command */
if (NS_STATE(ns->nxstate) != STATE_UNKNOWN && !(ns->nxstate & STATE_CMD_MASK)) {
- /*
- * We are in situation when something else (not command)
- * was expected but command was input. In this case ignore
- * previous command(s)/state(s) and accept the last one.
- */
- NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, "
- "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate));
+ /* Do not warn if only 2 id bytes are read */
+ if (!(ns->regs.command == NAND_CMD_READID &&
+ NS_STATE(ns->state) == STATE_DATAOUT_ID && ns->regs.count == 2)) {
+ /*
+ * We are in situation when something else (not command)
+ * was expected but command was input. In this case ignore
+ * previous command(s)/state(s) and accept the last one.
+ */
+ NS_WARN("write_byte: command (%#x) wasn't expected, expected state is %s, "
+ "ignore previous states\n", (uint)byte, get_state_name(ns->nxstate));
+ }
switch_to_ready_state(ns, NS_STATUS_FAILED(ns));
}
@@ -2044,7 +2297,7 @@ static int __init ns_init_module(void)
}
if (overridesize) {
- u_int64_t new_size = (u_int64_t)nsmtd->erasesize << overridesize;
+ uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize;
if (new_size >> overridesize != nsmtd->erasesize) {
NS_ERR("overridesize is too big\n");
goto err_exit;
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 955959eb02d4..582cf80f555a 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -2,12 +2,20 @@
* drivers/mtd/ndfc.c
*
* Overview:
- * Platform independend driver for NDFC (NanD Flash Controller)
+ * Platform independent driver for NDFC (NanD Flash Controller)
* integrated into EP440 cores
*
+ * Ported to an OF platform driver by Sean MacLennan
+ *
+ * The NDFC supports multiple chips, but this driver only supports a
+ * single chip since I do not have access to any boards with
+ * multiple chips.
+ *
* Author: Thomas Gleixner
*
* Copyright 2006 IBM
+ * Copyright 2008 PIKA Technologies
+ * Sean MacLennan <smaclennan@pikatech.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
@@ -21,27 +29,20 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/ndfc.h>
#include <linux/mtd/mtd.h>
-#include <linux/platform_device.h>
-
+#include <linux/of_platform.h>
#include <asm/io.h>
-#ifdef CONFIG_40x
-#include <asm/ibm405.h>
-#else
-#include <asm/ibm44x.h>
-#endif
-
-struct ndfc_nand_mtd {
- struct mtd_info mtd;
- struct nand_chip chip;
- struct platform_nand_chip *pl_chip;
-};
-static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
struct ndfc_controller {
- void __iomem *ndfcbase;
- struct nand_hw_control ndfc_control;
- atomic_t childs_active;
+ struct of_device *ofdev;
+ void __iomem *ndfcbase;
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ int chip_select;
+ struct nand_hw_control ndfc_control;
+#ifdef CONFIG_MTD_PARTITIONS
+ struct mtd_partition *parts;
+#endif
};
static struct ndfc_controller ndfc_ctrl;
@@ -50,17 +51,14 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip)
{
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *nandchip = mtd->priv;
- struct ndfc_nand_mtd *nandmtd = nandchip->priv;
- struct platform_nand_chip *pchip = nandmtd->pl_chip;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
if (chip >= 0) {
ccr &= ~NDFC_CCR_BS_MASK;
- ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
+ ccr |= NDFC_CCR_BS(chip + ndfc->chip_select);
} else
ccr |= NDFC_CCR_RESET_CE;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
}
static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -80,7 +78,7 @@ static int ndfc_ready(struct mtd_info *mtd)
{
struct ndfc_controller *ndfc = &ndfc_ctrl;
- return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
+ return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
}
static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
@@ -88,9 +86,9 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
uint32_t ccr;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+ ccr = in_be32(ndfc->ndfcbase + NDFC_CCR);
ccr |= NDFC_CCR_RESET_ECC;
- __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
wmb();
}
@@ -102,9 +100,10 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd,
uint8_t *p = (uint8_t *)&ecc;
wmb();
- ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
- ecc_code[0] = p[1];
- ecc_code[1] = p[2];
+ ecc = in_be32(ndfc->ndfcbase + NDFC_ECC);
+ /* The NDFC uses Smart Media (SMC) bytes order */
+ ecc_code[0] = p[2];
+ ecc_code[1] = p[1];
ecc_code[2] = p[3];
return 0;
@@ -123,7 +122,7 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
+ *p++ = in_be32(ndfc->ndfcbase + NDFC_DATA);
}
static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -132,7 +131,7 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
+ out_be32(ndfc->ndfcbase + NDFC_DATA, *p++);
}
static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
@@ -141,7 +140,7 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *) buf;
for(;len > 0; len -= 4)
- if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
+ if (*p++ != in_be32(ndfc->ndfcbase + NDFC_DATA))
return -EFAULT;
return 0;
}
@@ -149,10 +148,19 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
/*
* Initialize chip structure
*/
-static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
+static int ndfc_chip_init(struct ndfc_controller *ndfc,
+ struct device_node *node)
{
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct nand_chip *chip = &mtd->chip;
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ static const char *part_types[] = { "cmdlinepart", NULL };
+#else
+ static const char *part_types[] = { NULL };
+#endif
+#endif
+ struct device_node *flash_np;
+ struct nand_chip *chip = &ndfc->chip;
+ int ret;
chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
@@ -160,8 +168,6 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->dev_ready = ndfc_ready;
chip->select_chip = ndfc_select_chip;
chip->chip_delay = 50;
- chip->priv = mtd;
- chip->options = mtd->pl_chip->options;
chip->controller = &ndfc->ndfc_control;
chip->read_buf = ndfc_read_buf;
chip->write_buf = ndfc_write_buf;
@@ -172,143 +178,136 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = 256;
chip->ecc.bytes = 3;
- chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout;
- mtd->mtd.priv = chip;
- mtd->mtd.owner = THIS_MODULE;
-}
-
-static int ndfc_chip_probe(struct platform_device *pdev)
-{
- struct platform_nand_chip *nc = pdev->dev.platform_data;
- struct ndfc_chip_settings *settings = nc->priv;
- struct ndfc_controller *ndfc = &ndfc_ctrl;
- struct ndfc_nand_mtd *nandmtd;
-
- if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
- return -EINVAL;
-
- /* Set the bank settings */
- __raw_writel(settings->bank_settings,
- ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
- nandmtd = &ndfc_mtd[pdev->id];
- if (nandmtd->pl_chip)
- return -EBUSY;
+ ndfc->mtd.priv = chip;
+ ndfc->mtd.owner = THIS_MODULE;
- nandmtd->pl_chip = nc;
- ndfc_chip_init(nandmtd);
-
- /* Scan for chips */
- if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
- nandmtd->pl_chip = NULL;
+ flash_np = of_get_next_child(node, NULL);
+ if (!flash_np)
return -ENODEV;
+
+ ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
+ ndfc->ofdev->dev.bus_id, flash_np->name);
+ if (!ndfc->mtd.name) {
+ ret = -ENOMEM;
+ goto err;
}
-#ifdef CONFIG_MTD_PARTITIONS
- printk("Number of partitions %d\n", nc->nr_partitions);
- if (nc->nr_partitions) {
- /* Add the full device, so complete dumps can be made */
- add_mtd_device(&nandmtd->mtd);
- add_mtd_partitions(&nandmtd->mtd, nc->partitions,
- nc->nr_partitions);
+ ret = nand_scan(&ndfc->mtd, 1);
+ if (ret)
+ goto err;
- } else
-#else
- add_mtd_device(&nandmtd->mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+ ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
+ if (ret < 0)
+ goto err;
+
+#ifdef CONFIG_MTD_OF_PARTS
+ if (ret == 0) {
+ ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
+ &ndfc->parts);
+ if (ret < 0)
+ goto err;
+ }
#endif
- atomic_inc(&ndfc->childs_active);
- return 0;
-}
+ if (ret > 0)
+ ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret);
+ else
+#endif
+ ret = add_mtd_device(&ndfc->mtd);
-static int ndfc_chip_remove(struct platform_device *pdev)
-{
- return 0;
+err:
+ of_node_put(flash_np);
+ if (ret)
+ kfree(ndfc->mtd.name);
+ return ret;
}
-static int ndfc_nand_probe(struct platform_device *pdev)
+static int __devinit ndfc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
- struct platform_nand_ctrl *nc = pdev->dev.platform_data;
- struct ndfc_controller_settings *settings = nc->priv;
- struct resource *res = pdev->resource;
struct ndfc_controller *ndfc = &ndfc_ctrl;
- unsigned long long phys = settings->ndfc_erpn | res->start;
+ const u32 *reg;
+ u32 ccr;
+ int err, len;
-#ifndef CONFIG_PHYS_64BIT
- ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
-#else
- ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
-#endif
+ spin_lock_init(&ndfc->ndfc_control.lock);
+ init_waitqueue_head(&ndfc->ndfc_control.wq);
+ ndfc->ofdev = ofdev;
+ dev_set_drvdata(&ofdev->dev, ndfc);
+
+ /* Read the reg property to get the chip select */
+ reg = of_get_property(ofdev->node, "reg", &len);
+ if (reg == NULL || len != 12) {
+ dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
+ return -ENOENT;
+ }
+ ndfc->chip_select = reg[0];
+
+ ndfc->ndfcbase = of_iomap(ofdev->node, 0);
if (!ndfc->ndfcbase) {
- printk(KERN_ERR "NDFC: ioremap failed\n");
+ dev_err(&ofdev->dev, "failed to get memory\n");
return -EIO;
}
- __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
+ ccr = NDFC_CCR_BS(ndfc->chip_select);
- spin_lock_init(&ndfc->ndfc_control.lock);
- init_waitqueue_head(&ndfc->ndfc_control.wq);
+ /* It is ok if ccr does not exist - just default to 0 */
+ reg = of_get_property(ofdev->node, "ccr", NULL);
+ if (reg)
+ ccr |= *reg;
- platform_set_drvdata(pdev, ndfc);
+ out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
- printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
- __raw_readl(ndfc->ndfcbase + NDFC_REVID));
+ /* Set the bank settings if given */
+ reg = of_get_property(ofdev->node, "bank-settings", NULL);
+ if (reg) {
+ int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
+ out_be32(ndfc->ndfcbase + offset, *reg);
+ }
+
+ err = ndfc_chip_init(ndfc, ofdev->node);
+ if (err) {
+ iounmap(ndfc->ndfcbase);
+ return err;
+ }
return 0;
}
-static int ndfc_nand_remove(struct platform_device *pdev)
+static int __devexit ndfc_remove(struct of_device *ofdev)
{
- struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
+ struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
- if (atomic_read(&ndfc->childs_active))
- return -EBUSY;
+ nand_release(&ndfc->mtd);
- if (ndfc) {
- platform_set_drvdata(pdev, NULL);
- iounmap(ndfc_ctrl.ndfcbase);
- ndfc_ctrl.ndfcbase = NULL;
- }
return 0;
}
-/* driver device registration */
-
-static struct platform_driver ndfc_chip_driver = {
- .probe = ndfc_chip_probe,
- .remove = ndfc_chip_remove,
- .driver = {
- .name = "ndfc-chip",
- .owner = THIS_MODULE,
- },
+static const struct of_device_id ndfc_match[] = {
+ { .compatible = "ibm,ndfc", },
+ {}
};
+MODULE_DEVICE_TABLE(of, ndfc_match);
-static struct platform_driver ndfc_nand_driver = {
- .probe = ndfc_nand_probe,
- .remove = ndfc_nand_remove,
- .driver = {
- .name = "ndfc-nand",
- .owner = THIS_MODULE,
+static struct of_platform_driver ndfc_driver = {
+ .driver = {
+ .name = "ndfc",
},
+ .match_table = ndfc_match,
+ .probe = ndfc_probe,
+ .remove = __devexit_p(ndfc_remove),
};
static int __init ndfc_nand_init(void)
{
- int ret;
-
- spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
- init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
-
- ret = platform_driver_register(&ndfc_nand_driver);
- if (!ret)
- ret = platform_driver_register(&ndfc_chip_driver);
- return ret;
+ return of_register_platform_driver(&ndfc_driver);
}
static void __exit ndfc_nand_exit(void)
{
- platform_driver_unregister(&ndfc_chip_driver);
- platform_driver_unregister(&ndfc_nand_driver);
+ of_unregister_platform_driver(&ndfc_driver);
}
module_init(ndfc_nand_init);
@@ -316,6 +315,4 @@ module_exit(ndfc_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Platform driver for NDFC");
-MODULE_ALIAS("platform:ndfc-chip");
-MODULE_ALIAS("platform:ndfc-nand");
+MODULE_DESCRIPTION("OF Platform driver for NDFC");
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 9bd6c9ac8443..a8b9376cf324 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -107,7 +107,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev,
if (pasemi_nand_mtd)
return -ENODEV;
- pr_debug("pasemi_nand at %lx-%lx\n", res.start, res.end);
+ pr_debug("pasemi_nand at %llx-%llx\n", res.start, res.end);
/* Allocate memory for MTD device structure and private data */
pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) +
@@ -170,7 +170,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev,
goto out_lpc;
}
- printk(KERN_INFO "PA Semi NAND flash at %08lx, control at I/O %x\n",
+ printk(KERN_INFO "PA Semi NAND flash at %08llx, control at I/O %x\n",
res.start, lpcctl);
return 0;
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index f674c5427b17..75f9f4874ecf 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -54,7 +54,7 @@ static int __init plat_nand_probe(struct platform_device *pdev)
data->chip.priv = &data;
data->mtd.priv = &data->chip;
data->mtd.owner = THIS_MODULE;
- data->mtd.name = pdev->dev.bus_id;
+ data->mtd.name = dev_name(&pdev->dev);
data->chip.IO_ADDR_R = data->io_base;
data->chip.IO_ADDR_W = data->io_base;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index fc4144495610..cc55cbc2b308 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -298,7 +298,7 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = {
#define NDTR1_tAR(c) (min((c), 15) << 0)
/* convert nano-seconds to nand flash controller clock cycles */
-#define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) + 1)
+#define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) - 1)
static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
const struct pxa3xx_nand_timing *t)
@@ -368,14 +368,14 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
/* large block, 2 cycles for column address
* row address starts from 3rd cycle
*/
- info->ndcb1 |= (page_addr << 16) | (column & 0xffff);
+ info->ndcb1 |= page_addr << 16;
if (info->row_addr_cycles == 3)
info->ndcb2 = (page_addr >> 16) & 0xff;
} else
/* small block, 1 cycles for column address
* row address starts from 2nd cycle
*/
- info->ndcb1 = (page_addr << 8) | (column & 0xff);
+ info->ndcb1 = page_addr << 8;
if (cmd == cmdset->program)
info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 30a518e211bd..54ec7542a7b7 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -2,6 +2,7 @@
* drivers/mtd/nand/sharpsl.c
*
* Copyright (C) 2004 Richard Purdie
+ * Copyright (C) 2008 Dmitry Baryshkov
*
* Based on Sharp's NAND driver sharp_sl.c
*
@@ -19,22 +20,31 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
+#include <linux/mtd/sharpsl.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
#include <asm/io.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
-static void __iomem *sharpsl_io_base;
-static int sharpsl_phys_base = 0x0C000000;
+struct sharpsl_nand {
+ struct mtd_info mtd;
+ struct nand_chip chip;
+
+ void __iomem *io;
+};
+
+#define mtd_to_sharpsl(_mtd) container_of(_mtd, struct sharpsl_nand, mtd)
/* register offset */
-#define ECCLPLB sharpsl_io_base+0x00 /* line parity 7 - 0 bit */
-#define ECCLPUB sharpsl_io_base+0x04 /* line parity 15 - 8 bit */
-#define ECCCP sharpsl_io_base+0x08 /* column parity 5 - 0 bit */
-#define ECCCNTR sharpsl_io_base+0x0C /* ECC byte counter */
-#define ECCCLRR sharpsl_io_base+0x10 /* cleare ECC */
-#define FLASHIO sharpsl_io_base+0x14 /* Flash I/O */
-#define FLASHCTL sharpsl_io_base+0x18 /* Flash Control */
+#define ECCLPLB 0x00 /* line parity 7 - 0 bit */
+#define ECCLPUB 0x04 /* line parity 15 - 8 bit */
+#define ECCCP 0x08 /* column parity 5 - 0 bit */
+#define ECCCNTR 0x0C /* ECC byte counter */
+#define ECCCLRR 0x10 /* cleare ECC */
+#define FLASHIO 0x14 /* Flash I/O */
+#define FLASHCTL 0x18 /* Flash Control */
/* Flash control bit */
#define FLRYBY (1 << 5)
@@ -45,35 +55,6 @@ static int sharpsl_phys_base = 0x0C000000;
#define FLCE0 (1 << 0)
/*
- * MTD structure for SharpSL
- */
-static struct mtd_info *sharpsl_mtd = NULL;
-
-/*
- * Define partitions for flash device
- */
-#define DEFAULT_NUM_PARTITIONS 3
-
-static int nr_partitions;
-static struct mtd_partition sharpsl_nand_default_partition_info[] = {
- {
- .name = "System Area",
- .offset = 0,
- .size = 7 * 1024 * 1024,
- },
- {
- .name = "Root Filesystem",
- .offset = 7 * 1024 * 1024,
- .size = 30 * 1024 * 1024,
- },
- {
- .name = "Home Filesystem",
- .offset = MTDPART_OFS_APPEND,
- .size = MTDPART_SIZ_FULL,
- },
-};
-
-/*
* hardware specific access to control-lines
* ctrl:
* NAND_CNE: bit 0 -> ! bit 0 & 4
@@ -84,6 +65,7 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = {
static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
+ struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
struct nand_chip *chip = mtd->priv;
if (ctrl & NAND_CTRL_CHANGE) {
@@ -93,103 +75,97 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
bits ^= 0x11;
- writeb((readb(FLASHCTL) & ~0x17) | bits, FLASHCTL);
+ writeb((readb(sharpsl->io + FLASHCTL) & ~0x17) | bits, sharpsl->io + FLASHCTL);
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
}
-static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
-
-static struct nand_bbt_descr sharpsl_bbt = {
- .options = 0,
- .offs = 4,
- .len = 2,
- .pattern = scan_ff_pattern
-};
-
-static struct nand_bbt_descr sharpsl_akita_bbt = {
- .options = 0,
- .offs = 4,
- .len = 1,
- .pattern = scan_ff_pattern
-};
-
-static struct nand_ecclayout akita_oobinfo = {
- .eccbytes = 24,
- .eccpos = {
- 0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
- 0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
- 0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
- .oobfree = {{0x08, 0x09}}
-};
-
static int sharpsl_nand_dev_ready(struct mtd_info *mtd)
{
- return !((readb(FLASHCTL) & FLRYBY) == 0);
+ struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
+ return !((readb(sharpsl->io + FLASHCTL) & FLRYBY) == 0);
}
static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
- writeb(0, ECCCLRR);
+ struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
+ writeb(0, sharpsl->io + ECCCLRR);
}
static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code)
{
- ecc_code[0] = ~readb(ECCLPUB);
- ecc_code[1] = ~readb(ECCLPLB);
- ecc_code[2] = (~readb(ECCCP) << 2) | 0x03;
- return readb(ECCCNTR) != 0;
+ struct sharpsl_nand *sharpsl = mtd_to_sharpsl(mtd);
+ ecc_code[0] = ~readb(sharpsl->io + ECCLPUB);
+ ecc_code[1] = ~readb(sharpsl->io + ECCLPLB);
+ ecc_code[2] = (~readb(sharpsl->io + ECCCP) << 2) | 0x03;
+ return readb(sharpsl->io + ECCCNTR) != 0;
}
#ifdef CONFIG_MTD_PARTITIONS
-const char *part_probes[] = { "cmdlinepart", NULL };
+static const char *part_probes[] = { "cmdlinepart", NULL };
#endif
/*
* Main initialization routine
*/
-static int __init sharpsl_nand_init(void)
+static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
{
struct nand_chip *this;
+#ifdef CONFIG_MTD_PARTITIONS
struct mtd_partition *sharpsl_partition_info;
+ int nr_partitions;
+#endif
+ struct resource *r;
int err = 0;
+ struct sharpsl_nand *sharpsl;
+ struct sharpsl_nand_platform_data *data = pdev->dev.platform_data;
+
+ if (!data) {
+ dev_err(&pdev->dev, "no platform data!\n");
+ return -EINVAL;
+ }
/* Allocate memory for MTD device structure and private data */
- sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
- if (!sharpsl_mtd) {
+ sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL);
+ if (!sharpsl) {
printk("Unable to allocate SharpSL NAND MTD device structure.\n");
return -ENOMEM;
}
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no io memory resource defined!\n");
+ err = -ENODEV;
+ goto err_get_res;
+ }
+
/* map physical address */
- sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000);
- if (!sharpsl_io_base) {
+ sharpsl->io = ioremap(r->start, resource_size(r));
+ if (!sharpsl->io) {
printk("ioremap to access Sharp SL NAND chip failed\n");
- kfree(sharpsl_mtd);
- return -EIO;
+ err = -EIO;
+ goto err_ioremap;
}
/* Get pointer to private data */
- this = (struct nand_chip *)(&sharpsl_mtd[1]);
-
- /* Initialize structures */
- memset(sharpsl_mtd, 0, sizeof(struct mtd_info));
- memset(this, 0, sizeof(struct nand_chip));
+ this = (struct nand_chip *)(&sharpsl->chip);
/* Link the private data with the MTD structure */
- sharpsl_mtd->priv = this;
- sharpsl_mtd->owner = THIS_MODULE;
+ sharpsl->mtd.priv = this;
+ sharpsl->mtd.owner = THIS_MODULE;
+
+ platform_set_drvdata(pdev, sharpsl);
/*
* PXA initialize
*/
- writeb(readb(FLASHCTL) | FLWP, FLASHCTL);
+ writeb(readb(sharpsl->io + FLASHCTL) | FLWP, sharpsl->io + FLASHCTL);
/* Set address of NAND IO lines */
- this->IO_ADDR_R = FLASHIO;
- this->IO_ADDR_W = FLASHIO;
+ this->IO_ADDR_R = sharpsl->io + FLASHIO;
+ this->IO_ADDR_W = sharpsl->io + FLASHIO;
/* Set address of hardware control function */
this->cmd_ctrl = sharpsl_nand_hwcontrol;
this->dev_ready = sharpsl_nand_dev_ready;
@@ -199,68 +175,89 @@ static int __init sharpsl_nand_init(void)
this->ecc.mode = NAND_ECC_HW;
this->ecc.size = 256;
this->ecc.bytes = 3;
- this->badblock_pattern = &sharpsl_bbt;
- if (machine_is_akita() || machine_is_borzoi()) {
- this->badblock_pattern = &sharpsl_akita_bbt;
- this->ecc.layout = &akita_oobinfo;
- }
+ this->badblock_pattern = data->badblock_pattern;
+ this->ecc.layout = data->ecc_layout;
this->ecc.hwctl = sharpsl_nand_enable_hwecc;
this->ecc.calculate = sharpsl_nand_calculate_ecc;
this->ecc.correct = nand_correct_data;
/* Scan to find existence of the device */
- err = nand_scan(sharpsl_mtd, 1);
- if (err) {
- iounmap(sharpsl_io_base);
- kfree(sharpsl_mtd);
- return err;
- }
+ err = nand_scan(&sharpsl->mtd, 1);
+ if (err)
+ goto err_scan;
/* Register the partitions */
- sharpsl_mtd->name = "sharpsl-nand";
- nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0);
-
+ sharpsl->mtd.name = "sharpsl-nand";
+#ifdef CONFIG_MTD_PARTITIONS
+ nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0);
if (nr_partitions <= 0) {
- nr_partitions = DEFAULT_NUM_PARTITIONS;
- sharpsl_partition_info = sharpsl_nand_default_partition_info;
- if (machine_is_poodle()) {
- sharpsl_partition_info[1].size = 22 * 1024 * 1024;
- } else if (machine_is_corgi() || machine_is_shepherd()) {
- sharpsl_partition_info[1].size = 25 * 1024 * 1024;
- } else if (machine_is_husky()) {
- sharpsl_partition_info[1].size = 53 * 1024 * 1024;
- } else if (machine_is_spitz()) {
- sharpsl_partition_info[1].size = 5 * 1024 * 1024;
- } else if (machine_is_akita()) {
- sharpsl_partition_info[1].size = 58 * 1024 * 1024;
- } else if (machine_is_borzoi()) {
- sharpsl_partition_info[1].size = 32 * 1024 * 1024;
- }
+ nr_partitions = data->nr_partitions;
+ sharpsl_partition_info = data->partitions;
}
- add_mtd_partitions(sharpsl_mtd, sharpsl_partition_info, nr_partitions);
+ if (nr_partitions > 0)
+ err = add_mtd_partitions(&sharpsl->mtd, sharpsl_partition_info, nr_partitions);
+ else
+#endif
+ err = add_mtd_device(&sharpsl->mtd);
+ if (err)
+ goto err_add;
/* Return happy */
return 0;
-}
-module_init(sharpsl_nand_init);
+err_add:
+ nand_release(&sharpsl->mtd);
+
+err_scan:
+ platform_set_drvdata(pdev, NULL);
+ iounmap(sharpsl->io);
+err_ioremap:
+err_get_res:
+ kfree(sharpsl);
+ return err;
+}
/*
* Clean up routine
*/
-static void __exit sharpsl_nand_cleanup(void)
+static int __devexit sharpsl_nand_remove(struct platform_device *pdev)
{
+ struct sharpsl_nand *sharpsl = platform_get_drvdata(pdev);
+
/* Release resources, unregister device */
- nand_release(sharpsl_mtd);
+ nand_release(&sharpsl->mtd);
- iounmap(sharpsl_io_base);
+ platform_set_drvdata(pdev, NULL);
+
+ iounmap(sharpsl->io);
/* Free the MTD device structure */
- kfree(sharpsl_mtd);
+ kfree(sharpsl);
+
+ return 0;
+}
+
+static struct platform_driver sharpsl_nand_driver = {
+ .driver = {
+ .name = "sharpsl-nand",
+ .owner = THIS_MODULE,
+ },
+ .probe = sharpsl_nand_probe,
+ .remove = __devexit_p(sharpsl_nand_remove),
+};
+
+static int __init sharpsl_nand_init(void)
+{
+ return platform_driver_register(&sharpsl_nand_driver);
}
+module_init(sharpsl_nand_init);
-module_exit(sharpsl_nand_cleanup);
+static void __exit sharpsl_nand_exit(void)
+{
+ platform_driver_unregister(&sharpsl_nand_driver);
+}
+module_exit(sharpsl_nand_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index edb1e322113d..daa6a4c3b8ce 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -433,7 +433,7 @@ static int tmio_probe(struct platform_device *dev)
nand_chip->chip_delay = 15;
retval = request_irq(irq, &tmio_irq,
- IRQF_DISABLED, dev->dev.bus_id, tmio);
+ IRQF_DISABLED, dev_name(&dev->dev), tmio);
if (retval) {
dev_err(&dev->dev, "request_irq error %d\n", retval);
goto err_irq;
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index 320b929abe79..d1c4546513f7 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -39,7 +39,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
struct NFTLrecord *nftl;
unsigned long temp;
- if (mtd->type != MTD_NANDFLASH)
+ if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
return;
/* OK, this is moderately ugly. But probably safe. Alternatives? */
if (memcmp(mtd->name, "DiskOnChip", 10))
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index ccc4f209fbb5..8b22b1836e9f 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -51,7 +51,7 @@ static int find_boot_record(struct NFTLrecord *nftl)
the mtd device accordingly. We could even get rid of
nftl->EraseSize if there were any point in doing so. */
nftl->EraseSize = nftl->mbd.mtd->erasesize;
- nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
+ nftl->nb_blocks = (u32)nftl->mbd.mtd->size / nftl->EraseSize;
nftl->MediaUnit = BLOCK_NIL;
nftl->SpareMediaUnit = BLOCK_NIL;
@@ -168,7 +168,7 @@ device is already correct.
printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n",
mh->UnitSizeFactor);
nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
- nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
+ nftl->nb_blocks = (u32)nftl->mbd.mtd->size / nftl->EraseSize;
}
#endif
nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index ad81ab8e95e2..5b69e7773c6c 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -63,7 +63,7 @@ static int __devinit generic_onenand_probe(struct device *dev)
info->onenand.mmcontrol = pdata->mmcontrol;
info->onenand.irq = platform_get_irq(pdev, 0);
- info->mtd.name = pdev->dev.bus_id;
+ info->mtd.name = dev_name(&pdev->dev);
info->mtd.priv = &info->onenand;
info->mtd.owner = THIS_MODULE;
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index d1e0b8e7224b..77a4f1446156 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -629,7 +629,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
}
if (c->gpio_irq) {
- if ((r = omap_request_gpio(c->gpio_irq)) < 0) {
+ if ((r = gpio_request(c->gpio_irq, "OneNAND irq")) < 0) {
dev_err(&pdev->dev, "Failed to request GPIO%d for "
"OneNAND\n", c->gpio_irq);
goto err_iounmap;
@@ -668,7 +668,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
c->onenand.base);
c->pdev = pdev;
- c->mtd.name = pdev->dev.bus_id;
+ c->mtd.name = dev_name(&pdev->dev);
c->mtd.priv = &c->onenand;
c->mtd.owner = THIS_MODULE;
@@ -726,7 +726,7 @@ err_release_dma:
free_irq(gpio_to_irq(c->gpio_irq), c);
err_release_gpio:
if (c->gpio_irq)
- omap_free_gpio(c->gpio_irq);
+ gpio_free(c->gpio_irq);
err_iounmap:
iounmap(c->onenand.base);
err_release_mem_region:
@@ -761,7 +761,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
if (c->gpio_irq) {
free_irq(gpio_to_irq(c->gpio_irq), c);
- omap_free_gpio(c->gpio_irq);
+ gpio_free(c->gpio_irq);
}
iounmap(c->onenand.base);
release_mem_region(c->phys_base, ONENAND_IO_SIZE);
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index 90ed319f26e6..529af271db17 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1772,7 +1772,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
int len;
int ret = 0;
- DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
+ DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%012llx, len = %llu\n", (unsigned long long) instr->addr, (unsigned long long) instr->len);
block_size = (1 << this->erase_shift);
@@ -1810,7 +1810,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
/* Check if we have a bad block, we do not erase bad blocks */
if (onenand_block_isbad_nolock(mtd, addr, 0)) {
- printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr);
+ printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%012llx\n", (unsigned long long) addr);
instr->state = MTD_ERASE_FAILED;
goto erase_exit;
}
@@ -2029,7 +2029,7 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int
*
* Lock one or more blocks
*/
-static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int onenand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret;
@@ -2047,7 +2047,7 @@ static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
*
* Unlock one or more blocks
*/
-static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
int ret;
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index e538c0a72abb..d2aa9c46530f 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -21,8 +21,6 @@
#include <asm/types.h>
-#define const_cpu_to_le16 __constant_cpu_to_le16
-
static int block_size = 0;
module_param(block_size, int, 0);
MODULE_PARM_DESC(block_size, "Block size to use by RFD, defaults to erase unit size");
@@ -156,7 +154,7 @@ static int scan_header(struct partition *part)
size_t retlen;
sectors_per_block = part->block_size / SECTOR_SIZE;
- part->total_blocks = part->mbd.mtd->size / part->block_size;
+ part->total_blocks = (u32)part->mbd.mtd->size / part->block_size;
if (part->total_blocks < 2)
return -ENOENT;
@@ -276,16 +274,17 @@ static void erase_callback(struct erase_info *erase)
part = (struct partition*)erase->priv;
- i = erase->addr / part->block_size;
- if (i >= part->total_blocks || part->blocks[i].offset != erase->addr) {
- printk(KERN_ERR PREFIX "erase callback for unknown offset %x "
- "on '%s'\n", erase->addr, part->mbd.mtd->name);
+ i = (u32)erase->addr / part->block_size;
+ if (i >= part->total_blocks || part->blocks[i].offset != erase->addr ||
+ erase->addr > UINT_MAX) {
+ printk(KERN_ERR PREFIX "erase callback for unknown offset %llx "
+ "on '%s'\n", (unsigned long long)erase->addr, part->mbd.mtd->name);
return;
}
if (erase->state != MTD_ERASE_DONE) {
- printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', "
- "state %d\n", erase->addr,
+ printk(KERN_WARNING PREFIX "erase failed at 0x%llx on '%s', "
+ "state %d\n", (unsigned long long)erase->addr,
part->mbd.mtd->name, erase->state);
part->blocks[i].state = BLOCK_FAILED;
@@ -297,7 +296,7 @@ static void erase_callback(struct erase_info *erase)
return;
}
- magic = const_cpu_to_le16(RFD_MAGIC);
+ magic = cpu_to_le16(RFD_MAGIC);
part->blocks[i].state = BLOCK_ERASED;
part->blocks[i].free_sectors = part->data_sectors_per_block;
@@ -345,9 +344,9 @@ static int erase_block(struct partition *part, int block)
rc = part->mbd.mtd->erase(part->mbd.mtd, erase);
if (rc) {
- printk(KERN_ERR PREFIX "erase of region %x,%x on '%s' "
- "failed\n", erase->addr, erase->len,
- part->mbd.mtd->name);
+ printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' "
+ "failed\n", (unsigned long long)erase->addr,
+ (unsigned long long)erase->len, part->mbd.mtd->name);
kfree(erase);
}
@@ -587,7 +586,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
int block, offset, rc;
u_long addr;
size_t retlen;
- u16 del = const_cpu_to_le16(SECTOR_DELETED);
+ u16 del = cpu_to_le16(SECTOR_DELETED);
block = old_addr / part->block_size;
offset = (old_addr % part->block_size) / SECTOR_SIZE -
@@ -763,7 +762,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
struct partition *part;
- if (mtd->type != MTD_NORFLASH)
+ if (mtd->type != MTD_NORFLASH || mtd->size > UINT_MAX)
return;
part = kzalloc(sizeof(struct partition), GFP_KERNEL);
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 33a5d6ed6f18..3f67e00d98e0 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -294,7 +294,8 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
int cis_sector;
/* Check for small page NAND flash */
- if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE)
+ if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE ||
+ mtd->size > UINT_MAX)
return;
/* Check for SSDFC format by reading CIS/IDI sector */
@@ -316,7 +317,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
ssfdc->cis_block = cis_sector / (mtd->erasesize >> SECTOR_SHIFT);
ssfdc->erase_size = mtd->erasesize;
- ssfdc->map_len = mtd->size / mtd->erasesize;
+ ssfdc->map_len = (u32)mtd->size / mtd->erasesize;
DEBUG(MTD_DEBUG_LEVEL1,
"SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
@@ -327,7 +328,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
ssfdc->heads = 16;
ssfdc->sectors = 32;
get_chs(mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors);
- ssfdc->cylinders = (unsigned short)((mtd->size >> SECTOR_SHIFT) /
+ ssfdc->cylinders = (unsigned short)(((u32)mtd->size >> SECTOR_SHIFT) /
((long)ssfdc->sectors * (long)ssfdc->heads));
DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n",
diff --git a/drivers/mtd/tests/Makefile b/drivers/mtd/tests/Makefile
new file mode 100644
index 000000000000..c1d501335006
--- /dev/null
+++ b/drivers/mtd/tests/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_MTD_TESTS) += mtd_oobtest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_pagetest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_readtest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_speedtest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_stresstest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o
+obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o
diff --git a/drivers/mtd/tests/mtd_oobtest.c b/drivers/mtd/tests/mtd_oobtest.c
new file mode 100644
index 000000000000..afbc3f8126db
--- /dev/null
+++ b/drivers/mtd/tests/mtd_oobtest.c
@@ -0,0 +1,742 @@
+/*
+ * Copyright (C) 2006-2008 Nokia 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.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test OOB read and write on MTD device.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#include <asm/div64.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+
+#define PRINT_PREF KERN_INFO "mtd_oobtest: "
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *readbuf;
+static unsigned char *writebuf;
+static unsigned char *bbt;
+
+static int ebcnt;
+static int pgcnt;
+static int errcnt;
+static int use_offset;
+static int use_len;
+static int use_len_max;
+static int vary_offset;
+static unsigned long next = 1;
+
+static inline unsigned int simple_rand(void)
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned int)((next / 65536) % 32768);
+}
+
+static inline void simple_srand(unsigned long seed)
+{
+ next = seed;
+}
+
+static void set_random_data(unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ buf[i] = simple_rand();
+}
+
+static int erase_eraseblock(int ebnum)
+{
+ int err;
+ struct erase_info ei;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ memset(&ei, 0, sizeof(struct erase_info));
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = mtd->erasesize;
+
+ err = mtd->erase(mtd, &ei);
+ if (err) {
+ printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+ return err;
+ }
+
+ if (ei.state == MTD_ERASE_FAILED) {
+ printk(PRINT_PREF "some erase error occurred at EB %d\n",
+ ebnum);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int erase_whole_device(void)
+{
+ int err;
+ unsigned int i;
+
+ printk(PRINT_PREF "erasing whole device\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = erase_eraseblock(i);
+ if (err)
+ return err;
+ cond_resched();
+ }
+ printk(PRINT_PREF "erased %u eraseblocks\n", i);
+ return 0;
+}
+
+static void do_vary_offset(void)
+{
+ use_len -= 1;
+ if (use_len < 1) {
+ use_offset += 1;
+ if (use_offset >= use_len_max)
+ use_offset = 0;
+ use_len = use_len_max - use_offset;
+ }
+}
+
+static int write_eraseblock(int ebnum)
+{
+ int i;
+ struct mtd_oob_ops ops;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
+ set_random_data(writebuf, use_len);
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = use_len;
+ ops.oobretlen = 0;
+ ops.ooboffs = use_offset;
+ ops.datbuf = 0;
+ ops.oobbuf = writebuf;
+ err = mtd->write_oob(mtd, addr, &ops);
+ if (err || ops.oobretlen != use_len) {
+ printk(PRINT_PREF "error: writeoob failed at %#llx\n",
+ (long long)addr);
+ printk(PRINT_PREF "error: use_len %d, use_offset %d\n",
+ use_len, use_offset);
+ errcnt += 1;
+ return err ? err : -1;
+ }
+ if (vary_offset)
+ do_vary_offset();
+ }
+
+ return err;
+}
+
+static int write_whole_device(void)
+{
+ int err;
+ unsigned int i;
+
+ printk(PRINT_PREF "writing OOBs of whole device\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock(i);
+ if (err)
+ return err;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "written up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "written %u eraseblocks\n", i);
+ return 0;
+}
+
+static int verify_eraseblock(int ebnum)
+{
+ int i;
+ struct mtd_oob_ops ops;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ for (i = 0; i < pgcnt; ++i, addr += mtd->writesize) {
+ set_random_data(writebuf, use_len);
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = use_len;
+ ops.oobretlen = 0;
+ ops.ooboffs = use_offset;
+ ops.datbuf = 0;
+ ops.oobbuf = readbuf;
+ err = mtd->read_oob(mtd, addr, &ops);
+ if (err || ops.oobretlen != use_len) {
+ printk(PRINT_PREF "error: readoob failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ return err ? err : -1;
+ }
+ if (memcmp(readbuf, writebuf, use_len)) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ if (errcnt > 1000) {
+ printk(PRINT_PREF "error: too many errors\n");
+ return -1;
+ }
+ }
+ if (use_offset != 0 || use_len < mtd->ecclayout->oobavail) {
+ int k;
+
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = mtd->ecclayout->oobavail;
+ ops.oobretlen = 0;
+ ops.ooboffs = 0;
+ ops.datbuf = 0;
+ ops.oobbuf = readbuf;
+ err = mtd->read_oob(mtd, addr, &ops);
+ if (err || ops.oobretlen != mtd->ecclayout->oobavail) {
+ printk(PRINT_PREF "error: readoob failed at "
+ "%#llx\n", (long long)addr);
+ errcnt += 1;
+ return err ? err : -1;
+ }
+ if (memcmp(readbuf + use_offset, writebuf, use_len)) {
+ printk(PRINT_PREF "error: verify failed at "
+ "%#llx\n", (long long)addr);
+ errcnt += 1;
+ if (errcnt > 1000) {
+ printk(PRINT_PREF "error: too many "
+ "errors\n");
+ return -1;
+ }
+ }
+ for (k = 0; k < use_offset; ++k)
+ if (readbuf[k] != 0xff) {
+ printk(PRINT_PREF "error: verify 0xff "
+ "failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ if (errcnt > 1000) {
+ printk(PRINT_PREF "error: too "
+ "many errors\n");
+ return -1;
+ }
+ }
+ for (k = use_offset + use_len;
+ k < mtd->ecclayout->oobavail; ++k)
+ if (readbuf[k] != 0xff) {
+ printk(PRINT_PREF "error: verify 0xff "
+ "failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ if (errcnt > 1000) {
+ printk(PRINT_PREF "error: too "
+ "many errors\n");
+ return -1;
+ }
+ }
+ }
+ if (vary_offset)
+ do_vary_offset();
+ }
+ return err;
+}
+
+static int verify_eraseblock_in_one_go(int ebnum)
+{
+ struct mtd_oob_ops ops;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ size_t len = mtd->ecclayout->oobavail * pgcnt;
+
+ set_random_data(writebuf, len);
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = len;
+ ops.oobretlen = 0;
+ ops.ooboffs = 0;
+ ops.datbuf = 0;
+ ops.oobbuf = readbuf;
+ err = mtd->read_oob(mtd, addr, &ops);
+ if (err || ops.oobretlen != len) {
+ printk(PRINT_PREF "error: readoob failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ return err ? err : -1;
+ }
+ if (memcmp(readbuf, writebuf, len)) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ if (errcnt > 1000) {
+ printk(PRINT_PREF "error: too many errors\n");
+ return -1;
+ }
+ }
+
+ return err;
+}
+
+static int verify_all_eraseblocks(void)
+{
+ int err;
+ unsigned int i;
+
+ printk(PRINT_PREF "verifying all eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = verify_eraseblock(i);
+ if (err)
+ return err;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "verified %u eraseblocks\n", i);
+ return 0;
+}
+
+static int is_block_bad(int ebnum)
+{
+ int ret;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ ret = mtd->block_isbad(mtd, addr);
+ if (ret)
+ printk(PRINT_PREF "block %d is bad\n", ebnum);
+ return ret;
+}
+
+static int scan_for_bad_eraseblocks(void)
+{
+ int i, bad = 0;
+
+ bbt = kmalloc(ebcnt, GFP_KERNEL);
+ if (!bbt) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(bbt, 0 , ebcnt);
+
+ printk(PRINT_PREF "scanning for bad eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ bbt[i] = is_block_bad(i) ? 1 : 0;
+ if (bbt[i])
+ bad += 1;
+ cond_resched();
+ }
+ printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+ return 0;
+}
+
+static int __init mtd_oobtest_init(void)
+{
+ int err = 0;
+ unsigned int i;
+ uint64_t tmp;
+ struct mtd_oob_ops ops;
+ loff_t addr = 0, addr0;
+
+ printk(KERN_INFO "\n");
+ printk(KERN_INFO "=================================================\n");
+ printk(PRINT_PREF "MTD device: %d\n", dev);
+
+ mtd = get_mtd_device(NULL, dev);
+ if (IS_ERR(mtd)) {
+ err = PTR_ERR(mtd);
+ printk(PRINT_PREF "error: cannot get MTD device\n");
+ return err;
+ }
+
+ if (mtd->type != MTD_NANDFLASH) {
+ printk(PRINT_PREF "this test requires NAND flash\n");
+ goto out;
+ }
+
+ tmp = mtd->size;
+ do_div(tmp, mtd->erasesize);
+ ebcnt = tmp;
+ pgcnt = mtd->erasesize / mtd->writesize;
+
+ printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+ "page size %u, count of eraseblocks %u, pages per "
+ "eraseblock %u, OOB size %u\n",
+ (unsigned long long)mtd->size, mtd->erasesize,
+ mtd->writesize, ebcnt, pgcnt, mtd->oobsize);
+
+ err = -ENOMEM;
+ mtd->erasesize = mtd->erasesize;
+ readbuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!readbuf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+ writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!writebuf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+
+ err = scan_for_bad_eraseblocks();
+ if (err)
+ goto out;
+
+ use_offset = 0;
+ use_len = mtd->ecclayout->oobavail;
+ use_len_max = mtd->ecclayout->oobavail;
+ vary_offset = 0;
+
+ /* First test: write all OOB, read it back and verify */
+ printk(PRINT_PREF "test 1 of 5\n");
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ simple_srand(1);
+ err = write_whole_device();
+ if (err)
+ goto out;
+
+ simple_srand(1);
+ err = verify_all_eraseblocks();
+ if (err)
+ goto out;
+
+ /*
+ * Second test: write all OOB, a block at a time, read it back and
+ * verify.
+ */
+ printk(PRINT_PREF "test 2 of 5\n");
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ simple_srand(3);
+ err = write_whole_device();
+ if (err)
+ goto out;
+
+ /* Check all eraseblocks */
+ simple_srand(3);
+ printk(PRINT_PREF "verifying all eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = verify_eraseblock_in_one_go(i);
+ if (err)
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "verified %u eraseblocks\n", i);
+
+ /*
+ * Third test: write OOB at varying offsets and lengths, read it back
+ * and verify.
+ */
+ printk(PRINT_PREF "test 3 of 5\n");
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ /* Write all eraseblocks */
+ use_offset = 0;
+ use_len = mtd->ecclayout->oobavail;
+ use_len_max = mtd->ecclayout->oobavail;
+ vary_offset = 1;
+ simple_srand(5);
+ printk(PRINT_PREF "writing OOBs of whole device\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock(i);
+ if (err)
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "written up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "written %u eraseblocks\n", i);
+
+ /* Check all eraseblocks */
+ use_offset = 0;
+ use_len = mtd->ecclayout->oobavail;
+ use_len_max = mtd->ecclayout->oobavail;
+ vary_offset = 1;
+ simple_srand(5);
+ err = verify_all_eraseblocks();
+ if (err)
+ goto out;
+
+ use_offset = 0;
+ use_len = mtd->ecclayout->oobavail;
+ use_len_max = mtd->ecclayout->oobavail;
+ vary_offset = 0;
+
+ /* Fourth test: try to write off end of device */
+ printk(PRINT_PREF "test 4 of 5\n");
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ addr0 = 0;
+ for (i = 0; bbt[i] && i < ebcnt; ++i)
+ addr0 += mtd->erasesize;
+
+ /* Attempt to write off end of OOB */
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = 1;
+ ops.oobretlen = 0;
+ ops.ooboffs = mtd->ecclayout->oobavail;
+ ops.datbuf = 0;
+ ops.oobbuf = writebuf;
+ printk(PRINT_PREF "attempting to start write past end of OOB\n");
+ printk(PRINT_PREF "an error is expected...\n");
+ err = mtd->write_oob(mtd, addr0, &ops);
+ if (err) {
+ printk(PRINT_PREF "error occurred as expected\n");
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: can write past end of OOB\n");
+ errcnt += 1;
+ }
+
+ /* Attempt to read off end of OOB */
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = 1;
+ ops.oobretlen = 0;
+ ops.ooboffs = mtd->ecclayout->oobavail;
+ ops.datbuf = 0;
+ ops.oobbuf = readbuf;
+ printk(PRINT_PREF "attempting to start read past end of OOB\n");
+ printk(PRINT_PREF "an error is expected...\n");
+ err = mtd->read_oob(mtd, addr0, &ops);
+ if (err) {
+ printk(PRINT_PREF "error occurred as expected\n");
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: can read past end of OOB\n");
+ errcnt += 1;
+ }
+
+ if (bbt[ebcnt - 1])
+ printk(PRINT_PREF "skipping end of device tests because last "
+ "block is bad\n");
+ else {
+ /* Attempt to write off end of device */
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = mtd->ecclayout->oobavail + 1;
+ ops.oobretlen = 0;
+ ops.ooboffs = 0;
+ ops.datbuf = 0;
+ ops.oobbuf = writebuf;
+ printk(PRINT_PREF "attempting to write past end of device\n");
+ printk(PRINT_PREF "an error is expected...\n");
+ err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops);
+ if (err) {
+ printk(PRINT_PREF "error occurred as expected\n");
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: wrote past end of device\n");
+ errcnt += 1;
+ }
+
+ /* Attempt to read off end of device */
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = mtd->ecclayout->oobavail + 1;
+ ops.oobretlen = 0;
+ ops.ooboffs = 0;
+ ops.datbuf = 0;
+ ops.oobbuf = readbuf;
+ printk(PRINT_PREF "attempting to read past end of device\n");
+ printk(PRINT_PREF "an error is expected...\n");
+ err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops);
+ if (err) {
+ printk(PRINT_PREF "error occurred as expected\n");
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: read past end of device\n");
+ errcnt += 1;
+ }
+
+ err = erase_eraseblock(ebcnt - 1);
+ if (err)
+ goto out;
+
+ /* Attempt to write off end of device */
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = mtd->ecclayout->oobavail;
+ ops.oobretlen = 0;
+ ops.ooboffs = 1;
+ ops.datbuf = 0;
+ ops.oobbuf = writebuf;
+ printk(PRINT_PREF "attempting to write past end of device\n");
+ printk(PRINT_PREF "an error is expected...\n");
+ err = mtd->write_oob(mtd, mtd->size - mtd->writesize, &ops);
+ if (err) {
+ printk(PRINT_PREF "error occurred as expected\n");
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: wrote past end of device\n");
+ errcnt += 1;
+ }
+
+ /* Attempt to read off end of device */
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = mtd->ecclayout->oobavail;
+ ops.oobretlen = 0;
+ ops.ooboffs = 1;
+ ops.datbuf = 0;
+ ops.oobbuf = readbuf;
+ printk(PRINT_PREF "attempting to read past end of device\n");
+ printk(PRINT_PREF "an error is expected...\n");
+ err = mtd->read_oob(mtd, mtd->size - mtd->writesize, &ops);
+ if (err) {
+ printk(PRINT_PREF "error occurred as expected\n");
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: read past end of device\n");
+ errcnt += 1;
+ }
+ }
+
+ /* Fifth test: write / read across block boundaries */
+ printk(PRINT_PREF "test 5 of 5\n");
+
+ /* Erase all eraseblocks */
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ /* Write all eraseblocks */
+ simple_srand(11);
+ printk(PRINT_PREF "writing OOBs of whole device\n");
+ for (i = 0; i < ebcnt - 1; ++i) {
+ int cnt = 2;
+ int pg;
+ size_t sz = mtd->ecclayout->oobavail;
+ if (bbt[i] || bbt[i + 1])
+ continue;
+ addr = (i + 1) * mtd->erasesize - mtd->writesize;
+ for (pg = 0; pg < cnt; ++pg) {
+ set_random_data(writebuf, sz);
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = sz;
+ ops.oobretlen = 0;
+ ops.ooboffs = 0;
+ ops.datbuf = 0;
+ ops.oobbuf = writebuf;
+ err = mtd->write_oob(mtd, addr, &ops);
+ if (err)
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "written up to eraseblock "
+ "%u\n", i);
+ cond_resched();
+ addr += mtd->writesize;
+ }
+ }
+ printk(PRINT_PREF "written %u eraseblocks\n", i);
+
+ /* Check all eraseblocks */
+ simple_srand(11);
+ printk(PRINT_PREF "verifying all eraseblocks\n");
+ for (i = 0; i < ebcnt - 1; ++i) {
+ if (bbt[i] || bbt[i + 1])
+ continue;
+ set_random_data(writebuf, mtd->ecclayout->oobavail * 2);
+ addr = (i + 1) * mtd->erasesize - mtd->writesize;
+ ops.mode = MTD_OOB_AUTO;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = mtd->ecclayout->oobavail * 2;
+ ops.oobretlen = 0;
+ ops.ooboffs = 0;
+ ops.datbuf = 0;
+ ops.oobbuf = readbuf;
+ err = mtd->read_oob(mtd, addr, &ops);
+ if (err)
+ goto out;
+ if (memcmp(readbuf, writebuf, mtd->ecclayout->oobavail * 2)) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ if (errcnt > 1000) {
+ printk(PRINT_PREF "error: too many errors\n");
+ goto out;
+ }
+ }
+ if (i % 256 == 0)
+ printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "verified %u eraseblocks\n", i);
+
+ printk(PRINT_PREF "finished with %d errors\n", errcnt);
+out:
+ kfree(bbt);
+ kfree(writebuf);
+ kfree(readbuf);
+ put_mtd_device(mtd);
+ if (err)
+ printk(PRINT_PREF "error %d occurred\n", err);
+ printk(KERN_INFO "=================================================\n");
+ return err;
+}
+module_init(mtd_oobtest_init);
+
+static void __exit mtd_oobtest_exit(void)
+{
+ return;
+}
+module_exit(mtd_oobtest_exit);
+
+MODULE_DESCRIPTION("Out-of-band test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c
new file mode 100644
index 000000000000..9648818b9e2c
--- /dev/null
+++ b/drivers/mtd/tests/mtd_pagetest.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2006-2008 Nokia 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.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test page read and write on MTD device.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#include <asm/div64.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+
+#define PRINT_PREF KERN_INFO "mtd_pagetest: "
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *twopages;
+static unsigned char *writebuf;
+static unsigned char *boundary;
+static unsigned char *bbt;
+
+static int pgsize;
+static int bufsize;
+static int ebcnt;
+static int pgcnt;
+static int errcnt;
+static unsigned long next = 1;
+
+static inline unsigned int simple_rand(void)
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned int)((next / 65536) % 32768);
+}
+
+static inline void simple_srand(unsigned long seed)
+{
+ next = seed;
+}
+
+static void set_random_data(unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ buf[i] = simple_rand();
+}
+
+static int erase_eraseblock(int ebnum)
+{
+ int err;
+ struct erase_info ei;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ memset(&ei, 0, sizeof(struct erase_info));
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = mtd->erasesize;
+
+ err = mtd->erase(mtd, &ei);
+ if (err) {
+ printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+ return err;
+ }
+
+ if (ei.state == MTD_ERASE_FAILED) {
+ printk(PRINT_PREF "some erase error occurred at EB %d\n",
+ ebnum);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int write_eraseblock(int ebnum)
+{
+ int err = 0;
+ size_t written = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ set_random_data(writebuf, mtd->erasesize);
+ cond_resched();
+ err = mtd->write(mtd, addr, mtd->erasesize, &written, writebuf);
+ if (err || written != mtd->erasesize)
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ (long long)addr);
+
+ return err;
+}
+
+static int verify_eraseblock(int ebnum)
+{
+ uint32_t j;
+ size_t read = 0;
+ int err = 0, i;
+ loff_t addr0, addrn;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ addr0 = 0;
+ for (i = 0; bbt[i] && i < ebcnt; ++i)
+ addr0 += mtd->erasesize;
+
+ addrn = mtd->size;
+ for (i = 0; bbt[ebcnt - i - 1] && i < ebcnt; ++i)
+ addrn -= mtd->erasesize;
+
+ set_random_data(writebuf, mtd->erasesize);
+ for (j = 0; j < pgcnt - 1; ++j, addr += pgsize) {
+ /* Do a read to set the internal dataRAMs to different data */
+ err = mtd->read(mtd, addr0, bufsize, &read, twopages);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != bufsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr0);
+ return err;
+ }
+ err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != bufsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)(addrn - bufsize));
+ return err;
+ }
+ memset(twopages, 0, bufsize);
+ read = 0;
+ err = mtd->read(mtd, addr, bufsize, &read, twopages);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != bufsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ break;
+ }
+ if (memcmp(twopages, writebuf + (j * pgsize), bufsize)) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ }
+ }
+ /* Check boundary between eraseblocks */
+ if (addr <= addrn - pgsize - pgsize && !bbt[ebnum + 1]) {
+ unsigned long oldnext = next;
+ /* Do a read to set the internal dataRAMs to different data */
+ err = mtd->read(mtd, addr0, bufsize, &read, twopages);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != bufsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr0);
+ return err;
+ }
+ err = mtd->read(mtd, addrn - bufsize, bufsize, &read, twopages);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != bufsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)(addrn - bufsize));
+ return err;
+ }
+ memset(twopages, 0, bufsize);
+ read = 0;
+ err = mtd->read(mtd, addr, bufsize, &read, twopages);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != bufsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ return err;
+ }
+ memcpy(boundary, writebuf + mtd->erasesize - pgsize, pgsize);
+ set_random_data(boundary + pgsize, pgsize);
+ if (memcmp(twopages, boundary, bufsize)) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ }
+ next = oldnext;
+ }
+ return err;
+}
+
+static int crosstest(void)
+{
+ size_t read = 0;
+ int err = 0, i;
+ loff_t addr, addr0, addrn;
+ unsigned char *pp1, *pp2, *pp3, *pp4;
+
+ printk(PRINT_PREF "crosstest\n");
+ pp1 = kmalloc(pgsize * 4, GFP_KERNEL);
+ if (!pp1) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ pp2 = pp1 + pgsize;
+ pp3 = pp2 + pgsize;
+ pp4 = pp3 + pgsize;
+ memset(pp1, 0, pgsize * 4);
+
+ addr0 = 0;
+ for (i = 0; bbt[i] && i < ebcnt; ++i)
+ addr0 += mtd->erasesize;
+
+ addrn = mtd->size;
+ for (i = 0; bbt[ebcnt - i - 1] && i < ebcnt; ++i)
+ addrn -= mtd->erasesize;
+
+ /* Read 2nd-to-last page to pp1 */
+ read = 0;
+ addr = addrn - pgsize - pgsize;
+ err = mtd->read(mtd, addr, pgsize, &read, pp1);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ kfree(pp1);
+ return err;
+ }
+
+ /* Read 3rd-to-last page to pp1 */
+ read = 0;
+ addr = addrn - pgsize - pgsize - pgsize;
+ err = mtd->read(mtd, addr, pgsize, &read, pp1);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ kfree(pp1);
+ return err;
+ }
+
+ /* Read first page to pp2 */
+ read = 0;
+ addr = addr0;
+ printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+ err = mtd->read(mtd, addr, pgsize, &read, pp2);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ kfree(pp1);
+ return err;
+ }
+
+ /* Read last page to pp3 */
+ read = 0;
+ addr = addrn - pgsize;
+ printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+ err = mtd->read(mtd, addr, pgsize, &read, pp3);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ kfree(pp1);
+ return err;
+ }
+
+ /* Read first page again to pp4 */
+ read = 0;
+ addr = addr0;
+ printk(PRINT_PREF "reading page at %#llx\n", (long long)addr);
+ err = mtd->read(mtd, addr, pgsize, &read, pp4);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ kfree(pp1);
+ return err;
+ }
+
+ /* pp2 and pp4 should be the same */
+ printk(PRINT_PREF "verifying pages read at %#llx match\n",
+ (long long)addr0);
+ if (memcmp(pp2, pp4, pgsize)) {
+ printk(PRINT_PREF "verify failed!\n");
+ errcnt += 1;
+ } else if (!err)
+ printk(PRINT_PREF "crosstest ok\n");
+ kfree(pp1);
+ return err;
+}
+
+static int erasecrosstest(void)
+{
+ size_t read = 0, written = 0;
+ int err = 0, i, ebnum, ok = 1, ebnum2;
+ loff_t addr0;
+ char *readbuf = twopages;
+
+ printk(PRINT_PREF "erasecrosstest\n");
+
+ ebnum = 0;
+ addr0 = 0;
+ for (i = 0; bbt[i] && i < ebcnt; ++i) {
+ addr0 += mtd->erasesize;
+ ebnum += 1;
+ }
+
+ ebnum2 = ebcnt - 1;
+ while (ebnum2 && bbt[ebnum2])
+ ebnum2 -= 1;
+
+ printk(PRINT_PREF "erasing block %d\n", ebnum);
+ err = erase_eraseblock(ebnum);
+ if (err)
+ return err;
+
+ printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
+ set_random_data(writebuf, pgsize);
+ strcpy(writebuf, "There is no data like this!");
+ err = mtd->write(mtd, addr0, pgsize, &written, writebuf);
+ if (err || written != pgsize) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ (long long)addr0);
+ return err ? err : -1;
+ }
+
+ printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+ memset(readbuf, 0, pgsize);
+ err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr0);
+ return err ? err : -1;
+ }
+
+ printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum);
+ if (memcmp(writebuf, readbuf, pgsize)) {
+ printk(PRINT_PREF "verify failed!\n");
+ errcnt += 1;
+ ok = 0;
+ return err;
+ }
+
+ printk(PRINT_PREF "erasing block %d\n", ebnum);
+ err = erase_eraseblock(ebnum);
+ if (err)
+ return err;
+
+ printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
+ set_random_data(writebuf, pgsize);
+ strcpy(writebuf, "There is no data like this!");
+ err = mtd->write(mtd, addr0, pgsize, &written, writebuf);
+ if (err || written != pgsize) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ (long long)addr0);
+ return err ? err : -1;
+ }
+
+ printk(PRINT_PREF "erasing block %d\n", ebnum2);
+ err = erase_eraseblock(ebnum2);
+ if (err)
+ return err;
+
+ printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+ memset(readbuf, 0, pgsize);
+ err = mtd->read(mtd, addr0, pgsize, &read, readbuf);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr0);
+ return err ? err : -1;
+ }
+
+ printk(PRINT_PREF "verifying 1st page of block %d\n", ebnum);
+ if (memcmp(writebuf, readbuf, pgsize)) {
+ printk(PRINT_PREF "verify failed!\n");
+ errcnt += 1;
+ ok = 0;
+ }
+
+ if (ok && !err)
+ printk(PRINT_PREF "erasecrosstest ok\n");
+ return err;
+}
+
+static int erasetest(void)
+{
+ size_t read = 0, written = 0;
+ int err = 0, i, ebnum, ok = 1;
+ loff_t addr0;
+
+ printk(PRINT_PREF "erasetest\n");
+
+ ebnum = 0;
+ addr0 = 0;
+ for (i = 0; bbt[i] && i < ebcnt; ++i) {
+ addr0 += mtd->erasesize;
+ ebnum += 1;
+ }
+
+ printk(PRINT_PREF "erasing block %d\n", ebnum);
+ err = erase_eraseblock(ebnum);
+ if (err)
+ return err;
+
+ printk(PRINT_PREF "writing 1st page of block %d\n", ebnum);
+ set_random_data(writebuf, pgsize);
+ err = mtd->write(mtd, addr0, pgsize, &written, writebuf);
+ if (err || written != pgsize) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ (long long)addr0);
+ return err ? err : -1;
+ }
+
+ printk(PRINT_PREF "erasing block %d\n", ebnum);
+ err = erase_eraseblock(ebnum);
+ if (err)
+ return err;
+
+ printk(PRINT_PREF "reading 1st page of block %d\n", ebnum);
+ err = mtd->read(mtd, addr0, pgsize, &read, twopages);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr0);
+ return err ? err : -1;
+ }
+
+ printk(PRINT_PREF "verifying 1st page of block %d is all 0xff\n",
+ ebnum);
+ for (i = 0; i < pgsize; ++i)
+ if (twopages[i] != 0xff) {
+ printk(PRINT_PREF "verifying all 0xff failed at %d\n",
+ i);
+ errcnt += 1;
+ ok = 0;
+ break;
+ }
+
+ if (ok && !err)
+ printk(PRINT_PREF "erasetest ok\n");
+
+ return err;
+}
+
+static int is_block_bad(int ebnum)
+{
+ loff_t addr = ebnum * mtd->erasesize;
+ int ret;
+
+ ret = mtd->block_isbad(mtd, addr);
+ if (ret)
+ printk(PRINT_PREF "block %d is bad\n", ebnum);
+ return ret;
+}
+
+static int scan_for_bad_eraseblocks(void)
+{
+ int i, bad = 0;
+
+ bbt = kmalloc(ebcnt, GFP_KERNEL);
+ if (!bbt) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(bbt, 0 , ebcnt);
+
+ printk(PRINT_PREF "scanning for bad eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ bbt[i] = is_block_bad(i) ? 1 : 0;
+ if (bbt[i])
+ bad += 1;
+ cond_resched();
+ }
+ printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+ return 0;
+}
+
+static int __init mtd_pagetest_init(void)
+{
+ int err = 0;
+ uint64_t tmp;
+ uint32_t i;
+
+ printk(KERN_INFO "\n");
+ printk(KERN_INFO "=================================================\n");
+ printk(PRINT_PREF "MTD device: %d\n", dev);
+
+ mtd = get_mtd_device(NULL, dev);
+ if (IS_ERR(mtd)) {
+ err = PTR_ERR(mtd);
+ printk(PRINT_PREF "error: cannot get MTD device\n");
+ return err;
+ }
+
+ if (mtd->type != MTD_NANDFLASH) {
+ printk(PRINT_PREF "this test requires NAND flash\n");
+ goto out;
+ }
+
+ tmp = mtd->size;
+ do_div(tmp, mtd->erasesize);
+ ebcnt = tmp;
+ pgcnt = mtd->erasesize / mtd->writesize;
+
+ printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+ "page size %u, count of eraseblocks %u, pages per "
+ "eraseblock %u, OOB size %u\n",
+ (unsigned long long)mtd->size, mtd->erasesize,
+ pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+ err = -ENOMEM;
+ bufsize = pgsize * 2;
+ writebuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!writebuf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+ twopages = kmalloc(bufsize, GFP_KERNEL);
+ if (!twopages) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+ boundary = kmalloc(bufsize, GFP_KERNEL);
+ if (!boundary) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+
+ err = scan_for_bad_eraseblocks();
+ if (err)
+ goto out;
+
+ /* Erase all eraseblocks */
+ printk(PRINT_PREF "erasing whole device\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = erase_eraseblock(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ printk(PRINT_PREF "erased %u eraseblocks\n", i);
+
+ /* Write all eraseblocks */
+ simple_srand(1);
+ printk(PRINT_PREF "writing whole device\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock(i);
+ if (err)
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "written up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "written %u eraseblocks\n", i);
+
+ /* Check all eraseblocks */
+ simple_srand(1);
+ printk(PRINT_PREF "verifying all eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = verify_eraseblock(i);
+ if (err)
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "verified %u eraseblocks\n", i);
+
+ err = crosstest();
+ if (err)
+ goto out;
+
+ err = erasecrosstest();
+ if (err)
+ goto out;
+
+ err = erasetest();
+ if (err)
+ goto out;
+
+ printk(PRINT_PREF "finished with %d errors\n", errcnt);
+out:
+
+ kfree(bbt);
+ kfree(boundary);
+ kfree(twopages);
+ kfree(writebuf);
+ put_mtd_device(mtd);
+ if (err)
+ printk(PRINT_PREF "error %d occurred\n", err);
+ printk(KERN_INFO "=================================================\n");
+ return err;
+}
+module_init(mtd_pagetest_init);
+
+static void __exit mtd_pagetest_exit(void)
+{
+ return;
+}
+module_exit(mtd_pagetest_exit);
+
+MODULE_DESCRIPTION("NAND page test");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c
new file mode 100644
index 000000000000..645e77fdc63d
--- /dev/null
+++ b/drivers/mtd/tests/mtd_readtest.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2006-2008 Nokia 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.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Check MTD device read.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+
+#define PRINT_PREF KERN_INFO "mtd_readtest: "
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *iobuf;
+static unsigned char *iobuf1;
+static unsigned char *bbt;
+
+static int pgsize;
+static int ebcnt;
+static int pgcnt;
+
+static int read_eraseblock_by_page(int ebnum)
+{
+ size_t read = 0;
+ int i, ret, err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ void *buf = iobuf;
+ void *oobbuf = iobuf1;
+
+ for (i = 0; i < pgcnt; i++) {
+ memset(buf, 0 , pgcnt);
+ ret = mtd->read(mtd, addr, pgsize, &read, buf);
+ if (ret == -EUCLEAN)
+ ret = 0;
+ if (ret || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ if (!err)
+ err = ret;
+ if (!err)
+ err = -EINVAL;
+ }
+ if (mtd->oobsize) {
+ struct mtd_oob_ops ops;
+
+ ops.mode = MTD_OOB_PLACE;
+ ops.len = 0;
+ ops.retlen = 0;
+ ops.ooblen = mtd->oobsize;
+ ops.oobretlen = 0;
+ ops.ooboffs = 0;
+ ops.datbuf = 0;
+ ops.oobbuf = oobbuf;
+ ret = mtd->read_oob(mtd, addr, &ops);
+ if (ret || ops.oobretlen != mtd->oobsize) {
+ printk(PRINT_PREF "error: read oob failed at "
+ "%#llx\n", (long long)addr);
+ if (!err)
+ err = ret;
+ if (!err)
+ err = -EINVAL;
+ }
+ oobbuf += mtd->oobsize;
+ }
+ addr += pgsize;
+ buf += pgsize;
+ }
+
+ return err;
+}
+
+static void dump_eraseblock(int ebnum)
+{
+ int i, j, n;
+ char line[128];
+ int pg, oob;
+
+ printk(PRINT_PREF "dumping eraseblock %d\n", ebnum);
+ n = mtd->erasesize;
+ for (i = 0; i < n;) {
+ char *p = line;
+
+ p += sprintf(p, "%05x: ", i);
+ for (j = 0; j < 32 && i < n; j++, i++)
+ p += sprintf(p, "%02x", (unsigned int)iobuf[i]);
+ printk(KERN_CRIT "%s\n", line);
+ cond_resched();
+ }
+ if (!mtd->oobsize)
+ return;
+ printk(PRINT_PREF "dumping oob from eraseblock %d\n", ebnum);
+ n = mtd->oobsize;
+ for (pg = 0, i = 0; pg < pgcnt; pg++)
+ for (oob = 0; oob < n;) {
+ char *p = line;
+
+ p += sprintf(p, "%05x: ", i);
+ for (j = 0; j < 32 && oob < n; j++, oob++, i++)
+ p += sprintf(p, "%02x",
+ (unsigned int)iobuf1[i]);
+ printk(KERN_CRIT "%s\n", line);
+ cond_resched();
+ }
+}
+
+static int is_block_bad(int ebnum)
+{
+ loff_t addr = ebnum * mtd->erasesize;
+ int ret;
+
+ ret = mtd->block_isbad(mtd, addr);
+ if (ret)
+ printk(PRINT_PREF "block %d is bad\n", ebnum);
+ return ret;
+}
+
+static int scan_for_bad_eraseblocks(void)
+{
+ int i, bad = 0;
+
+ bbt = kmalloc(ebcnt, GFP_KERNEL);
+ if (!bbt) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(bbt, 0 , ebcnt);
+
+ printk(PRINT_PREF "scanning for bad eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ bbt[i] = is_block_bad(i) ? 1 : 0;
+ if (bbt[i])
+ bad += 1;
+ cond_resched();
+ }
+ printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+ return 0;
+}
+
+static int __init mtd_readtest_init(void)
+{
+ uint64_t tmp;
+ int err, i;
+
+ printk(KERN_INFO "\n");
+ printk(KERN_INFO "=================================================\n");
+ printk(PRINT_PREF "MTD device: %d\n", dev);
+
+ mtd = get_mtd_device(NULL, dev);
+ if (IS_ERR(mtd)) {
+ err = PTR_ERR(mtd);
+ printk(PRINT_PREF "error: Cannot get MTD device\n");
+ return err;
+ }
+
+ if (mtd->writesize == 1) {
+ printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+ "bytes.\n");
+ pgsize = 512;
+ } else
+ pgsize = mtd->writesize;
+
+ tmp = mtd->size;
+ do_div(tmp, mtd->erasesize);
+ ebcnt = tmp;
+ pgcnt = mtd->erasesize / mtd->writesize;
+
+ printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+ "page size %u, count of eraseblocks %u, pages per "
+ "eraseblock %u, OOB size %u\n",
+ (unsigned long long)mtd->size, mtd->erasesize,
+ pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+ err = -ENOMEM;
+ iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!iobuf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+ iobuf1 = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!iobuf1) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+
+ err = scan_for_bad_eraseblocks();
+ if (err)
+ goto out;
+
+ /* Read all eraseblocks 1 page at a time */
+ printk(PRINT_PREF "testing page read\n");
+ for (i = 0; i < ebcnt; ++i) {
+ int ret;
+
+ if (bbt[i])
+ continue;
+ ret = read_eraseblock_by_page(i);
+ if (ret) {
+ dump_eraseblock(i);
+ if (!err)
+ err = ret;
+ }
+ cond_resched();
+ }
+
+ if (err)
+ printk(PRINT_PREF "finished with errors\n");
+ else
+ printk(PRINT_PREF "finished\n");
+
+out:
+
+ kfree(iobuf);
+ kfree(iobuf1);
+ kfree(bbt);
+ put_mtd_device(mtd);
+ if (err)
+ printk(PRINT_PREF "error %d occurred\n", err);
+ printk(KERN_INFO "=================================================\n");
+ return err;
+}
+module_init(mtd_readtest_init);
+
+static void __exit mtd_readtest_exit(void)
+{
+ return;
+}
+module_exit(mtd_readtest_exit);
+
+MODULE_DESCRIPTION("Read test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c
new file mode 100644
index 000000000000..141363a7e805
--- /dev/null
+++ b/drivers/mtd/tests/mtd_speedtest.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2007 Nokia 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.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test read and write speed of a MTD device.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+
+#define PRINT_PREF KERN_INFO "mtd_speedtest: "
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *iobuf;
+static unsigned char *bbt;
+
+static int pgsize;
+static int ebcnt;
+static int pgcnt;
+static int goodebcnt;
+static struct timeval start, finish;
+static unsigned long next = 1;
+
+static inline unsigned int simple_rand(void)
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned int)((next / 65536) % 32768);
+}
+
+static inline void simple_srand(unsigned long seed)
+{
+ next = seed;
+}
+
+static void set_random_data(unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ buf[i] = simple_rand();
+}
+
+static int erase_eraseblock(int ebnum)
+{
+ int err;
+ struct erase_info ei;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ memset(&ei, 0, sizeof(struct erase_info));
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = mtd->erasesize;
+
+ err = mtd->erase(mtd, &ei);
+ if (err) {
+ printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+ return err;
+ }
+
+ if (ei.state == MTD_ERASE_FAILED) {
+ printk(PRINT_PREF "some erase error occurred at EB %d\n",
+ ebnum);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int erase_whole_device(void)
+{
+ int err;
+ unsigned int i;
+
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = erase_eraseblock(i);
+ if (err)
+ return err;
+ cond_resched();
+ }
+ return 0;
+}
+
+static int write_eraseblock(int ebnum)
+{
+ size_t written = 0;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ err = mtd->write(mtd, addr, mtd->erasesize, &written, iobuf);
+ if (err || written != mtd->erasesize) {
+ printk(PRINT_PREF "error: write failed at %#llx\n", addr);
+ if (!err)
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int write_eraseblock_by_page(int ebnum)
+{
+ size_t written = 0;
+ int i, err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ void *buf = iobuf;
+
+ for (i = 0; i < pgcnt; i++) {
+ err = mtd->write(mtd, addr, pgsize, &written, buf);
+ if (err || written != pgsize) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ addr);
+ if (!err)
+ err = -EINVAL;
+ break;
+ }
+ addr += pgsize;
+ buf += pgsize;
+ }
+
+ return err;
+}
+
+static int write_eraseblock_by_2pages(int ebnum)
+{
+ size_t written = 0, sz = pgsize * 2;
+ int i, n = pgcnt / 2, err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ void *buf = iobuf;
+
+ for (i = 0; i < n; i++) {
+ err = mtd->write(mtd, addr, sz, &written, buf);
+ if (err || written != sz) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ addr);
+ if (!err)
+ err = -EINVAL;
+ return err;
+ }
+ addr += sz;
+ buf += sz;
+ }
+ if (pgcnt % 2) {
+ err = mtd->write(mtd, addr, pgsize, &written, buf);
+ if (err || written != pgsize) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ addr);
+ if (!err)
+ err = -EINVAL;
+ }
+ }
+
+ return err;
+}
+
+static int read_eraseblock(int ebnum)
+{
+ size_t read = 0;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ err = mtd->read(mtd, addr, mtd->erasesize, &read, iobuf);
+ /* Ignore corrected ECC errors */
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != mtd->erasesize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n", addr);
+ if (!err)
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int read_eraseblock_by_page(int ebnum)
+{
+ size_t read = 0;
+ int i, err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ void *buf = iobuf;
+
+ for (i = 0; i < pgcnt; i++) {
+ err = mtd->read(mtd, addr, pgsize, &read, buf);
+ /* Ignore corrected ECC errors */
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ addr);
+ if (!err)
+ err = -EINVAL;
+ break;
+ }
+ addr += pgsize;
+ buf += pgsize;
+ }
+
+ return err;
+}
+
+static int read_eraseblock_by_2pages(int ebnum)
+{
+ size_t read = 0, sz = pgsize * 2;
+ int i, n = pgcnt / 2, err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ void *buf = iobuf;
+
+ for (i = 0; i < n; i++) {
+ err = mtd->read(mtd, addr, sz, &read, buf);
+ /* Ignore corrected ECC errors */
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != sz) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ addr);
+ if (!err)
+ err = -EINVAL;
+ return err;
+ }
+ addr += sz;
+ buf += sz;
+ }
+ if (pgcnt % 2) {
+ err = mtd->read(mtd, addr, pgsize, &read, buf);
+ /* Ignore corrected ECC errors */
+ if (err == -EUCLEAN)
+ err = 0;
+ if (err || read != pgsize) {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ addr);
+ if (!err)
+ err = -EINVAL;
+ }
+ }
+
+ return err;
+}
+
+static int is_block_bad(int ebnum)
+{
+ loff_t addr = ebnum * mtd->erasesize;
+ int ret;
+
+ ret = mtd->block_isbad(mtd, addr);
+ if (ret)
+ printk(PRINT_PREF "block %d is bad\n", ebnum);
+ return ret;
+}
+
+static inline void start_timing(void)
+{
+ do_gettimeofday(&start);
+}
+
+static inline void stop_timing(void)
+{
+ do_gettimeofday(&finish);
+}
+
+static long calc_speed(void)
+{
+ long ms, k, speed;
+
+ ms = (finish.tv_sec - start.tv_sec) * 1000 +
+ (finish.tv_usec - start.tv_usec) / 1000;
+ k = goodebcnt * mtd->erasesize / 1024;
+ speed = (k * 1000) / ms;
+ return speed;
+}
+
+static int scan_for_bad_eraseblocks(void)
+{
+ int i, bad = 0;
+
+ bbt = kmalloc(ebcnt, GFP_KERNEL);
+ if (!bbt) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(bbt, 0 , ebcnt);
+
+ printk(PRINT_PREF "scanning for bad eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ bbt[i] = is_block_bad(i) ? 1 : 0;
+ if (bbt[i])
+ bad += 1;
+ cond_resched();
+ }
+ printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+ goodebcnt = ebcnt - bad;
+ return 0;
+}
+
+static int __init mtd_speedtest_init(void)
+{
+ int err, i;
+ long speed;
+ uint64_t tmp;
+
+ printk(KERN_INFO "\n");
+ printk(KERN_INFO "=================================================\n");
+ printk(PRINT_PREF "MTD device: %d\n", dev);
+
+ mtd = get_mtd_device(NULL, dev);
+ if (IS_ERR(mtd)) {
+ err = PTR_ERR(mtd);
+ printk(PRINT_PREF "error: cannot get MTD device\n");
+ return err;
+ }
+
+ if (mtd->writesize == 1) {
+ printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+ "bytes.\n");
+ pgsize = 512;
+ } else
+ pgsize = mtd->writesize;
+
+ tmp = mtd->size;
+ do_div(tmp, mtd->erasesize);
+ ebcnt = tmp;
+ pgcnt = mtd->erasesize / mtd->writesize;
+
+ printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+ "page size %u, count of eraseblocks %u, pages per "
+ "eraseblock %u, OOB size %u\n",
+ (unsigned long long)mtd->size, mtd->erasesize,
+ pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+ err = -ENOMEM;
+ iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!iobuf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+
+ simple_srand(1);
+ set_random_data(iobuf, mtd->erasesize);
+
+ err = scan_for_bad_eraseblocks();
+ if (err)
+ goto out;
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ /* Write all eraseblocks, 1 eraseblock at a time */
+ printk(PRINT_PREF "testing eraseblock write speed\n");
+ start_timing();
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ stop_timing();
+ speed = calc_speed();
+ printk(PRINT_PREF "eraseblock write speed is %ld KiB/s\n", speed);
+
+ /* Read all eraseblocks, 1 eraseblock at a time */
+ printk(PRINT_PREF "testing eraseblock read speed\n");
+ start_timing();
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = read_eraseblock(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ stop_timing();
+ speed = calc_speed();
+ printk(PRINT_PREF "eraseblock read speed is %ld KiB/s\n", speed);
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ /* Write all eraseblocks, 1 page at a time */
+ printk(PRINT_PREF "testing page write speed\n");
+ start_timing();
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock_by_page(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ stop_timing();
+ speed = calc_speed();
+ printk(PRINT_PREF "page write speed is %ld KiB/s\n", speed);
+
+ /* Read all eraseblocks, 1 page at a time */
+ printk(PRINT_PREF "testing page read speed\n");
+ start_timing();
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = read_eraseblock_by_page(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ stop_timing();
+ speed = calc_speed();
+ printk(PRINT_PREF "page read speed is %ld KiB/s\n", speed);
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ /* Write all eraseblocks, 2 pages at a time */
+ printk(PRINT_PREF "testing 2 page write speed\n");
+ start_timing();
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock_by_2pages(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ stop_timing();
+ speed = calc_speed();
+ printk(PRINT_PREF "2 page write speed is %ld KiB/s\n", speed);
+
+ /* Read all eraseblocks, 2 pages at a time */
+ printk(PRINT_PREF "testing 2 page read speed\n");
+ start_timing();
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = read_eraseblock_by_2pages(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ stop_timing();
+ speed = calc_speed();
+ printk(PRINT_PREF "2 page read speed is %ld KiB/s\n", speed);
+
+ /* Erase all eraseblocks */
+ printk(PRINT_PREF "Testing erase speed\n");
+ start_timing();
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = erase_eraseblock(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ stop_timing();
+ speed = calc_speed();
+ printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed);
+
+ printk(PRINT_PREF "finished\n");
+out:
+ kfree(iobuf);
+ kfree(bbt);
+ put_mtd_device(mtd);
+ if (err)
+ printk(PRINT_PREF "error %d occurred\n", err);
+ printk(KERN_INFO "=================================================\n");
+ return err;
+}
+module_init(mtd_speedtest_init);
+
+static void __exit mtd_speedtest_exit(void)
+{
+ return;
+}
+module_exit(mtd_speedtest_exit);
+
+MODULE_DESCRIPTION("Speed test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c
new file mode 100644
index 000000000000..63920476b57a
--- /dev/null
+++ b/drivers/mtd/tests/mtd_stresstest.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2006-2008 Nokia 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.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test random reads, writes and erases on MTD device.
+ *
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+
+#define PRINT_PREF KERN_INFO "mtd_stresstest: "
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static int count = 10000;
+module_param(count, int, S_IRUGO);
+MODULE_PARM_DESC(count, "Number of operations to do (default is 10000)");
+
+static struct mtd_info *mtd;
+static unsigned char *writebuf;
+static unsigned char *readbuf;
+static unsigned char *bbt;
+static int *offsets;
+
+static int pgsize;
+static int bufsize;
+static int ebcnt;
+static int pgcnt;
+static unsigned long next = 1;
+
+static inline unsigned int simple_rand(void)
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned int)((next / 65536) % 32768);
+}
+
+static inline void simple_srand(unsigned long seed)
+{
+ next = seed;
+}
+
+static int rand_eb(void)
+{
+ int eb;
+
+again:
+ if (ebcnt < 32768)
+ eb = simple_rand();
+ else
+ eb = (simple_rand() << 15) | simple_rand();
+ /* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */
+ eb %= (ebcnt - 1);
+ if (bbt[eb])
+ goto again;
+ return eb;
+}
+
+static int rand_offs(void)
+{
+ int offs;
+
+ if (bufsize < 32768)
+ offs = simple_rand();
+ else
+ offs = (simple_rand() << 15) | simple_rand();
+ offs %= bufsize;
+ return offs;
+}
+
+static int rand_len(int offs)
+{
+ int len;
+
+ if (bufsize < 32768)
+ len = simple_rand();
+ else
+ len = (simple_rand() << 15) | simple_rand();
+ len %= (bufsize - offs);
+ return len;
+}
+
+static int erase_eraseblock(int ebnum)
+{
+ int err;
+ struct erase_info ei;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ memset(&ei, 0, sizeof(struct erase_info));
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = mtd->erasesize;
+
+ err = mtd->erase(mtd, &ei);
+ if (unlikely(err)) {
+ printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+ return err;
+ }
+
+ if (unlikely(ei.state == MTD_ERASE_FAILED)) {
+ printk(PRINT_PREF "some erase error occurred at EB %d\n",
+ ebnum);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int is_block_bad(int ebnum)
+{
+ loff_t addr = ebnum * mtd->erasesize;
+ int ret;
+
+ ret = mtd->block_isbad(mtd, addr);
+ if (ret)
+ printk(PRINT_PREF "block %d is bad\n", ebnum);
+ return ret;
+}
+
+static int do_read(void)
+{
+ size_t read = 0;
+ int eb = rand_eb();
+ int offs = rand_offs();
+ int len = rand_len(offs), err;
+ loff_t addr;
+
+ if (bbt[eb + 1]) {
+ if (offs >= mtd->erasesize)
+ offs -= mtd->erasesize;
+ if (offs + len > mtd->erasesize)
+ len = mtd->erasesize - offs;
+ }
+ addr = eb * mtd->erasesize + offs;
+ err = mtd->read(mtd, addr, len, &read, readbuf);
+ if (err == -EUCLEAN)
+ err = 0;
+ if (unlikely(err || read != len)) {
+ printk(PRINT_PREF "error: read failed at 0x%llx\n",
+ (long long)addr);
+ if (!err)
+ err = -EINVAL;
+ return err;
+ }
+ return 0;
+}
+
+static int do_write(void)
+{
+ int eb = rand_eb(), offs, err, len;
+ size_t written = 0;
+ loff_t addr;
+
+ offs = offsets[eb];
+ if (offs >= mtd->erasesize) {
+ err = erase_eraseblock(eb);
+ if (err)
+ return err;
+ offs = offsets[eb] = 0;
+ }
+ len = rand_len(offs);
+ len = ((len + pgsize - 1) / pgsize) * pgsize;
+ if (offs + len > mtd->erasesize) {
+ if (bbt[eb + 1])
+ len = mtd->erasesize - offs;
+ else {
+ err = erase_eraseblock(eb + 1);
+ if (err)
+ return err;
+ offsets[eb + 1] = 0;
+ }
+ }
+ addr = eb * mtd->erasesize + offs;
+ err = mtd->write(mtd, addr, len, &written, writebuf);
+ if (unlikely(err || written != len)) {
+ printk(PRINT_PREF "error: write failed at 0x%llx\n",
+ (long long)addr);
+ if (!err)
+ err = -EINVAL;
+ return err;
+ }
+ offs += len;
+ while (offs > mtd->erasesize) {
+ offsets[eb++] = mtd->erasesize;
+ offs -= mtd->erasesize;
+ }
+ offsets[eb] = offs;
+ return 0;
+}
+
+static int do_operation(void)
+{
+ if (simple_rand() & 1)
+ return do_read();
+ else
+ return do_write();
+}
+
+static int scan_for_bad_eraseblocks(void)
+{
+ int i, bad = 0;
+
+ bbt = kmalloc(ebcnt, GFP_KERNEL);
+ if (!bbt) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(bbt, 0 , ebcnt);
+
+ printk(PRINT_PREF "scanning for bad eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ bbt[i] = is_block_bad(i) ? 1 : 0;
+ if (bbt[i])
+ bad += 1;
+ cond_resched();
+ }
+ printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+ return 0;
+}
+
+static int __init mtd_stresstest_init(void)
+{
+ int err;
+ int i, op;
+ uint64_t tmp;
+
+ printk(KERN_INFO "\n");
+ printk(KERN_INFO "=================================================\n");
+ printk(PRINT_PREF "MTD device: %d\n", dev);
+
+ mtd = get_mtd_device(NULL, dev);
+ if (IS_ERR(mtd)) {
+ err = PTR_ERR(mtd);
+ printk(PRINT_PREF "error: cannot get MTD device\n");
+ return err;
+ }
+
+ if (mtd->writesize == 1) {
+ printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+ "bytes.\n");
+ pgsize = 512;
+ } else
+ pgsize = mtd->writesize;
+
+ tmp = mtd->size;
+ do_div(tmp, mtd->erasesize);
+ ebcnt = tmp;
+ pgcnt = mtd->erasesize / mtd->writesize;
+
+ printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+ "page size %u, count of eraseblocks %u, pages per "
+ "eraseblock %u, OOB size %u\n",
+ (unsigned long long)mtd->size, mtd->erasesize,
+ pgsize, ebcnt, pgcnt, mtd->oobsize);
+
+ /* Read or write up 2 eraseblocks at a time */
+ bufsize = mtd->erasesize * 2;
+
+ err = -ENOMEM;
+ readbuf = vmalloc(bufsize);
+ writebuf = vmalloc(bufsize);
+ offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL);
+ if (!readbuf || !writebuf || !offsets) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+ for (i = 0; i < ebcnt; i++)
+ offsets[i] = mtd->erasesize;
+ simple_srand(current->pid);
+ for (i = 0; i < bufsize; i++)
+ writebuf[i] = simple_rand();
+
+ err = scan_for_bad_eraseblocks();
+ if (err)
+ goto out;
+
+ /* Do operations */
+ printk(PRINT_PREF "doing operations\n");
+ for (op = 0; op < count; op++) {
+ if ((op & 1023) == 0)
+ printk(PRINT_PREF "%d operations done\n", op);
+ err = do_operation();
+ if (err)
+ goto out;
+ cond_resched();
+ }
+ printk(PRINT_PREF "finished, %d operations done\n", op);
+
+out:
+ kfree(offsets);
+ kfree(bbt);
+ vfree(writebuf);
+ vfree(readbuf);
+ put_mtd_device(mtd);
+ if (err)
+ printk(PRINT_PREF "error %d occurred\n", err);
+ printk(KERN_INFO "=================================================\n");
+ return err;
+}
+module_init(mtd_stresstest_init);
+
+static void __exit mtd_stresstest_exit(void)
+{
+ return;
+}
+module_exit(mtd_stresstest_exit);
+
+MODULE_DESCRIPTION("Stress test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c
new file mode 100644
index 000000000000..5b889724268e
--- /dev/null
+++ b/drivers/mtd/tests/mtd_subpagetest.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2006-2007 Nokia 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.
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Test sub-page read and write on MTD device.
+ * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+
+#define PRINT_PREF KERN_INFO "mtd_subpagetest: "
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static struct mtd_info *mtd;
+static unsigned char *writebuf;
+static unsigned char *readbuf;
+static unsigned char *bbt;
+
+static int subpgsize;
+static int bufsize;
+static int ebcnt;
+static int pgcnt;
+static int errcnt;
+static unsigned long next = 1;
+
+static inline unsigned int simple_rand(void)
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned int)((next / 65536) % 32768);
+}
+
+static inline void simple_srand(unsigned long seed)
+{
+ next = seed;
+}
+
+static void set_random_data(unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; ++i)
+ buf[i] = simple_rand();
+}
+
+static inline void clear_data(unsigned char *buf, size_t len)
+{
+ memset(buf, 0, len);
+}
+
+static int erase_eraseblock(int ebnum)
+{
+ int err;
+ struct erase_info ei;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ memset(&ei, 0, sizeof(struct erase_info));
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = mtd->erasesize;
+
+ err = mtd->erase(mtd, &ei);
+ if (err) {
+ printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+ return err;
+ }
+
+ if (ei.state == MTD_ERASE_FAILED) {
+ printk(PRINT_PREF "some erase error occurred at EB %d\n",
+ ebnum);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int erase_whole_device(void)
+{
+ int err;
+ unsigned int i;
+
+ printk(PRINT_PREF "erasing whole device\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = erase_eraseblock(i);
+ if (err)
+ return err;
+ cond_resched();
+ }
+ printk(PRINT_PREF "erased %u eraseblocks\n", i);
+ return 0;
+}
+
+static int write_eraseblock(int ebnum)
+{
+ size_t written = 0;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ set_random_data(writebuf, subpgsize);
+ err = mtd->write(mtd, addr, subpgsize, &written, writebuf);
+ if (unlikely(err || written != subpgsize)) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ (long long)addr);
+ if (written != subpgsize) {
+ printk(PRINT_PREF " write size: %#x\n", subpgsize);
+ printk(PRINT_PREF " written: %#zx\n", written);
+ }
+ return err ? err : -1;
+ }
+
+ addr += subpgsize;
+
+ set_random_data(writebuf, subpgsize);
+ err = mtd->write(mtd, addr, subpgsize, &written, writebuf);
+ if (unlikely(err || written != subpgsize)) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ (long long)addr);
+ if (written != subpgsize) {
+ printk(PRINT_PREF " write size: %#x\n", subpgsize);
+ printk(PRINT_PREF " written: %#zx\n", written);
+ }
+ return err ? err : -1;
+ }
+
+ return err;
+}
+
+static int write_eraseblock2(int ebnum)
+{
+ size_t written = 0;
+ int err = 0, k;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ for (k = 1; k < 33; ++k) {
+ if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
+ break;
+ set_random_data(writebuf, subpgsize * k);
+ err = mtd->write(mtd, addr, subpgsize * k, &written, writebuf);
+ if (unlikely(err || written != subpgsize * k)) {
+ printk(PRINT_PREF "error: write failed at %#llx\n",
+ (long long)addr);
+ if (written != subpgsize) {
+ printk(PRINT_PREF " write size: %#x\n",
+ subpgsize * k);
+ printk(PRINT_PREF " written: %#08zx\n",
+ written);
+ }
+ return err ? err : -1;
+ }
+ addr += subpgsize * k;
+ }
+
+ return err;
+}
+
+static void print_subpage(unsigned char *p)
+{
+ int i, j;
+
+ for (i = 0; i < subpgsize; ) {
+ for (j = 0; i < subpgsize && j < 32; ++i, ++j)
+ printk("%02x", *p++);
+ printk("\n");
+ }
+}
+
+static int verify_eraseblock(int ebnum)
+{
+ size_t read = 0;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ set_random_data(writebuf, subpgsize);
+ clear_data(readbuf, subpgsize);
+ read = 0;
+ err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
+ if (unlikely(err || read != subpgsize)) {
+ if (err == -EUCLEAN && read == subpgsize) {
+ printk(PRINT_PREF "ECC correction at %#llx\n",
+ (long long)addr);
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ return err ? err : -1;
+ }
+ }
+ if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ printk(PRINT_PREF "------------- written----------------\n");
+ print_subpage(writebuf);
+ printk(PRINT_PREF "------------- read ------------------\n");
+ print_subpage(readbuf);
+ printk(PRINT_PREF "-------------------------------------\n");
+ errcnt += 1;
+ }
+
+ addr += subpgsize;
+
+ set_random_data(writebuf, subpgsize);
+ clear_data(readbuf, subpgsize);
+ read = 0;
+ err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
+ if (unlikely(err || read != subpgsize)) {
+ if (err == -EUCLEAN && read == subpgsize) {
+ printk(PRINT_PREF "ECC correction at %#llx\n",
+ (long long)addr);
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: read failed at %#llx\n",
+ (long long)addr);
+ return err ? err : -1;
+ }
+ }
+ if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ printk(PRINT_PREF "------------- written----------------\n");
+ print_subpage(writebuf);
+ printk(PRINT_PREF "------------- read ------------------\n");
+ print_subpage(readbuf);
+ printk(PRINT_PREF "-------------------------------------\n");
+ errcnt += 1;
+ }
+
+ return err;
+}
+
+static int verify_eraseblock2(int ebnum)
+{
+ size_t read = 0;
+ int err = 0, k;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ for (k = 1; k < 33; ++k) {
+ if (addr + (subpgsize * k) > (ebnum + 1) * mtd->erasesize)
+ break;
+ set_random_data(writebuf, subpgsize * k);
+ clear_data(readbuf, subpgsize * k);
+ read = 0;
+ err = mtd->read(mtd, addr, subpgsize * k, &read, readbuf);
+ if (unlikely(err || read != subpgsize * k)) {
+ if (err == -EUCLEAN && read == subpgsize * k) {
+ printk(PRINT_PREF "ECC correction at %#llx\n",
+ (long long)addr);
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: read failed at "
+ "%#llx\n", (long long)addr);
+ return err ? err : -1;
+ }
+ }
+ if (unlikely(memcmp(readbuf, writebuf, subpgsize * k))) {
+ printk(PRINT_PREF "error: verify failed at %#llx\n",
+ (long long)addr);
+ errcnt += 1;
+ }
+ addr += subpgsize * k;
+ }
+
+ return err;
+}
+
+static int verify_eraseblock_ff(int ebnum)
+{
+ uint32_t j;
+ size_t read = 0;
+ int err = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ memset(writebuf, 0xff, subpgsize);
+ for (j = 0; j < mtd->erasesize / subpgsize; ++j) {
+ clear_data(readbuf, subpgsize);
+ read = 0;
+ err = mtd->read(mtd, addr, subpgsize, &read, readbuf);
+ if (unlikely(err || read != subpgsize)) {
+ if (err == -EUCLEAN && read == subpgsize) {
+ printk(PRINT_PREF "ECC correction at %#llx\n",
+ (long long)addr);
+ err = 0;
+ } else {
+ printk(PRINT_PREF "error: read failed at "
+ "%#llx\n", (long long)addr);
+ return err ? err : -1;
+ }
+ }
+ if (unlikely(memcmp(readbuf, writebuf, subpgsize))) {
+ printk(PRINT_PREF "error: verify 0xff failed at "
+ "%#llx\n", (long long)addr);
+ errcnt += 1;
+ }
+ addr += subpgsize;
+ }
+
+ return err;
+}
+
+static int verify_all_eraseblocks_ff(void)
+{
+ int err;
+ unsigned int i;
+
+ printk(PRINT_PREF "verifying all eraseblocks for 0xff\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = verify_eraseblock_ff(i);
+ if (err)
+ return err;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "verified %u eraseblocks\n", i);
+ return 0;
+}
+
+static int is_block_bad(int ebnum)
+{
+ loff_t addr = ebnum * mtd->erasesize;
+ int ret;
+
+ ret = mtd->block_isbad(mtd, addr);
+ if (ret)
+ printk(PRINT_PREF "block %d is bad\n", ebnum);
+ return ret;
+}
+
+static int scan_for_bad_eraseblocks(void)
+{
+ int i, bad = 0;
+
+ bbt = kmalloc(ebcnt, GFP_KERNEL);
+ if (!bbt) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(bbt, 0 , ebcnt);
+
+ printk(PRINT_PREF "scanning for bad eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ bbt[i] = is_block_bad(i) ? 1 : 0;
+ if (bbt[i])
+ bad += 1;
+ cond_resched();
+ }
+ printk(PRINT_PREF "scanned %d eraseblocks, %d are bad\n", i, bad);
+ return 0;
+}
+
+static int __init mtd_subpagetest_init(void)
+{
+ int err = 0;
+ uint32_t i;
+ uint64_t tmp;
+
+ printk(KERN_INFO "\n");
+ printk(KERN_INFO "=================================================\n");
+ printk(PRINT_PREF "MTD device: %d\n", dev);
+
+ mtd = get_mtd_device(NULL, dev);
+ if (IS_ERR(mtd)) {
+ err = PTR_ERR(mtd);
+ printk(PRINT_PREF "error: cannot get MTD device\n");
+ return err;
+ }
+
+ if (mtd->type != MTD_NANDFLASH) {
+ printk(PRINT_PREF "this test requires NAND flash\n");
+ goto out;
+ }
+
+ subpgsize = mtd->writesize >> mtd->subpage_sft;
+ printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
+ "page size %u, subpage size %u, count of eraseblocks %u, "
+ "pages per eraseblock %u, OOB size %u\n",
+ (unsigned long long)mtd->size, mtd->erasesize,
+ mtd->writesize, subpgsize, ebcnt, pgcnt, mtd->oobsize);
+
+ err = -ENOMEM;
+ bufsize = subpgsize * 32;
+ writebuf = kmalloc(bufsize, GFP_KERNEL);
+ if (!writebuf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+ readbuf = kmalloc(bufsize, GFP_KERNEL);
+ if (!readbuf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out;
+ }
+
+ tmp = mtd->size;
+ do_div(tmp, mtd->erasesize);
+ ebcnt = tmp;
+ pgcnt = mtd->erasesize / mtd->writesize;
+
+ err = scan_for_bad_eraseblocks();
+ if (err)
+ goto out;
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ printk(PRINT_PREF "writing whole device\n");
+ simple_srand(1);
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock(i);
+ if (unlikely(err))
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "written up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "written %u eraseblocks\n", i);
+
+ simple_srand(1);
+ printk(PRINT_PREF "verifying all eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = verify_eraseblock(i);
+ if (unlikely(err))
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "verified %u eraseblocks\n", i);
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ err = verify_all_eraseblocks_ff();
+ if (err)
+ goto out;
+
+ /* Write all eraseblocks */
+ simple_srand(3);
+ printk(PRINT_PREF "writing whole device\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = write_eraseblock2(i);
+ if (unlikely(err))
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "written up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "written %u eraseblocks\n", i);
+
+ /* Check all eraseblocks */
+ simple_srand(3);
+ printk(PRINT_PREF "verifying all eraseblocks\n");
+ for (i = 0; i < ebcnt; ++i) {
+ if (bbt[i])
+ continue;
+ err = verify_eraseblock2(i);
+ if (unlikely(err))
+ goto out;
+ if (i % 256 == 0)
+ printk(PRINT_PREF "verified up to eraseblock %u\n", i);
+ cond_resched();
+ }
+ printk(PRINT_PREF "verified %u eraseblocks\n", i);
+
+ err = erase_whole_device();
+ if (err)
+ goto out;
+
+ err = verify_all_eraseblocks_ff();
+ if (err)
+ goto out;
+
+ printk(PRINT_PREF "finished with %d errors\n", errcnt);
+
+out:
+ kfree(bbt);
+ kfree(readbuf);
+ kfree(writebuf);
+ put_mtd_device(mtd);
+ if (err)
+ printk(PRINT_PREF "error %d occurred\n", err);
+ printk(KERN_INFO "=================================================\n");
+ return err;
+}
+module_init(mtd_subpagetest_init);
+
+static void __exit mtd_subpagetest_exit(void)
+{
+ return;
+}
+module_exit(mtd_subpagetest_exit);
+
+MODULE_DESCRIPTION("Subpage test module");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/tests/mtd_torturetest.c b/drivers/mtd/tests/mtd_torturetest.c
new file mode 100644
index 000000000000..631a0ab3a33c
--- /dev/null
+++ b/drivers/mtd/tests/mtd_torturetest.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2006-2008 Artem Bityutskiy
+ * Copyright (C) 2006-2008 Jarkko Lavinen
+ * Copyright (C) 2006-2008 Adrian Hunter
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Artem Bityutskiy, Jarkko Lavinen, Adria Hunter
+ *
+ * WARNING: this test program may kill your flash and your device. Do not
+ * use it unless you know what you do. Authors are not responsible for any
+ * damage caused by this program.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/mtd/mtd.h>
+#include <linux/sched.h>
+
+#define PRINT_PREF KERN_INFO "mtd_torturetest: "
+#define RETRIES 3
+
+static int eb = 8;
+module_param(eb, int, S_IRUGO);
+MODULE_PARM_DESC(eb, "eraseblock number within the selected MTD device");
+
+static int ebcnt = 32;
+module_param(ebcnt, int, S_IRUGO);
+MODULE_PARM_DESC(ebcnt, "number of consecutive eraseblocks to torture");
+
+static int pgcnt;
+module_param(pgcnt, int, S_IRUGO);
+MODULE_PARM_DESC(pgcnt, "number of pages per eraseblock to torture (0 => all)");
+
+static int dev;
+module_param(dev, int, S_IRUGO);
+MODULE_PARM_DESC(dev, "MTD device number to use");
+
+static int gran = 512;
+module_param(gran, int, S_IRUGO);
+MODULE_PARM_DESC(gran, "how often the status information should be printed");
+
+static int check = 1;
+module_param(check, int, S_IRUGO);
+MODULE_PARM_DESC(check, "if the written data should be checked");
+
+static unsigned int cycles_count;
+module_param(cycles_count, uint, S_IRUGO);
+MODULE_PARM_DESC(cycles_count, "how many erase cycles to do "
+ "(infinite by default)");
+
+static struct mtd_info *mtd;
+
+/* This buffer contains 0x555555...0xAAAAAA... pattern */
+static unsigned char *patt_5A5;
+/* This buffer contains 0xAAAAAA...0x555555... pattern */
+static unsigned char *patt_A5A;
+/* This buffer contains all 0xFF bytes */
+static unsigned char *patt_FF;
+/* This a temporary buffer is use when checking data */
+static unsigned char *check_buf;
+/* How many erase cycles were done */
+static unsigned int erase_cycles;
+
+static int pgsize;
+static struct timeval start, finish;
+
+static void report_corrupt(unsigned char *read, unsigned char *written);
+
+static inline void start_timing(void)
+{
+ do_gettimeofday(&start);
+}
+
+static inline void stop_timing(void)
+{
+ do_gettimeofday(&finish);
+}
+
+/*
+ * Erase eraseblock number @ebnum.
+ */
+static inline int erase_eraseblock(int ebnum)
+{
+ int err;
+ struct erase_info ei;
+ loff_t addr = ebnum * mtd->erasesize;
+
+ memset(&ei, 0, sizeof(struct erase_info));
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = mtd->erasesize;
+
+ err = mtd->erase(mtd, &ei);
+ if (err) {
+ printk(PRINT_PREF "error %d while erasing EB %d\n", err, ebnum);
+ return err;
+ }
+
+ if (ei.state == MTD_ERASE_FAILED) {
+ printk(PRINT_PREF "some erase error occurred at EB %d\n",
+ ebnum);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/*
+ * Check that the contents of eraseblock number @enbum is equivalent to the
+ * @buf buffer.
+ */
+static inline int check_eraseblock(int ebnum, unsigned char *buf)
+{
+ int err, retries = 0;
+ size_t read = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ size_t len = mtd->erasesize;
+
+ if (pgcnt) {
+ addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
+ len = pgcnt * pgsize;
+ }
+
+retry:
+ err = mtd->read(mtd, addr, len, &read, check_buf);
+ if (err == -EUCLEAN)
+ printk(PRINT_PREF "single bit flip occurred at EB %d "
+ "MTD reported that it was fixed.\n", ebnum);
+ else if (err) {
+ printk(PRINT_PREF "error %d while reading EB %d, "
+ "read %zd\n", err, ebnum, read);
+ return err;
+ }
+
+ if (read != len) {
+ printk(PRINT_PREF "failed to read %zd bytes from EB %d, "
+ "read only %zd, but no error reported\n",
+ len, ebnum, read);
+ return -EIO;
+ }
+
+ if (memcmp(buf, check_buf, len)) {
+ printk(PRINT_PREF "read wrong data from EB %d\n", ebnum);
+ report_corrupt(check_buf, buf);
+
+ if (retries++ < RETRIES) {
+ /* Try read again */
+ yield();
+ printk(PRINT_PREF "re-try reading data from EB %d\n",
+ ebnum);
+ goto retry;
+ } else {
+ printk(PRINT_PREF "retried %d times, still errors, "
+ "give-up\n", RETRIES);
+ return -EINVAL;
+ }
+ }
+
+ if (retries != 0)
+ printk(PRINT_PREF "only attempt number %d was OK (!!!)\n",
+ retries);
+
+ return 0;
+}
+
+static inline int write_pattern(int ebnum, void *buf)
+{
+ int err;
+ size_t written = 0;
+ loff_t addr = ebnum * mtd->erasesize;
+ size_t len = mtd->erasesize;
+
+ if (pgcnt) {
+ addr = (ebnum + 1) * mtd->erasesize - pgcnt * pgsize;
+ len = pgcnt * pgsize;
+ }
+ err = mtd->write(mtd, addr, len, &written, buf);
+ if (err) {
+ printk(PRINT_PREF "error %d while writing EB %d, written %zd"
+ " bytes\n", err, ebnum, written);
+ return err;
+ }
+ if (written != len) {
+ printk(PRINT_PREF "written only %zd bytes of %zd, but no error"
+ " reported\n", written, len);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int __init tort_init(void)
+{
+ int err = 0, i, infinite = !cycles_count;
+ int bad_ebs[ebcnt];
+
+ printk(KERN_INFO "\n");
+ printk(KERN_INFO "=================================================\n");
+ printk(PRINT_PREF "Warning: this program is trying to wear out your "
+ "flash, stop it if this is not wanted.\n");
+ printk(PRINT_PREF "MTD device: %d\n", dev);
+ printk(PRINT_PREF "torture %d eraseblocks (%d-%d) of mtd%d\n",
+ ebcnt, eb, eb + ebcnt - 1, dev);
+ if (pgcnt)
+ printk(PRINT_PREF "torturing just %d pages per eraseblock\n",
+ pgcnt);
+ printk(PRINT_PREF "write verify %s\n", check ? "enabled" : "disabled");
+
+ mtd = get_mtd_device(NULL, dev);
+ if (IS_ERR(mtd)) {
+ err = PTR_ERR(mtd);
+ printk(PRINT_PREF "error: cannot get MTD device\n");
+ return err;
+ }
+
+ if (mtd->writesize == 1) {
+ printk(PRINT_PREF "not NAND flash, assume page size is 512 "
+ "bytes.\n");
+ pgsize = 512;
+ } else
+ pgsize = mtd->writesize;
+
+ if (pgcnt && (pgcnt > mtd->erasesize / pgsize || pgcnt < 0)) {
+ printk(PRINT_PREF "error: invalid pgcnt value %d\n", pgcnt);
+ goto out_mtd;
+ }
+
+ err = -ENOMEM;
+ patt_5A5 = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!patt_5A5) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out_mtd;
+ }
+
+ patt_A5A = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!patt_A5A) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out_patt_5A5;
+ }
+
+ patt_FF = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!patt_FF) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out_patt_A5A;
+ }
+
+ check_buf = kmalloc(mtd->erasesize, GFP_KERNEL);
+ if (!check_buf) {
+ printk(PRINT_PREF "error: cannot allocate memory\n");
+ goto out_patt_FF;
+ }
+
+ err = 0;
+
+ /* Initialize patterns */
+ memset(patt_FF, 0xFF, mtd->erasesize);
+ for (i = 0; i < mtd->erasesize / pgsize; i++) {
+ if (!(i & 1)) {
+ memset(patt_5A5 + i * pgsize, 0x55, pgsize);
+ memset(patt_A5A + i * pgsize, 0xAA, pgsize);
+ } else {
+ memset(patt_5A5 + i * pgsize, 0xAA, pgsize);
+ memset(patt_A5A + i * pgsize, 0x55, pgsize);
+ }
+ }
+
+ /*
+ * Check if there is a bad eraseblock among those we are going to test.
+ */
+ memset(&bad_ebs[0], 0, sizeof(int) * ebcnt);
+ if (mtd->block_isbad) {
+ for (i = eb; i < eb + ebcnt; i++) {
+ err = mtd->block_isbad(mtd,
+ (loff_t)i * mtd->erasesize);
+
+ if (err < 0) {
+ printk(PRINT_PREF "block_isbad() returned %d "
+ "for EB %d\n", err, i);
+ goto out;
+ }
+
+ if (err) {
+ printk("EB %d is bad. Skip it.\n", i);
+ bad_ebs[i - eb] = 1;
+ }
+ }
+ }
+
+ start_timing();
+ while (1) {
+ int i;
+ void *patt;
+
+ /* Erase all eraseblocks */
+ for (i = eb; i < eb + ebcnt; i++) {
+ if (bad_ebs[i - eb])
+ continue;
+ err = erase_eraseblock(i);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+
+ /* Check if the eraseblocks contain only 0xFF bytes */
+ if (check) {
+ for (i = eb; i < eb + ebcnt; i++) {
+ if (bad_ebs[i - eb])
+ continue;
+ err = check_eraseblock(i, patt_FF);
+ if (err) {
+ printk(PRINT_PREF "verify failed"
+ " for 0xFF... pattern\n");
+ goto out;
+ }
+ cond_resched();
+ }
+ }
+
+ /* Write the pattern */
+ for (i = eb; i < eb + ebcnt; i++) {
+ if (bad_ebs[i - eb])
+ continue;
+ if ((eb + erase_cycles) & 1)
+ patt = patt_5A5;
+ else
+ patt = patt_A5A;
+ err = write_pattern(i, patt);
+ if (err)
+ goto out;
+ cond_resched();
+ }
+
+ /* Verify what we wrote */
+ if (check) {
+ for (i = eb; i < eb + ebcnt; i++) {
+ if (bad_ebs[i - eb])
+ continue;
+ if ((eb + erase_cycles) & 1)
+ patt = patt_5A5;
+ else
+ patt = patt_A5A;
+ err = check_eraseblock(i, patt);
+ if (err) {
+ printk(PRINT_PREF "verify failed for %s"
+ " pattern\n",
+ ((eb + erase_cycles) & 1) ?
+ "0x55AA55..." : "0xAA55AA...");
+ goto out;
+ }
+ cond_resched();
+ }
+ }
+
+ erase_cycles += 1;
+
+ if (erase_cycles % gran == 0) {
+ long ms;
+
+ stop_timing();
+ ms = (finish.tv_sec - start.tv_sec) * 1000 +
+ (finish.tv_usec - start.tv_usec) / 1000;
+ printk(PRINT_PREF "%08u erase cycles done, took %lu "
+ "milliseconds (%lu seconds)\n",
+ erase_cycles, ms, ms / 1000);
+ start_timing();
+ }
+
+ if (!infinite && --cycles_count == 0)
+ break;
+ }
+out:
+
+ printk(PRINT_PREF "finished after %u erase cycles\n",
+ erase_cycles);
+ kfree(check_buf);
+out_patt_FF:
+ kfree(patt_FF);
+out_patt_A5A:
+ kfree(patt_A5A);
+out_patt_5A5:
+ kfree(patt_5A5);
+out_mtd:
+ put_mtd_device(mtd);
+ if (err)
+ printk(PRINT_PREF "error %d occurred during torturing\n", err);
+ printk(KERN_INFO "=================================================\n");
+ return err;
+}
+module_init(tort_init);
+
+static void __exit tort_exit(void)
+{
+ return;
+}
+module_exit(tort_exit);
+
+static int countdiffs(unsigned char *buf, unsigned char *check_buf,
+ unsigned offset, unsigned len, unsigned *bytesp,
+ unsigned *bitsp);
+static void print_bufs(unsigned char *read, unsigned char *written, int start,
+ int len);
+
+/*
+ * Report the detailed information about how the read EB differs from what was
+ * written.
+ */
+static void report_corrupt(unsigned char *read, unsigned char *written)
+{
+ int i;
+ int bytes, bits, pages, first;
+ int offset, len;
+ size_t check_len = mtd->erasesize;
+
+ if (pgcnt)
+ check_len = pgcnt * pgsize;
+
+ bytes = bits = pages = 0;
+ for (i = 0; i < check_len; i += pgsize)
+ if (countdiffs(written, read, i, pgsize, &bytes,
+ &bits) >= 0)
+ pages++;
+
+ printk(PRINT_PREF "verify fails on %d pages, %d bytes/%d bits\n",
+ pages, bytes, bits);
+ printk(PRINT_PREF "The following is a list of all differences between"
+ " what was read from flash and what was expected\n");
+
+ for (i = 0; i < check_len; i += pgsize) {
+ cond_resched();
+ bytes = bits = 0;
+ first = countdiffs(written, read, i, pgsize, &bytes,
+ &bits);
+ if (first < 0)
+ continue;
+
+ printk("-------------------------------------------------------"
+ "----------------------------------\n");
+
+ printk(PRINT_PREF "Page %zd has %d bytes/%d bits failing verify,"
+ " starting at offset 0x%x\n",
+ (mtd->erasesize - check_len + i) / pgsize,
+ bytes, bits, first);
+
+ offset = first & ~0x7;
+ len = ((first + bytes) | 0x7) + 1 - offset;
+
+ print_bufs(read, written, offset, len);
+ }
+}
+
+static void print_bufs(unsigned char *read, unsigned char *written, int start,
+ int len)
+{
+ int i = 0, j1, j2;
+ char *diff;
+
+ printk("Offset Read Written\n");
+ while (i < len) {
+ printk("0x%08x: ", start + i);
+ diff = " ";
+ for (j1 = 0; j1 < 8 && i + j1 < len; j1++) {
+ printk(" %02x", read[start + i + j1]);
+ if (read[start + i + j1] != written[start + i + j1])
+ diff = "***";
+ }
+
+ while (j1 < 8) {
+ printk(" ");
+ j1 += 1;
+ }
+
+ printk(" %s ", diff);
+
+ for (j2 = 0; j2 < 8 && i + j2 < len; j2++)
+ printk(" %02x", written[start + i + j2]);
+ printk("\n");
+ i += 8;
+ }
+}
+
+/*
+ * Count the number of differing bytes and bits and return the first differing
+ * offset.
+ */
+static int countdiffs(unsigned char *buf, unsigned char *check_buf,
+ unsigned offset, unsigned len, unsigned *bytesp,
+ unsigned *bitsp)
+{
+ unsigned i, bit;
+ int first = -1;
+
+ for (i = offset; i < offset + len; i++)
+ if (buf[i] != check_buf[i]) {
+ first = i;
+ break;
+ }
+
+ while (i < offset + len) {
+ if (buf[i] != check_buf[i]) {
+ (*bytesp)++;
+ bit = 1;
+ while (bit < 256) {
+ if ((buf[i] & bit) != (check_buf[i] & bit))
+ (*bitsp)++;
+ bit <<= 1;
+ }
+ }
+ i++;
+ }
+
+ return first;
+}
+
+MODULE_DESCRIPTION("Eraseblock torturing module");
+MODULE_AUTHOR("Artem Bityutskiy, Jarkko Lavinen, Adrian Hunter");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug
index 1e2ee22edeff..2246f154e2f7 100644
--- a/drivers/mtd/ubi/Kconfig.debug
+++ b/drivers/mtd/ubi/Kconfig.debug
@@ -33,16 +33,6 @@ config MTD_UBI_DEBUG_DISABLE_BGT
This option switches the background thread off by default. The thread
may be also be enabled/disabled via UBI sysfs.
-config MTD_UBI_DEBUG_USERSPACE_IO
- bool "Direct user-space write/erase support"
- default n
- depends on MTD_UBI_DEBUG
- help
- By default, users cannot directly write and erase individual
- eraseblocks of dynamic volumes, and have to use update operation
- instead. This option enables this capability - it is very useful for
- debugging and testing.
-
config MTD_UBI_DEBUG_EMULATE_BITFLIPS
bool "Emulate flash bit-flips"
depends on MTD_UBI_DEBUG
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index c7630a228310..4048db83aef6 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -263,8 +263,12 @@ static ssize_t dev_attribute_show(struct device *dev,
return ret;
}
-/* Fake "release" method for UBI devices */
-static void dev_release(struct device *dev) { }
+static void dev_release(struct device *dev)
+{
+ struct ubi_device *ubi = container_of(dev, struct ubi_device, dev);
+
+ kfree(ubi);
+}
/**
* ubi_sysfs_init - initialize sysfs for an UBI device.
@@ -280,7 +284,7 @@ static int ubi_sysfs_init(struct ubi_device *ubi)
ubi->dev.release = dev_release;
ubi->dev.devt = ubi->cdev.dev;
ubi->dev.class = ubi_class;
- sprintf(&ubi->dev.bus_id[0], UBI_NAME_STR"%d", ubi->ubi_num);
+ dev_set_name(&ubi->dev, UBI_NAME_STR"%d", ubi->ubi_num);
err = device_register(&ubi->dev);
if (err)
return err;
@@ -380,7 +384,7 @@ static void free_user_volumes(struct ubi_device *ubi)
*/
static int uif_init(struct ubi_device *ubi)
{
- int i, err, do_free = 0;
+ int i, err;
dev_t dev;
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
@@ -427,13 +431,10 @@ static int uif_init(struct ubi_device *ubi)
out_volumes:
kill_volumes(ubi);
- do_free = 0;
out_sysfs:
ubi_sysfs_close(ubi);
cdev_del(&ubi->cdev);
out_unreg:
- if (do_free)
- free_user_volumes(ubi);
unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err);
return err;
@@ -561,7 +562,7 @@ static int io_init(struct ubi_device *ubi)
*/
ubi->peb_size = ubi->mtd->erasesize;
- ubi->peb_count = ubi->mtd->size / ubi->mtd->erasesize;
+ ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
ubi->flash_size = ubi->mtd->size;
if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
@@ -815,19 +816,20 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
if (err)
goto out_free;
+ err = -ENOMEM;
ubi->peb_buf1 = vmalloc(ubi->peb_size);
if (!ubi->peb_buf1)
goto out_free;
ubi->peb_buf2 = vmalloc(ubi->peb_size);
if (!ubi->peb_buf2)
- goto out_free;
+ goto out_free;
#ifdef CONFIG_MTD_UBI_DEBUG
mutex_init(&ubi->dbg_buf_mutex);
ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
if (!ubi->dbg_peb_buf)
- goto out_free;
+ goto out_free;
#endif
err = attach_by_scanning(ubi);
@@ -946,6 +948,12 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
if (ubi->bgt_thread)
kthread_stop(ubi->bgt_thread);
+ /*
+ * Get a reference to the device in order to prevent 'dev_release()'
+ * from freeing @ubi object.
+ */
+ get_device(&ubi->dev);
+
uif_close(ubi);
ubi_wl_close(ubi);
free_internal_volumes(ubi);
@@ -957,7 +965,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
vfree(ubi->dbg_peb_buf);
#endif
ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
- kfree(ubi);
+ put_device(&ubi->dev);
return 0;
}
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index b30a0b83d7f1..e63c8fc3df3a 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -40,9 +40,9 @@
#include <linux/ioctl.h>
#include <linux/capability.h>
#include <linux/uaccess.h>
-#include <linux/smp_lock.h>
+#include <linux/compat.h>
+#include <linux/math64.h>
#include <mtd/ubi-user.h>
-#include <asm/div64.h>
#include "ubi.h"
/**
@@ -195,7 +195,6 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
int err, lnum, off, len, tbuf_size;
size_t count_save = count;
void *tbuf;
- uint64_t tmp;
dbg_gen("read %zd bytes from offset %lld of volume %d",
count, *offp, vol->vol_id);
@@ -225,10 +224,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
return -ENOMEM;
len = count > tbuf_size ? tbuf_size : count;
-
- tmp = *offp;
- off = do_div(tmp, vol->usable_leb_size);
- lnum = tmp;
+ lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
do {
cond_resched();
@@ -263,12 +259,9 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count,
return err ? err : count_save - count;
}
-#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
-
/*
* This function allows to directly write to dynamic UBI volumes, without
- * issuing the volume update operation. Available only as a debugging feature.
- * Very useful for testing UBI.
+ * issuing the volume update operation.
*/
static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
size_t count, loff_t *offp)
@@ -279,7 +272,9 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
int lnum, off, len, tbuf_size, err = 0;
size_t count_save = count;
char *tbuf;
- uint64_t tmp;
+
+ if (!vol->direct_writes)
+ return -EPERM;
dbg_gen("requested: write %zd bytes to offset %lld of volume %u",
count, *offp, vol->vol_id);
@@ -287,10 +282,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
if (vol->vol_type == UBI_STATIC_VOLUME)
return -EROFS;
- tmp = *offp;
- off = do_div(tmp, vol->usable_leb_size);
- lnum = tmp;
-
+ lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
if (off & (ubi->min_io_size - 1)) {
dbg_err("unaligned position");
return -EINVAL;
@@ -347,10 +339,6 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf,
return err ? err : count_save - count;
}
-#else
-#define vol_cdev_direct_write(file, buf, count, offp) (-EPERM)
-#endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */
-
static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
size_t count, loff_t *offp)
{
@@ -402,8 +390,8 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
return count;
}
-static int vol_cdev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
int err = 0;
struct ubi_volume_desc *desc = file->private_data;
@@ -487,7 +475,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
break;
}
-#ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO
/* Logical eraseblock erasure command */
case UBI_IOCEBER:
{
@@ -518,13 +505,77 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file,
err = ubi_wl_flush(ubi);
break;
}
-#endif
+
+ /* Logical eraseblock map command */
+ case UBI_IOCEBMAP:
+ {
+ struct ubi_map_req req;
+
+ err = copy_from_user(&req, argp, sizeof(struct ubi_map_req));
+ if (err) {
+ err = -EFAULT;
+ break;
+ }
+ err = ubi_leb_map(desc, req.lnum, req.dtype);
+ break;
+ }
+
+ /* Logical eraseblock un-map command */
+ case UBI_IOCEBUNMAP:
+ {
+ int32_t lnum;
+
+ err = get_user(lnum, (__user int32_t *)argp);
+ if (err) {
+ err = -EFAULT;
+ break;
+ }
+ err = ubi_leb_unmap(desc, lnum);
+ break;
+ }
+
+ /* Check if logical eraseblock is mapped command */
+ case UBI_IOCEBISMAP:
+ {
+ int32_t lnum;
+
+ err = get_user(lnum, (__user int32_t *)argp);
+ if (err) {
+ err = -EFAULT;
+ break;
+ }
+ err = ubi_is_mapped(desc, lnum);
+ break;
+ }
+
+ /* Set volume property command*/
+ case UBI_IOCSETPROP:
+ {
+ struct ubi_set_prop_req req;
+
+ err = copy_from_user(&req, argp,
+ sizeof(struct ubi_set_prop_req));
+ if (err) {
+ err = -EFAULT;
+ break;
+ }
+ switch (req.property) {
+ case UBI_PROP_DIRECT_WRITE:
+ mutex_lock(&ubi->volumes_mutex);
+ desc->vol->direct_writes = !!req.value;
+ mutex_unlock(&ubi->volumes_mutex);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ break;
+ }
default:
err = -ENOTTY;
break;
}
-
return err;
}
@@ -721,7 +772,8 @@ static int rename_volumes(struct ubi_device *ubi,
* It seems we need to remove volume with name @re->new_name,
* if it exists.
*/
- desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name, UBI_EXCLUSIVE);
+ desc = ubi_open_volume_nm(ubi->ubi_num, re->new_name,
+ UBI_EXCLUSIVE);
if (IS_ERR(desc)) {
err = PTR_ERR(desc);
if (err == -ENODEV)
@@ -761,8 +813,8 @@ out_free:
return err;
}
-static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long ubi_cdev_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
int err = 0;
struct ubi_device *ubi;
@@ -772,7 +824,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
if (!capable(CAP_SYS_RESOURCE))
return -EPERM;
- ubi = ubi_get_by_major(imajor(inode));
+ ubi = ubi_get_by_major(imajor(file->f_mapping->host));
if (!ubi)
return -ENODEV;
@@ -842,7 +894,6 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
case UBI_IOCRSVOL:
{
int pebs;
- uint64_t tmp;
struct ubi_rsvol_req req;
dbg_gen("re-size volume");
@@ -862,9 +913,8 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
break;
}
- tmp = req.bytes;
- pebs = !!do_div(tmp, desc->vol->usable_leb_size);
- pebs += tmp;
+ pebs = div_u64(req.bytes + desc->vol->usable_leb_size - 1,
+ desc->vol->usable_leb_size);
mutex_lock(&ubi->volumes_mutex);
err = ubi_resize_volume(desc, pebs);
@@ -908,8 +958,8 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
return err;
}
-static int ctrl_cdev_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
int err = 0;
void __user *argp = (void __user *)arg;
@@ -985,26 +1035,59 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file,
return err;
}
-/* UBI control character device operations */
-struct file_operations ubi_ctrl_cdev_operations = {
- .ioctl = ctrl_cdev_ioctl,
- .owner = THIS_MODULE,
+#ifdef CONFIG_COMPAT
+static long vol_cdev_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned long translated_arg = (unsigned long)compat_ptr(arg);
+
+ return vol_cdev_ioctl(file, cmd, translated_arg);
+}
+
+static long ubi_cdev_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned long translated_arg = (unsigned long)compat_ptr(arg);
+
+ return ubi_cdev_ioctl(file, cmd, translated_arg);
+}
+
+static long ctrl_cdev_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned long translated_arg = (unsigned long)compat_ptr(arg);
+
+ return ctrl_cdev_ioctl(file, cmd, translated_arg);
+}
+#else
+#define vol_cdev_compat_ioctl NULL
+#define ubi_cdev_compat_ioctl NULL
+#define ctrl_cdev_compat_ioctl NULL
+#endif
+
+/* UBI volume character device operations */
+const struct file_operations ubi_vol_cdev_operations = {
+ .owner = THIS_MODULE,
+ .open = vol_cdev_open,
+ .release = vol_cdev_release,
+ .llseek = vol_cdev_llseek,
+ .read = vol_cdev_read,
+ .write = vol_cdev_write,
+ .unlocked_ioctl = vol_cdev_ioctl,
+ .compat_ioctl = vol_cdev_compat_ioctl,
};
/* UBI character device operations */
-struct file_operations ubi_cdev_operations = {
- .owner = THIS_MODULE,
- .ioctl = ubi_cdev_ioctl,
- .llseek = no_llseek,
+const struct file_operations ubi_cdev_operations = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .unlocked_ioctl = ubi_cdev_ioctl,
+ .compat_ioctl = ubi_cdev_compat_ioctl,
};
-/* UBI volume character device operations */
-struct file_operations ubi_vol_cdev_operations = {
- .owner = THIS_MODULE,
- .open = vol_cdev_open,
- .release = vol_cdev_release,
- .llseek = vol_cdev_llseek,
- .read = vol_cdev_read,
- .write = vol_cdev_write,
- .ioctl = vol_cdev_ioctl,
+/* UBI control character device operations */
+const struct file_operations ubi_ctrl_cdev_operations = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = ctrl_cdev_ioctl,
+ .compat_ioctl = ctrl_cdev_compat_ioctl,
};
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 78e914d23ece..13777e5beac9 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -27,11 +27,11 @@
#define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__)
#define ubi_assert(expr) do { \
- if (unlikely(!(expr))) { \
- printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
- __func__, __LINE__, current->pid); \
- ubi_dbg_dump_stack(); \
- } \
+ if (unlikely(!(expr))) { \
+ printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
+ __func__, __LINE__, current->pid); \
+ ubi_dbg_dump_stack(); \
+ } \
} while (0)
#define dbg_msg(fmt, ...) \
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index d8966bae0e0b..25def348e5ba 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -504,12 +504,9 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
if (!vid_hdr)
return -ENOMEM;
- mutex_lock(&ubi->buf_mutex);
-
retry:
new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
if (new_pnum < 0) {
- mutex_unlock(&ubi->buf_mutex);
ubi_free_vid_hdr(ubi, vid_hdr);
return new_pnum;
}
@@ -529,20 +526,23 @@ retry:
goto write_error;
data_size = offset + len;
+ mutex_lock(&ubi->buf_mutex);
memset(ubi->peb_buf1 + offset, 0xFF, len);
/* Read everything before the area where the write failure happened */
if (offset > 0) {
err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
if (err && err != UBI_IO_BITFLIPS)
- goto out_put;
+ goto out_unlock;
}
memcpy(ubi->peb_buf1 + offset, buf, len);
err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
- if (err)
+ if (err) {
+ mutex_unlock(&ubi->buf_mutex);
goto write_error;
+ }
mutex_unlock(&ubi->buf_mutex);
ubi_free_vid_hdr(ubi, vid_hdr);
@@ -553,8 +553,9 @@ retry:
ubi_msg("data was successfully recovered");
return 0;
-out_put:
+out_unlock:
mutex_unlock(&ubi->buf_mutex);
+out_put:
ubi_wl_put_peb(ubi, new_pnum, 1);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -567,7 +568,6 @@ write_error:
ubi_warn("failed to write to PEB %d", new_pnum);
ubi_wl_put_peb(ubi, new_pnum, 1);
if (++tries > UBI_IO_RETRIES) {
- mutex_unlock(&ubi->buf_mutex);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
}
@@ -717,7 +717,7 @@ write_error:
* to the real data size, although the @buf buffer has to contain the
* alignment. In all other cases, @len has to be aligned.
*
- * It is prohibited to write more then once to logical eraseblocks of static
+ * It is prohibited to write more than once to logical eraseblocks of static
* volumes. This function returns zero in case of success and a negative error
* code in case of failure.
*/
@@ -949,10 +949,14 @@ write_error:
* This function copies logical eraseblock from physical eraseblock @from to
* physical eraseblock @to. The @vid_hdr buffer may be changed by this
* function. Returns:
- * o %0 in case of success;
- * o %1 if the operation was canceled and should be tried later (e.g.,
- * because a bit-flip was detected at the target PEB);
- * o %2 if the volume is being deleted and this LEB should not be moved.
+ * o %0 in case of success;
+ * o %1 if the operation was canceled because the volume is being deleted
+ * or because the PEB was put meanwhile;
+ * o %2 if the operation was canceled because there was a write error to the
+ * target PEB;
+ * o %-EAGAIN if the operation was canceled because a bit-flip was detected
+ * in the target PEB;
+ * o a negative error code in case of failure.
*/
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
struct ubi_vid_hdr *vid_hdr)
@@ -978,7 +982,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
/*
* Note, we may race with volume deletion, which means that the volume
* this logical eraseblock belongs to might be being deleted. Since the
- * volume deletion unmaps all the volume's logical eraseblocks, it will
+ * volume deletion un-maps all the volume's logical eraseblocks, it will
* be locked in 'ubi_wl_put_peb()' and wait for the WL worker to finish.
*/
vol = ubi->volumes[idx];
@@ -986,7 +990,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
/* No need to do further work, cancel */
dbg_eba("volume %d is being removed, cancel", vol_id);
spin_unlock(&ubi->volumes_lock);
- return 2;
+ return 1;
}
spin_unlock(&ubi->volumes_lock);
@@ -1023,7 +1027,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
/*
* OK, now the LEB is locked and we can safely start moving it. Since
- * this function utilizes thie @ubi->peb1_buf buffer which is shared
+ * this function utilizes the @ubi->peb1_buf buffer which is shared
* with some other functions, so lock the buffer by taking the
* @ubi->buf_mutex.
*/
@@ -1068,8 +1072,11 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi));
err = ubi_io_write_vid_hdr(ubi, to, vid_hdr);
- if (err)
+ if (err) {
+ if (err == -EIO)
+ err = 2;
goto out_unlock_buf;
+ }
cond_resched();
@@ -1079,14 +1086,17 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
if (err != UBI_IO_BITFLIPS)
ubi_warn("cannot read VID header back from PEB %d", to);
else
- err = 1;
+ err = -EAGAIN;
goto out_unlock_buf;
}
if (data_size > 0) {
err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
- if (err)
+ if (err) {
+ if (err == -EIO)
+ err = 2;
goto out_unlock_buf;
+ }
cond_resched();
@@ -1101,15 +1111,16 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
ubi_warn("cannot read data back from PEB %d",
to);
else
- err = 1;
+ err = -EAGAIN;
goto out_unlock_buf;
}
cond_resched();
if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
- ubi_warn("read data back from PEB %d - it is different",
- to);
+ ubi_warn("read data back from PEB %d and it is "
+ "different", to);
+ err = -EINVAL;
goto out_unlock_buf;
}
}
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index 605812bb0b1a..49cd55ade9c8 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -28,7 +28,7 @@
* eraseblock size is equivalent to the logical eraseblock size of the volume.
*/
-#include <asm/div64.h>
+#include <linux/math64.h>
#include "ubi.h"
/**
@@ -109,7 +109,6 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
int err = 0, lnum, offs, total_read;
struct ubi_volume *vol;
struct ubi_device *ubi;
- uint64_t tmp = from;
dbg_gen("read %zd bytes from offset %lld", len, from);
@@ -119,9 +118,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
ubi = vol->ubi;
- offs = do_div(tmp, mtd->erasesize);
- lnum = tmp;
-
+ lnum = div_u64_rem(from, mtd->erasesize, &offs);
total_read = len;
while (total_read) {
size_t to_read = mtd->erasesize - offs;
@@ -160,7 +157,6 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
int err = 0, lnum, offs, total_written;
struct ubi_volume *vol;
struct ubi_device *ubi;
- uint64_t tmp = to;
dbg_gen("write %zd bytes to offset %lld", len, to);
@@ -173,8 +169,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
if (ubi->ro_mode)
return -EROFS;
- offs = do_div(tmp, mtd->erasesize);
- lnum = tmp;
+ lnum = div_u64_rem(to, mtd->erasesize, &offs);
if (len % mtd->writesize || offs % mtd->writesize)
return -EINVAL;
@@ -215,7 +210,8 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
struct ubi_volume *vol;
struct ubi_device *ubi;
- dbg_gen("erase %u bytes at offset %u", instr->len, instr->addr);
+ dbg_gen("erase %llu bytes at offset %llu", (unsigned long long)instr->len,
+ (unsigned long long)instr->addr);
if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize)
return -EINVAL;
@@ -223,11 +219,11 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
if (instr->len < 0 || instr->addr + instr->len > mtd->size)
return -EINVAL;
- if (instr->addr % mtd->writesize || instr->len % mtd->writesize)
+ if (mtd_mod_by_ws(instr->addr, mtd) || mtd_mod_by_ws(instr->len, mtd))
return -EINVAL;
- lnum = instr->addr / mtd->erasesize;
- count = instr->len / mtd->erasesize;
+ lnum = mtd_div_by_eb(instr->addr, mtd);
+ count = mtd_div_by_eb(instr->len, mtd);
vol = container_of(mtd, struct ubi_volume, gluebi_mtd);
ubi = vol->ubi;
@@ -255,7 +251,7 @@ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
out_err:
instr->state = MTD_ERASE_FAILED;
- instr->fail_addr = lnum * mtd->erasesize;
+ instr->fail_addr = (long long)lnum * mtd->erasesize;
return err;
}
@@ -294,7 +290,7 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
* bytes.
*/
if (vol->vol_type == UBI_DYNAMIC_VOLUME)
- mtd->size = vol->usable_leb_size * vol->reserved_pebs;
+ mtd->size = (long long)vol->usable_leb_size * vol->reserved_pebs;
else
mtd->size = vol->used_bytes;
@@ -304,8 +300,8 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
return -ENFILE;
}
- dbg_gen("added mtd%d (\"%s\"), size %u, EB size %u",
- mtd->index, mtd->name, mtd->size, mtd->erasesize);
+ dbg_gen("added mtd%d (\"%s\"), size %llu, EB size %u",
+ mtd->index, mtd->name, (unsigned long long)mtd->size, mtd->erasesize);
return 0;
}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 2fb64be44f1b..fe81039f2a7c 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -465,7 +465,7 @@ out:
* This function synchronously erases physical eraseblock @pnum. If @torture
* flag is not zero, the physical eraseblock is checked by means of writing
* different patterns to it and reading them back. If the torturing is enabled,
- * the physical eraseblock is erased more then once.
+ * the physical eraseblock is erased more than once.
*
* This function returns the number of erasures made in case of success, %-EIO
* if the erasure failed or the torturing test failed, and other negative error
@@ -637,8 +637,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
dbg_io("read EC header from PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- if (UBI_IO_DEBUG)
- verbose = 1;
err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
if (err) {
@@ -685,6 +683,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
if (verbose)
ubi_warn("no EC header found at PEB %d, "
"only 0xFF bytes", pnum);
+ else if (UBI_IO_DEBUG)
+ dbg_msg("no EC header found at PEB %d, "
+ "only 0xFF bytes", pnum);
return UBI_IO_PEB_EMPTY;
}
@@ -696,7 +697,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
ubi_dbg_dump_ec_hdr(ec_hdr);
- }
+ } else if (UBI_IO_DEBUG)
+ dbg_msg("bad magic number at PEB %d: %08x instead of "
+ "%08x", pnum, magic, UBI_EC_HDR_MAGIC);
return UBI_IO_BAD_EC_HDR;
}
@@ -708,7 +711,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
ubi_warn("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
ubi_dbg_dump_ec_hdr(ec_hdr);
- }
+ } else if (UBI_IO_DEBUG)
+ dbg_msg("bad EC header CRC at PEB %d, calculated "
+ "%#08x, read %#08x", pnum, crc, hdr_crc);
return UBI_IO_BAD_EC_HDR;
}
@@ -912,8 +917,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
dbg_io("read VID header from PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- if (UBI_IO_DEBUG)
- verbose = 1;
p = (char *)vid_hdr - ubi->vid_hdr_shift;
err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
@@ -960,6 +963,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
if (verbose)
ubi_warn("no VID header found at PEB %d, "
"only 0xFF bytes", pnum);
+ else if (UBI_IO_DEBUG)
+ dbg_msg("no VID header found at PEB %d, "
+ "only 0xFF bytes", pnum);
return UBI_IO_PEB_FREE;
}
@@ -971,7 +977,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
ubi_dbg_dump_vid_hdr(vid_hdr);
- }
+ } else if (UBI_IO_DEBUG)
+ dbg_msg("bad magic number at PEB %d: %08x instead of "
+ "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
return UBI_IO_BAD_VID_HDR;
}
@@ -983,7 +991,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
ubi_warn("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
ubi_dbg_dump_vid_hdr(vid_hdr);
- }
+ } else if (UBI_IO_DEBUG)
+ dbg_msg("bad CRC at PEB %d, calculated %#08x, "
+ "read %#08x", pnum, crc, hdr_crc);
return UBI_IO_BAD_VID_HDR;
}
@@ -1024,7 +1034,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
err = paranoid_check_peb_ec_hdr(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL: err;
+ return err > 0 ? -EINVAL : err;
vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
vid_hdr->version = UBI_VERSION;
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 5d9bcf109c13..4abbe573fa40 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -564,7 +564,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap);
* @dtype: expected data type
*
* This function maps an un-mapped logical eraseblock @lnum to a physical
- * eraseblock. This means, that after a successfull invocation of this
+ * eraseblock. This means, that after a successful invocation of this
* function the logical eraseblock @lnum will be empty (contain only %0xFF
* bytes) and be mapped to a physical eraseblock, even if an unclean reboot
* happens.
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 41d47e1cf15c..c3d653ba5ca0 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -42,7 +42,7 @@
#include <linux/err.h>
#include <linux/crc32.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
@@ -478,7 +478,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
return 0;
} else {
/*
- * This logical eraseblock is older then the one found
+ * This logical eraseblock is older than the one found
* previously.
*/
if (cmp_res & 4)
@@ -904,10 +904,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
dbg_msg("scanning is finished");
/* Calculate mean erase counter */
- if (si->ec_count) {
- do_div(si->ec_sum, si->ec_count);
- si->mean_ec = si->ec_sum;
- }
+ if (si->ec_count)
+ si->mean_ec = div_u64(si->ec_sum, si->ec_count);
if (si->is_empty)
ubi_msg("empty MTD device detected");
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index 2ad940409053..8419fdccc79c 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -135,7 +135,7 @@ enum {
* The erase counter header takes 64 bytes and has a plenty of unused space for
* future usage. The unused fields are zeroed. The @version field is used to
* indicate the version of UBI implementation which is supposed to be able to
- * work with this UBI image. If @version is greater then the current UBI
+ * work with this UBI image. If @version is greater than the current UBI
* version, the image is rejected. This may be useful in future if something
* is changed radically. This field is duplicated in the volume identifier
* header.
@@ -187,7 +187,7 @@ struct ubi_ec_hdr {
* (sequence number) is used to distinguish between older and newer versions of
* logical eraseblocks.
*
- * There are 2 situations when there may be more then one physical eraseblock
+ * There are 2 situations when there may be more than one physical eraseblock
* corresponding to the same logical eraseblock, i.e., having the same @vol_id
* and @lnum values in the volume identifier header. Suppose we have a logical
* eraseblock L and it is mapped to the physical eraseblock P.
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 1c3fa18c26a7..c055511bb1b2 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -74,6 +74,13 @@
#define UBI_IO_RETRIES 3
/*
+ * Length of the protection queue. The length is effectively equivalent to the
+ * number of (global) erase cycles PEBs are protected from the wear-leveling
+ * worker.
+ */
+#define UBI_PROT_QUEUE_LEN 10
+
+/*
* Error codes returned by the I/O sub-system.
*
* UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only
@@ -95,7 +102,8 @@ enum {
/**
* struct ubi_wl_entry - wear-leveling entry.
- * @rb: link in the corresponding RB-tree
+ * @u.rb: link in the corresponding (free/used) RB-tree
+ * @u.list: link in the protection queue
* @ec: erase counter
* @pnum: physical eraseblock number
*
@@ -104,7 +112,10 @@ enum {
* RB-trees. See WL sub-system for details.
*/
struct ubi_wl_entry {
- struct rb_node rb;
+ union {
+ struct rb_node rb;
+ struct list_head list;
+ } u;
int ec;
int pnum;
};
@@ -195,6 +206,7 @@ struct ubi_volume_desc;
* @upd_marker: %1 if the update marker is set for this volume
* @updating: %1 if the volume is being updated
* @changing_leb: %1 if the atomic LEB change ioctl command is in progress
+ * @direct_writes: %1 if direct writes are enabled for this volume
*
* @gluebi_desc: gluebi UBI volume descriptor
* @gluebi_refcount: reference count of the gluebi MTD device
@@ -242,6 +254,7 @@ struct ubi_volume {
unsigned int upd_marker:1;
unsigned int updating:1;
unsigned int changing_leb:1;
+ unsigned int direct_writes:1;
#ifdef CONFIG_MTD_UBI_GLUEBI
/*
@@ -288,12 +301,13 @@ struct ubi_wl_entry;
* @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling
*
* @autoresize_vol_id: ID of the volume which has to be auto-resized at the end
- * of UBI ititializetion
+ * of UBI initialization
* @vtbl_slots: how many slots are available in the volume table
* @vtbl_size: size of the volume table in bytes
* @vtbl: in-RAM volume table copy
* @volumes_mutex: protects on-flash volume table and serializes volume
- * changes, like creation, deletion, update, re-size and re-name
+ * changes, like creation, deletion, update, re-size,
+ * re-name and set property
*
* @max_ec: current highest erase counter value
* @mean_ec: current mean erase counter value
@@ -306,18 +320,17 @@ struct ubi_wl_entry;
* @used: RB-tree of used physical eraseblocks
* @free: RB-tree of free physical eraseblocks
* @scrub: RB-tree of physical eraseblocks which need scrubbing
- * @prot: protection trees
- * @prot.pnum: protection tree indexed by physical eraseblock numbers
- * @prot.aec: protection tree indexed by absolute erase counter value
- * @wl_lock: protects the @used, @free, @prot, @lookuptbl, @abs_ec, @move_from,
- * @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works
- * fields
+ * @pq: protection queue (contain physical eraseblocks which are temporarily
+ * protected from the wear-leveling worker)
+ * @pq_head: protection queue head
+ * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from,
+ * @move_to, @move_to_put @erase_pending, @wl_scheduled and @works
+ * fields
* @move_mutex: serializes eraseblock moves
- * @work_sem: sycnhronizes the WL worker with use tasks
+ * @work_sem: synchronizes the WL worker with use tasks
* @wl_scheduled: non-zero if the wear-leveling was scheduled
* @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any
* physical eraseblock
- * @abs_ec: absolute erase counter
* @move_from: physical eraseblock from where the data is being moved
* @move_to: physical eraseblock where the data is being moved to
* @move_to_put: if the "to" PEB was put
@@ -351,11 +364,11 @@ struct ubi_wl_entry;
*
* @peb_buf1: a buffer of PEB size used for different purposes
* @peb_buf2: another buffer of PEB size used for different purposes
- * @buf_mutex: proptects @peb_buf1 and @peb_buf2
+ * @buf_mutex: protects @peb_buf1 and @peb_buf2
* @ckvol_mutex: serializes static volume checking when opening
- * @mult_mutex: serializes operations on multiple volumes, like re-nameing
+ * @mult_mutex: serializes operations on multiple volumes, like re-naming
* @dbg_peb_buf: buffer of PEB size used for debugging
- * @dbg_buf_mutex: proptects @dbg_peb_buf
+ * @dbg_buf_mutex: protects @dbg_peb_buf
*/
struct ubi_device {
struct cdev cdev;
@@ -392,16 +405,13 @@ struct ubi_device {
struct rb_root used;
struct rb_root free;
struct rb_root scrub;
- struct {
- struct rb_root pnum;
- struct rb_root aec;
- } prot;
+ struct list_head pq[UBI_PROT_QUEUE_LEN];
+ int pq_head;
spinlock_t wl_lock;
struct mutex move_mutex;
struct rw_semaphore work_sem;
int wl_scheduled;
struct ubi_wl_entry **lookuptbl;
- unsigned long long abs_ec;
struct ubi_wl_entry *move_from;
struct ubi_wl_entry *move_to;
int move_to_put;
@@ -442,9 +452,9 @@ struct ubi_device {
};
extern struct kmem_cache *ubi_wl_entry_slab;
-extern struct file_operations ubi_ctrl_cdev_operations;
-extern struct file_operations ubi_cdev_operations;
-extern struct file_operations ubi_vol_cdev_operations;
+extern const struct file_operations ubi_ctrl_cdev_operations;
+extern const struct file_operations ubi_cdev_operations;
+extern const struct file_operations ubi_vol_cdev_operations;
extern struct class *ubi_class;
extern struct mutex ubi_devices_mutex;
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 8b89cc18ff0b..6b4d1ae891ae 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -40,7 +40,7 @@
#include <linux/err.h>
#include <linux/uaccess.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
#include "ubi.h"
/**
@@ -89,7 +89,6 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
long long bytes)
{
int err;
- uint64_t tmp;
struct ubi_vtbl_record vtbl_rec;
dbg_gen("clear update marker for volume %d", vol->vol_id);
@@ -101,9 +100,9 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol,
if (vol->vol_type == UBI_STATIC_VOLUME) {
vol->corrupted = 0;
- vol->used_bytes = tmp = bytes;
- vol->last_eb_bytes = do_div(tmp, vol->usable_leb_size);
- vol->used_ebs = tmp;
+ vol->used_bytes = bytes;
+ vol->used_ebs = div_u64_rem(bytes, vol->usable_leb_size,
+ &vol->last_eb_bytes);
if (vol->last_eb_bytes)
vol->used_ebs += 1;
else
@@ -131,7 +130,6 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
long long bytes)
{
int i, err;
- uint64_t tmp;
dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes);
ubi_assert(!vol->updating && !vol->changing_leb);
@@ -161,9 +159,8 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
if (!vol->upd_buf)
return -ENOMEM;
- tmp = bytes;
- vol->upd_ebs = !!do_div(tmp, vol->usable_leb_size);
- vol->upd_ebs += tmp;
+ vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
+ vol->usable_leb_size);
vol->upd_bytes = bytes;
vol->upd_received = 0;
return 0;
@@ -282,7 +279,6 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
const void __user *buf, int count)
{
- uint64_t tmp;
int lnum, offs, err = 0, len, to_write = count;
dbg_gen("write %d of %lld bytes, %lld already passed",
@@ -291,10 +287,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
if (ubi->ro_mode)
return -EROFS;
- tmp = vol->upd_received;
- offs = do_div(tmp, vol->usable_leb_size);
- lnum = tmp;
-
+ lnum = div_u64_rem(vol->upd_received, vol->usable_leb_size, &offs);
if (vol->upd_received + count > vol->upd_bytes)
to_write = count = vol->upd_bytes - vol->upd_received;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 3531ca9a1e24..df5483562b7a 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -24,7 +24,7 @@
*/
#include <linux/err.h>
-#include <asm/div64.h>
+#include <linux/math64.h>
#include "ubi.h"
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
@@ -205,7 +205,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
int i, err, vol_id = req->vol_id, do_free = 1;
struct ubi_volume *vol;
struct ubi_vtbl_record vtbl_rec;
- uint64_t bytes;
dev_t dev;
if (ubi->ro_mode)
@@ -255,10 +254,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Calculate how many eraseblocks are requested */
vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment;
- bytes = req->bytes;
- if (do_div(bytes, vol->usable_leb_size))
- vol->reserved_pebs = 1;
- vol->reserved_pebs += bytes;
+ vol->reserved_pebs += div_u64(req->bytes + vol->usable_leb_size - 1,
+ vol->usable_leb_size);
/* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) {
@@ -301,10 +298,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vol->used_bytes =
(long long)vol->used_ebs * vol->usable_leb_size;
} else {
- bytes = vol->used_bytes;
- vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size);
- vol->used_ebs = bytes;
- if (vol->last_eb_bytes)
+ vol->used_ebs = div_u64_rem(vol->used_bytes,
+ vol->usable_leb_size,
+ &vol->last_eb_bytes);
+ if (vol->last_eb_bytes != 0)
vol->used_ebs += 1;
else
vol->last_eb_bytes = vol->usable_leb_size;
@@ -329,7 +326,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vol->dev.devt = dev;
vol->dev.class = ubi_class;
- sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id);
+ dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
err = device_register(&vol->dev);
if (err) {
ubi_err("cannot register device");
@@ -678,7 +675,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
vol->dev.parent = &ubi->dev;
vol->dev.devt = dev;
vol->dev.class = ubi_class;
- sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id);
+ dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
err = device_register(&vol->dev);
if (err)
goto out_gluebi;
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 333c8941552f..1afc61e7455d 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -577,7 +577,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
/* Auto re-size flag may be set only for one volume */
if (ubi->autoresize_vol_id != -1) {
- ubi_err("more then one auto-resize volume (%d "
+ ubi_err("more than one auto-resize volume (%d "
"and %d)", ubi->autoresize_vol_id, i);
kfree(vol);
return -EINVAL;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index dcb6dac1dc54..891534f8210d 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -22,7 +22,7 @@
* UBI wear-leveling sub-system.
*
* This sub-system is responsible for wear-leveling. It works in terms of
- * physical* eraseblocks and erase counters and knows nothing about logical
+ * physical eraseblocks and erase counters and knows nothing about logical
* eraseblocks, volumes, etc. From this sub-system's perspective all physical
* eraseblocks are of two types - used and free. Used physical eraseblocks are
* those that were "get" by the 'ubi_wl_get_peb()' function, and free physical
@@ -55,8 +55,39 @@
*
* As it was said, for the UBI sub-system all physical eraseblocks are either
* "free" or "used". Free eraseblock are kept in the @wl->free RB-tree, while
- * used eraseblocks are kept in a set of different RB-trees: @wl->used,
- * @wl->prot.pnum, @wl->prot.aec, and @wl->scrub.
+ * used eraseblocks are kept in @wl->used or @wl->scrub RB-trees, or
+ * (temporarily) in the @wl->pq queue.
+ *
+ * When the WL sub-system returns a physical eraseblock, the physical
+ * eraseblock is protected from being moved for some "time". For this reason,
+ * the physical eraseblock is not directly moved from the @wl->free tree to the
+ * @wl->used tree. There is a protection queue in between where this
+ * physical eraseblock is temporarily stored (@wl->pq).
+ *
+ * All this protection stuff is needed because:
+ * o we don't want to move physical eraseblocks just after we have given them
+ * to the user; instead, we first want to let users fill them up with data;
+ *
+ * o there is a chance that the user will put the physical eraseblock very
+ * soon, so it makes sense not to move it for some time, but wait; this is
+ * especially important in case of "short term" physical eraseblocks.
+ *
+ * Physical eraseblocks stay protected only for limited time. But the "time" is
+ * measured in erase cycles in this case. This is implemented with help of the
+ * protection queue. Eraseblocks are put to the tail of this queue when they
+ * are returned by the 'ubi_wl_get_peb()', and eraseblocks are removed from the
+ * head of the queue on each erase operation (for any eraseblock). So the
+ * length of the queue defines how may (global) erase cycles PEBs are protected.
+ *
+ * To put it differently, each physical eraseblock has 2 main states: free and
+ * used. The former state corresponds to the @wl->free tree. The latter state
+ * is split up on several sub-states:
+ * o the WL movement is allowed (@wl->used tree);
+ * o the WL movement is temporarily prohibited (@wl->pq queue);
+ * o scrubbing is needed (@wl->scrub tree).
+ *
+ * Depending on the sub-state, wear-leveling entries of the used physical
+ * eraseblocks may be kept in one of those structures.
*
* Note, in this implementation, we keep a small in-RAM object for each physical
* eraseblock. This is surely not a scalable solution. But it appears to be good
@@ -70,9 +101,6 @@
* target PEB, we pick a PEB with the highest EC if our PEB is "old" and we
* pick target PEB with an average EC if our PEB is not very "old". This is a
* room for future re-works of the WL sub-system.
- *
- * Note: the stuff with protection trees looks too complex and is difficult to
- * understand. Should be fixed.
*/
#include <linux/slab.h>
@@ -85,14 +113,6 @@
#define WL_RESERVED_PEBS 1
/*
- * How many erase cycles are short term, unknown, and long term physical
- * eraseblocks protected.
- */
-#define ST_PROTECTION 16
-#define U_PROTECTION 10
-#define LT_PROTECTION 4
-
-/*
* Maximum difference between two erase counters. If this threshold is
* exceeded, the WL sub-system starts moving data from used physical
* eraseblocks with low erase counter to free physical eraseblocks with high
@@ -108,7 +128,7 @@
* situation when the picked physical eraseblock is constantly erased after the
* data is written to it. So, we have a constant which limits the highest erase
* counter of the free physical eraseblock to pick. Namely, the WL sub-system
- * does not pick eraseblocks with erase counter greater then the lowest erase
+ * does not pick eraseblocks with erase counter greater than the lowest erase
* counter plus %WL_FREE_MAX_DIFF.
*/
#define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD)
@@ -120,64 +140,9 @@
#define WL_MAX_FAILURES 32
/**
- * struct ubi_wl_prot_entry - PEB protection entry.
- * @rb_pnum: link in the @wl->prot.pnum RB-tree
- * @rb_aec: link in the @wl->prot.aec RB-tree
- * @abs_ec: the absolute erase counter value when the protection ends
- * @e: the wear-leveling entry of the physical eraseblock under protection
- *
- * When the WL sub-system returns a physical eraseblock, the physical
- * eraseblock is protected from being moved for some "time". For this reason,
- * the physical eraseblock is not directly moved from the @wl->free tree to the
- * @wl->used tree. There is one more tree in between where this physical
- * eraseblock is temporarily stored (@wl->prot).
- *
- * All this protection stuff is needed because:
- * o we don't want to move physical eraseblocks just after we have given them
- * to the user; instead, we first want to let users fill them up with data;
- *
- * o there is a chance that the user will put the physical eraseblock very
- * soon, so it makes sense not to move it for some time, but wait; this is
- * especially important in case of "short term" physical eraseblocks.
- *
- * Physical eraseblocks stay protected only for limited time. But the "time" is
- * measured in erase cycles in this case. This is implemented with help of the
- * absolute erase counter (@wl->abs_ec). When it reaches certain value, the
- * physical eraseblocks are moved from the protection trees (@wl->prot.*) to
- * the @wl->used tree.
- *
- * Protected physical eraseblocks are searched by physical eraseblock number
- * (when they are put) and by the absolute erase counter (to check if it is
- * time to move them to the @wl->used tree). So there are actually 2 RB-trees
- * storing the protected physical eraseblocks: @wl->prot.pnum and
- * @wl->prot.aec. They are referred to as the "protection" trees. The
- * first one is indexed by the physical eraseblock number. The second one is
- * indexed by the absolute erase counter. Both trees store
- * &struct ubi_wl_prot_entry objects.
- *
- * Each physical eraseblock has 2 main states: free and used. The former state
- * corresponds to the @wl->free tree. The latter state is split up on several
- * sub-states:
- * o the WL movement is allowed (@wl->used tree);
- * o the WL movement is temporarily prohibited (@wl->prot.pnum and
- * @wl->prot.aec trees);
- * o scrubbing is needed (@wl->scrub tree).
- *
- * Depending on the sub-state, wear-leveling entries of the used physical
- * eraseblocks may be kept in one of those trees.
- */
-struct ubi_wl_prot_entry {
- struct rb_node rb_pnum;
- struct rb_node rb_aec;
- unsigned long long abs_ec;
- struct ubi_wl_entry *e;
-};
-
-/**
* struct ubi_work - UBI work description data structure.
* @list: a link in the list of pending works
* @func: worker function
- * @priv: private data of the worker function
* @e: physical eraseblock to erase
* @torture: if the physical eraseblock has to be tortured
*
@@ -198,9 +163,11 @@ struct ubi_work {
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
struct rb_root *root);
+static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e);
#else
#define paranoid_check_ec(ubi, pnum, ec) 0
#define paranoid_check_in_wl_tree(e, root)
+#define paranoid_check_in_pq(ubi, e) 0
#endif
/**
@@ -220,7 +187,7 @@ static void wl_tree_add(struct ubi_wl_entry *e, struct rb_root *root)
struct ubi_wl_entry *e1;
parent = *p;
- e1 = rb_entry(parent, struct ubi_wl_entry, rb);
+ e1 = rb_entry(parent, struct ubi_wl_entry, u.rb);
if (e->ec < e1->ec)
p = &(*p)->rb_left;
@@ -235,8 +202,8 @@ static void wl_tree_add(struct ubi_wl_entry *e, struct rb_root *root)
}
}
- rb_link_node(&e->rb, parent, p);
- rb_insert_color(&e->rb, root);
+ rb_link_node(&e->u.rb, parent, p);
+ rb_insert_color(&e->u.rb, root);
}
/**
@@ -331,7 +298,7 @@ static int in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root)
while (p) {
struct ubi_wl_entry *e1;
- e1 = rb_entry(p, struct ubi_wl_entry, rb);
+ e1 = rb_entry(p, struct ubi_wl_entry, u.rb);
if (e->pnum == e1->pnum) {
ubi_assert(e == e1);
@@ -355,50 +322,24 @@ static int in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root)
}
/**
- * prot_tree_add - add physical eraseblock to protection trees.
+ * prot_queue_add - add physical eraseblock to the protection queue.
* @ubi: UBI device description object
* @e: the physical eraseblock to add
- * @pe: protection entry object to use
- * @abs_ec: absolute erase counter value when this physical eraseblock has
- * to be removed from the protection trees.
*
- * @wl->lock has to be locked.
+ * This function adds @e to the tail of the protection queue @ubi->pq, where
+ * @e will stay for %UBI_PROT_QUEUE_LEN erase operations and will be
+ * temporarily protected from the wear-leveling worker. Note, @wl->lock has to
+ * be locked.
*/
-static void prot_tree_add(struct ubi_device *ubi, struct ubi_wl_entry *e,
- struct ubi_wl_prot_entry *pe, int abs_ec)
+static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e)
{
- struct rb_node **p, *parent = NULL;
- struct ubi_wl_prot_entry *pe1;
-
- pe->e = e;
- pe->abs_ec = ubi->abs_ec + abs_ec;
-
- p = &ubi->prot.pnum.rb_node;
- while (*p) {
- parent = *p;
- pe1 = rb_entry(parent, struct ubi_wl_prot_entry, rb_pnum);
-
- if (e->pnum < pe1->e->pnum)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
- rb_link_node(&pe->rb_pnum, parent, p);
- rb_insert_color(&pe->rb_pnum, &ubi->prot.pnum);
-
- p = &ubi->prot.aec.rb_node;
- parent = NULL;
- while (*p) {
- parent = *p;
- pe1 = rb_entry(parent, struct ubi_wl_prot_entry, rb_aec);
+ int pq_tail = ubi->pq_head - 1;
- if (pe->abs_ec < pe1->abs_ec)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
- rb_link_node(&pe->rb_aec, parent, p);
- rb_insert_color(&pe->rb_aec, &ubi->prot.aec);
+ if (pq_tail < 0)
+ pq_tail = UBI_PROT_QUEUE_LEN - 1;
+ ubi_assert(pq_tail >= 0 && pq_tail < UBI_PROT_QUEUE_LEN);
+ list_add_tail(&e->u.list, &ubi->pq[pq_tail]);
+ dbg_wl("added PEB %d EC %d to the protection queue", e->pnum, e->ec);
}
/**
@@ -414,14 +355,14 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
struct rb_node *p;
struct ubi_wl_entry *e;
- e = rb_entry(rb_first(root), struct ubi_wl_entry, rb);
+ e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
max += e->ec;
p = root->rb_node;
while (p) {
struct ubi_wl_entry *e1;
- e1 = rb_entry(p, struct ubi_wl_entry, rb);
+ e1 = rb_entry(p, struct ubi_wl_entry, u.rb);
if (e1->ec >= max)
p = p->rb_left;
else {
@@ -443,17 +384,12 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
*/
int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
{
- int err, protect, medium_ec;
+ int err, medium_ec;
struct ubi_wl_entry *e, *first, *last;
- struct ubi_wl_prot_entry *pe;
ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
dtype == UBI_UNKNOWN);
- pe = kmalloc(sizeof(struct ubi_wl_prot_entry), GFP_NOFS);
- if (!pe)
- return -ENOMEM;
-
retry:
spin_lock(&ubi->wl_lock);
if (!ubi->free.rb_node) {
@@ -461,16 +397,13 @@ retry:
ubi_assert(list_empty(&ubi->works));
ubi_err("no free eraseblocks");
spin_unlock(&ubi->wl_lock);
- kfree(pe);
return -ENOSPC;
}
spin_unlock(&ubi->wl_lock);
err = produce_free_peb(ubi);
- if (err < 0) {
- kfree(pe);
+ if (err < 0)
return err;
- }
goto retry;
}
@@ -483,7 +416,6 @@ retry:
* %WL_FREE_MAX_DIFF.
*/
e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- protect = LT_PROTECTION;
break;
case UBI_UNKNOWN:
/*
@@ -492,81 +424,63 @@ retry:
* eraseblock with erase counter greater or equivalent than the
* lowest erase counter plus %WL_FREE_MAX_DIFF.
*/
- first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
- last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, rb);
+ first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
+ u.rb);
+ last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
if (last->ec - first->ec < WL_FREE_MAX_DIFF)
e = rb_entry(ubi->free.rb_node,
- struct ubi_wl_entry, rb);
+ struct ubi_wl_entry, u.rb);
else {
medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
e = find_wl_entry(&ubi->free, medium_ec);
}
- protect = U_PROTECTION;
break;
case UBI_SHORTTERM:
/*
* For short term data we pick a physical eraseblock with the
* lowest erase counter as we expect it will be erased soon.
*/
- e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, rb);
- protect = ST_PROTECTION;
+ e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
break;
default:
- protect = 0;
- e = NULL;
BUG();
}
+ paranoid_check_in_wl_tree(e, &ubi->free);
+
/*
- * Move the physical eraseblock to the protection trees where it will
+ * Move the physical eraseblock to the protection queue where it will
* be protected from being moved for some time.
*/
- paranoid_check_in_wl_tree(e, &ubi->free);
- rb_erase(&e->rb, &ubi->free);
- prot_tree_add(ubi, e, pe, protect);
-
- dbg_wl("PEB %d EC %d, protection %d", e->pnum, e->ec, protect);
+ rb_erase(&e->u.rb, &ubi->free);
+ dbg_wl("PEB %d EC %d", e->pnum, e->ec);
+ prot_queue_add(ubi, e);
spin_unlock(&ubi->wl_lock);
-
return e->pnum;
}
/**
- * prot_tree_del - remove a physical eraseblock from the protection trees
+ * prot_queue_del - remove a physical eraseblock from the protection queue.
* @ubi: UBI device description object
* @pnum: the physical eraseblock to remove
*
- * This function returns PEB @pnum from the protection trees and returns zero
- * in case of success and %-ENODEV if the PEB was not found in the protection
- * trees.
+ * This function deletes PEB @pnum from the protection queue and returns zero
+ * in case of success and %-ENODEV if the PEB was not found.
*/
-static int prot_tree_del(struct ubi_device *ubi, int pnum)
+static int prot_queue_del(struct ubi_device *ubi, int pnum)
{
- struct rb_node *p;
- struct ubi_wl_prot_entry *pe = NULL;
-
- p = ubi->prot.pnum.rb_node;
- while (p) {
-
- pe = rb_entry(p, struct ubi_wl_prot_entry, rb_pnum);
-
- if (pnum == pe->e->pnum)
- goto found;
+ struct ubi_wl_entry *e;
- if (pnum < pe->e->pnum)
- p = p->rb_left;
- else
- p = p->rb_right;
- }
+ e = ubi->lookuptbl[pnum];
+ if (!e)
+ return -ENODEV;
- return -ENODEV;
+ if (paranoid_check_in_pq(ubi, e))
+ return -ENODEV;
-found:
- ubi_assert(pe->e->pnum == pnum);
- rb_erase(&pe->rb_aec, &ubi->prot.aec);
- rb_erase(&pe->rb_pnum, &ubi->prot.pnum);
- kfree(pe);
+ list_del(&e->u.list);
+ dbg_wl("deleted PEB %d from the protection queue", e->pnum);
return 0;
}
@@ -632,47 +546,47 @@ out_free:
}
/**
- * check_protection_over - check if it is time to stop protecting some PEBs.
+ * serve_prot_queue - check if it is time to stop protecting PEBs.
* @ubi: UBI device description object
*
- * This function is called after each erase operation, when the absolute erase
- * counter is incremented, to check if some physical eraseblock have not to be
- * protected any longer. These physical eraseblocks are moved from the
- * protection trees to the used tree.
+ * This function is called after each erase operation and removes PEBs from the
+ * tail of the protection queue. These PEBs have been protected for long enough
+ * and should be moved to the used tree.
*/
-static void check_protection_over(struct ubi_device *ubi)
+static void serve_prot_queue(struct ubi_device *ubi)
{
- struct ubi_wl_prot_entry *pe;
+ struct ubi_wl_entry *e, *tmp;
+ int count;
/*
* There may be several protected physical eraseblock to remove,
* process them all.
*/
- while (1) {
- spin_lock(&ubi->wl_lock);
- if (!ubi->prot.aec.rb_node) {
- spin_unlock(&ubi->wl_lock);
- break;
- }
-
- pe = rb_entry(rb_first(&ubi->prot.aec),
- struct ubi_wl_prot_entry, rb_aec);
+repeat:
+ count = 0;
+ spin_lock(&ubi->wl_lock);
+ list_for_each_entry_safe(e, tmp, &ubi->pq[ubi->pq_head], u.list) {
+ dbg_wl("PEB %d EC %d protection over, move to used tree",
+ e->pnum, e->ec);
- if (pe->abs_ec > ubi->abs_ec) {
+ list_del(&e->u.list);
+ wl_tree_add(e, &ubi->used);
+ if (count++ > 32) {
+ /*
+ * Let's be nice and avoid holding the spinlock for
+ * too long.
+ */
spin_unlock(&ubi->wl_lock);
- break;
+ cond_resched();
+ goto repeat;
}
-
- dbg_wl("PEB %d protection over, abs_ec %llu, PEB abs_ec %llu",
- pe->e->pnum, ubi->abs_ec, pe->abs_ec);
- rb_erase(&pe->rb_aec, &ubi->prot.aec);
- rb_erase(&pe->rb_pnum, &ubi->prot.pnum);
- wl_tree_add(pe->e, &ubi->used);
- spin_unlock(&ubi->wl_lock);
-
- kfree(pe);
- cond_resched();
}
+
+ ubi->pq_head += 1;
+ if (ubi->pq_head == UBI_PROT_QUEUE_LEN)
+ ubi->pq_head = 0;
+ ubi_assert(ubi->pq_head >= 0 && ubi->pq_head < UBI_PROT_QUEUE_LEN);
+ spin_unlock(&ubi->wl_lock);
}
/**
@@ -680,8 +594,8 @@ static void check_protection_over(struct ubi_device *ubi)
* @ubi: UBI device description object
* @wrk: the work to schedule
*
- * This function enqueues a work defined by @wrk to the tail of the pending
- * works list.
+ * This function adds a work defined by @wrk to the tail of the pending works
+ * list.
*/
static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
{
@@ -739,13 +653,11 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
int cancel)
{
- int err, put = 0, scrubbing = 0, protect = 0;
- struct ubi_wl_prot_entry *uninitialized_var(pe);
+ int err, scrubbing = 0, torture = 0;
struct ubi_wl_entry *e1, *e2;
struct ubi_vid_hdr *vid_hdr;
kfree(wrk);
-
if (cancel)
return 0;
@@ -781,7 +693,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
* highly worn-out free physical eraseblock. If the erase
* counters differ much enough, start wear-leveling.
*/
- e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, rb);
+ e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb);
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD)) {
@@ -790,21 +702,21 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
goto out_cancel;
}
paranoid_check_in_wl_tree(e1, &ubi->used);
- rb_erase(&e1->rb, &ubi->used);
+ rb_erase(&e1->u.rb, &ubi->used);
dbg_wl("move PEB %d EC %d to PEB %d EC %d",
e1->pnum, e1->ec, e2->pnum, e2->ec);
} else {
/* Perform scrubbing */
scrubbing = 1;
- e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, rb);
+ e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
paranoid_check_in_wl_tree(e1, &ubi->scrub);
- rb_erase(&e1->rb, &ubi->scrub);
+ rb_erase(&e1->u.rb, &ubi->scrub);
dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
}
paranoid_check_in_wl_tree(e2, &ubi->free);
- rb_erase(&e2->rb, &ubi->free);
+ rb_erase(&e2->u.rb, &ubi->free);
ubi->move_from = e1;
ubi->move_to = e2;
spin_unlock(&ubi->wl_lock);
@@ -844,46 +756,67 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
err = ubi_eba_copy_leb(ubi, e1->pnum, e2->pnum, vid_hdr);
if (err) {
-
+ if (err == -EAGAIN)
+ goto out_not_moved;
if (err < 0)
goto out_error;
- if (err == 1)
+ if (err == 2) {
+ /* Target PEB write error, torture it */
+ torture = 1;
goto out_not_moved;
+ }
/*
- * For some reason the LEB was not moved - it might be because
- * the volume is being deleted. We should prevent this PEB from
- * being selected for wear-levelling movement for some "time",
- * so put it to the protection tree.
+ * The LEB has not been moved because the volume is being
+ * deleted or the PEB has been put meanwhile. We should prevent
+ * this PEB from being selected for wear-leveling movement
+ * again, so put it to the protection queue.
*/
- dbg_wl("cancelled moving PEB %d", e1->pnum);
- pe = kmalloc(sizeof(struct ubi_wl_prot_entry), GFP_NOFS);
- if (!pe) {
- err = -ENOMEM;
- goto out_error;
- }
+ dbg_wl("canceled moving PEB %d", e1->pnum);
+ ubi_assert(err == 1);
+
+ ubi_free_vid_hdr(ubi, vid_hdr);
+ vid_hdr = NULL;
+
+ spin_lock(&ubi->wl_lock);
+ prot_queue_add(ubi, e1);
+ ubi_assert(!ubi->move_to_put);
+ ubi->move_from = ubi->move_to = NULL;
+ ubi->wl_scheduled = 0;
+ spin_unlock(&ubi->wl_lock);
- protect = 1;
+ e1 = NULL;
+ err = schedule_erase(ubi, e2, 0);
+ if (err)
+ goto out_error;
+ mutex_unlock(&ubi->move_mutex);
+ return 0;
}
+ /* The PEB has been successfully moved */
ubi_free_vid_hdr(ubi, vid_hdr);
- if (scrubbing && !protect)
+ vid_hdr = NULL;
+ if (scrubbing)
ubi_msg("scrubbed PEB %d, data moved to PEB %d",
e1->pnum, e2->pnum);
spin_lock(&ubi->wl_lock);
- if (protect)
- prot_tree_add(ubi, e1, pe, protect);
- if (!ubi->move_to_put)
+ if (!ubi->move_to_put) {
wl_tree_add(e2, &ubi->used);
- else
- put = 1;
+ e2 = NULL;
+ }
ubi->move_from = ubi->move_to = NULL;
ubi->move_to_put = ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock);
- if (put) {
+ err = schedule_erase(ubi, e1, 0);
+ if (err) {
+ e1 = NULL;
+ goto out_error;
+ }
+
+ if (e2) {
/*
* Well, the target PEB was put meanwhile, schedule it for
* erasure.
@@ -894,13 +827,6 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
goto out_error;
}
- if (!protect) {
- err = schedule_erase(ubi, e1, 0);
- if (err)
- goto out_error;
- }
-
-
dbg_wl("done");
mutex_unlock(&ubi->move_mutex);
return 0;
@@ -908,20 +834,24 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
/*
* For some reasons the LEB was not moved, might be an error, might be
* something else. @e1 was not changed, so return it back. @e2 might
- * be changed, schedule it for erasure.
+ * have been changed, schedule it for erasure.
*/
out_not_moved:
+ dbg_wl("canceled moving PEB %d", e1->pnum);
ubi_free_vid_hdr(ubi, vid_hdr);
+ vid_hdr = NULL;
spin_lock(&ubi->wl_lock);
if (scrubbing)
wl_tree_add(e1, &ubi->scrub);
else
wl_tree_add(e1, &ubi->used);
+ ubi_assert(!ubi->move_to_put);
ubi->move_from = ubi->move_to = NULL;
- ubi->move_to_put = ubi->wl_scheduled = 0;
+ ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock);
- err = schedule_erase(ubi, e2, 0);
+ e1 = NULL;
+ err = schedule_erase(ubi, e2, torture);
if (err)
goto out_error;
@@ -938,8 +868,10 @@ out_error:
ubi->move_to_put = ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock);
- kmem_cache_free(ubi_wl_entry_slab, e1);
- kmem_cache_free(ubi_wl_entry_slab, e2);
+ if (e1)
+ kmem_cache_free(ubi_wl_entry_slab, e1);
+ if (e2)
+ kmem_cache_free(ubi_wl_entry_slab, e2);
ubi_ro_mode(ubi);
mutex_unlock(&ubi->move_mutex);
@@ -985,10 +917,10 @@ static int ensure_wear_leveling(struct ubi_device *ubi)
/*
* We schedule wear-leveling only if the difference between the
* lowest erase counter of used physical eraseblocks and a high
- * erase counter of free physical eraseblocks is greater then
+ * erase counter of free physical eraseblocks is greater than
* %UBI_WL_THRESHOLD.
*/
- e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, rb);
+ e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb);
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
if (!(e2->ec - e1->ec >= UBI_WL_THRESHOLD))
@@ -1050,7 +982,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
kfree(wl_wrk);
spin_lock(&ubi->wl_lock);
- ubi->abs_ec += 1;
wl_tree_add(e, &ubi->free);
spin_unlock(&ubi->wl_lock);
@@ -1058,7 +989,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
* One more erase operation has happened, take care about
* protected physical eraseblocks.
*/
- check_protection_over(ubi);
+ serve_prot_queue(ubi);
/* And take care about wear-leveling */
err = ensure_wear_leveling(ubi);
@@ -1190,12 +1121,12 @@ retry:
} else {
if (in_wl_tree(e, &ubi->used)) {
paranoid_check_in_wl_tree(e, &ubi->used);
- rb_erase(&e->rb, &ubi->used);
+ rb_erase(&e->u.rb, &ubi->used);
} else if (in_wl_tree(e, &ubi->scrub)) {
paranoid_check_in_wl_tree(e, &ubi->scrub);
- rb_erase(&e->rb, &ubi->scrub);
+ rb_erase(&e->u.rb, &ubi->scrub);
} else {
- err = prot_tree_del(ubi, e->pnum);
+ err = prot_queue_del(ubi, e->pnum);
if (err) {
ubi_err("PEB %d not found", pnum);
ubi_ro_mode(ubi);
@@ -1255,11 +1186,11 @@ retry:
if (in_wl_tree(e, &ubi->used)) {
paranoid_check_in_wl_tree(e, &ubi->used);
- rb_erase(&e->rb, &ubi->used);
+ rb_erase(&e->u.rb, &ubi->used);
} else {
int err;
- err = prot_tree_del(ubi, e->pnum);
+ err = prot_queue_del(ubi, e->pnum);
if (err) {
ubi_err("PEB %d not found", pnum);
ubi_ro_mode(ubi);
@@ -1290,7 +1221,7 @@ int ubi_wl_flush(struct ubi_device *ubi)
int err;
/*
- * Erase while the pending works queue is not empty, but not more then
+ * Erase while the pending works queue is not empty, but not more than
* the number of currently pending works.
*/
dbg_wl("flush (%d pending works)", ubi->works_count);
@@ -1308,7 +1239,7 @@ int ubi_wl_flush(struct ubi_device *ubi)
up_write(&ubi->work_sem);
/*
- * And in case last was the WL worker and it cancelled the LEB
+ * And in case last was the WL worker and it canceled the LEB
* movement, flush again.
*/
while (ubi->works_count) {
@@ -1337,11 +1268,11 @@ static void tree_destroy(struct rb_root *root)
else if (rb->rb_right)
rb = rb->rb_right;
else {
- e = rb_entry(rb, struct ubi_wl_entry, rb);
+ e = rb_entry(rb, struct ubi_wl_entry, u.rb);
rb = rb_parent(rb);
if (rb) {
- if (rb->rb_left == &e->rb)
+ if (rb->rb_left == &e->u.rb)
rb->rb_left = NULL;
else
rb->rb_right = NULL;
@@ -1436,15 +1367,13 @@ static void cancel_pending(struct ubi_device *ubi)
*/
int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
{
- int err;
+ int err, i;
struct rb_node *rb1, *rb2;
struct ubi_scan_volume *sv;
struct ubi_scan_leb *seb, *tmp;
struct ubi_wl_entry *e;
-
ubi->used = ubi->free = ubi->scrub = RB_ROOT;
- ubi->prot.pnum = ubi->prot.aec = RB_ROOT;
spin_lock_init(&ubi->wl_lock);
mutex_init(&ubi->move_mutex);
init_rwsem(&ubi->work_sem);
@@ -1458,6 +1387,10 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (!ubi->lookuptbl)
return err;
+ for (i = 0; i < UBI_PROT_QUEUE_LEN; i++)
+ INIT_LIST_HEAD(&ubi->pq[i]);
+ ubi->pq_head = 0;
+
list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
cond_resched();
@@ -1552,33 +1485,18 @@ out_free:
}
/**
- * protection_trees_destroy - destroy the protection RB-trees.
+ * protection_queue_destroy - destroy the protection queue.
* @ubi: UBI device description object
*/
-static void protection_trees_destroy(struct ubi_device *ubi)
+static void protection_queue_destroy(struct ubi_device *ubi)
{
- struct rb_node *rb;
- struct ubi_wl_prot_entry *pe;
-
- rb = ubi->prot.aec.rb_node;
- while (rb) {
- if (rb->rb_left)
- rb = rb->rb_left;
- else if (rb->rb_right)
- rb = rb->rb_right;
- else {
- pe = rb_entry(rb, struct ubi_wl_prot_entry, rb_aec);
-
- rb = rb_parent(rb);
- if (rb) {
- if (rb->rb_left == &pe->rb_aec)
- rb->rb_left = NULL;
- else
- rb->rb_right = NULL;
- }
+ int i;
+ struct ubi_wl_entry *e, *tmp;
- kmem_cache_free(ubi_wl_entry_slab, pe->e);
- kfree(pe);
+ for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) {
+ list_for_each_entry_safe(e, tmp, &ubi->pq[i], u.list) {
+ list_del(&e->u.list);
+ kmem_cache_free(ubi_wl_entry_slab, e);
}
}
}
@@ -1591,7 +1509,7 @@ void ubi_wl_close(struct ubi_device *ubi)
{
dbg_wl("close the WL sub-system");
cancel_pending(ubi);
- protection_trees_destroy(ubi);
+ protection_queue_destroy(ubi);
tree_destroy(&ubi->used);
tree_destroy(&ubi->free);
tree_destroy(&ubi->scrub);
@@ -1661,4 +1579,27 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
return 1;
}
+/**
+ * paranoid_check_in_pq - check if wear-leveling entry is in the protection
+ * queue.
+ * @ubi: UBI device description object
+ * @e: the wear-leveling entry to check
+ *
+ * This function returns zero if @e is in @ubi->pq and %1 if it is not.
+ */
+static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
+{
+ struct ubi_wl_entry *p;
+ int i;
+
+ for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
+ list_for_each_entry(p, &ubi->pq[i], u.list)
+ if (p == e)
+ return 0;
+
+ ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
+ e->pnum, e->ec);
+ ubi_dbg_dump_stack();
+ return 1;
+}
#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index c092c3929224..5b91a85fe107 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -177,6 +177,7 @@ static const struct net_device_ops el2_netdev_ops = {
.ndo_get_stats = eip_get_stats,
.ndo_set_multicast_list = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = eip_poll,
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 665e7fdf27a1..cdbbb6226fc5 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -3109,6 +3109,8 @@ static void acpi_set_WOL(struct net_device *dev)
struct vortex_private *vp = netdev_priv(dev);
void __iomem *ioaddr = vp->ioaddr;
+ device_set_wakeup_enable(vp->gendev, vp->enable_wol);
+
if (vp->enable_wol) {
/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
EL3WINDOW(7);
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index dd7ac8290aec..4e19ae3ce6be 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1821,6 +1821,7 @@ static const struct net_device_ops cp_netdev_ops = {
.ndo_open = cp_open,
.ndo_stop = cp_close,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_set_multicast_list = cp_set_rx_mode,
.ndo_get_stats = cp_get_stats,
.ndo_do_ioctl = cp_ioctl,
@@ -1832,6 +1833,7 @@ static const struct net_device_ops cp_netdev_ops = {
#ifdef BROKEN
.ndo_change_mtu = cp_change_mtu,
#endif
+
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cp_poll_controller,
#endif
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index fe370f805793..a5b24202d564 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -917,6 +917,7 @@ static const struct net_device_ops rtl8139_netdev_ops = {
.ndo_stop = rtl8139_close,
.ndo_get_stats = rtl8139_get_stats,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_start_xmit = rtl8139_start_xmit,
.ndo_set_multicast_list = rtl8139_set_rx_mode,
.ndo_do_ioctl = netdev_ioctl,
@@ -924,7 +925,6 @@ static const struct net_device_ops rtl8139_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = rtl8139_poll_controller,
#endif
-
};
static int __devinit rtl8139_init_one (struct pci_dev *pdev,
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index fbe609a51e02..ec3e22e6306f 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -63,6 +63,7 @@ const struct net_device_ops ei_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c
index ee70b358a816..da863c91d1d0 100644
--- a/drivers/net/8390p.c
+++ b/drivers/net/8390p.c
@@ -68,6 +68,7 @@ const struct net_device_ops eip_netdev_ops = {
.ndo_get_stats = eip_get_stats,
.ndo_set_multicast_list = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = eip_poll,
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9a18270c1081..6bdfd47d679d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -830,7 +830,7 @@ config ULTRA32
config BFIN_MAC
tristate "Blackfin on-chip MAC support"
- depends on NET_ETHERNET && (BF526 || BF527 || BF536 || BF537)
+ depends on NET_ETHERNET && (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
select CRC32
select MII
select PHYLIB
@@ -1600,7 +1600,7 @@ config 8139_OLD_RX_RESET
old RX-reset behavior. If unsure, say N.
config R6040
- tristate "RDC R6040 Fast Ethernet Adapter support (EXPERIMENTAL)"
+ tristate "RDC R6040 Fast Ethernet Adapter support"
depends on NET_PCI && PCI
select CRC32
select MII
@@ -1829,7 +1829,7 @@ config 68360_ENET
config FEC
bool "FEC ethernet controller (of ColdFire CPUs)"
- depends on M523x || M527x || M5272 || M528x || M520x
+ depends on M523x || M527x || M5272 || M528x || M520x || M532x
help
Say Y here if you want to use the built-in 10/100 Fast ethernet
controller on some Motorola ColdFire processors.
@@ -2614,6 +2614,8 @@ source "drivers/net/tokenring/Kconfig"
source "drivers/net/wireless/Kconfig"
+source "drivers/net/wimax/Kconfig"
+
source "drivers/net/usb/Kconfig"
source "drivers/net/pcmcia/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index e5c34b464211..a3c5c002f224 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -263,3 +263,4 @@ obj-$(CONFIG_NIU) += niu.o
obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
obj-$(CONFIG_SFC) += sfc/
+obj-$(CONFIG_WIMAX) += wimax/
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 517fce48d94a..9589d620639d 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -66,6 +66,7 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/sockios.h>
+#include <linux/firmware.h>
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#include <linux/if_vlan.h>
@@ -186,8 +187,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
#define MAX_RODATA_LEN 8*1024
#define MAX_DATA_LEN 2*1024
-#include "acenic_firmware.h"
-
#ifndef tigon2FwReleaseLocal
#define tigon2FwReleaseLocal 0
#endif
@@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
+#ifndef CONFIG_ACENIC_OMIT_TIGON_I
+MODULE_FIRMWARE("acenic/tg1.bin");
+#endif
+MODULE_FIRMWARE("acenic/tg2.bin");
module_param_array_named(link, link_state, int, NULL, 0);
module_param_array(trace, int, NULL, 0);
@@ -457,6 +460,7 @@ static const struct net_device_ops ace_netdev_ops = {
.ndo_get_stats = ace_get_stats,
.ndo_start_xmit = ace_start_xmit,
.ndo_set_multicast_list = ace_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = ace_set_mac_addr,
.ndo_change_mtu = ace_change_mtu,
#if ACENIC_DO_VLAN
@@ -943,8 +947,8 @@ static int __devinit ace_init(struct net_device *dev)
case 4:
case 5:
printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ",
- tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor,
- tigonFwReleaseFix);
+ tig_ver, ap->firmware_major, ap->firmware_minor,
+ ap->firmware_fix);
writel(0, &regs->LocalCtrl);
ap->version = 1;
ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES;
@@ -952,8 +956,8 @@ static int __devinit ace_init(struct net_device *dev)
#endif
case 6:
printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
- tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor,
- tigon2FwReleaseFix);
+ tig_ver, ap->firmware_major, ap->firmware_minor,
+ ap->firmware_fix);
writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
readl(&regs->CpuBCtrl); /* PCI write posting */
/*
@@ -1205,7 +1209,9 @@ static int __devinit ace_init(struct net_device *dev)
memset(ap->info, 0, sizeof(struct ace_info));
memset(ap->skb, 0, sizeof(struct ace_skb));
- ace_load_firmware(dev);
+ if (ace_load_firmware(dev))
+ goto init_error;
+
ap->fw_running = 0;
tmp_ptr = ap->info_dma;
@@ -1441,10 +1447,7 @@ static int __devinit ace_init(struct net_device *dev)
if (ap->version >= 2)
writel(tmp, &regs->TuneFastLink);
- if (ACE_IS_TIGON_I(ap))
- writel(tigonFwStartAddr, &regs->Pc);
- if (ap->version == 2)
- writel(tigon2FwStartAddr, &regs->Pc);
+ writel(ap->firmware_start, &regs->Pc);
writel(0, &regs->Mb0Lo);
@@ -2761,8 +2764,8 @@ static void ace_get_drvinfo(struct net_device *dev,
strlcpy(info->driver, "acenic", sizeof(info->driver));
snprintf(info->version, sizeof(info->version), "%i.%i.%i",
- tigonFwReleaseMajor, tigonFwReleaseMinor,
- tigonFwReleaseFix);
+ ap->firmware_major, ap->firmware_minor,
+ ap->firmware_fix);
if (ap->pdev)
strlcpy(info->bus_info, pci_name(ap->pdev),
@@ -2869,11 +2872,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev)
}
-static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
- u32 dest, int size)
+static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+ u32 dest, int size)
{
void __iomem *tdest;
- u32 *wsrc;
short tsize, i;
if (size <= 0)
@@ -2885,20 +2887,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src,
tdest = (void __iomem *) &regs->Window +
(dest & (ACE_WINDOW_SIZE - 1));
writel(dest & ~(ACE_WINDOW_SIZE - 1), &regs->WinBase);
- /*
- * This requires byte swapping on big endian, however
- * writel does that for us
- */
- wsrc = src;
for (i = 0; i < (tsize / 4); i++) {
- writel(wsrc[i], tdest + i*4);
+ /* Firmware is big-endian */
+ writel(be32_to_cpup(src), tdest);
+ src++;
+ tdest += 4;
+ dest += 4;
+ size -= 4;
}
- dest += tsize;
- src += tsize;
- size -= tsize;
}
-
- return;
}
@@ -2937,8 +2934,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz
*/
static int __devinit ace_load_firmware(struct net_device *dev)
{
+ const struct firmware *fw;
+ const char *fw_name = "acenic/tg2.bin";
struct ace_private *ap = netdev_priv(dev);
struct ace_regs __iomem *regs = ap->regs;
+ const __be32 *fw_data;
+ u32 load_addr;
+ int ret;
if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
printk(KERN_ERR "%s: trying to download firmware while the "
@@ -2946,28 +2948,52 @@ static int __devinit ace_load_firmware(struct net_device *dev)
return -EFAULT;
}
+ if (ACE_IS_TIGON_I(ap))
+ fw_name = "acenic/tg1.bin";
+
+ ret = request_firmware(&fw, fw_name, &ap->pdev->dev);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+ ap->name, fw_name);
+ return ret;
+ }
+
+ fw_data = (void *)fw->data;
+
+ /* Firmware blob starts with version numbers, followed by
+ load and start address. Remainder is the blob to be loaded
+ contiguously from load address. We don't bother to represent
+ the BSS/SBSS sections any more, since we were clearing the
+ whole thing anyway. */
+ ap->firmware_major = fw->data[0];
+ ap->firmware_minor = fw->data[1];
+ ap->firmware_fix = fw->data[2];
+
+ ap->firmware_start = be32_to_cpu(fw_data[1]);
+ if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) {
+ printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+ ap->name, ap->firmware_start, fw_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ load_addr = be32_to_cpu(fw_data[2]);
+ if (load_addr < 0x4000 || load_addr >= 0x80000) {
+ printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n",
+ ap->name, load_addr, fw_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
/*
- * Do not try to clear more than 512KB or we end up seeing
- * funny things on NICs with only 512KB SRAM
+ * Do not try to clear more than 512KiB or we end up seeing
+ * funny things on NICs with only 512KiB SRAM
*/
ace_clear(regs, 0x2000, 0x80000-0x2000);
- if (ACE_IS_TIGON_I(ap)) {
- ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen);
- ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen);
- ace_copy(regs, tigonFwRodata, tigonFwRodataAddr,
- tigonFwRodataLen);
- ace_clear(regs, tigonFwBssAddr, tigonFwBssLen);
- ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen);
- }else if (ap->version == 2) {
- ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen);
- ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen);
- ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen);
- ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr,
- tigon2FwRodataLen);
- ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen);
- }
-
- return 0;
+ ace_copy(regs, &fw_data[3], load_addr, fw->size-12);
+ out:
+ release_firmware(fw);
+ return ret;
}
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 4487f32759a4..c987c9b5a137 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -694,6 +694,10 @@ struct ace_private
u32 last_tx, last_std_rx, last_mini_rx;
#endif
int pci_using_dac;
+ u8 firmware_major;
+ u8 firmware_minor;
+ u8 firmware_fix;
+ u32 firmware_start;
};
diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h
deleted file mode 100644
index fd41f7887e27..000000000000
--- a/drivers/net/acenic_firmware.h
+++ /dev/null
@@ -1,9456 +0,0 @@
-/*
- * Declare these here even if Tigon I support is disabled to avoid
- * the compiler complaining about undefined symbols.
- */
-#define tigonFwReleaseMajor 0xc
-#define tigonFwReleaseMinor 0x4
-#define tigonFwReleaseFix 0xb
-#define tigonFwStartAddr 0x00004000
-#define tigonFwTextAddr 0x00004000
-#define tigonFwTextLen 0x11140
-#define tigonFwRodataAddr 0x00015140
-#define tigonFwRodataLen 0xac0
-#define tigonFwDataAddr 0x00015c20
-#define tigonFwDataLen 0x170
-#define tigonFwSbssAddr 0x00015d90
-#define tigonFwSbssLen 0x38
-#define tigonFwBssAddr 0x00015dd0
-#define tigonFwBssLen 0x2080
-#ifdef CONFIG_ACENIC_OMIT_TIGON_I
-#define tigonFwText NULL
-#define tigonFwData NULL
-#define tigonFwRodata NULL
-#else
-/* Generated by genfw.c */
-static u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = {
-0x10000003,
-0x0, 0xd, 0xd, 0x3c1d0001,
-0x8fbd5c54, 0x3a0f021, 0x3c100000, 0x26104000,
-0xc00100c, 0x0, 0xd, 0x27bdffd8,
-0x3c1cc000, 0x3c1b0013, 0x377bd800, 0xd021,
-0x3c170013, 0x36f75418, 0x2e02021, 0x340583e8,
-0xafbf0024, 0xc002488, 0xafb00020, 0xc0023e8,
-0x0, 0x3c040001, 0x248451a4, 0x24050001,
-0x2e03021, 0x3821, 0x3c100001, 0x26107e50,
-0xafb00010, 0xc002403, 0xafbb0014, 0x3c02000f,
-0x3442ffff, 0x2021024, 0x362102b, 0x10400009,
-0x24050003, 0x3c040001, 0x248451b0, 0x2003021,
-0x3603821, 0x3c020010, 0xafa20010, 0xc002403,
-0xafa00014, 0x2021, 0x3405c000, 0x3c010001,
-0x370821, 0xa02083b0, 0x3c010001, 0x370821,
-0xa02083b2, 0x3c010001, 0x370821, 0xa02083b3,
-0x3c010001, 0x370821, 0xac2083b4, 0xa2e004d8,
-0x418c0, 0x24840001, 0x771021, 0xac40727c,
-0x771021, 0xac407280, 0x2e31021, 0xa445727c,
-0x2c820020, 0x1440fff7, 0x418c0, 0x2021,
-0x3405c000, 0x418c0, 0x24840001, 0x771021,
-0xac40737c, 0x771021, 0xac407380, 0x2e31021,
-0xa445737c, 0x2c820080, 0x5440fff7, 0x418c0,
-0xaf800054, 0xaf80011c, 0x8f820044, 0x34420040,
-0xaf820044, 0x8f820044, 0x34420020, 0xaf820044,
-0x8f420218, 0x30420002, 0x10400009, 0x0,
-0x8f420220, 0x3c030002, 0x34630004, 0x431025,
-0xaee204c4, 0x8f42021c, 0x8001074, 0x34420004,
-0x8f420220, 0x3c030002, 0x34630006, 0x431025,
-0xaee204c4, 0x8f42021c, 0x34420006, 0xaee204cc,
-0x8f420218, 0x30420010, 0x1040000a, 0x0,
-0x8f42021c, 0x34420004, 0xaee204c8, 0x8f420220,
-0x3c03000a, 0x34630004, 0x431025, 0x800108a,
-0xaee204c0, 0x8f420220, 0x3c03000a, 0x34630006,
-0x431025, 0xaee204c0, 0x8f42021c, 0x34420006,
-0xaee204c8, 0x8f420218, 0x30420200, 0x10400003,
-0x24020001, 0x8001091, 0xa2e27248, 0xa2e07248,
-0x24020001, 0xaf8200a0, 0xaf8200b0, 0x8f830054,
-0x8f820054, 0x8001099, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x0,
-0xaf800044, 0x8f420208, 0x8f43020c, 0xaee20010,
-0xaee30014, 0x8ee40010, 0x8ee50014, 0x26e20030,
-0xaee20028, 0x24020490, 0xaee20018, 0xaf840090,
-0xaf850094, 0x8ee20028, 0xaf8200b4, 0x96e2001a,
-0xaf82009c, 0x8f8200b0, 0x8ee304cc, 0x431025,
-0xaf8200b0, 0x8f8200b0, 0x30420004, 0x1440fffd,
-0x0, 0x8ee20450, 0x8ee30454, 0xaee304fc,
-0x8ee204fc, 0x2442e000, 0x2c422001, 0x1440000d,
-0x26e40030, 0x8ee20450, 0x8ee30454, 0x3c040001,
-0x248451bc, 0x3c050001, 0xafa00010, 0xafa00014,
-0x8ee704fc, 0x34a5f000, 0xc002403, 0x603021,
-0x26e40030, 0xc002488, 0x24050400, 0x27440080,
-0xc002488, 0x24050080, 0x26e4777c, 0xc002488,
-0x24050400, 0x8f42025c, 0x26e40094, 0xaee20060,
-0x8f420260, 0x27450200, 0x24060008, 0xaee20068,
-0x24020006, 0xc00249a, 0xaee20064, 0x3c023b9a,
-0x3442ca00, 0x2021, 0x24030002, 0xaee30074,
-0xaee30070, 0xaee2006c, 0x240203e8, 0xaee20104,
-0x24020001, 0xaee30100, 0xaee2010c, 0x3c030001,
-0x641821, 0x90635c20, 0x2e41021, 0x24840001,
-0xa043009c, 0x2c82000f, 0x1440fff8, 0x0,
-0x8f820040, 0x2e41821, 0x24840001, 0x21702,
-0x24420030, 0xa062009c, 0x2e41021, 0xa040009c,
-0x96e2046a, 0x30420003, 0x14400009, 0x0,
-0x96e2047a, 0x30420003, 0x50400131, 0x3c030800,
-0x96e2046a, 0x30420003, 0x1040002a, 0x3c020700,
-0x96e2047a, 0x30420003, 0x10400026, 0x3c020700,
-0x96e3047a, 0x96e2046a, 0x14620022, 0x3c020700,
-0x8ee204c0, 0x24030001, 0xa2e34e20, 0x34420e00,
-0xaee204c0, 0x8f420218, 0x30420100, 0x10400005,
-0x0, 0x3c020001, 0x2442e168, 0x800111d,
-0x21100, 0x3c020001, 0x2442d35c, 0x21100,
-0x21182, 0x3c030800, 0x431025, 0x3c010001,
-0xac221238, 0x3c020001, 0x2442f680, 0x21100,
-0x21182, 0x3c030800, 0x431025, 0x3c010001,
-0xac221278, 0x8ee20000, 0x34424000, 0x8001238,
-0xaee20000, 0x34423000, 0xafa20018, 0x8ee20608,
-0x8f430228, 0x24420001, 0x304900ff, 0x512300e2,
-0xafa00010, 0x8ee20608, 0x210c0, 0x571021,
-0x8fa30018, 0x8fa4001c, 0xac43060c, 0xac440610,
-0x8f870120, 0x27623800, 0x24e80020, 0x102102b,
-0x50400001, 0x27683000, 0x8f820128, 0x11020004,
-0x0, 0x8f820124, 0x15020007, 0x1021,
-0x8ee201a4, 0x3021, 0x24420001, 0xaee201a4,
-0x80011a0, 0x8ee201a4, 0x8ee40608, 0x420c0,
-0x801821, 0x8ee40430, 0x8ee50434, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee30608, 0x24020008, 0xa4e2000e,
-0x2402000d, 0xace20018, 0xace9001c, 0x318c0,
-0x2463060c, 0x2e31021, 0xace20008, 0x8ee204c4,
-0xace20010, 0xaf880120, 0x92e24e20, 0x14400037,
-0x24060001, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x24030040, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee54e30, 0x24420001, 0x10430007,
-0x0, 0x8ee24e34, 0x24420001, 0x10a20005,
-0x0, 0x800118a, 0x0, 0x14a00005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x80011a0, 0x0, 0x8ee24e30,
-0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x24020007,
-0xac820000, 0x24020001, 0xac820004, 0x54c0000c,
-0xaee90608, 0x3c040001, 0x248451c8, 0xafa00010,
-0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
-0xc002403, 0x34a5f000, 0x8001223, 0x0,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
-0x0, 0x8f820124, 0x14c20007, 0x0,
-0x8ee201a4, 0x3021, 0x24420001, 0xaee201a4,
-0x8001207, 0x8ee201a4, 0x8ee20608, 0xac62001c,
-0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008,
-0x24020008, 0xa462000e, 0x24020011, 0xac620018,
-0xac640000, 0xac650004, 0x8ee204c4, 0xac620010,
-0xaf860120, 0x92e24e20, 0x14400037, 0x24060001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c830000, 0x24020012, 0x1462001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee54e30, 0x24420001, 0x10430007, 0x0,
-0x8ee24e34, 0x24420001, 0x10a20005, 0x0,
-0x80011f1, 0x0, 0x14a00005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x8001207, 0x0, 0x8ee24e30, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020012, 0xac820000,
-0x24020001, 0xac820004, 0x14c0001b, 0x0,
-0x3c040001, 0x248451d0, 0xafa00010, 0xafa00014,
-0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
-0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0,
-0x8001223, 0x8ee201b0, 0x3c040001, 0x248451dc,
-0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
-0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001,
-0xaee201ac, 0x8ee201ac, 0x8ee20160, 0x3c040001,
-0x248451e8, 0x3405f001, 0x24420001, 0xaee20160,
-0x8ee20160, 0x3021, 0x3821, 0xafa00010,
-0xc002403, 0xafa00014, 0x8001238, 0x0,
-0x3c020001, 0x2442f5a8, 0x21100, 0x21182,
-0x431025, 0x3c010001, 0xac221278, 0x96e2045a,
-0x30420003, 0x10400025, 0x3c050fff, 0x8ee204c8,
-0x34a5ffff, 0x34420a00, 0xaee204c8, 0x8ee304c8,
-0x3c040001, 0x248451f4, 0x24020001, 0xa2e204ec,
-0xa2e204ed, 0x3c020002, 0x621825, 0x3c020001,
-0x2442a390, 0x451024, 0x21082, 0xaee304c8,
-0x3c030800, 0x431025, 0x3c010001, 0xac221220,
-0x3c020001, 0x2442add4, 0x451024, 0x21082,
-0x431025, 0x3c010001, 0xac221280, 0x96e6045a,
-0x3821, 0x24050011, 0xafa00010, 0xc002403,
-0xafa00014, 0x8001268, 0x0, 0x3c020001,
-0x2442a9d4, 0x21100, 0x21182, 0x3c030800,
-0x431025, 0x3c010001, 0xac221280, 0x96e2046a,
-0x30420010, 0x14400009, 0x0, 0x96e2047a,
-0x30420010, 0x10400112, 0x0, 0x96e2046a,
-0x30420010, 0x10400005, 0x3c020700, 0x96e2047a,
-0x30420010, 0x14400102, 0x3c020700, 0x34423000,
-0xafa20018, 0x8ee20608, 0x8f430228, 0x24420001,
-0x304900ff, 0x512300e2, 0xafa00010, 0x8ee20608,
-0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c,
-0xac43060c, 0xac440610, 0x8f870120, 0x27623800,
-0x24e80020, 0x102102b, 0x50400001, 0x27683000,
-0x8f820128, 0x11020004, 0x0, 0x8f820124,
-0x15020007, 0x1021, 0x8ee201a4, 0x3021,
-0x24420001, 0xaee201a4, 0x80012ea, 0x8ee201a4,
-0x8ee40608, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xace40000, 0xace50004, 0x8ee30608,
-0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018,
-0xace9001c, 0x318c0, 0x2463060c, 0x2e31021,
-0xace20008, 0x8ee204c4, 0xace20010, 0xaf880120,
-0x92e24e20, 0x14400037, 0x24060001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c830000,
-0x24020007, 0x1462001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee54e30,
-0x24420001, 0x10430007, 0x0, 0x8ee24e34,
-0x24420001, 0x10a20005, 0x0, 0x80012d4,
-0x0, 0x14a00005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x80012ea,
-0x0, 0x8ee24e30, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x24020007, 0xac820000, 0x24020001,
-0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001,
-0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608,
-0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000,
-0x800136d, 0x0, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x10c20004, 0x0, 0x8f820124,
-0x14c20007, 0x0, 0x8ee201a4, 0x3021,
-0x24420001, 0xaee201a4, 0x8001351, 0x8ee201a4,
-0x8ee20608, 0xac62001c, 0x8ee404a0, 0x8ee504a4,
-0x2462001c, 0xac620008, 0x24020008, 0xa462000e,
-0x24020011, 0xac620018, 0xac640000, 0xac650004,
-0x8ee204c4, 0xac620010, 0xaf860120, 0x92e24e20,
-0x14400037, 0x24060001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c830000, 0x24020012,
-0x1462001f, 0x0, 0x8ee34e30, 0x8ee24e34,
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e34, 0x8ee54e30, 0x24420001,
-0x10430007, 0x0, 0x8ee24e34, 0x24420001,
-0x10a20005, 0x0, 0x800133b, 0x0,
-0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x8001351, 0x0,
-0x8ee24e30, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x24020012, 0xac820000, 0x24020001, 0xac820004,
-0x14c0001b, 0x0, 0x3c040001, 0x248451d0,
-0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228,
-0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0,
-0x24420001, 0xaee201b0, 0x800136d, 0x8ee201b0,
-0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608,
-0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005,
-0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac,
-0x8ee20160, 0x3c040001, 0x248451e8, 0x3405f002,
-0x24420001, 0xaee20160, 0x8ee20160, 0x3021,
-0x3821, 0xafa00010, 0xc002403, 0xafa00014,
-0x96e6047a, 0x96e7046a, 0x3c040001, 0x24845200,
-0x24050012, 0xafa00010, 0xc002403, 0xafa00014,
-0xc004500, 0x0, 0xc002318, 0x0,
-0x3c060001, 0x34c63800, 0xaee00608, 0xaf400228,
-0xaf40022c, 0x96e30458, 0x8ee40000, 0x3c0512d8,
-0x34a5c358, 0x27623800, 0xaee27258, 0x27623800,
-0xaee27260, 0x27623800, 0xaee27264, 0x3661021,
-0xaee27270, 0x2402ffff, 0xaee004d4, 0xaee004e0,
-0xaee004e4, 0xaee004f0, 0xa2e004f4, 0xaee00e0c,
-0xaee00e18, 0xaee00e10, 0xaee00e14, 0xaee00e1c,
-0xaee0724c, 0xaee05244, 0xaee05240, 0xaee0523c,
-0xaee07250, 0xaee07254, 0xaee0725c, 0xaee07268,
-0xaee004d0, 0x2463ffff, 0x852025, 0xaee304f8,
-0xaee40000, 0xaf800060, 0xaf820064, 0x3c020100,
-0xafa20018, 0x8ee20608, 0x8f430228, 0x24420001,
-0x304900ff, 0x512300e2, 0xafa00010, 0x8ee20608,
-0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c,
-0xac43060c, 0xac440610, 0x8f870120, 0x27623800,
-0x24e80020, 0x102102b, 0x50400001, 0x27683000,
-0x8f820128, 0x11020004, 0x0, 0x8f820124,
-0x15020007, 0x1021, 0x8ee201a4, 0x3021,
-0x24420001, 0xaee201a4, 0x8001422, 0x8ee201a4,
-0x8ee40608, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xace40000, 0xace50004, 0x8ee30608,
-0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018,
-0xace9001c, 0x318c0, 0x2463060c, 0x2e31021,
-0xace20008, 0x8ee204c4, 0xace20010, 0xaf880120,
-0x92e24e20, 0x14400037, 0x24060001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c830000,
-0x24020007, 0x1462001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee54e30,
-0x24420001, 0x10430007, 0x0, 0x8ee24e34,
-0x24420001, 0x10a20005, 0x0, 0x800140c,
-0x0, 0x14a00005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8001422,
-0x0, 0x8ee24e30, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x24020007, 0xac820000, 0x24020001,
-0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001,
-0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608,
-0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000,
-0x80014a5, 0x0, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x10c20004, 0x0, 0x8f820124,
-0x14c20007, 0x0, 0x8ee201a4, 0x3021,
-0x24420001, 0xaee201a4, 0x8001489, 0x8ee201a4,
-0x8ee20608, 0xac62001c, 0x8ee404a0, 0x8ee504a4,
-0x2462001c, 0xac620008, 0x24020008, 0xa462000e,
-0x24020011, 0xac620018, 0xac640000, 0xac650004,
-0x8ee204c4, 0xac620010, 0xaf860120, 0x92e24e20,
-0x14400037, 0x24060001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c830000, 0x24020012,
-0x1462001f, 0x0, 0x8ee34e30, 0x8ee24e34,
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e34, 0x8ee54e30, 0x24420001,
-0x10430007, 0x0, 0x8ee24e34, 0x24420001,
-0x10a20005, 0x0, 0x8001473, 0x0,
-0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x8001489, 0x0,
-0x8ee24e30, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x24020012, 0xac820000, 0x24020001, 0xac820004,
-0x14c0001b, 0x0, 0x3c040001, 0x248451d0,
-0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228,
-0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0,
-0x24420001, 0xaee201b0, 0x80014a5, 0x8ee201b0,
-0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608,
-0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005,
-0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac,
-0x8ee20154, 0x24420001, 0xaee20154, 0xc0014dc,
-0x8ee20154, 0x8f8200a0, 0x30420004, 0x1440fffd,
-0x0, 0x8f820040, 0x30420001, 0x14400008,
-0x0, 0x8f430104, 0x24020001, 0x10620004,
-0x0, 0x8f420264, 0x10400006, 0x0,
-0x8ee2017c, 0x24420001, 0xaee2017c, 0x80014c5,
-0x8ee2017c, 0x8f820044, 0x34420004, 0xaf820044,
-0x8ee20178, 0x24420001, 0xaee20178, 0x8ee20178,
-0x8f8200d8, 0x8f8300d4, 0x431023, 0xaee2726c,
-0x8ee2726c, 0x1c400003, 0x3c030001, 0x431021,
-0xaee2726c, 0xc004064, 0x0, 0xc004440,
-0xaf800228, 0x8fbf0024, 0x8fb00020, 0x3e00008,
-0x27bd0028, 0x3e00008, 0x0, 0x3e00008,
-0x0, 0x0, 0x0, 0x2402002c,
-0xaf820050, 0xaee07274, 0x8f420238, 0xaee27278,
-0x8f820054, 0x24420067, 0xaf820058, 0xaee07b88,
-0xaee07b8c, 0xaee07b84, 0x3c010001, 0x370821,
-0xac2083bc, 0x3c010001, 0x370821, 0x3e00008,
-0xa02083b9, 0x27bdffd8, 0xafbf0024, 0xafb00020,
-0x8f820054, 0x3c030001, 0x8c635cd8, 0x24420067,
-0x1060000d, 0xaf820058, 0x3c020001, 0x571021,
-0x904283b8, 0x10400005, 0x3c030200, 0x3c010001,
-0x370821, 0x8001503, 0xa02083b8, 0x8ee20000,
-0x431025, 0xaee20000, 0x8f420218, 0x30420100,
-0x104000c6, 0x0, 0x8f8200b0, 0x30420004,
-0x104000c2, 0x0, 0x3c030001, 0x771821,
-0x8c6383d0, 0x8f820104, 0x146200b4, 0x0,
-0x3c030001, 0x771821, 0x8c6383d4, 0x8f8200b4,
-0x146200ae, 0x0, 0x8f8200b0, 0x3c030080,
-0x431024, 0x1040000d, 0x0, 0x8f82011c,
-0x34420002, 0xaf82011c, 0x8f8200b0, 0x2403fffb,
-0x431024, 0xaf8200b0, 0x8f82011c, 0x2403fffd,
-0x431024, 0x80015cc, 0xaf82011c, 0x3c030001,
-0x771821, 0x8c6383d0, 0x8f820104, 0x14620082,
-0x0, 0x3c030001, 0x771821, 0x8c6383d4,
-0x8f8200b4, 0x1462007c, 0x0, 0x3c070001,
-0xf73821, 0x8ce783d0, 0x8f8200b0, 0x3c040001,
-0x24845270, 0xafa00014, 0xafa20010, 0x8f8600b0,
-0x3c050005, 0xc002403, 0x34a50900, 0x8f82011c,
-0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0,
-0x34420001, 0xaf8200b0, 0xaf830104, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20006, 0x0, 0x8ee201a4,
-0x24420001, 0xaee201a4, 0x80015a0, 0x8ee201a4,
-0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008,
-0x24020400, 0xa462000e, 0x2402000f, 0xac620018,
-0xac60001c, 0xac640000, 0xac650004, 0x8ee204c4,
-0xac620010, 0xaf860120, 0x92e24e20, 0x14400037,
-0x0, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x24030040, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee54e30, 0x24420001, 0x10430007,
-0x0, 0x8ee24e34, 0x24420001, 0x10a20005,
-0x0, 0x800158a, 0x0, 0x14a00005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x80015a0, 0x0, 0x8ee24e30,
-0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x24020007,
-0xac820000, 0x24020001, 0xac820004, 0x8f82011c,
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201e4,
-0x3c070001, 0xf73821, 0x8ce783d0, 0x24420001,
-0xaee201e4, 0x8ee201e4, 0x3c040001, 0x2484527c,
-0x80015bd, 0xafa00010, 0x8f820104, 0x3c010001,
-0x370821, 0xac2283d0, 0x8f8200b4, 0x3c070001,
-0xf73821, 0x8ce783d0, 0x3c040001, 0x24845284,
-0x3c010001, 0x370821, 0xac2283d4, 0xafa00010,
-0xafa00014, 0x8f8600b0, 0x3c050005, 0xc002403,
-0x34a50900, 0x80015cc, 0x0, 0x8f820104,
-0x3c010001, 0x370821, 0xac2283d0, 0x8f8200b4,
-0x3c010001, 0x370821, 0xac2283d4, 0x8ee27274,
-0x92e304f4, 0x24420067, 0x14600006, 0xaee27274,
-0x8ee27274, 0x8f430234, 0x43102b, 0x1440007b,
-0x0, 0x8ee304e4, 0x8ee204f8, 0x14620004,
-0x0, 0x92e204f4, 0x50400074, 0xa2e004f4,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
-0x0, 0x8f820124, 0x14c20007, 0x0,
-0x8ee201a4, 0x8021, 0x24420001, 0xaee201a4,
-0x8001637, 0x8ee201a4, 0x8ee204e4, 0xac62001c,
-0x8ee404b0, 0x8ee504b4, 0x2462001c, 0xac620008,
-0x24020008, 0xa462000e, 0x24020011, 0xac620018,
-0xac640000, 0xac650004, 0x8ee204c4, 0xac620010,
-0xaf860120, 0x92e24e20, 0x14400037, 0x24100001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c830000, 0x24020012, 0x1462001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee54e30, 0x24420001, 0x10430007, 0x0,
-0x8ee24e34, 0x24420001, 0x10a20005, 0x0,
-0x8001621, 0x0, 0x14a00005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x8001637, 0x0, 0x8ee24e30, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020012, 0xac820000,
-0x24020001, 0xac820004, 0x5600000b, 0x24100001,
-0x8ee204e4, 0x3c040001, 0x2484528c, 0xafa00014,
-0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009,
-0xc002403, 0x34a5f006, 0x16000003, 0x24020001,
-0x8001650, 0xa2e204f4, 0x8ee20170, 0x24420001,
-0xaee20170, 0x8ee20170, 0x8ee204e4, 0xa2e004f4,
-0xaee004f0, 0xaee07274, 0xaee204f8, 0x8ee20e1c,
-0x1040006d, 0x0, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x10c20004, 0x0, 0x8f820124,
-0x14c20007, 0x0, 0x8ee201a4, 0x8021,
-0x24420001, 0xaee201a4, 0x80016ad, 0x8ee201a4,
-0x8ee2724c, 0xac62001c, 0x8ee404a8, 0x8ee504ac,
-0x2462001c, 0xac620008, 0x24020008, 0xa462000e,
-0x24020011, 0xac620018, 0xac640000, 0xac650004,
-0x8ee204c4, 0xac620010, 0xaf860120, 0x92e24e20,
-0x14400037, 0x24100001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c830000, 0x24020012,
-0x1462001f, 0x0, 0x8ee34e30, 0x8ee24e34,
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e34, 0x8ee54e30, 0x24420001,
-0x10430007, 0x0, 0x8ee24e34, 0x24420001,
-0x10a20005, 0x0, 0x8001697, 0x0,
-0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x80016ad, 0x0,
-0x8ee24e30, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x24020012, 0xac820000, 0x24020001, 0xac820004,
-0x5600000b, 0x24100001, 0x8ee2724c, 0x3c040001,
-0x24845298, 0xafa00014, 0xafa20010, 0x8ee6724c,
-0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008,
-0x56000001, 0xaee00e1c, 0x8ee20174, 0x24420001,
-0xaee20174, 0x8ee20174, 0x8ee24e24, 0x10400019,
-0x0, 0xaee04e24, 0x8f820040, 0x30420001,
-0x14400008, 0x0, 0x8f430104, 0x24020001,
-0x10620004, 0x0, 0x8f420264, 0x10400006,
-0x0, 0x8ee2017c, 0x24420001, 0xaee2017c,
-0x80016da, 0x8ee2017c, 0x8f820044, 0x34420004,
-0xaf820044, 0x8ee20178, 0x24420001, 0xaee20178,
-0x8ee20178, 0x8ee27278, 0x2442ff99, 0xaee27278,
-0x8ee27278, 0x1c4002ad, 0x0, 0x8f420238,
-0x104002aa, 0x0, 0x3c020001, 0x571021,
-0x904283e0, 0x144002a5, 0x0, 0x8f420080,
-0xaee2004c, 0x8f4200c0, 0xaee20048, 0x8f420084,
-0xaee20038, 0x8f420084, 0xaee20244, 0x8f420088,
-0xaee20248, 0x8f42008c, 0xaee2024c, 0x8f420090,
-0xaee20250, 0x8f420094, 0xaee20254, 0x8f420098,
-0xaee20258, 0x8f42009c, 0xaee2025c, 0x8f4200a0,
-0xaee20260, 0x8f4200a4, 0xaee20264, 0x8f4200a8,
-0xaee20268, 0x8f4200ac, 0xaee2026c, 0x8f4200b0,
-0xaee20270, 0x8f4200b4, 0xaee20274, 0x8f4200b8,
-0xaee20278, 0x8f4200bc, 0x24040001, 0xaee2027c,
-0xaee0003c, 0x41080, 0x571021, 0x8ee3003c,
-0x8c420244, 0x24840001, 0x621821, 0x2c82000f,
-0xaee3003c, 0x1440fff8, 0x41080, 0x8f4200cc,
-0xaee20050, 0x8f4200d0, 0xaee20054, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20007, 0x0, 0x8ee201a4,
-0x8021, 0x24420001, 0xaee201a4, 0x8001775,
-0x8ee201a4, 0x8f440208, 0x8f45020c, 0x26e20030,
-0xac620008, 0x24020400, 0xa462000e, 0x2402000f,
-0xac620018, 0xac60001c, 0xac640000, 0xac650004,
-0x8ee204c4, 0xac620010, 0xaf860120, 0x92e24e20,
-0x14400037, 0x24100001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c830000, 0x24020007,
-0x1462001f, 0x0, 0x8ee34e30, 0x8ee24e34,
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e34, 0x8ee54e30, 0x24420001,
-0x10430007, 0x0, 0x8ee24e34, 0x24420001,
-0x10a20005, 0x0, 0x800175f, 0x0,
-0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x8001775, 0x0,
-0x8ee24e30, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x12000212, 0x3c020400, 0xafa20018, 0x3c020001,
-0x571021, 0x904283b0, 0x1040010b, 0x0,
-0x8ee20608, 0x8f430228, 0x24420001, 0x304a00ff,
-0x514300fd, 0xafa00010, 0x8ee20608, 0x210c0,
-0x571021, 0x8fa30018, 0x8fa4001c, 0xac43060c,
-0xac440610, 0x8f830054, 0x8f820054, 0x24690032,
-0x1221023, 0x2c420033, 0x1040006a, 0x5821,
-0x24180008, 0x240f000d, 0x240d0007, 0x240c0040,
-0x240e0001, 0x8f870120, 0x27623800, 0x24e80020,
-0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x11020004, 0x0, 0x8f820124, 0x15020007,
-0x1021, 0x8ee201a4, 0x8021, 0x24420001,
-0xaee201a4, 0x80017f3, 0x8ee201a4, 0x8ee40608,
-0x420c0, 0x801821, 0x8ee40430, 0x8ee50434,
-0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xace40000, 0xace50004, 0x8ee20608, 0xa4f8000e,
-0xacef0018, 0xacea001c, 0x210c0, 0x2442060c,
-0x2e21021, 0xace20008, 0x8ee204c4, 0xace20010,
-0xaf880120, 0x92e24e20, 0x14400033, 0x24100001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c820000, 0x144d001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x104c0007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x80017e0,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x80017f3,
-0x0, 0x8ee24e30, 0x24420001, 0x504c0003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001,
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ff9d,
-0x0, 0x316300ff, 0x24020001, 0x14620077,
-0x3c050009, 0xaeea0608, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x10400061,
-0x5821, 0x240d0008, 0x240c0011, 0x24080012,
-0x24070040, 0x240a0001, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x10c20004, 0x0, 0x8f820124,
-0x14c20007, 0x0, 0x8ee201a4, 0x8021,
-0x24420001, 0xaee201a4, 0x800185f, 0x8ee201a4,
-0x8ee20608, 0xac62001c, 0x8ee404a0, 0x8ee504a4,
-0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018,
-0xac640000, 0xac650004, 0x8ee204c4, 0xac620010,
-0xaf860120, 0x92e24e20, 0x14400033, 0x24100001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c820000, 0x1448001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x10470007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x800184c,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x800185f,
-0x0, 0x8ee24e30, 0x24420001, 0x50470003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0xac880000, 0xac8a0004, 0x56000006, 0x240b0001,
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6,
-0x0, 0x316300ff, 0x24020001, 0x14620003,
-0x3c050009, 0x800197c, 0x24100001, 0x3c040001,
-0x248452a4, 0xafa00010, 0xafa00014, 0x8f860120,
-0x8f870124, 0x800187b, 0x34a5f011, 0x3c040001,
-0x248452b0, 0xafa00010, 0xafa00014, 0x8f860120,
-0x8f870124, 0x34a5f010, 0xc002403, 0x8021,
-0x800197c, 0x0, 0x3c040001, 0x248452bc,
-0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
-0x8001975, 0x34a5f00f, 0x8ee20608, 0x8f430228,
-0x24420001, 0x304900ff, 0x512300e2, 0xafa00010,
-0x8ee20608, 0x210c0, 0x571021, 0x8fa30018,
-0x8fa4001c, 0xac43060c, 0xac440610, 0x8f870120,
-0x27623800, 0x24e80020, 0x102102b, 0x50400001,
-0x27683000, 0x8f820128, 0x11020004, 0x0,
-0x8f820124, 0x15020007, 0x1021, 0x8ee201a4,
-0x8021, 0x24420001, 0xaee201a4, 0x80018f7,
-0x8ee201a4, 0x8ee40608, 0x420c0, 0x801821,
-0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0xace40000, 0xace50004,
-0x8ee30608, 0x24020008, 0xa4e2000e, 0x2402000d,
-0xace20018, 0xace9001c, 0x318c0, 0x2463060c,
-0x2e31021, 0xace20008, 0x8ee204c4, 0xace20010,
-0xaf880120, 0x92e24e20, 0x14400037, 0x24100001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c830000, 0x24020007, 0x1462001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee54e30, 0x24420001, 0x10430007, 0x0,
-0x8ee24e34, 0x24420001, 0x10a20005, 0x0,
-0x80018e1, 0x0, 0x14a00005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x80018f7, 0x0, 0x8ee24e30, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020007, 0xac820000,
-0x24020001, 0xac820004, 0x5600000c, 0xaee90608,
-0x3c040001, 0x248452c8, 0xafa00010, 0xafa00014,
-0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
-0x34a5f000, 0x800197c, 0x0, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20007, 0x0, 0x8ee201a4,
-0x8021, 0x24420001, 0xaee201a4, 0x800195e,
-0x8ee201a4, 0x8ee20608, 0xac62001c, 0x8ee404a0,
-0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008,
-0xa462000e, 0x24020011, 0xac620018, 0xac640000,
-0xac650004, 0x8ee204c4, 0xac620010, 0xaf860120,
-0x92e24e20, 0x14400037, 0x24100001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c830000,
-0x24020012, 0x1462001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee54e30,
-0x24420001, 0x10430007, 0x0, 0x8ee24e34,
-0x24420001, 0x10a20005, 0x0, 0x8001948,
-0x0, 0x14a00005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x800195e,
-0x0, 0x8ee24e30, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x24020012, 0xac820000, 0x24020001,
-0xac820004, 0x5600001d, 0x24100001, 0x3c040001,
-0x248452d0, 0xafa00010, 0xafa00014, 0x8ee60608,
-0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001,
-0x8ee201b0, 0x24420001, 0xaee201b0, 0x800197c,
-0x8ee201b0, 0x3c040001, 0x248452dc, 0xafa00014,
-0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f005,
-0xc002403, 0x0, 0x8ee201ac, 0x8021,
-0x24420001, 0xaee201ac, 0x8ee201ac, 0x1200000c,
-0x24020001, 0x3c010001, 0x370821, 0xa02083b0,
-0x8f420238, 0x8ee30158, 0x24630001, 0xaee30158,
-0x8ee30158, 0x800198c, 0xaee27278, 0x24020001,
-0x3c010001, 0x370821, 0xa02283b0, 0x3c020001,
-0x8c425cd8, 0x10400187, 0x0, 0x8ee27b84,
-0x24430001, 0x284200c9, 0x144001a4, 0xaee37b84,
-0x8ee204d4, 0x30420002, 0x14400119, 0xaee07b84,
-0x8ee204d4, 0x3c030600, 0x34631000, 0x34420002,
-0xaee204d4, 0xafa30018, 0x8ee20608, 0x8f430228,
-0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010,
-0x8ee20608, 0x210c0, 0x571021, 0x8fa30018,
-0x8fa4001c, 0xac43060c, 0xac440610, 0x8f830054,
-0x8f820054, 0x24690032, 0x1221023, 0x2c420033,
-0x1040006a, 0x5821, 0x24180008, 0x240f000d,
-0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120,
-0x27623800, 0x24e80020, 0x102102b, 0x50400001,
-0x27683000, 0x8f820128, 0x11020004, 0x0,
-0x8f820124, 0x15020007, 0x1021, 0x8ee201a4,
-0x8021, 0x24420001, 0xaee201a4, 0x8001a15,
-0x8ee201a4, 0x8ee40608, 0x420c0, 0x801821,
-0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0xace40000, 0xace50004,
-0x8ee20608, 0xa4f8000e, 0xacef0018, 0xacea001c,
-0x210c0, 0x2442060c, 0x2e21021, 0xace20008,
-0x8ee204c4, 0xace20010, 0xaf880120, 0x92e24e20,
-0x14400033, 0x24100001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c820000, 0x144d001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee34e30, 0x24420001, 0x104c0007,
-0x0, 0x8ee24e34, 0x24420001, 0x10620005,
-0x0, 0x8001a02, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x8001a15, 0x0, 0x8ee24e30,
-0x24420001, 0x504c0003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0xac8d0000, 0xac8e0004,
-0x56000006, 0x240b0001, 0x8f820054, 0x1221023,
-0x2c420033, 0x1440ff9d, 0x0, 0x316300ff,
-0x24020001, 0x54620078, 0xafa00010, 0xaeea0608,
-0x8f830054, 0x8f820054, 0x24690032, 0x1221023,
-0x2c420033, 0x10400061, 0x5821, 0x240d0008,
-0x240c0011, 0x24080012, 0x24070040, 0x240a0001,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
-0x0, 0x8f820124, 0x14c20007, 0x0,
-0x8ee201a4, 0x8021, 0x24420001, 0xaee201a4,
-0x8001a81, 0x8ee201a4, 0x8ee20608, 0xac62001c,
-0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008,
-0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004,
-0x8ee204c4, 0xac620010, 0xaf860120, 0x92e24e20,
-0x14400033, 0x24100001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c820000, 0x1448001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee34e30, 0x24420001, 0x10470007,
-0x0, 0x8ee24e34, 0x24420001, 0x10620005,
-0x0, 0x8001a6e, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x8001a81, 0x0, 0x8ee24e30,
-0x24420001, 0x50470003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0xac880000, 0xac8a0004,
-0x56000006, 0x240b0001, 0x8f820054, 0x1221023,
-0x2c420033, 0x1440ffa6, 0x0, 0x316300ff,
-0x24020001, 0x10620022, 0x0, 0x3c040001,
-0x248452a4, 0xafa00010, 0xafa00014, 0x8f860120,
-0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011,
-0x8001aad, 0x0, 0x3c040001, 0x248452b0,
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
-0xc002403, 0x34a5f010, 0x8001aad, 0x0,
-0x3c040001, 0x248452bc, 0xafa00014, 0x8ee60608,
-0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f,
-0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac,
-0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c,
-0x8ee204d4, 0x30420001, 0x10400055, 0x0,
-0x8f420218, 0x30420080, 0x10400029, 0x0,
-0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b7c,
-0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000,
-0x2407ffff, 0x2021, 0x461024, 0x1444000d,
-0x671824, 0x1465000b, 0x0, 0x8ee27b80,
-0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021,
-0x461024, 0x14440003, 0x671824, 0x1065000b,
-0x0, 0x8ee200c0, 0x8ee300c4, 0x8ee400e0,
-0x8ee500e4, 0xaee37b7c, 0xaee57b80, 0x8f820044,
-0x38420020, 0x8001b38, 0xaf820044, 0x8f820044,
-0x2403ffdf, 0x431024, 0x8001b38, 0xaf820044,
-0x8f820044, 0x2403ffdf, 0x431024, 0xaf820044,
-0x8ee27b7c, 0x402821, 0x8ee200c0, 0x8ee300c4,
-0x24060000, 0x2407ffff, 0x2021, 0x461024,
-0x1444000d, 0x671824, 0x1465000b, 0x0,
-0x8ee27b80, 0x402821, 0x8ee200e0, 0x8ee300e4,
-0x2021, 0x461024, 0x14440003, 0x671824,
-0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4,
-0x8ee400e0, 0x8ee500e4, 0xaee37b7c, 0xaee57b80,
-0x8f820044, 0x38420040, 0x8001b38, 0xaf820044,
-0x8f820044, 0x34420040, 0x8001b38, 0xaf820044,
-0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b8c,
-0x24430001, 0x28420015, 0x14400028, 0xaee37b8c,
-0x8f820044, 0x38420020, 0xaf820044, 0x8001b38,
-0xaee07b8c, 0x8ee204d4, 0x30420001, 0x10400011,
-0x0, 0x8f420218, 0x30420080, 0x10400009,
-0x0, 0x8f820044, 0x34420020, 0xaf820044,
-0x8f820044, 0x2403ffbf, 0x431024, 0x8001b36,
-0xaf820044, 0x8f820044, 0x34420060, 0x8001b36,
-0xaf820044, 0x8f820044, 0x34420040, 0xaf820044,
-0x8ee27b88, 0x24430001, 0x28421389, 0x14400005,
-0xaee37b88, 0x8f820044, 0x38420020, 0xaf820044,
-0xaee07b88, 0xc004603, 0x0, 0x8fbf0024,
-0x8fb00020, 0x3e00008, 0x27bd0028, 0x27bdffb8,
-0xafbf0044, 0xafb60040, 0xafb5003c, 0xafb40038,
-0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028,
-0x8f960064, 0x32c20004, 0x1040000c, 0x24020004,
-0xaf820064, 0x8f420114, 0xaee204e0, 0x8f820060,
-0x34420008, 0xaf820060, 0x8ee2016c, 0x24420001,
-0xaee2016c, 0x80022f4, 0x8ee2016c, 0x32c20001,
-0x10400004, 0x24020001, 0xaf820064, 0x80022f4,
-0x0, 0x32c20002, 0x1440000c, 0x3c050003,
-0x3c040001, 0x24845354, 0x34a50001, 0x2c03021,
-0x3821, 0xafa00010, 0xc002403, 0xafa00014,
-0x2402fff8, 0x80022f4, 0xaf820064, 0x8f43022c,
-0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c,
-0x21080, 0x5a1021, 0x8c420300, 0xafa20020,
-0x8f42022c, 0x24070001, 0x24420001, 0x3042003f,
-0x8001b80, 0xaf42022c, 0x3c040001, 0x24845360,
-0xafa00014, 0x8f46022c, 0x8f47010c, 0x3c050003,
-0xc002403, 0x34a5f01f, 0x3821, 0x14e00003,
-0x0, 0x80022ed, 0xaf960064, 0x93a20020,
-0x2443ffff, 0x2c620011, 0x10400658, 0x31080,
-0x3c010001, 0x220821, 0x8c225418, 0x400008,
-0x0, 0x8fa20020, 0x30420fff, 0xaee20e0c,
-0x8f820060, 0x34420200, 0xaf820060, 0x8ee20118,
-0x24420001, 0xaee20118, 0x80022e8, 0x8ee20118,
-0x8fa20020, 0x24030001, 0x3c010001, 0x370821,
-0xa02383b1, 0x30420fff, 0xaee25238, 0x8f820060,
-0x34420100, 0xaf820060, 0x8ee20144, 0x24420001,
-0xaee20144, 0x80022e8, 0x8ee20144, 0x8fa20020,
-0x21200, 0x22502, 0x24020001, 0x10820005,
-0x24020002, 0x10820009, 0x2402fffe, 0x8001bc9,
-0xafa00010, 0x8ee204d4, 0xaee40070, 0xaee40074,
-0x34420001, 0x8001bbd, 0xaee204d4, 0x8ee304d4,
-0xaee40070, 0xaee40074, 0x621824, 0xaee304d4,
-0x8f840054, 0x41442, 0x41c82, 0x431021,
-0x41cc2, 0x431023, 0x41d02, 0x431021,
-0x41d42, 0x431023, 0x8001bd0, 0xaee20078,
-0x3c040001, 0x2484536c, 0xafa00014, 0x8fa60020,
-0x3c050003, 0xc002403, 0x34a50004, 0x8ee20110,
-0x24420001, 0xaee20110, 0x80022e8, 0x8ee20110,
-0x27440212, 0xc0022fe, 0x24050006, 0x3049001f,
-0x920c0, 0x2e41021, 0x9442727c, 0x30424000,
-0x1040000a, 0x971021, 0x97430212, 0xa443727e,
-0x8f430214, 0x971021, 0xac437280, 0x2e41821,
-0x34028000, 0x8001c79, 0xa462727c, 0x9443727e,
-0x97420212, 0x14620006, 0x2e41021, 0x971021,
-0x8c437280, 0x8f420214, 0x1062009f, 0x2e41021,
-0x9442727c, 0x30428000, 0x1040002a, 0x2406ffff,
-0x2021, 0x410c0, 0x2e21021, 0x9442737c,
-0x30424000, 0x54400005, 0x803021, 0x24840001,
-0x2c820080, 0x1440fff8, 0x410c0, 0x4c10010,
-0x618c0, 0x610c0, 0x571821, 0x8c63737c,
-0x571021, 0xafa30010, 0x8c427380, 0x3c040001,
-0x24845378, 0xafa20014, 0x8f470214, 0x3c050003,
-0xc002403, 0x34a50013, 0x8001c90, 0x3c020800,
-0x97440212, 0x771021, 0xa444737e, 0x8f440214,
-0x771021, 0x2e31821, 0xac447380, 0x34028000,
-0xa462737c, 0x910c0, 0x2e21021, 0x8001c79,
-0xa446727c, 0x2e41021, 0x9445727c, 0x8001c2e,
-0x510c0, 0x9443737e, 0x97420212, 0x14620006,
-0x510c0, 0x971021, 0x8c437380, 0x8f420214,
-0x10620065, 0x510c0, 0x2e21021, 0x9445737c,
-0x510c0, 0x2e21021, 0x9442737c, 0x30428000,
-0x1040fff0, 0x971021, 0x520c0, 0x971021,
-0x9443737e, 0x97420212, 0x14620006, 0x2406ffff,
-0x971021, 0x8c437380, 0x8f420214, 0x10620053,
-0x3c020800, 0x2021, 0x410c0, 0x2e21021,
-0x9442737c, 0x30424000, 0x54400005, 0x803021,
-0x24840001, 0x2c820080, 0x1440fff8, 0x410c0,
-0x4c10023, 0x618c0, 0x910c0, 0x571821,
-0x8c63727c, 0x571021, 0xafa30010, 0x8c427280,
-0x3c040001, 0x24845384, 0xafa20014, 0x8f470214,
-0x3c050003, 0xc002403, 0x34a5f017, 0x8001c90,
-0x3c020800, 0x8f430210, 0xb71021, 0xac43777c,
-0x8f430214, 0xb71021, 0xac437780, 0x3c020001,
-0x571021, 0x8c4283b4, 0x24420001, 0x3c010001,
-0x370821, 0xac2283b4, 0x3c030001, 0x771821,
-0x8c6383b4, 0x2e51021, 0x8001c82, 0xa443777c,
-0x97440212, 0x771021, 0xa444737e, 0x8f440214,
-0x771021, 0x2e31821, 0xac447380, 0x34028000,
-0xa462737c, 0x510c0, 0x2e21021, 0xa446737c,
-0x2021, 0x428c0, 0x2e51021, 0x9442777c,
-0x1040ffdc, 0x24840001, 0x2c820080, 0x5440fffa,
-0x428c0, 0x92e204d8, 0x10400006, 0x24020001,
-0x8ee304dc, 0x1221004, 0x621825, 0x8001c8f,
-0xaee304dc, 0x8f830228, 0x24020001, 0x1221004,
-0x621825, 0xaf830228, 0x3c020800, 0x34421000,
-0xafa20018, 0x8ee20608, 0x8f430228, 0x24420001,
-0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee20608,
-0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c,
-0xac43060c, 0xac440610, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x1040006a,
-0x5821, 0x24100008, 0x240f000d, 0x240d0007,
-0x240c0040, 0x240e0001, 0x8f870120, 0x27623800,
-0x24e80020, 0x102102b, 0x50400001, 0x27683000,
-0x8f820128, 0x11020004, 0x0, 0x8f820124,
-0x15020007, 0x1021, 0x8ee201a4, 0x3821,
-0x24420001, 0xaee201a4, 0x8001d08, 0x8ee201a4,
-0x8ee40608, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xace40000, 0xace50004, 0x8ee20608,
-0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0,
-0x2442060c, 0x2e21021, 0xace20008, 0x8ee204c4,
-0xace20010, 0xaf880120, 0x92e24e20, 0x14400033,
-0x24070001, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c820000, 0x144d001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee34e30, 0x24420001, 0x104c0007, 0x0,
-0x8ee24e34, 0x24420001, 0x10620005, 0x0,
-0x8001cf5, 0x0, 0x14600005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x8001d08, 0x0, 0x8ee24e30, 0x24420001,
-0x504c0003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006,
-0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
-0x1440ff9d, 0x0, 0x316300ff, 0x24020001,
-0x54620078, 0xafa00010, 0xaeea0608, 0x8f830054,
-0x8f820054, 0x24690032, 0x1221023, 0x2c420033,
-0x10400061, 0x5821, 0x240e0008, 0x240d0011,
-0x240a0012, 0x24080040, 0x240c0001, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20007, 0x0, 0x8ee201a4,
-0x3821, 0x24420001, 0xaee201a4, 0x8001d74,
-0x8ee201a4, 0x8ee20608, 0xac62001c, 0x8ee404a0,
-0x8ee504a4, 0x2462001c, 0xac620008, 0xa46e000e,
-0xac6d0018, 0xac640000, 0xac650004, 0x8ee204c4,
-0xac620010, 0xaf860120, 0x92e24e20, 0x14400033,
-0x24070001, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c820000, 0x144a001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee34e30, 0x24420001, 0x10480007, 0x0,
-0x8ee24e34, 0x24420001, 0x10620005, 0x0,
-0x8001d61, 0x0, 0x14600005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x8001d74, 0x0, 0x8ee24e30, 0x24420001,
-0x50480003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006,
-0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
-0x1440ffa6, 0x0, 0x316300ff, 0x24020001,
-0x10620022, 0x0, 0x3c040001, 0x24845390,
-0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
-0x3c050009, 0xc002403, 0x34a5f011, 0x8001da0,
-0x0, 0x3c040001, 0x2484539c, 0xafa00014,
-0x8f860120, 0x8f870124, 0x3c050009, 0xc002403,
-0x34a5f010, 0x8001da0, 0x0, 0x3c040001,
-0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228,
-0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac,
-0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20124,
-0x24420001, 0xaee20124, 0x8001f97, 0x8ee20124,
-0x27440212, 0xc0022fe, 0x24050006, 0x3049001f,
-0x928c0, 0x2e51021, 0x9442727c, 0x30428000,
-0x1040002f, 0x2e51021, 0x9442727c, 0x30424000,
-0x1440001c, 0xb71021, 0x9443727e, 0x97420212,
-0x14620018, 0xb71021, 0x8c437280, 0x8f420214,
-0x54620016, 0xafa20010, 0x92e204d8, 0x10400007,
-0x24020001, 0x8ee304dc, 0x1221004, 0x21027,
-0x621824, 0x8001dc9, 0xaee304dc, 0x8f830228,
-0x1221004, 0x21027, 0x621824, 0xaf830228,
-0x910c0, 0x2e21821, 0x3402c000, 0x8001e4e,
-0xa462727c, 0x8f420214, 0xafa20010, 0x910c0,
-0x571021, 0x8c42727c, 0x3c040001, 0x248453b4,
-0x3c050003, 0xafa20014, 0x8f470210, 0x34a5f01c,
-0xc002403, 0x1203021, 0x8001e83, 0x3c020800,
-0xb71021, 0x9443727e, 0x97420212, 0x14620019,
-0x918c0, 0xb71021, 0x8c437280, 0x8f420214,
-0x14620014, 0x918c0, 0x2e51021, 0x9447727c,
-0x720c0, 0x971021, 0x9443737e, 0xb71021,
-0xa443727e, 0x971021, 0x8c437380, 0xb71021,
-0xac437280, 0x2e41021, 0x9443737c, 0x2e51021,
-0xa443727c, 0x2e41821, 0x3402c000, 0x8001e4e,
-0xa462737c, 0x2e31021, 0x9447727c, 0x3021,
-0x720c0, 0x2e41021, 0x9442737c, 0x4021,
-0x30428000, 0x14400025, 0xe02821, 0x605021,
-0x340bc000, 0x971021, 0x9443737e, 0x97420212,
-0x54620015, 0xe02821, 0x971021, 0x8c437380,
-0x8f420214, 0x54620010, 0xe02821, 0x11000006,
-0x2e41021, 0x9443737c, 0x510c0, 0x2e21021,
-0x8001e1a, 0xa443737c, 0x9443737c, 0x2ea1021,
-0xa443727c, 0x710c0, 0x2e21021, 0xa44b737c,
-0x8001e28, 0x24060001, 0x510c0, 0x2e21021,
-0x9447737c, 0x720c0, 0x2e41021, 0x9442737c,
-0x30428000, 0x1040ffdf, 0x25080001, 0x30c200ff,
-0x14400025, 0x2021, 0x720c0, 0x971021,
-0x9443737e, 0x97420212, 0x1462000f, 0x910c0,
-0x971021, 0x8c437380, 0x8f420214, 0x1462000a,
-0x910c0, 0x2e41821, 0x3402c000, 0x15000015,
-0xa462737c, 0x910c0, 0x2e21821, 0x34028000,
-0x8001e4e, 0xa462727c, 0x571021, 0x8c42727c,
-0x3c040001, 0x248453c0, 0x3c050003, 0xafa20010,
-0x710c0, 0x571021, 0x8c42737c, 0x34a5001e,
-0x1203021, 0xc002403, 0xafa20014, 0x8001e83,
-0x3c020800, 0x2021, 0x428c0, 0xb71021,
-0x9443777e, 0x97420212, 0x5462002b, 0x24840001,
-0xb71021, 0x8c437780, 0x8f420214, 0x54620026,
-0x24840001, 0x3c020001, 0x571021, 0x8c4283b4,
-0x2442ffff, 0x3c010001, 0x370821, 0xac2283b4,
-0x3c020001, 0x571021, 0x8c4283b4, 0x809021,
-0x242102b, 0x1040000e, 0x24b1777c, 0x24b07784,
-0x2f02021, 0x2f12821, 0xc002490, 0x24060008,
-0x26310008, 0x3c020001, 0x571021, 0x8c4283b4,
-0x26520001, 0x242102b, 0x1440fff5, 0x26100008,
-0x3c040001, 0x972021, 0x8c8483b4, 0x24050008,
-0x420c0, 0x2484777c, 0xc002488, 0x2e42021,
-0x8001e83, 0x3c020800, 0x2c820080, 0x1440ffcf,
-0x428c0, 0x3c020800, 0x34422000, 0xafa20018,
-0x8ee20608, 0x8f430228, 0x24420001, 0x304a00ff,
-0x514300fd, 0xafa00010, 0x8ee20608, 0x210c0,
-0x571021, 0x8fa30018, 0x8fa4001c, 0xac43060c,
-0xac440610, 0x8f830054, 0x8f820054, 0x24690032,
-0x1221023, 0x2c420033, 0x1040006a, 0x5821,
-0x24100008, 0x240f000d, 0x240d0007, 0x240c0040,
-0x240e0001, 0x8f870120, 0x27623800, 0x24e80020,
-0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x11020004, 0x0, 0x8f820124, 0x15020007,
-0x1021, 0x8ee201a4, 0x3821, 0x24420001,
-0xaee201a4, 0x8001efb, 0x8ee201a4, 0x8ee40608,
-0x420c0, 0x801821, 0x8ee40430, 0x8ee50434,
-0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xace40000, 0xace50004, 0x8ee20608, 0xa4f0000e,
-0xacef0018, 0xacea001c, 0x210c0, 0x2442060c,
-0x2e21021, 0xace20008, 0x8ee204c4, 0xace20010,
-0xaf880120, 0x92e24e20, 0x14400033, 0x24070001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c820000, 0x144d001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x104c0007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x8001ee8,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x8001efb,
-0x0, 0x8ee24e30, 0x24420001, 0x504c0003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001,
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ff9d,
-0x0, 0x316300ff, 0x24020001, 0x54620078,
-0xafa00010, 0xaeea0608, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x10400061,
-0x5821, 0x240e0008, 0x240d0011, 0x240a0012,
-0x24080040, 0x240c0001, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x10c20004, 0x0, 0x8f820124,
-0x14c20007, 0x0, 0x8ee201a4, 0x3821,
-0x24420001, 0xaee201a4, 0x8001f67, 0x8ee201a4,
-0x8ee20608, 0xac62001c, 0x8ee404a0, 0x8ee504a4,
-0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018,
-0xac640000, 0xac650004, 0x8ee204c4, 0xac620010,
-0xaf860120, 0x92e24e20, 0x14400033, 0x24070001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c820000, 0x144a001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x10480007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x8001f54,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x8001f67,
-0x0, 0x8ee24e30, 0x24420001, 0x50480003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001,
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6,
-0x0, 0x316300ff, 0x24020001, 0x10620022,
-0x0, 0x3c040001, 0x24845390, 0xafa00010,
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
-0xc002403, 0x34a5f011, 0x8001f93, 0x0,
-0x3c040001, 0x2484539c, 0xafa00014, 0x8f860120,
-0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010,
-0x8001f93, 0x0, 0x3c040001, 0x248453a8,
-0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
-0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001,
-0xaee201ac, 0x8ee201ac, 0x8ee20128, 0x24420001,
-0xaee20128, 0x8ee20128, 0x8ee20164, 0x24420001,
-0xaee20164, 0x80022e8, 0x8ee20164, 0x8fa20020,
-0x21200, 0x21d02, 0x24020001, 0x10620005,
-0x24020002, 0x1062000d, 0x0, 0x8001fb7,
-0xafa00010, 0x92e204d8, 0x14400006, 0x24020001,
-0x8f820228, 0xaee204dc, 0x2402ffff, 0xaf820228,
-0x24020001, 0x8001fbe, 0xa2e204d8, 0x92e204d8,
-0x5040000c, 0xa2e004d8, 0x8ee204dc, 0xaf820228,
-0x8001fbe, 0xa2e004d8, 0x3c040001, 0x248453c8,
-0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403,
-0x34a5f009, 0x8ee2013c, 0x24420001, 0xaee2013c,
-0x80022e8, 0x8ee2013c, 0x8fa20020, 0x21200,
-0x22502, 0x24020001, 0x10820005, 0x24020002,
-0x1082000f, 0x0, 0x8001fe3, 0xafa00010,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024,
-0x34420008, 0xaf820220, 0x24020001, 0x3c010001,
-0x370821, 0xa02283b2, 0x8001fea, 0xaee40108,
-0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024,
-0xaf820220, 0x3c010001, 0x370821, 0xa02083b2,
-0x8001fea, 0xaee40108, 0x3c040001, 0x248453d4,
-0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403,
-0x34a5f00a, 0x8ee2012c, 0x24420001, 0xaee2012c,
-0x80022e8, 0x8ee2012c, 0x8fa20020, 0x21200,
-0x21d02, 0x24020001, 0x10620005, 0x24020002,
-0x1062000e, 0x0, 0x8002011, 0xafa00010,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024,
-0x34420008, 0xaf820220, 0x24020001, 0x3c010001,
-0x370821, 0x8002018, 0xa02283b3, 0x3c020001,
-0x571021, 0x904283b2, 0x3c010001, 0x370821,
-0x1440000e, 0xa02083b3, 0x8f820220, 0x3c0308ff,
-0x3463fff7, 0x431024, 0x8002018, 0xaf820220,
-0x3c040001, 0x248453e0, 0xafa00014, 0x8fa60020,
-0x3c050003, 0xc002403, 0x34a5f00b, 0x8ee20114,
-0x24420001, 0xaee20114, 0x80022e8, 0x8ee20114,
-0x27840208, 0x27450200, 0xc00249a, 0x24060008,
-0x26e40094, 0x27450200, 0xc00249a, 0x24060008,
-0x8ee20134, 0x24420001, 0xaee20134, 0x80022e8,
-0x8ee20134, 0x8f460248, 0x2021, 0xc005108,
-0x24050004, 0x8ee20130, 0x24420001, 0xaee20130,
-0x80022e8, 0x8ee20130, 0x8ef301cc, 0x8ef401d0,
-0x8ef501d8, 0x8ee20140, 0x26e40030, 0x24420001,
-0xaee20140, 0x8ef00140, 0x8ef10074, 0x8ef20070,
-0xc002488, 0x24050400, 0xaef301cc, 0xaef401d0,
-0xaef501d8, 0xaef00140, 0xaef10074, 0xaef20070,
-0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260,
-0x27450200, 0x24060008, 0xaee20068, 0x24020006,
-0xc00249a, 0xaee20064, 0x3c023b9a, 0x3442ca00,
-0xaee2006c, 0x240203e8, 0x24040002, 0x24030001,
-0xaee20104, 0xaee40100, 0xaee3010c, 0x8f820220,
-0x30420008, 0x10400004, 0x0, 0xaee30108,
-0x8002061, 0x2021, 0xaee40108, 0x2021,
-0x3c030001, 0x641821, 0x90635c30, 0x2e41021,
-0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8,
-0x0, 0x8f820040, 0x2e41821, 0x24840001,
-0x21702, 0x24420030, 0xa062009c, 0x2e41021,
-0x80022e8, 0xa040009c, 0x24020001, 0x3c010001,
-0x370821, 0xa02283e0, 0x240b0400, 0x24080014,
-0x240a0040, 0x24090001, 0x8f830100, 0x27623000,
-0x24660020, 0xc2102b, 0x50400001, 0x27662800,
-0x8f820108, 0x10c20004, 0x0, 0x8f820104,
-0x14c20007, 0x26e20030, 0x8ee201a8, 0x3821,
-0x24420001, 0xaee201a8, 0x80020a8, 0x8ee201a8,
-0x8ee404b8, 0x8ee504bc, 0xac620008, 0xa46b000e,
-0xac680018, 0xac60001c, 0xac640000, 0xac650004,
-0x8ee204cc, 0xac620010, 0xaf860100, 0x92e204ec,
-0x1440000e, 0x24070001, 0x8ee24e28, 0x24420001,
-0x504a0003, 0x1021, 0x8ee24e28, 0x24420001,
-0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
-0x2e21021, 0xac480000, 0xac490004, 0x10e0ffd2,
-0x0, 0x80022e8, 0x0, 0x3c020900,
-0xaee05238, 0xaee0523c, 0xaee05240, 0xaee05244,
-0xaee001d0, 0x3c010001, 0x370821, 0xa02083b1,
-0xafa20018, 0x8ee20608, 0x8f430228, 0x24420001,
-0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee20608,
-0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c,
-0xac43060c, 0xac440610, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x1040006a,
-0x5821, 0x24100008, 0x240f000d, 0x240d0007,
-0x240c0040, 0x240e0001, 0x8f870120, 0x27623800,
-0x24e80020, 0x102102b, 0x50400001, 0x27683000,
-0x8f820128, 0x11020004, 0x0, 0x8f820124,
-0x15020007, 0x1021, 0x8ee201a4, 0x3821,
-0x24420001, 0xaee201a4, 0x800212c, 0x8ee201a4,
-0x8ee40608, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xace40000, 0xace50004, 0x8ee20608,
-0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0,
-0x2442060c, 0x2e21021, 0xace20008, 0x8ee204c4,
-0xace20010, 0xaf880120, 0x92e24e20, 0x14400033,
-0x24070001, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c820000, 0x144d001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee34e30, 0x24420001, 0x104c0007, 0x0,
-0x8ee24e34, 0x24420001, 0x10620005, 0x0,
-0x8002119, 0x0, 0x14600005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x800212c, 0x0, 0x8ee24e30, 0x24420001,
-0x504c0003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006,
-0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
-0x1440ff9d, 0x0, 0x316300ff, 0x24020001,
-0x54620078, 0xafa00010, 0xaeea0608, 0x8f830054,
-0x8f820054, 0x24690032, 0x1221023, 0x2c420033,
-0x10400061, 0x5821, 0x240e0008, 0x240d0011,
-0x240a0012, 0x24080040, 0x240c0001, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20007, 0x0, 0x8ee201a4,
-0x3821, 0x24420001, 0xaee201a4, 0x8002198,
-0x8ee201a4, 0x8ee20608, 0xac62001c, 0x8ee404a0,
-0x8ee504a4, 0x2462001c, 0xac620008, 0xa46e000e,
-0xac6d0018, 0xac640000, 0xac650004, 0x8ee204c4,
-0xac620010, 0xaf860120, 0x92e24e20, 0x14400033,
-0x24070001, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c820000, 0x144a001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee34e30, 0x24420001, 0x10480007, 0x0,
-0x8ee24e34, 0x24420001, 0x10620005, 0x0,
-0x8002185, 0x0, 0x14600005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x8002198, 0x0, 0x8ee24e30, 0x24420001,
-0x50480003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006,
-0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
-0x1440ffa6, 0x0, 0x316300ff, 0x24020001,
-0x10620022, 0x0, 0x3c040001, 0x24845390,
-0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
-0x3c050009, 0xc002403, 0x34a5f011, 0x80021c4,
-0x0, 0x3c040001, 0x2484539c, 0xafa00014,
-0x8f860120, 0x8f870124, 0x3c050009, 0xc002403,
-0x34a5f010, 0x80021c4, 0x0, 0x3c040001,
-0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228,
-0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac,
-0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20120,
-0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20168,
-0x24420001, 0xaee20168, 0x80022e8, 0x8ee20168,
-0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260,
-0x27450200, 0x24060008, 0xc00249a, 0xaee20068,
-0x8f820220, 0x30420008, 0x14400002, 0x24020001,
-0x24020002, 0xaee20108, 0x8ee2011c, 0x24420001,
-0xaee2011c, 0x80022e8, 0x8ee2011c, 0x3c040001,
-0x248453ec, 0xafa00010, 0xafa00014, 0x8fa60020,
-0x3c050003, 0xc002403, 0x34a5f00f, 0x93a20020,
-0x3c030700, 0x34631000, 0x431025, 0xafa20018,
-0x8ee20608, 0x8f430228, 0x24420001, 0x304900ff,
-0x512300e2, 0xafa00010, 0x8ee20608, 0x210c0,
-0x571021, 0x8fa30018, 0x8fa4001c, 0xac43060c,
-0xac440610, 0x8f870120, 0x27623800, 0x24e80020,
-0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x11020004, 0x0, 0x8f820124, 0x15020007,
-0x1021, 0x8ee201a4, 0x3821, 0x24420001,
-0xaee201a4, 0x800225d, 0x8ee201a4, 0x8ee40608,
-0x420c0, 0x801821, 0x8ee40430, 0x8ee50434,
-0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xace40000, 0xace50004, 0x8ee30608, 0x24020008,
-0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c,
-0x318c0, 0x2463060c, 0x2e31021, 0xace20008,
-0x8ee204c4, 0xace20010, 0xaf880120, 0x92e24e20,
-0x14400037, 0x24070001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c830000, 0x24020007,
-0x1462001f, 0x0, 0x8ee34e30, 0x8ee24e34,
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e34, 0x8ee54e30, 0x24420001,
-0x10430007, 0x0, 0x8ee24e34, 0x24420001,
-0x10a20005, 0x0, 0x8002247, 0x0,
-0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x800225d, 0x0,
-0x8ee24e30, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x54e0000c, 0xaee90608, 0x3c040001, 0x248453f4,
-0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228,
-0x3c050009, 0xc002403, 0x34a5f000, 0x80022e0,
-0x0, 0x8f830120, 0x27623800, 0x24660020,
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128,
-0x10c20004, 0x0, 0x8f820124, 0x14c20007,
-0x0, 0x8ee201a4, 0x3821, 0x24420001,
-0xaee201a4, 0x80022c4, 0x8ee201a4, 0x8ee20608,
-0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c,
-0xac620008, 0x24020008, 0xa462000e, 0x24020011,
-0xac620018, 0xac640000, 0xac650004, 0x8ee204c4,
-0xac620010, 0xaf860120, 0x92e24e20, 0x14400037,
-0x24070001, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c830000, 0x24020012, 0x1462001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x24030040, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee54e30, 0x24420001, 0x10430007,
-0x0, 0x8ee24e34, 0x24420001, 0x10a20005,
-0x0, 0x80022ae, 0x0, 0x14a00005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x80022c4, 0x0, 0x8ee24e30,
-0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x24020012,
-0xac820000, 0x24020001, 0xac820004, 0x14e0001b,
-0x0, 0x3c040001, 0x248453fc, 0xafa00010,
-0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009,
-0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001,
-0xaee201b0, 0x80022e0, 0x8ee201b0, 0x3c040001,
-0x24845408, 0xafa00014, 0x8ee60608, 0x8f470228,
-0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac,
-0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20150,
-0x24420001, 0xaee20150, 0x8ee20150, 0x8ee20160,
-0x24420001, 0xaee20160, 0x8ee20160, 0x8f43022c,
-0x8f42010c, 0x14620009, 0x24020002, 0xaf820064,
-0x8f820064, 0x14400005, 0x0, 0x8f43022c,
-0x8f42010c, 0x1462f875, 0x0, 0x8fbf0044,
-0x8fb60040, 0x8fb5003c, 0x8fb40038, 0x8fb30034,
-0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x3e00008,
-0x27bd0048, 0x27bdfff8, 0x2408ffff, 0x10a00014,
-0x4821, 0x3c0aedb8, 0x354a8320, 0x90870000,
-0x24840001, 0x3021, 0x1071026, 0x30420001,
-0x10400002, 0x81842, 0x6a1826, 0x604021,
-0x24c60001, 0x2cc20008, 0x1440fff7, 0x73842,
-0x25290001, 0x125102b, 0x1440fff0, 0x0,
-0x1001021, 0x3e00008, 0x27bd0008, 0x27bdffe8,
-0x27642800, 0xafbf0010, 0xc002488, 0x24051000,
-0x24020021, 0xaf800100, 0xaf800104, 0xaf800108,
-0xaf800110, 0xaf800114, 0xaf800118, 0xaf800120,
-0xaf800124, 0xaf800128, 0xaf800130, 0xaf800134,
-0xaf800138, 0xaee04e28, 0xaee04e2c, 0xaee04e30,
-0xaee04e34, 0xaf82011c, 0x8f420218, 0x30420040,
-0x10400004, 0x0, 0x8f82011c, 0x34420004,
-0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe0, 0xafbf0018, 0x8f820104, 0xafa20010,
-0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0,
-0x8f87011c, 0x3c040001, 0x248454c0, 0xc002403,
-0x34a5f000, 0x8f8300b0, 0x3c027f00, 0x621824,
-0x3c020400, 0x10620029, 0x43102b, 0x14400008,
-0x3c022000, 0x3c020100, 0x10620024, 0x3c020200,
-0x10620011, 0x0, 0x8002374, 0x0,
-0x10620008, 0x3c024000, 0x1462001c, 0x0,
-0x8ee20190, 0x24420001, 0xaee20190, 0x8002374,
-0x8ee20190, 0x8ee2018c, 0x24420001, 0xaee2018c,
-0x8002374, 0x8ee2018c, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001,
-0xaf8200b0, 0xaf830104, 0x8f82011c, 0x2403fffd,
-0x431024, 0xaf82011c, 0x8ee201a0, 0x24420001,
-0xaee201a0, 0x8002377, 0x8ee201a0, 0x8f8200b0,
-0x34420001, 0xaf8200b0, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x27bdffe0, 0xafbf001c, 0xafb00018,
-0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001,
-0xafa20014, 0x8f8600a0, 0x8f87011c, 0x3c040001,
-0x248454cc, 0xc002403, 0x34a5f000, 0x8f8300a0,
-0x3c027f00, 0x621824, 0x3c020400, 0x10620053,
-0x8021, 0x43102b, 0x14400008, 0x3c042000,
-0x3c020100, 0x1062004d, 0x3c020200, 0x1062003a,
-0x0, 0x80023e0, 0x0, 0x10640003,
-0x3c024000, 0x14620045, 0x0, 0x8f8200a0,
-0x441024, 0x10400006, 0x0, 0x8ee20194,
-0x24420001, 0xaee20194, 0x80023a9, 0x8ee20194,
-0x8ee20198, 0x24420001, 0xaee20198, 0x8ee20198,
-0x8f82011c, 0x34420002, 0xaf82011c, 0x8f82011c,
-0x30420200, 0x1040001b, 0x0, 0x8f8300a0,
-0x8f840124, 0x8f8200ac, 0x14400007, 0x24020001,
-0x3c020001, 0x3442f000, 0x621024, 0x50400001,
-0x24100001, 0x24020001, 0x1200000d, 0xaf8200a0,
-0x8f820124, 0x2442ffe0, 0xaf820124, 0x8f820124,
-0x8f820124, 0x27633000, 0x43102b, 0x10400005,
-0x276237e0, 0xaf820124, 0x80023ca, 0x0,
-0xaf840124, 0x8f82011c, 0x2403fffd, 0x431024,
-0x80023e3, 0xaf82011c, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001,
-0xaf8200a0, 0xaf830124, 0x8f82011c, 0x2403fffd,
-0x431024, 0xaf82011c, 0x8ee2019c, 0x24420001,
-0xaee2019c, 0x80023e3, 0x8ee2019c, 0x8f8200a0,
-0x34420001, 0xaf8200a0, 0x8fbf001c, 0x8fb00018,
-0x3e00008, 0x27bd0020, 0x0, 0x3c020001,
-0x8c425c58, 0x27bdffe8, 0xafbf0014, 0x14400012,
-0xafb00010, 0x3c100001, 0x26105dd0, 0x2002021,
-0xc002488, 0x24052000, 0x26021fe0, 0x3c010001,
-0xac225d94, 0x3c010001, 0xac225d90, 0xaf420250,
-0x24022000, 0xaf500254, 0xaf420258, 0x24020001,
-0x3c010001, 0xac225c58, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x3c030001, 0x8c635d94,
-0x8c820000, 0x8fa80010, 0x8fa90014, 0xac620000,
-0x3c020001, 0x8c425d94, 0x8c830004, 0xac430004,
-0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010,
-0xac470014, 0xac480018, 0xac49001c, 0x3c010001,
-0xac235d94, 0xac44000c, 0x3c020001, 0x24425dd0,
-0x62182b, 0x10600005, 0x0, 0x3c020001,
-0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001,
-0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620000,
-0x3c030001, 0x8c635d94, 0x3c020001, 0x8c425c40,
-0xac620004, 0x3e00008, 0xaf430250, 0x3c030001,
-0x8c635d94, 0x3c020001, 0x8c425c40, 0x27bdffd0,
-0xafb40020, 0x8fb40040, 0xafb00010, 0x808021,
-0xafb50024, 0x8fb50044, 0x8fa40048, 0xafb10014,
-0xa08821, 0xafbf0028, 0xafb3001c, 0xafb20018,
-0xac620000, 0x3c050001, 0x8ca55d94, 0x3c020001,
-0x8c425c40, 0xc09021, 0xe09821, 0x10800006,
-0xaca20004, 0x24a50008, 0xc002490, 0x24060018,
-0x800244e, 0x0, 0x24a40008, 0xc002488,
-0x24050018, 0x3c020001, 0x8c425d94, 0x3c050001,
-0x24a55dd0, 0x2442ffe0, 0x3c010001, 0xac225d94,
-0x45102b, 0x10400005, 0x0, 0x3c020001,
-0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001,
-0x8c635d94, 0x8e020000, 0xac620000, 0x3c030001,
-0x8c635d94, 0x8e020004, 0xac620004, 0xac710008,
-0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225d94,
-0x45102b, 0xac720010, 0xac730014, 0xac740018,
-0xac75001c, 0x10400005, 0xac64000c, 0x3c020001,
-0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001,
-0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620000,
-0x3c030001, 0x8c635d94, 0x3c020001, 0x8c425c40,
-0xac620004, 0xaf430250, 0x8fbf0028, 0x8fb50024,
-0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0030, 0x10a00005,
-0x0, 0xac800000, 0x24a5fffc, 0x14a0fffd,
-0x24840004, 0x3e00008, 0x0, 0x10c00007,
-0x0, 0x8c820000, 0x24840004, 0x24c6fffc,
-0xaca20000, 0x14c0fffb, 0x24a50004, 0x3e00008,
-0x0, 0x10c00007, 0x0, 0x8ca20000,
-0x24a50004, 0x24c6fffc, 0xac820000, 0x14c0fffb,
-0x24840004, 0x3e00008, 0x0, 0x3e00008,
-0x0, 0x27bdffd8, 0xafbf0020, 0x8ee304e4,
-0x8ee204e0, 0x10620436, 0x0, 0x8ee204e4,
-0x8ee304fc, 0x21100, 0x626021, 0x95870008,
-0x8d8a0000, 0x8d8b0004, 0x958d000a, 0x8ee2725c,
-0x8ee3726c, 0x30e4ffff, 0x441021, 0x62182b,
-0x10600015, 0x31a20004, 0x8f8200d8, 0x8ee37258,
-0x431023, 0xaee2726c, 0x8ee2726c, 0x1c400003,
-0x3c030001, 0x431021, 0xaee2726c, 0x8ee2725c,
-0x8ee3726c, 0x441021, 0x62182b, 0x10600006,
-0x31a20004, 0x8ee201b8, 0x24420001, 0xaee201b8,
-0x80028e1, 0x8ee201b8, 0x10400240, 0x31a20200,
-0x1040014d, 0x4821, 0x96e2045a, 0x30420010,
-0x10400149, 0x0, 0x8f840100, 0x27623000,
-0x24850020, 0xa2102b, 0x50400001, 0x27652800,
-0x8f820108, 0x10a20004, 0x0, 0x8f820104,
-0x14a20006, 0x2402000c, 0x8ee201a8, 0x24420001,
-0xaee201a8, 0x800252c, 0x8ee201a8, 0xac8a0000,
-0xac8b0004, 0x8ee37264, 0x24060005, 0xa482000e,
-0xac860018, 0xac830008, 0x8ee204e4, 0xac82001c,
-0x8ee204c8, 0xac820010, 0xaf850100, 0x92e204ec,
-0x14400036, 0x24090001, 0x8ee24e28, 0x210c0,
-0x24424e38, 0x2e22021, 0x8c820000, 0x1446001f,
-0x0, 0x8ee34e28, 0x8ee24e2c, 0x1062001b,
-0x24030040, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e2c, 0x8ee54e28, 0x24420001, 0x10430007,
-0x0, 0x8ee24e2c, 0x24420001, 0x10a20005,
-0x0, 0x8002516, 0x0, 0x14a00005,
-0x0, 0x8f820108, 0x24420020, 0xaf820108,
-0x8f820108, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x800252c, 0x0, 0x8ee24e28,
-0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e28, 0x24420001, 0xaee24e28, 0x8ee24e28,
-0x210c0, 0x24424e38, 0x2e22021, 0x24020005,
-0xac820000, 0x24020001, 0xac820004, 0x1520000a,
-0x3c040001, 0xafab0010, 0x8ee27264, 0x3c040001,
-0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4,
-0x80028be, 0x34a5f114, 0x8ee27264, 0x34843800,
-0x3641821, 0x24420010, 0x43102b, 0x14400073,
-0x0, 0x8ee27264, 0x24480010, 0x3641021,
-0x102102b, 0x14400002, 0x3c02ffff, 0x1024021,
-0x8f850100, 0x27623000, 0x24a60020, 0xc2102b,
-0x50400001, 0x27662800, 0x8f820108, 0x10c20004,
-0x0, 0x8f820104, 0x14c20007, 0x2563000c,
-0x8ee201a8, 0x4821, 0x24420001, 0xaee201a8,
-0x80025a0, 0x8ee201a8, 0x2c64000c, 0x1441021,
-0xaca20000, 0xaca30004, 0x24e2fff4, 0xa4a2000e,
-0x24020006, 0xaca80008, 0xaca20018, 0x8ee204e4,
-0xaca2001c, 0x8ee204c8, 0x3c030002, 0x431025,
-0xaca20010, 0xaf860100, 0x92e204ec, 0x14400037,
-0x24090001, 0x8ee24e28, 0x210c0, 0x24424e38,
-0x2e22021, 0x8c830000, 0x24020005, 0x1462001f,
-0x0, 0x8ee34e28, 0x8ee24e2c, 0x1062001b,
-0x24030040, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e2c, 0x8ee54e28, 0x24420001, 0x10430007,
-0x0, 0x8ee24e2c, 0x24420001, 0x10a20005,
-0x0, 0x800258a, 0x0, 0x14a00005,
-0x0, 0x8f820108, 0x24420020, 0xaf820108,
-0x8f820108, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x80025a0, 0x0, 0x8ee24e28,
-0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e28, 0x24420001, 0xaee24e28, 0x8ee24e28,
-0x210c0, 0x24424e38, 0x2e22021, 0x24020005,
-0xac820000, 0x24020001, 0xac820004, 0x1520000a,
-0x2508fffc, 0xafab0010, 0x8ee27264, 0x3c040001,
-0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4,
-0x80028be, 0x34a5f125, 0x34028100, 0xa5020000,
-0x9582000e, 0x800261d, 0xa5020002, 0x8f850100,
-0x27623000, 0x24a60020, 0xc2102b, 0x50400001,
-0x27662800, 0x8f820108, 0x10c20004, 0x0,
-0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a8,
-0x4821, 0x24420001, 0xaee201a8, 0x800260d,
-0x8ee201a8, 0x2c64000c, 0x1441021, 0xaca20000,
-0xaca30004, 0x8ee37264, 0x24e2fff4, 0xa4a2000e,
-0x24020006, 0xaca20018, 0x24630010, 0xaca30008,
-0x8ee204e4, 0xaca2001c, 0x8ee204c8, 0x3c030002,
-0x431025, 0xaca20010, 0xaf860100, 0x92e204ec,
-0x14400037, 0x24090001, 0x8ee24e28, 0x210c0,
-0x24424e38, 0x2e22021, 0x8c830000, 0x24020005,
-0x1462001f, 0x0, 0x8ee34e28, 0x8ee24e2c,
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e2c, 0x8ee54e28, 0x24420001,
-0x10430007, 0x0, 0x8ee24e2c, 0x24420001,
-0x10a20005, 0x0, 0x80025f7, 0x0,
-0x14a00005, 0x0, 0x8f820108, 0x24420020,
-0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x800260d, 0x0,
-0x8ee24e28, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e28, 0x24420001, 0xaee24e28,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
-0x24020005, 0xac820000, 0x24020001, 0xac820004,
-0x1520000a, 0x34028100, 0xafab0010, 0x8ee27264,
-0x3c040001, 0x24845730, 0x3c050004, 0xafa20014,
-0x8ee604e4, 0x80028be, 0x34a5f015, 0x8ee37264,
-0xa462000c, 0x8ee37264, 0x9582000e, 0xa462000e,
-0x8002681, 0x24e70004, 0x8f840100, 0x27623000,
-0x24850020, 0xa2102b, 0x50400001, 0x27652800,
-0x8f820108, 0x10a20004, 0x0, 0x8f820104,
-0x14a20007, 0x24020006, 0x8ee201a8, 0x4821,
-0x24420001, 0xaee201a8, 0x8002677, 0x8ee201a8,
-0xac8a0000, 0xac8b0004, 0x8ee37264, 0xa487000e,
-0xac820018, 0xac830008, 0x8ee204e4, 0xac82001c,
-0x8ee204c8, 0x3c030002, 0x431025, 0xac820010,
-0xaf850100, 0x92e204ec, 0x14400037, 0x24090001,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
-0x8c830000, 0x24020005, 0x1462001f, 0x0,
-0x8ee34e28, 0x8ee24e2c, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e2c,
-0x8ee54e28, 0x24420001, 0x10430007, 0x0,
-0x8ee24e2c, 0x24420001, 0x10a20005, 0x0,
-0x8002661, 0x0, 0x14a00005, 0x0,
-0x8f820108, 0x24420020, 0xaf820108, 0x8f820108,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x8002677, 0x0, 0x8ee24e28, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e28,
-0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0,
-0x24424e38, 0x2e22021, 0x24020005, 0xac820000,
-0x24020001, 0xac820004, 0x15200009, 0x3c050004,
-0xafab0010, 0x8ee27264, 0x3c040001, 0x24845730,
-0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f004,
-0x8ee2725c, 0x30e7ffff, 0x471021, 0xaee2725c,
-0x8ee204e4, 0x8ee304fc, 0x8ee47258, 0x21100,
-0x431021, 0xac44000c, 0x8ee27258, 0xafa20018,
-0x8ee3725c, 0xafa3001c, 0x8ee2725c, 0x2c42003c,
-0x10400004, 0x24620001, 0x2403fffe, 0x431024,
-0xafa2001c, 0x8ee27264, 0x3c060001, 0x34c63800,
-0x8ee3725c, 0x2405fff8, 0x471021, 0x24420007,
-0x451024, 0x24630007, 0xaee27258, 0x8ee2726c,
-0x8ee47258, 0x651824, 0x431023, 0xaee2726c,
-0x3661021, 0x82202b, 0x14800004, 0x3c03ffff,
-0x8ee27258, 0x431021, 0xaee27258, 0x8ee27258,
-0xaee27264, 0x8f8200f0, 0x24470008, 0x27621800,
-0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4,
-0x14e20007, 0x0, 0x8ee201b4, 0x4821,
-0x24420001, 0xaee201b4, 0x80026c4, 0x8ee201b4,
-0x8f8200f0, 0x24090001, 0x8fa30018, 0x8fa4001c,
-0xac430000, 0xac440004, 0xaf8700f0, 0x15200012,
-0xd1142, 0x8f8200f0, 0xafa20010, 0x8f8200f4,
-0x3c040001, 0x2484573c, 0xafa20014, 0x8fa60018,
-0x8fa7001c, 0x3c050004, 0xc002403, 0x34a5f005,
-0x8ee20088, 0x24420001, 0xaee20088, 0x8ee20088,
-0x80028d3, 0xaee0725c, 0x30430003, 0x24020002,
-0x10620016, 0x28620003, 0x10400005, 0x24020001,
-0x10620008, 0x0, 0x8002703, 0x0,
-0x24020003, 0x10620017, 0x0, 0x8002703,
-0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001,
-0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec,
-0x8ee200e8, 0x8002703, 0x8ee300ec, 0x8ee200f0,
-0x8ee300f4, 0x24630001, 0x2c640001, 0x441021,
-0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x8002703,
-0x8ee300f4, 0x8ee200f8, 0x8ee300fc, 0x24630001,
-0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc,
-0x8ee200f8, 0x8ee300fc, 0x8ee2725c, 0x8ee400e0,
-0x8ee500e4, 0x401821, 0x1021, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaee400e0,
-0xaee500e4, 0x80028d3, 0xaee0725c, 0x30e2ffff,
-0x104001c1, 0x31a20200, 0x1040014d, 0x4821,
-0x96e2045a, 0x30420010, 0x10400149, 0x0,
-0x8f840100, 0x27623000, 0x24850020, 0xa2102b,
-0x50400001, 0x27652800, 0x8f820108, 0x10a20004,
-0x0, 0x8f820104, 0x14a20006, 0x2402000c,
-0x8ee201a8, 0x24420001, 0xaee201a8, 0x800276e,
-0x8ee201a8, 0xac8a0000, 0xac8b0004, 0x8ee37264,
-0x24060005, 0xa482000e, 0xac860018, 0xac830008,
-0x8ee204e4, 0xac82001c, 0x8ee204c8, 0xac820010,
-0xaf850100, 0x92e204ec, 0x14400036, 0x24090001,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
-0x8c820000, 0x1446001f, 0x0, 0x8ee34e28,
-0x8ee24e2c, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e2c, 0x8ee54e28,
-0x24420001, 0x10430007, 0x0, 0x8ee24e2c,
-0x24420001, 0x10a20005, 0x0, 0x8002758,
-0x0, 0x14a00005, 0x0, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x800276e,
-0x0, 0x8ee24e28, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e28, 0x24420001,
-0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
-0x2e22021, 0x24020005, 0xac820000, 0x24020001,
-0xac820004, 0x1520000a, 0x3c040001, 0xafab0010,
-0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004,
-0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f014,
-0x8ee27264, 0x34843800, 0x3641821, 0x24420010,
-0x43102b, 0x14400073, 0x0, 0x8ee27264,
-0x24480010, 0x3641021, 0x102102b, 0x14400002,
-0x3c02ffff, 0x1024021, 0x8f850100, 0x27623000,
-0x24a60020, 0xc2102b, 0x50400001, 0x27662800,
-0x8f820108, 0x10c20004, 0x0, 0x8f820104,
-0x14c20007, 0x2563000c, 0x8ee201a8, 0x4821,
-0x24420001, 0xaee201a8, 0x80027e2, 0x8ee201a8,
-0x2c64000c, 0x1441021, 0xaca20000, 0xaca30004,
-0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca80008,
-0xaca20018, 0x8ee204e4, 0xaca2001c, 0x8ee204c8,
-0x3c030002, 0x431025, 0xaca20010, 0xaf860100,
-0x92e204ec, 0x14400037, 0x24090001, 0x8ee24e28,
-0x210c0, 0x24424e38, 0x2e22021, 0x8c830000,
-0x24020005, 0x1462001f, 0x0, 0x8ee34e28,
-0x8ee24e2c, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e2c, 0x8ee54e28,
-0x24420001, 0x10430007, 0x0, 0x8ee24e2c,
-0x24420001, 0x10a20005, 0x0, 0x80027cc,
-0x0, 0x14a00005, 0x0, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x80027e2,
-0x0, 0x8ee24e28, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e28, 0x24420001,
-0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
-0x2e22021, 0x24020005, 0xac820000, 0x24020001,
-0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010,
-0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004,
-0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f015,
-0x34028100, 0xa5020000, 0x9582000e, 0x800285f,
-0xa5020002, 0x8f850100, 0x27623000, 0x24a60020,
-0xc2102b, 0x50400001, 0x27662800, 0x8f820108,
-0x10c20004, 0x0, 0x8f820104, 0x14c20007,
-0x2563000c, 0x8ee201a8, 0x4821, 0x24420001,
-0xaee201a8, 0x800284f, 0x8ee201a8, 0x2c64000c,
-0x1441021, 0xaca20000, 0xaca30004, 0x8ee37264,
-0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca20018,
-0x24630010, 0xaca30008, 0x8ee204e4, 0xaca2001c,
-0x8ee204c8, 0x3c030002, 0x431025, 0xaca20010,
-0xaf860100, 0x92e204ec, 0x14400037, 0x24090001,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
-0x8c830000, 0x24020005, 0x1462001f, 0x0,
-0x8ee34e28, 0x8ee24e2c, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e2c,
-0x8ee54e28, 0x24420001, 0x10430007, 0x0,
-0x8ee24e2c, 0x24420001, 0x10a20005, 0x0,
-0x8002839, 0x0, 0x14a00005, 0x0,
-0x8f820108, 0x24420020, 0xaf820108, 0x8f820108,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x800284f, 0x0, 0x8ee24e28, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e28,
-0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0,
-0x24424e38, 0x2e22021, 0x24020005, 0xac820000,
-0x24020001, 0xac820004, 0x1520000a, 0x34028100,
-0xafab0010, 0x8ee27264, 0x3c040001, 0x24845730,
-0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be,
-0x34a5f016, 0x8ee37264, 0xa462000c, 0x8ee37264,
-0x9582000e, 0xa462000e, 0x80028c2, 0x24e70004,
-0x8f830100, 0x27623000, 0x24640020, 0x82102b,
-0x50400001, 0x27642800, 0x8f820108, 0x10820004,
-0x0, 0x8f820104, 0x14820007, 0x24050005,
-0x8ee201a8, 0x4821, 0x24420001, 0xaee201a8,
-0x80028b6, 0x8ee201a8, 0xac6a0000, 0xac6b0004,
-0x8ee27264, 0xa467000e, 0xac650018, 0xac620008,
-0x8ee204e4, 0xac62001c, 0x8ee204c8, 0xac620010,
-0xaf840100, 0x92e204ec, 0x14400036, 0x24090001,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
-0x8c820000, 0x1445001f, 0x0, 0x8ee34e28,
-0x8ee24e2c, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e2c, 0x8ee54e28,
-0x24420001, 0x10430007, 0x0, 0x8ee24e2c,
-0x24420001, 0x10a20005, 0x0, 0x80028a0,
-0x0, 0x14a00005, 0x0, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x80028b6,
-0x0, 0x8ee24e28, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e28, 0x24420001,
-0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
-0x2e22021, 0x24020005, 0xac820000, 0x24020001,
-0xac820004, 0x1520000b, 0x3c050004, 0x3c040001,
-0x24845748, 0xafab0010, 0xafa00014, 0x8ee604e4,
-0x34a5f017, 0xc002403, 0x30e7ffff, 0x80028e1,
-0x0, 0x8ee27264, 0x3c050001, 0x30e4ffff,
-0x441021, 0xaee27264, 0x8ee2725c, 0x8ee37264,
-0x34a53800, 0x441021, 0xaee2725c, 0x3651021,
-0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27264,
-0x431021, 0xaee27264, 0x8ee304e4, 0x96e20458,
-0x24630001, 0x2442ffff, 0x621824, 0xaee304e4,
-0x8ee304e4, 0x8ee204e0, 0x14620005, 0x0,
-0x8f820060, 0x2403fff7, 0x431024, 0xaf820060,
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x27bdffe0,
-0xafbf0018, 0x8ee304e8, 0x8ee204e0, 0x10620189,
-0x0, 0x8ee204e8, 0x8ee304fc, 0x21100,
-0x621821, 0x94670008, 0x92e204ed, 0x8c680000,
-0x8c690004, 0x10400023, 0x946a000a, 0x8ee204c8,
-0x34460400, 0x31420200, 0x1040001f, 0x0,
-0x96e2045a, 0x30420010, 0x1040001b, 0x3c028000,
-0x3c010001, 0x370821, 0xac2283d8, 0x8ee27264,
-0x9464000e, 0x3c050001, 0x34a53800, 0x24420004,
-0xaee27264, 0x8ee37264, 0x42400, 0x3651021,
-0x3c010001, 0x370821, 0xac2483dc, 0x62182b,
-0x14600005, 0x24e70004, 0x8ee27264, 0x3c03ffff,
-0x431021, 0xaee27264, 0x8ee27264, 0x8002917,
-0xaee27258, 0x8ee604c8, 0x8ee2726c, 0x30e4ffff,
-0x44102a, 0x10400015, 0x0, 0x8f8200d8,
-0x8ee37258, 0x431023, 0xaee2726c, 0x8ee2726c,
-0x1c400007, 0x44102a, 0x8ee2726c, 0x3c030001,
-0x431021, 0xaee2726c, 0x8ee2726c, 0x44102a,
-0x10400006, 0x0, 0x8ee201b8, 0x24420001,
-0xaee201b8, 0x8002a72, 0x8ee201b8, 0x3c020001,
-0x571021, 0x8c4283d8, 0x54400001, 0x24e7fffc,
-0x31420004, 0x104000b9, 0x30e2ffff, 0x3c020001,
-0x571021, 0x8c4283d8, 0x1040002f, 0x5021,
-0x8f840100, 0x27623000, 0x24850020, 0xa2102b,
-0x50400001, 0x27652800, 0x8f820108, 0x10a20032,
-0x0, 0x8f820104, 0x10a2002f, 0x24020015,
-0xac880000, 0xac890004, 0x8ee37264, 0xa487000e,
-0xac820018, 0xac830008, 0x8ee204e8, 0x3c030001,
-0x771821, 0x8c6383dc, 0xac860010, 0x431025,
-0xac82001c, 0xaf850100, 0x92e204ec, 0x14400066,
-0x240a0001, 0x8ee24e28, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e28, 0x24420001,
-0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
-0x2e21821, 0x24020015, 0xac620000, 0x24020001,
-0x80029bf, 0xac620004, 0x8f840100, 0x27623000,
-0x24850020, 0xa2102b, 0x50400001, 0x27652800,
-0x8f820108, 0x10a20004, 0x0, 0x8f820104,
-0x14a20006, 0x24020006, 0x8ee201a8, 0x24420001,
-0xaee201a8, 0x80029bf, 0x8ee201a8, 0xac880000,
-0xac890004, 0x8ee37264, 0xa487000e, 0xac820018,
-0xac830008, 0x8ee204e8, 0xac860010, 0xac82001c,
-0xaf850100, 0x92e204ec, 0x14400037, 0x240a0001,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
-0x8c830000, 0x24020005, 0x1462001f, 0x0,
-0x8ee34e28, 0x8ee24e2c, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e2c,
-0x8ee54e28, 0x24420001, 0x10430007, 0x0,
-0x8ee24e2c, 0x24420001, 0x10a20005, 0x0,
-0x80029a9, 0x0, 0x14a00005, 0x0,
-0x8f820108, 0x24420020, 0xaf820108, 0x8f820108,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x80029bf, 0x0, 0x8ee24e28, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e28,
-0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0,
-0x24424e38, 0x2e22021, 0x24020005, 0xac820000,
-0x24020001, 0xac820004, 0x1540000a, 0x24020001,
-0xafa90010, 0x8ee27264, 0x3c040001, 0x24845730,
-0x3c050004, 0xafa20014, 0x8ee604e4, 0x8002a4f,
-0x34a5f204, 0xa2e204ed, 0x8ee204e8, 0x8ee304fc,
-0x8ee47258, 0x3c060001, 0x34c63800, 0x3c010001,
-0x370821, 0xac2083d8, 0x3c010001, 0x370821,
-0xac2083dc, 0x21100, 0x431021, 0xac44000c,
-0x8ee27264, 0x2405fff8, 0x30e3ffff, 0x431021,
-0x24420007, 0x451024, 0x24630007, 0xaee27258,
-0x8ee2726c, 0x8ee47258, 0x651824, 0x431023,
-0xaee2726c, 0x3661021, 0x82202b, 0x14800004,
-0x3c03ffff, 0x8ee27258, 0x431021, 0xaee27258,
-0x8ee27258, 0x8002a64, 0xaee27264, 0x10400073,
-0x0, 0x8f830100, 0x27623000, 0x24640020,
-0x82102b, 0x14400002, 0x5021, 0x27642800,
-0x8f820108, 0x10820004, 0x0, 0x8f820104,
-0x14820006, 0x24050005, 0x8ee201a8, 0x24420001,
-0xaee201a8, 0x8002a46, 0x8ee201a8, 0xac680000,
-0xac690004, 0x8ee27264, 0xa467000e, 0xac650018,
-0xac620008, 0x8ee204e8, 0xac660010, 0xac62001c,
-0xaf840100, 0x92e204ec, 0x14400036, 0x240a0001,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021,
-0x8c820000, 0x1445001f, 0x0, 0x8ee34e28,
-0x8ee24e2c, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e2c, 0x8ee54e28,
-0x24420001, 0x10430007, 0x0, 0x8ee24e2c,
-0x24420001, 0x10a20005, 0x0, 0x8002a30,
-0x0, 0x14a00005, 0x0, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8002a46,
-0x0, 0x8ee24e28, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e28, 0x24420001,
-0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38,
-0x2e22021, 0x24020005, 0xac820000, 0x24020001,
-0xac820004, 0x1540000c, 0x30e5ffff, 0x3c040001,
-0x24845748, 0x3c050004, 0xafa90010, 0xafa00014,
-0x8ee604e4, 0x34a5f237, 0xc002403, 0x30e7ffff,
-0x8002a72, 0x0, 0x8ee27264, 0x451021,
-0xaee27264, 0x8ee2726c, 0x8ee37264, 0x3c040001,
-0x34843800, 0xa2e004ed, 0x451023, 0xaee2726c,
-0x3641021, 0x62182b, 0x14600004, 0x3c03ffff,
-0x8ee27264, 0x431021, 0xaee27264, 0x8ee304e8,
-0x96e20458, 0x24630001, 0x2442ffff, 0x621824,
-0xaee304e8, 0x8ee304e8, 0x8ee204e0, 0x14620005,
-0x0, 0x8f820060, 0x2403fff7, 0x431024,
-0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820100,
-0x8ee34e2c, 0x8f820104, 0x8f850108, 0x24020040,
-0x24630001, 0x50620003, 0x1021, 0x8ee24e2c,
-0x24420001, 0xaee24e2c, 0x8ee24e2c, 0x8ee34e2c,
-0x210c0, 0x24424e38, 0x2e22021, 0x8ee24e28,
-0x8c870004, 0x14620007, 0xa03021, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8002aa2,
-0xac800000, 0x8ee24e2c, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e2c, 0x24420001,
-0x210c0, 0x24424e38, 0x2e22021, 0x8c820004,
-0x8f830108, 0x21140, 0x621821, 0xaf830108,
-0xac800000, 0x8cc20018, 0x2443fffe, 0x2c620013,
-0x104000c1, 0x31080, 0x3c010001, 0x220821,
-0x8c225770, 0x400008, 0x0, 0x8ee204f0,
-0x471021, 0xaee204f0, 0x8ee204f0, 0x8f43023c,
-0x43102b, 0x144000be, 0x0, 0x8ee304e4,
-0x8ee204f8, 0x506200ba, 0xa2e004f4, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20007, 0x0, 0x8ee201a4,
-0x8021, 0x24420001, 0xaee201a4, 0x8002b12,
-0x8ee201a4, 0x8ee204e4, 0xac62001c, 0x8ee404b0,
-0x8ee504b4, 0x2462001c, 0xac620008, 0x24020008,
-0xa462000e, 0x24020011, 0xac620018, 0xac640000,
-0xac650004, 0x8ee204c4, 0xac620010, 0xaf860120,
-0x92e24e20, 0x14400037, 0x24100001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c830000,
-0x24020012, 0x1462001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee54e30,
-0x24420001, 0x10430007, 0x0, 0x8ee24e34,
-0x24420001, 0x10a20005, 0x0, 0x8002afc,
-0x0, 0x14a00005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8002b12,
-0x0, 0x8ee24e30, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x24020012, 0xac820000, 0x24020001,
-0xac820004, 0x5600000b, 0x24100001, 0x8ee204e4,
-0x3c040001, 0x24845754, 0xafa00014, 0xafa20010,
-0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
-0x34a5f006, 0x16000003, 0x24020001, 0x8002b71,
-0xa2e204f4, 0x8ee20170, 0x24420001, 0xaee20170,
-0x8ee20170, 0x8ee204e4, 0xa2e004f4, 0xaee004f0,
-0xaee204f8, 0x8f42023c, 0x50400045, 0xaee07274,
-0x8ee20184, 0x24420001, 0xaee20184, 0x8ee20184,
-0x8002b71, 0xaee07274, 0x8ee20504, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee20504,
-0x24420001, 0xaee20504, 0x8ee20504, 0x8cc30018,
-0x21080, 0x571021, 0x8c440508, 0x24020003,
-0x1462000f, 0x0, 0x3c020001, 0x571021,
-0x904283b1, 0x10400014, 0x0, 0x8ee201d0,
-0x8ee35240, 0x441021, 0xaee201d0, 0x8ee201d8,
-0x641821, 0x306300ff, 0x8002b59, 0xaee35240,
-0x8ee201cc, 0x8ee30e10, 0x441021, 0xaee201cc,
-0x8ee201d8, 0x641821, 0x306301ff, 0xaee30e10,
-0x441021, 0xaee201d8, 0x8ee20000, 0x34420040,
-0x8002b71, 0xaee20000, 0x8ee2014c, 0x3c010001,
-0x370821, 0xa02083e0, 0x24420001, 0xaee2014c,
-0x8002b71, 0x8ee2014c, 0x94c7000e, 0x8cc2001c,
-0x3c040001, 0x24845760, 0xafa60014, 0xafa20010,
-0x8cc60018, 0x3c050008, 0xc002403, 0x34a50910,
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
-0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb60058,
-0xafb50054, 0xafb40050, 0xafb3004c, 0xafb20048,
-0xafb10044, 0xafb00040, 0x8f830108, 0x8f820104,
-0xafa00024, 0x106203e7, 0xafa0002c, 0x3c1e0001,
-0x37de3800, 0x3c0bffff, 0x8f930108, 0x8e620018,
-0x8f830104, 0x2443fffe, 0x2c620014, 0x104003cf,
-0x31080, 0x3c010001, 0x220821, 0x8c2257c0,
-0x400008, 0x0, 0x9663000e, 0x8ee2725c,
-0x8ee404f0, 0x431021, 0xaee2725c, 0x8e63001c,
-0x96e20458, 0x24840001, 0xaee404f0, 0x24630001,
-0x2442ffff, 0x621824, 0xaee304e4, 0x8f42023c,
-0x82202b, 0x148003b9, 0x0, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20007, 0x0, 0x8ee201a4,
-0x8021, 0x24420001, 0xaee201a4, 0x8002bfe,
-0x8ee201a4, 0x8ee204e4, 0xac62001c, 0x8ee404b0,
-0x8ee504b4, 0x2462001c, 0xac620008, 0x24020008,
-0xa462000e, 0x24020011, 0xac620018, 0xac640000,
-0xac650004, 0x8ee204c4, 0xac620010, 0xaf860120,
-0x92e24e20, 0x14400037, 0x24100001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c830000,
-0x24020012, 0x1462001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x240c0040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x104c0007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x8002be8,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8002bfe,
-0x0, 0x8ee24e30, 0x240c0040, 0x24420001,
-0x504c0003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x24020012, 0x240c0001, 0xac820000,
-0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204e4,
-0x3c040001, 0x24845754, 0xafa00014, 0xafa20010,
-0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f006,
-0xc002403, 0xafab0038, 0x8fab0038, 0x1200030a,
-0x240c0001, 0x8002f19, 0x0, 0x966c001c,
-0xafac002c, 0x9662001e, 0x3c0c8000, 0xafac0024,
-0xae62001c, 0x8e75001c, 0x8ee204fc, 0x8ee404fc,
-0x151900, 0x621021, 0x8c52000c, 0x92e27b98,
-0x641821, 0x9476000a, 0x14400003, 0x32c20002,
-0xaef27ba4, 0xaef57b9c, 0x1040004b, 0x8021,
-0x96e2045a, 0x30420002, 0x10400047, 0x0,
-0x8e63001c, 0x8ee204fc, 0x32100, 0x821021,
-0x8c42000c, 0x37e1821, 0x24420022, 0x43102b,
-0x1440000a, 0x24050014, 0x8ee204fc, 0x821021,
-0x8c44000c, 0xafab0038, 0xc002f75, 0x2484000e,
-0x8fab0038, 0x8002c52, 0x3050ffff, 0x8ee204fc,
-0x821021, 0x8c42000c, 0x9450000e, 0x94430010,
-0x94440012, 0x94450014, 0x2038021, 0x2048021,
-0x2058021, 0x94430016, 0x94440018, 0x9445001a,
-0x2038021, 0x2048021, 0x2058021, 0x9443001c,
-0x9444001e, 0x94420020, 0x2038021, 0x2048021,
-0x2028021, 0x101c02, 0x3202ffff, 0x628021,
-0x8e63001c, 0x8ee204fc, 0x102402, 0x32900,
-0xa21021, 0x8c43000c, 0x3202ffff, 0x828021,
-0x37e1021, 0x24630018, 0x62182b, 0x14600009,
-0x0, 0x8ee204fc, 0xa21021, 0x8c43000c,
-0x101027, 0x3c01ffff, 0x230821, 0x8002c6f,
-0xa4220018, 0x8ee204fc, 0xa21021, 0x8c43000c,
-0x101027, 0xa4620018, 0x96e2045a, 0x8821,
-0x30420008, 0x14400063, 0xa021, 0x8e63001c,
-0x8ee204fc, 0x33100, 0xc21021, 0x8c42000c,
-0x37e1821, 0x24420022, 0x43102b, 0x14400035,
-0x0, 0x8ee204fc, 0xc21021, 0x8c42000c,
-0x24470010, 0x37e1021, 0xe2102b, 0x50400001,
-0xeb3821, 0x8ee204fc, 0x94f10000, 0xc21021,
-0x8c42000c, 0x24470016, 0x37e1021, 0xe2102b,
-0x14400002, 0x2634ffec, 0xeb3821, 0x8ee204fc,
-0x90e30001, 0xc21021, 0x8c42000c, 0x2447001a,
-0x37e1021, 0xe2102b, 0x14400002, 0x2838821,
-0xeb3821, 0x94e20000, 0x24e70002, 0x2228821,
-0x37e1021, 0xe2102b, 0x50400001, 0xeb3821,
-0x94e20000, 0x24e70002, 0x2228821, 0x37e1021,
-0xe2102b, 0x50400001, 0xeb3821, 0x94e20000,
-0x24e70002, 0x2228821, 0x37e1021, 0xe2102b,
-0x50400001, 0xeb3821, 0x94e20000, 0x8002cd0,
-0x2228821, 0x8ee204fc, 0xc21021, 0x8c43000c,
-0x8ee204fc, 0x94710010, 0x8ee304fc, 0xc21021,
-0x8c44000c, 0xc31821, 0x8c62000c, 0x2634ffec,
-0x90840017, 0x8ee304fc, 0x9442001a, 0x2848821,
-0xc31821, 0x8c65000c, 0x8ee304fc, 0x2228821,
-0x8ee204fc, 0xc31821, 0xc21021, 0x8c44000c,
-0x8c62000c, 0x94a3001c, 0x9484001e, 0x94420020,
-0x2238821, 0x2248821, 0x2228821, 0x111c02,
-0x3222ffff, 0x628821, 0x111c02, 0x3222ffff,
-0x628821, 0x32c20001, 0x104000b2, 0x0,
-0x96e2045a, 0x30420001, 0x104000ae, 0x32c20080,
-0x10400008, 0x0, 0x92e27b98, 0x14400005,
-0x0, 0x240c0001, 0xa2ec7b98, 0xaef57b9c,
-0xaef27ba4, 0x8ee304fc, 0x151100, 0x431021,
-0x8c47000c, 0x37e1821, 0x24e2000e, 0x43102b,
-0x14400008, 0xe02021, 0x2405000e, 0xc002f75,
-0xafab0038, 0x3042ffff, 0x8fab0038, 0x8002d09,
-0x2028021, 0x94e60000, 0x24e70002, 0x94e50000,
-0x24e70002, 0x94e30000, 0x24e70002, 0x94e20000,
-0x24e70002, 0x94e40000, 0x24e70002, 0x2068021,
-0x2058021, 0x2038021, 0x2028021, 0x94e20000,
-0x94e30002, 0x2048021, 0x2028021, 0x2038021,
-0x101c02, 0x3202ffff, 0x628021, 0x101c02,
-0x3202ffff, 0x8ee47b9c, 0x628021, 0x14950004,
-0x3205ffff, 0x96620016, 0x8002d17, 0x512021,
-0x96620016, 0x542021, 0x41402, 0x3083ffff,
-0x432021, 0x852023, 0x41402, 0x822021,
-0x3084ffff, 0x50800001, 0x3404ffff, 0x8ee27ba4,
-0x24430017, 0x37e1021, 0x62102b, 0x50400001,
-0x6b1821, 0x90630000, 0x24020011, 0x14620031,
-0x24020006, 0x8ee27ba4, 0x37e1821, 0x24420028,
-0x43102b, 0x14400018, 0x0, 0x8ee27b9c,
-0x12a2000a, 0x32c20100, 0x8ee27ba4, 0x3c01ffff,
-0x220821, 0x94220028, 0x822021, 0x41c02,
-0x3082ffff, 0x622021, 0x32c20100, 0x14400004,
-0x41027, 0x92e27b98, 0x14400002, 0x41027,
-0x3044ffff, 0x8ee27ba4, 0x3c01ffff, 0x220821,
-0x8002d8a, 0xa4240028, 0x8ee27b9c, 0x12a20008,
-0x32c20100, 0x8ee27ba4, 0x94420028, 0x822021,
-0x41c02, 0x3082ffff, 0x622021, 0x32c20100,
-0x14400004, 0x41027, 0x92e27b98, 0x14400002,
-0x41027, 0x3044ffff, 0x8ee27ba4, 0x8002d8a,
-0xa4440028, 0x1462002f, 0x37e1821, 0x8ee27ba4,
-0x24420032, 0x43102b, 0x14400018, 0x0,
-0x8ee27b9c, 0x12a2000a, 0x32c20100, 0x8ee27ba4,
-0x3c01ffff, 0x220821, 0x94220032, 0x822021,
-0x41c02, 0x3082ffff, 0x622021, 0x32c20100,
-0x14400004, 0x41027, 0x92e27b98, 0x14400002,
-0x41027, 0x3044ffff, 0x8ee27ba4, 0x3c01ffff,
-0x220821, 0x8002d8a, 0xa4240032, 0x8ee27b9c,
-0x12a20008, 0x32c20100, 0x8ee27ba4, 0x94420032,
-0x822021, 0x41c02, 0x3082ffff, 0x622021,
-0x32c20100, 0x14400004, 0x41027, 0x92e27b98,
-0x14400002, 0x41027, 0x3044ffff, 0x8ee27ba4,
-0xa4440032, 0x8fac0024, 0x1180002c, 0x37e1821,
-0x8e420000, 0xae42fffc, 0x2642000a, 0x43102b,
-0x1440001b, 0x34038100, 0x26430004, 0x37e1021,
-0x62102b, 0x14400003, 0x602021, 0x6b1821,
-0x602021, 0x8c620000, 0x24630004, 0xae420000,
-0x37e1021, 0x62102b, 0x50400001, 0x6b1821,
-0x8c620000, 0xac820000, 0x34028100, 0xa4620000,
-0x24630002, 0x37e1021, 0x62102b, 0x50400001,
-0x6b1821, 0x97ac002e, 0x8002db4, 0xa46c0000,
-0x8e420004, 0x8e440008, 0xa6430008, 0x97ac002e,
-0xa64c000a, 0xae420000, 0xae440004, 0x9662000e,
-0x2652fffc, 0x24420004, 0xa662000e, 0x9662000e,
-0x8ee3725c, 0x621821, 0xaee3725c, 0xafb20018,
-0x8ee3725c, 0xafa3001c, 0x8ee2725c, 0x2c42003c,
-0x10400004, 0x24620001, 0x2403fffe, 0x431024,
-0xafa2001c, 0x32c20080, 0x1040000c, 0x32c20100,
-0x8ee27ba8, 0x24430001, 0x210c0, 0x571021,
-0xaee37ba8, 0x8fa30018, 0x8fa4001c, 0xac437bac,
-0xac447bb0, 0x8002ea0, 0xaee0725c, 0x10400072,
-0x0, 0x8ee27ba8, 0x24430001, 0x210c0,
-0x571021, 0xaee37ba8, 0x8fa30018, 0x8fa4001c,
-0xac437bac, 0xac447bb0, 0x8ee27ba8, 0x10400063,
-0x4821, 0x5021, 0x8f8200f0, 0x24480008,
-0x27621800, 0x102102b, 0x50400001, 0x27681000,
-0x8f8200f4, 0x15020007, 0x0, 0x8ee201b4,
-0x8021, 0x24420001, 0xaee201b4, 0x8002dfa,
-0x8ee201b4, 0x8f8300f0, 0x24100001, 0x1571021,
-0x8c447bac, 0x8c457bb0, 0xac640000, 0xac650004,
-0xaf8800f0, 0x16000006, 0x2ea1021, 0x8ee20088,
-0x24420001, 0xaee20088, 0x8002e3f, 0x8ee20088,
-0x8c427bb0, 0x8ee400e0, 0x8ee500e4, 0x8ee67b9c,
-0x401821, 0x1021, 0xa32821, 0xa3382b,
-0x822021, 0x872021, 0x8ee204fc, 0xc93021,
-0x63100, 0xaee400e0, 0xaee500e4, 0xc23021,
-0x94c2000a, 0x240c0002, 0x21142, 0x30430003,
-0x106c0016, 0x28620003, 0x10400005, 0x240c0001,
-0x106c0008, 0x0, 0x8002e3f, 0x0,
-0x240c0003, 0x106c0017, 0x0, 0x8002e3f,
-0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001,
-0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec,
-0x8ee200e8, 0x8002e3f, 0x8ee300ec, 0x8ee200f0,
-0x8ee300f4, 0x24630001, 0x2c640001, 0x441021,
-0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x8002e3f,
-0x8ee300f4, 0x8ee200f8, 0x8ee300fc, 0x24630001,
-0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc,
-0x8ee200f8, 0x8ee300fc, 0x8ee27ba8, 0x25290001,
-0x122102b, 0x1440ffa0, 0x254a0008, 0xa2e07b98,
-0x8002e9f, 0xaee07ba8, 0x8f8200f0, 0x24470008,
-0x27621800, 0xe2102b, 0x50400001, 0x27671000,
-0x8f8200f4, 0x14e20007, 0x0, 0x8ee201b4,
-0x8021, 0x24420001, 0xaee201b4, 0x8002e5d,
-0x8ee201b4, 0x8f8200f0, 0x24100001, 0x8fa30018,
-0x8fa4001c, 0xac430000, 0xac440004, 0xaf8700f0,
-0x16000007, 0x0, 0x8ee20088, 0x24420001,
-0xaee20088, 0x8ee20088, 0x8002ea0, 0xaee0725c,
-0x8ee2725c, 0x8ee400e0, 0x8ee500e4, 0x240c0002,
-0x401821, 0x1021, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0x161142, 0x30430003,
-0xaee400e0, 0xaee500e4, 0x106c0017, 0x2c620003,
-0x10400005, 0x240c0001, 0x106c0008, 0x0,
-0x8002ea0, 0xaee0725c, 0x240c0003, 0x106c0019,
-0x0, 0x8002ea0, 0xaee0725c, 0x8ee200e8,
-0x8ee300ec, 0x24630001, 0x2c640001, 0x441021,
-0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8ee300ec,
-0x8002ea0, 0xaee0725c, 0x8ee200f0, 0x8ee300f4,
-0x24630001, 0x2c640001, 0x441021, 0xaee200f0,
-0xaee300f4, 0x8ee200f0, 0x8ee300f4, 0x8002ea0,
-0xaee0725c, 0x8ee200f8, 0x8ee300fc, 0x24630001,
-0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc,
-0x8ee200f8, 0x8ee300fc, 0xaee0725c, 0x8e62001c,
-0x96e30458, 0x8ee404f0, 0x24420001, 0x2463ffff,
-0x431024, 0x24840001, 0xaee204e4, 0xaee404f0,
-0x8f42023c, 0x82202b, 0x148000b0, 0x0,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
-0x0, 0x8f820124, 0x14c20007, 0x0,
-0x8ee201a4, 0x8021, 0x24420001, 0xaee201a4,
-0x8002f07, 0x8ee201a4, 0x8ee204e4, 0xac62001c,
-0x8ee404b0, 0x8ee504b4, 0x2462001c, 0xac620008,
-0x24020008, 0xa462000e, 0x24020011, 0xac620018,
-0xac640000, 0xac650004, 0x8ee204c4, 0xac620010,
-0xaf860120, 0x92e24e20, 0x14400037, 0x24100001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c830000, 0x24020012, 0x1462001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x240c0040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee34e30, 0x24420001, 0x104c0007, 0x0,
-0x8ee24e34, 0x24420001, 0x10620005, 0x0,
-0x8002ef1, 0x0, 0x14600005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x8002f07, 0x0, 0x8ee24e30, 0x240c0040,
-0x24420001, 0x504c0003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020012, 0x240c0001,
-0xac820000, 0xac8c0004, 0x5600000d, 0x24100001,
-0x8ee204e4, 0x3c040001, 0x24845754, 0xafa00014,
-0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009,
-0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038,
-0x16000003, 0x240c0001, 0x8002f5c, 0xa2ec04f4,
-0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170,
-0x8ee204e4, 0xa2e004f4, 0xaee004f0, 0xaee07274,
-0xaee204f8, 0x8f42023c, 0x10400038, 0x0,
-0x8ee20184, 0x24420001, 0xaee20184, 0x8002f5c,
-0x8ee20184, 0x8ee20504, 0x240c0040, 0x24420001,
-0x504c0003, 0x1021, 0x8ee20504, 0x24420001,
-0xaee20504, 0x8ee20504, 0x8e630018, 0x240c0003,
-0x21080, 0x571021, 0x146c000f, 0x8c440508,
-0x3c020001, 0x571021, 0x904283b1, 0x10400014,
-0x0, 0x8ee201d0, 0x8ee35240, 0x441021,
-0xaee201d0, 0x8ee201d8, 0x641821, 0x306300ff,
-0x8002f4f, 0xaee35240, 0x8ee201cc, 0x8ee30e10,
-0x441021, 0xaee201cc, 0x8ee201d8, 0x641821,
-0x306301ff, 0xaee30e10, 0x441021, 0xaee201d8,
-0x8ee20000, 0x34420040, 0x8002f5c, 0xaee20000,
-0x8ee2014c, 0x3c010001, 0x370821, 0xa02083e0,
-0x24420001, 0xaee2014c, 0x8ee2014c, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8f820108,
-0x27633000, 0x43102b, 0x14400002, 0x27622800,
-0xaf820108, 0x8f830108, 0x8f820104, 0x1462fc1e,
-0x0, 0x8fbf0060, 0x8fbe005c, 0x8fb60058,
-0x8fb50054, 0x8fb40050, 0x8fb3004c, 0x8fb20048,
-0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0068,
-0x52843, 0x10a0000d, 0x3021, 0x3c030001,
-0x34633800, 0x3c07ffff, 0x3631021, 0x82102b,
-0x50400001, 0x872021, 0x94820000, 0x24840002,
-0x24a5ffff, 0x14a0fff8, 0xc23021, 0x61c02,
-0x30c2ffff, 0x623021, 0x61c02, 0x30c2ffff,
-0x623021, 0x3e00008, 0x30c2ffff, 0x27bdff88,
-0x240f0001, 0xafbf0070, 0xafbe006c, 0xafb60068,
-0xafb50064, 0xafb40060, 0xafb3005c, 0xafb20058,
-0xafb10054, 0xafb00050, 0xa3a00027, 0xafaf002c,
-0x8ee204d4, 0x8021, 0x30420001, 0x1440002a,
-0xa3a00037, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8,
-0xe22023, 0x2c821000, 0x50400001, 0x24841000,
-0x420c2, 0x801821, 0x8ee400c8, 0x8ee500cc,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c8, 0xaee500cc, 0x8f8300c8,
-0x3c02000a, 0x3442efff, 0x1032023, 0x44102b,
-0x10400003, 0x3c02000a, 0x3442f000, 0x822021,
-0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021,
-0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4,
-0x80034cc, 0xaf8700e8, 0x3c020001, 0x571021,
-0x904283c0, 0x1040000b, 0x0, 0x3c140001,
-0x297a021, 0x8e9483c4, 0x3c130001, 0x2779821,
-0x8e7383c8, 0x3c120001, 0x2579021, 0x8003193,
-0x8e5283cc, 0x8f8300e0, 0x8f8200e4, 0x10430007,
-0x8821, 0x8f8200e4, 0x24110001, 0x8c430000,
-0x8c440004, 0xafa30018, 0xafa4001c, 0x1620000e,
-0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8,
-0x3c040001, 0x24845870, 0xafa20014, 0x8f8600e0,
-0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000,
-0x80034cc, 0x0, 0x8fa3001c, 0x8fb20018,
-0x3074ffff, 0x2694fffc, 0x621024, 0x10400058,
-0x2409821, 0x3c020080, 0x621024, 0x1040000a,
-0x3c040040, 0x8ee2007c, 0x24420001, 0xaee2007c,
-0x8ee2007c, 0x8ee201fc, 0x24420001, 0xaee201fc,
-0x80034c6, 0x8ee201fc, 0x3c060004, 0x3c0b0001,
-0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080,
-0x3c080020, 0x34078000, 0x24420001, 0xaee20080,
-0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021,
-0xc3102b, 0x14400007, 0x0, 0x106b0011,
-0x0, 0x106a0015, 0x0, 0x8003049,
-0x42042, 0x10650023, 0xa3102b, 0x14400005,
-0x0, 0x10690019, 0x0, 0x8003049,
-0x42042, 0x10680021, 0x0, 0x8003049,
-0x42042, 0x8ee20034, 0x24420001, 0xaee20034,
-0x8ee20034, 0x8003049, 0x42042, 0x8ee201ec,
-0x24420001, 0xaee201ec, 0x8ee201ec, 0x8003049,
-0x42042, 0x8ee201f0, 0x24420001, 0xaee201f0,
-0x8ee201f0, 0x8003049, 0x42042, 0x8ee201f4,
-0x24420001, 0xaee201f4, 0x8ee201f4, 0x8003049,
-0x42042, 0x8ee20030, 0x24420001, 0xaee20030,
-0x8ee20030, 0x8003049, 0x42042, 0x8ee201f8,
-0x24420001, 0xaee201f8, 0x8ee201f8, 0x42042,
-0x1087047c, 0x0, 0x800300e, 0x0,
-0x3c020001, 0x571021, 0x904283b2, 0x14400084,
-0x24020001, 0x3c030001, 0x771821, 0x906383b3,
-0x1462007f, 0x3c020100, 0x8e430000, 0x621024,
-0x1040006f, 0x2402ffff, 0x14620005, 0x24100001,
-0x96430004, 0x3402ffff, 0x10620075, 0x0,
-0x92e204d8, 0x14400072, 0x0, 0x3c020001,
-0x571021, 0x8c4283b4, 0x28420005, 0x10400020,
-0x3821, 0x3c020001, 0x571021, 0x8c4283b4,
-0x18400016, 0x2821, 0x96660000, 0x520c0,
-0x971021, 0x9442777e, 0x14460009, 0x971021,
-0x94437780, 0x96620002, 0x14620005, 0x971021,
-0x94437782, 0x96620004, 0x50620008, 0x24070001,
-0x3c020001, 0x571021, 0x8c4283b4, 0x24a50001,
-0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff,
-0x10400440, 0x0, 0x80030d5, 0x0,
-0x2402021, 0xc0022fe, 0x24050006, 0x3044001f,
-0x428c0, 0x2e51021, 0x9442727c, 0x30424000,
-0x14400434, 0xb71021, 0x9443727e, 0x96620000,
-0x1462000b, 0x418c0, 0xb71021, 0x94437280,
-0x96620002, 0x14620006, 0x418c0, 0xb71021,
-0x94437282, 0x96620004, 0x10620035, 0x418c0,
-0x2e31021, 0x9442727c, 0x30428000, 0x14400421,
-0x2e31021, 0x944b727c, 0x96670000, 0xb28c0,
-0xb71021, 0x9442737e, 0x80030b7, 0x3021,
-0x420c0, 0x2e41021, 0x9443737c, 0x2e41021,
-0x944b737c, 0x30638000, 0x14600010, 0xb28c0,
-0xb71021, 0x9442737e, 0x1447fff5, 0x1602021,
-0xb71021, 0x94437380, 0x96620002, 0x5462fff1,
-0x420c0, 0xb71021, 0x94437382, 0x96620004,
-0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff,
-0x10400400, 0x0, 0x80030d5, 0x0,
-0x97430202, 0x96420000, 0x146203fa, 0x0,
-0x97430204, 0x96420002, 0x146203f6, 0x0,
-0x97430206, 0x96420004, 0x146203f2, 0x0,
-0x92420000, 0x3a030001, 0x30420001, 0x431024,
-0x10400074, 0x2402ffff, 0x8e630000, 0x14620004,
-0x3402ffff, 0x96630004, 0x1062006f, 0x240f0002,
-0x3c020001, 0x571021, 0x904283b2, 0x1440006a,
-0x240f0003, 0x92e204d8, 0x54400068, 0xafaf002c,
-0x3c020001, 0x571021, 0x8c4283b4, 0x28420005,
-0x10400020, 0x3821, 0x3c020001, 0x571021,
-0x8c4283b4, 0x18400016, 0x2821, 0x96660000,
-0x520c0, 0x971021, 0x9442777e, 0x14460009,
-0x971021, 0x94437780, 0x96620002, 0x14620005,
-0x971021, 0x94437782, 0x96620004, 0x50620008,
-0x24070001, 0x3c020001, 0x571021, 0x8c4283b4,
-0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0,
-0x30e200ff, 0x14400044, 0x240f0003, 0x80034c6,
-0x0, 0x2402021, 0xc0022fe, 0x24050006,
-0x3044001f, 0x428c0, 0x2e51021, 0x9442727c,
-0x30424000, 0x144003af, 0xb71021, 0x9443727e,
-0x96620000, 0x1462000b, 0x418c0, 0xb71021,
-0x94437280, 0x96620002, 0x14620006, 0x418c0,
-0xb71021, 0x94437282, 0x96620004, 0x10620027,
-0x418c0, 0x2e31021, 0x9442727c, 0x30428000,
-0x1440039c, 0x2e31021, 0x944b727c, 0x96670000,
-0xb28c0, 0xb71021, 0x9442737e, 0x800313c,
-0x3021, 0x420c0, 0x2e41021, 0x9443737c,
-0x2e41021, 0x944b737c, 0x30638000, 0x14600010,
-0xb28c0, 0xb71021, 0x9442737e, 0x1447fff5,
-0x1602021, 0xb71021, 0x94437380, 0x96620002,
-0x5462fff1, 0x420c0, 0xb71021, 0x94437382,
-0x96620004, 0x5462ffec, 0x420c0, 0x24060001,
-0x30c200ff, 0x1040037b, 0x0, 0x800314f,
-0x240f0003, 0x240f0001, 0xafaf002c, 0x8f420260,
-0x54102b, 0x1040003a, 0x0, 0x8f8300e4,
-0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4,
-0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2801821,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058,
-0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c,
-0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0,
-0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845878,
-0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006,
-0xc002403, 0x34a5f003, 0x80034cc, 0x0,
-0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001,
-0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
-0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201c0,
-0x24420001, 0xaee201c0, 0x8ee20000, 0x8ee301c0,
-0x2403ffbf, 0x431024, 0x8003470, 0xaee20000,
-0x96e20468, 0x54102b, 0x10400003, 0x0,
-0x240f0001, 0xa3af0027, 0x12800301, 0x24160007,
-0x24150040, 0x241e0001, 0x240e0012, 0x8ee2724c,
-0x8f430280, 0x24420001, 0x304207ff, 0x106202d3,
-0x0, 0x93a20027, 0x10400014, 0x0,
-0x8ee35240, 0x8ee25244, 0x10620009, 0x26ed5244,
-0x8ee65244, 0x8ee35244, 0x21140, 0x24425248,
-0x2e28021, 0x24630001, 0x80031bf, 0x306b00ff,
-0x92e27248, 0x1440ffca, 0x0, 0x8ee201e0,
-0x24420001, 0xaee201e0, 0x8ee201e0, 0x8ee30e10,
-0x8ee20e18, 0x1062ffc2, 0x26ed0e18, 0x8ee60e18,
-0x8ee30e18, 0x21140, 0x24420e20, 0x2e28021,
-0x24630001, 0x306b01ff, 0x96e2046a, 0x30420010,
-0x10400019, 0x0, 0x9642000c, 0x340f8100,
-0x144f0015, 0x0, 0x3c020001, 0x571021,
-0x904283c0, 0x14400010, 0x0, 0x9642000e,
-0xa6020016, 0x8e420008, 0x8e430004, 0x8e440000,
-0x2694fffc, 0xae42000c, 0xae430008, 0xae440004,
-0x9602000e, 0x26730004, 0x240f0001, 0xa3af0037,
-0x34420200, 0xa602000e, 0x8e020000, 0x8e030004,
-0x3c040001, 0x34843800, 0x306a0007, 0x26a9823,
-0x3641021, 0x262102b, 0x10400005, 0x28aa021,
-0x2641023, 0x3621823, 0x3c020020, 0x439823,
-0x26820007, 0x2404fff8, 0x9603000a, 0x446024,
-0x6a1821, 0x6c102b, 0x10400002, 0x1803821,
-0x603821, 0xae130018, 0x8f880120, 0x24e20007,
-0x443824, 0x27623800, 0x25090020, 0x122102b,
-0x50400001, 0x27693000, 0x8f820128, 0x11220004,
-0x0, 0x8f820124, 0x15220007, 0x1401821,
-0x8ee201a4, 0x8821, 0x24420001, 0xaee201a4,
-0x800324c, 0x8ee201a4, 0x8e040000, 0x8e050004,
-0x1021, 0xad130008, 0xa507000e, 0xad160018,
-0xad06001c, 0xa3302b, 0xa32823, 0x822023,
-0x862023, 0xad040000, 0xad050004, 0x8ee204c0,
-0xad020010, 0xaf890120, 0x92e24e20, 0x14400033,
-0x24110001, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c820000, 0x1456001f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062001b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee34e30, 0x24420001, 0x10550007, 0x0,
-0x8ee24e34, 0x24420001, 0x10620005, 0x0,
-0x8003239, 0x0, 0x14600005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x800324c, 0x0, 0x8ee24e30, 0x24420001,
-0x50550003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0xac960000, 0xac9e0004, 0x16200018,
-0x3c050006, 0x8e020018, 0x3c040001, 0x24845890,
-0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009,
-0x2003021, 0xc002403, 0xafa30014, 0x93a20037,
-0x10400216, 0x340f8100, 0x8e420004, 0x8e430008,
-0x8e44000c, 0xa64f000c, 0xae420000, 0xae430004,
-0xae440008, 0x96020016, 0x8003470, 0xa642000e,
-0x14ec0168, 0x28a1823, 0x960c000a, 0x9603000e,
-0x28a1023, 0xa602000a, 0x34620004, 0xa602000e,
-0x8f880120, 0x27623800, 0x25090020, 0x122102b,
-0x14400002, 0x306affff, 0x27693000, 0x8f820128,
-0x11220004, 0x0, 0x8f820124, 0x15220007,
-0x24040020, 0x8ee201a4, 0x8821, 0x24420001,
-0xaee201a4, 0x80032ca, 0x8ee201a4, 0x8ee5724c,
-0x8ee60490, 0x8ee70494, 0xa504000e, 0x24040004,
-0xad100008, 0xad040018, 0x52940, 0xa01821,
-0x1021, 0xe33821, 0xe3202b, 0xc23021,
-0xc43021, 0xad060000, 0xad070004, 0x8ee2724c,
-0xad02001c, 0x8ee204c4, 0xad020010, 0xaf890120,
-0x92e24e20, 0x14400033, 0x24110001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c820000,
-0x1456001f, 0x0, 0x8ee34e30, 0x8ee24e34,
-0x1062001b, 0x0, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e34, 0x8ee34e30, 0x24420001,
-0x10550007, 0x0, 0x8ee24e34, 0x24420001,
-0x10620005, 0x0, 0x80032b7, 0x0,
-0x14600005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400010, 0xac800000, 0x80032ca, 0x0,
-0x8ee24e30, 0x24420001, 0x50550003, 0x1021,
-0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0xac960000,
-0xac9e0004, 0x1620000d, 0x0, 0xa60c000a,
-0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104,
-0x3c040001, 0x2484589c, 0x3c050006, 0xafa20014,
-0x8ee6724c, 0x800343b, 0x34a5f00b, 0x3c010001,
-0x370821, 0xa02083c0, 0xadab0000, 0x8ee201d8,
-0x8ee3724c, 0x2442ffff, 0xaee201d8, 0x8ee201d8,
-0x24630001, 0x306307ff, 0x26e25244, 0x15a20006,
-0xaee3724c, 0x8ee201d0, 0x2442ffff, 0xaee201d0,
-0x80032ef, 0x8ee201d0, 0x8ee201cc, 0x2442ffff,
-0xaee201cc, 0x8ee201cc, 0x8f420240, 0x10400073,
-0x0, 0x8ee20e1c, 0x24420001, 0xaee20e1c,
-0x8f430240, 0x43102b, 0x14400176, 0xa021,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
-0x0, 0x8f820124, 0x14c20007, 0x0,
-0x8ee201a4, 0x8821, 0x24420001, 0xaee201a4,
-0x800334f, 0x8ee201a4, 0x8ee2724c, 0xac62001c,
-0x8ee404a8, 0x8ee504ac, 0x2462001c, 0xac620008,
-0x24020008, 0xa462000e, 0x24020011, 0xac620018,
-0xac640000, 0xac650004, 0x8ee204c4, 0xac620010,
-0xaf860120, 0x92e24e20, 0x14400033, 0x24110001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c820000, 0x144e001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x10550007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x800333c,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x800334f,
-0x0, 0x8ee24e30, 0x24420001, 0x50550003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0xac8e0000, 0xac9e0004, 0x5620000d, 0x24110001,
-0x8ee2724c, 0x3c040001, 0x248458a8, 0xafa00014,
-0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009,
-0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048,
-0x56200001, 0xaee00e1c, 0x8ee20188, 0x24420001,
-0xaee20188, 0x80033c8, 0x8ee20188, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001,
-0x27663000, 0x8f820128, 0x10c20004, 0x0,
-0x8f820124, 0x14c20007, 0x0, 0x8ee201a4,
-0x8821, 0x24420001, 0xaee201a4, 0x80033ba,
-0x8ee201a4, 0x8ee2724c, 0xac62001c, 0x8ee404a8,
-0x8ee504ac, 0x2462001c, 0xac620008, 0x24020008,
-0xa462000e, 0x24020011, 0xac620018, 0xac640000,
-0xac650004, 0x8ee204c4, 0xac620010, 0xaf860120,
-0x92e24e20, 0x14400033, 0x24110001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c820000,
-0x144e001f, 0x0, 0x8ee34e30, 0x8ee24e34,
-0x1062001b, 0x0, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e34, 0x8ee34e30, 0x24420001,
-0x10550007, 0x0, 0x8ee24e34, 0x24420001,
-0x10620005, 0x0, 0x80033a7, 0x0,
-0x14600005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400010, 0xac800000, 0x80033ba, 0x0,
-0x8ee24e30, 0x24420001, 0x50550003, 0x1021,
-0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0xac8e0000,
-0xac9e0004, 0x1620000d, 0x0, 0x8ee2724c,
-0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010,
-0x8ee6724c, 0x8f470280, 0x3c050009, 0x34a5f008,
-0xc002403, 0xafae0048, 0x8fae0048, 0x8ee20174,
-0x24420001, 0xaee20174, 0x8ee20174, 0x800346e,
-0xa021, 0x960c000a, 0x183102b, 0x54400001,
-0x1801821, 0xa603000a, 0x8f880120, 0x27623800,
-0x25090020, 0x122102b, 0x50400001, 0x27693000,
-0x8f820128, 0x11220004, 0x0, 0x8f820124,
-0x15220007, 0x24040020, 0x8ee201a4, 0x8821,
-0x24420001, 0xaee201a4, 0x800342f, 0x8ee201a4,
-0x8ee5724c, 0x8ee60490, 0x8ee70494, 0xa504000e,
-0x24040004, 0xad100008, 0xad040018, 0x52940,
-0xa01821, 0x1021, 0xe33821, 0xe3202b,
-0xc23021, 0xc43021, 0xad060000, 0xad070004,
-0x8ee2724c, 0xad02001c, 0x8ee204c4, 0xad020010,
-0xaf890120, 0x92e24e20, 0x14400033, 0x24110001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c820000, 0x1456001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x10550007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x800341c,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x800342f,
-0x0, 0x8ee24e30, 0x24420001, 0x50550003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0xac960000, 0xac9e0004, 0x1620001d, 0x0,
-0xa60c000a, 0x8f820100, 0xafa20010, 0x8f820104,
-0x3c040001, 0x2484589c, 0x3c050006, 0xafa20014,
-0x8ee6724c, 0x34a5f00d, 0xc002403, 0x2003821,
-0x93a20037, 0x10400031, 0x340f8100, 0x8e420004,
-0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000,
-0xae430004, 0xae440008, 0x96020016, 0xa642000e,
-0x9602000e, 0x3042fdff, 0x8003470, 0xa602000e,
-0x8ee201d8, 0x2442ffff, 0xaee201d8, 0x8ee201d8,
-0x8ee201cc, 0x3c04001f, 0x3c010001, 0x370821,
-0xa03e83c0, 0x2442ffff, 0xaee201cc, 0x9603000a,
-0x3484ffff, 0x8ee201cc, 0x6a1821, 0x2639821,
-0x93202b, 0x10800003, 0x3c02fff5, 0x34421000,
-0x2629821, 0xadab0000, 0x8ee2724c, 0x24420001,
-0x304207ff, 0xaee2724c, 0x8f420240, 0x10400004,
-0x283a023, 0x8ee20e1c, 0x24420001, 0xaee20e1c,
-0xa3a00027, 0x1680fd29, 0x0, 0x12800024,
-0x0, 0x3c010001, 0x370821, 0xac3483c4,
-0x3c010001, 0x370821, 0xac3383c8, 0x3c010001,
-0x370821, 0xac3283cc, 0x93a20037, 0x10400008,
-0x0, 0x3c020001, 0x571021, 0x8c4283cc,
-0x24420004, 0x3c010001, 0x370821, 0xac2283cc,
-0x8ee2724c, 0x8f430280, 0x24420001, 0x304207ff,
-0x14620006, 0x0, 0x8ee201c4, 0x24420001,
-0xaee201c4, 0x80034cc, 0x8ee201c4, 0x8ee201bc,
-0x24420001, 0xaee201bc, 0x80034cc, 0x8ee201bc,
-0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0,
-0x8ee500c4, 0x1021, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0xaee400c0, 0xaee500c4,
-0x8faf002c, 0x24020002, 0x11e2000f, 0x29e20003,
-0x14400017, 0x24020003, 0x15e20015, 0x0,
-0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001,
-0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0,
-0x80034c6, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc,
-0x24630001, 0x2c640001, 0x441021, 0xaee200d8,
-0xaee300dc, 0x8ee200d8, 0x80034c6, 0x8ee300dc,
-0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001,
-0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8,
-0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003,
-0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0070,
-0x8fbe006c, 0x8fb60068, 0x8fb50064, 0x8fb40060,
-0x8fb3005c, 0x8fb20058, 0x8fb10054, 0x8fb00050,
-0x3e00008, 0x27bd0078, 0x27bdffb0, 0xafb50044,
-0xa821, 0xafb00030, 0x8021, 0xafbf004c,
-0xafb60048, 0xafb40040, 0xafb3003c, 0xafb20038,
-0xafb10034, 0x8ee204d4, 0x24140001, 0x30420001,
-0x1440002a, 0xb021, 0x8f8700e0, 0x8f8800c4,
-0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001,
-0x24841000, 0x420c2, 0x801821, 0x8ee400c8,
-0x8ee500cc, 0x1021, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0xaee400c8, 0xaee500cc,
-0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023,
-0x44102b, 0x10400003, 0x3c02000a, 0x3442f000,
-0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8,
-0xaf8700e4, 0x8003850, 0xaf8700e8, 0x3c020001,
-0x571021, 0x904283c0, 0x1040000b, 0x0,
-0x3c130001, 0x2779821, 0x8e7383c4, 0x3c110001,
-0x2378821, 0x8e3183c8, 0x3c120001, 0x2579021,
-0x80036e8, 0x8e5283cc, 0x8f8300e0, 0x8f8200e4,
-0x10430007, 0x4821, 0x8f8200e4, 0x24090001,
-0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c,
-0x1520000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010,
-0x8f8200c8, 0x3c040001, 0x24845870, 0xafa20014,
-0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403,
-0x34a5f000, 0x8003850, 0x0, 0x8fa3001c,
-0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024,
-0x10400058, 0x2408821, 0x3c020080, 0x621024,
-0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001,
-0xaee2007c, 0x8ee2007c, 0x8ee201fc, 0x24420001,
-0xaee201fc, 0x800384a, 0x8ee201fc, 0x3c060004,
-0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008,
-0x8ee20080, 0x3c080020, 0x34078000, 0x24420001,
-0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824,
-0x10660021, 0xc3102b, 0x14400007, 0x0,
-0x106b0011, 0x0, 0x106a0015, 0x0,
-0x8003592, 0x42042, 0x10650023, 0xa3102b,
-0x14400005, 0x0, 0x10690019, 0x0,
-0x8003592, 0x42042, 0x10680021, 0x0,
-0x8003592, 0x42042, 0x8ee20034, 0x24420001,
-0xaee20034, 0x8ee20034, 0x8003592, 0x42042,
-0x8ee201ec, 0x24420001, 0xaee201ec, 0x8ee201ec,
-0x8003592, 0x42042, 0x8ee201f0, 0x24420001,
-0xaee201f0, 0x8ee201f0, 0x8003592, 0x42042,
-0x8ee201f4, 0x24420001, 0xaee201f4, 0x8ee201f4,
-0x8003592, 0x42042, 0x8ee20030, 0x24420001,
-0xaee20030, 0x8ee20030, 0x8003592, 0x42042,
-0x8ee201f8, 0x24420001, 0xaee201f8, 0x8ee201f8,
-0x42042, 0x108702b7, 0x0, 0x8003557,
-0x0, 0x3c020001, 0x571021, 0x904283b2,
-0x14400084, 0x24020001, 0x3c030001, 0x771821,
-0x906383b3, 0x1462007f, 0x3c020100, 0x8e430000,
-0x621024, 0x1040006f, 0x2402ffff, 0x14620005,
-0x24100001, 0x96430004, 0x3402ffff, 0x10620075,
-0x0, 0x92e204d8, 0x14400072, 0x0,
-0x3c020001, 0x571021, 0x8c4283b4, 0x28420005,
-0x10400020, 0x3821, 0x3c020001, 0x571021,
-0x8c4283b4, 0x18400016, 0x2821, 0x96260000,
-0x520c0, 0x971021, 0x9442777e, 0x14460009,
-0x971021, 0x94437780, 0x96220002, 0x14620005,
-0x971021, 0x94437782, 0x96220004, 0x50620008,
-0x24070001, 0x3c020001, 0x571021, 0x8c4283b4,
-0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0,
-0x30e200ff, 0x1040027b, 0x0, 0x800361e,
-0x0, 0x2402021, 0xc0022fe, 0x24050006,
-0x3044001f, 0x428c0, 0x2e51021, 0x9442727c,
-0x30424000, 0x1440026f, 0xb71021, 0x9443727e,
-0x96220000, 0x1462000b, 0x418c0, 0xb71021,
-0x94437280, 0x96220002, 0x14620006, 0x418c0,
-0xb71021, 0x94437282, 0x96220004, 0x10620035,
-0x418c0, 0x2e31021, 0x9442727c, 0x30428000,
-0x1440025c, 0x2e31021, 0x9448727c, 0x96270000,
-0x828c0, 0xb71021, 0x9442737e, 0x8003600,
-0x3021, 0x420c0, 0x2e41021, 0x9443737c,
-0x2e41021, 0x9448737c, 0x30638000, 0x14600010,
-0x828c0, 0xb71021, 0x9442737e, 0x1447fff5,
-0x1002021, 0xb71021, 0x94437380, 0x96220002,
-0x5462fff1, 0x420c0, 0xb71021, 0x94437382,
-0x96220004, 0x5462ffec, 0x420c0, 0x24060001,
-0x30c200ff, 0x1040023b, 0x0, 0x800361e,
-0x0, 0x97430202, 0x96420000, 0x14620235,
-0x0, 0x97430204, 0x96420002, 0x14620231,
-0x0, 0x97430206, 0x96420004, 0x1462022d,
-0x0, 0x92420000, 0x3a030001, 0x30420001,
-0x431024, 0x10400074, 0x2402ffff, 0x8e230000,
-0x14620004, 0x3402ffff, 0x96230004, 0x1062006f,
-0x24140002, 0x3c020001, 0x571021, 0x904283b2,
-0x1440006a, 0x24140003, 0x92e204d8, 0x14400067,
-0x0, 0x3c020001, 0x571021, 0x8c4283b4,
-0x28420005, 0x10400020, 0x3821, 0x3c020001,
-0x571021, 0x8c4283b4, 0x18400016, 0x2821,
-0x96260000, 0x520c0, 0x971021, 0x9442777e,
-0x14460009, 0x971021, 0x94437780, 0x96220002,
-0x14620005, 0x971021, 0x94437782, 0x96220004,
-0x50620008, 0x24070001, 0x3c020001, 0x571021,
-0x8c4283b4, 0x24a50001, 0xa2102a, 0x5440ffee,
-0x520c0, 0x30e200ff, 0x14400044, 0x24140003,
-0x800384a, 0x0, 0x2402021, 0xc0022fe,
-0x24050006, 0x3044001f, 0x428c0, 0x2e51021,
-0x9442727c, 0x30424000, 0x144001ea, 0xb71021,
-0x9443727e, 0x96220000, 0x1462000b, 0x418c0,
-0xb71021, 0x94437280, 0x96220002, 0x14620006,
-0x418c0, 0xb71021, 0x94437282, 0x96220004,
-0x10620027, 0x418c0, 0x2e31021, 0x9442727c,
-0x30428000, 0x144001d7, 0x2e31021, 0x9448727c,
-0x96270000, 0x828c0, 0xb71021, 0x9442737e,
-0x8003685, 0x3021, 0x420c0, 0x2e41021,
-0x9443737c, 0x2e41021, 0x9448737c, 0x30638000,
-0x14600010, 0x828c0, 0xb71021, 0x9442737e,
-0x1447fff5, 0x1002021, 0xb71021, 0x94437380,
-0x96220002, 0x5462fff1, 0x420c0, 0xb71021,
-0x94437382, 0x96220004, 0x5462ffec, 0x420c0,
-0x24060001, 0x30c200ff, 0x104001b6, 0x0,
-0x8003698, 0x24140003, 0x24140001, 0x8f420260,
-0x53102b, 0x10400049, 0x0, 0x8f8300e4,
-0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4,
-0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2601821,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058,
-0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c,
-0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0,
-0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845878,
-0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006,
-0xc002403, 0x34a5f003, 0x8003850, 0x0,
-0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001,
-0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
-0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001,
-0xaee201c0, 0x8ee20000, 0x8ee301c0, 0x2403ffbf,
-0x431024, 0x80037f8, 0xaee20000, 0x8ee25240,
-0xafa20010, 0x8ee25244, 0x3c040001, 0x24845884,
-0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006,
-0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001,
-0xaee201c0, 0x80037f8, 0x8ee201c0, 0x96e20468,
-0x53102b, 0x54400001, 0x3c158000, 0x12600131,
-0x3c0c001f, 0x358cffff, 0x8ee2724c, 0x8f430280,
-0x24420001, 0x304207ff, 0x10620108, 0x0,
-0x12a00014, 0x0, 0x8ee35240, 0x8ee25244,
-0x10620009, 0x26ee5244, 0x8eeb5244, 0x8ee35244,
-0x21140, 0x24425248, 0x2e28021, 0x24630001,
-0x8003712, 0x306800ff, 0x92e27248, 0x1440ffc0,
-0x3c050006, 0x8ee201e0, 0x24420001, 0xaee201e0,
-0x8ee201e0, 0x8ee30e10, 0x8ee20e18, 0x1062ffcb,
-0x26ee0e18, 0x8eeb0e18, 0xa821, 0x8ee30e18,
-0x21140, 0x24420e20, 0x2e28021, 0x24630001,
-0x306801ff, 0x96e2046a, 0x30420010, 0x10400017,
-0x34028100, 0x9643000c, 0x14620014, 0x0,
-0x3c020001, 0x571021, 0x904283c0, 0x1440000f,
-0x0, 0x9642000e, 0xa6020016, 0x8e420008,
-0x8e430004, 0x8e440000, 0x2673fffc, 0xae42000c,
-0xae430008, 0xae440004, 0x9602000e, 0x26310004,
-0x24160001, 0x34420200, 0xa602000e, 0x9603000a,
-0x2605021, 0x73102b, 0x10400002, 0x2606821,
-0x605021, 0x2d42003d, 0x1040002a, 0x3821,
-0x9623000c, 0x24020800, 0x54620027, 0xae110018,
-0x3c020001, 0x571021, 0x904283c0, 0x54400022,
-0xae110018, 0x26220017, 0x182102b, 0x10400013,
-0x0, 0x3c02fff5, 0x511021, 0x90421017,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x10600013, 0x26220010, 0x182102b,
-0x1040000e, 0x0, 0x3c07fff5, 0xf13821,
-0x94e71010, 0x800375e, 0x24e7000e, 0x92220017,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x50600004, 0xae110018, 0x96270010,
-0x24e7000e, 0xae110018, 0x3c020001, 0x571021,
-0x904283c0, 0x2102b, 0x14e00002, 0x24ec0,
-0x1403821, 0x8f830120, 0x27623800, 0x24660020,
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128,
-0x10c20004, 0x0, 0x8f820124, 0x14c20007,
-0x2402000b, 0x8ee201a4, 0x4821, 0x24420001,
-0xaee201a4, 0x80037bf, 0x8ee201a4, 0x8e040000,
-0x8e050004, 0xac620018, 0x1751025, 0x491025,
-0xac710008, 0xa467000e, 0xac62001c, 0xac640000,
-0xac650004, 0x8ee204c0, 0xac620010, 0xaf860120,
-0x92e24e20, 0x14400038, 0x24090001, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c830000,
-0x24020007, 0x14620020, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001c, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee34e34, 0x8ee54e30,
-0x24020040, 0x24630001, 0x10620007, 0x0,
-0x8ee24e34, 0x24420001, 0x10a20005, 0x0,
-0x80037a9, 0x0, 0x14a00005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x80037bf, 0x0, 0x8ee24e30, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020007, 0xac820000,
-0x24020001, 0xac820004, 0x15200018, 0x3c050006,
-0x8e020018, 0x3c040001, 0x24845890, 0xafa20010,
-0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021,
-0xc002403, 0xafa30014, 0x32c200ff, 0x1040002b,
-0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c,
-0xa642000c, 0xae430000, 0xae440004, 0xae450008,
-0x96020016, 0x80037f8, 0xa642000e, 0x154d000a,
-0x0, 0x9602000e, 0xa613000a, 0x34420004,
-0xa602000e, 0x3c010001, 0x370821, 0xa02083c0,
-0x80037f6, 0x9821, 0x9604000a, 0x93102b,
-0x10400002, 0x2601821, 0x801821, 0x24020001,
-0xa603000a, 0x3c010001, 0x370821, 0xa02283c0,
-0x9604000a, 0x2248821, 0x191102b, 0x10400003,
-0x3c02fff5, 0x34421000, 0x2228821, 0x2649823,
-0xa821, 0x1660fef4, 0xadc80000, 0x12600021,
-0x32c200ff, 0x3c010001, 0x370821, 0xac3383c4,
-0x3c010001, 0x370821, 0xac3183c8, 0x3c010001,
-0x370821, 0x10400008, 0xac3283cc, 0x3c020001,
-0x571021, 0x8c4283cc, 0x24420004, 0x3c010001,
-0x370821, 0xac2283cc, 0x8ee2724c, 0x8f430280,
-0x24420001, 0x14620006, 0x0, 0x8ee201c4,
-0x24420001, 0xaee201c4, 0x8003850, 0x8ee201c4,
-0x8ee201bc, 0x24420001, 0xaee201bc, 0x8003850,
-0x8ee201bc, 0x97a4001e, 0x2484fffc, 0x801821,
-0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0x24020002,
-0xaee400c0, 0xaee500c4, 0x1282000f, 0x2a820003,
-0x14400017, 0x24020003, 0x16820015, 0x0,
-0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001,
-0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0,
-0x800384a, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc,
-0x24630001, 0x2c640001, 0x441021, 0xaee200d8,
-0xaee300dc, 0x8ee200d8, 0x800384a, 0x8ee300dc,
-0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001,
-0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8,
-0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003,
-0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf004c,
-0x8fb60048, 0x8fb50044, 0x8fb40040, 0x8fb3003c,
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
-0x27bd0050, 0x27bdff90, 0xafb60060, 0xb021,
-0xafbf0068, 0xafbe0064, 0xafb5005c, 0xafb40058,
-0xafb30054, 0xafb20050, 0xafb1004c, 0xafb00048,
-0x8ee204d4, 0x8821, 0x24150001, 0x30420001,
-0x1440002a, 0xa3a0002f, 0x8f8700e0, 0x8f8800c4,
-0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001,
-0x24841000, 0x420c2, 0x801821, 0x8ee400c8,
-0x8ee500cc, 0x1021, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0xaee400c8, 0xaee500cc,
-0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023,
-0x44102b, 0x10400003, 0x3c02000a, 0x3442f000,
-0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8,
-0xaf8700e4, 0x8003c5b, 0xaf8700e8, 0x3c020001,
-0x571021, 0x904283c0, 0x1040000b, 0x0,
-0x3c130001, 0x2779821, 0x8e7383c4, 0x3c100001,
-0x2178021, 0x8e1083c8, 0x3c120001, 0x2579021,
-0x8003a59, 0x8e5283cc, 0x8f8300e0, 0x8f8200e4,
-0x10430007, 0x3821, 0x8f8200e4, 0x24070001,
-0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c,
-0x14e0000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010,
-0x8f8200c8, 0x3c040001, 0x248458b4, 0xafa20014,
-0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403,
-0x34a5f200, 0x8003c5b, 0x0, 0x8fa3001c,
-0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024,
-0x10400058, 0x2408021, 0x3c020080, 0x621024,
-0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001,
-0xaee2007c, 0x8ee2007c, 0x8ee201fc, 0x24420001,
-0xaee201fc, 0x8003c55, 0x8ee201fc, 0x3c060004,
-0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008,
-0x8ee20080, 0x3c080020, 0x34078000, 0x24420001,
-0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824,
-0x10660021, 0xc3102b, 0x14400007, 0x0,
-0x106b0011, 0x0, 0x106a0015, 0x0,
-0x8003916, 0x42042, 0x10650023, 0xa3102b,
-0x14400005, 0x0, 0x10690019, 0x0,
-0x8003916, 0x42042, 0x10680021, 0x0,
-0x8003916, 0x42042, 0x8ee20034, 0x24420001,
-0xaee20034, 0x8ee20034, 0x8003916, 0x42042,
-0x8ee201ec, 0x24420001, 0xaee201ec, 0x8ee201ec,
-0x8003916, 0x42042, 0x8ee201f0, 0x24420001,
-0xaee201f0, 0x8ee201f0, 0x8003916, 0x42042,
-0x8ee201f4, 0x24420001, 0xaee201f4, 0x8ee201f4,
-0x8003916, 0x42042, 0x8ee20030, 0x24420001,
-0xaee20030, 0x8ee20030, 0x8003916, 0x42042,
-0x8ee201f8, 0x24420001, 0xaee201f8, 0x8ee201f8,
-0x42042, 0x1087033e, 0x0, 0x80038db,
-0x0, 0x3c020001, 0x571021, 0x904283b2,
-0x14400084, 0x24020001, 0x3c030001, 0x771821,
-0x906383b3, 0x1462007f, 0x3c020100, 0x8e430000,
-0x621024, 0x1040006f, 0x2402ffff, 0x14620005,
-0x24110001, 0x96430004, 0x3402ffff, 0x10620075,
-0x0, 0x92e204d8, 0x14400072, 0x0,
-0x3c020001, 0x571021, 0x8c4283b4, 0x28420005,
-0x10400020, 0x3821, 0x3c020001, 0x571021,
-0x8c4283b4, 0x18400016, 0x2821, 0x96060000,
-0x520c0, 0x971021, 0x9442777e, 0x14460009,
-0x971021, 0x94437780, 0x96020002, 0x14620005,
-0x971021, 0x94437782, 0x96020004, 0x50620008,
-0x24070001, 0x3c020001, 0x571021, 0x8c4283b4,
-0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0,
-0x30e200ff, 0x10400302, 0x0, 0x80039a2,
-0x0, 0x2402021, 0xc0022fe, 0x24050006,
-0x3044001f, 0x428c0, 0x2e51021, 0x9442727c,
-0x30424000, 0x144002f6, 0xb71021, 0x9443727e,
-0x96020000, 0x1462000b, 0x418c0, 0xb71021,
-0x94437280, 0x96020002, 0x14620006, 0x418c0,
-0xb71021, 0x94437282, 0x96020004, 0x10620035,
-0x418c0, 0x2e31021, 0x9442727c, 0x30428000,
-0x144002e3, 0x2e31021, 0x944d727c, 0x96070000,
-0xd28c0, 0xb71021, 0x9442737e, 0x8003984,
-0x3021, 0x420c0, 0x2e41021, 0x9443737c,
-0x2e41021, 0x944d737c, 0x30638000, 0x14600010,
-0xd28c0, 0xb71021, 0x9442737e, 0x1447fff5,
-0x1a02021, 0xb71021, 0x94437380, 0x96020002,
-0x5462fff1, 0x420c0, 0xb71021, 0x94437382,
-0x96020004, 0x5462ffec, 0x420c0, 0x24060001,
-0x30c200ff, 0x104002c2, 0x0, 0x80039a2,
-0x0, 0x97430202, 0x96420000, 0x146202bc,
-0x0, 0x97430204, 0x96420002, 0x146202b8,
-0x0, 0x97430206, 0x96420004, 0x146202b4,
-0x0, 0x92420000, 0x3a230001, 0x30420001,
-0x431024, 0x10400074, 0x2402ffff, 0x8e030000,
-0x14620004, 0x3402ffff, 0x96030004, 0x1062006f,
-0x24150002, 0x3c020001, 0x571021, 0x904283b2,
-0x1440006a, 0x24150003, 0x92e204d8, 0x14400067,
-0x0, 0x3c020001, 0x571021, 0x8c4283b4,
-0x28420005, 0x10400020, 0x3821, 0x3c020001,
-0x571021, 0x8c4283b4, 0x18400016, 0x2821,
-0x96060000, 0x520c0, 0x971021, 0x9442777e,
-0x14460009, 0x971021, 0x94437780, 0x96020002,
-0x14620005, 0x971021, 0x94437782, 0x96020004,
-0x50620008, 0x24070001, 0x3c020001, 0x571021,
-0x8c4283b4, 0x24a50001, 0xa2102a, 0x5440ffee,
-0x520c0, 0x30e200ff, 0x14400044, 0x24150003,
-0x8003c55, 0x0, 0x2402021, 0xc0022fe,
-0x24050006, 0x3044001f, 0x428c0, 0x2e51021,
-0x9442727c, 0x30424000, 0x14400271, 0xb71021,
-0x9443727e, 0x96020000, 0x1462000b, 0x418c0,
-0xb71021, 0x94437280, 0x96020002, 0x14620006,
-0x418c0, 0xb71021, 0x94437282, 0x96020004,
-0x10620027, 0x418c0, 0x2e31021, 0x9442727c,
-0x30428000, 0x1440025e, 0x2e31021, 0x944d727c,
-0x96070000, 0xd28c0, 0xb71021, 0x9442737e,
-0x8003a09, 0x3021, 0x420c0, 0x2e41021,
-0x9443737c, 0x2e41021, 0x944d737c, 0x30638000,
-0x14600010, 0xd28c0, 0xb71021, 0x9442737e,
-0x1447fff5, 0x1a02021, 0xb71021, 0x94437380,
-0x96020002, 0x5462fff1, 0x420c0, 0xb71021,
-0x94437382, 0x96020004, 0x5462ffec, 0x420c0,
-0x24060001, 0x30c200ff, 0x1040023d, 0x0,
-0x8003a1c, 0x24150003, 0x24150001, 0x8f420260,
-0x53102b, 0x10400036, 0x0, 0x8f8300e4,
-0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4,
-0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2601821,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058,
-0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c,
-0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0,
-0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c0,
-0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006,
-0xc002403, 0x34a5f203, 0x8003c5b, 0x0,
-0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001,
-0x248458cc, 0xafa20014, 0x8ee60e10, 0x8ee70e18,
-0x3c050006, 0xc002403, 0x34a5f202, 0x8ee201c0,
-0x24420001, 0xaee201c0, 0x8003c02, 0x8ee201c0,
-0x96e20468, 0x53102b, 0x54400001, 0x3c168000,
-0x126001cb, 0x3c0e001f, 0x35ceffff, 0x3c0ffff5,
-0x35ef1000, 0x241e0040, 0x8ee2724c, 0x8f430280,
-0x24420001, 0x304207ff, 0x1062019e, 0x0,
-0x12c00012, 0x0, 0x8ee35240, 0x8ee25244,
-0x1062000a, 0x26f85244, 0x8ef45244, 0xafb80024,
-0x8ee35244, 0x21140, 0x24425248, 0x2e28821,
-0x24630001, 0x8003a85, 0x306d00ff, 0x8ee201e0,
-0x24420001, 0xaee201e0, 0x8ee201e0, 0x8ee30e10,
-0x8ee20e18, 0x1062ffca, 0x26f80e18, 0x8ef40e18,
-0xb021, 0xafb80024, 0x8ee30e18, 0x21140,
-0x24420e20, 0x2e28821, 0x24630001, 0x306d01ff,
-0x96e2046a, 0x30420010, 0x10400018, 0x34028100,
-0x9643000c, 0x14620015, 0x0, 0x3c020001,
-0x571021, 0x904283c0, 0x14400010, 0x0,
-0x9642000e, 0xa6220016, 0x8e420008, 0x8e430004,
-0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008,
-0xae440004, 0x9622000e, 0x26100004, 0x24180001,
-0xa3b8002f, 0x34420200, 0xa622000e, 0x8e220000,
-0x8e230004, 0x3c040001, 0x34843800, 0x2003021,
-0x306a0007, 0x20a8023, 0x3641021, 0x202102b,
-0x10400005, 0x26a9821, 0x2041023, 0x3621823,
-0x3c020020, 0x438023, 0x26620007, 0x9623000a,
-0x2418fff8, 0x58c824, 0x6a1821, 0x79102b,
-0x10400002, 0x3206021, 0x606021, 0x1801821,
-0x24620007, 0x2418fff8, 0x586024, 0x26c102b,
-0x14400004, 0x1932823, 0x1832823, 0x8003ac3,
-0xc31021, 0xd31021, 0x4a2023, 0x1c4102b,
-0x54400001, 0x8f2021, 0x25420040, 0x4c102b,
-0x14400035, 0x5821, 0x94c3000c, 0x24020800,
-0x54620032, 0xae260018, 0x3c020001, 0x571021,
-0x904283c0, 0x5440002d, 0xae260018, 0x24c20017,
-0x1c2102b, 0x10400013, 0x0, 0x3c02fff5,
-0x461021, 0x90421017, 0x38430006, 0x2c630001,
-0x38420011, 0x2c420001, 0x621825, 0x10600014,
-0x24c20010, 0x1c2102b, 0x1040000e, 0x0,
-0x3c0bfff5, 0x1665821, 0x956b1010, 0x8003af4,
-0x2562000e, 0x90c20017, 0x38430006, 0x2c630001,
-0x38420011, 0x2c420001, 0x621825, 0x10600005,
-0x1601821, 0x94cb0010, 0x2562000e, 0x4a5821,
-0x1601821, 0x24620007, 0x2418fff8, 0x585824,
-0xc31021, 0x4a2023, 0x1c4102b, 0x10400002,
-0x1632823, 0x8f2021, 0xae260018, 0x3c020001,
-0x571021, 0x904283c0, 0x2102b, 0x216c0,
-0x15600002, 0xafa20044, 0x1805821, 0x30820001,
-0x10400007, 0x4021, 0x90880000, 0x24840001,
-0x1c4102b, 0x10400002, 0x24a5ffff, 0x8f2021,
-0x50a00012, 0x81c02, 0x2ca20002, 0x54400009,
-0x24a5ffff, 0x94820000, 0x24840002, 0x1024021,
-0x1c4102b, 0x10400006, 0x24a5fffe, 0x8003b21,
-0x8f2021, 0x90820000, 0x21200, 0x1024021,
-0x14a0fff2, 0x2ca20002, 0x81c02, 0x3102ffff,
-0x624021, 0x3108ffff, 0x1402821, 0x11400011,
-0x2002021, 0x2ca20002, 0x54400009, 0x24a5ffff,
-0x94820000, 0x24840002, 0x1024021, 0x1c4102b,
-0x10400006, 0x24a5fffe, 0x8003b38, 0x8f2021,
-0x90820000, 0x21200, 0x1024021, 0x14a0fff2,
-0x2ca20002, 0x81c02, 0x3102ffff, 0x624021,
-0x81c02, 0x3102ffff, 0x8f890120, 0x624021,
-0x27623800, 0x25230020, 0x62102b, 0x14400002,
-0x3108ffff, 0x27633000, 0x8f820128, 0x10620004,
-0x0, 0x8f820124, 0x14620007, 0x1402821,
-0x8ee201a4, 0x3821, 0x24420001, 0xaee201a4,
-0x8003bc9, 0x8ee201a4, 0x8e260000, 0x8e270004,
-0x81400, 0x3448000b, 0xad300008, 0xa52b000e,
-0xad280018, 0x8fb80044, 0x2021, 0x2961025,
-0x581025, 0xad22001c, 0xe5102b, 0xe53823,
-0xc43023, 0xc23023, 0xad260000, 0xad270004,
-0x8ee204c0, 0xad220010, 0xaf830120, 0x92e24e20,
-0x1440005f, 0x24070001, 0x2502ffee, 0x2c420002,
-0x14400003, 0x24020011, 0x15020024, 0x0,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c830000, 0x24020012, 0x1462000f, 0x0,
-0x8ee34e30, 0x8ee24e34, 0x1062000b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e34,
-0x8ee34e30, 0x24420001, 0x105e002a, 0x0,
-0x8003ba8, 0x0, 0x8ee24e30, 0x24420001,
-0x505e0003, 0x1021, 0x8ee24e30, 0x24420001,
-0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8003bc6, 0x24020012, 0x8ee24e30,
-0x210c0, 0x24425038, 0x2e22021, 0x8c830000,
-0x24020007, 0x1462001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x105e0007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x8003bb4,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400012, 0xac800000, 0x8003bc9,
-0x0, 0x8ee24e30, 0x24420001, 0x505e0003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x14e00019, 0x3c050006, 0x3c040001, 0x24845890,
-0x8e220018, 0x34a5f209, 0xafa20010, 0x8e220000,
-0x8e230004, 0x2203021, 0x1603821, 0xc002403,
-0xafa30014, 0x93a2002f, 0x1040002a, 0x34028100,
-0x8e430004, 0x8e440008, 0x8e45000c, 0xa642000c,
-0xae430000, 0xae440004, 0xae450008, 0x96220016,
-0x8003c02, 0xa642000e, 0x1599000a, 0x26a1823,
-0x9622000e, 0xa623000a, 0x34420004, 0xa622000e,
-0x3c010001, 0x370821, 0xa02083c0, 0x8003bff,
-0x9821, 0x9624000a, 0x83102b, 0x54400001,
-0x801821, 0x24020001, 0xa623000a, 0x3c010001,
-0x370821, 0xa02283c0, 0x9622000a, 0x4a1821,
-0x2038021, 0x1d0102b, 0x54400001, 0x20f8021,
-0x2639823, 0xb021, 0x8fb80024, 0x1660fe5e,
-0xaf0d0000, 0x12600022, 0x0, 0x3c010001,
-0x370821, 0xac3383c4, 0x3c010001, 0x370821,
-0xac3083c8, 0x3c010001, 0x370821, 0xac3283cc,
-0x93a2002f, 0x10400008, 0x0, 0x3c020001,
-0x571021, 0x8c4283cc, 0x24420004, 0x3c010001,
-0x370821, 0xac2283cc, 0x8f430280, 0x8ee2724c,
-0x14620006, 0x0, 0x8ee201c4, 0x24420001,
-0xaee201c4, 0x8003c5b, 0x8ee201c4, 0x8ee201bc,
-0x24420001, 0xaee201bc, 0x8003c5b, 0x8ee201bc,
-0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0,
-0x8ee500c4, 0x1021, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0x24020002, 0xaee400c0,
-0xaee500c4, 0x12a2000f, 0x2aa20003, 0x14400017,
-0x24020003, 0x16a20015, 0x0, 0x8ee200d0,
-0x8ee300d4, 0x24630001, 0x2c640001, 0x441021,
-0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x8003c55,
-0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001,
-0x2c640001, 0x441021, 0xaee200d8, 0xaee300dc,
-0x8ee200d8, 0x8003c55, 0x8ee300dc, 0x8ee200c8,
-0x8ee300cc, 0x24630001, 0x2c640001, 0x441021,
-0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc,
-0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008,
-0xaf8300e4, 0xaf8300e8, 0x8fbf0068, 0x8fbe0064,
-0x8fb60060, 0x8fb5005c, 0x8fb40058, 0x8fb30054,
-0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x3e00008,
-0x27bd0070, 0x27bdffe0, 0xafbf0018, 0x8ee30e14,
-0x8ee20e0c, 0x10620074, 0x0, 0x8ee30e0c,
-0x8ee20e14, 0x622023, 0x4820001, 0x24840200,
-0x8ee30e18, 0x8ee20e14, 0x43102b, 0x14400004,
-0x24020200, 0x8ee30e14, 0x8003c7d, 0x431823,
-0x8ee20e18, 0x8ee30e14, 0x431023, 0x2443ffff,
-0x804821, 0x69102a, 0x54400001, 0x604821,
-0x8f870100, 0x27623000, 0x24e80020, 0x102102b,
-0x50400001, 0x27682800, 0x8f820108, 0x11020004,
-0x0, 0x8f820104, 0x15020007, 0x1021,
-0x8ee201a8, 0x2021, 0x24420001, 0xaee201a8,
-0x8003cbf, 0x8ee201a8, 0x8ee40e14, 0x42140,
-0x801821, 0x8ee40460, 0x8ee50464, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee30e14, 0x91140, 0xa4e2000e,
-0x24020002, 0xace20018, 0x31940, 0x24630e20,
-0x2e31021, 0xace20008, 0x8ee20e14, 0xace2001c,
-0x8ee204cc, 0xace20010, 0xaf880100, 0x92e204ec,
-0x14400011, 0x24040001, 0x8ee24e28, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e28,
-0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0,
-0x24424e38, 0x2e21821, 0x24020002, 0xac620000,
-0x24020001, 0xac620004, 0x1480000e, 0x24030040,
-0x8ee20e14, 0xafa20010, 0x8ee20e18, 0x3c050007,
-0xafa20014, 0x8ee60e0c, 0x8ee70e10, 0x3c040001,
-0x248458d4, 0xc002403, 0x34a5f001, 0x8003cdd,
-0x0, 0x8ee20500, 0x24420001, 0x50430003,
-0x1021, 0x8ee20500, 0x24420001, 0xaee20500,
-0x8ee20500, 0x21080, 0x571021, 0xac490508,
-0x8ee20e14, 0x491021, 0x304201ff, 0xaee20e14,
-0x8ee30e14, 0x8ee20e0c, 0x14620005, 0x0,
-0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0,
-0xafbf0018, 0x8ee3523c, 0x8ee25238, 0x10620074,
-0x0, 0x8ee35238, 0x8ee2523c, 0x622023,
-0x4820001, 0x24840100, 0x8ee35244, 0x8ee2523c,
-0x43102b, 0x14400004, 0x24020100, 0x8ee3523c,
-0x8003cff, 0x431823, 0x8ee25244, 0x8ee3523c,
-0x431023, 0x2443ffff, 0x804821, 0x69102a,
-0x54400001, 0x604821, 0x8f870100, 0x27623000,
-0x24e80020, 0x102102b, 0x50400001, 0x27682800,
-0x8f820108, 0x11020004, 0x0, 0x8f820104,
-0x15020007, 0x1021, 0x8ee201a8, 0x2021,
-0x24420001, 0xaee201a8, 0x8003d41, 0x8ee201a8,
-0x8ee4523c, 0x42140, 0x801821, 0x8ee40470,
-0x8ee50474, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xace40000, 0xace50004, 0x8ee3523c,
-0x91140, 0xa4e2000e, 0x24020003, 0xace20018,
-0x31940, 0x24635248, 0x2e31021, 0xace20008,
-0x8ee2523c, 0xace2001c, 0x8ee204cc, 0xace20010,
-0xaf880100, 0x92e204ec, 0x14400011, 0x24040001,
-0x8ee24e28, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e28, 0x24420001, 0xaee24e28,
-0x8ee24e28, 0x210c0, 0x24424e38, 0x2e21821,
-0x24020003, 0xac620000, 0x24020001, 0xac620004,
-0x1480000e, 0x24030040, 0x8ee2523c, 0xafa20010,
-0x8ee25244, 0x3c050007, 0xafa20014, 0x8ee65238,
-0x8ee75240, 0x3c040001, 0x248458e0, 0xc002403,
-0x34a5f010, 0x8003d5f, 0x0, 0x8ee20500,
-0x24420001, 0x50430003, 0x1021, 0x8ee20500,
-0x24420001, 0xaee20500, 0x8ee20500, 0x21080,
-0x571021, 0xac490508, 0x8ee2523c, 0x491021,
-0x304200ff, 0xaee2523c, 0x8ee3523c, 0x8ee25238,
-0x14620005, 0x0, 0x8f820060, 0x2403feff,
-0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x8f820120, 0x8ee34e34, 0x8f820124,
-0x8f860128, 0x24020040, 0x24630001, 0x50620003,
-0x1021, 0x8ee24e34, 0x24420001, 0xaee24e34,
-0x8ee24e34, 0x8ee44e34, 0x8ee34e30, 0x210c0,
-0x24425038, 0x14830007, 0x2e22821, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8003d92,
-0xaca00000, 0x8ee24e34, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e34, 0x24420001,
-0x210c0, 0x24425038, 0x2e22821, 0x8ca20004,
-0x8f830128, 0x21140, 0x621821, 0xaf830128,
-0xaca00000, 0x8cc20018, 0x2443fffe, 0x2c620012,
-0x10400008, 0x31080, 0x3c010001, 0x220821,
-0x8c2258f0, 0x400008, 0x0, 0x24020001,
-0xaee24e24, 0x3e00008, 0x0, 0x27bdffc8,
-0xafbf0030, 0xafb5002c, 0xafb40028, 0xafb30024,
-0xafb20020, 0xafb1001c, 0xafb00018, 0x8f830128,
-0x8f820124, 0x106202b0, 0x9821, 0x3c11001f,
-0x3631ffff, 0x3c12fff5, 0x36521000, 0x24150012,
-0x24140040, 0x8f8c0128, 0x8f820128, 0x24420020,
-0xaf820128, 0x9182001b, 0x8f830128, 0x2443fffe,
-0x2c620012, 0x1040029c, 0x31080, 0x3c010001,
-0x220821, 0x8c225948, 0x400008, 0x0,
-0x8f420218, 0x30420100, 0x10400007, 0x0,
-0x95830016, 0x95820018, 0x621823, 0x31402,
-0x431021, 0xa5820016, 0x8d82001c, 0x3c038000,
-0x3044ffff, 0x436824, 0x3c030800, 0x431824,
-0x11a00004, 0xad84001c, 0x41140, 0x8003dd8,
-0x24425248, 0x41140, 0x24420e20, 0x2e25821,
-0x9562000e, 0x3042fffc, 0x10600004, 0xa562000e,
-0x95840016, 0x8003ec0, 0x0, 0x8d690018,
-0x4021, 0x952a0000, 0x25290002, 0x95270000,
-0x25290002, 0x95260000, 0x25290002, 0x95250000,
-0x25290002, 0x95240000, 0x25290002, 0x95230000,
-0x25290002, 0x95220000, 0x25290002, 0x1475021,
-0x1465021, 0x1455021, 0x1445021, 0x1435021,
-0x1425021, 0xa1c02, 0x3142ffff, 0x625021,
-0xa1c02, 0x3142ffff, 0x625021, 0x96e2046a,
-0x314effff, 0x30420002, 0x10400044, 0x5021,
-0x25220014, 0x222102b, 0x10400014, 0x1201821,
-0x2405000a, 0x2021, 0x223102b, 0x54400001,
-0x721821, 0x94620000, 0x24630002, 0x24a5ffff,
-0x14a0fff9, 0x822021, 0x41c02, 0x3082ffff,
-0x622021, 0x41402, 0x3083ffff, 0x431021,
-0x3042ffff, 0x8003e33, 0x1425021, 0x952a0000,
-0x25290002, 0x95280000, 0x25290002, 0x95270000,
-0x25290002, 0x95260000, 0x25290002, 0x95250000,
-0x25290002, 0x95230000, 0x25290002, 0x95220000,
-0x25290002, 0x95240000, 0x25290002, 0x1485021,
-0x1475021, 0x1465021, 0x1455021, 0x1435021,
-0x1425021, 0x95220000, 0x95230002, 0x1445021,
-0x1425021, 0x1435021, 0xa1c02, 0x3142ffff,
-0x625021, 0xa1c02, 0x3142ffff, 0x625021,
-0x3148ffff, 0x51000001, 0x3408ffff, 0x8d620018,
-0x9443000c, 0x24020800, 0x54620005, 0xa5680010,
-0x9562000e, 0x34420002, 0xa562000e, 0xa5680010,
-0x96e2046a, 0x2821, 0x30420008, 0x14400056,
-0x3021, 0x8d630018, 0x24620024, 0x222102b,
-0x10400034, 0x24690010, 0x229102b, 0x54400001,
-0x1324821, 0x95250000, 0x24690014, 0x229102b,
-0x10400002, 0x24a5ffec, 0x1324821, 0x95220000,
-0x30420fff, 0x14400003, 0x25290002, 0x8003e60,
-0x24130001, 0x9821, 0xa03021, 0x229102b,
-0x54400001, 0x1324821, 0x91220001, 0x25290002,
-0xa22821, 0x229102b, 0x54400001, 0x1324821,
-0x25290002, 0x229102b, 0x54400001, 0x1324821,
-0x95220000, 0x25290002, 0xa22821, 0x229102b,
-0x54400001, 0x1324821, 0x95220000, 0x25290002,
-0xa22821, 0x229102b, 0x54400001, 0x1324821,
-0x95220000, 0x25290002, 0xa22821, 0x229102b,
-0x54400001, 0x1324821, 0x95220000, 0x8003e99,
-0xa22821, 0x94650010, 0x94620014, 0x24690016,
-0x30420fff, 0x14400003, 0x24a5ffec, 0x8003e8c,
-0x24130001, 0x9821, 0xa03021, 0x91230001,
-0x25290004, 0x95220000, 0x25290002, 0x95240000,
-0x25290002, 0xa32821, 0xa22821, 0x95220000,
-0x95230002, 0xa42821, 0xa22821, 0xa32821,
-0x51c02, 0x30a2ffff, 0x622821, 0x51c02,
-0x30a2ffff, 0x622821, 0x96e2046a, 0x30420001,
-0x1040001e, 0x2021, 0x95820016, 0x4e2023,
-0x41402, 0x822021, 0x326200ff, 0x50400002,
-0x862021, 0x852021, 0x41402, 0x822021,
-0x3084ffff, 0x50800001, 0x3404ffff, 0x8d620018,
-0x24430017, 0x223102b, 0x54400001, 0x721821,
-0x90620000, 0x38430011, 0x2c630001, 0x38420006,
-0x2c420001, 0x621825, 0x10600004, 0x0,
-0x9562000e, 0x34420001, 0xa562000e, 0x9562000e,
-0x240a0002, 0x30420004, 0x10400002, 0xa5640012,
-0x240a0004, 0x8f880120, 0x27623800, 0x25090020,
-0x122102b, 0x50400001, 0x27693000, 0x8f820128,
-0x11220004, 0x0, 0x8f820124, 0x15220007,
-0x24040020, 0x8ee201a4, 0x8021, 0x24420001,
-0xaee201a4, 0x8003f4f, 0x8ee201a4, 0x8ee5724c,
-0x8ee60490, 0x8ee70494, 0xad0b0008, 0xa504000e,
-0xad0a0018, 0x52940, 0xa01821, 0x1021,
-0xe33821, 0xe3202b, 0xc23021, 0xc43021,
-0xad060000, 0xad070004, 0x8ee2724c, 0x4d1025,
-0xad02001c, 0x8ee204c4, 0xad020010, 0xaf890120,
-0x92e24e20, 0x14400060, 0x24100001, 0x2543ffee,
-0x2c630002, 0x39420011, 0x2c420001, 0x621825,
-0x10600024, 0x0, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c820000, 0x1455000f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062000b,
-0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee34e30, 0x24420001, 0x1054002b,
-0x0, 0x8003f2e, 0x0, 0x8ee24e30,
-0x24420001, 0x50540003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020001, 0x8003f4e,
-0xac950000, 0x8ee24e30, 0x210c0, 0x24425038,
-0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee34e30, 0x24420001, 0x10540007,
-0x0, 0x8ee24e34, 0x24420001, 0x10620005,
-0x0, 0x8003f3a, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400012,
-0xac800000, 0x8003f4f, 0x0, 0x8ee24e30,
-0x24420001, 0x50540003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020007, 0xac820000,
-0x24020001, 0xac820004, 0x1600000d, 0x0,
-0x8f820120, 0x3c040001, 0x24845938, 0xafa00014,
-0xafa20010, 0x8d86001c, 0x8f870124, 0x3c050008,
-0xc002403, 0x34a50001, 0x8004057, 0x0,
-0x8ee2724c, 0x24420001, 0x304207ff, 0x11a00006,
-0xaee2724c, 0x8ee201d0, 0x2442ffff, 0xaee201d0,
-0x8003f6b, 0x8ee201d0, 0x8ee201cc, 0x2442ffff,
-0xaee201cc, 0x8ee201cc, 0x8ee201d8, 0x2442ffff,
-0xaee201d8, 0x8004057, 0x8ee201d8, 0x8f420240,
-0x104000e5, 0x0, 0x8ee20e1c, 0x24420001,
-0x8004057, 0xaee20e1c, 0x9582001e, 0xad82001c,
-0x8f420240, 0x10400072, 0x0, 0x8ee20e1c,
-0x24420001, 0xaee20e1c, 0x8f430240, 0x43102b,
-0x144000d5, 0x0, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x10c20004, 0x0, 0x8f820124,
-0x14c20007, 0x0, 0x8ee201a4, 0x8021,
-0x24420001, 0xaee201a4, 0x8003fda, 0x8ee201a4,
-0x8ee2724c, 0xac62001c, 0x8ee404a8, 0x8ee504ac,
-0x2462001c, 0xac620008, 0x24020008, 0xa462000e,
-0x24020011, 0xac620018, 0xac640000, 0xac650004,
-0x8ee204c4, 0xac620010, 0xaf860120, 0x92e24e20,
-0x14400034, 0x24100001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c820000, 0x1455001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee34e30, 0x24420001, 0x10540007,
-0x0, 0x8ee24e34, 0x24420001, 0x10620005,
-0x0, 0x8003fc6, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400011,
-0xac800000, 0x8003fda, 0x0, 0x8ee24e30,
-0x24420001, 0x50540003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x24020001, 0xac950000,
-0xac820004, 0x5600000b, 0x24100001, 0x8ee2724c,
-0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010,
-0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403,
-0x34a5f008, 0x56000001, 0xaee00e1c, 0x8ee20188,
-0x24420001, 0xaee20188, 0x8004050, 0x8ee20188,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
-0x0, 0x8f820124, 0x14c20007, 0x0,
-0x8ee201a4, 0x8021, 0x24420001, 0xaee201a4,
-0x8004044, 0x8ee201a4, 0x8ee2724c, 0xac62001c,
-0x8ee404a8, 0x8ee504ac, 0x2462001c, 0xac620008,
-0x24020008, 0xa462000e, 0x24020011, 0xac620018,
-0xac640000, 0xac650004, 0x8ee204c4, 0xac620010,
-0xaf860120, 0x92e24e20, 0x14400034, 0x24100001,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x8c820000, 0x1455001f, 0x0, 0x8ee34e30,
-0x8ee24e34, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e34, 0x8ee34e30,
-0x24420001, 0x10540007, 0x0, 0x8ee24e34,
-0x24420001, 0x10620005, 0x0, 0x8004030,
-0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400011, 0xac800000, 0x8004044,
-0x0, 0x8ee24e30, 0x24420001, 0x50540003,
-0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30,
-0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021,
-0x24020001, 0xac950000, 0xac820004, 0x1600000b,
-0x0, 0x8ee2724c, 0x3c040001, 0x248458a8,
-0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280,
-0x3c050009, 0xc002403, 0x34a5f008, 0x8ee20174,
-0x24420001, 0xaee20174, 0x8004057, 0x8ee20174,
-0x24020001, 0xaee24e24, 0x8f830128, 0x8f820124,
-0x1462fd58, 0x0, 0x8fbf0030, 0x8fb5002c,
-0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0038, 0x27bdffe8,
-0x27840208, 0x27450200, 0x24060008, 0xafbf0014,
-0xc00249a, 0xafb00010, 0x2021, 0x24100001,
-0x2402241f, 0xaf900210, 0xaf900200, 0xaf800204,
-0xaf820214, 0x8f460248, 0x24030004, 0x3c020040,
-0x3c010001, 0xac235cc4, 0x3c010001, 0xac235cc8,
-0x3c010001, 0xac205d9c, 0x3c010001, 0xac225cc0,
-0x3c010001, 0xac235cc8, 0xc005108, 0x24050004,
-0xc004822, 0x0, 0x8ee20000, 0x3c03feff,
-0x3463fffd, 0x431024, 0xaee20000, 0x3c023c00,
-0xaf82021c, 0x3c010001, 0x370821, 0xac3083ac,
-0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018,
-0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018,
-0xafa00010, 0xafa00014, 0x8f860200, 0x3c040001,
-0x248459f0, 0xc002403, 0x3821, 0x8ee20280,
-0x24420001, 0xaee20280, 0x8ee20280, 0x8f830200,
-0x3c023f00, 0x621824, 0x8fbf0018, 0x3c020400,
-0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020,
-0xafb1001c, 0xafb00018, 0x8f900220, 0x8ee20214,
-0x3821, 0x24420001, 0xaee20214, 0x8ee20214,
-0x3c020300, 0x2021024, 0x10400027, 0x3c110400,
-0xc00429b, 0x0, 0x3c020100, 0x2021024,
-0x10400007, 0x0, 0x8ee20218, 0x24420001,
-0xaee20218, 0x8ee20218, 0x80040c6, 0x3c03fdff,
-0x8ee2021c, 0x24420001, 0xaee2021c, 0x8ee2021c,
-0x3c03fdff, 0x3463ffff, 0x3c0808ff, 0x3508ffff,
-0x8ee20000, 0x3c040001, 0x248459fc, 0x3c050008,
-0x2003021, 0x431024, 0xaee20000, 0x8f820220,
-0x3821, 0x3c030300, 0x481024, 0x431025,
-0xaf820220, 0xafa00010, 0xc002403, 0xafa00014,
-0x8004296, 0x0, 0x2111024, 0x1040001f,
-0x3c024000, 0x8f830224, 0x24021402, 0x1462000b,
-0x3c03fdff, 0x3c040001, 0x24845a08, 0x3c050008,
-0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff,
-0xc002403, 0x3821, 0x3c03fdff, 0x8ee20000,
-0x3463ffff, 0x2002021, 0x431024, 0xc004e54,
-0xaee20000, 0x8ee20220, 0x24420001, 0xaee20220,
-0x8ee20220, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x8004295, 0x511025, 0x2021024,
-0x10400142, 0x0, 0x8ee2022c, 0x24420001,
-0xaee2022c, 0x8ee2022c, 0x8f820220, 0x3c0308ff,
-0x3463ffff, 0x431024, 0x34420004, 0xaf820220,
-0x8f830054, 0x8f820054, 0x800410e, 0x24630002,
-0x8f820054, 0x621023, 0x2c420003, 0x1440fffc,
-0x0, 0x8f8600e0, 0x8f8400e4, 0x30c20007,
-0x10400012, 0x0, 0x8f8300e4, 0x2402fff8,
-0xc21024, 0x1043000d, 0x0, 0x8f820054,
-0x8f8300e0, 0x14c30009, 0x24440050, 0x8f820054,
-0x821023, 0x2c420051, 0x10400004, 0x0,
-0x8f8200e0, 0x10c2fff9, 0x0, 0x8f820220,
-0x3c0308ff, 0x3463fffd, 0x431024, 0xaf820220,
-0x8f8600e0, 0x30c20007, 0x10400003, 0x2402fff8,
-0xc23024, 0xaf8600e0, 0x8f8300c4, 0x3c02001f,
-0x3442ffff, 0x24680008, 0x48102b, 0x10400003,
-0x3c02fff5, 0x34421000, 0x1024021, 0x8f8b00c8,
-0x8f850120, 0x8f840124, 0x8004145, 0x6021,
-0x27623800, 0x82102b, 0x50400001, 0x27643000,
-0x10a40010, 0x318200ff, 0x8c820018, 0x38430007,
-0x2c630001, 0x3842000b, 0x2c420001, 0x621825,
-0x5060fff3, 0x24840020, 0x8ee20240, 0x240c0001,
-0x24420001, 0xaee20240, 0x8ee20240, 0x8c8b0008,
-0x318200ff, 0x14400065, 0x0, 0x3c020001,
-0x571021, 0x904283c0, 0x14400060, 0x0,
-0x8f8400e4, 0xc41023, 0x218c3, 0x4620001,
-0x24630200, 0x8f8900c4, 0x10600005, 0x24020001,
-0x10620009, 0x0, 0x8004187, 0x0,
-0x8ee20230, 0x1205821, 0x24420001, 0xaee20230,
-0x80041bc, 0x8ee20230, 0x8ee20234, 0x3c05000a,
-0x24420001, 0xaee20234, 0x8c8b0000, 0x34a5f000,
-0x8ee20234, 0x12b1823, 0xa3102b, 0x54400001,
-0x651821, 0x2c62233f, 0x14400040, 0x0,
-0x8f8200e8, 0x24420008, 0xaf8200e8, 0x8f8200e8,
-0x8f8200e4, 0x1205821, 0x24420008, 0xaf8200e4,
-0x80041bc, 0x8f8200e4, 0x8ee20238, 0x3c03000a,
-0x24420001, 0xaee20238, 0x8c840000, 0x3463f000,
-0x8ee20238, 0x883823, 0x67102b, 0x54400001,
-0xe33821, 0x3c020003, 0x34420d40, 0x47102b,
-0x10400003, 0x0, 0x80041bc, 0x805821,
-0x8f8200e4, 0x24440008, 0xaf8400e4, 0x8f8400e4,
-0x10860018, 0x3c05000a, 0x34a5f000, 0x3c0a0003,
-0x354a0d40, 0x8ee2007c, 0x24420001, 0xaee2007c,
-0x8c830000, 0x8ee2007c, 0x683823, 0xa7102b,
-0x54400001, 0xe53821, 0x147102b, 0x54400007,
-0x605821, 0x8f8200e4, 0x24440008, 0xaf8400e4,
-0x8f8400e4, 0x1486ffef, 0x0, 0x14860005,
-0x0, 0x1205821, 0xaf8600e4, 0x80041bc,
-0xaf8600e8, 0xaf8400e4, 0xaf8400e8, 0x8f8200c8,
-0x3c03000a, 0x3463f000, 0x483823, 0x67102b,
-0x54400001, 0xe33821, 0x3c020003, 0x34420d3f,
-0x47102b, 0x54400007, 0x6021, 0x1683823,
-0x67102b, 0x54400003, 0xe33821, 0x80041cf,
-0x3c020003, 0x3c020003, 0x34420d3f, 0x47102b,
-0x14400016, 0x318200ff, 0x14400006, 0x0,
-0x3c020001, 0x571021, 0x904283c0, 0x1040000f,
-0x0, 0x8ee2023c, 0x3c04fdff, 0x8ee30000,
-0x3484ffff, 0x24420001, 0xaee2023c, 0x8ee2023c,
-0x24020001, 0x641824, 0x3c010001, 0x370821,
-0xa02283b8, 0x800422c, 0xaee30000, 0xaf8b00c8,
-0x8f8300c8, 0x8f8200c4, 0x3c04000a, 0x3484f000,
-0x623823, 0x87102b, 0x54400001, 0xe43821,
-0x3c020003, 0x34420d40, 0x47102b, 0x2ce30001,
-0x431025, 0x10400008, 0x0, 0x8f820220,
-0x3c0308ff, 0x3463ffff, 0x431024, 0x3c034000,
-0x431025, 0xaf820220, 0x8f8600e0, 0x8f8400e4,
-0x10c4002a, 0x0, 0x8ee2007c, 0x24420001,
-0xaee2007c, 0x8ee2007c, 0x24c2fff8, 0xaf8200e0,
-0x3c020001, 0x8c427e30, 0x3c030008, 0x8f8600e0,
-0x431024, 0x1040001d, 0x0, 0x10c4001b,
-0x240dfff8, 0x3c0a000a, 0x354af000, 0x3c0c0080,
-0x24850008, 0x27622800, 0x50a20001, 0x27651800,
-0x8c880004, 0x8c820000, 0x8ca90000, 0x3103ffff,
-0x431021, 0x4d1024, 0x24430010, 0x6b102b,
-0x54400001, 0x6a1821, 0x12b102b, 0x54400001,
-0x12a4821, 0x10690002, 0x10c1025, 0xac820004,
-0xa02021, 0x14c4ffeb, 0x24850008, 0x8f820220,
-0x3c0308ff, 0x3463ffff, 0x431024, 0x34420002,
-0xaf820220, 0x8f830054, 0x8f820054, 0x8004237,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff,
-0x3463fffb, 0x431024, 0xaf820220, 0x6010055,
-0x0, 0x8ee20228, 0x24420001, 0xaee20228,
-0x8ee20228, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420004, 0xaf820220, 0x8f830054,
-0x8f820054, 0x8004251, 0x24630002, 0x8f820054,
-0x621023, 0x2c420003, 0x1440fffc, 0x0,
-0x8f8600e0, 0x30c20007, 0x10400012, 0x0,
-0x8f8300e4, 0x2402fff8, 0xc21024, 0x1043000d,
-0x0, 0x8f820054, 0x8f8300e0, 0x14c30009,
-0x24440032, 0x8f820054, 0x821023, 0x2c420033,
-0x10400004, 0x0, 0x8f8200e0, 0x10c2fff9,
-0x0, 0x8f820220, 0x3c0308ff, 0x3463fffd,
-0x431024, 0xaf820220, 0x8f8600e0, 0x30c20007,
-0x10400003, 0x2402fff8, 0xc23024, 0xaf8600e0,
-0x240301f5, 0x8f8200e8, 0x673823, 0x718c0,
-0x431021, 0xaf8200e8, 0x8f8200e8, 0xaf8200e4,
-0x8ee2007c, 0x3c0408ff, 0x3484ffff, 0x471021,
-0xaee2007c, 0x8f820220, 0x3c038000, 0x34630002,
-0x441024, 0x431025, 0xaf820220, 0x8f830054,
-0x8f820054, 0x800428d, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024,
-0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x3c020001, 0x8c425cd8,
-0x27bdffd8, 0x10400012, 0xafbf0020, 0x3c040001,
-0x24845a14, 0x3c050008, 0x24020001, 0x3c010001,
-0x370821, 0xac2283ac, 0xafa00010, 0xafa00014,
-0x8f860220, 0x34a50498, 0x3c010001, 0xac205cd8,
-0x3c010001, 0xac225ccc, 0xc002403, 0x3821,
-0x8f420268, 0x3c037fff, 0x3463ffff, 0x431024,
-0xaf420268, 0x8ee204d0, 0x8ee404d4, 0x2403fffe,
-0x431024, 0x30840002, 0x1080011e, 0xaee204d0,
-0x8ee204d4, 0x2403fffd, 0x431024, 0xaee204d4,
-0x8f820044, 0x3c030600, 0x34632000, 0x34420020,
-0xaf820044, 0xafa30018, 0x8ee20608, 0x8f430228,
-0x24420001, 0x304a00ff, 0x514300fe, 0xafa00010,
-0x8ee20608, 0x210c0, 0x571021, 0x8fa30018,
-0x8fa4001c, 0xac43060c, 0xac440610, 0x8f830054,
-0x8f820054, 0x24690032, 0x1221023, 0x2c420033,
-0x1040006a, 0x5821, 0x24180008, 0x240f000d,
-0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120,
-0x27623800, 0x24e80020, 0x102102b, 0x50400001,
-0x27683000, 0x8f820128, 0x11020004, 0x0,
-0x8f820124, 0x15020007, 0x1021, 0x8ee201a4,
-0x2821, 0x24420001, 0xaee201a4, 0x800433d,
-0x8ee201a4, 0x8ee40608, 0x420c0, 0x801821,
-0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0xace40000, 0xace50004,
-0x8ee20608, 0xa4f8000e, 0xacef0018, 0xacea001c,
-0x210c0, 0x2442060c, 0x2e21021, 0xace20008,
-0x8ee204c4, 0xace20010, 0xaf880120, 0x92e24e20,
-0x14400033, 0x24050001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c820000, 0x144d001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee34e30, 0x24420001, 0x104c0007,
-0x0, 0x8ee24e34, 0x24420001, 0x10620005,
-0x0, 0x800432a, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x800433d, 0x0, 0x8ee24e30,
-0x24420001, 0x504c0003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0xac8d0000, 0xac8e0004,
-0x54a00006, 0x240b0001, 0x8f820054, 0x1221023,
-0x2c420033, 0x1440ff9d, 0x0, 0x316300ff,
-0x24020001, 0x54620079, 0xafa00010, 0xaeea0608,
-0x8f830054, 0x8f820054, 0x24690032, 0x1221023,
-0x2c420033, 0x10400061, 0x5821, 0x240d0008,
-0x240c0011, 0x24080012, 0x24070040, 0x240a0001,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
-0x0, 0x8f820124, 0x14c20007, 0x0,
-0x8ee201a4, 0x2821, 0x24420001, 0xaee201a4,
-0x80043a9, 0x8ee201a4, 0x8ee20608, 0xac62001c,
-0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008,
-0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004,
-0x8ee204c4, 0xac620010, 0xaf860120, 0x92e24e20,
-0x14400033, 0x24050001, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0x8c820000, 0x1448001f,
-0x0, 0x8ee34e30, 0x8ee24e34, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e34, 0x8ee34e30, 0x24420001, 0x10470007,
-0x0, 0x8ee24e34, 0x24420001, 0x10620005,
-0x0, 0x8004396, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x80043a9, 0x0, 0x8ee24e30,
-0x24420001, 0x50470003, 0x1021, 0x8ee24e30,
-0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0,
-0x24425038, 0x2e22021, 0xac880000, 0xac8a0004,
-0x54a00006, 0x240b0001, 0x8f820054, 0x1221023,
-0x2c420033, 0x1440ffa6, 0x0, 0x316300ff,
-0x24020001, 0x54620003, 0xafa00010, 0x80043d6,
-0x0, 0x3c040001, 0x24845a20, 0xafa00014,
-0x8f860120, 0x8f870124, 0x3c050009, 0xc002403,
-0x34a5f011, 0x80043d6, 0x0, 0x3c040001,
-0x24845a2c, 0xafa00014, 0x8f860120, 0x8f870124,
-0x3c050009, 0xc002403, 0x34a5f010, 0x80043d6,
-0x0, 0x3c040001, 0x24845a38, 0xafa00014,
-0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403,
-0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac,
-0x8ee201ac, 0x8ee2015c, 0x24420001, 0xaee2015c,
-0x8ee2015c, 0x8fbf0020, 0x3e00008, 0x27bd0028,
-0x3c020001, 0x8c425cd8, 0x27bdffe0, 0x1440000d,
-0xafbf0018, 0x3c040001, 0x24845a44, 0x3c050008,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499,
-0x24020001, 0x3c010001, 0xac225cd8, 0xc002403,
-0x3821, 0x8ee204d0, 0x3c030001, 0x771821,
-0x946383b2, 0x34420001, 0x10600007, 0xaee204d0,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024,
-0x34420008, 0xaf820220, 0x2021, 0xc0052a2,
-0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x3c120001,
-0x26521200, 0x3c140001, 0x8e945c50, 0x3c100001,
-0x26101120, 0x3c15c000, 0x36b50060, 0x8e8a0000,
-0x8eb30000, 0x26a400b, 0x248000a, 0x200f821,
-0x0, 0xd, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x80014d6,
-0x0, 0x80014d8, 0x3c0a0001, 0x80014d8,
-0x3c0a0002, 0x80014d8, 0x0, 0x80024a6,
-0x0, 0x80014d8, 0x3c0a0003, 0x80014d8,
-0x3c0a0004, 0x8002f8c, 0x0, 0x80014d8,
-0x3c0a0005, 0x8003ce8, 0x0, 0x8003c66,
-0x0, 0x80014d8, 0x3c0a0006, 0x80014d8,
-0x3c0a0007, 0x80014d8, 0x0, 0x80014d8,
-0x0, 0x80014d8, 0x0, 0x8002a75,
-0x0, 0x80014d8, 0x3c0a000b, 0x80014d8,
-0x3c0a000c, 0x80014d8, 0x3c0a000d, 0x800237a,
-0x0, 0x8002339, 0x0, 0x80014d8,
-0x3c0a000e, 0x8001b3c, 0x0, 0x80024a4,
-0x0, 0x80014d8, 0x3c0a000f, 0x80040a7,
-0x0, 0x8004091, 0x0, 0x80014d8,
-0x3c0a0010, 0x80014ee, 0x0, 0x80014d8,
-0x3c0a0011, 0x80014d8, 0x3c0a0012, 0x80014d8,
-0x3c0a0013, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x3c030001,
-0x34633800, 0x24050080, 0x2404001f, 0x2406ffff,
-0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220,
-0x3631021, 0xaf8200c0, 0x3631021, 0xaf8200c4,
-0x3631021, 0xaf8200c8, 0x27623800, 0xaf8200d0,
-0x27623800, 0xaf8200d4, 0x27623800, 0xaf8200d8,
-0x27621800, 0xaf8200e0, 0x27621800, 0xaf8200e4,
-0x27621800, 0xaf8200e8, 0x27621000, 0xaf8200f0,
-0x27621000, 0xaf8200f4, 0x27621000, 0xaf8200f8,
-0xaca00000, 0x2484ffff, 0x1486fffd, 0x24a50004,
-0x8f830040, 0x3c02f000, 0x621824, 0x3c025000,
-0x1062000c, 0x43102b, 0x14400006, 0x3c026000,
-0x3c024000, 0x10620008, 0x24020800, 0x8004539,
-0x0, 0x10620004, 0x24020800, 0x8004539,
-0x0, 0x24020700, 0x3c010001, 0xac225cdc,
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
-0xafb00020, 0x8f830054, 0x8f820054, 0x3c010001,
-0xac205cc4, 0x8004545, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x0,
-0xc004d71, 0x0, 0x24040001, 0x2821,
-0x27a60018, 0x34028000, 0xc00498e, 0xa7a20018,
-0x8f830054, 0x8f820054, 0x8004556, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x24050001, 0xc00494c, 0x27a60018,
-0x8f830054, 0x8f820054, 0x8004562, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x24050001, 0xc00494c, 0x27a60018,
-0x8f830054, 0x8f820054, 0x800456e, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x3c060001, 0x24c65da0, 0xc00494c,
-0x24050002, 0x8f830054, 0x8f820054, 0x800457b,
-0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x24040001, 0x24050003, 0x3c100001,
-0x26105da2, 0xc00494c, 0x2003021, 0x97a60018,
-0x3c070001, 0x94e75da0, 0x3c040001, 0x24845ab0,
-0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100,
-0xc002403, 0xafa20010, 0x97a20018, 0x1040004c,
-0x24036040, 0x96020000, 0x3042fff0, 0x1443000a,
-0x24020020, 0x3c030001, 0x94635da0, 0x54620009,
-0x24027830, 0x24020003, 0x3c010001, 0xac225cc4,
-0x80045ac, 0x24020005, 0x3c030001, 0x94635da0,
-0x24027830, 0x1462000f, 0x24030010, 0x3c020001,
-0x94425da2, 0x3042fff0, 0x1443000a, 0x24020003,
-0x3c010001, 0xac225cc4, 0x24020006, 0x3c010001,
-0xac225db0, 0x3c010001, 0xac225dbc, 0x80045e6,
-0x3c09fff0, 0x3c020001, 0x8c425cc4, 0x3c030001,
-0x94635da0, 0x34420001, 0x3c010001, 0xac225cc4,
-0x24020015, 0x1462000f, 0x0, 0x3c020001,
-0x94425da2, 0x3042fff0, 0x3843f420, 0x2c630001,
-0x3842f430, 0x2c420001, 0x621825, 0x10600005,
-0x24020003, 0x3c010001, 0xac225dbc, 0x80045e6,
-0x3c09fff0, 0x3c030001, 0x94635da0, 0x24027810,
-0x1462000b, 0x24020002, 0x3c020001, 0x94425da2,
-0x3042fff0, 0x14400006, 0x24020002, 0x24020004,
-0x3c010001, 0xac225dbc, 0x80045e6, 0x3c09fff0,
-0x3c010001, 0xac225dbc, 0x80045e6, 0x3c09fff0,
-0x3c020001, 0x8c425cc4, 0x24030001, 0x3c010001,
-0xac235dbc, 0x34420004, 0x3c010001, 0xac225cc4,
-0x3c09fff0, 0x3529bdc0, 0x3c060001, 0x8cc65cc4,
-0x3c040001, 0x24845ab0, 0x24020001, 0x3c010001,
-0xac225ccc, 0x8f820054, 0x3c070001, 0x8ce75dbc,
-0x3c030001, 0x94635da0, 0x3c080001, 0x95085da2,
-0x3c05000d, 0x34a50100, 0x3c010001, 0xac205cc8,
-0x491021, 0x3c010001, 0xac225dac, 0xafa30010,
-0xc002403, 0xafa80014, 0x8fbf0024, 0x8fb00020,
-0x3e00008, 0x27bd0028, 0x27bdffe8, 0x3c050001,
-0x8ca55cc8, 0x24060004, 0x24020001, 0x14a20014,
-0xafbf0010, 0x3c020001, 0x8c427e3c, 0x30428000,
-0x10400005, 0x3c04000f, 0x3c030001, 0x8c635dbc,
-0x8004617, 0x34844240, 0x3c040004, 0x3c030001,
-0x8c635dbc, 0x348493e0, 0x24020005, 0x14620016,
-0x0, 0x3c04003d, 0x800462f, 0x34840900,
-0x3c020001, 0x8c427e38, 0x30428000, 0x10400005,
-0x3c04001e, 0x3c030001, 0x8c635dbc, 0x800462a,
-0x34848480, 0x3c04000f, 0x3c030001, 0x8c635dbc,
-0x34844240, 0x24020005, 0x14620003, 0x0,
-0x3c04007a, 0x34841200, 0x3c020001, 0x8c425dac,
-0x8f830054, 0x441021, 0x431023, 0x44102b,
-0x14400037, 0x0, 0x3c020001, 0x8c425cd0,
-0x14400033, 0x0, 0x3c010001, 0x10c00025,
-0xac205ce0, 0x3c090001, 0x8d295cc4, 0x24070001,
-0x3c044000, 0x3c080001, 0x25087e3c, 0x250afffc,
-0x52842, 0x14a00002, 0x24c6ffff, 0x24050008,
-0xa91024, 0x10400010, 0x0, 0x14a70008,
-0x0, 0x8d020000, 0x441024, 0x1040000a,
-0x0, 0x3c010001, 0x800465b, 0xac255ce0,
-0x8d420000, 0x441024, 0x10400003, 0x0,
-0x3c010001, 0xac275ce0, 0x3c020001, 0x8c425ce0,
-0x6182b, 0x2c420001, 0x431024, 0x5440ffe5,
-0x52842, 0x8f820054, 0x3c030001, 0x8c635ce0,
-0x3c010001, 0xac225dac, 0x1060002a, 0x24020001,
-0x3c010001, 0xac255cc8, 0x3c010001, 0xac225ccc,
-0x3c020001, 0x8c425ce0, 0x10400022, 0x0,
-0x3c020001, 0x8c425ccc, 0x1040000a, 0x24020001,
-0x3c010001, 0xac205ccc, 0x3c010001, 0x370821,
-0xac2283ac, 0x3c010001, 0xac205d4c, 0x3c010001,
-0xac225d04, 0x3c030001, 0x771821, 0x8c6383ac,
-0x24020008, 0x10620005, 0x24020001, 0xc004695,
-0x0, 0x8004692, 0x0, 0x3c030001,
-0x8c635cc8, 0x10620007, 0x2402000e, 0x3c030001,
-0x8c637dd0, 0x10620003, 0x0, 0xc004e54,
-0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000,
-0x3c050001, 0x8ca55cc8, 0x3c040001, 0x8c845cf0,
-0x3442ffff, 0x621824, 0x14a40008, 0xaee30000,
-0x3c030001, 0x771821, 0x8c6383ac, 0x3c020001,
-0x8c425cf4, 0x10620008, 0x0, 0x3c020001,
-0x571021, 0x8c4283ac, 0x3c010001, 0xac255cf0,
-0x3c010001, 0xac225cf4, 0x3c030001, 0x8c635cc8,
-0x24020002, 0x10620169, 0x2c620003, 0x10400005,
-0x24020001, 0x10620008, 0x0, 0x800481c,
-0x0, 0x24020004, 0x106200b1, 0x24020001,
-0x800481d, 0x0, 0x3c020001, 0x571021,
-0x8c4283ac, 0x2443ffff, 0x2c620008, 0x1040015a,
-0x31080, 0x3c010001, 0x220821, 0x8c225ac8,
-0x400008, 0x0, 0x3c030001, 0x8c635dbc,
-0x24020005, 0x14620014, 0x0, 0x3c020001,
-0x8c425cd4, 0x1040000a, 0x24020003, 0xc004822,
-0x0, 0x24020002, 0x3c010001, 0x370821,
-0xac2283ac, 0x3c010001, 0x80046e0, 0xac205cd4,
-0x3c010001, 0x370821, 0xac2283ac, 0x3c010001,
-0x800481f, 0xac205c60, 0xc004822, 0x0,
-0x3c020001, 0x8c425cd4, 0x3c010001, 0xac205c60,
-0x104000dd, 0x24020002, 0x3c010001, 0x370821,
-0xac2283ac, 0x3c010001, 0x800481f, 0xac205cd4,
-0x3c030001, 0x8c635dbc, 0x24020005, 0x14620003,
-0x24020001, 0x3c010001, 0xac225d00, 0xc0049cf,
-0x0, 0x3c030001, 0x8c635d00, 0x800478e,
-0x24020011, 0x3c050001, 0x8ca55cc8, 0x3c060001,
-0x8cc67e3c, 0xc005108, 0x2021, 0x24020005,
-0x3c010001, 0xac205cd4, 0x3c010001, 0x370821,
-0x800481f, 0xac2283ac, 0x3c040001, 0x24845abc,
-0x3c05000f, 0x34a50100, 0x3021, 0x3821,
-0xafa00010, 0xc002403, 0xafa00014, 0x800481f,
-0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0x80047b7, 0xaf820220, 0x8f820220, 0x3c030004,
-0x431024, 0x144000a9, 0x24020007, 0x8f830054,
-0x3c020001, 0x8c425da4, 0x2463d8f0, 0x431023,
-0x2c422710, 0x144000f8, 0x24020001, 0x800481d,
-0x0, 0x3c050001, 0x8ca55cc8, 0xc0052a2,
-0x2021, 0xc005386, 0x2021, 0x3c030001,
-0x8c637e34, 0x46100ea, 0x24020001, 0x3c020008,
-0x621024, 0x10400006, 0x0, 0x8f820214,
-0x3c03ffff, 0x431024, 0x8004741, 0x3442251f,
-0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f,
-0xaf820214, 0x8ee20000, 0x3c030200, 0x431025,
-0xaee20000, 0x8f820220, 0x2403fffb, 0x431024,
-0xaf820220, 0x8f820220, 0x34420002, 0xaf820220,
-0x24020008, 0x3c010001, 0x370821, 0xac2283ac,
-0x8f820220, 0x3c030004, 0x431024, 0x14400005,
-0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0xaf820220, 0x3c030001, 0x8c635dbc, 0x24020005,
-0x1462000a, 0x0, 0x3c020001, 0x94425da2,
-0x24429fbc, 0x2c420004, 0x10400004, 0x24040018,
-0x24050002, 0xc004d93, 0x24060020, 0xc0043dd,
-0x0, 0x3c010001, 0x800481f, 0xac205d50,
-0x3c020001, 0x571021, 0x8c4283ac, 0x2443ffff,
-0x2c620008, 0x104000ac, 0x31080, 0x3c010001,
-0x220821, 0x8c225ae8, 0x400008, 0x0,
-0xc00429b, 0x0, 0x3c010001, 0xac205ccc,
-0xaf800204, 0x3c010001, 0xc004822, 0xac207e20,
-0x24020001, 0x3c010001, 0xac225ce4, 0x24020002,
-0x3c010001, 0x370821, 0x800481f, 0xac2283ac,
-0xc00489f, 0x0, 0x3c030001, 0x8c635ce4,
-0x24020009, 0x14620090, 0x24020003, 0x3c010001,
-0x370821, 0x800481f, 0xac2283ac, 0x3c020001,
-0x8c427e38, 0x30424000, 0x10400005, 0x0,
-0x8f820044, 0x3c03ffff, 0x800479f, 0x34637fff,
-0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044,
-0x8f830054, 0x80047b9, 0x24020004, 0x8f830054,
-0x3c020001, 0x8c425da4, 0x2463d8f0, 0x431023,
-0x2c422710, 0x14400074, 0x24020005, 0x3c010001,
-0x370821, 0x800481f, 0xac2283ac, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0xaf800204,
-0x3c010001, 0xac207e20, 0x8f830054, 0x24020006,
-0x3c010001, 0x370821, 0xac2283ac, 0x3c010001,
-0x800481f, 0xac235da4, 0x8f830054, 0x3c020001,
-0x8c425da4, 0x2463fff6, 0x431023, 0x2c42000a,
-0x14400059, 0x0, 0x24020007, 0x3c010001,
-0x370821, 0x800481f, 0xac2283ac, 0x8f820220,
-0x3c04f700, 0x441025, 0xaf820220, 0x8f820220,
-0x3c030300, 0x431024, 0x14400005, 0x1821,
-0x8f820220, 0x24030001, 0x441025, 0xaf820220,
-0x10600043, 0x24020001, 0x8f820214, 0x3c03ffff,
-0x3c040001, 0x8c845d98, 0x431024, 0x3442251f,
-0xaf820214, 0x24020008, 0x3c010001, 0x370821,
-0x1080000b, 0xac2283ac, 0x3c020001, 0x8c425d74,
-0x14400007, 0x24020001, 0x3c010001, 0xac227dd0,
-0xc004e54, 0x8f840220, 0x800480c, 0x0,
-0x8f820220, 0x3c030008, 0x431024, 0x14400017,
-0x2402000e, 0x3c010001, 0xac227dd0, 0x8ee20000,
-0x2021, 0x3c030200, 0x431025, 0xc005386,
-0xaee20000, 0x8f820220, 0x2403fffb, 0x431024,
-0xaf820220, 0x8f820220, 0x34420002, 0xc0043dd,
-0xaf820220, 0x3c050001, 0x8ca55cc8, 0xc0052a2,
-0x2021, 0x800481f, 0x0, 0x3c020001,
-0x8c425d74, 0x10400010, 0x0, 0x3c020001,
-0x8c425d70, 0x2442ffff, 0x3c010001, 0xac225d70,
-0x14400009, 0x24020002, 0x3c010001, 0xac205d74,
-0x3c010001, 0x800481f, 0xac225d70, 0x24020001,
-0x3c010001, 0xac225ccc, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220,
-0x34420004, 0xaf820220, 0x8f820200, 0x3c060001,
-0x8cc65cc8, 0x34420004, 0xaf820200, 0x24020002,
-0x10c2003a, 0x2cc20003, 0x10400005, 0x24020001,
-0x10c20008, 0x0, 0x8004868, 0x0,
-0x24020004, 0x10c20013, 0x24020001, 0x8004868,
-0x0, 0x3c030001, 0x8c635cb8, 0x3c020001,
-0x8c425cc0, 0x3c040001, 0x8c845cdc, 0x3c050001,
-0x8ca55cbc, 0xaf860200, 0xaf860220, 0x34630022,
-0x441025, 0x451025, 0x34420002, 0x8004867,
-0xaf830200, 0x3c030001, 0x8c635d98, 0xaf820200,
-0x10600009, 0xaf820220, 0x3c020001, 0x8c425d74,
-0x14400005, 0x3c033f00, 0x3c020001, 0x8c425cb0,
-0x800485b, 0x346300e0, 0x3c020001, 0x8c425cb0,
-0x3c033f00, 0x346300e2, 0x431025, 0xaf820200,
-0x3c030001, 0x8c635cb4, 0x3c04f700, 0x3c020001,
-0x8c425cc0, 0x3c050001, 0x8ca55cdc, 0x641825,
-0x431025, 0x451025, 0xaf820220, 0x3e00008,
-0x0, 0x8f820220, 0x3c030001, 0x8c635cc8,
-0x34420004, 0xaf820220, 0x24020001, 0x1062000f,
-0x0, 0x8f830054, 0x8f820054, 0x24630002,
-0x621023, 0x2c420003, 0x10400011, 0x0,
-0x8f820054, 0x621023, 0x2c420003, 0x1040000c,
-0x0, 0x8004879, 0x0, 0x8f830054,
-0x8f820054, 0x8004885, 0x24630007, 0x8f820054,
-0x621023, 0x2c420008, 0x1440fffc, 0x0,
-0x8f8400e0, 0x30820007, 0x1040000d, 0x0,
-0x8f820054, 0x8f8300e0, 0x14830009, 0x24450032,
-0x8f820054, 0xa21023, 0x2c420033, 0x10400004,
-0x0, 0x8f8200e0, 0x1082fff9, 0x0,
-0x8f820220, 0x2403fffd, 0x431024, 0xaf820220,
-0x3e00008, 0x0, 0x3c030001, 0x8c635ce4,
-0x3c020001, 0x8c425ce8, 0x50620004, 0x2463ffff,
-0x3c010001, 0xac235ce8, 0x2463ffff, 0x2c620009,
-0x1040009d, 0x31080, 0x3c010001, 0x220821,
-0x8c225b08, 0x400008, 0x0, 0x8f820044,
-0x34428080, 0xaf820044, 0x8f830054, 0x8004938,
-0x24020002, 0x8f830054, 0x3c020001, 0x8c425da8,
-0x2463d8f0, 0x431023, 0x2c422710, 0x1440008a,
-0x24020003, 0x8004945, 0x0, 0x8f820044,
-0x3c03ffff, 0x34637fff, 0x431024, 0xaf820044,
-0x8f830054, 0x8004938, 0x24020004, 0x8f830054,
-0x3c020001, 0x8c425da8, 0x2463fff6, 0x431023,
-0x2c42000a, 0x14400078, 0x24020005, 0x8004945,
-0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0xaf820220, 0x8f820220, 0x2403fffb, 0x431024,
-0xaf820220, 0x8f820220, 0x34420002, 0xaf820220,
-0x3c023f00, 0x344200e0, 0xaf820200, 0x8f820200,
-0x2403fffd, 0x431024, 0xaf820200, 0x24040001,
-0x3405ffff, 0xaf840204, 0x8f830054, 0x8f820054,
-0x80048ec, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
-0x42040, 0xa4102b, 0x1040fff2, 0x0,
-0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
-0x8f820214, 0x3c03ffff, 0x431024, 0x3442251f,
-0xaf820214, 0x8f820220, 0x2403fffb, 0x431024,
-0xaf820220, 0x8f820220, 0x3c04f700, 0x34840008,
-0x34420002, 0xaf820220, 0x8f820220, 0x3c033f00,
-0x346300e2, 0x441025, 0xaf820220, 0xaf830200,
-0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008,
-0x27651000, 0x8f8200f4, 0x10a20007, 0x3c038000,
-0x34630040, 0x3c020001, 0x24425c70, 0xac820000,
-0xac830004, 0xaf8500f0, 0x8f830054, 0x8004938,
-0x24020006, 0x8f830054, 0x3c020001, 0x8c425da8,
-0x2463fff6, 0x431023, 0x2c42000a, 0x14400022,
-0x24020007, 0x8004945, 0x0, 0x8f8200e0,
-0xaf8200e4, 0x8f8200e0, 0xaf8200e8, 0x8f820220,
-0x34420004, 0xaf820220, 0x8f820220, 0x2403fff7,
-0x431024, 0xaf820220, 0x8f820044, 0x34428080,
-0xaf820044, 0x8f830054, 0x24020008, 0x3c010001,
-0xac225ce4, 0x3c010001, 0x8004947, 0xac235da8,
-0x8f830054, 0x3c020001, 0x8c425da8, 0x2463d8f0,
-0x431023, 0x2c422710, 0x14400003, 0x24020009,
-0x3c010001, 0xac225ce4, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x27bdffd8,
-0xafb20018, 0x809021, 0xafb3001c, 0xa09821,
-0xafb10014, 0xc08821, 0xafb00010, 0x8021,
-0xafbf0020, 0xa6200000, 0xc004d4b, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d4b, 0x2021, 0xc004d4b, 0x24040001,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0x24100010, 0x2501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d4b, 0x108042, 0x1600fffa,
-0x2501024, 0x24100010, 0x2701024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x2701024, 0xc004d71, 0x34108000,
-0xc004d71, 0x0, 0xc004d2b, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004d71, 0x0, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821,
-0xafb20018, 0xa09021, 0xafb3001c, 0xc09821,
-0xafb00010, 0x8021, 0xafbf0020, 0xc004d4b,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0x24100010, 0x2301024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x2301024, 0x24100010, 0x2501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x2501024, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0x34108000,
-0x96620000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d4b, 0x108042, 0x1600fff8,
-0x0, 0xc004d71, 0x0, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635d00,
-0x3c020001, 0x8c425d48, 0x27bdffd8, 0xafbf0020,
-0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001,
-0xac235d48, 0x2463ffff, 0x2c620013, 0x10400349,
-0x31080, 0x3c010001, 0x220821, 0x8c225b30,
-0x400008, 0x0, 0xc004d71, 0x8021,
-0x34028000, 0xa7a20010, 0x27b10010, 0xc004d4b,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0xc004d4b,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fff8, 0x0, 0xc004d71, 0x0,
-0x8004d24, 0x24020002, 0x27b10010, 0xa7a00010,
-0x8021, 0xc004d4b, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d4b,
-0x2021, 0xc004d4b, 0x24040001, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0xc004d4b, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0xc004d71, 0x34108000,
-0xc004d71, 0x0, 0xc004d2b, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004d71, 0x0, 0x97a20010, 0x30428000,
-0x144002dc, 0x24020003, 0x8004d24, 0x0,
-0x24021200, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0xc004d4b, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0xc004d4b, 0x24040001, 0xc004d4b,
-0x2021, 0x34108000, 0x96220000, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fff8, 0x0, 0xc004d71,
-0x0, 0x8f830054, 0x8004d16, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c425db8, 0x2463ff9c,
-0x431023, 0x2c420064, 0x1440029e, 0x24020002,
-0x3c030001, 0x8c635dbc, 0x10620297, 0x2c620003,
-0x14400296, 0x24020011, 0x24020003, 0x10620005,
-0x24020004, 0x10620291, 0x2402000f, 0x8004d24,
-0x24020011, 0x8004d24, 0x24020005, 0x24020014,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d4b,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020012,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020012, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d4b, 0x108042, 0x1600fff8,
-0x0, 0xc004d71, 0x0, 0x8f830054,
-0x8004d16, 0x24020006, 0x8f830054, 0x3c020001,
-0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400250, 0x24020007, 0x8004d24, 0x0,
-0x24020006, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020013, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020013,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fff8, 0x0, 0xc004d71, 0x0,
-0x8f830054, 0x8004d16, 0x24020008, 0x8f830054,
-0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440020f, 0x24020009, 0x8004d24,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001,
-0xc004d4b, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d71, 0x34108000, 0xc004d71, 0x0,
-0xc004d2b, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004d71, 0x8021,
-0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fff8, 0x0, 0xc004d71, 0x0,
-0x8f830054, 0x8004d16, 0x2402000a, 0x8f830054,
-0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440019b, 0x2402000b, 0x8004d24,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001,
-0xc004d4b, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020017,
-0xc004d71, 0x34108000, 0xc004d71, 0x0,
-0xc004d2b, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004d71, 0x8021,
-0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020017,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fff8, 0x0, 0xc004d71, 0x0,
-0x8f830054, 0x8004d16, 0x2402000c, 0x8f830054,
-0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023,
-0x2c420064, 0x14400127, 0x24020012, 0x8004d24,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001,
-0xc004d4b, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020014,
-0xc004d71, 0x34108000, 0xc004d71, 0x0,
-0xc004d2b, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004d71, 0x8021,
-0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020014,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fff8, 0x0, 0xc004d71, 0x0,
-0x8f830054, 0x8004d16, 0x24020013, 0x8f830054,
-0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023,
-0x2c420064, 0x144000b3, 0x2402000d, 0x8004d24,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001,
-0xc004d4b, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d71, 0x34108000, 0xc004d71, 0x0,
-0xc004d2b, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004d71, 0x8021,
-0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010,
-0xc004d4b, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0xc004d4b, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d4b, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d4b, 0x24040001, 0xc004d4b, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fff8, 0x0, 0xc004d71, 0x0,
-0x8f830054, 0x8004d16, 0x2402000e, 0x24020840,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d4b,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020013,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x32020013, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d4b, 0x108042, 0x1600fff8,
-0x0, 0xc004d71, 0x0, 0x8f830054,
-0x24020010, 0x3c010001, 0xac225d00, 0x3c010001,
-0x8004d26, 0xac235db8, 0x8f830054, 0x3c020001,
-0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400004, 0x0, 0x24020011, 0x3c010001,
-0xac225d00, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044,
-0x3c030001, 0x431025, 0x3c030008, 0xaf820044,
-0x8f840054, 0x8f820054, 0xa32824, 0x8004d37,
-0x24840001, 0x8f820054, 0x821023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
-0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
-0x8f820054, 0x8004d45, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0,
-0x3442ffff, 0x42480, 0x621824, 0x3c020002,
-0x822025, 0x641825, 0xaf830044, 0x8f820044,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
-0x8f830054, 0x8f820054, 0x8004d5e, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820044, 0x3c030001, 0x431025,
-0xaf820044, 0x8f830054, 0x8f820054, 0x8004d6b,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x3e00008, 0x0,
-0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024,
-0xaf820044, 0x8f820044, 0x3c030001, 0x431025,
-0xaf820044, 0x8f830054, 0x8f820054, 0x8004d7f,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
-0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
-0x8f820054, 0x8004d8d, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x3e00008, 0x0, 0x27bdffc8, 0xafb30024,
-0x809821, 0xafb5002c, 0xa0a821, 0xafb20020,
-0xc09021, 0x32a2ffff, 0xafbf0030, 0xafb40028,
-0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010,
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d4b,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x2301024, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0x34108000,
-0x96420000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d4b, 0x108042, 0x12000075,
-0x0, 0x8004dc9, 0x0, 0x3274ffff,
-0x27b10010, 0xa7a00010, 0x8021, 0xc004d4b,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x24040001, 0xc004d4b,
-0x2021, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2901024,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x2901024, 0xc004d71,
-0x34108000, 0xc004d71, 0x0, 0xc004d2b,
-0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7,
-0x0, 0xc004d71, 0x0, 0x32a5ffff,
-0x24020001, 0x54a20004, 0x24020002, 0x97a20010,
-0x8004e14, 0x521025, 0x14a20006, 0x3271ffff,
-0x97a20010, 0x121827, 0x431024, 0xa7a20010,
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d4b,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0xc004d4b,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d4b, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
-0x10400002, 0x2021, 0x24040001, 0xc004d4b,
-0x108042, 0x1600fffa, 0x2301024, 0xc004d4b,
-0x24040001, 0xc004d4b, 0x2021, 0x34108000,
-0x96420000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d4b, 0x108042, 0x1600fff8,
-0x0, 0xc004d71, 0x0, 0x8fbf0030,
-0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
-0x0, 0x0, 0x0, 0x27bdffe8,
-0xafbf0010, 0x3c030001, 0x771821, 0x8c6383ac,
-0x24020008, 0x1462022c, 0x803021, 0x3c020001,
-0x8c425d98, 0x14400033, 0x0, 0x8f850224,
-0x38a30020, 0x2c630001, 0x38a20010, 0x2c420001,
-0x621825, 0x1460000d, 0x38a30030, 0x2c630001,
-0x38a20400, 0x2c420001, 0x621825, 0x14600007,
-0x38a30402, 0x2c630001, 0x38a20404, 0x2c420001,
-0x621825, 0x10600005, 0x0, 0xc00429b,
-0x0, 0x8004e8d, 0x2402000e, 0xc0043dd,
-0x0, 0x3c050001, 0x8ca55cc8, 0xc0052a2,
-0x2021, 0x3c030001, 0x8c635cc8, 0x24020004,
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c425cc4,
-0x8004e89, 0x2403fff7, 0x3c020001, 0x8c425cc4,
-0x431024, 0x3c010001, 0xac225cc4, 0x2402000e,
-0x3c010001, 0xc00429b, 0xac227dd0, 0x8005087,
-0x0, 0x8f820220, 0x3c030400, 0x431024,
-0x10400027, 0x2403ffbf, 0x8f850224, 0x3c020001,
-0x8c427ddc, 0xa32024, 0x431024, 0x1482000c,
-0x0, 0x3c020001, 0x8c427de0, 0x24420001,
-0x3c010001, 0xac227de0, 0x2c420002, 0x14400008,
-0x24020001, 0x3c010001, 0x8004ead, 0xac227e00,
-0x3c010001, 0xac207de0, 0x3c010001, 0xac207e00,
-0x3c020001, 0x8c427e00, 0x10400006, 0x30a20040,
-0x10400004, 0x24020001, 0x3c010001, 0x8004eb8,
-0xac227e04, 0x3c010001, 0xac207e04, 0x3c010001,
-0xac257ddc, 0x3c010001, 0x8004ec8, 0xac207e10,
-0x24020001, 0x3c010001, 0xac227e10, 0x3c010001,
-0xac207e00, 0x3c010001, 0xac207de0, 0x3c010001,
-0xac207e04, 0x3c010001, 0xac207ddc, 0x3c030001,
-0x8c637dd0, 0x3c020001, 0x8c427dd4, 0x10620003,
-0x3c020200, 0x3c010001, 0xac237dd4, 0xc21024,
-0x10400007, 0x2463ffff, 0x8f820220, 0x24030001,
-0x3c010001, 0xac235ccc, 0x8005085, 0x3c03f700,
-0x2c62000e, 0x104001a8, 0x31080, 0x3c010001,
-0x220821, 0x8c225b80, 0x400008, 0x0,
-0x3c010001, 0xac207e00, 0x3c010001, 0xac207de0,
-0x3c010001, 0xac207ddc, 0x3c010001, 0xac207e04,
-0x3c010001, 0xac207df8, 0x3c010001, 0xac207df0,
-0xc00486a, 0xaf800224, 0x24020002, 0x3c010001,
-0xac227dd0, 0x3c020001, 0x8c427e10, 0x14400056,
-0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024,
-0xc00429b, 0xaee20000, 0xaf800204, 0x8f820200,
-0x2403fffd, 0x431024, 0xaf820200, 0x3c010001,
-0xac207e20, 0x8f830054, 0x3c020001, 0x8c427df8,
-0x24040001, 0x3c010001, 0xac247e0c, 0x24420001,
-0x3c010001, 0xac227df8, 0x2c420004, 0x3c010001,
-0xac237df4, 0x14400006, 0x24020003, 0x3c010001,
-0xac245ccc, 0x3c010001, 0x8005083, 0xac207df8,
-0x3c010001, 0x8005083, 0xac227dd0, 0x8f830054,
-0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023,
-0x2c422710, 0x14400003, 0x24020004, 0x3c010001,
-0xac227dd0, 0x3c020001, 0x8c427e10, 0x14400026,
-0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024,
-0x8005083, 0xaee20000, 0x3c040001, 0x8c845d9c,
-0x3c010001, 0xc00508a, 0xac207de8, 0x3c020001,
-0x8c427e1c, 0xaf820204, 0x3c020001, 0x8c427e10,
-0x14400015, 0x3c03fdff, 0x8ee20000, 0x3463ffff,
-0x431024, 0xaee20000, 0x8f820204, 0x30420030,
-0x1440013c, 0x24020002, 0x3c030001, 0x8c637e1c,
-0x24020005, 0x3c010001, 0xac227dd0, 0x3c010001,
-0x8005083, 0xac237e20, 0x3c020001, 0x8c427e10,
-0x10400010, 0x3c03fdff, 0x3c020001, 0x8c425d6c,
-0x24420001, 0x3c010001, 0xac225d6c, 0x2c420002,
-0x14400131, 0x24020001, 0x3c010001, 0xac225d74,
-0x3c010001, 0xac205d6c, 0x3c010001, 0x8005083,
-0xac225ccc, 0x8ee20000, 0x3463ffff, 0x431024,
-0xaee20000, 0x3c020001, 0x8c427e00, 0x10400122,
-0x0, 0x3c020001, 0x8c427ddc, 0x1040011e,
-0x0, 0x3c010001, 0xac227e08, 0x24020003,
-0x3c010001, 0xac227de0, 0x8005024, 0x24020006,
-0x3c010001, 0xac207de8, 0x8f820204, 0x34420040,
-0xaf820204, 0x3c020001, 0x8c427e20, 0x24030007,
-0x3c010001, 0xac237dd0, 0x34420040, 0x3c010001,
-0xac227e20, 0x3c020001, 0x8c427e00, 0x10400005,
-0x0, 0x3c020001, 0x8c427ddc, 0x104000f9,
-0x24020002, 0x3c050001, 0x24a57de0, 0x8ca20000,
-0x2c424e21, 0x104000f3, 0x24020002, 0x3c020001,
-0x8c427e04, 0x104000f8, 0x2404ffbf, 0x3c020001,
-0x8c427ddc, 0x3c030001, 0x8c637e08, 0x441024,
-0x641824, 0x10430004, 0x24020001, 0x3c010001,
-0x8005083, 0xac227dd0, 0x24020003, 0xaca20000,
-0x24020008, 0x3c010001, 0xac227dd0, 0x3c020001,
-0x8c427e0c, 0x1040000c, 0x24020001, 0x3c040001,
-0xc005097, 0x8c847ddc, 0x3c020001, 0x8c427e28,
-0x14400005, 0x24020001, 0x3c020001, 0x8c427e24,
-0x10400006, 0x24020001, 0x3c010001, 0xac225ccc,
-0x3c010001, 0x8005083, 0xac207df8, 0x3c020001,
-0x8c427df0, 0x3c030001, 0x8c637ddc, 0x2c420001,
-0x210c0, 0x30630008, 0x3c010001, 0xac227df0,
-0x3c010001, 0xac237dec, 0x8f830054, 0x24020009,
-0x3c010001, 0xac227dd0, 0x3c010001, 0x8005083,
-0xac237df4, 0x8f830054, 0x3c020001, 0x8c427df4,
-0x2463d8f0, 0x431023, 0x2c422710, 0x144000a8,
-0x0, 0x3c020001, 0x8c427e00, 0x10400005,
-0x0, 0x3c020001, 0x8c427ddc, 0x104000a9,
-0x24020002, 0x3c030001, 0x24637de0, 0x8c620000,
-0x2c424e21, 0x104000a3, 0x24020002, 0x3c020001,
-0x8c427e0c, 0x1040000e, 0x0, 0x3c020001,
-0x8c427ddc, 0x3c010001, 0xac207e0c, 0x30420080,
-0x1040002f, 0x2402000c, 0x8f820204, 0x30420080,
-0x1440000c, 0x24020003, 0x8005011, 0x2402000c,
-0x3c020001, 0x8c427ddc, 0x30420080, 0x14400005,
-0x24020003, 0x8f820204, 0x30420080, 0x1040001f,
-0x24020003, 0xac620000, 0x2402000a, 0x3c010001,
-0xac227dd0, 0x3c040001, 0x24847e18, 0x8c820000,
-0x3c030001, 0x8c637df0, 0x431025, 0xaf820204,
-0x8c830000, 0x3c040001, 0x8c847df0, 0x2402000b,
-0x3c010001, 0xac227dd0, 0x641825, 0x3c010001,
-0xac237e20, 0x3c050001, 0x24a57de0, 0x8ca20000,
-0x2c424e21, 0x1040006f, 0x24020002, 0x3c020001,
-0x8c427e10, 0x10400005, 0x0, 0x2402000c,
-0x3c010001, 0x8005083, 0xac227dd0, 0x3c020001,
-0x8c427e00, 0x1040006c, 0x0, 0x3c040001,
-0x8c847ddc, 0x1080005e, 0x30820008, 0x3c030001,
-0x8c637dec, 0x10620064, 0x24020003, 0x3c010001,
-0xac247e08, 0xaca20000, 0x24020006, 0x3c010001,
-0x8005083, 0xac227dd0, 0x8f820200, 0x34420002,
-0xaf820200, 0x8f830054, 0x2402000d, 0x3c010001,
-0xac227dd0, 0x3c010001, 0xac237df4, 0x8f830054,
-0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023,
-0x2c422710, 0x1440003a, 0x0, 0x3c020001,
-0x8c427e10, 0x10400029, 0x2402000e, 0x3c030001,
-0x8c637e24, 0x3c010001, 0x14600015, 0xac227dd0,
-0xc0043dd, 0x0, 0x3c050001, 0x8ca55cc8,
-0xc0052a2, 0x2021, 0x3c030001, 0x8c635cc8,
-0x24020004, 0x14620005, 0x2403fffb, 0x3c020001,
-0x8c425cc4, 0x8005052, 0x2403fff7, 0x3c020001,
-0x8c425cc4, 0x431024, 0x3c010001, 0xac225cc4,
-0x8ee20000, 0x3c030200, 0x431025, 0xaee20000,
-0x8f820224, 0x3c010001, 0xac227e2c, 0x8f820220,
-0x2403fffb, 0x431024, 0xaf820220, 0x8f820220,
-0x34420002, 0x8005083, 0xaf820220, 0x3c020001,
-0x8c427e00, 0x10400005, 0x0, 0x3c020001,
-0x8c427ddc, 0x1040000f, 0x24020002, 0x3c020001,
-0x8c427de0, 0x2c424e21, 0x1040000a, 0x24020002,
-0x3c020001, 0x8c427e00, 0x1040000f, 0x0,
-0x3c020001, 0x8c427ddc, 0x1440000b, 0x0,
-0x24020002, 0x3c010001, 0x8005083, 0xac227dd0,
-0x3c020001, 0x8c427e00, 0x10400003, 0x0,
-0xc00429b, 0x0, 0x8f820220, 0x3c03f700,
-0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x3c030001, 0x24637e28, 0x8c620000,
-0x10400005, 0x34422000, 0x3c010001, 0xac227e1c,
-0x8005095, 0xac600000, 0x3c010001, 0xac247e1c,
-0x3e00008, 0x0, 0x27bdffe0, 0x30820030,
-0xafbf0018, 0x3c010001, 0xac227e24, 0x14400067,
-0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061,
-0x24020030, 0x30822000, 0x1040005d, 0x30838000,
-0x31a02, 0x30820001, 0x21200, 0x3c040001,
-0x8c845d9c, 0x621825, 0x331c2, 0x3c030001,
-0x24635d78, 0x30828000, 0x21202, 0x30840001,
-0x42200, 0x441025, 0x239c2, 0x61080,
-0x431021, 0x471021, 0x90430000, 0x24020001,
-0x10620025, 0x0, 0x10600007, 0x24020002,
-0x10620013, 0x24020003, 0x1062002c, 0x3c05000f,
-0x80050f9, 0x0, 0x8f820200, 0x2403feff,
-0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe,
-0x3463ffff, 0x431024, 0xaf820220, 0x3c010001,
-0xac207e44, 0x3c010001, 0x8005104, 0xac207e4c,
-0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
-0x24020100, 0x3c010001, 0xac227e44, 0x3c010001,
-0x8005104, 0xac207e4c, 0x8f820200, 0x2403feff,
-0x431024, 0xaf820200, 0x8f820220, 0x3c030001,
-0x431025, 0xaf820220, 0x3c010001, 0xac207e44,
-0x3c010001, 0x8005104, 0xac237e4c, 0x8f820200,
-0x34420100, 0xaf820200, 0x8f820220, 0x3c030001,
-0x431025, 0xaf820220, 0x24020100, 0x3c010001,
-0xac227e44, 0x3c010001, 0x8005104, 0xac237e4c,
-0x34a5ffff, 0x3c040001, 0x24845bb8, 0xafa30010,
-0xc002403, 0xafa00014, 0x8005104, 0x0,
-0x24020030, 0x3c010001, 0xac227e28, 0x8fbf0018,
-0x3e00008, 0x27bd0020, 0x0, 0x27bdffc8,
-0xafb20028, 0x809021, 0xafb3002c, 0xa09821,
-0xafb00020, 0xc08021, 0x3c040001, 0x24845bd0,
-0x3c050009, 0x3c020001, 0x8c425cc8, 0x34a59001,
-0x2403021, 0x2603821, 0xafbf0030, 0xafb10024,
-0xa7a0001a, 0xafb00014, 0xc002403, 0xafa20010,
-0x24020002, 0x12620083, 0x2e620003, 0x10400005,
-0x24020001, 0x1262000a, 0x0, 0x800529b,
-0x0, 0x24020004, 0x126200fa, 0x24020008,
-0x126200f9, 0x3c02ffec, 0x800529b, 0x0,
-0x3c020001, 0x8c425cc4, 0x30420002, 0x14400004,
-0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024,
-0x3c010001, 0x310821, 0xac307e3c, 0x3c024000,
-0x2021024, 0x1040004e, 0x1023c2, 0x30840030,
-0x101382, 0x3042001c, 0x3c030001, 0x24635d08,
-0x431021, 0x823821, 0x3c020020, 0x2021024,
-0x10400006, 0x24020100, 0x3c010001, 0x310821,
-0xac227e40, 0x8005150, 0x3c020080, 0x3c010001,
-0x310821, 0xac207e40, 0x3c020080, 0x2021024,
-0x10400006, 0x121940, 0x3c020001, 0x3c010001,
-0x230821, 0x800515c, 0xac227e48, 0x121140,
-0x3c010001, 0x220821, 0xac207e48, 0x94e40000,
-0x3c030001, 0x8c635dbc, 0x24020005, 0x10620010,
-0xa7a40018, 0x32024000, 0x10400002, 0x34824000,
-0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
-0x24e60002, 0x34420001, 0xc00498e, 0xa4e20002,
-0x24040001, 0x2821, 0xc00498e, 0x27a60018,
-0x3c020001, 0x8c425cc8, 0x24110001, 0x3c010001,
-0xac315cd4, 0x14530004, 0x32028000, 0xc00429b,
-0x0, 0x32028000, 0x1040011f, 0x0,
-0xc00429b, 0x0, 0x3c030001, 0x8c635dbc,
-0x24020005, 0x10620118, 0x24020002, 0x3c010001,
-0xac315ccc, 0x3c010001, 0x800529b, 0xac225cc8,
-0x24040001, 0x24050004, 0x27b0001a, 0xc00498e,
-0x2003021, 0x24040001, 0x2821, 0xc00498e,
-0x2003021, 0x3c020001, 0x511021, 0x8c427e34,
-0x3c040001, 0x8c845cc8, 0x3c03bfff, 0x3463ffff,
-0x3c010001, 0xac335cd4, 0x431024, 0x3c010001,
-0x310821, 0x109300fa, 0xac227e34, 0x800529b,
-0x0, 0x3c022000, 0x2021024, 0x10400005,
-0x24020001, 0x3c010001, 0xac225d98, 0x80051ad,
-0x128940, 0x3c010001, 0xac205d98, 0x128940,
-0x3c010001, 0x310821, 0xac307e38, 0x3c024000,
-0x2021024, 0x14400016, 0x0, 0x3c020001,
-0x8c425d98, 0x10400008, 0x24040004, 0x24050001,
-0xc004d93, 0x24062000, 0x24020001, 0x3c010001,
-0x370821, 0xac2283ac, 0x3c020001, 0x511021,
-0x8c427e30, 0x3c03bfff, 0x3463ffff, 0x431024,
-0x3c010001, 0x310821, 0x8005299, 0xac227e30,
-0x3c020001, 0x8c425d98, 0x10400028, 0x3c0300a0,
-0x2031024, 0x5443000d, 0x3c020020, 0x3c020001,
-0x8c425d9c, 0x24030100, 0x3c010001, 0x310821,
-0xac237e44, 0x3c030001, 0x3c010001, 0x310821,
-0xac237e4c, 0x80051f0, 0x34420400, 0x2021024,
-0x10400008, 0x24030100, 0x3c020001, 0x8c425d9c,
-0x3c010001, 0x310821, 0xac237e44, 0x80051f0,
-0x34420800, 0x3c020080, 0x2021024, 0x1040002e,
-0x3c030001, 0x3c020001, 0x8c425d9c, 0x3c010001,
-0x310821, 0xac237e4c, 0x34420c00, 0x3c010001,
-0xac225d9c, 0x8005218, 0x24040001, 0x3c020020,
-0x2021024, 0x10400006, 0x24020100, 0x3c010001,
-0x310821, 0xac227e44, 0x8005201, 0x3c020080,
-0x3c010001, 0x310821, 0xac207e44, 0x3c020080,
-0x2021024, 0x10400007, 0x121940, 0x3c020001,
-0x3c010001, 0x230821, 0xac227e4c, 0x800520f,
-0x24040001, 0x121140, 0x3c010001, 0x220821,
-0xac207e4c, 0x24040001, 0x2821, 0x27b0001e,
-0xc00494c, 0x2003021, 0x24040001, 0x2821,
-0xc00494c, 0x2003021, 0x24040001, 0x24050001,
-0x27b0001c, 0xc00494c, 0x2003021, 0x24040001,
-0x24050001, 0xc00494c, 0x2003021, 0x8005299,
-0x0, 0x3c02ffec, 0x3442ffff, 0x2028024,
-0x3c020008, 0x2028025, 0x121140, 0x3c010001,
-0x220821, 0xac307e38, 0x3c022000, 0x2021024,
-0x10400009, 0x0, 0x3c020001, 0x8c425d74,
-0x14400005, 0x24020001, 0x3c010001, 0xac225d98,
-0x800523a, 0x3c024000, 0x3c010001, 0xac205d98,
-0x3c024000, 0x2021024, 0x1440001e, 0x0,
-0x3c020001, 0x8c425d98, 0x3c010001, 0xac205ce0,
-0x10400007, 0x24022020, 0x3c010001, 0xac225d9c,
-0x24020001, 0x3c010001, 0x370821, 0xac2283ac,
-0x3c04bfff, 0x121940, 0x3c020001, 0x431021,
-0x8c427e30, 0x3c050001, 0x8ca55cc8, 0x3484ffff,
-0x441024, 0x3c010001, 0x230821, 0xac227e30,
-0x24020001, 0x10a20044, 0x0, 0x8005299,
-0x0, 0x3c020001, 0x8c425d98, 0x1040001c,
-0x24022000, 0x3c010001, 0xac225d9c, 0x3c0300a0,
-0x2031024, 0x14430005, 0x121140, 0x3402a000,
-0x3c010001, 0x8005294, 0xac225d9c, 0x3c030001,
-0x621821, 0x8c637e38, 0x3c020020, 0x621024,
-0x10400004, 0x24022001, 0x3c010001, 0x8005294,
-0xac225d9c, 0x3c020080, 0x621024, 0x1040001f,
-0x3402a001, 0x3c010001, 0x8005294, 0xac225d9c,
-0x3c020020, 0x2021024, 0x10400007, 0x121940,
-0x24020100, 0x3c010001, 0x230821, 0xac227e44,
-0x8005288, 0x3c020080, 0x121140, 0x3c010001,
-0x220821, 0xac207e44, 0x3c020080, 0x2021024,
-0x10400006, 0x121940, 0x3c020001, 0x3c010001,
-0x230821, 0x8005294, 0xac227e4c, 0x121140,
-0x3c010001, 0x220821, 0xac207e4c, 0x3c030001,
-0x8c635cc8, 0x24020001, 0x10620003, 0x0,
-0xc00429b, 0x0, 0x8fbf0030, 0x8fb3002c,
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
-0x27bd0038, 0x27bdffd8, 0xafb20020, 0x809021,
-0xafb1001c, 0x8821, 0x24020002, 0xafbf0024,
-0xafb00018, 0xa7a00012, 0x10a200d3, 0xa7a00010,
-0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a,
-0x128140, 0x8005380, 0x2201021, 0x24020004,
-0x10a2007d, 0x24020008, 0x10a2007c, 0x122940,
-0x8005380, 0x2201021, 0x3c030001, 0x701821,
-0x8c637e3c, 0x3c024000, 0x621024, 0x14400009,
-0x24040001, 0x3c027fff, 0x3442ffff, 0x628824,
-0x3c010001, 0x300821, 0xac317e34, 0x8005380,
-0x2201021, 0x24050001, 0xc00494c, 0x27a60010,
-0x24040001, 0x24050001, 0xc00494c, 0x27a60010,
-0x97a20010, 0x30420004, 0x10400034, 0x3c114000,
-0x3c020001, 0x8c425dbc, 0x2443ffff, 0x2c620006,
-0x10400034, 0x31080, 0x3c010001, 0x220821,
-0x8c225be0, 0x400008, 0x0, 0x24040001,
-0x24050011, 0x27b00012, 0xc00494c, 0x2003021,
-0x24040001, 0x24050011, 0xc00494c, 0x2003021,
-0x97a50012, 0x30a24000, 0x10400002, 0x3c040010,
-0x3c040008, 0x3c030001, 0x8005301, 0x30a28000,
-0x24040001, 0x24050014, 0x27b00012, 0xc00494c,
-0x2003021, 0x24040001, 0x24050014, 0xc00494c,
-0x2003021, 0x97a50012, 0x30a21000, 0x10400002,
-0x3c040010, 0x3c040008, 0x3c030001, 0x30a20800,
-0x54400001, 0x3c030002, 0x3c028000, 0x2221025,
-0x641825, 0x800530e, 0x438825, 0x3c110001,
-0x2308821, 0x8e317e3c, 0x3c027fff, 0x3442ffff,
-0x2228824, 0x3c020001, 0x8c425cd8, 0x1040001d,
-0x121140, 0x3c020001, 0x8c425d98, 0x10400002,
-0x3c022000, 0x2228825, 0x121140, 0x3c010001,
-0x220821, 0x8c227e40, 0x10400003, 0x3c020020,
-0x8005322, 0x2228825, 0x3c02ffdf, 0x3442ffff,
-0x2228824, 0x121140, 0x3c010001, 0x220821,
-0x8c227e48, 0x10400003, 0x3c020080, 0x800532d,
-0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824,
-0x121140, 0x3c010001, 0x220821, 0xac317e34,
-0x8005380, 0x2201021, 0x122940, 0x3c030001,
-0x651821, 0x8c637e38, 0x3c024000, 0x621024,
-0x14400008, 0x3c027fff, 0x3442ffff, 0x628824,
-0x3c010001, 0x250821, 0xac317e30, 0x8005380,
-0x2201021, 0x3c020001, 0x8c425cd8, 0x10400033,
-0x3c11c00c, 0x3c020001, 0x8c425d74, 0x3c04c00c,
-0x34842000, 0x3c030001, 0x8c635d98, 0x2102b,
-0x21023, 0x441024, 0x10600003, 0x518825,
-0x3c022000, 0x2228825, 0x3c020001, 0x451021,
-0x8c427e44, 0x10400003, 0x3c020020, 0x800535d,
-0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x121140, 0x3c010001, 0x220821, 0x8c227e4c,
-0x10400003, 0x3c020080, 0x8005368, 0x2228825,
-0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c020001,
-0x8c425d60, 0x10400002, 0x3c020800, 0x2228825,
-0x3c020001, 0x8c425d64, 0x10400002, 0x3c020400,
-0x2228825, 0x3c020001, 0x8c425d68, 0x10400006,
-0x3c020100, 0x800537b, 0x2228825, 0x3c027fff,
-0x3442ffff, 0x628824, 0x121140, 0x3c010001,
-0x220821, 0xac317e30, 0x2201021, 0x8fbf0024,
-0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0028, 0x27bdffd8, 0xafb40020, 0x80a021,
-0xafbf0024, 0xafb3001c, 0xafb20018, 0xafb10014,
-0xafb00010, 0x8f900200, 0x3c030001, 0x8c635cc8,
-0x8f930220, 0x24020002, 0x10620063, 0x2c620003,
-0x10400005, 0x24020001, 0x1062000a, 0x141940,
-0x8005448, 0x0, 0x24020004, 0x1062005a,
-0x24020008, 0x10620059, 0x149140, 0x8005448,
-0x0, 0x3c040001, 0x832021, 0x8c847e3c,
-0x3c110001, 0x2238821, 0x8e317e34, 0x3c024000,
-0x821024, 0x1040003e, 0x3c020008, 0x2221024,
-0x10400020, 0x36100002, 0x3c020001, 0x431021,
-0x8c427e40, 0x10400005, 0x36100020, 0x36100100,
-0x3c020020, 0x80053bd, 0x2228825, 0x2402feff,
-0x2028024, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x141140, 0x3c010001, 0x220821, 0x8c227e48,
-0x10400005, 0x3c020001, 0x2629825, 0x3c020080,
-0x80053dc, 0x2228825, 0x3c02fffe, 0x3442ffff,
-0x2629824, 0x3c02ff7f, 0x3442ffff, 0x80053dc,
-0x2228824, 0x2402fedf, 0x2028024, 0x3c02fffe,
-0x3442ffff, 0x2629824, 0x3c02ff5f, 0x3442ffff,
-0x2228824, 0x3c010001, 0x230821, 0xac207e40,
-0x3c010001, 0x230821, 0xac207e48, 0xc00486a,
-0x0, 0xaf900200, 0xaf930220, 0x8f820220,
-0x2403fffb, 0x431024, 0xaf820220, 0x8f820220,
-0x34420002, 0xaf820220, 0x80053f3, 0x141140,
-0x8f820200, 0x2403fffd, 0x431024, 0xc00486a,
-0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b,
-0x2228824, 0x141140, 0x3c010001, 0x220821,
-0x8005448, 0xac317e34, 0x149140, 0x3c040001,
-0x922021, 0x8c847e38, 0x3c110001, 0x2328821,
-0x8e317e30, 0x3c024000, 0x821024, 0x14400011,
-0x0, 0x3c020001, 0x8c425d98, 0x14400006,
-0x3c02bfff, 0x8f820200, 0x34420002, 0xc00486a,
-0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b,
-0x2228824, 0x3c010001, 0x320821, 0x8005448,
-0xac317e30, 0x3c020001, 0x8c425d98, 0x10400005,
-0x3c020020, 0x3c020001, 0x8c425d74, 0x1040002b,
-0x3c020020, 0x821024, 0x10400007, 0x36100020,
-0x24020100, 0x3c010001, 0x320821, 0xac227e44,
-0x8005428, 0x36100100, 0x3c010001, 0x320821,
-0xac207e44, 0x2402feff, 0x2028024, 0x3c020080,
-0x821024, 0x10400007, 0x141940, 0x3c020001,
-0x3c010001, 0x230821, 0xac227e4c, 0x8005439,
-0x2629825, 0x141140, 0x3c010001, 0x220821,
-0xac207e4c, 0x3c02fffe, 0x3442ffff, 0x2629824,
-0xc00486a, 0x0, 0xaf900200, 0xaf930220,
-0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
-0x8f820220, 0x34420002, 0xaf820220, 0x141140,
-0x3c010001, 0x220821, 0xac317e30, 0x8fbf0024,
-0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 };
-static u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = {
-0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f66776d, 0x61696e2e, 0x632c7620, 0x312e312e,
-0x322e3131, 0x20313939, 0x382f3034, 0x2f323720,
-0x32323a31, 0x333a3432, 0x20736875, 0x616e6720,
-0x45787020, 0x24000000, 0x7468655f, 0x4441574e,
-0x0, 0x53544143, 0x4b5f3120, 0x0,
-0x42616453, 0x6e64526e, 0x67000000, 0x3f456e71,
-0x45767400, 0x3f6e6f51, 0x64457650, 0x0,
-0x6576526e, 0x6746756c, 0x6c000000, 0x496c6c43,
-0x6f6e6652, 0x78000000, 0x53656e64, 0x436b5375,
-0x6d000000, 0x52656376, 0x566c616e, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f74696d, 0x65722e63, 0x2c762031, 0x2e312e32,
-0x2e382031, 0x3939382f, 0x30372f33, 0x31203137,
-0x3a35383a, 0x34352073, 0x6875616e, 0x67204578,
-0x70202400, 0x542d446d, 0x61526431, 0x0,
-0x542d446d, 0x61424200, 0x542d446d, 0x61320000,
-0x3f6e6f51, 0x64547845, 0x0, 0x3f6e6f51,
-0x64527845, 0x0, 0x656e714d, 0x45765046,
-0x61696c00, 0x656e714d, 0x45764661, 0x696c0000,
-0x6661696c, 0x456e454d, 0x0, 0x3f456e71,
-0x45767400, 0x3f6e6f51, 0x64457650, 0x0,
-0x6576526e, 0x6746756c, 0x6c000000, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f636f6d, 0x6d616e64, 0x2e632c76, 0x20312e31,
-0x2e322e31, 0x30203139, 0x39382f31, 0x312f3138,
-0x2031373a, 0x31313a31, 0x38207368, 0x75616e67,
-0x20457870, 0x20240000, 0x3f4d626f, 0x78457674,
-0x0, 0x4e4f636f, 0x6d616e64, 0x0,
-0x68737465, 0x5f455252, 0x0, 0x412d4572,
-0x72427563, 0x0, 0x4552524f, 0x522d4164,
-0x64000000, 0x656e714d, 0x45765046, 0x61696c00,
-0x656e714d, 0x45764661, 0x696c0000, 0x6661696c,
-0x456e454d, 0x0, 0x442d4572, 0x724c6173,
-0x74000000, 0x442d4572, 0x72320000, 0x6d437374,
-0x4d644552, 0x52000000, 0x70726f6d, 0x4d644552,
-0x52000000, 0x46696c74, 0x4d644552, 0x52000000,
-0x636d645f, 0x45525200, 0x3f456e71, 0x45767400,
-0x3f6e6f51, 0x64457650, 0x0, 0x6576526e,
-0x6746756c, 0x6c000000, 0x0, 0x6ea0,
-0x7fbc, 0x6e38, 0x8734, 0x82b0,
-0x8780, 0x8780, 0x6f54, 0x7694,
-0x7f0c, 0x80a8, 0x8074, 0x8780,
-0x7e70, 0x80cc, 0x6e64, 0x81cc,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f646d61, 0x2e632c76, 0x20312e31, 0x2e322e33,
-0x20313939, 0x382f3034, 0x2f323720, 0x32323a31,
-0x333a3431, 0x20736875, 0x616e6720, 0x45787020,
-0x24000000, 0x646d6172, 0x6441544e, 0x0,
-0x646d6177, 0x7241544e, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f747261, 0x63652e63, 0x2c762031, 0x2e312e32,
-0x2e322031, 0x3939382f, 0x30342f32, 0x37203232,
-0x3a31333a, 0x35302073, 0x6875616e, 0x67204578,
-0x70202400, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f646174, 0x612e632c, 0x7620312e, 0x312e322e,
-0x32203139, 0x39382f30, 0x342f3237, 0x2032323a,
-0x31333a34, 0x30207368, 0x75616e67, 0x20457870,
-0x20240000, 0x46575f56, 0x45525349, 0x4f4e3a20,
-0x23312046, 0x72692041, 0x70722037, 0x2031373a,
-0x35353a34, 0x38205044, 0x54203230, 0x30300000,
-0x46575f43, 0x4f4d5049, 0x4c455f54, 0x494d453a,
-0x2031373a, 0x35353a34, 0x38000000, 0x46575f43,
-0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263,
-0x73000000, 0x46575f43, 0x4f4d5049, 0x4c455f48,
-0x4f53543a, 0x20636f6d, 0x70757465, 0x0,
-0x46575f43, 0x4f4d5049, 0x4c455f44, 0x4f4d4149,
-0x4e3a2065, 0x6e672e61, 0x6374656f, 0x6e2e636f,
-0x6d000000, 0x46575f43, 0x4f4d5049, 0x4c45523a,
-0x20676363, 0x20766572, 0x73696f6e, 0x20322e37,
-0x2e320000, 0x0, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f6d656d, 0x2e632c76, 0x20312e31, 0x2e322e32,
-0x20313939, 0x382f3034, 0x2f323720, 0x32323a31,
-0x333a3434, 0x20736875, 0x616e6720, 0x45787020,
-0x24000000, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f73656e, 0x642e632c, 0x7620312e, 0x312e322e,
-0x31312031, 0x3939382f, 0x31322f32, 0x32203137,
-0x3a31373a, 0x35352073, 0x6875616e, 0x67204578,
-0x70202400, 0x736e6464, 0x654e6f51, 0x20000000,
-0x6e6f454e, 0x515f5458, 0x0, 0x736e6464,
-0x744e6f51, 0x20000000, 0x3f6e6f51, 0x64547845,
-0x0, 0x756e6b72, 0x64747970, 0x65000000,
-0x0, 0xaccc, 0xaccc, 0xad9c,
-0xaab0, 0xaab0, 0xad9c, 0xad9c,
-0xad9c, 0xad9c, 0xad9c, 0xad9c,
-0xad9c, 0xad9c, 0xad9c, 0xad9c,
-0xad9c, 0xad9c, 0xad9c, 0xad7c,
-0x0, 0xbca8, 0xbca8, 0xbd70,
-0xae4c, 0xb058, 0xbd70, 0xbd70,
-0xbd70, 0xbd70, 0xbd70, 0xbd70,
-0xbd70, 0xbd70, 0xbd70, 0xbd70,
-0xbd70, 0xbd70, 0xbd70, 0xbd54,
-0xb040, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f726563, 0x762e632c, 0x7620312e, 0x312e322e,
-0x31392031, 0x3939382f, 0x30372f32, 0x34203231,
-0x3a33303a, 0x30352073, 0x6875616e, 0x67204578,
-0x70202400, 0x706b5278, 0x45525200, 0x66726d32,
-0x4c617267, 0x65000000, 0x72784e6f, 0x52784264,
-0x0, 0x72785144, 0x6d614446, 0x0,
-0x72785144, 0x6d614246, 0x0, 0x3f6e6f51,
-0x64527845, 0x0, 0x706b5278, 0x45525273,
-0x0, 0x66726d32, 0x4c726753, 0x0,
-0x72784e6f, 0x42645300, 0x3f724264, 0x446d6146,
-0x0, 0x3f724a42, 0x64446d46, 0x0,
-0x0, 0xf678, 0xf678, 0xf678,
-0xf678, 0xf678, 0xf678, 0xf678,
-0xf678, 0xf678, 0xf678, 0xf678,
-0xf678, 0xf678, 0xf678, 0xf678,
-0xf670, 0xf670, 0xf670, 0x572d444d,
-0x41456e46, 0x0, 0x0, 0xfdc0,
-0x1015c, 0xfddc, 0x1015c, 0x1015c,
-0x1015c, 0x1015c, 0x1015c, 0x1015c,
-0xf704, 0x1015c, 0x1015c, 0x1015c,
-0x1015c, 0x1015c, 0x10154, 0x10154,
-0x10154, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f6d6163, 0x2e632c76, 0x20312e31, 0x2e322e31,
-0x32203139, 0x39382f30, 0x342f3237, 0x2032323a,
-0x31333a34, 0x32207368, 0x75616e67, 0x20457870,
-0x20240000, 0x6d616374, 0x7841544e, 0x0,
-0x4e745379, 0x6e264c6b, 0x0, 0x72656d61,
-0x73737274, 0x0, 0x6c696e6b, 0x444f574e,
-0x0, 0x656e714d, 0x45765046, 0x61696c00,
-0x656e714d, 0x45764661, 0x696c0000, 0x6661696c,
-0x456e454d, 0x0, 0x6c696e6b, 0x55500000,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x772f636f, 0x6d6d6f6e,
-0x2f636b73, 0x756d2e63, 0x2c762031, 0x2e312e32,
-0x2e322031, 0x3939382f, 0x30342f32, 0x37203232,
-0x3a31333a, 0x33392073, 0x6875616e, 0x67204578,
-0x70202400, 0x50726f62, 0x65506879, 0x0,
-0x6c6e6b41, 0x53535254, 0x0, 0x11b2c,
-0x11bc4, 0x11bf8, 0x11c2c, 0x11c58,
-0x11c6c, 0x11ca8, 0x1207c, 0x11de4,
-0x11e24, 0x11e50, 0x11e90, 0x11ec0,
-0x11efc, 0x11f30, 0x1207c, 0x122c0,
-0x122d8, 0x12300, 0x12320, 0x12348,
-0x12478, 0x124a0, 0x124f4, 0x1251c,
-0x0, 0x1278c, 0x1285c, 0x12934,
-0x12a04, 0x12a60, 0x12b3c, 0x12b64,
-0x12c40, 0x12c68, 0x12e10, 0x12e38,
-0x12fe0, 0x131d8, 0x1346c, 0x13380,
-0x1346c, 0x13498, 0x13008, 0x131b0,
-0x0, 0x13b84, 0x13bc8, 0x13c60,
-0x13cac, 0x13d1c, 0x13db4, 0x13de8,
-0x13e70, 0x13f08, 0x13fd8, 0x14018,
-0x1409c, 0x140c0, 0x141f4, 0x646f4261,
-0x73655067, 0x0, 0x0, 0x0,
-0x0, 0x73746d61, 0x634c4e4b, 0x0,
-0x0, 0x14c38, 0x14c38, 0x14b80,
-0x14bc4, 0x14c38, 0x14c38, 0x0,
-0x0, 0x0 };
-static u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __devinitdata = {
-0x416c7465,
-0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465,
-0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242,
-0x0, 0x0, 0x0, 0x135418,
-0x13e7fc, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x60cf00,
-0x60, 0xcf000000, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3, 0x0,
-0x1, 0x0, 0x0, 0x0,
-0x1, 0x0, 0x1, 0x0,
-0x0, 0x0, 0x0, 0x1,
-0x1, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x1000000, 0x21000000,
-0x12000140, 0x0, 0x0, 0x20000000,
-0x120000a0, 0x0, 0x12000060, 0x12000180,
-0x120001e0, 0x0, 0x0, 0x0,
-0x1, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x2,
-0x0, 0x0, 0x30001, 0x1,
-0x30201, 0x0, 0x0, 0x0 };
-#endif
-/* Generated by genfw.c */
-#define tigon2FwReleaseMajor 0xc
-#define tigon2FwReleaseMinor 0x4
-#define tigon2FwReleaseFix 0xb
-#define tigon2FwStartAddr 0x00004000
-#define tigon2FwTextAddr 0x00004000
-#define tigon2FwTextLen 0x11bc0
-#define tigon2FwRodataAddr 0x00015bc0
-#define tigon2FwRodataLen 0x10d0
-#define tigon2FwDataAddr 0x00016cc0
-#define tigon2FwDataLen 0x1c0
-#define tigon2FwSbssAddr 0x00016e80
-#define tigon2FwSbssLen 0xcc
-#define tigon2FwBssAddr 0x00016f50
-#define tigon2FwBssLen 0x20c0
-static u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __devinitdata = {
-0x0,
-0x10000003, 0x0, 0xd, 0xd,
-0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000,
-0x26104000, 0xc0010c0, 0x0, 0xd,
-0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000,
-0x26104000, 0xc0017e0, 0x0, 0xd,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x2000008,
-0x0, 0x800172f, 0x3c0a0001, 0x800172f,
-0x3c0a0002, 0x800172f, 0x0, 0x8002cac,
-0x0, 0x8002c4f, 0x0, 0x800172f,
-0x3c0a0004, 0x800328a, 0x0, 0x8001a52,
-0x0, 0x800394d, 0x0, 0x80038f4,
-0x0, 0x800172f, 0x3c0a0006, 0x80039bb,
-0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f,
-0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6,
-0x0, 0x800172f, 0x3c0a000b, 0x800172f,
-0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb,
-0x0, 0x8002890, 0x0, 0x800172f,
-0x3c0a000e, 0x800208c, 0x0, 0x8001964,
-0x0, 0x8001a04, 0x0, 0x8003ca6,
-0x0, 0x8003c94, 0x0, 0x800172f,
-0x0, 0x800191a, 0x0, 0x800172f,
-0x0, 0x800172f, 0x3c0a0013, 0x800172f,
-0x3c0a0014, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x27bdffe0,
-0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140,
-0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20,
-0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc,
-0x401821, 0x3c020010, 0x3c010001, 0xac236e9c,
-0x10620011, 0x43102b, 0x14400002, 0x3c020020,
-0x3c020008, 0x1062000c, 0x24050100, 0x3c060001,
-0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020,
-0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001,
-0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4,
-0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe,
-0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002,
-0x24639010, 0x3c040001, 0x8c846cc4, 0x431023,
-0x14800002, 0x458021, 0x2610fa38, 0x2402f000,
-0x2028024, 0xc001785, 0x2002021, 0x2022823,
-0x3c040020, 0x821823, 0x651823, 0x247bb000,
-0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf,
-0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf,
-0x3463e000, 0x852023, 0x3c010001, 0xac246ea8,
-0x822023, 0x3c010001, 0xac256e90, 0x52842,
-0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001,
-0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823,
-0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac,
-0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011,
-0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
-0xc001749, 0x0, 0x3c020001, 0x8c426cd0,
-0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200,
-0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004,
-0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021,
-0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38,
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
-0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8,
-0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4,
-0x3c020001, 0x8c426cc8, 0x14400003, 0x0,
-0x3c010001, 0xac206cd0, 0xc001151, 0x0,
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
-0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8,
-0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060,
-0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c,
-0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014,
-0x8f860040, 0x3c040001, 0x24845c80, 0x24050200,
-0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821,
-0x8f830040, 0x3c02f000, 0x621824, 0x3c026000,
-0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001,
-0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014,
-0x8f860040, 0x24050300, 0xc002b3b, 0x2003821,
-0x8f820240, 0x3c030001, 0x431025, 0xaf820240,
-0xaf800048, 0x8f820048, 0x14400005, 0x0,
-0xaf800048, 0x8f820048, 0x10400004, 0x0,
-0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c,
-0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8,
-0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001,
-0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001,
-0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001,
-0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001,
-0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001,
-0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c,
-0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138,
-0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150,
-0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140,
-0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014,
-0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014,
-0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0,
-0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014,
-0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac,
-0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c,
-0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff,
-0x1061824, 0xe81024, 0x43102b, 0x10400006,
-0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010,
-0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010,
-0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004,
-0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000,
-0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c,
-0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010,
-0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c,
-0x8c020218, 0x30420002, 0x10400009, 0x0,
-0x8c020220, 0x3c030002, 0x34630004, 0x431025,
-0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004,
-0x8c020220, 0x3c030002, 0x34630006, 0x431025,
-0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014,
-0x8c020218, 0x30420010, 0x1040000a, 0x0,
-0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220,
-0x3c03000a, 0x34630004, 0x431025, 0x10000009,
-0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006,
-0x431025, 0xaf420008, 0x8c02021c, 0x34420006,
-0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0,
-0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0,
-0x10000002, 0x24630064, 0x8f820054, 0x621023,
-0x2c420065, 0x1440fffc, 0x0, 0x8c040208,
-0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490,
-0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008,
-0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
-0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c,
-0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004,
-0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00,
-0x431024, 0x10400021, 0x0, 0x8f8200b4,
-0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001,
-0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c,
-0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001,
-0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014,
-0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b,
-0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
-0x3c030001, 0x431025, 0xaf820140, 0x96e20472,
-0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482,
-0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b,
-0xafa20014, 0x96f00452, 0x32020001, 0x10400002,
-0xb021, 0x24160001, 0x32020002, 0x54400001,
-0x36d60002, 0x32020008, 0x54400001, 0x36d60004,
-0x32020010, 0x54400001, 0x36d60008, 0x32020020,
-0x54400001, 0x36d60010, 0x32020040, 0x54400001,
-0x36d60020, 0x32020080, 0x54400001, 0x36d60040,
-0x96e60482, 0x30c20200, 0x54400001, 0x36d64000,
-0x96e30472, 0x30620200, 0x10400003, 0x30620100,
-0x10000003, 0x36d62000, 0x54400001, 0x36d61000,
-0x96f00462, 0x32c24000, 0x14400004, 0x3207009b,
-0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000,
-0x1440000d, 0x32020001, 0x3062009b, 0x10e20009,
-0x240e0001, 0x3c040001, 0x24845d20, 0x24051300,
-0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b,
-0xafa00014, 0x32020001, 0x54400001, 0x36d60080,
-0x32020002, 0x54400001, 0x36d60100, 0x32020008,
-0x54400001, 0x36d60200, 0x32020010, 0x54400001,
-0x36d60400, 0x32020080, 0x54400001, 0x36d60800,
-0x8c020218, 0x30420200, 0x10400002, 0x3c020008,
-0x2c2b025, 0x8c020218, 0x30420800, 0x10400002,
-0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400,
-0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218,
-0x30420100, 0x10400002, 0x3c020200, 0x2c2b025,
-0x8c020218, 0x30420080, 0x10400002, 0x3c020400,
-0x2c2b025, 0x8c020218, 0x30422000, 0x10400002,
-0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000,
-0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218,
-0x30421000, 0x10400002, 0x3c020040, 0x2c2b025,
-0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164,
-0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c,
-0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174,
-0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c,
-0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184,
-0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c,
-0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194,
-0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c,
-0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4,
-0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8,
-0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c,
-0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
-0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a,
-0x3484ca00, 0x3821, 0x24020006, 0x24030002,
-0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200,
-0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290,
-0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8,
-0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f,
-0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001,
-0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c,
-0x24051400, 0x21702, 0x24420030, 0xa062022c,
-0x3471021, 0xa040022c, 0x8c070218, 0x2c03021,
-0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014,
-0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80,
-0x24060010, 0x27b10030, 0x2203821, 0x27b30034,
-0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8,
-0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00,
-0x8fa20034, 0x246400ff, 0x852024, 0x831823,
-0x431023, 0xafa20034, 0xafa40030, 0x3c040001,
-0x24845d44, 0x3c050000, 0x24a54100, 0x24060108,
-0x2203821, 0xc0017a3, 0xafb30010, 0x409021,
-0x32c20003, 0x3c010001, 0xac326e80, 0x10400045,
-0x2203821, 0x8f820050, 0x3c030010, 0x431024,
-0x10400016, 0x0, 0x8c020218, 0x30420040,
-0x1040000f, 0x24020001, 0x8f820050, 0x8c030218,
-0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f,
-0xafa20010, 0xafa30014, 0x8f870040, 0x24051500,
-0xc002b3b, 0x2c03021, 0x10000004, 0x0,
-0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
-0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001,
-0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030,
-0x2603821, 0x27b10034, 0x34420a00, 0xaf420010,
-0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70,
-0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90,
-0xc53023, 0x2603821, 0xaf420108, 0xc0017a3,
-0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001,
-0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023,
-0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3,
-0xafb10010, 0x3c040001, 0x24845da4, 0x10000024,
-0x24051600, 0x3c040001, 0x24845dac, 0x3c050001,
-0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc,
-0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c,
-0xc53023, 0x2203821, 0xaf420108, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001,
-0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023,
-0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845de4, 0x24051650,
-0x2c03021, 0x3821, 0x3c010001, 0xac226ef8,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020,
-0x10400021, 0x27a70030, 0x3c040001, 0x24845df0,
-0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8,
-0xc53023, 0x24022000, 0xaf42001c, 0x27a20034,
-0xc0017a3, 0xafa20010, 0x21900, 0x31982,
-0x3c040800, 0x641825, 0xae430028, 0x24030010,
-0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040,
-0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010,
-0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0,
-0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c,
-0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001,
-0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10,
-0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c,
-0x24051700, 0xc002b3b, 0x3821, 0x3c020000,
-0x24425cbc, 0x21100, 0x21182, 0x3c030800,
-0x431025, 0xae420028, 0x24020008, 0xaf42003c,
-0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001,
-0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c,
-0x24051800, 0x32c60020, 0xc002b3b, 0x0,
-0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff,
-0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800,
-0x651824, 0x31882, 0x641825, 0x451024,
-0x21082, 0x441025, 0xacc20080, 0x32c20180,
-0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080,
-0x431024, 0x1040000d, 0x0, 0x8f820050,
-0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001,
-0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040,
-0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050,
-0x3c030010, 0x431024, 0x10400016, 0x0,
-0x8c020218, 0x30420040, 0x1040000f, 0x24020001,
-0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001,
-0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014,
-0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021,
-0x10000004, 0x0, 0x3c010001, 0x370821,
-0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001,
-0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023,
-0x8f420008, 0x27b30030, 0x2603821, 0x27b10034,
-0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010,
-0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4,
-0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821,
-0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001,
-0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001,
-0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001,
-0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001,
-0x24845e7c, 0x10000027, 0x24052100, 0x3c040001,
-0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001,
-0x24c6a104, 0xc53023, 0x27b10030, 0x2203821,
-0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001,
-0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001,
-0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4,
-0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4,
-0xc53023, 0x2203821, 0x3c010001, 0xac226f04,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8,
-0x24052150, 0x2c03021, 0x3821, 0x3c010001,
-0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014,
-0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff,
-0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800,
-0x711824, 0x31882, 0x6e1825, 0x511024,
-0x21082, 0x4e1025, 0xae630038, 0xae620078,
-0x8c020218, 0x30420040, 0x14400004, 0x24020001,
-0x3c010001, 0x370821, 0xa02240f4, 0x3c040001,
-0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001,
-0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821,
-0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001,
-0xac226efc, 0x511024, 0x21082, 0x3c0e0800,
-0x4e1025, 0xae620050, 0x32c22000, 0x10400006,
-0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024,
-0x1000000f, 0x21082, 0x3c040001, 0x24845ed8,
-0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4,
-0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001,
-0xac226f14, 0x511024, 0x21082, 0x3c0e0800,
-0x4e1025, 0xae620048, 0x32c24000, 0x10400005,
-0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e,
-0x21100, 0x3c040001, 0x24845ef0, 0x3c050001,
-0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023,
-0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001,
-0xac226f08, 0x21100, 0x21182, 0x3c030800,
-0x431025, 0xae420060, 0x3c040001, 0x24845f08,
-0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650,
-0xc53023, 0x27b10030, 0x2203821, 0x27b30034,
-0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff,
-0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468,
-0x3c060000, 0x24c66588, 0xc53023, 0x2203821,
-0x240f021, 0x3c010001, 0xac226edc, 0x4e1024,
-0x21082, 0x3c150800, 0x551025, 0xafae0044,
-0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001,
-0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000,
-0x24c66808, 0x8fae0044, 0xc53023, 0x2203821,
-0x3c010001, 0xac226ed0, 0x4e1024, 0x21082,
-0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010,
-0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810,
-0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023,
-0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024,
-0x21082, 0x551025, 0xafc200c0, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001,
-0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044,
-0xc53023, 0x2203821, 0x3c010001, 0xac226ed4,
-0x4e1024, 0x21082, 0x551025, 0xafc200c8,
-0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c,
-0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20,
-0xc53023, 0x2203821, 0xaf420110, 0xc0017a3,
-0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001,
-0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023,
-0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010,
-0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80,
-0x3c060001, 0x24c65aac, 0xc53023, 0x2203821,
-0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010,
-0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298,
-0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821,
-0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044,
-0x3c010001, 0xac226f18, 0x4e1024, 0x21082,
-0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40,
-0x0, 0xc0027a8, 0x0, 0xac000228,
-0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038,
-0x96e20460, 0xaf420080, 0x32c24000, 0x14400003,
-0x0, 0x96e20480, 0xaf420084, 0x96e70490,
-0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088,
-0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000,
-0x10400003, 0x24020400, 0x10e2000b, 0x0,
-0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f,
-0x96e60490, 0x24052170, 0x2c03821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138,
-0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098,
-0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084,
-0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200,
-0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58,
-0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0,
-0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c,
-0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff,
-0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010,
-0x3c010001, 0xac226eb8, 0x21100, 0x21182,
-0x511025, 0xc0018fc, 0xae420000, 0x8f820240,
-0x3c030001, 0x431025, 0xaf820240, 0x3c020000,
-0x24424034, 0xaf820244, 0xaf800240, 0x8f820060,
-0x511024, 0x14400005, 0x3c030800, 0x8f820060,
-0x431024, 0x1040fffd, 0x0, 0xc003c4d,
-0x8821, 0x3c020100, 0xafa20020, 0x8f530018,
-0x240200ff, 0x56620001, 0x26710001, 0x8c020228,
-0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0xc01821, 0x8f440178, 0x8f45017c, 0x1021,
-0x24070004, 0xafa70010, 0xafb10014, 0x8f48000c,
-0x24c604c0, 0x2e63021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x1440000b, 0x24070008,
-0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020,
-0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164,
-0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010,
-0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x14400010, 0x0,
-0x8f420340, 0x24420001, 0xaf420340, 0x8f420340,
-0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020,
-0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4,
-0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f,
-0x10400069, 0x3c020700, 0x34423000, 0xafa20028,
-0x8f530018, 0x240200ff, 0x12620002, 0x8821,
-0x26710001, 0x8c020228, 0x1622000e, 0x1330c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f,
-0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c,
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
-0xafb10014, 0x8f48000c, 0x24c604c0, 0x2e63021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009,
-0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200,
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018,
-0x8f860120, 0x24020010, 0xafa20010, 0xafb10014,
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400010, 0x0, 0x8f420340, 0x24420001,
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009,
-0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b,
-0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0,
-0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010,
-0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b,
-0x3821, 0x10000004, 0x0, 0x8c020264,
-0x10400005, 0x0, 0x8f8200a0, 0x30420004,
-0x1440fffa, 0x0, 0x8f820044, 0x34420004,
-0xaf820044, 0x8f420308, 0x24420001, 0xaf420308,
-0x8f420308, 0x8f8200d8, 0x8f8300d4, 0x431023,
-0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81,
-0x10400006, 0x24020001, 0x8f420090, 0x8f430144,
-0x431021, 0xaf420090, 0x24020001, 0xaf42008c,
-0x32c20008, 0x10400006, 0x0, 0x8f820214,
-0x3c038100, 0x3042ffff, 0x431025, 0xaf820214,
-0x3c030001, 0x8c636d94, 0x30620002, 0x10400009,
-0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000,
-0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012,
-0xc53023, 0x10400009, 0x0, 0x3c040001,
-0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000,
-0x24c67678, 0x10000008, 0xc53023, 0x3c040001,
-0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000,
-0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034,
-0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc,
-0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100,
-0x21182, 0x431025, 0xae420040, 0x8f8200a0,
-0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c,
-0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001,
-0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001,
-0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001,
-0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b,
-0x24052400, 0x8f820200, 0xafa20010, 0x8f820220,
-0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001,
-0x24846008, 0xc002b3b, 0x24052500, 0x8f830060,
-0x74100b, 0x242000a, 0x200f821, 0x0,
-0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058,
-0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048,
-0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001,
-0x24846014, 0x24052600, 0x3021, 0x3821,
-0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
-0x0, 0x3e00008, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x3e00008, 0x0, 0x3e00008, 0x0,
-0x27bdfde0, 0x27a50018, 0x3c04dead, 0x3484beef,
-0xafbf0218, 0x8f820150, 0x3c03001f, 0x3463ffff,
-0xafa40018, 0xa22823, 0xa32824, 0x8ca20000,
-0x1044000a, 0x0, 0xafa50010, 0x8ca20000,
-0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001,
-0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218,
-0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba,
-0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f,
-0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000,
-0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000,
-0xaca30000, 0x10460005, 0xae040000, 0xa08021,
-0xf0102b, 0x1040fff5, 0x102840, 0x3c040001,
-0x24846028, 0x24052800, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021,
-0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020,
-0x8c020224, 0x3047003f, 0x10e00010, 0x803021,
-0x2821, 0x24030020, 0xe31024, 0x10400002,
-0x63042, 0xa62821, 0x31842, 0x1460fffb,
-0xe31024, 0x2402f000, 0xa22824, 0x3402ffff,
-0x45102b, 0x14400003, 0x3c020001, 0x10000008,
-0x3c020001, 0x3442ffff, 0x851823, 0x43102b,
-0x14400003, 0xa01021, 0x3c02fffe, 0x821021,
-0x3e00008, 0x0, 0x27bdffd0, 0xafb50028,
-0x8fb50040, 0xafb20020, 0xa09021, 0xafb1001c,
-0x24c60003, 0xafbf002c, 0xafb30024, 0xafb00018,
-0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b,
-0x1440001b, 0xe08821, 0x8e330000, 0xafb00010,
-0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000,
-0xc002b3b, 0x2403021, 0x8e230000, 0x702021,
-0x64102b, 0x10400007, 0x2402821, 0x8ca20000,
-0xac620000, 0x24630004, 0x64102b, 0x1440fffb,
-0x24a50004, 0x8ea20000, 0x501023, 0xaea20000,
-0x8e220000, 0x501021, 0x1000000b, 0xae220000,
-0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000,
-0x2409821, 0xafa20014, 0x8e270000, 0x24053100,
-0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c,
-0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8,
-0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84,
-0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc,
-0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001,
-0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0,
-0xac201ffc, 0x431023, 0x441023, 0x245bb000,
-0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021,
-0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0,
-0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0,
-0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001,
-0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d,
-0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200,
-0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4,
-0x3021, 0x3603821, 0xafbf0030, 0xafb3002c,
-0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c,
-0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014,
-0xc001916, 0x0, 0x8f820240, 0x34420004,
-0xaf820240, 0x24020001, 0xaf420000, 0x3c020001,
-0x571021, 0x904240f4, 0x10400092, 0x2403fffc,
-0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c,
-0x2121023, 0x438024, 0x8fa3001c, 0x3c040001,
-0x24846040, 0x70102b, 0x1440001a, 0x27b30018,
-0x8fb10018, 0x24053000, 0x2403021, 0xafb00010,
-0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018,
-0x702021, 0x64102b, 0x10400007, 0x2403021,
-0x8cc20000, 0xac620000, 0x24630004, 0x64102b,
-0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023,
-0xafa2001c, 0x8e620000, 0x501021, 0x1000000a,
-0xae620000, 0x2408821, 0x24053100, 0xafb00010,
-0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d,
-0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c,
-0x3c040001, 0x2484605c, 0x24120020, 0x3c010001,
-0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018,
-0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50,
-0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
-0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020,
-0x65102b, 0x10400007, 0x0, 0x8c820000,
-0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
-0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
-0x8e220000, 0x521021, 0x1000000b, 0xae220000,
-0x3c100001, 0x26106f50, 0x24053100, 0xafa70010,
-0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
-0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001,
-0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001,
-0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018,
-0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70,
-0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821,
-0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020,
-0x65102b, 0x10400007, 0x0, 0x8c820000,
-0xac620000, 0x24630004, 0x65102b, 0x1440fffb,
-0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c,
-0x8e220000, 0x521021, 0x1000000b, 0xae220000,
-0x3c100001, 0x26106f70, 0x24053100, 0xafa70010,
-0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d,
-0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031,
-0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001,
-0x2652809c, 0x2121023, 0x438024, 0x8fa3001c,
-0x3c040001, 0x24846084, 0x70102b, 0x1440001a,
-0x27b30018, 0x8fb10018, 0x24053000, 0x2403021,
-0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821,
-0x8fa30018, 0x702021, 0x64102b, 0x10400007,
-0x2403021, 0x8cc20000, 0xac620000, 0x24630004,
-0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c,
-0x501023, 0xafa2001c, 0x8e620000, 0x501021,
-0x1000000a, 0xae620000, 0x2408821, 0x24053100,
-0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021,
-0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001,
-0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400,
-0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c,
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
-0x27bd0038, 0x0, 0x0, 0x8f820040,
-0x3c03f000, 0x431024, 0x3c036000, 0x14430006,
-0x0, 0x8f820050, 0x2403ff80, 0x431024,
-0x34420055, 0xaf820050, 0x8f820054, 0x244203e8,
-0xaf820058, 0x240201f4, 0xaf4200e0, 0x24020004,
-0xaf4200e8, 0x24020002, 0xaf4001b0, 0xaf4000e4,
-0xaf4200dc, 0xaf4000d8, 0xaf4000d4, 0x3e00008,
-0xaf4000d0, 0x8f820054, 0x24420005, 0x3e00008,
-0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054,
-0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024,
-0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024,
-0x36940040, 0x3c020001, 0x8c426da8, 0x10400017,
-0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016,
-0x282a025, 0x3c020001, 0x8c426e44, 0x14400012,
-0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003,
-0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002,
-0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf,
-0x0, 0x10000004, 0x3c020200, 0xc004196,
-0x0, 0x3c020200, 0x2c21024, 0x10400003,
-0x0, 0xc001f4b, 0x0, 0x8f4200d8,
-0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b,
-0x14400003, 0x0, 0xaf4000d8, 0x36940080,
-0x8c030238, 0x1060000c, 0x0, 0x8f4201b0,
-0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006,
-0x0, 0x934205c5, 0x14400003, 0x0,
-0xc001da0, 0x0, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8,
-0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059,
-0x0, 0x3c020001, 0x571021, 0x904240f0,
-0x10400026, 0x24070008, 0x8f440170, 0x8f450174,
-0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010,
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f0, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x24846128, 0xafa20014,
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
-0x34a50900, 0x1000005c, 0x0, 0x8f420300,
-0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c,
-0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170,
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
-0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
-0x24020001, 0x3c010001, 0x370821, 0xa02240f1,
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
-0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120,
-0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036,
-0x0, 0x8f420300, 0x8f43002c, 0x24420001,
-0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
-0xaf430038, 0x3c010001, 0x370821, 0xa02040f1,
-0x3c010001, 0x370821, 0xa02040f0, 0x10000026,
-0xaf400034, 0x934205c1, 0x1040001d, 0x0,
-0xa34005c1, 0x8f820040, 0x30420001, 0x14400008,
-0x2021, 0x8c030104, 0x24020001, 0x50620005,
-0x24040001, 0x8c020264, 0x10400003, 0x801021,
-0x24040001, 0x801021, 0x10400006, 0x0,
-0x8f42030c, 0x24420001, 0xaf42030c, 0x10000008,
-0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
-0x8f420308, 0x24420001, 0xaf420308, 0x8f420308,
-0x3c010001, 0x370821, 0xa02040f0, 0x3c010001,
-0x370821, 0xa02040f1, 0x8f420000, 0x10400007,
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
-0x0, 0x10000005, 0x0, 0xaf800048,
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
-0x3c03ff7f, 0x3463ffff, 0x431024, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000002,
-0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008,
-0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8,
-0xafbf0020, 0x8f430044, 0x8f42007c, 0x10620029,
-0x24070008, 0x8f440168, 0x8f45016c, 0x8f48000c,
-0x8f860120, 0x24020040, 0xafa20010, 0xafa30014,
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044,
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300,
-0x1000000f, 0x0, 0x8f420304, 0x24420001,
-0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c,
-0x3c010001, 0x370821, 0xa02040f2, 0x10000004,
-0xaf400078, 0x3c010001, 0x370821, 0xa02040f2,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x3c03feff, 0x3463ffff,
-0x431024, 0xaf820060, 0x8f420000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048,
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
-0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8,
-0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044,
-0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5,
-0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b,
-0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002,
-0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001,
-0x8c636d98, 0x34420002, 0xaf420004, 0x24020001,
-0x14620003, 0x3c020600, 0x10000002, 0x34423000,
-0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034,
-0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff,
-0x11420002, 0x1821, 0x25430001, 0x8c020228,
-0x609821, 0x1662000e, 0x3c050009, 0x8f42033c,
-0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
-0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014,
-0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500,
-0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020,
-0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054,
-0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
-0x1040001b, 0xa821, 0xe09021, 0x265e04c0,
-0x8f440178, 0x8f45017c, 0x2401821, 0x240a0004,
-0xafaa0010, 0xafb30014, 0x8f48000c, 0x1021,
-0x2fe3021, 0xafa80018, 0x8f48010c, 0x24070008,
-0xa32821, 0xa3482b, 0x822021, 0x100f809,
-0x892021, 0x54400006, 0x24150001, 0x8f820054,
-0x2221023, 0x2c4203e9, 0x1440ffe9, 0x0,
-0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846118, 0xafa20014, 0x8d460000,
-0x3c050009, 0x10000035, 0x34a50600, 0x8f420308,
-0x24150001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054,
-0x247103e8, 0x2221023, 0x2c4203e9, 0x10400016,
-0xa821, 0x3c1e0020, 0x24120010, 0x8f42000c,
-0x8f440160, 0x8f450164, 0x8f860120, 0xafb20010,
-0xafb30014, 0x5e1025, 0xafa20018, 0x8f42010c,
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
-0x0, 0x8f820054, 0x2221023, 0x2c4203e9,
-0x1440ffee, 0x0, 0x32a200ff, 0x14400011,
-0x3c050009, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
-0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec,
-0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029,
-0x36100040, 0x3c020400, 0x2c21024, 0x10400013,
-0x2404ffdf, 0x8f420250, 0x8f430254, 0x8f4401b4,
-0x14640006, 0x36100040, 0x8f420270, 0x8f430274,
-0x8f4401b8, 0x10640007, 0x2402ffdf, 0x8f420250,
-0x8f430254, 0x8f440270, 0x8f450274, 0x10000012,
-0x3a100020, 0x1000002b, 0x2028024, 0x8f420250,
-0x8f430254, 0x8f4501b4, 0x14650006, 0x2048024,
-0x8f420270, 0x8f430274, 0x8f4401b8, 0x50640021,
-0x36100040, 0x8f420250, 0x8f430254, 0x8f440270,
-0x8f450274, 0x3a100040, 0xaf4301b4, 0x10000019,
-0xaf4501b8, 0x8f4200d4, 0x24430001, 0x10000011,
-0x28420033, 0x8f420004, 0x30420001, 0x10400009,
-0x3c020400, 0x2c21024, 0x10400004, 0x2402ffdf,
-0x2028024, 0x1000000b, 0x36100040, 0x10000009,
-0x36100060, 0x8f4200d4, 0x36100040, 0x24430001,
-0x284201f5, 0x14400003, 0xaf4300d4, 0xaf4000d4,
-0x3a100020, 0xaf900044, 0x2402ff7f, 0x282a024,
-0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
-0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008,
-0x27bd0058, 0x3e00008, 0x0, 0x3c020001,
-0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
-0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001,
-0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004,
-0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004,
-0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004,
-0x24020001, 0x14620003, 0x3c020600, 0x10000002,
-0x34423000, 0x34421000, 0xafa20020, 0x1821,
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
-0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
-0x8d460000, 0x10000035, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400016,
-0x9821, 0x3c150020, 0x24110010, 0x8f42000c,
-0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010,
-0xafb20014, 0x551025, 0xafa20018, 0x8f42010c,
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe3,
-0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
-0x1440ffee, 0x0, 0x326200ff, 0x14400011,
-0x0, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846120, 0x3c050009,
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
-0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec,
-0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018,
-0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4,
-0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270,
-0x8f430274, 0x8f4401b8, 0x10640021, 0x0,
-0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0,
-0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4,
-0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0,
-0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001,
-0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001,
-0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001,
-0x8f420004, 0x30420001, 0x10400008, 0x0,
-0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1,
-0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4,
-0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5,
-0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1,
-0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1,
-0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c,
-0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001,
-0x5462001f, 0x2021, 0x3c020001, 0x90426cf0,
-0x1443001b, 0x24040005, 0x10000019, 0x24040006,
-0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b,
-0x24020001, 0x3c030001, 0x90636cf1, 0x54620010,
-0x2021, 0x3c020001, 0x90426cf0, 0x1443000c,
-0x24040003, 0x1000000a, 0x24040004, 0x3c030001,
-0x90636cf1, 0x14620006, 0x2021, 0x3c020001,
-0x90426cf0, 0x24040001, 0x50440001, 0x24040002,
-0xc00565a, 0x0, 0x2402ff7f, 0x282a024,
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
-0x27bd0050, 0x3e00008, 0x0, 0x3c020001,
-0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
-0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001,
-0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8,
-0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002,
-0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002,
-0xaf420004, 0x24020001, 0x14820003, 0x3c020600,
-0x10000002, 0x34423000, 0x34421000, 0xafa20020,
-0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff,
-0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228,
-0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c,
-0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228,
-0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014,
-0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500,
-0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0,
-0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8,
-0x2021023, 0x2c4203e9, 0x1040001b, 0x9821,
-0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c,
-0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014,
-0x8f48000c, 0x1021, 0x2f53021, 0xafa80018,
-0x8f48010c, 0x24070008, 0xa32821, 0xa3482b,
-0x822021, 0x100f809, 0x892021, 0x54400006,
-0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9,
-0x1440ffe9, 0x0, 0x326200ff, 0x54400017,
-0xaf520018, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846118, 0x3c050009,
-0xafa20014, 0x8d460000, 0x10000035, 0x34a50600,
-0x8f420308, 0x24130001, 0x24420001, 0xaf420308,
-0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054,
-0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9,
-0x10400016, 0x9821, 0x3c150020, 0x24110010,
-0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
-0xafb10010, 0xafb20014, 0x551025, 0xafa20018,
-0x8f42010c, 0x24070008, 0x40f809, 0x24c6001c,
-0x1440ffe3, 0x0, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff,
-0x14400011, 0x0, 0x8f420378, 0x24420001,
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846120,
-0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700,
-0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001,
-0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001,
-0x10400033, 0x3c020400, 0x2c21024, 0x10400017,
-0x0, 0x934205c0, 0x8f440250, 0x8f450254,
-0x8f4301b4, 0x34420020, 0x14a30006, 0xa34205c0,
-0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640008,
-0x0, 0x8f420250, 0x8f430254, 0x934405c0,
-0x8f460270, 0x8f470274, 0x10000016, 0x38840040,
-0x934205c0, 0x10000048, 0x304200bf, 0x934205c0,
-0x8f440250, 0x8f450254, 0x8f4301b4, 0x304200bf,
-0x14a30006, 0xa34205c0, 0x8f420270, 0x8f430274,
-0x8f4401b8, 0x1064000b, 0x0, 0x8f420250,
-0x8f430254, 0x934405c0, 0x8f460270, 0x8f470274,
-0x38840020, 0xaf4301b4, 0xaf4701b8, 0x10000033,
-0xa34405c0, 0x934205c0, 0x1000002f, 0x34420020,
-0x934205c0, 0x8f4300d4, 0x34420020, 0xa34205c0,
-0x24620001, 0x10000023, 0x28630033, 0x8f4200e4,
-0x8f4300e0, 0x24420001, 0xaf4200e4, 0x43102a,
-0x14400006, 0x24030001, 0x8f4200e8, 0x14430002,
-0xaf4000e4, 0x24030004, 0xaf4300e8, 0x8f420004,
-0x30420001, 0x1040000d, 0x3c020400, 0x2c21024,
-0x10400007, 0x0, 0x934205c0, 0x34420040,
-0xa34205c0, 0x934205c0, 0x1000000f, 0x304200df,
-0x934205c0, 0x1000000c, 0x34420060, 0x934205c0,
-0x8f4300d4, 0x34420020, 0xa34205c0, 0x24620001,
-0x286300fb, 0x14600005, 0xaf4200d4, 0x934205c0,
-0xaf4000d4, 0x38420040, 0xa34205c0, 0x934205c0,
-0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001,
-0x14620005, 0x0, 0x934405c0, 0x42102,
-0x10000003, 0x348400f0, 0x934405c0, 0x3484000f,
-0xc005640, 0x0, 0x2402ff7f, 0x282a024,
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
-0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0,
-0x274401c0, 0x26e30028, 0x24650400, 0x65102b,
-0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c,
-0xafb20038, 0xafb10034, 0x10400007, 0xafb00030,
-0x8c820000, 0xac620000, 0x24630004, 0x65102b,
-0x1440fffb, 0x24840004, 0x8c020080, 0xaee20044,
-0x8c0200c0, 0xaee20040, 0x8c020084, 0xaee20030,
-0x8c020084, 0xaee2023c, 0x8c020088, 0xaee20240,
-0x8c02008c, 0xaee20244, 0x8c020090, 0xaee20248,
-0x8c020094, 0xaee2024c, 0x8c020098, 0xaee20250,
-0x8c02009c, 0xaee20254, 0x8c0200a0, 0xaee20258,
-0x8c0200a4, 0xaee2025c, 0x8c0200a8, 0xaee20260,
-0x8c0200ac, 0xaee20264, 0x8c0200b0, 0xaee20268,
-0x8c0200b4, 0xaee2026c, 0x8c0200b8, 0xaee20270,
-0x8c0200bc, 0x24040001, 0xaee20274, 0xaee00034,
-0x41080, 0x571021, 0x8ee30034, 0x8c42023c,
-0x24840001, 0x621821, 0x2c82000f, 0xaee30034,
-0x1440fff8, 0x41080, 0x8c0200cc, 0xaee20048,
-0x8c0200d0, 0xaee2004c, 0x8c0200e0, 0xaee201f8,
-0x8c0200e4, 0xaee201fc, 0x8c0200e8, 0xaee20200,
-0x8c0200ec, 0xaee20204, 0x8c0200f0, 0xaee20208,
-0x8ee400c0, 0x8ee500c4, 0x8c0200fc, 0x45102b,
-0x1040000b, 0x0, 0x8ee200c0, 0x8ee300c4,
-0x24040001, 0x24050000, 0x651821, 0x65302b,
-0x441021, 0x461021, 0xaee200c0, 0xaee300c4,
-0x8c0200fc, 0x8ee400c0, 0x8ee500c4, 0x2408ffff,
-0x24090000, 0x401821, 0x1021, 0x882024,
-0xa92824, 0x822025, 0xa32825, 0xaee400c0,
-0xaee500c4, 0x8ee400d0, 0x8ee500d4, 0x8c0200f4,
-0x45102b, 0x1040000b, 0x0, 0x8ee200d0,
-0x8ee300d4, 0x24040001, 0x24050000, 0x651821,
-0x65302b, 0x441021, 0x461021, 0xaee200d0,
-0xaee300d4, 0x8c0200f4, 0x8ee400d0, 0x8ee500d4,
-0x401821, 0x1021, 0x882024, 0xa92824,
-0x822025, 0xa32825, 0xaee400d0, 0xaee500d4,
-0x8ee400c8, 0x8ee500cc, 0x8c0200f8, 0x45102b,
-0x1040000b, 0x0, 0x8ee200c8, 0x8ee300cc,
-0x24040001, 0x24050000, 0x651821, 0x65302b,
-0x441021, 0x461021, 0xaee200c8, 0xaee300cc,
-0x8c0200f8, 0x8ee400c8, 0x8ee500cc, 0x401821,
-0x1021, 0x882024, 0xa92824, 0x822025,
-0xa32825, 0x24020008, 0xaee400c8, 0xaee500cc,
-0xafa20010, 0xafa00014, 0x8f42000c, 0x8c040208,
-0x8c05020c, 0xafa20018, 0x8f42010c, 0x26e60028,
-0x40f809, 0x24070400, 0x104000f0, 0x3c020400,
-0xafa20020, 0x934205c6, 0x10400089, 0x1821,
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
-0xafaa002c, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846118, 0x3c050009, 0xafa20014,
-0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
-0x326200ff, 0x54400012, 0x24020001, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24846120, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x1021,
-0x1440005b, 0x24020001, 0x10000065, 0x0,
-0x8f510018, 0x240200ff, 0x12220002, 0x8021,
-0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
-0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
-0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
-0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x54400011, 0x24020001, 0x8f420340, 0x24420001,
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846104, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
-0x2203821, 0x1021, 0x1040000d, 0x24020001,
-0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001,
-0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001,
-0xaee20150, 0x10000003, 0x8ee20150, 0x24020001,
-0xa34205c6, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-0x3e00008, 0x27bd0050, 0x27bdffd8, 0xafbf0020,
-0x8f8200b0, 0x30420004, 0x10400068, 0x0,
-0x8f430128, 0x8f820104, 0x14620005, 0x0,
-0x8f430130, 0x8f8200b4, 0x10620006, 0x0,
-0x8f820104, 0xaf420128, 0x8f8200b4, 0x1000005b,
-0xaf420130, 0x8f8200b0, 0x3c030080, 0x431024,
-0x1040000d, 0x0, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024,
-0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024,
-0x1000004a, 0xaf82011c, 0x8f430128, 0x8f820104,
-0x14620005, 0x0, 0x8f430130, 0x8f8200b4,
-0x10620010, 0x0, 0x8f820104, 0xaf420128,
-0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010,
-0x8f420130, 0x3c040001, 0x24846144, 0xafa20014,
-0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031,
-0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130,
-0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c,
-0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000,
-0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104,
-0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008,
-0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c,
-0x8c040208, 0x8c05020c, 0xafa20018, 0x8f42010c,
-0x26e60028, 0x40f809, 0x24070400, 0x8f82011c,
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
-0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128,
-0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c,
-0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005,
-0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0,
-0x30420004, 0x10400069, 0x0, 0x8f43012c,
-0x8f820124, 0x14620005, 0x0, 0x8f430134,
-0x8f8200a4, 0x10620006, 0x0, 0x8f820124,
-0xaf42012c, 0x8f8200a4, 0x1000005c, 0xaf420134,
-0x8f8200a0, 0x3c030080, 0x431024, 0x1040000d,
-0x0, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f8200a0, 0x2403fffb, 0x431024, 0xaf8200a0,
-0x8f82011c, 0x2403fffd, 0x431024, 0x1000004b,
-0xaf82011c, 0x8f43012c, 0x8f820124, 0x14620005,
-0x0, 0x8f430134, 0x8f8200a4, 0x10620010,
-0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4,
-0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134,
-0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c,
-0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200,
-0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001,
-0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0,
-0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c,
-0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0,
-0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124,
-0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208,
-0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001,
-0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c,
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc,
-0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c,
-0xafa20010, 0x8f420134, 0x3c040001, 0x24846180,
-0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005,
-0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020,
-0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001,
-0x3c060080, 0x3c050100, 0x8f820070, 0x481024,
-0x1040fffd, 0x0, 0x8f820054, 0x24420005,
-0xaf820078, 0x8c040234, 0x10800016, 0x1821,
-0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
-0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
-0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
-0x0, 0x3c030080, 0x3c010001, 0x370821,
-0xac2040e8, 0x3c010001, 0x370821, 0x1000000b,
-0xa02740f0, 0x3c020001, 0x571021, 0x904240f0,
-0x54400006, 0x661825, 0x3c020001, 0x571021,
-0x904240f1, 0x54400001, 0x661825, 0x8c040230,
-0x10800013, 0x0, 0x3c020001, 0x571021,
-0x8c4240ec, 0x24420005, 0x3c010001, 0x370821,
-0xac2240ec, 0x3c020001, 0x571021, 0x8c4240ec,
-0x44102b, 0x14400006, 0x0, 0x3c010001,
-0x370821, 0xac2040ec, 0x10000006, 0x651825,
-0x3c020001, 0x571021, 0x904240f2, 0x54400001,
-0x651825, 0x1060ffbc, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x431025, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x1000ffa7, 0xaf80004c,
-0x1000ffa5, 0xaf800048, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x27bdffe0,
-0xafbf0018, 0x8f860064, 0x30c20004, 0x10400025,
-0x24040004, 0x8c020114, 0xaf420020, 0xaf840064,
-0x8f4202fc, 0x24420001, 0xaf4202fc, 0x8f4202fc,
-0x8f820064, 0x30420004, 0x14400005, 0x0,
-0x8c030114, 0x8f420020, 0x1462fff2, 0x0,
-0x8f420000, 0x10400007, 0x8f43003c, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x431025, 0xaf820060,
-0x8f420000, 0x10400073, 0x0, 0x1000006f,
-0x0, 0x30c20008, 0x10400020, 0x24040008,
-0x8c02011c, 0xaf420048, 0xaf840064, 0x8f4202a8,
-0x24420001, 0xaf4202a8, 0x8f4202a8, 0x8f820064,
-0x30420008, 0x14400005, 0x0, 0x8c03011c,
-0x8f420048, 0x1462fff2, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x1000ffd9, 0x34420200, 0x30c20020,
-0x10400023, 0x24040020, 0x8c02012c, 0xaf420068,
-0xaf840064, 0x8f4202d8, 0x24420001, 0xaf4202d8,
-0x8f4202d8, 0x8f820064, 0x30420020, 0x14400005,
-0x32c24000, 0x8c03012c, 0x8f420068, 0x1462fff2,
-0x32c24000, 0x14400002, 0x3c020001, 0x2c2b025,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x1000ffb4, 0x34420800,
-0x30c20010, 0x10400029, 0x24040010, 0x8c020124,
-0xaf420058, 0xaf840064, 0x8f4202d4, 0x24420001,
-0xaf4202d4, 0x8f4202d4, 0x8f820064, 0x30420010,
-0x14400005, 0x32c22000, 0x8c030124, 0x8f420058,
-0x1462fff2, 0x32c22000, 0x50400001, 0x36d68000,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x34420100, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x1000006c,
-0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001,
-0x10400004, 0x24020001, 0xaf820064, 0x10000064,
-0x0, 0x30c20002, 0x1440000b, 0x3c050003,
-0x3c040001, 0x24846244, 0x34a50500, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0,
-0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c,
-0x10a20048, 0x51080, 0x8c460300, 0x24a20001,
-0x3045003f, 0x24020003, 0xac05022c, 0x61e02,
-0x10620005, 0x24020010, 0x1062001d, 0x30c20fff,
-0x10000039, 0x0, 0x8f4302a8, 0x8f440000,
-0x30c20fff, 0xaf420048, 0x24630001, 0xaf4302a8,
-0x10800007, 0x8f4202a8, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x34420200, 0xaf820060, 0x8f420000,
-0x1040001f, 0x0, 0x1000001b, 0x0,
-0xaf420058, 0x32c22000, 0x50400001, 0x36d68000,
-0x8f4202d4, 0x8f430000, 0x24420001, 0xaf4202d4,
-0x10600007, 0x8f4202d4, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x34420100, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x10000006, 0xaf80004c,
-0x10000004, 0xaf800048, 0xc002196, 0xc02021,
-0x402821, 0x8c02010c, 0x14a20002, 0x24020002,
-0xaf820064, 0x8f820064, 0x30420002, 0x14400004,
-0x0, 0x8c02010c, 0x14a2ffac, 0x0,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008,
-0x0, 0x27bdffa0, 0xafb00040, 0x808021,
-0x101602, 0x2442ffff, 0x304300ff, 0x2c620013,
-0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c,
-0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034,
-0x31080, 0x3c010001, 0x220821, 0x8c226288,
-0x400008, 0x0, 0x101302, 0x30440fff,
-0x24020001, 0x10820005, 0x24020002, 0x1082000c,
-0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004,
-0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204,
-0x3c040001, 0x8c846e80, 0x10000009, 0x34630001,
-0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001,
-0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28,
-0x21100, 0x21182, 0xaf430004, 0x3c030800,
-0x431025, 0xac820038, 0x8f840054, 0x41442,
-0x41c82, 0x431021, 0x41cc2, 0x431023,
-0x41d02, 0x431021, 0x41d42, 0x431023,
-0x10000009, 0xaf420208, 0x3c040001, 0x24846250,
-0x34a51000, 0x2003021, 0x3821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001,
-0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028,
-0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
-0xc002518, 0x2002021, 0x10000216, 0x0,
-0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
-0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
-0x21080, 0x8c430300, 0x25420001, 0x3042003f,
-0xafa20034, 0xac02022c, 0xafa50028, 0xc002518,
-0xafa3002c, 0x10000203, 0x0, 0x27b00028,
-0x2002021, 0x24050210, 0xc002bbf, 0x24060008,
-0xc002657, 0x2002021, 0x100001fa, 0x0,
-0x8faa0034, 0x27a40028, 0xa1880, 0x25420001,
-0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034,
-0x21080, 0x8c430300, 0x25420001, 0x3042003f,
-0xafa20034, 0xac02022c, 0xafa50028, 0xc002657,
-0xafa3002c, 0x100001e7, 0x0, 0x101302,
-0x30430fff, 0x24020001, 0x10620005, 0x24020002,
-0x1062001e, 0x3c020002, 0x10000033, 0x3c050003,
-0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025,
-0x8f820228, 0x3c010001, 0x370821, 0xac2238d8,
-0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc,
-0x8f820230, 0x3c010001, 0x370821, 0xac2238e0,
-0x8f820234, 0x3c010001, 0x370821, 0xac2238e4,
-0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230,
-0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024,
-0x10400012, 0x3c02fffd, 0x3c020001, 0x571021,
-0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021,
-0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021,
-0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021,
-0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff,
-0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c,
-0x34a51100, 0x2003021, 0x3821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001,
-0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302,
-0x30450fff, 0x24020001, 0x10a20005, 0x24020002,
-0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003,
-0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004,
-0x2c4b025, 0x621824, 0x34630008, 0xaf830220,
-0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb,
-0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024,
-0xaf820220, 0x10000009, 0xaf450298, 0x3c040001,
-0x24846268, 0x34a51200, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc,
-0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc,
-0x27840208, 0x24050200, 0xc002bbf, 0x24060008,
-0x27440224, 0x24050200, 0xc002bbf, 0x24060008,
-0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169,
-0x8f4202c4, 0x101302, 0x30430fff, 0x24020001,
-0x10620011, 0x28620002, 0x50400005, 0x24020002,
-0x10600007, 0x0, 0x10000017, 0x0,
-0x1062000f, 0x0, 0x10000013, 0x0,
-0x8c060248, 0x2021, 0xc005104, 0x24050004,
-0x10000007, 0x0, 0x8c060248, 0x2021,
-0xc005104, 0x24050004, 0x10000010, 0x0,
-0x8c06024c, 0x2021, 0xc005104, 0x24050001,
-0x1000000a, 0x0, 0x3c040001, 0x24846274,
-0x3c050003, 0x34a51300, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0,
-0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0,
-0xc002426, 0x0, 0x10000136, 0x0,
-0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8,
-0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014,
-0xafa20018, 0x8f420108, 0x26e60028, 0x40f809,
-0x24070400, 0x1040fff5, 0x0, 0x10000125,
-0x0, 0x3c03ffff, 0x34637fff, 0x8f420368,
-0x8f440360, 0x2c3b024, 0x1821, 0xaf400058,
-0xaf40005c, 0xaf400060, 0xaf400064, 0x441023,
-0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020,
-0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002,
-0xafaa003c, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846218, 0x3c050009, 0xafa20014,
-0x8d460000, 0x10000033, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24846220, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0,
-0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8,
-0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8,
-0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260,
-0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8,
-0x8f820220, 0x30420008, 0x14400002, 0x24020001,
-0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001,
-0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff,
-0x3442ffff, 0x2021824, 0x32c20180, 0x14400006,
-0x3402fffb, 0x43102b, 0x14400003, 0x0,
-0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280,
-0x3c050003, 0x34a51500, 0x2003021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700,
-0x34421000, 0x101e02, 0x621825, 0xafa30020,
-0x8f510018, 0x240200ff, 0x12220002, 0x8021,
-0x26300001, 0x8c020228, 0x1602000e, 0x1130c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f,
-0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178,
-0x8f45017c, 0x1021, 0x24070004, 0xafa70010,
-0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x24070008, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200,
-0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018,
-0x8f860120, 0x24020010, 0xafa20010, 0xafb00014,
-0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400010, 0x0, 0x8f420340, 0x24420001,
-0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846204, 0x3c050009,
-0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b,
-0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0,
-0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0,
-0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054,
-0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044,
-0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8,
-0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8,
-0x354a8320, 0x90870000, 0x24840001, 0x3021,
-0x1071026, 0x30420001, 0x10400002, 0x81842,
-0x6a1826, 0x604021, 0x24c60001, 0x2cc20008,
-0x1440fff7, 0x73842, 0x25290001, 0x125102b,
-0x1440fff0, 0x0, 0x1001021, 0x3e00008,
-0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044,
-0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034,
-0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200,
-0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420004, 0xaf820220, 0x8f820200,
-0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004,
-0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360,
-0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c,
-0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0,
-0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8,
-0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360,
-0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368,
-0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c,
-0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200,
-0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf,
-0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc,
-0x240203e8, 0x24040002, 0x24030001, 0xaf420294,
-0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008,
-0x10400004, 0x0, 0xaf430298, 0x10000003,
-0x3021, 0xaf440298, 0x3021, 0x3c030001,
-0x661821, 0x90636d00, 0x3461021, 0x24c60001,
-0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821,
-0x24c60001, 0x8f820040, 0x24040080, 0x24050080,
-0x21702, 0x24420030, 0xa062022c, 0x3461021,
-0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004,
-0x14400006, 0x0, 0x8f820220, 0x3c0308ff,
-0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c,
-0x30e20004, 0x14400006, 0x0, 0x8f820200,
-0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200,
-0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c,
-0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008,
-0x27bd0050, 0x0, 0x0, 0xaf400104,
-0x24040001, 0x410c0, 0x2e21821, 0x24820001,
-0x3c010001, 0x230821, 0xa42234d0, 0x402021,
-0x2c820080, 0x1440fff8, 0x410c0, 0x24020001,
-0x3c010001, 0x370821, 0xa42038d0, 0xaf420100,
-0xaf800228, 0xaf80022c, 0xaf800230, 0xaf800234,
-0x3e00008, 0x0, 0x27bdffe8, 0xafbf0014,
-0xafb00010, 0x8f420104, 0x28420005, 0x10400026,
-0x808021, 0x3c020001, 0x8f430104, 0x344230d0,
-0x2e22021, 0x318c0, 0x621821, 0x2e31821,
-0x83102b, 0x10400015, 0x1021, 0x96070000,
-0x24840006, 0x24660006, 0x9482fffc, 0x14470009,
-0x2821, 0x9483fffe, 0x96020002, 0x14620006,
-0xa01021, 0x94820000, 0x96030004, 0x431026,
-0x2c450001, 0xa01021, 0x14400009, 0x24840008,
-0x86102b, 0x1440fff0, 0x1021, 0x304200ff,
-0x14400030, 0x24020001, 0x1000002e, 0x1021,
-0x1000fffa, 0x24020001, 0x2002021, 0xc00240c,
-0x24050006, 0x3042007f, 0x218c0, 0x2e31021,
-0x3c010001, 0x220821, 0x942230d0, 0x1040fff2,
-0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0,
-0x10c0ffed, 0x3c080001, 0x350834d2, 0x96070000,
-0x610c0, 0x572021, 0x882021, 0x94820000,
-0x14470009, 0x2821, 0x94830002, 0x96020002,
-0x14620006, 0xa01021, 0x94820004, 0x96030004,
-0x431026, 0x2c450001, 0xa01021, 0x14400007,
-0x610c0, 0x2e21021, 0x3c060001, 0xc23021,
-0x94c634d0, 0x14c0ffeb, 0x610c0, 0x10c0ffd2,
-0x24020001, 0x8fbf0014, 0x8fb00010, 0x3e00008,
-0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0,
-0x801021, 0xafb00030, 0x24500002, 0x2002021,
-0x24050006, 0xafb10034, 0x408821, 0xafbf0048,
-0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c,
-0xafb20038, 0x3047007f, 0x710c0, 0x2e21021,
-0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c,
-0xa03021, 0x3c090001, 0x352934d2, 0x96280002,
-0x510c0, 0x572021, 0x892021, 0x94820000,
-0x14480009, 0x3021, 0x94830002, 0x96020002,
-0x14620006, 0xc01021, 0x94820004, 0x96030004,
-0x431026, 0x2c460001, 0xc01021, 0x14400007,
-0x510c0, 0x2e21021, 0x3c050001, 0xa22821,
-0x94a534d0, 0x14a0ffeb, 0x510c0, 0xa03021,
-0x10c00014, 0x610c0, 0x571821, 0x3c010001,
-0x230821, 0x8c2334d0, 0x571021, 0xafa30010,
-0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001,
-0x24846394, 0xafa20014, 0x8e260000, 0x8e270004,
-0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063,
-0x3c020800, 0x8f450100, 0x10a00006, 0x510c0,
-0x2e21021, 0x3c010001, 0x220821, 0x942234d0,
-0xaf420100, 0xa03021, 0x14c00011, 0x628c0,
-0x710c0, 0x2e21021, 0xafa70010, 0x3c010001,
-0x220821, 0x942230d0, 0x3c040001, 0x248463a0,
-0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004,
-0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800,
-0xb71821, 0x3c020001, 0x96040000, 0x344234d2,
-0x621821, 0xa4640000, 0x8e020002, 0x720c0,
-0xac620002, 0x2e41021, 0x3c030001, 0x621821,
-0x946330d0, 0x2e51021, 0x3c010001, 0x220821,
-0xa42334d0, 0x2e41021, 0x3c010001, 0x220821,
-0xa42630d0, 0x8f420104, 0x24420001, 0x28420080,
-0x1040000f, 0x3c020002, 0x8f420104, 0x3c040001,
-0x348430d2, 0x96030000, 0x210c0, 0x571021,
-0x441021, 0xa4430000, 0x8e030002, 0xac430002,
-0x8f420104, 0x24420001, 0xaf420104, 0x3c020002,
-0x2c21024, 0x10400011, 0x72142, 0x3c030001,
-0x346338d8, 0x24020003, 0x441023, 0x21080,
-0x572021, 0x832021, 0x571021, 0x431021,
-0x30e5001f, 0x8c430000, 0x24020001, 0xa21004,
-0x621825, 0x1000000c, 0xac830000, 0x24020003,
-0x441023, 0x21080, 0x5c2821, 0x5c1021,
-0x30e4001f, 0x8c430228, 0x24020001, 0x821004,
-0x621825, 0xaca30228, 0x3c020800, 0x34421000,
-0x1821, 0xafa20020, 0x8f5e0018, 0x27aa0020,
-0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001,
-0x8c020228, 0x609021, 0x1642000e, 0x1e38c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b,
-0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
-0x9821, 0xe08821, 0x263504c0, 0x8f440178,
-0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
-0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x54400006, 0x24130001, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
-0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x24846368,
-0x3c050009, 0xafa20014, 0x8d460000, 0x10000033,
-0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
-0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x10400014, 0x9821, 0x24110010,
-0x8f42000c, 0x8f440160, 0x8f450164, 0x8f860120,
-0xafb10010, 0xafb20014, 0xafa20018, 0x8f42010c,
-0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe5,
-0x0, 0x8f820054, 0x2021023, 0x2c4203e9,
-0x1440ffef, 0x0, 0x326200ff, 0x14400011,
-0x0, 0x8f420378, 0x24420001, 0xaf420378,
-0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010,
-0x8f820124, 0x3c040001, 0x24846370, 0x3c050009,
-0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b,
-0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4,
-0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4,
-0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021,
-0xafb00040, 0x24500002, 0x2002021, 0x24050006,
-0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054,
-0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048,
-0x3048007f, 0x810c0, 0x2e21021, 0x3c060001,
-0xc23021, 0x94c630d0, 0x10c0001c, 0x3821,
-0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0,
-0x572021, 0x8a2021, 0x94820000, 0x14490009,
-0x2821, 0x94830002, 0x96020002, 0x14620006,
-0xa01021, 0x94820004, 0x96030004, 0x431026,
-0x2c450001, 0xa01021, 0x14400008, 0x610c0,
-0xc03821, 0x2e21021, 0x3c060001, 0xc23021,
-0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011,
-0xafa70028, 0x810c0, 0x2e21021, 0xafa80010,
-0x3c010001, 0x220821, 0x942230d0, 0x3c040001,
-0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004,
-0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075,
-0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021,
-0x3c030001, 0x621821, 0x946334d0, 0x710c0,
-0x2e21021, 0x3c010001, 0x220821, 0xa42334d0,
-0x1000000b, 0x3c040001, 0x2e21021, 0x3c030001,
-0x621821, 0x946334d0, 0x810c0, 0x2e21021,
-0x3c010001, 0x220821, 0xa42330d0, 0x3c040001,
-0x348430d0, 0x8f430100, 0x610c0, 0x2e21021,
-0x3c010001, 0x220821, 0xa42334d0, 0x8f420104,
-0x2e43821, 0x2821, 0x18400029, 0xaf460100,
-0x24e60006, 0x94c3fffc, 0x96020000, 0x14620009,
-0x2021, 0x94c3fffe, 0x96020002, 0x14620006,
-0x801021, 0x94c20000, 0x96030004, 0x431026,
-0x2c440001, 0x801021, 0x50400014, 0x24a50001,
-0x8f420104, 0x2442ffff, 0xa2102a, 0x1040000b,
-0x24e40004, 0x94820006, 0x8c830008, 0xa482fffe,
-0xac830000, 0x8f420104, 0x24a50001, 0x2442ffff,
-0xa2102a, 0x1440fff7, 0x24840008, 0x8f420104,
-0x2442ffff, 0x10000006, 0xaf420104, 0x8f420104,
-0x24c60008, 0xa2102a, 0x1440ffda, 0x24e70008,
-0x810c0, 0x2e21021, 0x3c010001, 0x220821,
-0x942230d0, 0x14400023, 0x3c020800, 0x3c020002,
-0x2c21024, 0x10400012, 0x82142, 0x3c030001,
-0x346338d8, 0x24020003, 0x441023, 0x21080,
-0x572021, 0x832021, 0x571021, 0x431021,
-0x3105001f, 0x24030001, 0x8c420000, 0xa31804,
-0x31827, 0x431024, 0x1000000d, 0xac820000,
-0x24020003, 0x441023, 0x21080, 0x5c2821,
-0x5c1021, 0x3104001f, 0x24030001, 0x8c420228,
-0x831804, 0x31827, 0x431024, 0xaca20228,
-0x3c020800, 0x34422000, 0x1821, 0xafa20020,
-0x8f5e0018, 0x27ab0020, 0x240200ff, 0x13c20002,
-0xafab0034, 0x27c30001, 0x8c020228, 0x609021,
-0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001,
-0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001,
-0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010,
-0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021,
-0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x1040001b, 0x9821, 0xe08821,
-0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821,
-0x240b0004, 0xafab0010, 0xafb20014, 0x8f48000c,
-0x1021, 0x2f53021, 0xafa80018, 0x8f48010c,
-0x24070008, 0xa32821, 0xa3482b, 0x822021,
-0x100f809, 0x892021, 0x54400006, 0x24130001,
-0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9,
-0x0, 0x326200ff, 0x54400017, 0xaf520018,
-0x8f420378, 0x24420001, 0xaf420378, 0x8f420378,
-0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124,
-0x3c040001, 0x24846368, 0x3c050009, 0xafa20014,
-0x8d660000, 0x10000033, 0x34a50600, 0x8f420308,
-0x24130001, 0x24420001, 0xaf420308, 0x8f420308,
-0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014,
-0x9821, 0x24110010, 0x8f42000c, 0x8f440160,
-0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffef, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001,
-0x24846370, 0x3c050009, 0xafa20014, 0x8d660000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8,
-0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4,
-0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058,
-0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048,
-0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060,
-0x0, 0x0, 0x0, 0x27bdffe0,
-0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000,
-0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8,
-0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100,
-0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114,
-0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128,
-0xaf800130, 0xaf800134, 0xaf800138, 0xaf4200ec,
-0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4,
-0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021,
-0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c,
-0x3c040001, 0x24846470, 0x3c050001, 0x34420001,
-0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
-0x34a50100, 0xc002b3b, 0x3821, 0x8c020218,
-0x30420040, 0x10400014, 0x0, 0x8f82011c,
-0x3c040001, 0x2484647c, 0x3c050001, 0x34420004,
-0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c,
-0x10000007, 0x34a50200, 0x3c040001, 0x24846484,
-0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300,
-0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014,
-0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002,
-0x24680020, 0x27684800, 0x8f820128, 0x11020004,
-0x0, 0x8f820124, 0x15020007, 0x0,
-0x8f430334, 0x1021, 0x24630001, 0xaf430334,
-0x10000039, 0x8f430334, 0xac640000, 0xac650004,
-0xac660008, 0xa467000e, 0xac690018, 0xac6a001c,
-0xac6b0010, 0xac620014, 0xaf880120, 0x8f4200fc,
-0x8f4400f4, 0x2442ffff, 0xaf4200fc, 0x8c820000,
-0x10490005, 0x3042ff8f, 0x10400019, 0x3122ff8f,
-0x10400018, 0x3c020001, 0x8c830004, 0x2c620010,
-0x10400013, 0x3c020001, 0x24630001, 0xac830004,
-0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
-0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
-0x14440015, 0x24020001, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x1000000f, 0x24020001,
-0x3c020001, 0x344230c8, 0x2e21021, 0x54820004,
-0x24820008, 0x3c020001, 0x34422ec8, 0x2e21021,
-0x402021, 0x24020001, 0xaf4400f4, 0xac890000,
-0xac820004, 0x24020001, 0x3e00008, 0x0,
-0x3e00008, 0x0, 0x8fa90010, 0x8f83010c,
-0x8faa0014, 0x8fab0018, 0x1060000a, 0x276247e0,
-0x14620002, 0x24680020, 0x27684000, 0x8f820108,
-0x11020004, 0x0, 0x8f820104, 0x15020007,
-0x0, 0x8f430338, 0x1021, 0x24630001,
-0xaf430338, 0x10000035, 0x8f430338, 0xac640000,
-0xac650004, 0xac660008, 0xa467000e, 0xac690018,
-0xac6a001c, 0xac6b0010, 0xac620014, 0xaf880100,
-0x8f4400ec, 0x8c820000, 0x30420006, 0x10400019,
-0x31220006, 0x10400018, 0x3c020001, 0x8c830004,
-0x2c620010, 0x10400013, 0x3c020001, 0x24630001,
-0xac830004, 0x8f4300f0, 0x34422ec0, 0x2e21021,
-0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
-0x2e21021, 0x14440015, 0x24020001, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x1000000f,
-0x24020001, 0x3c020001, 0x34422ec0, 0x2e21021,
-0x54820004, 0x24820008, 0x3c020001, 0x34422cc0,
-0x2e21021, 0x402021, 0x24020001, 0xaf4400ec,
-0xac890000, 0xac820004, 0x24020001, 0x3e00008,
-0x0, 0x3e00008, 0x0, 0x27bdffd8,
-0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024,
-0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104,
-0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100,
-0x2403021, 0x2203821, 0xafa20010, 0xc002b3b,
-0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c,
-0x3c040001, 0x24846498, 0xafa20014, 0x8e060000,
-0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510,
-0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001,
-0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014,
-0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00,
-0x2221024, 0x3c030800, 0x54430016, 0x3c030200,
-0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200,
-0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030,
-0x3021, 0x3821, 0x36420002, 0xaf82011c,
-0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024,
-0x0, 0x2c31024, 0x1040000d, 0x2231024,
-0x1040000b, 0x36420002, 0xaf82011c, 0x36220001,
-0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330,
-0x24420001, 0xaf420330, 0x10000015, 0x8f420330,
-0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010,
-0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0,
-0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220,
-0x8f820140, 0x3c030001, 0x431025, 0xaf820140,
-0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001,
-0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020,
-0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0,
-0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021,
-0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014,
-0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001,
-0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004,
-0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018,
-0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500,
-0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001,
-0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024,
-0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac,
-0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001,
-0x2484650c, 0x3c050001, 0x34a5f030, 0x3021,
-0x3821, 0x36420002, 0xaf82011c, 0x36220001,
-0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x10000024, 0x0,
-0x2c31024, 0x1040000d, 0x2231024, 0x1040000b,
-0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0,
-0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001,
-0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001,
-0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014,
-0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b,
-0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f820220, 0x34420004, 0xaf820220, 0x8f820140,
-0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024,
-0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0028, 0x6021, 0x5021, 0x3021,
-0x2821, 0x6821, 0x4821, 0x7821,
-0x7021, 0x8f880124, 0x8f870104, 0x1580002e,
-0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120,
-0x10460029, 0x0, 0x3c040001, 0x8c846ee4,
-0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004,
-0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e,
-0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014,
-0x10000012, 0x24c60020, 0x10400017, 0x0,
-0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004,
-0xac820000, 0xac830004, 0x8d020008, 0xac820008,
-0x9502000e, 0xa482000e, 0x8d020010, 0x25060020,
-0xac820010, 0x8d020014, 0x240c0001, 0xc01821,
-0xac820014, 0x27624fe0, 0x43102b, 0x54400001,
-0x27634800, 0x603021, 0x1540002f, 0x31620100,
-0x11200014, 0x31628000, 0x8f820100, 0x1045002a,
-0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000,
-0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008,
-0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010,
-0x240a0001, 0xac820010, 0x8ca20014, 0x10000012,
-0x24a50020, 0x10400018, 0x31620100, 0x3c040001,
-0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000,
-0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e,
-0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010,
-0x8ce20014, 0x240a0001, 0xa01821, 0xac820014,
-0x276247e0, 0x43102b, 0x54400001, 0x27634000,
-0x602821, 0x31620100, 0x5440001d, 0x31621000,
-0x11a00009, 0x31a20800, 0x10400004, 0x25020020,
-0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124,
-0x8f880124, 0x6821, 0x11800011, 0x31621000,
-0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004,
-0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4,
-0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021,
-0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000,
-0x1440ff82, 0x0, 0x1120000f, 0x31220800,
-0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000,
-0x3c020002, 0x1221024, 0x10400004, 0x24e20020,
-0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104,
-0x8f870104, 0x4821, 0x1140ff70, 0x0,
-0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004,
-0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4,
-0x9482000e, 0xaf82009c, 0x8c820010, 0x5021,
-0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014,
-0x3e00008, 0x0, 0x6021, 0x5821,
-0x3021, 0x2821, 0x6821, 0x5021,
-0x7821, 0x7021, 0x8f880124, 0x8f870104,
-0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014,
-0x31220800, 0x8f820120, 0x10460029, 0x0,
-0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004,
-0xac820000, 0xac830004, 0x8cc20008, 0xac820008,
-0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001,
-0xac820010, 0x8cc20014, 0x10000012, 0x24c60020,
-0x10400017, 0x0, 0x3c040001, 0x8c846ee4,
-0x8d020000, 0x8d030004, 0xac820000, 0xac830004,
-0x8d020008, 0xac820008, 0x9502000e, 0xa482000e,
-0x8d020010, 0x25060020, 0xac820010, 0x8d020014,
-0x240c0001, 0xc01821, 0xac820014, 0x27624fe0,
-0x43102b, 0x54400001, 0x27634800, 0x603021,
-0x1560002f, 0x31220100, 0x11400014, 0x31228000,
-0x8f820100, 0x1045002a, 0x31220100, 0x3c040001,
-0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000,
-0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e,
-0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010,
-0x8ca20014, 0x10000012, 0x24a50020, 0x10400018,
-0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000,
-0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008,
-0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010,
-0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001,
-0xa01821, 0xac820014, 0x276247e0, 0x43102b,
-0x54400001, 0x27634000, 0x602821, 0x31220100,
-0x5440001d, 0x31221000, 0x11a00009, 0x31a20800,
-0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000,
-0x25020020, 0xaf820124, 0x8f880124, 0x6821,
-0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4,
-0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084,
-0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac,
-0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010,
-0x8c8f0014, 0x31221000, 0x14400022, 0x0,
-0x1140000f, 0x31420800, 0x10400004, 0x3c020002,
-0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024,
-0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4,
-0x24e20020, 0xaf820104, 0x8f870104, 0x5021,
-0x11600010, 0x0, 0x3c040001, 0x8c846ee0,
-0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
-0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c,
-0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010,
-0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024,
-0x1040ff5c, 0x0, 0x8f820054, 0x24420005,
-0xaf820078, 0x8c040234, 0x10800016, 0x1821,
-0x3c020001, 0x571021, 0x8c4240e8, 0x24420005,
-0x3c010001, 0x370821, 0xac2240e8, 0x3c020001,
-0x571021, 0x8c4240e8, 0x44102b, 0x14400009,
-0x24020001, 0x3c030080, 0x3c010001, 0x370821,
-0xac2040e8, 0x3c010001, 0x370821, 0x1000000c,
-0xa02240f0, 0x3c020001, 0x571021, 0x904240f0,
-0x14400006, 0x3c020080, 0x3c020001, 0x571021,
-0x904240f1, 0x10400002, 0x3c020080, 0x621825,
-0x8c040230, 0x10800013, 0x0, 0x3c020001,
-0x571021, 0x8c4240ec, 0x24420005, 0x3c010001,
-0x370821, 0xac2240ec, 0x3c020001, 0x571021,
-0x8c4240ec, 0x44102b, 0x14400006, 0x0,
-0x3c010001, 0x370821, 0xac2040ec, 0x10000006,
-0x781825, 0x3c020001, 0x571021, 0x904240f2,
-0x54400001, 0x781825, 0x1060ff1a, 0x0,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x431025, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x1000ff05,
-0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008,
-0x0, 0x0, 0x0, 0x3c020001,
-0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012,
-0xafb00010, 0x3c100001, 0x26106f90, 0x2002021,
-0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001,
-0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250,
-0x24022000, 0xac100254, 0xac020258, 0x24020001,
-0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010,
-0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec,
-0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000,
-0x8c820004, 0xad250008, 0xad220004, 0x8f820054,
-0xad260010, 0xad270014, 0xad230018, 0xad28001c,
-0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90,
-0x122102b, 0x10400003, 0x0, 0x3c090001,
-0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000,
-0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec,
-0xad220004, 0xac090250, 0x3e00008, 0x0,
-0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec,
-0x3c020001, 0x8c426d10, 0xafb10014, 0x808821,
-0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018,
-0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c,
-0xae020000, 0x3c020001, 0x8c426d10, 0xc09821,
-0xe0a821, 0x10800006, 0xae020004, 0x26050008,
-0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0,
-0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0,
-0x3c030001, 0x24636f90, 0x203102b, 0x10400003,
-0x0, 0x3c100001, 0x8e106ee8, 0x8e220000,
-0xae020000, 0x8e220004, 0xae120008, 0xae020004,
-0x8f820054, 0xae130010, 0xae150014, 0xae1e0018,
-0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0,
-0x203102b, 0x10400003, 0x0, 0x3c100001,
-0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000,
-0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec,
-0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024,
-0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821,
-0x83102b, 0x10400006, 0x0, 0xac800000,
-0x24840004, 0x83102b, 0x5440fffd, 0xac800000,
-0x3e00008, 0x0, 0xa61821, 0xa3102b,
-0x10400007, 0x0, 0x8c820000, 0xaca20000,
-0x24a50004, 0xa3102b, 0x1440fffb, 0x24840004,
-0x3e00008, 0x0, 0x861821, 0x83102b,
-0x10400007, 0x0, 0x8ca20000, 0xac820000,
-0x24840004, 0x83102b, 0x1440fffb, 0x24a50004,
-0x3e00008, 0x0, 0x63080, 0x861821,
-0x83102b, 0x10400006, 0x0, 0xac850000,
-0x24840004, 0x83102b, 0x5440fffd, 0xac850000,
-0x3e00008, 0x0, 0x0, 0x26e50028,
-0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c,
-0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204,
-0x8f4c0200, 0x24640400, 0x64102b, 0x10400008,
-0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004,
-0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff,
-0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c,
-0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204,
-0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200,
-0x821024, 0x34420004, 0xc31824, 0x34630004,
-0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084,
-0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c,
-0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094,
-0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c,
-0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4,
-0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac,
-0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4,
-0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc,
-0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0,
-0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0,
-0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4,
-0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec,
-0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c,
-0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4,
-0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8,
-0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff,
-0x3463fffb, 0x431024, 0xaf820220, 0x30c20004,
-0x14400006, 0x0, 0x8f820200, 0x3c03c0ff,
-0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc,
-0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc,
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
-0xafb00020, 0x8f430024, 0x8f420020, 0x10620038,
-0x0, 0x8f430020, 0x8f420024, 0x622023,
-0x4810003, 0x0, 0x8f420040, 0x822021,
-0x8f430030, 0x8f420024, 0x43102b, 0x14400005,
-0x0, 0x8f430040, 0x8f420024, 0x10000005,
-0x621023, 0x8f420030, 0x8f430024, 0x431023,
-0x2442ffff, 0x406021, 0x8c102a, 0x54400001,
-0x806021, 0x8f4a0024, 0x8f490040, 0x8f480024,
-0x8f440180, 0x8f450184, 0x8f460024, 0x8f4b001c,
-0x24070001, 0xafa70010, 0x84100, 0x1001821,
-0x14c5021, 0x2529ffff, 0x1498024, 0xafb00014,
-0x8f470014, 0x1021, 0x63100, 0xafa70018,
-0xa32821, 0xa3382b, 0x822021, 0x872021,
-0x8f420108, 0x1663021, 0x40f809, 0xc3900,
-0x54400001, 0xaf500024, 0x8f430024, 0x8f420020,
-0x14620018, 0x0, 0x8f420000, 0x10400007,
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
-0x0, 0x10000005, 0x0, 0xaf800048,
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
-0x2403ffef, 0x431024, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x10000002, 0xaf80004c,
-0xaf800048, 0x8fbf0024, 0x8fb00020, 0x3e00008,
-0x27bd0028, 0x3e00008, 0x0, 0x27bdffc0,
-0x32c20020, 0xafbf0038, 0xafb30034, 0xafb20030,
-0xafb1002c, 0x10400004, 0xafb00028, 0x8f530028,
-0x10000002, 0x0, 0x8f530020, 0x8f420030,
-0x105300eb, 0x21100, 0x8f43001c, 0x628021,
-0x8e040000, 0x8e050004, 0x96120008, 0x8f420090,
-0x9611000a, 0x3246ffff, 0x46102a, 0x10400017,
-0x0, 0x8f8200d8, 0x8f430098, 0x431023,
-0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf,
-0x10400005, 0x0, 0x8f420090, 0x8f430144,
-0x431021, 0xaf420090, 0x8f420090, 0x46102a,
-0x10400006, 0x0, 0x8f420348, 0x24420001,
-0xaf420348, 0x100000e1, 0x8f420348, 0x8f8200fc,
-0x14400006, 0x0, 0x8f420344, 0x24420001,
-0xaf420344, 0x100000d9, 0x8f420344, 0x934205c2,
-0x1040000b, 0x32c20008, 0x10400008, 0x32220200,
-0x10400006, 0x3c034000, 0x9602000e, 0xaf4300ac,
-0x21400, 0x10000002, 0xaf4200b0, 0xaf4000ac,
-0x32220004, 0x1040007f, 0x32220800, 0x10400003,
-0x3247ffff, 0x10000002, 0x24020020, 0x24020004,
-0xafa20010, 0x8f420030, 0xafa20014, 0x8f420010,
-0x3c030002, 0x431025, 0xafa20018, 0x8f460098,
-0x8f420108, 0x40f809, 0x0, 0x104000b7,
-0x0, 0x8f42009c, 0x8f430094, 0x2421021,
-0xaf42009c, 0xae03000c, 0x8f4200ac, 0x10400008,
-0x3c034000, 0x8f420094, 0x431025, 0xafa20020,
-0x8f42009c, 0x8f4300b0, 0x10000004, 0x431025,
-0x8f420094, 0xafa20020, 0x8f42009c, 0xafa20024,
-0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
-0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
-0x8f440270, 0x8f450274, 0x401821, 0x1021,
-0xa32821, 0xa3302b, 0x822021, 0x862021,
-0x32230060, 0x24020040, 0xaf440270, 0xaf450274,
-0x10620017, 0x2c620041, 0x10400005, 0x24020020,
-0x10620008, 0x24020001, 0x10000026, 0x0,
-0x24020060, 0x10620019, 0x24020001, 0x10000021,
-0x0, 0x8f420278, 0x8f43027c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
-0x8f420278, 0x8f43027c, 0x10000016, 0x24020001,
-0x8f420280, 0x8f430284, 0x24630001, 0x2c640001,
-0x441021, 0xaf420280, 0xaf430284, 0x8f420280,
-0x8f430284, 0x1000000b, 0x24020001, 0x8f420288,
-0x8f43028c, 0x24630001, 0x2c640001, 0x441021,
-0xaf420288, 0xaf43028c, 0x8f420288, 0x8f43028c,
-0x24020001, 0xa34205c2, 0x8f420098, 0x3244ffff,
-0x2406fff8, 0x8f45013c, 0x441021, 0x24420007,
-0x461024, 0x24840007, 0xaf420094, 0x8f420090,
-0x8f430094, 0x862024, 0x441023, 0x65182b,
-0x14600005, 0xaf420090, 0x8f420094, 0x8f430144,
-0x431023, 0xaf420094, 0x8f420094, 0x10000023,
-0xaf40009c, 0x3247ffff, 0x50e00022, 0x32c20020,
-0x14400002, 0x24020010, 0x24020002, 0xafa20010,
-0x8f420030, 0xafa20014, 0x8f420010, 0xafa20018,
-0x8f460098, 0x8f420108, 0x40f809, 0x0,
-0x1040003a, 0x3245ffff, 0x8f420098, 0x8f430090,
-0x8f46013c, 0x451021, 0xaf420098, 0x8f42009c,
-0x8f440098, 0xa34005c2, 0x651823, 0xaf430090,
-0x451021, 0x86202b, 0x14800005, 0xaf42009c,
-0x8f420098, 0x8f430144, 0x431023, 0xaf420098,
-0x32c20020, 0x10400005, 0x0, 0x8f420358,
-0x2442ffff, 0xaf420358, 0x8f420358, 0x8f420030,
-0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
-0xaf420030, 0x8f420030, 0x14530018, 0x0,
-0x8f420000, 0x10400007, 0x0, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x2403fff7, 0x431024,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0038,
-0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
-0x3e00008, 0x27bd0040, 0x3e00008, 0x0,
-0x27bdffd0, 0x32c20020, 0xafbf002c, 0xafb20028,
-0xafb10024, 0x10400004, 0xafb00020, 0x8f520028,
-0x10000002, 0x0, 0x8f520020, 0x8f420030,
-0x105200b5, 0x21100, 0x8f43001c, 0x628021,
-0x8e040000, 0x8e050004, 0x96110008, 0x8f420090,
-0x9607000a, 0x3226ffff, 0x46102a, 0x10400017,
-0x0, 0x8f8200d8, 0x8f430098, 0x431023,
-0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47,
-0x10400005, 0x0, 0x8f420090, 0x8f430144,
-0x431021, 0xaf420090, 0x8f420090, 0x46102a,
-0x10400006, 0x0, 0x8f420348, 0x24420001,
-0xaf420348, 0x100000ab, 0x8f420348, 0x8f8600fc,
-0x10c0000c, 0x0, 0x8f8200f4, 0x2403fff8,
-0x431024, 0x461023, 0x218c3, 0x58600001,
-0x24630100, 0x8f42008c, 0x43102b, 0x14400006,
-0x712c2, 0x8f420344, 0x24420001, 0xaf420344,
-0x10000098, 0x8f420344, 0x934305c2, 0x1060000f,
-0x30460001, 0x8f420010, 0x34480400, 0x32c20008,
-0x10400008, 0x30e20200, 0x10400006, 0x3c034000,
-0x9602000e, 0xaf4300ac, 0x21400, 0x10000004,
-0xaf4200b0, 0x10000002, 0xaf4000ac, 0x8f480010,
-0x30e20004, 0x10400045, 0x3227ffff, 0x8f4900ac,
-0x11200005, 0x30c200ff, 0x14400006, 0x24020040,
-0x10000004, 0x24020008, 0x14400002, 0x24020020,
-0x24020004, 0xafa20010, 0x8f430030, 0x11200004,
-0xafa30014, 0x8f4200b0, 0x621025, 0xafa20014,
-0x3c020002, 0x1021025, 0xafa20018, 0x8f460098,
-0x8f420108, 0x40f809, 0x0, 0x10400069,
-0x3224ffff, 0x8f42008c, 0x8f430094, 0x24420001,
-0xaf42008c, 0x24020001, 0xae03000c, 0xa34205c2,
-0x8f420098, 0x2406fff8, 0x8f45013c, 0x441021,
-0x24420007, 0x461024, 0x24840007, 0xaf420094,
-0x8f420090, 0x8f430094, 0x862024, 0x441023,
-0x65182b, 0x14600005, 0xaf420090, 0x8f420094,
-0x8f430144, 0x431023, 0xaf420094, 0x8f430094,
-0x8f420140, 0x43102b, 0x10400009, 0x0,
-0x8f43013c, 0x8f440094, 0x8f420090, 0x8f450138,
-0x641823, 0x431023, 0xaf420090, 0xaf450094,
-0x8f420094, 0x1000001f, 0xaf420098, 0x10e0001d,
-0x30c200ff, 0x14400002, 0x24020010, 0x24020002,
-0xafa20010, 0x8f420030, 0xafa80018, 0xafa20014,
-0x8f460098, 0x8f420108, 0x40f809, 0x0,
-0x10400030, 0x3225ffff, 0x8f420098, 0x8f44013c,
-0x451021, 0xaf420098, 0x8f420090, 0x8f430098,
-0xa34005c2, 0x451023, 0x64182b, 0x14600005,
-0xaf420090, 0x8f420098, 0x8f430144, 0x431023,
-0xaf420098, 0x8f420030, 0x8f430040, 0x24420001,
-0x2463ffff, 0x431024, 0xaf420030, 0x8f420030,
-0x14520018, 0x0, 0x8f420000, 0x10400007,
-0x0, 0xaf80004c, 0x8f82004c, 0x1040fffd,
-0x0, 0x10000005, 0x0, 0xaf800048,
-0x8f820048, 0x1040fffd, 0x0, 0x8f820060,
-0x2403fff7, 0x431024, 0xaf820060, 0x8f420000,
-0x10400003, 0x0, 0x10000002, 0xaf80004c,
-0xaf800048, 0x8fbf002c, 0x8fb20028, 0x8fb10024,
-0x8fb00020, 0x3e00008, 0x27bd0030, 0x3e00008,
-0x0, 0x27bdffd8, 0x3c020001, 0x34422ec0,
-0xafbf0020, 0x8f4300f0, 0x8f840108, 0x2e21021,
-0x54620004, 0x24620008, 0x3c020001, 0x34422cc0,
-0x2e21021, 0x401821, 0xaf4300f0, 0xac600000,
-0x8f4200ec, 0x8c660004, 0x14620004, 0x3c020001,
-0x24820020, 0x1000000f, 0xaf820108, 0x8f4300f0,
-0x34422ec0, 0x2e21021, 0x54620004, 0x24620008,
-0x3c020001, 0x34422cc0, 0x2e21021, 0x401821,
-0x8c620004, 0x21140, 0x821021, 0xaf820108,
-0xac600000, 0x8c850018, 0x30a20036, 0x1040006c,
-0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034,
-0x24420001, 0x2463ffff, 0x431024, 0x862021,
-0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034,
-0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4,
-0x0, 0x32c20010, 0x10400028, 0x24070008,
-0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
-0x8f860120, 0x24020080, 0xafa20010, 0xafa30014,
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c,
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100,
-0x10000036, 0x0, 0x8f420300, 0x8f43002c,
-0x24420001, 0xaf420300, 0x8f420300, 0x24020001,
-0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170,
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
-0x24020020, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
-0x24020001, 0x3c010001, 0x370821, 0xa02240f0,
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
-0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120,
-0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f,
-0x0, 0x8f420300, 0x24420001, 0xaf420300,
-0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038,
-0x3c010001, 0x370821, 0xa02040f1, 0x3c010001,
-0x370821, 0xa02040f0, 0xaf400034, 0x8f420314,
-0x24420001, 0xaf420314, 0x10000059, 0x8f420314,
-0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028,
-0xa22023, 0x4810003, 0x0, 0x8f420040,
-0x822021, 0x8f420358, 0x8f430000, 0xaf450028,
-0x441021, 0x10600007, 0xaf420358, 0xaf80004c,
-0x8f82004c, 0x1040fffd, 0x0, 0x10000005,
-0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x34420008, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000038,
-0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f,
-0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c,
-0x8f420050, 0x622023, 0x4820001, 0x24840200,
-0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368,
-0x1000001a, 0xaf430050, 0x1040000c, 0x32c28000,
-0x8c83001c, 0x8f420070, 0x622023, 0x4820001,
-0x24840400, 0x8f420364, 0x441021, 0xaf420364,
-0x8f420368, 0x1000000d, 0xaf430070, 0x1040000e,
-0x3c020800, 0x8c83001c, 0x8f420060, 0x622023,
-0x4820001, 0x24840100, 0x8f420360, 0x441021,
-0xaf420360, 0x8f420368, 0xaf430060, 0x441021,
-0xaf420368, 0x3c020800, 0x2c21024, 0x50400008,
-0x36940040, 0x10000006, 0x0, 0x30a20100,
-0x10400003, 0x0, 0xc002bd8, 0x0,
-0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008,
-0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c,
-0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c,
-0xafb00038, 0x8f910108, 0x26220020, 0xaf820108,
-0x8e320018, 0xa821, 0x32420024, 0x104001ba,
-0xf021, 0x8e26001c, 0x8f43001c, 0x61100,
-0x621821, 0x8c70000c, 0x9604000c, 0x962d0016,
-0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001,
-0x621825, 0x10600015, 0x2821, 0x32c20040,
-0x10400015, 0x24020800, 0x96030014, 0x14620012,
-0x3402aaaa, 0x9603000e, 0x14620007, 0x2021,
-0x96030010, 0x24020300, 0x14620004, 0x801021,
-0x96020012, 0x2c440001, 0x801021, 0x54400006,
-0x24050016, 0x10000004, 0x0, 0x24020800,
-0x50820001, 0x2405000e, 0x934205c3, 0x14400008,
-0x5821, 0x240b0001, 0x32620180, 0xaf4500a8,
-0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3,
-0x10a00085, 0x2054021, 0x91020000, 0x3821,
-0x3042000f, 0x25080, 0x32c20002, 0x10400012,
-0x10a1821, 0x32620002, 0x10400010, 0x32c20001,
-0x1002021, 0x94820000, 0x24840002, 0xe23821,
-0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02,
-0x623821, 0x71c02, 0x30e2ffff, 0x623821,
-0x71027, 0xa502000a, 0x32c20001, 0x1040006a,
-0x32620001, 0x10400068, 0x0, 0x8f4200a8,
-0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8,
-0x431021, 0x904c0009, 0x318900ff, 0x39230006,
-0x3182b, 0x39220011, 0x2102b, 0x621824,
-0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001,
-0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600,
-0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e,
-0x0, 0x32c20004, 0x14400013, 0x2821,
-0x316200ff, 0x14400004, 0x0, 0x95020002,
-0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e,
-0x95030010, 0xa22821, 0xa32821, 0x95030012,
-0x91040009, 0x95020002, 0xa32821, 0xa42821,
-0x4a1023, 0xa22821, 0x2002021, 0x94820000,
-0x24840002, 0xe23821, 0x88102b, 0x1440fffb,
-0x71c02, 0x30e2ffff, 0x623821, 0x71c02,
-0x30e2ffff, 0x623821, 0x1a52821, 0x51c02,
-0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff,
-0x622821, 0xa72823, 0x51402, 0xa22821,
-0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff,
-0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8,
-0x624021, 0x91020000, 0x3042000f, 0x25080,
-0x318300ff, 0x24020006, 0x14620003, 0x10a1021,
-0x10000002, 0x24440010, 0x24440006, 0x316200ff,
-0x14400006, 0x0, 0x94820000, 0xa22821,
-0x51c02, 0x30a2ffff, 0x622821, 0x934205c3,
-0x10400003, 0x32620100, 0x50400003, 0xa4850000,
-0x52827, 0xa4850000, 0x9622000e, 0x8f43009c,
-0x621821, 0x32a200ff, 0x10400007, 0xaf43009c,
-0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c,
-0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c,
-0xafa20024, 0x32620080, 0x10400010, 0x32620100,
-0x8f4200b4, 0x24430001, 0x210c0, 0x571021,
-0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001,
-0x220821, 0xac2338e8, 0x3c010001, 0x220821,
-0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064,
-0x0, 0x8f4200b4, 0x24430001, 0x210c0,
-0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024,
-0x3c010001, 0x220821, 0xac2338e8, 0x3c010001,
-0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051,
-0x3821, 0x3c090001, 0x352938e8, 0x3c08001f,
-0x3508ffff, 0x240bffff, 0x340affff, 0x710c0,
-0x571021, 0x491021, 0x8c430000, 0x8c440004,
-0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028,
-0x8fa4002c, 0xac430000, 0xac440004, 0x24420008,
-0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c,
-0x97a2002e, 0x8f440270, 0x8f450274, 0x401821,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaf440270, 0xaf450274, 0x8fa20028,
-0x481024, 0x90430000, 0x30630001, 0x1460000b,
-0x402021, 0x8f420278, 0x8f43027c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
-0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000,
-0x144b000e, 0x0, 0x94820004, 0x144a000b,
-0x0, 0x8f420288, 0x8f43028c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420288, 0xaf43028c,
-0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280,
-0x8f430284, 0x24630001, 0x2c640001, 0x441021,
-0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284,
-0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8,
-0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4,
-0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000,
-0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c,
-0x8f46008c, 0x8f440270, 0x8f450274, 0x401821,
-0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaf440270,
-0xaf450274, 0x92020000, 0x30420001, 0x1440000c,
-0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001,
-0x2c640001, 0x441021, 0xaf420278, 0xaf43027c,
-0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020,
-0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004,
-0x1462000c, 0x0, 0x8f420288, 0x8f43028c,
-0x24630001, 0x2c640001, 0x441021, 0xaf420288,
-0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b,
-0x32c20020, 0x8f420280, 0x8f430284, 0x24630001,
-0x2c640001, 0x441021, 0xaf420280, 0xaf430284,
-0x8f420280, 0x8f430284, 0x32c20020, 0x10400005,
-0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358,
-0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001,
-0x2463ffff, 0x431024, 0xaf42002c, 0x32420060,
-0x14400008, 0x32c20010, 0x8f420034, 0x24420001,
-0xaf420034, 0x8c03023c, 0x43102b, 0x14400102,
-0x32c20010, 0x10400018, 0x24070008, 0x8f440170,
-0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120,
-0x24020080, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047,
-0x24020001, 0x8f420300, 0x8f43002c, 0x24420001,
-0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1,
-0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174,
-0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020,
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x10400057, 0x24020001,
-0x10000065, 0x0, 0x32420012, 0x10400075,
-0x32420001, 0x9622000e, 0x8f43009c, 0x621821,
-0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358,
-0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c,
-0x8f430040, 0x24420001, 0x2463ffff, 0x431024,
-0xaf42002c, 0x32420010, 0x14400008, 0x32c20010,
-0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c,
-0x43102b, 0x144000bc, 0x32c20010, 0x10400028,
-0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c,
-0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010,
-0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809,
-0x24c6001c, 0x14400011, 0x24020001, 0x3c010001,
-0x370821, 0xa02240f1, 0x8f820124, 0xafa20010,
-0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014,
-0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b,
-0x34a51100, 0x10000036, 0x0, 0x8f420300,
-0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300,
-0x24020001, 0xa34205c1, 0x10000026, 0xaf430038,
-0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c,
-0x8f860120, 0x24020020, 0xafa20010, 0xafa30014,
-0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c,
-0x14400011, 0x24020001, 0x3c010001, 0x370821,
-0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128,
-0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c,
-0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900,
-0x1000000f, 0x0, 0x8f420300, 0x24420001,
-0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1,
-0xaf420038, 0x3c010001, 0x370821, 0xa02040f1,
-0x3c010001, 0x370821, 0xa02040f0, 0xaf400034,
-0x8f420314, 0x24420001, 0xaf420314, 0x10000062,
-0x8f420314, 0x10400022, 0x32427000, 0x8e25001c,
-0x8f420028, 0xa22023, 0x4810003, 0x0,
-0x8f420040, 0x822021, 0x8f420358, 0x8f430000,
-0xaf450028, 0x441021, 0x10600007, 0xaf420358,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x34420008,
-0xaf820060, 0x8f420000, 0x10400003, 0x0,
-0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048,
-0x1040002f, 0x32421000, 0x1040000c, 0x32424000,
-0x8e23001c, 0x8f420050, 0x622023, 0x4820001,
-0x24840200, 0x8f42035c, 0x441021, 0xaf42035c,
-0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c,
-0x32c28000, 0x8e23001c, 0x8f420070, 0x622023,
-0x4820001, 0x24840400, 0x8f420364, 0x441021,
-0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070,
-0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060,
-0x622023, 0x4820001, 0x24840100, 0x8f420360,
-0x441021, 0xaf420360, 0x8f420368, 0xaf430060,
-0x441021, 0xaf420368, 0x3c020800, 0x2c21024,
-0x50400011, 0x36940040, 0x1000000f, 0x0,
-0x32420048, 0x10400007, 0x24150001, 0x8e22001c,
-0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75,
-0xae22001c, 0x32420100, 0x10400003, 0x0,
-0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c,
-0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c,
-0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008,
-0x0, 0x0, 0x0, 0x8f8300e4,
-0x8f8200e0, 0x2404fff8, 0x441024, 0x621026,
-0x2102b, 0x21023, 0x3e00008, 0x621024,
-0x3e00008, 0x0, 0x27bdffe0, 0xafbf001c,
-0xafb00018, 0x8f8600c4, 0x8f8400e0, 0x8f8500e4,
-0x2402fff8, 0x821824, 0x10a30009, 0x27623ff8,
-0x14a20002, 0x24a20008, 0x27623000, 0x408021,
-0x16030005, 0x30820004, 0x10400004, 0xc02021,
-0x10000022, 0x1021, 0x8e040000, 0x8f42011c,
-0x14a20003, 0x0, 0x8f420120, 0xaf420114,
-0x8ca30000, 0x8f420148, 0x831823, 0x43102b,
-0x10400003, 0x0, 0x8f420148, 0x621821,
-0x94a20006, 0x24420050, 0x62102b, 0x1440000f,
-0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000,
-0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894,
-0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c,
-0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c,
-0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008,
-0x0, 0x8f8400e0, 0x8f8800c4, 0x8f8300e8,
-0x2402fff8, 0x823824, 0xe32023, 0x2c821000,
-0x50400001, 0x24841000, 0x420c2, 0x801821,
-0x8f440258, 0x8f45025c, 0x1021, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaf440258,
-0xaf45025c, 0x8f8300c8, 0x8f420148, 0x1032023,
-0x82102b, 0x14400004, 0x801821, 0x8f420148,
-0x822021, 0x801821, 0x8f440250, 0x8f450254,
-0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaf440250, 0xaf450254, 0xaf8800c8,
-0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0,
-0x27bdff30, 0x240a0001, 0xafbf00c8, 0xafbe00c4,
-0xafb500c0, 0xafb300bc, 0xafb200b8, 0xafb100b4,
-0xafb000b0, 0xa3a00097, 0xafa00044, 0xafaa005c,
-0x934205c4, 0xa7a0008e, 0x1040000a, 0xa7a00086,
-0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c,
-0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129,
-0xafaa007c, 0x8f420114, 0x40f809, 0x0,
-0x403021, 0x10c0034f, 0x0, 0x8cc20000,
-0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024,
-0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c,
-0x3c020006, 0x2c21024, 0xafab007c, 0x14400015,
-0xafaa0064, 0x91420000, 0x30420001, 0x10400011,
-0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff,
-0x95430004, 0x1062000b, 0x0, 0xc0024bb,
-0x8fa40064, 0x304200ff, 0x14400006, 0x0,
-0x8f420118, 0x40f809, 0x0, 0x1000032d,
-0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
-0x431024, 0x3c03ffff, 0x431824, 0x14600003,
-0xafa20024, 0x10000040, 0x1821, 0x3c020080,
-0x621024, 0x10400007, 0x0, 0x8f42038c,
-0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
-0x24030001, 0x8f420210, 0x24420001, 0xaf420210,
-0x8f420210, 0x3c020001, 0x621024, 0x10400006,
-0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
-0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
-0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
-0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
-0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
-0x8f420380, 0x3c020008, 0x621024, 0x10400006,
-0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
-0x8f420384, 0x3c020010, 0x621024, 0x10400006,
-0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
-0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
-0x24030001, 0x8f420388, 0x24420001, 0xaf420388,
-0x8f420388, 0x24030001, 0x8c020260, 0x8fab006c,
-0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8,
-0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c,
-0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010,
-0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
-0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
-0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080,
-0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c,
-0x3c020080, 0x34420100, 0x1621024, 0x10400005,
-0x0, 0x8f42020c, 0x24420001, 0xaf42020c,
-0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400,
-0x10400015, 0x34028100, 0x8faa0064, 0x9543000c,
-0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e,
-0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000,
-0x8faa006c, 0x8fab0064, 0x254afffc, 0xafaa006c,
-0xa7a20086, 0xad63000c, 0xad640008, 0xad650004,
-0x256b0004, 0xafab0064, 0x3c020100, 0x2c21024,
-0x10400004, 0x0, 0x8faa006c, 0x254a0004,
-0xafaa006c, 0x8f4200bc, 0x5040000a, 0xafa00074,
-0x8fab006c, 0x4b102b, 0x50400006, 0xafa00074,
-0x8f4200bc, 0x1621023, 0xafa20074, 0x8f4a00bc,
-0xafaa006c, 0x8f420080, 0x8fab006c, 0x4b102b,
-0x10400056, 0x32c28000, 0x1040005e, 0x240a0003,
-0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058,
-0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024,
-0x24420001, 0xaf420350, 0x1000024f, 0x8f420350,
-0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
-0x3c040001, 0x248468d0, 0x26620001, 0xafa20014,
-0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
-0xc002b3b, 0x34a52250, 0x1000023f, 0x0,
-0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128,
-0x3c040001, 0x248468d0, 0x24020002, 0xafa20014,
-0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007,
-0xc002b3b, 0x34a52450, 0x1000022f, 0x0,
-0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8,
-0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800,
-0xc002b3b, 0x603021, 0x10000223, 0x0,
-0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0,
-0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120,
-0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216,
-0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124,
-0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010,
-0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b,
-0x34a53200, 0x10000208, 0x0, 0x8f420084,
-0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001,
-0x2c21024, 0x10400004, 0x0, 0x240b0002,
-0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020,
-0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c,
-0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002,
-0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054,
-0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001,
-0x304201ff, 0xafa20054, 0x1e1140, 0x431021,
-0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c,
-0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010,
-0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b,
-0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024,
-0x24630001, 0xaf430350, 0x100001d3, 0x8f420350,
-0x156a001d, 0x0, 0x8f430074, 0x8f420070,
-0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c,
-0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140,
-0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044,
-0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007,
-0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070,
-0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c,
-0x1000ffc3, 0x0, 0x8f430064, 0x8f420060,
-0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c,
-0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054,
-0x24020004, 0x1562000e, 0x1e1140, 0x1e1180,
-0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a,
-0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024,
-0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097,
-0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044,
-0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014,
-0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007,
-0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024,
-0x1440ff34, 0x0, 0x8f420370, 0x240a0001,
-0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90,
-0x8f420370, 0x27a30036, 0x131040, 0x621821,
-0x94620000, 0x441021, 0x10000020, 0xa4620000,
-0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072,
-0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4,
-0x25420020, 0xafa20028, 0x25420008, 0xafa20030,
-0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a,
-0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a,
-0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018,
-0x24630002, 0x822023, 0x1880ffde, 0x26730001,
-0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
-0x26650001, 0xa2102a, 0x1440002b, 0x24030001,
-0x8f83012c, 0x10600023, 0x0, 0x8f820124,
-0x431023, 0x22143, 0x58800001, 0x24840040,
-0x8f820128, 0x431023, 0x21943, 0x58600001,
-0x24630040, 0x64102a, 0x54400001, 0x602021,
-0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011,
-0x24030001, 0x10000015, 0x306200ff, 0x8fab0064,
-0x96070018, 0xafab0010, 0x8e220008, 0x3c040001,
-0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400,
-0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b,
-0x0, 0x8f420334, 0x1821, 0x24420001,
-0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc,
-0x3c020800, 0x12600021, 0x9021, 0x8fb100a4,
-0x2208021, 0x8e220008, 0x96070018, 0x8fa60064,
-0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010,
-0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c,
-0x40f809, 0x0, 0x1040ffd8, 0x3c050007,
-0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821,
-0x14b102b, 0x10400004, 0xafab0064, 0x8f420148,
-0x1625823, 0xafab0064, 0x26100002, 0x26520001,
-0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c,
-0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002,
-0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c,
-0x10600013, 0x0, 0x8f820124, 0x431023,
-0x22143, 0x58800001, 0x24840040, 0x8f820128,
-0x431023, 0x21943, 0x58600001, 0x24630040,
-0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
-0x8f4200fc, 0xa2102a, 0x14400006, 0x24030001,
-0x8f420334, 0x1821, 0x24420001, 0xaf420334,
-0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800,
-0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b,
-0x54400001, 0x608021, 0x8ea40000, 0x8ea50004,
-0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008,
-0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809,
-0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e,
-0x97aa008e, 0x11400007, 0x609021, 0x934205c4,
-0x14400004, 0x0, 0x97ab0086, 0x6a1825,
-0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024,
-0x10400003, 0xa1402, 0x34630400, 0xa6a20014,
-0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004,
-0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a,
-0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000,
-0xafa20010, 0x8f420044, 0x2a03021, 0x24070020,
-0xafa20014, 0x8f42000c, 0x31940, 0x604821,
-0xafa20018, 0x8f42010c, 0x4021, 0xa92821,
-0xa9182b, 0x882021, 0x40f809, 0x832021,
-0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c,
-0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c,
-0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002,
-0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
-0x8f42035c, 0x156a0006, 0x0, 0x8f420364,
-0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364,
-0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360,
-0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044,
-0x8f440088, 0x8f430078, 0x24420001, 0x441024,
-0x24630001, 0xaf420044, 0xaf430078, 0x8c020240,
-0x62182b, 0x14600075, 0x24070008, 0x8f440168,
-0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120,
-0x24020040, 0xafa20010, 0xafa30014, 0xafa80018,
-0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011,
-0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2,
-0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001,
-0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120,
-0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b,
-0x0, 0x8f420304, 0x24420001, 0xaf420304,
-0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001,
-0x370821, 0xa02040f2, 0xaf400078, 0x8f420318,
-0x24420001, 0xaf420318, 0x10000048, 0x8f420318,
-0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4,
-0x34028000, 0xafa20010, 0x8f420044, 0x2a03021,
-0x24070020, 0xafa20014, 0x8f42000c, 0x31940,
-0x604821, 0xafa20018, 0x8f42010c, 0x4021,
-0xa92821, 0xa9182b, 0x882021, 0x40f809,
-0x832021, 0x1040fe1f, 0x240a0001, 0xa34a05c4,
-0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c,
-0x8fab009c, 0x1505021, 0x16a102b, 0x10400004,
-0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064,
-0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c,
-0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002,
-0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c,
-0x8f42035c, 0x114b0006, 0x0, 0x8f420360,
-0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360,
-0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364,
-0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044,
-0x8f440088, 0x8f430078, 0x24420001, 0x441024,
-0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c,
-0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e,
-0x0, 0x934205c4, 0x10400009, 0x0,
-0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c,
-0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc,
-0x97ab008e, 0x1160000b, 0x34038100, 0x8fa20020,
-0x8c46000c, 0xa443000c, 0x97aa0086, 0x8c440004,
-0x8c450008, 0xa44a000e, 0xac440000, 0xac450004,
-0xac460008, 0x8f42034c, 0x24420001, 0xaf42034c,
-0x10000010, 0x8f42034c, 0x8fab007c, 0x3164ffff,
-0x2484fffc, 0x801821, 0x8f440250, 0x8f450254,
-0x8f460118, 0x1021, 0xa32821, 0xa3382b,
-0x822021, 0x872021, 0xaf440250, 0xc0f809,
-0xaf450254, 0x8fbf00c8, 0x8fbe00c4, 0x8fb500c0,
-0x8fb300bc, 0x8fb200b8, 0x8fb100b4, 0x8fb000b0,
-0x3e00008, 0x27bd00d0, 0x3e00008, 0x0,
-0x27bdff38, 0x240b0001, 0xafbf00c0, 0xafbe00bc,
-0xafb500b8, 0xafb300b4, 0xafb200b0, 0xafb100ac,
-0xafb000a8, 0xa3a00087, 0xafa00044, 0xafab005c,
-0x934205c4, 0xa7a00076, 0x10400007, 0xa7a0007e,
-0x8f4c00c0, 0xafac0064, 0x8f4b00c8, 0x8f5e00c4,
-0x10000130, 0xafab006c, 0x8f420114, 0x40f809,
-0x0, 0x403021, 0x10c002a1, 0x0,
-0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024,
-0x8fac0024, 0x8fbe0020, 0x3182ffff, 0x2442fffc,
-0xafa20064, 0x3c020006, 0x2c21024, 0x14400015,
-0xafac006c, 0x93c20000, 0x30420001, 0x10400011,
-0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff,
-0x97c30004, 0x1062000b, 0x0, 0xc0024bb,
-0x3c02021, 0x304200ff, 0x14400006, 0x0,
-0x8f420118, 0x40f809, 0x0, 0x10000280,
-0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
-0x431024, 0x3c03ffff, 0x431824, 0x14600003,
-0xafa20024, 0x10000040, 0x8021, 0x3c020080,
-0x621024, 0x10400007, 0x0, 0x8f42038c,
-0x24420001, 0xaf42038c, 0x8f42038c, 0x10000036,
-0x24100001, 0x8f420210, 0x24420001, 0xaf420210,
-0x8f420210, 0x3c020001, 0x621024, 0x10400006,
-0x3c020002, 0x8f4201c4, 0x24420001, 0xaf4201c4,
-0x8f4201c4, 0x3c020002, 0x621024, 0x10400006,
-0x3c020004, 0x8f42037c, 0x24420001, 0xaf42037c,
-0x8f42037c, 0x3c020004, 0x621024, 0x10400006,
-0x3c020008, 0x8f420380, 0x24420001, 0xaf420380,
-0x8f420380, 0x3c020008, 0x621024, 0x10400006,
-0x3c020010, 0x8f420384, 0x24420001, 0xaf420384,
-0x8f420384, 0x3c020010, 0x621024, 0x10400006,
-0x3c020020, 0x8f4201c0, 0x24420001, 0xaf4201c0,
-0x8f4201c0, 0x3c020020, 0x621024, 0x10400006,
-0x24100001, 0x8f420388, 0x24420001, 0xaf420388,
-0x8f420388, 0x24100001, 0x8c020260, 0x8fab0064,
-0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8,
-0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c,
-0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010,
-0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0,
-0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007,
-0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010,
-0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400,
-0x8fab006c, 0x3c020080, 0x34420100, 0x1621024,
-0x10400005, 0x0, 0x8f42020c, 0x24420001,
-0xaf42020c, 0x8f42020c, 0x10000202, 0x8fa30064,
-0x32c20400, 0x10400012, 0x34028100, 0x97c3000c,
-0x1462000f, 0x0, 0x240c0200, 0xa7ac0076,
-0x97c2000e, 0x8fc30008, 0x8fc40004, 0x8fab0064,
-0x8fc50000, 0x256bfffc, 0xafab0064, 0xa7a2007e,
-0xafc3000c, 0xafc40008, 0xafc50004, 0x27de0004,
-0x8fa70064, 0x320200ff, 0x14400034, 0x3c020100,
-0x97c4000c, 0x2c8305dd, 0x38828870, 0x2c420001,
-0x621825, 0x10600015, 0x2821, 0x32c20800,
-0x10400015, 0x24020800, 0x97c30014, 0x14620012,
-0x3402aaaa, 0x97c3000e, 0x14620007, 0x2021,
-0x97c30010, 0x24020300, 0x14620004, 0x801021,
-0x97c20012, 0x2c440001, 0x801021, 0x54400006,
-0x24050016, 0x10000004, 0x0, 0x24020800,
-0x50820001, 0x2405000e, 0x10a00013, 0x3c52021,
-0x24830009, 0x3c02001f, 0x3442ffff, 0x43102b,
-0x10400003, 0x0, 0x8f420148, 0x621823,
-0x90620000, 0x38430006, 0x2c630001, 0x38420011,
-0x2c420001, 0x621825, 0x10600004, 0x3c020100,
-0x94820002, 0x453821, 0x3c020100, 0x2c21024,
-0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008,
-0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064,
-0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014,
-0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080,
-0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000,
-0x10400034, 0x240b0003, 0x32c21000, 0x10400031,
-0xafab005c, 0x1000002e, 0x240c0004, 0x8f420350,
-0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350,
-0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025,
-0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001,
-0x248468d0, 0x26620001, 0xafa20014, 0xafa30010,
-0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b,
-0x34a55300, 0x10000162, 0x0, 0x8ea20000,
-0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010,
-0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b,
-0x603021, 0x10000156, 0x0, 0x8f420084,
-0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001,
-0x2c21024, 0x10400004, 0x0, 0x240c0002,
-0xafac005c, 0x8fab0064, 0x11600166, 0x27ac0020,
-0xafac008c, 0x8fab005c, 0x240c0001, 0x556c0021,
-0x240c0002, 0x8f430054, 0x8f420050, 0x1062000b,
-0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c,
-0x26220001, 0x304201ff, 0xafa20054, 0x111140,
-0x431021, 0x1000006b, 0x2e2a821, 0x8f420044,
-0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014,
-0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007,
-0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf,
-0x282a024, 0x24630001, 0xaf430350, 0x10000124,
-0x8f420350, 0x156c001d, 0x0, 0x8f430074,
-0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074,
-0xafab004c, 0x26220001, 0x304203ff, 0xafa20054,
-0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821,
-0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8,
-0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074,
-0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b,
-0xafab005c, 0x1000ffc3, 0x0, 0x8f430064,
-0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064,
-0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff,
-0xafa20054, 0x24020004, 0x1562000e, 0x111140,
-0x111180, 0x24420cc0, 0x2e21021, 0xafa20044,
-0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b,
-0x10400024, 0x25950020, 0x240c0001, 0x10000021,
-0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821,
-0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4,
-0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060,
-0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008,
-0x2c21024, 0x1440ff61, 0x0, 0x8f420370,
-0x240c0001, 0xafac005c, 0x24420001, 0xaf420370,
-0x1000ff90, 0x8f420370, 0x27a30036, 0x131040,
-0x621821, 0x94620000, 0x441021, 0x1000001f,
-0xa4620000, 0xaebe0018, 0x93a20087, 0x10400084,
-0x9821, 0x8fab0044, 0x8fa40064, 0x8fa3008c,
-0x25620020, 0xafa20028, 0x25620008, 0xafa20030,
-0x25620010, 0xafab002c, 0xafa20034, 0x9562002a,
-0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a,
-0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018,
-0x24630002, 0x822023, 0x1880ffdf, 0x26730001,
-0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc,
-0x262102a, 0x14400030, 0x24030001, 0x8f83012c,
-0x10600028, 0x0, 0x8f820124, 0x431023,
-0x22143, 0x58800001, 0x24840040, 0x8f820128,
-0x431023, 0x21943, 0x58600001, 0x24630040,
-0x64102a, 0x54400001, 0x602021, 0xaf4400fc,
-0x8f4200fc, 0x262102a, 0x10400016, 0x24030001,
-0x1000001a, 0x306200ff, 0x8fac008c, 0x101040,
-0x4c1021, 0x94470018, 0x101080, 0x4c1021,
-0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc,
-0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500,
-0x2003021, 0xc002b3b, 0xafa30014, 0x10000039,
-0x0, 0x8f420334, 0x1821, 0x24420001,
-0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06,
-0x8021, 0x8f430008, 0x2402fbff, 0x1260002d,
-0x625024, 0x3c0b4000, 0x22b4025, 0x8fb1008c,
-0x2669ffff, 0x2209021, 0x8e420008, 0x96270018,
-0x8c440000, 0x8c450004, 0x56090004, 0x240b0001,
-0x240c0002, 0x10000002, 0xafac0010, 0xafab0010,
-0x16000004, 0xafa80014, 0x8f420008, 0x10000002,
-0xafa20018, 0xafaa0018, 0x8f42010c, 0x3c03021,
-0xafa80098, 0xafa9009c, 0x40f809, 0xafaa00a0,
-0x8fa80098, 0x8fa9009c, 0x8faa00a0, 0x1040ffc2,
-0x3c02001f, 0x96230018, 0x3442ffff, 0x3c3f021,
-0x5e102b, 0x10400003, 0x26310002, 0x8f420148,
-0x3c2f023, 0x26100001, 0x213102b, 0x1440ffda,
-0x26520004, 0x8fb00064, 0x1000001a, 0x0,
-0x96a3000a, 0x8fb00064, 0x70102b, 0x54400001,
-0x608021, 0x8ea40000, 0x8ea50004, 0x8fab005c,
-0x240c0002, 0xafac0010, 0x934305c4, 0xb1700,
-0x10600003, 0x2223025, 0x3c020800, 0xc23025,
-0xafa60014, 0x8f420008, 0xafa20018, 0x8f42010c,
-0x3c03021, 0x40f809, 0x2003821, 0x1040fecb,
-0x3c050007, 0x97ac0076, 0x11800007, 0x96a3000e,
-0x934205c4, 0x14400004, 0x0, 0x97ab007e,
-0x6c1825, 0xa6ab0016, 0x8fac006c, 0x3c02ffff,
-0x1821024, 0x10400003, 0xc1402, 0x34630400,
-0xa6a20014, 0xa6b0000a, 0x8fab0064, 0x560b0006,
-0x3d0f021, 0x34620004, 0xafa00064, 0xa6a2000e,
-0x1000000d, 0xa34005c4, 0x8fac0064, 0x3c02001f,
-0x3442ffff, 0x5e102b, 0x1906023, 0xafac0064,
-0xa6a3000e, 0x240b0001, 0x10400003, 0xa34b05c4,
-0x8f420148, 0x3c2f023, 0x8fab0054, 0x8fac004c,
-0xad8b0000, 0x8fac0064, 0x1580feba, 0x0,
-0x8fab0064, 0x1160001b, 0x0, 0x934205c4,
-0x10400006, 0x0, 0xaf5e00c4, 0xaf4b00c0,
-0x8fac006c, 0x1000000e, 0xaf4c00c8, 0x97ab0076,
-0x1160000b, 0x34038100, 0x8fa20020, 0x8c46000c,
-0xa443000c, 0x97ac007e, 0x8c440004, 0x8c450008,
-0xa44c000e, 0xac440000, 0xac450004, 0xac460008,
-0x8f42034c, 0x24420001, 0xaf42034c, 0x10000010,
-0x8f42034c, 0x8fab006c, 0x3164ffff, 0x2484fffc,
-0x801821, 0x8f440250, 0x8f450254, 0x8f460118,
-0x1021, 0xa32821, 0xa3382b, 0x822021,
-0x872021, 0xaf440250, 0xc0f809, 0xaf450254,
-0x8fbf00c0, 0x8fbe00bc, 0x8fb500b8, 0x8fb300b4,
-0x8fb200b0, 0x8fb100ac, 0x8fb000a8, 0x3e00008,
-0x27bd00c8, 0x3e00008, 0x0, 0x27bdffd8,
-0xafbf0024, 0xafb00020, 0x8f43004c, 0x8f420048,
-0x10620034, 0x0, 0x8f430048, 0x8f42004c,
-0x622023, 0x4820001, 0x24840200, 0x8f430054,
-0x8f42004c, 0x43102b, 0x14400004, 0x24020200,
-0x8f43004c, 0x10000005, 0x431023, 0x8f420054,
-0x8f43004c, 0x431023, 0x2442ffff, 0x405021,
-0x8a102a, 0x54400001, 0x805021, 0x8f49004c,
-0x8f48004c, 0x8f440188, 0x8f45018c, 0x8f46004c,
-0x24071000, 0xafa70010, 0x84140, 0x1001821,
-0x12a4821, 0x313001ff, 0xafb00014, 0x8f470014,
-0x1021, 0x63140, 0xafa70018, 0xa32821,
-0xa3382b, 0x822021, 0x872021, 0x3402ecc0,
-0xc23021, 0x8f420108, 0x2e63021, 0x40f809,
-0xa3940, 0x54400001, 0xaf50004c, 0x8f43004c,
-0x8f420048, 0x14620018, 0x0, 0x8f420000,
-0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
-0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
-0x8f420000, 0x10400003, 0x0, 0x10000002,
-0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb00020,
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f43005c,
-0x8f420058, 0x10620049, 0x0, 0x8f430058,
-0x8f42005c, 0x622023, 0x4820001, 0x24840100,
-0x8f430064, 0x8f42005c, 0x43102b, 0x14400004,
-0x24020100, 0x8f43005c, 0x10000005, 0x431023,
-0x8f420064, 0x8f43005c, 0x431023, 0x2442ffff,
-0x403821, 0x87102a, 0x54400001, 0x803821,
-0x8f42005c, 0x471021, 0x305000ff, 0x32c21000,
-0x10400015, 0x24082000, 0x8f49005c, 0x8f440190,
-0x8f450194, 0x8f46005c, 0x73980, 0xafa80010,
-0xafb00014, 0x8f480014, 0x94980, 0x1201821,
-0x1021, 0xa32821, 0xa3482b, 0x822021,
-0x892021, 0x63180, 0xafa80018, 0x8f420108,
-0x10000014, 0x24c60cc0, 0x8f49005c, 0x8f440190,
-0x8f450194, 0x8f46005c, 0x73940, 0xafa80010,
-0xafb00014, 0x8f480014, 0x94940, 0x1201821,
-0x1021, 0xa32821, 0xa3482b, 0x822021,
-0x892021, 0x63140, 0xafa80018, 0x8f420108,
-0x24c64cc0, 0x40f809, 0x2e63021, 0x54400001,
-0xaf50005c, 0x8f43005c, 0x8f420058, 0x14620018,
-0x0, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x2403feff,
-0x431024, 0xaf820060, 0x8f420000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048,
-0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
-0xafb00020, 0x8f43006c, 0x8f420068, 0x10620033,
-0x0, 0x8f430068, 0x8f42006c, 0x622023,
-0x4820001, 0x24840400, 0x8f430074, 0x8f42006c,
-0x43102b, 0x14400004, 0x24020400, 0x8f43006c,
-0x10000005, 0x431023, 0x8f420074, 0x8f43006c,
-0x431023, 0x2442ffff, 0x405021, 0x8a102a,
-0x54400001, 0x805021, 0x8f49006c, 0x8f48006c,
-0x8f440198, 0x8f45019c, 0x8f46006c, 0x24074000,
-0xafa70010, 0x84140, 0x1001821, 0x12a4821,
-0x313003ff, 0xafb00014, 0x8f470014, 0x1021,
-0x63140, 0x24c66cc0, 0xafa70018, 0xa32821,
-0xa3382b, 0x822021, 0x872021, 0x8f420108,
-0x2e63021, 0x40f809, 0xa3940, 0x54400001,
-0xaf50006c, 0x8f43006c, 0x8f420068, 0x14620018,
-0x0, 0x8f420000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048,
-0x1040fffd, 0x0, 0x8f820060, 0x2403f7ff,
-0x431024, 0xaf820060, 0x8f420000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048,
-0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x8f4200fc, 0x3c030001,
-0x8f4400f8, 0x346330c8, 0x24420001, 0xaf4200fc,
-0x8f850128, 0x2e31021, 0x54820004, 0x24820008,
-0x3c020001, 0x34422ec8, 0x2e21021, 0x401821,
-0xaf4300f8, 0xac600000, 0x8f4200f4, 0x14620004,
-0x3c020001, 0x24a20020, 0x1000000f, 0xaf820128,
-0x8f4300f8, 0x344230c8, 0x2e21021, 0x54620004,
-0x24620008, 0x3c020001, 0x34422ec8, 0x2e21021,
-0x401821, 0x8c620004, 0x21140, 0xa21021,
-0xaf820128, 0xac600000, 0x8ca30018, 0x30620070,
-0x1040002d, 0x30620020, 0x10400004, 0x3c020010,
-0x2c21024, 0x1040000d, 0x0, 0x30620040,
-0x10400004, 0x3c020020, 0x2c21024, 0x10400007,
-0x0, 0x30620010, 0x1040001f, 0x3c020040,
-0x2c21024, 0x1440001c, 0x0, 0x8f820040,
-0x30420001, 0x14400008, 0x2021, 0x8c030104,
-0x24020001, 0x50620005, 0x24040001, 0x8c020264,
-0x10400003, 0x801021, 0x24040001, 0x801021,
-0x10400006, 0x0, 0x8f42030c, 0x24420001,
-0xaf42030c, 0x10000008, 0x8f42030c, 0x8f820044,
-0x34420004, 0xaf820044, 0x8f420308, 0x24420001,
-0xaf420308, 0x8f420308, 0x3e00008, 0x0,
-0x3e00008, 0x0, 0x27bdff98, 0xafbf0060,
-0xafbe005c, 0xafb50058, 0xafb30054, 0xafb20050,
-0xafb1004c, 0xafb00048, 0x8f4200fc, 0x24420001,
-0xaf4200fc, 0x8f880128, 0x25020020, 0xaf820128,
-0x8d030018, 0x30620070, 0x1040002e, 0x30620020,
-0x10400004, 0x3c020010, 0x2c21024, 0x1040000d,
-0x0, 0x30620040, 0x10400004, 0x3c020020,
-0x2c21024, 0x10400007, 0x0, 0x30620010,
-0x104001a9, 0x3c020040, 0x2c21024, 0x144001a6,
-0x0, 0x8f820040, 0x30420001, 0x14400008,
-0x2021, 0x8c030104, 0x24020001, 0x50620005,
-0x24040001, 0x8c020264, 0x10400003, 0x801021,
-0x24040001, 0x801021, 0x10400006, 0x0,
-0x8f42030c, 0x24420001, 0xaf42030c, 0x10000192,
-0x8f42030c, 0x8f820044, 0x34420004, 0xaf820044,
-0x8f420308, 0x24420001, 0xaf420308, 0x1000018a,
-0x8f420308, 0x30620002, 0x1040014b, 0x3c020800,
-0x8d1e001c, 0x1e5702, 0xafaa0034, 0x950a0016,
-0x3c22024, 0xafaa0024, 0x8faa0034, 0x24020001,
-0x15420006, 0x33deffff, 0x1e1140, 0x3403ecc0,
-0x431021, 0x10000010, 0x2e2a821, 0x24020002,
-0x15420005, 0x24020003, 0x1e1140, 0x24426cc0,
-0x10000009, 0x2e2a821, 0x15420005, 0x1e1180,
-0x1e1140, 0x24424cc0, 0x10000003, 0x2e2a821,
-0x571021, 0x24550ce0, 0x96a2000e, 0x304afffc,
-0x30420400, 0x10400003, 0xafaa002c, 0x100000e1,
-0x8821, 0x10800004, 0x8821, 0x97b10026,
-0x100000dd, 0xa6b10012, 0x8eb30018, 0x966a000c,
-0xa7aa003e, 0x97a5003e, 0x2ca305dd, 0x38a28870,
-0x2c420001, 0x621825, 0x10600015, 0x2021,
-0x32c20800, 0x10400015, 0x24020800, 0x96630014,
-0x14620012, 0x3402aaaa, 0x9663000e, 0x14620007,
-0x2821, 0x96630010, 0x24020300, 0x14620004,
-0xa01021, 0x96620012, 0x2c450001, 0xa01021,
-0x54400006, 0x24040016, 0x10000004, 0x0,
-0x24020800, 0x50a20001, 0x2404000e, 0x108000b9,
-0x2649021, 0x92420000, 0x3042000f, 0x28080,
-0x32c20100, 0x10400020, 0x2501821, 0x3c020020,
-0x43102b, 0x1440000e, 0x2402021, 0x2821,
-0x94820000, 0x24840002, 0xa22821, 0x83102b,
-0x1440fffb, 0x30a2ffff, 0x51c02, 0x622821,
-0x51c02, 0x30a2ffff, 0x10000009, 0x622821,
-0x8f470148, 0x8f420110, 0x102842, 0x3c060020,
-0x40f809, 0xafa80040, 0x3045ffff, 0x8fa80040,
-0x50a00001, 0x3405ffff, 0x8faa002c, 0x354a0002,
-0x10000002, 0xafaa002c, 0x2821, 0x32c20080,
-0x10400090, 0xa6a50010, 0x26430009, 0x3c02001f,
-0x3442ffff, 0x43102b, 0x10400003, 0x0,
-0x8f420148, 0x621823, 0x90660000, 0x30c200ff,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x1060007f, 0x24020800, 0x8821,
-0x97a3003e, 0x1462000f, 0x2602021, 0x96710000,
-0x96620002, 0x96630004, 0x96640006, 0x2228821,
-0x2238821, 0x2248821, 0x96620008, 0x9663000a,
-0x9664000c, 0x2228821, 0x2238821, 0x10000007,
-0x2248821, 0x94820000, 0x24840002, 0x2228821,
-0x92102b, 0x1440fffb, 0x0, 0x111c02,
-0x3222ffff, 0x628821, 0x111c02, 0x3222ffff,
-0x628821, 0x32c20200, 0x10400003, 0x26440006,
-0x1000003e, 0x8021, 0x3c05001f, 0x34a5ffff,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x30421fff, 0x10400004,
-0x2644000c, 0x96420002, 0x10000030, 0x508023,
-0x96420002, 0x26430014, 0x508023, 0x3c020020,
-0x43102b, 0x1440000a, 0xd08021, 0x9642000c,
-0x2028021, 0x9642000e, 0x96430010, 0x96440012,
-0x2028021, 0x2038021, 0x10000020, 0x2048021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x24840002, 0x2028021,
-0xa4102b, 0x10400003, 0x0, 0x8f420148,
-0x822023, 0x94820000, 0x2028021, 0x3c020100,
-0x2c21024, 0x1040000e, 0x0, 0x8faa002c,
-0x31420004, 0x1040000a, 0x0, 0x9504000e,
-0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff,
-0x2228821, 0x111c02, 0x3222ffff, 0x628821,
-0x8faa0024, 0x1518823, 0x111402, 0x2228821,
-0x2308821, 0x111402, 0x2228821, 0x3231ffff,
-0x52200001, 0x3411ffff, 0x8faa002c, 0x354a0001,
-0xafaa002c, 0xa6b10012, 0x97aa002e, 0xa6aa000e,
-0x8faa002c, 0x31420004, 0x10400002, 0x24091000,
-0x34098000, 0x8f480044, 0x8f4401a0, 0x8f4501a4,
-0xafa90010, 0x8f490044, 0x84140, 0x1001821,
-0xafa90014, 0x8f48000c, 0x2a03021, 0x24070020,
-0xafa80018, 0x8f48010c, 0x1021, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x1440000b, 0x0, 0x8f820128, 0x3c040001,
-0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124,
-0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920,
-0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044,
-0x8f430088, 0x24420001, 0x431024, 0xaf420044,
-0x8faa0034, 0x8f440368, 0x24020001, 0x15420006,
-0x24020002, 0x8f42035c, 0x2442ffff, 0xaf42035c,
-0x10000049, 0x8f42035c, 0x15420006, 0x0,
-0x8f420364, 0x2442ffff, 0xaf420364, 0x10000042,
-0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360,
-0x1000003d, 0x8f420360, 0x30621000, 0x10400005,
-0x30628000, 0x8f420078, 0x24420001, 0x10000036,
-0xaf420078, 0x10400034, 0x0, 0x8f420078,
-0x24420001, 0xaf420078, 0x8c030240, 0x43102b,
-0x1440002d, 0x24070008, 0x8f440168, 0x8f45016c,
-0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040,
-0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c,
-0x40f809, 0x24c6001c, 0x14400011, 0x24020001,
-0x3c010001, 0x370821, 0xa02240f2, 0x8f820124,
-0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c,
-0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009,
-0xc002b3b, 0x34a51300, 0x1000000b, 0x0,
-0x8f420304, 0x24420001, 0xaf420304, 0x8f420304,
-0x8f420044, 0xaf42007c, 0x3c010001, 0x370821,
-0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001,
-0xaf420318, 0x8f420318, 0x8fbf0060, 0x8fbe005c,
-0x8fb50058, 0x8fb30054, 0x8fb20050, 0x8fb1004c,
-0x8fb00048, 0x3e00008, 0x27bd0068, 0x3e00008,
-0x0, 0x0, 0x0, 0x8f42013c,
-0xaf8200c0, 0x8f42013c, 0xaf8200c4, 0x8f42013c,
-0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138,
-0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8,
-0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018,
-0xc002bbf, 0x24060008, 0x8c020204, 0xc004012,
-0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002,
-0x1040000e, 0x2021, 0x8c060248, 0x24020002,
-0x3c010001, 0xac226d98, 0xc005104, 0x24050002,
-0x2021, 0x8c060248, 0x24020001, 0x3c010001,
-0xac226d98, 0x10000011, 0x24050001, 0x8c060248,
-0x24020004, 0x3c010001, 0xac226d98, 0xc005104,
-0x24050004, 0x3c020001, 0x8c426d94, 0x30420001,
-0x10400008, 0x24020001, 0x3c010001, 0xac226d98,
-0x2021, 0x24050001, 0x3c06601b, 0xc005104,
-0x0, 0x3c040001, 0x248469d0, 0x8f420150,
-0x8f430154, 0x3c050008, 0x8f460158, 0x21640,
-0x31940, 0x34630403, 0x431025, 0x633c0,
-0x461025, 0xaf82021c, 0xafa00010, 0xafa00014,
-0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821,
-0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0,
-0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010,
-0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc,
-0xc002b3b, 0x3821, 0x8f420410, 0x24420001,
-0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c,
-0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4,
-0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010,
-0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8,
-0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821,
-0x3c044000, 0x2041024, 0x504000b4, 0x3c040100,
-0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc,
-0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823,
-0x43102b, 0x10400003, 0x0, 0x8f420148,
-0x621821, 0x10600005, 0x0, 0x8f42014c,
-0x43102b, 0x1040000b, 0x0, 0x8f8200e0,
-0x8f430124, 0xaf42011c, 0xaf430114, 0x8f820220,
-0x3c0308ff, 0x3463fffb, 0x431024, 0x100000ce,
-0x441025, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420004, 0xaf820220, 0x8f8200e0,
-0x8f430124, 0xaf42011c, 0xaf430114, 0x8f8600c8,
-0x8f840120, 0x8f830124, 0x10000005, 0x2821,
-0x14620002, 0x24620020, 0x27624800, 0x401821,
-0x1064000c, 0x30a200ff, 0x8c620018, 0x30420003,
-0x1040fff7, 0x27624fe0, 0x8f4203d0, 0x24050001,
-0x24420001, 0xaf4203d0, 0x8f4203d0, 0x8c660008,
-0x30a200ff, 0x14400058, 0x0, 0x934205c4,
-0x14400055, 0x0, 0x8f8700c4, 0x8f8800e0,
-0x8f8400e4, 0x2402fff8, 0x1024024, 0x1041023,
-0x218c3, 0x4620001, 0x24630200, 0x10600005,
-0x24020001, 0x10620009, 0x0, 0x1000001f,
-0x0, 0x8f4203c0, 0xe03021, 0x24420001,
-0xaf4203c0, 0x10000040, 0x8f4203c0, 0x8f4203c4,
-0x24420001, 0xaf4203c4, 0x8c860000, 0x8f420148,
-0x8f4303c4, 0xe61823, 0x43102b, 0x10400004,
-0x2c62233f, 0x8f420148, 0x621821, 0x2c62233f,
-0x14400031, 0x0, 0x8f42020c, 0x24420001,
-0xaf42020c, 0x8f42020c, 0xe03021, 0x24820008,
-0xaf8200e4, 0x10000028, 0xaf8200e8, 0x8f4203c8,
-0x24420001, 0xaf4203c8, 0x8f4203c8, 0x8c850000,
-0x8f420148, 0xa71823, 0x43102b, 0x10400003,
-0x0, 0x8f420148, 0x621821, 0x8f42014c,
-0x43102b, 0x5440000a, 0xa03021, 0x8f42020c,
-0x24420001, 0xaf42020c, 0x8f42020c, 0x24820008,
-0xaf8200e4, 0x8f8400e4, 0x1488ffec, 0xaf8400e8,
-0x1488000d, 0x27623000, 0x14820002, 0x2482fff8,
-0x27623ff8, 0x94430006, 0x3c02001f, 0x3442ffff,
-0xc33021, 0x46102b, 0x10400003, 0x0,
-0x8f420148, 0xc23023, 0xaf8600c8, 0x8f8300c4,
-0x8f420148, 0xc31823, 0x43102b, 0x10400003,
-0x0, 0x8f420148, 0x621821, 0x10600005,
-0x0, 0x8f42014c, 0x43102b, 0x50400008,
-0x3c02fdff, 0x8f820220, 0x3c0308ff, 0x3463fffb,
-0x431024, 0x3c034000, 0x1000003f, 0x431025,
-0x8f4303cc, 0x3442ffff, 0x282a024, 0x24630001,
-0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024,
-0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001,
-0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff,
-0x3463ffff, 0x431024, 0x441025, 0xc003daf,
-0xaf820220, 0x10000029, 0x0, 0x2111024,
-0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001,
-0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019,
-0x0, 0x2111024, 0x1040001c, 0x0,
-0x8f830224, 0x24021402, 0x14620009, 0x3c050008,
-0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014,
-0x8f860224, 0x34a50500, 0xc002b3b, 0x3821,
-0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0,
-0x8f820220, 0x2002021, 0x34420002, 0xc004e9c,
-0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x511025, 0xaf820220, 0x8fbf0020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028,
-0x3e00008, 0x0, 0x3c020001, 0x8c426da8,
-0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040,
-0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f,
-0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600,
-0x24020001, 0x3c010001, 0xac206da8, 0x3c010001,
-0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff,
-0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024,
-0xac020268, 0x8f420004, 0x3484ffff, 0x30420002,
-0x10400092, 0x284a024, 0x3c040600, 0x34842000,
-0x8f420004, 0x2821, 0x2403fffd, 0x431024,
-0xaf420004, 0xafa40020, 0x8f5e0018, 0x27aa0020,
-0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001,
-0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0,
-0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c,
-0x8c020228, 0x3c040001, 0x24846998, 0x3c050009,
-0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d,
-0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024,
-0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
-0x247003e8, 0x2021023, 0x2c4203e9, 0x1040001b,
-0x9821, 0xe08821, 0x263504c0, 0x8f440178,
-0x8f45017c, 0x2201821, 0x240a0004, 0xafaa0010,
-0xafb20014, 0x8f48000c, 0x1021, 0x2f53021,
-0xafa80018, 0x8f48010c, 0x24070008, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021,
-0x54400006, 0x24130001, 0x8f820054, 0x2021023,
-0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff,
-0x54400017, 0xaf520018, 0x8f420378, 0x24420001,
-0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c,
-0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4,
-0x3c050009, 0xafa20014, 0x8d460000, 0x10000035,
-0x34a50600, 0x8f420308, 0x24130001, 0x24420001,
-0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff,
-0x8f830054, 0x8f820054, 0x247003e8, 0x2021023,
-0x2c4203e9, 0x10400016, 0x9821, 0x3c150020,
-0x24110010, 0x8f42000c, 0x8f440160, 0x8f450164,
-0x8f860120, 0xafb10010, 0xafb20014, 0x551025,
-0xafa20018, 0x8f42010c, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440ffe3, 0x0, 0x8f820054,
-0x2021023, 0x2c4203e9, 0x1440ffee, 0x0,
-0x326200ff, 0x14400011, 0x0, 0x8f420378,
-0x24420001, 0xaf420378, 0x8f420378, 0x8f820120,
-0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001,
-0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000,
-0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec,
-0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048,
-0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038,
-0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050,
-0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d,
-0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700,
-0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b,
-0x3821, 0x3c020004, 0x2c21024, 0x10400007,
-0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420008, 0xaf820220, 0x3c050001,
-0x8ca56d98, 0x24020001, 0x14a20007, 0x2021,
-0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c,
-0x10000006, 0x3c020007, 0xc00529b, 0x2021,
-0xac020268, 0x8c030268, 0x3c020007, 0x621824,
-0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b,
-0x14400006, 0x3c020004, 0x3c020001, 0x10620009,
-0x3c020098, 0x1000000b, 0x0, 0x14620009,
-0x3c023b9a, 0x10000004, 0x3442ca00, 0x10000002,
-0x3442e100, 0x34429680, 0xaf4201fc, 0x8f4201fc,
-0xaee20064, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x0, 0x0, 0x0, 0x86102b,
-0x50400001, 0x872023, 0xc41023, 0x24843,
-0x125102b, 0x1040001b, 0x91040, 0x824021,
-0x88102b, 0x10400007, 0x1821, 0x94820000,
-0x24840002, 0x621821, 0x88102b, 0x1440fffb,
-0x0, 0x602021, 0xc73023, 0xa91023,
-0x21040, 0xc22821, 0xc5102b, 0x10400007,
-0x1821, 0x94c20000, 0x24c60002, 0x621821,
-0xc5102b, 0x1440fffb, 0x0, 0x1000000d,
-0x832021, 0x51040, 0x822821, 0x85102b,
-0x10400007, 0x1821, 0x94820000, 0x24840002,
-0x621821, 0x85102b, 0x1440fffb, 0x0,
-0x602021, 0x41c02, 0x3082ffff, 0x622021,
-0x41c02, 0x3082ffff, 0x622021, 0x3e00008,
-0x3082ffff, 0x3e00008, 0x0, 0x802821,
-0x30a20001, 0x1040002b, 0x3c03001f, 0x3463ffff,
-0x24a20004, 0x62102b, 0x54400007, 0x65102b,
-0x90a20001, 0x90a40003, 0x90a30000, 0x90a50002,
-0x1000002a, 0x441021, 0x10400003, 0x0,
-0x8f420148, 0xa22823, 0x90a40000, 0x24a50001,
-0x65102b, 0x10400003, 0x0, 0x8f420148,
-0xa22823, 0x90a20000, 0x24a50001, 0x21200,
-0x822021, 0x65102b, 0x10400003, 0x0,
-0x8f420148, 0xa22823, 0x90a20000, 0x24a50001,
-0x822021, 0x65102b, 0x10400003, 0x0,
-0x8f420148, 0xa22823, 0x90a20000, 0x1000002d,
-0x21200, 0x3463ffff, 0x24a20004, 0x62102b,
-0x5440000a, 0x65102b, 0x90a20000, 0x90a40002,
-0x90a30001, 0x90a50003, 0x441021, 0x21200,
-0x651821, 0x10000020, 0x432021, 0x10400003,
-0x0, 0x8f420148, 0xa22823, 0x90a20000,
-0x24a50001, 0x22200, 0x65102b, 0x10400003,
-0x0, 0x8f420148, 0xa22823, 0x90a20000,
-0x24a50001, 0x822021, 0x65102b, 0x10400003,
-0x0, 0x8f420148, 0xa22823, 0x90a20000,
-0x24a50001, 0x21200, 0x822021, 0x65102b,
-0x10400003, 0x0, 0x8f420148, 0xa22823,
-0x90a20000, 0x822021, 0x41c02, 0x3082ffff,
-0x622021, 0x41c02, 0x3082ffff, 0x622021,
-0x3e00008, 0x3082ffff, 0x0, 0x8f820220,
-0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8,
-0x30424000, 0x10400054, 0x24040001, 0x8f820200,
-0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd,
-0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820224, 0x1444004d, 0x42040, 0xc4102b,
-0x1040fff1, 0x0, 0x8f820200, 0x451025,
-0xaf820200, 0x8f820220, 0x34428000, 0xaf820220,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820220, 0x3c030004, 0x431024,
-0x1440000f, 0x0, 0x8f820220, 0x3c03ffff,
-0x34637fff, 0x431024, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820220, 0x3c030004, 0x431024, 0x1440000d,
-0x0, 0x8f820220, 0x34428000, 0xaf820220,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820220, 0x3c030004, 0x431024,
-0x1040001b, 0x1021, 0x8f830220, 0x24020001,
-0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700,
-0x441025, 0xaf820220, 0x8f820220, 0x2403fffd,
-0x431024, 0xaf820220, 0x8f820220, 0x3c030300,
-0x431024, 0x14400003, 0x0, 0x10000008,
-0x1021, 0x8f820220, 0x34420002, 0xaf820220,
-0x8f830220, 0x24020001, 0x641825, 0xaf830220,
-0x3e00008, 0x0, 0x2021, 0x3c050100,
-0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220,
-0x27625000, 0xaf8200c0, 0x27625000, 0xaf8200c4,
-0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0,
-0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8,
-0x27623000, 0xaf8200e0, 0x27623000, 0xaf8200e4,
-0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0,
-0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8,
-0x418c0, 0x24840001, 0x3631021, 0xac453004,
-0x3631021, 0xac403000, 0x28820200, 0x1440fff9,
-0x418c0, 0x2021, 0x418c0, 0x24840001,
-0x3631021, 0xac402804, 0x3631021, 0xac402800,
-0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c,
-0x24030080, 0x24040100, 0xac600000, 0x24630004,
-0x64102b, 0x5440fffd, 0xac600000, 0x8f830040,
-0x3c02f000, 0x621824, 0x3c025000, 0x1062000c,
-0x43102b, 0x14400006, 0x3c026000, 0x3c024000,
-0x10620008, 0x24020800, 0x10000008, 0x0,
-0x10620004, 0x24020800, 0x10000004, 0x0,
-0x24020700, 0x3c010001, 0xac226dac, 0x3e00008,
-0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0,
-0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020,
-0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e,
-0x0, 0x3c010001, 0xac206dbc, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x0,
-0xc004db9, 0x0, 0x24040001, 0x2821,
-0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc,
-0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c,
-0x24050002, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x24040001, 0x24050003, 0x3c100001,
-0x26106f26, 0xc00457c, 0x2003021, 0x97a60018,
-0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0,
-0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100,
-0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d,
-0x24036040, 0x96020000, 0x3042fff0, 0x1443000c,
-0x24020020, 0x3c030001, 0x94636f24, 0x1462000b,
-0x24027830, 0x24020003, 0x3c010001, 0xac226d94,
-0x24020005, 0x3c010001, 0x1000003f, 0xac226f34,
-0x3c030001, 0x94636f24, 0x24027830, 0x1462000c,
-0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0,
-0x14430007, 0x24020003, 0x3c010001, 0xac226d94,
-0x24020006, 0x3c010001, 0x1000002f, 0xac226f34,
-0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24,
-0x34420001, 0x3c010001, 0xac226d94, 0x24020015,
-0x1462000b, 0x0, 0x3c020001, 0x94426f26,
-0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430,
-0x2c420001, 0x621825, 0x1460001b, 0x24020003,
-0x3c030001, 0x94636f24, 0x24027810, 0x14620016,
-0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0,
-0x14400011, 0x24020002, 0x1000000f, 0x24020004,
-0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001,
-0xac226d94, 0x1000005e, 0x24020004, 0x3c020001,
-0x8c426d94, 0x34420004, 0x3c010001, 0x100000af,
-0xac226d94, 0x24020001, 0x3c010001, 0xac226f40,
-0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2,
-0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054,
-0x8f820054, 0x24030008, 0x3c010001, 0xac236d98,
-0x10000002, 0x248401f4, 0x8f820054, 0x821023,
-0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb,
-0xaf820238, 0x8f830054, 0x8f820054, 0x10000002,
-0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5,
-0x1440fffc, 0x8021, 0x24120001, 0x24110009,
-0xc004482, 0x0, 0x3c010001, 0xac326db4,
-0xc004547, 0x0, 0x3c020001, 0x8c426db4,
-0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238,
-0x8f830054, 0x8f820054, 0x10000002, 0x2463000a,
-0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc,
-0x0, 0x8f820220, 0x24040001, 0x34420002,
-0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd,
-0x621824, 0xaf830200, 0xaf840204, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x8f820224, 0x14440005, 0x34028000, 0x42040,
-0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0,
-0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004,
-0x3c010001, 0xac226d98, 0x8021, 0x24120009,
-0x3c11ffff, 0x36313f7f, 0xc004482, 0x0,
-0x24020001, 0x3c010001, 0xac226db4, 0xc004547,
-0x0, 0x3c020001, 0x8c426db4, 0x1452fffb,
-0x0, 0x8f820044, 0x511024, 0x34425080,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x2463000a, 0x8f820054, 0x621023, 0x2c42000b,
-0x1440fffc, 0x0, 0x8f820044, 0x511024,
-0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x2463000a, 0x8f820054, 0x621023,
-0x2c42000b, 0x1440fffc, 0x0, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054,
-0x621023, 0x2c420065, 0x1440fffc, 0x0,
-0x8f820220, 0x24040001, 0x34420002, 0xaf820220,
-0x8f830200, 0x24057fff, 0x2402fffd, 0x621824,
-0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054,
-0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
-0x14440005, 0x34028000, 0x42040, 0xa4102b,
-0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001,
-0x2e020064, 0x1440ffb0, 0x0, 0x3c020001,
-0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0,
-0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
-0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001,
-0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001,
-0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001,
-0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001,
-0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001,
-0xac206d98, 0x491021, 0x3c010001, 0xac226f30,
-0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c,
-0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008,
-0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98,
-0x24060004, 0x24020001, 0x14a20014, 0xafbf0010,
-0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005,
-0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005,
-0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40,
-0x348493e0, 0x24020005, 0x14620016, 0x0,
-0x3c04003d, 0x10000013, 0x34840900, 0x3c020002,
-0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e,
-0x3c030001, 0x8c636f40, 0x10000005, 0x34848480,
-0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240,
-0x24020005, 0x14620003, 0x0, 0x3c04007a,
-0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054,
-0x441021, 0x431023, 0x44102b, 0x1440004c,
-0x0, 0x3c020001, 0x8c426da0, 0x14400048,
-0x0, 0x3c010001, 0x10c00025, 0xac206db0,
-0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000,
-0x3c080002, 0x25088ffc, 0x250afffc, 0x52842,
-0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024,
-0x10400010, 0x0, 0x14a70008, 0x0,
-0x8d020000, 0x441024, 0x1040000a, 0x0,
-0x3c010001, 0x10000007, 0xac256db0, 0x8d420000,
-0x441024, 0x10400003, 0x0, 0x3c010001,
-0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b,
-0x2c420001, 0x431024, 0x5440ffe5, 0x52842,
-0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001,
-0xac226f30, 0x1060003b, 0x24020005, 0x3c030001,
-0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012,
-0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000,
-0x34635000, 0x431024, 0x14400006, 0x24020001,
-0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98,
-0x24020001, 0x3c010001, 0xac226e24, 0x3c010001,
-0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c,
-0x3c020001, 0x8c426db0, 0x1040001e, 0x0,
-0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001,
-0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001,
-0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8,
-0x24020008, 0x10620005, 0x24020001, 0xc004239,
-0x0, 0x1000000b, 0x0, 0x3c030001,
-0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002,
-0x8c638f90, 0x10620003, 0x0, 0xc004e9c,
-0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98,
-0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024,
-0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001,
-0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8,
-0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4,
-0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c,
-0x2c620003, 0x10400005, 0x24020001, 0x1062000a,
-0x0, 0x10000226, 0x0, 0x24020004,
-0x106200b6, 0x24020008, 0x1062010a, 0x24020001,
-0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff,
-0x2c620008, 0x1040021c, 0x31080, 0x3c010001,
-0x220821, 0x8c226af8, 0x400008, 0x0,
-0x3c030001, 0x8c636f40, 0x24020005, 0x14620010,
-0x0, 0x3c020001, 0x8c426da4, 0x10400008,
-0x24020003, 0xc004482, 0x0, 0x24020002,
-0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4,
-0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30,
-0xc004482, 0x0, 0x3c020001, 0x8c426da4,
-0x3c010001, 0xac206d30, 0x1440017a, 0x24020002,
-0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40,
-0x24020005, 0x14620003, 0x24020001, 0x3c010001,
-0xac226dd0, 0xc0045ff, 0x0, 0x3c030001,
-0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001,
-0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104,
-0x2021, 0x24020005, 0x3c010001, 0xac206da4,
-0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec,
-0x3c05000f, 0x34a50100, 0x3021, 0x3821,
-0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6,
-0x0, 0x8f820220, 0x3c030004, 0x431024,
-0x14400175, 0x24020007, 0x8f830054, 0x3c020001,
-0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400003, 0x24020001, 0x3c010001, 0xac226d9c,
-0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2,
-0x0, 0x8f820220, 0x30428000, 0x1040017d,
-0x0, 0x10000175, 0x0, 0x3c050001,
-0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b,
-0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0,
-0x24020001, 0x3c020008, 0x621024, 0x10400006,
-0x0, 0x8f820214, 0x3c03ffff, 0x431024,
-0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff,
-0x431024, 0x3442241f, 0xaf820214, 0x8f820220,
-0x3c030200, 0x34420002, 0xaf820220, 0x24020008,
-0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004,
-0x431024, 0x14400016, 0x0, 0x3c020002,
-0x8c428ffc, 0x30425000, 0x1040000d, 0x0,
-0x8f820220, 0x30428000, 0x10400006, 0x0,
-0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003,
-0x431024, 0x8f820220, 0x34428000, 0xaf820220,
-0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
-0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a,
-0x0, 0x3c020001, 0x94426f26, 0x24429fbc,
-0x2c420004, 0x10400004, 0x24040018, 0x24050002,
-0xc004ddb, 0x24060020, 0xc003e6d, 0x0,
-0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8,
-0x2443ffff, 0x2c620008, 0x1040016b, 0x31080,
-0x3c010001, 0x220821, 0x8c226b18, 0x400008,
-0x0, 0xc004547, 0x0, 0x3c030001,
-0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002,
-0x8c428ff8, 0x30424000, 0x10400004, 0x0,
-0x8f820044, 0x10000006, 0x3442f080, 0x8f820044,
-0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080,
-0xaf820044, 0x8f830054, 0x100000ea, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
-0x431023, 0x2c422710, 0x14400147, 0x24020005,
-0x100000d8, 0x0, 0x8f820220, 0x3c03f700,
-0x431025, 0xaf820220, 0xaf800204, 0x3c010002,
-0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001,
-0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a,
-0x14400135, 0x24020007, 0x100000d7, 0x0,
-0xc003f50, 0x0, 0x1040012d, 0x24020001,
-0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c,
-0x431024, 0x3442251f, 0xaf820214, 0x24020008,
-0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44,
-0x10400064, 0x24020001, 0x8f820220, 0x3c030008,
-0x431024, 0x1040006a, 0x3c020200, 0x10000078,
-0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007,
-0x10400115, 0x31080, 0x3c010001, 0x220821,
-0x8c226b38, 0x400008, 0x0, 0xc003daf,
-0x0, 0x3c010001, 0xac206d9c, 0xaf800204,
-0x3c010002, 0xc004482, 0xac208fe0, 0x24020001,
-0x3c010001, 0xac226db4, 0x24020002, 0x10000102,
-0xaee204b8, 0xc004547, 0x0, 0x3c030001,
-0x8c636db4, 0x10000084, 0x24020009, 0x3c020002,
-0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8,
-0x10000002, 0x344201f6, 0x344201fe, 0xaf820238,
-0x8f830054, 0x1000008b, 0x24020004, 0x8f830054,
-0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023,
-0x2c422710, 0x144000e8, 0x24020005, 0x10000079,
-0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0xaf820220, 0xaf800204, 0x3c010002, 0x10000077,
-0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28,
-0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6,
-0x24020007, 0x10000078, 0x0, 0xc003f50,
-0x0, 0x104000ce, 0x24020001, 0x8f820214,
-0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024,
-0x3442251f, 0xaf820214, 0x24020008, 0x1080000f,
-0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b,
-0x0, 0x8f820220, 0x34420002, 0xaf820220,
-0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c,
-0x8f840220, 0x10000016, 0x0, 0x8f820220,
-0x3c030008, 0x431024, 0x14400011, 0x3c020200,
-0x282a025, 0x2402000e, 0x3c010002, 0xac228f90,
-0xc00551b, 0x2021, 0x8f820220, 0x34420002,
-0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98,
-0xc00529b, 0x2021, 0x100000a3, 0x0,
-0x3c020001, 0x8c426e44, 0x1040009f, 0x0,
-0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001,
-0xac226e40, 0x14400098, 0x24020002, 0x3c010001,
-0xac206e44, 0x3c010001, 0x10000093, 0xac226e40,
-0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e,
-0x31080, 0x3c010001, 0x220821, 0x8c226b58,
-0x400008, 0x0, 0x3c020001, 0x8c426da4,
-0x10400018, 0x24020005, 0xc004482, 0x0,
-0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e,
-0xac206da4, 0xc004963, 0x0, 0x3c030001,
-0x8c636dd4, 0x24020006, 0x14620077, 0x24020003,
-0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98,
-0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021,
-0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
-0x24020006, 0xaee204b8, 0x3c010001, 0x10000062,
-0xac236f28, 0x8f820220, 0x3c030004, 0x431024,
-0x10400003, 0x24020007, 0x1000005b, 0xaee204b8,
-0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0,
-0x431023, 0x2c422710, 0x14400003, 0x24020001,
-0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8,
-0x30425000, 0x1040004c, 0x0, 0x8f820220,
-0x30428000, 0x10400007, 0x0, 0x8f820220,
-0x3c03ffff, 0x34637fff, 0x431024, 0x10000042,
-0xaf820220, 0x8f820220, 0x34428000, 0x1000003e,
-0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b,
-0x2021, 0xc00551b, 0x2021, 0x3c020002,
-0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214,
-0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214,
-0x24020008, 0xaee204b8, 0x8f820220, 0x34420002,
-0xaf820220, 0x8f820220, 0x3c030004, 0x431024,
-0x14400016, 0x0, 0x3c020002, 0x8c428ff8,
-0x30425000, 0x1040000d, 0x0, 0x8f820220,
-0x30428000, 0x10400006, 0x0, 0x8f820220,
-0x3c03ffff, 0x34637fff, 0x10000003, 0x431024,
-0x8f820220, 0x34428000, 0xaf820220, 0x8f820220,
-0x3c03f700, 0x431025, 0xaf820220, 0x3c020001,
-0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004,
-0x24040018, 0x24050002, 0xc004ddb, 0x24060020,
-0xc003e6d, 0x0, 0x10000003, 0x0,
-0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220,
-0x34420004, 0xaf820220, 0x8f820200, 0x3c050001,
-0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002,
-0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001,
-0x10a2000a, 0x0, 0x100000b1, 0x0,
-0x24020004, 0x10a20072, 0x24020008, 0x10a20085,
-0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050,
-0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40,
-0x621824, 0x3c020700, 0x621825, 0x24020e00,
-0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200,
-0xaf850220, 0x14800006, 0xaf820238, 0x8f820044,
-0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044,
-0x3c030001, 0x8c636f40, 0x24020005, 0x14620004,
-0x0, 0x8f820044, 0x34425000, 0xaf820044,
-0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40,
-0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c,
-0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001,
-0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000,
-0x621825, 0x641825, 0x1000000a, 0x34620002,
-0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac,
-0x3c040001, 0x8c846d8c, 0x431025, 0x441025,
-0x34420002, 0xaf820220, 0x1000002f, 0x24020001,
-0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff,
-0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824,
-0x3c020d00, 0x621825, 0x24020001, 0xaf830050,
-0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00,
-0x3c020001, 0x8c426d80, 0x10000004, 0x34630070,
-0x3c020001, 0x8c426d80, 0x34630072, 0x431025,
-0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700,
-0x621825, 0x3c020001, 0x8c426d90, 0x3c040001,
-0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025,
-0x441025, 0xaf820220, 0x24020005, 0x14a20006,
-0x24020001, 0x8f820044, 0x2403afff, 0x431024,
-0xaf820044, 0x24020001, 0x1000003d, 0xaf820238,
-0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001,
-0x8c846f1c, 0x621824, 0x3c020a00, 0x621825,
-0x24020001, 0xaf830050, 0xaf820200, 0x1080001e,
-0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a,
-0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a,
-0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c,
-0x3442ffff, 0x621824, 0x1080000f, 0xaf830050,
-0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00,
-0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001,
-0xaf820200, 0xaf820220, 0x641825, 0xaf830200,
-0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80,
-0x3c033f00, 0x346300e2, 0x431025, 0xaf820200,
-0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84,
-0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac,
-0x651825, 0x431025, 0x441025, 0xaf820220,
-0x3e00008, 0x0, 0x3c030001, 0x8c636db4,
-0x3c020001, 0x8c426db8, 0x10620003, 0x24020002,
-0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003,
-0x10400025, 0x24020001, 0x14620023, 0x24020004,
-0x3c030001, 0x8c636d98, 0x10620006, 0x24020008,
-0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009,
-0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044,
-0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080,
-0xaf820044, 0x8f830054, 0x24020002, 0x3c010001,
-0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c,
-0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0,
-0x431023, 0x2c422710, 0x14400003, 0x24020009,
-0x3c010001, 0xac226db4, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x27bdffd8,
-0xafb20018, 0x809021, 0xafb3001c, 0xa09821,
-0xafb10014, 0xc08821, 0xafb00010, 0x8021,
-0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x2501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x2501024, 0x24100010, 0x2701024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x2701024, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c,
-0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821,
-0xafb20018, 0xa09021, 0xafb3001c, 0xc09821,
-0xafb00010, 0x8021, 0xafbf0020, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x2301024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x2301024, 0x24100010, 0x2501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2501024, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96620000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8fbf0020,
-0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0,
-0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020,
-0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001,
-0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005,
-0x14620005, 0x2483ffff, 0xc004963, 0x0,
-0x1000034c, 0x0, 0x2c620013, 0x10400349,
-0x31080, 0x3c010001, 0x220821, 0x8c226b80,
-0x400008, 0x0, 0xc004db9, 0x8021,
-0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010,
-0x8021, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x0, 0x97a20010, 0x30428000,
-0x144002dc, 0x24020003, 0x100002d8, 0x0,
-0x24021200, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0xc004d78, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x34108000, 0x96220000, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fff8, 0x0, 0xc004db9,
-0x0, 0x8f830054, 0x10000296, 0x24020004,
-0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c,
-0x431023, 0x2c420064, 0x1440029e, 0x24020002,
-0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003,
-0x14400296, 0x24020011, 0x24020003, 0x10620005,
-0x24020004, 0x10620291, 0x2402000f, 0x1000028f,
-0x24020011, 0x1000028d, 0x24020005, 0x24020014,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020012,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020012, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8f830054,
-0x10000248, 0x24020006, 0x8f830054, 0x3c020001,
-0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400250, 0x24020007, 0x1000024c, 0x0,
-0x24020006, 0xa7a20010, 0x27b10010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020013, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020013,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x10000207, 0x24020008, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440020f, 0x24020009, 0x1000020b,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x10000193, 0x2402000a, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x1440019b, 0x2402000b, 0x10000197,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020017, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020017,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x14400127, 0x24020012, 0x10000123,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020014, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020014,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x100000ab, 0x24020013, 0x8f830054,
-0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023,
-0x2c420064, 0x144000b3, 0x2402000d, 0x100000af,
-0x0, 0x27b10010, 0xa7a00010, 0x8021,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x8f830054, 0x10000037, 0x2402000e, 0x24020840,
-0xa7a20010, 0x27b10010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020013,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020013, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8f830054,
-0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001,
-0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001,
-0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400004, 0x0, 0x24020011, 0x3c010001,
-0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98,
-0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030,
-0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002,
-0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc,
-0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c,
-0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c,
-0x2463ffff, 0x2c620006, 0x10400377, 0x31080,
-0x3c010001, 0x220821, 0x8c226bd8, 0x400008,
-0x0, 0x2021, 0x2821, 0xc004ddb,
-0x34068000, 0x24040010, 0x24050002, 0x24060002,
-0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002,
-0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018,
-0xa7a00018, 0x8021, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x32020001, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0xc004d78, 0x2021,
-0x108042, 0x1600fffc, 0x0, 0xc004db9,
-0x34108000, 0xc004db9, 0x0, 0xc004d58,
-0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7,
-0x0, 0xc004db9, 0x0, 0x97a20018,
-0x30428000, 0x14400004, 0x24020003, 0x3c010001,
-0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a,
-0xac226dd4, 0x24040010, 0x24050002, 0x24060002,
-0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001,
-0x8c636e20, 0x24020001, 0x146201e1, 0x8021,
-0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x32020001, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0x32020018, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x96220000, 0x501025,
-0xa6220000, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0x27b10018, 0xa7a00018,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010,
-0x32020018, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020018,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x96220000, 0x501025, 0xa6220000, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0x24040018, 0x2821, 0xc004ddb, 0x24060404,
-0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0x32020018, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020018, 0xc004db9, 0x34108000, 0xc004db9,
-0x0, 0xc004d58, 0x0, 0x50400005,
-0x108042, 0x97a2001a, 0x501025, 0xa7a2001a,
-0x108042, 0x1600fff7, 0x0, 0xc004db9,
-0x8021, 0xa7a0001a, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0x32020001, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0x32020018, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020018, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x97a2001a, 0x501025,
-0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x24100010, 0xc004d78, 0x2021,
-0x108042, 0x1600fffc, 0x0, 0x24100010,
-0x3202001e, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x3202001e,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x97a2001c, 0x501025, 0xa7a2001c, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x8021,
-0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0xc004d78, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0x24100010, 0x3202001e, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x97a2001c, 0x501025,
-0xa7a2001c, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0x24020002, 0xa7a2001e,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0x24100010, 0x3202001e, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x3202001e, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x34108000, 0x97a2001e, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fff8, 0x0, 0xc004db9,
-0x8021, 0xa7a00020, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0x24100010, 0x3202001e,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x3202001e, 0xc004db9,
-0x34108000, 0xc004db9, 0x0, 0xc004d58,
-0x0, 0x50400005, 0x108042, 0x97a20020,
-0x501025, 0xa7a20020, 0x108042, 0x1600fff7,
-0x0, 0xc004db9, 0x8021, 0xa7a00020,
-0xc004d78, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004d78, 0x2021,
-0xc004d78, 0x24040001, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0x24100010, 0x3202001e, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fffa,
-0x3202001e, 0xc004db9, 0x34108000, 0xc004db9,
-0x0, 0xc004d58, 0x0, 0x50400005,
-0x108042, 0x97a20020, 0x501025, 0xa7a20020,
-0x108042, 0x1600fff7, 0x0, 0xc004db9,
-0x8021, 0xa7a00022, 0xc004d78, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0xc004d78, 0x2021, 0xc004d78, 0x24040001,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004d78, 0x24040001, 0xc004d78, 0x2021,
-0x34108000, 0x97a20022, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fff8, 0x0, 0xc004db9, 0x0,
-0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
-0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d,
-0x0, 0x3c020001, 0x94426f26, 0x3c010001,
-0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c,
-0x24040009, 0x24050001, 0xc004ddb, 0x24060400,
-0x24040018, 0x24050001, 0xc004ddb, 0x24060020,
-0x24040018, 0x24050001, 0xc004ddb, 0x24062000,
-0x3c024000, 0x2421024, 0x10400123, 0x3c022000,
-0x2421024, 0x10400004, 0x0, 0x3c010001,
-0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c,
-0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9,
-0x0, 0x3c020001, 0x8c426f1c, 0x10400067,
-0x3c020004, 0x2421024, 0x10400011, 0xa7a00018,
-0x3c020008, 0x2421024, 0x10400002, 0x24020200,
-0xa7a20018, 0x3c020010, 0x2421024, 0x10400004,
-0x0, 0x97a20018, 0x34420100, 0xa7a20018,
-0x97a60018, 0x24040009, 0x10000004, 0x2821,
-0x24040009, 0x2821, 0x3021, 0xc004ddb,
-0x0, 0x24020001, 0xa7a2001a, 0x3c020008,
-0x2421024, 0x1040000c, 0x3c020002, 0x2421024,
-0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001,
-0x2421024, 0x10400005, 0x3c020010, 0x97a2001a,
-0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024,
-0x1040000e, 0x3c020002, 0x2421024, 0x10400005,
-0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a,
-0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0,
-0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0,
-0x2431024, 0x54430004, 0x3c020020, 0x97a2001a,
-0x1000000c, 0x34420400, 0x2421024, 0x50400004,
-0x3c020080, 0x97a2001a, 0x10000006, 0x34420800,
-0x2421024, 0x10400004, 0x0, 0x97a2001a,
-0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004,
-0xc004ddb, 0x2821, 0x3c020004, 0x2421024,
-0x10400004, 0xa7a0001c, 0x32425000, 0x14400004,
-0x0, 0x32424000, 0x10400005, 0x2021,
-0xc004cf9, 0x2402021, 0x10000096, 0x0,
-0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb,
-0xa7a6001c, 0x1000008f, 0x0, 0x2421024,
-0x10400004, 0xa7a00018, 0x32425000, 0x14400004,
-0x0, 0x32424000, 0x10400005, 0x3c020010,
-0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a,
-0x2421024, 0x10400004, 0x0, 0x97a20018,
-0x10000004, 0xa7a20018, 0x97a20018, 0x34420100,
-0xa7a20018, 0x3c020001, 0x2421024, 0x10400004,
-0x0, 0x97a20018, 0x10000004, 0xa7a20018,
-0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018,
-0x2021, 0xc004ddb, 0x2821, 0xa7a0001a,
-0x8021, 0xc004d78, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004d78,
-0x2021, 0xc004d78, 0x24040001, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004d78, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0xc004d78, 0x2021, 0x108042,
-0x1600fffc, 0x0, 0xc004db9, 0x34108000,
-0xc004db9, 0x0, 0xc004d58, 0x0,
-0x50400005, 0x108042, 0x97a2001a, 0x501025,
-0xa7a2001a, 0x108042, 0x1600fff7, 0x0,
-0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0xc004d78,
-0x2021, 0x108042, 0x1600fffc, 0x0,
-0xc004db9, 0x34108000, 0xc004db9, 0x0,
-0xc004d58, 0x0, 0x50400005, 0x108042,
-0x97a2001a, 0x501025, 0xa7a2001a, 0x108042,
-0x1600fff7, 0x0, 0xc004db9, 0x0,
-0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a,
-0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c,
-0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b,
-0xafa30014, 0x8f830054, 0x24020004, 0x3c010001,
-0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38,
-0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c,
-0x431023, 0x2c420064, 0x1440000f, 0x0,
-0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4,
-0x3c03f700, 0x431025, 0x10000007, 0xaf820220,
-0x24020006, 0x3c010001, 0xac226dd4, 0x24020011,
-0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030,
-0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038,
-0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c,
-0x8821, 0x32024000, 0x10400013, 0xafbf0020,
-0x3c020010, 0x2021024, 0x2c420001, 0x21023,
-0x30434100, 0x3c020001, 0x2021024, 0x14400006,
-0x34714000, 0x3c020002, 0x2021024, 0x14400002,
-0x34716000, 0x34714040, 0x2021, 0x2821,
-0x10000036, 0x2203021, 0x32021000, 0x10400035,
-0x2021, 0x2821, 0xc004ddb, 0x24060040,
-0x24040018, 0x2821, 0xc004ddb, 0x24060c00,
-0x24040017, 0x2821, 0xc004ddb, 0x24060400,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x24040017, 0x2821, 0xc004ddb, 0x24062500,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x24040017, 0x2821, 0xc004ddb, 0x24064600,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x24040017, 0x2821, 0xc004ddb, 0x24066700,
-0x24040016, 0x2821, 0xc004ddb, 0x24060006,
-0x2404001f, 0x2821, 0xc004ddb, 0x24060010,
-0x24040009, 0x2821, 0xc004ddb, 0x24061500,
-0x24040009, 0x2821, 0x24061d00, 0xc004ddb,
-0x0, 0x3c040001, 0x24846bf0, 0x3c05000e,
-0x34a50100, 0x2003021, 0x2203821, 0xafa00010,
-0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044,
-0x8f820044, 0x3c030001, 0x431025, 0x3c030008,
-0xaf820044, 0x8f840054, 0x8f820054, 0xa32824,
-0x10000002, 0x24840001, 0x8f820054, 0x821023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x3e00008, 0xa01021, 0x8f830044,
-0x3c02fff0, 0x3442ffff, 0x42480, 0x621824,
-0x3c020002, 0x822025, 0x641825, 0xaf830044,
-0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x3c030001,
-0x431025, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
-0x0, 0x8f820044, 0x2403ff7f, 0x431024,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x34420080,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x3e00008, 0x0,
-0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024,
-0xaf820044, 0x8f820044, 0x3c030001, 0x431025,
-0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe,
-0x3463ffff, 0x431024, 0xaf820044, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054,
-0x621023, 0x2c420002, 0x1440fffc, 0x0,
-0x3e00008, 0x0, 0x27bdffc8, 0xafb30024,
-0x809821, 0xafbe002c, 0xa0f021, 0xafb20020,
-0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028,
-0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010,
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96420000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x12000075,
-0x0, 0x1000fff6, 0x0, 0x3275ffff,
-0x27b10010, 0xa7a00010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x24040001, 0xc004d78,
-0x2021, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2b01024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2b01024, 0xc004db9,
-0x34108000, 0xc004db9, 0x0, 0xc004d58,
-0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7,
-0x0, 0xc004db9, 0x0, 0x33c5ffff,
-0x24020001, 0x54a20004, 0x24020002, 0x97a20010,
-0x10000006, 0x521025, 0x14a20006, 0x3271ffff,
-0x97a20010, 0x121827, 0x431024, 0xa7a20010,
-0x3271ffff, 0x27b20010, 0x8021, 0xc004d78,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0xc004d78,
-0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004d78, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x2301024,
-0x10400002, 0x2021, 0x24040001, 0xc004d78,
-0x108042, 0x1600fffa, 0x2301024, 0xc004d78,
-0x24040001, 0xc004d78, 0x2021, 0x34108000,
-0x96420000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004d78, 0x108042, 0x1600fff8,
-0x0, 0xc004db9, 0x0, 0x8fbf0030,
-0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020,
-0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
-0x0, 0x0, 0x0, 0x27bdffe8,
-0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0,
-0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
-0x0, 0xc003daf, 0x8f840224, 0x100001d8,
-0x0, 0x8f820220, 0x3c030008, 0x431024,
-0x10400026, 0x24020001, 0x8f840224, 0x8f820220,
-0x3c030400, 0x431024, 0x10400006, 0x0,
-0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b,
-0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000,
-0x24420001, 0xac620000, 0x2c420002, 0x14400003,
-0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002,
-0x8c428fc0, 0x10400006, 0x30820040, 0x10400004,
-0x24020001, 0x3c010002, 0x10000003, 0xac228fc4,
-0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c,
-0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002,
-0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002,
-0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002,
-0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002,
-0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002,
-0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194,
-0x31080, 0x3c010001, 0x220821, 0x8c226c00,
-0x400008, 0x0, 0x24020002, 0x3c010002,
-0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002,
-0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002,
-0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224,
-0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0,
-0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf,
-0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd,
-0x431024, 0xaf820200, 0x3c010002, 0xac208fe0,
-0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001,
-0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002,
-0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4,
-0x14400006, 0x24020003, 0x3c010001, 0xac246d9c,
-0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002,
-0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002,
-0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400003, 0x24020004, 0x3c010002, 0xac228f90,
-0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff,
-0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001,
-0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8,
-0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002,
-0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204,
-0x3463ffff, 0x30420030, 0x1440012f, 0x283a024,
-0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002,
-0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0,
-0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff,
-0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001,
-0xac226e3c, 0x2c420002, 0x14400125, 0x24020001,
-0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c,
-0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002,
-0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024,
-0x3c020002, 0x8c428f9c, 0x10400115, 0x0,
-0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002,
-0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002,
-0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204,
-0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002,
-0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0,
-0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
-0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002,
-0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
-0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4,
-0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c,
-0x3c030002, 0x8c638fc8, 0x441024, 0x641824,
-0x10430004, 0x24020001, 0x3c010002, 0x100000e4,
-0xac228f90, 0x24020003, 0xaca20000, 0x24020008,
-0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc,
-0x1040000c, 0x24020001, 0x3c040002, 0xc005091,
-0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005,
-0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006,
-0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002,
-0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0,
-0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0,
-0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002,
-0xac238fac, 0x8f830054, 0x24020009, 0x3c010002,
-0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4,
-0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0,
-0x431023, 0x2c422710, 0x1440009f, 0x0,
-0x3c020002, 0x8c428fc0, 0x10400005, 0x0,
-0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002,
-0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21,
-0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc,
-0x1040000e, 0x0, 0x3c020002, 0x8c428f9c,
-0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f,
-0x2402000c, 0x8f820204, 0x30420080, 0x1440000c,
-0x24020003, 0x10000029, 0x2402000c, 0x3c020002,
-0x8c428f9c, 0x30420080, 0x14400005, 0x24020003,
-0x8f820204, 0x30420080, 0x1040001f, 0x24020003,
-0xac620000, 0x2402000a, 0x3c010002, 0xac228f90,
-0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002,
-0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000,
-0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002,
-0xac228f90, 0x641825, 0x3c010002, 0xac238fe0,
-0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21,
-0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0,
-0x10400005, 0x0, 0x2402000c, 0x3c010002,
-0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0,
-0x10400063, 0x0, 0x3c040002, 0x8c848f9c,
-0x10800055, 0x30820008, 0x3c030002, 0x8c638fac,
-0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8,
-0xaca20000, 0x24020006, 0x3c010002, 0x10000054,
-0xac228f90, 0x8f820200, 0x34420002, 0xaf820200,
-0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90,
-0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002,
-0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710,
-0x14400031, 0x0, 0x3c020002, 0x8c428fd0,
-0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4,
-0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d,
-0x0, 0x3c050001, 0x8ca56d98, 0xc00529b,
-0x2021, 0x3c030001, 0x8c636d98, 0x24020004,
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94,
-0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94,
-0x431024, 0x3c010001, 0xac226d94, 0x8f830224,
-0x3c020200, 0x3c010002, 0xac238fec, 0x10000020,
-0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005,
-0x0, 0x3c020002, 0x8c428f9c, 0x1040000f,
-0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21,
-0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0,
-0x1040000f, 0x0, 0x3c020002, 0x8c428f9c,
-0x1440000b, 0x0, 0x24020002, 0x3c010002,
-0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0,
-0x10400003, 0x0, 0xc003daf, 0x0,
-0x8f820220, 0x3c03f700, 0x431025, 0xaf820220,
-0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002,
-0x24638fe8, 0x8c620000, 0x10400005, 0x34422000,
-0x3c010002, 0xac228fdc, 0x10000003, 0xac600000,
-0x3c010002, 0xac248fdc, 0x3e00008, 0x0,
-0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002,
-0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e,
-0x821024, 0x14400061, 0x24020030, 0x30822000,
-0x1040005d, 0x30838000, 0x31a02, 0x30820001,
-0x21200, 0x3c040001, 0x8c846f20, 0x621825,
-0x331c2, 0x3c030001, 0x24636e48, 0x30828000,
-0x21202, 0x30840001, 0x42200, 0x441025,
-0x239c2, 0x61080, 0x431021, 0x471021,
-0x90430000, 0x24020001, 0x10620025, 0x0,
-0x10600007, 0x24020002, 0x10620013, 0x24020003,
-0x1062002c, 0x3c05000f, 0x10000037, 0x0,
-0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820220, 0x3c010002, 0xac209004, 0x3c010002,
-0x10000034, 0xac20900c, 0x8f820200, 0x34420100,
-0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff,
-0x431024, 0xaf820220, 0x24020100, 0x3c010002,
-0xac229004, 0x3c010002, 0x10000026, 0xac20900c,
-0x8f820200, 0x2403feff, 0x431024, 0xaf820200,
-0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
-0x3c010002, 0xac209004, 0x3c010002, 0x10000019,
-0xac23900c, 0x8f820200, 0x34420100, 0xaf820200,
-0x8f820220, 0x3c030001, 0x431025, 0xaf820220,
-0x24020100, 0x3c010002, 0xac229004, 0x3c010002,
-0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001,
-0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014,
-0x10000004, 0x0, 0x24020030, 0x3c010002,
-0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x0, 0x0, 0x0, 0x27bdffc8,
-0xafb20028, 0x809021, 0xafb3002c, 0xa09821,
-0xafb00020, 0xc08021, 0x3c040001, 0x24846c50,
-0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001,
-0x2403021, 0x2603821, 0xafbf0030, 0xafb10024,
-0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010,
-0x24020002, 0x12620083, 0x2e620003, 0x10400005,
-0x24020001, 0x1262000a, 0x0, 0x10000173,
-0x0, 0x24020004, 0x126200f8, 0x24020008,
-0x126200f7, 0x3c02ffec, 0x1000016c, 0x0,
-0x3c020001, 0x8c426d94, 0x30420002, 0x14400004,
-0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024,
-0x3c010002, 0x310821, 0xac308ffc, 0x3c024000,
-0x2021024, 0x1040004e, 0x1023c2, 0x30840030,
-0x101382, 0x3042001c, 0x3c030001, 0x24636dd8,
-0x431021, 0x823821, 0x3c020020, 0x2021024,
-0x10400006, 0x24020100, 0x3c010002, 0x310821,
-0xac229000, 0x10000005, 0x3c020080, 0x3c010002,
-0x310821, 0xac209000, 0x3c020080, 0x2021024,
-0x10400006, 0x121940, 0x3c020001, 0x3c010002,
-0x230821, 0x10000005, 0xac229008, 0x121140,
-0x3c010002, 0x220821, 0xac209008, 0x94e40000,
-0x3c030001, 0x8c636f40, 0x24020005, 0x10620010,
-0xa7a40018, 0x32024000, 0x10400002, 0x34824000,
-0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
-0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002,
-0x24040001, 0x2821, 0xc0045be, 0x27a60018,
-0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001,
-0xac316da4, 0x14530004, 0x32028000, 0xc003daf,
-0x0, 0x32028000, 0x1040011c, 0x0,
-0xc003daf, 0x0, 0x3c030001, 0x8c636f40,
-0x24020005, 0x10620115, 0x24020002, 0x3c010001,
-0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98,
-0x24040001, 0x24050004, 0x27b0001a, 0xc0045be,
-0x2003021, 0x24040001, 0x2821, 0xc0045be,
-0x2003021, 0x3c020002, 0x511021, 0x8c428ff4,
-0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff,
-0x3c010001, 0xac336da4, 0x431024, 0x3c010002,
-0x310821, 0x109300f7, 0xac228ff4, 0x100000f7,
-0x0, 0x3c022000, 0x2021024, 0x10400005,
-0x24020001, 0x3c010001, 0xac226f1c, 0x10000004,
-0x128940, 0x3c010001, 0xac206f1c, 0x128940,
-0x3c010002, 0x310821, 0xac308ff8, 0x3c024000,
-0x2021024, 0x14400014, 0x0, 0x3c020001,
-0x8c426f1c, 0x10400006, 0x24040004, 0x24050001,
-0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8,
-0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff,
-0x3463ffff, 0x431024, 0x3c010002, 0x310821,
-0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c,
-0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d,
-0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100,
-0x3c010002, 0x310821, 0xac239004, 0x3c030001,
-0x3c010002, 0x310821, 0xac23900c, 0x10000015,
-0x34420400, 0x2021024, 0x10400008, 0x24030100,
-0x3c020001, 0x8c426f20, 0x3c010002, 0x310821,
-0xac239004, 0x1000000b, 0x34420800, 0x3c020080,
-0x2021024, 0x1040002e, 0x3c030001, 0x3c020001,
-0x8c426f20, 0x3c010002, 0x310821, 0xac23900c,
-0x34420c00, 0x3c010001, 0xac226f20, 0x10000025,
-0x24040001, 0x3c020020, 0x2021024, 0x10400006,
-0x24020100, 0x3c010002, 0x310821, 0xac229004,
-0x10000005, 0x3c020080, 0x3c010002, 0x310821,
-0xac209004, 0x3c020080, 0x2021024, 0x10400007,
-0x121940, 0x3c020001, 0x3c010002, 0x230821,
-0xac22900c, 0x10000006, 0x24040001, 0x121140,
-0x3c010002, 0x220821, 0xac20900c, 0x24040001,
-0x2821, 0x27b0001e, 0xc00457c, 0x2003021,
-0x24040001, 0x2821, 0xc00457c, 0x2003021,
-0x24040001, 0x24050001, 0x27b0001c, 0xc00457c,
-0x2003021, 0x24040001, 0x24050001, 0xc00457c,
-0x2003021, 0x10000077, 0x0, 0x3c02ffec,
-0x3442ffff, 0x2028024, 0x3c020008, 0x2028025,
-0x121140, 0x3c010002, 0x220821, 0xac308ff8,
-0x3c022000, 0x2021024, 0x10400009, 0x0,
-0x3c020001, 0x8c426e44, 0x14400005, 0x24020001,
-0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000,
-0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024,
-0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c,
-0xaf820238, 0x3c010001, 0xac206db0, 0x10600005,
-0x24022020, 0x3c010001, 0xac226f20, 0x24020001,
-0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002,
-0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98,
-0x3484ffff, 0x441024, 0x3c010002, 0x230821,
-0xac228ff0, 0x24020001, 0x10a20044, 0x0,
-0x10000040, 0x0, 0x3c020001, 0x8c426f1c,
-0x1040001c, 0x24022000, 0x3c010001, 0xac226f20,
-0x3c0300a0, 0x2031024, 0x14430005, 0x121140,
-0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20,
-0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020,
-0x621024, 0x10400004, 0x24022001, 0x3c010001,
-0x10000023, 0xac226f20, 0x3c020080, 0x621024,
-0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c,
-0xac226f20, 0x3c020020, 0x2021024, 0x10400007,
-0x121940, 0x24020100, 0x3c010002, 0x230821,
-0xac229004, 0x10000006, 0x3c020080, 0x121140,
-0x3c010002, 0x220821, 0xac209004, 0x3c020080,
-0x2021024, 0x10400006, 0x121940, 0x3c020001,
-0x3c010002, 0x230821, 0x10000005, 0xac22900c,
-0x121140, 0x3c010002, 0x220821, 0xac20900c,
-0x3c030001, 0x8c636d98, 0x24020001, 0x10620003,
-0x0, 0xc003daf, 0x0, 0x8fbf0030,
-0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c,
-0x9821, 0xafb50040, 0xa821, 0xafb10034,
-0x8821, 0x24020002, 0xafbf0048, 0xafbe0044,
-0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a,
-0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022,
-0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005,
-0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d,
-0x2201021, 0x24020004, 0x10a2020a, 0x24020008,
-0x10a20208, 0x2201021, 0x10000256, 0x0,
-0x8fa8002c, 0x88140, 0x3c030002, 0x701821,
-0x8c638ffc, 0x621024, 0x14400009, 0x24040001,
-0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002,
-0x300821, 0xac318ff4, 0x10000246, 0x2201021,
-0x24050001, 0xc00457c, 0x27a60018, 0x24040001,
-0x24050001, 0xc00457c, 0x27a60018, 0x97a20018,
-0x30420004, 0x104000d9, 0x3c114000, 0x3c020001,
-0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9,
-0x31080, 0x3c010001, 0x220821, 0x8c226c68,
-0x400008, 0x0, 0x24040001, 0x24050011,
-0x27b0001a, 0xc00457c, 0x2003021, 0x24040001,
-0x24050011, 0xc00457c, 0x2003021, 0x97a3001a,
-0x30624000, 0x10400002, 0x3c150010, 0x3c150008,
-0x30628000, 0x104000aa, 0x3c130001, 0x100000a8,
-0x3c130002, 0x24040001, 0x24050014, 0x27b0001a,
-0xc00457c, 0x2003021, 0x24040001, 0x24050014,
-0xc00457c, 0x2003021, 0x97a3001a, 0x30621000,
-0x10400002, 0x3c150010, 0x3c150008, 0x30620800,
-0x10400097, 0x3c130001, 0x10000095, 0x3c130002,
-0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
-0x2003021, 0x24040001, 0x24050019, 0xc00457c,
-0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
-0x10620027, 0x28620401, 0x1040000e, 0x24020200,
-0x1062001f, 0x28620201, 0x10400005, 0x24020100,
-0x5062001e, 0x3c130001, 0x1000001e, 0x24040001,
-0x24020300, 0x50620019, 0x3c130002, 0x10000019,
-0x24040001, 0x24020600, 0x1062000d, 0x28620601,
-0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
-0x10000010, 0x24040001, 0x24020700, 0x1462000d,
-0x24040001, 0x3c130004, 0x1000000a, 0x3c150008,
-0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
-0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
-0x24040001, 0x24050018, 0x27b0001e, 0xc00457c,
-0x2003021, 0x24040001, 0x24050018, 0xc00457c,
-0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140,
-0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022,
-0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010,
-0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b,
-0xafa20014, 0x3c020004, 0x16620010, 0x3c020001,
-0x8f840054, 0x24030001, 0x24020002, 0x3c010001,
-0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001,
-0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001,
-0xac246f30, 0x1000004f, 0x2b38825, 0x16620039,
-0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e,
-0x24040018, 0x2021, 0x2821, 0xc004ddb,
-0x34068000, 0x8f830054, 0x8f820054, 0x2b38825,
-0x10000002, 0x24630032, 0x8f820054, 0x621023,
-0x2c420033, 0x1440fffc, 0x0, 0x8f830054,
-0x24020001, 0x3c010001, 0xac226e20, 0x3c010001,
-0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001,
-0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001,
-0x1000002c, 0xac236f30, 0x2821, 0xc004ddb,
-0x24060404, 0x2021, 0x2405001e, 0x27a60018,
-0x24020002, 0xc0045be, 0xa7a20018, 0x2021,
-0x2821, 0x27a60018, 0xc0045be, 0xa7a00018,
-0x24040018, 0x24050002, 0xc004ddb, 0x24060004,
-0x3c028000, 0x2221025, 0x2b31825, 0x10000015,
-0x438825, 0x2221025, 0x2751825, 0x438825,
-0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98,
-0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b,
-0xafb10014, 0x10000007, 0x0, 0x3c110002,
-0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff,
-0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e,
-0x0, 0x3c020001, 0x8c426f1c, 0x10400002,
-0x3c022000, 0x2228825, 0x8fa8002c, 0x81140,
-0x3c010002, 0x220821, 0x8c229000, 0x10400003,
-0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf,
-0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
-0x3c010002, 0x220821, 0x8c229008, 0x10400003,
-0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f,
-0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140,
-0x3c010002, 0x220821, 0xac318ff4, 0x10000135,
-0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002,
-0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024,
-0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff,
-0x628824, 0x3c010002, 0x3e0821, 0xac318ff0,
-0x10000124, 0x2201021, 0x2821, 0xc00457c,
-0x27a60018, 0x24040001, 0x2821, 0xc00457c,
-0x27a60018, 0x24040001, 0x24050001, 0x27b20020,
-0xc00457c, 0x2403021, 0x24040001, 0x24050001,
-0xc00457c, 0x2403021, 0x24040001, 0x24050004,
-0x27b1001e, 0xc00457c, 0x2203021, 0x24040001,
-0x24050004, 0xc00457c, 0x2203021, 0x24040001,
-0x24050005, 0x27b00022, 0xc00457c, 0x2003021,
-0x24040001, 0x24050005, 0xc00457c, 0x2003021,
-0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
-0x24040001, 0x24050010, 0xc00457c, 0x27a60018,
-0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
-0x24040001, 0x2405000a, 0xc00457c, 0x2403021,
-0x24040001, 0x24050018, 0xc00457c, 0x2203021,
-0x24040001, 0x24050018, 0xc00457c, 0x2203021,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x24040001, 0x24050001, 0xc00457c, 0x27a60018,
-0x97a20018, 0x30420004, 0x10400066, 0x3c114000,
-0x3c030001, 0x8c636f34, 0x24020005, 0x14620067,
-0x24040001, 0x24050019, 0x27b0001c, 0xc00457c,
-0x2003021, 0x24040001, 0x24050019, 0xc00457c,
-0x2003021, 0x97a2001c, 0x30430700, 0x24020400,
-0x10620027, 0x28620401, 0x1040000e, 0x24020200,
-0x1062001f, 0x28620201, 0x10400005, 0x24020100,
-0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004,
-0x24020300, 0x50620019, 0x3c130002, 0x10000019,
-0x3c020004, 0x24020600, 0x1062000d, 0x28620601,
-0x10400005, 0x24020500, 0x5062000b, 0x3c130002,
-0x10000010, 0x3c020004, 0x24020700, 0x1462000d,
-0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008,
-0x10000006, 0x3c130004, 0x10000005, 0x3c150008,
-0x3c130001, 0x10000002, 0x3c150008, 0x3c150010,
-0x3c020004, 0x12620017, 0x3c028000, 0x8f820054,
-0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001,
-0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001,
-0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001,
-0x16620022, 0x2758825, 0x2021, 0x2821,
-0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b,
-0xac306e20, 0x2221025, 0x2b31825, 0x438825,
-0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001,
-0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010,
-0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001,
-0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007,
-0x0, 0x3c110002, 0x23e8821, 0x8e318ff0,
-0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001,
-0x8c426da8, 0x10400069, 0x0, 0x3c020001,
-0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825,
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
-0x8c229004, 0x10400003, 0x3c020020, 0x10000005,
-0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
-0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f,
-0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b,
-0x2228824, 0x8fa8002c, 0x82940, 0x3c030002,
-0x651821, 0x8c638ff8, 0x3c024000, 0x621024,
-0x14400008, 0x3c027fff, 0x3442ffff, 0x628824,
-0x3c010002, 0x250821, 0xac318ff0, 0x10000041,
-0x2201021, 0x3c020001, 0x8c426da8, 0x10400034,
-0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c,
-0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b,
-0x21023, 0x441024, 0x10600003, 0x518825,
-0x3c022000, 0x2228825, 0x3c020002, 0x451021,
-0x8c429004, 0x10400003, 0x3c020020, 0x10000004,
-0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x8fa8002c, 0x81140, 0x3c010002, 0x220821,
-0x8c22900c, 0x10400003, 0x3c020080, 0x10000004,
-0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824,
-0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800,
-0x2228825, 0x3c020001, 0x8c426e34, 0x10400002,
-0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38,
-0x10400006, 0x3c020100, 0x10000004, 0x2228825,
-0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c,
-0x81140, 0x3c010002, 0x220821, 0xac318ff0,
-0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
-0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028,
-0x809021, 0xafbf002c, 0xafb10024, 0xafb00020,
-0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220,
-0x24020002, 0x1202005c, 0x2e020003, 0x10400005,
-0x24020001, 0x1202000a, 0x121940, 0x1000010c,
-0x0, 0x24020004, 0x120200bf, 0x24020008,
-0x120200be, 0x128940, 0x10000105, 0x0,
-0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002,
-0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024,
-0x10400038, 0x3c020008, 0x2021024, 0x10400020,
-0x34840002, 0x3c020002, 0x431021, 0x8c429000,
-0x10400005, 0x34840020, 0x34840100, 0x3c020020,
-0x10000006, 0x2028025, 0x2402feff, 0x822024,
-0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140,
-0x3c010002, 0x220821, 0x8c229008, 0x10400005,
-0x3c020001, 0xc23025, 0x3c020080, 0x10000016,
-0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024,
-0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024,
-0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff,
-0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024,
-0x3c010002, 0x230821, 0xac209000, 0x3c010002,
-0x230821, 0xac209008, 0xaf840200, 0xaf860220,
-0x8f820220, 0x34420002, 0xaf820220, 0x1000000a,
-0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200,
-0x2028024, 0x2402fffd, 0x621824, 0xc003daf,
-0xaf830200, 0x121140, 0x3c010002, 0x220821,
-0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c,
-0x10400069, 0x24050004, 0x24040001, 0xc00457c,
-0x27a60018, 0x24040001, 0x24050005, 0xc00457c,
-0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001,
-0x24846e48, 0x30630c00, 0x31a82, 0x30420c00,
-0x21282, 0xa7a2001a, 0x21080, 0x441021,
-0x431021, 0xa7a30018, 0x90480000, 0x24020001,
-0x3103ffff, 0x10620029, 0x28620002, 0x10400005,
-0x0, 0x10600009, 0x0, 0x1000003d,
-0x0, 0x10700013, 0x24020003, 0x1062002c,
-0x0, 0x10000037, 0x0, 0x8f820200,
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
-0x3c010002, 0xac209004, 0x3c010002, 0x10000032,
-0xac20900c, 0x8f820200, 0x34420100, 0xaf820200,
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
-0xaf820220, 0x24020100, 0x3c010002, 0xac229004,
-0x3c010002, 0x10000024, 0xac20900c, 0x8f820200,
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
-0x3c030001, 0x431025, 0xaf820220, 0x3c010002,
-0xac209004, 0x3c010002, 0x10000017, 0xac23900c,
-0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
-0x3c030001, 0x431025, 0xaf820220, 0x24020100,
-0x3c010002, 0xac229004, 0x3c010002, 0x1000000a,
-0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a,
-0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010,
-0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002,
-0x1000004b, 0xaf820200, 0x128940, 0x3c050002,
-0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021,
-0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010,
-0x0, 0x3c020001, 0x8c426f1c, 0x14400005,
-0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200,
-0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024,
-0x3c010002, 0x310821, 0x10000031, 0xac308ff0,
-0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020,
-0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020,
-0xa21024, 0x10400007, 0x34840020, 0x24020100,
-0x3c010002, 0x310821, 0xac229004, 0x10000006,
-0x34840100, 0x3c010002, 0x310821, 0xac209004,
-0x2402feff, 0x822024, 0x3c020080, 0xa21024,
-0x10400007, 0x121940, 0x3c020001, 0x3c010002,
-0x230821, 0xac22900c, 0x10000008, 0xc23025,
-0x121140, 0x3c010002, 0x220821, 0xac20900c,
-0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200,
-0xaf860220, 0x8f820220, 0x34420002, 0xaf820220,
-0x121140, 0x3c010002, 0x220821, 0xac308ff0,
-0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
-0x3e00008, 0x27bd0030, 0x0, 0x1821,
-0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007,
-0x30420001, 0x10400004, 0x0, 0x8f820044,
-0x10000003, 0x34420040, 0x8f820044, 0x461024,
-0xaf820044, 0x8f820044, 0x34420020, 0xaf820044,
-0x8f820044, 0x451024, 0xaf820044, 0x24630001,
-0x28620008, 0x5440ffee, 0x641007, 0x3e00008,
-0x0, 0x2c820008, 0x1040001b, 0x0,
-0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001,
-0x24426e60, 0x621821, 0x24640004, 0x90620000,
-0x10400004, 0x0, 0x8f820044, 0x10000003,
-0x34420040, 0x8f820044, 0x461024, 0xaf820044,
-0x8f820044, 0x34420020, 0xaf820044, 0x8f820044,
-0x451024, 0xaf820044, 0x24630001, 0x64102b,
-0x1440ffee, 0x0, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x8f8400c4,
-0x8f8600e0, 0x8f8700e4, 0x2402fff8, 0xc22824,
-0x10e5001a, 0x27623ff8, 0x14e20002, 0x24e80008,
-0x27683000, 0x55050004, 0x8d0a0000, 0x30c20004,
-0x14400012, 0x805021, 0x8ce90000, 0x8f42013c,
-0x1494823, 0x49182b, 0x94eb0006, 0x10600002,
-0x25630050, 0x494821, 0x123182b, 0x50400003,
-0x8f4201fc, 0x3e00008, 0xe01021, 0xaf8800e8,
-0x24420001, 0xaf4201fc, 0xaf8800e4, 0x3e00008,
-0x1021, 0x3e00008, 0x0, 0x8f8300e4,
-0x27623ff8, 0x10620004, 0x24620008, 0xaf8200e8,
-0x3e00008, 0xaf8200e4, 0x27623000, 0xaf8200e8,
-0x3e00008, 0xaf8200e4, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x8f880120,
-0x27624fe0, 0x8f830128, 0x15020002, 0x25090020,
-0x27694800, 0x11230012, 0x8fa20010, 0xad040000,
-0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
-0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
-0xad020010, 0xad030014, 0xaf890120, 0x8f4300fc,
-0x24020001, 0x2463ffff, 0x3e00008, 0xaf4300fc,
-0x8f430324, 0x1021, 0x24630001, 0x3e00008,
-0xaf430324, 0x3e00008, 0x0, 0x8f880100,
-0x276247e0, 0x8f830108, 0x15020002, 0x25090020,
-0x27694000, 0x1123000f, 0x8fa20010, 0xad040000,
-0xad050004, 0xad060008, 0xa507000e, 0x8fa30014,
-0xad020018, 0x8fa20018, 0xad03001c, 0x25030016,
-0xad020010, 0xad030014, 0xaf890100, 0x3e00008,
-0x24020001, 0x8f430328, 0x1021, 0x24630001,
-0x3e00008, 0xaf430328, 0x3e00008, 0x0,
-0x0, 0x0, 0x0, 0x0 };
-static u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __devinitdata = {
-0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6677, 0x6d61696e, 0x2e632c76, 0x20312e31,
-0x2e322e34, 0x35203139, 0x39392f30, 0x312f3234,
-0x2030303a, 0x31303a35, 0x35207368, 0x75616e67,
-0x20457870, 0x20240000, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x6261644d, 0x656d537a,
-0x0, 0x68775665, 0x72000000, 0x62616448,
-0x77566572, 0x0, 0x2a2a4441, 0x574e5f41,
-0x0, 0x74785278, 0x4266537a, 0x0,
-0x62664174, 0x6e4d726b, 0x0, 0x7265645a,
-0x6f6e6531, 0x0, 0x70636943, 0x6f6e6600,
-0x67656e43, 0x6f6e6600, 0x2a646d61, 0x5244666c,
-0x0, 0x2a50414e, 0x49432a00, 0x2e2e2f2e,
-0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 0x72632f6e,
-0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f6677,
-0x6d61696e, 0x2e630000, 0x72636246, 0x6c616773,
-0x0, 0x62616452, 0x78526362, 0x0,
-0x676c6f62, 0x466c6773, 0x0, 0x2b5f6469,
-0x73705f6c, 0x6f6f7000, 0x2b65765f, 0x68616e64,
-0x6c657200, 0x63616e74, 0x31446d61, 0x0,
-0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x635f636b,
-0x73756d00, 0x2b685f73, 0x656e645f, 0x64617461,
-0x5f726561, 0x64795f63, 0x6b73756d, 0x0,
-0x2b685f64, 0x6d615f72, 0x645f6173, 0x73697374,
-0x5f636b73, 0x756d0000, 0x74436b73, 0x6d4f6e00,
-0x2b715f64, 0x6d615f74, 0x6f5f6e69, 0x63000000,
-0x2b685f73, 0x656e645f, 0x64617461, 0x5f726561,
-0x64790000, 0x2b685f64, 0x6d615f72, 0x645f6173,
-0x73697374, 0x0, 0x74436b73, 0x6d4f6666,
-0x0, 0x2b685f73, 0x656e645f, 0x62645f72,
-0x65616479, 0x0, 0x68737453, 0x52696e67,
-0x0, 0x62616453, 0x52696e67, 0x0,
-0x6e696353, 0x52696e67, 0x0, 0x77446d61,
-0x416c6c41, 0x0, 0x2b715f64, 0x6d615f74,
-0x6f5f686f, 0x73745f63, 0x6b73756d, 0x0,
-0x2b685f6d, 0x61635f72, 0x785f636f, 0x6d705f63,
-0x6b73756d, 0x0, 0x2b685f64, 0x6d615f77,
-0x725f6173, 0x73697374, 0x5f636b73, 0x756d0000,
-0x72436b73, 0x6d4f6e00, 0x2b715f64, 0x6d615f74,
-0x6f5f686f, 0x73740000, 0x2b685f6d, 0x61635f72,
-0x785f636f, 0x6d700000, 0x2b685f64, 0x6d615f77,
-0x725f6173, 0x73697374, 0x0, 0x72436b73,
-0x6d4f6666, 0x0, 0x2b685f72, 0x6563765f,
-0x62645f72, 0x65616479, 0x0, 0x2b685f72,
-0x6563765f, 0x6a756d62, 0x6f5f6264, 0x5f726561,
-0x64790000, 0x2b685f72, 0x6563765f, 0x6d696e69,
-0x5f62645f, 0x72656164, 0x79000000, 0x2b6d685f,
-0x636f6d6d, 0x616e6400, 0x2b685f74, 0x696d6572,
-0x0, 0x2b685f64, 0x6f5f7570, 0x64617465,
-0x5f74785f, 0x636f6e73, 0x0, 0x2b685f64,
-0x6f5f7570, 0x64617465, 0x5f72785f, 0x70726f64,
-0x0, 0x2b636b73, 0x756d3136, 0x0,
-0x2b706565, 0x6b5f6d61, 0x635f7278, 0x5f776100,
-0x2b706565, 0x6b5f6d61, 0x635f7278, 0x0,
-0x2b646571, 0x5f6d6163, 0x5f727800, 0x2b685f6d,
-0x61635f72, 0x785f6174, 0x746e0000, 0x62616452,
-0x6574537a, 0x0, 0x72784264, 0x4266537a,
-0x0, 0x2b6e756c, 0x6c5f6861, 0x6e646c65,
-0x72000000, 0x66774f70, 0x4661696c, 0x0,
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64340000,
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64360000,
-0x2b685f75, 0x70646174, 0x655f6c65, 0x64320000,
-0x696e7453, 0x74617465, 0x0, 0x2a2a696e,
-0x69744370, 0x0, 0x23736372, 0x65616d00,
-0x69537461, 0x636b4572, 0x0, 0x70726f62,
-0x654d656d, 0x0, 0x2a2a4441, 0x574e5f42,
-0x0, 0x2b73775f, 0x646d615f, 0x61737369,
-0x73745f70, 0x6c75735f, 0x74696d65, 0x72000000,
-0x2b267072, 0x656c6f61, 0x645f7772, 0x5f646573,
-0x63720000, 0x2b267072, 0x656c6f61, 0x645f7264,
-0x5f646573, 0x63720000, 0x2b685f68, 0x665f7469,
-0x6d657200, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7469, 0x6d65722e, 0x632c7620, 0x312e312e,
-0x322e3335, 0x20313939, 0x392f3031, 0x2f323720,
-0x31393a30, 0x393a3530, 0x20686179, 0x65732045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x542d446d, 0x61526432,
-0x0, 0x542d446d, 0x61526431, 0x0,
-0x542d446d, 0x61526442, 0x0, 0x542d446d,
-0x61577232, 0x0, 0x542d446d, 0x61577231,
-0x0, 0x542d446d, 0x61577242, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f636f, 0x6d6d616e, 0x642e632c, 0x7620312e,
-0x312e322e, 0x32382031, 0x3939392f, 0x30312f32,
-0x30203139, 0x3a34393a, 0x34392073, 0x6875616e,
-0x67204578, 0x70202400, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x3f48636d, 0x644d6278,
-0x0, 0x3f636d64, 0x48737453, 0x0,
-0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64,
-0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b,
-0x0, 0x3f636d64, 0x45727200, 0x86ac,
-0x8e5c, 0x8e5c, 0x8de4, 0x8b78,
-0x8e30, 0x8e5c, 0x8790, 0x8800,
-0x8990, 0x8a68, 0x8a34, 0x8e5c,
-0x8870, 0x8b24, 0x8e5c, 0x8b34,
-0x87b4, 0x8824, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6d63, 0x6173742e, 0x632c7620, 0x312e312e,
-0x322e3820, 0x31393938, 0x2f31322f, 0x30382030,
-0x323a3336, 0x3a333620, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x6164644d, 0x63447570,
-0x0, 0x6164644d, 0x6346756c, 0x0,
-0x64656c4d, 0x634e6f45, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f646d, 0x612e632c, 0x7620312e, 0x312e322e,
-0x32342031, 0x3939382f, 0x31322f32, 0x31203030,
-0x3a33333a, 0x30392073, 0x6875616e, 0x67204578,
-0x70202400, 0x65767452, 0x6e674600, 0x51657674,
-0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
-0x526e6746, 0x0, 0x4d516576, 0x74460000,
-0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
-0x0, 0x5173436f, 0x6e734600, 0x51725072,
-0x6f644600, 0x7377446d, 0x614f6666, 0x0,
-0x31446d61, 0x4f6e0000, 0x7377446d, 0x614f6e00,
-0x2372446d, 0x6141544e, 0x0, 0x72446d61,
-0x41544e30, 0x0, 0x72446d61, 0x41544e31,
-0x0, 0x72446d61, 0x34476200, 0x2a50414e,
-0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f,
-0x2e2e2f73, 0x72632f6e, 0x69632f66, 0x77322f63,
-0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 0x2377446d,
-0x6141544e, 0x0, 0x77446d61, 0x41544e30,
-0x0, 0x77446d61, 0x41544e31, 0x0,
-0x77446d61, 0x34476200, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7472, 0x6163652e, 0x632c7620, 0x312e312e,
-0x322e3520, 0x31393938, 0x2f30392f, 0x33302031,
-0x383a3530, 0x3a323820, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6461, 0x74612e63, 0x2c762031, 0x2e312e32,
-0x2e313220, 0x31393939, 0x2f30312f, 0x32302031,
-0x393a3439, 0x3a353120, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x46575f56, 0x45525349,
-0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037,
-0x2031373a, 0x35373a35, 0x32205044, 0x54203230,
-0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54,
-0x494d453a, 0x2031373a, 0x35373a35, 0x32000000,
-0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064,
-0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049,
-0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465,
-0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44,
-0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f,
-0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049,
-0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e,
-0x20322e37, 0x2e320000, 0x0, 0x12041100,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6d65, 0x6d2e632c, 0x7620312e, 0x312e322e,
-0x35203139, 0x39382f30, 0x392f3330, 0x2031383a,
-0x35303a30, 0x38207368, 0x75616e67, 0x20457870,
-0x20240000, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7365, 0x6e642e63, 0x2c762031, 0x2e312e32,
-0x2e343420, 0x31393938, 0x2f31322f, 0x32312030,
-0x303a3333, 0x3a313820, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x69736e74, 0x54637055,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f7265, 0x63762e63, 0x2c762031, 0x2e312e32,
-0x2e353320, 0x31393939, 0x2f30312f, 0x31362030,
-0x323a3535, 0x3a343320, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x724d6163, 0x43686b30,
-0x0, 0x72784672, 0x6d324c67, 0x0,
-0x72784e6f, 0x53744264, 0x0, 0x72784e6f,
-0x4d694264, 0x0, 0x72784e6f, 0x4a6d4264,
-0x0, 0x7278436b, 0x446d6146, 0x0,
-0x72785144, 0x6d457846, 0x0, 0x72785144,
-0x6d614600, 0x72785144, 0x4c426446, 0x0,
-0x72785144, 0x6d426446, 0x0, 0x72784372,
-0x63506164, 0x0, 0x72536d51, 0x446d6146,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f6d61, 0x632e632c, 0x7620312e, 0x312e322e,
-0x32322031, 0x3939382f, 0x31322f30, 0x38203032,
-0x3a33363a, 0x33302073, 0x6875616e, 0x67204578,
-0x70202400, 0x65767452, 0x6e674600, 0x51657674,
-0x46000000, 0x51657674, 0x505f4600, 0x4d657674,
-0x526e6746, 0x0, 0x4d516576, 0x74460000,
-0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46,
-0x0, 0x5173436f, 0x6e734600, 0x51725072,
-0x6f644600, 0x6d616354, 0x68726573, 0x0,
-0x23744d61, 0x6341544e, 0x0, 0x23724d61,
-0x6341544e, 0x0, 0x72656d41, 0x73737274,
-0x0, 0x6c696e6b, 0x444f574e, 0x0,
-0x6c696e6b, 0x55500000, 0x0, 0x0,
-0x0, 0x24486561, 0x6465723a, 0x202f7072,
-0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765,
-0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f,
-0x6e2f636b, 0x73756d2e, 0x632c7620, 0x312e312e,
-0x322e3920, 0x31393939, 0x2f30312f, 0x31342030,
-0x303a3033, 0x3a343820, 0x73687561, 0x6e672045,
-0x78702024, 0x0, 0x65767452, 0x6e674600,
-0x51657674, 0x46000000, 0x51657674, 0x505f4600,
-0x4d657674, 0x526e6746, 0x0, 0x4d516576,
-0x74460000, 0x4d516576, 0x505f4600, 0x5173436f,
-0x6e495f46, 0x0, 0x5173436f, 0x6e734600,
-0x51725072, 0x6f644600, 0x0, 0x0,
-0x0, 0x50726f62, 0x65506879, 0x0,
-0x6c6e6b41, 0x53535254, 0x0, 0x109a4,
-0x10a1c, 0x10a50, 0x10a7c, 0x11050,
-0x10aa8, 0x10b10, 0x111fc, 0x10dc0,
-0x10c68, 0x10c80, 0x10cc4, 0x10cec,
-0x10d0c, 0x10d34, 0x111fc, 0x10dc0,
-0x10df8, 0x10e10, 0x10e40, 0x10e68,
-0x10e88, 0x10eb0, 0x0, 0x10fdc,
-0x11008, 0x1102c, 0x111fc, 0x11050,
-0x11078, 0x11108, 0x0, 0x0,
-0x0, 0x1186c, 0x1193c, 0x11a14,
-0x11ae4, 0x11b40, 0x11c1c, 0x11c44,
-0x11d20, 0x11d48, 0x11ef0, 0x11f18,
-0x120c0, 0x122b8, 0x1254c, 0x12460,
-0x1254c, 0x12578, 0x120e8, 0x12290,
-0x7273745f, 0x676d6969, 0x0, 0x12608,
-0x12640, 0x12728, 0x13374, 0x133b4,
-0x133cc, 0x7365746c, 0x6f6f7000, 0x0,
-0x0, 0x13bbc, 0x13bfc, 0x13c8c,
-0x13cd0, 0x13d34, 0x13dc0, 0x13df4,
-0x13e7c, 0x13f14, 0x13fe4, 0x14024,
-0x140a8, 0x140cc, 0x141dc, 0x646f4261,
-0x73655067, 0x0, 0x0, 0x0,
-0x0, 0x73746d61, 0x634c4e4b, 0x0,
-0x6765746d, 0x636c6e6b, 0x0, 0x14ed8,
-0x14ed8, 0x14b8c, 0x14bd8, 0x14c24,
-0x14ed8, 0x7365746d, 0x61636163, 0x74000000,
-0x0, 0x0 };
-static u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __devinitdata = {
-0x1,
-0x1, 0x1, 0xc001fc, 0x3ffc,
-0xc00000, 0x416c7465, 0x6f6e2041, 0x63654e49,
-0x43205600, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x416c7465,
-0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242,
-0x0, 0x0, 0x0, 0x1ffffc,
-0x1fff7c, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x60cf00,
-0x60, 0xcf000000, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3, 0x0,
-0x1, 0x0, 0x0, 0x0,
-0x1, 0x0, 0x1, 0x0,
-0x0, 0x0, 0x0, 0x1,
-0x1, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x1000000, 0x21000000,
-0x12000140, 0x0, 0x0, 0x20000000,
-0x120000a0, 0x0, 0x12000060, 0x12000180,
-0x120001e0, 0x0, 0x0, 0x0,
-0x1, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x2,
-0x0, 0x0, 0x30001, 0x1,
-0x30201, 0x0, 0x0, 0x1010101,
-0x1010100, 0x10100, 0x1010001, 0x10001,
-0x1000101, 0x101, 0x0, 0x0 };
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 187ac6eb6e94..7709992bb6bf 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1813,6 +1813,25 @@ static void __devinit amd8111e_probe_ext_phy(struct net_device* dev)
lp->ext_phy_addr = 1;
}
+static const struct net_device_ops amd8111e_netdev_ops = {
+ .ndo_open = amd8111e_open,
+ .ndo_stop = amd8111e_close,
+ .ndo_start_xmit = amd8111e_start_xmit,
+ .ndo_tx_timeout = amd8111e_tx_timeout,
+ .ndo_get_stats = amd8111e_get_stats,
+ .ndo_set_multicast_list = amd8111e_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = amd8111e_set_mac_address,
+ .ndo_do_ioctl = amd8111e_ioctl,
+ .ndo_change_mtu = amd8111e_change_mtu,
+#if AMD8111E_VLAN_TAG_USED
+ .ndo_vlan_rx_register = amd8111e_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = amd8111e_poll,
+#endif
+};
+
static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1872,7 +1891,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
#if AMD8111E_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ;
- dev->vlan_rx_register =amd8111e_vlan_rx_register;
#endif
lp = netdev_priv(dev);
@@ -1901,27 +1919,16 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
if(dynamic_ipg[card_idx++])
lp->options |= OPTION_DYN_IPG_ENABLE;
+
/* Initialize driver entry points */
- dev->open = amd8111e_open;
- dev->hard_start_xmit = amd8111e_start_xmit;
- dev->stop = amd8111e_close;
- dev->get_stats = amd8111e_get_stats;
- dev->set_multicast_list = amd8111e_set_multicast_list;
- dev->set_mac_address = amd8111e_set_mac_address;
- dev->do_ioctl = amd8111e_ioctl;
- dev->change_mtu = amd8111e_change_mtu;
+ dev->netdev_ops = &amd8111e_netdev_ops;
SET_ETHTOOL_OPS(dev, &ops);
dev->irq =pdev->irq;
- dev->tx_timeout = amd8111e_tx_timeout;
dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = amd8111e_poll;
-#endif
#if AMD8111E_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register =amd8111e_vlan_rx_register;
#endif
/* Probe the external PHY */
amd8111e_probe_ext_phy(dev);
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 9a0be9b2eaad..da64ba88d7f8 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -48,12 +48,18 @@ static int ipddp_mode = IPDDP_DECAP;
/* Index to functions, as function prototypes. */
static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *ipddp_get_stats(struct net_device *dev);
static int ipddp_create(struct ipddp_route *new_rt);
static int ipddp_delete(struct ipddp_route *rt);
static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt);
static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static const struct net_device_ops ipddp_netdev_ops = {
+ .ndo_start_xmit = ipddp_xmit,
+ .ndo_do_ioctl = ipddp_ioctl,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
static struct net_device * __init ipddp_init(void)
{
@@ -61,7 +67,7 @@ static struct net_device * __init ipddp_init(void)
struct net_device *dev;
int err;
- dev = alloc_etherdev(sizeof(struct net_device_stats));
+ dev = alloc_etherdev(0);
if (!dev)
return ERR_PTR(-ENOMEM);
@@ -71,9 +77,7 @@ static struct net_device * __init ipddp_init(void)
printk(version);
/* Initalize the device structure. */
- dev->hard_start_xmit = ipddp_xmit;
- dev->get_stats = ipddp_get_stats;
- dev->do_ioctl = ipddp_ioctl;
+ dev->netdev_ops = &ipddp_netdev_ops;
dev->type = ARPHRD_IPDDP; /* IP over DDP tunnel */
dev->mtu = 585;
@@ -103,13 +107,6 @@ static struct net_device * __init ipddp_init(void)
return dev;
}
-/*
- * Get the current statistics. This may be called with the card open or closed.
- */
-static struct net_device_stats *ipddp_get_stats(struct net_device *dev)
-{
- return netdev_priv(dev);
-}
/*
* Transmit LLAP/ELAP frame using aarp_send_ddp.
@@ -170,8 +167,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */
- ((struct net_device_stats *) netdev_priv(dev))->tx_packets++;
- ((struct net_device_stats *) netdev_priv(dev))->tx_bytes += skb->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
dev_kfree_skb(skb);
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 0c628a9e5339..c2d012fcc29b 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -208,9 +208,9 @@ am79c961_init_for_open(struct net_device *dev)
/*
* Stop the chip.
*/
- spin_lock_irqsave(priv->chip_lock, flags);
+ spin_lock_irqsave(&priv->chip_lock, flags);
write_rreg (dev->base_addr, CSR0, CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|CSR0_TINT|CSR0_RINT|CSR0_STOP);
- spin_unlock_irqrestore(priv->chip_lock, flags);
+ spin_unlock_irqrestore(&priv->chip_lock, flags);
write_ireg (dev->base_addr, 5, 0x00a0); /* Receive address LED */
write_ireg (dev->base_addr, 6, 0x0081); /* Collision LED */
@@ -332,10 +332,10 @@ am79c961_close(struct net_device *dev)
netif_stop_queue(dev);
netif_carrier_off(dev);
- spin_lock_irqsave(priv->chip_lock, flags);
+ spin_lock_irqsave(&priv->chip_lock, flags);
write_rreg (dev->base_addr, CSR0, CSR0_STOP);
write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
- spin_unlock_irqrestore(priv->chip_lock, flags);
+ spin_unlock_irqrestore(&priv->chip_lock, flags);
free_irq (dev->irq, dev);
@@ -391,7 +391,7 @@ static void am79c961_setmulticastlist (struct net_device *dev)
am79c961_mc_hash(dmi, multi_hash);
}
- spin_lock_irqsave(priv->chip_lock, flags);
+ spin_lock_irqsave(&priv->chip_lock, flags);
stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
@@ -405,9 +405,9 @@ static void am79c961_setmulticastlist (struct net_device *dev)
* Spin waiting for chip to report suspend mode
*/
while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) {
- spin_unlock_irqrestore(priv->chip_lock, flags);
+ spin_unlock_irqrestore(&priv->chip_lock, flags);
nop();
- spin_lock_irqsave(priv->chip_lock, flags);
+ spin_lock_irqsave(&priv->chip_lock, flags);
}
}
@@ -429,7 +429,7 @@ static void am79c961_setmulticastlist (struct net_device *dev)
write_rreg(dev->base_addr, CTRL1, 0);
}
- spin_unlock_irqrestore(priv->chip_lock, flags);
+ spin_unlock_irqrestore(&priv->chip_lock, flags);
}
static void am79c961_timeout(struct net_device *dev)
@@ -467,10 +467,10 @@ am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
priv->txhead = head;
- spin_lock_irqsave(priv->chip_lock, flags);
+ spin_lock_irqsave(&priv->chip_lock, flags);
write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
dev->trans_start = jiffies;
- spin_unlock_irqrestore(priv->chip_lock, flags);
+ spin_unlock_irqrestore(&priv->chip_lock, flags);
/*
* If the next packet is owned by the ethernet device,
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 6278606d1049..54b52e5b1821 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -646,6 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index 9ad22d1b00fd..1cf2f949c0b4 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -1357,6 +1357,7 @@ static const struct net_device_ops ks8695_netdev_ops = {
.ndo_start_xmit = ks8695_start_xmit,
.ndo_tx_timeout = ks8695_timeout,
.ndo_set_mac_address = ks8695_set_mac,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = ks8695_set_multicast,
};
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index ea493ce23982..4317b3edb3d7 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -204,8 +204,7 @@ static irqreturn_t atp_interrupt(int irq, void *dev_id);
static void net_rx(struct net_device *dev);
static void read_block(long ioaddr, int length, unsigned char *buffer, int data_mode);
static int net_close(struct net_device *dev);
-static void set_rx_mode_8002(struct net_device *dev);
-static void set_rx_mode_8012(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
static void tx_timeout(struct net_device *dev);
@@ -242,6 +241,17 @@ static int __init atp_init(void)
return -ENODEV;
}
+static const struct net_device_ops atp_netdev_ops = {
+ .ndo_open = net_open,
+ .ndo_stop = net_close,
+ .ndo_start_xmit = atp_send_packet,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_tx_timeout = tx_timeout,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __init atp_probe1(long ioaddr)
{
struct net_device *dev = NULL;
@@ -342,12 +352,7 @@ static int __init atp_probe1(long ioaddr)
if (dev->mem_end & 0xf)
net_debug = dev->mem_end & 7;
- dev->open = net_open;
- dev->stop = net_close;
- dev->hard_start_xmit = atp_send_packet;
- dev->set_multicast_list =
- lp->chip_type == RTL8002 ? &set_rx_mode_8002 : &set_rx_mode_8012;
- dev->tx_timeout = tx_timeout;
+ dev->netdev_ops = &atp_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
res = register_netdev(dev);
@@ -903,6 +908,17 @@ static void set_rx_mode_8012(struct net_device *dev)
write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Switch back to page 0 */
}
+static void set_rx_mode(struct net_device *dev)
+{
+ struct net_local *lp = netdev_priv(dev);
+
+ if (lp->chip_type == RTL8002)
+ return set_rx_mode_8002(dev);
+ else
+ return set_rx_mode_8012(dev);
+}
+
+
static int __init atp_init_module(void) {
if (debug) /* Emit version even if no cards detected. */
printk(KERN_INFO "%s", version);
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 337488ec707c..a4eb6c40678c 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -37,7 +37,10 @@ static int phy_debug = 0;
#define __ei_open ax_ei_open
#define __ei_close ax_ei_close
#define __ei_poll ax_ei_poll
+#define __ei_start_xmit ax_ei_start_xmit
#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_get_stats ax_ei_get_stats
+#define __ei_set_multicast_list ax_ei_set_multicast_list
#define __ei_interrupt ax_ei_interrupt
#define ____alloc_ei_netdev ax__alloc_ei_netdev
#define __NS8390_init ax_NS8390_init
@@ -623,6 +626,23 @@ static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
}
#endif
+static const struct net_device_ops ax_netdev_ops = {
+ .ndo_open = ax_open,
+ .ndo_stop = ax_close,
+ .ndo_do_ioctl = ax_ioctl,
+
+ .ndo_start_xmit = ax_ei_start_xmit,
+ .ndo_tx_timeout = ax_ei_tx_timeout,
+ .ndo_get_stats = ax_ei_get_stats,
+ .ndo_set_multicast_list = ax_ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ax_ei_poll,
+#endif
+};
+
/* setup code */
static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
@@ -738,9 +758,7 @@ static int ax_init_dev(struct net_device *dev, int first_init)
ei_status.get_8390_hdr = &ax_get_8390_hdr;
ei_status.priv = 0;
- dev->open = ax_open;
- dev->stop = ax_close;
- dev->do_ioctl = ax_ioctl;
+ dev->netdev_ops = &ax_netdev_ops;
dev->ethtool_ops = &ax_ethtool_ops;
ax->msg_enable = NETIF_MSG_LINK;
@@ -753,9 +771,6 @@ static int ax_init_dev(struct net_device *dev, int first_init)
ax->mii.mdio_write = ax_phy_write;
ax->mii.dev = dev;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ax_ei_poll;
-#endif
ax_NS8390_init(dev, 0);
if (first_init)
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 0e7470a201f0..c38512ebcea6 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -73,8 +73,8 @@
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
-#define RX_PKT_OFFSET 30
-#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
+#define RX_PKT_OFFSET (RX_HEADER_LEN + 2)
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET)
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
@@ -679,10 +679,10 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
dev_kfree_skb_any(skb);
return -ENOMEM;
}
+ bp->force_copybreak = 1;
}
rh = (struct rx_header *) skb->data;
- skb_reserve(skb, RX_PKT_OFFSET);
rh->len = 0;
rh->flags = 0;
@@ -693,13 +693,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (src_map != NULL)
src_map->skb = NULL;
- ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
+ ctrl = (DESC_CTRL_LEN & RX_PKT_BUF_SZ);
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= DESC_CTRL_EOT;
dp = &bp->rx_ring[dest_idx];
dp->ctrl = cpu_to_le32(ctrl);
- dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
+ dp->addr = cpu_to_le32((u32) mapping + bp->dma_offset);
if (bp->flags & B44_FLAG_RX_RING_HACK)
b44_sync_dma_desc_for_device(bp->sdev, bp->rx_ring_dma,
@@ -801,7 +801,7 @@ static int b44_rx(struct b44 *bp, int budget)
/* Omit CRC. */
len -= 4;
- if (len > RX_COPY_THRESHOLD) {
+ if (!bp->force_copybreak && len > RX_COPY_THRESHOLD) {
int skb_size;
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
if (skb_size < 0)
@@ -809,8 +809,8 @@ static int b44_rx(struct b44 *bp, int budget)
ssb_dma_unmap_single(bp->sdev, map,
skb_size, DMA_FROM_DEVICE);
/* Leave out rx_header */
- skb_put(skb, len + RX_PKT_OFFSET);
- skb_pull(skb, RX_PKT_OFFSET);
+ skb_put(skb, len + RX_PKT_OFFSET);
+ skb_pull(skb, RX_PKT_OFFSET);
} else {
struct sk_buff *copy_skb;
@@ -2108,6 +2108,22 @@ static int __devinit b44_get_invariants(struct b44 *bp)
return err;
}
+static const struct net_device_ops b44_netdev_ops = {
+ .ndo_open = b44_open,
+ .ndo_stop = b44_close,
+ .ndo_start_xmit = b44_start_xmit,
+ .ndo_get_stats = b44_get_stats,
+ .ndo_set_multicast_list = b44_set_rx_mode,
+ .ndo_set_mac_address = b44_set_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = b44_ioctl,
+ .ndo_tx_timeout = b44_tx_timeout,
+ .ndo_change_mtu = b44_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = b44_poll_controller,
+#endif
+};
+
static int __devinit b44_init_one(struct ssb_device *sdev,
const struct ssb_device_id *ent)
{
@@ -2137,6 +2153,7 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
bp = netdev_priv(dev);
bp->sdev = sdev;
bp->dev = dev;
+ bp->force_copybreak = 0;
bp->msg_enable = netif_msg_init(b44_debug, B44_DEF_MSG_ENABLE);
@@ -2145,20 +2162,9 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
bp->rx_pending = B44_DEF_RX_RING_PENDING;
bp->tx_pending = B44_DEF_TX_RING_PENDING;
- dev->open = b44_open;
- dev->stop = b44_close;
- dev->hard_start_xmit = b44_start_xmit;
- dev->get_stats = b44_get_stats;
- dev->set_multicast_list = b44_set_rx_mode;
- dev->set_mac_address = b44_set_mac_addr;
- dev->do_ioctl = b44_ioctl;
- dev->tx_timeout = b44_tx_timeout;
+ dev->netdev_ops = &b44_netdev_ops;
netif_napi_add(dev, &bp->napi, b44_poll, 64);
dev->watchdog_timeo = B44_TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = b44_poll_controller;
-#endif
- dev->change_mtu = b44_change_mtu;
dev->irq = sdev->irq;
SET_ETHTOOL_OPS(dev, &b44_ethtool_ops);
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 7db0c84a7950..e678498de6db 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -395,7 +395,7 @@ struct b44 {
u32 rx_pending;
u32 tx_pending;
u8 phy_addr;
-
+ u8 force_copybreak;
struct mii_if_info mii_if;
};
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h
index fd705d1295a7..15a5cf0f676b 100644
--- a/drivers/net/bnx2x.h
+++ b/drivers/net/bnx2x.h
@@ -1,6 +1,6 @@
/* bnx2x.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2008 Broadcom Corporation
+ * Copyright (c) 2007-2009 Broadcom Corporation
*
* 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
@@ -20,6 +20,11 @@
* (you will need to reboot afterwards) */
/* #define BNX2X_STOP_ON_ERROR */
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define BCM_VLAN 1
+#endif
+
+
/* error/debug prints */
#define DRV_MODULE_NAME "bnx2x"
@@ -78,11 +83,6 @@
#endif
-#ifdef NETIF_F_HW_VLAN_TX
-#define BCM_VLAN 1
-#endif
-
-
#define U64_LO(x) (u32)(((u64)(x)) & 0xffffffff)
#define U64_HI(x) (u32)(((u64)(x)) >> 32)
#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo))
@@ -150,6 +150,9 @@ struct sw_rx_page {
#define PAGES_PER_SGE_SHIFT 0
#define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT)
+#define SGE_PAGE_SIZE PAGE_SIZE
+#define SGE_PAGE_SHIFT PAGE_SHIFT
+#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN(addr)
#define BCM_RX_ETH_PAYLOAD_ALIGN 64
@@ -268,14 +271,7 @@ struct bnx2x_fastpath {
#define bnx2x_fp(bp, nr, var) (bp->fp[nr].var)
-#define BNX2X_HAS_TX_WORK(fp) \
- ((fp->tx_pkt_prod != le16_to_cpu(*fp->tx_cons_sb)) || \
- (fp->tx_pkt_prod != fp->tx_pkt_cons))
-
-#define BNX2X_HAS_RX_WORK(fp) \
- (fp->rx_comp_cons != rx_cons_sb)
-
-#define BNX2X_HAS_WORK(fp) (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp))
+#define BNX2X_HAS_WORK(fp) (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))
/* MC hsi */
@@ -736,7 +732,7 @@ struct bnx2x {
struct bnx2x_fastpath fp[MAX_CONTEXT];
void __iomem *regview;
void __iomem *doorbells;
-#define BNX2X_DB_SIZE (16*2048)
+#define BNX2X_DB_SIZE (16*BCM_PAGE_SIZE)
struct net_device *dev;
struct pci_dev *pdev;
@@ -801,6 +797,8 @@ struct bnx2x {
#define TPA_ENABLE_FLAG 0x80
#define NO_MCP_FLAG 0x100
#define BP_NOMCP(bp) (bp->flags & NO_MCP_FLAG)
+#define HW_VLAN_TX_FLAG 0x400
+#define HW_VLAN_RX_FLAG 0x800
int func;
#define BP_PORT(bp) (bp->func % PORT_MAX)
@@ -811,7 +809,7 @@ struct bnx2x {
int pm_cap;
int pcie_cap;
- struct work_struct sp_task;
+ struct delayed_work sp_task;
struct work_struct reset_task;
struct timer_list timer;
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index 67de94f1f30e..aea26b4dc453 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -1,4 +1,4 @@
-/* Copyright 2008 Broadcom Corporation
+/* Copyright 2008-2009 Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -317,6 +317,9 @@ static u8 bnx2x_emac_enable(struct link_params *params,
val &= ~0x810;
EMAC_WR(bp, EMAC_REG_EMAC_MODE, val);
+ /* enable emac */
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 1);
+
/* enable emac for jumbo packets */
EMAC_WR(bp, EMAC_REG_EMAC_RX_MTU_SIZE,
(EMAC_RX_MTU_SIZE_JUMBO_ENA |
@@ -1609,7 +1612,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
u32 gp_status)
{
struct bnx2x *bp = params->bp;
-
+ u16 new_line_speed;
u8 rc = 0;
vars->link_status = 0;
@@ -1629,7 +1632,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
switch (gp_status & GP_STATUS_SPEED_MASK) {
case GP_STATUS_10M:
- vars->line_speed = SPEED_10;
+ new_line_speed = SPEED_10;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_10TFD;
else
@@ -1637,7 +1640,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
break;
case GP_STATUS_100M:
- vars->line_speed = SPEED_100;
+ new_line_speed = SPEED_100;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_100TXFD;
else
@@ -1646,7 +1649,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
case GP_STATUS_1G:
case GP_STATUS_1G_KX:
- vars->line_speed = SPEED_1000;
+ new_line_speed = SPEED_1000;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_1000TFD;
else
@@ -1654,7 +1657,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
break;
case GP_STATUS_2_5G:
- vars->line_speed = SPEED_2500;
+ new_line_speed = SPEED_2500;
if (vars->duplex == DUPLEX_FULL)
vars->link_status |= LINK_2500TFD;
else
@@ -1671,32 +1674,32 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
case GP_STATUS_10G_KX4:
case GP_STATUS_10G_HIG:
case GP_STATUS_10G_CX4:
- vars->line_speed = SPEED_10000;
+ new_line_speed = SPEED_10000;
vars->link_status |= LINK_10GTFD;
break;
case GP_STATUS_12G_HIG:
- vars->line_speed = SPEED_12000;
+ new_line_speed = SPEED_12000;
vars->link_status |= LINK_12GTFD;
break;
case GP_STATUS_12_5G:
- vars->line_speed = SPEED_12500;
+ new_line_speed = SPEED_12500;
vars->link_status |= LINK_12_5GTFD;
break;
case GP_STATUS_13G:
- vars->line_speed = SPEED_13000;
+ new_line_speed = SPEED_13000;
vars->link_status |= LINK_13GTFD;
break;
case GP_STATUS_15G:
- vars->line_speed = SPEED_15000;
+ new_line_speed = SPEED_15000;
vars->link_status |= LINK_15GTFD;
break;
case GP_STATUS_16G:
- vars->line_speed = SPEED_16000;
+ new_line_speed = SPEED_16000;
vars->link_status |= LINK_16GTFD;
break;
@@ -1708,6 +1711,15 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
break;
}
+ /* Upon link speed change set the NIG into drain mode.
+ Comes to deals with possible FIFO glitch due to clk change
+ when speed is decreased without link down indicator */
+ if (new_line_speed != vars->line_speed) {
+ REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
+ + params->port*4, 0);
+ msleep(1);
+ }
+ vars->line_speed = new_line_speed;
vars->link_status |= LINK_STATUS_SERDES_LINK;
if ((params->req_line_speed == SPEED_AUTO_NEG) &&
@@ -3359,7 +3371,7 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len)
u8 shift = 8*4;
u8 digit;
if (len < 10) {
- /* Need more then 10chars for this format */
+ /* Need more than 10chars for this format */
*str_ptr = '\0';
return -EINVAL;
}
@@ -3571,7 +3583,7 @@ static void bnx2x_set_xgxs_loopback(struct link_params *params,
(MDIO_REG_BANK_CL73_IEEEB0 +
(MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
0x6041);
-
+ msleep(200);
/* set aer mmd back */
bnx2x_set_aer_mmd(params, vars);
@@ -3870,9 +3882,15 @@ static u8 bnx2x_link_initialize(struct link_params *params,
}
if (vars->phy_flags & PHY_XGXS_FLAG) {
- if (params->req_line_speed &&
+ if ((params->req_line_speed &&
((params->req_line_speed == SPEED_100) ||
- (params->req_line_speed == SPEED_10))) {
+ (params->req_line_speed == SPEED_10))) ||
+ (!params->req_line_speed &&
+ (params->speed_cap_mask >=
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL) &&
+ (params->speed_cap_mask <
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+ )) {
vars->phy_flags |= PHY_SGMII_FLAG;
} else {
vars->phy_flags &= ~PHY_SGMII_FLAG;
@@ -4194,6 +4212,11 @@ static u8 bnx2x_update_link_down(struct link_params *params,
/* activate nig drain */
REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
+ /* disable emac */
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+
+ msleep(10);
+
/* reset BigMac */
bnx2x_bmac_rx_disable(bp, params->port);
REG_WR(bp, GRCBASE_MISC +
@@ -4238,6 +4261,7 @@ static u8 bnx2x_update_link_up(struct link_params *params,
/* update shared memory */
bnx2x_update_mng(params, vars->link_status);
+ msleep(20);
return rc;
}
/* This function should called upon link interrupt */
@@ -4276,6 +4300,9 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68));
+ /* disable emac */
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
+
ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
/* Check external link change only for non-direct */
@@ -4377,10 +4404,11 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
ext_phy_addr[port],
MDIO_PMA_DEVAD,
MDIO_PMA_REG_ROM_VER1, &fw_ver1);
- if (fw_ver1 == 0) {
+ if (fw_ver1 == 0 || fw_ver1 == 0x4321) {
DP(NETIF_MSG_LINK,
- "bnx2x_8073_common_init_phy port %x "
- "fw Download failed\n", port);
+ "bnx2x_8073_common_init_phy port %x:"
+ "Download failed. fw version = 0x%x\n",
+ port, fw_ver1);
return -EINVAL;
}
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index ef8103b3523e..d3e7775a9ccf 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -1,6 +1,6 @@
/* bnx2x_main.c: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2008 Broadcom Corporation
+ * Copyright (c) 2007-2009 Broadcom Corporation
*
* 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
@@ -38,9 +38,7 @@
#include <linux/time.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
-#ifdef NETIF_F_HW_VLAN_TX
- #include <linux/if_vlan.h>
-#endif
+#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <net/checksum.h>
@@ -59,8 +57,8 @@
#include "bnx2x.h"
#include "bnx2x_init.h"
-#define DRV_MODULE_VERSION "1.45.23"
-#define DRV_MODULE_RELDATE "2008/11/03"
+#define DRV_MODULE_VERSION "1.45.26"
+#define DRV_MODULE_RELDATE "2009/01/26"
#define BNX2X_BC_VER 0x040200
/* Time in jiffies before concluding the transmitter is hung */
@@ -71,7 +69,7 @@ static char version[] __devinitdata =
DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
MODULE_AUTHOR("Eliezer Tamir");
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 Driver");
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
@@ -95,6 +93,7 @@ MODULE_PARM_DESC(debug, "default debug msglevel");
module_param(use_multi, int, 0);
MODULE_PARM_DESC(use_multi, "use per-CPU queues");
#endif
+static struct workqueue_struct *bnx2x_wq;
enum bnx2x_board_type {
BCM57710 = 0,
@@ -671,7 +670,8 @@ static void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
synchronize_irq(bp->pdev->irq);
/* make sure sp_task is not running */
- cancel_work_sync(&bp->sp_task);
+ cancel_delayed_work(&bp->sp_task);
+ flush_workqueue(bnx2x_wq);
}
/* fast path */
@@ -733,6 +733,24 @@ static u16 bnx2x_ack_int(struct bnx2x *bp)
* fast path service functions
*/
+static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
+{
+ u16 tx_cons_sb;
+
+ /* Tell compiler that status block fields can change */
+ barrier();
+ tx_cons_sb = le16_to_cpu(*fp->tx_cons_sb);
+ return (fp->tx_pkt_cons != tx_cons_sb);
+}
+
+static inline int bnx2x_has_tx_work_unload(struct bnx2x_fastpath *fp)
+{
+ /* Tell compiler that consumer and producer can change */
+ barrier();
+ return (fp->tx_pkt_prod != fp->tx_pkt_cons);
+
+}
+
/* free skb in the packet ring at pos idx
* return idx of last bd freed
*/
@@ -972,7 +990,7 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
return;
pci_unmap_page(bp->pdev, pci_unmap_addr(sw_buf, mapping),
- BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
+ SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
__free_pages(page, PAGES_PER_SGE_SHIFT);
sw_buf->page = NULL;
@@ -1000,7 +1018,7 @@ static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
if (unlikely(page == NULL))
return -ENOMEM;
- mapping = pci_map_page(bp->pdev, page, 0, BCM_PAGE_SIZE*PAGES_PER_SGE,
+ mapping = pci_map_page(bp->pdev, page, 0, SGE_PAGE_SIZE*PAGES_PER_SGE,
PCI_DMA_FROMDEVICE);
if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
__free_pages(page, PAGES_PER_SGE_SHIFT);
@@ -1096,9 +1114,9 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp,
struct eth_fast_path_rx_cqe *fp_cqe)
{
struct bnx2x *bp = fp->bp;
- u16 sge_len = BCM_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) -
+ u16 sge_len = SGE_PAGE_ALIGN(le16_to_cpu(fp_cqe->pkt_len) -
le16_to_cpu(fp_cqe->len_on_bd)) >>
- BCM_PAGE_SHIFT;
+ SGE_PAGE_SHIFT;
u16 last_max, last_elem, first_elem;
u16 delta = 0;
u16 i;
@@ -1203,22 +1221,22 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
u16 cqe_idx)
{
struct sw_rx_page *rx_pg, old_rx_pg;
- struct page *sge;
u16 len_on_bd = le16_to_cpu(fp_cqe->len_on_bd);
u32 i, frag_len, frag_size, pages;
int err;
int j;
frag_size = le16_to_cpu(fp_cqe->pkt_len) - len_on_bd;
- pages = BCM_PAGE_ALIGN(frag_size) >> BCM_PAGE_SHIFT;
+ pages = SGE_PAGE_ALIGN(frag_size) >> SGE_PAGE_SHIFT;
/* This is needed in order to enable forwarding support */
if (frag_size)
- skb_shinfo(skb)->gso_size = min((u32)BCM_PAGE_SIZE,
+ skb_shinfo(skb)->gso_size = min((u32)SGE_PAGE_SIZE,
max(frag_size, (u32)len_on_bd));
#ifdef BNX2X_STOP_ON_ERROR
- if (pages > 8*PAGES_PER_SGE) {
+ if (pages >
+ min((u32)8, (u32)MAX_SKB_FRAGS) * SGE_PAGE_SIZE * PAGES_PER_SGE) {
BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
pages, cqe_idx);
BNX2X_ERR("fp_cqe->pkt_len = %d fp_cqe->len_on_bd = %d\n",
@@ -1234,9 +1252,8 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* FW gives the indices of the SGE as if the ring is an array
(meaning that "next" element will consume 2 indices) */
- frag_len = min(frag_size, (u32)(BCM_PAGE_SIZE*PAGES_PER_SGE));
+ frag_len = min(frag_size, (u32)(SGE_PAGE_SIZE*PAGES_PER_SGE));
rx_pg = &fp->rx_page_ring[sge_idx];
- sge = rx_pg->page;
old_rx_pg = *rx_pg;
/* If we fail to allocate a substitute page, we simply stop
@@ -1249,7 +1266,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
/* Unmap the page as we r going to pass it to the stack */
pci_unmap_page(bp->pdev, pci_unmap_addr(&old_rx_pg, mapping),
- BCM_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
+ SGE_PAGE_SIZE*PAGES_PER_SGE, PCI_DMA_FROMDEVICE);
/* Add one frag and update the appropriate fields in the skb */
skb_fill_page_desc(skb, j, old_rx_pg.page, 0, frag_len);
@@ -1282,6 +1299,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
if (likely(new_skb)) {
/* fix ip xsum and give it to the stack */
/* (no need to map the new skb) */
+#ifdef BCM_VLAN
+ int is_vlan_cqe =
+ (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
+ PARSING_FLAGS_VLAN);
+ int is_not_hwaccel_vlan_cqe =
+ (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG)));
+#endif
prefetch(skb);
prefetch(((char *)(skb)) + 128);
@@ -1306,6 +1330,12 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
struct iphdr *iph;
iph = (struct iphdr *)skb->data;
+#ifdef BCM_VLAN
+ /* If there is no Rx VLAN offloading -
+ take VLAN tag into an account */
+ if (unlikely(is_not_hwaccel_vlan_cqe))
+ iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN);
+#endif
iph->check = 0;
iph->check = ip_fast_csum((u8 *)iph, iph->ihl);
}
@@ -1313,9 +1343,8 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
if (!bnx2x_fill_frag_skb(bp, fp, skb,
&cqe->fast_path_cqe, cqe_idx)) {
#ifdef BCM_VLAN
- if ((bp->vlgrp != NULL) &&
- (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
- PARSING_FLAGS_VLAN))
+ if ((bp->vlgrp != NULL) && is_vlan_cqe &&
+ (!is_not_hwaccel_vlan_cqe))
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
le16_to_cpu(cqe->fast_path_cqe.
vlan_tag));
@@ -1355,11 +1384,23 @@ static inline void bnx2x_update_rx_prod(struct bnx2x *bp,
rx_prods.cqe_prod = rx_comp_prod;
rx_prods.sge_prod = rx_sge_prod;
+ /*
+ * Make sure that the BD and SGE data is updated before updating the
+ * producers since FW might read the BD/SGE right after the producer
+ * is updated.
+ * This is only applicable for weak-ordered memory model archs such
+ * as IA-64. The following barrier is also mandatory since FW will
+ * assumes BDs must have buffers.
+ */
+ wmb();
+
for (i = 0; i < sizeof(struct tstorm_eth_rx_producers)/4; i++)
REG_WR(bp, BAR_TSTRORM_INTMEM +
TSTORM_RX_PRODS_OFFSET(BP_PORT(bp), FP_CL_ID(fp)) + i*4,
((u32 *)&rx_prods)[i]);
+ mmiowb(); /* keep prod updates ordered */
+
DP(NETIF_MSG_RX_STATUS,
"Wrote: bd_prod %u cqe_prod %u sge_prod %u\n",
bd_prod, rx_comp_prod, rx_sge_prod);
@@ -1415,7 +1456,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
DP(NETIF_MSG_RX_STATUS, "CQE type %x err %x status %x"
" queue %x vlan %x len %u\n", CQE_TYPE(cqe_fp_flags),
cqe_fp_flags, cqe->fast_path_cqe.status_flags,
- cqe->fast_path_cqe.rss_hash_result,
+ le32_to_cpu(cqe->fast_path_cqe.rss_hash_result),
le16_to_cpu(cqe->fast_path_cqe.vlan_tag),
le16_to_cpu(cqe->fast_path_cqe.pkt_len));
@@ -1547,7 +1588,7 @@ reuse_rx:
}
#ifdef BCM_VLAN
- if ((bp->vlgrp != NULL) &&
+ if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) &&
(le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) &
PARSING_FLAGS_VLAN))
vlan_hwaccel_receive_skb(skb, bp->vlgrp,
@@ -1580,7 +1621,6 @@ next_cqe:
/* Update producers */
bnx2x_update_rx_prod(bp, fp, bd_prod_fw, sw_comp_prod,
fp->rx_sge_prod);
- mmiowb(); /* keep prod updates ordered */
fp->rx_pkt += rx_pkt;
fp->rx_calls++;
@@ -1660,7 +1700,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
if (unlikely(status & 0x1)) {
- schedule_work(&bp->sp_task);
+ queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
status &= ~0x1;
if (!status)
@@ -1887,7 +1927,8 @@ static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
static void bnx2x_calc_fc_adv(struct bnx2x *bp)
{
- switch (bp->link_vars.ieee_fc) {
+ switch (bp->link_vars.ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK) {
case MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE:
bp->port.advertising &= ~(ADVERTISED_Asym_Pause |
ADVERTISED_Pause);
@@ -1957,10 +1998,11 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp)
rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
bnx2x_release_phy_lock(bp);
+ bnx2x_calc_fc_adv(bp);
+
if (bp->link_vars.link_up)
bnx2x_link_report(bp);
- bnx2x_calc_fc_adv(bp);
return rc;
}
@@ -2220,9 +2262,7 @@ static void bnx2x_link_attn(struct bnx2x *bp)
/* Make sure that we are synced with the current statistics */
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
- bnx2x_acquire_phy_lock(bp);
bnx2x_link_update(&bp->link_params, &bp->link_vars);
- bnx2x_release_phy_lock(bp);
if (bp->link_vars.link_up) {
@@ -2471,6 +2511,8 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
if (asserted & ATTN_HARD_WIRED_MASK) {
if (asserted & ATTN_NIG_FOR_FUNC) {
+ bnx2x_acquire_phy_lock(bp);
+
/* save nig interrupt mask */
bp->nig_mask = REG_RD(bp, nig_int_mask_addr);
REG_WR(bp, nig_int_mask_addr, 0);
@@ -2526,8 +2568,10 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
REG_WR(bp, hc_addr, asserted);
/* now set back the mask */
- if (asserted & ATTN_NIG_FOR_FUNC)
+ if (asserted & ATTN_NIG_FOR_FUNC) {
REG_WR(bp, nig_int_mask_addr, bp->nig_mask);
+ bnx2x_release_phy_lock(bp);
+ }
}
static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
@@ -2795,8 +2839,10 @@ static void bnx2x_attn_int_deasserted(struct bnx2x *bp, u32 deasserted)
static void bnx2x_attn_int(struct bnx2x *bp)
{
/* read local copy of bits */
- u32 attn_bits = bp->def_status_blk->atten_status_block.attn_bits;
- u32 attn_ack = bp->def_status_blk->atten_status_block.attn_bits_ack;
+ u32 attn_bits = le32_to_cpu(bp->def_status_blk->atten_status_block.
+ attn_bits);
+ u32 attn_ack = le32_to_cpu(bp->def_status_blk->atten_status_block.
+ attn_bits_ack);
u32 attn_state = bp->attn_state;
/* look for changed bits */
@@ -2820,7 +2866,7 @@ static void bnx2x_attn_int(struct bnx2x *bp)
static void bnx2x_sp_task(struct work_struct *work)
{
- struct bnx2x *bp = container_of(work, struct bnx2x, sp_task);
+ struct bnx2x *bp = container_of(work, struct bnx2x, sp_task.work);
u16 status;
@@ -2844,7 +2890,7 @@ static void bnx2x_sp_task(struct work_struct *work)
if (status & 0x2)
bp->stats_pending = 0;
- bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, bp->def_att_idx,
+ bnx2x_ack_sb(bp, DEF_SB_ID, ATTENTION_ID, le16_to_cpu(bp->def_att_idx),
IGU_INT_NOP, 1);
bnx2x_ack_sb(bp, DEF_SB_ID, USTORM_ID, le16_to_cpu(bp->def_u_idx),
IGU_INT_NOP, 1);
@@ -2875,7 +2921,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
return IRQ_HANDLED;
#endif
- schedule_work(&bp->sp_task);
+ queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
return IRQ_HANDLED;
}
@@ -2892,7 +2938,7 @@ static irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
#define ADD_64(s_hi, a_hi, s_lo, a_lo) \
do { \
s_lo += a_lo; \
- s_hi += a_hi + (s_lo < a_lo) ? 1 : 0; \
+ s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
} while (0)
/* difference = minuend - subtrahend */
@@ -4496,7 +4542,7 @@ static void bnx2x_init_context(struct bnx2x *bp)
static void bnx2x_init_ind_table(struct bnx2x *bp)
{
- int port = BP_PORT(bp);
+ int func = BP_FUNC(bp);
int i;
if (!is_multi(bp))
@@ -4505,10 +4551,8 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
DP(NETIF_MSG_IFUP, "Initializing indirection table\n");
for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
REG_WR8(bp, BAR_TSTRORM_INTMEM +
- TSTORM_INDIRECTION_TABLE_OFFSET(port) + i,
- i % bp->num_queues);
-
- REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
+ TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
+ BP_CL_ID(bp) + (i % bp->num_queues));
}
static void bnx2x_set_client_config(struct bnx2x *bp)
@@ -4517,12 +4561,12 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
int port = BP_PORT(bp);
int i;
- tstorm_client.mtu = bp->dev->mtu + ETH_OVREHEAD;
+ tstorm_client.mtu = bp->dev->mtu;
tstorm_client.statistics_counter_id = BP_CL_ID(bp);
tstorm_client.config_flags =
TSTORM_ETH_CLIENT_CONFIG_STATSITICS_ENABLE;
#ifdef BCM_VLAN
- if (bp->rx_mode && bp->vlgrp) {
+ if (bp->rx_mode && bp->vlgrp && (bp->flags & HW_VLAN_RX_FLAG)) {
tstorm_client.config_flags |=
TSTORM_ETH_CLIENT_CONFIG_VLAN_REMOVAL_ENABLE;
DP(NETIF_MSG_IFUP, "vlan removal enabled\n");
@@ -4531,7 +4575,7 @@ static void bnx2x_set_client_config(struct bnx2x *bp)
if (bp->flags & TPA_ENABLE_FLAG) {
tstorm_client.max_sges_for_packet =
- BCM_PAGE_ALIGN(tstorm_client.mtu) >> BCM_PAGE_SHIFT;
+ SGE_PAGE_ALIGN(tstorm_client.mtu) >> SGE_PAGE_SHIFT;
tstorm_client.max_sges_for_packet =
((tstorm_client.max_sges_for_packet +
PAGES_PER_SGE - 1) & (~(PAGES_PER_SGE - 1))) >>
@@ -4714,10 +4758,11 @@ static void bnx2x_init_internal_func(struct bnx2x *bp)
bp->e1hov);
}
- /* Init CQ ring mapping and aggregation size */
- max_agg_size = min((u32)(bp->rx_buf_size +
- 8*BCM_PAGE_SIZE*PAGES_PER_SGE),
- (u32)0xffff);
+ /* Init CQ ring mapping and aggregation size, the FW limit is 8 frags */
+ max_agg_size =
+ min((u32)(min((u32)8, (u32)MAX_SKB_FRAGS) *
+ SGE_PAGE_SIZE * PAGES_PER_SGE),
+ (u32)0xffff);
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
@@ -4785,6 +4830,15 @@ static void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
bnx2x_init_context(bp);
bnx2x_init_internal(bp, load_code);
bnx2x_init_ind_table(bp);
+ bnx2x_stats_init(bp);
+
+ /* At this point, we are ready for interrupts */
+ atomic_set(&bp->intr_sem, 0);
+
+ /* flush all before enabling interrupts */
+ mb();
+ mmiowb();
+
bnx2x_int_enable(bp);
}
@@ -5101,12 +5155,21 @@ static void enable_blocks_attention(struct bnx2x *bp)
}
+static void bnx2x_reset_common(struct bnx2x *bp)
+{
+ /* reset_common */
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
+ 0xd3ffff7f);
+ REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
+}
+
static int bnx2x_init_common(struct bnx2x *bp)
{
u32 val, i;
DP(BNX2X_MSG_MCP, "starting common init func %d\n", BP_FUNC(bp));
+ bnx2x_reset_common(bp);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc);
@@ -5134,7 +5197,6 @@ static int bnx2x_init_common(struct bnx2x *bp)
REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
- REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 1);
/* REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
@@ -5212,6 +5274,7 @@ static int bnx2x_init_common(struct bnx2x *bp)
}
bnx2x_init_block(bp, PRS_COMMON_START, PRS_COMMON_END);
+ REG_WR(bp, PRS_REG_A_PRSU_20, 0xf);
/* set NIC mode */
REG_WR(bp, PRS_REG_NIC_MODE, 1);
if (CHIP_IS_E1H(bp))
@@ -6087,8 +6150,8 @@ static void bnx2x_netif_start(struct bnx2x *bp)
static void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
{
bnx2x_int_disable_sync(bp, disable_hw);
+ bnx2x_napi_disable(bp);
if (netif_running(bp->dev)) {
- bnx2x_napi_disable(bp);
netif_tx_disable(bp->dev);
bp->dev->trans_start = jiffies; /* prevent tx timeout */
}
@@ -6108,7 +6171,7 @@ static void bnx2x_set_mac_addr_e1(struct bnx2x *bp, int set)
* multicast 64-127:port0 128-191:port1
*/
config->hdr.length_6b = 2;
- config->hdr.offset = port ? 31 : 0;
+ config->hdr.offset = port ? 32 : 0;
config->hdr.client_id = BP_CL_ID(bp);
config->hdr.reserved1 = 0;
@@ -6272,7 +6335,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev);
static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
u32 load_code;
- int i, rc;
+ int i, rc = 0;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
return -EPERM;
@@ -6280,48 +6343,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
- /* Send LOAD_REQUEST command to MCP
- Returns the type of LOAD command:
- if it is the first port to be initialized
- common blocks should be initialized, otherwise - not
- */
- if (!BP_NOMCP(bp)) {
- load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
- if (!load_code) {
- BNX2X_ERR("MCP response failure, aborting\n");
- return -EBUSY;
- }
- if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED)
- return -EBUSY; /* other port in diagnostic mode */
-
- } else {
- int port = BP_PORT(bp);
-
- DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n",
- load_count[0], load_count[1], load_count[2]);
- load_count[0]++;
- load_count[1 + port]++;
- DP(NETIF_MSG_IFUP, "NO MCP new load counts %d, %d, %d\n",
- load_count[0], load_count[1], load_count[2]);
- if (load_count[0] == 1)
- load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
- else if (load_count[1 + port] == 1)
- load_code = FW_MSG_CODE_DRV_LOAD_PORT;
- else
- load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
- }
-
- if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
- (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
- bp->port.pmf = 1;
- else
- bp->port.pmf = 0;
- DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
-
- /* if we can't use MSI-X we only need one fp,
- * so try to enable MSI-X with the requested number of fp's
- * and fallback to inta with one fp
- */
if (use_inta) {
bp->num_queues = 1;
@@ -6336,7 +6357,15 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
else
bp->num_queues = 1;
- if (bnx2x_enable_msix(bp)) {
+ DP(NETIF_MSG_IFUP,
+ "set number of queues to %d\n", bp->num_queues);
+
+ /* if we can't use MSI-X we only need one fp,
+ * so try to enable MSI-X with the requested number of fp's
+ * and fallback to MSI or legacy INTx with one fp
+ */
+ rc = bnx2x_enable_msix(bp);
+ if (rc) {
/* failed to enable MSI-X */
bp->num_queues = 1;
if (use_multi)
@@ -6344,8 +6373,6 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
" to enable MSI-X\n");
}
}
- DP(NETIF_MSG_IFUP,
- "set number of queues to %d\n", bp->num_queues);
if (bnx2x_alloc_mem(bp))
return -ENOMEM;
@@ -6354,30 +6381,85 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
bnx2x_fp(bp, i, disable_tpa) =
((bp->flags & TPA_ENABLE_FLAG) == 0);
+ for_each_queue(bp, i)
+ netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+ bnx2x_poll, 128);
+
+#ifdef BNX2X_STOP_ON_ERROR
+ for_each_queue(bp, i) {
+ struct bnx2x_fastpath *fp = &bp->fp[i];
+
+ fp->poll_no_work = 0;
+ fp->poll_calls = 0;
+ fp->poll_max_calls = 0;
+ fp->poll_complete = 0;
+ fp->poll_exit = 0;
+ }
+#endif
+ bnx2x_napi_enable(bp);
+
if (bp->flags & USING_MSIX_FLAG) {
rc = bnx2x_req_msix_irqs(bp);
if (rc) {
pci_disable_msix(bp->pdev);
- goto load_error;
+ goto load_error1;
}
+ printk(KERN_INFO PFX "%s: using MSI-X\n", bp->dev->name);
} else {
bnx2x_ack_int(bp);
rc = bnx2x_req_irq(bp);
if (rc) {
- BNX2X_ERR("IRQ request failed, aborting\n");
- goto load_error;
+ BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc);
+ goto load_error1;
}
}
- for_each_queue(bp, i)
- netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
- bnx2x_poll, 128);
+ /* Send LOAD_REQUEST command to MCP
+ Returns the type of LOAD command:
+ if it is the first port to be initialized
+ common blocks should be initialized, otherwise - not
+ */
+ if (!BP_NOMCP(bp)) {
+ load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ);
+ if (!load_code) {
+ BNX2X_ERR("MCP response failure, aborting\n");
+ rc = -EBUSY;
+ goto load_error2;
+ }
+ if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) {
+ rc = -EBUSY; /* other port in diagnostic mode */
+ goto load_error2;
+ }
+
+ } else {
+ int port = BP_PORT(bp);
+
+ DP(NETIF_MSG_IFUP, "NO MCP load counts before us %d, %d, %d\n",
+ load_count[0], load_count[1], load_count[2]);
+ load_count[0]++;
+ load_count[1 + port]++;
+ DP(NETIF_MSG_IFUP, "NO MCP new load counts %d, %d, %d\n",
+ load_count[0], load_count[1], load_count[2]);
+ if (load_count[0] == 1)
+ load_code = FW_MSG_CODE_DRV_LOAD_COMMON;
+ else if (load_count[1 + port] == 1)
+ load_code = FW_MSG_CODE_DRV_LOAD_PORT;
+ else
+ load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION;
+ }
+
+ if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) ||
+ (load_code == FW_MSG_CODE_DRV_LOAD_PORT))
+ bp->port.pmf = 1;
+ else
+ bp->port.pmf = 0;
+ DP(NETIF_MSG_LINK, "pmf %d\n", bp->port.pmf);
/* Initialize HW */
rc = bnx2x_init_hw(bp, load_code);
if (rc) {
BNX2X_ERR("HW init failed, aborting\n");
- goto load_int_disable;
+ goto load_error2;
}
/* Setup NIC internals and enable interrupts */
@@ -6389,25 +6471,16 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
if (!load_code) {
BNX2X_ERR("MCP response failure, aborting\n");
rc = -EBUSY;
- goto load_rings_free;
+ goto load_error3;
}
}
- bnx2x_stats_init(bp);
-
bp->state = BNX2X_STATE_OPENING_WAIT4_PORT;
- /* Enable Rx interrupt handling before sending the ramrod
- as it's completed on Rx FP queue */
- bnx2x_napi_enable(bp);
-
- /* Enable interrupt handling */
- atomic_set(&bp->intr_sem, 0);
-
rc = bnx2x_setup_leading(bp);
if (rc) {
BNX2X_ERR("Setup leading failed!\n");
- goto load_netif_stop;
+ goto load_error3;
}
if (CHIP_IS_E1H(bp))
@@ -6420,7 +6493,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
for_each_nondefault_queue(bp, i) {
rc = bnx2x_setup_multi(bp, i);
if (rc)
- goto load_netif_stop;
+ goto load_error3;
}
if (CHIP_IS_E1(bp))
@@ -6436,18 +6509,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
case LOAD_NORMAL:
/* Tx queue should be only reenabled */
netif_wake_queue(bp->dev);
+ /* Initialize the receive filter. */
bnx2x_set_rx_mode(bp->dev);
break;
case LOAD_OPEN:
netif_start_queue(bp->dev);
+ /* Initialize the receive filter. */
bnx2x_set_rx_mode(bp->dev);
- if (bp->flags & USING_MSIX_FLAG)
- printk(KERN_INFO PFX "%s: using MSI-X\n",
- bp->dev->name);
break;
case LOAD_DIAG:
+ /* Initialize the receive filter. */
bnx2x_set_rx_mode(bp->dev);
bp->state = BNX2X_STATE_DIAG;
break;
@@ -6465,20 +6538,25 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
return 0;
-load_netif_stop:
- bnx2x_napi_disable(bp);
-load_rings_free:
+load_error3:
+ bnx2x_int_disable_sync(bp, 1);
+ if (!BP_NOMCP(bp)) {
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP);
+ bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+ }
+ bp->port.pmf = 0;
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
-load_int_disable:
- bnx2x_int_disable_sync(bp, 1);
+load_error2:
/* Release IRQs */
bnx2x_free_irq(bp);
-load_error:
+load_error1:
+ bnx2x_napi_disable(bp);
+ for_each_queue(bp, i)
+ netif_napi_del(&bnx2x_fp(bp, i, napi));
bnx2x_free_mem(bp);
- bp->port.pmf = 0;
/* TBD we really need to reset the chip
if we want to recover from this */
@@ -6551,6 +6629,7 @@ static int bnx2x_stop_leading(struct bnx2x *bp)
}
cnt--;
msleep(1);
+ rmb(); /* Refresh the dsb_sp_prod */
}
bp->state = BNX2X_STATE_CLOSING_WAIT4_UNLOAD;
bp->fp[0].state = BNX2X_FP_STATE_CLOSED;
@@ -6602,14 +6681,6 @@ static void bnx2x_reset_port(struct bnx2x *bp)
/* TODO: Close Doorbell port? */
}
-static void bnx2x_reset_common(struct bnx2x *bp)
-{
- /* reset_common */
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
- 0xd3ffff7f);
- REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
-}
-
static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code)
{
DP(BNX2X_MSG_MCP, "function %d reset_code %x\n",
@@ -6650,20 +6721,22 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
bnx2x_set_storm_rx_mode(bp);
bnx2x_netif_stop(bp, 1);
- if (!netif_running(bp->dev))
- bnx2x_napi_disable(bp);
+
del_timer_sync(&bp->timer);
SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb,
(DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq));
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
+ /* Release IRQs */
+ bnx2x_free_irq(bp);
+
/* Wait until tx fast path tasks complete */
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
cnt = 1000;
smp_rmb();
- while (BNX2X_HAS_TX_WORK(fp)) {
+ while (bnx2x_has_tx_work_unload(fp)) {
bnx2x_tx_int(fp, 1000);
if (!cnt) {
@@ -6684,9 +6757,6 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
/* Give HW time to discard old tx messages */
msleep(1);
- /* Release IRQs */
- bnx2x_free_irq(bp);
-
if (CHIP_IS_E1(bp)) {
struct mac_configuration_cmd *config =
bnx2x_sp(bp, mcast_config);
@@ -6795,6 +6865,8 @@ unload_error:
bnx2x_free_skbs(bp);
for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
+ for_each_queue(bp, i)
+ netif_napi_del(&bnx2x_fp(bp, i, napi));
bnx2x_free_mem(bp);
bp->state = BNX2X_STATE_CLOSED;
@@ -6847,10 +6919,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
*/
bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
- if (val == 0x7)
- REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
-
if (val == 0x7) {
u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
/* save our func */
@@ -6858,6 +6926,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
u32 swap_en;
u32 swap_val;
+ /* clear the UNDI indication */
+ REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
+
BNX2X_DEV_INFO("UNDI is active! reset device\n");
/* try unload UNDI on port 0 */
@@ -6883,6 +6954,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
bnx2x_fw_command(bp, reset_code);
}
+ /* now it's safe to release the lock */
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
+
REG_WR(bp, (BP_PORT(bp) ? HC_REG_CONFIG_1 :
HC_REG_CONFIG_0), 0x1000);
@@ -6927,7 +7001,9 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
bp->fw_seq =
(SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) &
DRV_MSG_SEQ_NUMBER_MASK);
- }
+
+ } else
+ bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI);
}
}
@@ -6944,7 +7020,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
id |= ((val & 0xf) << 12);
val = REG_RD(bp, MISC_REG_CHIP_METAL);
id |= ((val & 0xff) << 4);
- REG_RD(bp, MISC_REG_BOND_ID);
+ val = REG_RD(bp, MISC_REG_BOND_ID);
id |= (val & 0xf);
bp->common.chip_id = id;
bp->link_params.chip_id = bp->common.chip_id;
@@ -7501,7 +7577,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
mutex_init(&bp->port.phy_mutex);
- INIT_WORK(&bp->sp_task, bnx2x_sp_task);
+ INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
INIT_WORK(&bp->reset_task, bnx2x_reset_task);
rc = bnx2x_get_hwinfo(bp);
@@ -8076,6 +8152,9 @@ static int bnx2x_get_eeprom(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
int rc;
+ if (!netif_running(dev))
+ return -EAGAIN;
+
DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
@@ -8243,6 +8322,9 @@ static int bnx2x_set_eeprom(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
int rc;
+ if (!netif_running(dev))
+ return -EAGAIN;
+
DP(BNX2X_MSG_NVM, "ethtool_eeprom: cmd %d\n"
DP_LEVEL " magic 0x%x offset 0x%x (%d) len 0x%x (%d)\n",
eeprom->cmd, eeprom->magic, eeprom->offset, eeprom->offset,
@@ -8675,18 +8757,17 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
if (loopback_mode == BNX2X_MAC_LOOPBACK) {
bp->link_params.loopback_mode = LOOPBACK_BMAC;
- bnx2x_acquire_phy_lock(bp);
bnx2x_phy_init(&bp->link_params, &bp->link_vars);
- bnx2x_release_phy_lock(bp);
} else if (loopback_mode == BNX2X_PHY_LOOPBACK) {
+ u16 cnt = 1000;
bp->link_params.loopback_mode = LOOPBACK_XGXS_10;
- bnx2x_acquire_phy_lock(bp);
bnx2x_phy_init(&bp->link_params, &bp->link_vars);
- bnx2x_release_phy_lock(bp);
/* wait until link state is restored */
- bnx2x_wait_for_link(bp, link_up);
-
+ if (link_up)
+ while (cnt-- && bnx2x_test_link(&bp->link_params,
+ &bp->link_vars))
+ msleep(10);
} else
return -EINVAL;
@@ -8724,6 +8805,8 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
tx_bd->general_data = ((UNICAST_ADDRESS <<
ETH_TX_BD_ETH_ADDR_TYPE_SHIFT) | 1);
+ wmb();
+
fp->hw_tx_prods->bds_prod =
cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + 1);
mb(); /* FW restriction: must not reorder writing nbd and packets */
@@ -8775,7 +8858,6 @@ test_loopback_rx_exit:
/* Update producers */
bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
fp->rx_sge_prod);
- mmiowb(); /* keep prod updates ordered */
test_loopback_exit:
bp->link_params.loopback_mode = LOOPBACK_NONE;
@@ -8791,6 +8873,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
return BNX2X_LOOPBACK_FAILED;
bnx2x_netif_stop(bp, 1);
+ bnx2x_acquire_phy_lock(bp);
if (bnx2x_run_loopback(bp, BNX2X_MAC_LOOPBACK, link_up)) {
DP(NETIF_MSG_PROBE, "MAC loopback failed\n");
@@ -8802,6 +8885,7 @@ static int bnx2x_test_loopback(struct bnx2x *bp, u8 link_up)
rc |= BNX2X_PHY_LOOPBACK_FAILED;
}
+ bnx2x_release_phy_lock(bp);
bnx2x_netif_start(bp);
return rc;
@@ -8875,7 +8959,10 @@ static int bnx2x_test_intr(struct bnx2x *bp)
return -ENODEV;
config->hdr.length_6b = 0;
- config->hdr.offset = 0;
+ if (CHIP_IS_E1(bp))
+ config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
+ else
+ config->hdr.offset = BP_FUNC(bp);
config->hdr.client_id = BP_CL_ID(bp);
config->hdr.reserved1 = 0;
@@ -9240,6 +9327,18 @@ static int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state)
return 0;
}
+static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
+{
+ u16 rx_cons_sb;
+
+ /* Tell compiler that status block fields can change */
+ barrier();
+ rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
+ if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
+ rx_cons_sb++;
+ return (fp->rx_comp_cons != rx_cons_sb);
+}
+
/*
* net_device service functions
*/
@@ -9250,7 +9349,6 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
napi);
struct bnx2x *bp = fp->bp;
int work_done = 0;
- u16 rx_cons_sb;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
@@ -9263,19 +9361,12 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
bnx2x_update_fpsb_idx(fp);
- if (BNX2X_HAS_TX_WORK(fp))
+ if (bnx2x_has_tx_work(fp))
bnx2x_tx_int(fp, budget);
- rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
- if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
- rx_cons_sb++;
- if (BNX2X_HAS_RX_WORK(fp))
+ if (bnx2x_has_rx_work(fp))
work_done = bnx2x_rx_int(fp, budget);
-
rmb(); /* BNX2X_HAS_WORK() reads the status block */
- rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
- if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
- rx_cons_sb++;
/* must not complete if we consumed full budget */
if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) {
@@ -9386,6 +9477,7 @@ static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
return rc;
}
+#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3)
/* check if packet requires linearization (packet is too fragmented) */
static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb,
u32 xmit_type)
@@ -9463,6 +9555,7 @@ exit_lbl:
return to_copy;
}
+#endif
/* called with netif_tx_lock
* bnx2x_tx_int() runs without netif_tx_lock unless it needs to call
@@ -9503,6 +9596,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
skb->ip_summed, skb->protocol, ipv6_hdr(skb)->nexthdr,
ip_hdr(skb)->protocol, skb_shinfo(skb)->gso_type, xmit_type);
+#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3)
/* First, check if we need to linearize the skb
(due to FW restrictions) */
if (bnx2x_pkt_req_lin(bp, skb, xmit_type)) {
@@ -9515,6 +9609,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
}
+#endif
/*
Please read carefully. First we use one BD which we mark as start,
@@ -9546,11 +9641,14 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
"sending pkt %u @%p next_idx %u bd %u @%p\n",
pkt_prod, tx_buf, fp->tx_pkt_prod, bd_prod, tx_bd);
- if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb)) {
+#ifdef BCM_VLAN
+ if ((bp->vlgrp != NULL) && vlan_tx_tag_present(skb) &&
+ (bp->flags & HW_VLAN_TX_FLAG)) {
tx_bd->vlan = cpu_to_le16(vlan_tx_tag_get(skb));
tx_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_VLAN_TAG;
vlan_off += 4;
} else
+#endif
tx_bd->vlan = cpu_to_le16(pkt_prod);
if (xmit_type) {
@@ -9702,6 +9800,15 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
DP(NETIF_MSG_TX_QUEUED, "doorbell: nbd %d bd %u\n", nbd, bd_prod);
+ /*
+ * Make sure that the BD data is updated before updating the producer
+ * since FW might read the BD right after the producer is updated.
+ * This is only applicable for weak-ordered memory model archs such
+ * as IA-64. The following barrier is also mandatory since FW will
+ * assumes packets must have BDs.
+ */
+ wmb();
+
fp->hw_tx_prods->bds_prod =
cpu_to_le16(le16_to_cpu(fp->hw_tx_prods->bds_prod) + nbd);
mb(); /* FW restriction: must not reorder writing nbd and packets */
@@ -9715,6 +9822,9 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
+ /* We want bnx2x_tx_int to "see" the updated tx_bd_prod
+ if we put Tx into XOFF state. */
+ smp_mb();
netif_stop_queue(dev);
bp->eth_stats.driver_xoff++;
if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)
@@ -9730,6 +9840,8 @@ static int bnx2x_open(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
+ netif_carrier_off(dev);
+
bnx2x_set_power_state(bp, PCI_D0);
return bnx2x_nic_load(bp, LOAD_OPEN);
@@ -9813,7 +9925,7 @@ static void bnx2x_set_rx_mode(struct net_device *dev)
for (; i < old; i++) {
if (CAM_IS_INVALID(config->
config_table[i])) {
- i--; /* already invalidated */
+ /* already invalidated */
break;
}
/* invalidate */
@@ -9984,6 +10096,16 @@ static void bnx2x_vlan_rx_register(struct net_device *dev,
struct bnx2x *bp = netdev_priv(dev);
bp->vlgrp = vlgrp;
+
+ /* Set flags according to the required capabilities */
+ bp->flags &= ~(HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
+
+ if (dev->features & NETIF_F_HW_VLAN_TX)
+ bp->flags |= HW_VLAN_TX_FLAG;
+
+ if (dev->features & NETIF_F_HW_VLAN_RX)
+ bp->flags |= HW_VLAN_RX_FLAG;
+
if (netif_running(dev))
bnx2x_set_client_config(bp);
}
@@ -10140,6 +10262,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->features |= NETIF_F_HIGHDMA;
#ifdef BCM_VLAN
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
+ bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
#endif
dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
dev->features |= NETIF_F_TSO6;
@@ -10212,22 +10335,18 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
return rc;
}
- rc = register_netdev(dev);
- if (rc) {
- dev_err(&pdev->dev, "Cannot register net device\n");
- goto init_one_exit;
- }
-
pci_set_drvdata(pdev, dev);
rc = bnx2x_init_bp(bp);
+ if (rc)
+ goto init_one_exit;
+
+ rc = register_netdev(dev);
if (rc) {
- unregister_netdev(dev);
+ dev_err(&pdev->dev, "Cannot register net device\n");
goto init_one_exit;
}
- netif_carrier_off(dev);
-
bp->common.name = board_info[ent->driver_data].name;
printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx,"
" IRQ %d, ", dev->name, bp->common.name,
@@ -10375,6 +10494,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
bnx2x_free_skbs(bp);
for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
+ for_each_queue(bp, i)
+ netif_napi_del(&bnx2x_fp(bp, i, napi));
bnx2x_free_mem(bp);
bp->state = BNX2X_STATE_CLOSED;
@@ -10516,12 +10637,20 @@ static struct pci_driver bnx2x_pci_driver = {
static int __init bnx2x_init(void)
{
+ bnx2x_wq = create_singlethread_workqueue("bnx2x");
+ if (bnx2x_wq == NULL) {
+ printk(KERN_ERR PFX "Cannot create workqueue\n");
+ return -ENOMEM;
+ }
+
return pci_register_driver(&bnx2x_pci_driver);
}
static void __exit bnx2x_cleanup(void)
{
pci_unregister_driver(&bnx2x_pci_driver);
+
+ destroy_workqueue(bnx2x_wq);
}
module_init(bnx2x_init);
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h
index a67b0c358ae4..d084e5fc4b51 100644
--- a/drivers/net/bnx2x_reg.h
+++ b/drivers/net/bnx2x_reg.h
@@ -1,6 +1,6 @@
/* bnx2x_reg.h: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2008 Broadcom Corporation
+ * Copyright (c) 2007-2009 Broadcom Corporation
*
* 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
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 460c2cad2755..9fb388388fb7 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4148,7 +4148,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
bond_for_each_slave(bond, slave, i) {
pr_debug("s %p s->p %p c_m %p\n", slave,
- slave->prev, slave->dev->change_mtu);
+ slave->prev, slave->dev->netdev_ops->ndo_change_mtu);
res = dev_set_mtu(slave->dev, new_mtu);
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 321f43d9f0e2..bbbc3bb08aa5 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -806,7 +806,7 @@ static int cas_reset_mii_phy(struct cas *cp)
cas_phy_write(cp, MII_BMCR, BMCR_RESET);
udelay(100);
- while (limit--) {
+ while (--limit) {
val = cas_phy_read(cp, MII_BMCR);
if ((val & BMCR_RESET) == 0)
break;
@@ -979,7 +979,7 @@ static void cas_phy_init(struct cas *cp)
writel(val, cp->regs + REG_PCS_MII_CTRL);
limit = STOP_TRIES;
- while (limit-- > 0) {
+ while (--limit > 0) {
udelay(10);
if ((readl(cp->regs + REG_PCS_MII_CTRL) &
PCS_MII_RESET) == 0)
@@ -4977,6 +4977,22 @@ static void __devinit cas_program_bridge(struct pci_dev *cas_pdev)
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xff);
}
+static const struct net_device_ops cas_netdev_ops = {
+ .ndo_open = cas_open,
+ .ndo_stop = cas_close,
+ .ndo_start_xmit = cas_start_xmit,
+ .ndo_get_stats = cas_get_stats,
+ .ndo_set_multicast_list = cas_set_multicast,
+ .ndo_do_ioctl = cas_ioctl,
+ .ndo_tx_timeout = cas_tx_timeout,
+ .ndo_change_mtu = cas_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = cas_netpoll,
+#endif
+};
+
static int __devinit cas_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -5166,22 +5182,13 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
for (i = 0; i < N_RX_FLOWS; i++)
skb_queue_head_init(&cp->rx_flows[i]);
- dev->open = cas_open;
- dev->stop = cas_close;
- dev->hard_start_xmit = cas_start_xmit;
- dev->get_stats = cas_get_stats;
- dev->set_multicast_list = cas_set_multicast;
- dev->do_ioctl = cas_ioctl;
+ dev->netdev_ops = &cas_netdev_ops;
dev->ethtool_ops = &cas_ethtool_ops;
- dev->tx_timeout = cas_tx_timeout;
dev->watchdog_timeo = CAS_TX_TIMEOUT;
- dev->change_mtu = cas_change_mtu;
+
#ifdef USE_NAPI
netif_napi_add(dev, &cp->napi, cas_poll, 64);
#endif
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = cas_netpoll;
-#endif
dev->irq = pdev->irq;
dev->dma = 0;
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 5b346f9eaa8b..a89d8cc51205 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -50,12 +50,17 @@ struct vlan_group;
struct adapter;
struct sge_qset;
+enum { /* rx_offload flags */
+ T3_RX_CSUM = 1 << 0,
+ T3_LRO = 1 << 1,
+};
+
struct port_info {
struct adapter *adapter;
struct vlan_group *vlan_grp;
struct sge_qset *qs;
u8 port_id;
- u8 rx_csum_offload;
+ u8 rx_offload;
u8 nqsets;
u8 first_qset;
struct cphy phy;
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 2847f947499d..0089746b8d02 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -546,7 +546,7 @@ static int setup_sge_qsets(struct adapter *adap)
pi->qs = &adap->sge.qs[pi->first_qset];
for (j = pi->first_qset; j < pi->first_qset + pi->nqsets;
++j, ++qset_idx) {
- set_qset_lro(dev, qset_idx, pi->rx_csum_offload);
+ set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO);
err = t3_sge_alloc_qset(adap, qset_idx, 1,
(adap->flags & USING_MSIX) ? qset_idx + 1 :
irq_idx,
@@ -1657,17 +1657,19 @@ static u32 get_rx_csum(struct net_device *dev)
{
struct port_info *p = netdev_priv(dev);
- return p->rx_csum_offload;
+ return p->rx_offload & T3_RX_CSUM;
}
static int set_rx_csum(struct net_device *dev, u32 data)
{
struct port_info *p = netdev_priv(dev);
- p->rx_csum_offload = data;
- if (!data) {
+ if (data) {
+ p->rx_offload |= T3_RX_CSUM;
+ } else {
int i;
+ p->rx_offload &= ~(T3_RX_CSUM | T3_LRO);
for (i = p->first_qset; i < p->first_qset + p->nqsets; i++)
set_qset_lro(dev, i, 0);
}
@@ -1830,15 +1832,18 @@ static int cxgb3_set_flags(struct net_device *dev, u32 data)
int i;
if (data & ETH_FLAG_LRO) {
- if (!pi->rx_csum_offload)
+ if (!(pi->rx_offload & T3_RX_CSUM))
return -EINVAL;
+ pi->rx_offload |= T3_LRO;
for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
set_qset_lro(dev, i, 1);
- } else
+ } else {
+ pi->rx_offload &= ~T3_LRO;
for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
set_qset_lro(dev, i, 0);
+ }
return 0;
}
@@ -1926,7 +1931,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
pi = adap2pinfo(adapter, i);
if (t.qset_idx >= pi->first_qset &&
t.qset_idx < pi->first_qset + pi->nqsets &&
- !pi->rx_csum_offload)
+ !(pi->rx_offload & T3_RX_CSUM))
return -EINVAL;
}
@@ -2946,7 +2951,7 @@ static int __devinit init_one(struct pci_dev *pdev,
adapter->port[i] = netdev;
pi = netdev_priv(netdev);
pi->adapter = adapter;
- pi->rx_csum_offload = 1;
+ pi->rx_offload = T3_RX_CSUM | T3_LRO;
pi->port_id = i;
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
@@ -2955,6 +2960,7 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->mem_end = mmio_start + mmio_len - 1;
netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
netdev->features |= NETIF_F_LLTX;
+ netdev->features |= NETIF_F_LRO;
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 6c641a889471..379a1324db4e 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -1932,7 +1932,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
skb_pull(skb, sizeof(*p) + pad);
skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
pi = netdev_priv(skb->dev);
- if (pi->rx_csum_offload && p->csum_valid && p->csum == htons(0xffff) &&
+ if ((pi->rx_offload & T3_RX_CSUM) && p->csum_valid && p->csum == htons(0xffff) &&
!p->fragment) {
qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2104,6 +2104,7 @@ static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr)
{
lro_mgr->dev = qs->netdev;
lro_mgr->features = LRO_F_NAPI;
+ lro_mgr->frag_align_pad = NET_IP_ALIGN;
lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
lro_mgr->max_desc = T3_MAX_LRO_SES;
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index 970f820ba814..de63f1d41d32 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -378,6 +378,16 @@ static void de600_rx_intr(struct net_device *dev)
*/
}
+static const struct net_device_ops de600_netdev_ops = {
+ .ndo_open = de600_open,
+ .ndo_stop = de600_close,
+ .ndo_start_xmit = de600_start_xmit,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+
static struct net_device * __init de600_probe(void)
{
int i;
@@ -439,9 +449,7 @@ static struct net_device * __init de600_probe(void)
printk(", Ethernet Address: %pM\n", dev->dev_addr);
- dev->open = de600_open;
- dev->stop = de600_close;
- dev->hard_start_xmit = &de600_start_xmit;
+ dev->netdev_ops = &de600_netdev_ops;
dev->flags&=~IFF_MULTICAST;
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index bdfa89403389..d52f34cc9526 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -784,6 +784,17 @@ static int adapter_init(struct net_device *dev)
return 0; /* all ok */
}
+static const struct net_device_ops de620_netdev_ops = {
+ .ndo_open = de620_open,
+ .ndo_stop = de620_close,
+ .ndo_start_xmit = de620_start_xmit,
+ .ndo_tx_timeout = de620_timeout,
+ .ndo_set_multicast_list = de620_set_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
/******************************************************************************
*
* Only start-up code below
@@ -861,12 +872,8 @@ struct net_device * __init de620_probe(int unit)
else
printk(" UTP)\n");
- dev->open = de620_open;
- dev->stop = de620_close;
- dev->hard_start_xmit = de620_start_xmit;
- dev->tx_timeout = de620_timeout;
+ dev->netdev_ops = &de620_netdev_ops;
dev->watchdog_timeo = HZ*2;
- dev->set_multicast_list = de620_set_multicast_list;
/* base_addr and irq are already set, see above! */
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 9f38b16ccbbd..86bb876fb123 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -161,6 +161,7 @@
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/string.h>
+#include <linux/firmware.h>
#include <asm/unaligned.h>
@@ -174,10 +175,17 @@
#define E100_WATCHDOG_PERIOD (2 * HZ)
#define E100_NAPI_WEIGHT 16
+#define FIRMWARE_D101M "e100/d101m_ucode.bin"
+#define FIRMWARE_D101S "e100/d101s_ucode.bin"
+#define FIRMWARE_D102E "e100/d102e_ucode.bin"
+
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+MODULE_FIRMWARE(FIRMWARE_D101M);
+MODULE_FIRMWARE(FIRMWARE_D101S);
+MODULE_FIRMWARE(FIRMWARE_D102E);
static int debug = 3;
static int eeprom_bad_csum_allow = 0;
@@ -658,12 +666,12 @@ static int e100_self_test(struct nic *nic)
e100_disable_irq(nic);
/* Check results of self-test */
- if(nic->mem->selftest.result != 0) {
+ if (nic->mem->selftest.result != 0) {
DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n",
nic->mem->selftest.result);
return -ETIMEDOUT;
}
- if(nic->mem->selftest.signature == 0) {
+ if (nic->mem->selftest.signature == 0) {
DPRINTK(HW, ERR, "Self-test failed: timed out\n");
return -ETIMEDOUT;
}
@@ -684,13 +692,13 @@ static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, __le16 da
cmd_addr_data[2] = op_ewds << (addr_len - 2);
/* Bit-bang cmds to write word to eeprom */
- for(j = 0; j < 3; j++) {
+ for (j = 0; j < 3; j++) {
/* Chip select */
iowrite8(eecs | eesk, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
- for(i = 31; i >= 0; i--) {
+ for (i = 31; i >= 0; i--) {
ctrl = (cmd_addr_data[j] & (1 << i)) ?
eecs | eedi : eecs;
iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
@@ -723,7 +731,7 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
e100_write_flush(nic); udelay(4);
/* Bit-bang to read word from eeprom */
- for(i = 31; i >= 0; i--) {
+ for (i = 31; i >= 0; i--) {
ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs;
iowrite8(ctrl, &nic->csr->eeprom_ctrl_lo);
e100_write_flush(nic); udelay(4);
@@ -734,7 +742,7 @@ static __le16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr)
/* Eeprom drives a dummy zero to EEDO after receiving
* complete address. Use this to adjust addr_len. */
ctrl = ioread8(&nic->csr->eeprom_ctrl_lo);
- if(!(ctrl & eedo) && i > 16) {
+ if (!(ctrl & eedo) && i > 16) {
*addr_len -= (i - 16);
i = 17;
}
@@ -758,9 +766,9 @@ static int e100_eeprom_load(struct nic *nic)
e100_eeprom_read(nic, &addr_len, 0);
nic->eeprom_wc = 1 << addr_len;
- for(addr = 0; addr < nic->eeprom_wc; addr++) {
+ for (addr = 0; addr < nic->eeprom_wc; addr++) {
nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr);
- if(addr < nic->eeprom_wc - 1)
+ if (addr < nic->eeprom_wc - 1)
checksum += le16_to_cpu(nic->eeprom[addr]);
}
@@ -784,15 +792,15 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
e100_eeprom_read(nic, &addr_len, 0);
nic->eeprom_wc = 1 << addr_len;
- if(start + count >= nic->eeprom_wc)
+ if (start + count >= nic->eeprom_wc)
return -EINVAL;
- for(addr = start; addr < start + count; addr++)
+ for (addr = start; addr < start + count; addr++)
e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]);
/* The checksum, stored in the last word, is calculated such that
* the sum of words should be 0xBABA */
- for(addr = 0; addr < nic->eeprom_wc - 1; addr++)
+ for (addr = 0; addr < nic->eeprom_wc - 1; addr++)
checksum += le16_to_cpu(nic->eeprom[addr]);
nic->eeprom[nic->eeprom_wc - 1] = cpu_to_le16(0xBABA - checksum);
e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
@@ -812,19 +820,19 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
spin_lock_irqsave(&nic->cmd_lock, flags);
/* Previous command is accepted when SCB clears */
- for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
- if(likely(!ioread8(&nic->csr->scb.cmd_lo)))
+ for (i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) {
+ if (likely(!ioread8(&nic->csr->scb.cmd_lo)))
break;
cpu_relax();
- if(unlikely(i > E100_WAIT_SCB_FAST))
+ if (unlikely(i > E100_WAIT_SCB_FAST))
udelay(5);
}
- if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
+ if (unlikely(i == E100_WAIT_SCB_TIMEOUT)) {
err = -EAGAIN;
goto err_unlock;
}
- if(unlikely(cmd != cuc_resume))
+ if (unlikely(cmd != cuc_resume))
iowrite32(dma_addr, &nic->csr->scb.gen_ptr);
iowrite8(cmd, &nic->csr->scb.cmd_lo);
@@ -843,7 +851,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
spin_lock_irqsave(&nic->cb_lock, flags);
- if(unlikely(!nic->cbs_avail)) {
+ if (unlikely(!nic->cbs_avail)) {
err = -ENOMEM;
goto err_unlock;
}
@@ -853,7 +861,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
nic->cbs_avail--;
cb->skb = skb;
- if(unlikely(!nic->cbs_avail))
+ if (unlikely(!nic->cbs_avail))
err = -ENOSPC;
cb_prepare(nic, cb, skb);
@@ -864,15 +872,15 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
wmb();
cb->prev->command &= cpu_to_le16(~cb_s);
- while(nic->cb_to_send != nic->cb_to_use) {
- if(unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
+ while (nic->cb_to_send != nic->cb_to_use) {
+ if (unlikely(e100_exec_cmd(nic, nic->cuc_cmd,
nic->cb_to_send->dma_addr))) {
/* Ok, here's where things get sticky. It's
* possible that we can't schedule the command
* because the controller is too busy, so
* let's just queue the command and try again
* when another command is scheduled. */
- if(err == -ENOSPC) {
+ if (err == -ENOSPC) {
//request a reset
schedule_work(&nic->tx_timeout_task);
}
@@ -945,7 +953,7 @@ static void e100_get_defaults(struct nic *nic)
/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
- if(nic->mac == mac_unknown)
+ if (nic->mac == mac_unknown)
nic->mac = mac_82557_D100_A;
nic->params.rfds = rfds;
@@ -1008,23 +1016,23 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
config->adaptive_ifs = nic->adaptive_ifs;
config->loopback = nic->loopback;
- if(nic->mii.force_media && nic->mii.full_duplex)
+ if (nic->mii.force_media && nic->mii.full_duplex)
config->full_duplex_force = 0x1; /* 1=force, 0=auto */
- if(nic->flags & promiscuous || nic->loopback) {
+ if (nic->flags & promiscuous || nic->loopback) {
config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */
config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */
config->promiscuous_mode = 0x1; /* 1=on, 0=off */
}
- if(nic->flags & multicast_all)
+ if (nic->flags & multicast_all)
config->multicast_all = 0x1; /* 1=accept, 0=no */
/* disable WoL when up */
- if(netif_running(nic->netdev) || !(nic->flags & wol_magic))
+ if (netif_running(nic->netdev) || !(nic->flags & wol_magic))
config->magic_packet_disable = 0x1; /* 1=off, 0=on */
- if(nic->mac >= mac_82558_D101_A4) {
+ if (nic->mac >= mac_82558_D101_A4) {
config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */
config->mwi_enable = 0x1; /* 1=enable, 0=disable */
config->standard_tcb = 0x0; /* 1=standard, 0=extended */
@@ -1049,178 +1057,6 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
}
-/********************************************************/
-/* Micro code for 8086:1229 Rev 8 */
-/********************************************************/
-
-/* Parameter values for the D101M B-step */
-#define D101M_CPUSAVER_TIMER_DWORD 78
-#define D101M_CPUSAVER_BUNDLE_DWORD 65
-#define D101M_CPUSAVER_MIN_SIZE_DWORD 126
-
-#define D101M_B_RCVBUNDLE_UCODE \
-{\
-0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \
-0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \
-0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \
-0x00380438, 0x00000000, 0x00140000, 0x00380555, \
-0x00308000, 0x00100662, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \
-0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \
-0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \
-0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \
-0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \
-0x00041000, 0x00010004, 0x00130826, 0x000C0006, \
-0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380C34, 0x00000000, 0x00000000, \
-0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \
-0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \
-0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \
-0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \
-0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \
-0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \
-0x00130826, 0x000C0001, 0x00220559, 0x00101313, \
-0x00380559, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00130831, 0x0010090B, 0x00124813, \
-0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \
-0x003806A8, 0x00000000, 0x00000000, 0x00000000, \
-}
-
-/********************************************************/
-/* Micro code for 8086:1229 Rev 9 */
-/********************************************************/
-
-/* Parameter values for the D101S */
-#define D101S_CPUSAVER_TIMER_DWORD 78
-#define D101S_CPUSAVER_BUNDLE_DWORD 67
-#define D101S_CPUSAVER_MIN_SIZE_DWORD 128
-
-#define D101S_RCVBUNDLE_UCODE \
-{\
-0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \
-0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \
-0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \
-0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \
-0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \
-0x00308000, 0x00100610, 0x00100561, 0x000E0408, \
-0x00134861, 0x000C0002, 0x00103093, 0x00308000, \
-0x00100624, 0x00100561, 0x000E0408, 0x00100861, \
-0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \
-0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \
-0x003A047E, 0x00044010, 0x00380819, 0x00000000, \
-0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \
-0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \
-0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \
-0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \
-0x00101313, 0x00380700, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00080600, 0x00101B10, 0x00050004, 0x00100826, \
-0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \
-0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \
-0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \
-0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \
-0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \
-0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \
-0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \
-0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \
-0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00130831, \
-0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \
-0x00041000, 0x00010004, 0x00380700 \
-}
-
-/********************************************************/
-/* Micro code for the 8086:1229 Rev F/10 */
-/********************************************************/
-
-/* Parameter values for the D102 E-step */
-#define D102_E_CPUSAVER_TIMER_DWORD 42
-#define D102_E_CPUSAVER_BUNDLE_DWORD 54
-#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46
-
-#define D102_E_RCVBUNDLE_UCODE \
-{\
-0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \
-0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \
-0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
-0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
-0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
-0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \
-0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-0x00000000, 0x00000000, 0x00000000, 0x00000000, \
-}
-
-static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
-{
-/* *INDENT-OFF* */
- static struct {
- u32 ucode[UCODE_SIZE + 1];
- u8 mac;
- u8 timer_dword;
- u8 bundle_dword;
- u8 min_size_dword;
- } ucode_opts[] = {
- { D101M_B_RCVBUNDLE_UCODE,
- mac_82559_D101M,
- D101M_CPUSAVER_TIMER_DWORD,
- D101M_CPUSAVER_BUNDLE_DWORD,
- D101M_CPUSAVER_MIN_SIZE_DWORD },
- { D101S_RCVBUNDLE_UCODE,
- mac_82559_D101S,
- D101S_CPUSAVER_TIMER_DWORD,
- D101S_CPUSAVER_BUNDLE_DWORD,
- D101S_CPUSAVER_MIN_SIZE_DWORD },
- { D102_E_RCVBUNDLE_UCODE,
- mac_82551_F,
- D102_E_CPUSAVER_TIMER_DWORD,
- D102_E_CPUSAVER_BUNDLE_DWORD,
- D102_E_CPUSAVER_MIN_SIZE_DWORD },
- { D102_E_RCVBUNDLE_UCODE,
- mac_82551_10,
- D102_E_CPUSAVER_TIMER_DWORD,
- D102_E_CPUSAVER_BUNDLE_DWORD,
- D102_E_CPUSAVER_MIN_SIZE_DWORD },
- { {0}, 0, 0, 0, 0}
- }, *opts;
-/* *INDENT-ON* */
-
/*************************************************************************
* CPUSaver parameters
*
@@ -1280,42 +1116,101 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb
#define BUNDLEMAX (u16)6
#define INTDELAY (u16)1536 /* 0x600 */
+/* Initialize firmware */
+static const struct firmware *e100_request_firmware(struct nic *nic)
+{
+ const char *fw_name;
+ const struct firmware *fw;
+ u8 timer, bundle, min_size;
+ int err;
+
/* do not load u-code for ICH devices */
if (nic->flags & ich)
- goto noloaducode;
+ return NULL;
/* Search for ucode match against h/w revision */
- for (opts = ucode_opts; opts->mac; opts++) {
- int i;
- u32 *ucode = opts->ucode;
- if (nic->mac != opts->mac)
- continue;
-
- /* Insert user-tunable settings */
- ucode[opts->timer_dword] &= 0xFFFF0000;
- ucode[opts->timer_dword] |= INTDELAY;
- ucode[opts->bundle_dword] &= 0xFFFF0000;
- ucode[opts->bundle_dword] |= BUNDLEMAX;
- ucode[opts->min_size_dword] &= 0xFFFF0000;
- ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80;
-
- for (i = 0; i < UCODE_SIZE; i++)
- cb->u.ucode[i] = cpu_to_le32(ucode[i]);
- cb->command = cpu_to_le16(cb_ucode | cb_el);
- return;
- }
-
-noloaducode:
- cb->command = cpu_to_le16(cb_nop | cb_el);
-}
-
-static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb,
- void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
-{
+ if (nic->mac == mac_82559_D101M)
+ fw_name = FIRMWARE_D101M;
+ else if (nic->mac == mac_82559_D101S)
+ fw_name = FIRMWARE_D101S;
+ else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10)
+ fw_name = FIRMWARE_D102E;
+ else /* No ucode on other devices */
+ return NULL;
+
+ err = request_firmware(&fw, fw_name, &nic->pdev->dev);
+ if (err) {
+ DPRINTK(PROBE, ERR, "Failed to load firmware \"%s\": %d\n",
+ fw_name, err);
+ return ERR_PTR(err);
+ }
+ /* Firmware should be precisely UCODE_SIZE (words) plus three bytes
+ indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */
+ if (fw->size != UCODE_SIZE * 4 + 3) {
+ DPRINTK(PROBE, ERR, "Firmware \"%s\" has wrong size %zu\n",
+ fw_name, fw->size);
+ release_firmware(fw);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* Read timer, bundle and min_size from end of firmware blob */
+ timer = fw->data[UCODE_SIZE * 4];
+ bundle = fw->data[UCODE_SIZE * 4 + 1];
+ min_size = fw->data[UCODE_SIZE * 4 + 2];
+
+ if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE ||
+ min_size >= UCODE_SIZE) {
+ DPRINTK(PROBE, ERR,
+ "\"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n",
+ fw_name, timer, bundle, min_size);
+ release_firmware(fw);
+ return ERR_PTR(-EINVAL);
+ }
+ /* OK, firmware is validated and ready to use... */
+ return fw;
+}
+
+static void e100_setup_ucode(struct nic *nic, struct cb *cb,
+ struct sk_buff *skb)
+{
+ const struct firmware *fw = (void *)skb;
+ u8 timer, bundle, min_size;
+
+ /* It's not a real skb; we just abused the fact that e100_exec_cb
+ will pass it through to here... */
+ cb->skb = NULL;
+
+ /* firmware is stored as little endian already */
+ memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4);
+
+ /* Read timer, bundle and min_size from end of firmware blob */
+ timer = fw->data[UCODE_SIZE * 4];
+ bundle = fw->data[UCODE_SIZE * 4 + 1];
+ min_size = fw->data[UCODE_SIZE * 4 + 2];
+
+ /* Insert user-tunable settings in cb->u.ucode */
+ cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000);
+ cb->u.ucode[timer] |= cpu_to_le32(INTDELAY);
+ cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000);
+ cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX);
+ cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000);
+ cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);
+
+ cb->command = cpu_to_le16(cb_ucode | cb_el);
+}
+
+static inline int e100_load_ucode_wait(struct nic *nic)
+{
+ const struct firmware *fw;
int err = 0, counter = 50;
struct cb *cb = nic->cb_to_clean;
- if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode)))
+ fw = e100_request_firmware(nic);
+ /* If it's NULL, then no ucode is required */
+ if (!fw || IS_ERR(fw))
+ return PTR_ERR(fw);
+
+ if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode)))
DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);
/* must restart cuc */
@@ -1369,21 +1264,21 @@ static int e100_phy_init(struct nic *nic)
u16 bmcr, stat, id_lo, id_hi, cong;
/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
- for(addr = 0; addr < 32; addr++) {
+ for (addr = 0; addr < 32; addr++) {
nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR);
stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR);
- if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
+ if (!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
break;
}
DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
- if(addr == 32)
+ if (addr == 32)
return -EAGAIN;
/* Selected the phy and isolate the rest */
- for(addr = 0; addr < 32; addr++) {
- if(addr != nic->mii.phy_id) {
+ for (addr = 0; addr < 32; addr++) {
+ if (addr != nic->mii.phy_id) {
mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
} else {
bmcr = mdio_read(netdev, addr, MII_BMCR);
@@ -1400,7 +1295,7 @@ static int e100_phy_init(struct nic *nic)
/* Handle National tx phys */
#define NCS_PHY_MODEL_MASK 0xFFF0FFFF
- if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
+ if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
/* Disable congestion control */
cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG);
cong |= NSC_CONG_TXREADY;
@@ -1408,7 +1303,7 @@ static int e100_phy_init(struct nic *nic)
mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
}
- if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
+ if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
/* enable/disable MDI/MDI-X auto-switching. */
@@ -1426,25 +1321,25 @@ static int e100_hw_init(struct nic *nic)
e100_hw_reset(nic);
DPRINTK(HW, ERR, "e100_hw_init\n");
- if(!in_interrupt() && (err = e100_self_test(nic)))
+ if (!in_interrupt() && (err = e100_self_test(nic)))
return err;
- if((err = e100_phy_init(nic)))
+ if ((err = e100_phy_init(nic)))
return err;
- if((err = e100_exec_cmd(nic, cuc_load_base, 0)))
+ if ((err = e100_exec_cmd(nic, cuc_load_base, 0)))
return err;
- if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
+ if ((err = e100_exec_cmd(nic, ruc_load_base, 0)))
return err;
- if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode)))
+ if ((err = e100_load_ucode_wait(nic)))
return err;
- if((err = e100_exec_cb(nic, NULL, e100_configure)))
+ if ((err = e100_exec_cb(nic, NULL, e100_configure)))
return err;
- if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
+ if ((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
return err;
- if((err = e100_exec_cmd(nic, cuc_dump_addr,
+ if ((err = e100_exec_cmd(nic, cuc_dump_addr,
nic->dma_addr + offsetof(struct mem, stats))))
return err;
- if((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
+ if ((err = e100_exec_cmd(nic, cuc_dump_reset, 0)))
return err;
e100_disable_irq(nic);
@@ -1460,7 +1355,7 @@ static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
cb->command = cpu_to_le16(cb_multi);
cb->u.multi.count = cpu_to_le16(count * ETH_ALEN);
- for(i = 0; list && i < count; i++, list = list->next)
+ for (i = 0; list && i < count; i++, list = list->next)
memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr,
ETH_ALEN);
}
@@ -1472,12 +1367,12 @@ static void e100_set_multicast_list(struct net_device *netdev)
DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n",
netdev->mc_count, netdev->flags);
- if(netdev->flags & IFF_PROMISC)
+ if (netdev->flags & IFF_PROMISC)
nic->flags |= promiscuous;
else
nic->flags &= ~promiscuous;
- if(netdev->flags & IFF_ALLMULTI ||
+ if (netdev->flags & IFF_ALLMULTI ||
netdev->mc_count > E100_MAX_MULTICAST_ADDRS)
nic->flags |= multicast_all;
else
@@ -1500,7 +1395,7 @@ static void e100_update_stats(struct nic *nic)
* complete, so we're always waiting for results of the
* previous command. */
- if(*complete == cpu_to_le32(cuc_dump_reset_complete)) {
+ if (*complete == cpu_to_le32(cuc_dump_reset_complete)) {
*complete = 0;
nic->tx_frames = le32_to_cpu(s->tx_good_frames);
nic->tx_collisions = le32_to_cpu(s->tx_total_collisions);
@@ -1527,12 +1422,12 @@ static void e100_update_stats(struct nic *nic)
le32_to_cpu(s->tx_single_collisions);
nic->tx_multiple_collisions +=
le32_to_cpu(s->tx_multiple_collisions);
- if(nic->mac >= mac_82558_D101_A4) {
+ if (nic->mac >= mac_82558_D101_A4) {
nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause);
nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause);
nic->rx_fc_unsupported +=
le32_to_cpu(s->fc_rcv_unsupported);
- if(nic->mac >= mac_82559_D101M) {
+ if (nic->mac >= mac_82559_D101M) {
nic->tx_tco_frames +=
le16_to_cpu(s->xmt_tco_frames);
nic->rx_tco_frames +=
@@ -1542,7 +1437,7 @@ static void e100_update_stats(struct nic *nic)
}
- if(e100_exec_cmd(nic, cuc_dump_reset, 0))
+ if (e100_exec_cmd(nic, cuc_dump_reset, 0))
DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
}
@@ -1551,19 +1446,19 @@ static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
/* Adjust inter-frame-spacing (IFS) between two transmits if
* we're getting collisions on a half-duplex connection. */
- if(duplex == DUPLEX_HALF) {
+ if (duplex == DUPLEX_HALF) {
u32 prev = nic->adaptive_ifs;
u32 min_frames = (speed == SPEED_100) ? 1000 : 100;
- if((nic->tx_frames / 32 < nic->tx_collisions) &&
+ if ((nic->tx_frames / 32 < nic->tx_collisions) &&
(nic->tx_frames > min_frames)) {
- if(nic->adaptive_ifs < 60)
+ if (nic->adaptive_ifs < 60)
nic->adaptive_ifs += 5;
} else if (nic->tx_frames < min_frames) {
- if(nic->adaptive_ifs >= 5)
+ if (nic->adaptive_ifs >= 5)
nic->adaptive_ifs -= 5;
}
- if(nic->adaptive_ifs != prev)
+ if (nic->adaptive_ifs != prev)
e100_exec_cb(nic, NULL, e100_configure);
}
}
@@ -1579,12 +1474,12 @@ static void e100_watchdog(unsigned long data)
mii_ethtool_gset(&nic->mii, &cmd);
- if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
+ if (mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n",
nic->netdev->name,
cmd.speed == SPEED_100 ? "100" : "10",
cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
- } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
+ } else if (!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
printk(KERN_INFO "e100: %s NIC Link is Down\n",
nic->netdev->name);
}
@@ -1604,11 +1499,11 @@ static void e100_watchdog(unsigned long data)
e100_update_stats(nic);
e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex);
- if(nic->mac <= mac_82557_D100_C)
+ if (nic->mac <= mac_82557_D100_C)
/* Issue a multicast command to workaround a 557 lock up */
e100_set_multicast_list(nic->netdev);
- if(nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF)
+ if (nic->flags & ich && cmd.speed==SPEED_10 && cmd.duplex==DUPLEX_HALF)
/* Need SW workaround for ICH[x] 10Mbps/half duplex Tx hang. */
nic->flags |= ich_10h_workaround;
else
@@ -1623,7 +1518,7 @@ static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
{
cb->command = nic->tx_command;
/* interrupt every 16 packets regardless of delay */
- if((nic->cbs_avail & ~15) == nic->cbs_avail)
+ if ((nic->cbs_avail & ~15) == nic->cbs_avail)
cb->command |= cpu_to_le16(cb_i);
cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
cb->u.tcb.tcb_byte_count = 0;
@@ -1640,18 +1535,18 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct nic *nic = netdev_priv(netdev);
int err;
- if(nic->flags & ich_10h_workaround) {
+ if (nic->flags & ich_10h_workaround) {
/* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
Issue a NOP command followed by a 1us delay before
issuing the Tx command. */
- if(e100_exec_cmd(nic, cuc_nop, 0))
+ if (e100_exec_cmd(nic, cuc_nop, 0))
DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n");
udelay(1);
}
err = e100_exec_cb(nic, skb, e100_xmit_prepare);
- switch(err) {
+ switch (err) {
case -ENOSPC:
/* We queued the skb, but now we're out of space. */
DPRINTK(TX_ERR, DEBUG, "No space for CB\n");
@@ -1677,14 +1572,14 @@ static int e100_tx_clean(struct nic *nic)
spin_lock(&nic->cb_lock);
/* Clean CBs marked complete */
- for(cb = nic->cb_to_clean;
+ for (cb = nic->cb_to_clean;
cb->status & cpu_to_le16(cb_complete);
cb = nic->cb_to_clean = cb->next) {
DPRINTK(TX_DONE, DEBUG, "cb[%d]->status = 0x%04X\n",
(int)(((void*)cb - (void*)nic->cbs)/sizeof(struct cb)),
cb->status);
- if(likely(cb->skb != NULL)) {
+ if (likely(cb->skb != NULL)) {
dev->stats.tx_packets++;
dev->stats.tx_bytes += cb->skb->len;
@@ -1703,7 +1598,7 @@ static int e100_tx_clean(struct nic *nic)
spin_unlock(&nic->cb_lock);
/* Recover from running out of Tx resources in xmit_frame */
- if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
+ if (unlikely(tx_cleaned && netif_queue_stopped(nic->netdev)))
netif_wake_queue(nic->netdev);
return tx_cleaned;
@@ -1711,10 +1606,10 @@ static int e100_tx_clean(struct nic *nic)
static void e100_clean_cbs(struct nic *nic)
{
- if(nic->cbs) {
- while(nic->cbs_avail != nic->params.cbs.count) {
+ if (nic->cbs) {
+ while (nic->cbs_avail != nic->params.cbs.count) {
struct cb *cb = nic->cb_to_clean;
- if(cb->skb) {
+ if (cb->skb) {
pci_unmap_single(nic->pdev,
le32_to_cpu(cb->u.tcb.tbd.buf_addr),
le16_to_cpu(cb->u.tcb.tbd.size),
@@ -1746,10 +1641,10 @@ static int e100_alloc_cbs(struct nic *nic)
nic->cbs = pci_alloc_consistent(nic->pdev,
sizeof(struct cb) * count, &nic->cbs_dma_addr);
- if(!nic->cbs)
+ if (!nic->cbs)
return -ENOMEM;
- for(cb = nic->cbs, i = 0; i < count; cb++, i++) {
+ for (cb = nic->cbs, i = 0; i < count; cb++, i++) {
cb->next = (i + 1 < count) ? cb + 1 : nic->cbs;
cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1;
@@ -1767,14 +1662,14 @@ static int e100_alloc_cbs(struct nic *nic)
static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
{
- if(!nic->rxs) return;
- if(RU_SUSPENDED != nic->ru_running) return;
+ if (!nic->rxs) return;
+ if (RU_SUSPENDED != nic->ru_running) return;
/* handle init time starts */
- if(!rx) rx = nic->rxs;
+ if (!rx) rx = nic->rxs;
/* (Re)start RU if suspended or idle and RFA is non-NULL */
- if(rx->skb) {
+ if (rx->skb) {
e100_exec_cmd(nic, ruc_start, rx->dma_addr);
nic->ru_running = RU_RUNNING;
}
@@ -1783,7 +1678,7 @@ static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
{
- if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN)))
+ if (!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN)))
return -ENOMEM;
/* Align, init, and map the RFD. */
@@ -1820,7 +1715,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
struct rfd *rfd = (struct rfd *)skb->data;
u16 rfd_status, actual_size;
- if(unlikely(work_done && *work_done >= work_to_do))
+ if (unlikely(work_done && *work_done >= work_to_do))
return -EAGAIN;
/* Need to sync before taking a peek at cb_complete bit */
@@ -1847,7 +1742,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
/* Get actual data size */
actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
- if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
+ if (unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd)))
actual_size = RFD_BUF_LEN - sizeof(struct rfd);
/* Get data */
@@ -1872,10 +1767,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
skb_put(skb, actual_size);
skb->protocol = eth_type_trans(skb, nic->netdev);
- if(unlikely(!(rfd_status & cb_ok))) {
+ if (unlikely(!(rfd_status & cb_ok))) {
/* Don't indicate if hardware indicates errors */
dev_kfree_skb_any(skb);
- } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
+ } else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
/* Don't indicate oversized frames */
nic->rx_over_length_errors++;
dev_kfree_skb_any(skb);
@@ -1883,7 +1778,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
dev->stats.rx_packets++;
dev->stats.rx_bytes += actual_size;
netif_receive_skb(skb);
- if(work_done)
+ if (work_done)
(*work_done)++;
}
@@ -1901,7 +1796,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
struct rfd *old_before_last_rfd, *new_before_last_rfd;
/* Indicate newly arrived packets */
- for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
+ for (rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
err = e100_rx_indicate(nic, rx, work_done, work_to_do);
/* Hit quota or no more to clean */
if (-EAGAIN == err || -ENODATA == err)
@@ -1922,8 +1817,8 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;
/* Alloc new skbs to refill list */
- for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
- if(unlikely(e100_rx_alloc_skb(nic, rx)))
+ for (rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
+ if (unlikely(e100_rx_alloc_skb(nic, rx)))
break; /* Better luck next time (see watchdog) */
}
@@ -1959,11 +1854,11 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
PCI_DMA_BIDIRECTIONAL);
}
- if(restart_required) {
+ if (restart_required) {
// ack the rnr?
iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
e100_start_receiver(nic, nic->rx_to_clean);
- if(work_done)
+ if (work_done)
(*work_done)++;
}
}
@@ -1975,9 +1870,9 @@ static void e100_rx_clean_list(struct nic *nic)
nic->ru_running = RU_UNINITIALIZED;
- if(nic->rxs) {
- for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
- if(rx->skb) {
+ if (nic->rxs) {
+ for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
+ if (rx->skb) {
pci_unmap_single(nic->pdev, rx->dma_addr,
RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
dev_kfree_skb(rx->skb);
@@ -1999,13 +1894,13 @@ static int e100_rx_alloc_list(struct nic *nic)
nic->rx_to_use = nic->rx_to_clean = NULL;
nic->ru_running = RU_UNINITIALIZED;
- if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
+ if (!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
return -ENOMEM;
- for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
+ for (rx = nic->rxs, i = 0; i < count; rx++, i++) {
rx->next = (i + 1 < count) ? rx + 1 : nic->rxs;
rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1;
- if(e100_rx_alloc_skb(nic, rx)) {
+ if (e100_rx_alloc_skb(nic, rx)) {
e100_rx_clean_list(nic);
return -ENOMEM;
}
@@ -2038,7 +1933,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack);
- if(stat_ack == stat_ack_not_ours || /* Not our interrupt */
+ if (stat_ack == stat_ack_not_ours || /* Not our interrupt */
stat_ack == stat_ack_not_present) /* Hardware is ejected */
return IRQ_NONE;
@@ -2046,10 +1941,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
iowrite8(stat_ack, &nic->csr->scb.stat_ack);
/* We hit Receive No Resource (RNR); restart RU after cleaning */
- if(stat_ack & stat_ack_rnr)
+ if (stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED;
- if(likely(netif_rx_schedule_prep(&nic->napi))) {
+ if (likely(netif_rx_schedule_prep(&nic->napi))) {
e100_disable_irq(nic);
__netif_rx_schedule(&nic->napi);
}
@@ -2102,7 +1997,7 @@ static int e100_set_mac_address(struct net_device *netdev, void *p)
static int e100_change_mtu(struct net_device *netdev, int new_mtu)
{
- if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
+ if (new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN)
return -EINVAL;
netdev->mtu = new_mtu;
return 0;
@@ -2121,16 +2016,16 @@ static int e100_up(struct nic *nic)
{
int err;
- if((err = e100_rx_alloc_list(nic)))
+ if ((err = e100_rx_alloc_list(nic)))
return err;
- if((err = e100_alloc_cbs(nic)))
+ if ((err = e100_alloc_cbs(nic)))
goto err_rx_clean_list;
- if((err = e100_hw_init(nic)))
+ if ((err = e100_hw_init(nic)))
goto err_clean_cbs;
e100_set_multicast_list(nic->netdev);
e100_start_receiver(nic, NULL);
mod_timer(&nic->watchdog, jiffies);
- if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
+ if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
nic->netdev->name, nic->netdev)))
goto err_no_irq;
netif_wake_queue(nic->netdev);
@@ -2192,26 +2087,26 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
* in loopback mode, and the test passes if the received
* packet compares byte-for-byte to the transmitted packet. */
- if((err = e100_rx_alloc_list(nic)))
+ if ((err = e100_rx_alloc_list(nic)))
return err;
- if((err = e100_alloc_cbs(nic)))
+ if ((err = e100_alloc_cbs(nic)))
goto err_clean_rx;
/* ICH PHY loopback is broken so do MAC loopback instead */
- if(nic->flags & ich && loopback_mode == lb_phy)
+ if (nic->flags & ich && loopback_mode == lb_phy)
loopback_mode = lb_mac;
nic->loopback = loopback_mode;
- if((err = e100_hw_init(nic)))
+ if ((err = e100_hw_init(nic)))
goto err_loopback_none;
- if(loopback_mode == lb_phy)
+ if (loopback_mode == lb_phy)
mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
BMCR_LOOPBACK);
e100_start_receiver(nic, NULL);
- if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
+ if (!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
err = -ENOMEM;
goto err_loopback_none;
}
@@ -2224,7 +2119,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
- if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
+ if (memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
skb->data, ETH_DATA_LEN))
err = -EAGAIN;
@@ -2301,7 +2196,7 @@ static void e100_get_regs(struct net_device *netdev,
buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
ioread8(&nic->csr->scb.cmd_lo) << 16 |
ioread16(&nic->csr->scb.status);
- for(i = E100_PHY_REGS; i >= 0; i--)
+ for (i = E100_PHY_REGS; i >= 0; i--)
buff[1 + E100_PHY_REGS - i] =
mdio_read(netdev, nic->mii.phy_id, i);
memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
@@ -2326,7 +2221,7 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
!device_can_wakeup(&nic->pdev->dev))
return -EOPNOTSUPP;
- if(wol->wolopts)
+ if (wol->wolopts)
nic->flags |= wol_magic;
else
nic->flags &= ~wol_magic;
@@ -2385,7 +2280,7 @@ static int e100_set_eeprom(struct net_device *netdev,
{
struct nic *nic = netdev_priv(netdev);
- if(eeprom->magic != E100_EEPROM_MAGIC)
+ if (eeprom->magic != E100_EEPROM_MAGIC)
return -EINVAL;
memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len);
@@ -2421,7 +2316,7 @@ static int e100_set_ringparam(struct net_device *netdev,
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
- if(netif_running(netdev))
+ if (netif_running(netdev))
e100_down(nic);
rfds->count = max(ring->rx_pending, rfds->min);
rfds->count = min(rfds->count, rfds->max);
@@ -2429,7 +2324,7 @@ static int e100_set_ringparam(struct net_device *netdev,
cbs->count = min(cbs->count, cbs->max);
DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n",
rfds->count, cbs->count);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e100_up(nic);
return 0;
@@ -2454,12 +2349,12 @@ static void e100_diag_test(struct net_device *netdev,
memset(data, 0, E100_TEST_LEN * sizeof(u64));
data[0] = !mii_link_ok(&nic->mii);
data[1] = e100_eeprom_load(nic);
- if(test->flags & ETH_TEST_FL_OFFLINE) {
+ if (test->flags & ETH_TEST_FL_OFFLINE) {
/* save speed, duplex & autoneg settings */
err = mii_ethtool_gset(&nic->mii, &cmd);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e100_down(nic);
data[2] = e100_self_test(nic);
data[3] = e100_loopback_test(nic, lb_mac);
@@ -2468,10 +2363,10 @@ static void e100_diag_test(struct net_device *netdev,
/* restore speed, duplex & autoneg settings */
err = mii_ethtool_sset(&nic->mii, &cmd);
- if(netif_running(netdev))
+ if (netif_running(netdev))
e100_up(nic);
}
- for(i = 0; i < E100_TEST_LEN; i++)
+ for (i = 0; i < E100_TEST_LEN; i++)
test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0;
msleep_interruptible(4 * 1000);
@@ -2481,7 +2376,7 @@ static int e100_phys_id(struct net_device *netdev, u32 data)
{
struct nic *nic = netdev_priv(netdev);
- if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+ if (!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
mod_timer(&nic->blink_timer, jiffies);
msleep_interruptible(data * 1000);
@@ -2524,7 +2419,7 @@ static void e100_get_ethtool_stats(struct net_device *netdev,
struct nic *nic = netdev_priv(netdev);
int i;
- for(i = 0; i < E100_NET_STATS_LEN; i++)
+ for (i = 0; i < E100_NET_STATS_LEN; i++)
data[i] = ((unsigned long *)&netdev->stats)[i];
data[i++] = nic->tx_deferred;
@@ -2539,7 +2434,7 @@ static void e100_get_ethtool_stats(struct net_device *netdev,
static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
{
- switch(stringset) {
+ switch (stringset) {
case ETH_SS_TEST:
memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test));
break;
@@ -2589,7 +2484,7 @@ static int e100_alloc(struct nic *nic)
static void e100_free(struct nic *nic)
{
- if(nic->mem) {
+ if (nic->mem) {
pci_free_consistent(nic->pdev, sizeof(struct mem),
nic->mem, nic->dma_addr);
nic->mem = NULL;
@@ -2602,7 +2497,7 @@ static int e100_open(struct net_device *netdev)
int err = 0;
netif_carrier_off(netdev);
- if((err = e100_up(nic)))
+ if ((err = e100_up(nic)))
DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n");
return err;
}
@@ -2635,8 +2530,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
struct nic *nic;
int err;
- if(!(netdev = alloc_etherdev(sizeof(struct nic)))) {
- if(((1 << debug) - 1) & NETIF_MSG_PROBE)
+ if (!(netdev = alloc_etherdev(sizeof(struct nic)))) {
+ if (((1 << debug) - 1) & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n");
return -ENOMEM;
}
@@ -2653,24 +2548,24 @@ static int __devinit e100_probe(struct pci_dev *pdev,
nic->msg_enable = (1 << debug) - 1;
pci_set_drvdata(pdev, netdev);
- if((err = pci_enable_device(pdev))) {
+ if ((err = pci_enable_device(pdev))) {
DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n");
goto err_out_free_dev;
}
- if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
DPRINTK(PROBE, ERR, "Cannot find proper PCI device "
"base address, aborting.\n");
err = -ENODEV;
goto err_out_disable_pdev;
}
- if((err = pci_request_regions(pdev, DRV_NAME))) {
+ if ((err = pci_request_regions(pdev, DRV_NAME))) {
DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n");
goto err_out_disable_pdev;
}
- if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
goto err_out_free_res;
}
@@ -2681,13 +2576,13 @@ static int __devinit e100_probe(struct pci_dev *pdev,
DPRINTK(PROBE, INFO, "using i/o access mode\n");
nic->csr = pci_iomap(pdev, (use_io ? 1 : 0), sizeof(struct csr));
- if(!nic->csr) {
+ if (!nic->csr) {
DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");
err = -ENOMEM;
goto err_out_free_res;
}
- if(ent->driver_data)
+ if (ent->driver_data)
nic->flags |= ich;
else
nic->flags &= ~ich;
@@ -2715,12 +2610,12 @@ static int __devinit e100_probe(struct pci_dev *pdev,
INIT_WORK(&nic->tx_timeout_task, e100_tx_timeout_task);
- if((err = e100_alloc(nic))) {
+ if ((err = e100_alloc(nic))) {
DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
goto err_out_iounmap;
}
- if((err = e100_eeprom_load(nic)))
+ if ((err = e100_eeprom_load(nic)))
goto err_out_free;
e100_phy_init(nic);
@@ -2740,7 +2635,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
}
/* Wol magic packet can be enabled from eeprom */
- if((nic->mac >= mac_82558_D101_A4) &&
+ if ((nic->mac >= mac_82558_D101_A4) &&
(nic->eeprom[eeprom_id] & eeprom_id_wol)) {
nic->flags |= wol_magic;
device_set_wakeup_enable(&pdev->dev, true);
@@ -2750,7 +2645,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
pci_pme_active(pdev, false);
strcpy(netdev->name, "eth%d");
- if((err = register_netdev(netdev))) {
+ if ((err = register_netdev(netdev))) {
DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n");
goto err_out_free;
}
@@ -2779,7 +2674,7 @@ static void __devexit e100_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- if(netdev) {
+ if (netdev) {
struct nic *nic = netdev_priv(netdev);
unregister_netdev(netdev);
e100_free(nic);
@@ -2932,7 +2827,7 @@ static struct pci_driver e100_driver = {
static int __init e100_init_module(void)
{
- if(((1 << debug) - 1) & NETIF_MSG_DRV) {
+ if (((1 << debug) - 1) & NETIF_MSG_DRV) {
printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
}
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index d04eef53571e..e1a3fc1303ee 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -6758,7 +6758,7 @@ static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
* returns: - E1000_ERR_XXX
* E1000_SUCCESS
*
- * For phy's older then IGP, this function simply reads the polarity bit in the
+ * For phy's older than IGP, this function simply reads the polarity bit in the
* Phy Status register. For IGP phy's, this bit is valid only if link speed is
* 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will
* return 0. If the link speed is 1000 Mbps the polarity status is in the
@@ -6834,7 +6834,7 @@ static s32 e1000_check_polarity(struct e1000_hw *hw,
* returns: - E1000_ERR_XXX
* E1000_SUCCESS
*
- * For phy's older then IGP, this function reads the Downshift bit in the Phy
+ * For phy's older than IGP, this function reads the Downshift bit in the Phy
* Specific Status register. For IGP phy's, it reads the Downgrade bit in the
* Link Health register. In IGP this bit is latched high, so the driver must
* read it immediately after link is established.
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 26474c92193f..6bd63cc67b3e 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -31,7 +31,7 @@
char e1000_driver_name[] = "e1000";
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-#define DRV_VERSION "7.3.20-k3-NAPI"
+#define DRV_VERSION "7.3.21-k3-NAPI"
const char e1000_driver_version[] = DRV_VERSION;
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
@@ -940,7 +940,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
err = pci_enable_device(pdev);
} else {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
- err = pci_enable_device(pdev);
+ err = pci_enable_device_mem(pdev);
}
if (err)
return err;
@@ -3712,7 +3712,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
struct e1000_hw *hw = &adapter->hw;
u32 rctl, icr = er32(ICR);
- if (unlikely(!icr))
+ if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags)))
return IRQ_NONE; /* Not our interrupt */
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index cf43ee743b3c..0890162953e9 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -981,11 +981,15 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
ew32(PBA_ECC, reg);
}
- /* PCI-Ex Control Register */
+ /* PCI-Ex Control Registers */
if (hw->mac.type == e1000_82574) {
reg = er32(GCR);
reg |= (1 << 22);
ew32(GCR, reg);
+
+ reg = er32(GCR2);
+ reg |= 1;
+ ew32(GCR2, reg);
}
return;
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index f25e961c6b3b..2d4ce0492df0 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -206,6 +206,7 @@ enum e1e_registers {
E1000_MANC2H = 0x05860, /* Management Control To Host - RW */
E1000_SW_FW_SYNC = 0x05B5C, /* Software-Firmware Synchronization - RW */
E1000_GCR = 0x05B00, /* PCI-Ex Control */
+ E1000_GCR2 = 0x05B64, /* PCI-Ex Control #2 */
E1000_FACTPS = 0x05B30, /* Function Active and Power State to MNG */
E1000_SWSM = 0x05B50, /* SW Semaphore */
E1000_FWSM = 0x05B54, /* FW Semaphore */
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index f2a5963b5a95..e415e81ecd3e 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -390,7 +390,8 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
}
static DEFINE_MUTEX(nvm_mutex);
-static pid_t nvm_owner = -1;
+static pid_t nvm_owner_pid = -1;
+static char nvm_owner_name[TASK_COMM_LEN] = "";
/**
* e1000_acquire_swflag_ich8lan - Acquire software control flag
@@ -408,11 +409,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
might_sleep();
if (!mutex_trylock(&nvm_mutex)) {
- WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n",
- nvm_owner);
+ WARN(1, KERN_ERR "e1000e mutex contention. Owned by process "
+ "%s (pid %d), required by process %s (pid %d)\n",
+ nvm_owner_name, nvm_owner_pid,
+ current->comm, current->pid);
+
mutex_lock(&nvm_mutex);
}
- nvm_owner = current->pid;
+ nvm_owner_pid = current->pid;
+ strncpy(nvm_owner_name, current->comm, TASK_COMM_LEN);
while (timeout) {
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -430,7 +435,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
- nvm_owner = -1;
+ nvm_owner_pid = -1;
+ strcpy(nvm_owner_name, "");
mutex_unlock(&nvm_mutex);
return -E1000_ERR_CONFIG;
}
@@ -454,7 +460,8 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
- nvm_owner = -1;
+ nvm_owner_pid = -1;
+ strcpy(nvm_owner_name, "");
mutex_unlock(&nvm_mutex);
}
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index d4639facd1bd..91817d0afcaf 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -4807,7 +4807,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
}
}
- err = pci_request_selected_regions(pdev,
+ err = pci_request_selected_regions_exclusive(pdev,
pci_select_bars(pdev, IORESOURCE_MEM),
e1000e_driver_name);
if (err)
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 20eb05cddb83..b07ba1924de0 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -169,6 +169,7 @@ static const struct net_device_ops e21_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 9930d5f8b9e1..6271b9411ccf 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -478,7 +478,7 @@ struct ehea_port {
int num_add_tx_qps;
int num_mcs;
int resets;
- u64 flags;
+ unsigned long flags;
u64 mac_addr;
u32 logical_port_id;
u32 port_speed;
@@ -510,7 +510,6 @@ void ehea_set_ethtool_ops(struct net_device *netdev);
int ehea_sense_port_attr(struct ehea_port *port);
int ehea_set_portspeed(struct ehea_port *port, u32 port_speed);
-extern u64 ehea_driver_flags;
extern struct work_struct ehea_rereg_mr_task;
#endif /* __EHEA_H__ */
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index a2f1905a23df..dfe92264e825 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -99,7 +99,7 @@ MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
static int port_name_cnt;
static LIST_HEAD(adapter_list);
-u64 ehea_driver_flags;
+static unsigned long ehea_driver_flags;
struct work_struct ehea_rereg_mr_task;
static DEFINE_MUTEX(dlpar_mem_lock);
struct ehea_fw_handle_array ehea_fw_handles;
@@ -132,7 +132,7 @@ void ehea_dump(void *adr, int len, char *msg)
int x;
unsigned char *deb = adr;
for (x = 0; x < len; x += 16) {
- printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
+ printk(DRV_NAME " %s adr=%p ofs=%04x %016llx %016llx\n", msg,
deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8]));
deb += 16;
}
@@ -883,7 +883,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
while (eqe) {
qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
- ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
+ ehea_error("QP aff_err: entry=0x%llx, token=0x%x",
eqe->entry, qp_token);
qp = port->port_res[qp_token].qp;
@@ -1159,7 +1159,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
netif_stop_queue(port->netdev);
break;
default:
- ehea_error("unknown event code %x, eqe=0x%lX", ec, eqe);
+ ehea_error("unknown event code %x, eqe=0x%llX", ec, eqe);
break;
}
}
@@ -1971,7 +1971,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
}
if (dev->mc_count > port->adapter->max_mc_mac) {
- ehea_info("Mcast registration limit reached (0x%lx). "
+ ehea_info("Mcast registration limit reached (0x%llx). "
"Use ALLMULTI!",
port->adapter->max_mc_mac);
goto out;
diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
index 2a33a613d9e6..8fe9dcaa7538 100644
--- a/drivers/net/ehea/ehea_phyp.c
+++ b/drivers/net/ehea/ehea_phyp.c
@@ -214,7 +214,7 @@ u64 ehea_h_alloc_resource_qp(const u64 adapter_handle,
u64 *qp_handle, struct h_epas *h_epas)
{
u64 hret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
u64 allocate_controls =
EHEA_BMASK_SET(H_ALL_RES_QP_EQPO, init_attr->low_lat_rq1 ? 1 : 0)
@@ -312,7 +312,7 @@ u64 ehea_h_alloc_resource_cq(const u64 adapter_handle,
u64 *cq_handle, struct h_epas *epas)
{
u64 hret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
outs,
@@ -374,7 +374,7 @@ u64 ehea_h_alloc_resource_eq(const u64 adapter_handle,
struct ehea_eq_attr *eq_attr, u64 *eq_handle)
{
u64 hret, allocate_controls;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
/* resource type */
allocate_controls =
@@ -407,7 +407,7 @@ u64 ehea_h_modify_ehea_qp(const u64 adapter_handle, const u8 cat,
u16 *out_swr, u16 *out_rwr)
{
u64 hret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
hret = ehea_plpar_hcall9(H_MODIFY_HEA_QP,
outs,
@@ -449,7 +449,7 @@ u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
struct ehea_mr *mr)
{
u64 hret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
hret = ehea_plpar_hcall9(H_REGISTER_SMR,
outs,
@@ -468,7 +468,7 @@ u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle)
{
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
return ehea_plpar_hcall9(H_DISABLE_AND_GET_HEA,
outs,
@@ -493,7 +493,7 @@ u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
const u32 pd, u64 *mr_handle, u32 *lkey)
{
u64 hret;
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
outs,
@@ -564,7 +564,7 @@ u64 ehea_h_modify_ehea_port(const u64 adapter_handle, const u16 port_num,
const u8 cb_cat, const u64 select_mask,
void *cb_addr)
{
- u64 outs[PLPAR_HCALL9_BUFSIZE];
+ unsigned long outs[PLPAR_HCALL9_BUFSIZE];
u64 port_info;
u64 arr_index = 0;
u64 cb_logaddr = virt_to_abs(cb_addr);
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index 225c692b5d99..49d766ebbcf4 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -168,7 +168,7 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
cq->fw_handle, rpage, 1);
if (hret < H_SUCCESS) {
ehea_error("register_rpage_cq failed ehea_cq=%p "
- "hret=%lx counter=%i act_pages=%i",
+ "hret=%llx counter=%i act_pages=%i",
cq, hret, counter, cq->attr.nr_pages);
goto out_kill_hwq;
}
@@ -178,13 +178,13 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
if ((hret != H_SUCCESS) || (vpage)) {
ehea_error("registration of pages not "
- "complete hret=%lx\n", hret);
+ "complete hret=%llx\n", hret);
goto out_kill_hwq;
}
} else {
if (hret != H_PAGE_REGISTERED) {
ehea_error("CQ: registration of page failed "
- "hret=%lx\n", hret);
+ "hret=%llx\n", hret);
goto out_kill_hwq;
}
}
@@ -986,15 +986,15 @@ void print_error_data(u64 *data)
length = EHEA_PAGESIZE;
if (type == 0x8) /* Queue Pair */
- ehea_error("QP (resource=%lX) state: AER=0x%lX, AERR=0x%lX, "
- "port=%lX", resource, data[6], data[12], data[22]);
+ ehea_error("QP (resource=%llX) state: AER=0x%llX, AERR=0x%llX, "
+ "port=%llX", resource, data[6], data[12], data[22]);
if (type == 0x4) /* Completion Queue */
- ehea_error("CQ (resource=%lX) state: AER=0x%lX", resource,
+ ehea_error("CQ (resource=%llX) state: AER=0x%llX", resource,
data[6]);
if (type == 0x3) /* Event Queue */
- ehea_error("EQ (resource=%lX) state: AER=0x%lX", resource,
+ ehea_error("EQ (resource=%llX) state: AER=0x%llX", resource,
data[6]);
ehea_dump(data, length, "error data");
@@ -1016,11 +1016,11 @@ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle)
rblock);
if (ret == H_R_STATE)
- ehea_error("No error data is available: %lX.", res_handle);
+ ehea_error("No error data is available: %llX.", res_handle);
else if (ret == H_SUCCESS)
print_error_data(rblock);
else
- ehea_error("Error data could not be fetched: %lX", res_handle);
+ ehea_error("Error data could not be fetched: %llX", res_handle);
kfree(rblock);
}
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index b0ef46c51a9d..fc6cc038c7b8 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -944,7 +944,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
if (netif_msg_rx_status(priv))
enc28j60_dump_rsv(priv, __func__, next_packet, len, rxstat);
- if (!RSV_GETBIT(rxstat, RSV_RXOK)) {
+ if (!RSV_GETBIT(rxstat, RSV_RXOK) || len > MAX_FRAMELEN) {
if (netif_msg_rx_err(priv))
dev_err(&ndev->dev, "Rx Error (%04x)\n", rxstat);
ndev->stats.rx_errors++;
@@ -952,6 +952,8 @@ static void enc28j60_hw_rx(struct net_device *ndev)
ndev->stats.rx_crc_errors++;
if (RSV_GETBIT(rxstat, RSV_LENCHECKERR))
ndev->stats.rx_frame_errors++;
+ if (len > MAX_FRAMELEN)
+ ndev->stats.rx_over_errors++;
} else {
skb = dev_alloc_skb(len + NET_IP_ALIGN);
if (!skb) {
@@ -1529,6 +1531,17 @@ static int enc28j60_chipset_init(struct net_device *dev)
return enc28j60_hw_init(priv);
}
+static const struct net_device_ops enc28j60_netdev_ops = {
+ .ndo_open = enc28j60_net_open,
+ .ndo_stop = enc28j60_net_close,
+ .ndo_start_xmit = enc28j60_send_packet,
+ .ndo_set_multicast_list = enc28j60_set_multicast_list,
+ .ndo_set_mac_address = enc28j60_set_mac_address,
+ .ndo_tx_timeout = enc28j60_tx_timeout,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit enc28j60_probe(struct spi_device *spi)
{
struct net_device *dev;
@@ -1583,12 +1596,7 @@ static int __devinit enc28j60_probe(struct spi_device *spi)
dev->if_port = IF_PORT_10BASET;
dev->irq = spi->irq;
- dev->open = enc28j60_net_open;
- dev->stop = enc28j60_net_close;
- dev->hard_start_xmit = enc28j60_send_packet;
- dev->set_multicast_list = &enc28j60_set_multicast_list;
- dev->set_mac_address = enc28j60_set_mac_address;
- dev->tx_timeout = &enc28j60_tx_timeout;
+ dev->netdev_ops = &enc28j60_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
SET_ETHTOOL_OPS(dev, &enc28j60_ethtool_ops);
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index d039e16f2763..7d60551d538f 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -1599,6 +1599,7 @@ static const struct net_device_ops enic_netdev_ops = {
.ndo_start_xmit = enic_hard_start_xmit,
.ndo_get_stats = enic_get_stats,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_set_multicast_list = enic_set_multicast_list,
.ndo_change_mtu = enic_change_mtu,
.ndo_vlan_rx_register = enic_vlan_rx_register,
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index f9b37c80dda6..a539bc3163cf 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -308,7 +308,18 @@ static int epic_close(struct net_device *dev);
static struct net_device_stats *epic_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
-
+static const struct net_device_ops epic_netdev_ops = {
+ .ndo_open = epic_open,
+ .ndo_stop = epic_close,
+ .ndo_start_xmit = epic_start_xmit,
+ .ndo_tx_timeout = epic_tx_timeout,
+ .ndo_get_stats = epic_get_stats,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
static int __devinit epic_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -483,15 +494,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
dev->if_port = ep->default_port = option;
/* The Epic-specific entries in the device structure. */
- dev->open = &epic_open;
- dev->hard_start_xmit = &epic_start_xmit;
- dev->stop = &epic_close;
- dev->get_stats = &epic_get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &netdev_ioctl;
+ dev->netdev_ops = &epic_netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
- dev->tx_timeout = &epic_tx_timeout;
netif_napi_add(dev, &ep->napi, epic_poll, 64);
ret = register_netdev(dev);
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 31ab1ff623fc..daf7272c3352 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -467,6 +467,18 @@ static void stop_nic_rxtx(void __iomem *ioaddr, long crvalue)
}
}
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = start_tx,
+ .ndo_get_stats = get_stats,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_do_ioctl = mii_ioctl,
+ .ndo_tx_timeout = fealnx_tx_timeout,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
static int __devinit fealnx_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -649,15 +661,8 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
np->mii.force_media = 1;
}
- /* The chip-specific entries in the device structure. */
- dev->open = &netdev_open;
- dev->hard_start_xmit = &start_tx;
- dev->stop = &netdev_close;
- dev->get_stats = &get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &mii_ioctl;
+ dev->netdev_ops = &netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
- dev->tx_timeout = &fealnx_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
err = register_netdev(dev);
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 7e33c129d51c..2769083bfe83 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1698,7 +1698,7 @@ static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_priva
/*
* Set MII speed to 2.5 MHz
*/
- fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
+ fep->phy_speed = (MCF_CLK / 3) / (2500000 * 2 ) * 2;
fecp->fec_mii_speed = fep->phy_speed;
fec_restart(dev, 0);
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 5b68dc20168d..5b910cf63740 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -13,7 +13,7 @@
* Copyright (C) 2004 Andrew de Quincey (wol support)
* Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane
* IRQ rate fixes, bigendian fixes, cleanups, verification)
- * Copyright (c) 2004,2005,2006,2007,2008 NVIDIA Corporation
+ * Copyright (c) 2004,2005,2006,2007,2008,2009 NVIDIA Corporation
*
* 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
@@ -39,7 +39,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.61"
+#define FORCEDETH_VERSION "0.62"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -2096,14 +2096,15 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
}
+ spin_lock_irqsave(&np->lock, flags);
empty_slots = nv_get_empty_tx_slots(np);
if (unlikely(empty_slots <= entries)) {
- spin_lock_irqsave(&np->lock, flags);
netif_stop_queue(dev);
np->tx_stop = 1;
spin_unlock_irqrestore(&np->lock, flags);
return NETDEV_TX_BUSY;
}
+ spin_unlock_irqrestore(&np->lock, flags);
start_tx = put_tx = np->put_tx.orig;
@@ -2214,14 +2215,15 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
((skb_shinfo(skb)->frags[i].size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
}
+ spin_lock_irqsave(&np->lock, flags);
empty_slots = nv_get_empty_tx_slots(np);
if (unlikely(empty_slots <= entries)) {
- spin_lock_irqsave(&np->lock, flags);
netif_stop_queue(dev);
np->tx_stop = 1;
spin_unlock_irqrestore(&np->lock, flags);
return NETDEV_TX_BUSY;
}
+ spin_unlock_irqrestore(&np->lock, flags);
start_tx = put_tx = np->put_tx.ex;
start_tx_ctx = np->put_tx_ctx;
@@ -3403,10 +3405,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
+ spin_lock(&np->lock);
netif_rx_schedule(&np->napi);
/* Disable furthur receive irq's */
- spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
@@ -3520,10 +3522,10 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
+ spin_lock(&np->lock);
netif_rx_schedule(&np->napi);
/* Disable furthur receive irq's */
- spin_lock(&np->lock);
np->irqmask &= ~NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
@@ -6167,19 +6169,19 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
- .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{0,},
};
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 4e6a9195fe5f..ce900e54d8d1 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -795,6 +795,7 @@ static int fs_enet_open(struct net_device *dev)
err = fs_init_phy(dev);
if (err) {
+ free_irq(fep->interrupt, dev);
if (fep->fpi->use_napi)
napi_disable(&fep->napi);
return err;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index c672ecfc9595..3f7eab42aef1 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -238,8 +238,8 @@ static int gfar_of_init(struct net_device *dev)
goto err_out;
}
- snprintf(priv->phy_bus_id, BUS_ID_SIZE, PHY_ID_FMT, "0",
- fixed_link[0]);
+ snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id),
+ PHY_ID_FMT, "0", fixed_link[0]);
} else {
phy = of_find_node_by_phandle(*ph);
@@ -256,7 +256,7 @@ static int gfar_of_init(struct net_device *dev)
of_node_put(mdio);
gfar_mdio_bus_name(bus_name, mdio);
- snprintf(priv->phy_bus_id, BUS_ID_SIZE, "%s:%02x",
+ snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x",
bus_name, *id);
}
@@ -296,6 +296,20 @@ err_out:
return err;
}
+/* Ioctl MII Interface */
+static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ if (!priv->phydev)
+ return -ENODEV;
+
+ return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd);
+}
+
/* Set up the ethernet device structure, private data,
* and anything else we need before we start */
static int gfar_probe(struct of_device *ofdev,
@@ -366,6 +380,7 @@ static int gfar_probe(struct of_device *ofdev,
dev->set_multicast_list = gfar_set_multi;
dev->ethtool_ops = &gfar_ethtool_ops;
+ dev->do_ioctl = gfar_ioctl;
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
priv->rx_csum_enable = 1;
@@ -1408,15 +1423,11 @@ static void gfar_vlan_rx_register(struct net_device *dev,
{
struct gfar_private *priv = netdev_priv(dev);
unsigned long flags;
- struct vlan_group *old_grp;
u32 tempval;
spin_lock_irqsave(&priv->rxlock, flags);
- old_grp = priv->vlgrp;
-
- if (old_grp == grp)
- return;
+ priv->vlgrp = grp;
if (grp) {
/* Enable VLAN tag insertion */
@@ -1607,10 +1618,18 @@ static int gfar_clean_tx_ring(struct net_device *dev)
static void gfar_schedule_cleanup(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
if (netif_rx_schedule_prep(&priv->napi)) {
gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED);
__netif_rx_schedule(&priv->napi);
}
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
}
/* Interrupt Handler for Transmit complete */
@@ -1973,6 +1992,8 @@ static void adjust_link(struct net_device *dev)
case 1000:
tempval =
((tempval & ~(MACCFG2_IF)) | MACCFG2_GMII);
+
+ ecntrl &= ~(ECNTRL_R100);
break;
case 100:
case 10:
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index f3706e415b45..f49a426ad681 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -234,6 +234,8 @@ static int gfar_mdio_probe(struct of_device *ofdev,
if (NULL == new_bus)
return -ENOMEM;
+ device_init_wakeup(&ofdev->dev, 1);
+
new_bus->name = "Gianfar MII Bus",
new_bus->read = &gfar_mdio_read,
new_bus->write = &gfar_mdio_write,
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 32200227c923..7e8b3c59a7d6 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -576,6 +576,7 @@ static const struct net_device_ops hamachi_netdev_ops = {
.ndo_set_multicast_list = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = hamachi_tx_timeout,
.ndo_do_ioctl = netdev_ioctl,
};
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 50f1e172ee8f..2d4089894ec7 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -717,11 +717,12 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct sixpack *sp = sp_get(tty);
- struct net_device *dev = sp->dev;
+ struct net_device *dev;
unsigned int tmp, err;
if (!sp)
return -ENXIO;
+ dev = sp->dev;
switch(cmd) {
case SIOCGIFNAME:
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index b507dbc16e62..5e070f446635 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -166,6 +166,7 @@ static const struct net_device_ops hpp_netdev_ops = {
.ndo_get_stats = eip_get_stats,
.ndo_set_multicast_list = eip_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = eip_poll,
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index ebe7651fcb86..ad8be7e78290 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -425,6 +425,28 @@ struct net_device * __init hp100_probe(int unit)
}
#endif /* !MODULE && CONFIG_ISA */
+static const struct net_device_ops hp100_bm_netdev_ops = {
+ .ndo_open = hp100_open,
+ .ndo_stop = hp100_close,
+ .ndo_start_xmit = hp100_start_xmit_bm,
+ .ndo_get_stats = hp100_get_stats,
+ .ndo_set_multicast_list = hp100_set_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+static const struct net_device_ops hp100_netdev_ops = {
+ .ndo_open = hp100_open,
+ .ndo_stop = hp100_close,
+ .ndo_start_xmit = hp100_start_xmit,
+ .ndo_get_stats = hp100_get_stats,
+ .ndo_set_multicast_list = hp100_set_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit hp100_probe1(struct net_device *dev, int ioaddr,
u_char bus, struct pci_dev *pci_dev)
{
@@ -657,16 +679,10 @@ static int __devinit hp100_probe1(struct net_device *dev, int ioaddr,
lp->virt_memory_size = virt_memory_size;
lp->rx_ratio = hp100_rx_ratio; /* can be conf'd with insmod */
- dev->open = hp100_open;
- dev->stop = hp100_close;
-
if (lp->mode == 1) /* busmaster */
- dev->hard_start_xmit = hp100_start_xmit_bm;
+ dev->netdev_ops = &hp100_bm_netdev_ops;
else
- dev->hard_start_xmit = hp100_start_xmit;
-
- dev->get_stats = hp100_get_stats;
- dev->set_multicast_list = &hp100_set_multicast_list;
+ dev->netdev_ops = &hp100_netdev_ops;
/* Ask the card for which IRQ line it is configured */
if (bus == HP100_BUS_PCI) {
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index 9cb38a8d4387..8ac0930c183c 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -103,6 +103,7 @@ static const struct net_device_ops hydra_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index ecf9798987fa..2a2fc17b2878 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -613,7 +613,9 @@ static int __devinit mal_probe(struct of_device *ofdev,
INIT_LIST_HEAD(&mal->list);
spin_lock_init(&mal->lock);
- netif_napi_add(NULL, &mal->napi, mal_poll,
+ init_dummy_netdev(&mal->dummy_dev);
+
+ netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll,
CONFIG_IBM_NEW_EMAC_POLL_WEIGHT);
/* Load power-on reset defaults */
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index 2f0a87360844..9ededfbf0726 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -214,6 +214,8 @@ struct mal_instance {
int index;
spinlock_t lock;
+ struct net_device dummy_dev;
+
unsigned int features;
};
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
index c40cd8df2212..ac9d964e59ec 100644
--- a/drivers/net/ibm_newemac/phy.c
+++ b/drivers/net/ibm_newemac/phy.c
@@ -60,7 +60,7 @@ int emac_mii_reset_phy(struct mii_phy *phy)
udelay(300);
- while (limit--) {
+ while (--limit) {
val = phy_read(phy, MII_BMCR);
if (val >= 0 && (val & BMCR_RESET) == 0)
break;
@@ -84,7 +84,7 @@ int emac_mii_reset_gpcs(struct mii_phy *phy)
udelay(300);
- while (limit--) {
+ while (--limit) {
val = gpcs_phy_read(phy, MII_BMCR);
if (val >= 0 && (val & BMCR_RESET) == 0)
break;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 9bc0f178f24b..dfa6348ac1dc 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -602,7 +602,7 @@ static int ibmveth_open(struct net_device *netdev)
if(lpar_rc != H_SUCCESS) {
ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
- ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n",
+ ibmveth_error_printk("buffer TCE:0x%llx filter TCE:0x%llx rxq desc:0x%llx MAC:0x%llx\n",
adapter->buffer_list_dma,
adapter->filter_list_dma,
rxq_desc.desc,
@@ -754,7 +754,7 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
void (*done) (struct net_device *, u32))
{
struct ibmveth_adapter *adapter = netdev_priv(dev);
- u64 set_attr, clr_attr, ret_attr;
+ unsigned long set_attr, clr_attr, ret_attr;
long ret;
int rc1 = 0, rc2 = 0;
int restart = 0;
@@ -1209,7 +1209,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
long ret;
struct net_device *netdev;
struct ibmveth_adapter *adapter;
- u64 set_attr, ret_attr;
+ unsigned long set_attr, ret_attr;
unsigned char *mac_addr_p;
unsigned int *mcastFilterSize_p;
@@ -1378,13 +1378,13 @@ static int ibmveth_show(struct seq_file *seq, void *v)
seq_printf(seq, "Firmware MAC: %pM\n", firmware_mac);
seq_printf(seq, "\nAdapter Statistics:\n");
- seq_printf(seq, " TX: vio_map_single failres: %ld\n", adapter->tx_map_failed);
- seq_printf(seq, " send failures: %ld\n", adapter->tx_send_failed);
- seq_printf(seq, " RX: replenish task cycles: %ld\n", adapter->replenish_task_cycles);
- seq_printf(seq, " alloc_skb_failures: %ld\n", adapter->replenish_no_mem);
- seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure);
- seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer);
- seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer);
+ seq_printf(seq, " TX: vio_map_single failres: %lld\n", adapter->tx_map_failed);
+ seq_printf(seq, " send failures: %lld\n", adapter->tx_send_failed);
+ seq_printf(seq, " RX: replenish task cycles: %lld\n", adapter->replenish_task_cycles);
+ seq_printf(seq, " alloc_skb_failures: %lld\n", adapter->replenish_no_mem);
+ seq_printf(seq, " add buffer failures: %lld\n", adapter->replenish_add_buff_failure);
+ seq_printf(seq, " invalid buffers: %lld\n", adapter->rx_invalid_buffer);
+ seq_printf(seq, " no buffers: %lld\n", adapter->rx_no_buffer);
return 0;
}
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index d28186948752..ec76ace66c6b 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -39,11 +39,11 @@
#define IbmVethMcastRemoveFilter 0x2UL
#define IbmVethMcastClearFilterTable 0x3UL
-#define IBMVETH_ILLAN_PADDED_PKT_CSUM 0x0000000000002000ULL
-#define IBMVETH_ILLAN_TRUNK_PRI_MASK 0x0000000000000F00ULL
-#define IBMVETH_ILLAN_IPV6_TCP_CSUM 0x0000000000000004ULL
-#define IBMVETH_ILLAN_IPV4_TCP_CSUM 0x0000000000000002ULL
-#define IBMVETH_ILLAN_ACTIVE_TRUNK 0x0000000000000001ULL
+#define IBMVETH_ILLAN_PADDED_PKT_CSUM 0x0000000000002000UL
+#define IBMVETH_ILLAN_TRUNK_PRI_MASK 0x0000000000000F00UL
+#define IBMVETH_ILLAN_IPV6_TCP_CSUM 0x0000000000000004UL
+#define IBMVETH_ILLAN_IPV4_TCP_CSUM 0x0000000000000002UL
+#define IBMVETH_ILLAN_ACTIVE_TRUNK 0x0000000000000001UL
/* hcall macros */
#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index f5e2e7235fcb..13ca73f96ec6 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -699,11 +699,18 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw)
/* SGMII link check is done through the PCS register. */
if ((hw->phy.media_type != e1000_media_type_copper) ||
- (igb_sgmii_active_82575(hw)))
+ (igb_sgmii_active_82575(hw))) {
ret_val = igb_get_pcs_speed_and_duplex_82575(hw, &speed,
&duplex);
- else
+ /*
+ * Use this flag to determine if link needs to be checked or
+ * not. If we have link clear the flag so that we do not
+ * continue to check for link.
+ */
+ hw->mac.get_link_status = !hw->mac.serdes_has_link;
+ } else {
ret_val = igb_check_for_copper_link(hw);
+ }
return ret_val;
}
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 5a27825cc48a..aebef8e48e76 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -300,11 +300,10 @@ struct igb_adapter {
#define IGB_FLAG_HAS_MSI (1 << 0)
#define IGB_FLAG_MSI_ENABLE (1 << 1)
-#define IGB_FLAG_HAS_DCA (1 << 2)
-#define IGB_FLAG_DCA_ENABLED (1 << 3)
-#define IGB_FLAG_IN_NETPOLL (1 << 5)
-#define IGB_FLAG_QUAD_PORT_A (1 << 6)
-#define IGB_FLAG_NEED_CTX_IDX (1 << 7)
+#define IGB_FLAG_DCA_ENABLED (1 << 2)
+#define IGB_FLAG_IN_NETPOLL (1 << 3)
+#define IGB_FLAG_QUAD_PORT_A (1 << 4)
+#define IGB_FLAG_NEED_CTX_IDX (1 << 5)
enum e1000_state_t {
__IGB_TESTING,
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 022794e579c7..a50db5398fa5 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -206,10 +206,11 @@ static int __init igb_init_module(void)
global_quad_port_a = 0;
- ret = pci_register_driver(&igb_driver);
#ifdef CONFIG_IGB_DCA
dca_register_notify(&dca_notifier);
#endif
+
+ ret = pci_register_driver(&igb_driver);
return ret;
}
@@ -1156,11 +1157,10 @@ static int __devinit igb_probe(struct pci_dev *pdev,
/* set flags */
switch (hw->mac.type) {
- case e1000_82576:
case e1000_82575:
- adapter->flags |= IGB_FLAG_HAS_DCA;
adapter->flags |= IGB_FLAG_NEED_CTX_IDX;
break;
+ case e1000_82576:
default:
break;
}
@@ -1310,8 +1310,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
goto err_register;
#ifdef CONFIG_IGB_DCA
- if ((adapter->flags & IGB_FLAG_HAS_DCA) &&
- (dca_add_requester(&pdev->dev) == 0)) {
+ if (dca_add_requester(&pdev->dev) == 0) {
adapter->flags |= IGB_FLAG_DCA_ENABLED;
dev_info(&pdev->dev, "DCA enabled\n");
/* Always use CB2 mode, difference is masked
@@ -1457,8 +1456,8 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
/* Number of supported queues. */
/* Having more queues than CPUs doesn't make sense. */
- adapter->num_rx_queues = min((u32)IGB_MAX_RX_QUEUES, (u32)num_online_cpus());
- adapter->num_tx_queues = min(IGB_MAX_TX_QUEUES, num_online_cpus());
+ adapter->num_rx_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
+ adapter->num_tx_queues = min_t(u32, IGB_MAX_TX_QUEUES, num_online_cpus());
/* This call may decrease the number of queues depending on
* interrupt mode. */
@@ -1835,11 +1834,11 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
rctl |= E1000_RCTL_SECRC;
/*
- * disable store bad packets, long packet enable, and clear size bits.
+ * disable store bad packets and clear size bits.
*/
- rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_LPE | E1000_RCTL_SZ_256);
+ rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_SZ_256);
- if (adapter->netdev->mtu > ETH_DATA_LEN)
+ /* enable LPE when to prevent packets larger than max_frame_size */
rctl |= E1000_RCTL_LPE;
/* Setup buffer sizes */
@@ -1865,7 +1864,7 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
*/
/* allocations using alloc_page take too long for regular MTU
* so only enable packet split for jumbo frames */
- if (rctl & E1000_RCTL_LPE) {
+ if (adapter->netdev->mtu > ETH_DATA_LEN) {
adapter->rx_ps_hdr_size = IGB_RXBUFFER_128;
srrctl |= adapter->rx_ps_hdr_size <<
E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
@@ -3473,19 +3472,16 @@ static int __igb_notify_dca(struct device *dev, void *data)
struct e1000_hw *hw = &adapter->hw;
unsigned long event = *(unsigned long *)data;
- if (!(adapter->flags & IGB_FLAG_HAS_DCA))
- goto out;
-
switch (event) {
case DCA_PROVIDER_ADD:
/* if already enabled, don't do it again */
if (adapter->flags & IGB_FLAG_DCA_ENABLED)
break;
- adapter->flags |= IGB_FLAG_DCA_ENABLED;
/* Always use CB2 mode, difference is masked
* in the CB driver. */
wr32(E1000_DCA_CTRL, 2);
if (dca_add_requester(dev) == 0) {
+ adapter->flags |= IGB_FLAG_DCA_ENABLED;
dev_info(&adapter->pdev->dev, "DCA enabled\n");
igb_setup_dca(adapter);
break;
@@ -3502,7 +3498,7 @@ static int __igb_notify_dca(struct device *dev, void *data)
}
break;
}
-out:
+
return 0;
}
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 7b6d435a8468..360aa5e35fda 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -2210,6 +2210,19 @@ static void __devexit ipg_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
+static const struct net_device_ops ipg_netdev_ops = {
+ .ndo_open = ipg_nic_open,
+ .ndo_stop = ipg_nic_stop,
+ .ndo_start_xmit = ipg_nic_hard_start_xmit,
+ .ndo_get_stats = ipg_nic_get_stats,
+ .ndo_set_multicast_list = ipg_nic_set_multicast_list,
+ .ndo_do_ioctl = ipg_ioctl,
+ .ndo_tx_timeout = ipg_tx_timeout,
+ .ndo_change_mtu = ipg_nic_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit ipg_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -2258,15 +2271,7 @@ static int __devinit ipg_probe(struct pci_dev *pdev,
/* Declare IPG NIC functions for Ethernet device methods.
*/
- dev->open = &ipg_nic_open;
- dev->stop = &ipg_nic_stop;
- dev->hard_start_xmit = &ipg_nic_hard_start_xmit;
- dev->get_stats = &ipg_nic_get_stats;
- dev->set_multicast_list = &ipg_nic_set_multicast_list;
- dev->do_ioctl = ipg_ioctl;
- dev->tx_timeout = ipg_tx_timeout;
- dev->change_mtu = &ipg_nic_change_mtu;
-
+ dev->netdev_ops = &ipg_netdev_ops;
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &ipg_ethtool_ops);
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 3c58e67ef1e4..17779f9bffc4 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -109,7 +109,6 @@ static int ali_ircc_net_open(struct net_device *dev);
static int ali_ircc_net_close(struct net_device *dev);
static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud);
-static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev);
/* SIR function */
static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -366,7 +365,6 @@ static int ali_ircc_open(int i, chipio_t *info)
dev->open = ali_ircc_net_open;
dev->stop = ali_ircc_net_close;
dev->do_ioctl = ali_ircc_net_ioctl;
- dev->get_stats = ali_ircc_net_get_stats;
err = register_netdev(dev);
if (err) {
@@ -876,7 +874,7 @@ static void ali_ircc_sir_receive(struct ali_ircc_cb *self)
* async_unwrap_char will deliver all found frames
*/
do {
- async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
+ async_unwrap_char(self->netdev, &self->netdev->stats, &self->rx_buff,
inb(iobase+UART_RX));
/* Make sure we don't stay here too long */
@@ -943,7 +941,7 @@ static void ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self)
netif_wake_queue(self->netdev);
}
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
/* Turn on receive interrupts */
outb(UART_IER_RDI, iobase+UART_IER);
@@ -1467,7 +1465,7 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
self->tx_fifo.tail += skb->len;
- self->stats.tx_bytes += skb->len;
+ dev->stats.tx_bytes += skb->len;
skb_copy_from_linear_data(skb, self->tx_fifo.queue[self->tx_fifo.free].start,
skb->len);
@@ -1661,12 +1659,12 @@ static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self)
{
IRDA_ERROR("%s(), ********* LSR_FRAME_ABORT *********\n", __func__);
- self->stats.tx_errors++;
- self->stats.tx_fifo_errors++;
+ self->netdev->stats.tx_errors++;
+ self->netdev->stats.tx_fifo_errors++;
}
else
{
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
}
/* Check if we need to change the speed */
@@ -1831,35 +1829,35 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self)
IRDA_DEBUG(0,"%s(), ************* RX Errors ************ \n", __func__ );
/* Skip frame */
- self->stats.rx_errors++;
+ self->netdev->stats.rx_errors++;
self->rx_buff.data += len;
if (status & LSR_FIFO_UR)
{
- self->stats.rx_frame_errors++;
+ self->netdev->stats.rx_frame_errors++;
IRDA_DEBUG(0,"%s(), ************* FIFO Errors ************ \n", __func__ );
}
if (status & LSR_FRAME_ERROR)
{
- self->stats.rx_frame_errors++;
+ self->netdev->stats.rx_frame_errors++;
IRDA_DEBUG(0,"%s(), ************* FRAME Errors ************ \n", __func__ );
}
if (status & LSR_CRC_ERROR)
{
- self->stats.rx_crc_errors++;
+ self->netdev->stats.rx_crc_errors++;
IRDA_DEBUG(0,"%s(), ************* CRC Errors ************ \n", __func__ );
}
if(self->rcvFramesOverflow)
{
- self->stats.rx_frame_errors++;
+ self->netdev->stats.rx_frame_errors++;
IRDA_DEBUG(0,"%s(), ************* Overran DMA buffer ************ \n", __func__ );
}
if(len == 0)
{
- self->stats.rx_frame_errors++;
+ self->netdev->stats.rx_frame_errors++;
IRDA_DEBUG(0,"%s(), ********** Receive Frame Size = 0 ********* \n", __func__ );
}
}
@@ -1910,7 +1908,7 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self)
IRDA_WARNING("%s(), memory squeeze, "
"dropping frame.\n",
__func__);
- self->stats.rx_dropped++;
+ self->netdev->stats.rx_dropped++;
return FALSE;
}
@@ -1924,8 +1922,8 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self)
/* Move to next frame */
self->rx_buff.data += len;
- self->stats.rx_bytes += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
@@ -1994,7 +1992,7 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
- self->stats.tx_bytes += self->tx_buff.len;
+ self->netdev->stats.tx_bytes += self->tx_buff.len;
/* Turn on transmit finished interrupt. Will fire immediately! */
outb(UART_IER_THRI, iobase+UART_IER);
@@ -2111,17 +2109,6 @@ static int ali_ircc_is_receiving(struct ali_ircc_cb *self)
return status;
}
-static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev)
-{
- struct ali_ircc_cb *self = netdev_priv(dev);
-
- IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ );
-
- IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __func__ );
-
- return &self->stats;
-}
-
static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state)
{
struct ali_ircc_cb *self = platform_get_drvdata(dev);
diff --git a/drivers/net/irda/ali-ircc.h b/drivers/net/irda/ali-ircc.h
index ed35d99763d5..0c8edb41bd0a 100644
--- a/drivers/net/irda/ali-ircc.h
+++ b/drivers/net/irda/ali-ircc.h
@@ -191,7 +191,6 @@ struct ali_ircc_cb {
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
- struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
diff --git a/drivers/net/irda/au1000_ircc.h b/drivers/net/irda/au1000_ircc.h
index b4763f24dded..c072c09a8d91 100644
--- a/drivers/net/irda/au1000_ircc.h
+++ b/drivers/net/irda/au1000_ircc.h
@@ -107,7 +107,6 @@ struct au1k_private {
iobuff_t rx_buff;
struct net_device *netdev;
- struct net_device_stats stats;
struct timeval stamp;
struct timeval now;
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index 6c4b53ffbcac..941164076a2b 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -53,7 +53,6 @@ static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *);
static int au1k_irda_rx(struct net_device *);
static void au1k_irda_interrupt(int, void *);
static void au1k_tx_timeout(struct net_device *);
-static struct net_device_stats *au1k_irda_stats(struct net_device *);
static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int);
static int au1k_irda_set_speed(struct net_device *dev, int speed);
@@ -213,7 +212,6 @@ static int au1k_irda_net_init(struct net_device *dev)
dev->open = au1k_irda_start;
dev->hard_start_xmit = au1k_irda_hard_xmit;
dev->stop = au1k_irda_stop;
- dev->get_stats = au1k_irda_stats;
dev->do_ioctl = au1k_irda_ioctl;
dev->tx_timeout = au1k_tx_timeout;
@@ -596,7 +594,7 @@ static int au1k_irda_rx(struct net_device *dev)
update_rx_stats(dev, flags, count);
skb=alloc_skb(count+1,GFP_ATOMIC);
if (skb == NULL) {
- aup->stats.rx_dropped++;
+ aup->netdev->stats.rx_dropped++;
continue;
}
skb_reserve(skb, 1);
@@ -832,13 +830,6 @@ au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
return ret;
}
-
-static struct net_device_stats *au1k_irda_stats(struct net_device *dev)
-{
- struct au1k_private *aup = netdev_priv(dev);
- return &aup->stats;
-}
-
MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
MODULE_DESCRIPTION("Au1000 IrDA Device Driver");
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 687c2d53d4d2..6f3e7f71658d 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -1194,13 +1194,13 @@ toshoboe_interrupt (int irq, void *dev_id)
txp = txpc;
txpc++;
txpc %= TX_SLOTS;
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS)
self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX;
}
- self->stats.tx_packets--;
+ self->netdev->stats.tx_packets--;
#else
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
#endif
toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX);
}
@@ -1280,7 +1280,7 @@ dumpbufs(self->rx_bufs[self->rxs],len,'<');
skb_put (skb, len);
skb_copy_to_linear_data(skb, self->rx_bufs[self->rxs],
len);
- self->stats.rx_packets++;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
skb->protocol = htons (ETH_P_IRDA);
diff --git a/drivers/net/irda/donauboe.h b/drivers/net/irda/donauboe.h
index 1e67720f1066..0dbd1932b72f 100644
--- a/drivers/net/irda/donauboe.h
+++ b/drivers/net/irda/donauboe.h
@@ -308,7 +308,6 @@ struct OboeRing
struct toshoboe_cb
{
struct net_device *netdev; /* Yes! we are some kind of netdevice */
- struct net_device_stats stats;
struct tty_driver ttydev;
struct irlap_cb *irlap; /* The link layer we are binded to */
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 205e4e825a97..3a22dc41b656 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -122,7 +122,6 @@ static int irda_usb_net_open(struct net_device *dev);
static int irda_usb_net_close(struct net_device *dev);
static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void irda_usb_net_timeout(struct net_device *dev);
-static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev);
/************************ TRANSMIT ROUTINES ************************/
/*
@@ -525,13 +524,13 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
/* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */
if ((res = usb_submit_urb(urb, GFP_ATOMIC))) {
IRDA_WARNING("%s(), failed Tx URB\n", __func__);
- self->stats.tx_errors++;
+ netdev->stats.tx_errors++;
/* Let USB recover : We will catch that in the watchdog */
/*netif_start_queue(netdev);*/
} else {
/* Increment packet stats */
- self->stats.tx_packets++;
- self->stats.tx_bytes += skb->len;
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
netdev->trans_start = jiffies;
}
@@ -677,7 +676,7 @@ static void irda_usb_net_timeout(struct net_device *netdev)
IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, urb->status, urb->transfer_flags);
/* Increase error count */
- self->stats.tx_errors++;
+ netdev->stats.tx_errors++;
#ifdef IU_BUG_KICK_TIMEOUT
/* Can't be a bad idea to reset the speed ;-) - Jean II */
@@ -826,7 +825,7 @@ static void irda_usb_receive(struct urb *urb)
if (urb->status != 0) {
switch (urb->status) {
case -EILSEQ:
- self->stats.rx_crc_errors++;
+ self->netdev->stats.rx_crc_errors++;
/* Also precursor to a hot-unplug on UHCI. */
/* Fallthrough... */
case -ECONNRESET:
@@ -839,7 +838,7 @@ static void irda_usb_receive(struct urb *urb)
case -ETIME:
/* Usually precursor to a hot-unplug on OHCI. */
default:
- self->stats.rx_errors++;
+ self->netdev->stats.rx_errors++;
IRDA_DEBUG(0, "%s(), RX status %d, transfer_flags 0x%04X \n", __func__, urb->status, urb->transfer_flags);
break;
}
@@ -890,7 +889,7 @@ static void irda_usb_receive(struct urb *urb)
IRDA_SKB_MAX_MTU);
if (!newskb) {
- self->stats.rx_dropped++;
+ self->netdev->stats.rx_dropped++;
/* We could deliver the current skb, but this would stall
* the Rx path. Better drop the packet... Jean II */
goto done;
@@ -927,8 +926,8 @@ static void irda_usb_receive(struct urb *urb)
netif_rx(dataskb);
/* Keep stats up to date */
- self->stats.rx_bytes += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
done:
/* Note : at this point, the URB we've just received (urb)
@@ -1074,7 +1073,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
{
unsigned int i;
int ret;
- char stir421x_fw_name[11];
+ char stir421x_fw_name[12];
const struct firmware *fw;
const unsigned char *fw_version_ptr; /* pointer to version string */
unsigned long fw_version = 0;
@@ -1342,14 +1341,6 @@ static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
/*------------------------------------------------------------------*/
-/*
- * Get device stats (for /proc/net/dev and ifconfig)
- */
-static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev)
-{
- struct irda_usb_cb *self = netdev_priv(dev);
- return &self->stats;
-}
/********************* IRDA CONFIG SUBROUTINES *********************/
/*
@@ -1428,7 +1419,6 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
netdev->watchdog_timeo = 250*HZ/1000; /* 250 ms > USB timeout */
netdev->open = irda_usb_net_open;
netdev->stop = irda_usb_net_close;
- netdev->get_stats = irda_usb_net_get_stats;
netdev->do_ioctl = irda_usb_net_ioctl;
return register_netdev(netdev);
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index a0ca9c1fe196..ac0443d52e50 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -152,7 +152,6 @@ struct irda_usb_cb {
struct urb *speed_urb; /* URB used to send speed commands */
struct net_device *netdev; /* Yes! we are some kind of netdev. */
- struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos;
char *speed_buff; /* Buffer for speed changes */
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index c747c874d44d..b4a61717254a 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -105,7 +105,7 @@ struct kingsun_cb {
struct usb_device *usbdev; /* init: probe_irda */
struct net_device *netdev; /* network layer */
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct net_device_stats stats; /* network statistics */
+
struct qos_info qos;
__u8 *in_buf; /* receive buffer */
@@ -186,12 +186,12 @@ static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
case -EPIPE:
break;
default:
- kingsun->stats.tx_errors++;
+ netdev->stats.tx_errors++;
netif_start_queue(netdev);
}
} else {
- kingsun->stats.tx_packets++;
- kingsun->stats.tx_bytes += skb->len;
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
}
dev_kfree_skb(skb);
@@ -232,7 +232,7 @@ static void kingsun_rcv_irq(struct urb *urb)
if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) {
for (i = 1; i <= bytes[0]; i++) {
async_unwrap_char(kingsun->netdev,
- &kingsun->stats,
+ &kingsun->netdev->stats,
&kingsun->rx_buff, bytes[i]);
}
do_gettimeofday(&kingsun->rx_time);
@@ -418,15 +418,6 @@ static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq,
return ret;
}
-/*
- * Get device stats (for /proc/net/dev and ifconfig)
- */
-static struct net_device_stats *
-kingsun_net_get_stats(struct net_device *netdev)
-{
- struct kingsun_cb *kingsun = netdev_priv(netdev);
- return &kingsun->stats;
-}
/*
* This routine is called by the USB subsystem for each new device
@@ -532,7 +523,6 @@ static int kingsun_probe(struct usb_interface *intf,
net->hard_start_xmit = kingsun_hard_xmit;
net->open = kingsun_net_open;
net->stop = kingsun_net_close;
- net->get_stats = kingsun_net_get_stats;
net->do_ioctl = kingsun_net_ioctl;
ret = register_netdev(net);
diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c
index 600d96f9cdb7..55322fb92cf1 100644
--- a/drivers/net/irda/ks959-sir.c
+++ b/drivers/net/irda/ks959-sir.c
@@ -174,7 +174,7 @@ struct ks959_cb {
struct usb_device *usbdev; /* init: probe_irda */
struct net_device *netdev; /* network layer */
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct net_device_stats stats; /* network statistics */
+
struct qos_info qos;
struct usb_ctrlrequest *tx_setuprequest;
@@ -366,7 +366,7 @@ static void ks959_send_irq(struct urb *urb)
case -EPIPE:
break;
default:
- kingsun->stats.tx_errors++;
+ netdev->stats.tx_errors++;
netif_start_queue(netdev);
}
}
@@ -416,12 +416,12 @@ static int ks959_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
case -EPIPE:
break;
default:
- kingsun->stats.tx_errors++;
+ netdev->stats.tx_errors++;
netif_start_queue(netdev);
}
} else {
- kingsun->stats.tx_packets++;
- kingsun->stats.tx_bytes += skb->len;
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
}
@@ -469,7 +469,7 @@ static void ks959_rcv_irq(struct urb *urb)
*/
if (kingsun->rx_variable_xormask != 0) {
async_unwrap_char(kingsun->netdev,
- &kingsun->stats,
+ &kingsun->netdev->stats,
&kingsun->rx_unwrap_buff,
bytes[i]);
}
@@ -669,15 +669,6 @@ static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
}
/*
- * Get device stats (for /proc/net/dev and ifconfig)
- */
-static struct net_device_stats *ks959_net_get_stats(struct net_device *netdev)
-{
- struct ks959_cb *kingsun = netdev_priv(netdev);
- return &kingsun->stats;
-}
-
-/*
* This routine is called by the USB subsystem for each new device
* in the system. We need to check if the device is ours, and in
* this case start handling it.
@@ -792,7 +783,6 @@ static int ks959_probe(struct usb_interface *intf,
net->hard_start_xmit = ks959_hard_xmit;
net->open = ks959_net_open;
net->stop = ks959_net_close;
- net->get_stats = ks959_net_get_stats;
net->do_ioctl = ks959_net_ioctl;
ret = register_netdev(net);
diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c
index 0e7f89337b25..5b327b09acd8 100644
--- a/drivers/net/irda/ksdazzle-sir.c
+++ b/drivers/net/irda/ksdazzle-sir.c
@@ -140,7 +140,7 @@ struct ksdazzle_cb {
struct usb_device *usbdev; /* init: probe_irda */
struct net_device *netdev; /* network layer */
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct net_device_stats stats; /* network statistics */
+
struct qos_info qos;
struct urb *tx_urb;
@@ -278,7 +278,7 @@ static void ksdazzle_send_irq(struct urb *urb)
case -EPIPE:
break;
default:
- kingsun->stats.tx_errors++;
+ netdev->stats.tx_errors++;
netif_start_queue(netdev);
}
}
@@ -329,12 +329,12 @@ static int ksdazzle_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
case -EPIPE:
break;
default:
- kingsun->stats.tx_errors++;
+ netdev->stats.tx_errors++;
netif_start_queue(netdev);
}
} else {
- kingsun->stats.tx_packets++;
- kingsun->stats.tx_bytes += skb->len;
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += skb->len;
}
@@ -348,9 +348,10 @@ static int ksdazzle_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
static void ksdazzle_rcv_irq(struct urb *urb)
{
struct ksdazzle_cb *kingsun = urb->context;
+ struct net_device *netdev = kingsun->netdev;
/* in process of stopping, just drop data */
- if (!netif_running(kingsun->netdev)) {
+ if (!netif_running(netdev)) {
kingsun->receiving = 0;
return;
}
@@ -368,7 +369,7 @@ static void ksdazzle_rcv_irq(struct urb *urb)
unsigned int i;
for (i = 0; i < urb->actual_length; i++) {
- async_unwrap_char(kingsun->netdev, &kingsun->stats,
+ async_unwrap_char(netdev, &netdev->stats,
&kingsun->rx_unwrap_buff, bytes[i]);
}
kingsun->receiving =
@@ -562,16 +563,6 @@ static int ksdazzle_net_ioctl(struct net_device *netdev, struct ifreq *rq,
}
/*
- * Get device stats (for /proc/net/dev and ifconfig)
- */
-static struct net_device_stats *ksdazzle_net_get_stats(struct net_device
- *netdev)
-{
- struct ksdazzle_cb *kingsun = netdev_priv(netdev);
- return &kingsun->stats;
-}
-
-/*
* This routine is called by the USB subsystem for each new device
* in the system. We need to check if the device is ours, and in
* this case start handling it.
@@ -696,7 +687,6 @@ static int ksdazzle_probe(struct usb_interface *intf,
net->hard_start_xmit = ksdazzle_hard_xmit;
net->open = ksdazzle_net_open;
net->stop = ksdazzle_net_close;
- net->get_stats = ksdazzle_net_get_stats;
net->do_ioctl = ksdazzle_net_ioctl;
ret = register_netdev(net);
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 904c9610c0dd..7eafdca19f34 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -403,8 +403,8 @@ static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len)
if(unlikely(new_len <= 0)) {
IRDA_ERROR("%s short frame length %d\n",
mcs->netdev->name, new_len);
- ++mcs->stats.rx_errors;
- ++mcs->stats.rx_length_errors;
+ ++mcs->netdev->stats.rx_errors;
+ ++mcs->netdev->stats.rx_length_errors;
return;
}
fcs = 0;
@@ -413,14 +413,14 @@ static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len)
if(fcs != GOOD_FCS) {
IRDA_ERROR("crc error calc 0x%x len %d\n",
fcs, new_len);
- mcs->stats.rx_errors++;
- mcs->stats.rx_crc_errors++;
+ mcs->netdev->stats.rx_errors++;
+ mcs->netdev->stats.rx_crc_errors++;
return;
}
skb = dev_alloc_skb(new_len + 1);
if(unlikely(!skb)) {
- ++mcs->stats.rx_dropped;
+ ++mcs->netdev->stats.rx_dropped;
return;
}
@@ -433,8 +433,8 @@ static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len)
netif_rx(skb);
- mcs->stats.rx_packets++;
- mcs->stats.rx_bytes += new_len;
+ mcs->netdev->stats.rx_packets++;
+ mcs->netdev->stats.rx_bytes += new_len;
return;
}
@@ -458,22 +458,22 @@ static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
if(unlikely(new_len <= 0)) {
IRDA_ERROR("%s short frame length %d\n",
mcs->netdev->name, new_len);
- ++mcs->stats.rx_errors;
- ++mcs->stats.rx_length_errors;
+ ++mcs->netdev->stats.rx_errors;
+ ++mcs->netdev->stats.rx_length_errors;
return;
}
fcs = ~(crc32_le(~0, buf, new_len));
if(fcs != get_unaligned_le32(buf + new_len)) {
IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len);
- mcs->stats.rx_errors++;
- mcs->stats.rx_crc_errors++;
+ mcs->netdev->stats.rx_errors++;
+ mcs->netdev->stats.rx_crc_errors++;
return;
}
skb = dev_alloc_skb(new_len + 1);
if(unlikely(!skb)) {
- ++mcs->stats.rx_dropped;
+ ++mcs->netdev->stats.rx_dropped;
return;
}
@@ -486,8 +486,8 @@ static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
netif_rx(skb);
- mcs->stats.rx_packets++;
- mcs->stats.rx_bytes += new_len;
+ mcs->netdev->stats.rx_packets++;
+ mcs->netdev->stats.rx_bytes += new_len;
return;
}
@@ -756,14 +756,6 @@ static int mcs_net_open(struct net_device *netdev)
return ret;
}
-
-/* Get device stats for /proc/net/dev and ifconfig */
-static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev)
-{
- struct mcs_cb *mcs = netdev_priv(netdev);
- return &mcs->stats;
-}
-
/* Receive callback function. */
static void mcs_receive_irq(struct urb *urb)
{
@@ -786,14 +778,14 @@ static void mcs_receive_irq(struct urb *urb)
*/
/* SIR speed */
if(mcs->speed < 576000) {
- async_unwrap_char(mcs->netdev, &mcs->stats,
+ async_unwrap_char(mcs->netdev, &mcs->netdev->stats,
&mcs->rx_buff, 0xc0);
for (i = 0; i < urb->actual_length; i++)
- async_unwrap_char(mcs->netdev, &mcs->stats,
+ async_unwrap_char(mcs->netdev, &mcs->netdev->stats,
&mcs->rx_buff, bytes[i]);
- async_unwrap_char(mcs->netdev, &mcs->stats,
+ async_unwrap_char(mcs->netdev, &mcs->netdev->stats,
&mcs->rx_buff, 0xc1);
}
/* MIR speed */
@@ -868,12 +860,12 @@ static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
case -EPIPE:
break;
default:
- mcs->stats.tx_errors++;
+ mcs->netdev->stats.tx_errors++;
netif_start_queue(ndev);
}
} else {
- mcs->stats.tx_packets++;
- mcs->stats.tx_bytes += skb->len;
+ mcs->netdev->stats.tx_packets++;
+ mcs->netdev->stats.tx_bytes += skb->len;
}
dev_kfree_skb(skb);
@@ -931,7 +923,6 @@ static int mcs_probe(struct usb_interface *intf,
ndev->hard_start_xmit = mcs_hard_xmit;
ndev->open = mcs_net_open;
ndev->stop = mcs_net_close;
- ndev->get_stats = mcs_net_get_stats;
ndev->do_ioctl = mcs_net_ioctl;
if (!intf->cur_altsetting)
diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h
index b18148cee638..6bdc621e67c6 100644
--- a/drivers/net/irda/mcs7780.h
+++ b/drivers/net/irda/mcs7780.h
@@ -104,7 +104,6 @@ struct mcs_cb {
struct usb_device *usbdev; /* init: probe_irda */
struct net_device *netdev; /* network layer */
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct net_device_stats stats; /* network statistics */
struct qos_info qos;
unsigned int speed; /* Current speed */
unsigned int new_speed; /* new speed */
@@ -154,7 +153,6 @@ static int mcs_speed_change(struct mcs_cb *mcs);
static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd);
static int mcs_net_close(struct net_device *netdev);
static int mcs_net_open(struct net_device *netdev);
-static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev);
static void mcs_receive_irq(struct urb *urb);
static void mcs_send_irq(struct urb *urb);
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 2c6bf2d11bb1..61e509cb712a 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -185,7 +185,6 @@ static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id);
static int nsc_ircc_net_open(struct net_device *dev);
static int nsc_ircc_net_close(struct net_device *dev);
static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
/* Globals */
static int pnp_registered;
@@ -446,7 +445,6 @@ static int __init nsc_ircc_open(chipio_t *info)
dev->open = nsc_ircc_net_open;
dev->stop = nsc_ircc_net_close;
dev->do_ioctl = nsc_ircc_net_ioctl;
- dev->get_stats = nsc_ircc_net_get_stats;
err = register_netdev(dev);
if (err) {
@@ -1401,7 +1399,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
- self->stats.tx_bytes += self->tx_buff.len;
+ dev->stats.tx_bytes += self->tx_buff.len;
/* Add interrupt on tx low level (will fire immediately) */
switch_bank(iobase, BANK0);
@@ -1473,7 +1471,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
self->tx_fifo.tail += skb->len;
- self->stats.tx_bytes += skb->len;
+ dev->stats.tx_bytes += skb->len;
skb_copy_from_linear_data(skb, self->tx_fifo.queue[self->tx_fifo.free].start,
skb->len);
@@ -1652,13 +1650,13 @@ static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self)
/* Check for underrrun! */
if (inb(iobase+ASCR) & ASCR_TXUR) {
- self->stats.tx_errors++;
- self->stats.tx_fifo_errors++;
+ self->netdev->stats.tx_errors++;
+ self->netdev->stats.tx_fifo_errors++;
/* Clear bit, by writing 1 into it */
outb(ASCR_TXUR, iobase+ASCR);
} else {
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
}
/* Finished with this frame, so prepare for next */
@@ -1793,28 +1791,28 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
if (status & FRM_ST_ERR_MSK) {
if (status & FRM_ST_LOST_FR) {
/* Add number of lost frames to stats */
- self->stats.rx_errors += len;
+ self->netdev->stats.rx_errors += len;
} else {
/* Skip frame */
- self->stats.rx_errors++;
+ self->netdev->stats.rx_errors++;
self->rx_buff.data += len;
if (status & FRM_ST_MAX_LEN)
- self->stats.rx_length_errors++;
+ self->netdev->stats.rx_length_errors++;
if (status & FRM_ST_PHY_ERR)
- self->stats.rx_frame_errors++;
+ self->netdev->stats.rx_frame_errors++;
if (status & FRM_ST_BAD_CRC)
- self->stats.rx_crc_errors++;
+ self->netdev->stats.rx_crc_errors++;
}
/* The errors below can be reported in both cases */
if (status & FRM_ST_OVR1)
- self->stats.rx_fifo_errors++;
+ self->netdev->stats.rx_fifo_errors++;
if (status & FRM_ST_OVR2)
- self->stats.rx_fifo_errors++;
+ self->netdev->stats.rx_fifo_errors++;
} else {
/*
* First we must make sure that the frame we
@@ -1863,7 +1861,7 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
IRDA_WARNING("%s(), memory squeeze, "
"dropping frame.\n",
__func__);
- self->stats.rx_dropped++;
+ self->netdev->stats.rx_dropped++;
/* Restore bank register */
outb(bank, iobase+BSR);
@@ -1889,8 +1887,8 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
/* Move to next frame */
self->rx_buff.data += len;
- self->stats.rx_bytes += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
@@ -1920,8 +1918,8 @@ static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self)
/* Receive all characters in Rx FIFO */
do {
byte = inb(iobase+RXD);
- async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
- byte);
+ async_unwrap_char(self->netdev, &self->netdev->stats,
+ &self->rx_buff, byte);
} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */
}
@@ -1952,7 +1950,7 @@ static void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir)
self->ier = IER_TXLDL_IE;
else {
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
netif_wake_queue(self->netdev);
self->ier = IER_TXEMP_IE;
}
@@ -2307,13 +2305,6 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return ret;
}
-static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
-{
- struct nsc_ircc_cb *self = netdev_priv(dev);
-
- return &self->stats;
-}
-
static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state)
{
struct nsc_ircc_cb *self = platform_get_drvdata(dev);
diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h
index 71cd3c5a0762..7ba7738759b9 100644
--- a/drivers/net/irda/nsc-ircc.h
+++ b/drivers/net/irda/nsc-ircc.h
@@ -251,7 +251,6 @@ struct nsc_ircc_cb {
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
- struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 004a9aab3a50..31794c2363ec 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -108,7 +108,6 @@ struct pxa_irda {
int txdma;
int rxdma;
- struct net_device_stats stats;
struct irlap_cb *irlap;
struct qos_info qos;
@@ -258,14 +257,15 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
data = STRBR;
if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
- si->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (lsr & LSR_FE)
- si->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (lsr & LSR_OE)
- si->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
} else {
- si->stats.rx_bytes++;
- async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
+ dev->stats.rx_bytes++;
+ async_unwrap_char(dev, &dev->stats,
+ &si->rx_buff, data);
}
lsr = STLSR;
}
@@ -277,8 +277,8 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
case 0x0C: /* Character Timeout Indication */
do {
- si->stats.rx_bytes++;
- async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
+ dev->stats.rx_bytes++;
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR);
} while (STLSR & LSR_DR);
si->last_oscr = OSCR;
break;
@@ -290,9 +290,8 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
}
if (si->tx_buff.len == 0) {
- si->stats.tx_packets++;
- si->stats.tx_bytes += si->tx_buff.data -
- si->tx_buff.head;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head;
/* We need to ensure that the transmitter has finished. */
while ((STLSR & LSR_TEMT) == 0)
@@ -343,10 +342,10 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
DCSR(channel) = dcsr & ~DCSR_RUN;
if (dcsr & DCSR_ENDINTR) {
- si->stats.tx_packets++;
- si->stats.tx_bytes += si->dma_tx_buff_len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += si->dma_tx_buff_len;
} else {
- si->stats.tx_errors++;
+ dev->stats.tx_errors++;
}
while (ICSR1 & ICSR1_TBY)
@@ -392,14 +391,14 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in
data = ICDR;
if (stat & (ICSR1_CRE | ICSR1_ROR)) {
- si->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (stat & ICSR1_CRE) {
printk(KERN_DEBUG "pxa_ir: fir receive CRC error\n");
- si->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
}
if (stat & ICSR1_ROR) {
printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
- si->stats.rx_over_errors++;
+ dev->stats.rx_over_errors++;
}
} else {
si->dma_rx_buff[len++] = data;
@@ -415,14 +414,14 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in
if (icsr0 & ICSR0_FRE) {
printk(KERN_ERR "pxa_ir: dropping erroneous frame\n");
- si->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
return;
}
skb = alloc_skb(len+1,GFP_ATOMIC);
if (!skb) {
printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
- si->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
return;
}
@@ -437,8 +436,8 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
- si->stats.rx_packets++;
- si->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
}
}
@@ -457,10 +456,10 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
if (icsr0 & ICSR0_FRE) {
printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");
- si->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
} else {
printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
- si->stats.rx_errors++;
+ dev->stats.rx_errors++;
}
ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
}
@@ -589,12 +588,6 @@ static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
return ret;
}
-static struct net_device_stats *pxa_irda_stats(struct net_device *dev)
-{
- struct pxa_irda *si = netdev_priv(dev);
- return &si->stats;
-}
-
static void pxa_irda_startup(struct pxa_irda *si)
{
/* Disable STUART interrupts */
@@ -857,7 +850,6 @@ static int pxa_irda_probe(struct platform_device *pdev)
dev->open = pxa_irda_start;
dev->stop = pxa_irda_stop;
dev->do_ioctl = pxa_irda_ioctl;
- dev->get_stats = pxa_irda_stats;
irda_init_max_qos_capabilies(&si->qos);
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index d302bcf4c148..7a2b003954ca 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -60,7 +60,6 @@ struct sa1100_irda {
dma_regs_t *txdma;
dma_regs_t *rxdma;
- struct net_device_stats stats;
struct device *dev;
struct irda_platform_data *pdata;
struct irlap_cb *irlap;
@@ -375,13 +374,13 @@ static void sa1100_irda_hpsir_irq(struct net_device *dev)
data = Ser2UTDR;
if (stat & (UTSR1_FRE | UTSR1_ROR)) {
- si->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (stat & UTSR1_FRE)
- si->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
if (stat & UTSR1_ROR)
- si->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
} else
- async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff, data);
status = Ser2UTSR0;
}
@@ -396,9 +395,9 @@ static void sa1100_irda_hpsir_irq(struct net_device *dev)
* There are at least 4 bytes in the FIFO. Read 3 bytes
* and leave the rest to the block below.
*/
- async_unwrap_char(dev, &si->stats, &si->rx_buff, Ser2UTDR);
- async_unwrap_char(dev, &si->stats, &si->rx_buff, Ser2UTDR);
- async_unwrap_char(dev, &si->stats, &si->rx_buff, Ser2UTDR);
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR);
}
if (status & (UTSR0_RFS | UTSR0_RID)) {
@@ -406,7 +405,7 @@ static void sa1100_irda_hpsir_irq(struct net_device *dev)
* Fifo contains more than 1 character.
*/
do {
- async_unwrap_char(dev, &si->stats, &si->rx_buff,
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff,
Ser2UTDR);
} while (Ser2UTSR1 & UTSR1_RNE);
@@ -422,8 +421,8 @@ static void sa1100_irda_hpsir_irq(struct net_device *dev)
} while (Ser2UTSR1 & UTSR1_TNF && si->tx_buff.len);
if (si->tx_buff.len == 0) {
- si->stats.tx_packets++;
- si->stats.tx_bytes += si->tx_buff.data -
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += si->tx_buff.data -
si->tx_buff.head;
/*
@@ -482,11 +481,11 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
data = Ser2HSDR;
if (stat & (HSSR1_CRE | HSSR1_ROR)) {
- si->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (stat & HSSR1_CRE)
- si->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (stat & HSSR1_ROR)
- si->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
} else
skb->data[len++] = data;
@@ -505,8 +504,8 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
skb->dev = dev;
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
- si->stats.rx_packets++;
- si->stats.rx_bytes += len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
/*
* Before we pass the buffer up, allocate a new one.
@@ -545,10 +544,10 @@ static void sa1100_irda_fir_irq(struct net_device *dev)
* from the fifo.
*/
if (Ser2HSSR0 & (HSSR0_FRE | HSSR0_RAB)) {
- si->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (Ser2HSSR0 & HSSR0_FRE)
- si->stats.rx_frame_errors++;
+ dev->stats.rx_frame_errors++;
/*
* Clear out the DMA...
@@ -633,8 +632,8 @@ static void sa1100_irda_txdma_irq(void *id)
*/
if (skb) {
dma_unmap_single(si->dev, si->txbuf_dma, skb->len, DMA_TO_DEVICE);
- si->stats.tx_packets ++;
- si->stats.tx_bytes += skb->len;
+ dev->stats.tx_packets ++;
+ dev->stats.tx_bytes += skb->len;
dev_kfree_skb_irq(skb);
}
@@ -762,12 +761,6 @@ sa1100_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
return ret;
}
-static struct net_device_stats *sa1100_irda_stats(struct net_device *dev)
-{
- struct sa1100_irda *si = netdev_priv(dev);
- return &si->stats;
-}
-
static int sa1100_irda_start(struct net_device *dev)
{
struct sa1100_irda *si = netdev_priv(dev);
@@ -924,7 +917,6 @@ static int sa1100_irda_probe(struct platform_device *pdev)
dev->open = sa1100_irda_start;
dev->stop = sa1100_irda_stop;
dev->do_ioctl = sa1100_irda_ioctl;
- dev->get_stats = sa1100_irda_stats;
dev->irq = IRQ_Ser2ICP;
irda_init_max_qos_capabilies(&si->qos);
diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h
index 2a57bc67ce35..6d5b1e2b1289 100644
--- a/drivers/net/irda/sir-dev.h
+++ b/drivers/net/irda/sir-dev.h
@@ -160,7 +160,6 @@ static inline int sirdev_schedule_mode(struct sir_dev *dev, int mode)
struct sir_dev {
struct net_device *netdev;
- struct net_device_stats stats;
struct irlap_cb *irlap;
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index ceef040aa76d..5b5862499def 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -455,8 +455,8 @@ void sirdev_write_complete(struct sir_dev *dev)
if ((skb=dev->tx_skb) != NULL) {
dev->tx_skb = NULL;
dev_kfree_skb_any(skb);
- dev->stats.tx_errors++;
- dev->stats.tx_dropped++;
+ dev->netdev->stats.tx_errors++;
+ dev->netdev->stats.tx_dropped++;
}
dev->tx_buff.len = 0;
}
@@ -493,8 +493,8 @@ void sirdev_write_complete(struct sir_dev *dev)
if ((skb=dev->tx_skb) != NULL) {
dev->tx_skb = NULL;
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
+ dev->netdev->stats.tx_packets++;
+ dev->netdev->stats.tx_bytes += skb->len;
dev_kfree_skb_any(skb);
}
@@ -548,7 +548,7 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
* just update stats and set media busy
*/
irda_device_set_media_busy(dev->netdev, TRUE);
- dev->stats.rx_dropped++;
+ dev->netdev->stats.rx_dropped++;
IRDA_DEBUG(0, "%s; rx-drop: %zd\n", __func__, count);
return 0;
}
@@ -557,7 +557,7 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
if (likely(atomic_read(&dev->enable_rx))) {
while (count--)
/* Unwrap and destuff one byte */
- async_unwrap_char(dev->netdev, &dev->stats,
+ async_unwrap_char(dev->netdev, &dev->netdev->stats,
&dev->rx_buff, *cp++);
} else {
while (count--) {
@@ -582,13 +582,6 @@ EXPORT_SYMBOL(sirdev_receive);
/* callbacks from network layer */
-static struct net_device_stats *sirdev_get_stats(struct net_device *ndev)
-{
- struct sir_dev *dev = netdev_priv(ndev);
-
- return (dev) ? &dev->stats : NULL;
-}
-
static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct sir_dev *dev = netdev_priv(ndev);
@@ -654,7 +647,7 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
*/
atomic_set(&dev->enable_rx, 0);
if (unlikely(sirdev_is_receiving(dev)))
- dev->stats.collisions++;
+ dev->netdev->stats.collisions++;
actual = dev->drv->do_write(dev, dev->tx_buff.data, dev->tx_buff.len);
@@ -669,8 +662,8 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
IRDA_ERROR("%s: drv->do_write failed (%d)\n",
__func__, actual);
dev_kfree_skb_any(skb);
- dev->stats.tx_errors++;
- dev->stats.tx_dropped++;
+ dev->netdev->stats.tx_errors++;
+ dev->netdev->stats.tx_dropped++;
netif_wake_queue(ndev);
}
spin_unlock_irqrestore(&dev->tx_lock, flags);
@@ -918,7 +911,6 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
ndev->hard_start_xmit = sirdev_hard_xmit;
ndev->open = sirdev_open;
ndev->stop = sirdev_close;
- ndev->get_stats = sirdev_get_stats;
ndev->do_ioctl = sirdev_ioctl;
if (register_netdev(ndev)) {
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 5d09e157e15b..dd73cce10991 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -150,7 +150,6 @@ struct smsc_chip_address {
/* Private data for each instance */
struct smsc_ircc_cb {
struct net_device *netdev; /* Yes! we are some kind of netdevice */
- struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
chipio_t io; /* IrDA controller information */
@@ -215,7 +214,6 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cm
#if SMSC_IRCC2_C_NET_TIMEOUT
static void smsc_ircc_timeout(struct net_device *dev);
#endif
-static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev);
static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self);
static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self);
static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed);
@@ -529,7 +527,6 @@ static int __init smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u
dev->open = smsc_ircc_net_open;
dev->stop = smsc_ircc_net_close;
dev->do_ioctl = smsc_ircc_net_ioctl;
- dev->get_stats = smsc_ircc_net_get_stats;
self = netdev_priv(dev);
self->netdev = dev;
@@ -834,13 +831,6 @@ static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd
return ret;
}
-static struct net_device_stats *smsc_ircc_net_get_stats(struct net_device *dev)
-{
- struct smsc_ircc_cb *self = netdev_priv(dev);
-
- return &self->stats;
-}
-
#if SMSC_IRCC2_C_NET_TIMEOUT
/*
* Function smsc_ircc_timeout (struct net_device *dev)
@@ -920,7 +910,7 @@ static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
- self->stats.tx_bytes += self->tx_buff.len;
+ dev->stats.tx_bytes += self->tx_buff.len;
/* Turn on transmit finished interrupt. Will fire immediately! */
outb(UART_IER_THRI, self->io.sir_base + UART_IER);
@@ -1320,16 +1310,16 @@ static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self)
/* Check for underrun! */
register_bank(iobase, 0);
if (inb(iobase + IRCC_LSR) & IRCC_LSR_UNDERRUN) {
- self->stats.tx_errors++;
- self->stats.tx_fifo_errors++;
+ self->netdev->stats.tx_errors++;
+ self->netdev->stats.tx_fifo_errors++;
/* Reset error condition */
register_bank(iobase, 0);
outb(IRCC_MASTER_ERROR_RESET, iobase + IRCC_MASTER);
outb(0x00, iobase + IRCC_MASTER);
} else {
- self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
+ self->netdev->stats.tx_packets++;
+ self->netdev->stats.tx_bytes += self->tx_buff.len;
}
/* Check if it's time to change the speed */
@@ -1429,15 +1419,15 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self)
/* Look for errors */
if (lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) {
- self->stats.rx_errors++;
+ self->netdev->stats.rx_errors++;
if (lsr & IRCC_LSR_FRAME_ERROR)
- self->stats.rx_frame_errors++;
+ self->netdev->stats.rx_frame_errors++;
if (lsr & IRCC_LSR_CRC_ERROR)
- self->stats.rx_crc_errors++;
+ self->netdev->stats.rx_crc_errors++;
if (lsr & IRCC_LSR_SIZE_ERROR)
- self->stats.rx_length_errors++;
+ self->netdev->stats.rx_length_errors++;
if (lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN))
- self->stats.rx_length_errors++;
+ self->netdev->stats.rx_length_errors++;
return;
}
@@ -1460,8 +1450,8 @@ static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self)
skb_reserve(skb, 1);
memcpy(skb_put(skb, len), self->rx_buff.data, len);
- self->stats.rx_packets++;
- self->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
@@ -1489,7 +1479,7 @@ static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self)
* async_unwrap_char will deliver all found frames
*/
do {
- async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
+ async_unwrap_char(self->netdev, &self->netdev->stats, &self->rx_buff,
inb(iobase + UART_RX));
/* Make sure we don't stay here to long */
@@ -1992,7 +1982,7 @@ static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self)
/* Tell network layer that we want more frames */
netif_wake_queue(self->netdev);
}
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
if (self->io.speed <= 115200) {
/*
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index ca4cd9266e55..8b1658c6c925 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -164,7 +164,7 @@ struct stir_cb {
struct usb_device *usbdev; /* init: probe_irda */
struct net_device *netdev; /* network layer */
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct net_device_stats stats; /* network statistics */
+
struct qos_info qos;
unsigned speed; /* Current speed */
@@ -323,16 +323,16 @@ static void fir_eof(struct stir_cb *stir)
pr_debug("%s: short frame len %d\n",
stir->netdev->name, len);
- ++stir->stats.rx_errors;
- ++stir->stats.rx_length_errors;
+ ++stir->netdev->stats.rx_errors;
+ ++stir->netdev->stats.rx_length_errors;
return;
}
fcs = ~(crc32_le(~0, rx_buff->data, len));
if (fcs != get_unaligned_le32(rx_buff->data + len)) {
pr_debug("crc error calc 0x%x len %d\n", fcs, len);
- stir->stats.rx_errors++;
- stir->stats.rx_crc_errors++;
+ stir->netdev->stats.rx_errors++;
+ stir->netdev->stats.rx_crc_errors++;
return;
}
@@ -340,7 +340,7 @@ static void fir_eof(struct stir_cb *stir)
if (len < IRDA_RX_COPY_THRESHOLD) {
nskb = dev_alloc_skb(len + 1);
if (unlikely(!nskb)) {
- ++stir->stats.rx_dropped;
+ ++stir->netdev->stats.rx_dropped;
return;
}
skb_reserve(nskb, 1);
@@ -349,7 +349,7 @@ static void fir_eof(struct stir_cb *stir)
} else {
nskb = dev_alloc_skb(rx_buff->truesize);
if (unlikely(!nskb)) {
- ++stir->stats.rx_dropped;
+ ++stir->netdev->stats.rx_dropped;
return;
}
skb_reserve(nskb, 1);
@@ -366,8 +366,8 @@ static void fir_eof(struct stir_cb *stir)
netif_rx(skb);
- stir->stats.rx_packets++;
- stir->stats.rx_bytes += len;
+ stir->netdev->stats.rx_packets++;
+ stir->netdev->stats.rx_bytes += len;
rx_buff->data = rx_buff->head;
rx_buff->len = 0;
@@ -437,7 +437,7 @@ static void stir_fir_chars(struct stir_cb *stir,
if (unlikely(rx_buff->len >= rx_buff->truesize)) {
pr_debug("%s: fir frame exceeds %d\n",
stir->netdev->name, rx_buff->truesize);
- ++stir->stats.rx_over_errors;
+ ++stir->netdev->stats.rx_over_errors;
goto error_recovery;
}
@@ -445,10 +445,10 @@ static void stir_fir_chars(struct stir_cb *stir,
continue;
frame_error:
- ++stir->stats.rx_frame_errors;
+ ++stir->netdev->stats.rx_frame_errors;
error_recovery:
- ++stir->stats.rx_errors;
+ ++stir->netdev->stats.rx_errors;
rx_buff->state = OUTSIDE_FRAME;
rx_buff->in_frame = FALSE;
}
@@ -461,7 +461,7 @@ static void stir_sir_chars(struct stir_cb *stir,
int i;
for (i = 0; i < len; i++)
- async_unwrap_char(stir->netdev, &stir->stats,
+ async_unwrap_char(stir->netdev, &stir->netdev->stats,
&stir->rx_buff, bytes[i]);
}
@@ -692,7 +692,7 @@ static void receive_stop(struct stir_cb *stir)
usb_kill_urb(stir->rx_urb);
if (stir->rx_buff.in_frame)
- stir->stats.collisions++;
+ stir->netdev->stats.collisions++;
}
/*
* Wrap data in socket buffer and send it.
@@ -718,15 +718,15 @@ static void stir_send(struct stir_cb *stir, struct sk_buff *skb)
if (!first_frame)
fifo_txwait(stir, wraplen);
- stir->stats.tx_packets++;
- stir->stats.tx_bytes += skb->len;
+ stir->netdev->stats.tx_packets++;
+ stir->netdev->stats.tx_bytes += skb->len;
stir->netdev->trans_start = jiffies;
pr_debug("send %d (%d)\n", skb->len, wraplen);
if (usb_bulk_msg(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1),
stir->io_buf, wraplen,
NULL, TRANSMIT_TIMEOUT))
- stir->stats.tx_errors++;
+ stir->netdev->stats.tx_errors++;
}
/*
@@ -1008,15 +1008,6 @@ static int stir_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
}
/*
- * Get device stats (for /proc/net/dev and ifconfig)
- */
-static struct net_device_stats *stir_net_get_stats(struct net_device *netdev)
-{
- struct stir_cb *stir = netdev_priv(netdev);
- return &stir->stats;
-}
-
-/*
* This routine is called by the USB subsystem for each new device
* in the system. We need to check if the device is ours, and in
* this case start handling it.
@@ -1066,7 +1057,6 @@ static int stir_probe(struct usb_interface *intf,
net->hard_start_xmit = stir_hard_xmit;
net->open = stir_net_open;
net->stop = stir_net_close;
- net->get_stats = stir_net_get_stats;
net->do_ioctl = stir_net_ioctl;
ret = register_netdev(net);
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index 74c78cf7a333..8b3e545924cc 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -101,8 +101,6 @@ static int via_ircc_net_open(struct net_device *dev);
static int via_ircc_net_close(struct net_device *dev);
static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq,
int cmd);
-static struct net_device_stats *via_ircc_net_get_stats(struct net_device
- *dev);
static void via_ircc_change_dongle_speed(int iobase, int speed,
int dongle_id);
static int RxTimerHandler(struct via_ircc_cb *self, int iobase);
@@ -434,7 +432,6 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
dev->open = via_ircc_net_open;
dev->stop = via_ircc_net_close;
dev->do_ioctl = via_ircc_net_ioctl;
- dev->get_stats = via_ircc_net_get_stats;
err = register_netdev(dev);
if (err)
@@ -855,7 +852,7 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb,
async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
- self->stats.tx_bytes += self->tx_buff.len;
+ dev->stats.tx_bytes += self->tx_buff.len;
/* Send this frame with old speed */
SetBaudRate(iobase, self->io.speed);
SetPulseWidth(iobase, 12);
@@ -921,7 +918,7 @@ static int via_ircc_hard_xmit_fir(struct sk_buff *skb,
self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
self->tx_fifo.tail += skb->len;
- self->stats.tx_bytes += skb->len;
+ dev->stats.tx_bytes += skb->len;
skb_copy_from_linear_data(skb,
self->tx_fifo.queue[self->tx_fifo.free].start, skb->len);
self->tx_fifo.len++;
@@ -990,12 +987,12 @@ static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self)
/* Clear bit, by writing 1 into it */
Tx_status = GetTXStatus(iobase);
if (Tx_status & 0x08) {
- self->stats.tx_errors++;
- self->stats.tx_fifo_errors++;
+ self->netdev->stats.tx_errors++;
+ self->netdev->stats.tx_fifo_errors++;
hwreset(self);
// how to clear underrrun ?
} else {
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
ResetChip(iobase, 3);
ResetChip(iobase, 4);
}
@@ -1119,8 +1116,8 @@ static int via_ircc_dma_receive_complete(struct via_ircc_cb *self,
}
// Move to next frame
self->rx_buff.data += len;
- self->stats.rx_bytes += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
@@ -1180,7 +1177,7 @@ F01_E */
*/
if ((skb == NULL) || (skb->data == NULL)
|| (self->rx_buff.data == NULL) || (len < 6)) {
- self->stats.rx_dropped++;
+ self->netdev->stats.rx_dropped++;
return TRUE;
}
skb_reserve(skb, 1);
@@ -1192,8 +1189,8 @@ F01_E */
// Move to next frame
self->rx_buff.data += len;
- self->stats.rx_bytes += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
@@ -1220,13 +1217,13 @@ static int upload_rxdata(struct via_ircc_cb *self, int iobase)
IRDA_DEBUG(2, "%s(): len=%x\n", __func__, len);
if ((len - 4) < 2) {
- self->stats.rx_dropped++;
+ self->netdev->stats.rx_dropped++;
return FALSE;
}
skb = dev_alloc_skb(len + 1);
if (skb == NULL) {
- self->stats.rx_dropped++;
+ self->netdev->stats.rx_dropped++;
return FALSE;
}
skb_reserve(skb, 1);
@@ -1238,8 +1235,8 @@ static int upload_rxdata(struct via_ircc_cb *self, int iobase)
st_fifo->tail = 0;
// Move to next frame
self->rx_buff.data += len;
- self->stats.rx_bytes += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
@@ -1295,7 +1292,7 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase)
*/
if ((skb == NULL) || (skb->data == NULL)
|| (self->rx_buff.data == NULL) || (len < 6)) {
- self->stats.rx_dropped++;
+ self->netdev->stats.rx_dropped++;
continue;
}
skb_reserve(skb, 1);
@@ -1307,8 +1304,8 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase)
// Move to next frame
self->rx_buff.data += len;
- self->stats.rx_bytes += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_bytes += len;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
@@ -1523,7 +1520,7 @@ static int via_ircc_net_open(struct net_device *dev)
IRDA_ASSERT(dev != NULL, return -1;);
self = netdev_priv(dev);
- self->stats.rx_packets = 0;
+ dev->stats.rx_packets = 0;
IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
if (request_irq(self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) {
@@ -1660,14 +1657,6 @@ static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq,
return ret;
}
-static struct net_device_stats *via_ircc_net_get_stats(struct net_device
- *dev)
-{
- struct via_ircc_cb *self = netdev_priv(dev);
-
- return &self->stats;
-}
-
MODULE_AUTHOR("VIA Technologies,inc");
MODULE_DESCRIPTION("VIA IrDA Device Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
index 403c3f77634c..d9d1db03fa2d 100644
--- a/drivers/net/irda/via-ircc.h
+++ b/drivers/net/irda/via-ircc.h
@@ -95,7 +95,6 @@ struct via_ircc_cb {
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
- struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 0d30f8d659a1..723c4588c803 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -291,14 +291,14 @@ static void vlsi_proc_ndev(struct seq_file *seq, struct net_device *ndev)
now.tv_sec - idev->last_rx.tv_sec - delta1, delta2);
seq_printf(seq, "RX: packets=%lu / bytes=%lu / errors=%lu / dropped=%lu",
- idev->stats.rx_packets, idev->stats.rx_bytes, idev->stats.rx_errors,
- idev->stats.rx_dropped);
+ ndev->stats.rx_packets, ndev->stats.rx_bytes, ndev->stats.rx_errors,
+ ndev->stats.rx_dropped);
seq_printf(seq, " / overrun=%lu / length=%lu / frame=%lu / crc=%lu\n",
- idev->stats.rx_over_errors, idev->stats.rx_length_errors,
- idev->stats.rx_frame_errors, idev->stats.rx_crc_errors);
+ ndev->stats.rx_over_errors, ndev->stats.rx_length_errors,
+ ndev->stats.rx_frame_errors, ndev->stats.rx_crc_errors);
seq_printf(seq, "TX: packets=%lu / bytes=%lu / errors=%lu / dropped=%lu / fifo=%lu\n",
- idev->stats.tx_packets, idev->stats.tx_bytes, idev->stats.tx_errors,
- idev->stats.tx_dropped, idev->stats.tx_fifo_errors);
+ ndev->stats.tx_packets, ndev->stats.tx_bytes, ndev->stats.tx_errors,
+ ndev->stats.tx_dropped, ndev->stats.tx_fifo_errors);
}
@@ -651,21 +651,21 @@ static void vlsi_rx_interrupt(struct net_device *ndev)
if (ret < 0) {
ret = -ret;
- idev->stats.rx_errors++;
+ ndev->stats.rx_errors++;
if (ret & VLSI_RX_DROP)
- idev->stats.rx_dropped++;
+ ndev->stats.rx_dropped++;
if (ret & VLSI_RX_OVER)
- idev->stats.rx_over_errors++;
+ ndev->stats.rx_over_errors++;
if (ret & VLSI_RX_LENGTH)
- idev->stats.rx_length_errors++;
+ ndev->stats.rx_length_errors++;
if (ret & VLSI_RX_FRAME)
- idev->stats.rx_frame_errors++;
+ ndev->stats.rx_frame_errors++;
if (ret & VLSI_RX_CRC)
- idev->stats.rx_crc_errors++;
+ ndev->stats.rx_crc_errors++;
}
else if (ret > 0) {
- idev->stats.rx_packets++;
- idev->stats.rx_bytes += ret;
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += ret;
}
}
@@ -686,6 +686,7 @@ static void vlsi_rx_interrupt(struct net_device *ndev)
static void vlsi_unarm_rx(vlsi_irda_dev_t *idev)
{
+ struct net_device *ndev = pci_get_drvdata(idev->pdev);
struct vlsi_ring *r = idev->rx_ring;
struct ring_descr *rd;
int ret;
@@ -711,21 +712,21 @@ static void vlsi_unarm_rx(vlsi_irda_dev_t *idev)
if (ret < 0) {
ret = -ret;
- idev->stats.rx_errors++;
+ ndev->stats.rx_errors++;
if (ret & VLSI_RX_DROP)
- idev->stats.rx_dropped++;
+ ndev->stats.rx_dropped++;
if (ret & VLSI_RX_OVER)
- idev->stats.rx_over_errors++;
+ ndev->stats.rx_over_errors++;
if (ret & VLSI_RX_LENGTH)
- idev->stats.rx_length_errors++;
+ ndev->stats.rx_length_errors++;
if (ret & VLSI_RX_FRAME)
- idev->stats.rx_frame_errors++;
+ ndev->stats.rx_frame_errors++;
if (ret & VLSI_RX_CRC)
- idev->stats.rx_crc_errors++;
+ ndev->stats.rx_crc_errors++;
}
else if (ret > 0) {
- idev->stats.rx_packets++;
- idev->stats.rx_bytes += ret;
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += ret;
}
}
}
@@ -1050,8 +1051,8 @@ drop_unlock:
drop:
IRDA_WARNING("%s: dropping packet - %s\n", __func__, msg);
dev_kfree_skb_any(skb);
- idev->stats.tx_errors++;
- idev->stats.tx_dropped++;
+ ndev->stats.tx_errors++;
+ ndev->stats.tx_dropped++;
/* Don't even think about returning NET_XMIT_DROP (=1) here!
* In fact any retval!=0 causes the packet scheduler to requeue the
* packet for later retry of transmission - which isn't exactly
@@ -1078,15 +1079,15 @@ static void vlsi_tx_interrupt(struct net_device *ndev)
if (ret < 0) {
ret = -ret;
- idev->stats.tx_errors++;
+ ndev->stats.tx_errors++;
if (ret & VLSI_TX_DROP)
- idev->stats.tx_dropped++;
+ ndev->stats.tx_dropped++;
if (ret & VLSI_TX_FIFO)
- idev->stats.tx_fifo_errors++;
+ ndev->stats.tx_fifo_errors++;
}
else if (ret > 0){
- idev->stats.tx_packets++;
- idev->stats.tx_bytes += ret;
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += ret;
}
}
@@ -1122,6 +1123,7 @@ static void vlsi_tx_interrupt(struct net_device *ndev)
static void vlsi_unarm_tx(vlsi_irda_dev_t *idev)
{
+ struct net_device *ndev = pci_get_drvdata(idev->pdev);
struct vlsi_ring *r = idev->tx_ring;
struct ring_descr *rd;
int ret;
@@ -1145,15 +1147,15 @@ static void vlsi_unarm_tx(vlsi_irda_dev_t *idev)
if (ret < 0) {
ret = -ret;
- idev->stats.tx_errors++;
+ ndev->stats.tx_errors++;
if (ret & VLSI_TX_DROP)
- idev->stats.tx_dropped++;
+ ndev->stats.tx_dropped++;
if (ret & VLSI_TX_FIFO)
- idev->stats.tx_fifo_errors++;
+ ndev->stats.tx_fifo_errors++;
}
else if (ret > 0){
- idev->stats.tx_packets++;
- idev->stats.tx_bytes += ret;
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += ret;
}
}
@@ -1373,13 +1375,6 @@ static int vlsi_stop_hw(vlsi_irda_dev_t *idev)
/**************************************************************/
-static struct net_device_stats * vlsi_get_stats(struct net_device *ndev)
-{
- vlsi_irda_dev_t *idev = netdev_priv(ndev);
-
- return &idev->stats;
-}
-
static void vlsi_tx_timeout(struct net_device *ndev)
{
vlsi_irda_dev_t *idev = netdev_priv(ndev);
@@ -1615,7 +1610,6 @@ static int vlsi_irda_init(struct net_device *ndev)
ndev->open = vlsi_open;
ndev->stop = vlsi_close;
- ndev->get_stats = vlsi_get_stats;
ndev->hard_start_xmit = vlsi_hard_start_xmit;
ndev->do_ioctl = vlsi_ioctl;
ndev->tx_timeout = vlsi_tx_timeout;
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 9b1884329fba..3050d1a0cccf 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -712,7 +712,6 @@ static inline struct ring_descr *ring_get(struct vlsi_ring *r)
typedef struct vlsi_irda_dev {
struct pci_dev *pdev;
- struct net_device_stats stats;
struct irlap_cb *irlap;
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 30ec9131c5ce..dc0a2e4d830f 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -102,7 +102,6 @@ static int w83977af_is_receiving(struct w83977af_ir *self);
static int w83977af_net_open(struct net_device *dev);
static int w83977af_net_close(struct net_device *dev);
static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev);
/*
* Function w83977af_init ()
@@ -237,7 +236,6 @@ static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
dev->open = w83977af_net_open;
dev->stop = w83977af_net_close;
dev->do_ioctl = w83977af_net_ioctl;
- dev->get_stats = w83977af_net_get_stats;
err = register_netdev(dev);
if (err) {
@@ -702,13 +700,13 @@ static void w83977af_dma_xmit_complete(struct w83977af_ir *self)
if (inb(iobase+AUDR) & AUDR_UNDR) {
IRDA_DEBUG(0, "%s(), Transmit underrun!\n", __func__ );
- self->stats.tx_errors++;
- self->stats.tx_fifo_errors++;
+ self->netdev->stats.tx_errors++;
+ self->netdev->stats.tx_fifo_errors++;
/* Clear bit, by writing 1 to it */
outb(AUDR_UNDR, iobase+AUDR);
} else
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
if (self->new_speed) {
@@ -846,28 +844,28 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
if (status & FS_FO_ERR_MSK) {
if (status & FS_FO_LST_FR) {
/* Add number of lost frames to stats */
- self->stats.rx_errors += len;
+ self->netdev->stats.rx_errors += len;
} else {
/* Skip frame */
- self->stats.rx_errors++;
+ self->netdev->stats.rx_errors++;
self->rx_buff.data += len;
if (status & FS_FO_MX_LEX)
- self->stats.rx_length_errors++;
+ self->netdev->stats.rx_length_errors++;
if (status & FS_FO_PHY_ERR)
- self->stats.rx_frame_errors++;
+ self->netdev->stats.rx_frame_errors++;
if (status & FS_FO_CRC_ERR)
- self->stats.rx_crc_errors++;
+ self->netdev->stats.rx_crc_errors++;
}
/* The errors below can be reported in both cases */
if (status & FS_FO_RX_OV)
- self->stats.rx_fifo_errors++;
+ self->netdev->stats.rx_fifo_errors++;
if (status & FS_FO_FSF_OV)
- self->stats.rx_fifo_errors++;
+ self->netdev->stats.rx_fifo_errors++;
} else {
/* Check if we have transferred all data to memory */
@@ -917,7 +915,7 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
/* Move to next frame */
self->rx_buff.data += len;
- self->stats.rx_packets++;
+ self->netdev->stats.rx_packets++;
skb->dev = self->netdev;
skb_reset_mac_header(skb);
@@ -951,7 +949,7 @@ static void w83977af_pio_receive(struct w83977af_ir *self)
/* Receive all characters in Rx FIFO */
do {
byte = inb(iobase+RBR);
- async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
+ async_unwrap_char(self->netdev, &self->netdev->stats, &self->rx_buff,
byte);
} while (inb(iobase+USR) & USR_RDR); /* Data available */
}
@@ -994,7 +992,7 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
outb(AUDR_SFEND, iobase+AUDR);
outb(set, iobase+SSR);
- self->stats.tx_packets++;
+ self->netdev->stats.tx_packets++;
/* Feed me more packets */
netif_wake_queue(self->netdev);
@@ -1336,13 +1334,6 @@ out:
return ret;
}
-static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev)
-{
- struct w83977af_ir *self = netdev_priv(dev);
-
- return &self->stats;
-}
-
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/w83977af_ir.h b/drivers/net/irda/w83977af_ir.h
index 87c3975baf62..fefe9b11e200 100644
--- a/drivers/net/irda/w83977af_ir.h
+++ b/drivers/net/irda/w83977af_ir.h
@@ -172,7 +172,6 @@ struct w83977af_ir {
int tx_len; /* Number of frames in tx_buff */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
- struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index c7457f97259d..cb793c2bade2 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -429,7 +429,7 @@ SIMPLE_PORT_ATTR(promiscuous);
SIMPLE_PORT_ATTR(num_mcast);
CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map);
CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map);
-CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr);
+CUSTOM_PORT_ATTR(mac_addr, "0x%llX\n", port->mac_addr);
#define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr)
static struct attribute *veth_port_default_attrs[] = {
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index acef3c65cd2c..d2f4d5f508b7 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -318,6 +318,9 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
+ rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_RRO_EN);
+ rxctrl &= ~(IXGBE_DCA_RXCTRL_DESC_WRO_EN |
+ IXGBE_DCA_RXCTRL_DESC_HSRO_EN);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
rx_ring->cpu = cpu;
}
@@ -1741,6 +1744,32 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
}
+static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ /* add VID to filter table */
+ hw->mac.ops.set_vfta(&adapter->hw, vid, 0, true);
+}
+
+static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ ixgbe_irq_disable(adapter);
+
+ vlan_group_set_device(adapter->vlgrp, vid, NULL);
+
+ if (!test_bit(__IXGBE_DOWN, &adapter->state))
+ ixgbe_irq_enable(adapter);
+
+ /* remove VID from filter table */
+ hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false);
+}
+
static void ixgbe_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp)
{
@@ -1760,6 +1789,7 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
ctrl |= IXGBE_VLNCTRL_VME;
ctrl &= ~IXGBE_VLNCTRL_CFIEN;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
+ ixgbe_vlan_rx_add_vid(netdev, 0);
if (grp) {
/* enable VLAN tag insert/strip */
@@ -1773,32 +1803,6 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
ixgbe_irq_enable(adapter);
}
-static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- struct ixgbe_hw *hw = &adapter->hw;
-
- /* add VID to filter table */
- hw->mac.ops.set_vfta(&adapter->hw, vid, 0, true);
-}
-
-static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- struct ixgbe_hw *hw = &adapter->hw;
-
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_disable(adapter);
-
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
- if (!test_bit(__IXGBE_DOWN, &adapter->state))
- ixgbe_irq_enable(adapter);
-
- /* remove VID from filter table */
- hw->mac.ops.set_vfta(&adapter->hw, vid, 0, false);
-}
-
static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter)
{
ixgbe_vlan_rx_register(adapter->netdev, adapter->vlgrp);
@@ -2074,6 +2078,9 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
ixgbe_irq_enable(adapter);
+ /* enable transmits */
+ netif_tx_start_all_queues(netdev);
+
/* bring the link up in the watchdog, this could race with our first
* link up interrupt but shouldn't be a problem */
adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
@@ -3475,7 +3482,6 @@ static void ixgbe_watchdog_task(struct work_struct *work)
(FLOW_TX ? "TX" : "None"))));
netif_carrier_on(netdev);
- netif_tx_wake_all_queues(netdev);
} else {
/* Force detection of hung controller */
adapter->detect_tx_hung = true;
@@ -3487,7 +3493,6 @@ static void ixgbe_watchdog_task(struct work_struct *work)
printk(KERN_INFO "ixgbe: %s NIC Link is Down\n",
netdev->name);
netif_carrier_off(netdev);
- netif_tx_stop_all_queues(netdev);
}
}
@@ -4218,7 +4223,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
}
netif_carrier_off(netdev);
- netif_tx_stop_all_queues(netdev);
strcpy(netdev->name, "eth%d");
err = register_netdev(netdev);
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 83a11ff9ffd1..f011c57c9205 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -404,6 +404,9 @@
#define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
#define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
#define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+#define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */
+#define IXGBE_DCA_RXCTRL_DESC_WRO_EN (1 << 13) /* DCA Rx wr Desc Relax Order */
+#define IXGBE_DCA_RXCTRL_DESC_HSRO_EN (1 << 15) /* DCA Rx Split Header RO */
#define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 4a5580c1126a..75010cac76ac 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -84,7 +84,10 @@
#define KORINA_NUM_RDS 64 /* number of receive descriptors */
#define KORINA_NUM_TDS 64 /* number of transmit descriptors */
-#define KORINA_RBSIZE 536 /* size of one resource buffer = Ether MTU */
+/* KORINA_RBSIZE is the hardware's default maximum receive
+ * frame size in bytes. Having this hardcoded means that there
+ * is no support for MTU sizes greater than 1500. */
+#define KORINA_RBSIZE 1536 /* size of one resource buffer = Ether MTU */
#define KORINA_RDS_MASK (KORINA_NUM_RDS - 1)
#define KORINA_TDS_MASK (KORINA_NUM_TDS - 1)
#define RD_RING_SIZE (KORINA_NUM_RDS * sizeof(struct dma_desc))
@@ -196,7 +199,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
struct korina_private *lp = netdev_priv(dev);
unsigned long flags;
u32 length;
- u32 chain_index;
+ u32 chain_prev, chain_next;
struct dma_desc *td;
spin_lock_irqsave(&lp->lock, flags);
@@ -228,8 +231,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
/* Setup the transmit descriptor. */
dma_cache_inv((u32) td, sizeof(*td));
td->ca = CPHYSADDR(skb->data);
- chain_index = (lp->tx_chain_tail - 1) &
- KORINA_TDS_MASK;
+ chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK;
+ chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK;
if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
if (lp->tx_chain_status == desc_empty) {
@@ -237,7 +240,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
/* Write to NDPTR */
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
&lp->tx_dma_regs->dmandptr);
@@ -248,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Link to prev */
- lp->td_ring[chain_index].control &=
+ lp->td_ring[chain_prev].control &=
~DMA_DESC_COF;
/* Link to prev */
- lp->td_ring[chain_index].link = CPHYSADDR(td);
+ lp->td_ring[chain_prev].link = CPHYSADDR(td);
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
/* Write to NDPTR */
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
&(lp->tx_dma_regs->dmandptr));
@@ -267,17 +270,16 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
lp->tx_chain_status = desc_filled;
- netif_stop_queue(dev);
} else {
/* Update tail */
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
- lp->td_ring[chain_index].control &=
+ lp->td_ring[chain_prev].control &=
~DMA_DESC_COF;
- lp->td_ring[chain_index].link = CPHYSADDR(td);
- lp->tx_chain_tail = chain_index;
+ lp->td_ring[chain_prev].link = CPHYSADDR(td);
+ lp->tx_chain_tail = chain_next;
}
}
dma_cache_wback((u32) td, sizeof(*td));
@@ -327,13 +329,13 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
dmas = readl(&lp->rx_dma_regs->dmas);
if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
- netif_rx_schedule_prep(&lp->napi);
-
dmasm = readl(&lp->rx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_DONE |
DMA_STAT_HALT | DMA_STAT_ERR),
&lp->rx_dma_regs->dmasm);
+ netif_rx_schedule(&lp->napi);
+
if (dmas & DMA_STAT_ERR)
printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
@@ -350,15 +352,20 @@ static int korina_rx(struct net_device *dev, int limit)
struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done];
struct sk_buff *skb, *skb_new;
u8 *pkt_buf;
- u32 devcs, pkt_len, dmas, rx_free_desc;
+ u32 devcs, pkt_len, dmas;
int count;
dma_cache_inv((u32)rd, sizeof(*rd));
for (count = 0; count < limit; count++) {
+ skb = lp->rx_skb[lp->rx_next_done];
+ skb_new = NULL;
devcs = rd->devcs;
+ if ((KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) == 0)
+ break;
+
/* Update statistics counters */
if (devcs & ETH_RX_CRC)
dev->stats.rx_crc_errors++;
@@ -381,63 +388,58 @@ static int korina_rx(struct net_device *dev, int limit)
* in Rc32434 (errata ref #077) */
dev->stats.rx_errors++;
dev->stats.rx_dropped++;
- }
-
- while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
- /* init the var. used for the later
- * operations within the while loop */
- skb_new = NULL;
+ } else if ((devcs & ETH_RX_ROK)) {
pkt_len = RCVPKT_LENGTH(devcs);
- skb = lp->rx_skb[lp->rx_next_done];
-
- if ((devcs & ETH_RX_ROK)) {
- /* must be the (first and) last
- * descriptor then */
- pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
-
- /* invalidate the cache */
- dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
-
- /* Malloc up new buffer. */
- skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
-
- if (!skb_new)
- break;
- /* Do not count the CRC */
- skb_put(skb, pkt_len - 4);
- skb->protocol = eth_type_trans(skb, dev);
-
- /* Pass the packet to upper layers */
- netif_receive_skb(skb);
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += pkt_len;
-
- /* Update the mcast stats */
- if (devcs & ETH_RX_MP)
- dev->stats.multicast++;
-
- lp->rx_skb[lp->rx_next_done] = skb_new;
- }
-
- rd->devcs = 0;
-
- /* Restore descriptor's curr_addr */
- if (skb_new)
- rd->ca = CPHYSADDR(skb_new->data);
- else
- rd->ca = CPHYSADDR(skb->data);
-
- rd->control = DMA_COUNT(KORINA_RBSIZE) |
- DMA_DESC_COD | DMA_DESC_IOD;
- lp->rd_ring[(lp->rx_next_done - 1) &
- KORINA_RDS_MASK].control &=
- ~DMA_DESC_COD;
-
- lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
- dma_cache_wback((u32)rd, sizeof(*rd));
- rd = &lp->rd_ring[lp->rx_next_done];
- writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
+
+ /* must be the (first and) last
+ * descriptor then */
+ pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
+
+ /* invalidate the cache */
+ dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
+
+ /* Malloc up new buffer. */
+ skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
+
+ if (!skb_new)
+ break;
+ /* Do not count the CRC */
+ skb_put(skb, pkt_len - 4);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ /* Pass the packet to upper layers */
+ netif_receive_skb(skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
+
+ /* Update the mcast stats */
+ if (devcs & ETH_RX_MP)
+ dev->stats.multicast++;
+
+ /* 16 bit align */
+ skb_reserve(skb_new, 2);
+
+ lp->rx_skb[lp->rx_next_done] = skb_new;
}
+
+ rd->devcs = 0;
+
+ /* Restore descriptor's curr_addr */
+ if (skb_new)
+ rd->ca = CPHYSADDR(skb_new->data);
+ else
+ rd->ca = CPHYSADDR(skb->data);
+
+ rd->control = DMA_COUNT(KORINA_RBSIZE) |
+ DMA_DESC_COD | DMA_DESC_IOD;
+ lp->rd_ring[(lp->rx_next_done - 1) &
+ KORINA_RDS_MASK].control &=
+ ~DMA_DESC_COD;
+
+ lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
+ dma_cache_wback((u32)rd, sizeof(*rd));
+ rd = &lp->rd_ring[lp->rx_next_done];
+ writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
}
dmas = readl(&lp->rx_dma_regs->dmas);
@@ -623,12 +625,12 @@ korina_tx_dma_interrupt(int irq, void *dev_id)
dmas = readl(&lp->tx_dma_regs->dmas);
if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
- korina_tx(dev);
-
dmasm = readl(&lp->tx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
&lp->tx_dma_regs->dmasm);
+ korina_tx(dev);
+
if (lp->tx_chain_status == desc_filled &&
(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
@@ -741,6 +743,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
static void korina_alloc_ring(struct net_device *dev)
{
struct korina_private *lp = netdev_priv(dev);
+ struct sk_buff *skb;
int i;
/* Initialize the transmit descriptors */
@@ -756,8 +759,6 @@ static void korina_alloc_ring(struct net_device *dev)
/* Initialize the receive descriptors */
for (i = 0; i < KORINA_NUM_RDS; i++) {
- struct sk_buff *skb = lp->rx_skb[i];
-
skb = dev_alloc_skb(KORINA_RBSIZE + 2);
if (!skb)
break;
@@ -770,11 +771,12 @@ static void korina_alloc_ring(struct net_device *dev)
lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]);
}
- /* loop back */
- lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[0]);
- lp->rx_next_done = 0;
+ /* loop back receive descriptors, so the last
+ * descriptor points to the first one */
+ lp->rd_ring[i - 1].link = CPHYSADDR(&lp->rd_ring[0]);
+ lp->rd_ring[i - 1].control |= DMA_DESC_COD;
- lp->rd_ring[i].control |= DMA_DESC_COD;
+ lp->rx_next_done = 0;
lp->rx_chain_head = 0;
lp->rx_chain_tail = 0;
lp->rx_chain_status = desc_empty;
@@ -901,6 +903,8 @@ static int korina_restart(struct net_device *dev)
korina_free_ring(dev);
+ napi_disable(&lp->napi);
+
ret = korina_init(dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: cannot restart device\n",
@@ -999,14 +1003,14 @@ static int korina_open(struct net_device *dev)
* that handles the Done Finished
* Ovr and Und Events */
ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev);
+ IRQF_DISABLED, "Korina ethernet Rx", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n",
dev->name, lp->rx_irq);
goto err_release;
}
ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev);
+ IRQF_DISABLED, "Korina ethernet Tx", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n",
dev->name, lp->tx_irq);
@@ -1015,7 +1019,7 @@ static int korina_open(struct net_device *dev)
/* Install handler for overrun error. */
ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev);
+ IRQF_DISABLED, "Ethernet Overflow", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n",
dev->name, lp->ovr_irq);
@@ -1024,7 +1028,7 @@ static int korina_open(struct net_device *dev)
/* Install handler for underflow error. */
ret = request_irq(lp->und_irq, &korina_und_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev);
+ IRQF_DISABLED, "Ethernet Underflow", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n",
dev->name, lp->und_irq);
@@ -1067,6 +1071,8 @@ static int korina_close(struct net_device *dev)
korina_free_ring(dev);
+ napi_disable(&lp->napi);
+
free_irq(lp->rx_irq, dev);
free_irq(lp->tx_irq, dev);
free_irq(lp->ovr_irq, dev);
@@ -1089,7 +1095,6 @@ static int korina_probe(struct platform_device *pdev)
return -ENOMEM;
}
SET_NETDEV_DEV(dev, &pdev->dev);
- platform_set_drvdata(pdev, dev);
lp = netdev_priv(dev);
bif->dev = dev;
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index 57716e22660c..8e884869a05b 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -486,6 +486,7 @@ static const struct net_device_ops mac8390_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index a04da4ecaa88..f6c4936e2fa8 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -321,6 +321,10 @@ static void macb_tx(struct macb *bp)
printk(KERN_ERR "%s: TX underrun, resetting buffers\n",
bp->dev->name);
+ /* Transfer ongoing, disable transmitter, to avoid confusion */
+ if (status & MACB_BIT(TGO))
+ macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE));
+
head = bp->tx_head;
/*Mark all the buffer as used to avoid sending a lost buffer*/
@@ -343,6 +347,10 @@ static void macb_tx(struct macb *bp)
}
bp->tx_head = bp->tx_tail = 0;
+
+ /* Enable the transmitter again */
+ if (status & MACB_BIT(TGO))
+ macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
}
if (!(status & MACB_BIT(COMP)))
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 15bb38d99304..9f6644a44030 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -952,6 +952,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
.ndo_get_stats = mlx4_en_get_stats,
.ndo_set_multicast_list = mlx4_en_set_multicast,
.ndo_set_mac_address = mlx4_en_set_mac,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = mlx4_en_change_mtu,
.ndo_tx_timeout = mlx4_en_tx_timeout,
.ndo_vlan_rx_register = mlx4_en_vlan_rx_register,
diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c
index cfeef0f1bacc..c1bd040b9e05 100644
--- a/drivers/net/mlx4/en_params.c
+++ b/drivers/net/mlx4/en_params.c
@@ -399,8 +399,10 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
rx_size = roundup_pow_of_two(param->rx_pending);
rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
+ rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
tx_size = roundup_pow_of_two(param->tx_pending);
tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
+ tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
if (rx_size == priv->prof->rx_ring_size &&
tx_size == priv->prof->tx_ring_size)
@@ -440,8 +442,8 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
struct mlx4_en_dev *mdev = priv->mdev;
memset(param, 0, sizeof(*param));
- param->rx_max_pending = mdev->dev->caps.max_rq_sg;
- param->tx_max_pending = mdev->dev->caps.max_sq_sg;
+ param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
+ param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
param->rx_pending = mdev->profile.prof[priv->port].rx_ring_size;
param->tx_pending = mdev->profile.prof[priv->port].tx_ring_size;
}
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index ff4d75205c25..4afd5993e31c 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -203,19 +203,21 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
/* Optimize the common case when there are no wraparounds */
if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) {
- if (tx_info->linear) {
- pci_unmap_single(mdev->pdev,
- (dma_addr_t) be64_to_cpu(data->addr),
+ if (!tx_info->inl) {
+ if (tx_info->linear) {
+ pci_unmap_single(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data->addr),
be32_to_cpu(data->byte_count),
PCI_DMA_TODEVICE);
- ++data;
- }
+ ++data;
+ }
- for (i = 0; i < frags; i++) {
- frag = &skb_shinfo(skb)->frags[i];
- pci_unmap_page(mdev->pdev,
- (dma_addr_t) be64_to_cpu(data[i].addr),
- frag->size, PCI_DMA_TODEVICE);
+ for (i = 0; i < frags; i++) {
+ frag = &skb_shinfo(skb)->frags[i];
+ pci_unmap_page(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data[i].addr),
+ frag->size, PCI_DMA_TODEVICE);
+ }
}
/* Stamp the freed descriptor */
for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
@@ -224,27 +226,29 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
}
} else {
- if ((void *) data >= end) {
- data = (struct mlx4_wqe_data_seg *)
- (ring->buf + ((void *) data - end));
- }
+ if (!tx_info->inl) {
+ if ((void *) data >= end) {
+ data = (struct mlx4_wqe_data_seg *)
+ (ring->buf + ((void *) data - end));
+ }
- if (tx_info->linear) {
- pci_unmap_single(mdev->pdev,
- (dma_addr_t) be64_to_cpu(data->addr),
+ if (tx_info->linear) {
+ pci_unmap_single(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data->addr),
be32_to_cpu(data->byte_count),
PCI_DMA_TODEVICE);
- ++data;
- }
+ ++data;
+ }
- for (i = 0; i < frags; i++) {
- /* Check for wraparound before unmapping */
- if ((void *) data >= end)
- data = (struct mlx4_wqe_data_seg *) ring->buf;
- frag = &skb_shinfo(skb)->frags[i];
- pci_unmap_page(mdev->pdev,
+ for (i = 0; i < frags; i++) {
+ /* Check for wraparound before unmapping */
+ if ((void *) data >= end)
+ data = (struct mlx4_wqe_data_seg *) ring->buf;
+ frag = &skb_shinfo(skb)->frags[i];
+ pci_unmap_page(mdev->pdev,
(dma_addr_t) be64_to_cpu(data->addr),
frag->size, PCI_DMA_TODEVICE);
+ }
}
/* Stamp the freed descriptor */
for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
@@ -790,8 +794,11 @@ int mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
wmb();
data->byte_count = cpu_to_be32(skb_headlen(skb) - lso_header_size);
}
- } else
+ tx_info->inl = 0;
+ } else {
build_inline_wqe(tx_desc, skb, real_size, &vlan_tag, tx_ind, fragptr);
+ tx_info->inl = 1;
+ }
ring->prod += nr_txbb;
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 710c79e7a2db..6ef2490d5c3e 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -912,8 +912,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
int i;
if (msi_x) {
- nreq = min(dev->caps.num_eqs - dev->caps.reserved_eqs,
- num_possible_cpus() + 1);
+ nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
+ num_possible_cpus() + 1);
entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
if (!entries)
goto no_msi;
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 2e96c7b2180a..e9af32d41ca4 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -115,6 +115,10 @@ enum {
};
#define MLX4_EN_MAX_RX_FRAGS 4
+/* Maximum ring sizes */
+#define MLX4_EN_MAX_TX_SIZE 8192
+#define MLX4_EN_MAX_RX_SIZE 8192
+
/* Minimum ring size for our page-allocation sceme to work */
#define MLX4_EN_MIN_RX_SIZE (MLX4_EN_ALLOC_SIZE / SMP_CACHE_BYTES)
#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
@@ -202,6 +206,7 @@ struct mlx4_en_tx_info {
u32 nr_txbb;
u8 linear;
u8 data_offset;
+ u8 inl;
};
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c
index 919fb9eb1b62..cebdf3243ca1 100644
--- a/drivers/net/mlx4/profile.c
+++ b/drivers/net/mlx4/profile.c
@@ -107,9 +107,9 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
profile[MLX4_RES_AUXC].num = request->num_qp;
profile[MLX4_RES_SRQ].num = request->num_srq;
profile[MLX4_RES_CQ].num = request->num_cq;
- profile[MLX4_RES_EQ].num = min(dev_cap->max_eqs,
- dev_cap->reserved_eqs +
- num_possible_cpus() + 1);
+ profile[MLX4_RES_EQ].num = min_t(unsigned, dev_cap->max_eqs,
+ dev_cap->reserved_eqs +
+ num_possible_cpus() + 1);
profile[MLX4_RES_DMPT].num = request->num_mpt;
profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
profile[MLX4_RES_MTT].num = request->num_mtt;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 7253a499d9c8..5f31bbb614af 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -136,21 +136,23 @@ static char mv643xx_eth_driver_version[] = "1.4";
/*
* SDMA configuration register.
*/
+#define RX_BURST_SIZE_4_64BIT (2 << 1)
#define RX_BURST_SIZE_16_64BIT (4 << 1)
#define BLM_RX_NO_SWAP (1 << 4)
#define BLM_TX_NO_SWAP (1 << 5)
+#define TX_BURST_SIZE_4_64BIT (2 << 22)
#define TX_BURST_SIZE_16_64BIT (4 << 22)
#if defined(__BIG_ENDIAN)
#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
- (RX_BURST_SIZE_16_64BIT | \
- TX_BURST_SIZE_16_64BIT)
+ (RX_BURST_SIZE_4_64BIT | \
+ TX_BURST_SIZE_4_64BIT)
#elif defined(__LITTLE_ENDIAN)
#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
- (RX_BURST_SIZE_16_64BIT | \
- BLM_RX_NO_SWAP | \
- BLM_TX_NO_SWAP | \
- TX_BURST_SIZE_16_64BIT)
+ (RX_BURST_SIZE_4_64BIT | \
+ BLM_RX_NO_SWAP | \
+ BLM_TX_NO_SWAP | \
+ TX_BURST_SIZE_4_64BIT)
#else
#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
#endif
@@ -1594,7 +1596,7 @@ oom:
entry = addr_crc(a);
}
- table[entry >> 2] |= 1 << (entry & 3);
+ table[entry >> 2] |= 1 << (8 * (entry & 3));
}
for (i = 0; i < 0x100; i += 4) {
@@ -2210,6 +2212,7 @@ static int mv643xx_eth_stop(struct net_device *dev)
struct mv643xx_eth_private *mp = netdev_priv(dev);
int i;
+ wrlp(mp, INT_MASK_EXT, 0x00000000);
wrlp(mp, INT_MASK, 0x00000000);
rdlp(mp, INT_MASK);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 5e70180bf569..e9c1296b267e 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -1,7 +1,7 @@
/*************************************************************************
* myri10ge.c: Myricom Myri-10G Ethernet driver.
*
- * Copyright (C) 2005 - 2007 Myricom, Inc.
+ * Copyright (C) 2005 - 2009 Myricom, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.4.4-1.395"
+#define MYRI10GE_VERSION_STR "1.4.4-1.401"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -3786,7 +3786,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (status != 0) {
dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n",
status);
- goto abort_with_netdev;
+ goto abort_with_enabled;
}
pci_set_master(pdev);
@@ -3801,13 +3801,13 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
if (status != 0) {
dev_err(&pdev->dev, "Error %d setting DMA mask\n", status);
- goto abort_with_netdev;
+ goto abort_with_enabled;
}
(void)pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd),
&mgp->cmd_bus, GFP_KERNEL);
if (mgp->cmd == NULL)
- goto abort_with_netdev;
+ goto abort_with_enabled;
mgp->board_span = pci_resource_len(pdev, 0);
mgp->iomem_base = pci_resource_start(pdev, 0);
@@ -3929,6 +3929,10 @@ abort_with_firmware:
myri10ge_dummy_rdma(mgp, 0);
abort_with_ioremap:
+ if (mgp->mac_addr_string != NULL)
+ dev_err(&pdev->dev,
+ "myri10ge_probe() failed: MAC=%s, SN=%ld\n",
+ mgp->mac_addr_string, mgp->serial_number);
iounmap(mgp->sram);
abort_with_mtrr:
@@ -3939,8 +3943,10 @@ abort_with_mtrr:
dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
mgp->cmd, mgp->cmd_bus);
-abort_with_netdev:
+abort_with_enabled:
+ pci_disable_device(pdev);
+abort_with_netdev:
free_netdev(netdev);
return status;
}
@@ -3986,6 +3992,7 @@ static void myri10ge_remove(struct pci_dev *pdev)
mgp->cmd, mgp->cmd_bus);
free_netdev(netdev);
+ pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
}
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 478edb92bca3..c5dec54251bf 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -779,6 +779,22 @@ static void __devinit natsemi_init_media (struct net_device *dev)
}
+static const struct net_device_ops natsemi_netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = start_tx,
+ .ndo_get_stats = get_stats,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_change_mtu = natsemi_change_mtu,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_tx_timeout = ns_tx_timeout,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = natsemi_poll_controller,
+#endif
+};
+
static int __devinit natsemi_probe1 (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -911,20 +927,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
if (find_cnt < MAX_UNITS && full_duplex[find_cnt])
np->full_duplex = 1;
- /* The chip-specific entries in the device structure. */
- dev->open = &netdev_open;
- dev->hard_start_xmit = &start_tx;
- dev->stop = &netdev_close;
- dev->get_stats = &get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->change_mtu = &natsemi_change_mtu;
- dev->do_ioctl = &netdev_ioctl;
- dev->tx_timeout = &ns_tx_timeout;
+ dev->netdev_ops = &natsemi_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &natsemi_poll_controller;
-#endif
SET_ETHTOOL_OPS(dev, &ethtool_ops);
if (mtu)
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index b57239171046..7bd6662d5b04 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -202,6 +202,7 @@ static const struct net_device_ops ne_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 62f20ba211cb..f090d3b9ec94 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -208,6 +208,7 @@ static const struct net_device_ops ne2k_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index f8e601c51da7..9c78c963b721 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -146,7 +146,7 @@
#define MAX_RX_BUFFER_LENGTH 1760
#define MAX_RX_JUMBO_BUFFER_LENGTH 8062
-#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512)
+#define MAX_RX_LRO_BUFFER_LENGTH (8062)
#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2)
#define RX_JUMBO_DMA_MAP_LEN \
(MAX_RX_JUMBO_BUFFER_LENGTH - 2)
@@ -207,11 +207,11 @@
#define MAX_CMD_DESCRIPTORS 4096
#define MAX_RCV_DESCRIPTORS 16384
-#define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4)
-#define MAX_RCV_DESCRIPTORS_1G (MAX_RCV_DESCRIPTORS / 4)
-#define MAX_RCV_DESCRIPTORS_10G 8192
+#define MAX_CMD_DESCRIPTORS_HOST 1024
+#define MAX_RCV_DESCRIPTORS_1G 2048
+#define MAX_RCV_DESCRIPTORS_10G 4096
#define MAX_JUMBO_RCV_DESCRIPTORS 1024
-#define MAX_LRO_RCV_DESCRIPTORS 64
+#define MAX_LRO_RCV_DESCRIPTORS 8
#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS
#define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS
#define MAX_RCV_DESC MAX_RCV_DESCRIPTORS
@@ -308,27 +308,16 @@ struct netxen_ring_ctx {
#define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
-#define netxen_set_cmd_desc_flags(cmd_desc, val) \
- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
- ~cpu_to_le16(0x7f)) | cpu_to_le16((val) & 0x7f)
-#define netxen_set_cmd_desc_opcode(cmd_desc, val) \
- (cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
- ~cpu_to_le16((u16)0x3f << 7)) | cpu_to_le16(((val) & 0x3f) << 7)
-
-#define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
- (cmd_desc)->num_of_buffers_total_length = \
- ((cmd_desc)->num_of_buffers_total_length & \
- ~cpu_to_le32(0xff)) | cpu_to_le32((val) & 0xff)
-#define netxen_set_cmd_desc_totallength(cmd_desc, val) \
- (cmd_desc)->num_of_buffers_total_length = \
- ((cmd_desc)->num_of_buffers_total_length & \
- ~cpu_to_le32((u32)0xffffff << 8)) | \
- cpu_to_le32(((val) & 0xffffff) << 8)
-
-#define netxen_get_cmd_desc_opcode(cmd_desc) \
- ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003f)
-#define netxen_get_cmd_desc_totallength(cmd_desc) \
- ((le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8) & 0xffffff)
+#define netxen_set_tx_port(_desc, _port) \
+ (_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0)
+
+#define netxen_set_tx_flags_opcode(_desc, _flags, _opcode) \
+ (_desc)->flags_opcode = \
+ cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7))
+
+#define netxen_set_tx_frags_len(_desc, _frags, _len) \
+ (_desc)->num_of_buffers_total_length = \
+ cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8))
struct cmd_desc_type0 {
u8 tcp_hdr_offset; /* For LSO only */
@@ -510,7 +499,8 @@ typedef enum {
NETXEN_BRDTYPE_P3_10G_SFP_CT = 0x002a,
NETXEN_BRDTYPE_P3_10G_SFP_QT = 0x002b,
NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
- NETXEN_BRDTYPE_P3_10G_XFP = 0x0032
+ NETXEN_BRDTYPE_P3_10G_XFP = 0x0032,
+ NETXEN_BRDTYPE_P3_10G_TP = 0x0080
} netxen_brdtype_t;
@@ -757,7 +747,7 @@ extern char netxen_nic_driver_name[];
*/
struct netxen_skb_frag {
u64 dma;
- u32 length;
+ ulong length;
};
#define _netxen_set_bits(config_word, start, bits, val) {\
@@ -783,13 +773,7 @@ struct netxen_skb_frag {
struct netxen_cmd_buffer {
struct sk_buff *skb;
struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
- u32 total_length;
- u32 mss;
- u16 port;
- u8 cmd;
- u8 frag_count;
- unsigned long time_stamp;
- u32 state;
+ u32 frag_count;
};
/* In rx_buffer, we do not need multiple fragments as is a single buffer */
@@ -876,7 +860,6 @@ struct nx_host_rds_ring {
u32 skb_size;
struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */
struct list_head free_list;
- int begin_alloc;
};
/*
@@ -995,31 +978,31 @@ struct netxen_recv_context {
*/
typedef struct {
- u64 host_phys_addr; /* Ring base addr */
- u32 ring_size; /* Ring entries */
- u16 msi_index;
- u16 rsvd; /* Padding */
+ __le64 host_phys_addr; /* Ring base addr */
+ __le32 ring_size; /* Ring entries */
+ __le16 msi_index;
+ __le16 rsvd; /* Padding */
} nx_hostrq_sds_ring_t;
typedef struct {
- u64 host_phys_addr; /* Ring base addr */
- u64 buff_size; /* Packet buffer size */
- u32 ring_size; /* Ring entries */
- u32 ring_kind; /* Class of ring */
+ __le64 host_phys_addr; /* Ring base addr */
+ __le64 buff_size; /* Packet buffer size */
+ __le32 ring_size; /* Ring entries */
+ __le32 ring_kind; /* Class of ring */
} nx_hostrq_rds_ring_t;
typedef struct {
- u64 host_rsp_dma_addr; /* Response dma'd here */
- u32 capabilities[4]; /* Flag bit vector */
- u32 host_int_crb_mode; /* Interrupt crb usage */
- u32 host_rds_crb_mode; /* RDS crb usage */
+ __le64 host_rsp_dma_addr; /* Response dma'd here */
+ __le32 capabilities[4]; /* Flag bit vector */
+ __le32 host_int_crb_mode; /* Interrupt crb usage */
+ __le32 host_rds_crb_mode; /* RDS crb usage */
/* These ring offsets are relative to data[0] below */
- u32 rds_ring_offset; /* Offset to RDS config */
- u32 sds_ring_offset; /* Offset to SDS config */
- u16 num_rds_rings; /* Count of RDS rings */
- u16 num_sds_rings; /* Count of SDS rings */
- u16 rsvd1; /* Padding */
- u16 rsvd2; /* Padding */
+ __le32 rds_ring_offset; /* Offset to RDS config */
+ __le32 sds_ring_offset; /* Offset to SDS config */
+ __le16 num_rds_rings; /* Count of RDS rings */
+ __le16 num_sds_rings; /* Count of SDS rings */
+ __le16 rsvd1; /* Padding */
+ __le16 rsvd2; /* Padding */
u8 reserved[128]; /* reserve space for future expansion*/
/* MUST BE 64-bit aligned.
The following is packed:
@@ -1029,24 +1012,24 @@ typedef struct {
} nx_hostrq_rx_ctx_t;
typedef struct {
- u32 host_producer_crb; /* Crb to use */
- u32 rsvd1; /* Padding */
+ __le32 host_producer_crb; /* Crb to use */
+ __le32 rsvd1; /* Padding */
} nx_cardrsp_rds_ring_t;
typedef struct {
- u32 host_consumer_crb; /* Crb to use */
- u32 interrupt_crb; /* Crb to use */
+ __le32 host_consumer_crb; /* Crb to use */
+ __le32 interrupt_crb; /* Crb to use */
} nx_cardrsp_sds_ring_t;
typedef struct {
/* These ring offsets are relative to data[0] below */
- u32 rds_ring_offset; /* Offset to RDS config */
- u32 sds_ring_offset; /* Offset to SDS config */
- u32 host_ctx_state; /* Starting State */
- u32 num_fn_per_port; /* How many PCI fn share the port */
- u16 num_rds_rings; /* Count of RDS rings */
- u16 num_sds_rings; /* Count of SDS rings */
- u16 context_id; /* Handle for context */
+ __le32 rds_ring_offset; /* Offset to RDS config */
+ __le32 sds_ring_offset; /* Offset to SDS config */
+ __le32 host_ctx_state; /* Starting State */
+ __le32 num_fn_per_port; /* How many PCI fn share the port */
+ __le16 num_rds_rings; /* Count of RDS rings */
+ __le16 num_sds_rings; /* Count of SDS rings */
+ __le16 context_id; /* Handle for context */
u8 phys_port; /* Physical id of port */
u8 virt_port; /* Virtual/Logical id of port */
u8 reserved[128]; /* save space for future expansion */
@@ -1072,34 +1055,34 @@ typedef struct {
*/
typedef struct {
- u64 host_phys_addr; /* Ring base addr */
- u32 ring_size; /* Ring entries */
- u32 rsvd; /* Padding */
+ __le64 host_phys_addr; /* Ring base addr */
+ __le32 ring_size; /* Ring entries */
+ __le32 rsvd; /* Padding */
} nx_hostrq_cds_ring_t;
typedef struct {
- u64 host_rsp_dma_addr; /* Response dma'd here */
- u64 cmd_cons_dma_addr; /* */
- u64 dummy_dma_addr; /* */
- u32 capabilities[4]; /* Flag bit vector */
- u32 host_int_crb_mode; /* Interrupt crb usage */
- u32 rsvd1; /* Padding */
- u16 rsvd2; /* Padding */
- u16 interrupt_ctl;
- u16 msi_index;
- u16 rsvd3; /* Padding */
+ __le64 host_rsp_dma_addr; /* Response dma'd here */
+ __le64 cmd_cons_dma_addr; /* */
+ __le64 dummy_dma_addr; /* */
+ __le32 capabilities[4]; /* Flag bit vector */
+ __le32 host_int_crb_mode; /* Interrupt crb usage */
+ __le32 rsvd1; /* Padding */
+ __le16 rsvd2; /* Padding */
+ __le16 interrupt_ctl;
+ __le16 msi_index;
+ __le16 rsvd3; /* Padding */
nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */
u8 reserved[128]; /* future expansion */
} nx_hostrq_tx_ctx_t;
typedef struct {
- u32 host_producer_crb; /* Crb to use */
- u32 interrupt_crb; /* Crb to use */
+ __le32 host_producer_crb; /* Crb to use */
+ __le32 interrupt_crb; /* Crb to use */
} nx_cardrsp_cds_ring_t;
typedef struct {
- u32 host_ctx_state; /* Starting state */
- u16 context_id; /* Handle for context */
+ __le32 host_ctx_state; /* Starting state */
+ __le16 context_id; /* Handle for context */
u8 phys_port; /* Physical id of port */
u8 virt_port; /* Virtual/Logical id of port */
nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */
@@ -1202,9 +1185,9 @@ enum {
#define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */
typedef struct {
- u64 qhdr;
- u64 req_hdr;
- u64 words[6];
+ __le64 qhdr;
+ __le64 req_hdr;
+ __le64 words[6];
} nx_nic_req_t;
typedef struct {
@@ -1486,8 +1469,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter);
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter);
int netxen_init_firmware(struct netxen_adapter *adapter);
-void netxen_tso_check(struct netxen_adapter *adapter,
- struct cmd_desc_type0 *desc, struct sk_buff *skb);
void netxen_nic_clear_stats(struct netxen_adapter *adapter);
void netxen_watchdog_task(struct work_struct *work);
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
@@ -1496,6 +1477,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter);
u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
void netxen_p2_nic_set_multi(struct net_device *netdev);
void netxen_p3_nic_set_multi(struct net_device *netdev);
+void netxen_p3_free_mac_list(struct netxen_adapter *adapter);
int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index 64b51643c626..746bdb470418 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -76,7 +76,7 @@ netxen_api_unlock(struct netxen_adapter *adapter)
static u32
netxen_poll_rsp(struct netxen_adapter *adapter)
{
- u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
+ u32 rsp = NX_CDRP_RSP_OK;
int timeout = 0;
do {
@@ -86,10 +86,7 @@ netxen_poll_rsp(struct netxen_adapter *adapter)
if (++timeout > NX_OS_CRB_RETRY_COUNT)
return NX_CDRP_RSP_TIMEOUT;
- netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET,
- &raw_rsp);
-
- rsp = le32_to_cpu(raw_rsp);
+ netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET, &rsp);
} while (!NX_CDRP_IS_RSP(rsp));
return rsp;
@@ -109,20 +106,16 @@ netxen_issue_cmd(struct netxen_adapter *adapter,
if (netxen_api_lock(adapter))
return NX_RCODE_TIMEOUT;
- netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET,
- cpu_to_le32(signature));
+ netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET, signature);
- netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET,
- cpu_to_le32(arg1));
+ netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET, arg1);
- netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET,
- cpu_to_le32(arg2));
+ netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET, arg2);
- netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET,
- cpu_to_le32(arg3));
+ netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET, arg3);
netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
- cpu_to_le32(NX_CDRP_FORM_CMD(cmd)));
+ NX_CDRP_FORM_CMD(cmd));
rsp = netxen_poll_rsp(adapter);
@@ -133,7 +126,6 @@ netxen_issue_cmd(struct netxen_adapter *adapter,
rcode = NX_RCODE_TIMEOUT;
} else if (rsp == NX_CDRP_RSP_FAIL) {
netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
- rcode = le32_to_cpu(rcode);
printk(KERN_ERR "%s: failed card response code:0x%x\n",
netxen_nic_driver_name, rcode);
@@ -183,7 +175,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
int i, nrds_rings, nsds_rings;
size_t rq_size, rsp_size;
- u32 cap, reg;
+ u32 cap, reg, val;
int err;
@@ -225,11 +217,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
prq->num_rds_rings = cpu_to_le16(nrds_rings);
prq->num_sds_rings = cpu_to_le16(nsds_rings);
- prq->rds_ring_offset = 0;
- prq->sds_ring_offset = prq->rds_ring_offset +
+ prq->rds_ring_offset = cpu_to_le32(0);
+
+ val = le32_to_cpu(prq->rds_ring_offset) +
(sizeof(nx_hostrq_rds_ring_t) * nrds_rings);
+ prq->sds_ring_offset = cpu_to_le32(val);
- prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset);
+ prq_rds = (nx_hostrq_rds_ring_t *)(prq->data +
+ le32_to_cpu(prq->rds_ring_offset));
for (i = 0; i < nrds_rings; i++) {
@@ -241,17 +236,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
}
- prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset);
+ prq_sds = (nx_hostrq_sds_ring_t *)(prq->data +
+ le32_to_cpu(prq->sds_ring_offset));
prq_sds[0].host_phys_addr =
cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count);
/* only one msix vector for now */
- prq_sds[0].msi_index = cpu_to_le32(0);
-
- /* now byteswap offsets */
- prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset);
- prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset);
+ prq_sds[0].msi_index = cpu_to_le16(0);
phys_addr = hostrq_phys_addr;
err = netxen_issue_cmd(adapter,
@@ -269,9 +261,9 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
prsp_rds = ((nx_cardrsp_rds_ring_t *)
- &prsp->data[prsp->rds_ring_offset]);
+ &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
- for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) {
+ for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) {
rds_ring = &recv_ctx->rds_rings[i];
reg = le32_to_cpu(prsp_rds[i].host_producer_crb);
@@ -279,7 +271,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
}
prsp_sds = ((nx_cardrsp_sds_ring_t *)
- &prsp->data[prsp->sds_ring_offset]);
+ &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]);
reg = le32_to_cpu(prsp_sds[0].host_consumer_crb);
recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
@@ -288,7 +280,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
recv_ctx->context_id = le16_to_cpu(prsp->context_id);
- recv_ctx->virt_port = le16_to_cpu(prsp->virt_port);
+ recv_ctx->virt_port = prsp->virt_port;
out_free_rsp:
pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index e45ce2951729..0894a7be0225 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -136,11 +136,9 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_TP;
- if (netif_running(dev)) {
- ecmd->speed = adapter->link_speed;
- ecmd->duplex = adapter->link_duplex;
- ecmd->autoneg = adapter->link_autoneg;
- }
+ ecmd->speed = adapter->link_speed;
+ ecmd->duplex = adapter->link_duplex;
+ ecmd->autoneg = adapter->link_autoneg;
} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
u32 val;
@@ -171,7 +169,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} else
return -EIO;
- ecmd->phy_address = adapter->portnum;
+ ecmd->phy_address = adapter->physical_port;
ecmd->transceiver = XCVR_EXTERNAL;
switch ((netxen_brdtype_t) boardinfo->board_type) {
@@ -180,13 +178,13 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
case NETXEN_BRDTYPE_P3_REF_QG:
case NETXEN_BRDTYPE_P3_4_GB:
case NETXEN_BRDTYPE_P3_4_GB_MM:
- case NETXEN_BRDTYPE_P3_10000_BASE_T:
ecmd->supported |= SUPPORTED_Autoneg;
ecmd->advertising |= ADVERTISED_Autoneg;
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
case NETXEN_BRDTYPE_P3_10G_CX4:
case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
@@ -204,16 +202,33 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
- case NETXEN_BRDTYPE_P2_SB31_10G:
case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
case NETXEN_BRDTYPE_P3_10G_SFP_CT:
case NETXEN_BRDTYPE_P3_10G_SFP_QT:
+ ecmd->advertising |= ADVERTISED_TP;
+ ecmd->supported |= SUPPORTED_TP;
+ case NETXEN_BRDTYPE_P2_SB31_10G:
case NETXEN_BRDTYPE_P3_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
+ case NETXEN_BRDTYPE_P3_10G_TP:
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
+ ecmd->autoneg = AUTONEG_DISABLE;
+ ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
+ ecmd->advertising |=
+ (ADVERTISED_FIBRE | ADVERTISED_TP);
+ ecmd->port = PORT_FIBRE;
+ } else {
+ ecmd->autoneg = AUTONEG_ENABLE;
+ ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
+ ecmd->advertising |=
+ (ADVERTISED_TP | ADVERTISED_Autoneg);
+ ecmd->port = PORT_TP;
+ }
+ break;
default:
printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
(netxen_brdtype_t) boardinfo->board_type);
@@ -546,7 +561,10 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
}
ring->tx_pending = adapter->max_tx_desc_count;
- ring->rx_max_pending = MAX_RCV_DESCRIPTORS;
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE)
+ ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
+ else
+ ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
ring->tx_max_pending = MAX_CMD_DESCRIPTORS_HOST;
ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS;
ring->rx_mini_max_pending = 0;
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index aa6e603bfcbf..821cff68b3f3 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -503,17 +503,15 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
i = 0;
+ netif_tx_lock_bh(adapter->netdev);
+
producer = adapter->cmd_producer;
do {
cmd_desc = &cmd_desc_arr[i];
pbuf = &adapter->cmd_buf_arr[producer];
- pbuf->mss = 0;
- pbuf->total_length = 0;
pbuf->skb = NULL;
- pbuf->cmd = 0;
pbuf->frag_count = 0;
- pbuf->port = 0;
/* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
memcpy(&adapter->ahw.cmd_desc_head[producer],
@@ -531,6 +529,8 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+ netif_tx_unlock_bh(adapter->netdev);
+
return 0;
}
@@ -539,16 +539,19 @@ static int nx_p3_sre_macaddr_change(struct net_device *dev,
{
struct netxen_adapter *adapter = netdev_priv(dev);
nx_nic_req_t req;
- nx_mac_req_t mac_req;
+ nx_mac_req_t *mac_req;
+ u64 word;
int rv;
memset(&req, 0, sizeof(nx_nic_req_t));
- req.qhdr |= (NX_NIC_REQUEST << 23);
- req.req_hdr |= NX_MAC_EVENT;
- req.req_hdr |= ((u64)adapter->portnum << 16);
- mac_req.op = op;
- memcpy(&mac_req.mac_addr, addr, 6);
- req.words[0] = cpu_to_le64(*(u64 *)&mac_req);
+ req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
+
+ word = NX_MAC_EVENT | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
+ mac_req = (nx_mac_req_t *)&req.words[0];
+ mac_req->op = op;
+ memcpy(mac_req->mac_addr, addr, 6);
rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0) {
@@ -612,18 +615,35 @@ send_fw_cmd:
int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
{
nx_nic_req_t req;
+ u64 word;
memset(&req, 0, sizeof(nx_nic_req_t));
- req.qhdr |= (NX_HOST_REQUEST << 23);
- req.req_hdr |= NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE;
- req.req_hdr |= ((u64)adapter->portnum << 16);
+ req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);
+
+ word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE |
+ ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
+
req.words[0] = cpu_to_le64(mode);
return netxen_send_cmd_descs(adapter,
(struct cmd_desc_type0 *)&req, 1);
}
+void netxen_p3_free_mac_list(struct netxen_adapter *adapter)
+{
+ nx_mac_list_t *cur, *next;
+
+ cur = adapter->mac_list;
+
+ while (cur) {
+ next = cur->next;
+ kfree(cur);
+ cur = next;
+ }
+}
+
#define NETXEN_CONFIG_INTR_COALESCE 3
/*
@@ -632,13 +652,15 @@ int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode)
int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
{
nx_nic_req_t req;
+ u64 word;
int rv;
memset(&req, 0, sizeof(nx_nic_req_t));
- req.qhdr |= (NX_NIC_REQUEST << 23);
- req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
- req.req_hdr |= ((u64)adapter->portnum << 16);
+ req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23);
+
+ word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16);
+ req.req_hdr = cpu_to_le64(word);
memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
@@ -772,13 +794,10 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac)
adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4);
adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4);
- mac_hi = cpu_to_le32(mac_hi);
- mac_lo = cpu_to_le32(mac_lo);
-
if (pci_func & 1)
- *mac = ((mac_lo >> 16) | ((u64)mac_hi << 16));
+ *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16));
else
- *mac = ((mac_lo) | ((u64)mac_hi << 32));
+ *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32));
return 0;
}
@@ -937,7 +956,7 @@ int netxen_load_firmware(struct netxen_adapter *adapter)
{
int i;
u32 data, size = 0;
- u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START;
+ u32 flashaddr = NETXEN_BOOTLD_START;
size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4;
@@ -949,10 +968,8 @@ int netxen_load_firmware(struct netxen_adapter *adapter)
if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
return -EIO;
- adapter->pci_mem_write(adapter, memaddr, &data, 4);
+ adapter->pci_mem_write(adapter, flashaddr, &data, 4);
flashaddr += 4;
- memaddr += 4;
- cond_resched();
}
msleep(1);
@@ -2034,7 +2051,13 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
rv = -1;
}
- DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type);
+ if (boardinfo->board_type == NETXEN_BRDTYPE_P3_4_GB_MM) {
+ u32 gpio = netxen_nic_reg_read(adapter,
+ NETXEN_ROMUSB_GLB_PAD_GPIO_I);
+ if ((gpio & 0x8000) == 0)
+ boardinfo->board_type = NETXEN_BRDTYPE_P3_10G_TP;
+ }
+
switch ((netxen_brdtype_t) boardinfo->board_type) {
case NETXEN_BRDTYPE_P2_SB35_4G:
adapter->ahw.board_type = NETXEN_NIC_GBE;
@@ -2053,7 +2076,6 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P3_10G_SFP_QT:
case NETXEN_BRDTYPE_P3_10G_XFP:
case NETXEN_BRDTYPE_P3_10000_BASE_T:
-
adapter->ahw.board_type = NETXEN_NIC_XGBE;
break;
case NETXEN_BRDTYPE_P1_BD:
@@ -2063,9 +2085,12 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P3_REF_QG:
case NETXEN_BRDTYPE_P3_4_GB:
case NETXEN_BRDTYPE_P3_4_GB_MM:
-
adapter->ahw.board_type = NETXEN_NIC_GBE;
break;
+ case NETXEN_BRDTYPE_P3_10G_TP:
+ adapter->ahw.board_type = (adapter->portnum < 2) ?
+ NETXEN_NIC_XGBE : NETXEN_NIC_GBE;
+ break;
default:
printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
boardinfo->board_type);
@@ -2110,12 +2135,16 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
{
__u32 status;
__u32 autoneg;
- __u32 mode;
__u32 port_mode;
- netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
- if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */
+ if (!netif_carrier_ok(adapter->netdev)) {
+ adapter->link_speed = 0;
+ adapter->link_duplex = -1;
+ adapter->link_autoneg = AUTONEG_ENABLE;
+ return;
+ }
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
adapter->hw_read_wx(adapter,
NETXEN_PORT_MODE_ADDR, &port_mode, 4);
if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
@@ -2141,7 +2170,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
adapter->link_speed = SPEED_1000;
break;
default:
- adapter->link_speed = -1;
+ adapter->link_speed = 0;
break;
}
switch (netxen_get_phy_duplex(status)) {
@@ -2164,7 +2193,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
goto link_down;
} else {
link_down:
- adapter->link_speed = -1;
+ adapter->link_speed = 0;
adapter->link_duplex = -1;
}
}
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index d924468e506e..ffd37bea1628 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -308,7 +308,6 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
}
memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
INIT_LIST_HEAD(&rds_ring->free_list);
- rds_ring->begin_alloc = 0;
/*
* Now go through all of them, set reference handles
* and put them in the queues.
@@ -439,6 +438,8 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter)
long timeout = 0;
long done = 0;
+ cond_resched();
+
while (done == 0) {
done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS);
done &= 2;
@@ -533,12 +534,9 @@ static int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
static int do_rom_fast_read(struct netxen_adapter *adapter,
int addr, int *valp)
{
- cond_resched();
-
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
- netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
- udelay(100); /* prevent bursting on CRB */
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
+ netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb);
if (netxen_wait_rom_done(adapter)) {
printk("Error waiting for rom done\n");
@@ -546,7 +544,7 @@ static int do_rom_fast_read(struct netxen_adapter *adapter,
}
/* reset abyte_cnt and dummy_byte_cnt */
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0);
- udelay(100); /* prevent bursting on CRB */
+ udelay(10);
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
*valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA);
@@ -884,14 +882,16 @@ int netxen_flash_unlock(struct netxen_adapter *adapter)
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
{
int addr, val;
- int i, init_delay = 0;
+ int i, n, init_delay = 0;
struct crb_addr_pair *buf;
- unsigned offset, n;
+ unsigned offset;
u32 off;
/* resetall */
+ rom_lock(adapter);
netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
0xffffffff);
+ netxen_rom_unlock(adapter);
if (verbose) {
if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
@@ -910,7 +910,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
- (n != 0xcafecafeUL) ||
+ (n != 0xcafecafe) ||
netxen_rom_fast_read(adapter, 4, &n) != 0) {
printk(KERN_ERR "%s: ERROR Reading crb_init area: "
"n: %08x\n", netxen_nic_driver_name, n);
@@ -947,8 +947,10 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
}
for (i = 0; i < n; i++) {
if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
- netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0)
+ netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
+ kfree(buf);
return -EIO;
+ }
buf[i].addr = addr;
buf[i].data = val;
@@ -975,6 +977,14 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
/* do not reset PCI */
if (off == (ROMUSB_GLB + 0xbc))
continue;
+ if (off == (ROMUSB_GLB + 0xa8))
+ continue;
+ if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
+ continue;
+ if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
+ continue;
if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
buf[i].data = 0x1020;
/* skip the function enable register */
@@ -992,23 +1002,21 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
continue;
}
+ init_delay = 1;
/* After writing this register, HW needs time for CRB */
/* to quiet down (else crb_window returns 0xffffffff) */
if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
- init_delay = 1;
+ init_delay = 1000;
if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
/* hold xdma in reset also */
buf[i].data = NETXEN_NIC_XDMA_RESET;
+ buf[i].data = 0x8000ff;
}
}
adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
- if (init_delay == 1) {
- msleep(1000);
- init_delay = 0;
- }
- msleep(1);
+ msleep(init_delay);
}
kfree(buf);
@@ -1277,7 +1285,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
dev_kfree_skb_any(skb);
for (i = 0; i < nr_frags; i++) {
- index = frag_desc->frag_handles[i];
+ index = le16_to_cpu(frag_desc->frag_handles[i]);
skb = netxen_process_rxbuf(adapter,
rds_ring, index, cksum);
if (skb)
@@ -1428,7 +1436,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
int count = 0;
- int index = 0;
netxen_ctx_msg msg = 0;
dma_addr_t dma;
struct list_head *head;
@@ -1436,7 +1443,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
rds_ring = &recv_ctx->rds_rings[ringid];
producer = rds_ring->producer;
- index = rds_ring->begin_alloc;
head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */
@@ -1444,39 +1450,37 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- rds_ring->begin_alloc = index;
break;
}
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
+
+ dma = pci_map_single(pdev, skb->data,
+ rds_ring->dma_size, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pdev, dma)) {
+ dev_kfree_skb_any(skb);
+ break;
+ }
+
+ count++;
buffer = list_entry(head->next, struct netxen_rx_buffer, list);
list_del(&buffer->list);
- count++; /* now there should be no failure */
- pdesc = &rds_ring->desc_head[producer];
-
- if (!adapter->ahw.cut_through)
- skb_reserve(skb, 2);
- /* This will be setup when we receive the
- * buffer after it has been filled FSL TBD TBD
- * skb->dev = netdev;
- */
- dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
- PCI_DMA_FROMDEVICE);
- pdesc->addr_buffer = cpu_to_le64(dma);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = dma;
+
/* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
+ pdesc->addr_buffer = cpu_to_le64(dma);
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
- DPRINTK(INFO, "done writing descripter\n");
- producer =
- get_next_index(producer, rds_ring->max_rx_desc_count);
- index = get_next_index(index, rds_ring->max_rx_desc_count);
+
+ producer = get_next_index(producer, rds_ring->max_rx_desc_count);
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rds_ring->begin_alloc = index;
rds_ring->producer = producer;
/* Window = 1 */
adapter->pci_write_normalize(adapter,
@@ -1515,49 +1519,50 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
int count = 0;
- int index = 0;
struct list_head *head;
+ dma_addr_t dma;
rds_ring = &recv_ctx->rds_rings[ringid];
producer = rds_ring->producer;
- index = rds_ring->begin_alloc;
head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */
while (!list_empty(head)) {
skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- rds_ring->begin_alloc = index;
break;
}
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
+
+ dma = pci_map_single(pdev, skb->data,
+ rds_ring->dma_size, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pdev, dma)) {
+ dev_kfree_skb_any(skb);
+ break;
+ }
+
+ count++;
buffer = list_entry(head->next, struct netxen_rx_buffer, list);
list_del(&buffer->list);
- count++; /* now there should be no failure */
- pdesc = &rds_ring->desc_head[producer];
- if (!adapter->ahw.cut_through)
- skb_reserve(skb, 2);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
- buffer->dma = pci_map_single(pdev, skb->data,
- rds_ring->dma_size,
- PCI_DMA_FROMDEVICE);
+ buffer->dma = dma;
/* make a rcv descriptor */
+ pdesc = &rds_ring->desc_head[producer];
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- producer =
- get_next_index(producer, rds_ring->max_rx_desc_count);
- index = get_next_index(index, rds_ring->max_rx_desc_count);
- buffer = &rds_ring->rx_buf_arr[index];
+
+ producer = get_next_index(producer, rds_ring->max_rx_desc_count);
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rds_ring->begin_alloc = index;
rds_ring->producer = producer;
/* Window = 1 */
adapter->pci_write_normalize(adapter,
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index ba01524b5531..645d384fe87e 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -39,7 +39,9 @@
#include "netxen_nic_phan_reg.h"
#include <linux/dma-mapping.h>
+#include <linux/if_vlan.h>
#include <net/ip.h>
+#include <linux/ipv6.h>
MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
MODULE_LICENSE("GPL");
@@ -242,7 +244,7 @@ static void netxen_check_options(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P3_4_GB:
case NETXEN_BRDTYPE_P3_4_GB_MM:
adapter->msix_supported = !!use_msi_x;
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
break;
case NETXEN_BRDTYPE_P2_SB35_4G:
@@ -251,6 +253,14 @@ static void netxen_check_options(struct netxen_adapter *adapter)
adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
break;
+ case NETXEN_BRDTYPE_P3_10G_TP:
+ adapter->msix_supported = !!use_msi_x;
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ else
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+ break;
+
default:
adapter->msix_supported = 0;
adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
@@ -271,10 +281,15 @@ static void netxen_check_options(struct netxen_adapter *adapter)
static int
netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
{
- int ret = 0;
+ u32 val, timeout;
if (first_boot == 0x55555555) {
/* This is the first boot after power up */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+
+ if (!NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return 0;
/* PCI bus master workaround */
adapter->hw_read_wx(adapter,
@@ -294,18 +309,26 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
/* clear the register for future unloads/loads */
adapter->pci_write_normalize(adapter,
NETXEN_CAM_RAM(0x1fc), 0);
- ret = -1;
+ return -EIO;
}
- if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
- /* Start P2 boot loader */
- adapter->pci_write_normalize(adapter,
- NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
- adapter->pci_write_normalize(adapter,
- NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
- }
+ /* Start P2 boot loader */
+ val = adapter->pci_read_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, val | 0x1);
+ timeout = 0;
+ do {
+ msleep(1);
+ val = adapter->pci_read_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc));
+
+ if (++timeout > 5000)
+ return -EIO;
+
+ } while (val == NETXEN_BDINFO_MAGIC);
}
- return ret;
+ return 0;
}
static void netxen_set_port_mode(struct netxen_adapter *adapter)
@@ -712,17 +735,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
- /* ScatterGather support */
- netdev->features = NETIF_F_SG;
- netdev->features |= NETIF_F_IP_CSUM;
- netdev->features |= NETIF_F_TSO;
+ netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+ netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+
if (NX_IS_REVISION_P3(revision_id)) {
- netdev->features |= NETIF_F_IPV6_CSUM;
- netdev->features |= NETIF_F_TSO6;
+ netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+ netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
}
- if (adapter->pci_using_dac)
+ if (adapter->pci_using_dac) {
netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
/*
* Set the CRB window to invalid. If any register in window 0 is
@@ -784,8 +808,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
CRB_CMDPEG_STATE, 0);
netxen_pinit_from_rom(adapter, 0);
msleep(1);
- netxen_load_firmware(adapter);
}
+ netxen_load_firmware(adapter);
if (NX_IS_REVISION_P3(revision_id))
netxen_pcie_strap_init(adapter);
@@ -801,13 +825,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
- if ((first_boot == 0x55555555) &&
- (NX_IS_REVISION_P2(revision_id))) {
- /* Unlock the HW, prompting the boot sequence */
- adapter->pci_write_normalize(adapter,
- NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
- }
-
err = netxen_initialize_adapter_offload(adapter);
if (err)
goto err_out_iounmap;
@@ -821,7 +838,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i);
/* Handshake with the card before we register the devices. */
- netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+ err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+ if (err)
+ goto err_out_free_offload;
} /* first_driver */
@@ -925,6 +944,7 @@ err_out_disable_msi:
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
+err_out_free_offload:
if (first_driver)
netxen_free_adapter_offload(adapter);
@@ -968,6 +988,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netxen_free_hw_resources(adapter);
netxen_release_rx_buffers(adapter);
netxen_free_sw_resources(adapter);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_p3_free_mac_list(adapter);
}
if (adapter->portnum == 0)
@@ -983,8 +1006,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
iounmap(adapter->ahw.db_base);
iounmap(adapter->ahw.pci_base0);
- iounmap(adapter->ahw.pci_base1);
- iounmap(adapter->ahw.pci_base2);
+ if (adapter->ahw.pci_base1 != NULL)
+ iounmap(adapter->ahw.pci_base1);
+ if (adapter->ahw.pci_base2 != NULL)
+ iounmap(adapter->ahw.pci_base2);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -1137,29 +1162,72 @@ static int netxen_nic_close(struct net_device *netdev)
return 0;
}
-void netxen_tso_check(struct netxen_adapter *adapter,
+static bool netxen_tso_check(struct net_device *netdev,
struct cmd_desc_type0 *desc, struct sk_buff *skb)
{
- if (desc->mss) {
- desc->total_hdr_length = (sizeof(struct ethhdr) +
- ip_hdrlen(skb) + tcp_hdrlen(skb));
+ bool tso = false;
+ u8 opcode = TX_ETHER_PKT;
+ __be16 protocol = skb->protocol;
+ u16 flags = 0;
+
+ if (protocol == __constant_htons(ETH_P_8021Q)) {
+ struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data;
+ protocol = vh->h_vlan_encapsulated_proto;
+ flags = FLAGS_VLAN_TAGGED;
+ }
- if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
- (skb->protocol == htons(ETH_P_IPV6)))
- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
- else
- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
+ if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+ skb_shinfo(skb)->gso_size > 0) {
+
+ desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ desc->total_hdr_length =
+ skb_transport_offset(skb) + tcp_hdrlen(skb);
+
+ opcode = (protocol == __constant_htons(ETH_P_IPV6)) ?
+ TX_TCP_LSO6 : TX_TCP_LSO;
+ tso = true;
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (ip_hdr(skb)->protocol == IPPROTO_TCP)
- netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
- else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
- netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
- else
- return;
+ u8 l4proto;
+
+ if (protocol == __constant_htons(ETH_P_IP)) {
+ l4proto = ip_hdr(skb)->protocol;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCP_PKT;
+ else if(l4proto == IPPROTO_UDP)
+ opcode = TX_UDP_PKT;
+ } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+ l4proto = ipv6_hdr(skb)->nexthdr;
+
+ if (l4proto == IPPROTO_TCP)
+ opcode = TX_TCPV6_PKT;
+ else if(l4proto == IPPROTO_UDP)
+ opcode = TX_UDPV6_PKT;
+ }
}
desc->tcp_hdr_offset = skb_transport_offset(skb);
desc->ip_hdr_offset = skb_network_offset(skb);
+ netxen_set_tx_flags_opcode(desc, flags, opcode);
+ return tso;
+}
+
+static void
+netxen_clean_tx_dma_mapping(struct pci_dev *pdev,
+ struct netxen_cmd_buffer *pbuf, int last)
+{
+ int k;
+ struct netxen_skb_frag *buffrag;
+
+ buffrag = &pbuf->frag_array[0];
+ pci_unmap_single(pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+
+ for (k = 1; k < last; k++) {
+ buffrag = &pbuf->frag_array[k];
+ pci_unmap_page(pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+ }
}
static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -1167,33 +1235,22 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct netxen_adapter *adapter = netdev_priv(netdev);
struct netxen_hardware_context *hw = &adapter->ahw;
unsigned int first_seg_len = skb->len - skb->data_len;
+ struct netxen_cmd_buffer *pbuf;
struct netxen_skb_frag *buffrag;
- unsigned int i;
+ struct cmd_desc_type0 *hwdesc;
+ struct pci_dev *pdev = adapter->pdev;
+ dma_addr_t temp_dma;
+ int i, k;
u32 producer, consumer;
- u32 saved_producer = 0;
- struct cmd_desc_type0 *hwdesc;
- int k;
- struct netxen_cmd_buffer *pbuf = NULL;
- int frag_count;
- int no_of_desc;
+ int frag_count, no_of_desc;
u32 num_txd = adapter->max_tx_desc_count;
+ bool is_tso = false;
frag_count = skb_shinfo(skb)->nr_frags + 1;
/* There 4 fragments per descriptor */
no_of_desc = (frag_count + 3) >> 2;
- if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
- if (skb_shinfo(skb)->gso_size > 0) {
-
- no_of_desc++;
- if ((ip_hdrlen(skb) + tcp_hdrlen(skb) +
- sizeof(struct ethhdr)) >
- (sizeof(struct cmd_desc_type0) - 2)) {
- no_of_desc++;
- }
- }
- }
producer = adapter->cmd_producer;
smp_mb();
@@ -1205,34 +1262,26 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
/* Copy the descriptors into the hardware */
- saved_producer = producer;
hwdesc = &hw->cmd_desc_head[producer];
memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
/* Take skb->data itself */
pbuf = &adapter->cmd_buf_arr[producer];
- if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
- skb_shinfo(skb)->gso_size > 0) {
- pbuf->mss = skb_shinfo(skb)->gso_size;
- hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
- } else {
- pbuf->mss = 0;
- hwdesc->mss = 0;
- }
- pbuf->total_length = skb->len;
+
+ is_tso = netxen_tso_check(netdev, hwdesc, skb);
+
pbuf->skb = skb;
- pbuf->cmd = TX_ETHER_PKT;
pbuf->frag_count = frag_count;
- pbuf->port = adapter->portnum;
buffrag = &pbuf->frag_array[0];
- buffrag->dma = pci_map_single(adapter->pdev, skb->data, first_seg_len,
+ temp_dma = pci_map_single(pdev, skb->data, first_seg_len,
PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, temp_dma))
+ goto drop_packet;
+
+ buffrag->dma = temp_dma;
buffrag->length = first_seg_len;
- netxen_set_cmd_desc_totallength(hwdesc, skb->len);
- netxen_set_cmd_desc_num_of_buff(hwdesc, frag_count);
- netxen_set_cmd_desc_opcode(hwdesc, TX_ETHER_PKT);
+ netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
+ netxen_set_tx_port(hwdesc, adapter->portnum);
- netxen_set_cmd_desc_port(hwdesc, adapter->portnum);
- netxen_set_cmd_desc_ctxid(hwdesc, adapter->portnum);
hwdesc->buffer1_length = cpu_to_le16(first_seg_len);
hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
@@ -1240,7 +1289,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct skb_frag_struct *frag;
int len, temp_len;
unsigned long offset;
- dma_addr_t temp_dma;
/* move to next desc. if there is a need */
if ((i & 0x3) == 0) {
@@ -1256,8 +1304,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
offset = frag->page_offset;
temp_len = len;
- temp_dma = pci_map_page(adapter->pdev, frag->page, offset,
+ temp_dma = pci_map_page(pdev, frag->page, offset,
len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, temp_dma)) {
+ netxen_clean_tx_dma_mapping(pdev, pbuf, i);
+ goto drop_packet;
+ }
buffrag++;
buffrag->dma = temp_dma;
@@ -1285,16 +1337,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
producer = get_next_index(producer, num_txd);
- /* might change opcode to TX_TCP_LSO */
- netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb);
-
/* For LSO, we need to copy the MAC/IP/TCP headers into
* the descriptor ring
*/
- if (netxen_get_cmd_desc_opcode(&hw->cmd_desc_head[saved_producer])
- == TX_TCP_LSO) {
+ if (is_tso) {
int hdr_len, first_hdr_len, more_hdr;
- hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length;
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
more_hdr = 1;
@@ -1336,6 +1384,11 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
netdev->trans_start = jiffies;
return NETDEV_TX_OK;
+
+drop_packet:
+ adapter->stats.txdropped++;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
}
static int netxen_nic_check_temp(struct netxen_adapter *adapter)
@@ -1407,6 +1460,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netif_carrier_off(netdev);
netif_stop_queue(netdev);
}
+
+ netxen_nic_set_link_parameters(adapter);
} else if (!adapter->ahw.linkup && linkup) {
printk(KERN_INFO "%s: %s NIC Link is up\n",
netxen_nic_driver_name, netdev->name);
@@ -1415,6 +1470,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
netif_carrier_on(netdev);
netif_wake_queue(netdev);
}
+
+ netxen_nic_set_link_parameters(adapter);
}
}
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 46b0772489e4..e80294d8cc19 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1956,7 +1956,11 @@ static const struct net_device_ops netdev_ops = {
.ndo_change_mtu = ns83820_change_mtu,
.ndo_set_multicast_list = ns83820_set_multicast,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = ns83820_tx_timeout,
+#ifdef NS83820_VLAN_ACCEL_SUPPORT
+ .ndo_vlan_rx_register = ns83820_vlan_rx_register,
+#endif
};
static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
@@ -2216,7 +2220,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
#ifdef NS83820_VLAN_ACCEL_SUPPORT
/* We also support hardware vlan acceleration */
ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- ndev->vlan_rx_register = ns83820_vlan_rx_register;
#endif
if (using_dac) {
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 5b7a574ce571..d0349e7d73ea 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -712,7 +712,7 @@ static inline void pasemi_mac_rx_error(const struct pasemi_mac *mac,
rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
ccmdsta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno));
- printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n",
+ printk(KERN_ERR "pasemi_mac: rx error. macrx %016llx, rx status %llx\n",
macrx, *chan->status);
printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
@@ -730,8 +730,8 @@ static inline void pasemi_mac_tx_error(const struct pasemi_mac *mac,
cmdsta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno));
- printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\
- "tx status 0x%016lx\n", mactx, *chan->status);
+ printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016llx, "\
+ "tx status 0x%016llx\n", mactx, *chan->status);
printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
}
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index c38ed777f0a8..a6999403f37b 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -586,7 +586,7 @@ static int pcnet_config(struct pcmcia_device *link)
}
if ((link->conf.ConfigBase == 0x03c0)
- && (link->manf_id == 0x149) && (link->card_id = 0xc1ab)) {
+ && (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n");
printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n");
goto failed;
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 044b7b07f5f4..665a4286da39 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1568,6 +1568,22 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}
+static const struct net_device_ops pcnet32_netdev_ops = {
+ .ndo_open = pcnet32_open,
+ .ndo_stop = pcnet32_close,
+ .ndo_start_xmit = pcnet32_start_xmit,
+ .ndo_tx_timeout = pcnet32_tx_timeout,
+ .ndo_get_stats = pcnet32_get_stats,
+ .ndo_set_multicast_list = pcnet32_set_multicast_list,
+ .ndo_do_ioctl = pcnet32_ioctl,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = pcnet32_poll_controller,
+#endif
+};
+
/* pcnet32_probe1
* Called from both pcnet32_probe_vlbus and pcnet_probe_pci.
* pdev will be NULL when called from pcnet32_probe_vlbus.
@@ -1934,20 +1950,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
lp->watchdog_timer.function = (void *)&pcnet32_watchdog;
/* The PCNET32-specific entries in the device structure. */
- dev->open = &pcnet32_open;
- dev->hard_start_xmit = &pcnet32_start_xmit;
- dev->stop = &pcnet32_close;
- dev->get_stats = &pcnet32_get_stats;
- dev->set_multicast_list = &pcnet32_set_multicast_list;
- dev->do_ioctl = &pcnet32_ioctl;
+ dev->netdev_ops = &pcnet32_netdev_ops;
dev->ethtool_ops = &pcnet32_ethtool_ops;
- dev->tx_timeout = pcnet32_tx_timeout;
dev->watchdog_timeo = (5 * HZ);
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = pcnet32_poll_controller;
-#endif
-
/* Fill in the generic fields of the device structure. */
if (register_netdev(dev))
goto err_free_ring;
@@ -2276,7 +2282,7 @@ static int pcnet32_open(struct net_device *dev)
if (lp->chip_version >= PCNET32_79C970A) {
/* Print the link status and start the watchdog */
pcnet32_check_media(dev, 1);
- mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+ mod_timer(&lp->watchdog_timer, PCNET32_WATCHDOG_TIMEOUT);
}
i = 0;
@@ -2911,7 +2917,7 @@ static void pcnet32_watchdog(struct net_device *dev)
pcnet32_check_media(dev, 0);
spin_unlock_irqrestore(&lp->lock, flags);
- mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+ mod_timer(&lp->watchdog_timer, round_jiffies(PCNET32_WATCHDOG_TIMEOUT));
}
static int pcnet32_pm_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 11adf6ed4628..811a637695ca 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -296,9 +296,8 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state)
struct phy_driver *phydrv = to_phy_driver(drv);
struct phy_device *phydev = to_phy_device(dev);
- if ((!device_may_wakeup(phydev->dev.parent)) &&
- (phydrv && phydrv->suspend))
- ret = phydrv->suspend(phydev);
+ if (drv && phydrv->suspend && !device_may_wakeup(phydev->dev.parent))
+ ret = phydrv->suspend(phydev);
return ret;
}
@@ -310,8 +309,7 @@ static int mdio_bus_resume(struct device * dev)
struct phy_driver *phydrv = to_phy_driver(drv);
struct phy_device *phydev = to_phy_device(dev);
- if ((!device_may_wakeup(phydev->dev.parent)) &&
- (phydrv && phydrv->resume))
+ if (drv && phydrv->resume && !device_may_wakeup(phydev->dev.parent))
ret = phydrv->resume(phydev);
return ret;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index e35460165bf7..0a06e4fd37d9 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -231,15 +231,6 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
if ((phy_id & 0x1fffffff) == 0x1fffffff)
return NULL;
- /*
- * Broken hardware is sometimes missing the pull-up resistor on the
- * MDIO line, which results in reads to non-existent devices returning
- * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
- * device as well.
- */
- if (phy_id == 0)
- return NULL;
-
dev = phy_device_create(bus, addr, phy_id);
return dev;
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index c05d38d46350..1387187543e4 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -81,6 +81,9 @@ static struct phy_driver lan83c185_driver = {
.ack_interrupt = smsc_phy_ack_interrupt,
.config_intr = smsc_phy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+
.driver = { .owner = THIS_MODULE, }
};
@@ -102,6 +105,9 @@ static struct phy_driver lan8187_driver = {
.ack_interrupt = smsc_phy_ack_interrupt,
.config_intr = smsc_phy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+
.driver = { .owner = THIS_MODULE, }
};
@@ -123,6 +129,9 @@ static struct phy_driver lan8700_driver = {
.ack_interrupt = smsc_phy_ack_interrupt,
.config_intr = smsc_phy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+
.driver = { .owner = THIS_MODULE, }
};
@@ -144,6 +153,9 @@ static struct phy_driver lan911x_int_driver = {
.ack_interrupt = smsc_phy_ack_interrupt,
.config_intr = smsc_phy_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+
.driver = { .owner = THIS_MODULE, }
};
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 0c46d603b8fe..0be0f0b164f3 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -265,6 +265,13 @@ static const struct header_ops plip_header_ops = {
.cache = plip_hard_header_cache,
};
+static const struct net_device_ops plip_netdev_ops = {
+ .ndo_open = plip_open,
+ .ndo_stop = plip_close,
+ .ndo_start_xmit = plip_tx_packet,
+ .ndo_do_ioctl = plip_ioctl,
+};
+
/* Entry point of PLIP driver.
Probe the hardware, and register/initialize the driver.
@@ -280,15 +287,11 @@ plip_init_netdev(struct net_device *dev)
struct net_local *nl = netdev_priv(dev);
/* Then, override parts of it */
- dev->hard_start_xmit = plip_tx_packet;
- dev->open = plip_open;
- dev->stop = plip_close;
- dev->do_ioctl = plip_ioctl;
-
dev->tx_queue_len = 10;
dev->flags = IFF_POINTOPOINT|IFF_NOARP;
memset(dev->dev_addr, 0xfc, ETH_ALEN);
+ dev->netdev_ops = &plip_netdev_ops;
dev->header_ops = &plip_header_ops;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 06b448285eb5..7b2728b8f1b7 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -250,6 +250,7 @@ static int ppp_connect_channel(struct channel *pch, int unit);
static int ppp_disconnect_channel(struct channel *pch);
static void ppp_destroy_channel(struct channel *pch);
static int unit_get(struct idr *p, void *ptr);
+static int unit_set(struct idr *p, void *ptr, int n);
static void unit_put(struct idr *p, int n);
static void *unit_find(struct idr *p, int n);
@@ -2432,11 +2433,18 @@ ppp_create_interface(int unit, int *retp)
} else {
if (unit_find(&ppp_units_idr, unit))
goto out2; /* unit already exists */
- else {
- /* darn, someone is cheating us? */
- *retp = -EINVAL;
+ /*
+ * if caller need a specified unit number
+ * lets try to satisfy him, otherwise --
+ * he should better ask us for new unit number
+ *
+ * NOTE: yes I know that returning EEXIST it's not
+ * fair but at least pppd will ask us to allocate
+ * new unit in this case so user is happy :)
+ */
+ unit = unit_set(&ppp_units_idr, ppp, unit);
+ if (unit < 0)
goto out2;
- }
}
/* Initialize the new ppp unit */
@@ -2677,14 +2685,37 @@ static void __exit ppp_cleanup(void)
* by holding all_ppp_mutex
*/
+/* associate pointer with specified number */
+static int unit_set(struct idr *p, void *ptr, int n)
+{
+ int unit, err;
+
+again:
+ if (!idr_pre_get(p, GFP_KERNEL)) {
+ printk(KERN_ERR "PPP: No free memory for idr\n");
+ return -ENOMEM;
+ }
+
+ err = idr_get_new_above(p, ptr, n, &unit);
+ if (err == -EAGAIN)
+ goto again;
+
+ if (unit != n) {
+ idr_remove(p, unit);
+ return -EINVAL;
+ }
+
+ return unit;
+}
+
/* get new free unit number and associate pointer with it */
static int unit_get(struct idr *p, void *ptr)
{
int unit, err;
again:
- if (idr_pre_get(p, GFP_KERNEL) == 0) {
- printk(KERN_ERR "Out of memory expanding drawable idr\n");
+ if (!idr_pre_get(p, GFP_KERNEL)) {
+ printk(KERN_ERR "PPP: No free memory for idr\n");
return -ENOMEM;
}
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
index ec2314246682..335da4831ab3 100644
--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -2168,7 +2168,7 @@ static void gelic_wl_connected_event(struct gelic_wl_info *wl,
complete(&wl->assoc_done);
netif_carrier_on(port_to_netdev(wl_port(wl)));
} else
- pr_debug("%s: event %#lx under wpa\n",
+ pr_debug("%s: event %#llx under wpa\n",
__func__, event);
}
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index ba2e1c5b6bcf..e6fdce9206cc 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -28,11 +28,11 @@
} while (0)
#define QLGE_VENDOR_ID 0x1077
-#define QLGE_DEVICE_ID1 0x8012
-#define QLGE_DEVICE_ID 0x8000
+#define QLGE_DEVICE_ID 0x8012
-#define MAX_RX_RINGS 128
-#define MAX_TX_RINGS 128
+#define MAX_CPUS 8
+#define MAX_TX_RINGS MAX_CPUS
+#define MAX_RX_RINGS ((MAX_CPUS * 2) + 1)
#define NUM_TX_RING_ENTRIES 256
#define NUM_RX_RING_ENTRIES 256
@@ -45,6 +45,7 @@
#define MAX_SPLIT_SIZE 1023
#define QLGE_SB_PAD 32
+#define MAX_CQ 128
#define DFLT_COALESCE_WAIT 100 /* 100 usec wait for coalescing */
#define MAX_INTER_FRAME_WAIT 10 /* 10 usec max interframe-wait for coalescing */
#define DFLT_INTER_FRAME_WAIT (MAX_INTER_FRAME_WAIT/2)
@@ -786,12 +787,12 @@ struct mbox_params {
struct flash_params {
u8 dev_id_str[4];
- u16 size;
- u16 csum;
- u16 ver;
- u16 sub_dev_id;
+ __le16 size;
+ __le16 csum;
+ __le16 ver;
+ __le16 sub_dev_id;
u8 mac_addr[6];
- u16 res;
+ __le16 res;
};
@@ -818,15 +819,6 @@ struct tx_doorbell_context {
};
/* DATA STRUCTURES SHARED WITH HARDWARE. */
-
-struct bq_element {
- u32 addr_lo;
-#define BQ_END 0x00000001
-#define BQ_CONT 0x00000002
-#define BQ_MASK 0x00000003
- u32 addr_hi;
-} __attribute((packed));
-
struct tx_buf_desc {
__le64 addr;
__le32 len;
@@ -860,8 +852,8 @@ struct ob_mac_iocb_req {
__le16 frame_len;
#define OB_MAC_IOCB_LEN_MASK 0x3ffff
__le16 reserved2;
- __le32 tid;
- __le32 txq_idx;
+ u32 tid;
+ u32 txq_idx;
__le32 reserved3;
__le16 vlan_tci;
__le16 reserved4;
@@ -880,8 +872,8 @@ struct ob_mac_iocb_rsp {
u8 flags2; /* */
u8 flags3; /* */
#define OB_MAC_IOCB_RSP_B 0x80 /* */
- __le32 tid;
- __le32 txq_idx;
+ u32 tid;
+ u32 txq_idx;
__le32 reserved[13];
} __attribute((packed));
@@ -903,8 +895,8 @@ struct ob_mac_tso_iocb_req {
#define OB_MAC_TSO_IOCB_V 0x04
__le32 reserved1[2];
__le32 frame_len;
- __le32 tid;
- __le32 txq_idx;
+ u32 tid;
+ u32 txq_idx;
__le16 total_hdrs_len;
__le16 net_trans_offset;
#define OB_MAC_TRANSPORT_HDR_SHIFT 6
@@ -925,8 +917,8 @@ struct ob_mac_tso_iocb_rsp {
u8 flags2; /* */
u8 flags3; /* */
#define OB_MAC_TSO_IOCB_RSP_B 0x8000
- __le32 tid;
- __le32 txq_idx;
+ u32 tid;
+ u32 txq_idx;
__le32 reserved2[13];
} __attribute((packed));
@@ -970,8 +962,7 @@ struct ib_mac_iocb_rsp {
#define IB_MAC_IOCB_RSP_DS 0x40 /* data is in small buffer */
#define IB_MAC_IOCB_RSP_DL 0x80 /* data is in large buffer */
__le32 data_len; /* */
- __le32 data_addr_lo; /* */
- __le32 data_addr_hi; /* */
+ __le64 data_addr; /* */
__le32 rss; /* */
__le16 vlan_id; /* 12 bits */
#define IB_MAC_IOCB_RSP_C 0x1000 /* VLAN CFI bit */
@@ -979,13 +970,13 @@ struct ib_mac_iocb_rsp {
__le16 reserved1;
__le32 reserved2[6];
- __le32 flags4;
-#define IB_MAC_IOCB_RSP_HV 0x20000000 /* */
-#define IB_MAC_IOCB_RSP_HS 0x40000000 /* */
-#define IB_MAC_IOCB_RSP_HL 0x80000000 /* */
+ u8 reserved3[3];
+ u8 flags4;
+#define IB_MAC_IOCB_RSP_HV 0x20
+#define IB_MAC_IOCB_RSP_HS 0x40
+#define IB_MAC_IOCB_RSP_HL 0x80
__le32 hdr_len; /* */
- __le32 hdr_addr_lo; /* */
- __le32 hdr_addr_hi; /* */
+ __le64 hdr_addr; /* */
} __attribute((packed));
struct ib_ae_iocb_rsp {
@@ -1050,10 +1041,8 @@ struct wqicb {
__le16 cq_id_rss;
#define Q_CQ_ID_RSS_RV 0x8000
__le16 rid;
- __le32 addr_lo;
- __le32 addr_hi;
- __le32 cnsmr_idx_addr_lo;
- __le32 cnsmr_idx_addr_hi;
+ __le64 addr;
+ __le64 cnsmr_idx_addr;
} __attribute((packed));
/*
@@ -1078,18 +1067,14 @@ struct cqicb {
#define LEN_CPP_64 0x0002
#define LEN_CPP_128 0x0003
__le16 rid;
- __le32 addr_lo;
- __le32 addr_hi;
- __le32 prod_idx_addr_lo;
- __le32 prod_idx_addr_hi;
+ __le64 addr;
+ __le64 prod_idx_addr;
__le16 pkt_delay;
__le16 irq_delay;
- __le32 lbq_addr_lo;
- __le32 lbq_addr_hi;
+ __le64 lbq_addr;
__le16 lbq_buf_size;
__le16 lbq_len; /* entry count */
- __le32 sbq_addr_lo;
- __le32 sbq_addr_hi;
+ __le64 sbq_addr;
__le16 sbq_buf_size;
__le16 sbq_len; /* entry count */
} __attribute((packed));
@@ -1126,7 +1111,7 @@ struct map_list {
struct tx_ring_desc {
struct sk_buff *skb;
struct ob_mac_iocb_req *queue_entry;
- int index;
+ u32 index;
struct oal oal;
struct map_list map[MAX_SKB_FRAGS + 1];
int map_cnt;
@@ -1138,8 +1123,8 @@ struct bq_desc {
struct page *lbq_page;
struct sk_buff *skb;
} p;
- struct bq_element *bq;
- int index;
+ __le64 *addr;
+ u32 index;
DECLARE_PCI_UNMAP_ADDR(mapaddr);
DECLARE_PCI_UNMAP_LEN(maplen);
};
@@ -1153,7 +1138,7 @@ struct tx_ring {
struct wqicb wqicb; /* structure used to inform chip of new queue */
void *wq_base; /* pci_alloc:virtual addr for tx */
dma_addr_t wq_base_dma; /* pci_alloc:dma addr for tx */
- u32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */
+ __le32 *cnsmr_idx_sh_reg; /* shadow copy of consumer idx */
dma_addr_t cnsmr_idx_sh_reg_dma; /* dma-shadow copy of consumer */
u32 wq_size; /* size in bytes of queue area */
u32 wq_len; /* number of entries in queue */
@@ -1189,7 +1174,7 @@ struct rx_ring {
u32 cq_size;
u32 cq_len;
u16 cq_id;
- u32 *prod_idx_sh_reg; /* Shadowed producer register. */
+ __le32 *prod_idx_sh_reg; /* Shadowed producer register. */
dma_addr_t prod_idx_sh_reg_dma;
void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */
u32 cnsmr_idx; /* current sw idx */
@@ -1410,9 +1395,11 @@ struct ql_adapter {
int rx_ring_count;
int ring_mem_size;
void *ring_mem;
- struct rx_ring *rx_ring;
+
+ struct rx_ring rx_ring[MAX_RX_RINGS];
+ struct tx_ring tx_ring[MAX_TX_RINGS];
+
int rx_csum;
- struct tx_ring *tx_ring;
u32 default_rx_queue;
u16 rx_coalesce_usecs; /* cqicb->int_delay */
@@ -1477,9 +1464,12 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr)
* update the relevant index register and then copy the value to the
* shadow register in host memory.
*/
-static inline unsigned int ql_read_sh_reg(const volatile void *addr)
+static inline u32 ql_read_sh_reg(__le32 *addr)
{
- return *(volatile unsigned int __force *)addr;
+ u32 reg;
+ reg = le32_to_cpu(*addr);
+ rmb();
+ return reg;
}
extern char qlge_driver_name[];
diff --git a/drivers/net/qlge/qlge_dbg.c b/drivers/net/qlge/qlge_dbg.c
index 47df304a02c8..379b895ed6e6 100644
--- a/drivers/net/qlge/qlge_dbg.c
+++ b/drivers/net/qlge/qlge_dbg.c
@@ -435,14 +435,10 @@ void ql_dump_wqicb(struct wqicb *wqicb)
printk(KERN_ERR PFX "wqicb->cq_id_rss = %d.\n",
le16_to_cpu(wqicb->cq_id_rss));
printk(KERN_ERR PFX "wqicb->rid = 0x%x.\n", le16_to_cpu(wqicb->rid));
- printk(KERN_ERR PFX "wqicb->wq_addr_lo = 0x%.08x.\n",
- le32_to_cpu(wqicb->addr_lo));
- printk(KERN_ERR PFX "wqicb->wq_addr_hi = 0x%.08x.\n",
- le32_to_cpu(wqicb->addr_hi));
- printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_lo = 0x%.08x.\n",
- le32_to_cpu(wqicb->cnsmr_idx_addr_lo));
- printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr_hi = 0x%.08x.\n",
- le32_to_cpu(wqicb->cnsmr_idx_addr_hi));
+ printk(KERN_ERR PFX "wqicb->wq_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(wqicb->addr));
+ printk(KERN_ERR PFX "wqicb->wq_cnsmr_idx_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(wqicb->cnsmr_idx_addr));
}
void ql_dump_tx_ring(struct tx_ring *tx_ring)
@@ -455,10 +451,11 @@ void ql_dump_tx_ring(struct tx_ring *tx_ring)
printk(KERN_ERR PFX "tx_ring->base = %p.\n", tx_ring->wq_base);
printk(KERN_ERR PFX "tx_ring->base_dma = 0x%llx.\n",
(unsigned long long) tx_ring->wq_base_dma);
- printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg = %p.\n",
- tx_ring->cnsmr_idx_sh_reg);
- printk(KERN_ERR PFX "tx_ring->cnsmr_idx_sh_reg_dma = 0x%llx.\n",
- (unsigned long long) tx_ring->cnsmr_idx_sh_reg_dma);
+ printk(KERN_ERR PFX
+ "tx_ring->cnsmr_idx_sh_reg, addr = 0x%p, value = %d.\n",
+ tx_ring->cnsmr_idx_sh_reg,
+ tx_ring->cnsmr_idx_sh_reg
+ ? ql_read_sh_reg(tx_ring->cnsmr_idx_sh_reg) : 0);
printk(KERN_ERR PFX "tx_ring->size = %d.\n", tx_ring->wq_size);
printk(KERN_ERR PFX "tx_ring->len = %d.\n", tx_ring->wq_len);
printk(KERN_ERR PFX "tx_ring->prod_idx_db_reg = %p.\n",
@@ -510,30 +507,22 @@ void ql_dump_cqicb(struct cqicb *cqicb)
printk(KERN_ERR PFX "cqicb->msix_vect = %d.\n", cqicb->msix_vect);
printk(KERN_ERR PFX "cqicb->flags = %x.\n", cqicb->flags);
printk(KERN_ERR PFX "cqicb->len = %d.\n", le16_to_cpu(cqicb->len));
- printk(KERN_ERR PFX "cqicb->addr_lo = %x.\n",
- le32_to_cpu(cqicb->addr_lo));
- printk(KERN_ERR PFX "cqicb->addr_hi = %x.\n",
- le32_to_cpu(cqicb->addr_hi));
- printk(KERN_ERR PFX "cqicb->prod_idx_addr_lo = %x.\n",
- le32_to_cpu(cqicb->prod_idx_addr_lo));
- printk(KERN_ERR PFX "cqicb->prod_idx_addr_hi = %x.\n",
- le32_to_cpu(cqicb->prod_idx_addr_hi));
+ printk(KERN_ERR PFX "cqicb->addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->addr));
+ printk(KERN_ERR PFX "cqicb->prod_idx_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->prod_idx_addr));
printk(KERN_ERR PFX "cqicb->pkt_delay = 0x%.04x.\n",
le16_to_cpu(cqicb->pkt_delay));
printk(KERN_ERR PFX "cqicb->irq_delay = 0x%.04x.\n",
le16_to_cpu(cqicb->irq_delay));
- printk(KERN_ERR PFX "cqicb->lbq_addr_lo = %x.\n",
- le32_to_cpu(cqicb->lbq_addr_lo));
- printk(KERN_ERR PFX "cqicb->lbq_addr_hi = %x.\n",
- le32_to_cpu(cqicb->lbq_addr_hi));
+ printk(KERN_ERR PFX "cqicb->lbq_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->lbq_addr));
printk(KERN_ERR PFX "cqicb->lbq_buf_size = 0x%.04x.\n",
le16_to_cpu(cqicb->lbq_buf_size));
printk(KERN_ERR PFX "cqicb->lbq_len = 0x%.04x.\n",
le16_to_cpu(cqicb->lbq_len));
- printk(KERN_ERR PFX "cqicb->sbq_addr_lo = %x.\n",
- le32_to_cpu(cqicb->sbq_addr_lo));
- printk(KERN_ERR PFX "cqicb->sbq_addr_hi = %x.\n",
- le32_to_cpu(cqicb->sbq_addr_hi));
+ printk(KERN_ERR PFX "cqicb->sbq_addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(cqicb->sbq_addr));
printk(KERN_ERR PFX "cqicb->sbq_buf_size = 0x%.04x.\n",
le16_to_cpu(cqicb->sbq_buf_size));
printk(KERN_ERR PFX "cqicb->sbq_len = 0x%.04x.\n",
@@ -558,9 +547,10 @@ void ql_dump_rx_ring(struct rx_ring *rx_ring)
printk(KERN_ERR PFX "rx_ring->cq_size = %d.\n", rx_ring->cq_size);
printk(KERN_ERR PFX "rx_ring->cq_len = %d.\n", rx_ring->cq_len);
printk(KERN_ERR PFX
- "rx_ring->prod_idx_sh_reg, addr = %p, value = %d.\n",
+ "rx_ring->prod_idx_sh_reg, addr = 0x%p, value = %d.\n",
rx_ring->prod_idx_sh_reg,
- rx_ring->prod_idx_sh_reg ? *(rx_ring->prod_idx_sh_reg) : 0);
+ rx_ring->prod_idx_sh_reg
+ ? ql_read_sh_reg(rx_ring->prod_idx_sh_reg) : 0);
printk(KERN_ERR PFX "rx_ring->prod_idx_sh_reg_dma = %llx.\n",
(unsigned long long) rx_ring->prod_idx_sh_reg_dma);
printk(KERN_ERR PFX "rx_ring->cnsmr_idx_db_reg = %p.\n",
@@ -809,10 +799,8 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp)
printk(KERN_ERR PFX "data_len = %d\n",
le32_to_cpu(ib_mac_rsp->data_len));
- printk(KERN_ERR PFX "data_addr_hi = 0x%x\n",
- le32_to_cpu(ib_mac_rsp->data_addr_hi));
- printk(KERN_ERR PFX "data_addr_lo = 0x%x\n",
- le32_to_cpu(ib_mac_rsp->data_addr_lo));
+ printk(KERN_ERR PFX "data_addr = 0x%llx\n",
+ (unsigned long long) le64_to_cpu(ib_mac_rsp->data_addr));
if (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_RSS_MASK)
printk(KERN_ERR PFX "rss = %x\n",
le32_to_cpu(ib_mac_rsp->rss));
@@ -821,20 +809,15 @@ void ql_dump_ib_mac_rsp(struct ib_mac_iocb_rsp *ib_mac_rsp)
le16_to_cpu(ib_mac_rsp->vlan_id));
printk(KERN_ERR PFX "flags4 = %s%s%s.\n",
- le32_to_cpu(ib_mac_rsp->
- flags4) & IB_MAC_IOCB_RSP_HV ? "HV " : "",
- le32_to_cpu(ib_mac_rsp->
- flags4) & IB_MAC_IOCB_RSP_HS ? "HS " : "",
- le32_to_cpu(ib_mac_rsp->
- flags4) & IB_MAC_IOCB_RSP_HL ? "HL " : "");
-
- if (le32_to_cpu(ib_mac_rsp->flags4) & IB_MAC_IOCB_RSP_HV) {
+ ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV ? "HV " : "",
+ ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HS ? "HS " : "",
+ ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HL ? "HL " : "");
+
+ if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) {
printk(KERN_ERR PFX "hdr length = %d.\n",
le32_to_cpu(ib_mac_rsp->hdr_len));
- printk(KERN_ERR PFX "hdr addr_hi = 0x%x.\n",
- le32_to_cpu(ib_mac_rsp->hdr_addr_hi));
- printk(KERN_ERR PFX "hdr addr_lo = 0x%x.\n",
- le32_to_cpu(ib_mac_rsp->hdr_addr_lo));
+ printk(KERN_ERR PFX "hdr addr = 0x%llx.\n",
+ (unsigned long long) le64_to_cpu(ib_mac_rsp->hdr_addr));
}
}
#endif
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index eefb81b13758..9d922e2ff226 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -56,9 +56,9 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
for (i = 1; i < qdev->rss_ring_first_cq_id; i++, rx_ring++) {
rx_ring = &qdev->rx_ring[i];
cqicb = (struct cqicb *)rx_ring;
- cqicb->irq_delay = le16_to_cpu(qdev->tx_coalesce_usecs);
+ cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs);
cqicb->pkt_delay =
- le16_to_cpu(qdev->tx_max_coalesced_frames);
+ cpu_to_le16(qdev->tx_max_coalesced_frames);
cqicb->flags = FLAGS_LI;
status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
CFG_LCQ, rx_ring->cq_id);
@@ -79,9 +79,9 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
i++) {
rx_ring = &qdev->rx_ring[i];
cqicb = (struct cqicb *)rx_ring;
- cqicb->irq_delay = le16_to_cpu(qdev->rx_coalesce_usecs);
+ cqicb->irq_delay = cpu_to_le16(qdev->rx_coalesce_usecs);
cqicb->pkt_delay =
- le16_to_cpu(qdev->rx_max_coalesced_frames);
+ cpu_to_le16(qdev->rx_max_coalesced_frames);
cqicb->flags = FLAGS_LI;
status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
CFG_LCQ, rx_ring->cq_id);
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 718a7bd0cd1a..3d1d7b6e55aa 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -76,7 +76,6 @@ MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy.");
static struct pci_device_id qlge_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID)},
- {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID1)},
/* required last entry */
{0,}
};
@@ -127,12 +126,12 @@ static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask)
int ql_sem_spinlock(struct ql_adapter *qdev, u32 sem_mask)
{
- unsigned int seconds = 3;
+ unsigned int wait_count = 30;
do {
if (!ql_sem_trylock(qdev, sem_mask))
return 0;
- ssleep(1);
- } while (--seconds);
+ udelay(100);
+ } while (--wait_count);
return -ETIMEDOUT;
}
@@ -257,7 +256,7 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
{
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MW, 0);
if (status)
goto exit;
ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -265,13 +264,13 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MR, 0);
if (status)
goto exit;
*value++ = ql_read32(qdev, MAC_ADDR_DATA);
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MW, 0);
if (status)
goto exit;
ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -279,14 +278,14 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MR, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MR, 0);
if (status)
goto exit;
*value++ = ql_read32(qdev, MAC_ADDR_DATA);
if (type == MAC_ADDR_TYPE_CAM_MAC) {
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MW, 0);
if (status)
goto exit;
ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -294,7 +293,7 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index,
MAC_ADDR_ADR | MAC_ADDR_RS | type); /* type */
status =
ql_wait_reg_rdy(qdev, MAC_ADDR_IDX,
- MAC_ADDR_MR, MAC_ADDR_E);
+ MAC_ADDR_MR, 0);
if (status)
goto exit;
*value++ = ql_read32(qdev, MAC_ADDR_DATA);
@@ -344,7 +343,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MW, 0);
if (status)
goto exit;
ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -353,7 +352,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
ql_write32(qdev, MAC_ADDR_DATA, lower);
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MW, 0);
if (status)
goto exit;
ql_write32(qdev, MAC_ADDR_IDX, (offset++) | /* offset */
@@ -362,7 +361,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
ql_write32(qdev, MAC_ADDR_DATA, upper);
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MW, 0);
if (status)
goto exit;
ql_write32(qdev, MAC_ADDR_IDX, (offset) | /* offset */
@@ -400,7 +399,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
status =
ql_wait_reg_rdy(qdev,
- MAC_ADDR_IDX, MAC_ADDR_MW, MAC_ADDR_E);
+ MAC_ADDR_IDX, MAC_ADDR_MW, 0);
if (status)
goto exit;
ql_write32(qdev, MAC_ADDR_IDX, offset | /* offset */
@@ -431,13 +430,13 @@ int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value)
if (status)
goto exit;
- status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, RT_IDX_E);
+ status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0);
if (status)
goto exit;
ql_write32(qdev, RT_IDX,
RT_IDX_TYPE_NICQ | RT_IDX_RS | (index << RT_IDX_IDX_SHIFT));
- status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, RT_IDX_E);
+ status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MR, 0);
if (status)
goto exit;
*value = ql_read32(qdev, RT_DATA);
@@ -642,7 +641,7 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev)
}
-static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
+static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data)
{
int status = 0;
/* wait for reg to come ready */
@@ -657,8 +656,11 @@ static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
FLASH_ADDR, FLASH_ADDR_RDY, FLASH_ADDR_ERR);
if (status)
goto exit;
- /* get the data */
- *data = ql_read32(qdev, FLASH_DATA);
+ /* This data is stored on flash as an array of
+ * __le32. Since ql_read32() returns cpu endian
+ * we need to swap it back.
+ */
+ *data = cpu_to_le32(ql_read32(qdev, FLASH_DATA));
exit:
return status;
}
@@ -667,13 +669,20 @@ static int ql_get_flash_params(struct ql_adapter *qdev)
{
int i;
int status;
- u32 *p = (u32 *)&qdev->flash;
+ __le32 *p = (__le32 *)&qdev->flash;
+ u32 offset = 0;
+
+ /* Second function's parameters follow the first
+ * function's.
+ */
+ if (qdev->func)
+ offset = sizeof(qdev->flash) / sizeof(u32);
if (ql_sem_spinlock(qdev, SEM_FLASH_MASK))
return -ETIMEDOUT;
for (i = 0; i < sizeof(qdev->flash) / sizeof(u32); i++, p++) {
- status = ql_read_flash_word(qdev, i, p);
+ status = ql_read_flash_word(qdev, i+offset, p);
if (status) {
QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n");
goto exit;
@@ -874,7 +883,6 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int clean_idx = rx_ring->lbq_clean_idx;
struct bq_desc *lbq_desc;
- struct bq_element *bq;
u64 map;
int i;
@@ -884,7 +892,6 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
"lbq: try cleaning clean_idx = %d.\n",
clean_idx);
lbq_desc = &rx_ring->lbq[clean_idx];
- bq = lbq_desc->bq;
if (lbq_desc->p.lbq_page == NULL) {
QPRINTK(qdev, RX_STATUS, DEBUG,
"lbq: getting new page for index %d.\n",
@@ -906,10 +913,7 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
}
pci_unmap_addr_set(lbq_desc, mapaddr, map);
pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE);
- bq->addr_lo = /*lbq_desc->addr_lo = */
- cpu_to_le32(map);
- bq->addr_hi = /*lbq_desc->addr_hi = */
- cpu_to_le32(map >> 32);
+ *lbq_desc->addr = cpu_to_le64(map);
}
clean_idx++;
if (clean_idx == rx_ring->lbq_len)
@@ -934,7 +938,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int clean_idx = rx_ring->sbq_clean_idx;
struct bq_desc *sbq_desc;
- struct bq_element *bq;
u64 map;
int i;
@@ -944,7 +947,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
QPRINTK(qdev, RX_STATUS, DEBUG,
"sbq: try cleaning clean_idx = %d.\n",
clean_idx);
- bq = sbq_desc->bq;
if (sbq_desc->p.skb == NULL) {
QPRINTK(qdev, RX_STATUS, DEBUG,
"sbq: getting new skb for index %d.\n",
@@ -963,11 +965,15 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)
sbq_desc->p.skb->data,
rx_ring->sbq_buf_size /
2, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(qdev->pdev, map)) {
+ QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n");
+ rx_ring->sbq_clean_idx = clean_idx;
+ return;
+ }
pci_unmap_addr_set(sbq_desc, mapaddr, map);
pci_unmap_len_set(sbq_desc, maplen,
rx_ring->sbq_buf_size / 2);
- bq->addr_lo = cpu_to_le32(map);
- bq->addr_hi = cpu_to_le32(map >> 32);
+ *sbq_desc->addr = cpu_to_le64(map);
}
clean_idx++;
@@ -1303,6 +1309,11 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
"No skb available, drop the packet.\n");
return NULL;
}
+ pci_unmap_page(qdev->pdev,
+ pci_unmap_addr(lbq_desc,
+ mapaddr),
+ pci_unmap_len(lbq_desc, maplen),
+ PCI_DMA_FROMDEVICE);
skb_reserve(skb, NET_IP_ALIGN);
QPRINTK(qdev, RX_STATUS, DEBUG,
"%d bytes of headers and data in large. Chain page to new skb and pull tail.\n", length);
@@ -1330,7 +1341,7 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
* eventually be in trouble.
*/
int size, offset, i = 0;
- struct bq_element *bq, bq_array[8];
+ __le64 *bq, bq_array[8];
sbq_desc = ql_get_curr_sbuf(rx_ring);
pci_unmap_single(qdev->pdev,
pci_unmap_addr(sbq_desc, mapaddr),
@@ -1356,16 +1367,10 @@ static struct sk_buff *ql_build_rx_skb(struct ql_adapter *qdev,
} else {
QPRINTK(qdev, RX_STATUS, DEBUG,
"Headers in small, %d bytes of data in chain of large.\n", length);
- bq = (struct bq_element *)sbq_desc->p.skb->data;
+ bq = (__le64 *)sbq_desc->p.skb->data;
}
while (length > 0) {
lbq_desc = ql_get_curr_lbuf(rx_ring);
- if ((bq->addr_lo & ~BQ_MASK) != lbq_desc->bq->addr_lo) {
- QPRINTK(qdev, RX_STATUS, ERR,
- "Panic!!! bad large buffer address, expected 0x%.08x, got 0x%.08x.\n",
- lbq_desc->bq->addr_lo, bq->addr_lo);
- return NULL;
- }
pci_unmap_page(qdev->pdev,
pci_unmap_addr(lbq_desc,
mapaddr),
@@ -1874,7 +1879,7 @@ static void ql_hw_csum_setup(struct sk_buff *skb,
{
int len;
struct iphdr *iph = ip_hdr(skb);
- u16 *check;
+ __sum16 *check;
mac_iocb_ptr->opcode = OPCODE_OB_MAC_TSO_IOCB;
mac_iocb_ptr->frame_len = cpu_to_le32((u32) skb->len);
mac_iocb_ptr->net_trans_offset =
@@ -2083,8 +2088,6 @@ static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
put_page(lbq_desc->p.lbq_page);
lbq_desc->p.lbq_page = NULL;
}
- lbq_desc->bq->addr_lo = 0;
- lbq_desc->bq->addr_hi = 0;
}
}
@@ -2097,12 +2100,12 @@ static int ql_alloc_lbq_buffers(struct ql_adapter *qdev,
int i;
struct bq_desc *lbq_desc;
u64 map;
- struct bq_element *bq = rx_ring->lbq_base;
+ __le64 *bq = rx_ring->lbq_base;
for (i = 0; i < rx_ring->lbq_len; i++) {
lbq_desc = &rx_ring->lbq[i];
memset(lbq_desc, 0, sizeof(lbq_desc));
- lbq_desc->bq = bq;
+ lbq_desc->addr = bq;
lbq_desc->index = i;
lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC);
if (unlikely(!lbq_desc->p.lbq_page)) {
@@ -2119,8 +2122,7 @@ static int ql_alloc_lbq_buffers(struct ql_adapter *qdev,
}
pci_unmap_addr_set(lbq_desc, mapaddr, map);
pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE);
- bq->addr_lo = cpu_to_le32(map);
- bq->addr_hi = cpu_to_le32(map >> 32);
+ *lbq_desc->addr = cpu_to_le64(map);
}
bq++;
}
@@ -2149,13 +2151,6 @@ static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
dev_kfree_skb(sbq_desc->p.skb);
sbq_desc->p.skb = NULL;
}
- if (sbq_desc->bq == NULL) {
- QPRINTK(qdev, IFUP, ERR, "sbq_desc->bq %d is NULL.\n",
- i);
- return;
- }
- sbq_desc->bq->addr_lo = 0;
- sbq_desc->bq->addr_hi = 0;
}
}
@@ -2167,13 +2162,13 @@ static int ql_alloc_sbq_buffers(struct ql_adapter *qdev,
struct bq_desc *sbq_desc;
struct sk_buff *skb;
u64 map;
- struct bq_element *bq = rx_ring->sbq_base;
+ __le64 *bq = rx_ring->sbq_base;
for (i = 0; i < rx_ring->sbq_len; i++) {
sbq_desc = &rx_ring->sbq[i];
memset(sbq_desc, 0, sizeof(sbq_desc));
sbq_desc->index = i;
- sbq_desc->bq = bq;
+ sbq_desc->addr = bq;
skb = netdev_alloc_skb(qdev->ndev, rx_ring->sbq_buf_size);
if (unlikely(!skb)) {
/* Better luck next round */
@@ -2199,10 +2194,7 @@ static int ql_alloc_sbq_buffers(struct ql_adapter *qdev,
}
pci_unmap_addr_set(sbq_desc, mapaddr, map);
pci_unmap_len_set(sbq_desc, maplen, rx_ring->sbq_buf_size / 2);
- bq->addr_lo = /*sbq_desc->addr_lo = */
- cpu_to_le32(map);
- bq->addr_hi = /*sbq_desc->addr_hi = */
- cpu_to_le32(map >> 32);
+ *sbq_desc->addr = cpu_to_le64(map);
bq++;
}
return 0;
@@ -2373,28 +2365,6 @@ static void ql_tx_ring_clean(struct ql_adapter *qdev)
}
}
-static void ql_free_ring_cb(struct ql_adapter *qdev)
-{
- kfree(qdev->ring_mem);
-}
-
-static int ql_alloc_ring_cb(struct ql_adapter *qdev)
-{
- /* Allocate space for tx/rx ring control blocks. */
- qdev->ring_mem_size =
- (qdev->tx_ring_count * sizeof(struct tx_ring)) +
- (qdev->rx_ring_count * sizeof(struct rx_ring));
- qdev->ring_mem = kmalloc(qdev->ring_mem_size, GFP_KERNEL);
- if (qdev->ring_mem == NULL) {
- return -ENOMEM;
- } else {
- qdev->rx_ring = qdev->ring_mem;
- qdev->tx_ring = qdev->ring_mem +
- (qdev->rx_ring_count * sizeof(struct rx_ring));
- }
- return 0;
-}
-
static void ql_free_mem_resources(struct ql_adapter *qdev)
{
int i;
@@ -2481,14 +2451,12 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
memset((void *)cqicb, 0, sizeof(struct cqicb));
cqicb->msix_vect = rx_ring->irq;
- cqicb->len = cpu_to_le16(rx_ring->cq_len | LEN_V | LEN_CPP_CONT);
+ bq_len = (rx_ring->cq_len == 65536) ? 0 : (u16) rx_ring->cq_len;
+ cqicb->len = cpu_to_le16(bq_len | LEN_V | LEN_CPP_CONT);
- cqicb->addr_lo = cpu_to_le32(rx_ring->cq_base_dma);
- cqicb->addr_hi = cpu_to_le32((u64) rx_ring->cq_base_dma >> 32);
+ cqicb->addr = cpu_to_le64(rx_ring->cq_base_dma);
- cqicb->prod_idx_addr_lo = cpu_to_le32(rx_ring->prod_idx_sh_reg_dma);
- cqicb->prod_idx_addr_hi =
- cpu_to_le32((u64) rx_ring->prod_idx_sh_reg_dma >> 32);
+ cqicb->prod_idx_addr = cpu_to_le64(rx_ring->prod_idx_sh_reg_dma);
/*
* Set up the control block load flags.
@@ -2499,12 +2467,13 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
if (rx_ring->lbq_len) {
cqicb->flags |= FLAGS_LL; /* Load lbq values */
*((u64 *) rx_ring->lbq_base_indirect) = rx_ring->lbq_base_dma;
- cqicb->lbq_addr_lo =
- cpu_to_le32(rx_ring->lbq_base_indirect_dma);
- cqicb->lbq_addr_hi =
- cpu_to_le32((u64) rx_ring->lbq_base_indirect_dma >> 32);
- cqicb->lbq_buf_size = cpu_to_le32(rx_ring->lbq_buf_size);
- bq_len = (u16) rx_ring->lbq_len;
+ cqicb->lbq_addr =
+ cpu_to_le64(rx_ring->lbq_base_indirect_dma);
+ bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 :
+ (u16) rx_ring->lbq_buf_size;
+ cqicb->lbq_buf_size = cpu_to_le16(bq_len);
+ bq_len = (rx_ring->lbq_len == 65536) ? 0 :
+ (u16) rx_ring->lbq_len;
cqicb->lbq_len = cpu_to_le16(bq_len);
rx_ring->lbq_prod_idx = rx_ring->lbq_len - 16;
rx_ring->lbq_curr_idx = 0;
@@ -2514,13 +2483,12 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
if (rx_ring->sbq_len) {
cqicb->flags |= FLAGS_LS; /* Load sbq values */
*((u64 *) rx_ring->sbq_base_indirect) = rx_ring->sbq_base_dma;
- cqicb->sbq_addr_lo =
- cpu_to_le32(rx_ring->sbq_base_indirect_dma);
- cqicb->sbq_addr_hi =
- cpu_to_le32((u64) rx_ring->sbq_base_indirect_dma >> 32);
+ cqicb->sbq_addr =
+ cpu_to_le64(rx_ring->sbq_base_indirect_dma);
cqicb->sbq_buf_size =
cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8);
- bq_len = (u16) rx_ring->sbq_len;
+ bq_len = (rx_ring->sbq_len == 65536) ? 0 :
+ (u16) rx_ring->sbq_len;
cqicb->sbq_len = cpu_to_le16(bq_len);
rx_ring->sbq_prod_idx = rx_ring->sbq_len - 16;
rx_ring->sbq_curr_idx = 0;
@@ -2623,12 +2591,9 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
Q_FLAGS_LB | Q_FLAGS_LI | Q_FLAGS_LO);
wqicb->cq_id_rss = cpu_to_le16(tx_ring->cq_id);
wqicb->rid = 0;
- wqicb->addr_lo = cpu_to_le32(tx_ring->wq_base_dma);
- wqicb->addr_hi = cpu_to_le32((u64) tx_ring->wq_base_dma >> 32);
+ wqicb->addr = cpu_to_le64(tx_ring->wq_base_dma);
- wqicb->cnsmr_idx_addr_lo = cpu_to_le32(tx_ring->cnsmr_idx_sh_reg_dma);
- wqicb->cnsmr_idx_addr_hi =
- cpu_to_le32((u64) tx_ring->cnsmr_idx_sh_reg_dma >> 32);
+ wqicb->cnsmr_idx_addr = cpu_to_le64(tx_ring->cnsmr_idx_sh_reg_dma);
ql_init_tx_ring(qdev, tx_ring);
@@ -2758,14 +2723,14 @@ static void ql_resolve_queues_to_irqs(struct ql_adapter *qdev)
* Outbound queue is for outbound completions only.
*/
intr_context->handler = qlge_msix_tx_isr;
- sprintf(intr_context->name, "%s-txq-%d",
+ sprintf(intr_context->name, "%s-tx-%d",
qdev->ndev->name, i);
} else {
/*
* Inbound queues handle unicast frames only.
*/
intr_context->handler = qlge_msix_rx_isr;
- sprintf(intr_context->name, "%s-rxq-%d",
+ sprintf(intr_context->name, "%s-rx-%d",
qdev->ndev->name, i);
}
}
@@ -3259,7 +3224,6 @@ static int qlge_close(struct net_device *ndev)
msleep(1);
ql_adapter_down(qdev);
ql_release_adapter_resources(qdev);
- ql_free_ring_cb(qdev);
return 0;
}
@@ -3285,8 +3249,8 @@ static int ql_configure_rings(struct ql_adapter *qdev)
* This limitation can be removed when requested.
*/
- if (cpu_cnt > 8)
- cpu_cnt = 8;
+ if (cpu_cnt > MAX_CPUS)
+ cpu_cnt = MAX_CPUS;
/*
* rx_ring[0] is always the default queue.
@@ -3306,9 +3270,6 @@ static int ql_configure_rings(struct ql_adapter *qdev)
*/
qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1;
- if (ql_alloc_ring_cb(qdev))
- return -ENOMEM;
-
for (i = 0; i < qdev->tx_ring_count; i++) {
tx_ring = &qdev->tx_ring[i];
memset((void *)tx_ring, 0, sizeof(tx_ring));
@@ -3341,11 +3302,11 @@ static int ql_configure_rings(struct ql_adapter *qdev)
rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
rx_ring->lbq_len = NUM_LARGE_BUFFERS;
rx_ring->lbq_size =
- rx_ring->lbq_len * sizeof(struct bq_element);
+ rx_ring->lbq_len * sizeof(__le64);
rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE;
rx_ring->sbq_len = NUM_SMALL_BUFFERS;
rx_ring->sbq_size =
- rx_ring->sbq_len * sizeof(struct bq_element);
+ rx_ring->sbq_len * sizeof(__le64);
rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2;
rx_ring->type = DEFAULT_Q;
} else if (i < qdev->rss_ring_first_cq_id) {
@@ -3372,11 +3333,11 @@ static int ql_configure_rings(struct ql_adapter *qdev)
rx_ring->cq_len * sizeof(struct ql_net_rsp_iocb);
rx_ring->lbq_len = NUM_LARGE_BUFFERS;
rx_ring->lbq_size =
- rx_ring->lbq_len * sizeof(struct bq_element);
+ rx_ring->lbq_len * sizeof(__le64);
rx_ring->lbq_buf_size = LARGE_BUFFER_SIZE;
rx_ring->sbq_len = NUM_SMALL_BUFFERS;
rx_ring->sbq_size =
- rx_ring->sbq_len * sizeof(struct bq_element);
+ rx_ring->sbq_len * sizeof(__le64);
rx_ring->sbq_buf_size = SMALL_BUFFER_SIZE * 2;
rx_ring->type = RX_Q;
}
@@ -3405,7 +3366,6 @@ static int qlge_open(struct net_device *ndev)
error_up:
ql_release_adapter_resources(qdev);
- ql_free_ring_cb(qdev);
return err;
}
@@ -3876,7 +3836,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql_adapter *qdev = netdev_priv(ndev);
- int err;
+ int err, i;
netif_device_detach(ndev);
@@ -3886,6 +3846,9 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state)
return err;
}
+ for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++)
+ netif_napi_del(&qdev->rx_ring[i].napi);
+
err = pci_save_state(pdev);
if (err)
return err;
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 53bbddfc8c95..b2dcdb5ed8bd 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -49,8 +49,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.19"
-#define DRV_RELDATE "18Dec2008"
+#define DRV_VERSION "0.21"
+#define DRV_RELDATE "09Jan2009"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -200,7 +200,7 @@ struct r6040_private {
static char version[] __devinitdata = KERN_INFO DRV_NAME
": RDC R6040 NAPI net driver,"
- "version "DRV_VERSION " (" DRV_RELDATE ")\n";
+ "version "DRV_VERSION " (" DRV_RELDATE ")";
static int phy_table[] = { PHY1_ADDR, PHY2_ADDR };
@@ -330,7 +330,7 @@ static int r6040_alloc_rxbufs(struct net_device *dev)
do {
skb = netdev_alloc_skb(dev, MAX_BUF_SIZE);
if (!skb) {
- printk(KERN_ERR "%s: failed to alloc skb for rx\n", dev->name);
+ printk(KERN_ERR DRV_NAME "%s: failed to alloc skb for rx\n", dev->name);
rc = -ENOMEM;
goto err_exit;
}
@@ -438,7 +438,6 @@ static void r6040_down(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- struct pci_dev *pdev = lp->pdev;
int limit = 2048;
u16 *adrp;
u16 cmd;
@@ -457,22 +456,12 @@ static void r6040_down(struct net_device *dev)
iowrite16(adrp[0], ioaddr + MID_0L);
iowrite16(adrp[1], ioaddr + MID_0M);
iowrite16(adrp[2], ioaddr + MID_0H);
- free_irq(dev->irq, dev);
-
- /* Free RX buffer */
- r6040_free_rxbufs(dev);
-
- /* Free TX buffer */
- r6040_free_txbufs(dev);
-
- /* Free Descriptor memory */
- pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
- pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
}
static int r6040_close(struct net_device *dev)
{
struct r6040_private *lp = netdev_priv(dev);
+ struct pci_dev *pdev = lp->pdev;
/* deleted timer */
del_timer_sync(&lp->timer);
@@ -481,8 +470,28 @@ static int r6040_close(struct net_device *dev)
napi_disable(&lp->napi);
netif_stop_queue(dev);
r6040_down(dev);
+
+ free_irq(dev->irq, dev);
+
+ /* Free RX buffer */
+ r6040_free_rxbufs(dev);
+
+ /* Free TX buffer */
+ r6040_free_txbufs(dev);
+
spin_unlock_irq(&lp->lock);
+ /* Free Descriptor memory */
+ if (lp->rx_ring) {
+ pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma);
+ lp->rx_ring = 0;
+ }
+
+ if (lp->tx_ring) {
+ pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma);
+ lp->tx_ring = 0;
+ }
+
return 0;
}
@@ -1049,6 +1058,7 @@ static const struct net_device_ops r6040_netdev_ops = {
.ndo_set_multicast_list = r6040_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = r6040_ioctl,
.ndo_tx_timeout = r6040_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1077,20 +1087,20 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
/* this should always be supported */
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
- printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
+ printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses"
"not supported by the card\n");
goto err_out;
}
err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (err) {
- printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses"
+ printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses"
"not supported by the card\n");
goto err_out;
}
/* IO Size check */
if (pci_resource_len(pdev, 0) < io_size) {
- printk(KERN_ERR DRV_NAME "Insufficient PCI resources, aborting\n");
+ printk(KERN_ERR DRV_NAME ": Insufficient PCI resources, aborting\n");
err = -EIO;
goto err_out;
}
@@ -1100,7 +1110,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
dev = alloc_etherdev(sizeof(struct r6040_private));
if (!dev) {
- printk(KERN_ERR DRV_NAME "Failed to allocate etherdev\n");
+ printk(KERN_ERR DRV_NAME ": Failed to allocate etherdev\n");
err = -ENOMEM;
goto err_out;
}
@@ -1116,11 +1126,15 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
ioaddr = pci_iomap(pdev, bar, io_size);
if (!ioaddr) {
- printk(KERN_ERR "ioremap failed for device %s\n",
+ printk(KERN_ERR DRV_NAME ": ioremap failed for device %s\n",
pci_name(pdev));
err = -EIO;
goto err_out_free_res;
}
+ /* If PHY status change register is still set to zero it means the
+ * bootloader didn't initialize it */
+ if (ioread16(ioaddr + PHY_CC) == 0)
+ iowrite16(0x9f07, ioaddr + PHY_CC);
/* Init system & device */
lp->base = ioaddr;
@@ -1137,6 +1151,13 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
adrp[1] = ioread16(ioaddr + MID_0M);
adrp[2] = ioread16(ioaddr + MID_0H);
+ /* Some bootloader/BIOSes do not initialize
+ * MAC address, warn about that */
+ if (!(adrp[0] || adrp[1] || adrp[2])) {
+ printk(KERN_WARNING DRV_NAME ": MAC address not initialized, generating random\n");
+ random_ether_addr(dev->dev_addr);
+ }
+
/* Link new device into r6040_root_dev */
lp->pdev = pdev;
lp->dev = dev;
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index be3025310e90..fc0e38bddeeb 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -134,6 +134,16 @@ static const struct pnp_device_id sb1000_pnp_ids[] = {
};
MODULE_DEVICE_TABLE(pnp, sb1000_pnp_ids);
+static const struct net_device_ops sb1000_netdev_ops = {
+ .ndo_open = sb1000_open,
+ .ndo_start_xmit = sb1000_start_xmit,
+ .ndo_do_ioctl = sb1000_dev_ioctl,
+ .ndo_stop = sb1000_close,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int
sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id)
{
@@ -192,11 +202,7 @@ sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id)
if (sb1000_debug > 0)
printk(KERN_NOTICE "%s", version);
- /* The SB1000-specific entries in the device structure. */
- dev->open = sb1000_open;
- dev->do_ioctl = sb1000_dev_ioctl;
- dev->hard_start_xmit = sb1000_start_xmit;
- dev->stop = sb1000_close;
+ dev->netdev_ops = &sb1000_netdev_ops;
/* hardware address is 0:0:serial_number */
dev->dev_addr[2] = serial_number >> 24 & 0xff;
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 42fd31276602..8b75bef4a841 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -1408,6 +1408,7 @@ static const struct net_device_ops sc92031_netdev_ops = {
.ndo_set_multicast_list = sc92031_set_multicast_list,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_tx_timeout = sc92031_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = sc92031_poll_controller,
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7673fd92eaf5..ab0e09bf154d 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -676,9 +676,8 @@ static int efx_init_port(struct efx_nic *efx)
rc = efx->phy_op->init(efx);
if (rc)
return rc;
- efx->phy_op->reconfigure(efx);
-
mutex_lock(&efx->mac_lock);
+ efx->phy_op->reconfigure(efx);
rc = falcon_switch_mac(efx);
mutex_unlock(&efx->mac_lock);
if (rc)
@@ -686,7 +685,7 @@ static int efx_init_port(struct efx_nic *efx)
efx->mac_op->reconfigure(efx);
efx->port_initialized = true;
- efx->stats_enabled = true;
+ efx_stats_enable(efx);
return 0;
fail:
@@ -735,6 +734,7 @@ static void efx_fini_port(struct efx_nic *efx)
if (!efx->port_initialized)
return;
+ efx_stats_disable(efx);
efx->phy_op->fini(efx);
efx->port_initialized = false;
@@ -1361,6 +1361,20 @@ static int efx_net_stop(struct net_device *net_dev)
return 0;
}
+void efx_stats_disable(struct efx_nic *efx)
+{
+ spin_lock(&efx->stats_lock);
+ ++efx->stats_disable_count;
+ spin_unlock(&efx->stats_lock);
+}
+
+void efx_stats_enable(struct efx_nic *efx)
+{
+ spin_lock(&efx->stats_lock);
+ --efx->stats_disable_count;
+ spin_unlock(&efx->stats_lock);
+}
+
/* Context: process, dev_base_lock or RTNL held, non-blocking. */
static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
{
@@ -1369,12 +1383,12 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
struct net_device_stats *stats = &net_dev->stats;
/* Update stats if possible, but do not wait if another thread
- * is updating them (or resetting the NIC); slightly stale
- * stats are acceptable.
+ * is updating them or if MAC stats fetches are temporarily
+ * disabled; slightly stale stats are acceptable.
*/
if (!spin_trylock(&efx->stats_lock))
return stats;
- if (efx->stats_enabled) {
+ if (!efx->stats_disable_count) {
efx->mac_op->update_stats(efx);
falcon_update_nic_stats(efx);
}
@@ -1622,16 +1636,12 @@ static void efx_unregister_netdev(struct efx_nic *efx)
/* Tears down the entire software state and most of the hardware state
* before reset. */
-void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+void efx_reset_down(struct efx_nic *efx, enum reset_type method,
+ struct ethtool_cmd *ecmd)
{
EFX_ASSERT_RESET_SERIALISED(efx);
- /* The net_dev->get_stats handler is quite slow, and will fail
- * if a fetch is pending over reset. Serialise against it. */
- spin_lock(&efx->stats_lock);
- efx->stats_enabled = false;
- spin_unlock(&efx->stats_lock);
-
+ efx_stats_disable(efx);
efx_stop_all(efx);
mutex_lock(&efx->mac_lock);
mutex_lock(&efx->spi_lock);
@@ -1639,6 +1649,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
efx->phy_op->get_settings(efx, ecmd);
efx_fini_channels(efx);
+ if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
+ efx->phy_op->fini(efx);
}
/* This function will always ensure that the locks acquired in
@@ -1646,7 +1658,8 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
* that we were unable to reinitialise the hardware, and the
* driver should be disabled. If ok is false, then the rx and tx
* engines are not restarted, pending a RESET_DISABLE. */
-int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
+int efx_reset_up(struct efx_nic *efx, enum reset_type method,
+ struct ethtool_cmd *ecmd, bool ok)
{
int rc;
@@ -1658,6 +1671,15 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
ok = false;
}
+ if (efx->port_initialized && method != RESET_TYPE_INVISIBLE) {
+ if (ok) {
+ rc = efx->phy_op->init(efx);
+ if (rc)
+ ok = false;
+ } else
+ efx->port_initialized = false;
+ }
+
if (ok) {
efx_init_channels(efx);
@@ -1670,7 +1692,7 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
if (ok) {
efx_start_all(efx);
- efx->stats_enabled = true;
+ efx_stats_enable(efx);
}
return rc;
}
@@ -1702,7 +1724,7 @@ static int efx_reset(struct efx_nic *efx)
EFX_INFO(efx, "resetting (%d)\n", method);
- efx_reset_down(efx, &ecmd);
+ efx_reset_down(efx, method, &ecmd);
rc = falcon_reset_hw(efx, method);
if (rc) {
@@ -1721,10 +1743,10 @@ static int efx_reset(struct efx_nic *efx)
/* Leave device stopped if necessary */
if (method == RESET_TYPE_DISABLE) {
- efx_reset_up(efx, &ecmd, false);
+ efx_reset_up(efx, method, &ecmd, false);
rc = -EIO;
} else {
- rc = efx_reset_up(efx, &ecmd, true);
+ rc = efx_reset_up(efx, method, &ecmd, true);
}
out_disable:
@@ -1876,6 +1898,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->rx_checksum_enabled = true;
spin_lock_init(&efx->netif_stop_lock);
spin_lock_init(&efx->stats_lock);
+ efx->stats_disable_count = 1;
mutex_init(&efx->mac_lock);
efx->mac_op = &efx_dummy_mac_operations;
efx->phy_op = &efx_dummy_phy_operations;
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 0dd7a532c78a..55d0f131b0e9 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -36,13 +36,16 @@ extern void efx_process_channel_now(struct efx_channel *channel);
extern void efx_flush_queues(struct efx_nic *efx);
/* Ports */
+extern void efx_stats_disable(struct efx_nic *efx);
+extern void efx_stats_enable(struct efx_nic *efx);
extern void efx_reconfigure_port(struct efx_nic *efx);
extern void __efx_reconfigure_port(struct efx_nic *efx);
/* Reset handling */
-extern void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd);
-extern int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd,
- bool ok);
+extern void efx_reset_down(struct efx_nic *efx, enum reset_type method,
+ struct ethtool_cmd *ecmd);
+extern int efx_reset_up(struct efx_nic *efx, enum reset_type method,
+ struct ethtool_cmd *ecmd, bool ok);
/* Global */
extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type);
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index 53d259e90187..7b5924c039b3 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -219,9 +219,6 @@ int efx_ethtool_set_settings(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
int rc;
- if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg)
- return -EINVAL;
-
/* Falcon GMAC does not support 1000Mbps HD */
if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 6884dc8c1f82..d5378e60fcdd 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -824,10 +824,6 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
rx_ev_pause_frm ? " [PAUSE]" : "");
}
#endif
-
- if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
- efx->phy_type == PHY_TYPE_SFX7101))
- tenxpress_crc_err(efx);
}
/* Handle receive events that are not in-order. */
@@ -1403,9 +1399,9 @@ static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx)
}
/* Disable both devices */
- pci_disable_device(efx->pci_dev);
+ pci_clear_master(efx->pci_dev);
if (FALCON_IS_DUAL_FUNC(efx))
- pci_disable_device(nic_data->pci_dev2);
+ pci_clear_master(nic_data->pci_dev2);
falcon_disable_interrupts(efx);
if (++n_int_errors < FALCON_MAX_INT_ERRORS) {
@@ -1887,7 +1883,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
/* MAC stats will fail whilst the TX fifo is draining. Serialise
* the drain sequence with the statistics fetch */
- spin_lock(&efx->stats_lock);
+ efx_stats_disable(efx);
falcon_read(efx, &reg, MAC0_CTRL_REG_KER);
EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1);
@@ -1917,7 +1913,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
udelay(10);
}
- spin_unlock(&efx->stats_lock);
+ efx_stats_enable(efx);
/* If we've reset the EM block and the link is up, then
* we'll have to kick the XAUI link so the PHY can recover */
@@ -2277,6 +2273,10 @@ int falcon_switch_mac(struct efx_nic *efx)
struct efx_mac_operations *old_mac_op = efx->mac_op;
efx_oword_t nic_stat;
unsigned strap_val;
+ int rc = 0;
+
+ /* Don't try to fetch MAC stats while we're switching MACs */
+ efx_stats_disable(efx);
/* Internal loopbacks override the phy speed setting */
if (efx->loopback_mode == LOOPBACK_GMAC) {
@@ -2287,16 +2287,12 @@ int falcon_switch_mac(struct efx_nic *efx)
efx->link_fd = true;
}
+ WARN_ON(!mutex_is_locked(&efx->mac_lock));
efx->mac_op = (EFX_IS10G(efx) ?
&falcon_xmac_operations : &falcon_gmac_operations);
- if (old_mac_op == efx->mac_op)
- return 0;
-
- WARN_ON(!mutex_is_locked(&efx->mac_lock));
-
- /* Not all macs support a mac-level link state */
- efx->mac_up = true;
+ /* Always push the NIC_STAT_REG setting even if the mac hasn't
+ * changed, because this function is run post online reset */
falcon_read(efx, &nic_stat, NIC_STAT_REG);
strap_val = EFX_IS10G(efx) ? 5 : 3;
if (falcon_rev(efx) >= FALCON_REV_B0) {
@@ -2309,9 +2305,17 @@ int falcon_switch_mac(struct efx_nic *efx)
BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val);
}
+ if (old_mac_op == efx->mac_op)
+ goto out;
EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
- return falcon_reset_macs(efx);
+ /* Not all macs support a mac-level link state */
+ efx->mac_up = true;
+
+ rc = falcon_reset_macs(efx);
+out:
+ efx_stats_enable(efx);
+ return rc;
}
/* This call is responsible for hooking in the MAC and PHY operations */
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index f6a16428113d..f9e2f95c3b48 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -15,6 +15,7 @@
#include "net_driver.h"
#include "mdio_10g.h"
#include "boards.h"
+#include "workarounds.h"
int mdio_clause45_reset_mmd(struct efx_nic *port, int mmd,
int spins, int spintime)
@@ -179,17 +180,12 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
return false;
else if (efx_phy_mode_disabled(efx->phy_mode))
return false;
- else if (efx->loopback_mode == LOOPBACK_PHYXS) {
+ else if (efx->loopback_mode == LOOPBACK_PHYXS)
mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
MDIO_MMDREG_DEVS_PCS |
MDIO_MMDREG_DEVS_PMAPMD |
MDIO_MMDREG_DEVS_AN);
- if (!mmd_mask) {
- reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
- MDIO_PHYXS_STATUS2);
- return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
- }
- } else if (efx->loopback_mode == LOOPBACK_PCS)
+ else if (efx->loopback_mode == LOOPBACK_PCS)
mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
MDIO_MMDREG_DEVS_PMAPMD |
MDIO_MMDREG_DEVS_AN);
@@ -197,6 +193,13 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD |
MDIO_MMDREG_DEVS_AN);
+ if (!mmd_mask) {
+ /* Use presence of XGMII faults in leui of link state */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
+ MDIO_PHYXS_STATUS2);
+ return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
+ }
+
while (mmd_mask) {
if (mmd_mask & 1) {
/* Double reads because link state is latched, and a
@@ -263,7 +266,7 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
}
}
-static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp)
+static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr)
{
int phy_id = efx->mii.phy_id;
u32 result = 0;
@@ -278,9 +281,6 @@ static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp)
result |= ADVERTISED_100baseT_Half;
if (reg & ADVERTISE_100FULL)
result |= ADVERTISED_100baseT_Full;
- if (reg & LPA_RESV)
- result |= xnp;
-
return result;
}
@@ -310,7 +310,7 @@ void mdio_clause45_get_settings(struct efx_nic *efx,
*/
void mdio_clause45_get_settings_ext(struct efx_nic *efx,
struct ethtool_cmd *ecmd,
- u32 xnp, u32 xnp_lpa)
+ u32 npage_adv, u32 npage_lpa)
{
int phy_id = efx->mii.phy_id;
int reg;
@@ -361,8 +361,8 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx,
ecmd->autoneg = AUTONEG_ENABLE;
ecmd->advertising |=
ADVERTISED_Autoneg |
- mdio_clause45_get_an(efx,
- MDIO_AN_ADVERTISE, xnp);
+ mdio_clause45_get_an(efx, MDIO_AN_ADVERTISE) |
+ npage_adv;
} else
ecmd->autoneg = AUTONEG_DISABLE;
} else
@@ -371,27 +371,30 @@ void mdio_clause45_get_settings_ext(struct efx_nic *efx,
if (ecmd->autoneg) {
/* If AN is complete, report best common mode,
* otherwise report best advertised mode. */
- u32 common = ecmd->advertising;
+ u32 modes = 0;
if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
MDIO_MMDREG_STAT1) &
- (1 << MDIO_AN_STATUS_AN_DONE_LBN)) {
- common &= mdio_clause45_get_an(efx, MDIO_AN_LPA,
- xnp_lpa);
- }
- if (common & ADVERTISED_10000baseT_Full) {
+ (1 << MDIO_AN_STATUS_AN_DONE_LBN))
+ modes = (ecmd->advertising &
+ (mdio_clause45_get_an(efx, MDIO_AN_LPA) |
+ npage_lpa));
+ if (modes == 0)
+ modes = ecmd->advertising;
+
+ if (modes & ADVERTISED_10000baseT_Full) {
ecmd->speed = SPEED_10000;
ecmd->duplex = DUPLEX_FULL;
- } else if (common & (ADVERTISED_1000baseT_Full |
- ADVERTISED_1000baseT_Half)) {
+ } else if (modes & (ADVERTISED_1000baseT_Full |
+ ADVERTISED_1000baseT_Half)) {
ecmd->speed = SPEED_1000;
- ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full);
- } else if (common & (ADVERTISED_100baseT_Full |
- ADVERTISED_100baseT_Half)) {
+ ecmd->duplex = !!(modes & ADVERTISED_1000baseT_Full);
+ } else if (modes & (ADVERTISED_100baseT_Full |
+ ADVERTISED_100baseT_Half)) {
ecmd->speed = SPEED_100;
- ecmd->duplex = !!(common & ADVERTISED_100baseT_Full);
+ ecmd->duplex = !!(modes & ADVERTISED_100baseT_Full);
} else {
ecmd->speed = SPEED_10;
- ecmd->duplex = !!(common & ADVERTISED_10baseT_Full);
+ ecmd->duplex = !!(modes & ADVERTISED_10baseT_Full);
}
} else {
/* Report forced settings */
@@ -415,7 +418,7 @@ int mdio_clause45_set_settings(struct efx_nic *efx,
int phy_id = efx->mii.phy_id;
struct ethtool_cmd prev;
u32 required;
- int ctrl1_bits, reg;
+ int reg;
efx->phy_op->get_settings(efx, &prev);
@@ -430,99 +433,83 @@ int mdio_clause45_set_settings(struct efx_nic *efx,
if (prev.port != PORT_TP || ecmd->port != PORT_TP)
return -EINVAL;
- /* Check that PHY supports these settings and work out the
- * basic control bits */
- if (ecmd->duplex) {
+ /* Check that PHY supports these settings */
+ if (ecmd->autoneg) {
+ required = SUPPORTED_Autoneg;
+ } else if (ecmd->duplex) {
switch (ecmd->speed) {
- case SPEED_10:
- ctrl1_bits = BMCR_FULLDPLX;
- required = SUPPORTED_10baseT_Full;
- break;
- case SPEED_100:
- ctrl1_bits = BMCR_SPEED100 | BMCR_FULLDPLX;
- required = SUPPORTED_100baseT_Full;
- break;
- case SPEED_1000:
- ctrl1_bits = BMCR_SPEED1000 | BMCR_FULLDPLX;
- required = SUPPORTED_1000baseT_Full;
- break;
- case SPEED_10000:
- ctrl1_bits = (BMCR_SPEED1000 | BMCR_SPEED100 |
- BMCR_FULLDPLX);
- required = SUPPORTED_10000baseT_Full;
- break;
- default:
- return -EINVAL;
+ case SPEED_10: required = SUPPORTED_10baseT_Full; break;
+ case SPEED_100: required = SUPPORTED_100baseT_Full; break;
+ default: return -EINVAL;
}
} else {
switch (ecmd->speed) {
- case SPEED_10:
- ctrl1_bits = 0;
- required = SUPPORTED_10baseT_Half;
- break;
- case SPEED_100:
- ctrl1_bits = BMCR_SPEED100;
- required = SUPPORTED_100baseT_Half;
- break;
- case SPEED_1000:
- ctrl1_bits = BMCR_SPEED1000;
- required = SUPPORTED_1000baseT_Half;
- break;
- default:
- return -EINVAL;
+ case SPEED_10: required = SUPPORTED_10baseT_Half; break;
+ case SPEED_100: required = SUPPORTED_100baseT_Half; break;
+ default: return -EINVAL;
}
}
- if (ecmd->autoneg)
- required |= SUPPORTED_Autoneg;
required |= ecmd->advertising;
if (required & ~prev.supported)
return -EINVAL;
- /* Set the basic control bits */
- reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
- MDIO_MMDREG_CTRL1);
- reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | 0x003c);
- reg |= ctrl1_bits;
- mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1,
- reg);
-
- /* Set the AN registers */
- if (ecmd->autoneg != prev.autoneg ||
- ecmd->advertising != prev.advertising) {
- bool xnp = false;
-
- if (efx->phy_op->set_xnp_advertise)
- xnp = efx->phy_op->set_xnp_advertise(efx,
- ecmd->advertising);
-
- if (ecmd->autoneg) {
- reg = 0;
- if (ecmd->advertising & ADVERTISED_10baseT_Half)
- reg |= ADVERTISE_10HALF;
- if (ecmd->advertising & ADVERTISED_10baseT_Full)
- reg |= ADVERTISE_10FULL;
- if (ecmd->advertising & ADVERTISED_100baseT_Half)
- reg |= ADVERTISE_100HALF;
- if (ecmd->advertising & ADVERTISED_100baseT_Full)
- reg |= ADVERTISE_100FULL;
- if (xnp)
- reg |= ADVERTISE_RESV;
- mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
- MDIO_AN_ADVERTISE, reg);
- }
+ if (ecmd->autoneg) {
+ bool xnp = (ecmd->advertising & ADVERTISED_10000baseT_Full
+ || EFX_WORKAROUND_13204(efx));
+
+ /* Set up the base page */
+ reg = ADVERTISE_CSMA;
+ if (ecmd->advertising & ADVERTISED_10baseT_Half)
+ reg |= ADVERTISE_10HALF;
+ if (ecmd->advertising & ADVERTISED_10baseT_Full)
+ reg |= ADVERTISE_10FULL;
+ if (ecmd->advertising & ADVERTISED_100baseT_Half)
+ reg |= ADVERTISE_100HALF;
+ if (ecmd->advertising & ADVERTISED_100baseT_Full)
+ reg |= ADVERTISE_100FULL;
+ if (xnp)
+ reg |= ADVERTISE_RESV;
+ else if (ecmd->advertising & (ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full))
+ reg |= ADVERTISE_NPAGE;
+ reg |= efx_fc_advertise(efx->wanted_fc);
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_ADVERTISE, reg);
+
+ /* Set up the (extended) next page if necessary */
+ if (efx->phy_op->set_npage_adv)
+ efx->phy_op->set_npage_adv(efx, ecmd->advertising);
+ /* Enable and restart AN */
reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
MDIO_MMDREG_CTRL1);
- if (ecmd->autoneg)
- reg |= BMCR_ANENABLE | BMCR_ANRESTART;
- else
- reg &= ~BMCR_ANENABLE;
+ reg |= BMCR_ANENABLE;
+ if (!(EFX_WORKAROUND_15195(efx) &&
+ LOOPBACK_MASK(efx) & efx->phy_op->loopbacks))
+ reg |= BMCR_ANRESTART;
if (xnp)
reg |= 1 << MDIO_AN_CTRL_XNP_LBN;
else
reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN);
mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
MDIO_MMDREG_CTRL1, reg);
+ } else {
+ /* Disable AN */
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
+ MDIO_MMDREG_CTRL1,
+ __ffs(BMCR_ANENABLE), false);
+
+ /* Set the basic control bits */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_CTRL1);
+ reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX |
+ 0x003c);
+ if (ecmd->speed == SPEED_100)
+ reg |= BMCR_SPEED100;
+ if (ecmd->duplex)
+ reg |= BMCR_FULLDPLX;
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_CTRL1, reg);
}
return 0;
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index 09bf801d0569..8ba49773ce7e 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -155,7 +155,8 @@
#define MDIO_AN_XNP 22
#define MDIO_AN_LPA_XNP 25
-#define MDIO_AN_10GBT_ADVERTISE 32
+#define MDIO_AN_10GBT_CTRL 32
+#define MDIO_AN_10GBT_CTRL_ADV_10G_LBN 12
#define MDIO_AN_10GBT_STATUS (33)
#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 5f255f75754e..e019ad1fb9a0 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -566,7 +566,7 @@ struct efx_mac_operations {
* @poll: Poll for hardware state. Serialised by the mac_lock.
* @get_settings: Get ethtool settings. Serialised by the mac_lock.
* @set_settings: Set ethtool settings. Serialised by the mac_lock.
- * @set_xnp_advertise: Set abilities advertised in Extended Next Page
+ * @set_npage_adv: Set abilities advertised in (Extended) Next Page
* (only needed where AN bit is set in mmds)
* @num_tests: Number of PHY-specific tests/results
* @test_names: Names of the tests/results
@@ -586,7 +586,7 @@ struct efx_phy_operations {
struct ethtool_cmd *ecmd);
int (*set_settings) (struct efx_nic *efx,
struct ethtool_cmd *ecmd);
- bool (*set_xnp_advertise) (struct efx_nic *efx, u32);
+ void (*set_npage_adv) (struct efx_nic *efx, u32);
u32 num_tests;
const char *const *test_names;
int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
@@ -754,8 +754,7 @@ union efx_multicast_hash {
* &struct net_device_stats.
* @stats_buffer: DMA buffer for statistics
* @stats_lock: Statistics update lock. Serialises statistics fetches
- * @stats_enabled: Temporarily disable statistics fetches.
- * Serialised by @stats_lock
+ * @stats_disable_count: Nest count for disabling statistics fetches
* @mac_op: MAC interface
* @mac_address: Permanent MAC address
* @phy_type: PHY type
@@ -837,7 +836,7 @@ struct efx_nic {
struct efx_mac_stats mac_stats;
struct efx_buffer stats_buffer;
spinlock_t stats_lock;
- bool stats_enabled;
+ unsigned int stats_disable_count;
struct efx_mac_operations *mac_op;
unsigned char mac_address[ETH_ALEN];
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index 58c493ef81bb..07e855c148bc 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -17,7 +17,6 @@ extern struct efx_phy_operations falcon_sfx7101_phy_ops;
extern struct efx_phy_operations falcon_sft9001_phy_ops;
extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
-extern void tenxpress_crc_err(struct efx_nic *efx);
/****************************************************************************
* Exported functions from the driver for XFP optical PHYs
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index dba0d64d50cd..0a598084c513 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -665,6 +665,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
{
enum efx_loopback_mode loopback_mode = efx->loopback_mode;
int phy_mode = efx->phy_mode;
+ enum reset_type reset_method = RESET_TYPE_INVISIBLE;
struct ethtool_cmd ecmd;
struct efx_channel *channel;
int rc_test = 0, rc_reset = 0, rc;
@@ -718,21 +719,21 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
mutex_unlock(&efx->mac_lock);
/* free up all consumers of SRAM (including all the queues) */
- efx_reset_down(efx, &ecmd);
+ efx_reset_down(efx, reset_method, &ecmd);
rc = efx_test_chip(efx, tests);
if (rc && !rc_test)
rc_test = rc;
/* reset the chip to recover from the register test */
- rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL);
+ rc_reset = falcon_reset_hw(efx, reset_method);
/* Ensure that the phy is powered and out of loopback
* for the bist and loopback tests */
efx->phy_mode &= ~PHY_MODE_LOW_POWER;
efx->loopback_mode = LOOPBACK_NONE;
- rc = efx_reset_up(efx, &ecmd, rc_reset == 0);
+ rc = efx_reset_up(efx, reset_method, &ecmd, rc_reset == 0);
if (rc && !rc_reset)
rc_reset = rc;
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index 16b80acb9992..cb25ae5b257a 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -186,19 +186,22 @@ static int sfn4111t_reset(struct efx_nic *efx)
{
efx_oword_t reg;
- /* GPIO pins are also used for I2C, so block that temporarily */
+ /* GPIO 3 and the GPIO register are shared with I2C, so block that */
mutex_lock(&efx->i2c_adap.bus_lock);
+ /* Pull RST_N (GPIO 2) low then let it up again, setting the
+ * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the
+ * output enables; the output levels should always be 0 (low)
+ * and we rely on external pull-ups. */
falcon_read(efx, &reg, GPIO_CTL_REG_KER);
EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true);
- EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, false);
falcon_write(efx, &reg, GPIO_CTL_REG_KER);
msleep(1000);
- EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, true);
- EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, true);
- EFX_SET_OWORD_FIELD(reg, GPIO3_OUT,
- !(efx->phy_mode & PHY_MODE_SPECIAL));
+ EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, false);
+ EFX_SET_OWORD_FIELD(reg, GPIO3_OEN,
+ !!(efx->phy_mode & PHY_MODE_SPECIAL));
falcon_write(efx, &reg, GPIO_CTL_REG_KER);
+ msleep(1);
mutex_unlock(&efx->i2c_adap.bus_lock);
@@ -232,12 +235,18 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
} else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
err = -EBUSY;
} else {
+ /* Reset the PHY, reconfigure the MAC and enable/disable
+ * MAC stats accordingly. */
efx->phy_mode = new_mode;
+ if (new_mode & PHY_MODE_SPECIAL)
+ efx_stats_disable(efx);
if (efx->board_info.type == EFX_BOARD_SFE4001)
err = sfe4001_poweron(efx);
else
err = sfn4111t_reset(efx);
efx_reconfigure_port(efx);
+ if (!(new_mode & PHY_MODE_SPECIAL))
+ efx_stats_enable(efx);
}
rtnl_unlock();
@@ -326,6 +335,11 @@ int sfe4001_init(struct efx_nic *efx)
efx->board_info.monitor = sfe4001_check_hw;
efx->board_info.fini = sfe4001_fini;
+ if (efx->phy_mode & PHY_MODE_SPECIAL) {
+ /* PHY won't generate a 156.25 MHz clock and MAC stats fetch
+ * will fail. */
+ efx_stats_disable(efx);
+ }
rc = sfe4001_poweron(efx);
if (rc)
goto fail_ioexp;
@@ -372,17 +386,25 @@ static void sfn4111t_fini(struct efx_nic *efx)
i2c_unregister_device(efx->board_info.hwmon_client);
}
-static struct i2c_board_info sfn4111t_hwmon_info = {
+static struct i2c_board_info sfn4111t_a0_hwmon_info = {
I2C_BOARD_INFO("max6647", 0x4e),
.irq = -1,
};
+static struct i2c_board_info sfn4111t_r5_hwmon_info = {
+ I2C_BOARD_INFO("max6646", 0x4d),
+ .irq = -1,
+};
+
int sfn4111t_init(struct efx_nic *efx)
{
int rc;
efx->board_info.hwmon_client =
- i2c_new_device(&efx->i2c_adap, &sfn4111t_hwmon_info);
+ i2c_new_device(&efx->i2c_adap,
+ (efx->board_info.minor < 5) ?
+ &sfn4111t_a0_hwmon_info :
+ &sfn4111t_r5_hwmon_info);
if (!efx->board_info.hwmon_client)
return -EIO;
@@ -394,8 +416,10 @@ int sfn4111t_init(struct efx_nic *efx)
if (rc)
goto fail_hwmon;
- if (efx->phy_mode & PHY_MODE_SPECIAL)
+ if (efx->phy_mode & PHY_MODE_SPECIAL) {
+ efx_stats_disable(efx);
sfn4111t_reset(efx);
+ }
return 0;
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index b9768760fae7..f0efd246962c 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -67,6 +67,8 @@
#define PMA_PMD_EXT_CLK312_WIDTH 1
#define PMA_PMD_EXT_LPOWER_LBN 12
#define PMA_PMD_EXT_LPOWER_WIDTH 1
+#define PMA_PMD_EXT_ROBUST_LBN 14
+#define PMA_PMD_EXT_ROBUST_WIDTH 1
#define PMA_PMD_EXT_SSR_LBN 15
#define PMA_PMD_EXT_SSR_WIDTH 1
@@ -177,35 +179,24 @@
#define C22EXT_STATUS_LINK_LBN 2
#define C22EXT_STATUS_LINK_WIDTH 1
-#define C22EXT_MSTSLV_REG 49162
-#define C22EXT_MSTSLV_1000_HD_LBN 10
-#define C22EXT_MSTSLV_1000_HD_WIDTH 1
-#define C22EXT_MSTSLV_1000_FD_LBN 11
-#define C22EXT_MSTSLV_1000_FD_WIDTH 1
+#define C22EXT_MSTSLV_CTRL 49161
+#define C22EXT_MSTSLV_CTRL_ADV_1000_HD_LBN 8
+#define C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN 9
+
+#define C22EXT_MSTSLV_STATUS 49162
+#define C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN 10
+#define C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN 11
/* Time to wait between powering down the LNPGA and turning off the power
* rails */
#define LNPGA_PDOWN_WAIT (HZ / 5)
-static int crc_error_reset_threshold = 100;
-module_param(crc_error_reset_threshold, int, 0644);
-MODULE_PARM_DESC(crc_error_reset_threshold,
- "Max number of CRC errors before XAUI reset");
-
struct tenxpress_phy_data {
enum efx_loopback_mode loopback_mode;
- atomic_t bad_crc_count;
enum efx_phy_mode phy_mode;
int bad_lp_tries;
};
-void tenxpress_crc_err(struct efx_nic *efx)
-{
- struct tenxpress_phy_data *phy_data = efx->phy_data;
- if (phy_data != NULL)
- atomic_inc(&phy_data->bad_crc_count);
-}
-
static ssize_t show_phy_short_reach(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -284,7 +275,9 @@ static int tenxpress_init(struct efx_nic *efx)
PMA_PMD_XCONTROL_REG);
reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
(1 << PMA_PMD_EXT_CLK_OUT_LBN) |
- (1 << PMA_PMD_EXT_CLK312_LBN));
+ (1 << PMA_PMD_EXT_CLK312_LBN) |
+ (1 << PMA_PMD_EXT_ROBUST_LBN));
+
mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
PMA_PMD_XCONTROL_REG, reg);
mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
@@ -346,6 +339,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
rc = tenxpress_init(efx);
if (rc < 0)
goto fail;
+ mdio_clause45_set_pause(efx);
if (efx->phy_type == PHY_TYPE_SFT9001B) {
rc = device_create_file(&efx->pci_dev->dev,
@@ -376,8 +370,8 @@ static int tenxpress_special_reset(struct efx_nic *efx)
/* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
* a special software reset can glitch the XGMAC sufficiently for stats
- * requests to fail. Since we don't often special_reset, just lock. */
- spin_lock(&efx->stats_lock);
+ * requests to fail. */
+ efx_stats_disable(efx);
/* Initiate reset */
reg = mdio_clause45_read(efx, efx->mii.phy_id,
@@ -392,17 +386,17 @@ static int tenxpress_special_reset(struct efx_nic *efx)
rc = mdio_clause45_wait_reset_mmds(efx,
TENXPRESS_REQUIRED_DEVS);
if (rc < 0)
- goto unlock;
+ goto out;
/* Try and reconfigure the device */
rc = tenxpress_init(efx);
if (rc < 0)
- goto unlock;
+ goto out;
/* Wait for the XGXS state machine to churn */
mdelay(10);
-unlock:
- spin_unlock(&efx->stats_lock);
+out:
+ efx_stats_enable(efx);
return rc;
}
@@ -520,7 +514,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
struct ethtool_cmd ecmd;
- bool phy_mode_change, loop_reset, loop_toggle, loopback;
+ bool phy_mode_change, loop_reset;
if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
phy_data->phy_mode = efx->phy_mode;
@@ -531,12 +525,10 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
phy_data->phy_mode != PHY_MODE_NORMAL);
- loopback = LOOPBACK_MASK(efx) & efx->phy_op->loopbacks;
- loop_toggle = LOOPBACK_CHANGED(phy_data, efx, efx->phy_op->loopbacks);
loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
- if (loop_reset || loop_toggle || loopback || phy_mode_change) {
+ if (loop_reset || phy_mode_change) {
int rc;
efx->phy_op->get_settings(efx, &ecmd);
@@ -551,20 +543,6 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx)
falcon_reset_xaui(efx);
}
- if (efx->phy_type != PHY_TYPE_SFX7101) {
- /* Only change autoneg once, on coming out or
- * going into loopback */
- if (loop_toggle)
- ecmd.autoneg = !loopback;
- if (loopback) {
- ecmd.duplex = DUPLEX_FULL;
- if (efx->loopback_mode == LOOPBACK_GPHY)
- ecmd.speed = SPEED_1000;
- else
- ecmd.speed = SPEED_10000;
- }
- }
-
rc = efx->phy_op->set_settings(efx, &ecmd);
WARN_ON(rc);
}
@@ -623,23 +601,17 @@ static void tenxpress_phy_poll(struct efx_nic *efx)
if (phy_data->phy_mode != PHY_MODE_NORMAL)
return;
-
- if (EFX_WORKAROUND_10750(efx) &&
- atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
- EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
- falcon_reset_xaui(efx);
- atomic_set(&phy_data->bad_crc_count, 0);
- }
}
static void tenxpress_phy_fini(struct efx_nic *efx)
{
int reg;
- if (efx->phy_type == PHY_TYPE_SFT9001B) {
+ if (efx->phy_type == PHY_TYPE_SFT9001B)
device_remove_file(&efx->pci_dev->dev,
&dev_attr_phy_short_reach);
- } else {
+
+ if (efx->phy_type == PHY_TYPE_SFX7101) {
/* Power down the LNPGA */
reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
@@ -771,107 +743,76 @@ reset:
return rc;
}
-static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx)
+static void
+tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
- int phy = efx->mii.phy_id;
- u32 lpa = 0;
+ int phy_id = efx->mii.phy_id;
+ u32 adv = 0, lpa = 0;
int reg;
if (efx->phy_type != PHY_TYPE_SFX7101) {
- reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT,
- C22EXT_MSTSLV_REG);
- if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN))
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
+ C22EXT_MSTSLV_CTRL);
+ if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN))
+ adv |= ADVERTISED_1000baseT_Full;
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
+ C22EXT_MSTSLV_STATUS);
+ if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN))
lpa |= ADVERTISED_1000baseT_Half;
- if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN))
+ if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN))
lpa |= ADVERTISED_1000baseT_Full;
}
- reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS);
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_10GBT_CTRL);
+ if (reg & (1 << MDIO_AN_10GBT_CTRL_ADV_10G_LBN))
+ adv |= ADVERTISED_10000baseT_Full;
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_10GBT_STATUS);
if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
lpa |= ADVERTISED_10000baseT_Full;
- return lpa;
-}
-static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
-{
- mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full,
- tenxpress_get_xnp_lpa(efx));
- ecmd->supported |= SUPPORTED_10000baseT_Full;
- ecmd->advertising |= ADVERTISED_10000baseT_Full;
+ mdio_clause45_get_settings_ext(efx, ecmd, adv, lpa);
+
+ if (efx->phy_type != PHY_TYPE_SFX7101)
+ ecmd->supported |= (SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full);
+
+ /* In loopback, the PHY automatically brings up the correct interface,
+ * but doesn't advertise the correct speed. So override it */
+ if (efx->loopback_mode == LOOPBACK_GPHY)
+ ecmd->speed = SPEED_1000;
+ else if (LOOPBACK_MASK(efx) & efx->phy_op->loopbacks)
+ ecmd->speed = SPEED_10000;
}
-static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
- int phy_id = efx->mii.phy_id;
- u32 xnp_adv = 0;
- int reg;
-
- reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
- PMA_PMD_SPEED_ENABLE_REG);
- if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN)))
- xnp_adv |= ADVERTISED_100baseT_Full;
- if (reg & (1 << PMA_PMD_1000T_ADV_LBN))
- xnp_adv |= ADVERTISED_1000baseT_Full;
- if (reg & (1 << PMA_PMD_10000T_ADV_LBN))
- xnp_adv |= ADVERTISED_10000baseT_Full;
+ if (!ecmd->autoneg)
+ return -EINVAL;
- mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv,
- tenxpress_get_xnp_lpa(efx));
-
- ecmd->supported |= (SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Full);
-
- /* Use the vendor defined C22ext register for duplex settings */
- if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) {
- reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
- GPHY_XCONTROL_REG);
- ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ?
- DUPLEX_FULL : DUPLEX_HALF);
- }
+ return mdio_clause45_set_settings(efx, ecmd);
}
-static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising)
{
- int phy_id = efx->mii.phy_id;
- int rc;
-
- rc = mdio_clause45_set_settings(efx, ecmd);
- if (rc)
- return rc;
-
- if (ecmd->speed != SPEED_10000 && !ecmd->autoneg)
- mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
- GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN,
- ecmd->duplex == DUPLEX_FULL);
-
- return rc;
+ mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_AN,
+ MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
+ advertising & ADVERTISED_10000baseT_Full);
}
-static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising)
+static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising)
{
- int phy = efx->mii.phy_id;
- int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD,
- PMA_PMD_SPEED_ENABLE_REG);
- bool enabled;
-
- reg &= ~((1 << 2) | (1 << 3));
- if (EFX_WORKAROUND_13204(efx) &&
- (advertising & ADVERTISED_100baseT_Full))
- reg |= 1 << PMA_PMD_100TX_ADV_LBN;
- if (advertising & ADVERTISED_1000baseT_Full)
- reg |= 1 << PMA_PMD_1000T_ADV_LBN;
- if (advertising & ADVERTISED_10000baseT_Full)
- reg |= 1 << PMA_PMD_10000T_ADV_LBN;
- mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD,
- PMA_PMD_SPEED_ENABLE_REG, reg);
-
- enabled = (advertising &
- (ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full |
- ADVERTISED_10000baseT_Full));
- if (EFX_WORKAROUND_13204(efx))
- enabled |= (advertising & ADVERTISED_100baseT_Full);
- return enabled;
+ int phy_id = efx->mii.phy_id;
+
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
+ C22EXT_MSTSLV_CTRL,
+ C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN,
+ advertising & ADVERTISED_1000baseT_Full);
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_10GBT_CTRL,
+ MDIO_AN_10GBT_CTRL_ADV_10G_LBN,
+ advertising & ADVERTISED_10000baseT_Full);
}
struct efx_phy_operations falcon_sfx7101_phy_ops = {
@@ -881,8 +822,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
.poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini,
.clear_interrupt = efx_port_dummy_op_void,
- .get_settings = sfx7101_get_settings,
- .set_settings = mdio_clause45_set_settings,
+ .get_settings = tenxpress_get_settings,
+ .set_settings = tenxpress_set_settings,
+ .set_npage_adv = sfx7101_set_npage_adv,
.num_tests = ARRAY_SIZE(sfx7101_test_names),
.test_names = sfx7101_test_names,
.run_tests = sfx7101_run_tests,
@@ -897,9 +839,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
.poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini,
.clear_interrupt = efx_port_dummy_op_void,
- .get_settings = sft9001_get_settings,
- .set_settings = sft9001_set_settings,
- .set_xnp_advertise = sft9001_set_xnp_advertise,
+ .get_settings = tenxpress_get_settings,
+ .set_settings = tenxpress_set_settings,
+ .set_npage_adv = sft9001_set_npage_adv,
.num_tests = ARRAY_SIZE(sft9001_test_names),
.test_names = sft9001_test_names,
.run_tests = sft9001_run_tests,
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index 82e03e1d7371..78de68f4a95b 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -18,8 +18,8 @@
#define EFX_WORKAROUND_ALWAYS(efx) 1
#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
-#define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101)
-#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A)
+#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \
+ (efx)->phy_type == PHY_TYPE_SFT9001B)
/* XAUI resets if link not detected */
#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
@@ -29,8 +29,6 @@
#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G
/* TX pkt parser problem with <= 16 byte TXes */
#define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
-/* Low rate CRC errors require XAUI reset */
-#define EFX_WORKAROUND_10750 EFX_WORKAROUND_SFX7101
/* TX_EV_PKT_ERR can be caused by a dangling TX descriptor
* or a PCIe error (bug 11028) */
#define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS
@@ -55,8 +53,8 @@
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
/* Need to send XNP pages for 100BaseT */
-#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001A
-/* Need to keep AN enabled */
-#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A
+#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001
+/* Don't restart AN in near-side loopback */
+#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001
#endif /* EFX_WORKAROUNDS_H */
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 83cc3c5f7946..a9732686134b 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -1782,6 +1782,21 @@ static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
}
+static const struct net_device_ops sis190_netdev_ops = {
+ .ndo_open = sis190_open,
+ .ndo_stop = sis190_close,
+ .ndo_do_ioctl = sis190_ioctl,
+ .ndo_start_xmit = sis190_start_xmit,
+ .ndo_tx_timeout = sis190_tx_timeout,
+ .ndo_set_multicast_list = sis190_set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = sis190_netpoll,
+#endif
+};
+
static int __devinit sis190_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1815,19 +1830,12 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
INIT_WORK(&tp->phy_task, sis190_phy_task);
- dev->open = sis190_open;
- dev->stop = sis190_close;
- dev->do_ioctl = sis190_ioctl;
- dev->tx_timeout = sis190_tx_timeout;
- dev->watchdog_timeo = SIS190_TX_TIMEOUT;
- dev->hard_start_xmit = sis190_start_xmit;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = sis190_netpoll;
-#endif
- dev->set_multicast_list = sis190_set_rx_mode;
+ dev->netdev_ops = &sis190_netdev_ops;
+
SET_ETHTOOL_OPS(dev, &sis190_ethtool_ops);
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) 0xdead;
+ dev->watchdog_timeo = SIS190_TX_TIMEOUT;
spin_lock_init(&tp->lock);
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 4acd41a093ad..be4465bc0a69 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -389,6 +389,7 @@ static const struct net_device_ops sis900_netdev_ops = {
.ndo_set_multicast_list = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = mii_ioctl,
.ndo_tx_timeout = sis900_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -508,10 +509,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
else
ret = sis900_get_mac_addr(pci_dev, net_dev);
- if (ret == 0) {
- printk(KERN_WARNING "%s: Cannot read MAC address.\n", dev_name);
- ret = -ENODEV;
- goto err_unmap_rx;
+ if (!ret || !is_valid_ether_addr(net_dev->dev_addr)) {
+ random_ether_addr(net_dev->dev_addr);
+ printk(KERN_WARNING "%s: Unreadable or invalid MAC address,"
+ "using random generated one\n", dev_name);
}
/* 630ET : set the mii access mode as software-mode */
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 607efeaf0bc5..9a00e5566af7 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -1003,9 +1003,9 @@ static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break;
case SKFP_CLR_STATS: /* Zero out the driver statistics */
if (!capable(CAP_NET_ADMIN)) {
- memset(&lp->MacStat, 0, sizeof(lp->MacStat));
- } else {
status = -EPERM;
+ } else {
+ memset(&lp->MacStat, 0, sizeof(lp->MacStat));
}
break;
default:
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3668e81e474d..994703cc0db3 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1403,9 +1403,6 @@ static int sky2_up(struct net_device *dev)
}
- if (netif_msg_ifup(sky2))
- printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
-
netif_carrier_off(dev);
/* must be power of 2 */
@@ -1484,6 +1481,9 @@ static int sky2_up(struct net_device *dev)
sky2_write32(hw, B0_IMSK, imask);
sky2_set_multicast(dev);
+
+ if (netif_msg_ifup(sky2))
+ printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
return 0;
err_out:
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 8e1c0baf6958..5c61d5fad908 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -603,7 +603,6 @@ static int sl_init(struct net_device *dev)
dev->mtu = sl->mtu;
dev->type = ARPHRD_SLIP + sl->mode;
#ifdef SL_CHECK_TRANSMIT
- dev->tx_timeout = sl_tx_timeout;
dev->watchdog_timeo = 20*HZ;
#endif
return 0;
@@ -617,19 +616,26 @@ static void sl_uninit(struct net_device *dev)
sl_free_bufs(sl);
}
+static const struct net_device_ops sl_netdev_ops = {
+ .ndo_init = sl_init,
+ .ndo_uninit = sl_uninit,
+ .ndo_open = sl_open,
+ .ndo_stop = sl_close,
+ .ndo_start_xmit = sl_xmit,
+ .ndo_get_stats = sl_get_stats,
+ .ndo_change_mtu = sl_change_mtu,
+ .ndo_tx_timeout = sl_tx_timeout,
+#ifdef CONFIG_SLIP_SMART
+ .ndo_do_ioctl = sl_ioctl,
+#endif
+};
+
+
static void sl_setup(struct net_device *dev)
{
- dev->init = sl_init;
- dev->uninit = sl_uninit;
- dev->open = sl_open;
+ dev->netdev_ops = &sl_netdev_ops;
dev->destructor = free_netdev;
- dev->stop = sl_close;
- dev->get_stats = sl_get_stats;
- dev->change_mtu = sl_change_mtu;
- dev->hard_start_xmit = sl_xmit;
-#ifdef CONFIG_SLIP_SMART
- dev->do_ioctl = sl_ioctl;
-#endif
+
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->tx_queue_len = 10;
diff --git a/drivers/net/slip.h b/drivers/net/slip.h
index 853e0f6ec710..9ea5c11287d2 100644
--- a/drivers/net/slip.h
+++ b/drivers/net/slip.h
@@ -75,7 +75,7 @@ struct slip {
unsigned long tx_errors; /* Planned stuff */
unsigned long rx_dropped; /* No memory for skb */
unsigned long tx_dropped; /* When MTU change */
- unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */
+ unsigned long rx_over_errors; /* Frame bigger than SLIP buf. */
#ifdef SL_INCLUDE_CSLIP
unsigned long tx_compressed;
unsigned long rx_compressed;
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 404b80e5ba11..8d36d40649ef 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -192,6 +192,7 @@ static const struct net_device_ops ultramca_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index b3866089a206..2033fee3143a 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -196,6 +196,7 @@ static const struct net_device_ops ultra_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index bf3aa2a1effe..223cde0d43be 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -220,9 +220,9 @@ static void smc911x_reset(struct net_device *dev)
/* make sure EEPROM has finished loading before setting GPIO_CFG */
timeout=1000;
- while ( timeout-- && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_)) {
+ while (--timeout && (SMC_GET_E2P_CMD(lp) & E2P_CMD_EPC_BUSY_))
udelay(10);
- }
+
if (timeout == 0){
PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name);
return;
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index dc3f1108884d..783c1a7b869e 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -144,6 +144,7 @@ static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
}
BUG();
+ return 0;
}
static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
@@ -952,7 +953,7 @@ smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
do {
udelay(1);
val = smsc911x_reg_read(pdata, RX_DP_CTRL);
- } while (timeout-- && (val & RX_DP_CTRL_RX_FFWD_));
+ } while (--timeout && (val & RX_DP_CTRL_RX_FFWD_));
if (unlikely(timeout == 0))
SMSC_WARNING(HW, "Timed out waiting for "
@@ -1740,6 +1741,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
.ndo_set_multicast_list = smsc911x_set_multicast_list,
.ndo_do_ioctl = smsc911x_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = smsc911x_poll_controller,
#endif
@@ -1967,7 +1969,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED,
- SMSC_CHIPNAME, dev);
+ dev->name, dev);
if (retval) {
SMSC_WARNING(PROBE,
"Unable to claim requested irq: %d", dev->irq);
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
index 27e017d96966..a1e4b3895b33 100644
--- a/drivers/net/smsc9420.c
+++ b/drivers/net/smsc9420.c
@@ -498,7 +498,7 @@ static void smsc9420_check_mac_address(struct net_device *dev)
static void smsc9420_stop_tx(struct smsc9420_pdata *pd)
{
u32 dmac_control, mac_cr, dma_intr_ena;
- int timeOut = 1000;
+ int timeout = 1000;
/* disable TX DMAC */
dmac_control = smsc9420_reg_read(pd, DMAC_CONTROL);
@@ -506,13 +506,13 @@ static void smsc9420_stop_tx(struct smsc9420_pdata *pd)
smsc9420_reg_write(pd, DMAC_CONTROL, dmac_control);
/* Wait max 10ms for transmit process to stop */
- while (timeOut--) {
+ while (--timeout) {
if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_TS_)
break;
udelay(10);
}
- if (!timeOut)
+ if (!timeout)
smsc_warn(IFDOWN, "TX DMAC failed to stop");
/* ACK Tx DMAC stop bit */
@@ -596,7 +596,7 @@ static void smsc9420_free_rx_ring(struct smsc9420_pdata *pd)
static void smsc9420_stop_rx(struct smsc9420_pdata *pd)
{
- int timeOut = 1000;
+ int timeout = 1000;
u32 mac_cr, dmac_control, dma_intr_ena;
/* mask RX DMAC interrupts */
@@ -617,13 +617,13 @@ static void smsc9420_stop_rx(struct smsc9420_pdata *pd)
smsc9420_pci_flush_write(pd);
/* wait up to 10ms for receive to stop */
- while (timeOut--) {
+ while (--timeout) {
if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_RS_)
break;
udelay(10);
}
- if (!timeOut)
+ if (!timeout)
smsc_warn(IFDOWN, "RX DMAC did not stop! timeout.");
/* ACK the Rx DMAC stop bit */
@@ -1378,6 +1378,7 @@ static int smsc9420_open(struct net_device *dev)
/* test the IRQ connection to the ISR */
smsc_dbg(IFUP, "Testing ISR using IRQ %d", dev->irq);
+ pd->software_irq_signal = false;
spin_lock_irqsave(&pd->int_lock, flags);
/* configure interrupt deassertion timer and enable interrupts */
@@ -1393,8 +1394,6 @@ static int smsc9420_open(struct net_device *dev)
smsc9420_pci_flush_write(pd);
timeout = 1000;
- pd->software_irq_signal = false;
- smp_wmb();
while (timeout--) {
if (pd->software_irq_signal)
break;
@@ -1551,6 +1550,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
.ndo_set_multicast_list = smsc9420_set_multicast_list,
.ndo_do_ioctl = smsc9420_do_ioctl,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = smsc9420_poll_controller,
#endif /* CONFIG_NET_POLL_CONTROLLER */
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index f54ac2389da2..da3a76b18eff 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -42,11 +42,11 @@
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <linux/mm.h>
+#include <linux/firmware.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/uaccess.h>
#include <asm/io.h>
-#include "starfire_firmware.h"
/*
* The current frame processor firmware fails to checksum a fragment
* of length 1. If and when this is fixed, the #define below can be removed.
@@ -173,6 +173,10 @@ static int full_duplex[MAX_UNITS] = {0, };
#define skb_first_frag_len(skb) skb_headlen(skb)
#define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
+/* Firmware names */
+#define FIRMWARE_RX "adaptec/starfire_rx.bin"
+#define FIRMWARE_TX "adaptec/starfire_tx.bin"
+
/* These identify the driver base version and may not be removed. */
static char version[] =
KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n"
@@ -182,6 +186,8 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+MODULE_FIRMWARE(FIRMWARE_RX);
+MODULE_FIRMWARE(FIRMWARE_TX);
module_param(max_interrupt_work, int, 0);
module_param(mtu, int, 0);
@@ -642,6 +648,24 @@ static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
#endif /* VLAN_SUPPORT */
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = start_tx,
+ .ndo_tx_timeout = tx_timeout,
+ .ndo_get_stats = get_stats,
+ .ndo_set_multicast_list = &set_rx_mode,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef VLAN_SUPPORT
+ .ndo_vlan_rx_register = netdev_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = netdev_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = netdev_vlan_rx_kill_vid,
+#endif
+};
+
static int __devinit starfire_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -704,11 +728,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
if (enable_hw_cksum)
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
#endif /* ZEROCOPY */
+
#ifdef VLAN_SUPPORT
dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
- dev->vlan_rx_register = netdev_vlan_rx_register;
- dev->vlan_rx_add_vid = netdev_vlan_rx_add_vid;
- dev->vlan_rx_kill_vid = netdev_vlan_rx_kill_vid;
#endif /* VLAN_RX_KILL_VID */
#ifdef ADDR_64BITS
dev->features |= NETIF_F_HIGHDMA;
@@ -804,18 +826,12 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
}
}
- /* The chip-specific entries in the device structure. */
- dev->open = &netdev_open;
- dev->hard_start_xmit = &start_tx;
- dev->tx_timeout = tx_timeout;
+ dev->netdev_ops = &netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
- netif_napi_add(dev, &np->napi, netdev_poll, max_interrupt_work);
- dev->stop = &netdev_close;
- dev->get_stats = &get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &netdev_ioctl;
SET_ETHTOOL_OPS(dev, &ethtool_ops);
+ netif_napi_add(dev, &np->napi, netdev_poll, max_interrupt_work);
+
if (mtu)
dev->mtu = mtu;
@@ -902,9 +918,12 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
static int netdev_open(struct net_device *dev)
{
+ const struct firmware *fw_rx, *fw_tx;
+ const __be32 *fw_rx_data, *fw_tx_data;
struct netdev_private *np = netdev_priv(dev);
void __iomem *ioaddr = np->base;
int i, retval;
+ size_t tx_size, rx_size;
size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
/* Do we ever need to reset the chip??? */
@@ -1040,11 +1059,40 @@ static int netdev_open(struct net_device *dev)
writel(ETH_P_8021Q, ioaddr + VlanType);
#endif /* VLAN_SUPPORT */
+ retval = request_firmware(&fw_rx, FIRMWARE_RX, &np->pci_dev->dev);
+ if (retval) {
+ printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+ FIRMWARE_RX);
+ return retval;
+ }
+ if (fw_rx->size % 4) {
+ printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+ fw_rx->size, FIRMWARE_RX);
+ retval = -EINVAL;
+ goto out_rx;
+ }
+ retval = request_firmware(&fw_tx, FIRMWARE_TX, &np->pci_dev->dev);
+ if (retval) {
+ printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+ FIRMWARE_TX);
+ goto out_rx;
+ }
+ if (fw_tx->size % 4) {
+ printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+ fw_tx->size, FIRMWARE_TX);
+ retval = -EINVAL;
+ goto out_tx;
+ }
+ fw_rx_data = (const __be32 *)&fw_rx->data[0];
+ fw_tx_data = (const __be32 *)&fw_tx->data[0];
+ rx_size = fw_rx->size / 4;
+ tx_size = fw_tx->size / 4;
+
/* Load Rx/Tx firmware into the frame processors */
- for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
- writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
- for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
- writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
+ for (i = 0; i < rx_size; i++)
+ writel(be32_to_cpup(&fw_rx_data[i]), ioaddr + RxGfpMem + i * 4);
+ for (i = 0; i < tx_size; i++)
+ writel(be32_to_cpup(&fw_tx_data[i]), ioaddr + TxGfpMem + i * 4);
if (enable_hw_cksum)
/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
@@ -1056,7 +1104,11 @@ static int netdev_open(struct net_device *dev)
printk(KERN_DEBUG "%s: Done netdev_open().\n",
dev->name);
- return 0;
+out_tx:
+ release_firmware(fw_tx);
+out_rx:
+ release_firmware(fw_rx);
+ return retval;
}
diff --git a/drivers/net/starfire_firmware.h b/drivers/net/starfire_firmware.h
deleted file mode 100644
index 0a668528955d..000000000000
--- a/drivers/net/starfire_firmware.h
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright 2003 Adaptec, Inc.
- *
- * Please read the following license before using the Adaptec Software
- * ("Program"). If you do not agree to the license terms, do not use the
- * Program:
- *
- * You agree to be bound by version 2 of the General Public License ("GPL")
- * dated June 1991, which can be found at http://www.fsf.org/licenses/gpl.html.
- * If the link is broken, write to Free Software Foundation, 59 Temple Place,
- * Boston, Massachusetts 02111-1307.
- *
- * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND
- * THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE
- * (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR
- * OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR
- * DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM.
- *
- */
-
-static const u32 firmware_rx[] = {
- 0x010003dc, 0x00000000,
- 0x04000421, 0x00000086,
- 0x80000015, 0x0000180e,
- 0x81000015, 0x00006664,
- 0x1a0040ab, 0x00000b06,
- 0x14200011, 0x00000000,
- 0x14204022, 0x0000aaaa,
- 0x14204022, 0x00000300,
- 0x14204022, 0x00000000,
- 0x1a0040ab, 0x00000b14,
- 0x14200011, 0x00000000,
- 0x83000015, 0x00000002,
- 0x04000021, 0x00000000,
- 0x00000010, 0x00000000,
- 0x04000421, 0x00000087,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00008015, 0x00000000,
- 0x0000003e, 0x00000000,
- 0x00000010, 0x00000000,
- 0x82000015, 0x00004000,
- 0x009e8050, 0x00000000,
- 0x03008015, 0x00000000,
- 0x86008015, 0x00000000,
- 0x82000015, 0x00008000,
- 0x0100001c, 0x00000000,
- 0x000050a0, 0x0000010c,
- 0x4e20d011, 0x00006008,
- 0x1420d012, 0x00004008,
- 0x0000f090, 0x00007000,
- 0x0000c8b0, 0x00003000,
- 0x00004040, 0x00000000,
- 0x00108015, 0x00000000,
- 0x00a2c150, 0x00004000,
- 0x00a400b0, 0x00000014,
- 0x00000020, 0x00000000,
- 0x2500400d, 0x00002525,
- 0x00047220, 0x00003100,
- 0x00934070, 0x00000000,
- 0x00000020, 0x00000000,
- 0x00924460, 0x00000184,
- 0x2b20c011, 0x00000000,
- 0x0000c420, 0x00000540,
- 0x36014018, 0x0000422d,
- 0x14200011, 0x00000000,
- 0x00924460, 0x00000183,
- 0x3200001f, 0x00000034,
- 0x02ac0015, 0x00000002,
- 0x00a60110, 0x00000008,
- 0x42200011, 0x00000000,
- 0x00924060, 0x00000103,
- 0x0000001e, 0x00000000,
- 0x00000020, 0x00000100,
- 0x0000001e, 0x00000000,
- 0x00924460, 0x00000086,
- 0x00004080, 0x00000000,
- 0x0092c070, 0x00000000,
- 0x00924060, 0x00000100,
- 0x0000c890, 0x00005000,
- 0x00a6c110, 0x00000000,
- 0x00b0c090, 0x00000012,
- 0x021c0015, 0x00000000,
- 0x3200001f, 0x00000034,
- 0x00924460, 0x00000510,
- 0x44210011, 0x00000000,
- 0x42000011, 0x00000000,
- 0x83000015, 0x00000040,
- 0x00924460, 0x00000508,
- 0x45014018, 0x00004545,
- 0x00808050, 0x00000000,
- 0x62208012, 0x00000000,
- 0x82000015, 0x00000800,
- 0x15200011, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x80000015, 0x0000eea4,
- 0x81000015, 0x0000005f,
- 0x00000060, 0x00000000,
- 0x00004120, 0x00000000,
- 0x00004a00, 0x00004000,
- 0x00924460, 0x00000190,
- 0x5601401a, 0x00005956,
- 0x14000011, 0x00000000,
- 0x00934050, 0x00000018,
- 0x00930050, 0x00000018,
- 0x3601403a, 0x0000002d,
- 0x000643a9, 0x00000000,
- 0x0000c420, 0x00000140,
- 0x5601401a, 0x00005956,
- 0x14000011, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x000642a9, 0x00000000,
- 0x00024420, 0x00000183,
- 0x5601401a, 0x00005956,
- 0x82000015, 0x00002000,
- 0x15200011, 0x00000000,
- 0x82000015, 0x00000010,
- 0x15200011, 0x00000000,
- 0x82000015, 0x00000010,
- 0x15200011, 0x00000000,
-}; /* 104 Rx instructions */
-#define FIRMWARE_RX_SIZE 104
-
-static const u32 firmware_tx[] = {
- 0x010003dc, 0x00000000,
- 0x04000421, 0x00000086,
- 0x80000015, 0x0000180e,
- 0x81000015, 0x00006664,
- 0x1a0040ab, 0x00000b06,
- 0x14200011, 0x00000000,
- 0x14204022, 0x0000aaaa,
- 0x14204022, 0x00000300,
- 0x14204022, 0x00000000,
- 0x1a0040ab, 0x00000b14,
- 0x14200011, 0x00000000,
- 0x83000015, 0x00000002,
- 0x04000021, 0x00000000,
- 0x00000010, 0x00000000,
- 0x04000421, 0x00000087,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00008015, 0x00000000,
- 0x0000003e, 0x00000000,
- 0x00000010, 0x00000000,
- 0x82000015, 0x00004000,
- 0x009e8050, 0x00000000,
- 0x03008015, 0x00000000,
- 0x86008015, 0x00000000,
- 0x82000015, 0x00008000,
- 0x0100001c, 0x00000000,
- 0x000050a0, 0x0000010c,
- 0x4e20d011, 0x00006008,
- 0x1420d012, 0x00004008,
- 0x0000f090, 0x00007000,
- 0x0000c8b0, 0x00003000,
- 0x00004040, 0x00000000,
- 0x00108015, 0x00000000,
- 0x00a2c150, 0x00004000,
- 0x00a400b0, 0x00000014,
- 0x00000020, 0x00000000,
- 0x2500400d, 0x00002525,
- 0x00047220, 0x00003100,
- 0x00934070, 0x00000000,
- 0x00000020, 0x00000000,
- 0x00924460, 0x00000184,
- 0x2b20c011, 0x00000000,
- 0x0000c420, 0x00000540,
- 0x36014018, 0x0000422d,
- 0x14200011, 0x00000000,
- 0x00924460, 0x00000183,
- 0x3200001f, 0x00000034,
- 0x02ac0015, 0x00000002,
- 0x00a60110, 0x00000008,
- 0x42200011, 0x00000000,
- 0x00924060, 0x00000103,
- 0x0000001e, 0x00000000,
- 0x00000020, 0x00000100,
- 0x0000001e, 0x00000000,
- 0x00924460, 0x00000086,
- 0x00004080, 0x00000000,
- 0x0092c070, 0x00000000,
- 0x00924060, 0x00000100,
- 0x0000c890, 0x00005000,
- 0x00a6c110, 0x00000000,
- 0x00b0c090, 0x00000012,
- 0x021c0015, 0x00000000,
- 0x3200001f, 0x00000034,
- 0x00924460, 0x00000510,
- 0x44210011, 0x00000000,
- 0x42000011, 0x00000000,
- 0x83000015, 0x00000040,
- 0x00924460, 0x00000508,
- 0x45014018, 0x00004545,
- 0x00808050, 0x00000000,
- 0x62208012, 0x00000000,
- 0x82000015, 0x00000800,
- 0x15200011, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x80000015, 0x0000eea4,
- 0x81000015, 0x0000005f,
- 0x00000060, 0x00000000,
- 0x00004120, 0x00000000,
- 0x00004a00, 0x00004000,
- 0x00924460, 0x00000190,
- 0x5601401a, 0x00005956,
- 0x14000011, 0x00000000,
- 0x00934050, 0x00000018,
- 0x00930050, 0x00000018,
- 0x3601403a, 0x0000002d,
- 0x000643a9, 0x00000000,
- 0x0000c420, 0x00000140,
- 0x5601401a, 0x00005956,
- 0x14000011, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x000642a9, 0x00000000,
- 0x00024420, 0x00000183,
- 0x5601401a, 0x00005956,
- 0x82000015, 0x00002000,
- 0x15200011, 0x00000000,
- 0x82000015, 0x00000010,
- 0x15200011, 0x00000000,
- 0x82000015, 0x00000010,
- 0x15200011, 0x00000000,
-}; /* 104 Tx instructions */
-#define FIRMWARE_TX_SIZE 104
-#if 0
-static const u32 firmware_wol[] = {
- 0x010003dc, 0x00000000,
- 0x19000421, 0x00000087,
- 0x80000015, 0x00001a1a,
- 0x81000015, 0x00001a1a,
- 0x1a0040ab, 0x00000b06,
- 0x15200011, 0x00000000,
- 0x15204022, 0x0000aaaa,
- 0x15204022, 0x00000300,
- 0x15204022, 0x00000000,
- 0x1a0040ab, 0x00000b15,
- 0x15200011, 0x00000000,
- 0x83000015, 0x00000002,
- 0x04000021, 0x00000000,
- 0x00000010, 0x00000000,
- 0x04000421, 0x00000087,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00008015, 0x00000000,
- 0x0000003e, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x82000015, 0x00004000,
- 0x82000015, 0x00008000,
- 0x0000000c, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00004080, 0x00000100,
- 0x1f20c011, 0x00001122,
- 0x2720f011, 0x00003011,
- 0x19200071, 0x00000000,
- 0x1a200051, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x1d2040a4, 0x00003344,
- 0x1d2040a2, 0x00005566,
- 0x000040a0, 0x00000100,
- 0x00108050, 0x00000001,
- 0x1a208012, 0x00000006,
- 0x82000015, 0x00008080,
- 0x010003dc, 0x00000000,
- 0x1d2040a4, 0x00002233,
- 0x1d2040a4, 0x00004455,
- 0x2d208011, 0x00000005,
- 0x1d2040a4, 0x00006611,
- 0x00108050, 0x00000001,
- 0x27200011, 0x00000000,
- 0x1d2050a4, 0x00006600,
- 0x82000015, 0x00008080,
- 0x010003dc, 0x00000000,
- 0x00000050, 0x00000000,
- 0x1b200031, 0x00000000,
- 0x0000001e, 0x00000000,
- 0x0000001e, 0x00000000,
- 0x0000001e, 0x00000000,
- 0x0000001e, 0x00000000,
- 0x00924460, 0x00000086,
- 0x00004080, 0x00000000,
- 0x0092c070, 0x00000000,
- 0x00924060, 0x00000100,
- 0x0000c890, 0x00005000,
- 0x00a6c110, 0x00000000,
- 0x00b0c090, 0x00000012,
- 0x021c0015, 0x00000000,
- 0x3200001f, 0x00000034,
- 0x00924460, 0x00000510,
- 0x44210011, 0x00000000,
- 0x42000011, 0x00000000,
- 0x83000015, 0x00000040,
- 0x00924460, 0x00000508,
- 0x476a0012, 0x00000100,
- 0x83000015, 0x00000008,
- 0x16200011, 0x00000000,
- 0x001e8050, 0x00000000,
- 0x001e8050, 0x00000000,
- 0x00808050, 0x00000000,
- 0x03008015, 0x00000000,
- 0x62208012, 0x00000000,
- 0x82000015, 0x00000800,
- 0x16200011, 0x00000000,
- 0x80000015, 0x0000eea4,
- 0x81000015, 0x0000005f,
- 0x00000020, 0x00000000,
- 0x00004120, 0x00000000,
- 0x00004a00, 0x00004000,
- 0x00924460, 0x00000190,
- 0x5c01401a, 0x0000595c,
- 0x15000011, 0x00000000,
- 0x00934050, 0x00000018,
- 0x00930050, 0x00000018,
- 0x3601403a, 0x0000002d,
- 0x00064029, 0x00000000,
- 0x0000c420, 0x00000140,
- 0x5c01401a, 0x0000595c,
- 0x15000011, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00000010, 0x00000000,
- 0x00064029, 0x00000000,
- 0x00024420, 0x00000183,
- 0x5c01401a, 0x0000595c,
- 0x82000015, 0x00002000,
- 0x16200011, 0x00000000,
- 0x82000015, 0x00000010,
- 0x16200011, 0x00000000,
- 0x82000015, 0x00000010,
- 0x16200011, 0x00000000,
-}; /* 104 WoL instructions */
-#define FIRMWARE_WOL_SIZE 104
-#endif
diff --git a/drivers/net/starfire_firmware.pl b/drivers/net/starfire_firmware.pl
deleted file mode 100644
index 0c82b80e1074..000000000000
--- a/drivers/net/starfire_firmware.pl
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/perl
-
-# This script can be used to generate a new starfire_firmware.h
-# from GFP_RX.DAT and GFP_TX.DAT, files included with the DDK
-# and also with the Novell drivers.
-
-open FW, "GFP_RX.DAT" || die;
-open FWH, ">starfire_firmware.h" || die;
-
-printf(FWH "static u32 firmware_rx[] = {\n");
-$counter = 0;
-while ($foo = <FW>) {
- chomp;
- printf(FWH " 0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
- $counter++;
-}
-
-close FW;
-open FW, "GFP_TX.DAT" || die;
-
-printf(FWH "};\t/* %d Rx instructions */\n#define FIRMWARE_RX_SIZE %d\n\nstatic u32 firmware_tx[] = {\n", $counter, $counter);
-$counter = 0;
-while ($foo = <FW>) {
- chomp;
- printf(FWH " 0x%s, 0x0000%s,\n", substr($foo, 4, 8), substr($foo, 0, 4));
- $counter++;
-}
-
-close FW;
-printf(FWH "};\t/* %d Tx instructions */\n#define FIRMWARE_TX_SIZE %d\n", $counter, $counter);
-close(FWH);
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 698893b92003..feaf0e0577d7 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -449,6 +449,19 @@ static void sundance_reset(struct net_device *dev, unsigned long reset_cmd)
}
}
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = start_tx,
+ .ndo_get_stats = get_stats,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_tx_timeout = tx_timeout,
+ .ndo_change_mtu = change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit sundance_probe1 (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -530,16 +543,10 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
np->mii_if.reg_num_mask = 0x1f;
/* The chip-specific entries in the device structure. */
- dev->open = &netdev_open;
- dev->hard_start_xmit = &start_tx;
- dev->stop = &netdev_close;
- dev->get_stats = &get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &netdev_ioctl;
+ dev->netdev_ops = &netdev_ops;
SET_ETHTOOL_OPS(dev, &ethtool_ops);
- dev->tx_timeout = &tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- dev->change_mtu = &change_mtu;
+
pci_set_drvdata(pdev, dev);
i = register_netdev(dev);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 8a7460412482..b17efa9cc530 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -148,7 +148,7 @@ static u16 __phy_read(struct gem *gp, int phy_addr, int reg)
cmd |= (MIF_FRAME_TAMSB);
writel(cmd, gp->regs + MIF_FRAME);
- while (limit--) {
+ while (--limit) {
cmd = readl(gp->regs + MIF_FRAME);
if (cmd & MIF_FRAME_TALSB)
break;
@@ -2989,6 +2989,19 @@ static void gem_remove_one(struct pci_dev *pdev)
}
}
+static const struct net_device_ops gem_netdev_ops = {
+ .ndo_open = gem_open,
+ .ndo_stop = gem_close,
+ .ndo_start_xmit = gem_start_xmit,
+ .ndo_get_stats = gem_get_stats,
+ .ndo_set_multicast_list = gem_set_multicast,
+ .ndo_do_ioctl = gem_ioctl,
+ .ndo_tx_timeout = gem_tx_timeout,
+ .ndo_change_mtu = gem_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit gem_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -3142,17 +3155,10 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
if (gem_get_device_address(gp))
goto err_out_free_consistent;
- dev->open = gem_open;
- dev->stop = gem_close;
- dev->hard_start_xmit = gem_start_xmit;
- dev->get_stats = gem_get_stats;
- dev->set_multicast_list = gem_set_multicast;
- dev->do_ioctl = gem_ioctl;
+ dev->netdev_ops = &gem_netdev_ops;
netif_napi_add(dev, &gp->napi, gem_poll, 64);
dev->ethtool_ops = &gem_ethtool_ops;
- dev->tx_timeout = gem_tx_timeout;
dev->watchdog_timeo = 5 * HZ;
- dev->change_mtu = gem_change_mtu;
dev->irq = pdev->irq;
dev->dma = 0;
dev->set_mac_address = gem_set_mac_address;
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index 61843fd57525..78f8cee5fd74 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -79,7 +79,7 @@ static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
udelay(100);
- while (limit--) {
+ while (--limit) {
val = __phy_read(phy, phy_id, MII_BMCR);
if ((val & BMCR_RESET) == 0)
break;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index b22d3355fb45..7a72a3112f0a 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2607,6 +2607,18 @@ static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
}
#endif /* CONFIG_PCI */
+static const struct net_device_ops hme_netdev_ops = {
+ .ndo_open = happy_meal_open,
+ .ndo_stop = happy_meal_close,
+ .ndo_start_xmit = happy_meal_start_xmit,
+ .ndo_tx_timeout = happy_meal_tx_timeout,
+ .ndo_get_stats = happy_meal_get_stats,
+ .ndo_set_multicast_list = happy_meal_set_multicast,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
#ifdef CONFIG_SBUS
static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
{
@@ -2750,12 +2762,7 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
init_timer(&hp->happy_timer);
hp->dev = dev;
- dev->open = &happy_meal_open;
- dev->stop = &happy_meal_close;
- dev->hard_start_xmit = &happy_meal_start_xmit;
- dev->get_stats = &happy_meal_get_stats;
- dev->set_multicast_list = &happy_meal_set_multicast;
- dev->tx_timeout = &happy_meal_tx_timeout;
+ dev->netdev_ops = &hme_netdev_ops;
dev->watchdog_timeo = 5*HZ;
dev->ethtool_ops = &hme_ethtool_ops;
@@ -3076,12 +3083,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
init_timer(&hp->happy_timer);
hp->dev = dev;
- dev->open = &happy_meal_open;
- dev->stop = &happy_meal_close;
- dev->hard_start_xmit = &happy_meal_start_xmit;
- dev->get_stats = &happy_meal_get_stats;
- dev->set_multicast_list = &happy_meal_set_multicast;
- dev->tx_timeout = &happy_meal_tx_timeout;
+ dev->netdev_ops = &hme_netdev_ops;
dev->watchdog_timeo = 5*HZ;
dev->ethtool_ops = &hme_ethtool_ops;
dev->irq = pdev->irq;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 6e8f377355fe..fe0c3f244562 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -227,7 +227,7 @@ static int qe_init(struct sunqe *qep, int from_irq)
if (!(sbus_readb(mregs + MREGS_PHYCONFIG) & MREGS_PHYCONFIG_LTESTDIS)) {
int tries = 50;
- while (tries--) {
+ while (--tries) {
u8 tmp;
mdelay(5);
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index 233f1cda36e5..611230fef2b6 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -336,7 +336,7 @@ static int vnet_walk_rx_one(struct vnet_port *port,
if (IS_ERR(desc))
return PTR_ERR(desc);
- viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%lx:%lx]\n",
+ viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%llx:%llx]\n",
desc->hdr.state, desc->hdr.ack,
desc->size, desc->ncookies,
desc->cookies[0].cookie_addr,
@@ -394,14 +394,14 @@ static int vnet_rx(struct vnet_port *port, void *msgbuf)
struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_RX_RING];
struct vio_driver_state *vio = &port->vio;
- viodbg(DATA, "vnet_rx stype_env[%04x] seq[%016lx] rcv_nxt[%016lx]\n",
+ viodbg(DATA, "vnet_rx stype_env[%04x] seq[%016llx] rcv_nxt[%016llx]\n",
pkt->tag.stype_env, pkt->seq, dr->rcv_nxt);
if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
return 0;
if (unlikely(pkt->seq != dr->rcv_nxt)) {
- printk(KERN_ERR PFX "RX out of sequence seq[0x%lx] "
- "rcv_nxt[0x%lx]\n", pkt->seq, dr->rcv_nxt);
+ printk(KERN_ERR PFX "RX out of sequence seq[0x%llx] "
+ "rcv_nxt[0x%llx]\n", pkt->seq, dr->rcv_nxt);
return 0;
}
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index a10a83a11d9f..a7a4dc4d6313 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -1004,7 +1004,7 @@ static inline void bdx_rxdb_free_elem(struct rxdb *db, int n)
* skb for rx. It assumes that Rx is desabled in HW
* funcs are grouped for better cache usage
*
- * RxD fifo is smaller then RxF fifo by design. Upon high load, RxD will be
+ * RxD fifo is smaller than RxF fifo by design. Upon high load, RxD will be
* filled and packets will be dropped by nic without getting into host or
* cousing interrupt. Anyway, in that condition, host has no chance to proccess
* all packets, but dropping in nic is cheaper, since it takes 0 cpu cycles
@@ -1826,7 +1826,7 @@ static void bdx_tx_free(struct bdx_priv *priv)
*
* Pushes desc to TxD fifo and overlaps it if needed.
* NOTE: this func does not check for available space. this is responsibility
- * of the caller. Neither does it check that data size is smaller then
+ * of the caller. Neither does it check that data size is smaller than
* fifo size.
*/
static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 04ae1e86aeaa..8b3f84685387 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -40,6 +40,7 @@
#include <linux/workqueue.h>
#include <linux/prefetch.h>
#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
#include <net/checksum.h>
#include <net/ip.h>
@@ -137,6 +138,10 @@
#define TG3_NUM_TEST 6
+#define FIRMWARE_TG3 "tigon/tg3.bin"
+#define FIRMWARE_TG3TSO "tigon/tg3_tso.bin"
+#define FIRMWARE_TG3TSO5 "tigon/tg3_tso5.bin"
+
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -144,6 +149,10 @@ MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox
MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FIRMWARE_TG3);
+MODULE_FIRMWARE(FIRMWARE_TG3TSO);
+MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
+
static int tg3_debug = -1; /* -1 == use TG3_DEF_MSG_ENABLE as value */
module_param(tg3_debug, int, 0);
@@ -6205,130 +6214,6 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent)
return 0;
}
-#define TG3_FW_RELEASE_MAJOR 0x0
-#define TG3_FW_RELASE_MINOR 0x0
-#define TG3_FW_RELEASE_FIX 0x0
-#define TG3_FW_START_ADDR 0x08000000
-#define TG3_FW_TEXT_ADDR 0x08000000
-#define TG3_FW_TEXT_LEN 0x9c0
-#define TG3_FW_RODATA_ADDR 0x080009c0
-#define TG3_FW_RODATA_LEN 0x60
-#define TG3_FW_DATA_ADDR 0x08000a40
-#define TG3_FW_DATA_LEN 0x20
-#define TG3_FW_SBSS_ADDR 0x08000a60
-#define TG3_FW_SBSS_LEN 0xc
-#define TG3_FW_BSS_ADDR 0x08000a70
-#define TG3_FW_BSS_LEN 0x10
-
-static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = {
- 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800,
- 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000,
- 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034,
- 0x0e00021c, 0x00000000, 0x0000000d, 0x00000000, 0x00000000, 0x00000000,
- 0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xaf80680c, 0x0e00004c, 0x241b2105,
- 0x97850000, 0x97870002, 0x9782002c, 0x9783002e, 0x3c040800, 0x248409c0,
- 0xafa00014, 0x00021400, 0x00621825, 0x00052c00, 0xafa30010, 0x8f860010,
- 0x00e52825, 0x0e000060, 0x24070102, 0x3c02ac00, 0x34420100, 0x3c03ac01,
- 0x34630100, 0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, 0xaf82049c,
- 0x24020001, 0xaf825ce0, 0x0e00003f, 0xaf825d00, 0x0e000140, 0x00000000,
- 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, 0x8f835400,
- 0x34630400, 0xaf835400, 0xaf825404, 0x3c020800, 0x24420034, 0xaf82541c,
- 0x03e00008, 0xaf805400, 0x00000000, 0x00000000, 0x3c020800, 0x34423000,
- 0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac220a64,
- 0x24020040, 0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, 0xac600000,
- 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
- 0x00804821, 0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, 0x8c840a68,
- 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac230a60, 0x14400003,
- 0x00004021, 0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, 0x3c030800,
- 0x8c630a64, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
- 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c420a60,
- 0x3c030800, 0x8c630a64, 0x8f84680c, 0x00021140, 0x00431021, 0xac440008,
- 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0x02000008, 0x00000000, 0x0a0001e3, 0x3c0a0001, 0x0a0001e3, 0x3c0a0002,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
- 0x0a0001e3, 0x3c0a0007, 0x0a0001e3, 0x3c0a0008, 0x0a0001e3, 0x3c0a0009,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000b,
- 0x0a0001e3, 0x3c0a000c, 0x0a0001e3, 0x3c0a000d, 0x0a0001e3, 0x00000000,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a000e, 0x0a0001e3, 0x00000000,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x00000000,
- 0x0a0001e3, 0x00000000, 0x0a0001e3, 0x3c0a0013, 0x0a0001e3, 0x3c0a0014,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0x27bdffe0, 0x00001821, 0x00001021, 0xafbf0018, 0xafb10014, 0xafb00010,
- 0x3c010800, 0x00220821, 0xac200a70, 0x3c010800, 0x00220821, 0xac200a74,
- 0x3c010800, 0x00220821, 0xac200a78, 0x24630001, 0x1860fff5, 0x2442000c,
- 0x24110001, 0x8f906810, 0x32020004, 0x14400005, 0x24040001, 0x3c020800,
- 0x8c420a78, 0x18400003, 0x00002021, 0x0e000182, 0x00000000, 0x32020001,
- 0x10400003, 0x00000000, 0x0e000169, 0x00000000, 0x0a000153, 0xaf915028,
- 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c050800,
- 0x8ca50a70, 0x3c060800, 0x8cc60a80, 0x3c070800, 0x8ce70a78, 0x27bdffe0,
- 0x3c040800, 0x248409d0, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014,
- 0x0e00017b, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x24020001,
- 0x8f836810, 0x00821004, 0x00021027, 0x00621824, 0x03e00008, 0xaf836810,
- 0x27bdffd8, 0xafbf0024, 0x1080002e, 0xafb00020, 0x8f825cec, 0xafa20018,
- 0x8f825cec, 0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, 0xaf825cec,
- 0x8e020000, 0x18400016, 0x00000000, 0x3c020800, 0x94420a74, 0x8fa3001c,
- 0x000221c0, 0xac830004, 0x8fa2001c, 0x3c010800, 0x0e000201, 0xac220a74,
- 0x10400005, 0x00000000, 0x8e020000, 0x24420001, 0x0a0001df, 0xae020000,
- 0x3c020800, 0x8c420a70, 0x00021c02, 0x000321c0, 0x0a0001c5, 0xafa2001c,
- 0x0e000201, 0x00000000, 0x1040001f, 0x00000000, 0x8e020000, 0x8fa3001c,
- 0x24420001, 0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, 0x0a0001df,
- 0xae020000, 0x3c100800, 0x26100a78, 0x8e020000, 0x18400028, 0x00000000,
- 0x0e000201, 0x00000000, 0x14400024, 0x00000000, 0x8e020000, 0x3c030800,
- 0x8c630a70, 0x2442ffff, 0xafa3001c, 0x18400006, 0xae020000, 0x00031402,
- 0x000221c0, 0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, 0x2442ff00,
- 0x2c420300, 0x1440000b, 0x24024000, 0x3c040800, 0x248409dc, 0xafa00010,
- 0xafa00014, 0x8fa6001c, 0x24050008, 0x0e000060, 0x00003821, 0x0a0001df,
- 0x00000000, 0xaf825cf8, 0x3c020800, 0x8c420a40, 0x8fa3001c, 0x24420001,
- 0xaf835cf8, 0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, 0x03e00008,
- 0x27bd0028, 0x27bdffe0, 0x3c040800, 0x248409e8, 0x00002821, 0x00003021,
- 0x00003821, 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x8fbf0018,
- 0x03e00008, 0x27bd0020, 0x8f82680c, 0x8f85680c, 0x00021827, 0x0003182b,
- 0x00031823, 0x00431024, 0x00441021, 0x00a2282b, 0x10a00006, 0x00000000,
- 0x00401821, 0x8f82680c, 0x0043102b, 0x1440fffd, 0x00000000, 0x03e00008,
- 0x00000000, 0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, 0x0064102b,
- 0x54400002, 0x00831023, 0x00641023, 0x2c420008, 0x03e00008, 0x38420001,
- 0x27bdffe0, 0x00802821, 0x3c040800, 0x24840a00, 0x00003021, 0x00003821,
- 0xafbf0018, 0xafa00010, 0x0e000060, 0xafa00014, 0x0a000216, 0x00000000,
- 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000, 0x27bdffe0, 0x3c1cc000,
- 0xafbf0018, 0x0e00004c, 0xaf80680c, 0x3c040800, 0x24840a10, 0x03802821,
- 0x00003021, 0x00003821, 0xafa00010, 0x0e000060, 0xafa00014, 0x2402ffff,
- 0xaf825404, 0x3c0200aa, 0x0e000234, 0xaf825434, 0x8fbf0018, 0x03e00008,
- 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe8, 0xafb00010,
- 0x24100001, 0xafbf0014, 0x3c01c003, 0xac200000, 0x8f826810, 0x30422000,
- 0x10400003, 0x00000000, 0x0e000246, 0x00000000, 0x0a00023a, 0xaf905428,
- 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdfff8, 0x8f845d0c,
- 0x3c0200ff, 0x3c030800, 0x8c630a50, 0x3442fff8, 0x00821024, 0x1043001e,
- 0x3c0500ff, 0x34a5fff8, 0x3c06c003, 0x3c074000, 0x00851824, 0x8c620010,
- 0x3c010800, 0xac230a50, 0x30420008, 0x10400005, 0x00871025, 0x8cc20000,
- 0x24420001, 0xacc20000, 0x00871025, 0xaf825d0c, 0x8fa20000, 0x24420001,
- 0xafa20000, 0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, 0x8fa20000,
- 0x8f845d0c, 0x3c030800, 0x8c630a50, 0x00851024, 0x1443ffe8, 0x00851824,
- 0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000
-};
-
-static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = {
- 0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430,
- 0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
- 0x00000000, 0x00000000, 0x4d61696e, 0x43707542, 0x00000000, 0x00000000,
- 0x00000000
-};
-
-#if 0 /* All zeros, don't eat up space with it. */
-u32 tg3FwData[(TG3_FW_DATA_LEN / sizeof(u32)) + 1] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000
-};
-#endif
-
#define RX_CPU_SCRATCH_BASE 0x30000
#define RX_CPU_SCRATCH_SIZE 0x04000
#define TX_CPU_SCRATCH_BASE 0x34000
@@ -6383,15 +6268,9 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
}
struct fw_info {
- unsigned int text_base;
- unsigned int text_len;
- const u32 *text_data;
- unsigned int rodata_base;
- unsigned int rodata_len;
- const u32 *rodata_data;
- unsigned int data_base;
- unsigned int data_len;
- const u32 *data_data;
+ unsigned int fw_base;
+ unsigned int fw_len;
+ const __be32 *fw_data;
};
/* tp->lock is held. */
@@ -6428,24 +6307,11 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
write_op(tp, cpu_scratch_base + i, 0);
tw32(cpu_base + CPU_STATE, 0xffffffff);
tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
- for (i = 0; i < (info->text_len / sizeof(u32)); i++)
- write_op(tp, (cpu_scratch_base +
- (info->text_base & 0xffff) +
- (i * sizeof(u32))),
- (info->text_data ?
- info->text_data[i] : 0));
- for (i = 0; i < (info->rodata_len / sizeof(u32)); i++)
+ for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
write_op(tp, (cpu_scratch_base +
- (info->rodata_base & 0xffff) +
+ (info->fw_base & 0xffff) +
(i * sizeof(u32))),
- (info->rodata_data ?
- info->rodata_data[i] : 0));
- for (i = 0; i < (info->data_len / sizeof(u32)); i++)
- write_op(tp, (cpu_scratch_base +
- (info->data_base & 0xffff) +
- (i * sizeof(u32))),
- (info->data_data ?
- info->data_data[i] : 0));
+ be32_to_cpu(info->fw_data[i]));
err = 0;
@@ -6457,17 +6323,20 @@ out:
static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
{
struct fw_info info;
+ const __be32 *fw_data;
int err, i;
- info.text_base = TG3_FW_TEXT_ADDR;
- info.text_len = TG3_FW_TEXT_LEN;
- info.text_data = &tg3FwText[0];
- info.rodata_base = TG3_FW_RODATA_ADDR;
- info.rodata_len = TG3_FW_RODATA_LEN;
- info.rodata_data = &tg3FwRodata[0];
- info.data_base = TG3_FW_DATA_ADDR;
- info.data_len = TG3_FW_DATA_LEN;
- info.data_data = NULL;
+ fw_data = (void *)tp->fw->data;
+
+ /* Firmware blob starts with version numbers, followed by
+ start address and length. We are setting complete length.
+ length = end_address_of_bss - start_address_of_text.
+ Remainder is the blob to be loaded contiguously
+ from start address. */
+
+ info.fw_base = be32_to_cpu(fw_data[1]);
+ info.fw_len = tp->fw->size - 12;
+ info.fw_data = &fw_data[3];
err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
@@ -6483,21 +6352,21 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
/* Now startup only the RX cpu. */
tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
- tw32_f(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR);
+ tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
for (i = 0; i < 5; i++) {
- if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR)
+ if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
break;
tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT);
- tw32_f(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR);
+ tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
udelay(1000);
}
if (i >= 5) {
printk(KERN_ERR PFX "tg3_load_firmware fails for %s "
"to set RX CPU PC, is %08x should be %08x\n",
tp->dev->name, tr32(RX_CPU_BASE + CPU_PC),
- TG3_FW_TEXT_ADDR);
+ info.fw_base);
return -ENODEV;
}
tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
@@ -6506,547 +6375,36 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
return 0;
}
-
-#define TG3_TSO_FW_RELEASE_MAJOR 0x1
-#define TG3_TSO_FW_RELASE_MINOR 0x6
-#define TG3_TSO_FW_RELEASE_FIX 0x0
-#define TG3_TSO_FW_START_ADDR 0x08000000
-#define TG3_TSO_FW_TEXT_ADDR 0x08000000
-#define TG3_TSO_FW_TEXT_LEN 0x1aa0
-#define TG3_TSO_FW_RODATA_ADDR 0x08001aa0
-#define TG3_TSO_FW_RODATA_LEN 0x60
-#define TG3_TSO_FW_DATA_ADDR 0x08001b20
-#define TG3_TSO_FW_DATA_LEN 0x30
-#define TG3_TSO_FW_SBSS_ADDR 0x08001b50
-#define TG3_TSO_FW_SBSS_LEN 0x2c
-#define TG3_TSO_FW_BSS_ADDR 0x08001b80
-#define TG3_TSO_FW_BSS_LEN 0x894
-
-static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = {
- 0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000,
- 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800,
- 0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
- 0xafbf0018, 0x0e0005d8, 0x34840002, 0x0e000668, 0x00000000, 0x3c030800,
- 0x90631b68, 0x24020002, 0x3c040800, 0x24841aac, 0x14620003, 0x24050001,
- 0x3c040800, 0x24841aa0, 0x24060006, 0x00003821, 0xafa00010, 0x0e00067c,
- 0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001,
- 0xaf625c90, 0x2402ffff, 0x0e000034, 0xaf625404, 0x8fbf0018, 0x03e00008,
- 0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c,
- 0xafb20018, 0xafb10014, 0x0e00005b, 0xafb00010, 0x24120002, 0x24110001,
- 0x8f706820, 0x32020100, 0x10400003, 0x00000000, 0x0e0000bb, 0x00000000,
- 0x8f706820, 0x32022000, 0x10400004, 0x32020001, 0x0e0001f0, 0x24040001,
- 0x32020001, 0x10400003, 0x00000000, 0x0e0000a3, 0x00000000, 0x3c020800,
- 0x90421b98, 0x14520003, 0x00000000, 0x0e0004c0, 0x00000000, 0x0a00003c,
- 0xaf715028, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
- 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ac0, 0x00002821, 0x00003021,
- 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x3c040800,
- 0x248423d8, 0xa4800000, 0x3c010800, 0xa0201b98, 0x3c010800, 0xac201b9c,
- 0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
- 0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bbc, 0x8f624434, 0x3c010800,
- 0xac221b88, 0x8f624438, 0x3c010800, 0xac221b8c, 0x8f624410, 0xac80f7a8,
- 0x3c010800, 0xac201b84, 0x3c010800, 0xac2023e0, 0x3c010800, 0xac2023c8,
- 0x3c010800, 0xac2023cc, 0x3c010800, 0xac202400, 0x3c010800, 0xac221b90,
- 0x8f620068, 0x24030007, 0x00021702, 0x10430005, 0x00000000, 0x8f620068,
- 0x00021702, 0x14400004, 0x24020001, 0x3c010800, 0x0a000097, 0xac20240c,
- 0xac820034, 0x3c040800, 0x24841acc, 0x3c050800, 0x8ca5240c, 0x00003021,
- 0x00003821, 0xafa00010, 0x0e00067c, 0xafa00014, 0x8fbf0018, 0x03e00008,
- 0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ad8, 0x00002821, 0x00003021,
- 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x0e00005b,
- 0x00000000, 0x0e0000b4, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020,
- 0x24020001, 0x8f636820, 0x00821004, 0x00021027, 0x00621824, 0x03e00008,
- 0xaf636820, 0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020,
- 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f675c5c, 0x3c030800,
- 0x24631bbc, 0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 0x90421b98,
- 0x14400119, 0x3c0200ff, 0x3442fff8, 0x00e28824, 0xac670000, 0x00111902,
- 0x306300ff, 0x30e20003, 0x000211c0, 0x00622825, 0x00a04021, 0x00071602,
- 0x3c030800, 0x90631b98, 0x3044000f, 0x14600036, 0x00804821, 0x24020001,
- 0x3c010800, 0xa0221b98, 0x00051100, 0x00821025, 0x3c010800, 0xac201b9c,
- 0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
- 0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4,
- 0x3c010800, 0xa42223d8, 0x9622000c, 0x30437fff, 0x3c010800, 0xa4222410,
- 0x30428000, 0x3c010800, 0xa4231bc6, 0x10400005, 0x24020001, 0x3c010800,
- 0xac2223f4, 0x0a000102, 0x2406003e, 0x24060036, 0x3c010800, 0xac2023f4,
- 0x9622000a, 0x3c030800, 0x94631bc6, 0x3c010800, 0xac2023f0, 0x3c010800,
- 0xac2023f8, 0x00021302, 0x00021080, 0x00c21021, 0x00621821, 0x3c010800,
- 0xa42223d0, 0x3c010800, 0x0a000115, 0xa4231b96, 0x9622000c, 0x3c010800,
- 0xa42223ec, 0x3c040800, 0x24841b9c, 0x8c820000, 0x00021100, 0x3c010800,
- 0x00220821, 0xac311bc8, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
- 0xac271bcc, 0x8c820000, 0x25030001, 0x306601ff, 0x00021100, 0x3c010800,
- 0x00220821, 0xac261bd0, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
- 0xac291bd4, 0x96230008, 0x3c020800, 0x8c421bac, 0x00432821, 0x3c010800,
- 0xac251bac, 0x9622000a, 0x30420004, 0x14400018, 0x00061100, 0x8f630c14,
- 0x3063000f, 0x2c620002, 0x1440000b, 0x3c02c000, 0x8f630c14, 0x3c020800,
- 0x8c421b40, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002,
- 0x1040fff7, 0x3c02c000, 0x00e21825, 0xaf635c5c, 0x8f625c50, 0x30420002,
- 0x10400014, 0x00000000, 0x0a000147, 0x00000000, 0x3c030800, 0x8c631b80,
- 0x3c040800, 0x94841b94, 0x01221025, 0x3c010800, 0xa42223da, 0x24020001,
- 0x3c010800, 0xac221bb8, 0x24630001, 0x0085202a, 0x3c010800, 0x10800003,
- 0xac231b80, 0x3c010800, 0xa4251b94, 0x3c060800, 0x24c61b9c, 0x8cc20000,
- 0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x00000000, 0x0e000656,
- 0x24040002, 0x0a0001e6, 0x00000000, 0x3c020800, 0x8c421bb8, 0x10400078,
- 0x24020001, 0x3c050800, 0x90a51b98, 0x14a20072, 0x00000000, 0x3c150800,
- 0x96b51b96, 0x3c040800, 0x8c841bac, 0x32a3ffff, 0x0083102a, 0x1440006c,
- 0x00000000, 0x14830003, 0x00000000, 0x3c010800, 0xac2523f0, 0x1060005c,
- 0x00009021, 0x24d60004, 0x0060a021, 0x24d30014, 0x8ec20000, 0x00028100,
- 0x3c110800, 0x02308821, 0x0e000625, 0x8e311bc8, 0x00402821, 0x10a00054,
- 0x00000000, 0x9628000a, 0x31020040, 0x10400005, 0x2407180c, 0x8e22000c,
- 0x2407188c, 0x00021400, 0xaca20018, 0x3c030800, 0x00701821, 0x8c631bd0,
- 0x3c020800, 0x00501021, 0x8c421bd4, 0x00031d00, 0x00021400, 0x00621825,
- 0xaca30014, 0x8ec30004, 0x96220008, 0x00432023, 0x3242ffff, 0x3083ffff,
- 0x00431021, 0x0282102a, 0x14400002, 0x02b23023, 0x00803021, 0x8e620000,
- 0x30c4ffff, 0x00441021, 0xae620000, 0x8e220000, 0xaca20000, 0x8e220004,
- 0x8e63fff4, 0x00431021, 0xaca20004, 0xa4a6000e, 0x8e62fff4, 0x00441021,
- 0xae62fff4, 0x96230008, 0x0043102a, 0x14400005, 0x02469021, 0x8e62fff0,
- 0xae60fff4, 0x24420001, 0xae62fff0, 0xaca00008, 0x3242ffff, 0x14540008,
- 0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c,
- 0x0a0001cb, 0x34e70020, 0xa4a2000c, 0x3c020800, 0x8c4223f0, 0x10400003,
- 0x3c024b65, 0x0a0001d3, 0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c,
- 0x30e2ffff, 0xaca20010, 0x0e0005a2, 0x00a02021, 0x3242ffff, 0x0054102b,
- 0x1440ffa9, 0x00000000, 0x24020002, 0x3c010800, 0x0a0001e6, 0xa0221b98,
- 0x8ec2083c, 0x24420001, 0x0a0001e6, 0xaec2083c, 0x0e0004c0, 0x00000000,
- 0x8fbf002c, 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
- 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028,
- 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff,
- 0x3442fff8, 0x3c070800, 0x24e71bb4, 0x02428824, 0x9623000e, 0x8ce20000,
- 0x00431021, 0xace20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821,
- 0x0e00063b, 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90,
- 0x30420002, 0x1040011e, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002,
- 0x10400119, 0x00000000, 0x0a00020d, 0x00000000, 0x8e240008, 0x8e230014,
- 0x00041402, 0x000231c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f,
- 0x00031942, 0x30637800, 0x00021100, 0x24424000, 0x00624821, 0x9522000a,
- 0x3084ffff, 0x30420008, 0x104000b0, 0x000429c0, 0x3c020800, 0x8c422400,
- 0x14400024, 0x24c50008, 0x94c20014, 0x3c010800, 0xa42223d0, 0x8cc40010,
- 0x00041402, 0x3c010800, 0xa42223d2, 0x3c010800, 0xa42423d4, 0x94c2000e,
- 0x3083ffff, 0x00431023, 0x3c010800, 0xac222408, 0x94c2001a, 0x3c010800,
- 0xac262400, 0x3c010800, 0xac322404, 0x3c010800, 0xac2223fc, 0x3c02c000,
- 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e5, 0x00000000,
- 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e0, 0x00000000, 0x0a000246,
- 0x00000000, 0x94c2000e, 0x3c030800, 0x946323d4, 0x00434023, 0x3103ffff,
- 0x2c620008, 0x1040001c, 0x00000000, 0x94c20014, 0x24420028, 0x00a22821,
- 0x00031042, 0x1840000b, 0x00002021, 0x24e60848, 0x00403821, 0x94a30000,
- 0x8cc20000, 0x24840001, 0x00431021, 0xacc20000, 0x0087102a, 0x1440fff9,
- 0x24a50002, 0x31020001, 0x1040001f, 0x3c024000, 0x3c040800, 0x248423fc,
- 0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021, 0x0a000285, 0xac820000,
- 0x8f626800, 0x3c030010, 0x00431024, 0x10400009, 0x00000000, 0x94c2001a,
- 0x3c030800, 0x8c6323fc, 0x00431021, 0x3c010800, 0xac2223fc, 0x0a000286,
- 0x3c024000, 0x94c2001a, 0x94c4001c, 0x3c030800, 0x8c6323fc, 0x00441023,
- 0x00621821, 0x3c010800, 0xac2323fc, 0x3c024000, 0x02421825, 0xaf635c9c,
- 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x9522000a, 0x30420010,
- 0x1040009b, 0x00000000, 0x3c030800, 0x946323d4, 0x3c070800, 0x24e72400,
- 0x8ce40000, 0x8f626800, 0x24630030, 0x00832821, 0x3c030010, 0x00431024,
- 0x1440000a, 0x00000000, 0x94a20004, 0x3c040800, 0x8c842408, 0x3c030800,
- 0x8c6323fc, 0x00441023, 0x00621821, 0x3c010800, 0xac2323fc, 0x3c040800,
- 0x8c8423fc, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, 0x00822021,
- 0x00041027, 0xa4a20006, 0x3c030800, 0x8c632404, 0x3c0200ff, 0x3442fff8,
- 0x00628824, 0x96220008, 0x24050001, 0x24034000, 0x000231c0, 0x00801021,
- 0xa4c2001a, 0xa4c0001c, 0xace00000, 0x3c010800, 0xac251b60, 0xaf635cb8,
- 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, 0x3c010800, 0xac201b60,
- 0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000,
- 0x3c010800, 0xac201b60, 0x3c020800, 0x8c421b60, 0x1040ffec, 0x00000000,
- 0x3c040800, 0x0e00063b, 0x8c842404, 0x0a00032a, 0x00000000, 0x3c030800,
- 0x90631b98, 0x24020002, 0x14620003, 0x3c034b65, 0x0a0002e1, 0x00008021,
- 0x8e22001c, 0x34637654, 0x10430002, 0x24100002, 0x24100001, 0x00c02021,
- 0x0e000350, 0x02003021, 0x24020003, 0x3c010800, 0xa0221b98, 0x24020002,
- 0x1202000a, 0x24020001, 0x3c030800, 0x8c6323f0, 0x10620006, 0x00000000,
- 0x3c020800, 0x944223d8, 0x00021400, 0x0a00031f, 0xae220014, 0x3c040800,
- 0x248423da, 0x94820000, 0x00021400, 0xae220014, 0x3c020800, 0x8c421bbc,
- 0x3c03c000, 0x3c010800, 0xa0201b98, 0x00431025, 0xaf625c5c, 0x8f625c50,
- 0x30420002, 0x10400009, 0x00000000, 0x2484f7e2, 0x8c820000, 0x00431025,
- 0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa, 0x00000000, 0x3c020800,
- 0x24421b84, 0x8c430000, 0x24630001, 0xac430000, 0x8f630c14, 0x3063000f,
- 0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14, 0x3c020800, 0x8c421b40,
- 0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7,
- 0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002,
- 0x1440fffc, 0x00000000, 0x12600003, 0x00000000, 0x0e0004c0, 0x00000000,
- 0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x03e00008,
- 0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b88, 0x8c820000, 0x00031c02,
- 0x0043102b, 0x14400007, 0x3c038000, 0x8c840004, 0x8f624450, 0x00021c02,
- 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
- 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3c024000,
- 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00000000,
- 0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821, 0x14c00011, 0x256e0008,
- 0x3c020800, 0x8c4223f4, 0x10400007, 0x24020016, 0x3c010800, 0xa42223d2,
- 0x2402002a, 0x3c010800, 0x0a000364, 0xa42223d4, 0x8d670010, 0x00071402,
- 0x3c010800, 0xa42223d2, 0x3c010800, 0xa42723d4, 0x3c040800, 0x948423d4,
- 0x3c030800, 0x946323d2, 0x95cf0006, 0x3c020800, 0x944223d0, 0x00832023,
- 0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821, 0x3082ffff, 0x14c0001a,
- 0x01226021, 0x9582000c, 0x3042003f, 0x3c010800, 0xa42223d6, 0x95820004,
- 0x95830006, 0x3c010800, 0xac2023e4, 0x3c010800, 0xac2023e8, 0x00021400,
- 0x00431025, 0x3c010800, 0xac221bc0, 0x95220004, 0x3c010800, 0xa4221bc4,
- 0x95230002, 0x01e51023, 0x0043102a, 0x10400010, 0x24020001, 0x3c010800,
- 0x0a000398, 0xac2223f8, 0x3c030800, 0x8c6323e8, 0x3c020800, 0x94421bc4,
- 0x00431021, 0xa5220004, 0x3c020800, 0x94421bc0, 0xa5820004, 0x3c020800,
- 0x8c421bc0, 0xa5820006, 0x3c020800, 0x8c4223f0, 0x3c0d0800, 0x8dad23e4,
- 0x3c0a0800, 0x144000e5, 0x8d4a23e8, 0x3c020800, 0x94421bc4, 0x004a1821,
- 0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d, 0x01435023, 0x3c020800,
- 0x944223d6, 0x30420009, 0x10400008, 0x00000000, 0x9582000c, 0x3042fff6,
- 0xa582000c, 0x3c020800, 0x944223d6, 0x30420009, 0x01a26823, 0x3c020800,
- 0x8c4223f8, 0x1040004a, 0x01203821, 0x3c020800, 0x944223d2, 0x00004021,
- 0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff, 0x00021042, 0x18400008,
- 0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021, 0x0103102a,
- 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402,
- 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021, 0x2527000c,
- 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004, 0x1440fffb,
- 0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023, 0x01803821,
- 0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042, 0x18400010, 0x00c33021,
- 0x00404821, 0x94e20000, 0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006,
- 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008,
- 0x0109102a, 0x1440fff3, 0x00000000, 0x30820001, 0x10400005, 0x00061c02,
- 0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02, 0x30c2ffff, 0x00623021,
- 0x00061402, 0x00c23021, 0x0a00047d, 0x30c6ffff, 0x24020002, 0x14c20081,
- 0x00000000, 0x3c020800, 0x8c42240c, 0x14400007, 0x00000000, 0x3c020800,
- 0x944223d2, 0x95230002, 0x01e21023, 0x10620077, 0x00000000, 0x3c020800,
- 0x944223d2, 0x01e21023, 0xa5220002, 0x3c020800, 0x8c42240c, 0x1040001a,
- 0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421b96, 0x00e04021, 0x00072c02,
- 0x00aa2021, 0x00431023, 0x00823823, 0x00072402, 0x30e2ffff, 0x00823821,
- 0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800, 0x948423d4, 0x00453023,
- 0x00e02821, 0x00641823, 0x006d1821, 0x00c33021, 0x00061c02, 0x30c2ffff,
- 0x0a00047d, 0x00623021, 0x01203821, 0x00004021, 0x3082ffff, 0x00021042,
- 0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021,
- 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021,
- 0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021,
- 0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004,
- 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023,
- 0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800, 0x948423d4, 0x00621821,
- 0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061c02, 0x3c020800,
- 0x944223d0, 0x00c34821, 0x00441023, 0x00021fc2, 0x00431021, 0x00021043,
- 0x18400010, 0x00003021, 0x00402021, 0x94e20000, 0x24e70002, 0x00c23021,
- 0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80,
- 0x00625824, 0x25670008, 0x0104102a, 0x1440fff3, 0x00000000, 0x3c020800,
- 0x944223ec, 0x00c23021, 0x3122ffff, 0x00c23021, 0x00061c02, 0x30c2ffff,
- 0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010,
- 0xadc00014, 0x0a00049d, 0xadc00000, 0x8dc70010, 0x00e04021, 0x11400007,
- 0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff, 0x00433021, 0x00061402,
- 0x00c22821, 0x00051027, 0xa522000a, 0x3c030800, 0x946323d4, 0x3102ffff,
- 0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02, 0x30c2ffff, 0x00623021,
- 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010, 0x3102ffff,
- 0x00051c00, 0x00431025, 0xadc20010, 0x3c020800, 0x8c4223f4, 0x10400005,
- 0x2de205eb, 0x14400002, 0x25e2fff2, 0x34028870, 0xa5c20034, 0x3c030800,
- 0x246323e8, 0x8c620000, 0x24420001, 0xac620000, 0x3c040800, 0x8c8423e4,
- 0x3c020800, 0x8c421bc0, 0x3303ffff, 0x00832021, 0x00431821, 0x0062102b,
- 0x3c010800, 0xac2423e4, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223e4,
- 0x3c010800, 0xac231bc0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800,
- 0x24a51b96, 0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034,
- 0xafb40030, 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x94a90000,
- 0x3c020800, 0x944223d0, 0x3c030800, 0x8c631bb0, 0x3c040800, 0x8c841bac,
- 0x01221023, 0x0064182a, 0xa7a9001e, 0x106000be, 0xa7a20016, 0x24be0022,
- 0x97b6001e, 0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 0x00000000,
- 0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000b0,
- 0x00000000, 0x97d50818, 0x32a2ffff, 0x104000a3, 0x00009021, 0x0040a021,
- 0x00008821, 0x0e000625, 0x00000000, 0x00403021, 0x14c00007, 0x00000000,
- 0x3c020800, 0x8c4223dc, 0x24420001, 0x3c010800, 0x0a000596, 0xac2223dc,
- 0x3c100800, 0x02118021, 0x8e101bc8, 0x9608000a, 0x31020040, 0x10400005,
- 0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x31020080,
- 0x54400001, 0x34e70010, 0x3c020800, 0x00511021, 0x8c421bd0, 0x3c030800,
- 0x00711821, 0x8c631bd4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014,
- 0x96040008, 0x3242ffff, 0x00821021, 0x0282102a, 0x14400002, 0x02b22823,
- 0x00802821, 0x8e020000, 0x02459021, 0xacc20000, 0x8e020004, 0x00c02021,
- 0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010,
- 0x24020305, 0x0e0005a2, 0xa482000c, 0x3242ffff, 0x0054102b, 0x1440ffc5,
- 0x3242ffff, 0x0a00058e, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
- 0x10400067, 0x00000000, 0x8e62fff0, 0x00028900, 0x3c100800, 0x02118021,
- 0x0e000625, 0x8e101bc8, 0x00403021, 0x14c00005, 0x00000000, 0x8e62082c,
- 0x24420001, 0x0a000596, 0xae62082c, 0x9608000a, 0x31020040, 0x10400005,
- 0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x3c020800,
- 0x00511021, 0x8c421bd0, 0x3c030800, 0x00711821, 0x8c631bd4, 0x00021500,
- 0x00031c00, 0x00431025, 0xacc20014, 0x8e63fff4, 0x96020008, 0x00432023,
- 0x3242ffff, 0x3083ffff, 0x00431021, 0x02c2102a, 0x10400003, 0x00802821,
- 0x97a9001e, 0x01322823, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000,
- 0xa4c5000e, 0x8e020000, 0xacc20000, 0x8e020004, 0x8e63fff4, 0x00431021,
- 0xacc20004, 0x8e63fff4, 0x96020008, 0x00641821, 0x0062102a, 0x14400006,
- 0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0x0a000571, 0xae62fff0,
- 0xae63fff4, 0xacc00008, 0x3242ffff, 0x10560003, 0x31020004, 0x10400006,
- 0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x34e70020, 0x24020905,
- 0xa4c2000c, 0x8ee30000, 0x8ee20004, 0x14620007, 0x3c02b49a, 0x8ee20860,
- 0x54400001, 0x34e70400, 0x3c024b65, 0x0a000588, 0x34427654, 0x344289ab,
- 0xacc2001c, 0x30e2ffff, 0xacc20010, 0x0e0005a2, 0x00c02021, 0x3242ffff,
- 0x0056102b, 0x1440ff9b, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
- 0x1440ff48, 0x00000000, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038,
- 0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
- 0x03e00008, 0x27bd0048, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450,
- 0x8f634410, 0x0a0005b1, 0x00808021, 0x8f626820, 0x30422000, 0x10400003,
- 0x00000000, 0x0e0001f0, 0x00002021, 0x8f624450, 0x8f634410, 0x3042ffff,
- 0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002,
- 0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, 0x8c421b40, 0x3063000f,
- 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7, 0x00000000,
- 0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, 0x00000000, 0x8f626820,
- 0x30422000, 0x1040fff8, 0x00000000, 0x0e0001f0, 0x00002021, 0x0a0005c4,
- 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000,
- 0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010,
- 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50,
- 0x3c010800, 0xac221b54, 0x24020b78, 0x3c010800, 0xac221b64, 0x34630002,
- 0xaf634000, 0x0e000605, 0x00808021, 0x3c010800, 0xa0221b68, 0x304200ff,
- 0x24030002, 0x14430005, 0x00000000, 0x3c020800, 0x8c421b54, 0x0a0005f8,
- 0xac5000c0, 0x3c020800, 0x8c421b54, 0xac5000bc, 0x8f624434, 0x8f634438,
- 0x8f644410, 0x3c010800, 0xac221b5c, 0x3c010800, 0xac231b6c, 0x3c010800,
- 0xac241b58, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c040800,
- 0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, 0xac830000, 0x8cc20000,
- 0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa, 0xac830000, 0x8cc20000,
- 0x50430001, 0x24050001, 0x3c020800, 0xac470000, 0x03e00008, 0x00a01021,
- 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe,
- 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008,
- 0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b5c, 0x00031c02, 0x0043102b,
- 0x14400008, 0x3c038000, 0x3c040800, 0x8c841b6c, 0x8f624450, 0x00021c02,
- 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
- 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff,
- 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0a000648, 0x2402ffff,
- 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021,
- 0x03e00008, 0x00000000, 0x8f624450, 0x3c030800, 0x8c631b58, 0x0a000651,
- 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000,
- 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040800, 0x24841af0,
- 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014,
- 0x0a000660, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000,
- 0x00000000, 0x00000000, 0x3c020800, 0x34423000, 0x3c030800, 0x34633000,
- 0x3c040800, 0x348437ff, 0x3c010800, 0xac221b74, 0x24020040, 0x3c010800,
- 0xac221b78, 0x3c010800, 0xac201b70, 0xac600000, 0x24630004, 0x0083102b,
- 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, 0x00804821, 0x8faa0010,
- 0x3c020800, 0x8c421b70, 0x3c040800, 0x8c841b78, 0x8fab0014, 0x24430001,
- 0x0044102b, 0x3c010800, 0xac231b70, 0x14400003, 0x00004021, 0x3c010800,
- 0xac201b70, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74, 0x91240000,
- 0x00021140, 0x00431021, 0x00481021, 0x25080001, 0xa0440000, 0x29020008,
- 0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74,
- 0x8f64680c, 0x00021140, 0x00431021, 0xac440008, 0xac45000c, 0xac460010,
- 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3TsoFwRodata[] = {
- 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
- 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f,
- 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000,
- 0x00000000,
-};
-
-static const u32 tg3TsoFwData[] = {
- 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000,
-};
-
/* 5705 needs a special version of the TSO firmware. */
-#define TG3_TSO5_FW_RELEASE_MAJOR 0x1
-#define TG3_TSO5_FW_RELASE_MINOR 0x2
-#define TG3_TSO5_FW_RELEASE_FIX 0x0
-#define TG3_TSO5_FW_START_ADDR 0x00010000
-#define TG3_TSO5_FW_TEXT_ADDR 0x00010000
-#define TG3_TSO5_FW_TEXT_LEN 0xe90
-#define TG3_TSO5_FW_RODATA_ADDR 0x00010e90
-#define TG3_TSO5_FW_RODATA_LEN 0x50
-#define TG3_TSO5_FW_DATA_ADDR 0x00010f00
-#define TG3_TSO5_FW_DATA_LEN 0x20
-#define TG3_TSO5_FW_SBSS_ADDR 0x00010f20
-#define TG3_TSO5_FW_SBSS_LEN 0x28
-#define TG3_TSO5_FW_BSS_ADDR 0x00010f50
-#define TG3_TSO5_FW_BSS_LEN 0x88
-
-static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = {
- 0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000,
- 0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001,
- 0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
- 0xafbf0018, 0x0c0042e8, 0x34840002, 0x0c004364, 0x00000000, 0x3c030001,
- 0x90630f34, 0x24020002, 0x3c040001, 0x24840e9c, 0x14620003, 0x24050001,
- 0x3c040001, 0x24840e90, 0x24060002, 0x00003821, 0xafa00010, 0x0c004378,
- 0xafa00014, 0x0c00402c, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020,
- 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014,
- 0x0c0042d4, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400,
- 0x10400007, 0x00000000, 0x8f641008, 0x00921024, 0x14400003, 0x00000000,
- 0x0c004064, 0x00000000, 0x3c020001, 0x90420f56, 0x10510003, 0x32020200,
- 0x1040fff1, 0x00000000, 0x0c0041b4, 0x00000000, 0x08004034, 0x00000000,
- 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
- 0x27bdffe0, 0x3c040001, 0x24840eb0, 0x00002821, 0x00003021, 0x00003821,
- 0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0000d021, 0x24020130,
- 0xaf625000, 0x3c010001, 0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018,
- 0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f60,
- 0x90620000, 0x27bdfff0, 0x14400003, 0x0080c021, 0x08004073, 0x00004821,
- 0x3c022000, 0x03021024, 0x10400003, 0x24090002, 0x08004073, 0xa0600000,
- 0x24090001, 0x00181040, 0x30431f80, 0x346f8008, 0x1520004b, 0x25eb0028,
- 0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f7a, 0x00041402,
- 0xa0a20000, 0x3c010001, 0xa0240f7b, 0x3c020001, 0x00431021, 0x94428014,
- 0x3c010001, 0xa0220f7c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff,
- 0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f60, 0x0124102b,
- 0x1040000c, 0x00003821, 0x24a6000e, 0x01602821, 0x8ca20000, 0x8ca30004,
- 0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 0x00e4102b, 0x1440fff8,
- 0x24c60008, 0x00003821, 0x3c080001, 0x25080f7b, 0x91060000, 0x3c020001,
- 0x90420f7c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021,
- 0x00021043, 0x1840000c, 0x00002021, 0x91020001, 0x00461023, 0x00021fc2,
- 0x00431021, 0x00021843, 0x94a20000, 0x24e70001, 0x00822021, 0x00e3102a,
- 0x1440fffb, 0x24a50002, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
- 0x00822021, 0x3c02ffff, 0x01821024, 0x3083ffff, 0x00431025, 0x3c010001,
- 0x080040fa, 0xac220f80, 0x3c050001, 0x24a50f7c, 0x90a20000, 0x3c0c0001,
- 0x01836021, 0x8d8c8018, 0x000220c2, 0x1080000e, 0x00003821, 0x01603021,
- 0x24a5000c, 0x8ca20000, 0x8ca30004, 0x24a50008, 0x24e70001, 0xacc20000,
- 0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f7c,
- 0x90a20000, 0x30430007, 0x24020004, 0x10620011, 0x28620005, 0x10400005,
- 0x24020002, 0x10620008, 0x000710c0, 0x080040fa, 0x00000000, 0x24020006,
- 0x1062000e, 0x000710c0, 0x080040fa, 0x00000000, 0x00a21821, 0x9463000c,
- 0x004b1021, 0x080040fa, 0xa4430000, 0x000710c0, 0x00a21821, 0x8c63000c,
- 0x004b1021, 0x080040fa, 0xac430000, 0x00a21821, 0x8c63000c, 0x004b2021,
- 0x00a21021, 0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 0x3c020001,
- 0x90420f7c, 0x3c030001, 0x90630f7a, 0x00e2c823, 0x3c020001, 0x90420f7b,
- 0x24630028, 0x01e34021, 0x24420028, 0x15200012, 0x01e23021, 0x94c2000c,
- 0x3c010001, 0xa4220f78, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f76,
- 0x3c010001, 0xa4200f72, 0x00021400, 0x00431025, 0x3c010001, 0xac220f6c,
- 0x95020004, 0x3c010001, 0x08004124, 0xa4220f70, 0x3c020001, 0x94420f70,
- 0x3c030001, 0x94630f72, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f6c,
- 0xa4c20004, 0x3c020001, 0x8c420f6c, 0xa4c20006, 0x3c040001, 0x94840f72,
- 0x3c020001, 0x94420f70, 0x3c0a0001, 0x954a0f76, 0x00441821, 0x3063ffff,
- 0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f78,
- 0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f78,
- 0x30420009, 0x01425023, 0x24020001, 0x1122001b, 0x29220002, 0x50400005,
- 0x24020002, 0x11200007, 0x31a2ffff, 0x08004197, 0x00000000, 0x1122001d,
- 0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0f80, 0x10800005,
- 0x01806821, 0x01c42021, 0x00041c02, 0x3082ffff, 0x00627021, 0x000e1027,
- 0xa502000a, 0x3c030001, 0x90630f7b, 0x31a2ffff, 0x00e21021, 0x0800418d,
- 0x00432023, 0x3c020001, 0x94420f80, 0x00442021, 0x00041c02, 0x3082ffff,
- 0x00622021, 0x00807021, 0x00041027, 0x08004185, 0xa502000a, 0x3c050001,
- 0x24a50f7a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000,
- 0x00e21023, 0xa5020002, 0x3c030001, 0x94630f80, 0x3c020001, 0x94420f5a,
- 0x30e5ffff, 0x00641821, 0x00451023, 0x00622023, 0x00041c02, 0x3082ffff,
- 0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f7c, 0x24620001,
- 0x14a20005, 0x00807021, 0x01631021, 0x90420000, 0x08004185, 0x00026200,
- 0x24620002, 0x14a20003, 0x306200fe, 0x004b1021, 0x944c0000, 0x3c020001,
- 0x94420f82, 0x3183ffff, 0x3c040001, 0x90840f7b, 0x00431021, 0x00e21021,
- 0x00442023, 0x008a2021, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
- 0x00822021, 0x00806821, 0x00041027, 0xa4c20010, 0x31a2ffff, 0x000e1c00,
- 0x00431025, 0x3c040001, 0x24840f72, 0xade20010, 0x94820000, 0x3c050001,
- 0x94a50f76, 0x3c030001, 0x8c630f6c, 0x24420001, 0x00b92821, 0xa4820000,
- 0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f76, 0x10600003,
- 0x24a2ffff, 0x3c010001, 0xa4220f76, 0x3c024000, 0x03021025, 0x3c010001,
- 0xac240f6c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f56,
- 0x27bdffe8, 0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 0x8f620cf4,
- 0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f64,
- 0x8c434008, 0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 0x24020088,
- 0x24020008, 0x3c010001, 0xa4220f68, 0x30620004, 0x10400005, 0x24020001,
- 0x3c010001, 0xa0220f57, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f57,
- 0x00031402, 0x3c010001, 0xa4220f54, 0x9483000c, 0x24020001, 0x3c010001,
- 0xa4200f50, 0x3c010001, 0xa0220f56, 0x3c010001, 0xa4230f62, 0x24020001,
- 0x1342001e, 0x00000000, 0x13400005, 0x24020003, 0x13420067, 0x00000000,
- 0x080042cf, 0x00000000, 0x3c020001, 0x94420f62, 0x241a0001, 0x3c010001,
- 0xa4200f5e, 0x3c010001, 0xa4200f52, 0x304407ff, 0x00021bc2, 0x00031823,
- 0x3063003e, 0x34630036, 0x00021242, 0x3042003c, 0x00621821, 0x3c010001,
- 0xa4240f58, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f5a, 0x3c010001,
- 0xa4230f5c, 0x3c060001, 0x24c60f52, 0x94c50000, 0x94c30002, 0x3c040001,
- 0x94840f5a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021,
- 0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008,
- 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4,
- 0x00501024, 0x104000b7, 0x00000000, 0x0800420f, 0x00000000, 0x3c030001,
- 0x94630f50, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001,
- 0xa4230f50, 0xaf620ce8, 0x3c020001, 0x94420f68, 0x34420024, 0xaf620cec,
- 0x94c30002, 0x3c020001, 0x94420f50, 0x14620012, 0x3c028000, 0x3c108000,
- 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008, 0x00901024,
- 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024,
- 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, 0xaf620cf4, 0x3c108000,
- 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000,
- 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003,
- 0x3c070001, 0x24e70f50, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001,
- 0x8c420f64, 0xaf620ce4, 0x3c050001, 0x94a50f54, 0x94e30000, 0x3c040001,
- 0x94840f58, 0x3c020001, 0x94420f5e, 0x00a32823, 0x00822023, 0x30a6ffff,
- 0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f5c,
- 0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f54,
- 0x00441021, 0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 0x3c020001,
- 0x90420f57, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624,
- 0x0800427c, 0x0000d021, 0x3c020001, 0x94420f68, 0x3c030008, 0x34630624,
- 0x00431025, 0xaf620cec, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
- 0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
- 0x00000000, 0x8f620cf4, 0x00501024, 0x10400015, 0x00000000, 0x08004283,
- 0x00000000, 0x3c030001, 0x94630f68, 0x34420624, 0x3c108000, 0x00621825,
- 0x3c028000, 0xaf630cec, 0xaf620cf4, 0x8f641008, 0x00901024, 0x14400003,
- 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7,
- 0x00000000, 0x3c010001, 0x080042cf, 0xa4200f5e, 0x3c020001, 0x94420f5c,
- 0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f57, 0x10400009,
- 0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624, 0x0000d021, 0x00431025,
- 0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f68, 0x3c030008,
- 0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f5e, 0x00451021,
- 0x3c010001, 0xa4220f5e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
- 0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
- 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x8fbf0014,
- 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000, 0x27bdffe0, 0x3c040001,
- 0x24840ec0, 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010,
- 0x0c004378, 0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001,
- 0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018, 0x03e00008, 0x27bd0020,
- 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804,
- 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, 0x3c010001, 0xac220f20,
- 0x24020b78, 0x3c010001, 0xac220f30, 0x34630002, 0xaf634000, 0x0c004315,
- 0x00808021, 0x3c010001, 0xa0220f34, 0x304200ff, 0x24030002, 0x14430005,
- 0x00000000, 0x3c020001, 0x8c420f20, 0x08004308, 0xac5000c0, 0x3c020001,
- 0x8c420f20, 0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 0x3c010001,
- 0xac220f28, 0x3c010001, 0xac230f38, 0x3c010001, 0xac240f24, 0x8fbf0014,
- 0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008, 0x24020001, 0x27bdfff8,
- 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x00000000,
- 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008, 0x27bd0008,
- 0x8f634450, 0x3c020001, 0x8c420f28, 0x00031c02, 0x0043102b, 0x14400008,
- 0x3c038000, 0x3c040001, 0x8c840f38, 0x8f624450, 0x00021c02, 0x0083102b,
- 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, 0x1440fffd,
- 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff, 0x2442e000,
- 0x2c422001, 0x14400003, 0x3c024000, 0x08004347, 0x2402ffff, 0x00822025,
- 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021, 0x03e00008,
- 0x00000000, 0x8f624450, 0x3c030001, 0x8c630f24, 0x08004350, 0x3042ffff,
- 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000, 0x03e00008,
- 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001, 0x24840ed0, 0x00003021,
- 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0800435f,
- 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x3c020001, 0x3442d600,
- 0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff, 0x3c010001, 0xac220f40,
- 0x24020040, 0x3c010001, 0xac220f44, 0x3c010001, 0xac200f3c, 0xac600000,
- 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
- 0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f3c, 0x3c040001, 0x8c840f44,
- 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001, 0xac230f3c, 0x14400003,
- 0x00004021, 0x3c010001, 0xac200f3c, 0x3c020001, 0x8c420f3c, 0x3c030001,
- 0x8c630f40, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
- 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020001, 0x8c420f3c,
- 0x3c030001, 0x8c630f40, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008,
- 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
- 0x00000000, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
- 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
- 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000,
- 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
- 0x00000000, 0x00000000, 0x00000000,
-};
-
-static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
- 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
-};
/* tp->lock is held. */
static int tg3_load_tso_firmware(struct tg3 *tp)
{
struct fw_info info;
+ const __be32 *fw_data;
unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
int err, i;
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
return 0;
+ fw_data = (void *)tp->fw->data;
+
+ /* Firmware blob starts with version numbers, followed by
+ start address and length. We are setting complete length.
+ length = end_address_of_bss - start_address_of_text.
+ Remainder is the blob to be loaded contiguously
+ from start address. */
+
+ info.fw_base = be32_to_cpu(fw_data[1]);
+ cpu_scratch_size = tp->fw_len;
+ info.fw_len = tp->fw->size - 12;
+ info.fw_data = &fw_data[3];
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
- info.text_base = TG3_TSO5_FW_TEXT_ADDR;
- info.text_len = TG3_TSO5_FW_TEXT_LEN;
- info.text_data = &tg3Tso5FwText[0];
- info.rodata_base = TG3_TSO5_FW_RODATA_ADDR;
- info.rodata_len = TG3_TSO5_FW_RODATA_LEN;
- info.rodata_data = &tg3Tso5FwRodata[0];
- info.data_base = TG3_TSO5_FW_DATA_ADDR;
- info.data_len = TG3_TSO5_FW_DATA_LEN;
- info.data_data = &tg3Tso5FwData[0];
cpu_base = RX_CPU_BASE;
cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
- cpu_scratch_size = (info.text_len +
- info.rodata_len +
- info.data_len +
- TG3_TSO5_FW_SBSS_LEN +
- TG3_TSO5_FW_BSS_LEN);
} else {
- info.text_base = TG3_TSO_FW_TEXT_ADDR;
- info.text_len = TG3_TSO_FW_TEXT_LEN;
- info.text_data = &tg3TsoFwText[0];
- info.rodata_base = TG3_TSO_FW_RODATA_ADDR;
- info.rodata_len = TG3_TSO_FW_RODATA_LEN;
- info.rodata_data = &tg3TsoFwRodata[0];
- info.data_base = TG3_TSO_FW_DATA_ADDR;
- info.data_len = TG3_TSO_FW_DATA_LEN;
- info.data_data = &tg3TsoFwData[0];
cpu_base = TX_CPU_BASE;
cpu_scratch_base = TX_CPU_SCRATCH_BASE;
cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
@@ -7060,21 +6418,21 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
/* Now startup the cpu. */
tw32(cpu_base + CPU_STATE, 0xffffffff);
- tw32_f(cpu_base + CPU_PC, info.text_base);
+ tw32_f(cpu_base + CPU_PC, info.fw_base);
for (i = 0; i < 5; i++) {
- if (tr32(cpu_base + CPU_PC) == info.text_base)
+ if (tr32(cpu_base + CPU_PC) == info.fw_base)
break;
tw32(cpu_base + CPU_STATE, 0xffffffff);
tw32(cpu_base + CPU_MODE, CPU_MODE_HALT);
- tw32_f(cpu_base + CPU_PC, info.text_base);
+ tw32_f(cpu_base + CPU_PC, info.fw_base);
udelay(1000);
}
if (i >= 5) {
printk(KERN_ERR PFX "tg3_load_tso_firmware fails for %s "
"to set CPU PC, is %08x should be %08x\n",
tp->dev->name, tr32(cpu_base + CPU_PC),
- info.text_base);
+ info.fw_base);
return -ENODEV;
}
tw32(cpu_base + CPU_STATE, 0xffffffff);
@@ -7299,11 +6657,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
else if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
int fw_len;
- fw_len = (TG3_TSO5_FW_TEXT_LEN +
- TG3_TSO5_FW_RODATA_LEN +
- TG3_TSO5_FW_DATA_LEN +
- TG3_TSO5_FW_SBSS_LEN +
- TG3_TSO5_FW_BSS_LEN);
+ fw_len = tp->fw_len;
fw_len = (fw_len + (0x80 - 1)) & ~(0x80 - 1);
tw32(BUFMGR_MB_POOL_ADDR,
NIC_SRAM_MBUF_POOL_BASE5705 + fw_len);
@@ -8181,11 +7535,58 @@ static int tg3_test_msi(struct tg3 *tp)
return err;
}
+static int tg3_request_firmware(struct tg3 *tp)
+{
+ const __be32 *fw_data;
+
+ if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) {
+ printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+ tp->dev->name, tp->fw_needed);
+ return -ENOENT;
+ }
+
+ fw_data = (void *)tp->fw->data;
+
+ /* Firmware blob starts with version numbers, followed by
+ * start address and _full_ length including BSS sections
+ * (which must be longer than the actual data, of course
+ */
+
+ tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */
+ if (tp->fw_len < (tp->fw->size - 12)) {
+ printk(KERN_ERR "%s: bogus length %d in \"%s\"\n",
+ tp->dev->name, tp->fw_len, tp->fw_needed);
+ release_firmware(tp->fw);
+ tp->fw = NULL;
+ return -EINVAL;
+ }
+
+ /* We no longer need firmware; we have it. */
+ tp->fw_needed = NULL;
+ return 0;
+}
+
static int tg3_open(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
int err;
+ if (tp->fw_needed) {
+ err = tg3_request_firmware(tp);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
+ if (err)
+ return err;
+ } else if (err) {
+ printk(KERN_WARNING "%s: TSO capability disabled.\n",
+ tp->dev->name);
+ tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
+ } else if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
+ printk(KERN_NOTICE "%s: TSO capability restored.\n",
+ tp->dev->name);
+ tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
+ }
+ }
+
netif_carrier_off(tp->dev);
err = tg3_set_power_state(tp, PCI_D0);
@@ -13735,6 +13136,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tg3_init_bufmgr_config(tp);
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0)
+ tp->fw_needed = FIRMWARE_TG3;
+
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
}
@@ -13746,6 +13150,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
} else {
tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+ tp->fw_needed = FIRMWARE_TG3TSO5;
+ else
+ tp->fw_needed = FIRMWARE_TG3TSO;
}
/* TSO is on by default on chips that support hardware TSO.
@@ -13778,7 +13186,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
if (err) {
printk(KERN_ERR PFX "Could not obtain valid ethernet address, "
"aborting.\n");
- goto err_out_iounmap;
+ goto err_out_fw;
}
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
@@ -13787,7 +13195,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
printk(KERN_ERR PFX "Cannot map APE registers, "
"aborting.\n");
err = -ENOMEM;
- goto err_out_iounmap;
+ goto err_out_fw;
}
tg3_ape_lock_init(tp);
@@ -13867,6 +13275,10 @@ err_out_apeunmap:
tp->aperegs = NULL;
}
+err_out_fw:
+ if (tp->fw)
+ release_firmware(tp->fw);
+
err_out_iounmap:
if (tp->regs) {
iounmap(tp->regs);
@@ -13892,6 +13304,9 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
if (dev) {
struct tg3 *tp = netdev_priv(dev);
+ if (tp->fw)
+ release_firmware(tp->fw);
+
flush_scheduled_work();
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 8936edfb0438..508def3e077f 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2762,6 +2762,11 @@ struct tg3 {
#define SST_25VF0X0_PAGE_SIZE 4098
struct ethtool_coalesce coal;
+
+ /* firmware info */
+ const char *fw_needed;
+ const struct firmware *fw;
+ u32 fw_len; /* includes BSS */
};
#endif /* !(_T3_H) */
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 85ef8b744557..68b967b585aa 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -831,6 +831,21 @@ static void TLan_Poll(struct net_device *dev)
}
#endif
+static const struct net_device_ops TLan_netdev_ops = {
+ .ndo_open = TLan_Open,
+ .ndo_stop = TLan_Close,
+ .ndo_start_xmit = TLan_StartTx,
+ .ndo_tx_timeout = TLan_tx_timeout,
+ .ndo_get_stats = TLan_GetStats,
+ .ndo_set_multicast_list = TLan_SetMulticastList,
+ .ndo_do_ioctl = TLan_ioctl,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = TLan_Poll,
+#endif
+};
@@ -892,16 +907,7 @@ static int TLan_Init( struct net_device *dev )
netif_carrier_off(dev);
/* Device methods */
- dev->open = &TLan_Open;
- dev->hard_start_xmit = &TLan_StartTx;
- dev->stop = &TLan_Close;
- dev->get_stats = &TLan_GetStats;
- dev->set_multicast_list = &TLan_SetMulticastList;
- dev->do_ioctl = &TLan_ioctl;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &TLan_Poll;
-#endif
- dev->tx_timeout = &TLan_tx_timeout;
+ dev->netdev_ops = &TLan_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
return 0;
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index a011666342ff..50eb29ce3c87 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3064,7 +3064,7 @@ static int smctr_load_node_addr(struct net_device *dev)
* will consequently cause a timeout.
*
* NOTE 1: If the monitor_state is MS_BEACON_TEST_STATE, all transmit
- * queues other then the one used for the lobe_media_test should be
+ * queues other than the one used for the lobe_media_test should be
* disabled.!?
*
* NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index 75461dbd4876..a9fd2b2ccaf6 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -1237,7 +1237,7 @@ static void tsi108_init_phy(struct net_device *dev)
spin_lock_irqsave(&phy_lock, flags);
tsi108_write_mii(data, MII_BMCR, BMCR_RESET);
- while (i--){
+ while (--i) {
if(!(tsi108_read_mii(data, MII_BMCR) & BMCR_RESET))
break;
udelay(10);
diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c
index 1210fb3748a7..db7d5e11855d 100644
--- a/drivers/net/tulip/21142.c
+++ b/drivers/net/tulip/21142.c
@@ -9,6 +9,11 @@
Please refer to Documentation/DocBook/tulip-user.{pdf,ps,html}
for more information on this driver.
+
+ DC21143 manual "21143 PCI/CardBus 10/100Mb/s Ethernet LAN Controller
+ Hardware Reference Manual" is currently available at :
+ http://developer.intel.com/design/network/manuals/278074.htm
+
Please submit bugs to http://bugzilla.kernel.org/ .
*/
@@ -32,7 +37,11 @@ void t21142_media_task(struct work_struct *work)
int csr12 = ioread32(ioaddr + CSR12);
int next_tick = 60*HZ;
int new_csr6 = 0;
+ int csr14 = ioread32(ioaddr + CSR14);
+ /* CSR12[LS10,LS100] are not reliable during autonegotiation */
+ if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000)
+ csr12 |= 6;
if (tulip_debug > 2)
printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n",
dev->name, csr12, medianame[dev->if_port]);
@@ -76,7 +85,7 @@ void t21142_media_task(struct work_struct *work)
new_csr6 = 0x83860000;
dev->if_port = 3;
iowrite32(0, ioaddr + CSR13);
- iowrite32(0x0003FF7F, ioaddr + CSR14);
+ iowrite32(0x0003FFFF, ioaddr + CSR14);
iowrite16(8, ioaddr + CSR15);
iowrite32(1, ioaddr + CSR13);
}
@@ -132,10 +141,14 @@ void t21142_lnk_change(struct net_device *dev, int csr5)
struct tulip_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->base_addr;
int csr12 = ioread32(ioaddr + CSR12);
+ int csr14 = ioread32(ioaddr + CSR14);
+ /* CSR12[LS10,LS100] are not reliable during autonegotiation */
+ if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000)
+ csr12 |= 6;
if (tulip_debug > 1)
printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, "
- "%8.8x.\n", dev->name, csr12, csr5, ioread32(ioaddr + CSR14));
+ "%8.8x.\n", dev->name, csr12, csr5, csr14);
/* If NWay finished and we have a negotiated partner capability. */
if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) {
@@ -143,7 +156,9 @@ void t21142_lnk_change(struct net_device *dev, int csr5)
int negotiated = tp->sym_advertise & (csr12 >> 16);
tp->lpar = csr12 >> 16;
tp->nwayset = 1;
- if (negotiated & 0x0100) dev->if_port = 5;
+ /* If partner cannot negotiate, it is 10Mbps Half Duplex */
+ if (!(csr12 & 0x8000)) dev->if_port = 0;
+ else if (negotiated & 0x0100) dev->if_port = 5;
else if (negotiated & 0x0080) dev->if_port = 3;
else if (negotiated & 0x0040) dev->if_port = 4;
else if (negotiated & 0x0020) dev->if_port = 0;
@@ -214,7 +229,7 @@ void t21142_lnk_change(struct net_device *dev, int csr5)
tp->timer.expires = RUN_AT(3*HZ);
add_timer(&tp->timer);
} else if (dev->if_port == 5)
- iowrite32(ioread32(ioaddr + CSR14) & ~0x080, ioaddr + CSR14);
+ iowrite32(csr14 & ~0x080, ioaddr + CSR14);
} else if (dev->if_port == 0 || dev->if_port == 4) {
if ((csr12 & 4) == 0)
printk(KERN_INFO"%s: 21143 10baseT link beat good.\n",
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 5166be930a52..0bf2114738be 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -392,7 +392,7 @@ static void de_rx (struct de_private *de)
unsigned drop = 0;
int rc;
- while (rx_work--) {
+ while (--rx_work) {
u32 status, len;
dma_addr_t mapping;
struct sk_buff *skb, *copy_skb;
@@ -1922,6 +1922,18 @@ bad_srom:
goto fill_defaults;
}
+static const struct net_device_ops de_netdev_ops = {
+ .ndo_open = de_open,
+ .ndo_stop = de_close,
+ .ndo_set_multicast_list = de_set_rx_mode,
+ .ndo_start_xmit = de_start_xmit,
+ .ndo_get_stats = de_get_stats,
+ .ndo_tx_timeout = de_tx_timeout,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit de_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1944,14 +1956,9 @@ static int __devinit de_init_one (struct pci_dev *pdev,
if (!dev)
return -ENOMEM;
+ dev->netdev_ops = &de_netdev_ops;
SET_NETDEV_DEV(dev, &pdev->dev);
- dev->open = de_open;
- dev->stop = de_close;
- dev->set_multicast_list = de_set_rx_mode;
- dev->hard_start_xmit = de_start_xmit;
- dev->get_stats = de_get_stats;
dev->ethtool_ops = &de_ethtool_ops;
- dev->tx_timeout = de_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
de = netdev_priv(dev);
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 67bfd6f43366..6418f74415d7 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1077,6 +1077,18 @@ static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = {
mdelay(2); /* Wait for 2ms */\
}
+static const struct net_device_ops de4x5_netdev_ops = {
+ .ndo_open = de4x5_open,
+ .ndo_stop = de4x5_close,
+ .ndo_start_xmit = de4x5_queue_pkt,
+ .ndo_get_stats = de4x5_get_stats,
+ .ndo_set_multicast_list = set_multicast_list,
+ .ndo_do_ioctl = de4x5_ioctl,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address= eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static int __devinit
de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
@@ -1258,13 +1270,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
/* The DE4X5-specific entries in the device structure. */
SET_NETDEV_DEV(dev, gendev);
- dev->open = &de4x5_open;
- dev->hard_start_xmit = &de4x5_queue_pkt;
- dev->stop = &de4x5_close;
- dev->get_stats = &de4x5_get_stats;
- dev->set_multicast_list = &set_multicast_list;
- dev->do_ioctl = &de4x5_ioctl;
-
+ dev->netdev_ops = &de4x5_netdev_ops;
dev->mem_start = 0;
/* Fill in the generic fields of the device structure. */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 28a5c51b43a0..2e5c99941f35 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -257,9 +257,6 @@ struct dmfe_board_info {
u8 wol_mode; /* user WOL settings */
struct timer_list timer;
- /* System defined statistic counter */
- struct net_device_stats stats;
-
/* Driver defined statistic counter */
unsigned long tx_fifo_underrun;
unsigned long tx_loss_carrier;
@@ -316,7 +313,6 @@ static u8 SF_mode; /* Special Function: 1:VLAN, 2:RX Flow Control
static int dmfe_open(struct DEVICE *);
static int dmfe_start_xmit(struct sk_buff *, struct DEVICE *);
static int dmfe_stop(struct DEVICE *);
-static struct net_device_stats * dmfe_get_stats(struct DEVICE *);
static void dmfe_set_filter_mode(struct DEVICE *);
static const struct ethtool_ops netdev_ethtool_ops;
static u16 read_srom_word(long ,int);
@@ -351,6 +347,19 @@ static void dmfe_set_phyxcer(struct dmfe_board_info *);
/* DM910X network board routine ---------------------------- */
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = dmfe_open,
+ .ndo_stop = dmfe_stop,
+ .ndo_start_xmit = dmfe_start_xmit,
+ .ndo_set_multicast_list = dmfe_set_filter_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = poll_dmfe,
+#endif
+};
+
/*
* Search DM910X board ,allocate space and register it
*/
@@ -442,14 +451,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
dev->base_addr = db->ioaddr;
dev->irq = pdev->irq;
pci_set_drvdata(pdev, dev);
- dev->open = &dmfe_open;
- dev->hard_start_xmit = &dmfe_start_xmit;
- dev->stop = &dmfe_stop;
- dev->get_stats = &dmfe_get_stats;
- dev->set_multicast_list = &dmfe_set_filter_mode;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &poll_dmfe;
-#endif
+ dev->netdev_ops = &netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
netif_carrier_off(dev);
spin_lock_init(&db->lock);
@@ -867,15 +869,15 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db)
/* A packet sent completed */
db->tx_packet_cnt--;
- db->stats.tx_packets++;
+ dev->stats.tx_packets++;
/* Transmit statistic counter */
if ( tdes0 != 0x7fffffff ) {
/* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
- db->stats.collisions += (tdes0 >> 3) & 0xf;
- db->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
+ dev->stats.collisions += (tdes0 >> 3) & 0xf;
+ dev->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
if (tdes0 & TDES0_ERR_MASK) {
- db->stats.tx_errors++;
+ dev->stats.tx_errors++;
if (tdes0 & 0x0002) { /* UnderRun */
db->tx_fifo_underrun++;
@@ -969,13 +971,13 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
if (rdes0 & 0x8000) {
/* This is a error packet */
//printk(DRV_NAME ": rdes0: %lx\n", rdes0);
- db->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (rdes0 & 1)
- db->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
if (rdes0 & 2)
- db->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (rdes0 & 0x80)
- db->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
}
if ( !(rdes0 & 0x8000) ||
@@ -1008,8 +1010,8 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- db->stats.rx_packets++;
- db->stats.rx_bytes += rxlen;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += rxlen;
}
} else {
/* Reuse SKB buffer when the packet is error */
@@ -1024,20 +1026,6 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
db->rx_ready_ptr = rxptr;
}
-
-/*
- * Get statistics from driver.
- */
-
-static struct net_device_stats * dmfe_get_stats(struct DEVICE *dev)
-{
- struct dmfe_board_info *db = netdev_priv(dev);
-
- DMFE_DBUG(0, "dmfe_get_stats", 0);
- return &db->stats;
-}
-
-
/*
* Set DM910X multicast address
*/
@@ -1161,7 +1149,7 @@ static void dmfe_timer(unsigned long data)
/* Operating Mode Check */
if ( (db->dm910x_chk_mode & 0x1) &&
- (db->stats.rx_packets > MAX_CHECK_PACKET) )
+ (dev->stats.rx_packets > MAX_CHECK_PACKET) )
db->dm910x_chk_mode = 0x4;
/* Dynamic reset DM910X : system error or transmit time-out */
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index ff84babb3ff3..bee75fa87a9c 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1225,6 +1225,22 @@ static int tulip_uli_dm_quirk(struct pci_dev *pdev)
return 0;
}
+static const struct net_device_ops tulip_netdev_ops = {
+ .ndo_open = tulip_open,
+ .ndo_start_xmit = tulip_start_xmit,
+ .ndo_tx_timeout = tulip_tx_timeout,
+ .ndo_stop = tulip_close,
+ .ndo_get_stats = tulip_get_stats,
+ .ndo_do_ioctl = private_ioctl,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = poll_tulip,
+#endif
+};
+
static int __devinit tulip_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1601,20 +1617,11 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
}
/* The Tulip-specific entries in the device structure. */
- dev->open = tulip_open;
- dev->hard_start_xmit = tulip_start_xmit;
- dev->tx_timeout = tulip_tx_timeout;
+ dev->netdev_ops = &tulip_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
#ifdef CONFIG_TULIP_NAPI
netif_napi_add(dev, &tp->napi, tulip_poll, 16);
#endif
- dev->stop = tulip_close;
- dev->get_stats = tulip_get_stats;
- dev->do_ioctl = private_ioctl;
- dev->set_multicast_list = set_rx_mode;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &poll_tulip;
-#endif
SET_ETHTOOL_OPS(dev, &ops);
if (register_netdev(dev))
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 00cbc5251dcc..030e02e63023 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -168,9 +168,6 @@ struct uli526x_board_info {
u8 wait_reset; /* Hardware failed, need to reset */
struct timer_list timer;
- /* System defined statistic counter */
- struct net_device_stats stats;
-
/* Driver defined statistic counter */
unsigned long tx_fifo_underrun;
unsigned long tx_loss_carrier;
@@ -220,7 +217,6 @@ static int mode = 8;
static int uli526x_open(struct net_device *);
static int uli526x_start_xmit(struct sk_buff *, struct net_device *);
static int uli526x_stop(struct net_device *);
-static struct net_device_stats * uli526x_get_stats(struct net_device *);
static void uli526x_set_filter_mode(struct net_device *);
static const struct ethtool_ops netdev_ethtool_ops;
static u16 read_srom_word(long, int);
@@ -251,6 +247,19 @@ static void uli526x_set_phyxcer(struct uli526x_board_info *);
/* ULI526X network board routine ---------------------------- */
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = uli526x_open,
+ .ndo_stop = uli526x_stop,
+ .ndo_start_xmit = uli526x_start_xmit,
+ .ndo_set_multicast_list = uli526x_set_filter_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = uli526x_poll,
+#endif
+};
+
/*
* Search ULI526X board, allocate space and register it
*/
@@ -335,15 +344,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
pci_set_drvdata(pdev, dev);
/* Register some necessary functions */
- dev->open = &uli526x_open;
- dev->hard_start_xmit = &uli526x_start_xmit;
- dev->stop = &uli526x_stop;
- dev->get_stats = &uli526x_get_stats;
- dev->set_multicast_list = &uli526x_set_filter_mode;
+ dev->netdev_ops = &netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &uli526x_poll;
-#endif
+
spin_lock_init(&db->lock);
@@ -733,7 +736,8 @@ static void uli526x_poll(struct net_device *dev)
* Free TX resource after TX complete
*/
-static void uli526x_free_tx_pkt(struct net_device *dev, struct uli526x_board_info * db)
+static void uli526x_free_tx_pkt(struct net_device *dev,
+ struct uli526x_board_info * db)
{
struct tx_desc *txptr;
u32 tdes0;
@@ -747,15 +751,15 @@ static void uli526x_free_tx_pkt(struct net_device *dev, struct uli526x_board_inf
/* A packet sent completed */
db->tx_packet_cnt--;
- db->stats.tx_packets++;
+ dev->stats.tx_packets++;
/* Transmit statistic counter */
if ( tdes0 != 0x7fffffff ) {
/* printk(DRV_NAME ": tdes0=%x\n", tdes0); */
- db->stats.collisions += (tdes0 >> 3) & 0xf;
- db->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
+ dev->stats.collisions += (tdes0 >> 3) & 0xf;
+ dev->stats.tx_bytes += le32_to_cpu(txptr->tdes1) & 0x7ff;
if (tdes0 & TDES0_ERR_MASK) {
- db->stats.tx_errors++;
+ dev->stats.tx_errors++;
if (tdes0 & 0x0002) { /* UnderRun */
db->tx_fifo_underrun++;
if ( !(db->cr6_data & CR6_SFT) ) {
@@ -825,13 +829,13 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
if (rdes0 & 0x8000) {
/* This is a error packet */
//printk(DRV_NAME ": rdes0: %lx\n", rdes0);
- db->stats.rx_errors++;
+ dev->stats.rx_errors++;
if (rdes0 & 1)
- db->stats.rx_fifo_errors++;
+ dev->stats.rx_fifo_errors++;
if (rdes0 & 2)
- db->stats.rx_crc_errors++;
+ dev->stats.rx_crc_errors++;
if (rdes0 & 0x80)
- db->stats.rx_length_errors++;
+ dev->stats.rx_length_errors++;
}
if ( !(rdes0 & 0x8000) ||
@@ -854,8 +858,8 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- db->stats.rx_packets++;
- db->stats.rx_bytes += rxlen;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += rxlen;
} else {
/* Reuse SKB buffer when the packet is error */
@@ -872,19 +876,6 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
/*
- * Get statistics from driver.
- */
-
-static struct net_device_stats * uli526x_get_stats(struct net_device *dev)
-{
- struct uli526x_board_info *db = netdev_priv(dev);
-
- ULI526X_DBUG(0, "uli526x_get_stats", 0);
- return &db->stats;
-}
-
-
-/*
* Set ULI526X multicast address
*/
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 022d99af8646..f467bf87817d 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -343,7 +343,18 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static const struct ethtool_ops netdev_ethtool_ops;
static int netdev_close(struct net_device *dev);
-
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = netdev_open,
+ .ndo_stop = netdev_close,
+ .ndo_start_xmit = start_tx,
+ .ndo_get_stats = get_stats,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_tx_timeout = tx_timeout,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
static int __devinit w840_probe1 (struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -420,14 +431,8 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
np->mii_if.force_media = 1;
/* The chip-specific entries in the device structure. */
- dev->open = &netdev_open;
- dev->hard_start_xmit = &start_tx;
- dev->stop = &netdev_close;
- dev->get_stats = &get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &netdev_ioctl;
+ dev->netdev_ops = &netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
- dev->tx_timeout = &tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
i = register_netdev(dev);
@@ -1555,7 +1560,7 @@ static void __devexit w840_remove1 (struct pci_dev *pdev)
* rtnl_lock, & netif_device_detach after the rtnl_unlock.
* - get_stats:
* spin_lock_irq(np->lock), doesn't touch hw if not present
- * - hard_start_xmit:
+ * - start_xmit:
* synchronize_irq + netif_tx_disable;
* - tx_timeout:
* netif_device_detach + netif_tx_disable;
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 13c8703ecb9f..c2ca9f40e40e 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -104,10 +104,8 @@ struct xircom_private {
*/
spinlock_t lock;
-
struct pci_dev *pdev;
struct net_device *dev;
- struct net_device_stats stats;
};
@@ -119,7 +117,6 @@ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev);
static int xircom_open(struct net_device *dev);
static int xircom_close(struct net_device *dev);
static void xircom_up(struct xircom_private *card);
-static struct net_device_stats *xircom_get_stats(struct net_device *dev);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void xircom_poll_controller(struct net_device *dev);
#endif
@@ -194,6 +191,18 @@ static const struct ethtool_ops netdev_ethtool_ops = {
.get_drvinfo = netdev_get_drvinfo,
};
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = xircom_open,
+ .ndo_stop = xircom_close,
+ .ndo_start_xmit = xircom_start_xmit,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = xircom_poll_controller,
+#endif
+};
+
/* xircom_probe is the code that gets called on device insertion.
it sets up the hardware and registers the device to the networklayer.
@@ -266,13 +275,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
read_mac_address(private);
setup_descriptors(private);
- dev->open = &xircom_open;
- dev->hard_start_xmit = &xircom_start_xmit;
- dev->stop = &xircom_close;
- dev->get_stats = &xircom_get_stats;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &xircom_poll_controller;
-#endif
+ dev->netdev_ops = &netdev_ops;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
pci_set_drvdata(pdev, dev);
@@ -497,14 +500,6 @@ static int xircom_close(struct net_device *dev)
}
-
-static struct net_device_stats *xircom_get_stats(struct net_device *dev)
-{
- struct xircom_private *card = netdev_priv(dev);
- return &card->stats;
-}
-
-
#ifdef CONFIG_NET_POLL_CONTROLLER
static void xircom_poll_controller(struct net_device *dev)
{
@@ -1193,7 +1188,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri
skb = dev_alloc_skb(pkt_len + 2);
if (skb == NULL) {
- card->stats.rx_dropped++;
+ dev->stats.rx_dropped++;
goto out;
}
skb_reserve(skb, 2);
@@ -1201,8 +1196,8 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- card->stats.rx_packets++;
- card->stats.rx_bytes += pkt_len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
out:
/* give the buffer back to the card */
@@ -1232,16 +1227,16 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p
#endif
if (status > 0) { /* bit 31 is 0 when done */
if (card->tx_skb[descnr]!=NULL) {
- card->stats.tx_bytes += card->tx_skb[descnr]->len;
+ dev->stats.tx_bytes += card->tx_skb[descnr]->len;
dev_kfree_skb_irq(card->tx_skb[descnr]);
}
card->tx_skb[descnr] = NULL;
/* Bit 8 in the status field is 1 if there was a collision */
if (status&(1<<8))
- card->stats.collisions++;
+ dev->stats.collisions++;
card->tx_buffer[4*descnr] = 0; /* descriptor is free again */
netif_wake_queue (dev);
- card->stats.tx_packets++;
+ dev->stats.tx_packets++;
}
leave("investigate_write_descriptor");
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 69f9a0ec764d..d7b81e4fdd56 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -213,7 +213,7 @@ static int check_filter(struct tap_filter *filter, const struct sk_buff *skb)
/* Network device part of the driver */
-static unsigned int tun_net_id;
+static int tun_net_id;
struct tun_net {
struct list_head dev_list;
};
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 0009f4e34433..3af9a9516ccb 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -2296,6 +2296,19 @@ out:
return mode;
}
+static const struct net_device_ops typhoon_netdev_ops = {
+ .ndo_open = typhoon_open,
+ .ndo_stop = typhoon_close,
+ .ndo_start_xmit = typhoon_start_tx,
+ .ndo_set_multicast_list = typhoon_set_rx_mode,
+ .ndo_tx_timeout = typhoon_tx_timeout,
+ .ndo_get_stats = typhoon_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = typhoon_set_mac_address,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_vlan_rx_register = typhoon_vlan_rx_register,
+};
+
static int __devinit
typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -2495,16 +2508,9 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* The chip-specific entries in the device structure. */
- dev->open = typhoon_open;
- dev->hard_start_xmit = typhoon_start_tx;
- dev->stop = typhoon_close;
- dev->set_multicast_list = typhoon_set_rx_mode;
- dev->tx_timeout = typhoon_tx_timeout;
+ dev->netdev_ops = &typhoon_netdev_ops;
netif_napi_add(dev, &tp->napi, typhoon_poll, 16);
dev->watchdog_timeo = TX_TIMEOUT;
- dev->get_stats = typhoon_get_stats;
- dev->set_mac_address = typhoon_set_mac_address;
- dev->vlan_rx_register = typhoon_vlan_rx_register;
SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 7d5a1303e30d..e87986867ba5 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -442,40 +442,30 @@ static void magic_packet_detection_enable(struct ucc_geth_private *ugeth)
{
struct ucc_fast_private *uccf;
struct ucc_geth __iomem *ug_regs;
- u32 maccfg2, uccm;
uccf = ugeth->uccf;
ug_regs = ugeth->ug_regs;
/* Enable interrupts for magic packet detection */
- uccm = in_be32(uccf->p_uccm);
- uccm |= UCCE_MPD;
- out_be32(uccf->p_uccm, uccm);
+ setbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
/* Enable magic packet detection */
- maccfg2 = in_be32(&ug_regs->maccfg2);
- maccfg2 |= MACCFG2_MPE;
- out_be32(&ug_regs->maccfg2, maccfg2);
+ setbits32(&ug_regs->maccfg2, MACCFG2_MPE);
}
static void magic_packet_detection_disable(struct ucc_geth_private *ugeth)
{
struct ucc_fast_private *uccf;
struct ucc_geth __iomem *ug_regs;
- u32 maccfg2, uccm;
uccf = ugeth->uccf;
ug_regs = ugeth->ug_regs;
/* Disable interrupts for magic packet detection */
- uccm = in_be32(uccf->p_uccm);
- uccm &= ~UCCE_MPD;
- out_be32(uccf->p_uccm, uccm);
+ clrbits32(uccf->p_uccm, UCC_GETH_UCCE_MPD);
/* Disable magic packet detection */
- maccfg2 = in_be32(&ug_regs->maccfg2);
- maccfg2 &= ~MACCFG2_MPE;
- out_be32(&ug_regs->maccfg2, maccfg2);
+ clrbits32(&ug_regs->maccfg2, MACCFG2_MPE);
}
#endif /* MAGIC_PACKET */
@@ -585,7 +575,8 @@ static void get_statistics(struct ucc_geth_private *ugeth,
/* Hardware only if user handed pointer and driver actually
gathers hardware statistics */
- if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) {
+ if (hardware_statistics &&
+ (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) {
hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
@@ -1181,9 +1172,7 @@ int init_flow_control_params(u32 automatic_flow_control_mode,
out_be32(uempr_register, value);
/* Set UPSMR register */
- value = in_be32(upsmr_register);
- value |= automatic_flow_control_mode;
- out_be32(upsmr_register, value);
+ setbits32(upsmr_register, automatic_flow_control_mode);
value = in_be32(maccfg1_register);
if (rx_flow_control_enable)
@@ -1200,14 +1189,11 @@ static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
u32 __iomem *upsmr_register,
u16 __iomem *uescr_register)
{
- u32 upsmr_value = 0;
u16 uescr_value = 0;
+
/* Enable hardware statistics gathering if requested */
- if (enable_hardware_statistics) {
- upsmr_value = in_be32(upsmr_register);
- upsmr_value |= UPSMR_HSE;
- out_be32(upsmr_register, upsmr_value);
- }
+ if (enable_hardware_statistics)
+ setbits32(upsmr_register, UCC_GETH_UPSMR_HSE);
/* Clear hardware statistics counters */
uescr_value = in_be16(uescr_register);
@@ -1233,23 +1219,17 @@ static int init_firmware_statistics_gathering_mode(int
{
/* Note: this function does not check if */
/* the parameters it receives are NULL */
- u16 temoder_value;
- u32 remoder_value;
if (enable_tx_firmware_statistics) {
out_be32(tx_rmon_base_ptr,
tx_firmware_statistics_structure_address);
- temoder_value = in_be16(temoder_register);
- temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE;
- out_be16(temoder_register, temoder_value);
+ setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE);
}
if (enable_rx_firmware_statistics) {
out_be32(rx_rmon_base_ptr,
rx_firmware_statistics_structure_address);
- remoder_value = in_be32(remoder_register);
- remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE;
- out_be32(remoder_register, remoder_value);
+ setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE);
}
return 0;
@@ -1316,15 +1296,12 @@ static int init_check_frame_length_mode(int length_check,
static int init_preamble_length(u8 preamble_length,
u32 __iomem *maccfg2_register)
{
- u32 value = 0;
-
if ((preamble_length < 3) || (preamble_length > 7))
return -EINVAL;
- value = in_be32(maccfg2_register);
- value &= ~MACCFG2_PREL_MASK;
- value |= (preamble_length << MACCFG2_PREL_SHIFT);
- out_be32(maccfg2_register, value);
+ clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK,
+ preamble_length << MACCFG2_PREL_SHIFT);
+
return 0;
}
@@ -1337,19 +1314,19 @@ static int init_rx_parameters(int reject_broadcast,
value = in_be32(upsmr_register);
if (reject_broadcast)
- value |= UPSMR_BRO;
+ value |= UCC_GETH_UPSMR_BRO;
else
- value &= ~UPSMR_BRO;
+ value &= ~UCC_GETH_UPSMR_BRO;
if (receive_short_frames)
- value |= UPSMR_RSH;
+ value |= UCC_GETH_UPSMR_RSH;
else
- value &= ~UPSMR_RSH;
+ value &= ~UCC_GETH_UPSMR_RSH;
if (promiscuous)
- value |= UPSMR_PRO;
+ value |= UCC_GETH_UPSMR_PRO;
else
- value &= ~UPSMR_PRO;
+ value &= ~UCC_GETH_UPSMR_PRO;
out_be32(upsmr_register, value);
@@ -1410,26 +1387,27 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
/* Set UPSMR */
upsmr = in_be32(&uf_regs->upsmr);
- upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM);
+ upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
+ UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- upsmr |= UPSMR_RPM;
+ upsmr |= UCC_GETH_UPSMR_RPM;
switch (ugeth->max_speed) {
case SPEED_10:
- upsmr |= UPSMR_R10M;
+ upsmr |= UCC_GETH_UPSMR_R10M;
/* FALLTHROUGH */
case SPEED_100:
if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI)
- upsmr |= UPSMR_RMM;
+ upsmr |= UCC_GETH_UPSMR_RMM;
}
}
if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- upsmr |= UPSMR_TBIM;
+ upsmr |= UCC_GETH_UPSMR_TBIM;
}
out_be32(&uf_regs->upsmr, upsmr);
@@ -1517,9 +1495,9 @@ static void adjust_link(struct net_device *dev)
(ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
(ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
if (phydev->speed == SPEED_10)
- upsmr |= UPSMR_R10M;
+ upsmr |= UCC_GETH_UPSMR_R10M;
else
- upsmr &= ~(UPSMR_R10M);
+ upsmr &= ~UCC_GETH_UPSMR_R10M;
}
break;
default:
@@ -1558,6 +1536,11 @@ static void adjust_link(struct net_device *dev)
static int init_phy(struct net_device *dev)
{
struct ucc_geth_private *priv = netdev_priv(dev);
+ struct device_node *np = priv->node;
+ struct device_node *phy, *mdio;
+ const phandle *ph;
+ char bus_name[MII_BUS_ID_SIZE];
+ const unsigned int *id;
struct phy_device *phydev;
char phy_id[BUS_ID_SIZE];
@@ -1565,8 +1548,18 @@ static int init_phy(struct net_device *dev)
priv->oldspeed = 0;
priv->oldduplex = -1;
- snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->ug_info->mdio_bus,
- priv->ug_info->phy_address);
+ ph = of_get_property(np, "phy-handle", NULL);
+ phy = of_find_node_by_phandle(*ph);
+ mdio = of_get_parent(phy);
+
+ id = of_get_property(phy, "reg", NULL);
+
+ of_node_put(phy);
+ of_node_put(mdio);
+
+ uec_mdio_bus_name(bus_name, mdio);
+ snprintf(phy_id, sizeof(phy_id), "%s:%02x",
+ bus_name, *id);
phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface);
@@ -1602,10 +1595,8 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
uccf = ugeth->uccf;
/* Mask GRACEFUL STOP TX interrupt bit and clear it */
- temp = in_be32(uccf->p_uccm);
- temp &= ~UCCE_GRA;
- out_be32(uccf->p_uccm, temp);
- out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */
+ clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA);
+ out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */
/* Issue host command */
cecr_subblock =
@@ -1617,7 +1608,7 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
do {
msleep(10);
temp = in_be32(uccf->p_ucce);
- } while (!(temp & UCCE_GRA) && --i);
+ } while (!(temp & UCC_GETH_UCCE_GRA) && --i);
uccf->stopped_tx = 1;
@@ -1975,12 +1966,9 @@ static void ucc_geth_set_multi(struct net_device *dev)
uf_regs = ugeth->uccf->uf_regs;
if (dev->flags & IFF_PROMISC) {
-
- out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr) | UPSMR_PRO);
-
+ setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
} else {
-
- out_be32(&uf_regs->upsmr, in_be32(&uf_regs->upsmr)&~UPSMR_PRO);
+ clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
p_82xx_addr_filt =
(struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->
@@ -2020,7 +2008,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
{
struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
struct phy_device *phydev = ugeth->phydev;
- u32 tempval;
ugeth_vdbg("%s: IN", __func__);
@@ -2037,9 +2024,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
out_be32(ugeth->uccf->p_ucce, 0xffffffff);
/* Disable Rx and Tx */
- tempval = in_be32(&ug_regs->maccfg1);
- tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
- out_be32(&ug_regs->maccfg1, tempval);
+ clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
ucc_geth_memclean(ugeth);
}
@@ -2153,10 +2138,10 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
/* Generate uccm_mask for receive */
uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
for (i = 0; i < ug_info->numQueuesRx; i++)
- uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i);
+ uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i);
for (i = 0; i < ug_info->numQueuesTx; i++)
- uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
+ uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i);
/* Initialize the general fast UCC block. */
if (ucc_fast_init(uf_info, &ugeth->uccf)) {
if (netif_msg_probe(ugeth))
@@ -2185,7 +2170,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
struct ucc_geth __iomem *ug_regs;
int ret_val = -EINVAL;
u32 remoder = UCC_GETH_REMODER_INIT;
- u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
+ u32 init_enet_pram_offset, cecr_subblock, command;
u32 ifstat, i, j, size, l2qt, l3qt, length;
u16 temoder = UCC_GETH_TEMODER_INIT;
u16 test;
@@ -2281,10 +2266,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
&uf_regs->upsmr,
&ug_regs->uempr, &ug_regs->maccfg1);
- maccfg1 = in_be32(&ug_regs->maccfg1);
- maccfg1 |= MACCFG1_ENABLE_RX;
- maccfg1 |= MACCFG1_ENABLE_TX;
- out_be32(&ug_regs->maccfg1, maccfg1);
+ setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
/* Set IPGIFG */
/* For more details see the hardware spec. */
@@ -3274,7 +3256,6 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ)
static int ucc_geth_poll(struct napi_struct *napi, int budget)
{
struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi);
- struct net_device *dev = ugeth->dev;
struct ucc_geth_info *ug_info;
int howmany, i;
@@ -3285,14 +3266,8 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget)
howmany += ucc_geth_rx(ugeth, i, budget - howmany);
if (howmany < budget) {
- struct ucc_fast_private *uccf;
- u32 uccm;
-
netif_rx_complete(napi);
- uccf = ugeth->uccf;
- uccm = in_be32(uccf->p_uccm);
- uccm |= UCCE_RX_EVENTS;
- out_be32(uccf->p_uccm, uccm);
+ setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS);
}
return howmany;
@@ -3332,7 +3307,7 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
/* Tx event processing */
if (ucce & UCCE_TX_EVENTS) {
spin_lock(&ugeth->lock);
- tx_mask = UCCE_TXBF_SINGLE_MASK;
+ tx_mask = UCC_GETH_UCCE_TXB0;
for (i = 0; i < ug_info->numQueuesTx; i++) {
if (ucce & tx_mask)
ucc_geth_tx(dev, i);
@@ -3344,12 +3319,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
/* Errors and other events */
if (ucce & UCCE_OTHER) {
- if (ucce & UCCE_BSY) {
+ if (ucce & UCC_GETH_UCCE_BSY)
dev->stats.rx_errors++;
- }
- if (ucce & UCCE_TXE) {
+ if (ucce & UCC_GETH_UCCE_TXE)
dev->stats.tx_errors++;
- }
}
return IRQ_HANDLED;
@@ -3790,6 +3763,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
ugeth->ug_info = ug_info;
ugeth->dev = dev;
+ ugeth->node = np;
return 0;
}
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index d74d2f7cb739..16cbe42ba43c 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -162,92 +162,27 @@ struct ucc_geth {
boundary */
/* UCC GETH Event Register */
-#define UCCE_MPD 0x80000000 /* Magic packet
- detection */
-#define UCCE_SCAR 0x40000000
-#define UCCE_GRA 0x20000000 /* Tx graceful
- stop
- complete */
-#define UCCE_CBPR 0x10000000
-#define UCCE_BSY 0x08000000
-#define UCCE_RXC 0x04000000
-#define UCCE_TXC 0x02000000
-#define UCCE_TXE 0x01000000
-#define UCCE_TXB7 0x00800000
-#define UCCE_TXB6 0x00400000
-#define UCCE_TXB5 0x00200000
-#define UCCE_TXB4 0x00100000
-#define UCCE_TXB3 0x00080000
-#define UCCE_TXB2 0x00040000
-#define UCCE_TXB1 0x00020000
-#define UCCE_TXB0 0x00010000
-#define UCCE_RXB7 0x00008000
-#define UCCE_RXB6 0x00004000
-#define UCCE_RXB5 0x00002000
-#define UCCE_RXB4 0x00001000
-#define UCCE_RXB3 0x00000800
-#define UCCE_RXB2 0x00000400
-#define UCCE_RXB1 0x00000200
-#define UCCE_RXB0 0x00000100
-#define UCCE_RXF7 0x00000080
-#define UCCE_RXF6 0x00000040
-#define UCCE_RXF5 0x00000020
-#define UCCE_RXF4 0x00000010
-#define UCCE_RXF3 0x00000008
-#define UCCE_RXF2 0x00000004
-#define UCCE_RXF1 0x00000002
-#define UCCE_RXF0 0x00000001
-
-#define UCCE_RXBF_SINGLE_MASK (UCCE_RXF0)
-#define UCCE_TXBF_SINGLE_MASK (UCCE_TXB0)
-
-#define UCCE_TXB (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\
- UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0)
-#define UCCE_RXB (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\
- UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0)
-#define UCCE_RXF (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\
- UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0)
-#define UCCE_OTHER (UCCE_SCAR | UCCE_GRA | UCCE_CBPR | UCCE_BSY |\
- UCCE_RXC | UCCE_TXC | UCCE_TXE)
-
-#define UCCE_RX_EVENTS (UCCE_RXF | UCCE_BSY)
-#define UCCE_TX_EVENTS (UCCE_TXB | UCCE_TXE)
-
-/* UCC GETH UPSMR (Protocol Specific Mode Register) */
-#define UPSMR_ECM 0x04000000 /* Enable CAM
- Miss or
- Enable
- Filtering
- Miss */
-#define UPSMR_HSE 0x02000000 /* Hardware
- Statistics
- Enable */
-#define UPSMR_PRO 0x00400000 /* Promiscuous*/
-#define UPSMR_CAP 0x00200000 /* CAM polarity
- */
-#define UPSMR_RSH 0x00100000 /* Receive
- Short Frames
- */
-#define UPSMR_RPM 0x00080000 /* Reduced Pin
- Mode
- interfaces */
-#define UPSMR_R10M 0x00040000 /* RGMII/RMII
- 10 Mode */
-#define UPSMR_RLPB 0x00020000 /* RMII
- Loopback
- Mode */
-#define UPSMR_TBIM 0x00010000 /* Ten-bit
- Interface
- Mode */
-#define UPSMR_RMM 0x00001000 /* RMII/RGMII
- Mode */
-#define UPSMR_CAM 0x00000400 /* CAM Address
- Matching */
-#define UPSMR_BRO 0x00000200 /* Broadcast
- Address */
-#define UPSMR_RES1 0x00002000 /* Reserved
- feild - must
- be 1 */
+#define UCCE_TXB (UCC_GETH_UCCE_TXB7 | UCC_GETH_UCCE_TXB6 | \
+ UCC_GETH_UCCE_TXB5 | UCC_GETH_UCCE_TXB4 | \
+ UCC_GETH_UCCE_TXB3 | UCC_GETH_UCCE_TXB2 | \
+ UCC_GETH_UCCE_TXB1 | UCC_GETH_UCCE_TXB0)
+
+#define UCCE_RXB (UCC_GETH_UCCE_RXB7 | UCC_GETH_UCCE_RXB6 | \
+ UCC_GETH_UCCE_RXB5 | UCC_GETH_UCCE_RXB4 | \
+ UCC_GETH_UCCE_RXB3 | UCC_GETH_UCCE_RXB2 | \
+ UCC_GETH_UCCE_RXB1 | UCC_GETH_UCCE_RXB0)
+
+#define UCCE_RXF (UCC_GETH_UCCE_RXF7 | UCC_GETH_UCCE_RXF6 | \
+ UCC_GETH_UCCE_RXF5 | UCC_GETH_UCCE_RXF4 | \
+ UCC_GETH_UCCE_RXF3 | UCC_GETH_UCCE_RXF2 | \
+ UCC_GETH_UCCE_RXF1 | UCC_GETH_UCCE_RXF0)
+
+#define UCCE_OTHER (UCC_GETH_UCCE_SCAR | UCC_GETH_UCCE_GRA | \
+ UCC_GETH_UCCE_CBPR | UCC_GETH_UCCE_BSY | \
+ UCC_GETH_UCCE_RXC | UCC_GETH_UCCE_TXC | UCC_GETH_UCCE_TXE)
+
+#define UCCE_RX_EVENTS (UCCE_RXF | UCC_GETH_UCCE_BSY)
+#define UCCE_TX_EVENTS (UCCE_TXB | UCC_GETH_UCCE_TXE)
/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control
@@ -945,9 +880,10 @@ struct ucc_geth_hardware_statistics {
#define UCC_GETH_REMODER_INIT 0 /* bits that must be
set */
#define UCC_GETH_TEMODER_INIT 0xC000 /* bits that must */
-#define UCC_GETH_UPSMR_INIT (UPSMR_RES1) /* Start value
- for this
- register */
+
+/* Initial value for UPSMR */
+#define UCC_GETH_UPSMR_INIT UCC_GETH_UPSMR_RES1
+
#define UCC_GETH_MACCFG1_INIT 0
#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1)
@@ -1250,6 +1186,8 @@ struct ucc_geth_private {
int oldspeed;
int oldduplex;
int oldlink;
+
+ struct device_node *node;
};
void uec_set_ethtool_ops(struct net_device *netdev);
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index c001d261366b..54635911305c 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -156,7 +156,7 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma
if (err)
goto reg_map_fail;
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+ uec_mdio_bus_name(new_bus->id, np);
new_bus->irq = kmalloc(32 * sizeof(int), GFP_KERNEL);
@@ -283,3 +283,13 @@ void uec_mdio_exit(void)
{
of_unregister_platform_driver(&uec_mdio_driver);
}
+
+void uec_mdio_bus_name(char *name, struct device_node *np)
+{
+ const u32 *reg;
+
+ reg = of_get_property(np, "reg", NULL);
+
+ snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0);
+}
+
diff --git a/drivers/net/ucc_geth_mii.h b/drivers/net/ucc_geth_mii.h
index 1e45b2028a50..840cf80235b7 100644
--- a/drivers/net/ucc_geth_mii.h
+++ b/drivers/net/ucc_geth_mii.h
@@ -97,4 +97,5 @@ int uec_mdio_read(struct mii_bus *bus, int mii_id, int regnum);
int uec_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value);
int __init uec_mdio_init(void);
void uec_mdio_exit(void);
+void uec_mdio_bus_name(char *name, struct device_node *np);
#endif /* __UEC_MII_H */
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index edd244f3acb5..5b67bbf1987e 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -23,7 +23,7 @@
#include <linux/usb/usbnet.h>
/* datasheet:
- http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
+ http://ptm2.cc.utu.fi/ftp/network/cards/DM9601/From_NET/DM9601-DS-P01-930914.pdf
*/
/* control requests */
@@ -397,16 +397,24 @@ static void dm9601_set_multicast(struct net_device *net)
dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
}
+static void __dm9601_set_mac_address(struct usbnet *dev)
+{
+ dm_write_async(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
+}
+
static int dm9601_set_mac_address(struct net_device *net, void *p)
{
struct sockaddr *addr = p;
struct usbnet *dev = netdev_priv(net);
- if (!is_valid_ether_addr(addr->sa_data))
+ if (!is_valid_ether_addr(addr->sa_data)) {
+ dev_err(&net->dev, "not setting invalid mac address %pM\n",
+ addr->sa_data);
return -EINVAL;
+ }
memcpy(net->dev_addr, addr->sa_data, net->addr_len);
- dm_write_async(dev, DM_PHY_ADDR, net->addr_len, net->dev_addr);
+ __dm9601_set_mac_address(dev);
return 0;
}
@@ -414,6 +422,7 @@ static int dm9601_set_mac_address(struct net_device *net, void *p)
static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
{
int ret;
+ u8 mac[ETH_ALEN];
ret = usbnet_get_endpoints(dev, intf);
if (ret)
@@ -438,12 +447,24 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
udelay(20);
/* read MAC */
- if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr) < 0) {
+ if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, mac) < 0) {
printk(KERN_ERR "Error reading MAC address\n");
ret = -ENODEV;
goto out;
}
+ /*
+ * Overwrite the auto-generated address only with good ones.
+ */
+ if (is_valid_ether_addr(mac))
+ memcpy(dev->net->dev_addr, mac, ETH_ALEN);
+ else {
+ printk(KERN_WARNING
+ "dm9601: No valid MAC address in EEPROM, using %pM\n",
+ dev->net->dev_addr);
+ __dm9601_set_mac_address(dev);
+ }
+
/* power up phy */
dm_write_reg(dev, DM_GPR_CTRL, 1);
dm_write_reg(dev, DM_GPR_DATA, 0);
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 9f7896a25f1b..fe98acaead97 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -3,6 +3,8 @@
* Driver for Option High Speed Mobile Devices.
*
* Copyright (C) 2008 Option International
+ * Filip Aben <f.aben@option.com>
+ * Denis Joseph Barrow <d.barow@option.com>
* Copyright (C) 2007 Andrew Bird (Sphere Systems Ltd)
* <ajb@spheresystems.co.uk>
* Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
@@ -39,8 +41,11 @@
* port is opened, as this have a huge impact on the network port
* throughput.
*
- * Interface 2: Standard modem interface - circuit switched interface, should
- * not be used.
+ * Interface 2: Standard modem interface - circuit switched interface, this
+ * can be used to make a standard ppp connection however it
+ * should not be used in conjunction with the IP network interface
+ * enabled for USB performance reasons i.e. if using this set
+ * ideally disable_net=1.
*
*****************************************************************************/
@@ -63,6 +68,8 @@
#include <linux/usb/cdc.h>
#include <net/arp.h>
#include <asm/byteorder.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
#define DRIVER_VERSION "1.2"
@@ -182,6 +189,41 @@ enum rx_ctrl_state{
RX_PENDING
};
+#define BM_REQUEST_TYPE (0xa1)
+#define B_NOTIFICATION (0x20)
+#define W_VALUE (0x0)
+#define W_INDEX (0x2)
+#define W_LENGTH (0x2)
+
+#define B_OVERRUN (0x1<<6)
+#define B_PARITY (0x1<<5)
+#define B_FRAMING (0x1<<4)
+#define B_RING_SIGNAL (0x1<<3)
+#define B_BREAK (0x1<<2)
+#define B_TX_CARRIER (0x1<<1)
+#define B_RX_CARRIER (0x1<<0)
+
+struct hso_serial_state_notification {
+ u8 bmRequestType;
+ u8 bNotification;
+ u16 wValue;
+ u16 wIndex;
+ u16 wLength;
+ u16 UART_state_bitmap;
+} __attribute__((packed));
+
+struct hso_tiocmget {
+ struct mutex mutex;
+ wait_queue_head_t waitq;
+ int intr_completed;
+ struct usb_endpoint_descriptor *endp;
+ struct urb *urb;
+ struct hso_serial_state_notification serial_state_notification;
+ u16 prev_UART_state_bitmap;
+ struct uart_icount icount;
+};
+
+
struct hso_serial {
struct hso_device *parent;
int magic;
@@ -219,6 +261,7 @@ struct hso_serial {
spinlock_t serial_lock;
int (*write_data) (struct hso_serial *serial);
+ struct hso_tiocmget *tiocmget;
/* Hacks required to get flow control
* working on the serial receive buffers
* so as not to drop characters on the floor.
@@ -305,7 +348,7 @@ static void async_get_intf(struct work_struct *data);
static void async_put_intf(struct work_struct *data);
static int hso_put_activity(struct hso_device *hso_dev);
static int hso_get_activity(struct hso_device *hso_dev);
-
+static void tiocmget_intr_callback(struct urb *urb);
/*****************************************************************************/
/* Helping functions */
/*****************************************************************************/
@@ -362,8 +405,6 @@ static struct tty_driver *tty_drv;
static struct hso_device *serial_table[HSO_SERIAL_TTY_MINORS];
static struct hso_device *network_table[HSO_MAX_NET_DEVICES];
static spinlock_t serial_table_lock;
-static struct ktermios *hso_serial_termios[HSO_SERIAL_TTY_MINORS];
-static struct ktermios *hso_serial_termios_locked[HSO_SERIAL_TTY_MINORS];
static const s32 default_port_spec[] = {
HSO_INTF_MUX | HSO_PORT_NETWORK,
@@ -414,6 +455,7 @@ static const struct usb_device_id hso_ids[] = {
{icon321_port_device(0x0af0, 0xd033)}, /* Icon-322 */
{USB_DEVICE(0x0af0, 0x7301)}, /* GE40x */
{USB_DEVICE(0x0af0, 0x7361)}, /* GE40x */
+ {USB_DEVICE(0x0af0, 0x7381)}, /* GE40x */
{USB_DEVICE(0x0af0, 0x7401)}, /* GI 0401 */
{USB_DEVICE(0x0af0, 0x7501)}, /* GTM 382 */
{USB_DEVICE(0x0af0, 0x7601)}, /* GE40x */
@@ -421,7 +463,8 @@ static const struct usb_device_id hso_ids[] = {
{USB_DEVICE(0x0af0, 0x7801)},
{USB_DEVICE(0x0af0, 0x7901)},
{USB_DEVICE(0x0af0, 0x7361)},
- {icon321_port_device(0x0af0, 0xd051)},
+ {USB_DEVICE(0x0af0, 0xd057)},
+ {USB_DEVICE(0x0af0, 0xd055)},
{}
};
MODULE_DEVICE_TABLE(usb, hso_ids);
@@ -1009,23 +1052,11 @@ static void read_bulk_callback(struct urb *urb)
/* Serial driver functions */
-static void _hso_serial_set_termios(struct tty_struct *tty,
- struct ktermios *old)
+static void hso_init_termios(struct ktermios *termios)
{
- struct hso_serial *serial = get_serial_by_tty(tty);
- struct ktermios *termios;
-
- if ((!tty) || (!tty->termios) || (!serial)) {
- printk(KERN_ERR "%s: no tty structures", __func__);
- return;
- }
-
- D4("port %d", serial->minor);
-
/*
* The default requirements for this device are:
*/
- termios = tty->termios;
termios->c_iflag &=
~(IGNBRK /* disable ignore break */
| BRKINT /* disable break causes interrupt */
@@ -1057,15 +1088,38 @@ static void _hso_serial_set_termios(struct tty_struct *tty,
termios->c_cflag |= CS8; /* character size 8 bits */
/* baud rate 115200 */
- tty_encode_baud_rate(serial->tty, 115200, 115200);
+ tty_termios_encode_baud_rate(termios, 115200, 115200);
+}
+
+static void _hso_serial_set_termios(struct tty_struct *tty,
+ struct ktermios *old)
+{
+ struct hso_serial *serial = get_serial_by_tty(tty);
+ struct ktermios *termios;
+
+ if (!serial) {
+ printk(KERN_ERR "%s: no tty structures", __func__);
+ return;
+ }
+
+ D4("port %d", serial->minor);
/*
- * Force low_latency on; otherwise the pushes are scheduled;
- * this is bad as it opens up the possibility of dropping bytes
- * on the floor. We don't want to drop bytes on the floor. :)
+ * Fix up unsupported bits
*/
- serial->tty->low_latency = 1;
- return;
+ termios = tty->termios;
+ termios->c_iflag &= ~IXON; /* disable enable XON/XOFF flow control */
+
+ termios->c_cflag &=
+ ~(CSIZE /* no size */
+ | PARENB /* disable parity bit */
+ | CBAUD /* clear current baud rate */
+ | CBAUDEX); /* clear current buad rate */
+
+ termios->c_cflag |= CS8; /* character size 8 bits */
+
+ /* baud rate 115200 */
+ tty_encode_baud_rate(tty, 115200, 115200);
}
static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb)
@@ -1228,6 +1282,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
/* sanity check */
if (serial == NULL || serial->magic != HSO_SERIAL_MAGIC) {
+ WARN_ON(1);
tty->driver_data = NULL;
D1("Failed to open port");
return -ENODEV;
@@ -1242,8 +1297,11 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
kref_get(&serial->parent->ref);
/* setup */
+ spin_lock_irq(&serial->serial_lock);
tty->driver_data = serial;
- serial->tty = tty;
+ tty_kref_put(serial->tty);
+ serial->tty = tty_kref_get(tty);
+ spin_unlock_irq(&serial->serial_lock);
/* check for port already opened, if not set the termios */
serial->open_count++;
@@ -1285,6 +1343,10 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
D1("Closing serial port");
+ /* Open failed, no close cleanup required */
+ if (serial == NULL)
+ return;
+
mutex_lock(&serial->parent->mutex);
usb_gone = serial->parent->usb_gone;
@@ -1297,10 +1359,13 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp)
kref_put(&serial->parent->ref, hso_serial_ref_free);
if (serial->open_count <= 0) {
serial->open_count = 0;
- if (serial->tty) {
+ spin_lock_irq(&serial->serial_lock);
+ if (serial->tty == tty) {
serial->tty->driver_data = NULL;
serial->tty = NULL;
+ tty_kref_put(tty);
}
+ spin_unlock_irq(&serial->serial_lock);
if (!usb_gone)
hso_stop_serial_device(serial->parent);
tasklet_kill(&serial->unthrottle_tasklet);
@@ -1400,25 +1465,217 @@ static int hso_serial_chars_in_buffer(struct tty_struct *tty)
return chars;
}
+int tiocmget_submit_urb(struct hso_serial *serial,
+ struct hso_tiocmget *tiocmget,
+ struct usb_device *usb)
+{
+ int result;
+
+ if (serial->parent->usb_gone)
+ return -ENODEV;
+ usb_fill_int_urb(tiocmget->urb, usb,
+ usb_rcvintpipe(usb,
+ tiocmget->endp->
+ bEndpointAddress & 0x7F),
+ &tiocmget->serial_state_notification,
+ sizeof(struct hso_serial_state_notification),
+ tiocmget_intr_callback, serial,
+ tiocmget->endp->bInterval);
+ result = usb_submit_urb(tiocmget->urb, GFP_ATOMIC);
+ if (result) {
+ dev_warn(&usb->dev, "%s usb_submit_urb failed %d\n", __func__,
+ result);
+ }
+ return result;
+
+}
+
+static void tiocmget_intr_callback(struct urb *urb)
+{
+ struct hso_serial *serial = urb->context;
+ struct hso_tiocmget *tiocmget;
+ int status = urb->status;
+ u16 UART_state_bitmap, prev_UART_state_bitmap;
+ struct uart_icount *icount;
+ struct hso_serial_state_notification *serial_state_notification;
+ struct usb_device *usb;
+
+ /* Sanity checks */
+ if (!serial)
+ return;
+ if (status) {
+ log_usb_status(status, __func__);
+ return;
+ }
+ tiocmget = serial->tiocmget;
+ if (!tiocmget)
+ return;
+ usb = serial->parent->usb;
+ serial_state_notification = &tiocmget->serial_state_notification;
+ if (serial_state_notification->bmRequestType != BM_REQUEST_TYPE ||
+ serial_state_notification->bNotification != B_NOTIFICATION ||
+ le16_to_cpu(serial_state_notification->wValue) != W_VALUE ||
+ le16_to_cpu(serial_state_notification->wIndex) != W_INDEX ||
+ le16_to_cpu(serial_state_notification->wLength) != W_LENGTH) {
+ dev_warn(&usb->dev,
+ "hso received invalid serial state notification\n");
+ DUMP(serial_state_notification,
+ sizeof(hso_serial_state_notifation))
+ } else {
+
+ UART_state_bitmap = le16_to_cpu(serial_state_notification->
+ UART_state_bitmap);
+ prev_UART_state_bitmap = tiocmget->prev_UART_state_bitmap;
+ icount = &tiocmget->icount;
+ spin_lock(&serial->serial_lock);
+ if ((UART_state_bitmap & B_OVERRUN) !=
+ (prev_UART_state_bitmap & B_OVERRUN))
+ icount->parity++;
+ if ((UART_state_bitmap & B_PARITY) !=
+ (prev_UART_state_bitmap & B_PARITY))
+ icount->parity++;
+ if ((UART_state_bitmap & B_FRAMING) !=
+ (prev_UART_state_bitmap & B_FRAMING))
+ icount->frame++;
+ if ((UART_state_bitmap & B_RING_SIGNAL) &&
+ !(prev_UART_state_bitmap & B_RING_SIGNAL))
+ icount->rng++;
+ if ((UART_state_bitmap & B_BREAK) !=
+ (prev_UART_state_bitmap & B_BREAK))
+ icount->brk++;
+ if ((UART_state_bitmap & B_TX_CARRIER) !=
+ (prev_UART_state_bitmap & B_TX_CARRIER))
+ icount->dsr++;
+ if ((UART_state_bitmap & B_RX_CARRIER) !=
+ (prev_UART_state_bitmap & B_RX_CARRIER))
+ icount->dcd++;
+ tiocmget->prev_UART_state_bitmap = UART_state_bitmap;
+ spin_unlock(&serial->serial_lock);
+ tiocmget->intr_completed = 1;
+ wake_up_interruptible(&tiocmget->waitq);
+ }
+ memset(serial_state_notification, 0,
+ sizeof(struct hso_serial_state_notification));
+ tiocmget_submit_urb(serial,
+ tiocmget,
+ serial->parent->usb);
+}
+
+/*
+ * next few functions largely stolen from drivers/serial/serial_core.c
+ */
+/* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+ * - mask passed in arg for lines of interest
+ * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+ * Caller should use TIOCGICOUNT to see which one it was
+ */
+static int
+hso_wait_modem_status(struct hso_serial *serial, unsigned long arg)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct uart_icount cprev, cnow;
+ struct hso_tiocmget *tiocmget;
+ int ret;
+
+ tiocmget = serial->tiocmget;
+ if (!tiocmget)
+ return -ENOENT;
+ /*
+ * note the counters on entry
+ */
+ spin_lock_irq(&serial->serial_lock);
+ memcpy(&cprev, &tiocmget->icount, sizeof(struct uart_icount));
+ spin_unlock_irq(&serial->serial_lock);
+ add_wait_queue(&tiocmget->waitq, &wait);
+ for (;;) {
+ spin_lock_irq(&serial->serial_lock);
+ memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
+ spin_unlock_irq(&serial->serial_lock);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd))) {
+ ret = 0;
+ break;
+ }
+ schedule();
+ /* see if a signal did it */
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ cprev = cnow;
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&tiocmget->waitq, &wait);
+
+ return ret;
+}
+
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+static int hso_get_count(struct hso_serial *serial,
+ struct serial_icounter_struct __user *icnt)
+{
+ struct serial_icounter_struct icount;
+ struct uart_icount cnow;
+ struct hso_tiocmget *tiocmget = serial->tiocmget;
+
+ if (!tiocmget)
+ return -ENOENT;
+ spin_lock_irq(&serial->serial_lock);
+ memcpy(&cnow, &tiocmget->icount, sizeof(struct uart_icount));
+ spin_unlock_irq(&serial->serial_lock);
+
+ icount.cts = cnow.cts;
+ icount.dsr = cnow.dsr;
+ icount.rng = cnow.rng;
+ icount.dcd = cnow.dcd;
+ icount.rx = cnow.rx;
+ icount.tx = cnow.tx;
+ icount.frame = cnow.frame;
+ icount.overrun = cnow.overrun;
+ icount.parity = cnow.parity;
+ icount.brk = cnow.brk;
+ icount.buf_overrun = cnow.buf_overrun;
+
+ return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0;
+}
+
static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file)
{
- unsigned int value;
+ int retval;
struct hso_serial *serial = get_serial_by_tty(tty);
- unsigned long flags;
+ struct hso_tiocmget *tiocmget;
+ u16 UART_state_bitmap;
/* sanity check */
if (!serial) {
D1("no tty structures");
return -EINVAL;
}
-
- spin_lock_irqsave(&serial->serial_lock, flags);
- value = ((serial->rts_state) ? TIOCM_RTS : 0) |
+ spin_lock_irq(&serial->serial_lock);
+ retval = ((serial->rts_state) ? TIOCM_RTS : 0) |
((serial->dtr_state) ? TIOCM_DTR : 0);
- spin_unlock_irqrestore(&serial->serial_lock, flags);
+ tiocmget = serial->tiocmget;
+ if (tiocmget) {
- return value;
+ UART_state_bitmap = le16_to_cpu(
+ tiocmget->prev_UART_state_bitmap);
+ if (UART_state_bitmap & B_RING_SIGNAL)
+ retval |= TIOCM_RNG;
+ if (UART_state_bitmap & B_RX_CARRIER)
+ retval |= TIOCM_CD;
+ if (UART_state_bitmap & B_TX_CARRIER)
+ retval |= TIOCM_DSR;
+ }
+ spin_unlock_irq(&serial->serial_lock);
+ return retval;
}
static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
@@ -1460,6 +1717,32 @@ static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
USB_CTRL_SET_TIMEOUT);
}
+static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct hso_serial *serial = get_serial_by_tty(tty);
+ void __user *uarg = (void __user *)arg;
+ int ret = 0;
+ D4("IOCTL cmd: %d, arg: %ld", cmd, arg);
+
+ if (!serial)
+ return -ENODEV;
+ switch (cmd) {
+ case TIOCMIWAIT:
+ ret = hso_wait_modem_status(serial, arg);
+ break;
+
+ case TIOCGICOUNT:
+ ret = hso_get_count(serial, uarg);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+ return ret;
+}
+
+
/* starts a transmit */
static void hso_kick_transmit(struct hso_serial *serial)
{
@@ -1512,8 +1795,8 @@ static int mux_device_request(struct hso_serial *serial, u8 type, u16 port,
/* initialize */
ctrl_req->wValue = 0;
- ctrl_req->wIndex = hso_port_to_mux(port);
- ctrl_req->wLength = size;
+ ctrl_req->wIndex = cpu_to_le16(hso_port_to_mux(port));
+ ctrl_req->wLength = cpu_to_le16(size);
if (type == USB_CDC_GET_ENCAPSULATED_RESPONSE) {
/* Reading command */
@@ -1653,6 +1936,7 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
{
struct hso_serial *serial = urb->context;
int status = urb->status;
+ struct tty_struct *tty;
/* sanity check */
if (!serial) {
@@ -1662,14 +1946,18 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb)
spin_lock(&serial->serial_lock);
serial->tx_urb_used = 0;
+ tty = tty_kref_get(serial->tty);
spin_unlock(&serial->serial_lock);
if (status) {
log_usb_status(status, __func__);
+ tty_kref_put(tty);
return;
}
hso_put_activity(serial->parent);
- if (serial->tty)
- tty_wakeup(serial->tty);
+ if (tty) {
+ tty_wakeup(tty);
+ tty_kref_put(tty);
+ }
hso_kick_transmit(serial);
D1(" ");
@@ -1706,6 +1994,7 @@ static void ctrl_callback(struct urb *urb)
struct hso_serial *serial = urb->context;
struct usb_ctrlrequest *req;
int status = urb->status;
+ struct tty_struct *tty;
/* sanity check */
if (!serial)
@@ -1713,9 +2002,11 @@ static void ctrl_callback(struct urb *urb)
spin_lock(&serial->serial_lock);
serial->tx_urb_used = 0;
+ tty = tty_kref_get(serial->tty);
spin_unlock(&serial->serial_lock);
if (status) {
log_usb_status(status, __func__);
+ tty_kref_put(tty);
return;
}
@@ -1734,33 +2025,40 @@ static void ctrl_callback(struct urb *urb)
spin_unlock(&serial->serial_lock);
} else {
hso_put_activity(serial->parent);
- if (serial->tty)
- tty_wakeup(serial->tty);
+ if (tty)
+ tty_wakeup(tty);
/* response to a write command */
hso_kick_transmit(serial);
}
+ tty_kref_put(tty);
}
/* handle RX data for serial port */
static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
{
- struct tty_struct *tty = serial->tty;
+ struct tty_struct *tty;
int write_length_remaining = 0;
int curr_write_len;
+
/* Sanity check */
if (urb == NULL || serial == NULL) {
D1("serial = NULL");
return -2;
}
+ /* All callers to put_rxbuf_data hold serial_lock */
+ tty = tty_kref_get(serial->tty);
+
/* Push data to tty */
if (tty) {
write_length_remaining = urb->actual_length -
serial->curr_rx_urb_offset;
D1("data to push to tty");
while (write_length_remaining) {
- if (test_bit(TTY_THROTTLED, &tty->flags))
+ if (test_bit(TTY_THROTTLED, &tty->flags)) {
+ tty_kref_put(tty);
return -1;
+ }
curr_write_len = tty_insert_flip_string
(tty, urb->transfer_buffer +
serial->curr_rx_urb_offset,
@@ -1774,6 +2072,7 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
serial->curr_rx_urb_offset = 0;
serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
}
+ tty_kref_put(tty);
return write_length_remaining;
}
@@ -1922,7 +2221,10 @@ static int hso_start_serial_device(struct hso_device *hso_dev, gfp_t flags)
serial->shared_int->use_count++;
mutex_unlock(&serial->shared_int->shared_int_lock);
}
-
+ if (serial->tiocmget)
+ tiocmget_submit_urb(serial,
+ serial->tiocmget,
+ serial->parent->usb);
return result;
}
@@ -1930,6 +2232,7 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)
{
int i;
struct hso_serial *serial = dev2ser(hso_dev);
+ struct hso_tiocmget *tiocmget;
if (!serial)
return -ENODEV;
@@ -1958,6 +2261,11 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)
}
mutex_unlock(&serial->shared_int->shared_int_lock);
}
+ tiocmget = serial->tiocmget;
+ if (tiocmget) {
+ wake_up_interruptible(&tiocmget->waitq);
+ usb_kill_urb(tiocmget->urb);
+ }
return 0;
}
@@ -2304,6 +2612,20 @@ exit:
return NULL;
}
+static void hso_free_tiomget(struct hso_serial *serial)
+{
+ struct hso_tiocmget *tiocmget = serial->tiocmget;
+ if (tiocmget) {
+ kfree(tiocmget);
+ if (tiocmget->urb) {
+ usb_free_urb(tiocmget->urb);
+ tiocmget->urb = NULL;
+ }
+ serial->tiocmget = NULL;
+
+ }
+}
+
/* Frees an AT channel ( goes for both mux and non-mux ) */
static void hso_free_serial_device(struct hso_device *hso_dev)
{
@@ -2322,6 +2644,7 @@ static void hso_free_serial_device(struct hso_device *hso_dev)
else
mutex_unlock(&serial->shared_int->shared_int_lock);
}
+ hso_free_tiomget(serial);
kfree(serial);
hso_free_device(hso_dev);
}
@@ -2333,6 +2656,7 @@ static struct hso_device *hso_create_bulk_serial_device(
struct hso_device *hso_dev;
struct hso_serial *serial;
int num_urbs;
+ struct hso_tiocmget *tiocmget;
hso_dev = hso_create_device(interface, port);
if (!hso_dev)
@@ -2345,8 +2669,27 @@ static struct hso_device *hso_create_bulk_serial_device(
serial->parent = hso_dev;
hso_dev->port_data.dev_serial = serial;
- if (port & HSO_PORT_MODEM)
+ if ((port & HSO_PORT_MASK) == HSO_PORT_MODEM) {
num_urbs = 2;
+ serial->tiocmget = kzalloc(sizeof(struct hso_tiocmget),
+ GFP_KERNEL);
+ /* it isn't going to break our heart if serial->tiocmget
+ * allocation fails don't bother checking this.
+ */
+ if (serial->tiocmget) {
+ tiocmget = serial->tiocmget;
+ tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (tiocmget->urb) {
+ mutex_init(&tiocmget->mutex);
+ init_waitqueue_head(&tiocmget->waitq);
+ tiocmget->endp = hso_get_ep(
+ interface,
+ USB_ENDPOINT_XFER_INT,
+ USB_DIR_IN);
+ } else
+ hso_free_tiomget(serial);
+ }
+ }
else
num_urbs = 1;
@@ -2382,6 +2725,7 @@ static struct hso_device *hso_create_bulk_serial_device(
exit2:
hso_serial_common_free(serial);
exit:
+ hso_free_tiomget(serial);
kfree(serial);
hso_free_device(hso_dev);
return NULL;
@@ -2786,15 +3130,20 @@ static void hso_serial_ref_free(struct kref *ref)
static void hso_free_interface(struct usb_interface *interface)
{
struct hso_serial *hso_dev;
+ struct tty_struct *tty;
int i;
for (i = 0; i < HSO_SERIAL_TTY_MINORS; i++) {
if (serial_table[i]
&& (serial_table[i]->interface == interface)) {
hso_dev = dev2ser(serial_table[i]);
- if (hso_dev->tty)
- tty_hangup(hso_dev->tty);
+ spin_lock_irq(&hso_dev->serial_lock);
+ tty = tty_kref_get(hso_dev->tty);
+ spin_unlock_irq(&hso_dev->serial_lock);
+ if (tty)
+ tty_hangup(tty);
mutex_lock(&hso_dev->parent->mutex);
+ tty_kref_put(tty);
hso_dev->parent->usb_gone = 1;
mutex_unlock(&hso_dev->parent->mutex);
kref_put(&serial_table[i]->ref, hso_serial_ref_free);
@@ -2887,6 +3236,7 @@ static const struct tty_operations hso_serial_ops = {
.close = hso_serial_close,
.write = hso_serial_write,
.write_room = hso_serial_write_room,
+ .ioctl = hso_serial_ioctl,
.set_termios = hso_serial_set_termios,
.chars_in_buffer = hso_serial_chars_in_buffer,
.tiocmget = hso_serial_tiocmget,
@@ -2939,9 +3289,7 @@ static int __init hso_init(void)
tty_drv->subtype = SERIAL_TYPE_NORMAL;
tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
tty_drv->init_termios = tty_std_termios;
- tty_drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- tty_drv->termios = hso_serial_termios;
- tty_drv->termios_locked = hso_serial_termios_locked;
+ hso_init_termios(&tty_drv->init_termios);
tty_set_operations(tty_drv, &hso_serial_ops);
/* register the tty driver */
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 2ee034f70d1c..7cb10a0a5316 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -251,7 +251,6 @@ struct kaweth_device
struct net_device_stats stats;
};
-
/****************************************************************
* kaweth_control
****************************************************************/
@@ -283,9 +282,9 @@ static int kaweth_control(struct kaweth_device *kaweth,
dr->bRequestType= requesttype;
dr->bRequest = request;
- dr->wValue = cpu_to_le16p(&value);
- dr->wIndex = cpu_to_le16p(&index);
- dr->wLength = cpu_to_le16p(&size);
+ dr->wValue = cpu_to_le16(value);
+ dr->wIndex = cpu_to_le16(index);
+ dr->wLength = cpu_to_le16(size);
return kaweth_internal_control_msg(kaweth->dev,
pipe,
@@ -975,6 +974,17 @@ static int kaweth_resume(struct usb_interface *intf)
/****************************************************************
* kaweth_probe
****************************************************************/
+
+
+static const struct net_device_ops kaweth_netdev_ops = {
+ .ndo_open = kaweth_open,
+ .ndo_stop = kaweth_close,
+ .ndo_start_xmit = kaweth_start_xmit,
+ .ndo_tx_timeout = kaweth_tx_timeout,
+ .ndo_set_multicast_list = kaweth_set_rx_mode,
+ .ndo_get_stats = kaweth_netdev_stats,
+};
+
static int kaweth_probe(
struct usb_interface *intf,
const struct usb_device_id *id /* from id_table */
@@ -1147,22 +1157,13 @@ err_fw:
memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr,
sizeof(kaweth->configuration.hw_addr));
- netdev->open = kaweth_open;
- netdev->stop = kaweth_close;
-
+ netdev->netdev_ops = &kaweth_netdev_ops;
netdev->watchdog_timeo = KAWETH_TX_TIMEOUT;
- netdev->tx_timeout = kaweth_tx_timeout;
-
- netdev->hard_start_xmit = kaweth_start_xmit;
- netdev->set_multicast_list = kaweth_set_rx_mode;
- netdev->get_stats = kaweth_netdev_stats;
netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size);
SET_ETHTOOL_OPS(netdev, &ops);
/* kaweth is zeroed as part of alloc_netdev */
-
INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl);
-
usb_set_intfdata(intf, kaweth);
#if 0
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index 5385d66b306e..ced8f36ebd01 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -94,10 +94,18 @@ static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
{
struct usb_device *xdev = dev->udev;
int ret;
+ void *buffer;
+
+ buffer = kmalloc(size, GFP_NOIO);
+ if (buffer == NULL)
+ return -ENOMEM;
ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ,
- MCS7830_RD_BMREQ, 0x0000, index, data,
+ MCS7830_RD_BMREQ, 0x0000, index, buffer,
size, MCS7830_CTRL_TIMEOUT);
+ memcpy(data, buffer, size);
+ kfree(buffer);
+
return ret;
}
@@ -105,10 +113,18 @@ static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data)
{
struct usb_device *xdev = dev->udev;
int ret;
+ void *buffer;
+
+ buffer = kmalloc(size, GFP_NOIO);
+ if (buffer == NULL)
+ return -ENOMEM;
+
+ memcpy(buffer, data, size);
ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ,
- MCS7830_WR_BMREQ, 0x0000, index, data,
+ MCS7830_WR_BMREQ, 0x0000, index, buffer,
size, MCS7830_CTRL_TIMEOUT);
+ kfree(buffer);
return ret;
}
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 166880c113d6..a8228d87c8cf 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -93,6 +93,7 @@ module_param (msg_level, int, 0);
MODULE_PARM_DESC (msg_level, "Override default message level");
MODULE_DEVICE_TABLE(usb, pegasus_ids);
+static const struct net_device_ops pegasus_netdev_ops;
static int update_eth_regs_async(pegasus_t *);
/* Aargh!!! I _really_ hate such tweaks */
@@ -150,8 +151,8 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
pegasus->dr.bRequestType = PEGASUS_REQT_READ;
pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS;
pegasus->dr.wValue = cpu_to_le16(0);
- pegasus->dr.wIndex = cpu_to_le16p(&indx);
- pegasus->dr.wLength = cpu_to_le16p(&size);
+ pegasus->dr.wIndex = cpu_to_le16(indx);
+ pegasus->dr.wLength = cpu_to_le16(size);
pegasus->ctrl_urb->transfer_buffer_length = size;
usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
@@ -208,8 +209,8 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS;
pegasus->dr.wValue = cpu_to_le16(0);
- pegasus->dr.wIndex = cpu_to_le16p(&indx);
- pegasus->dr.wLength = cpu_to_le16p(&size);
+ pegasus->dr.wIndex = cpu_to_le16(indx);
+ pegasus->dr.wLength = cpu_to_le16(size);
pegasus->ctrl_urb->transfer_buffer_length = size;
usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb,
@@ -261,7 +262,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data)
pegasus->dr.bRequestType = PEGASUS_REQT_WRITE;
pegasus->dr.bRequest = PEGASUS_REQ_SET_REG;
pegasus->dr.wValue = cpu_to_le16(data);
- pegasus->dr.wIndex = cpu_to_le16p(&indx);
+ pegasus->dr.wIndex = cpu_to_le16(indx);
pegasus->dr.wLength = cpu_to_le16(1);
pegasus->ctrl_urb->transfer_buffer_length = 1;
@@ -476,7 +477,7 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
for (i = 0; i < 3; i++) {
read_eprom_word(pegasus, i, &w16);
- ((__le16 *) id)[i] = cpu_to_le16p(&w16);
+ ((__le16 *) id)[i] = cpu_to_le16(w16);
}
}
@@ -1360,14 +1361,10 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus->intf = intf;
pegasus->usb = dev;
pegasus->net = net;
- net->open = pegasus_open;
- net->stop = pegasus_close;
+
+
net->watchdog_timeo = PEGASUS_TX_TIMEOUT;
- net->tx_timeout = pegasus_tx_timeout;
- net->do_ioctl = pegasus_ioctl;
- net->hard_start_xmit = pegasus_start_xmit;
- net->set_multicast_list = pegasus_set_multicast;
- net->get_stats = pegasus_netdev_stats;
+ net->netdev_ops = &pegasus_netdev_ops;
SET_ETHTOOL_OPS(net, &ops);
pegasus->mii.dev = net;
pegasus->mii.mdio_read = mdio_read;
@@ -1482,6 +1479,16 @@ static int pegasus_resume (struct usb_interface *intf)
return 0;
}
+static const struct net_device_ops pegasus_netdev_ops = {
+ .ndo_open = pegasus_open,
+ .ndo_stop = pegasus_close,
+ .ndo_do_ioctl = pegasus_ioctl,
+ .ndo_start_xmit = pegasus_start_xmit,
+ .ndo_set_multicast_list = pegasus_set_multicast,
+ .ndo_get_stats = pegasus_netdev_stats,
+ .ndo_tx_timeout = pegasus_tx_timeout,
+};
+
static struct usb_driver pegasus_driver = {
.name = driver_name,
.probe = pegasus_probe,
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index ac07cc6e3cb2..3b8e63254277 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -622,6 +622,7 @@ static const struct net_device_ops rhine_netdev_ops = {
.ndo_get_stats = rhine_get_stats,
.ndo_set_multicast_list = rhine_set_rx_mode,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = rhine_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 58e25d090ae0..c5691fdb7079 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -855,6 +855,7 @@ static const struct net_device_ops velocity_netdev_ops = {
.ndo_start_xmit = velocity_xmit,
.ndo_get_stats = velocity_get_stats,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_set_multicast_list = velocity_set_multi,
.ndo_change_mtu = velocity_change_mtu,
.ndo_do_ioctl = velocity_ioctl,
@@ -1301,7 +1302,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
static int velocity_init_td_ring(struct velocity_info *vptr)
{
dma_addr_t curr;
- unsigned int j;
+ int j;
/* Init the TD ring entries */
for (j = 0; j < vptr->tx.numq; j++) {
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index b7004ff36451..c68808336c8c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -24,6 +24,7 @@
#include <linux/virtio.h>
#include <linux/virtio_net.h>
#include <linux/scatterlist.h>
+#include <linux/if_vlan.h>
static int napi_weight = 128;
module_param(napi_weight, int, 0444);
@@ -33,7 +34,7 @@ module_param(csum, bool, 0444);
module_param(gso, bool, 0444);
/* FIXME: MTU in config. */
-#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
+#define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
#define GOOD_COPY_LEN 128
struct virtnet_info
@@ -286,7 +287,7 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi)
skb_put(skb, MAX_PACKET_LEN);
hdr = skb_vnet_hdr(skb);
- sg_init_one(sg, hdr, sizeof(*hdr));
+ sg_set_buf(sg, hdr, sizeof(*hdr));
if (vi->big_packets) {
for (i = 0; i < MAX_SKB_FRAGS; i++) {
@@ -487,9 +488,9 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
/* Encode metadata header at front. */
if (vi->mergeable_rx_bufs)
- sg_init_one(sg, mhdr, sizeof(*mhdr));
+ sg_set_buf(sg, mhdr, sizeof(*mhdr));
else
- sg_init_one(sg, hdr, sizeof(*hdr));
+ sg_set_buf(sg, hdr, sizeof(*hdr));
num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
@@ -624,6 +625,18 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+static const struct net_device_ops virtnet_netdev = {
+ .ndo_open = virtnet_open,
+ .ndo_stop = virtnet_close,
+ .ndo_start_xmit = start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_change_mtu = virtnet_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = virtnet_netpoll,
+#endif
+};
+
static int virtnet_probe(struct virtio_device *vdev)
{
int err;
@@ -636,14 +649,8 @@ static int virtnet_probe(struct virtio_device *vdev)
return -ENOMEM;
/* Set up network device as normal. */
- dev->open = virtnet_open;
- dev->stop = virtnet_close;
- dev->hard_start_xmit = start_xmit;
- dev->change_mtu = virtnet_change_mtu;
+ dev->netdev_ops = &virtnet_netdev;
dev->features = NETIF_F_HIGHDMA;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = virtnet_netpoll;
-#endif
SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops);
SET_NETDEV_DEV(dev, &vdev->dev);
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 2dc241689d37..0dbd85b0162d 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -622,7 +622,7 @@ static void hss_hdlc_rx_irq(void *pdev)
printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name);
#endif
qmgr_disable_irq(queue_ids[port->id].rx);
- netif_rx_schedule(dev, &port->napi);
+ netif_rx_schedule(&port->napi);
}
static int hss_hdlc_poll(struct napi_struct *napi, int budget)
@@ -651,7 +651,7 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
printk(KERN_DEBUG "%s: hss_hdlc_poll"
" netif_rx_complete\n", dev->name);
#endif
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
qmgr_enable_irq(rxq);
if (!qmgr_stat_empty(rxq) &&
netif_rx_reschedule(napi)) {
@@ -1069,7 +1069,7 @@ static int hss_hdlc_open(struct net_device *dev)
hss_start_hdlc(port);
/* we may already have RX data, enables IRQ */
- netif_rx_schedule(dev, &port->napi);
+ netif_rx_schedule(&port->napi);
return 0;
err_unlock:
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 3c1edda08d3d..d8322d2d1e29 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -155,6 +155,7 @@ static const struct net_device_ops wd_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/net/wimax/Kconfig b/drivers/net/wimax/Kconfig
new file mode 100644
index 000000000000..565018ec1e3b
--- /dev/null
+++ b/drivers/net/wimax/Kconfig
@@ -0,0 +1,17 @@
+#
+# WiMAX LAN device drivers configuration
+#
+
+
+comment "Enable WiMAX (Networking options) to see the WiMAX drivers"
+ depends on WIMAX = n
+
+if WIMAX
+
+menu "WiMAX Wireless Broadband devices"
+
+source "drivers/net/wimax/i2400m/Kconfig"
+
+endmenu
+
+endif
diff --git a/drivers/net/wimax/Makefile b/drivers/net/wimax/Makefile
new file mode 100644
index 000000000000..992bc02bc016
--- /dev/null
+++ b/drivers/net/wimax/Makefile
@@ -0,0 +1,5 @@
+
+obj-$(CONFIG_WIMAX_I2400M) += i2400m/
+
+# (from Sam Ravnborg) force kbuild to create built-in.o
+obj- := dummy.o
diff --git a/drivers/net/wimax/i2400m/Kconfig b/drivers/net/wimax/i2400m/Kconfig
new file mode 100644
index 000000000000..d623b3d99a4b
--- /dev/null
+++ b/drivers/net/wimax/i2400m/Kconfig
@@ -0,0 +1,49 @@
+
+config WIMAX_I2400M
+ tristate
+ depends on WIMAX
+ select FW_LOADER
+
+comment "Enable USB support to see WiMAX USB drivers"
+ depends on USB = n
+
+comment "Enable MMC support to see WiMAX SDIO drivers"
+ depends on MMC = n
+
+config WIMAX_I2400M_USB
+ tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)"
+ depends on WIMAX && USB
+ select WIMAX_I2400M
+ help
+ Select if you have a device based on the Intel WiMAX
+ Connection 2400 over USB (like any of the Intel Wireless
+ WiMAX/WiFi Link 5x50 series).
+
+ If unsure, it is safe to select M (module).
+
+config WIMAX_I2400M_SDIO
+ tristate "Intel Wireless WiMAX Connection 2400 over SDIO"
+ depends on WIMAX && MMC
+ select WIMAX_I2400M
+ help
+ Select if you have a device based on the Intel WiMAX
+ Connection 2400 over SDIO.
+
+ If unsure, it is safe to select M (module).
+
+config WIMAX_I2400M_DEBUG_LEVEL
+ int "WiMAX i2400m debug level"
+ depends on WIMAX_I2400M
+ default 8
+ help
+
+ Select the maximum debug verbosity level to be compiled into
+ the WiMAX i2400m driver code.
+
+ By default, this is disabled at runtime and can be
+ selectively enabled at runtime for different parts of the
+ code using the sysfs debug-levels file.
+
+ If set at zero, this will compile out all the debug code.
+
+ It is recommended that it is left at 8.
diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile
new file mode 100644
index 000000000000..1696e936cf5a
--- /dev/null
+++ b/drivers/net/wimax/i2400m/Makefile
@@ -0,0 +1,29 @@
+
+obj-$(CONFIG_WIMAX_I2400M) += i2400m.o
+obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o
+obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o
+
+i2400m-y := \
+ control.o \
+ driver.o \
+ fw.o \
+ op-rfkill.o \
+ netdev.o \
+ tx.o \
+ rx.o
+
+i2400m-$(CONFIG_DEBUG_FS) += debugfs.o
+
+i2400m-usb-y := \
+ usb-fw.o \
+ usb-notif.o \
+ usb-tx.o \
+ usb-rx.o \
+ usb.o
+
+
+i2400m-sdio-y := \
+ sdio.o \
+ sdio-tx.o \
+ sdio-fw.o \
+ sdio-rx.o
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c
new file mode 100644
index 000000000000..15d9f51b292c
--- /dev/null
+++ b/drivers/net/wimax/i2400m/control.c
@@ -0,0 +1,1291 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Miscellaneous control functions for managing the device
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Initial implementation
+ *
+ * This is a collection of functions used to control the device (plus
+ * a few helpers).
+ *
+ * There are utilities for handling TLV buffers, hooks on the device's
+ * reports to act on device changes of state [i2400m_report_hook()],
+ * on acks to commands [i2400m_msg_ack_hook()], a helper for sending
+ * commands to the device and blocking until a reply arrives
+ * [i2400m_msg_to_dev()], a few high level commands for manipulating
+ * the device state, powersving mode and configuration plus the
+ * routines to setup the device once communication is stablished with
+ * it [i2400m_dev_initialize()].
+ *
+ * ROADMAP
+ *
+ * i2400m_dev_initalize() Called by i2400m_dev_start()
+ * i2400m_set_init_config()
+ * i2400m_firmware_check()
+ * i2400m_cmd_get_state()
+ * i2400m_dev_shutdown() Called by i2400m_dev_stop()
+ * i2400m->bus_reset()
+ *
+ * i2400m_{cmd,get,set}_*()
+ * i2400m_msg_to_dev()
+ * i2400m_msg_check_status()
+ *
+ * i2400m_report_hook() Called on reception of an event
+ * i2400m_report_state_hook()
+ * i2400m_tlv_buffer_walk()
+ * i2400m_tlv_match()
+ * i2400m_report_tlv_system_state()
+ * i2400m_report_tlv_rf_switches_status()
+ * i2400m_report_tlv_media_status()
+ * i2400m_cmd_enter_powersave()
+ *
+ * i2400m_msg_ack_hook() Called on reception of a reply to a
+ * command, get or set
+ */
+
+#include <stdarg.h>
+#include "i2400m.h"
+#include <linux/kernel.h>
+#include <linux/wimax/i2400m.h>
+
+
+#define D_SUBMODULE control
+#include "debug-levels.h"
+
+
+/*
+ * Return if a TLV is of a give type and size
+ *
+ * @tlv_hdr: pointer to the TLV
+ * @tlv_type: type of the TLV we are looking for
+ * @tlv_size: expected size of the TLV we are looking for (if -1,
+ * don't check the size). This includes the header
+ * Returns: 0 if the TLV matches
+ * < 0 if it doesn't match at all
+ * > 0 total TLV + payload size, if the type matches, but not
+ * the size
+ */
+static
+ssize_t i2400m_tlv_match(const struct i2400m_tlv_hdr *tlv,
+ enum i2400m_tlv tlv_type, ssize_t tlv_size)
+{
+ if (le16_to_cpu(tlv->type) != tlv_type) /* Not our type? skip */
+ return -1;
+ if (tlv_size != -1
+ && le16_to_cpu(tlv->length) + sizeof(*tlv) != tlv_size) {
+ size_t size = le16_to_cpu(tlv->length) + sizeof(*tlv);
+ printk(KERN_WARNING "W: tlv type 0x%x mismatched because of "
+ "size (got %zu vs %zu expected)\n",
+ tlv_type, size, tlv_size);
+ return size;
+ }
+ return 0;
+}
+
+
+/*
+ * Given a buffer of TLVs, iterate over them
+ *
+ * @i2400m: device instance
+ * @tlv_buf: pointer to the beginning of the TLV buffer
+ * @buf_size: buffer size in bytes
+ * @tlv_pos: seek position; this is assumed to be a pointer returned
+ * by i2400m_tlv_buffer_walk() [and thus, validated]. The
+ * TLV returned will be the one following this one.
+ *
+ * Usage:
+ *
+ * tlv_itr = NULL;
+ * while (tlv_itr = i2400m_tlv_buffer_walk(i2400m, buf, size, tlv_itr)) {
+ * ...
+ * // Do stuff with tlv_itr, DON'T MODIFY IT
+ * ...
+ * }
+ */
+static
+const struct i2400m_tlv_hdr *i2400m_tlv_buffer_walk(
+ struct i2400m *i2400m,
+ const void *tlv_buf, size_t buf_size,
+ const struct i2400m_tlv_hdr *tlv_pos)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ const struct i2400m_tlv_hdr *tlv_top = tlv_buf + buf_size;
+ size_t offset, length, avail_size;
+ unsigned type;
+
+ if (tlv_pos == NULL) /* Take the first one? */
+ tlv_pos = tlv_buf;
+ else /* Nope, the next one */
+ tlv_pos = (void *) tlv_pos
+ + le16_to_cpu(tlv_pos->length) + sizeof(*tlv_pos);
+ if (tlv_pos == tlv_top) { /* buffer done */
+ tlv_pos = NULL;
+ goto error_beyond_end;
+ }
+ if (tlv_pos > tlv_top) {
+ tlv_pos = NULL;
+ WARN_ON(1);
+ goto error_beyond_end;
+ }
+ offset = (void *) tlv_pos - (void *) tlv_buf;
+ avail_size = buf_size - offset;
+ if (avail_size < sizeof(*tlv_pos)) {
+ dev_err(dev, "HW BUG? tlv_buf %p [%zu bytes], tlv @%zu: "
+ "short header\n", tlv_buf, buf_size, offset);
+ goto error_short_header;
+ }
+ type = le16_to_cpu(tlv_pos->type);
+ length = le16_to_cpu(tlv_pos->length);
+ if (avail_size < sizeof(*tlv_pos) + length) {
+ dev_err(dev, "HW BUG? tlv_buf %p [%zu bytes], "
+ "tlv type 0x%04x @%zu: "
+ "short data (%zu bytes vs %zu needed)\n",
+ tlv_buf, buf_size, type, offset, avail_size,
+ sizeof(*tlv_pos) + length);
+ goto error_short_header;
+ }
+error_short_header:
+error_beyond_end:
+ return tlv_pos;
+}
+
+
+/*
+ * Find a TLV in a buffer of sequential TLVs
+ *
+ * @i2400m: device descriptor
+ * @tlv_hdr: pointer to the first TLV in the sequence
+ * @size: size of the buffer in bytes; all TLVs are assumed to fit
+ * fully in the buffer (otherwise we'll complain).
+ * @tlv_type: type of the TLV we are looking for
+ * @tlv_size: expected size of the TLV we are looking for (if -1,
+ * don't check the size). This includes the header
+ *
+ * Returns: NULL if the TLV is not found, otherwise a pointer to
+ * it. If the sizes don't match, an error is printed and NULL
+ * returned.
+ */
+static
+const struct i2400m_tlv_hdr *i2400m_tlv_find(
+ struct i2400m *i2400m,
+ const struct i2400m_tlv_hdr *tlv_hdr, size_t size,
+ enum i2400m_tlv tlv_type, ssize_t tlv_size)
+{
+ ssize_t match;
+ struct device *dev = i2400m_dev(i2400m);
+ const struct i2400m_tlv_hdr *tlv = NULL;
+ while ((tlv = i2400m_tlv_buffer_walk(i2400m, tlv_hdr, size, tlv))) {
+ match = i2400m_tlv_match(tlv, tlv_type, tlv_size);
+ if (match == 0) /* found it :) */
+ break;
+ if (match > 0)
+ dev_warn(dev, "TLV type 0x%04x found with size "
+ "mismatch (%zu vs %zu needed)\n",
+ tlv_type, match, tlv_size);
+ }
+ return tlv;
+}
+
+
+static const struct
+{
+ char *msg;
+ int errno;
+} ms_to_errno[I2400M_MS_MAX] = {
+ [I2400M_MS_DONE_OK] = { "", 0 },
+ [I2400M_MS_DONE_IN_PROGRESS] = { "", 0 },
+ [I2400M_MS_INVALID_OP] = { "invalid opcode", -ENOSYS },
+ [I2400M_MS_BAD_STATE] = { "invalid state", -EILSEQ },
+ [I2400M_MS_ILLEGAL_VALUE] = { "illegal value", -EINVAL },
+ [I2400M_MS_MISSING_PARAMS] = { "missing parameters", -ENOMSG },
+ [I2400M_MS_VERSION_ERROR] = { "bad version", -EIO },
+ [I2400M_MS_ACCESSIBILITY_ERROR] = { "accesibility error", -EIO },
+ [I2400M_MS_BUSY] = { "busy", -EBUSY },
+ [I2400M_MS_CORRUPTED_TLV] = { "corrupted TLV", -EILSEQ },
+ [I2400M_MS_UNINITIALIZED] = { "not unitialized", -EILSEQ },
+ [I2400M_MS_UNKNOWN_ERROR] = { "unknown error", -EIO },
+ [I2400M_MS_PRODUCTION_ERROR] = { "production error", -EIO },
+ [I2400M_MS_NO_RF] = { "no RF", -EIO },
+ [I2400M_MS_NOT_READY_FOR_POWERSAVE] =
+ { "not ready for powersave", -EACCES },
+ [I2400M_MS_THERMAL_CRITICAL] = { "thermal critical", -EL3HLT },
+};
+
+
+/*
+ * i2400m_msg_check_status - translate a message's status code
+ *
+ * @i2400m: device descriptor
+ * @l3l4_hdr: message header
+ * @strbuf: buffer to place a formatted error message (unless NULL).
+ * @strbuf_size: max amount of available space; larger messages will
+ * be truncated.
+ *
+ * Returns: errno code corresponding to the status code in @l3l4_hdr
+ * and a message in @strbuf describing the error.
+ */
+int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *l3l4_hdr,
+ char *strbuf, size_t strbuf_size)
+{
+ int result;
+ enum i2400m_ms status = le16_to_cpu(l3l4_hdr->status);
+ const char *str;
+
+ if (status == 0)
+ return 0;
+ if (status > ARRAY_SIZE(ms_to_errno)) {
+ str = "unknown status code";
+ result = -EBADR;
+ } else {
+ str = ms_to_errno[status].msg;
+ result = ms_to_errno[status].errno;
+ }
+ if (strbuf)
+ snprintf(strbuf, strbuf_size, "%s (%d)", str, status);
+ return result;
+}
+
+
+/*
+ * Act on a TLV System State reported by the device
+ *
+ * @i2400m: device descriptor
+ * @ss: validated System State TLV
+ */
+static
+void i2400m_report_tlv_system_state(struct i2400m *i2400m,
+ const struct i2400m_tlv_system_state *ss)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+ enum i2400m_system_state i2400m_state = le32_to_cpu(ss->state);
+
+ d_fnstart(3, dev, "(i2400m %p ss %p [%u])\n", i2400m, ss, i2400m_state);
+
+ if (unlikely(i2400m->ready == 0)) /* act if up */
+ goto out;
+ if (i2400m->state != i2400m_state) {
+ i2400m->state = i2400m_state;
+ wake_up_all(&i2400m->state_wq);
+ }
+ switch (i2400m_state) {
+ case I2400M_SS_UNINITIALIZED:
+ case I2400M_SS_INIT:
+ case I2400M_SS_CONFIG:
+ case I2400M_SS_PRODUCTION:
+ wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED);
+ break;
+
+ case I2400M_SS_RF_OFF:
+ case I2400M_SS_RF_SHUTDOWN:
+ wimax_state_change(wimax_dev, WIMAX_ST_RADIO_OFF);
+ break;
+
+ case I2400M_SS_READY:
+ case I2400M_SS_STANDBY:
+ case I2400M_SS_SLEEPACTIVE:
+ wimax_state_change(wimax_dev, WIMAX_ST_READY);
+ break;
+
+ case I2400M_SS_CONNECTING:
+ case I2400M_SS_WIMAX_CONNECTED:
+ wimax_state_change(wimax_dev, WIMAX_ST_READY);
+ break;
+
+ case I2400M_SS_SCAN:
+ case I2400M_SS_OUT_OF_ZONE:
+ wimax_state_change(wimax_dev, WIMAX_ST_SCANNING);
+ break;
+
+ case I2400M_SS_IDLE:
+ d_printf(1, dev, "entering BS-negotiated idle mode\n");
+ case I2400M_SS_DISCONNECTING:
+ case I2400M_SS_DATA_PATH_CONNECTED:
+ wimax_state_change(wimax_dev, WIMAX_ST_CONNECTED);
+ break;
+
+ default:
+ /* Huh? just in case, shut it down */
+ dev_err(dev, "HW BUG? unknown state %u: shutting down\n",
+ i2400m_state);
+ i2400m->bus_reset(i2400m, I2400M_RT_WARM);
+ break;
+ };
+out:
+ d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n",
+ i2400m, ss, i2400m_state);
+}
+
+
+/*
+ * Parse and act on a TLV Media Status sent by the device
+ *
+ * @i2400m: device descriptor
+ * @ms: validated Media Status TLV
+ *
+ * This will set the carrier up on down based on the device's link
+ * report. This is done asides of what the WiMAX stack does based on
+ * the device's state as sometimes we need to do a link-renew (the BS
+ * wants us to renew a DHCP lease, for example).
+ *
+ * In fact, doc says that everytime we get a link-up, we should do a
+ * DHCP negotiation...
+ */
+static
+void i2400m_report_tlv_media_status(struct i2400m *i2400m,
+ const struct i2400m_tlv_media_status *ms)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+ struct net_device *net_dev = wimax_dev->net_dev;
+ enum i2400m_media_status status = le32_to_cpu(ms->media_status);
+
+ d_fnstart(3, dev, "(i2400m %p ms %p [%u])\n", i2400m, ms, status);
+
+ if (unlikely(i2400m->ready == 0)) /* act if up */
+ goto out;
+ switch (status) {
+ case I2400M_MEDIA_STATUS_LINK_UP:
+ netif_carrier_on(net_dev);
+ break;
+ case I2400M_MEDIA_STATUS_LINK_DOWN:
+ netif_carrier_off(net_dev);
+ break;
+ /*
+ * This is the network telling us we need to retrain the DHCP
+ * lease -- so far, we are trusting the WiMAX Network Service
+ * in user space to pick this up and poke the DHCP client.
+ */
+ case I2400M_MEDIA_STATUS_LINK_RENEW:
+ netif_carrier_on(net_dev);
+ break;
+ default:
+ dev_err(dev, "HW BUG? unknown media status %u\n",
+ status);
+ };
+out:
+ d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n",
+ i2400m, ms, status);
+}
+
+
+/*
+ * Parse a 'state report' and extract carrier on/off information
+ *
+ * @i2400m: device descriptor
+ * @l3l4_hdr: pointer to message; it has been already validated for
+ * consistent size.
+ * @size: size of the message (header + payload). The header length
+ * declaration is assumed to be congruent with @size (as in
+ * sizeof(*l3l4_hdr) + l3l4_hdr->length == size)
+ *
+ * Extract from the report state the system state TLV and infer from
+ * there if we have a carrier or not. Update our local state and tell
+ * netdev.
+ *
+ * When setting the carrier, it's fine to set OFF twice (for example),
+ * as netif_carrier_off() will not generate two OFF events (just on
+ * the transitions).
+ */
+static
+void i2400m_report_state_hook(struct i2400m *i2400m,
+ const struct i2400m_l3l4_hdr *l3l4_hdr,
+ size_t size, const char *tag)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ const struct i2400m_tlv_hdr *tlv;
+ const struct i2400m_tlv_system_state *ss;
+ const struct i2400m_tlv_rf_switches_status *rfss;
+ const struct i2400m_tlv_media_status *ms;
+ size_t tlv_size = le16_to_cpu(l3l4_hdr->length);
+
+ d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n",
+ i2400m, l3l4_hdr, size, tag);
+ tlv = NULL;
+
+ while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl,
+ tlv_size, tlv))) {
+ if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE,
+ sizeof(*ss))) {
+ ss = container_of(tlv, typeof(*ss), hdr);
+ d_printf(2, dev, "%s: system state TLV "
+ "found (0x%04x), state 0x%08x\n",
+ tag, I2400M_TLV_SYSTEM_STATE,
+ le32_to_cpu(ss->state));
+ i2400m_report_tlv_system_state(i2400m, ss);
+ }
+ if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS,
+ sizeof(*rfss))) {
+ rfss = container_of(tlv, typeof(*rfss), hdr);
+ d_printf(2, dev, "%s: RF status TLV "
+ "found (0x%04x), sw 0x%02x hw 0x%02x\n",
+ tag, I2400M_TLV_RF_STATUS,
+ le32_to_cpu(rfss->sw_rf_switch),
+ le32_to_cpu(rfss->hw_rf_switch));
+ i2400m_report_tlv_rf_switches_status(i2400m, rfss);
+ }
+ if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS,
+ sizeof(*ms))) {
+ ms = container_of(tlv, typeof(*ms), hdr);
+ d_printf(2, dev, "%s: Media Status TLV: %u\n",
+ tag, le32_to_cpu(ms->media_status));
+ i2400m_report_tlv_media_status(i2400m, ms);
+ }
+ }
+ d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n",
+ i2400m, l3l4_hdr, size, tag);
+}
+
+
+/*
+ * i2400m_report_hook - (maybe) act on a report
+ *
+ * @i2400m: device descriptor
+ * @l3l4_hdr: pointer to message; it has been already validated for
+ * consistent size.
+ * @size: size of the message (header + payload). The header length
+ * declaration is assumed to be congruent with @size (as in
+ * sizeof(*l3l4_hdr) + l3l4_hdr->length == size)
+ *
+ * Extract information we might need (like carrien on/off) from a
+ * device report.
+ */
+void i2400m_report_hook(struct i2400m *i2400m,
+ const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ unsigned msg_type;
+
+ d_fnstart(3, dev, "(i2400m %p l3l4_hdr %p size %zu)\n",
+ i2400m, l3l4_hdr, size);
+ /* Chew on the message, we might need some information from
+ * here */
+ msg_type = le16_to_cpu(l3l4_hdr->type);
+ switch (msg_type) {
+ case I2400M_MT_REPORT_STATE: /* carrier detection... */
+ i2400m_report_state_hook(i2400m,
+ l3l4_hdr, size, "REPORT STATE");
+ break;
+ /* If the device is ready for power save, then ask it to do
+ * it. */
+ case I2400M_MT_REPORT_POWERSAVE_READY: /* zzzzz */
+ if (l3l4_hdr->status == cpu_to_le16(I2400M_MS_DONE_OK)) {
+ d_printf(1, dev, "ready for powersave, requesting\n");
+ i2400m_cmd_enter_powersave(i2400m);
+ }
+ break;
+ };
+ d_fnend(3, dev, "(i2400m %p l3l4_hdr %p size %zu) = void\n",
+ i2400m, l3l4_hdr, size);
+}
+
+
+/*
+ * i2400m_msg_ack_hook - process cmd/set/get ack for internal status
+ *
+ * @i2400m: device descriptor
+ * @l3l4_hdr: pointer to message; it has been already validated for
+ * consistent size.
+ * @size: size of the message
+ *
+ * Extract information we might need from acks to commands and act on
+ * it. This is akin to i2400m_report_hook(). Note most of this
+ * processing should be done in the function that calls the
+ * command. This is here for some cases where it can't happen...
+ */
+void i2400m_msg_ack_hook(struct i2400m *i2400m,
+ const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ unsigned ack_type, ack_status;
+ char strerr[32];
+
+ /* Chew on the message, we might need some information from
+ * here */
+ ack_type = le16_to_cpu(l3l4_hdr->type);
+ ack_status = le16_to_cpu(l3l4_hdr->status);
+ switch (ack_type) {
+ case I2400M_MT_CMD_ENTER_POWERSAVE:
+ /* This is just left here for the sake of example, as
+ * the processing is done somewhere else. */
+ if (0) {
+ result = i2400m_msg_check_status(
+ l3l4_hdr, strerr, sizeof(strerr));
+ if (result >= 0)
+ d_printf(1, dev, "ready for power save: %zd\n",
+ size);
+ }
+ break;
+ };
+ return;
+}
+
+
+/*
+ * i2400m_msg_size_check() - verify message size and header are congruent
+ *
+ * It is ok if the total message size is larger than the expected
+ * size, as there can be padding.
+ */
+int i2400m_msg_size_check(struct i2400m *i2400m,
+ const struct i2400m_l3l4_hdr *l3l4_hdr,
+ size_t msg_size)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ size_t expected_size;
+ d_fnstart(4, dev, "(i2400m %p l3l4_hdr %p msg_size %zu)\n",
+ i2400m, l3l4_hdr, msg_size);
+ if (msg_size < sizeof(*l3l4_hdr)) {
+ dev_err(dev, "bad size for message header "
+ "(expected at least %zu, got %zu)\n",
+ (size_t) sizeof(*l3l4_hdr), msg_size);
+ result = -EIO;
+ goto error_hdr_size;
+ }
+ expected_size = le16_to_cpu(l3l4_hdr->length) + sizeof(*l3l4_hdr);
+ if (msg_size < expected_size) {
+ dev_err(dev, "bad size for message code 0x%04x (expected %zu, "
+ "got %zu)\n", le16_to_cpu(l3l4_hdr->type),
+ expected_size, msg_size);
+ result = -EIO;
+ } else
+ result = 0;
+error_hdr_size:
+ d_fnend(4, dev,
+ "(i2400m %p l3l4_hdr %p msg_size %zu) = %d\n",
+ i2400m, l3l4_hdr, msg_size, result);
+ return result;
+}
+
+
+
+/*
+ * Cancel a wait for a command ACK
+ *
+ * @i2400m: device descriptor
+ * @code: [negative] errno code to cancel with (don't use
+ * -EINPROGRESS)
+ *
+ * If there is an ack already filled out, free it.
+ */
+void i2400m_msg_to_dev_cancel_wait(struct i2400m *i2400m, int code)
+{
+ struct sk_buff *ack_skb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ ack_skb = i2400m->ack_skb;
+ if (ack_skb && !IS_ERR(ack_skb))
+ kfree_skb(ack_skb);
+ i2400m->ack_skb = ERR_PTR(code);
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+}
+
+
+/**
+ * i2400m_msg_to_dev - Send a control message to the device and get a response
+ *
+ * @i2400m: device descriptor
+ *
+ * @msg_skb: an skb *
+ *
+ * @buf: pointer to the buffer containing the message to be sent; it
+ * has to start with a &struct i2400M_l3l4_hdr and then
+ * followed by the payload. Once this function returns, the
+ * buffer can be reused.
+ *
+ * @buf_len: buffer size
+ *
+ * Returns:
+ *
+ * Pointer to skb containing the ack message. You need to check the
+ * pointer with IS_ERR(), as it might be an error code. Error codes
+ * could happen because:
+ *
+ * - the message wasn't formatted correctly
+ * - couldn't send the message
+ * - failed waiting for a response
+ * - the ack message wasn't formatted correctly
+ *
+ * The returned skb has been allocated with wimax_msg_to_user_alloc(),
+ * it contains the reponse in a netlink attribute and is ready to be
+ * passed up to user space with wimax_msg_to_user_send(). To access
+ * the payload and its length, use wimax_msg_{data,len}() on the skb.
+ *
+ * The skb has to be freed with kfree_skb() once done.
+ *
+ * Description:
+ *
+ * This function delivers a message/command to the device and waits
+ * for an ack to be received. The format is described in
+ * linux/wimax/i2400m.h. In summary, a command/get/set is followed by an
+ * ack.
+ *
+ * This function will not check the ack status, that's left up to the
+ * caller. Once done with the ack skb, it has to be kfree_skb()ed.
+ *
+ * The i2400m handles only one message at the same time, thus we need
+ * the mutex to exclude other players.
+ *
+ * We write the message and then wait for an answer to come back. The
+ * RX path intercepts control messages and handles them in
+ * i2400m_rx_ctl(). Reports (notifications) are (maybe) processed
+ * locally and then forwarded (as needed) to user space on the WiMAX
+ * stack message pipe. Acks are saved and passed back to us through an
+ * skb in i2400m->ack_skb which is ready to be given to generic
+ * netlink if need be.
+ */
+struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m,
+ const void *buf, size_t buf_len)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ const struct i2400m_l3l4_hdr *msg_l3l4_hdr;
+ struct sk_buff *ack_skb;
+ const struct i2400m_l3l4_hdr *ack_l3l4_hdr;
+ size_t ack_len;
+ int ack_timeout;
+ unsigned msg_type;
+ unsigned long flags;
+
+ d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n",
+ i2400m, buf, buf_len);
+
+ if (i2400m->boot_mode)
+ return ERR_PTR(-ENODEV);
+
+ msg_l3l4_hdr = buf;
+ /* Check msg & payload consistency */
+ result = i2400m_msg_size_check(i2400m, msg_l3l4_hdr, buf_len);
+ if (result < 0)
+ goto error_bad_msg;
+ msg_type = le16_to_cpu(msg_l3l4_hdr->type);
+ d_printf(1, dev, "CMD/GET/SET 0x%04x %zu bytes\n",
+ msg_type, buf_len);
+ d_dump(2, dev, buf, buf_len);
+
+ /* Setup the completion, ack_skb ("we are waiting") and send
+ * the message to the device */
+ mutex_lock(&i2400m->msg_mutex);
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ i2400m->ack_skb = ERR_PTR(-EINPROGRESS);
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+ init_completion(&i2400m->msg_completion);
+ result = i2400m_tx(i2400m, buf, buf_len, I2400M_PT_CTRL);
+ if (result < 0) {
+ dev_err(dev, "can't send message 0x%04x: %d\n",
+ le16_to_cpu(msg_l3l4_hdr->type), result);
+ goto error_tx;
+ }
+
+ /* Some commands take longer to execute because of crypto ops,
+ * so we give them some more leeway on timeout */
+ switch (msg_type) {
+ case I2400M_MT_GET_TLS_OPERATION_RESULT:
+ case I2400M_MT_CMD_SEND_EAP_RESPONSE:
+ ack_timeout = 5 * HZ;
+ break;
+ default:
+ ack_timeout = HZ;
+ };
+
+ /* The RX path in rx.c will put any response for this message
+ * in i2400m->ack_skb and wake us up. If we cancel the wait,
+ * we need to change the value of i2400m->ack_skb to something
+ * not -EINPROGRESS so RX knows there is no one waiting. */
+ result = wait_for_completion_interruptible_timeout(
+ &i2400m->msg_completion, ack_timeout);
+ if (result == 0) {
+ dev_err(dev, "timeout waiting for reply to message 0x%04x\n",
+ msg_type);
+ result = -ETIMEDOUT;
+ i2400m_msg_to_dev_cancel_wait(i2400m, result);
+ goto error_wait_for_completion;
+ } else if (result < 0) {
+ dev_err(dev, "error waiting for reply to message 0x%04x: %d\n",
+ msg_type, result);
+ i2400m_msg_to_dev_cancel_wait(i2400m, result);
+ goto error_wait_for_completion;
+ }
+
+ /* Pull out the ack data from i2400m->ack_skb -- see if it is
+ * an error and act accordingly */
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ ack_skb = i2400m->ack_skb;
+ if (IS_ERR(ack_skb))
+ result = PTR_ERR(ack_skb);
+ else
+ result = 0;
+ i2400m->ack_skb = NULL;
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+ if (result < 0)
+ goto error_ack_status;
+ ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len);
+
+ /* Check the ack and deliver it if it is ok */
+ result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len);
+ if (result < 0) {
+ dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n",
+ msg_type, result);
+ goto error_bad_ack_len;
+ }
+ if (msg_type != le16_to_cpu(ack_l3l4_hdr->type)) {
+ dev_err(dev, "HW BUG? bad reply 0x%04x to message 0x%04x\n",
+ le16_to_cpu(ack_l3l4_hdr->type), msg_type);
+ result = -EIO;
+ goto error_bad_ack_type;
+ }
+ i2400m_msg_ack_hook(i2400m, ack_l3l4_hdr, ack_len);
+ mutex_unlock(&i2400m->msg_mutex);
+ d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %p\n",
+ i2400m, buf, buf_len, ack_skb);
+ return ack_skb;
+
+error_bad_ack_type:
+error_bad_ack_len:
+ kfree_skb(ack_skb);
+error_ack_status:
+error_wait_for_completion:
+error_tx:
+ mutex_unlock(&i2400m->msg_mutex);
+error_bad_msg:
+ d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %d\n",
+ i2400m, buf, buf_len, result);
+ return ERR_PTR(result);
+}
+
+
+/*
+ * Definitions for the Enter Power Save command
+ *
+ * The Enter Power Save command requests the device to go into power
+ * saving mode. The device will ack or nak the command depending on it
+ * being ready for it. If it acks, we tell the USB subsystem to
+ *
+ * As well, the device might request to go into power saving mode by
+ * sending a report (REPORT_POWERSAVE_READY), in which case, we issue
+ * this command. The hookups in the RX coder allow
+ */
+enum {
+ I2400M_WAKEUP_ENABLED = 0x01,
+ I2400M_WAKEUP_DISABLED = 0x02,
+ I2400M_TLV_TYPE_WAKEUP_MODE = 144,
+};
+
+struct i2400m_cmd_enter_power_save {
+ struct i2400m_l3l4_hdr hdr;
+ struct i2400m_tlv_hdr tlv;
+ __le32 val;
+} __attribute__((packed));
+
+
+/*
+ * Request entering power save
+ *
+ * This command is (mainly) executed when the device indicates that it
+ * is ready to go into powersave mode via a REPORT_POWERSAVE_READY.
+ */
+int i2400m_cmd_enter_powersave(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+ struct i2400m_cmd_enter_power_save *cmd;
+ char strerr[32];
+
+ result = -ENOMEM;
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ goto error_alloc;
+ cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_ENTER_POWERSAVE);
+ cmd->hdr.length = cpu_to_le16(sizeof(*cmd) - sizeof(cmd->hdr));
+ cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION);
+ cmd->tlv.type = cpu_to_le16(I2400M_TLV_TYPE_WAKEUP_MODE);
+ cmd->tlv.length = cpu_to_le16(sizeof(cmd->val));
+ cmd->val = cpu_to_le32(I2400M_WAKEUP_ENABLED);
+
+ ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
+ result = PTR_ERR(ack_skb);
+ if (IS_ERR(ack_skb)) {
+ dev_err(dev, "Failed to issue 'Enter power save' command: %d\n",
+ result);
+ goto error_msg_to_dev;
+ }
+ result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
+ strerr, sizeof(strerr));
+ if (result == -EACCES)
+ d_printf(1, dev, "Cannot enter power save mode\n");
+ else if (result < 0)
+ dev_err(dev, "'Enter power save' (0x%04x) command failed: "
+ "%d - %s\n", I2400M_MT_CMD_ENTER_POWERSAVE,
+ result, strerr);
+ else
+ d_printf(1, dev, "device ready to power save\n");
+ kfree_skb(ack_skb);
+error_msg_to_dev:
+ kfree(cmd);
+error_alloc:
+ return result;
+}
+EXPORT_SYMBOL_GPL(i2400m_cmd_enter_powersave);
+
+
+/*
+ * Definitions for getting device information
+ */
+enum {
+ I2400M_TLV_DETAILED_DEVICE_INFO = 140
+};
+
+/**
+ * i2400m_get_device_info - Query the device for detailed device information
+ *
+ * @i2400m: device descriptor
+ *
+ * Returns: an skb whose skb->data points to a 'struct
+ * i2400m_tlv_detailed_device_info'. When done, kfree_skb() it. The
+ * skb is *guaranteed* to contain the whole TLV data structure.
+ *
+ * On error, IS_ERR(skb) is true and ERR_PTR(skb) is the error
+ * code.
+ */
+struct sk_buff *i2400m_get_device_info(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+ struct i2400m_l3l4_hdr *cmd;
+ const struct i2400m_l3l4_hdr *ack;
+ size_t ack_len;
+ const struct i2400m_tlv_hdr *tlv;
+ const struct i2400m_tlv_detailed_device_info *ddi;
+ char strerr[32];
+
+ ack_skb = ERR_PTR(-ENOMEM);
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ goto error_alloc;
+ cmd->type = cpu_to_le16(I2400M_MT_GET_DEVICE_INFO);
+ cmd->length = 0;
+ cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
+
+ ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
+ if (IS_ERR(ack_skb)) {
+ dev_err(dev, "Failed to issue 'get device info' command: %ld\n",
+ PTR_ERR(ack_skb));
+ goto error_msg_to_dev;
+ }
+ ack = wimax_msg_data_len(ack_skb, &ack_len);
+ result = i2400m_msg_check_status(ack, strerr, sizeof(strerr));
+ if (result < 0) {
+ dev_err(dev, "'get device info' (0x%04x) command failed: "
+ "%d - %s\n", I2400M_MT_GET_DEVICE_INFO, result,
+ strerr);
+ goto error_cmd_failed;
+ }
+ tlv = i2400m_tlv_find(i2400m, ack->pl, ack_len - sizeof(*ack),
+ I2400M_TLV_DETAILED_DEVICE_INFO, sizeof(*ddi));
+ if (tlv == NULL) {
+ dev_err(dev, "GET DEVICE INFO: "
+ "detailed device info TLV not found (0x%04x)\n",
+ I2400M_TLV_DETAILED_DEVICE_INFO);
+ result = -EIO;
+ goto error_no_tlv;
+ }
+ skb_pull(ack_skb, (void *) tlv - (void *) ack_skb->data);
+error_msg_to_dev:
+ kfree(cmd);
+error_alloc:
+ return ack_skb;
+
+error_no_tlv:
+error_cmd_failed:
+ kfree_skb(ack_skb);
+ kfree(cmd);
+ return ERR_PTR(result);
+}
+
+
+/* Firmware interface versions we support */
+enum {
+ I2400M_HDIv_MAJOR = 9,
+ I2400M_HDIv_MAJOR_2 = 8,
+ I2400M_HDIv_MINOR = 1,
+};
+
+
+/**
+ * i2400m_firmware_check - check firmware versions are compatible with
+ * the driver
+ *
+ * @i2400m: device descriptor
+ *
+ * Returns: 0 if ok, < 0 errno code an error and a message in the
+ * kernel log.
+ *
+ * Long function, but quite simple; first chunk launches the command
+ * and double checks the reply for the right TLV. Then we process the
+ * TLV (where the meat is).
+ */
+int i2400m_firmware_check(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+ struct i2400m_l3l4_hdr *cmd;
+ const struct i2400m_l3l4_hdr *ack;
+ size_t ack_len;
+ const struct i2400m_tlv_hdr *tlv;
+ const struct i2400m_tlv_l4_message_versions *l4mv;
+ char strerr[32];
+ unsigned major, minor, branch;
+
+ result = -ENOMEM;
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ goto error_alloc;
+ cmd->type = cpu_to_le16(I2400M_MT_GET_LM_VERSION);
+ cmd->length = 0;
+ cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
+
+ ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
+ if (IS_ERR(ack_skb)) {
+ result = PTR_ERR(ack_skb);
+ dev_err(dev, "Failed to issue 'get lm version' command: %-d\n",
+ result);
+ goto error_msg_to_dev;
+ }
+ ack = wimax_msg_data_len(ack_skb, &ack_len);
+ result = i2400m_msg_check_status(ack, strerr, sizeof(strerr));
+ if (result < 0) {
+ dev_err(dev, "'get lm version' (0x%04x) command failed: "
+ "%d - %s\n", I2400M_MT_GET_LM_VERSION, result,
+ strerr);
+ goto error_cmd_failed;
+ }
+ tlv = i2400m_tlv_find(i2400m, ack->pl, ack_len - sizeof(*ack),
+ I2400M_TLV_L4_MESSAGE_VERSIONS, sizeof(*l4mv));
+ if (tlv == NULL) {
+ dev_err(dev, "get lm version: TLV not found (0x%04x)\n",
+ I2400M_TLV_L4_MESSAGE_VERSIONS);
+ result = -EIO;
+ goto error_no_tlv;
+ }
+ l4mv = container_of(tlv, typeof(*l4mv), hdr);
+ major = le16_to_cpu(l4mv->major);
+ minor = le16_to_cpu(l4mv->minor);
+ branch = le16_to_cpu(l4mv->branch);
+ result = -EINVAL;
+ if (major != I2400M_HDIv_MAJOR
+ && major != I2400M_HDIv_MAJOR_2) {
+ dev_err(dev, "unsupported major fw interface version "
+ "%u.%u.%u\n", major, minor, branch);
+ goto error_bad_major;
+ }
+ if (major == I2400M_HDIv_MAJOR_2)
+ dev_err(dev, "deprecated major fw interface version "
+ "%u.%u.%u\n", major, minor, branch);
+ result = 0;
+ if (minor != I2400M_HDIv_MINOR)
+ dev_warn(dev, "untested minor fw firmware version %u.%u.%u\n",
+ major, minor, branch);
+error_bad_major:
+ dev_info(dev, "firmware interface version %u.%u.%u\n",
+ major, minor, branch);
+error_no_tlv:
+error_cmd_failed:
+ kfree_skb(ack_skb);
+error_msg_to_dev:
+ kfree(cmd);
+error_alloc:
+ return result;
+}
+
+
+/*
+ * Send an DoExitIdle command to the device to ask it to go out of
+ * basestation-idle mode.
+ *
+ * @i2400m: device descriptor
+ *
+ * This starts a renegotiation with the basestation that might involve
+ * another crypto handshake with user space.
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ */
+int i2400m_cmd_exit_idle(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+ struct i2400m_l3l4_hdr *cmd;
+ char strerr[32];
+
+ result = -ENOMEM;
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ goto error_alloc;
+ cmd->type = cpu_to_le16(I2400M_MT_CMD_EXIT_IDLE);
+ cmd->length = 0;
+ cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
+
+ ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
+ result = PTR_ERR(ack_skb);
+ if (IS_ERR(ack_skb)) {
+ dev_err(dev, "Failed to issue 'exit idle' command: %d\n",
+ result);
+ goto error_msg_to_dev;
+ }
+ result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
+ strerr, sizeof(strerr));
+ kfree_skb(ack_skb);
+error_msg_to_dev:
+ kfree(cmd);
+error_alloc:
+ return result;
+
+}
+
+
+/*
+ * Query the device for its state, update the WiMAX stack's idea of it
+ *
+ * @i2400m: device descriptor
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ *
+ * Executes a 'Get State' command and parses the returned
+ * TLVs.
+ *
+ * Because this is almost identical to a 'Report State', we use
+ * i2400m_report_state_hook() to parse the answer. This will set the
+ * carrier state, as well as the RF Kill switches state.
+ */
+int i2400m_cmd_get_state(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+ struct i2400m_l3l4_hdr *cmd;
+ const struct i2400m_l3l4_hdr *ack;
+ size_t ack_len;
+ char strerr[32];
+
+ result = -ENOMEM;
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ goto error_alloc;
+ cmd->type = cpu_to_le16(I2400M_MT_GET_STATE);
+ cmd->length = 0;
+ cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
+
+ ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
+ if (IS_ERR(ack_skb)) {
+ dev_err(dev, "Failed to issue 'get state' command: %ld\n",
+ PTR_ERR(ack_skb));
+ result = PTR_ERR(ack_skb);
+ goto error_msg_to_dev;
+ }
+ ack = wimax_msg_data_len(ack_skb, &ack_len);
+ result = i2400m_msg_check_status(ack, strerr, sizeof(strerr));
+ if (result < 0) {
+ dev_err(dev, "'get state' (0x%04x) command failed: "
+ "%d - %s\n", I2400M_MT_GET_STATE, result, strerr);
+ goto error_cmd_failed;
+ }
+ i2400m_report_state_hook(i2400m, ack, ack_len - sizeof(*ack),
+ "GET STATE");
+ result = 0;
+ kfree_skb(ack_skb);
+error_cmd_failed:
+error_msg_to_dev:
+ kfree(cmd);
+error_alloc:
+ return result;
+}
+EXPORT_SYMBOL_GPL(i2400m_cmd_get_state);
+
+
+/**
+ * Set basic configuration settings
+ *
+ * @i2400m: device descriptor
+ * @args: array of pointers to the TLV headers to send for
+ * configuration (each followed by its payload).
+ * TLV headers and payloads must be properly initialized, with the
+ * right endianess (LE).
+ * @arg_size: number of pointers in the @args array
+ */
+int i2400m_set_init_config(struct i2400m *i2400m,
+ const struct i2400m_tlv_hdr **arg, size_t args)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+ struct i2400m_l3l4_hdr *cmd;
+ char strerr[32];
+ unsigned argc, argsize, tlv_size;
+ const struct i2400m_tlv_hdr *tlv_hdr;
+ void *buf, *itr;
+
+ d_fnstart(3, dev, "(i2400m %p arg %p args %zu)\n", i2400m, arg, args);
+ result = 0;
+ if (args == 0)
+ goto none;
+ /* Compute the size of all the TLVs, so we can alloc a
+ * contiguous command block to copy them. */
+ argsize = 0;
+ for (argc = 0; argc < args; argc++) {
+ tlv_hdr = arg[argc];
+ argsize += sizeof(*tlv_hdr) + le16_to_cpu(tlv_hdr->length);
+ }
+ WARN_ON(argc >= 9); /* As per hw spec */
+
+ /* Alloc the space for the command and TLVs*/
+ result = -ENOMEM;
+ buf = kzalloc(sizeof(*cmd) + argsize, GFP_KERNEL);
+ if (buf == NULL)
+ goto error_alloc;
+ cmd = buf;
+ cmd->type = cpu_to_le16(I2400M_MT_SET_INIT_CONFIG);
+ cmd->length = cpu_to_le16(argsize);
+ cmd->version = cpu_to_le16(I2400M_L3L4_VERSION);
+
+ /* Copy the TLVs */
+ itr = buf + sizeof(*cmd);
+ for (argc = 0; argc < args; argc++) {
+ tlv_hdr = arg[argc];
+ tlv_size = sizeof(*tlv_hdr) + le16_to_cpu(tlv_hdr->length);
+ memcpy(itr, tlv_hdr, tlv_size);
+ itr += tlv_size;
+ }
+
+ /* Send the message! */
+ ack_skb = i2400m_msg_to_dev(i2400m, buf, sizeof(*cmd) + argsize);
+ result = PTR_ERR(ack_skb);
+ if (IS_ERR(ack_skb)) {
+ dev_err(dev, "Failed to issue 'init config' command: %d\n",
+ result);
+
+ goto error_msg_to_dev;
+ }
+ result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
+ strerr, sizeof(strerr));
+ if (result < 0)
+ dev_err(dev, "'init config' (0x%04x) command failed: %d - %s\n",
+ I2400M_MT_SET_INIT_CONFIG, result, strerr);
+ kfree_skb(ack_skb);
+error_msg_to_dev:
+ kfree(buf);
+error_alloc:
+none:
+ d_fnend(3, dev, "(i2400m %p arg %p args %zu) = %d\n",
+ i2400m, arg, args, result);
+ return result;
+
+}
+EXPORT_SYMBOL_GPL(i2400m_set_init_config);
+
+
+/**
+ * i2400m_dev_initialize - Initialize the device once communications are ready
+ *
+ * @i2400m: device descriptor
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ *
+ * Configures the device to work the way we like it.
+ *
+ * At the point of this call, the device is registered with the WiMAX
+ * and netdev stacks, firmware is uploaded and we can talk to the
+ * device normally.
+ */
+int i2400m_dev_initialize(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400m_tlv_config_idle_parameters idle_params;
+ const struct i2400m_tlv_hdr *args[9];
+ unsigned argc = 0;
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ /* Useless for now...might change */
+ if (i2400m_idle_mode_disabled) {
+ idle_params.hdr.type =
+ cpu_to_le16(I2400M_TLV_CONFIG_IDLE_PARAMETERS);
+ idle_params.hdr.length = cpu_to_le16(
+ sizeof(idle_params) - sizeof(idle_params.hdr));
+ idle_params.idle_timeout = 0;
+ idle_params.idle_paging_interval = 0;
+ args[argc++] = &idle_params.hdr;
+ }
+ result = i2400m_set_init_config(i2400m, args, argc);
+ if (result < 0)
+ goto error;
+ result = i2400m_firmware_check(i2400m); /* fw versions ok? */
+ if (result < 0)
+ goto error;
+ /*
+ * Update state: Here it just calls a get state; parsing the
+ * result (System State TLV and RF Status TLV [done in the rx
+ * path hooks]) will set the hardware and software RF-Kill
+ * status.
+ */
+ result = i2400m_cmd_get_state(i2400m);
+error:
+ d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
+ return result;
+}
+
+
+/**
+ * i2400m_dev_shutdown - Shutdown a running device
+ *
+ * @i2400m: device descriptor
+ *
+ * Gracefully stops the device, moving it to the lowest power
+ * consumption state possible.
+ */
+void i2400m_dev_shutdown(struct i2400m *i2400m)
+{
+ int result = -ENODEV;
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ result = i2400m->bus_reset(i2400m, I2400M_RT_WARM);
+ d_fnend(3, dev, "(i2400m %p) = void [%d]\n", i2400m, result);
+ return;
+}
diff --git a/drivers/net/wimax/i2400m/debug-levels.h b/drivers/net/wimax/i2400m/debug-levels.h
new file mode 100644
index 000000000000..3183baa16a52
--- /dev/null
+++ b/drivers/net/wimax/i2400m/debug-levels.h
@@ -0,0 +1,45 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Debug levels control file for the i2400m module
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __debug_levels__h__
+#define __debug_levels__h__
+
+/* Maximum compile and run time debug level for all submodules */
+#define D_MODULENAME i2400m
+#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
+
+#include <linux/wimax/debug.h>
+
+/* List of all the enabled modules */
+enum d_module {
+ D_SUBMODULE_DECLARE(control),
+ D_SUBMODULE_DECLARE(driver),
+ D_SUBMODULE_DECLARE(debugfs),
+ D_SUBMODULE_DECLARE(fw),
+ D_SUBMODULE_DECLARE(netdev),
+ D_SUBMODULE_DECLARE(rfkill),
+ D_SUBMODULE_DECLARE(rx),
+ D_SUBMODULE_DECLARE(tx),
+};
+
+
+#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
new file mode 100644
index 000000000000..9b81af3f80a9
--- /dev/null
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -0,0 +1,378 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Debugfs interfaces to manipulate driver and device information
+ *
+ *
+ * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include "i2400m.h"
+
+
+#define D_SUBMODULE debugfs
+#include "debug-levels.h"
+
+static
+int debugfs_netdev_queue_stopped_get(void *data, u64 *val)
+{
+ struct i2400m *i2400m = data;
+ *val = netif_queue_stopped(i2400m->wimax_dev.net_dev);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_netdev_queue_stopped,
+ debugfs_netdev_queue_stopped_get,
+ NULL, "%llu\n");
+
+
+static
+struct dentry *debugfs_create_netdev_queue_stopped(
+ const char *name, struct dentry *parent, struct i2400m *i2400m)
+{
+ return debugfs_create_file(name, 0400, parent, i2400m,
+ &fops_netdev_queue_stopped);
+}
+
+
+/*
+ * inode->i_private has the @data argument to debugfs_create_file()
+ */
+static
+int i2400m_stats_open(struct inode *inode, struct file *filp)
+{
+ filp->private_data = inode->i_private;
+ return 0;
+}
+
+/*
+ * We don't allow partial reads of this file, as then the reader would
+ * get weirdly confused data as it is updated.
+ *
+ * So or you read it all or nothing; if you try to read with an offset
+ * != 0, we consider you are done reading.
+ */
+static
+ssize_t i2400m_rx_stats_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct i2400m *i2400m = filp->private_data;
+ char buf[128];
+ unsigned long flags;
+
+ if (*ppos != 0)
+ return 0;
+ if (count < sizeof(buf))
+ return -ENOSPC;
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n",
+ i2400m->rx_pl_num, i2400m->rx_pl_min,
+ i2400m->rx_pl_max, i2400m->rx_num,
+ i2400m->rx_size_acc,
+ i2400m->rx_size_min, i2400m->rx_size_max);
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+ return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
+}
+
+
+/* Any write clears the stats */
+static
+ssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct i2400m *i2400m = filp->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ i2400m->rx_pl_num = 0;
+ i2400m->rx_pl_max = 0;
+ i2400m->rx_pl_min = UINT_MAX;
+ i2400m->rx_num = 0;
+ i2400m->rx_size_acc = 0;
+ i2400m->rx_size_min = UINT_MAX;
+ i2400m->rx_size_max = 0;
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+ return count;
+}
+
+static
+const struct file_operations i2400m_rx_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = i2400m_stats_open,
+ .read = i2400m_rx_stats_read,
+ .write = i2400m_rx_stats_write,
+};
+
+
+/* See i2400m_rx_stats_read() */
+static
+ssize_t i2400m_tx_stats_read(struct file *filp, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct i2400m *i2400m = filp->private_data;
+ char buf[128];
+ unsigned long flags;
+
+ if (*ppos != 0)
+ return 0;
+ if (count < sizeof(buf))
+ return -ENOSPC;
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+ snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n",
+ i2400m->tx_pl_num, i2400m->tx_pl_min,
+ i2400m->tx_pl_max, i2400m->tx_num,
+ i2400m->tx_size_acc,
+ i2400m->tx_size_min, i2400m->tx_size_max);
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+ return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
+}
+
+/* Any write clears the stats */
+static
+ssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct i2400m *i2400m = filp->private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+ i2400m->tx_pl_num = 0;
+ i2400m->tx_pl_max = 0;
+ i2400m->tx_pl_min = UINT_MAX;
+ i2400m->tx_num = 0;
+ i2400m->tx_size_acc = 0;
+ i2400m->tx_size_min = UINT_MAX;
+ i2400m->tx_size_max = 0;
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+ return count;
+}
+
+static
+const struct file_operations i2400m_tx_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = i2400m_stats_open,
+ .read = i2400m_tx_stats_read,
+ .write = i2400m_tx_stats_write,
+};
+
+
+/* Write 1 to ask the device to go into suspend */
+static
+int debugfs_i2400m_suspend_set(void *data, u64 val)
+{
+ int result;
+ struct i2400m *i2400m = data;
+ result = i2400m_cmd_enter_powersave(i2400m);
+ if (result >= 0)
+ result = 0;
+ return result;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_suspend,
+ NULL, debugfs_i2400m_suspend_set,
+ "%llu\n");
+
+static
+struct dentry *debugfs_create_i2400m_suspend(
+ const char *name, struct dentry *parent, struct i2400m *i2400m)
+{
+ return debugfs_create_file(name, 0200, parent, i2400m,
+ &fops_i2400m_suspend);
+}
+
+
+/*
+ * Reset the device
+ *
+ * Write 0 to ask the device to soft reset, 1 to cold reset, 2 to bus
+ * reset (as defined by enum i2400m_reset_type).
+ */
+static
+int debugfs_i2400m_reset_set(void *data, u64 val)
+{
+ int result;
+ struct i2400m *i2400m = data;
+ enum i2400m_reset_type rt = val;
+ switch(rt) {
+ case I2400M_RT_WARM:
+ case I2400M_RT_COLD:
+ case I2400M_RT_BUS:
+ result = i2400m->bus_reset(i2400m, rt);
+ if (result >= 0)
+ result = 0;
+ default:
+ result = -EINVAL;
+ }
+ return result;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_reset,
+ NULL, debugfs_i2400m_reset_set,
+ "%llu\n");
+
+static
+struct dentry *debugfs_create_i2400m_reset(
+ const char *name, struct dentry *parent, struct i2400m *i2400m)
+{
+ return debugfs_create_file(name, 0200, parent, i2400m,
+ &fops_i2400m_reset);
+}
+
+
+#define __debugfs_register(prefix, name, parent) \
+do { \
+ result = d_level_register_debugfs(prefix, name, parent); \
+ if (result < 0) \
+ goto error; \
+} while (0)
+
+
+int i2400m_debugfs_add(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct dentry *dentry = i2400m->wimax_dev.debugfs_dentry;
+ struct dentry *fd;
+
+ dentry = debugfs_create_dir("i2400m", dentry);
+ result = PTR_ERR(dentry);
+ if (IS_ERR(dentry)) {
+ if (result == -ENODEV)
+ result = 0; /* No debugfs support */
+ goto error;
+ }
+ i2400m->debugfs_dentry = dentry;
+ __debugfs_register("dl_", control, dentry);
+ __debugfs_register("dl_", driver, dentry);
+ __debugfs_register("dl_", debugfs, dentry);
+ __debugfs_register("dl_", fw, dentry);
+ __debugfs_register("dl_", netdev, dentry);
+ __debugfs_register("dl_", rfkill, dentry);
+ __debugfs_register("dl_", rx, dentry);
+ __debugfs_register("dl_", tx, dentry);
+
+ fd = debugfs_create_size_t("tx_in", 0400, dentry,
+ &i2400m->tx_in);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "tx_in: %d\n", result);
+ goto error;
+ }
+
+ fd = debugfs_create_size_t("tx_out", 0400, dentry,
+ &i2400m->tx_out);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "tx_out: %d\n", result);
+ goto error;
+ }
+
+ fd = debugfs_create_u32("state", 0600, dentry,
+ &i2400m->state);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "state: %d\n", result);
+ goto error;
+ }
+
+ /*
+ * Trace received messages from user space
+ *
+ * In order to tap the bidirectional message stream in the
+ * 'msg' pipe, user space can read from the 'msg' pipe;
+ * however, due to limitations in libnl, we can't know what
+ * the different applications are sending down to the kernel.
+ *
+ * So we have this hack where the driver will echo any message
+ * received on the msg pipe from user space [through a call to
+ * wimax_dev->op_msg_from_user() into
+ * i2400m_op_msg_from_user()] into the 'trace' pipe that this
+ * driver creates.
+ *
+ * So then, reading from both the 'trace' and 'msg' pipes in
+ * user space will provide a full dump of the traffic.
+ *
+ * Write 1 to activate, 0 to clear.
+ *
+ * It is not really very atomic, but it is also not too
+ * critical.
+ */
+ fd = debugfs_create_u8("trace_msg_from_user", 0600, dentry,
+ &i2400m->trace_msg_from_user);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "trace_msg_from_user: %d\n", result);
+ goto error;
+ }
+
+ fd = debugfs_create_netdev_queue_stopped("netdev_queue_stopped",
+ dentry, i2400m);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "netdev_queue_stopped: %d\n", result);
+ goto error;
+ }
+
+ fd = debugfs_create_file("rx_stats", 0600, dentry, i2400m,
+ &i2400m_rx_stats_fops);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "rx_stats: %d\n", result);
+ goto error;
+ }
+
+ fd = debugfs_create_file("tx_stats", 0600, dentry, i2400m,
+ &i2400m_tx_stats_fops);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "tx_stats: %d\n", result);
+ goto error;
+ }
+
+ fd = debugfs_create_i2400m_suspend("suspend", dentry, i2400m);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry suspend: %d\n",
+ result);
+ goto error;
+ }
+
+ fd = debugfs_create_i2400m_reset("reset", dentry, i2400m);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry reset: %d\n", result);
+ goto error;
+ }
+
+ result = 0;
+error:
+ return result;
+}
+
+void i2400m_debugfs_rm(struct i2400m *i2400m)
+{
+ debugfs_remove_recursive(i2400m->debugfs_dentry);
+}
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
new file mode 100644
index 000000000000..e80a0b65a754
--- /dev/null
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -0,0 +1,744 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Generic probe/disconnect, reset and message passing
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * See i2400m.h for driver documentation. This contains helpers for
+ * the driver model glue [_setup()/_release()], handling device resets
+ * [_dev_reset_handle()], and the backends for the WiMAX stack ops
+ * reset [_op_reset()] and message from user [_op_msg_from_user()].
+ *
+ * ROADMAP:
+ *
+ * i2400m_op_msg_from_user()
+ * i2400m_msg_to_dev()
+ * wimax_msg_to_user_send()
+ *
+ * i2400m_op_reset()
+ * i240m->bus_reset()
+ *
+ * i2400m_dev_reset_handle()
+ * __i2400m_dev_reset_handle()
+ * __i2400m_dev_stop()
+ * __i2400m_dev_start()
+ *
+ * i2400m_setup()
+ * i2400m_bootrom_init()
+ * register_netdev()
+ * i2400m_dev_start()
+ * __i2400m_dev_start()
+ * i2400m_dev_bootstrap()
+ * i2400m_tx_setup()
+ * i2400m->bus_dev_start()
+ * i2400m_check_mac_addr()
+ * wimax_dev_add()
+ *
+ * i2400m_release()
+ * wimax_dev_rm()
+ * i2400m_dev_stop()
+ * __i2400m_dev_stop()
+ * i2400m_dev_shutdown()
+ * i2400m->bus_dev_stop()
+ * i2400m_tx_release()
+ * unregister_netdev()
+ */
+#include "i2400m.h"
+#include <linux/wimax/i2400m.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#define D_SUBMODULE driver
+#include "debug-levels.h"
+
+
+int i2400m_idle_mode_disabled; /* 0 (idle mode enabled) by default */
+module_param_named(idle_mode_disabled, i2400m_idle_mode_disabled, int, 0644);
+MODULE_PARM_DESC(idle_mode_disabled,
+ "If true, the device will not enable idle mode negotiation "
+ "with the base station (when connected) to save power.");
+
+/**
+ * i2400m_queue_work - schedule work on a i2400m's queue
+ *
+ * @i2400m: device descriptor
+ *
+ * @fn: function to run to execute work. It gets passed a 'struct
+ * work_struct' that is wrapped in a 'struct i2400m_work'. Once
+ * done, you have to (1) i2400m_put(i2400m_work->i2400m) and then
+ * (2) kfree(i2400m_work).
+ *
+ * @gfp_flags: GFP flags for memory allocation.
+ *
+ * @pl: pointer to a payload buffer that you want to pass to the _work
+ * function. Use this to pack (for example) a struct with extra
+ * arguments.
+ *
+ * @pl_size: size of the payload buffer.
+ *
+ * We do this quite often, so this just saves typing; allocate a
+ * wrapper for a i2400m, get a ref to it, pack arguments and launch
+ * the work.
+ *
+ * A usual workflow is:
+ *
+ * struct my_work_args {
+ * void *something;
+ * int whatever;
+ * };
+ * ...
+ *
+ * struct my_work_args my_args = {
+ * .something = FOO,
+ * .whaetever = BLAH
+ * };
+ * i2400m_queue_work(i2400m, 1, my_work_function, GFP_KERNEL,
+ * &args, sizeof(args))
+ *
+ * And now the work function can unpack the arguments and call the
+ * real function (or do the job itself):
+ *
+ * static
+ * void my_work_fn((struct work_struct *ws)
+ * {
+ * struct i2400m_work *iw =
+ * container_of(ws, struct i2400m_work, ws);
+ * struct my_work_args *my_args = (void *) iw->pl;
+ *
+ * my_work(iw->i2400m, my_args->something, my_args->whatevert);
+ * }
+ */
+int i2400m_queue_work(struct i2400m *i2400m,
+ void (*fn)(struct work_struct *), gfp_t gfp_flags,
+ const void *pl, size_t pl_size)
+{
+ int result;
+ struct i2400m_work *iw;
+
+ BUG_ON(i2400m->work_queue == NULL);
+ result = -ENOMEM;
+ iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags);
+ if (iw == NULL)
+ goto error_kzalloc;
+ iw->i2400m = i2400m_get(i2400m);
+ memcpy(iw->pl, pl, pl_size);
+ INIT_WORK(&iw->ws, fn);
+ result = queue_work(i2400m->work_queue, &iw->ws);
+error_kzalloc:
+ return result;
+}
+EXPORT_SYMBOL_GPL(i2400m_queue_work);
+
+
+/*
+ * Schedule i2400m's specific work on the system's queue.
+ *
+ * Used for a few cases where we really need it; otherwise, identical
+ * to i2400m_queue_work().
+ *
+ * Returns < 0 errno code on error, 1 if ok.
+ *
+ * If it returns zero, something really bad happened, as it means the
+ * works struct was already queued, but we have just allocated it, so
+ * it should not happen.
+ */
+int i2400m_schedule_work(struct i2400m *i2400m,
+ void (*fn)(struct work_struct *), gfp_t gfp_flags)
+{
+ int result;
+ struct i2400m_work *iw;
+
+ BUG_ON(i2400m->work_queue == NULL);
+ result = -ENOMEM;
+ iw = kzalloc(sizeof(*iw), gfp_flags);
+ if (iw == NULL)
+ goto error_kzalloc;
+ iw->i2400m = i2400m_get(i2400m);
+ INIT_WORK(&iw->ws, fn);
+ result = schedule_work(&iw->ws);
+ if (result == 0)
+ result = -ENXIO;
+error_kzalloc:
+ return result;
+}
+
+
+/*
+ * WiMAX stack operation: relay a message from user space
+ *
+ * @wimax_dev: device descriptor
+ * @pipe_name: named pipe the message is for
+ * @msg_buf: pointer to the message bytes
+ * @msg_len: length of the buffer
+ * @genl_info: passed by the generic netlink layer
+ *
+ * The WiMAX stack will call this function when a message was received
+ * from user space.
+ *
+ * For the i2400m, this is an L3L4 message, as specified in
+ * include/linux/wimax/i2400m.h, and thus prefixed with a 'struct
+ * i2400m_l3l4_hdr'. Driver (and device) expect the messages to be
+ * coded in Little Endian.
+ *
+ * This function just verifies that the header declaration and the
+ * payload are consistent and then deals with it, either forwarding it
+ * to the device or procesing it locally.
+ *
+ * In the i2400m, messages are basically commands that will carry an
+ * ack, so we use i2400m_msg_to_dev() and then deliver the ack back to
+ * user space. The rx.c code might intercept the response and use it
+ * to update the driver's state, but then it will pass it on so it can
+ * be relayed back to user space.
+ *
+ * Note that asynchronous events from the device are processed and
+ * sent to user space in rx.c.
+ */
+static
+int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev,
+ const char *pipe_name,
+ const void *msg_buf, size_t msg_len,
+ const struct genl_info *genl_info)
+{
+ int result;
+ struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+
+ d_fnstart(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p "
+ "msg_len %zu genl_info %p)\n", wimax_dev, i2400m,
+ msg_buf, msg_len, genl_info);
+ ack_skb = i2400m_msg_to_dev(i2400m, msg_buf, msg_len);
+ result = PTR_ERR(ack_skb);
+ if (IS_ERR(ack_skb))
+ goto error_msg_to_dev;
+ if (unlikely(i2400m->trace_msg_from_user))
+ wimax_msg(&i2400m->wimax_dev, "trace",
+ msg_buf, msg_len, GFP_KERNEL);
+ result = wimax_msg_send(&i2400m->wimax_dev, ack_skb);
+error_msg_to_dev:
+ d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu "
+ "genl_info %p) = %d\n", wimax_dev, i2400m, msg_buf, msg_len,
+ genl_info, result);
+ return result;
+}
+
+
+/*
+ * Context to wait for a reset to finalize
+ */
+struct i2400m_reset_ctx {
+ struct completion completion;
+ int result;
+};
+
+
+/*
+ * WiMAX stack operation: reset a device
+ *
+ * @wimax_dev: device descriptor
+ *
+ * See the documentation for wimax_reset() and wimax_dev->op_reset for
+ * the requirements of this function. The WiMAX stack guarantees
+ * serialization on calls to this function.
+ *
+ * Do a warm reset on the device; if it fails, resort to a cold reset
+ * and return -ENODEV. On successful warm reset, we need to block
+ * until it is complete.
+ *
+ * The bus-driver implementation of reset takes care of falling back
+ * to cold reset if warm fails.
+ */
+static
+int i2400m_op_reset(struct wimax_dev *wimax_dev)
+{
+ int result;
+ struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400m_reset_ctx ctx = {
+ .completion = COMPLETION_INITIALIZER_ONSTACK(ctx.completion),
+ .result = 0,
+ };
+
+ d_fnstart(4, dev, "(wimax_dev %p)\n", wimax_dev);
+ mutex_lock(&i2400m->init_mutex);
+ i2400m->reset_ctx = &ctx;
+ mutex_unlock(&i2400m->init_mutex);
+ result = i2400m->bus_reset(i2400m, I2400M_RT_WARM);
+ if (result < 0)
+ goto out;
+ result = wait_for_completion_timeout(&ctx.completion, 4*HZ);
+ if (result == 0)
+ result = -ETIMEDOUT;
+ else if (result > 0)
+ result = ctx.result;
+ /* if result < 0, pass it on */
+ mutex_lock(&i2400m->init_mutex);
+ i2400m->reset_ctx = NULL;
+ mutex_unlock(&i2400m->init_mutex);
+out:
+ d_fnend(4, dev, "(wimax_dev %p) = %d\n", wimax_dev, result);
+ return result;
+}
+
+
+/*
+ * Check the MAC address we got from boot mode is ok
+ *
+ * @i2400m: device descriptor
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ */
+static
+int i2400m_check_mac_addr(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *skb;
+ const struct i2400m_tlv_detailed_device_info *ddi;
+ struct net_device *net_dev = i2400m->wimax_dev.net_dev;
+ const unsigned char zeromac[ETH_ALEN] = { 0 };
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ skb = i2400m_get_device_info(i2400m);
+ if (IS_ERR(skb)) {
+ result = PTR_ERR(skb);
+ dev_err(dev, "Cannot verify MAC address, error reading: %d\n",
+ result);
+ goto error;
+ }
+ /* Extract MAC addresss */
+ ddi = (void *) skb->data;
+ BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address));
+ d_printf(2, dev, "GET DEVICE INFO: mac addr "
+ "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ ddi->mac_address[0], ddi->mac_address[1],
+ ddi->mac_address[2], ddi->mac_address[3],
+ ddi->mac_address[4], ddi->mac_address[5]);
+ if (!memcmp(net_dev->perm_addr, ddi->mac_address,
+ sizeof(ddi->mac_address)))
+ goto ok;
+ dev_warn(dev, "warning: device reports a different MAC address "
+ "to that of boot mode's\n");
+ dev_warn(dev, "device reports %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ddi->mac_address[0], ddi->mac_address[1],
+ ddi->mac_address[2], ddi->mac_address[3],
+ ddi->mac_address[4], ddi->mac_address[5]);
+ dev_warn(dev, "boot mode reported %02x:%02x:%02x:%02x:%02x:%02x\n",
+ net_dev->perm_addr[0], net_dev->perm_addr[1],
+ net_dev->perm_addr[2], net_dev->perm_addr[3],
+ net_dev->perm_addr[4], net_dev->perm_addr[5]);
+ if (!memcmp(zeromac, ddi->mac_address, sizeof(zeromac)))
+ dev_err(dev, "device reports an invalid MAC address, "
+ "not updating\n");
+ else {
+ dev_warn(dev, "updating MAC address\n");
+ net_dev->addr_len = ETH_ALEN;
+ memcpy(net_dev->perm_addr, ddi->mac_address, ETH_ALEN);
+ memcpy(net_dev->dev_addr, ddi->mac_address, ETH_ALEN);
+ }
+ok:
+ result = 0;
+ kfree_skb(skb);
+error:
+ d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
+ return result;
+}
+
+
+/**
+ * __i2400m_dev_start - Bring up driver communication with the device
+ *
+ * @i2400m: device descriptor
+ * @flags: boot mode flags
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ *
+ * Uploads firmware and brings up all the resources needed to be able
+ * to communicate with the device.
+ *
+ * TX needs to be setup before the bus-specific code (otherwise on
+ * shutdown, the bus-tx code could try to access it).
+ */
+static
+int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)
+{
+ int result;
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+ struct net_device *net_dev = wimax_dev->net_dev;
+ struct device *dev = i2400m_dev(i2400m);
+ int times = 3;
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+retry:
+ result = i2400m_dev_bootstrap(i2400m, flags);
+ if (result < 0) {
+ dev_err(dev, "cannot bootstrap device: %d\n", result);
+ goto error_bootstrap;
+ }
+ result = i2400m_tx_setup(i2400m);
+ if (result < 0)
+ goto error_tx_setup;
+ result = i2400m->bus_dev_start(i2400m);
+ if (result < 0)
+ goto error_bus_dev_start;
+ i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name);
+ if (i2400m->work_queue == NULL) {
+ result = -ENOMEM;
+ dev_err(dev, "cannot create workqueue\n");
+ goto error_create_workqueue;
+ }
+ /* At this point is ok to send commands to the device */
+ result = i2400m_check_mac_addr(i2400m);
+ if (result < 0)
+ goto error_check_mac_addr;
+ i2400m->ready = 1;
+ wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED);
+ result = i2400m_dev_initialize(i2400m);
+ if (result < 0)
+ goto error_dev_initialize;
+ /* At this point, reports will come for the device and set it
+ * to the right state if it is different than UNINITIALIZED */
+ d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
+ net_dev, i2400m, result);
+ return result;
+
+error_dev_initialize:
+error_check_mac_addr:
+ destroy_workqueue(i2400m->work_queue);
+error_create_workqueue:
+ i2400m->bus_dev_stop(i2400m);
+error_bus_dev_start:
+ i2400m_tx_release(i2400m);
+error_tx_setup:
+error_bootstrap:
+ if (result == -ERESTARTSYS && times-- > 0) {
+ flags = I2400M_BRI_SOFT;
+ goto retry;
+ }
+ d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
+ net_dev, i2400m, result);
+ return result;
+}
+
+
+static
+int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags)
+{
+ int result;
+ mutex_lock(&i2400m->init_mutex); /* Well, start the device */
+ result = __i2400m_dev_start(i2400m, bm_flags);
+ if (result >= 0)
+ i2400m->updown = 1;
+ mutex_unlock(&i2400m->init_mutex);
+ return result;
+}
+
+
+/**
+ * i2400m_dev_stop - Tear down driver communication with the device
+ *
+ * @i2400m: device descriptor
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ *
+ * Releases all the resources allocated to communicate with the device.
+ */
+static
+void __i2400m_dev_stop(struct i2400m *i2400m)
+{
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
+ i2400m_dev_shutdown(i2400m);
+ i2400m->ready = 0;
+ destroy_workqueue(i2400m->work_queue);
+ i2400m->bus_dev_stop(i2400m);
+ i2400m_tx_release(i2400m);
+ wimax_state_change(wimax_dev, WIMAX_ST_DOWN);
+ d_fnend(3, dev, "(i2400m %p) = 0\n", i2400m);
+}
+
+
+/*
+ * Watch out -- we only need to stop if there is a need for it. The
+ * device could have reset itself and failed to come up again (see
+ * _i2400m_dev_reset_handle()).
+ */
+static
+void i2400m_dev_stop(struct i2400m *i2400m)
+{
+ mutex_lock(&i2400m->init_mutex);
+ if (i2400m->updown) {
+ __i2400m_dev_stop(i2400m);
+ i2400m->updown = 0;
+ }
+ mutex_unlock(&i2400m->init_mutex);
+}
+
+
+/*
+ * The device has rebooted; fix up the device and the driver
+ *
+ * Tear down the driver communication with the device, reload the
+ * firmware and reinitialize the communication with the device.
+ *
+ * If someone calls a reset when the device's firmware is down, in
+ * theory we won't see it because we are not listening. However, just
+ * in case, leave the code to handle it.
+ *
+ * If there is a reset context, use it; this means someone is waiting
+ * for us to tell him when the reset operation is complete and the
+ * device is ready to rock again.
+ *
+ * NOTE: if we are in the process of bringing up or down the
+ * communication with the device [running i2400m_dev_start() or
+ * _stop()], don't do anything, let it fail and handle it.
+ *
+ * This function is ran always in a thread context
+ */
+static
+void __i2400m_dev_reset_handle(struct work_struct *ws)
+{
+ int result;
+ struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws);
+ struct i2400m *i2400m = iw->i2400m;
+ struct device *dev = i2400m_dev(i2400m);
+ enum wimax_st wimax_state;
+ struct i2400m_reset_ctx *ctx = i2400m->reset_ctx;
+
+ d_fnstart(3, dev, "(ws %p i2400m %p)\n", ws, i2400m);
+ result = 0;
+ if (mutex_trylock(&i2400m->init_mutex) == 0) {
+ /* We are still in i2400m_dev_start() [let it fail] or
+ * i2400m_dev_stop() [we are shutting down anyway, so
+ * ignore it] or we are resetting somewhere else. */
+ dev_err(dev, "device rebooted\n");
+ i2400m_msg_to_dev_cancel_wait(i2400m, -ERESTARTSYS);
+ complete(&i2400m->msg_completion);
+ goto out;
+ }
+ wimax_state = wimax_state_get(&i2400m->wimax_dev);
+ if (wimax_state < WIMAX_ST_UNINITIALIZED) {
+ dev_info(dev, "device rebooted: it is down, ignoring\n");
+ goto out_unlock; /* ifconfig up/down wasn't called */
+ }
+ dev_err(dev, "device rebooted: reinitializing driver\n");
+ __i2400m_dev_stop(i2400m);
+ i2400m->updown = 0;
+ result = __i2400m_dev_start(i2400m,
+ I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT);
+ if (result < 0) {
+ dev_err(dev, "device reboot: cannot start the device: %d\n",
+ result);
+ result = i2400m->bus_reset(i2400m, I2400M_RT_BUS);
+ if (result >= 0)
+ result = -ENODEV;
+ } else
+ i2400m->updown = 1;
+out_unlock:
+ if (i2400m->reset_ctx) {
+ ctx->result = result;
+ complete(&ctx->completion);
+ }
+ mutex_unlock(&i2400m->init_mutex);
+out:
+ i2400m_put(i2400m);
+ kfree(iw);
+ d_fnend(3, dev, "(ws %p i2400m %p) = void\n", ws, i2400m);
+ return;
+}
+
+
+/**
+ * i2400m_dev_reset_handle - Handle a device's reset in a thread context
+ *
+ * Schedule a device reset handling out on a thread context, so it
+ * is safe to call from atomic context. We can't use the i2400m's
+ * queue as we are going to destroy it and reinitialize it as part of
+ * the driver bringup/bringup process.
+ *
+ * See __i2400m_dev_reset_handle() for details; that takes care of
+ * reinitializing the driver to handle the reset, calling into the
+ * bus-specific functions ops as needed.
+ */
+int i2400m_dev_reset_handle(struct i2400m *i2400m)
+{
+ return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle,
+ GFP_ATOMIC);
+}
+EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle);
+
+
+/**
+ * i2400m_setup - bus-generic setup function for the i2400m device
+ *
+ * @i2400m: device descriptor (bus-specific parts have been initialized)
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ *
+ * Initializes the bus-generic parts of the i2400m driver; the
+ * bus-specific parts have been initialized, function pointers filled
+ * out by the bus-specific probe function.
+ *
+ * As well, this registers the WiMAX and net device nodes. Once this
+ * function returns, the device is operative and has to be ready to
+ * receive and send network traffic and WiMAX control operations.
+ */
+int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags)
+{
+ int result = -ENODEV;
+ struct device *dev = i2400m_dev(i2400m);
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+ struct net_device *net_dev = i2400m->wimax_dev.net_dev;
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+
+ snprintf(wimax_dev->name, sizeof(wimax_dev->name),
+ "i2400m-%s:%s", dev->bus->name, dev->bus_id);
+
+ i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL);
+ if (i2400m->bm_cmd_buf == NULL) {
+ dev_err(dev, "cannot allocate USB command buffer\n");
+ goto error_bm_cmd_kzalloc;
+ }
+ i2400m->bm_ack_buf = kzalloc(I2400M_BM_ACK_BUF_SIZE, GFP_KERNEL);
+ if (i2400m->bm_ack_buf == NULL) {
+ dev_err(dev, "cannot allocate USB ack buffer\n");
+ goto error_bm_ack_buf_kzalloc;
+ }
+ result = i2400m_bootrom_init(i2400m, bm_flags);
+ if (result < 0) {
+ dev_err(dev, "read mac addr: bootrom init "
+ "failed: %d\n", result);
+ goto error_bootrom_init;
+ }
+ result = i2400m_read_mac_addr(i2400m);
+ if (result < 0)
+ goto error_read_mac_addr;
+
+ result = register_netdev(net_dev); /* Okey dokey, bring it up */
+ if (result < 0) {
+ dev_err(dev, "cannot register i2400m network device: %d\n",
+ result);
+ goto error_register_netdev;
+ }
+ netif_carrier_off(net_dev);
+
+ result = i2400m_dev_start(i2400m, bm_flags);
+ if (result < 0)
+ goto error_dev_start;
+
+ i2400m->wimax_dev.op_msg_from_user = i2400m_op_msg_from_user;
+ i2400m->wimax_dev.op_rfkill_sw_toggle = i2400m_op_rfkill_sw_toggle;
+ i2400m->wimax_dev.op_reset = i2400m_op_reset;
+ result = wimax_dev_add(&i2400m->wimax_dev, net_dev);
+ if (result < 0)
+ goto error_wimax_dev_add;
+ /* User space needs to do some init stuff */
+ wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED);
+
+ /* Now setup all that requires a registered net and wimax device. */
+ result = i2400m_debugfs_add(i2400m);
+ if (result < 0) {
+ dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result);
+ goto error_debugfs_setup;
+ }
+ d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
+ return result;
+
+error_debugfs_setup:
+ wimax_dev_rm(&i2400m->wimax_dev);
+error_wimax_dev_add:
+ i2400m_dev_stop(i2400m);
+error_dev_start:
+ unregister_netdev(net_dev);
+error_register_netdev:
+error_read_mac_addr:
+error_bootrom_init:
+ kfree(i2400m->bm_ack_buf);
+error_bm_ack_buf_kzalloc:
+ kfree(i2400m->bm_cmd_buf);
+error_bm_cmd_kzalloc:
+ d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
+ return result;
+}
+EXPORT_SYMBOL_GPL(i2400m_setup);
+
+
+/**
+ * i2400m_release - release the bus-generic driver resources
+ *
+ * Sends a disconnect message and undoes any setup done by i2400m_setup()
+ */
+void i2400m_release(struct i2400m *i2400m)
+{
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ netif_stop_queue(i2400m->wimax_dev.net_dev);
+
+ i2400m_debugfs_rm(i2400m);
+ wimax_dev_rm(&i2400m->wimax_dev);
+ i2400m_dev_stop(i2400m);
+ unregister_netdev(i2400m->wimax_dev.net_dev);
+ kfree(i2400m->bm_ack_buf);
+ kfree(i2400m->bm_cmd_buf);
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+}
+EXPORT_SYMBOL_GPL(i2400m_release);
+
+
+/*
+ * Debug levels control; see debug.h
+ */
+struct d_level D_LEVEL[] = {
+ D_SUBMODULE_DEFINE(control),
+ D_SUBMODULE_DEFINE(driver),
+ D_SUBMODULE_DEFINE(debugfs),
+ D_SUBMODULE_DEFINE(fw),
+ D_SUBMODULE_DEFINE(netdev),
+ D_SUBMODULE_DEFINE(rfkill),
+ D_SUBMODULE_DEFINE(rx),
+ D_SUBMODULE_DEFINE(tx),
+};
+size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
+
+
+static
+int __init i2400m_driver_init(void)
+{
+ return 0;
+}
+module_init(i2400m_driver_init);
+
+static
+void __exit i2400m_driver_exit(void)
+{
+ /* for scheds i2400m_dev_reset_handle() */
+ flush_scheduled_work();
+ return;
+}
+module_exit(i2400m_driver_exit);
+
+MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
+MODULE_DESCRIPTION("Intel 2400M WiMAX networking bus-generic driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c
new file mode 100644
index 000000000000..1d8271f34c38
--- /dev/null
+++ b/drivers/net/wimax/i2400m/fw.c
@@ -0,0 +1,1095 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Firmware uploader
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Initial implementation
+ *
+ *
+ * THE PROCEDURE
+ *
+ * (this is decribed for USB, but for SDIO is similar)
+ *
+ * The 2400m works in two modes: boot-mode or normal mode. In boot
+ * mode we can execute only a handful of commands targeted at
+ * uploading the firmware and launching it.
+ *
+ * The 2400m enters boot mode when it is first connected to the
+ * system, when it crashes and when you ask it to reboot. There are
+ * two submodes of the boot mode: signed and non-signed. Signed takes
+ * firmwares signed with a certain private key, non-signed takes any
+ * firmware. Normal hardware takes only signed firmware.
+ *
+ * Upon entrance to boot mode, the device sends a few zero length
+ * packets (ZLPs) on the notification endpoint, then a reboot barker
+ * (4 le32 words with value I2400M_{S,N}BOOT_BARKER). We ack it by
+ * sending the same barker on the bulk out endpoint. The device acks
+ * with a reboot ack barker (4 le32 words with value 0xfeedbabe) and
+ * then the device is fully rebooted. At this point we can upload the
+ * firmware.
+ *
+ * This process is accomplished by the i2400m_bootrom_init()
+ * function. All the device interaction happens through the
+ * i2400m_bm_cmd() [boot mode command]. Special return values will
+ * indicate if the device resets.
+ *
+ * After this, we read the MAC address and then (if needed)
+ * reinitialize the device. We need to read it ahead of time because
+ * in the future, we might not upload the firmware until userspace
+ * 'ifconfig up's the device.
+ *
+ * We can then upload the firmware file. The file is composed of a BCF
+ * header (basic data, keys and signatures) and a list of write
+ * commands and payloads. We first upload the header
+ * [i2400m_dnload_init()] and then pass the commands and payloads
+ * verbatim to the i2400m_bm_cmd() function
+ * [i2400m_dnload_bcf()]. Then we tell the device to jump to the new
+ * firmware [i2400m_dnload_finalize()].
+ *
+ * Once firmware is uploaded, we are good to go :)
+ *
+ * When we don't know in which mode we are, we first try by sending a
+ * warm reset request that will take us to boot-mode. If we time out
+ * waiting for a reboot barker, that means maybe we are already in
+ * boot mode, so we send a reboot barker.
+ *
+ * COMMAND EXECUTION
+ *
+ * This code (and process) is single threaded; for executing commands,
+ * we post a URB to the notification endpoint, post the command, wait
+ * for data on the notification buffer. We don't need to worry about
+ * others as we know we are the only ones in there.
+ *
+ * BACKEND IMPLEMENTATION
+ *
+ * This code is bus-generic; the bus-specific driver provides back end
+ * implementations to send a boot mode command to the device and to
+ * read an acknolwedgement from it (or an asynchronous notification)
+ * from it.
+ *
+ * ROADMAP
+ *
+ * i2400m_dev_bootstrap Called by __i2400m_dev_start()
+ * request_firmware
+ * i2400m_fw_check
+ * i2400m_fw_dnload
+ * release_firmware
+ *
+ * i2400m_fw_dnload
+ * i2400m_bootrom_init
+ * i2400m_bm_cmd
+ * i2400m->bus_reset
+ * i2400m_dnload_init
+ * i2400m_dnload_init_signed
+ * i2400m_dnload_init_nonsigned
+ * i2400m_download_chunk
+ * i2400m_bm_cmd
+ * i2400m_dnload_bcf
+ * i2400m_bm_cmd
+ * i2400m_dnload_finalize
+ * i2400m_bm_cmd
+ *
+ * i2400m_bm_cmd
+ * i2400m->bus_bm_cmd_send()
+ * i2400m->bus_bm_wait_for_ack
+ * __i2400m_bm_ack_verify
+ *
+ * i2400m_bm_cmd_prepare Used by bus-drivers to prep
+ * commands before sending
+ */
+#include <linux/firmware.h>
+#include <linux/sched.h>
+#include <linux/usb.h>
+#include "i2400m.h"
+
+
+#define D_SUBMODULE fw
+#include "debug-levels.h"
+
+
+static const __le32 i2400m_ACK_BARKER[4] = {
+ __constant_cpu_to_le32(I2400M_ACK_BARKER),
+ __constant_cpu_to_le32(I2400M_ACK_BARKER),
+ __constant_cpu_to_le32(I2400M_ACK_BARKER),
+ __constant_cpu_to_le32(I2400M_ACK_BARKER)
+};
+
+
+/**
+ * Prepare a boot-mode command for delivery
+ *
+ * @cmd: pointer to bootrom header to prepare
+ *
+ * Computes checksum if so needed. After calling this function, DO NOT
+ * modify the command or header as the checksum won't work anymore.
+ *
+ * We do it from here because some times we cannot do it in the
+ * original context the command was sent (it is a const), so when we
+ * copy it to our staging buffer, we add the checksum there.
+ */
+void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *cmd)
+{
+ if (i2400m_brh_get_use_checksum(cmd)) {
+ int i;
+ u32 checksum = 0;
+ const u32 *checksum_ptr = (void *) cmd->payload;
+ for (i = 0; i < cmd->data_size / 4; i++)
+ checksum += cpu_to_le32(*checksum_ptr++);
+ checksum += cmd->command + cmd->target_addr + cmd->data_size;
+ cmd->block_checksum = cpu_to_le32(checksum);
+ }
+}
+EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare);
+
+
+/*
+ * Verify the ack data received
+ *
+ * Given a reply to a boot mode command, chew it and verify everything
+ * is ok.
+ *
+ * @opcode: opcode which generated this ack. For error messages.
+ * @ack: pointer to ack data we received
+ * @ack_size: size of that data buffer
+ * @flags: I2400M_BM_CMD_* flags we called the command with.
+ *
+ * Way too long function -- maybe it should be further split
+ */
+static
+ssize_t __i2400m_bm_ack_verify(struct i2400m *i2400m, int opcode,
+ struct i2400m_bootrom_header *ack,
+ size_t ack_size, int flags)
+{
+ ssize_t result = -ENOMEM;
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(8, dev, "(i2400m %p opcode %d ack %p size %zu)\n",
+ i2400m, opcode, ack, ack_size);
+ if (ack_size < sizeof(*ack)) {
+ result = -EIO;
+ dev_err(dev, "boot-mode cmd %d: HW BUG? notification didn't "
+ "return enough data (%zu bytes vs %zu expected)\n",
+ opcode, ack_size, sizeof(*ack));
+ goto error_ack_short;
+ }
+ if (ack_size == sizeof(i2400m_NBOOT_BARKER)
+ && memcmp(ack, i2400m_NBOOT_BARKER, sizeof(*ack)) == 0) {
+ result = -ERESTARTSYS;
+ i2400m->sboot = 0;
+ d_printf(6, dev, "boot-mode cmd %d: "
+ "HW non-signed boot barker\n", opcode);
+ goto error_reboot;
+ }
+ if (ack_size == sizeof(i2400m_SBOOT_BARKER)
+ && memcmp(ack, i2400m_SBOOT_BARKER, sizeof(*ack)) == 0) {
+ result = -ERESTARTSYS;
+ i2400m->sboot = 1;
+ d_printf(6, dev, "boot-mode cmd %d: HW signed reboot barker\n",
+ opcode);
+ goto error_reboot;
+ }
+ if (ack_size == sizeof(i2400m_ACK_BARKER)
+ && memcmp(ack, i2400m_ACK_BARKER, sizeof(*ack)) == 0) {
+ result = -EISCONN;
+ d_printf(3, dev, "boot-mode cmd %d: HW reboot ack barker\n",
+ opcode);
+ goto error_reboot_ack;
+ }
+ result = 0;
+ if (flags & I2400M_BM_CMD_RAW)
+ goto out_raw;
+ ack->data_size = le32_to_cpu(ack->data_size);
+ ack->target_addr = le32_to_cpu(ack->target_addr);
+ ack->block_checksum = le32_to_cpu(ack->block_checksum);
+ d_printf(5, dev, "boot-mode cmd %d: notification for opcode %u "
+ "response %u csum %u rr %u da %u\n",
+ opcode, i2400m_brh_get_opcode(ack),
+ i2400m_brh_get_response(ack),
+ i2400m_brh_get_use_checksum(ack),
+ i2400m_brh_get_response_required(ack),
+ i2400m_brh_get_direct_access(ack));
+ result = -EIO;
+ if (i2400m_brh_get_signature(ack) != 0xcbbc) {
+ dev_err(dev, "boot-mode cmd %d: HW BUG? wrong signature "
+ "0x%04x\n", opcode, i2400m_brh_get_signature(ack));
+ goto error_ack_signature;
+ }
+ if (opcode != -1 && opcode != i2400m_brh_get_opcode(ack)) {
+ dev_err(dev, "boot-mode cmd %d: HW BUG? "
+ "received response for opcode %u, expected %u\n",
+ opcode, i2400m_brh_get_opcode(ack), opcode);
+ goto error_ack_opcode;
+ }
+ if (i2400m_brh_get_response(ack) != 0) { /* failed? */
+ dev_err(dev, "boot-mode cmd %d: error; hw response %u\n",
+ opcode, i2400m_brh_get_response(ack));
+ goto error_ack_failed;
+ }
+ if (ack_size < ack->data_size + sizeof(*ack)) {
+ dev_err(dev, "boot-mode cmd %d: SW BUG "
+ "driver provided only %zu bytes for %zu bytes "
+ "of data\n", opcode, ack_size,
+ (size_t) le32_to_cpu(ack->data_size) + sizeof(*ack));
+ goto error_ack_short_buffer;
+ }
+ result = ack_size;
+ /* Don't you love this stack of empty targets? Well, I don't
+ * either, but it helps track exactly who comes in here and
+ * why :) */
+error_ack_short_buffer:
+error_ack_failed:
+error_ack_opcode:
+error_ack_signature:
+out_raw:
+error_reboot_ack:
+error_reboot:
+error_ack_short:
+ d_fnend(8, dev, "(i2400m %p opcode %d ack %p size %zu) = %d\n",
+ i2400m, opcode, ack, ack_size, (int) result);
+ return result;
+}
+
+
+/**
+ * i2400m_bm_cmd - Execute a boot mode command
+ *
+ * @cmd: buffer containing the command data (pointing at the header).
+ * This data can be ANYWHERE (for USB, we will copy it to an
+ * specific buffer). Make sure everything is in proper little
+ * endian.
+ *
+ * A raw buffer can be also sent, just cast it and set flags to
+ * I2400M_BM_CMD_RAW.
+ *
+ * This function will generate a checksum for you if the
+ * checksum bit in the command is set (unless I2400M_BM_CMD_RAW
+ * is set).
+ *
+ * You can use the i2400m->bm_cmd_buf to stage your commands and
+ * send them.
+ *
+ * If NULL, no command is sent (we just wait for an ack).
+ *
+ * @cmd_size: size of the command. Will be auto padded to the
+ * bus-specific drivers padding requirements.
+ *
+ * @ack: buffer where to place the acknowledgement. If it is a regular
+ * command response, all fields will be returned with the right,
+ * native endianess.
+ *
+ * You *cannot* use i2400m->bm_ack_buf for this buffer.
+ *
+ * @ack_size: size of @ack, 16 aligned; you need to provide at least
+ * sizeof(*ack) bytes and then enough to contain the return data
+ * from the command
+ *
+ * @flags: see I2400M_BM_CMD_* above.
+ *
+ * @returns: bytes received by the notification; if < 0, an errno code
+ * denoting an error or:
+ *
+ * -ERESTARTSYS The device has rebooted
+ *
+ * Executes a boot-mode command and waits for a response, doing basic
+ * validation on it; if a zero length response is received, it retries
+ * waiting for a response until a non-zero one is received (timing out
+ * after %I2400M_BOOT_RETRIES retries).
+ */
+static
+ssize_t i2400m_bm_cmd(struct i2400m *i2400m,
+ const struct i2400m_bootrom_header *cmd, size_t cmd_size,
+ struct i2400m_bootrom_header *ack, size_t ack_size,
+ int flags)
+{
+ ssize_t result = -ENOMEM, rx_bytes;
+ struct device *dev = i2400m_dev(i2400m);
+ int opcode = cmd == NULL ? -1 : i2400m_brh_get_opcode(cmd);
+
+ d_fnstart(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu)\n",
+ i2400m, cmd, cmd_size, ack, ack_size);
+ BUG_ON(ack_size < sizeof(*ack));
+ BUG_ON(i2400m->boot_mode == 0);
+
+ if (cmd != NULL) { /* send the command */
+ memcpy(i2400m->bm_cmd_buf, cmd, cmd_size);
+ result = i2400m->bus_bm_cmd_send(i2400m, cmd, cmd_size, flags);
+ if (result < 0)
+ goto error_cmd_send;
+ if ((flags & I2400M_BM_CMD_RAW) == 0)
+ d_printf(5, dev,
+ "boot-mode cmd %d csum %u rr %u da %u: "
+ "addr 0x%04x size %u block csum 0x%04x\n",
+ opcode, i2400m_brh_get_use_checksum(cmd),
+ i2400m_brh_get_response_required(cmd),
+ i2400m_brh_get_direct_access(cmd),
+ cmd->target_addr, cmd->data_size,
+ cmd->block_checksum);
+ }
+ result = i2400m->bus_bm_wait_for_ack(i2400m, ack, ack_size);
+ if (result < 0) {
+ dev_err(dev, "boot-mode cmd %d: error waiting for an ack: %d\n",
+ opcode, (int) result); /* bah, %zd doesn't work */
+ goto error_wait_for_ack;
+ }
+ rx_bytes = result;
+ /* verify the ack and read more if neccessary [result is the
+ * final amount of bytes we get in the ack] */
+ result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags);
+ if (result < 0)
+ goto error_bad_ack;
+ /* Don't you love this stack of empty targets? Well, I don't
+ * either, but it helps track exactly who comes in here and
+ * why :) */
+ result = rx_bytes;
+error_bad_ack:
+error_wait_for_ack:
+error_cmd_send:
+ d_fnend(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu) = %d\n",
+ i2400m, cmd, cmd_size, ack, ack_size, (int) result);
+ return result;
+}
+
+
+/**
+ * i2400m_download_chunk - write a single chunk of data to the device's memory
+ *
+ * @i2400m: device descriptor
+ * @buf: the buffer to write
+ * @buf_len: length of the buffer to write
+ * @addr: address in the device memory space
+ * @direct: bootrom write mode
+ * @do_csum: should a checksum validation be performed
+ */
+static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk,
+ size_t __chunk_len, unsigned long addr,
+ unsigned int direct, unsigned int do_csum)
+{
+ int ret;
+ size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_PAD);
+ struct device *dev = i2400m_dev(i2400m);
+ struct {
+ struct i2400m_bootrom_header cmd;
+ u8 cmd_payload[chunk_len];
+ } __attribute__((packed)) *buf;
+ struct i2400m_bootrom_header ack;
+
+ d_fnstart(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
+ "direct %u do_csum %u)\n", i2400m, chunk, __chunk_len,
+ addr, direct, do_csum);
+ buf = i2400m->bm_cmd_buf;
+ memcpy(buf->cmd_payload, chunk, __chunk_len);
+ memset(buf->cmd_payload + __chunk_len, 0xad, chunk_len - __chunk_len);
+
+ buf->cmd.command = i2400m_brh_command(I2400M_BRH_WRITE,
+ __chunk_len & 0x3 ? 0 : do_csum,
+ __chunk_len & 0xf ? 0 : direct);
+ buf->cmd.target_addr = cpu_to_le32(addr);
+ buf->cmd.data_size = cpu_to_le32(__chunk_len);
+ ret = i2400m_bm_cmd(i2400m, &buf->cmd, sizeof(buf->cmd) + chunk_len,
+ &ack, sizeof(ack), 0);
+ if (ret >= 0)
+ ret = 0;
+ d_fnend(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx "
+ "direct %u do_csum %u) = %d\n", i2400m, chunk, __chunk_len,
+ addr, direct, do_csum, ret);
+ return ret;
+}
+
+
+/*
+ * Download a BCF file's sections to the device
+ *
+ * @i2400m: device descriptor
+ * @bcf: pointer to firmware data (followed by the payloads). Assumed
+ * verified and consistent.
+ * @bcf_len: length (in bytes) of the @bcf buffer.
+ *
+ * Returns: < 0 errno code on error or the offset to the jump instruction.
+ *
+ * Given a BCF file, downloads each section (a command and a payload)
+ * to the device's address space. Actually, it just executes each
+ * command i the BCF file.
+ *
+ * The section size has to be aligned to 4 bytes AND the padding has
+ * to be taken from the firmware file, as the signature takes it into
+ * account.
+ */
+static
+ssize_t i2400m_dnload_bcf(struct i2400m *i2400m,
+ const struct i2400m_bcf_hdr *bcf, size_t bcf_len)
+{
+ ssize_t ret;
+ struct device *dev = i2400m_dev(i2400m);
+ size_t offset, /* iterator offset */
+ data_size, /* Size of the data payload */
+ section_size, /* Size of the whole section (cmd + payload) */
+ section = 1;
+ const struct i2400m_bootrom_header *bh;
+ struct i2400m_bootrom_header ack;
+
+ d_fnstart(3, dev, "(i2400m %p bcf %p bcf_len %zu)\n",
+ i2400m, bcf, bcf_len);
+ /* Iterate over the command blocks in the BCF file that start
+ * after the header */
+ offset = le32_to_cpu(bcf->header_len) * sizeof(u32);
+ while (1) { /* start sending the file */
+ bh = (void *) bcf + offset;
+ data_size = le32_to_cpu(bh->data_size);
+ section_size = ALIGN(sizeof(*bh) + data_size, 4);
+ d_printf(7, dev,
+ "downloading section #%zu (@%zu %zu B) to 0x%08x\n",
+ section, offset, sizeof(*bh) + data_size,
+ le32_to_cpu(bh->target_addr));
+ if (i2400m_brh_get_opcode(bh) == I2400M_BRH_SIGNED_JUMP) {
+ /* Secure boot needs to stop here */
+ d_printf(5, dev, "signed jump found @%zu\n", offset);
+ break;
+ }
+ if (offset + section_size == bcf_len)
+ /* Non-secure boot stops here */
+ break;
+ if (offset + section_size > bcf_len) {
+ dev_err(dev, "fw %s: bad section #%zu, "
+ "end (@%zu) beyond EOF (@%zu)\n",
+ i2400m->bus_fw_name, section,
+ offset + section_size, bcf_len);
+ ret = -EINVAL;
+ goto error_section_beyond_eof;
+ }
+ __i2400m_msleep(20);
+ ret = i2400m_bm_cmd(i2400m, bh, section_size,
+ &ack, sizeof(ack), I2400M_BM_CMD_RAW);
+ if (ret < 0) {
+ dev_err(dev, "fw %s: section #%zu (@%zu %zu B) "
+ "failed %d\n", i2400m->bus_fw_name, section,
+ offset, sizeof(*bh) + data_size, (int) ret);
+ goto error_send;
+ }
+ offset += section_size;
+ section++;
+ }
+ ret = offset;
+error_section_beyond_eof:
+error_send:
+ d_fnend(3, dev, "(i2400m %p bcf %p bcf_len %zu) = %d\n",
+ i2400m, bcf, bcf_len, (int) ret);
+ return ret;
+}
+
+
+/*
+ * Do the final steps of uploading firmware
+ *
+ * Depending on the boot mode (signed vs non-signed), different
+ * actions need to be taken.
+ */
+static
+int i2400m_dnload_finalize(struct i2400m *i2400m,
+ const struct i2400m_bcf_hdr *bcf, size_t offset)
+{
+ int ret = 0;
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400m_bootrom_header *cmd, ack;
+ struct {
+ struct i2400m_bootrom_header cmd;
+ u8 cmd_pl[0];
+ } __attribute__((packed)) *cmd_buf;
+ size_t signature_block_offset, signature_block_size;
+
+ d_fnstart(3, dev, "offset %zu\n", offset);
+ cmd = (void *) bcf + offset;
+ if (i2400m->sboot == 0) {
+ struct i2400m_bootrom_header jump_ack;
+ d_printf(3, dev, "unsecure boot, jumping to 0x%08x\n",
+ le32_to_cpu(cmd->target_addr));
+ i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP);
+ cmd->data_size = 0;
+ ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
+ &jump_ack, sizeof(jump_ack), 0);
+ } else {
+ d_printf(3, dev, "secure boot, jumping to 0x%08x\n",
+ le32_to_cpu(cmd->target_addr));
+ cmd_buf = i2400m->bm_cmd_buf;
+ memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd));
+ signature_block_offset =
+ sizeof(*bcf)
+ + le32_to_cpu(bcf->key_size) * sizeof(u32)
+ + le32_to_cpu(bcf->exponent_size) * sizeof(u32);
+ signature_block_size =
+ le32_to_cpu(bcf->modulus_size) * sizeof(u32);
+ memcpy(cmd_buf->cmd_pl, (void *) bcf + signature_block_offset,
+ signature_block_size);
+ ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd,
+ sizeof(cmd_buf->cmd) + signature_block_size,
+ &ack, sizeof(ack), I2400M_BM_CMD_RAW);
+ }
+ d_fnend(3, dev, "returning %d\n", ret);
+ return ret;
+}
+
+
+/**
+ * i2400m_bootrom_init - Reboots a powered device into boot mode
+ *
+ * @i2400m: device descriptor
+ * @flags:
+ * I2400M_BRI_SOFT: a reboot notification has been seen
+ * already, so don't wait for it.
+ *
+ * I2400M_BRI_NO_REBOOT: Don't send a reboot command, but wait
+ * for a reboot barker notification. This is a one shot; if
+ * the state machine needs to send a reboot command it will.
+ *
+ * Returns:
+ *
+ * < 0 errno code on error, 0 if ok.
+ *
+ * i2400m->sboot set to 0 for unsecure boot process, 1 for secure
+ * boot process.
+ *
+ * Description:
+ *
+ * Tries hard enough to put the device in boot-mode. There are two
+ * main phases to this:
+ *
+ * a. (1) send a reboot command and (2) get a reboot barker
+ * b. (1) ack the reboot sending a reboot barker and (2) getting an
+ * ack barker in return
+ *
+ * We want to skip (a) in some cases [soft]. The state machine is
+ * horrible, but it is basically: on each phase, send what has to be
+ * sent (if any), wait for the answer and act on the answer. We might
+ * have to backtrack and retry, so we keep a max tries counter for
+ * that.
+ *
+ * If we get a timeout after sending a warm reset, we do it again.
+ */
+int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400m_bootrom_header *cmd;
+ struct i2400m_bootrom_header ack;
+ int count = I2400M_BOOT_RETRIES;
+ int ack_timeout_cnt = 1;
+
+ BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_NBOOT_BARKER));
+ BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER));
+
+ d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags);
+ result = -ENOMEM;
+ cmd = i2400m->bm_cmd_buf;
+ if (flags & I2400M_BRI_SOFT)
+ goto do_reboot_ack;
+do_reboot:
+ if (--count < 0)
+ goto error_timeout;
+ d_printf(4, dev, "device reboot: reboot command [%d # left]\n",
+ count);
+ if ((flags & I2400M_BRI_NO_REBOOT) == 0)
+ i2400m->bus_reset(i2400m, I2400M_RT_WARM);
+ result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack),
+ I2400M_BM_CMD_RAW);
+ flags &= ~I2400M_BRI_NO_REBOOT;
+ switch (result) {
+ case -ERESTARTSYS:
+ d_printf(4, dev, "device reboot: got reboot barker\n");
+ break;
+ case -EISCONN: /* we don't know how it got here...but we follow it */
+ d_printf(4, dev, "device reboot: got ack barker - whatever\n");
+ goto do_reboot;
+ case -ETIMEDOUT: /* device has timed out, we might be in boot
+ * mode already and expecting an ack, let's try
+ * that */
+ dev_info(dev, "warm reset timed out, trying an ack\n");
+ goto do_reboot_ack;
+ case -EPROTO:
+ case -ESHUTDOWN: /* dev is gone */
+ case -EINTR: /* user cancelled */
+ goto error_dev_gone;
+ default:
+ dev_err(dev, "device reboot: error %d while waiting "
+ "for reboot barker - rebooting\n", result);
+ goto do_reboot;
+ }
+ /* At this point we ack back with 4 REBOOT barkers and expect
+ * 4 ACK barkers. This is ugly, as we send a raw command --
+ * hence the cast. _bm_cmd() will catch the reboot ack
+ * notification and report it as -EISCONN. */
+do_reboot_ack:
+ d_printf(4, dev, "device reboot ack: sending ack [%d # left]\n", count);
+ if (i2400m->sboot == 0)
+ memcpy(cmd, i2400m_NBOOT_BARKER,
+ sizeof(i2400m_NBOOT_BARKER));
+ else
+ memcpy(cmd, i2400m_SBOOT_BARKER,
+ sizeof(i2400m_SBOOT_BARKER));
+ result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
+ &ack, sizeof(ack), I2400M_BM_CMD_RAW);
+ switch (result) {
+ case -ERESTARTSYS:
+ d_printf(4, dev, "reboot ack: got reboot barker - retrying\n");
+ if (--count < 0)
+ goto error_timeout;
+ goto do_reboot_ack;
+ case -EISCONN:
+ d_printf(4, dev, "reboot ack: got ack barker - good\n");
+ break;
+ case -ETIMEDOUT: /* no response, maybe it is the other type? */
+ if (ack_timeout_cnt-- >= 0) {
+ d_printf(4, dev, "reboot ack timedout: "
+ "trying the other type?\n");
+ i2400m->sboot = !i2400m->sboot;
+ goto do_reboot_ack;
+ } else {
+ dev_err(dev, "reboot ack timedout too long: "
+ "trying reboot\n");
+ goto do_reboot;
+ }
+ break;
+ case -EPROTO:
+ case -ESHUTDOWN: /* dev is gone */
+ goto error_dev_gone;
+ default:
+ dev_err(dev, "device reboot ack: error %d while waiting for "
+ "reboot ack barker - rebooting\n", result);
+ goto do_reboot;
+ }
+ d_printf(2, dev, "device reboot ack: got ack barker - boot done\n");
+ result = 0;
+exit_timeout:
+error_dev_gone:
+ d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n",
+ i2400m, flags, result);
+ return result;
+
+error_timeout:
+ dev_err(dev, "Timed out waiting for reboot ack, resetting\n");
+ i2400m->bus_reset(i2400m, I2400M_RT_BUS);
+ result = -ETIMEDOUT;
+ goto exit_timeout;
+}
+
+
+/*
+ * Read the MAC addr
+ *
+ * The position this function reads is fixed in device memory and
+ * always available, even without firmware.
+ *
+ * Note we specify we want to read only six bytes, but provide space
+ * for 16, as we always get it rounded up.
+ */
+int i2400m_read_mac_addr(struct i2400m *i2400m)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct net_device *net_dev = i2400m->wimax_dev.net_dev;
+ struct i2400m_bootrom_header *cmd;
+ struct {
+ struct i2400m_bootrom_header ack;
+ u8 ack_pl[16];
+ } __attribute__((packed)) ack_buf;
+
+ d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
+ cmd = i2400m->bm_cmd_buf;
+ cmd->command = i2400m_brh_command(I2400M_BRH_READ, 0, 1);
+ cmd->target_addr = cpu_to_le32(0x00203fe8);
+ cmd->data_size = cpu_to_le32(6);
+ result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd),
+ &ack_buf.ack, sizeof(ack_buf), 0);
+ if (result < 0) {
+ dev_err(dev, "BM: read mac addr failed: %d\n", result);
+ goto error_read_mac;
+ }
+ d_printf(2, dev,
+ "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ack_buf.ack_pl[0], ack_buf.ack_pl[1],
+ ack_buf.ack_pl[2], ack_buf.ack_pl[3],
+ ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
+ if (i2400m->bus_bm_mac_addr_impaired == 1) {
+ ack_buf.ack_pl[0] = 0x00;
+ ack_buf.ack_pl[1] = 0x16;
+ ack_buf.ack_pl[2] = 0xd3;
+ get_random_bytes(&ack_buf.ack_pl[3], 3);
+ dev_err(dev, "BM is MAC addr impaired, faking MAC addr to "
+ "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n",
+ ack_buf.ack_pl[0], ack_buf.ack_pl[1],
+ ack_buf.ack_pl[2], ack_buf.ack_pl[3],
+ ack_buf.ack_pl[4], ack_buf.ack_pl[5]);
+ result = 0;
+ }
+ net_dev->addr_len = ETH_ALEN;
+ memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN);
+ memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN);
+error_read_mac:
+ d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result);
+ return result;
+}
+
+
+/*
+ * Initialize a non signed boot
+ *
+ * This implies sending some magic values to the device's memory. Note
+ * we convert the values to little endian in the same array
+ * declaration.
+ */
+static
+int i2400m_dnload_init_nonsigned(struct i2400m *i2400m)
+{
+#define POKE(a, d) { \
+ .address = __constant_cpu_to_le32(a), \
+ .data = __constant_cpu_to_le32(d) \
+}
+ static const struct {
+ __le32 address;
+ __le32 data;
+ } i2400m_pokes[] = {
+ POKE(0x081A58, 0xA7810230),
+ POKE(0x080040, 0x00000000),
+ POKE(0x080048, 0x00000082),
+ POKE(0x08004C, 0x0000081F),
+ POKE(0x080054, 0x00000085),
+ POKE(0x080058, 0x00000180),
+ POKE(0x08005C, 0x00000018),
+ POKE(0x080060, 0x00000010),
+ POKE(0x080574, 0x00000001),
+ POKE(0x080550, 0x00000005),
+ POKE(0xAE0000, 0x00000000),
+ };
+#undef POKE
+ unsigned i;
+ int ret;
+ struct device *dev = i2400m_dev(i2400m);
+
+ dev_warn(dev, "WARNING!!! non-signed boot UNTESTED PATH!\n");
+
+ d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
+ for (i = 0; i < ARRAY_SIZE(i2400m_pokes); i++) {
+ ret = i2400m_download_chunk(i2400m, &i2400m_pokes[i].data,
+ sizeof(i2400m_pokes[i].data),
+ i2400m_pokes[i].address, 1, 1);
+ if (ret < 0)
+ break;
+ }
+ d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
+ return ret;
+}
+
+
+/*
+ * Initialize the signed boot process
+ *
+ * @i2400m: device descriptor
+ *
+ * @bcf_hdr: pointer to the firmware header; assumes it is fully in
+ * memory (it has gone through basic validation).
+ *
+ * Returns: 0 if ok, < 0 errno code on error, -ERESTARTSYS if the hw
+ * rebooted.
+ *
+ * This writes the firmware BCF header to the device using the
+ * HASH_PAYLOAD_ONLY command.
+ */
+static
+int i2400m_dnload_init_signed(struct i2400m *i2400m,
+ const struct i2400m_bcf_hdr *bcf_hdr)
+{
+ int ret;
+ struct device *dev = i2400m_dev(i2400m);
+ struct {
+ struct i2400m_bootrom_header cmd;
+ struct i2400m_bcf_hdr cmd_pl;
+ } __attribute__((packed)) *cmd_buf;
+ struct i2400m_bootrom_header ack;
+
+ d_fnstart(5, dev, "(i2400m %p bcf_hdr %p)\n", i2400m, bcf_hdr);
+ cmd_buf = i2400m->bm_cmd_buf;
+ cmd_buf->cmd.command =
+ i2400m_brh_command(I2400M_BRH_HASH_PAYLOAD_ONLY, 0, 0);
+ cmd_buf->cmd.target_addr = 0;
+ cmd_buf->cmd.data_size = cpu_to_le32(sizeof(cmd_buf->cmd_pl));
+ memcpy(&cmd_buf->cmd_pl, bcf_hdr, sizeof(*bcf_hdr));
+ ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, sizeof(*cmd_buf),
+ &ack, sizeof(ack), 0);
+ if (ret >= 0)
+ ret = 0;
+ d_fnend(5, dev, "(i2400m %p bcf_hdr %p) = %d\n", i2400m, bcf_hdr, ret);
+ return ret;
+}
+
+
+/*
+ * Initialize the firmware download at the device size
+ *
+ * Multiplex to the one that matters based on the device's mode
+ * (signed or non-signed).
+ */
+static
+int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ u32 module_id = le32_to_cpu(bcf->module_id);
+
+ if (i2400m->sboot == 0
+ && (module_id & I2400M_BCF_MOD_ID_POKES) == 0) {
+ /* non-signed boot process without pokes */
+ result = i2400m_dnload_init_nonsigned(i2400m);
+ if (result == -ERESTARTSYS)
+ return result;
+ if (result < 0)
+ dev_err(dev, "fw %s: non-signed download "
+ "initialization failed: %d\n",
+ i2400m->bus_fw_name, result);
+ } else if (i2400m->sboot == 0
+ && (module_id & I2400M_BCF_MOD_ID_POKES)) {
+ /* non-signed boot process with pokes, nothing to do */
+ result = 0;
+ } else { /* signed boot process */
+ result = i2400m_dnload_init_signed(i2400m, bcf);
+ if (result == -ERESTARTSYS)
+ return result;
+ if (result < 0)
+ dev_err(dev, "fw %s: signed boot download "
+ "initialization failed: %d\n",
+ i2400m->bus_fw_name, result);
+ }
+ return result;
+}
+
+
+/*
+ * Run quick consistency tests on the firmware file
+ *
+ * Check for the firmware being made for the i2400m device,
+ * etc...These checks are mostly informative, as the device will make
+ * them too; but the driver's response is more informative on what
+ * went wrong.
+ */
+static
+int i2400m_fw_check(struct i2400m *i2400m,
+ const struct i2400m_bcf_hdr *bcf,
+ size_t bcf_size)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ unsigned module_type, header_len, major_version, minor_version,
+ module_id, module_vendor, date, size;
+
+ /* Check hard errors */
+ result = -EINVAL;
+ if (bcf_size < sizeof(*bcf)) { /* big enough header? */
+ dev_err(dev, "firmware %s too short: "
+ "%zu B vs %zu (at least) expected\n",
+ i2400m->bus_fw_name, bcf_size, sizeof(*bcf));
+ goto error;
+ }
+
+ module_type = bcf->module_type;
+ header_len = sizeof(u32) * le32_to_cpu(bcf->header_len);
+ major_version = le32_to_cpu(bcf->header_version) & 0xffff0000 >> 16;
+ minor_version = le32_to_cpu(bcf->header_version) & 0x0000ffff;
+ module_id = le32_to_cpu(bcf->module_id);
+ module_vendor = le32_to_cpu(bcf->module_vendor);
+ date = le32_to_cpu(bcf->date);
+ size = sizeof(u32) * le32_to_cpu(bcf->size);
+
+ if (bcf_size != size) { /* annoyingly paranoid */
+ dev_err(dev, "firmware %s: bad size, got "
+ "%zu B vs %u expected\n",
+ i2400m->bus_fw_name, bcf_size, size);
+ goto error;
+ }
+
+ d_printf(2, dev, "type 0x%x id 0x%x vendor 0x%x; header v%u.%u (%zu B) "
+ "date %08x (%zu B)\n",
+ module_type, module_id, module_vendor,
+ major_version, minor_version, (size_t) header_len,
+ date, (size_t) size);
+
+ if (module_type != 6) { /* built for the right hardware? */
+ dev_err(dev, "bad fw %s: unexpected module type 0x%x; "
+ "aborting\n", i2400m->bus_fw_name, module_type);
+ goto error;
+ }
+
+ /* Check soft-er errors */
+ result = 0;
+ if (module_vendor != 0x8086)
+ dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n",
+ i2400m->bus_fw_name, module_vendor);
+ if (date < 0x20080300)
+ dev_err(dev, "bad fw %s? build date too old %08x\n",
+ i2400m->bus_fw_name, date);
+error:
+ return result;
+}
+
+
+/*
+ * Download the firmware to the device
+ *
+ * @i2400m: device descriptor
+ * @bcf: pointer to loaded (and minimally verified for consistency)
+ * firmware
+ * @bcf_size: size of the @bcf buffer (header plus payloads)
+ *
+ * The process for doing this is described in this file's header.
+ *
+ * Note we only reinitialize boot-mode if the flags say so. Some hw
+ * iterations need it, some don't. In any case, if we loop, we always
+ * need to reinitialize the boot room, hence the flags modification.
+ */
+static
+int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,
+ size_t bcf_size, enum i2400m_bri flags)
+{
+ int ret = 0;
+ struct device *dev = i2400m_dev(i2400m);
+ int count = I2400M_BOOT_RETRIES;
+
+ d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n",
+ i2400m, bcf, bcf_size);
+ i2400m->boot_mode = 1;
+hw_reboot:
+ if (count-- == 0) {
+ ret = -ERESTARTSYS;
+ dev_err(dev, "device rebooted too many times, aborting\n");
+ goto error_too_many_reboots;
+ }
+ if (flags & I2400M_BRI_MAC_REINIT) {
+ ret = i2400m_bootrom_init(i2400m, flags);
+ if (ret < 0) {
+ dev_err(dev, "bootrom init failed: %d\n", ret);
+ goto error_bootrom_init;
+ }
+ }
+ flags |= I2400M_BRI_MAC_REINIT;
+
+ /*
+ * Initialize the download, push the bytes to the device and
+ * then jump to the new firmware. Note @ret is passed with the
+ * offset of the jump instruction to _dnload_finalize()
+ */
+ ret = i2400m_dnload_init(i2400m, bcf); /* Init device's dnload */
+ if (ret == -ERESTARTSYS)
+ goto error_dev_rebooted;
+ if (ret < 0)
+ goto error_dnload_init;
+
+ ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size);
+ if (ret == -ERESTARTSYS)
+ goto error_dev_rebooted;
+ if (ret < 0) {
+ dev_err(dev, "fw %s: download failed: %d\n",
+ i2400m->bus_fw_name, ret);
+ goto error_dnload_bcf;
+ }
+
+ ret = i2400m_dnload_finalize(i2400m, bcf, ret);
+ if (ret == -ERESTARTSYS)
+ goto error_dev_rebooted;
+ if (ret < 0) {
+ dev_err(dev, "fw %s: "
+ "download finalization failed: %d\n",
+ i2400m->bus_fw_name, ret);
+ goto error_dnload_finalize;
+ }
+
+ d_printf(2, dev, "fw %s successfully uploaded\n",
+ i2400m->bus_fw_name);
+ i2400m->boot_mode = 0;
+error_dnload_finalize:
+error_dnload_bcf:
+error_dnload_init:
+error_bootrom_init:
+error_too_many_reboots:
+ d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n",
+ i2400m, bcf, bcf_size, ret);
+ return ret;
+
+error_dev_rebooted:
+ dev_err(dev, "device rebooted, %d tries left\n", count);
+ /* we got the notification already, no need to wait for it again */
+ flags |= I2400M_BRI_SOFT;
+ goto hw_reboot;
+}
+
+
+/**
+ * i2400m_dev_bootstrap - Bring the device to a known state and upload firmware
+ *
+ * @i2400m: device descriptor
+ *
+ * Returns: >= 0 if ok, < 0 errno code on error.
+ *
+ * This sets up the firmware upload environment, loads the firmware
+ * file from disk, verifies and then calls the firmware upload process
+ * per se.
+ *
+ * Can be called either from probe, or after a warm reset. Can not be
+ * called from within an interrupt. All the flow in this code is
+ * single-threade; all I/Os are synchronous.
+ */
+int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags)
+{
+ int ret = 0;
+ struct device *dev = i2400m_dev(i2400m);
+ const struct firmware *fw;
+ const struct i2400m_bcf_hdr *bcf; /* Firmware data */
+
+ d_fnstart(5, dev, "(i2400m %p)\n", i2400m);
+ /* Load firmware files to memory. */
+ ret = request_firmware(&fw, i2400m->bus_fw_name, dev);
+ if (ret) {
+ dev_err(dev, "fw %s: request failed: %d\n",
+ i2400m->bus_fw_name, ret);
+ goto error_fw_req;
+ }
+ bcf = (void *) fw->data;
+
+ ret = i2400m_fw_check(i2400m, bcf, fw->size);
+ if (ret < 0)
+ goto error_fw_bad;
+ ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags);
+error_fw_bad:
+ release_firmware(fw);
+error_fw_req:
+ d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap);
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
new file mode 100644
index 000000000000..08c2fb739234
--- /dev/null
+++ b/drivers/net/wimax/i2400m/i2400m-sdio.h
@@ -0,0 +1,132 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * SDIO-specific i2400m driver definitions
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Brian Bian <brian.bian@intel.com>
+ * Dirk Brandewie <dirk.j.brandewie@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * - Initial implementation
+ *
+ *
+ * This driver implements the bus-specific part of the i2400m for
+ * SDIO. Check i2400m.h for a generic driver description.
+ *
+ * ARCHITECTURE
+ *
+ * This driver sits under the bus-generic i2400m driver, providing the
+ * connection to the device.
+ *
+ * When probed, all the function pointers are setup and then the
+ * bus-generic code called. The generic driver will then use the
+ * provided pointers for uploading firmware (i2400ms_bus_bm*() in
+ * sdio-fw.c) and then setting up the device (i2400ms_dev_*() in
+ * sdio.c).
+ *
+ * Once firmware is uploaded, TX functions (sdio-tx.c) are called when
+ * data is ready for transmission in the TX fifo; then the SDIO IRQ is
+ * fired and data is available (sdio-rx.c), it is sent to the generic
+ * driver for processing with i2400m_rx.
+ */
+
+#ifndef __I2400M_SDIO_H__
+#define __I2400M_SDIO_H__
+
+#include "i2400m.h"
+
+/* Host-Device interface for SDIO */
+enum {
+ I2400MS_BLK_SIZE = 256,
+ I2400MS_PL_SIZE_MAX = 0x3E00,
+
+ I2400MS_DATA_ADDR = 0x0,
+ I2400MS_INTR_STATUS_ADDR = 0x13,
+ I2400MS_INTR_CLEAR_ADDR = 0x13,
+ I2400MS_INTR_ENABLE_ADDR = 0x14,
+ I2400MS_INTR_GET_SIZE_ADDR = 0x2C,
+ /* The number of ticks to wait for the device to signal that
+ * it is ready */
+ I2400MS_INIT_SLEEP_INTERVAL = 10,
+};
+
+
+/**
+ * struct i2400ms - descriptor for a SDIO connected i2400m
+ *
+ * @i2400m: bus-generic i2400m implementation; has to be first (see
+ * it's documentation in i2400m.h).
+ *
+ * @func: pointer to our SDIO function
+ *
+ * @tx_worker: workqueue struct used to TX data when the bus-generic
+ * code signals packets are pending for transmission to the device.
+ *
+ * @tx_workqueue: workqeueue used for data TX; we don't use the
+ * system's workqueue as that might cause deadlocks with code in
+ * the bus-generic driver.
+ */
+struct i2400ms {
+ struct i2400m i2400m; /* FIRST! See doc */
+ struct sdio_func *func;
+
+ struct work_struct tx_worker;
+ struct workqueue_struct *tx_workqueue;
+ char tx_wq_name[32];
+
+ struct dentry *debugfs_dentry;
+};
+
+
+static inline
+void i2400ms_init(struct i2400ms *i2400ms)
+{
+ i2400m_init(&i2400ms->i2400m);
+}
+
+
+extern int i2400ms_rx_setup(struct i2400ms *);
+extern void i2400ms_rx_release(struct i2400ms *);
+extern ssize_t __i2400ms_rx_get_size(struct i2400ms *);
+
+extern int i2400ms_tx_setup(struct i2400ms *);
+extern void i2400ms_tx_release(struct i2400ms *);
+extern void i2400ms_bus_tx_kick(struct i2400m *);
+
+extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *,
+ const struct i2400m_bootrom_header *,
+ size_t, int);
+extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *,
+ struct i2400m_bootrom_header *,
+ size_t);
+#endif /* #ifndef __I2400M_SDIO_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h
new file mode 100644
index 000000000000..6f76558b170f
--- /dev/null
+++ b/drivers/net/wimax/i2400m/i2400m-usb.h
@@ -0,0 +1,264 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * USB-specific i2400m driver definitions
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * - Initial implementation
+ *
+ *
+ * This driver implements the bus-specific part of the i2400m for
+ * USB. Check i2400m.h for a generic driver description.
+ *
+ * ARCHITECTURE
+ *
+ * This driver listens to notifications sent from the notification
+ * endpoint (in usb-notif.c); when data is ready to read, the code in
+ * there schedules a read from the device (usb-rx.c) and then passes
+ * the data to the generic RX code (rx.c).
+ *
+ * When the generic driver needs to send data (network or control), it
+ * queues up in the TX FIFO (tx.c) and that will notify the driver
+ * through the i2400m->bus_tx_kick() callback
+ * (usb-tx.c:i2400mu_bus_tx_kick) which will send the items in the
+ * FIFO queue.
+ *
+ * This driver, as well, implements the USB-specific ops for the generic
+ * driver to be able to setup/teardown communication with the device
+ * [i2400m_bus_dev_start() and i2400m_bus_dev_stop()], reseting the
+ * device [i2400m_bus_reset()] and performing firmware upload
+ * [i2400m_bus_bm_cmd() and i2400_bus_bm_wait_for_ack()].
+ */
+
+#ifndef __I2400M_USB_H__
+#define __I2400M_USB_H__
+
+#include "i2400m.h"
+#include <linux/kthread.h>
+
+
+/*
+ * Error Density Count: cheapo error density (over time) counter
+ *
+ * Originally by Reinette Chatre <reinette.chatre@intel.com>
+ *
+ * Embed an 'struct edc' somewhere. Each time there is a soft or
+ * retryable error, call edc_inc() and check if the error top
+ * watermark has been reached.
+ */
+enum {
+ EDC_MAX_ERRORS = 10,
+ EDC_ERROR_TIMEFRAME = HZ,
+};
+
+/* error density counter */
+struct edc {
+ unsigned long timestart;
+ u16 errorcount;
+};
+
+static inline void edc_init(struct edc *edc)
+{
+ edc->timestart = jiffies;
+}
+
+/**
+ * edc_inc - report a soft error and check if we are over the watermark
+ *
+ * @edc: pointer to error density counter.
+ * @max_err: maximum number of errors we can accept over the timeframe
+ * @timeframe: lenght of the timeframe (in jiffies).
+ *
+ * Returns: !0 1 if maximum acceptable errors per timeframe has been
+ * exceeded. 0 otherwise.
+ *
+ * This is way to determine if the number of acceptable errors per time
+ * period has been exceeded. It is not accurate as there are cases in which
+ * this scheme will not work, for example if there are periodic occurences
+ * of errors that straddle updates to the start time. This scheme is
+ * sufficient for our usage.
+ *
+ * To use, embed a 'struct edc' somewhere, initialize it with
+ * edc_init() and when an error hits:
+ *
+ * if (do_something_fails_with_a_soft_error) {
+ * if (edc_inc(&my->edc, MAX_ERRORS, MAX_TIMEFRAME))
+ * Ops, hard error, do something about it
+ * else
+ * Retry or ignore, depending on whatever
+ * }
+ */
+static inline int edc_inc(struct edc *edc, u16 max_err, u16 timeframe)
+{
+ unsigned long now;
+
+ now = jiffies;
+ if (now - edc->timestart > timeframe) {
+ edc->errorcount = 1;
+ edc->timestart = now;
+ } else if (++edc->errorcount > max_err) {
+ edc->errorcount = 0;
+ edc->timestart = now;
+ return 1;
+ }
+ return 0;
+}
+
+/* Host-Device interface for USB */
+enum {
+ I2400MU_MAX_NOTIFICATION_LEN = 256,
+ I2400MU_BLK_SIZE = 16,
+ I2400MU_PL_SIZE_MAX = 0x3EFF,
+
+ /* Endpoints */
+ I2400MU_EP_BULK_OUT = 0,
+ I2400MU_EP_NOTIFICATION,
+ I2400MU_EP_RESET_COLD,
+ I2400MU_EP_BULK_IN,
+};
+
+
+/**
+ * struct i2400mu - descriptor for a USB connected i2400m
+ *
+ * @i2400m: bus-generic i2400m implementation; has to be first (see
+ * it's documentation in i2400m.h).
+ *
+ * @usb_dev: pointer to our USB device
+ *
+ * @usb_iface: pointer to our USB interface
+ *
+ * @urb_edc: error density counter; used to keep a density-on-time tab
+ * on how many soft (retryable or ignorable) errors we get. If we
+ * go over the threshold, we consider the bus transport is failing
+ * too much and reset.
+ *
+ * @notif_urb: URB for receiving notifications from the device.
+ *
+ * @tx_kthread: thread we use for data TX. We use a thread because in
+ * order to do deep power saving and put the device to sleep, we
+ * need to call usb_autopm_*() [blocking functions].
+ *
+ * @tx_wq: waitqueue for the TX kthread to sleep when there is no data
+ * to be sent; when more data is available, it is woken up by
+ * i2400mu_bus_tx_kick().
+ *
+ * @rx_kthread: thread we use for data RX. We use a thread because in
+ * order to do deep power saving and put the device to sleep, we
+ * need to call usb_autopm_*() [blocking functions].
+ *
+ * @rx_wq: waitqueue for the RX kthread to sleep when there is no data
+ * to receive. When data is available, it is woken up by
+ * usb-notif.c:i2400mu_notification_grok().
+ *
+ * @rx_pending_count: number of rx-data-ready notifications that were
+ * still not handled by the RX kthread.
+ *
+ * @rx_size: current RX buffer size that is being used.
+ *
+ * @rx_size_acc: accumulator of the sizes of the previous read
+ * transactions.
+ *
+ * @rx_size_cnt: number of read transactions accumulated in
+ * @rx_size_acc.
+ *
+ * @do_autopm: disable(0)/enable(>0) calling the
+ * usb_autopm_get/put_interface() barriers when executing
+ * commands. See doc in i2400mu_suspend() for more information.
+ *
+ * @rx_size_auto_shrink: if true, the rx_size is shrinked
+ * automatically based on the average size of the received
+ * transactions. This allows the receive code to allocate smaller
+ * chunks of memory and thus reduce pressure on the memory
+ * allocator by not wasting so much space. By default it is
+ * enabled.
+ *
+ * @debugfs_dentry: hookup for debugfs files.
+ * These have to be in a separate directory, a child of
+ * (wimax_dev->debugfs_dentry) so they can be removed when the
+ * module unloads, as we don't keep each dentry.
+ */
+struct i2400mu {
+ struct i2400m i2400m; /* FIRST! See doc */
+
+ struct usb_device *usb_dev;
+ struct usb_interface *usb_iface;
+ struct edc urb_edc; /* Error density counter */
+
+ struct urb *notif_urb;
+ struct task_struct *tx_kthread;
+ wait_queue_head_t tx_wq;
+
+ struct task_struct *rx_kthread;
+ wait_queue_head_t rx_wq;
+ atomic_t rx_pending_count;
+ size_t rx_size, rx_size_acc, rx_size_cnt;
+ atomic_t do_autopm;
+ u8 rx_size_auto_shrink;
+
+ struct dentry *debugfs_dentry;
+};
+
+
+static inline
+void i2400mu_init(struct i2400mu *i2400mu)
+{
+ i2400m_init(&i2400mu->i2400m);
+ edc_init(&i2400mu->urb_edc);
+ init_waitqueue_head(&i2400mu->tx_wq);
+ atomic_set(&i2400mu->rx_pending_count, 0);
+ init_waitqueue_head(&i2400mu->rx_wq);
+ i2400mu->rx_size = PAGE_SIZE - sizeof(struct skb_shared_info);
+ atomic_set(&i2400mu->do_autopm, 1);
+ i2400mu->rx_size_auto_shrink = 1;
+}
+
+extern int i2400mu_notification_setup(struct i2400mu *);
+extern void i2400mu_notification_release(struct i2400mu *);
+
+extern int i2400mu_rx_setup(struct i2400mu *);
+extern void i2400mu_rx_release(struct i2400mu *);
+extern void i2400mu_rx_kick(struct i2400mu *);
+
+extern int i2400mu_tx_setup(struct i2400mu *);
+extern void i2400mu_tx_release(struct i2400mu *);
+extern void i2400mu_bus_tx_kick(struct i2400m *);
+
+extern ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *,
+ const struct i2400m_bootrom_header *,
+ size_t, int);
+extern ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *,
+ struct i2400m_bootrom_header *,
+ size_t);
+#endif /* #ifndef __I2400M_USB_H__ */
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
new file mode 100644
index 000000000000..067c871cc226
--- /dev/null
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -0,0 +1,755 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Declarations for bus-generic internal APIs
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * - Initial implementation
+ *
+ *
+ * GENERAL DRIVER ARCHITECTURE
+ *
+ * The i2400m driver is split in the following two major parts:
+ *
+ * - bus specific driver
+ * - bus generic driver (this part)
+ *
+ * The bus specific driver sets up stuff specific to the bus the
+ * device is connected to (USB, SDIO, PCI, tam-tam...non-authoritative
+ * nor binding list) which is basically the device-model management
+ * (probe/disconnect, etc), moving data from device to kernel and
+ * back, doing the power saving details and reseting the device.
+ *
+ * For details on each bus-specific driver, see it's include file,
+ * i2400m-BUSNAME.h
+ *
+ * The bus-generic functionality break up is:
+ *
+ * - Firmware upload: fw.c - takes care of uploading firmware to the
+ * device. bus-specific driver just needs to provides a way to
+ * execute boot-mode commands and to reset the device.
+ *
+ * - RX handling: rx.c - receives data from the bus-specific code and
+ * feeds it to the network or WiMAX stack or uses it to modify
+ * the driver state. bus-specific driver only has to receive
+ * frames and pass them to this module.
+ *
+ * - TX handling: tx.c - manages the TX FIFO queue and provides means
+ * for the bus-specific TX code to pull data from the FIFO
+ * queue. bus-specific code just pulls frames from this module
+ * to sends them to the device.
+ *
+ * - netdev glue: netdev.c - interface with Linux networking
+ * stack. Pass around data frames, and configure when the
+ * device is up and running or shutdown (through ifconfig up /
+ * down). Bus-generic only.
+ *
+ * - control ops: control.c - implements various commmands for
+ * controlling the device. bus-generic only.
+ *
+ * - device model glue: driver.c - implements helpers for the
+ * device-model glue done by the bus-specific layer
+ * (setup/release the driver resources), turning the device on
+ * and off, handling the device reboots/resets and a few simple
+ * WiMAX stack ops.
+ *
+ * Code is also broken up in linux-glue / device-glue.
+ *
+ * Linux glue contains functions that deal mostly with gluing with the
+ * rest of the Linux kernel.
+ *
+ * Device-glue are functions that deal mostly with the way the device
+ * does things and talk the device's language.
+ *
+ * device-glue code is licensed BSD so other open source OSes can take
+ * it to implement their drivers.
+ *
+ *
+ * APIs AND HEADER FILES
+ *
+ * This bus generic code exports three APIs:
+ *
+ * - HDI (host-device interface) definitions common to all busses
+ * (include/linux/wimax/i2400m.h); these can be also used by user
+ * space code.
+ * - internal API for the bus-generic code
+ * - external API for the bus-specific drivers
+ *
+ *
+ * LIFE CYCLE:
+ *
+ * When the bus-specific driver probes, it allocates a network device
+ * with enough space for it's data structue, that must contain a
+ * &struct i2400m at the top.
+ *
+ * On probe, it needs to fill the i2400m members marked as [fill], as
+ * well as i2400m->wimax_dev.net_dev and call i2400m_setup(). The
+ * i2400m driver will only register with the WiMAX and network stacks;
+ * the only access done to the device is to read the MAC address so we
+ * can register a network device. This calls i2400m_dev_start() to
+ * load firmware, setup communication with the device and configure it
+ * for operation.
+ *
+ * At this point, control and data communications are possible.
+ *
+ * On disconnect/driver unload, the bus-specific disconnect function
+ * calls i2400m_release() to undo i2400m_setup(). i2400m_dev_stop()
+ * shuts the firmware down and releases resources uses to communicate
+ * with the device.
+ *
+ * While the device is up, it might reset. The bus-specific driver has
+ * to catch that situation and call i2400m_dev_reset_handle() to deal
+ * with it (reset the internal driver structures and go back to square
+ * one).
+ */
+
+#ifndef __I2400M_H__
+#define __I2400M_H__
+
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/completion.h>
+#include <linux/rwsem.h>
+#include <asm/atomic.h>
+#include <net/wimax.h>
+#include <linux/wimax/i2400m.h>
+#include <asm/byteorder.h>
+
+/* Misc constants */
+enum {
+ /* Firmware uploading */
+ I2400M_BOOT_RETRIES = 3,
+ /* Size of the Boot Mode Command buffer */
+ I2400M_BM_CMD_BUF_SIZE = 16 * 1024,
+ I2400M_BM_ACK_BUF_SIZE = 256,
+};
+
+
+/* Firmware version we request when pulling the fw image file */
+#define I2400M_FW_VERSION "1.3"
+
+
+/**
+ * i2400m_reset_type - methods to reset a device
+ *
+ * @I2400M_RT_WARM: Reset without device disconnection, device handles
+ * are kept valid but state is back to power on, with firmware
+ * re-uploaded.
+ * @I2400M_RT_COLD: Tell the device to disconnect itself from the bus
+ * and reconnect. Renders all device handles invalid.
+ * @I2400M_RT_BUS: Tells the bus to reset the device; last measure
+ * used when both types above don't work.
+ */
+enum i2400m_reset_type {
+ I2400M_RT_WARM, /* first measure */
+ I2400M_RT_COLD, /* second measure */
+ I2400M_RT_BUS, /* call in artillery */
+};
+
+struct i2400m_reset_ctx;
+
+/**
+ * struct i2400m - descriptor for an Intel 2400m
+ *
+ * Members marked with [fill] must be filled out/initialized before
+ * calling i2400m_setup().
+ *
+ * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16,
+ * so we have a tx_blk_size variable that the bus layer sets to
+ * tell the engine how much of that we need.
+ *
+ * @bus_pl_size_max: [fill] Maximum payload size.
+ *
+ * @bus_dev_start: [fill] Function called by the bus-generic code
+ * [i2400m_dev_start()] to setup the bus-specific communications
+ * to the the device. See LIFE CYCLE above.
+ *
+ * NOTE: Doesn't need to upload the firmware, as that is taken
+ * care of by the bus-generic code.
+ *
+ * @bus_dev_stop: [fill] Function called by the bus-generic code
+ * [i2400m_dev_stop()] to shutdown the bus-specific communications
+ * to the the device. See LIFE CYCLE above.
+ *
+ * This function does not need to reset the device, just tear down
+ * all the host resources created to handle communication with
+ * the device.
+ *
+ * @bus_tx_kick: [fill] Function called by the bus-generic code to let
+ * the bus-specific code know that there is data available in the
+ * TX FIFO for transmission to the device.
+ *
+ * This function cannot sleep.
+ *
+ * @bus_reset: [fill] Function called by the bus-generic code to reset
+ * the device in in various ways. Doesn't need to wait for the
+ * reset to finish.
+ *
+ * If warm or cold reset fail, this function is expected to do a
+ * bus-specific reset (eg: USB reset) to get the device to a
+ * working state (even if it implies device disconecction).
+ *
+ * Note the warm reset is used by the firmware uploader to
+ * reinitialize the device.
+ *
+ * IMPORTANT: this is called very early in the device setup
+ * process, so it cannot rely on common infrastructure being laid
+ * out.
+ *
+ * @bus_bm_cmd_send: [fill] Function called to send a boot-mode
+ * command. Flags are defined in 'enum i2400m_bm_cmd_flags'. This
+ * is synchronous and has to return 0 if ok or < 0 errno code in
+ * any error condition.
+ *
+ * @bus_bm_wait_for_ack: [fill] Function called to wait for a
+ * boot-mode notification (that can be a response to a previously
+ * issued command or an asynchronous one). Will read until all the
+ * indicated size is read or timeout. Reading more or less data
+ * than asked for is an error condition. Return 0 if ok, < 0 errno
+ * code on error.
+ *
+ * The caller to this function will check if the response is a
+ * barker that indicates the device going into reset mode.
+ *
+ * @bus_fw_name: [fill] name of the firmware image (in most cases,
+ * they are all the same for a single release, except that they
+ * have the type of the bus embedded in the name (eg:
+ * i2400m-fw-X-VERSION.sbcf, where X is the bus name).
+ *
+ * @bus_bm_mac_addr_impaired: [fill] Set to true if the device's MAC
+ * address provided in boot mode is kind of broken and needs to
+ * be re-read later on.
+ *
+ *
+ * @wimax_dev: WiMAX generic device for linkage into the kernel WiMAX
+ * stack. Due to the way a net_device is allocated, we need to
+ * force this to be the first field so that we can get from
+ * netdev_priv() the right pointer.
+ *
+ * @state: device's state (as reported by it)
+ *
+ * @state_wq: waitqueue that is woken up whenever the state changes
+ *
+ * @tx_lock: spinlock to protect TX members
+ *
+ * @tx_buf: FIFO buffer for TX; we queue data here
+ *
+ * @tx_in: FIFO index for incoming data. Note this doesn't wrap around
+ * and it is always greater than @tx_out.
+ *
+ * @tx_out: FIFO index for outgoing data
+ *
+ * @tx_msg: current TX message that is active in the FIFO for
+ * appending payloads.
+ *
+ * @tx_sequence: current sequence number for TX messages from the
+ * device to the host.
+ *
+ * @tx_msg_size: size of the current message being transmitted by the
+ * bus-specific code.
+ *
+ * @tx_pl_num: total number of payloads sent
+ *
+ * @tx_pl_max: maximum number of payloads sent in a TX message
+ *
+ * @tx_pl_min: minimum number of payloads sent in a TX message
+ *
+ * @tx_num: number of TX messages sent
+ *
+ * @tx_size_acc: number of bytes in all TX messages sent
+ * (this is different to net_dev's statistics as it also counts
+ * control messages).
+ *
+ * @tx_size_min: smallest TX message sent.
+ *
+ * @tx_size_max: biggest TX message sent.
+ *
+ * @rx_lock: spinlock to protect RX members
+ *
+ * @rx_pl_num: total number of payloads received
+ *
+ * @rx_pl_max: maximum number of payloads received in a RX message
+ *
+ * @rx_pl_min: minimum number of payloads received in a RX message
+ *
+ * @rx_num: number of RX messages received
+ *
+ * @rx_size_acc: number of bytes in all RX messages received
+ * (this is different to net_dev's statistics as it also counts
+ * control messages).
+ *
+ * @rx_size_min: smallest RX message received.
+ *
+ * @rx_size_max: buggest RX message received.
+ *
+ * @init_mutex: Mutex used for serializing the device bringup
+ * sequence; this way if the device reboots in the middle, we
+ * don't try to do a bringup again while we are tearing down the
+ * one that failed.
+ *
+ * Can't reuse @msg_mutex because from within the bringup sequence
+ * we need to send messages to the device and thus use @msg_mutex.
+ *
+ * @msg_mutex: mutex used to send control commands to the device (we
+ * only allow one at a time, per host-device interface design).
+ *
+ * @msg_completion: used to wait for an ack to a control command sent
+ * to the device.
+ *
+ * @ack_skb: used to store the actual ack to a control command if the
+ * reception of the command was successful. Otherwise, a ERR_PTR()
+ * errno code that indicates what failed with the ack reception.
+ *
+ * Only valid after @msg_completion is woken up. Only updateable
+ * if @msg_completion is armed. Only touched by
+ * i2400m_msg_to_dev().
+ *
+ * Protected by @rx_lock. In theory the command execution flow is
+ * sequential, but in case the device sends an out-of-phase or
+ * very delayed response, we need to avoid it trampling current
+ * execution.
+ *
+ * @bm_cmd_buf: boot mode command buffer for composing firmware upload
+ * commands.
+ *
+ * USB can't r/w to stack, vmalloc, etc...as well, we end up
+ * having to alloc/free a lot to compose commands, so we use these
+ * for stagging and not having to realloc all the time.
+ *
+ * This assumes the code always runs serialized. Only one thread
+ * can call i2400m_bm_cmd() at the same time.
+ *
+ * @bm_ack_buf: boot mode acknoledge buffer for staging reception of
+ * responses to commands.
+ *
+ * See @bm_cmd_buf.
+ *
+ * @work_queue: work queue for processing device reports. This
+ * workqueue cannot be used for processing TX or RX to the device,
+ * as from it we'll process device reports, which might require
+ * further communication with the device.
+ *
+ * @debugfs_dentry: hookup for debugfs files.
+ * These have to be in a separate directory, a child of
+ * (wimax_dev->debugfs_dentry) so they can be removed when the
+ * module unloads, as we don't keep each dentry.
+ */
+struct i2400m {
+ struct wimax_dev wimax_dev; /* FIRST! See doc */
+
+ unsigned updown:1; /* Network device is up or down */
+ unsigned boot_mode:1; /* is the device in boot mode? */
+ unsigned sboot:1; /* signed or unsigned fw boot */
+ unsigned ready:1; /* all probing steps done */
+ u8 trace_msg_from_user; /* echo rx msgs to 'trace' pipe */
+ /* typed u8 so debugfs/u8 can tweak */
+ enum i2400m_system_state state;
+ wait_queue_head_t state_wq; /* Woken up when on state updates */
+
+ size_t bus_tx_block_size;
+ size_t bus_pl_size_max;
+ int (*bus_dev_start)(struct i2400m *);
+ void (*bus_dev_stop)(struct i2400m *);
+ void (*bus_tx_kick)(struct i2400m *);
+ int (*bus_reset)(struct i2400m *, enum i2400m_reset_type);
+ ssize_t (*bus_bm_cmd_send)(struct i2400m *,
+ const struct i2400m_bootrom_header *,
+ size_t, int flags);
+ ssize_t (*bus_bm_wait_for_ack)(struct i2400m *,
+ struct i2400m_bootrom_header *, size_t);
+ const char *bus_fw_name;
+ unsigned bus_bm_mac_addr_impaired:1;
+
+ spinlock_t tx_lock; /* protect TX state */
+ void *tx_buf;
+ size_t tx_in, tx_out;
+ struct i2400m_msg_hdr *tx_msg;
+ size_t tx_sequence, tx_msg_size;
+ /* TX stats */
+ unsigned tx_pl_num, tx_pl_max, tx_pl_min,
+ tx_num, tx_size_acc, tx_size_min, tx_size_max;
+
+ /* RX stats */
+ spinlock_t rx_lock; /* protect RX state */
+ unsigned rx_pl_num, rx_pl_max, rx_pl_min,
+ rx_num, rx_size_acc, rx_size_min, rx_size_max;
+
+ struct mutex msg_mutex; /* serialize command execution */
+ struct completion msg_completion;
+ struct sk_buff *ack_skb; /* protected by rx_lock */
+
+ void *bm_ack_buf; /* for receiving acks over USB */
+ void *bm_cmd_buf; /* for issuing commands over USB */
+
+ struct workqueue_struct *work_queue;
+
+ struct mutex init_mutex; /* protect bringup seq */
+ struct i2400m_reset_ctx *reset_ctx; /* protected by init_mutex */
+
+ struct work_struct wake_tx_ws;
+ struct sk_buff *wake_tx_skb;
+
+ struct dentry *debugfs_dentry;
+};
+
+
+/*
+ * Initialize a 'struct i2400m' from all zeroes
+ *
+ * This is a bus-generic API call.
+ */
+static inline
+void i2400m_init(struct i2400m *i2400m)
+{
+ wimax_dev_init(&i2400m->wimax_dev);
+
+ i2400m->boot_mode = 1;
+ init_waitqueue_head(&i2400m->state_wq);
+
+ spin_lock_init(&i2400m->tx_lock);
+ i2400m->tx_pl_min = UINT_MAX;
+ i2400m->tx_size_min = UINT_MAX;
+
+ spin_lock_init(&i2400m->rx_lock);
+ i2400m->rx_pl_min = UINT_MAX;
+ i2400m->rx_size_min = UINT_MAX;
+
+ mutex_init(&i2400m->msg_mutex);
+ init_completion(&i2400m->msg_completion);
+
+ mutex_init(&i2400m->init_mutex);
+ /* wake_tx_ws is initialized in i2400m_tx_setup() */
+}
+
+
+/*
+ * Bus-generic internal APIs
+ * -------------------------
+ */
+
+static inline
+struct i2400m *wimax_dev_to_i2400m(struct wimax_dev *wimax_dev)
+{
+ return container_of(wimax_dev, struct i2400m, wimax_dev);
+}
+
+static inline
+struct i2400m *net_dev_to_i2400m(struct net_device *net_dev)
+{
+ return wimax_dev_to_i2400m(netdev_priv(net_dev));
+}
+
+/*
+ * Boot mode support
+ */
+
+/**
+ * i2400m_bm_cmd_flags - flags to i2400m_bm_cmd()
+ *
+ * @I2400M_BM_CMD_RAW: send the command block as-is, without doing any
+ * extra processing for adding CRC.
+ */
+enum i2400m_bm_cmd_flags {
+ I2400M_BM_CMD_RAW = 1 << 2,
+};
+
+/**
+ * i2400m_bri - Boot-ROM indicators
+ *
+ * Flags for i2400m_bootrom_init() and i2400m_dev_bootstrap() [which
+ * are passed from things like i2400m_setup()]. Can be combined with
+ * |.
+ *
+ * @I2400M_BRI_SOFT: The device rebooted already and a reboot
+ * barker received, proceed directly to ack the boot sequence.
+ * @I2400M_BRI_NO_REBOOT: Do not reboot the device and proceed
+ * directly to wait for a reboot barker from the device.
+ * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot
+ * rom after reading the MAC adress. This is quite a dirty hack,
+ * if you ask me -- the device requires the bootrom to be
+ * intialized after reading the MAC address.
+ */
+enum i2400m_bri {
+ I2400M_BRI_SOFT = 1 << 1,
+ I2400M_BRI_NO_REBOOT = 1 << 2,
+ I2400M_BRI_MAC_REINIT = 1 << 3,
+};
+
+extern void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *);
+extern int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri);
+extern int i2400m_read_mac_addr(struct i2400m *);
+extern int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri);
+
+/* Make/grok boot-rom header commands */
+
+static inline
+__le32 i2400m_brh_command(enum i2400m_brh_opcode opcode, unsigned use_checksum,
+ unsigned direct_access)
+{
+ return cpu_to_le32(
+ I2400M_BRH_SIGNATURE
+ | (direct_access ? I2400M_BRH_DIRECT_ACCESS : 0)
+ | I2400M_BRH_RESPONSE_REQUIRED /* response always required */
+ | (use_checksum ? I2400M_BRH_USE_CHECKSUM : 0)
+ | (opcode & I2400M_BRH_OPCODE_MASK));
+}
+
+static inline
+void i2400m_brh_set_opcode(struct i2400m_bootrom_header *hdr,
+ enum i2400m_brh_opcode opcode)
+{
+ hdr->command = cpu_to_le32(
+ (le32_to_cpu(hdr->command) & ~I2400M_BRH_OPCODE_MASK)
+ | (opcode & I2400M_BRH_OPCODE_MASK));
+}
+
+static inline
+unsigned i2400m_brh_get_opcode(const struct i2400m_bootrom_header *hdr)
+{
+ return le32_to_cpu(hdr->command) & I2400M_BRH_OPCODE_MASK;
+}
+
+static inline
+unsigned i2400m_brh_get_response(const struct i2400m_bootrom_header *hdr)
+{
+ return (le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_MASK)
+ >> I2400M_BRH_RESPONSE_SHIFT;
+}
+
+static inline
+unsigned i2400m_brh_get_use_checksum(const struct i2400m_bootrom_header *hdr)
+{
+ return le32_to_cpu(hdr->command) & I2400M_BRH_USE_CHECKSUM;
+}
+
+static inline
+unsigned i2400m_brh_get_response_required(
+ const struct i2400m_bootrom_header *hdr)
+{
+ return le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_REQUIRED;
+}
+
+static inline
+unsigned i2400m_brh_get_direct_access(const struct i2400m_bootrom_header *hdr)
+{
+ return le32_to_cpu(hdr->command) & I2400M_BRH_DIRECT_ACCESS;
+}
+
+static inline
+unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr)
+{
+ return (le32_to_cpu(hdr->command) & I2400M_BRH_SIGNATURE_MASK)
+ >> I2400M_BRH_SIGNATURE_SHIFT;
+}
+
+
+/*
+ * Driver / device setup and internal functions
+ */
+extern void i2400m_netdev_setup(struct net_device *net_dev);
+extern int i2400m_tx_setup(struct i2400m *);
+extern void i2400m_wake_tx_work(struct work_struct *);
+extern void i2400m_tx_release(struct i2400m *);
+
+extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned,
+ const void *, int);
+enum i2400m_pt;
+extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt);
+
+#ifdef CONFIG_DEBUG_FS
+extern int i2400m_debugfs_add(struct i2400m *);
+extern void i2400m_debugfs_rm(struct i2400m *);
+#else
+static inline int i2400m_debugfs_add(struct i2400m *i2400m)
+{
+ return 0;
+}
+static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {}
+#endif
+
+/* Called by _dev_start()/_dev_stop() to initialize the device itself */
+extern int i2400m_dev_initialize(struct i2400m *);
+extern void i2400m_dev_shutdown(struct i2400m *);
+
+extern struct attribute_group i2400m_dev_attr_group;
+
+extern int i2400m_schedule_work(struct i2400m *,
+ void (*)(struct work_struct *), gfp_t);
+
+/* HDI message's payload description handling */
+
+static inline
+size_t i2400m_pld_size(const struct i2400m_pld *pld)
+{
+ return I2400M_PLD_SIZE_MASK & le32_to_cpu(pld->val);
+}
+
+static inline
+enum i2400m_pt i2400m_pld_type(const struct i2400m_pld *pld)
+{
+ return (I2400M_PLD_TYPE_MASK & le32_to_cpu(pld->val))
+ >> I2400M_PLD_TYPE_SHIFT;
+}
+
+static inline
+void i2400m_pld_set(struct i2400m_pld *pld, size_t size,
+ enum i2400m_pt type)
+{
+ pld->val = cpu_to_le32(
+ ((type << I2400M_PLD_TYPE_SHIFT) & I2400M_PLD_TYPE_MASK)
+ | (size & I2400M_PLD_SIZE_MASK));
+}
+
+
+/*
+ * API for the bus-specific drivers
+ * --------------------------------
+ */
+
+static inline
+struct i2400m *i2400m_get(struct i2400m *i2400m)
+{
+ dev_hold(i2400m->wimax_dev.net_dev);
+ return i2400m;
+}
+
+static inline
+void i2400m_put(struct i2400m *i2400m)
+{
+ dev_put(i2400m->wimax_dev.net_dev);
+}
+
+extern int i2400m_dev_reset_handle(struct i2400m *);
+
+/*
+ * _setup()/_release() are called by the probe/disconnect functions of
+ * the bus-specific drivers.
+ */
+extern int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags);
+extern void i2400m_release(struct i2400m *);
+
+extern int i2400m_rx(struct i2400m *, struct sk_buff *);
+extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *);
+extern void i2400m_tx_msg_sent(struct i2400m *);
+
+static const __le32 i2400m_NBOOT_BARKER[4] = {
+ __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
+ __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
+ __constant_cpu_to_le32(I2400M_NBOOT_BARKER),
+ __constant_cpu_to_le32(I2400M_NBOOT_BARKER)
+};
+
+static const __le32 i2400m_SBOOT_BARKER[4] = {
+ __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
+ __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
+ __constant_cpu_to_le32(I2400M_SBOOT_BARKER),
+ __constant_cpu_to_le32(I2400M_SBOOT_BARKER)
+};
+
+
+/*
+ * Utility functions
+ */
+
+static inline
+struct device *i2400m_dev(struct i2400m *i2400m)
+{
+ return i2400m->wimax_dev.net_dev->dev.parent;
+}
+
+/*
+ * Helper for scheduling simple work functions
+ *
+ * This struct can get any kind of payload attached (normally in the
+ * form of a struct where you pack the stuff you want to pass to the
+ * _work function).
+ */
+struct i2400m_work {
+ struct work_struct ws;
+ struct i2400m *i2400m;
+ u8 pl[0];
+};
+extern int i2400m_queue_work(struct i2400m *,
+ void (*)(struct work_struct *), gfp_t,
+ const void *, size_t);
+
+extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *,
+ char *, size_t);
+extern int i2400m_msg_size_check(struct i2400m *,
+ const struct i2400m_l3l4_hdr *, size_t);
+extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t);
+extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int);
+extern void i2400m_msg_ack_hook(struct i2400m *,
+ const struct i2400m_l3l4_hdr *, size_t);
+extern void i2400m_report_hook(struct i2400m *,
+ const struct i2400m_l3l4_hdr *, size_t);
+extern int i2400m_cmd_enter_powersave(struct i2400m *);
+extern int i2400m_cmd_get_state(struct i2400m *);
+extern int i2400m_cmd_exit_idle(struct i2400m *);
+extern struct sk_buff *i2400m_get_device_info(struct i2400m *);
+extern int i2400m_firmware_check(struct i2400m *);
+extern int i2400m_set_init_config(struct i2400m *,
+ const struct i2400m_tlv_hdr **, size_t);
+
+static inline
+struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep)
+{
+ return &iface->cur_altsetting->endpoint[ep].desc;
+}
+
+extern int i2400m_op_rfkill_sw_toggle(struct wimax_dev *,
+ enum wimax_rf_state);
+extern void i2400m_report_tlv_rf_switches_status(
+ struct i2400m *, const struct i2400m_tlv_rf_switches_status *);
+
+
+/*
+ * Do a millisecond-sleep for allowing wireshark to dump all the data
+ * packets. Used only for debugging.
+ */
+static inline
+void __i2400m_msleep(unsigned ms)
+{
+#if 1
+#else
+ msleep(ms);
+#endif
+}
+
+/* Module parameters */
+
+extern int i2400m_idle_mode_disabled;
+
+
+#endif /* #ifndef __I2400M_H__ */
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
new file mode 100644
index 000000000000..63fe708e8a31
--- /dev/null
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -0,0 +1,524 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Glue with the networking stack
+ *
+ *
+ * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * This implements an ethernet device for the i2400m.
+ *
+ * We fake being an ethernet device to simplify the support from user
+ * space and from the other side. The world is (sadly) configured to
+ * take in only Ethernet devices...
+ *
+ * Because of this, currently there is an copy-each-rxed-packet
+ * overhead on the RX path. Each IP packet has to be reallocated to
+ * add an ethernet header (as there is no space in what we get from
+ * the device). This is a known drawback and coming versions of the
+ * device's firmware are being changed to add header space that can be
+ * used to insert the ethernet header without having to reallocate and
+ * copy.
+ *
+ * TX error handling is tricky; because we have to FIFO/queue the
+ * buffers for transmission (as the hardware likes it aggregated), we
+ * just give the skb to the TX subsystem and by the time it is
+ * transmitted, we have long forgotten about it. So we just don't care
+ * too much about it.
+ *
+ * Note that when the device is in idle mode with the basestation, we
+ * need to negotiate coming back up online. That involves negotiation
+ * and possible user space interaction. Thus, we defer to a workqueue
+ * to do all that. By default, we only queue a single packet and drop
+ * the rest, as potentially the time to go back from idle to normal is
+ * long.
+ *
+ * ROADMAP
+ *
+ * i2400m_open Called on ifconfig up
+ * i2400m_stop Called on ifconfig down
+ *
+ * i2400m_hard_start_xmit Called by the network stack to send a packet
+ * i2400m_net_wake_tx Wake up device from basestation-IDLE & TX
+ * i2400m_wake_tx_work
+ * i2400m_cmd_exit_idle
+ * i2400m_tx
+ * i2400m_net_tx TX a data frame
+ * i2400m_tx
+ *
+ * i2400m_change_mtu Called on ifconfig mtu XXX
+ *
+ * i2400m_tx_timeout Called when the device times out
+ *
+ * i2400m_net_rx Called by the RX code when a data frame is
+ * available.
+ * i2400m_netdev_setup Called to setup all the netdev stuff from
+ * alloc_netdev.
+ */
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include "i2400m.h"
+
+
+#define D_SUBMODULE netdev
+#include "debug-levels.h"
+
+enum {
+/* netdev interface */
+ /*
+ * Out of NWG spec (R1_v1.2.2), 3.3.3 ASN Bearer Plane MTU Size
+ *
+ * The MTU is 1400 or less
+ */
+ I2400M_MAX_MTU = 1400,
+ I2400M_TX_TIMEOUT = HZ,
+ I2400M_TX_QLEN = 5,
+};
+
+
+static
+int i2400m_open(struct net_device *net_dev)
+{
+ int result;
+ struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
+ if (i2400m->ready == 0) {
+ dev_err(dev, "Device is still initializing\n");
+ result = -EBUSY;
+ } else
+ result = 0;
+ d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
+ net_dev, i2400m, result);
+ return result;
+}
+
+
+/*
+ *
+ * On kernel versions where cancel_work_sync() didn't return anything,
+ * we rely on wake_tx_skb() being non-NULL.
+ */
+static
+int i2400m_stop(struct net_device *net_dev)
+{
+ struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m);
+ /* See i2400m_hard_start_xmit(), references are taken there
+ * and here we release them if the work was still
+ * pending. Note we can't differentiate work not pending vs
+ * never scheduled, so the NULL check does that. */
+ if (cancel_work_sync(&i2400m->wake_tx_ws) == 0
+ && i2400m->wake_tx_skb != NULL) {
+ unsigned long flags;
+ struct sk_buff *wake_tx_skb;
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+ wake_tx_skb = i2400m->wake_tx_skb; /* compat help */
+ i2400m->wake_tx_skb = NULL; /* compat help */
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+ i2400m_put(i2400m);
+ kfree_skb(wake_tx_skb);
+ }
+ d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m);
+ return 0;
+}
+
+
+/*
+ * Wake up the device and transmit a held SKB, then restart the net queue
+ *
+ * When the device goes into basestation-idle mode, we need to tell it
+ * to exit that mode; it will negotiate with the base station, user
+ * space may have to intervene to rehandshake crypto and then tell us
+ * when it is ready to transmit the packet we have "queued". Still we
+ * need to give it sometime after it reports being ok.
+ *
+ * On error, there is not much we can do. If the error was on TX, we
+ * still wake the queue up to see if the next packet will be luckier.
+ *
+ * If _cmd_exit_idle() fails...well, it could be many things; most
+ * commonly it is that something else took the device out of IDLE mode
+ * (for example, the base station). In that case we get an -EILSEQ and
+ * we are just going to ignore that one. If the device is back to
+ * connected, then fine -- if it is someother state, the packet will
+ * be dropped anyway.
+ */
+void i2400m_wake_tx_work(struct work_struct *ws)
+{
+ int result;
+ struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws);
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *skb = i2400m->wake_tx_skb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+ skb = i2400m->wake_tx_skb;
+ i2400m->wake_tx_skb = NULL;
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+
+ d_fnstart(3, dev, "(ws %p i2400m %p skb %p)\n", ws, i2400m, skb);
+ result = -EINVAL;
+ if (skb == NULL) {
+ dev_err(dev, "WAKE&TX: skb dissapeared!\n");
+ goto out_put;
+ }
+ result = i2400m_cmd_exit_idle(i2400m);
+ if (result == -EILSEQ)
+ result = 0;
+ if (result < 0) {
+ dev_err(dev, "WAKE&TX: device didn't get out of idle: "
+ "%d\n", result);
+ goto error;
+ }
+ result = wait_event_timeout(i2400m->state_wq,
+ i2400m->state != I2400M_SS_IDLE, 5 * HZ);
+ if (result == 0)
+ result = -ETIMEDOUT;
+ if (result < 0) {
+ dev_err(dev, "WAKE&TX: error waiting for device to exit IDLE: "
+ "%d\n", result);
+ goto error;
+ }
+ msleep(20); /* device still needs some time or it drops it */
+ result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA);
+ netif_wake_queue(i2400m->wimax_dev.net_dev);
+error:
+ kfree_skb(skb); /* refcount transferred by _hard_start_xmit() */
+out_put:
+ i2400m_put(i2400m);
+ d_fnend(3, dev, "(ws %p i2400m %p skb %p) = void [%d]\n",
+ ws, i2400m, skb, result);
+}
+
+
+/*
+ * Prepare the data payload TX header
+ *
+ * The i2400m expects a 4 byte header in front of a data packet.
+ *
+ * Because we pretend to be an ethernet device, this packet comes with
+ * an ethernet header. Pull it and push our header.
+ */
+static
+void i2400m_tx_prep_header(struct sk_buff *skb)
+{
+ struct i2400m_pl_data_hdr *pl_hdr;
+ skb_pull(skb, ETH_HLEN);
+ pl_hdr = (struct i2400m_pl_data_hdr *) skb_push(skb, sizeof(*pl_hdr));
+ pl_hdr->reserved = 0;
+}
+
+
+/*
+ * TX an skb to an idle device
+ *
+ * When the device is in basestation-idle mode, we need to wake it up
+ * and then TX. So we queue a work_struct for doing so.
+ *
+ * We need to get an extra ref for the skb (so it is not dropped), as
+ * well as be careful not to queue more than one request (won't help
+ * at all). If more than one request comes or there are errors, we
+ * just drop the packets (see i2400m_hard_start_xmit()).
+ */
+static
+int i2400m_net_wake_tx(struct i2400m *i2400m, struct net_device *net_dev,
+ struct sk_buff *skb)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ unsigned long flags;
+
+ d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
+ if (net_ratelimit()) {
+ d_printf(3, dev, "WAKE&NETTX: "
+ "skb %p sending %d bytes to radio\n",
+ skb, skb->len);
+ d_dump(4, dev, skb->data, skb->len);
+ }
+ /* We hold a ref count for i2400m and skb, so when
+ * stopping() the device, we need to cancel that work
+ * and if pending, release those resources. */
+ result = 0;
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+ if (!work_pending(&i2400m->wake_tx_ws)) {
+ netif_stop_queue(net_dev);
+ i2400m_get(i2400m);
+ i2400m->wake_tx_skb = skb_get(skb); /* transfer ref count */
+ i2400m_tx_prep_header(skb);
+ result = schedule_work(&i2400m->wake_tx_ws);
+ WARN_ON(result == 0);
+ }
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+ if (result == 0) {
+ /* Yes, this happens even if we stopped the
+ * queue -- blame the queue disciplines that
+ * queue without looking -- I guess there is a reason
+ * for that. */
+ if (net_ratelimit())
+ d_printf(1, dev, "NETTX: device exiting idle, "
+ "dropping skb %p, queue running %d\n",
+ skb, netif_queue_stopped(net_dev));
+ result = -EBUSY;
+ }
+ d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
+ return result;
+}
+
+
+/*
+ * Transmit a packet to the base station on behalf of the network stack.
+ *
+ * Returns: 0 if ok, < 0 errno code on error.
+ *
+ * We need to pull the ethernet header and add the hardware header,
+ * which is currently set to all zeroes and reserved.
+ */
+static
+int i2400m_net_tx(struct i2400m *i2400m, struct net_device *net_dev,
+ struct sk_buff *skb)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(i2400m %p net_dev %p skb %p)\n",
+ i2400m, net_dev, skb);
+ /* FIXME: check eth hdr, only IPv4 is routed by the device as of now */
+ net_dev->trans_start = jiffies;
+ i2400m_tx_prep_header(skb);
+ d_printf(3, dev, "NETTX: skb %p sending %d bytes to radio\n",
+ skb, skb->len);
+ d_dump(4, dev, skb->data, skb->len);
+ result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA);
+ d_fnend(3, dev, "(i2400m %p net_dev %p skb %p) = %d\n",
+ i2400m, net_dev, skb, result);
+ return result;
+}
+
+
+/*
+ * Transmit a packet to the base station on behalf of the network stack
+ *
+ *
+ * Returns: NETDEV_TX_OK (always, even in case of error)
+ *
+ * In case of error, we just drop it. Reasons:
+ *
+ * - we add a hw header to each skb, and if the network stack
+ * retries, we have no way to know if that skb has it or not.
+ *
+ * - network protocols have their own drop-recovery mechanisms
+ *
+ * - there is not much else we can do
+ *
+ * If the device is idle, we need to wake it up; that is an operation
+ * that will sleep. See i2400m_net_wake_tx() for details.
+ */
+static
+int i2400m_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *net_dev)
+{
+ int result;
+ struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
+ if (i2400m->state == I2400M_SS_IDLE)
+ result = i2400m_net_wake_tx(i2400m, net_dev, skb);
+ else
+ result = i2400m_net_tx(i2400m, net_dev, skb);
+ if (result < 0)
+ net_dev->stats.tx_dropped++;
+ else {
+ net_dev->stats.tx_packets++;
+ net_dev->stats.tx_bytes += skb->len;
+ }
+ kfree_skb(skb);
+ result = NETDEV_TX_OK;
+ d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
+ return result;
+}
+
+
+static
+int i2400m_change_mtu(struct net_device *net_dev, int new_mtu)
+{
+ int result;
+ struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+ struct device *dev = i2400m_dev(i2400m);
+
+ if (new_mtu >= I2400M_MAX_MTU) {
+ dev_err(dev, "Cannot change MTU to %d (max is %d)\n",
+ new_mtu, I2400M_MAX_MTU);
+ result = -EINVAL;
+ } else {
+ net_dev->mtu = new_mtu;
+ result = 0;
+ }
+ return result;
+}
+
+
+static
+void i2400m_tx_timeout(struct net_device *net_dev)
+{
+ /*
+ * We might want to kick the device
+ *
+ * There is not much we can do though, as the device requires
+ * that we send the data aggregated. By the time we receive
+ * this, there might be data pending to be sent or not...
+ */
+ net_dev->stats.tx_errors++;
+ return;
+}
+
+
+/*
+ * Create a fake ethernet header
+ *
+ * For emulating an ethernet device, every received IP header has to
+ * be prefixed with an ethernet header.
+ *
+ * What we receive has (potentially) many IP packets concatenated with
+ * no ETH_HLEN bytes prefixed. Thus there is no space for an eth
+ * header.
+ *
+ * We would have to reallocate or do ugly fragment tricks in order to
+ * add it.
+ *
+ * But what we do is use the header space of the RX transaction
+ * (*msg_hdr) as we don't need it anymore; then we'll point all the
+ * data skbs there, as they share the same backing store.
+ *
+ * We only support IPv4 for v3 firmware.
+ */
+static
+void i2400m_rx_fake_eth_header(struct net_device *net_dev,
+ void *_eth_hdr)
+{
+ struct ethhdr *eth_hdr = _eth_hdr;
+
+ memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest));
+ memset(eth_hdr->h_source, 0, sizeof(eth_hdr->h_dest));
+ eth_hdr->h_proto = __constant_cpu_to_be16(ETH_P_IP);
+}
+
+
+/*
+ * i2400m_net_rx - pass a network packet to the stack
+ *
+ * @i2400m: device instance
+ * @skb_rx: the skb where the buffer pointed to by @buf is
+ * @i: 1 if payload is the only one
+ * @buf: pointer to the buffer containing the data
+ * @len: buffer's length
+ *
+ * We just clone the skb and set it up so that it's skb->data pointer
+ * points to "buf" and it's length.
+ *
+ * Note that if the payload is the last (or the only one) in a
+ * multi-payload message, we don't clone the SKB but just reuse it.
+ *
+ * This function is normally run from a thread context. However, we
+ * still use netif_rx() instead of netif_receive_skb() as was
+ * recommended in the mailing list. Reason is in some stress tests
+ * when sending/receiving a lot of data we seem to hit a softlock in
+ * the kernel's TCP implementation [aroudn tcp_delay_timer()]. Using
+ * netif_rx() took care of the issue.
+ *
+ * This is, of course, still open to do more research on why running
+ * with netif_receive_skb() hits this softlock. FIXME.
+ *
+ * FIXME: currently we don't do any efforts at distinguishing if what
+ * we got was an IPv4 or IPv6 header, to setup the protocol field
+ * correctly.
+ */
+void i2400m_net_rx(struct i2400m *i2400m, struct sk_buff *skb_rx,
+ unsigned i, const void *buf, int buf_len)
+{
+ struct net_device *net_dev = i2400m->wimax_dev.net_dev;
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *skb;
+
+ d_fnstart(2, dev, "(i2400m %p buf %p buf_len %d)\n",
+ i2400m, buf, buf_len);
+ if (i) {
+ skb = skb_get(skb_rx);
+ d_printf(2, dev, "RX: reusing first payload skb %p\n", skb);
+ skb_pull(skb, buf - (void *) skb->data);
+ skb_trim(skb, (void *) skb_end_pointer(skb) - buf);
+ } else {
+ /* Yes, this is bad -- a lot of overhead -- see
+ * comments at the top of the file */
+ skb = __netdev_alloc_skb(net_dev, buf_len, GFP_KERNEL);
+ if (skb == NULL) {
+ dev_err(dev, "NETRX: no memory to realloc skb\n");
+ net_dev->stats.rx_dropped++;
+ goto error_skb_realloc;
+ }
+ memcpy(skb_put(skb, buf_len), buf, buf_len);
+ }
+ i2400m_rx_fake_eth_header(i2400m->wimax_dev.net_dev,
+ skb->data - ETH_HLEN);
+ skb_set_mac_header(skb, -ETH_HLEN);
+ skb->dev = i2400m->wimax_dev.net_dev;
+ skb->protocol = htons(ETH_P_IP);
+ net_dev->stats.rx_packets++;
+ net_dev->stats.rx_bytes += buf_len;
+ d_printf(3, dev, "NETRX: receiving %d bytes to network stack\n",
+ buf_len);
+ d_dump(4, dev, buf, buf_len);
+ netif_rx_ni(skb); /* see notes in function header */
+error_skb_realloc:
+ d_fnend(2, dev, "(i2400m %p buf %p buf_len %d) = void\n",
+ i2400m, buf, buf_len);
+}
+
+
+/**
+ * i2400m_netdev_setup - Setup setup @net_dev's i2400m private data
+ *
+ * Called by alloc_netdev()
+ */
+void i2400m_netdev_setup(struct net_device *net_dev)
+{
+ d_fnstart(3, NULL, "(net_dev %p)\n", net_dev);
+ ether_setup(net_dev);
+ net_dev->mtu = I2400M_MAX_MTU;
+ net_dev->tx_queue_len = I2400M_TX_QLEN;
+ net_dev->features =
+ NETIF_F_VLAN_CHALLENGED
+ | NETIF_F_HIGHDMA;
+ net_dev->flags =
+ IFF_NOARP /* i2400m is apure IP device */
+ & (~IFF_BROADCAST /* i2400m is P2P */
+ & ~IFF_MULTICAST);
+ net_dev->watchdog_timeo = I2400M_TX_TIMEOUT;
+ net_dev->open = i2400m_open;
+ net_dev->stop = i2400m_stop;
+ net_dev->hard_start_xmit = i2400m_hard_start_xmit;
+ net_dev->change_mtu = i2400m_change_mtu;
+ net_dev->tx_timeout = i2400m_tx_timeout;
+ d_fnend(3, NULL, "(net_dev %p) = void\n", net_dev);
+}
+EXPORT_SYMBOL_GPL(i2400m_netdev_setup);
+
diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c
new file mode 100644
index 000000000000..487ec58cea46
--- /dev/null
+++ b/drivers/net/wimax/i2400m/op-rfkill.c
@@ -0,0 +1,207 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Implement backend for the WiMAX stack rfkill support
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * The WiMAX kernel stack integrates into RF-Kill and keeps the
+ * switches's status. We just need to:
+ *
+ * - report changes in the HW RF Kill switch [with
+ * wimax_rfkill_{sw,hw}_report(), which happens when we detect those
+ * indications coming through hardware reports]. We also do it on
+ * initialization to let the stack know the intial HW state.
+ *
+ * - implement indications from the stack to change the SW RF Kill
+ * switch (coming from sysfs, the wimax stack or user space).
+ */
+#include "i2400m.h"
+#include <linux/wimax/i2400m.h>
+
+
+
+#define D_SUBMODULE rfkill
+#include "debug-levels.h"
+
+/*
+ * Return true if the i2400m radio is in the requested wimax_rf_state state
+ *
+ */
+static
+int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state)
+{
+ if (state == WIMAX_RF_OFF)
+ return i2400m->state == I2400M_SS_RF_OFF
+ || i2400m->state == I2400M_SS_RF_SHUTDOWN;
+ else if (state == WIMAX_RF_ON)
+ /* state == WIMAX_RF_ON */
+ return i2400m->state != I2400M_SS_RF_OFF
+ && i2400m->state != I2400M_SS_RF_SHUTDOWN;
+ else
+ BUG();
+}
+
+
+/*
+ * WiMAX stack operation: implement SW RFKill toggling
+ *
+ * @wimax_dev: device descriptor
+ * @skb: skb where the message has been received; skb->data is
+ * expected to point to the message payload.
+ * @genl_info: passed by the generic netlink layer
+ *
+ * Generic Netlink will call this function when a message is sent from
+ * userspace to change the software RF-Kill switch status.
+ *
+ * This function will set the device's sofware RF-Kill switch state to
+ * match what is requested.
+ *
+ * NOTE: the i2400m has a strict state machine; we can only set the
+ * RF-Kill switch when it is on, the HW RF-Kill is on and the
+ * device is initialized. So we ignore errors steaming from not
+ * being in the right state (-EILSEQ).
+ */
+int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev,
+ enum wimax_rf_state state)
+{
+ int result;
+ struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
+ struct device *dev = i2400m_dev(i2400m);
+ struct sk_buff *ack_skb;
+ struct {
+ struct i2400m_l3l4_hdr hdr;
+ struct i2400m_tlv_rf_operation sw_rf;
+ } __attribute__((packed)) *cmd;
+ char strerr[32];
+
+ d_fnstart(4, dev, "(wimax_dev %p state %d)\n", wimax_dev, state);
+
+ result = -ENOMEM;
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ goto error_alloc;
+ cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_RF_CONTROL);
+ cmd->hdr.length = sizeof(cmd->sw_rf);
+ cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION);
+ cmd->sw_rf.hdr.type = cpu_to_le16(I2400M_TLV_RF_OPERATION);
+ cmd->sw_rf.hdr.length = cpu_to_le16(sizeof(cmd->sw_rf.status));
+ switch (state) {
+ case WIMAX_RF_OFF: /* RFKILL ON, radio OFF */
+ cmd->sw_rf.status = cpu_to_le32(2);
+ break;
+ case WIMAX_RF_ON: /* RFKILL OFF, radio ON */
+ cmd->sw_rf.status = cpu_to_le32(1);
+ break;
+ default:
+ BUG();
+ }
+
+ ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
+ result = PTR_ERR(ack_skb);
+ if (IS_ERR(ack_skb)) {
+ dev_err(dev, "Failed to issue 'RF Control' command: %d\n",
+ result);
+ goto error_msg_to_dev;
+ }
+ result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
+ strerr, sizeof(strerr));
+ if (result < 0) {
+ dev_err(dev, "'RF Control' (0x%04x) command failed: %d - %s\n",
+ I2400M_MT_CMD_RF_CONTROL, result, strerr);
+ goto error_cmd;
+ }
+
+ /* Now we wait for the state to change to RADIO_OFF or RADIO_ON */
+ result = wait_event_timeout(
+ i2400m->state_wq, i2400m_radio_is(i2400m, state),
+ 5 * HZ);
+ if (result == 0)
+ result = -ETIMEDOUT;
+ if (result < 0)
+ dev_err(dev, "Error waiting for device to toggle RF state: "
+ "%d\n", result);
+ result = 0;
+error_cmd:
+ kfree_skb(ack_skb);
+error_msg_to_dev:
+error_alloc:
+ d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n",
+ wimax_dev, state, result);
+ return result;
+}
+
+
+/*
+ * Inform the WiMAX stack of changes in the RF Kill switches reported
+ * by the device
+ *
+ * @i2400m: device descriptor
+ * @rfss: TLV for RF Switches status; already validated
+ *
+ * NOTE: the reports on RF switch status cannot be trusted
+ * or used until the device is in a state of RADIO_OFF
+ * or greater.
+ */
+void i2400m_report_tlv_rf_switches_status(
+ struct i2400m *i2400m,
+ const struct i2400m_tlv_rf_switches_status *rfss)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ enum i2400m_rf_switch_status hw, sw;
+ enum wimax_st wimax_state;
+
+ sw = le32_to_cpu(rfss->sw_rf_switch);
+ hw = le32_to_cpu(rfss->hw_rf_switch);
+
+ d_fnstart(3, dev, "(i2400m %p rfss %p [hw %u sw %u])\n",
+ i2400m, rfss, hw, sw);
+ /* We only process rw switch evens when the device has been
+ * fully initialized */
+ wimax_state = wimax_state_get(&i2400m->wimax_dev);
+ if (wimax_state < WIMAX_ST_RADIO_OFF) {
+ d_printf(3, dev, "ignoring RF switches report, state %u\n",
+ wimax_state);
+ goto out;
+ }
+ switch (sw) {
+ case I2400M_RF_SWITCH_ON: /* RF Kill disabled (radio on) */
+ wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_ON);
+ break;
+ case I2400M_RF_SWITCH_OFF: /* RF Kill enabled (radio off) */
+ wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_OFF);
+ break;
+ default:
+ dev_err(dev, "HW BUG? Unknown RF SW state 0x%x\n", sw);
+ }
+
+ switch (hw) {
+ case I2400M_RF_SWITCH_ON: /* RF Kill disabled (radio on) */
+ wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_ON);
+ break;
+ case I2400M_RF_SWITCH_OFF: /* RF Kill enabled (radio off) */
+ wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_OFF);
+ break;
+ default:
+ dev_err(dev, "HW BUG? Unknown RF HW state 0x%x\n", hw);
+ }
+out:
+ d_fnend(3, dev, "(i2400m %p rfss %p [hw %u sw %u]) = void\n",
+ i2400m, rfss, hw, sw);
+}
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c
new file mode 100644
index 000000000000..6922022710ac
--- /dev/null
+++ b/drivers/net/wimax/i2400m/rx.c
@@ -0,0 +1,534 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Handle incoming traffic and deliver it to the control or data planes
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * - Initial implementation
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Use skb_clone(), break up processing in chunks
+ * - Split transport/device specific
+ * - Make buffer size dynamic to exert less memory pressure
+ *
+ *
+ * This handles the RX path.
+ *
+ * We receive an RX message from the bus-specific driver, which
+ * contains one or more payloads that have potentially different
+ * destinataries (data or control paths).
+ *
+ * So we just take that payload from the transport specific code in
+ * the form of an skb, break it up in chunks (a cloned skb each in the
+ * case of network packets) and pass it to netdev or to the
+ * command/ack handler (and from there to the WiMAX stack).
+ *
+ * PROTOCOL FORMAT
+ *
+ * The format of the buffer is:
+ *
+ * HEADER (struct i2400m_msg_hdr)
+ * PAYLOAD DESCRIPTOR 0 (struct i2400m_pld)
+ * PAYLOAD DESCRIPTOR 1
+ * ...
+ * PAYLOAD DESCRIPTOR N
+ * PAYLOAD 0 (raw bytes)
+ * PAYLOAD 1
+ * ...
+ * PAYLOAD N
+ *
+ * See tx.c for a deeper description on alignment requirements and
+ * other fun facts of it.
+ *
+ * ROADMAP
+ *
+ * i2400m_rx
+ * i2400m_rx_msg_hdr_check
+ * i2400m_rx_pl_descr_check
+ * i2400m_rx_payload
+ * i2400m_net_rx
+ * i2400m_rx_ctl
+ * i2400m_msg_size_check
+ * i2400m_report_hook_work [in a workqueue]
+ * i2400m_report_hook
+ * wimax_msg_to_user
+ * i2400m_rx_ctl_ack
+ * wimax_msg_to_user_alloc
+ * i2400m_rx_trace
+ * i2400m_msg_size_check
+ * wimax_msg
+ */
+#include <linux/kernel.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include "i2400m.h"
+
+
+#define D_SUBMODULE rx
+#include "debug-levels.h"
+
+struct i2400m_report_hook_args {
+ struct sk_buff *skb_rx;
+ const struct i2400m_l3l4_hdr *l3l4_hdr;
+ size_t size;
+};
+
+
+/*
+ * Execute i2400m_report_hook in a workqueue
+ *
+ * Unpacks arguments from the deferred call, executes it and then
+ * drops the references.
+ *
+ * Obvious NOTE: References are needed because we are a separate
+ * thread; otherwise the buffer changes under us because it is
+ * released by the original caller.
+ */
+static
+void i2400m_report_hook_work(struct work_struct *ws)
+{
+ struct i2400m_work *iw =
+ container_of(ws, struct i2400m_work, ws);
+ struct i2400m_report_hook_args *args = (void *) iw->pl;
+ i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size);
+ kfree_skb(args->skb_rx);
+ i2400m_put(iw->i2400m);
+ kfree(iw);
+}
+
+
+/*
+ * Process an ack to a command
+ *
+ * @i2400m: device descriptor
+ * @payload: pointer to message
+ * @size: size of the message
+ *
+ * Pass the acknodledgment (in an skb) to the thread that is waiting
+ * for it in i2400m->msg_completion.
+ *
+ * We need to coordinate properly with the thread waiting for the
+ * ack. Check if it is waiting or if it is gone. We loose the spinlock
+ * to avoid allocating on atomic contexts (yeah, could use GFP_ATOMIC,
+ * but this is not so speed critical).
+ */
+static
+void i2400m_rx_ctl_ack(struct i2400m *i2400m,
+ const void *payload, size_t size)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+ unsigned long flags;
+ struct sk_buff *ack_skb;
+
+ /* Anyone waiting for an answer? */
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ if (i2400m->ack_skb != ERR_PTR(-EINPROGRESS)) {
+ dev_err(dev, "Huh? reply to command with no waiters\n");
+ goto error_no_waiter;
+ }
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+
+ ack_skb = wimax_msg_alloc(wimax_dev, NULL, payload, size, GFP_KERNEL);
+
+ /* Check waiter didn't time out waiting for the answer... */
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ if (i2400m->ack_skb != ERR_PTR(-EINPROGRESS)) {
+ d_printf(1, dev, "Huh? waiter for command reply cancelled\n");
+ goto error_waiter_cancelled;
+ }
+ if (ack_skb == NULL) {
+ dev_err(dev, "CMD/GET/SET ack: cannot allocate SKB\n");
+ i2400m->ack_skb = ERR_PTR(-ENOMEM);
+ } else
+ i2400m->ack_skb = ack_skb;
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+ complete(&i2400m->msg_completion);
+ return;
+
+error_waiter_cancelled:
+ if (ack_skb)
+ kfree_skb(ack_skb);
+error_no_waiter:
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+ return;
+}
+
+
+/*
+ * Receive and process a control payload
+ *
+ * @i2400m: device descriptor
+ * @skb_rx: skb that contains the payload (for reference counting)
+ * @payload: pointer to message
+ * @size: size of the message
+ *
+ * There are two types of control RX messages: reports (asynchronous,
+ * like your every day interrupts) and 'acks' (reponses to a command,
+ * get or set request).
+ *
+ * If it is a report, we run hooks on it (to extract information for
+ * things we need to do in the driver) and then pass it over to the
+ * WiMAX stack to send it to user space.
+ *
+ * NOTE: report processing is done in a workqueue specific to the
+ * generic driver, to avoid deadlocks in the system.
+ *
+ * If it is not a report, it is an ack to a previously executed
+ * command, set or get, so wake up whoever is waiting for it from
+ * i2400m_msg_to_dev(). i2400m_rx_ctl_ack() takes care of that.
+ *
+ * Note that the sizes we pass to other functions from here are the
+ * sizes of the _l3l4_hdr + payload, not full buffer sizes, as we have
+ * verified in _msg_size_check() that they are congruent.
+ *
+ * For reports: We can't clone the original skb where the data is
+ * because we need to send this up via netlink; netlink has to add
+ * headers and we can't overwrite what's preceeding the payload...as
+ * it is another message. So we just dup them.
+ */
+static
+void i2400m_rx_ctl(struct i2400m *i2400m, struct sk_buff *skb_rx,
+ const void *payload, size_t size)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ const struct i2400m_l3l4_hdr *l3l4_hdr = payload;
+ unsigned msg_type;
+
+ result = i2400m_msg_size_check(i2400m, l3l4_hdr, size);
+ if (result < 0) {
+ dev_err(dev, "HW BUG? device sent a bad message: %d\n",
+ result);
+ goto error_check;
+ }
+ msg_type = le16_to_cpu(l3l4_hdr->type);
+ d_printf(1, dev, "%s 0x%04x: %zu bytes\n",
+ msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET",
+ msg_type, size);
+ d_dump(2, dev, l3l4_hdr, size);
+ if (msg_type & I2400M_MT_REPORT_MASK) {
+ /* These hooks have to be ran serialized; as well, the
+ * handling might force the execution of commands, and
+ * that might cause reentrancy issues with
+ * bus-specific subdrivers and workqueues. So we run
+ * it in a separate workqueue. */
+ struct i2400m_report_hook_args args = {
+ .skb_rx = skb_rx,
+ .l3l4_hdr = l3l4_hdr,
+ .size = size
+ };
+ if (unlikely(i2400m->ready == 0)) /* only send if up */
+ return;
+ skb_get(skb_rx);
+ i2400m_queue_work(i2400m, i2400m_report_hook_work,
+ GFP_KERNEL, &args, sizeof(args));
+ result = wimax_msg(&i2400m->wimax_dev, NULL, l3l4_hdr, size,
+ GFP_KERNEL);
+ if (result < 0)
+ dev_err(dev, "error sending report to userspace: %d\n",
+ result);
+ } else /* an ack to a CMD, GET or SET */
+ i2400m_rx_ctl_ack(i2400m, payload, size);
+error_check:
+ return;
+}
+
+
+
+
+/*
+ * Receive and send up a trace
+ *
+ * @i2400m: device descriptor
+ * @skb_rx: skb that contains the trace (for reference counting)
+ * @payload: pointer to trace message inside the skb
+ * @size: size of the message
+ *
+ * THe i2400m might produce trace information (diagnostics) and we
+ * send them through a different kernel-to-user pipe (to avoid
+ * clogging it).
+ *
+ * As in i2400m_rx_ctl(), we can't clone the original skb where the
+ * data is because we need to send this up via netlink; netlink has to
+ * add headers and we can't overwrite what's preceeding the
+ * payload...as it is another message. So we just dup them.
+ */
+static
+void i2400m_rx_trace(struct i2400m *i2400m,
+ const void *payload, size_t size)
+{
+ int result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+ const struct i2400m_l3l4_hdr *l3l4_hdr = payload;
+ unsigned msg_type;
+
+ result = i2400m_msg_size_check(i2400m, l3l4_hdr, size);
+ if (result < 0) {
+ dev_err(dev, "HW BUG? device sent a bad trace message: %d\n",
+ result);
+ goto error_check;
+ }
+ msg_type = le16_to_cpu(l3l4_hdr->type);
+ d_printf(1, dev, "Trace %s 0x%04x: %zu bytes\n",
+ msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET",
+ msg_type, size);
+ d_dump(2, dev, l3l4_hdr, size);
+ if (unlikely(i2400m->ready == 0)) /* only send if up */
+ return;
+ result = wimax_msg(wimax_dev, "trace", l3l4_hdr, size, GFP_KERNEL);
+ if (result < 0)
+ dev_err(dev, "error sending trace to userspace: %d\n",
+ result);
+error_check:
+ return;
+}
+
+
+/*
+ * Act on a received payload
+ *
+ * @i2400m: device instance
+ * @skb_rx: skb where the transaction was received
+ * @single: 1 if there is only one payload, 0 otherwise
+ * @pld: payload descriptor
+ * @payload: payload data
+ *
+ * Upon reception of a payload, look at its guts in the payload
+ * descriptor and decide what to do with it.
+ */
+static
+void i2400m_rx_payload(struct i2400m *i2400m, struct sk_buff *skb_rx,
+ unsigned single, const struct i2400m_pld *pld,
+ const void *payload)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ size_t pl_size = i2400m_pld_size(pld);
+ enum i2400m_pt pl_type = i2400m_pld_type(pld);
+
+ switch (pl_type) {
+ case I2400M_PT_DATA:
+ d_printf(3, dev, "RX: data payload %zu bytes\n", pl_size);
+ i2400m_net_rx(i2400m, skb_rx, single, payload, pl_size);
+ break;
+ case I2400M_PT_CTRL:
+ i2400m_rx_ctl(i2400m, skb_rx, payload, pl_size);
+ break;
+ case I2400M_PT_TRACE:
+ i2400m_rx_trace(i2400m, payload, pl_size);
+ break;
+ default: /* Anything else shouldn't come to the host */
+ if (printk_ratelimit())
+ dev_err(dev, "RX: HW BUG? unexpected payload type %u\n",
+ pl_type);
+ }
+}
+
+
+/*
+ * Check a received transaction's message header
+ *
+ * @i2400m: device descriptor
+ * @msg_hdr: message header
+ * @buf_size: size of the received buffer
+ *
+ * Check that the declarations done by a RX buffer message header are
+ * sane and consistent with the amount of data that was received.
+ */
+static
+int i2400m_rx_msg_hdr_check(struct i2400m *i2400m,
+ const struct i2400m_msg_hdr *msg_hdr,
+ size_t buf_size)
+{
+ int result = -EIO;
+ struct device *dev = i2400m_dev(i2400m);
+ if (buf_size < sizeof(*msg_hdr)) {
+ dev_err(dev, "RX: HW BUG? message with short header (%zu "
+ "vs %zu bytes expected)\n", buf_size, sizeof(*msg_hdr));
+ goto error;
+ }
+ if (msg_hdr->barker != cpu_to_le32(I2400M_D2H_MSG_BARKER)) {
+ dev_err(dev, "RX: HW BUG? message received with unknown "
+ "barker 0x%08x (buf_size %zu bytes)\n",
+ le32_to_cpu(msg_hdr->barker), buf_size);
+ goto error;
+ }
+ if (msg_hdr->num_pls == 0) {
+ dev_err(dev, "RX: HW BUG? zero payload packets in message\n");
+ goto error;
+ }
+ if (le16_to_cpu(msg_hdr->num_pls) > I2400M_MAX_PLS_IN_MSG) {
+ dev_err(dev, "RX: HW BUG? message contains more payload "
+ "than maximum; ignoring.\n");
+ goto error;
+ }
+ result = 0;
+error:
+ return result;
+}
+
+
+/*
+ * Check a payload descriptor against the received data
+ *
+ * @i2400m: device descriptor
+ * @pld: payload descriptor
+ * @pl_itr: offset (in bytes) in the received buffer the payload is
+ * located
+ * @buf_size: size of the received buffer
+ *
+ * Given a payload descriptor (part of a RX buffer), check it is sane
+ * and that the data it declares fits in the buffer.
+ */
+static
+int i2400m_rx_pl_descr_check(struct i2400m *i2400m,
+ const struct i2400m_pld *pld,
+ size_t pl_itr, size_t buf_size)
+{
+ int result = -EIO;
+ struct device *dev = i2400m_dev(i2400m);
+ size_t pl_size = i2400m_pld_size(pld);
+ enum i2400m_pt pl_type = i2400m_pld_type(pld);
+
+ if (pl_size > i2400m->bus_pl_size_max) {
+ dev_err(dev, "RX: HW BUG? payload @%zu: size %zu is "
+ "bigger than maximum %zu; ignoring message\n",
+ pl_itr, pl_size, i2400m->bus_pl_size_max);
+ goto error;
+ }
+ if (pl_itr + pl_size > buf_size) { /* enough? */
+ dev_err(dev, "RX: HW BUG? payload @%zu: size %zu "
+ "goes beyond the received buffer "
+ "size (%zu bytes); ignoring message\n",
+ pl_itr, pl_size, buf_size);
+ goto error;
+ }
+ if (pl_type >= I2400M_PT_ILLEGAL) {
+ dev_err(dev, "RX: HW BUG? illegal payload type %u; "
+ "ignoring message\n", pl_type);
+ goto error;
+ }
+ result = 0;
+error:
+ return result;
+}
+
+
+/**
+ * i2400m_rx - Receive a buffer of data from the device
+ *
+ * @i2400m: device descriptor
+ * @skb: skbuff where the data has been received
+ *
+ * Parse in a buffer of data that contains an RX message sent from the
+ * device. See the file header for the format. Run all checks on the
+ * buffer header, then run over each payload's descriptors, verify
+ * their consistency and act on each payload's contents. If
+ * everything is succesful, update the device's statistics.
+ *
+ * Note: You need to set the skb to contain only the length of the
+ * received buffer; for that, use skb_trim(skb, RECEIVED_SIZE).
+ *
+ * Returns:
+ *
+ * 0 if ok, < 0 errno on error
+ *
+ * If ok, this function owns now the skb and the caller DOESN'T have
+ * to run kfree_skb() on it. However, on error, the caller still owns
+ * the skb and it is responsible for releasing it.
+ */
+int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb)
+{
+ int i, result;
+ struct device *dev = i2400m_dev(i2400m);
+ const struct i2400m_msg_hdr *msg_hdr;
+ size_t pl_itr, pl_size, skb_len;
+ unsigned long flags;
+ unsigned num_pls;
+
+ skb_len = skb->len;
+ d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n",
+ i2400m, skb, skb_len);
+ result = -EIO;
+ msg_hdr = (void *) skb->data;
+ result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len);
+ if (result < 0)
+ goto error_msg_hdr_check;
+ result = -EIO;
+ num_pls = le16_to_cpu(msg_hdr->num_pls);
+ pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */
+ num_pls * sizeof(msg_hdr->pld[0]);
+ pl_itr = ALIGN(pl_itr, I2400M_PL_PAD);
+ if (pl_itr > skb->len) { /* got all the payload descriptors? */
+ dev_err(dev, "RX: HW BUG? message too short (%u bytes) for "
+ "%u payload descriptors (%zu each, total %zu)\n",
+ skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr);
+ goto error_pl_descr_short;
+ }
+ /* Walk each payload payload--check we really got it */
+ for (i = 0; i < num_pls; i++) {
+ /* work around old gcc warnings */
+ pl_size = i2400m_pld_size(&msg_hdr->pld[i]);
+ result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i],
+ pl_itr, skb->len);
+ if (result < 0)
+ goto error_pl_descr_check;
+ i2400m_rx_payload(i2400m, skb, num_pls == 1, &msg_hdr->pld[i],
+ skb->data + pl_itr);
+ pl_itr += ALIGN(pl_size, I2400M_PL_PAD);
+ cond_resched(); /* Don't monopolize */
+ }
+ kfree_skb(skb);
+ /* Update device statistics */
+ spin_lock_irqsave(&i2400m->rx_lock, flags);
+ i2400m->rx_pl_num += i;
+ if (i > i2400m->rx_pl_max)
+ i2400m->rx_pl_max = i;
+ if (i < i2400m->rx_pl_min)
+ i2400m->rx_pl_min = i;
+ i2400m->rx_num++;
+ i2400m->rx_size_acc += skb->len;
+ if (skb->len < i2400m->rx_size_min)
+ i2400m->rx_size_min = skb->len;
+ if (skb->len > i2400m->rx_size_max)
+ i2400m->rx_size_max = skb->len;
+ spin_unlock_irqrestore(&i2400m->rx_lock, flags);
+error_pl_descr_check:
+error_pl_descr_short:
+error_msg_hdr_check:
+ d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n",
+ i2400m, skb, skb_len, result);
+ return result;
+}
+EXPORT_SYMBOL_GPL(i2400m_rx);
diff --git a/drivers/net/wimax/i2400m/sdio-debug-levels.h b/drivers/net/wimax/i2400m/sdio-debug-levels.h
new file mode 100644
index 000000000000..c51998741301
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-debug-levels.h
@@ -0,0 +1,22 @@
+/*
+ * debug levels control file for the i2400m module's
+ */
+#ifndef __debug_levels__h__
+#define __debug_levels__h__
+
+/* Maximum compile and run time debug level for all submodules */
+#define D_MODULENAME i2400m_sdio
+#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
+
+#include <linux/wimax/debug.h>
+
+/* List of all the enabled modules */
+enum d_module {
+ D_SUBMODULE_DECLARE(main),
+ D_SUBMODULE_DECLARE(tx),
+ D_SUBMODULE_DECLARE(rx),
+ D_SUBMODULE_DECLARE(fw)
+};
+
+
+#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/sdio-fw.c b/drivers/net/wimax/i2400m/sdio-fw.c
new file mode 100644
index 000000000000..3487205d8f50
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-fw.c
@@ -0,0 +1,224 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Firmware uploader's SDIO specifics
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Initial implementation
+ *
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Bus generic/specific split for USB
+ *
+ * Dirk Brandewie <dirk.j.brandewie@intel.com>
+ * - Initial implementation for SDIO
+ *
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - SDIO rehash for changes in the bus-driver model
+ *
+ * THE PROCEDURE
+ *
+ * See fw.c for the generic description of this procedure.
+ *
+ * This file implements only the SDIO specifics. It boils down to how
+ * to send a command and waiting for an acknowledgement from the
+ * device. We do polled reads.
+ *
+ * COMMAND EXECUTION
+ *
+ * THe generic firmware upload code will call i2400m_bus_bm_cmd_send()
+ * to send commands.
+ *
+ * The SDIO devices expects things in 256 byte blocks, so it will pad
+ * it, compute the checksum (if needed) and pass it to SDIO.
+ *
+ * ACK RECEPTION
+ *
+ * This works in polling mode -- the fw loader says when to wait for
+ * data and for that it calls i2400ms_bus_bm_wait_for_ack().
+ *
+ * This will poll the device for data until it is received. We need to
+ * receive at least as much bytes as where asked for (although it'll
+ * always be a multiple of 256 bytes).
+ */
+#include <linux/mmc/sdio_func.h>
+#include "i2400m-sdio.h"
+
+
+#define D_SUBMODULE fw
+#include "sdio-debug-levels.h"
+
+/*
+ * Send a boot-mode command to the SDIO function
+ *
+ * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to
+ * touch the header if the RAW flag is not set.
+ *
+ * @flags: pass thru from i2400m_bm_cmd()
+ * @return: cmd_size if ok, < 0 errno code on error.
+ *
+ * Note the command is padded to the SDIO block size for the device.
+ */
+ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m,
+ const struct i2400m_bootrom_header *_cmd,
+ size_t cmd_size, int flags)
+{
+ ssize_t result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
+ int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd);
+ struct i2400m_bootrom_header *cmd;
+ /* SDIO restriction */
+ size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE);
+
+ d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n",
+ i2400m, _cmd, cmd_size);
+ result = -E2BIG;
+ if (cmd_size > I2400M_BM_CMD_BUF_SIZE)
+ goto error_too_big;
+
+ memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size); /* Prep command */
+ cmd = i2400m->bm_cmd_buf;
+ if (cmd_size_a > cmd_size) /* Zero pad space */
+ memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size);
+ if ((flags & I2400M_BM_CMD_RAW) == 0) {
+ if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0))
+ dev_warn(dev, "SW BUG: response_required == 0\n");
+ i2400m_bm_cmd_prepare(cmd);
+ }
+ d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n",
+ opcode, cmd_size, cmd_size_a);
+ d_dump(5, dev, cmd, cmd_size);
+
+ sdio_claim_host(i2400ms->func); /* Send & check */
+ result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR,
+ i2400m->bm_cmd_buf, cmd_size_a);
+ sdio_release_host(i2400ms->func);
+ if (result < 0) {
+ dev_err(dev, "BM cmd %d: cannot send: %ld\n",
+ opcode, (long) result);
+ goto error_cmd_send;
+ }
+ result = cmd_size;
+error_cmd_send:
+error_too_big:
+ d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n",
+ i2400m, _cmd, cmd_size, (int) result);
+ return result;
+}
+
+
+/*
+ * Read an ack from the device's boot-mode (polling)
+ *
+ * @i2400m:
+ * @_ack: pointer to where to store the read data
+ * @ack_size: how many bytes we should read
+ *
+ * Returns: < 0 errno code on error; otherwise, amount of received bytes.
+ *
+ * The ACK for a BM command is always at least sizeof(*ack) bytes, so
+ * check for that. We don't need to check for device reboots
+ *
+ * NOTE: We do an artificial timeout of 1 sec over the SDIO timeout;
+ * this way we have control over it...there is no way that I know
+ * of setting an SDIO transaction timeout.
+ */
+ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m,
+ struct i2400m_bootrom_header *ack,
+ size_t ack_size)
+{
+ int result;
+ ssize_t rx_size;
+ u64 timeout;
+ struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+
+ BUG_ON(sizeof(*ack) > ack_size);
+
+ d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n",
+ i2400m, ack, ack_size);
+
+ timeout = get_jiffies_64() + 2 * HZ;
+ sdio_claim_host(func);
+ while (1) {
+ if (time_after64(get_jiffies_64(), timeout)) {
+ rx_size = -ETIMEDOUT;
+ dev_err(dev, "timeout waiting for ack data\n");
+ goto error_timedout;
+ }
+
+ /* Find the RX size, check if it fits or not -- it if
+ * doesn't fit, fail, as we have no way to dispose of
+ * the extra data. */
+ rx_size = __i2400ms_rx_get_size(i2400ms);
+ if (rx_size < 0)
+ goto error_rx_get_size;
+ result = -ENOSPC; /* Check it fits */
+ if (rx_size < sizeof(*ack)) {
+ rx_size = -EIO;
+ dev_err(dev, "HW BUG? received is too small (%zu vs "
+ "%zu needed)\n", sizeof(*ack), rx_size);
+ goto error_too_small;
+ }
+ if (rx_size > I2400M_BM_ACK_BUF_SIZE) {
+ dev_err(dev, "SW BUG? BM_ACK_BUF is too small (%u vs "
+ "%zu needed)\n", I2400M_BM_ACK_BUF_SIZE,
+ rx_size);
+ goto error_too_small;
+ }
+
+ /* Read it */
+ result = sdio_memcpy_fromio(func, i2400m->bm_ack_buf,
+ I2400MS_DATA_ADDR, rx_size);
+ if (result == -ETIMEDOUT || result == -ETIME)
+ continue;
+ if (result < 0) {
+ dev_err(dev, "BM SDIO receive (%zu B) failed: %d\n",
+ rx_size, result);
+ goto error_read;
+ } else
+ break;
+ }
+ rx_size = min((ssize_t)ack_size, rx_size);
+ memcpy(ack, i2400m->bm_ack_buf, rx_size);
+error_read:
+error_too_small:
+error_rx_get_size:
+error_timedout:
+ sdio_release_host(func);
+ d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %ld\n",
+ i2400m, ack, ack_size, (long) rx_size);
+ return rx_size;
+}
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c
new file mode 100644
index 000000000000..a3008b904f7d
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-rx.c
@@ -0,0 +1,255 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * SDIO RX handling
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Dirk Brandewie <dirk.j.brandewie@intel.com>
+ * - Initial implementation
+ *
+ *
+ * This handles the RX path on SDIO.
+ *
+ * The SDIO bus driver calls the "irq" routine when data is available.
+ * This is not a traditional interrupt routine since the SDIO bus
+ * driver calls us from its irq thread context. Because of this
+ * sleeping in the SDIO RX IRQ routine is okay.
+ *
+ * From there on, we obtain the size of the data that is available,
+ * allocate an skb, copy it and then pass it to the generic driver's
+ * RX routine [i2400m_rx()].
+ *
+ * ROADMAP
+ *
+ * i2400ms_irq()
+ * i2400ms_rx()
+ * __i2400ms_rx_get_size()
+ * i2400m_rx()
+ *
+ * i2400ms_rx_setup()
+ *
+ * i2400ms_rx_release()
+ */
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/skbuff.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#include "i2400m-sdio.h"
+
+#define D_SUBMODULE rx
+#include "sdio-debug-levels.h"
+
+
+/*
+ * Read and return the amount of bytes available for RX
+ *
+ * The RX size has to be read like this: byte reads of three
+ * sequential locations; then glue'em together.
+ *
+ * sdio_readl() doesn't work.
+ */
+ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms)
+{
+ int ret, cnt, val;
+ ssize_t rx_size;
+ unsigned xfer_size_addr;
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &i2400ms->func->dev;
+
+ d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
+ xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR;
+ rx_size = 0;
+ for (cnt = 0; cnt < 3; cnt++) {
+ val = sdio_readb(func, xfer_size_addr + cnt, &ret);
+ if (ret < 0) {
+ dev_err(dev, "RX: Can't read byte %d of RX size from "
+ "0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret);
+ rx_size = ret;
+ goto error_read;
+ }
+ rx_size = rx_size << 8 | (val & 0xff);
+ }
+ d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size);
+error_read:
+ d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size);
+ return rx_size;
+}
+
+
+/*
+ * Read data from the device (when in normal)
+ *
+ * Allocate an SKB of the right size, read the data in and then
+ * deliver it to the generic layer.
+ *
+ * We also check for a reboot barker. That means the device died and
+ * we have to reboot it.
+ */
+static
+void i2400ms_rx(struct i2400ms *i2400ms)
+{
+ int ret;
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+ struct i2400m *i2400m = &i2400ms->i2400m;
+ struct sk_buff *skb;
+ ssize_t rx_size;
+
+ d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms);
+ rx_size = __i2400ms_rx_get_size(i2400ms);
+ if (rx_size < 0) {
+ ret = rx_size;
+ goto error_get_size;
+ }
+ ret = -ENOMEM;
+ skb = alloc_skb(rx_size, GFP_ATOMIC);
+ if (NULL == skb) {
+ dev_err(dev, "RX: unable to alloc skb\n");
+ goto error_alloc_skb;
+ }
+
+ ret = sdio_memcpy_fromio(func, skb->data,
+ I2400MS_DATA_ADDR, rx_size);
+ if (ret < 0) {
+ dev_err(dev, "RX: SDIO data read failed: %d\n", ret);
+ goto error_memcpy_fromio;
+ }
+ /* Check if device has reset */
+ if (!memcmp(skb->data, i2400m_NBOOT_BARKER,
+ sizeof(i2400m_NBOOT_BARKER))
+ || !memcmp(skb->data, i2400m_SBOOT_BARKER,
+ sizeof(i2400m_SBOOT_BARKER))) {
+ ret = i2400m_dev_reset_handle(i2400m);
+ kfree_skb(skb);
+ } else {
+ skb_put(skb, rx_size);
+ i2400m_rx(i2400m, skb);
+ }
+ d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms);
+ return;
+
+error_memcpy_fromio:
+ kfree_skb(skb);
+error_alloc_skb:
+error_get_size:
+ d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret);
+ return;
+}
+
+
+/*
+ * Process an interrupt from the SDIO card
+ *
+ * FIXME: need to process other events that are not just ready-to-read
+ *
+ * Checks there is data ready and then proceeds to read it.
+ */
+static
+void i2400ms_irq(struct sdio_func *func)
+{
+ int ret;
+ struct i2400ms *i2400ms = sdio_get_drvdata(func);
+ struct i2400m *i2400m = &i2400ms->i2400m;
+ struct device *dev = &func->dev;
+ int val;
+
+ d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms);
+ val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret);
+ if (ret < 0) {
+ dev_err(dev, "RX: Can't read interrupt status: %d\n", ret);
+ goto error_no_irq;
+ }
+ if (!val) {
+ dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n");
+ goto error_no_irq;
+ }
+ sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret);
+ if (WARN_ON(i2400m->boot_mode != 0))
+ dev_err(dev, "RX: SW BUG? boot mode and IRQ is up?\n");
+ else
+ i2400ms_rx(i2400ms);
+error_no_irq:
+ d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms);
+ return;
+}
+
+
+/*
+ * Setup SDIO RX
+ *
+ * Hooks up the IRQ handler and then enables IRQs.
+ */
+int i2400ms_rx_setup(struct i2400ms *i2400ms)
+{
+ int result;
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+
+ d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
+ sdio_claim_host(func);
+ result = sdio_claim_irq(func, i2400ms_irq);
+ if (result < 0) {
+ dev_err(dev, "Cannot claim IRQ: %d\n", result);
+ goto error_irq_claim;
+ }
+ result = 0;
+ sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result);
+ if (result < 0) {
+ sdio_release_irq(func);
+ dev_err(dev, "Failed to enable interrupts %d\n", result);
+ }
+error_irq_claim:
+ sdio_release_host(func);
+ d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
+ return result;
+}
+
+
+/*
+ * Tear down SDIO RX
+ *
+ * Disables IRQs in the device and removes the IRQ handler.
+ */
+void i2400ms_rx_release(struct i2400ms *i2400ms)
+{
+ int result;
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+
+ d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
+ sdio_claim_host(func);
+ sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result);
+ sdio_release_irq(func);
+ sdio_release_host(func);
+ d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
+}
diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c
new file mode 100644
index 000000000000..5105a5ebc44f
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio-tx.c
@@ -0,0 +1,153 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * SDIO TX transaction backends
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Dirk Brandewie <dirk.j.brandewie@intel.com>
+ * - Initial implementation
+ *
+ *
+ * Takes the TX messages in the i2400m's driver TX FIFO and sends them
+ * to the device until there are no more.
+ *
+ * If we fail sending the message, we just drop it. There isn't much
+ * we can do at this point. Most of the traffic is network, which has
+ * recovery methods for dropped packets.
+ *
+ * The SDIO functions are not atomic, so we can't run from the context
+ * where i2400m->bus_tx_kick() [i2400ms_bus_tx_kick()] is being called
+ * (some times atomic). Thus, the actual TX work is deferred to a
+ * workqueue.
+ *
+ * ROADMAP
+ *
+ * i2400ms_bus_tx_kick()
+ * i2400ms_tx_submit() [through workqueue]
+ *
+ * i2400m_tx_setup()
+ *
+ * i2400m_tx_release()
+ */
+#include <linux/mmc/sdio_func.h>
+#include "i2400m-sdio.h"
+
+#define D_SUBMODULE tx
+#include "sdio-debug-levels.h"
+
+
+/*
+ * Pull TX transations from the TX FIFO and send them to the device
+ * until there are no more.
+ */
+static
+void i2400ms_tx_submit(struct work_struct *ws)
+{
+ int result;
+ struct i2400ms *i2400ms = container_of(ws, struct i2400ms, tx_worker);
+ struct i2400m *i2400m = &i2400ms->i2400m;
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+ struct i2400m_msg_hdr *tx_msg;
+ size_t tx_msg_size;
+
+ d_fnstart(4, dev, "(i2400ms %p, i2400m %p)\n", i2400ms, i2400ms);
+
+ while (NULL != (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) {
+ d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
+ d_dump(5, dev, tx_msg, tx_msg_size);
+
+ sdio_claim_host(func);
+ result = sdio_memcpy_toio(func, 0, tx_msg, tx_msg_size);
+ sdio_release_host(func);
+
+ i2400m_tx_msg_sent(i2400m);
+
+ if (result < 0) {
+ dev_err(dev, "TX: cannot submit TX; tx_msg @%zu %zu B:"
+ " %d\n", (void *) tx_msg - i2400m->tx_buf,
+ tx_msg_size, result);
+ }
+
+ d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size);
+ }
+
+ d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms);
+}
+
+
+/*
+ * The generic driver notifies us that there is data ready for TX
+ *
+ * Schedule a run of i2400ms_tx_submit() to handle it.
+ */
+void i2400ms_bus_tx_kick(struct i2400m *i2400m)
+{
+ struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
+ struct device *dev = &i2400ms->func->dev;
+
+ d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
+
+ /* schedule tx work, this is because tx may block, therefore
+ * it has to run in a thread context.
+ */
+ queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker);
+
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+}
+
+int i2400ms_tx_setup(struct i2400ms *i2400ms)
+{
+ int result;
+ struct device *dev = &i2400ms->func->dev;
+ struct i2400m *i2400m = &i2400ms->i2400m;
+
+ d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms);
+
+ INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit);
+ snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name),
+ "%s-tx", i2400m->wimax_dev.name);
+ i2400ms->tx_workqueue =
+ create_singlethread_workqueue(i2400ms->tx_wq_name);
+ if (NULL == i2400ms->tx_workqueue) {
+ dev_err(dev, "TX: failed to create workqueue\n");
+ result = -ENOMEM;
+ } else
+ result = 0;
+ d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result);
+ return result;
+}
+
+void i2400ms_tx_release(struct i2400ms *i2400ms)
+{
+ destroy_workqueue(i2400ms->tx_workqueue);
+}
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
new file mode 100644
index 000000000000..1bfa283bbd8a
--- /dev/null
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -0,0 +1,511 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Linux driver model glue for the SDIO device, reset & fw upload
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
+ * Dirk Brandewie <dirk.j.brandewie@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * See i2400m-sdio.h for a general description of this driver.
+ *
+ * This file implements driver model glue, and hook ups for the
+ * generic driver to implement the bus-specific functions (device
+ * communication setup/tear down, firmware upload and resetting).
+ *
+ * ROADMAP
+ *
+ * i2400m_probe()
+ * alloc_netdev()
+ * i2400ms_netdev_setup()
+ * i2400ms_init()
+ * i2400m_netdev_setup()
+ * i2400ms_enable_function()
+ * i2400m_setup()
+ *
+ * i2400m_remove()
+ * i2400m_release()
+ * free_netdev(net_dev)
+ *
+ * i2400ms_bus_reset() Called by i2400m->bus_reset
+ * __i2400ms_reset()
+ * __i2400ms_send_barker()
+ *
+ * i2400ms_bus_dev_start() Called by i2400m_dev_start() [who is
+ * i2400ms_tx_setup() called by i2400m_setup()]
+ * i2400ms_rx_setup()
+ *
+ * i2400ms_bus_dev_stop() Called by i2400m_dev_stop() [who is
+ * i2400ms_rx_release() is called by i2400m_release()]
+ * i2400ms_tx_release()
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#include "i2400m-sdio.h"
+#include <linux/wimax/i2400m.h>
+
+#define D_SUBMODULE main
+#include "sdio-debug-levels.h"
+
+/* IOE WiMAX function timeout in seconds */
+static int ioe_timeout = 2;
+module_param(ioe_timeout, int, 0);
+
+/* Our firmware file name */
+#define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-" I2400M_FW_VERSION ".sbcf"
+
+/*
+ * Enable the SDIO function
+ *
+ * Tries to enable the SDIO function; might fail if it is still not
+ * ready (in some hardware, the SDIO WiMAX function is only enabled
+ * when we ask it to explicitly doing). Tries until a timeout is
+ * reached.
+ *
+ * The reverse of this is...sdio_disable_function()
+ *
+ * Returns: 0 if the SDIO function was enabled, < 0 errno code on
+ * error (-ENODEV when it was unable to enable the function).
+ */
+static
+int i2400ms_enable_function(struct sdio_func *func)
+{
+ u64 timeout;
+ int err;
+ struct device *dev = &func->dev;
+
+ d_fnstart(3, dev, "(func %p)\n", func);
+ /* Setup timeout (FIXME: This needs to read the CIS table to
+ * get a real timeout) and then wait for the device to signal
+ * it is ready */
+ timeout = get_jiffies_64() + ioe_timeout * HZ;
+ err = -ENODEV;
+ while (err != 0 && time_before64(get_jiffies_64(), timeout)) {
+ sdio_claim_host(func);
+ err = sdio_enable_func(func);
+ if (0 == err) {
+ sdio_release_host(func);
+ d_printf(2, dev, "SDIO function enabled\n");
+ goto function_enabled;
+ }
+ d_printf(2, dev, "SDIO function failed to enable: %d\n", err);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+ msleep(I2400MS_INIT_SLEEP_INTERVAL);
+ }
+ /* If timed out, device is not there yet -- get -ENODEV so
+ * the device driver core will retry later on. */
+ if (err == -ETIME) {
+ dev_err(dev, "Can't enable WiMAX function; "
+ " has the function been enabled?\n");
+ err = -ENODEV;
+ }
+function_enabled:
+ d_fnend(3, dev, "(func %p) = %d\n", func, err);
+ return err;
+}
+
+
+/*
+ * Setup driver resources needed to communicate with the device
+ *
+ * The fw needs some time to settle, and it was just uploaded,
+ * so give it a break first. I'd prefer to just wait for the device to
+ * send something, but seems the poking we do to enable SDIO stuff
+ * interferes with it, so just give it a break before starting...
+ */
+static
+int i2400ms_bus_dev_start(struct i2400m *i2400m)
+{
+ int result;
+ struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ msleep(200);
+ result = i2400ms_rx_setup(i2400ms);
+ if (result < 0)
+ goto error_rx_setup;
+ result = i2400ms_tx_setup(i2400ms);
+ if (result < 0)
+ goto error_tx_setup;
+ d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
+ return result;
+
+ i2400ms_tx_release(i2400ms);
+error_tx_setup:
+ i2400ms_rx_release(i2400ms);
+error_rx_setup:
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+ return result;
+}
+
+
+static
+void i2400ms_bus_dev_stop(struct i2400m *i2400m)
+{
+ struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ i2400ms_rx_release(i2400ms);
+ i2400ms_tx_release(i2400ms);
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+}
+
+
+/*
+ * Sends a barker buffer to the device
+ *
+ * This helper will allocate a kmalloced buffer and use it to transmit
+ * (then free it). Reason for this is that the SDIO host controller
+ * expects alignment (unknown exactly which) which the stack won't
+ * really provide and certain arches/host-controller combinations
+ * cannot use stack/vmalloc/text areas for DMA transfers.
+ */
+static
+int __i2400ms_send_barker(struct i2400ms *i2400ms,
+ const __le32 *barker, size_t barker_size)
+{
+ int ret;
+ struct sdio_func *func = i2400ms->func;
+ struct device *dev = &func->dev;
+ void *buffer;
+
+ ret = -ENOMEM;
+ buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL);
+ if (buffer == NULL)
+ goto error_kzalloc;
+
+ memcpy(buffer, barker, barker_size);
+ sdio_claim_host(func);
+ ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE);
+ sdio_release_host(func);
+
+ if (ret < 0)
+ d_printf(0, dev, "E: barker error: %d\n", ret);
+
+ kfree(buffer);
+error_kzalloc:
+ return ret;
+}
+
+
+/*
+ * Reset a device at different levels (warm, cold or bus)
+ *
+ * @i2400ms: device descriptor
+ * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS)
+ *
+ * FIXME: not tested -- need to confirm expected effects
+ *
+ * Warm and cold resets get an SDIO reset if they fail (unimplemented)
+ *
+ * Warm reset:
+ *
+ * The device will be fully reset internally, but won't be
+ * disconnected from the USB bus (so no reenumeration will
+ * happen). Firmware upload will be neccessary.
+ *
+ * The device will send a reboot barker in the notification endpoint
+ * that will trigger the driver to reinitialize the state
+ * automatically from notif.c:i2400m_notification_grok() into
+ * i2400m_dev_bootstrap_delayed().
+ *
+ * Cold and bus (USB) reset:
+ *
+ * The device will be fully reset internally, disconnected from the
+ * USB bus an a reenumeration will happen. Firmware upload will be
+ * neccessary. Thus, we don't do any locking or struct
+ * reinitialization, as we are going to be fully disconnected and
+ * reenumerated.
+ *
+ * Note we need to return -ENODEV if a warm reset was requested and we
+ * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset()
+ * and wimax_dev->op_reset.
+ *
+ * WARNING: no driver state saved/fixed
+ */
+static
+int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
+{
+ int result;
+ struct i2400ms *i2400ms =
+ container_of(i2400m, struct i2400ms, i2400m);
+ struct device *dev = i2400m_dev(i2400m);
+ static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ };
+ static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ };
+
+ if (rt == I2400M_RT_WARM)
+ result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER,
+ sizeof(i2400m_WARM_BOOT_BARKER));
+ else if (rt == I2400M_RT_COLD)
+ result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER,
+ sizeof(i2400m_COLD_BOOT_BARKER));
+ else if (rt == I2400M_RT_BUS) {
+do_bus_reset:
+ dev_err(dev, "FIXME: SDIO bus reset not implemented\n");
+ result = rt == I2400M_RT_WARM ? -ENODEV : -ENOSYS;
+ } else
+ BUG();
+ if (result < 0 && rt != I2400M_RT_BUS) {
+ dev_err(dev, "%s reset failed (%d); trying SDIO reset\n",
+ rt == I2400M_RT_WARM ? "warm" : "cold", result);
+ rt = I2400M_RT_BUS;
+ goto do_bus_reset;
+ }
+ return result;
+}
+
+
+static
+void i2400ms_netdev_setup(struct net_device *net_dev)
+{
+ struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+ struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);
+ i2400ms_init(i2400ms);
+ i2400m_netdev_setup(net_dev);
+}
+
+
+/*
+ * Debug levels control; see debug.h
+ */
+struct d_level D_LEVEL[] = {
+ D_SUBMODULE_DEFINE(main),
+ D_SUBMODULE_DEFINE(tx),
+ D_SUBMODULE_DEFINE(rx),
+ D_SUBMODULE_DEFINE(fw),
+};
+size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
+
+
+#define __debugfs_register(prefix, name, parent) \
+do { \
+ result = d_level_register_debugfs(prefix, name, parent); \
+ if (result < 0) \
+ goto error; \
+} while (0)
+
+
+static
+int i2400ms_debugfs_add(struct i2400ms *i2400ms)
+{
+ int result;
+ struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry;
+
+ dentry = debugfs_create_dir("i2400m-usb", dentry);
+ result = PTR_ERR(dentry);
+ if (IS_ERR(dentry)) {
+ if (result == -ENODEV)
+ result = 0; /* No debugfs support */
+ goto error;
+ }
+ i2400ms->debugfs_dentry = dentry;
+ __debugfs_register("dl_", main, dentry);
+ __debugfs_register("dl_", tx, dentry);
+ __debugfs_register("dl_", rx, dentry);
+ __debugfs_register("dl_", fw, dentry);
+
+ return 0;
+
+error:
+ debugfs_remove_recursive(i2400ms->debugfs_dentry);
+ return result;
+}
+
+
+/*
+ * Probe a i2400m interface and register it
+ *
+ * @func: SDIO function
+ * @id: SDIO device ID
+ * @returns: 0 if ok, < 0 errno code on error.
+ *
+ * Alloc a net device, initialize the bus-specific details and then
+ * calls the bus-generic initialization routine. That will register
+ * the wimax and netdev devices, upload the firmware [using
+ * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
+ * communication with the device and then will start to talk to it to
+ * finnish setting it up.
+ *
+ * Initialization is tricky; some instances of the hw are packed with
+ * others in a way that requires a third driver that enables the WiMAX
+ * function. In those cases, we can't enable the SDIO function and
+ * we'll return with -ENODEV. When the driver that enables the WiMAX
+ * function does its thing, it has to do a bus_rescan_devices() on the
+ * SDIO bus so this driver is called again to enumerate the WiMAX
+ * function.
+ */
+static
+int i2400ms_probe(struct sdio_func *func,
+ const struct sdio_device_id *id)
+{
+ int result;
+ struct net_device *net_dev;
+ struct device *dev = &func->dev;
+ struct i2400m *i2400m;
+ struct i2400ms *i2400ms;
+
+ /* Allocate instance [calls i2400m_netdev_setup() on it]. */
+ result = -ENOMEM;
+ net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d",
+ i2400ms_netdev_setup);
+ if (net_dev == NULL) {
+ dev_err(dev, "no memory for network device instance\n");
+ goto error_alloc_netdev;
+ }
+ SET_NETDEV_DEV(net_dev, dev);
+ i2400m = net_dev_to_i2400m(net_dev);
+ i2400ms = container_of(i2400m, struct i2400ms, i2400m);
+ i2400m->wimax_dev.net_dev = net_dev;
+ i2400ms->func = func;
+ sdio_set_drvdata(func, i2400ms);
+
+ i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
+ i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
+ i2400m->bus_dev_start = i2400ms_bus_dev_start;
+ i2400m->bus_dev_stop = i2400ms_bus_dev_stop;
+ i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
+ i2400m->bus_reset = i2400ms_bus_reset;
+ i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
+ i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
+ i2400m->bus_fw_name = I2400MS_FW_FILE_NAME;
+ i2400m->bus_bm_mac_addr_impaired = 1;
+
+ result = i2400ms_enable_function(i2400ms->func);
+ if (result < 0) {
+ dev_err(dev, "Cannot enable SDIO function: %d\n", result);
+ goto error_func_enable;
+ }
+
+ sdio_claim_host(func);
+ result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
+ if (result < 0) {
+ dev_err(dev, "Failed to set block size: %d\n", result);
+ goto error_set_blk_size;
+ }
+ sdio_release_host(func);
+
+ result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
+ if (result < 0) {
+ dev_err(dev, "cannot setup device: %d\n", result);
+ goto error_setup;
+ }
+
+ result = i2400ms_debugfs_add(i2400ms);
+ if (result < 0) {
+ dev_err(dev, "cannot create SDIO debugfs: %d\n",
+ result);
+ goto error_debugfs_add;
+ }
+ return 0;
+
+error_debugfs_add:
+ i2400m_release(i2400m);
+error_setup:
+ sdio_set_drvdata(func, NULL);
+ sdio_claim_host(func);
+error_set_blk_size:
+ sdio_disable_func(func);
+ sdio_release_host(func);
+error_func_enable:
+ free_netdev(net_dev);
+error_alloc_netdev:
+ return result;
+}
+
+
+static
+void i2400ms_remove(struct sdio_func *func)
+{
+ struct device *dev = &func->dev;
+ struct i2400ms *i2400ms = sdio_get_drvdata(func);
+ struct i2400m *i2400m = &i2400ms->i2400m;
+ struct net_device *net_dev = i2400m->wimax_dev.net_dev;
+
+ d_fnstart(3, dev, "SDIO func %p\n", func);
+ debugfs_remove_recursive(i2400ms->debugfs_dentry);
+ i2400m_release(i2400m);
+ sdio_set_drvdata(func, NULL);
+ sdio_claim_host(func);
+ sdio_disable_func(func);
+ sdio_release_host(func);
+ free_netdev(net_dev);
+ d_fnend(3, dev, "SDIO func %p\n", func);
+}
+
+enum {
+ I2400MS_INTEL_VID = 0x89,
+};
+
+static
+const struct sdio_device_id i2400ms_sdio_ids[] = {
+ /* Intel: i2400m WiMAX over SDIO */
+ { SDIO_DEVICE(I2400MS_INTEL_VID, 0x1402) },
+ { }, /* end: all zeroes */
+};
+MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids);
+
+
+static
+struct sdio_driver i2400m_sdio_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = i2400ms_probe,
+ .remove = i2400ms_remove,
+ .id_table = i2400ms_sdio_ids,
+};
+
+
+static
+int __init i2400ms_driver_init(void)
+{
+ return sdio_register_driver(&i2400m_sdio_driver);
+}
+module_init(i2400ms_driver_init);
+
+
+static
+void __exit i2400ms_driver_exit(void)
+{
+ flush_scheduled_work(); /* for the stuff we schedule */
+ sdio_unregister_driver(&i2400m_sdio_driver);
+}
+module_exit(i2400ms_driver_exit);
+
+
+MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
+MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(I2400MS_FW_FILE_NAME);
diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c
new file mode 100644
index 000000000000..613a88ffd651
--- /dev/null
+++ b/drivers/net/wimax/i2400m/tx.c
@@ -0,0 +1,817 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Generic (non-bus specific) TX handling
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * - Initial implementation
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Rewritten to use a single FIFO to lower the memory allocation
+ * pressure and optimize cache hits when copying to the queue, as
+ * well as splitting out bus-specific code.
+ *
+ *
+ * Implements data transmission to the device; this is done through a
+ * software FIFO, as data/control frames can be coalesced (while the
+ * device is reading the previous tx transaction, others accumulate).
+ *
+ * A FIFO is used because at the end it is resource-cheaper that trying
+ * to implement scatter/gather over USB. As well, most traffic is going
+ * to be download (vs upload).
+ *
+ * The format for sending/receiving data to/from the i2400m is
+ * described in detail in rx.c:PROTOCOL FORMAT. In here we implement
+ * the transmission of that. This is split between a bus-independent
+ * part that just prepares everything and a bus-specific part that
+ * does the actual transmission over the bus to the device (in the
+ * bus-specific driver).
+ *
+ *
+ * The general format of a device-host transaction is MSG-HDR, PLD1,
+ * PLD2...PLDN, PL1, PL2,...PLN, PADDING.
+ *
+ * Because we need the send payload descriptors and then payloads and
+ * because it is kind of expensive to do scatterlists in USB (one URB
+ * per node), it becomes cheaper to append all the data to a FIFO
+ * (copying to a FIFO potentially in cache is cheaper).
+ *
+ * Then the bus-specific code takes the parts of that FIFO that are
+ * written and passes them to the device.
+ *
+ * So the concepts to keep in mind there are:
+ *
+ * We use a FIFO to queue the data in a linear buffer. We first append
+ * a MSG-HDR, space for I2400M_TX_PLD_MAX payload descriptors and then
+ * go appending payloads until we run out of space or of payload
+ * descriptors. Then we append padding to make the whole transaction a
+ * multiple of i2400m->bus_tx_block_size (as defined by the bus layer).
+ *
+ * - A TX message: a combination of a message header, payload
+ * descriptors and payloads.
+ *
+ * Open: it is marked as active (i2400m->tx_msg is valid) and we
+ * can keep adding payloads to it.
+ *
+ * Closed: we are not appending more payloads to this TX message
+ * (exahusted space in the queue, too many payloads or
+ * whichever). We have appended padding so the whole message
+ * length is aligned to i2400m->bus_tx_block_size (as set by the
+ * bus/transport layer).
+ *
+ * - Most of the time we keep a TX message open to which we append
+ * payloads.
+ *
+ * - If we are going to append and there is no more space (we are at
+ * the end of the FIFO), we close the message, mark the rest of the
+ * FIFO space unusable (skip_tail), create a new message at the
+ * beginning of the FIFO (if there is space) and append the message
+ * there.
+ *
+ * This is because we need to give linear TX messages to the bus
+ * engine. So we don't write a message to the remaining FIFO space
+ * until the tail and continue at the head of it.
+ *
+ * - We overload one of the fields in the message header to use it as
+ * 'size' of the TX message, so we can iterate over them. It also
+ * contains a flag that indicates if we have to skip it or not.
+ * When we send the buffer, we update that to its real on-the-wire
+ * value.
+ *
+ * - The MSG-HDR PLD1...PLD2 stuff has to be a size multiple of 16.
+ *
+ * It follows that if MSG-HDR says we have N messages, the whole
+ * header + descriptors is 16 + 4*N; for those to be a multiple of
+ * 16, it follows that N can be 4, 8, 12, ... (32, 48, 64, 80...
+ * bytes).
+ *
+ * So if we have only 1 payload, we have to submit a header that in
+ * all truth has space for 4.
+ *
+ * The implication is that we reserve space for 12 (64 bytes); but
+ * if we fill up only (eg) 2, our header becomes 32 bytes only. So
+ * the TX engine has to shift those 32 bytes of msg header and 2
+ * payloads and padding so that right after it the payloads start
+ * and the TX engine has to know about that.
+ *
+ * It is cheaper to move the header up than the whole payloads down.
+ *
+ * We do this in i2400m_tx_close(). See 'i2400m_msg_hdr->offset'.
+ *
+ * - Each payload has to be size-padded to 16 bytes; before appending
+ * it, we just do it.
+ *
+ * - The whole message has to be padded to i2400m->bus_tx_block_size;
+ * we do this at close time. Thus, when reserving space for the
+ * payload, we always make sure there is also free space for this
+ * padding that sooner or later will happen.
+ *
+ * When we append a message, we tell the bus specific code to kick in
+ * TXs. It will TX (in parallel) until the buffer is exhausted--hence
+ * the lockin we do. The TX code will only send a TX message at the
+ * time (which remember, might contain more than one payload). Of
+ * course, when the bus-specific driver attempts to TX a message that
+ * is still open, it gets closed first.
+ *
+ * Gee, this is messy; well a picture. In the example below we have a
+ * partially full FIFO, with a closed message ready to be delivered
+ * (with a moved message header to make sure it is size-aligned to
+ * 16), TAIL room that was unusable (and thus is marked with a message
+ * header that says 'skip this') and at the head of the buffer, an
+ * imcomplete message with a couple of payloads.
+ *
+ * N ___________________________________________________
+ * | |
+ * | TAIL room |
+ * | |
+ * | msg_hdr to skip (size |= 0x80000) |
+ * |---------------------------------------------------|-------
+ * | | /|\
+ * | | |
+ * | TX message padding | |
+ * | | |
+ * | | |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - -| |
+ * | | |
+ * | payload 1 | |
+ * | | N * tx_block_size
+ * | | |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - -| |
+ * | | |
+ * | payload 1 | |
+ * | | |
+ * | | |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - -|- -|- - - -
+ * | padding 3 /|\ | | /|\
+ * | padding 2 | | | |
+ * | pld 1 32 bytes (2 * 16) | | |
+ * | pld 0 | | | |
+ * | moved msg_hdr \|/ | \|/ |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - -|- - - |
+ * | | _PLD_SIZE
+ * | unused | |
+ * | | |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - -| |
+ * | msg_hdr (size X) [this message is closed] | \|/
+ * |===================================================|========== <=== OUT
+ * | |
+ * | |
+ * | |
+ * | Free rooom |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * |===================================================|========== <=== IN
+ * | |
+ * | |
+ * | |
+ * | |
+ * | payload 1 |
+ * | |
+ * | |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - -|
+ * | |
+ * | payload 0 |
+ * | |
+ * | |
+ * |- - - - - - - - - - - - - - - - - - - - - - - - - -|
+ * | pld 11 /|\ |
+ * | ... | |
+ * | pld 1 64 bytes (2 * 16) |
+ * | pld 0 | |
+ * | msg_hdr (size X) \|/ [message is open] |
+ * 0 ---------------------------------------------------
+ *
+ *
+ * ROADMAP
+ *
+ * i2400m_tx_setup() Called by i2400m_setup
+ * i2400m_tx_release() Called by i2400m_release()
+ *
+ * i2400m_tx() Called to send data or control frames
+ * i2400m_tx_fifo_push() Allocates append-space in the FIFO
+ * i2400m_tx_new() Opens a new message in the FIFO
+ * i2400m_tx_fits() Checks if a new payload fits in the message
+ * i2400m_tx_close() Closes an open message in the FIFO
+ * i2400m_tx_skip_tail() Marks unusable FIFO tail space
+ * i2400m->bus_tx_kick()
+ *
+ * Now i2400m->bus_tx_kick() is the the bus-specific driver backend
+ * implementation; that would do:
+ *
+ * i2400m->bus_tx_kick()
+ * i2400m_tx_msg_get() Gets first message ready to go
+ * ...sends it...
+ * i2400m_tx_msg_sent() Ack the message is sent; repeat from
+ * _tx_msg_get() until it returns NULL
+ * (FIFO empty).
+ */
+#include <linux/netdevice.h>
+#include "i2400m.h"
+
+
+#define D_SUBMODULE tx
+#include "debug-levels.h"
+
+enum {
+ /**
+ * TX Buffer size
+ *
+ * Doc says maximum transaction is 16KiB. If we had 16KiB en
+ * route and 16KiB being queued, it boils down to needing
+ * 32KiB.
+ */
+ I2400M_TX_BUF_SIZE = 32768,
+ /**
+ * Message header and payload descriptors have to be 16
+ * aligned (16 + 4 * N = 16 * M). If we take that average sent
+ * packets are MTU size (~1400-~1500) it follows that we could
+ * fit at most 10-11 payloads in one transaction. To meet the
+ * alignment requirement, that means we need to leave space
+ * for 12 (64 bytes). To simplify, we leave space for that. If
+ * at the end there are less, we pad up to the nearest
+ * multiple of 16.
+ */
+ I2400M_TX_PLD_MAX = 12,
+ I2400M_TX_PLD_SIZE = sizeof(struct i2400m_msg_hdr)
+ + I2400M_TX_PLD_MAX * sizeof(struct i2400m_pld),
+ I2400M_TX_SKIP = 0x80000000,
+};
+
+#define TAIL_FULL ((void *)~(unsigned long)NULL)
+
+/*
+ * Allocate @size bytes in the TX fifo, return a pointer to it
+ *
+ * @i2400m: device descriptor
+ * @size: size of the buffer we need to allocate
+ * @padding: ensure that there is at least this many bytes of free
+ * contiguous space in the fifo. This is needed because later on
+ * we might need to add padding.
+ *
+ * Returns:
+ *
+ * Pointer to the allocated space. NULL if there is no
+ * space. TAIL_FULL if there is no space at the tail but there is at
+ * the head (Case B below).
+ *
+ * These are the two basic cases we need to keep an eye for -- it is
+ * much better explained in linux/kernel/kfifo.c, but this code
+ * basically does the same. No rocket science here.
+ *
+ * Case A Case B
+ * N ___________ ___________
+ * | tail room | | data |
+ * | | | |
+ * |<- IN ->| |<- OUT ->|
+ * | | | |
+ * | data | | room |
+ * | | | |
+ * |<- OUT ->| |<- IN ->|
+ * | | | |
+ * | head room | | data |
+ * 0 ----------- -----------
+ *
+ * We allocate only *contiguous* space.
+ *
+ * We can allocate only from 'room'. In Case B, it is simple; in case
+ * A, we only try from the tail room; if it is not enough, we just
+ * fail and return TAIL_FULL and let the caller figure out if we wants to
+ * skip the tail room and try to allocate from the head.
+ *
+ * Note:
+ *
+ * Assumes i2400m->tx_lock is taken, and we use that as a barrier
+ *
+ * The indexes keep increasing and we reset them to zero when we
+ * pop data off the queue
+ */
+static
+void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size, size_t padding)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ size_t room, tail_room, needed_size;
+ void *ptr;
+
+ needed_size = size + padding;
+ room = I2400M_TX_BUF_SIZE - (i2400m->tx_in - i2400m->tx_out);
+ if (room < needed_size) { /* this takes care of Case B */
+ d_printf(2, dev, "fifo push %zu/%zu: no space\n",
+ size, padding);
+ return NULL;
+ }
+ /* Is there space at the tail? */
+ tail_room = I2400M_TX_BUF_SIZE - i2400m->tx_in % I2400M_TX_BUF_SIZE;
+ if (tail_room < needed_size) {
+ if (i2400m->tx_out % I2400M_TX_BUF_SIZE
+ < i2400m->tx_in % I2400M_TX_BUF_SIZE) {
+ d_printf(2, dev, "fifo push %zu/%zu: tail full\n",
+ size, padding);
+ return TAIL_FULL; /* There might be head space */
+ } else {
+ d_printf(2, dev, "fifo push %zu/%zu: no head space\n",
+ size, padding);
+ return NULL; /* There is no space */
+ }
+ }
+ ptr = i2400m->tx_buf + i2400m->tx_in % I2400M_TX_BUF_SIZE;
+ d_printf(2, dev, "fifo push %zu/%zu: at @%zu\n", size, padding,
+ i2400m->tx_in % I2400M_TX_BUF_SIZE);
+ i2400m->tx_in += size;
+ return ptr;
+}
+
+
+/*
+ * Mark the tail of the FIFO buffer as 'to-skip'
+ *
+ * We should never hit the BUG_ON() because all the sizes we push to
+ * the FIFO are padded to be a multiple of 16 -- the size of *msg
+ * (I2400M_PL_PAD for the payloads, I2400M_TX_PLD_SIZE for the
+ * header).
+ *
+ * Note:
+ *
+ * Assumes i2400m->tx_lock is taken, and we use that as a barrier
+ */
+static
+void i2400m_tx_skip_tail(struct i2400m *i2400m)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ size_t tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE;
+ size_t tail_room = I2400M_TX_BUF_SIZE - tx_in;
+ struct i2400m_msg_hdr *msg = i2400m->tx_buf + tx_in;
+ BUG_ON(tail_room < sizeof(*msg));
+ msg->size = tail_room | I2400M_TX_SKIP;
+ d_printf(2, dev, "skip tail: skipping %zu bytes @%zu\n",
+ tail_room, tx_in);
+ i2400m->tx_in += tail_room;
+}
+
+
+/*
+ * Check if a skb will fit in the TX queue's current active TX
+ * message (if there are still descriptors left unused).
+ *
+ * Returns:
+ * 0 if the message won't fit, 1 if it will.
+ *
+ * Note:
+ *
+ * Assumes a TX message is active (i2400m->tx_msg).
+ *
+ * Assumes i2400m->tx_lock is taken, and we use that as a barrier
+ */
+static
+unsigned i2400m_tx_fits(struct i2400m *i2400m)
+{
+ struct i2400m_msg_hdr *msg_hdr = i2400m->tx_msg;
+ return le16_to_cpu(msg_hdr->num_pls) < I2400M_TX_PLD_MAX;
+
+}
+
+
+/*
+ * Start a new TX message header in the queue.
+ *
+ * Reserve memory from the base FIFO engine and then just initialize
+ * the message header.
+ *
+ * We allocate the biggest TX message header we might need (one that'd
+ * fit I2400M_TX_PLD_MAX payloads) -- when it is closed it will be
+ * 'ironed it out' and the unneeded parts removed.
+ *
+ * NOTE:
+ *
+ * Assumes that the previous message is CLOSED (eg: either
+ * there was none or 'i2400m_tx_close()' was called on it).
+ *
+ * Assumes i2400m->tx_lock is taken, and we use that as a barrier
+ */
+static
+void i2400m_tx_new(struct i2400m *i2400m)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400m_msg_hdr *tx_msg;
+ BUG_ON(i2400m->tx_msg != NULL);
+try_head:
+ tx_msg = i2400m_tx_fifo_push(i2400m, I2400M_TX_PLD_SIZE, 0);
+ if (tx_msg == NULL)
+ goto out;
+ else if (tx_msg == TAIL_FULL) {
+ i2400m_tx_skip_tail(i2400m);
+ d_printf(2, dev, "new TX message: tail full, trying head\n");
+ goto try_head;
+ }
+ memset(tx_msg, 0, I2400M_TX_PLD_SIZE);
+ tx_msg->size = I2400M_TX_PLD_SIZE;
+out:
+ i2400m->tx_msg = tx_msg;
+ d_printf(2, dev, "new TX message: %p @%zu\n",
+ tx_msg, (void *) tx_msg - i2400m->tx_buf);
+}
+
+
+/*
+ * Finalize the current TX message header
+ *
+ * Sets the message header to be at the proper location depending on
+ * how many descriptors we have (check documentation at the file's
+ * header for more info on that).
+ *
+ * Appends padding bytes to make sure the whole TX message (counting
+ * from the 'relocated' message header) is aligned to
+ * tx_block_size. We assume the _append() code has left enough space
+ * in the FIFO for that. If there are no payloads, just pass, as it
+ * won't be transferred.
+ *
+ * The amount of padding bytes depends on how many payloads are in the
+ * TX message, as the "msg header and payload descriptors" will be
+ * shifted up in the buffer.
+ */
+static
+void i2400m_tx_close(struct i2400m *i2400m)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg;
+ struct i2400m_msg_hdr *tx_msg_moved;
+ size_t aligned_size, padding, hdr_size;
+ void *pad_buf;
+
+ if (tx_msg->size & I2400M_TX_SKIP) /* a skipper? nothing to do */
+ goto out;
+
+ /* Relocate the message header
+ *
+ * Find the current header size, align it to 16 and if we need
+ * to move it so the tail is next to the payloads, move it and
+ * set the offset.
+ *
+ * If it moved, this header is good only for transmission; the
+ * original one (it is kept if we moved) is still used to
+ * figure out where the next TX message starts (and where the
+ * offset to the moved header is).
+ */
+ hdr_size = sizeof(*tx_msg)
+ + le16_to_cpu(tx_msg->num_pls) * sizeof(tx_msg->pld[0]);
+ hdr_size = ALIGN(hdr_size, I2400M_PL_PAD);
+ tx_msg->offset = I2400M_TX_PLD_SIZE - hdr_size;
+ tx_msg_moved = (void *) tx_msg + tx_msg->offset;
+ memmove(tx_msg_moved, tx_msg, hdr_size);
+ tx_msg_moved->size -= tx_msg->offset;
+ /*
+ * Now figure out how much we have to add to the (moved!)
+ * message so the size is a multiple of i2400m->bus_tx_block_size.
+ */
+ aligned_size = ALIGN(tx_msg_moved->size, i2400m->bus_tx_block_size);
+ padding = aligned_size - tx_msg_moved->size;
+ if (padding > 0) {
+ pad_buf = i2400m_tx_fifo_push(i2400m, padding, 0);
+ if (unlikely(WARN_ON(pad_buf == NULL
+ || pad_buf == TAIL_FULL))) {
+ /* This should not happen -- append should verify
+ * there is always space left at least to append
+ * tx_block_size */
+ dev_err(dev,
+ "SW BUG! Possible data leakage from memory the "
+ "device should not read for padding - "
+ "size %lu aligned_size %zu tx_buf %p in "
+ "%zu out %zu\n",
+ (unsigned long) tx_msg_moved->size,
+ aligned_size, i2400m->tx_buf, i2400m->tx_in,
+ i2400m->tx_out);
+ } else
+ memset(pad_buf, 0xad, padding);
+ }
+ tx_msg_moved->padding = cpu_to_le16(padding);
+ tx_msg_moved->size += padding;
+ if (tx_msg != tx_msg_moved)
+ tx_msg->size += padding;
+out:
+ i2400m->tx_msg = NULL;
+}
+
+
+/**
+ * i2400m_tx - send the data in a buffer to the device
+ *
+ * @buf: pointer to the buffer to transmit
+ *
+ * @buf_len: buffer size
+ *
+ * @pl_type: type of the payload we are sending.
+ *
+ * Returns:
+ * 0 if ok, < 0 errno code on error (-ENOSPC, if there is no more
+ * room for the message in the queue).
+ *
+ * Appends the buffer to the TX FIFO and notifies the bus-specific
+ * part of the driver that there is new data ready to transmit.
+ * Once this function returns, the buffer has been copied, so it can
+ * be reused.
+ *
+ * The steps followed to append are explained in detail in the file
+ * header.
+ *
+ * Whenever we write to a message, we increase msg->size, so it
+ * reflects exactly how big the message is. This is needed so that if
+ * we concatenate two messages before they can be sent, the code that
+ * sends the messages can find the boundaries (and it will replace the
+ * size with the real barker before sending).
+ *
+ * Note:
+ *
+ * Cold and warm reset payloads need to be sent as a single
+ * payload, so we handle that.
+ */
+int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len,
+ enum i2400m_pt pl_type)
+{
+ int result = -ENOSPC;
+ struct device *dev = i2400m_dev(i2400m);
+ unsigned long flags;
+ size_t padded_len;
+ void *ptr;
+ unsigned is_singleton = pl_type == I2400M_PT_RESET_WARM
+ || pl_type == I2400M_PT_RESET_COLD;
+
+ d_fnstart(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u)\n",
+ i2400m, buf, buf_len, pl_type);
+ padded_len = ALIGN(buf_len, I2400M_PL_PAD);
+ d_printf(5, dev, "padded_len %zd buf_len %zd\n", padded_len, buf_len);
+ /* If there is no current TX message, create one; if the
+ * current one is out of payload slots or we have a singleton,
+ * close it and start a new one */
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+try_new:
+ if (unlikely(i2400m->tx_msg == NULL))
+ i2400m_tx_new(i2400m);
+ else if (unlikely(!i2400m_tx_fits(i2400m)
+ || (is_singleton && i2400m->tx_msg->num_pls != 0))) {
+ d_printf(2, dev, "closing TX message (fits %u singleton "
+ "%u num_pls %u)\n", i2400m_tx_fits(i2400m),
+ is_singleton, i2400m->tx_msg->num_pls);
+ i2400m_tx_close(i2400m);
+ i2400m_tx_new(i2400m);
+ }
+ if (i2400m->tx_msg->size + padded_len > I2400M_TX_BUF_SIZE / 2) {
+ d_printf(2, dev, "TX: message too big, going new\n");
+ i2400m_tx_close(i2400m);
+ i2400m_tx_new(i2400m);
+ }
+ if (i2400m->tx_msg == NULL)
+ goto error_tx_new;
+ /* So we have a current message header; now append space for
+ * the message -- if there is not enough, try the head */
+ ptr = i2400m_tx_fifo_push(i2400m, padded_len,
+ i2400m->bus_tx_block_size);
+ if (ptr == TAIL_FULL) { /* Tail is full, try head */
+ d_printf(2, dev, "pl append: tail full\n");
+ i2400m_tx_close(i2400m);
+ i2400m_tx_skip_tail(i2400m);
+ goto try_new;
+ } else if (ptr == NULL) { /* All full */
+ result = -ENOSPC;
+ d_printf(2, dev, "pl append: all full\n");
+ } else { /* Got space, copy it, set padding */
+ struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg;
+ unsigned num_pls = le16_to_cpu(tx_msg->num_pls);
+ memcpy(ptr, buf, buf_len);
+ memset(ptr + buf_len, 0xad, padded_len - buf_len);
+ i2400m_pld_set(&tx_msg->pld[num_pls], buf_len, pl_type);
+ d_printf(3, dev, "pld 0x%08x (type 0x%1x len 0x%04zx\n",
+ le32_to_cpu(tx_msg->pld[num_pls].val),
+ pl_type, buf_len);
+ tx_msg->num_pls = le16_to_cpu(num_pls+1);
+ tx_msg->size += padded_len;
+ d_printf(2, dev, "TX: appended %zu b (up to %u b) pl #%u \n",
+ padded_len, tx_msg->size, num_pls+1);
+ d_printf(2, dev,
+ "TX: appended hdr @%zu %zu b pl #%u @%zu %zu/%zu b\n",
+ (void *)tx_msg - i2400m->tx_buf, (size_t)tx_msg->size,
+ num_pls+1, ptr - i2400m->tx_buf, buf_len, padded_len);
+ result = 0;
+ if (is_singleton)
+ i2400m_tx_close(i2400m);
+ }
+error_tx_new:
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+ i2400m->bus_tx_kick(i2400m); /* always kick, might free up space */
+ d_fnend(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u) = %d\n",
+ i2400m, buf, buf_len, pl_type, result);
+ return result;
+}
+EXPORT_SYMBOL_GPL(i2400m_tx);
+
+
+/**
+ * i2400m_tx_msg_get - Get the first TX message in the FIFO to start sending it
+ *
+ * @i2400m: device descriptors
+ * @bus_size: where to place the size of the TX message
+ *
+ * Called by the bus-specific driver to get the first TX message at
+ * the FIF that is ready for transmission.
+ *
+ * It sets the state in @i2400m to indicate the bus-specific driver is
+ * transfering that message (i2400m->tx_msg_size).
+ *
+ * Once the transfer is completed, call i2400m_tx_msg_sent().
+ *
+ * Notes:
+ *
+ * The size of the TX message to be transmitted might be smaller than
+ * that of the TX message in the FIFO (in case the header was
+ * shorter). Hence, we copy it in @bus_size, for the bus layer to
+ * use. We keep the message's size in i2400m->tx_msg_size so that
+ * when the bus later is done transferring we know how much to
+ * advance the fifo.
+ *
+ * We collect statistics here as all the data is available and we
+ * assume it is going to work [see i2400m_tx_msg_sent()].
+ */
+struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *i2400m,
+ size_t *bus_size)
+{
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400m_msg_hdr *tx_msg, *tx_msg_moved;
+ unsigned long flags, pls;
+
+ d_fnstart(3, dev, "(i2400m %p bus_size %p)\n", i2400m, bus_size);
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+skip:
+ tx_msg_moved = NULL;
+ if (i2400m->tx_in == i2400m->tx_out) { /* Empty FIFO? */
+ i2400m->tx_in = 0;
+ i2400m->tx_out = 0;
+ d_printf(2, dev, "TX: FIFO empty: resetting\n");
+ goto out_unlock;
+ }
+ tx_msg = i2400m->tx_buf + i2400m->tx_out % I2400M_TX_BUF_SIZE;
+ if (tx_msg->size & I2400M_TX_SKIP) { /* skip? */
+ d_printf(2, dev, "TX: skip: msg @%zu (%zu b)\n",
+ i2400m->tx_out % I2400M_TX_BUF_SIZE,
+ (size_t) tx_msg->size & ~I2400M_TX_SKIP);
+ i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP;
+ goto skip;
+ }
+
+ if (tx_msg->num_pls == 0) { /* No payloads? */
+ if (tx_msg == i2400m->tx_msg) { /* open, we are done */
+ d_printf(2, dev,
+ "TX: FIFO empty: open msg w/o payloads @%zu\n",
+ (void *) tx_msg - i2400m->tx_buf);
+ tx_msg = NULL;
+ goto out_unlock;
+ } else { /* closed, skip it */
+ d_printf(2, dev,
+ "TX: skip msg w/o payloads @%zu (%zu b)\n",
+ (void *) tx_msg - i2400m->tx_buf,
+ (size_t) tx_msg->size);
+ i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP;
+ goto skip;
+ }
+ }
+ if (tx_msg == i2400m->tx_msg) /* open msg? */
+ i2400m_tx_close(i2400m);
+
+ /* Now we have a valid TX message (with payloads) to TX */
+ tx_msg_moved = (void *) tx_msg + tx_msg->offset;
+ i2400m->tx_msg_size = tx_msg->size;
+ *bus_size = tx_msg_moved->size;
+ d_printf(2, dev, "TX: pid %d msg hdr at @%zu offset +@%zu "
+ "size %zu bus_size %zu\n",
+ current->pid, (void *) tx_msg - i2400m->tx_buf,
+ (size_t) tx_msg->offset, (size_t) tx_msg->size,
+ (size_t) tx_msg_moved->size);
+ tx_msg_moved->barker = le32_to_cpu(I2400M_H2D_PREVIEW_BARKER);
+ tx_msg_moved->sequence = le32_to_cpu(i2400m->tx_sequence++);
+
+ pls = le32_to_cpu(tx_msg_moved->num_pls);
+ i2400m->tx_pl_num += pls; /* Update stats */
+ if (pls > i2400m->tx_pl_max)
+ i2400m->tx_pl_max = pls;
+ if (pls < i2400m->tx_pl_min)
+ i2400m->tx_pl_min = pls;
+ i2400m->tx_num++;
+ i2400m->tx_size_acc += *bus_size;
+ if (*bus_size < i2400m->tx_size_min)
+ i2400m->tx_size_min = *bus_size;
+ if (*bus_size > i2400m->tx_size_max)
+ i2400m->tx_size_max = *bus_size;
+out_unlock:
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+ d_fnstart(3, dev, "(i2400m %p bus_size %p [%zu]) = %p\n",
+ i2400m, bus_size, *bus_size, tx_msg_moved);
+ return tx_msg_moved;
+}
+EXPORT_SYMBOL_GPL(i2400m_tx_msg_get);
+
+
+/**
+ * i2400m_tx_msg_sent - indicate the transmission of a TX message
+ *
+ * @i2400m: device descriptor
+ *
+ * Called by the bus-specific driver when a message has been sent;
+ * this pops it from the FIFO; and as there is space, start the queue
+ * in case it was stopped.
+ *
+ * Should be called even if the message send failed and we are
+ * dropping this TX message.
+ */
+void i2400m_tx_msg_sent(struct i2400m *i2400m)
+{
+ unsigned n;
+ unsigned long flags;
+ struct device *dev = i2400m_dev(i2400m);
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ spin_lock_irqsave(&i2400m->tx_lock, flags);
+ i2400m->tx_out += i2400m->tx_msg_size;
+ d_printf(2, dev, "TX: sent %zu b\n", (size_t) i2400m->tx_msg_size);
+ i2400m->tx_msg_size = 0;
+ BUG_ON(i2400m->tx_out > i2400m->tx_in);
+ /* level them FIFO markers off */
+ n = i2400m->tx_out / I2400M_TX_BUF_SIZE;
+ i2400m->tx_out %= I2400M_TX_BUF_SIZE;
+ i2400m->tx_in -= n * I2400M_TX_BUF_SIZE;
+ netif_start_queue(i2400m->wimax_dev.net_dev);
+ spin_unlock_irqrestore(&i2400m->tx_lock, flags);
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+}
+EXPORT_SYMBOL_GPL(i2400m_tx_msg_sent);
+
+
+/**
+ * i2400m_tx_setup - Initialize the TX queue and infrastructure
+ *
+ * Make sure we reset the TX sequence to zero, as when this function
+ * is called, the firmware has been just restarted.
+ */
+int i2400m_tx_setup(struct i2400m *i2400m)
+{
+ int result;
+
+ /* Do this here only once -- can't do on
+ * i2400m_hard_start_xmit() as we'll cause race conditions if
+ * the WS was scheduled on another CPU */
+ INIT_WORK(&i2400m->wake_tx_ws, i2400m_wake_tx_work);
+
+ i2400m->tx_sequence = 0;
+ i2400m->tx_buf = kmalloc(I2400M_TX_BUF_SIZE, GFP_KERNEL);
+ if (i2400m->tx_buf == NULL)
+ result = -ENOMEM;
+ else
+ result = 0;
+ /* Huh? the bus layer has to define this... */
+ BUG_ON(i2400m->bus_tx_block_size == 0);
+ return result;
+
+}
+
+
+/**
+ * i2400m_tx_release - Tear down the TX queue and infrastructure
+ */
+void i2400m_tx_release(struct i2400m *i2400m)
+{
+ kfree(i2400m->tx_buf);
+}
diff --git a/drivers/net/wimax/i2400m/usb-debug-levels.h b/drivers/net/wimax/i2400m/usb-debug-levels.h
new file mode 100644
index 000000000000..e4358bd880be
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-debug-levels.h
@@ -0,0 +1,42 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Debug levels control file for the i2400m-usb module
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __debug_levels__h__
+#define __debug_levels__h__
+
+/* Maximum compile and run time debug level for all submodules */
+#define D_MODULENAME i2400m_usb
+#define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL
+
+#include <linux/wimax/debug.h>
+
+/* List of all the enabled modules */
+enum d_module {
+ D_SUBMODULE_DECLARE(usb),
+ D_SUBMODULE_DECLARE(fw),
+ D_SUBMODULE_DECLARE(notif),
+ D_SUBMODULE_DECLARE(rx),
+ D_SUBMODULE_DECLARE(tx),
+};
+
+
+#endif /* #ifndef __debug_levels__h__ */
diff --git a/drivers/net/wimax/i2400m/usb-fw.c b/drivers/net/wimax/i2400m/usb-fw.c
new file mode 100644
index 000000000000..5ad287c228b8
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-fw.c
@@ -0,0 +1,340 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Firmware uploader's USB specifics
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Initial implementation
+ *
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - bus generic/specific split
+ *
+ * THE PROCEDURE
+ *
+ * See fw.c for the generic description of this procedure.
+ *
+ * This file implements only the USB specifics. It boils down to how
+ * to send a command and waiting for an acknowledgement from the
+ * device.
+ *
+ * This code (and process) is single threaded. It assumes it is the
+ * only thread poking around (guaranteed by fw.c).
+ *
+ * COMMAND EXECUTION
+ *
+ * A write URB is posted with the buffer to the bulk output endpoint.
+ *
+ * ACK RECEPTION
+ *
+ * We just post a URB to the notification endpoint and wait for
+ * data. We repeat until we get all the data we expect (as indicated
+ * by the call from the bus generic code).
+ *
+ * The data is not read from the bulk in endpoint for boot mode.
+ *
+ * ROADMAP
+ *
+ * i2400mu_bus_bm_cmd_send
+ * i2400m_bm_cmd_prepare...
+ * i2400mu_tx_bulk_out
+ *
+ * i2400mu_bus_bm_wait_for_ack
+ * i2400m_notif_submit
+ */
+#include <linux/usb.h>
+#include "i2400m-usb.h"
+
+
+#define D_SUBMODULE fw
+#include "usb-debug-levels.h"
+
+
+/*
+ * Synchronous write to the device
+ *
+ * Takes care of updating EDC counts and thus, handle device errors.
+ */
+static
+ssize_t i2400mu_tx_bulk_out(struct i2400mu *i2400mu, void *buf, size_t buf_size)
+{
+ int result;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ int len;
+ struct usb_endpoint_descriptor *epd;
+ int pipe, do_autopm = 1;
+
+ result = usb_autopm_get_interface(i2400mu->usb_iface);
+ if (result < 0) {
+ dev_err(dev, "BM-CMD: can't get autopm: %d\n", result);
+ do_autopm = 0;
+ }
+ epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT);
+ pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
+retry:
+ result = usb_bulk_msg(i2400mu->usb_dev, pipe, buf, buf_size, &len, HZ);
+ switch (result) {
+ case 0:
+ if (len != buf_size) {
+ dev_err(dev, "BM-CMD: short write (%u B vs %zu "
+ "expected)\n", len, buf_size);
+ result = -EIO;
+ break;
+ }
+ result = len;
+ break;
+ case -EINVAL: /* while removing driver */
+ case -ENODEV: /* dev disconnect ... */
+ case -ENOENT: /* just ignore it */
+ case -ESHUTDOWN: /* and exit */
+ case -ECONNRESET:
+ result = -ESHUTDOWN;
+ break;
+ case -ETIMEDOUT: /* bah... */
+ break;
+ default: /* any other? */
+ if (edc_inc(&i2400mu->urb_edc,
+ EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
+ dev_err(dev, "BM-CMD: maximum errors in "
+ "URB exceeded; resetting device\n");
+ usb_queue_reset_device(i2400mu->usb_iface);
+ result = -ENODEV;
+ break;
+ }
+ dev_err(dev, "BM-CMD: URB error %d, retrying\n",
+ result);
+ goto retry;
+ }
+ result = len;
+ if (do_autopm)
+ usb_autopm_put_interface(i2400mu->usb_iface);
+ return result;
+}
+
+
+/*
+ * Send a boot-mode command over the bulk-out pipe
+ *
+ * Command can be a raw command, which requires no preparation (and
+ * which might not even be following the command format). Checks that
+ * the right amount of data was transfered.
+ *
+ * To satisfy USB requirements (no onstack, vmalloc or in data segment
+ * buffers), we copy the command to i2400m->bm_cmd_buf and send it from
+ * there.
+ *
+ * @flags: pass thru from i2400m_bm_cmd()
+ * @return: cmd_size if ok, < 0 errno code on error.
+ */
+ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *i2400m,
+ const struct i2400m_bootrom_header *_cmd,
+ size_t cmd_size, int flags)
+{
+ ssize_t result;
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd);
+ struct i2400m_bootrom_header *cmd;
+ size_t cmd_size_a = ALIGN(cmd_size, 16); /* USB restriction */
+
+ d_fnstart(8, dev, "(i2400m %p cmd %p size %zu)\n",
+ i2400m, _cmd, cmd_size);
+ result = -E2BIG;
+ if (cmd_size > I2400M_BM_CMD_BUF_SIZE)
+ goto error_too_big;
+ memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size);
+ cmd = i2400m->bm_cmd_buf;
+ if (cmd_size_a > cmd_size) /* Zero pad space */
+ memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size);
+ if ((flags & I2400M_BM_CMD_RAW) == 0) {
+ if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0))
+ dev_warn(dev, "SW BUG: response_required == 0\n");
+ i2400m_bm_cmd_prepare(cmd);
+ }
+ result = i2400mu_tx_bulk_out(i2400mu, i2400m->bm_cmd_buf, cmd_size);
+ if (result < 0) {
+ dev_err(dev, "boot-mode cmd %d: cannot send: %zd\n",
+ opcode, result);
+ goto error_cmd_send;
+ }
+ if (result != cmd_size) { /* all was transferred? */
+ dev_err(dev, "boot-mode cmd %d: incomplete transfer "
+ "(%zu vs %zu submitted)\n", opcode, result, cmd_size);
+ result = -EIO;
+ goto error_cmd_size;
+ }
+error_cmd_size:
+error_cmd_send:
+error_too_big:
+ d_fnend(8, dev, "(i2400m %p cmd %p size %zu) = %zd\n",
+ i2400m, _cmd, cmd_size, result);
+ return result;
+}
+
+
+static
+void __i2400mu_bm_notif_cb(struct urb *urb)
+{
+ complete(urb->context);
+}
+
+
+/*
+ * submit a read to the notification endpoint
+ *
+ * @i2400m: device descriptor
+ * @urb: urb to use
+ * @completion: completion varible to complete when done
+ *
+ * Data is always read to i2400m->bm_ack_buf
+ */
+static
+int i2400mu_notif_submit(struct i2400mu *i2400mu, struct urb *urb,
+ struct completion *completion)
+{
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct usb_endpoint_descriptor *epd;
+ int pipe;
+
+ epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION);
+ pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress);
+ usb_fill_int_urb(urb, i2400mu->usb_dev, pipe,
+ i2400m->bm_ack_buf, I2400M_BM_ACK_BUF_SIZE,
+ __i2400mu_bm_notif_cb, completion,
+ epd->bInterval);
+ return usb_submit_urb(urb, GFP_KERNEL);
+}
+
+
+/*
+ * Read an ack from the notification endpoint
+ *
+ * @i2400m:
+ * @_ack: pointer to where to store the read data
+ * @ack_size: how many bytes we should read
+ *
+ * Returns: < 0 errno code on error; otherwise, amount of received bytes.
+ *
+ * Submits a notification read, appends the read data to the given ack
+ * buffer and then repeats (until @ack_size bytes have been
+ * received).
+ */
+ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *i2400m,
+ struct i2400m_bootrom_header *_ack,
+ size_t ack_size)
+{
+ ssize_t result = -ENOMEM;
+ struct device *dev = i2400m_dev(i2400m);
+ struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ struct urb notif_urb;
+ void *ack = _ack;
+ size_t offset, len;
+ long val;
+ int do_autopm = 1;
+ DECLARE_COMPLETION_ONSTACK(notif_completion);
+
+ d_fnstart(8, dev, "(i2400m %p ack %p size %zu)\n",
+ i2400m, ack, ack_size);
+ BUG_ON(_ack == i2400m->bm_ack_buf);
+ result = usb_autopm_get_interface(i2400mu->usb_iface);
+ if (result < 0) {
+ dev_err(dev, "BM-ACK: can't get autopm: %d\n", (int) result);
+ do_autopm = 0;
+ }
+ usb_init_urb(&notif_urb); /* ready notifications */
+ usb_get_urb(&notif_urb);
+ offset = 0;
+ while (offset < ack_size) {
+ init_completion(&notif_completion);
+ result = i2400mu_notif_submit(i2400mu, &notif_urb,
+ &notif_completion);
+ if (result < 0)
+ goto error_notif_urb_submit;
+ val = wait_for_completion_interruptible_timeout(
+ &notif_completion, HZ);
+ if (val == 0) {
+ result = -ETIMEDOUT;
+ usb_kill_urb(&notif_urb); /* Timedout */
+ goto error_notif_wait;
+ }
+ if (val == -ERESTARTSYS) {
+ result = -EINTR; /* Interrupted */
+ usb_kill_urb(&notif_urb);
+ goto error_notif_wait;
+ }
+ result = notif_urb.status; /* How was the ack? */
+ switch (result) {
+ case 0:
+ break;
+ case -EINVAL: /* while removing driver */
+ case -ENODEV: /* dev disconnect ... */
+ case -ENOENT: /* just ignore it */
+ case -ESHUTDOWN: /* and exit */
+ case -ECONNRESET:
+ result = -ESHUTDOWN;
+ goto error_dev_gone;
+ default: /* any other? */
+ usb_kill_urb(&notif_urb); /* Timedout */
+ if (edc_inc(&i2400mu->urb_edc,
+ EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME))
+ goto error_exceeded;
+ dev_err(dev, "BM-ACK: URB error %d, "
+ "retrying\n", notif_urb.status);
+ continue; /* retry */
+ }
+ if (notif_urb.actual_length == 0) {
+ d_printf(6, dev, "ZLP received, retrying\n");
+ continue;
+ }
+ /* Got data, append it to the buffer */
+ len = min(ack_size - offset, (size_t) notif_urb.actual_length);
+ memcpy(ack + offset, i2400m->bm_ack_buf, len);
+ offset += len;
+ }
+ result = offset;
+error_notif_urb_submit:
+error_notif_wait:
+error_dev_gone:
+out:
+ if (do_autopm)
+ usb_autopm_put_interface(i2400mu->usb_iface);
+ d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %zd\n",
+ i2400m, ack, ack_size, result);
+ return result;
+
+error_exceeded:
+ dev_err(dev, "bm: maximum errors in notification URB exceeded; "
+ "resetting device\n");
+ usb_queue_reset_device(i2400mu->usb_iface);
+ goto out;
+}
diff --git a/drivers/net/wimax/i2400m/usb-notif.c b/drivers/net/wimax/i2400m/usb-notif.c
new file mode 100644
index 000000000000..9702c22b2497
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-notif.c
@@ -0,0 +1,269 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m over USB
+ * Notification handling
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Initial implementation
+ *
+ *
+ * The notification endpoint is active when the device is not in boot
+ * mode; in here we just read and get notifications; based on those,
+ * we act to either reinitialize the device after a reboot or to
+ * submit a RX request.
+ *
+ * ROADMAP
+ *
+ * i2400mu_usb_notification_setup()
+ *
+ * i2400mu_usb_notification_release()
+ *
+ * i2400mu_usb_notification_cb() Called when a URB is ready
+ * i2400mu_notif_grok()
+ * i2400m_dev_reset_handle()
+ * i2400mu_rx_kick()
+ */
+#include <linux/usb.h>
+#include "i2400m-usb.h"
+
+
+#define D_SUBMODULE notif
+#include "usb-debug-levels.h"
+
+
+static const
+__le32 i2400m_ZERO_BARKER[4] = { 0, 0, 0, 0 };
+
+
+/*
+ * Process a received notification
+ *
+ * In normal operation mode, we can only receive two types of payloads
+ * on the notification endpoint:
+ *
+ * - a reboot barker, we do a bootstrap (the device has reseted).
+ *
+ * - a block of zeroes: there is pending data in the IN endpoint
+ */
+static
+int i2400mu_notification_grok(struct i2400mu *i2400mu, const void *buf,
+ size_t buf_len)
+{
+ int ret;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ struct i2400m *i2400m = &i2400mu->i2400m;
+
+ d_fnstart(4, dev, "(i2400m %p buf %p buf_len %zu)\n",
+ i2400mu, buf, buf_len);
+ ret = -EIO;
+ if (buf_len < sizeof(i2400m_NBOOT_BARKER))
+ /* Not a bug, just ignore */
+ goto error_bad_size;
+ if (!memcmp(i2400m_NBOOT_BARKER, buf, sizeof(i2400m_NBOOT_BARKER))
+ || !memcmp(i2400m_SBOOT_BARKER, buf, sizeof(i2400m_SBOOT_BARKER)))
+ ret = i2400m_dev_reset_handle(i2400m);
+ else if (!memcmp(i2400m_ZERO_BARKER, buf, sizeof(i2400m_ZERO_BARKER))) {
+ i2400mu_rx_kick(i2400mu);
+ ret = 0;
+ } else { /* Unknown or unexpected data in the notif message */
+ char prefix[64];
+ ret = -EIO;
+ dev_err(dev, "HW BUG? Unknown/unexpected data in notification "
+ "message (%zu bytes)\n", buf_len);
+ snprintf(prefix, sizeof(prefix), "%s %s: ",
+ dev_driver_string(dev) , dev->bus_id);
+ if (buf_len > 64) {
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
+ 8, 4, buf, 64, 0);
+ printk(KERN_ERR "%s... (only first 64 bytes "
+ "dumped)\n", prefix);
+ } else
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
+ 8, 4, buf, buf_len, 0);
+ }
+error_bad_size:
+ d_fnend(4, dev, "(i2400m %p buf %p buf_len %zu) = %d\n",
+ i2400mu, buf, buf_len, ret);
+ return ret;
+}
+
+
+/*
+ * URB callback for the notification endpoint
+ *
+ * @urb: the urb received from the notification endpoint
+ *
+ * This function will just process the USB side of the transaction,
+ * checking everything is fine, pass the processing to
+ * i2400m_notification_grok() and resubmit the URB.
+ */
+static
+void i2400mu_notification_cb(struct urb *urb)
+{
+ int ret;
+ struct i2400mu *i2400mu = urb->context;
+ struct device *dev = &i2400mu->usb_iface->dev;
+
+ d_fnstart(4, dev, "(urb %p status %d actual_length %d)\n",
+ urb, urb->status, urb->actual_length);
+ ret = urb->status;
+ switch (ret) {
+ case 0:
+ ret = i2400mu_notification_grok(i2400mu, urb->transfer_buffer,
+ urb->actual_length);
+ if (ret == -EIO && edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS,
+ EDC_ERROR_TIMEFRAME))
+ goto error_exceeded;
+ if (ret == -ENOMEM) /* uff...power cycle? shutdown? */
+ goto error_exceeded;
+ break;
+ case -EINVAL: /* while removing driver */
+ case -ENODEV: /* dev disconnect ... */
+ case -ENOENT: /* ditto */
+ case -ESHUTDOWN: /* URB killed */
+ case -ECONNRESET: /* disconnection */
+ goto out; /* Notify around */
+ default: /* Some error? */
+ if (edc_inc(&i2400mu->urb_edc,
+ EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME))
+ goto error_exceeded;
+ dev_err(dev, "notification: URB error %d, retrying\n",
+ urb->status);
+ }
+ usb_mark_last_busy(i2400mu->usb_dev);
+ ret = usb_submit_urb(i2400mu->notif_urb, GFP_ATOMIC);
+ switch (ret) {
+ case 0:
+ case -EINVAL: /* while removing driver */
+ case -ENODEV: /* dev disconnect ... */
+ case -ENOENT: /* ditto */
+ case -ESHUTDOWN: /* URB killed */
+ case -ECONNRESET: /* disconnection */
+ break; /* just ignore */
+ default: /* Some error? */
+ dev_err(dev, "notification: cannot submit URB: %d\n", ret);
+ goto error_submit;
+ }
+ d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n",
+ urb, urb->status, urb->actual_length);
+ return;
+
+error_exceeded:
+ dev_err(dev, "maximum errors in notification URB exceeded; "
+ "resetting device\n");
+error_submit:
+ usb_queue_reset_device(i2400mu->usb_iface);
+out:
+ d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n",
+ urb, urb->status, urb->actual_length);
+ return;
+}
+
+
+/*
+ * setup the notification endpoint
+ *
+ * @i2400m: device descriptor
+ *
+ * This procedure prepares the notification urb and handler for receiving
+ * unsolicited barkers from the device.
+ */
+int i2400mu_notification_setup(struct i2400mu *i2400mu)
+{
+ struct device *dev = &i2400mu->usb_iface->dev;
+ int usb_pipe, ret = 0;
+ struct usb_endpoint_descriptor *epd;
+ char *buf;
+
+ d_fnstart(4, dev, "(i2400m %p)\n", i2400mu);
+ buf = kmalloc(I2400MU_MAX_NOTIFICATION_LEN, GFP_KERNEL | GFP_DMA);
+ if (buf == NULL) {
+ dev_err(dev, "notification: buffer allocation failed\n");
+ ret = -ENOMEM;
+ goto error_buf_alloc;
+ }
+
+ i2400mu->notif_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!i2400mu->notif_urb) {
+ ret = -ENOMEM;
+ dev_err(dev, "notification: cannot allocate URB\n");
+ goto error_alloc_urb;
+ }
+ epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION);
+ usb_pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress);
+ usb_fill_int_urb(i2400mu->notif_urb, i2400mu->usb_dev, usb_pipe,
+ buf, I2400MU_MAX_NOTIFICATION_LEN,
+ i2400mu_notification_cb, i2400mu, epd->bInterval);
+ ret = usb_submit_urb(i2400mu->notif_urb, GFP_KERNEL);
+ if (ret != 0) {
+ dev_err(dev, "notification: cannot submit URB: %d\n", ret);
+ goto error_submit;
+ }
+ d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret);
+ return ret;
+
+error_submit:
+ usb_free_urb(i2400mu->notif_urb);
+error_alloc_urb:
+ kfree(buf);
+error_buf_alloc:
+ d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret);
+ return ret;
+}
+
+
+/*
+ * Tear down of the notification mechanism
+ *
+ * @i2400m: device descriptor
+ *
+ * Kill the interrupt endpoint urb, free any allocated resources.
+ *
+ * We need to check if we have done it before as for example,
+ * _suspend() call this; if after a suspend() we get a _disconnect()
+ * (as the case is when hibernating), nothing bad happens.
+ */
+void i2400mu_notification_release(struct i2400mu *i2400mu)
+{
+ struct device *dev = &i2400mu->usb_iface->dev;
+
+ d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
+ if (i2400mu->notif_urb != NULL) {
+ usb_kill_urb(i2400mu->notif_urb);
+ kfree(i2400mu->notif_urb->transfer_buffer);
+ usb_free_urb(i2400mu->notif_urb);
+ i2400mu->notif_urb = NULL;
+ }
+ d_fnend(4, dev, "(i2400mu %p)\n", i2400mu);
+}
diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c
new file mode 100644
index 000000000000..a314799967cf
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-rx.c
@@ -0,0 +1,420 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * USB RX handling
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * - Initial implementation
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Use skb_clone(), break up processing in chunks
+ * - Split transport/device specific
+ * - Make buffer size dynamic to exert less memory pressure
+ *
+ *
+ * This handles the RX path on USB.
+ *
+ * When a notification is received that says 'there is RX data ready',
+ * we call i2400mu_rx_kick(); that wakes up the RX kthread, which
+ * reads a buffer from USB and passes it to i2400m_rx() in the generic
+ * handling code. The RX buffer has an specific format that is
+ * described in rx.c.
+ *
+ * We use a kernel thread in a loop because:
+ *
+ * - we want to be able to call the USB power management get/put
+ * functions (blocking) before each transaction.
+ *
+ * - We might get a lot of notifications and we don't want to submit
+ * a zillion reads; by serializing, we are throttling.
+ *
+ * - RX data processing can get heavy enough so that it is not
+ * appropiate for doing it in the USB callback; thus we run it in a
+ * process context.
+ *
+ * We provide a read buffer of an arbitrary size (short of a page); if
+ * the callback reports -EOVERFLOW, it means it was too small, so we
+ * just double the size and retry (being careful to append, as
+ * sometimes the device provided some data). Every now and then we
+ * check if the average packet size is smaller than the current packet
+ * size and if so, we halve it. At the end, the size of the
+ * preallocated buffer should be following the average received
+ * transaction size, adapting dynamically to it.
+ *
+ * ROADMAP
+ *
+ * i2400mu_rx_kick() Called from notif.c when we get a
+ * 'data ready' notification
+ * i2400mu_rxd() Kernel RX daemon
+ * i2400mu_rx() Receive USB data
+ * i2400m_rx() Send data to generic i2400m RX handling
+ *
+ * i2400mu_rx_setup() called from i2400mu_bus_dev_start()
+ *
+ * i2400mu_rx_release() called from i2400mu_bus_dev_stop()
+ */
+#include <linux/workqueue.h>
+#include <linux/usb.h>
+#include "i2400m-usb.h"
+
+
+#define D_SUBMODULE rx
+#include "usb-debug-levels.h"
+
+/*
+ * Dynamic RX size
+ *
+ * We can't let the rx_size be a multiple of 512 bytes (the RX
+ * endpoint's max packet size). On some USB host controllers (we
+ * haven't been able to fully characterize which), if the device is
+ * about to send (for example) X bytes and we only post a buffer to
+ * receive n*512, it will fail to mark that as babble (so that
+ * i2400mu_rx() [case -EOVERFLOW] can resize the buffer and get the
+ * rest).
+ *
+ * So on growing or shrinking, if it is a multiple of the
+ * maxpacketsize, we remove some (instead of incresing some, so in a
+ * buddy allocator we try to waste less space).
+ *
+ * Note we also need a hook for this on i2400mu_rx() -- when we do the
+ * first read, we are sure we won't hit this spot because
+ * i240mm->rx_size has been set properly. However, if we have to
+ * double because of -EOVERFLOW, when we launch the read to get the
+ * rest of the data, we *have* to make sure that also is not a
+ * multiple of the max_pkt_size.
+ */
+
+static
+size_t i2400mu_rx_size_grow(struct i2400mu *i2400mu)
+{
+ struct device *dev = &i2400mu->usb_iface->dev;
+ size_t rx_size;
+ const size_t max_pkt_size = 512;
+
+ rx_size = 2 * i2400mu->rx_size;
+ if (rx_size % max_pkt_size == 0) {
+ rx_size -= 8;
+ d_printf(1, dev,
+ "RX: expected size grew to %zu [adjusted -8] "
+ "from %zu\n",
+ rx_size, i2400mu->rx_size);
+ } else
+ d_printf(1, dev,
+ "RX: expected size grew to %zu from %zu\n",
+ rx_size, i2400mu->rx_size);
+ return rx_size;
+}
+
+
+static
+void i2400mu_rx_size_maybe_shrink(struct i2400mu *i2400mu)
+{
+ const size_t max_pkt_size = 512;
+ struct device *dev = &i2400mu->usb_iface->dev;
+
+ if (unlikely(i2400mu->rx_size_cnt >= 100
+ && i2400mu->rx_size_auto_shrink)) {
+ size_t avg_rx_size =
+ i2400mu->rx_size_acc / i2400mu->rx_size_cnt;
+ size_t new_rx_size = i2400mu->rx_size / 2;
+ if (avg_rx_size < new_rx_size) {
+ if (new_rx_size % max_pkt_size == 0) {
+ new_rx_size -= 8;
+ d_printf(1, dev,
+ "RX: expected size shrank to %zu "
+ "[adjusted -8] from %zu\n",
+ new_rx_size, i2400mu->rx_size);
+ } else
+ d_printf(1, dev,
+ "RX: expected size shrank to %zu "
+ "from %zu\n",
+ new_rx_size, i2400mu->rx_size);
+ i2400mu->rx_size = new_rx_size;
+ i2400mu->rx_size_cnt = 0;
+ i2400mu->rx_size_acc = i2400mu->rx_size;
+ }
+ }
+}
+
+/*
+ * Receive a message with payloads from the USB bus into an skb
+ *
+ * @i2400mu: USB device descriptor
+ * @rx_skb: skb where to place the received message
+ *
+ * Deals with all the USB-specifics of receiving, dynamically
+ * increasing the buffer size if so needed. Returns the payload in the
+ * skb, ready to process. On a zero-length packet, we retry.
+ *
+ * On soft USB errors, we retry (until they become too frequent and
+ * then are promoted to hard); on hard USB errors, we reset the
+ * device. On other errors (skb realloacation, we just drop it and
+ * hope for the next invocation to solve it).
+ *
+ * Returns: pointer to the skb if ok, ERR_PTR on error.
+ * NOTE: this function might realloc the skb (if it is too small),
+ * so always update with the one returned.
+ * ERR_PTR() is < 0 on error.
+ * Will return NULL if it cannot reallocate -- this can be
+ * considered a transient retryable error.
+ */
+static
+struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb)
+{
+ int result = 0;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ int usb_pipe, read_size, rx_size, do_autopm;
+ struct usb_endpoint_descriptor *epd;
+ const size_t max_pkt_size = 512;
+
+ d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
+ do_autopm = atomic_read(&i2400mu->do_autopm);
+ result = do_autopm ?
+ usb_autopm_get_interface(i2400mu->usb_iface) : 0;
+ if (result < 0) {
+ dev_err(dev, "RX: can't get autopm: %d\n", result);
+ do_autopm = 0;
+ }
+ epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_IN);
+ usb_pipe = usb_rcvbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
+retry:
+ rx_size = skb_end_pointer(rx_skb) - rx_skb->data - rx_skb->len;
+ if (unlikely(rx_size % max_pkt_size == 0)) {
+ rx_size -= 8;
+ d_printf(1, dev, "RX: rx_size adapted to %d [-8]\n", rx_size);
+ }
+ result = usb_bulk_msg(
+ i2400mu->usb_dev, usb_pipe, rx_skb->data + rx_skb->len,
+ rx_size, &read_size, HZ);
+ usb_mark_last_busy(i2400mu->usb_dev);
+ switch (result) {
+ case 0:
+ if (read_size == 0)
+ goto retry; /* ZLP, just resubmit */
+ skb_put(rx_skb, read_size);
+ break;
+ case -EINVAL: /* while removing driver */
+ case -ENODEV: /* dev disconnect ... */
+ case -ENOENT: /* just ignore it */
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ break;
+ case -EOVERFLOW: { /* too small, reallocate */
+ struct sk_buff *new_skb;
+ rx_size = i2400mu_rx_size_grow(i2400mu);
+ if (rx_size <= (1 << 16)) /* cap it */
+ i2400mu->rx_size = rx_size;
+ else if (printk_ratelimit()) {
+ dev_err(dev, "BUG? rx_size up to %d\n", rx_size);
+ result = -EINVAL;
+ goto out;
+ }
+ skb_put(rx_skb, read_size);
+ new_skb = skb_copy_expand(rx_skb, 0, rx_size - rx_skb->len,
+ GFP_KERNEL);
+ if (new_skb == NULL) {
+ if (printk_ratelimit())
+ dev_err(dev, "RX: Can't reallocate skb to %d; "
+ "RX dropped\n", rx_size);
+ kfree_skb(rx_skb);
+ rx_skb = NULL;
+ goto out; /* drop it...*/
+ }
+ kfree_skb(rx_skb);
+ rx_skb = new_skb;
+ i2400mu->rx_size_cnt = 0;
+ i2400mu->rx_size_acc = i2400mu->rx_size;
+ d_printf(1, dev, "RX: size changed to %d, received %d, "
+ "copied %d, capacity %ld\n",
+ rx_size, read_size, rx_skb->len,
+ (long) (skb_end_pointer(new_skb) - new_skb->head));
+ goto retry;
+ }
+ /* In most cases, it happens due to the hardware scheduling a
+ * read when there was no data - unfortunately, we have no way
+ * to tell this timeout from a USB timeout. So we just ignore
+ * it. */
+ case -ETIMEDOUT:
+ dev_err(dev, "RX: timeout: %d\n", result);
+ result = 0;
+ break;
+ default: /* Any error */
+ if (edc_inc(&i2400mu->urb_edc,
+ EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME))
+ goto error_reset;
+ dev_err(dev, "RX: error receiving URB: %d, retrying\n", result);
+ goto retry;
+ }
+out:
+ if (do_autopm)
+ usb_autopm_put_interface(i2400mu->usb_iface);
+ d_fnend(4, dev, "(i2400mu %p) = %p\n", i2400mu, rx_skb);
+ return rx_skb;
+
+error_reset:
+ dev_err(dev, "RX: maximum errors in URB exceeded; "
+ "resetting device\n");
+ usb_queue_reset_device(i2400mu->usb_iface);
+ rx_skb = ERR_PTR(result);
+ goto out;
+}
+
+
+/*
+ * Kernel thread for USB reception of data
+ *
+ * This thread waits for a kick; once kicked, it will allocate an skb
+ * and receive a single message to it from USB (using
+ * i2400mu_rx()). Once received, it is passed to the generic i2400m RX
+ * code for processing.
+ *
+ * When done processing, it runs some dirty statistics to verify if
+ * the last 100 messages received were smaller than half of the
+ * current RX buffer size. In that case, the RX buffer size is
+ * halved. This will helps lowering the pressure on the memory
+ * allocator.
+ *
+ * Hard errors force the thread to exit.
+ */
+static
+int i2400mu_rxd(void *_i2400mu)
+{
+ int result = 0;
+ struct i2400mu *i2400mu = _i2400mu;
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ struct net_device *net_dev = i2400m->wimax_dev.net_dev;
+ size_t pending;
+ int rx_size;
+ struct sk_buff *rx_skb;
+
+ d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
+ while (1) {
+ d_printf(2, dev, "TX: waiting for messages\n");
+ pending = 0;
+ wait_event_interruptible(
+ i2400mu->rx_wq,
+ (kthread_should_stop() /* check this first! */
+ || (pending = atomic_read(&i2400mu->rx_pending_count)))
+ );
+ if (kthread_should_stop())
+ break;
+ if (pending == 0)
+ continue;
+ rx_size = i2400mu->rx_size;
+ d_printf(2, dev, "RX: reading up to %d bytes\n", rx_size);
+ rx_skb = __netdev_alloc_skb(net_dev, rx_size, GFP_KERNEL);
+ if (rx_skb == NULL) {
+ dev_err(dev, "RX: can't allocate skb [%d bytes]\n",
+ rx_size);
+ msleep(50); /* give it some time? */
+ continue;
+ }
+
+ /* Receive the message with the payloads */
+ rx_skb = i2400mu_rx(i2400mu, rx_skb);
+ result = PTR_ERR(rx_skb);
+ if (IS_ERR(rx_skb))
+ goto out;
+ atomic_dec(&i2400mu->rx_pending_count);
+ if (rx_skb == NULL || rx_skb->len == 0) {
+ /* some "ignorable" condition */
+ kfree_skb(rx_skb);
+ continue;
+ }
+
+ /* Deliver the message to the generic i2400m code */
+ i2400mu->rx_size_cnt++;
+ i2400mu->rx_size_acc += rx_skb->len;
+ result = i2400m_rx(i2400m, rx_skb);
+ if (result == -EIO
+ && edc_inc(&i2400mu->urb_edc,
+ EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
+ goto error_reset;
+ }
+
+ /* Maybe adjust RX buffer size */
+ i2400mu_rx_size_maybe_shrink(i2400mu);
+ }
+ result = 0;
+out:
+ d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result);
+ return result;
+
+error_reset:
+ dev_err(dev, "RX: maximum errors in received buffer exceeded; "
+ "resetting device\n");
+ usb_queue_reset_device(i2400mu->usb_iface);
+ goto out;
+}
+
+
+/*
+ * Start reading from the device
+ *
+ * @i2400m: device instance
+ *
+ * Notify the RX thread that there is data pending.
+ */
+void i2400mu_rx_kick(struct i2400mu *i2400mu)
+{
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct device *dev = &i2400mu->usb_iface->dev;
+
+ d_fnstart(3, dev, "(i2400mu %p)\n", i2400m);
+ atomic_inc(&i2400mu->rx_pending_count);
+ wake_up_all(&i2400mu->rx_wq);
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+}
+
+
+int i2400mu_rx_setup(struct i2400mu *i2400mu)
+{
+ int result = 0;
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+
+ i2400mu->rx_kthread = kthread_run(i2400mu_rxd, i2400mu, "%s-rx",
+ wimax_dev->name);
+ if (IS_ERR(i2400mu->rx_kthread)) {
+ result = PTR_ERR(i2400mu->rx_kthread);
+ dev_err(dev, "RX: cannot start thread: %d\n", result);
+ }
+ return result;
+}
+
+void i2400mu_rx_release(struct i2400mu *i2400mu)
+{
+ kthread_stop(i2400mu->rx_kthread);
+}
+
diff --git a/drivers/net/wimax/i2400m/usb-tx.c b/drivers/net/wimax/i2400m/usb-tx.c
new file mode 100644
index 000000000000..dfd893356f49
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb-tx.c
@@ -0,0 +1,229 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * USB specific TX handling
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Intel Corporation <linux-wimax@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ * - Initial implementation
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * - Split transport/device specific
+ *
+ *
+ * Takes the TX messages in the i2400m's driver TX FIFO and sends them
+ * to the device until there are no more.
+ *
+ * If we fail sending the message, we just drop it. There isn't much
+ * we can do at this point. We could also retry, but the USB stack has
+ * already retried and still failed, so there is not much of a
+ * point. As well, most of the traffic is network, which has recovery
+ * methods for dropped packets.
+ *
+ * For sending we just obtain a FIFO buffer to send, send it to the
+ * USB bulk out, tell the TX FIFO code we have sent it; query for
+ * another one, etc... until done.
+ *
+ * We use a thread so we can call usb_autopm_enable() and
+ * usb_autopm_disable() for each transaction; this way when the device
+ * goes idle, it will suspend. It also has less overhead than a
+ * dedicated workqueue, as it is being used for a single task.
+ *
+ * ROADMAP
+ *
+ * i2400mu_tx_setup()
+ * i2400mu_tx_release()
+ *
+ * i2400mu_bus_tx_kick() - Called by the tx.c code when there
+ * is new data in the FIFO.
+ * i2400mu_txd()
+ * i2400m_tx_msg_get()
+ * i2400m_tx_msg_sent()
+ */
+#include "i2400m-usb.h"
+
+
+#define D_SUBMODULE tx
+#include "usb-debug-levels.h"
+
+
+/*
+ * Get the next TX message in the TX FIFO and send it to the device
+ *
+ * Note that any iteration consumes a message to be sent, no matter if
+ * it succeeds or fails (we have no real way to retry or complain).
+ *
+ * Return: 0 if ok, < 0 errno code on hard error.
+ */
+static
+int i2400mu_tx(struct i2400mu *i2400mu, struct i2400m_msg_hdr *tx_msg,
+ size_t tx_msg_size)
+{
+ int result = 0;
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ int usb_pipe, sent_size, do_autopm;
+ struct usb_endpoint_descriptor *epd;
+
+ d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
+ do_autopm = atomic_read(&i2400mu->do_autopm);
+ result = do_autopm ?
+ usb_autopm_get_interface(i2400mu->usb_iface) : 0;
+ if (result < 0) {
+ dev_err(dev, "TX: can't get autopm: %d\n", result);
+ do_autopm = 0;
+ }
+ epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT);
+ usb_pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
+retry:
+ result = usb_bulk_msg(i2400mu->usb_dev, usb_pipe,
+ tx_msg, tx_msg_size, &sent_size, HZ);
+ usb_mark_last_busy(i2400mu->usb_dev);
+ switch (result) {
+ case 0:
+ if (sent_size != tx_msg_size) { /* Too short? drop it */
+ dev_err(dev, "TX: short write (%d B vs %zu "
+ "expected)\n", sent_size, tx_msg_size);
+ result = -EIO;
+ }
+ break;
+ case -EINVAL: /* while removing driver */
+ case -ENODEV: /* dev disconnect ... */
+ case -ENOENT: /* just ignore it */
+ case -ESHUTDOWN: /* and exit */
+ case -ECONNRESET:
+ result = -ESHUTDOWN;
+ break;
+ default: /* Some error? */
+ if (edc_inc(&i2400mu->urb_edc,
+ EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {
+ dev_err(dev, "TX: maximum errors in URB "
+ "exceeded; resetting device\n");
+ usb_queue_reset_device(i2400mu->usb_iface);
+ } else {
+ dev_err(dev, "TX: cannot send URB; retrying. "
+ "tx_msg @%zu %zu B [%d sent]: %d\n",
+ (void *) tx_msg - i2400m->tx_buf,
+ tx_msg_size, sent_size, result);
+ goto retry;
+ }
+ }
+ if (do_autopm)
+ usb_autopm_put_interface(i2400mu->usb_iface);
+ d_fnend(4, dev, "(i2400mu %p) = result\n", i2400mu);
+ return result;
+}
+
+
+/*
+ * Get the next TX message in the TX FIFO and send it to the device
+ *
+ * Note we exit the loop if i2400mu_tx() fails; that funtion only
+ * fails on hard error (failing to tx a buffer not being one of them,
+ * see its doc).
+ *
+ * Return: 0
+ */
+static
+int i2400mu_txd(void *_i2400mu)
+{
+ int result = 0;
+ struct i2400mu *i2400mu = _i2400mu;
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ struct i2400m_msg_hdr *tx_msg;
+ size_t tx_msg_size;
+
+ d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu);
+
+ while (1) {
+ d_printf(2, dev, "TX: waiting for messages\n");
+ tx_msg = NULL;
+ wait_event_interruptible(
+ i2400mu->tx_wq,
+ (kthread_should_stop() /* check this first! */
+ || (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size)))
+ );
+ if (kthread_should_stop())
+ break;
+ WARN_ON(tx_msg == NULL); /* should not happen...*/
+ d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size);
+ d_dump(5, dev, tx_msg, tx_msg_size);
+ /* Yeah, we ignore errors ... not much we can do */
+ i2400mu_tx(i2400mu, tx_msg, tx_msg_size);
+ i2400m_tx_msg_sent(i2400m); /* ack it, advance the FIFO */
+ if (result < 0)
+ break;
+ }
+ d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result);
+ return result;
+}
+
+
+/*
+ * i2400m TX engine notifies us that there is data in the FIFO ready
+ * for TX
+ *
+ * If there is a URB in flight, don't do anything; when it finishes,
+ * it will see there is data in the FIFO and send it. Else, just
+ * submit a write.
+ */
+void i2400mu_bus_tx_kick(struct i2400m *i2400m)
+{
+ struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ struct device *dev = &i2400mu->usb_iface->dev;
+
+ d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m);
+ wake_up_all(&i2400mu->tx_wq);
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+}
+
+
+int i2400mu_tx_setup(struct i2400mu *i2400mu)
+{
+ int result = 0;
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
+
+ i2400mu->tx_kthread = kthread_run(i2400mu_txd, i2400mu, "%s-tx",
+ wimax_dev->name);
+ if (IS_ERR(i2400mu->tx_kthread)) {
+ result = PTR_ERR(i2400mu->tx_kthread);
+ dev_err(dev, "TX: cannot start thread: %d\n", result);
+ }
+ return result;
+}
+
+void i2400mu_tx_release(struct i2400mu *i2400mu)
+{
+ kthread_stop(i2400mu->tx_kthread);
+}
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
new file mode 100644
index 000000000000..c6d93465c7e2
--- /dev/null
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -0,0 +1,597 @@
+/*
+ * Intel Wireless WiMAX Connection 2400m
+ * Linux driver model glue for USB device, reset & fw upload
+ *
+ *
+ * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
+ * Yanir Lubetkin <yanirx.lubetkin@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ *
+ * See i2400m-usb.h for a general description of this driver.
+ *
+ * This file implements driver model glue, and hook ups for the
+ * generic driver to implement the bus-specific functions (device
+ * communication setup/tear down, firmware upload and resetting).
+ *
+ * ROADMAP
+ *
+ * i2400mu_probe()
+ * alloc_netdev()...
+ * i2400mu_netdev_setup()
+ * i2400mu_init()
+ * i2400m_netdev_setup()
+ * i2400m_setup()...
+ *
+ * i2400mu_disconnect
+ * i2400m_release()
+ * free_netdev()
+ *
+ * i2400mu_suspend()
+ * i2400m_cmd_enter_powersave()
+ * i2400mu_notification_release()
+ *
+ * i2400mu_resume()
+ * i2400mu_notification_setup()
+ *
+ * i2400mu_bus_dev_start() Called by i2400m_dev_start() [who is
+ * i2400mu_tx_setup() called by i2400m_setup()]
+ * i2400mu_rx_setup()
+ * i2400mu_notification_setup()
+ *
+ * i2400mu_bus_dev_stop() Called by i2400m_dev_stop() [who is
+ * i2400mu_notification_release() called by i2400m_release()]
+ * i2400mu_rx_release()
+ * i2400mu_tx_release()
+ *
+ * i2400mu_bus_reset() Called by i2400m->bus_reset
+ * __i2400mu_reset()
+ * __i2400mu_send_barker()
+ * usb_reset_device()
+ */
+#include "i2400m-usb.h"
+#include <linux/wimax/i2400m.h>
+#include <linux/debugfs.h>
+
+
+#define D_SUBMODULE usb
+#include "usb-debug-levels.h"
+
+
+/* Our firmware file name */
+#define I2400MU_FW_FILE_NAME "i2400m-fw-usb-" I2400M_FW_VERSION ".sbcf"
+
+static
+int i2400mu_bus_dev_start(struct i2400m *i2400m)
+{
+ int result;
+ struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ struct device *dev = &i2400mu->usb_iface->dev;
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ result = i2400mu_tx_setup(i2400mu);
+ if (result < 0)
+ goto error_usb_tx_setup;
+ result = i2400mu_rx_setup(i2400mu);
+ if (result < 0)
+ goto error_usb_rx_setup;
+ result = i2400mu_notification_setup(i2400mu);
+ if (result < 0)
+ goto error_notif_setup;
+ d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
+ return result;
+
+error_notif_setup:
+ i2400mu_rx_release(i2400mu);
+error_usb_rx_setup:
+ i2400mu_tx_release(i2400mu);
+error_usb_tx_setup:
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+ return result;
+}
+
+
+static
+void i2400mu_bus_dev_stop(struct i2400m *i2400m)
+{
+ struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ struct device *dev = &i2400mu->usb_iface->dev;
+
+ d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
+ i2400mu_notification_release(i2400mu);
+ i2400mu_rx_release(i2400mu);
+ i2400mu_tx_release(i2400mu);
+ d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
+}
+
+
+/*
+ * Sends a barker buffer to the device
+ *
+ * This helper will allocate a kmalloced buffer and use it to transmit
+ * (then free it). Reason for this is that other arches cannot use
+ * stack/vmalloc/text areas for DMA transfers.
+ *
+ * Error recovery here is simpler: anything is considered a hard error
+ * and will move the reset code to use a last-resort bus-based reset.
+ */
+static
+int __i2400mu_send_barker(struct i2400mu *i2400mu,
+ const __le32 *barker,
+ size_t barker_size,
+ unsigned endpoint)
+{
+ struct usb_endpoint_descriptor *epd = NULL;
+ int pipe, actual_len, ret;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ void *buffer;
+ int do_autopm = 1;
+
+ ret = usb_autopm_get_interface(i2400mu->usb_iface);
+ if (ret < 0) {
+ dev_err(dev, "RESET: can't get autopm: %d\n", ret);
+ do_autopm = 0;
+ }
+ ret = -ENOMEM;
+ buffer = kmalloc(barker_size, GFP_KERNEL);
+ if (buffer == NULL)
+ goto error_kzalloc;
+ epd = usb_get_epd(i2400mu->usb_iface, endpoint);
+ pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress);
+ memcpy(buffer, barker, barker_size);
+ ret = usb_bulk_msg(i2400mu->usb_dev, pipe, buffer, barker_size,
+ &actual_len, HZ);
+ if (ret < 0) {
+ if (ret != -EINVAL)
+ dev_err(dev, "E: barker error: %d\n", ret);
+ } else if (actual_len != barker_size) {
+ dev_err(dev, "E: only %d bytes transmitted\n", actual_len);
+ ret = -EIO;
+ }
+ kfree(buffer);
+error_kzalloc:
+ if (do_autopm)
+ usb_autopm_put_interface(i2400mu->usb_iface);
+ return ret;
+}
+
+
+/*
+ * Reset a device at different levels (warm, cold or bus)
+ *
+ * @i2400m: device descriptor
+ * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS)
+ *
+ * Warm and cold resets get a USB reset if they fail.
+ *
+ * Warm reset:
+ *
+ * The device will be fully reset internally, but won't be
+ * disconnected from the USB bus (so no reenumeration will
+ * happen). Firmware upload will be neccessary.
+ *
+ * The device will send a reboot barker in the notification endpoint
+ * that will trigger the driver to reinitialize the state
+ * automatically from notif.c:i2400m_notification_grok() into
+ * i2400m_dev_bootstrap_delayed().
+ *
+ * Cold and bus (USB) reset:
+ *
+ * The device will be fully reset internally, disconnected from the
+ * USB bus an a reenumeration will happen. Firmware upload will be
+ * neccessary. Thus, we don't do any locking or struct
+ * reinitialization, as we are going to be fully disconnected and
+ * reenumerated.
+ *
+ * Note we need to return -ENODEV if a warm reset was requested and we
+ * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset()
+ * and wimax_dev->op_reset.
+ *
+ * WARNING: no driver state saved/fixed
+ */
+static
+int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
+{
+ int result;
+ struct i2400mu *i2400mu =
+ container_of(i2400m, struct i2400mu, i2400m);
+ struct device *dev = i2400m_dev(i2400m);
+ static const __le32 i2400m_WARM_BOOT_BARKER[4] = {
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER),
+ };
+ static const __le32 i2400m_COLD_BOOT_BARKER[4] = {
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER),
+ };
+
+ d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt);
+ if (rt == I2400M_RT_WARM)
+ result = __i2400mu_send_barker(i2400mu, i2400m_WARM_BOOT_BARKER,
+ sizeof(i2400m_WARM_BOOT_BARKER),
+ I2400MU_EP_BULK_OUT);
+ else if (rt == I2400M_RT_COLD)
+ result = __i2400mu_send_barker(i2400mu, i2400m_COLD_BOOT_BARKER,
+ sizeof(i2400m_COLD_BOOT_BARKER),
+ I2400MU_EP_RESET_COLD);
+ else if (rt == I2400M_RT_BUS) {
+do_bus_reset:
+ result = usb_reset_device(i2400mu->usb_dev);
+ switch (result) {
+ case 0:
+ case -EINVAL: /* device is gone */
+ case -ENODEV:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ result = rt == I2400M_RT_WARM ? -ENODEV : 0;
+ break; /* We assume the device is disconnected */
+ default:
+ dev_err(dev, "USB reset failed (%d), giving up!\n",
+ result);
+ }
+ } else
+ BUG();
+ if (result < 0
+ && result != -EINVAL /* device is gone */
+ && rt != I2400M_RT_BUS) {
+ dev_err(dev, "%s reset failed (%d); trying USB reset\n",
+ rt == I2400M_RT_WARM ? "warm" : "cold", result);
+ rt = I2400M_RT_BUS;
+ goto do_bus_reset;
+ }
+ d_fnend(3, dev, "(i2400m %p rt %u) = %d\n", i2400m, rt, result);
+ return result;
+}
+
+
+static
+void i2400mu_netdev_setup(struct net_device *net_dev)
+{
+ struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+ struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ i2400mu_init(i2400mu);
+ i2400m_netdev_setup(net_dev);
+}
+
+
+/*
+ * Debug levels control; see debug.h
+ */
+struct d_level D_LEVEL[] = {
+ D_SUBMODULE_DEFINE(usb),
+ D_SUBMODULE_DEFINE(fw),
+ D_SUBMODULE_DEFINE(notif),
+ D_SUBMODULE_DEFINE(rx),
+ D_SUBMODULE_DEFINE(tx),
+};
+size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
+
+
+#define __debugfs_register(prefix, name, parent) \
+do { \
+ result = d_level_register_debugfs(prefix, name, parent); \
+ if (result < 0) \
+ goto error; \
+} while (0)
+
+
+static
+int i2400mu_debugfs_add(struct i2400mu *i2400mu)
+{
+ int result;
+ struct device *dev = &i2400mu->usb_iface->dev;
+ struct dentry *dentry = i2400mu->i2400m.wimax_dev.debugfs_dentry;
+ struct dentry *fd;
+
+ dentry = debugfs_create_dir("i2400m-usb", dentry);
+ result = PTR_ERR(dentry);
+ if (IS_ERR(dentry)) {
+ if (result == -ENODEV)
+ result = 0; /* No debugfs support */
+ goto error;
+ }
+ i2400mu->debugfs_dentry = dentry;
+ __debugfs_register("dl_", usb, dentry);
+ __debugfs_register("dl_", fw, dentry);
+ __debugfs_register("dl_", notif, dentry);
+ __debugfs_register("dl_", rx, dentry);
+ __debugfs_register("dl_", tx, dentry);
+
+ /* Don't touch these if you don't know what you are doing */
+ fd = debugfs_create_u8("rx_size_auto_shrink", 0600, dentry,
+ &i2400mu->rx_size_auto_shrink);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "rx_size_auto_shrink: %d\n", result);
+ goto error;
+ }
+
+ fd = debugfs_create_size_t("rx_size", 0600, dentry,
+ &i2400mu->rx_size);
+ result = PTR_ERR(fd);
+ if (IS_ERR(fd) && result != -ENODEV) {
+ dev_err(dev, "Can't create debugfs entry "
+ "rx_size: %d\n", result);
+ goto error;
+ }
+
+ return 0;
+
+error:
+ debugfs_remove_recursive(i2400mu->debugfs_dentry);
+ return result;
+}
+
+
+/*
+ * Probe a i2400m interface and register it
+ *
+ * @iface: USB interface to link to
+ * @id: USB class/subclass/protocol id
+ * @returns: 0 if ok, < 0 errno code on error.
+ *
+ * Alloc a net device, initialize the bus-specific details and then
+ * calls the bus-generic initialization routine. That will register
+ * the wimax and netdev devices, upload the firmware [using
+ * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
+ * communication with the device and then will start to talk to it to
+ * finnish setting it up.
+ */
+static
+int i2400mu_probe(struct usb_interface *iface,
+ const struct usb_device_id *id)
+{
+ int result;
+ struct net_device *net_dev;
+ struct device *dev = &iface->dev;
+ struct i2400m *i2400m;
+ struct i2400mu *i2400mu;
+ struct usb_device *usb_dev = interface_to_usbdev(iface);
+
+ if (usb_dev->speed != USB_SPEED_HIGH)
+ dev_err(dev, "device not connected as high speed\n");
+
+ /* Allocate instance [calls i2400m_netdev_setup() on it]. */
+ result = -ENOMEM;
+ net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
+ i2400mu_netdev_setup);
+ if (net_dev == NULL) {
+ dev_err(dev, "no memory for network device instance\n");
+ goto error_alloc_netdev;
+ }
+ SET_NETDEV_DEV(net_dev, dev);
+ i2400m = net_dev_to_i2400m(net_dev);
+ i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ i2400m->wimax_dev.net_dev = net_dev;
+ i2400mu->usb_dev = usb_get_dev(usb_dev);
+ i2400mu->usb_iface = iface;
+ usb_set_intfdata(iface, i2400mu);
+
+ i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
+ i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
+ i2400m->bus_dev_start = i2400mu_bus_dev_start;
+ i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
+ i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
+ i2400m->bus_reset = i2400mu_bus_reset;
+ i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
+ i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
+ i2400m->bus_fw_name = I2400MU_FW_FILE_NAME;
+ i2400m->bus_bm_mac_addr_impaired = 0;
+
+#ifdef CONFIG_PM
+ iface->needs_remote_wakeup = 1; /* autosuspend (15s delay) */
+ device_init_wakeup(dev, 1);
+ usb_autopm_enable(i2400mu->usb_iface);
+ usb_dev->autosuspend_delay = 15 * HZ;
+ usb_dev->autosuspend_disabled = 0;
+#endif
+
+ result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);
+ if (result < 0) {
+ dev_err(dev, "cannot setup device: %d\n", result);
+ goto error_setup;
+ }
+ result = i2400mu_debugfs_add(i2400mu);
+ if (result < 0) {
+ dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result);
+ goto error_debugfs_add;
+ }
+ return 0;
+
+error_debugfs_add:
+ i2400m_release(i2400m);
+error_setup:
+ usb_set_intfdata(iface, NULL);
+ usb_put_dev(i2400mu->usb_dev);
+ free_netdev(net_dev);
+error_alloc_netdev:
+ return result;
+}
+
+
+/*
+ * Disconect a i2400m from the system.
+ *
+ * i2400m_stop() has been called before, so al the rx and tx contexts
+ * have been taken down already. Make sure the queue is stopped,
+ * unregister netdev and i2400m, free and kill.
+ */
+static
+void i2400mu_disconnect(struct usb_interface *iface)
+{
+ struct i2400mu *i2400mu = usb_get_intfdata(iface);
+ struct i2400m *i2400m = &i2400mu->i2400m;
+ struct net_device *net_dev = i2400m->wimax_dev.net_dev;
+ struct device *dev = &iface->dev;
+
+ d_fnstart(3, dev, "(iface %p i2400m %p)\n", iface, i2400m);
+
+ debugfs_remove_recursive(i2400mu->debugfs_dentry);
+ i2400m_release(i2400m);
+ usb_set_intfdata(iface, NULL);
+ usb_put_dev(i2400mu->usb_dev);
+ free_netdev(net_dev);
+ d_fnend(3, dev, "(iface %p i2400m %p) = void\n", iface, i2400m);
+}
+
+
+/*
+ * Get the device ready for USB port or system standby and hibernation
+ *
+ * USB port and system standby are handled the same.
+ *
+ * When the system hibernates, the USB device is powered down and then
+ * up, so we don't really have to do much here, as it will be seen as
+ * a reconnect. Still for simplicity we consider this case the same as
+ * suspend, so that the device has a chance to do notify the base
+ * station (if connected).
+ *
+ * So at the end, the three cases require common handling.
+ *
+ * If at the time of this call the device's firmware is not loaded,
+ * nothing has to be done.
+ *
+ * If the firmware is loaded, we need to:
+ *
+ * - tell the device to go into host interface power save mode, wait
+ * for it to ack
+ *
+ * This is quite more interesting than it is; we need to execute a
+ * command, but this time, we don't want the code in usb-{tx,rx}.c
+ * to call the usb_autopm_get/put_interface() barriers as it'd
+ * deadlock, so we need to decrement i2400mu->do_autopm, that acts
+ * as a poor man's semaphore. Ugly, but it works.
+ *
+ * As well, the device might refuse going to sleep for whichever
+ * reason. In this case we just fail. For system suspend/hibernate,
+ * we *can't* fail. We look at usb_dev->auto_pm to see if the
+ * suspend call comes from the USB stack or from the system and act
+ * in consequence.
+ *
+ * - stop the notification endpoint polling
+ */
+static
+int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
+{
+ int result = 0;
+ struct device *dev = &iface->dev;
+ struct i2400mu *i2400mu = usb_get_intfdata(iface);
+#ifdef CONFIG_PM
+ struct usb_device *usb_dev = i2400mu->usb_dev;
+#endif
+ struct i2400m *i2400m = &i2400mu->i2400m;
+
+ d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event);
+ if (i2400m->updown == 0)
+ goto no_firmware;
+ d_printf(1, dev, "fw up, requesting standby\n");
+ atomic_dec(&i2400mu->do_autopm);
+ result = i2400m_cmd_enter_powersave(i2400m);
+ atomic_inc(&i2400mu->do_autopm);
+#ifdef CONFIG_PM
+ if (result < 0 && usb_dev->auto_pm == 0) {
+ /* System suspend, can't fail */
+ dev_err(dev, "failed to suspend, will reset on resume\n");
+ result = 0;
+ }
+#endif
+ if (result < 0)
+ goto error_enter_powersave;
+ i2400mu_notification_release(i2400mu);
+ d_printf(1, dev, "fw up, got standby\n");
+error_enter_powersave:
+no_firmware:
+ d_fnend(3, dev, "(iface %p pm_msg %u) = %d\n",
+ iface, pm_msg.event, result);
+ return result;
+}
+
+
+static
+int i2400mu_resume(struct usb_interface *iface)
+{
+ int ret = 0;
+ struct device *dev = &iface->dev;
+ struct i2400mu *i2400mu = usb_get_intfdata(iface);
+ struct i2400m *i2400m = &i2400mu->i2400m;
+
+ d_fnstart(3, dev, "(iface %p)\n", iface);
+ if (i2400m->updown == 0) {
+ d_printf(1, dev, "fw was down, no resume neeed\n");
+ goto out;
+ }
+ d_printf(1, dev, "fw was up, resuming\n");
+ i2400mu_notification_setup(i2400mu);
+ /* USB has flow control, so we don't need to give it time to
+ * come back; otherwise, we'd use something like a get-state
+ * command... */
+out:
+ d_fnend(3, dev, "(iface %p) = %d\n", iface, ret);
+ return ret;
+}
+
+
+static
+struct usb_device_id i2400mu_id_table[] = {
+ { USB_DEVICE(0x8086, 0x0181) },
+ { USB_DEVICE(0x8086, 0x1403) },
+ { USB_DEVICE(0x8086, 0x1405) },
+ { USB_DEVICE(0x8086, 0x0180) },
+ { USB_DEVICE(0x8086, 0x0182) },
+ { USB_DEVICE(0x8086, 0x1406) },
+ { USB_DEVICE(0x8086, 0x1403) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, i2400mu_id_table);
+
+
+static
+struct usb_driver i2400mu_driver = {
+ .name = KBUILD_MODNAME,
+ .suspend = i2400mu_suspend,
+ .resume = i2400mu_resume,
+ .probe = i2400mu_probe,
+ .disconnect = i2400mu_disconnect,
+ .id_table = i2400mu_id_table,
+ .supports_autosuspend = 1,
+};
+
+static
+int __init i2400mu_driver_init(void)
+{
+ return usb_register(&i2400mu_driver);
+}
+module_init(i2400mu_driver_init);
+
+
+static
+void __exit i2400mu_driver_exit(void)
+{
+ flush_scheduled_work(); /* for the stuff we schedule from sysfs.c */
+ usb_deregister(&i2400mu_driver);
+}
+module_exit(i2400mu_driver_exit);
+
+MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
+MODULE_DESCRIPTION("Intel 2400M WiMAX networking for USB");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(I2400MU_FW_FILE_NAME);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ea543fcf2687..e4f9f747de88 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -111,7 +111,7 @@ config WLAN_80211
lets you choose drivers.
config PCMCIA_RAYCS
- tristate "Aviator/Raytheon 2.4MHz wireless support"
+ tristate "Aviator/Raytheon 2.4GHz wireless support"
depends on PCMCIA && WLAN_80211
select WIRELESS_EXT
---help---
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 4af2607deec0..a533ed60bb4d 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1028,6 +1028,8 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
* it's done by reseting the chip. To accomplish this we must
* first cleanup any pending DMA, then restart stuff after a la
* ath5k_init.
+ *
+ * Called with sc->lock.
*/
static int
ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
@@ -2644,7 +2646,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (skb_headroom(skb) < padsize) {
ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
" headroom to pad %d\n", hdrlen, padsize);
- return -1;
+ return NETDEV_TX_BUSY;
}
skb_push(skb, padsize);
memmove(skb->data, skb->data+padsize, hdrlen);
@@ -2655,7 +2657,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
spin_unlock_irqrestore(&sc->txbuflock, flags);
ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
- return -1;
+ return NETDEV_TX_BUSY;
}
bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
list_del(&bf->list);
@@ -2673,10 +2675,10 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
sc->txbuf_len++;
spin_unlock_irqrestore(&sc->txbuflock, flags);
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
}
- return 0;
+ return NETDEV_TX_OK;
}
static int
@@ -2814,11 +2816,17 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath5k_softc *sc = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
+ int ret;
+
+ mutex_lock(&sc->lock);
sc->bintval = conf->beacon_int;
sc->power_level = conf->power_level;
- return ath5k_chan_set(sc, conf->channel);
+ ret = ath5k_chan_set(sc, conf->channel);
+
+ mutex_unlock(&sc->lock);
+ return ret;
}
static int
diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c
index 7e2b1a67e5da..b65b4feb2d28 100644
--- a/drivers/net/wireless/ath5k/dma.c
+++ b/drivers/net/wireless/ath5k/dma.c
@@ -594,7 +594,7 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
* XXX: BMISS interrupts may occur after association.
* I found this on 5210 code but it needs testing. If this is
* true we should disable them before assoc and re-enable them
- * after a successfull assoc + some jiffies.
+ * after a successful assoc + some jiffies.
interrupt_mask &= ~AR5K_INT_BMISS;
*/
}
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c
index 0cac05c6a9ce..75eb9f43c741 100644
--- a/drivers/net/wireless/ath5k/pcu.c
+++ b/drivers/net/wireless/ath5k/pcu.c
@@ -65,7 +65,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
if (ah->ah_version == AR5K_AR5210)
pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
else
- AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
break;
case NL80211_IFTYPE_AP:
@@ -75,7 +75,7 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
if (ah->ah_version == AR5K_AR5210)
pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
else
- AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS);
break;
case NL80211_IFTYPE_STATION:
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index 91aaeaf88199..9189ab13286c 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -73,7 +73,7 @@
#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */
#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */
-#define AR5K_CFG_ADHOC 0x00000020 /* AP/Adhoc indication [5211+] */
+#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */
#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */
diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig
index c43bd321f97f..90a8dd873786 100644
--- a/drivers/net/wireless/ath9k/Kconfig
+++ b/drivers/net/wireless/ath9k/Kconfig
@@ -1,6 +1,7 @@
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211 && WLAN_80211
+ depends on RFKILL || RFKILL=n
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 191eec50dc75..727f067aca4f 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -2164,13 +2164,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
conf->ht.channel_type);
}
+ ath_update_chainmask(sc, conf->ht.enabled);
+
if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) {
DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n");
mutex_unlock(&sc->mutex);
return -EINVAL;
}
-
- ath_update_chainmask(sc, conf->ht.enabled);
}
if (changed & IEEE80211_CONF_CHANGE_POWER)
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index 04ab457a8faa..1b71b934bb5e 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -490,7 +490,7 @@ static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
{
- if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG))
+ if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG))
return 0;
if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
return 0;
diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h
index 9112c030b1e8..6df1b3b77c25 100644
--- a/drivers/net/wireless/ath9k/regd_common.h
+++ b/drivers/net/wireless/ath9k/regd_common.h
@@ -228,7 +228,7 @@ enum {
};
#define REG_DOMAIN_2GHZ_MASK (REQ_MASK & \
- (!(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB)))
+ (~(ADHOC_NO_11A | DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB)))
#define REG_DOMAIN_5GHZ_MASK REQ_MASK
static struct reg_dmn_pair_mapping regDomainPairs[] = {
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 3bfc3b90f256..c92f0c6e4adc 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -126,15 +126,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
tx_info->flags |= IEEE80211_TX_STAT_ACK;
}
- tx_info->status.rates[0].count = tx_status->retries;
- if (tx_info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
- /* Change idx from internal table index to MCS index */
- int idx = tx_info->status.rates[0].idx;
- struct ath_rate_table *rate_table = sc->cur_rate_table;
- if (idx >= 0 && idx < rate_table->rate_cnt)
- tx_info->status.rates[0].idx =
- rate_table->info[idx].ratecode & 0x7f;
- }
+ tx_info->status.rates[0].count = tx_status->retries + 1;
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
padsize = hdrlen & 3;
@@ -264,25 +256,22 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb,
}
/* Get seqno */
-
- if (ieee80211_is_data(fc) && !is_pae(skb)) {
- /* For HT capable stations, we save tidno for later use.
- * We also override seqno set by upper layer with the one
- * in tx aggregation state.
- *
- * If fragmentation is on, the sequence number is
- * not overridden, since it has been
- * incremented by the fragmentation routine.
- *
- * FIXME: check if the fragmentation threshold exceeds
- * IEEE80211 max.
- */
- tid = ATH_AN_2_TID(an, bf->bf_tidno);
- hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
- IEEE80211_SEQ_SEQ_SHIFT);
- bf->bf_seqno = tid->seq_next;
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
- }
+ /* For HT capable stations, we save tidno for later use.
+ * We also override seqno set by upper layer with the one
+ * in tx aggregation state.
+ *
+ * If fragmentation is on, the sequence number is
+ * not overridden, since it has been
+ * incremented by the fragmentation routine.
+ *
+ * FIXME: check if the fragmentation threshold exceeds
+ * IEEE80211 max.
+ */
+ tid = ATH_AN_2_TID(an, bf->bf_tidno);
+ hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
+ IEEE80211_SEQ_SEQ_SHIFT);
+ bf->bf_seqno = tid->seq_next;
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
}
static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
@@ -1718,11 +1707,10 @@ static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
/* Assign seqno, tidno */
- if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR))
+ if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR))
assign_aggr_tid_seqno(skb, bf);
/* DMA setup */
-
bf->bf_mpdu = skb;
bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data,
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 350157fcd080..4223672c4432 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -3836,7 +3836,7 @@ static int reset_atmel_card(struct net_device *dev)
This routine is also responsible for initialising some
hardware-specific fields in the atmel_private structure,
including a copy of the firmware's hostinfo stucture
- which is the route into the rest of the firmare datastructures. */
+ which is the route into the rest of the firmware datastructures. */
struct atmel_private *priv = netdev_priv(dev);
u8 configuration;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 7b31a327b24a..c788bad10661 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3261,7 +3261,7 @@ static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
struct b43_wldev *down_dev;
struct b43_wldev *d;
int err;
- bool gmode;
+ bool uninitialized_var(gmode);
int prev_status;
/* Find a device and PHY which supports the band. */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c1324e31d2f6..fb996c27a19b 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2465,7 +2465,7 @@ static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev)
static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
unsigned int new_mode)
{
- struct b43legacy_wldev *up_dev;
+ struct b43legacy_wldev *uninitialized_var(up_dev);
struct b43legacy_wldev *down_dev;
int err;
bool gmode = 0;
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 1667065b86a7..823c2bf5e31e 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -1332,7 +1332,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv)
IPW_AUX_HOST_RESET_REG_STOP_MASTER);
/* Step 2. Wait for stop Master Assert
- * (not more then 50us, otherwise ret error */
+ * (not more than 50us, otherwise ret error */
i = 5;
do {
udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY);
@@ -1830,7 +1830,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
cancel_delayed_work(&priv->rf_kill);
}
- /* Kill the firmare hang check timer */
+ /* Kill the firmware hang check timer */
if (!priv->stop_hang_check) {
priv->stop_hang_check = 1;
cancel_delayed_work(&priv->hang_check);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 9b60a0c5de5f..21c841847d88 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -638,12 +638,16 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
s8 scale_action = 0;
unsigned long flags;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- u16 fc, rate_mask;
+ u16 fc;
+ u16 rate_mask = 0;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE("enter\n");
+ if (sta)
+ rate_mask = sta->supp_rates[sband->band];
+
/* Send management frames and broadcast/multicast data using lowest
* rate. */
fc = le16_to_cpu(hdr->frame_control);
@@ -651,11 +655,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
is_multicast_ether_addr(hdr->addr1) ||
!sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
- info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ if (!rate_mask)
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, NULL);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, sta);
return;
}
- rate_mask = sta->supp_rates[sband->band];
index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
if (sband->band == IEEE80211_BAND_5GHZ)
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 8fdb34222c0a..45cfa1cf194a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2219,7 +2219,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv)
/* set tx power value for all OFDM rates */
for (rate_index = 0; rate_index < IWL_OFDM_RATES;
rate_index++) {
- s32 power_idx;
+ s32 uninitialized_var(power_idx);
int rc;
/* use channel group's clip-power table,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index f3f17929ca0b..27f50471aed8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -944,7 +944,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
}
/* See if there's a better rate or modulation mode to try. */
- rs_rate_scale_perform(priv, hdr, sta, lq_sta);
+ if (sta && sta->supp_rates[sband->band])
+ rs_rate_scale_perform(priv, hdr, sta, lq_sta);
out:
return;
}
@@ -2101,14 +2102,23 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_lq_sta *lq_sta = priv_sta;
int rate_idx;
+ u64 mask_bit = 0;
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
+ if (sta)
+ mask_bit = sta->supp_rates[sband->band];
+
/* Send management frames and broadcast/multicast data using lowest
* rate. */
if (!ieee80211_is_data(hdr->frame_control) ||
is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) {
- info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ if (!mask_bit)
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, NULL);
+ else
+ info->control.rates[0].idx =
+ rate_lowest_index(sband, sta);
return;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 5da6b35cd26d..b35c8813bef4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1719,6 +1719,10 @@ static int iwl_read_ucode(struct iwl_priv *priv)
priv->ucode_data_backup.len = data_size;
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+ if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
+ !priv->ucode_data_backup.v_addr)
+ goto err_pci_alloc;
+
/* Initialization instructions and data */
if (init_size && init_data_size) {
priv->ucode_init.len = init_size;
@@ -2482,7 +2486,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb_any(skb);
IWL_DEBUG_MACDUMP("leave\n");
- return 0;
+ return NETDEV_TX_OK;
}
static int iwl_mac_add_interface(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 52966ffbef6e..ba997204c8d4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -255,7 +255,7 @@ struct iwl_cmd_header {
* 0x3) 54 Mbps
*
* Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"):
- * 3-0: 10) 1 Mbps
+ * 6-0: 10) 1 Mbps
* 20) 2 Mbps
* 55) 5.5 Mbps
* 110) 11 Mbps
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 01a2169cecec..4b35b30e493e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -51,6 +51,7 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_REMOVE_STA);
IWL_CMD(REPLY_REMOVE_ALL_STA);
IWL_CMD(REPLY_WEPKEY);
+ IWL_CMD(REPLY_3945_RX);
IWL_CMD(REPLY_TX);
IWL_CMD(REPLY_RATE_SCALE);
IWL_CMD(REPLY_LEDS_CMD);
@@ -223,7 +224,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
IWL_ERROR("Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
- goto out;
+ goto cancel;
}
ret = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index d64580805d6e..95d01984c80e 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -745,7 +745,7 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_
IWL_ERROR("Error: Response NULL in '%s'\n",
get_cmd_string(cmd->id));
ret = -EIO;
- goto out;
+ goto cancel;
}
ret = 0;
@@ -6538,7 +6538,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb_any(skb);
IWL_DEBUG_MAC80211("leave\n");
- return 0;
+ return NETDEV_TX_OK;
}
static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index e173b1b46c23..f6a79a653b7b 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -32,7 +32,7 @@ struct txpd {
u8 pktdelay_2ms;
/* reserved */
u8 reserved1;
-};
+} __attribute__ ((packed));
/* RxPD Descriptor */
struct rxpd {
@@ -63,7 +63,7 @@ struct rxpd {
/* Pkt Priority */
u8 priority;
u8 reserved[3];
-};
+} __attribute__ ((packed));
struct cmd_header {
__le16 command;
@@ -97,7 +97,7 @@ struct enc_key {
struct lbs_offset_value {
u32 offset;
u32 value;
-};
+} __attribute__ ((packed));
/* Define general data structure */
/* cmd_DS_GEN */
@@ -107,7 +107,7 @@ struct cmd_ds_gen {
__le16 seqnum;
__le16 result;
void *cmdresp[0];
-};
+} __attribute__ ((packed));
#define S_DS_GEN sizeof(struct cmd_ds_gen)
@@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event {
* bump this up a bit.
*/
uint8_t tlv[128];
-};
+} __attribute__ ((packed));
/*
* This scan handle Country Information IE(802.11d compliant)
@@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan {
mrvlietypes_chanlistparamset_t ChanListParamSet;
mrvlietypes_ratesparamset_t OpRateSet;
#endif
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_scan_rsp {
struct cmd_header hdr;
@@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp {
__le16 bssdescriptsize;
uint8_t nr_sets;
uint8_t bssdesc_and_tlvbuffer[0];
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_get_log {
struct cmd_header hdr;
@@ -206,33 +206,33 @@ struct cmd_ds_802_11_get_log {
__le32 fcserror;
__le32 txframe;
__le32 wepundecryptable;
-};
+} __attribute__ ((packed));
struct cmd_ds_mac_control {
struct cmd_header hdr;
__le16 action;
u16 reserved;
-};
+} __attribute__ ((packed));
struct cmd_ds_mac_multicast_adr {
struct cmd_header hdr;
__le16 action;
__le16 nr_of_adrs;
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_authenticate {
u8 macaddr[ETH_ALEN];
u8 authtype;
u8 reserved[10];
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_deauthenticate {
struct cmd_header hdr;
u8 macaddr[ETH_ALEN];
__le16 reasoncode;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_associate {
u8 peerstaaddr[6];
@@ -251,7 +251,7 @@ struct cmd_ds_802_11_associate {
struct cmd_ds_802_11_associate_rsp {
struct ieeetypes_assocrsp assocRsp;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_set_wep {
struct cmd_header hdr;
@@ -265,7 +265,7 @@ struct cmd_ds_802_11_set_wep {
/* 40, 128bit or TXWEP */
uint8_t keytype[4];
uint8_t keymaterial[4][16];
-};
+} __attribute__ ((packed));
struct cmd_ds_802_3_get_stat {
__le32 xmitok;
@@ -274,7 +274,7 @@ struct cmd_ds_802_3_get_stat {
__le32 rcverror;
__le32 rcvnobuffer;
__le32 rcvcrcerror;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_get_stat {
__le32 txfragmentcnt;
@@ -294,7 +294,7 @@ struct cmd_ds_802_11_get_stat {
__le32 txbeacon;
__le32 rxbeacon;
__le32 wepundecryptable;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_snmp_mib {
struct cmd_header hdr;
@@ -303,58 +303,58 @@ struct cmd_ds_802_11_snmp_mib {
__le16 oid;
__le16 bufsize;
u8 value[128];
-};
+} __attribute__ ((packed));
struct cmd_ds_mac_reg_map {
__le16 buffersize;
u8 regmap[128];
__le16 reserved;
-};
+} __attribute__ ((packed));
struct cmd_ds_bbp_reg_map {
__le16 buffersize;
u8 regmap[128];
__le16 reserved;
-};
+} __attribute__ ((packed));
struct cmd_ds_rf_reg_map {
__le16 buffersize;
u8 regmap[64];
__le16 reserved;
-};
+} __attribute__ ((packed));
struct cmd_ds_mac_reg_access {
__le16 action;
__le16 offset;
__le32 value;
-};
+} __attribute__ ((packed));
struct cmd_ds_bbp_reg_access {
__le16 action;
__le16 offset;
u8 value;
u8 reserved[3];
-};
+} __attribute__ ((packed));
struct cmd_ds_rf_reg_access {
__le16 action;
__le16 offset;
u8 value;
u8 reserved[3];
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_radio_control {
struct cmd_header hdr;
__le16 action;
__le16 control;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_beacon_control {
__le16 action;
__le16 beacon_enable;
__le16 beacon_period;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_sleep_params {
struct cmd_header hdr;
@@ -379,7 +379,7 @@ struct cmd_ds_802_11_sleep_params {
/* reserved field, should be set to zero */
__le16 reserved;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_inactivity_timeout {
struct cmd_header hdr;
@@ -389,7 +389,7 @@ struct cmd_ds_802_11_inactivity_timeout {
/* Inactivity timeout in msec */
__le16 timeout;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_rf_channel {
struct cmd_header hdr;
@@ -399,7 +399,7 @@ struct cmd_ds_802_11_rf_channel {
__le16 rftype; /* unused */
__le16 reserved; /* unused */
u8 channellist[32]; /* unused */
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_rssi {
/* weighting factor */
@@ -408,21 +408,21 @@ struct cmd_ds_802_11_rssi {
__le16 reserved_0;
__le16 reserved_1;
__le16 reserved_2;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_rssi_rsp {
__le16 SNR;
__le16 noisefloor;
__le16 avgSNR;
__le16 avgnoisefloor;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_mac_address {
struct cmd_header hdr;
__le16 action;
u8 macadd[ETH_ALEN];
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_rf_tx_power {
struct cmd_header hdr;
@@ -431,7 +431,7 @@ struct cmd_ds_802_11_rf_tx_power {
__le16 curlevel;
s8 maxlevel;
s8 minlevel;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_rf_antenna {
__le16 action;
@@ -439,33 +439,33 @@ struct cmd_ds_802_11_rf_antenna {
/* Number of antennas or 0xffff(diversity) */
__le16 antennamode;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_monitor_mode {
__le16 action;
__le16 mode;
-};
+} __attribute__ ((packed));
struct cmd_ds_set_boot2_ver {
struct cmd_header hdr;
__le16 action;
__le16 version;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_fw_wake_method {
struct cmd_header hdr;
__le16 action;
__le16 method;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_sleep_period {
struct cmd_header hdr;
__le16 action;
__le16 period;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_ps_mode {
__le16 action;
@@ -473,7 +473,7 @@ struct cmd_ds_802_11_ps_mode {
__le16 multipledtim;
__le16 reserved;
__le16 locallisteninterval;
-};
+} __attribute__ ((packed));
struct cmd_confirm_sleep {
struct cmd_header hdr;
@@ -483,7 +483,7 @@ struct cmd_confirm_sleep {
__le16 multipledtim;
__le16 reserved;
__le16 locallisteninterval;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_data_rate {
struct cmd_header hdr;
@@ -491,14 +491,14 @@ struct cmd_ds_802_11_data_rate {
__le16 action;
__le16 reserved;
u8 rates[MAX_RATES];
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_rate_adapt_rateset {
struct cmd_header hdr;
__le16 action;
__le16 enablehwauto;
__le16 bitmap;
-};
+} __attribute__ ((packed));
struct cmd_ds_802_11_ad_hoc_start {
struct cmd_header hdr;
@@ -520,7 +520,7 @@ struct cmd_ds_802_11_ad_hoc_result {
u8 pad[3];
u8 bssid[ETH_ALEN];
-};
+} __attribute__ ((packed));
struct adhoc_bssdesc {
u8 bssid[ETH_ALEN];
@@ -578,7 +578,7 @@ struct MrvlIEtype_keyParamSet {
/* key material of size keylen */
u8 key[32];
-};
+} __attribute__ ((packed));
#define MAX_WOL_RULES 16
@@ -590,7 +590,7 @@ struct host_wol_rule {
__le16 reserve;
__be32 sig_mask;
__be32 signature;
-};
+} __attribute__ ((packed));
struct wol_config {
uint8_t action;
@@ -598,8 +598,7 @@ struct wol_config {
uint8_t no_rules_in_cmd;
uint8_t result;
struct host_wol_rule rule[MAX_WOL_RULES];
-};
-
+} __attribute__ ((packed));
struct cmd_ds_host_sleep {
struct cmd_header hdr;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 3dba83679444..4e0007d20030 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1369,7 +1369,7 @@ EXPORT_SYMBOL_GPL(lbs_start_card);
void lbs_stop_card(struct lbs_private *priv)
{
- struct net_device *dev = priv->dev;
+ struct net_device *dev;
struct cmd_ctrl_node *cmdnode;
unsigned long flags;
@@ -1377,9 +1377,10 @@ void lbs_stop_card(struct lbs_private *priv)
if (!priv)
goto out;
+ dev = priv->dev;
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
lbs_debugfs_remove_one(priv);
if (priv->mesh_tlv) {
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index d1fc305de5fe..e7289e2e7f16 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -206,7 +206,7 @@ static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* there are no buffered multicast frames to send
*/
ieee80211_stop_queues(priv->hw);
- return 0;
+ return NETDEV_TX_OK;
}
static void lbtf_tx_work(struct work_struct *work)
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
index bc84e2792f8a..45a04faa7818 100644
--- a/drivers/net/wireless/orinoco/orinoco.c
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -1610,6 +1610,16 @@ static void orinoco_rx_isr_tasklet(unsigned long data)
struct orinoco_rx_data *rx_data, *temp;
struct hermes_rx_descriptor *desc;
struct sk_buff *skb;
+ unsigned long flags;
+
+ /* orinoco_rx requires the driver lock, and we also need to
+ * protect priv->rx_list, so just hold the lock over the
+ * lot.
+ *
+ * If orinoco_lock fails, we've unplugged the card. In this
+ * case just abort. */
+ if (orinoco_lock(priv, &flags) != 0)
+ return;
/* extract desc and skb from queue */
list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
@@ -1622,6 +1632,8 @@ static void orinoco_rx_isr_tasklet(unsigned long data)
kfree(desc);
}
+
+ orinoco_unlock(priv, &flags);
}
/********************************************************************/
@@ -1661,7 +1673,7 @@ static void print_linkstatus(struct net_device *dev, u16 status)
s = "UNKNOWN";
}
- printk(KERN_INFO "%s: New link status: %s (%04x)\n",
+ printk(KERN_DEBUG "%s: New link status: %s (%04x)\n",
dev->name, s, status);
}
@@ -3645,12 +3657,22 @@ struct net_device
void free_orinocodev(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
+ struct orinoco_rx_data *rx_data, *temp;
- /* No need to empty priv->rx_list: if the tasklet is scheduled
- * when we call tasklet_kill it will run one final time,
- * emptying the list */
+ /* If the tasklet is scheduled when we call tasklet_kill it
+ * will run one final time. However the tasklet will only
+ * drain priv->rx_list if the hw is still available. */
tasklet_kill(&priv->rx_tasklet);
+ /* Explicitly drain priv->rx_list */
+ list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
+ list_del(&rx_data->list);
+
+ dev_kfree_skb(rx_data->skb);
+ kfree(rx_data->desc);
+ kfree(rx_data);
+ }
+
unregister_pm_notifier(&priv->pm_notifier);
orinoco_uncache_fw(priv);
@@ -5046,33 +5068,30 @@ static int orinoco_ioctl_set_genie(struct net_device *dev,
struct orinoco_private *priv = netdev_priv(dev);
u8 *buf;
unsigned long flags;
- int err = 0;
/* cut off at IEEE80211_MAX_DATA_LEN */
if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
(wrqu->data.length && (extra == NULL)))
return -EINVAL;
- if (orinoco_lock(priv, &flags) != 0)
- return -EBUSY;
-
if (wrqu->data.length) {
buf = kmalloc(wrqu->data.length, GFP_KERNEL);
- if (buf == NULL) {
- err = -ENOMEM;
- goto out;
- }
+ if (buf == NULL)
+ return -ENOMEM;
memcpy(buf, extra, wrqu->data.length);
- kfree(priv->wpa_ie);
- priv->wpa_ie = buf;
- priv->wpa_ie_len = wrqu->data.length;
- } else {
- kfree(priv->wpa_ie);
- priv->wpa_ie = NULL;
- priv->wpa_ie_len = 0;
+ } else
+ buf = NULL;
+
+ if (orinoco_lock(priv, &flags) != 0) {
+ kfree(buf);
+ return -EBUSY;
}
+ kfree(priv->wpa_ie);
+ priv->wpa_ie = buf;
+ priv->wpa_ie_len = wrqu->data.length;
+
if (priv->wpa_ie) {
/* Looks like wl_lkm wants to check the auth alg, and
* somehow pass it to the firmware.
@@ -5081,9 +5100,8 @@ static int orinoco_ioctl_set_genie(struct net_device *dev,
*/
}
-out:
orinoco_unlock(priv, &flags);
- return err;
+ return 0;
}
static int orinoco_ioctl_get_genie(struct net_device *dev,
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index f127602670ec..0b32215d3f5d 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -435,6 +435,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
+ PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */
PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 82354b974a04..34561e6e816b 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -138,6 +138,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
u8 *fw_version = NULL;
size_t len;
int i;
+ int maxlen;
if (priv->rx_start)
return 0;
@@ -195,6 +196,16 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
else
priv->rx_mtu = (size_t)
0x620 - priv->tx_hdr_len;
+ maxlen = priv->tx_hdr_len + /* USB devices */
+ sizeof(struct p54_rx_data) +
+ 4 + /* rx alignment */
+ IEEE80211_MAX_FRAG_THRESHOLD;
+ if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) {
+ printk(KERN_INFO "p54: rx_mtu reduced from %d "
+ "to %d\n", priv->rx_mtu,
+ maxlen);
+ priv->rx_mtu = maxlen;
+ }
break;
}
case BR_CODE_EXPOSED_IF:
@@ -440,8 +451,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
}
if (err)
goto err;
-
- }
+ }
+ break;
case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
if (!priv->iq_autocal) {
@@ -575,6 +586,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
u16 freq = le16_to_cpu(hdr->freq);
size_t header_len = sizeof(*hdr);
u32 tsf32;
+ u8 rate = hdr->rate & 0xf;
/*
* If the device is in a unspecified state we have to
@@ -603,8 +615,11 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
rx_status.qual = (100 * hdr->rssi) / 127;
if (hdr->rate & 0x10)
rx_status.flag |= RX_FLAG_SHORTPRE;
- rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ?
- hdr->rate : (hdr->rate - 4)) & 0xf;
+ if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
+ rx_status.rate_idx = (rate < 4) ? 0 : rate - 4;
+ else
+ rx_status.rate_idx = rate;
+
rx_status.freq = freq;
rx_status.band = dev->conf.channel->band;
rx_status.antenna = hdr->antenna;
@@ -730,7 +745,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
struct p54_hdr *entry_hdr;
struct p54_tx_data *entry_data;
- int pad = 0;
+ unsigned int pad = 0, frame_len;
range = (void *)info->rate_driver_data;
if (range->start_addr != addr) {
@@ -753,6 +768,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
__skb_unlink(entry, &priv->tx_queue);
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ frame_len = entry->len;
entry_hdr = (struct p54_hdr *) entry->data;
entry_data = (struct p54_tx_data *) entry_hdr->data;
priv->tx_stats[entry_data->hw_queue].len--;
@@ -798,6 +814,29 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
info->status.ack_signal = p54_rssi_to_dbm(dev,
(int)payload->ack_rssi);
+
+ /* Undo all changes to the frame. */
+ switch (entry_data->key_type) {
+ case P54_CRYPTO_TKIPMICHAEL: {
+ u8 *iv = (u8 *)(entry_data->align + pad +
+ entry_data->crypt_offset);
+
+ /* Restore the original TKIP IV. */
+ iv[2] = iv[0];
+ iv[0] = iv[1];
+ iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */
+
+ frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */
+ break;
+ }
+ case P54_CRYPTO_AESCCMP:
+ frame_len -= 8; /* remove CCMP_MIC */
+ break;
+ case P54_CRYPTO_WEP:
+ frame_len -= 4; /* remove WEP_ICV */
+ break;
+ }
+ skb_trim(entry, frame_len);
skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
ieee80211_tx_status_irqsafe(dev, entry);
goto out;
@@ -1122,7 +1161,7 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
sizeof(struct p54_hdr) + sizeof(*tim),
- P54_CONTROL_TYPE_TIM, GFP_KERNEL);
+ P54_CONTROL_TYPE_TIM, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
@@ -1383,7 +1422,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
hdr->tries = ridx;
txhdr->rts_rate_idx = 0;
if (info->control.hw_key) {
- crypt_offset += info->control.hw_key->iv_len;
txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
@@ -1397,6 +1435,8 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
}
/* reserve some space for ICV */
len += info->control.hw_key->icv_len;
+ memset(skb_put(skb, info->control.hw_key->icv_len), 0,
+ info->control.hw_key->icv_len);
} else {
txhdr->key_type = 0;
txhdr->key_len = 0;
@@ -1584,7 +1624,7 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
err:
printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
- kfree_skb(skb);
+ p54_free_skb(dev, skb);
return -EINVAL;
}
@@ -1824,7 +1864,7 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
static int p54_config(struct ieee80211_hw *dev, u32 changed)
{
- int ret;
+ int ret = 0;
struct p54_common *priv = dev->priv;
struct ieee80211_conf *conf = &dev->conf;
@@ -2051,7 +2091,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
algo = P54_CRYPTO_AESCCMP;
break;
default:
- return -EINVAL;
+ return -EOPNOTSUPP;
}
}
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index c44a200059d2..5de2ebfb28c7 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
{USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
{USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
{USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
+ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
{USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
@@ -143,11 +144,8 @@ static void p54u_tx_cb(struct urb *urb)
struct sk_buff *skb = urb->context;
struct ieee80211_hw *dev = (struct ieee80211_hw *)
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
- struct p54u_priv *priv = dev->priv;
- skb_pull(skb, priv->common.tx_hdr_len);
- if (FREE_AFTER_TX(skb))
- p54_free_skb(dev, skb);
+ p54_free_skb(dev, skb);
}
static void p54u_tx_dummy_cb(struct urb *urb) { }
@@ -229,7 +227,10 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb)
p54u_tx_dummy_cb, dev);
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
- skb->data, skb->len, p54u_tx_cb, skb);
+ skb->data, skb->len, FREE_AFTER_TX(skb) ?
+ p54u_tx_cb : p54u_tx_dummy_cb, skb);
+ addr_urb->transfer_flags |= URB_ZERO_PACKET;
+ data_urb->transfer_flags |= URB_ZERO_PACKET;
usb_anchor_urb(addr_urb, &priv->submitted);
err = usb_submit_urb(addr_urb, GFP_ATOMIC);
@@ -238,7 +239,7 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb)
goto out;
}
- usb_anchor_urb(addr_urb, &priv->submitted);
+ usb_anchor_urb(data_urb, &priv->submitted);
err = usb_submit_urb(data_urb, GFP_ATOMIC);
if (err)
usb_unanchor_urb(data_urb);
@@ -268,27 +269,24 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
struct urb *data_urb;
- struct lm87_tx_hdr *hdr;
- __le32 checksum;
- __le32 addr = ((struct p54_hdr *)skb->data)->req_id;
+ struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
data_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!data_urb)
return;
- checksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
- hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
- hdr->chksum = checksum;
- hdr->device_addr = addr;
+ hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
+ hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
- skb->data, skb->len, p54u_tx_cb, skb);
+ hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
+ p54u_tx_cb : p54u_tx_dummy_cb, skb);
+ data_urb->transfer_flags |= URB_ZERO_PACKET;
usb_anchor_urb(data_urb, &priv->submitted);
if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
usb_unanchor_urb(data_urb);
- skb_pull(skb, sizeof(*hdr));
p54_free_skb(dev, skb);
}
usb_free_urb(data_urb);
@@ -298,11 +296,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
struct urb *int_urb, *data_urb;
- struct net2280_tx_hdr *hdr;
+ struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
struct net2280_reg_write *reg;
int err = 0;
- __le32 addr = ((struct p54_hdr *) skb->data)->req_id;
- __le16 len = cpu_to_le16(skb->len);
reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
if (!reg)
@@ -325,10 +321,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
reg->addr = cpu_to_le32(P54U_DEV_BASE);
reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
- hdr = (void *)skb_push(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(*hdr));
- hdr->len = len;
- hdr->device_addr = addr;
+ hdr->len = cpu_to_le16(skb->len);
+ hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id;
usb_fill_bulk_urb(int_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
@@ -339,11 +334,13 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
* free what's inside the transfer_buffer after the callback routine
* has completed.
*/
- int_urb->transfer_flags |= URB_FREE_BUFFER;
+ int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET;
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
- skb->data, skb->len, p54u_tx_cb, skb);
+ hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
+ p54u_tx_cb : p54u_tx_dummy_cb, skb);
+ data_urb->transfer_flags |= URB_ZERO_PACKET;
usb_anchor_urb(int_urb, &priv->submitted);
err = usb_submit_urb(int_urb, GFP_ATOMIC);
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 607ce9f61b54..ed93ac41297f 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1649,9 +1649,7 @@ static char *rndis_translate_scan(struct net_device *dev,
char *end_buf,
struct ndis_80211_bssid_ex *bssid)
{
-#ifdef DEBUG
struct usbnet *usbdev = netdev_priv(dev);
-#endif
u8 *ie;
char *current_val;
int bssid_len, ie_len, i;
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 30028e2422fc..af6b5847be5c 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -38,7 +38,7 @@
/*
* Allow hardware encryption to be disabled.
*/
-static int modparam_nohwcrypt = 1;
+static int modparam_nohwcrypt = 0;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@ -376,11 +376,11 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
/*
* The driver does not support the IV/EIV generation
- * in hardware. However it doesn't support the IV/EIV
- * inside the ieee80211 frame either, but requires it
- * to be provided seperately for the descriptor.
- * rt2x00lib will cut the IV/EIV data out of all frames
- * given to us by mac80211, but we must tell mac80211
+ * in hardware. However it demands the data to be provided
+ * both seperately as well as inside the frame.
+ * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib
+ * to ensure rt2x00lib will not strip the data from the
+ * frame after the copy, now we must tell mac80211
* to generate the IV/EIV data.
*/
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
@@ -1181,7 +1181,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
- rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher);
+ rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
rt2x00_desc_write(txd, 0, word);
}
@@ -1334,14 +1334,7 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
/* ICV is located at the end of frame */
- /*
- * Hardware has stripped IV/EIV data from 802.11 frame during
- * decryption. It has provided the data seperately but rt2x00lib
- * should decide if it should be reinserted.
- */
- rxdesc->flags |= RX_FLAG_IV_STRIPPED;
- if (rxdesc->cipher != CIPHER_TKIP)
- rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
rxdesc->flags |= RX_FLAG_DECRYPTED;
else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 37ad0d2fb64c..aee9cba13eb3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -184,8 +184,8 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
* Make room for new data, note that we increase both
* headsize and tailsize when required. The tailsize is
* only needed when ICV data needs to be inserted and
- * the padding is smaller then the ICV data.
- * When alignment requirements is greater then the
+ * the padding is smaller than the ICV data.
+ * When alignment requirements is greater than the
* ICV data we must trim the skb to the correct size
* because we need to remove the extra bytes.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 6d92542fcf0d..87c0f2c83077 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -807,13 +807,11 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
{
entry->flags = 0;
entry->bitrate = rate->bitrate;
- entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
- entry->hw_value_short = entry->hw_value;
+ entry->hw_value =index;
+ entry->hw_value_short = index;
- if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
+ if (rate->flags & DEV_RATE_SHORT_PREAMBLE)
entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
- entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
- }
}
static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
index 68f4e0fc35b9..a0cd35b6beb5 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -97,7 +97,7 @@ void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
{
- if (rt2x00dev->led_radio.type == LED_TYPE_ASSOC)
+ if (rt2x00dev->led_radio.type == LED_TYPE_RADIO)
rt2x00led_led_simple(&rt2x00dev->led_radio, enabled);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 03024327767b..86cd26fbf769 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -52,22 +52,11 @@ struct rt2x00_rate {
extern const struct rt2x00_rate rt2x00_supported_rates[12];
-static inline u16 rt2x00_create_rate_hw_value(const u16 index,
- const u16 short_preamble)
-{
- return (short_preamble << 8) | (index & 0xff);
-}
-
static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
{
return &rt2x00_supported_rates[hw_value & 0xff];
}
-static inline int rt2x00_get_rate_preamble(const u16 hw_value)
-{
- return (hw_value & 0xff00);
-}
-
/*
* Radio control handlers.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index eaec6bd93ed5..0709decec9c2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -154,6 +154,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
+ struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
struct ieee80211_rate *rate =
ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
const struct rt2x00_rate *hwrate;
@@ -313,7 +314,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
* When preamble is enabled we should set the
* preamble bit for the signal.
*/
- if (rt2x00_get_rate_preamble(rate->hw_value))
+ if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
txdesc->signal |= 0x08;
}
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
index c3f53a92180a..3298cae1e12d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
@@ -162,7 +162,7 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
{
- if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->flags))
+ if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
return;
cancel_delayed_work_sync(&rt2x00dev->rfkill_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 83df312ac56f..0b29d767a258 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -434,11 +434,11 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
if (usb_endpoint_is_bulk_in(ep_desc)) {
rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
- } else if (usb_endpoint_is_bulk_out(ep_desc)) {
+ } else if (usb_endpoint_is_bulk_out(ep_desc) &&
+ (queue != queue_end(rt2x00dev))) {
rt2x00usb_assign_endpoint(queue, ep_desc);
+ queue = queue_next(queue);
- if (queue != queue_end(rt2x00dev))
- queue = queue_next(queue);
tx_ep_desc = ep_desc;
}
}
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index d638a8a59370..96a8d69f8790 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2321,6 +2321,7 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Linksys */
{ USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
/* MSI */
{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index 5f887fb137a9..387c133ec0f2 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -897,6 +897,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SIGNAL_UNSPEC;
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
dev->queues = 1;
dev->max_signal = 65;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 00ce3ef39abe..22bc07ef2f37 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -213,7 +213,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
kfree_skb(skb);
- return -ENOMEM;
+ return NETDEV_TX_OK;
}
flags = skb->len;
@@ -273,6 +273,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
buf, skb->len, rtl8187_tx_cb, skb);
+ urb->transfer_flags |= URB_ZERO_PACKET;
usb_anchor_urb(urb, &priv->anchored);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0) {
@@ -281,7 +282,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
}
usb_free_urb(urb);
- return rc;
+ return NETDEV_TX_OK;
}
static void rtl8187_rx_cb(struct urb *urb)
@@ -1471,6 +1472,7 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
ieee80211_unregister_hw(dev);
priv = dev->priv;
+ usb_reset_device(priv->udev);
usb_put_dev(interface_to_usbdev(intf));
ieee80211_free_hw(dev);
}
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
index 4e75e8e7fa90..78df281b297a 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
@@ -285,7 +285,10 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
ofdm_power = priv->channels[channel - 1].hw_value >> 4;
cck_power = min(cck_power, (u8)11);
- ofdm_power = min(ofdm_power, (u8)35);
+ if (ofdm_power > (u8)15)
+ ofdm_power = 25;
+ else
+ ofdm_power += 10;
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
@@ -536,7 +539,10 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
cck_power += priv->txpwr_base & 0xF;
cck_power = min(cck_power, (u8)35);
- ofdm_power = min(ofdm_power, (u8)15);
+ if (ofdm_power > (u8)15)
+ ofdm_power = 25;
+ else
+ ofdm_power += 10;
ofdm_power += priv->txpwr_base >> 4;
ofdm_power = min(ofdm_power, (u8)35);
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index dd0de3a9ed4e..7015f2480550 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -236,7 +236,7 @@ struct strip {
unsigned long tx_errors; /* Planned stuff */
unsigned long rx_dropped; /* No memory for skb */
unsigned long tx_dropped; /* When MTU change */
- unsigned long rx_over_errors; /* Frame bigger then STRIP buf. */
+ unsigned long rx_over_errors; /* Frame bigger than STRIP buf. */
unsigned long pps_timer; /* Timer to determine pps */
unsigned long rx_pps_count; /* Counter to determine pps */
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 9caa96a13586..a611ad857983 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -287,7 +287,7 @@ static void zd_op_stop(struct ieee80211_hw *hw)
* @skb - a sk-buffer
* @flags: extra flags to set in the TX status info
* @ackssi: ACK signal strength
- * @success - True for successfull transmission of the frame
+ * @success - True for successful transmission of the frame
*
* This information calls ieee80211_tx_status_irqsafe() if required by the
* control information. It copies the control information into the status
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index b5db57d2fcf5..17527f765b39 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -84,6 +84,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
+ { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B },
/* "Driverless" devices that need ejecting */
{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
{ USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 761635be9104..cd6184ee08ee 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1105,6 +1105,16 @@ static void xennet_uninit(struct net_device *dev)
gnttab_free_grant_references(np->gref_rx_head);
}
+static const struct net_device_ops xennet_netdev_ops = {
+ .ndo_open = xennet_open,
+ .ndo_uninit = xennet_uninit,
+ .ndo_stop = xennet_close,
+ .ndo_start_xmit = xennet_start_xmit,
+ .ndo_change_mtu = xennet_change_mtu,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev)
{
int i, err;
@@ -1161,12 +1171,9 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
goto exit_free_tx;
}
- netdev->open = xennet_open;
- netdev->hard_start_xmit = xennet_start_xmit;
- netdev->stop = xennet_close;
+ netdev->netdev_ops = &xennet_netdev_ops;
+
netif_napi_add(netdev, &np->napi, xennet_poll, 64);
- netdev->uninit = xennet_uninit;
- netdev->change_mtu = xennet_change_mtu;
netdev->features = NETIF_F_IP_CSUM;
SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index cf9712922778..2f1645dcb8c8 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -362,6 +362,7 @@ static const struct net_device_ops netdev_ops = {
.ndo_set_multicast_list = set_rx_mode,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl = netdev_ioctl,
.ndo_tx_timeout = yellowfin_tx_timeout,
};
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index affd904deafc..37c84e3b8be0 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -147,6 +147,7 @@ static const struct net_device_ops zorro8390_netdev_ops = {
.ndo_get_stats = ei_get_stats,
.ndo_set_multicast_list = ei_set_multicast_list,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = eth_change_mtu,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ei_poll,
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index e1b0ad6e918f..fa65a2b2ae2e 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -66,4 +66,23 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
}
EXPORT_SYMBOL(of_register_i2c_devices);
+static int of_dev_node_match(struct device *dev, void *data)
+{
+ return dev_archdata_get_node(&dev->archdata) == data;
+}
+
+/* must call put_device() when done with returned i2c_client device */
+struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
+{
+ struct device *dev;
+
+ dev = bus_find_device(&i2c_bus_type, NULL, node,
+ of_dev_node_match);
+ if (!dev)
+ return NULL;
+
+ return to_i2c_client(dev);
+}
+EXPORT_SYMBOL(of_find_i2c_device_by_node);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 737bd9484822..9da5a4b81133 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -1,11 +1,12 @@
/**
* @file buffer_sync.c
*
- * @remark Copyright 2002 OProfile authors
+ * @remark Copyright 2002-2009 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
* @author Barry Kasindorf
+ * @author Robert Richter <robert.richter@amd.com>
*
* This is the core of the buffer management. Each
* CPU buffer is processed and entered into the
@@ -200,7 +201,7 @@ static inline unsigned long fast_get_dcookie(struct path *path)
{
unsigned long cookie;
- if (path->dentry->d_cookie)
+ if (path->dentry->d_flags & DCACHE_COOKIE)
return (unsigned long)path->dentry;
get_dcookie(path, &cookie);
return cookie;
@@ -315,88 +316,73 @@ static void add_trace_begin(void)
add_event_entry(TRACE_BEGIN_CODE);
}
-#ifdef CONFIG_OPROFILE_IBS
-
-#define IBS_FETCH_CODE_SIZE 2
-#define IBS_OP_CODE_SIZE 5
-
-/*
- * Add IBS fetch and op entries to event buffer
- */
-static void add_ibs_begin(int cpu, int code, struct mm_struct *mm)
+static void add_data(struct op_entry *entry, struct mm_struct *mm)
{
- unsigned long rip;
- int i, count;
- unsigned long ibs_cookie = 0;
+ unsigned long code, pc, val;
+ unsigned long cookie;
off_t offset;
- struct op_sample *sample;
-
- sample = cpu_buffer_read_entry(cpu);
- if (!sample)
- goto Error;
- rip = sample->eip;
-#ifdef __LP64__
- rip += sample->event << 32;
-#endif
+ if (!op_cpu_buffer_get_data(entry, &code))
+ return;
+ if (!op_cpu_buffer_get_data(entry, &pc))
+ return;
+ if (!op_cpu_buffer_get_size(entry))
+ return;
if (mm) {
- ibs_cookie = lookup_dcookie(mm, rip, &offset);
+ cookie = lookup_dcookie(mm, pc, &offset);
- if (ibs_cookie == NO_COOKIE)
- offset = rip;
- if (ibs_cookie == INVALID_COOKIE) {
+ if (cookie == NO_COOKIE)
+ offset = pc;
+ if (cookie == INVALID_COOKIE) {
atomic_inc(&oprofile_stats.sample_lost_no_mapping);
- offset = rip;
+ offset = pc;
}
- if (ibs_cookie != last_cookie) {
- add_cookie_switch(ibs_cookie);
- last_cookie = ibs_cookie;
+ if (cookie != last_cookie) {
+ add_cookie_switch(cookie);
+ last_cookie = cookie;
}
} else
- offset = rip;
+ offset = pc;
add_event_entry(ESCAPE_CODE);
add_event_entry(code);
add_event_entry(offset); /* Offset from Dcookie */
- /* we send the Dcookie offset, but send the raw Linear Add also*/
- add_event_entry(sample->eip);
- add_event_entry(sample->event);
-
- if (code == IBS_FETCH_CODE)
- count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/
- else
- count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/
-
- for (i = 0; i < count; i++) {
- sample = cpu_buffer_read_entry(cpu);
- if (!sample)
- goto Error;
- add_event_entry(sample->eip);
- add_event_entry(sample->event);
- }
-
- return;
-
-Error:
- return;
+ while (op_cpu_buffer_get_data(entry, &val))
+ add_event_entry(val);
}
-#endif
-
-static void add_sample_entry(unsigned long offset, unsigned long event)
+static inline void add_sample_entry(unsigned long offset, unsigned long event)
{
add_event_entry(offset);
add_event_entry(event);
}
-static int add_us_sample(struct mm_struct *mm, struct op_sample *s)
+/*
+ * Add a sample to the global event buffer. If possible the
+ * sample is converted into a persistent dentry/offset pair
+ * for later lookup from userspace. Return 0 on failure.
+ */
+static int
+add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)
{
unsigned long cookie;
off_t offset;
+ if (in_kernel) {
+ add_sample_entry(s->eip, s->event);
+ return 1;
+ }
+
+ /* add userspace sample */
+
+ if (!mm) {
+ atomic_inc(&oprofile_stats.sample_lost_no_mm);
+ return 0;
+ }
+
cookie = lookup_dcookie(mm, s->eip, &offset);
if (cookie == INVALID_COOKIE) {
@@ -415,25 +401,6 @@ static int add_us_sample(struct mm_struct *mm, struct op_sample *s)
}
-/* Add a sample to the global event buffer. If possible the
- * sample is converted into a persistent dentry/offset pair
- * for later lookup from userspace.
- */
-static int
-add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel)
-{
- if (in_kernel) {
- add_sample_entry(s->eip, s->event);
- return 1;
- } else if (mm) {
- return add_us_sample(mm, s);
- } else {
- atomic_inc(&oprofile_stats.sample_lost_no_mm);
- }
- return 0;
-}
-
-
static void release_mm(struct mm_struct *mm)
{
if (!mm)
@@ -526,66 +493,69 @@ void sync_buffer(int cpu)
{
struct mm_struct *mm = NULL;
struct mm_struct *oldmm;
+ unsigned long val;
struct task_struct *new;
unsigned long cookie = 0;
int in_kernel = 1;
sync_buffer_state state = sb_buffer_start;
unsigned int i;
unsigned long available;
+ unsigned long flags;
+ struct op_entry entry;
+ struct op_sample *sample;
mutex_lock(&buffer_mutex);
add_cpu_switch(cpu);
- cpu_buffer_reset(cpu);
- available = cpu_buffer_entries(cpu);
+ op_cpu_buffer_reset(cpu);
+ available = op_cpu_buffer_entries(cpu);
for (i = 0; i < available; ++i) {
- struct op_sample *s = cpu_buffer_read_entry(cpu);
- if (!s)
+ sample = op_cpu_buffer_read_entry(&entry, cpu);
+ if (!sample)
break;
- if (is_code(s->eip)) {
- switch (s->event) {
- case 0:
- case CPU_IS_KERNEL:
+ if (is_code(sample->eip)) {
+ flags = sample->event;
+ if (flags & TRACE_BEGIN) {
+ state = sb_bt_start;
+ add_trace_begin();
+ }
+ if (flags & KERNEL_CTX_SWITCH) {
/* kernel/userspace switch */
- in_kernel = s->event;
+ in_kernel = flags & IS_KERNEL;
if (state == sb_buffer_start)
state = sb_sample_start;
- add_kernel_ctx_switch(s->event);
- break;
- case CPU_TRACE_BEGIN:
- state = sb_bt_start;
- add_trace_begin();
- break;
-#ifdef CONFIG_OPROFILE_IBS
- case IBS_FETCH_BEGIN:
- state = sb_bt_start;
- add_ibs_begin(cpu, IBS_FETCH_CODE, mm);
- break;
- case IBS_OP_BEGIN:
- state = sb_bt_start;
- add_ibs_begin(cpu, IBS_OP_CODE, mm);
- break;
-#endif
- default:
+ add_kernel_ctx_switch(flags & IS_KERNEL);
+ }
+ if (flags & USER_CTX_SWITCH
+ && op_cpu_buffer_get_data(&entry, &val)) {
/* userspace context switch */
+ new = (struct task_struct *)val;
oldmm = mm;
- new = (struct task_struct *)s->event;
release_mm(oldmm);
mm = take_tasks_mm(new);
if (mm != oldmm)
cookie = get_exec_dcookie(mm);
add_user_ctx_switch(new, cookie);
- break;
- }
- } else if (state >= sb_bt_start &&
- !add_sample(mm, s, in_kernel)) {
- if (state == sb_bt_start) {
- state = sb_bt_ignore;
- atomic_inc(&oprofile_stats.bt_lost_no_mapping);
}
+ if (op_cpu_buffer_get_size(&entry))
+ add_data(&entry, mm);
+ continue;
+ }
+
+ if (state < sb_bt_start)
+ /* ignore sample */
+ continue;
+
+ if (add_sample(mm, sample, in_kernel))
+ continue;
+
+ /* ignore backtraces if failed to add a sample */
+ if (state == sb_bt_start) {
+ state = sb_bt_ignore;
+ atomic_inc(&oprofile_stats.bt_lost_no_mapping);
}
}
release_mm(mm);
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 61090969158f..e76d715e4342 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -1,11 +1,12 @@
/**
* @file cpu_buffer.c
*
- * @remark Copyright 2002 OProfile authors
+ * @remark Copyright 2002-2009 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
* @author Barry Kasindorf <barry.kasindorf@amd.com>
+ * @author Robert Richter <robert.richter@amd.com>
*
* Each CPU has a local buffer that stores PC value/event
* pairs. We also log context switches when we notice them.
@@ -45,8 +46,8 @@
* can be changed to a single buffer solution when the ring buffer
* access is implemented as non-locking atomic code.
*/
-struct ring_buffer *op_ring_buffer_read;
-struct ring_buffer *op_ring_buffer_write;
+static struct ring_buffer *op_ring_buffer_read;
+static struct ring_buffer *op_ring_buffer_write;
DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
static void wq_sync_buffer(struct work_struct *work);
@@ -54,19 +55,9 @@ static void wq_sync_buffer(struct work_struct *work);
#define DEFAULT_TIMER_EXPIRE (HZ / 10)
static int work_enabled;
-void free_cpu_buffers(void)
-{
- if (op_ring_buffer_read)
- ring_buffer_free(op_ring_buffer_read);
- op_ring_buffer_read = NULL;
- if (op_ring_buffer_write)
- ring_buffer_free(op_ring_buffer_write);
- op_ring_buffer_write = NULL;
-}
-
unsigned long oprofile_get_cpu_buffer_size(void)
{
- return fs_cpu_buffer_size;
+ return oprofile_cpu_buffer_size;
}
void oprofile_cpu_buffer_inc_smpl_lost(void)
@@ -77,11 +68,21 @@ void oprofile_cpu_buffer_inc_smpl_lost(void)
cpu_buf->sample_lost_overflow++;
}
+void free_cpu_buffers(void)
+{
+ if (op_ring_buffer_read)
+ ring_buffer_free(op_ring_buffer_read);
+ op_ring_buffer_read = NULL;
+ if (op_ring_buffer_write)
+ ring_buffer_free(op_ring_buffer_write);
+ op_ring_buffer_write = NULL;
+}
+
int alloc_cpu_buffers(void)
{
int i;
- unsigned long buffer_size = fs_cpu_buffer_size;
+ unsigned long buffer_size = oprofile_cpu_buffer_size;
op_ring_buffer_read = ring_buffer_alloc(buffer_size, OP_BUFFER_FLAGS);
if (!op_ring_buffer_read)
@@ -97,8 +98,6 @@ int alloc_cpu_buffers(void)
b->last_is_kernel = -1;
b->tracing = 0;
b->buffer_size = buffer_size;
- b->tail_pos = 0;
- b->head_pos = 0;
b->sample_received = 0;
b->sample_lost_overflow = 0;
b->backtrace_aborted = 0;
@@ -145,47 +144,156 @@ void end_cpu_work(void)
flush_scheduled_work();
}
-static inline int
-add_sample(struct oprofile_cpu_buffer *cpu_buf,
- unsigned long pc, unsigned long event)
+/*
+ * This function prepares the cpu buffer to write a sample.
+ *
+ * Struct op_entry is used during operations on the ring buffer while
+ * struct op_sample contains the data that is stored in the ring
+ * buffer. Struct entry can be uninitialized. The function reserves a
+ * data array that is specified by size. Use
+ * op_cpu_buffer_write_commit() after preparing the sample. In case of
+ * errors a null pointer is returned, otherwise the pointer to the
+ * sample.
+ *
+ */
+struct op_sample
+*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size)
+{
+ entry->event = ring_buffer_lock_reserve
+ (op_ring_buffer_write, sizeof(struct op_sample) +
+ size * sizeof(entry->sample->data[0]), &entry->irq_flags);
+ if (entry->event)
+ entry->sample = ring_buffer_event_data(entry->event);
+ else
+ entry->sample = NULL;
+
+ if (!entry->sample)
+ return NULL;
+
+ entry->size = size;
+ entry->data = entry->sample->data;
+
+ return entry->sample;
+}
+
+int op_cpu_buffer_write_commit(struct op_entry *entry)
+{
+ return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event,
+ entry->irq_flags);
+}
+
+struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu)
+{
+ struct ring_buffer_event *e;
+ e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
+ if (e)
+ goto event;
+ if (ring_buffer_swap_cpu(op_ring_buffer_read,
+ op_ring_buffer_write,
+ cpu))
+ return NULL;
+ e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
+ if (e)
+ goto event;
+ return NULL;
+
+event:
+ entry->event = e;
+ entry->sample = ring_buffer_event_data(e);
+ entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample))
+ / sizeof(entry->sample->data[0]);
+ entry->data = entry->sample->data;
+ return entry->sample;
+}
+
+unsigned long op_cpu_buffer_entries(int cpu)
+{
+ return ring_buffer_entries_cpu(op_ring_buffer_read, cpu)
+ + ring_buffer_entries_cpu(op_ring_buffer_write, cpu);
+}
+
+static int
+op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace,
+ int is_kernel, struct task_struct *task)
{
struct op_entry entry;
- int ret;
+ struct op_sample *sample;
+ unsigned long flags;
+ int size;
- ret = cpu_buffer_write_entry(&entry);
- if (ret)
- return ret;
+ flags = 0;
- entry.sample->eip = pc;
- entry.sample->event = event;
+ if (backtrace)
+ flags |= TRACE_BEGIN;
- ret = cpu_buffer_write_commit(&entry);
- if (ret)
- return ret;
+ /* notice a switch from user->kernel or vice versa */
+ is_kernel = !!is_kernel;
+ if (cpu_buf->last_is_kernel != is_kernel) {
+ cpu_buf->last_is_kernel = is_kernel;
+ flags |= KERNEL_CTX_SWITCH;
+ if (is_kernel)
+ flags |= IS_KERNEL;
+ }
+
+ /* notice a task switch */
+ if (cpu_buf->last_task != task) {
+ cpu_buf->last_task = task;
+ flags |= USER_CTX_SWITCH;
+ }
+
+ if (!flags)
+ /* nothing to do */
+ return 0;
+
+ if (flags & USER_CTX_SWITCH)
+ size = 1;
+ else
+ size = 0;
+
+ sample = op_cpu_buffer_write_reserve(&entry, size);
+ if (!sample)
+ return -ENOMEM;
+
+ sample->eip = ESCAPE_CODE;
+ sample->event = flags;
+
+ if (size)
+ op_cpu_buffer_add_data(&entry, (unsigned long)task);
+
+ op_cpu_buffer_write_commit(&entry);
return 0;
}
static inline int
-add_code(struct oprofile_cpu_buffer *buffer, unsigned long value)
+op_add_sample(struct oprofile_cpu_buffer *cpu_buf,
+ unsigned long pc, unsigned long event)
{
- return add_sample(buffer, ESCAPE_CODE, value);
+ struct op_entry entry;
+ struct op_sample *sample;
+
+ sample = op_cpu_buffer_write_reserve(&entry, 0);
+ if (!sample)
+ return -ENOMEM;
+
+ sample->eip = pc;
+ sample->event = event;
+
+ return op_cpu_buffer_write_commit(&entry);
}
-/* This must be safe from any context. It's safe writing here
- * because of the head/tail separation of the writer and reader
- * of the CPU buffer.
+/*
+ * This must be safe from any context.
*
* is_kernel is needed because on some architectures you cannot
* tell if you are in kernel or user space simply by looking at
* pc. We tag this in the buffer by generating kernel enter/exit
* events whenever is_kernel changes
*/
-static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
- int is_kernel, unsigned long event)
+static int
+log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
+ unsigned long backtrace, int is_kernel, unsigned long event)
{
- struct task_struct *task;
-
cpu_buf->sample_received++;
if (pc == ESCAPE_CODE) {
@@ -193,25 +301,10 @@ static int log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
return 0;
}
- is_kernel = !!is_kernel;
-
- task = current;
-
- /* notice a switch from user->kernel or vice versa */
- if (cpu_buf->last_is_kernel != is_kernel) {
- cpu_buf->last_is_kernel = is_kernel;
- if (add_code(cpu_buf, is_kernel))
- goto fail;
- }
-
- /* notice a task switch */
- if (cpu_buf->last_task != task) {
- cpu_buf->last_task = task;
- if (add_code(cpu_buf, (unsigned long)task))
- goto fail;
- }
+ if (op_add_code(cpu_buf, backtrace, is_kernel, current))
+ goto fail;
- if (add_sample(cpu_buf, pc, event))
+ if (op_add_sample(cpu_buf, pc, event))
goto fail;
return 1;
@@ -221,109 +314,107 @@ fail:
return 0;
}
-static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf)
+static inline void oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf)
{
- add_code(cpu_buf, CPU_TRACE_BEGIN);
cpu_buf->tracing = 1;
- return 1;
}
-static void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf)
+static inline void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf)
{
cpu_buf->tracing = 0;
}
-void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
- unsigned long event, int is_kernel)
+static inline void
+__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
+ unsigned long event, int is_kernel)
{
struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
-
- if (!backtrace_depth) {
- log_sample(cpu_buf, pc, is_kernel, event);
- return;
- }
-
- if (!oprofile_begin_trace(cpu_buf))
- return;
+ unsigned long backtrace = oprofile_backtrace_depth;
/*
* if log_sample() fail we can't backtrace since we lost the
* source of this event
*/
- if (log_sample(cpu_buf, pc, is_kernel, event))
- oprofile_ops.backtrace(regs, backtrace_depth);
+ if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event))
+ /* failed */
+ return;
+
+ if (!backtrace)
+ return;
+
+ oprofile_begin_trace(cpu_buf);
+ oprofile_ops.backtrace(regs, backtrace);
oprofile_end_trace(cpu_buf);
}
+void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
+ unsigned long event, int is_kernel)
+{
+ __oprofile_add_ext_sample(pc, regs, event, is_kernel);
+}
+
void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
{
int is_kernel = !user_mode(regs);
unsigned long pc = profile_pc(regs);
- oprofile_add_ext_sample(pc, regs, event, is_kernel);
+ __oprofile_add_ext_sample(pc, regs, event, is_kernel);
}
-#ifdef CONFIG_OPROFILE_IBS
-
-#define MAX_IBS_SAMPLE_SIZE 14
-
-void oprofile_add_ibs_sample(struct pt_regs * const regs,
- unsigned int * const ibs_sample, int ibs_code)
+/*
+ * Add samples with data to the ring buffer.
+ *
+ * Use oprofile_add_data(&entry, val) to add data and
+ * oprofile_write_commit(&entry) to commit the sample.
+ */
+void
+oprofile_write_reserve(struct op_entry *entry, struct pt_regs * const regs,
+ unsigned long pc, int code, int size)
{
+ struct op_sample *sample;
int is_kernel = !user_mode(regs);
struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
- struct task_struct *task;
- int fail = 0;
cpu_buf->sample_received++;
- /* notice a switch from user->kernel or vice versa */
- if (cpu_buf->last_is_kernel != is_kernel) {
- if (add_code(cpu_buf, is_kernel))
- goto fail;
- cpu_buf->last_is_kernel = is_kernel;
- }
-
- /* notice a task switch */
- if (!is_kernel) {
- task = current;
- if (cpu_buf->last_task != task) {
- if (add_code(cpu_buf, (unsigned long)task))
- goto fail;
- cpu_buf->last_task = task;
- }
- }
-
- fail = fail || add_code(cpu_buf, ibs_code);
- fail = fail || add_sample(cpu_buf, ibs_sample[0], ibs_sample[1]);
- fail = fail || add_sample(cpu_buf, ibs_sample[2], ibs_sample[3]);
- fail = fail || add_sample(cpu_buf, ibs_sample[4], ibs_sample[5]);
-
- if (ibs_code == IBS_OP_BEGIN) {
- fail = fail || add_sample(cpu_buf, ibs_sample[6], ibs_sample[7]);
- fail = fail || add_sample(cpu_buf, ibs_sample[8], ibs_sample[9]);
- fail = fail || add_sample(cpu_buf, ibs_sample[10], ibs_sample[11]);
- }
+ /* no backtraces for samples with data */
+ if (op_add_code(cpu_buf, 0, is_kernel, current))
+ goto fail;
- if (fail)
+ sample = op_cpu_buffer_write_reserve(entry, size + 2);
+ if (!sample)
goto fail;
+ sample->eip = ESCAPE_CODE;
+ sample->event = 0; /* no flags */
- if (backtrace_depth)
- oprofile_ops.backtrace(regs, backtrace_depth);
+ op_cpu_buffer_add_data(entry, code);
+ op_cpu_buffer_add_data(entry, pc);
return;
fail:
+ entry->event = NULL;
cpu_buf->sample_lost_overflow++;
- return;
}
-#endif
+int oprofile_add_data(struct op_entry *entry, unsigned long val)
+{
+ if (!entry->event)
+ return 0;
+ return op_cpu_buffer_add_data(entry, val);
+}
+
+int oprofile_write_commit(struct op_entry *entry)
+{
+ if (!entry->event)
+ return -EINVAL;
+ return op_cpu_buffer_write_commit(entry);
+}
void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
{
struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer);
- log_sample(cpu_buf, pc, is_kernel, event);
+ log_sample(cpu_buf, pc, 0, is_kernel, event);
}
void oprofile_add_trace(unsigned long pc)
@@ -340,7 +431,7 @@ void oprofile_add_trace(unsigned long pc)
if (pc == ESCAPE_CODE)
goto fail;
- if (add_sample(cpu_buf, pc, 0))
+ if (op_add_sample(cpu_buf, pc, 0))
goto fail;
return;
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
index aacb0f0bc566..272995d20293 100644
--- a/drivers/oprofile/cpu_buffer.h
+++ b/drivers/oprofile/cpu_buffer.h
@@ -1,10 +1,11 @@
/**
* @file cpu_buffer.h
*
- * @remark Copyright 2002 OProfile authors
+ * @remark Copyright 2002-2009 OProfile authors
* @remark Read the file COPYING
*
* @author John Levon <levon@movementarian.org>
+ * @author Robert Richter <robert.richter@amd.com>
*/
#ifndef OPROFILE_CPU_BUFFER_H
@@ -31,17 +32,12 @@ void end_cpu_work(void);
struct op_sample {
unsigned long eip;
unsigned long event;
+ unsigned long data[0];
};
-struct op_entry {
- struct ring_buffer_event *event;
- struct op_sample *sample;
- unsigned long irq_flags;
-};
+struct op_entry;
struct oprofile_cpu_buffer {
- volatile unsigned long head_pos;
- volatile unsigned long tail_pos;
unsigned long buffer_size;
struct task_struct *last_task;
int last_is_kernel;
@@ -54,8 +50,6 @@ struct oprofile_cpu_buffer {
struct delayed_work work;
};
-extern struct ring_buffer *op_ring_buffer_read;
-extern struct ring_buffer *op_ring_buffer_write;
DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
/*
@@ -64,7 +58,7 @@ DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer);
* reset these to invalid values; the next sample collected will
* populate the buffer with proper values to initialize the buffer
*/
-static inline void cpu_buffer_reset(int cpu)
+static inline void op_cpu_buffer_reset(int cpu)
{
struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu);
@@ -72,55 +66,55 @@ static inline void cpu_buffer_reset(int cpu)
cpu_buf->last_task = NULL;
}
-static inline int cpu_buffer_write_entry(struct op_entry *entry)
-{
- entry->event = ring_buffer_lock_reserve(op_ring_buffer_write,
- sizeof(struct op_sample),
- &entry->irq_flags);
- if (entry->event)
- entry->sample = ring_buffer_event_data(entry->event);
- else
- entry->sample = NULL;
-
- if (!entry->sample)
- return -ENOMEM;
-
- return 0;
-}
+/*
+ * op_cpu_buffer_add_data() and op_cpu_buffer_write_commit() may be
+ * called only if op_cpu_buffer_write_reserve() did not return NULL or
+ * entry->event != NULL, otherwise entry->size or entry->event will be
+ * used uninitialized.
+ */
+
+struct op_sample
+*op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size);
+int op_cpu_buffer_write_commit(struct op_entry *entry);
+struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu);
+unsigned long op_cpu_buffer_entries(int cpu);
-static inline int cpu_buffer_write_commit(struct op_entry *entry)
+/* returns the remaining free size of data in the entry */
+static inline
+int op_cpu_buffer_add_data(struct op_entry *entry, unsigned long val)
{
- return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event,
- entry->irq_flags);
+ if (!entry->size)
+ return 0;
+ *entry->data = val;
+ entry->size--;
+ entry->data++;
+ return entry->size;
}
-static inline struct op_sample *cpu_buffer_read_entry(int cpu)
+/* returns the size of data in the entry */
+static inline
+int op_cpu_buffer_get_size(struct op_entry *entry)
{
- struct ring_buffer_event *e;
- e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
- if (e)
- return ring_buffer_event_data(e);
- if (ring_buffer_swap_cpu(op_ring_buffer_read,
- op_ring_buffer_write,
- cpu))
- return NULL;
- e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL);
- if (e)
- return ring_buffer_event_data(e);
- return NULL;
+ return entry->size;
}
-/* "acquire" as many cpu buffer slots as we can */
-static inline unsigned long cpu_buffer_entries(int cpu)
+/* returns 0 if empty or the size of data including the current value */
+static inline
+int op_cpu_buffer_get_data(struct op_entry *entry, unsigned long *val)
{
- return ring_buffer_entries_cpu(op_ring_buffer_read, cpu)
- + ring_buffer_entries_cpu(op_ring_buffer_write, cpu);
+ int size = entry->size;
+ if (!size)
+ return 0;
+ *val = *entry->data;
+ entry->size--;
+ entry->data++;
+ return size;
}
-/* transient events for the CPU buffer -> event buffer */
-#define CPU_IS_KERNEL 1
-#define CPU_TRACE_BEGIN 2
-#define IBS_FETCH_BEGIN 3
-#define IBS_OP_BEGIN 4
+/* extra data flags */
+#define KERNEL_CTX_SWITCH (1UL << 0)
+#define IS_KERNEL (1UL << 1)
+#define TRACE_BEGIN (1UL << 2)
+#define USER_CTX_SWITCH (1UL << 3)
#endif /* OPROFILE_CPU_BUFFER_H */
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 191a3202cecc..2b7ae366ceb1 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -73,8 +73,8 @@ int alloc_event_buffer(void)
unsigned long flags;
spin_lock_irqsave(&oprofilefs_lock, flags);
- buffer_size = fs_buffer_size;
- buffer_watershed = fs_buffer_watershed;
+ buffer_size = oprofile_buffer_size;
+ buffer_watershed = oprofile_buffer_watershed;
spin_unlock_irqrestore(&oprofilefs_lock, flags);
if (buffer_watershed >= buffer_size)
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
index cd375907f26f..3cffce90f82a 100644
--- a/drivers/oprofile/oprof.c
+++ b/drivers/oprofile/oprof.c
@@ -23,7 +23,7 @@
struct oprofile_operations oprofile_ops;
unsigned long oprofile_started;
-unsigned long backtrace_depth;
+unsigned long oprofile_backtrace_depth;
static unsigned long is_setup;
static DEFINE_MUTEX(start_mutex);
@@ -172,7 +172,7 @@ int oprofile_set_backtrace(unsigned long val)
goto out;
}
- backtrace_depth = val;
+ oprofile_backtrace_depth = val;
out:
mutex_unlock(&start_mutex);
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h
index 5df0c21a608f..c288d3c24b50 100644
--- a/drivers/oprofile/oprof.h
+++ b/drivers/oprofile/oprof.h
@@ -21,12 +21,12 @@ void oprofile_stop(void);
struct oprofile_operations;
-extern unsigned long fs_buffer_size;
-extern unsigned long fs_cpu_buffer_size;
-extern unsigned long fs_buffer_watershed;
+extern unsigned long oprofile_buffer_size;
+extern unsigned long oprofile_cpu_buffer_size;
+extern unsigned long oprofile_buffer_watershed;
extern struct oprofile_operations oprofile_ops;
extern unsigned long oprofile_started;
-extern unsigned long backtrace_depth;
+extern unsigned long oprofile_backtrace_depth;
struct super_block;
struct dentry;
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index d8201998b0b7..5d36ffc30dd5 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -14,17 +14,18 @@
#include "oprofile_stats.h"
#include "oprof.h"
-#define FS_BUFFER_SIZE_DEFAULT 131072
-#define FS_CPU_BUFFER_SIZE_DEFAULT 8192
-#define FS_BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */
+#define BUFFER_SIZE_DEFAULT 131072
+#define CPU_BUFFER_SIZE_DEFAULT 8192
+#define BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */
-unsigned long fs_buffer_size;
-unsigned long fs_cpu_buffer_size;
-unsigned long fs_buffer_watershed;
+unsigned long oprofile_buffer_size;
+unsigned long oprofile_cpu_buffer_size;
+unsigned long oprofile_buffer_watershed;
static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{
- return oprofilefs_ulong_to_user(backtrace_depth, buf, count, offset);
+ return oprofilefs_ulong_to_user(oprofile_backtrace_depth, buf, count,
+ offset);
}
@@ -125,16 +126,16 @@ static const struct file_operations dump_fops = {
void oprofile_create_files(struct super_block *sb, struct dentry *root)
{
/* reinitialize default values */
- fs_buffer_size = FS_BUFFER_SIZE_DEFAULT;
- fs_cpu_buffer_size = FS_CPU_BUFFER_SIZE_DEFAULT;
- fs_buffer_watershed = FS_BUFFER_WATERSHED_DEFAULT;
+ oprofile_buffer_size = BUFFER_SIZE_DEFAULT;
+ oprofile_cpu_buffer_size = CPU_BUFFER_SIZE_DEFAULT;
+ oprofile_buffer_watershed = BUFFER_WATERSHED_DEFAULT;
oprofilefs_create_file(sb, root, "enable", &enable_fops);
oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
- oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
- oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed);
- oprofilefs_create_ulong(sb, root, "cpu_buffer_size", &fs_cpu_buffer_size);
+ oprofilefs_create_ulong(sb, root, "buffer_size", &oprofile_buffer_size);
+ oprofilefs_create_ulong(sb, root, "buffer_watershed", &oprofile_buffer_watershed);
+ oprofilefs_create_ulong(sb, root, "cpu_buffer_size", &oprofile_cpu_buffer_size);
oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops);
oprofilefs_create_file(sb, root, "backtrace_depth", &depth_fops);
oprofilefs_create_file(sb, root, "pointer_size", &pointer_size_fops);
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index ddc4c59f02dc..b7e4cee24269 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -29,9 +29,6 @@ static struct inode *oprofilefs_get_inode(struct super_block *sb, int mode)
if (inode) {
inode->i_mode = mode;
- inode->i_uid = 0;
- inode->i_gid = 0;
- inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}
return inode;
diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c
index 821369135369..7931133526c4 100644
--- a/drivers/parisc/asp.c
+++ b/drivers/parisc/asp.c
@@ -71,8 +71,7 @@ static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
*/
#define ASP_INTERRUPT_ADDR 0xf0800000
-int __init
-asp_init_chip(struct parisc_device *dev)
+static int __init asp_init_chip(struct parisc_device *dev)
{
struct gsc_irq gsc_irq;
int ret;
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index dcc1e9958d2f..cd4dd7ed2c06 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -555,7 +555,7 @@ static u32 hint_lookup[] = {
* (Load Coherence Index) instruction. The 8 bits used for the virtual
* index are bits 12:19 of the value returned by LCI.
*/
-void CCIO_INLINE
+static void CCIO_INLINE
ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
unsigned long hints)
{
@@ -1578,8 +1578,6 @@ static int __init ccio_probe(struct parisc_device *dev)
ioc_count++;
- parisc_vmerge_boundary = IOVP_SIZE;
- parisc_vmerge_max_size = BITS_PER_LONG * IOVP_SIZE;
parisc_has_iommu();
return 0;
}
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 3bc54b30c3a1..d539d9df88e7 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -287,7 +287,7 @@ DINO_PORT_OUT(b, 8, 3)
DINO_PORT_OUT(w, 16, 2)
DINO_PORT_OUT(l, 32, 0)
-struct pci_port_ops dino_port_ops = {
+static struct pci_port_ops dino_port_ops = {
.inb = dino_in8,
.inw = dino_in16,
.inl = dino_in32,
@@ -547,7 +547,7 @@ dino_card_fixup(struct pci_dev *dev)
** The additional "-1" adjusts for skewing the IRQ<->slot.
*/
dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin);
- dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
+ dev->irq = pci_swizzle_interrupt_pin(dev, irq_pin) - 1;
/* Shouldn't really need to do this but it's in case someone tries
** to bypass PCI services and look at the card themselves.
@@ -672,7 +672,7 @@ dino_fixup_bus(struct pci_bus *bus)
dino_cfg_read(dev->bus, dev->devfn,
PCI_INTERRUPT_PIN, 1, &irq_pin);
- irq_pin = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
+ irq_pin = pci_swizzle_interrupt_pin(dev, irq_pin) - 1;
printk(KERN_WARNING "Device %s has undefined IRQ, "
"setting to %d\n", pci_name(dev), irq_pin);
dino_cfg_write(dev->bus, dev->devfn,
@@ -690,7 +690,7 @@ dino_fixup_bus(struct pci_bus *bus)
}
-struct pci_bios_ops dino_bios_ops = {
+static struct pci_bios_ops dino_bios_ops = {
.init = dino_bios_init,
.fixup_bus = dino_fixup_bus
};
diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
index 65eee67aa2ae..13856415b432 100644
--- a/drivers/parisc/hppb.c
+++ b/drivers/parisc/hppb.c
@@ -29,7 +29,7 @@ struct hppb_card {
struct hppb_card *next;
};
-struct hppb_card hppb_card_head = {
+static struct hppb_card hppb_card_head = {
.hpa = 0,
.next = NULL,
};
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 7beffcab2745..0797659ee016 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -519,8 +519,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
**
** Advantage is it's really easy to implement.
*/
- intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
- intr_pin++; /* convert back to INTA-D (1-4) */
+ intr_pin = pci_swizzle_interrupt_pin(pcidev, intr_pin);
#endif /* PCI_BRIDGE_FUNCS */
/*
@@ -704,16 +703,17 @@ static unsigned int iosapic_startup_irq(unsigned int irq)
}
#ifdef CONFIG_SMP
-static void iosapic_set_affinity_irq(unsigned int irq, cpumask_t dest)
+static void iosapic_set_affinity_irq(unsigned int irq,
+ const struct cpumask *dest)
{
struct vector_info *vi = iosapic_get_vector(irq);
u32 d0, d1, dummy_d0;
unsigned long flags;
- if (cpu_check_affinity(irq, &dest))
+ if (cpu_check_affinity(irq, dest))
return;
- vi->txn_addr = txn_affinity_addr(irq, first_cpu(dest));
+ vi->txn_addr = txn_affinity_addr(irq, cpumask_first(dest));
spin_lock_irqsave(&iosapic_lock, flags);
/* d1 contains the destination CPU, so only want to set that
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index bee510098ce8..e65727ca9fc0 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -107,7 +107,7 @@ lasi_init_irq(struct gsc_asic *this_lasi)
#else
-void __init lasi_led_init(unsigned long lasi_hpa)
+static void __init lasi_led_init(unsigned long lasi_hpa)
{
unsigned long datareg;
@@ -163,8 +163,7 @@ static void lasi_power_off(void)
gsc_writel(0x02, datareg);
}
-int __init
-lasi_init_chip(struct parisc_device *dev)
+static int __init lasi_init_chip(struct parisc_device *dev)
{
extern void (*chassis_power_off)(void);
struct gsc_asic *lasi;
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index a28c8946deaa..d8233de8c75d 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -824,7 +824,7 @@ lba_fixup_bus(struct pci_bus *bus)
}
-struct pci_bios_ops lba_bios_ops = {
+static struct pci_bios_ops lba_bios_ops = {
.init = lba_bios_init,
.fixup_bus = lba_fixup_bus,
};
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index bc73b96346ff..a70cf16ee1ad 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -561,7 +561,7 @@ typedef unsigned long space_t;
* IOMMU uses little endian for the pdir.
*/
-void SBA_INLINE
+static void SBA_INLINE
sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
unsigned long hint)
{
@@ -668,7 +668,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
* @dev: instance of PCI owned by the driver that's asking
* @mask: number of address bits this PCI device can handle
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
static int sba_dma_supported( struct device *dev, u64 mask)
{
@@ -680,8 +680,8 @@ static int sba_dma_supported( struct device *dev, u64 mask)
return(0);
}
- /* Documentation/DMA-mapping.txt tells drivers to try 64-bit first,
- * then fall back to 32-bit if that fails.
+ /* Documentation/PCI/PCI-DMA-mapping.txt tells drivers to try 64-bit
+ * first, then fall back to 32-bit if that fails.
* We are just "encouraging" 32-bit DMA masks here since we can
* never allow IOMMU bypass unless we add special support for ZX1.
*/
@@ -706,7 +706,7 @@ static int sba_dma_supported( struct device *dev, u64 mask)
* @size: number of bytes to map in driver buffer.
* @direction: R/W or both.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
static dma_addr_t
sba_map_single(struct device *dev, void *addr, size_t size,
@@ -785,7 +785,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
* @size: number of bytes mapped in driver buffer.
* @direction: R/W or both.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
static void
sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
@@ -861,7 +861,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
* @size: number of bytes mapped in driver buffer.
* @dma_handle: IOVA of new buffer.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
static void *sba_alloc_consistent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
@@ -892,7 +892,7 @@ static void *sba_alloc_consistent(struct device *hwdev, size_t size,
* @vaddr: virtual address IOVA of "consistent" buffer.
* @dma_handler: IO virtual address of "consistent" buffer.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
static void
sba_free_consistent(struct device *hwdev, size_t size, void *vaddr,
@@ -927,7 +927,7 @@ int dump_run_sg = 0;
* @nents: number of entries in list
* @direction: R/W or both.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
static int
sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
@@ -1011,7 +1011,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
* @nents: number of entries in list
* @direction: R/W or both.
*
- * See Documentation/DMA-mapping.txt
+ * See Documentation/PCI/PCI-DMA-mapping.txt
*/
static void
sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
@@ -1874,7 +1874,7 @@ static struct parisc_device_id sba_tbl[] = {
{ 0, }
};
-int sba_driver_callback(struct parisc_device *);
+static int sba_driver_callback(struct parisc_device *);
static struct parisc_driver sba_driver = {
.name = MODULE_NAME,
@@ -1887,8 +1887,7 @@ static struct parisc_driver sba_driver = {
** If so, initialize the chip and tell other partners in crime they
** have work to do.
*/
-int
-sba_driver_callback(struct parisc_device *dev)
+static int sba_driver_callback(struct parisc_device *dev)
{
struct sba_device *sba_dev;
u32 func_class;
@@ -1979,8 +1978,6 @@ sba_driver_callback(struct parisc_device *dev)
proc_create("sba_iommu-bitmap", 0, root, &sba_proc_bitmap_fops);
#endif
- parisc_vmerge_boundary = IOVP_SIZE;
- parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG;
parisc_has_iommu();
return 0;
}
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 1e93c837514f..4fa3bb2ddfe4 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -405,7 +405,6 @@ static void __init superio_serial_init(void)
serial_port.type = PORT_16550A;
serial_port.uartclk = 115200*16;
serial_port.fifosize = 16;
- spin_lock_init(&serial_port.lock);
/* serial port #1 */
serial_port.iobase = sio_dev.sp1_base;
diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c
index 892a83bbe73d..da9d5ad1353c 100644
--- a/drivers/parisc/wax.c
+++ b/drivers/parisc/wax.c
@@ -68,8 +68,7 @@ wax_init_irq(struct gsc_asic *wax)
// gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */
}
-int __init
-wax_init_chip(struct parisc_device *dev)
+static int __init wax_init_chip(struct parisc_device *dev)
{
struct gsc_asic *wax;
struct parisc_device *parent;
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
index ac2a805ac7ea..8901ecf6e037 100644
--- a/drivers/parport/ieee1284.c
+++ b/drivers/parport/ieee1284.c
@@ -84,7 +84,7 @@ int parport_wait_event (struct parport *port, signed long timeout)
add_timer (&timer);
ret = down_interruptible (&port->physport->ieee1284.irq);
- if (!del_timer (&timer) && !ret)
+ if (!del_timer_sync(&timer) && !ret)
/* Timed out. */
ret = 1;
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index e1ca42591ac4..2a4501dd2515 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -42,6 +42,15 @@ config PCI_DEBUG
When in doubt, say N.
+config PCI_STUB
+ tristate "PCI Stub driver"
+ depends on PCI
+ help
+ Say Y or M here if you want be able to reserve a PCI device
+ when it is going to be assigned to a guest operating system.
+
+ When in doubt, say N.
+
config HT_IRQ
bool "Interrupts on hypertransport devices"
default y
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index af3bfe22847b..3d07ce24f6a8 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -53,6 +53,8 @@ obj-$(CONFIG_HOTPLUG) += setup-bus.o
obj-$(CONFIG_PCI_SYSCALL) += syscall.o
+obj-$(CONFIG_PCI_STUB) += pci-stub.o
+
ifeq ($(CONFIG_PCI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 39bb96b413ef..381444794778 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -66,6 +66,39 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);
+
+/**
+ * pci_read_vpd - Read one entry from Vital Product Data
+ * @dev: pci device struct
+ * @pos: offset in vpd space
+ * @count: number of bytes to read
+ * @buf: pointer to where to store result
+ *
+ */
+ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf)
+{
+ if (!dev->vpd || !dev->vpd->ops)
+ return -ENODEV;
+ return dev->vpd->ops->read(dev, pos, count, buf);
+}
+EXPORT_SYMBOL(pci_read_vpd);
+
+/**
+ * pci_write_vpd - Write entry to Vital Product Data
+ * @dev: pci device struct
+ * @pos: offset in vpd space
+ * @count: number of bytes to read
+ * @val: value to write
+ *
+ */
+ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
+{
+ if (!dev->vpd || !dev->vpd->ops)
+ return -ENODEV;
+ return dev->vpd->ops->write(dev, pos, count, buf);
+}
+EXPORT_SYMBOL(pci_write_vpd);
+
/*
* The following routines are to prevent the user from accessing PCI config
* space when it's unsafe to do so. Some devices require this during BIST and
@@ -133,125 +166,145 @@ PCI_USER_WRITE_CONFIG(dword, u32)
struct pci_vpd_pci22 {
struct pci_vpd base;
- spinlock_t lock; /* controls access to hardware and the flags */
- u8 cap;
+ struct mutex lock;
+ u16 flag;
bool busy;
- bool flag; /* value of F bit to wait for */
+ u8 cap;
};
-/* Wait for last operation to complete */
+/*
+ * Wait for last operation to complete.
+ * This code has to spin since there is no other notification from the PCI
+ * hardware. Since the VPD is often implemented by serial attachment to an
+ * EEPROM, it may take many milliseconds to complete.
+ */
static int pci_vpd_pci22_wait(struct pci_dev *dev)
{
struct pci_vpd_pci22 *vpd =
container_of(dev->vpd, struct pci_vpd_pci22, base);
- u16 flag, status;
- int wait;
+ unsigned long timeout = jiffies + HZ/20 + 2;
+ u16 status;
int ret;
if (!vpd->busy)
return 0;
- flag = vpd->flag ? PCI_VPD_ADDR_F : 0;
- wait = vpd->flag ? 10 : 1000; /* read: 100 us; write: 10 ms */
for (;;) {
- ret = pci_user_read_config_word(dev,
- vpd->cap + PCI_VPD_ADDR,
+ ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
&status);
- if (ret < 0)
+ if (ret)
return ret;
- if ((status & PCI_VPD_ADDR_F) == flag) {
+
+ if ((status & PCI_VPD_ADDR_F) == vpd->flag) {
vpd->busy = false;
return 0;
}
- if (wait-- == 0)
+
+ if (time_after(jiffies, timeout))
return -ETIMEDOUT;
- udelay(10);
+ if (fatal_signal_pending(current))
+ return -EINTR;
+ if (!cond_resched())
+ udelay(10);
}
}
-static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size,
- char *buf)
+static ssize_t pci_vpd_pci22_read(struct pci_dev *dev, loff_t pos, size_t count,
+ void *arg)
{
struct pci_vpd_pci22 *vpd =
container_of(dev->vpd, struct pci_vpd_pci22, base);
- u32 val;
int ret;
- int begin, end, i;
+ loff_t end = pos + count;
+ u8 *buf = arg;
- if (pos < 0 || pos > vpd->base.len || size > vpd->base.len - pos)
+ if (pos < 0 || pos > vpd->base.len || end > vpd->base.len)
return -EINVAL;
- if (size == 0)
- return 0;
- spin_lock_irq(&vpd->lock);
- ret = pci_vpd_pci22_wait(dev);
- if (ret < 0)
- goto out;
- ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
- pos & ~3);
- if (ret < 0)
- goto out;
- vpd->busy = true;
- vpd->flag = 1;
+ if (mutex_lock_killable(&vpd->lock))
+ return -EINTR;
+
ret = pci_vpd_pci22_wait(dev);
if (ret < 0)
goto out;
- ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA,
- &val);
-out:
- spin_unlock_irq(&vpd->lock);
- if (ret < 0)
- return ret;
-
- /* Convert to bytes */
- begin = pos & 3;
- end = min(4, begin + size);
- for (i = 0; i < end; ++i) {
- if (i >= begin)
- *buf++ = val;
- val >>= 8;
+
+ while (pos < end) {
+ u32 val;
+ unsigned int i, skip;
+
+ ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
+ pos & ~3);
+ if (ret < 0)
+ break;
+ vpd->busy = true;
+ vpd->flag = PCI_VPD_ADDR_F;
+ ret = pci_vpd_pci22_wait(dev);
+ if (ret < 0)
+ break;
+
+ ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA, &val);
+ if (ret < 0)
+ break;
+
+ skip = pos & 3;
+ for (i = 0; i < sizeof(u32); i++) {
+ if (i >= skip) {
+ *buf++ = val;
+ if (++pos == end)
+ break;
+ }
+ val >>= 8;
+ }
}
- return end - begin;
+out:
+ mutex_unlock(&vpd->lock);
+ return ret ? ret : count;
}
-static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size,
- const char *buf)
+static ssize_t pci_vpd_pci22_write(struct pci_dev *dev, loff_t pos, size_t count,
+ const void *arg)
{
struct pci_vpd_pci22 *vpd =
container_of(dev->vpd, struct pci_vpd_pci22, base);
- u32 val;
- int ret;
+ const u8 *buf = arg;
+ loff_t end = pos + count;
+ int ret = 0;
- if (pos < 0 || pos > vpd->base.len || pos & 3 ||
- size > vpd->base.len - pos || size < 4)
+ if (pos < 0 || (pos & 3) || (count & 3) || end > vpd->base.len)
return -EINVAL;
- val = (u8) *buf++;
- val |= ((u8) *buf++) << 8;
- val |= ((u8) *buf++) << 16;
- val |= ((u32)(u8) *buf++) << 24;
+ if (mutex_lock_killable(&vpd->lock))
+ return -EINTR;
- spin_lock_irq(&vpd->lock);
ret = pci_vpd_pci22_wait(dev);
if (ret < 0)
goto out;
- ret = pci_user_write_config_dword(dev, vpd->cap + PCI_VPD_DATA,
- val);
- if (ret < 0)
- goto out;
- ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
- pos | PCI_VPD_ADDR_F);
- if (ret < 0)
- goto out;
- vpd->busy = true;
- vpd->flag = 0;
- ret = pci_vpd_pci22_wait(dev);
-out:
- spin_unlock_irq(&vpd->lock);
- if (ret < 0)
- return ret;
- return 4;
+ while (pos < end) {
+ u32 val;
+
+ val = *buf++;
+ val |= *buf++ << 8;
+ val |= *buf++ << 16;
+ val |= *buf++ << 24;
+
+ ret = pci_user_write_config_dword(dev, vpd->cap + PCI_VPD_DATA, val);
+ if (ret < 0)
+ break;
+ ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
+ pos | PCI_VPD_ADDR_F);
+ if (ret < 0)
+ break;
+
+ vpd->busy = true;
+ vpd->flag = 0;
+ ret = pci_vpd_pci22_wait(dev);
+
+ pos += sizeof(u32);
+ }
+out:
+ mutex_unlock(&vpd->lock);
+ return ret ? ret : count;
}
static void pci_vpd_pci22_release(struct pci_dev *dev)
@@ -259,7 +312,7 @@ static void pci_vpd_pci22_release(struct pci_dev *dev)
kfree(container_of(dev->vpd, struct pci_vpd_pci22, base));
}
-static struct pci_vpd_ops pci_vpd_pci22_ops = {
+static const struct pci_vpd_ops pci_vpd_pci22_ops = {
.read = pci_vpd_pci22_read,
.write = pci_vpd_pci22_write,
.release = pci_vpd_pci22_release,
@@ -279,7 +332,7 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
vpd->base.len = PCI_VPD_PCI22_SIZE;
vpd->base.ops = &pci_vpd_pci22_ops;
- spin_lock_init(&vpd->lock);
+ mutex_init(&vpd->lock);
vpd->cap = cap;
vpd->busy = false;
dev->vpd = &vpd->base;
@@ -287,6 +340,29 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
}
/**
+ * pci_vpd_truncate - Set available Vital Product Data size
+ * @dev: pci device struct
+ * @size: available memory in bytes
+ *
+ * Adjust size of available VPD area.
+ */
+int pci_vpd_truncate(struct pci_dev *dev, size_t size)
+{
+ if (!dev->vpd)
+ return -EINVAL;
+
+ /* limited by the access method */
+ if (size > dev->vpd->len)
+ return -EINVAL;
+
+ dev->vpd->len = size;
+ dev->vpd->attr->size = size;
+
+ return 0;
+}
+EXPORT_SYMBOL(pci_vpd_truncate);
+
+/**
* pci_block_user_cfg_access - Block userspace PCI config reads/writes
* @dev: pci device struct
*
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 999cc4088b59..52b54f053be0 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -71,7 +71,7 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
}
/**
- * add a single device
+ * pci_bus_add_device - add a single device
* @dev: device to add
*
* This adds a single pci device to the global
@@ -91,6 +91,37 @@ int pci_bus_add_device(struct pci_dev *dev)
}
/**
+ * pci_bus_add_child - add a child bus
+ * @bus: bus to add
+ *
+ * This adds sysfs entries for a single bus
+ */
+int pci_bus_add_child(struct pci_bus *bus)
+{
+ int retval;
+
+ if (bus->bridge)
+ bus->dev.parent = bus->bridge;
+
+ retval = device_register(&bus->dev);
+ if (retval)
+ return retval;
+
+ bus->is_added = 1;
+
+ retval = device_create_file(&bus->dev, &dev_attr_cpuaffinity);
+ if (retval)
+ return retval;
+
+ retval = device_create_file(&bus->dev, &dev_attr_cpulistaffinity);
+
+ /* Create legacy_io and legacy_mem files for this bus */
+ pci_create_legacy_files(bus);
+
+ return retval;
+}
+
+/**
* pci_bus_add_devices - insert newly discovered PCI devices
* @bus: bus to check for new devices
*
@@ -105,7 +136,7 @@ int pci_bus_add_device(struct pci_dev *dev)
void pci_bus_add_devices(struct pci_bus *bus)
{
struct pci_dev *dev;
- struct pci_bus *child_bus;
+ struct pci_bus *child;
int retval;
list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -120,45 +151,29 @@ void pci_bus_add_devices(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
BUG_ON(!dev->is_added);
+ child = dev->subordinate;
/*
* If there is an unattached subordinate bus, attach
* it and then scan for unattached PCI devices.
*/
- if (dev->subordinate) {
- if (list_empty(&dev->subordinate->node)) {
- down_write(&pci_bus_sem);
- list_add_tail(&dev->subordinate->node,
- &dev->bus->children);
- up_write(&pci_bus_sem);
- }
- pci_bus_add_devices(dev->subordinate);
-
- /* register the bus with sysfs as the parent is now
- * properly registered. */
- child_bus = dev->subordinate;
- if (child_bus->is_added)
- continue;
- child_bus->dev.parent = child_bus->bridge;
- retval = device_register(&child_bus->dev);
- if (retval)
- dev_err(&dev->dev, "Error registering pci_bus,"
- " continuing...\n");
- else {
- child_bus->is_added = 1;
- retval = device_create_file(&child_bus->dev,
- &dev_attr_cpuaffinity);
- }
- if (retval)
- dev_err(&dev->dev, "Error creating cpuaffinity"
- " file, continuing...\n");
-
- retval = device_create_file(&child_bus->dev,
- &dev_attr_cpulistaffinity);
- if (retval)
- dev_err(&dev->dev,
- "Error creating cpulistaffinity"
- " file, continuing...\n");
+ if (!child)
+ continue;
+ if (list_empty(&child->node)) {
+ down_write(&pci_bus_sem);
+ list_add_tail(&child->node, &dev->bus->children);
+ up_write(&pci_bus_sem);
}
+ pci_bus_add_devices(child);
+
+ /*
+ * register the bus with sysfs as the parent is now
+ * properly registered.
+ */
+ if (child->is_added)
+ continue;
+ retval = pci_bus_add_child(child);
+ if (retval)
+ dev_err(&dev->dev, "Error adding bus, continuing\n");
}
}
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 691b3adeb870..f5a662a50acb 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -191,26 +191,17 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
static int __init dmar_parse_dev(struct dmar_drhd_unit *dmaru)
{
struct acpi_dmar_hardware_unit *drhd;
- static int include_all;
int ret = 0;
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
- if (!dmaru->include_all)
- ret = dmar_parse_dev_scope((void *)(drhd + 1),
+ if (dmaru->include_all)
+ return 0;
+
+ ret = dmar_parse_dev_scope((void *)(drhd + 1),
((void *)drhd) + drhd->header.length,
&dmaru->devices_cnt, &dmaru->devices,
drhd->segment);
- else {
- /* Only allow one INCLUDE_ALL */
- if (include_all) {
- printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL "
- "device scope is allowed\n");
- ret = -EINVAL;
- }
- include_all = 1;
- }
-
if (ret) {
list_del(&dmaru->list);
kfree(dmaru);
@@ -384,12 +375,21 @@ int dmar_pci_device_match(struct pci_dev *devices[], int cnt,
struct dmar_drhd_unit *
dmar_find_matched_drhd_unit(struct pci_dev *dev)
{
- struct dmar_drhd_unit *drhd = NULL;
+ struct dmar_drhd_unit *dmaru = NULL;
+ struct acpi_dmar_hardware_unit *drhd;
- list_for_each_entry(drhd, &dmar_drhd_units, list) {
- if (drhd->include_all || dmar_pci_device_match(drhd->devices,
- drhd->devices_cnt, dev))
- return drhd;
+ list_for_each_entry(dmaru, &dmar_drhd_units, list) {
+ drhd = container_of(dmaru->hdr,
+ struct acpi_dmar_hardware_unit,
+ header);
+
+ if (dmaru->include_all &&
+ drhd->segment == pci_domain_nr(dev->bus))
+ return dmaru;
+
+ if (dmar_pci_device_match(dmaru->devices,
+ dmaru->devices_cnt, dev))
+ return dmaru;
}
return NULL;
@@ -491,6 +491,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
int map_size;
u32 ver;
static int iommu_allocated = 0;
+ int agaw;
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
if (!iommu)
@@ -506,6 +507,15 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+ agaw = iommu_calculate_agaw(iommu);
+ if (agaw < 0) {
+ printk(KERN_ERR
+ "Cannot get a valid agaw for iommu (seq_id = %d)\n",
+ iommu->seq_id);
+ goto error;
+ }
+ iommu->agaw = agaw;
+
/* the registers might be more than one page */
map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
cap_max_fault_reg_offset(iommu->cap));
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 9bdbe1a6688f..2aa117c8cd87 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -5,11 +5,15 @@
obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
+
+# pciehp should be linked before acpiphp in order to allow the native driver
+# to attempt to bind first. We can then fall back to generic support.
+
+obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
-obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
@@ -55,6 +59,9 @@ pciehp-objs := pciehp_core.o \
pciehp_ctrl.o \
pciehp_pci.o \
pciehp_hpc.o
+ifdef CONFIG_ACPI
+pciehp-objs += pciehp_acpi.o
+endif
shpchp-objs := shpchp_core.o \
shpchp_ctrl.o \
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index e17ef54f0efc..1c1141801060 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -33,7 +33,6 @@
#include <linux/pci-acpi.h>
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
#define MY_NAME "acpi_pcihp"
@@ -501,5 +500,74 @@ int acpi_root_bridge(acpi_handle handle)
}
EXPORT_SYMBOL_GPL(acpi_root_bridge);
+
+static int is_ejectable(acpi_handle handle)
+{
+ acpi_status status;
+ acpi_handle tmp;
+ unsigned long long removable;
+ status = acpi_get_handle(handle, "_ADR", &tmp);
+ if (ACPI_FAILURE(status))
+ return 0;
+ status = acpi_get_handle(handle, "_EJ0", &tmp);
+ if (ACPI_SUCCESS(status))
+ return 1;
+ status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
+ if (ACPI_SUCCESS(status) && removable)
+ return 1;
+ return 0;
+}
+
+/**
+ * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot
+ * @pbus: the PCI bus of the PCI slot corresponding to 'handle'
+ * @handle: ACPI handle to check
+ *
+ * Return 1 if handle is ejectable PCI slot, 0 otherwise.
+ */
+int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle)
+{
+ acpi_handle bridge_handle, parent_handle;
+
+ if (!(bridge_handle = acpi_pci_get_bridge_handle(pbus)))
+ return 0;
+ if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))))
+ return 0;
+ if (bridge_handle != parent_handle)
+ return 0;
+ return is_ejectable(handle);
+}
+EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable);
+
+static acpi_status
+check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ int *found = (int *)context;
+ if (is_ejectable(handle)) {
+ *found = 1;
+ return AE_CTRL_TERMINATE;
+ }
+ return AE_OK;
+}
+
+/**
+ * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots
+ * @pbus - PCI bus to scan
+ *
+ * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise.
+ */
+int acpi_pci_detect_ejectable(struct pci_bus *pbus)
+{
+ acpi_handle handle;
+ int found = 0;
+
+ if (!(handle = acpi_pci_get_bridge_handle(pbus)))
+ return 0;
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+ check_hotplug, (void *)&found, NULL);
+ return found;
+}
+EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable);
+
module_param(debug_acpi, bool, 0644);
MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 9bcb6cbd5aa9..4fc168b70095 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -44,7 +44,7 @@
do { \
if (acpiphp_debug) \
printk(KERN_DEBUG "%s: " format, \
- MY_NAME , ## arg); \
+ MY_NAME , ## arg); \
} while (0)
#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 3affc6472e65..803d9ddd6e75 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -46,6 +46,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
+#include <linux/pci-acpi.h>
#include <linux/mutex.h>
#include "../pci.h"
@@ -62,61 +63,6 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus);
static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);
static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
-
-/*
- * initialization & terminatation routines
- */
-
-/**
- * is_ejectable - determine if a slot is ejectable
- * @handle: handle to acpi namespace
- *
- * Ejectable slot should satisfy at least these conditions:
- *
- * 1. has _ADR method
- * 2. has _EJ0 method
- *
- * optionally
- *
- * 1. has _STA method
- * 2. has _PS0 method
- * 3. has _PS3 method
- * 4. ..
- */
-static int is_ejectable(acpi_handle handle)
-{
- acpi_status status;
- acpi_handle tmp;
-
- status = acpi_get_handle(handle, "_ADR", &tmp);
- if (ACPI_FAILURE(status)) {
- return 0;
- }
-
- status = acpi_get_handle(handle, "_EJ0", &tmp);
- if (ACPI_FAILURE(status)) {
- return 0;
- }
-
- return 1;
-}
-
-
-/* callback routine to check for the existence of ejectable slots */
-static acpi_status
-is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- int *count = (int *)context;
-
- if (is_ejectable(handle)) {
- (*count)++;
- /* only one ejectable slot is enough */
- return AE_CTRL_TERMINATE;
- } else {
- return AE_OK;
- }
-}
-
/* callback routine to check for the existence of a pci dock device */
static acpi_status
is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
@@ -131,9 +77,6 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
}
}
-
-
-
/*
* the _DCK method can do funny things... and sometimes not
* hah-hah funny.
@@ -160,9 +103,9 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
if (((buses >> 8) & 0xff) != bus->secondary) {
buses = (buses & 0xff000000)
- | ((unsigned int)(bus->primary) << 0)
- | ((unsigned int)(bus->secondary) << 8)
- | ((unsigned int)(bus->subordinate) << 16);
+ | ((unsigned int)(bus->primary) << 0)
+ | ((unsigned int)(bus->secondary) << 8)
+ | ((unsigned int)(bus->subordinate) << 16);
pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
}
return NOTIFY_OK;
@@ -184,17 +127,12 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
acpi_status status = AE_OK;
unsigned long long adr, sun;
int device, function, retval;
+ struct pci_bus *pbus = bridge->pci_bus;
- status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
-
- if (ACPI_FAILURE(status))
- return AE_OK;
-
- status = acpi_get_handle(handle, "_EJ0", &tmp);
-
- if (ACPI_FAILURE(status) && !(is_dock_device(handle)))
+ if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
return AE_OK;
+ acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
device = (adr >> 16) & 0xffff;
function = adr & 0xffff;
@@ -205,7 +143,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
INIT_LIST_HEAD(&newfunc->sibling);
newfunc->handle = handle;
newfunc->function = function;
- if (ACPI_SUCCESS(status))
+
+ if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
newfunc->flags = FUNC_HAS_EJ0;
if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp)))
@@ -256,8 +195,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
bridge->nr_slots++;
dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
- slot->sun, pci_domain_nr(bridge->pci_bus),
- bridge->pci_bus->number, slot->device);
+ slot->sun, pci_domain_nr(pbus), pbus->number, device);
retval = acpiphp_register_hotplug_slot(slot);
if (retval) {
if (retval == -EBUSY)
@@ -274,8 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
list_add_tail(&newfunc->sibling, &slot->funcs);
/* associate corresponding pci_dev */
- newfunc->pci_dev = pci_get_slot(bridge->pci_bus,
- PCI_DEVFN(device, function));
+ newfunc->pci_dev = pci_get_slot(pbus, PCI_DEVFN(device, function));
if (newfunc->pci_dev) {
slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
}
@@ -324,27 +261,17 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
/* see if it's worth looking at this bridge */
-static int detect_ejectable_slots(acpi_handle *bridge_handle)
+static int detect_ejectable_slots(struct pci_bus *pbus)
{
- acpi_status status;
- int count;
-
- count = 0;
-
- /* only check slots defined directly below bridge object */
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
- is_ejectable_slot, (void *)&count, NULL);
-
- /*
- * we also need to add this bridge if there is a dock bridge or
- * other pci device on a dock station (removable)
- */
- if (!count)
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle,
- (u32)1, is_pci_dock_device, (void *)&count,
- NULL);
-
- return count;
+ int found = acpi_pci_detect_ejectable(pbus);
+ if (!found) {
+ acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus);
+ if (!bridge_handle)
+ return 0;
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1,
+ is_pci_dock_device, (void *)&found, NULL);
+ }
+ return found;
}
@@ -554,7 +481,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
goto out;
/* check if this bridge has ejectable slots */
- if ((detect_ejectable_slots(handle) > 0)) {
+ if ((detect_ejectable_slots(dev->subordinate) > 0)) {
dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
add_p2p_bridge(handle, dev);
}
@@ -615,7 +542,7 @@ static int add_bridge(acpi_handle handle)
}
/* check if this bridge has ejectable slots */
- if (detect_ejectable_slots(handle) > 0) {
+ if (detect_ejectable_slots(pci_bus) > 0) {
dbg("found PCI host-bus bridge with hot-pluggable slots\n");
add_host_bridge(handle, pci_bus);
}
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 881fdd2b7313..5befa7e379b7 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -271,7 +271,7 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
dbg("%s: generationg bus event\n", __func__);
acpi_bus_generate_proc_event(note->device, note->event, detail);
acpi_bus_generate_netlink_event(note->device->pnp.device_class,
- note->device->dev.bus_id,
+ dev_name(&note->device->dev),
note->event, detail);
} else
note->event = event;
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 8514c3a1746a..c2e1bcbb28a7 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -45,7 +45,7 @@
#include "cpqphp.h"
#include "cpqphp_nvram.h"
-#include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */
+#include <asm/pci_x86.h>
/* Global variables */
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index a60a25290995..cc227a8c4b11 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -1954,7 +1954,7 @@ void cpqhp_pushbutton_thread(unsigned long slot)
return ;
}
- if (func != NULL && ctrl != NULL) {
+ if (ctrl != NULL) {
if (cpqhp_process_SI(ctrl, func) != 0) {
amber_LED_on(ctrl, hp_slot);
green_LED_off(ctrl, hp_slot);
@@ -2604,7 +2604,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
for (cloop = 0; cloop < 4; cloop++) {
if (irqs.valid_INT & (0x01 << cloop)) {
rc = cpqhp_set_irq(func->bus, func->device,
- 0x0A + cloop, irqs.interrupt[cloop]);
+ cloop + 1, irqs.interrupt[cloop]);
if (rc)
goto free_and_out;
}
@@ -2945,7 +2945,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
}
if (!behind_bridge) {
- rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ);
+ rc = cpqhp_set_irq(func->bus, func->device, temp_byte, IRQ);
if (rc)
return 1;
} else {
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
index 09021930589f..6c0ed0fcb8ee 100644
--- a/drivers/pci/hotplug/cpqphp_pci.c
+++ b/drivers/pci/hotplug/cpqphp_pci.c
@@ -37,7 +37,7 @@
#include "../pci.h"
#include "cpqphp.h"
#include "cpqphp_nvram.h"
-#include "../../../arch/x86/pci/pci.h" /* horrible hack showing how processor dependent we are... */
+#include <asm/pci_x86.h>
u8 cpqhp_nic_irq;
@@ -171,7 +171,7 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
fakebus->number = bus_num;
dbg("%s: dev %d, bus %d, pin %d, num %d\n",
__func__, dev_num, bus_num, int_pin, irq_num);
- rc = pcibios_set_irq_routing(fakedev, int_pin - 0x0a, irq_num);
+ rc = pcibios_set_irq_routing(fakedev, int_pin - 1, irq_num);
kfree(fakedev);
kfree(fakebus);
dbg("%s: rc %d\n", __func__, rc);
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 3a2637a00934..d8649e127298 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -195,13 +195,13 @@ static void remove_slot_worker(struct work_struct *work)
* Tries hard not to re-enable already existing devices;
* also handles scanning of subfunctions.
*/
-static void pci_rescan_slot(struct pci_dev *temp)
+static int pci_rescan_slot(struct pci_dev *temp)
{
struct pci_bus *bus = temp->bus;
struct pci_dev *dev;
int func;
- int retval;
u8 hdr_type;
+ int count = 0;
if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
temp->hdr_type = hdr_type & 0x7f;
@@ -213,17 +213,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
dbg("New device on %s function %x:%x\n",
bus->name, temp->devfn >> 3,
temp->devfn & 7);
- retval = pci_bus_add_device(dev);
- if (retval)
- dev_err(&dev->dev, "error adding "
- "device, continuing.\n");
- else
- add_slot(dev);
+ count++;
}
}
/* multifunction device? */
if (!(hdr_type & 0x80))
- return;
+ return count;
/* continue scanning for other functions */
for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) {
@@ -239,16 +234,13 @@ static void pci_rescan_slot(struct pci_dev *temp)
dbg("New device on %s function %x:%x\n",
bus->name, temp->devfn >> 3,
temp->devfn & 7);
- retval = pci_bus_add_device(dev);
- if (retval)
- dev_err(&dev->dev, "error adding "
- "device, continuing.\n");
- else
- add_slot(dev);
+ count++;
}
}
}
}
+
+ return count;
}
@@ -262,6 +254,8 @@ static void pci_rescan_bus(const struct pci_bus *bus)
{
unsigned int devfn;
struct pci_dev *dev;
+ int retval;
+ int found = 0;
dev = alloc_pci_dev();
if (!dev)
return;
@@ -270,7 +264,23 @@ static void pci_rescan_bus(const struct pci_bus *bus)
dev->sysdata = bus->sysdata;
for (devfn = 0; devfn < 0x100; devfn += 8) {
dev->devfn = devfn;
- pci_rescan_slot(dev);
+ found += pci_rescan_slot(dev);
+ }
+
+ if (found) {
+ pci_bus_assign_resources(bus);
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ /* Skip already-added devices */
+ if (dev->is_added)
+ continue;
+ retval = pci_bus_add_device(dev);
+ if (retval)
+ dev_err(&dev->dev,
+ "Error adding device, continuing\n");
+ else
+ add_slot(dev);
+ }
+ pci_bus_add_devices(bus);
}
kfree(dev);
}
@@ -324,6 +334,7 @@ static int disable_slot(struct hotplug_slot *slot)
if (test_and_set_bit(0, &dslot->removed)) {
dbg("Slot already scheduled for removal\n");
+ pci_dev_put(dev);
return -ENODEV;
}
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 633e743442ac..dd18f857dfb0 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -35,7 +35,7 @@
#include <linux/delay.h>
#include <linux/wait.h>
#include "../pci.h"
-#include "../../../arch/x86/pci/pci.h" /* for struct irq_routing_table */
+#include <asm/pci_x86.h> /* for struct irq_routing_table */
#include "ibmphp.h"
#define attn_on(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index b2801a7ee37f..db85284ffb62 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -217,14 +217,25 @@ struct hpc_ops {
#ifdef CONFIG_ACPI
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
#include <linux/pci-acpi.h>
+extern void __init pciehp_acpi_slot_detection_init(void);
+extern int pciehp_acpi_slot_detection_check(struct pci_dev *dev);
+
+static inline void pciehp_firmware_init(void)
+{
+ pciehp_acpi_slot_detection_init();
+}
+
static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
+ int retval;
u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
- return acpi_get_hp_hw_control_from_firmware(dev, flags);
+ retval = acpi_get_hp_hw_control_from_firmware(dev, flags);
+ if (retval)
+ return retval;
+ return pciehp_acpi_slot_detection_check(dev);
}
static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
@@ -235,6 +246,7 @@ static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
return 0;
}
#else
+#define pciehp_firmware_init() do {} while (0)
#define pciehp_get_hp_hw_control_from_firmware(dev) 0
#define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV)
#endif /* CONFIG_ACPI */
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
new file mode 100644
index 000000000000..438d795f9fe3
--- /dev/null
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -0,0 +1,141 @@
+/*
+ * ACPI related functions for PCI Express Hot Plug driver.
+ *
+ * Copyright (C) 2008 Kenji Kaneshige
+ * Copyright (C) 2008 Fujitsu Limited.
+ *
+ * All rights reserved.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
+#include "pciehp.h"
+
+#define PCIEHP_DETECT_PCIE (0)
+#define PCIEHP_DETECT_ACPI (1)
+#define PCIEHP_DETECT_AUTO (2)
+#define PCIEHP_DETECT_DEFAULT PCIEHP_DETECT_AUTO
+
+static int slot_detection_mode;
+static char *pciehp_detect_mode;
+module_param(pciehp_detect_mode, charp, 0444);
+MODULE_PARM_DESC(pciehp_detect_mode,
+ "Slot detection mode: pcie, acpi, auto\n"
+ " pcie - Use PCIe based slot detection\n"
+ " acpi - Use ACPI for slot detection\n"
+ " auto(default) - Auto select mode. Use acpi option if duplicate\n"
+ " slot ids are found. Otherwise, use pcie option\n");
+
+int pciehp_acpi_slot_detection_check(struct pci_dev *dev)
+{
+ if (slot_detection_mode != PCIEHP_DETECT_ACPI)
+ return 0;
+ if (acpi_pci_detect_ejectable(dev->subordinate))
+ return 0;
+ return -ENODEV;
+}
+
+static int __init parse_detect_mode(void)
+{
+ if (!pciehp_detect_mode)
+ return PCIEHP_DETECT_DEFAULT;
+ if (!strcmp(pciehp_detect_mode, "pcie"))
+ return PCIEHP_DETECT_PCIE;
+ if (!strcmp(pciehp_detect_mode, "acpi"))
+ return PCIEHP_DETECT_ACPI;
+ if (!strcmp(pciehp_detect_mode, "auto"))
+ return PCIEHP_DETECT_AUTO;
+ warn("bad specifier '%s' for pciehp_detect_mode. Use default\n",
+ pciehp_detect_mode);
+ return PCIEHP_DETECT_DEFAULT;
+}
+
+static struct pcie_port_service_id __initdata port_pci_ids[] = {
+ {
+ .vendor = PCI_ANY_ID,
+ .device = PCI_ANY_ID,
+ .port_type = PCIE_ANY_PORT,
+ .service_type = PCIE_PORT_SERVICE_HP,
+ .driver_data = 0,
+ }, { /* end: all zeroes */ }
+};
+
+static int __initdata dup_slot_id;
+static int __initdata acpi_slot_detected;
+static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots);
+
+/* Dummy driver for dumplicate name detection */
+static int __init dummy_probe(struct pcie_device *dev,
+ const struct pcie_port_service_id *id)
+{
+ int pos;
+ u32 slot_cap;
+ struct slot *slot, *tmp;
+ struct pci_dev *pdev = dev->port;
+ struct pci_bus *pbus = pdev->subordinate;
+ if (!(slot = kzalloc(sizeof(*slot), GFP_KERNEL)))
+ return -ENOMEM;
+ /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
+ if (pciehp_get_hp_hw_control_from_firmware(pdev))
+ return -ENODEV;
+ if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP)))
+ return -ENODEV;
+ pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap);
+ slot->number = slot_cap >> 19;
+ list_for_each_entry(tmp, &dummy_slots, slot_list) {
+ if (tmp->number == slot->number)
+ dup_slot_id++;
+ }
+ list_add_tail(&slot->slot_list, &dummy_slots);
+ if (!acpi_slot_detected && acpi_pci_detect_ejectable(pbus))
+ acpi_slot_detected = 1;
+ return -ENODEV; /* dummy driver always returns error */
+}
+
+static struct pcie_port_service_driver __initdata dummy_driver = {
+ .name = "pciehp_dummy",
+ .id_table = port_pci_ids,
+ .probe = dummy_probe,
+};
+
+static int __init select_detection_mode(void)
+{
+ struct slot *slot, *tmp;
+ pcie_port_service_register(&dummy_driver);
+ pcie_port_service_unregister(&dummy_driver);
+ list_for_each_entry_safe(slot, tmp, &dummy_slots, slot_list) {
+ list_del(&slot->slot_list);
+ kfree(slot);
+ }
+ if (acpi_slot_detected && dup_slot_id)
+ return PCIEHP_DETECT_ACPI;
+ return PCIEHP_DETECT_PCIE;
+}
+
+void __init pciehp_acpi_slot_detection_init(void)
+{
+ slot_detection_mode = parse_detect_mode();
+ if (slot_detection_mode != PCIEHP_DETECT_AUTO)
+ goto out;
+ slot_detection_mode = select_detection_mode();
+out:
+ if (slot_detection_mode == PCIEHP_DETECT_ACPI)
+ info("Using ACPI for slot detection.\n");
+}
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 39cf248d24e3..c2485542f543 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -126,8 +126,10 @@ static int set_lock_status(struct hotplug_slot *hotplug_slot, u8 status)
mutex_lock(&slot->ctrl->crit_sect);
/* has it been >1 sec since our last toggle? */
- if ((get_seconds() - slot->last_emi_toggle) < 1)
+ if ((get_seconds() - slot->last_emi_toggle) < 1) {
+ mutex_unlock(&slot->ctrl->crit_sect);
return -EINVAL;
+ }
/* see what our current state is */
retval = get_lock_status(hotplug_slot, &value);
@@ -522,6 +524,7 @@ static int __init pcied_init(void)
{
int retval = 0;
+ pciehp_firmware_init();
retval = pcie_port_service_register(&hpdriver_portdrv);
dbg("pcie_port_service_register = %d\n", retval);
info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index fead63c6b49e..ff4034502d24 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -178,15 +178,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
"Issue of Slot Power Off command failed\n");
return;
}
+ /*
+ * After turning power off, we must wait for at least 1 second
+ * before taking any action that relies on power having been
+ * removed from the slot/adapter.
+ */
+ msleep(1000);
}
- /*
- * After turning power off, we must wait for at least 1 second
- * before taking any action that relies on power having been
- * removed from the slot/adapter.
- */
- msleep(1000);
-
if (PWR_LED(ctrl))
pslot->hpc_ops->green_led_off(pslot);
@@ -286,15 +285,14 @@ static int remove_board(struct slot *p_slot)
"Issue of Slot Disable command failed\n");
return retval;
}
+ /*
+ * After turning power off, we must wait for at least 1 second
+ * before taking any action that relies on power having been
+ * removed from the slot/adapter.
+ */
+ msleep(1000);
}
- /*
- * After turning power off, we must wait for at least 1 second
- * before taking any action that relies on power having been
- * removed from the slot/adapter.
- */
- msleep(1000);
-
if (PWR_LED(ctrl))
/* turn off Green LED */
p_slot->hpc_ops->green_led_off(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index b643ca13e4f1..71a8012886b0 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -42,42 +42,6 @@
static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
-struct ctrl_reg {
- u8 cap_id;
- u8 nxt_ptr;
- u16 cap_reg;
- u32 dev_cap;
- u16 dev_ctrl;
- u16 dev_status;
- u32 lnk_cap;
- u16 lnk_ctrl;
- u16 lnk_status;
- u32 slot_cap;
- u16 slot_ctrl;
- u16 slot_status;
- u16 root_ctrl;
- u16 rsvp;
- u32 root_status;
-} __attribute__ ((packed));
-
-/* offsets to the controller registers based on the above structure layout */
-enum ctrl_offsets {
- PCIECAPID = offsetof(struct ctrl_reg, cap_id),
- NXTCAPPTR = offsetof(struct ctrl_reg, nxt_ptr),
- CAPREG = offsetof(struct ctrl_reg, cap_reg),
- DEVCAP = offsetof(struct ctrl_reg, dev_cap),
- DEVCTRL = offsetof(struct ctrl_reg, dev_ctrl),
- DEVSTATUS = offsetof(struct ctrl_reg, dev_status),
- LNKCAP = offsetof(struct ctrl_reg, lnk_cap),
- LNKCTRL = offsetof(struct ctrl_reg, lnk_ctrl),
- LNKSTATUS = offsetof(struct ctrl_reg, lnk_status),
- SLOTCAP = offsetof(struct ctrl_reg, slot_cap),
- SLOTCTRL = offsetof(struct ctrl_reg, slot_ctrl),
- SLOTSTATUS = offsetof(struct ctrl_reg, slot_status),
- ROOTCTRL = offsetof(struct ctrl_reg, root_ctrl),
- ROOTSTATUS = offsetof(struct ctrl_reg, root_status),
-};
-
static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
{
struct pci_dev *dev = ctrl->pci_dev;
@@ -102,95 +66,9 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
return pci_write_config_dword(dev, ctrl->cap_base + reg, value);
}
-/* Field definitions in PCI Express Capabilities Register */
-#define CAP_VER 0x000F
-#define DEV_PORT_TYPE 0x00F0
-#define SLOT_IMPL 0x0100
-#define MSG_NUM 0x3E00
-
-/* Device or Port Type */
-#define NAT_ENDPT 0x00
-#define LEG_ENDPT 0x01
-#define ROOT_PORT 0x04
-#define UP_STREAM 0x05
-#define DN_STREAM 0x06
-#define PCIE_PCI_BRDG 0x07
-#define PCI_PCIE_BRDG 0x10
-
-/* Field definitions in Device Capabilities Register */
-#define DATTN_BUTTN_PRSN 0x1000
-#define DATTN_LED_PRSN 0x2000
-#define DPWR_LED_PRSN 0x4000
-
-/* Field definitions in Link Capabilities Register */
-#define MAX_LNK_SPEED 0x000F
-#define MAX_LNK_WIDTH 0x03F0
-#define LINK_ACTIVE_REPORTING 0x00100000
-
-/* Link Width Encoding */
-#define LNK_X1 0x01
-#define LNK_X2 0x02
-#define LNK_X4 0x04
-#define LNK_X8 0x08
-#define LNK_X12 0x0C
-#define LNK_X16 0x10
-#define LNK_X32 0x20
-
-/*Field definitions of Link Status Register */
-#define LNK_SPEED 0x000F
-#define NEG_LINK_WD 0x03F0
-#define LNK_TRN_ERR 0x0400
-#define LNK_TRN 0x0800
-#define SLOT_CLK_CONF 0x1000
-#define LINK_ACTIVE 0x2000
-
-/* Field definitions in Slot Capabilities Register */
-#define ATTN_BUTTN_PRSN 0x00000001
-#define PWR_CTRL_PRSN 0x00000002
-#define MRL_SENS_PRSN 0x00000004
-#define ATTN_LED_PRSN 0x00000008
-#define PWR_LED_PRSN 0x00000010
-#define HP_SUPR_RM_SUP 0x00000020
-#define HP_CAP 0x00000040
-#define SLOT_PWR_VALUE 0x000003F8
-#define SLOT_PWR_LIMIT 0x00000C00
-#define PSN 0xFFF80000 /* PSN: Physical Slot Number */
-
-/* Field definitions in Slot Control Register */
-#define ATTN_BUTTN_ENABLE 0x0001
-#define PWR_FAULT_DETECT_ENABLE 0x0002
-#define MRL_DETECT_ENABLE 0x0004
-#define PRSN_DETECT_ENABLE 0x0008
-#define CMD_CMPL_INTR_ENABLE 0x0010
-#define HP_INTR_ENABLE 0x0020
-#define ATTN_LED_CTRL 0x00C0
-#define PWR_LED_CTRL 0x0300
-#define PWR_CTRL 0x0400
-#define EMI_CTRL 0x0800
-
-/* Attention indicator and Power indicator states */
-#define LED_ON 0x01
-#define LED_BLINK 0x10
-#define LED_OFF 0x11
-
/* Power Control Command */
#define POWER_ON 0
-#define POWER_OFF 0x0400
-
-/* EMI Status defines */
-#define EMI_DISENGAGED 0
-#define EMI_ENGAGED 1
-
-/* Field definitions in Slot Status Register */
-#define ATTN_BUTTN_PRESSED 0x0001
-#define PWR_FAULT_DETECTED 0x0002
-#define MRL_SENS_CHANGED 0x0004
-#define PRSN_DETECT_CHANGED 0x0008
-#define CMD_COMPLETED 0x0010
-#define MRL_STATE 0x0020
-#define PRSN_STATE 0x0040
-#define EMI_STATE 0x0080
-#define EMI_STATUS_BIT 7
+#define POWER_OFF PCI_EXP_SLTCTL_PCC
static irqreturn_t pcie_isr(int irq, void *dev_id);
static void start_int_poll_timer(struct controller *ctrl, int sec);
@@ -253,22 +131,20 @@ static inline void pciehp_free_irq(struct controller *ctrl)
static int pcie_poll_cmd(struct controller *ctrl)
{
u16 slot_status;
- int timeout = 1000;
+ int err, timeout = 1000;
- if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) {
- if (slot_status & CMD_COMPLETED) {
- pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
- return 1;
- }
+ err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
+ if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) {
+ pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC);
+ return 1;
}
while (timeout > 0) {
msleep(10);
timeout -= 10;
- if (!pciehp_readw(ctrl, SLOTSTATUS, &slot_status)) {
- if (slot_status & CMD_COMPLETED) {
- pciehp_writew(ctrl, SLOTSTATUS, CMD_COMPLETED);
- return 1;
- }
+ err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
+ if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) {
+ pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC);
+ return 1;
}
}
return 0; /* timeout */
@@ -302,14 +178,14 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
mutex_lock(&ctrl->ctrl_lock);
- retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
__func__);
goto out;
}
- if (slot_status & CMD_COMPLETED) {
+ if (slot_status & PCI_EXP_SLTSTA_CC) {
if (!ctrl->no_cmd_complete) {
/*
* After 1 sec and CMD_COMPLETED still not set, just
@@ -332,7 +208,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
}
}
- retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
goto out;
@@ -342,7 +218,7 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
slot_ctrl |= (cmd & mask);
ctrl->cmd_busy = 1;
smp_mb();
- retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
+ retval = pciehp_writew(ctrl, PCI_EXP_SLTCTL, slot_ctrl);
if (retval)
ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n");
@@ -356,8 +232,8 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
* completed interrupt is not enabled, we need to poll
* command completed event.
*/
- if (!(slot_ctrl & HP_INTR_ENABLE) ||
- !(slot_ctrl & CMD_CMPL_INTR_ENABLE))
+ if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) ||
+ !(slot_ctrl & PCI_EXP_SLTCTL_CCIE))
poll = 1;
pcie_wait_cmd(ctrl, poll);
}
@@ -370,9 +246,9 @@ static inline int check_link_active(struct controller *ctrl)
{
u16 link_status;
- if (pciehp_readw(ctrl, LNKSTATUS, &link_status))
+ if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &link_status))
return 0;
- return !!(link_status & LINK_ACTIVE);
+ return !!(link_status & PCI_EXP_LNKSTA_DLLLA);
}
static void pcie_wait_link_active(struct controller *ctrl)
@@ -412,15 +288,15 @@ static int hpc_check_lnk_status(struct controller *ctrl)
} else
msleep(1000);
- retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
if (retval) {
ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
return retval;
}
ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
- if ( (lnk_status & LNK_TRN) || (lnk_status & LNK_TRN_ERR) ||
- !(lnk_status & NEG_LINK_WD)) {
+ if ((lnk_status & PCI_EXP_LNKSTA_LT) ||
+ !(lnk_status & PCI_EXP_LNKSTA_NLW)) {
ctrl_err(ctrl, "Link Training Error occurs \n");
retval = -1;
return retval;
@@ -436,16 +312,16 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
u8 atten_led_state;
int retval = 0;
- retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
return retval;
}
ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl);
- atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
+ atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6;
switch (atten_led_state) {
case 0:
@@ -475,15 +351,15 @@ static int hpc_get_power_status(struct slot *slot, u8 *status)
u8 pwr_state;
int retval = 0;
- retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
return retval;
}
ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl);
- pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
+ pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10;
switch (pwr_state) {
case 0:
@@ -504,17 +380,15 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
{
struct controller *ctrl = slot->ctrl;
u16 slot_status;
- int retval = 0;
+ int retval;
- retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
__func__);
return retval;
}
-
- *status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1;
-
+ *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS);
return 0;
}
@@ -522,18 +396,15 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
{
struct controller *ctrl = slot->ctrl;
u16 slot_status;
- u8 card_state;
- int retval = 0;
+ int retval;
- retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
__func__);
return retval;
}
- card_state = (u8)((slot_status & PRSN_STATE) >> 6);
- *status = (card_state == 1) ? 1 : 0;
-
+ *status = !!(slot_status & PCI_EXP_SLTSTA_PDS);
return 0;
}
@@ -541,32 +412,28 @@ static int hpc_query_power_fault(struct slot *slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_status;
- u8 pwr_fault;
- int retval = 0;
+ int retval;
- retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "Cannot check for power fault\n");
return retval;
}
- pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
-
- return pwr_fault;
+ return !!(slot_status & PCI_EXP_SLTSTA_PFD);
}
static int hpc_get_emi_status(struct slot *slot, u8 *status)
{
struct controller *ctrl = slot->ctrl;
u16 slot_status;
- int retval = 0;
+ int retval;
- retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "Cannot check EMI status\n");
return retval;
}
- *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT;
-
+ *status = !!(slot_status & PCI_EXP_SLTSTA_EIS);
return retval;
}
@@ -576,8 +443,8 @@ static int hpc_toggle_emi(struct slot *slot)
u16 cmd_mask;
int rc;
- slot_cmd = EMI_CTRL;
- cmd_mask = EMI_CTRL;
+ slot_cmd = PCI_EXP_SLTCTL_EIC;
+ cmd_mask = PCI_EXP_SLTCTL_EIC;
rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
slot->last_emi_toggle = get_seconds();
@@ -591,7 +458,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
u16 cmd_mask;
int rc;
- cmd_mask = ATTN_LED_CTRL;
+ cmd_mask = PCI_EXP_SLTCTL_AIC;
switch (value) {
case 0 : /* turn off */
slot_cmd = 0x00C0;
@@ -607,7 +474,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
}
rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
return rc;
}
@@ -619,10 +486,10 @@ static void hpc_set_green_led_on(struct slot *slot)
u16 cmd_mask;
slot_cmd = 0x0100;
- cmd_mask = PWR_LED_CTRL;
+ cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
}
static void hpc_set_green_led_off(struct slot *slot)
@@ -632,10 +499,10 @@ static void hpc_set_green_led_off(struct slot *slot)
u16 cmd_mask;
slot_cmd = 0x0300;
- cmd_mask = PWR_LED_CTRL;
+ cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
}
static void hpc_set_green_led_blink(struct slot *slot)
@@ -645,10 +512,10 @@ static void hpc_set_green_led_blink(struct slot *slot)
u16 cmd_mask;
slot_cmd = 0x0200;
- cmd_mask = PWR_LED_CTRL;
+ cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
}
static int hpc_power_on_slot(struct slot * slot)
@@ -662,15 +529,15 @@ static int hpc_power_on_slot(struct slot * slot)
ctrl_dbg(ctrl, "%s: slot->hp_slot %x\n", __func__, slot->hp_slot);
/* Clear sticky power-fault bit from previous power failures */
- retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n",
__func__);
return retval;
}
- slot_status &= PWR_FAULT_DETECTED;
+ slot_status &= PCI_EXP_SLTSTA_PFD;
if (slot_status) {
- retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status);
+ retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status);
if (retval) {
ctrl_err(ctrl,
"%s: Cannot write to SLOTSTATUS register\n",
@@ -680,13 +547,13 @@ static int hpc_power_on_slot(struct slot * slot)
}
slot_cmd = POWER_ON;
- cmd_mask = PWR_CTRL;
+ cmd_mask = PCI_EXP_SLTCTL_PCC;
/* Enable detection that we turned off at slot power-off time */
if (!pciehp_poll_mode) {
- slot_cmd |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
- PRSN_DETECT_ENABLE);
- cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
- PRSN_DETECT_ENABLE);
+ slot_cmd |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
+ PCI_EXP_SLTCTL_PDCE);
+ cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
+ PCI_EXP_SLTCTL_PDCE);
}
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
@@ -696,7 +563,7 @@ static int hpc_power_on_slot(struct slot * slot)
return -1;
}
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
return retval;
}
@@ -753,7 +620,7 @@ static int hpc_power_off_slot(struct slot * slot)
changed = pcie_mask_bad_dllp(ctrl);
slot_cmd = POWER_OFF;
- cmd_mask = PWR_CTRL;
+ cmd_mask = PCI_EXP_SLTCTL_PCC;
/*
* If we get MRL or presence detect interrupts now, the isr
* will notice the sticky power-fault bit too and issue power
@@ -762,10 +629,10 @@ static int hpc_power_off_slot(struct slot * slot)
* till the slot is powered on again.
*/
if (!pciehp_poll_mode) {
- slot_cmd &= ~(PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
- PRSN_DETECT_ENABLE);
- cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
- PRSN_DETECT_ENABLE);
+ slot_cmd &= ~(PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
+ PCI_EXP_SLTCTL_PDCE);
+ cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE |
+ PCI_EXP_SLTCTL_PDCE);
}
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
@@ -775,7 +642,7 @@ static int hpc_power_off_slot(struct slot * slot)
goto out;
}
ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
out:
if (changed)
pcie_unmask_bad_dllp(ctrl);
@@ -796,19 +663,19 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
*/
intr_loc = 0;
do {
- if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) {
+ if (pciehp_readw(ctrl, PCI_EXP_SLTSTA, &detected)) {
ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n",
__func__);
return IRQ_NONE;
}
- detected &= (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
- MRL_SENS_CHANGED | PRSN_DETECT_CHANGED |
- CMD_COMPLETED);
+ detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
+ PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC |
+ PCI_EXP_SLTSTA_CC);
intr_loc |= detected;
if (!intr_loc)
return IRQ_NONE;
- if (detected && pciehp_writew(ctrl, SLOTSTATUS, detected)) {
+ if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, detected)) {
ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n",
__func__);
return IRQ_NONE;
@@ -818,31 +685,31 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc);
/* Check Command Complete Interrupt Pending */
- if (intr_loc & CMD_COMPLETED) {
+ if (intr_loc & PCI_EXP_SLTSTA_CC) {
ctrl->cmd_busy = 0;
smp_mb();
wake_up(&ctrl->queue);
}
- if (!(intr_loc & ~CMD_COMPLETED))
+ if (!(intr_loc & ~PCI_EXP_SLTSTA_CC))
return IRQ_HANDLED;
p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
/* Check MRL Sensor Changed */
- if (intr_loc & MRL_SENS_CHANGED)
+ if (intr_loc & PCI_EXP_SLTSTA_MRLSC)
pciehp_handle_switch_change(p_slot);
/* Check Attention Button Pressed */
- if (intr_loc & ATTN_BUTTN_PRESSED)
+ if (intr_loc & PCI_EXP_SLTSTA_ABP)
pciehp_handle_attention_button(p_slot);
/* Check Presence Detect Changed */
- if (intr_loc & PRSN_DETECT_CHANGED)
+ if (intr_loc & PCI_EXP_SLTSTA_PDC)
pciehp_handle_presence_change(p_slot);
/* Check Power Fault Detected */
- if (intr_loc & PWR_FAULT_DETECTED)
+ if (intr_loc & PCI_EXP_SLTSTA_PFD)
pciehp_handle_power_fault(p_slot);
return IRQ_HANDLED;
@@ -855,7 +722,7 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
u32 lnk_cap;
int retval = 0;
- retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
+ retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
return retval;
@@ -884,13 +751,13 @@ static int hpc_get_max_lnk_width(struct slot *slot,
u32 lnk_cap;
int retval = 0;
- retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap);
+ retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
return retval;
}
- switch ((lnk_cap & 0x03F0) >> 4){
+ switch ((lnk_cap & PCI_EXP_LNKSTA_NLW) >> 4){
case 0:
lnk_wdth = PCIE_LNK_WIDTH_RESRV;
break;
@@ -933,14 +800,14 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value)
int retval = 0;
u16 lnk_status;
- retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
__func__);
return retval;
}
- switch (lnk_status & 0x0F) {
+ switch (lnk_status & PCI_EXP_LNKSTA_CLS) {
case 1:
lnk_speed = PCIE_2PT5GB;
break;
@@ -963,14 +830,14 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
int retval = 0;
u16 lnk_status;
- retval = pciehp_readw(ctrl, LNKSTATUS, &lnk_status);
+ retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
if (retval) {
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
__func__);
return retval;
}
- switch ((lnk_status & 0x03F0) >> 4){
+ switch ((lnk_status & PCI_EXP_LNKSTA_NLW) >> 4){
case 0:
lnk_wdth = PCIE_LNK_WIDTH_RESRV;
break;
@@ -1036,18 +903,19 @@ int pcie_enable_notification(struct controller *ctrl)
{
u16 cmd, mask;
- cmd = PRSN_DETECT_ENABLE;
+ cmd = PCI_EXP_SLTCTL_PDCE;
if (ATTN_BUTTN(ctrl))
- cmd |= ATTN_BUTTN_ENABLE;
+ cmd |= PCI_EXP_SLTCTL_ABPE;
if (POWER_CTRL(ctrl))
- cmd |= PWR_FAULT_DETECT_ENABLE;
+ cmd |= PCI_EXP_SLTCTL_PFDE;
if (MRL_SENS(ctrl))
- cmd |= MRL_DETECT_ENABLE;
+ cmd |= PCI_EXP_SLTCTL_MRLSCE;
if (!pciehp_poll_mode)
- cmd |= HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
+ cmd |= PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE;
- mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
- PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
+ mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
+ PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
+ PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
if (pcie_write_cmd(ctrl, cmd, mask)) {
ctrl_err(ctrl, "Cannot enable software notification\n");
@@ -1059,8 +927,9 @@ int pcie_enable_notification(struct controller *ctrl)
static void pcie_disable_notification(struct controller *ctrl)
{
u16 mask;
- mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
- PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
+ mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
+ PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
+ PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
if (pcie_write_cmd(ctrl, 0, mask))
ctrl_warn(ctrl, "Cannot disable software notification\n");
}
@@ -1157,9 +1026,9 @@ static inline void dbg_ctrl(struct controller *ctrl)
EMI(ctrl) ? "yes" : "no");
ctrl_info(ctrl, " Command Completed : %3s\n",
NO_CMD_CMPL(ctrl) ? "no" : "yes");
- pciehp_readw(ctrl, SLOTSTATUS, &reg16);
+ pciehp_readw(ctrl, PCI_EXP_SLTSTA, &reg16);
ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16);
- pciehp_readw(ctrl, SLOTCTRL, &reg16);
+ pciehp_readw(ctrl, PCI_EXP_SLTCTL, &reg16);
ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16);
}
@@ -1183,7 +1052,7 @@ struct controller *pcie_init(struct pcie_device *dev)
ctrl_err(ctrl, "Cannot find PCI Express capability\n");
goto abort_ctrl;
}
- if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
+ if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) {
ctrl_err(ctrl, "Cannot read SLOTCAP register\n");
goto abort_ctrl;
}
@@ -1208,17 +1077,17 @@ struct controller *pcie_init(struct pcie_device *dev)
ctrl->no_cmd_complete = 1;
/* Check if Data Link Layer Link Active Reporting is implemented */
- if (pciehp_readl(ctrl, LNKCAP, &link_cap)) {
+ if (pciehp_readl(ctrl, PCI_EXP_LNKCAP, &link_cap)) {
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
goto abort_ctrl;
}
- if (link_cap & LINK_ACTIVE_REPORTING) {
+ if (link_cap & PCI_EXP_LNKCAP_DLLLARC) {
ctrl_dbg(ctrl, "Link Active Reporting supported\n");
ctrl->link_active_reporting = 1;
}
/* Clear all remaining event bits in Slot Status register */
- if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f))
+ if (pciehp_writew(ctrl, PCI_EXP_SLTSTA, 0x1f))
goto abort_ctrl;
/* Disable sotfware notification */
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 5c8baa43ac9c..3dfecb20d5e7 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -27,7 +27,6 @@
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-#include <linux/sysdev.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/dmar.h>
@@ -35,6 +34,7 @@
#include <linux/mempool.h>
#include <linux/timer.h>
#include <linux/iova.h>
+#include <linux/iommu.h>
#include <linux/intel-iommu.h>
#include <asm/cacheflush.h>
#include <asm/iommu.h>
@@ -54,6 +54,195 @@
#define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
+#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
+#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK)
+#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK)
+
+/* global iommu list, set NULL for ignored DMAR units */
+static struct intel_iommu **g_iommus;
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+ u64 val;
+ u64 rsvd1;
+};
+#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
+static inline bool root_present(struct root_entry *root)
+{
+ return (root->val & 1);
+}
+static inline void set_root_present(struct root_entry *root)
+{
+ root->val |= 1;
+}
+static inline void set_root_value(struct root_entry *root, unsigned long value)
+{
+ root->val |= value & VTD_PAGE_MASK;
+}
+
+static inline struct context_entry *
+get_context_addr_from_root(struct root_entry *root)
+{
+ return (struct context_entry *)
+ (root_present(root)?phys_to_virt(
+ root->val & VTD_PAGE_MASK) :
+ NULL);
+}
+
+/*
+ * low 64 bits:
+ * 0: present
+ * 1: fault processing disable
+ * 2-3: translation type
+ * 12-63: address space root
+ * high 64 bits:
+ * 0-2: address width
+ * 3-6: aval
+ * 8-23: domain id
+ */
+struct context_entry {
+ u64 lo;
+ u64 hi;
+};
+
+static inline bool context_present(struct context_entry *context)
+{
+ return (context->lo & 1);
+}
+static inline void context_set_present(struct context_entry *context)
+{
+ context->lo |= 1;
+}
+
+static inline void context_set_fault_enable(struct context_entry *context)
+{
+ context->lo &= (((u64)-1) << 2) | 1;
+}
+
+#define CONTEXT_TT_MULTI_LEVEL 0
+
+static inline void context_set_translation_type(struct context_entry *context,
+ unsigned long value)
+{
+ context->lo &= (((u64)-1) << 4) | 3;
+ context->lo |= (value & 3) << 2;
+}
+
+static inline void context_set_address_root(struct context_entry *context,
+ unsigned long value)
+{
+ context->lo |= value & VTD_PAGE_MASK;
+}
+
+static inline void context_set_address_width(struct context_entry *context,
+ unsigned long value)
+{
+ context->hi |= value & 7;
+}
+
+static inline void context_set_domain_id(struct context_entry *context,
+ unsigned long value)
+{
+ context->hi |= (value & ((1 << 16) - 1)) << 8;
+}
+
+static inline void context_clear_entry(struct context_entry *context)
+{
+ context->lo = 0;
+ context->hi = 0;
+}
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-11: available
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+ u64 val;
+};
+
+static inline void dma_clear_pte(struct dma_pte *pte)
+{
+ pte->val = 0;
+}
+
+static inline void dma_set_pte_readable(struct dma_pte *pte)
+{
+ pte->val |= DMA_PTE_READ;
+}
+
+static inline void dma_set_pte_writable(struct dma_pte *pte)
+{
+ pte->val |= DMA_PTE_WRITE;
+}
+
+static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot)
+{
+ pte->val = (pte->val & ~3) | (prot & 3);
+}
+
+static inline u64 dma_pte_addr(struct dma_pte *pte)
+{
+ return (pte->val & VTD_PAGE_MASK);
+}
+
+static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr)
+{
+ pte->val |= (addr & VTD_PAGE_MASK);
+}
+
+static inline bool dma_pte_present(struct dma_pte *pte)
+{
+ return (pte->val & 3) != 0;
+}
+
+/* devices under the same p2p bridge are owned in one domain */
+#define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0)
+
+/* domain represents a virtual machine, more than one devices
+ * across iommus may be owned in one domain, e.g. kvm guest.
+ */
+#define DOMAIN_FLAG_VIRTUAL_MACHINE (1 << 1)
+
+struct dmar_domain {
+ int id; /* domain id */
+ unsigned long iommu_bmp; /* bitmap of iommus this domain uses*/
+
+ struct list_head devices; /* all devices' list */
+ struct iova_domain iovad; /* iova's that belong to this domain */
+
+ struct dma_pte *pgd; /* virtual address */
+ spinlock_t mapping_lock; /* page table lock */
+ int gaw; /* max guest address width */
+
+ /* adjusted guest address width, 0 is level 2 30-bit */
+ int agaw;
+
+ int flags; /* flags to find out type of domain */
+
+ int iommu_coherency;/* indicate coherency of iommu access */
+ int iommu_count; /* reference count of iommu */
+ spinlock_t iommu_lock; /* protect iommu set in domain */
+ u64 max_addr; /* maximum mapped address */
+};
+
+/* PCI domain-device relationship */
+struct device_domain_info {
+ struct list_head link; /* link to domain siblings */
+ struct list_head global; /* link to global list */
+ u8 bus; /* PCI bus numer */
+ u8 devfn; /* PCI devfn number */
+ struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */
+ struct dmar_domain *domain; /* pointer to domain */
+};
static void flush_unmaps_timeout(unsigned long data);
@@ -88,6 +277,8 @@ static int intel_iommu_strict;
static DEFINE_SPINLOCK(device_domain_lock);
static LIST_HEAD(device_domain_list);
+static struct iommu_ops intel_iommu_ops;
+
static int __init intel_iommu_setup(char *str)
{
if (!str)
@@ -184,6 +375,88 @@ void free_iova_mem(struct iova *iova)
kmem_cache_free(iommu_iova_cache, iova);
}
+
+static inline int width_to_agaw(int width);
+
+/* calculate agaw for each iommu.
+ * "SAGAW" may be different across iommus, use a default agaw, and
+ * get a supported less agaw for iommus that don't support the default agaw.
+ */
+int iommu_calculate_agaw(struct intel_iommu *iommu)
+{
+ unsigned long sagaw;
+ int agaw = -1;
+
+ sagaw = cap_sagaw(iommu->cap);
+ for (agaw = width_to_agaw(DEFAULT_DOMAIN_ADDRESS_WIDTH);
+ agaw >= 0; agaw--) {
+ if (test_bit(agaw, &sagaw))
+ break;
+ }
+
+ return agaw;
+}
+
+/* in native case, each domain is related to only one iommu */
+static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
+{
+ int iommu_id;
+
+ BUG_ON(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE);
+
+ iommu_id = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+ if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
+ return NULL;
+
+ return g_iommus[iommu_id];
+}
+
+/* "Coherency" capability may be different across iommus */
+static void domain_update_iommu_coherency(struct dmar_domain *domain)
+{
+ int i;
+
+ domain->iommu_coherency = 1;
+
+ i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+ for (; i < g_num_of_iommus; ) {
+ if (!ecap_coherent(g_iommus[i]->ecap)) {
+ domain->iommu_coherency = 0;
+ break;
+ }
+ i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
+ }
+}
+
+static struct intel_iommu *device_to_iommu(u8 bus, u8 devfn)
+{
+ struct dmar_drhd_unit *drhd = NULL;
+ int i;
+
+ for_each_drhd_unit(drhd) {
+ if (drhd->ignored)
+ continue;
+
+ for (i = 0; i < drhd->devices_cnt; i++)
+ if (drhd->devices[i] &&
+ drhd->devices[i]->bus->number == bus &&
+ drhd->devices[i]->devfn == devfn)
+ return drhd->iommu;
+
+ if (drhd->include_all)
+ return drhd->iommu;
+ }
+
+ return NULL;
+}
+
+static void domain_flush_cache(struct dmar_domain *domain,
+ void *addr, int size)
+{
+ if (!domain->iommu_coherency)
+ clflush_cache_range(addr, size);
+}
+
/* Gets context entry for a given bus and devfn */
static struct context_entry * device_to_context_entry(struct intel_iommu *iommu,
u8 bus, u8 devfn)
@@ -226,7 +499,7 @@ static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
ret = 0;
goto out;
}
- ret = context_present(context[devfn]);
+ ret = context_present(&context[devfn]);
out:
spin_unlock_irqrestore(&iommu->lock, flags);
return ret;
@@ -242,7 +515,7 @@ static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn)
root = &iommu->root_entry[bus];
context = get_context_addr_from_root(root);
if (context) {
- context_clear_entry(context[devfn]);
+ context_clear_entry(&context[devfn]);
__iommu_flush_cache(iommu, &context[devfn], \
sizeof(*context));
}
@@ -339,7 +612,7 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
if (level == 1)
break;
- if (!dma_pte_present(*pte)) {
+ if (!dma_pte_present(pte)) {
tmp_page = alloc_pgtable_page();
if (!tmp_page) {
@@ -347,18 +620,17 @@ static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
flags);
return NULL;
}
- __iommu_flush_cache(domain->iommu, tmp_page,
- PAGE_SIZE);
- dma_set_pte_addr(*pte, virt_to_phys(tmp_page));
+ domain_flush_cache(domain, tmp_page, PAGE_SIZE);
+ dma_set_pte_addr(pte, virt_to_phys(tmp_page));
/*
* high level table always sets r/w, last level page
* table control read/write
*/
- dma_set_pte_readable(*pte);
- dma_set_pte_writable(*pte);
- __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+ dma_set_pte_readable(pte);
+ dma_set_pte_writable(pte);
+ domain_flush_cache(domain, pte, sizeof(*pte));
}
- parent = phys_to_virt(dma_pte_addr(*pte));
+ parent = phys_to_virt(dma_pte_addr(pte));
level--;
}
@@ -381,9 +653,9 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
if (level == total)
return pte;
- if (!dma_pte_present(*pte))
+ if (!dma_pte_present(pte))
break;
- parent = phys_to_virt(dma_pte_addr(*pte));
+ parent = phys_to_virt(dma_pte_addr(pte));
total--;
}
return NULL;
@@ -398,8 +670,8 @@ static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
pte = dma_addr_level_pte(domain, addr, 1);
if (pte) {
- dma_clear_pte(*pte);
- __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+ dma_clear_pte(pte);
+ domain_flush_cache(domain, pte, sizeof(*pte));
}
}
@@ -445,10 +717,9 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain,
pte = dma_addr_level_pte(domain, tmp, level);
if (pte) {
free_pgtable_page(
- phys_to_virt(dma_pte_addr(*pte)));
- dma_clear_pte(*pte);
- __iommu_flush_cache(domain->iommu,
- pte, sizeof(*pte));
+ phys_to_virt(dma_pte_addr(pte)));
+ dma_clear_pte(pte);
+ domain_flush_cache(domain, pte, sizeof(*pte));
}
tmp += level_size(level);
}
@@ -950,17 +1221,28 @@ static int iommu_init_domains(struct intel_iommu *iommu)
static void domain_exit(struct dmar_domain *domain);
+static void vm_domain_exit(struct dmar_domain *domain);
void free_dmar_iommu(struct intel_iommu *iommu)
{
struct dmar_domain *domain;
int i;
+ unsigned long flags;
i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap));
for (; i < cap_ndoms(iommu->cap); ) {
domain = iommu->domains[i];
clear_bit(i, iommu->domain_ids);
- domain_exit(domain);
+
+ spin_lock_irqsave(&domain->iommu_lock, flags);
+ if (--domain->iommu_count == 0) {
+ if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
+ vm_domain_exit(domain);
+ else
+ domain_exit(domain);
+ }
+ spin_unlock_irqrestore(&domain->iommu_lock, flags);
+
i = find_next_bit(iommu->domain_ids,
cap_ndoms(iommu->cap), i+1);
}
@@ -978,6 +1260,17 @@ void free_dmar_iommu(struct intel_iommu *iommu)
kfree(iommu->domains);
kfree(iommu->domain_ids);
+ g_iommus[iommu->seq_id] = NULL;
+
+ /* if all iommus are freed, free g_iommus */
+ for (i = 0; i < g_num_of_iommus; i++) {
+ if (g_iommus[i])
+ break;
+ }
+
+ if (i == g_num_of_iommus)
+ kfree(g_iommus);
+
/* free context mapping */
free_context_table(iommu);
}
@@ -1006,7 +1299,9 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
set_bit(num, iommu->domain_ids);
domain->id = num;
- domain->iommu = iommu;
+ memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+ set_bit(iommu->seq_id, &domain->iommu_bmp);
+ domain->flags = 0;
iommu->domains[num] = domain;
spin_unlock_irqrestore(&iommu->lock, flags);
@@ -1016,10 +1311,13 @@ static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu)
static void iommu_free_domain(struct dmar_domain *domain)
{
unsigned long flags;
+ struct intel_iommu *iommu;
- spin_lock_irqsave(&domain->iommu->lock, flags);
- clear_bit(domain->id, domain->iommu->domain_ids);
- spin_unlock_irqrestore(&domain->iommu->lock, flags);
+ iommu = domain_get_iommu(domain);
+
+ spin_lock_irqsave(&iommu->lock, flags);
+ clear_bit(domain->id, iommu->domain_ids);
+ spin_unlock_irqrestore(&iommu->lock, flags);
}
static struct iova_domain reserved_iova_list;
@@ -1094,11 +1392,12 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
spin_lock_init(&domain->mapping_lock);
+ spin_lock_init(&domain->iommu_lock);
domain_reserve_special_ranges(domain);
/* calculate AGAW */
- iommu = domain->iommu;
+ iommu = domain_get_iommu(domain);
if (guest_width > cap_mgaw(iommu->cap))
guest_width = cap_mgaw(iommu->cap);
domain->gaw = guest_width;
@@ -1115,6 +1414,13 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
domain->agaw = agaw;
INIT_LIST_HEAD(&domain->devices);
+ if (ecap_coherent(iommu->ecap))
+ domain->iommu_coherency = 1;
+ else
+ domain->iommu_coherency = 0;
+
+ domain->iommu_count = 1;
+
/* always allocate the top pgd */
domain->pgd = (struct dma_pte *)alloc_pgtable_page();
if (!domain->pgd)
@@ -1151,28 +1457,82 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
u8 bus, u8 devfn)
{
struct context_entry *context;
- struct intel_iommu *iommu = domain->iommu;
unsigned long flags;
+ struct intel_iommu *iommu;
+ struct dma_pte *pgd;
+ unsigned long num;
+ unsigned long ndomains;
+ int id;
+ int agaw;
pr_debug("Set context mapping for %02x:%02x.%d\n",
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
BUG_ON(!domain->pgd);
+
+ iommu = device_to_iommu(bus, devfn);
+ if (!iommu)
+ return -ENODEV;
+
context = device_to_context_entry(iommu, bus, devfn);
if (!context)
return -ENOMEM;
spin_lock_irqsave(&iommu->lock, flags);
- if (context_present(*context)) {
+ if (context_present(context)) {
spin_unlock_irqrestore(&iommu->lock, flags);
return 0;
}
- context_set_domain_id(*context, domain->id);
- context_set_address_width(*context, domain->agaw);
- context_set_address_root(*context, virt_to_phys(domain->pgd));
- context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL);
- context_set_fault_enable(*context);
- context_set_present(*context);
- __iommu_flush_cache(iommu, context, sizeof(*context));
+ id = domain->id;
+ pgd = domain->pgd;
+
+ if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) {
+ int found = 0;
+
+ /* find an available domain id for this device in iommu */
+ ndomains = cap_ndoms(iommu->cap);
+ num = find_first_bit(iommu->domain_ids, ndomains);
+ for (; num < ndomains; ) {
+ if (iommu->domains[num] == domain) {
+ id = num;
+ found = 1;
+ break;
+ }
+ num = find_next_bit(iommu->domain_ids,
+ cap_ndoms(iommu->cap), num+1);
+ }
+
+ if (found == 0) {
+ num = find_first_zero_bit(iommu->domain_ids, ndomains);
+ if (num >= ndomains) {
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ printk(KERN_ERR "IOMMU: no free domain ids\n");
+ return -EFAULT;
+ }
+
+ set_bit(num, iommu->domain_ids);
+ iommu->domains[num] = domain;
+ id = num;
+ }
+
+ /* Skip top levels of page tables for
+ * iommu which has less agaw than default.
+ */
+ for (agaw = domain->agaw; agaw != iommu->agaw; agaw--) {
+ pgd = phys_to_virt(dma_pte_addr(pgd));
+ if (!dma_pte_present(pgd)) {
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ return -ENOMEM;
+ }
+ }
+ }
+
+ context_set_domain_id(context, id);
+ context_set_address_width(context, iommu->agaw);
+ context_set_address_root(context, virt_to_phys(pgd));
+ context_set_translation_type(context, CONTEXT_TT_MULTI_LEVEL);
+ context_set_fault_enable(context);
+ context_set_present(context);
+ domain_flush_cache(domain, context, sizeof(*context));
/* it's a non-present to present mapping */
if (iommu->flush.flush_context(iommu, domain->id,
@@ -1183,6 +1543,13 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_DSI_FLUSH, 0);
spin_unlock_irqrestore(&iommu->lock, flags);
+
+ spin_lock_irqsave(&domain->iommu_lock, flags);
+ if (!test_and_set_bit(iommu->seq_id, &domain->iommu_bmp)) {
+ domain->iommu_count++;
+ domain_update_iommu_coherency(domain);
+ }
+ spin_unlock_irqrestore(&domain->iommu_lock, flags);
return 0;
}
@@ -1218,13 +1585,17 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev)
tmp->bus->number, tmp->devfn);
}
-static int domain_context_mapped(struct dmar_domain *domain,
- struct pci_dev *pdev)
+static int domain_context_mapped(struct pci_dev *pdev)
{
int ret;
struct pci_dev *tmp, *parent;
+ struct intel_iommu *iommu;
+
+ iommu = device_to_iommu(pdev->bus->number, pdev->devfn);
+ if (!iommu)
+ return -ENODEV;
- ret = device_context_mapped(domain->iommu,
+ ret = device_context_mapped(iommu,
pdev->bus->number, pdev->devfn);
if (!ret)
return ret;
@@ -1235,17 +1606,17 @@ static int domain_context_mapped(struct dmar_domain *domain,
/* Secondary interface's bus number and devfn 0 */
parent = pdev->bus->self;
while (parent != tmp) {
- ret = device_context_mapped(domain->iommu, parent->bus->number,
+ ret = device_context_mapped(iommu, parent->bus->number,
parent->devfn);
if (!ret)
return ret;
parent = parent->bus->self;
}
if (tmp->is_pcie)
- return device_context_mapped(domain->iommu,
+ return device_context_mapped(iommu,
tmp->subordinate->number, 0);
else
- return device_context_mapped(domain->iommu,
+ return device_context_mapped(iommu,
tmp->bus->number, tmp->devfn);
}
@@ -1273,22 +1644,25 @@ domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
/* We don't need lock here, nobody else
* touches the iova range
*/
- BUG_ON(dma_pte_addr(*pte));
- dma_set_pte_addr(*pte, start_pfn << VTD_PAGE_SHIFT);
- dma_set_pte_prot(*pte, prot);
- __iommu_flush_cache(domain->iommu, pte, sizeof(*pte));
+ BUG_ON(dma_pte_addr(pte));
+ dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT);
+ dma_set_pte_prot(pte, prot);
+ domain_flush_cache(domain, pte, sizeof(*pte));
start_pfn++;
index++;
}
return 0;
}
-static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
+static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
{
- clear_context_table(domain->iommu, bus, devfn);
- domain->iommu->flush.flush_context(domain->iommu, 0, 0, 0,
+ if (!iommu)
+ return;
+
+ clear_context_table(iommu, bus, devfn);
+ iommu->flush.flush_context(iommu, 0, 0, 0,
DMA_CCMD_GLOBAL_INVL, 0);
- domain->iommu->flush.flush_iotlb(domain->iommu, 0, 0, 0,
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0,
DMA_TLB_GLOBAL_FLUSH, 0);
}
@@ -1296,6 +1670,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
{
struct device_domain_info *info;
unsigned long flags;
+ struct intel_iommu *iommu;
spin_lock_irqsave(&device_domain_lock, flags);
while (!list_empty(&domain->devices)) {
@@ -1307,7 +1682,8 @@ static void domain_remove_dev_info(struct dmar_domain *domain)
info->dev->dev.archdata.iommu = NULL;
spin_unlock_irqrestore(&device_domain_lock, flags);
- detach_domain_for_dev(info->domain, info->bus, info->devfn);
+ iommu = device_to_iommu(info->bus, info->devfn);
+ iommu_detach_dev(iommu, info->bus, info->devfn);
free_devinfo_mem(info);
spin_lock_irqsave(&device_domain_lock, flags);
@@ -1400,7 +1776,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
info->dev = NULL;
info->domain = domain;
/* This domain is shared by devices under p2p bridge */
- domain->flags |= DOMAIN_FLAG_MULTIPLE_DEVICES;
+ domain->flags |= DOMAIN_FLAG_P2P_MULTIPLE_DEVICES;
/* pcie-to-pci bridge already has a domain, uses it */
found = NULL;
@@ -1563,6 +1939,11 @@ static void __init iommu_prepare_gfx_mapping(void)
printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
}
}
+#else /* !CONFIG_DMAR_GFX_WA */
+static inline void iommu_prepare_gfx_mapping(void)
+{
+ return;
+}
#endif
#ifdef CONFIG_DMAR_FLOPPY_WA
@@ -1590,7 +1971,7 @@ static inline void iommu_prepare_isa(void)
}
#endif /* !CONFIG_DMAR_FLPY_WA */
-int __init init_dmars(void)
+static int __init init_dmars(void)
{
struct dmar_drhd_unit *drhd;
struct dmar_rmrr_unit *rmrr;
@@ -1613,9 +1994,18 @@ int __init init_dmars(void)
*/
}
+ g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
+ GFP_KERNEL);
+ if (!g_iommus) {
+ printk(KERN_ERR "Allocating global iommu array failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
deferred_flush = kzalloc(g_num_of_iommus *
sizeof(struct deferred_flush_tables), GFP_KERNEL);
if (!deferred_flush) {
+ kfree(g_iommus);
ret = -ENOMEM;
goto error;
}
@@ -1625,6 +2015,7 @@ int __init init_dmars(void)
continue;
iommu = drhd->iommu;
+ g_iommus[iommu->seq_id] = iommu;
ret = iommu_init_domains(iommu);
if (ret)
@@ -1737,6 +2128,7 @@ error:
iommu = drhd->iommu;
free_iommu(iommu);
}
+ kfree(g_iommus);
return ret;
}
@@ -1805,7 +2197,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
}
/* make sure context mapping is ok */
- if (unlikely(!domain_context_mapped(domain, pdev))) {
+ if (unlikely(!domain_context_mapped(pdev))) {
ret = domain_context_mapping(domain, pdev);
if (ret) {
printk(KERN_ERR
@@ -1827,6 +2219,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
struct iova *iova;
int prot = 0;
int ret;
+ struct intel_iommu *iommu;
BUG_ON(dir == DMA_NONE);
if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
@@ -1836,6 +2229,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
if (!domain)
return 0;
+ iommu = domain_get_iommu(domain);
size = aligned_size((u64)paddr, size);
iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
@@ -1849,7 +2243,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
* mappings..
*/
if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
- !cap_zlr(domain->iommu->cap))
+ !cap_zlr(iommu->cap))
prot |= DMA_PTE_READ;
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
prot |= DMA_PTE_WRITE;
@@ -1865,10 +2259,10 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
goto error;
/* it's a non-present to present mapping */
- ret = iommu_flush_iotlb_psi(domain->iommu, domain->id,
+ ret = iommu_flush_iotlb_psi(iommu, domain->id,
start_paddr, size >> VTD_PAGE_SHIFT, 1);
if (ret)
- iommu_flush_write_buffer(domain->iommu);
+ iommu_flush_write_buffer(iommu);
return start_paddr + ((u64)paddr & (~PAGE_MASK));
@@ -1895,10 +2289,11 @@ static void flush_unmaps(void)
/* just flush them all */
for (i = 0; i < g_num_of_iommus; i++) {
- if (deferred_flush[i].next) {
- struct intel_iommu *iommu =
- deferred_flush[i].domain[0]->iommu;
+ struct intel_iommu *iommu = g_iommus[i];
+ if (!iommu)
+ continue;
+ if (deferred_flush[i].next) {
iommu->flush.flush_iotlb(iommu, 0, 0, 0,
DMA_TLB_GLOBAL_FLUSH, 0);
for (j = 0; j < deferred_flush[i].next; j++) {
@@ -1925,12 +2320,14 @@ static void add_unmap(struct dmar_domain *dom, struct iova *iova)
{
unsigned long flags;
int next, iommu_id;
+ struct intel_iommu *iommu;
spin_lock_irqsave(&async_umap_flush_lock, flags);
if (list_size == HIGH_WATER_MARK)
flush_unmaps();
- iommu_id = dom->iommu->seq_id;
+ iommu = domain_get_iommu(dom);
+ iommu_id = iommu->seq_id;
next = deferred_flush[iommu_id].next;
deferred_flush[iommu_id].domain[next] = dom;
@@ -1952,12 +2349,15 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
struct dmar_domain *domain;
unsigned long start_addr;
struct iova *iova;
+ struct intel_iommu *iommu;
if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
return;
domain = find_domain(pdev);
BUG_ON(!domain);
+ iommu = domain_get_iommu(domain);
+
iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
if (!iova)
return;
@@ -1973,9 +2373,9 @@ void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
/* free page tables */
dma_pte_free_pagetable(domain, start_addr, start_addr + size);
if (intel_iommu_strict) {
- if (iommu_flush_iotlb_psi(domain->iommu,
+ if (iommu_flush_iotlb_psi(iommu,
domain->id, start_addr, size >> VTD_PAGE_SHIFT, 0))
- iommu_flush_write_buffer(domain->iommu);
+ iommu_flush_write_buffer(iommu);
/* free iova */
__free_iova(&domain->iovad, iova);
} else {
@@ -2036,11 +2436,15 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
size_t size = 0;
void *addr;
struct scatterlist *sg;
+ struct intel_iommu *iommu;
if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
return;
domain = find_domain(pdev);
+ BUG_ON(!domain);
+
+ iommu = domain_get_iommu(domain);
iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
if (!iova)
@@ -2057,9 +2461,9 @@ void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
/* free page tables */
dma_pte_free_pagetable(domain, start_addr, start_addr + size);
- if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr,
+ if (iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
size >> VTD_PAGE_SHIFT, 0))
- iommu_flush_write_buffer(domain->iommu);
+ iommu_flush_write_buffer(iommu);
/* free iova */
__free_iova(&domain->iovad, iova);
@@ -2093,6 +2497,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
int ret;
struct scatterlist *sg;
unsigned long start_addr;
+ struct intel_iommu *iommu;
BUG_ON(dir == DMA_NONE);
if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO)
@@ -2102,6 +2507,8 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
if (!domain)
return 0;
+ iommu = domain_get_iommu(domain);
+
for_each_sg(sglist, sg, nelems, i) {
addr = SG_ENT_VIRT_ADDRESS(sg);
addr = (void *)virt_to_phys(addr);
@@ -2119,7 +2526,7 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
* mappings..
*/
if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
- !cap_zlr(domain->iommu->cap))
+ !cap_zlr(iommu->cap))
prot |= DMA_PTE_READ;
if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
prot |= DMA_PTE_WRITE;
@@ -2151,9 +2558,9 @@ int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
}
/* it's a non-present to present mapping */
- if (iommu_flush_iotlb_psi(domain->iommu, domain->id,
+ if (iommu_flush_iotlb_psi(iommu, domain->id,
start_addr, offset >> VTD_PAGE_SHIFT, 1))
- iommu_flush_write_buffer(domain->iommu);
+ iommu_flush_write_buffer(iommu);
return nelems;
}
@@ -2325,10 +2732,220 @@ int __init intel_iommu_init(void)
init_timer(&unmap_timer);
force_iommu = 1;
dma_ops = &intel_dma_ops;
+
+ register_iommu(&intel_iommu_ops);
+
return 0;
}
-void intel_iommu_domain_exit(struct dmar_domain *domain)
+static int vm_domain_add_dev_info(struct dmar_domain *domain,
+ struct pci_dev *pdev)
+{
+ struct device_domain_info *info;
+ unsigned long flags;
+
+ info = alloc_devinfo_mem();
+ if (!info)
+ return -ENOMEM;
+
+ info->bus = pdev->bus->number;
+ info->devfn = pdev->devfn;
+ info->dev = pdev;
+ info->domain = domain;
+
+ spin_lock_irqsave(&device_domain_lock, flags);
+ list_add(&info->link, &domain->devices);
+ list_add(&info->global, &device_domain_list);
+ pdev->dev.archdata.iommu = info;
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+
+ return 0;
+}
+
+static void vm_domain_remove_one_dev_info(struct dmar_domain *domain,
+ struct pci_dev *pdev)
+{
+ struct device_domain_info *info;
+ struct intel_iommu *iommu;
+ unsigned long flags;
+ int found = 0;
+ struct list_head *entry, *tmp;
+
+ iommu = device_to_iommu(pdev->bus->number, pdev->devfn);
+ if (!iommu)
+ return;
+
+ spin_lock_irqsave(&device_domain_lock, flags);
+ list_for_each_safe(entry, tmp, &domain->devices) {
+ info = list_entry(entry, struct device_domain_info, link);
+ if (info->bus == pdev->bus->number &&
+ info->devfn == pdev->devfn) {
+ list_del(&info->link);
+ list_del(&info->global);
+ if (info->dev)
+ info->dev->dev.archdata.iommu = NULL;
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+
+ iommu_detach_dev(iommu, info->bus, info->devfn);
+ free_devinfo_mem(info);
+
+ spin_lock_irqsave(&device_domain_lock, flags);
+
+ if (found)
+ break;
+ else
+ continue;
+ }
+
+ /* if there is no other devices under the same iommu
+ * owned by this domain, clear this iommu in iommu_bmp
+ * update iommu count and coherency
+ */
+ if (device_to_iommu(info->bus, info->devfn) == iommu)
+ found = 1;
+ }
+
+ if (found == 0) {
+ unsigned long tmp_flags;
+ spin_lock_irqsave(&domain->iommu_lock, tmp_flags);
+ clear_bit(iommu->seq_id, &domain->iommu_bmp);
+ domain->iommu_count--;
+ domain_update_iommu_coherency(domain);
+ spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+ }
+
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+}
+
+static void vm_domain_remove_all_dev_info(struct dmar_domain *domain)
+{
+ struct device_domain_info *info;
+ struct intel_iommu *iommu;
+ unsigned long flags1, flags2;
+
+ spin_lock_irqsave(&device_domain_lock, flags1);
+ while (!list_empty(&domain->devices)) {
+ info = list_entry(domain->devices.next,
+ struct device_domain_info, link);
+ list_del(&info->link);
+ list_del(&info->global);
+ if (info->dev)
+ info->dev->dev.archdata.iommu = NULL;
+
+ spin_unlock_irqrestore(&device_domain_lock, flags1);
+
+ iommu = device_to_iommu(info->bus, info->devfn);
+ iommu_detach_dev(iommu, info->bus, info->devfn);
+
+ /* clear this iommu in iommu_bmp, update iommu count
+ * and coherency
+ */
+ spin_lock_irqsave(&domain->iommu_lock, flags2);
+ if (test_and_clear_bit(iommu->seq_id,
+ &domain->iommu_bmp)) {
+ domain->iommu_count--;
+ domain_update_iommu_coherency(domain);
+ }
+ spin_unlock_irqrestore(&domain->iommu_lock, flags2);
+
+ free_devinfo_mem(info);
+ spin_lock_irqsave(&device_domain_lock, flags1);
+ }
+ spin_unlock_irqrestore(&device_domain_lock, flags1);
+}
+
+/* domain id for virtual machine, it won't be set in context */
+static unsigned long vm_domid;
+
+static int vm_domain_min_agaw(struct dmar_domain *domain)
+{
+ int i;
+ int min_agaw = domain->agaw;
+
+ i = find_first_bit(&domain->iommu_bmp, g_num_of_iommus);
+ for (; i < g_num_of_iommus; ) {
+ if (min_agaw > g_iommus[i]->agaw)
+ min_agaw = g_iommus[i]->agaw;
+
+ i = find_next_bit(&domain->iommu_bmp, g_num_of_iommus, i+1);
+ }
+
+ return min_agaw;
+}
+
+static struct dmar_domain *iommu_alloc_vm_domain(void)
+{
+ struct dmar_domain *domain;
+
+ domain = alloc_domain_mem();
+ if (!domain)
+ return NULL;
+
+ domain->id = vm_domid++;
+ memset(&domain->iommu_bmp, 0, sizeof(unsigned long));
+ domain->flags = DOMAIN_FLAG_VIRTUAL_MACHINE;
+
+ return domain;
+}
+
+static int vm_domain_init(struct dmar_domain *domain, int guest_width)
+{
+ int adjust_width;
+
+ init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
+ spin_lock_init(&domain->mapping_lock);
+ spin_lock_init(&domain->iommu_lock);
+
+ domain_reserve_special_ranges(domain);
+
+ /* calculate AGAW */
+ domain->gaw = guest_width;
+ adjust_width = guestwidth_to_adjustwidth(guest_width);
+ domain->agaw = width_to_agaw(adjust_width);
+
+ INIT_LIST_HEAD(&domain->devices);
+
+ domain->iommu_count = 0;
+ domain->iommu_coherency = 0;
+ domain->max_addr = 0;
+
+ /* always allocate the top pgd */
+ domain->pgd = (struct dma_pte *)alloc_pgtable_page();
+ if (!domain->pgd)
+ return -ENOMEM;
+ domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
+ return 0;
+}
+
+static void iommu_free_vm_domain(struct dmar_domain *domain)
+{
+ unsigned long flags;
+ struct dmar_drhd_unit *drhd;
+ struct intel_iommu *iommu;
+ unsigned long i;
+ unsigned long ndomains;
+
+ for_each_drhd_unit(drhd) {
+ if (drhd->ignored)
+ continue;
+ iommu = drhd->iommu;
+
+ ndomains = cap_ndoms(iommu->cap);
+ i = find_first_bit(iommu->domain_ids, ndomains);
+ for (; i < ndomains; ) {
+ if (iommu->domains[i] == domain) {
+ spin_lock_irqsave(&iommu->lock, flags);
+ clear_bit(i, iommu->domain_ids);
+ iommu->domains[i] = NULL;
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ break;
+ }
+ i = find_next_bit(iommu->domain_ids, ndomains, i+1);
+ }
+ }
+}
+
+static void vm_domain_exit(struct dmar_domain *domain)
{
u64 end;
@@ -2336,6 +2953,9 @@ void intel_iommu_domain_exit(struct dmar_domain *domain)
if (!domain)
return;
+ vm_domain_remove_all_dev_info(domain);
+ /* destroy iovas */
+ put_iova_domain(&domain->iovad);
end = DOMAIN_MAX_ADDR(domain->gaw);
end = end & (~VTD_PAGE_MASK);
@@ -2345,94 +2965,167 @@ void intel_iommu_domain_exit(struct dmar_domain *domain)
/* free page tables */
dma_pte_free_pagetable(domain, 0, end);
- iommu_free_domain(domain);
+ iommu_free_vm_domain(domain);
free_domain_mem(domain);
}
-EXPORT_SYMBOL_GPL(intel_iommu_domain_exit);
-struct dmar_domain *intel_iommu_domain_alloc(struct pci_dev *pdev)
+static int intel_iommu_domain_init(struct iommu_domain *domain)
{
- struct dmar_drhd_unit *drhd;
- struct dmar_domain *domain;
- struct intel_iommu *iommu;
-
- drhd = dmar_find_matched_drhd_unit(pdev);
- if (!drhd) {
- printk(KERN_ERR "intel_iommu_domain_alloc: drhd == NULL\n");
- return NULL;
- }
+ struct dmar_domain *dmar_domain;
- iommu = drhd->iommu;
- if (!iommu) {
- printk(KERN_ERR
- "intel_iommu_domain_alloc: iommu == NULL\n");
- return NULL;
- }
- domain = iommu_alloc_domain(iommu);
- if (!domain) {
+ dmar_domain = iommu_alloc_vm_domain();
+ if (!dmar_domain) {
printk(KERN_ERR
- "intel_iommu_domain_alloc: domain == NULL\n");
- return NULL;
+ "intel_iommu_domain_init: dmar_domain == NULL\n");
+ return -ENOMEM;
}
- if (domain_init(domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
+ if (vm_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
printk(KERN_ERR
- "intel_iommu_domain_alloc: domain_init() failed\n");
- intel_iommu_domain_exit(domain);
- return NULL;
+ "intel_iommu_domain_init() failed\n");
+ vm_domain_exit(dmar_domain);
+ return -ENOMEM;
}
- return domain;
+ domain->priv = dmar_domain;
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(intel_iommu_domain_alloc);
-int intel_iommu_context_mapping(
- struct dmar_domain *domain, struct pci_dev *pdev)
+static void intel_iommu_domain_destroy(struct iommu_domain *domain)
{
- int rc;
- rc = domain_context_mapping(domain, pdev);
- return rc;
+ struct dmar_domain *dmar_domain = domain->priv;
+
+ domain->priv = NULL;
+ vm_domain_exit(dmar_domain);
}
-EXPORT_SYMBOL_GPL(intel_iommu_context_mapping);
-int intel_iommu_page_mapping(
- struct dmar_domain *domain, dma_addr_t iova,
- u64 hpa, size_t size, int prot)
+static int intel_iommu_attach_device(struct iommu_domain *domain,
+ struct device *dev)
{
- int rc;
- rc = domain_page_mapping(domain, iova, hpa, size, prot);
- return rc;
+ struct dmar_domain *dmar_domain = domain->priv;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct intel_iommu *iommu;
+ int addr_width;
+ u64 end;
+ int ret;
+
+ /* normally pdev is not mapped */
+ if (unlikely(domain_context_mapped(pdev))) {
+ struct dmar_domain *old_domain;
+
+ old_domain = find_domain(pdev);
+ if (old_domain) {
+ if (dmar_domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE)
+ vm_domain_remove_one_dev_info(old_domain, pdev);
+ else
+ domain_remove_dev_info(old_domain);
+ }
+ }
+
+ iommu = device_to_iommu(pdev->bus->number, pdev->devfn);
+ if (!iommu)
+ return -ENODEV;
+
+ /* check if this iommu agaw is sufficient for max mapped address */
+ addr_width = agaw_to_width(iommu->agaw);
+ end = DOMAIN_MAX_ADDR(addr_width);
+ end = end & VTD_PAGE_MASK;
+ if (end < dmar_domain->max_addr) {
+ printk(KERN_ERR "%s: iommu agaw (%d) is not "
+ "sufficient for the mapped address (%llx)\n",
+ __func__, iommu->agaw, dmar_domain->max_addr);
+ return -EFAULT;
+ }
+
+ ret = domain_context_mapping(dmar_domain, pdev);
+ if (ret)
+ return ret;
+
+ ret = vm_domain_add_dev_info(dmar_domain, pdev);
+ return ret;
}
-EXPORT_SYMBOL_GPL(intel_iommu_page_mapping);
-void intel_iommu_detach_dev(struct dmar_domain *domain, u8 bus, u8 devfn)
+static void intel_iommu_detach_device(struct iommu_domain *domain,
+ struct device *dev)
{
- detach_domain_for_dev(domain, bus, devfn);
+ struct dmar_domain *dmar_domain = domain->priv;
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ vm_domain_remove_one_dev_info(dmar_domain, pdev);
}
-EXPORT_SYMBOL_GPL(intel_iommu_detach_dev);
-struct dmar_domain *
-intel_iommu_find_domain(struct pci_dev *pdev)
+static int intel_iommu_map_range(struct iommu_domain *domain,
+ unsigned long iova, phys_addr_t hpa,
+ size_t size, int iommu_prot)
{
- return find_domain(pdev);
+ struct dmar_domain *dmar_domain = domain->priv;
+ u64 max_addr;
+ int addr_width;
+ int prot = 0;
+ int ret;
+
+ if (iommu_prot & IOMMU_READ)
+ prot |= DMA_PTE_READ;
+ if (iommu_prot & IOMMU_WRITE)
+ prot |= DMA_PTE_WRITE;
+
+ max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size);
+ if (dmar_domain->max_addr < max_addr) {
+ int min_agaw;
+ u64 end;
+
+ /* check if minimum agaw is sufficient for mapped address */
+ min_agaw = vm_domain_min_agaw(dmar_domain);
+ addr_width = agaw_to_width(min_agaw);
+ end = DOMAIN_MAX_ADDR(addr_width);
+ end = end & VTD_PAGE_MASK;
+ if (end < max_addr) {
+ printk(KERN_ERR "%s: iommu agaw (%d) is not "
+ "sufficient for the mapped address (%llx)\n",
+ __func__, min_agaw, max_addr);
+ return -EFAULT;
+ }
+ dmar_domain->max_addr = max_addr;
+ }
+
+ ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot);
+ return ret;
}
-EXPORT_SYMBOL_GPL(intel_iommu_find_domain);
-int intel_iommu_found(void)
+static void intel_iommu_unmap_range(struct iommu_domain *domain,
+ unsigned long iova, size_t size)
{
- return g_num_of_iommus;
+ struct dmar_domain *dmar_domain = domain->priv;
+ dma_addr_t base;
+
+ /* The address might not be aligned */
+ base = iova & VTD_PAGE_MASK;
+ size = VTD_PAGE_ALIGN(size);
+ dma_pte_clear_range(dmar_domain, base, base + size);
+
+ if (dmar_domain->max_addr == base + size)
+ dmar_domain->max_addr = base;
}
-EXPORT_SYMBOL_GPL(intel_iommu_found);
-u64 intel_iommu_iova_to_pfn(struct dmar_domain *domain, u64 iova)
+static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
+ unsigned long iova)
{
+ struct dmar_domain *dmar_domain = domain->priv;
struct dma_pte *pte;
- u64 pfn;
-
- pfn = 0;
- pte = addr_to_dma_pte(domain, iova);
+ u64 phys = 0;
+ pte = addr_to_dma_pte(dmar_domain, iova);
if (pte)
- pfn = dma_pte_addr(*pte);
+ phys = dma_pte_addr(pte);
- return pfn >> VTD_PAGE_SHIFT;
+ return phys;
}
-EXPORT_SYMBOL_GPL(intel_iommu_iova_to_pfn);
+
+static struct iommu_ops intel_iommu_ops = {
+ .domain_init = intel_iommu_domain_init,
+ .domain_destroy = intel_iommu_domain_destroy,
+ .attach_dev = intel_iommu_attach_device,
+ .detach_dev = intel_iommu_detach_device,
+ .map = intel_iommu_map_range,
+ .unmap = intel_iommu_unmap_range,
+ .iova_to_phys = intel_iommu_iova_to_phys,
+};
diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c
index 6441dfa969a3..de01174aff06 100644
--- a/drivers/pci/irq.c
+++ b/drivers/pci/irq.c
@@ -15,7 +15,7 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
dev_printk(KERN_ERR, &pdev->dev,
"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
- parent->dev.bus_id, parent->vendor, parent->device);
+ dev_name(&parent->dev), parent->vendor, parent->device);
dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
WARN_ON(1);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 11a51f8ed3b3..44f15ff70c1d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -103,6 +103,16 @@ static void msix_set_enable(struct pci_dev *dev, int enable)
}
}
+/*
+ * Essentially, this is ((1 << (1 << x)) - 1), but without the
+ * undefinedness of a << 32.
+ */
+static inline __attribute_const__ u32 msi_mask(unsigned x)
+{
+ static const u32 mask[] = { 1, 2, 4, 0xf, 0xff, 0xffff, 0xffffffff };
+ return mask[x];
+}
+
static void msix_flush_writes(struct irq_desc *desc)
{
struct msi_desc *entry;
@@ -398,21 +408,18 @@ static int msi_capability_init(struct pci_dev *dev)
entry->msi_attrib.masked = 1;
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
entry->msi_attrib.pos = pos;
- if (entry->msi_attrib.maskbit) {
- entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
- entry->msi_attrib.is_64);
- }
entry->dev = dev;
if (entry->msi_attrib.maskbit) {
- unsigned int maskbits, temp;
+ unsigned int base, maskbits, temp;
+
+ base = msi_mask_bits_reg(pos, entry->msi_attrib.is_64);
+ entry->mask_base = (void __iomem *)(long)base;
+
/* All MSIs are unmasked by default, Mask them all */
- pci_read_config_dword(dev,
- msi_mask_bits_reg(pos, entry->msi_attrib.is_64),
- &maskbits);
- temp = (1 << multi_msi_capable(control));
- temp = ((temp - 1) & ~temp);
+ pci_read_config_dword(dev, base, &maskbits);
+ temp = msi_mask((control & PCI_MSI_FLAGS_QMASK) >> 1);
maskbits |= temp;
- pci_write_config_dword(dev, entry->msi_attrib.is_64, maskbits);
+ pci_write_config_dword(dev, base, maskbits);
entry->msi_attrib.maskbits_mask = temp;
}
list_add_tail(&entry->list, &dev->msi_list);
@@ -776,28 +783,19 @@ void pci_no_msi(void)
pci_msi_enable = 0;
}
-void pci_msi_init_pci_dev(struct pci_dev *dev)
-{
- INIT_LIST_HEAD(&dev->msi_list);
-}
-
-#ifdef CONFIG_ACPI
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
-static void __devinit msi_acpi_init(void)
+/**
+ * pci_msi_enabled - is MSI enabled?
+ *
+ * Returns true if MSI has not been disabled by the command-line option
+ * pci=nomsi.
+ **/
+int pci_msi_enabled(void)
{
- if (acpi_pci_disabled)
- return;
- pci_osc_support_set(OSC_MSI_SUPPORT);
- pcie_osc_support_set(OSC_MSI_SUPPORT);
+ return pci_msi_enable;
}
-#else
-static inline void msi_acpi_init(void) { }
-#endif /* CONFIG_ACPI */
+EXPORT_SYMBOL(pci_msi_enabled);
-void __devinit msi_init(void)
+void pci_msi_init_pci_dev(struct pci_dev *dev)
{
- if (!pci_msi_enable)
- return;
- msi_acpi_init();
+ INIT_LIST_HEAD(&dev->msi_list);
}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index ae5ec76dca77..deea8a187eb8 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -13,8 +13,6 @@
#include <linux/module.h>
#include <linux/pci-aspm.h>
#include <acpi/acpi.h>
-#include <acpi/acnamesp.h>
-#include <acpi/acresrc.h>
#include <acpi/acpi_bus.h>
#include <linux/pci-acpi.h>
@@ -24,13 +22,14 @@ struct acpi_osc_data {
acpi_handle handle;
u32 support_set;
u32 control_set;
+ u32 control_query;
+ int is_queried;
struct list_head sibiling;
};
static LIST_HEAD(acpi_osc_data_list);
struct acpi_osc_args {
u32 capbuf[3];
- u32 ctrl_result;
};
static DEFINE_MUTEX(pci_acpi_lock);
@@ -56,7 +55,7 @@ static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
static acpi_status acpi_run_osc(acpi_handle handle,
- struct acpi_osc_args *osc_args)
+ struct acpi_osc_args *osc_args, u32 *retval)
{
acpi_status status;
struct acpi_object_list input;
@@ -112,8 +111,7 @@ static acpi_status acpi_run_osc(acpi_handle handle,
goto out_kfree;
}
out_success:
- osc_args->ctrl_result =
- *((u32 *)(out_obj->buffer.pointer + 8));
+ *retval = *((u32 *)(out_obj->buffer.pointer + 8));
status = AE_OK;
out_kfree:
@@ -121,11 +119,10 @@ out_kfree:
return status;
}
-static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
- u32 *result)
+static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data)
{
acpi_status status;
- u32 support_set;
+ u32 support_set, result;
struct acpi_osc_args osc_args;
/* do _OSC query for all possible controls */
@@ -134,56 +131,45 @@ static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
- status = acpi_run_osc(osc_data->handle, &osc_args);
+ status = acpi_run_osc(osc_data->handle, &osc_args, &result);
if (ACPI_SUCCESS(status)) {
osc_data->support_set = support_set;
- *result = osc_args.ctrl_result;
+ osc_data->control_query = result;
+ osc_data->is_queried = 1;
}
return status;
}
-static acpi_status acpi_query_osc(acpi_handle handle,
- u32 level, void *context, void **retval)
+/*
+ * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature
+ * @flags: Bitmask of flags to support
+ *
+ * See the ACPI spec for the definition of the flags
+ */
+int pci_acpi_osc_support(acpi_handle handle, u32 flags)
{
acpi_status status;
- struct acpi_osc_data *osc_data;
- u32 flags = (unsigned long)context, dummy;
acpi_handle tmp;
+ struct acpi_osc_data *osc_data;
+ int rc = 0;
status = acpi_get_handle(handle, "_OSC", &tmp);
if (ACPI_FAILURE(status))
- return AE_OK;
+ return -ENOTTY;
mutex_lock(&pci_acpi_lock);
osc_data = acpi_get_osc_data(handle);
if (!osc_data) {
printk(KERN_ERR "acpi osc data array is full\n");
+ rc = -ENOMEM;
goto out;
}
- __acpi_query_osc(flags, osc_data, &dummy);
+ __acpi_query_osc(flags, osc_data);
out:
mutex_unlock(&pci_acpi_lock);
- return AE_OK;
-}
-
-/**
- * __pci_osc_support_set - register OS support to Firmware
- * @flags: OS support bits
- * @hid: hardware ID
- *
- * Update OS support fields and doing a _OSC Query to obtain an update
- * from Firmware on supported control bits.
- **/
-acpi_status __pci_osc_support_set(u32 flags, const char *hid)
-{
- if (!(flags & OSC_SUPPORT_MASKS))
- return AE_TYPE;
-
- acpi_get_devices(hid, acpi_query_osc,
- (void *)(unsigned long)flags, NULL);
- return AE_OK;
+ return rc;
}
/**
@@ -196,7 +182,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
{
acpi_status status;
- u32 ctrlset, control_set, result;
+ u32 control_req, control_set, result;
acpi_handle tmp;
struct acpi_osc_data *osc_data;
struct acpi_osc_args osc_args;
@@ -213,28 +199,34 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
goto out;
}
- ctrlset = (flags & OSC_CONTROL_MASKS);
- if (!ctrlset) {
+ control_req = (flags & OSC_CONTROL_MASKS);
+ if (!control_req) {
status = AE_TYPE;
goto out;
}
- status = __acpi_query_osc(osc_data->support_set, osc_data, &result);
- if (ACPI_FAILURE(status))
+ /* No need to evaluate _OSC if the control was already granted. */
+ if ((osc_data->control_set & control_req) == control_req)
goto out;
- if ((result & ctrlset) != ctrlset) {
+ if (!osc_data->is_queried) {
+ status = __acpi_query_osc(osc_data->support_set, osc_data);
+ if (ACPI_FAILURE(status))
+ goto out;
+ }
+
+ if ((osc_data->control_query & control_req) != control_req) {
status = AE_SUPPORT;
goto out;
}
- control_set = osc_data->control_set | ctrlset;
+ control_set = osc_data->control_set | control_req;
osc_args.capbuf[OSC_QUERY_TYPE] = 0;
osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
- status = acpi_run_osc(handle, &osc_args);
+ status = acpi_run_osc(handle, &osc_args, &result);
if (ACPI_SUCCESS(status))
- osc_data->control_set = control_set;
+ osc_data->control_set = result;
out:
mutex_unlock(&pci_acpi_lock);
return status;
@@ -375,7 +367,7 @@ static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
* The string should be the same as root bridge's name
* Please look at 'pci_scan_bus_parented'
*/
- num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus);
+ num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus);
if (num != 2)
return -ENODEV;
*handle = acpi_get_pci_rootbridge_handle(seg, bus);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index b4cdd690ae71..ab1d615425a8 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/sched.h>
+#include <linux/cpu.h>
#include "pci.h"
/*
@@ -48,7 +49,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
subdevice=PCI_ANY_ID, class=0, class_mask=0;
unsigned long driver_data=0;
int fields=0;
- int retval;
+ int retval=0;
fields = sscanf(buf, "%x %x %x %x %x %x %lx",
&vendor, &device, &subvendor, &subdevice,
@@ -58,16 +59,18 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
/* Only accept driver_data values that match an existing id_table
entry */
- retval = -EINVAL;
- while (ids->vendor || ids->subvendor || ids->class_mask) {
- if (driver_data == ids->driver_data) {
- retval = 0;
- break;
+ if (ids) {
+ retval = -EINVAL;
+ while (ids->vendor || ids->subvendor || ids->class_mask) {
+ if (driver_data == ids->driver_data) {
+ retval = 0;
+ break;
+ }
+ ids++;
}
- ids++;
+ if (retval) /* No match */
+ return retval;
}
- if (retval) /* No match */
- return retval;
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
if (!dynid)
@@ -183,32 +186,43 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
return pci_match_id(drv->id_table, dev);
}
+struct drv_dev_and_id {
+ struct pci_driver *drv;
+ struct pci_dev *dev;
+ const struct pci_device_id *id;
+};
+
+static long local_pci_probe(void *_ddi)
+{
+ struct drv_dev_and_id *ddi = _ddi;
+
+ return ddi->drv->probe(ddi->dev, ddi->id);
+}
+
static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
const struct pci_device_id *id)
{
- int error;
-#ifdef CONFIG_NUMA
- /* Execute driver initialization on node where the
- device's bus is attached to. This way the driver likely
- allocates its local memory on the right node without
- any need to change it. */
- struct mempolicy *oldpol;
- cpumask_t oldmask = current->cpus_allowed;
- int node = dev_to_node(&dev->dev);
+ int error, node;
+ struct drv_dev_and_id ddi = { drv, dev, id };
+ /* Execute driver initialization on node where the device's
+ bus is attached to. This way the driver likely allocates
+ its local memory on the right node without any need to
+ change it. */
+ node = dev_to_node(&dev->dev);
if (node >= 0) {
+ int cpu;
node_to_cpumask_ptr(nodecpumask, node);
- set_cpus_allowed_ptr(current, nodecpumask);
- }
- /* And set default memory allocation policy */
- oldpol = current->mempolicy;
- current->mempolicy = NULL; /* fall back to system default policy */
-#endif
- error = drv->probe(dev, id);
-#ifdef CONFIG_NUMA
- set_cpus_allowed_ptr(current, &oldmask);
- current->mempolicy = oldpol;
-#endif
+
+ get_online_cpus();
+ cpu = cpumask_any_and(nodecpumask, cpu_online_mask);
+ if (cpu < nr_cpu_ids)
+ error = work_on_cpu(cpu, local_pci_probe, &ddi);
+ else
+ error = local_pci_probe(&ddi);
+ put_online_cpus();
+ } else
+ error = local_pci_probe(&ddi);
return error;
}
@@ -302,11 +316,10 @@ static void pci_device_shutdown(struct device *dev)
/*
* Default "suspend" method for devices that have no driver provided suspend,
- * or not even a driver at all.
+ * or not even a driver at all (second part).
*/
-static void pci_default_pm_suspend(struct pci_dev *pci_dev)
+static void pci_pm_set_unknown_state(struct pci_dev *pci_dev)
{
- pci_save_state(pci_dev);
/*
* mark its power state as "unknown", since we don't know if
* e.g. the BIOS will change its device state when we suspend.
@@ -317,14 +330,12 @@ static void pci_default_pm_suspend(struct pci_dev *pci_dev)
/*
* Default "resume" method for devices that have no driver provided resume,
- * or not even a driver at all.
+ * or not even a driver at all (second part).
*/
-static int pci_default_pm_resume(struct pci_dev *pci_dev)
+static int pci_pm_reenable_device(struct pci_dev *pci_dev)
{
- int retval = 0;
+ int retval;
- /* restore the PCI config space */
- pci_restore_state(pci_dev);
/* if the device was enabled before suspend, reenable */
retval = pci_reenable_device(pci_dev);
/*
@@ -344,11 +355,30 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)
int i = 0;
if (drv && drv->suspend) {
+ pci_dev->state_saved = false;
+
i = drv->suspend(pci_dev, state);
suspend_report_result(drv->suspend, i);
- } else {
- pci_default_pm_suspend(pci_dev);
+ if (i)
+ return i;
+
+ if (pci_dev->state_saved)
+ goto Fixup;
+
+ if (WARN_ON_ONCE(pci_dev->current_state != PCI_D0))
+ goto Fixup;
}
+
+ pci_save_state(pci_dev);
+ pci_dev->state_saved = true;
+ /*
+ * This is for compatibility with existing code with legacy PM support.
+ */
+ pci_pm_set_unknown_state(pci_dev);
+
+ Fixup:
+ pci_fixup_device(pci_fixup_suspend, pci_dev);
+
return i;
}
@@ -365,30 +395,84 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)
return i;
}
-static int pci_legacy_resume(struct device *dev)
+static int pci_legacy_resume_early(struct device *dev)
{
- int error;
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
- if (drv && drv->resume)
- error = drv->resume(pci_dev);
- else
- error = pci_default_pm_resume(pci_dev);
- return error;
+ return drv && drv->resume_early ?
+ drv->resume_early(pci_dev) : 0;
}
-static int pci_legacy_resume_early(struct device *dev)
+static int pci_legacy_resume(struct device *dev)
{
- int error = 0;
struct pci_dev * pci_dev = to_pci_dev(dev);
struct pci_driver * drv = pci_dev->driver;
- if (drv && drv->resume_early)
- error = drv->resume_early(pci_dev);
- return error;
+ pci_fixup_device(pci_fixup_resume, pci_dev);
+
+ return drv && drv->resume ?
+ drv->resume(pci_dev) : pci_pm_reenable_device(pci_dev);
+}
+
+/* Auxiliary functions used by the new power management framework */
+
+static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
+{
+ pci_restore_standard_config(pci_dev);
+ pci_dev->state_saved = false;
+ pci_fixup_device(pci_fixup_resume_early, pci_dev);
}
+static int pci_pm_default_resume(struct pci_dev *pci_dev)
+{
+ pci_fixup_device(pci_fixup_resume, pci_dev);
+
+ if (!pci_is_bridge(pci_dev))
+ pci_enable_wake(pci_dev, PCI_D0, false);
+
+ return pci_pm_reenable_device(pci_dev);
+}
+
+static void pci_pm_default_suspend_generic(struct pci_dev *pci_dev)
+{
+ /* If device is enabled at this point, disable it */
+ pci_disable_enabled_device(pci_dev);
+ /*
+ * Save state with interrupts enabled, because in principle the bus the
+ * device is on may be put into a low power state after this code runs.
+ */
+ pci_save_state(pci_dev);
+}
+
+static void pci_pm_default_suspend(struct pci_dev *pci_dev)
+{
+ pci_pm_default_suspend_generic(pci_dev);
+
+ if (!pci_is_bridge(pci_dev))
+ pci_prepare_to_sleep(pci_dev);
+
+ pci_fixup_device(pci_fixup_suspend, pci_dev);
+}
+
+static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
+{
+ struct pci_driver *drv = pci_dev->driver;
+ bool ret = drv && (drv->suspend || drv->suspend_late || drv->resume
+ || drv->resume_early);
+
+ /*
+ * Legacy PM support is used by default, so warn if the new framework is
+ * supported as well. Drivers are supposed to support either the
+ * former, or the latter, but not both at the same time.
+ */
+ WARN_ON(ret && drv->driver.pm);
+
+ return ret;
+}
+
+/* New power management framework */
+
static int pci_pm_prepare(struct device *dev)
{
struct device_driver *drv = dev->driver;
@@ -416,17 +500,16 @@ static int pci_pm_suspend(struct device *dev)
struct device_driver *drv = dev->driver;
int error = 0;
- if (drv && drv->pm) {
- if (drv->pm->suspend) {
- error = drv->pm->suspend(dev);
- suspend_report_result(drv->pm->suspend, error);
- } else {
- pci_default_pm_suspend(pci_dev);
- }
- } else {
- error = pci_legacy_suspend(dev, PMSG_SUSPEND);
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_suspend(dev, PMSG_SUSPEND);
+
+ if (drv && drv->pm && drv->pm->suspend) {
+ error = drv->pm->suspend(dev);
+ suspend_report_result(drv->pm->suspend, error);
}
- pci_fixup_device(pci_fixup_suspend, pci_dev);
+
+ if (!error)
+ pci_pm_default_suspend(pci_dev);
return error;
}
@@ -434,53 +517,60 @@ static int pci_pm_suspend(struct device *dev)
static int pci_pm_suspend_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
+ struct device_driver *drv = dev->driver;
int error = 0;
- if (drv && drv->pm) {
- if (drv->pm->suspend_noirq) {
- error = drv->pm->suspend_noirq(dev);
- suspend_report_result(drv->pm->suspend_noirq, error);
- }
- } else {
- error = pci_legacy_suspend_late(dev, PMSG_SUSPEND);
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_suspend_late(dev, PMSG_SUSPEND);
+
+ if (drv && drv->pm && drv->pm->suspend_noirq) {
+ error = drv->pm->suspend_noirq(dev);
+ suspend_report_result(drv->pm->suspend_noirq, error);
}
+ if (!error)
+ pci_pm_set_unknown_state(pci_dev);
+
return error;
}
-static int pci_pm_resume(struct device *dev)
+static int pci_pm_resume_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
- int error;
+ int error = 0;
- pci_fixup_device(pci_fixup_resume, pci_dev);
+ pci_pm_default_resume_noirq(pci_dev);
- if (drv && drv->pm) {
- error = drv->pm->resume ? drv->pm->resume(dev) :
- pci_default_pm_resume(pci_dev);
- } else {
- error = pci_legacy_resume(dev);
- }
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_resume_early(dev);
+
+ if (drv && drv->pm && drv->pm->resume_noirq)
+ error = drv->pm->resume_noirq(dev);
return error;
}
-static int pci_pm_resume_noirq(struct device *dev)
+static int pci_pm_resume(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
+ struct device_driver *drv = dev->driver;
int error = 0;
- pci_fixup_device(pci_fixup_resume_early, pci_dev);
+ /*
+ * This is necessary for the suspend error path in which resume is
+ * called without restoring the standard config registers of the device.
+ */
+ if (pci_dev->state_saved)
+ pci_restore_standard_config(pci_dev);
- if (drv && drv->pm) {
- if (drv->pm->resume_noirq)
- error = drv->pm->resume_noirq(dev);
- } else {
- error = pci_legacy_resume_early(dev);
- }
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_resume(dev);
+
+ error = pci_pm_default_resume(pci_dev);
+
+ if (!error && drv && drv->pm && drv->pm->resume)
+ error = drv->pm->resume(dev);
return error;
}
@@ -502,141 +592,150 @@ static int pci_pm_freeze(struct device *dev)
struct device_driver *drv = dev->driver;
int error = 0;
- if (drv && drv->pm) {
- if (drv->pm->freeze) {
- error = drv->pm->freeze(dev);
- suspend_report_result(drv->pm->freeze, error);
- } else {
- pci_default_pm_suspend(pci_dev);
- }
- } else {
- error = pci_legacy_suspend(dev, PMSG_FREEZE);
- pci_fixup_device(pci_fixup_suspend, pci_dev);
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_suspend(dev, PMSG_FREEZE);
+
+ if (drv && drv->pm && drv->pm->freeze) {
+ error = drv->pm->freeze(dev);
+ suspend_report_result(drv->pm->freeze, error);
}
+ if (!error)
+ pci_pm_default_suspend_generic(pci_dev);
+
return error;
}
static int pci_pm_freeze_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
+ struct device_driver *drv = dev->driver;
int error = 0;
- if (drv && drv->pm) {
- if (drv->pm->freeze_noirq) {
- error = drv->pm->freeze_noirq(dev);
- suspend_report_result(drv->pm->freeze_noirq, error);
- }
- } else {
- error = pci_legacy_suspend_late(dev, PMSG_FREEZE);
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_suspend_late(dev, PMSG_FREEZE);
+
+ if (drv && drv->pm && drv->pm->freeze_noirq) {
+ error = drv->pm->freeze_noirq(dev);
+ suspend_report_result(drv->pm->freeze_noirq, error);
}
+ if (!error)
+ pci_pm_set_unknown_state(pci_dev);
+
return error;
}
-static int pci_pm_thaw(struct device *dev)
+static int pci_pm_thaw_noirq(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
- if (drv && drv->pm) {
- if (drv->pm->thaw)
- error = drv->pm->thaw(dev);
- } else {
- pci_fixup_device(pci_fixup_resume, to_pci_dev(dev));
- error = pci_legacy_resume(dev);
- }
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_resume_early(dev);
+
+ pci_update_current_state(pci_dev, PCI_D0);
+
+ if (drv && drv->pm && drv->pm->thaw_noirq)
+ error = drv->pm->thaw_noirq(dev);
return error;
}
-static int pci_pm_thaw_noirq(struct device *dev)
+static int pci_pm_thaw(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
+ struct device_driver *drv = dev->driver;
int error = 0;
- if (drv && drv->pm) {
- if (drv->pm->thaw_noirq)
- error = drv->pm->thaw_noirq(dev);
- } else {
- pci_fixup_device(pci_fixup_resume_early, pci_dev);
- error = pci_legacy_resume_early(dev);
- }
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_resume(dev);
+
+ pci_pm_reenable_device(pci_dev);
+
+ if (drv && drv->pm && drv->pm->thaw)
+ error = drv->pm->thaw(dev);
return error;
}
static int pci_pm_poweroff(struct device *dev)
{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
int error = 0;
- pci_fixup_device(pci_fixup_suspend, to_pci_dev(dev));
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_suspend(dev, PMSG_HIBERNATE);
- if (drv && drv->pm) {
- if (drv->pm->poweroff) {
- error = drv->pm->poweroff(dev);
- suspend_report_result(drv->pm->poweroff, error);
- }
- } else {
- error = pci_legacy_suspend(dev, PMSG_HIBERNATE);
+ if (!drv || !drv->pm)
+ return 0;
+
+ if (drv->pm->poweroff) {
+ error = drv->pm->poweroff(dev);
+ suspend_report_result(drv->pm->poweroff, error);
}
+ if (!error)
+ pci_pm_default_suspend(pci_dev);
+
return error;
}
static int pci_pm_poweroff_noirq(struct device *dev)
{
- struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
+ struct device_driver *drv = dev->driver;
int error = 0;
- if (drv && drv->pm) {
- if (drv->pm->poweroff_noirq) {
- error = drv->pm->poweroff_noirq(dev);
- suspend_report_result(drv->pm->poweroff_noirq, error);
- }
- } else {
- error = pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
+ if (pci_has_legacy_pm_support(to_pci_dev(dev)))
+ return pci_legacy_suspend_late(dev, PMSG_HIBERNATE);
+
+ if (drv && drv->pm && drv->pm->poweroff_noirq) {
+ error = drv->pm->poweroff_noirq(dev);
+ suspend_report_result(drv->pm->poweroff_noirq, error);
}
return error;
}
-static int pci_pm_restore(struct device *dev)
+static int pci_pm_restore_noirq(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct device_driver *drv = dev->driver;
- int error;
+ int error = 0;
- if (drv && drv->pm) {
- error = drv->pm->restore ? drv->pm->restore(dev) :
- pci_default_pm_resume(pci_dev);
- } else {
- error = pci_legacy_resume(dev);
- }
- pci_fixup_device(pci_fixup_resume, pci_dev);
+ pci_pm_default_resume_noirq(pci_dev);
+
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_resume_early(dev);
+
+ if (drv && drv->pm && drv->pm->restore_noirq)
+ error = drv->pm->restore_noirq(dev);
return error;
}
-static int pci_pm_restore_noirq(struct device *dev)
+static int pci_pm_restore(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *drv = pci_dev->driver;
+ struct device_driver *drv = dev->driver;
int error = 0;
- pci_fixup_device(pci_fixup_resume, pci_dev);
+ /*
+ * This is necessary for the hibernation error path in which restore is
+ * called without restoring the standard config registers of the device.
+ */
+ if (pci_dev->state_saved)
+ pci_restore_standard_config(pci_dev);
- if (drv && drv->pm) {
- if (drv->pm->restore_noirq)
- error = drv->pm->restore_noirq(dev);
- } else {
- error = pci_legacy_resume_early(dev);
- }
- pci_fixup_device(pci_fixup_resume_early, pci_dev);
+ if (pci_has_legacy_pm_support(pci_dev))
+ return pci_legacy_resume(dev);
+
+ error = pci_pm_default_resume(pci_dev);
+
+ if (!error && drv && drv->pm && drv->pm->restore)
+ error = drv->pm->restore(dev);
return error;
}
@@ -654,17 +753,15 @@ static int pci_pm_restore_noirq(struct device *dev)
#endif /* !CONFIG_HIBERNATION */
-struct pm_ext_ops pci_pm_ops = {
- .base = {
- .prepare = pci_pm_prepare,
- .complete = pci_pm_complete,
- .suspend = pci_pm_suspend,
- .resume = pci_pm_resume,
- .freeze = pci_pm_freeze,
- .thaw = pci_pm_thaw,
- .poweroff = pci_pm_poweroff,
- .restore = pci_pm_restore,
- },
+struct dev_pm_ops pci_dev_pm_ops = {
+ .prepare = pci_pm_prepare,
+ .complete = pci_pm_complete,
+ .suspend = pci_pm_suspend,
+ .resume = pci_pm_resume,
+ .freeze = pci_pm_freeze,
+ .thaw = pci_pm_thaw,
+ .poweroff = pci_pm_poweroff,
+ .restore = pci_pm_restore,
.suspend_noirq = pci_pm_suspend_noirq,
.resume_noirq = pci_pm_resume_noirq,
.freeze_noirq = pci_pm_freeze_noirq,
@@ -673,7 +770,7 @@ struct pm_ext_ops pci_pm_ops = {
.restore_noirq = pci_pm_restore_noirq,
};
-#define PCI_PM_OPS_PTR &pci_pm_ops
+#define PCI_PM_OPS_PTR (&pci_dev_pm_ops)
#else /* !CONFIG_PM_SLEEP */
@@ -703,9 +800,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
drv->driver.owner = owner;
drv->driver.mod_name = mod_name;
- if (drv->pm)
- drv->driver.pm = &drv->pm->base;
-
spin_lock_init(&drv->dynids.lock);
INIT_LIST_HEAD(&drv->dynids.list);
diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c
new file mode 100644
index 000000000000..74fbec0bf6cb
--- /dev/null
+++ b/drivers/pci/pci-stub.c
@@ -0,0 +1,47 @@
+/* pci-stub - simple stub driver to reserve a pci device
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Author:
+ * Chris Wright
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * Usage is simple, allocate a new id to the stub driver and bind the
+ * device to it. For example:
+ *
+ * # echo "8086 10f5" > /sys/bus/pci/drivers/pci-stub/new_id
+ * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind
+ * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/pci-stub/bind
+ * # ls -l /sys/bus/pci/devices/0000:00:19.0/driver
+ * .../0000:00:19.0/driver -> ../../../bus/pci/drivers/pci-stub
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static struct pci_driver stub_driver = {
+ .name = "pci-stub",
+ .id_table = NULL, /* only dynamic id's */
+ .probe = pci_stub_probe,
+};
+
+static int __init pci_stub_init(void)
+{
+ return pci_register_driver(&stub_driver);
+}
+
+static void __exit pci_stub_exit(void)
+{
+ pci_unregister_driver(&stub_driver);
+}
+
+module_init(pci_stub_init);
+module_exit(pci_stub_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Chris Wright <chrisw@sous-sol.org>");
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5d72866897a8..db7ec14fa719 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -58,22 +58,23 @@ static ssize_t broken_parity_status_store(struct device *dev,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
- ssize_t consumed = -EINVAL;
+ unsigned long val;
- if ((count > 0) && (*buf == '0' || *buf == '1')) {
- pdev->broken_parity_status = *buf == '1' ? 1 : 0;
- consumed = count;
- }
- return consumed;
+ if (strict_strtoul(buf, 0, &val) < 0)
+ return -EINVAL;
+
+ pdev->broken_parity_status = !!val;
+
+ return count;
}
static ssize_t local_cpus_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- cpumask_t mask;
+ const struct cpumask *mask;
int len;
- mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+ mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
buf[len++] = '\n';
buf[len] = '\0';
@@ -84,10 +85,10 @@ static ssize_t local_cpus_show(struct device *dev,
static ssize_t local_cpulist_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- cpumask_t mask;
+ const struct cpumask *mask;
int len;
- mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
+ mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
buf[len++] = '\n';
buf[len] = '\0';
@@ -101,11 +102,13 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)
struct pci_dev * pci_dev = to_pci_dev(dev);
char * str = buf;
int i;
- int max = 7;
+ int max;
resource_size_t start, end;
if (pci_dev->subordinate)
max = DEVICE_COUNT_RESOURCE;
+ else
+ max = PCI_BRIDGE_RESOURCES;
for (i = 0; i < max; i++) {
struct resource *res = &pci_dev->resource[i];
@@ -133,19 +136,23 @@ static ssize_t is_enabled_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
- ssize_t result = -EINVAL;
struct pci_dev *pdev = to_pci_dev(dev);
+ unsigned long val;
+ ssize_t result = strict_strtoul(buf, 0, &val);
+
+ if (result < 0)
+ return result;
/* this can crash the machine when done on the "wrong" device */
if (!capable(CAP_SYS_ADMIN))
- return count;
+ return -EPERM;
- if (*buf == '0') {
+ if (!val) {
if (atomic_read(&pdev->enable_cnt) != 0)
pci_disable_device(pdev);
else
result = -EIO;
- } else if (*buf == '1')
+ } else
result = pci_enable_device(pdev);
return result < 0 ? result : count;
@@ -185,25 +192,28 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 0, &val) < 0)
+ return -EINVAL;
/* bad things may happen if the no_msi flag is changed
* while some drivers are loaded */
if (!capable(CAP_SYS_ADMIN))
- return count;
+ return -EPERM;
+ /* Maybe pci devices without subordinate busses shouldn't even have this
+ * attribute in the first place? */
if (!pdev->subordinate)
return count;
- if (*buf == '0') {
- pdev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
- dev_warn(&pdev->dev, "forced subordinate bus to not support MSI,"
- " bad things could happen.\n");
- }
+ /* Is the flag going to change, or keep the value it already had? */
+ if (!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI) ^
+ !!val) {
+ pdev->subordinate->bus_flags ^= PCI_BUS_FLAGS_NO_MSI;
- if (*buf == '1') {
- pdev->subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI;
- dev_warn(&pdev->dev, "forced subordinate bus to support MSI,"
- " bad things could happen.\n");
+ dev_warn(&pdev->dev, "forced subordinate bus to%s support MSI,"
+ " bad things could happen\n", val ? "" : " not");
}
return count;
@@ -361,55 +371,33 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
}
static ssize_t
-pci_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
+read_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_dev *dev =
to_pci_dev(container_of(kobj, struct device, kobj));
- int end;
- int ret;
if (off > bin_attr->size)
count = 0;
else if (count > bin_attr->size - off)
count = bin_attr->size - off;
- end = off + count;
-
- while (off < end) {
- ret = dev->vpd->ops->read(dev, off, end - off, buf);
- if (ret < 0)
- return ret;
- buf += ret;
- off += ret;
- }
- return count;
+ return pci_read_vpd(dev, off, count, buf);
}
static ssize_t
-pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
- char *buf, loff_t off, size_t count)
+write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_dev *dev =
to_pci_dev(container_of(kobj, struct device, kobj));
- int end;
- int ret;
if (off > bin_attr->size)
count = 0;
else if (count > bin_attr->size - off)
count = bin_attr->size - off;
- end = off + count;
-
- while (off < end) {
- ret = dev->vpd->ops->write(dev, off, end - off, buf);
- if (ret < 0)
- return ret;
- buf += ret;
- off += ret;
- }
- return count;
+ return pci_write_vpd(dev, off, count, buf);
}
#ifdef HAVE_PCI_LEGACY
@@ -569,7 +557,7 @@ void pci_remove_legacy_files(struct pci_bus *b)
#ifdef HAVE_PCI_MMAP
-static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma)
{
unsigned long nr, start, size;
@@ -620,6 +608,9 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
vma->vm_pgoff += start >> PAGE_SHIFT;
mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+ if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(start))
+ return -EINVAL;
+
return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
}
@@ -832,8 +823,8 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
attr->size = dev->vpd->len;
attr->attr.name = "vpd";
attr->attr.mode = S_IRUSR | S_IWUSR;
- attr->read = pci_read_vpd;
- attr->write = pci_write_vpd;
+ attr->read = read_vpd_attr;
+ attr->write = write_vpd_attr;
retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
if (retval) {
kfree(dev->vpd->attr);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 061d1ee0046a..48807556b47a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -22,7 +22,7 @@
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
-unsigned int pci_pm_d3_delay = 10;
+unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT;
#ifdef CONFIG_PCI_DOMAINS
int pci_domains_supported = 1;
@@ -56,6 +56,22 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus)
}
EXPORT_SYMBOL_GPL(pci_bus_max_busnr);
+#ifdef CONFIG_HAS_IOMEM
+void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
+{
+ /*
+ * Make sure the BAR is actually a memory resource, not an IO resource
+ */
+ if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
+ WARN_ON(1);
+ return NULL;
+ }
+ return ioremap_nocache(pci_resource_start(pdev, bar),
+ pci_resource_len(pdev, bar));
+}
+EXPORT_SYMBOL_GPL(pci_ioremap_bar);
+#endif
+
#if 0
/**
* pci_max_busnr - returns maximum PCI bus number
@@ -360,25 +376,10 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
static void
pci_restore_bars(struct pci_dev *dev)
{
- int i, numres;
-
- switch (dev->hdr_type) {
- case PCI_HEADER_TYPE_NORMAL:
- numres = 6;
- break;
- case PCI_HEADER_TYPE_BRIDGE:
- numres = 2;
- break;
- case PCI_HEADER_TYPE_CARDBUS:
- numres = 1;
- break;
- default:
- /* Should never get here, but just in case... */
- return;
- }
+ int i;
- for (i = 0; i < numres; i ++)
- pci_update_resource(dev, &dev->resource[i], i);
+ for (i = 0; i < PCI_BRIDGE_RESOURCES; i++)
+ pci_update_resource(dev, i);
}
static struct pci_platform_pm_ops *pci_platform_pm;
@@ -425,6 +426,7 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
* given PCI device
* @dev: PCI device to handle.
* @state: PCI power state (D0, D1, D2, D3hot) to put the device into.
+ * @wait: If 'true', wait for the device to change its power state
*
* RETURN VALUE:
* -EINVAL if the requested state is invalid.
@@ -434,7 +436,7 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
* 0 if device's power state has been successfully changed.
*/
static int
-pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
+pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait)
{
u16 pmcsr;
bool need_restore = false;
@@ -479,8 +481,10 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
break;
case PCI_UNKNOWN: /* Boot-up */
if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
- && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
+ && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) {
need_restore = true;
+ wait = true;
+ }
/* Fall-through: force to D0 */
default:
pmcsr = 0;
@@ -490,12 +494,15 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
/* enter specified state */
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
+ if (!wait)
+ return 0;
+
/* Mandatory power management transition delays */
/* see PCI PM 1.1 5.6.1 table 18 */
if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
msleep(pci_pm_d3_delay);
else if (state == PCI_D2 || dev->current_state == PCI_D2)
- udelay(200);
+ udelay(PCI_PM_D2_DELAY);
dev->current_state = state;
@@ -514,7 +521,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
if (need_restore)
pci_restore_bars(dev);
- if (dev->bus->self)
+ if (wait && dev->bus->self)
pcie_aspm_pm_state_change(dev->bus->self);
return 0;
@@ -524,14 +531,17 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
* pci_update_current_state - Read PCI power state of given device from its
* PCI PM registers and cache it
* @dev: PCI device to handle.
+ * @state: State to cache in case the device doesn't have the PM capability
*/
-static void pci_update_current_state(struct pci_dev *dev)
+void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
{
if (dev->pm_cap) {
u16 pmcsr;
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
+ } else {
+ dev->current_state = state;
}
}
@@ -574,20 +584,20 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
*/
int ret = platform_pci_set_power_state(dev, PCI_D0);
if (!ret)
- pci_update_current_state(dev);
+ pci_update_current_state(dev, PCI_D0);
}
/* This device is quirked not to be put into D3, so
don't put it in D3 */
if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
return 0;
- error = pci_raw_set_power_state(dev, state);
+ error = pci_raw_set_power_state(dev, state, true);
if (state > PCI_D0 && platform_pci_power_manageable(dev)) {
/* Allow the platform to finalize the transition */
int ret = platform_pci_set_power_state(dev, state);
if (!ret) {
- pci_update_current_state(dev);
+ pci_update_current_state(dev, state);
error = 0;
}
}
@@ -640,19 +650,14 @@ static int pci_save_pcie_state(struct pci_dev *dev)
int pos, i = 0;
struct pci_cap_saved_state *save_state;
u16 *cap;
- int found = 0;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (pos <= 0)
return 0;
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
- if (!save_state)
- save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
- else
- found = 1;
if (!save_state) {
- dev_err(&dev->dev, "out of memory in pci_save_pcie_state\n");
+ dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__);
return -ENOMEM;
}
cap = (u16 *)&save_state->data[0];
@@ -661,9 +666,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
- save_state->cap_nr = PCI_CAP_ID_EXP;
- if (!found)
- pci_add_saved_cap(dev, save_state);
+
return 0;
}
@@ -688,30 +691,21 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
static int pci_save_pcix_state(struct pci_dev *dev)
{
- int pos, i = 0;
+ int pos;
struct pci_cap_saved_state *save_state;
- u16 *cap;
- int found = 0;
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (pos <= 0)
return 0;
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
- if (!save_state)
- save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
- else
- found = 1;
if (!save_state) {
- dev_err(&dev->dev, "out of memory in pci_save_pcie_state\n");
+ dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__);
return -ENOMEM;
}
- cap = (u16 *)&save_state->data[0];
- pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
- save_state->cap_nr = PCI_CAP_ID_PCIX;
- if (!found)
- pci_add_saved_cap(dev, save_state);
+ pci_read_config_word(dev, pos + PCI_X_CMD, (u16 *)save_state->data);
+
return 0;
}
@@ -742,6 +736,7 @@ pci_save_state(struct pci_dev *dev)
/* XXX: 100% dword access ok here? */
for (i = 0; i < 16; i++)
pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
+ dev->state_saved = true;
if ((i = pci_save_pcie_state(dev)) != 0)
return i;
if ((i = pci_save_pcix_state(dev)) != 0)
@@ -982,6 +977,32 @@ void pcim_pin_device(struct pci_dev *pdev)
*/
void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {}
+static void do_pci_disable_device(struct pci_dev *dev)
+{
+ u16 pci_command;
+
+ pci_read_config_word(dev, PCI_COMMAND, &pci_command);
+ if (pci_command & PCI_COMMAND_MASTER) {
+ pci_command &= ~PCI_COMMAND_MASTER;
+ pci_write_config_word(dev, PCI_COMMAND, pci_command);
+ }
+
+ pcibios_disable_device(dev);
+}
+
+/**
+ * pci_disable_enabled_device - Disable device without updating enable_cnt
+ * @dev: PCI device to disable
+ *
+ * NOTE: This function is a backend of PCI power management routines and is
+ * not supposed to be called drivers.
+ */
+void pci_disable_enabled_device(struct pci_dev *dev)
+{
+ if (atomic_read(&dev->enable_cnt))
+ do_pci_disable_device(dev);
+}
+
/**
* pci_disable_device - Disable PCI device after use
* @dev: PCI device to be disabled
@@ -996,7 +1017,6 @@ void
pci_disable_device(struct pci_dev *dev)
{
struct pci_devres *dr;
- u16 pci_command;
dr = find_pci_dr(dev);
if (dr)
@@ -1005,14 +1025,9 @@ pci_disable_device(struct pci_dev *dev)
if (atomic_sub_return(1, &dev->enable_cnt) != 0)
return;
- pci_read_config_word(dev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_MASTER) {
- pci_command &= ~PCI_COMMAND_MASTER;
- pci_write_config_word(dev, PCI_COMMAND, pci_command);
- }
- dev->is_busmaster = 0;
+ do_pci_disable_device(dev);
- pcibios_disable_device(dev);
+ dev->is_busmaster = 0;
}
/**
@@ -1107,7 +1122,7 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
int error = 0;
bool pme_done = false;
- if (!device_may_wakeup(&dev->dev))
+ if (enable && !device_may_wakeup(&dev->dev))
return -EINVAL;
/*
@@ -1301,6 +1316,115 @@ void pci_pm_init(struct pci_dev *dev)
}
/**
+ * platform_pci_wakeup_init - init platform wakeup if present
+ * @dev: PCI device
+ *
+ * Some devices don't have PCI PM caps but can still generate wakeup
+ * events through platform methods (like ACPI events). If @dev supports
+ * platform wakeup events, set the device flag to indicate as much. This
+ * may be redundant if the device also supports PCI PM caps, but double
+ * initialization should be safe in that case.
+ */
+void platform_pci_wakeup_init(struct pci_dev *dev)
+{
+ if (!platform_pci_can_wakeup(dev))
+ return;
+
+ device_set_wakeup_capable(&dev->dev, true);
+ device_set_wakeup_enable(&dev->dev, false);
+ platform_pci_sleep_wake(dev, false);
+}
+
+/**
+ * pci_add_save_buffer - allocate buffer for saving given capability registers
+ * @dev: the PCI device
+ * @cap: the capability to allocate the buffer for
+ * @size: requested size of the buffer
+ */
+static int pci_add_cap_save_buffer(
+ struct pci_dev *dev, char cap, unsigned int size)
+{
+ int pos;
+ struct pci_cap_saved_state *save_state;
+
+ pos = pci_find_capability(dev, cap);
+ if (pos <= 0)
+ return 0;
+
+ save_state = kzalloc(sizeof(*save_state) + size, GFP_KERNEL);
+ if (!save_state)
+ return -ENOMEM;
+
+ save_state->cap_nr = cap;
+ pci_add_saved_cap(dev, save_state);
+
+ return 0;
+}
+
+/**
+ * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities
+ * @dev: the PCI device
+ */
+void pci_allocate_cap_save_buffers(struct pci_dev *dev)
+{
+ int error;
+
+ error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP, 4 * sizeof(u16));
+ if (error)
+ dev_err(&dev->dev,
+ "unable to preallocate PCI Express save buffer\n");
+
+ error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_PCIX, sizeof(u16));
+ if (error)
+ dev_err(&dev->dev,
+ "unable to preallocate PCI-X save buffer\n");
+}
+
+/**
+ * pci_restore_standard_config - restore standard config registers of PCI device
+ * @dev: PCI device to handle
+ *
+ * This function assumes that the device's configuration space is accessible.
+ * If the device needs to be powered up, the function will wait for it to
+ * change the state.
+ */
+int pci_restore_standard_config(struct pci_dev *dev)
+{
+ pci_power_t prev_state;
+ int error;
+
+ pci_update_current_state(dev, PCI_D0);
+
+ prev_state = dev->current_state;
+ if (prev_state == PCI_D0)
+ goto Restore;
+
+ error = pci_raw_set_power_state(dev, PCI_D0, false);
+ if (error)
+ return error;
+
+ /*
+ * This assumes that we won't get a bus in B2 or B3 from the BIOS, but
+ * we've made this assumption forever and it appears to be universally
+ * satisfied.
+ */
+ switch(prev_state) {
+ case PCI_D3cold:
+ case PCI_D3hot:
+ mdelay(pci_pm_d3_delay);
+ break;
+ case PCI_D2:
+ udelay(PCI_PM_D2_DELAY);
+ break;
+ }
+
+ dev->current_state = PCI_D0;
+
+ Restore:
+ return pci_restore_state(dev);
+}
+
+/**
* pci_enable_ari - enable ARI forwarding if hardware support it
* @dev: the PCI device
*/
@@ -1337,6 +1461,20 @@ void pci_enable_ari(struct pci_dev *dev)
bridge->ari_enabled = 1;
}
+/**
+ * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
+ * @dev: the PCI device
+ * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTD, 4=INTD)
+ *
+ * Perform INTx swizzling for a device behind one level of bridge. This is
+ * required by section 9.1 of the PCI-to-PCI bridge specification for devices
+ * behind bridges on add-in cards.
+ */
+u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
+{
+ return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+}
+
int
pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
{
@@ -1345,9 +1483,9 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
pin = dev->pin;
if (!pin)
return -1;
- pin--;
+
while (dev->bus->self) {
- pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+ pin = pci_swizzle_interrupt_pin(dev, pin);
dev = dev->bus->self;
}
*bridge = dev;
@@ -1355,6 +1493,26 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
}
/**
+ * pci_common_swizzle - swizzle INTx all the way to root bridge
+ * @dev: the PCI device
+ * @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD)
+ *
+ * Perform INTx swizzling for a device. This traverses through all PCI-to-PCI
+ * bridges all the way up to a PCI root bus.
+ */
+u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ u8 pin = *pinp;
+
+ while (dev->bus->self) {
+ pin = pci_swizzle_interrupt_pin(dev, pin);
+ dev = dev->bus->self;
+ }
+ *pinp = pin;
+ return PCI_SLOT(dev->devfn);
+}
+
+/**
* pci_release_region - Release a PCI bar
* @pdev: PCI device whose resources were previously reserved by pci_request_region
* @bar: BAR to release
@@ -1395,7 +1553,8 @@ void pci_release_region(struct pci_dev *pdev, int bar)
* Returns 0 on success, or %EBUSY on error. A warning
* message is also printed on failure.
*/
-int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
+static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_name,
+ int exclusive)
{
struct pci_devres *dr;
@@ -1408,8 +1567,9 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
goto err_out;
}
else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
- if (!request_mem_region(pci_resource_start(pdev, bar),
- pci_resource_len(pdev, bar), res_name))
+ if (!__request_mem_region(pci_resource_start(pdev, bar),
+ pci_resource_len(pdev, bar), res_name,
+ exclusive))
goto err_out;
}
@@ -1428,6 +1588,47 @@ err_out:
}
/**
+ * pci_request_region - Reserved PCI I/O and memory resource
+ * @pdev: PCI device whose resources are to be reserved
+ * @bar: BAR to be reserved
+ * @res_name: Name to be associated with resource.
+ *
+ * Mark the PCI region associated with PCI device @pdev BR @bar as
+ * being reserved by owner @res_name. Do not access any
+ * address inside the PCI regions unless this call returns
+ * successfully.
+ *
+ * Returns 0 on success, or %EBUSY on error. A warning
+ * message is also printed on failure.
+ */
+int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
+{
+ return __pci_request_region(pdev, bar, res_name, 0);
+}
+
+/**
+ * pci_request_region_exclusive - Reserved PCI I/O and memory resource
+ * @pdev: PCI device whose resources are to be reserved
+ * @bar: BAR to be reserved
+ * @res_name: Name to be associated with resource.
+ *
+ * Mark the PCI region associated with PCI device @pdev BR @bar as
+ * being reserved by owner @res_name. Do not access any
+ * address inside the PCI regions unless this call returns
+ * successfully.
+ *
+ * Returns 0 on success, or %EBUSY on error. A warning
+ * message is also printed on failure.
+ *
+ * The key difference that _exclusive makes it that userspace is
+ * explicitly not allowed to map the resource via /dev/mem or
+ * sysfs.
+ */
+int pci_request_region_exclusive(struct pci_dev *pdev, int bar, const char *res_name)
+{
+ return __pci_request_region(pdev, bar, res_name, IORESOURCE_EXCLUSIVE);
+}
+/**
* pci_release_selected_regions - Release selected PCI I/O and memory resources
* @pdev: PCI device whose resources were previously reserved
* @bars: Bitmask of BARs to be released
@@ -1444,20 +1645,14 @@ void pci_release_selected_regions(struct pci_dev *pdev, int bars)
pci_release_region(pdev, i);
}
-/**
- * pci_request_selected_regions - Reserve selected PCI I/O and memory resources
- * @pdev: PCI device whose resources are to be reserved
- * @bars: Bitmask of BARs to be requested
- * @res_name: Name to be associated with resource
- */
-int pci_request_selected_regions(struct pci_dev *pdev, int bars,
- const char *res_name)
+int __pci_request_selected_regions(struct pci_dev *pdev, int bars,
+ const char *res_name, int excl)
{
int i;
for (i = 0; i < 6; i++)
if (bars & (1 << i))
- if(pci_request_region(pdev, i, res_name))
+ if (__pci_request_region(pdev, i, res_name, excl))
goto err_out;
return 0;
@@ -1469,6 +1664,26 @@ err_out:
return -EBUSY;
}
+
+/**
+ * pci_request_selected_regions - Reserve selected PCI I/O and memory resources
+ * @pdev: PCI device whose resources are to be reserved
+ * @bars: Bitmask of BARs to be requested
+ * @res_name: Name to be associated with resource
+ */
+int pci_request_selected_regions(struct pci_dev *pdev, int bars,
+ const char *res_name)
+{
+ return __pci_request_selected_regions(pdev, bars, res_name, 0);
+}
+
+int pci_request_selected_regions_exclusive(struct pci_dev *pdev,
+ int bars, const char *res_name)
+{
+ return __pci_request_selected_regions(pdev, bars, res_name,
+ IORESOURCE_EXCLUSIVE);
+}
+
/**
* pci_release_regions - Release reserved PCI I/O and memory resources
* @pdev: PCI device whose resources were previously reserved by pci_request_regions
@@ -1502,27 +1717,66 @@ int pci_request_regions(struct pci_dev *pdev, const char *res_name)
}
/**
+ * pci_request_regions_exclusive - Reserved PCI I/O and memory resources
+ * @pdev: PCI device whose resources are to be reserved
+ * @res_name: Name to be associated with resource.
+ *
+ * Mark all PCI regions associated with PCI device @pdev as
+ * being reserved by owner @res_name. Do not access any
+ * address inside the PCI regions unless this call returns
+ * successfully.
+ *
+ * pci_request_regions_exclusive() will mark the region so that
+ * /dev/mem and the sysfs MMIO access will not be allowed.
+ *
+ * Returns 0 on success, or %EBUSY on error. A warning
+ * message is also printed on failure.
+ */
+int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)
+{
+ return pci_request_selected_regions_exclusive(pdev,
+ ((1 << 6) - 1), res_name);
+}
+
+static void __pci_set_master(struct pci_dev *dev, bool enable)
+{
+ u16 old_cmd, cmd;
+
+ pci_read_config_word(dev, PCI_COMMAND, &old_cmd);
+ if (enable)
+ cmd = old_cmd | PCI_COMMAND_MASTER;
+ else
+ cmd = old_cmd & ~PCI_COMMAND_MASTER;
+ if (cmd != old_cmd) {
+ dev_dbg(&dev->dev, "%s bus mastering\n",
+ enable ? "enabling" : "disabling");
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ dev->is_busmaster = enable;
+}
+
+/**
* pci_set_master - enables bus-mastering for device dev
* @dev: the PCI device to enable
*
* Enables bus-mastering on the device and calls pcibios_set_master()
* to do the needed arch specific settings.
*/
-void
-pci_set_master(struct pci_dev *dev)
+void pci_set_master(struct pci_dev *dev)
{
- u16 cmd;
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- if (! (cmd & PCI_COMMAND_MASTER)) {
- dev_dbg(&dev->dev, "enabling bus mastering\n");
- cmd |= PCI_COMMAND_MASTER;
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- dev->is_busmaster = 1;
+ __pci_set_master(dev, true);
pcibios_set_master(dev);
}
+/**
+ * pci_clear_master - disables bus-mastering for device dev
+ * @dev: the PCI device to disable
+ */
+void pci_clear_master(struct pci_dev *dev)
+{
+ __pci_set_master(dev, false);
+}
+
#ifdef PCI_DISABLE_MWI
int pci_set_mwi(struct pci_dev *dev)
{
@@ -1751,24 +2005,7 @@ int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
EXPORT_SYMBOL(pci_set_dma_seg_boundary);
#endif
-/**
- * pci_execute_reset_function() - Reset a PCI device function
- * @dev: Device function to reset
- *
- * Some devices allow an individual function to be reset without affecting
- * other functions in the same device. The PCI device must be responsive
- * to PCI config space in order to use this function.
- *
- * The device function is presumed to be unused when this function is called.
- * Resetting the device will make the contents of PCI configuration space
- * random, so any caller of this must be prepared to reinitialise the
- * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
- * etc.
- *
- * Returns 0 if the device function was successfully reset or -ENOTTY if the
- * device doesn't support resetting a single function.
- */
-int pci_execute_reset_function(struct pci_dev *dev)
+static int __pcie_flr(struct pci_dev *dev, int probe)
{
u16 status;
u32 cap;
@@ -1780,6 +2017,9 @@ int pci_execute_reset_function(struct pci_dev *dev)
if (!(cap & PCI_EXP_DEVCAP_FLR))
return -ENOTTY;
+ if (probe)
+ return 0;
+
pci_block_user_cfg_access(dev);
/* Wait for Transaction Pending bit clean */
@@ -1802,6 +2042,80 @@ int pci_execute_reset_function(struct pci_dev *dev)
pci_unblock_user_cfg_access(dev);
return 0;
}
+
+static int __pci_af_flr(struct pci_dev *dev, int probe)
+{
+ int cappos = pci_find_capability(dev, PCI_CAP_ID_AF);
+ u8 status;
+ u8 cap;
+
+ if (!cappos)
+ return -ENOTTY;
+ pci_read_config_byte(dev, cappos + PCI_AF_CAP, &cap);
+ if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
+ return -ENOTTY;
+
+ if (probe)
+ return 0;
+
+ pci_block_user_cfg_access(dev);
+
+ /* Wait for Transaction Pending bit clean */
+ msleep(100);
+ pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status);
+ if (status & PCI_AF_STATUS_TP) {
+ dev_info(&dev->dev, "Busy after 100ms while trying to"
+ " reset; sleeping for 1 second\n");
+ ssleep(1);
+ pci_read_config_byte(dev,
+ cappos + PCI_AF_STATUS, &status);
+ if (status & PCI_AF_STATUS_TP)
+ dev_info(&dev->dev, "Still busy after 1s; "
+ "proceeding with reset anyway\n");
+ }
+ pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
+ mdelay(100);
+
+ pci_unblock_user_cfg_access(dev);
+ return 0;
+}
+
+static int __pci_reset_function(struct pci_dev *pdev, int probe)
+{
+ int res;
+
+ res = __pcie_flr(pdev, probe);
+ if (res != -ENOTTY)
+ return res;
+
+ res = __pci_af_flr(pdev, probe);
+ if (res != -ENOTTY)
+ return res;
+
+ return res;
+}
+
+/**
+ * pci_execute_reset_function() - Reset a PCI device function
+ * @dev: Device function to reset
+ *
+ * Some devices allow an individual function to be reset without affecting
+ * other functions in the same device. The PCI device must be responsive
+ * to PCI config space in order to use this function.
+ *
+ * The device function is presumed to be unused when this function is called.
+ * Resetting the device will make the contents of PCI configuration space
+ * random, so any caller of this must be prepared to reinitialise the
+ * device including MSI, bus mastering, BARs, decoding IO and memory spaces,
+ * etc.
+ *
+ * Returns 0 if the device function was successfully reset or -ENOTTY if the
+ * device doesn't support resetting a single function.
+ */
+int pci_execute_reset_function(struct pci_dev *dev)
+{
+ return __pci_reset_function(dev, 0);
+}
EXPORT_SYMBOL_GPL(pci_execute_reset_function);
/**
@@ -1822,15 +2136,10 @@ EXPORT_SYMBOL_GPL(pci_execute_reset_function);
*/
int pci_reset_function(struct pci_dev *dev)
{
- u32 cap;
- int exppos = pci_find_capability(dev, PCI_CAP_ID_EXP);
- int r;
+ int r = __pci_reset_function(dev, 1);
- if (!exppos)
- return -ENOTTY;
- pci_read_config_dword(dev, exppos + PCI_EXP_DEVCAP, &cap);
- if (!(cap & PCI_EXP_DEVCAP_FLR))
- return -ENOTTY;
+ if (r < 0)
+ return r;
if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0)
disable_irq(dev->irq);
@@ -2022,6 +2331,28 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags)
return bars;
}
+/**
+ * pci_resource_bar - get position of the BAR associated with a resource
+ * @dev: the PCI device
+ * @resno: the resource number
+ * @type: the BAR type to be filled in
+ *
+ * Returns BAR position in config space, or 0 if the BAR is invalid.
+ */
+int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
+{
+ if (resno < PCI_ROM_RESOURCE) {
+ *type = pci_bar_unknown;
+ return PCI_BASE_ADDRESS_0 + 4 * resno;
+ } else if (resno == PCI_ROM_RESOURCE) {
+ *type = pci_bar_mem32;
+ return dev->rom_base_reg;
+ }
+
+ dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno);
+ return 0;
+}
+
static void __devinit pci_no_domains(void)
{
#ifdef CONFIG_PCI_DOMAINS
@@ -2029,6 +2360,19 @@ static void __devinit pci_no_domains(void)
#endif
}
+/**
+ * pci_ext_cfg_enabled - can we access extended PCI config space?
+ * @dev: The PCI device of the root bridge.
+ *
+ * Returns 1 if we can access PCI extended config space (offsets
+ * greater than 0xff). This is the default implementation. Architecture
+ * implementations can override this.
+ */
+int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
+{
+ return 1;
+}
+
static int __devinit pci_init(void)
{
struct pci_dev *dev = NULL;
@@ -2037,8 +2381,6 @@ static int __devinit pci_init(void)
pci_fixup_device(pci_fixup_final, dev);
}
- msi_init();
-
return 0;
}
@@ -2083,11 +2425,15 @@ EXPORT_SYMBOL(pci_find_capability);
EXPORT_SYMBOL(pci_bus_find_capability);
EXPORT_SYMBOL(pci_release_regions);
EXPORT_SYMBOL(pci_request_regions);
+EXPORT_SYMBOL(pci_request_regions_exclusive);
EXPORT_SYMBOL(pci_release_region);
EXPORT_SYMBOL(pci_request_region);
+EXPORT_SYMBOL(pci_request_region_exclusive);
EXPORT_SYMBOL(pci_release_selected_regions);
EXPORT_SYMBOL(pci_request_selected_regions);
+EXPORT_SYMBOL(pci_request_selected_regions_exclusive);
EXPORT_SYMBOL(pci_set_master);
+EXPORT_SYMBOL(pci_clear_master);
EXPORT_SYMBOL(pci_set_mwi);
EXPORT_SYMBOL(pci_try_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 9de87e9f98f5..26ddf78ac300 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -10,6 +10,10 @@ extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_cleanup_rom(struct pci_dev *dev);
+#ifdef HAVE_PCI_MMAP
+extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
+ struct vm_area_struct *vma);
+#endif
/**
* Firmware PM callbacks
@@ -40,7 +44,17 @@ struct pci_platform_pm_ops {
};
extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
+extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
+extern void pci_disable_enabled_device(struct pci_dev *dev);
extern void pci_pm_init(struct pci_dev *dev);
+extern void platform_pci_wakeup_init(struct pci_dev *dev);
+extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
+extern int pci_restore_standard_config(struct pci_dev *dev);
+
+static inline bool pci_is_bridge(struct pci_dev *pci_dev)
+{
+ return !!(pci_dev->subordinate);
+}
extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
@@ -50,14 +64,14 @@ extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
struct pci_vpd_ops {
- int (*read)(struct pci_dev *dev, int pos, int size, char *buf);
- int (*write)(struct pci_dev *dev, int pos, int size, const char *buf);
+ ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
+ ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
void (*release)(struct pci_dev *dev);
};
struct pci_vpd {
unsigned int len;
- struct pci_vpd_ops *ops;
+ const struct pci_vpd_ops *ops;
struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
};
@@ -98,11 +112,9 @@ extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI
void pci_no_msi(void);
extern void pci_msi_init_pci_dev(struct pci_dev *dev);
-extern void __devinit msi_init(void);
#else
static inline void pci_no_msi(void) { }
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
-static inline void msi_init(void) { }
#endif
#ifdef CONFIG_PCIEAER
@@ -159,16 +171,28 @@ struct pci_slot_attribute {
};
#define to_pci_slot_attr(s) container_of(s, struct pci_slot_attribute, attr)
+enum pci_bar_type {
+ pci_bar_unknown, /* Standard PCI BAR probe */
+ pci_bar_io, /* An io port BAR */
+ pci_bar_mem32, /* A 32-bit memory BAR */
+ pci_bar_mem64, /* A 64-bit memory BAR */
+};
+
+extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
+ struct resource *res, unsigned int reg);
+extern int pci_resource_bar(struct pci_dev *dev, int resno,
+ enum pci_bar_type *type);
+extern int pci_bus_add_child(struct pci_bus *bus);
extern void pci_enable_ari(struct pci_dev *dev);
/**
* pci_ari_enabled - query ARI forwarding status
- * @dev: the PCI device
+ * @bus: the PCI bus
*
* Returns 1 if ARI forwarding is enabled, or 0 if not enabled;
*/
-static inline int pci_ari_enabled(struct pci_dev *dev)
+static inline int pci_ari_enabled(struct pci_bus *bus)
{
- return dev->ari_enabled;
+ return bus->self && bus->self->ari_enabled;
}
#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index 6dd7b13e9808..ebce26c37049 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -38,7 +38,6 @@ int aer_osc_setup(struct pcie_device *pciedev)
handle = acpi_find_root_bridge_handle(pdev);
if (handle) {
- pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
status = pci_osc_control_set(handle,
OSC_PCI_EXPRESS_AER_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
index 3933d4f30e8c..0fc29ae80df8 100644
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -233,7 +233,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
if (info->flags & AER_TLP_HEADER_VALID_FLAG) {
unsigned char *tlp = (unsigned char *) &info->tlp;
- printk("%sTLB Header:\n", loglevel);
+ printk("%sTLP Header:\n", loglevel);
printk("%s%02x%02x%02x%02x %02x%02x%02x%02x"
" %02x%02x%02x%02x %02x%02x%02x%02x\n",
loglevel,
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 9aad608bcf3f..586b6f75910d 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
+#include <linux/delay.h>
#include <linux/pci-aspm.h>
#include "../pci.h"
@@ -33,6 +34,11 @@ struct endpoint_state {
struct pcie_link_state {
struct list_head sibiling;
struct pci_dev *pdev;
+ bool downstream_has_switch;
+
+ struct pcie_link_state *parent;
+ struct list_head children;
+ struct list_head link;
/* ASPM state */
unsigned int support_state;
@@ -70,6 +76,8 @@ static const char *policy_str[] = {
[POLICY_POWERSAVE] = "powersave"
};
+#define LINK_RETRAIN_TIMEOUT HZ
+
static int policy_to_aspm_state(struct pci_dev *pdev)
{
struct pcie_link_state *link_state = pdev->link_state;
@@ -125,7 +133,7 @@ static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
link_state->clk_pm_enabled = !!enable;
}
-static void pcie_check_clock_pm(struct pci_dev *pdev)
+static void pcie_check_clock_pm(struct pci_dev *pdev, int blacklist)
{
int pos;
u32 reg32;
@@ -149,10 +157,26 @@ static void pcie_check_clock_pm(struct pci_dev *pdev)
if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
enabled = 0;
}
- link_state->clk_pm_capable = capable;
link_state->clk_pm_enabled = enabled;
link_state->bios_clk_state = enabled;
- pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+ if (!blacklist) {
+ link_state->clk_pm_capable = capable;
+ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+ } else {
+ link_state->clk_pm_capable = 0;
+ pcie_set_clock_pm(pdev, 0);
+ }
+}
+
+static bool pcie_aspm_downstream_has_switch(struct pci_dev *pdev)
+{
+ struct pci_dev *child_dev;
+
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ if (child_dev->pcie_type == PCI_EXP_TYPE_UPSTREAM)
+ return true;
+ }
+ return false;
}
/*
@@ -217,16 +241,18 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
/* Wait for link training end */
- /* break out after waiting for 1 second */
+ /* break out after waiting for timeout */
start_jiffies = jiffies;
- while ((jiffies - start_jiffies) < HZ) {
+ for (;;) {
pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
if (!(reg16 & PCI_EXP_LNKSTA_LT))
break;
- cpu_relax();
+ if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT))
+ break;
+ msleep(1);
}
/* training failed -> recover */
- if ((jiffies - start_jiffies) >= HZ) {
+ if (reg16 & PCI_EXP_LNKSTA_LT) {
dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure"
" common clock\n");
i = 0;
@@ -419,9 +445,9 @@ static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
{
struct pci_dev *child_dev;
- /* If no child, disable the link */
+ /* If no child, ignore the link */
if (list_empty(&pdev->subordinate->devices))
- return 0;
+ return state;
list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
/*
@@ -462,6 +488,9 @@ static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
int valid = 1;
struct pcie_link_state *link_state = pdev->link_state;
+ /* If no child, disable the link */
+ if (list_empty(&pdev->subordinate->devices))
+ state = 0;
/*
* if the downstream component has pci bridge function, don't do ASPM
* now
@@ -493,20 +522,52 @@ static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
link_state->enabled_state = state;
}
+static struct pcie_link_state *get_root_port_link(struct pcie_link_state *link)
+{
+ struct pcie_link_state *root_port_link = link;
+ while (root_port_link->parent)
+ root_port_link = root_port_link->parent;
+ return root_port_link;
+}
+
+/* check the whole hierarchy, and configure each link in the hierarchy */
static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
unsigned int state)
{
struct pcie_link_state *link_state = pdev->link_state;
+ struct pcie_link_state *root_port_link = get_root_port_link(link_state);
+ struct pcie_link_state *leaf;
- if (link_state->support_state == 0)
- return;
state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
- /* state 0 means disabling aspm */
- state = pcie_aspm_check_state(pdev, state);
+ /* check all links who have specific root port link */
+ list_for_each_entry(leaf, &link_list, sibiling) {
+ if (!list_empty(&leaf->children) ||
+ get_root_port_link(leaf) != root_port_link)
+ continue;
+ state = pcie_aspm_check_state(leaf->pdev, state);
+ }
+ /* check root port link too in case it hasn't children */
+ state = pcie_aspm_check_state(root_port_link->pdev, state);
+
if (link_state->enabled_state == state)
return;
- __pcie_aspm_config_link(pdev, state);
+
+ /*
+ * we must change the hierarchy. See comments in
+ * __pcie_aspm_config_link for the order
+ **/
+ if (state & PCIE_LINK_STATE_L1) {
+ list_for_each_entry(leaf, &link_list, sibiling) {
+ if (get_root_port_link(leaf) == root_port_link)
+ __pcie_aspm_config_link(leaf->pdev, state);
+ }
+ } else {
+ list_for_each_entry_reverse(leaf, &link_list, sibiling) {
+ if (get_root_port_link(leaf) == root_port_link)
+ __pcie_aspm_config_link(leaf->pdev, state);
+ }
+ }
}
/*
@@ -570,6 +631,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
unsigned int state;
struct pcie_link_state *link_state;
int error = 0;
+ int blacklist;
if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
return;
@@ -580,29 +642,58 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
if (list_empty(&pdev->subordinate->devices))
goto out;
- if (pcie_aspm_sanity_check(pdev))
- goto out;
+ blacklist = !!pcie_aspm_sanity_check(pdev);
mutex_lock(&aspm_lock);
link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
if (!link_state)
goto unlock_out;
- pdev->link_state = link_state;
- pcie_aspm_configure_common_clock(pdev);
+ link_state->downstream_has_switch = pcie_aspm_downstream_has_switch(pdev);
+ INIT_LIST_HEAD(&link_state->children);
+ INIT_LIST_HEAD(&link_state->link);
+ if (pdev->bus->self) {/* this is a switch */
+ struct pcie_link_state *parent_link_state;
- pcie_aspm_cap_init(pdev);
+ parent_link_state = pdev->bus->parent->self->link_state;
+ if (!parent_link_state) {
+ kfree(link_state);
+ goto unlock_out;
+ }
+ list_add(&link_state->link, &parent_link_state->children);
+ link_state->parent = parent_link_state;
+ }
- /* config link state to avoid BIOS error */
- state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
- __pcie_aspm_config_link(pdev, state);
+ pdev->link_state = link_state;
- pcie_check_clock_pm(pdev);
+ if (!blacklist) {
+ pcie_aspm_configure_common_clock(pdev);
+ pcie_aspm_cap_init(pdev);
+ } else {
+ link_state->enabled_state = PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+ link_state->bios_aspm_state = 0;
+ /* Set support state to 0, so we will disable ASPM later */
+ link_state->support_state = 0;
+ }
link_state->pdev = pdev;
list_add(&link_state->sibiling, &link_list);
+ if (link_state->downstream_has_switch) {
+ /*
+ * If link has switch, delay the link config. The leaf link
+ * initialization will config the whole hierarchy. but we must
+ * make sure BIOS doesn't set unsupported link state
+ **/
+ state = pcie_aspm_check_state(pdev, link_state->bios_aspm_state);
+ __pcie_aspm_config_link(pdev, state);
+ } else
+ __pcie_aspm_configure_link_state(pdev,
+ policy_to_aspm_state(pdev));
+
+ pcie_check_clock_pm(pdev, blacklist);
+
unlock_out:
if (error)
free_link_state(pdev);
@@ -635,6 +726,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
/* All functions are removed, so just disable ASPM for the link */
__pcie_aspm_config_one_dev(parent, 0);
list_del(&link_state->sibiling);
+ list_del(&link_state->link);
/* Clock PM is for endpoint device */
free_link_state(parent);
@@ -857,24 +949,15 @@ void pcie_no_aspm(void)
aspm_disabled = 1;
}
-#ifdef CONFIG_ACPI
-#include <acpi/acpi_bus.h>
-#include <linux/pci-acpi.h>
-static void pcie_aspm_platform_init(void)
-{
- pcie_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
- OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
-}
-#else
-static inline void pcie_aspm_platform_init(void) { }
-#endif
-
-static int __init pcie_aspm_init(void)
+/**
+ * pcie_aspm_enabled - is PCIe ASPM enabled?
+ *
+ * Returns true if ASPM has not been disabled by the command-line option
+ * pcie_aspm=off.
+ **/
+int pcie_aspm_enabled(void)
{
- if (aspm_disabled)
- return 0;
- pcie_aspm_platform_init();
- return 0;
+ return !aspm_disabled;
}
+EXPORT_SYMBOL(pcie_aspm_enabled);
-fs_initcall(pcie_aspm_init);
diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c
index 359fe5568df1..eec89b767f9f 100644
--- a/drivers/pci/pcie/portdrv_bus.c
+++ b/drivers/pci/pcie/portdrv_bus.c
@@ -16,14 +16,10 @@
#include "portdrv.h"
static int pcie_port_bus_match(struct device *dev, struct device_driver *drv);
-static int pcie_port_bus_suspend(struct device *dev, pm_message_t state);
-static int pcie_port_bus_resume(struct device *dev);
struct bus_type pcie_port_bus_type = {
.name = "pci_express",
.match = pcie_port_bus_match,
- .suspend = pcie_port_bus_suspend,
- .resume = pcie_port_bus_resume,
};
EXPORT_SYMBOL_GPL(pcie_port_bus_type);
@@ -49,32 +45,12 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
return 1;
}
-static int pcie_port_bus_suspend(struct device *dev, pm_message_t state)
+int pcie_port_bus_register(void)
{
- struct pcie_device *pciedev;
- struct pcie_port_service_driver *driver;
-
- if (!dev || !dev->driver)
- return 0;
-
- pciedev = to_pcie_device(dev);
- driver = to_service_driver(dev->driver);
- if (driver && driver->suspend)
- driver->suspend(pciedev, state);
- return 0;
+ return bus_register(&pcie_port_bus_type);
}
-static int pcie_port_bus_resume(struct device *dev)
+void pcie_port_bus_unregister(void)
{
- struct pcie_device *pciedev;
- struct pcie_port_service_driver *driver;
-
- if (!dev || !dev->driver)
- return 0;
-
- pciedev = to_pcie_device(dev);
- driver = to_service_driver(dev->driver);
- if (driver && driver->resume)
- driver->resume(pciedev);
- return 0;
+ bus_unregister(&pcie_port_bus_type);
}
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 2e091e014829..8b3f8c18032f 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -19,91 +19,15 @@
extern int pcie_mch_quirk; /* MSI-quirk Indicator */
-static int pcie_port_probe_service(struct device *dev)
-{
- struct pcie_device *pciedev;
- struct pcie_port_service_driver *driver;
- int status;
-
- if (!dev || !dev->driver)
- return -ENODEV;
-
- driver = to_service_driver(dev->driver);
- if (!driver || !driver->probe)
- return -ENODEV;
-
- pciedev = to_pcie_device(dev);
- status = driver->probe(pciedev, driver->id_table);
- if (!status) {
- dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n",
- driver->name);
- get_device(dev);
- }
- return status;
-}
-
-static int pcie_port_remove_service(struct device *dev)
-{
- struct pcie_device *pciedev;
- struct pcie_port_service_driver *driver;
-
- if (!dev || !dev->driver)
- return 0;
-
- pciedev = to_pcie_device(dev);
- driver = to_service_driver(dev->driver);
- if (driver && driver->remove) {
- dev_printk(KERN_DEBUG, dev, "unloading service driver %s\n",
- driver->name);
- driver->remove(pciedev);
- put_device(dev);
- }
- return 0;
-}
-
-static void pcie_port_shutdown_service(struct device *dev) {}
-
-static int pcie_port_suspend_service(struct device *dev, pm_message_t state)
-{
- struct pcie_device *pciedev;
- struct pcie_port_service_driver *driver;
-
- if (!dev || !dev->driver)
- return 0;
-
- pciedev = to_pcie_device(dev);
- driver = to_service_driver(dev->driver);
- if (driver && driver->suspend)
- driver->suspend(pciedev, state);
- return 0;
-}
-
-static int pcie_port_resume_service(struct device *dev)
-{
- struct pcie_device *pciedev;
- struct pcie_port_service_driver *driver;
-
- if (!dev || !dev->driver)
- return 0;
-
- pciedev = to_pcie_device(dev);
- driver = to_service_driver(dev->driver);
-
- if (driver && driver->resume)
- driver->resume(pciedev);
- return 0;
-}
-
-/*
- * release_pcie_device
- *
- * Being invoked automatically when device is being removed
- * in response to device_unregister(dev) call.
- * Release all resources being claimed.
+/**
+ * release_pcie_device - free PCI Express port service device structure
+ * @dev: Port service device to release
+ *
+ * Invoked automatically when device is being removed in response to
+ * device_unregister(dev). Release all resources being claimed.
*/
static void release_pcie_device(struct device *dev)
{
- dev_printk(KERN_DEBUG, dev, "free port service\n");
kfree(to_pcie_device(dev));
}
@@ -128,7 +52,16 @@ static int is_msi_quirked(struct pci_dev *dev)
}
return quirk;
}
-
+
+/**
+ * assign_interrupt_mode - choose interrupt mode for PCI Express port services
+ * (INTx, MSI-X, MSI) and set up vectors
+ * @dev: PCI Express port to handle
+ * @vectors: Array of interrupt vectors to populate
+ * @mask: Bitmask of port capabilities returned by get_port_device_capability()
+ *
+ * Return value: Interrupt mode associated with the port
+ */
static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
{
int i, pos, nvec, status = -EINVAL;
@@ -150,7 +83,6 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
if (pos) {
struct msix_entry msix_entries[PCIE_PORT_DEVICE_MAXSERVICES] =
{{0, 0}, {0, 1}, {0, 2}, {0, 3}};
- dev_info(&dev->dev, "found MSI-X capability\n");
status = pci_enable_msix(dev, msix_entries, nvec);
if (!status) {
int j = 0;
@@ -165,7 +97,6 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
if (status) {
pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
if (pos) {
- dev_info(&dev->dev, "found MSI capability\n");
status = pci_enable_msi(dev);
if (!status) {
interrupt_mode = PCIE_PORT_MSI_MODE;
@@ -177,6 +108,16 @@ static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
return interrupt_mode;
}
+/**
+ * get_port_device_capability - discover capabilities of a PCI Express port
+ * @dev: PCI Express port to examine
+ *
+ * The capabilities are read from the port's PCI Express configuration registers
+ * as described in PCI Express Base Specification 1.0a sections 7.8.2, 7.8.9 and
+ * 7.9 - 7.11.
+ *
+ * Return value: Bitmask of discovered port capabilities
+ */
static int get_port_device_capability(struct pci_dev *dev)
{
int services = 0, pos;
@@ -204,6 +145,15 @@ static int get_port_device_capability(struct pci_dev *dev)
return services;
}
+/**
+ * pcie_device_init - initialize PCI Express port service device
+ * @dev: Port service device to initialize
+ * @parent: PCI Express port to associate the service device with
+ * @port_type: Type of the port
+ * @service_type: Type of service to associate with the service device
+ * @irq: Interrupt vector to associate with the service device
+ * @irq_mode: Interrupt mode of the service (INTx, MSI-X, MSI)
+ */
static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
int port_type, int service_type, int irq, int irq_mode)
{
@@ -224,11 +174,19 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
device->driver = NULL;
device->driver_data = NULL;
device->release = release_pcie_device; /* callback to free pcie dev */
- snprintf(device->bus_id, sizeof(device->bus_id), "%s:pcie%02x",
+ dev_set_name(device, "%s:pcie%02x",
pci_name(parent), get_descriptor_id(port_type, service_type));
device->parent = &parent->dev;
}
+/**
+ * alloc_pcie_device - allocate PCI Express port service device structure
+ * @parent: PCI Express port to associate the service device with
+ * @port_type: Type of the port
+ * @service_type: Type of service to associate with the service device
+ * @irq: Interrupt vector to associate with the service device
+ * @irq_mode: Interrupt mode of the service (INTx, MSI-X, MSI)
+ */
static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
int port_type, int service_type, int irq, int irq_mode)
{
@@ -239,10 +197,13 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
return NULL;
pcie_device_init(parent, device, port_type, service_type, irq,irq_mode);
- dev_printk(KERN_DEBUG, &device->device, "allocate port service\n");
return device;
}
+/**
+ * pcie_port_device_probe - check if device is a PCI Express port
+ * @dev: Device to check
+ */
int pcie_port_device_probe(struct pci_dev *dev)
{
int pos, type;
@@ -260,6 +221,13 @@ int pcie_port_device_probe(struct pci_dev *dev)
return -ENODEV;
}
+/**
+ * pcie_port_device_register - register PCI Express port
+ * @dev: PCI Express port to register
+ *
+ * Allocate the port extension structure and register services associated with
+ * the port.
+ */
int pcie_port_device_register(struct pci_dev *dev)
{
struct pcie_port_device_ext *p_ext;
@@ -323,6 +291,11 @@ static int suspend_iter(struct device *dev, void *data)
return 0;
}
+/**
+ * pcie_port_device_suspend - suspend port services associated with a PCIe port
+ * @dev: PCI Express port to handle
+ * @state: Representation of system power management transition in progress
+ */
int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
{
return device_for_each_child(&dev->dev, &state, suspend_iter);
@@ -341,6 +314,10 @@ static int resume_iter(struct device *dev, void *data)
return 0;
}
+/**
+ * pcie_port_device_suspend - resume port services associated with a PCIe port
+ * @dev: PCI Express port to handle
+ */
int pcie_port_device_resume(struct pci_dev *dev)
{
return device_for_each_child(&dev->dev, NULL, resume_iter);
@@ -363,6 +340,13 @@ static int remove_iter(struct device *dev, void *data)
return 0;
}
+/**
+ * pcie_port_device_remove - unregister PCI Express port service devices
+ * @dev: PCI Express port the service devices to unregister are associated with
+ *
+ * Remove PCI Express port service devices associated with given port and
+ * disable MSI-X or MSI for the port.
+ */
void pcie_port_device_remove(struct pci_dev *dev)
{
struct device *device;
@@ -386,16 +370,80 @@ void pcie_port_device_remove(struct pci_dev *dev)
pci_disable_msi(dev);
}
-int pcie_port_bus_register(void)
+/**
+ * pcie_port_probe_service - probe driver for given PCI Express port service
+ * @dev: PCI Express port service device to probe against
+ *
+ * If PCI Express port service driver is registered with
+ * pcie_port_service_register(), this function will be called by the driver core
+ * whenever match is found between the driver and a port service device.
+ */
+static int pcie_port_probe_service(struct device *dev)
{
- return bus_register(&pcie_port_bus_type);
+ struct pcie_device *pciedev;
+ struct pcie_port_service_driver *driver;
+ int status;
+
+ if (!dev || !dev->driver)
+ return -ENODEV;
+
+ driver = to_service_driver(dev->driver);
+ if (!driver || !driver->probe)
+ return -ENODEV;
+
+ pciedev = to_pcie_device(dev);
+ status = driver->probe(pciedev, driver->id_table);
+ if (!status) {
+ dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n",
+ driver->name);
+ get_device(dev);
+ }
+ return status;
}
-void pcie_port_bus_unregister(void)
+/**
+ * pcie_port_remove_service - detach driver from given PCI Express port service
+ * @dev: PCI Express port service device to handle
+ *
+ * If PCI Express port service driver is registered with
+ * pcie_port_service_register(), this function will be called by the driver core
+ * when device_unregister() is called for the port service device associated
+ * with the driver.
+ */
+static int pcie_port_remove_service(struct device *dev)
{
- bus_unregister(&pcie_port_bus_type);
+ struct pcie_device *pciedev;
+ struct pcie_port_service_driver *driver;
+
+ if (!dev || !dev->driver)
+ return 0;
+
+ pciedev = to_pcie_device(dev);
+ driver = to_service_driver(dev->driver);
+ if (driver && driver->remove) {
+ dev_printk(KERN_DEBUG, dev, "unloading service driver %s\n",
+ driver->name);
+ driver->remove(pciedev);
+ put_device(dev);
+ }
+ return 0;
}
+/**
+ * pcie_port_shutdown_service - shut down given PCI Express port service
+ * @dev: PCI Express port service device to handle
+ *
+ * If PCI Express port service driver is registered with
+ * pcie_port_service_register(), this function will be called by the driver core
+ * when device_shutdown() is called for the port service device associated
+ * with the driver.
+ */
+static void pcie_port_shutdown_service(struct device *dev) {}
+
+/**
+ * pcie_port_service_register - register PCI Express port service driver
+ * @new: PCI Express port service driver to register
+ */
int pcie_port_service_register(struct pcie_port_service_driver *new)
{
new->driver.name = (char *)new->name;
@@ -403,15 +451,17 @@ int pcie_port_service_register(struct pcie_port_service_driver *new)
new->driver.probe = pcie_port_probe_service;
new->driver.remove = pcie_port_remove_service;
new->driver.shutdown = pcie_port_shutdown_service;
- new->driver.suspend = pcie_port_suspend_service;
- new->driver.resume = pcie_port_resume_service;
return driver_register(&new->driver);
}
-void pcie_port_service_unregister(struct pcie_port_service_driver *new)
+/**
+ * pcie_port_service_unregister - unregister PCI Express port service driver
+ * @drv: PCI Express port service driver to unregister
+ */
+void pcie_port_service_unregister(struct pcie_port_service_driver *drv)
{
- driver_unregister(&new->driver);
+ driver_unregister(&drv->driver);
}
EXPORT_SYMBOL(pcie_port_service_register);
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 584422da8d8b..99a914a027f8 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -41,7 +41,6 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
{
int retval;
- pci_restore_state(dev);
retval = pci_enable_device(dev);
if (retval)
return retval;
@@ -52,11 +51,18 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev)
#ifdef CONFIG_PM
static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
{
- int ret = pcie_port_device_suspend(dev, state);
+ return pcie_port_device_suspend(dev, state);
- if (!ret)
- ret = pcie_portdrv_save_config(dev);
- return ret;
+}
+
+static int pcie_portdrv_suspend_late(struct pci_dev *dev, pm_message_t state)
+{
+ return pci_save_state(dev);
+}
+
+static int pcie_portdrv_resume_early(struct pci_dev *dev)
+{
+ return pci_restore_state(dev);
}
static int pcie_portdrv_resume(struct pci_dev *dev)
@@ -66,6 +72,8 @@ static int pcie_portdrv_resume(struct pci_dev *dev)
}
#else
#define pcie_portdrv_suspend NULL
+#define pcie_portdrv_suspend_late NULL
+#define pcie_portdrv_resume_early NULL
#define pcie_portdrv_resume NULL
#endif
@@ -221,6 +229,7 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
/* If fatal, restore cfg space for possible link reset at upstream */
if (dev->error_state == pci_channel_io_frozen) {
+ pci_restore_state(dev);
pcie_portdrv_restore_config(dev);
pci_enable_pcie_error_reporting(dev);
}
@@ -283,6 +292,8 @@ static struct pci_driver pcie_portdriver = {
.remove = pcie_portdrv_remove,
.suspend = pcie_portdrv_suspend,
+ .suspend_late = pcie_portdrv_suspend_late,
+ .resume_early = pcie_portdrv_resume_early,
.resume = pcie_portdrv_resume,
.err_handler = &pcie_portdrv_err_handler,
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 003a9b3c293f..55ec44a27e89 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -51,11 +51,11 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
char *buf)
{
int ret;
- cpumask_t cpumask;
+ const struct cpumask *cpumask;
- cpumask = pcibus_to_cpumask(to_pci_bus(dev));
+ cpumask = cpumask_of_pcibus(to_pci_bus(dev));
ret = type?
- cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask):
+ cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask) :
cpumask_scnprintf(buf, PAGE_SIZE-2, cpumask);
buf[ret++] = '\n';
buf[ret] = '\0';
@@ -135,13 +135,6 @@ static u64 pci_size(u64 base, u64 maxbase, u64 mask)
return size;
}
-enum pci_bar_type {
- pci_bar_unknown, /* Standard PCI BAR probe */
- pci_bar_io, /* An io port BAR */
- pci_bar_mem32, /* A 32-bit memory BAR */
- pci_bar_mem64, /* A 64-bit memory BAR */
-};
-
static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
{
if ((bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
@@ -156,11 +149,16 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
return pci_bar_mem32;
}
-/*
- * If the type is not unknown, we assume that the lowest bit is 'enable'.
- * Returns 1 if the BAR was 64-bit and 0 if it was 32-bit.
+/**
+ * pci_read_base - read a PCI BAR
+ * @dev: the PCI device
+ * @type: type of the BAR
+ * @res: resource buffer to be filled in
+ * @pos: BAR position in the config space
+ *
+ * Returns 1 if the BAR is 64-bit, or 0 if 32-bit.
*/
-static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
+int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
struct resource *res, unsigned int pos)
{
u32 l, sz, mask;
@@ -400,19 +398,17 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
if (!child)
return NULL;
- child->self = bridge;
child->parent = parent;
child->ops = parent->ops;
child->sysdata = parent->sysdata;
child->bus_flags = parent->bus_flags;
- child->bridge = get_device(&bridge->dev);
/* initialize some portions of the bus device, but don't register it
* now as the parent is not properly set up yet. This device will get
* registered later in pci_bus_add_devices()
*/
child->dev.class = &pcibus_class;
- sprintf(child->dev.bus_id, "%04x:%02x", pci_domain_nr(child), busnr);
+ dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr);
/*
* Set up the primary, secondary and subordinate
@@ -422,8 +418,14 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
child->primary = parent->secondary;
child->subordinate = 0xff;
+ if (!bridge)
+ return child;
+
+ child->self = bridge;
+ child->bridge = get_device(&bridge->dev);
+
/* Set up default resource pointers and names.. */
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i];
child->resource[i]->name = child->name;
}
@@ -958,8 +960,12 @@ static void pci_init_capabilities(struct pci_dev *dev)
/* MSI/MSI-X list */
pci_msi_init_pci_dev(dev);
+ /* Buffers for saving PCIe and PCI-X capabilities */
+ pci_allocate_cap_save_buffers(dev);
+
/* Power Management */
pci_pm_init(dev);
+ platform_pci_wakeup_init(dev);
/* Vital Product Data */
pci_vpd_pci22_init(dev);
@@ -1130,7 +1136,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
memset(dev, 0, sizeof(*dev));
dev->parent = parent;
dev->release = pci_release_bus_bridge_dev;
- sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus);
+ dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus);
error = device_register(dev);
if (error)
goto dev_reg_err;
@@ -1141,7 +1147,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
b->dev.class = &pcibus_class;
b->dev.parent = b->bridge;
- sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
+ dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), bus);
error = device_register(&b->dev);
if (error)
goto class_dev_reg_err;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index e1098c302c45..593bb844b8db 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -252,11 +252,20 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
const struct proc_dir_entry *dp = PDE(inode);
struct pci_dev *dev = dp->data;
struct pci_filp_private *fpriv = file->private_data;
- int ret;
+ int i, ret;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
+ /* Make sure the caller is mapping a real resource for this device */
+ for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+ if (pci_mmap_fits(dev, i, vma))
+ break;
+ }
+
+ if (i >= PCI_ROM_RESOURCE)
+ return -ENODEV;
+
ret = pci_mmap_page_range(dev, vma,
fpriv->mmap_state,
fpriv->write_combine);
@@ -352,15 +361,16 @@ static int show_device(struct seq_file *m, void *v)
dev->vendor,
dev->device,
dev->irq);
- /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
- for (i=0; i<7; i++) {
+
+ /* only print standard and ROM resources to preserve compatibility */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
resource_size_t start, end;
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
seq_printf(m, "\t%16llx",
(unsigned long long)(start |
(dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
}
- for (i=0; i<7; i++) {
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
resource_size_t start, end;
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
seq_printf(m, "\t%16llx",
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index ce0985615133..baad093aafe3 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -56,7 +56,7 @@ static void quirk_passive_release(struct pci_dev *dev)
while ((d = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
pci_read_config_byte(d, 0x82, &dlc);
if (!(dlc & 1<<1)) {
- dev_err(&d->dev, "PIIX3: Enabling Passive Release\n");
+ dev_info(&d->dev, "PIIX3: Enabling Passive Release\n");
dlc |= 1<<1;
pci_write_config_byte(d, 0x82, dlc);
}
@@ -449,7 +449,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi);
-static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
+static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
{
u32 region;
@@ -459,20 +459,95 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
pci_read_config_dword(dev, 0x48, &region);
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich6_lpc_acpi);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich6_lpc_acpi);
+
+static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
+{
+ u32 val;
+ u32 size, base;
+
+ pci_read_config_dword(dev, reg, &val);
+
+ /* Enabled? */
+ if (!(val & 1))
+ return;
+ base = val & 0xfffc;
+ if (dynsize) {
+ /*
+ * This is not correct. It is 16, 32 or 64 bytes depending on
+ * register D31:F0:ADh bits 5:4.
+ *
+ * But this gets us at least _part_ of it.
+ */
+ size = 16;
+ } else {
+ size = 128;
+ }
+ base &= ~(size-1);
+
+ /* Just print it out for now. We should reserve it after more debugging */
+ dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base+size-1);
+}
+
+static void __devinit quirk_ich6_lpc(struct pci_dev *dev)
+{
+ /* Shared ACPI/GPIO decode with all ICH6+ */
+ ich6_lpc_acpi_gpio(dev);
+
+ /* ICH6-specific generic IO decode */
+ ich6_lpc_generic_decode(dev, 0x84, "LPC Generic IO decode 1", 0);
+ ich6_lpc_generic_decode(dev, 0x88, "LPC Generic IO decode 2", 1);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc);
+
+static void __devinit ich7_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name)
+{
+ u32 val;
+ u32 mask, base;
+
+ pci_read_config_dword(dev, reg, &val);
+
+ /* Enabled? */
+ if (!(val & 1))
+ return;
+
+ /*
+ * IO base in bits 15:2, mask in bits 23:18, both
+ * are dword-based
+ */
+ base = val & 0xfffc;
+ mask = (val >> 16) & 0xfc;
+ mask |= 3;
+
+ /* Just print it out for now. We should reserve it after more debugging */
+ dev_info(&dev->dev, "%s PIO at %04x (mask %04x)\n", name, base, mask);
+}
+
+/* ICH7-10 has the same common LPC generic IO decode registers */
+static void __devinit quirk_ich7_lpc(struct pci_dev *dev)
+{
+ /* We share the common ACPI/DPIO decode with ICH6 */
+ ich6_lpc_acpi_gpio(dev);
+
+ /* And have 4 ICH7+ generic decodes */
+ ich7_lpc_generic_decode(dev, 0x84, "ICH7 LPC Generic IO decode 1");
+ ich7_lpc_generic_decode(dev, 0x88, "ICH7 LPC Generic IO decode 2");
+ ich7_lpc_generic_decode(dev, 0x8c, "ICH7 LPC Generic IO decode 3");
+ ich7_lpc_generic_decode(dev, 0x90, "ICH7 LPC Generic IO decode 4");
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich7_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_1, quirk_ich7_lpc);
/*
* VIA ACPI: One IO region pointed to by longword at
@@ -2074,11 +2149,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
#endif /* CONFIG_PCI_MSI */
-static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
+static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
+ struct pci_fixup *end)
{
while (f < end) {
if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
- (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
+ (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
dev_dbg(&dev->dev, "calling %pF\n", f->hook);
f->hook(dev);
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index ea979f2bc6db..704608945780 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -536,9 +536,8 @@ static void pci_bus_dump_res(struct pci_bus *bus)
if (!res)
continue;
- printk(KERN_INFO "bus: %02x index %x %s: %pR\n",
- bus->number, i,
- (res->flags & IORESOURCE_IO) ? "io port" : "mmio", res);
+ dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i,
+ (res->flags & IORESOURCE_IO) ? "io: " : "mem:", res);
}
}
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 2dbd96cce2d8..32e8d88a4619 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -26,11 +26,13 @@
#include "pci.h"
-void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
+void pci_update_resource(struct pci_dev *dev, int resno)
{
struct pci_bus_region region;
u32 new, check, mask;
int reg;
+ enum pci_bar_type type;
+ struct resource *res = dev->resource + resno;
/*
* Ignore resources for unimplemented BARs and unused resource slots
@@ -61,17 +63,13 @@ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
else
mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
- if (resno < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4 * resno;
- } else if (resno == PCI_ROM_RESOURCE) {
+ reg = pci_resource_bar(dev, resno, &type);
+ if (!reg)
+ return;
+ if (type != pci_bar_unknown) {
if (!(res->flags & IORESOURCE_ROM_ENABLE))
return;
new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Hmm, non-standard resource. */
-
- return; /* kill uninitialised var warning */
}
pci_write_config_dword(dev, reg, new);
@@ -134,7 +132,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
align = resource_alignment(res);
if (!align) {
- dev_err(&dev->dev, "BAR %d: can't allocate resource (bogus "
+ dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
"alignment) %pR flags %#lx\n",
resno, res, res->flags);
return -EINVAL;
@@ -157,12 +155,12 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
}
if (ret) {
- dev_err(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
+ dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
} else {
res->flags &= ~IORESOURCE_STARTALIGN;
if (resno < PCI_BRIDGE_RESOURCES)
- pci_update_resource(dev, res, resno);
+ pci_update_resource(dev, resno);
}
return ret;
@@ -197,7 +195,7 @@ int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
dev_err(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
} else if (resno < PCI_BRIDGE_RESOURCES) {
- pci_update_resource(dev, res, resno);
+ pci_update_resource(dev, resno);
}
return ret;
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 645d7a60e412..ec22284eed30 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -14,10 +14,8 @@
#include <asm/uaccess.h>
#include "pci.h"
-asmlinkage long
-sys_pciconfig_read(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- void __user *buf)
+SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn,
+ unsigned long, off, unsigned long, len, void __user *, buf)
{
struct pci_dev *dev;
u8 byte;
@@ -86,10 +84,8 @@ error:
return err;
}
-asmlinkage long
-sys_pciconfig_write(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- void __user *buf)
+SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
+ unsigned long, off, unsigned long, len, void __user *, buf)
{
struct pci_dev *dev;
u8 byte;
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index a34284b1482a..d187ba4c5e0e 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -297,7 +297,7 @@ static int __devinit electra_cf_probe(struct of_device *ofdev,
goto fail3;
}
- dev_info(device, "at mem 0x%lx io 0x%lx irq %d\n",
+ dev_info(device, "at mem 0x%lx io 0x%llx irq %d\n",
cf->mem_phys, io.start, cf->irq);
cf->active = 1;
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
new file mode 100644
index 000000000000..9652c3fe7f5e
--- /dev/null
+++ b/drivers/platform/Kconfig
@@ -0,0 +1,5 @@
+# drivers/platform/Kconfig
+
+if X86
+source "drivers/platform/x86/Kconfig"
+endif
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
new file mode 100644
index 000000000000..782953ae4c03
--- /dev/null
+++ b/drivers/platform/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for linux/drivers/platform
+#
+
+obj-$(CONFIG_X86) += x86/
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
new file mode 100644
index 000000000000..1a266d4ab5f1
--- /dev/null
+++ b/drivers/platform/x86/Kconfig
@@ -0,0 +1,398 @@
+#
+# X86 Platform Specific Drivers
+#
+
+menuconfig X86_PLATFORM_DEVICES
+ bool "X86 Platform Specific Device Drivers"
+ default y
+ ---help---
+ Say Y here to get to see options for device drivers for various
+ x86 platforms, including vendor-specific laptop extension drivers.
+ This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and disabled.
+
+if X86_PLATFORM_DEVICES
+
+config ACER_WMI
+ tristate "Acer WMI Laptop Extras (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ depends on ACPI
+ depends on LEDS_CLASS
+ depends on NEW_LEDS
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on SERIO_I8042
+ depends on RFKILL
+ select ACPI_WMI
+ ---help---
+ This is a driver for newer Acer (and Wistron) laptops. It adds
+ wireless radio and bluetooth control, and on some laptops,
+ exposes the mail LED and LCD backlight.
+
+ For more information about this driver see
+ <file:Documentation/laptops/acer-wmi.txt>
+
+ If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
+ here.
+
+config ASUS_LAPTOP
+ tristate "Asus Laptop Extras (EXPERIMENTAL)"
+ depends on ACPI
+ depends on EXPERIMENTAL && !ACPI_ASUS
+ depends on LEDS_CLASS
+ depends on NEW_LEDS
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This is the new Linux driver for Asus laptops. It may also support some
+ MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
+ standard ACPI events that go through /proc/acpi/events. It also adds
+ support for video output switching, LCD backlight control, Bluetooth and
+ Wlan control, and most importantly, allows you to blink those fancy LEDs.
+
+ For more information and a userspace daemon for handling the extra
+ buttons see <http://acpi4asus.sf.net/>.
+
+ If you have an ACPI-compatible ASUS laptop, say Y or M here.
+
+config DELL_LAPTOP
+ tristate "Dell Laptop Extras (EXPERIMENTAL)"
+ depends on X86
+ depends on DCDBAS
+ depends on EXPERIMENTAL
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on RFKILL
+ default n
+ ---help---
+ This driver adds support for rfkill and backlight control to Dell
+ laptops.
+
+config FUJITSU_LAPTOP
+ tristate "Fujitsu Laptop Extras"
+ depends on ACPI
+ depends on INPUT
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This is a driver for laptops built by Fujitsu:
+
+ * P2xxx/P5xxx/S6xxx/S7xxx series Lifebooks
+ * Possibly other Fujitsu laptop models
+ * Tested with S6410 and S7020
+
+ It adds support for LCD brightness control and some hotkeys.
+
+ If you have a Fujitsu laptop, say Y or M here.
+
+config FUJITSU_LAPTOP_DEBUG
+ bool "Verbose debug mode for Fujitsu Laptop Extras"
+ depends on FUJITSU_LAPTOP
+ default n
+ ---help---
+ Enables extra debug output from the fujitsu extras driver, at the
+ expense of a slight increase in driver size.
+
+ If you are not sure, say N here.
+
+config TC1100_WMI
+ tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
+ depends on !X86_64
+ depends on EXPERIMENTAL
+ depends on ACPI
+ select ACPI_WMI
+ ---help---
+ This is a driver for the WMI extensions (wireless and bluetooth power
+ control) of the HP Compaq TC1100 tablet.
+
+config HP_WMI
+ tristate "HP WMI extras"
+ depends on ACPI_WMI
+ depends on INPUT
+ depends on RFKILL
+ help
+ Say Y here if you want to support WMI-based hotkeys on HP laptops and
+ to read data from WMI such as docking or ambient light sensor state.
+
+ To compile this driver as a module, choose M here: the module will
+ be called hp-wmi.
+
+config MSI_LAPTOP
+ tristate "MSI Laptop Extras"
+ depends on ACPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This is a driver for laptops built by MSI (MICRO-STAR
+ INTERNATIONAL):
+
+ MSI MegaBook S270 (MS-1013)
+ Cytron/TCM/Medion/Tchibo MD96100/SAM2000
+
+ It adds support for Bluetooth, WLAN and LCD brightness control.
+
+ More information about this driver is available at
+ <http://0pointer.de/lennart/tchibo.html>.
+
+ If you have an MSI S270 laptop, say Y or M here.
+
+config PANASONIC_LAPTOP
+ tristate "Panasonic Laptop Extras"
+ depends on INPUT && ACPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This driver adds support for access to backlight control and hotkeys
+ on Panasonic Let's Note laptops.
+
+ If you have a Panasonic Let's note laptop (such as the R1(N variant),
+ R2, R3, R5, T2, W2 and Y2 series), say Y.
+
+config COMPAL_LAPTOP
+ tristate "Compal Laptop Extras"
+ depends on ACPI
+ depends on BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This is a driver for laptops built by Compal:
+
+ Compal FL90/IFL90
+ Compal FL91/IFL91
+ Compal FL92/JFL92
+ Compal FT00/IFT00
+
+ It adds support for Bluetooth, WLAN and LCD brightness control.
+
+ If you have an Compal FL9x/IFL9x/FT00 laptop, say Y or M here.
+
+config SONY_LAPTOP
+ tristate "Sony Laptop Extras"
+ depends on ACPI
+ select BACKLIGHT_CLASS_DEVICE
+ depends on INPUT
+ ---help---
+ This mini-driver drives the SNC and SPIC devices present in the ACPI
+ BIOS of the Sony Vaio laptops.
+
+ It gives access to some extra laptop functionalities like Bluetooth,
+ screen brightness control, Fn keys and allows powering on/off some
+ devices.
+
+ Read <file:Documentation/laptops/sony-laptop.txt> for more information.
+
+config SONYPI_COMPAT
+ bool "Sonypi compatibility"
+ depends on SONY_LAPTOP
+ ---help---
+ Build the sonypi driver compatibility code into the sony-laptop driver.
+
+config THINKPAD_ACPI
+ tristate "ThinkPad ACPI Laptop Extras"
+ depends on ACPI
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ select HWMON
+ select NVRAM
+ select INPUT
+ select NEW_LEDS
+ select LEDS_CLASS
+ select NET
+ select RFKILL
+ ---help---
+ This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
+ support for Fn-Fx key combinations, Bluetooth control, video
+ output switching, ThinkLight control, UltraBay eject and more.
+ For more information about this driver see
+ <file:Documentation/laptops/thinkpad-acpi.txt> and
+ <http://ibm-acpi.sf.net/> .
+
+ This driver was formerly known as ibm-acpi.
+
+ If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
+
+config THINKPAD_ACPI_DEBUGFACILITIES
+ bool "Maintainer debug facilities"
+ depends on THINKPAD_ACPI
+ default n
+ ---help---
+ Enables extra stuff in the thinkpad-acpi which is completely useless
+ for normal use. Read the driver source to find out what it does.
+
+ Say N here, unless you were told by a kernel maintainer to do
+ otherwise.
+
+config THINKPAD_ACPI_DEBUG
+ bool "Verbose debug mode"
+ depends on THINKPAD_ACPI
+ default n
+ ---help---
+ Enables extra debugging information, at the expense of a slightly
+ increase in driver size.
+
+ If you are not sure, say N here.
+
+config THINKPAD_ACPI_DOCK
+ bool "Legacy Docking Station Support"
+ depends on THINKPAD_ACPI
+ depends on ACPI_DOCK=n
+ default n
+ ---help---
+ Allows the thinkpad_acpi driver to handle docking station events.
+ This support was made obsolete by the generic ACPI docking station
+ support (CONFIG_ACPI_DOCK). It will allow locking and removing the
+ laptop from the docking station, but will not properly connect PCI
+ devices.
+
+ If you are not sure, say N here.
+
+config THINKPAD_ACPI_BAY
+ bool "Legacy Removable Bay Support"
+ depends on THINKPAD_ACPI
+ default y
+ ---help---
+ Allows the thinkpad_acpi driver to handle removable bays. It will
+ electrically disable the device in the bay, and also generate
+ notifications when the bay lever is ejected or inserted.
+
+ If you are not sure, say Y here.
+
+config THINKPAD_ACPI_VIDEO
+ bool "Video output control support"
+ depends on THINKPAD_ACPI
+ default y
+ ---help---
+ Allows the thinkpad_acpi driver to provide an interface to control
+ the various video output ports.
+
+ This feature often won't work well, depending on ThinkPad model,
+ display state, video output devices in use, whether there is a X
+ server running, phase of the moon, and the current mood of
+ Schroedinger's cat. If you can use X.org's RandR to control
+ your ThinkPad's video output ports instead of this feature,
+ don't think twice: do it and say N here to save some memory.
+
+ If you are not sure, say Y here.
+
+config THINKPAD_ACPI_HOTKEY_POLL
+ bool "Support NVRAM polling for hot keys"
+ depends on THINKPAD_ACPI
+ default y
+ ---help---
+ Some thinkpad models benefit from NVRAM polling to detect a few of
+ the hot key press events. If you know your ThinkPad model does not
+ need to do NVRAM polling to support any of the hot keys you use,
+ unselecting this option will save about 1kB of memory.
+
+ ThinkPads T40 and newer, R52 and newer, and X31 and newer are
+ unlikely to need NVRAM polling in their latest BIOS versions.
+
+ NVRAM polling can detect at most the following keys: ThinkPad/Access
+ IBM, Zoom, Switch Display (fn+F7), ThinkLight, Volume up/down/mute,
+ Brightness up/down, Display Expand (fn+F8), Hibernate (fn+F12).
+
+ If you are not sure, say Y here. The driver enables polling only if
+ it is strictly necessary to do so.
+
+config INTEL_MENLOW
+ tristate "Thermal Management driver for Intel menlow platform"
+ depends on ACPI_THERMAL
+ select THERMAL
+ ---help---
+ ACPI thermal management enhancement driver on
+ Intel Menlow platform.
+
+ If unsure, say N.
+
+config EEEPC_LAPTOP
+ tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
+ depends on ACPI
+ depends on EXPERIMENTAL
+ select BACKLIGHT_CLASS_DEVICE
+ select HWMON
+ select RFKILL
+ ---help---
+ This driver supports the Fn-Fx keys on Eee PC laptops.
+ It also adds the ability to switch camera/wlan on/off.
+
+ If you have an Eee PC laptop, say Y or M here.
+
+
+config ACPI_WMI
+ tristate "WMI (EXPERIMENTAL)"
+ depends on ACPI
+ depends on EXPERIMENTAL
+ help
+ This driver adds support for the ACPI-WMI (Windows Management
+ Instrumentation) mapper device (PNP0C14) found on some systems.
+
+ ACPI-WMI is a proprietary extension to ACPI to expose parts of the
+ ACPI firmware to userspace - this is done through various vendor
+ defined methods and data blocks in a PNP0C14 device, which are then
+ made available for userspace to call.
+
+ The implementation of this in Linux currently only exposes this to
+ other kernel space drivers.
+
+ This driver is a required dependency to build the firmware specific
+ drivers needed on many machines, including Acer and HP laptops.
+
+ It is safe to enable this driver even if your DSDT doesn't define
+ any ACPI-WMI devices.
+
+config ACPI_ASUS
+ tristate "ASUS/Medion Laptop Extras"
+ depends on ACPI
+ select BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This driver provides support for extra features of ACPI-compatible
+ ASUS laptops. As some of Medion laptops are made by ASUS, it may also
+ support some Medion laptops (such as 9675 for example). It makes all
+ the extra buttons generate standard ACPI events that go through
+ /proc/acpi/events, and (on some models) adds support for changing the
+ display brightness and output, switching the LCD backlight on and off,
+ and most importantly, allows you to blink those fancy LEDs intended
+ for reporting mail and wireless status.
+
+ Note: display switching code is currently considered EXPERIMENTAL,
+ toying with these values may even lock your machine.
+
+ All settings are changed via /proc/acpi/asus directory entries. Owner
+ and group for these entries can be set with asus_uid and asus_gid
+ parameters.
+
+ More information and a userspace daemon for handling the extra buttons
+ at <http://sourceforge.net/projects/acpi4asus/>.
+
+ If you have an ACPI-compatible ASUS laptop, say Y or M here. This
+ driver is still under development, so if your laptop is unsupported or
+ something works not quite as expected, please use the mailing list
+ available on the above page (acpi4asus-user@lists.sourceforge.net).
+
+ NOTE: This driver is deprecated and will probably be removed soon,
+ use asus-laptop instead.
+
+config ACPI_TOSHIBA
+ tristate "Toshiba Laptop Extras"
+ depends on ACPI
+ depends on INPUT
+ select INPUT_POLLDEV
+ select NET
+ select RFKILL
+ select BACKLIGHT_CLASS_DEVICE
+ ---help---
+ This driver adds support for access to certain system settings
+ on "legacy free" Toshiba laptops. These laptops can be recognized by
+ their lack of a BIOS setup menu and APM support.
+
+ On these machines, all system configuration is handled through the
+ ACPI. This driver is required for access to controls not covered
+ by the general ACPI drivers, such as LCD brightness, video output,
+ etc.
+
+ This driver differs from the non-ACPI Toshiba laptop driver (located
+ under "Processor type and features") in several aspects.
+ Configuration is accessed by reading and writing text files in the
+ /proc tree instead of by program interface to /dev. Furthermore, no
+ power management functions are exposed, as those are handled by the
+ general ACPI drivers.
+
+ More information about this driver is available at
+ <http://memebeam.org/toys/ToshibaAcpiDriver>.
+
+ If you have a legacy free Toshiba laptop (such as the Libretto L1
+ series), say Y.
+endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
new file mode 100644
index 000000000000..e29065120be9
--- /dev/null
+++ b/drivers/platform/x86/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for linux/drivers/platform/x86
+# x86 Platform-Specific Drivers
+#
+obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
+obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
+obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
+obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
+obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
+obj-$(CONFIG_ACER_WMI) += acer-wmi.o
+obj-$(CONFIG_HP_WMI) += hp-wmi.o
+obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
+obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
+obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
+obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
+obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
+obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
+obj-$(CONFIG_ACPI_WMI) += wmi.o
+obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
+obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
diff --git a/drivers/misc/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 94c9f911824e..94c9f911824e 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
diff --git a/drivers/misc/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 8fb8b3591048..8fb8b3591048 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
diff --git a/drivers/acpi/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index 1e74988c7b2d..1e74988c7b2d 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
diff --git a/drivers/misc/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 11003bba10d3..11003bba10d3 100644
--- a/drivers/misc/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
new file mode 100644
index 000000000000..16e11c2ee19a
--- /dev/null
+++ b/drivers/platform/x86/dell-laptop.c
@@ -0,0 +1,436 @@
+/*
+ * Driver for Dell laptop extras
+ *
+ * Copyright (c) Red Hat <mjg@redhat.com>
+ *
+ * Based on documentation in the libsmbios package, Copyright (C) 2005 Dell
+ * Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/dmi.h>
+#include <linux/io.h>
+#include <linux/rfkill.h>
+#include <linux/power_supply.h>
+#include <linux/acpi.h>
+#include "../../firmware/dcdbas.h"
+
+#define BRIGHTNESS_TOKEN 0x7d
+
+/* This structure will be modified by the firmware when we enter
+ * system management mode, hence the volatiles */
+
+struct calling_interface_buffer {
+ u16 class;
+ u16 select;
+ volatile u32 input[4];
+ volatile u32 output[4];
+} __packed;
+
+struct calling_interface_token {
+ u16 tokenID;
+ u16 location;
+ union {
+ u16 value;
+ u16 stringlength;
+ };
+};
+
+struct calling_interface_structure {
+ struct dmi_header header;
+ u16 cmdIOAddress;
+ u8 cmdIOCode;
+ u32 supportedCmds;
+ struct calling_interface_token tokens[];
+} __packed;
+
+static int da_command_address;
+static int da_command_code;
+static int da_num_tokens;
+static struct calling_interface_token *da_tokens;
+
+static struct backlight_device *dell_backlight_device;
+static struct rfkill *wifi_rfkill;
+static struct rfkill *bluetooth_rfkill;
+static struct rfkill *wwan_rfkill;
+
+static const struct dmi_system_id __initdata dell_device_table[] = {
+ {
+ .ident = "Dell laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
+ },
+ },
+ { }
+};
+
+static void parse_da_table(const struct dmi_header *dm)
+{
+ /* Final token is a terminator, so we don't want to copy it */
+ int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
+ struct calling_interface_structure *table =
+ container_of(dm, struct calling_interface_structure, header);
+
+ /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least
+ 6 bytes of entry */
+
+ if (dm->length < 17)
+ return;
+
+ da_command_address = table->cmdIOAddress;
+ da_command_code = table->cmdIOCode;
+
+ da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
+ sizeof(struct calling_interface_token),
+ GFP_KERNEL);
+
+ if (!da_tokens)
+ return;
+
+ memcpy(da_tokens+da_num_tokens, table->tokens,
+ sizeof(struct calling_interface_token) * tokens);
+
+ da_num_tokens += tokens;
+}
+
+static void find_tokens(const struct dmi_header *dm)
+{
+ switch (dm->type) {
+ case 0xd4: /* Indexed IO */
+ break;
+ case 0xd5: /* Protected Area Type 1 */
+ break;
+ case 0xd6: /* Protected Area Type 2 */
+ break;
+ case 0xda: /* Calling interface */
+ parse_da_table(dm);
+ break;
+ }
+}
+
+static int find_token_location(int tokenid)
+{
+ int i;
+ for (i = 0; i < da_num_tokens; i++) {
+ if (da_tokens[i].tokenID == tokenid)
+ return da_tokens[i].location;
+ }
+
+ return -1;
+}
+
+static struct calling_interface_buffer *
+dell_send_request(struct calling_interface_buffer *buffer, int class,
+ int select)
+{
+ struct smi_cmd command;
+
+ command.magic = SMI_CMD_MAGIC;
+ command.command_address = da_command_address;
+ command.command_code = da_command_code;
+ command.ebx = virt_to_phys(buffer);
+ command.ecx = 0x42534931;
+
+ buffer->class = class;
+ buffer->select = select;
+
+ dcdbas_smi_request(&command);
+
+ return buffer;
+}
+
+/* Derived from information in DellWirelessCtl.cpp:
+ Class 17, select 11 is radio control. It returns an array of 32-bit values.
+
+ result[0]: return code
+ result[1]:
+ Bit 0: Hardware switch supported
+ Bit 1: Wifi locator supported
+ Bit 2: Wifi is supported
+ Bit 3: Bluetooth is supported
+ Bit 4: WWAN is supported
+ Bit 5: Wireless keyboard supported
+ Bits 6-7: Reserved
+ Bit 8: Wifi is installed
+ Bit 9: Bluetooth is installed
+ Bit 10: WWAN is installed
+ Bits 11-15: Reserved
+ Bit 16: Hardware switch is on
+ Bit 17: Wifi is blocked
+ Bit 18: Bluetooth is blocked
+ Bit 19: WWAN is blocked
+ Bits 20-31: Reserved
+ result[2]: NVRAM size in bytes
+ result[3]: NVRAM format version number
+*/
+
+static int dell_rfkill_set(int radio, enum rfkill_state state)
+{
+ struct calling_interface_buffer buffer;
+ int disable = (state == RFKILL_STATE_UNBLOCKED) ? 0 : 1;
+
+ memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+ buffer.input[0] = (1 | (radio<<8) | (disable << 16));
+ dell_send_request(&buffer, 17, 11);
+
+ return 0;
+}
+
+static int dell_wifi_set(void *data, enum rfkill_state state)
+{
+ return dell_rfkill_set(1, state);
+}
+
+static int dell_bluetooth_set(void *data, enum rfkill_state state)
+{
+ return dell_rfkill_set(2, state);
+}
+
+static int dell_wwan_set(void *data, enum rfkill_state state)
+{
+ return dell_rfkill_set(3, state);
+}
+
+static int dell_rfkill_get(int bit, enum rfkill_state *state)
+{
+ struct calling_interface_buffer buffer;
+ int status;
+ int new_state = RFKILL_STATE_HARD_BLOCKED;
+
+ memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+ dell_send_request(&buffer, 17, 11);
+ status = buffer.output[1];
+
+ if (status & (1<<16))
+ new_state = RFKILL_STATE_SOFT_BLOCKED;
+
+ if (status & (1<<bit))
+ *state = new_state;
+ else
+ *state = RFKILL_STATE_UNBLOCKED;
+
+ return 0;
+}
+
+static int dell_wifi_get(void *data, enum rfkill_state *state)
+{
+ return dell_rfkill_get(17, state);
+}
+
+static int dell_bluetooth_get(void *data, enum rfkill_state *state)
+{
+ return dell_rfkill_get(18, state);
+}
+
+static int dell_wwan_get(void *data, enum rfkill_state *state)
+{
+ return dell_rfkill_get(19, state);
+}
+
+static int dell_setup_rfkill(void)
+{
+ struct calling_interface_buffer buffer;
+ int status;
+ int ret;
+
+ memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+ dell_send_request(&buffer, 17, 11);
+ status = buffer.output[1];
+
+ if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
+ wifi_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_WLAN);
+ if (!wifi_rfkill)
+ goto err_wifi;
+ wifi_rfkill->name = "dell-wifi";
+ wifi_rfkill->toggle_radio = dell_wifi_set;
+ wifi_rfkill->get_state = dell_wifi_get;
+ ret = rfkill_register(wifi_rfkill);
+ if (ret)
+ goto err_wifi;
+ }
+
+ if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
+ bluetooth_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_BLUETOOTH);
+ if (!bluetooth_rfkill)
+ goto err_bluetooth;
+ bluetooth_rfkill->name = "dell-bluetooth";
+ bluetooth_rfkill->toggle_radio = dell_bluetooth_set;
+ bluetooth_rfkill->get_state = dell_bluetooth_get;
+ ret = rfkill_register(bluetooth_rfkill);
+ if (ret)
+ goto err_bluetooth;
+ }
+
+ if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
+ wwan_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_WWAN);
+ if (!wwan_rfkill)
+ goto err_wwan;
+ wwan_rfkill->name = "dell-wwan";
+ wwan_rfkill->toggle_radio = dell_wwan_set;
+ wwan_rfkill->get_state = dell_wwan_get;
+ ret = rfkill_register(wwan_rfkill);
+ if (ret)
+ goto err_wwan;
+ }
+
+ return 0;
+err_wwan:
+ if (wwan_rfkill)
+ rfkill_free(wwan_rfkill);
+ if (bluetooth_rfkill) {
+ rfkill_unregister(bluetooth_rfkill);
+ bluetooth_rfkill = NULL;
+ }
+err_bluetooth:
+ if (bluetooth_rfkill)
+ rfkill_free(bluetooth_rfkill);
+ if (wifi_rfkill) {
+ rfkill_unregister(wifi_rfkill);
+ wifi_rfkill = NULL;
+ }
+err_wifi:
+ if (wifi_rfkill)
+ rfkill_free(wifi_rfkill);
+
+ return ret;
+}
+
+static int dell_send_intensity(struct backlight_device *bd)
+{
+ struct calling_interface_buffer buffer;
+
+ memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+ buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
+ buffer.input[1] = bd->props.brightness;
+
+ if (buffer.input[0] == -1)
+ return -ENODEV;
+
+ if (power_supply_is_system_supplied() > 0)
+ dell_send_request(&buffer, 1, 2);
+ else
+ dell_send_request(&buffer, 1, 1);
+
+ return 0;
+}
+
+static int dell_get_intensity(struct backlight_device *bd)
+{
+ struct calling_interface_buffer buffer;
+
+ memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+ buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
+
+ if (buffer.input[0] == -1)
+ return -ENODEV;
+
+ if (power_supply_is_system_supplied() > 0)
+ dell_send_request(&buffer, 0, 2);
+ else
+ dell_send_request(&buffer, 0, 1);
+
+ return buffer.output[1];
+}
+
+static struct backlight_ops dell_ops = {
+ .get_brightness = dell_get_intensity,
+ .update_status = dell_send_intensity,
+};
+
+static int __init dell_init(void)
+{
+ struct calling_interface_buffer buffer;
+ int max_intensity = 0;
+ int ret;
+
+ if (!dmi_check_system(dell_device_table))
+ return -ENODEV;
+
+ dmi_walk(find_tokens);
+
+ if (!da_tokens) {
+ printk(KERN_INFO "dell-laptop: Unable to find dmi tokens\n");
+ return -ENODEV;
+ }
+
+ ret = dell_setup_rfkill();
+
+ if (ret) {
+ printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n");
+ goto out;
+ }
+
+#ifdef CONFIG_ACPI
+ /* In the event of an ACPI backlight being available, don't
+ * register the platform controller.
+ */
+ if (acpi_video_backlight_support())
+ return 0;
+#endif
+
+ memset(&buffer, 0, sizeof(struct calling_interface_buffer));
+ buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
+
+ if (buffer.input[0] != -1) {
+ dell_send_request(&buffer, 0, 2);
+ max_intensity = buffer.output[3];
+ }
+
+ if (max_intensity) {
+ dell_backlight_device = backlight_device_register(
+ "dell_backlight",
+ NULL, NULL,
+ &dell_ops);
+
+ if (IS_ERR(dell_backlight_device)) {
+ ret = PTR_ERR(dell_backlight_device);
+ dell_backlight_device = NULL;
+ goto out;
+ }
+
+ dell_backlight_device->props.max_brightness = max_intensity;
+ dell_backlight_device->props.brightness =
+ dell_get_intensity(dell_backlight_device);
+ backlight_update_status(dell_backlight_device);
+ }
+
+ return 0;
+out:
+ if (wifi_rfkill)
+ rfkill_unregister(wifi_rfkill);
+ if (bluetooth_rfkill)
+ rfkill_unregister(bluetooth_rfkill);
+ if (wwan_rfkill)
+ rfkill_unregister(wwan_rfkill);
+ kfree(da_tokens);
+ return ret;
+}
+
+static void __exit dell_exit(void)
+{
+ backlight_device_unregister(dell_backlight_device);
+ if (wifi_rfkill)
+ rfkill_unregister(wifi_rfkill);
+ if (bluetooth_rfkill)
+ rfkill_unregister(bluetooth_rfkill);
+ if (wwan_rfkill)
+ rfkill_unregister(wwan_rfkill);
+}
+
+module_init(dell_init);
+module_exit(dell_exit);
+
+MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
+MODULE_DESCRIPTION("Dell laptop driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 02fe2b8b8939..9d93cb971e59 100644
--- a/drivers/misc/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -90,7 +90,7 @@ enum {
};
static const char *cm_getv[] = {
- "WLDG", NULL, NULL, NULL,
+ "WLDG", "BTHG", NULL, NULL,
"CAMG", NULL, NULL, NULL,
NULL, "PBLG", NULL, NULL,
"CFVG", NULL, NULL, NULL,
@@ -99,7 +99,7 @@ static const char *cm_getv[] = {
};
static const char *cm_setv[] = {
- "WLDS", NULL, NULL, NULL,
+ "WLDS", "BTHS", NULL, NULL,
"CAMS", NULL, NULL, NULL,
"SDSP", "PBLS", "HDPS", NULL,
"CFVS", NULL, NULL, NULL,
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index a7dd3e9fb79d..65dc41540c62 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -3,6 +3,7 @@
/*
Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
Copyright (C) 2008 Peter Gruber <nokos@gmx.net>
+ Copyright (C) 2008 Tony Vroon <tony@linx.net>
Based on earlier work:
Copyright (C) 2003 Shane Spencer <shane@bogomip.com>
Adrian Yee <brewt-fujitsu@brewt.org>
@@ -65,8 +66,11 @@
#include <linux/kfifo.h>
#include <linux/video_output.h>
#include <linux/platform_device.h>
+#ifdef CONFIG_LEDS_CLASS
+#include <linux/leds.h>
+#endif
-#define FUJITSU_DRIVER_VERSION "0.4.3"
+#define FUJITSU_DRIVER_VERSION "0.5.0"
#define FUJITSU_LCD_N_LEVELS 8
@@ -83,6 +87,24 @@
#define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86
#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
+/* FUNC interface - command values */
+#define FUNC_RFKILL 0x1000
+#define FUNC_LEDS 0x1001
+#define FUNC_BUTTONS 0x1002
+#define FUNC_BACKLIGHT 0x1004
+
+/* FUNC interface - responses */
+#define UNSUPPORTED_CMD 0x80000000
+
+#ifdef CONFIG_LEDS_CLASS
+/* FUNC interface - LED control */
+#define FUNC_LED_OFF 0x1
+#define FUNC_LED_ON 0x30001
+#define KEYBOARD_LAMPS 0x100
+#define LOGOLAMP_POWERON 0x2000
+#define LOGOLAMP_ALWAYS 0x4000
+#endif
+
/* Hotkey details */
#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
#define KEY2_CODE 0x411
@@ -133,7 +155,6 @@ struct fujitsu_t {
static struct fujitsu_t *fujitsu;
static int use_alt_lcd_levels = -1;
-static int disable_brightness_keys = -1;
static int disable_brightness_adjust = -1;
/* Device used to access other hotkeys on the laptop */
@@ -145,8 +166,9 @@ struct fujitsu_hotkey_t {
struct platform_device *pf_device;
struct kfifo *fifo;
spinlock_t fifo_lock;
-
- unsigned int irb; /* info about the pressed buttons */
+ int rfkill_state;
+ int logolamp_registered;
+ int kblamps_registered;
};
static struct fujitsu_hotkey_t *fujitsu_hotkey;
@@ -154,12 +176,139 @@ static struct fujitsu_hotkey_t *fujitsu_hotkey;
static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
void *data);
+#ifdef CONFIG_LEDS_CLASS
+static enum led_brightness logolamp_get(struct led_classdev *cdev);
+static void logolamp_set(struct led_classdev *cdev,
+ enum led_brightness brightness);
+
+struct led_classdev logolamp_led = {
+ .name = "fujitsu::logolamp",
+ .brightness_get = logolamp_get,
+ .brightness_set = logolamp_set
+};
+
+static enum led_brightness kblamps_get(struct led_classdev *cdev);
+static void kblamps_set(struct led_classdev *cdev,
+ enum led_brightness brightness);
+
+struct led_classdev kblamps_led = {
+ .name = "fujitsu::kblamps",
+ .brightness_get = kblamps_get,
+ .brightness_set = kblamps_set
+};
+#endif
+
#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
static u32 dbg_level = 0x03;
#endif
static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data);
+/* Fujitsu ACPI interface function */
+
+static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
+{
+ acpi_status status = AE_OK;
+ union acpi_object params[4] = {
+ { .type = ACPI_TYPE_INTEGER },
+ { .type = ACPI_TYPE_INTEGER },
+ { .type = ACPI_TYPE_INTEGER },
+ { .type = ACPI_TYPE_INTEGER }
+ };
+ struct acpi_object_list arg_list = { 4, &params[0] };
+ struct acpi_buffer output;
+ union acpi_object out_obj;
+ acpi_handle handle = NULL;
+
+ status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle);
+ if (ACPI_FAILURE(status)) {
+ vdbg_printk(FUJLAPTOP_DBG_ERROR,
+ "FUNC interface is not present\n");
+ return -ENODEV;
+ }
+
+ params[0].integer.value = cmd;
+ params[1].integer.value = arg0;
+ params[2].integer.value = arg1;
+ params[3].integer.value = arg2;
+
+ output.length = sizeof(out_obj);
+ output.pointer = &out_obj;
+
+ status = acpi_evaluate_object(handle, NULL, &arg_list, &output);
+ if (ACPI_FAILURE(status)) {
+ vdbg_printk(FUJLAPTOP_DBG_WARN,
+ "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n",
+ cmd, arg0, arg1, arg2);
+ return -ENODEV;
+ }
+
+ if (out_obj.type != ACPI_TYPE_INTEGER) {
+ vdbg_printk(FUJLAPTOP_DBG_WARN,
+ "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not "
+ "return an integer\n",
+ cmd, arg0, arg1, arg2);
+ return -ENODEV;
+ }
+
+ vdbg_printk(FUJLAPTOP_DBG_TRACE,
+ "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
+ cmd, arg0, arg1, arg2, (int)out_obj.integer.value);
+ return out_obj.integer.value;
+}
+
+#ifdef CONFIG_LEDS_CLASS
+/* LED class callbacks */
+
+static void logolamp_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ if (brightness >= LED_FULL) {
+ call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON);
+ call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON);
+ } else if (brightness >= LED_HALF) {
+ call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON);
+ call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF);
+ } else {
+ call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF);
+ }
+}
+
+static void kblamps_set(struct led_classdev *cdev,
+ enum led_brightness brightness)
+{
+ if (brightness >= LED_FULL)
+ call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON);
+ else
+ call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF);
+}
+
+static enum led_brightness logolamp_get(struct led_classdev *cdev)
+{
+ enum led_brightness brightness = LED_OFF;
+ int poweron, always;
+
+ poweron = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
+ if (poweron == FUNC_LED_ON) {
+ brightness = LED_HALF;
+ always = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
+ if (always == FUNC_LED_ON)
+ brightness = LED_FULL;
+ }
+ return brightness;
+}
+
+static enum led_brightness kblamps_get(struct led_classdev *cdev)
+{
+ enum led_brightness brightness = LED_OFF;
+
+ if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON)
+ brightness = LED_FULL;
+
+ return brightness;
+}
+#endif
+
/* Hardware access for LCD brightness control */
static int set_lcd_level(int level)
@@ -263,44 +412,34 @@ static int get_max_brightness(void)
return fujitsu->max_brightness;
}
-static int get_lcd_level_alt(void)
-{
- unsigned long long state = 0;
- acpi_status status = AE_OK;
-
- vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n");
-
- status =
- acpi_evaluate_integer(fujitsu->acpi_handle, "GBLS", NULL, &state);
- if (status < 0)
- return status;
-
- fujitsu->brightness_level = state & 0x0fffffff;
-
- if (state & 0x80000000)
- fujitsu->brightness_changed = 1;
- else
- fujitsu->brightness_changed = 0;
-
- return fujitsu->brightness_level;
-}
-
/* Backlight device stuff */
static int bl_get_brightness(struct backlight_device *b)
{
- if (use_alt_lcd_levels)
- return get_lcd_level_alt();
- else
- return get_lcd_level();
+ return get_lcd_level();
}
static int bl_update_status(struct backlight_device *b)
{
+ int ret;
+ if (b->props.power == 4)
+ ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
+ else
+ ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
+ if (ret != 0)
+ vdbg_printk(FUJLAPTOP_DBG_ERROR,
+ "Unable to adjust backlight power, error code %i\n",
+ ret);
+
if (use_alt_lcd_levels)
- return set_lcd_level_alt(b->props.brightness);
+ ret = set_lcd_level_alt(b->props.brightness);
else
- return set_lcd_level(b->props.brightness);
+ ret = set_lcd_level(b->props.brightness);
+ if (ret != 0)
+ vdbg_printk(FUJLAPTOP_DBG_ERROR,
+ "Unable to adjust LCD brightness, error code %i\n",
+ ret);
+ return ret;
}
static struct backlight_ops fujitsubl_ops = {
@@ -344,10 +483,7 @@ static ssize_t show_lcd_level(struct device *dev,
int ret;
- if (use_alt_lcd_levels)
- ret = get_lcd_level_alt();
- else
- ret = get_lcd_level();
+ ret = get_lcd_level();
if (ret < 0)
return ret;
@@ -372,52 +508,71 @@ static ssize_t store_lcd_level(struct device *dev,
if (ret < 0)
return ret;
- if (use_alt_lcd_levels)
- ret = get_lcd_level_alt();
- else
- ret = get_lcd_level();
+ ret = get_lcd_level();
if (ret < 0)
return ret;
return count;
}
-/* Hardware access for hotkey device */
-
-static int get_irb(void)
+static ssize_t
+ignore_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
{
- unsigned long long state = 0;
- acpi_status status = AE_OK;
-
- vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n");
-
- status =
- acpi_evaluate_integer(fujitsu_hotkey->acpi_handle, "GIRB", NULL,
- &state);
- if (status < 0)
- return status;
+ return count;
+}
- fujitsu_hotkey->irb = state;
+static ssize_t
+show_lid_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+ return sprintf(buf, "unknown\n");
+ if (fujitsu_hotkey->rfkill_state & 0x100)
+ return sprintf(buf, "open\n");
+ else
+ return sprintf(buf, "closed\n");
+}
- return fujitsu_hotkey->irb;
+static ssize_t
+show_dock_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+ return sprintf(buf, "unknown\n");
+ if (fujitsu_hotkey->rfkill_state & 0x200)
+ return sprintf(buf, "docked\n");
+ else
+ return sprintf(buf, "undocked\n");
}
static ssize_t
-ignore_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
+show_radios_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- return count;
+ if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+ return sprintf(buf, "unknown\n");
+ if (fujitsu_hotkey->rfkill_state & 0x20)
+ return sprintf(buf, "on\n");
+ else
+ return sprintf(buf, "killed\n");
}
static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store);
static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed,
ignore_store);
static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
+static DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store);
+static DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store);
+static DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store);
static struct attribute *fujitsupf_attributes[] = {
&dev_attr_brightness_changed.attr,
&dev_attr_max_brightness.attr,
&dev_attr_lcd_level.attr,
+ &dev_attr_lid.attr,
+ &dev_attr_dock.attr,
+ &dev_attr_radios.attr,
NULL
};
@@ -435,24 +590,16 @@ static struct platform_driver fujitsupf_driver = {
static void dmi_check_cb_common(const struct dmi_system_id *id)
{
acpi_handle handle;
- int have_blnf;
printk(KERN_INFO "fujitsu-laptop: Identified laptop model '%s'.\n",
id->ident);
- have_blnf = ACPI_SUCCESS
- (acpi_get_handle(NULL, "\\_SB.PCI0.GFX0.LCD.BLNF", &handle));
if (use_alt_lcd_levels == -1) {
- vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detecting usealt\n");
- use_alt_lcd_levels = 1;
- }
- if (disable_brightness_keys == -1) {
- vdbg_printk(FUJLAPTOP_DBG_TRACE,
- "auto-detecting disable_keys\n");
- disable_brightness_keys = have_blnf ? 1 : 0;
- }
- if (disable_brightness_adjust == -1) {
- vdbg_printk(FUJLAPTOP_DBG_TRACE,
- "auto-detecting disable_adjust\n");
- disable_brightness_adjust = have_blnf ? 0 : 1;
+ if (ACPI_SUCCESS(acpi_get_handle(NULL,
+ "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle)))
+ use_alt_lcd_levels = 1;
+ else
+ use_alt_lcd_levels = 0;
+ vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detected usealt as "
+ "%i\n", use_alt_lcd_levels);
}
}
@@ -581,19 +728,14 @@ static int acpi_fujitsu_add(struct acpi_device *device)
/* do config (detect defaults) */
use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
- disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
vdbg_printk(FUJLAPTOP_DBG_INFO,
- "config: [alt interface: %d], [key disable: %d], [adjust disable: %d]\n",
- use_alt_lcd_levels, disable_brightness_keys,
- disable_brightness_adjust);
+ "config: [alt interface: %d], [adjust disable: %d]\n",
+ use_alt_lcd_levels, disable_brightness_adjust);
if (get_max_brightness() <= 0)
fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS;
- if (use_alt_lcd_levels)
- get_lcd_level_alt();
- else
- get_lcd_level();
+ get_lcd_level();
return result;
@@ -644,43 +786,23 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
case ACPI_FUJITSU_NOTIFY_CODE1:
keycode = 0;
oldb = fujitsu->brightness_level;
- get_lcd_level(); /* the alt version always yields changed */
+ get_lcd_level();
newb = fujitsu->brightness_level;
vdbg_printk(FUJLAPTOP_DBG_TRACE,
"brightness button event [%i -> %i (%i)]\n",
oldb, newb, fujitsu->brightness_changed);
- if (oldb == newb && fujitsu->brightness_changed) {
- keycode = 0;
- if (disable_brightness_keys != 1) {
- if (oldb == 0) {
- acpi_bus_generate_proc_event
- (fujitsu->dev,
- ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
- 0);
- keycode = KEY_BRIGHTNESSDOWN;
- } else if (oldb ==
- (fujitsu->max_brightness) - 1) {
- acpi_bus_generate_proc_event
- (fujitsu->dev,
- ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
- 0);
- keycode = KEY_BRIGHTNESSUP;
- }
- }
- } else if (oldb < newb) {
+ if (oldb < newb) {
if (disable_brightness_adjust != 1) {
if (use_alt_lcd_levels)
set_lcd_level_alt(newb);
else
set_lcd_level(newb);
}
- if (disable_brightness_keys != 1) {
- acpi_bus_generate_proc_event(fujitsu->dev,
- ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
- keycode = KEY_BRIGHTNESSUP;
- }
+ acpi_bus_generate_proc_event(fujitsu->dev,
+ ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
+ keycode = KEY_BRIGHTNESSUP;
} else if (oldb > newb) {
if (disable_brightness_adjust != 1) {
if (use_alt_lcd_levels)
@@ -688,13 +810,9 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
else
set_lcd_level(newb);
}
- if (disable_brightness_keys != 1) {
- acpi_bus_generate_proc_event(fujitsu->dev,
- ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
- keycode = KEY_BRIGHTNESSDOWN;
- }
- } else {
- keycode = KEY_UNKNOWN;
+ acpi_bus_generate_proc_event(fujitsu->dev,
+ ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
+ keycode = KEY_BRIGHTNESSDOWN;
}
break;
default:
@@ -771,7 +889,8 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
input->id.bustype = BUS_HOST;
input->id.product = 0x06;
input->dev.parent = &device->dev;
- input->evbit[0] = BIT(EV_KEY);
+
+ set_bit(EV_KEY, input->evbit);
set_bit(fujitsu->keycode1, input->keybit);
set_bit(fujitsu->keycode2, input->keybit);
set_bit(fujitsu->keycode3, input->keybit);
@@ -803,10 +922,44 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
printk(KERN_ERR "_INI Method failed\n");
}
- i = 0; /* Discard hotkey ringbuffer */
- while (get_irb() != 0 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) ;
+ i = 0;
+ while (call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0
+ && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE)
+ ; /* No action, result is discarded */
vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
+ fujitsu_hotkey->rfkill_state =
+ call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
+
+ /* Suspect this is a keymap of the application panel, print it */
+ printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n",
+ call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));
+
+ #ifdef CONFIG_LEDS_CLASS
+ if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
+ result = led_classdev_register(&fujitsu->pf_device->dev,
+ &logolamp_led);
+ if (result == 0) {
+ fujitsu_hotkey->logolamp_registered = 1;
+ } else {
+ printk(KERN_ERR "fujitsu-laptop: Could not register "
+ "LED handler for logo lamp, error %i\n", result);
+ }
+ }
+
+ if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
+ (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
+ result = led_classdev_register(&fujitsu->pf_device->dev,
+ &kblamps_led);
+ if (result == 0) {
+ fujitsu_hotkey->kblamps_registered = 1;
+ } else {
+ printk(KERN_ERR "fujitsu-laptop: Could not register "
+ "LED handler for keyboard lamps, error %i\n", result);
+ }
+ }
+ #endif
+
return result;
end:
@@ -852,16 +1005,15 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
input = fujitsu_hotkey->input;
- vdbg_printk(FUJLAPTOP_DBG_TRACE, "Hotkey event\n");
+ fujitsu_hotkey->rfkill_state =
+ call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
switch (event) {
case ACPI_FUJITSU_NOTIFY_CODE1:
i = 0;
- while ((irb = get_irb()) != 0
- && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) {
- vdbg_printk(FUJLAPTOP_DBG_TRACE, "GIRB result [%x]\n",
- irb);
-
+ while ((irb =
+ call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0
+ && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) {
switch (irb & 0x4ff) {
case KEY1_CODE:
keycode = fujitsu->keycode1;
@@ -1035,6 +1187,15 @@ static int __init fujitsu_init(void)
goto fail_hotkey1;
}
+ /* Sync backlight power status (needs FUJ02E3 device, hence deferred) */
+
+ if (!acpi_video_backlight_support()) {
+ if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
+ fujitsu->bl_device->props.power = 4;
+ else
+ fujitsu->bl_device->props.power = 0;
+ }
+
printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
" successfully loaded.\n");
@@ -1074,6 +1235,14 @@ fail_acpi:
static void __exit fujitsu_cleanup(void)
{
+ #ifdef CONFIG_LEDS_CLASS
+ if (fujitsu_hotkey->logolamp_registered != 0)
+ led_classdev_unregister(&logolamp_led);
+
+ if (fujitsu_hotkey->kblamps_registered != 0)
+ led_classdev_unregister(&kblamps_led);
+ #endif
+
sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
&fujitsupf_attribute_group);
platform_device_unregister(fujitsu->pf_device);
@@ -1098,9 +1267,6 @@ module_exit(fujitsu_cleanup);
module_param(use_alt_lcd_levels, uint, 0644);
MODULE_PARM_DESC(use_alt_lcd_levels,
"Use alternative interface for lcd_levels (needed for Lifebook s6410).");
-module_param(disable_brightness_keys, uint, 0644);
-MODULE_PARM_DESC(disable_brightness_keys,
- "Disable brightness keys (eg. if they are already handled by the generic ACPI_VIDEO device).");
module_param(disable_brightness_adjust, uint, 0644);
MODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment .");
#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
@@ -1108,12 +1274,13 @@ module_param_named(debug, dbg_level, uint, 0644);
MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
#endif
-MODULE_AUTHOR("Jonathan Woithe, Peter Gruber");
+MODULE_AUTHOR("Jonathan Woithe, Peter Gruber, Tony Vroon");
MODULE_DESCRIPTION("Fujitsu laptop extras support");
MODULE_VERSION(FUJITSU_DRIVER_VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
+MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*");
MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
static struct pnp_device_id pnp_ids[] = {
diff --git a/drivers/misc/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 4b7c24c519c3..f41135f2fb29 100644
--- a/drivers/misc/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -382,6 +382,11 @@ static int __init hp_wmi_input_setup(void)
case KE_SW:
set_bit(EV_SW, hp_wmi_input_dev->evbit);
set_bit(key->keycode, hp_wmi_input_dev->swbit);
+
+ /* Set initial dock state */
+ input_report_switch(hp_wmi_input_dev, key->keycode,
+ hp_wmi_dock_state());
+ input_sync(hp_wmi_input_dev);
break;
}
}
@@ -428,7 +433,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wifi_rfkill->state = hp_wmi_wifi_state();
wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
wifi_rfkill->user_claim_unsupported = 1;
- rfkill_register(wifi_rfkill);
+ err = rfkill_register(wifi_rfkill);
+ if (err)
+ goto add_sysfs_error;
}
if (wireless & 0x2) {
@@ -438,7 +445,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
bluetooth_rfkill->state = hp_wmi_bluetooth_state();
bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
bluetooth_rfkill->user_claim_unsupported = 1;
- rfkill_register(bluetooth_rfkill);
+ err = rfkill_register(bluetooth_rfkill);
+ if (err)
+ goto register_bluetooth_error;
}
if (wireless & 0x4) {
@@ -447,10 +456,18 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wwan_rfkill->state = hp_wmi_wwan_state();
wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
wwan_rfkill->user_claim_unsupported = 1;
- rfkill_register(wwan_rfkill);
+ err = rfkill_register(wwan_rfkill);
+ if (err)
+ goto register_wwan_err;
}
return 0;
+register_wwan_err:
+ if (bluetooth_rfkill)
+ rfkill_unregister(bluetooth_rfkill);
+register_bluetooth_error:
+ if (wifi_rfkill)
+ rfkill_unregister(wifi_rfkill);
add_sysfs_error:
cleanup_sysfs(device);
return err;
diff --git a/drivers/misc/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index 27b7662955bb..27b7662955bb 100644
--- a/drivers/misc/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
diff --git a/drivers/misc/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 759763d18e4c..759763d18e4c 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
diff --git a/drivers/misc/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 4a1bc64485d5..f30db367c82e 100644
--- a/drivers/misc/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -241,8 +241,6 @@ static int acpi_pcc_write_sset(struct pcc_acpi *pcc, int func, int val)
};
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_pcc_write_sset");
-
status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SSET,
&params, NULL);
@@ -254,8 +252,6 @@ static inline int acpi_pcc_get_sqty(struct acpi_device *device)
unsigned long long s;
acpi_status status;
- ACPI_FUNCTION_TRACE("acpi_pcc_get_sqty");
-
status = acpi_evaluate_integer(device->handle, METHOD_HKEY_SQTY,
NULL, &s);
if (ACPI_SUCCESS(status))
@@ -274,8 +270,6 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
union acpi_object *hkey = NULL;
int i;
- ACPI_FUNCTION_TRACE("acpi_pcc_retrieve_biosdata");
-
status = acpi_evaluate_object(pcc->handle, METHOD_HKEY_SINF, 0,
&buffer);
if (ACPI_FAILURE(status)) {
@@ -501,8 +495,6 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
int key_code, hkey_num;
unsigned long long result;
- ACPI_FUNCTION_TRACE("acpi_pcc_generate_keyinput");
-
rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
NULL, &result);
if (!ACPI_SUCCESS(rc)) {
@@ -538,8 +530,6 @@ static void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data)
{
struct pcc_acpi *pcc = (struct pcc_acpi *) data;
- ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_notify");
-
switch (event) {
case HKEY_NOTIFY:
acpi_pcc_generate_keyinput(pcc);
@@ -554,8 +544,6 @@ static int acpi_pcc_init_input(struct pcc_acpi *pcc)
{
int i, rc;
- ACPI_FUNCTION_TRACE("acpi_pcc_init_input");
-
pcc->input_dev = input_allocate_device();
if (!pcc->input_dev) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
@@ -597,8 +585,6 @@ static int acpi_pcc_hotkey_resume(struct acpi_device *device)
struct pcc_acpi *pcc = acpi_driver_data(device);
acpi_status status = AE_OK;
- ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume");
-
if (device == NULL || pcc == NULL)
return -EINVAL;
@@ -616,8 +602,6 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
struct pcc_acpi *pcc;
int num_sifr, result;
- ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add");
-
if (!device)
return -EINVAL;
@@ -714,8 +698,6 @@ static int __init acpi_pcc_init(void)
{
int result = 0;
- ACPI_FUNCTION_TRACE("acpi_pcc_init");
-
if (acpi_disabled)
return -ENODEV;
@@ -733,8 +715,6 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
{
struct pcc_acpi *pcc = acpi_driver_data(device);
- ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove");
-
if (!device || !pcc)
return -EINVAL;
@@ -757,8 +737,6 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
static void __exit acpi_pcc_exit(void)
{
- ACPI_FUNCTION_TRACE("acpi_pcc_exit");
-
acpi_bus_unregister_driver(&acpi_pcc_driver);
}
diff --git a/drivers/misc/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 571b211608d1..537959d07148 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -935,14 +935,17 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
void *context, void **return_value)
{
- struct acpi_namespace_node *node;
- union acpi_operand_object *operand;
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- node = (struct acpi_namespace_node *)handle;
- operand = (union acpi_operand_object *)node->object;
+ if (ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) {
+ info = buffer.pointer;
- printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", node->name.ascii,
- (u32) operand->method.param_count);
+ printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n",
+ (char *)&info->name, info->param_count);
+
+ kfree(buffer.pointer);
+ }
return AE_OK;
}
diff --git a/drivers/misc/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c
index f25e4c974dcf..b4a4aa9ee482 100644
--- a/drivers/misc/tc1100-wmi.c
+++ b/drivers/platform/x86/tc1100-wmi.c
@@ -30,7 +30,6 @@
#include <linux/init.h>
#include <linux/types.h>
#include <acpi/acpi.h>
-#include <acpi/actypes.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <linux/platform_device.h>
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 899766e16fa8..bcbc05107ba8 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,7 +21,7 @@
* 02110-1301, USA.
*/
-#define TPACPI_VERSION "0.21"
+#define TPACPI_VERSION "0.22"
#define TPACPI_SYSFS_VERSION 0x020200
/*
@@ -76,7 +76,6 @@
#include <linux/workqueue.h>
#include <acpi/acpi_drivers.h>
-#include <acpi/acnamesp.h>
#include <linux/pci_ids.h>
@@ -123,6 +122,27 @@ enum {
#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */
#define TPACPI_HKEY_INPUT_VERSION 0x4101
+/* ACPI \WGSV commands */
+enum {
+ TP_ACPI_WGSV_GET_STATE = 0x01, /* Get state information */
+ TP_ACPI_WGSV_PWR_ON_ON_RESUME = 0x02, /* Resume WWAN powered on */
+ TP_ACPI_WGSV_PWR_OFF_ON_RESUME = 0x03, /* Resume WWAN powered off */
+ TP_ACPI_WGSV_SAVE_STATE = 0x04, /* Save state for S4/S5 */
+};
+
+/* TP_ACPI_WGSV_GET_STATE bits */
+enum {
+ TP_ACPI_WGSV_STATE_WWANEXIST = 0x0001, /* WWAN hw available */
+ TP_ACPI_WGSV_STATE_WWANPWR = 0x0002, /* WWAN radio enabled */
+ TP_ACPI_WGSV_STATE_WWANPWRRES = 0x0004, /* WWAN state at resume */
+ TP_ACPI_WGSV_STATE_WWANBIOSOFF = 0x0008, /* WWAN disabled in BIOS */
+ TP_ACPI_WGSV_STATE_BLTHEXIST = 0x0001, /* BLTH hw available */
+ TP_ACPI_WGSV_STATE_BLTHPWR = 0x0002, /* BLTH radio enabled */
+ TP_ACPI_WGSV_STATE_BLTHPWRRES = 0x0004, /* BLTH state at resume */
+ TP_ACPI_WGSV_STATE_BLTHBIOSOFF = 0x0008, /* BLTH disabled in BIOS */
+ TP_ACPI_WGSV_STATE_UWBEXIST = 0x0010, /* UWB hw available */
+ TP_ACPI_WGSV_STATE_UWBPWR = 0x0020, /* UWB radio enabled */
+};
/****************************************************************************
* Main driver
@@ -149,14 +169,17 @@ enum {
enum {
TPACPI_RFK_BLUETOOTH_SW_ID = 0,
TPACPI_RFK_WWAN_SW_ID,
+ TPACPI_RFK_UWB_SW_ID,
};
/* Debugging */
#define TPACPI_LOG TPACPI_FILE ": "
-#define TPACPI_ERR KERN_ERR TPACPI_LOG
-#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
-#define TPACPI_INFO KERN_INFO TPACPI_LOG
-#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG
+#define TPACPI_ALERT KERN_ALERT TPACPI_LOG
+#define TPACPI_CRIT KERN_CRIT TPACPI_LOG
+#define TPACPI_ERR KERN_ERR TPACPI_LOG
+#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
+#define TPACPI_INFO KERN_INFO TPACPI_LOG
+#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG
#define TPACPI_DBG_ALL 0xffff
#define TPACPI_DBG_INIT 0x0001
@@ -202,6 +225,7 @@ struct ibm_struct {
void (*exit) (void);
void (*resume) (void);
void (*suspend) (pm_message_t state);
+ void (*shutdown) (void);
struct list_head all_drivers;
@@ -240,6 +264,7 @@ static struct {
u32 bright_16levels:1;
u32 bright_acpimode:1;
u32 wan:1;
+ u32 uwb:1;
u32 fan_ctrl_status_undef:1;
u32 input_device_registered:1;
u32 platform_drv_registered:1;
@@ -289,6 +314,18 @@ struct tpacpi_led_classdev {
unsigned int led;
};
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+static int dbg_wlswemul;
+static int tpacpi_wlsw_emulstate;
+static int dbg_bluetoothemul;
+static int tpacpi_bluetooth_emulstate;
+static int dbg_wwanemul;
+static int tpacpi_wwan_emulstate;
+static int dbg_uwbemul;
+static int tpacpi_uwb_emulstate;
+#endif
+
+
/****************************************************************************
****************************************************************************
*
@@ -729,6 +766,18 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
return 0;
}
+static void tpacpi_shutdown_handler(struct platform_device *pdev)
+{
+ struct ibm_struct *ibm, *itmp;
+
+ list_for_each_entry_safe(ibm, itmp,
+ &tpacpi_all_drivers,
+ all_drivers) {
+ if (ibm->shutdown)
+ (ibm->shutdown)();
+ }
+}
+
static struct platform_driver tpacpi_pdriver = {
.driver = {
.name = TPACPI_DRVR_NAME,
@@ -736,6 +785,7 @@ static struct platform_driver tpacpi_pdriver = {
},
.suspend = tpacpi_suspend_handler,
.resume = tpacpi_resume_handler,
+ .shutdown = tpacpi_shutdown_handler,
};
static struct platform_driver tpacpi_hwmon_pdriver = {
@@ -923,11 +973,27 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
struct rfkill **rfk,
const enum rfkill_type rfktype,
const char *name,
+ const bool set_default,
int (*toggle_radio)(void *, enum rfkill_state),
int (*get_state)(void *, enum rfkill_state *))
{
int res;
- enum rfkill_state initial_state;
+ enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED;
+
+ res = get_state(NULL, &initial_state);
+ if (res < 0) {
+ printk(TPACPI_ERR
+ "failed to read initial state for %s, error %d; "
+ "will turn radio off\n", name, res);
+ } else if (set_default) {
+ /* try to set the initial state as the default for the rfkill
+ * type, since we ask the firmware to preserve it across S5 in
+ * NVRAM */
+ rfkill_set_default(rfktype,
+ (initial_state == RFKILL_STATE_UNBLOCKED) ?
+ RFKILL_STATE_UNBLOCKED :
+ RFKILL_STATE_SOFT_BLOCKED);
+ }
*rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
if (!*rfk) {
@@ -939,9 +1005,7 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
(*rfk)->name = name;
(*rfk)->get_state = get_state;
(*rfk)->toggle_radio = toggle_radio;
-
- if (!get_state(NULL, &initial_state))
- (*rfk)->state = initial_state;
+ (*rfk)->state = initial_state;
res = rfkill_register(*rfk);
if (res < 0) {
@@ -1007,6 +1071,119 @@ static DRIVER_ATTR(version, S_IRUGO,
/* --------------------------------------------------------------------- */
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+
+static void tpacpi_send_radiosw_update(void);
+
+/* wlsw_emulstate ------------------------------------------------------ */
+static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wlsw_emulstate);
+}
+
+static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ unsigned long t;
+
+ if (parse_strtoul(buf, 1, &t))
+ return -EINVAL;
+
+ if (tpacpi_wlsw_emulstate != t) {
+ tpacpi_wlsw_emulstate = !!t;
+ tpacpi_send_radiosw_update();
+ } else
+ tpacpi_wlsw_emulstate = !!t;
+
+ return count;
+}
+
+static DRIVER_ATTR(wlsw_emulstate, S_IWUSR | S_IRUGO,
+ tpacpi_driver_wlsw_emulstate_show,
+ tpacpi_driver_wlsw_emulstate_store);
+
+/* bluetooth_emulstate ------------------------------------------------- */
+static ssize_t tpacpi_driver_bluetooth_emulstate_show(
+ struct device_driver *drv,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_bluetooth_emulstate);
+}
+
+static ssize_t tpacpi_driver_bluetooth_emulstate_store(
+ struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ unsigned long t;
+
+ if (parse_strtoul(buf, 1, &t))
+ return -EINVAL;
+
+ tpacpi_bluetooth_emulstate = !!t;
+
+ return count;
+}
+
+static DRIVER_ATTR(bluetooth_emulstate, S_IWUSR | S_IRUGO,
+ tpacpi_driver_bluetooth_emulstate_show,
+ tpacpi_driver_bluetooth_emulstate_store);
+
+/* wwan_emulstate ------------------------------------------------- */
+static ssize_t tpacpi_driver_wwan_emulstate_show(
+ struct device_driver *drv,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wwan_emulstate);
+}
+
+static ssize_t tpacpi_driver_wwan_emulstate_store(
+ struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ unsigned long t;
+
+ if (parse_strtoul(buf, 1, &t))
+ return -EINVAL;
+
+ tpacpi_wwan_emulstate = !!t;
+
+ return count;
+}
+
+static DRIVER_ATTR(wwan_emulstate, S_IWUSR | S_IRUGO,
+ tpacpi_driver_wwan_emulstate_show,
+ tpacpi_driver_wwan_emulstate_store);
+
+/* uwb_emulstate ------------------------------------------------- */
+static ssize_t tpacpi_driver_uwb_emulstate_show(
+ struct device_driver *drv,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_uwb_emulstate);
+}
+
+static ssize_t tpacpi_driver_uwb_emulstate_store(
+ struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ unsigned long t;
+
+ if (parse_strtoul(buf, 1, &t))
+ return -EINVAL;
+
+ tpacpi_uwb_emulstate = !!t;
+
+ return count;
+}
+
+static DRIVER_ATTR(uwb_emulstate, S_IWUSR | S_IRUGO,
+ tpacpi_driver_uwb_emulstate_show,
+ tpacpi_driver_uwb_emulstate_store);
+#endif
+
+/* --------------------------------------------------------------------- */
+
static struct driver_attribute *tpacpi_driver_attributes[] = {
&driver_attr_debug_level, &driver_attr_version,
&driver_attr_interface_version,
@@ -1023,6 +1200,17 @@ static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
i++;
}
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (!res && dbg_wlswemul)
+ res = driver_create_file(drv, &driver_attr_wlsw_emulstate);
+ if (!res && dbg_bluetoothemul)
+ res = driver_create_file(drv, &driver_attr_bluetooth_emulstate);
+ if (!res && dbg_wwanemul)
+ res = driver_create_file(drv, &driver_attr_wwan_emulstate);
+ if (!res && dbg_uwbemul)
+ res = driver_create_file(drv, &driver_attr_uwb_emulstate);
+#endif
+
return res;
}
@@ -1032,6 +1220,13 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
driver_remove_file(drv, tpacpi_driver_attributes[i]);
+
+#ifdef THINKPAD_ACPI_DEBUGFACILITIES
+ driver_remove_file(drv, &driver_attr_wlsw_emulstate);
+ driver_remove_file(drv, &driver_attr_bluetooth_emulstate);
+ driver_remove_file(drv, &driver_attr_wwan_emulstate);
+ driver_remove_file(drv, &driver_attr_uwb_emulstate);
+#endif
}
/****************************************************************************
@@ -1217,6 +1412,12 @@ static struct attribute_set *hotkey_dev_attributes;
static int hotkey_get_wlsw(int *status)
{
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_wlswemul) {
+ *status = !!tpacpi_wlsw_emulstate;
+ return 0;
+ }
+#endif
if (!acpi_evalf(hkey_handle, status, "WLSW", "d"))
return -EIO;
return 0;
@@ -1679,7 +1880,7 @@ static ssize_t hotkey_mask_show(struct device *dev,
{
int res;
- if (mutex_lock_interruptible(&hotkey_mutex))
+ if (mutex_lock_killable(&hotkey_mutex))
return -ERESTARTSYS;
res = hotkey_mask_get();
mutex_unlock(&hotkey_mutex);
@@ -1698,7 +1899,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
if (parse_strtoul(buf, 0xffffffffUL, &t))
return -EINVAL;
- if (mutex_lock_interruptible(&hotkey_mutex))
+ if (mutex_lock_killable(&hotkey_mutex))
return -ERESTARTSYS;
res = hotkey_mask_set(t);
@@ -1784,7 +1985,7 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
((t & ~TPACPI_HKEY_NVRAM_KNOWN_MASK) != 0))
return -EINVAL;
- if (mutex_lock_interruptible(&hotkey_mutex))
+ if (mutex_lock_killable(&hotkey_mutex))
return -ERESTARTSYS;
HOTKEY_CONFIG_CRITICAL_START
@@ -1819,7 +2020,7 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
if (parse_strtoul(buf, 25, &t))
return -EINVAL;
- if (mutex_lock_interruptible(&hotkey_mutex))
+ if (mutex_lock_killable(&hotkey_mutex))
return -ERESTARTSYS;
hotkey_poll_freq = t;
@@ -1959,6 +2160,7 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
static void bluetooth_update_rfk(void);
static void wan_update_rfk(void);
+static void uwb_update_rfk(void);
static void tpacpi_send_radiosw_update(void)
{
int wlsw;
@@ -1968,6 +2170,8 @@ static void tpacpi_send_radiosw_update(void)
bluetooth_update_rfk();
if (tp_features.wan)
wan_update_rfk();
+ if (tp_features.uwb)
+ uwb_update_rfk();
if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
mutex_lock(&tpacpi_inputdev_send_mutex);
@@ -2223,6 +2427,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
hotkey_source_mask, hotkey_poll_freq);
#endif
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_wlswemul) {
+ tp_features.hotkey_wlsw = 1;
+ printk(TPACPI_INFO
+ "radio switch emulation enabled\n");
+ } else
+#endif
/* Not all thinkpads have a hardware radio switch */
if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
tp_features.hotkey_wlsw = 1;
@@ -2362,13 +2573,154 @@ err_exit:
return (res < 0)? res : 1;
}
+static bool hotkey_notify_hotkey(const u32 hkey,
+ bool *send_acpi_ev,
+ bool *ignore_acpi_ev)
+{
+ /* 0x1000-0x1FFF: key presses */
+ unsigned int scancode = hkey & 0xfff;
+ *send_acpi_ev = true;
+ *ignore_acpi_ev = false;
+
+ if (scancode > 0 && scancode < 0x21) {
+ scancode--;
+ if (!(hotkey_source_mask & (1 << scancode))) {
+ tpacpi_input_send_key(scancode);
+ *send_acpi_ev = false;
+ } else {
+ *ignore_acpi_ev = true;
+ }
+ return true;
+ }
+ return false;
+}
+
+static bool hotkey_notify_wakeup(const u32 hkey,
+ bool *send_acpi_ev,
+ bool *ignore_acpi_ev)
+{
+ /* 0x2000-0x2FFF: Wakeup reason */
+ *send_acpi_ev = true;
+ *ignore_acpi_ev = false;
+
+ switch (hkey) {
+ case 0x2304: /* suspend, undock */
+ case 0x2404: /* hibernation, undock */
+ hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
+ *ignore_acpi_ev = true;
+ break;
+
+ case 0x2305: /* suspend, bay eject */
+ case 0x2405: /* hibernation, bay eject */
+ hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
+ *ignore_acpi_ev = true;
+ break;
+
+ case 0x2313: /* Battery on critical low level (S3) */
+ case 0x2413: /* Battery on critical low level (S4) */
+ printk(TPACPI_ALERT
+ "EMERGENCY WAKEUP: battery almost empty\n");
+ /* how to auto-heal: */
+ /* 2313: woke up from S3, go to S4/S5 */
+ /* 2413: woke up from S4, go to S5 */
+ break;
+
+ default:
+ return false;
+ }
+
+ if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
+ printk(TPACPI_INFO
+ "woke up due to a hot-unplug "
+ "request...\n");
+ hotkey_wakeup_reason_notify_change();
+ }
+ return true;
+}
+
+static bool hotkey_notify_usrevent(const u32 hkey,
+ bool *send_acpi_ev,
+ bool *ignore_acpi_ev)
+{
+ /* 0x5000-0x5FFF: human interface helpers */
+ *send_acpi_ev = true;
+ *ignore_acpi_ev = false;
+
+ switch (hkey) {
+ case 0x5010: /* Lenovo new BIOS: brightness changed */
+ case 0x500b: /* X61t: tablet pen inserted into bay */
+ case 0x500c: /* X61t: tablet pen removed from bay */
+ return true;
+
+ case 0x5009: /* X41t-X61t: swivel up (tablet mode) */
+ case 0x500a: /* X41t-X61t: swivel down (normal mode) */
+ tpacpi_input_send_tabletsw();
+ hotkey_tablet_mode_notify_change();
+ *send_acpi_ev = false;
+ return true;
+
+ case 0x5001:
+ case 0x5002:
+ /* LID switch events. Do not propagate */
+ *ignore_acpi_ev = true;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool hotkey_notify_thermal(const u32 hkey,
+ bool *send_acpi_ev,
+ bool *ignore_acpi_ev)
+{
+ /* 0x6000-0x6FFF: thermal alarms */
+ *send_acpi_ev = true;
+ *ignore_acpi_ev = false;
+
+ switch (hkey) {
+ case 0x6011:
+ printk(TPACPI_CRIT
+ "THERMAL ALARM: battery is too hot!\n");
+ /* recommended action: warn user through gui */
+ return true;
+ case 0x6012:
+ printk(TPACPI_ALERT
+ "THERMAL EMERGENCY: battery is extremely hot!\n");
+ /* recommended action: immediate sleep/hibernate */
+ return true;
+ case 0x6021:
+ printk(TPACPI_CRIT
+ "THERMAL ALARM: "
+ "a sensor reports something is too hot!\n");
+ /* recommended action: warn user through gui, that */
+ /* some internal component is too hot */
+ return true;
+ case 0x6022:
+ printk(TPACPI_ALERT
+ "THERMAL EMERGENCY: "
+ "a sensor reports something is extremely hot!\n");
+ /* recommended action: immediate sleep/hibernate */
+ return true;
+ case 0x6030:
+ printk(TPACPI_INFO
+ "EC reports that Thermal Table has changed\n");
+ /* recommended action: do nothing, we don't have
+ * Lenovo ATM information */
+ return true;
+ default:
+ printk(TPACPI_ALERT
+ "THERMAL ALERT: unknown thermal alarm received\n");
+ return false;
+ }
+}
+
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
{
u32 hkey;
- unsigned int scancode;
- int send_acpi_ev;
- int ignore_acpi_ev;
- int unk_ev;
+ bool send_acpi_ev;
+ bool ignore_acpi_ev;
+ bool known_ev;
if (event != 0x80) {
printk(TPACPI_ERR
@@ -2376,7 +2728,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
/* forward it to userspace, maybe it knows how to handle it */
acpi_bus_generate_netlink_event(
ibm->acpi->device->pnp.device_class,
- ibm->acpi->device->dev.bus_id,
+ dev_name(&ibm->acpi->device->dev),
event, 0);
return;
}
@@ -2392,107 +2744,72 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
return;
}
- send_acpi_ev = 1;
- ignore_acpi_ev = 0;
- unk_ev = 0;
+ send_acpi_ev = true;
+ ignore_acpi_ev = false;
switch (hkey >> 12) {
case 1:
/* 0x1000-0x1FFF: key presses */
- scancode = hkey & 0xfff;
- if (scancode > 0 && scancode < 0x21) {
- scancode--;
- if (!(hotkey_source_mask & (1 << scancode))) {
- tpacpi_input_send_key(scancode);
- send_acpi_ev = 0;
- } else {
- ignore_acpi_ev = 1;
- }
- } else {
- unk_ev = 1;
- }
+ known_ev = hotkey_notify_hotkey(hkey, &send_acpi_ev,
+ &ignore_acpi_ev);
break;
case 2:
- /* Wakeup reason */
- switch (hkey) {
- case 0x2304: /* suspend, undock */
- case 0x2404: /* hibernation, undock */
- hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
- ignore_acpi_ev = 1;
- break;
- case 0x2305: /* suspend, bay eject */
- case 0x2405: /* hibernation, bay eject */
- hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
- ignore_acpi_ev = 1;
- break;
- default:
- unk_ev = 1;
- }
- if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
- printk(TPACPI_INFO
- "woke up due to a hot-unplug "
- "request...\n");
- hotkey_wakeup_reason_notify_change();
- }
+ /* 0x2000-0x2FFF: Wakeup reason */
+ known_ev = hotkey_notify_wakeup(hkey, &send_acpi_ev,
+ &ignore_acpi_ev);
break;
case 3:
- /* bay-related wakeups */
+ /* 0x3000-0x3FFF: bay-related wakeups */
if (hkey == 0x3003) {
hotkey_autosleep_ack = 1;
printk(TPACPI_INFO
"bay ejected\n");
hotkey_wakeup_hotunplug_complete_notify_change();
+ known_ev = true;
} else {
- unk_ev = 1;
+ known_ev = false;
}
break;
case 4:
- /* dock-related wakeups */
+ /* 0x4000-0x4FFF: dock-related wakeups */
if (hkey == 0x4003) {
hotkey_autosleep_ack = 1;
printk(TPACPI_INFO
"undocked\n");
hotkey_wakeup_hotunplug_complete_notify_change();
+ known_ev = true;
} else {
- unk_ev = 1;
+ known_ev = false;
}
break;
case 5:
/* 0x5000-0x5FFF: human interface helpers */
- switch (hkey) {
- case 0x5010: /* Lenovo new BIOS: brightness changed */
- case 0x500b: /* X61t: tablet pen inserted into bay */
- case 0x500c: /* X61t: tablet pen removed from bay */
- break;
- case 0x5009: /* X41t-X61t: swivel up (tablet mode) */
- case 0x500a: /* X41t-X61t: swivel down (normal mode) */
- tpacpi_input_send_tabletsw();
- hotkey_tablet_mode_notify_change();
- send_acpi_ev = 0;
- break;
- case 0x5001:
- case 0x5002:
- /* LID switch events. Do not propagate */
- ignore_acpi_ev = 1;
- break;
- default:
- unk_ev = 1;
- }
+ known_ev = hotkey_notify_usrevent(hkey, &send_acpi_ev,
+ &ignore_acpi_ev);
+ break;
+ case 6:
+ /* 0x6000-0x6FFF: thermal alarms */
+ known_ev = hotkey_notify_thermal(hkey, &send_acpi_ev,
+ &ignore_acpi_ev);
break;
case 7:
/* 0x7000-0x7FFF: misc */
if (tp_features.hotkey_wlsw && hkey == 0x7000) {
tpacpi_send_radiosw_update();
send_acpi_ev = 0;
+ known_ev = true;
break;
}
/* fallthrough to default */
default:
- unk_ev = 1;
+ known_ev = false;
}
- if (unk_ev) {
+ if (!known_ev) {
printk(TPACPI_NOTICE
"unhandled HKEY event 0x%04x\n", hkey);
+ printk(TPACPI_NOTICE
+ "please report the conditions when this "
+ "event happened to %s\n", TPACPI_MAIL);
}
/* Legacy events */
@@ -2506,7 +2823,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
if (!ignore_acpi_ev && send_acpi_ev) {
acpi_bus_generate_netlink_event(
ibm->acpi->device->pnp.device_class,
- ibm->acpi->device->dev.bus_id,
+ dev_name(&ibm->acpi->device->dev),
event, hkey);
}
}
@@ -2545,7 +2862,7 @@ static int hotkey_read(char *p)
return len;
}
- if (mutex_lock_interruptible(&hotkey_mutex))
+ if (mutex_lock_killable(&hotkey_mutex))
return -ERESTARTSYS;
res = hotkey_status_get(&status);
if (!res)
@@ -2576,7 +2893,7 @@ static int hotkey_write(char *buf)
if (!tp_features.hotkey)
return -ENODEV;
- if (mutex_lock_interruptible(&hotkey_mutex))
+ if (mutex_lock_killable(&hotkey_mutex))
return -ERESTARTSYS;
status = -1;
@@ -2641,11 +2958,28 @@ enum {
/* ACPI GBDC/SBDC bits */
TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */
- TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */
+ TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume:
+ off / last state */
+};
+
+enum {
+ /* ACPI \BLTH commands */
+ TP_ACPI_BLTH_GET_ULTRAPORT_ID = 0x00, /* Get Ultraport BT ID */
+ TP_ACPI_BLTH_GET_PWR_ON_RESUME = 0x01, /* Get power-on-resume state */
+ TP_ACPI_BLTH_PWR_ON_ON_RESUME = 0x02, /* Resume powered on */
+ TP_ACPI_BLTH_PWR_OFF_ON_RESUME = 0x03, /* Resume powered off */
+ TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */
};
static struct rfkill *tpacpi_bluetooth_rfkill;
+static void bluetooth_suspend(pm_message_t state)
+{
+ /* Try to make sure radio will resume powered off */
+ acpi_evalf(NULL, NULL, "\\BLTH", "vd",
+ TP_ACPI_BLTH_PWR_OFF_ON_RESUME);
+}
+
static int bluetooth_get_radiosw(void)
{
int status;
@@ -2657,6 +2991,12 @@ static int bluetooth_get_radiosw(void)
if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
return RFKILL_STATE_HARD_BLOCKED;
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_bluetoothemul)
+ return (tpacpi_bluetooth_emulstate) ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+#endif
+
if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
return -EIO;
@@ -2690,12 +3030,20 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk)
&& radio_on)
return -EPERM;
- if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
- return -EIO;
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_bluetoothemul) {
+ tpacpi_bluetooth_emulstate = !!radio_on;
+ if (update_rfk)
+ bluetooth_update_rfk();
+ return 0;
+ }
+#endif
+
+ /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
if (radio_on)
- status |= TP_ACPI_BLUETOOTH_RADIOSSW;
+ status = TP_ACPI_BLUETOOTH_RADIOSSW;
else
- status &= ~TP_ACPI_BLUETOOTH_RADIOSSW;
+ status = 0;
if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
return -EIO;
@@ -2766,8 +3114,19 @@ static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
}
+static void bluetooth_shutdown(void)
+{
+ /* Order firmware to save current state to NVRAM */
+ if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
+ TP_ACPI_BLTH_SAVE_STATE))
+ printk(TPACPI_NOTICE
+ "failed to save bluetooth state to NVRAM\n");
+}
+
static void bluetooth_exit(void)
{
+ bluetooth_shutdown();
+
if (tpacpi_bluetooth_rfkill)
rfkill_unregister(tpacpi_bluetooth_rfkill);
@@ -2793,6 +3152,13 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
str_supported(tp_features.bluetooth),
status);
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_bluetoothemul) {
+ tp_features.bluetooth = 1;
+ printk(TPACPI_INFO
+ "bluetooth switch emulation enabled\n");
+ } else
+#endif
if (tp_features.bluetooth &&
!(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
/* no bluetooth hardware present in system */
@@ -2813,6 +3179,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
&tpacpi_bluetooth_rfkill,
RFKILL_TYPE_BLUETOOTH,
"tpacpi_bluetooth_sw",
+ true,
tpacpi_bluetooth_rfk_set,
tpacpi_bluetooth_rfk_get);
if (res) {
@@ -2865,6 +3232,8 @@ static struct ibm_struct bluetooth_driver_data = {
.read = bluetooth_read,
.write = bluetooth_write,
.exit = bluetooth_exit,
+ .suspend = bluetooth_suspend,
+ .shutdown = bluetooth_shutdown,
};
/*************************************************************************
@@ -2875,11 +3244,19 @@ enum {
/* ACPI GWAN/SWAN bits */
TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */
- TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */
+ TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume:
+ off / last state */
};
static struct rfkill *tpacpi_wan_rfkill;
+static void wan_suspend(pm_message_t state)
+{
+ /* Try to make sure radio will resume powered off */
+ acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
+ TP_ACPI_WGSV_PWR_OFF_ON_RESUME);
+}
+
static int wan_get_radiosw(void)
{
int status;
@@ -2891,6 +3268,12 @@ static int wan_get_radiosw(void)
if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
return RFKILL_STATE_HARD_BLOCKED;
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_wwanemul)
+ return (tpacpi_wwan_emulstate) ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+#endif
+
if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
return -EIO;
@@ -2924,12 +3307,20 @@ static int wan_set_radiosw(int radio_on, int update_rfk)
&& radio_on)
return -EPERM;
- if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
- return -EIO;
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_wwanemul) {
+ tpacpi_wwan_emulstate = !!radio_on;
+ if (update_rfk)
+ wan_update_rfk();
+ return 0;
+ }
+#endif
+
+ /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
if (radio_on)
- status |= TP_ACPI_WANCARD_RADIOSSW;
+ status = TP_ACPI_WANCARD_RADIOSSW;
else
- status &= ~TP_ACPI_WANCARD_RADIOSSW;
+ status = 0;
if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
return -EIO;
@@ -3000,8 +3391,19 @@ static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
}
+static void wan_shutdown(void)
+{
+ /* Order firmware to save current state to NVRAM */
+ if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd",
+ TP_ACPI_WGSV_SAVE_STATE))
+ printk(TPACPI_NOTICE
+ "failed to save WWAN state to NVRAM\n");
+}
+
static void wan_exit(void)
{
+ wan_shutdown();
+
if (tpacpi_wan_rfkill)
rfkill_unregister(tpacpi_wan_rfkill);
@@ -3025,6 +3427,13 @@ static int __init wan_init(struct ibm_init_struct *iibm)
str_supported(tp_features.wan),
status);
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_wwanemul) {
+ tp_features.wan = 1;
+ printk(TPACPI_INFO
+ "wwan switch emulation enabled\n");
+ } else
+#endif
if (tp_features.wan &&
!(status & TP_ACPI_WANCARD_HWPRESENT)) {
/* no wan hardware present in system */
@@ -3045,6 +3454,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
&tpacpi_wan_rfkill,
RFKILL_TYPE_WWAN,
"tpacpi_wwan_sw",
+ true,
tpacpi_wan_rfk_set,
tpacpi_wan_rfk_get);
if (res) {
@@ -3097,6 +3507,164 @@ static struct ibm_struct wan_driver_data = {
.read = wan_read,
.write = wan_write,
.exit = wan_exit,
+ .suspend = wan_suspend,
+ .shutdown = wan_shutdown,
+};
+
+/*************************************************************************
+ * UWB subdriver
+ */
+
+enum {
+ /* ACPI GUWB/SUWB bits */
+ TP_ACPI_UWB_HWPRESENT = 0x01, /* UWB hw available */
+ TP_ACPI_UWB_RADIOSSW = 0x02, /* UWB radio enabled */
+};
+
+static struct rfkill *tpacpi_uwb_rfkill;
+
+static int uwb_get_radiosw(void)
+{
+ int status;
+
+ if (!tp_features.uwb)
+ return -ENODEV;
+
+ /* WLSW overrides UWB in firmware/hardware, reflect that */
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
+ return RFKILL_STATE_HARD_BLOCKED;
+
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_uwbemul)
+ return (tpacpi_uwb_emulstate) ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+#endif
+
+ if (!acpi_evalf(hkey_handle, &status, "GUWB", "d"))
+ return -EIO;
+
+ return ((status & TP_ACPI_UWB_RADIOSSW) != 0) ?
+ RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
+}
+
+static void uwb_update_rfk(void)
+{
+ int status;
+
+ if (!tpacpi_uwb_rfkill)
+ return;
+
+ status = uwb_get_radiosw();
+ if (status < 0)
+ return;
+ rfkill_force_state(tpacpi_uwb_rfkill, status);
+}
+
+static int uwb_set_radiosw(int radio_on, int update_rfk)
+{
+ int status;
+
+ if (!tp_features.uwb)
+ return -ENODEV;
+
+ /* WLSW overrides UWB in firmware/hardware, but there is no
+ * reason to risk weird behaviour. */
+ if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
+ && radio_on)
+ return -EPERM;
+
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_uwbemul) {
+ tpacpi_uwb_emulstate = !!radio_on;
+ if (update_rfk)
+ uwb_update_rfk();
+ return 0;
+ }
+#endif
+
+ status = (radio_on) ? TP_ACPI_UWB_RADIOSSW : 0;
+ if (!acpi_evalf(hkey_handle, NULL, "SUWB", "vd", status))
+ return -EIO;
+
+ if (update_rfk)
+ uwb_update_rfk();
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state)
+{
+ int uwbs = uwb_get_radiosw();
+
+ if (uwbs < 0)
+ return uwbs;
+
+ *state = uwbs;
+ return 0;
+}
+
+static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state)
+{
+ return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
+}
+
+static void uwb_exit(void)
+{
+ if (tpacpi_uwb_rfkill)
+ rfkill_unregister(tpacpi_uwb_rfkill);
+}
+
+static int __init uwb_init(struct ibm_init_struct *iibm)
+{
+ int res;
+ int status = 0;
+
+ vdbg_printk(TPACPI_DBG_INIT, "initializing uwb subdriver\n");
+
+ TPACPI_ACPIHANDLE_INIT(hkey);
+
+ tp_features.uwb = hkey_handle &&
+ acpi_evalf(hkey_handle, &status, "GUWB", "qd");
+
+ vdbg_printk(TPACPI_DBG_INIT, "uwb is %s, status 0x%02x\n",
+ str_supported(tp_features.uwb),
+ status);
+
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+ if (dbg_uwbemul) {
+ tp_features.uwb = 1;
+ printk(TPACPI_INFO
+ "uwb switch emulation enabled\n");
+ } else
+#endif
+ if (tp_features.uwb &&
+ !(status & TP_ACPI_UWB_HWPRESENT)) {
+ /* no uwb hardware present in system */
+ tp_features.uwb = 0;
+ dbg_printk(TPACPI_DBG_INIT,
+ "uwb hardware not installed\n");
+ }
+
+ if (!tp_features.uwb)
+ return 1;
+
+ res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID,
+ &tpacpi_uwb_rfkill,
+ RFKILL_TYPE_UWB,
+ "tpacpi_uwb_sw",
+ false,
+ tpacpi_uwb_rfk_set,
+ tpacpi_uwb_rfk_get);
+
+ return res;
+}
+
+static struct ibm_struct uwb_driver_data = {
+ .name = "uwb",
+ .exit = uwb_exit,
+ .flags.experimental = 1,
};
/*************************************************************************
@@ -3725,7 +4293,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
}
acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
- ibm->acpi->device->dev.bus_id,
+ dev_name(&ibm->acpi->device->dev),
event, data);
}
@@ -3827,7 +4395,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event)
{
acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
- ibm->acpi->device->dev.bus_id,
+ dev_name(&ibm->acpi->device->dev),
event, 0);
}
@@ -4851,7 +5419,7 @@ static int brightness_set(int value)
value < 0)
return -EINVAL;
- res = mutex_lock_interruptible(&brightness_mutex);
+ res = mutex_lock_killable(&brightness_mutex);
if (res < 0)
return res;
@@ -5335,6 +5903,60 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */
); /* all others */
/*
+ * Unitialized HFSP quirk: ACPI DSDT and EC fail to initialize the
+ * HFSP register at boot, so it contains 0x07 but the Thinkpad could
+ * be in auto mode (0x80).
+ *
+ * This is corrected by any write to HFSP either by the driver, or
+ * by the firmware.
+ *
+ * We assume 0x07 really means auto mode while this quirk is active,
+ * as this is far more likely than the ThinkPad being in level 7,
+ * which is only used by the firmware during thermal emergencies.
+ */
+
+static void fan_quirk1_detect(void)
+{
+ /* In some ThinkPads, neither the EC nor the ACPI
+ * DSDT initialize the HFSP register, and it ends up
+ * being initially set to 0x07 when it *could* be
+ * either 0x07 or 0x80.
+ *
+ * Enable for TP-1Y (T43), TP-78 (R51e),
+ * TP-76 (R52), TP-70 (T43, R52), which are known
+ * to be buggy. */
+ if (fan_control_initial_status == 0x07) {
+ switch (thinkpad_id.ec_model) {
+ case 0x5931: /* TP-1Y */
+ case 0x3837: /* TP-78 */
+ case 0x3637: /* TP-76 */
+ case 0x3037: /* TP-70 */
+ printk(TPACPI_NOTICE
+ "fan_init: initial fan status is unknown, "
+ "assuming it is in auto mode\n");
+ tp_features.fan_ctrl_status_undef = 1;
+ ;;
+ }
+ }
+}
+
+static void fan_quirk1_handle(u8 *fan_status)
+{
+ if (unlikely(tp_features.fan_ctrl_status_undef)) {
+ if (*fan_status != fan_control_initial_status) {
+ /* something changed the HFSP regisnter since
+ * driver init time, so it is not undefined
+ * anymore */
+ tp_features.fan_ctrl_status_undef = 0;
+ } else {
+ /* Return most likely status. In fact, it
+ * might be the only possible status */
+ *fan_status = TP_EC_FAN_AUTO;
+ }
+ }
+}
+
+/*
* Call with fan_mutex held
*/
static void fan_update_desired_level(u8 status)
@@ -5372,8 +5994,10 @@ static int fan_get_status(u8 *status)
if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
return -EIO;
- if (likely(status))
+ if (likely(status)) {
*status = s;
+ fan_quirk1_handle(status);
+ }
break;
@@ -5389,7 +6013,7 @@ static int fan_get_status_safe(u8 *status)
int rc;
u8 s;
- if (mutex_lock_interruptible(&fan_mutex))
+ if (mutex_lock_killable(&fan_mutex))
return -ERESTARTSYS;
rc = fan_get_status(&s);
if (!rc)
@@ -5472,7 +6096,7 @@ static int fan_set_level_safe(int level)
if (!fan_control_allowed)
return -EPERM;
- if (mutex_lock_interruptible(&fan_mutex))
+ if (mutex_lock_killable(&fan_mutex))
return -ERESTARTSYS;
if (level == TPACPI_FAN_LAST_LEVEL)
@@ -5494,7 +6118,7 @@ static int fan_set_enable(void)
if (!fan_control_allowed)
return -EPERM;
- if (mutex_lock_interruptible(&fan_mutex))
+ if (mutex_lock_killable(&fan_mutex))
return -ERESTARTSYS;
switch (fan_control_access_mode) {
@@ -5549,7 +6173,7 @@ static int fan_set_disable(void)
if (!fan_control_allowed)
return -EPERM;
- if (mutex_lock_interruptible(&fan_mutex))
+ if (mutex_lock_killable(&fan_mutex))
return -ERESTARTSYS;
rc = 0;
@@ -5587,7 +6211,7 @@ static int fan_set_speed(int speed)
if (!fan_control_allowed)
return -EPERM;
- if (mutex_lock_interruptible(&fan_mutex))
+ if (mutex_lock_killable(&fan_mutex))
return -ERESTARTSYS;
rc = 0;
@@ -5683,16 +6307,6 @@ static ssize_t fan_pwm1_enable_show(struct device *dev,
if (res)
return res;
- if (unlikely(tp_features.fan_ctrl_status_undef)) {
- if (status != fan_control_initial_status) {
- tp_features.fan_ctrl_status_undef = 0;
- } else {
- /* Return most likely status. In fact, it
- * might be the only possible status */
- status = TP_EC_FAN_AUTO;
- }
- }
-
if (status & TP_EC_FAN_FULLSPEED) {
mode = 0;
} else if (status & TP_EC_FAN_AUTO) {
@@ -5757,14 +6371,6 @@ static ssize_t fan_pwm1_show(struct device *dev,
if (res)
return res;
- if (unlikely(tp_features.fan_ctrl_status_undef)) {
- if (status != fan_control_initial_status) {
- tp_features.fan_ctrl_status_undef = 0;
- } else {
- status = TP_EC_FAN_AUTO;
- }
- }
-
if ((status &
(TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0)
status = fan_control_desired_level;
@@ -5789,7 +6395,7 @@ static ssize_t fan_pwm1_store(struct device *dev,
/* scale down from 0-255 to 0-7 */
newlevel = (s >> 5) & 0x07;
- if (mutex_lock_interruptible(&fan_mutex))
+ if (mutex_lock_killable(&fan_mutex))
return -ERESTARTSYS;
rc = fan_get_status(&status);
@@ -5896,29 +6502,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
if (likely(acpi_ec_read(fan_status_offset,
&fan_control_initial_status))) {
fan_status_access_mode = TPACPI_FAN_RD_TPEC;
-
- /* In some ThinkPads, neither the EC nor the ACPI
- * DSDT initialize the fan status, and it ends up
- * being set to 0x07 when it *could* be either
- * 0x07 or 0x80.
- *
- * Enable for TP-1Y (T43), TP-78 (R51e),
- * TP-76 (R52), TP-70 (T43, R52), which are known
- * to be buggy. */
- if (fan_control_initial_status == 0x07) {
- switch (thinkpad_id.ec_model) {
- case 0x5931: /* TP-1Y */
- case 0x3837: /* TP-78 */
- case 0x3637: /* TP-76 */
- case 0x3037: /* TP-70 */
- printk(TPACPI_NOTICE
- "fan_init: initial fan status "
- "is unknown, assuming it is "
- "in auto mode\n");
- tp_features.fan_ctrl_status_undef = 1;
- ;;
- }
- }
+ fan_quirk1_detect();
} else {
printk(TPACPI_ERR
"ThinkPad ACPI EC access misbehaving, "
@@ -6107,15 +6691,6 @@ static int fan_read(char *p)
if (rc < 0)
return rc;
- if (unlikely(tp_features.fan_ctrl_status_undef)) {
- if (status != fan_control_initial_status)
- tp_features.fan_ctrl_status_undef = 0;
- else
- /* Return most likely status. In fact, it
- * might be the only possible status */
- status = TP_EC_FAN_AUTO;
- }
-
len += sprintf(p + len, "status:\t\t%s\n",
(status != 0) ? "enabled" : "disabled");
@@ -6564,6 +7139,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
.init = wan_init,
.data = &wan_driver_data,
},
+ {
+ .init = uwb_init,
+ .data = &uwb_driver_data,
+ },
#ifdef CONFIG_THINKPAD_ACPI_VIDEO
{
.init = video_init,
@@ -6702,6 +7281,32 @@ TPACPI_PARAM(brightness);
TPACPI_PARAM(volume);
TPACPI_PARAM(fan);
+#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
+module_param(dbg_wlswemul, uint, 0);
+MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
+module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
+MODULE_PARM_DESC(wlsw_state,
+ "Initial state of the emulated WLSW switch");
+
+module_param(dbg_bluetoothemul, uint, 0);
+MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
+module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
+MODULE_PARM_DESC(bluetooth_state,
+ "Initial state of the emulated bluetooth switch");
+
+module_param(dbg_wwanemul, uint, 0);
+MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
+module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
+MODULE_PARM_DESC(wwan_state,
+ "Initial state of the emulated WWAN switch");
+
+module_param(dbg_uwbemul, uint, 0);
+MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
+module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
+MODULE_PARM_DESC(uwb_state,
+ "Initial state of the emulated UWB switch");
+#endif
+
static void thinkpad_acpi_module_exit(void)
{
struct ibm_struct *ibm, *itmp;
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 40e60fc2e596..40e60fc2e596 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
diff --git a/drivers/acpi/wmi.c b/drivers/platform/x86/wmi.c
index 8a8b377712c9..8a8b377712c9 100644
--- a/drivers/acpi/wmi.c
+++ b/drivers/platform/x86/wmi.c
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index e75b060daa95..efea128f02da 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -165,8 +165,7 @@ struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnp
card->number = id;
card->dev.parent = &card->protocol->dev;
- sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
- card->number);
+ dev_set_name(&card->dev, "%02x:%02x", card->protocol->number, card->number);
card->dev.coherent_dma_mask = DMA_24BIT_MASK;
card->dev.dma_mask = &card->dev.coherent_dma_mask;
@@ -295,8 +294,8 @@ int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev)
{
dev->dev.parent = &card->dev;
dev->card_link = NULL;
- snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x",
- dev->protocol->number, card->number, dev->number);
+ dev_set_name(&dev->dev, "%02x:%02x.%02x",
+ dev->protocol->number, card->number, dev->number);
spin_lock(&pnp_lock);
dev->card = card;
list_add_tail(&dev->card_list, &card->devices);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index 16c01c6fa7c5..14814f231739 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -70,7 +70,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol)
spin_unlock(&pnp_lock);
protocol->number = nodenum;
- sprintf(protocol->dev.bus_id, "pnp%d", nodenum);
+ dev_set_name(&protocol->dev, "pnp%d", nodenum);
return device_register(&protocol->dev);
}
@@ -145,8 +145,7 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid
dev->dev.coherent_dma_mask = dev->dma_mask;
dev->dev.release = &pnp_release_device;
- sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
- dev->number);
+ dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number);
dev_id = pnp_add_id(dev, pnpid);
if (!dev_id) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 383e47c392a4..2834846a185d 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -23,7 +23,6 @@
#include <linux/pnp.h>
#include <linux/mod_devicetable.h>
#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
#include "../base.h"
#include "pnpacpi.h"
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index 7ff824496b39..7e6b5a3b3281 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -481,7 +481,7 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header)
set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
- for (i = 0; i < NR_CPUS; i++) {
+ for_each_possible_cpu(i) {
struct desc_struct *gdt = get_cpu_gdt_table(i);
if (!gdt)
continue;
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index 764f3a310685..59b90922da8c 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -26,7 +26,7 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start,
resource_size_t end, int port)
{
char *regionid;
- const char *pnpid = dev->dev.bus_id;
+ const char *pnpid = dev_name(&dev->dev);
struct resource *res;
regionid = kmalloc(16, GFP_KERNEL);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 8e0c2b47803c..33da1127992a 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -29,6 +29,13 @@ config APM_POWER
Say Y here to enable support APM status emulation using
battery class devices.
+config WM8350_POWER
+ tristate "WM8350 PMU support"
+ depends on MFD_WM8350
+ help
+ Say Y here to enable support for the power management unit
+ provided by the Wolfson Microelectronics WM8350 PMIC.
+
config BATTERY_DS2760
tristate "DS2760 battery driver (HP iPAQ & others)"
select W1
@@ -68,4 +75,17 @@ config BATTERY_BQ27x00
help
Say Y here to enable support for batteries with BQ27200(I2C) chip.
+config BATTERY_DA9030
+ tristate "DA9030 battery driver"
+ depends on PMIC_DA903X
+ help
+ Say Y here to enable support for batteries charger integrated into
+ DA9030 PMIC.
+
+config CHARGER_PCF50633
+ tristate "NXP PCF50633 MBC"
+ depends on MFD_PCF50633
+ help
+ Say Y to include support for NXP PCF50633 Main Battery Charger.
+
endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index e8f1ecec5d8f..2fcf41d13e5c 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
obj-$(CONFIG_PDA_POWER) += pda_power.o
obj-$(CONFIG_APM_POWER) += apm_power.o
+obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
@@ -23,3 +24,5 @@ obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
+obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
+obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o \ No newline at end of file
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
new file mode 100644
index 000000000000..1662bb0f23a5
--- /dev/null
+++ b/drivers/power/da9030_battery.c
@@ -0,0 +1,600 @@
+/*
+ * Battery charger driver for Dialog Semiconductor DA9030
+ *
+ * Copyright (C) 2008 Compulab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/da903x.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#define DA9030_STATUS_CHDET (1 << 3)
+
+#define DA9030_FAULT_LOG 0x0a
+#define DA9030_FAULT_LOG_OVER_TEMP (1 << 7)
+#define DA9030_FAULT_LOG_VBAT_OVER (1 << 4)
+
+#define DA9030_CHARGE_CONTROL 0x28
+#define DA9030_CHRG_CHARGER_ENABLE (1 << 7)
+
+#define DA9030_ADC_MAN_CONTROL 0x30
+#define DA9030_ADC_TBATREF_ENABLE (1 << 5)
+#define DA9030_ADC_LDO_INT_ENABLE (1 << 4)
+
+#define DA9030_ADC_AUTO_CONTROL 0x31
+#define DA9030_ADC_TBAT_ENABLE (1 << 5)
+#define DA9030_ADC_VBAT_IN_TXON (1 << 4)
+#define DA9030_ADC_VCH_ENABLE (1 << 3)
+#define DA9030_ADC_ICH_ENABLE (1 << 2)
+#define DA9030_ADC_VBAT_ENABLE (1 << 1)
+#define DA9030_ADC_AUTO_SLEEP_ENABLE (1 << 0)
+
+#define DA9030_VBATMON 0x32
+#define DA9030_VBATMONTXON 0x33
+#define DA9030_TBATHIGHP 0x34
+#define DA9030_TBATHIGHN 0x35
+#define DA9030_TBATLOW 0x36
+
+#define DA9030_VBAT_RES 0x41
+#define DA9030_VBATMIN_RES 0x42
+#define DA9030_VBATMINTXON_RES 0x43
+#define DA9030_ICHMAX_RES 0x44
+#define DA9030_ICHMIN_RES 0x45
+#define DA9030_ICHAVERAGE_RES 0x46
+#define DA9030_VCHMAX_RES 0x47
+#define DA9030_VCHMIN_RES 0x48
+#define DA9030_TBAT_RES 0x49
+
+struct da9030_adc_res {
+ uint8_t vbat_res;
+ uint8_t vbatmin_res;
+ uint8_t vbatmintxon;
+ uint8_t ichmax_res;
+ uint8_t ichmin_res;
+ uint8_t ichaverage_res;
+ uint8_t vchmax_res;
+ uint8_t vchmin_res;
+ uint8_t tbat_res;
+ uint8_t adc_in4_res;
+ uint8_t adc_in5_res;
+};
+
+struct da9030_battery_thresholds {
+ int tbat_low;
+ int tbat_high;
+ int tbat_restart;
+
+ int vbat_low;
+ int vbat_crit;
+ int vbat_charge_start;
+ int vbat_charge_stop;
+ int vbat_charge_restart;
+
+ int vcharge_min;
+ int vcharge_max;
+};
+
+struct da9030_charger {
+ struct power_supply psy;
+
+ struct device *master;
+
+ struct da9030_adc_res adc;
+ struct delayed_work work;
+ unsigned int interval;
+
+ struct power_supply_info *battery_info;
+
+ struct da9030_battery_thresholds thresholds;
+
+ unsigned int charge_milliamp;
+ unsigned int charge_millivolt;
+
+ /* charger status */
+ bool chdet;
+ uint8_t fault;
+ int mA;
+ int mV;
+ bool is_on;
+
+ struct notifier_block nb;
+
+ /* platform callbacks for battery low and critical events */
+ void (*battery_low)(void);
+ void (*battery_critical)(void);
+
+ struct dentry *debug_file;
+};
+
+static inline int da9030_reg_to_mV(int reg)
+{
+ return ((reg * 2650) >> 8) + 2650;
+}
+
+static inline int da9030_millivolt_to_reg(int mV)
+{
+ return ((mV - 2650) << 8) / 2650;
+}
+
+static inline int da9030_reg_to_mA(int reg)
+{
+ return ((reg * 24000) >> 8) / 15;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int bat_debug_show(struct seq_file *s, void *data)
+{
+ struct da9030_charger *charger = s->private;
+
+ seq_printf(s, "charger is %s\n", charger->is_on ? "on" : "off");
+ if (charger->chdet) {
+ seq_printf(s, "iset = %dmA, vset = %dmV\n",
+ charger->mA, charger->mV);
+ }
+
+ seq_printf(s, "vbat_res = %d (%dmV)\n",
+ charger->adc.vbat_res,
+ da9030_reg_to_mV(charger->adc.vbat_res));
+ seq_printf(s, "vbatmin_res = %d (%dmV)\n",
+ charger->adc.vbatmin_res,
+ da9030_reg_to_mV(charger->adc.vbatmin_res));
+ seq_printf(s, "vbatmintxon = %d (%dmV)\n",
+ charger->adc.vbatmintxon,
+ da9030_reg_to_mV(charger->adc.vbatmintxon));
+ seq_printf(s, "ichmax_res = %d (%dmA)\n",
+ charger->adc.ichmax_res,
+ da9030_reg_to_mV(charger->adc.ichmax_res));
+ seq_printf(s, "ichmin_res = %d (%dmA)\n",
+ charger->adc.ichmin_res,
+ da9030_reg_to_mA(charger->adc.ichmin_res));
+ seq_printf(s, "ichaverage_res = %d (%dmA)\n",
+ charger->adc.ichaverage_res,
+ da9030_reg_to_mA(charger->adc.ichaverage_res));
+ seq_printf(s, "vchmax_res = %d (%dmV)\n",
+ charger->adc.vchmax_res,
+ da9030_reg_to_mA(charger->adc.vchmax_res));
+ seq_printf(s, "vchmin_res = %d (%dmV)\n",
+ charger->adc.vchmin_res,
+ da9030_reg_to_mV(charger->adc.vchmin_res));
+
+ return 0;
+}
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, bat_debug_show, inode->i_private);
+}
+
+static const struct file_operations bat_debug_fops = {
+ .open = debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
+{
+ charger->debug_file = debugfs_create_file("charger", 0666, 0, charger,
+ &bat_debug_fops);
+ return charger->debug_file;
+}
+
+static void da9030_bat_remove_debugfs(struct da9030_charger *charger)
+{
+ debugfs_remove(charger->debug_file);
+}
+#else
+static inline struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
+{
+ return NULL;
+}
+static inline void da9030_bat_remove_debugfs(struct da9030_charger *charger)
+{
+}
+#endif
+
+static inline void da9030_read_adc(struct da9030_charger *charger,
+ struct da9030_adc_res *adc)
+{
+ da903x_reads(charger->master, DA9030_VBAT_RES,
+ sizeof(*adc), (uint8_t *)adc);
+}
+
+static void da9030_charger_update_state(struct da9030_charger *charger)
+{
+ uint8_t val;
+
+ da903x_read(charger->master, DA9030_CHARGE_CONTROL, &val);
+ charger->is_on = (val & DA9030_CHRG_CHARGER_ENABLE) ? 1 : 0;
+ charger->mA = ((val >> 3) & 0xf) * 100;
+ charger->mV = (val & 0x7) * 50 + 4000;
+
+ da9030_read_adc(charger, &charger->adc);
+ da903x_read(charger->master, DA9030_FAULT_LOG, &charger->fault);
+ charger->chdet = da903x_query_status(charger->master,
+ DA9030_STATUS_CHDET);
+}
+
+static void da9030_set_charge(struct da9030_charger *charger, int on)
+{
+ uint8_t val;
+
+ if (on) {
+ val = DA9030_CHRG_CHARGER_ENABLE;
+ val |= (charger->charge_milliamp / 100) << 3;
+ val |= (charger->charge_millivolt - 4000) / 50;
+ charger->is_on = 1;
+ } else {
+ val = 0;
+ charger->is_on = 0;
+ }
+
+ da903x_write(charger->master, DA9030_CHARGE_CONTROL, val);
+}
+
+static void da9030_charger_check_state(struct da9030_charger *charger)
+{
+ da9030_charger_update_state(charger);
+
+ /* we wake or boot with external power on */
+ if (!charger->is_on) {
+ if ((charger->chdet) &&
+ (charger->adc.vbat_res <
+ charger->thresholds.vbat_charge_start)) {
+ da9030_set_charge(charger, 1);
+ }
+ } else {
+ if (charger->adc.vbat_res >=
+ charger->thresholds.vbat_charge_stop) {
+ da9030_set_charge(charger, 0);
+ da903x_write(charger->master, DA9030_VBATMON,
+ charger->thresholds.vbat_charge_restart);
+ } else if (charger->adc.vbat_res >
+ charger->thresholds.vbat_low) {
+ /* we are charging and passed LOW_THRESH,
+ so upate DA9030 VBAT threshold
+ */
+ da903x_write(charger->master, DA9030_VBATMON,
+ charger->thresholds.vbat_low);
+ }
+ if (charger->adc.vchmax_res > charger->thresholds.vcharge_max ||
+ charger->adc.vchmin_res < charger->thresholds.vcharge_min ||
+ /* Tempreture readings are negative */
+ charger->adc.tbat_res < charger->thresholds.tbat_high ||
+ charger->adc.tbat_res > charger->thresholds.tbat_low) {
+ /* disable charger */
+ da9030_set_charge(charger, 0);
+ }
+ }
+}
+
+static void da9030_charging_monitor(struct work_struct *work)
+{
+ struct da9030_charger *charger;
+
+ charger = container_of(work, struct da9030_charger, work.work);
+
+ da9030_charger_check_state(charger);
+
+ /* reschedule for the next time */
+ schedule_delayed_work(&charger->work, charger->interval);
+}
+
+static enum power_supply_property da9030_battery_props[] = {
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+};
+
+static void da9030_battery_check_status(struct da9030_charger *charger,
+ union power_supply_propval *val)
+{
+ if (charger->chdet) {
+ if (charger->is_on)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+}
+
+static void da9030_battery_check_health(struct da9030_charger *charger,
+ union power_supply_propval *val)
+{
+ if (charger->fault & DA9030_FAULT_LOG_OVER_TEMP)
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ else if (charger->fault & DA9030_FAULT_LOG_VBAT_OVER)
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+}
+
+static int da9030_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct da9030_charger *charger;
+ charger = container_of(psy, struct da9030_charger, psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ da9030_battery_check_status(charger, val);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ da9030_battery_check_health(charger, val);
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = charger->battery_info->technology;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ val->intval = charger->battery_info->voltage_max_design;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = charger->battery_info->voltage_min_design;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = da9030_reg_to_mV(charger->adc.vbat_res) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval =
+ da9030_reg_to_mA(charger->adc.ichaverage_res) * 1000;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = charger->battery_info->name;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void da9030_battery_vbat_event(struct da9030_charger *charger)
+{
+ da9030_read_adc(charger, &charger->adc);
+
+ if (charger->is_on)
+ return;
+
+ if (charger->adc.vbat_res < charger->thresholds.vbat_low) {
+ /* set VBAT threshold for critical */
+ da903x_write(charger->master, DA9030_VBATMON,
+ charger->thresholds.vbat_crit);
+ if (charger->battery_low)
+ charger->battery_low();
+ } else if (charger->adc.vbat_res <
+ charger->thresholds.vbat_crit) {
+ /* notify the system of battery critical */
+ if (charger->battery_critical)
+ charger->battery_critical();
+ }
+}
+
+static int da9030_battery_event(struct notifier_block *nb, unsigned long event,
+ void *data)
+{
+ struct da9030_charger *charger =
+ container_of(nb, struct da9030_charger, nb);
+ int status;
+
+ switch (event) {
+ case DA9030_EVENT_CHDET:
+ status = da903x_query_status(charger->master,
+ DA9030_STATUS_CHDET);
+ da9030_set_charge(charger, status);
+ break;
+ case DA9030_EVENT_VBATMON:
+ da9030_battery_vbat_event(charger);
+ break;
+ case DA9030_EVENT_CHIOVER:
+ case DA9030_EVENT_TBAT:
+ da9030_set_charge(charger, 0);
+ break;
+ }
+
+ return 0;
+}
+
+static void da9030_battery_convert_thresholds(struct da9030_charger *charger,
+ struct da9030_battery_info *pdata)
+{
+ charger->thresholds.tbat_low = pdata->tbat_low;
+ charger->thresholds.tbat_high = pdata->tbat_high;
+ charger->thresholds.tbat_restart = pdata->tbat_restart;
+
+ charger->thresholds.vbat_low =
+ da9030_millivolt_to_reg(pdata->vbat_low);
+ charger->thresholds.vbat_crit =
+ da9030_millivolt_to_reg(pdata->vbat_crit);
+ charger->thresholds.vbat_charge_start =
+ da9030_millivolt_to_reg(pdata->vbat_charge_start);
+ charger->thresholds.vbat_charge_stop =
+ da9030_millivolt_to_reg(pdata->vbat_charge_stop);
+ charger->thresholds.vbat_charge_restart =
+ da9030_millivolt_to_reg(pdata->vbat_charge_restart);
+
+ charger->thresholds.vcharge_min =
+ da9030_millivolt_to_reg(pdata->vcharge_min);
+ charger->thresholds.vcharge_max =
+ da9030_millivolt_to_reg(pdata->vcharge_max);
+}
+
+static void da9030_battery_setup_psy(struct da9030_charger *charger)
+{
+ struct power_supply *psy = &charger->psy;
+ struct power_supply_info *info = charger->battery_info;
+
+ psy->name = info->name;
+ psy->use_for_apm = info->use_for_apm;
+ psy->type = POWER_SUPPLY_TYPE_BATTERY;
+ psy->get_property = da9030_battery_get_property;
+
+ psy->properties = da9030_battery_props;
+ psy->num_properties = ARRAY_SIZE(da9030_battery_props);
+};
+
+static int da9030_battery_charger_init(struct da9030_charger *charger)
+{
+ char v[5];
+ int ret;
+
+ v[0] = v[1] = charger->thresholds.vbat_low;
+ v[2] = charger->thresholds.tbat_high;
+ v[3] = charger->thresholds.tbat_restart;
+ v[4] = charger->thresholds.tbat_low;
+
+ ret = da903x_writes(charger->master, DA9030_VBATMON, 5, v);
+ if (ret)
+ return ret;
+
+ /*
+ * Enable reference voltage supply for ADC from the LDO_INTERNAL
+ * regulator. Must be set before ADC measurements can be made.
+ */
+ ret = da903x_write(charger->master, DA9030_ADC_MAN_CONTROL,
+ DA9030_ADC_LDO_INT_ENABLE |
+ DA9030_ADC_TBATREF_ENABLE);
+ if (ret)
+ return ret;
+
+ /* enable auto ADC measuremnts */
+ return da903x_write(charger->master, DA9030_ADC_AUTO_CONTROL,
+ DA9030_ADC_TBAT_ENABLE | DA9030_ADC_VBAT_IN_TXON |
+ DA9030_ADC_VCH_ENABLE | DA9030_ADC_ICH_ENABLE |
+ DA9030_ADC_VBAT_ENABLE |
+ DA9030_ADC_AUTO_SLEEP_ENABLE);
+}
+
+static int da9030_battery_probe(struct platform_device *pdev)
+{
+ struct da9030_charger *charger;
+ struct da9030_battery_info *pdata = pdev->dev.platform_data;
+ int ret;
+
+ if (pdata == NULL)
+ return -EINVAL;
+
+ if (pdata->charge_milliamp >= 1500 ||
+ pdata->charge_millivolt < 4000 ||
+ pdata->charge_millivolt > 4350)
+ return -EINVAL;
+
+ charger = kzalloc(sizeof(*charger), GFP_KERNEL);
+ if (charger == NULL)
+ return -ENOMEM;
+
+ charger->master = pdev->dev.parent;
+
+ /* 10 seconds between monotor runs unless platfrom defines other
+ interval */
+ charger->interval = msecs_to_jiffies(
+ (pdata->batmon_interval ? : 10) * 1000);
+
+ charger->charge_milliamp = pdata->charge_milliamp;
+ charger->charge_millivolt = pdata->charge_millivolt;
+ charger->battery_info = pdata->battery_info;
+ charger->battery_low = pdata->battery_low;
+ charger->battery_critical = pdata->battery_critical;
+
+ da9030_battery_convert_thresholds(charger, pdata);
+
+ ret = da9030_battery_charger_init(charger);
+ if (ret)
+ goto err_charger_init;
+
+ INIT_DELAYED_WORK(&charger->work, da9030_charging_monitor);
+ schedule_delayed_work(&charger->work, charger->interval);
+
+ charger->nb.notifier_call = da9030_battery_event;
+ ret = da903x_register_notifier(charger->master, &charger->nb,
+ DA9030_EVENT_CHDET |
+ DA9030_EVENT_VBATMON |
+ DA9030_EVENT_CHIOVER |
+ DA9030_EVENT_TBAT);
+ if (ret)
+ goto err_notifier;
+
+ da9030_battery_setup_psy(charger);
+ ret = power_supply_register(&pdev->dev, &charger->psy);
+ if (ret)
+ goto err_ps_register;
+
+ charger->debug_file = da9030_bat_create_debugfs(charger);
+ platform_set_drvdata(pdev, charger);
+ return 0;
+
+err_ps_register:
+ da903x_unregister_notifier(charger->master, &charger->nb,
+ DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
+ DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
+err_notifier:
+ cancel_delayed_work(&charger->work);
+
+err_charger_init:
+ kfree(charger);
+
+ return ret;
+}
+
+static int da9030_battery_remove(struct platform_device *dev)
+{
+ struct da9030_charger *charger = platform_get_drvdata(dev);
+
+ da9030_bat_remove_debugfs(charger);
+
+ da903x_unregister_notifier(charger->master, &charger->nb,
+ DA9030_EVENT_CHDET | DA9030_EVENT_VBATMON |
+ DA9030_EVENT_CHIOVER | DA9030_EVENT_TBAT);
+ cancel_delayed_work(&charger->work);
+ power_supply_unregister(&charger->psy);
+
+ kfree(charger);
+
+ return 0;
+}
+
+static struct platform_driver da903x_battery_driver = {
+ .driver = {
+ .name = "da903x-battery",
+ .owner = THIS_MODULE,
+ },
+ .probe = da9030_battery_probe,
+ .remove = da9030_battery_remove,
+};
+
+static int da903x_battery_init(void)
+{
+ return platform_driver_register(&da903x_battery_driver);
+}
+
+static void da903x_battery_exit(void)
+{
+ platform_driver_unregister(&da903x_battery_driver);
+}
+
+module_init(da903x_battery_init);
+module_exit(da903x_battery_exit);
+
+MODULE_DESCRIPTION("DA9030 battery charger driver");
+MODULE_AUTHOR("Mike Rapoport, CompuLab");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 308ddb201b66..1d768928e0bb 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -354,7 +354,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data;
di->dev = &pdev->dev;
di->w1_dev = pdev->dev.parent;
- di->bat.name = pdev->dev.bus_id;
+ di->bat.name = dev_name(&pdev->dev);
di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
di->bat.properties = ds2760_battery_props;
di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
@@ -371,7 +371,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
}
INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
- di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);
+ di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
if (!di->monitor_wqueue) {
retval = -ESRCH;
goto workqueue_failed;
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
new file mode 100644
index 000000000000..e988ec130fcd
--- /dev/null
+++ b/drivers/power/pcf50633-charger.c
@@ -0,0 +1,358 @@
+/* NXP PCF50633 Main Battery Charger Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/mbc.h>
+
+struct pcf50633_mbc {
+ struct pcf50633 *pcf;
+
+ int adapter_active;
+ int adapter_online;
+ int usb_active;
+ int usb_online;
+
+ struct power_supply usb;
+ struct power_supply adapter;
+};
+
+int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
+ int ret = 0;
+ u8 bits;
+
+ if (ma >= 1000)
+ bits = PCF50633_MBCC7_USB_1000mA;
+ else if (ma >= 500)
+ bits = PCF50633_MBCC7_USB_500mA;
+ else if (ma >= 100)
+ bits = PCF50633_MBCC7_USB_100mA;
+ else
+ bits = PCF50633_MBCC7_USB_SUSPEND;
+
+ ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7,
+ PCF50633_MBCC7_USB_MASK, bits);
+ if (ret)
+ dev_err(pcf->dev, "error setting usb curlim to %d mA\n", ma);
+ else
+ dev_info(pcf->dev, "usb curlim to %d mA\n", ma);
+
+ power_supply_changed(&mbc->usb);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pcf50633_mbc_usb_curlim_set);
+
+int pcf50633_mbc_get_status(struct pcf50633 *pcf)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
+ int status = 0;
+
+ if (mbc->usb_online)
+ status |= PCF50633_MBC_USB_ONLINE;
+ if (mbc->usb_active)
+ status |= PCF50633_MBC_USB_ACTIVE;
+ if (mbc->adapter_online)
+ status |= PCF50633_MBC_ADAPTER_ONLINE;
+ if (mbc->adapter_active)
+ status |= PCF50633_MBC_ADAPTER_ACTIVE;
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
+
+void pcf50633_mbc_set_status(struct pcf50633 *pcf, int what, int status)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
+
+ if (what & PCF50633_MBC_USB_ONLINE)
+ mbc->usb_online = !!status;
+ if (what & PCF50633_MBC_USB_ACTIVE)
+ mbc->usb_active = !!status;
+ if (what & PCF50633_MBC_ADAPTER_ONLINE)
+ mbc->adapter_online = !!status;
+ if (what & PCF50633_MBC_ADAPTER_ACTIVE)
+ mbc->adapter_active = !!status;
+}
+EXPORT_SYMBOL_GPL(pcf50633_mbc_set_status);
+
+static ssize_t
+show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+
+ u8 mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
+ u8 chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
+
+ return sprintf(buf, "%d\n", chgmod);
+}
+static DEVICE_ATTR(chgmode, S_IRUGO, show_chgmode, NULL);
+
+static ssize_t
+show_usblim(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+ u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
+ PCF50633_MBCC7_USB_MASK;
+ unsigned int ma;
+
+ if (usblim == PCF50633_MBCC7_USB_1000mA)
+ ma = 1000;
+ else if (usblim == PCF50633_MBCC7_USB_500mA)
+ ma = 500;
+ else if (usblim == PCF50633_MBCC7_USB_100mA)
+ ma = 100;
+ else
+ ma = 0;
+
+ return sprintf(buf, "%u\n", ma);
+}
+
+static ssize_t set_usblim(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
+ unsigned long ma;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &ma);
+ if (ret)
+ return -EINVAL;
+
+ pcf50633_mbc_usb_curlim_set(mbc->pcf, ma);
+
+ return count;
+}
+
+static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim);
+
+static struct attribute *pcf50633_mbc_sysfs_entries[] = {
+ &dev_attr_chgmode.attr,
+ &dev_attr_usb_curlim.attr,
+ NULL,
+};
+
+static struct attribute_group mbc_attr_group = {
+ .name = NULL, /* put in device directory */
+ .attrs = pcf50633_mbc_sysfs_entries,
+};
+
+static void
+pcf50633_mbc_irq_handler(int irq, void *data)
+{
+ struct pcf50633_mbc *mbc = data;
+
+ /* USB */
+ if (irq == PCF50633_IRQ_USBINS) {
+ mbc->usb_online = 1;
+ } else if (irq == PCF50633_IRQ_USBREM) {
+ mbc->usb_online = 0;
+ mbc->usb_active = 0;
+ pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
+ }
+
+ /* Adapter */
+ if (irq == PCF50633_IRQ_ADPINS) {
+ mbc->adapter_online = 1;
+ mbc->adapter_active = 1;
+ } else if (irq == PCF50633_IRQ_ADPREM) {
+ mbc->adapter_online = 0;
+ mbc->adapter_active = 0;
+ }
+
+ if (irq == PCF50633_IRQ_BATFULL) {
+ mbc->usb_active = 0;
+ mbc->adapter_active = 0;
+ }
+
+ power_supply_changed(&mbc->usb);
+ power_supply_changed(&mbc->adapter);
+
+ if (mbc->pcf->pdata->mbc_event_callback)
+ mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
+}
+
+static int adapter_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = mbc->adapter_online;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int usb_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = mbc->usb_online;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property power_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static const u8 mbc_irq_handlers[] = {
+ PCF50633_IRQ_ADPINS,
+ PCF50633_IRQ_ADPREM,
+ PCF50633_IRQ_USBINS,
+ PCF50633_IRQ_USBREM,
+ PCF50633_IRQ_BATFULL,
+ PCF50633_IRQ_CHGHALT,
+ PCF50633_IRQ_THLIMON,
+ PCF50633_IRQ_THLIMOFF,
+ PCF50633_IRQ_USBLIMON,
+ PCF50633_IRQ_USBLIMOFF,
+ PCF50633_IRQ_LOWSYS,
+ PCF50633_IRQ_LOWBAT,
+};
+
+static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
+{
+ struct pcf50633_mbc *mbc;
+ struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
+ int ret;
+ int i;
+ u8 mbcs1;
+
+ mbc = kzalloc(sizeof(*mbc), GFP_KERNEL);
+ if (!mbc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mbc);
+ mbc->pcf = pdata->pcf;
+
+ /* Set up IRQ handlers */
+ for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
+ pcf50633_register_irq(mbc->pcf, mbc_irq_handlers[i],
+ pcf50633_mbc_irq_handler, mbc);
+
+ /* Create power supplies */
+ mbc->adapter.name = "adapter";
+ mbc->adapter.type = POWER_SUPPLY_TYPE_MAINS;
+ mbc->adapter.properties = power_props;
+ mbc->adapter.num_properties = ARRAY_SIZE(power_props);
+ mbc->adapter.get_property = &adapter_get_property;
+ mbc->adapter.supplied_to = mbc->pcf->pdata->batteries;
+ mbc->adapter.num_supplicants = mbc->pcf->pdata->num_batteries;
+
+ mbc->usb.name = "usb";
+ mbc->usb.type = POWER_SUPPLY_TYPE_USB;
+ mbc->usb.properties = power_props;
+ mbc->usb.num_properties = ARRAY_SIZE(power_props);
+ mbc->usb.get_property = usb_get_property;
+ mbc->usb.supplied_to = mbc->pcf->pdata->batteries;
+ mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries;
+
+ ret = power_supply_register(&pdev->dev, &mbc->adapter);
+ if (ret) {
+ dev_err(mbc->pcf->dev, "failed to register adapter\n");
+ kfree(mbc);
+ return ret;
+ }
+
+ ret = power_supply_register(&pdev->dev, &mbc->usb);
+ if (ret) {
+ dev_err(mbc->pcf->dev, "failed to register usb\n");
+ power_supply_unregister(&mbc->adapter);
+ kfree(mbc);
+ return ret;
+ }
+
+ ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
+ if (ret)
+ dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
+
+ mbcs1 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS1);
+ if (mbcs1 & PCF50633_MBCS1_USBPRES)
+ pcf50633_mbc_irq_handler(PCF50633_IRQ_USBINS, mbc);
+ if (mbcs1 & PCF50633_MBCS1_ADAPTPRES)
+ pcf50633_mbc_irq_handler(PCF50633_IRQ_ADPINS, mbc);
+
+ return 0;
+}
+
+static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pdev);
+ int i;
+
+ /* Remove IRQ handlers */
+ for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
+ pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
+
+ power_supply_unregister(&mbc->usb);
+ power_supply_unregister(&mbc->adapter);
+
+ kfree(mbc);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_mbc_driver = {
+ .driver = {
+ .name = "pcf50633-mbc",
+ },
+ .probe = pcf50633_mbc_probe,
+ .remove = __devexit_p(pcf50633_mbc_remove),
+};
+
+static int __init pcf50633_mbc_init(void)
+{
+ return platform_driver_register(&pcf50633_mbc_driver);
+}
+module_init(pcf50633_mbc_init);
+
+static void __exit pcf50633_mbc_exit(void)
+{
+ platform_driver_unregister(&pcf50633_mbc_driver);
+}
+module_exit(pcf50633_mbc_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 mbc driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-mbc");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index d30bb766fcef..b56a704409d2 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -20,7 +20,7 @@
static inline unsigned int get_irq_flags(struct resource *res)
{
- unsigned int flags = IRQF_DISABLED | IRQF_SHARED;
+ unsigned int flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED;
flags |= res->flags & IRQF_TRIGGER_MASK;
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 23ae8460f5c1..ac01e06817fb 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -45,7 +45,7 @@ static ssize_t power_supply_show_property(struct device *dev,
};
static char *health_text[] = {
"Unknown", "Good", "Overheat", "Dead", "Over voltage",
- "Unspecified failure"
+ "Unspecified failure", "Cold",
};
static char *technology_text[] = {
"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd",
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
new file mode 100644
index 000000000000..1b16bf343f2f
--- /dev/null
+++ b/drivers/power/wm8350_power.c
@@ -0,0 +1,532 @@
+/*
+ * Battery driver for wm8350 PMIC
+ *
+ * Copyright 2007, 2008 Wolfson Microelectronics PLC.
+ *
+ * Based on OLPC Battery Driver
+ *
+ * Copyright 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/wm8350/supply.h>
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/comparator.h>
+
+static int wm8350_read_battery_uvolts(struct wm8350 *wm8350)
+{
+ return wm8350_read_auxadc(wm8350, WM8350_AUXADC_BATT, 0, 0)
+ * WM8350_AUX_COEFF;
+}
+
+static int wm8350_read_line_uvolts(struct wm8350 *wm8350)
+{
+ return wm8350_read_auxadc(wm8350, WM8350_AUXADC_LINE, 0, 0)
+ * WM8350_AUX_COEFF;
+}
+
+static int wm8350_read_usb_uvolts(struct wm8350 *wm8350)
+{
+ return wm8350_read_auxadc(wm8350, WM8350_AUXADC_USB, 0, 0)
+ * WM8350_AUX_COEFF;
+}
+
+#define WM8350_BATT_SUPPLY 1
+#define WM8350_USB_SUPPLY 2
+#define WM8350_LINE_SUPPLY 4
+
+static inline int wm8350_charge_time_min(struct wm8350 *wm8350, int min)
+{
+ if (!wm8350->power.rev_g_coeff)
+ return (((min - 30) / 15) & 0xf) << 8;
+ else
+ return (((min - 30) / 30) & 0xf) << 8;
+}
+
+static int wm8350_get_supplies(struct wm8350 *wm8350)
+{
+ u16 sm, ov, co, chrg;
+ int supplies = 0;
+
+ sm = wm8350_reg_read(wm8350, WM8350_STATE_MACHINE_STATUS);
+ ov = wm8350_reg_read(wm8350, WM8350_MISC_OVERRIDES);
+ co = wm8350_reg_read(wm8350, WM8350_COMPARATOR_OVERRIDES);
+ chrg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2);
+
+ /* USB_SM */
+ sm = (sm & WM8350_USB_SM_MASK) >> WM8350_USB_SM_SHIFT;
+
+ /* CHG_ISEL */
+ chrg &= WM8350_CHG_ISEL_MASK;
+
+ /* If the USB state machine is active then we're using that with or
+ * without battery, otherwise check for wall supply */
+ if (((sm == WM8350_USB_SM_100_SLV) ||
+ (sm == WM8350_USB_SM_500_SLV) ||
+ (sm == WM8350_USB_SM_STDBY_SLV))
+ && !(ov & WM8350_USB_LIMIT_OVRDE))
+ supplies = WM8350_USB_SUPPLY;
+ else if (((sm == WM8350_USB_SM_100_SLV) ||
+ (sm == WM8350_USB_SM_500_SLV) ||
+ (sm == WM8350_USB_SM_STDBY_SLV))
+ && (ov & WM8350_USB_LIMIT_OVRDE) && (chrg == 0))
+ supplies = WM8350_USB_SUPPLY | WM8350_BATT_SUPPLY;
+ else if (co & WM8350_WALL_FB_OVRDE)
+ supplies = WM8350_LINE_SUPPLY;
+ else
+ supplies = WM8350_BATT_SUPPLY;
+
+ return supplies;
+}
+
+static int wm8350_charger_config(struct wm8350 *wm8350,
+ struct wm8350_charger_policy *policy)
+{
+ u16 reg, eoc_mA, fast_limit_mA;
+
+ if (!policy) {
+ dev_warn(wm8350->dev,
+ "No charger policy, charger not configured.\n");
+ return -EINVAL;
+ }
+
+ /* make sure USB fast charge current is not > 500mA */
+ if (policy->fast_limit_USB_mA > 500) {
+ dev_err(wm8350->dev, "USB fast charge > 500mA\n");
+ return -EINVAL;
+ }
+
+ eoc_mA = WM8350_CHG_EOC_mA(policy->eoc_mA);
+
+ wm8350_reg_unlock(wm8350);
+
+ reg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1)
+ & WM8350_CHG_ENA_R168;
+ wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1,
+ reg | eoc_mA | policy->trickle_start_mV |
+ WM8350_CHG_TRICKLE_TEMP_CHOKE |
+ WM8350_CHG_TRICKLE_USB_CHOKE |
+ WM8350_CHG_FAST_USB_THROTTLE);
+
+ if (wm8350_get_supplies(wm8350) & WM8350_USB_SUPPLY) {
+ fast_limit_mA =
+ WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_USB_mA);
+ wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2,
+ policy->charge_mV | policy->trickle_charge_USB_mA |
+ fast_limit_mA | wm8350_charge_time_min(wm8350,
+ policy->charge_timeout));
+
+ } else {
+ fast_limit_mA =
+ WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_mA);
+ wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2,
+ policy->charge_mV | policy->trickle_charge_mA |
+ fast_limit_mA | wm8350_charge_time_min(wm8350,
+ policy->charge_timeout));
+ }
+
+ wm8350_reg_lock(wm8350);
+ return 0;
+}
+
+static int wm8350_batt_status(struct wm8350 *wm8350)
+{
+ u16 state;
+
+ state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2);
+ state &= WM8350_CHG_STS_MASK;
+
+ switch (state) {
+ case WM8350_CHG_STS_OFF:
+ return POWER_SUPPLY_STATUS_DISCHARGING;
+
+ case WM8350_CHG_STS_TRICKLE:
+ case WM8350_CHG_STS_FAST:
+ return POWER_SUPPLY_STATUS_CHARGING;
+
+ default:
+ return POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+}
+
+static ssize_t charger_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+ char *charge;
+ int state;
+
+ state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2) &
+ WM8350_CHG_STS_MASK;
+ switch (state) {
+ case WM8350_CHG_STS_OFF:
+ charge = "Charger Off";
+ break;
+ case WM8350_CHG_STS_TRICKLE:
+ charge = "Trickle Charging";
+ break;
+ case WM8350_CHG_STS_FAST:
+ charge = "Fast Charging";
+ break;
+ default:
+ return 0;
+ }
+
+ return sprintf(buf, "%s\n", charge);
+}
+
+static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL);
+
+static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data)
+{
+ struct wm8350_power *power = &wm8350->power;
+ struct wm8350_charger_policy *policy = power->policy;
+
+ switch (irq) {
+ case WM8350_IRQ_CHG_BAT_FAIL:
+ dev_err(wm8350->dev, "battery failed\n");
+ break;
+ case WM8350_IRQ_CHG_TO:
+ dev_err(wm8350->dev, "charger timeout\n");
+ power_supply_changed(&power->battery);
+ break;
+
+ case WM8350_IRQ_CHG_BAT_HOT:
+ case WM8350_IRQ_CHG_BAT_COLD:
+ case WM8350_IRQ_CHG_START:
+ case WM8350_IRQ_CHG_END:
+ power_supply_changed(&power->battery);
+ break;
+
+ case WM8350_IRQ_CHG_FAST_RDY:
+ dev_dbg(wm8350->dev, "fast charger ready\n");
+ wm8350_charger_config(wm8350, policy);
+ wm8350_reg_unlock(wm8350);
+ wm8350_set_bits(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1,
+ WM8350_CHG_FAST);
+ wm8350_reg_lock(wm8350);
+ break;
+
+ case WM8350_IRQ_CHG_VBATT_LT_3P9:
+ dev_warn(wm8350->dev, "battery < 3.9V\n");
+ break;
+ case WM8350_IRQ_CHG_VBATT_LT_3P1:
+ dev_warn(wm8350->dev, "battery < 3.1V\n");
+ break;
+ case WM8350_IRQ_CHG_VBATT_LT_2P85:
+ dev_warn(wm8350->dev, "battery < 2.85V\n");
+ break;
+
+ /* Supply change. We will overnotify but it should do
+ * no harm. */
+ case WM8350_IRQ_EXT_USB_FB:
+ case WM8350_IRQ_EXT_WALL_FB:
+ wm8350_charger_config(wm8350, policy);
+ case WM8350_IRQ_EXT_BAT_FB: /* Fall through */
+ power_supply_changed(&power->battery);
+ power_supply_changed(&power->usb);
+ power_supply_changed(&power->ac);
+ break;
+
+ default:
+ dev_err(wm8350->dev, "Unknown interrupt %d\n", irq);
+ }
+}
+
+/*********************************************************************
+ * AC Power
+ *********************************************************************/
+static int wm8350_ac_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(wm8350_get_supplies(wm8350) &
+ WM8350_LINE_SUPPLY);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = wm8350_read_line_uvolts(wm8350);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property wm8350_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+/*********************************************************************
+ * USB Power
+ *********************************************************************/
+static int wm8350_usb_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(wm8350_get_supplies(wm8350) &
+ WM8350_USB_SUPPLY);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = wm8350_read_usb_uvolts(wm8350);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property wm8350_usb_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+
+static int wm8350_bat_check_health(struct wm8350 *wm8350)
+{
+ u16 reg;
+
+ if (wm8350_read_battery_uvolts(wm8350) < 2850000)
+ return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+
+ reg = wm8350_reg_read(wm8350, WM8350_CHARGER_OVERRIDES);
+ if (reg & WM8350_CHG_BATT_HOT_OVRDE)
+ return POWER_SUPPLY_HEALTH_OVERHEAT;
+
+ if (reg & WM8350_CHG_BATT_COLD_OVRDE)
+ return POWER_SUPPLY_HEALTH_COLD;
+
+ return POWER_SUPPLY_HEALTH_GOOD;
+}
+
+static int wm8350_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = wm8350_batt_status(wm8350);
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = !!(wm8350_get_supplies(wm8350) &
+ WM8350_BATT_SUPPLY);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = wm8350_read_battery_uvolts(wm8350);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = wm8350_bat_check_health(wm8350);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static enum power_supply_property wm8350_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_HEALTH,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static void wm8350_init_charger(struct wm8350 *wm8350)
+{
+ /* register our interest in charger events */
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
+ wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
+
+ /* and supply change events */
+ wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
+ wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
+ wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
+ wm8350_charger_handler, NULL);
+ wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+}
+
+static void free_charger_irq(struct wm8350 *wm8350)
+{
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
+ wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+}
+
+static __devinit int wm8350_power_probe(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_power *power = &wm8350->power;
+ struct wm8350_charger_policy *policy = power->policy;
+ struct power_supply *usb = &power->usb;
+ struct power_supply *battery = &power->battery;
+ struct power_supply *ac = &power->ac;
+ int ret;
+
+ ac->name = "wm8350-ac";
+ ac->type = POWER_SUPPLY_TYPE_MAINS;
+ ac->properties = wm8350_ac_props;
+ ac->num_properties = ARRAY_SIZE(wm8350_ac_props);
+ ac->get_property = wm8350_ac_get_prop;
+ ret = power_supply_register(&pdev->dev, ac);
+ if (ret)
+ return ret;
+
+ battery->name = "wm8350-battery";
+ battery->properties = wm8350_bat_props;
+ battery->num_properties = ARRAY_SIZE(wm8350_bat_props);
+ battery->get_property = wm8350_bat_get_property;
+ battery->use_for_apm = 1;
+ ret = power_supply_register(&pdev->dev, battery);
+ if (ret)
+ goto battery_failed;
+
+ usb->name = "wm8350-usb",
+ usb->type = POWER_SUPPLY_TYPE_USB;
+ usb->properties = wm8350_usb_props;
+ usb->num_properties = ARRAY_SIZE(wm8350_usb_props);
+ usb->get_property = wm8350_usb_get_prop;
+ ret = power_supply_register(&pdev->dev, usb);
+ if (ret)
+ goto usb_failed;
+
+ ret = device_create_file(&pdev->dev, &dev_attr_charger_state);
+ if (ret < 0)
+ dev_warn(wm8350->dev, "failed to add charge sysfs: %d\n", ret);
+ ret = 0;
+
+ wm8350_init_charger(wm8350);
+ if (wm8350_charger_config(wm8350, policy) == 0) {
+ wm8350_reg_unlock(wm8350);
+ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CHG_ENA);
+ wm8350_reg_lock(wm8350);
+ }
+
+ return ret;
+
+usb_failed:
+ power_supply_unregister(battery);
+battery_failed:
+ power_supply_unregister(ac);
+
+ return ret;
+}
+
+static __devexit int wm8350_power_remove(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = platform_get_drvdata(pdev);
+ struct wm8350_power *power = &wm8350->power;
+
+ free_charger_irq(wm8350);
+ device_remove_file(&pdev->dev, &dev_attr_charger_state);
+ power_supply_unregister(&power->battery);
+ power_supply_unregister(&power->ac);
+ power_supply_unregister(&power->usb);
+ return 0;
+}
+
+static struct platform_driver wm8350_power_driver = {
+ .probe = wm8350_power_probe,
+ .remove = __devexit_p(wm8350_power_remove),
+ .driver = {
+ .name = "wm8350-power",
+ },
+};
+
+static int __init wm8350_power_init(void)
+{
+ return platform_driver_register(&wm8350_power_driver);
+}
+module_init(wm8350_power_init);
+
+static void __exit wm8350_power_exit(void)
+{
+ platform_driver_unregister(&wm8350_power_driver);
+}
+module_exit(wm8350_power_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Power supply driver for WM8350");
+MODULE_ALIAS("platform:wm8350-power");
diff --git a/drivers/ps3/ps3-lpm.c b/drivers/ps3/ps3-lpm.c
index 204158cf7a55..fe96793e3f08 100644
--- a/drivers/ps3/ps3-lpm.c
+++ b/drivers/ps3/ps3-lpm.c
@@ -732,7 +732,7 @@ static u64 pm_signal_group_to_ps3_lv1_signal_group(u64 group)
case 8:
return pm_translate_signal_group_number_on_island8(subgroup);
default:
- dev_dbg(sbd_core(), "%s:%u: island not found: %lu\n", __func__,
+ dev_dbg(sbd_core(), "%s:%u: island not found: %llu\n", __func__,
__LINE__, group);
BUG();
break;
@@ -765,7 +765,7 @@ static int __ps3_set_signal(u64 lv1_signal_group, u64 bus_select,
signal_select, attr1, attr2, attr3);
if (ret)
dev_err(sbd_core(),
- "%s:%u: error:%d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+ "%s:%u: error:%d 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx\n",
__func__, __LINE__, ret, lv1_signal_group, bus_select,
signal_select, attr1, attr2, attr3);
@@ -908,7 +908,7 @@ void ps3_disable_pm(u32 cpu)
lpm_priv->tb_count = tmp;
- dev_dbg(sbd_core(), "%s:%u: tb_count %lu (%lxh)\n", __func__, __LINE__,
+ dev_dbg(sbd_core(), "%s:%u: tb_count %llu (%llxh)\n", __func__, __LINE__,
lpm_priv->tb_count, lpm_priv->tb_count);
}
EXPORT_SYMBOL_GPL(ps3_disable_pm);
@@ -938,7 +938,7 @@ int ps3_lpm_copy_tb(unsigned long offset, void *buf, unsigned long count,
if (offset >= lpm_priv->tb_count)
return 0;
- count = min(count, lpm_priv->tb_count - offset);
+ count = min_t(u64, count, lpm_priv->tb_count - offset);
while (*bytes_copied < count) {
const unsigned long request = count - *bytes_copied;
@@ -993,7 +993,7 @@ int ps3_lpm_copy_tb_to_user(unsigned long offset, void __user *buf,
if (offset >= lpm_priv->tb_count)
return 0;
- count = min(count, lpm_priv->tb_count - offset);
+ count = min_t(u64, count, lpm_priv->tb_count - offset);
while (*bytes_copied < count) {
const unsigned long request = count - *bytes_copied;
@@ -1013,7 +1013,7 @@ int ps3_lpm_copy_tb_to_user(unsigned long offset, void __user *buf,
result = copy_to_user(buf, lpm_priv->tb_cache, tmp);
if (result) {
- dev_dbg(sbd_core(), "%s:%u: 0x%lx bytes at 0x%p\n",
+ dev_dbg(sbd_core(), "%s:%u: 0x%llx bytes at 0x%p\n",
__func__, __LINE__, tmp, buf);
dev_err(sbd_core(), "%s:%u: copy_to_user failed: %d\n",
__func__, __LINE__, result);
@@ -1148,8 +1148,8 @@ int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache,
lpm_priv->shadow.group_control = PS3_LPM_SHADOW_REG_INIT;
lpm_priv->shadow.debug_bus_control = PS3_LPM_SHADOW_REG_INIT;
- dev_dbg(sbd_core(), "%s:%u: lpm_id 0x%lx, outlet_id 0x%lx, "
- "tb_size 0x%lx\n", __func__, __LINE__, lpm_priv->lpm_id,
+ dev_dbg(sbd_core(), "%s:%u: lpm_id 0x%llx, outlet_id 0x%llx, "
+ "tb_size 0x%llx\n", __func__, __LINE__, lpm_priv->lpm_id,
lpm_priv->outlet_id, tb_size);
return 0;
diff --git a/drivers/ps3/ps3-vuart.c b/drivers/ps3/ps3-vuart.c
index 90c097a7a47a..e4ad5ba5d0a3 100644
--- a/drivers/ps3/ps3-vuart.c
+++ b/drivers/ps3/ps3-vuart.c
@@ -114,7 +114,7 @@ struct ports_bmp {
static void __maybe_unused _dump_ports_bmp(
const struct ports_bmp *bmp, const char *func, int line)
{
- pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
+ pr_debug("%s:%d: ports_bmp: %016llxh\n", func, line, bmp->status);
}
#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
@@ -159,11 +159,13 @@ int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
struct vuart_triggers *trig)
{
int result;
- unsigned long size;
- unsigned long val;
+ u64 size;
+ u64 val;
+ u64 tx;
result = lv1_get_virtual_uart_param(dev->port_number,
- PARAM_TX_TRIGGER, &trig->tx);
+ PARAM_TX_TRIGGER, &tx);
+ trig->tx = tx;
if (result) {
dev_dbg(&dev->core, "%s:%d: tx_trigger failed: %s\n",
@@ -201,7 +203,7 @@ int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
unsigned int rx)
{
int result;
- unsigned long size;
+ u64 size;
result = lv1_set_virtual_uart_param(dev->port_number,
PARAM_TX_TRIGGER, tx);
@@ -248,7 +250,7 @@ static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
dev_dbg(&dev->core, "%s:%d: rx_bytes failed: %s\n",
__func__, __LINE__, ps3_result(result));
- dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__,
+ dev_dbg(&dev->core, "%s:%d: %llxh\n", __func__, __LINE__,
*bytes_waiting);
return result;
}
@@ -295,7 +297,7 @@ static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
*status = tmp & priv->interrupt_mask;
- dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
+ dev_dbg(&dev->core, "%s:%d: m %llxh, s %llxh, m&s %lxh\n",
__func__, __LINE__, priv->interrupt_mask, tmp, *status);
return result;
@@ -363,7 +365,7 @@ int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
*/
static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
- const void *buf, unsigned int bytes, unsigned long *bytes_written)
+ const void *buf, unsigned int bytes, u64 *bytes_written)
{
int result;
struct ps3_vuart_port_priv *priv = to_port_priv(dev);
@@ -379,7 +381,7 @@ static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
priv->stats.bytes_written += *bytes_written;
- dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
+ dev_dbg(&dev->core, "%s:%d: wrote %llxh/%xh=>%lxh\n", __func__, __LINE__,
*bytes_written, bytes, priv->stats.bytes_written);
return result;
@@ -393,7 +395,7 @@ static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
*/
static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
- unsigned int bytes, unsigned long *bytes_read)
+ unsigned int bytes, u64 *bytes_read)
{
int result;
struct ps3_vuart_port_priv *priv = to_port_priv(dev);
@@ -411,7 +413,7 @@ static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
priv->stats.bytes_read += *bytes_read;
- dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
+ dev_dbg(&dev->core, "%s:%d: read %llxh/%xh=>%lxh\n", __func__, __LINE__,
*bytes_read, bytes, priv->stats.bytes_read);
return result;
@@ -500,7 +502,7 @@ int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
spin_lock_irqsave(&priv->tx_list.lock, flags);
if (list_empty(&priv->tx_list.head)) {
- unsigned long bytes_written;
+ u64 bytes_written;
result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
@@ -592,7 +594,7 @@ static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
list_add_tail(&lb->link, &priv->rx_list.head);
priv->rx_list.bytes_held += bytes;
- dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
+ dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %llxh bytes\n",
__func__, __LINE__, lb->dbg_number, bytes);
*bytes_queued = bytes;
@@ -745,7 +747,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
- unsigned long bytes_written;
+ u64 bytes_written;
result = ps3_vuart_raw_write(dev, lb->head, lb->tail - lb->head,
&bytes_written);
@@ -762,7 +764,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
if (bytes_written < lb->tail - lb->head) {
lb->head += bytes_written;
dev_dbg(&dev->core,
- "%s:%d cleared buf_%lu, %lxh bytes\n",
+ "%s:%d cleared buf_%lu, %llxh bytes\n",
__func__, __LINE__, lb->dbg_number,
bytes_written);
goto port_full;
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
index 55955f16ad91..18066d555397 100644
--- a/drivers/ps3/ps3stor_lib.c
+++ b/drivers/ps3/ps3stor_lib.c
@@ -70,7 +70,7 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
__func__, __LINE__, n);
dev->region_idx = __ffs(dev->accessible_regions);
dev_info(&dev->sbd.core,
- "First accessible region has index %u start %lu size %lu\n",
+ "First accessible region has index %u start %llu size %llu\n",
dev->region_idx, dev->regions[dev->region_idx].start,
dev->regions[dev->region_idx].size);
@@ -220,7 +220,7 @@ u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
const char *op = write ? "write" : "read";
int res;
- dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+ dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n",
__func__, __LINE__, op, sectors, start_sector);
init_completion(&dev->done);
@@ -238,7 +238,7 @@ u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
wait_for_completion(&dev->done);
if (dev->lv1_status) {
- dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+ dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
__LINE__, op, dev->lv1_status);
return dev->lv1_status;
}
@@ -268,7 +268,7 @@ u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
{
int res;
- dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__,
+ dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%llx\n", __func__,
__LINE__, cmd);
init_completion(&dev->done);
@@ -277,19 +277,19 @@ u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1,
arg2, arg3, arg4, &dev->tag);
if (res) {
dev_err(&dev->sbd.core,
- "%s:%u: send_device_command 0x%lx failed %d\n",
+ "%s:%u: send_device_command 0x%llx failed %d\n",
__func__, __LINE__, cmd, res);
return -1;
}
wait_for_completion(&dev->done);
if (dev->lv1_status) {
- dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n",
+ dev_dbg(&dev->sbd.core, "%s:%u: command 0x%llx failed 0x%llx\n",
__func__, __LINE__, cmd, dev->lv1_status);
return dev->lv1_status;
}
- dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__,
+ dev_dbg(&dev->sbd.core, "%s:%u: command 0x%llx completed\n", __func__,
__LINE__, cmd);
return 0;
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index 956d3e79f6aa..addb87cf44d9 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -79,7 +79,6 @@ void rio_dev_put(struct rio_dev *rdev)
/**
* rio_device_probe - Tell if a RIO device structure has a matching RIO device id structure
- * @id: the RIO device id structure to match against
* @dev: the RIO device structure to match against
*
* return 0 and set rio_dev->driver when drv claims rio_dev, else error
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 39360e2a4540..e7e0cf102d6d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -73,4 +73,11 @@ config REGULATOR_DA903X
Say y here to support the BUCKs and LDOs regulators found on
Dialog Semiconductor DA9030/DA9034 PMIC.
+config REGULATOR_PCF50633
+ tristate "PCF50633 regulator driver"
+ depends on MFD_PCF50633
+ help
+ Say Y here to support the voltage regulators and convertors
+ on PCF50633
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 254d40c02ee8..61b30c6ddecc 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -11,5 +11,6 @@ obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
+obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c
index 366565aba865..c175e38a4cd5 100644
--- a/drivers/regulator/bq24022.c
+++ b/drivers/regulator/bq24022.c
@@ -152,11 +152,7 @@ static void __exit bq24022_exit(void)
platform_driver_unregister(&bq24022_driver);
}
-/*
- * make sure this is probed before gpio_vbus and pda_power,
- * but after asic3 or other GPIO expander drivers.
- */
-subsys_initcall(bq24022_init);
+module_init(bq24022_init);
module_exit(bq24022_exit);
MODULE_AUTHOR("Philipp Zabel");
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 02a774424e8d..f511a406fcaa 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -29,7 +29,7 @@ static DEFINE_MUTEX(regulator_list_mutex);
static LIST_HEAD(regulator_list);
static LIST_HEAD(regulator_map_list);
-/**
+/*
* struct regulator_dev
*
* Voltage / Current regulator class device. One for each regulator.
@@ -56,7 +56,7 @@ struct regulator_dev {
void *reg_data; /* regulator_dev data */
};
-/**
+/*
* struct regulator_map
*
* Used to provide symbolic supply names to devices.
@@ -79,7 +79,7 @@ struct regulator {
int uA_load;
int min_uV;
int max_uV;
- int enabled; /* client has called enabled */
+ int enabled; /* count of client enables */
char *supply_name;
struct device_attribute dev_attr;
struct regulator_dev *rdev;
@@ -174,6 +174,16 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
/* operating mode constraint check */
static int regulator_check_mode(struct regulator_dev *rdev, int mode)
{
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ case REGULATOR_MODE_NORMAL:
+ case REGULATOR_MODE_IDLE:
+ case REGULATOR_MODE_STANDBY:
+ break;
+ default:
+ return -EINVAL;
+ }
+
if (!rdev->constraints) {
printk(KERN_ERR "%s: no constraints for %s\n", __func__,
rdev->desc->name);
@@ -232,6 +242,7 @@ static ssize_t regulator_uV_show(struct device *dev,
return ret;
}
+static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);
static ssize_t regulator_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -240,6 +251,7 @@ static ssize_t regulator_uA_show(struct device *dev,
return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));
}
+static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);
static ssize_t regulator_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -257,12 +269,8 @@ static ssize_t regulator_name_show(struct device *dev,
return sprintf(buf, "%s\n", name);
}
-static ssize_t regulator_opmode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t regulator_print_opmode(char *buf, int mode)
{
- struct regulator_dev *rdev = dev_get_drvdata(dev);
- int mode = _regulator_get_mode(rdev);
-
switch (mode) {
case REGULATOR_MODE_FAST:
return sprintf(buf, "fast\n");
@@ -276,12 +284,17 @@ static ssize_t regulator_opmode_show(struct device *dev,
return sprintf(buf, "unknown\n");
}
-static ssize_t regulator_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t regulator_opmode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- int state = _regulator_is_enabled(rdev);
+ return regulator_print_opmode(buf, _regulator_get_mode(rdev));
+}
+static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL);
+
+static ssize_t regulator_print_state(char *buf, int state)
+{
if (state > 0)
return sprintf(buf, "enabled\n");
else if (state == 0)
@@ -290,6 +303,15 @@ static ssize_t regulator_state_show(struct device *dev,
return sprintf(buf, "unknown\n");
}
+static ssize_t regulator_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct regulator_dev *rdev = dev_get_drvdata(dev);
+
+ return regulator_print_state(buf, _regulator_is_enabled(rdev));
+}
+static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);
+
static ssize_t regulator_min_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -300,6 +322,7 @@ static ssize_t regulator_min_uA_show(struct device *dev,
return sprintf(buf, "%d\n", rdev->constraints->min_uA);
}
+static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL);
static ssize_t regulator_max_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -311,6 +334,7 @@ static ssize_t regulator_max_uA_show(struct device *dev,
return sprintf(buf, "%d\n", rdev->constraints->max_uA);
}
+static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL);
static ssize_t regulator_min_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -322,6 +346,7 @@ static ssize_t regulator_min_uV_show(struct device *dev,
return sprintf(buf, "%d\n", rdev->constraints->min_uV);
}
+static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL);
static ssize_t regulator_max_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -333,6 +358,7 @@ static ssize_t regulator_max_uV_show(struct device *dev,
return sprintf(buf, "%d\n", rdev->constraints->max_uV);
}
+static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL);
static ssize_t regulator_total_uA_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -347,6 +373,7 @@ static ssize_t regulator_total_uA_show(struct device *dev,
mutex_unlock(&rdev->mutex);
return sprintf(buf, "%d\n", uA);
}
+static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);
static ssize_t regulator_num_users_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -374,153 +401,106 @@ static ssize_t regulator_suspend_mem_uV_show(struct device *dev,
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);
}
+static DEVICE_ATTR(suspend_mem_microvolts, 0444,
+ regulator_suspend_mem_uV_show, NULL);
static ssize_t regulator_suspend_disk_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);
}
+static DEVICE_ATTR(suspend_disk_microvolts, 0444,
+ regulator_suspend_disk_uV_show, NULL);
static ssize_t regulator_suspend_standby_uV_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);
}
-
-static ssize_t suspend_opmode_show(struct regulator_dev *rdev,
- unsigned int mode, char *buf)
-{
- switch (mode) {
- case REGULATOR_MODE_FAST:
- return sprintf(buf, "fast\n");
- case REGULATOR_MODE_NORMAL:
- return sprintf(buf, "normal\n");
- case REGULATOR_MODE_IDLE:
- return sprintf(buf, "idle\n");
- case REGULATOR_MODE_STANDBY:
- return sprintf(buf, "standby\n");
- }
- return sprintf(buf, "unknown\n");
-}
+static DEVICE_ATTR(suspend_standby_microvolts, 0444,
+ regulator_suspend_standby_uV_show, NULL);
static ssize_t regulator_suspend_mem_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
- return suspend_opmode_show(rdev,
- rdev->constraints->state_mem.mode, buf);
+ return regulator_print_opmode(buf,
+ rdev->constraints->state_mem.mode);
}
+static DEVICE_ATTR(suspend_mem_mode, 0444,
+ regulator_suspend_mem_mode_show, NULL);
static ssize_t regulator_suspend_disk_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
- return suspend_opmode_show(rdev,
- rdev->constraints->state_disk.mode, buf);
+ return regulator_print_opmode(buf,
+ rdev->constraints->state_disk.mode);
}
+static DEVICE_ATTR(suspend_disk_mode, 0444,
+ regulator_suspend_disk_mode_show, NULL);
static ssize_t regulator_suspend_standby_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
- return suspend_opmode_show(rdev,
- rdev->constraints->state_standby.mode, buf);
+ return regulator_print_opmode(buf,
+ rdev->constraints->state_standby.mode);
}
+static DEVICE_ATTR(suspend_standby_mode, 0444,
+ regulator_suspend_standby_mode_show, NULL);
static ssize_t regulator_suspend_mem_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
-
- if (rdev->constraints->state_mem.enabled)
- return sprintf(buf, "enabled\n");
- else
- return sprintf(buf, "disabled\n");
+ return regulator_print_state(buf,
+ rdev->constraints->state_mem.enabled);
}
+static DEVICE_ATTR(suspend_mem_state, 0444,
+ regulator_suspend_mem_state_show, NULL);
static ssize_t regulator_suspend_disk_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
-
- if (rdev->constraints->state_disk.enabled)
- return sprintf(buf, "enabled\n");
- else
- return sprintf(buf, "disabled\n");
+ return regulator_print_state(buf,
+ rdev->constraints->state_disk.enabled);
}
+static DEVICE_ATTR(suspend_disk_state, 0444,
+ regulator_suspend_disk_state_show, NULL);
static ssize_t regulator_suspend_standby_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct regulator_dev *rdev = dev_get_drvdata(dev);
- if (!rdev->constraints)
- return sprintf(buf, "not defined\n");
-
- if (rdev->constraints->state_standby.enabled)
- return sprintf(buf, "enabled\n");
- else
- return sprintf(buf, "disabled\n");
+ return regulator_print_state(buf,
+ rdev->constraints->state_standby.enabled);
}
+static DEVICE_ATTR(suspend_standby_state, 0444,
+ regulator_suspend_standby_state_show, NULL);
+
+/*
+ * These are the only attributes are present for all regulators.
+ * Other attributes are a function of regulator functionality.
+ */
static struct device_attribute regulator_dev_attrs[] = {
__ATTR(name, 0444, regulator_name_show, NULL),
- __ATTR(microvolts, 0444, regulator_uV_show, NULL),
- __ATTR(microamps, 0444, regulator_uA_show, NULL),
- __ATTR(opmode, 0444, regulator_opmode_show, NULL),
- __ATTR(state, 0444, regulator_state_show, NULL),
- __ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL),
- __ATTR(min_microamps, 0444, regulator_min_uA_show, NULL),
- __ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL),
- __ATTR(max_microamps, 0444, regulator_max_uA_show, NULL),
- __ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL),
__ATTR(num_users, 0444, regulator_num_users_show, NULL),
__ATTR(type, 0444, regulator_type_show, NULL),
- __ATTR(suspend_mem_microvolts, 0444,
- regulator_suspend_mem_uV_show, NULL),
- __ATTR(suspend_disk_microvolts, 0444,
- regulator_suspend_disk_uV_show, NULL),
- __ATTR(suspend_standby_microvolts, 0444,
- regulator_suspend_standby_uV_show, NULL),
- __ATTR(suspend_mem_mode, 0444,
- regulator_suspend_mem_mode_show, NULL),
- __ATTR(suspend_disk_mode, 0444,
- regulator_suspend_disk_mode_show, NULL),
- __ATTR(suspend_standby_mode, 0444,
- regulator_suspend_standby_mode_show, NULL),
- __ATTR(suspend_mem_state, 0444,
- regulator_suspend_mem_state_show, NULL),
- __ATTR(suspend_disk_state, 0444,
- regulator_suspend_disk_state_show, NULL),
- __ATTR(suspend_standby_state, 0444,
- regulator_suspend_standby_state_show, NULL),
__ATTR_NULL,
};
@@ -675,7 +655,8 @@ static void print_constraints(struct regulator_dev *rdev)
/**
* set_machine_constraints - sets regulator constraints
- * @regulator: regulator source
+ * @rdev: regulator source
+ * @constraints: constraints to apply
*
* Allows platform initialisation code to define and constrain
* regulator circuits e.g. valid voltage/current ranges, etc. NOTE:
@@ -750,8 +731,8 @@ out:
/**
* set_supply - set regulator supply regulator
- * @regulator: regulator name
- * @supply: supply regulator name
+ * @rdev: regulator name
+ * @supply_rdev: supply regulator name
*
* Called by platform initialisation code to set the supply regulator for this
* regulator. This ensures that a regulators supply will also be enabled by the
@@ -778,9 +759,9 @@ out:
/**
* set_consumer_device_supply: Bind a regulator to a symbolic supply
- * @regulator: regulator source
- * @dev: device the supply applies to
- * @supply: symbolic name for supply
+ * @rdev: regulator source
+ * @consumer_dev: device the supply applies to
+ * @supply: symbolic name for supply
*
* Allows platform initialisation code to map physical regulator
* sources to symbolic names for supplies for use by devices. Devices
@@ -795,6 +776,20 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
if (supply == NULL)
return -EINVAL;
+ list_for_each_entry(node, &regulator_map_list, list) {
+ if (consumer_dev != node->dev)
+ continue;
+ if (strcmp(node->supply, supply) != 0)
+ continue;
+
+ dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n",
+ dev_name(&node->regulator->dev),
+ node->regulator->desc->name,
+ supply,
+ dev_name(&rdev->dev), rdev->desc->name);
+ return -EBUSY;
+ }
+
node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL);
if (node == NULL)
return -ENOMEM;
@@ -963,16 +958,13 @@ void regulator_put(struct regulator *regulator)
if (regulator == NULL || IS_ERR(regulator))
return;
- if (regulator->enabled) {
- printk(KERN_WARNING "Releasing supply %s while enabled\n",
- regulator->supply_name);
- WARN_ON(regulator->enabled);
- regulator_disable(regulator);
- }
-
mutex_lock(&regulator_list_mutex);
rdev = regulator->rdev;
+ if (WARN(regulator->enabled, "Releasing supply %s while enabled\n",
+ regulator->supply_name))
+ _regulator_disable(rdev);
+
/* remove any sysfs entries */
if (regulator->dev) {
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
@@ -1034,29 +1026,26 @@ static int _regulator_enable(struct regulator_dev *rdev)
* regulator_enable - enable regulator output
* @regulator: regulator source
*
- * Enable the regulator output at the predefined voltage or current value.
+ * Request that the regulator be enabled with the regulator output at
+ * the predefined voltage or current value. Calls to regulator_enable()
+ * must be balanced with calls to regulator_disable().
+ *
* NOTE: the output value can be set by other drivers, boot loader or may be
* hardwired in the regulator.
- * NOTE: calls to regulator_enable() must be balanced with calls to
- * regulator_disable().
*/
int regulator_enable(struct regulator *regulator)
{
- int ret;
-
- if (regulator->enabled) {
- printk(KERN_CRIT "Regulator %s already enabled\n",
- regulator->supply_name);
- WARN_ON(regulator->enabled);
- return 0;
- }
+ struct regulator_dev *rdev = regulator->rdev;
+ int ret = 0;
- mutex_lock(&regulator->rdev->mutex);
- regulator->enabled = 1;
- ret = _regulator_enable(regulator->rdev);
- if (ret != 0)
- regulator->enabled = 0;
- mutex_unlock(&regulator->rdev->mutex);
+ mutex_lock(&rdev->mutex);
+ if (regulator->enabled == 0)
+ ret = _regulator_enable(rdev);
+ else if (regulator->enabled < 0)
+ ret = -EIO;
+ if (ret == 0)
+ regulator->enabled++;
+ mutex_unlock(&rdev->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_enable);
@@ -1100,27 +1089,31 @@ static int _regulator_disable(struct regulator_dev *rdev)
* regulator_disable - disable regulator output
* @regulator: regulator source
*
- * Disable the regulator output voltage or current.
- * NOTE: this will only disable the regulator output if no other consumer
- * devices have it enabled.
- * NOTE: calls to regulator_enable() must be balanced with calls to
+ * Disable the regulator output voltage or current. Calls to
+ * regulator_enable() must be balanced with calls to
* regulator_disable().
+ *
+ * NOTE: this will only disable the regulator output if no other consumer
+ * devices have it enabled, the regulator device supports disabling and
+ * machine constraints permit this operation.
*/
int regulator_disable(struct regulator *regulator)
{
- int ret;
-
- if (!regulator->enabled) {
- printk(KERN_ERR "%s: not in use by this consumer\n",
- __func__);
- return 0;
- }
+ struct regulator_dev *rdev = regulator->rdev;
+ int ret = 0;
- mutex_lock(&regulator->rdev->mutex);
- regulator->enabled = 0;
- regulator->uA_load = 0;
- ret = _regulator_disable(regulator->rdev);
- mutex_unlock(&regulator->rdev->mutex);
+ mutex_lock(&rdev->mutex);
+ if (regulator->enabled == 1) {
+ ret = _regulator_disable(rdev);
+ if (ret == 0)
+ regulator->uA_load = 0;
+ } else if (WARN(regulator->enabled <= 0,
+ "unbalanced disables for supply %s\n",
+ regulator->supply_name))
+ ret = -EIO;
+ if (ret == 0)
+ regulator->enabled--;
+ mutex_unlock(&rdev->mutex);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_disable);
@@ -1196,7 +1189,13 @@ out:
* regulator_is_enabled - is the regulator output enabled
* @regulator: regulator source
*
- * Returns zero for disabled otherwise return number of enable requests.
+ * Returns positive if the regulator driver backing the source/client
+ * has requested that the device be enabled, zero if it hasn't, else a
+ * negative errno code.
+ *
+ * Note that the device backing this regulator handle can have multiple
+ * users, so it might be enabled even if regulator_enable() was never
+ * called for this particular source.
*/
int regulator_is_enabled(struct regulator *regulator)
{
@@ -1219,7 +1218,7 @@ EXPORT_SYMBOL_GPL(regulator_is_enabled);
*
* NOTE: If the regulator is shared between several devices then the lowest
* request voltage that meets the system constraints will be used.
- * NOTE: Regulator system constraints must be set for this regulator before
+ * Regulator system constraints must be set for this regulator before
* calling this function otherwise this call will fail.
*/
int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
@@ -1493,7 +1492,8 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
mode = rdev->desc->ops->get_optimum_mode(rdev,
input_uV, output_uV,
total_uA_load);
- if (ret <= 0) {
+ ret = regulator_check_mode(rdev, mode);
+ if (ret < 0) {
printk(KERN_ERR "%s: failed to get optimum mode for %s @"
" %d uA %d -> %d uV\n", __func__, rdev->desc->name,
total_uA_load, input_uV, output_uV);
@@ -1501,7 +1501,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
}
ret = rdev->desc->ops->set_mode(rdev, mode);
- if (ret <= 0) {
+ if (ret < 0) {
printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n",
__func__, mode, rdev->desc->name);
goto out;
@@ -1516,7 +1516,7 @@ EXPORT_SYMBOL_GPL(regulator_set_optimum_mode);
/**
* regulator_register_notifier - register regulator event notifier
* @regulator: regulator source
- * @notifier_block: notifier block
+ * @nb: notifier block
*
* Register notifier block to receive regulator events.
*/
@@ -1531,7 +1531,7 @@ EXPORT_SYMBOL_GPL(regulator_register_notifier);
/**
* regulator_unregister_notifier - unregister regulator event notifier
* @regulator: regulator source
- * @notifier_block: notifier block
+ * @nb: notifier block
*
* Unregister regulator event notifier block.
*/
@@ -1697,9 +1697,9 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free);
/**
* regulator_notifier_call_chain - call regulator event notifier
- * @regulator: regulator source
+ * @rdev: regulator source
* @event: notifier block
- * @data:
+ * @data: callback-specific data.
*
* Called by regulator drivers to notify clients a regulator event has
* occurred. We also notify regulator clients downstream.
@@ -1713,10 +1713,122 @@ int regulator_notifier_call_chain(struct regulator_dev *rdev,
}
EXPORT_SYMBOL_GPL(regulator_notifier_call_chain);
+/*
+ * To avoid cluttering sysfs (and memory) with useless state, only
+ * create attributes that can be meaningfully displayed.
+ */
+static int add_regulator_attributes(struct regulator_dev *rdev)
+{
+ struct device *dev = &rdev->dev;
+ struct regulator_ops *ops = rdev->desc->ops;
+ int status = 0;
+
+ /* some attributes need specific methods to be displayed */
+ if (ops->get_voltage) {
+ status = device_create_file(dev, &dev_attr_microvolts);
+ if (status < 0)
+ return status;
+ }
+ if (ops->get_current_limit) {
+ status = device_create_file(dev, &dev_attr_microamps);
+ if (status < 0)
+ return status;
+ }
+ if (ops->get_mode) {
+ status = device_create_file(dev, &dev_attr_opmode);
+ if (status < 0)
+ return status;
+ }
+ if (ops->is_enabled) {
+ status = device_create_file(dev, &dev_attr_state);
+ if (status < 0)
+ return status;
+ }
+
+ /* some attributes are type-specific */
+ if (rdev->desc->type == REGULATOR_CURRENT) {
+ status = device_create_file(dev, &dev_attr_requested_microamps);
+ if (status < 0)
+ return status;
+ }
+
+ /* all the other attributes exist to support constraints;
+ * don't show them if there are no constraints, or if the
+ * relevant supporting methods are missing.
+ */
+ if (!rdev->constraints)
+ return status;
+
+ /* constraints need specific supporting methods */
+ if (ops->set_voltage) {
+ status = device_create_file(dev, &dev_attr_min_microvolts);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev, &dev_attr_max_microvolts);
+ if (status < 0)
+ return status;
+ }
+ if (ops->set_current_limit) {
+ status = device_create_file(dev, &dev_attr_min_microamps);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev, &dev_attr_max_microamps);
+ if (status < 0)
+ return status;
+ }
+
+ /* suspend mode constraints need multiple supporting methods */
+ if (!(ops->set_suspend_enable && ops->set_suspend_disable))
+ return status;
+
+ status = device_create_file(dev, &dev_attr_suspend_standby_state);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev, &dev_attr_suspend_mem_state);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev, &dev_attr_suspend_disk_state);
+ if (status < 0)
+ return status;
+
+ if (ops->set_suspend_voltage) {
+ status = device_create_file(dev,
+ &dev_attr_suspend_standby_microvolts);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev,
+ &dev_attr_suspend_mem_microvolts);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev,
+ &dev_attr_suspend_disk_microvolts);
+ if (status < 0)
+ return status;
+ }
+
+ if (ops->set_suspend_mode) {
+ status = device_create_file(dev,
+ &dev_attr_suspend_standby_mode);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev,
+ &dev_attr_suspend_mem_mode);
+ if (status < 0)
+ return status;
+ status = device_create_file(dev,
+ &dev_attr_suspend_disk_mode);
+ if (status < 0)
+ return status;
+ }
+
+ return status;
+}
+
/**
* regulator_register - register regulator
- * @regulator: regulator source
- * @reg_data: private regulator data
+ * @regulator_desc: regulator to register
+ * @dev: struct device for the regulator
+ * @driver_data: private regulator data
*
* Called by regulator drivers to register a regulator.
* Returns 0 on success.
@@ -1761,45 +1873,37 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
/* preform any regulator specific init */
if (init_data->regulator_init) {
ret = init_data->regulator_init(rdev->reg_data);
- if (ret < 0) {
- kfree(rdev);
- rdev = ERR_PTR(ret);
- goto out;
- }
- }
-
- /* set regulator constraints */
- ret = set_machine_constraints(rdev, &init_data->constraints);
- if (ret < 0) {
- kfree(rdev);
- rdev = ERR_PTR(ret);
- goto out;
+ if (ret < 0)
+ goto clean;
}
/* register with sysfs */
rdev->dev.class = &regulator_class;
rdev->dev.parent = dev;
- snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id),
- "regulator.%d", atomic_inc_return(&regulator_no) - 1);
+ dev_set_name(&rdev->dev, "regulator.%d",
+ atomic_inc_return(&regulator_no) - 1);
ret = device_register(&rdev->dev);
- if (ret != 0) {
- kfree(rdev);
- rdev = ERR_PTR(ret);
- goto out;
- }
+ if (ret != 0)
+ goto clean;
dev_set_drvdata(&rdev->dev, rdev);
+ /* set regulator constraints */
+ ret = set_machine_constraints(rdev, &init_data->constraints);
+ if (ret < 0)
+ goto scrub;
+
+ /* add attributes supported by this regulator */
+ ret = add_regulator_attributes(rdev);
+ if (ret < 0)
+ goto scrub;
+
/* set supply regulator if it exists */
if (init_data->supply_regulator_dev) {
ret = set_supply(rdev,
dev_get_drvdata(init_data->supply_regulator_dev));
- if (ret < 0) {
- device_unregister(&rdev->dev);
- kfree(rdev);
- rdev = ERR_PTR(ret);
- goto out;
- }
+ if (ret < 0)
+ goto scrub;
}
/* add consumers devices */
@@ -1811,10 +1915,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
for (--i; i >= 0; i--)
unset_consumer_device_supply(rdev,
init_data->consumer_supplies[i].dev);
- device_unregister(&rdev->dev);
- kfree(rdev);
- rdev = ERR_PTR(ret);
- goto out;
+ goto scrub;
}
}
@@ -1822,12 +1923,19 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
out:
mutex_unlock(&regulator_list_mutex);
return rdev;
+
+scrub:
+ device_unregister(&rdev->dev);
+clean:
+ kfree(rdev);
+ rdev = ERR_PTR(ret);
+ goto out;
}
EXPORT_SYMBOL_GPL(regulator_register);
/**
* regulator_unregister - unregister regulator
- * @regulator: regulator source
+ * @rdev: regulator to unregister
*
* Called by regulator drivers to unregister a regulator.
*/
@@ -1846,7 +1954,7 @@ void regulator_unregister(struct regulator_dev *rdev)
EXPORT_SYMBOL_GPL(regulator_unregister);
/**
- * regulator_suspend_prepare: prepare regulators for system wide suspend
+ * regulator_suspend_prepare - prepare regulators for system wide suspend
* @state: system suspend state
*
* Configure each regulator with it's suspend operating parameters for state.
@@ -1882,7 +1990,7 @@ EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
/**
* rdev_get_drvdata - get rdev regulator driver data
- * @regulator: regulator
+ * @rdev: regulator
*
* Get rdev regulator driver private data. This call can be used in the
* regulator driver context.
@@ -1919,7 +2027,7 @@ EXPORT_SYMBOL_GPL(regulator_set_drvdata);
/**
* regulator_get_id - get regulator ID
- * @regulator: regulator
+ * @rdev: regulator
*/
int rdev_get_id(struct regulator_dev *rdev)
{
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c
index 773b29cec8be..fe77730a7edb 100644
--- a/drivers/regulator/da903x.c
+++ b/drivers/regulator/da903x.c
@@ -102,7 +102,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev,
uint8_t val, mask;
if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
return -EINVAL;
}
@@ -159,7 +159,7 @@ static int da903x_is_enabled(struct regulator_dev *rdev)
if (ret)
return ret;
- return reg_val & (1 << info->enable_bit);
+ return !!(reg_val & (1 << info->enable_bit));
}
/* DA9030 specific operations */
@@ -172,7 +172,7 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev,
int ret;
if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
return -EINVAL;
}
@@ -199,7 +199,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev,
int thresh;
if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
return -EINVAL;
}
@@ -248,7 +248,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev,
int ret;
if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
return -EINVAL;
}
@@ -273,7 +273,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev,
uint8_t val, mask;
if (check_range(info, min_uV, max_uV)) {
- pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV);
+ pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV);
return -EINVAL;
}
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c
new file mode 100644
index 000000000000..4cc85ec6e120
--- /dev/null
+++ b/drivers/regulator/pcf50633-regulator.c
@@ -0,0 +1,329 @@
+/* NXP PCF50633 PMIC Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte and Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/pcf50633/core.h>
+#include <linux/mfd/pcf50633/pmic.h>
+
+#define PCF50633_REGULATOR(_name, _id) \
+ { \
+ .name = _name, \
+ .id = _id, \
+ .ops = &pcf50633_regulator_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ }
+
+static const u8 pcf50633_regulator_registers[PCF50633_NUM_REGULATORS] = {
+ [PCF50633_REGULATOR_AUTO] = PCF50633_REG_AUTOOUT,
+ [PCF50633_REGULATOR_DOWN1] = PCF50633_REG_DOWN1OUT,
+ [PCF50633_REGULATOR_DOWN2] = PCF50633_REG_DOWN2OUT,
+ [PCF50633_REGULATOR_MEMLDO] = PCF50633_REG_MEMLDOOUT,
+ [PCF50633_REGULATOR_LDO1] = PCF50633_REG_LDO1OUT,
+ [PCF50633_REGULATOR_LDO2] = PCF50633_REG_LDO2OUT,
+ [PCF50633_REGULATOR_LDO3] = PCF50633_REG_LDO3OUT,
+ [PCF50633_REGULATOR_LDO4] = PCF50633_REG_LDO4OUT,
+ [PCF50633_REGULATOR_LDO5] = PCF50633_REG_LDO5OUT,
+ [PCF50633_REGULATOR_LDO6] = PCF50633_REG_LDO6OUT,
+ [PCF50633_REGULATOR_HCLDO] = PCF50633_REG_HCLDOOUT,
+};
+
+/* Bits from voltage value */
+static u8 auto_voltage_bits(unsigned int millivolts)
+{
+ if (millivolts < 1800)
+ return 0;
+ if (millivolts > 3800)
+ return 0xff;
+
+ millivolts -= 625;
+
+ return millivolts / 25;
+}
+
+static u8 down_voltage_bits(unsigned int millivolts)
+{
+ if (millivolts < 625)
+ return 0;
+ else if (millivolts > 3000)
+ return 0xff;
+
+ millivolts -= 625;
+
+ return millivolts / 25;
+}
+
+static u8 ldo_voltage_bits(unsigned int millivolts)
+{
+ if (millivolts < 900)
+ return 0;
+ else if (millivolts > 3600)
+ return 0x1f;
+
+ millivolts -= 900;
+ return millivolts / 100;
+}
+
+/* Obtain voltage value from bits */
+static unsigned int auto_voltage_value(u8 bits)
+{
+ if (bits < 0x2f)
+ return 0;
+
+ return 625 + (bits * 25);
+}
+
+
+static unsigned int down_voltage_value(u8 bits)
+{
+ return 625 + (bits * 25);
+}
+
+
+static unsigned int ldo_voltage_value(u8 bits)
+{
+ bits &= 0x1f;
+
+ return 900 + (bits * 100);
+}
+
+static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct pcf50633 *pcf;
+ int regulator_id, millivolts;
+ u8 volt_bits, regnr;
+
+ pcf = rdev_get_drvdata(rdev);
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ millivolts = min_uV / 1000;
+
+ regnr = pcf50633_regulator_registers[regulator_id];
+
+ switch (regulator_id) {
+ case PCF50633_REGULATOR_AUTO:
+ volt_bits = auto_voltage_bits(millivolts);
+ break;
+ case PCF50633_REGULATOR_DOWN1:
+ volt_bits = down_voltage_bits(millivolts);
+ break;
+ case PCF50633_REGULATOR_DOWN2:
+ volt_bits = down_voltage_bits(millivolts);
+ break;
+ case PCF50633_REGULATOR_LDO1:
+ case PCF50633_REGULATOR_LDO2:
+ case PCF50633_REGULATOR_LDO3:
+ case PCF50633_REGULATOR_LDO4:
+ case PCF50633_REGULATOR_LDO5:
+ case PCF50633_REGULATOR_LDO6:
+ case PCF50633_REGULATOR_HCLDO:
+ volt_bits = ldo_voltage_bits(millivolts);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return pcf50633_reg_write(pcf, regnr, volt_bits);
+}
+
+static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf;
+ int regulator_id, millivolts, volt_bits;
+ u8 regnr;
+
+ pcf = rdev_get_drvdata(rdev);;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ regnr = pcf50633_regulator_registers[regulator_id];
+
+ volt_bits = pcf50633_reg_read(pcf, regnr);
+ if (volt_bits < 0)
+ return -1;
+
+ switch (regulator_id) {
+ case PCF50633_REGULATOR_AUTO:
+ millivolts = auto_voltage_value(volt_bits);
+ break;
+ case PCF50633_REGULATOR_DOWN1:
+ millivolts = down_voltage_value(volt_bits);
+ break;
+ case PCF50633_REGULATOR_DOWN2:
+ millivolts = down_voltage_value(volt_bits);
+ break;
+ case PCF50633_REGULATOR_LDO1:
+ case PCF50633_REGULATOR_LDO2:
+ case PCF50633_REGULATOR_LDO3:
+ case PCF50633_REGULATOR_LDO4:
+ case PCF50633_REGULATOR_LDO5:
+ case PCF50633_REGULATOR_LDO6:
+ case PCF50633_REGULATOR_HCLDO:
+ millivolts = ldo_voltage_value(volt_bits);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return millivolts * 1000;
+}
+
+static int pcf50633_regulator_enable(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf = rdev_get_drvdata(rdev);
+ int regulator_id;
+ u8 regnr;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ /* The *ENA register is always one after the *OUT register */
+ regnr = pcf50633_regulator_registers[regulator_id] + 1;
+
+ return pcf50633_reg_set_bit_mask(pcf, regnr, PCF50633_REGULATOR_ON,
+ PCF50633_REGULATOR_ON);
+}
+
+static int pcf50633_regulator_disable(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf = rdev_get_drvdata(rdev);
+ int regulator_id;
+ u8 regnr;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ /* the *ENA register is always one after the *OUT register */
+ regnr = pcf50633_regulator_registers[regulator_id] + 1;
+
+ return pcf50633_reg_set_bit_mask(pcf, regnr,
+ PCF50633_REGULATOR_ON, 0);
+}
+
+static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct pcf50633 *pcf = rdev_get_drvdata(rdev);
+ int regulator_id = rdev_get_id(rdev);
+ u8 regnr;
+
+ regulator_id = rdev_get_id(rdev);
+ if (regulator_id >= PCF50633_NUM_REGULATORS)
+ return -EINVAL;
+
+ /* the *ENA register is always one after the *OUT register */
+ regnr = pcf50633_regulator_registers[regulator_id] + 1;
+
+ return pcf50633_reg_read(pcf, regnr) & PCF50633_REGULATOR_ON;
+}
+
+static struct regulator_ops pcf50633_regulator_ops = {
+ .set_voltage = pcf50633_regulator_set_voltage,
+ .get_voltage = pcf50633_regulator_get_voltage,
+ .enable = pcf50633_regulator_enable,
+ .disable = pcf50633_regulator_disable,
+ .is_enabled = pcf50633_regulator_is_enabled,
+};
+
+static struct regulator_desc regulators[] = {
+ [PCF50633_REGULATOR_AUTO] =
+ PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO),
+ [PCF50633_REGULATOR_DOWN1] =
+ PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1),
+ [PCF50633_REGULATOR_DOWN2] =
+ PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2),
+ [PCF50633_REGULATOR_LDO1] =
+ PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1),
+ [PCF50633_REGULATOR_LDO2] =
+ PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2),
+ [PCF50633_REGULATOR_LDO3] =
+ PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3),
+ [PCF50633_REGULATOR_LDO4] =
+ PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4),
+ [PCF50633_REGULATOR_LDO5] =
+ PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5),
+ [PCF50633_REGULATOR_LDO6] =
+ PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6),
+ [PCF50633_REGULATOR_HCLDO] =
+ PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO),
+ [PCF50633_REGULATOR_MEMLDO] =
+ PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO),
+};
+
+static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+ struct pcf50633 *pcf;
+
+ /* Already set by core driver */
+ pcf = platform_get_drvdata(pdev);
+
+ rdev = regulator_register(&regulators[pdev->id], &pdev->dev, pcf);
+ if (IS_ERR(rdev))
+ return PTR_ERR(rdev);
+
+ if (pcf->pdata->regulator_registered)
+ pcf->pdata->regulator_registered(pcf, pdev->id);
+
+ return 0;
+}
+
+static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_regulator_driver = {
+ .driver = {
+ .name = "pcf50633-regltr",
+ },
+ .probe = pcf50633_regulator_probe,
+ .remove = __devexit_p(pcf50633_regulator_remove),
+};
+
+static int __init pcf50633_regulator_init(void)
+{
+ return platform_driver_register(&pcf50633_regulator_driver);
+}
+module_init(pcf50633_regulator_init);
+
+static void __exit pcf50633_regulator_exit(void)
+{
+ platform_driver_unregister(&pcf50633_regulator_driver);
+}
+module_exit(pcf50633_regulator_exit);
+
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_DESCRIPTION("PCF50633 regulator driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pcf50633-regulator");
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 1f44b17e23b1..5056e23e4414 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1380,6 +1380,13 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
if (wm8350->pmic.pdev[reg])
return -EBUSY;
+ if (reg >= WM8350_DCDC_1 && reg <= WM8350_DCDC_6 &&
+ reg > wm8350->pmic.max_dcdc)
+ return -ENODEV;
+ if (reg >= WM8350_ISINK_A && reg <= WM8350_ISINK_B &&
+ reg > wm8350->pmic.max_isink)
+ return -ENODEV;
+
pdev = platform_device_alloc("wm8350-regulator", reg);
if (!pdev)
return -ENOMEM;
@@ -1405,6 +1412,97 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg,
}
EXPORT_SYMBOL_GPL(wm8350_register_regulator);
+/**
+ * wm8350_register_led - Register a WM8350 LED output
+ *
+ * @param wm8350 The WM8350 device to configure.
+ * @param lednum LED device index to create.
+ * @param dcdc The DCDC to use for the LED.
+ * @param isink The ISINK to use for the LED.
+ * @param pdata Configuration for the LED.
+ *
+ * The WM8350 supports the use of an ISINK together with a DCDC to
+ * provide a power-efficient LED driver. This function registers the
+ * regulators and instantiates the platform device for a LED. The
+ * operating modes for the LED regulators must be configured using
+ * wm8350_isink_set_flash(), wm8350_dcdc25_set_mode() and
+ * wm8350_dcdc_set_slot() prior to calling this function.
+ */
+int wm8350_register_led(struct wm8350 *wm8350, int lednum, int dcdc, int isink,
+ struct wm8350_led_platform_data *pdata)
+{
+ struct wm8350_led *led;
+ struct platform_device *pdev;
+ int ret;
+
+ if (lednum >= ARRAY_SIZE(wm8350->pmic.led) || lednum < 0) {
+ dev_err(wm8350->dev, "Invalid LED index %d\n", lednum);
+ return -ENODEV;
+ }
+
+ led = &wm8350->pmic.led[lednum];
+
+ if (led->pdev) {
+ dev_err(wm8350->dev, "LED %d already allocated\n", lednum);
+ return -EINVAL;
+ }
+
+ pdev = platform_device_alloc("wm8350-led", lednum);
+ if (pdev == NULL) {
+ dev_err(wm8350->dev, "Failed to allocate LED %d\n", lednum);
+ return -ENOMEM;
+ }
+
+ led->isink_consumer.dev = &pdev->dev;
+ led->isink_consumer.supply = "led_isink";
+ led->isink_init.num_consumer_supplies = 1;
+ led->isink_init.consumer_supplies = &led->isink_consumer;
+ led->isink_init.constraints.min_uA = 0;
+ led->isink_init.constraints.max_uA = pdata->max_uA;
+ led->isink_init.constraints.valid_ops_mask = REGULATOR_CHANGE_CURRENT;
+ led->isink_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
+ ret = wm8350_register_regulator(wm8350, isink, &led->isink_init);
+ if (ret != 0) {
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ led->dcdc_consumer.dev = &pdev->dev;
+ led->dcdc_consumer.supply = "led_vcc";
+ led->dcdc_init.num_consumer_supplies = 1;
+ led->dcdc_init.consumer_supplies = &led->dcdc_consumer;
+ led->dcdc_init.constraints.valid_modes_mask = REGULATOR_MODE_NORMAL;
+ ret = wm8350_register_regulator(wm8350, dcdc, &led->dcdc_init);
+ if (ret != 0) {
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ switch (isink) {
+ case WM8350_ISINK_A:
+ wm8350->pmic.isink_A_dcdc = dcdc;
+ break;
+ case WM8350_ISINK_B:
+ wm8350->pmic.isink_B_dcdc = dcdc;
+ break;
+ }
+
+ pdev->dev.platform_data = pdata;
+ pdev->dev.parent = wm8350->dev;
+ ret = platform_device_add(pdev);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Failed to register LED %d: %d\n",
+ lednum, ret);
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ led->pdev = pdev;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(wm8350_register_led);
+
static struct platform_driver wm8350_regulator_driver = {
.probe = wm8350_regulator_probe,
.remove = wm8350_regulator_remove,
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c
index 48b372e038a8..56e23d44ba59 100644
--- a/drivers/regulator/wm8400-regulator.c
+++ b/drivers/regulator/wm8400-regulator.c
@@ -289,7 +289,7 @@ static struct regulator_desc regulators[] = {
},
};
-static int __init wm8400_regulator_probe(struct platform_device *pdev)
+static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
{
struct regulator_dev *rdev;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 123092d8a984..81450fbd8b12 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -35,8 +35,8 @@ config RTC_HCTOSYS_DEVICE
default "rtc0"
help
The RTC device that will be used to (re)initialize the system
- clock, usually rtc0. Initialization is done when the system
- starts up, and when it resumes from a low power state. This
+ clock, usually rtc0. Initialization is done when the system
+ starts up, and when it resumes from a low power state. This
device should record time in UTC, since the kernel won't do
timezone correction.
@@ -44,7 +44,7 @@ config RTC_HCTOSYS_DEVICE
functions run, so it must usually be statically linked.
This clock should be battery-backed, so that it reads the correct
- time when the system boots from a power-off state. Otherwise, your
+ time when the system boots from a power-off state. Otherwise, your
system will need an external clock source (like an NTP server).
If the clock you specify here is not battery backed, it may still
@@ -69,8 +69,7 @@ config RTC_INTF_SYSFS
Say yes here if you want to use your RTCs using sysfs interfaces,
/sys/class/rtc/rtc0 through /sys/.../rtcN.
- This driver can also be built as a module. If so, the module
- will be called rtc-sysfs.
+ If unsure, say Y.
config RTC_INTF_PROC
boolean "/proc/driver/rtc (procfs for rtc0)"
@@ -78,11 +77,10 @@ config RTC_INTF_PROC
default RTC_CLASS
help
Say yes here if you want to use your first RTC through the proc
- interface, /proc/driver/rtc. Other RTCs will not be available
+ interface, /proc/driver/rtc. Other RTCs will not be available
through that API.
- This driver can also be built as a module. If so, the module
- will be called rtc-proc.
+ If unsure, say Y.
config RTC_INTF_DEV
boolean "/dev/rtcN (character devices)"
@@ -90,21 +88,27 @@ config RTC_INTF_DEV
help
Say yes here if you want to use your RTCs using the /dev
interfaces, which "udev" sets up as /dev/rtc0 through
- /dev/rtcN. You may want to set up a symbolic link so one
- of these can be accessed as /dev/rtc, which is a name
- expected by "hwclock" and some other programs.
+ /dev/rtcN.
- This driver can also be built as a module. If so, the module
- will be called rtc-dev.
+ You may want to set up a symbolic link so one of these
+ can be accessed as /dev/rtc, which is a name
+ expected by "hwclock" and some other programs. Recent
+ versions of "udev" are known to set up the symlink for you.
+
+ If unsure, say Y.
config RTC_INTF_DEV_UIE_EMUL
bool "RTC UIE emulation on dev interface"
depends on RTC_INTF_DEV
help
Provides an emulation for RTC_UIE if the underlying rtc chip
- driver does not expose RTC_UIE ioctls. Those requests generate
+ driver does not expose RTC_UIE ioctls. Those requests generate
once-per-second update interrupts, used for synchronization.
+ The emulation code will read the time from the hardware
+ clock several times per second, please enable this option
+ only if you know that you really need it.
+
config RTC_DRV_TEST
tristate "Test driver/device"
help
@@ -128,14 +132,14 @@ config RTC_DRV_DS1307
tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00"
help
If you say yes here you get support for various compatible RTC
- chips (often with battery backup) connected with I2C. This driver
+ chips (often with battery backup) connected with I2C. This driver
should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00,
- and probably other chips. In some cases the RTC must already
+ and probably other chips. In some cases the RTC must already
have been initialized (by manufacturing or a bootloader).
The first seven registers on these chips hold an RTC, and other
registers may add features such as NVRAM, a trickle charger for
- the RTC/NVRAM backup power, and alarms. NVRAM is visible in
+ the RTC/NVRAM backup power, and alarms. NVRAM is visible in
sysfs, but other chip features may not be available.
This driver can also be built as a module. If so, the module
@@ -146,10 +150,10 @@ config RTC_DRV_DS1374
depends on RTC_CLASS && I2C
help
If you say yes here you get support for Dallas Semiconductor
- DS1374 real-time clock chips. If an interrupt is associated
+ DS1374 real-time clock chips. If an interrupt is associated
with the device, the alarm functionality is supported.
- This driver can also be built as a module. If so, the module
+ This driver can also be built as a module. If so, the module
will be called rtc-ds1374.
config RTC_DRV_DS1672
@@ -237,13 +241,19 @@ config RTC_DRV_M41T80_WDT
If you say Y here you will get support for the
watchdog timer in the ST M41T60 and M41T80 RTC chips series.
+config RTC_DRV_DM355EVM
+ tristate "TI DaVinci DM355 EVM RTC"
+ depends on MFD_DM355EVM_MSP
+ help
+ Supports the RTC firmware in the MSP430 on the DM355 EVM.
+
config RTC_DRV_TWL92330
boolean "TI TWL92330/Menelaus"
depends on MENELAUS
help
If you say yes here you get support for the RTC on the
TWL92330 "Menelaus" power management chip, used with OMAP2
- platforms. The support is integrated with the rest of
+ platforms. The support is integrated with the rest of
the Menelaus driver; it's not separate module.
config RTC_DRV_TWL4030
@@ -304,7 +314,7 @@ config RTC_DRV_DS1305
tristate "Dallas/Maxim DS1305/DS1306"
help
Select this driver to get support for the Dallas/Maxim DS1305
- and DS1306 real time clock chips. These support a trickle
+ and DS1306 real time clock chips. These support a trickle
charger, alarms, and NVRAM in addition to the clock.
This driver can also be built as a module. If so, the module
@@ -313,7 +323,8 @@ config RTC_DRV_DS1305
config RTC_DRV_DS1390
tristate "Dallas/Maxim DS1390/93/94"
help
- If you say yes here you get support for the DS1390/93/94 chips.
+ If you say yes here you get support for the
+ Dallas/Maxim DS1390/93/94 chips.
This driver only supports the RTC feature, and not other chip
features such as alarms and trickle charging.
@@ -377,7 +388,7 @@ config RTC_DRV_CMOS
or LPC bus chips, and so on.
Your system will need to define the platform device used by
- this driver, otherwise it won't be accessible. This means
+ this driver, otherwise it won't be accessible. This means
you can safely enable this driver if you don't know whether
or not your board has this kind of hardware.
@@ -497,6 +508,13 @@ config RTC_DRV_WM8350
This driver can also be built as a module. If so, the module
will be called "rtc-wm8350".
+config RTC_DRV_PCF50633
+ depends on MFD_PCF50633
+ tristate "NXP PCF50633 RTC"
+ help
+ If you say yes here you get support for the RTC subsystem of the
+ NXP PCF50633 used in embedded systems.
+
comment "on-CPU RTC drivers"
config RTC_DRV_OMAP
@@ -594,7 +612,7 @@ config RTC_DRV_AT91RM9200
depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL
help
Driver for the internal RTC (Realtime Clock) module found on
- Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips
+ Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips
this is powered by the backup power supply.
config RTC_DRV_AT91SAM9
@@ -616,8 +634,8 @@ config RTC_DRV_AT91SAM9_RTT
prompt "RTT module Number" if ARCH_AT91SAM9263
depends on RTC_DRV_AT91SAM9
help
- More than one RTT module is available. You can choose which
- one will be used as an RTC. The default of zero is normally
+ More than one RTT module is available. You can choose which
+ one will be used as an RTC. The default of zero is normally
OK to use, though some systems use that for non-RTC purposes.
config RTC_DRV_AT91SAM9_GPBR
@@ -629,10 +647,20 @@ config RTC_DRV_AT91SAM9_GPBR
depends on RTC_DRV_AT91SAM9
help
The RTC driver needs to use one of the General Purpose Backup
- Registers (GPBRs) as well as the RTT. You can choose which one
- will be used. The default of zero is normally OK to use, but
+ Registers (GPBRs) as well as the RTT. You can choose which one
+ will be used. The default of zero is normally OK to use, but
on some systems other software needs to use that register.
+config RTC_DRV_AU1XXX
+ tristate "Au1xxx Counter0 RTC support"
+ depends on SOC_AU1X00
+ help
+ This is a driver for the Au1xxx on-chip Counter0 (Time-Of-Year
+ counter) to be used as a RTC.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-au1xxx.
+
config RTC_DRV_BFIN
tristate "Blackfin On-Chip RTC"
depends on BLACKFIN && !BF561
@@ -665,6 +693,17 @@ config RTC_DRV_PPC
the RTC. This exposes that functionality through the generic RTC
class.
+config RTC_DRV_PXA
+ tristate "PXA27x/PXA3xx"
+ depends on ARCH_PXA
+ help
+ If you say Y here you will get access to the real time clock
+ built into your PXA27x or PXA3xx CPU.
+
+ This RTC driver uses PXA RTC registers available since pxa27x
+ series (RDxR, RYxR) instead of legacy RCNR, RTAR.
+
+
config RTC_DRV_SUN4V
bool "SUN4V Hypervisor RTC"
depends on SPARC64
@@ -679,4 +718,22 @@ config RTC_DRV_STARFIRE
If you say Y here you will get support for the RTC found on
Starfire systems.
+config RTC_DRV_TX4939
+ tristate "TX4939 SoC"
+ depends on SOC_TX4939
+ help
+ Driver for the internal RTC (Realtime Clock) module found on
+ Toshiba TX4939 SoC.
+
+config RTC_DRV_MV
+ tristate "Marvell SoC RTC"
+ depends on ARCH_KIRKWOOD
+ help
+ If you say yes here you will get support for the in-chip RTC
+ that can be found in some of Marvell's SoC devices, such as
+ the Kirkwood 88F6281 and 88F6192.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-mv.
+
endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6e79c912bf9e..0e697aa51caa 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -20,8 +20,10 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
+obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o
obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o
obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
+obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o
obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
@@ -47,6 +49,7 @@ obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o
obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
@@ -54,6 +57,7 @@ obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PARISC) += rtc-parisc.o
obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o
+obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
@@ -66,7 +70,9 @@ obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o
+obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 4dfdf019fccc..be5a6b73e601 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -48,9 +48,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg)
struct rtc_time tm;
struct timespec ts = current_kernel_time();
- if (strncmp(rtc->dev.bus_id,
- CONFIG_RTC_HCTOSYS_DEVICE,
- BUS_ID_SIZE) != 0)
+ if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;
rtc_read_time(rtc, &tm);
@@ -71,20 +69,18 @@ static int rtc_resume(struct device *dev)
time_t newtime;
struct timespec time;
- if (strncmp(rtc->dev.bus_id,
- CONFIG_RTC_HCTOSYS_DEVICE,
- BUS_ID_SIZE) != 0)
+ if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
return 0;
rtc_read_time(rtc, &tm);
if (rtc_valid_tm(&tm) != 0) {
- pr_debug("%s: bogus resume time\n", rtc->dev.bus_id);
+ pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev));
return 0;
}
rtc_tm_to_time(&tm, &newtime);
if (newtime <= oldtime) {
if (newtime < oldtime)
- pr_debug("%s: time travel!\n", rtc->dev.bus_id);
+ pr_debug("%s: time travel!\n", dev_name(&rtc->dev));
return 0;
}
@@ -156,7 +152,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
init_waitqueue_head(&rtc->irq_queue);
strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
- snprintf(rtc->dev.bus_id, BUS_ID_SIZE, "rtc%d", id);
+ dev_set_name(&rtc->dev, "rtc%d", id);
rtc_dev_prepare(rtc);
@@ -169,7 +165,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
rtc_proc_add_device(rtc);
dev_info(dev, "rtc core: registered %s as %s\n",
- rtc->name, rtc->dev.bus_id);
+ rtc->name, dev_name(&rtc->dev));
return rtc;
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index a04c1b6b1575..4348c4b0d453 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -50,10 +50,15 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
if (!rtc->ops)
err = -ENODEV;
- else if (!rtc->ops->set_time)
- err = -EINVAL;
- else
+ else if (rtc->ops->set_time)
err = rtc->ops->set_time(rtc->dev.parent, tm);
+ else if (rtc->ops->set_mmss) {
+ unsigned long secs;
+ err = rtc_tm_to_time(tm, &secs);
+ if (err == 0)
+ err = rtc->ops->set_mmss(rtc->dev.parent, secs);
+ } else
+ err = -EINVAL;
mutex_unlock(&rtc->ops_lock);
return err;
@@ -307,6 +312,60 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
}
EXPORT_SYMBOL_GPL(rtc_set_alarm);
+int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
+{
+ int err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return err;
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->alarm_irq_enable)
+ err = -EINVAL;
+ else
+ err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);
+
+ mutex_unlock(&rtc->ops_lock);
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);
+
+int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
+{
+ int err = mutex_lock_interruptible(&rtc->ops_lock);
+ if (err)
+ return err;
+
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+ if (enabled == 0 && rtc->uie_irq_active) {
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_dev_update_irq_enable_emul(rtc, enabled);
+ }
+#endif
+
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->update_irq_enable)
+ err = -EINVAL;
+ else
+ err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled);
+
+ mutex_unlock(&rtc->ops_lock);
+
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+ /*
+ * Enable emulation if the driver did not provide
+ * the update_irq_enable function pointer or if returned
+ * -EINVAL to signal that it has been configured without
+ * interrupts or that are not available at the moment.
+ */
+ if (err == -EINVAL)
+ err = rtc_dev_update_irq_enable_emul(rtc, enabled);
+#endif
+ return err;
+}
+EXPORT_SYMBOL_GPL(rtc_update_irq_enable);
+
/**
* rtc_update_irq - report RTC periodic, alarm, and/or update irqs
* @rtc: the rtc device
@@ -335,7 +394,7 @@ static int __rtc_match(struct device *dev, void *data)
{
char *name = (char *)data;
- if (strncmp(dev->bus_id, name, BUS_ID_SIZE) == 0)
+ if (strcmp(dev_name(dev), name) == 0)
return 1;
return 0;
}
@@ -450,9 +509,6 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
if (rtc->ops->irq_set_freq == NULL)
return -ENXIO;
- if (!is_power_of_2(freq))
- return -EINVAL;
-
spin_lock_irqsave(&rtc->irq_task_lock, flags);
if (rtc->irq_task != NULL && task == NULL)
err = -EBUSY;
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index 90b9a6503e15..e1ec33e40e38 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -205,7 +205,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
{
struct resource *regs;
struct rtc_at32ap700x *rtc;
- int irq = -1;
+ int irq;
int ret;
rtc = kzalloc(sizeof(struct rtc_at32ap700x), GFP_KERNEL);
@@ -222,7 +222,7 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
}
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
+ if (irq <= 0) {
dev_dbg(&pdev->dev, "could not get irq\n");
ret = -ENXIO;
goto out;
diff --git a/drivers/rtc/rtc-au1xxx.c b/drivers/rtc/rtc-au1xxx.c
new file mode 100644
index 000000000000..8906a688e6a6
--- /dev/null
+++ b/drivers/rtc/rtc-au1xxx.c
@@ -0,0 +1,153 @@
+/*
+ * Au1xxx counter0 (aka Time-Of-Year counter) RTC interface driver.
+ *
+ * Copyright (C) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
+ *
+ * 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.
+ */
+
+/* All current Au1xxx SoCs have 2 counters fed by an external 32.768 kHz
+ * crystal. Counter 0, which keeps counting during sleep/powerdown, is
+ * used to count seconds since the beginning of the unix epoch.
+ *
+ * The counters must be configured and enabled by bootloader/board code;
+ * no checks as to whether they really get a proper 32.768kHz clock are
+ * made as this would take far too long.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/* 32kHz clock enabled and detected */
+#define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
+
+static int au1xtoy_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long t;
+
+ t = au_readl(SYS_TOYREAD);
+
+ rtc_time_to_tm(t, tm);
+
+ return rtc_valid_tm(tm);
+}
+
+static int au1xtoy_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long t;
+
+ rtc_tm_to_time(tm, &t);
+
+ au_writel(t, SYS_TOYWRITE);
+ au_sync();
+
+ /* wait for the pending register write to succeed. This can
+ * take up to 6 seconds...
+ */
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+ msleep(1);
+
+ return 0;
+}
+
+static struct rtc_class_ops au1xtoy_rtc_ops = {
+ .read_time = au1xtoy_rtc_read_time,
+ .set_time = au1xtoy_rtc_set_time,
+};
+
+static int __devinit au1xtoy_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtcdev;
+ unsigned long t;
+ int ret;
+
+ t = au_readl(SYS_COUNTER_CNTRL);
+ if (!(t & CNTR_OK)) {
+ dev_err(&pdev->dev, "counters not working; aborting.\n");
+ ret = -ENODEV;
+ goto out_err;
+ }
+
+ ret = -ETIMEDOUT;
+
+ /* set counter0 tickrate to 1Hz if necessary */
+ if (au_readl(SYS_TOYTRIM) != 32767) {
+ /* wait until hardware gives access to TRIM register */
+ t = 0x00100000;
+ while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S) && t--)
+ msleep(1);
+
+ if (!t) {
+ /* timed out waiting for register access; assume
+ * counters are unusable.
+ */
+ dev_err(&pdev->dev, "timeout waiting for access\n");
+ goto out_err;
+ }
+
+ /* set 1Hz TOY tick rate */
+ au_writel(32767, SYS_TOYTRIM);
+ au_sync();
+ }
+
+ /* wait until the hardware allows writes to the counter reg */
+ while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S)
+ msleep(1);
+
+ rtcdev = rtc_device_register("rtc-au1xxx", &pdev->dev,
+ &au1xtoy_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtcdev)) {
+ ret = PTR_ERR(rtcdev);
+ goto out_err;
+ }
+
+ platform_set_drvdata(pdev, rtcdev);
+
+ return 0;
+
+out_err:
+ return ret;
+}
+
+static int __devexit au1xtoy_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_device *rtcdev = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(rtcdev);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver au1xrtc_driver = {
+ .driver = {
+ .name = "rtc-au1xxx",
+ .owner = THIS_MODULE,
+ },
+ .remove = __devexit_p(au1xtoy_rtc_remove),
+};
+
+static int __init au1xtoy_rtc_init(void)
+{
+ return platform_driver_probe(&au1xrtc_driver, au1xtoy_rtc_probe);
+}
+
+static void __exit au1xtoy_rtc_exit(void)
+{
+ platform_driver_unregister(&au1xrtc_driver);
+}
+
+module_init(au1xtoy_rtc_init);
+module_exit(au1xtoy_rtc_exit);
+
+MODULE_DESCRIPTION("Au1xxx TOY-counter-based RTC driver");
+MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rtc-au1xxx");
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
index 34439ce3967e..aafd3e6ebb0d 100644
--- a/drivers/rtc/rtc-bfin.c
+++ b/drivers/rtc/rtc-bfin.c
@@ -390,7 +390,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev)
/* Register our RTC with the RTC framework */
rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE);
- if (unlikely(IS_ERR(rtc))) {
+ if (unlikely(IS_ERR(rtc->rtc_dev))) {
ret = PTR_ERR(rtc->rtc_dev);
goto err_irq;
}
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 6cf8e282338f..b6d35f50e404 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
+#include <linux/log2.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
@@ -58,7 +59,7 @@ struct cmos_rtc {
};
/* both platform and pnp busses use negative numbers for invalid irqs */
-#define is_valid_irq(n) ((n) >= 0)
+#define is_valid_irq(n) ((n) > 0)
static const char driver_name[] = "rtc_cmos";
@@ -384,6 +385,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
if (!is_valid_irq(cmos->irq))
return -ENXIO;
+ if (!is_power_of_2(freq))
+ return -EINVAL;
/* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
f = ffs(freq);
if (f-- > 16)
@@ -729,7 +732,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
cmos_rtc.dev = dev;
dev_set_drvdata(dev, &cmos_rtc);
- rename_region(ports, cmos_rtc.rtc->dev.bus_id);
+ rename_region(ports, dev_name(&cmos_rtc.rtc->dev));
spin_lock_irq(&rtc_lock);
@@ -777,7 +780,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
rtc_cmos_int_handler = cmos_interrupt;
retval = request_irq(rtc_irq, rtc_cmos_int_handler,
- IRQF_DISABLED, cmos_rtc.rtc->dev.bus_id,
+ IRQF_DISABLED, dev_name(&cmos_rtc.rtc->dev),
cmos_rtc.rtc);
if (retval < 0) {
dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
@@ -795,7 +798,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
}
pr_info("%s: alarms up to one %s%s, %zd bytes nvram%s\n",
- cmos_rtc.rtc->dev.bus_id,
+ dev_name(&cmos_rtc.rtc->dev),
is_valid_irq(rtc_irq)
? (cmos_rtc.mon_alrm
? "year"
@@ -885,7 +888,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
}
pr_debug("%s: suspend%s, ctrl %02x\n",
- cmos_rtc.rtc->dev.bus_id,
+ dev_name(&cmos_rtc.rtc->dev),
(tmp & RTC_AIE) ? ", alarm may wake" : "",
tmp);
@@ -941,7 +944,7 @@ static int cmos_resume(struct device *dev)
}
pr_debug("%s: resume, ctrl %02x\n",
- cmos_rtc.rtc->dev.bus_id,
+ dev_name(&cmos_rtc.rtc->dev),
tmp);
return 0;
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index ecdea44ae4e5..45152f4952d6 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -92,10 +92,10 @@ static void rtc_uie_timer(unsigned long data)
spin_unlock_irqrestore(&rtc->irq_lock, flags);
}
-static void clear_uie(struct rtc_device *rtc)
+static int clear_uie(struct rtc_device *rtc)
{
spin_lock_irq(&rtc->irq_lock);
- if (rtc->irq_active) {
+ if (rtc->uie_irq_active) {
rtc->stop_uie_polling = 1;
if (rtc->uie_timer_active) {
spin_unlock_irq(&rtc->irq_lock);
@@ -108,9 +108,10 @@ static void clear_uie(struct rtc_device *rtc)
flush_scheduled_work();
spin_lock_irq(&rtc->irq_lock);
}
- rtc->irq_active = 0;
+ rtc->uie_irq_active = 0;
}
spin_unlock_irq(&rtc->irq_lock);
+ return 0;
}
static int set_uie(struct rtc_device *rtc)
@@ -122,8 +123,8 @@ static int set_uie(struct rtc_device *rtc)
if (err)
return err;
spin_lock_irq(&rtc->irq_lock);
- if (!rtc->irq_active) {
- rtc->irq_active = 1;
+ if (!rtc->uie_irq_active) {
+ rtc->uie_irq_active = 1;
rtc->stop_uie_polling = 0;
rtc->oldsecs = tm.tm_sec;
rtc->uie_task_active = 1;
@@ -134,6 +135,16 @@ static int set_uie(struct rtc_device *rtc)
spin_unlock_irq(&rtc->irq_lock);
return 0;
}
+
+int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled)
+{
+ if (enabled)
+ return set_uie(rtc);
+ else
+ return clear_uie(rtc);
+}
+EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul);
+
#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */
static ssize_t
@@ -357,6 +368,22 @@ static long rtc_dev_ioctl(struct file *file,
err = rtc_irq_set_state(rtc, NULL, 0);
break;
+ case RTC_AIE_ON:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_alarm_irq_enable(rtc, 1);
+
+ case RTC_AIE_OFF:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_alarm_irq_enable(rtc, 0);
+
+ case RTC_UIE_ON:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_update_irq_enable(rtc, 1);
+
+ case RTC_UIE_OFF:
+ mutex_unlock(&rtc->ops_lock);
+ return rtc_update_irq_enable(rtc, 0);
+
case RTC_IRQP_SET:
err = rtc_irq_set_freq(rtc, NULL, arg);
break;
@@ -401,17 +428,6 @@ static long rtc_dev_ioctl(struct file *file,
err = -EFAULT;
return err;
-#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
- case RTC_UIE_OFF:
- mutex_unlock(&rtc->ops_lock);
- clear_uie(rtc);
- return 0;
-
- case RTC_UIE_ON:
- mutex_unlock(&rtc->ops_lock);
- err = set_uie(rtc);
- return err;
-#endif
default:
err = -ENOTTY;
break;
@@ -440,7 +456,10 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
* Leave the alarm alone; it may be set to trigger a system wakeup
* later, or be used by kernel code, and is a one-shot event anyway.
*/
+
+ /* Keep ioctl until all drivers are converted */
rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
+ rtc_update_irq_enable(rtc, 0);
rtc_irq_set_state(rtc, NULL, 0);
if (rtc->ops->release)
diff --git a/drivers/rtc/rtc-dm355evm.c b/drivers/rtc/rtc-dm355evm.c
new file mode 100644
index 000000000000..58d4e18530da
--- /dev/null
+++ b/drivers/rtc/rtc-dm355evm.c
@@ -0,0 +1,175 @@
+/*
+ * rtc-dm355evm.c - access battery-backed counter in MSP430 firmware
+ *
+ * Copyright (c) 2008 by David Brownell
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+#include <linux/i2c/dm355evm_msp.h>
+
+
+/*
+ * The MSP430 firmware on the DM355 EVM uses a watch crystal to feed
+ * a 1 Hz counter. When a backup battery is supplied, that makes a
+ * reasonable RTC for applications where alarms and non-NTP drift
+ * compensation aren't important.
+ *
+ * The only real glitch is the inability to read or write all four
+ * counter bytes atomically: the count may increment in the middle
+ * of an operation, causing trouble when the LSB rolls over.
+ *
+ * This driver was tested with firmware revision A4.
+ */
+union evm_time {
+ u8 bytes[4];
+ u32 value;
+};
+
+static int dm355evm_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ union evm_time time;
+ int status;
+ int tries = 0;
+
+ do {
+ /*
+ * Read LSB(0) to MSB(3) bytes. Defend against the counter
+ * rolling over by re-reading until the value is stable,
+ * and assuming the four reads take at most a few seconds.
+ */
+ status = dm355evm_msp_read(DM355EVM_MSP_RTC_0);
+ if (status < 0)
+ return status;
+ if (tries && time.bytes[0] == status)
+ break;
+ time.bytes[0] = status;
+
+ status = dm355evm_msp_read(DM355EVM_MSP_RTC_1);
+ if (status < 0)
+ return status;
+ if (tries && time.bytes[1] == status)
+ break;
+ time.bytes[1] = status;
+
+ status = dm355evm_msp_read(DM355EVM_MSP_RTC_2);
+ if (status < 0)
+ return status;
+ if (tries && time.bytes[2] == status)
+ break;
+ time.bytes[2] = status;
+
+ status = dm355evm_msp_read(DM355EVM_MSP_RTC_3);
+ if (status < 0)
+ return status;
+ if (tries && time.bytes[3] == status)
+ break;
+ time.bytes[3] = status;
+
+ } while (++tries < 5);
+
+ dev_dbg(dev, "read timestamp %08x\n", time.value);
+
+ rtc_time_to_tm(le32_to_cpu(time.value), tm);
+ return 0;
+}
+
+static int dm355evm_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ union evm_time time;
+ unsigned long value;
+ int status;
+
+ rtc_tm_to_time(tm, &value);
+ time.value = cpu_to_le32(value);
+
+ dev_dbg(dev, "write timestamp %08x\n", time.value);
+
+ /*
+ * REVISIT handle non-atomic writes ... maybe just retry until
+ * byte[1] sticks (no rollover)?
+ */
+ status = dm355evm_msp_write(time.bytes[0], DM355EVM_MSP_RTC_0);
+ if (status < 0)
+ return status;
+
+ status = dm355evm_msp_write(time.bytes[1], DM355EVM_MSP_RTC_1);
+ if (status < 0)
+ return status;
+
+ status = dm355evm_msp_write(time.bytes[2], DM355EVM_MSP_RTC_2);
+ if (status < 0)
+ return status;
+
+ status = dm355evm_msp_write(time.bytes[3], DM355EVM_MSP_RTC_3);
+ if (status < 0)
+ return status;
+
+ return 0;
+}
+
+static struct rtc_class_ops dm355evm_rtc_ops = {
+ .read_time = dm355evm_rtc_read_time,
+ .set_time = dm355evm_rtc_set_time,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit dm355evm_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+
+ rtc = rtc_device_register(pdev->name,
+ &pdev->dev, &dm355evm_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
+ PTR_ERR(rtc));
+ return PTR_ERR(rtc);
+ }
+ platform_set_drvdata(pdev, rtc);
+
+ return 0;
+}
+
+static int __devexit dm355evm_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(rtc);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+/*
+ * I2C is used to talk to the MSP430, but this platform device is
+ * exposed by an MFD driver that manages I2C communications.
+ */
+static struct platform_driver rtc_dm355evm_driver = {
+ .probe = dm355evm_rtc_probe,
+ .remove = __devexit_p(dm355evm_rtc_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "rtc-dm355evm",
+ },
+};
+
+static int __init dm355evm_rtc_init(void)
+{
+ return platform_driver_register(&rtc_dm355evm_driver);
+}
+module_init(dm355evm_rtc_init);
+
+static void __exit dm355evm_rtc_exit(void)
+{
+ platform_driver_unregister(&rtc_dm355evm_driver);
+}
+module_exit(dm355evm_rtc_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c
index 9a234a4ec06d..4aedc705518c 100644
--- a/drivers/rtc/rtc-ds1216.c
+++ b/drivers/rtc/rtc-ds1216.c
@@ -10,7 +10,7 @@
#include <linux/platform_device.h>
#include <linux/bcd.h>
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
struct ds1216_regs {
u8 tsec;
@@ -101,7 +101,8 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_year = bcd2bin(regs.year);
if (tm->tm_year < 70)
tm->tm_year += 100;
- return 0;
+
+ return rtc_valid_tm(tm);
}
static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -138,9 +139,8 @@ static const struct rtc_class_ops ds1216_rtc_ops = {
.set_time = ds1216_rtc_set_time,
};
-static int __devinit ds1216_rtc_probe(struct platform_device *pdev)
+static int __init ds1216_rtc_probe(struct platform_device *pdev)
{
- struct rtc_device *rtc;
struct resource *res;
struct ds1216_priv *priv;
int ret = 0;
@@ -152,7 +152,10 @@ static int __devinit ds1216_rtc_probe(struct platform_device *pdev)
priv = kzalloc(sizeof *priv, GFP_KERNEL);
if (!priv)
return -ENOMEM;
- priv->size = res->end - res->start + 1;
+
+ platform_set_drvdata(pdev, priv);
+
+ priv->size = resource_size(res);
if (!request_mem_region(res->start, priv->size, pdev->name)) {
ret = -EBUSY;
goto out;
@@ -163,22 +166,18 @@ static int __devinit ds1216_rtc_probe(struct platform_device *pdev)
ret = -ENOMEM;
goto out;
}
- rtc = rtc_device_register("ds1216", &pdev->dev,
+ priv->rtc = rtc_device_register("ds1216", &pdev->dev,
&ds1216_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- ret = PTR_ERR(rtc);
+ if (IS_ERR(priv->rtc)) {
+ ret = PTR_ERR(priv->rtc);
goto out;
}
- priv->rtc = rtc;
- platform_set_drvdata(pdev, priv);
/* dummy read to get clock into a known state */
ds1216_read(priv->ioaddr, dummy);
return 0;
out:
- if (priv->rtc)
- rtc_device_unregister(priv->rtc);
if (priv->ioaddr)
iounmap(priv->ioaddr);
if (priv->baseaddr)
@@ -187,7 +186,7 @@ out:
return ret;
}
-static int __devexit ds1216_rtc_remove(struct platform_device *pdev)
+static int __exit ds1216_rtc_remove(struct platform_device *pdev)
{
struct ds1216_priv *priv = platform_get_drvdata(pdev);
@@ -203,13 +202,12 @@ static struct platform_driver ds1216_rtc_platform_driver = {
.name = "rtc-ds1216",
.owner = THIS_MODULE,
},
- .probe = ds1216_rtc_probe,
- .remove = __devexit_p(ds1216_rtc_remove),
+ .remove = __exit_p(ds1216_rtc_remove),
};
static int __init ds1216_rtc_init(void)
{
- return platform_driver_register(&ds1216_rtc_platform_driver);
+ return platform_driver_probe(&ds1216_rtc_platform_driver, ds1216_rtc_probe);
}
static void __exit ds1216_rtc_exit(void)
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 162330b9d1dc..7e5155e88ac7 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -86,13 +86,11 @@ enum ds_type {
struct ds1307 {
- u8 reg_addr;
u8 regs[11];
enum ds_type type;
unsigned long flags;
#define HAS_NVRAM 0 /* bit 0 == sysfs file active */
#define HAS_ALARM 1 /* bit 1 == irq claimed */
- struct i2c_msg msg[2];
struct i2c_client *client;
struct rtc_device *rtc;
struct work_struct work;
@@ -204,13 +202,9 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
int tmp;
/* read the RTC date and time registers all at once */
- ds1307->reg_addr = 0;
- ds1307->msg[1].flags = I2C_M_RD;
- ds1307->msg[1].len = 7;
-
- tmp = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
- ds1307->msg, 2);
- if (tmp != 2) {
+ tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
+ DS1307_REG_SECS, 7, ds1307->regs);
+ if (tmp != 7) {
dev_err(dev, "%s error %d\n", "read", tmp);
return -EIO;
}
@@ -257,7 +251,6 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
t->tm_hour, t->tm_mday,
t->tm_mon, t->tm_year, t->tm_wday);
- *buf++ = 0; /* first register addr */
buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
buf[DS1307_REG_MIN] = bin2bcd(t->tm_min);
buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
@@ -282,23 +275,19 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
break;
}
- ds1307->msg[1].flags = 0;
- ds1307->msg[1].len = 8;
-
dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
"write", buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6]);
- result = i2c_transfer(to_i2c_adapter(ds1307->client->dev.parent),
- &ds1307->msg[1], 1);
- if (result != 1) {
- dev_err(dev, "%s error %d\n", "write", tmp);
- return -EIO;
+ result = i2c_smbus_write_i2c_block_data(ds1307->client, 0, 7, buf);
+ if (result < 0) {
+ dev_err(dev, "%s error %d\n", "write", result);
+ return result;
}
return 0;
}
-static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t)
+static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds1307 *ds1307 = i2c_get_clientdata(client);
@@ -308,13 +297,9 @@ static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t)
return -EINVAL;
/* read all ALARM1, ALARM2, and status registers at once */
- ds1307->reg_addr = DS1339_REG_ALARM1_SECS;
- ds1307->msg[1].flags = I2C_M_RD;
- ds1307->msg[1].len = 9;
-
- ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
- ds1307->msg, 2);
- if (ret != 2) {
+ ret = i2c_smbus_read_i2c_block_data(client,
+ DS1339_REG_ALARM1_SECS, 9, ds1307->regs);
+ if (ret != 9) {
dev_err(dev, "%s error %d\n", "alarm read", ret);
return -EIO;
}
@@ -353,7 +338,7 @@ static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t)
return 0;
}
-static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t)
+static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds1307 *ds1307 = i2c_get_clientdata(client);
@@ -371,13 +356,9 @@ static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t)
t->enabled, t->pending);
/* read current status of both alarms and the chip */
- ds1307->reg_addr = DS1339_REG_ALARM1_SECS;
- ds1307->msg[1].flags = I2C_M_RD;
- ds1307->msg[1].len = 9;
-
- ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
- ds1307->msg, 2);
- if (ret != 2) {
+ ret = i2c_smbus_read_i2c_block_data(client,
+ DS1339_REG_ALARM1_SECS, 9, buf);
+ if (ret != 9) {
dev_err(dev, "%s error %d\n", "alarm write", ret);
return -EIO;
}
@@ -392,7 +373,6 @@ static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t)
ds1307->regs[6], control, status);
/* set ALARM1, using 24 hour and day-of-month modes */
- *buf++ = DS1339_REG_ALARM1_SECS; /* first register addr */
buf[0] = bin2bcd(t->time.tm_sec);
buf[1] = bin2bcd(t->time.tm_min);
buf[2] = bin2bcd(t->time.tm_hour);
@@ -411,14 +391,11 @@ static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t)
}
buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I);
- ds1307->msg[1].flags = 0;
- ds1307->msg[1].len = 10;
-
- ret = i2c_transfer(to_i2c_adapter(client->dev.parent),
- &ds1307->msg[1], 1);
- if (ret != 1) {
+ ret = i2c_smbus_write_i2c_block_data(client,
+ DS1339_REG_ALARM1_SECS, 9, buf);
+ if (ret < 0) {
dev_err(dev, "can't set alarm time\n");
- return -EIO;
+ return ret;
}
return 0;
@@ -475,8 +452,8 @@ static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
static const struct rtc_class_ops ds13xx_rtc_ops = {
.read_time = ds1307_get_time,
.set_time = ds1307_set_time,
- .read_alarm = ds1307_read_alarm,
- .set_alarm = ds1307_set_alarm,
+ .read_alarm = ds1337_read_alarm,
+ .set_alarm = ds1337_set_alarm,
.ioctl = ds1307_ioctl,
};
@@ -490,7 +467,6 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
{
struct i2c_client *client;
struct ds1307 *ds1307;
- struct i2c_msg msg[2];
int result;
client = kobj_to_i2c_client(kobj);
@@ -503,24 +479,10 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
if (unlikely(!count))
return count;
- msg[0].addr = client->addr;
- msg[0].flags = 0;
- msg[0].len = 1;
- msg[0].buf = buf;
-
- buf[0] = 8 + off;
-
- msg[1].addr = client->addr;
- msg[1].flags = I2C_M_RD;
- msg[1].len = count;
- msg[1].buf = buf;
-
- result = i2c_transfer(to_i2c_adapter(client->dev.parent), msg, 2);
- if (result != 2) {
+ result = i2c_smbus_read_i2c_block_data(client, 8 + off, count, buf);
+ if (result < 0)
dev_err(&client->dev, "%s error %d\n", "nvram read", result);
- return -EIO;
- }
- return count;
+ return result;
}
static ssize_t
@@ -528,8 +490,7 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client;
- u8 buffer[NVRAM_SIZE + 1];
- int ret;
+ int result;
client = kobj_to_i2c_client(kobj);
@@ -540,11 +501,12 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
if (unlikely(!count))
return count;
- buffer[0] = 8 + off;
- memcpy(buffer + 1, buf, count);
-
- ret = i2c_master_send(client, buffer, count + 1);
- return (ret < 0) ? ret : (ret - 1);
+ result = i2c_smbus_write_i2c_block_data(client, 8 + off, count, buf);
+ if (result < 0) {
+ dev_err(&client->dev, "%s error %d\n", "nvram write", result);
+ return result;
+ }
+ return count;
}
static struct bin_attribute nvram = {
@@ -571,9 +533,11 @@ static int __devinit ds1307_probe(struct i2c_client *client,
const struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
int want_irq = false;
+ unsigned char *buf;
if (!i2c_check_functionality(adapter,
- I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
return -EIO;
if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL)))
@@ -581,18 +545,8 @@ static int __devinit ds1307_probe(struct i2c_client *client,
ds1307->client = client;
i2c_set_clientdata(client, ds1307);
-
- ds1307->msg[0].addr = client->addr;
- ds1307->msg[0].flags = 0;
- ds1307->msg[0].len = 1;
- ds1307->msg[0].buf = &ds1307->reg_addr;
-
- ds1307->msg[1].addr = client->addr;
- ds1307->msg[1].flags = I2C_M_RD;
- ds1307->msg[1].len = sizeof(ds1307->regs);
- ds1307->msg[1].buf = ds1307->regs;
-
ds1307->type = id->driver_data;
+ buf = ds1307->regs;
switch (ds1307->type) {
case ds_1337:
@@ -602,21 +556,15 @@ static int __devinit ds1307_probe(struct i2c_client *client,
INIT_WORK(&ds1307->work, ds1307_work);
want_irq = true;
}
-
- ds1307->reg_addr = DS1337_REG_CONTROL;
- ds1307->msg[1].len = 2;
-
/* get registers that the "rtc" read below won't read... */
- tmp = i2c_transfer(adapter, ds1307->msg, 2);
+ tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
+ DS1337_REG_CONTROL, 2, buf);
if (tmp != 2) {
pr_debug("read error %d\n", tmp);
err = -EIO;
goto exit_free;
}
- ds1307->reg_addr = 0;
- ds1307->msg[1].len = sizeof(ds1307->regs);
-
/* oscillator off? turn it on, so clock can tick. */
if (ds1307->regs[0] & DS1337_BIT_nEOSC)
ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
@@ -647,9 +595,8 @@ static int __devinit ds1307_probe(struct i2c_client *client,
read_rtc:
/* read RTC registers */
-
- tmp = i2c_transfer(adapter, ds1307->msg, 2);
- if (tmp != 2) {
+ tmp = i2c_smbus_read_i2c_block_data(ds1307->client, 0, 8, buf);
+ if (tmp != 8) {
pr_debug("read error %d\n", tmp);
err = -EIO;
goto exit_free;
@@ -707,22 +654,6 @@ read_rtc:
break;
}
- tmp = ds1307->regs[DS1307_REG_SECS];
- tmp = bcd2bin(tmp & 0x7f);
- if (tmp > 60)
- goto exit_bad;
- tmp = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
- if (tmp > 60)
- goto exit_bad;
-
- tmp = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
- if (tmp == 0 || tmp > 31)
- goto exit_bad;
-
- tmp = bcd2bin(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
- if (tmp == 0 || tmp > 12)
- goto exit_bad;
-
tmp = ds1307->regs[DS1307_REG_HOUR];
switch (ds1307->type) {
case ds_1340:
@@ -779,13 +710,6 @@ read_rtc:
return 0;
-exit_bad:
- dev_dbg(&client->dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
- "bogus register",
- ds1307->regs[0], ds1307->regs[1],
- ds1307->regs[2], ds1307->regs[3],
- ds1307->regs[4], ds1307->regs[5],
- ds1307->regs[6]);
exit_irq:
if (ds1307->rtc)
rtc_device_unregister(ds1307->rtc);
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
index 599e976bf014..e01b955db077 100644
--- a/drivers/rtc/rtc-ds1390.c
+++ b/drivers/rtc/rtc-ds1390.c
@@ -1,5 +1,5 @@
/*
- * rtc-ds1390.c -- driver for DS1390/93/94
+ * rtc-ds1390.c -- driver for the Dallas/Maxim DS1390/93/94 SPI RTC
*
* Copyright (C) 2008 Mercury IMC Ltd
* Written by Mark Jackson <mpfj@mimc.co.uk>
@@ -8,11 +8,13 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * NOTE : Currently this driver only supports the bare minimum for read
- * and write the RTC. The extra features provided by the chip family
+ * NOTE: Currently this driver only supports the bare minimum for read
+ * and write the RTC. The extra features provided by the chip family
* (alarms, trickle charger, different control registers) are unavailable.
*/
+#include <linux/init.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spi/spi.h>
@@ -42,20 +44,6 @@ struct ds1390 {
u8 txrx_buf[9]; /* cmd + 8 registers */
};
-static void ds1390_set_reg(struct device *dev, unsigned char address,
- unsigned char data)
-{
- struct spi_device *spi = to_spi_device(dev);
- struct ds1390 *chip = dev_get_drvdata(dev);
-
- /* Set MSB to indicate write */
- chip->txrx_buf[0] = address | 0x80;
- chip->txrx_buf[1] = data;
-
- /* do the i/o */
- spi_write_then_read(spi, chip->txrx_buf, 2, NULL, 0);
-}
-
static int ds1390_get_reg(struct device *dev, unsigned char address,
unsigned char *data)
{
@@ -78,7 +66,7 @@ static int ds1390_get_reg(struct device *dev, unsigned char address,
return 0;
}
-static int ds1390_get_datetime(struct device *dev, struct rtc_time *dt)
+static int ds1390_read_time(struct device *dev, struct rtc_time *dt)
{
struct spi_device *spi = to_spi_device(dev);
struct ds1390 *chip = dev_get_drvdata(dev);
@@ -107,7 +95,7 @@ static int ds1390_get_datetime(struct device *dev, struct rtc_time *dt)
return rtc_valid_tm(dt);
}
-static int ds1390_set_datetime(struct device *dev, struct rtc_time *dt)
+static int ds1390_set_time(struct device *dev, struct rtc_time *dt)
{
struct spi_device *spi = to_spi_device(dev);
struct ds1390 *chip = dev_get_drvdata(dev);
@@ -127,16 +115,6 @@ static int ds1390_set_datetime(struct device *dev, struct rtc_time *dt)
return spi_write_then_read(spi, chip->txrx_buf, 8, NULL, 0);
}
-static int ds1390_read_time(struct device *dev, struct rtc_time *tm)
-{
- return ds1390_get_datetime(dev, tm);
-}
-
-static int ds1390_set_time(struct device *dev, struct rtc_time *tm)
-{
- return ds1390_set_datetime(dev, tm);
-}
-
static const struct rtc_class_ops ds1390_rtc_ops = {
.read_time = ds1390_read_time,
.set_time = ds1390_set_time,
@@ -144,51 +122,44 @@ static const struct rtc_class_ops ds1390_rtc_ops = {
static int __devinit ds1390_probe(struct spi_device *spi)
{
- struct rtc_device *rtc;
unsigned char tmp;
struct ds1390 *chip;
int res;
- printk(KERN_DEBUG "DS1390 SPI RTC driver\n");
-
- rtc = rtc_device_register("ds1390",
- &spi->dev, &ds1390_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- printk(KERN_ALERT "RTC : unable to register device\n");
- return PTR_ERR(rtc);
- }
-
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
chip = kzalloc(sizeof *chip, GFP_KERNEL);
if (!chip) {
- printk(KERN_ALERT "RTC : unable to allocate device memory\n");
- rtc_device_unregister(rtc);
+ dev_err(&spi->dev, "unable to allocate device memory\n");
return -ENOMEM;
}
- chip->rtc = rtc;
dev_set_drvdata(&spi->dev, chip);
res = ds1390_get_reg(&spi->dev, DS1390_REG_SECONDS, &tmp);
- if (res) {
- printk(KERN_ALERT "RTC : unable to read device\n");
- rtc_device_unregister(rtc);
+ if (res != 0) {
+ dev_err(&spi->dev, "unable to read device\n");
+ kfree(chip);
return res;
}
- return 0;
+ chip->rtc = rtc_device_register("ds1390",
+ &spi->dev, &ds1390_rtc_ops, THIS_MODULE);
+ if (IS_ERR(chip->rtc)) {
+ dev_err(&spi->dev, "unable to register device\n");
+ res = PTR_ERR(chip->rtc);
+ kfree(chip);
+ }
+
+ return res;
}
static int __devexit ds1390_remove(struct spi_device *spi)
{
struct ds1390 *chip = platform_get_drvdata(spi);
- struct rtc_device *rtc = chip->rtc;
-
- if (rtc)
- rtc_device_unregister(rtc);
+ rtc_device_unregister(chip->rtc);
kfree(chip);
return 0;
@@ -215,6 +186,6 @@ static __exit void ds1390_exit(void)
}
module_exit(ds1390_exit);
-MODULE_DESCRIPTION("DS1390/93/94 SPI RTC driver");
+MODULE_DESCRIPTION("Dallas/Maxim DS1390/93/94 SPI RTC driver");
MODULE_AUTHOR("Mark Jackson <mpfj@mimc.co.uk>");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 25caada78398..0b6b7730c716 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -326,9 +326,9 @@ ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0) {
+ if (pdata->irq <= 0)
return -EINVAL;
- }
+
pdata->alrm_mday = alrm->time.tm_mday;
pdata->alrm_hour = alrm->time.tm_hour;
pdata->alrm_min = alrm->time.tm_min;
@@ -346,9 +346,9 @@ ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0) {
+ if (pdata->irq <= 0)
return -EINVAL;
- }
+
alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
@@ -385,7 +385,7 @@ ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0) {
+ if (pdata->irq <= 0) {
return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
}
switch (cmd) {
@@ -503,7 +503,6 @@ ds1511_rtc_probe(struct platform_device *pdev)
if (!pdata) {
return -ENOMEM;
}
- pdata->irq = -1;
pdata->size = res->end - res->start + 1;
if (!request_mem_region(res->start, pdata->size, pdev->name)) {
ret = -EBUSY;
@@ -545,13 +544,13 @@ ds1511_rtc_probe(struct platform_device *pdev)
* if the platform has an interrupt in mind for this device,
* then by all means, set it
*/
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
rtc_read(RTC_CMD1);
if (request_irq(pdata->irq, ds1511_interrupt,
IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) {
dev_warn(&pdev->dev, "interrupt not available.\n");
- pdata->irq = -1;
+ pdata->irq = 0;
}
}
@@ -572,7 +571,7 @@ ds1511_rtc_probe(struct platform_device *pdev)
if (pdata->rtc) {
rtc_device_unregister(pdata->rtc);
}
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
free_irq(pdata->irq, pdev);
}
if (ds1511_base) {
@@ -595,7 +594,7 @@ ds1511_rtc_remove(struct platform_device *pdev)
sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
rtc_device_unregister(pdata->rtc);
pdata->rtc = NULL;
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
/*
* disable the alarm interrupt
*/
@@ -631,7 +630,7 @@ ds1511_rtc_init(void)
static void __exit
ds1511_rtc_exit(void)
{
- return platform_driver_unregister(&ds1511_rtc_driver);
+ platform_driver_unregister(&ds1511_rtc_driver);
}
module_init(ds1511_rtc_init);
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index b9475cd20210..38d472b63406 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -162,7 +162,7 @@ static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
pdata->alrm_mday = alrm->time.tm_mday;
pdata->alrm_hour = alrm->time.tm_hour;
@@ -179,7 +179,7 @@ static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
@@ -213,7 +213,7 @@ static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
switch (cmd) {
case RTC_AIE_OFF:
@@ -301,7 +301,6 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- pdata->irq = -1;
if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
ret = -EBUSY;
goto out;
@@ -327,13 +326,13 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF)
dev_warn(&pdev->dev, "voltage-low detected.\n");
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, ioaddr + RTC_INTERRUPTS);
if (request_irq(pdata->irq, ds1553_rtc_interrupt,
IRQF_DISABLED | IRQF_SHARED,
pdev->name, pdev) < 0) {
dev_warn(&pdev->dev, "interrupt not available.\n");
- pdata->irq = -1;
+ pdata->irq = 0;
}
}
@@ -353,7 +352,7 @@ static int __devinit ds1553_rtc_probe(struct platform_device *pdev)
out:
if (pdata->rtc)
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0)
+ if (pdata->irq > 0)
free_irq(pdata->irq, pdev);
if (ioaddr)
iounmap(ioaddr);
@@ -369,7 +368,7 @@ static int __devexit ds1553_rtc_remove(struct platform_device *pdev)
sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
free_irq(pdata->irq, pdev);
}
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c
index 4e91419e8911..06dfb54f99b6 100644
--- a/drivers/rtc/rtc-ds1672.c
+++ b/drivers/rtc/rtc-ds1672.c
@@ -83,32 +83,11 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs)
return 0;
}
-static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm)
-{
- unsigned long secs;
-
- dev_dbg(&client->dev,
- "%s: secs=%d, mins=%d, hours=%d, "
- "mday=%d, mon=%d, year=%d, wday=%d\n",
- __func__,
- tm->tm_sec, tm->tm_min, tm->tm_hour,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
-
- rtc_tm_to_time(tm, &secs);
-
- return ds1672_set_mmss(client, secs);
-}
-
static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return ds1672_get_datetime(to_i2c_client(dev), tm);
}
-static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return ds1672_set_datetime(to_i2c_client(dev), tm);
-}
-
static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs)
{
return ds1672_set_mmss(to_i2c_client(dev), secs);
@@ -152,7 +131,6 @@ static DEVICE_ATTR(control, S_IRUGO, show_control, NULL);
static const struct rtc_class_ops ds1672_rtc_ops = {
.read_time = ds1672_rtc_read_time,
- .set_time = ds1672_rtc_set_time,
.set_mmss = ds1672_rtc_set_mmss,
};
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c
index 45e5b106af73..c51589ede5b7 100644
--- a/drivers/rtc/rtc-ds3234.c
+++ b/drivers/rtc/rtc-ds3234.c
@@ -1,4 +1,4 @@
-/* drivers/rtc/rtc-ds3234.c
+/* rtc-ds3234.c
*
* Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal
* and SRAM.
@@ -9,13 +9,10 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * Changelog:
- *
- * 07-May-2008: Dennis Aberilla <denzzzhome@yahoo.com>
- * - Created based on the max6902 code. Only implements the
- * date/time keeping functions; no SRAM yet.
*/
+#include <linux/init.h>
+#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
@@ -34,16 +31,7 @@
#define DS3234_REG_CONTROL 0x0E
#define DS3234_REG_CONT_STAT 0x0F
-#undef DS3234_DEBUG
-
-struct ds3234 {
- struct rtc_device *rtc;
- u8 buf[8]; /* Burst read: addr + 7 regs */
- u8 tx_buf[2];
- u8 rx_buf[2];
-};
-
-static void ds3234_set_reg(struct device *dev, unsigned char address,
+static int ds3234_set_reg(struct device *dev, unsigned char address,
unsigned char data)
{
struct spi_device *spi = to_spi_device(dev);
@@ -53,107 +41,45 @@ static void ds3234_set_reg(struct device *dev, unsigned char address,
buf[0] = address | 0x80;
buf[1] = data;
- spi_write(spi, buf, 2);
+ return spi_write_then_read(spi, buf, 2, NULL, 0);
}
static int ds3234_get_reg(struct device *dev, unsigned char address,
unsigned char *data)
{
struct spi_device *spi = to_spi_device(dev);
- struct ds3234 *chip = dev_get_drvdata(dev);
- struct spi_message message;
- struct spi_transfer xfer;
- int status;
-
- if (!data)
- return -EINVAL;
-
- /* Build our spi message */
- spi_message_init(&message);
- memset(&xfer, 0, sizeof(xfer));
-
- /* Address + dummy tx byte */
- xfer.len = 2;
- xfer.tx_buf = chip->tx_buf;
- xfer.rx_buf = chip->rx_buf;
-
- chip->tx_buf[0] = address;
- chip->tx_buf[1] = 0xff;
- spi_message_add_tail(&xfer, &message);
+ *data = address & 0x7f;
- /* do the i/o */
- status = spi_sync(spi, &message);
- if (status == 0)
- status = message.status;
- else
- return status;
-
- *data = chip->rx_buf[1];
-
- return status;
+ return spi_write_then_read(spi, data, 1, data, 1);
}
-static int ds3234_get_datetime(struct device *dev, struct rtc_time *dt)
+static int ds3234_read_time(struct device *dev, struct rtc_time *dt)
{
+ int err;
+ unsigned char buf[8];
struct spi_device *spi = to_spi_device(dev);
- struct ds3234 *chip = dev_get_drvdata(dev);
- struct spi_message message;
- struct spi_transfer xfer;
- int status;
-
- /* build the message */
- spi_message_init(&message);
- memset(&xfer, 0, sizeof(xfer));
- xfer.len = 1 + 7; /* Addr + 7 registers */
- xfer.tx_buf = chip->buf;
- xfer.rx_buf = chip->buf;
- chip->buf[0] = 0x00; /* Start address */
- spi_message_add_tail(&xfer, &message);
-
- /* do the i/o */
- status = spi_sync(spi, &message);
- if (status == 0)
- status = message.status;
- else
- return status;
- /* Seconds, Minutes, Hours, Day, Date, Month, Year */
- dt->tm_sec = bcd2bin(chip->buf[1]);
- dt->tm_min = bcd2bin(chip->buf[2]);
- dt->tm_hour = bcd2bin(chip->buf[3] & 0x3f);
- dt->tm_wday = bcd2bin(chip->buf[4]) - 1; /* 0 = Sun */
- dt->tm_mday = bcd2bin(chip->buf[5]);
- dt->tm_mon = bcd2bin(chip->buf[6] & 0x1f) - 1; /* 0 = Jan */
- dt->tm_year = bcd2bin(chip->buf[7] & 0xff) + 100; /* Assume 20YY */
-
-#ifdef DS3234_DEBUG
- dev_dbg(dev, "\n%s : Read RTC values\n", __func__);
- dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
- dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
- dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
- dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
- dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
- dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon);
- dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
-#endif
+ buf[0] = 0x00; /* Start address */
- return 0;
+ err = spi_write_then_read(spi, buf, 1, buf, 8);
+ if (err != 0)
+ return err;
+
+ /* Seconds, Minutes, Hours, Day, Date, Month, Year */
+ dt->tm_sec = bcd2bin(buf[0]);
+ dt->tm_min = bcd2bin(buf[1]);
+ dt->tm_hour = bcd2bin(buf[2] & 0x3f);
+ dt->tm_wday = bcd2bin(buf[3]) - 1; /* 0 = Sun */
+ dt->tm_mday = bcd2bin(buf[4]);
+ dt->tm_mon = bcd2bin(buf[5] & 0x1f) - 1; /* 0 = Jan */
+ dt->tm_year = bcd2bin(buf[6] & 0xff) + 100; /* Assume 20YY */
+
+ return rtc_valid_tm(dt);
}
-static int ds3234_set_datetime(struct device *dev, struct rtc_time *dt)
+static int ds3234_set_time(struct device *dev, struct rtc_time *dt)
{
-#ifdef DS3234_DEBUG
- dev_dbg(dev, "\n%s : Setting RTC values\n", __func__);
- dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec);
- dev_dbg(dev, "tm_min : %i\n", dt->tm_min);
- dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour);
- dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday);
- dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday);
- dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon);
- dev_dbg(dev, "tm_year: %i\n", dt->tm_year);
-#endif
-
ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec));
ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min));
ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f);
@@ -174,16 +100,6 @@ static int ds3234_set_datetime(struct device *dev, struct rtc_time *dt)
return 0;
}
-static int ds3234_read_time(struct device *dev, struct rtc_time *tm)
-{
- return ds3234_get_datetime(dev, tm);
-}
-
-static int ds3234_set_time(struct device *dev, struct rtc_time *tm)
-{
- return ds3234_set_datetime(dev, tm);
-}
-
static const struct rtc_class_ops ds3234_rtc_ops = {
.read_time = ds3234_read_time,
.set_time = ds3234_set_time,
@@ -193,31 +109,15 @@ static int __devinit ds3234_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
unsigned char tmp;
- struct ds3234 *chip;
int res;
- rtc = rtc_device_register("ds3234",
- &spi->dev, &ds3234_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
-
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
- chip = kzalloc(sizeof(struct ds3234), GFP_KERNEL);
- if (!chip) {
- rtc_device_unregister(rtc);
- return -ENOMEM;
- }
- chip->rtc = rtc;
- dev_set_drvdata(&spi->dev, chip);
-
res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp);
- if (res) {
- rtc_device_unregister(rtc);
+ if (res != 0)
return res;
- }
/* Control settings
*
@@ -246,26 +146,27 @@ static int __devinit ds3234_probe(struct spi_device *spi)
ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
+ rtc = rtc_device_register("ds3234",
+ &spi->dev, &ds3234_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ dev_set_drvdata(&spi->dev, rtc);
+
return 0;
}
static int __devexit ds3234_remove(struct spi_device *spi)
{
- struct ds3234 *chip = platform_get_drvdata(spi);
- struct rtc_device *rtc = chip->rtc;
-
- if (rtc)
- rtc_device_unregister(rtc);
-
- kfree(chip);
+ struct rtc_device *rtc = platform_get_drvdata(spi);
+ rtc_device_unregister(rtc);
return 0;
}
static struct spi_driver ds3234_driver = {
.driver = {
.name = "ds3234",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = ds3234_probe,
@@ -274,7 +175,6 @@ static struct spi_driver ds3234_driver = {
static __init int ds3234_init(void)
{
- printk(KERN_INFO "DS3234 SPI RTC Driver\n");
return spi_register_driver(&ds3234_driver);
}
module_init(ds3234_init);
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 36e4ac0bd69c..f7a3283dd029 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -49,18 +49,6 @@ static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs)
return 0;
}
-static int ep93xx_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- int err;
- unsigned long secs;
-
- err = rtc_tm_to_time(tm, &secs);
- if (err != 0)
- return err;
-
- return ep93xx_rtc_set_mmss(dev, secs);
-}
-
static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned short preload, delete;
@@ -75,7 +63,6 @@ static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq)
static const struct rtc_class_ops ep93xx_rtc_ops = {
.read_time = ep93xx_rtc_read_time,
- .set_time = ep93xx_rtc_set_time,
.set_mmss = ep93xx_rtc_set_mmss,
.proc = ep93xx_rtc_proc,
};
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 43afb7ab5289..33921a6b1707 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -450,7 +450,7 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
* the mode without IRQ.
*/
m48t59->irq = platform_get_irq(pdev, 0);
- if (m48t59->irq < 0)
+ if (m48t59->irq <= 0)
m48t59->irq = NO_IRQ;
if (m48t59->irq != NO_IRQ) {
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
index 2f6507df7b49..36a8ea9ed8ba 100644
--- a/drivers/rtc/rtc-max6902.c
+++ b/drivers/rtc/rtc-max6902.c
@@ -9,14 +9,6 @@
*
* Driver for MAX6902 spi RTC
*
- * Changelog:
- *
- * 24-May-2006: Raphael Assenat <raph@8d.com>
- * - Major rework
- * Converted to rtc_device and uses the SPI layer.
- *
- * ??-???-2005: Someone at Compulab
- * - Initial driver creation.
*/
#include <linux/module.h>
@@ -26,7 +18,6 @@
#include <linux/rtc.h>
#include <linux/spi/spi.h>
#include <linux/bcd.h>
-#include <linux/delay.h>
#define MAX6902_REG_SECONDS 0x01
#define MAX6902_REG_MINUTES 0x03
@@ -38,16 +29,7 @@
#define MAX6902_REG_CONTROL 0x0F
#define MAX6902_REG_CENTURY 0x13
-#undef MAX6902_DEBUG
-
-struct max6902 {
- struct rtc_device *rtc;
- u8 buf[9]; /* Burst read cmd + 8 registers */
- u8 tx_buf[2];
- u8 rx_buf[2];
-};
-
-static void max6902_set_reg(struct device *dev, unsigned char address,
+static int max6902_set_reg(struct device *dev, unsigned char address,
unsigned char data)
{
struct spi_device *spi = to_spi_device(dev);
@@ -57,113 +39,58 @@ static void max6902_set_reg(struct device *dev, unsigned char address,
buf[0] = address & 0x7f;
buf[1] = data;
- spi_write(spi, buf, 2);
+ return spi_write_then_read(spi, buf, 2, NULL, 0);
}
static int max6902_get_reg(struct device *dev, unsigned char address,
unsigned char *data)
{
struct spi_device *spi = to_spi_device(dev);
- struct max6902 *chip = dev_get_drvdata(dev);
- struct spi_message message;
- struct spi_transfer xfer;
- int status;
-
- if (!data)
- return -EINVAL;
-
- /* Build our spi message */
- spi_message_init(&message);
- memset(&xfer, 0, sizeof(xfer));
- xfer.len = 2;
- /* Can tx_buf and rx_buf be equal? The doc in spi.h is not sure... */
- xfer.tx_buf = chip->tx_buf;
- xfer.rx_buf = chip->rx_buf;
/* Set MSB to indicate read */
- chip->tx_buf[0] = address | 0x80;
-
- spi_message_add_tail(&xfer, &message);
+ *data = address | 0x80;
- /* do the i/o */
- status = spi_sync(spi, &message);
-
- if (status == 0)
- *data = chip->rx_buf[1];
- return status;
+ return spi_write_then_read(spi, data, 1, data, 1);
}
-static int max6902_get_datetime(struct device *dev, struct rtc_time *dt)
+static int max6902_read_time(struct device *dev, struct rtc_time *dt)
{
- unsigned char tmp;
- int century;
- int err;
+ int err, century;
struct spi_device *spi = to_spi_device(dev);
- struct max6902 *chip = dev_get_drvdata(dev);
- struct spi_message message;
- struct spi_transfer xfer;
- int status;
+ unsigned char buf[8];
- err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &tmp);
- if (err)
- return err;
-
- /* build the message */
- spi_message_init(&message);
- memset(&xfer, 0, sizeof(xfer));
- xfer.len = 1 + 7; /* Burst read command + 7 registers */
- xfer.tx_buf = chip->buf;
- xfer.rx_buf = chip->buf;
- chip->buf[0] = 0xbf; /* Burst read */
- spi_message_add_tail(&xfer, &message);
+ buf[0] = 0xbf; /* Burst read */
- /* do the i/o */
- status = spi_sync(spi, &message);
- if (status)
- return status;
+ err = spi_write_then_read(spi, buf, 1, buf, 8);
+ if (err != 0)
+ return err;
/* The chip sends data in this order:
* Seconds, Minutes, Hours, Date, Month, Day, Year */
- dt->tm_sec = bcd2bin(chip->buf[1]);
- dt->tm_min = bcd2bin(chip->buf[2]);
- dt->tm_hour = bcd2bin(chip->buf[3]);
- dt->tm_mday = bcd2bin(chip->buf[4]);
- dt->tm_mon = bcd2bin(chip->buf[5]) - 1;
- dt->tm_wday = bcd2bin(chip->buf[6]);
- dt->tm_year = bcd2bin(chip->buf[7]);
+ dt->tm_sec = bcd2bin(buf[0]);
+ dt->tm_min = bcd2bin(buf[1]);
+ dt->tm_hour = bcd2bin(buf[2]);
+ dt->tm_mday = bcd2bin(buf[3]);
+ dt->tm_mon = bcd2bin(buf[4]) - 1;
+ dt->tm_wday = bcd2bin(buf[5]);
+ dt->tm_year = bcd2bin(buf[6]);
+
+ /* Read century */
+ err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &buf[0]);
+ if (err != 0)
+ return err;
- century = bcd2bin(tmp) * 100;
+ century = bcd2bin(buf[0]) * 100;
dt->tm_year += century;
dt->tm_year -= 1900;
-#ifdef MAX6902_DEBUG
- printk("\n%s : Read RTC values\n",__func__);
- printk("tm_hour: %i\n",dt->tm_hour);
- printk("tm_min : %i\n",dt->tm_min);
- printk("tm_sec : %i\n",dt->tm_sec);
- printk("tm_year: %i\n",dt->tm_year);
- printk("tm_mon : %i\n",dt->tm_mon);
- printk("tm_mday: %i\n",dt->tm_mday);
- printk("tm_wday: %i\n",dt->tm_wday);
-#endif
-
- return 0;
+ return rtc_valid_tm(dt);
}
-static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
+static int max6902_set_time(struct device *dev, struct rtc_time *dt)
{
- dt->tm_year = dt->tm_year+1900;
-
-#ifdef MAX6902_DEBUG
- printk("\n%s : Setting RTC values\n",__func__);
- printk("tm_sec : %i\n",dt->tm_sec);
- printk("tm_min : %i\n",dt->tm_min);
- printk("tm_hour: %i\n",dt->tm_hour);
- printk("tm_mday: %i\n",dt->tm_mday);
- printk("tm_wday: %i\n",dt->tm_wday);
- printk("tm_year: %i\n",dt->tm_year);
-#endif
+ dt->tm_year = dt->tm_year + 1900;
/* Remove write protection */
max6902_set_reg(dev, 0xF, 0);
@@ -173,10 +100,10 @@ static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
max6902_set_reg(dev, 0x05, bin2bcd(dt->tm_hour));
max6902_set_reg(dev, 0x07, bin2bcd(dt->tm_mday));
- max6902_set_reg(dev, 0x09, bin2bcd(dt->tm_mon+1));
+ max6902_set_reg(dev, 0x09, bin2bcd(dt->tm_mon + 1));
max6902_set_reg(dev, 0x0B, bin2bcd(dt->tm_wday));
- max6902_set_reg(dev, 0x0D, bin2bcd(dt->tm_year%100));
- max6902_set_reg(dev, 0x13, bin2bcd(dt->tm_year/100));
+ max6902_set_reg(dev, 0x0D, bin2bcd(dt->tm_year % 100));
+ max6902_set_reg(dev, 0x13, bin2bcd(dt->tm_year / 100));
/* Compulab used a delay here. However, the datasheet
* does not mention a delay being required anywhere... */
@@ -188,16 +115,6 @@ static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
return 0;
}
-static int max6902_read_time(struct device *dev, struct rtc_time *tm)
-{
- return max6902_get_datetime(dev, tm);
-}
-
-static int max6902_set_time(struct device *dev, struct rtc_time *tm)
-{
- return max6902_set_datetime(dev, tm);
-}
-
static const struct rtc_class_ops max6902_rtc_ops = {
.read_time = max6902_read_time,
.set_time = max6902_set_time,
@@ -207,45 +124,29 @@ static int __devinit max6902_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
unsigned char tmp;
- struct max6902 *chip;
int res;
- rtc = rtc_device_register("max6902",
- &spi->dev, &max6902_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
-
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
- chip = kzalloc(sizeof *chip, GFP_KERNEL);
- if (!chip) {
- rtc_device_unregister(rtc);
- return -ENOMEM;
- }
- chip->rtc = rtc;
- dev_set_drvdata(&spi->dev, chip);
-
res = max6902_get_reg(&spi->dev, MAX6902_REG_SECONDS, &tmp);
- if (res) {
- rtc_device_unregister(rtc);
+ if (res != 0)
return res;
- }
+
+ rtc = rtc_device_register("max6902",
+ &spi->dev, &max6902_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
return 0;
}
static int __devexit max6902_remove(struct spi_device *spi)
{
- struct max6902 *chip = platform_get_drvdata(spi);
- struct rtc_device *rtc = chip->rtc;
-
- if (rtc)
- rtc_device_unregister(rtc);
-
- kfree(chip);
+ struct rtc_device *rtc = platform_get_drvdata(spi);
+ rtc_device_unregister(rtc);
return 0;
}
@@ -261,7 +162,6 @@ static struct spi_driver max6902_driver = {
static __init int max6902_init(void)
{
- printk("max6902 spi driver\n");
return spi_register_driver(&max6902_driver);
}
module_init(max6902_init);
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
new file mode 100644
index 000000000000..45f12dcd3716
--- /dev/null
+++ b/drivers/rtc/rtc-mv.c
@@ -0,0 +1,163 @@
+/*
+ * Driver for the RTC in Marvell SoCs.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+
+#define RTC_TIME_REG_OFFS 0
+#define RTC_SECONDS_OFFS 0
+#define RTC_MINUTES_OFFS 8
+#define RTC_HOURS_OFFS 16
+#define RTC_WDAY_OFFS 24
+#define RTC_HOURS_12H_MODE (1 << 22) /* 12 hours mode */
+
+#define RTC_DATE_REG_OFFS 4
+#define RTC_MDAY_OFFS 0
+#define RTC_MONTH_OFFS 8
+#define RTC_YEAR_OFFS 16
+
+
+struct rtc_plat_data {
+ struct rtc_device *rtc;
+ void __iomem *ioaddr;
+};
+
+static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ u32 rtc_reg;
+
+ rtc_reg = (bin2bcd(tm->tm_sec) << RTC_SECONDS_OFFS) |
+ (bin2bcd(tm->tm_min) << RTC_MINUTES_OFFS) |
+ (bin2bcd(tm->tm_hour) << RTC_HOURS_OFFS) |
+ (bin2bcd(tm->tm_wday) << RTC_WDAY_OFFS);
+ writel(rtc_reg, ioaddr + RTC_TIME_REG_OFFS);
+
+ rtc_reg = (bin2bcd(tm->tm_mday) << RTC_MDAY_OFFS) |
+ (bin2bcd(tm->tm_mon + 1) << RTC_MONTH_OFFS) |
+ (bin2bcd(tm->tm_year % 100) << RTC_YEAR_OFFS);
+ writel(rtc_reg, ioaddr + RTC_DATE_REG_OFFS);
+
+ return 0;
+}
+
+static int mv_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ u32 rtc_time, rtc_date;
+ unsigned int year, month, day, hour, minute, second, wday;
+
+ rtc_time = readl(ioaddr + RTC_TIME_REG_OFFS);
+ rtc_date = readl(ioaddr + RTC_DATE_REG_OFFS);
+
+ second = rtc_time & 0x7f;
+ minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f;
+ hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */
+ wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7;
+
+ day = rtc_date & 0x3f;
+ month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f;
+ year = (rtc_date >> RTC_YEAR_OFFS) & 0xff;
+
+ tm->tm_sec = bcd2bin(second);
+ tm->tm_min = bcd2bin(minute);
+ tm->tm_hour = bcd2bin(hour);
+ tm->tm_mday = bcd2bin(day);
+ tm->tm_wday = bcd2bin(wday);
+ tm->tm_mon = bcd2bin(month) - 1;
+ /* hw counts from year 2000, but tm_year is relative to 1900 */
+ tm->tm_year = bcd2bin(year) + 100;
+
+ return rtc_valid_tm(tm);
+}
+
+static const struct rtc_class_ops mv_rtc_ops = {
+ .read_time = mv_rtc_read_time,
+ .set_time = mv_rtc_set_time,
+};
+
+static int __init mv_rtc_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct rtc_plat_data *pdata;
+ resource_size_t size;
+ u32 rtc_time;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ size = resource_size(res);
+ if (!devm_request_mem_region(&pdev->dev, res->start, size,
+ pdev->name))
+ return -EBUSY;
+
+ pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, size);
+ if (!pdata->ioaddr)
+ return -ENOMEM;
+
+ /* make sure the 24 hours mode is enabled */
+ rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
+ if (rtc_time & RTC_HOURS_12H_MODE) {
+ dev_err(&pdev->dev, "24 Hours mode not supported.\n");
+ return -EINVAL;
+ }
+
+ platform_set_drvdata(pdev, pdata);
+ pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
+ &mv_rtc_ops, THIS_MODULE);
+ if (IS_ERR(pdata->rtc))
+ return PTR_ERR(pdata->rtc);
+
+ return 0;
+}
+
+static int __exit mv_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(pdata->rtc);
+ return 0;
+}
+
+static struct platform_driver mv_rtc_driver = {
+ .remove = __exit_p(mv_rtc_remove),
+ .driver = {
+ .name = "rtc-mv",
+ .owner = THIS_MODULE,
+ },
+};
+
+static __init int mv_init(void)
+{
+ return platform_driver_probe(&mv_rtc_driver, mv_rtc_probe);
+}
+
+static __exit void mv_exit(void)
+{
+ platform_driver_unregister(&mv_rtc_driver);
+}
+
+module_init(mv_init);
+module_exit(mv_exit);
+
+MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
+MODULE_DESCRIPTION("Marvell RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:rtc-mv");
diff --git a/drivers/rtc/rtc-parisc.c b/drivers/rtc/rtc-parisc.c
index 346d633655e7..c6bfa6fe1a2a 100644
--- a/drivers/rtc/rtc-parisc.c
+++ b/drivers/rtc/rtc-parisc.c
@@ -34,7 +34,8 @@ static int parisc_get_time(struct device *dev, struct rtc_time *tm)
static int parisc_set_time(struct device *dev, struct rtc_time *tm)
{
struct parisc_rtc *p = dev_get_drvdata(dev);
- unsigned long flags, ret;
+ unsigned long flags;
+ int ret;
spin_lock_irqsave(&p->lock, flags);
ret = set_rtc_time(tm);
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
new file mode 100644
index 000000000000..f4dd87e29075
--- /dev/null
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -0,0 +1,344 @@
+/* NXP PCF50633 RTC Driver
+ *
+ * (C) 2006-2008 by Openmoko, Inc.
+ * Author: Balaji Rao <balajirrao@openmoko.org>
+ * All rights reserved.
+ *
+ * Broken down from monstrous PCF50633 driver mainly by
+ * Harald Welte, Andy Green and Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/err.h>
+
+#include <linux/mfd/pcf50633/core.h>
+
+#define PCF50633_REG_RTCSC 0x59 /* Second */
+#define PCF50633_REG_RTCMN 0x5a /* Minute */
+#define PCF50633_REG_RTCHR 0x5b /* Hour */
+#define PCF50633_REG_RTCWD 0x5c /* Weekday */
+#define PCF50633_REG_RTCDT 0x5d /* Day */
+#define PCF50633_REG_RTCMT 0x5e /* Month */
+#define PCF50633_REG_RTCYR 0x5f /* Year */
+#define PCF50633_REG_RTCSCA 0x60 /* Alarm Second */
+#define PCF50633_REG_RTCMNA 0x61 /* Alarm Minute */
+#define PCF50633_REG_RTCHRA 0x62 /* Alarm Hour */
+#define PCF50633_REG_RTCWDA 0x63 /* Alarm Weekday */
+#define PCF50633_REG_RTCDTA 0x64 /* Alarm Day */
+#define PCF50633_REG_RTCMTA 0x65 /* Alarm Month */
+#define PCF50633_REG_RTCYRA 0x66 /* Alarm Year */
+
+enum pcf50633_time_indexes {
+ PCF50633_TI_SEC,
+ PCF50633_TI_MIN,
+ PCF50633_TI_HOUR,
+ PCF50633_TI_WKDAY,
+ PCF50633_TI_DAY,
+ PCF50633_TI_MONTH,
+ PCF50633_TI_YEAR,
+ PCF50633_TI_EXTENT /* always last */
+};
+
+struct pcf50633_time {
+ u_int8_t time[PCF50633_TI_EXTENT];
+};
+
+struct pcf50633_rtc {
+ int alarm_enabled;
+ int second_enabled;
+
+ struct pcf50633 *pcf;
+ struct rtc_device *rtc_dev;
+};
+
+static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf)
+{
+ rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]);
+ rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]);
+ rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]);
+ rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]);
+ rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]);
+ rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]);
+ rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100;
+}
+
+static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc)
+{
+ pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec);
+ pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min);
+ pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour);
+ pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday);
+ pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday);
+ pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon);
+ pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
+}
+
+static int
+pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
+ int err;
+
+ if (enabled)
+ err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+ else
+ err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ if (err < 0)
+ return err;
+
+ rtc->alarm_enabled = enabled;
+
+ return 0;
+}
+
+static int
+pcf50633_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
+ int err;
+
+ if (enabled)
+ err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
+ else
+ err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
+
+ if (err < 0)
+ return err;
+
+ rtc->second_enabled = enabled;
+
+ return 0;
+}
+
+static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int ret;
+
+ rtc = dev_get_drvdata(dev);
+
+ ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSC,
+ PCF50633_TI_EXTENT,
+ &pcf_tm.time[0]);
+ if (ret != PCF50633_TI_EXTENT) {
+ dev_err(dev, "Failed to read time\n");
+ return -EIO;
+ }
+
+ dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
+ pcf_tm.time[PCF50633_TI_DAY],
+ pcf_tm.time[PCF50633_TI_MONTH],
+ pcf_tm.time[PCF50633_TI_YEAR],
+ pcf_tm.time[PCF50633_TI_HOUR],
+ pcf_tm.time[PCF50633_TI_MIN],
+ pcf_tm.time[PCF50633_TI_SEC]);
+
+ pcf2rtc_time(tm, &pcf_tm);
+
+ dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
+ tm->tm_mday, tm->tm_mon, tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return rtc_valid_tm(tm);
+}
+
+static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int second_masked, alarm_masked, ret = 0;
+
+ rtc = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
+ tm->tm_mday, tm->tm_mon, tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ rtc2pcf_time(&pcf_tm, tm);
+
+ dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
+ pcf_tm.time[PCF50633_TI_DAY],
+ pcf_tm.time[PCF50633_TI_MONTH],
+ pcf_tm.time[PCF50633_TI_YEAR],
+ pcf_tm.time[PCF50633_TI_HOUR],
+ pcf_tm.time[PCF50633_TI_MIN],
+ pcf_tm.time[PCF50633_TI_SEC]);
+
+
+ second_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_SECOND);
+ alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ if (!second_masked)
+ pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
+ if (!alarm_masked)
+ pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ /* Returns 0 on success */
+ ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC,
+ PCF50633_TI_EXTENT,
+ &pcf_tm.time[0]);
+
+ if (!second_masked)
+ pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
+ if (!alarm_masked)
+ pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ return ret;
+}
+
+static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int ret = 0;
+
+ rtc = dev_get_drvdata(dev);
+
+ alrm->enabled = rtc->alarm_enabled;
+
+ ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA,
+ PCF50633_TI_EXTENT, &pcf_tm.time[0]);
+ if (ret != PCF50633_TI_EXTENT) {
+ dev_err(dev, "Failed to read time\n");
+ return -EIO;
+ }
+
+ pcf2rtc_time(&alrm->time, &pcf_tm);
+
+ return rtc_valid_tm(&alrm->time);
+}
+
+static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pcf50633_rtc *rtc;
+ struct pcf50633_time pcf_tm;
+ int alarm_masked, ret = 0;
+
+ rtc = dev_get_drvdata(dev);
+
+ rtc2pcf_time(&pcf_tm, &alrm->time);
+
+ /* do like mktime does and ignore tm_wday */
+ pcf_tm.time[PCF50633_TI_WKDAY] = 7;
+
+ alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ /* disable alarm interrupt */
+ if (!alarm_masked)
+ pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ /* Returns 0 on success */
+ ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
+ PCF50633_TI_EXTENT, &pcf_tm.time[0]);
+
+ if (!alarm_masked)
+ pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
+
+ return ret;
+}
+
+static struct rtc_class_ops pcf50633_rtc_ops = {
+ .read_time = pcf50633_rtc_read_time,
+ .set_time = pcf50633_rtc_set_time,
+ .read_alarm = pcf50633_rtc_read_alarm,
+ .set_alarm = pcf50633_rtc_set_alarm,
+ .alarm_irq_enable = pcf50633_rtc_alarm_irq_enable,
+ .update_irq_enable = pcf50633_rtc_update_irq_enable,
+};
+
+static void pcf50633_rtc_irq(int irq, void *data)
+{
+ struct pcf50633_rtc *rtc = data;
+
+ switch (irq) {
+ case PCF50633_IRQ_ALARM:
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+ break;
+ case PCF50633_IRQ_SECOND:
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
+ break;
+ }
+}
+
+static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)
+{
+ struct pcf50633_subdev_pdata *pdata;
+ struct pcf50633_rtc *rtc;
+
+
+ rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ pdata = pdev->dev.platform_data;
+ rtc->pcf = pdata->pcf;
+ platform_set_drvdata(pdev, rtc);
+ rtc->rtc_dev = rtc_device_register("pcf50633-rtc", &pdev->dev,
+ &pcf50633_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc->rtc_dev)) {
+ kfree(rtc);
+ return PTR_ERR(rtc->rtc_dev);
+ }
+
+ pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM,
+ pcf50633_rtc_irq, rtc);
+ pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_SECOND,
+ pcf50633_rtc_irq, rtc);
+
+ return 0;
+}
+
+static int __devexit pcf50633_rtc_remove(struct platform_device *pdev)
+{
+ struct pcf50633_rtc *rtc;
+
+ rtc = platform_get_drvdata(pdev);
+
+ pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM);
+ pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_SECOND);
+
+ rtc_device_unregister(rtc->rtc_dev);
+ kfree(rtc);
+
+ return 0;
+}
+
+static struct platform_driver pcf50633_rtc_driver = {
+ .driver = {
+ .name = "pcf50633-rtc",
+ },
+ .probe = pcf50633_rtc_probe,
+ .remove = __devexit_p(pcf50633_rtc_remove),
+};
+
+static int __init pcf50633_rtc_init(void)
+{
+ return platform_driver_register(&pcf50633_rtc_driver);
+}
+module_init(pcf50633_rtc_init);
+
+static void __exit pcf50633_rtc_exit(void)
+{
+ platform_driver_unregister(&pcf50633_rtc_driver);
+}
+module_exit(pcf50633_rtc_exit);
+
+MODULE_DESCRIPTION("PCF50633 RTC driver");
+MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
new file mode 100644
index 000000000000..bd56a033bfd0
--- /dev/null
+++ b/drivers/rtc/rtc-pxa.c
@@ -0,0 +1,491 @@
+/*
+ * Real Time Clock interface for XScale PXA27x and PXA3xx
+ *
+ * Copyright (C) 2008 Robert Jarzmik
+ *
+ * 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
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#define TIMER_FREQ CLOCK_TICK_RATE
+#define RTC_DEF_DIVIDER (32768 - 1)
+#define RTC_DEF_TRIM 0
+#define MAXFREQ_PERIODIC 1000
+
+/*
+ * PXA Registers and bits definitions
+ */
+#define RTSR_PICE (1 << 15) /* Periodic interrupt count enable */
+#define RTSR_PIALE (1 << 14) /* Periodic interrupt Alarm enable */
+#define RTSR_PIAL (1 << 13) /* Periodic interrupt detected */
+#define RTSR_SWALE2 (1 << 11) /* RTC stopwatch alarm2 enable */
+#define RTSR_SWAL2 (1 << 10) /* RTC stopwatch alarm2 detected */
+#define RTSR_SWALE1 (1 << 9) /* RTC stopwatch alarm1 enable */
+#define RTSR_SWAL1 (1 << 8) /* RTC stopwatch alarm1 detected */
+#define RTSR_RDALE2 (1 << 7) /* RTC alarm2 enable */
+#define RTSR_RDAL2 (1 << 6) /* RTC alarm2 detected */
+#define RTSR_RDALE1 (1 << 5) /* RTC alarm1 enable */
+#define RTSR_RDAL1 (1 << 4) /* RTC alarm1 detected */
+#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
+#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
+#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
+#define RTSR_AL (1 << 0) /* RTC alarm detected */
+#define RTSR_TRIG_MASK (RTSR_AL | RTSR_HZ | RTSR_RDAL1 | RTSR_RDAL2\
+ | RTSR_SWAL1 | RTSR_SWAL2)
+#define RYxR_YEAR_S 9
+#define RYxR_YEAR_MASK (0xfff << RYxR_YEAR_S)
+#define RYxR_MONTH_S 5
+#define RYxR_MONTH_MASK (0xf << RYxR_MONTH_S)
+#define RYxR_DAY_MASK 0x1f
+#define RDxR_HOUR_S 12
+#define RDxR_HOUR_MASK (0x1f << RDxR_HOUR_S)
+#define RDxR_MIN_S 6
+#define RDxR_MIN_MASK (0x3f << RDxR_MIN_S)
+#define RDxR_SEC_MASK 0x3f
+
+#define RTSR 0x08
+#define RTTR 0x0c
+#define RDCR 0x10
+#define RYCR 0x14
+#define RDAR1 0x18
+#define RYAR1 0x1c
+#define RTCPICR 0x34
+#define PIAR 0x38
+
+#define rtc_readl(pxa_rtc, reg) \
+ __raw_readl((pxa_rtc)->base + (reg))
+#define rtc_writel(pxa_rtc, reg, value) \
+ __raw_writel((value), (pxa_rtc)->base + (reg))
+
+struct pxa_rtc {
+ struct resource *ress;
+ void __iomem *base;
+ int irq_1Hz;
+ int irq_Alrm;
+ struct rtc_device *rtc;
+ spinlock_t lock; /* Protects this structure */
+ struct rtc_time rtc_alarm;
+};
+
+static u32 ryxr_calc(struct rtc_time *tm)
+{
+ return ((tm->tm_year + 1900) << RYxR_YEAR_S)
+ | ((tm->tm_mon + 1) << RYxR_MONTH_S)
+ | tm->tm_mday;
+}
+
+static u32 rdxr_calc(struct rtc_time *tm)
+{
+ return (tm->tm_hour << RDxR_HOUR_S) | (tm->tm_min << RDxR_MIN_S)
+ | tm->tm_sec;
+}
+
+static void tm_calc(u32 rycr, u32 rdcr, struct rtc_time *tm)
+{
+ tm->tm_year = ((rycr & RYxR_YEAR_MASK) >> RYxR_YEAR_S) - 1900;
+ tm->tm_mon = (((rycr & RYxR_MONTH_MASK) >> RYxR_MONTH_S)) - 1;
+ tm->tm_mday = (rycr & RYxR_DAY_MASK);
+ tm->tm_hour = (rdcr & RDxR_HOUR_MASK) >> RDxR_HOUR_S;
+ tm->tm_min = (rdcr & RDxR_MIN_MASK) >> RDxR_MIN_S;
+ tm->tm_sec = rdcr & RDxR_SEC_MASK;
+}
+
+static void rtsr_clear_bits(struct pxa_rtc *pxa_rtc, u32 mask)
+{
+ u32 rtsr;
+
+ rtsr = rtc_readl(pxa_rtc, RTSR);
+ rtsr &= ~RTSR_TRIG_MASK;
+ rtsr &= ~mask;
+ rtc_writel(pxa_rtc, RTSR, rtsr);
+}
+
+static void rtsr_set_bits(struct pxa_rtc *pxa_rtc, u32 mask)
+{
+ u32 rtsr;
+
+ rtsr = rtc_readl(pxa_rtc, RTSR);
+ rtsr &= ~RTSR_TRIG_MASK;
+ rtsr |= mask;
+ rtc_writel(pxa_rtc, RTSR, rtsr);
+}
+
+static irqreturn_t pxa_rtc_irq(int irq, void *dev_id)
+{
+ struct platform_device *pdev = to_platform_device(dev_id);
+ struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev);
+ u32 rtsr;
+ unsigned long events = 0;
+
+ spin_lock(&pxa_rtc->lock);
+
+ /* clear interrupt sources */
+ rtsr = rtc_readl(pxa_rtc, RTSR);
+ rtc_writel(pxa_rtc, RTSR, rtsr);
+
+ /* temporary disable rtc interrupts */
+ rtsr_clear_bits(pxa_rtc, RTSR_RDALE1 | RTSR_PIALE | RTSR_HZE);
+
+ /* clear alarm interrupt if it has occurred */
+ if (rtsr & RTSR_RDAL1)
+ rtsr &= ~RTSR_RDALE1;
+
+ /* update irq data & counter */
+ if (rtsr & RTSR_RDAL1)
+ events |= RTC_AF | RTC_IRQF;
+ if (rtsr & RTSR_HZ)
+ events |= RTC_UF | RTC_IRQF;
+ if (rtsr & RTSR_PIAL)
+ events |= RTC_PF | RTC_IRQF;
+
+ rtc_update_irq(pxa_rtc->rtc, 1, events);
+
+ /* enable back rtc interrupts */
+ rtc_writel(pxa_rtc, RTSR, rtsr & ~RTSR_TRIG_MASK);
+
+ spin_unlock(&pxa_rtc->lock);
+ return IRQ_HANDLED;
+}
+
+static int pxa_rtc_open(struct device *dev)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+ int ret;
+
+ ret = request_irq(pxa_rtc->irq_1Hz, pxa_rtc_irq, IRQF_DISABLED,
+ "rtc 1Hz", dev);
+ if (ret < 0) {
+ dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_1Hz,
+ ret);
+ goto err_irq_1Hz;
+ }
+ ret = request_irq(pxa_rtc->irq_Alrm, pxa_rtc_irq, IRQF_DISABLED,
+ "rtc Alrm", dev);
+ if (ret < 0) {
+ dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_Alrm,
+ ret);
+ goto err_irq_Alrm;
+ }
+
+ return 0;
+
+err_irq_Alrm:
+ free_irq(pxa_rtc->irq_1Hz, dev);
+err_irq_1Hz:
+ return ret;
+}
+
+static void pxa_rtc_release(struct device *dev)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+
+ spin_lock_irq(&pxa_rtc->lock);
+ rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
+ spin_unlock_irq(&pxa_rtc->lock);
+
+ free_irq(pxa_rtc->irq_Alrm, dev);
+ free_irq(pxa_rtc->irq_1Hz, dev);
+}
+
+static int pxa_periodic_irq_set_freq(struct device *dev, int freq)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+ int period_ms;
+
+ if (freq < 1 || freq > MAXFREQ_PERIODIC)
+ return -EINVAL;
+
+ period_ms = 1000 / freq;
+ rtc_writel(pxa_rtc, PIAR, period_ms);
+
+ return 0;
+}
+
+static int pxa_periodic_irq_set_state(struct device *dev, int enabled)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+
+ if (enabled)
+ rtsr_set_bits(pxa_rtc, RTSR_PIALE | RTSR_PICE);
+ else
+ rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_PICE);
+
+ return 0;
+}
+
+static int pxa_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+ int ret = 0;
+
+ spin_lock_irq(&pxa_rtc->lock);
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ rtsr_clear_bits(pxa_rtc, RTSR_RDALE1);
+ break;
+ case RTC_AIE_ON:
+ rtsr_set_bits(pxa_rtc, RTSR_RDALE1);
+ break;
+ case RTC_UIE_OFF:
+ rtsr_clear_bits(pxa_rtc, RTSR_HZE);
+ break;
+ case RTC_UIE_ON:
+ rtsr_set_bits(pxa_rtc, RTSR_HZE);
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ }
+
+ spin_unlock_irq(&pxa_rtc->lock);
+ return ret;
+}
+
+static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+ u32 rycr, rdcr;
+
+ rycr = rtc_readl(pxa_rtc, RYCR);
+ rdcr = rtc_readl(pxa_rtc, RDCR);
+
+ tm_calc(rycr, rdcr, tm);
+ return 0;
+}
+
+static int pxa_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+
+ rtc_writel(pxa_rtc, RYCR, ryxr_calc(tm));
+ rtc_writel(pxa_rtc, RDCR, rdxr_calc(tm));
+
+ return 0;
+}
+
+static int pxa_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+ u32 rtsr, ryar, rdar;
+
+ ryar = rtc_readl(pxa_rtc, RYAR1);
+ rdar = rtc_readl(pxa_rtc, RDAR1);
+ tm_calc(ryar, rdar, &alrm->time);
+
+ rtsr = rtc_readl(pxa_rtc, RTSR);
+ alrm->enabled = (rtsr & RTSR_RDALE1) ? 1 : 0;
+ alrm->pending = (rtsr & RTSR_RDAL1) ? 1 : 0;
+ return 0;
+}
+
+static int pxa_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+ u32 rtsr;
+
+ spin_lock_irq(&pxa_rtc->lock);
+
+ rtc_writel(pxa_rtc, RYAR1, ryxr_calc(&alrm->time));
+ rtc_writel(pxa_rtc, RDAR1, rdxr_calc(&alrm->time));
+
+ rtsr = rtc_readl(pxa_rtc, RTSR);
+ if (alrm->enabled)
+ rtsr |= RTSR_RDALE1;
+ else
+ rtsr &= ~RTSR_RDALE1;
+ rtc_writel(pxa_rtc, RTSR, rtsr);
+
+ spin_unlock_irq(&pxa_rtc->lock);
+
+ return 0;
+}
+
+static int pxa_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
+
+ seq_printf(seq, "trim/divider\t: 0x%08x\n", rtc_readl(pxa_rtc, RTTR));
+ seq_printf(seq, "update_IRQ\t: %s\n",
+ (rtc_readl(pxa_rtc, RTSR) & RTSR_HZE) ? "yes" : "no");
+ seq_printf(seq, "periodic_IRQ\t: %s\n",
+ (rtc_readl(pxa_rtc, RTSR) & RTSR_PIALE) ? "yes" : "no");
+ seq_printf(seq, "periodic_freq\t: %u\n", rtc_readl(pxa_rtc, PIAR));
+
+ return 0;
+}
+
+static const struct rtc_class_ops pxa_rtc_ops = {
+ .open = pxa_rtc_open,
+ .release = pxa_rtc_release,
+ .ioctl = pxa_rtc_ioctl,
+ .read_time = pxa_rtc_read_time,
+ .set_time = pxa_rtc_set_time,
+ .read_alarm = pxa_rtc_read_alarm,
+ .set_alarm = pxa_rtc_set_alarm,
+ .proc = pxa_rtc_proc,
+ .irq_set_state = pxa_periodic_irq_set_state,
+ .irq_set_freq = pxa_periodic_irq_set_freq,
+};
+
+static int __init pxa_rtc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pxa_rtc *pxa_rtc;
+ int ret;
+ u32 rttr;
+
+ pxa_rtc = kzalloc(sizeof(struct pxa_rtc), GFP_KERNEL);
+ if (!pxa_rtc)
+ return -ENOMEM;
+
+ spin_lock_init(&pxa_rtc->lock);
+ platform_set_drvdata(pdev, pxa_rtc);
+
+ ret = -ENXIO;
+ pxa_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!pxa_rtc->ress) {
+ dev_err(dev, "No I/O memory resource defined\n");
+ goto err_ress;
+ }
+
+ pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0);
+ if (pxa_rtc->irq_1Hz < 0) {
+ dev_err(dev, "No 1Hz IRQ resource defined\n");
+ goto err_ress;
+ }
+ pxa_rtc->irq_Alrm = platform_get_irq(pdev, 1);
+ if (pxa_rtc->irq_Alrm < 0) {
+ dev_err(dev, "No alarm IRQ resource defined\n");
+ goto err_ress;
+ }
+
+ ret = -ENOMEM;
+ pxa_rtc->base = ioremap(pxa_rtc->ress->start,
+ resource_size(pxa_rtc->ress));
+ if (!pxa_rtc->base) {
+ dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n");
+ goto err_map;
+ }
+
+ /*
+ * If the clock divider is uninitialized then reset it to the
+ * default value to get the 1Hz clock.
+ */
+ if (rtc_readl(pxa_rtc, RTTR) == 0) {
+ rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+ rtc_writel(pxa_rtc, RTTR, rttr);
+ dev_warn(dev, "warning: initializing default clock"
+ " divider/trim value\n");
+ }
+
+ rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
+
+ pxa_rtc->rtc = rtc_device_register("pxa-rtc", &pdev->dev, &pxa_rtc_ops,
+ THIS_MODULE);
+ ret = PTR_ERR(pxa_rtc->rtc);
+ if (IS_ERR(pxa_rtc->rtc)) {
+ dev_err(dev, "Failed to register RTC device -> %d\n", ret);
+ goto err_rtc_reg;
+ }
+
+ device_init_wakeup(dev, 1);
+
+ return 0;
+
+err_rtc_reg:
+ iounmap(pxa_rtc->base);
+err_ress:
+err_map:
+ kfree(pxa_rtc);
+ return ret;
+}
+
+static int __exit pxa_rtc_remove(struct platform_device *pdev)
+{
+ struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(pxa_rtc->rtc);
+
+ spin_lock_irq(&pxa_rtc->lock);
+ iounmap(pxa_rtc->base);
+ spin_unlock_irq(&pxa_rtc->lock);
+
+ kfree(pxa_rtc);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int pxa_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(pxa_rtc->irq_Alrm);
+ return 0;
+}
+
+static int pxa_rtc_resume(struct platform_device *pdev)
+{
+ struct pxa_rtc *pxa_rtc = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ disable_irq_wake(pxa_rtc->irq_Alrm);
+ return 0;
+}
+#else
+#define pxa_rtc_suspend NULL
+#define pxa_rtc_resume NULL
+#endif
+
+static struct platform_driver pxa_rtc_driver = {
+ .remove = __exit_p(pxa_rtc_remove),
+ .suspend = pxa_rtc_suspend,
+ .resume = pxa_rtc_resume,
+ .driver = {
+ .name = "pxa-rtc",
+ },
+};
+
+static int __init pxa_rtc_init(void)
+{
+ if (cpu_is_pxa27x() || cpu_is_pxa3xx())
+ return platform_driver_probe(&pxa_rtc_driver, pxa_rtc_probe);
+
+ return -ENODEV;
+}
+
+static void __exit pxa_rtc_exit(void)
+{
+ platform_driver_unregister(&pxa_rtc_driver);
+}
+
+module_init(pxa_rtc_init);
+module_exit(pxa_rtc_exit);
+
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_DESCRIPTION("PXA27x/PXA3xx Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:pxa-rtc");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 7a568beba3f0..e0d7b9991505 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -94,6 +94,9 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
{
unsigned int tmp;
+ if (!is_power_of_2(freq))
+ return -EINVAL;
+
spin_lock_irq(&s3c_rtc_pie_lock);
tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index aaf9d6a337cc..1c3fc6b428e9 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/log2.h>
#include <asm/rtc.h>
#define DRV_NAME "sh-rtc"
@@ -89,7 +90,9 @@ struct sh_rtc {
void __iomem *regbase;
unsigned long regsize;
struct resource *res;
- unsigned int alarm_irq, periodic_irq, carry_irq;
+ int alarm_irq;
+ int periodic_irq;
+ int carry_irq;
struct rtc_device *rtc_dev;
spinlock_t lock;
unsigned long capabilities; /* See asm-sh/rtc.h for cap bits */
@@ -549,6 +552,8 @@ static int sh_rtc_irq_set_state(struct device *dev, int enabled)
static int sh_rtc_irq_set_freq(struct device *dev, int freq)
{
+ if (!is_power_of_2(freq))
+ return -EINVAL;
return sh_rtc_ioctl(dev, RTC_IRQP_SET, freq);
}
@@ -578,7 +583,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
/* get periodic/carry/alarm irqs */
ret = platform_get_irq(pdev, 0);
- if (unlikely(ret < 0)) {
+ if (unlikely(ret <= 0)) {
ret = -ENOENT;
dev_err(&pdev->dev, "No IRQ for period\n");
goto err_badres;
@@ -586,7 +591,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
rtc->periodic_irq = ret;
ret = platform_get_irq(pdev, 1);
- if (unlikely(ret < 0)) {
+ if (unlikely(ret <= 0)) {
ret = -ENOENT;
dev_err(&pdev->dev, "No IRQ for carry\n");
goto err_badres;
@@ -594,7 +599,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
rtc->carry_irq = ret;
ret = platform_get_irq(pdev, 2);
- if (unlikely(ret < 0)) {
+ if (unlikely(ret <= 0)) {
ret = -ENOENT;
dev_err(&pdev->dev, "No IRQ for alarm\n");
goto err_badres;
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index f4cd46e15af9..7d1547b0070e 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -170,7 +170,7 @@ static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
pdata->alrm_mday = alrm->time.tm_mday;
pdata->alrm_hour = alrm->time.tm_hour;
@@ -187,7 +187,7 @@ static int stk17ta8_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -EINVAL;
alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
@@ -221,7 +221,7 @@ static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd,
struct platform_device *pdev = to_platform_device(dev);
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- if (pdata->irq < 0)
+ if (pdata->irq <= 0)
return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
switch (cmd) {
case RTC_AIE_OFF:
@@ -303,7 +303,6 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev)
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- pdata->irq = -1;
if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
ret = -EBUSY;
goto out;
@@ -329,13 +328,13 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev)
if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF)
dev_warn(&pdev->dev, "voltage-low detected.\n");
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, ioaddr + RTC_INTERRUPTS);
if (request_irq(pdata->irq, stk17ta8_rtc_interrupt,
IRQF_DISABLED | IRQF_SHARED,
pdev->name, pdev) < 0) {
dev_warn(&pdev->dev, "interrupt not available.\n");
- pdata->irq = -1;
+ pdata->irq = 0;
}
}
@@ -355,7 +354,7 @@ static int __init stk17ta8_rtc_probe(struct platform_device *pdev)
out:
if (pdata->rtc)
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0)
+ if (pdata->irq > 0)
free_irq(pdata->irq, pdev);
if (ioaddr)
iounmap(ioaddr);
@@ -371,7 +370,7 @@ static int __devexit stk17ta8_rtc_remove(struct platform_device *pdev)
sysfs_remove_bin_file(&pdev->dev.kobj, &stk17ta8_nvram_attr);
rtc_device_unregister(pdata->rtc);
- if (pdata->irq >= 0) {
+ if (pdata->irq > 0) {
writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
free_irq(pdata->irq, pdev);
}
@@ -400,7 +399,7 @@ static __init int stk17ta8_init(void)
static __exit void stk17ta8_exit(void)
{
- return platform_driver_unregister(&stk17ta8_rtc_driver);
+ platform_driver_unregister(&stk17ta8_rtc_driver);
}
module_init(stk17ta8_init);
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index bc930022004a..e478280ff628 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -34,14 +34,9 @@ static int test_rtc_read_time(struct device *dev,
return 0;
}
-static int test_rtc_set_time(struct device *dev,
- struct rtc_time *tm)
-{
- return 0;
-}
-
static int test_rtc_set_mmss(struct device *dev, unsigned long secs)
{
+ dev_info(dev, "%s, secs = %lu\n", __func__, secs);
return 0;
}
@@ -78,7 +73,6 @@ static int test_rtc_ioctl(struct device *dev, unsigned int cmd,
static const struct rtc_class_ops test_rtc_ops = {
.proc = test_rtc_proc,
.read_time = test_rtc_read_time,
- .set_time = test_rtc_set_time,
.read_alarm = test_rtc_read_alarm,
.set_alarm = test_rtc_set_alarm,
.set_mmss = test_rtc_set_mmss,
diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c
index 01d8da9afdc8..ad35f76c46b7 100644
--- a/drivers/rtc/rtc-twl4030.c
+++ b/drivers/rtc/rtc-twl4030.c
@@ -19,6 +19,7 @@
*/
#include <linux/kernel.h>
+#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -119,7 +120,7 @@ static int twl4030_rtc_write_u8(u8 data, u8 reg)
static unsigned char rtc_irq_bits;
/*
- * Enable timer and/or alarm interrupts.
+ * Enable 1/second update and/or alarm interrupts.
*/
static int set_rtc_irq_bit(unsigned char bit)
{
@@ -127,6 +128,7 @@ static int set_rtc_irq_bit(unsigned char bit)
int ret;
val = rtc_irq_bits | bit;
+ val &= ~BIT_RTC_INTERRUPTS_REG_EVERY_M;
ret = twl4030_rtc_write_u8(val, REG_RTC_INTERRUPTS_REG);
if (ret == 0)
rtc_irq_bits = val;
@@ -135,7 +137,7 @@ static int set_rtc_irq_bit(unsigned char bit)
}
/*
- * Disable timer and/or alarm interrupts.
+ * Disable update and/or alarm interrupts.
*/
static int mask_rtc_irq_bit(unsigned char bit)
{
@@ -150,7 +152,7 @@ static int mask_rtc_irq_bit(unsigned char bit)
return ret;
}
-static inline int twl4030_rtc_alarm_irq_set_state(int enabled)
+static int twl4030_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
{
int ret;
@@ -162,7 +164,7 @@ static inline int twl4030_rtc_alarm_irq_set_state(int enabled)
return ret;
}
-static inline int twl4030_rtc_irq_set_state(int enabled)
+static int twl4030_rtc_update_irq_enable(struct device *dev, unsigned enabled)
{
int ret;
@@ -291,7 +293,7 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
unsigned char alarm_data[ALL_TIME_REGS + 1];
int ret;
- ret = twl4030_rtc_alarm_irq_set_state(0);
+ ret = twl4030_rtc_alarm_irq_enable(dev, 0);
if (ret)
goto out;
@@ -311,35 +313,11 @@ static int twl4030_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
}
if (alm->enabled)
- ret = twl4030_rtc_alarm_irq_set_state(1);
+ ret = twl4030_rtc_alarm_irq_enable(dev, 1);
out:
return ret;
}
-#ifdef CONFIG_RTC_INTF_DEV
-
-static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd,
- unsigned long arg)
-{
- switch (cmd) {
- case RTC_AIE_OFF:
- return twl4030_rtc_alarm_irq_set_state(0);
- case RTC_AIE_ON:
- return twl4030_rtc_alarm_irq_set_state(1);
- case RTC_UIE_OFF:
- return twl4030_rtc_irq_set_state(0);
- case RTC_UIE_ON:
- return twl4030_rtc_irq_set_state(1);
-
- default:
- return -ENOIOCTLCMD;
- }
-}
-
-#else
-#define twl4030_rtc_ioctl NULL
-#endif
-
static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc)
{
unsigned long events = 0;
@@ -399,11 +377,12 @@ out:
}
static struct rtc_class_ops twl4030_rtc_ops = {
- .ioctl = twl4030_rtc_ioctl,
.read_time = twl4030_rtc_read_time,
.set_time = twl4030_rtc_set_time,
.read_alarm = twl4030_rtc_read_alarm,
.set_alarm = twl4030_rtc_set_alarm,
+ .alarm_irq_enable = twl4030_rtc_alarm_irq_enable,
+ .update_irq_enable = twl4030_rtc_update_irq_enable,
};
/*----------------------------------------------------------------------*/
@@ -415,13 +394,13 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
int irq = platform_get_irq(pdev, 0);
u8 rd_reg;
- if (irq < 0)
- return irq;
+ if (irq <= 0)
+ return -EINVAL;
rtc = rtc_device_register(pdev->name,
&pdev->dev, &twl4030_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
- ret = -EINVAL;
+ ret = PTR_ERR(rtc);
dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
PTR_ERR(rtc));
goto out0;
@@ -431,7 +410,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc);
ret = twl4030_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG);
-
if (ret < 0)
goto out1;
@@ -474,7 +452,6 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev)
return ret;
-
out2:
free_irq(irq, rtc);
out1:
@@ -505,8 +482,9 @@ static int __devexit twl4030_rtc_remove(struct platform_device *pdev)
static void twl4030_rtc_shutdown(struct platform_device *pdev)
{
- mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M |
- BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
+ /* mask timer interrupts, but leave alarm interrupts on to enable
+ power-on when alarm is triggered */
+ mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
}
#ifdef CONFIG_PM
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
new file mode 100644
index 000000000000..4ee4857ff207
--- /dev/null
+++ b/drivers/rtc/rtc-tx4939.c
@@ -0,0 +1,317 @@
+/*
+ * TX4939 internal RTC driver
+ * Based on RBTX49xx patch from CELF patch archive.
+ *
+ * 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.
+ *
+ * (C) Copyright TOSHIBA CORPORATION 2005-2007
+ */
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/txx9/tx4939.h>
+
+struct tx4939rtc_plat_data {
+ struct rtc_device *rtc;
+ struct tx4939_rtc_reg __iomem *rtcreg;
+};
+
+static struct tx4939rtc_plat_data *get_tx4939rtc_plat_data(struct device *dev)
+{
+ return platform_get_drvdata(to_platform_device(dev));
+}
+
+static int tx4939_rtc_cmd(struct tx4939_rtc_reg __iomem *rtcreg, int cmd)
+{
+ int i = 0;
+
+ __raw_writel(cmd, &rtcreg->ctl);
+ /* This might take 30us (next 32.768KHz clock) */
+ while (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_BUSY) {
+ /* timeout on approx. 100us (@ GBUS200MHz) */
+ if (i++ > 200 * 100)
+ return -EBUSY;
+ cpu_relax();
+ }
+ return 0;
+}
+
+static int tx4939_rtc_set_mmss(struct device *dev, unsigned long secs)
+{
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
+ int i, ret;
+ unsigned char buf[6];
+
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = secs;
+ buf[3] = secs >> 8;
+ buf[4] = secs >> 16;
+ buf[5] = secs >> 24;
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ __raw_writel(0, &rtcreg->adr);
+ for (i = 0; i < 6; i++)
+ __raw_writel(buf[i], &rtcreg->dat);
+ ret = tx4939_rtc_cmd(rtcreg,
+ TX4939_RTCCTL_COMMAND_SETTIME |
+ (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ return ret;
+}
+
+static int tx4939_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
+ int i, ret;
+ unsigned long sec;
+ unsigned char buf[6];
+
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ ret = tx4939_rtc_cmd(rtcreg,
+ TX4939_RTCCTL_COMMAND_GETTIME |
+ (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
+ if (ret) {
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ return ret;
+ }
+ __raw_writel(2, &rtcreg->adr);
+ for (i = 2; i < 6; i++)
+ buf[i] = __raw_readl(&rtcreg->dat);
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
+ rtc_time_to_tm(sec, tm);
+ return rtc_valid_tm(tm);
+}
+
+static int tx4939_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
+ int i, ret;
+ unsigned long sec;
+ unsigned char buf[6];
+
+ if (alrm->time.tm_sec < 0 ||
+ alrm->time.tm_min < 0 ||
+ alrm->time.tm_hour < 0 ||
+ alrm->time.tm_mday < 0 ||
+ alrm->time.tm_mon < 0 ||
+ alrm->time.tm_year < 0)
+ return -EINVAL;
+ rtc_tm_to_time(&alrm->time, &sec);
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = sec;
+ buf[3] = sec >> 8;
+ buf[4] = sec >> 16;
+ buf[5] = sec >> 24;
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ __raw_writel(0, &rtcreg->adr);
+ for (i = 0; i < 6; i++)
+ __raw_writel(buf[i], &rtcreg->dat);
+ ret = tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_SETALARM |
+ (alrm->enabled ? TX4939_RTCCTL_ALME : 0));
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ return ret;
+}
+
+static int tx4939_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
+ int i, ret;
+ unsigned long sec;
+ unsigned char buf[6];
+ u32 ctl;
+
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ ret = tx4939_rtc_cmd(rtcreg,
+ TX4939_RTCCTL_COMMAND_GETALARM |
+ (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALME));
+ if (ret) {
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ return ret;
+ }
+ __raw_writel(2, &rtcreg->adr);
+ for (i = 2; i < 6; i++)
+ buf[i] = __raw_readl(&rtcreg->dat);
+ ctl = __raw_readl(&rtcreg->ctl);
+ alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
+ alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
+ rtc_time_to_tm(sec, &alrm->time);
+ return rtc_valid_tm(&alrm->time);
+}
+
+static int tx4939_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ tx4939_rtc_cmd(pdata->rtcreg,
+ TX4939_RTCCTL_COMMAND_NOP |
+ (enabled ? TX4939_RTCCTL_ALME : 0));
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ return 0;
+}
+
+static irqreturn_t tx4939_rtc_interrupt(int irq, void *dev_id)
+{
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev_id);
+ struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
+ unsigned long events = RTC_IRQF;
+
+ spin_lock(&pdata->rtc->irq_lock);
+ if (__raw_readl(&rtcreg->ctl) & TX4939_RTCCTL_ALMD) {
+ events |= RTC_AF;
+ tx4939_rtc_cmd(rtcreg, TX4939_RTCCTL_COMMAND_NOP);
+ }
+ spin_unlock(&pdata->rtc->irq_lock);
+ rtc_update_irq(pdata->rtc, 1, events);
+ return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops tx4939_rtc_ops = {
+ .read_time = tx4939_rtc_read_time,
+ .read_alarm = tx4939_rtc_read_alarm,
+ .set_alarm = tx4939_rtc_set_alarm,
+ .set_mmss = tx4939_rtc_set_mmss,
+ .alarm_irq_enable = tx4939_rtc_alarm_irq_enable,
+};
+
+static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
+ ssize_t count;
+
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
+ count++, size--) {
+ __raw_writel(pos++, &rtcreg->adr);
+ *buf++ = __raw_readl(&rtcreg->dat);
+ }
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ return count;
+}
+
+static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct tx4939rtc_plat_data *pdata = get_tx4939rtc_plat_data(dev);
+ struct tx4939_rtc_reg __iomem *rtcreg = pdata->rtcreg;
+ ssize_t count;
+
+ spin_lock_irq(&pdata->rtc->irq_lock);
+ for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
+ count++, size--) {
+ __raw_writel(pos++, &rtcreg->adr);
+ __raw_writel(*buf++, &rtcreg->dat);
+ }
+ spin_unlock_irq(&pdata->rtc->irq_lock);
+ return count;
+}
+
+static struct bin_attribute tx4939_rtc_nvram_attr = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .size = TX4939_RTC_REG_RAMSIZE,
+ .read = tx4939_rtc_nvram_read,
+ .write = tx4939_rtc_nvram_write,
+};
+
+static int __init tx4939_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ struct tx4939rtc_plat_data *pdata;
+ struct resource *res;
+ int irq, ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENODEV;
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, pdata);
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
+ pdata->rtcreg = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!pdata->rtcreg)
+ return -EBUSY;
+
+ tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
+ if (devm_request_irq(&pdev->dev, irq, tx4939_rtc_interrupt,
+ IRQF_DISABLED | IRQF_SHARED,
+ pdev->name, &pdev->dev) < 0) {
+ return -EBUSY;
+ }
+ rtc = rtc_device_register(pdev->name, &pdev->dev,
+ &tx4939_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+ pdata->rtc = rtc;
+ ret = sysfs_create_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
+ if (ret)
+ rtc_device_unregister(rtc);
+ return ret;
+}
+
+static int __exit tx4939_rtc_remove(struct platform_device *pdev)
+{
+ struct tx4939rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_device *rtc = pdata->rtc;
+
+ spin_lock_irq(&rtc->irq_lock);
+ tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);
+ spin_unlock_irq(&rtc->irq_lock);
+ sysfs_remove_bin_file(&pdev->dev.kobj, &tx4939_rtc_nvram_attr);
+ rtc_device_unregister(rtc);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static struct platform_driver tx4939_rtc_driver = {
+ .remove = __exit_p(tx4939_rtc_remove),
+ .driver = {
+ .name = "tx4939rtc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init tx4939rtc_init(void)
+{
+ return platform_driver_probe(&tx4939_rtc_driver, tx4939_rtc_probe);
+}
+
+static void __exit tx4939rtc_exit(void)
+{
+ platform_driver_unregister(&tx4939_rtc_driver);
+}
+
+module_init(tx4939rtc_init);
+module_exit(tx4939rtc_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("TX4939 internal RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tx4939rtc");
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 834dcc6d785f..f11297aff854 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -27,6 +27,7 @@
#include <linux/rtc.h>
#include <linux/spinlock.h>
#include <linux/types.h>
+#include <linux/log2.h>
#include <asm/div64.h>
#include <asm/io.h>
@@ -84,8 +85,8 @@ static DEFINE_SPINLOCK(rtc_lock);
static char rtc_name[] = "RTC";
static unsigned long periodic_count;
static unsigned int alarm_enabled;
-static int aie_irq = -1;
-static int pie_irq = -1;
+static int aie_irq;
+static int pie_irq;
static inline unsigned long read_elapsed_second(void)
{
@@ -210,6 +211,8 @@ static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq)
{
unsigned long count;
+ if (!is_power_of_2(freq))
+ return -EINVAL;
count = RTC_FREQUENCY;
do_div(count, freq);
@@ -360,7 +363,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
spin_unlock_irq(&rtc_lock);
aie_irq = platform_get_irq(pdev, 0);
- if (aie_irq < 0 || aie_irq >= nr_irqs) {
+ if (aie_irq <= 0) {
retval = -EBUSY;
goto err_device_unregister;
}
@@ -371,7 +374,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
goto err_device_unregister;
pie_irq = platform_get_irq(pdev, 1);
- if (pie_irq < 0 || pie_irq >= nr_irqs)
+ if (pie_irq <= 0)
goto err_free_irq;
retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile
index 4f4e7cf105d4..d0eae59bc366 100644
--- a/drivers/s390/Makefile
+++ b/drivers/s390/Makefile
@@ -4,7 +4,7 @@
CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
-obj-y += s390mach.o sysinfo.o s390_rdev.o
+obj-y += s390mach.o sysinfo.o
obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/
drivers-y += drivers/s390/built-in.o
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 570ae59c1d5e..bd5914994142 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -336,6 +336,9 @@ static int
dasd_state_ready_to_online(struct dasd_device * device)
{
int rc;
+ struct gendisk *disk;
+ struct disk_part_iter piter;
+ struct hd_struct *part;
if (device->discipline->ready_to_online) {
rc = device->discipline->ready_to_online(device);
@@ -343,8 +346,14 @@ dasd_state_ready_to_online(struct dasd_device * device)
return rc;
}
device->state = DASD_STATE_ONLINE;
- if (device->block)
+ if (device->block) {
dasd_schedule_block_bh(device->block);
+ disk = device->block->bdev->bd_disk;
+ disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
+ while ((part = disk_part_iter_next(&piter)))
+ kobject_uevent(&part_to_dev(part)->kobj, KOBJ_CHANGE);
+ disk_part_iter_exit(&piter);
+ }
return 0;
}
@@ -354,6 +363,9 @@ dasd_state_ready_to_online(struct dasd_device * device)
static int dasd_state_online_to_ready(struct dasd_device *device)
{
int rc;
+ struct gendisk *disk;
+ struct disk_part_iter piter;
+ struct hd_struct *part;
if (device->discipline->online_to_ready) {
rc = device->discipline->online_to_ready(device);
@@ -361,6 +373,13 @@ static int dasd_state_online_to_ready(struct dasd_device *device)
return rc;
}
device->state = DASD_STATE_READY;
+ if (device->block) {
+ disk = device->block->bdev->bd_disk;
+ disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
+ while ((part = disk_part_iter_next(&piter)))
+ kobject_uevent(&part_to_dev(part)->kobj, KOBJ_CHANGE);
+ disk_part_iter_exit(&piter);
+ }
return 0;
}
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index b8f9c00633f3..d82aad5224f0 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -2621,7 +2621,7 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
}
}
- /* double-check if current erp/cqr was successfull */
+ /* double-check if current erp/cqr was successful */
if ((cqr->irb.scsw.cmd.cstat == 0x00) &&
(cqr->irb.scsw.cmd.dstat ==
(DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 2ef25731d197..300e28a531f8 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -206,6 +206,8 @@ dasd_feature_list(char *str, char **endp)
features |= DASD_FEATURE_USEDIAG;
else if (len == 6 && !strncmp(str, "erplog", 6))
features |= DASD_FEATURE_ERPLOG;
+ else if (len == 8 && !strncmp(str, "failfast", 8))
+ features |= DASD_FEATURE_FAILFAST;
else {
MESSAGE(KERN_WARNING,
"unsupported feature: %*s, "
@@ -667,6 +669,51 @@ dasd_device_from_cdev(struct ccw_device *cdev)
*/
/*
+ * failfast controls the behaviour, if no path is available
+ */
+static ssize_t dasd_ff_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct dasd_devmap *devmap;
+ int ff_flag;
+
+ devmap = dasd_find_busid(dev->bus_id);
+ if (!IS_ERR(devmap))
+ ff_flag = (devmap->features & DASD_FEATURE_FAILFAST) != 0;
+ else
+ ff_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_FAILFAST) != 0;
+ return snprintf(buf, PAGE_SIZE, ff_flag ? "1\n" : "0\n");
+}
+
+static ssize_t dasd_ff_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dasd_devmap *devmap;
+ int val;
+ char *endp;
+
+ devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
+ if (IS_ERR(devmap))
+ return PTR_ERR(devmap);
+
+ val = simple_strtoul(buf, &endp, 0);
+ if (((endp + 1) < (buf + count)) || (val > 1))
+ return -EINVAL;
+
+ spin_lock(&dasd_devmap_lock);
+ if (val)
+ devmap->features |= DASD_FEATURE_FAILFAST;
+ else
+ devmap->features &= ~DASD_FEATURE_FAILFAST;
+ if (devmap->device)
+ devmap->device->features = devmap->features;
+ spin_unlock(&dasd_devmap_lock);
+ return count;
+}
+
+static DEVICE_ATTR(failfast, 0644, dasd_ff_show, dasd_ff_store);
+
+/*
* readonly controls the readonly status of a dasd
*/
static ssize_t
@@ -1020,6 +1067,7 @@ static struct attribute * dasd_attrs[] = {
&dev_attr_use_diag.attr,
&dev_attr_eer_enabled.attr,
&dev_attr_erplog.attr,
+ &dev_attr_failfast.attr,
NULL,
};
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 7844461a995b..ef2a56952054 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -544,7 +544,8 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
}
cqr->retries = DIAG_MAX_RETRIES;
cqr->buildclk = get_clock();
- if (blk_noretry_request(req))
+ if (blk_noretry_request(req) ||
+ block->base->features & DASD_FEATURE_FAILFAST)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->startdev = memdev;
cqr->memdev = memdev;
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index bd2c52e20762..bdb87998f364 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1700,7 +1700,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
recid++;
}
}
- if (blk_noretry_request(req))
+ if (blk_noretry_request(req) ||
+ block->base->features & DASD_FEATURE_FAILFAST)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->startdev = startdev;
cqr->memdev = startdev;
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 892e2878d61b..f8e05ce98621 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -535,8 +535,8 @@ static int dasd_eer_open(struct inode *inp, struct file *filp)
eerb->buffer_page_count > INT_MAX / PAGE_SIZE) {
kfree(eerb);
MESSAGE(KERN_WARNING, "can't open device since module "
- "parameter eer_pages is smaller then 1 or"
- " bigger then %d", (int)(INT_MAX / PAGE_SIZE));
+ "parameter eer_pages is smaller than 1 or"
+ " bigger than %d", (int)(INT_MAX / PAGE_SIZE));
unlock_kernel();
return -EINVAL;
}
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 7d442aeff3d1..f1d176021694 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -355,7 +355,8 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
recid++;
}
}
- if (blk_noretry_request(req))
+ if (blk_noretry_request(req) ||
+ block->base->features & DASD_FEATURE_FAILFAST)
set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
cqr->startdev = memdev;
cqr->memdev = memdev;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 05a14536c369..4a39084d9c95 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -199,7 +199,7 @@ struct dasd_ccw_req {
#define DASD_CQR_ERROR 0x82 /* request is completed with error */
#define DASD_CQR_CLEAR_PENDING 0x83 /* request is clear pending */
#define DASD_CQR_CLEARED 0x84 /* request was cleared */
-#define DASD_CQR_SUCCESS 0x85 /* request was successfull */
+#define DASD_CQR_SUCCESS 0x85 /* request was successful */
/* per dasd_ccw_req flags */
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 26ffc6ab441d..cfdcf1aed33c 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -18,7 +18,6 @@
#include <asm/io.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
-#include <asm/s390_rdev.h>
#define DCSSBLK_NAME "dcssblk"
#define DCSSBLK_MINORS_PER_DISK 1
@@ -946,7 +945,7 @@ dcssblk_check_params(void)
static void __exit
dcssblk_exit(void)
{
- s390_root_dev_unregister(dcssblk_root_dev);
+ root_device_unregister(dcssblk_root_dev);
unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
}
@@ -955,22 +954,22 @@ dcssblk_init(void)
{
int rc;
- dcssblk_root_dev = s390_root_dev_register("dcssblk");
+ dcssblk_root_dev = root_device_register("dcssblk");
if (IS_ERR(dcssblk_root_dev))
return PTR_ERR(dcssblk_root_dev);
rc = device_create_file(dcssblk_root_dev, &dev_attr_add);
if (rc) {
- s390_root_dev_unregister(dcssblk_root_dev);
+ root_device_unregister(dcssblk_root_dev);
return rc;
}
rc = device_create_file(dcssblk_root_dev, &dev_attr_remove);
if (rc) {
- s390_root_dev_unregister(dcssblk_root_dev);
+ root_device_unregister(dcssblk_root_dev);
return rc;
}
rc = register_blkdev(0, DCSSBLK_NAME);
if (rc < 0) {
- s390_root_dev_unregister(dcssblk_root_dev);
+ root_device_unregister(dcssblk_root_dev);
return rc;
}
dcssblk_major = rc;
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
index 643033890e34..0769ced52dbd 100644
--- a/drivers/s390/char/Kconfig
+++ b/drivers/s390/char/Kconfig
@@ -100,7 +100,7 @@ comment "S/390 tape interface support"
config S390_TAPE_BLOCK
bool "Support for tape block devices"
- depends on S390_TAPE
+ depends on S390_TAPE && BLOCK
help
Select this option if you want to access your channel-attached tape
devices using the block device interface. This interface is similar
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 4005c44a404c..71605a179d65 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -801,7 +801,7 @@ tape_3590_done(struct tape_device *device, struct tape_request *request)
static inline int
tape_3590_erp_succeded(struct tape_device *device, struct tape_request *request)
{
- DBF_EVENT(3, "Error Recovery successfull for %s\n",
+ DBF_EVENT(3, "Error Recovery successful for %s\n",
tape_op_verbose[request->op]);
return tape_3590_done(device, request);
}
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index aabbeb909cc6..d8a2289fcb69 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -427,7 +427,7 @@ static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
buffer = priv->buffer + sizeof(int);
}
/*
- * If the record is bigger then our buffer, we receive only
+ * If the record is bigger than our buffer, we receive only
* a part of it. We can get the rest later.
*/
if (iucv_data_count > NET_BUFFER_SIZE)
@@ -437,7 +437,7 @@ static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv)
0, buffer, iucv_data_count,
&priv->residual_length);
spin_unlock_bh(&priv->priv_lock);
- /* An rc of 5 indicates that the record was bigger then
+ /* An rc of 5 indicates that the record was bigger than
* the buffer, which is OK for us. A 9 indicates that the
* record was purged befor we could receive it.
*/
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 8a8df7552969..659f8a791656 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -379,7 +379,7 @@ int cio_commit_config(struct subchannel *sch)
if (ccode < 0) /* -EIO if msch gets a program check. */
return ccode;
switch (ccode) {
- case 0: /* successfull */
+ case 0: /* successful */
if (stsch(sch->schid, &schib) ||
!css_sch_is_valid(&schib))
return -ENODEV;
@@ -632,8 +632,8 @@ do_IRQ (struct pt_regs *regs)
struct pt_regs *old_regs;
old_regs = set_irq_regs(regs);
- irq_enter();
s390_idle_check();
+ irq_enter();
if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/* Serve timer interrupts first. */
clock_comparator_work();
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index f8a3b6967f69..da7afb04e71f 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -169,6 +169,8 @@ static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
q->nr);
debugfs_queues[i] = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
debugfs_root, q, &debugfs_fops);
+ if (IS_ERR(debugfs_queues[i]))
+ debugfs_queues[i] = NULL;
}
void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 744f928a59ea..10cb0f8726e5 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -114,7 +114,7 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
* @count: count of buffers to examine
* @auto_ack: automatically acknowledge buffers
*
- * Returns the number of successfull extracted equal buffer states.
+ * Returns the number of successfully extracted equal buffer states.
* Stops processing if a state is different from the last buffers state.
*/
static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 1f5f5d2d87d9..9c148406b980 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -36,7 +36,6 @@
#include <linux/notifier.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
-#include <asm/s390_rdev.h>
#include <asm/reset.h>
#include <asm/airq.h>
#include <asm/atomic.h>
@@ -1522,7 +1521,7 @@ int __init ap_module_init(void)
}
/* Create /sys/devices/ap. */
- ap_root_device = s390_root_dev_register("ap");
+ ap_root_device = root_device_register("ap");
rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0;
if (rc)
goto out_bus;
@@ -1565,7 +1564,7 @@ out_work:
hrtimer_cancel(&ap_poll_timer);
destroy_workqueue(ap_work_queue);
out_root:
- s390_root_dev_unregister(ap_root_device);
+ root_device_unregister(ap_root_device);
out_bus:
while (i--)
bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
@@ -1600,7 +1599,7 @@ void ap_module_exit(void)
hrtimer_cancel(&ap_poll_timer);
destroy_workqueue(ap_work_queue);
tasklet_kill(&ap_tasklet);
- s390_root_dev_unregister(ap_root_device);
+ root_device_unregister(ap_root_device);
while ((dev = bus_find_device(&ap_bus_type, NULL, NULL,
__ap_match_all)))
{
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 28c90b89f2b4..cbc8566fab70 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -24,7 +24,6 @@
#include <asm/kvm_virtio.h>
#include <asm/setup.h>
#include <asm/s390_ext.h>
-#include <asm/s390_rdev.h>
#define VIRTIO_SUBCODE_64 0x0D00
@@ -335,7 +334,7 @@ static int __init kvm_devices_init(void)
if (!MACHINE_IS_KVM)
return -ENODEV;
- kvm_root = s390_root_dev_register("kvm_s390");
+ kvm_root = root_device_register("kvm_s390");
if (IS_ERR(kvm_root)) {
rc = PTR_ERR(kvm_root);
printk(KERN_ERR "Could not register kvm_s390 root device");
@@ -344,7 +343,7 @@ static int __init kvm_devices_init(void)
rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
if (rc) {
- s390_root_dev_unregister(kvm_root);
+ root_device_unregister(kvm_root);
return rc;
}
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index f4a32375c037..48383459e99b 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/err.h>
-#include <asm/s390_rdev.h>
#include <asm/ccwdev.h>
#include <asm/ccwgroup.h>
@@ -120,12 +119,12 @@ cu3088_init (void)
{
int rc;
- cu3088_root_dev = s390_root_dev_register("cu3088");
+ cu3088_root_dev = root_device_register("cu3088");
if (IS_ERR(cu3088_root_dev))
return PTR_ERR(cu3088_root_dev);
rc = ccw_driver_register(&cu3088_driver);
if (rc)
- s390_root_dev_unregister(cu3088_root_dev);
+ root_device_unregister(cu3088_root_dev);
return rc;
}
@@ -134,7 +133,7 @@ static void __exit
cu3088_exit (void)
{
ccw_driver_unregister(&cu3088_driver);
- s390_root_dev_unregister(cu3088_root_dev);
+ root_device_unregister(cu3088_root_dev);
}
MODULE_DEVICE_TABLE(ccw,cu3088_ids);
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index acca6678cb2b..49c3bfa1afd7 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -70,7 +70,9 @@ static char debug_buffer[255];
static void lcs_tasklet(unsigned long);
static void lcs_start_kernel_thread(struct work_struct *);
static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
+#ifdef CONFIG_IP_MULTICAST
static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
+#endif /* CONFIG_IP_MULTICAST */
static int lcs_recovery(void *ptr);
/**
@@ -1285,6 +1287,8 @@ out:
lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
return 0;
}
+#endif /* CONFIG_IP_MULTICAST */
+
/**
* function called by net device to
* handle multicast address relevant things
@@ -1292,6 +1296,7 @@ out:
static void
lcs_set_multicast_list(struct net_device *dev)
{
+#ifdef CONFIG_IP_MULTICAST
struct lcs_card *card;
LCS_DBF_TEXT(4, trace, "setmulti");
@@ -1299,9 +1304,8 @@ lcs_set_multicast_list(struct net_device *dev)
if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD))
schedule_work(&card->kernel_thread_starter);
-}
-
#endif /* CONFIG_IP_MULTICAST */
+}
static long
lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb)
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index d5ccce1643e4..e0c45574b0c8 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -643,7 +643,6 @@ struct qeth_card_options {
int macaddr_mode;
int fake_broadcast;
int add_hhlen;
- int fake_ll;
int layer2;
enum qeth_large_send_types large_send;
int performance_stats;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index e783644a2105..d1b5bebea7fb 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -24,7 +24,6 @@
#include <asm/ebcdic.h>
#include <asm/io.h>
-#include <asm/s390_rdev.h>
#include "qeth_core.h"
#include "qeth_core_offl.h"
@@ -287,8 +286,15 @@ int qeth_set_large_send(struct qeth_card *card,
card->options.large_send = type;
switch (card->options.large_send) {
case QETH_LARGE_SEND_EDDP:
- card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
+ if (card->info.type != QETH_CARD_TYPE_IQD) {
+ card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
NETIF_F_HW_CSUM;
+ } else {
+ card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
+ NETIF_F_HW_CSUM);
+ card->options.large_send = QETH_LARGE_SEND_NO;
+ rc = -EOPNOTSUPP;
+ }
break;
case QETH_LARGE_SEND_TSO:
if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
@@ -572,6 +578,10 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel,
card = CARD_FROM_CDEV(channel->ccwdev);
if (qeth_check_idx_response(iob->data)) {
qeth_clear_ipacmd_list(card);
+ if (((iob->data[2] & 0xc0) == 0xc0) && iob->data[4] == 0xf6)
+ dev_err(&card->gdev->dev,
+ "The qeth device is not configured "
+ "for the OSI layer required by z/VM\n");
qeth_schedule_recovery(card);
goto out;
}
@@ -1072,7 +1082,6 @@ static void qeth_set_intial_options(struct qeth_card *card)
card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL;
card->options.fake_broadcast = 0;
card->options.add_hhlen = DEFAULT_ADD_HHLEN;
- card->options.fake_ll = 0;
card->options.performance_stats = 0;
card->options.rx_sg_cb = QETH_RX_SG_CB;
}
@@ -1682,6 +1691,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
unsigned long flags;
struct qeth_reply *reply = NULL;
unsigned long timeout;
+ struct qeth_ipa_cmd *cmd;
QETH_DBF_TEXT(TRACE, 2, "sendctl");
@@ -1728,17 +1738,34 @@ int qeth_send_control_data(struct qeth_card *card, int len,
wake_up(&card->wait_q);
return rc;
}
- while (!atomic_read(&reply->received)) {
- if (time_after(jiffies, timeout)) {
- spin_lock_irqsave(&reply->card->lock, flags);
- list_del_init(&reply->list);
- spin_unlock_irqrestore(&reply->card->lock, flags);
- reply->rc = -ETIME;
- atomic_inc(&reply->received);
- wake_up(&reply->wait_q);
- }
- cpu_relax();
- };
+
+ /* we have only one long running ipassist, since we can ensure
+ process context of this command we can sleep */
+ cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
+ if ((cmd->hdr.command == IPA_CMD_SETIP) &&
+ (cmd->hdr.prot_version == QETH_PROT_IPV4)) {
+ if (!wait_event_timeout(reply->wait_q,
+ atomic_read(&reply->received), timeout))
+ goto time_err;
+ } else {
+ while (!atomic_read(&reply->received)) {
+ if (time_after(jiffies, timeout))
+ goto time_err;
+ cpu_relax();
+ };
+ }
+
+ rc = reply->rc;
+ qeth_put_reply(reply);
+ return rc;
+
+time_err:
+ spin_lock_irqsave(&reply->card->lock, flags);
+ list_del_init(&reply->list);
+ spin_unlock_irqrestore(&reply->card->lock, flags);
+ reply->rc = -ETIME;
+ atomic_inc(&reply->received);
+ wake_up(&reply->wait_q);
rc = reply->rc;
qeth_put_reply(reply);
return rc;
@@ -2250,7 +2277,8 @@ void qeth_print_status_message(struct qeth_card *card)
}
/* fallthrough */
case QETH_CARD_TYPE_IQD:
- if (card->info.guestlan) {
+ if ((card->info.guestlan) ||
+ (card->info.mcl_level[0] & 0x80)) {
card->info.mcl_level[0] = (char) _ebcasc[(__u8)
card->info.mcl_level[0]];
card->info.mcl_level[1] = (char) _ebcasc[(__u8)
@@ -4496,7 +4524,7 @@ static int __init qeth_core_init(void)
&driver_attr_group);
if (rc)
goto driver_err;
- qeth_core_root_dev = s390_root_dev_register("qeth");
+ qeth_core_root_dev = root_device_register("qeth");
rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0;
if (rc)
goto register_err;
@@ -4510,7 +4538,7 @@ static int __init qeth_core_init(void)
return 0;
slab_err:
- s390_root_dev_unregister(qeth_core_root_dev);
+ root_device_unregister(qeth_core_root_dev);
register_err:
driver_remove_file(&qeth_core_ccwgroup_driver.driver,
&driver_attr_group);
@@ -4528,7 +4556,7 @@ out_err:
static void __exit qeth_core_exit(void)
{
- s390_root_dev_unregister(qeth_core_root_dev);
+ root_device_unregister(qeth_core_root_dev);
driver_remove_file(&qeth_core_ccwgroup_driver.driver,
&driver_attr_group);
ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver);
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 2c48591ced44..07ab8a5c1c46 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -20,8 +20,6 @@
#include <linux/mii.h>
#include <linux/ip.h>
-#include <asm/s390_rdev.h>
-
#include "qeth_core.h"
#include "qeth_core_offl.h"
@@ -918,6 +916,21 @@ static struct ethtool_ops qeth_l2_osn_ops = {
.get_drvinfo = qeth_core_get_drvinfo,
};
+static const struct net_device_ops qeth_l2_netdev_ops = {
+ .ndo_open = qeth_l2_open,
+ .ndo_stop = qeth_l2_stop,
+ .ndo_get_stats = qeth_get_stats,
+ .ndo_start_xmit = qeth_l2_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = qeth_l2_set_multicast_list,
+ .ndo_do_ioctl = qeth_l2_do_ioctl,
+ .ndo_set_mac_address = qeth_l2_set_mac_address,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid,
+ .ndo_tx_timeout = qeth_tx_timeout,
+};
+
static int qeth_l2_setup_netdev(struct qeth_card *card)
{
switch (card->info.type) {
@@ -939,19 +952,9 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
return -ENODEV;
card->dev->ml_priv = card;
- card->dev->tx_timeout = &qeth_tx_timeout;
card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
- card->dev->open = qeth_l2_open;
- card->dev->stop = qeth_l2_stop;
- card->dev->hard_start_xmit = qeth_l2_hard_start_xmit;
- card->dev->do_ioctl = qeth_l2_do_ioctl;
- card->dev->get_stats = qeth_get_stats;
- card->dev->change_mtu = qeth_change_mtu;
- card->dev->set_multicast_list = qeth_l2_set_multicast_list;
- card->dev->vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid;
- card->dev->vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid;
- card->dev->set_mac_address = qeth_l2_set_mac_address;
card->dev->mtu = card->info.initial_mtu;
+ card->dev->netdev_ops = &qeth_l2_netdev_ops;
if (card->info.type != QETH_CARD_TYPE_OSN)
SET_ETHTOOL_OPS(card->dev, &qeth_l2_ethtool_ops);
else
@@ -1126,9 +1129,11 @@ static int qeth_l2_recover(void *ptr)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
else {
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
+ if (card->dev) {
+ rtnl_lock();
+ dev_close(card->dev);
+ rtnl_unlock();
+ }
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index c0b30b25a5f1..3d04920b9bb9 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -26,8 +26,6 @@
#include <net/ip.h>
#include <net/arp.h>
-#include <asm/s390_rdev.h>
-
#include "qeth_l3.h"
#include "qeth_core_offl.h"
@@ -1047,7 +1045,7 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card)
rc = qeth_setadpparms_change_macaddr(card);
if (rc)
dev_warn(&card->gdev->dev, "Reading the adapter MAC"
- " address failed\n", rc);
+ " address failed\n");
}
if ((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
@@ -1207,12 +1205,9 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
QETH_DBF_TEXT(TRACE, 3, "stsrcmac");
- if (!card->options.fake_ll)
- return -EOPNOTSUPP;
-
if (!qeth_is_supported(card, IPA_SOURCE_MAC)) {
dev_info(&card->gdev->dev,
- "Inbound source address not supported on %s\n",
+ "Inbound source MAC-address not supported on %s\n",
QETH_CARD_IFNAME(card));
return -EOPNOTSUPP;
}
@@ -1221,7 +1216,7 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
IPA_CMD_ASS_START, 0);
if (rc)
dev_warn(&card->gdev->dev,
- "Starting proxy ARP support for %s failed\n",
+ "Starting source MAC-address support for %s failed\n",
QETH_CARD_IFNAME(card));
return rc;
}
@@ -1834,28 +1829,6 @@ static void qeth_l3_vlan_rx_register(struct net_device *dev,
static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
{
- struct net_device *vlandev;
- struct qeth_card *card = dev->ml_priv;
- struct in_device *in_dev;
-
- if (card->info.type == QETH_CARD_TYPE_IQD)
- return;
-
- vlandev = vlan_group_get_device(card->vlangrp, vid);
- vlandev->neigh_setup = qeth_l3_neigh_setup;
-
- in_dev = in_dev_get(vlandev);
-#ifdef CONFIG_SYSCTL
- neigh_sysctl_unregister(in_dev->arp_parms);
-#endif
- neigh_parms_release(&arp_tbl, in_dev->arp_parms);
-
- in_dev->arp_parms = neigh_parms_alloc(vlandev, &arp_tbl);
-#ifdef CONFIG_SYSCTL
- neigh_sysctl_register(vlandev, in_dev->arp_parms, NET_IPV4,
- NET_IPV4_NEIGH, "ipv4", NULL, NULL);
-#endif
- in_dev_put(in_dev);
return;
}
@@ -1921,8 +1894,13 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card,
memcpy(tg_addr, card->dev->dev_addr,
card->dev->addr_len);
}
- card->dev->header_ops->create(skb, card->dev, prot, tg_addr,
- "FAKELL", card->dev->addr_len);
+ if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+ card->dev->header_ops->create(skb, card->dev, prot,
+ tg_addr, &hdr->hdr.l3.dest_addr[2],
+ card->dev->addr_len);
+ else
+ card->dev->header_ops->create(skb, card->dev, prot,
+ tg_addr, "FAKELL", card->dev->addr_len);
}
#ifdef CONFIG_TR
@@ -2080,9 +2058,11 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
if (recovery_mode)
qeth_l3_stop(card->dev);
else {
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
+ if (card->dev) {
+ rtnl_lock();
+ dev_close(card->dev);
+ rtnl_unlock();
+ }
}
if (!card->use_hard_stop) {
rc = qeth_send_stoplan(card);
@@ -2914,6 +2894,37 @@ qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
return 0;
}
+static const struct net_device_ops qeth_l3_netdev_ops = {
+ .ndo_open = qeth_l3_open,
+ .ndo_stop = qeth_l3_stop,
+ .ndo_get_stats = qeth_get_stats,
+ .ndo_start_xmit = qeth_l3_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = qeth_l3_set_multicast_list,
+ .ndo_do_ioctl = qeth_l3_do_ioctl,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_vlan_rx_register = qeth_l3_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
+ .ndo_tx_timeout = qeth_tx_timeout,
+};
+
+static const struct net_device_ops qeth_l3_osa_netdev_ops = {
+ .ndo_open = qeth_l3_open,
+ .ndo_stop = qeth_l3_stop,
+ .ndo_get_stats = qeth_get_stats,
+ .ndo_start_xmit = qeth_l3_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = qeth_l3_set_multicast_list,
+ .ndo_do_ioctl = qeth_l3_do_ioctl,
+ .ndo_change_mtu = qeth_change_mtu,
+ .ndo_vlan_rx_register = qeth_l3_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid,
+ .ndo_tx_timeout = qeth_tx_timeout,
+ .ndo_neigh_setup = qeth_l3_neigh_setup,
+};
+
static int qeth_l3_setup_netdev(struct qeth_card *card)
{
if (card->info.type == QETH_CARD_TYPE_OSAE) {
@@ -2924,11 +2935,12 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
#endif
if (!card->dev)
return -ENODEV;
+ card->dev->netdev_ops = &qeth_l3_netdev_ops;
} else {
card->dev = alloc_etherdev(0);
if (!card->dev)
return -ENODEV;
- card->dev->neigh_setup = qeth_l3_neigh_setup;
+ card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
/*IPv6 address autoconfiguration stuff*/
qeth_l3_get_unique_id(card);
@@ -2941,25 +2953,14 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
if (!card->dev)
return -ENODEV;
card->dev->flags |= IFF_NOARP;
+ card->dev->netdev_ops = &qeth_l3_netdev_ops;
qeth_l3_iqd_read_initial_mac(card);
} else
return -ENODEV;
- card->dev->hard_start_xmit = qeth_l3_hard_start_xmit;
card->dev->ml_priv = card;
- card->dev->tx_timeout = &qeth_tx_timeout;
card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
- card->dev->open = qeth_l3_open;
- card->dev->stop = qeth_l3_stop;
- card->dev->do_ioctl = qeth_l3_do_ioctl;
- card->dev->get_stats = qeth_get_stats;
- card->dev->change_mtu = qeth_change_mtu;
- card->dev->set_multicast_list = qeth_l3_set_multicast_list;
- card->dev->vlan_rx_register = qeth_l3_vlan_rx_register;
- card->dev->vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid;
- card->dev->vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid;
card->dev->mtu = card->info.initial_mtu;
- card->dev->set_mac_address = NULL;
SET_ETHTOOL_OPS(card->dev, &qeth_l3_ethtool_ops);
card->dev->features |= NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
diff --git a/drivers/s390/s390_rdev.c b/drivers/s390/s390_rdev.c
deleted file mode 100644
index 64371c05a3b3..000000000000
--- a/drivers/s390/s390_rdev.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * drivers/s390/s390_rdev.c
- * s390 root device
- *
- * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH,
- * IBM Corporation
- * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
- * Carsten Otte (cotte@de.ibm.com)
- */
-
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <asm/s390_rdev.h>
-
-static void
-s390_root_dev_release(struct device *dev)
-{
- kfree(dev);
-}
-
-struct device *
-s390_root_dev_register(const char *name)
-{
- struct device *dev;
- int ret;
-
- if (!strlen(name))
- return ERR_PTR(-EINVAL);
- dev = kzalloc(sizeof(struct device), GFP_KERNEL);
- if (!dev)
- return ERR_PTR(-ENOMEM);
- dev_set_name(dev, name);
- dev->release = s390_root_dev_release;
- ret = device_register(dev);
- if (ret) {
- kfree(dev);
- return ERR_PTR(ret);
- }
- return dev;
-}
-
-void
-s390_root_dev_unregister(struct device *dev)
-{
- if (dev)
- device_unregister(dev);
-}
-
-EXPORT_SYMBOL(s390_root_dev_register);
-EXPORT_SYMBOL(s390_root_dev_unregister);
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 834e9ee7e934..92b0417f8e12 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -18,6 +18,7 @@
#include <asm/etr.h>
#include <asm/lowcore.h>
#include <asm/cio.h>
+#include <asm/cpu.h>
#include "s390mach.h"
static struct semaphore m_sem;
@@ -369,6 +370,8 @@ s390_do_machine_check(struct pt_regs *regs)
lockdep_off();
+ s390_idle_check();
+
mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
mcck = &__get_cpu_var(cpu_mcck);
umode = user_mode(regs);
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 2550af4ae432..4431578d8c45 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -214,7 +214,7 @@ static int __devinit d7s_probe(struct of_device *op,
writeb(regs, p->regs);
- printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%lx] %s\n",
+ printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%llx] %s\n",
op->node->full_name,
(regs & D7S_FLIP) ? " (FLIPPED)" : "",
op->resource[0].start,
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 152d4aa9354f..256c7bec7bd7 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -21,7 +21,7 @@ config SCSI
You also need to say Y here if you have a device which speaks
the SCSI protocol. Examples of this include the parallel port
version of the IOMEGA ZIP drive, USB storage devices, Fibre
- Channel, FireWire storage and the IDE-SCSI emulation driver.
+ Channel, and FireWire storage.
To compile this driver as a module, choose M here and read
<file:Documentation/scsi/scsi.txt>.
@@ -101,9 +101,9 @@ config CHR_DEV_OSST
---help---
The OnStream SC-x0 SCSI tape drives cannot be driven by the
standard st driver, but instead need this special osst driver and
- use the /dev/osstX char device nodes (major 206). Via usb-storage
- and ide-scsi, you may be able to drive the USB-x0 and DI-x0 drives
- as well. Note that there is also a second generation of OnStream
+ use the /dev/osstX char device nodes (major 206). Via usb-storage,
+ you may be able to drive the USB-x0 and DI-x0 drives as well.
+ Note that there is also a second generation of OnStream
tape drives (ADR-x0) that supports the standard SCSI-2 commands for
tapes (QIC-157) and can be driven by the standard driver st.
For more information, you may have a look at the SCSI-HOWTO
@@ -884,6 +884,7 @@ config SCSI_IBMVSCSI
tristate "IBM Virtual SCSI support"
depends on PPC_PSERIES || PPC_ISERIES
select SCSI_SRP_ATTRS
+ select VIOPATH if PPC_ISERIES
help
This is the IBM POWER Virtual SCSI Client
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 1410697257cb..7461eb09a031 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -105,7 +105,6 @@ obj-$(CONFIG_SCSI_GDTH) += gdth.o
obj-$(CONFIG_SCSI_INITIO) += initio.o
obj-$(CONFIG_SCSI_INIA100) += a100u2w.o
obj-$(CONFIG_SCSI_QLOGICPTI) += qlogicpti.o
-obj-$(CONFIG_BLK_DEV_IDESCSI) += ide-scsi.o
obj-$(CONFIG_SCSI_MESH) += mesh.o
obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o
obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c
index 9e64b21ef637..c889d8458684 100644
--- a/drivers/scsi/NCR_D700.c
+++ b/drivers/scsi/NCR_D700.c
@@ -318,7 +318,7 @@ NCR_D700_probe(struct device *dev)
return -ENOMEM;
p->dev = dev;
- snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id);
+ snprintf(p->name, sizeof(p->name), "D700(%s)", dev_name(dev));
if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) {
printk(KERN_ERR "D700: request_irq failed\n");
kfree(p);
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 3c298c7253ee..964769f66eac 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -633,7 +633,7 @@ static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsig
return FAILED;
}
- /* Reset device is handled by the firmare, we fill in an SCB and
+ /* Reset device is handled by the firmware, we fill in an SCB and
fire it at the controller, it does the rest */
scb->opcode = ORC_BUSDEVRST;
scb->target = target;
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 07d572feceed..37dd47136fb1 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -169,10 +169,8 @@ int __init a2091_detect(struct scsi_host_template *tpnt)
continue;
instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
- if (instance == NULL) {
- release_mem_region(address, 256);
- continue;
- }
+ if (instance == NULL)
+ goto release;
instance->base = ZTWO_VADDR(address);
instance->irq = IRQ_AMIGA_PORTS;
instance->unique_id = z->slotaddr;
@@ -183,10 +181,18 @@ int __init a2091_detect(struct scsi_host_template *tpnt)
HDATA(instance)->fast = 0;
HDATA(instance)->dma_mode = CTRL_DMA;
wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
- request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
- instance);
+ if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, "A2091 SCSI",
+ instance))
+ goto unregister;
DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
num_a2091++;
+ continue;
+
+unregister:
+ scsi_unregister(instance);
+ wd33c93_release();
+release:
+ release_mem_region(address, 256);
}
return num_a2091;
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 2f602720193e..7507d8bc57a1 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2527,7 +2527,7 @@ static void asc_prt_scsi_host(struct Scsi_Host *s)
{
struct asc_board *boardp = shost_priv(s);
- printk("Scsi_Host at addr 0x%p, device %s\n", s, boardp->dev->bus_id);
+ printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev));
printk(" host_busy %u, host_no %d, last_reset %d,\n",
s->host_busy, s->host_no, (unsigned)s->last_reset);
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index d4640ef6d44f..78eb86fc6276 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -189,7 +189,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev)
asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE);
/* send a hard reset */
ASD_DPRINTK("sending %s reset to %s\n",
- reset_type ? "hard" : "soft", phy->dev.bus_id);
+ reset_type ? "hard" : "soft", dev_name(&phy->dev));
res = sas_phy_reset(phy, reset_type);
if (res == TMF_RESP_FUNC_COMPLETE) {
/* wait for the maximum settle time */
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
index 1a41f04264f7..08f3a09d9233 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
@@ -11,6 +11,7 @@
*/
#include <linux/skbuff.h>
+#include <linux/scatterlist.h>
/* from cxgb3 LLD */
#include "common.h"
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index ca7363752401..5d1bf7e3d245 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -329,12 +329,16 @@ int __init gvp11_detect(struct scsi_host_template *tpnt)
(epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10
: WD33C93_FS_12_15);
- request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, "GVP11 SCSI",
- instance);
+ if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, "GVP11 SCSI",
+ instance))
+ goto unregister;
DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
num_gvp11++;
continue;
+unregister:
+ scsi_unregister(instance);
+ wd33c93_release();
release:
release_mem_region(address, 256);
}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 3fdbb13e80a8..aa670a1d1513 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -388,8 +388,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
shost->dma_boundary = 0xffffffff;
device_initialize(&shost->shost_gendev);
- snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d",
- shost->host_no);
+ dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
#ifndef CONFIG_SYSFS_DEPRECATED
shost->shost_gendev.bus = &scsi_bus_type;
#endif
@@ -398,8 +397,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
device_initialize(&shost->shost_dev);
shost->shost_dev.parent = &shost->shost_gendev;
shost->shost_dev.class = &shost_class;
- snprintf(shost->shost_dev.bus_id, BUS_ID_SIZE, "host%d",
- shost->host_no);
+ dev_set_name(&shost->shost_dev, "host%d", shost->host_no);
shost->shost_dev.groups = scsi_sysfs_shost_attr_groups;
shost->ehandler = kthread_run(scsi_error_handler, shost,
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 44f202f33101..a1a511bdec8c 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -101,7 +101,7 @@ static const struct {
{ IBMVFC_FABRIC_MAPPED, IBMVFC_UNABLE_TO_ESTABLISH, DID_ERROR, 1, 1, "unable to establish" },
{ IBMVFC_FABRIC_MAPPED, IBMVFC_XPORT_FAULT, DID_OK, 1, 0, "transport fault" },
{ IBMVFC_FABRIC_MAPPED, IBMVFC_CMD_TIMEOUT, DID_TIME_OUT, 1, 1, "command timeout" },
- { IBMVFC_FABRIC_MAPPED, IBMVFC_ENETDOWN, DID_NO_CONNECT, 1, 1, "network down" },
+ { IBMVFC_FABRIC_MAPPED, IBMVFC_ENETDOWN, DID_TRANSPORT_DISRUPTED, 1, 1, "network down" },
{ IBMVFC_FABRIC_MAPPED, IBMVFC_HW_FAILURE, DID_ERROR, 1, 1, "hardware failure" },
{ IBMVFC_FABRIC_MAPPED, IBMVFC_LINK_DOWN_ERR, DID_REQUEUE, 0, 0, "link down" },
{ IBMVFC_FABRIC_MAPPED, IBMVFC_LINK_DEAD_ERR, DID_ERROR, 0, 0, "link dead" },
@@ -115,11 +115,11 @@ static const struct {
{ IBMVFC_VIOS_FAILURE, IBMVFC_CRQ_FAILURE, DID_REQUEUE, 1, 1, "CRQ failure" },
{ IBMVFC_VIOS_FAILURE, IBMVFC_SW_FAILURE, DID_ERROR, 0, 1, "software failure" },
- { IBMVFC_VIOS_FAILURE, IBMVFC_INVALID_PARAMETER, DID_ABORT, 0, 1, "invalid parameter" },
- { IBMVFC_VIOS_FAILURE, IBMVFC_MISSING_PARAMETER, DID_ABORT, 0, 1, "missing parameter" },
+ { IBMVFC_VIOS_FAILURE, IBMVFC_INVALID_PARAMETER, DID_ERROR, 0, 1, "invalid parameter" },
+ { IBMVFC_VIOS_FAILURE, IBMVFC_MISSING_PARAMETER, DID_ERROR, 0, 1, "missing parameter" },
{ IBMVFC_VIOS_FAILURE, IBMVFC_HOST_IO_BUS, DID_ERROR, 1, 1, "host I/O bus failure" },
- { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED, DID_ABORT, 0, 1, "transaction cancelled" },
- { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED_IMPLICIT, DID_ABORT, 0, 1, "transaction cancelled implicit" },
+ { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED, DID_ERROR, 0, 1, "transaction cancelled" },
+ { IBMVFC_VIOS_FAILURE, IBMVFC_TRANS_CANCELLED_IMPLICIT, DID_ERROR, 0, 1, "transaction cancelled implicit" },
{ IBMVFC_VIOS_FAILURE, IBMVFC_INSUFFICIENT_RESOURCE, DID_REQUEUE, 1, 1, "insufficient resources" },
{ IBMVFC_VIOS_FAILURE, IBMVFC_PLOGI_REQUIRED, DID_ERROR, 0, 1, "port login required" },
{ IBMVFC_VIOS_FAILURE, IBMVFC_COMMAND_FAILED, DID_ERROR, 1, 1, "command failed" },
@@ -933,7 +933,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost)
fc_host_speed(shost) = FC_PORTSPEED_16GBIT;
break;
default:
- ibmvfc_log(vhost, 3, "Unknown port speed: %ld Gbit\n",
+ ibmvfc_log(vhost, 3, "Unknown port speed: %lld Gbit\n",
vhost->login_buf->resp.link_speed / 100);
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
@@ -1145,10 +1145,10 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
strncpy(login_info->device_name,
- vhost->host->shost_gendev.bus_id, IBMVFC_MAX_NAME);
+ dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
location = of_get_property(of_node, "ibm,loc-code", NULL);
- location = location ? location : vhost->dev->bus_id;
+ location = location ? location : dev_name(vhost->dev);
strncpy(login_info->drc_name, location, IBMVFC_MAX_NAME);
}
@@ -1322,7 +1322,9 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
&evt->ext_list_token);
if (!evt->ext_list) {
- scmd_printk(KERN_ERR, scmd, "Can't allocate memory for scatterlist\n");
+ scsi_dma_unmap(scmd);
+ if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
+ scmd_printk(KERN_ERR, scmd, "Can't allocate memory for scatterlist\n");
return -ENOMEM;
}
}
@@ -2149,8 +2151,8 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
{
const char *desc = ibmvfc_get_ae_desc(crq->event);
- ibmvfc_log(vhost, 3, "%s event received. scsi_id: %lx, wwpn: %lx,"
- " node_name: %lx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
+ ibmvfc_log(vhost, 3, "%s event received. scsi_id: %llx, wwpn: %llx,"
+ " node_name: %llx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name);
switch (crq->event) {
case IBMVFC_AE_LINK_UP:
@@ -2184,7 +2186,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
ibmvfc_link_down(vhost, IBMVFC_HALTED);
break;
default:
- dev_err(vhost->dev, "Unknown async event received: %ld\n", crq->event);
+ dev_err(vhost->dev, "Unknown async event received: %lld\n", crq->event);
break;
};
}
@@ -2261,13 +2263,13 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
* actually sent
*/
if (unlikely(!ibmvfc_valid_event(&vhost->pool, evt))) {
- dev_err(vhost->dev, "Returned correlation_token 0x%08lx is invalid!\n",
+ dev_err(vhost->dev, "Returned correlation_token 0x%08llx is invalid!\n",
crq->ioba);
return;
}
if (unlikely(atomic_read(&evt->free))) {
- dev_err(vhost->dev, "Received duplicate correlation_token 0x%08lx!\n",
+ dev_err(vhost->dev, "Received duplicate correlation_token 0x%08llx!\n",
crq->ioba);
return;
}
@@ -3259,7 +3261,7 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
tgt = mempool_alloc(vhost->tgt_pool, GFP_KERNEL);
if (!tgt) {
- dev_err(vhost->dev, "Target allocation failure for scsi id %08lx\n",
+ dev_err(vhost->dev, "Target allocation failure for scsi id %08llx\n",
scsi_id);
return -ENOMEM;
}
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index babdf3db59df..87dafd0f8d44 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -691,13 +691,13 @@ struct ibmvfc_host {
#define DBG_CMD(CMD) do { if (ibmvfc_debug) CMD; } while (0)
#define tgt_dbg(t, fmt, ...) \
- DBG_CMD(dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__))
+ DBG_CMD(dev_info((t)->vhost->dev, "%llX: " fmt, (t)->scsi_id, ##__VA_ARGS__))
#define tgt_info(t, fmt, ...) \
- dev_info((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
+ dev_info((t)->vhost->dev, "%llX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
#define tgt_err(t, fmt, ...) \
- dev_err((t)->vhost->dev, "%lX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
+ dev_err((t)->vhost->dev, "%llX: " fmt, (t)->scsi_id, ##__VA_ARGS__)
#define ibmvfc_dbg(vhost, ...) \
DBG_CMD(dev_info((vhost)->dev, ##__VA_ARGS__))
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 868d35ea01bb..74d07d137dae 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -89,6 +89,7 @@ static int max_id = 64;
static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT;
+static int max_events = IBMVSCSI_MAX_REQUESTS_DEFAULT + 2;
static struct scsi_transport_template *ibmvscsi_transport_template;
@@ -1060,7 +1061,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
sdev_printk(KERN_INFO, cmd->device,
- "aborting command. lun 0x%lx, tag 0x%lx\n",
+ "aborting command. lun 0x%llx, tag 0x%llx\n",
(((u64) lun) << 48), (u64) found_evt);
wait_for_completion(&evt->comp);
@@ -1081,7 +1082,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
if (rsp_rc) {
if (printk_ratelimit())
sdev_printk(KERN_WARNING, cmd->device,
- "abort code %d for task tag 0x%lx\n",
+ "abort code %d for task tag 0x%llx\n",
rsp_rc, tsk_mgmt->task_tag);
return FAILED;
}
@@ -1101,12 +1102,12 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
if (found_evt == NULL) {
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
- sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%lx completed\n",
+ sdev_printk(KERN_INFO, cmd->device, "aborted task tag 0x%llx completed\n",
tsk_mgmt->task_tag);
return SUCCESS;
}
- sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%lx\n",
+ sdev_printk(KERN_INFO, cmd->device, "successfully aborted task tag 0x%llx\n",
tsk_mgmt->task_tag);
cmd->result = (DID_ABORT << 16);
@@ -1181,7 +1182,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
return FAILED;
}
- sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
+ sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%llx\n",
(((u64) lun) << 48));
wait_for_completion(&evt->comp);
@@ -1202,7 +1203,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
if (rsp_rc) {
if (printk_ratelimit())
sdev_printk(KERN_WARNING, cmd->device,
- "reset code %d for task tag 0x%lx\n",
+ "reset code %d for task tag 0x%llx\n",
rsp_rc, tsk_mgmt->task_tag);
return FAILED;
}
@@ -1633,7 +1634,7 @@ static struct scsi_host_template driver_template = {
static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev)
{
/* iu_storage data allocated in initialize_event_pool */
- unsigned long desired_io = max_requests * sizeof(union viosrp_iu);
+ unsigned long desired_io = max_events * sizeof(union viosrp_iu);
/* add io space for sg data */
desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 *
@@ -1657,7 +1658,6 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vdev->dev.driver_data = NULL;
- driver_template.can_queue = max_requests - 2;
host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
if (!host) {
dev_err(&vdev->dev, "couldn't allocate host data\n");
@@ -1673,12 +1673,12 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
atomic_set(&hostdata->request_limit, -1);
hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
- rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests);
+ rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_events);
if (rc != 0 && rc != H_RESOURCE) {
dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc);
goto init_crq_failed;
}
- if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
+ if (initialize_event_pool(&hostdata->pool, max_events, hostdata) != 0) {
dev_err(&vdev->dev, "couldn't initialize event pool\n");
goto init_pool_failed;
}
@@ -1730,7 +1730,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
add_host_failed:
release_event_pool(&hostdata->pool, hostdata);
init_pool_failed:
- ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests);
+ ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_events);
init_crq_failed:
scsi_host_put(host);
scsi_host_alloc_failed:
@@ -1742,7 +1742,7 @@ static int ibmvscsi_remove(struct vio_dev *vdev)
struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
release_event_pool(&hostdata->pool, hostdata);
ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata,
- max_requests);
+ max_events);
srp_remove_host(hostdata->host);
scsi_remove_host(hostdata->host);
@@ -1779,6 +1779,10 @@ int __init ibmvscsi_module_init(void)
{
int ret;
+ /* Ensure we have two requests to do error recovery */
+ driver_template.can_queue = max_requests;
+ max_events = max_requests + 2;
+
if (firmware_has_feature(FW_FEATURE_ISERIES))
ibmvscsi_ops = &iseriesvscsi_ops;
else if (firmware_has_feature(FW_FEATURE_VIO))
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
deleted file mode 100644
index c24140aff8e7..000000000000
--- a/drivers/scsi/ide-scsi.c
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 1996-1999 Gadi Oxman <gadio@netvision.net.il>
- * Copyright (C) 2004-2005 Bartlomiej Zolnierkiewicz
- */
-
-/*
- * Emulation of a SCSI host adapter for IDE ATAPI devices.
- *
- * With this driver, one can use the Linux SCSI drivers instead of the
- * native IDE ATAPI drivers.
- *
- * Ver 0.1 Dec 3 96 Initial version.
- * Ver 0.2 Jan 26 97 Fixed bug in cleanup_module() and added emulation
- * of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks
- * to Janos Farkas for pointing this out.
- * Avoid using bitfields in structures for m68k.
- * Added Scatter/Gather and DMA support.
- * Ver 0.4 Dec 7 97 Add support for ATAPI PD/CD drives.
- * Use variable timeout for each command.
- * Ver 0.5 Jan 2 98 Fix previous PD/CD support.
- * Allow disabling of SCSI-6 to SCSI-10 transformation.
- * Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer
- * for access through /dev/sg.
- * Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
- * Ver 0.7 Dec 04 98 Ignore commands where lun != 0 to avoid multiple
- * detection of devices with CONFIG_SCSI_MULTI_LUN
- * Ver 0.8 Feb 05 99 Optical media need translation too. Reverse 0.7.
- * Ver 0.9 Jul 04 99 Fix a bug in SG_SET_TRANSFORM.
- * Ver 0.91 Jun 10 02 Fix "off by one" error in transforms
- * Ver 0.92 Dec 31 02 Implement new SCSI mid level API
- */
-
-#define IDESCSI_VERSION "0.92"
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/ide.h>
-#include <linux/scatterlist.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/sg.h>
-
-#define IDESCSI_DEBUG_LOG 0
-
-#if IDESCSI_DEBUG_LOG
-#define debug_log(fmt, args...) \
- printk(KERN_INFO "ide-scsi: " fmt, ## args)
-#else
-#define debug_log(fmt, args...) do {} while (0)
-#endif
-
-/*
- * SCSI command transformation layer
- */
-#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */
-
-/*
- * Log flags
- */
-#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */
-
-typedef struct ide_scsi_obj {
- ide_drive_t *drive;
- ide_driver_t *driver;
- struct gendisk *disk;
- struct Scsi_Host *host;
-
- unsigned long transform; /* SCSI cmd translation layer */
- unsigned long log; /* log flags */
-} idescsi_scsi_t;
-
-static DEFINE_MUTEX(idescsi_ref_mutex);
-/* Set by module param to skip cd */
-static int idescsi_nocd;
-
-#define ide_scsi_g(disk) \
- container_of((disk)->private_data, struct ide_scsi_obj, driver)
-
-static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
-{
- struct ide_scsi_obj *scsi = NULL;
-
- mutex_lock(&idescsi_ref_mutex);
- scsi = ide_scsi_g(disk);
- if (scsi) {
- if (ide_device_get(scsi->drive))
- scsi = NULL;
- else
- scsi_host_get(scsi->host);
- }
- mutex_unlock(&idescsi_ref_mutex);
- return scsi;
-}
-
-static void ide_scsi_put(struct ide_scsi_obj *scsi)
-{
- ide_drive_t *drive = scsi->drive;
-
- mutex_lock(&idescsi_ref_mutex);
- scsi_host_put(scsi->host);
- ide_device_put(drive);
- mutex_unlock(&idescsi_ref_mutex);
-}
-
-static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host)
-{
- return (idescsi_scsi_t*) (&host[1]);
-}
-
-static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
-{
- return scsihost_to_idescsi(ide_drive->driver_data);
-}
-
-static void ide_scsi_hex_dump(u8 *data, int len)
-{
- print_hex_dump(KERN_CONT, "", DUMP_PREFIX_NONE, 16, 1, data, len, 0);
-}
-
-static int idescsi_end_request(ide_drive_t *, int, int);
-
-static void ide_scsi_callback(ide_drive_t *drive, int dsc)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct ide_atapi_pc *pc = drive->pc;
-
- if (pc->flags & PC_FLAG_TIMEDOUT)
- debug_log("%s: got timed out packet %lu at %lu\n", __func__,
- pc->scsi_cmd->serial_number, jiffies);
- /* end this request now - scsi should retry it*/
- else if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk(KERN_INFO "Packet command completed, %d bytes"
- " transferred\n", pc->xferred);
-
- idescsi_end_request(drive, 1, 0);
-}
-
-static int idescsi_check_condition(ide_drive_t *drive,
- struct request *failed_cmd)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct ide_atapi_pc *pc;
- struct request *rq;
- u8 *buf;
-
- /* stuff a sense request in front of our current request */
- pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = blk_get_request(drive->queue, READ, GFP_ATOMIC);
- buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
- if (!pc || !rq || !buf) {
- kfree(buf);
- if (rq)
- blk_put_request(rq);
- kfree(pc);
- return -ENOMEM;
- }
- rq->special = (char *) pc;
- pc->rq = rq;
- pc->buf = buf;
- pc->c[0] = REQUEST_SENSE;
- pc->c[4] = pc->req_xfer = pc->buf_size = SCSI_SENSE_BUFFERSIZE;
- rq->cmd_type = REQ_TYPE_SENSE;
- rq->cmd_flags |= REQ_PREEMPT;
- pc->timeout = jiffies + WAIT_READY;
- /* NOTE! Save the failed packet command in "rq->buffer" */
- rq->buffer = (void *) failed_cmd->special;
- pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
- printk ("ide-scsi: %s: queue cmd = ", drive->name);
- ide_scsi_hex_dump(pc->c, 6);
- }
- rq->rq_disk = scsi->disk;
- rq->ref_count++;
- memcpy(rq->cmd, pc->c, 12);
- ide_do_drive_cmd(drive, rq);
- return 0;
-}
-
-static ide_startstop_t
-idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
- ide_hwif_t *hwif = drive->hwif;
-
- if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ))
- /* force an abort */
- hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE);
-
- rq->errors++;
-
- idescsi_end_request(drive, 0, 0);
-
- return ide_stopped;
-}
-
-static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
-{
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
- struct request *rq = HWGROUP(drive)->rq;
- struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special;
- int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
- struct Scsi_Host *host;
- int errors = rq->errors;
- unsigned long flags;
-
- if (!blk_special_request(rq) && !blk_sense_request(rq)) {
- ide_end_request(drive, uptodate, nrsecs);
- return 0;
- }
- ide_end_drive_cmd (drive, 0, 0);
- if (blk_sense_request(rq)) {
- struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer;
- if (log) {
- printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
- ide_scsi_hex_dump(pc->buf, 16);
- }
- memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf,
- SCSI_SENSE_BUFFERSIZE);
- kfree(pc->buf);
- kfree(pc);
- blk_put_request(rq);
- pc = opc;
- rq = pc->rq;
- pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
- (((pc->flags & PC_FLAG_TIMEDOUT) ?
- DID_TIME_OUT :
- DID_OK) << 16);
- } else if (pc->flags & PC_FLAG_TIMEDOUT) {
- if (log)
- printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
- drive->name, pc->scsi_cmd->serial_number);
- pc->scsi_cmd->result = DID_TIME_OUT << 16;
- } else if (errors >= ERROR_MAX) {
- pc->scsi_cmd->result = DID_ERROR << 16;
- if (log)
- printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);
- } else if (errors) {
- if (log)
- printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);
- if (!idescsi_check_condition(drive, rq))
- /* we started a request sense, so we'll be back, exit for now */
- return 0;
- pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
- } else {
- pc->scsi_cmd->result = DID_OK << 16;
- }
- host = pc->scsi_cmd->device->host;
- spin_lock_irqsave(host->host_lock, flags);
- pc->done(pc->scsi_cmd);
- spin_unlock_irqrestore(host->host_lock, flags);
- kfree(pc);
- blk_put_request(rq);
- drive->pc = NULL;
- return 0;
-}
-
-static inline int idescsi_set_direction(struct ide_atapi_pc *pc)
-{
- switch (pc->c[0]) {
- case READ_6: case READ_10: case READ_12:
- pc->flags &= ~PC_FLAG_WRITING;
- return 0;
- case WRITE_6: case WRITE_10: case WRITE_12:
- pc->flags |= PC_FLAG_WRITING;
- return 0;
- default:
- return 1;
- }
-}
-
-static int idescsi_map_sg(ide_drive_t *drive, struct ide_atapi_pc *pc)
-{
- ide_hwif_t *hwif = drive->hwif;
- struct scatterlist *sg, *scsi_sg;
- int segments;
-
- if (!pc->req_xfer || pc->req_xfer % 1024)
- return 1;
-
- if (idescsi_set_direction(pc))
- return 1;
-
- sg = hwif->sg_table;
- scsi_sg = scsi_sglist(pc->scsi_cmd);
- segments = scsi_sg_count(pc->scsi_cmd);
-
- if (segments > hwif->sg_max_nents)
- return 1;
-
- hwif->sg_nents = segments;
- memcpy(sg, scsi_sg, sizeof(*sg) * segments);
-
- return 0;
-}
-
-static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
- struct ide_atapi_pc *pc)
-{
- /* Set the current packet command */
- drive->pc = pc;
-
- return ide_issue_pc(drive, ide_scsi_get_timeout(pc), ide_scsi_expiry);
-}
-
-/*
- * idescsi_do_request is our request handling function.
- */
-static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *rq, sector_t block)
-{
- debug_log("dev: %s, cmd: %x, errors: %d\n", rq->rq_disk->disk_name,
- rq->cmd[0], rq->errors);
- debug_log("sector: %ld, nr_sectors: %ld, current_nr_sectors: %d\n",
- rq->sector, rq->nr_sectors, rq->current_nr_sectors);
-
- if (blk_sense_request(rq) || blk_special_request(rq)) {
- struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
-
- if ((drive->dev_flags & IDE_DFLAG_USING_DMA) &&
- idescsi_map_sg(drive, pc) == 0)
- pc->flags |= PC_FLAG_DMA_OK;
-
- return idescsi_issue_pc(drive, pc);
- }
- blk_dump_rq_flags(rq, "ide-scsi: unsup command");
- idescsi_end_request (drive, 0, 0);
- return ide_stopped;
-}
-
-#ifdef CONFIG_IDE_PROC_FS
-static ide_proc_entry_t idescsi_proc[] = {
- { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
- { NULL, 0, NULL, NULL }
-};
-
-#define ide_scsi_devset_get(name, field) \
-static int get_##name(ide_drive_t *drive) \
-{ \
- idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
- return scsi->field; \
-}
-
-#define ide_scsi_devset_set(name, field) \
-static int set_##name(ide_drive_t *drive, int arg) \
-{ \
- idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
- scsi->field = arg; \
- return 0; \
-}
-
-#define ide_scsi_devset_rw_field(_name, _field) \
-ide_scsi_devset_get(_name, _field); \
-ide_scsi_devset_set(_name, _field); \
-IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name);
-
-ide_devset_rw_field(bios_cyl, bios_cyl);
-ide_devset_rw_field(bios_head, bios_head);
-ide_devset_rw_field(bios_sect, bios_sect);
-
-ide_scsi_devset_rw_field(transform, transform);
-ide_scsi_devset_rw_field(log, log);
-
-static const struct ide_proc_devset idescsi_settings[] = {
- IDE_PROC_DEVSET(bios_cyl, 0, 1023),
- IDE_PROC_DEVSET(bios_head, 0, 255),
- IDE_PROC_DEVSET(bios_sect, 0, 63),
- IDE_PROC_DEVSET(log, 0, 1),
- IDE_PROC_DEVSET(transform, 0, 3),
- { 0 },
-};
-
-static ide_proc_entry_t *ide_scsi_proc_entries(ide_drive_t *drive)
-{
- return idescsi_proc;
-}
-
-static const struct ide_proc_devset *ide_scsi_proc_devsets(ide_drive_t *drive)
-{
- return idescsi_settings;
-}
-#endif
-
-/*
- * Driver initialization.
- */
-static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
-{
- clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
-#if IDESCSI_DEBUG_LOG
- set_bit(IDESCSI_LOG_CMD, &scsi->log);
-#endif /* IDESCSI_DEBUG_LOG */
-
- drive->pc_callback = ide_scsi_callback;
- drive->pc_update_buffers = NULL;
- drive->pc_io_buffers = ide_io_buffers;
-
- ide_proc_register_driver(drive, scsi->driver);
-}
-
-static void ide_scsi_remove(ide_drive_t *drive)
-{
- struct Scsi_Host *scsihost = drive->driver_data;
- struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
- struct gendisk *g = scsi->disk;
-
- scsi_remove_host(scsihost);
- ide_proc_unregister_driver(drive, scsi->driver);
-
- ide_unregister_region(g);
-
- drive->driver_data = NULL;
- g->private_data = NULL;
- put_disk(g);
-
- ide_scsi_put(scsi);
-
- drive->dev_flags &= ~IDE_DFLAG_SCSI;
-}
-
-static int ide_scsi_probe(ide_drive_t *);
-
-static ide_driver_t idescsi_driver = {
- .gen_driver = {
- .owner = THIS_MODULE,
- .name = "ide-scsi",
- .bus = &ide_bus_type,
- },
- .probe = ide_scsi_probe,
- .remove = ide_scsi_remove,
- .version = IDESCSI_VERSION,
- .do_request = idescsi_do_request,
- .end_request = idescsi_end_request,
- .error = idescsi_atapi_error,
-#ifdef CONFIG_IDE_PROC_FS
- .proc_entries = ide_scsi_proc_entries,
- .proc_devsets = ide_scsi_proc_devsets,
-#endif
-};
-
-static int idescsi_ide_open(struct block_device *bdev, fmode_t mode)
-{
- struct ide_scsi_obj *scsi = ide_scsi_get(bdev->bd_disk);
-
- if (!scsi)
- return -ENXIO;
-
- return 0;
-}
-
-static int idescsi_ide_release(struct gendisk *disk, fmode_t mode)
-{
- ide_scsi_put(ide_scsi_g(disk));
- return 0;
-}
-
-static int idescsi_ide_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- struct ide_scsi_obj *scsi = ide_scsi_g(bdev->bd_disk);
- return generic_ide_ioctl(scsi->drive, bdev, cmd, arg);
-}
-
-static struct block_device_operations idescsi_ops = {
- .owner = THIS_MODULE,
- .open = idescsi_ide_open,
- .release = idescsi_ide_release,
- .locked_ioctl = idescsi_ide_ioctl,
-};
-
-static int idescsi_slave_configure(struct scsi_device * sdp)
-{
- /* Configure detected device */
- sdp->use_10_for_rw = 1;
- sdp->use_10_for_ms = 1;
- scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun);
- return 0;
-}
-
-static const char *idescsi_info (struct Scsi_Host *host)
-{
- return "SCSI host adapter emulation for IDE ATAPI devices";
-}
-
-static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg)
-{
- idescsi_scsi_t *scsi = scsihost_to_idescsi(dev->host);
-
- if (cmd == SG_SET_TRANSFORM) {
- if (arg)
- set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
- else
- clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
- return 0;
- } else if (cmd == SG_GET_TRANSFORM)
- return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int __user *) arg);
- return -EINVAL;
-}
-
-static int idescsi_queue (struct scsi_cmnd *cmd,
- void (*done)(struct scsi_cmnd *))
-{
- struct Scsi_Host *host = cmd->device->host;
- idescsi_scsi_t *scsi = scsihost_to_idescsi(host);
- ide_drive_t *drive = scsi->drive;
- struct request *rq = NULL;
- struct ide_atapi_pc *pc = NULL;
- int write = cmd->sc_data_direction == DMA_TO_DEVICE;
-
- if (!drive) {
- scmd_printk (KERN_ERR, cmd, "drive not present\n");
- goto abort;
- }
- scsi = drive_to_idescsi(drive);
- pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = blk_get_request(drive->queue, write, GFP_ATOMIC);
- if (rq == NULL || pc == NULL) {
- printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
- goto abort;
- }
-
- memset (pc->c, 0, 12);
- pc->flags = 0;
- if (cmd->sc_data_direction == DMA_TO_DEVICE)
- pc->flags |= PC_FLAG_WRITING;
- pc->rq = rq;
- memcpy (pc->c, cmd->cmnd, cmd->cmd_len);
- pc->buf = NULL;
- pc->sg = scsi_sglist(cmd);
- pc->sg_cnt = scsi_sg_count(cmd);
- pc->b_count = 0;
- pc->req_xfer = pc->buf_size = scsi_bufflen(cmd);
- pc->scsi_cmd = cmd;
- pc->done = done;
- pc->timeout = jiffies + cmd->request->timeout;
-
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
- printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
- ide_scsi_hex_dump(cmd->cmnd, cmd->cmd_len);
- if (memcmp(pc->c, cmd->cmnd, cmd->cmd_len)) {
- printk ("ide-scsi: %s: que %lu, tsl = ", drive->name, cmd->serial_number);
- ide_scsi_hex_dump(pc->c, 12);
- }
- }
-
- rq->special = (char *) pc;
- rq->cmd_type = REQ_TYPE_SPECIAL;
- spin_unlock_irq(host->host_lock);
- rq->ref_count++;
- memcpy(rq->cmd, pc->c, 12);
- blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
- spin_lock_irq(host->host_lock);
- return 0;
-abort:
- kfree (pc);
- if (rq)
- blk_put_request(rq);
- cmd->result = DID_ERROR << 16;
- done(cmd);
- return 0;
-}
-
-static int idescsi_eh_abort (struct scsi_cmnd *cmd)
-{
- idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
- ide_drive_t *drive = scsi->drive;
- ide_hwif_t *hwif;
- ide_hwgroup_t *hwgroup;
- int busy;
- int ret = FAILED;
-
- struct ide_atapi_pc *pc;
-
- /* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
-
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number);
-
- if (!drive) {
- printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_abort\n");
- WARN_ON(1);
- goto no_drive;
- }
-
- hwif = drive->hwif;
- hwgroup = hwif->hwgroup;
-
- /* First give it some more time, how much is "right" is hard to say :-(
- FIXME - uses mdelay which causes latency? */
- busy = ide_wait_not_busy(hwif, 100);
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");
-
- spin_lock_irq(&hwgroup->lock);
-
- /* If there is no pc running we're done (our interrupt took care of it) */
- pc = drive->pc;
- if (pc == NULL) {
- ret = SUCCESS;
- goto ide_unlock;
- }
-
- /* It's somewhere in flight. Does ide subsystem agree? */
- if (pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
- elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != pc->rq) {
- /*
- * FIXME - not sure this condition can ever occur
- */
- printk (KERN_ERR "ide-scsi: cmd aborted!\n");
-
- if (blk_sense_request(pc->rq))
- kfree(pc->buf);
- /* we need to call blk_put_request twice. */
- blk_put_request(pc->rq);
- blk_put_request(pc->rq);
- kfree(pc);
- drive->pc = NULL;
-
- ret = SUCCESS;
- }
-
-ide_unlock:
- spin_unlock_irq(&hwgroup->lock);
-no_drive:
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");
-
- return ret;
-}
-
-static int idescsi_eh_reset (struct scsi_cmnd *cmd)
-{
- struct request *req;
- idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host);
- ide_drive_t *drive = scsi->drive;
- ide_hwgroup_t *hwgroup;
- int ready = 0;
- int ret = SUCCESS;
-
- struct ide_atapi_pc *pc;
-
- /* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
-
- if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
- printk (KERN_WARNING "ide-scsi: reset called for %lu\n", cmd->serial_number);
-
- if (!drive) {
- printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_reset\n");
- WARN_ON(1);
- return FAILED;
- }
-
- hwgroup = drive->hwif->hwgroup;
-
- spin_lock_irq(cmd->device->host->host_lock);
- spin_lock(&hwgroup->lock);
-
- pc = drive->pc;
- if (pc)
- req = pc->rq;
-
- if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) {
- printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
- spin_unlock(&hwgroup->lock);
- spin_unlock_irq(cmd->device->host->host_lock);
- return FAILED;
- }
-
- /* kill current request */
- if (__blk_end_request(req, -EIO, 0))
- BUG();
- if (blk_sense_request(req))
- kfree(pc->buf);
- kfree(pc);
- drive->pc = NULL;
- blk_put_request(req);
-
- /* now nuke the drive queue */
- while ((req = elv_next_request(drive->queue))) {
- if (__blk_end_request(req, -EIO, 0))
- BUG();
- }
-
- hwgroup->rq = NULL;
- hwgroup->handler = NULL;
- hwgroup->busy = 1; /* will set this to zero when ide reset finished */
- spin_unlock(&hwgroup->lock);
-
- ide_do_reset(drive);
-
- /* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */
-
- do {
- spin_unlock_irq(cmd->device->host->host_lock);
- msleep(50);
- spin_lock_irq(cmd->device->host->host_lock);
- } while ( HWGROUP(drive)->handler );
-
- ready = drive_is_ready(drive);
- HWGROUP(drive)->busy--;
- if (!ready) {
- printk (KERN_ERR "ide-scsi: reset failed!\n");
- ret = FAILED;
- }
-
- spin_unlock_irq(cmd->device->host->host_lock);
- return ret;
-}
-
-static int idescsi_bios(struct scsi_device *sdev, struct block_device *bdev,
- sector_t capacity, int *parm)
-{
- idescsi_scsi_t *idescsi = scsihost_to_idescsi(sdev->host);
- ide_drive_t *drive = idescsi->drive;
-
- if (drive->bios_cyl && drive->bios_head && drive->bios_sect) {
- parm[0] = drive->bios_head;
- parm[1] = drive->bios_sect;
- parm[2] = drive->bios_cyl;
- }
- return 0;
-}
-
-static struct scsi_host_template idescsi_template = {
- .module = THIS_MODULE,
- .name = "idescsi",
- .info = idescsi_info,
- .slave_configure = idescsi_slave_configure,
- .ioctl = idescsi_ioctl,
- .queuecommand = idescsi_queue,
- .eh_abort_handler = idescsi_eh_abort,
- .eh_host_reset_handler = idescsi_eh_reset,
- .bios_param = idescsi_bios,
- .can_queue = 40,
- .this_id = -1,
- .sg_tablesize = 256,
- .cmd_per_lun = 5,
- .max_sectors = 128,
- .use_clustering = DISABLE_CLUSTERING,
- .emulated = 1,
- .proc_name = "ide-scsi",
-};
-
-static int ide_scsi_probe(ide_drive_t *drive)
-{
- idescsi_scsi_t *idescsi;
- struct Scsi_Host *host;
- struct gendisk *g;
- static int warned;
- int err = -ENOMEM;
- u16 last_lun;
-
- if (!warned && drive->media == ide_cdrom) {
- printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n");
- warned = 1;
- }
-
- if (idescsi_nocd && drive->media == ide_cdrom)
- return -ENODEV;
-
- if (!strstr("ide-scsi", drive->driver_req) ||
- drive->media == ide_disk ||
- !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
- return -ENODEV;
-
- drive->dev_flags |= IDE_DFLAG_SCSI;
-
- g = alloc_disk(1 << PARTN_BITS);
- if (!g)
- goto out_host_put;
-
- ide_init_disk(g, drive);
-
- host->max_id = 1;
-
- last_lun = drive->id[ATA_ID_LAST_LUN];
- if (last_lun)
- debug_log("%s: last_lun=%u\n", drive->name, last_lun);
-
- if ((last_lun & 7) != 7)
- host->max_lun = (last_lun & 7) + 1;
- else
- host->max_lun = 1;
-
- drive->driver_data = host;
- idescsi = scsihost_to_idescsi(host);
- idescsi->drive = drive;
- idescsi->driver = &idescsi_driver;
- idescsi->host = host;
- idescsi->disk = g;
- g->private_data = &idescsi->driver;
- err = 0;
- idescsi_setup(drive, idescsi);
- g->fops = &idescsi_ops;
- ide_register_region(g);
- err = scsi_add_host(host, &drive->gendev);
- if (!err) {
- scsi_scan_host(host);
- return 0;
- }
- /* fall through on error */
- ide_unregister_region(g);
- ide_proc_unregister_driver(drive, &idescsi_driver);
-
- put_disk(g);
-out_host_put:
- drive->dev_flags &= ~IDE_DFLAG_SCSI;
- scsi_host_put(host);
- return err;
-}
-
-static int __init init_idescsi_module(void)
-{
- return driver_register(&idescsi_driver.gen_driver);
-}
-
-static void __exit exit_idescsi_module(void)
-{
- driver_unregister(&idescsi_driver.gen_driver);
-}
-
-module_param(idescsi_nocd, int, 0600);
-MODULE_PARM_DESC(idescsi_nocd, "Disable handling of CD-ROMs so they may be driven by ide-cd");
-module_init(init_idescsi_module);
-module_exit(exit_idescsi_module);
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 0edfb1fa63ce..07829009a8be 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2184,7 +2184,7 @@ static void ipr_dump_location_data(struct ipr_ioa_cfg *ioa_cfg,
sizeof(struct ipr_dump_entry_header);
driver_dump->location_entry.hdr.data_type = IPR_DUMP_DATA_TYPE_ASCII;
driver_dump->location_entry.hdr.id = IPR_DUMP_LOCATION_ID;
- strcpy(driver_dump->location_entry.location, ioa_cfg->pdev->dev.bus_id);
+ strcpy(driver_dump->location_entry.location, dev_name(&ioa_cfg->pdev->dev));
driver_dump->hdr.num_entries++;
}
@@ -4912,7 +4912,7 @@ static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
if (res && ipr_is_gata(res)) {
if (cmd == HDIO_GET_IDENTITY)
return -ENOTTY;
- return ata_scsi_ioctl(sdev, cmd, arg);
+ return ata_sas_scsi_ioctl(res->sata_port->ap, sdev, cmd, arg);
}
return -EINVAL;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 59459141b437..8f872f816fe4 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1272,7 +1272,7 @@ struct ipr_dump_entry_header {
struct ipr_dump_location_entry {
struct ipr_dump_entry_header hdr;
- u8 location[BUS_ID_SIZE];
+ u8 location[20];
}__attribute__((packed));
struct ipr_dump_trace_entry {
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 3126824da36d..4a4e6954ec79 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -103,8 +103,7 @@ lasi700_probe(struct parisc_device *dev)
hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
if (!hostdata) {
- printk(KERN_ERR "%s: Failed to allocate host data\n",
- dev->dev.bus_id);
+ dev_printk(KERN_ERR, dev, "Failed to allocate host data\n");
return -ENOMEM;
}
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 7225b6e2029e..257c24115de9 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1981,6 +1981,7 @@ void iscsi_pool_free(struct iscsi_pool *q)
kfree(q->pool[i]);
if (q->pool)
kfree(q->pool);
+ kfree(q->queue);
}
EXPORT_SYMBOL_GPL(iscsi_pool_free);
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index a745f91d2928..e7705d3532c9 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -177,7 +177,6 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
struct iscsi_segment *segment, int recv,
unsigned copied)
{
- static unsigned char padbuf[ISCSI_PAD_LEN];
struct scatterlist sg;
unsigned int pad;
@@ -233,7 +232,7 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
debug_tcp("consume %d pad bytes\n", pad);
segment->total_size += pad;
segment->size = pad;
- segment->data = padbuf;
+ segment->data = segment->padbuf;
return 0;
}
}
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 709a6f75ca9d..facc5bfcf7db 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -169,7 +169,7 @@ int sas_notify_lldd_dev_found(struct domain_device *dev)
if (res) {
printk("sas: driver on pcidev %s cannot handle "
"device %llx, error:%d\n",
- sas_ha->dev->bus_id,
+ dev_name(sas_ha->dev),
SAS_ADDR(dev->sas_addr), res);
}
}
diff --git a/drivers/scsi/libsas/sas_dump.c b/drivers/scsi/libsas/sas_dump.c
index bf34a236f946..c17c25030f1c 100644
--- a/drivers/scsi/libsas/sas_dump.c
+++ b/drivers/scsi/libsas/sas_dump.c
@@ -56,7 +56,7 @@ void sas_dprint_phye(int phyid, enum phy_event pe)
void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he)
{
- SAS_DPRINTK("ha %s: %s event\n", sas_ha->dev->bus_id,
+ SAS_DPRINTK("ha %s: %s event\n", dev_name(sas_ha->dev),
sas_hae_str[he]);
}
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index 16f93123271e..d110a366c48a 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -199,8 +199,8 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_DISCOVER:
- req->data_len =- 16;
- if (req->data_len < 0) {
+ req->data_len -= 16;
+ if ((int)req->data_len < 0) {
req->data_len = 0;
error = -EINVAL;
goto out;
@@ -215,8 +215,8 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_REPORT_PHY_SATA:
- req->data_len =- 16;
- if (req->data_len < 0) {
+ req->data_len -= 16;
+ if ((int)req->data_len < 0) {
req->data_len = 0;
error = -EINVAL;
goto out;
@@ -238,8 +238,8 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
break;
case SMP_PHY_CONTROL:
- req->data_len =- 44;
- if (req->data_len < 0) {
+ req->data_len -= 44;
+ if ((int)req->data_len < 0) {
req->data_len = 0;
error = -EINVAL;
goto out;
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index 139935a121b4..e6ac59c023f1 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -113,7 +113,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
sas_port_add_phy(port->port, phy->phy);
SAS_DPRINTK("%s added to %s, phy_mask:0x%x (%16llx)\n",
- phy->phy->dev.bus_id,port->port->dev.bus_id,
+ dev_name(&phy->phy->dev), dev_name(&port->port->dev),
port->phy_mask,
SAS_ADDR(port->attached_sas_addr));
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 744838780ada..1c558d3bce18 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -717,7 +717,7 @@ int sas_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
struct domain_device *dev = sdev_to_domain_dev(sdev);
if (dev_is_sata(dev))
- return ata_scsi_ioctl(sdev, cmd, arg);
+ return ata_sas_scsi_ioctl(dev->sata_dev.ap, sdev, cmd, arg);
return -EINVAL;
}
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 8c64494444bf..311ed6dea726 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1964,10 +1964,10 @@ lpfc_set_disctmo(struct lpfc_vport *vport)
uint32_t tmo;
if (vport->port_state == LPFC_LOCAL_CFG_LINK) {
- /* For FAN, timeout should be greater then edtov */
+ /* For FAN, timeout should be greater than edtov */
tmo = (((phba->fc_edtov + 999) / 1000) + 1);
} else {
- /* Normal discovery timeout should be > then ELS/CT timeout
+ /* Normal discovery timeout should be > than ELS/CT timeout
* FC spec states we need 3 * ratov for CT requests
*/
tmo = ((phba->fc_ratov * 3) + 3);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4c77038c8f1c..6c867311cef1 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1795,12 +1795,13 @@ lpfc_block_mgmt_io(struct lpfc_hba * phba)
int
lpfc_online(struct lpfc_hba *phba)
{
- struct lpfc_vport *vport = phba->pport;
+ struct lpfc_vport *vport;
struct lpfc_vport **vports;
int i;
if (!phba)
return 0;
+ vport = phba->pport;
if (!(vport->fc_flag & FC_OFFLINE_MODE))
return 0;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 01dfdc8696f8..a36a120561e2 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -420,7 +420,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
if (unlikely(pring->local_getidx >= max_cmd_idx)) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0315 Ring %d issue: portCmdGet %d "
- "is bigger then cmd ring %d\n",
+ "is bigger than cmd ring %d\n",
pring->ringno,
pring->local_getidx, max_cmd_idx);
@@ -1628,12 +1628,12 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
{
struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno];
/*
- * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
+ * Ring <ringno> handler: portRspPut <portRspPut> is bigger than
* rsp ring <portRspMax>
*/
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0312 Ring %d handler: portRspPut %d "
- "is bigger then rsp ring %d\n",
+ "is bigger than rsp ring %d\n",
pring->ringno, le32_to_cpu(pgp->rspPutInx),
pring->numRiocb);
@@ -2083,12 +2083,12 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
portRspPut = le32_to_cpu(pgp->rspPutInx);
if (portRspPut >= portRspMax) {
/*
- * Ring <ringno> handler: portRspPut <portRspPut> is bigger then
+ * Ring <ringno> handler: portRspPut <portRspPut> is bigger than
* rsp ring <portRspMax>
*/
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0303 Ring %d handler: portRspPut %d "
- "is bigger then rsp ring %d\n",
+ "is bigger than rsp ring %d\n",
pring->ringno, portRspPut, portRspMax);
phba->link_state = LPFC_HBA_ERROR;
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 7dc62deb4087..9fdcd60c5493 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -1967,8 +1967,8 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor)
scb->state |= aor;
/*
- * Check if this command has firmare owenership. If
- * yes, we cannot reset this command. Whenever, f/w
+ * Check if this command has firmware ownership. If
+ * yes, we cannot reset this command. Whenever f/w
* completes this command, we will return appropriate
* status from ISR.
*/
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c
index 1dd70d7a4947..23e5a876bb10 100644
--- a/drivers/scsi/mvsas.c
+++ b/drivers/scsi/mvsas.c
@@ -2959,7 +2959,7 @@ static int __devinit mvs_hw_init(struct mvs_info *mvi)
/* enable auto port detection */
mw32(GBL_PORT_TYPE, MODE_AUTO_DET_EN);
- msleep(100);
+ msleep(1100);
/* init and reset phys */
for (i = 0; i < mvi->chip->n_phy; i++) {
u32 lo = be32_to_cpu(*(u32 *)&mvi->sas_addr[4]);
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 165ff884f48e..67cde0138061 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -114,7 +114,7 @@ static int aha152x_probe(struct pcmcia_device *link)
link->io.NumPorts1 = 0x20;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
link->io.IOAddrLines = 10;
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index ce48e2d0193c..ca0dd33497ec 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -290,11 +290,11 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
if (tag != dev->tag)
dev_err(&dev->sbd.core,
- "%s:%u: tag mismatch, got %lx, expected %lx\n",
+ "%s:%u: tag mismatch, got %llx, expected %llx\n",
__func__, __LINE__, tag, dev->tag);
if (res) {
- dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
+ dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
__func__, __LINE__, res, status);
return IRQ_HANDLED;
}
@@ -364,7 +364,7 @@ static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
if (dev->blk_size != CD_FRAMESIZE) {
dev_err(&dev->sbd.core,
- "%s:%u: cannot handle block size %lu\n", __func__,
+ "%s:%u: cannot handle block size %llu\n", __func__,
__LINE__, dev->blk_size);
return -EINVAL;
}
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 8cb9240596ab..df09820e8916 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -128,7 +128,7 @@
- Integrate ql12160_set_target_parameters() with 1280 version
- Make qla1280_setup() non static
- Do not call qla1280_check_for_dead_scsi_bus() on every I/O request
- sent to the card - this command pauses the firmare!!!
+ sent to the card - this command pauses the firmware!!!
Rev 3.23.15 Beta March 19, 2002, Jes Sorensen
- Clean up qla1280.h - remove obsolete QL_DEBUG_LEVEL_x definitions
- Remove a pile of pointless and confusing (srb_t **) and
@@ -659,7 +659,7 @@ static int qla1280_read_nvram(struct scsi_qla_host *ha)
/* The firmware interface is, um, interesting, in that the
* actual firmware image on the chip is little endian, thus,
* the process of taking that image to the CPU would end up
- * little endian. However, the firmare interface requires it
+ * little endian. However, the firmware interface requires it
* to be read a word (two bytes) at a time.
*
* The net result of this would be that the word (and
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index cd53627cc761..33a3c13fd893 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -303,7 +303,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
else if (start == (ha->flt_region_boot * 4) ||
start == (ha->flt_region_fw * 4))
valid = 1;
- else if (IS_QLA25XX(ha) &&
+ else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) &&
start == (ha->flt_region_vpd_nvram * 4))
valid = 1;
if (!valid) {
@@ -815,6 +815,21 @@ qla2x00_total_isp_aborts_show(struct device *dev,
ha->qla_stats.total_isp_aborts);
}
+static ssize_t
+qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA81XX(ha))
+ return snprintf(buf, PAGE_SIZE, "\n");
+
+ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x (%x)\n",
+ ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2],
+ ha->mpi_version[3], ha->mpi_capabilities);
+}
+
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@@ -839,6 +854,7 @@ static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
NULL);
static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
NULL);
+static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@@ -858,6 +874,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_optrom_fcode_version,
&dev_attr_optrom_fw_version,
&dev_attr_total_isp_aborts,
+ &dev_attr_mpi_version,
NULL,
};
@@ -892,6 +909,9 @@ qla2x00_get_host_speed(struct Scsi_Host *shost)
case PORT_SPEED_8GB:
speed = FC_PORTSPEED_8GBIT;
break;
+ case PORT_SPEED_10GB:
+ speed = FC_PORTSPEED_10GBIT;
+ break;
}
fc_host_speed(shost) = speed;
}
@@ -996,6 +1016,9 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
struct Scsi_Host *host = rport_to_shost(rport);
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+ if (!fcport)
+ return;
+
qla2x00_abort_fcport_cmds(fcport);
/*
@@ -1013,6 +1036,9 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
{
fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+ if (!fcport)
+ return;
+
/*
* At this point all fcport's software-states are cleared. Perform any
* final cleanup of firmware resources (PCBs and XCBs).
@@ -1382,7 +1408,9 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
fc_host_max_npiv_vports(vha->host) = ha->max_npiv_vports;
fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;
- if (IS_QLA25XX(ha))
+ if (IS_QLA81XX(ha))
+ speed = FC_PORTSPEED_10GBIT;
+ else if (IS_QLA25XX(ha))
speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
else if (IS_QLA24XX_TYPE(ha))
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 1cf77772623b..34760f8d4f17 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -310,6 +310,76 @@ qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
*buf++ = htons(RD_REG_WORD(dmp_reg++));
}
+static inline void *
+qla24xx_copy_eft(struct qla_hw_data *ha, void *ptr)
+{
+ if (!ha->eft)
+ return ptr;
+
+ memcpy(ptr, ha->eft, ntohl(ha->fw_dump->eft_size));
+ return ptr + ntohl(ha->fw_dump->eft_size);
+}
+
+static inline void *
+qla25xx_copy_fce(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+{
+ uint32_t cnt;
+ uint32_t *iter_reg;
+ struct qla2xxx_fce_chain *fcec = ptr;
+
+ if (!ha->fce)
+ return ptr;
+
+ *last_chain = &fcec->type;
+ fcec->type = __constant_htonl(DUMP_CHAIN_FCE);
+ fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) +
+ fce_calc_size(ha->fce_bufs));
+ fcec->size = htonl(fce_calc_size(ha->fce_bufs));
+ fcec->addr_l = htonl(LSD(ha->fce_dma));
+ fcec->addr_h = htonl(MSD(ha->fce_dma));
+
+ iter_reg = fcec->eregs;
+ for (cnt = 0; cnt < 8; cnt++)
+ *iter_reg++ = htonl(ha->fce_mb[cnt]);
+
+ memcpy(iter_reg, ha->fce, ntohl(fcec->size));
+
+ return iter_reg;
+}
+
+static inline void *
+qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
+{
+ uint32_t cnt, que_idx;
+ uint8_t req_cnt, rsp_cnt, que_cnt;
+ struct qla2xxx_mq_chain *mq = ptr;
+ struct device_reg_25xxmq __iomem *reg;
+
+ if (!ha->mqenable)
+ return ptr;
+
+ mq = ptr;
+ *last_chain = &mq->type;
+ mq->type = __constant_htonl(DUMP_CHAIN_MQ);
+ mq->chain_size = __constant_htonl(sizeof(struct qla2xxx_mq_chain));
+
+ req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues);
+ rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues);
+ que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt;
+ mq->count = htonl(que_cnt);
+ for (cnt = 0; cnt < que_cnt; cnt++) {
+ reg = (struct device_reg_25xxmq *) ((void *)
+ ha->mqiobase + cnt * QLA_QUE_PAGE);
+ que_idx = cnt * 4;
+ mq->qregs[que_idx] = htonl(RD_REG_DWORD(&reg->req_q_in));
+ mq->qregs[que_idx+1] = htonl(RD_REG_DWORD(&reg->req_q_out));
+ mq->qregs[que_idx+2] = htonl(RD_REG_DWORD(&reg->rsp_q_in));
+ mq->qregs[que_idx+3] = htonl(RD_REG_DWORD(&reg->rsp_q_out));
+ }
+
+ return ptr + sizeof(struct qla2xxx_mq_chain);
+}
+
/**
* qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
* @ha: HA context
@@ -913,8 +983,8 @@ qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
goto qla24xx_fw_dump_failed_0;
nxt = qla2xxx_copy_queues(ha, nxt);
- if (ha->eft)
- memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
+
+ qla24xx_copy_eft(ha, nxt);
qla24xx_fw_dump_failed_0:
if (rval != QLA_SUCCESS) {
@@ -942,19 +1012,14 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
uint32_t risc_address;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- struct device_reg_25xxmq __iomem *reg25;
uint32_t __iomem *dmp_reg;
uint32_t *iter_reg;
uint16_t __iomem *mbx_reg;
unsigned long flags;
struct qla25xx_fw_dump *fw;
uint32_t ext_mem_cnt;
- void *nxt;
- struct qla2xxx_fce_chain *fcec;
- struct qla2xxx_mq_chain *mq = NULL;
- uint32_t qreg_size;
- uint8_t req_cnt, rsp_cnt, que_cnt;
- uint32_t que_idx;
+ void *nxt, *nxt_chain;
+ uint32_t *last_chain = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
risc_address = ext_mem_cnt = 0;
@@ -1001,28 +1066,6 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
- /* Multi queue registers */
- if (ha->mqenable) {
- qreg_size = sizeof(struct qla2xxx_mq_chain);
- mq = kzalloc(qreg_size, GFP_KERNEL);
- if (!mq)
- goto qla25xx_fw_dump_failed_0;
- req_cnt = find_first_zero_bit(ha->req_qid_map, ha->max_queues);
- rsp_cnt = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues);
- que_cnt = req_cnt > rsp_cnt ? req_cnt : rsp_cnt;
- mq->count = htonl(que_cnt);
- mq->chain_size = htonl(qreg_size);
- mq->type = __constant_htonl(DUMP_CHAIN_MQ);
- for (cnt = 0; cnt < que_cnt; cnt++) {
- reg25 = (struct device_reg_25xxmq *) ((void *)
- ha->mqiobase + cnt * QLA_QUE_PAGE);
- que_idx = cnt * 4;
- mq->qregs[que_idx] = htonl(reg25->req_q_in);
- mq->qregs[que_idx+1] = htonl(reg25->req_q_out);
- mq->qregs[que_idx+2] = htonl(reg25->rsp_q_in);
- mq->qregs[que_idx+3] = htonl(reg25->rsp_q_out);
- }
- }
WRT_REG_DWORD(&reg->iobase_window, 0x00);
RD_REG_DWORD(&reg->iobase_window);
@@ -1240,6 +1283,10 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
+ /* Multi queue registers */
+ nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset,
+ &last_chain);
+
rval = qla24xx_soft_reset(ha);
if (rval != QLA_SUCCESS)
goto qla25xx_fw_dump_failed_0;
@@ -1249,39 +1296,341 @@ qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
if (rval != QLA_SUCCESS)
goto qla25xx_fw_dump_failed_0;
- /* Fibre Channel Trace Buffer. */
nxt = qla2xxx_copy_queues(ha, nxt);
- if (ha->eft)
- memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
- /* Fibre Channel Event Buffer. */
- if (!ha->fce)
- goto qla25xx_fw_dump_failed_0;
+ nxt = qla24xx_copy_eft(ha, nxt);
+
+ /* Chain entries -- started with MQ. */
+ qla25xx_copy_fce(ha, nxt_chain, &last_chain);
+ if (last_chain) {
+ ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
+ *last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
+ }
- ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
+qla25xx_fw_dump_failed_0:
+ if (rval != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Failed to dump firmware (%x)!!!\n", rval);
+ ha->fw_dumped = 0;
- if (ha->mqenable) {
- nxt = nxt + ntohl(ha->fw_dump->eft_size);
- memcpy(nxt, mq, qreg_size);
- kfree(mq);
- fcec = nxt + qreg_size;
} else {
- fcec = nxt + ntohl(ha->fw_dump->eft_size);
+ qla_printk(KERN_INFO, ha,
+ "Firmware dump saved to temp buffer (%ld/%p).\n",
+ base_vha->host_no, ha->fw_dump);
+ ha->fw_dumped = 1;
}
- fcec->type = __constant_htonl(DUMP_CHAIN_FCE | DUMP_CHAIN_LAST);
- fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) +
- fce_calc_size(ha->fce_bufs));
- fcec->size = htonl(fce_calc_size(ha->fce_bufs));
- fcec->addr_l = htonl(LSD(ha->fce_dma));
- fcec->addr_h = htonl(MSD(ha->fce_dma));
- iter_reg = fcec->eregs;
- for (cnt = 0; cnt < 8; cnt++)
- *iter_reg++ = htonl(ha->fce_mb[cnt]);
+qla25xx_fw_dump_failed:
+ if (!hardware_locked)
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
- memcpy(iter_reg, ha->fce, ntohl(fcec->size));
+void
+qla81xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
+{
+ int rval;
+ uint32_t cnt;
+ uint32_t risc_address;
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ uint32_t __iomem *dmp_reg;
+ uint32_t *iter_reg;
+ uint16_t __iomem *mbx_reg;
+ unsigned long flags;
+ struct qla81xx_fw_dump *fw;
+ uint32_t ext_mem_cnt;
+ void *nxt, *nxt_chain;
+ uint32_t *last_chain = NULL;
+ struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
-qla25xx_fw_dump_failed_0:
+ risc_address = ext_mem_cnt = 0;
+ flags = 0;
+
+ if (!hardware_locked)
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ if (!ha->fw_dump) {
+ qla_printk(KERN_WARNING, ha,
+ "No buffer available for dump!!!\n");
+ goto qla81xx_fw_dump_failed;
+ }
+
+ if (ha->fw_dumped) {
+ qla_printk(KERN_WARNING, ha,
+ "Firmware has been previously dumped (%p) -- ignoring "
+ "request...\n", ha->fw_dump);
+ goto qla81xx_fw_dump_failed;
+ }
+ fw = &ha->fw_dump->isp.isp81;
+ qla2xxx_prep_dump(ha, ha->fw_dump);
+
+ fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
+
+ /* Pause RISC. */
+ rval = qla24xx_pause_risc(reg);
+ if (rval != QLA_SUCCESS)
+ goto qla81xx_fw_dump_failed_0;
+
+ /* Host/Risc registers. */
+ iter_reg = fw->host_risc_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7010, 16, iter_reg);
+
+ /* PCIe registers. */
+ WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
+ RD_REG_DWORD(&reg->iobase_addr);
+ WRT_REG_DWORD(&reg->iobase_window, 0x01);
+ dmp_reg = &reg->iobase_c4;
+ fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
+ fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
+ fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
+ fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
+
+ WRT_REG_DWORD(&reg->iobase_window, 0x00);
+ RD_REG_DWORD(&reg->iobase_window);
+
+ /* Host interface registers. */
+ dmp_reg = &reg->flash_addr;
+ for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
+ fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
+
+ /* Disable interrupts. */
+ WRT_REG_DWORD(&reg->ictrl, 0);
+ RD_REG_DWORD(&reg->ictrl);
+
+ /* Shadow registers. */
+ WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
+ RD_REG_DWORD(&reg->iobase_addr);
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
+ fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
+ fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
+ fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
+ fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
+ fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
+ fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
+ fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
+ fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
+ fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
+ fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
+ fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
+
+ /* RISC I/O register. */
+ WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
+ fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
+
+ /* Mailbox registers. */
+ mbx_reg = &reg->mailbox0;
+ for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
+ fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
+
+ /* Transfer sequence registers. */
+ iter_reg = fw->xseq_gp_reg;
+ iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
+ qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
+
+ iter_reg = fw->xseq_0_reg;
+ iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
+ qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
+
+ qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
+
+ /* Receive sequence registers. */
+ iter_reg = fw->rseq_gp_reg;
+ iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
+ qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
+
+ iter_reg = fw->rseq_0_reg;
+ iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
+ qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
+
+ qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
+ qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
+
+ /* Auxiliary sequence registers. */
+ iter_reg = fw->aseq_gp_reg;
+ iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
+ qla24xx_read_window(reg, 0xB070, 16, iter_reg);
+
+ iter_reg = fw->aseq_0_reg;
+ iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
+ qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
+
+ qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
+ qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
+
+ /* Command DMA registers. */
+ qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
+
+ /* Queues. */
+ iter_reg = fw->req0_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
+ dmp_reg = &reg->iobase_q;
+ for (cnt = 0; cnt < 7; cnt++)
+ *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+ iter_reg = fw->resp0_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
+ dmp_reg = &reg->iobase_q;
+ for (cnt = 0; cnt < 7; cnt++)
+ *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+ iter_reg = fw->req1_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
+ dmp_reg = &reg->iobase_q;
+ for (cnt = 0; cnt < 7; cnt++)
+ *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
+
+ /* Transmit DMA registers. */
+ iter_reg = fw->xmt0_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7610, 16, iter_reg);
+
+ iter_reg = fw->xmt1_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7630, 16, iter_reg);
+
+ iter_reg = fw->xmt2_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7650, 16, iter_reg);
+
+ iter_reg = fw->xmt3_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7670, 16, iter_reg);
+
+ iter_reg = fw->xmt4_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7690, 16, iter_reg);
+
+ qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
+
+ /* Receive DMA registers. */
+ iter_reg = fw->rcvt0_data_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7710, 16, iter_reg);
+
+ iter_reg = fw->rcvt1_data_dma_reg;
+ iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
+ qla24xx_read_window(reg, 0x7730, 16, iter_reg);
+
+ /* RISC registers. */
+ iter_reg = fw->risc_gp_reg;
+ iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
+ qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
+
+ /* Local memory controller registers. */
+ iter_reg = fw->lmc_reg;
+ iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
+ qla24xx_read_window(reg, 0x3070, 16, iter_reg);
+
+ /* Fibre Protocol Module registers. */
+ iter_reg = fw->fpm_hdw_reg;
+ iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x40C0, 16, iter_reg);
+ qla24xx_read_window(reg, 0x40D0, 16, iter_reg);
+
+ /* Frame Buffer registers. */
+ iter_reg = fw->fb_hdw_reg;
+ iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
+ iter_reg = qla24xx_read_window(reg, 0x61C0, 16, iter_reg);
+ qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
+
+ /* Multi queue registers */
+ nxt_chain = qla25xx_copy_mq(ha, (void *)ha->fw_dump + ha->chain_offset,
+ &last_chain);
+
+ rval = qla24xx_soft_reset(ha);
+ if (rval != QLA_SUCCESS)
+ goto qla81xx_fw_dump_failed_0;
+
+ rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
+ &nxt);
+ if (rval != QLA_SUCCESS)
+ goto qla81xx_fw_dump_failed_0;
+
+ nxt = qla2xxx_copy_queues(ha, nxt);
+
+ nxt = qla24xx_copy_eft(ha, nxt);
+
+ /* Chain entries -- started with MQ. */
+ qla25xx_copy_fce(ha, nxt_chain, &last_chain);
+ if (last_chain) {
+ ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
+ *last_chain |= __constant_htonl(DUMP_CHAIN_LAST);
+ }
+
+qla81xx_fw_dump_failed_0:
if (rval != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Failed to dump firmware (%x)!!!\n", rval);
@@ -1294,10 +1643,11 @@ qla25xx_fw_dump_failed_0:
ha->fw_dumped = 1;
}
-qla25xx_fw_dump_failed:
+qla81xx_fw_dump_failed:
if (!hardware_locked)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
+
/****************************************************************************/
/* Driver Debug Functions. */
/****************************************************************************/
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index c1794a70a45f..f660dd70b72e 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -251,6 +251,45 @@ struct qla25xx_fw_dump {
uint32_t ext_mem[1];
};
+struct qla81xx_fw_dump {
+ uint32_t host_status;
+ uint32_t host_risc_reg[32];
+ uint32_t pcie_regs[4];
+ uint32_t host_reg[32];
+ uint32_t shadow_reg[11];
+ uint32_t risc_io_reg;
+ uint16_t mailbox_reg[32];
+ uint32_t xseq_gp_reg[128];
+ uint32_t xseq_0_reg[48];
+ uint32_t xseq_1_reg[16];
+ uint32_t rseq_gp_reg[128];
+ uint32_t rseq_0_reg[32];
+ uint32_t rseq_1_reg[16];
+ uint32_t rseq_2_reg[16];
+ uint32_t aseq_gp_reg[128];
+ uint32_t aseq_0_reg[32];
+ uint32_t aseq_1_reg[16];
+ uint32_t aseq_2_reg[16];
+ uint32_t cmd_dma_reg[16];
+ uint32_t req0_dma_reg[15];
+ uint32_t resp0_dma_reg[15];
+ uint32_t req1_dma_reg[15];
+ uint32_t xmt0_dma_reg[32];
+ uint32_t xmt1_dma_reg[32];
+ uint32_t xmt2_dma_reg[32];
+ uint32_t xmt3_dma_reg[32];
+ uint32_t xmt4_dma_reg[32];
+ uint32_t xmt_data_dma_reg[16];
+ uint32_t rcvt0_data_dma_reg[32];
+ uint32_t rcvt1_data_dma_reg[32];
+ uint32_t risc_gp_reg[128];
+ uint32_t lmc_reg[128];
+ uint32_t fpm_hdw_reg[224];
+ uint32_t fb_hdw_reg[208];
+ uint32_t code_ram[0x2000];
+ uint32_t ext_mem[1];
+};
+
#define EFT_NUM_BUFFERS 4
#define EFT_BYTES_PER_BUFFER 0x4000
#define EFT_SIZE ((EFT_BYTES_PER_BUFFER) * (EFT_NUM_BUFFERS))
@@ -313,5 +352,6 @@ struct qla2xxx_fw_dump {
struct qla2300_fw_dump isp23;
struct qla24xx_fw_dump isp24;
struct qla25xx_fw_dump isp25;
+ struct qla81xx_fw_dump isp81;
} isp;
};
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a29c95204975..023ee77fb027 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -187,7 +187,6 @@ struct req_que;
* SCSI Request Block
*/
typedef struct srb {
- struct scsi_qla_host *vha; /* HA the SP is queued on */
struct req_que *que;
struct fc_port *fcport;
@@ -2136,7 +2135,6 @@ struct qla_msix_entry {
/* Work events. */
enum qla_work_type {
QLA_EVT_AEN,
- QLA_EVT_HWE_LOG,
};
@@ -2151,10 +2149,6 @@ struct qla_work_evt {
enum fc_host_event_code code;
u32 data;
} aen;
- struct {
- uint16_t code;
- uint16_t d1, d2, d3;
- } hwe;
} u;
};
@@ -2309,6 +2303,7 @@ struct qla_hw_data {
#define PORT_SPEED_2GB 0x01
#define PORT_SPEED_4GB 0x03
#define PORT_SPEED_8GB 0x04
+#define PORT_SPEED_10GB 0x13
uint16_t link_data_rate; /* F/W operating speed */
uint8_t current_topology;
@@ -2328,6 +2323,7 @@ struct qla_hw_data {
#define PCI_DEVICE_ID_QLOGIC_ISP2532 0x2532
#define PCI_DEVICE_ID_QLOGIC_ISP8432 0x8432
+#define PCI_DEVICE_ID_QLOGIC_ISP8001 0x8001
uint32_t device_type;
#define DT_ISP2100 BIT_0
#define DT_ISP2200 BIT_1
@@ -2342,7 +2338,8 @@ struct qla_hw_data {
#define DT_ISP5432 BIT_10
#define DT_ISP2532 BIT_11
#define DT_ISP8432 BIT_12
-#define DT_ISP_LAST (DT_ISP8432 << 1)
+#define DT_ISP8001 BIT_13
+#define DT_ISP_LAST (DT_ISP8001 << 1)
#define DT_IIDMA BIT_26
#define DT_FWI2 BIT_27
@@ -2364,6 +2361,7 @@ struct qla_hw_data {
#define IS_QLA5432(ha) (DT_MASK(ha) & DT_ISP5432)
#define IS_QLA2532(ha) (DT_MASK(ha) & DT_ISP2532)
#define IS_QLA8432(ha) (DT_MASK(ha) & DT_ISP8432)
+#define IS_QLA8001(ha) (DT_MASK(ha) & DT_ISP8001)
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha))
@@ -2373,8 +2371,11 @@ struct qla_hw_data {
#define IS_QLA84XX(ha) (IS_QLA8432(ha))
#define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
IS_QLA84XX(ha))
+#define IS_QLA81XX(ha) (IS_QLA8001(ha))
#define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \
- IS_QLA25XX(ha))
+ IS_QLA25XX(ha) || IS_QLA81XX(ha))
+#define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
+ (ha)->flags.msix_enabled)
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
@@ -2472,6 +2473,9 @@ struct qla_hw_data {
uint8_t fw_seriallink_options[4];
uint16_t fw_seriallink_options24[4];
+ uint8_t mpi_version[4];
+ uint32_t mpi_capabilities;
+
/* Firmware dump information. */
struct qla2xxx_fw_dump *fw_dump;
uint32_t fw_dump_len;
@@ -2480,6 +2484,7 @@ struct qla_hw_data {
dma_addr_t eft_dma;
void *eft;
+ uint32_t chain_offset;
struct dentry *dfs_dir;
struct dentry *dfs_fce;
dma_addr_t fce_dma;
@@ -2489,10 +2494,6 @@ struct qla_hw_data {
uint64_t fce_wr, fce_rd;
struct mutex fce_mutex;
- uint32_t hw_event_start;
- uint32_t hw_event_ptr;
- uint32_t hw_event_pause_errors;
-
uint32_t pci_attr;
uint16_t chip_revision;
@@ -2522,6 +2523,12 @@ struct qla_hw_data {
uint8_t fcode_revision[16];
uint32_t fw_revision[4];
+ /* Offsets for flash/nvram access (set to ~0 if not used). */
+ uint32_t flash_conf_off;
+ uint32_t flash_data_off;
+ uint32_t nvram_conf_off;
+ uint32_t nvram_data_off;
+
uint32_t fdt_wrt_disable;
uint32_t fdt_erase_cmd;
uint32_t fdt_block_size;
@@ -2533,7 +2540,6 @@ struct qla_hw_data {
uint32_t flt_region_boot;
uint32_t flt_region_fw;
uint32_t flt_region_vpd_nvram;
- uint32_t flt_region_hw_event;
uint32_t flt_region_npiv_conf;
/* Needed for BEACON */
@@ -2737,6 +2743,7 @@ typedef struct scsi_qla_host {
#define OPTROM_SIZE_2322 0x100000
#define OPTROM_SIZE_24XX 0x100000
#define OPTROM_SIZE_25XX 0x200000
+#define OPTROM_SIZE_81XX 0x400000
#include "qla_gbl.h"
#include "qla_dbg.h"
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index 0e366a1b44b3..c66036da7d2b 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -113,7 +113,8 @@ int
qla2x00_dfs_setup(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA25XX(ha))
+
+ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))
goto out;
if (!ha->fce)
goto out;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index ee1f1e794c2d..7abb045a0410 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1215,9 +1215,10 @@ struct qla_fdt_layout {
struct qla_flt_location {
uint8_t sig[4];
- uint32_t start_lo;
- uint32_t start_hi;
- uint16_t unused;
+ uint16_t start_lo;
+ uint16_t start_hi;
+ uint8_t version;
+ uint8_t unused[5];
uint16_t checksum;
};
@@ -1390,4 +1391,291 @@ struct access_chip_rsp_84xx {
uint32_t reserved[12];
};
+
+/* 81XX Support **************************************************************/
+
+#define MBA_DCBX_START 0x8016
+#define MBA_DCBX_COMPLETE 0x8030
+#define MBA_FCF_CONF_ERR 0x8031
+#define MBA_DCBX_PARAM_UPDATE 0x8032
+#define MBA_IDC_COMPLETE 0x8100
+#define MBA_IDC_NOTIFY 0x8101
+#define MBA_IDC_TIME_EXT 0x8102
+
+struct nvram_81xx {
+ /* NVRAM header. */
+ uint8_t id[4];
+ uint16_t nvram_version;
+ uint16_t reserved_0;
+
+ /* Firmware Initialization Control Block. */
+ uint16_t version;
+ uint16_t reserved_1;
+ uint16_t frame_payload_size;
+ uint16_t execution_throttle;
+ uint16_t exchange_count;
+ uint16_t reserved_2;
+
+ uint8_t port_name[WWN_SIZE];
+ uint8_t node_name[WWN_SIZE];
+
+ uint16_t login_retry_count;
+ uint16_t reserved_3;
+ uint16_t interrupt_delay_timer;
+ uint16_t login_timeout;
+
+ uint32_t firmware_options_1;
+ uint32_t firmware_options_2;
+ uint32_t firmware_options_3;
+
+ uint16_t reserved_4[4];
+
+ /* Offset 64. */
+ uint8_t enode_mac[6];
+ uint16_t reserved_5[5];
+
+ /* Offset 80. */
+ uint16_t reserved_6[24];
+
+ /* Offset 128. */
+ uint16_t reserved_7[64];
+
+ /*
+ * BIT 0 = Enable spinup delay
+ * BIT 1 = Disable BIOS
+ * BIT 2 = Enable Memory Map BIOS
+ * BIT 3 = Enable Selectable Boot
+ * BIT 4 = Disable RISC code load
+ * BIT 5 = Disable Serdes
+ * BIT 6 = Opt boot mode
+ * BIT 7 = Interrupt enable
+ *
+ * BIT 8 = EV Control enable
+ * BIT 9 = Enable lip reset
+ * BIT 10 = Enable lip full login
+ * BIT 11 = Enable target reset
+ * BIT 12 = Stop firmware
+ * BIT 13 = Enable nodename option
+ * BIT 14 = Default WWPN valid
+ * BIT 15 = Enable alternate WWN
+ *
+ * BIT 16 = CLP LUN string
+ * BIT 17 = CLP Target string
+ * BIT 18 = CLP BIOS enable string
+ * BIT 19 = CLP Serdes string
+ * BIT 20 = CLP WWPN string
+ * BIT 21 = CLP WWNN string
+ * BIT 22 =
+ * BIT 23 =
+ * BIT 24 = Keep WWPN
+ * BIT 25 = Temp WWPN
+ * BIT 26-31 =
+ */
+ uint32_t host_p;
+
+ uint8_t alternate_port_name[WWN_SIZE];
+ uint8_t alternate_node_name[WWN_SIZE];
+
+ uint8_t boot_port_name[WWN_SIZE];
+ uint16_t boot_lun_number;
+ uint16_t reserved_8;
+
+ uint8_t alt1_boot_port_name[WWN_SIZE];
+ uint16_t alt1_boot_lun_number;
+ uint16_t reserved_9;
+
+ uint8_t alt2_boot_port_name[WWN_SIZE];
+ uint16_t alt2_boot_lun_number;
+ uint16_t reserved_10;
+
+ uint8_t alt3_boot_port_name[WWN_SIZE];
+ uint16_t alt3_boot_lun_number;
+ uint16_t reserved_11;
+
+ /*
+ * BIT 0 = Selective Login
+ * BIT 1 = Alt-Boot Enable
+ * BIT 2 = Reserved
+ * BIT 3 = Boot Order List
+ * BIT 4 = Reserved
+ * BIT 5 = Selective LUN
+ * BIT 6 = Reserved
+ * BIT 7-31 =
+ */
+ uint32_t efi_parameters;
+
+ uint8_t reset_delay;
+ uint8_t reserved_12;
+ uint16_t reserved_13;
+
+ uint16_t boot_id_number;
+ uint16_t reserved_14;
+
+ uint16_t max_luns_per_target;
+ uint16_t reserved_15;
+
+ uint16_t port_down_retry_count;
+ uint16_t link_down_timeout;
+
+ /* FCode parameters. */
+ uint16_t fcode_parameter;
+
+ uint16_t reserved_16[3];
+
+ /* Offset 352. */
+ uint8_t reserved_17[4];
+ uint16_t reserved_18[5];
+ uint8_t reserved_19[2];
+ uint16_t reserved_20[8];
+
+ /* Offset 384. */
+ uint8_t reserved_21[16];
+ uint16_t reserved_22[8];
+
+ /* Offset 416. */
+ uint16_t reserved_23[32];
+
+ /* Offset 480. */
+ uint8_t model_name[16];
+
+ /* Offset 496. */
+ uint16_t feature_mask_l;
+ uint16_t feature_mask_h;
+ uint16_t reserved_24[2];
+
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_device_id;
+
+ uint32_t checksum;
+};
+
+/*
+ * ISP Initialization Control Block.
+ * Little endian except where noted.
+ */
+#define ICB_VERSION 1
+struct init_cb_81xx {
+ uint16_t version;
+ uint16_t reserved_1;
+
+ uint16_t frame_payload_size;
+ uint16_t execution_throttle;
+ uint16_t exchange_count;
+
+ uint16_t reserved_2;
+
+ uint8_t port_name[WWN_SIZE]; /* Big endian. */
+ uint8_t node_name[WWN_SIZE]; /* Big endian. */
+
+ uint16_t response_q_inpointer;
+ uint16_t request_q_outpointer;
+
+ uint16_t login_retry_count;
+
+ uint16_t prio_request_q_outpointer;
+
+ uint16_t response_q_length;
+ uint16_t request_q_length;
+
+ uint16_t reserved_3;
+
+ uint16_t prio_request_q_length;
+
+ uint32_t request_q_address[2];
+ uint32_t response_q_address[2];
+ uint32_t prio_request_q_address[2];
+
+ uint8_t reserved_4[8];
+
+ uint16_t atio_q_inpointer;
+ uint16_t atio_q_length;
+ uint32_t atio_q_address[2];
+
+ uint16_t interrupt_delay_timer; /* 100us increments. */
+ uint16_t login_timeout;
+
+ /*
+ * BIT 0-3 = Reserved
+ * BIT 4 = Enable Target Mode
+ * BIT 5 = Disable Initiator Mode
+ * BIT 6 = Reserved
+ * BIT 7 = Reserved
+ *
+ * BIT 8-13 = Reserved
+ * BIT 14 = Node Name Option
+ * BIT 15-31 = Reserved
+ */
+ uint32_t firmware_options_1;
+
+ /*
+ * BIT 0 = Operation Mode bit 0
+ * BIT 1 = Operation Mode bit 1
+ * BIT 2 = Operation Mode bit 2
+ * BIT 3 = Operation Mode bit 3
+ * BIT 4-7 = Reserved
+ *
+ * BIT 8 = Enable Class 2
+ * BIT 9 = Enable ACK0
+ * BIT 10 = Reserved
+ * BIT 11 = Enable FC-SP Security
+ * BIT 12 = FC Tape Enable
+ * BIT 13 = Reserved
+ * BIT 14 = Enable Target PRLI Control
+ * BIT 15-31 = Reserved
+ */
+ uint32_t firmware_options_2;
+
+ /*
+ * BIT 0-3 = Reserved
+ * BIT 4 = FCP RSP Payload bit 0
+ * BIT 5 = FCP RSP Payload bit 1
+ * BIT 6 = Enable Receive Out-of-Order data frame handling
+ * BIT 7 = Reserved
+ *
+ * BIT 8 = Reserved
+ * BIT 9 = Enable Out-of-Order FCP_XFER_RDY relative offset handling
+ * BIT 10-16 = Reserved
+ * BIT 17 = Enable multiple FCFs
+ * BIT 18-20 = MAC addressing mode
+ * BIT 21-25 = Ethernet data rate
+ * BIT 26 = Enable ethernet header rx IOCB for ATIO q
+ * BIT 27 = Enable ethernet header rx IOCB for response q
+ * BIT 28 = SPMA selection bit 0
+ * BIT 28 = SPMA selection bit 1
+ * BIT 30-31 = Reserved
+ */
+ uint32_t firmware_options_3;
+
+ uint8_t reserved_5[8];
+
+ uint8_t enode_mac[6];
+
+ uint8_t reserved_6[10];
+};
+
+struct mid_init_cb_81xx {
+ struct init_cb_81xx init_cb;
+
+ uint16_t count;
+ uint16_t options;
+
+ struct mid_conf_entry_24xx entries[MAX_MULTI_ID_FABRIC];
+};
+
+#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000
+#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000
+
+/* 81XX Flash locations -- occupies second 2MB region. */
+#define FA_BOOT_CODE_ADDR_81 0x80000
+#define FA_RISC_CODE_ADDR_81 0xA0000
+#define FA_FW_AREA_ADDR_81 0xC0000
+#define FA_VPD_NVRAM_ADDR_81 0xD0000
+#define FA_FEATURE_ADDR_81 0xD4000
+#define FA_FLASH_DESCR_ADDR_81 0xD8000
+#define FA_FLASH_LAYOUT_ADDR_81 0xD8400
+#define FA_HW_EVENT0_ADDR_81 0xDC000
+#define FA_HW_EVENT1_ADDR_81 0xDC400
+#define FA_NPIV_CONF0_ADDR_81 0xD1000
+#define FA_NPIV_CONF1_ADDR_81 0xD2000
+
#endif
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 0011e31205db..a336b4bc81a7 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -28,10 +28,13 @@ extern void qla2x00_reset_adapter(struct scsi_qla_host *);
extern void qla24xx_reset_adapter(struct scsi_qla_host *);
extern int qla2x00_nvram_config(struct scsi_qla_host *);
extern int qla24xx_nvram_config(struct scsi_qla_host *);
+extern int qla81xx_nvram_config(struct scsi_qla_host *);
extern void qla2x00_update_fw_options(struct scsi_qla_host *);
extern void qla24xx_update_fw_options(scsi_qla_host_t *);
+extern void qla81xx_update_fw_options(scsi_qla_host_t *);
extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
+extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *);
extern int qla2x00_loop_resync(scsi_qla_host_t *);
@@ -69,8 +72,6 @@ extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
fc_host_event_code, u32);
-extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
- uint16_t, uint16_t);
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
@@ -143,7 +144,7 @@ qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
extern void
qla2x00_get_fw_version(scsi_qla_host_t *, uint16_t *,
- uint16_t *, uint16_t *, uint16_t *, uint32_t *);
+ uint16_t *, uint16_t *, uint16_t *, uint32_t *, uint8_t *, uint32_t *);
extern int
qla2x00_get_fw_options(scsi_qla_host_t *, uint16_t *);
@@ -317,9 +318,6 @@ extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *);
-extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
- uint16_t, uint16_t);
-
extern int qla2xxx_get_flash_info(scsi_qla_host_t *);
extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
@@ -332,6 +330,7 @@ extern void qla2100_fw_dump(scsi_qla_host_t *, int);
extern void qla2300_fw_dump(scsi_qla_host_t *, int);
extern void qla24xx_fw_dump(scsi_qla_host_t *, int);
extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
+extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
extern void qla2x00_dump_regs(scsi_qla_host_t *);
extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 0a6f72973996..557f58d5bf88 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1535,7 +1535,10 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
eiter = (struct ct_fdmi_port_attr *) (entries + size);
eiter->type = __constant_cpu_to_be16(FDMI_PORT_SUPPORT_SPEED);
eiter->len = __constant_cpu_to_be16(4 + 4);
- if (IS_QLA25XX(ha))
+ if (IS_QLA81XX(ha))
+ eiter->a.sup_speed = __constant_cpu_to_be32(
+ FDMI_PORT_SPEED_10GB);
+ else if (IS_QLA25XX(ha))
eiter->a.sup_speed = __constant_cpu_to_be32(
FDMI_PORT_SPEED_1GB|FDMI_PORT_SPEED_2GB|
FDMI_PORT_SPEED_4GB|FDMI_PORT_SPEED_8GB);
@@ -1575,6 +1578,10 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
eiter->a.cur_speed =
__constant_cpu_to_be32(FDMI_PORT_SPEED_8GB);
break;
+ case PORT_SPEED_10GB:
+ eiter->a.cur_speed =
+ __constant_cpu_to_be32(FDMI_PORT_SPEED_10GB);
+ break;
default:
eiter->a.cur_speed =
__constant_cpu_to_be32(FDMI_PORT_SPEED_UNKNOWN);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 52ed56ecf195..f6368a1d3021 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -552,10 +552,6 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
d2 = RD_REG_DWORD(&reg->ctrl_status);
barrier();
}
- if (cnt == 0 || hw_evt)
- qla2xxx_hw_event_log(vha, HW_EVENT_RESET_ERR,
- RD_REG_WORD(&reg->mailbox1), RD_REG_WORD(&reg->mailbox2),
- RD_REG_WORD(&reg->mailbox3));
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET);
RD_REG_DWORD(&reg->hccr);
@@ -574,6 +570,9 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ if (IS_NOPOLLING_TYPE(ha))
+ ha->isp_ops->enable_intrs(ha);
}
/**
@@ -779,16 +778,19 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
mem_size = (ha->fw_memory_size - 0x11000 + 1) *
sizeof(uint16_t);
} else if (IS_FWI2_CAPABLE(ha)) {
- fixed_size = IS_QLA25XX(ha) ?
- offsetof(struct qla25xx_fw_dump, ext_mem) :
- offsetof(struct qla24xx_fw_dump, ext_mem);
+ if (IS_QLA81XX(ha))
+ fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
+ else if (IS_QLA25XX(ha))
+ fixed_size = offsetof(struct qla25xx_fw_dump, ext_mem);
+ else
+ fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem);
mem_size = (ha->fw_memory_size - 0x100000 + 1) *
sizeof(uint32_t);
if (ha->mqenable)
mq_size = sizeof(struct qla2xxx_mq_chain);
/* Allocate memory for Fibre Channel Event Buffer. */
- if (!IS_QLA25XX(ha))
+ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))
goto try_eft;
tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
@@ -851,7 +853,9 @@ cont_alloc:
dump_size = offsetof(struct qla2xxx_fw_dump, isp);
dump_size += fixed_size + mem_size + req_q_size + rsp_q_size +
- mq_size + eft_size + fce_size;
+ eft_size;
+ ha->chain_offset = dump_size;
+ dump_size += mq_size + fce_size;
ha->fw_dump = vmalloc(dump_size);
if (!ha->fw_dump) {
@@ -987,7 +991,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
&ha->fw_major_version,
&ha->fw_minor_version,
&ha->fw_subminor_version,
- &ha->fw_attributes, &ha->fw_memory_size);
+ &ha->fw_attributes, &ha->fw_memory_size,
+ ha->mpi_version, &ha->mpi_capabilities);
ha->flags.npiv_supported = 0;
if (IS_QLA2XXX_MIDTYPE(ha) &&
(ha->fw_attributes & BIT_2)) {
@@ -1253,35 +1258,48 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
{
int rval;
unsigned long flags = 0;
- int cnt;
+ int cnt, que;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
- struct rsp_que *rsp = ha->rsp_q_map[0];
+ struct req_que *req;
+ struct rsp_que *rsp;
+ struct scsi_qla_host *vp;
struct mid_init_cb_24xx *mid_init_cb =
(struct mid_init_cb_24xx *) ha->init_cb;
spin_lock_irqsave(&ha->hardware_lock, flags);
/* Clear outstanding commands array. */
- for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
- req->outstanding_cmds[cnt] = NULL;
+ for (que = 0; que < ha->max_queues; que++) {
+ req = ha->req_q_map[que];
+ if (!req)
+ continue;
+ for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
+ req->outstanding_cmds[cnt] = NULL;
- req->current_outstanding_cmd = 0;
+ req->current_outstanding_cmd = 0;
- /* Clear RSCN queue. */
- vha->rscn_in_ptr = 0;
- vha->rscn_out_ptr = 0;
+ /* Initialize firmware. */
+ req->ring_ptr = req->ring;
+ req->ring_index = 0;
+ req->cnt = req->length;
+ }
- /* Initialize firmware. */
- req->ring_ptr = req->ring;
- req->ring_index = 0;
- req->cnt = req->length;
- rsp->ring_ptr = rsp->ring;
- rsp->ring_index = 0;
+ for (que = 0; que < ha->max_queues; que++) {
+ rsp = ha->rsp_q_map[que];
+ if (!rsp)
+ continue;
+ rsp->ring_ptr = rsp->ring;
+ rsp->ring_index = 0;
- /* Initialize response queue entries */
- qla2x00_init_response_q_entries(rsp);
+ /* Initialize response queue entries */
+ qla2x00_init_response_q_entries(rsp);
+ }
+ /* Clear RSCN queue. */
+ list_for_each_entry(vp, &ha->vp_list, list) {
+ vp->rscn_in_ptr = 0;
+ vp->rscn_out_ptr = 0;
+ }
ha->isp_ops->config_rings(vha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1665,10 +1683,6 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
"invalid -- WWPN) defaults.\n");
- if (chksum)
- qla2xxx_hw_event_log(vha, HW_EVENT_NVRAM_CHKSUM_ERR, 0,
- MSW(chksum), LSW(chksum));
-
/*
* Set default initialization control block.
*/
@@ -3211,8 +3225,8 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
int rval = QLA_SUCCESS;
uint32_t wait_time;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
- struct rsp_que *rsp = ha->rsp_q_map[0];
+ struct req_que *req = ha->req_q_map[vha->req_ques[0]];
+ struct rsp_que *rsp = req->rsp;
atomic_set(&vha->loop_state, LOOP_UPDATE);
clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
@@ -3491,6 +3505,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
}
req = ha->req_q_map[i];
if (req) {
+ /* Clear outstanding commands array. */
req->options &= ~BIT_0;
ret = qla25xx_init_req_que(base_vha, req, req->options);
if (ret != QLA_SUCCESS)
@@ -3499,7 +3514,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
req->id));
else
DEBUG2_17(printk(KERN_WARNING
- "%s Rsp que:%d inited\n", __func__,
+ "%s Req que:%d inited\n", __func__,
req->id));
}
}
@@ -3547,6 +3562,9 @@ qla24xx_reset_adapter(scsi_qla_host_t *vha)
WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
RD_REG_DWORD(&reg->hccr);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ if (IS_NOPOLLING_TYPE(ha))
+ ha->isp_ops->enable_intrs(ha);
}
/* On sparc systems, obtain port and node WWN from firmware
@@ -3832,6 +3850,10 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr)
uint32_t i;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
+
+ qla_printk(KERN_INFO, ha,
+ "FW: Loading from flash (%x)...\n", ha->flt_region_fw);
+
rval = QLA_SUCCESS;
segments = FA_RISC_CODE_SEGMENTS;
@@ -4007,8 +4029,8 @@ fail_fw_integrity:
return QLA_FUNCTION_FAILED;
}
-int
-qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
+static int
+qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
int segments, fragment;
@@ -4028,12 +4050,12 @@ qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
"from: " QLA_FW_URL ".\n");
- /* Try to load RISC code from flash. */
- qla_printk(KERN_ERR, ha, "Attempting to load (potentially "
- "outdated) firmware from flash.\n");
- return qla24xx_load_risc_flash(vha, srisc_addr);
+ return QLA_FUNCTION_FAILED;
}
+ qla_printk(KERN_INFO, ha,
+ "FW: Loading via request-firmware...\n");
+
rval = QLA_SUCCESS;
segments = FA_RISC_CODE_SEGMENTS;
@@ -4118,6 +4140,40 @@ fail_fw_integrity:
return QLA_FUNCTION_FAILED;
}
+int
+qla24xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
+{
+ int rval;
+
+ /*
+ * FW Load priority:
+ * 1) Firmware via request-firmware interface (.bin file).
+ * 2) Firmware residing in flash.
+ */
+ rval = qla24xx_load_risc_blob(vha, srisc_addr);
+ if (rval == QLA_SUCCESS)
+ return rval;
+
+ return qla24xx_load_risc_flash(vha, srisc_addr);
+}
+
+int
+qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
+{
+ int rval;
+
+ /*
+ * FW Load priority:
+ * 1) Firmware residing in flash.
+ * 2) Firmware via request-firmware interface (.bin file).
+ */
+ rval = qla24xx_load_risc_flash(vha, srisc_addr);
+ if (rval == QLA_SUCCESS)
+ return rval;
+
+ return qla24xx_load_risc_blob(vha, srisc_addr);
+}
+
void
qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha)
{
@@ -4150,8 +4206,8 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- struct req_que *req = ha->req_q_map[0];
- struct rsp_que *rsp = ha->rsp_q_map[0];
+ struct req_que *req = ha->req_q_map[vha->req_ques[0]];
+ struct rsp_que *rsp = req->rsp;
if (!vha->vp_idx)
return -EINVAL;
@@ -4255,3 +4311,269 @@ qla84xx_init_chip(scsi_qla_host_t *vha)
return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
QLA_SUCCESS;
}
+
+/* 81XX Support **************************************************************/
+
+int
+qla81xx_nvram_config(scsi_qla_host_t *vha)
+{
+ int rval;
+ struct init_cb_81xx *icb;
+ struct nvram_81xx *nv;
+ uint32_t *dptr;
+ uint8_t *dptr1, *dptr2;
+ uint32_t chksum;
+ uint16_t cnt;
+ struct qla_hw_data *ha = vha->hw;
+
+ rval = QLA_SUCCESS;
+ icb = (struct init_cb_81xx *)ha->init_cb;
+ nv = ha->nvram;
+
+ /* Determine NVRAM starting address. */
+ ha->nvram_size = sizeof(struct nvram_81xx);
+ ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
+ ha->vpd_size = FA_NVRAM_VPD_SIZE;
+ ha->vpd_base = FA_NVRAM_VPD0_ADDR;
+ if (PCI_FUNC(ha->pdev->devfn) & 1) {
+ ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
+ ha->vpd_base = FA_NVRAM_VPD1_ADDR;
+ }
+
+ /* Get VPD data into cache */
+ ha->vpd = ha->nvram + VPD_OFFSET;
+ ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd,
+ ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
+
+ /* Get NVRAM data into cache and calculate checksum. */
+ dptr = (uint32_t *)nv;
+ ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
+ ha->nvram_size);
+ for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
+ chksum += le32_to_cpu(*dptr++);
+
+ DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no));
+ DEBUG5(qla2x00_dump_buffer((uint8_t *)nv, ha->nvram_size));
+
+ /* Bad NVRAM data, set defaults parameters. */
+ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
+ || nv->id[3] != ' ' ||
+ nv->nvram_version < __constant_cpu_to_le16(ICB_VERSION)) {
+ /* Reset NVRAM data. */
+ qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: "
+ "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0],
+ le16_to_cpu(nv->nvram_version));
+ qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet "
+ "invalid -- WWPN) defaults.\n");
+
+ /*
+ * Set default initialization control block.
+ */
+ memset(nv, 0, ha->nvram_size);
+ nv->nvram_version = __constant_cpu_to_le16(ICB_VERSION);
+ nv->version = __constant_cpu_to_le16(ICB_VERSION);
+ nv->frame_payload_size = __constant_cpu_to_le16(2048);
+ nv->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+ nv->exchange_count = __constant_cpu_to_le16(0);
+ nv->port_name[0] = 0x21;
+ nv->port_name[1] = 0x00 + PCI_FUNC(ha->pdev->devfn);
+ nv->port_name[2] = 0x00;
+ nv->port_name[3] = 0xe0;
+ nv->port_name[4] = 0x8b;
+ nv->port_name[5] = 0x1c;
+ nv->port_name[6] = 0x55;
+ nv->port_name[7] = 0x86;
+ nv->node_name[0] = 0x20;
+ nv->node_name[1] = 0x00;
+ nv->node_name[2] = 0x00;
+ nv->node_name[3] = 0xe0;
+ nv->node_name[4] = 0x8b;
+ nv->node_name[5] = 0x1c;
+ nv->node_name[6] = 0x55;
+ nv->node_name[7] = 0x86;
+ nv->login_retry_count = __constant_cpu_to_le16(8);
+ nv->interrupt_delay_timer = __constant_cpu_to_le16(0);
+ nv->login_timeout = __constant_cpu_to_le16(0);
+ nv->firmware_options_1 =
+ __constant_cpu_to_le32(BIT_14|BIT_13|BIT_2|BIT_1);
+ nv->firmware_options_2 = __constant_cpu_to_le32(2 << 4);
+ nv->firmware_options_2 |= __constant_cpu_to_le32(BIT_12);
+ nv->firmware_options_3 = __constant_cpu_to_le32(2 << 13);
+ nv->host_p = __constant_cpu_to_le32(BIT_11|BIT_10);
+ nv->efi_parameters = __constant_cpu_to_le32(0);
+ nv->reset_delay = 5;
+ nv->max_luns_per_target = __constant_cpu_to_le16(128);
+ nv->port_down_retry_count = __constant_cpu_to_le16(30);
+ nv->link_down_timeout = __constant_cpu_to_le16(30);
+ nv->enode_mac[0] = 0x01;
+ nv->enode_mac[1] = 0x02;
+ nv->enode_mac[2] = 0x03;
+ nv->enode_mac[3] = 0x04;
+ nv->enode_mac[4] = 0x05;
+ nv->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn);
+
+ rval = 1;
+ }
+
+ /* Reset Initialization control block */
+ memset(icb, 0, sizeof(struct init_cb_81xx));
+
+ /* Copy 1st segment. */
+ dptr1 = (uint8_t *)icb;
+ dptr2 = (uint8_t *)&nv->version;
+ cnt = (uint8_t *)&icb->response_q_inpointer - (uint8_t *)&icb->version;
+ while (cnt--)
+ *dptr1++ = *dptr2++;
+
+ icb->login_retry_count = nv->login_retry_count;
+
+ /* Copy 2nd segment. */
+ dptr1 = (uint8_t *)&icb->interrupt_delay_timer;
+ dptr2 = (uint8_t *)&nv->interrupt_delay_timer;
+ cnt = (uint8_t *)&icb->reserved_5 -
+ (uint8_t *)&icb->interrupt_delay_timer;
+ while (cnt--)
+ *dptr1++ = *dptr2++;
+
+ memcpy(icb->enode_mac, nv->enode_mac, sizeof(icb->enode_mac));
+ /* Some boards (with valid NVRAMs) still have NULL enode_mac!! */
+ if (!memcmp(icb->enode_mac, "\0\0\0\0\0\0", sizeof(icb->enode_mac))) {
+ icb->enode_mac[0] = 0x01;
+ icb->enode_mac[1] = 0x02;
+ icb->enode_mac[2] = 0x03;
+ icb->enode_mac[3] = 0x04;
+ icb->enode_mac[4] = 0x05;
+ icb->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn);
+ }
+
+ /*
+ * Setup driver NVRAM options.
+ */
+ qla2x00_set_model_info(vha, nv->model_name, sizeof(nv->model_name),
+ "QLE81XX");
+
+ /* Use alternate WWN? */
+ if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
+ memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
+ memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
+ }
+
+ /* Prepare nodename */
+ if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) {
+ /*
+ * Firmware will apply the following mask if the nodename was
+ * not provided.
+ */
+ memcpy(icb->node_name, icb->port_name, WWN_SIZE);
+ icb->node_name[0] &= 0xF0;
+ }
+
+ /* Set host adapter parameters. */
+ ha->flags.disable_risc_code_load = 0;
+ ha->flags.enable_lip_reset = 0;
+ ha->flags.enable_lip_full_login =
+ le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
+ ha->flags.enable_target_reset =
+ le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
+ ha->flags.enable_led_scheme = 0;
+ ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
+
+ ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
+ (BIT_6 | BIT_5 | BIT_4)) >> 4;
+
+ /* save HBA serial number */
+ ha->serial0 = icb->port_name[5];
+ ha->serial1 = icb->port_name[6];
+ ha->serial2 = icb->port_name[7];
+ memcpy(vha->node_name, icb->node_name, WWN_SIZE);
+ memcpy(vha->port_name, icb->port_name, WWN_SIZE);
+
+ icb->execution_throttle = __constant_cpu_to_le16(0xFFFF);
+
+ ha->retry_count = le16_to_cpu(nv->login_retry_count);
+
+ /* Set minimum login_timeout to 4 seconds. */
+ if (le16_to_cpu(nv->login_timeout) < ql2xlogintimeout)
+ nv->login_timeout = cpu_to_le16(ql2xlogintimeout);
+ if (le16_to_cpu(nv->login_timeout) < 4)
+ nv->login_timeout = __constant_cpu_to_le16(4);
+ ha->login_timeout = le16_to_cpu(nv->login_timeout);
+ icb->login_timeout = nv->login_timeout;
+
+ /* Set minimum RATOV to 100 tenths of a second. */
+ ha->r_a_tov = 100;
+
+ ha->loop_reset_delay = nv->reset_delay;
+
+ /* Link Down Timeout = 0:
+ *
+ * When Port Down timer expires we will start returning
+ * I/O's to OS with "DID_NO_CONNECT".
+ *
+ * Link Down Timeout != 0:
+ *
+ * The driver waits for the link to come up after link down
+ * before returning I/Os to OS with "DID_NO_CONNECT".
+ */
+ if (le16_to_cpu(nv->link_down_timeout) == 0) {
+ ha->loop_down_abort_time =
+ (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
+ } else {
+ ha->link_down_timeout = le16_to_cpu(nv->link_down_timeout);
+ ha->loop_down_abort_time =
+ (LOOP_DOWN_TIME - ha->link_down_timeout);
+ }
+
+ /* Need enough time to try and get the port back. */
+ ha->port_down_retry_count = le16_to_cpu(nv->port_down_retry_count);
+ if (qlport_down_retry)
+ ha->port_down_retry_count = qlport_down_retry;
+
+ /* Set login_retry_count */
+ ha->login_retry_count = le16_to_cpu(nv->login_retry_count);
+ if (ha->port_down_retry_count ==
+ le16_to_cpu(nv->port_down_retry_count) &&
+ ha->port_down_retry_count > 3)
+ ha->login_retry_count = ha->port_down_retry_count;
+ else if (ha->port_down_retry_count > (int)ha->login_retry_count)
+ ha->login_retry_count = ha->port_down_retry_count;
+ if (ql2xloginretrycount)
+ ha->login_retry_count = ql2xloginretrycount;
+
+ /* Enable ZIO. */
+ if (!vha->flags.init_done) {
+ ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
+ (BIT_3 | BIT_2 | BIT_1 | BIT_0);
+ ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
+ le16_to_cpu(icb->interrupt_delay_timer): 2;
+ }
+ icb->firmware_options_2 &= __constant_cpu_to_le32(
+ ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
+ vha->flags.process_response_queue = 0;
+ if (ha->zio_mode != QLA_ZIO_DISABLED) {
+ ha->zio_mode = QLA_ZIO_MODE_6;
+
+ DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
+ "(%d us).\n", vha->host_no, ha->zio_mode,
+ ha->zio_timer * 100));
+ qla_printk(KERN_INFO, ha,
+ "ZIO mode %d enabled; timer delay (%d us).\n",
+ ha->zio_mode, ha->zio_timer * 100);
+
+ icb->firmware_options_2 |= cpu_to_le32(
+ (uint32_t)ha->zio_mode);
+ icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
+ vha->flags.process_response_queue = 1;
+ }
+
+ if (rval) {
+ DEBUG2_3(printk(KERN_WARNING
+ "scsi(%ld): NVRAM configuration failed!\n", vha->host_no));
+ }
+ return (rval);
+}
+
+void
+qla81xx_update_fw_options(scsi_qla_host_t *ha)
+{
+}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 5bedc9d05942..2258152b1f41 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -173,7 +173,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
return;
}
- vha = sp->vha;
+ vha = sp->fcport->vha;
req = sp->que;
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
@@ -234,7 +234,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
return;
}
- vha = sp->vha;
+ vha = sp->fcport->vha;
req = sp->que;
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
@@ -294,7 +294,7 @@ qla2x00_start_scsi(srb_t *sp)
/* Setup device pointers. */
ret = 0;
- vha = sp->vha;
+ vha = sp->fcport->vha;
ha = vha->hw;
reg = &ha->iobase->isp;
cmd = sp->cmd;
@@ -353,7 +353,6 @@ qla2x00_start_scsi(srb_t *sp)
/* Build command packet */
req->current_outstanding_cmd = handle;
req->outstanding_cmds[handle] = sp;
- sp->vha = vha;
sp->que = req;
sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
req->cnt -= req_cnt;
@@ -656,7 +655,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
return;
}
- vha = sp->vha;
+ vha = sp->fcport->vha;
req = sp->que;
/* Set transfer direction */
@@ -723,7 +722,7 @@ qla24xx_start_scsi(srb_t *sp)
struct req_que *req = NULL;
struct rsp_que *rsp = NULL;
struct scsi_cmnd *cmd = sp->cmd;
- struct scsi_qla_host *vha = sp->vha;
+ struct scsi_qla_host *vha = sp->fcport->vha;
struct qla_hw_data *ha = vha->hw;
uint16_t que_id;
@@ -791,7 +790,6 @@ qla24xx_start_scsi(srb_t *sp)
/* Build command packet. */
req->current_outstanding_cmd = handle;
req->outstanding_cmds[handle] = sp;
- sp->vha = vha;
sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
req->cnt -= req_cnt;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index d5fb79a88001..e28ad81baf1e 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -275,7 +275,7 @@ void
qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
{
#define LS_UNKNOWN 2
- static char *link_speeds[5] = { "1", "2", "?", "4", "8" };
+ static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" };
char *link_speed;
uint16_t handle_cnt;
uint16_t cnt;
@@ -288,6 +288,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
/* Setup to process RIO completion. */
handle_cnt = 0;
+ if (IS_QLA81XX(ha))
+ goto skip_rio;
switch (mb[0]) {
case MBA_SCSI_COMPLETION:
handles[0] = le32_to_cpu((uint32_t)((mb[2] << 16) | mb[1]));
@@ -339,7 +341,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
default:
break;
}
-
+skip_rio:
switch (mb[0]) {
case MBA_SCSI_COMPLETION: /* Fast Post */
if (!vha->flags.online)
@@ -362,7 +364,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
"ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
mb[1], mb[2], mb[3]);
- qla2x00_post_hwe_work(vha, mb[0], mb[1], mb[2], mb[3]);
ha->isp_ops->fw_dump(vha, 1);
if (IS_FWI2_CAPABLE(ha)) {
@@ -387,7 +388,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
vha->host_no));
qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");
- qla2x00_post_hwe_work(vha, mb[0], mb[1], mb[2], mb[3]);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
@@ -396,7 +396,6 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
vha->host_no));
qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
- qla2x00_post_hwe_work(vha, mb[0], mb[1], mb[2], mb[3]);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
@@ -436,6 +435,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
link_speed = link_speeds[LS_UNKNOWN];
if (mb[1] < 5)
link_speed = link_speeds[mb[1]];
+ else if (mb[1] == 0x13)
+ link_speed = link_speeds[5];
ha->link_data_rate = mb[1];
}
@@ -495,12 +496,17 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
qla2x00_post_aen_work(vha, FCH_EVT_LIPRESET, mb[1]);
break;
+ /* case MBA_DCBX_COMPLETE: */
case MBA_POINT_TO_POINT: /* Point-to-Point */
if (IS_QLA2100(ha))
break;
- DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE received.\n",
- vha->host_no));
+ if (IS_QLA81XX(ha))
+ DEBUG2(printk("scsi(%ld): DCBX Completed -- %04x %04x "
+ "%04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+ else
+ DEBUG2(printk("scsi(%ld): Asynchronous P2P MODE "
+ "received.\n", vha->host_no));
/*
* Until there's a transition from loop down to loop up, treat
@@ -641,10 +647,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
/* case MBA_RIO_RESPONSE: */
case MBA_ZIO_RESPONSE:
- DEBUG2(printk("scsi(%ld): [R|Z]IO update completion.\n",
- vha->host_no));
- DEBUG(printk(KERN_INFO
- "scsi(%ld): [R|Z]IO update completion.\n",
+ DEBUG3(printk("scsi(%ld): [R|Z]IO update completion.\n",
vha->host_no));
if (IS_FWI2_CAPABLE(ha))
@@ -698,6 +701,35 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
}
spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
break;
+ case MBA_DCBX_START:
+ DEBUG2(printk("scsi(%ld): DCBX Started -- %04x %04x %04x\n",
+ vha->host_no, mb[1], mb[2], mb[3]));
+ break;
+ case MBA_DCBX_PARAM_UPDATE:
+ DEBUG2(printk("scsi(%ld): DCBX Parameters Updated -- "
+ "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+ break;
+ case MBA_FCF_CONF_ERR:
+ DEBUG2(printk("scsi(%ld): FCF Configuration Error -- "
+ "%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
+ break;
+ case MBA_IDC_COMPLETE:
+ DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
+ "Complete -- %04x %04x %04x\n", vha->host_no, mb[1], mb[2],
+ mb[3]));
+ break;
+ case MBA_IDC_NOTIFY:
+ DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
+ "Request Notification -- %04x %04x %04x\n", vha->host_no,
+ mb[1], mb[2], mb[3]));
+ /**** Mailbox registers 4 - 7 valid!!! */
+ break;
+ case MBA_IDC_TIME_EXT:
+ DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
+ "Time Extension -- %04x %04x %04x\n", vha->host_no, mb[1],
+ mb[2], mb[3]));
+ /**** Mailbox registers 4 - 7 valid!!! */
+ break;
}
if (!vha->vp_idx && ha->num_vhosts)
@@ -1510,7 +1542,7 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- if (!IS_QLA25XX(ha))
+ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))
return;
rval = QLA_SUCCESS;
@@ -1590,12 +1622,6 @@ qla24xx_intr_handler(int irq, void *dev_id)
if (pci_channel_offline(ha->pdev))
break;
- if (ha->hw_event_pause_errors == 0)
- qla2x00_post_hwe_work(vha, HW_EVENT_PARITY_ERR,
- 0, MSW(stat), LSW(stat));
- else if (ha->hw_event_pause_errors < 0xffffffff)
- ha->hw_event_pause_errors++;
-
hccr = RD_REG_DWORD(&reg->hccr);
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
@@ -1740,12 +1766,6 @@ qla24xx_msix_default(int irq, void *dev_id)
if (pci_channel_offline(ha->pdev))
break;
- if (ha->hw_event_pause_errors == 0)
- qla2x00_post_hwe_work(vha, HW_EVENT_PARITY_ERR,
- 0, MSW(stat), LSW(stat));
- else if (ha->hw_event_pause_errors < 0xffffffff)
- ha->hw_event_pause_errors++;
-
hccr = RD_REG_DWORD(&reg->hccr);
qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
@@ -1848,6 +1868,7 @@ qla24xx_disable_msix(struct qla_hw_data *ha)
static int
qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
{
+#define MIN_MSIX_COUNT 2
int i, ret;
struct msix_entry *entries;
struct qla_msix_entry *qentry;
@@ -1863,12 +1884,16 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
ret = pci_enable_msix(ha->pdev, entries, ha->msix_count);
if (ret) {
+ if (ret < MIN_MSIX_COUNT)
+ goto msix_failed;
+
qla_printk(KERN_WARNING, ha,
"MSI-X: Failed to enable support -- %d/%d\n"
" Retry with %d vectors\n", ha->msix_count, ret, ret);
ha->msix_count = ret;
ret = pci_enable_msix(ha->pdev, entries, ha->msix_count);
if (ret) {
+msix_failed:
qla_printk(KERN_WARNING, ha, "MSI-X: Failed to enable"
" support, giving up -- %d/%d\n",
ha->msix_count, ret);
@@ -1944,7 +1969,8 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
device_reg_t __iomem *reg = ha->iobase;
/* If possible, enable MSI-X. */
- if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
+ if (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
+ !IS_QLA8432(ha) && !IS_QLA8001(ha))
goto skip_msix;
if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX ||
@@ -1979,7 +2005,8 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
"MSI-X: Falling back-to INTa mode -- %d.\n", ret);
skip_msix:
- if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
+ if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
+ !IS_QLA8001(ha))
goto skip_msi;
ret = pci_enable_msi(ha->pdev);
@@ -2000,6 +2027,12 @@ skip_msi:
ha->flags.inta_enabled = 1;
clear_risc_ints:
+ /*
+ * FIXME: Noted that 8014s were being dropped during NK testing.
+ * Timing deltas during MSI-X/INTa transitions?
+ */
+ if (IS_QLA81XX(ha))
+ goto fail;
spin_lock_irq(&ha->hardware_lock);
if (IS_FWI2_CAPABLE(ha)) {
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
@@ -2044,7 +2077,7 @@ qla2x00_get_rsp_host(struct rsp_que *rsp)
if (pkt && pkt->handle < MAX_OUTSTANDING_COMMANDS) {
sp = req->outstanding_cmds[pkt->handle];
if (sp)
- vha = sp->vha;
+ vha = sp->fcport->vha;
}
}
if (!vha)
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index a99976f5fabd..f94ffbb98e95 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -58,14 +58,11 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
* seconds. This is to serialize actual issuing of mailbox cmds during
* non ISP abort time.
*/
- if (!abort_active) {
- if (!wait_for_completion_timeout(&ha->mbx_cmd_comp,
- mcp->tov * HZ)) {
- /* Timeout occurred. Return error. */
- DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
- "Exiting.\n", __func__, base_vha->host_no));
- return QLA_FUNCTION_TIMEOUT;
- }
+ if (!wait_for_completion_timeout(&ha->mbx_cmd_comp, mcp->tov * HZ)) {
+ /* Timeout occurred. Return error. */
+ DEBUG2_3_11(printk("%s(%ld): cmd access timeout. "
+ "Exiting.\n", __func__, base_vha->host_no));
+ return QLA_FUNCTION_TIMEOUT;
}
ha->flags.mbox_busy = 1;
@@ -123,8 +120,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
/* Wait for mbx cmd completion until timeout */
- if (!abort_active && io_lock_on) {
-
+ if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
if (IS_FWI2_CAPABLE(ha))
@@ -218,7 +214,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
/* Clean up */
ha->mcp = NULL;
- if (abort_active || !io_lock_on) {
+ if ((abort_active || !io_lock_on) && !IS_NOPOLLING_TYPE(ha)) {
DEBUG11(printk("%s(%ld): checking for additional resp "
"interrupt.\n", __func__, base_vha->host_no));
@@ -266,8 +262,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
}
/* Allow next mbx cmd to come in. */
- if (!abort_active)
- complete(&ha->mbx_cmd_comp);
+ complete(&ha->mbx_cmd_comp);
if (rval) {
DEBUG2_3_11(printk("%s(%ld): **** FAILED. mbx0=%x, mbx1=%x, "
@@ -412,7 +407,8 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
*/
void
qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
- uint16_t *subminor, uint16_t *attributes, uint32_t *memory)
+ uint16_t *subminor, uint16_t *attributes, uint32_t *memory, uint8_t *mpi,
+ uint32_t *mpi_caps)
{
int rval;
mbx_cmd_t mc;
@@ -423,6 +419,8 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
mcp->mb[0] = MBC_GET_FIRMWARE_VERSION;
mcp->out_mb = MBX_0;
mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ if (IS_QLA81XX(vha->hw))
+ mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
mcp->flags = 0;
mcp->tov = MBX_TOV_SECONDS;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -436,6 +434,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
*memory = 0x1FFFF; /* Defaults to 128KB. */
else
*memory = (mcp->mb[5] << 16) | mcp->mb[4];
+ if (IS_QLA81XX(vha->hw)) {
+ mpi[0] = mcp->mb[10] >> 8;
+ mpi[1] = mcp->mb[10] & 0xff;
+ mpi[2] = mcp->mb[11] >> 8;
+ mpi[3] = mcp->mb[11] & 0xff;
+ *mpi_caps = (mcp->mb[12] << 16) | mcp->mb[13];
+ }
if (rval != QLA_SUCCESS) {
/*EMPTY*/
@@ -568,7 +573,6 @@ int
qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
{
int rval;
- struct qla_hw_data *ha = vha->hw;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
@@ -595,14 +599,6 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
if (mcp->mb[5] != 0xA5A5 || mcp->mb[6] != 0x5A5A ||
mcp->mb[7] != 0x2525)
rval = QLA_FUNCTION_FAILED;
- if (rval == QLA_FUNCTION_FAILED) {
- struct device_reg_24xx __iomem *reg =
- &ha->iobase->isp24;
-
- qla2xxx_hw_event_log(vha, HW_EVENT_ISP_ERR, 0,
- LSW(RD_REG_DWORD(&reg->hccr)),
- LSW(RD_REG_DWORD(&reg->istatus)));
- }
}
if (rval != QLA_SUCCESS) {
@@ -1363,7 +1359,13 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
- if (IS_FWI2_CAPABLE(vha->hw)) {
+ if (IS_QLA81XX(vha->hw)) {
+ /* Logout across all FCFs. */
+ mcp->mb[0] = MBC_LIP_FULL_LOGIN;
+ mcp->mb[1] = BIT_1;
+ mcp->mb[2] = 0;
+ mcp->out_mb = MBX_2|MBX_1|MBX_0;
+ } else if (IS_FWI2_CAPABLE(vha->hw)) {
mcp->mb[0] = MBC_LIP_FULL_LOGIN;
mcp->mb[1] = BIT_6;
mcp->mb[2] = 0;
@@ -1853,6 +1855,9 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
+ if (IS_QLA81XX(vha->hw))
+ return QLA_SUCCESS;
+
DEBUG11(printk("qla2x00_full_login_lip(%ld): entered.\n",
vha->host_no));
@@ -2512,7 +2517,7 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- if (!IS_QLA25XX(vha->hw))
+ if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw))
return QLA_FUNCTION_FAILED;
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
@@ -3155,7 +3160,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
mcp->mb[7] = LSW(MSD(rsp->dma));
mcp->mb[5] = rsp->length;
mcp->mb[11] = rsp->vp_idx;
- mcp->mb[14] = rsp->msix->vector;
+ mcp->mb[14] = rsp->msix->entry;
mcp->mb[13] = rsp->rid;
reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) +
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 386ffeae5b5a..f53179c46423 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -614,8 +614,10 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->vp_idx = vp_idx;
req->qos = qos;
- if (ha->rsp_q_map[rsp_que])
+ if (ha->rsp_q_map[rsp_que]) {
req->rsp = ha->rsp_q_map[rsp_que];
+ req->rsp->req = req;
+ }
/* Use alternate PCI bus number */
if (MSB(req->rid))
options |= BIT_4;
@@ -627,6 +629,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->ring_index = 0;
req->cnt = req->length;
req->id = que_id;
+ req->max_q_depth = ha->req_q_map[0]->max_q_depth;
mutex_unlock(&ha->vport_lock);
ret = qla25xx_init_req_que(base_vha, req, options);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 8ea927788b3f..c11f872d3e10 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -65,8 +65,6 @@ MODULE_PARM_DESC(ql2xextended_error_logging,
static void qla2x00_free_device(scsi_qla_host_t *);
-static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
-
int ql2xfdmienable=1;
module_param(ql2xfdmienable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xfdmienable,
@@ -404,26 +402,9 @@ static char *
qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
{
struct qla_hw_data *ha = vha->hw;
- sprintf(str, "%d.%02d.%02d ", ha->fw_major_version,
- ha->fw_minor_version,
- ha->fw_subminor_version);
- if (ha->fw_attributes & BIT_0)
- strcat(str, "[Class 2] ");
- if (ha->fw_attributes & BIT_1)
- strcat(str, "[IP] ");
- if (ha->fw_attributes & BIT_2)
- strcat(str, "[Multi-ID] ");
- if (ha->fw_attributes & BIT_3)
- strcat(str, "[SB-2] ");
- if (ha->fw_attributes & BIT_4)
- strcat(str, "[T10 CRC] ");
- if (ha->fw_attributes & BIT_5)
- strcat(str, "[VI] ");
- if (ha->fw_attributes & BIT_10)
- strcat(str, "[84XX] ");
- if (ha->fw_attributes & BIT_13)
- strcat(str, "[Experimental]");
+ sprintf(str, "%d.%02d.%02d (%x)", ha->fw_major_version,
+ ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes);
return str;
}
@@ -438,7 +419,6 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
if (!sp)
return sp;
- sp->vha = vha;
sp->fcport = fcport;
sp->cmd = cmd;
sp->que = ha->req_q_map[0];
@@ -818,6 +798,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
if (ha->isp_ops->abort_command(vha, sp, req)) {
DEBUG2(printk("%s(%ld): abort_command "
"mbx failed.\n", __func__, vha->host_no));
+ ret = FAILED;
} else {
DEBUG3(printk("%s(%ld): abort_command "
"mbx success.\n", __func__, vha->host_no));
@@ -1176,13 +1157,13 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
struct req_que *req;
spin_lock_irqsave(&ha->hardware_lock, flags);
- for (que = 0; que < QLA_MAX_HOST_QUES; que++) {
- req = ha->req_q_map[vha->req_ques[que]];
+ for (que = 0; que < ha->max_queues; que++) {
+ req = ha->req_q_map[que];
if (!req)
continue;
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = req->outstanding_cmds[cnt];
- if (sp && sp->vha == vha) {
+ if (sp && sp->fcport->vha == vha) {
req->outstanding_cmds[cnt] = NULL;
sp->cmd->result = res;
qla2x00_sp_compl(ha, sp);
@@ -1211,7 +1192,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
scsi_qla_host_t *vha = shost_priv(sdev->host);
struct qla_hw_data *ha = vha->hw;
struct fc_rport *rport = starget_to_rport(sdev->sdev_target);
- struct req_que *req = ha->req_q_map[0];
+ struct req_que *req = ha->req_q_map[vha->req_ques[0]];
if (sdev->tagged_supported)
scsi_activate_tcq(sdev, req->max_q_depth);
@@ -1259,9 +1240,8 @@ qla2x00_change_queue_type(struct scsi_device *sdev, int tag_type)
* supported addressing method.
*/
static void
-qla2x00_config_dma_addressing(scsi_qla_host_t *vha)
+qla2x00_config_dma_addressing(struct qla_hw_data *ha)
{
- struct qla_hw_data *ha = vha->hw;
/* Assume a 32bit DMA mask. */
ha->flags.enable_64bit_addressing = 0;
@@ -1329,6 +1309,8 @@ qla24xx_disable_intrs(struct qla_hw_data *ha)
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ if (IS_NOPOLLING_TYPE(ha))
+ return;
spin_lock_irqsave(&ha->hardware_lock, flags);
ha->interrupts_on = 0;
WRT_REG_DWORD(&reg->ictrl, 0);
@@ -1488,6 +1470,44 @@ static struct isp_operations qla25xx_isp_ops = {
.rd_req_reg = qla24xx_rd_req_reg,
};
+static struct isp_operations qla81xx_isp_ops = {
+ .pci_config = qla25xx_pci_config,
+ .reset_chip = qla24xx_reset_chip,
+ .chip_diag = qla24xx_chip_diag,
+ .config_rings = qla24xx_config_rings,
+ .reset_adapter = qla24xx_reset_adapter,
+ .nvram_config = qla81xx_nvram_config,
+ .update_fw_options = qla81xx_update_fw_options,
+ .load_risc = qla81xx_load_risc,
+ .pci_info_str = qla24xx_pci_info_str,
+ .fw_version_str = qla24xx_fw_version_str,
+ .intr_handler = qla24xx_intr_handler,
+ .enable_intrs = qla24xx_enable_intrs,
+ .disable_intrs = qla24xx_disable_intrs,
+ .abort_command = qla24xx_abort_command,
+ .target_reset = qla24xx_abort_target,
+ .lun_reset = qla24xx_lun_reset,
+ .fabric_login = qla24xx_login_fabric,
+ .fabric_logout = qla24xx_fabric_logout,
+ .calc_req_entries = NULL,
+ .build_iocbs = NULL,
+ .prep_ms_iocb = qla24xx_prep_ms_iocb,
+ .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb,
+ .read_nvram = qla25xx_read_nvram_data,
+ .write_nvram = qla25xx_write_nvram_data,
+ .fw_dump = qla81xx_fw_dump,
+ .beacon_on = qla24xx_beacon_on,
+ .beacon_off = qla24xx_beacon_off,
+ .beacon_blink = qla24xx_beacon_blink,
+ .read_optrom = qla25xx_read_optrom_data,
+ .write_optrom = qla24xx_write_optrom_data,
+ .get_flash_version = qla24xx_get_flash_version,
+ .start_scsi = qla24xx_start_scsi,
+ .wrt_req_reg = qla24xx_wrt_req_reg,
+ .wrt_rsp_reg = qla24xx_wrt_rsp_reg,
+ .rd_req_reg = qla24xx_rd_req_reg,
+};
+
static inline void
qla2x00_set_isp_flags(struct qla_hw_data *ha)
{
@@ -1567,6 +1587,13 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->device_type |= DT_IIDMA;
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
+ case PCI_DEVICE_ID_QLOGIC_ISP8001:
+ ha->device_type |= DT_ISP8001;
+ ha->device_type |= DT_ZIO_SUPPORTED;
+ ha->device_type |= DT_FWI2;
+ ha->device_type |= DT_IIDMA;
+ ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+ break;
}
}
@@ -1629,7 +1656,7 @@ skip_pio:
/* Determine queue resources */
ha->max_queues = 1;
- if (ql2xmaxqueues <= 1 || !IS_QLA25XX(ha))
+ if (ql2xmaxqueues <= 1 || (!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
goto mqiobase_exit;
ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3),
pci_resource_len(ha->pdev, 3));
@@ -1706,7 +1733,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 ||
- pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532) {
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001) {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
sht = &qla24xx_driver_template;
mem_only = 1;
@@ -1760,6 +1788,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
rsp_length = RESPONSE_ENTRY_CNT_2100;
ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
ha->gid_list_info_size = 4;
+ ha->flash_conf_off = ~0;
+ ha->flash_data_off = ~0;
+ ha->nvram_conf_off = ~0;
+ ha->nvram_data_off = ~0;
ha->isp_ops = &qla2100_isp_ops;
} else if (IS_QLA2200(ha)) {
ha->mbx_count = MAILBOX_REGISTER_COUNT;
@@ -1767,6 +1799,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
rsp_length = RESPONSE_ENTRY_CNT_2100;
ha->max_loop_id = SNS_LAST_LOOP_ID_2100;
ha->gid_list_info_size = 4;
+ ha->flash_conf_off = ~0;
+ ha->flash_data_off = ~0;
+ ha->nvram_conf_off = ~0;
+ ha->nvram_data_off = ~0;
ha->isp_ops = &qla2100_isp_ops;
} else if (IS_QLA23XX(ha)) {
ha->mbx_count = MAILBOX_REGISTER_COUNT;
@@ -1776,6 +1812,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->gid_list_info_size = 6;
if (IS_QLA2322(ha) || IS_QLA6322(ha))
ha->optrom_size = OPTROM_SIZE_2322;
+ ha->flash_conf_off = ~0;
+ ha->flash_data_off = ~0;
+ ha->nvram_conf_off = ~0;
+ ha->nvram_data_off = ~0;
ha->isp_ops = &qla2300_isp_ops;
} else if (IS_QLA24XX_TYPE(ha)) {
ha->mbx_count = MAILBOX_REGISTER_COUNT;
@@ -1787,6 +1827,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->optrom_size = OPTROM_SIZE_24XX;
ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA24XX;
ha->isp_ops = &qla24xx_isp_ops;
+ ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
+ ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
+ ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
+ ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
} else if (IS_QLA25XX(ha)) {
ha->mbx_count = MAILBOX_REGISTER_COUNT;
req_length = REQUEST_ENTRY_CNT_24XX;
@@ -1797,6 +1841,23 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->optrom_size = OPTROM_SIZE_25XX;
ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
ha->isp_ops = &qla25xx_isp_ops;
+ ha->flash_conf_off = FARX_ACCESS_FLASH_CONF;
+ ha->flash_data_off = FARX_ACCESS_FLASH_DATA;
+ ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
+ ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
+ } else if (IS_QLA81XX(ha)) {
+ ha->mbx_count = MAILBOX_REGISTER_COUNT;
+ req_length = REQUEST_ENTRY_CNT_24XX;
+ rsp_length = RESPONSE_ENTRY_CNT_2300;
+ ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
+ ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
+ ha->gid_list_info_size = 8;
+ ha->optrom_size = OPTROM_SIZE_81XX;
+ ha->isp_ops = &qla81xx_isp_ops;
+ ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_81XX;
+ ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;
+ ha->nvram_conf_off = ~0;
+ ha->nvram_data_off = ~0;
}
mutex_init(&ha->vport_lock);
@@ -1806,6 +1867,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
set_bit(0, (unsigned long *) ha->vp_idx_map);
+ qla2x00_config_dma_addressing(ha);
ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp);
if (!ret) {
qla_printk(KERN_WARNING, ha,
@@ -1825,13 +1887,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
"[ERROR] Failed to allocate memory for scsi_host\n");
ret = -ENOMEM;
+ qla2x00_mem_free(ha);
+ qla2x00_free_que(ha, req, rsp);
goto probe_hw_failed;
}
pci_set_drvdata(pdev, base_vha);
- qla2x00_config_dma_addressing(base_vha);
-
host = base_vha->host;
base_vha->req_ques[0] = req->id;
host->can_queue = req->length + 128;
@@ -1854,14 +1916,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Set up the irqs */
ret = qla2x00_request_irqs(ha, rsp);
if (ret)
- goto probe_failed;
-
+ goto probe_init_failed;
/* Alloc arrays of request and response ring ptrs */
if (!qla2x00_alloc_queues(ha)) {
qla_printk(KERN_WARNING, ha,
"[ERROR] Failed to allocate memory for queue"
" pointers\n");
- goto probe_failed;
+ goto probe_init_failed;
}
ha->rsp_q_map[0] = rsp;
ha->req_q_map[0] = req;
@@ -1934,8 +1995,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
-probe_failed:
+probe_init_failed:
qla2x00_free_que(ha, req, rsp);
+ ha->max_queues = 0;
+
+probe_failed:
qla2x00_free_device(base_vha);
scsi_host_put(base_vha->host);
@@ -2458,23 +2522,6 @@ qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
return qla2x00_post_work(vha, e, 1);
}
-int
-qla2x00_post_hwe_work(struct scsi_qla_host *vha, uint16_t code, uint16_t d1,
- uint16_t d2, uint16_t d3)
-{
- struct qla_work_evt *e;
-
- e = qla2x00_alloc_work(vha, QLA_EVT_HWE_LOG, 1);
- if (!e)
- return QLA_FUNCTION_FAILED;
-
- e->u.hwe.code = code;
- e->u.hwe.d1 = d1;
- e->u.hwe.d2 = d2;
- e->u.hwe.d3 = d3;
- return qla2x00_post_work(vha, e, 1);
-}
-
static void
qla2x00_do_work(struct scsi_qla_host *vha)
{
@@ -2492,10 +2539,6 @@ qla2x00_do_work(struct scsi_qla_host *vha)
fc_host_post_event(vha->host, fc_get_event_number(),
e->u.aen.code, e->u.aen.data);
break;
- case QLA_EVT_HWE_LOG:
- qla2xxx_hw_event_log(vha, e->u.hwe.code, e->u.hwe.d1,
- e->u.hwe.d2, e->u.hwe.d3);
- break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
@@ -2914,13 +2957,14 @@ qla2x00_timer(scsi_qla_host_t *vha)
/* Firmware interface routines. */
-#define FW_BLOBS 6
+#define FW_BLOBS 7
#define FW_ISP21XX 0
#define FW_ISP22XX 1
#define FW_ISP2300 2
#define FW_ISP2322 3
#define FW_ISP24XX 4
#define FW_ISP25XX 5
+#define FW_ISP81XX 6
#define FW_FILE_ISP21XX "ql2100_fw.bin"
#define FW_FILE_ISP22XX "ql2200_fw.bin"
@@ -2928,6 +2972,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
#define FW_FILE_ISP2322 "ql2322_fw.bin"
#define FW_FILE_ISP24XX "ql2400_fw.bin"
#define FW_FILE_ISP25XX "ql2500_fw.bin"
+#define FW_FILE_ISP81XX "ql8100_fw.bin"
static DEFINE_MUTEX(qla_fw_lock);
@@ -2938,6 +2983,7 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
{ .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
{ .name = FW_FILE_ISP24XX, },
{ .name = FW_FILE_ISP25XX, },
+ { .name = FW_FILE_ISP81XX, },
};
struct fw_blob *
@@ -2959,6 +3005,8 @@ qla2x00_request_firmware(scsi_qla_host_t *vha)
blob = &qla_fw_blobs[FW_ISP24XX];
} else if (IS_QLA25XX(ha)) {
blob = &qla_fw_blobs[FW_ISP25XX];
+ } else if (IS_QLA81XX(ha)) {
+ blob = &qla_fw_blobs[FW_ISP81XX];
}
mutex_lock(&qla_fw_lock);
@@ -3112,6 +3160,7 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) },
{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
@@ -3200,3 +3249,4 @@ MODULE_FIRMWARE(FW_FILE_ISP2300);
MODULE_FIRMWARE(FW_FILE_ISP2322);
MODULE_FIRMWARE(FW_FILE_ISP24XX);
MODULE_FIRMWARE(FW_FILE_ISP25XX);
+MODULE_FIRMWARE(FW_FILE_ISP81XX);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index c538ee1b1a31..9c3b694c049d 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -425,27 +425,27 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4)
static inline uint32_t
-flash_conf_to_access_addr(uint32_t faddr)
+flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr)
{
- return FARX_ACCESS_FLASH_CONF | faddr;
+ return ha->flash_conf_off | faddr;
}
static inline uint32_t
-flash_data_to_access_addr(uint32_t faddr)
+flash_data_addr(struct qla_hw_data *ha, uint32_t faddr)
{
- return FARX_ACCESS_FLASH_DATA | faddr;
+ return ha->flash_data_off | faddr;
}
static inline uint32_t
-nvram_conf_to_access_addr(uint32_t naddr)
+nvram_conf_addr(struct qla_hw_data *ha, uint32_t naddr)
{
- return FARX_ACCESS_NVRAM_CONF | naddr;
+ return ha->nvram_conf_off | naddr;
}
static inline uint32_t
-nvram_data_to_access_addr(uint32_t naddr)
+nvram_data_addr(struct qla_hw_data *ha, uint32_t naddr)
{
- return FARX_ACCESS_NVRAM_DATA | naddr;
+ return ha->nvram_data_off | naddr;
}
static uint32_t
@@ -481,10 +481,12 @@ qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
uint32_t i;
+ struct qla_hw_data *ha = vha->hw;
+
/* Dword reads to flash. */
for (i = 0; i < dwords; i++, faddr++)
- dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(vha->hw,
- flash_data_to_access_addr(faddr)));
+ dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
+ flash_data_addr(ha, faddr)));
return dwptr;
}
@@ -518,7 +520,7 @@ qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id,
{
uint32_t ids;
- ids = qla24xx_read_flash_dword(ha, flash_data_to_access_addr(0xd03ab));
+ ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x03ab));
*man_id = LSB(ids);
*flash_id = MSB(ids);
@@ -530,8 +532,7 @@ qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id,
* Example: ATMEL 0x00 01 45 1F
* Extract MFG and Dev ID from last two bytes.
*/
- ids = qla24xx_read_flash_dword(ha,
- flash_data_to_access_addr(0xd009f));
+ ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x009f));
*man_id = LSB(ids);
*flash_id = MSB(ids);
}
@@ -555,9 +556,13 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
/* Begin with sane defaults. */
loc = locations[0];
- *start = IS_QLA24XX_TYPE(ha) ? FA_FLASH_LAYOUT_ADDR_24:
- FA_FLASH_LAYOUT_ADDR;
-
+ *start = 0;
+ if (IS_QLA24XX_TYPE(ha))
+ *start = FA_FLASH_LAYOUT_ADDR_24;
+ else if (IS_QLA25XX(ha))
+ *start = FA_FLASH_LAYOUT_ADDR;
+ else if (IS_QLA81XX(ha))
+ *start = FA_FLASH_LAYOUT_ADDR_81;
/* Begin with first PCI expansion ROM header. */
buf = (uint8_t *)req->ring;
dcode = (uint32_t *)req->ring;
@@ -618,6 +623,22 @@ static void
qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
{
const char *loc, *locations[] = { "DEF", "FLT" };
+ const uint32_t def_fw[] =
+ { FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR_81 };
+ const uint32_t def_boot[] =
+ { FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR_81 };
+ const uint32_t def_vpd_nvram[] =
+ { FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR_81 };
+ const uint32_t def_fdt[] =
+ { FA_FLASH_DESCR_ADDR_24, FA_FLASH_DESCR_ADDR,
+ FA_FLASH_DESCR_ADDR_81 };
+ const uint32_t def_npiv_conf0[] =
+ { FA_NPIV_CONF0_ADDR_24, FA_NPIV_CONF0_ADDR,
+ FA_NPIV_CONF0_ADDR_81 };
+ const uint32_t def_npiv_conf1[] =
+ { FA_NPIV_CONF1_ADDR_24, FA_NPIV_CONF1_ADDR,
+ FA_NPIV_CONF1_ADDR_81 };
+ uint32_t def;
uint16_t *wptr;
uint16_t cnt, chksum;
uint32_t start;
@@ -676,20 +697,12 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
case FLT_REG_FDT:
ha->flt_region_fdt = start;
break;
- case FLT_REG_HW_EVENT_0:
- if (!PCI_FUNC(ha->pdev->devfn))
- ha->flt_region_hw_event = start;
- break;
- case FLT_REG_HW_EVENT_1:
- if (PCI_FUNC(ha->pdev->devfn))
- ha->flt_region_hw_event = start;
- break;
case FLT_REG_NPIV_CONF_0:
- if (!PCI_FUNC(ha->pdev->devfn))
+ if (!(PCI_FUNC(ha->pdev->devfn) & 1))
ha->flt_region_npiv_conf = start;
break;
case FLT_REG_NPIV_CONF_1:
- if (PCI_FUNC(ha->pdev->devfn))
+ if (PCI_FUNC(ha->pdev->devfn) & 1)
ha->flt_region_npiv_conf = start;
break;
}
@@ -699,22 +712,24 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
no_flash_data:
/* Use hardcoded defaults. */
loc = locations[0];
- ha->flt_region_fw = FA_RISC_CODE_ADDR;
- ha->flt_region_boot = FA_BOOT_CODE_ADDR;
- ha->flt_region_vpd_nvram = FA_VPD_NVRAM_ADDR;
- ha->flt_region_fdt = IS_QLA24XX_TYPE(ha) ? FA_FLASH_DESCR_ADDR_24:
- FA_FLASH_DESCR_ADDR;
- ha->flt_region_hw_event = !PCI_FUNC(ha->pdev->devfn) ?
- FA_HW_EVENT0_ADDR: FA_HW_EVENT1_ADDR;
- ha->flt_region_npiv_conf = !PCI_FUNC(ha->pdev->devfn) ?
- (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF0_ADDR_24: FA_NPIV_CONF0_ADDR):
- (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF1_ADDR_24: FA_NPIV_CONF1_ADDR);
+ def = 0;
+ if (IS_QLA24XX_TYPE(ha))
+ def = 0;
+ else if (IS_QLA25XX(ha))
+ def = 1;
+ else if (IS_QLA81XX(ha))
+ def = 2;
+ ha->flt_region_fw = def_fw[def];
+ ha->flt_region_boot = def_boot[def];
+ ha->flt_region_vpd_nvram = def_vpd_nvram[def];
+ ha->flt_region_fdt = def_fdt[def];
+ ha->flt_region_npiv_conf = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
+ def_npiv_conf0[def]: def_npiv_conf1[def];
done:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
- "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x npiv=0x%x.\n", loc,
+ "vpd_nvram=0x%x fdt=0x%x flt=0x%x npiv=0x%x.\n", loc,
ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram,
- ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event,
- ha->flt_region_npiv_conf));
+ ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_npiv_conf));
}
static void
@@ -757,14 +772,14 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
mid = le16_to_cpu(fdt->man_id);
fid = le16_to_cpu(fdt->id);
ha->fdt_wrt_disable = fdt->wrt_disable_bits;
- ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd);
+ ha->fdt_erase_cmd = flash_conf_addr(ha, 0x0300 | fdt->erase_cmd);
ha->fdt_block_size = le32_to_cpu(fdt->block_size);
if (fdt->unprotect_sec_cmd) {
- ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0300 |
+ ha->fdt_unprotect_sec_cmd = flash_conf_addr(ha, 0x0300 |
fdt->unprotect_sec_cmd);
ha->fdt_protect_sec_cmd = fdt->protect_sec_cmd ?
- flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd):
- flash_conf_to_access_addr(0x0336);
+ flash_conf_addr(ha, 0x0300 | fdt->protect_sec_cmd):
+ flash_conf_addr(ha, 0x0336);
}
goto done;
no_flash_data:
@@ -773,7 +788,7 @@ no_flash_data:
mid = man_id;
fid = flash_id;
ha->fdt_wrt_disable = 0x9c;
- ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8);
+ ha->fdt_erase_cmd = flash_conf_addr(ha, 0x03d8);
switch (man_id) {
case 0xbf: /* STT flash. */
if (flash_id == 0x8e)
@@ -782,16 +797,16 @@ no_flash_data:
ha->fdt_block_size = FLASH_BLK_SIZE_32K;
if (flash_id == 0x80)
- ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0352);
+ ha->fdt_erase_cmd = flash_conf_addr(ha, 0x0352);
break;
case 0x13: /* ST M25P80. */
ha->fdt_block_size = FLASH_BLK_SIZE_64K;
break;
case 0x1f: /* Atmel 26DF081A. */
ha->fdt_block_size = FLASH_BLK_SIZE_4K;
- ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320);
- ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339);
- ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336);
+ ha->fdt_erase_cmd = flash_conf_addr(ha, 0x0320);
+ ha->fdt_unprotect_sec_cmd = flash_conf_addr(ha, 0x0339);
+ ha->fdt_protect_sec_cmd = flash_conf_addr(ha, 0x0336);
break;
default:
/* Default to 64 kb sector size. */
@@ -813,7 +828,7 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha)
uint32_t flt_addr;
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
+ if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha))
return QLA_SUCCESS;
ret = qla2xxx_find_flt_start(vha, &flt_addr);
@@ -838,7 +853,7 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
struct qla_npiv_entry *entry;
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha))
+ if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) && !IS_QLA81XX(ha))
return;
ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr,
@@ -929,10 +944,10 @@ qla24xx_unprotect_flash(struct qla_hw_data *ha)
if (!ha->fdt_wrt_disable)
return;
- /* Disable flash write-protection. */
- qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
- /* Some flash parts need an additional zero-write to clear bits.*/
- qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+ /* Disable flash write-protection, first clear SR protection bit */
+ qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
+ /* Then write zero again to clear remaining SR bits.*/
+ qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
}
static void
@@ -945,11 +960,10 @@ qla24xx_protect_flash(struct qla_hw_data *ha)
goto skip_wrt_protect;
/* Enable flash write-protection and wait for completion. */
- qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101),
+ qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101),
ha->fdt_wrt_disable);
for (cnt = 300; cnt &&
- qla24xx_read_flash_dword(ha,
- flash_conf_to_access_addr(0x005)) & BIT_0;
+ qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x005)) & BIT_0;
cnt--) {
udelay(10);
}
@@ -966,18 +980,17 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
int ret;
- uint32_t liter, miter;
+ uint32_t liter;
uint32_t sec_mask, rest_addr;
- uint32_t fdata, findex;
+ uint32_t fdata;
dma_addr_t optrom_dma;
void *optrom = NULL;
- uint32_t *s, *d;
struct qla_hw_data *ha = vha->hw;
ret = QLA_SUCCESS;
/* Prepare burst-capable write on supported ISPs. */
- if (IS_QLA25XX(ha) && !(faddr & 0xfff) &&
+ if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && !(faddr & 0xfff) &&
dwords > OPTROM_BURST_DWORDS) {
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
&optrom_dma, GFP_KERNEL);
@@ -989,17 +1002,15 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
}
rest_addr = (ha->fdt_block_size >> 2) - 1;
- sec_mask = 0x80000 - (ha->fdt_block_size >> 2);
+ sec_mask = ~rest_addr;
qla24xx_unprotect_flash(ha);
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
-
- findex = faddr;
- fdata = (findex & sec_mask) << 2;
+ fdata = (faddr & sec_mask) << 2;
/* Are we at the beginning of a sector? */
- if ((findex & rest_addr) == 0) {
+ if ((faddr & rest_addr) == 0) {
/* Do sector unprotect. */
if (ha->fdt_unprotect_sec_cmd)
qla24xx_write_flash_dword(ha,
@@ -1010,7 +1021,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
(fdata & 0xff00) |((fdata << 16) &
0xff0000) | ((fdata >> 16) & 0xff));
if (ret != QLA_SUCCESS) {
- DEBUG9(qla_printk("Unable to flash sector: "
+ DEBUG9(qla_printk("Unable to erase sector: "
"address=%x.\n", faddr));
break;
}
@@ -1019,18 +1030,16 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
/* Go with burst-write. */
if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) {
/* Copy data to DMA'ble buffer. */
- for (miter = 0, s = optrom, d = dwptr;
- miter < OPTROM_BURST_DWORDS; miter++, s++, d++)
- *s = cpu_to_le32(*d);
+ memcpy(optrom, dwptr, OPTROM_BURST_SIZE);
ret = qla2x00_load_ram(vha, optrom_dma,
- flash_data_to_access_addr(faddr),
+ flash_data_addr(ha, faddr),
OPTROM_BURST_DWORDS);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha,
"Unable to burst-write optrom segment "
"(%x/%x/%llx).\n", ret,
- flash_data_to_access_addr(faddr),
+ flash_data_addr(ha, faddr),
(unsigned long long)optrom_dma);
qla_printk(KERN_WARNING, ha,
"Reverting to slow-write.\n");
@@ -1047,7 +1056,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
}
ret = qla24xx_write_flash_dword(ha,
- flash_data_to_access_addr(faddr), cpu_to_le32(*dwptr));
+ flash_data_addr(ha, faddr), cpu_to_le32(*dwptr));
if (ret != QLA_SUCCESS) {
DEBUG9(printk("%s(%ld) Unable to program flash "
"address=%x data=%x.\n", __func__,
@@ -1098,12 +1107,13 @@ qla24xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
{
uint32_t i;
uint32_t *dwptr;
+ struct qla_hw_data *ha = vha->hw;
/* Dword reads to flash. */
dwptr = (uint32_t *)buf;
for (i = 0; i < bytes >> 2; i++, naddr++)
- dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(vha->hw,
- nvram_data_to_access_addr(naddr)));
+ dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
+ nvram_data_addr(ha, naddr)));
return buf;
}
@@ -1160,17 +1170,14 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
/* Disable NVRAM write-protection. */
- qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
- 0);
- qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
- 0);
+ qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0);
+ qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0);
/* Dword writes to flash. */
dwptr = (uint32_t *)buf;
for (i = 0; i < bytes >> 2; i++, naddr++, dwptr++) {
ret = qla24xx_write_flash_dword(ha,
- nvram_data_to_access_addr(naddr),
- cpu_to_le32(*dwptr));
+ nvram_data_addr(ha, naddr), cpu_to_le32(*dwptr));
if (ret != QLA_SUCCESS) {
DEBUG9(qla_printk("Unable to program nvram address=%x "
"data=%x.\n", naddr, *dwptr));
@@ -1179,8 +1186,7 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
}
/* Enable NVRAM write-protection. */
- qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
- 0x8c);
+ qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0x8c);
/* Disable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
@@ -1202,8 +1208,7 @@ qla25xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
dwptr = (uint32_t *)buf;
for (i = 0; i < bytes >> 2; i++, naddr++)
dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
- flash_data_to_access_addr(ha->flt_region_vpd_nvram |
- naddr)));
+ flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr)));
return buf;
}
@@ -2246,12 +2251,12 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
burst = left;
rval = qla2x00_dump_ram(vha, optrom_dma,
- flash_data_to_access_addr(faddr), burst);
+ flash_data_addr(ha, faddr), burst);
if (rval) {
qla_printk(KERN_WARNING, ha,
"Unable to burst-read optrom segment "
"(%x/%x/%llx).\n", rval,
- flash_data_to_access_addr(faddr),
+ flash_data_addr(ha, faddr),
(unsigned long long)optrom_dma);
qla_printk(KERN_WARNING, ha,
"Reverting to slow-read.\n");
@@ -2648,108 +2653,3 @@ qla2xxx_get_vpd_field(scsi_qla_host_t *vha, char *key, char *str, size_t size)
return 0;
}
-
-static int
-qla2xxx_hw_event_store(scsi_qla_host_t *vha, uint32_t *fdata)
-{
- uint32_t d[2], faddr;
- struct qla_hw_data *ha = vha->hw;
-
- /* Locate first empty entry. */
- for (;;) {
- if (ha->hw_event_ptr >=
- ha->flt_region_hw_event + FA_HW_EVENT_SIZE) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "HW event -- Log Full!\n"));
- return QLA_MEMORY_ALLOC_FAILED;
- }
-
- qla24xx_read_flash_data(vha, d, ha->hw_event_ptr, 2);
- faddr = flash_data_to_access_addr(ha->hw_event_ptr);
- ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
- if (d[0] == __constant_cpu_to_le32(0xffffffff) &&
- d[1] == __constant_cpu_to_le32(0xffffffff)) {
- qla24xx_unprotect_flash(ha);
-
- qla24xx_write_flash_dword(ha, faddr++,
- cpu_to_le32(jiffies));
- qla24xx_write_flash_dword(ha, faddr++, 0);
- qla24xx_write_flash_dword(ha, faddr++, *fdata++);
- qla24xx_write_flash_dword(ha, faddr++, *fdata);
-
- qla24xx_protect_flash(ha);
- break;
- }
- }
- return QLA_SUCCESS;
-}
-
-int
-qla2xxx_hw_event_log(scsi_qla_host_t *vha, uint16_t code, uint16_t d1,
- uint16_t d2, uint16_t d3)
-{
-#define QMARK(a, b, c, d) \
- cpu_to_le32(LSB(a) << 24 | LSB(b) << 16 | LSB(c) << 8 | LSB(d))
- struct qla_hw_data *ha = vha->hw;
- int rval;
- uint32_t marker[2], fdata[4];
-
- if (ha->flt_region_hw_event == 0)
- return QLA_FUNCTION_FAILED;
-
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "HW event -- code=%x, d1=%x, d2=%x, d3=%x.\n", code, d1, d2, d3));
-
- /* If marker not already found, locate or write. */
- if (!ha->flags.hw_event_marker_found) {
- /* Create marker. */
- marker[0] = QMARK('L', ha->fw_major_version,
- ha->fw_minor_version, ha->fw_subminor_version);
- marker[1] = QMARK(QLA_DRIVER_MAJOR_VER, QLA_DRIVER_MINOR_VER,
- QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER);
-
- /* Locate marker. */
- ha->hw_event_ptr = ha->flt_region_hw_event;
- for (;;) {
- qla24xx_read_flash_data(vha, fdata, ha->hw_event_ptr,
- 4);
- if (fdata[0] == __constant_cpu_to_le32(0xffffffff) &&
- fdata[1] == __constant_cpu_to_le32(0xffffffff))
- break;
- ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE;
- if (ha->hw_event_ptr >=
- ha->flt_region_hw_event + FA_HW_EVENT_SIZE) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "HW event -- Log Full!\n"));
- return QLA_MEMORY_ALLOC_FAILED;
- }
- if (fdata[2] == marker[0] && fdata[3] == marker[1]) {
- ha->flags.hw_event_marker_found = 1;
- break;
- }
- }
- /* No marker, write it. */
- if (!ha->flags.hw_event_marker_found) {
- rval = qla2xxx_hw_event_store(vha, marker);
- if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "HW event -- Failed marker write=%x.!\n",
- rval));
- return rval;
- }
- ha->flags.hw_event_marker_found = 1;
- }
- }
-
- /* Store error. */
- fdata[0] = cpu_to_le32(code << 16 | d1);
- fdata[1] = cpu_to_le32(d2 << 16 | d3);
- rval = qla2xxx_hw_event_store(vha, fdata);
- if (rval != QLA_SUCCESS) {
- DEBUG2(qla_printk(KERN_WARNING, ha,
- "HW event -- Failed error write=%x.!\n",
- rval));
- }
-
- return rval;
-}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index be22f3a09f8d..cfa4c11a4797 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.03-k1"
+#define QLA2XXX_VERSION "8.03.00-k2"
#define QLA_DRIVER_MAJOR_VER 8
-#define QLA_DRIVER_MINOR_VER 2
-#define QLA_DRIVER_PATCH_VER 3
+#define QLA_DRIVER_MINOR_VER 3
+#define QLA_DRIVER_PATCH_VER 0
#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index d6be0762eb91..b586f27c3bd4 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -244,6 +244,7 @@ struct ddb_entry {
uint8_t ip_addr[ISCSI_IPADDR_SIZE];
uint8_t iscsi_name[ISCSI_NAME_SIZE]; /* 72 x48 */
uint8_t iscsi_alias[0x20];
+ uint8_t isid[6];
};
/*
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 109c5f5985ec..af8c3233e8ae 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -342,8 +342,12 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
__func__, fw_ddb_index));
list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
- if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
- ISCSI_NAME_SIZE) == 0) {
+ if ((memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
+ ISCSI_NAME_SIZE) == 0) &&
+ (ddb_entry->tpgt ==
+ le32_to_cpu(fw_ddb_entry->tgt_portal_grp)) &&
+ (memcmp(ddb_entry->isid, fw_ddb_entry->isid,
+ sizeof(ddb_entry->isid)) == 0)) {
found++;
break;
}
@@ -430,6 +434,8 @@ static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
+ memcpy(ddb_entry->isid, fw_ddb_entry->isid, sizeof(ddb_entry->isid));
+
memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
min(sizeof(ddb_entry->iscsi_name),
sizeof(fw_ddb_entry->iscsi_name)));
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index c577d79bd7e8..051b0f5e8c8e 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -392,7 +392,7 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
else
dev_info(&ha->pdev->dev, "WARNING!!! You have less than %d "
- "firmare IOCBs available (%d).\n",
+ "firmware IOCBs available (%d).\n",
IOCB_HIWAT_CUSHION, ha->iocb_hiwat);
return QLA_SUCCESS;
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 913a931176ef..8e5c169b03fb 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -237,8 +237,7 @@ int raid_component_add(struct raid_template *r,struct device *raid_dev,
rc->dev.parent = get_device(component_dev);
rc->num = rd->component_count++;
- snprintf(rc->dev.bus_id, sizeof(rc->dev.bus_id),
- "component-%d", rc->num);
+ dev_set_name(&rc->dev, "component-%d", rc->num);
list_add_tail(&rc->node, &rd->component_list);
rc->dev.class = &raid_class.class;
err = device_add(&rc->dev);
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index f8b79d401d58..cbcd3f681b62 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -651,10 +651,6 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
unsigned long timeout;
int rtn = 0;
- /*
- * We will use a queued command if possible, otherwise we will
- * emulate the queuing and calling of completion function ourselves.
- */
atomic_inc(&cmd->device->iorequest_cnt);
/* check if the device is still usable */
@@ -1099,7 +1095,8 @@ EXPORT_SYMBOL(__starget_for_each_device);
* Description: Looks up the scsi_device with the specified @lun for a given
* @starget. The returned scsi_device does not have an additional
* reference. You must hold the host's host_lock over this call and
- * any access to the returned scsi_device.
+ * any access to the returned scsi_device. A scsi_device in state
+ * SDEV_DEL is skipped.
*
* Note: The only reason why drivers should use this is because
* they need to access the device list in irq context. Otherwise you
@@ -1111,6 +1108,8 @@ struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget,
struct scsi_device *sdev;
list_for_each_entry(sdev, &starget->devices, same_target_siblings) {
+ if (sdev->sdev_state == SDEV_DEL)
+ continue;
if (sdev->lun ==lun)
return sdev;
}
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 27c633f55794..6eebd0bbe8a8 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2508,7 +2508,7 @@ static void pseudo_0_release(struct device *dev)
}
static struct device pseudo_primary = {
- .bus_id = "pseudo_0",
+ .init_name = "pseudo_0",
.release = pseudo_0_release,
};
@@ -2680,7 +2680,7 @@ static int sdebug_add_adapter(void)
sdbg_host->dev.bus = &pseudo_lld_bus;
sdbg_host->dev.parent = &pseudo_primary;
sdbg_host->dev.release = &sdebug_release_adapter;
- sprintf(sdbg_host->dev.bus_id, "adapter%d", scsi_debug_add_host);
+ dev_set_name(&sdbg_host->dev, "adapter%d", scsi_debug_add_host);
error = device_register(&sdbg_host->dev);
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 4969e4ec75ea..099b5455bbce 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -224,6 +224,7 @@ static struct {
{"SGI", "TP9100", "*", BLIST_REPORTLUN2},
{"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
{"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+ {"SUN", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
{"SMSC", "USB 2 HS-CF", NULL, BLIST_SPARSELUN | BLIST_INQUIRY_36},
{"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN},
{"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 381838ebd460..ad6a1370761e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -124,34 +124,22 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
enum blk_eh_timer_return scsi_times_out(struct request *req)
{
struct scsi_cmnd *scmd = req->special;
- enum blk_eh_timer_return (*eh_timed_out)(struct scsi_cmnd *);
enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
scsi_log_completion(scmd, TIMEOUT_ERROR);
if (scmd->device->host->transportt->eh_timed_out)
- eh_timed_out = scmd->device->host->transportt->eh_timed_out;
+ rtn = scmd->device->host->transportt->eh_timed_out(scmd);
else if (scmd->device->host->hostt->eh_timed_out)
- eh_timed_out = scmd->device->host->hostt->eh_timed_out;
- else
- eh_timed_out = NULL;
+ rtn = scmd->device->host->hostt->eh_timed_out(scmd);
- if (eh_timed_out) {
- rtn = eh_timed_out(scmd);
- switch (rtn) {
- case BLK_EH_NOT_HANDLED:
- break;
- default:
- return rtn;
- }
- }
-
- if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
+ if (unlikely(rtn == BLK_EH_NOT_HANDLED &&
+ !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
scmd->result |= DID_TIME_OUT << 16;
- return BLK_EH_HANDLED;
+ rtn = BLK_EH_HANDLED;
}
- return BLK_EH_NOT_HANDLED;
+ return rtn;
}
/**
@@ -1650,7 +1638,7 @@ int scsi_error_handler(void *data)
* We use TASK_INTERRUPTIBLE so that the thread is not
* counted against the load average as a running process.
* We never actually get interrupted because kthread_run
- * disables singal delivery for the created thread.
+ * disables signal delivery for the created thread.
*/
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 2ae4f8fc5831..b98f763931c5 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -167,10 +167,17 @@ EXPORT_SYMBOL(scsi_set_medium_removal);
static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg)
{
struct device *dev = scsi_get_device(sdev->host);
+ const char *name;
if (!dev)
return -ENXIO;
- return copy_to_user(arg, dev->bus_id, sizeof(dev->bus_id))? -EFAULT: 0;
+
+ name = dev_name(dev);
+
+ /* compatibility with old ioctl which only returned
+ * 20 characters */
+ return copy_to_user(arg, name, min(strlen(name), (size_t)20))
+ ? -EFAULT: 0;
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index f2f51e0333eb..940dc32ff0dc 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -91,26 +91,19 @@ static void scsi_unprep_request(struct request *req)
scsi_put_command(cmd);
}
-/*
- * Function: scsi_queue_insert()
- *
- * Purpose: Insert a command in the midlevel queue.
- *
- * Arguments: cmd - command that we are adding to queue.
- * reason - why we are inserting command to queue.
- *
- * Lock status: Assumed that lock is not held upon entry.
- *
- * Returns: Nothing.
- *
- * Notes: We do this for one of two cases. Either the host is busy
- * and it cannot accept any more commands for the time being,
- * or the device returned QUEUE_FULL and can accept no more
- * commands.
- * Notes: This could be called either from an interrupt context or a
- * normal process context.
+/**
+ * __scsi_queue_insert - private queue insertion
+ * @cmd: The SCSI command being requeued
+ * @reason: The reason for the requeue
+ * @unbusy: Whether the queue should be unbusied
+ *
+ * This is a private queue insertion. The public interface
+ * scsi_queue_insert() always assumes the queue should be unbusied
+ * because it's always called before the completion. This function is
+ * for a requeue after completion, which should only occur in this
+ * file.
*/
-int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
+static int __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
{
struct Scsi_Host *host = cmd->device->host;
struct scsi_device *device = cmd->device;
@@ -150,7 +143,8 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
* Decrement the counters, since these commands are no longer
* active on the host/device.
*/
- scsi_device_unbusy(device);
+ if (unbusy)
+ scsi_device_unbusy(device);
/*
* Requeue this command. It will go before all other commands
@@ -172,6 +166,29 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
return 0;
}
+/*
+ * Function: scsi_queue_insert()
+ *
+ * Purpose: Insert a command in the midlevel queue.
+ *
+ * Arguments: cmd - command that we are adding to queue.
+ * reason - why we are inserting command to queue.
+ *
+ * Lock status: Assumed that lock is not held upon entry.
+ *
+ * Returns: Nothing.
+ *
+ * Notes: We do this for one of two cases. Either the host is busy
+ * and it cannot accept any more commands for the time being,
+ * or the device returned QUEUE_FULL and can accept no more
+ * commands.
+ * Notes: This could be called either from an interrupt context or a
+ * normal process context.
+ */
+int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
+{
+ return __scsi_queue_insert(cmd, reason, 1);
+}
/**
* scsi_execute - insert request and wait for the result
* @sdev: scsi device
@@ -684,6 +701,8 @@ void scsi_run_host_queues(struct Scsi_Host *shost)
scsi_run_queue(sdev->request_queue);
}
+static void __scsi_release_buffers(struct scsi_cmnd *, int);
+
/*
* Function: scsi_end_request()
*
@@ -732,6 +751,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
* leftovers in the front of the
* queue, and goose the queue again.
*/
+ scsi_release_buffers(cmd);
scsi_requeue_command(q, cmd);
cmd = NULL;
}
@@ -743,6 +763,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
* This will goose the queue request function at the end, so we don't
* need to worry about launching another command.
*/
+ __scsi_release_buffers(cmd, 0);
scsi_next_command(cmd);
return NULL;
}
@@ -798,6 +819,26 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free);
}
+static void __scsi_release_buffers(struct scsi_cmnd *cmd, int do_bidi_check)
+{
+
+ if (cmd->sdb.table.nents)
+ scsi_free_sgtable(&cmd->sdb);
+
+ memset(&cmd->sdb, 0, sizeof(cmd->sdb));
+
+ if (do_bidi_check && scsi_bidi_cmnd(cmd)) {
+ struct scsi_data_buffer *bidi_sdb =
+ cmd->request->next_rq->special;
+ scsi_free_sgtable(bidi_sdb);
+ kmem_cache_free(scsi_sdb_cache, bidi_sdb);
+ cmd->request->next_rq->special = NULL;
+ }
+
+ if (scsi_prot_sg_count(cmd))
+ scsi_free_sgtable(cmd->prot_sdb);
+}
+
/*
* Function: scsi_release_buffers()
*
@@ -817,21 +858,7 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb)
*/
void scsi_release_buffers(struct scsi_cmnd *cmd)
{
- if (cmd->sdb.table.nents)
- scsi_free_sgtable(&cmd->sdb);
-
- memset(&cmd->sdb, 0, sizeof(cmd->sdb));
-
- if (scsi_bidi_cmnd(cmd)) {
- struct scsi_data_buffer *bidi_sdb =
- cmd->request->next_rq->special;
- scsi_free_sgtable(bidi_sdb);
- kmem_cache_free(scsi_sdb_cache, bidi_sdb);
- cmd->request->next_rq->special = NULL;
- }
-
- if (scsi_prot_sg_count(cmd))
- scsi_free_sgtable(cmd->prot_sdb);
+ __scsi_release_buffers(cmd, 1);
}
EXPORT_SYMBOL(scsi_release_buffers);
@@ -945,7 +972,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
}
BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */
- scsi_release_buffers(cmd);
/*
* Next deal with any sectors which we were able to correctly
@@ -963,6 +989,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
return;
this_count = blk_rq_bytes(req);
+ error = -EIO;
+
if (host_byte(result) == DID_RESET) {
/* Third party bus reset or reset for error recovery
* reasons. Just retry the command and see what
@@ -1004,13 +1032,18 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
/* This will issue a new 6-byte command. */
cmd->device->use_10_for_rw = 0;
action = ACTION_REPREP;
+ } else if (sshdr.asc == 0x10) /* DIX */ {
+ description = "Host Data Integrity Failure";
+ action = ACTION_FAIL;
+ error = -EILSEQ;
} else
action = ACTION_FAIL;
break;
case ABORTED_COMMAND:
if (sshdr.asc == 0x10) { /* DIF */
+ description = "Target Data Integrity Failure";
action = ACTION_FAIL;
- description = "Data Integrity Failure";
+ error = -EILSEQ;
} else
action = ACTION_RETRY;
break;
@@ -1029,6 +1062,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
case 0x09: /* self test in progress */
action = ACTION_DELAYED_RETRY;
break;
+ default:
+ description = "Device not ready";
+ action = ACTION_FAIL;
+ break;
}
} else {
description = "Device not ready";
@@ -1052,9 +1089,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
switch (action) {
case ACTION_FAIL:
/* Give up and fail the remainder of the request */
+ scsi_release_buffers(cmd);
if (!(req->cmd_flags & REQ_QUIET)) {
if (description)
- scmd_printk(KERN_INFO, cmd, "%s",
+ scmd_printk(KERN_INFO, cmd, "%s\n",
description);
scsi_print_result(cmd);
if (driver_byte(result) & DRIVER_SENSE)
@@ -1067,15 +1105,16 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
/* Unprep the request and put it back at the head of the queue.
* A new command will be prepared and issued.
*/
+ scsi_release_buffers(cmd);
scsi_requeue_command(q, cmd);
break;
case ACTION_RETRY:
/* Retry the same command immediately */
- scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY);
+ __scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY, 0);
break;
case ACTION_DELAYED_RETRY:
/* Retry the same command after a delay */
- scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
+ __scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY, 0);
break;
}
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 18486b51668d..66505bb79410 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/spinlock.h>
+#include <linux/async.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -179,6 +180,8 @@ int scsi_complete_async_scans(void)
spin_unlock(&async_scan_lock);
kfree(data);
+ /* Synchronize async operations globally */
+ async_synchronize_full();
return 0;
}
@@ -411,8 +414,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
device_initialize(dev);
starget->reap_ref = 1;
dev->parent = get_device(parent);
- sprintf(dev->bus_id, "target%d:%d:%d",
- shost->host_no, channel, id);
+ dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
#ifndef CONFIG_SYSFS_DEPRECATED
dev->bus = &scsi_bus_type;
#endif
@@ -1021,7 +1023,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
if (rescan || !scsi_device_created(sdev)) {
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
"scsi scan: device exists on %s\n",
- sdev->sdev_gendev.bus_id));
+ dev_name(&sdev->sdev_gendev)));
if (sdevp)
*sdevp = sdev;
else
@@ -1160,7 +1162,7 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget,
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of"
- "%s\n", starget->dev.bus_id));
+ "%s\n", dev_name(&starget->dev)));
max_dev_lun = min(max_scsi_luns, shost->max_lun);
/*
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 93c28f30bbd7..da63802cbf9d 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1079,16 +1079,14 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
device_initialize(&sdev->sdev_gendev);
sdev->sdev_gendev.bus = &scsi_bus_type;
sdev->sdev_gendev.type = &scsi_dev_type;
- sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
- sdev->host->host_no, sdev->channel, sdev->id,
- sdev->lun);
-
+ dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%d",
+ sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
+
device_initialize(&sdev->sdev_dev);
sdev->sdev_dev.parent = &sdev->sdev_gendev;
sdev->sdev_dev.class = &sdev_class;
- snprintf(sdev->sdev_dev.bus_id, BUS_ID_SIZE,
- "%d:%d:%d:%d", sdev->host->host_no,
- sdev->channel, sdev->id, sdev->lun);
+ dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d",
+ sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
sdev->scsi_level = starget->scsi_level;
transport_setup_device(&sdev->sdev_gendev);
spin_lock_irqsave(shost->host_lock, flags);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 062304de4854..5f77417ed585 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -2407,8 +2407,12 @@ fc_rport_final_delete(struct work_struct *work)
/*
* Notify the driver that the rport is now dead. The LLDD will
* also guarantee that any communication to the rport is terminated
+ *
+ * Avoid this call if we already called it when we preserved the
+ * rport for the binding.
*/
- if (i->f->dev_loss_tmo_callbk)
+ if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) &&
+ (i->f->dev_loss_tmo_callbk))
i->f->dev_loss_tmo_callbk(rport);
transport_remove_device(dev);
@@ -2486,8 +2490,8 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
device_initialize(dev); /* takes self reference */
dev->parent = get_device(&shost->shost_gendev); /* parent reference */
dev->release = fc_rport_dev_release;
- sprintf(dev->bus_id, "rport-%d:%d-%d",
- shost->host_no, channel, rport->number);
+ dev_set_name(dev, "rport-%d:%d-%d",
+ shost->host_no, channel, rport->number);
transport_setup_device(dev);
error = device_add(dev);
@@ -2647,7 +2651,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
spin_lock_irqsave(shost->host_lock, flags);
rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT |
- FC_RPORT_DEVLOSS_PENDING);
+ FC_RPORT_DEVLOSS_PENDING |
+ FC_RPORT_DEVLOSS_CALLBK_DONE);
/* if target, initiate a scan */
if (rport->scsi_target_id != -1) {
@@ -2944,6 +2949,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
struct fc_rport *rport =
container_of(work, struct fc_rport, dev_loss_work.work);
struct Scsi_Host *shost = rport_to_shost(rport);
+ struct fc_internal *i = to_fc_internal(shost->transportt);
struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
unsigned long flags;
@@ -3011,6 +3017,7 @@ fc_timeout_deleted_rport(struct work_struct *work)
rport->roles = FC_PORT_ROLE_UNKNOWN;
rport->port_state = FC_PORTSTATE_NOTPRESENT;
rport->flags &= ~FC_RPORT_FAST_FAIL_TIMEDOUT;
+ rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE;
/*
* Pre-emptively kill I/O rather than waiting for the work queue
@@ -3046,8 +3053,18 @@ fc_timeout_deleted_rport(struct work_struct *work)
* all attached scsi devices.
*/
fc_queue_work(shost, &rport->stgt_delete_work);
+
+ /*
+ * Notify the driver that the rport is now dead. The LLDD will
+ * also guarantee that any communication to the rport is terminated
+ *
+ * Note: we set the CALLBK_DONE flag above to correspond
+ */
+ if (i->f->dev_loss_tmo_callbk)
+ i->f->dev_loss_tmo_callbk(rport);
}
+
/**
* fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a disconnected SCSI target.
* @work: rport to terminate io on.
@@ -3164,8 +3181,8 @@ fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
device_initialize(dev); /* takes self reference */
dev->parent = get_device(pdev); /* takes parent reference */
dev->release = fc_vport_dev_release;
- sprintf(dev->bus_id, "vport-%d:%d-%d",
- shost->host_no, channel, vport->number);
+ dev_set_name(dev, "vport-%d:%d-%d",
+ shost->host_no, channel, vport->number);
transport_setup_device(dev);
error = device_add(dev);
@@ -3188,19 +3205,19 @@ fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev,
*/
if (pdev != &shost->shost_gendev) {
error = sysfs_create_link(&shost->shost_gendev.kobj,
- &dev->kobj, dev->bus_id);
+ &dev->kobj, dev_name(dev));
if (error)
printk(KERN_ERR
"%s: Cannot create vport symlinks for "
"%s, err=%d\n",
- __func__, dev->bus_id, error);
+ __func__, dev_name(dev), error);
}
spin_lock_irqsave(shost->host_lock, flags);
vport->flags &= ~FC_VPORT_CREATING;
spin_unlock_irqrestore(shost->host_lock, flags);
dev_printk(KERN_NOTICE, pdev,
- "%s created via shost%d channel %d\n", dev->bus_id,
+ "%s created via shost%d channel %d\n", dev_name(dev),
shost->host_no, channel);
*ret_vport = vport;
@@ -3297,7 +3314,7 @@ fc_vport_terminate(struct fc_vport *vport)
return stat;
if (dev->parent != &shost->shost_gendev)
- sysfs_remove_link(&shost->shost_gendev.kobj, dev->bus_id);
+ sysfs_remove_link(&shost->shost_gendev.kobj, dev_name(dev));
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
@@ -3329,7 +3346,7 @@ fc_vport_sched_delete(struct work_struct *work)
dev_printk(KERN_ERR, vport->dev.parent,
"%s: %s could not be deleted created via "
"shost%d channel %d - error %d\n", __func__,
- vport->dev.bus_id, vport->shost->host_no,
+ dev_name(&vport->dev), vport->shost->host_no,
vport->channel, stat);
}
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 4a803ebaf508..75c9297694cb 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -187,8 +187,7 @@ iscsi_create_endpoint(int dd_size)
ep->id = id;
ep->dev.class = &iscsi_endpoint_class;
- snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%llu",
- (unsigned long long) id);
+ dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
err = device_register(&ep->dev);
if (err)
goto free_ep;
@@ -724,8 +723,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
}
session->target_id = id;
- snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
- session->sid);
+ dev_set_name(&session->dev, "session%u", session->sid);
err = device_add(&session->dev);
if (err) {
iscsi_cls_session_printk(KERN_ERR, session,
@@ -898,8 +896,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
if (!get_device(&session->dev))
goto free_conn;
- snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
- session->sid, cid);
+ dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
conn->dev.parent = &session->dev;
conn->dev.release = iscsi_conn_release;
err = device_register(&conn->dev);
@@ -1816,7 +1813,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
priv->t.create_work_queue = 1;
priv->dev.class = &iscsi_transport_class;
- snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
+ dev_set_name(&priv->dev, "%s", tt->name);
err = device_register(&priv->dev);
if (err)
goto free_priv;
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 366609386be1..50988cbf7b2d 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -207,7 +207,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
struct request_queue *q;
int error;
struct device *dev;
- char namebuf[BUS_ID_SIZE];
+ char namebuf[20];
const char *name;
void (*release)(struct device *);
@@ -219,7 +219,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
if (rphy) {
q = blk_init_queue(sas_non_host_smp_request, NULL);
dev = &rphy->dev;
- name = dev->bus_id;
+ name = dev_name(dev);
release = NULL;
} else {
q = blk_init_queue(sas_host_smp_request, NULL);
@@ -629,10 +629,10 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
INIT_LIST_HEAD(&phy->port_siblings);
if (scsi_is_sas_expander_device(parent)) {
struct sas_rphy *rphy = dev_to_rphy(parent);
- sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no,
+ dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no,
rphy->scsi_target_id, number);
} else
- sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
+ dev_set_name(&phy->dev, "phy-%d:%d", shost->host_no, number);
transport_setup_device(&phy->dev);
@@ -770,7 +770,7 @@ static void sas_port_create_link(struct sas_port *port,
int res;
res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj,
- phy->dev.bus_id);
+ dev_name(&phy->dev));
if (res)
goto err;
res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
@@ -785,7 +785,7 @@ err:
static void sas_port_delete_link(struct sas_port *port,
struct sas_phy *phy)
{
- sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id);
+ sysfs_remove_link(&port->dev.kobj, dev_name(&phy->dev));
sysfs_remove_link(&phy->dev.kobj, "port");
}
@@ -821,11 +821,11 @@ struct sas_port *sas_port_alloc(struct device *parent, int port_id)
if (scsi_is_sas_expander_device(parent)) {
struct sas_rphy *rphy = dev_to_rphy(parent);
- sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no,
- rphy->scsi_target_id, port->port_identifier);
+ dev_set_name(&port->dev, "port-%d:%d:%d", shost->host_no,
+ rphy->scsi_target_id, port->port_identifier);
} else
- sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no,
- port->port_identifier);
+ dev_set_name(&port->dev, "port-%d:%d", shost->host_no,
+ port->port_identifier);
transport_setup_device(&port->dev);
@@ -935,7 +935,7 @@ void sas_port_delete(struct sas_port *port)
if (port->is_backlink) {
struct device *parent = port->dev.parent;
- sysfs_remove_link(&port->dev.kobj, parent->bus_id);
+ sysfs_remove_link(&port->dev.kobj, dev_name(parent));
port->is_backlink = 0;
}
@@ -984,7 +984,8 @@ void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)
/* If this trips, you added a phy that was already
* part of a different port */
if (unlikely(tmp != phy)) {
- dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", phy->dev.bus_id);
+ dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n",
+ dev_name(&phy->dev));
BUG();
}
} else {
@@ -1023,7 +1024,7 @@ void sas_port_mark_backlink(struct sas_port *port)
return;
port->is_backlink = 1;
res = sysfs_create_link(&port->dev.kobj, &parent->kobj,
- parent->bus_id);
+ dev_name(parent));
if (res)
goto err;
return;
@@ -1367,11 +1368,12 @@ struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
rdev->rphy.dev.release = sas_end_device_release;
if (scsi_is_sas_expander_device(parent->dev.parent)) {
struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent);
- sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d",
- shost->host_no, rphy->scsi_target_id, parent->port_identifier);
+ dev_set_name(&rdev->rphy.dev, "end_device-%d:%d:%d",
+ shost->host_no, rphy->scsi_target_id,
+ parent->port_identifier);
} else
- sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d",
- shost->host_no, parent->port_identifier);
+ dev_set_name(&rdev->rphy.dev, "end_device-%d:%d",
+ shost->host_no, parent->port_identifier);
rdev->rphy.identify.device_type = SAS_END_DEVICE;
sas_rphy_initialize(&rdev->rphy);
transport_setup_device(&rdev->rphy.dev);
@@ -1411,8 +1413,8 @@ struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
mutex_lock(&sas_host->lock);
rdev->rphy.scsi_target_id = sas_host->next_expander_id++;
mutex_unlock(&sas_host->lock);
- sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d",
- shost->host_no, rdev->rphy.scsi_target_id);
+ dev_set_name(&rdev->rphy.dev, "expander-%d:%d",
+ shost->host_no, rdev->rphy.scsi_target_id);
rdev->rphy.identify.device_type = type;
sas_rphy_initialize(&rdev->rphy);
transport_setup_device(&rdev->rphy.dev);
@@ -1445,7 +1447,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
transport_add_device(&rphy->dev);
transport_configure_device(&rphy->dev);
if (sas_bsg_initialize(shost, rphy))
- printk("fail to a bsg device %s\n", rphy->dev.bus_id);
+ printk("fail to a bsg device %s\n", dev_name(&rphy->dev));
mutex_lock(&sas_host->lock);
diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c
index 8a7af951d98a..21a045e0559f 100644
--- a/drivers/scsi/scsi_transport_srp.c
+++ b/drivers/scsi/scsi_transport_srp.c
@@ -212,7 +212,7 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost,
rport->roles = ids->roles;
id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id);
- sprintf(rport->dev.bus_id, "port-%d:%d", shost->host_no, id);
+ dev_set_name(&rport->dev, "port-%d:%d", shost->host_no, id);
transport_setup_device(&rport->dev);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 62b28d58e65e..d57566b8be0a 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -48,6 +48,7 @@
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/string_helpers.h>
+#include <linux/async.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
@@ -1802,6 +1803,71 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
return 0;
}
+/*
+ * The asynchronous part of sd_probe
+ */
+static void sd_probe_async(void *data, async_cookie_t cookie)
+{
+ struct scsi_disk *sdkp = data;
+ struct scsi_device *sdp;
+ struct gendisk *gd;
+ u32 index;
+ struct device *dev;
+
+ sdp = sdkp->device;
+ gd = sdkp->disk;
+ index = sdkp->index;
+ dev = &sdp->sdev_gendev;
+
+ if (!sdp->request_queue->rq_timeout) {
+ if (sdp->type != TYPE_MOD)
+ blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
+ else
+ blk_queue_rq_timeout(sdp->request_queue,
+ SD_MOD_TIMEOUT);
+ }
+
+ device_initialize(&sdkp->dev);
+ sdkp->dev.parent = &sdp->sdev_gendev;
+ sdkp->dev.class = &sd_disk_class;
+ dev_set_name(&sdkp->dev, dev_name(&sdp->sdev_gendev));
+
+ if (device_add(&sdkp->dev))
+ goto out_free_index;
+
+ get_device(&sdp->sdev_gendev);
+
+ if (index < SD_MAX_DISKS) {
+ gd->major = sd_major((index & 0xf0) >> 4);
+ gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
+ gd->minors = SD_MINORS;
+ }
+ gd->fops = &sd_fops;
+ gd->private_data = &sdkp->driver;
+ gd->queue = sdkp->device->request_queue;
+
+ sd_revalidate_disk(gd);
+
+ blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
+
+ gd->driverfs_dev = &sdp->sdev_gendev;
+ gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS;
+ if (sdp->removable)
+ gd->flags |= GENHD_FL_REMOVABLE;
+
+ dev_set_drvdata(dev, sdkp);
+ add_disk(gd);
+ sd_dif_config_host(sdkp);
+
+ sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
+ sdp->removable ? "removable " : "");
+
+ return;
+
+ out_free_index:
+ ida_remove(&sd_index_ida, index);
+}
+
/**
* sd_probe - called during driver initialization and whenever a
* new scsi device is attached to the system. It is called once
@@ -1865,48 +1931,7 @@ static int sd_probe(struct device *dev)
sdkp->openers = 0;
sdkp->previous_state = 1;
- if (!sdp->request_queue->rq_timeout) {
- if (sdp->type != TYPE_MOD)
- blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
- else
- blk_queue_rq_timeout(sdp->request_queue,
- SD_MOD_TIMEOUT);
- }
-
- device_initialize(&sdkp->dev);
- sdkp->dev.parent = &sdp->sdev_gendev;
- sdkp->dev.class = &sd_disk_class;
- strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
-
- if (device_add(&sdkp->dev))
- goto out_free_index;
-
- get_device(&sdp->sdev_gendev);
-
- if (index < SD_MAX_DISKS) {
- gd->major = sd_major((index & 0xf0) >> 4);
- gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
- gd->minors = SD_MINORS;
- }
- gd->fops = &sd_fops;
- gd->private_data = &sdkp->driver;
- gd->queue = sdkp->device->request_queue;
-
- sd_revalidate_disk(gd);
-
- blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
-
- gd->driverfs_dev = &sdp->sdev_gendev;
- gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS;
- if (sdp->removable)
- gd->flags |= GENHD_FL_REMOVABLE;
-
- dev_set_drvdata(dev, sdkp);
- add_disk(gd);
- sd_dif_config_host(sdkp);
-
- sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
- sdp->removable ? "removable " : "");
+ async_schedule(sd_probe_async, sdkp);
return 0;
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 3ebb1f289490..184dff492797 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -142,7 +142,7 @@ static int sd_dif_type1_verify_ip(struct blk_integrity_exchg *bix)
static void sd_dif_type1_set_tag(void *prot, void *tag_buf, unsigned int sectors)
{
struct sd_dif_tuple *sdt = prot;
- char *tag = tag_buf;
+ u8 *tag = tag_buf;
unsigned int i, j;
for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
@@ -154,7 +154,7 @@ static void sd_dif_type1_set_tag(void *prot, void *tag_buf, unsigned int sectors
static void sd_dif_type1_get_tag(void *prot, void *tag_buf, unsigned int sectors)
{
struct sd_dif_tuple *sdt = prot;
- char *tag = tag_buf;
+ u8 *tag = tag_buf;
unsigned int i, j;
for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
@@ -256,7 +256,7 @@ static int sd_dif_type3_verify_ip(struct blk_integrity_exchg *bix)
static void sd_dif_type3_set_tag(void *prot, void *tag_buf, unsigned int sectors)
{
struct sd_dif_tuple *sdt = prot;
- char *tag = tag_buf;
+ u8 *tag = tag_buf;
unsigned int i, j;
for (i = 0, j = 0 ; i < sectors ; i++, j += 6, sdt++) {
@@ -269,7 +269,7 @@ static void sd_dif_type3_set_tag(void *prot, void *tag_buf, unsigned int sectors
static void sd_dif_type3_get_tag(void *prot, void *tag_buf, unsigned int sectors)
{
struct sd_dif_tuple *sdt = prot;
- char *tag = tag_buf;
+ u8 *tag = tag_buf;
unsigned int i, j;
for (i = 0, j = 0 ; i < sectors ; i++, j += 2, sdt++) {
@@ -374,7 +374,10 @@ void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsig
else
csum_convert = 0;
+ BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] == WRITE_6));
+
switch (scmd->cmnd[0]) {
+ case READ_6:
case READ_10:
case READ_12:
case READ_16:
@@ -390,6 +393,7 @@ void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsig
break;
+ case WRITE_6:
case WRITE_10:
case WRITE_12:
case WRITE_16:
@@ -475,8 +479,9 @@ int sd_dif_prepare(struct request *rq, sector_t hw_sector, unsigned int sector_s
error:
kunmap_atomic(sdt, KM_USER0);
- sd_printk(KERN_ERR, sdkp, "%s: virt %u, phys %u, ref %u\n",
- __func__, virt, phys, be32_to_cpu(sdt->ref_tag));
+ sd_printk(KERN_ERR, sdkp, "%s: virt %u, phys %u, ref %u, app %4x\n",
+ __func__, virt, phys, be32_to_cpu(sdt->ref_tag),
+ be16_to_cpu(sdt->app_tag));
return -EIO;
}
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 7f0df29f3a64..e946e05db7f7 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -526,7 +526,7 @@ static int ses_intf_add(struct device *cdev,
if (!scomp)
goto err_free;
- edev = enclosure_register(cdev->parent, sdev->sdev_gendev.bus_id,
+ edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev),
components, &ses_enclosure_callbacks);
if (IS_ERR(edev)) {
err = PTR_ERR(edev);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 5103855242ae..8f0bd3f7a59f 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1669,6 +1669,8 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
md->pages = req_schp->pages;
md->page_order = req_schp->page_order;
md->nr_entries = req_schp->k_use_sg;
+ md->offset = 0;
+ md->null_mapped = hp->dxferp ? 0 : 1;
}
if (iov_count)
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 31fe6051c799..0807b260268b 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -297,7 +297,7 @@ out:
return err;
}
-static void __exit sgiwd93_remove(struct platform_device *pdev)
+static int __exit sgiwd93_remove(struct platform_device *pdev)
{
struct Scsi_Host *host = platform_get_drvdata(pdev);
struct ip22_hostdata *hdata = (struct ip22_hostdata *) host->hostdata;
@@ -307,6 +307,7 @@ static void __exit sgiwd93_remove(struct platform_device *pdev)
free_irq(pd->irq, host);
dma_free_noncoherent(&pdev->dev, HPC_DMA_SIZE, hdata->cpu, hdata->dma);
scsi_host_put(host);
+ return 0;
}
static struct platform_driver sgiwd93_driver = {
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index d63d229e2323..6dc8b846c112 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -102,7 +102,7 @@ sim710_probe_common(struct device *dev, unsigned long base_addr,
struct NCR_700_Host_Parameters *hostdata =
kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL);
- printk(KERN_NOTICE "sim710: %s\n", dev->bus_id);
+ printk(KERN_NOTICE "sim710: %s\n", dev_name(dev));
printk(KERN_NOTICE "sim710: irq = %d, clock = %d, base = 0x%lx, scsi_id = %d\n",
irq, clock, base_addr, scsi_id);
@@ -305,7 +305,7 @@ sim710_eisa_probe(struct device *dev)
scsi_id = ffs(val) - 1;
if(scsi_id > 7 || (val & ~(1<<scsi_id)) != 0) {
- printk(KERN_ERR "sim710.c, EISA card %s has incorrect scsi_id, setting to 7\n", dev->bus_id);
+ printk(KERN_ERR "sim710.c, EISA card %s has incorrect scsi_id, setting to 7\n", dev_name(dev));
scsi_id = 7;
}
} else {
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
index 2bbef4c45a0d..77f0b2cdaa94 100644
--- a/drivers/scsi/sni_53c710.c
+++ b/drivers/scsi/sni_53c710.c
@@ -78,8 +78,7 @@ static int __init snirm710_probe(struct platform_device *dev)
base = res->start;
hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
if (!hostdata) {
- printk(KERN_ERR "%s: Failed to allocate host data\n",
- dev->dev.bus_id);
+ dev_printk(KERN_ERR, dev, "Failed to allocate host data\n");
return -ENOMEM;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 7f3f317ee6ca..c6f19ee8f2cb 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static const char *verstr = "20080504";
+static const char *verstr = "20081215";
#include <linux/module.h>
@@ -182,18 +182,16 @@ static struct scsi_tape **scsi_tapes = NULL;
static int modes_defined;
-static struct st_buffer *new_tape_buffer(int, int, int);
static int enlarge_buffer(struct st_buffer *, int, int);
static void clear_buffer(struct st_buffer *);
static void normalize_buffer(struct st_buffer *);
static int append_to_buffer(const char __user *, struct st_buffer *, int);
static int from_buffer(struct st_buffer *, char __user *, int);
static void move_buffer_data(struct st_buffer *, int);
-static void buf_to_sg(struct st_buffer *, unsigned int);
-static int sgl_map_user_pages(struct scatterlist *, const unsigned int,
+static int sgl_map_user_pages(struct st_buffer *, const unsigned int,
unsigned long, size_t, int);
-static int sgl_unmap_user_pages(struct scatterlist *, const unsigned int, int);
+static int sgl_unmap_user_pages(struct st_buffer *, const unsigned int, int);
static int st_probe(struct device *);
static int st_remove(struct device *);
@@ -435,22 +433,6 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
return (-EIO);
}
-
-/* Wakeup from interrupt */
-static void st_sleep_done(void *data, char *sense, int result, int resid)
-{
- struct st_request *SRpnt = data;
- struct scsi_tape *STp = SRpnt->stp;
-
- memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
- (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result;
- (STp->buffer)->cmdstat.residual = resid;
- DEB( STp->write_pending = 0; )
-
- if (SRpnt->waiting)
- complete(SRpnt->waiting);
-}
-
static struct st_request *st_allocate_request(struct scsi_tape *stp)
{
struct st_request *streq;
@@ -475,6 +457,63 @@ static void st_release_request(struct st_request *streq)
kfree(streq);
}
+static void st_scsi_execute_end(struct request *req, int uptodate)
+{
+ struct st_request *SRpnt = req->end_io_data;
+ struct scsi_tape *STp = SRpnt->stp;
+
+ STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
+ STp->buffer->cmdstat.residual = req->data_len;
+
+ if (SRpnt->waiting)
+ complete(SRpnt->waiting);
+
+ blk_rq_unmap_user(SRpnt->bio);
+ __blk_put_request(req->q, req);
+}
+
+static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
+ int data_direction, void *buffer, unsigned bufflen,
+ int timeout, int retries)
+{
+ struct request *req;
+ struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
+ int err = 0;
+ int write = (data_direction == DMA_TO_DEVICE);
+
+ req = blk_get_request(SRpnt->stp->device->request_queue, write,
+ GFP_KERNEL);
+ if (!req)
+ return DRIVER_ERROR << 24;
+
+ req->cmd_type = REQ_TYPE_BLOCK_PC;
+ req->cmd_flags |= REQ_QUIET;
+
+ mdata->null_mapped = 1;
+
+ if (bufflen) {
+ err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen,
+ GFP_KERNEL);
+ if (err) {
+ blk_put_request(req);
+ return DRIVER_ERROR << 24;
+ }
+ }
+
+ SRpnt->bio = req->bio;
+ req->cmd_len = COMMAND_SIZE(cmd[0]);
+ memset(req->cmd, 0, BLK_MAX_CDB);
+ memcpy(req->cmd, cmd, req->cmd_len);
+ req->sense = SRpnt->sense;
+ req->sense_len = 0;
+ req->timeout = timeout;
+ req->retries = retries;
+ req->end_io_data = SRpnt;
+
+ blk_execute_rq_nowait(req->q, NULL, req, 1, st_scsi_execute_end);
+ return 0;
+}
+
/* Do the scsi command. Waits until command performed if do_wait is true.
Otherwise write_behind_check() is used to check that the command
has finished. */
@@ -483,6 +522,8 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd
int bytes, int direction, int timeout, int retries, int do_wait)
{
struct completion *waiting;
+ struct rq_map_data *mdata = &STp->buffer->map_data;
+ int ret;
/* if async, make sure there's no command outstanding */
if (!do_wait && ((STp->buffer)->last_SRpnt)) {
@@ -510,21 +551,27 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd
init_completion(waiting);
SRpnt->waiting = waiting;
- if (!STp->buffer->do_dio)
- buf_to_sg(STp->buffer, bytes);
+ if (STp->buffer->do_dio) {
+ mdata->nr_entries = STp->buffer->sg_segs;
+ mdata->pages = STp->buffer->mapped_pages;
+ } else {
+ mdata->nr_entries =
+ DIV_ROUND_UP(bytes, PAGE_SIZE << mdata->page_order);
+ STp->buffer->map_data.pages = STp->buffer->reserved_pages;
+ STp->buffer->map_data.offset = 0;
+ }
memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
STp->buffer->cmdstat.have_sense = 0;
STp->buffer->syscall_result = 0;
- if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction,
- &((STp->buffer)->sg[0]), bytes, (STp->buffer)->sg_segs,
- timeout, retries, SRpnt, st_sleep_done, GFP_KERNEL)) {
+ ret = st_scsi_execute(SRpnt, cmd, direction, NULL, bytes, timeout,
+ retries);
+ if (ret) {
/* could not allocate the buffer or request was too large */
(STp->buffer)->syscall_result = (-EBUSY);
(STp->buffer)->last_SRpnt = NULL;
- }
- else if (do_wait) {
+ } else if (do_wait) {
wait_for_completion(waiting);
SRpnt->waiting = NULL;
(STp->buffer)->syscall_result = st_chk_result(STp, SRpnt);
@@ -533,28 +580,6 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd
return SRpnt;
}
-static int st_scsi_kern_execute(struct st_request *streq,
- const unsigned char *cmd, int data_direction,
- void *buffer, unsigned bufflen, int timeout,
- int retries)
-{
- struct scsi_tape *stp = streq->stp;
- int ret, resid;
-
- stp->buffer->cmdstat.have_sense = 0;
- memcpy(streq->cmd, cmd, sizeof(streq->cmd));
-
- ret = scsi_execute(stp->device, cmd, data_direction, buffer, bufflen,
- streq->sense, timeout, retries, 0, &resid);
- if (driver_byte(ret) & DRIVER_ERROR)
- return -EBUSY;
-
- stp->buffer->cmdstat.midlevel_result = streq->result = ret;
- stp->buffer->cmdstat.residual = resid;
- stp->buffer->syscall_result = st_chk_result(stp, streq);
-
- return 0;
-}
/* Handle the write-behind checking (waits for completion). Returns -ENOSPC if
write has been correct but EOM early warning reached, -EIO if write ended in
@@ -627,7 +652,6 @@ static int cross_eof(struct scsi_tape * STp, int forward)
{
struct st_request *SRpnt;
unsigned char cmd[MAX_COMMAND_SIZE];
- int ret;
cmd[0] = SPACE;
cmd[1] = 0x01; /* Space FileMarks */
@@ -641,26 +665,20 @@ static int cross_eof(struct scsi_tape * STp, int forward)
DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n",
tape_name(STp), forward ? "forward" : "backward"));
- SRpnt = st_allocate_request(STp);
+ SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
+ STp->device->request_queue->rq_timeout,
+ MAX_RETRIES, 1);
if (!SRpnt)
- return STp->buffer->syscall_result;
-
- ret = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0,
- STp->device->request_queue->rq_timeout,
- MAX_RETRIES);
- if (ret)
- goto out;
+ return (STp->buffer)->syscall_result;
- ret = STp->buffer->syscall_result;
+ st_release_request(SRpnt);
+ SRpnt = NULL;
if ((STp->buffer)->cmdstat.midlevel_result != 0)
printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",
tape_name(STp), forward ? "forward" : "backward");
-out:
- st_release_request(SRpnt);
-
- return ret;
+ return (STp->buffer)->syscall_result;
}
@@ -881,24 +899,21 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
int attentions, waits, max_wait, scode;
int retval = CHKRES_READY, new_session = 0;
unsigned char cmd[MAX_COMMAND_SIZE];
- struct st_request *SRpnt;
+ struct st_request *SRpnt = NULL;
struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat;
- SRpnt = st_allocate_request(STp);
- if (!SRpnt)
- return STp->buffer->syscall_result;
-
max_wait = do_wait ? ST_BLOCK_SECONDS : 0;
for (attentions=waits=0; ; ) {
memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
cmd[0] = TEST_UNIT_READY;
+ SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
+ STp->long_timeout, MAX_READY_RETRIES, 1);
- retval = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0,
- STp->long_timeout,
- MAX_READY_RETRIES);
- if (retval)
+ if (!SRpnt) {
+ retval = (STp->buffer)->syscall_result;
break;
+ }
if (cmdstatp->have_sense) {
@@ -942,8 +957,8 @@ static int test_ready(struct scsi_tape *STp, int do_wait)
break;
}
- st_release_request(SRpnt);
-
+ if (SRpnt != NULL)
+ st_release_request(SRpnt);
return retval;
}
@@ -1020,24 +1035,17 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
}
}
- SRpnt = st_allocate_request(STp);
- if (!SRpnt) {
- retval = STp->buffer->syscall_result;
- goto err_out;
- }
-
if (STp->omit_blklims)
STp->min_block = STp->max_block = (-1);
else {
memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);
cmd[0] = READ_BLOCK_LIMITS;
- retval = st_scsi_kern_execute(SRpnt, cmd, DMA_FROM_DEVICE,
- STp->buffer->b_data, 6,
- STp->device->request_queue->rq_timeout,
- MAX_READY_RETRIES);
- if (retval) {
- st_release_request(SRpnt);
+ SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, DMA_FROM_DEVICE,
+ STp->device->request_queue->rq_timeout,
+ MAX_READY_RETRIES, 1);
+ if (!SRpnt) {
+ retval = (STp->buffer)->syscall_result;
goto err_out;
}
@@ -1061,12 +1069,11 @@ static int check_tape(struct scsi_tape *STp, struct file *filp)
cmd[0] = MODE_SENSE;
cmd[4] = 12;
- retval = st_scsi_kern_execute(SRpnt, cmd, DMA_FROM_DEVICE,
- STp->buffer->b_data, 12,
- STp->device->request_queue->rq_timeout,
- MAX_READY_RETRIES);
- if (retval) {
- st_release_request(SRpnt);
+ SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, DMA_FROM_DEVICE,
+ STp->device->request_queue->rq_timeout,
+ MAX_READY_RETRIES, 1);
+ if (!SRpnt) {
+ retval = (STp->buffer)->syscall_result;
goto err_out;
}
@@ -1296,17 +1303,11 @@ static int st_flush(struct file *filp, fl_owner_t id)
cmd[0] = WRITE_FILEMARKS;
cmd[4] = 1 + STp->two_fm;
- SRpnt = st_allocate_request(STp);
+ SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
+ STp->device->request_queue->rq_timeout,
+ MAX_WRITE_RETRIES, 1);
if (!SRpnt) {
- result = STp->buffer->syscall_result;
- goto out;
- }
-
- result = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0,
- STp->device->request_queue->rq_timeout,
- MAX_WRITE_RETRIES);
- if (result) {
- st_release_request(SRpnt);
+ result = (STp->buffer)->syscall_result;
goto out;
}
@@ -1471,8 +1472,8 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
if (i && ((unsigned long)buf & queue_dma_alignment(
STp->device->request_queue)) == 0) {
- i = sgl_map_user_pages(&(STbp->sg[0]), STbp->use_sg,
- (unsigned long)buf, count, (is_read ? READ : WRITE));
+ i = sgl_map_user_pages(STbp, STbp->use_sg, (unsigned long)buf,
+ count, (is_read ? READ : WRITE));
if (i > 0) {
STbp->do_dio = i;
STbp->buffer_bytes = 0; /* can be used as transfer counter */
@@ -1480,7 +1481,6 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf,
else
STbp->do_dio = 0; /* fall back to buffering with any error */
STbp->sg_segs = STbp->do_dio;
- STbp->frp_sg_current = 0;
DEB(
if (STbp->do_dio) {
STp->nbr_dio++;
@@ -1526,7 +1526,7 @@ static void release_buffering(struct scsi_tape *STp, int is_read)
STbp = STp->buffer;
if (STbp->do_dio) {
- sgl_unmap_user_pages(&(STbp->sg[0]), STbp->do_dio, is_read);
+ sgl_unmap_user_pages(STbp, STbp->do_dio, is_read);
STbp->do_dio = 0;
STbp->sg_segs = 0;
}
@@ -2372,7 +2372,6 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
{
unsigned char cmd[MAX_COMMAND_SIZE];
struct st_request *SRpnt;
- int ret;
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SENSE;
@@ -2381,17 +2380,14 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
cmd[2] = page;
cmd[4] = 255;
- SRpnt = st_allocate_request(STp);
- if (!SRpnt)
- return STp->buffer->syscall_result;
+ SRpnt = st_do_scsi(NULL, STp, cmd, cmd[4], DMA_FROM_DEVICE,
+ STp->device->request_queue->rq_timeout, 0, 1);
+ if (SRpnt == NULL)
+ return (STp->buffer)->syscall_result;
- ret = st_scsi_kern_execute(SRpnt, cmd, DMA_FROM_DEVICE,
- STp->buffer->b_data, cmd[4],
- STp->device->request_queue->rq_timeout,
- MAX_RETRIES);
st_release_request(SRpnt);
- return ret ? : STp->buffer->syscall_result;
+ return STp->buffer->syscall_result;
}
@@ -2399,9 +2395,10 @@ static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs)
in the buffer is correctly formatted. The long timeout is used if slow is non-zero. */
static int write_mode_page(struct scsi_tape *STp, int page, int slow)
{
- int pgo, timeout, ret = 0;
+ int pgo;
unsigned char cmd[MAX_COMMAND_SIZE];
struct st_request *SRpnt;
+ int timeout;
memset(cmd, 0, MAX_COMMAND_SIZE);
cmd[0] = MODE_SELECT;
@@ -2415,21 +2412,16 @@ static int write_mode_page(struct scsi_tape *STp, int page, int slow)
(STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP;
(STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR;
- SRpnt = st_allocate_request(STp);
- if (!SRpnt)
- return ret;
-
- timeout = slow ? STp->long_timeout :
- STp->device->request_queue->rq_timeout;
-
- ret = st_scsi_kern_execute(SRpnt, cmd, DMA_TO_DEVICE,
- STp->buffer->b_data, cmd[4], timeout, 0);
- if (!ret)
- ret = STp->buffer->syscall_result;
+ timeout = slow ?
+ STp->long_timeout : STp->device->request_queue->rq_timeout;
+ SRpnt = st_do_scsi(NULL, STp, cmd, cmd[4], DMA_TO_DEVICE,
+ timeout, 0, 1);
+ if (SRpnt == NULL)
+ return (STp->buffer)->syscall_result;
st_release_request(SRpnt);
- return ret;
+ return STp->buffer->syscall_result;
}
@@ -2547,16 +2539,13 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
printk(ST_DEB_MSG "%s: Loading tape.\n", name);
);
- SRpnt = st_allocate_request(STp);
+ SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE,
+ timeout, MAX_RETRIES, 1);
if (!SRpnt)
- return STp->buffer->syscall_result;
-
- retval = st_scsi_kern_execute(SRpnt, cmd, DMA_NONE, NULL, 0, timeout,
- MAX_RETRIES);
- if (retval)
- goto out;
+ return (STp->buffer)->syscall_result;
retval = (STp->buffer)->syscall_result;
+ st_release_request(SRpnt);
if (!retval) { /* SCSI command successful */
@@ -2575,8 +2564,6 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod
STps = &(STp->ps[STp->partition]);
STps->drv_file = STps->drv_block = (-1);
}
-out:
- st_release_request(SRpnt);
return retval;
}
@@ -2852,15 +2839,12 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
return (-ENOSYS);
}
- SRpnt = st_allocate_request(STp);
+ SRpnt = st_do_scsi(NULL, STp, cmd, datalen, direction,
+ timeout, MAX_RETRIES, 1);
if (!SRpnt)
return (STp->buffer)->syscall_result;
- ioctl_result = st_scsi_kern_execute(SRpnt, cmd, direction,
- STp->buffer->b_data, datalen,
- timeout, MAX_RETRIES);
- if (!ioctl_result)
- ioctl_result = (STp->buffer)->syscall_result;
+ ioctl_result = (STp->buffer)->syscall_result;
if (!ioctl_result) { /* SCSI command successful */
st_release_request(SRpnt);
@@ -3022,17 +3006,11 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
if (!logical && !STp->scsi2_logical)
scmd[1] = 1;
}
-
- SRpnt = st_allocate_request(STp);
+ SRpnt = st_do_scsi(NULL, STp, scmd, 20, DMA_FROM_DEVICE,
+ STp->device->request_queue->rq_timeout,
+ MAX_READY_RETRIES, 1);
if (!SRpnt)
- return STp->buffer->syscall_result;
-
- result = st_scsi_kern_execute(SRpnt, scmd, DMA_FROM_DEVICE,
- STp->buffer->b_data, 20,
- STp->device->request_queue->rq_timeout,
- MAX_READY_RETRIES);
- if (result)
- goto out;
+ return (STp->buffer)->syscall_result;
if ((STp->buffer)->syscall_result != 0 ||
(STp->device->scsi_level >= SCSI_2 &&
@@ -3060,7 +3038,6 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti
DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name,
*block, *partition));
}
-out:
st_release_request(SRpnt);
SRpnt = NULL;
@@ -3135,14 +3112,10 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
timeout = STp->device->request_queue->rq_timeout;
}
- SRpnt = st_allocate_request(STp);
+ SRpnt = st_do_scsi(NULL, STp, scmd, 0, DMA_NONE,
+ timeout, MAX_READY_RETRIES, 1);
if (!SRpnt)
- return STp->buffer->syscall_result;
-
- result = st_scsi_kern_execute(SRpnt, scmd, DMA_NONE, NULL, 0,
- timeout, MAX_READY_RETRIES);
- if (result)
- goto out;
+ return (STp->buffer)->syscall_result;
STps->drv_block = STps->drv_file = (-1);
STps->eof = ST_NOEOF;
@@ -3167,7 +3140,7 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
STps->drv_block = STps->drv_file = 0;
result = 0;
}
-out:
+
st_release_request(SRpnt);
SRpnt = NULL;
@@ -3696,38 +3669,34 @@ static long st_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a
/* Try to allocate a new tape buffer. Calling function must not hold
dev_arr_lock. */
-static struct st_buffer *
- new_tape_buffer(int from_initialization, int need_dma, int max_sg)
+static struct st_buffer *new_tape_buffer(int need_dma, int max_sg)
{
- int i, got = 0;
- gfp_t priority;
struct st_buffer *tb;
- if (from_initialization)
- priority = GFP_ATOMIC;
- else
- priority = GFP_KERNEL;
-
- i = sizeof(struct st_buffer) + (max_sg - 1) * sizeof(struct scatterlist) +
- max_sg * sizeof(struct st_buf_fragment);
- tb = kzalloc(i, priority);
+ tb = kzalloc(sizeof(struct st_buffer), GFP_ATOMIC);
if (!tb) {
printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n");
return NULL;
}
- tb->frp_segs = tb->orig_frp_segs = 0;
+ tb->frp_segs = 0;
tb->use_sg = max_sg;
- tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg);
-
tb->dma = need_dma;
- tb->buffer_size = got;
- sg_init_table(tb->sg, max_sg);
+ tb->buffer_size = 0;
+
+ tb->reserved_pages = kzalloc(max_sg * sizeof(struct page *),
+ GFP_ATOMIC);
+ if (!tb->reserved_pages) {
+ kfree(tb);
+ return NULL;
+ }
return tb;
}
/* Try to allocate enough space in the tape buffer */
+#define ST_MAX_ORDER 6
+
static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dma)
{
int segs, nbr, max_segs, b_size, order, got;
@@ -3747,33 +3716,45 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm
priority = GFP_KERNEL | __GFP_NOWARN;
if (need_dma)
priority |= GFP_DMA;
- for (b_size = PAGE_SIZE, order=0; order <= 6 &&
- b_size < new_size - STbuffer->buffer_size;
- order++, b_size *= 2)
- ; /* empty */
+
+ if (STbuffer->cleared)
+ priority |= __GFP_ZERO;
+
+ if (STbuffer->frp_segs) {
+ order = STbuffer->map_data.page_order;
+ b_size = PAGE_SIZE << order;
+ } else {
+ for (b_size = PAGE_SIZE, order = 0;
+ order < ST_MAX_ORDER && b_size < new_size;
+ order++, b_size *= 2)
+ ; /* empty */
+ }
+ if (max_segs * (PAGE_SIZE << order) < new_size) {
+ if (order == ST_MAX_ORDER)
+ return 0;
+ normalize_buffer(STbuffer);
+ return enlarge_buffer(STbuffer, new_size, need_dma);
+ }
for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size;
segs < max_segs && got < new_size;) {
- STbuffer->frp[segs].page = alloc_pages(priority, order);
- if (STbuffer->frp[segs].page == NULL) {
- if (new_size - got <= (max_segs - segs) * b_size / 2) {
- b_size /= 2; /* Large enough for the rest of the buffers */
- order--;
- continue;
- }
+ struct page *page;
+
+ page = alloc_pages(priority, order);
+ if (!page) {
DEB(STbuffer->buffer_size = got);
normalize_buffer(STbuffer);
return 0;
}
- STbuffer->frp[segs].length = b_size;
+
STbuffer->frp_segs += 1;
got += b_size;
STbuffer->buffer_size = got;
- if (STbuffer->cleared)
- memset(page_address(STbuffer->frp[segs].page), 0, b_size);
+ STbuffer->reserved_pages[segs] = page;
segs++;
}
- STbuffer->b_data = page_address(STbuffer->frp[0].page);
+ STbuffer->b_data = page_address(STbuffer->reserved_pages[0]);
+ STbuffer->map_data.page_order = order;
return 1;
}
@@ -3785,7 +3766,8 @@ static void clear_buffer(struct st_buffer * st_bp)
int i;
for (i=0; i < st_bp->frp_segs; i++)
- memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length);
+ memset(page_address(st_bp->reserved_pages[i]), 0,
+ PAGE_SIZE << st_bp->map_data.page_order);
st_bp->cleared = 1;
}
@@ -3793,16 +3775,16 @@ static void clear_buffer(struct st_buffer * st_bp)
/* Release the extra buffer */
static void normalize_buffer(struct st_buffer * STbuffer)
{
- int i, order;
+ int i, order = STbuffer->map_data.page_order;
- for (i = STbuffer->orig_frp_segs; i < STbuffer->frp_segs; i++) {
- order = get_order(STbuffer->frp[i].length);
- __free_pages(STbuffer->frp[i].page, order);
- STbuffer->buffer_size -= STbuffer->frp[i].length;
+ for (i = 0; i < STbuffer->frp_segs; i++) {
+ __free_pages(STbuffer->reserved_pages[i], order);
+ STbuffer->buffer_size -= (PAGE_SIZE << order);
}
- STbuffer->frp_segs = STbuffer->orig_frp_segs;
- STbuffer->frp_sg_current = 0;
+ STbuffer->frp_segs = 0;
STbuffer->sg_segs = 0;
+ STbuffer->map_data.page_order = 0;
+ STbuffer->map_data.offset = 0;
}
@@ -3811,18 +3793,19 @@ static void normalize_buffer(struct st_buffer * STbuffer)
static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, int do_count)
{
int i, cnt, res, offset;
+ int length = PAGE_SIZE << st_bp->map_data.page_order;
for (i = 0, offset = st_bp->buffer_bytes;
- i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
- offset -= st_bp->frp[i].length;
+ i < st_bp->frp_segs && offset >= length; i++)
+ offset -= length;
if (i == st_bp->frp_segs) { /* Should never happen */
printk(KERN_WARNING "st: append_to_buffer offset overflow.\n");
return (-EIO);
}
for (; i < st_bp->frp_segs && do_count > 0; i++) {
- cnt = st_bp->frp[i].length - offset < do_count ?
- st_bp->frp[i].length - offset : do_count;
- res = copy_from_user(page_address(st_bp->frp[i].page) + offset, ubp, cnt);
+ struct page *page = st_bp->reserved_pages[i];
+ cnt = length - offset < do_count ? length - offset : do_count;
+ res = copy_from_user(page_address(page) + offset, ubp, cnt);
if (res)
return (-EFAULT);
do_count -= cnt;
@@ -3842,18 +3825,19 @@ static int append_to_buffer(const char __user *ubp, struct st_buffer * st_bp, in
static int from_buffer(struct st_buffer * st_bp, char __user *ubp, int do_count)
{
int i, cnt, res, offset;
+ int length = PAGE_SIZE << st_bp->map_data.page_order;
for (i = 0, offset = st_bp->read_pointer;
- i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
- offset -= st_bp->frp[i].length;
+ i < st_bp->frp_segs && offset >= length; i++)
+ offset -= length;
if (i == st_bp->frp_segs) { /* Should never happen */
printk(KERN_WARNING "st: from_buffer offset overflow.\n");
return (-EIO);
}
for (; i < st_bp->frp_segs && do_count > 0; i++) {
- cnt = st_bp->frp[i].length - offset < do_count ?
- st_bp->frp[i].length - offset : do_count;
- res = copy_to_user(ubp, page_address(st_bp->frp[i].page) + offset, cnt);
+ struct page *page = st_bp->reserved_pages[i];
+ cnt = length - offset < do_count ? length - offset : do_count;
+ res = copy_to_user(ubp, page_address(page) + offset, cnt);
if (res)
return (-EFAULT);
do_count -= cnt;
@@ -3874,6 +3858,7 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset)
{
int src_seg, dst_seg, src_offset = 0, dst_offset;
int count, total;
+ int length = PAGE_SIZE << st_bp->map_data.page_order;
if (offset == 0)
return;
@@ -3881,24 +3866,26 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset)
total=st_bp->buffer_bytes - offset;
for (src_seg=0; src_seg < st_bp->frp_segs; src_seg++) {
src_offset = offset;
- if (src_offset < st_bp->frp[src_seg].length)
+ if (src_offset < length)
break;
- offset -= st_bp->frp[src_seg].length;
+ offset -= length;
}
st_bp->buffer_bytes = st_bp->read_pointer = total;
for (dst_seg=dst_offset=0; total > 0; ) {
- count = min(st_bp->frp[dst_seg].length - dst_offset,
- st_bp->frp[src_seg].length - src_offset);
- memmove(page_address(st_bp->frp[dst_seg].page) + dst_offset,
- page_address(st_bp->frp[src_seg].page) + src_offset, count);
+ struct page *dpage = st_bp->reserved_pages[dst_seg];
+ struct page *spage = st_bp->reserved_pages[src_seg];
+
+ count = min(length - dst_offset, length - src_offset);
+ memmove(page_address(dpage) + dst_offset,
+ page_address(spage) + src_offset, count);
src_offset += count;
- if (src_offset >= st_bp->frp[src_seg].length) {
+ if (src_offset >= length) {
src_seg++;
src_offset = 0;
}
dst_offset += count;
- if (dst_offset >= st_bp->frp[dst_seg].length) {
+ if (dst_offset >= length) {
dst_seg++;
dst_offset = 0;
}
@@ -3906,32 +3893,6 @@ static void move_buffer_data(struct st_buffer * st_bp, int offset)
}
}
-
-/* Fill the s/g list up to the length required for this transfer */
-static void buf_to_sg(struct st_buffer *STbp, unsigned int length)
-{
- int i;
- unsigned int count;
- struct scatterlist *sg;
- struct st_buf_fragment *frp;
-
- if (length == STbp->frp_sg_current)
- return; /* work already done */
-
- sg = &(STbp->sg[0]);
- frp = STbp->frp;
- for (i=count=0; count < length; i++) {
- if (length - count > frp[i].length)
- sg_set_page(&sg[i], frp[i].page, frp[i].length, 0);
- else
- sg_set_page(&sg[i], frp[i].page, length - count, 0);
- count += sg[i].length;
- }
- STbp->sg_segs = i;
- STbp->frp_sg_current = length;
-}
-
-
/* Validate the options from command line or module parameters */
static void validate_options(void)
{
@@ -4026,7 +3987,7 @@ static int st_probe(struct device *dev)
SDp->request_queue->max_phys_segments);
if (st_max_sg_segs < i)
i = st_max_sg_segs;
- buffer = new_tape_buffer(1, (SDp->host)->unchecked_isa_dma, i);
+ buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i);
if (buffer == NULL) {
printk(KERN_ERR
"st: Can't allocate new tape buffer. Device not attached.\n");
@@ -4280,8 +4241,8 @@ static void scsi_tape_release(struct kref *kref)
tpnt->device = NULL;
if (tpnt->buffer) {
- tpnt->buffer->orig_frp_segs = 0;
normalize_buffer(tpnt->buffer);
+ kfree(tpnt->buffer->reserved_pages);
kfree(tpnt->buffer);
}
@@ -4567,14 +4528,16 @@ out:
}
/* The following functions may be useful for a larger audience. */
-static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages,
- unsigned long uaddr, size_t count, int rw)
+static int sgl_map_user_pages(struct st_buffer *STbp,
+ const unsigned int max_pages, unsigned long uaddr,
+ size_t count, int rw)
{
unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long start = uaddr >> PAGE_SHIFT;
const int nr_pages = end - start;
int res, i, j;
struct page **pages;
+ struct rq_map_data *mdata = &STbp->map_data;
/* User attempted Overflow! */
if ((uaddr + count) < uaddr)
@@ -4616,24 +4579,11 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa
flush_dcache_page(pages[i]);
}
- /* Populate the scatter/gather list */
- sg_set_page(&sgl[0], pages[0], 0, uaddr & ~PAGE_MASK);
- if (nr_pages > 1) {
- sgl[0].length = PAGE_SIZE - sgl[0].offset;
- count -= sgl[0].length;
- for (i=1; i < nr_pages ; i++) {
- sg_set_page(&sgl[i], pages[i],
- count < PAGE_SIZE ? count : PAGE_SIZE, 0);;
- count -= PAGE_SIZE;
- }
- }
- else {
- sgl[0].length = count;
- }
+ mdata->offset = uaddr & ~PAGE_MASK;
+ mdata->page_order = 0;
+ STbp->mapped_pages = pages;
- kfree(pages);
return nr_pages;
-
out_unmap:
if (res > 0) {
for (j=0; j < res; j++)
@@ -4646,13 +4596,13 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa
/* And unmap them... */
-static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages,
- int dirtied)
+static int sgl_unmap_user_pages(struct st_buffer *STbp,
+ const unsigned int nr_pages, int dirtied)
{
int i;
for (i=0; i < nr_pages; i++) {
- struct page *page = sg_page(&sgl[i]);
+ struct page *page = STbp->mapped_pages[i];
if (dirtied)
SetPageDirty(page);
@@ -4661,6 +4611,8 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p
*/
page_cache_release(page);
}
+ kfree(STbp->mapped_pages);
+ STbp->mapped_pages = NULL;
return 0;
}
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index b92712f95931..544dc6b1f548 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -29,6 +29,7 @@ struct st_request {
int result;
struct scsi_tape *stp;
struct completion *waiting;
+ struct bio *bio;
};
/* The tape buffer descriptor. */
@@ -44,20 +45,13 @@ struct st_buffer {
int syscall_result;
struct st_request *last_SRpnt;
struct st_cmdstatus cmdstat;
+ struct page **reserved_pages;
+ struct page **mapped_pages;
+ struct rq_map_data map_data;
unsigned char *b_data;
unsigned short use_sg; /* zero or max number of s/g segments for this adapter */
unsigned short sg_segs; /* number of segments in s/g list */
- unsigned short orig_frp_segs; /* number of segments allocated at first try */
unsigned short frp_segs; /* number of buffer segments */
- unsigned int frp_sg_current; /* driver buffer length currently in s/g list */
- struct st_buf_fragment *frp; /* the allocated buffer fragment list */
- struct scatterlist sg[1]; /* MUST BE last item */
-};
-
-/* The tape buffer fragment descriptor */
-struct st_buf_fragment {
- struct page *page;
- unsigned int length;
};
/* The tape mode definition */
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index 3c4a300494a4..a8d61a62522e 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -137,8 +137,8 @@ zalon_probe(struct parisc_device *dev)
goto fail;
if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) {
- printk(KERN_ERR "%s: irq problem with %d, detaching\n ",
- dev->dev.bus_id, dev->irq);
+ dev_printk(KERN_ERR, dev, "irq problem with %d, detaching\n ",
+ dev->irq);
goto fail;
}
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 303272af386e..0d934bfbdd9b 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -279,6 +279,13 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
+ [PORT_OCTEON] = {
+ .name = "OCTEON",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
+ },
};
#if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -303,16 +310,16 @@ static const u8 au_io_out_map[] = {
};
/* sane hardware needs no mapping */
-static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_AU)
+ if (p->iotype != UPIO_AU)
return offset;
return au_io_in_map[offset];
}
-static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_AU)
+ if (p->iotype != UPIO_AU)
return offset;
return au_io_out_map[offset];
}
@@ -341,16 +348,16 @@ static const u8
[UART_SCR] = 0x2c
};
-static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_RM9000)
+ if (p->iotype != UPIO_RM9000)
return offset;
return regmap_in[offset];
}
-static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_RM9000)
+ if (p->iotype != UPIO_RM9000)
return offset;
return regmap_out[offset];
}
@@ -363,108 +370,170 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
#endif
-static unsigned int serial_in(struct uart_8250_port *up, int offset)
+static unsigned int hub6_serial_in(struct uart_port *p, int offset)
{
- unsigned int tmp;
- offset = map_8250_in_reg(up, offset) << up->port.regshift;
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ return inb(p->iobase + 1);
+}
- switch (up->port.iotype) {
- case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- return inb(up->port.iobase + 1);
+static void hub6_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ outb(value, p->iobase + 1);
+}
- case UPIO_MEM:
- case UPIO_DWAPB:
- return readb(up->port.membase + offset);
+static unsigned int mem_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return readb(p->membase + offset);
+}
- case UPIO_RM9000:
- case UPIO_MEM32:
- return readl(up->port.membase + offset);
+static void mem_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ writeb(value, p->membase + offset);
+}
+
+static void mem32_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ writel(value, p->membase + offset);
+}
+
+static unsigned int mem32_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return readl(p->membase + offset);
+}
#ifdef CONFIG_SERIAL_8250_AU1X00
- case UPIO_AU:
- return __raw_readl(up->port.membase + offset);
+static unsigned int au_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return __raw_readl(p->membase + offset);
+}
+
+static void au_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ __raw_writel(value, p->membase + offset);
+}
#endif
- case UPIO_TSI:
- if (offset == UART_IIR) {
- tmp = readl(up->port.membase + (UART_IIR & ~3));
- return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
- } else
- return readb(up->port.membase + offset);
+static unsigned int tsi_serial_in(struct uart_port *p, int offset)
+{
+ unsigned int tmp;
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ if (offset == UART_IIR) {
+ tmp = readl(p->membase + (UART_IIR & ~3));
+ return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+ } else
+ return readb(p->membase + offset);
+}
- default:
- return inb(up->port.iobase + offset);
- }
+static void tsi_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+ writeb(value, p->membase + offset);
}
-static void
-serial_out(struct uart_8250_port *up, int offset, int value)
+static void dwapb_serial_out(struct uart_port *p, int offset, int value)
{
- /* Save the offset before it's remapped */
int save_offset = offset;
- offset = map_8250_out_reg(up, offset) << up->port.regshift;
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ /* Save the LCR value so it can be re-written when a
+ * Busy Detect interrupt occurs. */
+ if (save_offset == UART_LCR) {
+ struct uart_8250_port *up = (struct uart_8250_port *)p;
+ up->lcr = value;
+ }
+ writeb(value, p->membase + offset);
+ /* Read the IER to ensure any interrupt is cleared before
+ * returning from ISR. */
+ if (save_offset == UART_TX || save_offset == UART_IER)
+ value = p->serial_in(p, UART_IER);
+}
- switch (up->port.iotype) {
+static unsigned int io_serial_in(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return inb(p->iobase + offset);
+}
+
+static void io_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ outb(value, p->iobase + offset);
+}
+
+static void set_io_from_upio(struct uart_port *p)
+{
+ switch (p->iotype) {
case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- outb(value, up->port.iobase + 1);
+ p->serial_in = hub6_serial_in;
+ p->serial_out = hub6_serial_out;
break;
case UPIO_MEM:
- writeb(value, up->port.membase + offset);
+ p->serial_in = mem_serial_in;
+ p->serial_out = mem_serial_out;
break;
case UPIO_RM9000:
case UPIO_MEM32:
- writel(value, up->port.membase + offset);
+ p->serial_in = mem32_serial_in;
+ p->serial_out = mem32_serial_out;
break;
#ifdef CONFIG_SERIAL_8250_AU1X00
case UPIO_AU:
- __raw_writel(value, up->port.membase + offset);
+ p->serial_in = au_serial_in;
+ p->serial_out = au_serial_out;
break;
#endif
case UPIO_TSI:
- if (!((offset == UART_IER) && (value & UART_IER_UUE)))
- writeb(value, up->port.membase + offset);
+ p->serial_in = tsi_serial_in;
+ p->serial_out = tsi_serial_out;
break;
case UPIO_DWAPB:
- /* Save the LCR value so it can be re-written when a
- * Busy Detect interrupt occurs. */
- if (save_offset == UART_LCR)
- up->lcr = value;
- writeb(value, up->port.membase + offset);
- /* Read the IER to ensure any interrupt is cleared before
- * returning from ISR. */
- if (save_offset == UART_TX || save_offset == UART_IER)
- value = serial_in(up, UART_IER);
+ p->serial_in = mem_serial_in;
+ p->serial_out = dwapb_serial_out;
break;
default:
- outb(value, up->port.iobase + offset);
+ p->serial_in = io_serial_in;
+ p->serial_out = io_serial_out;
+ break;
}
}
static void
serial_out_sync(struct uart_8250_port *up, int offset, int value)
{
- switch (up->port.iotype) {
+ struct uart_port *p = &up->port;
+ switch (p->iotype) {
case UPIO_MEM:
case UPIO_MEM32:
#ifdef CONFIG_SERIAL_8250_AU1X00
case UPIO_AU:
#endif
case UPIO_DWAPB:
- serial_out(up, offset, value);
- serial_in(up, UART_LCR); /* safe, no side-effects */
+ p->serial_out(p, offset, value);
+ p->serial_in(p, UART_LCR); /* safe, no side-effects */
break;
default:
- serial_out(up, offset, value);
+ p->serial_out(p, offset, value);
}
}
+#define serial_in(up, offset) \
+ (up->port.serial_in(&(up)->port, (offset)))
+#define serial_out(up, offset, value) \
+ (up->port.serial_out(&(up)->port, (offset), (value)))
/*
* We used to support using pause I/O for certain machines. We
* haven't supported this for a while, but just in case it's badly
@@ -2576,6 +2645,7 @@ static void __init serial8250_isa_init_ports(void)
up->port.membase = old_serial_port[i].iomem_base;
up->port.iotype = old_serial_port[i].io_type;
up->port.regshift = old_serial_port[i].iomem_reg_shift;
+ set_io_from_upio(&up->port);
if (share_irqs)
up->port.flags |= UPF_SHARE_IRQ;
}
@@ -2752,12 +2822,32 @@ static struct uart_driver serial8250_reg = {
*/
int __init early_serial_setup(struct uart_port *port)
{
+ struct uart_port *p;
+
if (port->line >= ARRAY_SIZE(serial8250_ports))
return -ENODEV;
serial8250_isa_init_ports();
- serial8250_ports[port->line].port = *port;
- serial8250_ports[port->line].port.ops = &serial8250_pops;
+ p = &serial8250_ports[port->line].port;
+ p->iobase = port->iobase;
+ p->membase = port->membase;
+ p->irq = port->irq;
+ p->uartclk = port->uartclk;
+ p->fifosize = port->fifosize;
+ p->regshift = port->regshift;
+ p->iotype = port->iotype;
+ p->flags = port->flags;
+ p->mapbase = port->mapbase;
+ p->private_data = port->private_data;
+ p->type = port->type;
+ p->line = port->line;
+
+ set_io_from_upio(p);
+ if (port->serial_in)
+ p->serial_in = port->serial_in;
+ if (port->serial_out)
+ p->serial_out = port->serial_out;
+
return 0;
}
@@ -2822,6 +2912,9 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.mapbase = p->mapbase;
port.hub6 = p->hub6;
port.private_data = p->private_data;
+ port.type = p->type;
+ port.serial_in = p->serial_in;
+ port.serial_out = p->serial_out;
port.dev = &dev->dev;
if (share_irqs)
port.flags |= UPF_SHARE_IRQ;
@@ -2976,6 +3069,20 @@ int serial8250_register_port(struct uart_port *port)
if (port->dev)
uart->port.dev = port->dev;
+ if (port->flags & UPF_FIXED_TYPE) {
+ uart->port.type = port->type;
+ uart->port.fifosize = uart_config[port->type].fifo_size;
+ uart->capabilities = uart_config[port->type].flags;
+ uart->tx_loadsz = uart_config[port->type].tx_loadsz;
+ }
+
+ set_io_from_upio(&uart->port);
+ /* Possibly override default I/O functions. */
+ if (port->serial_in)
+ uart->port.serial_in = port->serial_in;
+ if (port->serial_out)
+ uart->port.serial_out = port->serial_out;
+
ret = uart_add_one_port(&serial8250_reg, &uart->port);
if (ret == 0)
ret = uart->port.line;
@@ -3018,7 +3125,7 @@ static int __init serial8250_init(void)
if (nr_uarts > UART_NR)
nr_uarts = UART_NR;
- printk(KERN_INFO "Serial: 8250/16550 driver"
+ printk(KERN_INFO "Serial: 8250/16550 driver, "
"%d ports, IRQ sharing %sabled\n", nr_uarts,
share_irqs ? "en" : "dis");
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 5450a0e5ecdb..536d8e510f66 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -42,7 +42,8 @@ struct pci_serial_quirk {
u32 subvendor;
u32 subdevice;
int (*init)(struct pci_dev *dev);
- int (*setup)(struct serial_private *, struct pciserial_board *,
+ int (*setup)(struct serial_private *,
+ const struct pciserial_board *,
struct uart_port *, int);
void (*exit)(struct pci_dev *dev);
};
@@ -107,7 +108,7 @@ setup_port(struct serial_private *priv, struct uart_port *port,
* ADDI-DATA GmbH communication cards <info@addi-data.com>
*/
static int addidata_apci7800_setup(struct serial_private *priv,
- struct pciserial_board *board,
+ const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
@@ -134,7 +135,7 @@ static int addidata_apci7800_setup(struct serial_private *priv,
* Not that ugly ;) -- HW
*/
static int
-afavlab_setup(struct serial_private *priv, struct pciserial_board *board,
+afavlab_setup(struct serial_private *priv, const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -188,8 +189,9 @@ static int pci_hp_diva_init(struct pci_dev *dev)
* some serial ports are supposed to be hidden on certain models.
*/
static int
-pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board,
- struct uart_port *port, int idx)
+pci_hp_diva_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
{
unsigned int offset = board->first_offset;
unsigned int bar = FL_GET_BASE(board->flags);
@@ -306,7 +308,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */
static int
-sbs_setup(struct serial_private *priv, struct pciserial_board *board,
+sbs_setup(struct serial_private *priv, const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -463,7 +465,7 @@ static int pci_siig_init(struct pci_dev *dev)
}
static int pci_siig_setup(struct serial_private *priv,
- struct pciserial_board *board,
+ const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0;
@@ -534,7 +536,8 @@ static int pci_timedia_init(struct pci_dev *dev)
* Ugh, this is ugly as all hell --- TYT
*/
static int
-pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board,
+pci_timedia_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar = 0, offset = board->first_offset;
@@ -568,7 +571,7 @@ pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board,
*/
static int
titan_400l_800l_setup(struct serial_private *priv,
- struct pciserial_board *board,
+ const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset;
@@ -599,6 +602,10 @@ static int pci_netmos_init(struct pci_dev *dev)
/* subdevice 0x00PS means <P> parallel, <S> serial */
unsigned int num_serial = dev->subsystem_device & 0xf;
+ if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
+ dev->subsystem_device == 0x0299)
+ return 0;
+
if (num_serial == 0)
return -ENODEV;
return num_serial;
@@ -737,8 +744,41 @@ static void __devexit pci_ite887x_exit(struct pci_dev *dev)
release_region(ioport, ITE_887x_IOSIZE);
}
+/*
+ * Oxford Semiconductor Inc.
+ * Check that device is part of the Tornado range of devices, then determine
+ * the number of ports available on the device.
+ */
+static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+{
+ u8 __iomem *p;
+ unsigned long deviceID;
+ unsigned int number_uarts = 0;
+
+ /* OxSemi Tornado devices are all 0xCxxx */
+ if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
+ (dev->device & 0xF000) != 0xC000)
+ return 0;
+
+ p = pci_iomap(dev, 0, 5);
+ if (p == NULL)
+ return -ENOMEM;
+
+ deviceID = ioread32(p);
+ /* Tornado device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+ printk(KERN_DEBUG
+ "%d ports detected on Oxford PCI Express device\n",
+ number_uarts);
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+}
+
static int
-pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
+pci_default_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar, offset = board->first_offset, maxnr;
@@ -766,6 +806,8 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
#define PCI_SUBDEVICE_ID_OCTPRO422 0x0208
#define PCI_SUBDEVICE_ID_POCTAL232 0x0308
#define PCI_SUBDEVICE_ID_POCTAL422 0x0408
+#define PCI_VENDOR_ID_ADVANTECH 0x13fe
+#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@@ -1018,6 +1060,25 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.setup = pci_default_setup,
},
/*
+ * For Oxford Semiconductor and Mainpine
+ */
+ {
+ .vendor = PCI_VENDOR_ID_OXSEMI,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_MAINPINE,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ /*
* Default "match everything" terminator entry
*/
{
@@ -1048,7 +1109,7 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
}
static inline int get_pci_irq(struct pci_dev *dev,
- struct pciserial_board *board)
+ const struct pciserial_board *board)
{
if (board->flags & FL_NOIRQ)
return 0;
@@ -1843,8 +1904,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
}
static inline int
-serial_pci_matches(struct pciserial_board *board,
- struct pciserial_board *guessed)
+serial_pci_matches(const struct pciserial_board *board,
+ const struct pciserial_board *guessed)
{
return
board->num_ports == guessed->num_ports &&
@@ -1854,54 +1915,14 @@ serial_pci_matches(struct pciserial_board *board,
board->first_offset == guessed->first_offset;
}
-/*
- * Oxford Semiconductor Inc.
- * Check that device is part of the Tornado range of devices, then determine
- * the number of ports available on the device.
- */
-static int pci_oxsemi_tornado_init(struct pci_dev *dev, struct pciserial_board *board)
-{
- u8 __iomem *p;
- unsigned long deviceID;
- unsigned int number_uarts;
-
- /* OxSemi Tornado devices are all 0xCxxx */
- if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
- (dev->device & 0xF000) != 0xC000)
- return 0;
-
- p = pci_iomap(dev, 0, 5);
- if (p == NULL)
- return -ENOMEM;
-
- deviceID = ioread32(p);
- /* Tornado device */
- if (deviceID == 0x07000200) {
- number_uarts = ioread8(p + 4);
- board->num_ports = number_uarts;
- printk(KERN_DEBUG
- "%d ports detected on Oxford PCI Express device\n",
- number_uarts);
- }
- pci_iounmap(dev, p);
- return 0;
-}
-
struct serial_private *
-pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)
+pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
{
struct uart_port serial_port;
struct serial_private *priv;
struct pci_serial_quirk *quirk;
int rc, nr_ports, i;
- /*
- * Find number of ports on board
- */
- if (dev->vendor == PCI_VENDOR_ID_OXSEMI ||
- dev->vendor == PCI_VENDOR_ID_MAINPINE)
- pci_oxsemi_tornado_init(dev, board);
-
nr_ports = board->num_ports;
/*
@@ -2028,7 +2049,8 @@ static int __devinit
pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
{
struct serial_private *priv;
- struct pciserial_board *board, tmp;
+ const struct pciserial_board *board;
+ struct pciserial_board tmp;
int rc;
if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
@@ -2055,7 +2077,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
* We matched one of our class entries. Try to
* determine the parameters of this board.
*/
- rc = serial_pci_guess_board(dev, board);
+ rc = serial_pci_guess_board(dev, &tmp);
if (rc)
goto disable;
} else {
@@ -2132,6 +2154,10 @@ static int pciserial_resume_one(struct pci_dev *dev)
#endif
static struct pci_device_id serial_pci_tbl[] = {
+ /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */
+ { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
+ PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
+ pbn_b2_8_921600 },
{ PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0,
@@ -2271,6 +2297,9 @@ static struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b2_8_115200 },
+ { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b2_8_460800 },
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b2_8_115200 },
@@ -2372,6 +2401,9 @@ static struct pci_device_id serial_pci_tbl[] = {
* For now just used the hex ID 0x950a.
*/
{ PCI_VENDOR_ID_OXSEMI, 0x950a,
+ PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0,
+ pbn_b0_2_115200 },
+ { PCI_VENDOR_ID_OXSEMI, 0x950a,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_2_1130000 },
{ PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954,
@@ -3074,6 +3106,10 @@ static struct pci_device_id serial_pci_tbl[] = {
0,
pbn_b0_8_115200 },
+ { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+ PCI_VENDOR_ID_IBM, 0x0299,
+ 0, 0, pbn_b0_bt_2_115200 },
+
/*
* These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index fde7f9ccf57e..bbcfc26a3b6d 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -270,6 +270,8 @@ static const struct pnp_device_id pnp_dev_table[] = {
{ "RSS0250", 0 },
/* SupraExpress 28.8 Data/Fax PnP modem */
{ "SUP1310", 0 },
+ /* SupraExpress 336i PnP Voice Modem */
+ { "SUP1381", 0 },
/* SupraExpress 33.6 Data/Fax PnP modem */
{ "SUP1421", 0 },
/* SupraExpress 33.6 Data/Fax PnP modem */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index b695ab3142d8..7d7f576da202 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -457,7 +457,7 @@ config SERIAL_SAMSUNG
config SERIAL_SAMSUNG_UARTS
int
- depends on SERIAL_SAMSUNG
+ depends on ARM && PLAT_S3C
default 2 if ARCH_S3C2400
default 4 if ARCH_S3C64XX || CPU_S3C2443
default 3
@@ -982,7 +982,7 @@ config SERIAL_SH_SCI_CONSOLE
config SERIAL_PNX8XXX
bool "Enable PNX8XXX SoCs' UART Support"
- depends on MIPS && SOC_PNX8550
+ depends on MIPS && (SOC_PNX8550 || SOC_PNX833X)
select SERIAL_CORE
help
If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
@@ -1320,13 +1320,30 @@ config SERIAL_NETX_CONSOLE
config SERIAL_OF_PLATFORM
tristate "Serial port on Open Firmware platform bus"
depends on PPC_OF
- depends on SERIAL_8250
+ depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
help
If you have a PowerPC based system that has serial ports
on a platform specific bus, you should enable this option.
Currently, only 8250 compatible ports are supported, but
others can easily be added.
+config SERIAL_OF_PLATFORM_NWPSERIAL
+ tristate "NWP serial port driver"
+ depends on PPC_OF && PPC_DCR
+ select SERIAL_OF_PLATFORM
+ select SERIAL_CORE_CONSOLE
+ select SERIAL_CORE
+ help
+ This driver supports the cell network processor nwp serial
+ device.
+
+config SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
+ bool "Console on NWP serial port"
+ depends on SERIAL_OF_PLATFORM_NWPSERIAL=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Support for Console on the NWP serial ports.
+
config SERIAL_QE
tristate "Freescale QUICC Engine serial port support"
depends on QUICC_ENGINE
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index dfe775ac45b2..8844c0a03929 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
+obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index d5efd6c77904..89362d733d62 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -579,7 +579,7 @@ static void atmel_tx_dma(struct uart_port *port)
/* disable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
- if (!uart_circ_empty(xmit)) {
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
dma_sync_single_for_device(port->dev,
pdc->dma_addr,
pdc->dma_size,
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 569f0e2476c6..318d69dce8e1 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -22,7 +22,8 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
-#ifdef CONFIG_KGDB_UART
+#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
#include <linux/kgdb.h>
#include <asm/irq_regs.h>
#endif
@@ -45,6 +46,16 @@
static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS];
static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource);
+#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
+
+# ifndef CONFIG_SERIAL_BFIN_PIO
+# error KGDB only support UART in PIO mode.
+# endif
+
+static int kgdboc_port_line;
+static int kgdboc_break_enabled;
+#endif
/*
* Setup for console. Argument comes from the menuconfig
*/
@@ -62,13 +73,17 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
+static void bfin_serial_reset_irda(struct uart_port *port);
+
/*
* interrupts are disabled on entry
*/
static void bfin_serial_stop_tx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+#ifdef CONFIG_SERIAL_BFIN_DMA
struct circ_buf *xmit = &uart->port.info->xmit;
+#endif
while (!(UART_GET_LSR(uart) & TEMT))
cpu_relax();
@@ -94,6 +109,14 @@ static void bfin_serial_stop_tx(struct uart_port *port)
static void bfin_serial_start_tx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+ struct tty_struct *tty = uart->port.info->port.tty;
+
+ /*
+ * To avoid losting RX interrupt, we reset IR function
+ * before sending data.
+ */
+ if (tty->termios->c_line == N_IRDA)
+ bfin_serial_reset_irda(port);
#ifdef CONFIG_SERIAL_BFIN_DMA
if (uart->tx_done)
@@ -110,9 +133,7 @@ static void bfin_serial_start_tx(struct uart_port *port)
static void bfin_serial_stop_rx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
-#ifdef CONFIG_KGDB_UART
- if (uart->port.line != CONFIG_KGDB_UART_PORT)
-#endif
+
UART_CLEAR_IER(uart, ERBFI);
}
@@ -123,49 +144,6 @@ static void bfin_serial_enable_ms(struct uart_port *port)
{
}
-#ifdef CONFIG_KGDB_UART
-static int kgdb_entry_state;
-
-void kgdb_put_debug_char(int chr)
-{
- struct bfin_serial_port *uart;
-
- if (CONFIG_KGDB_UART_PORT < 0
- || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
- uart = &bfin_serial_ports[0];
- else
- uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
-
- while (!(UART_GET_LSR(uart) & THRE)) {
- SSYNC();
- }
-
- UART_CLEAR_DLAB(uart);
- UART_PUT_CHAR(uart, (unsigned char)chr);
- SSYNC();
-}
-
-int kgdb_get_debug_char(void)
-{
- struct bfin_serial_port *uart;
- unsigned char chr;
-
- if (CONFIG_KGDB_UART_PORT < 0
- || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS)
- uart = &bfin_serial_ports[0];
- else
- uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
-
- while(!(UART_GET_LSR(uart) & DR)) {
- SSYNC();
- }
- UART_CLEAR_DLAB(uart);
- chr = UART_GET_CHAR(uart);
- SSYNC();
-
- return chr;
-}
-#endif
#if ANOMALY_05000363 && defined(CONFIG_SERIAL_BFIN_PIO)
# define UART_GET_ANOMALY_THRESHOLD(uart) ((uart)->anomaly_threshold)
@@ -178,7 +156,7 @@ int kgdb_get_debug_char(void)
#ifdef CONFIG_SERIAL_BFIN_PIO
static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{
- struct tty_struct *tty = uart->port.info->port.tty;
+ struct tty_struct *tty = NULL;
unsigned int status, ch, flg;
static struct timeval anomaly_start = { .tv_sec = 0 };
@@ -188,27 +166,18 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
ch = UART_GET_CHAR(uart);
uart->port.icount.rx++;
-#ifdef CONFIG_KGDB_UART
- if (uart->port.line == CONFIG_KGDB_UART_PORT) {
- struct pt_regs *regs = get_irq_regs();
- if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */
- kgdb_breakkey_pressed(regs);
- return;
- } else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */
- kgdb_entry_state = 1;
- } else if (kgdb_entry_state == 1 && ch == 'q') {
- kgdb_entry_state = 0;
- kgdb_breakkey_pressed(regs);
- return;
- } else if (ch == 0x3) {/* Ctrl + C */
- kgdb_entry_state = 0;
- kgdb_breakkey_pressed(regs);
+#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
+ if (kgdb_connected && kgdboc_port_line == uart->port.line)
+ if (ch == 0x3) {/* Ctrl + C */
+ kgdb_breakpoint();
return;
- } else {
- kgdb_entry_state = 0;
}
- }
+
+ if (!uart->port.info || !uart->port.info->tty)
+ return;
#endif
+ tty = uart->port.info->tty;
if (ANOMALY_05000363) {
/* The BF533 (and BF561) family of processors have a nice anomaly
@@ -250,6 +219,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
return;
known_good_char:
+ status &= ~BI;
anomaly_start.tv_sec = 0;
}
}
@@ -445,7 +415,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
{
- int x_pos, pos;
+ int x_pos, pos, flags;
+
+ spin_lock_irqsave(&uart->port.lock, flags);
uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
@@ -463,6 +435,8 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
}
+ spin_unlock_irqrestore(&uart->port.lock, flags);
+
mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
}
@@ -497,10 +471,9 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
spin_lock(&uart->port.lock);
irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
clear_dma_irqstat(uart->rx_dma_channel);
+ bfin_serial_dma_rx_chars(uart);
spin_unlock(&uart->port.lock);
- mod_timer(&(uart->rx_dma_timer), jiffies);
-
return IRQ_HANDLED;
}
#endif
@@ -630,16 +603,16 @@ static int bfin_serial_startup(struct uart_port *port)
uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
add_timer(&(uart->rx_dma_timer));
#else
+#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
+ if (kgdboc_port_line == uart->port.line && kgdboc_break_enabled)
+ kgdboc_break_enabled = 0;
+ else {
+# endif
if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
"BFIN_UART_RX", uart)) {
-# ifdef CONFIG_KGDB_UART
- if (uart->port.line != CONFIG_KGDB_UART_PORT) {
-# endif
printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
return -EBUSY;
-# ifdef CONFIG_KGDB_UART
- }
-# endif
}
if (request_irq
@@ -685,6 +658,10 @@ static int bfin_serial_startup(struct uart_port *port)
}
}
# endif
+#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
+ }
+# endif
#endif
UART_SET_IER(uart, ERBFI);
return 0;
@@ -716,9 +693,6 @@ static void bfin_serial_shutdown(struct uart_port *port)
break;
};
#endif
-#ifdef CONFIG_KGDB_UART
- if (uart->port.line != CONFIG_KGDB_UART_PORT)
-#endif
free_irq(uart->port.irq, uart);
free_irq(uart->port.irq+1, uart);
#endif
@@ -887,6 +861,65 @@ static void bfin_serial_set_ldisc(struct uart_port *port)
}
}
+#ifdef CONFIG_CONSOLE_POLL
+static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr)
+{
+ struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+
+ while (!(UART_GET_LSR(uart) & THRE))
+ cpu_relax();
+
+ UART_CLEAR_DLAB(uart);
+ UART_PUT_CHAR(uart, (unsigned char)chr);
+}
+
+static int bfin_serial_poll_get_char(struct uart_port *port)
+{
+ struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+ unsigned char chr;
+
+ while (!(UART_GET_LSR(uart) & DR))
+ cpu_relax();
+
+ UART_CLEAR_DLAB(uart);
+ chr = UART_GET_CHAR(uart);
+
+ return chr;
+}
+#endif
+
+#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
+static void bfin_kgdboc_port_shutdown(struct uart_port *port)
+{
+ if (kgdboc_break_enabled) {
+ kgdboc_break_enabled = 0;
+ bfin_serial_shutdown(port);
+ }
+}
+
+static int bfin_kgdboc_port_startup(struct uart_port *port)
+{
+ kgdboc_port_line = port->line;
+ kgdboc_break_enabled = !bfin_serial_startup(port);
+ return 0;
+}
+#endif
+
+static void bfin_serial_reset_irda(struct uart_port *port)
+{
+ int line = port->line;
+ unsigned short val;
+
+ val = UART_GET_GCTL(&bfin_serial_ports[line]);
+ val &= ~(IREN | RPOLC);
+ UART_PUT_GCTL(&bfin_serial_ports[line], val);
+ SSYNC();
+ val |= (IREN | RPOLC);
+ UART_PUT_GCTL(&bfin_serial_ports[line], val);
+ SSYNC();
+}
+
static struct uart_ops bfin_serial_pops = {
.tx_empty = bfin_serial_tx_empty,
.set_mctrl = bfin_serial_set_mctrl,
@@ -905,6 +938,15 @@ static struct uart_ops bfin_serial_pops = {
.request_port = bfin_serial_request_port,
.config_port = bfin_serial_config_port,
.verify_port = bfin_serial_verify_port,
+#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
+ defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
+ .kgdboc_port_startup = bfin_kgdboc_port_startup,
+ .kgdboc_port_shutdown = bfin_kgdboc_port_shutdown,
+#endif
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_put_char = bfin_serial_poll_put_char,
+ .poll_get_char = bfin_serial_poll_get_char,
+#endif
};
static void __init bfin_serial_init_ports(void)
@@ -950,7 +992,7 @@ static void __init bfin_serial_init_ports(void)
}
-#ifdef CONFIG_SERIAL_BFIN_CONSOLE
+#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
/*
* If the port was already initialised (eg, by a boot loader),
* try to determine the current setup.
@@ -994,24 +1036,20 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
}
pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits);
}
-#endif
-#if defined(CONFIG_SERIAL_BFIN_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
static struct uart_driver bfin_serial_reg;
static int __init
bfin_serial_console_setup(struct console *co, char *options)
{
struct bfin_serial_port *uart;
-# ifdef CONFIG_SERIAL_BFIN_CONSOLE
int baud = 57600;
int bits = 8;
int parity = 'n';
-# ifdef CONFIG_SERIAL_BFIN_CTSRTS
+# ifdef CONFIG_SERIAL_BFIN_CTSRTS
int flow = 'r';
-# else
+# else
int flow = 'n';
-# endif
# endif
/*
@@ -1023,16 +1061,12 @@ bfin_serial_console_setup(struct console *co, char *options)
co->index = 0;
uart = &bfin_serial_ports[co->index];
-# ifdef CONFIG_SERIAL_BFIN_CONSOLE
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
bfin_serial_console_get_options(uart, &baud, &parity, &bits);
return uart_set_options(&uart->port, co, baud, parity, bits, flow);
-# else
- return 0;
-# endif
}
#endif /* defined (CONFIG_SERIAL_BFIN_CONSOLE) ||
defined (CONFIG_EARLY_PRINTK) */
@@ -1076,10 +1110,7 @@ static int __init bfin_serial_rs_console_init(void)
{
bfin_serial_init_ports();
register_console(&bfin_serial_console);
-#ifdef CONFIG_KGDB_UART
- kgdb_entry_state = 0;
- init_kgdb_uart();
-#endif
+
return 0;
}
console_initcall(bfin_serial_rs_console_init);
@@ -1144,7 +1175,7 @@ struct console __init *bfin_earlyserial_init(unsigned int port,
return &bfin_early_serial_console;
}
-#endif /* CONFIG_SERIAL_BFIN_CONSOLE */
+#endif /* CONFIG_EARLY_PRINTK */
static struct uart_driver bfin_serial_reg = {
.owner = THIS_MODULE,
@@ -1235,10 +1266,6 @@ static struct platform_driver bfin_serial_driver = {
static int __init bfin_serial_init(void)
{
int ret;
-#ifdef CONFIG_KGDB_UART
- struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
- struct ktermios t;
-#endif
pr_info("Serial: Blackfin serial driver\n");
@@ -1252,21 +1279,6 @@ static int __init bfin_serial_init(void)
uart_unregister_driver(&bfin_serial_reg);
}
}
-#ifdef CONFIG_KGDB_UART
- if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) {
- request_irq(uart->port.irq, bfin_serial_rx_int,
- IRQF_DISABLED, "BFIN_UART_RX", uart);
- pr_info("Request irq for kgdb uart port\n");
- UART_SET_IER(uart, ERBFI);
- SSYNC();
- t.c_cflag = CS8|B57600;
- t.c_iflag = 0;
- t.c_oflag = 0;
- t.c_lflag = ICANON;
- t.c_line = CONFIG_KGDB_UART_PORT;
- bfin_serial_set_termios(&uart->port, &t, &t);
- }
-#endif
return ret;
}
@@ -1276,6 +1288,7 @@ static void __exit bfin_serial_exit(void)
uart_unregister_driver(&bfin_serial_reg);
}
+
module_init(bfin_serial_init);
module_exit(bfin_serial_exit);
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index dd8564d25051..529c0ff7952c 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -99,7 +99,7 @@ static void sport_stop_tx(struct uart_port *port);
static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
{
- pr_debug("%s value:%x\n", __FUNCTION__, value);
+ pr_debug("%s value:%x\n", __func__, value);
/* Place a Start and Stop bit */
__asm__ volatile (
"R2 = b#01111111100;\n\t"
@@ -110,7 +110,7 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
:"=r"(value)
:"0"(value)
:"R2", "R3");
- pr_debug("%s value:%x\n", __FUNCTION__, value);
+ pr_debug("%s value:%x\n", __func__, value);
SPORT_PUT_TX(up, value);
}
@@ -120,7 +120,7 @@ static inline unsigned int rx_one_byte(struct sport_uart_port *up)
unsigned int value, extract;
value = SPORT_GET_RX32(up);
- pr_debug("%s value:%x\n", __FUNCTION__, value);
+ pr_debug("%s value:%x\n", __func__, value);
/* Extract 8 bits data */
__asm__ volatile (
@@ -151,12 +151,12 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
/* Set TCR1 and TCR2 */
SPORT_PUT_TCR1(up, (LTFS | ITFS | TFSR | TLSBIT | ITCLK));
SPORT_PUT_TCR2(up, 10);
- pr_debug("%s TCR1:%x, TCR2:%x\n", __FUNCTION__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
+ pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
/* Set RCR1 and RCR2 */
SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK));
SPORT_PUT_RCR2(up, 28);
- pr_debug("%s RCR1:%x, RCR2:%x\n", __FUNCTION__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
+ pr_debug("%s RCR1:%x, RCR2:%x\n", __func__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
tclkdiv = sclk/(2 * baud_rate) - 1;
tfsdiv = 12;
@@ -166,7 +166,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
SPORT_PUT_RCLKDIV(up, rclkdiv);
SSYNC();
pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n",
- __FUNCTION__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv);
+ __func__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv);
return 0;
}
@@ -231,7 +231,7 @@ static int sport_startup(struct uart_port *port)
char buffer[20];
int retval;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
memset(buffer, 20, '\0');
snprintf(buffer, 20, "%s rx", up->name);
retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
@@ -320,7 +320,7 @@ static unsigned int sport_tx_empty(struct uart_port *port)
unsigned int stat;
stat = SPORT_GET_STAT(up);
- pr_debug("%s stat:%04x\n", __FUNCTION__, stat);
+ pr_debug("%s stat:%04x\n", __func__, stat);
if (stat & TXHRE) {
return TIOCSER_TEMT;
} else
@@ -329,13 +329,13 @@ static unsigned int sport_tx_empty(struct uart_port *port)
static unsigned int sport_get_mctrl(struct uart_port *port)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR);
}
static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
}
static void sport_stop_tx(struct uart_port *port)
@@ -343,7 +343,7 @@ static void sport_stop_tx(struct uart_port *port)
struct sport_uart_port *up = (struct sport_uart_port *)port;
unsigned int stat;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
stat = SPORT_GET_STAT(up);
while(!(stat & TXHRE)) {
@@ -366,21 +366,21 @@ static void sport_start_tx(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
/* Write data into SPORT FIFO before enable SPROT to transmit */
sport_uart_tx_chars(up);
/* Enable transmit, then an interrupt will generated */
SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
SSYNC();
- pr_debug("%s exit\n", __FUNCTION__);
+ pr_debug("%s exit\n", __func__);
}
static void sport_stop_rx(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
/* Disable sport to stop rx */
SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
SSYNC();
@@ -388,19 +388,19 @@ static void sport_stop_rx(struct uart_port *port)
static void sport_enable_ms(struct uart_port *port)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
}
static void sport_break_ctl(struct uart_port *port, int break_state)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
}
static void sport_shutdown(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
/* Disable sport */
SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
@@ -421,7 +421,7 @@ static void sport_shutdown(struct uart_port *port)
static void sport_set_termios(struct uart_port *port,
struct termios *termios, struct termios *old)
{
- pr_debug("%s enter, c_cflag:%08x\n", __FUNCTION__, termios->c_cflag);
+ pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
uart_update_timeout(port, CS8 ,port->uartclk);
}
@@ -429,18 +429,18 @@ static const char *sport_type(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
return up->name;
}
static void sport_release_port(struct uart_port *port)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
}
static int sport_request_port(struct uart_port *port)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
return 0;
}
@@ -448,13 +448,13 @@ static void sport_config_port(struct uart_port *port, int flags)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
up->port.type = PORT_BFIN_SPORT;
}
static int sport_verify_port(struct uart_port *port, struct serial_struct *ser)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
return 0;
}
@@ -527,7 +527,7 @@ static int sport_uart_suspend(struct platform_device *dev, pm_message_t state)
{
struct sport_uart_port *sport = platform_get_drvdata(dev);
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
if (sport)
uart_suspend_port(&sport_uart_reg, &sport->port);
@@ -538,7 +538,7 @@ static int sport_uart_resume(struct platform_device *dev)
{
struct sport_uart_port *sport = platform_get_drvdata(dev);
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
if (sport)
uart_resume_port(&sport_uart_reg, &sport->port);
@@ -547,7 +547,7 @@ static int sport_uart_resume(struct platform_device *dev)
static int sport_uart_probe(struct platform_device *dev)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
sport_uart_ports[dev->id].port.dev = &dev->dev;
uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port);
platform_set_drvdata(dev, &sport_uart_ports[dev->id]);
@@ -559,7 +559,7 @@ static int sport_uart_remove(struct platform_device *dev)
{
struct sport_uart_port *sport = platform_get_drvdata(dev);
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
platform_set_drvdata(dev, NULL);
if (sport)
@@ -582,7 +582,7 @@ static int __init sport_uart_init(void)
{
int ret;
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
ret = uart_register_driver(&sport_uart_reg);
if (ret != 0) {
printk(KERN_ERR "Failed to register %s:%d\n",
@@ -597,13 +597,13 @@ static int __init sport_uart_init(void)
}
- pr_debug("%s exit\n", __FUNCTION__);
+ pr_debug("%s exit\n", __func__);
return ret;
}
static void __exit sport_uart_exit(void)
{
- pr_debug("%s enter\n", __FUNCTION__);
+ pr_debug("%s enter\n", __func__);
platform_driver_unregister(&sport_uart_driver);
uart_unregister_driver(&sport_uart_reg);
}
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 8b2c619a09f2..e642c22c80e2 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -1203,7 +1203,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info)
unsigned long flags;
/* Disable output DMA channel for the serial port in question
- * ( set to something other then serialX)
+ * ( set to something other than serialX)
*/
local_irq_save(flags);
DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line));
@@ -1266,7 +1266,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info)
unsigned long flags;
/* Disable input DMA channel for the serial port in question
- * ( set to something other then serialX)
+ * ( set to something other than serialX)
*/
local_irq_save(flags);
if (info->line == 0) {
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 338cf8a08b43..92187e28608a 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -180,7 +180,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}
-static void jsm_remove_one(struct pci_dev *pdev)
+static void __devexit jsm_remove_one(struct pci_dev *pdev)
{
struct jsm_board *brd = pci_get_drvdata(pdev);
int i = 0;
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c
index b7584ca55ade..e6390d023634 100644
--- a/drivers/serial/jsm/jsm_neo.c
+++ b/drivers/serial/jsm/jsm_neo.c
@@ -577,9 +577,6 @@ static void neo_parse_modem(struct jsm_channel *ch, u8 signals)
jsm_printk(MSIGS, INFO, &ch->ch_bd->pci_dev,
"neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals);
- if (!ch)
- return;
-
/* Scrub off lower bits. They signify delta's, which I don't care about */
/* Keep DDCD and DDSR though */
msignals &= 0xf8;
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index a697914ae3d0..324c74d2f666 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -161,6 +161,11 @@ static void jsm_tty_stop_rx(struct uart_port *port)
channel->ch_bd->bd_ops->disable_receiver(channel);
}
+static void jsm_tty_enable_ms(struct uart_port *port)
+{
+ /* Nothing needed */
+}
+
static void jsm_tty_break(struct uart_port *port, int break_state)
{
unsigned long lock_flags;
@@ -272,7 +277,7 @@ static void jsm_tty_close(struct uart_port *port)
jsm_printk(CLOSE, INFO, &channel->ch_bd->pci_dev, "start\n");
bd = channel->ch_bd;
- ts = channel->uart_port.info->port.tty->termios;
+ ts = port->info->port.tty->termios;
channel->ch_flags &= ~(CH_STOPI);
@@ -345,6 +350,7 @@ static struct uart_ops jsm_ops = {
.start_tx = jsm_tty_start_tx,
.send_xchar = jsm_tty_send_xchar,
.stop_rx = jsm_tty_stop_rx,
+ .enable_ms = jsm_tty_enable_ms,
.break_ctl = jsm_tty_break,
.startup = jsm_tty_open,
.shutdown = jsm_tty_close,
diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c
index b2001c5b145c..56841fe5f483 100644
--- a/drivers/serial/mcf.c
+++ b/drivers/serial/mcf.c
@@ -212,10 +212,18 @@ static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
{
unsigned long flags;
unsigned int baud, baudclk;
+#if defined(CONFIG_M5272)
+ unsigned int baudfr;
+#endif
unsigned char mr1, mr2;
baud = uart_get_baud_rate(port, termios, old, 0, 230400);
+#if defined(CONFIG_M5272)
+ baudclk = (MCF_BUSCLK / baud) / 32;
+ baudfr = (((MCF_BUSCLK / baud) + 1) / 2) % 16;
+#else
baudclk = ((MCF_BUSCLK / baud) + 16) / 32;
+#endif
mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
mr2 = 0;
@@ -262,6 +270,9 @@ static void mcf_set_termios(struct uart_port *port, struct ktermios *termios,
writeb(mr2, port->membase + MCFUART_UMR);
writeb((baudclk & 0xff00) >> 8, port->membase + MCFUART_UBG1);
writeb((baudclk & 0xff), port->membase + MCFUART_UBG2);
+#if defined(CONFIG_M5272)
+ writeb((baudfr & 0x0f), port->membase + MCFUART_UFPD);
+#endif
writeb(MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER,
port->membase + MCFUART_UCSR);
writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
diff --git a/drivers/serial/nwpserial.c b/drivers/serial/nwpserial.c
new file mode 100644
index 000000000000..32f3eaf0d262
--- /dev/null
+++ b/drivers/serial/nwpserial.c
@@ -0,0 +1,475 @@
+/*
+ * Serial Port driver for a NWP uart device
+ *
+ * Copyright (C) 2008 IBM Corp., Benjamin Krill <ben@codiert.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_core.h>
+#include <linux/tty.h>
+#include <linux/irqreturn.h>
+#include <linux/mutex.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/nwpserial.h>
+#include <asm/prom.h>
+#include <asm/dcr.h>
+
+#define NWPSERIAL_NR 2
+
+#define NWPSERIAL_STATUS_RXVALID 0x1
+#define NWPSERIAL_STATUS_TXFULL 0x2
+
+struct nwpserial_port {
+ struct uart_port port;
+ dcr_host_t dcr_host;
+ unsigned int ier;
+ unsigned int mcr;
+};
+
+static DEFINE_MUTEX(nwpserial_mutex);
+static struct nwpserial_port nwpserial_ports[NWPSERIAL_NR];
+
+static void wait_for_bits(struct nwpserial_port *up, int bits)
+{
+ unsigned int status, tmout = 10000;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ do {
+ status = dcr_read(up->dcr_host, UART_LSR);
+
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ } while ((status & bits) != bits);
+}
+
+#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
+static void nwpserial_console_putchar(struct uart_port *port, int c)
+{
+ struct nwpserial_port *up;
+ up = container_of(port, struct nwpserial_port, port);
+ /* check if tx buffer is full */
+ wait_for_bits(up, UART_LSR_THRE);
+ dcr_write(up->dcr_host, UART_TX, c);
+ up->port.icount.tx++;
+}
+
+static void
+nwpserial_console_write(struct console *co, const char *s, unsigned int count)
+{
+ struct nwpserial_port *up = &nwpserial_ports[co->index];
+ unsigned long flags;
+ int locked = 1;
+
+ if (oops_in_progress)
+ locked = spin_trylock_irqsave(&up->port.lock, flags);
+ else
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ /* save and disable interrupt */
+ up->ier = dcr_read(up->dcr_host, UART_IER);
+ dcr_write(up->dcr_host, UART_IER, up->ier & ~UART_IER_RDI);
+
+ uart_console_write(&up->port, s, count, nwpserial_console_putchar);
+
+ /* wait for transmitter to become emtpy */
+ while ((dcr_read(up->dcr_host, UART_LSR) & UART_LSR_THRE) == 0)
+ cpu_relax();
+
+ /* restore interrupt state */
+ dcr_write(up->dcr_host, UART_IER, up->ier);
+
+ if (locked)
+ spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static struct uart_driver nwpserial_reg;
+static struct console nwpserial_console = {
+ .name = "ttySQ",
+ .write = nwpserial_console_write,
+ .device = uart_console_device,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &nwpserial_reg,
+};
+#define NWPSERIAL_CONSOLE (&nwpserial_console)
+#else
+#define NWPSERIAL_CONSOLE NULL
+#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
+
+/**************************************************************************/
+
+static int nwpserial_request_port(struct uart_port *port)
+{
+ return 0;
+}
+
+static void nwpserial_release_port(struct uart_port *port)
+{
+ /* N/A */
+}
+
+static void nwpserial_config_port(struct uart_port *port, int flags)
+{
+ port->type = PORT_NWPSERIAL;
+}
+
+static irqreturn_t nwpserial_interrupt(int irq, void *dev_id)
+{
+ struct nwpserial_port *up = dev_id;
+ struct tty_struct *tty = up->port.info->port.tty;
+ irqreturn_t ret;
+ unsigned int iir;
+ unsigned char ch;
+
+ spin_lock(&up->port.lock);
+
+ /* check if the uart was the interrupt source. */
+ iir = dcr_read(up->dcr_host, UART_IIR);
+ if (!iir) {
+ ret = IRQ_NONE;
+ goto out;
+ }
+
+ do {
+ up->port.icount.rx++;
+ ch = dcr_read(up->dcr_host, UART_RX);
+ if (up->port.ignore_status_mask != NWPSERIAL_STATUS_RXVALID)
+ tty_insert_flip_char(tty, ch, TTY_NORMAL);
+ } while (dcr_read(up->dcr_host, UART_RX) & UART_LSR_DR);
+
+ tty_flip_buffer_push(tty);
+ ret = IRQ_HANDLED;
+
+out:
+ spin_unlock(&up->port.lock);
+ return ret;
+}
+
+static int nwpserial_startup(struct uart_port *port)
+{
+ struct nwpserial_port *up;
+ int err;
+
+ up = container_of(port, struct nwpserial_port, port);
+
+ /* disable flow control by default */
+ up->mcr = dcr_read(up->dcr_host, UART_MCR) & ~UART_MCR_AFE;
+ dcr_write(up->dcr_host, UART_MCR, up->mcr);
+
+ /* register interrupt handler */
+ err = request_irq(up->port.irq, nwpserial_interrupt,
+ IRQF_SHARED, "nwpserial", up);
+ if (err)
+ return err;
+
+ /* enable interrupts */
+ up->ier = UART_IER_RDI;
+ dcr_write(up->dcr_host, UART_IER, up->ier);
+
+ /* enable receiving */
+ up->port.ignore_status_mask &= ~NWPSERIAL_STATUS_RXVALID;
+
+ return 0;
+}
+
+static void nwpserial_shutdown(struct uart_port *port)
+{
+ struct nwpserial_port *up;
+ up = container_of(port, struct nwpserial_port, port);
+
+ /* disable receiving */
+ up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
+
+ /* disable interrupts from this port */
+ up->ier = 0;
+ dcr_write(up->dcr_host, UART_IER, up->ier);
+
+ /* free irq */
+ free_irq(up->port.irq, port);
+}
+
+static int nwpserial_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ return -EINVAL;
+}
+
+static const char *nwpserial_type(struct uart_port *port)
+{
+ return port->type == PORT_NWPSERIAL ? "nwpserial" : NULL;
+}
+
+static void nwpserial_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old)
+{
+ struct nwpserial_port *up;
+ up = container_of(port, struct nwpserial_port, port);
+
+ up->port.read_status_mask = NWPSERIAL_STATUS_RXVALID
+ | NWPSERIAL_STATUS_TXFULL;
+
+ up->port.ignore_status_mask = 0;
+ /* ignore all characters if CREAD is not set */
+ if ((termios->c_cflag & CREAD) == 0)
+ up->port.ignore_status_mask |= NWPSERIAL_STATUS_RXVALID;
+
+ /* Copy back the old hardware settings */
+ if (old)
+ tty_termios_copy_hw(termios, old);
+}
+
+static void nwpserial_break_ctl(struct uart_port *port, int ctl)
+{
+ /* N/A */
+}
+
+static void nwpserial_enable_ms(struct uart_port *port)
+{
+ /* N/A */
+}
+
+static void nwpserial_stop_rx(struct uart_port *port)
+{
+ struct nwpserial_port *up;
+ up = container_of(port, struct nwpserial_port, port);
+ /* don't forward any more data (like !CREAD) */
+ up->port.ignore_status_mask = NWPSERIAL_STATUS_RXVALID;
+}
+
+static void nwpserial_putchar(struct nwpserial_port *up, unsigned char c)
+{
+ /* check if tx buffer is full */
+ wait_for_bits(up, UART_LSR_THRE);
+ dcr_write(up->dcr_host, UART_TX, c);
+ up->port.icount.tx++;
+}
+
+static void nwpserial_start_tx(struct uart_port *port)
+{
+ struct nwpserial_port *up;
+ struct circ_buf *xmit;
+ up = container_of(port, struct nwpserial_port, port);
+ xmit = &up->port.info->xmit;
+
+ if (port->x_char) {
+ nwpserial_putchar(up, up->port.x_char);
+ port->x_char = 0;
+ }
+
+ while (!(uart_circ_empty(xmit) || uart_tx_stopped(&up->port))) {
+ nwpserial_putchar(up, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
+ }
+}
+
+static unsigned int nwpserial_get_mctrl(struct uart_port *port)
+{
+ return 0;
+}
+
+static void nwpserial_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ /* N/A */
+}
+
+static void nwpserial_stop_tx(struct uart_port *port)
+{
+ /* N/A */
+}
+
+static unsigned int nwpserial_tx_empty(struct uart_port *port)
+{
+ struct nwpserial_port *up;
+ unsigned long flags;
+ int ret;
+ up = container_of(port, struct nwpserial_port, port);
+
+ spin_lock_irqsave(&up->port.lock, flags);
+ ret = dcr_read(up->dcr_host, UART_LSR);
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ return ret & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+}
+
+static struct uart_ops nwpserial_pops = {
+ .tx_empty = nwpserial_tx_empty,
+ .set_mctrl = nwpserial_set_mctrl,
+ .get_mctrl = nwpserial_get_mctrl,
+ .stop_tx = nwpserial_stop_tx,
+ .start_tx = nwpserial_start_tx,
+ .stop_rx = nwpserial_stop_rx,
+ .enable_ms = nwpserial_enable_ms,
+ .break_ctl = nwpserial_break_ctl,
+ .startup = nwpserial_startup,
+ .shutdown = nwpserial_shutdown,
+ .set_termios = nwpserial_set_termios,
+ .type = nwpserial_type,
+ .release_port = nwpserial_release_port,
+ .request_port = nwpserial_request_port,
+ .config_port = nwpserial_config_port,
+ .verify_port = nwpserial_verify_port,
+};
+
+static struct uart_driver nwpserial_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "nwpserial",
+ .dev_name = "ttySQ",
+ .major = TTY_MAJOR,
+ .minor = 68,
+ .nr = NWPSERIAL_NR,
+ .cons = NWPSERIAL_CONSOLE,
+};
+
+int nwpserial_register_port(struct uart_port *port)
+{
+ struct nwpserial_port *up = NULL;
+ int ret = -1;
+ int i;
+ static int first = 1;
+ int dcr_len;
+ int dcr_base;
+ struct device_node *dn;
+
+ mutex_lock(&nwpserial_mutex);
+
+ dn = to_of_device(port->dev)->node;
+ if (dn == NULL)
+ goto out;
+
+ /* get dcr base. */
+ dcr_base = dcr_resource_start(dn, 0);
+
+ /* find matching entry */
+ for (i = 0; i < NWPSERIAL_NR; i++)
+ if (nwpserial_ports[i].port.iobase == dcr_base) {
+ up = &nwpserial_ports[i];
+ break;
+ }
+
+ /* we didn't find a mtching entry, search for a free port */
+ if (up == NULL)
+ for (i = 0; i < NWPSERIAL_NR; i++)
+ if (nwpserial_ports[i].port.type == PORT_UNKNOWN &&
+ nwpserial_ports[i].port.iobase == 0) {
+ up = &nwpserial_ports[i];
+ break;
+ }
+
+ if (up == NULL) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (first)
+ uart_register_driver(&nwpserial_reg);
+ first = 0;
+
+ up->port.membase = port->membase;
+ up->port.irq = port->irq;
+ up->port.uartclk = port->uartclk;
+ up->port.fifosize = port->fifosize;
+ up->port.regshift = port->regshift;
+ up->port.iotype = port->iotype;
+ up->port.flags = port->flags;
+ up->port.mapbase = port->mapbase;
+ up->port.private_data = port->private_data;
+
+ if (port->dev)
+ up->port.dev = port->dev;
+
+ if (up->port.iobase != dcr_base) {
+ up->port.ops = &nwpserial_pops;
+ up->port.fifosize = 16;
+
+ spin_lock_init(&up->port.lock);
+
+ up->port.iobase = dcr_base;
+ dcr_len = dcr_resource_len(dn, 0);
+
+ up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
+ if (!DCR_MAP_OK(up->dcr_host)) {
+ printk(KERN_ERR "Cannot map DCR resources for NWPSERIAL");
+ goto out;
+ }
+ }
+
+ ret = uart_add_one_port(&nwpserial_reg, &up->port);
+ if (ret == 0)
+ ret = up->port.line;
+
+out:
+ mutex_unlock(&nwpserial_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(nwpserial_register_port);
+
+void nwpserial_unregister_port(int line)
+{
+ struct nwpserial_port *up = &nwpserial_ports[line];
+ mutex_lock(&nwpserial_mutex);
+ uart_remove_one_port(&nwpserial_reg, &up->port);
+
+ up->port.type = PORT_UNKNOWN;
+
+ mutex_unlock(&nwpserial_mutex);
+}
+EXPORT_SYMBOL(nwpserial_unregister_port);
+
+#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE
+static int __init nwpserial_console_init(void)
+{
+ struct nwpserial_port *up = NULL;
+ struct device_node *dn;
+ const char *name;
+ int dcr_base;
+ int dcr_len;
+ int i;
+
+ /* search for a free port */
+ for (i = 0; i < NWPSERIAL_NR; i++)
+ if (nwpserial_ports[i].port.type == PORT_UNKNOWN) {
+ up = &nwpserial_ports[i];
+ break;
+ }
+
+ if (up == NULL)
+ return -1;
+
+ name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+ if (name == NULL)
+ return -1;
+
+ dn = of_find_node_by_path(name);
+ if (!dn)
+ return -1;
+
+ spin_lock_init(&up->port.lock);
+ up->port.ops = &nwpserial_pops;
+ up->port.type = PORT_NWPSERIAL;
+ up->port.fifosize = 16;
+
+ dcr_base = dcr_resource_start(dn, 0);
+ dcr_len = dcr_resource_len(dn, 0);
+ up->port.iobase = dcr_base;
+
+ up->dcr_host = dcr_map(dn, dcr_base, dcr_len);
+ if (!DCR_MAP_OK(up->dcr_host)) {
+ printk("Cannot map DCR resources for SERIAL");
+ return -1;
+ }
+ register_console(&nwpserial_console);
+ return 0;
+}
+console_initcall(nwpserial_console_init);
+#endif /* CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL_CONSOLE */
diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
index 8fa0ff561e9f..14f8fa9135be 100644
--- a/drivers/serial/of_serial.c
+++ b/drivers/serial/of_serial.c
@@ -14,6 +14,7 @@
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
#include <linux/of_platform.h>
+#include <linux/nwpserial.h>
#include <asm/prom.h>
@@ -99,9 +100,16 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev,
goto out;
switch (port_type) {
+#ifdef CONFIG_SERIAL_8250
case PORT_8250 ... PORT_MAX_8250:
ret = serial8250_register_port(&port);
break;
+#endif
+#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
+ case PORT_NWPSERIAL:
+ ret = nwpserial_register_port(&port);
+ break;
+#endif
default:
/* need to add code for these */
case PORT_UNKNOWN:
@@ -129,9 +137,16 @@ static int of_platform_serial_remove(struct of_device *ofdev)
{
struct of_serial_info *info = ofdev->dev.driver_data;
switch (info->type) {
+#ifdef CONFIG_SERIAL_8250
case PORT_8250 ... PORT_MAX_8250:
serial8250_unregister_port(info->line);
break;
+#endif
+#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
+ case PORT_NWPSERIAL:
+ nwpserial_unregister_port(info->line);
+ break;
+#endif
default:
/* need to add code for these */
break;
@@ -148,6 +163,11 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
{ .type = "serial", .compatible = "ns16450", .data = (void *)PORT_16450, },
{ .type = "serial", .compatible = "ns16550", .data = (void *)PORT_16550, },
{ .type = "serial", .compatible = "ns16750", .data = (void *)PORT_16750, },
+ { .type = "serial", .compatible = "ns16850", .data = (void *)PORT_16850, },
+#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
+ { .type = "serial", .compatible = "ibm,qpace-nwp-serial",
+ .data = (void *)PORT_NWPSERIAL, },
+#endif
{ .type = "serial", .data = (void *)PORT_UNKNOWN, },
{ /* end of list */ },
};
diff --git a/drivers/serial/pnx8xxx_uart.c b/drivers/serial/pnx8xxx_uart.c
index 22e30d21225e..1bb8f1b45767 100644
--- a/drivers/serial/pnx8xxx_uart.c
+++ b/drivers/serial/pnx8xxx_uart.c
@@ -187,7 +187,7 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
- ch = serial_in(sport, PNX8XXX_FIFO);
+ ch = serial_in(sport, PNX8XXX_FIFO) & 0xff;
sport->port.icount.rx++;
@@ -198,9 +198,16 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
* out of the main execution path
*/
if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
- PNX8XXX_UART_FIFO_RXPAR) |
+ PNX8XXX_UART_FIFO_RXPAR |
+ PNX8XXX_UART_FIFO_RXBRK) |
ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
- if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
+ if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) {
+ status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
+ FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR));
+ sport->port.icount.brk++;
+ if (uart_handle_break(&sport->port))
+ goto ignore_char;
+ } else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
sport->port.icount.parity++;
else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
sport->port.icount.frame++;
@@ -284,14 +291,8 @@ static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
/* Get the interrupts */
status = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
- /* Break signal received */
- if (status & PNX8XXX_UART_INT_BREAK) {
- sport->port.icount.brk++;
- uart_handle_break(&sport->port);
- }
-
- /* Byte received */
- if (status & PNX8XXX_UART_INT_RX)
+ /* Byte or break signal received */
+ if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK))
pnx8xxx_rx_chars(sport);
/* TX holding register empty - transmit a byte */
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 874786a11fe9..42f4e66fccaf 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -50,7 +50,7 @@ static struct lock_class_key port_lock_key;
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
-#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->port.blocked_open : 0))
+#define uart_users(state) ((state)->count + (state)->info.port.blocked_open)
#ifdef CONFIG_SERIAL_CORE_CONSOLE
#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line)
@@ -94,7 +94,7 @@ static void __uart_start(struct tty_struct *tty)
struct uart_state *state = tty->driver_data;
struct uart_port *port = state->port;
- if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf &&
+ if (!uart_circ_empty(&state->info.xmit) && state->info.xmit.buf &&
!tty->stopped && !tty->hw_stopped)
port->ops->start_tx(port);
}
@@ -113,7 +113,7 @@ static void uart_start(struct tty_struct *tty)
static void uart_tasklet_action(unsigned long data)
{
struct uart_state *state = (struct uart_state *)data;
- tty_wakeup(state->info->port.tty);
+ tty_wakeup(state->info.port.tty);
}
static inline void
@@ -139,7 +139,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
*/
static int uart_startup(struct uart_state *state, int init_hw)
{
- struct uart_info *info = state->info;
+ struct uart_info *info = &state->info;
struct uart_port *port = state->port;
unsigned long page;
int retval = 0;
@@ -212,14 +212,15 @@ static int uart_startup(struct uart_state *state, int init_hw)
*/
static void uart_shutdown(struct uart_state *state)
{
- struct uart_info *info = state->info;
+ struct uart_info *info = &state->info;
struct uart_port *port = state->port;
+ struct tty_struct *tty = info->port.tty;
/*
* Set the TTY IO error marker
*/
- if (info->port.tty)
- set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
if (info->flags & UIF_INITIALIZED) {
info->flags &= ~UIF_INITIALIZED;
@@ -227,7 +228,7 @@ static void uart_shutdown(struct uart_state *state)
/*
* Turn off DTR and RTS early.
*/
- if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL))
+ if (!tty || (tty->termios->c_cflag & HUPCL))
uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
/*
@@ -427,7 +428,7 @@ EXPORT_SYMBOL(uart_get_divisor);
static void
uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
{
- struct tty_struct *tty = state->info->port.tty;
+ struct tty_struct *tty = state->info.port.tty;
struct uart_port *port = state->port;
struct ktermios *termios;
@@ -444,14 +445,14 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
* Set flags based on termios cflag
*/
if (termios->c_cflag & CRTSCTS)
- state->info->flags |= UIF_CTS_FLOW;
+ state->info.flags |= UIF_CTS_FLOW;
else
- state->info->flags &= ~UIF_CTS_FLOW;
+ state->info.flags &= ~UIF_CTS_FLOW;
if (termios->c_cflag & CLOCAL)
- state->info->flags &= ~UIF_CHECK_CD;
+ state->info.flags &= ~UIF_CHECK_CD;
else
- state->info->flags |= UIF_CHECK_CD;
+ state->info.flags |= UIF_CHECK_CD;
port->ops->set_termios(port, termios, old_termios);
}
@@ -479,7 +480,7 @@ static int uart_put_char(struct tty_struct *tty, unsigned char ch)
{
struct uart_state *state = tty->driver_data;
- return __uart_put_char(state->port, &state->info->xmit, ch);
+ return __uart_put_char(state->port, &state->info.xmit, ch);
}
static void uart_flush_chars(struct tty_struct *tty)
@@ -500,13 +501,13 @@ uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
* This means you called this function _after_ the port was
* closed. No cookie for you.
*/
- if (!state || !state->info) {
+ if (!state) {
WARN_ON(1);
return -EL3HLT;
}
port = state->port;
- circ = &state->info->xmit;
+ circ = &state->info.xmit;
if (!circ->buf)
return 0;
@@ -537,7 +538,7 @@ static int uart_write_room(struct tty_struct *tty)
int ret;
spin_lock_irqsave(&state->port->lock, flags);
- ret = uart_circ_chars_free(&state->info->xmit);
+ ret = uart_circ_chars_free(&state->info.xmit);
spin_unlock_irqrestore(&state->port->lock, flags);
return ret;
}
@@ -549,7 +550,7 @@ static int uart_chars_in_buffer(struct tty_struct *tty)
int ret;
spin_lock_irqsave(&state->port->lock, flags);
- ret = uart_circ_chars_pending(&state->info->xmit);
+ ret = uart_circ_chars_pending(&state->info.xmit);
spin_unlock_irqrestore(&state->port->lock, flags);
return ret;
}
@@ -564,7 +565,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
* This means you called this function _after_ the port was
* closed. No cookie for you.
*/
- if (!state || !state->info) {
+ if (!state) {
WARN_ON(1);
return;
}
@@ -573,7 +574,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
pr_debug("uart_flush_buffer(%d) called\n", tty->index);
spin_lock_irqsave(&port->lock, flags);
- uart_circ_clear(&state->info->xmit);
+ uart_circ_clear(&state->info.xmit);
if (port->ops->flush_buffer)
port->ops->flush_buffer(port);
spin_unlock_irqrestore(&port->lock, flags);
@@ -837,15 +838,15 @@ static int uart_set_info(struct uart_state *state,
state->closing_wait = closing_wait;
if (new_serial.xmit_fifo_size)
port->fifosize = new_serial.xmit_fifo_size;
- if (state->info->port.tty)
- state->info->port.tty->low_latency =
+ if (state->info.port.tty)
+ state->info.port.tty->low_latency =
(port->flags & UPF_LOW_LATENCY) ? 1 : 0;
check_and_exit:
retval = 0;
if (port->type == PORT_UNKNOWN)
goto exit;
- if (state->info->flags & UIF_INITIALIZED) {
+ if (state->info.flags & UIF_INITIALIZED) {
if (((old_flags ^ port->flags) & UPF_SPD_MASK) ||
old_custom_divisor != port->custom_divisor) {
/*
@@ -858,7 +859,7 @@ static int uart_set_info(struct uart_state *state,
printk(KERN_NOTICE
"%s sets custom speed on %s. This "
"is deprecated.\n", current->comm,
- tty_name(state->info->port.tty, buf));
+ tty_name(state->info.port.tty, buf));
}
uart_change_speed(state, NULL);
}
@@ -889,8 +890,8 @@ static int uart_get_lsr_info(struct uart_state *state,
* interrupt happens).
*/
if (port->x_char ||
- ((uart_circ_chars_pending(&state->info->xmit) > 0) &&
- !state->info->port.tty->stopped && !state->info->port.tty->hw_stopped))
+ ((uart_circ_chars_pending(&state->info.xmit) > 0) &&
+ !state->info.port.tty->stopped && !state->info.port.tty->hw_stopped))
result &= ~TIOCSER_TEMT;
return put_user(result, value);
@@ -1017,7 +1018,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
port->ops->enable_ms(port);
spin_unlock_irq(&port->lock);
- add_wait_queue(&state->info->delta_msr_wait, &wait);
+ add_wait_queue(&state->info.delta_msr_wait, &wait);
for (;;) {
spin_lock_irq(&port->lock);
memcpy(&cnow, &port->icount, sizeof(struct uart_icount));
@@ -1045,7 +1046,7 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
}
current->state = TASK_RUNNING;
- remove_wait_queue(&state->info->delta_msr_wait, &wait);
+ remove_wait_queue(&state->info.delta_msr_wait, &wait);
return ret;
}
@@ -1241,7 +1242,7 @@ static void uart_set_termios(struct tty_struct *tty,
*/
if (!(old_termios->c_cflag & CLOCAL) &&
(tty->termios->c_cflag & CLOCAL))
- wake_up_interruptible(&state->info->port.open_wait);
+ wake_up_interruptible(&info->port.open_wait);
#endif
}
@@ -1303,7 +1304,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
* At this point, we stop accepting input. To do this, we
* disable the receive line status interrupts.
*/
- if (state->info->flags & UIF_INITIALIZED) {
+ if (state->info.flags & UIF_INITIALIZED) {
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
port->ops->stop_rx(port);
@@ -1322,9 +1323,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
tty_ldisc_flush(tty);
tty->closing = 0;
- state->info->port.tty = NULL;
+ state->info.port.tty = NULL;
- if (state->info->port.blocked_open) {
+ if (state->info.port.blocked_open) {
if (state->close_delay)
msleep_interruptible(state->close_delay);
} else if (!uart_console(port)) {
@@ -1334,8 +1335,8 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
/*
* Wake up anyone trying to open this port.
*/
- state->info->flags &= ~UIF_NORMAL_ACTIVE;
- wake_up_interruptible(&state->info->port.open_wait);
+ state->info.flags &= ~UIF_NORMAL_ACTIVE;
+ wake_up_interruptible(&state->info.port.open_wait);
done:
mutex_unlock(&state->mutex);
@@ -1409,19 +1410,20 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
static void uart_hangup(struct tty_struct *tty)
{
struct uart_state *state = tty->driver_data;
+ struct uart_info *info = &state->info;
BUG_ON(!kernel_locked());
pr_debug("uart_hangup(%d)\n", state->port->line);
mutex_lock(&state->mutex);
- if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) {
+ if (info->flags & UIF_NORMAL_ACTIVE) {
uart_flush_buffer(tty);
uart_shutdown(state);
state->count = 0;
- state->info->flags &= ~UIF_NORMAL_ACTIVE;
- state->info->port.tty = NULL;
- wake_up_interruptible(&state->info->port.open_wait);
- wake_up_interruptible(&state->info->delta_msr_wait);
+ info->flags &= ~UIF_NORMAL_ACTIVE;
+ info->port.tty = NULL;
+ wake_up_interruptible(&info->port.open_wait);
+ wake_up_interruptible(&info->delta_msr_wait);
}
mutex_unlock(&state->mutex);
}
@@ -1434,7 +1436,7 @@ static void uart_hangup(struct tty_struct *tty)
*/
static void uart_update_termios(struct uart_state *state)
{
- struct tty_struct *tty = state->info->port.tty;
+ struct tty_struct *tty = state->info.port.tty;
struct uart_port *port = state->port;
if (uart_console(port) && port->cons->cflag) {
@@ -1469,7 +1471,7 @@ static int
uart_block_til_ready(struct file *filp, struct uart_state *state)
{
DECLARE_WAITQUEUE(wait, current);
- struct uart_info *info = state->info;
+ struct uart_info *info = &state->info;
struct uart_port *port = state->port;
unsigned int mctrl;
@@ -1563,28 +1565,6 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
ret = -ENXIO;
goto err_unlock;
}
-
- /* BKL: RACE HERE - LEAK */
- /* We should move this into the uart_state structure and kill off
- this whole complexity */
- if (!state->info) {
- state->info = kzalloc(sizeof(struct uart_info), GFP_KERNEL);
- if (state->info) {
- init_waitqueue_head(&state->info->port.open_wait);
- init_waitqueue_head(&state->info->delta_msr_wait);
-
- /*
- * Link the info into the other structures.
- */
- state->port->info = state->info;
-
- tasklet_init(&state->info->tlet, uart_tasklet_action,
- (unsigned long)state);
- } else {
- ret = -ENOMEM;
- goto err_unlock;
- }
- }
return state;
err_unlock:
@@ -1641,9 +1621,10 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
* Any failures from here onwards should not touch the count.
*/
tty->driver_data = state;
+ state->port->info = &state->info;
tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0;
tty->alt_speed = 0;
- state->info->port.tty = tty;
+ state->info.port.tty = tty;
/*
* If the port is in the middle of closing, bail out now.
@@ -1676,8 +1657,8 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
/*
* If this is the first open to succeed, adjust things to suit.
*/
- if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) {
- state->info->flags |= UIF_NORMAL_ACTIVE;
+ if (retval == 0 && !(state->info.flags & UIF_NORMAL_ACTIVE)) {
+ state->info.flags |= UIF_NORMAL_ACTIVE;
uart_update_termios(state);
}
@@ -2028,11 +2009,11 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
}
port->suspended = 1;
- if (state->info && state->info->flags & UIF_INITIALIZED) {
+ if (state->info.flags & UIF_INITIALIZED) {
const struct uart_ops *ops = port->ops;
int tries;
- state->info->flags = (state->info->flags & ~UIF_INITIALIZED)
+ state->info.flags = (state->info.flags & ~UIF_INITIALIZED)
| UIF_SUSPENDED;
spin_lock_irq(&port->lock);
@@ -2049,7 +2030,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
if (!tries)
printk(KERN_ERR "%s%s%s%d: Unable to drain "
"transmitter\n",
- port->dev ? port->dev->bus_id : "",
+ port->dev ? dev_name(port->dev) : "",
port->dev ? ": " : "",
drv->dev_name,
drv->tty_driver->name_base + port->line);
@@ -2107,15 +2088,15 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
/*
* If that's unset, use the tty termios setting.
*/
- if (state->info && state->info->port.tty && termios.c_cflag == 0)
- termios = *state->info->port.tty->termios;
+ if (state->info.port.tty && termios.c_cflag == 0)
+ termios = *state->info.port.tty->termios;
uart_change_pm(state, 0);
port->ops->set_termios(port, &termios, NULL);
console_start(port->cons);
}
- if (state->info && state->info->flags & UIF_SUSPENDED) {
+ if (state->info.flags & UIF_SUSPENDED) {
const struct uart_ops *ops = port->ops;
int ret;
@@ -2130,7 +2111,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
ops->set_mctrl(port, port->mctrl);
ops->start_tx(port);
spin_unlock_irq(&port->lock);
- state->info->flags |= UIF_INITIALIZED;
+ state->info.flags |= UIF_INITIALIZED;
} else {
/*
* Failed to resume - maybe hardware went away?
@@ -2140,7 +2121,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
uart_shutdown(state);
}
- state->info->flags &= ~UIF_SUSPENDED;
+ state->info.flags &= ~UIF_SUSPENDED;
}
mutex_unlock(&state->mutex);
@@ -2175,7 +2156,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
}
printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
- port->dev ? port->dev->bus_id : "",
+ port->dev ? dev_name(port->dev) : "",
port->dev ? ": " : "",
drv->dev_name,
drv->tty_driver->name_base + port->line,
@@ -2198,11 +2179,14 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
* Now do the auto configuration stuff. Note that config_port
* is expected to claim the resources and map the port for us.
*/
- flags = UART_CONFIG_TYPE;
+ flags = 0;
if (port->flags & UPF_AUTO_IRQ)
flags |= UART_CONFIG_IRQ;
if (port->flags & UPF_BOOT_AUTOCONF) {
- port->type = PORT_UNKNOWN;
+ if (!(port->flags & UPF_FIXED_TYPE)) {
+ port->type = PORT_UNKNOWN;
+ flags |= UART_CONFIG_TYPE;
+ }
port->ops->config_port(port, flags);
}
@@ -2383,8 +2367,12 @@ int uart_register_driver(struct uart_driver *drv)
state->close_delay = 500; /* .5 seconds */
state->closing_wait = 30000; /* 30 seconds */
-
mutex_init(&state->mutex);
+
+ tty_port_init(&state->info.port);
+ init_waitqueue_head(&state->info.delta_msr_wait);
+ tasklet_init(&state->info.tlet, uart_tasklet_action,
+ (unsigned long)state);
}
retval = tty_register_driver(normal);
@@ -2455,7 +2443,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
state->pm_state = -1;
port->cons = drv->cons;
- port->info = state->info;
+ port->info = &state->info;
/*
* If this port is a console, then the spinlock is already
@@ -2527,18 +2515,11 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
*/
tty_unregister_device(drv->tty_driver, port->line);
- info = state->info;
+ info = &state->info;
if (info && info->port.tty)
tty_vhangup(info->port.tty);
/*
- * All users of this port should now be disconnected from
- * this driver, and the port shut down. We should be the
- * only thread fiddling with this port from now on.
- */
- state->info = NULL;
-
- /*
* Free the port IO and memory resources, if any.
*/
if (port->type != PORT_UNKNOWN)
@@ -2552,10 +2533,8 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
/*
* Kill the tasklet, and free resources.
*/
- if (info) {
+ if (info)
tasklet_kill(&info->tlet);
- kfree(info);
- }
state->port = NULL;
mutex_unlock(&port_mutex);
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index 38c600c0dbbf..3599828b9766 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -32,7 +32,9 @@
#elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721)
# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
-#define SCIF_ORER 0x0200 /* overrun error bit */
+# define PORT_PTCR 0xA405011EUL
+# define PORT_PVCR 0xA4050122UL
+# define SCIF_ORER 0x0200 /* overrun error bit */
#elif defined(CONFIG_SH_RTS7751R2D)
# define SCSPTR1 0xFFE0001C /* 8 bit SCIF */
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
@@ -393,6 +395,7 @@ SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16)
SCIx_FNS(SCxTDR, 0x20, 8, 0x0c, 8)
SCIx_FNS(SCxSR, 0x14, 16, 0x10, 16)
SCIx_FNS(SCxRDR, 0x24, 8, 0x14, 8)
+SCIx_FNS(SCSPTR, 0, 0, 0, 0)
SCIF_FNS(SCTDSR, 0x0c, 8)
SCIF_FNS(SCFER, 0x10, 16)
SCIF_FNS(SCFCR, 0x18, 16)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b9d0efb6803f..83a185d52961 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -78,7 +78,7 @@ config SPI_AU1550
will be called au1550_spi.
config SPI_BITBANG
- tristate "Bitbanging SPI master"
+ tristate "Utilities for Bitbanging SPI masters"
help
With a few GPIO pins, your system can bitbang the SPI protocol.
Select this to get SPI support through I/O pins (GPIO, parallel
@@ -100,6 +100,22 @@ config SPI_BUTTERFLY
inexpensive battery powered microcontroller evaluation board.
This same cable can be used to flash new firmware.
+config SPI_GPIO
+ tristate "GPIO-based bitbanging SPI Master"
+ depends on GENERIC_GPIO
+ select SPI_BITBANG
+ help
+ This simple GPIO bitbanging SPI master uses the arch-neutral GPIO
+ interface to manage MOSI, MISO, SCK, and chipselect signals. SPI
+ slaves connected to a bus using this driver are configured as usual,
+ except that the spi_board_info.controller_data holds the GPIO number
+ for the chipselect used by this controller driver.
+
+ Note that this driver often won't achieve even 1 Mbit/sec speeds,
+ making it unusually slow for SPI. If your platform can inline
+ GPIO operations, you should be able to leverage that for better
+ speed with a custom version of this driver; see the source code.
+
config SPI_IMX
tristate "Freescale iMX SPI controller"
depends on ARCH_IMX && EXPERIMENTAL
@@ -214,17 +230,6 @@ config SPI_XILINX
#
comment "SPI Protocol Masters"
-config SPI_AT25
- tristate "SPI EEPROMs from most vendors"
- depends on SYSFS
- help
- Enable this driver to get read/write support to most SPI EEPROMs,
- after you configure the board init code to know about each eeprom
- on your target board.
-
- This driver can also be built as a module. If so, the module
- will be called at25.
-
config SPI_SPIDEV
tristate "User mode SPI device driver support"
depends on EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index ccf18de34e1e..5d0451936d86 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
+obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
@@ -32,7 +33,6 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
# ... add above this line ...
# SPI protocol drivers (device/link on bus)
-obj-$(CONFIG_SPI_AT25) += at25.o
obj-$(CONFIG_SPI_SPIDEV) += spidev.o
obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o
# ... add above this line ...
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 8abae4ad0fa5..56ff3e6864ea 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -30,13 +30,6 @@
* The core SPI transfer engine just talks to a register bank to set up
* DMA transfers; transfer queue progress is driven by IRQs. The clock
* framework provides the base clock, subdivided for each spi_device.
- *
- * Newer controllers, marked with "new_1" flag, have:
- * - CR.LASTXFER
- * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
- * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
- * - SPI_CSRx.CSAAT
- * - SPI_CSRx.SBCR allows faster clocking
*/
struct atmel_spi {
spinlock_t lock;
@@ -45,7 +38,6 @@ struct atmel_spi {
int irq;
struct clk *clk;
struct platform_device *pdev;
- unsigned new_1:1;
struct spi_device *stay;
u8 stopping;
@@ -59,10 +51,33 @@ struct atmel_spi {
dma_addr_t buffer_dma;
};
+/* Controller-specific per-slave state */
+struct atmel_spi_device {
+ unsigned int npcs_pin;
+ u32 csr;
+};
+
#define BUFFER_SIZE PAGE_SIZE
#define INVALID_DMA_ADDRESS 0xffffffff
/*
+ * Version 2 of the SPI controller has
+ * - CR.LASTXFER
+ * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
+ * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
+ * - SPI_CSRx.CSAAT
+ * - SPI_CSRx.SBCR allows faster clocking
+ *
+ * We can determine the controller version by reading the VERSION
+ * register, but I haven't checked that it exists on all chips, and
+ * this is cheaper anyway.
+ */
+static bool atmel_spi_is_v2(void)
+{
+ return !cpu_is_at91rm9200();
+}
+
+/*
* Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
* they assume that spi slave device state will not change on deselect, so
* that automagic deselection is OK. ("NPCSx rises if no data is to be
@@ -80,39 +95,58 @@ struct atmel_spi {
* Master on Chip Select 0.") No workaround exists for that ... so for
* nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
* and (c) will trigger that first erratum in some cases.
+ *
+ * TODO: Test if the atmel_spi_is_v2() branch below works on
+ * AT91RM9200 if we use some other register than CSR0. However, don't
+ * do this unconditionally since AP7000 has an errata where the BITS
+ * field in CSR0 overrides all other CSRs.
*/
static void cs_activate(struct atmel_spi *as, struct spi_device *spi)
{
- unsigned gpio = (unsigned) spi->controller_data;
+ struct atmel_spi_device *asd = spi->controller_state;
unsigned active = spi->mode & SPI_CS_HIGH;
u32 mr;
- int i;
- u32 csr;
- u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
-
- /* Make sure clock polarity is correct */
- for (i = 0; i < spi->master->num_chipselect; i++) {
- csr = spi_readl(as, CSR0 + 4 * i);
- if ((csr ^ cpol) & SPI_BIT(CPOL))
- spi_writel(as, CSR0 + 4 * i, csr ^ SPI_BIT(CPOL));
- }
- mr = spi_readl(as, MR);
- mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
+ if (atmel_spi_is_v2()) {
+ /*
+ * Always use CSR0. This ensures that the clock
+ * switches to the correct idle polarity before we
+ * toggle the CS.
+ */
+ spi_writel(as, CSR0, asd->csr);
+ spi_writel(as, MR, SPI_BF(PCS, 0x0e) | SPI_BIT(MODFDIS)
+ | SPI_BIT(MSTR));
+ mr = spi_readl(as, MR);
+ gpio_set_value(asd->npcs_pin, active);
+ } else {
+ u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
+ int i;
+ u32 csr;
+
+ /* Make sure clock polarity is correct */
+ for (i = 0; i < spi->master->num_chipselect; i++) {
+ csr = spi_readl(as, CSR0 + 4 * i);
+ if ((csr ^ cpol) & SPI_BIT(CPOL))
+ spi_writel(as, CSR0 + 4 * i,
+ csr ^ SPI_BIT(CPOL));
+ }
+
+ mr = spi_readl(as, MR);
+ mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
+ if (spi->chip_select != 0)
+ gpio_set_value(asd->npcs_pin, active);
+ spi_writel(as, MR, mr);
+ }
dev_dbg(&spi->dev, "activate %u%s, mr %08x\n",
- gpio, active ? " (high)" : "",
+ asd->npcs_pin, active ? " (high)" : "",
mr);
-
- if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
- gpio_set_value(gpio, active);
- spi_writel(as, MR, mr);
}
static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
{
- unsigned gpio = (unsigned) spi->controller_data;
+ struct atmel_spi_device *asd = spi->controller_state;
unsigned active = spi->mode & SPI_CS_HIGH;
u32 mr;
@@ -126,11 +160,11 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
}
dev_dbg(&spi->dev, "DEactivate %u%s, mr %08x\n",
- gpio, active ? " (low)" : "",
+ asd->npcs_pin, active ? " (low)" : "",
mr);
- if (!(cpu_is_at91rm9200() && spi->chip_select == 0))
- gpio_set_value(gpio, !active);
+ if (atmel_spi_is_v2() || spi->chip_select != 0)
+ gpio_set_value(asd->npcs_pin, !active);
}
static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
@@ -502,6 +536,7 @@ atmel_spi_interrupt(int irq, void *dev_id)
static int atmel_spi_setup(struct spi_device *spi)
{
struct atmel_spi *as;
+ struct atmel_spi_device *asd;
u32 scbr, csr;
unsigned int bits = spi->bits_per_word;
unsigned long bus_hz;
@@ -536,19 +571,16 @@ static int atmel_spi_setup(struct spi_device *spi)
}
/* see notes above re chipselect */
- if (cpu_is_at91rm9200()
+ if (!atmel_spi_is_v2()
&& spi->chip_select == 0
&& (spi->mode & SPI_CS_HIGH)) {
dev_dbg(&spi->dev, "setup: can't be active-high\n");
return -EINVAL;
}
- /*
- * Pre-new_1 chips start out at half the peripheral
- * bus speed.
- */
+ /* v1 chips start out at half the peripheral bus speed. */
bus_hz = clk_get_rate(as->clk);
- if (!as->new_1)
+ if (!atmel_spi_is_v2())
bus_hz /= 2;
if (spi->max_speed_hz) {
@@ -589,11 +621,20 @@ static int atmel_spi_setup(struct spi_device *spi)
/* chipselect must have been muxed as GPIO (e.g. in board setup) */
npcs_pin = (unsigned int)spi->controller_data;
- if (!spi->controller_state) {
+ asd = spi->controller_state;
+ if (!asd) {
+ asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
+ if (!asd)
+ return -ENOMEM;
+
ret = gpio_request(npcs_pin, spi->dev.bus_id);
- if (ret)
+ if (ret) {
+ kfree(asd);
return ret;
- spi->controller_state = (void *)npcs_pin;
+ }
+
+ asd->npcs_pin = npcs_pin;
+ spi->controller_state = asd;
gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH));
} else {
unsigned long flags;
@@ -605,11 +646,14 @@ static int atmel_spi_setup(struct spi_device *spi)
spin_unlock_irqrestore(&as->lock, flags);
}
+ asd->csr = csr;
+
dev_dbg(&spi->dev,
"setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
- spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
+ if (!atmel_spi_is_v2())
+ spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
return 0;
}
@@ -626,8 +670,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
dev_dbg(controller, "new message %p submitted for %s\n",
msg, spi->dev.bus_id);
- if (unlikely(list_empty(&msg->transfers)
- || !spi->max_speed_hz))
+ if (unlikely(list_empty(&msg->transfers)))
return -EINVAL;
if (as->stopping)
@@ -684,10 +727,11 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
static void atmel_spi_cleanup(struct spi_device *spi)
{
struct atmel_spi *as = spi_master_get_devdata(spi->master);
+ struct atmel_spi_device *asd = spi->controller_state;
unsigned gpio = (unsigned) spi->controller_data;
unsigned long flags;
- if (!spi->controller_state)
+ if (!asd)
return;
spin_lock_irqsave(&as->lock, flags);
@@ -697,7 +741,9 @@ static void atmel_spi_cleanup(struct spi_device *spi)
}
spin_unlock_irqrestore(&as->lock, flags);
+ spi->controller_state = NULL;
gpio_free(gpio);
+ kfree(asd);
}
/*-------------------------------------------------------------------------*/
@@ -755,8 +801,6 @@ static int __init atmel_spi_probe(struct platform_device *pdev)
goto out_free_buffer;
as->irq = irq;
as->clk = clk;
- if (!cpu_is_at91rm9200())
- as->new_1 = 1;
ret = request_irq(irq, atmel_spi_interrupt, 0,
pdev->dev.bus_id, master);
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 6104f461a3cd..d0fc4ca2f656 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1561,11 +1561,12 @@ out_error_master_alloc:
static int pxa2xx_spi_remove(struct platform_device *pdev)
{
struct driver_data *drv_data = platform_get_drvdata(pdev);
- struct ssp_device *ssp = drv_data->ssp;
+ struct ssp_device *ssp;
int status = 0;
if (!drv_data)
return 0;
+ ssp = drv_data->ssp;
/* Remove the queue */
status = destroy_queue(drv_data);
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 3734dc9708e1..643908b74bc0 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -47,7 +47,7 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf)
{
const struct spi_device *spi = to_spi_device(dev);
- return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias);
+ return sprintf(buf, "%s\n", spi->modalias);
}
static struct device_attribute spi_dev_attrs[] = {
@@ -63,7 +63,7 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
{
const struct spi_device *spi = to_spi_device(dev);
- return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
+ return strcmp(spi->modalias, drv->name) == 0;
}
static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -243,8 +243,7 @@ int spi_add_device(struct spi_device *spi)
}
/* Set the bus ID string */
- snprintf(spi->dev.bus_id, sizeof spi->dev.bus_id,
- "%s.%u", spi->master->dev.bus_id,
+ dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
spi->chip_select);
@@ -254,7 +253,7 @@ int spi_add_device(struct spi_device *spi)
*/
mutex_lock(&spi_add_lock);
- if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id)
+ if (bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev))
!= NULL) {
dev_err(dev, "chipselect %d already in use\n",
spi->chip_select);
@@ -269,7 +268,7 @@ int spi_add_device(struct spi_device *spi)
status = spi->master->setup(spi);
if (status < 0) {
dev_err(dev, "can't %s %s, status %d\n",
- "setup", spi->dev.bus_id, status);
+ "setup", dev_name(&spi->dev), status);
goto done;
}
@@ -277,9 +276,9 @@ int spi_add_device(struct spi_device *spi)
status = device_add(&spi->dev);
if (status < 0)
dev_err(dev, "can't %s %s, status %d\n",
- "add", spi->dev.bus_id, status);
+ "add", dev_name(&spi->dev), status);
else
- dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
+ dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
done:
mutex_unlock(&spi_add_lock);
@@ -504,12 +503,11 @@ int spi_register_master(struct spi_master *master)
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
- snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
- "spi%u", master->bus_num);
+ dev_set_name(&master->dev, "spi%u", master->bus_num);
status = device_add(&master->dev);
if (status < 0)
goto done;
- dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id,
+ dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
dynamic ? " (dynamic)" : "");
/* populate children from any spi device tables */
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 96cc39ecb6e2..85e61f451218 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -475,7 +475,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue(
- bitbang->master->dev.parent->bus_id);
+ dev_name(bitbang->master->dev.parent));
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c
index 0ee2b2090252..c2184866fa9c 100644
--- a/drivers/spi/spi_butterfly.c
+++ b/drivers/spi/spi_butterfly.c
@@ -287,7 +287,7 @@ static void butterfly_attach(struct parport *p)
pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
if (pp->dataflash)
pr_debug("%s: dataflash at %s\n", p->name,
- pp->dataflash->dev.bus_id);
+ dev_name(&pp->dataflash->dev));
// dev_info(_what?_, ...)
pr_info("%s: AVR Butterfly\n", p->name);
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
new file mode 100644
index 000000000000..49698cabc30d
--- /dev/null
+++ b/drivers/spi/spi_gpio.c
@@ -0,0 +1,360 @@
+/*
+ * spi_gpio.c - SPI master driver using generic bitbanged GPIO
+ *
+ * Copyright (C) 2006,2008 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_gpio.h>
+
+
+/*
+ * This bitbanging SPI master driver should help make systems usable
+ * when a native hardware SPI engine is not available, perhaps because
+ * its driver isn't yet working or because the I/O pins it requires
+ * are used for other purposes.
+ *
+ * platform_device->driver_data ... points to spi_gpio
+ *
+ * spi->controller_state ... reserved for bitbang framework code
+ * spi->controller_data ... holds chipselect GPIO
+ *
+ * spi->master->dev.driver_data ... points to spi_gpio->bitbang
+ */
+
+struct spi_gpio {
+ struct spi_bitbang bitbang;
+ struct spi_gpio_platform_data pdata;
+ struct platform_device *pdev;
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Because the overhead of going through four GPIO procedure calls
+ * per transferred bit can make performance a problem, this code
+ * is set up so that you can use it in either of two ways:
+ *
+ * - The slow generic way: set up platform_data to hold the GPIO
+ * numbers used for MISO/MOSI/SCK, and issue procedure calls for
+ * each of them. This driver can handle several such busses.
+ *
+ * - The quicker inlined way: only helps with platform GPIO code
+ * that inlines operations for constant GPIOs. This can give
+ * you tight (fast!) inner loops, but each such bus needs a
+ * new driver. You'll define a new C file, with Makefile and
+ * Kconfig support; the C code can be a total of six lines:
+ *
+ * #define DRIVER_NAME "myboard_spi2"
+ * #define SPI_MISO_GPIO 119
+ * #define SPI_MOSI_GPIO 120
+ * #define SPI_SCK_GPIO 121
+ * #define SPI_N_CHIPSEL 4
+ * #include "spi_gpio.c"
+ */
+
+#ifndef DRIVER_NAME
+#define DRIVER_NAME "spi_gpio"
+
+#define GENERIC_BITBANG /* vs tight inlines */
+
+/* all functions referencing these symbols must define pdata */
+#define SPI_MISO_GPIO ((pdata)->miso)
+#define SPI_MOSI_GPIO ((pdata)->mosi)
+#define SPI_SCK_GPIO ((pdata)->sck)
+
+#define SPI_N_CHIPSEL ((pdata)->num_chipselect)
+
+#endif
+
+/*----------------------------------------------------------------------*/
+
+static inline const struct spi_gpio_platform_data * __pure
+spi_to_pdata(const struct spi_device *spi)
+{
+ const struct spi_bitbang *bang;
+ const struct spi_gpio *spi_gpio;
+
+ bang = spi_master_get_devdata(spi->master);
+ spi_gpio = container_of(bang, struct spi_gpio, bitbang);
+ return &spi_gpio->pdata;
+}
+
+/* this is #defined to avoid unused-variable warnings when inlining */
+#define pdata spi_to_pdata(spi)
+
+static inline void setsck(const struct spi_device *spi, int is_on)
+{
+ gpio_set_value(SPI_SCK_GPIO, is_on);
+}
+
+static inline void setmosi(const struct spi_device *spi, int is_on)
+{
+ gpio_set_value(SPI_MOSI_GPIO, is_on);
+}
+
+static inline int getmiso(const struct spi_device *spi)
+{
+ return gpio_get_value(SPI_MISO_GPIO);
+}
+
+#undef pdata
+
+/*
+ * NOTE: this clocks "as fast as we can". It "should" be a function of the
+ * requested device clock. Software overhead means we usually have trouble
+ * reaching even one Mbit/sec (except when we can inline bitops), so for now
+ * we'll just assume we never need additional per-bit slowdowns.
+ */
+#define spidelay(nsecs) do {} while (0)
+
+#define EXPAND_BITBANG_TXRX
+#include <linux/spi/spi_bitbang.h>
+
+/*
+ * These functions can leverage inline expansion of GPIO calls to shrink
+ * costs for a txrx bit, often by factors of around ten (by instruction
+ * count). That is particularly visible for larger word sizes, but helps
+ * even with default 8-bit words.
+ *
+ * REVISIT overheads calling these functions for each word also have
+ * significant performance costs. Having txrx_bufs() calls that inline
+ * the txrx_word() logic would help performance, e.g. on larger blocks
+ * used with flash storage or MMC/SD. There should also be ways to make
+ * GCC be less stupid about reloading registers inside the I/O loops,
+ * even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3?
+ */
+
+static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,
+ unsigned nsecs, u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,
+ unsigned nsecs, u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,
+ unsigned nsecs, u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
+}
+
+static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,
+ unsigned nsecs, u32 word, u8 bits)
+{
+ return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
+}
+
+/*----------------------------------------------------------------------*/
+
+static void spi_gpio_chipselect(struct spi_device *spi, int is_active)
+{
+ unsigned long cs = (unsigned long) spi->controller_data;
+
+ /* set initial clock polarity */
+ if (is_active)
+ setsck(spi, spi->mode & SPI_CPOL);
+
+ /* SPI is normally active-low */
+ gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+}
+
+static int spi_gpio_setup(struct spi_device *spi)
+{
+ unsigned long cs = (unsigned long) spi->controller_data;
+ int status = 0;
+
+ if (spi->bits_per_word > 32)
+ return -EINVAL;
+
+ if (!spi->controller_state) {
+ status = gpio_request(cs, spi->dev.bus_id);
+ if (status)
+ return status;
+ status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
+ }
+ if (!status)
+ status = spi_bitbang_setup(spi);
+ if (status) {
+ if (!spi->controller_state)
+ gpio_free(cs);
+ }
+ return status;
+}
+
+static void spi_gpio_cleanup(struct spi_device *spi)
+{
+ unsigned long cs = (unsigned long) spi->controller_data;
+
+ gpio_free(cs);
+ spi_bitbang_cleanup(spi);
+}
+
+static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in)
+{
+ int value;
+
+ value = gpio_request(pin, label);
+ if (value == 0) {
+ if (is_in)
+ value = gpio_direction_input(pin);
+ else
+ value = gpio_direction_output(pin, 0);
+ }
+ return value;
+}
+
+static int __init
+spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label)
+{
+ int value;
+
+ /* NOTE: SPI_*_GPIO symbols may reference "pdata" */
+
+ value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false);
+ if (value)
+ goto done;
+
+ value = spi_gpio_alloc(SPI_MISO_GPIO, label, true);
+ if (value)
+ goto free_mosi;
+
+ value = spi_gpio_alloc(SPI_SCK_GPIO, label, false);
+ if (value)
+ goto free_miso;
+
+ goto done;
+
+free_miso:
+ gpio_free(SPI_MISO_GPIO);
+free_mosi:
+ gpio_free(SPI_MOSI_GPIO);
+done:
+ return value;
+}
+
+static int __init spi_gpio_probe(struct platform_device *pdev)
+{
+ int status;
+ struct spi_master *master;
+ struct spi_gpio *spi_gpio;
+ struct spi_gpio_platform_data *pdata;
+
+ pdata = pdev->dev.platform_data;
+#ifdef GENERIC_BITBANG
+ if (!pdata || !pdata->num_chipselect)
+ return -ENODEV;
+#endif
+
+ status = spi_gpio_request(pdata, dev_name(&pdev->dev));
+ if (status < 0)
+ return status;
+
+ master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio);
+ if (!master) {
+ status = -ENOMEM;
+ goto gpio_free;
+ }
+ spi_gpio = spi_master_get_devdata(master);
+ platform_set_drvdata(pdev, spi_gpio);
+
+ spi_gpio->pdev = pdev;
+ if (pdata)
+ spi_gpio->pdata = *pdata;
+
+ master->bus_num = pdev->id;
+ master->num_chipselect = SPI_N_CHIPSEL;
+ master->setup = spi_gpio_setup;
+ master->cleanup = spi_gpio_cleanup;
+
+ spi_gpio->bitbang.master = spi_master_get(master);
+ spi_gpio->bitbang.chipselect = spi_gpio_chipselect;
+ spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0;
+ spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1;
+ spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2;
+ spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3;
+ spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer;
+ spi_gpio->bitbang.flags = SPI_CS_HIGH;
+
+ status = spi_bitbang_start(&spi_gpio->bitbang);
+ if (status < 0) {
+ spi_master_put(spi_gpio->bitbang.master);
+gpio_free:
+ gpio_free(SPI_MISO_GPIO);
+ gpio_free(SPI_MOSI_GPIO);
+ gpio_free(SPI_SCK_GPIO);
+ spi_master_put(master);
+ }
+
+ return status;
+}
+
+static int __exit spi_gpio_remove(struct platform_device *pdev)
+{
+ struct spi_gpio *spi_gpio;
+ struct spi_gpio_platform_data *pdata;
+ int status;
+
+ spi_gpio = platform_get_drvdata(pdev);
+ pdata = pdev->dev.platform_data;
+
+ /* stop() unregisters child devices too */
+ status = spi_bitbang_stop(&spi_gpio->bitbang);
+ spi_master_put(spi_gpio->bitbang.master);
+
+ platform_set_drvdata(pdev, NULL);
+
+ gpio_free(SPI_MISO_GPIO);
+ gpio_free(SPI_MOSI_GPIO);
+ gpio_free(SPI_SCK_GPIO);
+
+ return status;
+}
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+
+static struct platform_driver spi_gpio_driver = {
+ .driver.name = DRIVER_NAME,
+ .driver.owner = THIS_MODULE,
+ .remove = __exit_p(spi_gpio_remove),
+};
+
+static int __init spi_gpio_init(void)
+{
+ return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe);
+}
+module_init(spi_gpio_init);
+
+static void __exit spi_gpio_exit(void)
+{
+ platform_driver_unregister(&spi_gpio_driver);
+}
+module_exit(spi_gpio_exit);
+
+
+MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO ");
+MODULE_AUTHOR("David Brownell");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c
index 39d8d8ad65c0..568c781ad91c 100644
--- a/drivers/spi/spi_lm70llp.c
+++ b/drivers/spi/spi_lm70llp.c
@@ -1,5 +1,5 @@
/*
- * spi_lm70llp.c - driver for lm70llp eval board for the LM70 sensor
+ * spi_lm70llp.c - driver for LM70EVAL-LLP board for the LM70 sensor
*
* Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
*
@@ -40,8 +40,12 @@
* master controller driver. The hwmon/lm70 driver is a "SPI protocol
* driver", layered on top of this one and usable without the lm70llp.
*
+ * Datasheet and Schematic:
* The LM70 is a temperature sensor chip from National Semiconductor; its
* datasheet is available at http://www.national.com/pf/LM/LM70.html
+ * The schematic for this particular board (the LM70EVAL-LLP) is
+ * available (on page 4) here:
+ * http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf
*
* Also see Documentation/spi/spi-lm70llp. The SPI<->parport code here is
* (heavily) based on spi-butterfly by David Brownell.
@@ -64,7 +68,7 @@
*
* Note that parport pin 13 actually gets inverted by the transistor
* arrangement which lets either the parport or the LM70 drive the
- * SI/SO signal.
+ * SI/SO signal (see the schematic for details).
*/
#define DRVNAME "spi-lm70llp"
@@ -106,12 +110,16 @@ static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi)
static inline void deassertCS(struct spi_lm70llp *pp)
{
u8 data = parport_read_data(pp->port);
+
+ data &= ~0x80; /* pull D7/SI-out low while de-asserted */
parport_write_data(pp->port, data | nCS);
}
static inline void assertCS(struct spi_lm70llp *pp)
{
u8 data = parport_read_data(pp->port);
+
+ data |= 0x80; /* pull D7/SI-out high so lm70 drives SO-in */
parport_write_data(pp->port, data & ~nCS);
}
@@ -184,22 +192,7 @@ static void lm70_chipselect(struct spi_device *spi, int value)
*/
static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits)
{
- static u32 sio=0;
- static int first_time=1;
-
- /* First time: perform SPI bitbang and return the LSB of
- * the result of the SPI call.
- */
- if (first_time) {
- sio = bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
- first_time=0;
- return (sio & 0x00ff);
- }
- /* Return the MSB of the result of the SPI call */
- else {
- first_time=1;
- return (sio >> 8);
- }
+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
}
static void spi_lm70llp_attach(struct parport *p)
@@ -287,16 +280,15 @@ static void spi_lm70llp_attach(struct parport *p)
pp->spidev_lm70 = spi_new_device(pp->bitbang.master, &pp->info);
if (pp->spidev_lm70)
dev_dbg(&pp->spidev_lm70->dev, "spidev_lm70 at %s\n",
- pp->spidev_lm70->dev.bus_id);
+ dev_name(&pp->spidev_lm70->dev));
else {
printk(KERN_WARNING "%s: spi_new_device failed\n", DRVNAME);
status = -ENODEV;
goto out_bitbang_stop;
}
- pp->spidev_lm70->bits_per_word = 16;
+ pp->spidev_lm70->bits_per_word = 8;
lm70llp = pp;
-
return;
out_bitbang_stop:
@@ -326,7 +318,6 @@ static void spi_lm70llp_detach(struct parport *p)
/* power down */
parport_write_data(pp->port, 0);
- msleep(10);
parport_release(pp->pd);
parport_unregister_device(pp->pd);
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 256d18395a23..b3ebc1d0f85f 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -19,6 +19,7 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
@@ -27,7 +28,6 @@
#include <asm/dma.h>
#include <mach/hardware.h>
-#include <mach/regs-gpio.h>
#include <plat/regs-spi.h>
#include <mach/spi.h>
@@ -66,7 +66,7 @@ static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
{
- s3c2410_gpio_setpin(spi->pin_cs, pol);
+ gpio_set_value(spi->pin_cs, pol);
}
static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
@@ -248,8 +248,13 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)
writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);
writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON);
- if (hw->pdata && hw->pdata->gpio_setup)
- hw->pdata->gpio_setup(hw->pdata, 1);
+ if (hw->pdata) {
+ if (hw->set_cs == s3c24xx_spi_gpiocs)
+ gpio_direction_output(hw->pdata->pin_cs, 1);
+
+ if (hw->pdata->gpio_setup)
+ hw->pdata->gpio_setup(hw->pdata, 1);
+ }
}
static int __init s3c24xx_spi_probe(struct platform_device *pdev)
@@ -343,18 +348,27 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev)
goto err_no_clk;
}
- s3c24xx_spi_initialsetup(hw);
-
/* setup any gpio we can */
if (!pdata->set_cs) {
- hw->set_cs = s3c24xx_spi_gpiocs;
+ if (pdata->pin_cs < 0) {
+ dev_err(&pdev->dev, "No chipselect pin\n");
+ goto err_register;
+ }
- s3c2410_gpio_setpin(pdata->pin_cs, 1);
- s3c2410_gpio_cfgpin(pdata->pin_cs, S3C2410_GPIO_OUTPUT);
+ err = gpio_request(pdata->pin_cs, dev_name(&pdev->dev));
+ if (err) {
+ dev_err(&pdev->dev, "Failed to get gpio for cs\n");
+ goto err_register;
+ }
+
+ hw->set_cs = s3c24xx_spi_gpiocs;
+ gpio_direction_output(pdata->pin_cs, 1);
} else
hw->set_cs = pdata->set_cs;
+ s3c24xx_spi_initialsetup(hw);
+
/* register our spi controller */
err = spi_bitbang_start(&hw->bitbang);
@@ -366,6 +380,9 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev)
return 0;
err_register:
+ if (hw->set_cs == s3c24xx_spi_gpiocs)
+ gpio_free(pdata->pin_cs);
+
clk_disable(hw->clk);
clk_put(hw->clk);
@@ -401,6 +418,9 @@ static int __exit s3c24xx_spi_remove(struct platform_device *dev)
free_irq(hw->irq, hw);
iounmap(hw->regs);
+ if (hw->set_cs == s3c24xx_spi_gpiocs)
+ gpio_free(hw->pdata->pin_cs);
+
release_resource(hw->ioarea);
kfree(hw->ioarea);
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 68d6f4988fb5..fe7e5f35e5d0 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -15,12 +15,15 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_spi.h>
+
#include <linux/spi/spi.h>
#include <linux/spi/spi_bitbang.h>
#include <linux/io.h>
-#include <syslib/virtex_devices.h>
-
#define XILINX_SPI_NAME "xilinx_spi"
/* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e)
@@ -144,23 +147,14 @@ static int xilinx_spi_setup_transfer(struct spi_device *spi,
struct spi_transfer *t)
{
u8 bits_per_word;
- u32 hz;
- struct xilinx_spi *xspi = spi_master_get_devdata(spi->master);
bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
- hz = (t) ? t->speed_hz : spi->max_speed_hz;
if (bits_per_word != 8) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
__func__, bits_per_word);
return -EINVAL;
}
- if (hz && xspi->speed_hz > hz) {
- dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n",
- __func__, hz);
- return -EINVAL;
- }
-
return 0;
}
@@ -304,32 +298,38 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __init xilinx_spi_probe(struct platform_device *dev)
+static int __init xilinx_spi_of_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
- int ret = 0;
struct spi_master *master;
struct xilinx_spi *xspi;
- struct xspi_platform_data *pdata;
- struct resource *r;
+ struct resource r_irq_struct;
+ struct resource r_mem_struct;
+
+ struct resource *r_irq = &r_irq_struct;
+ struct resource *r_mem = &r_mem_struct;
+ int rc = 0;
+ const u32 *prop;
+ int len;
/* Get resources(memory, IRQ) associated with the device */
- master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi));
+ master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi));
if (master == NULL) {
return -ENOMEM;
}
- platform_set_drvdata(dev, master);
- pdata = dev->dev.platform_data;
+ dev_set_drvdata(&ofdev->dev, master);
- if (pdata == NULL) {
- ret = -ENODEV;
+ rc = of_address_to_resource(ofdev->node, 0, r_mem);
+ if (rc) {
+ dev_warn(&ofdev->dev, "invalid address\n");
goto put_master;
}
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (r == NULL) {
- ret = -ENODEV;
+ rc = of_irq_to_resource(ofdev->node, 0, r_irq);
+ if (rc == NO_IRQ) {
+ dev_warn(&ofdev->dev, "no IRQ found\n");
goto put_master;
}
@@ -341,47 +341,57 @@ static int __init xilinx_spi_probe(struct platform_device *dev)
xspi->bitbang.master->setup = xilinx_spi_setup;
init_completion(&xspi->done);
- if (!request_mem_region(r->start,
- r->end - r->start + 1, XILINX_SPI_NAME)) {
- ret = -ENXIO;
+ xspi->irq = r_irq->start;
+
+ if (!request_mem_region(r_mem->start,
+ r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) {
+ rc = -ENXIO;
+ dev_warn(&ofdev->dev, "memory request failure\n");
goto put_master;
}
- xspi->regs = ioremap(r->start, r->end - r->start + 1);
+ xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1);
if (xspi->regs == NULL) {
- ret = -ENOMEM;
+ rc = -ENOMEM;
+ dev_warn(&ofdev->dev, "ioremap failure\n");
goto put_master;
}
+ xspi->irq = r_irq->start;
- ret = platform_get_irq(dev, 0);
- if (ret < 0) {
- ret = -ENXIO;
- goto unmap_io;
- }
- xspi->irq = ret;
+ /* dynamic bus assignment */
+ master->bus_num = -1;
- master->bus_num = pdata->bus_num;
- master->num_chipselect = pdata->num_chipselect;
- xspi->speed_hz = pdata->speed_hz;
+ /* number of slave select bits is required */
+ prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len);
+ if (!prop || len < sizeof(*prop)) {
+ dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n");
+ goto put_master;
+ }
+ master->num_chipselect = *prop;
/* SPI controller initializations */
xspi_init_hw(xspi->regs);
/* Register for SPI Interrupt */
- ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
- if (ret != 0)
+ rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi);
+ if (rc != 0) {
+ dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq);
goto unmap_io;
+ }
- ret = spi_bitbang_start(&xspi->bitbang);
- if (ret != 0) {
- dev_err(&dev->dev, "spi_bitbang_start FAILED\n");
+ rc = spi_bitbang_start(&xspi->bitbang);
+ if (rc != 0) {
+ dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n");
goto free_irq;
}
- dev_info(&dev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
- r->start, (u32)xspi->regs, xspi->irq);
+ dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n",
+ (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq);
- return ret;
+ /* Add any subnodes on the SPI bus */
+ of_register_spi_devices(master, ofdev->node);
+
+ return rc;
free_irq:
free_irq(xspi->irq, xspi);
@@ -389,21 +399,21 @@ unmap_io:
iounmap(xspi->regs);
put_master:
spi_master_put(master);
- return ret;
+ return rc;
}
-static int __devexit xilinx_spi_remove(struct platform_device *dev)
+static int __devexit xilinx_spi_remove(struct of_device *ofdev)
{
struct xilinx_spi *xspi;
struct spi_master *master;
- master = platform_get_drvdata(dev);
+ master = platform_get_drvdata(ofdev);
xspi = spi_master_get_devdata(master);
spi_bitbang_stop(&xspi->bitbang);
free_irq(xspi->irq, xspi);
iounmap(xspi->regs);
- platform_set_drvdata(dev, 0);
+ dev_set_drvdata(&ofdev->dev, 0);
spi_master_put(xspi->bitbang.master);
return 0;
@@ -412,27 +422,42 @@ static int __devexit xilinx_spi_remove(struct platform_device *dev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:" XILINX_SPI_NAME);
-static struct platform_driver xilinx_spi_driver = {
- .probe = xilinx_spi_probe,
- .remove = __devexit_p(xilinx_spi_remove),
+static int __exit xilinx_spi_of_remove(struct of_device *op)
+{
+ return xilinx_spi_remove(op);
+}
+
+static struct of_device_id xilinx_spi_of_match[] = {
+ { .compatible = "xlnx,xps-spi-2.00.a", },
+ { .compatible = "xlnx,xps-spi-2.00.b", },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
+
+static struct of_platform_driver xilinx_spi_of_driver = {
+ .owner = THIS_MODULE,
+ .name = "xilinx-xps-spi",
+ .match_table = xilinx_spi_of_match,
+ .probe = xilinx_spi_of_probe,
+ .remove = __exit_p(xilinx_spi_of_remove),
.driver = {
- .name = XILINX_SPI_NAME,
+ .name = "xilinx-xps-spi",
.owner = THIS_MODULE,
},
};
static int __init xilinx_spi_init(void)
{
- return platform_driver_register(&xilinx_spi_driver);
+ return of_register_platform_driver(&xilinx_spi_of_driver);
}
module_init(xilinx_spi_init);
static void __exit xilinx_spi_exit(void)
{
- platform_driver_unregister(&xilinx_spi_driver);
+ of_unregister_platform_driver(&xilinx_spi_of_driver);
}
module_exit(xilinx_spi_exit);
-
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx SPI driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 5d457c96bd7e..ce6badded47a 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -49,6 +49,8 @@ source "drivers/staging/sxg/Kconfig"
source "drivers/staging/me4000/Kconfig"
+source "drivers/staging/meilhaus/Kconfig"
+
source "drivers/staging/go7007/Kconfig"
source "drivers/staging/usbip/Kconfig"
@@ -63,5 +65,35 @@ source "drivers/staging/at76_usb/Kconfig"
source "drivers/staging/poch/Kconfig"
+source "drivers/staging/agnx/Kconfig"
+
+source "drivers/staging/otus/Kconfig"
+
+source "drivers/staging/rt2860/Kconfig"
+
+source "drivers/staging/rt2870/Kconfig"
+
+source "drivers/staging/benet/Kconfig"
+
+source "drivers/staging/comedi/Kconfig"
+
+source "drivers/staging/asus_oled/Kconfig"
+
+source "drivers/staging/panel/Kconfig"
+
+source "drivers/staging/altpciechdma/Kconfig"
+
+source "drivers/staging/rtl8187se/Kconfig"
+
+source "drivers/staging/rspiusb/Kconfig"
+
+source "drivers/staging/mimio/Kconfig"
+
+source "drivers/staging/frontier/Kconfig"
+
+source "drivers/staging/epl/Kconfig"
+
+source "drivers/staging/android/Kconfig"
+
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 71c4d53760b8..9ddcc2bb3365 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_ET131X) += et131x/
obj-$(CONFIG_SLICOSS) += slicoss/
obj-$(CONFIG_SXG) += sxg/
obj-$(CONFIG_ME4000) += me4000/
+obj-$(CONFIG_MEILHAUS) += meilhaus/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
obj-$(CONFIG_USB_IP_COMMON) += usbip/
obj-$(CONFIG_W35UND) += winbond/
@@ -14,3 +15,18 @@ obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_USB_ATMEL) += at76_usb/
obj-$(CONFIG_POCH) += poch/
+obj-$(CONFIG_AGNX) += agnx/
+obj-$(CONFIG_OTUS) += otus/
+obj-$(CONFIG_RT2860) += rt2860/
+obj-$(CONFIG_RT2870) += rt2870/
+obj-$(CONFIG_BENET) += benet/
+obj-$(CONFIG_COMEDI) += comedi/
+obj-$(CONFIG_ASUS_OLED) += asus_oled/
+obj-$(CONFIG_PANEL) += panel/
+obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma/
+obj-$(CONFIG_RTL8187SE) += rtl8187se/
+obj-$(CONFIG_USB_RSPI) += rspiusb/
+obj-$(CONFIG_INPUT_MIMIO) += mimio/
+obj-$(CONFIG_TRANZPORT) += frontier/
+obj-$(CONFIG_EPL) += epl/
+obj-$(CONFIG_ANDROID) += android/
diff --git a/drivers/staging/agnx/Kconfig b/drivers/staging/agnx/Kconfig
new file mode 100644
index 000000000000..7f43549e36dd
--- /dev/null
+++ b/drivers/staging/agnx/Kconfig
@@ -0,0 +1,5 @@
+config AGNX
+ tristate "Wireless Airgo AGNX support"
+ depends on WLAN_80211 && MAC80211
+ ---help---
+ This is an experimental driver for Airgo AGNX00 wireless chip.
diff --git a/drivers/staging/agnx/Makefile b/drivers/staging/agnx/Makefile
new file mode 100644
index 000000000000..1216564a312d
--- /dev/null
+++ b/drivers/staging/agnx/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_AGNX) += agnx.o
+
+agnx-objs := rf.o \
+ pci.o \
+ xmit.o \
+ table.o \
+ sta.o \
+ phy.o
diff --git a/drivers/staging/agnx/TODO b/drivers/staging/agnx/TODO
new file mode 100644
index 000000000000..89bec74318aa
--- /dev/null
+++ b/drivers/staging/agnx/TODO
@@ -0,0 +1,22 @@
+2008 7/18
+
+The RX has can't receive OFDM packet correctly,
+Guess it need be do RX calibrate.
+
+
+before 2008 3/1
+
+1: The RX get too much "CRC failed" pakets, it make the card work very unstable,
+2: After running a while, the card will get infinity "RX Frame" and "Error"
+interrupt, not know the root reason so far, try to fix it
+3: Using two tx queue txd and txm but not only txm.
+4: Set the hdr correctly.
+5: Try to do recalibrate correvtly
+6: To support G mode in future
+7: Fix the mac address can't be readed and set correctly in BE machine.
+8: Fix include and exclude FCS in promisous mode and manage mode
+9: Using sta_notify to notice sta change
+10: Turn on frame reception at the end of start
+11: Guess the card support HW_MULTICAST_FILTER
+12: The tx process should be implment atomic?
+13: Using mac80211 function to control the TX&RX LED.
diff --git a/drivers/staging/agnx/agnx.h b/drivers/staging/agnx/agnx.h
new file mode 100644
index 000000000000..20f36da62475
--- /dev/null
+++ b/drivers/staging/agnx/agnx.h
@@ -0,0 +1,156 @@
+#ifndef AGNX_H_
+#define AGNX_H_
+
+#include <linux/io.h>
+
+#include "xmit.h"
+
+#define PFX KBUILD_MODNAME ": "
+
+static inline u32 agnx_read32(void __iomem *mem_region, u32 offset)
+{
+ return ioread32(mem_region + offset);
+}
+
+static inline void agnx_write32(void __iomem *mem_region, u32 offset, u32 val)
+{
+ iowrite32(val, mem_region + offset);
+}
+
+/* static const struct ieee80211_rate agnx_rates_80211b[] = { */
+/* { .rate = 10, */
+/* .val = 0xa, */
+/* .flags = IEEE80211_RATE_CCK }, */
+/* { .rate = 20, */
+/* .val = 0x14, */
+/* .hw_value = -0x14, */
+/* .flags = IEEE80211_RATE_CCK_2 }, */
+/* { .rate = 55, */
+/* .val = 0x37, */
+/* .val2 = -0x37, */
+/* .flags = IEEE80211_RATE_CCK_2 }, */
+/* { .rate = 110, */
+/* .val = 0x6e, */
+/* .val2 = -0x6e, */
+/* .flags = IEEE80211_RATE_CCK_2 } */
+/* }; */
+
+
+static const struct ieee80211_rate agnx_rates_80211g[] = {
+/* { .bitrate = 10, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
+/* { .bitrate = 20, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
+/* { .bitrate = 55, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
+/* { .bitrate = 110, .hw_value = 4, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, */
+ { .bitrate = 10, .hw_value = 1, },
+ { .bitrate = 20, .hw_value = 2, },
+ { .bitrate = 55, .hw_value = 3, },
+ { .bitrate = 110, .hw_value = 4,},
+
+ { .bitrate = 60, .hw_value = 0xB, },
+ { .bitrate = 90, .hw_value = 0xF, },
+ { .bitrate = 120, .hw_value = 0xA },
+ { .bitrate = 180, .hw_value = 0xE, },
+// { .bitrate = 240, .hw_value = 0xd, },
+ { .bitrate = 360, .hw_value = 0xD, },
+ { .bitrate = 480, .hw_value = 0x8, },
+ { .bitrate = 540, .hw_value = 0xC, },
+};
+
+static const struct ieee80211_channel agnx_channels[] = {
+ { .center_freq = 2412, .hw_value = 1, },
+ { .center_freq = 2417, .hw_value = 2, },
+ { .center_freq = 2422, .hw_value = 3, },
+ { .center_freq = 2427, .hw_value = 4, },
+ { .center_freq = 2432, .hw_value = 5, },
+ { .center_freq = 2437, .hw_value = 6, },
+ { .center_freq = 2442, .hw_value = 7, },
+ { .center_freq = 2447, .hw_value = 8, },
+ { .center_freq = 2452, .hw_value = 9, },
+ { .center_freq = 2457, .hw_value = 10, },
+ { .center_freq = 2462, .hw_value = 11, },
+ { .center_freq = 2467, .hw_value = 12, },
+ { .center_freq = 2472, .hw_value = 13, },
+ { .center_freq = 2484, .hw_value = 14, },
+};
+
+#define NUM_DRIVE_MODES 2
+/* Agnx operate mode */
+enum {
+ AGNX_MODE_80211A,
+ AGNX_MODE_80211A_OOB,
+ AGNX_MODE_80211A_MIMO,
+ AGNX_MODE_80211B_SHORT,
+ AGNX_MODE_80211B_LONG,
+ AGNX_MODE_80211G,
+ AGNX_MODE_80211G_OOB,
+ AGNX_MODE_80211G_MIMO,
+};
+
+enum {
+ AGNX_UNINIT,
+ AGNX_START,
+ AGNX_STOP,
+};
+
+struct agnx_priv {
+ struct pci_dev *pdev;
+ struct ieee80211_hw *hw;
+
+ spinlock_t lock;
+ struct mutex mutex;
+ unsigned int init_status;
+
+ void __iomem *ctl; /* pointer to base ram address */
+ void __iomem *data; /* pointer to mem region #2 */
+
+ struct agnx_ring rx;
+ struct agnx_ring txm;
+ struct agnx_ring txd;
+
+ /* Need volatile? */
+ u32 irq_status;
+
+ struct delayed_work periodic_work; /* Periodic tasks like recalibrate*/
+ struct ieee80211_low_level_stats stats;
+
+// unsigned int phymode;
+ int mode;
+ int channel;
+ u8 bssid[ETH_ALEN];
+
+ u8 mac_addr[ETH_ALEN];
+ u8 revid;
+
+ struct ieee80211_supported_band band;
+};
+
+
+#define AGNX_CHAINS_MAX 6
+#define AGNX_PERIODIC_DELAY 60000 /* unit: ms */
+#define LOCAL_STAID 0 /* the station entry for the card itself */
+#define BSSID_STAID 1 /* the station entry for the bsssid AP */
+#define spi_delay() udelay(40)
+#define eeprom_delay() udelay(40)
+#define routing_table_delay() udelay(50)
+
+/* PDU pool MEM region #2 */
+#define AGNX_PDUPOOL 0x40000 /* PDU pool */
+#define AGNX_PDUPOOL_SIZE 0x8000 /* PDU pool size*/
+#define AGNX_PDU_TX_WQ 0x41000 /* PDU list TX workqueue */
+#define AGNX_PDU_FREE 0x41800 /* Free Pool */
+#define PDU_SIZE 0x80 /* Free Pool node size */
+#define PDU_FREE_CNT 0xd0 /* Free pool node count */
+
+
+/* RF stuffs */
+extern void rf_chips_init(struct agnx_priv *priv);
+extern void spi_rc_write(void __iomem *mem_region, u32 chip_ids, u32 sw);
+extern void calibrate_oscillator(struct agnx_priv *priv);
+extern void do_calibration(struct agnx_priv *priv);
+extern void antenna_calibrate(struct agnx_priv *priv);
+extern void __antenna_calibrate(struct agnx_priv *priv);
+extern void print_offsets(struct agnx_priv *priv);
+extern int agnx_set_channel(struct agnx_priv *priv, unsigned int channel);
+
+
+#endif /* AGNX_H_ */
diff --git a/drivers/staging/agnx/debug.h b/drivers/staging/agnx/debug.h
new file mode 100644
index 000000000000..e3e25dda0ba0
--- /dev/null
+++ b/drivers/staging/agnx/debug.h
@@ -0,0 +1,418 @@
+#ifndef AGNX_DEBUG_H_
+#define AGNX_DEBUG_H_
+
+#include "agnx.h"
+#include "phy.h"
+#include "sta.h"
+#include "xmit.h"
+
+#define AGNX_TRACE printk(KERN_ERR PFX "function:%s line:%d\n", __func__, __LINE__)
+
+#define PRINTK_LE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", le16_to_cpu(var))
+#define PRINTK_LE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", le32_to_cpu(var))
+#define PRINTK_U8(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.2x\n", var)
+#define PRINTK_BE16(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.4x\n", be16_to_cpu(var))
+#define PRINTK_BE32(prefix, var) printk(KERN_DEBUG PFX #prefix ": " #var " 0x%.8x\n", be32_to_cpu(var))
+#define PRINTK_BITS(prefix, field) printk(KERN_DEBUG PFX #prefix ": " #field ": 0x%x\n", (reg & field) >> field##_SHIFT)
+
+static inline void agnx_bug(char *reason)
+{
+ printk(KERN_ERR PFX "%s\n", reason);
+ BUG();
+}
+
+static inline void agnx_print_desc(struct agnx_desc *desc)
+{
+ u32 reg = be32_to_cpu(desc->frag);
+
+ PRINTK_BITS(DESC, PACKET_LEN);
+
+ if (reg & FIRST_FRAG) {
+ PRINTK_BITS(DESC, FIRST_PACKET_MASK);
+ PRINTK_BITS(DESC, FIRST_RESERV2);
+ PRINTK_BITS(DESC, FIRST_TKIP_ERROR);
+ PRINTK_BITS(DESC, FIRST_TKIP_PACKET);
+ PRINTK_BITS(DESC, FIRST_RESERV1);
+ PRINTK_BITS(DESC, FIRST_FRAG_LEN);
+ } else {
+ PRINTK_BITS(DESC, SUB_RESERV2);
+ PRINTK_BITS(DESC, SUB_TKIP_ERROR);
+ PRINTK_BITS(DESC, SUB_TKIP_PACKET);
+ PRINTK_BITS(DESC, SUB_RESERV1);
+ PRINTK_BITS(DESC, SUB_FRAG_LEN);
+ }
+
+ PRINTK_BITS(DESC, FIRST_FRAG);
+ PRINTK_BITS(DESC, LAST_FRAG);
+ PRINTK_BITS(DESC, OWNER);
+}
+
+
+static inline void dump_ieee80211b_phy_hdr(__be32 _11b0, __be32 _11b1)
+{
+
+}
+
+static inline void agnx_print_hdr(struct agnx_hdr *hdr)
+{
+ u32 reg;
+ int i;
+
+ reg = be32_to_cpu(hdr->reg0);
+ PRINTK_BITS(HDR, RTS);
+ PRINTK_BITS(HDR, MULTICAST);
+ PRINTK_BITS(HDR, ACK);
+ PRINTK_BITS(HDR, TM);
+ PRINTK_BITS(HDR, RELAY);
+ PRINTK_BITS(HDR, REVISED_FCS);
+ PRINTK_BITS(HDR, NEXT_BUFFER_ADDR);
+
+ reg = be32_to_cpu(hdr->reg1);
+ PRINTK_BITS(HDR, MAC_HDR_LEN);
+ PRINTK_BITS(HDR, DURATION_OVERIDE);
+ PRINTK_BITS(HDR, PHY_HDR_OVERIDE);
+ PRINTK_BITS(HDR, CRC_FAIL);
+ PRINTK_BITS(HDR, SEQUENCE_NUMBER);
+ PRINTK_BITS(HDR, BUFF_HEAD_ADDR);
+
+ reg = be32_to_cpu(hdr->reg2);
+ PRINTK_BITS(HDR, PDU_COUNT);
+ PRINTK_BITS(HDR, WEP_KEY);
+ PRINTK_BITS(HDR, USES_WEP_KEY);
+ PRINTK_BITS(HDR, KEEP_ALIVE);
+ PRINTK_BITS(HDR, BUFF_TAIL_ADDR);
+
+ reg = be32_to_cpu(hdr->reg3);
+ PRINTK_BITS(HDR, CTS_11G);
+ PRINTK_BITS(HDR, RTS_11G);
+ PRINTK_BITS(HDR, FRAG_SIZE);
+ PRINTK_BITS(HDR, PAYLOAD_LEN);
+ PRINTK_BITS(HDR, FRAG_NUM);
+
+ reg = be32_to_cpu(hdr->reg4);
+ PRINTK_BITS(HDR, RELAY_STAID);
+ PRINTK_BITS(HDR, STATION_ID);
+ PRINTK_BITS(HDR, WORKQUEUE_ID);
+
+ reg = be32_to_cpu(hdr->reg5);
+ /* printf the route flag */
+ PRINTK_BITS(HDR, ROUTE_HOST);
+ PRINTK_BITS(HDR, ROUTE_CARD_CPU);
+ PRINTK_BITS(HDR, ROUTE_ENCRYPTION);
+ PRINTK_BITS(HDR, ROUTE_TX);
+ PRINTK_BITS(HDR, ROUTE_RX1);
+ PRINTK_BITS(HDR, ROUTE_RX2);
+ PRINTK_BITS(HDR, ROUTE_COMPRESSION);
+
+ PRINTK_BE32(HDR, hdr->_11g0);
+ PRINTK_BE32(HDR, hdr->_11g1);
+ PRINTK_BE32(HDR, hdr->_11b0);
+ PRINTK_BE32(HDR, hdr->_11b1);
+
+ dump_ieee80211b_phy_hdr(hdr->_11b0, hdr->_11b1);
+
+ /* Fixme */
+ for (i = 0; i < ARRAY_SIZE(hdr->mac_hdr); i++) {
+ if (i == 0)
+ printk(KERN_DEBUG PFX "IEEE80211 HDR: ");
+ printk("%.2x ", hdr->mac_hdr[i]);
+ if (i + 1 == ARRAY_SIZE(hdr->mac_hdr))
+ printk("\n");
+ }
+
+ PRINTK_BE16(HDR, hdr->rts_duration);
+ PRINTK_BE16(HDR, hdr->last_duration);
+ PRINTK_BE16(HDR, hdr->sec_last_duration);
+ PRINTK_BE16(HDR, hdr->other_duration);
+ PRINTK_BE16(HDR, hdr->tx_other_duration);
+ PRINTK_BE16(HDR, hdr->last_11g_len);
+ PRINTK_BE16(HDR, hdr->other_11g_len);
+ PRINTK_BE16(HDR, hdr->last_11b_len);
+ PRINTK_BE16(HDR, hdr->other_11b_len);
+
+ /* FIXME */
+ reg = be16_to_cpu(hdr->reg6);
+ PRINTK_BITS(HDR, MBF);
+ PRINTK_BITS(HDR, RSVD4);
+
+ PRINTK_BE16(HDR, hdr->rx_frag_stat);
+
+ PRINTK_BE32(HDR, hdr->time_stamp);
+ PRINTK_BE32(HDR, hdr->phy_stats_hi);
+ PRINTK_BE32(HDR, hdr->phy_stats_lo);
+ PRINTK_BE32(HDR, hdr->mic_key0);
+ PRINTK_BE32(HDR, hdr->mic_key1);
+} /* agnx_print_hdr */
+
+
+static inline void agnx_print_rx_hdr(struct agnx_hdr *hdr)
+{
+ agnx_print_hdr(hdr);
+
+ PRINTK_BE16(HDR, hdr->rx.rx_packet_duration);
+ PRINTK_BE16(HDR, hdr->rx.replay_cnt);
+
+ PRINTK_U8(HDR, hdr->rx_channel);
+}
+
+static inline void agnx_print_tx_hdr(struct agnx_hdr *hdr)
+{
+ agnx_print_hdr(hdr);
+
+ PRINTK_U8(HDR, hdr->tx.long_retry_limit);
+ PRINTK_U8(HDR, hdr->tx.short_retry_limit);
+ PRINTK_U8(HDR, hdr->tx.long_retry_cnt);
+ PRINTK_U8(HDR, hdr->tx.short_retry_cnt);
+
+ PRINTK_U8(HDR, hdr->rx_channel);
+}
+
+static inline void
+agnx_print_sta_power(struct agnx_priv *priv, unsigned int sta_idx)
+{
+ struct agnx_sta_power power;
+ u32 reg;
+
+ get_sta_power(priv, &power, sta_idx);
+
+ reg = le32_to_cpu(power.reg);
+ PRINTK_BITS(STA_POWER, SIGNAL);
+ PRINTK_BITS(STA_POWER, RATE);
+ PRINTK_BITS(STA_POWER, TIFS);
+ PRINTK_BITS(STA_POWER, EDCF);
+ PRINTK_BITS(STA_POWER, CHANNEL_BOND);
+ PRINTK_BITS(STA_POWER, PHY_MODE);
+ PRINTK_BITS(STA_POWER, POWER_LEVEL);
+ PRINTK_BITS(STA_POWER, NUM_TRANSMITTERS);
+}
+
+static inline void
+agnx_print_sta_tx_wq(struct agnx_priv *priv, unsigned int sta_idx, unsigned int wq_idx)
+{
+ struct agnx_sta_tx_wq tx_wq;
+ u32 reg;
+
+ get_sta_tx_wq(priv, &tx_wq, sta_idx, wq_idx);
+
+ reg = le32_to_cpu(tx_wq.reg0);
+ PRINTK_BITS(STA_TX_WQ, TAIL_POINTER);
+ PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_LOW);
+
+ reg = le32_to_cpu(tx_wq.reg3);
+ PRINTK_BITS(STA_TX_WQ, HEAD_POINTER_HIGH);
+ PRINTK_BITS(STA_TX_WQ, ACK_POINTER_LOW);
+
+ reg = le32_to_cpu(tx_wq.reg1);
+ PRINTK_BITS(STA_TX_WQ, ACK_POINTER_HIGH);
+ PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_TAIL_PACK_CNT);
+ PRINTK_BITS(STA_TX_WQ, ACK_TIMOUT_TAIL_PACK_CNT);
+
+ reg = le32_to_cpu(tx_wq.reg2);
+ PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_BYTE_CNT);
+ PRINTK_BITS(STA_TX_WQ, HEAD_TIMOUT_WIN_LIM_FRAG_CNT);
+ PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_ACK_TYPE);
+ PRINTK_BITS(STA_TX_WQ, WORK_QUEUE_VALID);
+}
+
+static inline void agnx_print_sta_traffic(struct agnx_sta_traffic *traffic)
+{
+ u32 reg;
+
+ reg = le32_to_cpu(traffic->reg0);
+ PRINTK_BITS(STA_TRAFFIC, ACK_TIMOUT_CNT);
+ PRINTK_BITS(STA_TRAFFIC, TRAFFIC_ACK_TYPE);
+ PRINTK_BITS(STA_TRAFFIC, NEW_PACKET);
+ PRINTK_BITS(STA_TRAFFIC, TRAFFIC_VALID);
+ PRINTK_BITS(STA_TRAFFIC, RX_HDR_DESC_POINTER);
+
+ reg = le32_to_cpu(traffic->reg1);
+ PRINTK_BITS(STA_TRAFFIC, RX_PACKET_TIMESTAMP);
+ PRINTK_BITS(STA_TRAFFIC, TRAFFIC_RESERVED);
+ PRINTK_BITS(STA_TRAFFIC, SV);
+ PRINTK_BITS(STA_TRAFFIC, RX_SEQUENCE_NUM);
+
+ PRINTK_LE32(STA_TRAFFIC, traffic->tx_replay_cnt_low);
+
+ PRINTK_LE16(STA_TRAFFIC, traffic->tx_replay_cnt_high);
+ PRINTK_LE16(STA_TRAFFIC, traffic->rx_replay_cnt_high);
+
+ PRINTK_LE32(STA_TRAFFIC, traffic->rx_replay_cnt_low);
+}
+
+static inline void agnx_print_sta(struct agnx_priv *priv, unsigned int sta_idx)
+{
+ struct agnx_sta station;
+ struct agnx_sta *sta = &station;
+ u32 reg;
+ unsigned int i;
+
+ get_sta(priv, sta, sta_idx);
+
+ for (i = 0; i < 4; i++)
+ PRINTK_LE32(STA, sta->tx_session_keys[i]);
+ for (i = 0; i < 4; i++)
+ PRINTK_LE32(STA, sta->rx_session_keys[i]);
+
+ reg = le32_to_cpu(sta->reg);
+ PRINTK_BITS(STA, ID_1);
+ PRINTK_BITS(STA, ID_0);
+ PRINTK_BITS(STA, ENABLE_CONCATENATION);
+ PRINTK_BITS(STA, ENABLE_DECOMPRESSION);
+ PRINTK_BITS(STA, STA_RESERVED);
+ PRINTK_BITS(STA, EAP);
+ PRINTK_BITS(STA, ED_NULL);
+ PRINTK_BITS(STA, ENCRYPTION_POLICY);
+ PRINTK_BITS(STA, DEFINED_KEY_ID);
+ PRINTK_BITS(STA, FIXED_KEY);
+ PRINTK_BITS(STA, KEY_VALID);
+ PRINTK_BITS(STA, STATION_VALID);
+
+ PRINTK_LE32(STA, sta->tx_aes_blks_unicast);
+ PRINTK_LE32(STA, sta->rx_aes_blks_unicast);
+
+ PRINTK_LE16(STA, sta->aes_format_err_unicast_cnt);
+ PRINTK_LE16(STA, sta->aes_replay_unicast);
+
+ PRINTK_LE16(STA, sta->aes_decrypt_err_unicast);
+ PRINTK_LE16(STA, sta->aes_decrypt_err_default);
+
+ PRINTK_LE16(STA, sta->single_retry_packets);
+ PRINTK_LE16(STA, sta->failed_tx_packets);
+
+ PRINTK_LE16(STA, sta->muti_retry_packets);
+ PRINTK_LE16(STA, sta->ack_timeouts);
+
+ PRINTK_LE16(STA, sta->frag_tx_cnt);
+ PRINTK_LE16(STA, sta->rts_brq_sent);
+
+ PRINTK_LE16(STA, sta->tx_packets);
+ PRINTK_LE16(STA, sta->cts_back_timeout);
+
+ PRINTK_LE32(STA, sta->phy_stats_high);
+ PRINTK_LE32(STA, sta->phy_stats_low);
+
+// for (i = 0; i < 8; i++)
+ agnx_print_sta_traffic(sta->traffic + 0);
+
+ PRINTK_LE16(STA, sta->traffic_class0_frag_success);
+ PRINTK_LE16(STA, sta->traffic_class1_frag_success);
+ PRINTK_LE16(STA, sta->traffic_class2_frag_success);
+ PRINTK_LE16(STA, sta->traffic_class3_frag_success);
+ PRINTK_LE16(STA, sta->traffic_class4_frag_success);
+ PRINTK_LE16(STA, sta->traffic_class5_frag_success);
+ PRINTK_LE16(STA, sta->traffic_class6_frag_success);
+ PRINTK_LE16(STA, sta->traffic_class7_frag_success);
+
+ PRINTK_LE16(STA, sta->num_frag_non_prime_rates);
+ PRINTK_LE16(STA, sta->ack_timeout_non_prime_rates);
+}
+
+
+static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
+{
+ u16 fctl;
+ int hdrlen;
+ DECLARE_MAC_BUF(mac);
+
+ fctl = le16_to_cpu(hdr->frame_control);
+ switch (fctl & IEEE80211_FCTL_FTYPE) {
+ case IEEE80211_FTYPE_DATA:
+ printk(PFX "%s DATA ", tag);
+ break;
+ case IEEE80211_FTYPE_CTL:
+ printk(PFX "%s CTL ", tag);
+ break;
+ case IEEE80211_FTYPE_MGMT:
+ printk(PFX "%s MGMT ", tag);
+ switch(fctl & IEEE80211_FCTL_STYPE) {
+ case IEEE80211_STYPE_ASSOC_REQ:
+ printk("SubType: ASSOC_REQ ");
+ break;
+ case IEEE80211_STYPE_ASSOC_RESP:
+ printk("SubType: ASSOC_RESP ");
+ break;
+ case IEEE80211_STYPE_REASSOC_REQ:
+ printk("SubType: REASSOC_REQ ");
+ break;
+ case IEEE80211_STYPE_REASSOC_RESP:
+ printk("SubType: REASSOC_RESP ");
+ break;
+ case IEEE80211_STYPE_PROBE_REQ:
+ printk("SubType: PROBE_REQ ");
+ break;
+ case IEEE80211_STYPE_PROBE_RESP:
+ printk("SubType: PROBE_RESP ");
+ break;
+ case IEEE80211_STYPE_BEACON:
+ printk("SubType: BEACON ");
+ break;
+ case IEEE80211_STYPE_ATIM:
+ printk("SubType: ATIM ");
+ break;
+ case IEEE80211_STYPE_DISASSOC:
+ printk("SubType: DISASSOC ");
+ break;
+ case IEEE80211_STYPE_AUTH:
+ printk("SubType: AUTH ");
+ break;
+ case IEEE80211_STYPE_DEAUTH:
+ printk("SubType: DEAUTH ");
+ break;
+ case IEEE80211_STYPE_ACTION:
+ printk("SubType: ACTION ");
+ break;
+ default:
+ printk("SubType: Unknow\n");
+ }
+ break;
+ default:
+ printk(PFX "%s Packet type: Unknow\n", tag);
+ }
+
+ hdrlen = ieee80211_hdrlen(fctl);
+
+ if (hdrlen >= 4)
+ printk("FC=0x%04x DUR=0x%04x",
+ fctl, le16_to_cpu(hdr->duration_id));
+ if (hdrlen >= 10)
+ printk(" A1=%s", print_mac(mac, hdr->addr1));
+ if (hdrlen >= 16)
+ printk(" A2=%s", print_mac(mac, hdr->addr2));
+ if (hdrlen >= 24)
+ printk(" A3=%s", print_mac(mac, hdr->addr3));
+ if (hdrlen >= 30)
+ printk(" A4=%s", print_mac(mac, hdr->addr4));
+ printk("\n");
+}
+
+static inline void dump_txm_registers(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ int i;
+ for (i = 0; i <=0x1e8; i += 4) {
+ printk(KERN_DEBUG PFX "TXM: %x---> 0x%.8x\n", i, ioread32(ctl + i));
+ }
+}
+static inline void dump_rxm_registers(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ int i;
+ for (i = 0; i <=0x108; i += 4)
+ printk(KERN_DEBUG PFX "RXM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2000 + i));
+}
+static inline void dump_bm_registers(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ int i;
+ for (i = 0; i <=0x90; i += 4)
+ printk(KERN_DEBUG PFX "BM: %x---> 0x%.8x\n", i, ioread32(ctl + 0x2c00 + i));
+}
+static inline void dump_cir_registers(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ int i;
+ for (i = 0; i <=0xb8; i += 4)
+ printk(KERN_DEBUG PFX "CIR: %x---> 0x%.8x\n", i, ioread32(ctl + 0x3000 + i));
+}
+
+#endif /* AGNX_DEBUG_H_ */
diff --git a/drivers/staging/agnx/pci.c b/drivers/staging/agnx/pci.c
new file mode 100644
index 000000000000..854630cb527e
--- /dev/null
+++ b/drivers/staging/agnx/pci.c
@@ -0,0 +1,644 @@
+/**
+ * Airgo MIMO wireless driver
+ *
+ * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
+
+ * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
+ * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/etherdevice.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "agnx.h"
+#include "debug.h"
+#include "xmit.h"
+#include "phy.h"
+
+MODULE_AUTHOR("Li YanBo <dreamfly281@gmail.com>");
+MODULE_DESCRIPTION("Airgo MIMO PCI wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct pci_device_id agnx_pci_id_tbl[] __devinitdata = {
+ { PCI_DEVICE(0x17cb, 0x0001) }, /* Beklin F5d8010, Netgear WGM511 etc */
+ { PCI_DEVICE(0x17cb, 0x0002) }, /* Netgear Wpnt511 */
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, agnx_pci_id_tbl);
+
+
+static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ if ( *reason & AGNX_STAT_RX ) {
+ /* Mark complete RX */
+ reg = ioread32(ctl + AGNX_CIR_RXCTL);
+ reg |= 0x4;
+ iowrite32(reg, ctl + AGNX_CIR_RXCTL);
+ /* disable Rx interrupt */
+ }
+ if ( *reason & AGNX_STAT_TX ) {
+ reg = ioread32(ctl + AGNX_CIR_TXDCTL);
+ if (reg & 0x4) {
+ iowrite32(reg, ctl + AGNX_CIR_TXDCTL);
+ *reason |= AGNX_STAT_TXD;
+ }
+ reg = ioread32(ctl + AGNX_CIR_TXMCTL);
+ if (reg & 0x4) {
+ iowrite32(reg, ctl + AGNX_CIR_TXMCTL);
+ *reason |= AGNX_STAT_TXM;
+ }
+ }
+ if ( *reason & AGNX_STAT_X ) {
+/* reg = ioread32(ctl + AGNX_INT_STAT); */
+/* iowrite32(reg, ctl + AGNX_INT_STAT); */
+/* /\* FIXME reinit interrupt mask *\/ */
+/* reg = 0xc390bf9 & ~IRQ_TX_BEACON; */
+/* reg &= ~IRQ_TX_DISABLE; */
+/* iowrite32(reg, ctl + AGNX_INT_MASK); */
+/* iowrite32(0x800, ctl + AGNX_CIR_BLKCTL); */
+ }
+} /* agnx_interrupt_ack */
+
+static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
+{
+ struct ieee80211_hw *dev = dev_id;
+ struct agnx_priv *priv = dev->priv;
+ void __iomem *ctl = priv->ctl;
+ irqreturn_t ret = IRQ_NONE;
+ u32 irq_reason;
+
+ spin_lock(&priv->lock);
+
+// printk(KERN_ERR PFX "Get a interrupt %s\n", __func__);
+
+ if (priv->init_status != AGNX_START)
+ goto out;
+
+ /* FiXME Here has no lock, Is this will lead to race? */
+ irq_reason = ioread32(ctl + AGNX_CIR_BLKCTL);
+ if (!(irq_reason & 0x7))
+ goto out;
+
+ ret = IRQ_HANDLED;
+ priv->irq_status = ioread32(ctl + AGNX_INT_STAT);
+
+// printk(PFX "Interrupt reason is 0x%x\n", irq_reason);
+ /* Make sure the txm and txd flags don't conflict with other unknown
+ interrupt flag, maybe is not necessary */
+ irq_reason &= 0xF;
+
+ disable_rx_interrupt(priv);
+ /* TODO Make sure the card finished initialized */
+ agnx_interrupt_ack(priv, &irq_reason);
+
+ if ( irq_reason & AGNX_STAT_RX )
+ handle_rx_irq(priv);
+ if ( irq_reason & AGNX_STAT_TXD )
+ handle_txd_irq(priv);
+ if ( irq_reason & AGNX_STAT_TXM )
+ handle_txm_irq(priv);
+ if ( irq_reason & AGNX_STAT_X )
+ handle_other_irq(priv);
+
+ enable_rx_interrupt(priv);
+out:
+ spin_unlock(&priv->lock);
+ return ret;
+} /* agnx_interrupt_handler */
+
+
+/* FIXME */
+static int agnx_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ AGNX_TRACE;
+ return _agnx_tx(dev->priv, skb);
+} /* agnx_tx */
+
+
+static int agnx_get_mac_address(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ /* Attention! directly read the MAC or other date from EEPROM will
+ lead to cardbus(WGM511) lock up when write to PM PLL register */
+ reg = agnx_read32(ctl, 0x3544);
+ udelay(40);
+ reg = agnx_read32(ctl, 0x354c);
+ udelay(50);
+ /* Get the mac address */
+ reg = agnx_read32(ctl, 0x3544);
+ udelay(40);
+
+ /* HACK */
+ reg = cpu_to_le32(reg);
+ priv->mac_addr[0] = ((u8 *)&reg)[2];
+ priv->mac_addr[1] = ((u8 *)&reg)[3];
+ reg = agnx_read32(ctl, 0x3548);
+ udelay(50);
+ *((u32 *)(priv->mac_addr + 2)) = cpu_to_le32(reg);
+
+ if (!is_valid_ether_addr(priv->mac_addr)) {
+ DECLARE_MAC_BUF(mbuf);
+ printk(KERN_WARNING PFX "read mac %s\n", print_mac(mbuf, priv->mac_addr));
+ printk(KERN_WARNING PFX "Invalid hwaddr! Using random hwaddr\n");
+ random_ether_addr(priv->mac_addr);
+ }
+
+ return 0;
+} /* agnx_get_mac_address */
+
+static int agnx_alloc_rings(struct agnx_priv *priv)
+{
+ unsigned int len;
+ AGNX_TRACE;
+
+ /* Allocate RX/TXM/TXD rings info */
+ priv->rx.size = AGNX_RX_RING_SIZE;
+ priv->txm.size = AGNX_TXM_RING_SIZE;
+ priv->txd.size = AGNX_TXD_RING_SIZE;
+
+ len = priv->rx.size + priv->txm.size + priv->txd.size;
+
+// priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_KERNEL);
+ priv->rx.info = kzalloc(sizeof(struct agnx_info) * len, GFP_ATOMIC);
+ if (!priv->rx.info)
+ return -ENOMEM;
+ priv->txm.info = priv->rx.info + priv->rx.size;
+ priv->txd.info = priv->txm.info + priv->txm.size;
+
+ /* Allocate RX/TXM/TXD descriptors */
+ priv->rx.desc = pci_alloc_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
+ &priv->rx.dma);
+ if (!priv->rx.desc) {
+ kfree(priv->rx.info);
+ return -ENOMEM;
+ }
+
+ priv->txm.desc = priv->rx.desc + priv->rx.size;
+ priv->txm.dma = priv->rx.dma + sizeof(struct agnx_desc) * priv->rx.size;
+ priv->txd.desc = priv->txm.desc + priv->txm.size;
+ priv->txd.dma = priv->txm.dma + sizeof(struct agnx_desc) * priv->txm.size;
+
+ return 0;
+} /* agnx_alloc_rings */
+
+static void rings_free(struct agnx_priv *priv)
+{
+ unsigned int len = priv->rx.size + priv->txm.size + priv->txd.size;
+ unsigned long flags;
+ AGNX_TRACE;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ kfree(priv->rx.info);
+ pci_free_consistent(priv->pdev, sizeof(struct agnx_desc) * len,
+ priv->rx.desc, priv->rx.dma);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+#if 0
+static void agnx_periodic_work_handler(struct work_struct *work)
+{
+ struct agnx_priv *priv = container_of(work, struct agnx_priv,
+ periodic_work.work);
+// unsigned long flags;
+ unsigned long delay;
+
+ /* fixme: using mutex?? */
+// spin_lock_irqsave(&priv->lock, flags);
+
+ /* TODO Recalibrate*/
+// calibrate_oscillator(priv);
+// antenna_calibrate(priv);
+// agnx_send_packet(priv, 997);
+ /* FIXME */
+/* if (debug == 3) */
+/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
+/* else */
+ delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY);
+// delay = round_jiffies(HZ * 15);
+
+ queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay);
+
+// spin_unlock_irqrestore(&priv->lock, flags);
+}
+#endif
+
+static int agnx_start(struct ieee80211_hw *dev)
+{
+ struct agnx_priv *priv = dev->priv;
+ /* unsigned long delay; */
+ int err = 0;
+ AGNX_TRACE;
+
+ err = agnx_alloc_rings(priv);
+ if (err) {
+ printk(KERN_ERR PFX "Can't alloc RX/TXM/TXD rings\n");
+ goto out;
+ }
+ err = request_irq(priv->pdev->irq, &agnx_interrupt_handler,
+ IRQF_SHARED, "agnx_pci", dev);
+ if (err) {
+ printk(KERN_ERR PFX "Failed to register IRQ handler\n");
+ rings_free(priv);
+ goto out;
+ }
+
+// mdelay(500);
+
+ might_sleep();
+ agnx_hw_init(priv);
+
+// mdelay(500);
+ might_sleep();
+
+ priv->init_status = AGNX_START;
+/* INIT_DELAYED_WORK(&priv->periodic_work, agnx_periodic_work_handler); */
+/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
+/* queue_delayed_work(priv->hw->workqueue, &priv->periodic_work, delay); */
+out:
+ return err;
+} /* agnx_start */
+
+static void agnx_stop(struct ieee80211_hw *dev)
+{
+ struct agnx_priv *priv = dev->priv;
+ AGNX_TRACE;
+
+ priv->init_status = AGNX_STOP;
+ /* make sure hardware will not generate irq */
+ agnx_hw_reset(priv);
+ free_irq(priv->pdev->irq, dev);
+ flush_workqueue(priv->hw->workqueue);
+// cancel_delayed_work_sync(&priv->periodic_work);
+ unfill_rings(priv);
+ rings_free(priv);
+}
+
+static int agnx_config(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+{
+ struct agnx_priv *priv = dev->priv;
+ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
+ AGNX_TRACE;
+
+ spin_lock(&priv->lock);
+ /* FIXME need priv lock? */
+ if (channel != priv->channel) {
+ priv->channel = channel;
+ agnx_set_channel(priv, priv->channel);
+ }
+
+ spin_unlock(&priv->lock);
+ return 0;
+}
+
+static int agnx_config_interface(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+{
+ struct agnx_priv *priv = dev->priv;
+ void __iomem *ctl = priv->ctl;
+ AGNX_TRACE;
+
+ spin_lock(&priv->lock);
+
+ if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
+// u32 reghi, reglo;
+ agnx_set_bssid(priv, conf->bssid);
+ memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+ hash_write(priv, conf->bssid, BSSID_STAID);
+ sta_init(priv, BSSID_STAID);
+ /* FIXME needed? */
+ sta_power_init(priv, BSSID_STAID);
+ agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1);
+ }
+ spin_unlock(&priv->lock);
+ return 0;
+} /* agnx_config_interface */
+
+
+static void agnx_configure_filter(struct ieee80211_hw *dev,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ int mc_count, struct dev_mc_list *mclist)
+{
+ unsigned int new_flags = 0;
+
+ *total_flags = new_flags;
+ /* TODO */
+}
+
+static int agnx_add_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct agnx_priv *priv = dev->priv;
+ AGNX_TRACE;
+
+ spin_lock(&priv->lock);
+ /* FIXME */
+ if (priv->mode != NL80211_IFTYPE_MONITOR)
+ return -EOPNOTSUPP;
+
+ switch (conf->type) {
+ case NL80211_IFTYPE_STATION:
+ priv->mode = conf->type;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ spin_unlock(&priv->lock);
+
+ return 0;
+}
+
+static void agnx_remove_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct agnx_priv *priv = dev->priv;
+ AGNX_TRACE;
+
+ /* TODO */
+ priv->mode = NL80211_IFTYPE_MONITOR;
+}
+
+static int agnx_get_stats(struct ieee80211_hw *dev,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct agnx_priv *priv = dev->priv;
+ AGNX_TRACE;
+ spin_lock(&priv->lock);
+ /* TODO !! */
+ memcpy(stats, &priv->stats, sizeof(*stats));
+ spin_unlock(&priv->lock);
+
+ return 0;
+}
+
+static u64 agnx_get_tsft(struct ieee80211_hw *dev)
+{
+ void __iomem *ctl = ((struct agnx_priv *)dev->priv)->ctl;
+ u32 tsftl;
+ u64 tsft;
+ AGNX_TRACE;
+
+ /* FIXME */
+ tsftl = ioread32(ctl + AGNX_TXM_TIMESTAMPLO);
+ tsft = ioread32(ctl + AGNX_TXM_TIMESTAMPHI);
+ tsft <<= 32;
+ tsft |= tsftl;
+
+ return tsft;
+}
+
+static int agnx_get_tx_stats(struct ieee80211_hw *dev,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct agnx_priv *priv = dev->priv;
+ AGNX_TRACE;
+
+ /* FIXME now we just using txd queue, but should using txm queue too */
+ stats[0].len = (priv->txd.idx - priv->txd.idx_sent) / 2;
+ stats[0].limit = priv->txd.size - 2;
+ stats[0].count = priv->txd.idx / 2;
+
+ return 0;
+}
+
+static struct ieee80211_ops agnx_ops = {
+ .tx = agnx_tx,
+ .start = agnx_start,
+ .stop = agnx_stop,
+ .add_interface = agnx_add_interface,
+ .remove_interface = agnx_remove_interface,
+ .config = agnx_config,
+ .config_interface = agnx_config_interface,
+ .configure_filter = agnx_configure_filter,
+ .get_stats = agnx_get_stats,
+ .get_tx_stats = agnx_get_tx_stats,
+ .get_tsf = agnx_get_tsft
+};
+
+static void __devexit agnx_pci_remove(struct pci_dev *pdev)
+{
+ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+ struct agnx_priv *priv = dev->priv;
+ AGNX_TRACE;
+
+ if (!dev)
+ return;
+ ieee80211_unregister_hw(dev);
+ pci_iounmap(pdev, priv->ctl);
+ pci_iounmap(pdev, priv->data);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+ ieee80211_free_hw(dev);
+}
+
+static int __devinit agnx_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct ieee80211_hw *dev;
+ struct agnx_priv *priv;
+ u32 mem_addr0, mem_len0;
+ u32 mem_addr1, mem_len1;
+ int err;
+ DECLARE_MAC_BUF(mac);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR PFX "Can't enable new PCI device\n");
+ return err;
+ }
+
+ /* get pci resource */
+ mem_addr0 = pci_resource_start(pdev, 0);
+ mem_len0 = pci_resource_len(pdev, 0);
+ mem_addr1 = pci_resource_start(pdev, 1);
+ mem_len1 = pci_resource_len(pdev, 1);
+ printk(KERN_DEBUG PFX "Memaddr0 is %x, length is %x\n", mem_addr0, mem_len0);
+ printk(KERN_DEBUG PFX "Memaddr1 is %x, length is %x\n", mem_addr1, mem_len1);
+
+ err = pci_request_regions(pdev, "agnx-pci");
+ if (err) {
+ printk(KERN_ERR PFX "Can't obtain PCI resource\n");
+ return err;
+ }
+
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
+ pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_ERR PFX "No suitable DMA available\n");
+ goto err_free_reg;
+ }
+
+ pci_set_master(pdev);
+ printk(KERN_DEBUG PFX "pdev->irq is %d\n", pdev->irq);
+
+ dev = ieee80211_alloc_hw(sizeof(*priv), &agnx_ops);
+ if (!dev) {
+ printk(KERN_ERR PFX "ieee80211 alloc failed\n");
+ err = -ENOMEM;
+ goto err_free_reg;
+ }
+ /* init priv */
+ priv = dev->priv;
+ memset(priv, 0, sizeof(*priv));
+ priv->mode = NL80211_IFTYPE_MONITOR;
+ priv->pdev = pdev;
+ priv->hw = dev;
+ spin_lock_init(&priv->lock);
+ priv->init_status = AGNX_UNINIT;
+
+ /* Map mem #1 and #2 */
+ priv->ctl = pci_iomap(pdev, 0, mem_len0);
+// printk(KERN_DEBUG PFX"MEM1 mapped address is 0x%p\n", priv->ctl);
+ if (!priv->ctl) {
+ printk(KERN_ERR PFX "Can't map device memory\n");
+ goto err_free_dev;
+ }
+ priv->data = pci_iomap(pdev, 1, mem_len1);
+ printk(KERN_DEBUG PFX "MEM2 mapped address is 0x%p\n", priv->data);
+ if (!priv->data) {
+ printk(KERN_ERR PFX "Can't map device memory\n");
+ goto err_iounmap2;
+ }
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &priv->revid);
+
+ priv->band.channels = (struct ieee80211_channel *)agnx_channels;
+ priv->band.n_channels = ARRAY_SIZE(agnx_channels);
+ priv->band.bitrates = (struct ieee80211_rate *)agnx_rates_80211g;
+ priv->band.n_bitrates = ARRAY_SIZE(agnx_rates_80211g);
+
+ /* Init ieee802.11 dev */
+ SET_IEEE80211_DEV(dev, &pdev->dev);
+ pci_set_drvdata(pdev, dev);
+ dev->extra_tx_headroom = sizeof(struct agnx_hdr);
+
+ /* FIXME It only include FCS in promious mode but not manage mode */
+/* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS; */
+ dev->channel_change_time = 5000;
+ dev->max_signal = 100;
+ /* FIXME */
+ dev->queues = 1;
+
+ agnx_get_mac_address(priv);
+
+ SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr);
+
+/* /\* FIXME *\/ */
+/* for (i = 1; i < NUM_DRIVE_MODES; i++) { */
+/* err = ieee80211_register_hwmode(dev, &priv->modes[i]); */
+/* if (err) { */
+/* printk(KERN_ERR PFX "Can't register hwmode\n"); */
+/* goto err_iounmap; */
+/* } */
+/* } */
+
+ priv->channel = 1;
+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
+
+ err = ieee80211_register_hw(dev);
+ if (err) {
+ printk(KERN_ERR PFX "Can't register hardware\n");
+ goto err_iounmap;
+ }
+
+ agnx_hw_reset(priv);
+
+
+ printk(PFX "%s: hwaddr %s, Rev 0x%02x\n", wiphy_name(dev->wiphy),
+ print_mac(mac, dev->wiphy->perm_addr), priv->revid);
+ return 0;
+
+ err_iounmap:
+ pci_iounmap(pdev, priv->data);
+
+ err_iounmap2:
+ pci_iounmap(pdev, priv->ctl);
+
+ err_free_dev:
+ pci_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(dev);
+
+ err_free_reg:
+ pci_release_regions(pdev);
+
+ pci_disable_device(pdev);
+ return err;
+} /* agnx_pci_probe*/
+
+#ifdef CONFIG_PM
+
+static int agnx_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+ AGNX_TRACE;
+
+ ieee80211_stop_queues(dev);
+ agnx_stop(dev);
+
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+}
+
+static int agnx_pci_resume(struct pci_dev *pdev)
+{
+ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+ AGNX_TRACE;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ agnx_start(dev);
+ ieee80211_wake_queues(dev);
+
+ return 0;
+}
+
+#else
+
+#define agnx_pci_suspend NULL
+#define agnx_pci_resume NULL
+
+#endif /* CONFIG_PM */
+
+
+static struct pci_driver agnx_pci_driver = {
+ .name = "agnx-pci",
+ .id_table = agnx_pci_id_tbl,
+ .probe = agnx_pci_probe,
+ .remove = __devexit_p(agnx_pci_remove),
+ .suspend = agnx_pci_suspend,
+ .resume = agnx_pci_resume,
+};
+
+static int __init agnx_pci_init(void)
+{
+ AGNX_TRACE;
+ return pci_register_driver(&agnx_pci_driver);
+}
+
+static void __exit agnx_pci_exit(void)
+{
+ AGNX_TRACE;
+ pci_unregister_driver(&agnx_pci_driver);
+}
+
+
+module_init(agnx_pci_init);
+module_exit(agnx_pci_exit);
diff --git a/drivers/staging/agnx/phy.c b/drivers/staging/agnx/phy.c
new file mode 100644
index 000000000000..da8f10c08382
--- /dev/null
+++ b/drivers/staging/agnx/phy.c
@@ -0,0 +1,960 @@
+/**
+ * Airgo MIMO wireless driver
+ *
+ * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
+
+ * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
+ * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/etherdevice.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include "agnx.h"
+#include "debug.h"
+#include "phy.h"
+#include "table.h"
+#include "sta.h"
+#include "xmit.h"
+
+u8 read_from_eeprom(struct agnx_priv *priv, u16 address)
+{
+ void __iomem *ctl = priv->ctl;
+ struct agnx_eeprom cmd;
+ u32 reg;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = EEPROM_CMD_READ << AGNX_EEPROM_COMMAND_SHIFT;
+ cmd.address = address;
+ /* Verify that the Status bit is clear */
+ /* Read Command and Address are written to the Serial Interface */
+ iowrite32(*(__le32 *)&cmd, ctl + AGNX_CIR_SERIALITF);
+ /* Wait for the Status bit to clear again */
+ eeprom_delay();
+ /* Read from Data */
+ reg = ioread32(ctl + AGNX_CIR_SERIALITF);
+
+ cmd = *(struct agnx_eeprom *)&reg;
+
+ return cmd.data;
+}
+
+static int card_full_reset(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
+ agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x80);
+ reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
+ return 0;
+}
+
+inline void enable_power_saving(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg &= ~0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+}
+
+inline void disable_power_saving(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+}
+
+
+void disable_receiver(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ AGNX_TRACE;
+
+ /* FIXME Disable the receiver */
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
+ /* Set gain control reset */
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
+ /* Reset gain control reset */
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
+}
+
+
+/* Fixme this shoule be disable RX, above is enable RX */
+void enable_receiver(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ AGNX_TRACE;
+
+ /* Set adaptive gain control discovery mode */
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
+ /* Set gain control reset */
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
+ /* Clear gain control reset */
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
+}
+
+static void mac_address_set(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u8 *mac_addr = priv->mac_addr;
+ u32 reg;
+
+ /* FIXME */
+ reg = (mac_addr[0] << 24) | (mac_addr[1] << 16) | mac_addr[2] << 8 | mac_addr[3];
+ iowrite32(reg, ctl + AGNX_RXM_MACHI);
+ reg = (mac_addr[4] << 8) | mac_addr[5];
+ iowrite32(reg, ctl + AGNX_RXM_MACLO);
+}
+
+static void receiver_bssid_set(struct agnx_priv *priv, u8 *bssid)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ disable_receiver(priv);
+ /* FIXME */
+ reg = bssid[0] << 24 | (bssid[1] << 16) | (bssid[2] << 8) | bssid[3];
+ iowrite32(reg, ctl + AGNX_RXM_BSSIDHI);
+ reg = (bssid[4] << 8) | bssid[5];
+ iowrite32(reg, ctl + AGNX_RXM_BSSIDLO);
+
+ /* Enable the receiver */
+ enable_receiver(priv);
+
+ /* Clear the TSF */
+/* agnx_write32(ctl, AGNX_TXM_TSFLO, 0x0); */
+/* agnx_write32(ctl, AGNX_TXM_TSFHI, 0x0); */
+ /* Clear the TBTT */
+ agnx_write32(ctl, AGNX_TXM_TBTTLO, 0x0);
+ agnx_write32(ctl, AGNX_TXM_TBTTHI, 0x0);
+ disable_receiver(priv);
+} /* receiver_bssid_set */
+
+static void band_management_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ void __iomem *data = priv->data;
+ u32 reg;
+ int i;
+ AGNX_TRACE;
+
+ agnx_write32(ctl, AGNX_BM_TXWADDR, AGNX_PDU_TX_WQ);
+ agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
+ memset_io(data + AGNX_PDUPOOL, 0x0, AGNX_PDUPOOL_SIZE);
+ agnx_write32(ctl, AGNX_BM_BMCTL, 0x200);
+
+ agnx_write32(ctl, AGNX_BM_CIPDUWCNT, 0x40);
+ agnx_write32(ctl, AGNX_BM_SPPDUWCNT, 0x2);
+ agnx_write32(ctl, AGNX_BM_RFPPDUWCNT, 0x0);
+ agnx_write32(ctl, AGNX_BM_RHPPDUWCNT, 0x22);
+
+ /* FIXME Initialize the Free Pool Linked List */
+ /* 1. Write the Address of the Next Node ((0x41800 + node*size)/size)
+ to the first word of each node. */
+ for (i = 0; i < PDU_FREE_CNT; i++) {
+ iowrite32((AGNX_PDU_FREE + (i+1)*PDU_SIZE)/PDU_SIZE,
+ data + AGNX_PDU_FREE + (PDU_SIZE * i));
+ /* The last node should be set to 0x0 */
+ if ((i + 1) == PDU_FREE_CNT)
+ memset_io(data + AGNX_PDU_FREE + (PDU_SIZE * i),
+ 0x0, PDU_SIZE);
+ }
+
+ /* Head is First Pool address (0x41800) / size (0x80) */
+ agnx_write32(ctl, AGNX_BM_FPLHP, AGNX_PDU_FREE/PDU_SIZE);
+ /* Tail is Last Pool Address (0x47f80) / size (0x80) */
+ agnx_write32(ctl, AGNX_BM_FPLTP, 0x47f80/PDU_SIZE);
+ /* Count is Number of Nodes in the Pool (0xd0) */
+ agnx_write32(ctl, AGNX_BM_FPCNT, PDU_FREE_CNT);
+
+ /* Start all workqueue */
+ agnx_write32(ctl, AGNX_BM_CIWQCTL, 0x80000);
+ agnx_write32(ctl, AGNX_BM_CPULWCTL, 0x80000);
+ agnx_write32(ctl, AGNX_BM_CPUHWCTL, 0x80000);
+ agnx_write32(ctl, AGNX_BM_CPUTXWCTL, 0x80000);
+ agnx_write32(ctl, AGNX_BM_CPURXWCTL, 0x80000);
+ agnx_write32(ctl, AGNX_BM_SPRXWCTL, 0x80000);
+ agnx_write32(ctl, AGNX_BM_SPTXWCTL, 0x80000);
+ agnx_write32(ctl, AGNX_BM_RFPWCTL, 0x80000);
+
+ /* Enable the Band Management */
+ reg = agnx_read32(ctl, AGNX_BM_BMCTL);
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_BM_BMCTL, reg);
+} /* band_managment_init */
+
+
+static void system_itf_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x0);
+ agnx_write32(ctl, AGNX_PM_TESTPHY, 0x11e143a);
+
+ if (priv->revid == 0) {
+ reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
+ reg |= 0x11;
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
+ }
+ /* ??? What is that means? it should difference for differice type
+ of cards */
+ agnx_write32(ctl, AGNX_CIR_SERIALITF, 0xfff81006);
+
+ agnx_write32(ctl, AGNX_SYSITF_GPIOIN, 0x1f0000);
+ agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
+ reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
+}
+
+static void encryption_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ AGNX_TRACE;
+
+ agnx_write32(ctl, AGNX_ENCRY_WEPKEY0, 0x0);
+ agnx_write32(ctl, AGNX_ENCRY_WEPKEY1, 0x0);
+ agnx_write32(ctl, AGNX_ENCRY_WEPKEY2, 0x0);
+ agnx_write32(ctl, AGNX_ENCRY_WEPKEY3, 0x0);
+ agnx_write32(ctl, AGNX_ENCRY_CCMRECTL, 0x8);
+}
+
+static void tx_management_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ void __iomem *data = priv->data;
+ u32 reg;
+ AGNX_TRACE;
+
+ /* Fill out the ComputationalEngineLookupTable
+ * starting at memory #2 offset 0x800
+ */
+ tx_engine_lookup_tbl_init(priv);
+ memset_io(data + 0x1000, 0, 0xfe0);
+ /* Enable Transmission Management Functions */
+ agnx_write32(ctl, AGNX_TXM_ETMF, 0x3ff);
+ /* Write 0x3f to Transmission Template */
+ agnx_write32(ctl, AGNX_TXM_TXTEMP, 0x3f);
+
+ if (priv->revid >= 2)
+ agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e140a0b);
+ else
+ agnx_write32(ctl, AGNX_TXM_SIFSPIFS, 0x1e190a0b);
+
+ reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
+ reg &= 0xff00;
+ reg |= 0xb;
+ agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
+ reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
+ reg &= 0xffff00ff;
+ reg |= 0xa00;
+ agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
+ /* Enable TIFS */
+ agnx_write32(ctl, AGNX_TXM_CTL, 0x40000);
+
+ reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
+ reg &= 0xff00ffff;
+ reg |= 0x510000;
+ agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
+ reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
+ reg &= 0xff00ffff;
+ agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
+ reg = agnx_read32(ctl, AGNX_TXM_TIFSEIFS);
+ reg &= 0x00ffffff;
+ reg |= 0x1c000000;
+ agnx_write32(ctl, AGNX_TXM_TIFSEIFS, reg);
+ reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
+ reg &= 0x00ffffff;
+ reg |= 0x01000000;
+ agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
+
+ /* # Set DIF 0-1,2-3,4-5,6-7 to defaults */
+ agnx_write32(ctl, AGNX_TXM_DIF01, 0x321d321d);
+ agnx_write32(ctl, AGNX_TXM_DIF23, 0x321d321d);
+ agnx_write32(ctl, AGNX_TXM_DIF45, 0x321d321d);
+ agnx_write32(ctl, AGNX_TXM_DIF67, 0x321d321d);
+
+ /* Max Ack timeout limit */
+ agnx_write32(ctl, AGNX_TXM_MAXACKTIM, 0x1e19);
+ /* Max RX Data Timeout count, */
+ reg = agnx_read32(ctl, AGNX_TXM_MAXRXTIME);
+ reg &= 0xffff0000;
+ reg |= 0xff;
+ agnx_write32(ctl, AGNX_TXM_MAXRXTIME, reg);
+
+ /* CF poll RX Timeout count */
+ reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
+ reg &= 0xffff;
+ reg |= 0xff0000;
+ agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
+
+ /* Max Timeout Exceeded count, */
+ reg = agnx_read32(ctl, AGNX_TXM_MAXTIMOUT);
+ reg &= 0xff00ffff;
+ reg |= 0x190000;
+ agnx_write32(ctl, AGNX_TXM_MAXTIMOUT, reg);
+
+ /* CF ack timeout limit for 11b */
+ reg = agnx_read32(ctl, AGNX_TXM_CFACKT11B);
+ reg &= 0xff00;
+ reg |= 0x1e;
+ agnx_write32(ctl, AGNX_TXM_CFACKT11B, reg);
+
+ /* Max CF Poll Timeout Count */
+ reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
+ reg &= 0xffff0000;
+ reg |= 0x19;
+ agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
+ /* CF Poll RX Timeout Count */
+ reg = agnx_read32(ctl, AGNX_TXM_CFPOLLRXTIM);
+ reg &= 0xffff0000;
+ reg |= 0x1e;
+ agnx_write32(ctl, AGNX_TXM_CFPOLLRXTIM, reg);
+
+ /* # write default to */
+ /* 1. Schedule Empty Count */
+ agnx_write32(ctl, AGNX_TXM_SCHEMPCNT, 0x5);
+ /* 2. CFP Period Count */
+ agnx_write32(ctl, AGNX_TXM_CFPERCNT, 0x1);
+ /* 3. CFP MDV */
+ agnx_write32(ctl, AGNX_TXM_CFPMDV, 0x10000);
+
+ /* Probe Delay */
+ reg = agnx_read32(ctl, AGNX_TXM_PROBDELAY);
+ reg &= 0xffff0000;
+ reg |= 0x400;
+ agnx_write32(ctl, AGNX_TXM_PROBDELAY, reg);
+
+ /* Max CCA count Slot */
+ reg = agnx_read32(ctl, AGNX_TXM_MAXCCACNTSLOT);
+ reg &= 0xffff00ff;
+ reg |= 0x900;
+ agnx_write32(ctl, AGNX_TXM_MAXCCACNTSLOT, reg);
+
+ /* Slot limit/1 msec Limit */
+ reg = agnx_read32(ctl, AGNX_TXM_SLOTLIMIT);
+ reg &= 0xff00ffff;
+ reg |= 0x140077;
+ agnx_write32(ctl, AGNX_TXM_SLOTLIMIT, reg);
+
+ /* # Set CW #(0-7) to default */
+ agnx_write32(ctl, AGNX_TXM_CW0, 0xff0007);
+ agnx_write32(ctl, AGNX_TXM_CW1, 0xff0007);
+ agnx_write32(ctl, AGNX_TXM_CW2, 0xff0007);
+ agnx_write32(ctl, AGNX_TXM_CW3, 0xff0007);
+ agnx_write32(ctl, AGNX_TXM_CW4, 0xff0007);
+ agnx_write32(ctl, AGNX_TXM_CW5, 0xff0007);
+ agnx_write32(ctl, AGNX_TXM_CW6, 0xff0007);
+ agnx_write32(ctl, AGNX_TXM_CW7, 0xff0007);
+
+ /* # Set Short/Long limit #(0-7) to default */
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM0, 0xa000a);
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM1, 0xa000a);
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM2, 0xa000a);
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM3, 0xa000a);
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM4, 0xa000a);
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM5, 0xa000a);
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM6, 0xa000a);
+ agnx_write32(ctl, AGNX_TXM_SLBEALIM7, 0xa000a);
+
+ reg = agnx_read32(ctl, AGNX_TXM_CTL);
+ reg |= 0x1400;
+ agnx_write32(ctl, AGNX_TXM_CTL, reg);
+ /* Wait for bit 0 in Control Reg to clear */
+ udelay(80);
+ reg = agnx_read32(ctl, AGNX_TXM_CTL);
+ /* Or 0x18000 to Control reg */
+ reg = agnx_read32(ctl, AGNX_TXM_CTL);
+ reg |= 0x18000;
+ agnx_write32(ctl, AGNX_TXM_CTL, reg);
+ /* Wait for bit 0 in Control Reg to clear */
+ udelay(80);
+ reg = agnx_read32(ctl, AGNX_TXM_CTL);
+
+ /* Set Listen Interval Count to default */
+ agnx_write32(ctl, AGNX_TXM_LISINTERCNT, 0x1);
+ /* Set DTIM period count to default */
+ agnx_write32(ctl, AGNX_TXM_DTIMPERICNT, 0x2000);
+} /* tx_management_init */
+
+static void rx_management_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ AGNX_TRACE;
+
+ /* Initialize the Routing Table */
+ routing_table_init(priv);
+
+ if (priv->revid >= 3) {
+ agnx_write32(ctl, 0x2074, 0x1f171710);
+ agnx_write32(ctl, 0x2078, 0x10100d0d);
+ agnx_write32(ctl, 0x207c, 0x11111010);
+ }
+ else
+ agnx_write32(ctl, AGNX_RXM_DELAY11, 0x0);
+ agnx_write32(ctl, AGNX_RXM_REQRATE, 0x8195e00);
+}
+
+
+static void agnx_timer_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ AGNX_TRACE;
+
+/* /\* Write 0x249f00 (tick duration?) to Timer 1 *\/ */
+/* agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x249f00); */
+/* /\* Write 0xe2 to Timer 1 Control *\/ */
+/* agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0xe2); */
+
+ /* Write 0x249f00 (tick duration?) to Timer 1 */
+ agnx_write32(ctl, AGNX_TIMCTL_TIMER1, 0x0);
+ /* Write 0xe2 to Timer 1 Control */
+ agnx_write32(ctl, AGNX_TIMCTL_TIM1CTL, 0x0);
+
+ iowrite32(0xFFFFFFFF, priv->ctl + AGNX_TXM_BEACON_CTL);
+}
+
+static void power_manage_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ agnx_write32(ctl, AGNX_PM_MACMSW, 0x1f);
+ agnx_write32(ctl, AGNX_PM_RFCTL, 0x1f);
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg &= 0xf00f;
+ reg |= 0xa0;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+
+ if (priv->revid >= 3) {
+ reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
+ reg |= 0x18;
+ agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
+ }
+} /* power_manage_init */
+
+
+static void gain_ctlcnt_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ agnx_write32(ctl, AGNX_GCR_TRACNT5, 0x119);
+ agnx_write32(ctl, AGNX_GCR_TRACNT6, 0x118);
+ agnx_write32(ctl, AGNX_GCR_TRACNT7, 0x117);
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg &= ~0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+
+ agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x0);
+
+ /* FIXME Write the initial Station Descriptor for the card */
+ sta_init(priv, LOCAL_STAID);
+ sta_init(priv, BSSID_STAID);
+
+ /* Enable staion 0 and 1 can do TX */
+ /* It seemed if we set other bit to 1 the bit 0 will
+ be auto change to 0 */
+ agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x2 | 0x1);
+// agnx_write32(ctl, AGNX_BM_TXTOPEER, 0x1);
+} /* gain_ctlcnt_init */
+
+
+static void phy_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ void __iomem *data = priv->data;
+ u32 reg;
+ AGNX_TRACE;
+
+ /* Load InitialGainTable */
+ gain_table_init(priv);
+
+ agnx_write32(ctl, AGNX_CIR_ADDRWIN, 0x2000000);
+
+ /* Clear the following offsets in Memory Range #2: */
+ memset_io(data + 0x5040, 0, 0xa * 4);
+ memset_io(data + 0x5080, 0, 0xa * 4);
+ memset_io(data + 0x50c0, 0, 0xa * 4);
+ memset_io(data + 0x5400, 0, 0x80 * 4);
+ memset_io(data + 0x6000, 0, 0x280 * 4);
+ memset_io(data + 0x7000, 0, 0x280 * 4);
+ memset_io(data + 0x8000, 0, 0x280 * 4);
+
+ /* Initialize the Following Registers According to PCI Revision ID */
+ if (priv->revid == 0) {
+ /* fixme the part hasn't been update but below has been update
+ based on WGM511 */
+ agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
+ agnx_write32(ctl, AGNX_ACI_TIMER1, 0x1d);
+ agnx_write32(ctl, AGNX_ACI_TIMER2, 0x3);
+ agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
+ agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
+ agnx_write32(ctl, AGNX_GCR_THD0AL, 0x4b);
+ agnx_write32(ctl, AGNX_GCR_THD0B, 0x4b);
+ agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
+ agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
+ agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
+ agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
+ agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
+ agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
+ agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
+ agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
+ agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
+ agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
+ reg = agnx_read32(ctl, AGNX_GCR_CWDETEC);
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_GCR_CWDETEC, reg);
+ agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
+ agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
+ agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
+ agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
+ agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
+ agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
+ agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
+ agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1);
+ agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0x1);
+ agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
+ agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x78);
+ agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x1c);
+ agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
+ agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x1);
+ agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
+ agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
+ agnx_write32(ctl, AGNX_GCR_THJUMP, 0x14);
+ agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x30);
+ agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x32);
+ agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
+ agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
+ agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
+ agnx_write32(ctl, 0x9400, 0x0);
+ agnx_write32(ctl, 0x940c, 0x6ff);
+ agnx_write32(ctl, 0x9428, 0xa0);
+ agnx_write32(ctl, 0x9434, 0x0);
+ agnx_write32(ctl, 0x9c04, 0x15);
+ agnx_write32(ctl, 0x9c0c, 0x7f);
+ agnx_write32(ctl, 0x9c34, 0x0);
+ agnx_write32(ctl, 0xc000, 0x38d);
+ agnx_write32(ctl, 0x14018, 0x0);
+ agnx_write32(ctl, 0x16000, 0x1);
+ agnx_write32(ctl, 0x11004, 0x0);
+ agnx_write32(ctl, 0xec54, 0xa);
+ agnx_write32(ctl, 0xec1c, 0x5);
+ } else if (priv->revid > 0) {
+ agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
+ agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
+ agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
+ agnx_write32(ctl, AGNX_ACI_AICCHA0OVE, 0x11);
+ agnx_write32(ctl, AGNX_ACI_AICCHA1OVE, 0x0);
+ agnx_write32(ctl, AGNX_GCR_DUNSAT, 0x14);
+ agnx_write32(ctl, AGNX_GCR_DSAT, 0x24);
+ agnx_write32(ctl, AGNX_GCR_DFIRCAL, 0x8);
+ agnx_write32(ctl, AGNX_GCR_DGCTL11A, 0x1a);
+ agnx_write32(ctl, AGNX_GCR_DGCTL11B, 0x3);
+ agnx_write32(ctl, AGNX_GCR_GAININIT, 0xd);
+ agnx_write32(ctl, AGNX_GCR_THNOSIG, 0x1);
+ agnx_write32(ctl, AGNX_GCR_COARSTEP, 0x7);
+ agnx_write32(ctl, AGNX_GCR_SIFST11A, 0x28);
+ agnx_write32(ctl, AGNX_GCR_SIFST11B, 0x28);
+ agnx_write32(ctl, AGNX_GCR_CWDETEC, 0x0);
+ agnx_write32(ctl, AGNX_GCR_0X38, 0x1e);
+// agnx_write32(ctl, AGNX_GCR_BOACT, 0x26);
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
+
+ agnx_write32(ctl, AGNX_GCR_THCAP11A, 0x32);
+ agnx_write32(ctl, AGNX_GCR_THCAP11B, 0x32);
+ agnx_write32(ctl, AGNX_GCR_THCAPRX11A, 0x32);
+ agnx_write32(ctl, AGNX_GCR_THCAPRX11B, 0x32);
+ agnx_write32(ctl, AGNX_GCR_THLEVDRO, 0x10);
+ agnx_write32(ctl, AGNX_GCR_MAXRXTIME11A, 0x1ad);
+ agnx_write32(ctl, AGNX_GCR_MAXRXTIME11B, 0xa10);
+ agnx_write32(ctl, AGNX_GCR_CORRTIME, 0x190);
+ agnx_write32(ctl, AGNX_GCR_CORRDROP, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THCS, 0x0);
+ agnx_write32(ctl, AGNX_GCR_MAXPOWDIFF, 0x4);
+ agnx_write32(ctl, AGNX_GCR_TESTBUS, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THJUMP, 0x1e);
+ agnx_write32(ctl, AGNX_GCR_THPOWER, 0x0);
+ agnx_write32(ctl, AGNX_GCR_THPOWCLIP, 0x2a);
+ agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
+ agnx_write32(ctl, AGNX_GCR_THRX11BPOWMIN, 0x19);
+ agnx_write32(ctl, AGNX_GCR_0X14c, 0x0);
+ agnx_write32(ctl, AGNX_GCR_0X150, 0x0);
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
+ agnx_write32(ctl, AGNX_GCR_WATCHDOG, 0x37);
+ agnx_write32(ctl, 0x9400, 0x0);
+ agnx_write32(ctl, 0x940c, 0x6ff);
+ agnx_write32(ctl, 0x9428, 0xa0);
+ agnx_write32(ctl, 0x9434, 0x0);
+ agnx_write32(ctl, 0x9c04, 0x15);
+ agnx_write32(ctl, 0x9c0c, 0x7f);
+ agnx_write32(ctl, 0x9c34, 0x0);
+ agnx_write32(ctl, 0xc000, 0x38d);
+ agnx_write32(ctl, 0x14014, 0x1000);
+ agnx_write32(ctl, 0x14018, 0x0);
+ agnx_write32(ctl, 0x16000, 0x1);
+ agnx_write32(ctl, 0x11004, 0x0);
+ agnx_write32(ctl, 0xec54, 0xa);
+ agnx_write32(ctl, 0xec1c, 0x50);
+ } else if (priv->revid > 1) {
+ reg = agnx_read32(ctl, 0xec18);
+ reg |= 0x8;
+ agnx_write32(ctl, 0xec18, reg);
+ }
+
+ /* Write the TX Fir Coefficient Table */
+ tx_fir_table_init(priv);
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg &= ~0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+ reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
+
+/* reg = agnx_read32(ctl, 0x1a030); */
+/* reg &= ~0x4; */
+/* agnx_write32(ctl, 0x1a030, reg); */
+
+ agnx_write32(ctl, AGNX_GCR_TRACNT4, 0x113);
+} /* phy_init */
+
+static void chip_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ band_management_init(priv);
+
+ rf_chips_init(priv);
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+
+ /* Initialize the PHY */
+ phy_init(priv);
+
+ encryption_init(priv);
+
+ tx_management_init(priv);
+
+ rx_management_init(priv);
+
+ power_manage_init(priv);
+
+ /* Initialize the Timers */
+ agnx_timer_init(priv);
+
+ /* Write 0xc390bf9 to Interrupt Mask (Disable TX) */
+ reg = 0xc390bf9 & ~IRQ_TX_BEACON;
+ reg &= ~IRQ_TX_DISABLE;
+ agnx_write32(ctl, AGNX_INT_MASK, reg);
+
+ reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
+ reg |= 0x800;
+ agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
+
+ /* set it when need get multicast enable? */
+ agnx_write32(ctl, AGNX_BM_MTSM, 0xff);
+} /* chip_init */
+
+
+static inline void set_promis_and_managed(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10 | 0x2);
+}
+static inline void set_learn_mode(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x8);
+}
+static inline void set_scan_mode(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x20);
+}
+static inline void set_promiscuous_mode(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ /* agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x210);*/
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x10);
+}
+static inline void set_managed_mode(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x2);
+}
+static inline void set_adhoc_mode(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, 0x0);
+}
+
+#if 0
+static void unknow_register_write(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x0, 0x3e);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4, 0xb2);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x8, 0x140);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0xc, 0x1C0);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x10, 0x1FF);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x14, 0x1DD);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x18, 0x15F);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x1c, 0xA1);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x20, 0x3E7);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x24, 0x36B);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x28, 0x348);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x2c, 0x37D);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x30, 0x3DE);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x34, 0x36);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x38, 0x64);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x3c, 0x57);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x40, 0x23);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x44, 0x3ED);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x48, 0x3C9);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x4c, 0x3CA);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x50, 0x3E7);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x54, 0x8);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x58, 0x1F);
+ agnx_write32(ctl, AGNX_UNKNOWN_BASE + 0x5c, 0x1a);
+}
+#endif
+
+static void card_interface_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u8 bssid[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u32 reg;
+ unsigned int i;
+ AGNX_TRACE;
+
+ might_sleep();
+ /* Clear RX Control and Enable RX queues */
+ agnx_write32(ctl, AGNX_CIR_RXCTL, 0x8);
+
+ might_sleep();
+ /* Do a full reset of the card */
+ card_full_reset(priv);
+ might_sleep();
+
+ /* Check and set Card Endianness */
+ reg = ioread32(priv->ctl + AGNX_CIR_ENDIAN);
+ /* TODO If not 0xB3B2B1B0 set to 0xB3B2B1B0 */
+ printk(KERN_INFO PFX "CIR_ENDIAN is %x\n", reg);
+
+
+ /* Config the eeprom */
+ agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x7000086);
+ udelay(10);
+ reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
+
+
+ agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
+ reg = agnx_read32(ctl, 0xec50);
+ reg |= 0xf;
+ agnx_write32(ctl, 0xec50, reg);
+ agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
+
+
+ reg = agnx_read32(ctl, AGNX_SYSITF_GPIOIN);
+ udelay(10);
+ reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
+
+ /* Dump the eeprom */
+ do {
+ char eeprom[0x100000/0x100];
+
+ for (i = 0; i < 0x100000; i += 0x100) {
+ agnx_write32(ctl, AGNX_CIR_SERIALITF, 0x3000000 + i);
+ udelay(13);
+ reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
+ udelay(70);
+ reg = agnx_read32(ctl, AGNX_CIR_SERIALITF);
+ eeprom[i/0x100] = reg & 0xFF;
+ udelay(10);
+ }
+ print_hex_dump_bytes(PFX "EEPROM: ", DUMP_PREFIX_NONE, eeprom,
+ ARRAY_SIZE(eeprom));
+ } while(0);
+
+ spi_rc_write(ctl, RF_CHIP0, 0x26);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+
+ /* Initialize the system interface */
+ system_itf_init(priv);
+
+ might_sleep();
+ /* Chip Initialization (Polaris) */
+ chip_init(priv);
+ might_sleep();
+
+ /* Calibrate the antennae */
+ antenna_calibrate(priv);
+
+ reg = agnx_read32(ctl, 0xec50);
+ reg &= ~0x40;
+ agnx_write32(ctl, 0xec50, reg);
+ agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
+ agnx_write32(ctl, AGNX_PM_PLLCTL, 0x1);
+
+ reg = agnx_read32(ctl, AGNX_BM_BMCTL);
+ reg |= 0x8000;
+ agnx_write32(ctl, AGNX_BM_BMCTL, reg);
+ enable_receiver(priv);
+ reg = agnx_read32(ctl, AGNX_SYSITF_SYSMODE);
+ reg |= 0x200;
+ agnx_write32(ctl, AGNX_SYSITF_SYSMODE, reg);
+ enable_receiver(priv);
+
+ might_sleep();
+ /* Initialize Gain Control Counts */
+ gain_ctlcnt_init(priv);
+
+ /* Write Initial Station Power Template for this station(#0) */
+ sta_power_init(priv, LOCAL_STAID);
+
+ might_sleep();
+ /* Initialize the rx,td,tm rings, for each node in the ring */
+ fill_rings(priv);
+
+ might_sleep();
+
+
+ agnx_write32(ctl, AGNX_PM_SOFTRST, 0x80000033);
+ agnx_write32(ctl, 0xec50, 0xc);
+ agnx_write32(ctl, AGNX_PM_SOFTRST, 0x0);
+
+ /* FIXME Initialize the transmit control register */
+ agnx_write32(ctl, AGNX_TXM_CTL, 0x194c1);
+
+ enable_receiver(priv);
+
+ might_sleep();
+ /* FIXME Set the Receive Control Mac Address to card address */
+ mac_address_set(priv);
+ enable_receiver(priv);
+ might_sleep();
+
+ /* Set the recieve request rate */
+ /* FIXME Enable the request */
+ /* Check packet length */
+ /* Set maximum packet length */
+/* agnx_write32(ctl, AGNX_RXM_REQRATE, 0x88195e00); */
+/* enable_receiver(priv); */
+
+ /* Set the Receiver BSSID */
+ receiver_bssid_set(priv, bssid);
+
+ /* FIXME Set to managed mode */
+ set_managed_mode(priv);
+// set_promiscuous_mode(priv);
+/* set_scan_mode(priv); */
+/* set_learn_mode(priv); */
+// set_promis_and_managed(priv);
+// set_adhoc_mode(priv);
+
+ /* Set the recieve request rate */
+ /* Check packet length */
+ agnx_write32(ctl, AGNX_RXM_REQRATE, 0x08000000);
+ reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
+ /* Set maximum packet length */
+ reg |= 0x00195e00;
+ agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
+
+ /* Configure the RX and TX interrupt */
+ reg = ENABLE_RX_INTERRUPT | RX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
+ agnx_write32(ctl, AGNX_CIR_RXCFG, reg);
+ /* FIXME */
+ reg = ENABLE_TX_INTERRUPT | TX_CACHE_LINE | FRAG_LEN_2048 | FRAG_BE;
+ agnx_write32(ctl, AGNX_CIR_TXCFG, reg);
+
+ /* Enable RX TX Interrupts */
+ agnx_write32(ctl, AGNX_CIR_RXCTL, 0x80);
+ agnx_write32(ctl, AGNX_CIR_TXMCTL, 0x80);
+ agnx_write32(ctl, AGNX_CIR_TXDCTL, 0x80);
+
+ /* FIXME Set the master control interrupt in block control */
+ agnx_write32(ctl, AGNX_CIR_BLKCTL, 0x800);
+
+ /* Enable RX and TX queues */
+ reg = agnx_read32(ctl, AGNX_CIR_RXCTL);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_CIR_RXCTL, reg);
+ reg = agnx_read32(ctl, AGNX_CIR_TXMCTL);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_CIR_TXMCTL, reg);
+ reg = agnx_read32(ctl, AGNX_CIR_TXDCTL);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_CIR_TXDCTL, reg);
+
+ agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
+ /* FIXME */
+ /* unknow_register_write(priv); */
+ /* Update local card hash entry */
+ hash_write(priv, priv->mac_addr, LOCAL_STAID);
+
+ might_sleep();
+
+ /* FIXME */
+ agnx_set_channel(priv, 1);
+ might_sleep();
+} /* agnx_card_interface_init */
+
+
+void agnx_hw_init(struct agnx_priv *priv)
+{
+ AGNX_TRACE;
+ might_sleep();
+ card_interface_init(priv);
+}
+
+int agnx_hw_reset(struct agnx_priv *priv)
+{
+ return card_full_reset(priv);
+}
+
+int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len)
+{
+ AGNX_TRACE;
+ return 0;
+}
+
+void agnx_set_bssid(struct agnx_priv *priv, u8 *bssid)
+{
+ receiver_bssid_set(priv, bssid);
+}
diff --git a/drivers/staging/agnx/phy.h b/drivers/staging/agnx/phy.h
new file mode 100644
index 000000000000..55e1e222179e
--- /dev/null
+++ b/drivers/staging/agnx/phy.h
@@ -0,0 +1,409 @@
+#ifndef AGNX_PHY_H_
+#define AGNX_PHY_H_
+
+#include "agnx.h"
+
+/* Transmission Managment Registers */
+#define AGNX_TXM_BASE 0x0000
+#define AGNX_TXM_CTL 0x0000 /* control register */
+#define AGNX_TXM_ETMF 0x0004 /* enable transmission management functions */
+#define AGNX_TXM_TXTEMP 0x0008 /* transmission template */
+#define AGNX_TXM_RETRYSTAID 0x000c /* Retry Station ID */
+#define AGNX_TXM_TIMESTAMPLO 0x0010 /* Timestamp Lo */
+#define AGNX_TXM_TIMESTAMPHI 0x0014 /* Timestamp Hi */
+#define AGNX_TXM_TXDELAY 0x0018 /* tx delay */
+#define AGNX_TXM_TBTTLO 0x0020 /* tbtt Lo */
+#define AGNX_TXM_TBTTHI 0x0024 /* tbtt Hi */
+#define AGNX_TXM_BEAINTER 0x0028 /* Beacon Interval */
+#define AGNX_TXM_NAV 0x0030 /* NAV */
+#define AGNX_TXM_CFPMDV 0x0034 /* CFP MDV */
+#define AGNX_TXM_CFPERCNT 0x0038 /* CFP period count */
+#define AGNX_TXM_PROBDELAY 0x003c /* probe delay */
+#define AGNX_TXM_LISINTERCNT 0x0040 /* listen interval count */
+#define AGNX_TXM_DTIMPERICNT 0x004c /* DTIM period count */
+
+#define AGNX_TXM_BEACON_CTL 0x005c /* beacon control */
+
+#define AGNX_TXM_SCHEMPCNT 0x007c /* schedule empty count */
+#define AGNX_TXM_MAXTIMOUT 0x0084 /* max timeout exceed count */
+#define AGNX_TXM_MAXCFPTIM 0x0088 /* max CF poll timeout count */
+#define AGNX_TXM_MAXRXTIME 0x008c /* max RX timeout count */
+#define AGNX_TXM_MAXACKTIM 0x0090 /* max ACK timeout count */
+#define AGNX_TXM_DIF01 0x00a0 /* DIF 0-1 */
+#define AGNX_TXM_DIF23 0x00a4 /* DIF 2-3 */
+#define AGNX_TXM_DIF45 0x00a8 /* DIF 4-5 */
+#define AGNX_TXM_DIF67 0x00ac /* DIF 6-7 */
+#define AGNX_TXM_SIFSPIFS 0x00b0 /* SIFS/PIFS */
+#define AGNX_TXM_TIFSEIFS 0x00b4 /* TIFS/EIFS */
+#define AGNX_TXM_MAXCCACNTSLOT 0x00b8 /* max CCA count slot */
+#define AGNX_TXM_SLOTLIMIT 0x00bc /* slot limit/1 msec limit */
+#define AGNX_TXM_CFPOLLRXTIM 0x00f0 /* CF poll RX timeout count */
+#define AGNX_TXM_CFACKT11B 0x00f4 /* CF ack timeout limit for 11b */
+#define AGNX_TXM_CW0 0x0100 /* CW 0 */
+#define AGNX_TXM_SLBEALIM0 0x0108 /* short/long beacon limit 0 */
+#define AGNX_TXM_CW1 0x0120 /* CW 1 */
+#define AGNX_TXM_SLBEALIM1 0x0128 /* short/long beacon limit 1 */
+#define AGNX_TXM_CW2 0x0140 /* CW 2 */
+#define AGNX_TXM_SLBEALIM2 0x0148 /* short/long beacon limit 2 */
+#define AGNX_TXM_CW3 0x0160 /* CW 3 */
+#define AGNX_TXM_SLBEALIM3 0x0168 /* short/long beacon limit 3 */
+#define AGNX_TXM_CW4 0x0180 /* CW 4 */
+#define AGNX_TXM_SLBEALIM4 0x0188 /* short/long beacon limit 4 */
+#define AGNX_TXM_CW5 0x01a0 /* CW 5 */
+#define AGNX_TXM_SLBEALIM5 0x01a8 /* short/long beacon limit 5 */
+#define AGNX_TXM_CW6 0x01c0 /* CW 6 */
+#define AGNX_TXM_SLBEALIM6 0x01c8 /* short/long beacon limit 6 */
+#define AGNX_TXM_CW7 0x01e0 /* CW 7 */
+#define AGNX_TXM_SLBEALIM7 0x01e8 /* short/long beacon limit 7 */
+#define AGNX_TXM_BEACONTEMP 0x1000 /* beacon template */
+#define AGNX_TXM_STAPOWTEMP 0x1a00 /* Station Power Template */
+
+/* Receive Management Control Registers */
+#define AGNX_RXM_BASE 0x2000
+#define AGNX_RXM_REQRATE 0x2000 /* requested rate */
+#define AGNX_RXM_MACHI 0x2004 /* first 4 bytes of mac address */
+#define AGNX_RXM_MACLO 0x2008 /* last 2 bytes of mac address */
+#define AGNX_RXM_BSSIDHI 0x200c /* bssid hi */
+#define AGNX_RXM_BSSIDLO 0x2010 /* bssid lo */
+#define AGNX_RXM_HASH_CMD_FLAG 0x2014 /* Flags for the RX Hash Command Default:0 */
+#define AGNX_RXM_HASH_CMD_HIGH 0x2018 /* The High half of the Hash Command */
+#define AGNX_RXM_HASH_CMD_LOW 0x201c /* The Low half of the Hash Command */
+#define AGNX_RXM_ROUTAB 0x2020 /* routing table */
+#define ROUTAB_SUBTYPE_SHIFT 24
+#define ROUTAB_TYPE_SHIFT 28
+#define ROUTAB_STATUS_SHIFT 30
+#define ROUTAB_RW_SHIFT 31
+#define ROUTAB_ROUTE_DROP 0xf00000 /* Drop */
+#define ROUTAB_ROUTE_CPU 0x400000 /* CPU */
+#define ROUTAB_ROUTE_ENCRY 0x500800 /* Encryption */
+#define ROUTAB_ROUTE_RFP 0x800000 /* RFP */
+
+#define ROUTAB_TYPE_MANAG 0x0 /* Management */
+#define ROUTAB_TYPE_CTL 0x1 /* Control */
+#define ROUTAB_TYPE_DATA 0x2 /* Data */
+
+#define ROUTAB_SUBTYPE_DATA 0x0
+#define ROUTAB_SUBTYPE_DATAACK 0x1
+#define ROUTAB_SUBTYPE_DATAPOLL 0x2
+#define ROUTAB_SUBTYPE_DATAPOLLACK 0x3
+#define ROUTAB_SUBTYPE_NULL 0x4 /* NULL */
+#define ROUTAB_SUBTYPE_NULLACK 0x5
+#define ROUTAB_SUBTYPE_NULLPOLL 0x6
+#define ROUTAB_SUBTYPE_NULLPOLLACK 0x7
+#define ROUTAB_SUBTYPE_QOSDATA 0x8 /* QOS DATA */
+#define ROUTAB_SUBTYPE_QOSDATAACK 0x9
+#define ROUTAB_SUBTYPE_QOSDATAPOLL 0xa
+#define ROUTAB_SUBTYPE_QOSDATAACKPOLL 0xb
+#define ROUTAB_SUBTYPE_QOSNULL 0xc
+#define ROUTAB_SUBTYPE_QOSNULLACK 0xd
+#define ROUTAB_SUBTYPE_QOSNULLPOLL 0xe
+#define ROUTAB_SUBTYPE_QOSNULLPOLLACK 0xf
+#define AGNX_RXM_DELAY11 0x2024 /* delay 11(AB) */
+#define AGNX_RXM_SOF_CNT 0x2028 /* SOF Count */
+#define AGNX_RXM_FRAG_CNT 0x202c /* Fragment Count*/
+#define AGNX_RXM_FCS_CNT 0x2030 /* FCS Count */
+#define AGNX_RXM_BSSID_MISS_CNT 0x2034 /* BSSID Miss Count */
+#define AGNX_RXM_PDU_ERR_CNT 0x2038 /* PDU Error Count */
+#define AGNX_RXM_DEST_MISS_CNT 0x203C /* Destination Miss Count */
+#define AGNX_RXM_DROP_CNT 0x2040 /* Drop Count */
+#define AGNX_RXM_ABORT_CNT 0x2044 /* Abort Count */
+#define AGNX_RXM_RELAY_CNT 0x2048 /* Relay Count */
+#define AGNX_RXM_HASH_MISS_CNT 0x204c /* Hash Miss Count */
+#define AGNX_RXM_SA_HI 0x2050 /* Address of received packet Hi */
+#define AGNX_RXM_SA_LO 0x2054 /* Address of received packet Lo */
+#define AGNX_RXM_HASH_DUMP_LST 0x2100 /* Contains Hash Data */
+#define AGNX_RXM_HASH_DUMP_MST 0x2104 /* Contains Hash Data */
+#define AGNX_RXM_HASH_DUMP_DATA 0x2108 /* The Station ID to dump */
+
+
+/* Encryption Managment */
+#define AGNX_ENCRY_BASE 0x2400
+#define AGNX_ENCRY_WEPKEY0 0x2440 /* wep key #0 */
+#define AGNX_ENCRY_WEPKEY1 0x2444 /* wep key #1 */
+#define AGNX_ENCRY_WEPKEY2 0x2448 /* wep key #2 */
+#define AGNX_ENCRY_WEPKEY3 0x244c /* wep key #3 */
+#define AGNX_ENCRY_CCMRECTL 0x2460 /* ccm replay control */
+
+
+/* Band Management Registers */
+#define AGNX_BM_BASE 0x2c00
+#define AGNX_BM_BMCTL 0x2c00 /* band management control */
+#define AGNX_BM_TXWADDR 0x2c18 /* tx workqueue address start */
+#define AGNX_BM_TXTOPEER 0x2c24 /* transmit to peers */
+#define AGNX_BM_FPLHP 0x2c2c /* free pool list head pointer */
+#define AGNX_BM_FPLTP 0x2c30 /* free pool list tail pointer */
+#define AGNX_BM_FPCNT 0x2c34 /* free pool count */
+#define AGNX_BM_CIPDUWCNT 0x2c38 /* card interface pdu workqueue count */
+#define AGNX_BM_SPPDUWCNT 0x2c3c /* sp pdu workqueue count */
+#define AGNX_BM_RFPPDUWCNT 0x2c40 /* rfp pdu workqueue count */
+#define AGNX_BM_RHPPDUWCNT 0x2c44 /* rhp pdu workqueue count */
+#define AGNX_BM_CIWQCTL 0x2c48 /* Card Interface WorkQueue Control */
+#define AGNX_BM_CPUTXWCTL 0x2c50 /* cpu tx workqueue control */
+#define AGNX_BM_CPURXWCTL 0x2c58 /* cpu rx workqueue control */
+#define AGNX_BM_CPULWCTL 0x2c60 /* cpu low workqueue control */
+#define AGNX_BM_CPUHWCTL 0x2c68 /* cpu high workqueue control */
+#define AGNX_BM_SPTXWCTL 0x2c70 /* sp tx workqueue control */
+#define AGNX_BM_SPRXWCTL 0x2c78 /* sp rx workqueue control */
+#define AGNX_BM_RFPWCTL 0x2c80 /* RFP workqueue control */
+#define AGNX_BM_MTSM 0x2c90 /* Multicast Transmit Station Mask */
+
+/* Card Interface Registers (32bits) */
+#define AGNX_CIR_BASE 0x3000
+#define AGNX_CIR_BLKCTL 0x3000 /* block control*/
+#define AGNX_STAT_TX 0x1
+#define AGNX_STAT_RX 0x2
+#define AGNX_STAT_X 0x4
+/* Below two interrupt flags will be set by our but not CPU or the card */
+#define AGNX_STAT_TXD 0x10
+#define AGNX_STAT_TXM 0x20
+
+#define AGNX_CIR_ADDRWIN 0x3004 /* Addressable Windows*/
+#define AGNX_CIR_ENDIAN 0x3008 /* card endianness */
+#define AGNX_CIR_SERIALITF 0x3020 /* serial interface */
+#define AGNX_CIR_RXCFG 0x3040 /* receive config */
+#define ENABLE_RX_INTERRUPT 0x20
+#define RX_CACHE_LINE 0x8
+/* the RX fragment length */
+#define FRAG_LEN_256 0x0 /* 256B */
+#define FRAG_LEN_512 0x1
+#define FRAG_LEN_1024 0x2
+#define FRAG_LEN_2048 0x3
+#define FRAG_BE 0x10
+#define AGNX_CIR_RXCTL 0x3050 /* receive control */
+/* memory address, chipside */
+#define AGNX_CIR_RXCMSTART 0x3054 /* receive client memory start */
+#define AGNX_CIR_RXCMEND 0x3058 /* receive client memory end */
+/* memory address, pci */
+#define AGNX_CIR_RXHOSTADDR 0x3060 /* receive hostside address */
+/* memory address, chipside */
+#define AGNX_CIR_RXCLIADDR 0x3064 /* receive clientside address */
+#define AGNX_CIR_RXDMACTL 0x3068 /* receive dma control */
+#define AGNX_CIR_TXCFG 0x3080 /* transmit config */
+#define AGNX_CIR_TXMCTL 0x3090 /* Transmit Management Control */
+#define ENABLE_TX_INTERRUPT 0x20
+#define TX_CACHE_LINE 0x8
+#define AGNX_CIR_TXMSTART 0x3094 /* Transmit Management Start */
+#define AGNX_CIR_TXMEND 0x3098 /* Transmit Management End */
+#define AGNX_CIR_TXDCTL 0x30a0 /* transmit data control */
+/* memeory address, chipset */
+#define AGNX_CIR_TXDSTART 0x30a4 /* transmit data start */
+#define AGNX_CIR_TXDEND 0x30a8 /* transmit data end */
+#define AGNX_CIR_TXMHADDR 0x30b0 /* Transmit Management Hostside Address */
+#define AGNX_CIR_TXMCADDR 0x30b4 /* Transmit Management Clientside Address */
+#define AGNX_CIR_TXDMACTL 0x30b8 /* transmit dma control */
+
+
+/* Power Managment Unit */
+#define AGNX_PM_BASE 0x3c00
+#define AGNX_PM_PMCTL 0x3c00 /* PM Control*/
+#define AGNX_PM_MACMSW 0x3c08 /* MAC Manual Slow Work Enable */
+#define AGNX_PM_RFCTL 0x3c0c /* RF Control */
+#define AGNX_PM_PHYMW 0x3c14 /* Phy Mannal Work */
+#define AGNX_PM_SOFTRST 0x3c18 /* PMU Soft Reset */
+#define AGNX_PM_PLLCTL 0x3c1c /* PMU PLL control*/
+#define AGNX_PM_TESTPHY 0x3c24 /* PMU Test Phy */
+
+
+/* Interrupt Control interface */
+#define AGNX_INT_BASE 0x4000
+#define AGNX_INT_STAT 0x4000 /* interrupt status */
+#define AGNX_INT_MASK 0x400c /* interrupt mask */
+/* FIXME */
+#define IRQ_TX_BEACON 0x1 /* TX Beacon */
+#define IRQ_TX_RETRY 0x8 /* TX Retry Interrupt */
+#define IRQ_TX_ACTIVITY 0x10 /* TX Activity */
+#define IRQ_RX_ACTIVITY 0x20 /* RX Activity */
+/* FIXME I guess that instead RX a none exist staion's packet or
+ the station hasn't been init */
+#define IRQ_RX_X 0x40
+#define IRQ_RX_Y 0x80 /* RX ? */
+#define IRQ_RX_HASHHIT 0x100 /* RX Hash Hit */
+#define IRQ_RX_FRAME 0x200 /* RX Frame */
+#define IRQ_ERR_INT 0x400 /* Error Interrupt */
+#define IRQ_TX_QUE_FULL 0x800 /* TX Workqueue Full */
+#define IRQ_BANDMAN_ERR 0x10000 /* Bandwidth Management Error */
+#define IRQ_TX_DISABLE 0x20000 /* TX Disable */
+#define IRQ_RX_IVASESKEY 0x80000 /* RX Invalid Session Key */
+#define IRQ_RX_KEYIDMIS 0x100000 /* RX key ID Mismatch */
+#define IRQ_REP_THHIT 0x200000 /* Replay Threshold Hit */
+#define IRQ_TIMER1 0x4000000 /* Timer1 */
+#define IRQ_TIMER_CNT 0x10000000 /* Timer Count */
+#define IRQ_PHY_FASTINT 0x20000000 /* Phy Fast Interrupt */
+#define IRQ_PHY_SLOWINT 0x40000000 /* Phy Slow Interrupt */
+#define IRQ_OTHER 0x80000000 /* Unknow interrupt */
+#define AGNX_IRQ_ALL 0xffffffff
+
+/* System Interface */
+#define AGNX_SYSITF_BASE 0x4400
+#define AGNX_SYSITF_SYSMODE 0x4400 /* system mode */
+#define AGNX_SYSITF_GPIOIN 0x4410 /* GPIO In */
+/* PIN lines for leds? */
+#define AGNX_SYSITF_GPIOUT 0x4414 /* GPIO Out */
+
+/* Timer Control */
+#define AGNX_TIMCTL_TIMER1 0x4800 /* Timer 1 */
+#define AGNX_TIMCTL_TIM1CTL 0x4808 /* Timer 1 Control */
+
+
+/* Antenna Calibration Interface */
+#define AGNX_ACI_BASE 0x5000
+#define AGNX_ACI_MODE 0x5000 /* Mode */
+#define AGNX_ACI_MEASURE 0x5004 /* Measure */
+#define AGNX_ACI_SELCHAIN 0x5008 /* Select Chain */
+#define AGNX_ACI_LEN 0x500c /* Length */
+#define AGNX_ACI_TIMER1 0x5018 /* Timer 1 */
+#define AGNX_ACI_TIMER2 0x501c /* Timer 2 */
+#define AGNX_ACI_OFFSET 0x5020 /* Offset */
+#define AGNX_ACI_STATUS 0x5030 /* Status */
+#define CALI_IDLE 0x0
+#define CALI_DONE 0x1
+#define CALI_BUSY 0x2
+#define CALI_ERR 0x3
+#define AGNX_ACI_AICCHA0OVE 0x5034 /* AIC Channel 0 Override */
+#define AGNX_ACI_AICCHA1OVE 0x5038 /* AIC Channel 1 Override */
+
+/* Gain Control Registers */
+#define AGNX_GCR_BASE 0x9000
+/* threshold of primary antenna */
+#define AGNX_GCR_THD0A 0x9000 /* threshold? D0 A */
+/* low threshold of primary antenna */
+#define AGNX_GCR_THD0AL 0x9004 /* threshold? D0 A low */
+/* threshold of secondary antenna */
+#define AGNX_GCR_THD0B 0x9008 /* threshold? D0_B */
+#define AGNX_GCR_DUNSAT 0x900c /* d unsaturated */
+#define AGNX_GCR_DSAT 0x9010 /* d saturated */
+#define AGNX_GCR_DFIRCAL 0x9014 /* D Fir/Cal */
+#define AGNX_GCR_DGCTL11A 0x9018 /* d gain control 11a */
+#define AGNX_GCR_DGCTL11B 0x901c /* d gain control 11b */
+/* strength of gain */
+#define AGNX_GCR_GAININIT 0x9020 /* gain initialization */
+#define AGNX_GCR_THNOSIG 0x9024 /* threhold no signal */
+#define AGNX_GCR_COARSTEP 0x9028 /* coarse stepping */
+#define AGNX_GCR_SIFST11A 0x902c /* sifx time 11a */
+#define AGNX_GCR_SIFST11B 0x9030 /* sifx time 11b */
+#define AGNX_GCR_CWDETEC 0x9034 /* cw detection */
+#define AGNX_GCR_0X38 0x9038 /* ???? */
+#define AGNX_GCR_BOACT 0x903c /* BO Active */
+#define AGNX_GCR_BOINACT 0x9040 /* BO Inactive */
+#define AGNX_GCR_BODYNA 0x9044 /* BO dynamic */
+/* 802.11 mode(a,b,g) */
+#define AGNX_GCR_DISCOVMOD 0x9048 /* discovery mode */
+#define AGNX_GCR_NLISTANT 0x904c /* number of listening antenna */
+#define AGNX_GCR_NACTIANT 0x9050 /* number of active antenna */
+#define AGNX_GCR_NMEASANT 0x9054 /* number of measuring antenna */
+#define AGNX_GCR_NCAPTANT 0x9058 /* number of capture antenna */
+#define AGNX_GCR_THCAP11A 0x905c /* threshold capture 11a */
+#define AGNX_GCR_THCAP11B 0x9060 /* threshold capture 11b */
+#define AGNX_GCR_THCAPRX11A 0x9064 /* threshold capture rx 11a */
+#define AGNX_GCR_THCAPRX11B 0x9068 /* threshold capture rx 11b */
+#define AGNX_GCR_THLEVDRO 0x906c /* threshold level drop */
+#define AGNX_GCR_GAINSET0 0x9070 /* Gainset 0 */
+#define AGNX_GCR_GAINSET1 0x9074 /* Gainset 1 */
+#define AGNX_GCR_GAINSET2 0x9078 /* Gainset 2 */
+#define AGNX_GCR_MAXRXTIME11A 0x907c /* maximum rx time 11a */
+#define AGNX_GCR_MAXRXTIME11B 0x9080 /* maximum rx time 11b */
+#define AGNX_GCR_CORRTIME 0x9084 /* correction time */
+/* reset the subsystem, 0 = disable, 1 = enable */
+#define AGNX_GCR_RSTGCTL 0x9088 /* reset gain control */
+/* channel receiving */
+#define AGNX_GCR_RXCHANEL 0x908c /* receive channel */
+#define AGNX_GCR_NOISE0 0x9090 /* Noise 0 */
+#define AGNX_GCR_NOISE1 0x9094 /* Noise 1 */
+#define AGNX_GCR_NOISE2 0x9098 /* Noise 2 */
+#define AGNX_GCR_SIGHTH 0x909c /* Signal High Threshold */
+#define AGNX_GCR_SIGLTH 0x90a0 /* Signal Low Threshold */
+#define AGNX_GCR_CORRDROP 0x90a4 /* correction drop */
+/* threshold of tertiay antenna */
+#define AGNX_GCR_THCD 0x90a8 /* threshold? CD */
+#define AGNX_GCR_THCS 0x90ac /* threshold? CS */
+#define AGNX_GCR_MAXPOWDIFF 0x90b8 /* maximum power difference */
+#define AGNX_GCR_TRACNT4 0x90ec /* Transition Count 4 */
+#define AGNX_GCR_TRACNT5 0x90f0 /* transition count 5 */
+#define AGNX_GCR_TRACNT6 0x90f4 /* transition count 6 */
+#define AGNX_GCR_TRACNT7 0x90f8 /* transition coutn 7 */
+#define AGNX_GCR_TESTBUS 0x911c /* test bus */
+#define AGNX_GCR_CHAINNUM 0x9120 /* Number of Chains */
+#define AGNX_GCR_ANTCFG 0x9124 /* Antenna Config */
+#define AGNX_GCR_THJUMP 0x912c /* threhold jump */
+#define AGNX_GCR_THPOWER 0x9130 /* threshold power */
+#define AGNX_GCR_THPOWCLIP 0x9134 /* threshold power clip*/
+#define AGNX_GCR_FORCECTLCLK 0x9138 /* Force Gain Control Clock */
+#define AGNX_GCR_GAINSETWRITE 0x913c /* Gainset Write */
+#define AGNX_GCR_THD0BTFEST 0x9140 /* threshold d0 b tf estimate */
+#define AGNX_GCR_THRX11BPOWMIN 0x9144 /* threshold rx 11b power minimum */
+#define AGNX_GCR_0X14c 0x914c /* ?? */
+#define AGNX_GCR_0X150 0x9150 /* ?? */
+#define AGNX_GCR_RXOVERIDE 0x9194 /* recieve override */
+#define AGNX_GCR_WATCHDOG 0x91b0 /* watchdog timeout */
+
+
+/* Spi Interface */
+#define AGNX_SPI_BASE 0xdc00
+#define AGNX_SPI_CFG 0xdc00 /* spi configuration */
+/* Only accept 16 bits */
+#define AGNX_SPI_WMSW 0xdc04 /* write most significant word */
+/* Only accept 16 bits */
+#define AGNX_SPI_WLSW 0xdc08 /* write least significant word */
+#define AGNX_SPI_CTL 0xdc0c /* spi control */
+#define AGNX_SPI_RMSW 0xdc10 /* read most significant word */
+#define AGNX_SPI_RLSW 0xdc14 /* read least significant word */
+/* SPI Control Mask */
+#define SPI_READ_CTL 0x4000 /* read control */
+#define SPI_BUSY_CTL 0x8000 /* busy control */
+/* RF and synth chips in spi */
+#define RF_CHIP0 0x400
+#define RF_CHIP1 0x800
+#define RF_CHIP2 0x1000
+#define SYNTH_CHIP 0x2000
+
+/* Unknown register */
+#define AGNX_UNKNOWN_BASE 0x7800
+
+/* FIXME MonitorGain */
+#define AGNX_MONGCR_BASE 0x12000
+
+/* Gain Table */
+#define AGNX_GAIN_TABLE 0x12400
+
+/* The initial FIR coefficient table */
+#define AGNX_FIR_BASE 0x19804
+
+#define AGNX_ENGINE_LOOKUP_TBL 0x800
+
+/* eeprom commands */
+#define EEPROM_CMD_NULL 0x0 /* NULL */
+#define EEPROM_CMD_WRITE 0x2 /* write */
+#define EEPROM_CMD_READ 0x3 /* read */
+#define EEPROM_CMD_STATUSREAD 0x5 /* status register read */
+#define EEPROM_CMD_WRITEENABLE 0x6 /* write enable */
+#define EEPROM_CMD_CONFIGURE 0x7 /* configure */
+
+#define EEPROM_DATAFORCOFIGURE 0x6 /* ??? */
+
+/* eeprom address */
+#define EEPROM_ADDR_SUBVID 0x0 /* Sub Vendor ID */
+#define EEPROM_ADDR_SUBSID 0x2 /* Sub System ID */
+#define EEPROM_ADDR_MACADDR 0x146 /* MAC Address */
+#define EEPROM_ADDR_LOTYPE 0x14f /* LO type */
+
+struct agnx_eeprom {
+ u8 data; /* date */
+ u16 address; /* address in EEPROM */
+ u8 cmd; /* command, unknown, status */
+} __attribute__((__packed__));
+
+#define AGNX_EEPROM_COMMAND_SHIFT 5
+#define AGNX_EEPROM_COMMAND_STAT 0x01
+
+void disable_receiver(struct agnx_priv *priv);
+void enable_receiver(struct agnx_priv *priv);
+u8 read_from_eeprom(struct agnx_priv *priv, u16 address);
+void agnx_hw_init(struct agnx_priv *priv);
+int agnx_hw_reset(struct agnx_priv *priv);
+int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len);
+void agnx_set_bssid(struct agnx_priv *priv, u8 *bssid);
+void enable_power_saving(struct agnx_priv *priv);
+void disable_power_saving(struct agnx_priv *priv);
+void calibrate_antenna_period(unsigned long data);
+
+#endif /* AGNX_PHY_H_ */
diff --git a/drivers/staging/agnx/rf.c b/drivers/staging/agnx/rf.c
new file mode 100644
index 000000000000..8294b6e2eb9d
--- /dev/null
+++ b/drivers/staging/agnx/rf.c
@@ -0,0 +1,894 @@
+/**
+ * Airgo MIMO wireless driver
+ *
+ * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
+
+ * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
+ * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include "agnx.h"
+#include "debug.h"
+#include "phy.h"
+#include "table.h"
+
+/* FIXME! */
+static inline void spi_write(void __iomem *region, u32 chip_ids, u32 sw,
+ u16 size, u32 control)
+{
+ u32 reg;
+ u32 lsw = sw & 0xffff; /* lower 16 bits of sw*/
+ u32 msw = sw >> 16; /* high 16 bits of sw */
+
+ /* FIXME Write Most Significant Word of the 32bit data to MSW */
+ /* FIXME And Least Significant Word to LSW */
+ iowrite32((lsw), region + AGNX_SPI_WLSW);
+ iowrite32((msw), region + AGNX_SPI_WMSW);
+ reg = chip_ids | size | control;
+ /* Write chip id(s), write size and busy control to Control Register */
+ iowrite32((reg), region + AGNX_SPI_CTL);
+ /* Wait for Busy control to clear */
+ spi_delay();
+}
+
+/*
+ * Write to SPI Synth register
+ */
+static inline void spi_sy_write(void __iomem *region, u32 chip_ids, u32 sw)
+{
+ /* FIXME the size 0x15 is a magic value*/
+ spi_write(region, chip_ids, sw, 0x15, SPI_BUSY_CTL);
+}
+
+/*
+ * Write to SPI RF register
+ */
+static inline void spi_rf_write(void __iomem *region, u32 chip_ids, u32 sw)
+{
+ /* FIXME the size 0xd is a magic value*/
+ spi_write(region, chip_ids, sw, 0xd, SPI_BUSY_CTL);
+} /* spi_rf_write */
+
+/*
+ * Write to SPI with Read Control bit set
+ */
+inline void spi_rc_write(void __iomem *region, u32 chip_ids, u32 sw)
+{
+ /* FIXME the size 0xe5 is a magic value */
+ spi_write(region, chip_ids, sw, 0xe5, SPI_BUSY_CTL|SPI_READ_CTL);
+}
+
+/* Get the active chains's count */
+static int get_active_chains(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ int num = 0;
+ u32 reg;
+ AGNX_TRACE;
+
+ spi_rc_write(ctl, RF_CHIP0, 0x21);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+ if (reg == 1)
+ num++;
+
+ spi_rc_write(ctl, RF_CHIP1, 0x21);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+ if (reg == 1)
+ num++;
+
+ spi_rc_write(ctl, RF_CHIP2, 0x21);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+ if (reg == 1)
+ num++;
+
+ spi_rc_write(ctl, RF_CHIP0, 0x26);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+ if (0x33 != reg)
+ printk(KERN_WARNING PFX "Unmatched rf chips result\n");
+
+ return num;
+} /* get_active_chains */
+
+void rf_chips_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ int num;
+ AGNX_TRACE;
+
+ if (priv->revid == 1) {
+ reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
+ }
+
+ /* Set SPI clock speed to 200NS */
+ reg = agnx_read32(ctl, AGNX_SPI_CFG);
+ reg &= ~0xF;
+ reg |= 0x3;
+ agnx_write32(ctl, AGNX_SPI_CFG, reg);
+
+ /* Set SPI clock speed to 50NS */
+ reg = agnx_read32(ctl, AGNX_SPI_CFG);
+ reg &= ~0xF;
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_SPI_CFG, reg);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1101);
+
+ num = get_active_chains(priv);
+ printk(KERN_INFO PFX "Active chains are %d\n", num);
+
+ reg = agnx_read32(ctl, AGNX_SPI_CFG);
+ reg &= ~0xF;
+ agnx_write32(ctl, AGNX_SPI_CFG, reg);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1908);
+} /* rf_chips_init */
+
+
+static u32 channel_tbl[15][9] = {
+ {0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {1, 0x00, 0x00, 0x624, 0x00, 0x1a4, 0x28, 0x00, 0x1e},
+ {2, 0x00, 0x00, 0x615, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
+ {3, 0x00, 0x00, 0x61a, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
+ {4, 0x00, 0x00, 0x61f, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
+ {5, 0x00, 0x00, 0x624, 0x00, 0x1ae, 0x28, 0x00, 0x1e},
+ {6, 0x00, 0x00, 0x61f, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
+ {7, 0x00, 0x00, 0x624, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
+ {8, 0x00, 0x00, 0x629, 0x00, 0x1b3, 0x28, 0x00, 0x1e},
+ {9, 0x00, 0x00, 0x624, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
+ {10, 0x00, 0x00, 0x629, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
+ {11, 0x00, 0x00, 0x62e, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
+ {12, 0x00, 0x00, 0x633, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
+ {13, 0x00, 0x00, 0x628, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
+ {14, 0x00, 0x00, 0x644, 0x00, 0x1b8, 0x28, 0x00, 0x1e},
+};
+
+
+static inline void
+channel_tbl_write(struct agnx_priv *priv, unsigned int channel, unsigned int reg_num)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ reg = channel_tbl[channel][reg_num];
+ reg <<= 4;
+ reg |= reg_num;
+ spi_sy_write(ctl, SYNTH_CHIP, reg);
+}
+
+static void synth_freq_set(struct agnx_priv *priv, unsigned int channel)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
+
+ /* Set the Clock bits to 50NS */
+ reg = agnx_read32(ctl, AGNX_SPI_CFG);
+ reg &= ~0xF;
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_SPI_CFG, reg);
+
+ /* Write 0x00c0 to LSW and 0x3 to MSW of Synth Chip */
+ spi_sy_write(ctl, SYNTH_CHIP, 0x300c0);
+
+ spi_sy_write(ctl, SYNTH_CHIP, 0x32);
+
+ /* # Write to Register 1 on the Synth Chip */
+ channel_tbl_write(priv, channel, 1);
+ /* # Write to Register 3 on the Synth Chip */
+ channel_tbl_write(priv, channel, 3);
+ /* # Write to Register 6 on the Synth Chip */
+ channel_tbl_write(priv, channel, 6);
+ /* # Write to Register 5 on the Synth Chip */
+ channel_tbl_write(priv, channel, 5);
+ /* # Write to register 8 on the Synth Chip */
+ channel_tbl_write(priv, channel, 8);
+
+ /* FIXME Clear the clock bits */
+ reg = agnx_read32(ctl, AGNX_SPI_CFG);
+ reg &= ~0xf;
+ agnx_write32(ctl, AGNX_SPI_CFG, reg);
+} /* synth_chip_init */
+
+
+static void antenna_init(struct agnx_priv *priv, int num_antenna)
+{
+ void __iomem *ctl = priv->ctl;
+
+ switch (num_antenna) {
+ case 1:
+ agnx_write32(ctl, AGNX_GCR_NLISTANT, 1);
+ agnx_write32(ctl, AGNX_GCR_NMEASANT, 1);
+ agnx_write32(ctl, AGNX_GCR_NACTIANT, 1);
+ agnx_write32(ctl, AGNX_GCR_NCAPTANT, 1);
+
+ agnx_write32(ctl, AGNX_GCR_ANTCFG, 7);
+ agnx_write32(ctl, AGNX_GCR_BOACT, 34);
+ agnx_write32(ctl, AGNX_GCR_BOINACT, 34);
+ agnx_write32(ctl, AGNX_GCR_BODYNA, 30);
+
+ agnx_write32(ctl, AGNX_GCR_THD0A, 125);
+ agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
+ agnx_write32(ctl, AGNX_GCR_THD0B, 90);
+
+ agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 80);
+ agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
+ agnx_write32(ctl, AGNX_GCR_SIGLTH, 16);
+ break;
+ case 2:
+ agnx_write32(ctl, AGNX_GCR_NLISTANT, 2);
+ agnx_write32(ctl, AGNX_GCR_NMEASANT, 2);
+ agnx_write32(ctl, AGNX_GCR_NACTIANT, 2);
+ agnx_write32(ctl, AGNX_GCR_NCAPTANT, 2);
+ agnx_write32(ctl, AGNX_GCR_ANTCFG, 15);
+ agnx_write32(ctl, AGNX_GCR_BOACT, 36);
+ agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
+ agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
+ agnx_write32(ctl, AGNX_GCR_THD0A, 120);
+ agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
+ agnx_write32(ctl, AGNX_GCR_THD0B, 80);
+ agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
+ agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
+ agnx_write32(ctl, AGNX_GCR_SIGLTH, 32);
+ break;
+ case 3:
+ agnx_write32(ctl, AGNX_GCR_NLISTANT, 3);
+ agnx_write32(ctl, AGNX_GCR_NMEASANT, 3);
+ agnx_write32(ctl, AGNX_GCR_NACTIANT, 3);
+ agnx_write32(ctl, AGNX_GCR_NCAPTANT, 3);
+ agnx_write32(ctl, AGNX_GCR_ANTCFG, 31);
+ agnx_write32(ctl, AGNX_GCR_BOACT, 36);
+ agnx_write32(ctl, AGNX_GCR_BOINACT, 36);
+ agnx_write32(ctl, AGNX_GCR_BODYNA, 32);
+ agnx_write32(ctl, AGNX_GCR_THD0A, 100);
+ agnx_write32(ctl, AGNX_GCR_THD0AL, 100);
+ agnx_write32(ctl, AGNX_GCR_THD0B, 70);
+ agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 70);
+ agnx_write32(ctl, AGNX_GCR_SIGHTH, 100);
+ agnx_write32(ctl, AGNX_GCR_SIGLTH, 48);
+// agnx_write32(ctl, AGNX_GCR_SIGLTH, 16);
+ break;
+ default:
+ printk(KERN_WARNING PFX "Unknow antenna number\n");
+ }
+} /* antenna_init */
+
+static void chain_update(struct agnx_priv *priv, u32 chain)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ spi_rc_write(ctl, RF_CHIP0, 0x20);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+
+ if (reg == 0x4)
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
+ else if (reg != 0x0)
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
+ else {
+ if (chain == 3 || chain == 6) {
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, reg|0x1000);
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
+ } else if (chain == 2 || chain == 4) {
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, reg|0x1000);
+ spi_rf_write(ctl, RF_CHIP2, 0x1005);
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x824);
+ } else if (chain == 1) {
+ spi_rf_write(ctl, RF_CHIP0, reg|0x1000);
+ spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1004);
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xc36);
+ }
+ }
+
+ spi_rc_write(ctl, RF_CHIP0, 0x22);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+
+ switch (reg) {
+ case 0:
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
+ break;
+ case 1:
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
+ break;
+ case 2:
+ if (chain == 6 || chain == 4) {
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1202);
+ spi_rf_write(ctl, RF_CHIP2, 0x1005);
+ } else if (chain < 3) {
+ spi_rf_write(ctl, RF_CHIP0, 0x1202);
+ spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1005);
+ }
+ break;
+ default:
+ if (chain == 3) {
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
+ spi_rf_write(ctl, RF_CHIP2, 0x1201);
+ } else if (chain == 2) {
+ spi_rf_write(ctl, RF_CHIP0, 0x1203);
+ spi_rf_write(ctl, RF_CHIP2, 0x1200);
+ spi_rf_write(ctl, RF_CHIP1, 0x1201);
+ } else if (chain == 1) {
+ spi_rf_write(ctl, RF_CHIP0, 0x1203);
+ spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1200);
+ } else if (chain == 4) {
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
+ spi_rf_write(ctl, RF_CHIP2, 0x1201);
+ } else {
+ spi_rf_write(ctl, RF_CHIP0, 0x1203);
+ spi_rf_write(ctl, RF_CHIP1|RF_CHIP2, 0x1201);
+ }
+ }
+} /* chain_update */
+
+static void antenna_config(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ /* Write 0x0 to the TX Management Control Register Enable bit */
+ reg = agnx_read32(ctl, AGNX_TXM_CTL);
+ reg &= ~0x1;
+ agnx_write32(ctl, AGNX_TXM_CTL, reg);
+
+ /* FIXME */
+ /* Set initial value based on number of Antennae */
+ antenna_init(priv, 3);
+
+ /* FIXME Update Power Templates for current valid Stations */
+ /* sta_power_init(priv, 0);*/
+
+ /* FIXME the number of chains should get from eeprom*/
+ chain_update(priv, AGNX_CHAINS_MAX);
+} /* antenna_config */
+
+void calibrate_oscillator(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
+ reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
+ reg |= 0x10;
+ agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
+
+ agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 1);
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 1);
+
+ agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
+
+ agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
+ agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
+ /* (Residual DC Calibration) to Calibration Mode */
+ agnx_write32(ctl, AGNX_ACI_MODE, 0x2);
+
+ spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x1004);
+ agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
+ /* (TX LO Calibration) to Calibration Mode */
+ agnx_write32(ctl, AGNX_ACI_MODE, 0x4);
+
+ do {
+ u32 reg1, reg2, reg3;
+ /* Enable Power Saving Control */
+ enable_power_saving(priv);
+ /* Save the following registers to restore */
+ reg1 = ioread32(ctl + 0x11000);
+ reg2 = ioread32(ctl + 0xec50);
+ reg3 = ioread32(ctl + 0xec54);
+ wmb();
+
+ agnx_write32(ctl, 0x11000, 0xcfdf);
+ agnx_write32(ctl, 0xec50, 0x70);
+ /* Restore the registers */
+ agnx_write32(ctl, 0x11000, reg1);
+ agnx_write32(ctl, 0xec50, reg2);
+ agnx_write32(ctl, 0xec54, reg3);
+ /* Disable Power Saving Control */
+ disable_power_saving(priv);
+ } while (0);
+
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0);
+} /* calibrate_oscillator */
+
+
+static void radio_channel_set(struct agnx_priv *priv, unsigned int channel)
+{
+ void __iomem *ctl = priv->ctl;
+ unsigned int freq = priv->band.channels[channel - 1].center_freq;
+ u32 reg;
+ AGNX_TRACE;
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
+ /* Set SPI Clock to 50 Ns */
+ reg = agnx_read32(ctl, AGNX_SPI_CFG);
+ reg &= ~0xF;
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_SPI_CFG, reg);
+
+ /* Clear the Disable Tx interrupt bit in Interrupt Mask */
+/* reg = agnx_read32(ctl, AGNX_INT_MASK); */
+/* reg &= ~IRQ_TX_DISABLE; */
+/* agnx_write32(ctl, AGNX_INT_MASK, reg); */
+
+ /* Band Selection */
+ reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
+
+ /* FIXME Set the SiLabs Chip Frequency */
+ synth_freq_set(priv, channel);
+
+ reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
+ reg |= 0x80100030;
+ agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
+ reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
+ reg |= 0x20009;
+ agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
+
+ agnx_write32(ctl, AGNX_SYSITF_GPIOUT, 0x5);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1100);
+
+ /* Load the MonitorGain Table */
+ monitor_gain_table_init(priv);
+
+ /* Load the TX Fir table */
+ tx_fir_table_init(priv);
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg |= 0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+
+ spi_rc_write(ctl, RF_CHIP0|RF_CHIP1, 0x22);
+ udelay(80);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+
+
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff);
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
+
+ reg = agnx_read32(ctl, 0xec50);
+ reg |= 0x4f;
+ agnx_write32(ctl, 0xec50, reg);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
+ agnx_write32(ctl, 0x11008, 0x1);
+ agnx_write32(ctl, 0x1100c, 0x0);
+ agnx_write32(ctl, 0x11008, 0x0);
+ agnx_write32(ctl, 0xec50, 0xc);
+
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
+ agnx_write32(ctl, 0x11010, 0x6e);
+ agnx_write32(ctl, 0x11014, 0x6c);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1201);
+
+ /* Calibrate the Antenna */
+ /* antenna_calibrate(priv); */
+ /* Calibrate the TxLocalOscillator */
+ calibrate_oscillator(priv);
+
+ reg = agnx_read32(ctl, AGNX_PM_PMCTL);
+ reg &= ~0x8;
+ agnx_write32(ctl, AGNX_PM_PMCTL, reg);
+ agnx_write32(ctl, AGNX_GCR_GAININIT, 0xa);
+ agnx_write32(ctl, AGNX_GCR_THCD, 0x0);
+
+ agnx_write32(ctl, 0x11018, 0xb);
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x0);
+
+ /* Write Frequency to Gain Control Channel */
+ agnx_write32(ctl, AGNX_GCR_RXCHANEL, freq);
+ /* Write 0x140000/Freq to 0x9c08 */
+ reg = 0x140000/freq;
+ agnx_write32(ctl, 0x9c08, reg);
+
+ reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
+ reg &= ~0x80100030;
+ agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
+
+ reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
+ reg &= ~0x20009;
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
+
+ agnx_write32(ctl, AGNX_ACI_MODE, 0x0);
+
+/* FIXME According to Number of Chains: */
+
+/* 1. 1: */
+/* 1. Write 0x1203 to RF Chip 0 */
+/* 2. Write 0x1200 to RF Chips 1 +2 */
+/* 2. 2: */
+/* 1. Write 0x1203 to RF Chip 0 */
+/* 2. Write 0x1200 to RF Chip 2 */
+/* 3. Write 0x1201 to RF Chip 1 */
+/* 3. 3: */
+/* 1. Write 0x1203 to RF Chip 0 */
+/* 2. Write 0x1201 to RF Chip 1 + 2 */
+/* 4. 4: */
+/* 1. Write 0x1203 to RF Chip 0 + 1 */
+/* 2. Write 0x1200 to RF Chip 2 */
+
+/* 5. 6: */
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1, 0x1203);
+ spi_rf_write(ctl, RF_CHIP2, 0x1201);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
+
+ /* FIXME Set the Disable Tx interrupt bit in Interrupt Mask
+ (Or 0x20000 to Interrupt Mask) */
+/* reg = agnx_read32(ctl, AGNX_INT_MASK); */
+/* reg |= IRQ_TX_DISABLE; */
+/* agnx_write32(ctl, AGNX_INT_MASK, reg); */
+
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
+
+ /* Configure the Antenna */
+ antenna_config(priv);
+
+ /* Write 0x0 to Discovery Mode Enable detect G, B, A packet? */
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0);
+
+ reg = agnx_read32(ctl, AGNX_RXM_REQRATE);
+ reg |= 0x80000000;
+ agnx_write32(ctl, AGNX_RXM_REQRATE, reg);
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
+
+ /* enable radio on and the power LED */
+ reg = agnx_read32(ctl, AGNX_SYSITF_GPIOUT);
+ reg &= ~0x1;
+ reg |= 0x2;
+ agnx_write32(ctl, AGNX_SYSITF_GPIOUT, reg);
+
+ reg = agnx_read32(ctl, AGNX_TXM_CTL);
+ reg |= 0x1;
+ agnx_write32(ctl, AGNX_TXM_CTL, reg);
+} /* radio_channel_set */
+
+static void base_band_filter_calibrate(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1001);
+ agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x0);
+ spi_rc_write(ctl, RF_CHIP0, 0x27);
+ spi_rc_write(ctl, RF_CHIP1, 0x27);
+ spi_rc_write(ctl, RF_CHIP2, 0x27);
+ agnx_write32(ctl, AGNX_GCR_FORCECTLCLK, 0x1);
+}
+
+static void print_offset(struct agnx_priv *priv, u32 chain)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 offset;
+
+ iowrite32((chain), ctl + AGNX_ACI_SELCHAIN);
+ udelay(10);
+ offset = (ioread32(ctl + AGNX_ACI_OFFSET));
+ printk(PFX "Chain is 0x%x, Offset is 0x%x\n", chain, offset);
+}
+
+void print_offsets(struct agnx_priv *priv)
+{
+ print_offset(priv, 0);
+ print_offset(priv, 4);
+ print_offset(priv, 1);
+ print_offset(priv, 5);
+ print_offset(priv, 2);
+ print_offset(priv, 6);
+}
+
+
+struct chains {
+ u32 cali; /* calibrate value*/
+
+#define NEED_CALIBRATE 0
+#define SUCCESS_CALIBRATE 1
+ int status;
+};
+
+static void chain_calibrate(struct agnx_priv *priv, struct chains *chains,
+ unsigned int num)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 calibra = chains[num].cali;
+
+ if (num < 3)
+ calibra |= 0x1400;
+ else
+ calibra |= 0x1500;
+
+ switch (num) {
+ case 0:
+ case 4:
+ spi_rf_write(ctl, RF_CHIP0, calibra);
+ break;
+ case 1:
+ case 5:
+ spi_rf_write(ctl, RF_CHIP1, calibra);
+ break;
+ case 2:
+ case 6:
+ spi_rf_write(ctl, RF_CHIP2, calibra);
+ break;
+ default:
+ BUG();
+ }
+} /* chain_calibrate */
+
+
+static void inline get_calibrete_value(struct agnx_priv *priv, struct chains *chains,
+ unsigned int num)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 offset;
+
+ iowrite32((num), ctl + AGNX_ACI_SELCHAIN);
+ /* FIXME */
+ udelay(10);
+ offset = (ioread32(ctl + AGNX_ACI_OFFSET));
+
+ if (offset < 0xf) {
+ chains[num].status = SUCCESS_CALIBRATE;
+ return;
+ }
+
+ if (num == 0 || num == 1 || num == 2) {
+ if ( 0 == chains[num].cali)
+ chains[num].cali = 0xff;
+ else
+ chains[num].cali--;
+ } else
+ chains[num].cali++;
+
+ chains[num].status = NEED_CALIBRATE;
+}
+
+static inline void calibra_delay(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ unsigned int i = 100;
+
+ wmb();
+ while (i--) {
+ reg = (ioread32(ctl + AGNX_ACI_STATUS));
+ if (reg == 0x4000)
+ break;
+ udelay(10);
+ }
+ if (!i)
+ printk(PFX "calibration failed\n");
+}
+
+void do_calibration(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ struct chains chains[7];
+ unsigned int i, j;
+ AGNX_TRACE;
+
+ for (i = 0; i < 7; i++) {
+ if (i == 3)
+ continue;
+
+ chains[i].cali = 0x7f;
+ chains[i].status = NEED_CALIBRATE;
+ }
+
+ /* FIXME 0x300 is a magic number */
+ for (j = 0; j < 0x300; j++) {
+ if (chains[0].status == SUCCESS_CALIBRATE &&
+ chains[1].status == SUCCESS_CALIBRATE &&
+ chains[2].status == SUCCESS_CALIBRATE &&
+ chains[4].status == SUCCESS_CALIBRATE &&
+ chains[5].status == SUCCESS_CALIBRATE &&
+ chains[6].status == SUCCESS_CALIBRATE)
+ break;
+
+ /* Attention, there is no chain 3 */
+ for (i = 0; i < 7; i++) {
+ if (i == 3)
+ continue;
+ if (chains[i].status == NEED_CALIBRATE)
+ chain_calibrate(priv, chains, i);
+ }
+ /* Write 0x1 to Calibration Measure */
+ iowrite32((0x1), ctl + AGNX_ACI_MEASURE);
+ calibra_delay(priv);
+
+ for (i = 0; i < 7; i++) {
+ if (i == 3)
+ continue;
+
+ get_calibrete_value(priv, chains, i);
+ }
+ }
+ printk(PFX "Clibrate times is %d\n", j);
+ print_offsets(priv);
+} /* do_calibration */
+
+void antenna_calibrate(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+ AGNX_TRACE;
+
+ agnx_write32(ctl, AGNX_GCR_NLISTANT, 0x3);
+ agnx_write32(ctl, AGNX_GCR_NMEASANT, 0x3);
+ agnx_write32(ctl, AGNX_GCR_NACTIANT, 0x3);
+ agnx_write32(ctl, AGNX_GCR_NCAPTANT, 0x3);
+
+ agnx_write32(ctl, AGNX_GCR_ANTCFG, 0x1f);
+ agnx_write32(ctl, AGNX_GCR_BOACT, 0x24);
+ agnx_write32(ctl, AGNX_GCR_BOINACT, 0x24);
+ agnx_write32(ctl, AGNX_GCR_BODYNA, 0x20);
+ agnx_write32(ctl, AGNX_GCR_THD0A, 0x64);
+ agnx_write32(ctl, AGNX_GCR_THD0AL, 0x64);
+ agnx_write32(ctl, AGNX_GCR_THD0B, 0x46);
+ agnx_write32(ctl, AGNX_GCR_THD0BTFEST, 0x3c);
+ agnx_write32(ctl, AGNX_GCR_SIGHTH, 0x64);
+ agnx_write32(ctl, AGNX_GCR_SIGLTH, 0x30);
+
+ spi_rc_write(ctl, RF_CHIP0, 0x20);
+ /* Fixme */
+ udelay(80);
+ /* 1. Should read 0x0 */
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+ if (0x0 != reg)
+ printk(KERN_WARNING PFX "Unmatched rf chips result\n");
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1000);
+
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
+
+ spi_rc_write(ctl, RF_CHIP0, 0x22);
+ udelay(80);
+ reg = agnx_read32(ctl, AGNX_SPI_RLSW);
+ if (0x0 != reg)
+ printk(KERN_WARNING PFX "Unmatched rf chips result\n");
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1005);
+
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x1);
+ agnx_write32(ctl, AGNX_GCR_RSTGCTL, 0x0);
+
+ reg = agnx_read32(ctl, AGNX_PM_SOFTRST);
+ reg |= 0x1c000032;
+ agnx_write32(ctl, AGNX_PM_SOFTRST, reg);
+ reg = agnx_read32(ctl, AGNX_PM_PLLCTL);
+ reg |= 0x0003f07;
+ agnx_write32(ctl, AGNX_PM_PLLCTL, reg);
+
+ reg = agnx_read32(ctl, 0xec50);
+ reg |= 0x40;
+ agnx_write32(ctl, 0xec50, reg);
+
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0xff8);
+ agnx_write32(ctl, AGNX_GCR_DISCOVMOD, 0x3);
+
+ agnx_write32(ctl, AGNX_GCR_CHAINNUM, 0x6);
+ agnx_write32(ctl, 0x19874, 0x0);
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1700);
+
+ /* Calibrate the BaseBandFilter */
+ base_band_filter_calibrate(priv);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
+
+ agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
+ agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
+ agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
+ agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
+
+ agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
+ agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
+
+ agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
+ agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
+
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
+
+ /* Measure Calibration */
+ agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
+ calibra_delay(priv);
+
+ /* do calibration */
+ do_calibration(priv);
+
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
+ agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
+ agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
+ agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
+
+ reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
+ reg &= 0xf;
+ agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
+ reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
+ reg &= 0xf;
+ agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
+ reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
+ reg &= 0xf;
+ agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
+
+ agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
+ disable_receiver(priv);
+} /* antenna_calibrate */
+
+void __antenna_calibrate(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ /* Calibrate the BaseBandFilter */
+ /* base_band_filter_calibrate(priv); */
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1002);
+
+
+ agnx_write32(ctl, AGNX_GCR_GAINSET0, 0x1d);
+ agnx_write32(ctl, AGNX_GCR_GAINSET1, 0x1d);
+ agnx_write32(ctl, AGNX_GCR_GAINSET2, 0x1d);
+
+ agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x1);
+
+ agnx_write32(ctl, AGNX_ACI_MODE, 0x1);
+ agnx_write32(ctl, AGNX_ACI_LEN, 0x3ff);
+
+
+ agnx_write32(ctl, AGNX_ACI_TIMER1, 0x27);
+ agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1400);
+ spi_rf_write(ctl, RF_CHIP0|RF_CHIP1|RF_CHIP2, 0x1500);
+ /* Measure Calibration */
+ agnx_write32(ctl, AGNX_ACI_MEASURE, 0x1);
+ calibra_delay(priv);
+ do_calibration(priv);
+ agnx_write32(ctl, AGNX_GCR_RXOVERIDE, 0x0);
+
+ agnx_write32(ctl, AGNX_ACI_TIMER1, 0x21);
+ agnx_write32(ctl, AGNX_ACI_TIMER2, 0x27);
+
+ agnx_write32(ctl, AGNX_ACI_LEN, 0xf);
+
+ reg = agnx_read32(ctl, AGNX_GCR_GAINSET0);
+ reg &= 0xf;
+ agnx_write32(ctl, AGNX_GCR_GAINSET0, reg);
+ reg = agnx_read32(ctl, AGNX_GCR_GAINSET1);
+ reg &= 0xf;
+ agnx_write32(ctl, AGNX_GCR_GAINSET1, reg);
+ reg = agnx_read32(ctl, AGNX_GCR_GAINSET2);
+ reg &= 0xf;
+ agnx_write32(ctl, AGNX_GCR_GAINSET2, reg);
+
+
+ agnx_write32(ctl, AGNX_GCR_GAINSETWRITE, 0x0);
+
+ /* Write 0x3 Gain Control Discovery Mode */
+ enable_receiver(priv);
+}
+
+int agnx_set_channel(struct agnx_priv *priv, unsigned int channel)
+{
+ AGNX_TRACE;
+
+ printk(KERN_ERR PFX "Channel is %d %s\n", channel, __func__);
+ radio_channel_set(priv, channel);
+ return 0;
+}
diff --git a/drivers/staging/agnx/sta.c b/drivers/staging/agnx/sta.c
new file mode 100644
index 000000000000..d3ac675e45bd
--- /dev/null
+++ b/drivers/staging/agnx/sta.c
@@ -0,0 +1,219 @@
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include "phy.h"
+#include "sta.h"
+#include "debug.h"
+
+void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
+{
+ void __iomem *ctl = priv->ctl;
+
+ reglo &= 0xFFFF;
+ reglo |= 0x30000000;
+ reglo |= 0x40000000; /* Set status busy */
+ reglo |= sta_id << 16;
+
+ iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
+ iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
+ iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
+
+ reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
+ reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
+ printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
+}
+
+void hash_write(struct agnx_priv *priv, u8 *mac_addr, u8 sta_id)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reghi, reglo;
+
+ if (!is_valid_ether_addr(mac_addr))
+ printk(KERN_WARNING PFX "Update hash table: Invalid hwaddr!\n");
+
+ reghi = mac_addr[0] << 24 | mac_addr[1] << 16 | mac_addr[2] << 8 | mac_addr[3];
+ reglo = mac_addr[4] << 8 | mac_addr[5];
+ reglo |= 0x10000000; /* Set hash commmand */
+ reglo |= 0x40000000; /* Set status busy */
+ reglo |= sta_id << 16;
+
+ iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
+ iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
+ iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
+
+ reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
+ if (!(reglo & 0x80000000))
+ printk(KERN_WARNING PFX "Update hash table failed\n");
+}
+
+void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
+{
+ void __iomem *ctl = priv->ctl;
+
+ reglo &= 0xFFFF;
+ reglo |= 0x20000000;
+ reglo |= 0x40000000; /* Set status busy */
+ reglo |= sta_id << 16;
+
+ iowrite32(0, ctl + AGNX_RXM_HASH_CMD_FLAG);
+ iowrite32(reghi, ctl + AGNX_RXM_HASH_CMD_HIGH);
+ iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
+ reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
+
+ reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
+ printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
+
+}
+
+void hash_dump(struct agnx_priv *priv, u8 sta_id)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reghi, reglo;
+
+ reglo = 0x0; /* dump command */
+ reglo|= 0x40000000; /* status bit */
+ iowrite32(reglo, ctl + AGNX_RXM_HASH_CMD_LOW);
+ iowrite32(sta_id << 16, ctl + AGNX_RXM_HASH_DUMP_DATA);
+
+ udelay(80);
+
+ reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_HIGH);
+ reglo = ioread32(ctl + AGNX_RXM_HASH_CMD_LOW);
+ printk(PFX "hash cmd are : %.8x%.8x\n", reghi, reglo);
+ reghi = ioread32(ctl + AGNX_RXM_HASH_CMD_FLAG);
+ printk(PFX "hash flag is : %.8x\n", reghi);
+ reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_MST);
+ reglo = ioread32(ctl + AGNX_RXM_HASH_DUMP_LST);
+ printk(PFX "hash dump mst lst: %.8x%.8x\n", reghi, reglo);
+ reghi = ioread32(ctl + AGNX_RXM_HASH_DUMP_DATA);
+ printk(PFX "hash dump data: %.8x\n", reghi);
+}
+
+void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
+{
+ void __iomem *ctl = priv->ctl;
+ memcpy_fromio(power, ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
+ sizeof(*power));
+}
+
+inline void
+set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx)
+{
+ void __iomem *ctl = priv->ctl;
+ /* FIXME 2. Write Template to offset + station number */
+ memcpy_toio(ctl + AGNX_TXM_STAPOWTEMP + sizeof(*power) * sta_idx,
+ power, sizeof(*power));
+}
+
+
+void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
+ unsigned int sta_idx, unsigned int wq_idx)
+{
+ void __iomem *data = priv->data;
+ memcpy_fromio(tx_wq, data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
+ sizeof(*tx_wq) * wq_idx, sizeof(*tx_wq));
+
+}
+
+inline void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
+ unsigned int sta_idx, unsigned int wq_idx)
+{
+ void __iomem *data = priv->data;
+ memcpy_toio(data + AGNX_PDU_TX_WQ + sizeof(*tx_wq) * STA_TX_WQ_NUM * sta_idx +
+ sizeof(*tx_wq) * wq_idx, tx_wq, sizeof(*tx_wq));
+}
+
+
+void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
+{
+ void __iomem *data = priv->data;
+
+ memcpy_fromio(sta, data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
+ sizeof(*sta));
+}
+
+inline void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx)
+{
+ void __iomem *data = priv->data;
+
+ memcpy_toio(data + AGNX_PDUPOOL + sizeof(*sta) * sta_idx,
+ sta, sizeof(*sta));
+}
+
+/* FIXME */
+void sta_power_init(struct agnx_priv *priv, unsigned int sta_idx)
+{
+ struct agnx_sta_power power;
+ u32 reg;
+ AGNX_TRACE;
+
+ memset(&power, 0, sizeof(power));
+ reg = agnx_set_bits(EDCF, EDCF_SHIFT, 0x1);
+ power.reg = cpu_to_le32(reg);
+ set_sta_power(priv, &power, sta_idx);
+ udelay(40);
+} /* add_power_template */
+
+
+/* @num: The #number of station that is visible to the card */
+static void sta_tx_workqueue_init(struct agnx_priv *priv, unsigned int sta_idx)
+{
+ struct agnx_sta_tx_wq tx_wq;
+ u32 reg;
+ unsigned int i;
+
+ memset(&tx_wq, 0, sizeof(tx_wq));
+
+ reg = agnx_set_bits(WORK_QUEUE_VALID, WORK_QUEUE_VALID_SHIFT, 1);
+ reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 1);
+// reg |= agnx_set_bits(WORK_QUEUE_ACK_TYPE, WORK_QUEUE_ACK_TYPE_SHIFT, 0);
+ tx_wq.reg2 |= cpu_to_le32(reg);
+
+ /* Suppose all 8 traffic class are used */
+ for (i = 0; i < STA_TX_WQ_NUM; i++)
+ set_sta_tx_wq(priv, &tx_wq, sta_idx, i);
+} /* sta_tx_workqueue_init */
+
+
+static void sta_traffic_init(struct agnx_sta_traffic *traffic)
+{
+ u32 reg;
+ memset(traffic, 0, sizeof(*traffic));
+
+ reg = agnx_set_bits(NEW_PACKET, NEW_PACKET_SHIFT, 1);
+ reg |= agnx_set_bits(TRAFFIC_VALID, TRAFFIC_VALID_SHIFT, 1);
+// reg |= agnx_set_bits(TRAFFIC_ACK_TYPE, TRAFFIC_ACK_TYPE_SHIFT, 1);
+ traffic->reg0 = cpu_to_le32(reg);
+
+ /* 3. setting RX Sequence Number to 4095 */
+ reg = agnx_set_bits(RX_SEQUENCE_NUM, RX_SEQUENCE_NUM_SHIFT, 4095);
+ traffic->reg1 = cpu_to_le32(reg);
+}
+
+
+/* @num: The #number of station that is visible to the card */
+void sta_init(struct agnx_priv *priv, unsigned int sta_idx)
+{
+ /* FIXME the length of sta is 256 bytes Is that
+ * dangerous to stack overflow? */
+ struct agnx_sta sta;
+ u32 reg;
+ int i;
+
+ memset(&sta, 0, sizeof(sta));
+ /* Set valid to 1 */
+ reg = agnx_set_bits(STATION_VALID, STATION_VALID_SHIFT, 1);
+ /* Set Enable Concatenation to 0 (?) */
+ reg |= agnx_set_bits(ENABLE_CONCATENATION, ENABLE_CONCATENATION_SHIFT, 0);
+ /* Set Enable Decompression to 0 (?) */
+ reg |= agnx_set_bits(ENABLE_DECOMPRESSION, ENABLE_DECOMPRESSION_SHIFT, 0);
+ sta.reg = cpu_to_le32(reg);
+
+ /* Initialize each of the Traffic Class Structures by: */
+ for (i = 0; i < 8; i++)
+ sta_traffic_init(sta.traffic + i);
+
+ set_sta(priv, &sta, sta_idx);
+ sta_tx_workqueue_init(priv, sta_idx);
+} /* sta_descriptor_init */
+
+
diff --git a/drivers/staging/agnx/sta.h b/drivers/staging/agnx/sta.h
new file mode 100644
index 000000000000..58d0b12900df
--- /dev/null
+++ b/drivers/staging/agnx/sta.h
@@ -0,0 +1,222 @@
+#ifndef AGNX_STA_H_
+#define AGNX_STA_H_
+
+#define STA_TX_WQ_NUM 8 /* The number of TX workqueue one STA has */
+
+struct agnx_hash_cmd {
+ __be32 cmdhi;
+#define MACLO 0xFFFF0000
+#define MACLO_SHIFT 16
+#define STA_ID 0x0000FFF0
+#define STA_ID_SHIFT 4
+#define CMD 0x0000000C
+#define CMD_SHIFT 2
+#define STATUS 0x00000002
+#define STATUS_SHIFT 1
+#define PASS 0x00000001
+#define PASS_SHIFT 1
+ __be32 cmdlo;
+}__attribute__((__packed__));
+
+
+/*
+ * Station Power Template
+ * FIXME Just for agn100 yet
+ */
+struct agnx_sta_power {
+ __le32 reg;
+#define SIGNAL 0x000000FF /* signal */
+#define SIGNAL_SHIFT 0
+#define RATE 0x00000F00
+#define RATE_SHIFT 8
+#define TIFS 0x00001000
+#define TIFS_SHIFT 12
+#define EDCF 0x00002000
+#define EDCF_SHIFT 13
+#define CHANNEL_BOND 0x00004000
+#define CHANNEL_BOND_SHIFT 14
+#define PHY_MODE 0x00038000
+#define PHY_MODE_SHIFT 15
+#define POWER_LEVEL 0x007C0000
+#define POWER_LEVEL_SHIFT 18
+#define NUM_TRANSMITTERS 0x00800000
+#define NUM_TRANSMITTERS_SHIFT 23
+} __attribute__((__packed__));
+
+/*
+ * TX Workqueue Descriptor
+ */
+struct agnx_sta_tx_wq {
+ __le32 reg0;
+#define HEAD_POINTER_LOW 0xFF000000 /* Head pointer low */
+#define HEAD_POINTER_LOW_SHIFT 24
+#define TAIL_POINTER 0x00FFFFFF /* Tail pointer */
+#define TAIL_POINTER_SHIFT 0
+
+ __le32 reg3;
+#define ACK_POINTER_LOW 0xFFFF0000 /* ACK pointer low */
+#define ACK_POINTER_LOW_SHIFT 16
+#define HEAD_POINTER_HIGH 0x0000FFFF /* Head pointer high */
+#define HEAD_POINTER_HIGH_SHIFT 0
+
+ __le32 reg1;
+/* ACK timeout tail packet count */
+#define ACK_TIMOUT_TAIL_PACK_CNT 0xFFF00000
+#define ACK_TIMOUT_TAIL_PACK_CNT_SHIFT 20
+/* Head timeout tail packet count */
+#define HEAD_TIMOUT_TAIL_PACK_CNT 0x000FFF00
+#define HEAD_TIMOUT_TAIL_PACK_CNT_SHIFT 8
+#define ACK_POINTER_HIGH 0x000000FF /* ACK pointer high */
+#define ACK_POINTER_HIGH_SHIFT 0
+
+ __le32 reg2;
+#define WORK_QUEUE_VALID 0x80000000 /* valid */
+#define WORK_QUEUE_VALID_SHIFT 31
+#define WORK_QUEUE_ACK_TYPE 0x40000000 /* ACK type */
+#define WORK_QUEUE_ACK_TYPE_SHIFT 30
+/* Head timeout window limit fragmentation count */
+#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT 0x3FFF0000
+#define HEAD_TIMOUT_WIN_LIM_FRAG_CNT_SHIFT 16
+/* Head timeout window limit byte count */
+#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT 0x0000FFFF
+#define HEAD_TIMOUT_WIN_LIM_BYTE_CNT_SHIFT 0
+} __attribute__((__packed__));
+
+
+/*
+ * Traffic Class Structure
+ */
+struct agnx_sta_traffic {
+ __le32 reg0;
+#define ACK_TIMOUT_CNT 0xFF800000 /* ACK Timeout Counts */
+#define ACK_TIMOUT_CNT_SHIFT 23
+#define TRAFFIC_ACK_TYPE 0x00600000 /* ACK Type */
+#define TRAFFIC_ACK_TYPE_SHIFT 21
+#define NEW_PACKET 0x00100000 /* New Packet */
+#define NEW_PACKET_SHIFT 20
+#define TRAFFIC_VALID 0x00080000 /* Valid */
+#define TRAFFIC_VALID_SHIFT 19
+#define RX_HDR_DESC_POINTER 0x0007FFFF /* RX Header Descripter pointer */
+#define RX_HDR_DESC_POINTER_SHIFT 0
+
+ __le32 reg1;
+#define RX_PACKET_TIMESTAMP 0xFFFF0000 /* RX Packet Timestamp */
+#define RX_PACKET_TIMESTAMP_SHIFT 16
+#define TRAFFIC_RESERVED 0x0000E000 /* Reserved */
+#define TRAFFIC_RESERVED_SHIFT 13
+#define SV 0x00001000 /* sv */
+#define SV_SHIFT 12
+#define RX_SEQUENCE_NUM 0x00000FFF /* RX Sequence Number */
+#define RX_SEQUENCE_NUM_SHIFT 0
+
+ __le32 tx_replay_cnt_low; /* TX Replay Counter Low */
+
+ __le16 tx_replay_cnt_high; /* TX Replay Counter High */
+ __le16 rx_replay_cnt_high; /* RX Replay Counter High */
+
+ __be32 rx_replay_cnt_low; /* RX Replay Counter Low */
+} __attribute__((__packed__));
+
+/*
+ * Station Descriptors
+ */
+struct agnx_sta {
+ __le32 tx_session_keys[4]; /* Transmit Session Key (0-3) */
+ __le32 rx_session_keys[4]; /* Receive Session Key (0-3) */
+
+ __le32 reg;
+#define ID_1 0xC0000000 /* id 1 */
+#define ID_1_SHIFT 30
+#define ID_0 0x30000000 /* id 0 */
+#define ID_0_SHIFT 28
+#define ENABLE_CONCATENATION 0x0FF00000 /* Enable concatenation */
+#define ENABLE_CONCATENATION_SHIFT 20
+#define ENABLE_DECOMPRESSION 0x000FF000 /* Enable decompression */
+#define ENABLE_DECOMPRESSION_SHIFT 12
+#define STA_RESERVED 0x00000C00 /* Reserved */
+#define STA_RESERVED_SHIFT 10
+#define EAP 0x00000200 /* EAP */
+#define EAP_SHIFT 9
+#define ED_NULL 0x00000100 /* ED NULL */
+#define ED_NULL_SHIFT 8
+#define ENCRYPTION_POLICY 0x000000E0 /* Encryption Policy */
+#define ENCRYPTION_POLICY_SHIFT 5
+#define DEFINED_KEY_ID 0x00000018 /* Defined Key ID */
+#define DEFINED_KEY_ID_SHIFT 3
+#define FIXED_KEY 0x00000004 /* Fixed Key */
+#define FIXED_KEY_SHIFT 2
+#define KEY_VALID 0x00000002 /* Key Valid */
+#define KEY_VALID_SHIFT 1
+#define STATION_VALID 0x00000001 /* Station Valid */
+#define STATION_VALID_SHIFT 0
+
+ __le32 tx_aes_blks_unicast; /* TX AES Blks Unicast */
+ __le32 rx_aes_blks_unicast; /* RX AES Blks Unicast */
+
+ __le16 aes_format_err_unicast_cnt; /* AES Format Error Unicast Counts */
+ __le16 aes_replay_unicast; /* AES Replay Unicast */
+
+ __le16 aes_decrypt_err_unicast; /* AES Decrypt Error Unicast */
+ __le16 aes_decrypt_err_default; /* AES Decrypt Error default */
+
+ __le16 single_retry_packets; /* Single Retry Packets */
+ __le16 failed_tx_packets; /* Failed Tx Packets */
+
+ __le16 muti_retry_packets; /* Multiple Retry Packets */
+ __le16 ack_timeouts; /* ACK Timeouts */
+
+ __le16 frag_tx_cnt; /* Fragment TX Counts */
+ __le16 rts_brq_sent; /* RTS Brq Sent */
+
+ __le16 tx_packets; /* TX Packets */
+ __le16 cts_back_timeout; /* CTS Back Timeout */
+
+ __le32 phy_stats_high; /* PHY Stats High */
+ __le32 phy_stats_low; /* PHY Stats Low */
+
+ struct agnx_sta_traffic traffic[8]; /* Traffic Class Structure (8) */
+
+ __le16 traffic_class0_frag_success; /* Traffic Class 0 Fragment Success */
+ __le16 traffic_class1_frag_success; /* Traffic Class 1 Fragment Success */
+ __le16 traffic_class2_frag_success; /* Traffic Class 2 Fragment Success */
+ __le16 traffic_class3_frag_success; /* Traffic Class 3 Fragment Success */
+ __le16 traffic_class4_frag_success; /* Traffic Class 4 Fragment Success */
+ __le16 traffic_class5_frag_success; /* Traffic Class 5 Fragment Success */
+ __le16 traffic_class6_frag_success; /* Traffic Class 6 Fragment Success */
+ __le16 traffic_class7_frag_success; /* Traffic Class 7 Fragment Success */
+
+ __le16 num_frag_non_prime_rates; /* number of Fragments for non-prime rates */
+ __le16 ack_timeout_non_prime_rates; /* ACK Timeout for non-prime rates */
+
+} __attribute__((__packed__));
+
+
+struct agnx_beacon_hdr {
+ struct agnx_sta_power power; /* Tx Station Power Template */
+ u8 phy_hdr[6]; /* PHY Hdr */
+ u8 frame_len_lo; /* Frame Length Lo */
+ u8 frame_len_hi; /* Frame Length Hi */
+ u8 mac_hdr[24]; /* MAC Header */
+ /* FIXME */
+ /* 802.11(abg) beacon */
+} __attribute__((__packed__));
+
+void hash_write(struct agnx_priv *priv, u8 *mac_addr, u8 sta_id);
+void hash_dump(struct agnx_priv *priv, u8 sta_id);
+void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
+void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
+
+void get_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power, unsigned int sta_idx);
+void set_sta_power(struct agnx_priv *priv, struct agnx_sta_power *power,
+ unsigned int sta_idx);
+void get_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
+ unsigned int sta_idx, unsigned int wq_idx);
+void set_sta_tx_wq(struct agnx_priv *priv, struct agnx_sta_tx_wq *tx_wq,
+ unsigned int sta_idx, unsigned int wq_idx);
+void get_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
+void set_sta(struct agnx_priv *priv, struct agnx_sta *sta, unsigned int sta_idx);
+
+void sta_power_init(struct agnx_priv *priv, unsigned int num);
+void sta_init(struct agnx_priv *priv, unsigned int num);
+
+#endif /* AGNX_STA_H_ */
diff --git a/drivers/staging/agnx/table.c b/drivers/staging/agnx/table.c
new file mode 100644
index 000000000000..c60048487b5a
--- /dev/null
+++ b/drivers/staging/agnx/table.c
@@ -0,0 +1,168 @@
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include "agnx.h"
+#include "debug.h"
+#include "phy.h"
+
+static const u32
+tx_fir_table[] = { 0x19, 0x5d, 0xce, 0x151, 0x1c3, 0x1ff, 0x1ea, 0x17c, 0xcf,
+ 0x19, 0x38e, 0x350, 0x362, 0x3ad, 0x5, 0x44, 0x59, 0x49,
+ 0x21, 0x3f7, 0x3e0, 0x3e3, 0x3f3, 0x0 };
+
+void tx_fir_table_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tx_fir_table); i++)
+ iowrite32(tx_fir_table[i], ctl + AGNX_FIR_BASE + i*4);
+} /* fir_table_setup */
+
+
+static const u32
+gain_table[] = { 0x8, 0x8, 0xf, 0x13, 0x17, 0x1b, 0x1f, 0x23, 0x27, 0x2b,
+ 0x2f, 0x33, 0x37, 0x3b, 0x3f, 0x43, 0x47, 0x4b, 0x4f,
+ 0x53, 0x57, 0x5b, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+ 0x5f, 0x5f, 0x5f, 0x5f };
+
+void gain_table_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(gain_table); i++) {
+ iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4);
+ iowrite32(gain_table[i], ctl + AGNX_GAIN_TABLE + i*4 + 0x80);
+ }
+} /* gain_table_init */
+
+void monitor_gain_table_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ unsigned int i;
+
+ for (i = 0; i < 0x44; i += 4) {
+ iowrite32(0x61, ctl + AGNX_MONGCR_BASE + i);
+ iowrite32(0x61, ctl + AGNX_MONGCR_BASE + 0x200 + i);
+ }
+ for (i = 0x44; i < 0x64; i += 4) {
+ iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + i);
+ iowrite32(0x6e, ctl + AGNX_MONGCR_BASE + 0x200 + i);
+ }
+ for (i = 0x64; i < 0x94; i += 4) {
+ iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + i);
+ iowrite32(0x7a, ctl + AGNX_MONGCR_BASE + 0x200 + i);
+ }
+ for (i = 0x94; i < 0xdc; i += 4) {
+ iowrite32(0x87, ctl + AGNX_MONGCR_BASE + i);
+ iowrite32(0x87, ctl + AGNX_MONGCR_BASE + 0x200 + i);
+ }
+ for (i = 0xdc; i < 0x148; i += 4) {
+ iowrite32(0x95, ctl + AGNX_MONGCR_BASE + i);
+ iowrite32(0x95, ctl + AGNX_MONGCR_BASE + 0x200 + i);
+ }
+ for (i = 0x148; i < 0x1e8; i += 4) {
+ iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + i);
+ iowrite32(0xa2, ctl + AGNX_MONGCR_BASE + 0x200 + i);
+ }
+ for (i = 0x1e8; i <= 0x1fc; i += 4) {
+ iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + i);
+ iowrite32(0xb0, ctl + AGNX_MONGCR_BASE + 0x200 + i);
+ }
+} /* monitor_gain_table_init */
+
+
+void routing_table_init(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ unsigned int type, subtype;
+ u32 reg;
+
+ disable_receiver(priv);
+
+ for ( type = 0; type < 0x3; type++ ) {
+ for (subtype = 0; subtype < 0x10; subtype++) {
+ /* 1. Set Routing table to R/W and to Return status on Read */
+ reg = (type << ROUTAB_TYPE_SHIFT) |
+ (subtype << ROUTAB_SUBTYPE_SHIFT);
+ reg |= (1 << ROUTAB_RW_SHIFT) | (1 << ROUTAB_STATUS_SHIFT);
+ if (type == ROUTAB_TYPE_DATA) {
+ /* NULL goes to RFP */
+ if (subtype == ROUTAB_SUBTYPE_NULL)
+// reg |= ROUTAB_ROUTE_RFP;
+ reg |= ROUTAB_ROUTE_CPU;
+ /* QOS NULL goes to CPU */
+ else if (subtype == ROUTAB_SUBTYPE_QOSNULL)
+ reg |= ROUTAB_ROUTE_CPU;
+ /* All Data and QOS data subtypes go to Encryption */
+ else if ((subtype == ROUTAB_SUBTYPE_DATA) ||
+ (subtype == ROUTAB_SUBTYPE_DATAACK) ||
+ (subtype == ROUTAB_SUBTYPE_DATAPOLL) ||
+ (subtype == ROUTAB_SUBTYPE_DATAPOLLACK) ||
+ (subtype == ROUTAB_SUBTYPE_QOSDATA) ||
+ (subtype == ROUTAB_SUBTYPE_QOSDATAACK) ||
+ (subtype == ROUTAB_SUBTYPE_QOSDATAPOLL) ||
+ (subtype == ROUTAB_SUBTYPE_QOSDATAACKPOLL))
+ reg |= ROUTAB_ROUTE_ENCRY;
+// reg |= ROUTAB_ROUTE_CPU;
+ /*Drop NULL and QOS NULL ack, poll and poll ack*/
+ else if ((subtype == ROUTAB_SUBTYPE_NULLACK) ||
+ (subtype == ROUTAB_SUBTYPE_QOSNULLACK) ||
+ (subtype == ROUTAB_SUBTYPE_NULLPOLL) ||
+ (subtype == ROUTAB_SUBTYPE_QOSNULLPOLL) ||
+ (subtype == ROUTAB_SUBTYPE_NULLPOLLACK) ||
+ (subtype == ROUTAB_SUBTYPE_QOSNULLPOLLACK))
+// reg |= ROUTAB_ROUTE_DROP;
+ reg |= ROUTAB_ROUTE_CPU;
+ }
+ else
+ reg |= (ROUTAB_ROUTE_CPU);
+ iowrite32(reg, ctl + AGNX_RXM_ROUTAB);
+ /* Check to verify that the status bit cleared */
+ routing_table_delay();
+ }
+ }
+ enable_receiver(priv);
+} /* routing_table_init */
+
+void tx_engine_lookup_tbl_init(struct agnx_priv *priv)
+{
+ void __iomem *data = priv->data;
+ unsigned int i;
+
+ for (i = 0; i <= 28; i += 4)
+ iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ for (i = 32; i <= 120; i += 8) {
+ iowrite32(0x1e58, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ iowrite32(0xb00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
+ }
+
+ for (i = 128; i <= 156; i += 4)
+ iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ for (i = 160; i <= 248; i += 8) {
+ iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
+ }
+
+ for (i = 256; i <= 284; i += 4)
+ iowrite32(0x980c, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ for (i = 288; i <= 376; i += 8) {
+ iowrite32(0x1a58, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ iowrite32(0x1858, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
+ }
+
+ for (i = 512; i <= 540; i += 4)
+ iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ for (i = 544; i <= 632; i += 8) {
+ iowrite32(0x2058, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ iowrite32(0xc00c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
+ }
+
+ for (i = 640; i <= 668; i += 4)
+ iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ for (i = 672; i <= 764; i += 8) {
+ iowrite32(0x2258, data + AGNX_ENGINE_LOOKUP_TBL + i);
+ iowrite32(0xc80c, data + AGNX_ENGINE_LOOKUP_TBL + i + 4);
+ }
+}
+
diff --git a/drivers/staging/agnx/table.h b/drivers/staging/agnx/table.h
new file mode 100644
index 000000000000..f0626b5ee86b
--- /dev/null
+++ b/drivers/staging/agnx/table.h
@@ -0,0 +1,10 @@
+#ifndef AGNX_TABLE_H_
+#define AGNX_TABLE_H_
+
+void tx_fir_table_init(struct agnx_priv *priv);
+void gain_table_init(struct agnx_priv *priv);
+void monitor_gain_table_init(struct agnx_priv *priv);
+void routing_table_init(struct agnx_priv *priv);
+void tx_engine_lookup_tbl_init(struct agnx_priv *priv);
+
+#endif /* AGNX_TABLE_H_ */
diff --git a/drivers/staging/agnx/xmit.c b/drivers/staging/agnx/xmit.c
new file mode 100644
index 000000000000..7f01528b8a46
--- /dev/null
+++ b/drivers/staging/agnx/xmit.c
@@ -0,0 +1,819 @@
+/**
+ * Airgo MIMO wireless driver
+ *
+ * Copyright (c) 2007 Li YanBo <dreamfly281@gmail.com>
+
+ * Thanks for Jeff Williams <angelbane@gmail.com> do reverse engineer
+ * works and published the SPECS at http://airgo.wdwconsulting.net/mymoin
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include "agnx.h"
+#include "debug.h"
+#include "phy.h"
+
+unsigned int rx_frame_cnt = 0;
+//unsigned int local_tx_sent_cnt = 0;
+
+static inline void disable_rx_engine(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ iowrite32(0x100, ctl + AGNX_CIR_RXCTL);
+ /* Wait for RX Control to have the Disable Rx Interrupt (0x100) set */
+ ioread32(ctl + AGNX_CIR_RXCTL);
+}
+
+static inline void enable_rx_engine(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ iowrite32(0x80, ctl + AGNX_CIR_RXCTL);
+ ioread32(ctl + AGNX_CIR_RXCTL);
+}
+
+inline void disable_rx_interrupt(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ disable_rx_engine(priv);
+ reg = ioread32(ctl + AGNX_CIR_RXCFG);
+ reg &= ~0x20;
+ iowrite32(reg, ctl + AGNX_CIR_RXCFG);
+ ioread32(ctl + AGNX_CIR_RXCFG);
+}
+
+inline void enable_rx_interrupt(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ reg = ioread32(ctl + AGNX_CIR_RXCFG);
+ reg |= 0x20;
+ iowrite32(reg, ctl + AGNX_CIR_RXCFG);
+ ioread32(ctl + AGNX_CIR_RXCFG);
+ enable_rx_engine(priv);
+}
+
+static inline void rx_desc_init(struct agnx_priv *priv, unsigned int idx)
+{
+ struct agnx_desc *desc = priv->rx.desc + idx;
+ struct agnx_info *info = priv->rx.info + idx;
+
+ memset(info, 0, sizeof(*info));
+
+ info->dma_len = IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct agnx_hdr);
+ info->skb = dev_alloc_skb(info->dma_len);
+ if (info->skb == NULL)
+ agnx_bug("refill err");
+
+ info->mapping = pci_map_single(priv->pdev, skb_tail_pointer(info->skb),
+ info->dma_len, PCI_DMA_FROMDEVICE);
+ memset(desc, 0, sizeof(*desc));
+ desc->dma_addr = cpu_to_be32(info->mapping);
+ /* Set the owner to the card */
+ desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
+}
+
+static inline void rx_desc_reinit(struct agnx_priv *priv, unsigned int idx)
+{
+ struct agnx_info *info = priv->rx.info + idx;
+
+ /* Cause ieee80211 will free the skb buffer, so we needn't to free it again?! */
+ pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
+ rx_desc_init(priv, idx);
+}
+
+static inline void rx_desc_reusing(struct agnx_priv *priv, unsigned int idx)
+{
+ struct agnx_desc *desc = priv->rx.desc + idx;
+ struct agnx_info *info = priv->rx.info + idx;
+
+ memset(desc, 0, sizeof(*desc));
+ desc->dma_addr = cpu_to_be32(info->mapping);
+ /* Set the owner to the card */
+ desc->frag = cpu_to_be32(be32_to_cpu(desc->frag) | OWNER);
+}
+
+static void rx_desc_free(struct agnx_priv *priv, unsigned int idx)
+{
+ struct agnx_desc *desc = priv->rx.desc + idx;
+ struct agnx_info *info = priv->rx.info + idx;
+
+ BUG_ON(!desc || !info);
+ if (info->mapping)
+ pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_FROMDEVICE);
+ if (info->skb)
+ dev_kfree_skb(info->skb);
+ memset(info, 0, sizeof(*info));
+ memset(desc, 0, sizeof(*desc));
+}
+
+static inline void __tx_desc_free(struct agnx_priv *priv,
+ struct agnx_desc *desc, struct agnx_info *info)
+{
+ BUG_ON(!desc || !info);
+ /* TODO make sure mapping, skb and len are consistency */
+ if (info->mapping)
+ pci_unmap_single(priv->pdev, info->mapping,
+ info->dma_len, PCI_DMA_TODEVICE);
+ if (info->type == PACKET)
+ dev_kfree_skb(info->skb);
+
+ memset(info, 0, sizeof(*info));
+ memset(desc, 0, sizeof(*desc));
+}
+
+static void txm_desc_free(struct agnx_priv *priv, unsigned int idx)
+{
+ struct agnx_desc *desc = priv->txm.desc + idx;
+ struct agnx_info *info = priv->txm.info + idx;
+
+ __tx_desc_free(priv, desc, info);
+}
+
+static void txd_desc_free(struct agnx_priv *priv, unsigned int idx)
+{
+ struct agnx_desc *desc = priv->txd.desc + idx;
+ struct agnx_info *info = priv->txd.info + idx;
+
+ __tx_desc_free(priv, desc, info);
+}
+
+int fill_rings(struct agnx_priv *priv)
+{
+ void __iomem *ctl = priv->ctl;
+ unsigned int i;
+ u32 reg;
+ AGNX_TRACE;
+
+ priv->txd.idx_sent = priv->txm.idx_sent = 0;
+ priv->rx.idx = priv->txm.idx = priv->txd.idx = 0;
+
+ for (i = 0; i < priv->rx.size; i++)
+ rx_desc_init(priv, i);
+ for (i = 0; i < priv->txm.size; i++) {
+ memset(priv->txm.desc + i, 0, sizeof(struct agnx_desc));
+ memset(priv->txm.info + i, 0, sizeof(struct agnx_info));
+ }
+ for (i = 0; i < priv->txd.size; i++) {
+ memset(priv->txd.desc + i, 0, sizeof(struct agnx_desc));
+ memset(priv->txd.info + i, 0, sizeof(struct agnx_info));
+ }
+
+ /* FIXME Set the card RX TXM and TXD address */
+ agnx_write32(ctl, AGNX_CIR_RXCMSTART, priv->rx.dma);
+ agnx_write32(ctl, AGNX_CIR_RXCMEND, priv->txm.dma);
+
+ agnx_write32(ctl, AGNX_CIR_TXMSTART, priv->txm.dma);
+ agnx_write32(ctl, AGNX_CIR_TXMEND, priv->txd.dma);
+
+ agnx_write32(ctl, AGNX_CIR_TXDSTART, priv->txd.dma);
+ agnx_write32(ctl, AGNX_CIR_TXDEND, priv->txd.dma +
+ sizeof(struct agnx_desc) * priv->txd.size);
+
+ /* FIXME Relinquish control of rings to card */
+ reg = agnx_read32(ctl, AGNX_CIR_BLKCTL);
+ reg &= ~0x800;
+ agnx_write32(ctl, AGNX_CIR_BLKCTL, reg);
+ return 0;
+} /* fill_rings */
+
+void unfill_rings(struct agnx_priv *priv)
+{
+ unsigned long flags;
+ unsigned int i;
+ AGNX_TRACE;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ for (i = 0; i < priv->rx.size; i++)
+ rx_desc_free(priv, i);
+ for (i = 0; i < priv->txm.size; i++)
+ txm_desc_free(priv, i);
+ for (i = 0; i < priv->txd.size; i++)
+ txd_desc_free(priv, i);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/* Extract the bitrate out of a CCK PLCP header.
+ copy from bcm43xx driver */
+static inline u8 agnx_plcp_get_bitrate_cck(__be32 *phyhdr_11b)
+{
+ /* FIXME */
+ switch (*(u8 *)phyhdr_11b) {
+ case 0x0A:
+ return 0;
+ case 0x14:
+ return 1;
+ case 0x37:
+ return 2;
+ case 0x6E:
+ return 3;
+ }
+ agnx_bug("Wrong plcp rate");
+ return 0;
+}
+
+/* FIXME */
+static inline u8 agnx_plcp_get_bitrate_ofdm(__be32 *phyhdr_11g)
+{
+ u8 rate = *(u8 *)phyhdr_11g & 0xF;
+
+ printk(PFX "G mode rate is 0x%x\n", rate);
+ return rate;
+}
+
+/* FIXME */
+static void get_rx_stats(struct agnx_priv *priv, struct agnx_hdr *hdr,
+ struct ieee80211_rx_status *stat)
+{
+ void __iomem *ctl = priv->ctl;
+ u8 *rssi;
+ u32 noise;
+ /* FIXME just for test */
+ int snr = 40; /* signal-to-noise ratio */
+
+ memset(stat, 0, sizeof(*stat));
+ /* RSSI */
+ rssi = (u8 *)&hdr->phy_stats_lo;
+// stat->ssi = (rssi[0] + rssi[1] + rssi[2]) / 3;
+ /* Noise */
+ noise = ioread32(ctl + AGNX_GCR_NOISE0);
+ noise += ioread32(ctl + AGNX_GCR_NOISE1);
+ noise += ioread32(ctl + AGNX_GCR_NOISE2);
+ stat->noise = noise / 3;
+ /* Signal quality */
+ //snr = stat->ssi - stat->noise;
+ if (snr >=0 && snr < 40)
+ stat->signal = 5 * snr / 2;
+ else if (snr >= 40)
+ stat->signal = 100;
+ else
+ stat->signal = 0;
+
+
+ if (hdr->_11b0 && !hdr->_11g0) {
+ stat->rate_idx = agnx_plcp_get_bitrate_cck(&hdr->_11b0);
+ } else if (!hdr->_11b0 && hdr->_11g0) {
+ printk(PFX "RX: Found G mode packet\n");
+ stat->rate_idx = agnx_plcp_get_bitrate_ofdm(&hdr->_11g0);
+ } else
+ agnx_bug("Unknown packets type");
+
+
+ stat->band = IEEE80211_BAND_2GHZ;
+ stat->freq = agnx_channels[priv->channel - 1].center_freq;
+// stat->antenna = 3;
+// stat->mactime = be32_to_cpu(hdr->time_stamp);
+// stat->channel = priv->channel;
+
+}
+
+static inline void combine_hdr_frag(struct ieee80211_hdr *ieeehdr,
+ struct sk_buff *skb)
+{
+ u16 fctl;
+ unsigned int hdrlen;
+
+ fctl = le16_to_cpu(ieeehdr->frame_control);
+ hdrlen = ieee80211_hdrlen(fctl);
+ /* FIXME */
+ if (hdrlen < (2+2+6)/*minimum hdr*/ ||
+ hdrlen > sizeof(struct ieee80211_mgmt)) {
+ printk(KERN_ERR PFX "hdr len is %d\n", hdrlen);
+ agnx_bug("Wrong ieee80211 hdr detected");
+ }
+ skb_push(skb, hdrlen);
+ memcpy(skb->data, ieeehdr, hdrlen);
+} /* combine_hdr_frag */
+
+static inline int agnx_packet_check(struct agnx_priv *priv, struct agnx_hdr *agnxhdr,
+ unsigned packet_len)
+{
+ if (agnx_get_bits(CRC_FAIL, CRC_FAIL_SHIFT, be32_to_cpu(agnxhdr->reg1)) == 1){
+ printk(PFX "RX: CRC check fail\n");
+ goto drop;
+ }
+ if (packet_len > 2048) {
+ printk(PFX "RX: Too long packet detected\n");
+ goto drop;
+ }
+
+ /* FIXME Just usable for Promious Mode, for Manage mode exclude FCS */
+/* if (packet_len - sizeof(*agnxhdr) < FCS_LEN) { */
+/* printk(PFX "RX: Too short packet detected\n"); */
+/* goto drop; */
+/* } */
+ return 0;
+drop:
+ priv->stats.dot11FCSErrorCount++;
+ return -1;
+}
+
+void handle_rx_irq(struct agnx_priv *priv)
+{
+ struct ieee80211_rx_status status;
+ unsigned int len;
+// AGNX_TRACE;
+
+ do {
+ struct agnx_desc *desc;
+ u32 frag;
+ struct agnx_info *info;
+ struct agnx_hdr *hdr;
+ struct sk_buff *skb;
+ unsigned int i = priv->rx.idx % priv->rx.size;
+
+ desc = priv->rx.desc + i;
+ frag = be32_to_cpu(desc->frag);
+ if (frag & OWNER)
+ break;
+
+ info = priv->rx.info + i;
+ skb = info->skb;
+ hdr = (struct agnx_hdr *)(skb->data);
+
+ len = (frag & PACKET_LEN) >> PACKET_LEN_SHIFT;
+ if (agnx_packet_check(priv, hdr, len) == -1) {
+ rx_desc_reusing(priv, i);
+ continue;
+ }
+ skb_put(skb, len);
+
+ do {
+ u16 fctl;
+ fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr)->frame_control);
+ if ((fctl & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_BEACON)// && !(fctl & IEEE80211_STYPE_BEACON))
+ dump_ieee80211_hdr((struct ieee80211_hdr *)hdr->mac_hdr, "RX");
+ } while (0);
+
+ if (hdr->_11b0 && !hdr->_11g0) {
+/* int j; */
+/* u16 fctl = le16_to_cpu(((struct ieee80211_hdr *)hdr->mac_hdr) */
+/* ->frame_control); */
+/* if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { */
+/* agnx_print_rx_hdr(hdr); */
+// agnx_print_sta(priv, BSSID_STAID);
+/* for (j = 0; j < 8; j++) */
+/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
+/* } */
+
+ get_rx_stats(priv, hdr, &status);
+ skb_pull(skb, sizeof(*hdr));
+ combine_hdr_frag((struct ieee80211_hdr *)hdr->mac_hdr, skb);
+ } else if (!hdr->_11b0 && hdr->_11g0) {
+// int j;
+ agnx_print_rx_hdr(hdr);
+ agnx_print_sta(priv, BSSID_STAID);
+// for (j = 0; j < 8; j++)
+ agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
+
+ print_hex_dump_bytes("agnx: RX_PACKET: ", DUMP_PREFIX_NONE,
+ skb->data, skb->len + 8);
+
+// if (agnx_plcp_get_bitrate_ofdm(&hdr->_11g0) == 0)
+ get_rx_stats(priv, hdr, &status);
+ skb_pull(skb, sizeof(*hdr));
+ combine_hdr_frag((struct ieee80211_hdr *)
+ ((void *)&hdr->mac_hdr), skb);
+// dump_ieee80211_hdr((struct ieee80211_hdr *)skb->data, "RX G");
+ } else
+ agnx_bug("Unknown packets type");
+ ieee80211_rx_irqsafe(priv->hw, skb, &status);
+ rx_desc_reinit(priv, i);
+
+ } while ( priv->rx.idx++ );
+} /* handle_rx_irq */
+
+static inline void handle_tx_irq(struct agnx_priv *priv, struct agnx_ring *ring)
+{
+ struct agnx_desc *desc;
+ struct agnx_info *info;
+ unsigned int idx;
+
+ for (idx = ring->idx_sent; idx < ring->idx; idx++) {
+ unsigned int i = idx % ring->size;
+ u32 frag;
+
+ desc = ring->desc + i;
+ info = ring->info + i;
+
+ frag = be32_to_cpu(desc->frag);
+ if (frag & OWNER) {
+ if (info->type == HEADER)
+ break;
+ else
+ agnx_bug("TX error");
+ }
+
+ pci_unmap_single(priv->pdev, info->mapping, info->dma_len, PCI_DMA_TODEVICE);
+
+ do {
+// int j;
+ size_t len;
+ len = info->skb->len - sizeof(struct agnx_hdr) + info->hdr_len;
+ // if (len == 614) {
+// agnx_print_desc(desc);
+ if (info->type == PACKET) {
+// agnx_print_tx_hdr((struct agnx_hdr *)info->skb->data);
+/* agnx_print_sta_power(priv, LOCAL_STAID); */
+/* agnx_print_sta(priv, LOCAL_STAID); */
+/* // for (j = 0; j < 8; j++) */
+/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, 0); */
+// agnx_print_sta_power(priv, BSSID_STAID);
+// agnx_print_sta(priv, BSSID_STAID);
+// for (j = 0; j < 8; j++)
+// agnx_print_sta_tx_wq(priv, BSSID_STAID, 0);
+ }
+// }
+ } while (0);
+
+ if (info->type == PACKET) {
+// dump_txm_registers(priv);
+// dump_rxm_registers(priv);
+// dump_bm_registers(priv);
+// dump_cir_registers(priv);
+ }
+
+ if (info->type == PACKET) {
+// struct ieee80211_hdr *hdr;
+ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(info->skb);
+
+ skb_pull(info->skb, sizeof(struct agnx_hdr));
+ memcpy(skb_push(info->skb, info->hdr_len), &info->hdr, info->hdr_len);
+
+// dump_ieee80211_hdr((struct ieee80211_hdr *)info->skb->data, "TX_HANDLE");
+/* print_hex_dump_bytes("agnx: TX_HANDLE: ", DUMP_PREFIX_NONE, */
+/* info->skb->data, info->skb->len); */
+
+ if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK))
+ txi->flags |= IEEE80211_TX_STAT_ACK;
+
+ ieee80211_tx_status_irqsafe(priv->hw, info->skb);
+
+
+/* info->tx_status.queue_number = (ring->size - i) / 2; */
+/* ieee80211_tx_status_irqsafe(priv->hw, info->skb, &(info->tx_status)); */
+/* } else */
+/* dev_kfree_skb_irq(info->skb); */
+ }
+ memset(desc, 0, sizeof(*desc));
+ memset(info, 0, sizeof(*info));
+ }
+
+ ring->idx_sent = idx;
+ /* TODO fill the priv->low_level_stats */
+
+ /* ieee80211_wake_queue(priv->hw, 0); */
+}
+
+void handle_txm_irq(struct agnx_priv *priv)
+{
+ handle_tx_irq(priv, &priv->txm);
+}
+
+void handle_txd_irq(struct agnx_priv *priv)
+{
+ handle_tx_irq(priv, &priv->txd);
+}
+
+void handle_other_irq(struct agnx_priv *priv)
+{
+// void __iomem *ctl = priv->ctl;
+ u32 status = priv->irq_status;
+ void __iomem *ctl = priv->ctl;
+ u32 reg;
+
+ if (status & IRQ_TX_BEACON) {
+ iowrite32(IRQ_TX_BEACON, ctl + AGNX_INT_STAT);
+ printk(PFX "IRQ: TX Beacon control is 0X%.8X\n", ioread32(ctl + AGNX_TXM_BEACON_CTL));
+ printk(PFX "IRQ: TX Beacon rx frame num: %d\n", rx_frame_cnt);
+ }
+ if (status & IRQ_TX_RETRY) {
+ reg = ioread32(ctl + AGNX_TXM_RETRYSTAID);
+ printk(PFX "IRQ: TX Retry, RETRY STA ID is %x\n", reg);
+ }
+ if (status & IRQ_TX_ACTIVITY)
+ printk(PFX "IRQ: TX Activity\n");
+ if (status & IRQ_RX_ACTIVITY)
+ printk(PFX "IRQ: RX Activity\n");
+ if (status & IRQ_RX_X)
+ printk(PFX "IRQ: RX X\n");
+ if (status & IRQ_RX_Y) {
+ reg = ioread32(ctl + AGNX_INT_MASK);
+ reg &= ~IRQ_RX_Y;
+ iowrite32(reg, ctl + AGNX_INT_MASK);
+ iowrite32(IRQ_RX_Y, ctl + AGNX_INT_STAT);
+ printk(PFX "IRQ: RX Y\n");
+ }
+ if (status & IRQ_RX_HASHHIT) {
+ reg = ioread32(ctl + AGNX_INT_MASK);
+ reg &= ~IRQ_RX_HASHHIT;
+ iowrite32(reg, ctl + AGNX_INT_MASK);
+ iowrite32(IRQ_RX_HASHHIT, ctl + AGNX_INT_STAT);
+ printk(PFX "IRQ: RX Hash Hit\n");
+
+ }
+ if (status & IRQ_RX_FRAME) {
+ reg = ioread32(ctl + AGNX_INT_MASK);
+ reg &= ~IRQ_RX_FRAME;
+ iowrite32(reg, ctl + AGNX_INT_MASK);
+ iowrite32(IRQ_RX_FRAME, ctl + AGNX_INT_STAT);
+ printk(PFX "IRQ: RX Frame\n");
+ rx_frame_cnt++;
+ }
+ if (status & IRQ_ERR_INT) {
+ iowrite32(IRQ_ERR_INT, ctl + AGNX_INT_STAT);
+// agnx_hw_reset(priv);
+ printk(PFX "IRQ: Error Interrupt\n");
+ }
+ if (status & IRQ_TX_QUE_FULL)
+ printk(PFX "IRQ: TX Workqueue Full\n");
+ if (status & IRQ_BANDMAN_ERR)
+ printk(PFX "IRQ: Bandwidth Management Error\n");
+ if (status & IRQ_TX_DISABLE)
+ printk(PFX "IRQ: TX Disable\n");
+ if (status & IRQ_RX_IVASESKEY)
+ printk(PFX "IRQ: RX Invalid Session Key\n");
+ if (status & IRQ_REP_THHIT)
+ printk(PFX "IRQ: Replay Threshold Hit\n");
+ if (status & IRQ_TIMER1)
+ printk(PFX "IRQ: Timer1\n");
+ if (status & IRQ_TIMER_CNT)
+ printk(PFX "IRQ: Timer Count\n");
+ if (status & IRQ_PHY_FASTINT)
+ printk(PFX "IRQ: Phy Fast Interrupt\n");
+ if (status & IRQ_PHY_SLOWINT)
+ printk(PFX "IRQ: Phy Slow Interrupt\n");
+ if (status & IRQ_OTHER)
+ printk(PFX "IRQ: 0x80000000\n");
+} /* handle_other_irq */
+
+
+static inline void route_flag_set(struct agnx_hdr *txhdr)
+{
+// u32 reg = 0;
+
+ /* FIXME */
+/* reg = (0x7 << ROUTE_COMPRESSION_SHIFT) & ROUTE_COMPRESSION; */
+/* txhdr->reg5 = cpu_to_be32(reg); */
+ txhdr->reg5 = (0xa << 0x0) | (0x7 << 0x18);
+// txhdr->reg5 = cpu_to_be32((0xa << 0x0) | (0x7 << 0x18));
+// txhdr->reg5 = cpu_to_be32(0x7 << 0x0);
+}
+
+/* Return 0 if no match */
+static inline unsigned int get_power_level(unsigned int rate, unsigned int antennas_num)
+{
+ unsigned int power_level;
+
+ switch (rate) {
+ case 10:
+ case 20:
+ case 55:
+ case 60:
+ case 90:
+ case 120: power_level = 22; break;
+ case 180: power_level = 19; break;
+ case 240: power_level = 18; break;
+ case 360: power_level = 16; break;
+ case 480: power_level = 15; break;
+ case 540: power_level = 14; break;
+ default:
+ agnx_bug("Error rate setting\n");
+ }
+
+ if (power_level && (antennas_num == 2))
+ power_level -= 3;
+
+ return power_level;
+}
+
+static inline void fill_agnx_hdr(struct agnx_priv *priv, struct agnx_info *tx_info)
+{
+ struct agnx_hdr *txhdr = (struct agnx_hdr *)tx_info->skb->data;
+ size_t len;
+ u16 fc = le16_to_cpu(*(__le16 *)&tx_info->hdr);
+ u32 reg;
+
+ memset(txhdr, 0, sizeof(*txhdr));
+
+// reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, LOCAL_STAID);
+ reg = agnx_set_bits(STATION_ID, STATION_ID_SHIFT, BSSID_STAID);
+ reg |= agnx_set_bits(WORKQUEUE_ID, WORKQUEUE_ID_SHIFT, 0);
+ txhdr->reg4 = cpu_to_be32(reg);
+
+ /* Set the Hardware Sequence Number to 1? */
+ reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 0);
+// reg = agnx_set_bits(SEQUENCE_NUMBER, SEQUENCE_NUMBER_SHIFT, 1);
+ reg |= agnx_set_bits(MAC_HDR_LEN, MAC_HDR_LEN_SHIFT, tx_info->hdr_len);
+ txhdr->reg1 = cpu_to_be32(reg);
+ /* Set the agnx_hdr's MAC header */
+ memcpy(txhdr->mac_hdr, &tx_info->hdr, tx_info->hdr_len);
+
+ reg = agnx_set_bits(ACK, ACK_SHIFT, 1);
+// reg = agnx_set_bits(ACK, ACK_SHIFT, 0);
+ reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 0);
+// reg |= agnx_set_bits(MULTICAST, MULTICAST_SHIFT, 1);
+ reg |= agnx_set_bits(RELAY, RELAY_SHIFT, 0);
+ reg |= agnx_set_bits(TM, TM_SHIFT, 0);
+ txhdr->reg0 = cpu_to_be32(reg);
+
+ /* Set the long and short retry limits */
+ txhdr->tx.short_retry_limit = tx_info->txi->control.rates[0].count;
+ txhdr->tx.long_retry_limit = tx_info->txi->control.rates[0].count;
+
+ /* FIXME */
+ len = tx_info->skb->len - sizeof(*txhdr) + tx_info->hdr_len + FCS_LEN;
+ if (fc & IEEE80211_FCTL_PROTECTED)
+ len += 8;
+ len = 2398;
+ reg = agnx_set_bits(FRAG_SIZE, FRAG_SIZE_SHIFT, len);
+ len = tx_info->skb->len - sizeof(*txhdr);
+ reg |= agnx_set_bits(PAYLOAD_LEN, PAYLOAD_LEN_SHIFT, len);
+ txhdr->reg3 = cpu_to_be32(reg);
+
+ route_flag_set(txhdr);
+} /* fill_hdr */
+
+static void txm_power_set(struct agnx_priv *priv,
+ struct ieee80211_tx_info *txi)
+{
+ struct agnx_sta_power power;
+ u32 reg;
+
+ /* FIXME */
+ if (txi->control.rates[0].idx < 0) {
+ /* For B mode Short Preamble */
+ reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_SHORT);
+// control->tx_rate = -control->tx_rate;
+ } else
+ reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211G);
+// reg = agnx_set_bits(PHY_MODE, PHY_MODE_SHIFT, AGNX_MODE_80211B_LONG);
+ reg |= agnx_set_bits(SIGNAL, SIGNAL_SHIFT, 0xB);
+ reg |= agnx_set_bits(RATE, RATE_SHIFT, 0xB);
+// reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 15);
+ reg |= agnx_set_bits(POWER_LEVEL, POWER_LEVEL_SHIFT, 20);
+ /* if rate < 11M set it to 0 */
+ reg |= agnx_set_bits(NUM_TRANSMITTERS, NUM_TRANSMITTERS_SHIFT, 1);
+// reg |= agnx_set_bits(EDCF, EDCF_SHIFT, 1);
+// reg |= agnx_set_bits(TIFS, TIFS_SHIFT, 1);
+
+ power.reg = reg;
+// power.reg = cpu_to_le32(reg);
+
+// set_sta_power(priv, &power, LOCAL_STAID);
+ set_sta_power(priv, &power, BSSID_STAID);
+}
+
+static inline int tx_packet_check(struct sk_buff *skb)
+{
+ unsigned int ieee_len = ieee80211_get_hdrlen_from_skb(skb);
+ if (skb->len > 2048) {
+ printk(KERN_ERR PFX "length is %d\n", skb->len);
+ agnx_bug("Too long TX skb");
+ return -1;
+ }
+ /* FIXME */
+ if (skb->len == ieee_len) {
+ printk(PFX "A strange TX packet\n");
+ return -1;
+ /* tx_faile_irqsafe(); */
+ }
+ return 0;
+}
+
+static int __agnx_tx(struct agnx_priv *priv, struct sk_buff *skb,
+ struct agnx_ring *ring)
+{
+ struct agnx_desc *hdr_desc, *frag_desc;
+ struct agnx_info *hdr_info, *frag_info;
+ struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb);
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ /* The RX interrupt need be Disable until this TX packet
+ is handled in the next tx interrupt */
+ disable_rx_interrupt(priv);
+
+ i = ring->idx;
+ ring->idx += 2;
+/* if (priv->txm_idx - priv->txm_idx_sent == AGNX_TXM_RING_SIZE - 2) */
+/* ieee80211_stop_queue(priv->hw, 0); */
+
+ /* Set agnx header's info and desc */
+ i %= ring->size;
+ hdr_desc = ring->desc + i;
+ hdr_info = ring->info + i;
+ hdr_info->hdr_len = ieee80211_get_hdrlen_from_skb(skb);
+ memcpy(&hdr_info->hdr, skb->data, hdr_info->hdr_len);
+
+ /* Add the agnx header to the front of the SKB */
+ skb_push(skb, sizeof(struct agnx_hdr) - hdr_info->hdr_len);
+
+ hdr_info->txi = txi;
+ hdr_info->dma_len = sizeof(struct agnx_hdr);
+ hdr_info->skb = skb;
+ hdr_info->type = HEADER;
+ fill_agnx_hdr(priv, hdr_info);
+ hdr_info->mapping = pci_map_single(priv->pdev, skb->data,
+ hdr_info->dma_len, PCI_DMA_TODEVICE);
+ do {
+ u32 frag = 0;
+ frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 1);
+ frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 0);
+ frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
+ frag |= agnx_set_bits(FIRST_FRAG_LEN, FIRST_FRAG_LEN_SHIFT, 1);
+ frag |= agnx_set_bits(OWNER, OWNER_SHIFT, 1);
+ hdr_desc->frag = cpu_to_be32(frag);
+ } while (0);
+ hdr_desc->dma_addr = cpu_to_be32(hdr_info->mapping);
+
+
+ /* Set Frag's info and desc */
+ i = (i + 1) % ring->size;
+ frag_desc = ring->desc + i;
+ frag_info = ring->info + i;
+ memcpy(frag_info, hdr_info, sizeof(struct agnx_info));
+ frag_info->type = PACKET;
+ frag_info->dma_len = skb->len - hdr_info->dma_len;
+ frag_info->mapping = pci_map_single(priv->pdev, skb->data + hdr_info->dma_len,
+ frag_info->dma_len, PCI_DMA_TODEVICE);
+ do {
+ u32 frag = 0;
+ frag |= agnx_set_bits(FIRST_FRAG, FIRST_FRAG_SHIFT, 0);
+ frag |= agnx_set_bits(LAST_FRAG, LAST_FRAG_SHIFT, 1);
+ frag |= agnx_set_bits(PACKET_LEN, PACKET_LEN_SHIFT, skb->len);
+ frag |= agnx_set_bits(SUB_FRAG_LEN, SUB_FRAG_LEN_SHIFT, frag_info->dma_len);
+ frag_desc->frag = cpu_to_be32(frag);
+ } while (0);
+ frag_desc->dma_addr = cpu_to_be32(frag_info->mapping);
+
+ txm_power_set(priv, txi);
+
+/* do { */
+/* int j; */
+/* size_t len; */
+/* len = skb->len - hdr_info->dma_len + hdr_info->hdr_len; */
+/* // if (len == 614) { */
+/* agnx_print_desc(hdr_desc); */
+/* agnx_print_desc(frag_desc); */
+/* agnx_print_tx_hdr((struct agnx_hdr *)skb->data); */
+/* agnx_print_sta_power(priv, LOCAL_STAID); */
+/* agnx_print_sta(priv, LOCAL_STAID); */
+/* for (j = 0; j < 8; j++) */
+/* agnx_print_sta_tx_wq(priv, LOCAL_STAID, j); */
+/* agnx_print_sta_power(priv, BSSID_STAID); */
+/* agnx_print_sta(priv, BSSID_STAID); */
+/* for (j = 0; j < 8; j++) */
+/* agnx_print_sta_tx_wq(priv, BSSID_STAID, j); */
+/* // } */
+/* } while (0); */
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* FIXME ugly code */
+ /* Trigger TXM */
+ do {
+ u32 reg;
+ reg = (ioread32(priv->ctl + AGNX_CIR_TXMCTL));
+ reg |= 0x8;
+ iowrite32((reg), priv->ctl + AGNX_CIR_TXMCTL);
+ }while (0);
+
+ /* Trigger TXD */
+ do {
+ u32 reg;
+ reg = (ioread32(priv->ctl + AGNX_CIR_TXDCTL));
+ reg |= 0x8;
+ iowrite32((reg), priv->ctl + AGNX_CIR_TXDCTL);
+ }while (0);
+
+ return 0;
+}
+
+int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb)
+{
+ u16 fctl;
+
+ if (tx_packet_check(skb))
+ return 0;
+
+/* print_hex_dump_bytes("agnx: TX_PACKET: ", DUMP_PREFIX_NONE, */
+/* skb->data, skb->len); */
+
+ fctl = le16_to_cpu(*((__le16 *)skb->data));
+
+ if ( (fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA )
+ return __agnx_tx(priv, skb, &priv->txd);
+ else
+ return __agnx_tx(priv, skb, &priv->txm);
+}
diff --git a/drivers/staging/agnx/xmit.h b/drivers/staging/agnx/xmit.h
new file mode 100644
index 000000000000..93ac4157e697
--- /dev/null
+++ b/drivers/staging/agnx/xmit.h
@@ -0,0 +1,250 @@
+#ifndef AGNX_XMIT_H_
+#define AGNX_XMIT_H_
+
+#include <net/mac80211.h>
+
+struct agnx_priv;
+
+static inline u32 agnx_set_bits(u32 mask, u8 shift, u32 value)
+{
+ return (value << shift) & mask;
+}
+
+static inline u32 agnx_get_bits(u32 mask, u8 shift, u32 value)
+{
+ return (value & mask) >> shift;
+}
+
+
+struct agnx_rx {
+ __be16 rx_packet_duration; /* RX Packet Duration */
+ __be16 replay_cnt; /* Replay Count */
+} __attribute__((__packed__));
+
+
+struct agnx_tx {
+ u8 long_retry_limit; /* Long Retry Limit */
+ u8 short_retry_limit; /* Short Retry Limit */
+ u8 long_retry_cnt; /* Long Retry Count */
+ u8 short_retry_cnt; /* Short Retry Count */
+} __attribute__((__packed__));
+
+
+/* Copy from bcm43xx */
+#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
+#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
+#define PAD_BYTES(nr_bytes) P4D_BYTES(__LINE__, nr_bytes)
+
+#define P4D_BIT3S(magic, nr_bits) __be32 __padding##magic:nr_bits
+#define P4D_BITS(line, nr_bits) P4D_BIT3S(line, nr_bits)
+#define PAD_BITS(nr_bits) P4D_BITS(__LINE__, nr_bits)
+
+
+struct agnx_hdr {
+ __be32 reg0;
+#define RTS 0x80000000 /* RTS */
+#define RTS_SHIFT 31
+#define MULTICAST 0x40000000 /* multicast */
+#define MULTICAST_SHIFT 30
+#define ACK 0x30000000 /* ACK */
+#define ACK_SHIFT 28
+#define TM 0x08000000 /* TM */
+#define TM_SHIFT 27
+#define RELAY 0x04000000 /* Relay */
+#define RELAY_SHIFT 26
+/* PAD_BITS(4); */
+#define REVISED_FCS 0x00380000 /* revised FCS */
+#define REVISED_FCS_SHIFT 19
+#define NEXT_BUFFER_ADDR 0x0007FFFF /* Next Buffer Address */
+#define NEXT_BUFFER_ADDR_SHIFT 0
+
+ __be32 reg1;
+#define MAC_HDR_LEN 0xFC000000 /* MAC Header Length */
+#define MAC_HDR_LEN_SHIFT 26
+#define DURATION_OVERIDE 0x02000000 /* Duration Override */
+#define DURATION_OVERIDE_SHIFT 25
+#define PHY_HDR_OVERIDE 0x01000000 /* PHY Header Override */
+#define PHY_HDR_OVERIDE_SHIFT 24
+#define CRC_FAIL 0x00800000 /* CRC fail */
+#define CRC_FAIL_SHIFT 23
+/* PAD_BITS(1); */
+#define SEQUENCE_NUMBER 0x00200000 /* Sequence Number */
+#define SEQUENCE_NUMBER_SHIFT 21
+/* PAD_BITS(2); */
+#define BUFF_HEAD_ADDR 0x0007FFFF /* Buffer Head Address */
+#define BUFF_HEAD_ADDR_SHIFT 0
+
+ __be32 reg2;
+#define PDU_COUNT 0xFC000000 /* PDU Count */
+#define PDU_COUNT_SHIFT 26
+/* PAD_BITS(3); */
+#define WEP_KEY 0x00600000 /* WEP Key # */
+#define WEP_KEY_SHIFT 21
+#define USES_WEP_KEY 0x00100000 /* Uses WEP Key */
+#define USES_WEP_KEY_SHIFT 20
+#define KEEP_ALIVE 0x00080000 /* Keep alive */
+#define KEEP_ALIVE_SHIFT 19
+#define BUFF_TAIL_ADDR 0x0007FFFF /* Buffer Tail Address */
+#define BUFF_TAIL_ADDR_SHIFT 0
+
+ __be32 reg3;
+#define CTS_11G 0x80000000 /* CTS in 11g */
+#define CTS_11G_SHIFT 31
+#define RTS_11G 0x40000000 /* RTS in 11g */
+#define RTS_11G_SHIFT 30
+/* PAD_BITS(2); */
+#define FRAG_SIZE 0x0FFF0000 /* fragment size */
+#define FRAG_SIZE_SHIFT 16
+#define PAYLOAD_LEN 0x0000FFF0 /* payload length */
+#define PAYLOAD_LEN_SHIFT 4
+#define FRAG_NUM 0x0000000F /* number of frags */
+#define FRAG_NUM_SHIFT 0
+
+ __be32 reg4;
+/* PAD_BITS(4); */
+#define RELAY_STAID 0x0FFF0000 /* relayStald */
+#define RELAY_STAID_SHIFT 16
+#define STATION_ID 0x0000FFF0 /* Station ID */
+#define STATION_ID_SHIFT 4
+#define WORKQUEUE_ID 0x0000000F /* Workqueue ID */
+#define WORKQUEUE_ID_SHIFT 0
+
+ /* FIXME this register maybe is LE? */
+ __be32 reg5;
+/* PAD_BITS(4); */
+#define ROUTE_HOST 0x0F000000
+#define ROUTE_HOST_SHIFT 24
+#define ROUTE_CARD_CPU 0x00F00000
+#define ROUTE_CARD_CPU_SHIFT 20
+#define ROUTE_ENCRYPTION 0x000F0000
+#define ROUTE_ENCRYPTION_SHIFT 16
+#define ROUTE_TX 0x0000F000
+#define ROUTE_TX_SHIFT 12
+#define ROUTE_RX1 0x00000F00
+#define ROUTE_RX1_SHIFT 8
+#define ROUTE_RX2 0x000000F0
+#define ROUTE_RX2_SHIFT 4
+#define ROUTE_COMPRESSION 0x0000000F
+#define ROUTE_COMPRESSION_SHIFT 0
+
+ __be32 _11g0; /* 11g */
+ __be32 _11g1; /* 11g */
+ __be32 _11b0; /* 11b */
+ __be32 _11b1; /* 11b */
+ u8 mac_hdr[32]; /* MAC header */
+
+ __be16 rts_duration; /* RTS duration */
+ __be16 last_duration; /* Last duration */
+ __be16 sec_last_duration; /* Second to Last duration */
+ __be16 other_duration; /* Other duration */
+ __be16 tx_last_duration; /* TX Last duration */
+ __be16 tx_other_duration; /* TX Other Duration */
+ __be16 last_11g_len; /* Length of last 11g */
+ __be16 other_11g_len; /* Lenght of other 11g */
+
+ __be16 last_11b_len; /* Length of last 11b */
+ __be16 other_11b_len; /* Lenght of other 11b */
+
+
+ __be16 reg6;
+#define MBF 0xF000 /* mbf */
+#define MBF_SHIFT 12
+#define RSVD4 0x0FFF /* rsvd4 */
+#define RSVD4_SHIFT 0
+
+ __be16 rx_frag_stat; /* RX fragmentation status */
+
+ __be32 time_stamp; /* TimeStamp */
+ __be32 phy_stats_hi; /* PHY stats hi */
+ __be32 phy_stats_lo; /* PHY stats lo */
+ __be32 mic_key0; /* MIC key 0 */
+ __be32 mic_key1; /* MIC key 1 */
+
+ union { /* RX/TX Union */
+ struct agnx_rx rx;
+ struct agnx_tx tx;
+ };
+
+ u8 rx_channel; /* Recieve Channel */
+ PAD_BYTES(3);
+
+ u8 reserved[4];
+} __attribute__((__packed__));
+
+
+struct agnx_desc {
+#define PACKET_LEN 0xFFF00000
+#define PACKET_LEN_SHIFT 20
+/* ------------------------------------------------ */
+#define FIRST_PACKET_MASK 0x00080000
+#define FIRST_PACKET_MASK_SHIFT 19
+#define FIRST_RESERV2 0x00040000
+#define FIRST_RESERV2_SHIFT 18
+#define FIRST_TKIP_ERROR 0x00020000
+#define FIRST_TKIP_ERROR_SHIFT 17
+#define FIRST_TKIP_PACKET 0x00010000
+#define FIRST_TKIP_PACKET_SHIFT 16
+#define FIRST_RESERV1 0x0000F000
+#define FIRST_RESERV1_SHIFT 12
+#define FIRST_FRAG_LEN 0x00000FF8
+#define FIRST_FRAG_LEN_SHIFT 3
+/* ------------------------------------------------ */
+#define SUB_RESERV2 0x000c0000
+#define SUB_RESERV2_SHIFT 18
+#define SUB_TKIP_ERROR 0x00020000
+#define SUB_TKIP_ERROR_SHIFT 17
+#define SUB_TKIP_PACKET 0x00010000
+#define SUB_TKIP_PACKET_SHIFT 16
+#define SUB_RESERV1 0x00008000
+#define SUB_RESERV1_SHIFT 15
+#define SUB_FRAG_LEN 0x00007FF8
+#define SUB_FRAG_LEN_SHIFT 3
+/* ------------------------------------------------ */
+#define FIRST_FRAG 0x00000004
+#define FIRST_FRAG_SHIFT 2
+#define LAST_FRAG 0x00000002
+#define LAST_FRAG_SHIFT 1
+#define OWNER 0x00000001
+#define OWNER_SHIFT 0
+ __be32 frag;
+ __be32 dma_addr;
+} __attribute__((__packed__));
+
+enum {HEADER, PACKET};
+
+struct agnx_info {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+ u32 dma_len; /* dma buffer len */
+ /* Below fields only usful for tx */
+ u32 hdr_len; /* ieee80211 header length */
+ unsigned int type;
+ struct ieee80211_tx_info *txi;
+ struct ieee80211_hdr hdr;
+};
+
+
+struct agnx_ring {
+ struct agnx_desc *desc;
+ dma_addr_t dma;
+ struct agnx_info *info;
+ /* Will lead to overflow when sent packet number enough? */
+ unsigned int idx;
+ unsigned int idx_sent; /* only usful for txd and txm */
+ unsigned int size;
+};
+
+#define AGNX_RX_RING_SIZE 128
+#define AGNX_TXD_RING_SIZE 256
+#define AGNX_TXM_RING_SIZE 128
+
+void disable_rx_interrupt(struct agnx_priv *priv);
+void enable_rx_interrupt(struct agnx_priv *priv);
+int fill_rings(struct agnx_priv *priv);
+void unfill_rings(struct agnx_priv *priv);
+void handle_rx_irq(struct agnx_priv *priv);
+void handle_txd_irq(struct agnx_priv *priv);
+void handle_txm_irq(struct agnx_priv *priv);
+void handle_other_irq(struct agnx_priv *priv);
+int _agnx_tx(struct agnx_priv *priv, struct sk_buff *skb);
+#endif /* AGNX_XMIT_H_ */
diff --git a/drivers/staging/altpciechdma/Kconfig b/drivers/staging/altpciechdma/Kconfig
new file mode 100644
index 000000000000..0f4bf92cbbfb
--- /dev/null
+++ b/drivers/staging/altpciechdma/Kconfig
@@ -0,0 +1,10 @@
+config ALTERA_PCIE_CHDMA
+ tristate "Altera PCI Express Chaining DMA driver"
+ depends on PCI
+ default N
+ ---help---
+ A reference driver that exercises the Chaining DMA logic reference
+ design generated along the Altera FPGA PCI Express soft or hard core,
+ only if instantiated using the MegaWizard, not the SOPC builder, of
+ Quartus 8.1.
+
diff --git a/drivers/staging/altpciechdma/Makefile b/drivers/staging/altpciechdma/Makefile
new file mode 100644
index 000000000000..c08c8437f4db
--- /dev/null
+++ b/drivers/staging/altpciechdma/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma.o
+
diff --git a/drivers/staging/altpciechdma/TODO b/drivers/staging/altpciechdma/TODO
new file mode 100644
index 000000000000..12c945fd61e1
--- /dev/null
+++ b/drivers/staging/altpciechdma/TODO
@@ -0,0 +1,15 @@
+DONE:
+ - functionality similar to logic testbench
+
+TODO:
+ - checkpatch.pl cleanups.
+ - keep state of DMA engines.
+ - keep data structure that keeps state of each transfer.
+ - interrupt handler should iterate over outstanding descriptor tables.
+ - complete userspace cdev to read/write using the DMA engines.
+ - split off the DMA support functions in a module, re-usable by custom
+ drivers.
+
+Please coordinate work with, and send patches to
+Leon Woestenberg <leon@sidebranch.com>
+
diff --git a/drivers/staging/altpciechdma/altpciechdma.c b/drivers/staging/altpciechdma/altpciechdma.c
new file mode 100644
index 000000000000..f516140ca976
--- /dev/null
+++ b/drivers/staging/altpciechdma/altpciechdma.c
@@ -0,0 +1,1184 @@
+/**
+ * Driver for Altera PCIe core chaining DMA reference design.
+ *
+ * Copyright (C) 2008 Leon Woestenberg <leon.woestenberg@axon.tv>
+ * Copyright (C) 2008 Nickolas Heppermann <heppermannwdt@gmail.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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *
+ * Rationale: This driver exercises the chaining DMA read and write engine
+ * in the reference design. It is meant as a complementary reference
+ * driver that can be used for testing early designs as well as a basis to
+ * write your custom driver.
+ *
+ * Status: Test results from Leon Woestenberg <leon.woestenberg@axon.tv>:
+ *
+ * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
+ * Dell Precision 370 PC, x86, kernel 2.6.20 from Ubuntu 7.04.
+ *
+ * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
+ * Freescale MPC8313E-RDB board, PowerPC, 2.6.24 w/ Freescale patches.
+ *
+ * Driver tests passed with PCIe Compiler 8.1. With PCIe 8.0 the DMA
+ * loopback test had reproducable compare errors. I assume a change
+ * in the compiler or reference design, but could not find evidence nor
+ * documentation on a change or fix in that direction.
+ *
+ * The reference design does not have readable locations and thus a
+ * dummy read, used to flush PCI posted writes, cannot be performed.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+
+/* by default do not build the character device interface */
+/* XXX It is non-functional yet */
+#ifndef ALTPCIECHDMA_CDEV
+# define ALTPCIECHDMA_CDEV 0
+#endif
+
+/* build the character device interface? */
+#if ALTPCIECHDMA_CDEV
+# define MAX_CHDMA_SIZE (8 * 1024 * 1024)
+# include "mapper_user_to_sg.h"
+#endif
+
+/** driver name, mimicks Altera naming of the reference design */
+#define DRV_NAME "altpciechdma"
+/** number of BARs on the device */
+#define APE_BAR_NUM (6)
+/** BAR number where the RCSLAVE memory sits */
+#define APE_BAR_RCSLAVE (0)
+/** BAR number where the Descriptor Header sits */
+#define APE_BAR_HEADER (2)
+
+/** maximum size in bytes of the descriptor table, chdma logic limit */
+#define APE_CHDMA_TABLE_SIZE (4096)
+/* single transfer must not exceed 255 table entries. worst case this can be
+ * achieved by 255 scattered pages, with only a single byte in the head and
+ * tail pages. 253 * PAGE_SIZE is a safe upper bound for the transfer size.
+ */
+#define APE_CHDMA_MAX_TRANSFER_LEN (253 * PAGE_SIZE)
+
+/**
+ * Specifies those BARs to be mapped and the length of each mapping.
+ *
+ * Zero (0) means do not map, otherwise specifies the BAR lengths to be mapped.
+ * If the actual BAR length is less, this is considered an error; then
+ * reconfigure your PCIe core.
+ *
+ * @see ug_pci_express 8.0, table 7-2 at page 7-13.
+ */
+static const unsigned long bar_min_len[APE_BAR_NUM] =
+ { 32768, 0, 256, 0, 32768, 0 };
+
+/**
+ * Descriptor Header, controls the DMA read engine or write engine.
+ *
+ * The descriptor header is the main data structure for starting DMA transfers.
+ *
+ * It sits in End Point (FPGA) memory BAR[2] for 32-bit or BAR[3:2] for 64-bit.
+ * It references a descriptor table which exists in Root Complex (PC) memory.
+ * Writing the rclast field starts the DMA operation, thus all other structures
+ * and fields must be setup before doing so.
+ *
+ * @see ug_pci_express 8.0, tables 7-3, 7-4 and 7-5 at page 7-14.
+ * @note This header must be written in four 32-bit (PCI DWORD) writes.
+ */
+struct ape_chdma_header {
+ /**
+ * w0 consists of two 16-bit fields:
+ * lsb u16 number; number of descriptors in ape_chdma_table
+ * msb u16 control; global control flags
+ */
+ u32 w0;
+ /* bus address to ape_chdma_table in Root Complex memory */
+ u32 bdt_addr_h;
+ u32 bdt_addr_l;
+ /**
+ * w3 consists of two 16-bit fields:
+ * - lsb u16 rclast; last descriptor number available in Root Complex
+ * - zero (0) means the first descriptor is ready,
+ * - one (1) means two descriptors are ready, etc.
+ * - msb u16 reserved;
+ *
+ * @note writing to this memory location starts the DMA operation!
+ */
+ u32 w3;
+} __attribute__ ((packed));
+
+/**
+ * Descriptor Entry, describing a (non-scattered) single memory block transfer.
+ *
+ * There is one descriptor for each memory block involved in the transfer, a
+ * block being a contiguous address range on the bus.
+ *
+ * Multiple descriptors are chained by means of the ape_chdma_table data
+ * structure.
+ *
+ * @see ug_pci_express 8.0, tables 7-6, 7-7 and 7-8 at page 7-14 and page 7-15.
+ */
+struct ape_chdma_desc {
+ /**
+ * w0 consists of two 16-bit fields:
+ * number of DWORDS to transfer
+ * - lsb u16 length;
+ * global control
+ * - msb u16 control;
+ */
+ u32 w0;
+ /* address of memory in the End Point */
+ u32 ep_addr;
+ /* bus address of source or destination memory in the Root Complex */
+ u32 rc_addr_h;
+ u32 rc_addr_l;
+} __attribute__ ((packed));
+
+/**
+ * Descriptor Table, an array of descriptors describing a chained transfer.
+ *
+ * An array of descriptors, preceded by workspace for the End Point.
+ * It exists in Root Complex memory.
+ *
+ * The End Point can update its last completed descriptor number in the
+ * eplast field if requested by setting the EPLAST_ENA bit either
+ * globally in the header's or locally in any descriptor's control field.
+ *
+ * @note this structure may not exceed 4096 bytes. This results in a
+ * maximum of 4096 / (4 * 4) - 1 = 255 descriptors per chained transfer.
+ *
+ * @see ug_pci_express 8.0, tables 7-9, 7-10 and 7-11 at page 7-17 and page 7-18.
+ */
+struct ape_chdma_table {
+ /* workspace 0x00-0x0b, reserved */
+ u32 reserved1[3];
+ /* workspace 0x0c-0x0f, last descriptor handled by End Point */
+ u32 w3;
+ /* the actual array of descriptors
+ * 0x10-0x1f, 0x20-0x2f, ... 0xff0-0xfff (255 entries)
+ */
+ struct ape_chdma_desc desc[255];
+} __attribute__ ((packed));
+
+/**
+ * Altera PCI Express ('ape') board specific book keeping data
+ *
+ * Keeps state of the PCIe core and the Chaining DMA controller
+ * application.
+ */
+struct ape_dev {
+ /** the kernel pci device data structure provided by probe() */
+ struct pci_dev *pci_dev;
+ /**
+ * kernel virtual address of the mapped BAR memory and IO regions of
+ * the End Point. Used by map_bars()/unmap_bars().
+ */
+ void * __iomem bar[APE_BAR_NUM];
+ /** kernel virtual address for Descriptor Table in Root Complex memory */
+ struct ape_chdma_table *table_virt;
+ /**
+ * bus address for the Descriptor Table in Root Complex memory, in
+ * CPU-native endianess
+ */
+ dma_addr_t table_bus;
+ /* if the device regions could not be allocated, assume and remember it
+ * is in use by another driver; this driver must not disable the device.
+ */
+ int in_use;
+ /* whether this driver enabled msi for the device */
+ int msi_enabled;
+ /* whether this driver could obtain the regions */
+ int got_regions;
+ /* irq line succesfully requested by this driver, -1 otherwise */
+ int irq_line;
+ /* board revision */
+ u8 revision;
+ /* interrupt count, incremented by the interrupt handler */
+ int irq_count;
+#if ALTPCIECHDMA_CDEV
+ /* character device */
+ dev_t cdevno;
+ struct cdev cdev;
+ /* user space scatter gather mapper */
+ struct sg_mapping_t *sgm;
+#endif
+};
+
+/**
+ * Using the subsystem vendor id and subsystem id, it is possible to
+ * distinguish between different cards bases around the same
+ * (third-party) logic core.
+ *
+ * Default Altera vendor and device ID's, and some (non-reserved)
+ * ID's are now used here that are used amongst the testers/developers.
+ */
+static const struct pci_device_id ids[] = {
+ { PCI_DEVICE(0x1172, 0xE001), },
+ { PCI_DEVICE(0x2071, 0x2071), },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, ids);
+
+#if ALTPCIECHDMA_CDEV
+/* prototypes for character device */
+static int sg_init(struct ape_dev *ape);
+static void sg_exit(struct ape_dev *ape);
+#endif
+
+/**
+ * altpciechdma_isr() - Interrupt handler
+ *
+ */
+static irqreturn_t altpciechdma_isr(int irq, void *dev_id)
+{
+ struct ape_dev *ape = (struct ape_dev *)dev_id;
+ if (!ape)
+ return IRQ_NONE;
+ ape->irq_count++;
+ return IRQ_HANDLED;
+}
+
+static int __devinit scan_bars(struct ape_dev *ape, struct pci_dev *dev)
+{
+ int i;
+ for (i = 0; i < APE_BAR_NUM; i++) {
+ unsigned long bar_start = pci_resource_start(dev, i);
+ if (bar_start) {
+ unsigned long bar_end = pci_resource_end(dev, i);
+ unsigned long bar_flags = pci_resource_flags(dev, i);
+ printk(KERN_DEBUG "BAR%d 0x%08lx-0x%08lx flags 0x%08lx\n",
+ i, bar_start, bar_end, bar_flags);
+ }
+ }
+ return 0;
+}
+
+/**
+ * Unmap the BAR regions that had been mapped earlier using map_bars()
+ */
+static void unmap_bars(struct ape_dev *ape, struct pci_dev *dev)
+{
+ int i;
+ for (i = 0; i < APE_BAR_NUM; i++) {
+ /* is this BAR mapped? */
+ if (ape->bar[i]) {
+ /* unmap BAR */
+ pci_iounmap(dev, ape->bar[i]);
+ ape->bar[i] = NULL;
+ }
+ }
+}
+
+/**
+ * Map the device memory regions into kernel virtual address space after
+ * verifying their sizes respect the minimum sizes needed, given by the
+ * bar_min_len[] array.
+ */
+static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
+{
+ int rc;
+ int i;
+ /* iterate through all the BARs */
+ for (i = 0; i < APE_BAR_NUM; i++) {
+ unsigned long bar_start = pci_resource_start(dev, i);
+ unsigned long bar_end = pci_resource_end(dev, i);
+ unsigned long bar_length = bar_end - bar_start + 1;
+ ape->bar[i] = NULL;
+ /* do not map, and skip, BARs with length 0 */
+ if (!bar_min_len[i])
+ continue;
+ /* do not map BARs with address 0 */
+ if (!bar_start || !bar_end) {
+ printk(KERN_DEBUG "BAR #%d is not present?!\n", i);
+ rc = -1;
+ goto fail;
+ }
+ bar_length = bar_end - bar_start + 1;
+ /* BAR length is less than driver requires? */
+ if (bar_length < bar_min_len[i]) {
+ printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
+ "requires at least %lu bytes\n", i, bar_length, bar_min_len[i]);
+ rc = -1;
+ goto fail;
+ }
+ /* map the device memory or IO region into kernel virtual
+ * address space */
+ ape->bar[i] = pci_iomap(dev, i, bar_min_len[i]);
+ if (!ape->bar[i]) {
+ printk(KERN_DEBUG "Could not map BAR #%d.\n", i);
+ rc = -1;
+ goto fail;
+ }
+ printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
+ ape->bar[i], bar_min_len[i], bar_length);
+ }
+ /* succesfully mapped all required BAR regions */
+ rc = 0;
+ goto success;
+fail:
+ /* unmap any BARs that we did map */
+ unmap_bars(ape, dev);
+success:
+ return rc;
+}
+
+#if 0 /* not yet implemented fully FIXME add opcode */
+static void __devinit rcslave_test(struct ape_dev *ape, struct pci_dev *dev)
+{
+ u32 *rcslave_mem = (u32 *)ape->bar[APE_BAR_RCSLAVE];
+ u32 result = 0;
+ /** this number is assumed to be different each time this test runs */
+ u32 seed = (u32)jiffies;
+ u32 value = seed;
+ int i;
+
+ /* write loop */
+ value = seed;
+ for (i = 1024; i < 32768 / 4 ; i++) {
+ printk(KERN_DEBUG "Writing 0x%08x to 0x%p.\n",
+ (u32)value, (void *)rcslave_mem + i);
+ iowrite32(value, rcslave_mem + i);
+ value++;
+ }
+ /* read-back loop */
+ value = seed;
+ for (i = 1024; i < 32768 / 4; i++) {
+ result = ioread32(rcslave_mem + i);
+ if (result != value) {
+ printk(KERN_DEBUG "Wrote 0x%08x to 0x%p, but read back 0x%08x.\n",
+ (u32)value, (void *)rcslave_mem + i, (u32)result);
+ break;
+ }
+ value++;
+ }
+}
+#endif
+
+/* obtain the 32 most significant (high) bits of a 32-bit or 64-bit address */
+#define pci_dma_h(addr) ((addr >> 16) >> 16)
+/* obtain the 32 least significant (low) bits of a 32-bit or 64-bit address */
+#define pci_dma_l(addr) (addr & 0xffffffffUL)
+
+/* ape_fill_chdma_desc() - Fill a Altera PCI Express Chaining DMA descriptor
+ *
+ * @desc pointer to descriptor to be filled
+ * @addr root complex address
+ * @ep_addr end point address
+ * @len number of bytes, must be a multiple of 4.
+ */
+static inline void ape_chdma_desc_set(struct ape_chdma_desc *desc, dma_addr_t addr, u32 ep_addr, int len)
+{
+ BUG_ON(len & 3);
+ desc->w0 = cpu_to_le32(len / 4);
+ desc->ep_addr = cpu_to_le32(ep_addr);
+ desc->rc_addr_h = cpu_to_le32(pci_dma_h(addr));
+ desc->rc_addr_l = cpu_to_le32(pci_dma_l(addr));
+}
+
+/*
+ * ape_sg_to_chdma_table() - Create a device descriptor table from a scatterlist.
+ *
+ * The scatterlist must have been mapped by pci_map_sg(sgm->sgl).
+ *
+ * @sgl scatterlist.
+ * @nents Number of entries in the scatterlist.
+ * @first Start index in the scatterlist sgm->sgl.
+ * @ep_addr End Point address for the scatter/gather transfer.
+ * @desc pointer to first descriptor
+ *
+ * Returns Number of entries in the table on success, -1 on error.
+ */
+static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first, struct ape_chdma_desc *desc, u32 ep_addr)
+{
+ int i = first, j = 0;
+ /* inspect first entry */
+ dma_addr_t addr = sg_dma_address(&sgl[i]);
+ unsigned int len = sg_dma_len(&sgl[i]);
+ /* contiguous block */
+ dma_addr_t cont_addr = addr;
+ unsigned int cont_len = len;
+ /* iterate over remaining entries */
+ for (; j < 25 && i < nents - 1; i++) {
+ /* bus address of next entry i + 1 */
+ dma_addr_t next = sg_dma_address(&sgl[i + 1]);
+ /* length of this entry i */
+ len = sg_dma_len(&sgl[i]);
+ printk(KERN_DEBUG "%04d: addr=0x%08x length=0x%08x\n", i, addr, len);
+ /* entry i + 1 is non-contiguous with entry i? */
+ if (next != addr + len) {
+ /* TODO create entry here (we could overwrite i) */
+ printk(KERN_DEBUG "%4d: cont_addr=0x%08x cont_len=0x%08x\n", j, cont_addr, cont_len);
+ /* set descriptor for contiguous transfer */
+ ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len);
+ /* next end point memory address */
+ ep_addr += cont_len;
+ /* start new contiguous block */
+ cont_addr = next;
+ cont_len = 0;
+ j++;
+ }
+ /* add entry i + 1 to current contiguous block */
+ cont_len += len;
+ /* goto entry i + 1 */
+ addr = next;
+ }
+ /* TODO create entry here (we could overwrite i) */
+ printk(KERN_DEBUG "%04d: addr=0x%08x length=0x%08x\n", i, addr, len);
+ printk(KERN_DEBUG "%4d: cont_addr=0x%08x length=0x%08x\n", j, cont_addr, cont_len);
+ j++;
+ return j;
+}
+
+/* compare buffers */
+static inline int compare(u32 *p, u32 *q, int len)
+{
+ int result = -1;
+ int fail = 0;
+ int i;
+ for (i = 0; i < len / 4; i++) {
+ if (*p == *q) {
+ /* every so many u32 words, show equals */
+ if ((i & 255) == 0)
+ printk(KERN_DEBUG "[%p] = 0x%08x [%p] = 0x%08x\n", p, *p, q, *q);
+ } else {
+ fail++;
+ /* show the first few miscompares */
+ if (fail < 10) {
+ printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
+ /* but stop after a while */
+ } else if (fail == 10) {
+ printk(KERN_DEBUG "---more errors follow! not printed---\n");
+ } else {
+ /* stop compare after this many errors */
+ break;
+ }
+ }
+ p++;
+ q++;
+ }
+ if (!fail)
+ result = 0;
+ return result;
+}
+
+/* dma_test() - Perform DMA loop back test to end point and back to root complex.
+ *
+ * Allocate a cache-coherent buffer in host memory, consisting of four pages.
+ *
+ * Fill the four memory pages such that each 32-bit word contains its own address.
+ *
+ * Now perform a loop back test, have the end point device copy the first buffer
+ * half to end point memory, then have it copy back into the second half.
+ *
+ * Create a descriptor table to copy the first buffer half into End Point
+ * memory. Instruct the End Point to do a DMA read using that table.
+ *
+ * Create a descriptor table to copy End Point memory to the second buffer
+ * half. Instruct the End Point to do a DMA write using that table.
+ *
+ * Compare results, fail or pass.
+ *
+ */
+static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
+{
+ /* test result; guilty until proven innocent */
+ int result = -1;
+ /* the DMA read header sits at address 0x00 of the DMA engine BAR */
+ struct ape_chdma_header *write_header = (struct ape_chdma_header *)ape->bar[APE_BAR_HEADER];
+ /* the write DMA header sits after the read header at address 0x10 */
+ struct ape_chdma_header *read_header = write_header + 1;
+ /* virtual address of the allocated buffer */
+ u8 *buffer_virt = 0;
+ /* bus address of the allocated buffer */
+ dma_addr_t buffer_bus = 0;
+ int i, n = 0, irq_count;
+
+ /* temporary value used to construct 32-bit data words */
+ u32 w;
+
+ printk(KERN_DEBUG "bar_tests(), PAGE_SIZE = 0x%0x\n", (int)PAGE_SIZE);
+ printk(KERN_DEBUG "write_header = 0x%p.\n", write_header);
+ printk(KERN_DEBUG "read_header = 0x%p.\n", read_header);
+ printk(KERN_DEBUG "&write_header->w3 = 0x%p\n", &write_header->w3);
+ printk(KERN_DEBUG "&read_header->w3 = 0x%p\n", &read_header->w3);
+ printk(KERN_DEBUG "ape->table_virt = 0x%p.\n", ape->table_virt);
+
+ if (!write_header || !read_header || !ape->table_virt)
+ goto fail;
+
+ /* allocate and map coherently-cached memory for a DMA-able buffer */
+ /* @see Documentation/PCI/PCI-DMA-mapping.txt, near line 318 */
+ buffer_virt = (u8 *)pci_alloc_consistent(dev, PAGE_SIZE * 4, &buffer_bus);
+ if (!buffer_virt) {
+ printk(KERN_DEBUG "Could not allocate coherent DMA buffer.\n");
+ goto fail;
+ }
+ printk(KERN_DEBUG "Allocated cache-coherent DMA buffer (virtual address = 0x%016llx, bus address = 0x%016llx).\n",
+ (u64)buffer_virt, (u64)buffer_bus);
+
+ /* fill first half of buffer with its virtual address as data */
+ for (i = 0; i < 4 * PAGE_SIZE; i += 4)
+#if 0
+ *(u32 *)(buffer_virt + i) = i / PAGE_SIZE + 1;
+#else
+ *(u32 *)(buffer_virt + i) = (buffer_virt + i);
+#endif
+#if 0
+ compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
+#endif
+
+#if 0
+ /* fill second half of buffer with zeroes */
+ for (i = 2 * PAGE_SIZE; i < 4 * PAGE_SIZE; i += 4)
+ *(u32 *)(buffer_virt + i) = 0;
+#endif
+
+ /* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
+ ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
+
+ /* fill in first descriptor */
+ n = 0;
+ /* read 8192 bytes from RC buffer to EP address 4096 */
+ ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus, 4096, 2 * PAGE_SIZE);
+#if 1
+ for (i = 0; i < 255; i++) {
+ ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus, 4096, 2 * PAGE_SIZE);
+ }
+ /* index of last descriptor */
+ n = i - 1;
+#endif
+#if 0
+ /* fill in next descriptor */
+ n++;
+ /* read 1024 bytes from RC buffer to EP address 4096 + 1024 */
+ ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 1024, 4096 + 1024, 1024);
+#endif
+
+#if 1
+ /* enable MSI after the last descriptor is completed */
+ if (ape->msi_enabled)
+ ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
+#endif
+#if 0
+ /* dump descriptor table for debugging */
+ printk(KERN_DEBUG "Descriptor Table (Read, in Root Complex Memory, # = %d)\n", n + 1);
+ for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
+ u32 *p = (u32 *)ape->table_virt;
+ p += i;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
+ p++;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
+ p++;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
+ p++;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
+ }
+#endif
+ /* set available number of descriptors in table */
+ w = (u32)(n + 1);
+ w |= (1UL << 18)/*global EPLAST_EN*/;
+#if 0
+ if (ape->msi_enabled)
+ w |= (1UL << 17)/*global MSI*/;
+#endif
+ printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", w, (void *)&read_header->w0);
+ iowrite32(w, &read_header->w0);
+
+ /* write table address (higher 32-bits) */
+ printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)((ape->table_bus >> 16) >> 16), (void *)&read_header->bdt_addr_h);
+ iowrite32(pci_dma_h(ape->table_bus), &read_header->bdt_addr_h);
+
+ /* write table address (lower 32-bits) */
+ printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)(ape->table_bus & 0xffffffffUL), (void *)&read_header->bdt_addr_l);
+ iowrite32(pci_dma_l(ape->table_bus), &read_header->bdt_addr_l);
+
+ /* memory write barrier */
+ wmb();
+ printk(KERN_DEBUG "Flush posted writes\n");
+ /** FIXME Add dummy read to flush posted writes but need a readable location! */
+#if 0
+ (void)ioread32();
+#endif
+
+ /* remember IRQ count before the transfer */
+ irq_count = ape->irq_count;
+ /* write number of descriptors - this starts the DMA */
+ printk(KERN_DEBUG "\nStart DMA read\n");
+ printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)n, (void *)&read_header->w3);
+ iowrite32(n, &read_header->w3);
+ printk(KERN_DEBUG "EPLAST = %lu\n", le32_to_cpu(*(u32 *)&ape->table_virt->w3) & 0xffffUL);
+
+ /** memory write barrier */
+ wmb();
+ /* dummy read to flush posted writes */
+ /* FIXME Need a readable location! */
+#if 0
+ (void)ioread32();
+#endif
+ printk(KERN_DEBUG "POLL FOR READ:\n");
+ /* poll for chain completion, 1000 times 1 millisecond */
+ for (i = 0; i < 100; i++) {
+ volatile u32 *p = &ape->table_virt->w3;
+ u32 eplast = le32_to_cpu(*p) & 0xffffUL;
+ printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
+ if (eplast == n) {
+ printk(KERN_DEBUG "DONE\n");
+ /* print IRQ count before the transfer */
+ printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
+ break;
+ }
+ udelay(100);
+ }
+
+ /* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
+ ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
+
+ /* setup first descriptor */
+ n = 0;
+ ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
+#if 1
+ for (i = 0; i < 255; i++) {
+ ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
+ }
+ /* index of last descriptor */
+ n = i - 1;
+#endif
+#if 1 /* test variable, make a module option later */
+ if (ape->msi_enabled)
+ ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
+#endif
+#if 0
+ /* dump descriptor table for debugging */
+ printk(KERN_DEBUG "Descriptor Table (Write, in Root Complex Memory, # = %d)\n", n + 1);
+ for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
+ u32 *p = (u32 *)ape->table_virt;
+ p += i;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
+ p++;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
+ p++;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
+ p++;
+ printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
+ }
+#endif
+
+ /* set number of available descriptors in the table */
+ w = (u32)(n + 1);
+ /* enable updates of eplast for each descriptor completion */
+ w |= (u32)(1UL << 18)/*global EPLAST_EN*/;
+#if 0 // test variable, make a module option later
+ /* enable MSI for each descriptor completion */
+ if (ape->msi_enabled)
+ w |= (1UL << 17)/*global MSI*/;
+#endif
+ iowrite32(w, &write_header->w0);
+ iowrite32(pci_dma_h(ape->table_bus), &write_header->bdt_addr_h);
+ iowrite32(pci_dma_l(ape->table_bus), &write_header->bdt_addr_l);
+
+ /** memory write barrier and flush posted writes */
+ wmb();
+ /* dummy read to flush posted writes */
+ /* FIXME Need a readable location! */
+#if 0
+ (void)ioread32();
+#endif
+ irq_count = ape->irq_count;
+
+ printk(KERN_DEBUG "\nStart DMA write\n");
+ iowrite32(n, &write_header->w3);
+
+ /** memory write barrier */
+ wmb();
+ /** dummy read to flush posted writes */
+ //(void)ioread32();
+
+ printk(KERN_DEBUG "POLL FOR WRITE:\n");
+ /* poll for completion, 1000 times 1 millisecond */
+ for (i = 0; i < 100; i++) {
+ volatile u32 *p = &ape->table_virt->w3;
+ u32 eplast = le32_to_cpu(*p) & 0xffffUL;
+ printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
+ if (eplast == n) {
+ printk(KERN_DEBUG "DONE\n");
+ /* print IRQ count before the transfer */
+ printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
+ break;
+ }
+ udelay(100);
+ }
+ /* soft-reset DMA write engine */
+ iowrite32(0x0000ffffUL, &write_header->w0);
+ /* soft-reset DMA read engine */
+ iowrite32(0x0000ffffUL, &read_header->w0);
+
+ /** memory write barrier */
+ wmb();
+ /* dummy read to flush posted writes */
+ /* FIXME Need a readable location! */
+#if 0
+ (void)ioread32();
+#endif
+ /* compare first half of buffer with second half, should be identical */
+ result = compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
+ printk(KERN_DEBUG "DMA loop back test %s.\n", result ? "FAILED" : "PASSED");
+
+ pci_free_consistent(dev, 4 * PAGE_SIZE, buffer_virt, buffer_bus);
+fail:
+ printk(KERN_DEBUG "bar_tests() end, result %d\n", result);
+ return result;
+}
+
+/* Called when the PCI sub system thinks we can control the given device.
+ * Inspect if we can support the device and if so take control of it.
+ *
+ * Return 0 when we have taken control of the given device.
+ *
+ * - allocate board specific bookkeeping
+ * - allocate coherently-mapped memory for the descriptor table
+ * - enable the board
+ * - verify board revision
+ * - request regions
+ * - query DMA mask
+ * - obtain and request irq
+ * - map regions into kernel address space
+ */
+static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int rc = 0;
+ struct ape_dev *ape = NULL;
+ u8 irq_pin, irq_line;
+ printk(KERN_DEBUG "probe(dev = 0x%p, pciid = 0x%p)\n", dev, id);
+
+ /* allocate memory for per-board book keeping */
+ ape = kzalloc(sizeof(struct ape_dev), GFP_KERNEL);
+ if (!ape) {
+ printk(KERN_DEBUG "Could not kzalloc()ate memory.\n");
+ goto err_ape;
+ }
+ ape->pci_dev = dev;
+ dev->dev.driver_data = (void *)ape;
+ printk(KERN_DEBUG "probe() ape = 0x%p\n", ape);
+
+ printk(KERN_DEBUG "sizeof(struct ape_chdma_table) = %d.\n",
+ (int)sizeof(struct ape_chdma_table));
+ /* the reference design has a size restriction on the table size */
+ BUG_ON(sizeof(struct ape_chdma_table) > APE_CHDMA_TABLE_SIZE);
+
+ /* allocate and map coherently-cached memory for a descriptor table */
+ /* @see LDD3 page 446 */
+ ape->table_virt = (struct ape_chdma_table *)pci_alloc_consistent(dev,
+ APE_CHDMA_TABLE_SIZE, &ape->table_bus);
+ /* could not allocate table? */
+ if (!ape->table_virt) {
+ printk(KERN_DEBUG "Could not dma_alloc()ate_coherent memory.\n");
+ goto err_table;
+ }
+
+ printk(KERN_DEBUG "table_virt = 0x%16llx, table_bus = 0x%16llx.\n",
+ (u64)ape->table_virt, (u64)ape->table_bus);
+
+ /* enable device */
+ rc = pci_enable_device(dev);
+ if (rc) {
+ printk(KERN_DEBUG "pci_enable_device() failed\n");
+ goto err_enable;
+ }
+
+ /* enable bus master capability on device */
+ pci_set_master(dev);
+ /* enable message signaled interrupts */
+ rc = pci_enable_msi(dev);
+ /* could not use MSI? */
+ if (rc) {
+ /* resort to legacy interrupts */
+ printk(KERN_DEBUG "Could not enable MSI interrupting.\n");
+ ape->msi_enabled = 0;
+ /* MSI enabled, remember for cleanup */
+ } else {
+ printk(KERN_DEBUG "Enabled MSI interrupting.\n");
+ ape->msi_enabled = 1;
+ }
+
+ pci_read_config_byte(dev, PCI_REVISION_ID, &ape->revision);
+#if 0 /* example */
+ /* (for example) this driver does not support revision 0x42 */
+ if (ape->revision == 0x42) {
+ printk(KERN_DEBUG "Revision 0x42 is not supported by this driver.\n");
+ rc = -ENODEV;
+ goto err_rev;
+ }
+#endif
+ /** XXX check for native or legacy PCIe endpoint? */
+
+ rc = pci_request_regions(dev, DRV_NAME);
+ /* could not request all regions? */
+ if (rc) {
+ /* assume device is in use (and do not disable it later!) */
+ ape->in_use = 1;
+ goto err_regions;
+ }
+ ape->got_regions = 1;
+
+#if 1 // @todo For now, disable 64-bit, because I do not understand the implications (DAC!)
+ /* query for DMA transfer */
+ /* @see Documentation/PCI/PCI-DMA-mapping.txt */
+ if (!pci_set_dma_mask(dev, DMA_64BIT_MASK)) {
+ pci_set_consistent_dma_mask(dev, DMA_64BIT_MASK);
+ /* use 64-bit DMA */
+ printk(KERN_DEBUG "Using a 64-bit DMA mask.\n");
+ } else
+#endif
+ if (!pci_set_dma_mask(dev, DMA_32BIT_MASK)) {
+ printk(KERN_DEBUG "Could not set 64-bit DMA mask.\n");
+ pci_set_consistent_dma_mask(dev, DMA_32BIT_MASK);
+ /* use 32-bit DMA */
+ printk(KERN_DEBUG "Using a 32-bit DMA mask.\n");
+ } else {
+ printk(KERN_DEBUG "No suitable DMA possible.\n");
+ /** @todo Choose proper error return code */
+ rc = -1;
+ goto err_mask;
+ }
+
+ rc = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
+ /* could not read? */
+ if (rc)
+ goto err_irq;
+ printk(KERN_DEBUG "IRQ pin #%d (0=none, 1=INTA#...4=INTD#).\n", irq_pin);
+
+ /* @see LDD3, page 318 */
+ rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_line);
+ /* could not read? */
+ if (rc) {
+ printk(KERN_DEBUG "Could not query PCI_INTERRUPT_LINE, error %d\n", rc);
+ goto err_irq;
+ }
+ printk(KERN_DEBUG "IRQ line #%d.\n", irq_line);
+#if 1
+ irq_line = dev->irq;
+ /* @see LDD3, page 259 */
+ rc = request_irq(irq_line, altpciechdma_isr, IRQF_SHARED, DRV_NAME, (void *)ape);
+ if (rc) {
+ printk(KERN_DEBUG "Could not request IRQ #%d, error %d\n", irq_line, rc);
+ ape->irq_line = -1;
+ goto err_irq;
+ }
+ /* remember which irq we allocated */
+ ape->irq_line = (int)irq_line;
+ printk(KERN_DEBUG "Succesfully requested IRQ #%d with dev_id 0x%p\n", irq_line, ape);
+#endif
+ /* show BARs */
+ scan_bars(ape, dev);
+ /* map BARs */
+ rc = map_bars(ape, dev);
+ if (rc)
+ goto err_map;
+#if ALTPCIECHDMA_CDEV
+ /* initialize character device */
+ rc = sg_init(ape);
+ if (rc)
+ goto err_cdev;
+#endif
+ /* perform DMA engines loop back test */
+ rc = dma_test(ape, dev);
+ (void)rc;
+ /* succesfully took the device */
+ rc = 0;
+ printk(KERN_DEBUG "probe() successful.\n");
+ goto end;
+err_cdev:
+ /* unmap the BARs */
+ unmap_bars(ape, dev);
+err_map:
+ /* free allocated irq */
+ if (ape->irq_line >= 0)
+ free_irq(ape->irq_line, (void *)ape);
+err_irq:
+ if (ape->msi_enabled)
+ pci_disable_msi(dev);
+ /* disable the device iff it is not in use */
+ if (!ape->in_use)
+ pci_disable_device(dev);
+ if (ape->got_regions)
+ pci_release_regions(dev);
+err_mask:
+err_regions:
+err_rev:
+/* clean up everything before device enable() */
+err_enable:
+ if (ape->table_virt)
+ pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
+/* clean up everything before allocating descriptor table */
+err_table:
+ if (ape)
+ kfree(ape);
+err_ape:
+end:
+ return rc;
+}
+
+static void __devexit remove(struct pci_dev *dev)
+{
+ struct ape_dev *ape;
+ printk(KERN_DEBUG "remove(0x%p)\n", dev);
+ if ((dev == 0) || (dev->dev.driver_data == 0)) {
+ printk(KERN_DEBUG "remove(dev = 0x%p) dev->dev.driver_data = 0x%p\n", dev, dev->dev.driver_data);
+ return;
+ }
+ ape = (struct ape_dev *)dev->dev.driver_data;
+ printk(KERN_DEBUG "remove(dev = 0x%p) where dev->dev.driver_data = 0x%p\n", dev, ape);
+ if (ape->pci_dev != dev) {
+ printk(KERN_DEBUG "dev->dev.driver_data->pci_dev (0x%08lx) != dev (0x%08lx)\n",
+ (unsigned long)ape->pci_dev, (unsigned long)dev);
+ }
+ /* remove character device */
+#if ALTPCIECHDMA_CDEV
+ sg_exit(ape);
+#endif
+
+ if (ape->table_virt)
+ pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
+
+ /* free IRQ
+ * @see LDD3 page 279
+ */
+ if (ape->irq_line >= 0) {
+ printk(KERN_DEBUG "Freeing IRQ #%d for dev_id 0x%08lx.\n",
+ ape->irq_line, (unsigned long)ape);
+ free_irq(ape->irq_line, (void *)ape);
+ }
+ /* MSI was enabled? */
+ if (ape->msi_enabled) {
+ /* Disable MSI @see Documentation/MSI-HOWTO.txt */
+ pci_disable_msi(dev);
+ ape->msi_enabled = 0;
+ }
+ /* unmap the BARs */
+ unmap_bars(ape, dev);
+ if (!ape->in_use)
+ pci_disable_device(dev);
+ if (ape->got_regions)
+ /* to be called after device disable */
+ pci_release_regions(dev);
+}
+
+#if ALTPCIECHDMA_CDEV
+
+/*
+ * Called when the device goes from unused to used.
+ */
+static int sg_open(struct inode *inode, struct file *file)
+{
+ struct ape_dev *ape;
+ printk(KERN_DEBUG DRV_NAME "_open()\n");
+ /* pointer to containing data structure of the character device inode */
+ ape = container_of(inode->i_cdev, struct ape_dev, cdev);
+ /* create a reference to our device state in the opened file */
+ file->private_data = ape;
+ /* create virtual memory mapper */
+ ape->sgm = sg_create_mapper(MAX_CHDMA_SIZE);
+ return 0;
+}
+
+/*
+ * Called when the device goes from used to unused.
+ */
+static int sg_close(struct inode *inode, struct file *file)
+{
+ /* fetch device specific data stored earlier during open */
+ struct ape_dev *ape = (struct ape_dev *)file->private_data;
+ printk(KERN_DEBUG DRV_NAME "_close()\n");
+ /* destroy virtual memory mapper */
+ sg_destroy_mapper(ape->sgm);
+ return 0;
+}
+
+static ssize_t sg_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
+{
+ /* fetch device specific data stored earlier during open */
+ struct ape_dev *ape = (struct ape_dev *)file->private_data;
+ (void)ape;
+ printk(KERN_DEBUG DRV_NAME "_read(buf=0x%p, count=%lld, pos=%llu)\n", buf, (s64)count, (u64)*pos);
+ return count;
+}
+
+/* sg_write() - Write to the device
+ *
+ * @buf userspace buffer
+ * @count number of bytes in the userspace buffer
+ *
+ * Iterate over the userspace buffer, taking at most 255 * PAGE_SIZE bytes for
+ * each DMA transfer.
+ * For each transfer, get the user pages, build a sglist, map, build a
+ * descriptor table. submit the transfer. wait for the interrupt handler
+ * to wake us on completion.
+ */
+static ssize_t sg_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
+{
+ int hwnents, tents;
+ size_t transfer_len, remaining = count, done = 0;
+ u64 transfer_addr = (u64)buf;
+ /* fetch device specific data stored earlier during open */
+ struct ape_dev *ape = (struct ape_dev *)file->private_data;
+ printk(KERN_DEBUG DRV_NAME "_write(buf=0x%p, count=%lld, pos=%llu)\n",
+ buf, (s64)count, (u64)*pos);
+ /* TODO transfer boundaries at PAGE_SIZE granularity */
+ while (remaining > 0)
+ {
+ /* limit DMA transfer size */
+ transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN)? remaining:
+ APE_CHDMA_MAX_TRANSFER_LEN;
+ /* get all user space buffer pages and create a scattergather list */
+ sgm_map_user_pages(ape->sgm, transfer_addr, transfer_len, 0/*read from userspace*/);
+ printk(KERN_DEBUG DRV_NAME "mapped_pages=%d\n", ape->sgm->mapped_pages);
+ /* map all entries in the scattergather list */
+ hwnents = pci_map_sg(ape->pci_dev, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
+ printk(KERN_DEBUG DRV_NAME "hwnents=%d\n", hwnents);
+ /* build device descriptor tables and submit them to the DMA engine */
+ tents = ape_sg_to_chdma_table(ape->sgm->sgl, hwnents, 0, &ape->table_virt->desc[0], 4096);
+ printk(KERN_DEBUG DRV_NAME "tents=%d\n", hwnents);
+#if 0
+ while (tables) {
+ /* TODO build table */
+ /* TODO submit table to the device */
+ /* if engine stopped and unfinished work then start engine */
+ }
+ put ourselves on wait queue
+#endif
+
+ dma_unmap_sg(NULL, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
+ /* dirty and free the pages */
+ sgm_unmap_user_pages(ape->sgm, 1/*dirtied*/);
+ /* book keeping */
+ transfer_addr += transfer_len;
+ remaining -= transfer_len;
+ done += transfer_len;
+ }
+ return done;
+}
+
+/*
+ * character device file operations
+ */
+static struct file_operations sg_fops = {
+ .owner = THIS_MODULE,
+ .open = sg_open,
+ .release = sg_close,
+ .read = sg_read,
+ .write = sg_write,
+};
+
+/* sg_init() - Initialize character device
+ *
+ * XXX Should ideally be tied to the device, on device probe, not module init.
+ */
+static int sg_init(struct ape_dev *ape)
+{
+ int rc;
+ printk(KERN_DEBUG DRV_NAME " sg_init()\n");
+ /* allocate a dynamically allocated character device node */
+ rc = alloc_chrdev_region(&ape->cdevno, 0/*requested minor*/, 1/*count*/, DRV_NAME);
+ /* allocation failed? */
+ if (rc < 0) {
+ printk("alloc_chrdev_region() = %d\n", rc);
+ goto fail_alloc;
+ }
+ /* couple the device file operations to the character device */
+ cdev_init(&ape->cdev, &sg_fops);
+ ape->cdev.owner = THIS_MODULE;
+ /* bring character device live */
+ rc = cdev_add(&ape->cdev, ape->cdevno, 1/*count*/);
+ if (rc < 0) {
+ printk("cdev_add() = %d\n", rc);
+ goto fail_add;
+ }
+ printk(KERN_DEBUG "altpciechdma = %d:%d\n", MAJOR(ape->cdevno), MINOR(ape->cdevno));
+ return 0;
+fail_add:
+ /* free the dynamically allocated character device node */
+ unregister_chrdev_region(ape->cdevno, 1/*count*/);
+fail_alloc:
+ return -1;
+}
+
+/* sg_exit() - Cleanup character device
+ *
+ * XXX Should ideally be tied to the device, on device remove, not module exit.
+ */
+
+static void sg_exit(struct ape_dev *ape)
+{
+ printk(KERN_DEBUG DRV_NAME " sg_exit()\n");
+ /* remove the character device */
+ cdev_del(&ape->cdev);
+ /* free the dynamically allocated character device node */
+ unregister_chrdev_region(ape->cdevno, 1/*count*/);
+}
+
+#endif /* ALTPCIECHDMA_CDEV */
+
+/* used to register the driver with the PCI kernel sub system
+ * @see LDD3 page 311
+ */
+static struct pci_driver pci_driver = {
+ .name = DRV_NAME,
+ .id_table = ids,
+ .probe = probe,
+ .remove = remove,
+ /* resume, suspend are optional */
+};
+
+/**
+ * alterapciechdma_init() - Module initialization, registers devices.
+ */
+static int __init alterapciechdma_init(void)
+{
+ int rc = 0;
+ printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n");
+ /* register this driver with the PCI bus driver */
+ rc = pci_register_driver(&pci_driver);
+ if (rc < 0)
+ return rc;
+ return 0;
+}
+
+/**
+ * alterapciechdma_init() - Module cleanup, unregisters devices.
+ */
+static void __exit alterapciechdma_exit(void)
+{
+ printk(KERN_DEBUG DRV_NAME " exit(), built at " __DATE__ " " __TIME__ "\n");
+ /* unregister this driver from the PCI bus driver */
+ pci_unregister_driver(&pci_driver);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(alterapciechdma_init);
+module_exit(alterapciechdma_exit);
+
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
new file mode 100644
index 000000000000..6b996db0dd6a
--- /dev/null
+++ b/drivers/staging/android/Kconfig
@@ -0,0 +1,86 @@
+menu "Android"
+
+config ANDROID
+ bool "Android Drivers"
+ default N
+ ---help---
+ Enable support for various drivers needed on the Android platform
+
+config ANDROID_BINDER_IPC
+ bool "Android Binder IPC Driver"
+ default n
+
+config ANDROID_LOGGER
+ tristate "Android log driver"
+ default n
+
+config ANDROID_RAM_CONSOLE
+ bool "Android RAM buffer console"
+ default n
+
+config ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
+ bool "Enable verbose console messages on Android RAM console"
+ default y
+ depends on ANDROID_RAM_CONSOLE
+
+menuconfig ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ bool "Android RAM Console Enable error correction"
+ default n
+ depends on ANDROID_RAM_CONSOLE
+ select REED_SOLOMON
+ select REED_SOLOMON_ENC8
+ select REED_SOLOMON_DEC8
+
+if ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE
+ int "Android RAM Console Data data size"
+ default 128
+ help
+ Must be a power of 2.
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE
+ int "Android RAM Console ECC size"
+ default 16
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE
+ int "Android RAM Console Symbol size"
+ default 8
+
+config ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL
+ hex "Android RAM Console Polynomial"
+ default 0x19 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 4)
+ default 0x29 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 5)
+ default 0x61 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 6)
+ default 0x89 if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 7)
+ default 0x11d if (ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE = 8)
+
+endif # ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+
+config ANDROID_RAM_CONSOLE_EARLY_INIT
+ bool "Start Android RAM console early"
+ default n
+ depends on ANDROID_RAM_CONSOLE
+
+config ANDROID_RAM_CONSOLE_EARLY_ADDR
+ hex "Android RAM console virtual address"
+ default 0
+ depends on ANDROID_RAM_CONSOLE_EARLY_INIT
+
+config ANDROID_RAM_CONSOLE_EARLY_SIZE
+ hex "Android RAM console buffer size"
+ default 0
+ depends on ANDROID_RAM_CONSOLE_EARLY_INIT
+
+config ANDROID_TIMED_GPIO
+ tristate "Android timed gpio driver"
+ depends on GENERIC_GPIO
+ default n
+
+config ANDROID_LOW_MEMORY_KILLER
+ bool "Android Low Memory Killer"
+ default N
+ ---help---
+ Register processes to be killed when memory is low
+
+endmenu
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
new file mode 100644
index 000000000000..95209d6273a1
--- /dev/null
+++ b/drivers/staging/android/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
+obj-$(CONFIG_ANDROID_LOGGER) += logger.o
+obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
+obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
+obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO
new file mode 100644
index 000000000000..e59c5be4be2b
--- /dev/null
+++ b/drivers/staging/android/TODO
@@ -0,0 +1,10 @@
+TODO:
+ - checkpatch.pl cleanups
+ - sparse fixes
+ - rename files to be not so "generic"
+ - make sure things build as modules properly
+ - add proper arch dependancies as needed
+ - audit userspace interfaces to make sure they are sane
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
+Brian Swetland <swetland@google.com>
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
new file mode 100644
index 000000000000..758131cad08a
--- /dev/null
+++ b/drivers/staging/android/binder.c
@@ -0,0 +1,3503 @@
+/* binder.c
+ *
+ * Android IPC Subsystem
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/nsproxy.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/rbtree.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include "binder.h"
+
+static DEFINE_MUTEX(binder_lock);
+static HLIST_HEAD(binder_procs);
+static struct binder_node *binder_context_mgr_node;
+static uid_t binder_context_mgr_uid = -1;
+static int binder_last_id;
+static struct proc_dir_entry *binder_proc_dir_entry_root;
+static struct proc_dir_entry *binder_proc_dir_entry_proc;
+static struct hlist_head binder_dead_nodes;
+
+static int binder_read_proc_proc(
+ char *page, char **start, off_t off, int count, int *eof, void *data);
+
+/* This is only defined in include/asm-arm/sizes.h */
+#ifndef SZ_1K
+#define SZ_1K 0x400
+#endif
+
+#ifndef SZ_4M
+#define SZ_4M 0x400000
+#endif
+
+#ifndef __i386__
+#define FORBIDDEN_MMAP_FLAGS (VM_WRITE | VM_EXEC)
+#else
+#define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
+#endif
+
+#define BINDER_SMALL_BUF_SIZE (PAGE_SIZE * 64)
+
+enum {
+ BINDER_DEBUG_USER_ERROR = 1U << 0,
+ BINDER_DEBUG_FAILED_TRANSACTION = 1U << 1,
+ BINDER_DEBUG_DEAD_TRANSACTION = 1U << 2,
+ BINDER_DEBUG_OPEN_CLOSE = 1U << 3,
+ BINDER_DEBUG_DEAD_BINDER = 1U << 4,
+ BINDER_DEBUG_DEATH_NOTIFICATION = 1U << 5,
+ BINDER_DEBUG_READ_WRITE = 1U << 6,
+ BINDER_DEBUG_USER_REFS = 1U << 7,
+ BINDER_DEBUG_THREADS = 1U << 8,
+ BINDER_DEBUG_TRANSACTION = 1U << 9,
+ BINDER_DEBUG_TRANSACTION_COMPLETE = 1U << 10,
+ BINDER_DEBUG_FREE_BUFFER = 1U << 11,
+ BINDER_DEBUG_INTERNAL_REFS = 1U << 12,
+ BINDER_DEBUG_BUFFER_ALLOC = 1U << 13,
+ BINDER_DEBUG_PRIORITY_CAP = 1U << 14,
+ BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15,
+};
+static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
+ BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
+module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
+static int binder_debug_no_lock;
+module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
+static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
+static int binder_stop_on_user_error;
+static int binder_set_stop_on_user_error(
+ const char *val, struct kernel_param *kp)
+{
+ int ret;
+ ret = param_set_int(val, kp);
+ if (binder_stop_on_user_error < 2)
+ wake_up(&binder_user_error_wait);
+ return ret;
+}
+module_param_call(stop_on_user_error, binder_set_stop_on_user_error,
+ param_get_int, &binder_stop_on_user_error, S_IWUSR | S_IRUGO);
+
+#define binder_user_error(x...) \
+ do { \
+ if (binder_debug_mask & BINDER_DEBUG_USER_ERROR) \
+ printk(KERN_INFO x); \
+ if (binder_stop_on_user_error) \
+ binder_stop_on_user_error = 2; \
+ } while (0)
+
+enum {
+ BINDER_STAT_PROC,
+ BINDER_STAT_THREAD,
+ BINDER_STAT_NODE,
+ BINDER_STAT_REF,
+ BINDER_STAT_DEATH,
+ BINDER_STAT_TRANSACTION,
+ BINDER_STAT_TRANSACTION_COMPLETE,
+ BINDER_STAT_COUNT
+};
+
+struct binder_stats {
+ int br[_IOC_NR(BR_FAILED_REPLY) + 1];
+ int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1];
+ int obj_created[BINDER_STAT_COUNT];
+ int obj_deleted[BINDER_STAT_COUNT];
+};
+
+static struct binder_stats binder_stats;
+
+struct binder_transaction_log_entry {
+ int debug_id;
+ int call_type;
+ int from_proc;
+ int from_thread;
+ int target_handle;
+ int to_proc;
+ int to_thread;
+ int to_node;
+ int data_size;
+ int offsets_size;
+};
+struct binder_transaction_log {
+ int next;
+ int full;
+ struct binder_transaction_log_entry entry[32];
+};
+struct binder_transaction_log binder_transaction_log;
+struct binder_transaction_log binder_transaction_log_failed;
+
+static struct binder_transaction_log_entry *binder_transaction_log_add(
+ struct binder_transaction_log *log)
+{
+ struct binder_transaction_log_entry *e;
+ e = &log->entry[log->next];
+ memset(e, 0, sizeof(*e));
+ log->next++;
+ if (log->next == ARRAY_SIZE(log->entry)) {
+ log->next = 0;
+ log->full = 1;
+ }
+ return e;
+}
+
+struct binder_work {
+ struct list_head entry;
+ enum {
+ BINDER_WORK_TRANSACTION = 1,
+ BINDER_WORK_TRANSACTION_COMPLETE,
+ BINDER_WORK_NODE,
+ BINDER_WORK_DEAD_BINDER,
+ BINDER_WORK_DEAD_BINDER_AND_CLEAR,
+ BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
+ } type;
+};
+
+struct binder_node {
+ int debug_id;
+ struct binder_work work;
+ union {
+ struct rb_node rb_node;
+ struct hlist_node dead_node;
+ };
+ struct binder_proc *proc;
+ struct hlist_head refs;
+ int internal_strong_refs;
+ int local_weak_refs;
+ int local_strong_refs;
+ void __user *ptr;
+ void __user *cookie;
+ unsigned has_strong_ref : 1;
+ unsigned pending_strong_ref : 1;
+ unsigned has_weak_ref : 1;
+ unsigned pending_weak_ref : 1;
+ unsigned has_async_transaction : 1;
+ unsigned accept_fds : 1;
+ int min_priority : 8;
+ struct list_head async_todo;
+};
+
+struct binder_ref_death {
+ struct binder_work work;
+ void __user *cookie;
+};
+
+struct binder_ref {
+ /* Lookups needed: */
+ /* node + proc => ref (transaction) */
+ /* desc + proc => ref (transaction, inc/dec ref) */
+ /* node => refs + procs (proc exit) */
+ int debug_id;
+ struct rb_node rb_node_desc;
+ struct rb_node rb_node_node;
+ struct hlist_node node_entry;
+ struct binder_proc *proc;
+ struct binder_node *node;
+ uint32_t desc;
+ int strong;
+ int weak;
+ struct binder_ref_death *death;
+};
+
+struct binder_buffer {
+ struct list_head entry; /* free and allocated entries by addesss */
+ struct rb_node rb_node; /* free entry by size or allocated entry */
+ /* by address */
+ unsigned free : 1;
+ unsigned allow_user_free : 1;
+ unsigned async_transaction : 1;
+ unsigned debug_id : 29;
+
+ struct binder_transaction *transaction;
+
+ struct binder_node *target_node;
+ size_t data_size;
+ size_t offsets_size;
+ uint8_t data[0];
+};
+
+struct binder_proc {
+ struct hlist_node proc_node;
+ struct rb_root threads;
+ struct rb_root nodes;
+ struct rb_root refs_by_desc;
+ struct rb_root refs_by_node;
+ int pid;
+ struct vm_area_struct *vma;
+ struct task_struct *tsk;
+ void *buffer;
+ size_t user_buffer_offset;
+
+ struct list_head buffers;
+ struct rb_root free_buffers;
+ struct rb_root allocated_buffers;
+ size_t free_async_space;
+
+ struct page **pages;
+ size_t buffer_size;
+ uint32_t buffer_free;
+ struct list_head todo;
+ wait_queue_head_t wait;
+ struct binder_stats stats;
+ struct list_head delivered_death;
+ int max_threads;
+ int requested_threads;
+ int requested_threads_started;
+ int ready_threads;
+ long default_priority;
+};
+
+enum {
+ BINDER_LOOPER_STATE_REGISTERED = 0x01,
+ BINDER_LOOPER_STATE_ENTERED = 0x02,
+ BINDER_LOOPER_STATE_EXITED = 0x04,
+ BINDER_LOOPER_STATE_INVALID = 0x08,
+ BINDER_LOOPER_STATE_WAITING = 0x10,
+ BINDER_LOOPER_STATE_NEED_RETURN = 0x20
+};
+
+struct binder_thread {
+ struct binder_proc *proc;
+ struct rb_node rb_node;
+ int pid;
+ int looper;
+ struct binder_transaction *transaction_stack;
+ struct list_head todo;
+ uint32_t return_error; /* Write failed, return error code in read buf */
+ uint32_t return_error2; /* Write failed, return error code in read */
+ /* buffer. Used when sending a reply to a dead process that */
+ /* we are also waiting on */
+ wait_queue_head_t wait;
+ struct binder_stats stats;
+};
+
+struct binder_transaction {
+ int debug_id;
+ struct binder_work work;
+ struct binder_thread *from;
+ struct binder_transaction *from_parent;
+ struct binder_proc *to_proc;
+ struct binder_thread *to_thread;
+ struct binder_transaction *to_parent;
+ unsigned need_reply : 1;
+ /*unsigned is_dead : 1;*/ /* not used at the moment */
+
+ struct binder_buffer *buffer;
+ unsigned int code;
+ unsigned int flags;
+ long priority;
+ long saved_priority;
+ uid_t sender_euid;
+};
+
+/*
+ * copied from get_unused_fd_flags
+ */
+int task_get_unused_fd_flags(struct task_struct *tsk, int flags)
+{
+ struct files_struct *files = get_files_struct(tsk);
+ int fd, error;
+ struct fdtable *fdt;
+ unsigned long rlim_cur;
+ unsigned long irqs;
+
+ if (files == NULL)
+ return -ESRCH;
+
+ error = -EMFILE;
+ spin_lock(&files->file_lock);
+
+repeat:
+ fdt = files_fdtable(files);
+ fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds,
+ files->next_fd);
+
+ /*
+ * N.B. For clone tasks sharing a files structure, this test
+ * will limit the total number of files that can be opened.
+ */
+ rlim_cur = 0;
+ if (lock_task_sighand(tsk, &irqs)) {
+ rlim_cur = tsk->signal->rlim[RLIMIT_NOFILE].rlim_cur;
+ unlock_task_sighand(tsk, &irqs);
+ }
+ if (fd >= rlim_cur)
+ goto out;
+
+ /* Do we need to expand the fd array or fd set? */
+ error = expand_files(files, fd);
+ if (error < 0)
+ goto out;
+
+ if (error) {
+ /*
+ * If we needed to expand the fs array we
+ * might have blocked - try again.
+ */
+ error = -EMFILE;
+ goto repeat;
+ }
+
+ FD_SET(fd, fdt->open_fds);
+ if (flags & O_CLOEXEC)
+ FD_SET(fd, fdt->close_on_exec);
+ else
+ FD_CLR(fd, fdt->close_on_exec);
+ files->next_fd = fd + 1;
+#if 1
+ /* Sanity check */
+ if (fdt->fd[fd] != NULL) {
+ printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
+ fdt->fd[fd] = NULL;
+ }
+#endif
+ error = fd;
+
+out:
+ spin_unlock(&files->file_lock);
+ put_files_struct(files);
+ return error;
+}
+
+/*
+ * copied from fd_install
+ */
+static void task_fd_install(
+ struct task_struct *tsk, unsigned int fd, struct file *file)
+{
+ struct files_struct *files = get_files_struct(tsk);
+ struct fdtable *fdt;
+
+ if (files == NULL)
+ return;
+
+ spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
+ BUG_ON(fdt->fd[fd] != NULL);
+ rcu_assign_pointer(fdt->fd[fd], file);
+ spin_unlock(&files->file_lock);
+ put_files_struct(files);
+}
+
+/*
+ * copied from __put_unused_fd in open.c
+ */
+static void __put_unused_fd(struct files_struct *files, unsigned int fd)
+{
+ struct fdtable *fdt = files_fdtable(files);
+ __FD_CLR(fd, fdt->open_fds);
+ if (fd < files->next_fd)
+ files->next_fd = fd;
+}
+
+/*
+ * copied from sys_close
+ */
+static long task_close_fd(struct task_struct *tsk, unsigned int fd)
+{
+ struct file *filp;
+ struct files_struct *files = get_files_struct(tsk);
+ struct fdtable *fdt;
+ int retval;
+
+ if (files == NULL)
+ return -ESRCH;
+
+ spin_lock(&files->file_lock);
+ fdt = files_fdtable(files);
+ if (fd >= fdt->max_fds)
+ goto out_unlock;
+ filp = fdt->fd[fd];
+ if (!filp)
+ goto out_unlock;
+ rcu_assign_pointer(fdt->fd[fd], NULL);
+ FD_CLR(fd, fdt->close_on_exec);
+ __put_unused_fd(files, fd);
+ spin_unlock(&files->file_lock);
+ retval = filp_close(filp, files);
+
+ /* can't restart close syscall because file table entry was cleared */
+ if (unlikely(retval == -ERESTARTSYS ||
+ retval == -ERESTARTNOINTR ||
+ retval == -ERESTARTNOHAND ||
+ retval == -ERESTART_RESTARTBLOCK))
+ retval = -EINTR;
+
+ put_files_struct(files);
+ return retval;
+
+out_unlock:
+ spin_unlock(&files->file_lock);
+ put_files_struct(files);
+ return -EBADF;
+}
+
+static void binder_set_nice(long nice)
+{
+ long min_nice;
+ if (can_nice(current, nice)) {
+ set_user_nice(current, nice);
+ return;
+ }
+ min_nice = 20 - current->signal->rlim[RLIMIT_NICE].rlim_cur;
+ if (binder_debug_mask & BINDER_DEBUG_PRIORITY_CAP)
+ printk(KERN_INFO "binder: %d: nice value %ld not allowed use "
+ "%ld instead\n", current->pid, nice, min_nice);
+ set_user_nice(current, min_nice);
+ if (min_nice < 20)
+ return;
+ binder_user_error("binder: %d RLIMIT_NICE not set\n", current->pid);
+}
+
+static size_t binder_buffer_size(
+ struct binder_proc *proc, struct binder_buffer *buffer)
+{
+ if (list_is_last(&buffer->entry, &proc->buffers))
+ return proc->buffer + proc->buffer_size - (void *)buffer->data;
+ else
+ return (size_t)list_entry(buffer->entry.next,
+ struct binder_buffer, entry) - (size_t)buffer->data;
+}
+
+static void binder_insert_free_buffer(
+ struct binder_proc *proc, struct binder_buffer *new_buffer)
+{
+ struct rb_node **p = &proc->free_buffers.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_buffer *buffer;
+ size_t buffer_size;
+ size_t new_buffer_size;
+
+ BUG_ON(!new_buffer->free);
+
+ new_buffer_size = binder_buffer_size(proc, new_buffer);
+
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: add free buffer, size %zd, "
+ "at %p\n", proc->pid, new_buffer_size, new_buffer);
+
+ while (*p) {
+ parent = *p;
+ buffer = rb_entry(parent, struct binder_buffer, rb_node);
+ BUG_ON(!buffer->free);
+
+ buffer_size = binder_buffer_size(proc, buffer);
+
+ if (new_buffer_size < buffer_size)
+ p = &parent->rb_left;
+ else
+ p = &parent->rb_right;
+ }
+ rb_link_node(&new_buffer->rb_node, parent, p);
+ rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
+}
+
+static void binder_insert_allocated_buffer(
+ struct binder_proc *proc, struct binder_buffer *new_buffer)
+{
+ struct rb_node **p = &proc->allocated_buffers.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_buffer *buffer;
+
+ BUG_ON(new_buffer->free);
+
+ while (*p) {
+ parent = *p;
+ buffer = rb_entry(parent, struct binder_buffer, rb_node);
+ BUG_ON(buffer->free);
+
+ if (new_buffer < buffer)
+ p = &parent->rb_left;
+ else if (new_buffer > buffer)
+ p = &parent->rb_right;
+ else
+ BUG();
+ }
+ rb_link_node(&new_buffer->rb_node, parent, p);
+ rb_insert_color(&new_buffer->rb_node, &proc->allocated_buffers);
+}
+
+static struct binder_buffer *binder_buffer_lookup(
+ struct binder_proc *proc, void __user *user_ptr)
+{
+ struct rb_node *n = proc->allocated_buffers.rb_node;
+ struct binder_buffer *buffer;
+ struct binder_buffer *kern_ptr;
+
+ kern_ptr = user_ptr - proc->user_buffer_offset
+ - offsetof(struct binder_buffer, data);
+
+ while (n) {
+ buffer = rb_entry(n, struct binder_buffer, rb_node);
+ BUG_ON(buffer->free);
+
+ if (kern_ptr < buffer)
+ n = n->rb_left;
+ else if (kern_ptr > buffer)
+ n = n->rb_right;
+ else
+ return buffer;
+ }
+ return NULL;
+}
+
+static int binder_update_page_range(struct binder_proc *proc, int allocate,
+ void *start, void *end, struct vm_area_struct *vma)
+{
+ void *page_addr;
+ unsigned long user_page_addr;
+ struct vm_struct tmp_area;
+ struct page **page;
+ struct mm_struct *mm;
+
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: %s pages %p-%p\n",
+ proc->pid, allocate ? "allocate" : "free", start, end);
+
+ if (end <= start)
+ return 0;
+
+ if (vma)
+ mm = NULL;
+ else
+ mm = get_task_mm(proc->tsk);
+
+ if (mm) {
+ down_write(&mm->mmap_sem);
+ vma = proc->vma;
+ }
+
+ if (allocate == 0)
+ goto free_range;
+
+ if (vma == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed to "
+ "map pages in userspace, no vma\n", proc->pid);
+ goto err_no_vma;
+ }
+
+ for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) {
+ int ret;
+ struct page **page_array_ptr;
+ page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
+
+ BUG_ON(*page);
+ *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (*page == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ "for page at %p\n", proc->pid, page_addr);
+ goto err_alloc_page_failed;
+ }
+ tmp_area.addr = page_addr;
+ tmp_area.size = PAGE_SIZE + PAGE_SIZE /* guard page? */;
+ page_array_ptr = page;
+ ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
+ if (ret) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ "to map page at %p in kernel\n",
+ proc->pid, page_addr);
+ goto err_map_kernel_failed;
+ }
+ user_page_addr = (size_t)page_addr + proc->user_buffer_offset;
+ ret = vm_insert_page(vma, user_page_addr, page[0]);
+ if (ret) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ "to map page at %lx in userspace\n",
+ proc->pid, user_page_addr);
+ goto err_vm_insert_page_failed;
+ }
+ /* vm_insert_page does not seem to increment the refcount */
+ }
+ if (mm) {
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ }
+ return 0;
+
+free_range:
+ for (page_addr = end - PAGE_SIZE; page_addr >= start;
+ page_addr -= PAGE_SIZE) {
+ page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
+ if (vma)
+ zap_page_range(vma, (size_t)page_addr +
+ proc->user_buffer_offset, PAGE_SIZE, NULL);
+err_vm_insert_page_failed:
+ unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE);
+err_map_kernel_failed:
+ __free_page(*page);
+ *page = NULL;
+err_alloc_page_failed:
+ ;
+ }
+err_no_vma:
+ if (mm) {
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ }
+ return -ENOMEM;
+}
+
+static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
+ size_t data_size, size_t offsets_size, int is_async)
+{
+ struct rb_node *n = proc->free_buffers.rb_node;
+ struct binder_buffer *buffer;
+ size_t buffer_size;
+ struct rb_node *best_fit = NULL;
+ void *has_page_addr;
+ void *end_page_addr;
+ size_t size;
+
+ if (proc->vma == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma\n",
+ proc->pid);
+ return NULL;
+ }
+
+ size = ALIGN(data_size, sizeof(void *)) +
+ ALIGN(offsets_size, sizeof(void *));
+
+ if (size < data_size || size < offsets_size) {
+ binder_user_error("binder: %d: got transaction with invalid "
+ "size %zd-%zd\n", proc->pid, data_size, offsets_size);
+ return NULL;
+ }
+
+ if (is_async &&
+ proc->free_async_space < size + sizeof(struct binder_buffer)) {
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd f"
+ "ailed, no async space left\n", proc->pid, size);
+ return NULL;
+ }
+
+ while (n) {
+ buffer = rb_entry(n, struct binder_buffer, rb_node);
+ BUG_ON(!buffer->free);
+ buffer_size = binder_buffer_size(proc, buffer);
+
+ if (size < buffer_size) {
+ best_fit = n;
+ n = n->rb_left;
+ } else if (size > buffer_size)
+ n = n->rb_right;
+ else {
+ best_fit = n;
+ break;
+ }
+ }
+ if (best_fit == NULL) {
+ printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd failed, "
+ "no address space\n", proc->pid, size);
+ return NULL;
+ }
+ if (n == NULL) {
+ buffer = rb_entry(best_fit, struct binder_buffer, rb_node);
+ buffer_size = binder_buffer_size(proc, buffer);
+ }
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd got buff"
+ "er %p size %zd\n", proc->pid, size, buffer, buffer_size);
+
+ has_page_addr =
+ (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK);
+ if (n == NULL) {
+ if (size + sizeof(struct binder_buffer) + 4 >= buffer_size)
+ buffer_size = size; /* no room for other buffers */
+ else
+ buffer_size = size + sizeof(struct binder_buffer);
+ }
+ end_page_addr = (void *)PAGE_ALIGN((size_t)buffer->data + buffer_size);
+ if (end_page_addr > has_page_addr)
+ end_page_addr = has_page_addr;
+ if (binder_update_page_range(proc, 1,
+ (void *)PAGE_ALIGN((size_t)buffer->data), end_page_addr, NULL))
+ return NULL;
+
+ rb_erase(best_fit, &proc->free_buffers);
+ buffer->free = 0;
+ binder_insert_allocated_buffer(proc, buffer);
+ if (buffer_size != size) {
+ struct binder_buffer *new_buffer = (void *)buffer->data + size;
+ list_add(&new_buffer->entry, &buffer->entry);
+ new_buffer->free = 1;
+ binder_insert_free_buffer(proc, new_buffer);
+ }
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd got "
+ "%p\n", proc->pid, size, buffer);
+ buffer->data_size = data_size;
+ buffer->offsets_size = offsets_size;
+ buffer->async_transaction = is_async;
+ if (is_async) {
+ proc->free_async_space -= size + sizeof(struct binder_buffer);
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC_ASYNC)
+ printk(KERN_INFO "binder: %d: binder_alloc_buf size %zd "
+ "async free %zd\n", proc->pid, size,
+ proc->free_async_space);
+ }
+
+ return buffer;
+}
+
+static void *buffer_start_page(struct binder_buffer *buffer)
+{
+ return (void *)((size_t)buffer & PAGE_MASK);
+}
+
+static void *buffer_end_page(struct binder_buffer *buffer)
+{
+ return (void *)(((size_t)(buffer + 1) - 1) & PAGE_MASK);
+}
+
+static void binder_delete_free_buffer(
+ struct binder_proc *proc, struct binder_buffer *buffer)
+{
+ struct binder_buffer *prev, *next = NULL;
+ int free_page_end = 1;
+ int free_page_start = 1;
+
+ BUG_ON(proc->buffers.next == &buffer->entry);
+ prev = list_entry(buffer->entry.prev, struct binder_buffer, entry);
+ BUG_ON(!prev->free);
+ if (buffer_end_page(prev) == buffer_start_page(buffer)) {
+ free_page_start = 0;
+ if (buffer_end_page(prev) == buffer_end_page(buffer))
+ free_page_end = 0;
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: merge free, buffer %p "
+ "share page with %p\n", proc->pid, buffer, prev);
+ }
+
+ if (!list_is_last(&buffer->entry, &proc->buffers)) {
+ next = list_entry(buffer->entry.next,
+ struct binder_buffer, entry);
+ if (buffer_start_page(next) == buffer_end_page(buffer)) {
+ free_page_end = 0;
+ if (buffer_start_page(next) ==
+ buffer_start_page(buffer))
+ free_page_start = 0;
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: merge free, "
+ "buffer %p share page with %p\n",
+ proc->pid, buffer, prev);
+ }
+ }
+ list_del(&buffer->entry);
+ if (free_page_start || free_page_end) {
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: merge free, buffer %p do "
+ "not share page%s%s with with %p or %p\n",
+ proc->pid, buffer, free_page_start ? "" : " end",
+ free_page_end ? "" : " start", prev, next);
+ binder_update_page_range(proc, 0, free_page_start ?
+ buffer_start_page(buffer) : buffer_end_page(buffer),
+ (free_page_end ? buffer_end_page(buffer) :
+ buffer_start_page(buffer)) + PAGE_SIZE, NULL);
+ }
+}
+
+static void binder_free_buf(
+ struct binder_proc *proc, struct binder_buffer *buffer)
+{
+ size_t size, buffer_size;
+
+ buffer_size = binder_buffer_size(proc, buffer);
+
+ size = ALIGN(buffer->data_size, sizeof(void *)) +
+ ALIGN(buffer->offsets_size, sizeof(void *));
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder: %d: binder_free_buf %p size %zd buffer"
+ "_size %zd\n", proc->pid, buffer, size, buffer_size);
+
+ BUG_ON(buffer->free);
+ BUG_ON(size > buffer_size);
+ BUG_ON(buffer->transaction != NULL);
+ BUG_ON((void *)buffer < proc->buffer);
+ BUG_ON((void *)buffer > proc->buffer + proc->buffer_size);
+
+ if (buffer->async_transaction) {
+ proc->free_async_space += size + sizeof(struct binder_buffer);
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC_ASYNC)
+ printk(KERN_INFO "binder: %d: binder_free_buf size %zd "
+ "async free %zd\n", proc->pid, size,
+ proc->free_async_space);
+ }
+
+ binder_update_page_range(proc, 0,
+ (void *)PAGE_ALIGN((size_t)buffer->data),
+ (void *)(((size_t)buffer->data + buffer_size) & PAGE_MASK),
+ NULL);
+ rb_erase(&buffer->rb_node, &proc->allocated_buffers);
+ buffer->free = 1;
+ if (!list_is_last(&buffer->entry, &proc->buffers)) {
+ struct binder_buffer *next = list_entry(buffer->entry.next,
+ struct binder_buffer, entry);
+ if (next->free) {
+ rb_erase(&next->rb_node, &proc->free_buffers);
+ binder_delete_free_buffer(proc, next);
+ }
+ }
+ if (proc->buffers.next != &buffer->entry) {
+ struct binder_buffer *prev = list_entry(buffer->entry.prev,
+ struct binder_buffer, entry);
+ if (prev->free) {
+ binder_delete_free_buffer(proc, buffer);
+ rb_erase(&prev->rb_node, &proc->free_buffers);
+ buffer = prev;
+ }
+ }
+ binder_insert_free_buffer(proc, buffer);
+}
+
+static struct binder_node *
+binder_get_node(struct binder_proc *proc, void __user *ptr)
+{
+ struct rb_node *n = proc->nodes.rb_node;
+ struct binder_node *node;
+
+ while (n) {
+ node = rb_entry(n, struct binder_node, rb_node);
+
+ if (ptr < node->ptr)
+ n = n->rb_left;
+ else if (ptr > node->ptr)
+ n = n->rb_right;
+ else
+ return node;
+ }
+ return NULL;
+}
+
+static struct binder_node *
+binder_new_node(struct binder_proc *proc, void __user *ptr, void __user *cookie)
+{
+ struct rb_node **p = &proc->nodes.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_node *node;
+
+ while (*p) {
+ parent = *p;
+ node = rb_entry(parent, struct binder_node, rb_node);
+
+ if (ptr < node->ptr)
+ p = &(*p)->rb_left;
+ else if (ptr > node->ptr)
+ p = &(*p)->rb_right;
+ else
+ return NULL;
+ }
+
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (node == NULL)
+ return NULL;
+ binder_stats.obj_created[BINDER_STAT_NODE]++;
+ rb_link_node(&node->rb_node, parent, p);
+ rb_insert_color(&node->rb_node, &proc->nodes);
+ node->debug_id = ++binder_last_id;
+ node->proc = proc;
+ node->ptr = ptr;
+ node->cookie = cookie;
+ node->work.type = BINDER_WORK_NODE;
+ INIT_LIST_HEAD(&node->work.entry);
+ INIT_LIST_HEAD(&node->async_todo);
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: %d:%d node %d u%p c%p created\n",
+ proc->pid, current->pid, node->debug_id,
+ node->ptr, node->cookie);
+ return node;
+}
+
+static int
+binder_inc_node(struct binder_node *node, int strong, int internal,
+ struct list_head *target_list)
+{
+ if (strong) {
+ if (internal) {
+ if (target_list == NULL &&
+ node->internal_strong_refs == 0 &&
+ !(node == binder_context_mgr_node &&
+ node->has_strong_ref)) {
+ printk(KERN_ERR "binder: invalid inc strong "
+ "node for %d\n", node->debug_id);
+ return -EINVAL;
+ }
+ node->internal_strong_refs++;
+ } else
+ node->local_strong_refs++;
+ if (!node->has_strong_ref && target_list) {
+ list_del_init(&node->work.entry);
+ list_add_tail(&node->work.entry, target_list);
+ }
+ } else {
+ if (!internal)
+ node->local_weak_refs++;
+ if (!node->has_weak_ref && list_empty(&node->work.entry)) {
+ if (target_list == NULL) {
+ printk(KERN_ERR "binder: invalid inc weak node "
+ "for %d\n", node->debug_id);
+ return -EINVAL;
+ }
+ list_add_tail(&node->work.entry, target_list);
+ }
+ }
+ return 0;
+}
+
+static int
+binder_dec_node(struct binder_node *node, int strong, int internal)
+{
+ if (strong) {
+ if (internal)
+ node->internal_strong_refs--;
+ else
+ node->local_strong_refs--;
+ if (node->local_strong_refs || node->internal_strong_refs)
+ return 0;
+ } else {
+ if (!internal)
+ node->local_weak_refs--;
+ if (node->local_weak_refs || !hlist_empty(&node->refs))
+ return 0;
+ }
+ if (node->proc && (node->has_strong_ref || node->has_weak_ref)) {
+ if (list_empty(&node->work.entry)) {
+ list_add_tail(&node->work.entry, &node->proc->todo);
+ wake_up_interruptible(&node->proc->wait);
+ }
+ } else {
+ if (hlist_empty(&node->refs) && !node->local_strong_refs &&
+ !node->local_weak_refs) {
+ list_del_init(&node->work.entry);
+ if (node->proc) {
+ rb_erase(&node->rb_node, &node->proc->nodes);
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: refless node %d deleted\n", node->debug_id);
+ } else {
+ hlist_del(&node->dead_node);
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: dead node %d deleted\n", node->debug_id);
+ }
+ kfree(node);
+ binder_stats.obj_deleted[BINDER_STAT_NODE]++;
+ }
+ }
+
+ return 0;
+}
+
+
+static struct binder_ref *
+binder_get_ref(struct binder_proc *proc, uint32_t desc)
+{
+ struct rb_node *n = proc->refs_by_desc.rb_node;
+ struct binder_ref *ref;
+
+ while (n) {
+ ref = rb_entry(n, struct binder_ref, rb_node_desc);
+
+ if (desc < ref->desc)
+ n = n->rb_left;
+ else if (desc > ref->desc)
+ n = n->rb_right;
+ else
+ return ref;
+ }
+ return NULL;
+}
+
+static struct binder_ref *
+binder_get_ref_for_node(struct binder_proc *proc, struct binder_node *node)
+{
+ struct rb_node *n;
+ struct rb_node **p = &proc->refs_by_node.rb_node;
+ struct rb_node *parent = NULL;
+ struct binder_ref *ref, *new_ref;
+
+ while (*p) {
+ parent = *p;
+ ref = rb_entry(parent, struct binder_ref, rb_node_node);
+
+ if (node < ref->node)
+ p = &(*p)->rb_left;
+ else if (node > ref->node)
+ p = &(*p)->rb_right;
+ else
+ return ref;
+ }
+ new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ if (new_ref == NULL)
+ return NULL;
+ binder_stats.obj_created[BINDER_STAT_REF]++;
+ new_ref->debug_id = ++binder_last_id;
+ new_ref->proc = proc;
+ new_ref->node = node;
+ rb_link_node(&new_ref->rb_node_node, parent, p);
+ rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
+
+ new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;
+ for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
+ ref = rb_entry(n, struct binder_ref, rb_node_desc);
+ if (ref->desc > new_ref->desc)
+ break;
+ new_ref->desc = ref->desc + 1;
+ }
+
+ p = &proc->refs_by_desc.rb_node;
+ while (*p) {
+ parent = *p;
+ ref = rb_entry(parent, struct binder_ref, rb_node_desc);
+
+ if (new_ref->desc < ref->desc)
+ p = &(*p)->rb_left;
+ else if (new_ref->desc > ref->desc)
+ p = &(*p)->rb_right;
+ else
+ BUG();
+ }
+ rb_link_node(&new_ref->rb_node_desc, parent, p);
+ rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc);
+ if (node) {
+ hlist_add_head(&new_ref->node_entry, &node->refs);
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: %d new ref %d desc %d for "
+ "node %d\n", proc->pid, new_ref->debug_id,
+ new_ref->desc, node->debug_id);
+ } else {
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: %d new ref %d desc %d for "
+ "dead node\n", proc->pid, new_ref->debug_id,
+ new_ref->desc);
+ }
+ return new_ref;
+}
+
+static void
+binder_delete_ref(struct binder_ref *ref)
+{
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: %d delete ref %d desc %d for "
+ "node %d\n", ref->proc->pid, ref->debug_id,
+ ref->desc, ref->node->debug_id);
+ rb_erase(&ref->rb_node_desc, &ref->proc->refs_by_desc);
+ rb_erase(&ref->rb_node_node, &ref->proc->refs_by_node);
+ if (ref->strong)
+ binder_dec_node(ref->node, 1, 1);
+ hlist_del(&ref->node_entry);
+ binder_dec_node(ref->node, 0, 1);
+ if (ref->death) {
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
+ printk(KERN_INFO "binder: %d delete ref %d desc %d "
+ "has death notification\n", ref->proc->pid,
+ ref->debug_id, ref->desc);
+ list_del(&ref->death->work.entry);
+ kfree(ref->death);
+ binder_stats.obj_deleted[BINDER_STAT_DEATH]++;
+ }
+ kfree(ref);
+ binder_stats.obj_deleted[BINDER_STAT_REF]++;
+}
+
+static int
+binder_inc_ref(
+ struct binder_ref *ref, int strong, struct list_head *target_list)
+{
+ int ret;
+ if (strong) {
+ if (ref->strong == 0) {
+ ret = binder_inc_node(ref->node, 1, 1, target_list);
+ if (ret)
+ return ret;
+ }
+ ref->strong++;
+ } else {
+ if (ref->weak == 0) {
+ ret = binder_inc_node(ref->node, 0, 1, target_list);
+ if (ret)
+ return ret;
+ }
+ ref->weak++;
+ }
+ return 0;
+}
+
+
+static int
+binder_dec_ref(struct binder_ref *ref, int strong)
+{
+ if (strong) {
+ if (ref->strong == 0) {
+ binder_user_error("binder: %d invalid dec strong, "
+ "ref %d desc %d s %d w %d\n",
+ ref->proc->pid, ref->debug_id,
+ ref->desc, ref->strong, ref->weak);
+ return -EINVAL;
+ }
+ ref->strong--;
+ if (ref->strong == 0) {
+ int ret;
+ ret = binder_dec_node(ref->node, strong, 1);
+ if (ret)
+ return ret;
+ }
+ } else {
+ if (ref->weak == 0) {
+ binder_user_error("binder: %d invalid dec weak, "
+ "ref %d desc %d s %d w %d\n",
+ ref->proc->pid, ref->debug_id,
+ ref->desc, ref->strong, ref->weak);
+ return -EINVAL;
+ }
+ ref->weak--;
+ }
+ if (ref->strong == 0 && ref->weak == 0)
+ binder_delete_ref(ref);
+ return 0;
+}
+
+static void
+binder_pop_transaction(
+ struct binder_thread *target_thread, struct binder_transaction *t)
+{
+ if (target_thread) {
+ BUG_ON(target_thread->transaction_stack != t);
+ BUG_ON(target_thread->transaction_stack->from != target_thread);
+ target_thread->transaction_stack =
+ target_thread->transaction_stack->from_parent;
+ t->from = NULL;
+ }
+ t->need_reply = 0;
+ if (t->buffer)
+ t->buffer->transaction = NULL;
+ kfree(t);
+ binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++;
+}
+
+static void
+binder_send_failed_reply(struct binder_transaction *t, uint32_t error_code)
+{
+ struct binder_thread *target_thread;
+ BUG_ON(t->flags & TF_ONE_WAY);
+ while (1) {
+ target_thread = t->from;
+ if (target_thread) {
+ if (target_thread->return_error != BR_OK &&
+ target_thread->return_error2 == BR_OK) {
+ target_thread->return_error2 =
+ target_thread->return_error;
+ target_thread->return_error = BR_OK;
+ }
+ if (target_thread->return_error == BR_OK) {
+ if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)
+ printk(KERN_INFO "binder: send failed reply for transaction %d to %d:%d\n",
+ t->debug_id, target_thread->proc->pid, target_thread->pid);
+
+ binder_pop_transaction(target_thread, t);
+ target_thread->return_error = error_code;
+ wake_up_interruptible(&target_thread->wait);
+ } else {
+ printk(KERN_ERR "binder: reply failed, target "
+ "thread, %d:%d, has error code %d "
+ "already\n", target_thread->proc->pid,
+ target_thread->pid,
+ target_thread->return_error);
+ }
+ return;
+ } else {
+ struct binder_transaction *next = t->from_parent;
+
+ if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)
+ printk(KERN_INFO "binder: send failed reply "
+ "for transaction %d, target dead\n",
+ t->debug_id);
+
+ binder_pop_transaction(target_thread, t);
+ if (next == NULL) {
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
+ printk(KERN_INFO "binder: reply failed,"
+ " no target thread at root\n");
+ return;
+ }
+ t = next;
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
+ printk(KERN_INFO "binder: reply failed, no targ"
+ "et thread -- retry %d\n", t->debug_id);
+ }
+ }
+}
+
+static void
+binder_transaction_buffer_release(struct binder_proc *proc,
+ struct binder_buffer *buffer, size_t *failed_at);
+
+static void
+binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
+ struct binder_transaction_data *tr, int reply)
+{
+ struct binder_transaction *t;
+ struct binder_work *tcomplete;
+ size_t *offp, *off_end;
+ struct binder_proc *target_proc;
+ struct binder_thread *target_thread = NULL;
+ struct binder_node *target_node = NULL;
+ struct list_head *target_list;
+ wait_queue_head_t *target_wait;
+ struct binder_transaction *in_reply_to = NULL;
+ struct binder_transaction_log_entry *e;
+ uint32_t return_error;
+
+ e = binder_transaction_log_add(&binder_transaction_log);
+ e->call_type = reply ? 2 : !!(tr->flags & TF_ONE_WAY);
+ e->from_proc = proc->pid;
+ e->from_thread = thread->pid;
+ e->target_handle = tr->target.handle;
+ e->data_size = tr->data_size;
+ e->offsets_size = tr->offsets_size;
+
+ if (reply) {
+ in_reply_to = thread->transaction_stack;
+ if (in_reply_to == NULL) {
+ binder_user_error("binder: %d:%d got reply transaction "
+ "with no transaction stack\n",
+ proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_empty_call_stack;
+ }
+ binder_set_nice(in_reply_to->saved_priority);
+ if (in_reply_to->to_thread != thread) {
+ binder_user_error("binder: %d:%d got reply transaction "
+ "with bad transaction stack,"
+ " transaction %d has target %d:%d\n",
+ proc->pid, thread->pid, in_reply_to->debug_id,
+ in_reply_to->to_proc ?
+ in_reply_to->to_proc->pid : 0,
+ in_reply_to->to_thread ?
+ in_reply_to->to_thread->pid : 0);
+ return_error = BR_FAILED_REPLY;
+ in_reply_to = NULL;
+ goto err_bad_call_stack;
+ }
+ thread->transaction_stack = in_reply_to->to_parent;
+ target_thread = in_reply_to->from;
+ if (target_thread == NULL) {
+ return_error = BR_DEAD_REPLY;
+ goto err_dead_binder;
+ }
+ if (target_thread->transaction_stack != in_reply_to) {
+ binder_user_error("binder: %d:%d got reply transaction "
+ "with bad target transaction stack %d, "
+ "expected %d\n",
+ proc->pid, thread->pid,
+ target_thread->transaction_stack ?
+ target_thread->transaction_stack->debug_id : 0,
+ in_reply_to->debug_id);
+ return_error = BR_FAILED_REPLY;
+ in_reply_to = NULL;
+ target_thread = NULL;
+ goto err_dead_binder;
+ }
+ target_proc = target_thread->proc;
+ } else {
+ if (tr->target.handle) {
+ struct binder_ref *ref;
+ ref = binder_get_ref(proc, tr->target.handle);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d got "
+ "transaction to invalid handle\n",
+ proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_invalid_target_handle;
+ }
+ target_node = ref->node;
+ } else {
+ target_node = binder_context_mgr_node;
+ if (target_node == NULL) {
+ return_error = BR_DEAD_REPLY;
+ goto err_no_context_mgr_node;
+ }
+ }
+ e->to_node = target_node->debug_id;
+ target_proc = target_node->proc;
+ if (target_proc == NULL) {
+ return_error = BR_DEAD_REPLY;
+ goto err_dead_binder;
+ }
+ if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
+ struct binder_transaction *tmp;
+ tmp = thread->transaction_stack;
+ while (tmp) {
+ if (tmp->from && tmp->from->proc == target_proc)
+ target_thread = tmp->from;
+ tmp = tmp->from_parent;
+ }
+ }
+ }
+ if (target_thread) {
+ e->to_thread = target_thread->pid;
+ target_list = &target_thread->todo;
+ target_wait = &target_thread->wait;
+ } else {
+ target_list = &target_proc->todo;
+ target_wait = &target_proc->wait;
+ }
+ e->to_proc = target_proc->pid;
+
+ /* TODO: reuse incoming transaction for reply */
+ t = kzalloc(sizeof(*t), GFP_KERNEL);
+ if (t == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_alloc_t_failed;
+ }
+ binder_stats.obj_created[BINDER_STAT_TRANSACTION]++;
+
+ tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
+ if (tcomplete == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_alloc_tcomplete_failed;
+ }
+ binder_stats.obj_created[BINDER_STAT_TRANSACTION_COMPLETE]++;
+
+ t->debug_id = ++binder_last_id;
+ e->debug_id = t->debug_id;
+
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION) {
+ if (reply)
+ printk(KERN_INFO "binder: %d:%d BC_REPLY %d -> %d:%d, "
+ "data %p-%p size %zd-%zd\n",
+ proc->pid, thread->pid, t->debug_id,
+ target_proc->pid, target_thread->pid,
+ tr->data.ptr.buffer, tr->data.ptr.offsets,
+ tr->data_size, tr->offsets_size);
+ else
+ printk(KERN_INFO "binder: %d:%d BC_TRANSACTION %d -> "
+ "%d - node %d, data %p-%p size %zd-%zd\n",
+ proc->pid, thread->pid, t->debug_id,
+ target_proc->pid, target_node->debug_id,
+ tr->data.ptr.buffer, tr->data.ptr.offsets,
+ tr->data_size, tr->offsets_size);
+ }
+
+ if (!reply && !(tr->flags & TF_ONE_WAY))
+ t->from = thread;
+ else
+ t->from = NULL;
+ t->sender_euid = proc->tsk->cred->euid;
+ t->to_proc = target_proc;
+ t->to_thread = target_thread;
+ t->code = tr->code;
+ t->flags = tr->flags;
+ t->priority = task_nice(current);
+ t->buffer = binder_alloc_buf(target_proc, tr->data_size,
+ tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
+ if (t->buffer == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_alloc_buf_failed;
+ }
+ t->buffer->allow_user_free = 0;
+ t->buffer->debug_id = t->debug_id;
+ t->buffer->transaction = t;
+ t->buffer->target_node = target_node;
+ if (target_node)
+ binder_inc_node(target_node, 1, 0, NULL);
+
+ offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));
+
+ if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
+ binder_user_error("binder: %d:%d got transaction with invalid "
+ "data ptr\n", proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_copy_data_failed;
+ }
+ if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
+ binder_user_error("binder: %d:%d got transaction with invalid "
+ "offsets ptr\n", proc->pid, thread->pid);
+ return_error = BR_FAILED_REPLY;
+ goto err_copy_data_failed;
+ }
+ off_end = (void *)offp + tr->offsets_size;
+ for (; offp < off_end; offp++) {
+ struct flat_binder_object *fp;
+ if (*offp > t->buffer->data_size - sizeof(*fp)) {
+ binder_user_error("binder: %d:%d got transaction with "
+ "invalid offset, %zd\n",
+ proc->pid, thread->pid, *offp);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_offset;
+ }
+ fp = (struct flat_binder_object *)(t->buffer->data + *offp);
+ switch (fp->type) {
+ case BINDER_TYPE_BINDER:
+ case BINDER_TYPE_WEAK_BINDER: {
+ struct binder_ref *ref;
+ struct binder_node *node = binder_get_node(proc, fp->binder);
+ if (node == NULL) {
+ node = binder_new_node(proc, fp->binder, fp->cookie);
+ if (node == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_new_node_failed;
+ }
+ node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
+ node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+ }
+ if (fp->cookie != node->cookie) {
+ binder_user_error("binder: %d:%d sending u%p "
+ "node %d, cookie mismatch %p != %p\n",
+ proc->pid, thread->pid,
+ fp->binder, node->debug_id,
+ fp->cookie, node->cookie);
+ goto err_binder_get_ref_for_node_failed;
+ }
+ ref = binder_get_ref_for_node(target_proc, node);
+ if (ref == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_for_node_failed;
+ }
+ if (fp->type == BINDER_TYPE_BINDER)
+ fp->type = BINDER_TYPE_HANDLE;
+ else
+ fp->type = BINDER_TYPE_WEAK_HANDLE;
+ fp->handle = ref->desc;
+ binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE, &thread->todo);
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " node %d u%p -> ref %d desc %d\n",
+ node->debug_id, node->ptr, ref->debug_id, ref->desc);
+ } break;
+ case BINDER_TYPE_HANDLE:
+ case BINDER_TYPE_WEAK_HANDLE: {
+ struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d got "
+ "transaction with invalid "
+ "handle, %ld\n", proc->pid,
+ thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_failed;
+ }
+ if (ref->node->proc == target_proc) {
+ if (fp->type == BINDER_TYPE_HANDLE)
+ fp->type = BINDER_TYPE_BINDER;
+ else
+ fp->type = BINDER_TYPE_WEAK_BINDER;
+ fp->binder = ref->node->ptr;
+ fp->cookie = ref->node->cookie;
+ binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " ref %d desc %d -> node %d u%p\n",
+ ref->debug_id, ref->desc, ref->node->debug_id, ref->node->ptr);
+ } else {
+ struct binder_ref *new_ref;
+ new_ref = binder_get_ref_for_node(target_proc, ref->node);
+ if (new_ref == NULL) {
+ return_error = BR_FAILED_REPLY;
+ goto err_binder_get_ref_for_node_failed;
+ }
+ fp->handle = new_ref->desc;
+ binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " ref %d desc %d -> ref %d desc %d (node %d)\n",
+ ref->debug_id, ref->desc, new_ref->debug_id, new_ref->desc, ref->node->debug_id);
+ }
+ } break;
+
+ case BINDER_TYPE_FD: {
+ int target_fd;
+ struct file *file;
+
+ if (reply) {
+ if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
+ binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
+ proc->pid, thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_fd_not_allowed;
+ }
+ } else if (!target_node->accept_fds) {
+ binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
+ proc->pid, thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_fd_not_allowed;
+ }
+
+ file = fget(fp->handle);
+ if (file == NULL) {
+ binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
+ proc->pid, thread->pid, fp->handle);
+ return_error = BR_FAILED_REPLY;
+ goto err_fget_failed;
+ }
+ target_fd = task_get_unused_fd_flags(target_proc->tsk, O_CLOEXEC);
+ if (target_fd < 0) {
+ fput(file);
+ return_error = BR_FAILED_REPLY;
+ goto err_get_unused_fd_failed;
+ }
+ task_fd_install(target_proc->tsk, target_fd, file);
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " fd %ld -> %d\n", fp->handle, target_fd);
+ /* TODO: fput? */
+ fp->handle = target_fd;
+ } break;
+
+ default:
+ binder_user_error("binder: %d:%d got transactio"
+ "n with invalid object type, %lx\n",
+ proc->pid, thread->pid, fp->type);
+ return_error = BR_FAILED_REPLY;
+ goto err_bad_object_type;
+ }
+ }
+ if (reply) {
+ BUG_ON(t->buffer->async_transaction != 0);
+ binder_pop_transaction(target_thread, in_reply_to);
+ } else if (!(t->flags & TF_ONE_WAY)) {
+ BUG_ON(t->buffer->async_transaction != 0);
+ t->need_reply = 1;
+ t->from_parent = thread->transaction_stack;
+ thread->transaction_stack = t;
+ } else {
+ BUG_ON(target_node == NULL);
+ BUG_ON(t->buffer->async_transaction != 1);
+ if (target_node->has_async_transaction) {
+ target_list = &target_node->async_todo;
+ target_wait = NULL;
+ } else
+ target_node->has_async_transaction = 1;
+ }
+ t->work.type = BINDER_WORK_TRANSACTION;
+ list_add_tail(&t->work.entry, target_list);
+ tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
+ list_add_tail(&tcomplete->entry, &thread->todo);
+ if (target_wait)
+ wake_up_interruptible(target_wait);
+ return;
+
+err_get_unused_fd_failed:
+err_fget_failed:
+err_fd_not_allowed:
+err_binder_get_ref_for_node_failed:
+err_binder_get_ref_failed:
+err_binder_new_node_failed:
+err_bad_object_type:
+err_bad_offset:
+err_copy_data_failed:
+ binder_transaction_buffer_release(target_proc, t->buffer, offp);
+ t->buffer->transaction = NULL;
+ binder_free_buf(target_proc, t->buffer);
+err_binder_alloc_buf_failed:
+ kfree(tcomplete);
+ binder_stats.obj_deleted[BINDER_STAT_TRANSACTION_COMPLETE]++;
+err_alloc_tcomplete_failed:
+ kfree(t);
+ binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++;
+err_alloc_t_failed:
+err_bad_call_stack:
+err_empty_call_stack:
+err_dead_binder:
+err_invalid_target_handle:
+err_no_context_mgr_node:
+ if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)
+ printk(KERN_INFO "binder: %d:%d transaction failed %d, size"
+ "%zd-%zd\n",
+ proc->pid, thread->pid, return_error,
+ tr->data_size, tr->offsets_size);
+
+ {
+ struct binder_transaction_log_entry *fe;
+ fe = binder_transaction_log_add(&binder_transaction_log_failed);
+ *fe = *e;
+ }
+
+ BUG_ON(thread->return_error != BR_OK);
+ if (in_reply_to) {
+ thread->return_error = BR_TRANSACTION_COMPLETE;
+ binder_send_failed_reply(in_reply_to, return_error);
+ } else
+ thread->return_error = return_error;
+}
+
+static void
+binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer *buffer, size_t *failed_at)
+{
+ size_t *offp, *off_end;
+ int debug_id = buffer->debug_id;
+
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO "binder: %d buffer release %d, size %zd-%zd, failed at %p\n",
+ proc->pid, buffer->debug_id,
+ buffer->data_size, buffer->offsets_size, failed_at);
+
+ if (buffer->target_node)
+ binder_dec_node(buffer->target_node, 1, 0);
+
+ offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
+ if (failed_at)
+ off_end = failed_at;
+ else
+ off_end = (void *)offp + buffer->offsets_size;
+ for (; offp < off_end; offp++) {
+ struct flat_binder_object *fp;
+ if (*offp > buffer->data_size - sizeof(*fp)) {
+ printk(KERN_ERR "binder: transaction release %d bad"
+ "offset %zd, size %zd\n", debug_id, *offp, buffer->data_size);
+ continue;
+ }
+ fp = (struct flat_binder_object *)(buffer->data + *offp);
+ switch (fp->type) {
+ case BINDER_TYPE_BINDER:
+ case BINDER_TYPE_WEAK_BINDER: {
+ struct binder_node *node = binder_get_node(proc, fp->binder);
+ if (node == NULL) {
+ printk(KERN_ERR "binder: transaction release %d bad node %p\n", debug_id, fp->binder);
+ break;
+ }
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " node %d u%p\n",
+ node->debug_id, node->ptr);
+ binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
+ } break;
+ case BINDER_TYPE_HANDLE:
+ case BINDER_TYPE_WEAK_HANDLE: {
+ struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ if (ref == NULL) {
+ printk(KERN_ERR "binder: transaction release %d bad handle %ld\n", debug_id, fp->handle);
+ break;
+ }
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " ref %d desc %d (node %d)\n",
+ ref->debug_id, ref->desc, ref->node->debug_id);
+ binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE);
+ } break;
+
+ case BINDER_TYPE_FD:
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO " fd %ld\n", fp->handle);
+ if (failed_at)
+ task_close_fd(proc->tsk, fp->handle);
+ break;
+
+ default:
+ printk(KERN_ERR "binder: transaction release %d bad object type %lx\n", debug_id, fp->type);
+ break;
+ }
+ }
+}
+
+int
+binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
+ void __user *buffer, int size, signed long *consumed)
+{
+ uint32_t cmd;
+ void __user *ptr = buffer + *consumed;
+ void __user *end = buffer + size;
+
+ while (ptr < end && thread->return_error == BR_OK) {
+ if (get_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
+ binder_stats.bc[_IOC_NR(cmd)]++;
+ proc->stats.bc[_IOC_NR(cmd)]++;
+ thread->stats.bc[_IOC_NR(cmd)]++;
+ }
+ switch (cmd) {
+ case BC_INCREFS:
+ case BC_ACQUIRE:
+ case BC_RELEASE:
+ case BC_DECREFS: {
+ uint32_t target;
+ struct binder_ref *ref;
+ const char *debug_string;
+
+ if (get_user(target, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (target == 0 && binder_context_mgr_node &&
+ (cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
+ ref = binder_get_ref_for_node(proc,
+ binder_context_mgr_node);
+ if (ref->desc != target) {
+ binder_user_error("binder: %d:"
+ "%d tried to acquire "
+ "reference to desc 0, "
+ "got %d instead\n",
+ proc->pid, thread->pid,
+ ref->desc);
+ }
+ } else
+ ref = binder_get_ref(proc, target);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d refcou"
+ "nt change on invalid ref %d\n",
+ proc->pid, thread->pid, target);
+ break;
+ }
+ switch (cmd) {
+ case BC_INCREFS:
+ debug_string = "IncRefs";
+ binder_inc_ref(ref, 0, NULL);
+ break;
+ case BC_ACQUIRE:
+ debug_string = "Acquire";
+ binder_inc_ref(ref, 1, NULL);
+ break;
+ case BC_RELEASE:
+ debug_string = "Release";
+ binder_dec_ref(ref, 1);
+ break;
+ case BC_DECREFS:
+ default:
+ debug_string = "DecRefs";
+ binder_dec_ref(ref, 0);
+ break;
+ }
+ if (binder_debug_mask & BINDER_DEBUG_USER_REFS)
+ printk(KERN_INFO "binder: %d:%d %s ref %d desc %d s %d w %d for node %d\n",
+ proc->pid, thread->pid, debug_string, ref->debug_id, ref->desc, ref->strong, ref->weak, ref->node->debug_id);
+ break;
+ }
+ case BC_INCREFS_DONE:
+ case BC_ACQUIRE_DONE: {
+ void __user *node_ptr;
+ void *cookie;
+ struct binder_node *node;
+
+ if (get_user(node_ptr, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ if (get_user(cookie, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ node = binder_get_node(proc, node_ptr);
+ if (node == NULL) {
+ binder_user_error("binder: %d:%d "
+ "%s u%p no match\n",
+ proc->pid, thread->pid,
+ cmd == BC_INCREFS_DONE ?
+ "BC_INCREFS_DONE" :
+ "BC_ACQUIRE_DONE",
+ node_ptr);
+ break;
+ }
+ if (cookie != node->cookie) {
+ binder_user_error("binder: %d:%d %s u%p node %d"
+ " cookie mismatch %p != %p\n",
+ proc->pid, thread->pid,
+ cmd == BC_INCREFS_DONE ?
+ "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
+ node_ptr, node->debug_id,
+ cookie, node->cookie);
+ break;
+ }
+ if (cmd == BC_ACQUIRE_DONE) {
+ if (node->pending_strong_ref == 0) {
+ binder_user_error("binder: %d:%d "
+ "BC_ACQUIRE_DONE node %d has "
+ "no pending acquire request\n",
+ proc->pid, thread->pid,
+ node->debug_id);
+ break;
+ }
+ node->pending_strong_ref = 0;
+ } else {
+ if (node->pending_weak_ref == 0) {
+ binder_user_error("binder: %d:%d "
+ "BC_INCREFS_DONE node %d has "
+ "no pending increfs request\n",
+ proc->pid, thread->pid,
+ node->debug_id);
+ break;
+ }
+ node->pending_weak_ref = 0;
+ }
+ binder_dec_node(node, cmd == BC_ACQUIRE_DONE, 0);
+ if (binder_debug_mask & BINDER_DEBUG_USER_REFS)
+ printk(KERN_INFO "binder: %d:%d %s node %d ls %d lw %d\n",
+ proc->pid, thread->pid, cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE", node->debug_id, node->local_strong_refs, node->local_weak_refs);
+ break;
+ }
+ case BC_ATTEMPT_ACQUIRE:
+ printk(KERN_ERR "binder: BC_ATTEMPT_ACQUIRE not supported\n");
+ return -EINVAL;
+ case BC_ACQUIRE_RESULT:
+ printk(KERN_ERR "binder: BC_ACQUIRE_RESULT not supported\n");
+ return -EINVAL;
+
+ case BC_FREE_BUFFER: {
+ void __user *data_ptr;
+ struct binder_buffer *buffer;
+
+ if (get_user(data_ptr, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+
+ buffer = binder_buffer_lookup(proc, data_ptr);
+ if (buffer == NULL) {
+ binder_user_error("binder: %d:%d "
+ "BC_FREE_BUFFER u%p no match\n",
+ proc->pid, thread->pid, data_ptr);
+ break;
+ }
+ if (!buffer->allow_user_free) {
+ binder_user_error("binder: %d:%d "
+ "BC_FREE_BUFFER u%p matched "
+ "unreturned buffer\n",
+ proc->pid, thread->pid, data_ptr);
+ break;
+ }
+ if (binder_debug_mask & BINDER_DEBUG_FREE_BUFFER)
+ printk(KERN_INFO "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
+ proc->pid, thread->pid, data_ptr, buffer->debug_id,
+ buffer->transaction ? "active" : "finished");
+
+ if (buffer->transaction) {
+ buffer->transaction->buffer = NULL;
+ buffer->transaction = NULL;
+ }
+ if (buffer->async_transaction && buffer->target_node) {
+ BUG_ON(!buffer->target_node->has_async_transaction);
+ if (list_empty(&buffer->target_node->async_todo))
+ buffer->target_node->has_async_transaction = 0;
+ else
+ list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
+ }
+ binder_transaction_buffer_release(proc, buffer, NULL);
+ binder_free_buf(proc, buffer);
+ break;
+ }
+
+ case BC_TRANSACTION:
+ case BC_REPLY: {
+ struct binder_transaction_data tr;
+
+ if (copy_from_user(&tr, ptr, sizeof(tr)))
+ return -EFAULT;
+ ptr += sizeof(tr);
+ binder_transaction(proc, thread, &tr, cmd == BC_REPLY);
+ break;
+ }
+
+ case BC_REGISTER_LOOPER:
+ if (binder_debug_mask & BINDER_DEBUG_THREADS)
+ printk(KERN_INFO "binder: %d:%d BC_REGISTER_LOOPER\n",
+ proc->pid, thread->pid);
+ if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
+ thread->looper |= BINDER_LOOPER_STATE_INVALID;
+ binder_user_error("binder: %d:%d ERROR:"
+ " BC_REGISTER_LOOPER called "
+ "after BC_ENTER_LOOPER\n",
+ proc->pid, thread->pid);
+ } else if (proc->requested_threads == 0) {
+ thread->looper |= BINDER_LOOPER_STATE_INVALID;
+ binder_user_error("binder: %d:%d ERROR:"
+ " BC_REGISTER_LOOPER called "
+ "without request\n",
+ proc->pid, thread->pid);
+ } else {
+ proc->requested_threads--;
+ proc->requested_threads_started++;
+ }
+ thread->looper |= BINDER_LOOPER_STATE_REGISTERED;
+ break;
+ case BC_ENTER_LOOPER:
+ if (binder_debug_mask & BINDER_DEBUG_THREADS)
+ printk(KERN_INFO "binder: %d:%d BC_ENTER_LOOPER\n",
+ proc->pid, thread->pid);
+ if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
+ thread->looper |= BINDER_LOOPER_STATE_INVALID;
+ binder_user_error("binder: %d:%d ERROR:"
+ " BC_ENTER_LOOPER called after "
+ "BC_REGISTER_LOOPER\n",
+ proc->pid, thread->pid);
+ }
+ thread->looper |= BINDER_LOOPER_STATE_ENTERED;
+ break;
+ case BC_EXIT_LOOPER:
+ if (binder_debug_mask & BINDER_DEBUG_THREADS)
+ printk(KERN_INFO "binder: %d:%d BC_EXIT_LOOPER\n",
+ proc->pid, thread->pid);
+ thread->looper |= BINDER_LOOPER_STATE_EXITED;
+ break;
+
+ case BC_REQUEST_DEATH_NOTIFICATION:
+ case BC_CLEAR_DEATH_NOTIFICATION: {
+ uint32_t target;
+ void __user *cookie;
+ struct binder_ref *ref;
+ struct binder_ref_death *death;
+
+ if (get_user(target, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (get_user(cookie, (void __user * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ ref = binder_get_ref(proc, target);
+ if (ref == NULL) {
+ binder_user_error("binder: %d:%d %s "
+ "invalid ref %d\n",
+ proc->pid, thread->pid,
+ cmd == BC_REQUEST_DEATH_NOTIFICATION ?
+ "BC_REQUEST_DEATH_NOTIFICATION" :
+ "BC_CLEAR_DEATH_NOTIFICATION",
+ target);
+ break;
+ }
+
+ if (binder_debug_mask & BINDER_DEBUG_DEATH_NOTIFICATION)
+ printk(KERN_INFO "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+ proc->pid, thread->pid,
+ cmd == BC_REQUEST_DEATH_NOTIFICATION ?
+ "BC_REQUEST_DEATH_NOTIFICATION" :
+ "BC_CLEAR_DEATH_NOTIFICATION",
+ cookie, ref->debug_id, ref->desc,
+ ref->strong, ref->weak, ref->node->debug_id);
+
+ if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
+ if (ref->death) {
+ binder_user_error("binder: %d:%"
+ "d BC_REQUEST_DEATH_NOTI"
+ "FICATION death notific"
+ "ation already set\n",
+ proc->pid, thread->pid);
+ break;
+ }
+ death = kzalloc(sizeof(*death), GFP_KERNEL);
+ if (death == NULL) {
+ thread->return_error = BR_ERROR;
+ if (binder_debug_mask & BINDER_DEBUG_FAILED_TRANSACTION)
+ printk(KERN_INFO "binder: %d:%d "
+ "BC_REQUEST_DEATH_NOTIFICATION failed\n",
+ proc->pid, thread->pid);
+ break;
+ }
+ binder_stats.obj_created[BINDER_STAT_DEATH]++;
+ INIT_LIST_HEAD(&death->work.entry);
+ death->cookie = cookie;
+ ref->death = death;
+ if (ref->node->proc == NULL) {
+ ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+ if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
+ list_add_tail(&ref->death->work.entry, &thread->todo);
+ } else {
+ list_add_tail(&ref->death->work.entry, &proc->todo);
+ wake_up_interruptible(&proc->wait);
+ }
+ }
+ } else {
+ if (ref->death == NULL) {
+ binder_user_error("binder: %d:%"
+ "d BC_CLEAR_DEATH_NOTIFI"
+ "CATION death notificat"
+ "ion not active\n",
+ proc->pid, thread->pid);
+ break;
+ }
+ death = ref->death;
+ if (death->cookie != cookie) {
+ binder_user_error("binder: %d:%"
+ "d BC_CLEAR_DEATH_NOTIFI"
+ "CATION death notificat"
+ "ion cookie mismatch "
+ "%p != %p\n",
+ proc->pid, thread->pid,
+ death->cookie, cookie);
+ break;
+ }
+ ref->death = NULL;
+ if (list_empty(&death->work.entry)) {
+ death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
+ if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
+ list_add_tail(&death->work.entry, &thread->todo);
+ } else {
+ list_add_tail(&death->work.entry, &proc->todo);
+ wake_up_interruptible(&proc->wait);
+ }
+ } else {
+ BUG_ON(death->work.type != BINDER_WORK_DEAD_BINDER);
+ death->work.type = BINDER_WORK_DEAD_BINDER_AND_CLEAR;
+ }
+ }
+ } break;
+ case BC_DEAD_BINDER_DONE: {
+ struct binder_work *w;
+ void __user *cookie;
+ struct binder_ref_death *death = NULL;
+ if (get_user(cookie, (void __user * __user *)ptr))
+ return -EFAULT;
+
+ ptr += sizeof(void *);
+ list_for_each_entry(w, &proc->delivered_death, entry) {
+ struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
+ if (tmp_death->cookie == cookie) {
+ death = tmp_death;
+ break;
+ }
+ }
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
+ printk(KERN_INFO "binder: %d:%d BC_DEAD_BINDER_DONE %p found %p\n",
+ proc->pid, thread->pid, cookie, death);
+ if (death == NULL) {
+ binder_user_error("binder: %d:%d BC_DEAD"
+ "_BINDER_DONE %p not found\n",
+ proc->pid, thread->pid, cookie);
+ break;
+ }
+
+ list_del_init(&death->work.entry);
+ if (death->work.type == BINDER_WORK_DEAD_BINDER_AND_CLEAR) {
+ death->work.type = BINDER_WORK_CLEAR_DEATH_NOTIFICATION;
+ if (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED)) {
+ list_add_tail(&death->work.entry, &thread->todo);
+ } else {
+ list_add_tail(&death->work.entry, &proc->todo);
+ wake_up_interruptible(&proc->wait);
+ }
+ }
+ } break;
+
+ default:
+ printk(KERN_ERR "binder: %d:%d unknown command %d\n", proc->pid, thread->pid, cmd);
+ return -EINVAL;
+ }
+ *consumed = ptr - buffer;
+ }
+ return 0;
+}
+
+void
+binder_stat_br(struct binder_proc *proc, struct binder_thread *thread, uint32_t cmd)
+{
+ if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
+ binder_stats.br[_IOC_NR(cmd)]++;
+ proc->stats.br[_IOC_NR(cmd)]++;
+ thread->stats.br[_IOC_NR(cmd)]++;
+ }
+}
+
+static int
+binder_has_proc_work(struct binder_proc *proc, struct binder_thread *thread)
+{
+ return !list_empty(&proc->todo) || (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
+}
+
+static int
+binder_has_thread_work(struct binder_thread *thread)
+{
+ return !list_empty(&thread->todo) || thread->return_error != BR_OK ||
+ (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
+}
+
+static int
+binder_thread_read(struct binder_proc *proc, struct binder_thread *thread,
+ void __user *buffer, int size, signed long *consumed, int non_block)
+{
+ void __user *ptr = buffer + *consumed;
+ void __user *end = buffer + size;
+
+ int ret = 0;
+ int wait_for_proc_work;
+
+ if (*consumed == 0) {
+ if (put_user(BR_NOOP, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ }
+
+retry:
+ wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);
+
+ if (thread->return_error != BR_OK && ptr < end) {
+ if (thread->return_error2 != BR_OK) {
+ if (put_user(thread->return_error2, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (ptr == end)
+ goto done;
+ thread->return_error2 = BR_OK;
+ }
+ if (put_user(thread->return_error, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ thread->return_error = BR_OK;
+ goto done;
+ }
+
+
+ thread->looper |= BINDER_LOOPER_STATE_WAITING;
+ if (wait_for_proc_work)
+ proc->ready_threads++;
+ mutex_unlock(&binder_lock);
+ if (wait_for_proc_work) {
+ if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
+ BINDER_LOOPER_STATE_ENTERED))) {
+ binder_user_error("binder: %d:%d ERROR: Thread waiting "
+ "for process work before calling BC_REGISTER_"
+ "LOOPER or BC_ENTER_LOOPER (state %x)\n",
+ proc->pid, thread->pid, thread->looper);
+ wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
+ }
+ binder_set_nice(proc->default_priority);
+ if (non_block) {
+ if (!binder_has_proc_work(proc, thread))
+ ret = -EAGAIN;
+ } else
+ ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread));
+ } else {
+ if (non_block) {
+ if (!binder_has_thread_work(thread))
+ ret = -EAGAIN;
+ } else
+ ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));
+ }
+ mutex_lock(&binder_lock);
+ if (wait_for_proc_work)
+ proc->ready_threads--;
+ thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
+
+ if (ret)
+ return ret;
+
+ while (1) {
+ uint32_t cmd;
+ struct binder_transaction_data tr;
+ struct binder_work *w;
+ struct binder_transaction *t = NULL;
+
+ if (!list_empty(&thread->todo))
+ w = list_first_entry(&thread->todo, struct binder_work, entry);
+ else if (!list_empty(&proc->todo) && wait_for_proc_work)
+ w = list_first_entry(&proc->todo, struct binder_work, entry);
+ else {
+ if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
+ goto retry;
+ break;
+ }
+
+ if (end - ptr < sizeof(tr) + 4)
+ break;
+
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION: {
+ t = container_of(w, struct binder_transaction, work);
+ } break;
+ case BINDER_WORK_TRANSACTION_COMPLETE: {
+ cmd = BR_TRANSACTION_COMPLETE;
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+
+ binder_stat_br(proc, thread, cmd);
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION_COMPLETE)
+ printk(KERN_INFO "binder: %d:%d BR_TRANSACTION_COMPLETE\n",
+ proc->pid, thread->pid);
+
+ list_del(&w->entry);
+ kfree(w);
+ binder_stats.obj_deleted[BINDER_STAT_TRANSACTION_COMPLETE]++;
+ } break;
+ case BINDER_WORK_NODE: {
+ struct binder_node *node = container_of(w, struct binder_node, work);
+ uint32_t cmd = BR_NOOP;
+ const char *cmd_name;
+ int strong = node->internal_strong_refs || node->local_strong_refs;
+ int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
+ if (weak && !node->has_weak_ref) {
+ cmd = BR_INCREFS;
+ cmd_name = "BR_INCREFS";
+ node->has_weak_ref = 1;
+ node->pending_weak_ref = 1;
+ node->local_weak_refs++;
+ } else if (strong && !node->has_strong_ref) {
+ cmd = BR_ACQUIRE;
+ cmd_name = "BR_ACQUIRE";
+ node->has_strong_ref = 1;
+ node->pending_strong_ref = 1;
+ node->local_strong_refs++;
+ } else if (!strong && node->has_strong_ref) {
+ cmd = BR_RELEASE;
+ cmd_name = "BR_RELEASE";
+ node->has_strong_ref = 0;
+ } else if (!weak && node->has_weak_ref) {
+ cmd = BR_DECREFS;
+ cmd_name = "BR_DECREFS";
+ node->has_weak_ref = 0;
+ }
+ if (cmd != BR_NOOP) {
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (put_user(node->ptr, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ if (put_user(node->cookie, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+
+ binder_stat_br(proc, thread, cmd);
+ if (binder_debug_mask & BINDER_DEBUG_USER_REFS)
+ printk(KERN_INFO "binder: %d:%d %s %d u%p c%p\n",
+ proc->pid, thread->pid, cmd_name, node->debug_id, node->ptr, node->cookie);
+ } else {
+ list_del_init(&w->entry);
+ if (!weak && !strong) {
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: %d:%d node %d u%p c%p deleted\n",
+ proc->pid, thread->pid, node->debug_id, node->ptr, node->cookie);
+ rb_erase(&node->rb_node, &proc->nodes);
+ kfree(node);
+ binder_stats.obj_deleted[BINDER_STAT_NODE]++;
+ } else {
+ if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
+ printk(KERN_INFO "binder: %d:%d node %d u%p c%p state unchanged\n",
+ proc->pid, thread->pid, node->debug_id, node->ptr, node->cookie);
+ }
+ }
+ } break;
+ case BINDER_WORK_DEAD_BINDER:
+ case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+ case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+ struct binder_ref_death *death = container_of(w, struct binder_ref_death, work);
+ uint32_t cmd;
+ if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
+ cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
+ else
+ cmd = BR_DEAD_BINDER;
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (put_user(death->cookie, (void * __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(void *);
+ if (binder_debug_mask & BINDER_DEBUG_DEATH_NOTIFICATION)
+ printk(KERN_INFO "binder: %d:%d %s %p\n",
+ proc->pid, thread->pid,
+ cmd == BR_DEAD_BINDER ?
+ "BR_DEAD_BINDER" :
+ "BR_CLEAR_DEATH_NOTIFICATION_DONE",
+ death->cookie);
+
+ if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
+ list_del(&w->entry);
+ kfree(death);
+ binder_stats.obj_deleted[BINDER_STAT_DEATH]++;
+ } else
+ list_move(&w->entry, &proc->delivered_death);
+ if (cmd == BR_DEAD_BINDER)
+ goto done; /* DEAD_BINDER notifications can cause transactions */
+ } break;
+ }
+
+ if (!t)
+ continue;
+
+ BUG_ON(t->buffer == NULL);
+ if (t->buffer->target_node) {
+ struct binder_node *target_node = t->buffer->target_node;
+ tr.target.ptr = target_node->ptr;
+ tr.cookie = target_node->cookie;
+ t->saved_priority = task_nice(current);
+ if (t->priority < target_node->min_priority &&
+ !(t->flags & TF_ONE_WAY))
+ binder_set_nice(t->priority);
+ else if (!(t->flags & TF_ONE_WAY) ||
+ t->saved_priority > target_node->min_priority)
+ binder_set_nice(target_node->min_priority);
+ cmd = BR_TRANSACTION;
+ } else {
+ tr.target.ptr = NULL;
+ tr.cookie = NULL;
+ cmd = BR_REPLY;
+ }
+ tr.code = t->code;
+ tr.flags = t->flags;
+ tr.sender_euid = t->sender_euid;
+
+ if (t->from) {
+ struct task_struct *sender = t->from->proc->tsk;
+ tr.sender_pid = task_tgid_nr_ns(sender, current->nsproxy->pid_ns);
+ } else {
+ tr.sender_pid = 0;
+ }
+
+ tr.data_size = t->buffer->data_size;
+ tr.offsets_size = t->buffer->offsets_size;
+ tr.data.ptr.buffer = (void *)((void *)t->buffer->data + proc->user_buffer_offset);
+ tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));
+
+ if (put_user(cmd, (uint32_t __user *)ptr))
+ return -EFAULT;
+ ptr += sizeof(uint32_t);
+ if (copy_to_user(ptr, &tr, sizeof(tr)))
+ return -EFAULT;
+ ptr += sizeof(tr);
+
+ binder_stat_br(proc, thread, cmd);
+ if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)
+ printk(KERN_INFO "binder: %d:%d %s %d %d:%d, cmd %d"
+ "size %zd-%zd ptr %p-%p\n",
+ proc->pid, thread->pid,
+ (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : "BR_REPLY",
+ t->debug_id, t->from ? t->from->proc->pid : 0,
+ t->from ? t->from->pid : 0, cmd,
+ t->buffer->data_size, t->buffer->offsets_size,
+ tr.data.ptr.buffer, tr.data.ptr.offsets);
+
+ list_del(&t->work.entry);
+ t->buffer->allow_user_free = 1;
+ if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
+ t->to_parent = thread->transaction_stack;
+ t->to_thread = thread;
+ thread->transaction_stack = t;
+ } else {
+ t->buffer->transaction = NULL;
+ kfree(t);
+ binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++;
+ }
+ break;
+ }
+
+done:
+
+ *consumed = ptr - buffer;
+ if (proc->requested_threads + proc->ready_threads == 0 &&
+ proc->requested_threads_started < proc->max_threads &&
+ (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
+ BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
+ /*spawn a new thread if we leave this out */) {
+ proc->requested_threads++;
+ if (binder_debug_mask & BINDER_DEBUG_THREADS)
+ printk(KERN_INFO "binder: %d:%d BR_SPAWN_LOOPER\n",
+ proc->pid, thread->pid);
+ if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static void binder_release_work(struct list_head *list)
+{
+ struct binder_work *w;
+ while (!list_empty(list)) {
+ w = list_first_entry(list, struct binder_work, entry);
+ list_del_init(&w->entry);
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION: {
+ struct binder_transaction *t = container_of(w, struct binder_transaction, work);
+ if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+ binder_send_failed_reply(t, BR_DEAD_REPLY);
+ } break;
+ case BINDER_WORK_TRANSACTION_COMPLETE: {
+ kfree(w);
+ binder_stats.obj_deleted[BINDER_STAT_TRANSACTION_COMPLETE]++;
+ } break;
+ default:
+ break;
+ }
+ }
+
+}
+
+static struct binder_thread *binder_get_thread(struct binder_proc *proc)
+{
+ struct binder_thread *thread = NULL;
+ struct rb_node *parent = NULL;
+ struct rb_node **p = &proc->threads.rb_node;
+
+ while (*p) {
+ parent = *p;
+ thread = rb_entry(parent, struct binder_thread, rb_node);
+
+ if (current->pid < thread->pid)
+ p = &(*p)->rb_left;
+ else if (current->pid > thread->pid)
+ p = &(*p)->rb_right;
+ else
+ break;
+ }
+ if (*p == NULL) {
+ thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+ if (thread == NULL)
+ return NULL;
+ binder_stats.obj_created[BINDER_STAT_THREAD]++;
+ thread->proc = proc;
+ thread->pid = current->pid;
+ init_waitqueue_head(&thread->wait);
+ INIT_LIST_HEAD(&thread->todo);
+ rb_link_node(&thread->rb_node, parent, p);
+ rb_insert_color(&thread->rb_node, &proc->threads);
+ thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+ thread->return_error = BR_OK;
+ thread->return_error2 = BR_OK;
+ }
+ return thread;
+}
+
+static int binder_free_thread(struct binder_proc *proc, struct binder_thread *thread)
+{
+ struct binder_transaction *t;
+ struct binder_transaction *send_reply = NULL;
+ int active_transactions = 0;
+
+ rb_erase(&thread->rb_node, &proc->threads);
+ t = thread->transaction_stack;
+ if (t && t->to_thread == thread)
+ send_reply = t;
+ while (t) {
+ active_transactions++;
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_TRANSACTION)
+ printk(KERN_INFO "binder: release %d:%d transaction %d %s, still active\n",
+ proc->pid, thread->pid, t->debug_id, (t->to_thread == thread) ? "in" : "out");
+ if (t->to_thread == thread) {
+ t->to_proc = NULL;
+ t->to_thread = NULL;
+ if (t->buffer) {
+ t->buffer->transaction = NULL;
+ t->buffer = NULL;
+ }
+ t = t->to_parent;
+ } else if (t->from == thread) {
+ t->from = NULL;
+ t = t->from_parent;
+ } else
+ BUG();
+ }
+ if (send_reply)
+ binder_send_failed_reply(send_reply, BR_DEAD_REPLY);
+ binder_release_work(&thread->todo);
+ kfree(thread);
+ binder_stats.obj_deleted[BINDER_STAT_THREAD]++;
+ return active_transactions;
+}
+
+static unsigned int binder_poll(struct file *filp, struct poll_table_struct *wait)
+{
+ struct binder_proc *proc = filp->private_data;
+ struct binder_thread *thread = NULL;
+ int wait_for_proc_work;
+
+ mutex_lock(&binder_lock);
+ thread = binder_get_thread(proc);
+
+ wait_for_proc_work = thread->transaction_stack == NULL &&
+ list_empty(&thread->todo) && thread->return_error == BR_OK;
+ mutex_unlock(&binder_lock);
+
+ if (wait_for_proc_work) {
+ if (binder_has_proc_work(proc, thread))
+ return POLLIN;
+ poll_wait(filp, &proc->wait, wait);
+ if (binder_has_proc_work(proc, thread))
+ return POLLIN;
+ } else {
+ if (binder_has_thread_work(thread))
+ return POLLIN;
+ poll_wait(filp, &thread->wait, wait);
+ if (binder_has_thread_work(thread))
+ return POLLIN;
+ }
+ return 0;
+}
+
+static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int ret;
+ struct binder_proc *proc = filp->private_data;
+ struct binder_thread *thread;
+ unsigned int size = _IOC_SIZE(cmd);
+ void __user *ubuf = (void __user *)arg;
+
+ /*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
+
+ ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
+ if (ret)
+ return ret;
+
+ mutex_lock(&binder_lock);
+ thread = binder_get_thread(proc);
+ if (thread == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ switch (cmd) {
+ case BINDER_WRITE_READ: {
+ struct binder_write_read bwr;
+ if (size != sizeof(struct binder_write_read)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
+ ret = -EFAULT;
+ goto err;
+ }
+ if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)
+ printk(KERN_INFO "binder: %d:%d write %ld at %08lx, read %ld at %08lx\n",
+ proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer);
+ if (bwr.write_size > 0) {
+ ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed);
+ if (ret < 0) {
+ bwr.read_consumed = 0;
+ if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
+ ret = -EFAULT;
+ goto err;
+ }
+ }
+ if (bwr.read_size > 0) {
+ ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
+ if (!list_empty(&proc->todo))
+ wake_up_interruptible(&proc->wait);
+ if (ret < 0) {
+ if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
+ ret = -EFAULT;
+ goto err;
+ }
+ }
+ if (binder_debug_mask & BINDER_DEBUG_READ_WRITE)
+ printk(KERN_INFO "binder: %d:%d wrote %ld of %ld, read return %ld of %ld\n",
+ proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size);
+ if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
+ ret = -EFAULT;
+ goto err;
+ }
+ break;
+ }
+ case BINDER_SET_MAX_THREADS:
+ if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ case BINDER_SET_CONTEXT_MGR:
+ if (binder_context_mgr_node != NULL) {
+ printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
+ ret = -EBUSY;
+ goto err;
+ }
+ if (binder_context_mgr_uid != -1) {
+ if (binder_context_mgr_uid != current->cred->euid) {
+ printk(KERN_ERR "binder: BINDER_SET_"
+ "CONTEXT_MGR bad uid %d != %d\n",
+ current->cred->euid,
+ binder_context_mgr_uid);
+ ret = -EPERM;
+ goto err;
+ }
+ } else
+ binder_context_mgr_uid = current->cred->euid;
+ binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
+ if (binder_context_mgr_node == NULL) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ binder_context_mgr_node->local_weak_refs++;
+ binder_context_mgr_node->local_strong_refs++;
+ binder_context_mgr_node->has_strong_ref = 1;
+ binder_context_mgr_node->has_weak_ref = 1;
+ break;
+ case BINDER_THREAD_EXIT:
+ if (binder_debug_mask & BINDER_DEBUG_THREADS)
+ printk(KERN_INFO "binder: %d:%d exit\n",
+ proc->pid, thread->pid);
+ binder_free_thread(proc, thread);
+ thread = NULL;
+ break;
+ case BINDER_VERSION:
+ if (size != sizeof(struct binder_version)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
+ ret = 0;
+err:
+ if (thread)
+ thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
+ mutex_unlock(&binder_lock);
+ wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
+ if (ret && ret != -ERESTARTSYS)
+ printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
+ return ret;
+}
+
+static void binder_vma_open(struct vm_area_struct *vma)
+{
+ struct binder_proc *proc = vma->vm_private_data;
+ if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
+ printk(KERN_INFO "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot));
+ dump_stack();
+}
+static void binder_vma_close(struct vm_area_struct *vma)
+{
+ struct binder_proc *proc = vma->vm_private_data;
+ if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
+ printk(KERN_INFO "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot));
+ proc->vma = NULL;
+}
+
+static struct vm_operations_struct binder_vm_ops = {
+ .open = binder_vma_open,
+ .close = binder_vma_close,
+};
+
+static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ int ret;
+ struct vm_struct *area;
+ struct binder_proc *proc = filp->private_data;
+ const char *failure_string;
+ struct binder_buffer *buffer;
+
+ if ((vma->vm_end - vma->vm_start) > SZ_4M)
+ vma->vm_end = vma->vm_start + SZ_4M;
+
+ if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
+ printk(KERN_INFO "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, pgprot_val(vma->vm_page_prot));
+
+ if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
+ ret = -EPERM;
+ failure_string = "bad vm_flags";
+ goto err_bad_arg;
+ }
+ vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;
+
+ area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
+ if (area == NULL) {
+ ret = -ENOMEM;
+ failure_string = "get_vm_area";
+ goto err_get_vm_area_failed;
+ }
+ proc->buffer = area->addr;
+ proc->user_buffer_offset = vma->vm_start - (size_t)proc->buffer;
+
+#ifdef CONFIG_CPU_CACHE_VIPT
+ if (cache_is_vipt_aliasing()) {
+ while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) {
+ printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
+ vma->vm_start += PAGE_SIZE;
+ }
+ }
+#endif
+ proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
+ if (proc->pages == NULL) {
+ ret = -ENOMEM;
+ failure_string = "alloc page array";
+ goto err_alloc_pages_failed;
+ }
+ proc->buffer_size = vma->vm_end - vma->vm_start;
+
+ vma->vm_ops = &binder_vm_ops;
+ vma->vm_private_data = proc;
+
+ if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
+ ret = -ENOMEM;
+ failure_string = "alloc small buf";
+ goto err_alloc_small_buf_failed;
+ }
+ buffer = proc->buffer;
+ INIT_LIST_HEAD(&proc->buffers);
+ list_add(&buffer->entry, &proc->buffers);
+ buffer->free = 1;
+ binder_insert_free_buffer(proc, buffer);
+ proc->free_async_space = proc->buffer_size / 2;
+ barrier();
+ proc->vma = vma;
+
+ /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
+ return 0;
+
+err_alloc_small_buf_failed:
+ kfree(proc->pages);
+err_alloc_pages_failed:
+ vfree(proc->buffer);
+err_get_vm_area_failed:
+ mutex_unlock(&binder_lock);
+err_bad_arg:
+ printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
+ return ret;
+}
+
+static int binder_open(struct inode *nodp, struct file *filp)
+{
+ struct binder_proc *proc;
+
+ if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
+ printk(KERN_INFO "binder_open: %d:%d\n", current->group_leader->pid, current->pid);
+
+ proc = kzalloc(sizeof(*proc), GFP_KERNEL);
+ if (proc == NULL)
+ return -ENOMEM;
+ get_task_struct(current);
+ proc->tsk = current;
+ INIT_LIST_HEAD(&proc->todo);
+ init_waitqueue_head(&proc->wait);
+ proc->default_priority = task_nice(current);
+ mutex_lock(&binder_lock);
+ binder_stats.obj_created[BINDER_STAT_PROC]++;
+ hlist_add_head(&proc->proc_node, &binder_procs);
+ proc->pid = current->group_leader->pid;
+ INIT_LIST_HEAD(&proc->delivered_death);
+ filp->private_data = proc;
+ mutex_unlock(&binder_lock);
+
+ if (binder_proc_dir_entry_proc) {
+ char strbuf[11];
+ snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+ create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc);
+ }
+
+ return 0;
+}
+
+static int binder_flush(struct file *filp, fl_owner_t id)
+{
+ struct rb_node *n;
+ struct binder_proc *proc = filp->private_data;
+ int wake_count = 0;
+
+ mutex_lock(&binder_lock);
+ for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
+ struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
+ thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN;
+ if (thread->looper & BINDER_LOOPER_STATE_WAITING) {
+ wake_up_interruptible(&thread->wait);
+ wake_count++;
+ }
+ }
+ wake_up_interruptible_all(&proc->wait);
+ mutex_unlock(&binder_lock);
+
+ if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
+ printk(KERN_INFO "binder_flush: %d woke %d threads\n", proc->pid, wake_count);
+
+ return 0;
+}
+
+static int binder_release(struct inode *nodp, struct file *filp)
+{
+ struct hlist_node *pos;
+ struct binder_transaction *t;
+ struct rb_node *n;
+ struct binder_proc *proc = filp->private_data;
+ int threads, nodes, incoming_refs, outgoing_refs, buffers, active_transactions, page_count;
+
+ if (binder_proc_dir_entry_proc) {
+ char strbuf[11];
+ snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
+ remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
+ }
+ mutex_lock(&binder_lock);
+ hlist_del(&proc->proc_node);
+ if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
+ printk(KERN_INFO "binder_release: %d context_mgr_node gone\n", proc->pid);
+ binder_context_mgr_node = NULL;
+ }
+
+ threads = 0;
+ active_transactions = 0;
+ while ((n = rb_first(&proc->threads))) {
+ struct binder_thread *thread = rb_entry(n, struct binder_thread, rb_node);
+ threads++;
+ active_transactions += binder_free_thread(proc, thread);
+ }
+ nodes = 0;
+ incoming_refs = 0;
+ while ((n = rb_first(&proc->nodes))) {
+ struct binder_node *node = rb_entry(n, struct binder_node, rb_node);
+
+ nodes++;
+ rb_erase(&node->rb_node, &proc->nodes);
+ list_del_init(&node->work.entry);
+ if (hlist_empty(&node->refs)) {
+ kfree(node);
+ binder_stats.obj_deleted[BINDER_STAT_NODE]++;
+ } else {
+ struct binder_ref *ref;
+ int death = 0;
+
+ node->proc = NULL;
+ node->local_strong_refs = 0;
+ node->local_weak_refs = 0;
+ hlist_add_head(&node->dead_node, &binder_dead_nodes);
+
+ hlist_for_each_entry(ref, pos, &node->refs, node_entry) {
+ incoming_refs++;
+ if (ref->death) {
+ death++;
+ if (list_empty(&ref->death->work.entry)) {
+ ref->death->work.type = BINDER_WORK_DEAD_BINDER;
+ list_add_tail(&ref->death->work.entry, &ref->proc->todo);
+ wake_up_interruptible(&ref->proc->wait);
+ } else
+ BUG();
+ }
+ }
+ if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
+ printk(KERN_INFO "binder: node %d now dead, refs %d, death %d\n", node->debug_id, incoming_refs, death);
+ }
+ }
+ outgoing_refs = 0;
+ while ((n = rb_first(&proc->refs_by_desc))) {
+ struct binder_ref *ref = rb_entry(n, struct binder_ref, rb_node_desc);
+ outgoing_refs++;
+ binder_delete_ref(ref);
+ }
+ binder_release_work(&proc->todo);
+ buffers = 0;
+
+ while ((n = rb_first(&proc->allocated_buffers))) {
+ struct binder_buffer *buffer = rb_entry(n, struct binder_buffer, rb_node);
+ t = buffer->transaction;
+ if (t) {
+ t->buffer = NULL;
+ buffer->transaction = NULL;
+ printk(KERN_ERR "binder: release proc %d, transaction %d, not freed\n", proc->pid, t->debug_id);
+ /*BUG();*/
+ }
+ binder_free_buf(proc, buffer);
+ buffers++;
+ }
+
+ binder_stats.obj_deleted[BINDER_STAT_PROC]++;
+ mutex_unlock(&binder_lock);
+
+ page_count = 0;
+ if (proc->pages) {
+ int i;
+ for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
+ if (proc->pages[i]) {
+ if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
+ printk(KERN_INFO "binder_release: %d: page %d at %p not freed\n", proc->pid, i, proc->buffer + i * PAGE_SIZE);
+ __free_page(proc->pages[i]);
+ page_count++;
+ }
+ }
+ kfree(proc->pages);
+ vfree(proc->buffer);
+ }
+
+ put_task_struct(proc->tsk);
+
+ if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
+ printk(KERN_INFO "binder_release: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
+ proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count);
+
+ kfree(proc);
+ return 0;
+}
+
+static char *print_binder_transaction(char *buf, char *end, const char *prefix, struct binder_transaction *t)
+{
+ buf += snprintf(buf, end - buf, "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
+ prefix, t->debug_id, t, t->from ? t->from->proc->pid : 0,
+ t->from ? t->from->pid : 0,
+ t->to_proc ? t->to_proc->pid : 0,
+ t->to_thread ? t->to_thread->pid : 0,
+ t->code, t->flags, t->priority, t->need_reply);
+ if (buf >= end)
+ return buf;
+ if (t->buffer == NULL) {
+ buf += snprintf(buf, end - buf, " buffer free\n");
+ return buf;
+ }
+ if (t->buffer->target_node) {
+ buf += snprintf(buf, end - buf, " node %d",
+ t->buffer->target_node->debug_id);
+ if (buf >= end)
+ return buf;
+ }
+ buf += snprintf(buf, end - buf, " size %zd:%zd data %p\n",
+ t->buffer->data_size, t->buffer->offsets_size,
+ t->buffer->data);
+ return buf;
+}
+
+static char *print_binder_buffer(char *buf, char *end, const char *prefix, struct binder_buffer *buffer)
+{
+ buf += snprintf(buf, end - buf, "%s %d: %p size %zd:%zd %s\n",
+ prefix, buffer->debug_id, buffer->data,
+ buffer->data_size, buffer->offsets_size,
+ buffer->transaction ? "active" : "delivered");
+ return buf;
+}
+
+static char *print_binder_work(char *buf, char *end, const char *prefix,
+ const char *transaction_prefix, struct binder_work *w)
+{
+ struct binder_node *node;
+ struct binder_transaction *t;
+
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION:
+ t = container_of(w, struct binder_transaction, work);
+ buf = print_binder_transaction(buf, end, transaction_prefix, t);
+ break;
+ case BINDER_WORK_TRANSACTION_COMPLETE:
+ buf += snprintf(buf, end - buf,
+ "%stransaction complete\n", prefix);
+ break;
+ case BINDER_WORK_NODE:
+ node = container_of(w, struct binder_node, work);
+ buf += snprintf(buf, end - buf, "%snode work %d: u%p c%p\n",
+ prefix, node->debug_id, node->ptr, node->cookie);
+ break;
+ case BINDER_WORK_DEAD_BINDER:
+ buf += snprintf(buf, end - buf, "%shas dead binder\n", prefix);
+ break;
+ case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+ buf += snprintf(buf, end - buf,
+ "%shas cleared dead binder\n", prefix);
+ break;
+ case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
+ buf += snprintf(buf, end - buf,
+ "%shas cleared death notification\n", prefix);
+ break;
+ default:
+ buf += snprintf(buf, end - buf, "%sunknown work: type %d\n",
+ prefix, w->type);
+ break;
+ }
+ return buf;
+}
+
+static char *print_binder_thread(char *buf, char *end, struct binder_thread *thread, int print_always)
+{
+ struct binder_transaction *t;
+ struct binder_work *w;
+ char *start_buf = buf;
+ char *header_buf;
+
+ buf += snprintf(buf, end - buf, " thread %d: l %02x\n", thread->pid, thread->looper);
+ header_buf = buf;
+ t = thread->transaction_stack;
+ while (t) {
+ if (buf >= end)
+ break;
+ if (t->from == thread) {
+ buf = print_binder_transaction(buf, end, " outgoing transaction", t);
+ t = t->from_parent;
+ } else if (t->to_thread == thread) {
+ buf = print_binder_transaction(buf, end, " incoming transaction", t);
+ t = t->to_parent;
+ } else {
+ buf = print_binder_transaction(buf, end, " bad transaction", t);
+ t = NULL;
+ }
+ }
+ list_for_each_entry(w, &thread->todo, entry) {
+ if (buf >= end)
+ break;
+ buf = print_binder_work(buf, end, " ",
+ " pending transaction", w);
+ }
+ if (!print_always && buf == header_buf)
+ buf = start_buf;
+ return buf;
+}
+
+static char *print_binder_node(char *buf, char *end, struct binder_node *node)
+{
+ struct binder_ref *ref;
+ struct hlist_node *pos;
+ struct binder_work *w;
+ int count;
+ count = 0;
+ hlist_for_each_entry(ref, pos, &node->refs, node_entry)
+ count++;
+
+ buf += snprintf(buf, end - buf, " node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d",
+ node->debug_id, node->ptr, node->cookie,
+ node->has_strong_ref, node->has_weak_ref,
+ node->local_strong_refs, node->local_weak_refs,
+ node->internal_strong_refs, count);
+ if (buf >= end)
+ return buf;
+ if (count) {
+ buf += snprintf(buf, end - buf, " proc");
+ if (buf >= end)
+ return buf;
+ hlist_for_each_entry(ref, pos, &node->refs, node_entry) {
+ buf += snprintf(buf, end - buf, " %d", ref->proc->pid);
+ if (buf >= end)
+ return buf;
+ }
+ }
+ buf += snprintf(buf, end - buf, "\n");
+ list_for_each_entry(w, &node->async_todo, entry) {
+ if (buf >= end)
+ break;
+ buf = print_binder_work(buf, end, " ",
+ " pending async transaction", w);
+ }
+ return buf;
+}
+
+static char *print_binder_ref(char *buf, char *end, struct binder_ref *ref)
+{
+ buf += snprintf(buf, end - buf, " ref %d: desc %d %snode %d s %d w %d d %p\n",
+ ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ",
+ ref->node->debug_id, ref->strong, ref->weak, ref->death);
+ return buf;
+}
+
+static char *print_binder_proc(char *buf, char *end, struct binder_proc *proc, int print_all)
+{
+ struct binder_work *w;
+ struct rb_node *n;
+ char *start_buf = buf;
+ char *header_buf;
+
+ buf += snprintf(buf, end - buf, "proc %d\n", proc->pid);
+ header_buf = buf;
+
+ for (n = rb_first(&proc->threads); n != NULL && buf < end; n = rb_next(n))
+ buf = print_binder_thread(buf, end, rb_entry(n, struct binder_thread, rb_node), print_all);
+ for (n = rb_first(&proc->nodes); n != NULL && buf < end; n = rb_next(n)) {
+ struct binder_node *node = rb_entry(n, struct binder_node, rb_node);
+ if (print_all || node->has_async_transaction)
+ buf = print_binder_node(buf, end, node);
+ }
+ if (print_all) {
+ for (n = rb_first(&proc->refs_by_desc); n != NULL && buf < end; n = rb_next(n))
+ buf = print_binder_ref(buf, end, rb_entry(n, struct binder_ref, rb_node_desc));
+ }
+ for (n = rb_first(&proc->allocated_buffers); n != NULL && buf < end; n = rb_next(n))
+ buf = print_binder_buffer(buf, end, " buffer", rb_entry(n, struct binder_buffer, rb_node));
+ list_for_each_entry(w, &proc->todo, entry) {
+ if (buf >= end)
+ break;
+ buf = print_binder_work(buf, end, " ",
+ " pending transaction", w);
+ }
+ list_for_each_entry(w, &proc->delivered_death, entry) {
+ if (buf >= end)
+ break;
+ buf += snprintf(buf, end - buf, " has delivered dead binder\n");
+ break;
+ }
+ if (!print_all && buf == header_buf)
+ buf = start_buf;
+ return buf;
+}
+
+static const char *binder_return_strings[] = {
+ "BR_ERROR",
+ "BR_OK",
+ "BR_TRANSACTION",
+ "BR_REPLY",
+ "BR_ACQUIRE_RESULT",
+ "BR_DEAD_REPLY",
+ "BR_TRANSACTION_COMPLETE",
+ "BR_INCREFS",
+ "BR_ACQUIRE",
+ "BR_RELEASE",
+ "BR_DECREFS",
+ "BR_ATTEMPT_ACQUIRE",
+ "BR_NOOP",
+ "BR_SPAWN_LOOPER",
+ "BR_FINISHED",
+ "BR_DEAD_BINDER",
+ "BR_CLEAR_DEATH_NOTIFICATION_DONE",
+ "BR_FAILED_REPLY"
+};
+
+static const char *binder_command_strings[] = {
+ "BC_TRANSACTION",
+ "BC_REPLY",
+ "BC_ACQUIRE_RESULT",
+ "BC_FREE_BUFFER",
+ "BC_INCREFS",
+ "BC_ACQUIRE",
+ "BC_RELEASE",
+ "BC_DECREFS",
+ "BC_INCREFS_DONE",
+ "BC_ACQUIRE_DONE",
+ "BC_ATTEMPT_ACQUIRE",
+ "BC_REGISTER_LOOPER",
+ "BC_ENTER_LOOPER",
+ "BC_EXIT_LOOPER",
+ "BC_REQUEST_DEATH_NOTIFICATION",
+ "BC_CLEAR_DEATH_NOTIFICATION",
+ "BC_DEAD_BINDER_DONE"
+};
+
+static const char *binder_objstat_strings[] = {
+ "proc",
+ "thread",
+ "node",
+ "ref",
+ "death",
+ "transaction",
+ "transaction_complete"
+};
+
+static char *print_binder_stats(char *buf, char *end, const char *prefix, struct binder_stats *stats)
+{
+ int i;
+
+ BUILD_BUG_ON(ARRAY_SIZE(stats->bc) != ARRAY_SIZE(binder_command_strings));
+ for (i = 0; i < ARRAY_SIZE(stats->bc); i++) {
+ if (stats->bc[i])
+ buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix,
+ binder_command_strings[i], stats->bc[i]);
+ if (buf >= end)
+ return buf;
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(stats->br) != ARRAY_SIZE(binder_return_strings));
+ for (i = 0; i < ARRAY_SIZE(stats->br); i++) {
+ if (stats->br[i])
+ buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix,
+ binder_return_strings[i], stats->br[i]);
+ if (buf >= end)
+ return buf;
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != ARRAY_SIZE(binder_objstat_strings));
+ BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != ARRAY_SIZE(stats->obj_deleted));
+ for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) {
+ if (stats->obj_created[i] || stats->obj_deleted[i])
+ buf += snprintf(buf, end - buf, "%s%s: active %d total %d\n", prefix,
+ binder_objstat_strings[i],
+ stats->obj_created[i] - stats->obj_deleted[i],
+ stats->obj_created[i]);
+ if (buf >= end)
+ return buf;
+ }
+ return buf;
+}
+
+static char *print_binder_proc_stats(char *buf, char *end, struct binder_proc *proc)
+{
+ struct binder_work *w;
+ struct rb_node *n;
+ int count, strong, weak;
+
+ buf += snprintf(buf, end - buf, "proc %d\n", proc->pid);
+ if (buf >= end)
+ return buf;
+ count = 0;
+ for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
+ count++;
+ buf += snprintf(buf, end - buf, " threads: %d\n", count);
+ if (buf >= end)
+ return buf;
+ buf += snprintf(buf, end - buf, " requested threads: %d+%d/%d\n"
+ " ready threads %d\n"
+ " free async space %zd\n", proc->requested_threads,
+ proc->requested_threads_started, proc->max_threads,
+ proc->ready_threads, proc->free_async_space);
+ if (buf >= end)
+ return buf;
+ count = 0;
+ for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
+ count++;
+ buf += snprintf(buf, end - buf, " nodes: %d\n", count);
+ if (buf >= end)
+ return buf;
+ count = 0;
+ strong = 0;
+ weak = 0;
+ for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
+ struct binder_ref *ref = rb_entry(n, struct binder_ref, rb_node_desc);
+ count++;
+ strong += ref->strong;
+ weak += ref->weak;
+ }
+ buf += snprintf(buf, end - buf, " refs: %d s %d w %d\n", count, strong, weak);
+ if (buf >= end)
+ return buf;
+
+ count = 0;
+ for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n))
+ count++;
+ buf += snprintf(buf, end - buf, " buffers: %d\n", count);
+ if (buf >= end)
+ return buf;
+
+ count = 0;
+ list_for_each_entry(w, &proc->todo, entry) {
+ switch (w->type) {
+ case BINDER_WORK_TRANSACTION:
+ count++;
+ break;
+ default:
+ break;
+ }
+ }
+ buf += snprintf(buf, end - buf, " pending transactions: %d\n", count);
+ if (buf >= end)
+ return buf;
+
+ buf = print_binder_stats(buf, end, " ", &proc->stats);
+
+ return buf;
+}
+
+
+static int binder_read_proc_state(
+ char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ struct binder_proc *proc;
+ struct hlist_node *pos;
+ struct binder_node *node;
+ int len = 0;
+ char *buf = page;
+ char *end = page + PAGE_SIZE;
+ int do_lock = !binder_debug_no_lock;
+
+ if (off)
+ return 0;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+
+ buf += snprintf(buf, end - buf, "binder state:\n");
+
+ if (!hlist_empty(&binder_dead_nodes))
+ buf += snprintf(buf, end - buf, "dead nodes:\n");
+ hlist_for_each_entry(node, pos, &binder_dead_nodes, dead_node) {
+ if (buf >= end)
+ break;
+ buf = print_binder_node(buf, end, node);
+ }
+
+ hlist_for_each_entry(proc, pos, &binder_procs, proc_node) {
+ if (buf >= end)
+ break;
+ buf = print_binder_proc(buf, end, proc, 1);
+ }
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+ if (buf > page + PAGE_SIZE)
+ buf = page + PAGE_SIZE;
+
+ *start = page + off;
+
+ len = buf - page;
+ if (len > off)
+ len -= off;
+ else
+ len = 0;
+
+ return len < count ? len : count;
+}
+
+static int binder_read_proc_stats(
+ char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ struct binder_proc *proc;
+ struct hlist_node *pos;
+ int len = 0;
+ char *p = page;
+ int do_lock = !binder_debug_no_lock;
+
+ if (off)
+ return 0;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+
+ p += snprintf(p, PAGE_SIZE, "binder stats:\n");
+
+ p = print_binder_stats(p, page + PAGE_SIZE, "", &binder_stats);
+
+ hlist_for_each_entry(proc, pos, &binder_procs, proc_node) {
+ if (p >= page + PAGE_SIZE)
+ break;
+ p = print_binder_proc_stats(p, page + PAGE_SIZE, proc);
+ }
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+ if (p > page + PAGE_SIZE)
+ p = page + PAGE_SIZE;
+
+ *start = page + off;
+
+ len = p - page;
+ if (len > off)
+ len -= off;
+ else
+ len = 0;
+
+ return len < count ? len : count;
+}
+
+static int binder_read_proc_transactions(
+ char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ struct binder_proc *proc;
+ struct hlist_node *pos;
+ int len = 0;
+ char *buf = page;
+ char *end = page + PAGE_SIZE;
+ int do_lock = !binder_debug_no_lock;
+
+ if (off)
+ return 0;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+
+ buf += snprintf(buf, end - buf, "binder transactions:\n");
+ hlist_for_each_entry(proc, pos, &binder_procs, proc_node) {
+ if (buf >= end)
+ break;
+ buf = print_binder_proc(buf, end, proc, 0);
+ }
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+ if (buf > page + PAGE_SIZE)
+ buf = page + PAGE_SIZE;
+
+ *start = page + off;
+
+ len = buf - page;
+ if (len > off)
+ len -= off;
+ else
+ len = 0;
+
+ return len < count ? len : count;
+}
+
+static int binder_read_proc_proc(
+ char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ struct binder_proc *proc = data;
+ int len = 0;
+ char *p = page;
+ int do_lock = !binder_debug_no_lock;
+
+ if (off)
+ return 0;
+
+ if (do_lock)
+ mutex_lock(&binder_lock);
+ p += snprintf(p, PAGE_SIZE, "binder proc state:\n");
+ p = print_binder_proc(p, page + PAGE_SIZE, proc, 1);
+ if (do_lock)
+ mutex_unlock(&binder_lock);
+
+ if (p > page + PAGE_SIZE)
+ p = page + PAGE_SIZE;
+ *start = page + off;
+
+ len = p - page;
+ if (len > off)
+ len -= off;
+ else
+ len = 0;
+
+ return len < count ? len : count;
+}
+
+static char *print_binder_transaction_log_entry(char *buf, char *end, struct binder_transaction_log_entry *e)
+{
+ buf += snprintf(buf, end - buf, "%d: %s from %d:%d to %d:%d node %d handle %d size %d:%d\n",
+ e->debug_id, (e->call_type == 2) ? "reply" :
+ ((e->call_type == 1) ? "async" : "call "), e->from_proc,
+ e->from_thread, e->to_proc, e->to_thread, e->to_node,
+ e->target_handle, e->data_size, e->offsets_size);
+ return buf;
+}
+
+static int binder_read_proc_transaction_log(
+ char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ struct binder_transaction_log *log = data;
+ int len = 0;
+ int i;
+ char *buf = page;
+ char *end = page + PAGE_SIZE;
+
+ if (off)
+ return 0;
+
+ if (log->full) {
+ for (i = log->next; i < ARRAY_SIZE(log->entry); i++) {
+ if (buf >= end)
+ break;
+ buf = print_binder_transaction_log_entry(buf, end, &log->entry[i]);
+ }
+ }
+ for (i = 0; i < log->next; i++) {
+ if (buf >= end)
+ break;
+ buf = print_binder_transaction_log_entry(buf, end, &log->entry[i]);
+ }
+
+ *start = page + off;
+
+ len = buf - page;
+ if (len > off)
+ len -= off;
+ else
+ len = 0;
+
+ return len < count ? len : count;
+}
+
+static struct file_operations binder_fops = {
+ .owner = THIS_MODULE,
+ .poll = binder_poll,
+ .unlocked_ioctl = binder_ioctl,
+ .mmap = binder_mmap,
+ .open = binder_open,
+ .flush = binder_flush,
+ .release = binder_release,
+};
+
+static struct miscdevice binder_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "binder",
+ .fops = &binder_fops
+};
+
+static int __init binder_init(void)
+{
+ int ret;
+
+ binder_proc_dir_entry_root = proc_mkdir("binder", NULL);
+ if (binder_proc_dir_entry_root)
+ binder_proc_dir_entry_proc = proc_mkdir("proc", binder_proc_dir_entry_root);
+ ret = misc_register(&binder_miscdev);
+ if (binder_proc_dir_entry_root) {
+ create_proc_read_entry("state", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_state, NULL);
+ create_proc_read_entry("stats", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_stats, NULL);
+ create_proc_read_entry("transactions", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transactions, NULL);
+ create_proc_read_entry("transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log);
+ create_proc_read_entry("failed_transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log_failed);
+ }
+ return ret;
+}
+
+device_initcall(binder_init);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h
new file mode 100644
index 000000000000..863ae1ad5d55
--- /dev/null
+++ b/drivers/staging/android/binder.h
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * Based on, but no longer compatible with, the original
+ * OpenBinder.org binder driver interface, which is:
+ *
+ * Copyright (c) 2005 Palmsource, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_BINDER_H
+#define _LINUX_BINDER_H
+
+#include <linux/ioctl.h>
+
+#define B_PACK_CHARS(c1, c2, c3, c4) \
+ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
+#define B_TYPE_LARGE 0x85
+
+enum {
+ BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
+ BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
+ BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
+ BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
+ BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
+};
+
+enum {
+ FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
+ FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
+};
+
+/*
+ * This is the flattened representation of a Binder object for transfer
+ * between processes. The 'offsets' supplied as part of a binder transaction
+ * contains offsets into the data where these structures occur. The Binder
+ * driver takes care of re-writing the structure type and data as it moves
+ * between processes.
+ */
+struct flat_binder_object {
+ /* 8 bytes for large_flat_header. */
+ unsigned long type;
+ unsigned long flags;
+
+ /* 8 bytes of data. */
+ union {
+ void *binder; /* local object */
+ signed long handle; /* remote object */
+ };
+
+ /* extra data associated with local object */
+ void *cookie;
+};
+
+/*
+ * On 64-bit platforms where user code may run in 32-bits the driver must
+ * translate the buffer (and local binder) addresses apropriately.
+ */
+
+struct binder_write_read {
+ signed long write_size; /* bytes to write */
+ signed long write_consumed; /* bytes consumed by driver */
+ unsigned long write_buffer;
+ signed long read_size; /* bytes to read */
+ signed long read_consumed; /* bytes consumed by driver */
+ unsigned long read_buffer;
+};
+
+/* Use with BINDER_VERSION, driver fills in fields. */
+struct binder_version {
+ /* driver protocol version -- increment with incompatible change */
+ signed long protocol_version;
+};
+
+/* This is the current protocol version. */
+#define BINDER_CURRENT_PROTOCOL_VERSION 7
+
+#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
+#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, int64_t)
+#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t)
+#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int)
+#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
+#define BINDER_THREAD_EXIT _IOW('b', 8, int)
+#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
+
+/*
+ * NOTE: Two special error codes you should check for when calling
+ * in to the driver are:
+ *
+ * EINTR -- The operation has been interupted. This should be
+ * handled by retrying the ioctl() until a different error code
+ * is returned.
+ *
+ * ECONNREFUSED -- The driver is no longer accepting operations
+ * from your process. That is, the process is being destroyed.
+ * You should handle this by exiting from your process. Note
+ * that once this error code is returned, all further calls to
+ * the driver from any thread will return this same code.
+ */
+
+enum transaction_flags {
+ TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */
+ TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */
+ TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
+ TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
+};
+
+struct binder_transaction_data {
+ /* The first two are only used for bcTRANSACTION and brTRANSACTION,
+ * identifying the target and contents of the transaction.
+ */
+ union {
+ size_t handle; /* target descriptor of command transaction */
+ void *ptr; /* target descriptor of return transaction */
+ } target;
+ void *cookie; /* target object cookie */
+ unsigned int code; /* transaction command */
+
+ /* General information about the transaction. */
+ unsigned int flags;
+ pid_t sender_pid;
+ uid_t sender_euid;
+ size_t data_size; /* number of bytes of data */
+ size_t offsets_size; /* number of bytes of offsets */
+
+ /* If this transaction is inline, the data immediately
+ * follows here; otherwise, it ends with a pointer to
+ * the data buffer.
+ */
+ union {
+ struct {
+ /* transaction data */
+ const void *buffer;
+ /* offsets from buffer to flat_binder_object structs */
+ const void *offsets;
+ } ptr;
+ uint8_t buf[8];
+ } data;
+};
+
+struct binder_ptr_cookie {
+ void *ptr;
+ void *cookie;
+};
+
+struct binder_pri_desc {
+ int priority;
+ int desc;
+};
+
+struct binder_pri_ptr_cookie {
+ int priority;
+ void *ptr;
+ void *cookie;
+};
+
+enum BinderDriverReturnProtocol {
+ BR_ERROR = _IOR('r', 0, int),
+ /*
+ * int: error code
+ */
+
+ BR_OK = _IO('r', 1),
+ /* No parameters! */
+
+ BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
+ BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
+ /*
+ * binder_transaction_data: the received command.
+ */
+
+ BR_ACQUIRE_RESULT = _IOR('r', 4, int),
+ /*
+ * not currently supported
+ * int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
+ * Else the remote object has acquired a primary reference.
+ */
+
+ BR_DEAD_REPLY = _IO('r', 5),
+ /*
+ * The target of the last transaction (either a bcTRANSACTION or
+ * a bcATTEMPT_ACQUIRE) is no longer with us. No parameters.
+ */
+
+ BR_TRANSACTION_COMPLETE = _IO('r', 6),
+ /*
+ * No parameters... always refers to the last transaction requested
+ * (including replies). Note that this will be sent even for
+ * asynchronous transactions.
+ */
+
+ BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
+ BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
+ BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
+ BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie for binder
+ */
+
+ BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
+ /*
+ * not currently supported
+ * int: priority
+ * void *: ptr to binder
+ * void *: cookie for binder
+ */
+
+ BR_NOOP = _IO('r', 12),
+ /*
+ * No parameters. Do nothing and examine the next command. It exists
+ * primarily so that we can replace it with a BR_SPAWN_LOOPER command.
+ */
+
+ BR_SPAWN_LOOPER = _IO('r', 13),
+ /*
+ * No parameters. The driver has determined that a process has no
+ * threads waiting to service incomming transactions. When a process
+ * receives this command, it must spawn a new service thread and
+ * register it via bcENTER_LOOPER.
+ */
+
+ BR_FINISHED = _IO('r', 14),
+ /*
+ * not currently supported
+ * stop threadpool thread
+ */
+
+ BR_DEAD_BINDER = _IOR('r', 15, void *),
+ /*
+ * void *: cookie
+ */
+ BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
+ /*
+ * void *: cookie
+ */
+
+ BR_FAILED_REPLY = _IO('r', 17),
+ /*
+ * The the last transaction (either a bcTRANSACTION or
+ * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters.
+ */
+};
+
+enum BinderDriverCommandProtocol {
+ BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data),
+ BC_REPLY = _IOW('c', 1, struct binder_transaction_data),
+ /*
+ * binder_transaction_data: the sent command.
+ */
+
+ BC_ACQUIRE_RESULT = _IOW('c', 2, int),
+ /*
+ * not currently supported
+ * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful.
+ * Else you have acquired a primary reference on the object.
+ */
+
+ BC_FREE_BUFFER = _IOW('c', 3, int),
+ /*
+ * void *: ptr to transaction data received on a read
+ */
+
+ BC_INCREFS = _IOW('c', 4, int),
+ BC_ACQUIRE = _IOW('c', 5, int),
+ BC_RELEASE = _IOW('c', 6, int),
+ BC_DECREFS = _IOW('c', 7, int),
+ /*
+ * int: descriptor
+ */
+
+ BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
+ BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie for binder
+ */
+
+ BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
+ /*
+ * not currently supported
+ * int: priority
+ * int: descriptor
+ */
+
+ BC_REGISTER_LOOPER = _IO('c', 11),
+ /*
+ * No parameters.
+ * Register a spawned looper thread with the device.
+ */
+
+ BC_ENTER_LOOPER = _IO('c', 12),
+ BC_EXIT_LOOPER = _IO('c', 13),
+ /*
+ * No parameters.
+ * These two commands are sent as an application-level thread
+ * enters and exits the binder loop, respectively. They are
+ * used so the binder can have an accurate count of the number
+ * of looping threads it has available.
+ */
+
+ BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie
+ */
+
+ BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
+ /*
+ * void *: ptr to binder
+ * void *: cookie
+ */
+
+ BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
+ /*
+ * void *: cookie
+ */
+};
+
+#endif /* _LINUX_BINDER_H */
+
diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c
new file mode 100644
index 000000000000..ab32003ecd0b
--- /dev/null
+++ b/drivers/staging/android/logger.c
@@ -0,0 +1,607 @@
+/*
+ * drivers/misc/logger.c
+ *
+ * A Logging Subsystem
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * Robert Love <rlove@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/time.h>
+#include "logger.h"
+
+#include <asm/ioctls.h>
+
+/*
+ * struct logger_log - represents a specific log, such as 'main' or 'radio'
+ *
+ * This structure lives from module insertion until module removal, so it does
+ * not need additional reference counting. The structure is protected by the
+ * mutex 'mutex'.
+ */
+struct logger_log {
+ unsigned char * buffer; /* the ring buffer itself */
+ struct miscdevice misc; /* misc device representing the log */
+ wait_queue_head_t wq; /* wait queue for readers */
+ struct list_head readers; /* this log's readers */
+ struct mutex mutex; /* mutex protecting buffer */
+ size_t w_off; /* current write head offset */
+ size_t head; /* new readers start here */
+ size_t size; /* size of the log */
+};
+
+/*
+ * struct logger_reader - a logging device open for reading
+ *
+ * This object lives from open to release, so we don't need additional
+ * reference counting. The structure is protected by log->mutex.
+ */
+struct logger_reader {
+ struct logger_log * log; /* associated log */
+ struct list_head list; /* entry in logger_log's list */
+ size_t r_off; /* current read head offset */
+};
+
+/* logger_offset - returns index 'n' into the log via (optimized) modulus */
+#define logger_offset(n) ((n) & (log->size - 1))
+
+/*
+ * file_get_log - Given a file structure, return the associated log
+ *
+ * This isn't aesthetic. We have several goals:
+ *
+ * 1) Need to quickly obtain the associated log during an I/O operation
+ * 2) Readers need to maintain state (logger_reader)
+ * 3) Writers need to be very fast (open() should be a near no-op)
+ *
+ * In the reader case, we can trivially go file->logger_reader->logger_log.
+ * For a writer, we don't want to maintain a logger_reader, so we just go
+ * file->logger_log. Thus what file->private_data points at depends on whether
+ * or not the file was opened for reading. This function hides that dirtiness.
+ */
+static inline struct logger_log * file_get_log(struct file *file)
+{
+ if (file->f_mode & FMODE_READ) {
+ struct logger_reader *reader = file->private_data;
+ return reader->log;
+ } else
+ return file->private_data;
+}
+
+/*
+ * get_entry_len - Grabs the length of the payload of the next entry starting
+ * from 'off'.
+ *
+ * Caller needs to hold log->mutex.
+ */
+static __u32 get_entry_len(struct logger_log *log, size_t off)
+{
+ __u16 val;
+
+ switch (log->size - off) {
+ case 1:
+ memcpy(&val, log->buffer + off, 1);
+ memcpy(((char *) &val) + 1, log->buffer, 1);
+ break;
+ default:
+ memcpy(&val, log->buffer + off, 2);
+ }
+
+ return sizeof(struct logger_entry) + val;
+}
+
+/*
+ * do_read_log_to_user - reads exactly 'count' bytes from 'log' into the
+ * user-space buffer 'buf'. Returns 'count' on success.
+ *
+ * Caller must hold log->mutex.
+ */
+static ssize_t do_read_log_to_user(struct logger_log *log,
+ struct logger_reader *reader,
+ char __user *buf,
+ size_t count)
+{
+ size_t len;
+
+ /*
+ * We read from the log in two disjoint operations. First, we read from
+ * the current read head offset up to 'count' bytes or to the end of
+ * the log, whichever comes first.
+ */
+ len = min(count, log->size - reader->r_off);
+ if (copy_to_user(buf, log->buffer + reader->r_off, len))
+ return -EFAULT;
+
+ /*
+ * Second, we read any remaining bytes, starting back at the head of
+ * the log.
+ */
+ if (count != len)
+ if (copy_to_user(buf + len, log->buffer, count - len))
+ return -EFAULT;
+
+ reader->r_off = logger_offset(reader->r_off + count);
+
+ return count;
+}
+
+/*
+ * logger_read - our log's read() method
+ *
+ * Behavior:
+ *
+ * - O_NONBLOCK works
+ * - If there are no log entries to read, blocks until log is written to
+ * - Atomically reads exactly one log entry
+ *
+ * Optimal read size is LOGGER_ENTRY_MAX_LEN. Will set errno to EINVAL if read
+ * buffer is insufficient to hold next entry.
+ */
+static ssize_t logger_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct logger_reader *reader = file->private_data;
+ struct logger_log *log = reader->log;
+ ssize_t ret;
+ DEFINE_WAIT(wait);
+
+start:
+ while (1) {
+ prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE);
+
+ mutex_lock(&log->mutex);
+ ret = (log->w_off == reader->r_off);
+ mutex_unlock(&log->mutex);
+ if (!ret)
+ break;
+
+ if (file->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+
+ schedule();
+ }
+
+ finish_wait(&log->wq, &wait);
+ if (ret)
+ return ret;
+
+ mutex_lock(&log->mutex);
+
+ /* is there still something to read or did we race? */
+ if (unlikely(log->w_off == reader->r_off)) {
+ mutex_unlock(&log->mutex);
+ goto start;
+ }
+
+ /* get the size of the next entry */
+ ret = get_entry_len(log, reader->r_off);
+ if (count < ret) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* get exactly one entry from the log */
+ ret = do_read_log_to_user(log, reader, buf, ret);
+
+out:
+ mutex_unlock(&log->mutex);
+
+ return ret;
+}
+
+/*
+ * get_next_entry - return the offset of the first valid entry at least 'len'
+ * bytes after 'off'.
+ *
+ * Caller must hold log->mutex.
+ */
+static size_t get_next_entry(struct logger_log *log, size_t off, size_t len)
+{
+ size_t count = 0;
+
+ do {
+ size_t nr = get_entry_len(log, off);
+ off = logger_offset(off + nr);
+ count += nr;
+ } while (count < len);
+
+ return off;
+}
+
+/*
+ * clock_interval - is a < c < b in mod-space? Put another way, does the line
+ * from a to b cross c?
+ */
+static inline int clock_interval(size_t a, size_t b, size_t c)
+{
+ if (b < a) {
+ if (a < c || b >= c)
+ return 1;
+ } else {
+ if (a < c && b >= c)
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * fix_up_readers - walk the list of all readers and "fix up" any who were
+ * lapped by the writer; also do the same for the default "start head".
+ * We do this by "pulling forward" the readers and start head to the first
+ * entry after the new write head.
+ *
+ * The caller needs to hold log->mutex.
+ */
+static void fix_up_readers(struct logger_log *log, size_t len)
+{
+ size_t old = log->w_off;
+ size_t new = logger_offset(old + len);
+ struct logger_reader *reader;
+
+ if (clock_interval(old, new, log->head))
+ log->head = get_next_entry(log, log->head, len);
+
+ list_for_each_entry(reader, &log->readers, list)
+ if (clock_interval(old, new, reader->r_off))
+ reader->r_off = get_next_entry(log, reader->r_off, len);
+}
+
+/*
+ * do_write_log - writes 'len' bytes from 'buf' to 'log'
+ *
+ * The caller needs to hold log->mutex.
+ */
+static void do_write_log(struct logger_log *log, const void *buf, size_t count)
+{
+ size_t len;
+
+ len = min(count, log->size - log->w_off);
+ memcpy(log->buffer + log->w_off, buf, len);
+
+ if (count != len)
+ memcpy(log->buffer, buf + len, count - len);
+
+ log->w_off = logger_offset(log->w_off + count);
+
+}
+
+/*
+ * do_write_log_user - writes 'len' bytes from the user-space buffer 'buf' to
+ * the log 'log'
+ *
+ * The caller needs to hold log->mutex.
+ *
+ * Returns 'count' on success, negative error code on failure.
+ */
+static ssize_t do_write_log_from_user(struct logger_log *log,
+ const void __user *buf, size_t count)
+{
+ size_t len;
+
+ len = min(count, log->size - log->w_off);
+ if (len && copy_from_user(log->buffer + log->w_off, buf, len))
+ return -EFAULT;
+
+ if (count != len)
+ if (copy_from_user(log->buffer, buf + len, count - len))
+ return -EFAULT;
+
+ log->w_off = logger_offset(log->w_off + count);
+
+ return count;
+}
+
+/*
+ * logger_aio_write - our write method, implementing support for write(),
+ * writev(), and aio_write(). Writes are our fast path, and we try to optimize
+ * them above all else.
+ */
+ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t ppos)
+{
+ struct logger_log *log = file_get_log(iocb->ki_filp);
+ size_t orig = log->w_off;
+ struct logger_entry header;
+ struct timespec now;
+ ssize_t ret = 0;
+
+ now = current_kernel_time();
+
+ header.pid = current->tgid;
+ header.tid = current->pid;
+ header.sec = now.tv_sec;
+ header.nsec = now.tv_nsec;
+ header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
+
+ /* null writes succeed, return zero */
+ if (unlikely(!header.len))
+ return 0;
+
+ mutex_lock(&log->mutex);
+
+ /*
+ * Fix up any readers, pulling them forward to the first readable
+ * entry after (what will be) the new write offset. We do this now
+ * because if we partially fail, we can end up with clobbered log
+ * entries that encroach on readable buffer.
+ */
+ fix_up_readers(log, sizeof(struct logger_entry) + header.len);
+
+ do_write_log(log, &header, sizeof(struct logger_entry));
+
+ while (nr_segs-- > 0) {
+ size_t len;
+ ssize_t nr;
+
+ /* figure out how much of this vector we can keep */
+ len = min_t(size_t, iov->iov_len, header.len - ret);
+
+ /* write out this segment's payload */
+ nr = do_write_log_from_user(log, iov->iov_base, len);
+ if (unlikely(nr < 0)) {
+ log->w_off = orig;
+ mutex_unlock(&log->mutex);
+ return nr;
+ }
+
+ iov++;
+ ret += nr;
+ }
+
+ mutex_unlock(&log->mutex);
+
+ /* wake up any blocked readers */
+ wake_up_interruptible(&log->wq);
+
+ return ret;
+}
+
+static struct logger_log * get_log_from_minor(int);
+
+/*
+ * logger_open - the log's open() file operation
+ *
+ * Note how near a no-op this is in the write-only case. Keep it that way!
+ */
+static int logger_open(struct inode *inode, struct file *file)
+{
+ struct logger_log *log;
+ int ret;
+
+ ret = nonseekable_open(inode, file);
+ if (ret)
+ return ret;
+
+ log = get_log_from_minor(MINOR(inode->i_rdev));
+ if (!log)
+ return -ENODEV;
+
+ if (file->f_mode & FMODE_READ) {
+ struct logger_reader *reader;
+
+ reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL);
+ if (!reader)
+ return -ENOMEM;
+
+ reader->log = log;
+ INIT_LIST_HEAD(&reader->list);
+
+ mutex_lock(&log->mutex);
+ reader->r_off = log->head;
+ list_add_tail(&reader->list, &log->readers);
+ mutex_unlock(&log->mutex);
+
+ file->private_data = reader;
+ } else
+ file->private_data = log;
+
+ return 0;
+}
+
+/*
+ * logger_release - the log's release file operation
+ *
+ * Note this is a total no-op in the write-only case. Keep it that way!
+ */
+static int logger_release(struct inode *ignored, struct file *file)
+{
+ if (file->f_mode & FMODE_READ) {
+ struct logger_reader *reader = file->private_data;
+ list_del(&reader->list);
+ kfree(reader);
+ }
+
+ return 0;
+}
+
+/*
+ * logger_poll - the log's poll file operation, for poll/select/epoll
+ *
+ * Note we always return POLLOUT, because you can always write() to the log.
+ * Note also that, strictly speaking, a return value of POLLIN does not
+ * guarantee that the log is readable without blocking, as there is a small
+ * chance that the writer can lap the reader in the interim between poll()
+ * returning and the read() request.
+ */
+static unsigned int logger_poll(struct file *file, poll_table *wait)
+{
+ struct logger_reader *reader;
+ struct logger_log *log;
+ unsigned int ret = POLLOUT | POLLWRNORM;
+
+ if (!(file->f_mode & FMODE_READ))
+ return ret;
+
+ reader = file->private_data;
+ log = reader->log;
+
+ poll_wait(file, &log->wq, wait);
+
+ mutex_lock(&log->mutex);
+ if (log->w_off != reader->r_off)
+ ret |= POLLIN | POLLRDNORM;
+ mutex_unlock(&log->mutex);
+
+ return ret;
+}
+
+static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct logger_log *log = file_get_log(file);
+ struct logger_reader *reader;
+ long ret = -ENOTTY;
+
+ mutex_lock(&log->mutex);
+
+ switch (cmd) {
+ case LOGGER_GET_LOG_BUF_SIZE:
+ ret = log->size;
+ break;
+ case LOGGER_GET_LOG_LEN:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ if (log->w_off >= reader->r_off)
+ ret = log->w_off - reader->r_off;
+ else
+ ret = (log->size - reader->r_off) + log->w_off;
+ break;
+ case LOGGER_GET_NEXT_ENTRY_LEN:
+ if (!(file->f_mode & FMODE_READ)) {
+ ret = -EBADF;
+ break;
+ }
+ reader = file->private_data;
+ if (log->w_off != reader->r_off)
+ ret = get_entry_len(log, reader->r_off);
+ else
+ ret = 0;
+ break;
+ case LOGGER_FLUSH_LOG:
+ if (!(file->f_mode & FMODE_WRITE)) {
+ ret = -EBADF;
+ break;
+ }
+ list_for_each_entry(reader, &log->readers, list)
+ reader->r_off = log->w_off;
+ log->head = log->w_off;
+ ret = 0;
+ break;
+ }
+
+ mutex_unlock(&log->mutex);
+
+ return ret;
+}
+
+static struct file_operations logger_fops = {
+ .owner = THIS_MODULE,
+ .read = logger_read,
+ .aio_write = logger_aio_write,
+ .poll = logger_poll,
+ .unlocked_ioctl = logger_ioctl,
+ .compat_ioctl = logger_ioctl,
+ .open = logger_open,
+ .release = logger_release,
+};
+
+/*
+ * Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which
+ * must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than
+ * LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
+ */
+#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \
+static unsigned char _buf_ ## VAR[SIZE]; \
+static struct logger_log VAR = { \
+ .buffer = _buf_ ## VAR, \
+ .misc = { \
+ .minor = MISC_DYNAMIC_MINOR, \
+ .name = NAME, \
+ .fops = &logger_fops, \
+ .parent = NULL, \
+ }, \
+ .wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \
+ .readers = LIST_HEAD_INIT(VAR .readers), \
+ .mutex = __MUTEX_INITIALIZER(VAR .mutex), \
+ .w_off = 0, \
+ .head = 0, \
+ .size = SIZE, \
+};
+
+DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024)
+DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
+DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024)
+
+static struct logger_log * get_log_from_minor(int minor)
+{
+ if (log_main.misc.minor == minor)
+ return &log_main;
+ if (log_events.misc.minor == minor)
+ return &log_events;
+ if (log_radio.misc.minor == minor)
+ return &log_radio;
+ return NULL;
+}
+
+static int __init init_log(struct logger_log *log)
+{
+ int ret;
+
+ ret = misc_register(&log->misc);
+ if (unlikely(ret)) {
+ printk(KERN_ERR "logger: failed to register misc "
+ "device for log '%s'!\n", log->misc.name);
+ return ret;
+ }
+
+ printk(KERN_INFO "logger: created %luK log '%s'\n",
+ (unsigned long) log->size >> 10, log->misc.name);
+
+ return 0;
+}
+
+static int __init logger_init(void)
+{
+ int ret;
+
+ ret = init_log(&log_main);
+ if (unlikely(ret))
+ goto out;
+
+ ret = init_log(&log_events);
+ if (unlikely(ret))
+ goto out;
+
+ ret = init_log(&log_radio);
+ if (unlikely(ret))
+ goto out;
+
+out:
+ return ret;
+}
+device_initcall(logger_init);
diff --git a/drivers/staging/android/logger.h b/drivers/staging/android/logger.h
new file mode 100644
index 000000000000..a562434d7419
--- /dev/null
+++ b/drivers/staging/android/logger.h
@@ -0,0 +1,48 @@
+/* include/linux/logger.h
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ * Author: Robert Love <rlove@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_LOGGER_H
+#define _LINUX_LOGGER_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+struct logger_entry {
+ __u16 len; /* length of the payload */
+ __u16 __pad; /* no matter what, we get 2 bytes of padding */
+ __s32 pid; /* generating process's pid */
+ __s32 tid; /* generating process's tid */
+ __s32 sec; /* seconds since Epoch */
+ __s32 nsec; /* nanoseconds */
+ char msg[0]; /* the entry's payload */
+};
+
+#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */
+#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */
+#define LOGGER_LOG_MAIN "log_main" /* everything else */
+
+#define LOGGER_ENTRY_MAX_LEN (4*1024)
+#define LOGGER_ENTRY_MAX_PAYLOAD \
+ (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
+
+#define __LOGGERIO 0xAE
+
+#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */
+#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
+#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
+#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
+
+#endif /* _LINUX_LOGGER_H */
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
new file mode 100644
index 000000000000..3715d56ca96b
--- /dev/null
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -0,0 +1,119 @@
+/* drivers/misc/lowmemorykiller.c
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/oom.h>
+#include <linux/sched.h>
+
+static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask);
+
+static struct shrinker lowmem_shrinker = {
+ .shrink = lowmem_shrink,
+ .seeks = DEFAULT_SEEKS * 16
+};
+static uint32_t lowmem_debug_level = 2;
+static int lowmem_adj[6] = {
+ 0,
+ 1,
+ 6,
+ 12,
+};
+static int lowmem_adj_size = 4;
+static size_t lowmem_minfree[6] = {
+ 3*512, // 6MB
+ 2*1024, // 8MB
+ 4*1024, // 16MB
+ 16*1024, // 64MB
+};
+static int lowmem_minfree_size = 4;
+
+#define lowmem_print(level, x...) do { if(lowmem_debug_level >= (level)) printk(x); } while(0)
+
+module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
+module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size, S_IRUGO | S_IWUSR);
+module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, S_IRUGO | S_IWUSR);
+module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
+
+static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
+{
+ struct task_struct *p;
+ struct task_struct *selected = NULL;
+ int rem = 0;
+ int tasksize;
+ int i;
+ int min_adj = OOM_ADJUST_MAX + 1;
+ int selected_tasksize = 0;
+ int array_size = ARRAY_SIZE(lowmem_adj);
+ int other_free = global_page_state(NR_FREE_PAGES) + global_page_state(NR_FILE_PAGES);
+ if(lowmem_adj_size < array_size)
+ array_size = lowmem_adj_size;
+ if(lowmem_minfree_size < array_size)
+ array_size = lowmem_minfree_size;
+ for(i = 0; i < array_size; i++) {
+ if(other_free < lowmem_minfree[i]) {
+ min_adj = lowmem_adj[i];
+ break;
+ }
+ }
+ if(nr_to_scan > 0)
+ lowmem_print(3, "lowmem_shrink %d, %x, ofree %d, ma %d\n", nr_to_scan, gfp_mask, other_free, min_adj);
+ read_lock(&tasklist_lock);
+ for_each_process(p) {
+ if(p->oomkilladj >= 0 && p->mm) {
+ tasksize = get_mm_rss(p->mm);
+ if(nr_to_scan > 0 && tasksize > 0 && p->oomkilladj >= min_adj) {
+ if(selected == NULL ||
+ p->oomkilladj > selected->oomkilladj ||
+ (p->oomkilladj == selected->oomkilladj &&
+ tasksize > selected_tasksize)) {
+ selected = p;
+ selected_tasksize = tasksize;
+ lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
+ p->pid, p->comm, p->oomkilladj, tasksize);
+ }
+ }
+ rem += tasksize;
+ }
+ }
+ if(selected != NULL) {
+ lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
+ selected->pid, selected->comm,
+ selected->oomkilladj, selected_tasksize);
+ force_sig(SIGKILL, selected);
+ rem -= selected_tasksize;
+ }
+ lowmem_print(4, "lowmem_shrink %d, %x, return %d\n", nr_to_scan, gfp_mask, rem);
+ read_unlock(&tasklist_lock);
+ return rem;
+}
+
+static int __init lowmem_init(void)
+{
+ register_shrinker(&lowmem_shrinker);
+ return 0;
+}
+
+static void __exit lowmem_exit(void)
+{
+ unregister_shrinker(&lowmem_shrinker);
+}
+
+module_init(lowmem_init);
+module_exit(lowmem_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/staging/android/lowmemorykiller.txt b/drivers/staging/android/lowmemorykiller.txt
new file mode 100644
index 000000000000..bd5c0c028968
--- /dev/null
+++ b/drivers/staging/android/lowmemorykiller.txt
@@ -0,0 +1,16 @@
+The lowmemorykiller driver lets user-space specify a set of memory thresholds
+where processes with a range of oom_adj values will get killed. Specify the
+minimum oom_adj values in /sys/module/lowmemorykiller/parameters/adj and the
+number of free pages in /sys/module/lowmemorykiller/parameters/minfree. Both
+files take a comma separated list of numbers in ascending order.
+
+For example, write "0,8" to /sys/module/lowmemorykiller/parameters/adj and
+"1024,4096" to /sys/module/lowmemorykiller/parameters/minfree to kill processes
+with a oom_adj value of 8 or higher when the free memory drops below 4096 pages
+and kill processes with a oom_adj value of 0 or higher when the free memory
+drops below 1024 pages.
+
+The driver considers memory used for caches to be free, but if a large
+percentage of the cached memory is locked this can be very inaccurate
+and processes may not get killed until the normal oom killer is triggered.
+
diff --git a/drivers/staging/android/ram_console.c b/drivers/staging/android/ram_console.c
new file mode 100644
index 000000000000..bf006857a87a
--- /dev/null
+++ b/drivers/staging/android/ram_console.c
@@ -0,0 +1,395 @@
+/* drivers/android/ram_console.c
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+#include <linux/rslib.h>
+#endif
+
+struct ram_console_buffer {
+ uint32_t sig;
+ uint32_t start;
+ uint32_t size;
+ uint8_t data[0];
+};
+
+#define RAM_CONSOLE_SIG (0x43474244) /* DBGC */
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+static char __initdata
+ ram_console_old_log_init_buffer[CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE];
+#endif
+static char *ram_console_old_log;
+static size_t ram_console_old_log_size;
+
+static struct ram_console_buffer *ram_console_buffer;
+static size_t ram_console_buffer_size;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+static char *ram_console_par_buffer;
+static struct rs_control *ram_console_rs_decoder;
+static int ram_console_corrected_bytes;
+static int ram_console_bad_blocks;
+#define ECC_BLOCK_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE
+#define ECC_SIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE
+#define ECC_SYMSIZE CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE
+#define ECC_POLY CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL
+#endif
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+static void ram_console_encode_rs8(uint8_t *data, size_t len, uint8_t *ecc)
+{
+ int i;
+ uint16_t par[ECC_SIZE];
+ /* Initialize the parity buffer */
+ memset(par, 0, sizeof(par));
+ encode_rs8(ram_console_rs_decoder, data, len, par, 0);
+ for (i = 0; i < ECC_SIZE; i++)
+ ecc[i] = par[i];
+}
+
+static int ram_console_decode_rs8(void *data, size_t len, uint8_t *ecc)
+{
+ int i;
+ uint16_t par[ECC_SIZE];
+ for (i = 0; i < ECC_SIZE; i++)
+ par[i] = ecc[i];
+ return decode_rs8(ram_console_rs_decoder, data, par, len,
+ NULL, 0, NULL, 0, NULL);
+}
+#endif
+
+static void ram_console_update(const char *s, unsigned int count)
+{
+ struct ram_console_buffer *buffer = ram_console_buffer;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ uint8_t *buffer_end = buffer->data + ram_console_buffer_size;
+ uint8_t *block;
+ uint8_t *par;
+ int size = ECC_BLOCK_SIZE;
+#endif
+ memcpy(buffer->data + buffer->start, s, count);
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ block = buffer->data + (buffer->start & ~(ECC_BLOCK_SIZE - 1));
+ par = ram_console_par_buffer +
+ (buffer->start / ECC_BLOCK_SIZE) * ECC_SIZE;
+ do {
+ if (block + ECC_BLOCK_SIZE > buffer_end)
+ size = buffer_end - block;
+ ram_console_encode_rs8(block, size, par);
+ block += ECC_BLOCK_SIZE;
+ par += ECC_SIZE;
+ } while (block < buffer->data + buffer->start + count);
+#endif
+}
+
+static void ram_console_update_header(void)
+{
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ struct ram_console_buffer *buffer = ram_console_buffer;
+ uint8_t *par;
+ par = ram_console_par_buffer +
+ DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE;
+ ram_console_encode_rs8((uint8_t *)buffer, sizeof(*buffer), par);
+#endif
+}
+
+static void
+ram_console_write(struct console *console, const char *s, unsigned int count)
+{
+ int rem;
+ struct ram_console_buffer *buffer = ram_console_buffer;
+
+ if (count > ram_console_buffer_size) {
+ s += count - ram_console_buffer_size;
+ count = ram_console_buffer_size;
+ }
+ rem = ram_console_buffer_size - buffer->start;
+ if (rem < count) {
+ ram_console_update(s, rem);
+ s += rem;
+ count -= rem;
+ buffer->start = 0;
+ buffer->size = ram_console_buffer_size;
+ }
+ ram_console_update(s, count);
+
+ buffer->start += count;
+ if (buffer->size < ram_console_buffer_size)
+ buffer->size += count;
+ ram_console_update_header();
+}
+
+static struct console ram_console = {
+ .name = "ram",
+ .write = ram_console_write,
+ .flags = CON_PRINTBUFFER | CON_ENABLED,
+ .index = -1,
+};
+
+static void __init
+ram_console_save_old(struct ram_console_buffer *buffer, char *dest)
+{
+ size_t old_log_size = buffer->size;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ uint8_t *block;
+ uint8_t *par;
+ char strbuf[80];
+ int strbuf_len;
+
+ block = buffer->data;
+ par = ram_console_par_buffer;
+ while (block < buffer->data + buffer->size) {
+ int numerr;
+ int size = ECC_BLOCK_SIZE;
+ if (block + size > buffer->data + ram_console_buffer_size)
+ size = buffer->data + ram_console_buffer_size - block;
+ numerr = ram_console_decode_rs8(block, size, par);
+ if (numerr > 0) {
+#if 0
+ printk(KERN_INFO "ram_console: error in block %p, %d\n",
+ block, numerr);
+#endif
+ ram_console_corrected_bytes += numerr;
+ } else if (numerr < 0) {
+#if 0
+ printk(KERN_INFO "ram_console: uncorrectable error in "
+ "block %p\n", block);
+#endif
+ ram_console_bad_blocks++;
+ }
+ block += ECC_BLOCK_SIZE;
+ par += ECC_SIZE;
+ }
+ if (ram_console_corrected_bytes || ram_console_bad_blocks)
+ strbuf_len = snprintf(strbuf, sizeof(strbuf),
+ "\n%d Corrected bytes, %d unrecoverable blocks\n",
+ ram_console_corrected_bytes, ram_console_bad_blocks);
+ else
+ strbuf_len = snprintf(strbuf, sizeof(strbuf),
+ "\nNo errors detected\n");
+ if (strbuf_len >= sizeof(strbuf))
+ strbuf_len = sizeof(strbuf) - 1;
+ old_log_size += strbuf_len;
+#endif
+
+ if (dest == NULL) {
+ dest = kmalloc(old_log_size, GFP_KERNEL);
+ if (dest == NULL) {
+ printk(KERN_ERR
+ "ram_console: failed to allocate buffer\n");
+ return;
+ }
+ }
+
+ ram_console_old_log = dest;
+ ram_console_old_log_size = old_log_size;
+ memcpy(ram_console_old_log,
+ &buffer->data[buffer->start], buffer->size - buffer->start);
+ memcpy(ram_console_old_log + buffer->size - buffer->start,
+ &buffer->data[0], buffer->start);
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ memcpy(ram_console_old_log + old_log_size - strbuf_len,
+ strbuf, strbuf_len);
+#endif
+}
+
+static int __init ram_console_init(struct ram_console_buffer *buffer,
+ size_t buffer_size, char *old_buf)
+{
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ int numerr;
+ uint8_t *par;
+#endif
+ ram_console_buffer = buffer;
+ ram_console_buffer_size =
+ buffer_size - sizeof(struct ram_console_buffer);
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
+ ram_console_buffer_size -= (DIV_ROUND_UP(ram_console_buffer_size,
+ ECC_BLOCK_SIZE) + 1) * ECC_SIZE;
+ ram_console_par_buffer = buffer->data + ram_console_buffer_size;
+
+
+ /* first consecutive root is 0
+ * primitive element to generate roots = 1
+ */
+ ram_console_rs_decoder = init_rs(ECC_SYMSIZE, ECC_POLY, 0, 1, ECC_SIZE);
+ if (ram_console_rs_decoder == NULL) {
+ printk(KERN_INFO "ram_console: init_rs failed\n");
+ return 0;
+ }
+
+ ram_console_corrected_bytes = 0;
+ ram_console_bad_blocks = 0;
+
+ par = ram_console_par_buffer +
+ DIV_ROUND_UP(ram_console_buffer_size, ECC_BLOCK_SIZE) * ECC_SIZE;
+
+ numerr = ram_console_decode_rs8(buffer, sizeof(*buffer), par);
+ if (numerr > 0) {
+ printk(KERN_INFO "ram_console: error in header, %d\n", numerr);
+ ram_console_corrected_bytes += numerr;
+ } else if (numerr < 0) {
+ printk(KERN_INFO
+ "ram_console: uncorrectable error in header\n");
+ ram_console_bad_blocks++;
+ }
+#endif
+
+ if (buffer->sig == RAM_CONSOLE_SIG) {
+ if (buffer->size > ram_console_buffer_size
+ || buffer->start > buffer->size)
+ printk(KERN_INFO "ram_console: found existing invalid "
+ "buffer, size %d, start %d\n",
+ buffer->size, buffer->start);
+ else {
+ printk(KERN_INFO "ram_console: found existing buffer, "
+ "size %d, start %d\n",
+ buffer->size, buffer->start);
+ ram_console_save_old(buffer, old_buf);
+ }
+ } else {
+ printk(KERN_INFO "ram_console: no valid data in buffer "
+ "(sig = 0x%08x)\n", buffer->sig);
+ }
+
+ buffer->sig = RAM_CONSOLE_SIG;
+ buffer->start = 0;
+ buffer->size = 0;
+
+ register_console(&ram_console);
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE
+ console_verbose();
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+static int __init ram_console_early_init(void)
+{
+ return ram_console_init((struct ram_console_buffer *)
+ CONFIG_ANDROID_RAM_CONSOLE_EARLY_ADDR,
+ CONFIG_ANDROID_RAM_CONSOLE_EARLY_SIZE,
+ ram_console_old_log_init_buffer);
+}
+#else
+static int ram_console_driver_probe(struct platform_device *pdev)
+{
+ struct resource *res = pdev->resource;
+ size_t start;
+ size_t buffer_size;
+ void *buffer;
+
+ if (res == NULL || pdev->num_resources != 1 ||
+ !(res->flags & IORESOURCE_MEM)) {
+ printk(KERN_ERR "ram_console: invalid resource, %p %d flags "
+ "%lx\n", res, pdev->num_resources, res ? res->flags : 0);
+ return -ENXIO;
+ }
+ buffer_size = res->end - res->start + 1;
+ start = res->start;
+ printk(KERN_INFO "ram_console: got buffer at %x, size %x\n",
+ start, buffer_size);
+ buffer = ioremap(res->start, buffer_size);
+ if (buffer == NULL) {
+ printk(KERN_ERR "ram_console: failed to map memory\n");
+ return -ENOMEM;
+ }
+
+ return ram_console_init(buffer, buffer_size, NULL/* allocate */);
+}
+
+static struct platform_driver ram_console_driver = {
+ .probe = ram_console_driver_probe,
+ .driver = {
+ .name = "ram_console",
+ },
+};
+
+static int __init ram_console_module_init(void)
+{
+ int err;
+ err = platform_driver_register(&ram_console_driver);
+ return err;
+}
+#endif
+
+static ssize_t ram_console_read_old(struct file *file, char __user *buf,
+ size_t len, loff_t *offset)
+{
+ loff_t pos = *offset;
+ ssize_t count;
+
+ if (pos >= ram_console_old_log_size)
+ return 0;
+
+ count = min(len, (size_t)(ram_console_old_log_size - pos));
+ if (copy_to_user(buf, ram_console_old_log + pos, count))
+ return -EFAULT;
+
+ *offset += count;
+ return count;
+}
+
+static struct file_operations ram_console_file_ops = {
+ .owner = THIS_MODULE,
+ .read = ram_console_read_old,
+};
+
+static int __init ram_console_late_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ if (ram_console_old_log == NULL)
+ return 0;
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+ ram_console_old_log = kmalloc(ram_console_old_log_size, GFP_KERNEL);
+ if (ram_console_old_log == NULL) {
+ printk(KERN_ERR
+ "ram_console: failed to allocate buffer for old log\n");
+ ram_console_old_log_size = 0;
+ return 0;
+ }
+ memcpy(ram_console_old_log,
+ ram_console_old_log_init_buffer, ram_console_old_log_size);
+#endif
+ entry = create_proc_entry("last_kmsg", S_IFREG | S_IRUGO, NULL);
+ if (!entry) {
+ printk(KERN_ERR "ram_console: failed to create proc entry\n");
+ kfree(ram_console_old_log);
+ ram_console_old_log = NULL;
+ return 0;
+ }
+
+ entry->proc_fops = &ram_console_file_ops;
+ entry->size = ram_console_old_log_size;
+ return 0;
+}
+
+#ifdef CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT
+console_initcall(ram_console_early_init);
+#else
+module_init(ram_console_module_init);
+#endif
+late_initcall(ram_console_late_init);
+
diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c
new file mode 100644
index 000000000000..903270cbbe02
--- /dev/null
+++ b/drivers/staging/android/timed_gpio.c
@@ -0,0 +1,178 @@
+/* drivers/misc/timed_gpio.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/hrtimer.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+
+#include "timed_gpio.h"
+
+
+static struct class *timed_gpio_class;
+
+struct timed_gpio_data {
+ struct device *dev;
+ struct hrtimer timer;
+ spinlock_t lock;
+ unsigned gpio;
+ int max_timeout;
+ u8 active_low;
+};
+
+static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
+{
+ struct timed_gpio_data *gpio_data = container_of(timer, struct timed_gpio_data, timer);
+
+ gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? 1 : 0);
+ return HRTIMER_NORESTART;
+}
+
+static ssize_t gpio_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct timed_gpio_data *gpio_data = dev_get_drvdata(dev);
+ int remaining;
+
+ if (hrtimer_active(&gpio_data->timer)) {
+ ktime_t r = hrtimer_get_remaining(&gpio_data->timer);
+ struct timeval t = ktime_to_timeval(r);
+ remaining = t.tv_sec * 1000 + t.tv_usec;
+ } else
+ remaining = 0;
+
+ return sprintf(buf, "%d\n", remaining);
+}
+
+static ssize_t gpio_enable_store(
+ struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct timed_gpio_data *gpio_data = dev_get_drvdata(dev);
+ int value;
+ unsigned long flags;
+
+ sscanf(buf, "%d", &value);
+
+ spin_lock_irqsave(&gpio_data->lock, flags);
+
+ /* cancel previous timer and set GPIO according to value */
+ hrtimer_cancel(&gpio_data->timer);
+ gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? !value : !!value);
+
+ if (value > 0) {
+ if (value > gpio_data->max_timeout)
+ value = gpio_data->max_timeout;
+
+ hrtimer_start(&gpio_data->timer,
+ ktime_set(value / 1000, (value % 1000) * 1000000),
+ HRTIMER_MODE_REL);
+ }
+
+ spin_unlock_irqrestore(&gpio_data->lock, flags);
+
+ return size;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, gpio_enable_show, gpio_enable_store);
+
+static int timed_gpio_probe(struct platform_device *pdev)
+{
+ struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct timed_gpio *cur_gpio;
+ struct timed_gpio_data *gpio_data, *gpio_dat;
+ int i, ret = 0;
+
+ if (!pdata)
+ return -EBUSY;
+
+ gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios, GFP_KERNEL);
+ if (!gpio_data)
+ return -ENOMEM;
+
+ for (i = 0; i < pdata->num_gpios; i++) {
+ cur_gpio = &pdata->gpios[i];
+ gpio_dat = &gpio_data[i];
+
+ hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ gpio_dat->timer.function = gpio_timer_func;
+ spin_lock_init(&gpio_dat->lock);
+
+ gpio_dat->gpio = cur_gpio->gpio;
+ gpio_dat->max_timeout = cur_gpio->max_timeout;
+ gpio_dat->active_low = cur_gpio->active_low;
+ gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
+
+ gpio_dat->dev = device_create(timed_gpio_class, &pdev->dev, 0, "%s", cur_gpio->name);
+ if (unlikely(IS_ERR(gpio_dat->dev)))
+ return PTR_ERR(gpio_dat->dev);
+
+ dev_set_drvdata(gpio_dat->dev, gpio_dat);
+ ret = device_create_file(gpio_dat->dev, &dev_attr_enable);
+ if (ret)
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, gpio_data);
+
+ return 0;
+}
+
+static int timed_gpio_remove(struct platform_device *pdev)
+{
+ struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
+ struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < pdata->num_gpios; i++) {
+ device_remove_file(gpio_data[i].dev, &dev_attr_enable);
+ device_unregister(gpio_data[i].dev);
+ }
+
+ kfree(gpio_data);
+
+ return 0;
+}
+
+static struct platform_driver timed_gpio_driver = {
+ .probe = timed_gpio_probe,
+ .remove = timed_gpio_remove,
+ .driver = {
+ .name = "timed-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init timed_gpio_init(void)
+{
+ timed_gpio_class = class_create(THIS_MODULE, "timed_output");
+ if (IS_ERR(timed_gpio_class))
+ return PTR_ERR(timed_gpio_class);
+ return platform_driver_register(&timed_gpio_driver);
+}
+
+static void __exit timed_gpio_exit(void)
+{
+ class_destroy(timed_gpio_class);
+ platform_driver_unregister(&timed_gpio_driver);
+}
+
+module_init(timed_gpio_init);
+module_exit(timed_gpio_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_DESCRIPTION("timed gpio driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/android/timed_gpio.h b/drivers/staging/android/timed_gpio.h
new file mode 100644
index 000000000000..78449b2161cf
--- /dev/null
+++ b/drivers/staging/android/timed_gpio.h
@@ -0,0 +1,31 @@
+/* include/linux/timed_gpio.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+*/
+
+#ifndef _LINUX_TIMED_GPIO_H
+#define _LINUX_TIMED_GPIO_H
+
+struct timed_gpio {
+ const char *name;
+ unsigned gpio;
+ int max_timeout;
+ u8 active_low;
+};
+
+struct timed_gpio_platform_data {
+ int num_gpios;
+ struct timed_gpio *gpios;
+};
+
+#endif
diff --git a/drivers/staging/asus_oled/Kconfig b/drivers/staging/asus_oled/Kconfig
new file mode 100644
index 000000000000..e56dbb25ac5d
--- /dev/null
+++ b/drivers/staging/asus_oled/Kconfig
@@ -0,0 +1,6 @@
+config ASUS_OLED
+ tristate "Asus OLED driver"
+ depends on USB
+ default N
+ ---help---
+ Enable support for the OLED display present in some Asus laptops.
diff --git a/drivers/staging/asus_oled/Makefile b/drivers/staging/asus_oled/Makefile
new file mode 100644
index 000000000000..e71f9aa9e037
--- /dev/null
+++ b/drivers/staging/asus_oled/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ASUS_OLED) += asus_oled.o
diff --git a/drivers/staging/asus_oled/README b/drivers/staging/asus_oled/README
new file mode 100644
index 000000000000..96b9717f168f
--- /dev/null
+++ b/drivers/staging/asus_oled/README
@@ -0,0 +1,156 @@
+
+ Driver for Asus OLED display present in some Asus laptops.
+
+ The code of this driver is based on 'asusoled' program taken from
+ https://launchpad.net/asusoled/. I just wanted to have a simple
+ kernel driver for controlling this device, but I didn't know how
+ to do that. Now I know ;) Also, that program can not be used
+ with usbhid loaded, which means no USB mouse/keyboard while
+ controlling OLED display :(
+
+ It has been tested on Asus G1 and didn't cause any problems,
+ but I don't guarantee that it won't do anything wrong :)
+
+ It can (and probably does) have errors. It is usable
+ in my case, and I hope others will find it useful too!
+
+*******
+
+Building the module
+
+ To build the module you need kernel 2.6 include files and some C compiler.
+
+ Just run:
+ make
+ make install (as a root)
+
+ It will build (hopefully) the module and install it in
+ /lib/modules/'uname -r'/extra/asus_oled.ko.
+
+ To load it just use:
+ modprobe asus_oled
+
+ You can check if it has detected your OLED display by looking into dmesg output.
+ There should be something like this:
+ asus-oled 2-7:1.0: Attached Asus OLED device
+
+ If it doesn't find your display, you can try removing usbhid module.
+ If you add asus_oled into the list of modules loaded during system boot
+ before usbhid, it will work even when usbhid is present.
+
+ If it still doesn't detect your hardware, check lsusb output.
+ There should be similar line:
+ Bus 002 Device 005: ID 0b05:1726 ASUSTek Computer, Inc.
+
+ If you don't see any lines with '0b05:1726' it means that you have different
+ type of hardware that is not detected (it may or may not work, but the driver
+ knows only '0b05:1726' device).
+
+*******
+
+Configuration
+
+ There is only one option: start_off.
+ You can use it by: 'modprobe asus_oled start_off=1', or by adding this
+ line to /etc/modprobe.conf:
+ options asus_oled start_off=1
+
+ With this option provided, asus_oled driver will switch off the display
+ when it is detected and attached. It is nice feature to just switch off the 'ASUS'
+ logo. If you don't use the display, it is probably the good idea to switch it off,
+ to protect OLEDs from "wearing off".
+
+*******
+
+Usage
+
+ This module can be controlled with two special files:
+ /sys/class/asus_oled/oled_N/enabled
+ /sys/class/asus_oled/oled_N/picture
+
+ (N is the device number, the first, and probably the only, has number 1,
+ so it is /sys/class/asus_oled/oled_1/enabled
+ and /sys/class/asus_oled/oled_1/picture)
+
+ 'enabled' files is for reading and writing, 'picture' is writeable only.
+
+ You can write 0 or 1 to 'enabled' file, which will switch
+ on and off the display. Reading from this file will tell you the last
+ status set, either 0 or 1. By default it is 1, so if the device was set to 'off',
+ and the computer was rebooted without power-off, this file will contain wrong
+ value - because the device is off, but hasn't been disabled this time and is
+ assumed to be on...
+
+ To 'picture' file you write pictures to be displayed by the OLED device.
+ The format of the file:
+ <M:WxH>
+ 00001110010111000
+ 00010101010101010
+ ....
+
+ First line is a configuration parameter. Meaning of fields in <M:WxH>:
+ M - picture mode. It can be either 's' for static pictures,
+ 'r' for rolling pictures, and 'f' for flashing pictures.
+ W - width of the picture. May be between 1 and 1792
+ H - height of the picture. May be between 1 and 32
+
+ For example <s:128x32> means static picture, 128 pixels long and 32 pixels high.
+
+ The physical size of the display is 128x32 pixels. Static and flashing pictures
+ can't be larger than that (actually they can, but only part of them will be displayed ;) )
+
+ If the picture is smaller than 128x32 it will be centered. Rolling pictures wider than
+ 128 pixels will be centered too, unless their width = n*128. Vertically they will be
+ centered just like static pictures, if their height is smaller than 32.
+
+ Flashing pictures will be centered horizontally if their width < 128, but they were
+ centered vertically in a different way. If their height < 16, they will be centered
+ in the upper half of the display (rows 0-15). This is because only the first half
+ of flashing pictures is used for flashing. When the picture with heigh = 32 is
+ displayed in flashing mode, its upper 16 rows will be flashing in the upper half
+ of the display, and the lower half will be empty. After few seconds upper part will
+ stop flashing (but that part of the picture will remain there), and the lower
+ half of the display will start displayin the lower half of the picture
+ in rolling mode, unless it is empty, or the picture was small enough to fit in
+ upper part. It is not mine idea, this is just the way Asus' display work ;)
+ So if you need just flashing, use at most 128x16 picture. If you need flashing and
+ rolling, use whole size of the display.
+
+ Lines following the first, configuration, line are picture data. Each '1' means
+ that the pixel is lit, and '0' means that it is not. You can also use '#' as ON,
+ and ' ' (space) as OFF. Empty lines and all other characters are ignored.
+
+ It is possible to write everything in one line <M:WxH>01010101010101010...,
+ and W*H characters will be used. If there is not enough characters, nothing will be
+ displayed. However, the 'line mode' is easier to read (and write), and it also
+ lets to omit parts of data. Whenever End-Of-Line character is found, but
+ the line is not W characters long, it is assumed that all missing characters
+ are equal to the last character in the line.
+
+ Following line represents '0', '1' and a lots of '0's, dependng on the width of the picture
+ provided in configuration data:
+ 010
+
+ So if you need empty line, it is sufficient to write line with only one '0' in it.
+ The same works with '1' (or ' ' and '#').
+
+ If there are too many data in the file, they will be ignored. If you are not sure
+ how many characters you are missing, you can add few lines with one zero in each of them.
+
+ There are some example pictures in .txt format, that can be used as follows:
+ cat foo.txt > /sys/class/asus_oled/oled_1/picture
+
+ If the display is switched off you also need to run:
+ echo 1 > /sys/class/asus_oled/oled_1/enabled
+ To switch it off, just use:
+ echo 0 > /sys/class/asus_oled/oled_1/enabled
+
+
+*******
+
+ For any additional info please have a look at http://lapsus.berlios.de/asus_oled.html
+
+
+
+ Jakub Schmidtke (sjakub@gmail.com)
+
diff --git a/drivers/staging/asus_oled/TODO b/drivers/staging/asus_oled/TODO
new file mode 100644
index 000000000000..2514131670a3
--- /dev/null
+++ b/drivers/staging/asus_oled/TODO
@@ -0,0 +1,10 @@
+TODO:
+ - checkpatch.pl cleanups
+ - sparse fixes
+ - audit the userspace interface
+ - sysfs vs. char?
+ - Documentation/ABI/ needs to be added
+ - put the sample .txt files and README file somewhere.
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
+Cc: Jakub Schmidtke <sjakub@gmail.com>
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
new file mode 100644
index 000000000000..666a186e212b
--- /dev/null
+++ b/drivers/staging/asus_oled/asus_oled.c
@@ -0,0 +1,745 @@
+/*
+ * Asus OLED USB driver
+ *
+ * Copyright (C) 2007,2008 Jakub Schmidtke (sjakub@gmail.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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *
+ *
+ * This module is based on usbled and asus-laptop modules.
+ *
+ *
+ * Asus OLED support is based on asusoled program taken from
+ * https://launchpad.net/asusoled/.
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+#include <linux/ctype.h>
+
+#define ASUS_OLED_VERSION "0.04-dev"
+#define ASUS_OLED_NAME "asus-oled"
+#define ASUS_OLED_UNDERSCORE_NAME "asus_oled"
+
+#define ASUS_OLED_ERROR "Asus OLED Display Error: "
+
+#define ASUS_OLED_STATIC 's'
+#define ASUS_OLED_ROLL 'r'
+#define ASUS_OLED_FLASH 'f'
+
+#define ASUS_OLED_MAX_WIDTH 1792
+#define ASUS_OLED_DISP_HEIGHT 32
+#define ASUS_OLED_PACKET_BUF_SIZE 256
+
+MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
+MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION);
+MODULE_LICENSE("GPL");
+
+static struct class *oled_class = 0;
+static int oled_num = 0;
+
+static uint start_off = 0;
+
+module_param(start_off, uint, 0644);
+
+MODULE_PARM_DESC(start_off, "Set to 1 to switch off OLED display after it is attached");
+
+typedef enum {
+ PACK_MODE_G1,
+ PACK_MODE_G50,
+ PACK_MODE_LAST
+} oled_pack_mode_t;
+
+struct oled_dev_desc_str {
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t devWidth; // width of display
+ oled_pack_mode_t packMode; // formula to be used while packing the picture
+ const char *devDesc;
+};
+
+/* table of devices that work with this driver */
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0b05, 0x1726) }, // Asus G1/G2 (and variants)
+ { USB_DEVICE(0x0b05, 0x175b) }, // Asus G50V (and possibly others - G70? G71?)
+ { },
+};
+
+/* parameters of specific devices */
+static struct oled_dev_desc_str oled_dev_desc_table [] = {
+ { 0x0b05, 0x1726, 128, PACK_MODE_G1, "G1/G2" },
+ { 0x0b05, 0x175b, 256, PACK_MODE_G50, "G50" },
+ { },
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+#define SETUP_PACKET_HEADER(packet, val1, val2, val3, val4, val5, val6, val7) \
+ do { \
+ memset(packet, 0, sizeof(struct asus_oled_header)); \
+ packet->header.magic1 = 0x55; \
+ packet->header.magic2 = 0xaa; \
+ packet->header.flags = val1; \
+ packet->header.value3 = val2; \
+ packet->header.buffer1 = val3; \
+ packet->header.buffer2 = val4; \
+ packet->header.value6 = val5; \
+ packet->header.value7 = val6; \
+ packet->header.value8 = val7; \
+ } while(0);
+
+struct asus_oled_header {
+ uint8_t magic1;
+ uint8_t magic2;
+ uint8_t flags;
+ uint8_t value3;
+ uint8_t buffer1;
+ uint8_t buffer2;
+ uint8_t value6;
+ uint8_t value7;
+ uint8_t value8;
+ uint8_t padding2[7];
+} __attribute((packed));
+
+struct asus_oled_packet {
+ struct asus_oled_header header;
+ uint8_t bitmap[ASUS_OLED_PACKET_BUF_SIZE];
+} __attribute((packed));
+
+struct asus_oled_dev {
+ struct usb_device * udev;
+ uint8_t pic_mode;
+ uint16_t dev_width;
+ oled_pack_mode_t pack_mode;
+ size_t height;
+ size_t width;
+ size_t x_shift;
+ size_t y_shift;
+ size_t buf_offs;
+ uint8_t last_val;
+ size_t buf_size;
+ char *buf;
+ uint8_t enabled;
+ struct device *dev;
+};
+
+static void enable_oled(struct asus_oled_dev *odev, uint8_t enabl)
+{
+ int a;
+ int retval;
+ int act_len;
+ struct asus_oled_packet * packet;
+
+ packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL);
+
+ if (!packet) {
+ dev_err(&odev->udev->dev, "out of memory\n");
+ return;
+ }
+
+ SETUP_PACKET_HEADER(packet, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00);
+
+ if (enabl) packet->bitmap[0] = 0xaf;
+ else packet->bitmap[0] = 0xae;
+
+ for (a=0; a<1; a++) {
+ retval = usb_bulk_msg(odev->udev,
+ usb_sndbulkpipe(odev->udev, 2),
+ packet,
+ sizeof(struct asus_oled_header) + 1,
+ &act_len,
+ -1);
+
+ if (retval)
+ dev_dbg(&odev->udev->dev, "retval = %d\n", retval);
+ }
+
+ odev->enabled = enabl;
+
+ kfree(packet);
+}
+
+static ssize_t set_enabled(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct asus_oled_dev *odev = usb_get_intfdata(intf);
+ int temp = simple_strtoul(buf, NULL, 10);
+
+ enable_oled(odev, temp);
+
+ return count;
+}
+
+static ssize_t class_set_enabled(struct device *device, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct asus_oled_dev *odev = (struct asus_oled_dev *) dev_get_drvdata(device);
+
+ int temp = simple_strtoul(buf, NULL, 10);
+
+ enable_oled(odev, temp);
+
+ return count;
+}
+
+static ssize_t get_enabled(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+ struct asus_oled_dev *odev = usb_get_intfdata(intf);
+
+ return sprintf(buf, "%d\n", odev->enabled);
+}
+
+static ssize_t class_get_enabled(struct device *device, struct device_attribute *attr, char *buf)
+{
+ struct asus_oled_dev *odev = (struct asus_oled_dev *) dev_get_drvdata(device);
+
+ return sprintf(buf, "%d\n", odev->enabled);
+}
+
+static void send_packets(struct usb_device *udev, struct asus_oled_packet *packet,
+ char *buf, uint8_t p_type, size_t p_num)
+{
+ size_t i;
+ int act_len;
+
+ for (i = 0; i < p_num; i++) {
+ int retval;
+
+ switch (p_type) {
+ case ASUS_OLED_ROLL:
+ SETUP_PACKET_HEADER(packet, 0x40, 0x80, p_num, i + 1, 0x00, 0x01, 0xff);
+ break;
+ case ASUS_OLED_STATIC:
+ SETUP_PACKET_HEADER(packet, 0x10 + i, 0x80, 0x01, 0x01, 0x00, 0x01, 0x00);
+ break;
+ case ASUS_OLED_FLASH:
+ SETUP_PACKET_HEADER(packet, 0x10 + i, 0x80, 0x01, 0x01, 0x00, 0x00, 0xff);
+ break;
+ }
+
+ memcpy(packet->bitmap, buf + (ASUS_OLED_PACKET_BUF_SIZE*i), ASUS_OLED_PACKET_BUF_SIZE);
+
+ retval = usb_bulk_msg(udev,
+ usb_sndctrlpipe(udev, 2),
+ packet,
+ sizeof(struct asus_oled_packet),
+ &act_len,
+ -1);
+
+ if (retval)
+ dev_dbg(&udev->dev, "retval = %d\n", retval);
+ }
+}
+
+static void send_packet(struct usb_device *udev, struct asus_oled_packet *packet, size_t offset, size_t len, char *buf, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6){
+ int retval;
+ int act_len;
+
+ SETUP_PACKET_HEADER(packet, b1, b2, b3, b4, b5, b6, 0x00);
+ memcpy(packet->bitmap, buf + offset, len);
+
+ retval = usb_bulk_msg(udev,
+ usb_sndctrlpipe(udev, 2),
+ packet,
+ sizeof(struct asus_oled_packet),
+ &act_len,
+ -1);
+
+ if (retval)
+ dev_dbg(&udev->dev, "retval = %d\n", retval);
+}
+
+
+static void send_packets_g50(struct usb_device *udev, struct asus_oled_packet *packet, char *buf)
+{
+ send_packet(udev, packet, 0, 0x100, buf, 0x10, 0x00, 0x02, 0x01, 0x00, 0x01);
+ send_packet(udev, packet, 0x100, 0x080, buf, 0x10, 0x00, 0x02, 0x02, 0x80, 0x00);
+
+ send_packet(udev, packet, 0x180, 0x100, buf, 0x11, 0x00, 0x03, 0x01, 0x00, 0x01);
+ send_packet(udev, packet, 0x280, 0x100, buf, 0x11, 0x00, 0x03, 0x02, 0x00, 0x01);
+ send_packet(udev, packet, 0x380, 0x080, buf, 0x11, 0x00, 0x03, 0x03, 0x80, 0x00);
+}
+
+
+static void send_data(struct asus_oled_dev *odev)
+{
+ size_t packet_num = odev->buf_size / ASUS_OLED_PACKET_BUF_SIZE;
+ struct asus_oled_packet * packet;
+
+ packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL);
+
+ if (!packet) {
+ dev_err(&odev->udev->dev, "out of memory\n");
+ return;
+ }
+
+ if (odev->pack_mode==PACK_MODE_G1){
+ // When sending roll-mode data the display updated only first packet.
+ // I have no idea why, but when static picture is send just before
+ // rolling picture - everything works fine.
+ if (odev->pic_mode == ASUS_OLED_ROLL)
+ send_packets(odev->udev, packet, odev->buf, ASUS_OLED_STATIC, 2);
+
+ // Only ROLL mode can use more than 2 packets.
+ if (odev->pic_mode != ASUS_OLED_ROLL && packet_num > 2)
+ packet_num = 2;
+
+ send_packets(odev->udev, packet, odev->buf, odev->pic_mode, packet_num);
+ }
+ else
+ if (odev->pack_mode==PACK_MODE_G50){
+ send_packets_g50(odev->udev, packet, odev->buf);
+ }
+
+ kfree(packet);
+}
+
+static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
+{
+ while (count-- > 0) {
+ if (val) {
+ size_t x = odev->buf_offs % odev->width;
+ size_t y = odev->buf_offs / odev->width;
+ size_t i;
+
+ x += odev->x_shift;
+ y += odev->y_shift;
+
+ switch(odev->pack_mode)
+ {
+ case PACK_MODE_G1:
+ // i = (x/128)*640 + 127 - x + (y/8)*128;
+ // This one for 128 is the same, but might be better for different widths?
+ i = (x/odev->dev_width)*640 + odev->dev_width - 1 - x + (y/8)*odev->dev_width;
+ break;
+
+ case PACK_MODE_G50:
+ i = (odev->dev_width - 1 - x)/8 + y*odev->dev_width/8;
+ break;
+
+ default:
+ i = 0;
+ printk(ASUS_OLED_ERROR "Unknown OLED Pack Mode: %d!\n", odev->pack_mode);
+ break;
+ }
+
+ if (i >= odev->buf_size) {
+ printk(ASUS_OLED_ERROR "Buffer overflow! Report a bug in the driver: offs: %d >= %d i: %d (x: %d y: %d)\n",
+ (int) odev->buf_offs, (int) odev->buf_size, (int) i, (int) x, (int) y);
+ return -EIO;
+ }
+
+ switch (odev->pack_mode)
+ {
+ case PACK_MODE_G1:
+ odev->buf[i] &= ~(1<<(y%8));
+ break;
+
+ case PACK_MODE_G50:
+ odev->buf[i] &= ~(1<<(x%8));
+ break;
+
+ default:
+ // cannot get here; stops gcc complaining
+ ;
+ }
+ }
+
+ odev->last_val = val;
+ odev->buf_offs++;
+ }
+
+ return 0;
+}
+
+static ssize_t odev_set_picture(struct asus_oled_dev *odev, const char *buf, size_t count)
+{
+ size_t offs = 0, max_offs;
+
+ if (count < 1) return 0;
+
+ if (tolower(buf[0]) == 'b'){
+ // binary mode, set the entire memory
+
+ size_t i;
+
+ odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8;
+
+ if (odev->buf) kfree(odev->buf);
+ odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
+
+ memset(odev->buf, 0xff, odev->buf_size);
+
+ for (i=1; i < count && i<=32*32; i++){
+ odev->buf[i-1] = buf[i];
+ odev->buf_offs = i-1;
+ }
+
+ odev->width=odev->dev_width / 8;
+ odev->height=ASUS_OLED_DISP_HEIGHT;
+ odev->x_shift=0;
+ odev->y_shift=0;
+ odev->last_val=0;
+
+ send_data(odev);
+
+ return count;
+ }
+
+ if (buf[0] == '<') {
+ size_t i;
+ size_t w = 0, h = 0;
+ size_t w_mem, h_mem;
+
+ if (count < 10 || buf[2] != ':') {
+ goto error_header;
+ }
+
+ switch(tolower(buf[1])) {
+ case ASUS_OLED_STATIC:
+ case ASUS_OLED_ROLL:
+ case ASUS_OLED_FLASH:
+ odev->pic_mode = buf[1];
+ break;
+ default:
+ printk(ASUS_OLED_ERROR "Wrong picture mode: '%c'.\n", buf[1]);
+ return -EIO;
+ break;
+ }
+
+ for (i = 3; i < count; ++i) {
+ if (buf[i] >= '0' && buf[i] <= '9') {
+ w = 10*w + (buf[i] - '0');
+
+ if (w > ASUS_OLED_MAX_WIDTH) goto error_width;
+ }
+ else if (tolower(buf[i]) == 'x') break;
+ else goto error_width;
+ }
+
+ for (++i; i < count; ++i) {
+ if (buf[i] >= '0' && buf[i] <= '9') {
+ h = 10*h + (buf[i] - '0');
+
+ if (h > ASUS_OLED_DISP_HEIGHT) goto error_height;
+ }
+ else if (tolower(buf[i]) == '>') break;
+ else goto error_height;
+ }
+
+ if (w < 1 || w > ASUS_OLED_MAX_WIDTH) goto error_width;
+
+ if (h < 1 || h > ASUS_OLED_DISP_HEIGHT) goto error_height;
+
+ if (i >= count || buf[i] != '>') goto error_header;
+
+ offs = i+1;
+
+ if (w % (odev->dev_width) != 0)
+ w_mem = (w/(odev->dev_width) + 1)*(odev->dev_width);
+ else
+ w_mem = w;
+
+ if (h < ASUS_OLED_DISP_HEIGHT)
+ h_mem = ASUS_OLED_DISP_HEIGHT;
+ else
+ h_mem = h;
+
+ odev->buf_size = w_mem * h_mem / 8;
+
+ if (odev->buf) kfree(odev->buf);
+ odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
+
+ if (odev->buf == NULL) {
+ odev->buf_size = 0;
+ printk(ASUS_OLED_ERROR "Out of memory!\n");
+ return -ENOMEM;
+ }
+
+ memset(odev->buf, 0xff, odev->buf_size);
+
+ odev->buf_offs = 0;
+ odev->width = w;
+ odev->height = h;
+ odev->x_shift = 0;
+ odev->y_shift = 0;
+ odev->last_val = 0;
+
+ if (odev->pic_mode == ASUS_OLED_FLASH) {
+ if (h < ASUS_OLED_DISP_HEIGHT/2)
+ odev->y_shift = (ASUS_OLED_DISP_HEIGHT/2 - h)/2;
+ }
+ else {
+ if (h < ASUS_OLED_DISP_HEIGHT)
+ odev->y_shift = (ASUS_OLED_DISP_HEIGHT - h)/2;
+ }
+
+ if (w < (odev->dev_width))
+ odev->x_shift = ((odev->dev_width) - w)/2;
+ }
+
+ max_offs = odev->width * odev->height;
+
+ while (offs < count && odev->buf_offs < max_offs) {
+ int ret;
+
+ if (buf[offs] == '1' || buf[offs] == '#') {
+ if ( (ret = append_values(odev, 1, 1)) < 0) return ret;
+ }
+ else if (buf[offs] == '0' || buf[offs] == ' ') {
+ if ( (ret = append_values(odev, 0, 1)) < 0) return ret;
+ }
+ else if (buf[offs] == '\n') {
+ // New line detected. Lets assume, that all characters till the end of the
+ // line were equal to the last character in this line.
+ if (odev->buf_offs % odev->width != 0)
+ if ( (ret = append_values(odev, odev->last_val,
+ odev->width - (odev->buf_offs % odev->width))) < 0) return ret;
+ }
+
+ offs++;
+ }
+
+ if (odev->buf_offs >= max_offs) send_data(odev);
+
+ return count;
+
+error_width:
+ printk(ASUS_OLED_ERROR "Wrong picture width specified.\n");
+ return -EIO;
+
+error_height:
+ printk(ASUS_OLED_ERROR "Wrong picture height specified.\n");
+ return -EIO;
+
+error_header:
+ printk(ASUS_OLED_ERROR "Wrong picture header.\n");
+ return -EIO;
+}
+
+static ssize_t set_picture(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct usb_interface *intf = to_usb_interface(dev);
+
+ return odev_set_picture(usb_get_intfdata(intf), buf, count);
+}
+
+static ssize_t class_set_picture(struct device *device, struct device_attribute *attr, const char *buf, size_t count)
+{
+ return odev_set_picture((struct asus_oled_dev *) dev_get_drvdata(device), buf, count);
+}
+
+#define ASUS_OLED_DEVICE_ATTR(_file) dev_attr_asus_oled_##_file
+
+static DEVICE_ATTR(asus_oled_enabled, S_IWUGO | S_IRUGO, get_enabled, set_enabled);
+static DEVICE_ATTR(asus_oled_picture, S_IWUGO , NULL, set_picture);
+
+static DEVICE_ATTR(enabled, S_IWUGO | S_IRUGO, class_get_enabled, class_set_enabled);
+static DEVICE_ATTR(picture, S_IWUGO, NULL, class_set_picture);
+
+static int asus_oled_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ struct asus_oled_dev *odev = NULL;
+ int retval = -ENOMEM;
+ uint16_t dev_width = 0;
+ oled_pack_mode_t pack_mode = PACK_MODE_LAST;
+ const struct oled_dev_desc_str * dev_desc = oled_dev_desc_table;
+ const char *desc = 0;
+
+ if (id == 0) {
+ // Even possible? Just to make sure...
+ dev_err(&interface->dev, "No usb_device_id provided!\n");
+ return -ENODEV;
+ }
+
+ for (; dev_desc->idVendor; dev_desc++)
+ {
+ if (dev_desc->idVendor == id->idVendor
+ && dev_desc->idProduct == id->idProduct)
+ {
+ dev_width = dev_desc->devWidth;
+ desc = dev_desc->devDesc;
+ pack_mode = dev_desc->packMode;
+ break;
+ }
+ }
+
+ if ( !desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) {
+ dev_err(&interface->dev, "Missing or incomplete device description!\n");
+ return -ENODEV;
+ }
+
+ odev = kzalloc(sizeof(struct asus_oled_dev), GFP_KERNEL);
+
+ if (odev == NULL) {
+ dev_err(&interface->dev, "Out of memory\n");
+ return -ENOMEM;
+ }
+
+ odev->udev = usb_get_dev(udev);
+ odev->pic_mode = ASUS_OLED_STATIC;
+ odev->dev_width = dev_width;
+ odev->pack_mode = pack_mode;
+ odev->height = 0;
+ odev->width = 0;
+ odev->x_shift = 0;
+ odev->y_shift = 0;
+ odev->buf_offs = 0;
+ odev->buf_size = 0;
+ odev->last_val = 0;
+ odev->buf = NULL;
+ odev->enabled = 1;
+ odev->dev = 0;
+
+ usb_set_intfdata (interface, odev);
+
+ if ((retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)))) {
+ goto err_files;
+ }
+
+ if ((retval = device_create_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)))) {
+ goto err_files;
+ }
+
+ odev->dev = device_create(oled_class, &interface->dev, MKDEV(0,0),
+ NULL,"oled_%d", ++oled_num);
+
+ if (IS_ERR(odev->dev)) {
+ retval = PTR_ERR(odev->dev);
+ goto err_files;
+ }
+
+ dev_set_drvdata(odev->dev, odev);
+
+ if ( (retval = device_create_file(odev->dev, &dev_attr_enabled))) {
+ goto err_class_enabled;
+ }
+
+ if ( (retval = device_create_file(odev->dev, &dev_attr_picture))) {
+ goto err_class_picture;
+ }
+
+ dev_info(&interface->dev, "Attached Asus OLED device: %s [width %u, pack_mode %d]\n", desc, odev->dev_width, odev->pack_mode);
+
+ if (start_off)
+ enable_oled(odev, 0);
+
+ return 0;
+
+err_class_picture:
+ device_remove_file(odev->dev, &dev_attr_picture);
+
+err_class_enabled:
+ device_remove_file(odev->dev, &dev_attr_enabled);
+ device_unregister(odev->dev);
+
+err_files:
+ device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled));
+ device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture));
+
+ usb_set_intfdata (interface, NULL);
+ usb_put_dev(odev->udev);
+ kfree(odev);
+
+ return retval;
+}
+
+static void asus_oled_disconnect(struct usb_interface *interface)
+{
+ struct asus_oled_dev *odev;
+
+ odev = usb_get_intfdata (interface);
+ usb_set_intfdata (interface, NULL);
+
+ device_remove_file(odev->dev, &dev_attr_picture);
+ device_remove_file(odev->dev, &dev_attr_enabled);
+ device_unregister(odev->dev);
+
+ device_remove_file(&interface->dev, & ASUS_OLED_DEVICE_ATTR(picture));
+ device_remove_file(&interface->dev, & ASUS_OLED_DEVICE_ATTR(enabled));
+
+ usb_put_dev(odev->udev);
+
+ if (odev->buf) kfree(odev->buf);
+
+ kfree(odev);
+
+ dev_info(&interface->dev, "Disconnected Asus OLED device\n");
+}
+
+static struct usb_driver oled_driver = {
+ .name = ASUS_OLED_NAME,
+ .probe = asus_oled_probe,
+ .disconnect = asus_oled_disconnect,
+ .id_table = id_table,
+};
+
+static ssize_t version_show(struct class *dev, char *buf)
+{
+ return sprintf(buf, ASUS_OLED_UNDERSCORE_NAME " %s\n", ASUS_OLED_VERSION);
+}
+
+static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
+
+static int __init asus_oled_init(void)
+{
+ int retval = 0;
+ oled_class = class_create(THIS_MODULE, ASUS_OLED_UNDERSCORE_NAME);
+
+ if (IS_ERR(oled_class)) {
+ err("Error creating " ASUS_OLED_UNDERSCORE_NAME " class");
+ return PTR_ERR(oled_class);
+ }
+
+ if ((retval = class_create_file(oled_class, &class_attr_version))) {
+ err("Error creating class version file");
+ goto error;
+ }
+
+ retval = usb_register(&oled_driver);
+
+ if (retval) {
+ err("usb_register failed. Error number %d", retval);
+ goto error;
+ }
+
+ return retval;
+
+error:
+ class_destroy(oled_class);
+ return retval;
+}
+
+static void __exit asus_oled_exit(void)
+{
+ class_remove_file(oled_class, &class_attr_version);
+ class_destroy(oled_class);
+
+ usb_deregister(&oled_driver);
+}
+
+module_init (asus_oled_init);
+module_exit (asus_oled_exit);
+
diff --git a/drivers/staging/asus_oled/linux.txt b/drivers/staging/asus_oled/linux.txt
new file mode 100644
index 000000000000..dc758b0eb379
--- /dev/null
+++ b/drivers/staging/asus_oled/linux.txt
@@ -0,0 +1,33 @@
+<s:74x32>
+0
+0
+00000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000
+01111111111000000000000000000000000000000000000000000000000000000000000000
+00011111100000000000000111000000000000000000000000000000000000000000000000
+00001111000000000000000111000000000000000000000000000000000000000000000000
+00001111000000000000000111000000000000000000000000000000000000000000000000
+00001111000000000000000000000000000000000000000000000000000000000000000000
+00001111000000000000000000000000000000000000000000000000000000000000000000
+00001111000000000000011100001111111111100000111110011111100011111101111000
+00001111000000000000111110000011111000111000111110000111100001111000110000
+00001111000000000001101110000011111000111000001111000111100000111100100000
+00001111000000000001001110000011110000111100001111000111100000111101100000
+00001111000000000100001110000011110000111100001111000111100000011111000000
+00001111000000000100011110000011110000111100001111000111100000001111000000
+00001111000000000100011110000011110000111100001111000111100000001111000000
+00001111000000000100011100100011110000111100001111000111100000001111100000
+00001111000000001100111100100011110000111100001111000111100000001111110000
+00001111000000001100111101100011110000111100001111000111100000011011110000
+00001111000000011100111101000011110000111100001111000111100000010001111000
+00011111000001111100111011000011110000111100001111001111100000110000111100
+11111111111111111100011110001111111011111110000111110111111011111011111110
+00000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000
+0
+0
+0
+0
diff --git a/drivers/staging/asus_oled/linux_f.txt b/drivers/staging/asus_oled/linux_f.txt
new file mode 100644
index 000000000000..b4bb85cc6ebb
--- /dev/null
+++ b/drivers/staging/asus_oled/linux_f.txt
@@ -0,0 +1,18 @@
+<f:128x16>
+00000000000000000000000000000000001111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000011000111111111100001111001111100111110111000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000111100001111000110001111000111100011100010000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000001011100001111000111000111100111100001110110000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000011100001110000111000111100111100001111100000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000100111001001110000111000111100111100000111110000000000000000000000000000000000000
+00000000000000000000000000000000000011110000001100111011001110000111000111100111100000111110000000000000000000000000000000000000
+00000000000000000000000000000000000011110000001100111010001110000111000111100111100000100111000000000000000000000000000000000000
+00000000000000000000000000000000000011110000111100110110001110000111000111100111100001000011100000000000000000000000000000000000
+00000000000000000000000000000000001111111111111100111100111111011111100011110111110111101111110000000000000000000000000000000000
+
diff --git a/drivers/staging/asus_oled/linux_fr.txt b/drivers/staging/asus_oled/linux_fr.txt
new file mode 100644
index 000000000000..f88e2b3bdd1b
--- /dev/null
+++ b/drivers/staging/asus_oled/linux_fr.txt
@@ -0,0 +1,33 @@
+<f:128x32>
+00000000000000000000000000000000001111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000011000111111111100001111001111100111110111000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000111100001111000110001111000111100011100010000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000001011100001111000111000111100111100001110110000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000000011100001110000111000111100111100001111100000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000
+00000000000000000000000000000000000011110000000100111001001110000111000111100111100000111110000000000000000000000000000000000000
+00000000000000000000000000000000000011110000001100111011001110000111000111100111100000111110000000000000000000000000000000000000
+00000000000000000000000000000000000011110000001100111010001110000111000111100111100000100111000000000000000000000000000000000000
+00000000000000000000000000000000000011110000111100110110001110000111000111100111100001000011100000000000000000000000000000000000
+00000000000000000000000000000000001111111111111100111100111111011111100011110111110111101111110000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000
+00000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000
+00000000000000000000000000011111100000000000000000000000000000000000000000000000000000000000011111100000000000000000000000000000
+00000000000000000000000000011111100000000000000000000000000000000000000000000000000000000000011111100000000000000000000000000000
+00000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000
+00000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
diff --git a/drivers/staging/asus_oled/tux.txt b/drivers/staging/asus_oled/tux.txt
new file mode 100644
index 000000000000..9d2052854b64
--- /dev/null
+++ b/drivers/staging/asus_oled/tux.txt
@@ -0,0 +1,33 @@
+<s:32x32>
+00000000000001111111000000000000
+0000000000001 100000000000
+000000000001 10000000000
+000000000001 10000000000
+000000000001 10000000000
+000000000001 1 111 10000000000
+000000000001 1 1 1000000000
+000000000001 111 1000000000
+000000000001 111111 1000000000
+000000000001 111111 1000000000
+000000000001 1 1 100000000
+00000000001 11 100000000
+00000000001 11111111 10000000
+0000000001 11111111 1000000
+000000001 111111111 1000000
+000000001 1111111111 100000
+00000001 11111111111 100000
+00000001 111111111111 10000
+0000001 111111111111 10000
+0000001 111111111111 10000
+0000001 111111111111 10000
+0000001 111111111111 10000
+000000011 11111111111 10000
+000011 11 11111111111 100000
+0001 1111 111111111111111 1000
+001 1111111 11111111111111 1000
+001 1111111 1111111 111111 100
+001 11111111 111111 1111111 10
+001 11111111 11111 100
+001 1111111 111 11100
+000111 111 11111 11 100000
+000000111 111111111 1000000
diff --git a/drivers/staging/asus_oled/tux_r.txt b/drivers/staging/asus_oled/tux_r.txt
new file mode 100644
index 000000000000..fd81a3e84949
--- /dev/null
+++ b/drivers/staging/asus_oled/tux_r.txt
@@ -0,0 +1,33 @@
+<r:32x32>
+00000000000001111111000000000000
+0000000000001 100000000000
+000000000001 10000000000
+000000000001 10000000000
+000000000001 10000000000
+000000000001 1 111 10000000000
+000000000001 1 1 1000000000
+000000000001 111 1000000000
+000000000001 111111 1000000000
+000000000001 111111 1000000000
+000000000001 1 1 100000000
+00000000001 11 100000000
+00000000001 11111111 10000000
+0000000001 11111111 1000000
+000000001 111111111 1000000
+000000001 1111111111 100000
+00000001 11111111111 100000
+00000001 111111111111 10000
+0000001 111111111111 10000
+0000001 111111111111 10000
+0000001 111111111111 10000
+0000001 111111111111 10000
+000000011 11111111111 10000
+000011 11 11111111111 100000
+0001 1111 111111111111111 1000
+001 1111111 11111111111111 1000
+001 1111111 1111111 111111 100
+001 11111111 111111 1111111 10
+001 11111111 11111 100
+001 1111111 111 11100
+000111 111 11111 11 100000
+000000111 111111111 1000000
diff --git a/drivers/staging/asus_oled/tux_r2.txt b/drivers/staging/asus_oled/tux_r2.txt
new file mode 100644
index 000000000000..e94d84eaab0b
--- /dev/null
+++ b/drivers/staging/asus_oled/tux_r2.txt
@@ -0,0 +1,33 @@
+<r:256x32>
+000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 1 111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 1 1 100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111100000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000001 1 1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000001 11 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000001 11111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000011100001111111111100000111110011111100011111101111000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000001 11111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000111110000011111000111000111110000111100001111000110000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000001 111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000001101110000011111000111000001111000111100000111100100000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000001 1111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000001001110000011110000111100001111000111100000111101100000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000001 11111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100001110000011110000111100001111000111100000011111000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000001 111111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000011110000000001000111100000111100001111000011110001111000000011110000000
+0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100011110000011110000111100001111000111100000001111000000
+0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100011100100011110000111100001111000111100000001111100000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000001100111100100011110000111100001111000111100000001111110000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000001100111101100011110000111100001111000111100000011011110000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000011 11111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000011100111101000011110000111100001111000111100000010001111000000000000000000000000000000
+000000000000000000000000000000000000000000000000000011 11 11111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000011111000001111100111011000011110000111100001111001111100000110000111100000000000000000000000000000
+0000000000000000000000000000000000000000000000000001 1111 111111111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111100011110001111111011111110000111110111111011111011111110000000000000000000000000000
+000000000000000000000000000000000000000000000000001 1111111 11111111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000001 1111111 1111111 111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000001 11111111 111111 1111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000001 11111111 11111 1000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000001 1111111 111 111000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000111 111 11111 11 10
+000000000000000000000000000000000000000000000000000000111 111111111 10
diff --git a/drivers/staging/asus_oled/zig.txt b/drivers/staging/asus_oled/zig.txt
new file mode 100644
index 000000000000..31573d8f799a
--- /dev/null
+++ b/drivers/staging/asus_oled/zig.txt
@@ -0,0 +1,33 @@
+<r:128x32>
+10000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001
+01000000000000000000000000000000000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000010
+00100000000000000000000000000000000000000000000000000000000001000010000000000000000000000000000000000000000000000000000000000100
+00010000000000000000000000000000000000000000000000000000000010000001000000000000000000000000000000000000000000000000000000001000
+00001000000000000000000000000000000000000000000000000000000100000000100000000000000000000000000000000000000000000000000000010000
+00000100000000000000000000000000000000000000000000000000001000000000010000000000000000000000000000000000000000000000000000100000
+00000010000000000000000000000000000000000000000000000000010000000000001000000000000000000000000000000000000000000000000001000000
+00000001000000000000000000000000000000000000000000000000100000000000000100000000000000000000000000000000000000000000000010000000
+00000000100000000000000000000000000000000000000000000001000000000000000010000000000000000000000000000000000000000000000100000000
+00000000010000000000000000000000000000000000000000000010000000000000000001000000000000000000000000000000000000000000001000000000
+00000000001000000000000000000000000000000000000000000100000000000000000000100000000000000000000000000000000000000000010000000000
+00000000000100000000000000000000000000000000000000001000000000000000000000010000000000000000000000000000000000000000100000000000
+00000000000010000000000000000000000000000000000000010000000000000000000000001000000000000000000000000000000000000001000000000000
+00000000000001000000000000000000000000000000000000100000000000000000000000000100000000000000000000000000000000000010000000000000
+00000000000000100000000000000000000000000000000001000000000000000000000000000010000000000000000000000000000000000100000000000000
+00000000000000010000000000000000000000000000000010000000000000000000000000000001000000000000000000000000000000001000000000000000
+00000000000000001000000000000000000000000000000100000000000000000000000000000000100000000000000000000000000000010000000000000000
+00000000000000000100000000000000000000000000001000000000000000000000000000000000010000000000000000000000000000100000000000000000
+00000000000000000010000000000000000000000000010000000000000000000000000000000000001000000000000000000000000001000000000000000000
+00000000000000000001000000000000000000000000100000000000000000000000000000000000000100000000000000000000000010000000000000000000
+00000000000000000000100000000000000000000001000000000000000000000000000000000000000010000000000000000000000100000000000000000000
+00000000000000000000010000000000000000000010000000000000000000000000000000000000000001000000000000000000001000000000000000000000
+00000000000000000000001000000000000000000100000000000000000000000000000000000000000000100000000000000000010000000000000000000000
+00000000000000000000000100000000000000001000000000000000000000000000000000000000000000010000000000000000100000000000000000000000
+00000000000000000000000010000000000000010000000000000000000000000000000000000000000000001000000000000001000000000000000000000000
+00000000000000000000000001000000000000100000000000000000000000000000000000000000000000000100000000000010000000000000000000000000
+00000000000000000000000000100000000001000000000000000000000000000000000000000000000000000010000000000100000000000000000000000000
+00000000000000000000000000010000000010000000000000000000000000000000000000000000000000000001000000001000000000000000000000000000
+00000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000100000010000000000000000000000000000
+00000000000000000000000000000100001000000000000000000000000000000000000000000000000000000000010000100000000000000000000000000000
+00000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000
+00000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000
diff --git a/drivers/staging/at76_usb/Kconfig b/drivers/staging/at76_usb/Kconfig
index 8606f9621624..4c0e55e15448 100644
--- a/drivers/staging/at76_usb/Kconfig
+++ b/drivers/staging/at76_usb/Kconfig
@@ -1,6 +1,6 @@
config USB_ATMEL
tristate "Atmel at76c503/at76c505/at76c505a USB cards"
- depends on WLAN_80211 && USB
+ depends on MAC80211 && WLAN_80211 && USB
default N
select FW_LOADER
---help---
diff --git a/drivers/staging/at76_usb/at76_usb.c b/drivers/staging/at76_usb/at76_usb.c
index 174e2bec9223..185533e54769 100644
--- a/drivers/staging/at76_usb/at76_usb.c
+++ b/drivers/staging/at76_usb/at76_usb.c
@@ -6,6 +6,7 @@
* Copyright (c) 2004 Nick Jones
* Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
* Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org>
+ * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -16,6 +17,13 @@
* Atmel AT76C503A/505/505A.
*
* Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed
+ *
+ * TODO for the mac80211 port:
+ * o adhoc support
+ * o RTS/CTS support
+ * o Power Save Mode support
+ * o support for short/long preambles
+ * o export variables through debugfs/sysfs
*/
#include <linux/init.h>
@@ -36,7 +44,7 @@
#include <net/ieee80211_radiotap.h>
#include <linux/firmware.h>
#include <linux/leds.h>
-#include <net/ieee80211.h>
+#include <net/mac80211.h>
#include "at76_usb.h"
@@ -76,31 +84,43 @@
#define DBG_WE_EVENTS 0x08000000 /* dump wireless events */
#define DBG_FW 0x10000000 /* firmware download */
#define DBG_DFU 0x20000000 /* device firmware upgrade */
+#define DBG_CMD 0x40000000
+#define DBG_MAC80211 0x80000000
#define DBG_DEFAULTS 0
/* Use our own dbg macro */
#define at76_dbg(bits, format, arg...) \
- do { \
- if (at76_debug & (bits)) \
+do { \
+ if (at76_debug & (bits)) \
+ printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \
+} while (0)
+
+#define at76_dbg_dump(bits, buf, len, format, arg...) \
+do { \
+ if (at76_debug & (bits)) { \
printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \
- } while (0)
+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); \
+ } \
+} while (0)
static int at76_debug = DBG_DEFAULTS;
+#define FIRMWARE_IS_WPA(ver) ((ver.major == 1) && (ver.minor == 103))
+
/* Protect against concurrent firmware loading and parsing */
static struct mutex fw_mutex;
static struct fwentry firmwares[] = {
- [0] = {""},
- [BOARD_503_ISL3861] = {"atmel_at76c503-i3861.bin"},
- [BOARD_503_ISL3863] = {"atmel_at76c503-i3863.bin"},
- [BOARD_503] = {"atmel_at76c503-rfmd.bin"},
- [BOARD_503_ACC] = {"atmel_at76c503-rfmd-acc.bin"},
- [BOARD_505] = {"atmel_at76c505-rfmd.bin"},
- [BOARD_505_2958] = {"atmel_at76c505-rfmd2958.bin"},
- [BOARD_505A] = {"atmel_at76c505a-rfmd2958.bin"},
- [BOARD_505AMX] = {"atmel_at76c505amx-rfmd.bin"},
+ [0] = { "" },
+ [BOARD_503_ISL3861] = { "atmel_at76c503-i3861.bin" },
+ [BOARD_503_ISL3863] = { "atmel_at76c503-i3863.bin" },
+ [BOARD_503] = { "atmel_at76c503-rfmd.bin" },
+ [BOARD_503_ACC] = { "atmel_at76c503-rfmd-acc.bin" },
+ [BOARD_505] = { "atmel_at76c505-rfmd.bin" },
+ [BOARD_505_2958] = { "atmel_at76c505-rfmd2958.bin" },
+ [BOARD_505A] = { "atmel_at76c505a-rfmd2958.bin" },
+ [BOARD_505AMX] = { "atmel_at76c505amx-rfmd.bin" },
};
#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
@@ -110,133 +130,133 @@ static struct usb_device_id dev_table[] = {
* at76c503-i3861
*/
/* Generic AT76C503/3861 device */
- {USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Linksys WUSB11 v2.1/v2.6 */
- {USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Netgear MA101 rev. A */
- {USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Tekram U300C / Allnet ALL0193 */
- {USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* HP HN210W J7801A */
- {USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Sitecom/Z-Com/Zyxel M4Y-750 */
- {USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Dynalink/Askey WLL013 (intersil) */
- {USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */
- {USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* BenQ AWL300 */
- {USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Addtron AWU-120, Compex WLU11 */
- {USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Intel AP310 AnyPoint II USB */
- {USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Dynalink L11U */
- {USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* Arescom WL-210, FCC id 07J-GL2411USB */
- {USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* I-O DATA WN-B11/USB */
- {USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/* BT Voyager 1010 */
- {USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861)},
+ { USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861) },
/*
* at76c503-i3863
*/
/* Generic AT76C503/3863 device */
- {USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863)},
+ { USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863) },
/* Samsung SWL-2100U */
- {USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863)},
+ { USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863) },
/*
* at76c503-rfmd
*/
/* Generic AT76C503/RFMD device */
- {USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503) },
/* Dynalink/Askey WLL013 (rfmd) */
- {USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503) },
/* Linksys WUSB11 v2.6 */
- {USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503) },
/* Network Everywhere NWU11B */
- {USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503) },
/* Netgear MA101 rev. B */
- {USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503) },
/* D-Link DWL-120 rev. E */
- {USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503) },
/* Actiontec 802UAT1, HWU01150-01UK */
- {USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503) },
/* AirVast W-Buddie WN210 */
- {USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503) },
/* Dick Smith Electronics XH1153 802.11b USB adapter */
- {USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503) },
/* CNet CNUSB611 */
- {USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503) },
/* FiberLine FL-WL200U */
- {USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503) },
/* BenQ AWL400 USB stick */
- {USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) },
/* 3Com 3CRSHEW696 */
- {USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) },
/* Siemens Santis ADSL WLAN USB adapter WLL 013 */
- {USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) },
/* Belkin F5D6050, version 2 */
- {USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) },
/* iBlitzz, BWU613 (not *B or *SB) */
- {USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503) },
/* Gigabyte GN-WLBM101 */
- {USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503) },
/* Planex GW-US11S */
- {USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503) },
/* Internal WLAN adapter in h5[4,5]xx series iPAQs */
- {USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503) },
/* Corega Wireless LAN USB-11 mini */
- {USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503) },
/* Corega Wireless LAN USB-11 mini2 */
- {USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503) },
/* Uniden PCW100 */
- {USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503)},
+ { USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503) },
/*
* at76c503-rfmd-acc
*/
/* SMC2664W */
- {USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC)},
+ { USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC) },
/* Belkin F5D6050, SMC2662W v2, SMC2662W-AR */
- {USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC)},
+ { USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC) },
/*
* at76c505-rfmd
*/
/* Generic AT76C505/RFMD */
- {USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505)},
+ { USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505) },
/*
* at76c505-rfmd2958
*/
/* Generic AT76C505/RFMD, OvisLink WL-1130USB */
- {USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)},
+ { USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) },
/* Fiberline FL-WL240U */
- {USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958)},
+ { USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958) },
/* CNet CNUSB-611G */
- {USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958)},
+ { USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958) },
/* Linksys WUSB11 v2.8 */
- {USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958)},
+ { USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) },
/* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */
- {USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958)},
+ { USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) },
/* Corega WLAN USB Stick 11 */
- {USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958)},
+ { USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) },
/* Microstar MSI Box MS6978 */
- {USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958)},
+ { USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) },
/*
* at76c505a-rfmd2958
*/
/* Generic AT76C505A device */
- {USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A)},
+ { USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A) },
/* Generic AT76C505AS device */
- {USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A)},
+ { USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A) },
/* Siemens Gigaset USB WLAN Adapter 11 */
- {USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A)},
+ { USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A) },
/*
* at76c505amx-rfmd
*/
/* Generic AT76C505AMX device */
- {USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX)},
- {}
+ { USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX) },
+ { }
};
MODULE_DEVICE_TABLE(usb, dev_table);
@@ -244,26 +264,8 @@ MODULE_DEVICE_TABLE(usb, dev_table);
/* Supported rates of this hardware, bit 7 marks basic rates */
static const u8 hw_rates[] = { 0x82, 0x84, 0x0b, 0x16 };
-/* Frequency of each channel in MHz */
-static const long channel_frequency[] = {
- 2412, 2417, 2422, 2427, 2432, 2437, 2442,
- 2447, 2452, 2457, 2462, 2467, 2472, 2484
-};
-
-#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
-
static const char *const preambles[] = { "long", "short", "auto" };
-static const char *const mac_states[] = {
- [MAC_INIT] = "INIT",
- [MAC_SCANNING] = "SCANNING",
- [MAC_AUTH] = "AUTH",
- [MAC_ASSOC] = "ASSOC",
- [MAC_JOINING] = "JOINING",
- [MAC_CONNECTED] = "CONNECTED",
- [MAC_OWN_IBSS] = "OWN_IBSS"
-};
-
/* Firmware download */
/* DFU states */
#define STATE_IDLE 0x00
@@ -298,17 +300,30 @@ struct dfu_status {
static inline int at76_is_intersil(enum board_type board)
{
- return (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863);
+ if (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863)
+ return 1;
+ return 0;
}
static inline int at76_is_503rfmd(enum board_type board)
{
- return (board == BOARD_503 || board == BOARD_503_ACC);
+ if (board == BOARD_503 || board == BOARD_503_ACC)
+ return 1;
+ return 0;
+}
+
+static inline int at76_is_505(enum board_type board)
+{
+ if (board == BOARD_505 || board == BOARD_505_2958)
+ return 1;
+ return 0;
}
static inline int at76_is_505a(enum board_type board)
{
- return (board == BOARD_505A || board == BOARD_505AMX);
+ if (board == BOARD_505A || board == BOARD_505AMX)
+ return 1;
+ return 0;
}
/* Load a block of the first (internal) part of the firmware */
@@ -489,41 +504,6 @@ exit:
return ret;
}
-/* Report that the scan results are ready */
-static inline void at76_iwevent_scan_complete(struct net_device *netdev)
-{
- union iwreq_data wrqu;
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- wireless_send_event(netdev, SIOCGIWSCAN, &wrqu, NULL);
- at76_dbg(DBG_WE_EVENTS, "%s: SIOCGIWSCAN sent", netdev->name);
-}
-
-static inline void at76_iwevent_bss_connect(struct net_device *netdev,
- u8 *bssid)
-{
- union iwreq_data wrqu;
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL);
- at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name,
- __func__);
-}
-
-static inline void at76_iwevent_bss_disconnect(struct net_device *netdev)
-{
- union iwreq_data wrqu;
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(netdev, SIOCGIWAP, &wrqu, NULL);
- at76_dbg(DBG_WE_EVENTS, "%s: %s: SIOCGIWAP sent", netdev->name,
- __func__);
-}
-
#define HEX2STR_BUFFERS 4
#define HEX2STR_MAX_LEN 64
#define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10)
@@ -595,37 +575,6 @@ static void at76_ledtrig_tx_activity(void)
mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4);
}
-/* Check if the given ssid is hidden */
-static inline int at76_is_hidden_ssid(u8 *ssid, int length)
-{
- static const u8 zeros[32];
-
- if (length == 0)
- return 1;
-
- if (length == 1 && ssid[0] == ' ')
- return 1;
-
- return (memcmp(ssid, zeros, length) == 0);
-}
-
-static inline void at76_free_bss_list(struct at76_priv *priv)
-{
- struct list_head *next, *ptr;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->bss_list_spinlock, flags);
-
- priv->curr_bss = NULL;
-
- list_for_each_safe(ptr, next, &priv->bss_list) {
- list_del(ptr);
- kfree(list_entry(ptr, struct bss_info, list));
- }
-
- spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
-}
-
static int at76_remap(struct usb_device *udev)
{
int ret;
@@ -641,18 +590,25 @@ static int at76_remap(struct usb_device *udev)
static int at76_get_op_mode(struct usb_device *udev)
{
int ret;
- u8 op_mode;
+ u8 saved;
+ u8 *op_mode;
+ op_mode = kmalloc(1, GFP_NOIO);
+ if (!op_mode)
+ return -ENOMEM;
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
USB_TYPE_VENDOR | USB_DIR_IN |
USB_RECIP_INTERFACE, 0x01, 0, &op_mode, 1,
USB_CTRL_GET_TIMEOUT);
+ saved = *op_mode;
+ kfree(op_mode);
+
if (ret < 0)
return ret;
else if (ret < 1)
return -EIO;
else
- return op_mode;
+ return saved;
}
/* Load a block of the second ("external") part of the firmware */
@@ -720,7 +676,7 @@ exit:
kfree(hwcfg);
if (ret < 0)
printk(KERN_ERR "%s: cannot get HW Config (error %d)\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
@@ -729,15 +685,15 @@ static struct reg_domain const *at76_get_reg_domain(u16 code)
{
int i;
static struct reg_domain const fd_tab[] = {
- {0x10, "FCC (USA)", 0x7ff}, /* ch 1-11 */
- {0x20, "IC (Canada)", 0x7ff}, /* ch 1-11 */
- {0x30, "ETSI (most of Europe)", 0x1fff}, /* ch 1-13 */
- {0x31, "Spain", 0x600}, /* ch 10-11 */
- {0x32, "France", 0x1e00}, /* ch 10-13 */
- {0x40, "MKK (Japan)", 0x2000}, /* ch 14 */
- {0x41, "MKK1 (Japan)", 0x3fff}, /* ch 1-14 */
- {0x50, "Israel", 0x3fc}, /* ch 3-9 */
- {0x00, "<unknown>", 0xffffffff} /* ch 1-32 */
+ { 0x10, "FCC (USA)", 0x7ff }, /* ch 1-11 */
+ { 0x20, "IC (Canada)", 0x7ff }, /* ch 1-11 */
+ { 0x30, "ETSI (most of Europe)", 0x1fff }, /* ch 1-13 */
+ { 0x31, "Spain", 0x600 }, /* ch 10-11 */
+ { 0x32, "France", 0x1e00 }, /* ch 10-13 */
+ { 0x40, "MKK (Japan)", 0x2000 }, /* ch 14 */
+ { 0x41, "MKK1 (Japan)", 0x3fff }, /* ch 1-14 */
+ { 0x50, "Israel", 0x3fc }, /* ch 3-9 */
+ { 0x00, "<unknown>", 0xffffffff } /* ch 1-32 */
};
/* Last entry is fallback for unknown domain code */
@@ -765,20 +721,43 @@ static inline int at76_get_mib(struct usb_device *udev, u16 mib, void *buf,
/* Return positive number for status, negative for an error */
static inline int at76_get_cmd_status(struct usb_device *udev, u8 cmd)
{
- u8 stat_buf[40];
+ u8 *stat_buf;
int ret;
+ stat_buf = kmalloc(40, GFP_NOIO);
+ if (!stat_buf)
+ return -ENOMEM;
+
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x22,
USB_TYPE_VENDOR | USB_DIR_IN |
USB_RECIP_INTERFACE, cmd, 0, stat_buf,
sizeof(stat_buf), USB_CTRL_GET_TIMEOUT);
- if (ret < 0)
- return ret;
+ if (ret >= 0)
+ ret = stat_buf[5];
+ kfree(stat_buf);
- return stat_buf[5];
+ return ret;
}
-static int at76_set_card_command(struct usb_device *udev, int cmd, void *buf,
+#define MAKE_CMD_CASE(c) case (c): return #c
+
+static const char *at76_get_cmd_string(u8 cmd_status)
+{
+ switch (cmd_status) {
+ MAKE_CMD_CASE(CMD_SET_MIB);
+ MAKE_CMD_CASE(CMD_GET_MIB);
+ MAKE_CMD_CASE(CMD_SCAN);
+ MAKE_CMD_CASE(CMD_JOIN);
+ MAKE_CMD_CASE(CMD_START_IBSS);
+ MAKE_CMD_CASE(CMD_RADIO_ON);
+ MAKE_CMD_CASE(CMD_RADIO_OFF);
+ MAKE_CMD_CASE(CMD_STARTUP);
+ }
+
+ return "UNKNOWN";
+}
+
+static int at76_set_card_command(struct usb_device *udev, u8 cmd, void *buf,
int buf_size)
{
int ret;
@@ -793,6 +772,10 @@ static int at76_set_card_command(struct usb_device *udev, int cmd, void *buf,
cmd_buf->size = cpu_to_le16(buf_size);
memcpy(cmd_buf->data, buf, buf_size);
+ at76_dbg_dump(DBG_CMD, cmd_buf, sizeof(struct at76_command) + buf_size,
+ "issuing command %s (0x%02x)",
+ at76_get_cmd_string(cmd), cmd);
+
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e,
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
0, 0, cmd_buf,
@@ -830,13 +813,13 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd)
status = at76_get_cmd_status(priv->udev, cmd);
if (status < 0) {
printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n",
- priv->netdev->name, status);
+ wiphy_name(priv->hw->wiphy), status);
break;
}
at76_dbg(DBG_WAIT_COMPLETE,
"%s: Waiting on cmd %d, status = %d (%s)",
- priv->netdev->name, cmd, status,
+ wiphy_name(priv->hw->wiphy), cmd, status,
at76_get_cmd_status_string(status));
if (status != CMD_STATUS_IN_PROGRESS
@@ -847,7 +830,7 @@ static int at76_wait_completion(struct at76_priv *priv, int cmd)
if (time_after(jiffies, timeout)) {
printk(KERN_ERR
"%s: completion timeout for command %d\n",
- priv->netdev->name, cmd);
+ wiphy_name(priv->hw->wiphy), cmd);
status = -ETIMEDOUT;
break;
}
@@ -870,7 +853,7 @@ static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf)
if (ret != CMD_STATUS_COMPLETE) {
printk(KERN_INFO
"%s: set_mib: at76_wait_completion failed "
- "with %d\n", priv->netdev->name, ret);
+ "with %d\n", wiphy_name(priv->hw->wiphy), ret);
ret = -EIO;
}
@@ -891,7 +874,7 @@ static int at76_set_radio(struct at76_priv *priv, int enable)
ret = at76_set_card_command(priv->udev, cmd, NULL, 0);
if (ret < 0)
printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n",
- priv->netdev->name, cmd, ret);
+ wiphy_name(priv->hw->wiphy), cmd, ret);
else
ret = 1;
@@ -912,44 +895,7 @@ static int at76_set_pm_mode(struct at76_priv *priv)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n",
- priv->netdev->name, ret);
-
- return ret;
-}
-
-/* Set the association id for power save mode */
-static int at76_set_associd(struct at76_priv *priv, u16 id)
-{
- int ret = 0;
-
- priv->mib_buf.type = MIB_MAC_MGMT;
- priv->mib_buf.size = 2;
- priv->mib_buf.index = offsetof(struct mib_mac_mgmt, station_id);
- priv->mib_buf.data.word = cpu_to_le16(id);
-
- ret = at76_set_mib(priv, &priv->mib_buf);
- if (ret < 0)
- printk(KERN_ERR "%s: set_mib (associd) failed: %d\n",
- priv->netdev->name, ret);
-
- return ret;
-}
-
-/* Set the listen interval for power save mode */
-static int at76_set_listen_interval(struct at76_priv *priv, u16 interval)
-{
- int ret = 0;
-
- priv->mib_buf.type = MIB_MAC;
- priv->mib_buf.size = 2;
- priv->mib_buf.index = offsetof(struct mib_mac, listen_interval);
- priv->mib_buf.data.word = cpu_to_le16(interval);
-
- ret = at76_set_mib(priv, &priv->mib_buf);
- if (ret < 0)
- printk(KERN_ERR
- "%s: set_mib (listen_interval) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
@@ -966,7 +912,7 @@ static int at76_set_preamble(struct at76_priv *priv, u8 type)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
@@ -983,7 +929,7 @@ static int at76_set_frag(struct at76_priv *priv, u16 size)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
@@ -1000,7 +946,7 @@ static int at76_set_rts(struct at76_priv *priv, u16 size)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
printk(KERN_ERR "%s: set_mib (rts) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
@@ -1017,24 +963,41 @@ static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
-static int at76_add_mac_address(struct at76_priv *priv, void *addr)
+static int at76_set_tkip_bssid(struct at76_priv *priv, const void *addr)
{
int ret = 0;
- priv->mib_buf.type = MIB_MAC_ADDR;
+ priv->mib_buf.type = MIB_MAC_ENCRYPTION;
priv->mib_buf.size = ETH_ALEN;
- priv->mib_buf.index = offsetof(struct mib_mac_addr, mac_addr);
+ priv->mib_buf.index = offsetof(struct mib_mac_encryption, tkip_bssid);
memcpy(priv->mib_buf.data.addr, addr, ETH_ALEN);
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
- printk(KERN_ERR "%s: set_mib (MAC_ADDR, mac_addr) failed: %d\n",
- priv->netdev->name, ret);
+ printk(KERN_ERR "%s: set_mib (MAC_ENCRYPTION, tkip_bssid) failed: %d\n",
+ wiphy_name(priv->hw->wiphy), ret);
+
+ return ret;
+}
+
+static int at76_reset_rsc(struct at76_priv *priv)
+{
+ int ret = 0;
+
+ priv->mib_buf.type = MIB_MAC_ENCRYPTION;
+ priv->mib_buf.size = 4 * 8;
+ priv->mib_buf.index = offsetof(struct mib_mac_encryption, key_rsc);
+ memset(priv->mib_buf.data.data, 0 , priv->mib_buf.size);
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret < 0)
+ printk(KERN_ERR "%s: set_mib (MAC_ENCRYPTION, key_rsc) failed: %d\n",
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
@@ -1053,16 +1016,16 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv)
sizeof(struct mib_mac_addr));
if (ret < 0) {
printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
goto exit;
}
at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x",
- priv->netdev->name,
+ wiphy_name(priv->hw->wiphy),
mac2str(m->mac_addr), m->res[0], m->res[1]);
for (i = 0; i < ARRAY_SIZE(m->group_addr); i++)
at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, "
- "status %d", priv->netdev->name, i,
+ "status %d", wiphy_name(priv->hw->wiphy), i,
mac2str(m->group_addr[i]), m->group_addr_status[i]);
exit:
kfree(m);
@@ -1082,13 +1045,13 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv)
sizeof(struct mib_mac_wep));
if (ret < 0) {
printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
goto exit;
}
at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: priv_invoked %u def_key_id %u "
"key_len %u excl_unencr %u wep_icv_err %u wep_excluded %u "
- "encr_level %u key %d", priv->netdev->name,
+ "encr_level %u key %d", wiphy_name(priv->hw->wiphy),
m->privacy_invoked, m->wep_default_key_id,
m->wep_key_mapping_len, m->exclude_unencrypted,
le32_to_cpu(m->wep_icv_error_count),
@@ -1100,12 +1063,55 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv)
for (i = 0; i < WEP_KEYS; i++)
at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s",
- priv->netdev->name, i,
+ wiphy_name(priv->hw->wiphy), i,
hex2str(m->wep_default_keyvalue[i], key_len));
exit:
kfree(m);
}
+static void at76_dump_mib_mac_encryption(struct at76_priv *priv)
+{
+ int i;
+ int ret;
+ /*int key_len;*/
+ struct mib_mac_encryption *m;
+
+ m = kmalloc(sizeof(struct mib_mac_encryption), GFP_KERNEL);
+ if (!m)
+ return;
+
+ ret = at76_get_mib(priv->udev, MIB_MAC_ENCRYPTION, m,
+ sizeof(struct mib_mac_encryption));
+ if (ret < 0) {
+ dev_err(&priv->udev->dev,
+ "%s: at76_get_mib (MAC_ENCRYPTION) failed: %d\n",
+ wiphy_name(priv->hw->wiphy), ret);
+ goto exit;
+ }
+
+ at76_dbg(DBG_MIB,
+ "%s: MIB MAC_ENCRYPTION: tkip_bssid %s priv_invoked %u "
+ "ciph_key_id %u grp_key_id %u excl_unencr %u "
+ "ckip_key_perm %u wep_icv_err %u wep_excluded %u",
+ wiphy_name(priv->hw->wiphy), mac2str(m->tkip_bssid),
+ m->privacy_invoked, m->cipher_default_key_id,
+ m->cipher_default_group_key_id, m->exclude_unencrypted,
+ m->ckip_key_permutation,
+ le32_to_cpu(m->wep_icv_error_count),
+ le32_to_cpu(m->wep_excluded_count));
+
+ /*key_len = (m->encryption_level == 1) ?
+ WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;*/
+
+ for (i = 0; i < CIPHER_KEYS; i++)
+ at76_dbg(DBG_MIB, "%s: MIB MAC_ENCRYPTION: key %d: %s",
+ wiphy_name(priv->hw->wiphy), i,
+ hex2str(m->cipher_default_keyvalue[i],
+ CIPHER_KEY_LEN));
+exit:
+ kfree(m);
+}
+
static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
{
int ret;
@@ -1119,7 +1125,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
sizeof(struct mib_mac_mgmt));
if (ret < 0) {
printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
goto exit;
}
@@ -1130,7 +1136,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
"pm_mode %d ibss_change %d res %d "
"multi_domain_capability_implemented %d "
"international_roaming %d country_string %.3s",
- priv->netdev->name, le16_to_cpu(m->beacon_period),
+ wiphy_name(priv->hw->wiphy), le16_to_cpu(m->beacon_period),
le16_to_cpu(m->CFP_max_duration),
le16_to_cpu(m->medium_occupancy_limit),
le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
@@ -1155,7 +1161,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac));
if (ret < 0) {
printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
goto exit;
}
@@ -1165,7 +1171,8 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
"scan_type %d scan_channel %d probe_delay %u "
"min_channel_time %d max_channel_time %d listen_int %d "
"desired_ssid %s desired_bssid %s desired_bsstype %d",
- priv->netdev->name, le32_to_cpu(m->max_tx_msdu_lifetime),
+ wiphy_name(priv->hw->wiphy),
+ le32_to_cpu(m->max_tx_msdu_lifetime),
le32_to_cpu(m->max_rx_lifetime),
le16_to_cpu(m->frag_threshold), le16_to_cpu(m->rts_threshold),
le16_to_cpu(m->cwmin), le16_to_cpu(m->cwmax),
@@ -1191,7 +1198,7 @@ static void at76_dump_mib_phy(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy));
if (ret < 0) {
printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
goto exit;
}
@@ -1200,7 +1207,7 @@ static void at76_dump_mib_phy(struct at76_priv *priv)
"mpdu_max_length %d cca_mode_supported %d operation_rate_set "
"0x%x 0x%x 0x%x 0x%x channel_id %d current_cca_mode %d "
"phy_type %d current_reg_domain %d",
- priv->netdev->name, le32_to_cpu(m->ed_threshold),
+ wiphy_name(priv->hw->wiphy), le32_to_cpu(m->ed_threshold),
le16_to_cpu(m->slot_time), le16_to_cpu(m->sifs_time),
le16_to_cpu(m->preamble_length),
le16_to_cpu(m->plcp_header_length),
@@ -1224,13 +1231,14 @@ static void at76_dump_mib_local(struct at76_priv *priv)
ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
if (ret < 0) {
printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
goto exit;
}
at76_dbg(DBG_MIB, "%s: MIB LOCAL: beacon_enable %d "
"txautorate_fallback %d ssid_size %d promiscuous_mode %d "
- "preamble_type %d", priv->netdev->name, m->beacon_enable,
+ "preamble_type %d", wiphy_name(priv->hw->wiphy),
+ m->beacon_enable,
m->txautorate_fallback, m->ssid_size, m->promiscuous_mode,
m->preamble_type);
exit:
@@ -1249,118 +1257,21 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv)
sizeof(struct mib_mdomain));
if (ret < 0) {
printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
goto exit;
}
at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s",
- priv->netdev->name,
+ wiphy_name(priv->hw->wiphy),
hex2str(m->channel_list, sizeof(m->channel_list)));
at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s",
- priv->netdev->name,
+ wiphy_name(priv->hw->wiphy),
hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel)));
exit:
kfree(m);
}
-static int at76_get_current_bssid(struct at76_priv *priv)
-{
- int ret = 0;
- struct mib_mac_mgmt *mac_mgmt =
- kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL);
-
- if (!mac_mgmt) {
- ret = -ENOMEM;
- goto exit;
- }
-
- ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, mac_mgmt,
- sizeof(struct mib_mac_mgmt));
- if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib failed: %d\n",
- priv->netdev->name, ret);
- goto error;
- }
- memcpy(priv->bssid, mac_mgmt->current_bssid, ETH_ALEN);
- printk(KERN_INFO "%s: using BSSID %s\n", priv->netdev->name,
- mac2str(priv->bssid));
-error:
- kfree(mac_mgmt);
-exit:
- return ret;
-}
-
-static int at76_get_current_channel(struct at76_priv *priv)
-{
- int ret = 0;
- struct mib_phy *phy = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
-
- if (!phy) {
- ret = -ENOMEM;
- goto exit;
- }
- ret = at76_get_mib(priv->udev, MIB_PHY, phy, sizeof(struct mib_phy));
- if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib(MIB_PHY) failed: %d\n",
- priv->netdev->name, ret);
- goto error;
- }
- priv->channel = phy->channel_id;
-error:
- kfree(phy);
-exit:
- return ret;
-}
-
-/**
- * at76_start_scan - start a scan
- *
- * @use_essid - use the configured ESSID in non passive mode
- */
-static int at76_start_scan(struct at76_priv *priv, int use_essid)
-{
- struct at76_req_scan scan;
-
- memset(&scan, 0, sizeof(struct at76_req_scan));
- memset(scan.bssid, 0xff, ETH_ALEN);
-
- if (use_essid) {
- memcpy(scan.essid, priv->essid, IW_ESSID_MAX_SIZE);
- scan.essid_size = priv->essid_size;
- } else
- scan.essid_size = 0;
-
- /* jal: why should we start at a certain channel? we do scan the whole
- range allowed by reg domain. */
- scan.channel = priv->channel;
-
- /* atmelwlandriver differs between scan type 0 and 1 (active/passive)
- For ad-hoc mode, it uses type 0 only. */
- scan.scan_type = priv->scan_mode;
-
- /* INFO: For probe_delay, not multiplying by 1024 as this will be
- slightly less than min_channel_time
- (per spec: probe delay < min. channel time) */
- scan.min_channel_time = cpu_to_le16(priv->scan_min_time);
- scan.max_channel_time = cpu_to_le16(priv->scan_max_time);
- scan.probe_delay = cpu_to_le16(priv->scan_min_time * 1000);
- scan.international_scan = 0;
-
- /* other values are set to 0 for type 0 */
-
- at76_dbg(DBG_PROGRESS, "%s: start_scan (use_essid = %d, intl = %d, "
- "channel = %d, probe_delay = %d, scan_min_time = %d, "
- "scan_max_time = %d)",
- priv->netdev->name, use_essid,
- scan.international_scan, scan.channel,
- le16_to_cpu(scan.probe_delay),
- le16_to_cpu(scan.min_channel_time),
- le16_to_cpu(scan.max_channel_time));
-
- return at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
-}
-
/* Enable monitor mode */
static int at76_start_monitor(struct at76_priv *priv)
{
@@ -1381,86 +1292,6 @@ static int at76_start_monitor(struct at76_priv *priv)
return ret;
}
-static int at76_start_ibss(struct at76_priv *priv)
-{
- struct at76_req_ibss bss;
- int ret;
-
- WARN_ON(priv->mac_state != MAC_OWN_IBSS);
- if (priv->mac_state != MAC_OWN_IBSS)
- return -EBUSY;
-
- memset(&bss, 0, sizeof(struct at76_req_ibss));
- memset(bss.bssid, 0xff, ETH_ALEN);
- memcpy(bss.essid, priv->essid, IW_ESSID_MAX_SIZE);
- bss.essid_size = priv->essid_size;
- bss.bss_type = ADHOC_MODE;
- bss.channel = priv->channel;
-
- ret = at76_set_card_command(priv->udev, CMD_START_IBSS, &bss,
- sizeof(struct at76_req_ibss));
- if (ret < 0) {
- printk(KERN_ERR "%s: start_ibss failed: %d\n",
- priv->netdev->name, ret);
- return ret;
- }
-
- ret = at76_wait_completion(priv, CMD_START_IBSS);
- if (ret != CMD_STATUS_COMPLETE) {
- printk(KERN_ERR "%s: start_ibss failed to complete, %d\n",
- priv->netdev->name, ret);
- return ret;
- }
-
- ret = at76_get_current_bssid(priv);
- if (ret < 0)
- return ret;
-
- ret = at76_get_current_channel(priv);
- if (ret < 0)
- return ret;
-
- /* not sure what this is good for ??? */
- priv->mib_buf.type = MIB_MAC_MGMT;
- priv->mib_buf.size = 1;
- priv->mib_buf.index = offsetof(struct mib_mac_mgmt, ibss_change);
- priv->mib_buf.data.byte = 0;
-
- ret = at76_set_mib(priv, &priv->mib_buf);
- if (ret < 0) {
- printk(KERN_ERR "%s: set_mib (ibss change ok) failed: %d\n",
- priv->netdev->name, ret);
- return ret;
- }
-
- netif_carrier_on(priv->netdev);
- netif_start_queue(priv->netdev);
- return 0;
-}
-
-/* Request card to join BSS in managed or ad-hoc mode */
-static int at76_join_bss(struct at76_priv *priv, struct bss_info *ptr)
-{
- struct at76_req_join join;
-
- BUG_ON(!ptr);
-
- memset(&join, 0, sizeof(struct at76_req_join));
- memcpy(join.bssid, ptr->bssid, ETH_ALEN);
- memcpy(join.essid, ptr->ssid, ptr->ssid_len);
- join.essid_size = ptr->ssid_len;
- join.bss_type = (priv->iw_mode == IW_MODE_ADHOC ? 1 : 2);
- join.channel = ptr->channel;
- join.timeout = cpu_to_le16(2000);
-
- at76_dbg(DBG_PROGRESS,
- "%s join addr %s ssid %s type %d ch %d timeout %d",
- priv->netdev->name, mac2str(join.bssid), join.essid,
- join.bss_type, join.channel, le16_to_cpu(join.timeout));
- return at76_set_card_command(priv->udev, CMD_JOIN, &join,
- sizeof(struct at76_req_join));
-}
-
/* Calculate padding from txbuf->wlength (which excludes the USB TX header),
likely to compensate a flaw in the AT76C503A USB part ... */
static inline int at76_calc_padding(int wlen)
@@ -1479,14 +1310,6 @@ static inline int at76_calc_padding(int wlen)
return 0;
}
-/* We are doing a lot of things here in an interrupt. Need
- a bh handler (Watching TV with a TV card is probably
- a good test: if you see flickers, we are doing too much.
- Currently I do see flickers... even with our tasklet :-( )
- Maybe because the bttv driver and usb-uhci use the same interrupt
-*/
-/* Or maybe because our BH handler is preempting bttv's BH handler.. BHs don't
- * solve everything.. (alex) */
static void at76_rx_callback(struct urb *urb)
{
struct at76_priv *priv = urb->context;
@@ -1496,1758 +1319,6 @@ static void at76_rx_callback(struct urb *urb)
return;
}
-static void at76_tx_callback(struct urb *urb)
-{
- struct at76_priv *priv = urb->context;
- struct net_device_stats *stats = &priv->stats;
- unsigned long flags;
- struct at76_tx_buffer *mgmt_buf;
- int ret;
-
- switch (urb->status) {
- case 0:
- stats->tx_packets++;
- break;
- case -ENOENT:
- case -ECONNRESET:
- /* urb has been unlinked */
- return;
- default:
- at76_dbg(DBG_URB, "%s - nonzero tx status received: %d",
- __func__, urb->status);
- stats->tx_errors++;
- break;
- }
-
- spin_lock_irqsave(&priv->mgmt_spinlock, flags);
- mgmt_buf = priv->next_mgmt_bulk;
- priv->next_mgmt_bulk = NULL;
- spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
-
- if (!mgmt_buf) {
- netif_wake_queue(priv->netdev);
- return;
- }
-
- /* we don't copy the padding bytes, but add them
- to the length */
- memcpy(priv->bulk_out_buffer, mgmt_buf,
- le16_to_cpu(mgmt_buf->wlength) + AT76_TX_HDRLEN);
- usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe,
- priv->bulk_out_buffer,
- le16_to_cpu(mgmt_buf->wlength) + mgmt_buf->padding +
- AT76_TX_HDRLEN, at76_tx_callback, priv);
- ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
- if (ret)
- printk(KERN_ERR "%s: error in tx submit urb: %d\n",
- priv->netdev->name, ret);
-
- kfree(mgmt_buf);
-}
-
-/* Send a management frame on bulk-out. txbuf->wlength must be set */
-static int at76_tx_mgmt(struct at76_priv *priv, struct at76_tx_buffer *txbuf)
-{
- unsigned long flags;
- int ret;
- int urb_status;
- void *oldbuf = NULL;
-
- netif_carrier_off(priv->netdev); /* stop netdev watchdog */
- netif_stop_queue(priv->netdev); /* stop tx data packets */
-
- spin_lock_irqsave(&priv->mgmt_spinlock, flags);
-
- urb_status = priv->tx_urb->status;
- if (urb_status == -EINPROGRESS) {
- /* cannot transmit now, put in the queue */
- oldbuf = priv->next_mgmt_bulk;
- priv->next_mgmt_bulk = txbuf;
- }
- spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
-
- if (oldbuf) {
- /* a data/mgmt tx is already pending in the URB -
- if this is no error in some situations we must
- implement a queue or silently modify the old msg */
- printk(KERN_ERR "%s: removed pending mgmt buffer %s\n",
- priv->netdev->name, hex2str(oldbuf, 64));
- kfree(oldbuf);
- return 0;
- }
-
- txbuf->tx_rate = TX_RATE_1MBIT;
- txbuf->padding = at76_calc_padding(le16_to_cpu(txbuf->wlength));
- memset(txbuf->reserved, 0, sizeof(txbuf->reserved));
-
- if (priv->next_mgmt_bulk)
- printk(KERN_ERR "%s: URB status %d, but mgmt is pending\n",
- priv->netdev->name, urb_status);
-
- at76_dbg(DBG_TX_MGMT,
- "%s: tx mgmt: wlen %d tx_rate %d pad %d %s",
- priv->netdev->name, le16_to_cpu(txbuf->wlength),
- txbuf->tx_rate, txbuf->padding,
- hex2str(txbuf->packet, le16_to_cpu(txbuf->wlength)));
-
- /* txbuf was not consumed above -> send mgmt msg immediately */
- memcpy(priv->bulk_out_buffer, txbuf,
- le16_to_cpu(txbuf->wlength) + AT76_TX_HDRLEN);
- usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe,
- priv->bulk_out_buffer,
- le16_to_cpu(txbuf->wlength) + txbuf->padding +
- AT76_TX_HDRLEN, at76_tx_callback, priv);
- ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
- if (ret)
- printk(KERN_ERR "%s: error in tx submit urb: %d\n",
- priv->netdev->name, ret);
-
- kfree(txbuf);
-
- return ret;
-}
-
-/* Go to the next information element */
-static inline void next_ie(struct ieee80211_info_element **ie)
-{
- *ie = (struct ieee80211_info_element *)(&(*ie)->data[(*ie)->len]);
-}
-
-/* Challenge is the challenge string (in TLV format)
- we got with seq_nr 2 for shared secret authentication only and
- send in seq_nr 3 WEP encrypted to prove we have the correct WEP key;
- otherwise it is NULL */
-static int at76_auth_req(struct at76_priv *priv, struct bss_info *bss,
- int seq_nr, struct ieee80211_info_element *challenge)
-{
- struct at76_tx_buffer *tx_buffer;
- struct ieee80211_hdr_3addr *mgmt;
- struct ieee80211_auth *req;
- int buf_len = (seq_nr != 3 ? AUTH_FRAME_SIZE :
- AUTH_FRAME_SIZE + 1 + 1 + challenge->len);
-
- BUG_ON(!bss);
- BUG_ON(seq_nr == 3 && !challenge);
- tx_buffer = kmalloc(buf_len + MAX_PADDING_SIZE, GFP_ATOMIC);
- if (!tx_buffer)
- return -ENOMEM;
-
- req = (struct ieee80211_auth *)tx_buffer->packet;
- mgmt = &req->header;
-
- /* make wireless header */
- /* first auth msg is not encrypted, only the second (seq_nr == 3) */
- mgmt->frame_ctl =
- cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH |
- (seq_nr == 3 ? IEEE80211_FCTL_PROTECTED : 0));
-
- mgmt->duration_id = cpu_to_le16(0x8000);
- memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);
- memcpy(mgmt->addr2, priv->netdev->dev_addr, ETH_ALEN);
- memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);
- mgmt->seq_ctl = cpu_to_le16(0);
-
- req->algorithm = cpu_to_le16(priv->auth_mode);
- req->transaction = cpu_to_le16(seq_nr);
- req->status = cpu_to_le16(0);
-
- if (seq_nr == 3)
- memcpy(req->info_element, challenge, 1 + 1 + challenge->len);
-
- /* init. at76_priv tx header */
- tx_buffer->wlength = cpu_to_le16(buf_len - AT76_TX_HDRLEN);
- at76_dbg(DBG_TX_MGMT, "%s: AuthReq bssid %s alg %d seq_nr %d",
- priv->netdev->name, mac2str(mgmt->addr3),
- le16_to_cpu(req->algorithm), le16_to_cpu(req->transaction));
- if (seq_nr == 3)
- at76_dbg(DBG_TX_MGMT, "%s: AuthReq challenge: %s ...",
- priv->netdev->name, hex2str(req->info_element, 18));
-
- /* either send immediately (if no data tx is pending
- or put it in pending list */
- return at76_tx_mgmt(priv, tx_buffer);
-}
-
-static int at76_assoc_req(struct at76_priv *priv, struct bss_info *bss)
-{
- struct at76_tx_buffer *tx_buffer;
- struct ieee80211_hdr_3addr *mgmt;
- struct ieee80211_assoc_request *req;
- struct ieee80211_info_element *ie;
- char *essid;
- int essid_len;
- u16 capa;
-
- BUG_ON(!bss);
-
- tx_buffer = kmalloc(ASSOCREQ_MAX_SIZE + MAX_PADDING_SIZE, GFP_ATOMIC);
- if (!tx_buffer)
- return -ENOMEM;
-
- req = (struct ieee80211_assoc_request *)tx_buffer->packet;
- mgmt = &req->header;
- ie = req->info_element;
-
- /* make wireless header */
- mgmt->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ASSOC_REQ);
-
- mgmt->duration_id = cpu_to_le16(0x8000);
- memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);
- memcpy(mgmt->addr2, priv->netdev->dev_addr, ETH_ALEN);
- memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);
- mgmt->seq_ctl = cpu_to_le16(0);
-
- /* we must set the Privacy bit in the capabilities to assure an
- Agere-based AP with optional WEP transmits encrypted frames
- to us. AP only set the Privacy bit in their capabilities
- if WEP is mandatory in the BSS! */
- capa = bss->capa;
- if (priv->wep_enabled)
- capa |= WLAN_CAPABILITY_PRIVACY;
- if (priv->preamble_type != PREAMBLE_TYPE_LONG)
- capa |= WLAN_CAPABILITY_SHORT_PREAMBLE;
- req->capability = cpu_to_le16(capa);
-
- req->listen_interval = cpu_to_le16(2 * bss->beacon_interval);
-
- /* write TLV data elements */
-
- ie->id = MFIE_TYPE_SSID;
- ie->len = bss->ssid_len;
- memcpy(ie->data, bss->ssid, bss->ssid_len);
- next_ie(&ie);
-
- ie->id = MFIE_TYPE_RATES;
- ie->len = sizeof(hw_rates);
- memcpy(ie->data, hw_rates, sizeof(hw_rates));
- next_ie(&ie); /* ie points behind the supp_rates field */
-
- /* init. at76_priv tx header */
- tx_buffer->wlength = cpu_to_le16((u8 *)ie - (u8 *)mgmt);
-
- ie = req->info_element;
- essid = ie->data;
- essid_len = min_t(int, IW_ESSID_MAX_SIZE, ie->len);
-
- next_ie(&ie); /* points to IE of rates now */
- at76_dbg(DBG_TX_MGMT,
- "%s: AssocReq bssid %s capa 0x%04x ssid %.*s rates %s",
- priv->netdev->name, mac2str(mgmt->addr3),
- le16_to_cpu(req->capability), essid_len, essid,
- hex2str(ie->data, ie->len));
-
- /* either send immediately (if no data tx is pending
- or put it in pending list */
- return at76_tx_mgmt(priv, tx_buffer);
-}
-
-/* We got to check the bss_list for old entries */
-static void at76_bss_list_timeout(unsigned long par)
-{
- struct at76_priv *priv = (struct at76_priv *)par;
- unsigned long flags;
- struct list_head *lptr, *nptr;
- struct bss_info *ptr;
-
- spin_lock_irqsave(&priv->bss_list_spinlock, flags);
-
- list_for_each_safe(lptr, nptr, &priv->bss_list) {
-
- ptr = list_entry(lptr, struct bss_info, list);
-
- if (ptr != priv->curr_bss
- && time_after(jiffies, ptr->last_rx + BSS_LIST_TIMEOUT)) {
- at76_dbg(DBG_BSS_TABLE_RM,
- "%s: bss_list: removing old BSS %s ch %d",
- priv->netdev->name, mac2str(ptr->bssid),
- ptr->channel);
- list_del(&ptr->list);
- kfree(ptr);
- }
- }
- spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
- /* restart the timer */
- mod_timer(&priv->bss_list_timer, jiffies + BSS_LIST_TIMEOUT);
-}
-
-static inline void at76_set_mac_state(struct at76_priv *priv,
- enum mac_state mac_state)
-{
- at76_dbg(DBG_MAC_STATE, "%s state: %s", priv->netdev->name,
- mac_states[mac_state]);
- priv->mac_state = mac_state;
-}
-
-static void at76_dump_bss_table(struct at76_priv *priv)
-{
- struct bss_info *ptr;
- unsigned long flags;
- struct list_head *lptr;
-
- spin_lock_irqsave(&priv->bss_list_spinlock, flags);
-
- at76_dbg(DBG_BSS_TABLE, "%s BSS table (curr=%p):", priv->netdev->name,
- priv->curr_bss);
-
- list_for_each(lptr, &priv->bss_list) {
- ptr = list_entry(lptr, struct bss_info, list);
- at76_dbg(DBG_BSS_TABLE, "0x%p: bssid %s channel %d ssid %.*s "
- "(%s) capa 0x%04x rates %s rssi %d link %d noise %d",
- ptr, mac2str(ptr->bssid), ptr->channel, ptr->ssid_len,
- ptr->ssid, hex2str(ptr->ssid, ptr->ssid_len),
- ptr->capa, hex2str(ptr->rates, ptr->rates_len),
- ptr->rssi, ptr->link_qual, ptr->noise_level);
- }
- spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
-}
-
-/* Called upon successful association to mark interface as connected */
-static void at76_work_assoc_done(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- work_assoc_done);
-
- mutex_lock(&priv->mtx);
-
- WARN_ON(priv->mac_state != MAC_ASSOC);
- WARN_ON(!priv->curr_bss);
- if (priv->mac_state != MAC_ASSOC || !priv->curr_bss)
- goto exit;
-
- if (priv->iw_mode == IW_MODE_INFRA) {
- if (priv->pm_mode != AT76_PM_OFF) {
- /* calculate the listen interval in units of
- beacon intervals of the curr_bss */
- u32 pm_period_beacon = (priv->pm_period >> 10) /
- priv->curr_bss->beacon_interval;
-
- pm_period_beacon = max(pm_period_beacon, 2u);
- pm_period_beacon = min(pm_period_beacon, 0xffffu);
-
- at76_dbg(DBG_PM,
- "%s: pm_mode %d assoc id 0x%x listen int %d",
- priv->netdev->name, priv->pm_mode,
- priv->assoc_id, pm_period_beacon);
-
- at76_set_associd(priv, priv->assoc_id);
- at76_set_listen_interval(priv, (u16)pm_period_beacon);
- }
- schedule_delayed_work(&priv->dwork_beacon, BEACON_TIMEOUT);
- }
- at76_set_pm_mode(priv);
-
- netif_carrier_on(priv->netdev);
- netif_wake_queue(priv->netdev);
- at76_set_mac_state(priv, MAC_CONNECTED);
- at76_iwevent_bss_connect(priv->netdev, priv->curr_bss->bssid);
- at76_dbg(DBG_PROGRESS, "%s: connected to BSSID %s",
- priv->netdev->name, mac2str(priv->curr_bss->bssid));
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
-/* We only store the new mac address in netdev struct,
- it gets set when the netdev is opened. */
-static int at76_set_mac_address(struct net_device *netdev, void *addr)
-{
- struct sockaddr *mac = addr;
- memcpy(netdev->dev_addr, mac->sa_data, ETH_ALEN);
- return 1;
-}
-
-static struct net_device_stats *at76_get_stats(struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- return &priv->stats;
-}
-
-static struct iw_statistics *at76_get_wireless_stats(struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_IOCTL, "RETURN qual %d level %d noise %d updated %d",
- priv->wstats.qual.qual, priv->wstats.qual.level,
- priv->wstats.qual.noise, priv->wstats.qual.updated);
-
- return &priv->wstats;
-}
-
-static void at76_set_multicast(struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int promisc;
-
- promisc = ((netdev->flags & IFF_PROMISC) != 0);
- if (promisc != priv->promisc) {
- /* This gets called in interrupt, must reschedule */
- priv->promisc = promisc;
- schedule_work(&priv->work_set_promisc);
- }
-}
-
-/* Stop all network activity, flush all pending tasks */
-static void at76_quiesce(struct at76_priv *priv)
-{
- unsigned long flags;
-
- netif_stop_queue(priv->netdev);
- netif_carrier_off(priv->netdev);
-
- at76_set_mac_state(priv, MAC_INIT);
-
- cancel_delayed_work(&priv->dwork_get_scan);
- cancel_delayed_work(&priv->dwork_beacon);
- cancel_delayed_work(&priv->dwork_auth);
- cancel_delayed_work(&priv->dwork_assoc);
- cancel_delayed_work(&priv->dwork_restart);
-
- spin_lock_irqsave(&priv->mgmt_spinlock, flags);
- kfree(priv->next_mgmt_bulk);
- priv->next_mgmt_bulk = NULL;
- spin_unlock_irqrestore(&priv->mgmt_spinlock, flags);
-}
-
-/*******************************************************************************
- * at76_priv implementations of iw_handler functions:
- */
-static int at76_iw_handler_commit(struct net_device *netdev,
- struct iw_request_info *info,
- void *null, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_IOCTL, "%s %s: restarting the device", netdev->name,
- __func__);
-
- if (priv->mac_state != MAC_INIT)
- at76_quiesce(priv);
-
- /* Wait half second before the restart to process subsequent
- * requests from the same iwconfig in a single restart */
- schedule_delayed_work(&priv->dwork_restart, HZ / 2);
-
- return 0;
-}
-
-static int at76_iw_handler_get_name(struct net_device *netdev,
- struct iw_request_info *info,
- char *name, char *extra)
-{
- strcpy(name, "IEEE 802.11b");
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWNAME - name %s", netdev->name, name);
- return 0;
-}
-
-static int at76_iw_handler_set_freq(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int chan = -1;
- int ret = -EIWCOMMIT;
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - freq.m %d freq.e %d",
- netdev->name, freq->m, freq->e);
-
- if ((freq->e == 0) && (freq->m <= 1000))
- /* Setting by channel number */
- chan = freq->m;
- else {
- /* Setting by frequency - search the table */
- int mult = 1;
- int i;
-
- for (i = 0; i < (6 - freq->e); i++)
- mult *= 10;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- if (freq->m == (channel_frequency[i] * mult))
- chan = i + 1;
- }
- }
-
- if (chan < 1 || !priv->domain)
- /* non-positive channels are invalid
- * we need a domain info to set the channel
- * either that or an invalid frequency was
- * provided by the user */
- ret = -EINVAL;
- else if (!(priv->domain->channel_map & (1 << (chan - 1)))) {
- printk(KERN_INFO "%s: channel %d not allowed for domain %s\n",
- priv->netdev->name, chan, priv->domain->name);
- ret = -EINVAL;
- }
-
- if (ret == -EIWCOMMIT) {
- priv->channel = chan;
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWFREQ - ch %d", netdev->name,
- chan);
- }
-
- return ret;
-}
-
-static int at76_iw_handler_get_freq(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- freq->m = priv->channel;
- freq->e = 0;
-
- if (priv->channel)
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - freq %ld x 10e%d",
- netdev->name, channel_frequency[priv->channel - 1], 6);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWFREQ - ch %d", netdev->name,
- priv->channel);
-
- return 0;
-}
-
-static int at76_iw_handler_set_mode(struct net_device *netdev,
- struct iw_request_info *info,
- __u32 *mode, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWMODE - %d", netdev->name, *mode);
-
- if ((*mode != IW_MODE_ADHOC) && (*mode != IW_MODE_INFRA) &&
- (*mode != IW_MODE_MONITOR))
- return -EINVAL;
-
- priv->iw_mode = *mode;
- if (priv->iw_mode != IW_MODE_INFRA)
- priv->pm_mode = AT76_PM_OFF;
-
- return -EIWCOMMIT;
-}
-
-static int at76_iw_handler_get_mode(struct net_device *netdev,
- struct iw_request_info *info,
- __u32 *mode, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- *mode = priv->iw_mode;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWMODE - %d", netdev->name, *mode);
-
- return 0;
-}
-
-static int at76_iw_handler_get_range(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- /* inspired by atmel.c */
- struct at76_priv *priv = netdev_priv(netdev);
- struct iw_range *range = (struct iw_range *)extra;
- int i;
-
- data->length = sizeof(struct iw_range);
- memset(range, 0, sizeof(struct iw_range));
-
- /* TODO: range->throughput = xxxxxx; */
-
- range->min_nwid = 0x0000;
- range->max_nwid = 0x0000;
-
- /* this driver doesn't maintain sensitivity information */
- range->sensitivity = 0;
-
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
- range->max_qual.noise = 0;
- range->max_qual.updated = IW_QUAL_NOISE_INVALID;
-
- range->avg_qual.qual = 50;
- range->avg_qual.level = 50;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = IW_QUAL_NOISE_INVALID;
-
- range->bitrate[0] = 1000000;
- range->bitrate[1] = 2000000;
- range->bitrate[2] = 5500000;
- range->bitrate[3] = 11000000;
- range->num_bitrates = 4;
-
- range->min_rts = 0;
- range->max_rts = MAX_RTS_THRESHOLD;
-
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
-
- range->pmp_flags = IW_POWER_PERIOD;
- range->pmt_flags = IW_POWER_ON;
- range->pm_capa = IW_POWER_PERIOD | IW_POWER_ALL_R;
-
- range->encoding_size[0] = WEP_SMALL_KEY_LEN;
- range->encoding_size[1] = WEP_LARGE_KEY_LEN;
- range->num_encoding_sizes = 2;
- range->max_encoding_tokens = WEP_KEYS;
-
- /* both WL-240U and Linksys WUSB11 v2.6 specify 15 dBm as output power
- - take this for all (ignore antenna gains) */
- range->txpower[0] = 15;
- range->num_txpower = 1;
- range->txpower_capa = IW_TXPOW_DBM;
-
- range->we_version_source = WIRELESS_EXT;
- range->we_version_compiled = WIRELESS_EXT;
-
- /* same as the values used in atmel.c */
- range->retry_capa = IW_RETRY_LIMIT;
- range->retry_flags = IW_RETRY_LIMIT;
- range->r_time_flags = 0;
- range->min_retry = 1;
- range->max_retry = 255;
-
- range->num_channels = NUM_CHANNELS;
- range->num_frequency = 0;
-
- for (i = 0; i < NUM_CHANNELS; i++) {
- /* test if channel map bit is raised */
- if (priv->domain->channel_map & (0x1 << i)) {
- range->num_frequency += 1;
-
- range->freq[i].i = i + 1;
- range->freq[i].m = channel_frequency[i] * 100000;
- range->freq[i].e = 1; /* freq * 10^1 */
- }
- }
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWRANGE", netdev->name);
-
- return 0;
-}
-
-static int at76_iw_handler_set_spy(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = 0;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWSPY - number of addresses %d",
- netdev->name, data->length);
-
- spin_lock_bh(&priv->spy_spinlock);
- ret = iw_handler_set_spy(priv->netdev, info, (union iwreq_data *)data,
- extra);
- spin_unlock_bh(&priv->spy_spinlock);
-
- return ret;
-}
-
-static int at76_iw_handler_get_spy(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
-
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = 0;
-
- spin_lock_bh(&priv->spy_spinlock);
- ret = iw_handler_get_spy(priv->netdev, info,
- (union iwreq_data *)data, extra);
- spin_unlock_bh(&priv->spy_spinlock);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWSPY - number of addresses %d",
- netdev->name, data->length);
-
- return ret;
-}
-
-static int at76_iw_handler_set_thrspy(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWTHRSPY - number of addresses %d)",
- netdev->name, data->length);
-
- spin_lock_bh(&priv->spy_spinlock);
- ret = iw_handler_set_thrspy(netdev, info, (union iwreq_data *)data,
- extra);
- spin_unlock_bh(&priv->spy_spinlock);
-
- return ret;
-}
-
-static int at76_iw_handler_get_thrspy(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret;
-
- spin_lock_bh(&priv->spy_spinlock);
- ret = iw_handler_get_thrspy(netdev, info, (union iwreq_data *)data,
- extra);
- spin_unlock_bh(&priv->spy_spinlock);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWTHRSPY - number of addresses %d)",
- netdev->name, data->length);
-
- return ret;
-}
-
-static int at76_iw_handler_set_wap(struct net_device *netdev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWAP - wap/bssid %s", netdev->name,
- mac2str(ap_addr->sa_data));
-
- /* if the incoming address == ff:ff:ff:ff:ff:ff, the user has
- chosen any or auto AP preference */
- if (is_broadcast_ether_addr(ap_addr->sa_data)
- || is_zero_ether_addr(ap_addr->sa_data))
- priv->wanted_bssid_valid = 0;
- else {
- /* user wants to set a preferred AP address */
- priv->wanted_bssid_valid = 1;
- memcpy(priv->wanted_bssid, ap_addr->sa_data, ETH_ALEN);
- }
-
- return -EIWCOMMIT;
-}
-
-static int at76_iw_handler_get_wap(struct net_device *netdev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- ap_addr->sa_family = ARPHRD_ETHER;
- memcpy(ap_addr->sa_data, priv->bssid, ETH_ALEN);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWAP - wap/bssid %s", netdev->name,
- mac2str(ap_addr->sa_data));
-
- return 0;
-}
-
-static int at76_iw_handler_set_scan(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = 0;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWSCAN", netdev->name);
-
- if (mutex_lock_interruptible(&priv->mtx))
- return -EINTR;
-
- if (!netif_running(netdev)) {
- ret = -ENETDOWN;
- goto exit;
- }
-
- /* jal: we don't allow "iwlist ethX scan" while we are
- in monitor mode */
- if (priv->iw_mode == IW_MODE_MONITOR) {
- ret = -EBUSY;
- goto exit;
- }
-
- /* Discard old scan results */
- if ((jiffies - priv->last_scan) > (20 * HZ))
- priv->scan_state = SCAN_IDLE;
- priv->last_scan = jiffies;
-
- /* Initiate a scan command */
- if (priv->scan_state == SCAN_IN_PROGRESS) {
- ret = -EBUSY;
- goto exit;
- }
-
- priv->scan_state = SCAN_IN_PROGRESS;
-
- at76_quiesce(priv);
-
- /* Try to do passive or active scan if WE asks as. */
- if (wrqu->data.length
- && wrqu->data.length == sizeof(struct iw_scan_req)) {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
-
- if (req->scan_type == IW_SCAN_TYPE_PASSIVE)
- priv->scan_mode = SCAN_TYPE_PASSIVE;
- else if (req->scan_type == IW_SCAN_TYPE_ACTIVE)
- priv->scan_mode = SCAN_TYPE_ACTIVE;
-
- /* Sanity check values? */
- if (req->min_channel_time > 0)
- priv->scan_min_time = req->min_channel_time;
-
- if (req->max_channel_time > 0)
- priv->scan_max_time = req->max_channel_time;
- }
-
- /* change to scanning state */
- at76_set_mac_state(priv, MAC_SCANNING);
- schedule_work(&priv->work_start_scan);
-
-exit:
- mutex_unlock(&priv->mtx);
- return ret;
-}
-
-static int at76_iw_handler_get_scan(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- unsigned long flags;
- struct list_head *lptr, *nptr;
- struct bss_info *curr_bss;
- struct iw_event *iwe = kmalloc(sizeof(struct iw_event), GFP_KERNEL);
- char *curr_val, *curr_pos = extra;
- int i;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWSCAN", netdev->name);
-
- if (!iwe)
- return -ENOMEM;
-
- if (priv->scan_state != SCAN_COMPLETED) {
- /* scan not yet finished */
- kfree(iwe);
- return -EAGAIN;
- }
-
- spin_lock_irqsave(&priv->bss_list_spinlock, flags);
-
- list_for_each_safe(lptr, nptr, &priv->bss_list) {
- curr_bss = list_entry(lptr, struct bss_info, list);
-
- iwe->cmd = SIOCGIWAP;
- iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe->u.ap_addr.sa_data, curr_bss->bssid, 6);
- curr_pos = iwe_stream_add_event(info, curr_pos,
- extra + IW_SCAN_MAX_DATA, iwe,
- IW_EV_ADDR_LEN);
-
- iwe->u.data.length = curr_bss->ssid_len;
- iwe->cmd = SIOCGIWESSID;
- iwe->u.data.flags = 1;
-
- curr_pos = iwe_stream_add_point(info, curr_pos,
- extra + IW_SCAN_MAX_DATA, iwe,
- curr_bss->ssid);
-
- iwe->cmd = SIOCGIWMODE;
- iwe->u.mode = (curr_bss->capa & WLAN_CAPABILITY_IBSS) ?
- IW_MODE_ADHOC :
- (curr_bss->capa & WLAN_CAPABILITY_ESS) ?
- IW_MODE_MASTER : IW_MODE_AUTO;
- /* IW_MODE_AUTO = 0 which I thought is
- * the most logical value to return in this case */
- curr_pos = iwe_stream_add_event(info, curr_pos,
- extra + IW_SCAN_MAX_DATA, iwe,
- IW_EV_UINT_LEN);
-
- iwe->cmd = SIOCGIWFREQ;
- iwe->u.freq.m = curr_bss->channel;
- iwe->u.freq.e = 0;
- curr_pos = iwe_stream_add_event(info, curr_pos,
- extra + IW_SCAN_MAX_DATA, iwe,
- IW_EV_FREQ_LEN);
-
- iwe->cmd = SIOCGIWENCODE;
- if (curr_bss->capa & 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;
- curr_pos = iwe_stream_add_point(info, curr_pos,
- extra + IW_SCAN_MAX_DATA, iwe,
- NULL);
-
- /* Add quality statistics */
- iwe->cmd = IWEVQUAL;
- iwe->u.qual.noise = 0;
- iwe->u.qual.updated =
- IW_QUAL_NOISE_INVALID | IW_QUAL_LEVEL_UPDATED;
- iwe->u.qual.level = (curr_bss->rssi * 100 / 42);
- if (iwe->u.qual.level > 100)
- iwe->u.qual.level = 100;
- if (at76_is_intersil(priv->board_type))
- iwe->u.qual.qual = curr_bss->link_qual;
- else {
- iwe->u.qual.qual = 0;
- iwe->u.qual.updated |= IW_QUAL_QUAL_INVALID;
- }
- /* Add new value to event */
- curr_pos = iwe_stream_add_event(info, curr_pos,
- extra + IW_SCAN_MAX_DATA, iwe,
- IW_EV_QUAL_LEN);
-
- /* Rate: stuffing multiple values in a single event requires
- * a bit more of magic - Jean II */
- curr_val = curr_pos + IW_EV_LCP_LEN;
-
- iwe->cmd = SIOCGIWRATE;
- /* Those two flags are ignored... */
- iwe->u.bitrate.fixed = 0;
- iwe->u.bitrate.disabled = 0;
- /* Max 8 values */
- for (i = 0; i < curr_bss->rates_len; i++) {
- /* Bit rate given in 500 kb/s units (+ 0x80) */
- iwe->u.bitrate.value =
- ((curr_bss->rates[i] & 0x7f) * 500000);
- /* Add new value to event */
- curr_val = iwe_stream_add_value(info, curr_pos,
- curr_val,
- extra +
- IW_SCAN_MAX_DATA, iwe,
- IW_EV_PARAM_LEN);
- }
-
- /* Check if we added any event */
- if ((curr_val - curr_pos) > IW_EV_LCP_LEN)
- curr_pos = curr_val;
-
- /* more information may be sent back using IWECUSTOM */
-
- }
-
- spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
-
- data->length = (curr_pos - extra);
- data->flags = 0;
-
- kfree(iwe);
- return 0;
-}
-
-static int at76_iw_handler_set_essid(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWESSID - %s", netdev->name, extra);
-
- if (data->flags) {
- memcpy(priv->essid, extra, data->length);
- priv->essid_size = data->length;
- } else
- priv->essid_size = 0; /* Use any SSID */
-
- return -EIWCOMMIT;
-}
-
-static int at76_iw_handler_get_essid(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- if (priv->essid_size) {
- /* not the ANY ssid in priv->essid */
- data->flags = 1;
- data->length = priv->essid_size;
- memcpy(extra, priv->essid, data->length);
- } else {
- /* the ANY ssid was specified */
- if (priv->mac_state == MAC_CONNECTED && priv->curr_bss) {
- /* report the SSID we have found */
- data->flags = 1;
- data->length = priv->curr_bss->ssid_len;
- memcpy(extra, priv->curr_bss->ssid, data->length);
- } else {
- /* report ANY back */
- data->flags = 0;
- data->length = 0;
- }
- }
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWESSID - %.*s", netdev->name,
- data->length, extra);
-
- return 0;
-}
-
-static int at76_iw_handler_set_rate(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *bitrate, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = -EIWCOMMIT;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWRATE - %d", netdev->name,
- bitrate->value);
-
- switch (bitrate->value) {
- case -1:
- priv->txrate = TX_RATE_AUTO;
- break; /* auto rate */
- case 1000000:
- priv->txrate = TX_RATE_1MBIT;
- break;
- case 2000000:
- priv->txrate = TX_RATE_2MBIT;
- break;
- case 5500000:
- priv->txrate = TX_RATE_5_5MBIT;
- break;
- case 11000000:
- priv->txrate = TX_RATE_11MBIT;
- break;
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static int at76_iw_handler_get_rate(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *bitrate, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = 0;
-
- switch (priv->txrate) {
- /* return max rate if RATE_AUTO */
- case TX_RATE_AUTO:
- bitrate->value = 11000000;
- break;
- case TX_RATE_1MBIT:
- bitrate->value = 1000000;
- break;
- case TX_RATE_2MBIT:
- bitrate->value = 2000000;
- break;
- case TX_RATE_5_5MBIT:
- bitrate->value = 5500000;
- break;
- case TX_RATE_11MBIT:
- bitrate->value = 11000000;
- break;
- default:
- ret = -EINVAL;
- }
-
- bitrate->fixed = (priv->txrate != TX_RATE_AUTO);
- bitrate->disabled = 0;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWRATE - %d", netdev->name,
- bitrate->value);
-
- return ret;
-}
-
-static int at76_iw_handler_set_rts(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *rts, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = -EIWCOMMIT;
- int rthr = rts->value;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWRTS - value %d disabled %s",
- netdev->name, rts->value, (rts->disabled) ? "true" : "false");
-
- if (rts->disabled)
- rthr = MAX_RTS_THRESHOLD;
-
- if ((rthr < 0) || (rthr > MAX_RTS_THRESHOLD))
- ret = -EINVAL;
- else
- priv->rts_threshold = rthr;
-
- return ret;
-}
-
-static int at76_iw_handler_get_rts(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *rts, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- rts->value = priv->rts_threshold;
- rts->disabled = (rts->value >= MAX_RTS_THRESHOLD);
- rts->fixed = 1;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWRTS - value %d disabled %s",
- netdev->name, rts->value, (rts->disabled) ? "true" : "false");
-
- return 0;
-}
-
-static int at76_iw_handler_set_frag(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *frag, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = -EIWCOMMIT;
- int fthr = frag->value;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWFRAG - value %d, disabled %s",
- netdev->name, frag->value,
- (frag->disabled) ? "true" : "false");
-
- if (frag->disabled)
- fthr = MAX_FRAG_THRESHOLD;
-
- if ((fthr < MIN_FRAG_THRESHOLD) || (fthr > MAX_FRAG_THRESHOLD))
- ret = -EINVAL;
- else
- priv->frag_threshold = fthr & ~0x1; /* get an even value */
-
- return ret;
-}
-
-static int at76_iw_handler_get_frag(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *frag, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- frag->value = priv->frag_threshold;
- frag->disabled = (frag->value >= MAX_FRAG_THRESHOLD);
- frag->fixed = 1;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWFRAG - value %d, disabled %s",
- netdev->name, frag->value,
- (frag->disabled) ? "true" : "false");
-
- return 0;
-}
-
-static int at76_iw_handler_get_txpow(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *power, char *extra)
-{
- power->value = 15;
- power->fixed = 1; /* No power control */
- power->disabled = 0;
- power->flags = IW_TXPOW_DBM;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWTXPOW - txpow %d dBm", netdev->name,
- power->value);
-
- return 0;
-}
-
-/* jal: short retry is handled by the firmware (at least 0.90.x),
- while long retry is not (?) */
-static int at76_iw_handler_set_retry(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *retry, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = -EIWCOMMIT;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWRETRY disabled %d flags 0x%x val %d",
- netdev->name, retry->disabled, retry->flags, retry->value);
-
- if (!retry->disabled && (retry->flags & IW_RETRY_LIMIT)) {
- if ((retry->flags & IW_RETRY_MIN) ||
- !(retry->flags & IW_RETRY_MAX))
- priv->short_retry_limit = retry->value;
- else
- ret = -EINVAL;
- } else
- ret = -EINVAL;
-
- return ret;
-}
-
-/* Adapted (ripped) from atmel.c */
-static int at76_iw_handler_get_retry(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *retry, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWRETRY", netdev->name);
-
- retry->disabled = 0; /* Can't be disabled */
- retry->flags = IW_RETRY_LIMIT;
- retry->value = priv->short_retry_limit;
-
- return 0;
-}
-
-static int at76_iw_handler_set_encode(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *encoding, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int index = (encoding->flags & IW_ENCODE_INDEX) - 1;
- int len = encoding->length;
-
- at76_dbg(DBG_IOCTL, "%s: SIOCSIWENCODE - enc.flags %08x "
- "pointer %p len %d", netdev->name, encoding->flags,
- encoding->pointer, encoding->length);
- at76_dbg(DBG_IOCTL,
- "%s: SIOCSIWENCODE - old wepstate: enabled %s key_id %d "
- "auth_mode %s", netdev->name,
- (priv->wep_enabled) ? "true" : "false", priv->wep_key_id,
- (priv->auth_mode ==
- WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
-
- /* take the old default key if index is invalid */
- if ((index < 0) || (index >= WEP_KEYS))
- index = priv->wep_key_id;
-
- if (len > 0) {
- if (len > WEP_LARGE_KEY_LEN)
- len = WEP_LARGE_KEY_LEN;
-
- memset(priv->wep_keys[index], 0, WEP_KEY_LEN);
- memcpy(priv->wep_keys[index], extra, len);
- priv->wep_keys_len[index] = (len <= WEP_SMALL_KEY_LEN) ?
- WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
- priv->wep_enabled = 1;
- }
-
- priv->wep_key_id = index;
- priv->wep_enabled = ((encoding->flags & IW_ENCODE_DISABLED) == 0);
-
- if (encoding->flags & IW_ENCODE_RESTRICTED)
- priv->auth_mode = WLAN_AUTH_SHARED_KEY;
- if (encoding->flags & IW_ENCODE_OPEN)
- priv->auth_mode = WLAN_AUTH_OPEN;
-
- at76_dbg(DBG_IOCTL,
- "%s: SIOCSIWENCODE - new wepstate: enabled %s key_id %d "
- "key_len %d auth_mode %s", netdev->name,
- (priv->wep_enabled) ? "true" : "false", priv->wep_key_id + 1,
- priv->wep_keys_len[priv->wep_key_id],
- (priv->auth_mode ==
- WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
-
- return -EIWCOMMIT;
-}
-
-static int at76_iw_handler_get_encode(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *encoding, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int index = (encoding->flags & IW_ENCODE_INDEX) - 1;
-
- if ((index < 0) || (index >= WEP_KEYS))
- index = priv->wep_key_id;
-
- encoding->flags =
- (priv->auth_mode == WLAN_AUTH_SHARED_KEY) ?
- IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
-
- if (!priv->wep_enabled)
- encoding->flags |= IW_ENCODE_DISABLED;
-
- if (encoding->pointer) {
- encoding->length = priv->wep_keys_len[index];
-
- memcpy(extra, priv->wep_keys[index], priv->wep_keys_len[index]);
-
- encoding->flags |= (index + 1);
- }
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWENCODE - enc.flags %08x "
- "pointer %p len %d", netdev->name, encoding->flags,
- encoding->pointer, encoding->length);
- at76_dbg(DBG_IOCTL,
- "%s: SIOCGIWENCODE - wepstate: enabled %s key_id %d "
- "key_len %d auth_mode %s", netdev->name,
- (priv->wep_enabled) ? "true" : "false", priv->wep_key_id + 1,
- priv->wep_keys_len[priv->wep_key_id],
- (priv->auth_mode ==
- WLAN_AUTH_SHARED_KEY) ? "restricted" : "open");
-
- return 0;
-}
-
-static int at76_iw_handler_set_power(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *prq, char *extra)
-{
- int err = -EIWCOMMIT;
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_IOCTL,
- "%s: SIOCSIWPOWER - disabled %s flags 0x%x value 0x%x",
- netdev->name, (prq->disabled) ? "true" : "false", prq->flags,
- prq->value);
-
- if (prq->disabled)
- priv->pm_mode = AT76_PM_OFF;
- else {
- switch (prq->flags & IW_POWER_MODE) {
- case IW_POWER_ALL_R:
- case IW_POWER_ON:
- break;
- default:
- err = -EINVAL;
- goto exit;
- }
- if (prq->flags & IW_POWER_PERIOD)
- priv->pm_period = prq->value;
-
- if (prq->flags & IW_POWER_TIMEOUT) {
- err = -EINVAL;
- goto exit;
- }
- priv->pm_mode = AT76_PM_ON;
- }
-exit:
- return err;
-}
-
-static int at76_iw_handler_get_power(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_param *power, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- power->disabled = (priv->pm_mode == AT76_PM_OFF);
- if (!power->disabled) {
- power->flags = IW_POWER_PERIOD | IW_POWER_ALL_R;
- power->value = priv->pm_period;
- }
-
- at76_dbg(DBG_IOCTL, "%s: SIOCGIWPOWER - %s flags 0x%x value 0x%x",
- netdev->name, power->disabled ? "disabled" : "enabled",
- power->flags, power->value);
-
- return 0;
-}
-
-/*******************************************************************************
- * Private IOCTLS
- */
-static int at76_iw_set_short_preamble(struct net_device *netdev,
- struct iw_request_info *info, char *name,
- char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int val = *((int *)name);
- int ret = -EIWCOMMIT;
-
- at76_dbg(DBG_IOCTL, "%s: AT76_SET_SHORT_PREAMBLE, %d",
- netdev->name, val);
-
- if (val < PREAMBLE_TYPE_LONG || val > PREAMBLE_TYPE_AUTO)
- ret = -EINVAL;
- else
- priv->preamble_type = val;
-
- return ret;
-}
-
-static int at76_iw_get_short_preamble(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- snprintf(wrqu->name, sizeof(wrqu->name), "%s (%d)",
- preambles[priv->preamble_type], priv->preamble_type);
- return 0;
-}
-
-static int at76_iw_set_debug(struct net_device *netdev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra)
-{
- char *ptr;
- u32 val;
-
- if (data->length > 0) {
- val = simple_strtol(extra, &ptr, 0);
-
- if (ptr == extra)
- val = DBG_DEFAULTS;
-
- at76_dbg(DBG_IOCTL, "%s: AT76_SET_DEBUG input %d: %s -> 0x%x",
- netdev->name, data->length, extra, val);
- } else
- val = DBG_DEFAULTS;
-
- at76_dbg(DBG_IOCTL, "%s: AT76_SET_DEBUG, old 0x%x, new 0x%x",
- netdev->name, at76_debug, val);
-
- /* jal: some more output to pin down lockups */
- at76_dbg(DBG_IOCTL, "%s: netif running %d queue_stopped %d "
- "carrier_ok %d", netdev->name, netif_running(netdev),
- netif_queue_stopped(netdev), netif_carrier_ok(netdev));
-
- at76_debug = val;
-
- return 0;
-}
-
-static int at76_iw_get_debug(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- snprintf(wrqu->name, sizeof(wrqu->name), "0x%08x", at76_debug);
- return 0;
-}
-
-static int at76_iw_set_powersave_mode(struct net_device *netdev,
- struct iw_request_info *info, char *name,
- char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int val = *((int *)name);
- int ret = -EIWCOMMIT;
-
- at76_dbg(DBG_IOCTL, "%s: AT76_SET_POWERSAVE_MODE, %d (%s)",
- netdev->name, val,
- val == AT76_PM_OFF ? "active" : val == AT76_PM_ON ? "save" :
- val == AT76_PM_SMART ? "smart save" : "<invalid>");
- if (val < AT76_PM_OFF || val > AT76_PM_SMART)
- ret = -EINVAL;
- else
- priv->pm_mode = val;
-
- return ret;
-}
-
-static int at76_iw_get_powersave_mode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int *param = (int *)extra;
-
- param[0] = priv->pm_mode;
- return 0;
-}
-
-static int at76_iw_set_scan_times(struct net_device *netdev,
- struct iw_request_info *info, char *name,
- char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int mint = *((int *)name);
- int maxt = *((int *)name + 1);
- int ret = -EIWCOMMIT;
-
- at76_dbg(DBG_IOCTL, "%s: AT76_SET_SCAN_TIMES - min %d max %d",
- netdev->name, mint, maxt);
- if (mint <= 0 || maxt <= 0 || mint > maxt)
- ret = -EINVAL;
- else {
- priv->scan_min_time = mint;
- priv->scan_max_time = maxt;
- }
-
- return ret;
-}
-
-static int at76_iw_get_scan_times(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int *param = (int *)extra;
-
- param[0] = priv->scan_min_time;
- param[1] = priv->scan_max_time;
- return 0;
-}
-
-static int at76_iw_set_scan_mode(struct net_device *netdev,
- struct iw_request_info *info, char *name,
- char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int val = *((int *)name);
- int ret = -EIWCOMMIT;
-
- at76_dbg(DBG_IOCTL, "%s: AT76_SET_SCAN_MODE - mode %s",
- netdev->name, (val = SCAN_TYPE_ACTIVE) ? "active" :
- (val = SCAN_TYPE_PASSIVE) ? "passive" : "<invalid>");
-
- if (val != SCAN_TYPE_ACTIVE && val != SCAN_TYPE_PASSIVE)
- ret = -EINVAL;
- else
- priv->scan_mode = val;
-
- return ret;
-}
-
-static int at76_iw_get_scan_mode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int *param = (int *)extra;
-
- param[0] = priv->scan_mode;
- return 0;
-}
-
-#define AT76_SET_HANDLER(h, f) [h - SIOCIWFIRST] = (iw_handler) f
-
-/* Standard wireless handlers */
-static const iw_handler at76_handlers[] = {
- AT76_SET_HANDLER(SIOCSIWCOMMIT, at76_iw_handler_commit),
- AT76_SET_HANDLER(SIOCGIWNAME, at76_iw_handler_get_name),
- AT76_SET_HANDLER(SIOCSIWFREQ, at76_iw_handler_set_freq),
- AT76_SET_HANDLER(SIOCGIWFREQ, at76_iw_handler_get_freq),
- AT76_SET_HANDLER(SIOCSIWMODE, at76_iw_handler_set_mode),
- AT76_SET_HANDLER(SIOCGIWMODE, at76_iw_handler_get_mode),
- AT76_SET_HANDLER(SIOCGIWRANGE, at76_iw_handler_get_range),
- AT76_SET_HANDLER(SIOCSIWSPY, at76_iw_handler_set_spy),
- AT76_SET_HANDLER(SIOCGIWSPY, at76_iw_handler_get_spy),
- AT76_SET_HANDLER(SIOCSIWTHRSPY, at76_iw_handler_set_thrspy),
- AT76_SET_HANDLER(SIOCGIWTHRSPY, at76_iw_handler_get_thrspy),
- AT76_SET_HANDLER(SIOCSIWAP, at76_iw_handler_set_wap),
- AT76_SET_HANDLER(SIOCGIWAP, at76_iw_handler_get_wap),
- AT76_SET_HANDLER(SIOCSIWSCAN, at76_iw_handler_set_scan),
- AT76_SET_HANDLER(SIOCGIWSCAN, at76_iw_handler_get_scan),
- AT76_SET_HANDLER(SIOCSIWESSID, at76_iw_handler_set_essid),
- AT76_SET_HANDLER(SIOCGIWESSID, at76_iw_handler_get_essid),
- AT76_SET_HANDLER(SIOCSIWRATE, at76_iw_handler_set_rate),
- AT76_SET_HANDLER(SIOCGIWRATE, at76_iw_handler_get_rate),
- AT76_SET_HANDLER(SIOCSIWRTS, at76_iw_handler_set_rts),
- AT76_SET_HANDLER(SIOCGIWRTS, at76_iw_handler_get_rts),
- AT76_SET_HANDLER(SIOCSIWFRAG, at76_iw_handler_set_frag),
- AT76_SET_HANDLER(SIOCGIWFRAG, at76_iw_handler_get_frag),
- AT76_SET_HANDLER(SIOCGIWTXPOW, at76_iw_handler_get_txpow),
- AT76_SET_HANDLER(SIOCSIWRETRY, at76_iw_handler_set_retry),
- AT76_SET_HANDLER(SIOCGIWRETRY, at76_iw_handler_get_retry),
- AT76_SET_HANDLER(SIOCSIWENCODE, at76_iw_handler_set_encode),
- AT76_SET_HANDLER(SIOCGIWENCODE, at76_iw_handler_get_encode),
- AT76_SET_HANDLER(SIOCSIWPOWER, at76_iw_handler_set_power),
- AT76_SET_HANDLER(SIOCGIWPOWER, at76_iw_handler_get_power)
-};
-
-#define AT76_SET_PRIV(h, f) [h - SIOCIWFIRSTPRIV] = (iw_handler) f
-
-/* Private wireless handlers */
-static const iw_handler at76_priv_handlers[] = {
- AT76_SET_PRIV(AT76_SET_SHORT_PREAMBLE, at76_iw_set_short_preamble),
- AT76_SET_PRIV(AT76_GET_SHORT_PREAMBLE, at76_iw_get_short_preamble),
- AT76_SET_PRIV(AT76_SET_DEBUG, at76_iw_set_debug),
- AT76_SET_PRIV(AT76_GET_DEBUG, at76_iw_get_debug),
- AT76_SET_PRIV(AT76_SET_POWERSAVE_MODE, at76_iw_set_powersave_mode),
- AT76_SET_PRIV(AT76_GET_POWERSAVE_MODE, at76_iw_get_powersave_mode),
- AT76_SET_PRIV(AT76_SET_SCAN_TIMES, at76_iw_set_scan_times),
- AT76_SET_PRIV(AT76_GET_SCAN_TIMES, at76_iw_get_scan_times),
- AT76_SET_PRIV(AT76_SET_SCAN_MODE, at76_iw_set_scan_mode),
- AT76_SET_PRIV(AT76_GET_SCAN_MODE, at76_iw_get_scan_mode),
-};
-
-/* Names and arguments of private wireless handlers */
-static const struct iw_priv_args at76_priv_args[] = {
- /* 0 - long, 1 - short */
- {AT76_SET_SHORT_PREAMBLE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"},
-
- {AT76_GET_SHORT_PREAMBLE,
- 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 10, "get_preamble"},
-
- /* we must pass the new debug mask as a string, because iwpriv cannot
- * parse hex numbers starting with 0x :-( */
- {AT76_SET_DEBUG,
- IW_PRIV_TYPE_CHAR | 10, 0, "set_debug"},
-
- {AT76_GET_DEBUG,
- 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 10, "get_debug"},
-
- /* 1 - active, 2 - power save, 3 - smart power save */
- {AT76_SET_POWERSAVE_MODE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_powersave"},
-
- {AT76_GET_POWERSAVE_MODE,
- 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_powersave"},
-
- /* min_channel_time, max_channel_time */
- {AT76_SET_SCAN_TIMES,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_scan_times"},
-
- {AT76_GET_SCAN_TIMES,
- 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, "get_scan_times"},
-
- /* 0 - active, 1 - passive scan */
- {AT76_SET_SCAN_MODE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_scan_mode"},
-
- {AT76_GET_SCAN_MODE,
- 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_scan_mode"},
-};
-
-static const struct iw_handler_def at76_handler_def = {
- .num_standard = ARRAY_SIZE(at76_handlers),
- .num_private = ARRAY_SIZE(at76_priv_handlers),
- .num_private_args = ARRAY_SIZE(at76_priv_args),
- .standard = at76_handlers,
- .private = at76_priv_handlers,
- .private_args = at76_priv_args,
- .get_wireless_stats = at76_get_wireless_stats,
-};
-
-static const u8 snapsig[] = { 0xaa, 0xaa, 0x03 };
-
-/* RFC 1042 encapsulates Ethernet frames in 802.2 SNAP (0xaa, 0xaa, 0x03) with
- * a SNAP OID of 0 (0x00, 0x00, 0x00) */
-static const u8 rfc1042sig[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-
-static int at76_tx(struct sk_buff *skb, struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- struct net_device_stats *stats = &priv->stats;
- int ret = 0;
- int wlen;
- int submit_len;
- struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
- struct ieee80211_hdr_3addr *i802_11_hdr =
- (struct ieee80211_hdr_3addr *)tx_buffer->packet;
- u8 *payload = i802_11_hdr->payload;
- struct ethhdr *eh = (struct ethhdr *)skb->data;
-
- if (netif_queue_stopped(netdev)) {
- printk(KERN_ERR "%s: %s called while netdev is stopped\n",
- netdev->name, __func__);
- /* skip this packet */
- dev_kfree_skb(skb);
- return 0;
- }
-
- if (priv->tx_urb->status == -EINPROGRESS) {
- printk(KERN_ERR "%s: %s called while tx urb is pending\n",
- netdev->name, __func__);
- /* skip this packet */
- dev_kfree_skb(skb);
- return 0;
- }
-
- if (skb->len < ETH_HLEN) {
- printk(KERN_ERR "%s: %s: skb too short (%d)\n",
- netdev->name, __func__, skb->len);
- dev_kfree_skb(skb);
- return 0;
- }
-
- at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
-
- /* we can get rid of memcpy if we set netdev->hard_header_len to
- reserve enough space, but we would need to keep the skb around */
-
- if (ntohs(eh->h_proto) <= ETH_DATA_LEN) {
- /* this is a 802.3 packet */
- if (skb->len >= ETH_HLEN + sizeof(rfc1042sig)
- && skb->data[ETH_HLEN] == rfc1042sig[0]
- && skb->data[ETH_HLEN + 1] == rfc1042sig[1]) {
- /* higher layer delivered SNAP header - keep it */
- memcpy(payload, skb->data + ETH_HLEN,
- skb->len - ETH_HLEN);
- wlen = IEEE80211_3ADDR_LEN + skb->len - ETH_HLEN;
- } else {
- printk(KERN_ERR "%s: dropping non-SNAP 802.2 packet "
- "(DSAP 0x%02x SSAP 0x%02x cntrl 0x%02x)\n",
- priv->netdev->name, skb->data[ETH_HLEN],
- skb->data[ETH_HLEN + 1],
- skb->data[ETH_HLEN + 2]);
- dev_kfree_skb(skb);
- return 0;
- }
- } else {
- /* add RFC 1042 header in front */
- memcpy(payload, rfc1042sig, sizeof(rfc1042sig));
- memcpy(payload + sizeof(rfc1042sig), &eh->h_proto,
- skb->len - offsetof(struct ethhdr, h_proto));
- wlen = IEEE80211_3ADDR_LEN + sizeof(rfc1042sig) + skb->len -
- offsetof(struct ethhdr, h_proto);
- }
-
- /* make wireless header */
- i802_11_hdr->frame_ctl =
- cpu_to_le16(IEEE80211_FTYPE_DATA |
- (priv->wep_enabled ? IEEE80211_FCTL_PROTECTED : 0) |
- (priv->iw_mode ==
- IW_MODE_INFRA ? IEEE80211_FCTL_TODS : 0));
-
- if (priv->iw_mode == IW_MODE_ADHOC) {
- memcpy(i802_11_hdr->addr1, eh->h_dest, ETH_ALEN);
- memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN);
- memcpy(i802_11_hdr->addr3, priv->bssid, ETH_ALEN);
- } else if (priv->iw_mode == IW_MODE_INFRA) {
- memcpy(i802_11_hdr->addr1, priv->bssid, ETH_ALEN);
- memcpy(i802_11_hdr->addr2, eh->h_source, ETH_ALEN);
- memcpy(i802_11_hdr->addr3, eh->h_dest, ETH_ALEN);
- }
-
- i802_11_hdr->duration_id = cpu_to_le16(0);
- i802_11_hdr->seq_ctl = cpu_to_le16(0);
-
- /* setup 'Atmel' header */
- tx_buffer->wlength = cpu_to_le16(wlen);
- tx_buffer->tx_rate = priv->txrate;
- /* for broadcast destination addresses, the firmware 0.100.x
- seems to choose the highest rate set with CMD_STARTUP in
- basic_rate_set replacing this value */
-
- memset(tx_buffer->reserved, 0, sizeof(tx_buffer->reserved));
-
- tx_buffer->padding = at76_calc_padding(wlen);
- submit_len = wlen + AT76_TX_HDRLEN + tx_buffer->padding;
-
- at76_dbg(DBG_TX_DATA_CONTENT, "%s skb->data %s", priv->netdev->name,
- hex2str(skb->data, 32));
- at76_dbg(DBG_TX_DATA, "%s tx: wlen 0x%x pad 0x%x rate %d hdr %s",
- priv->netdev->name,
- le16_to_cpu(tx_buffer->wlength),
- tx_buffer->padding, tx_buffer->tx_rate,
- hex2str(i802_11_hdr, sizeof(*i802_11_hdr)));
- at76_dbg(DBG_TX_DATA_CONTENT, "%s payload %s", priv->netdev->name,
- hex2str(payload, 48));
-
- /* send stuff */
- netif_stop_queue(netdev);
- netdev->trans_start = jiffies;
-
- usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe, tx_buffer,
- submit_len, at76_tx_callback, priv);
- ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
- if (ret) {
- stats->tx_errors++;
- printk(KERN_ERR "%s: error in tx submit urb: %d\n",
- netdev->name, ret);
- if (ret == -EINVAL)
- printk(KERN_ERR
- "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n",
- priv->netdev->name, priv->tx_urb,
- priv->tx_urb->hcpriv, priv->tx_urb->complete);
- } else {
- stats->tx_bytes += skb->len;
- dev_kfree_skb(skb);
- }
-
- return ret;
-}
-
-static void at76_tx_timeout(struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- if (!priv)
- return;
- dev_warn(&netdev->dev, "tx timeout.");
-
- usb_unlink_urb(priv->tx_urb);
- priv->stats.tx_errors++;
-}
-
static int at76_submit_rx_urb(struct at76_priv *priv)
{
int ret;
@@ -3256,7 +1327,7 @@ static int at76_submit_rx_urb(struct at76_priv *priv)
if (!priv->rx_urb) {
printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n",
- priv->netdev->name, __func__);
+ wiphy_name(priv->hw->wiphy), __func__);
return -EFAULT;
}
@@ -3264,7 +1335,7 @@ static int at76_submit_rx_urb(struct at76_priv *priv)
skb = dev_alloc_skb(sizeof(struct at76_rx_buffer));
if (!skb) {
printk(KERN_ERR "%s: cannot allocate rx skbuff\n",
- priv->netdev->name);
+ wiphy_name(priv->hw->wiphy));
ret = -ENOMEM;
goto exit;
}
@@ -3284,110 +1355,18 @@ static int at76_submit_rx_urb(struct at76_priv *priv)
"usb_submit_urb returned -ENODEV");
else
printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
}
exit:
if (ret < 0 && ret != -ENODEV)
printk(KERN_ERR "%s: cannot submit rx urb - please unload the "
"driver and/or power cycle the device\n",
- priv->netdev->name);
+ wiphy_name(priv->hw->wiphy));
return ret;
}
-static int at76_open(struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- int ret = 0;
-
- at76_dbg(DBG_PROC_ENTRY, "%s(): entry", __func__);
-
- if (mutex_lock_interruptible(&priv->mtx))
- return -EINTR;
-
- /* if netdev->dev_addr != priv->mac_addr we must
- set the mac address in the device ! */
- if (compare_ether_addr(netdev->dev_addr, priv->mac_addr)) {
- if (at76_add_mac_address(priv, netdev->dev_addr) >= 0)
- at76_dbg(DBG_PROGRESS, "%s: set new MAC addr %s",
- netdev->name, mac2str(netdev->dev_addr));
- }
-
- priv->scan_state = SCAN_IDLE;
- priv->last_scan = jiffies;
-
- ret = at76_submit_rx_urb(priv);
- if (ret < 0) {
- printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n",
- netdev->name, ret);
- goto error;
- }
-
- schedule_delayed_work(&priv->dwork_restart, 0);
-
- at76_dbg(DBG_PROC_ENTRY, "%s(): end", __func__);
-error:
- mutex_unlock(&priv->mtx);
- return ret < 0 ? ret : 0;
-}
-
-static int at76_stop(struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- at76_dbg(DBG_DEVSTART, "%s: ENTER", __func__);
-
- if (mutex_lock_interruptible(&priv->mtx))
- return -EINTR;
-
- at76_quiesce(priv);
-
- if (!priv->device_unplugged) {
- /* We are called by "ifconfig ethX down", not because the
- * device is not available anymore. */
- at76_set_radio(priv, 0);
-
- /* We unlink rx_urb because at76_open() re-submits it.
- * If unplugged, at76_delete_device() takes care of it. */
- usb_kill_urb(priv->rx_urb);
- }
-
- /* free the bss_list */
- at76_free_bss_list(priv);
-
- mutex_unlock(&priv->mtx);
- at76_dbg(DBG_DEVSTART, "%s: EXIT", __func__);
-
- return 0;
-}
-
-static void at76_ethtool_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *info)
-{
- struct at76_priv *priv = netdev_priv(netdev);
-
- strncpy(info->driver, DRIVER_NAME, sizeof(info->driver));
- strncpy(info->version, DRIVER_VERSION, sizeof(info->version));
-
- usb_make_path(priv->udev, info->bus_info, sizeof(info->bus_info));
-
- snprintf(info->fw_version, sizeof(info->fw_version), "%d.%d.%d-%d",
- priv->fw_version.major, priv->fw_version.minor,
- priv->fw_version.patch, priv->fw_version.build);
-}
-
-static u32 at76_ethtool_get_link(struct net_device *netdev)
-{
- struct at76_priv *priv = netdev_priv(netdev);
- return priv->mac_state == MAC_CONNECTED;
-}
-
-static struct ethtool_ops at76_ethtool_ops = {
- .get_drvinfo = at76_ethtool_get_drvinfo,
- .get_link = at76_ethtool_get_link,
-};
-
/* Download external firmware */
static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
{
@@ -3484,406 +1463,6 @@ exit:
return ret;
}
-static int at76_match_essid(struct at76_priv *priv, struct bss_info *ptr)
-{
- /* common criteria for both modi */
-
- int ret = (priv->essid_size == 0 /* ANY ssid */ ||
- (priv->essid_size == ptr->ssid_len &&
- !memcmp(priv->essid, ptr->ssid, ptr->ssid_len)));
- if (!ret)
- at76_dbg(DBG_BSS_MATCH,
- "%s bss table entry %p: essid didn't match",
- priv->netdev->name, ptr);
- return ret;
-}
-
-static inline int at76_match_mode(struct at76_priv *priv, struct bss_info *ptr)
-{
- int ret;
-
- if (priv->iw_mode == IW_MODE_ADHOC)
- ret = ptr->capa & WLAN_CAPABILITY_IBSS;
- else
- ret = ptr->capa & WLAN_CAPABILITY_ESS;
- if (!ret)
- at76_dbg(DBG_BSS_MATCH,
- "%s bss table entry %p: mode didn't match",
- priv->netdev->name, ptr);
- return ret;
-}
-
-static int at76_match_rates(struct at76_priv *priv, struct bss_info *ptr)
-{
- int i;
-
- for (i = 0; i < ptr->rates_len; i++) {
- u8 rate = ptr->rates[i];
-
- if (!(rate & 0x80))
- continue;
-
- /* this is a basic rate we have to support
- (see IEEE802.11, ch. 7.3.2.2) */
- if (rate != (0x80 | hw_rates[0])
- && rate != (0x80 | hw_rates[1])
- && rate != (0x80 | hw_rates[2])
- && rate != (0x80 | hw_rates[3])) {
- at76_dbg(DBG_BSS_MATCH,
- "%s: bss table entry %p: basic rate %02x not "
- "supported", priv->netdev->name, ptr, rate);
- return 0;
- }
- }
-
- /* if we use short preamble, the bss must support it */
- if (priv->preamble_type == PREAMBLE_TYPE_SHORT &&
- !(ptr->capa & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
- at76_dbg(DBG_BSS_MATCH,
- "%s: %p does not support short preamble",
- priv->netdev->name, ptr);
- return 0;
- } else
- return 1;
-}
-
-static inline int at76_match_wep(struct at76_priv *priv, struct bss_info *ptr)
-{
- if (!priv->wep_enabled && ptr->capa & WLAN_CAPABILITY_PRIVACY) {
- /* we have disabled WEP, but the BSS signals privacy */
- at76_dbg(DBG_BSS_MATCH,
- "%s: bss table entry %p: requires encryption",
- priv->netdev->name, ptr);
- return 0;
- }
- /* otherwise if the BSS does not signal privacy it may well
- accept encrypted packets from us ... */
- return 1;
-}
-
-static inline int at76_match_bssid(struct at76_priv *priv, struct bss_info *ptr)
-{
- if (!priv->wanted_bssid_valid ||
- !compare_ether_addr(ptr->bssid, priv->wanted_bssid))
- return 1;
-
- at76_dbg(DBG_BSS_MATCH,
- "%s: requested bssid - %s does not match",
- priv->netdev->name, mac2str(priv->wanted_bssid));
- at76_dbg(DBG_BSS_MATCH,
- " AP bssid - %s of bss table entry %p",
- mac2str(ptr->bssid), ptr);
- return 0;
-}
-
-/**
- * at76_match_bss - try to find a matching bss in priv->bss
- *
- * last - last bss tried
- *
- * last == NULL signals a new round starting with priv->bss_list.next
- * this function must be called inside an acquired priv->bss_list_spinlock
- * otherwise the timeout on bss may remove the newly chosen entry
- */
-static struct bss_info *at76_match_bss(struct at76_priv *priv,
- struct bss_info *last)
-{
- struct bss_info *ptr = NULL;
- struct list_head *curr;
-
- curr = last ? last->list.next : priv->bss_list.next;
- while (curr != &priv->bss_list) {
- ptr = list_entry(curr, struct bss_info, list);
- if (at76_match_essid(priv, ptr) && at76_match_mode(priv, ptr)
- && at76_match_wep(priv, ptr) && at76_match_rates(priv, ptr)
- && at76_match_bssid(priv, ptr))
- break;
- curr = curr->next;
- }
-
- if (curr == &priv->bss_list)
- ptr = NULL;
- /* otherwise ptr points to the struct bss_info we have chosen */
-
- at76_dbg(DBG_BSS_TABLE, "%s %s: returned %p", priv->netdev->name,
- __func__, ptr);
- return ptr;
-}
-
-/* Start joining a matching BSS, or create own IBSS */
-static void at76_work_join(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- work_join);
- int ret;
- unsigned long flags;
-
- mutex_lock(&priv->mtx);
-
- WARN_ON(priv->mac_state != MAC_JOINING);
- if (priv->mac_state != MAC_JOINING)
- goto exit;
-
- /* secure the access to priv->curr_bss ! */
- spin_lock_irqsave(&priv->bss_list_spinlock, flags);
- priv->curr_bss = at76_match_bss(priv, priv->curr_bss);
- spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
-
- if (!priv->curr_bss) {
- /* here we haven't found a matching (i)bss ... */
- if (priv->iw_mode == IW_MODE_ADHOC) {
- at76_set_mac_state(priv, MAC_OWN_IBSS);
- at76_start_ibss(priv);
- goto exit;
- }
- /* haven't found a matching BSS in infra mode - try again */
- at76_set_mac_state(priv, MAC_SCANNING);
- schedule_work(&priv->work_start_scan);
- goto exit;
- }
-
- ret = at76_join_bss(priv, priv->curr_bss);
- if (ret < 0) {
- printk(KERN_ERR "%s: join_bss failed with %d\n",
- priv->netdev->name, ret);
- goto exit;
- }
-
- ret = at76_wait_completion(priv, CMD_JOIN);
- if (ret != CMD_STATUS_COMPLETE) {
- if (ret != CMD_STATUS_TIME_OUT)
- printk(KERN_ERR "%s: join_bss completed with %d\n",
- priv->netdev->name, ret);
- else
- printk(KERN_INFO "%s: join_bss ssid %s timed out\n",
- priv->netdev->name,
- mac2str(priv->curr_bss->bssid));
-
- /* retry next BSS immediately */
- schedule_work(&priv->work_join);
- goto exit;
- }
-
- /* here we have joined the (I)BSS */
- if (priv->iw_mode == IW_MODE_ADHOC) {
- struct bss_info *bptr = priv->curr_bss;
- at76_set_mac_state(priv, MAC_CONNECTED);
- /* get ESSID, BSSID and channel for priv->curr_bss */
- priv->essid_size = bptr->ssid_len;
- memcpy(priv->essid, bptr->ssid, bptr->ssid_len);
- memcpy(priv->bssid, bptr->bssid, ETH_ALEN);
- priv->channel = bptr->channel;
- at76_iwevent_bss_connect(priv->netdev, bptr->bssid);
- netif_carrier_on(priv->netdev);
- netif_start_queue(priv->netdev);
- /* just to be sure */
- cancel_delayed_work(&priv->dwork_get_scan);
- cancel_delayed_work(&priv->dwork_auth);
- cancel_delayed_work(&priv->dwork_assoc);
- } else {
- /* send auth req */
- priv->retries = AUTH_RETRIES;
- at76_set_mac_state(priv, MAC_AUTH);
- at76_auth_req(priv, priv->curr_bss, 1, NULL);
- at76_dbg(DBG_MGMT_TIMER,
- "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
- schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
- }
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
-/* Reap scan results */
-static void at76_dwork_get_scan(struct work_struct *work)
-{
- int status;
- int ret;
- struct at76_priv *priv = container_of(work, struct at76_priv,
- dwork_get_scan.work);
-
- mutex_lock(&priv->mtx);
- WARN_ON(priv->mac_state != MAC_SCANNING);
- if (priv->mac_state != MAC_SCANNING)
- goto exit;
-
- status = at76_get_cmd_status(priv->udev, CMD_SCAN);
- if (status < 0) {
- printk(KERN_ERR "%s: %s: at76_get_cmd_status failed with %d\n",
- priv->netdev->name, __func__, status);
- status = CMD_STATUS_IN_PROGRESS;
- /* INFO: Hope it was a one off error - if not, scanning
- further down the line and stop this cycle */
- }
- at76_dbg(DBG_PROGRESS,
- "%s %s: got cmd_status %d (state %s, need_any %d)",
- priv->netdev->name, __func__, status,
- mac_states[priv->mac_state], priv->scan_need_any);
-
- if (status != CMD_STATUS_COMPLETE) {
- if ((status != CMD_STATUS_IN_PROGRESS) &&
- (status != CMD_STATUS_IDLE))
- printk(KERN_ERR "%s: %s: Bad scan status: %s\n",
- priv->netdev->name, __func__,
- at76_get_cmd_status_string(status));
-
- /* the first cmd status after scan start is always a IDLE ->
- start the timer to poll again until COMPLETED */
- at76_dbg(DBG_MGMT_TIMER,
- "%s:%d: starting mgmt_timer for %d ticks",
- __func__, __LINE__, SCAN_POLL_INTERVAL);
- schedule_delayed_work(&priv->dwork_get_scan,
- SCAN_POLL_INTERVAL);
- goto exit;
- }
-
- if (at76_debug & DBG_BSS_TABLE)
- at76_dump_bss_table(priv);
-
- if (priv->scan_need_any) {
- ret = at76_start_scan(priv, 0);
- if (ret < 0)
- printk(KERN_ERR
- "%s: %s: start_scan (ANY) failed with %d\n",
- priv->netdev->name, __func__, ret);
- at76_dbg(DBG_MGMT_TIMER,
- "%s:%d: starting mgmt_timer for %d ticks", __func__,
- __LINE__, SCAN_POLL_INTERVAL);
- schedule_delayed_work(&priv->dwork_get_scan,
- SCAN_POLL_INTERVAL);
- priv->scan_need_any = 0;
- } else {
- priv->scan_state = SCAN_COMPLETED;
- /* report the end of scan to user space */
- at76_iwevent_scan_complete(priv->netdev);
- at76_set_mac_state(priv, MAC_JOINING);
- schedule_work(&priv->work_join);
- }
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
-/* Handle loss of beacons from the AP */
-static void at76_dwork_beacon(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- dwork_beacon.work);
-
- mutex_lock(&priv->mtx);
- if (priv->mac_state != MAC_CONNECTED || priv->iw_mode != IW_MODE_INFRA)
- goto exit;
-
- /* We haven't received any beacons from out AP for BEACON_TIMEOUT */
- printk(KERN_INFO "%s: lost beacon bssid %s\n",
- priv->netdev->name, mac2str(priv->curr_bss->bssid));
-
- netif_carrier_off(priv->netdev);
- netif_stop_queue(priv->netdev);
- at76_iwevent_bss_disconnect(priv->netdev);
- at76_set_mac_state(priv, MAC_SCANNING);
- schedule_work(&priv->work_start_scan);
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
-/* Handle authentication response timeout */
-static void at76_dwork_auth(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- dwork_auth.work);
-
- mutex_lock(&priv->mtx);
- WARN_ON(priv->mac_state != MAC_AUTH);
- if (priv->mac_state != MAC_AUTH)
- goto exit;
-
- at76_dbg(DBG_PROGRESS, "%s: authentication response timeout",
- priv->netdev->name);
-
- if (priv->retries-- >= 0) {
- at76_auth_req(priv, priv->curr_bss, 1, NULL);
- at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ",
- __func__, __LINE__);
- schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
- } else {
- /* try to get next matching BSS */
- at76_set_mac_state(priv, MAC_JOINING);
- schedule_work(&priv->work_join);
- }
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
-/* Handle association response timeout */
-static void at76_dwork_assoc(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- dwork_assoc.work);
-
- mutex_lock(&priv->mtx);
- WARN_ON(priv->mac_state != MAC_ASSOC);
- if (priv->mac_state != MAC_ASSOC)
- goto exit;
-
- at76_dbg(DBG_PROGRESS, "%s: association response timeout",
- priv->netdev->name);
-
- if (priv->retries-- >= 0) {
- at76_assoc_req(priv, priv->curr_bss);
- at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ",
- __func__, __LINE__);
- schedule_delayed_work(&priv->dwork_assoc, ASSOC_TIMEOUT);
- } else {
- /* try to get next matching BSS */
- at76_set_mac_state(priv, MAC_JOINING);
- schedule_work(&priv->work_join);
- }
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
-/* Read new bssid in ad-hoc mode */
-static void at76_work_new_bss(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- work_new_bss);
- int ret;
- struct mib_mac_mgmt mac_mgmt;
-
- mutex_lock(&priv->mtx);
-
- ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, &mac_mgmt,
- sizeof(struct mib_mac_mgmt));
- if (ret < 0) {
- printk(KERN_ERR "%s: at76_get_mib failed: %d\n",
- priv->netdev->name, ret);
- goto exit;
- }
-
- at76_dbg(DBG_PROGRESS, "ibss_change = 0x%2x", mac_mgmt.ibss_change);
- memcpy(priv->bssid, mac_mgmt.current_bssid, ETH_ALEN);
- at76_dbg(DBG_PROGRESS, "using BSSID %s", mac2str(priv->bssid));
-
- at76_iwevent_bss_connect(priv->netdev, priv->bssid);
-
- priv->mib_buf.type = MIB_MAC_MGMT;
- priv->mib_buf.size = 1;
- priv->mib_buf.index = offsetof(struct mib_mac_mgmt, ibss_change);
- priv->mib_buf.data.byte = 0;
-
- ret = at76_set_mib(priv, &priv->mib_buf);
- if (ret < 0)
- printk(KERN_ERR "%s: set_mib (ibss change ok) failed: %d\n",
- priv->netdev->name, ret);
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
static int at76_startup_device(struct at76_priv *priv)
{
struct at76_card_config *ccfg = &priv->card_config;
@@ -3891,14 +1470,14 @@ static int at76_startup_device(struct at76_priv *priv)
at76_dbg(DBG_PARAMS,
"%s param: ssid %.*s (%s) mode %s ch %d wep %s key %d "
- "keylen %d", priv->netdev->name, priv->essid_size, priv->essid,
- hex2str(priv->essid, IW_ESSID_MAX_SIZE),
+ "keylen %d", wiphy_name(priv->hw->wiphy), priv->essid_size,
+ priv->essid, hex2str(priv->essid, IW_ESSID_MAX_SIZE),
priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra",
priv->channel, priv->wep_enabled ? "enabled" : "disabled",
priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]);
at76_dbg(DBG_PARAMS,
"%s param: preamble %s rts %d retry %d frag %d "
- "txrate %s auth_mode %d", priv->netdev->name,
+ "txrate %s auth_mode %d", wiphy_name(priv->hw->wiphy),
preambles[priv->preamble_type], priv->rts_threshold,
priv->short_retry_limit, priv->frag_threshold,
priv->txrate == TX_RATE_1MBIT ? "1MBit" : priv->txrate ==
@@ -3909,7 +1488,7 @@ static int at76_startup_device(struct at76_priv *priv)
at76_dbg(DBG_PARAMS,
"%s param: pm_mode %d pm_period %d auth_mode %s "
"scan_times %d %d scan_mode %s",
- priv->netdev->name, priv->pm_mode, priv->pm_period,
+ wiphy_name(priv->hw->wiphy), priv->pm_mode, priv->pm_period,
priv->auth_mode == WLAN_AUTH_OPEN ? "open" : "shared_secret",
priv->scan_min_time, priv->scan_max_time,
priv->scan_mode == SCAN_TYPE_ACTIVE ? "active" : "passive");
@@ -3943,7 +1522,8 @@ static int at76_startup_device(struct at76_priv *priv)
ccfg->ssid_len = priv->essid_size;
ccfg->wep_default_key_id = priv->wep_key_id;
- memcpy(ccfg->wep_default_key_value, priv->wep_keys, 4 * WEP_KEY_LEN);
+ memcpy(ccfg->wep_default_key_value, priv->wep_keys,
+ sizeof(priv->wep_keys));
ccfg->short_preamble = priv->preamble_type;
ccfg->beacon_period = cpu_to_le16(priv->beacon_period);
@@ -3952,7 +1532,7 @@ static int at76_startup_device(struct at76_priv *priv)
sizeof(struct at76_card_config));
if (ret < 0) {
printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
return ret;
}
@@ -3998,69 +1578,6 @@ static int at76_startup_device(struct at76_priv *priv)
return 0;
}
-/* Restart the interface */
-static void at76_dwork_restart(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- dwork_restart.work);
-
- mutex_lock(&priv->mtx);
-
- netif_carrier_off(priv->netdev); /* stop netdev watchdog */
- netif_stop_queue(priv->netdev); /* stop tx data packets */
-
- at76_startup_device(priv);
-
- if (priv->iw_mode != IW_MODE_MONITOR) {
- priv->netdev->type = ARPHRD_ETHER;
- at76_set_mac_state(priv, MAC_SCANNING);
- schedule_work(&priv->work_start_scan);
- } else {
- priv->netdev->type = ARPHRD_IEEE80211_RADIOTAP;
- at76_start_monitor(priv);
- }
-
- mutex_unlock(&priv->mtx);
-}
-
-/* Initiate scanning */
-static void at76_work_start_scan(struct work_struct *work)
-{
- struct at76_priv *priv = container_of(work, struct at76_priv,
- work_start_scan);
- int ret;
-
- mutex_lock(&priv->mtx);
-
- WARN_ON(priv->mac_state != MAC_SCANNING);
- if (priv->mac_state != MAC_SCANNING)
- goto exit;
-
- /* only clear the bss list when a scan is actively initiated,
- * otherwise simply rely on at76_bss_list_timeout */
- if (priv->scan_state == SCAN_IN_PROGRESS) {
- at76_free_bss_list(priv);
- priv->scan_need_any = 1;
- } else
- priv->scan_need_any = 0;
-
- ret = at76_start_scan(priv, 1);
-
- if (ret < 0)
- printk(KERN_ERR "%s: %s: start_scan failed with %d\n",
- priv->netdev->name, __func__, ret);
- else {
- at76_dbg(DBG_MGMT_TIMER,
- "%s:%d: starting mgmt_timer for %d ticks",
- __func__, __LINE__, SCAN_POLL_INTERVAL);
- schedule_delayed_work(&priv->dwork_get_scan,
- SCAN_POLL_INTERVAL);
- }
-
-exit:
- mutex_unlock(&priv->mtx);
-}
-
/* Enable or disable promiscuous mode */
static void at76_work_set_promisc(struct work_struct *work)
{
@@ -4078,7 +1595,7 @@ static void at76_work_set_promisc(struct work_struct *work)
ret = at76_set_mib(priv, &priv->mib_buf);
if (ret < 0)
printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n",
- priv->netdev->name, ret);
+ wiphy_name(priv->hw->wiphy), ret);
mutex_unlock(&priv->mtx);
}
@@ -4094,1088 +1611,759 @@ static void at76_work_submit_rx(struct work_struct *work)
mutex_unlock(&priv->mtx);
}
-/* We got an association response */
-static void at76_rx_mgmt_assoc(struct at76_priv *priv,
- struct at76_rx_buffer *buf)
+static void at76_rx_tasklet(unsigned long param)
{
- struct ieee80211_assoc_response *resp =
- (struct ieee80211_assoc_response *)buf->packet;
- u16 assoc_id = le16_to_cpu(resp->aid);
- u16 status = le16_to_cpu(resp->status);
-
- at76_dbg(DBG_RX_MGMT, "%s: rx AssocResp bssid %s capa 0x%04x status "
- "0x%04x assoc_id 0x%04x rates %s", priv->netdev->name,
- mac2str(resp->header.addr3), le16_to_cpu(resp->capability),
- status, assoc_id, hex2str(resp->info_element->data,
- resp->info_element->len));
-
- if (priv->mac_state != MAC_ASSOC) {
- printk(KERN_INFO "%s: AssocResp in state %s ignored\n",
- priv->netdev->name, mac_states[priv->mac_state]);
- return;
- }
-
- BUG_ON(!priv->curr_bss);
-
- cancel_delayed_work(&priv->dwork_assoc);
- if (status == WLAN_STATUS_SUCCESS) {
- struct bss_info *ptr = priv->curr_bss;
- priv->assoc_id = assoc_id & 0x3fff;
- /* update iwconfig params */
- memcpy(priv->bssid, ptr->bssid, ETH_ALEN);
- memcpy(priv->essid, ptr->ssid, ptr->ssid_len);
- priv->essid_size = ptr->ssid_len;
- priv->channel = ptr->channel;
- schedule_work(&priv->work_assoc_done);
- } else {
- at76_set_mac_state(priv, MAC_JOINING);
- schedule_work(&priv->work_join);
- }
-}
+ struct urb *urb = (struct urb *)param;
+ struct at76_priv *priv = urb->context;
+ struct at76_rx_buffer *buf;
+ struct ieee80211_rx_status rx_status = { 0 };
-/* Process disassociation request from the AP */
-static void at76_rx_mgmt_disassoc(struct at76_priv *priv,
- struct at76_rx_buffer *buf)
-{
- struct ieee80211_disassoc *resp =
- (struct ieee80211_disassoc *)buf->packet;
- struct ieee80211_hdr_3addr *mgmt = &resp->header;
-
- at76_dbg(DBG_RX_MGMT,
- "%s: rx DisAssoc bssid %s reason 0x%04x destination %s",
- priv->netdev->name, mac2str(mgmt->addr3),
- le16_to_cpu(resp->reason), mac2str(mgmt->addr1));
-
- /* We are not connected, ignore */
- if (priv->mac_state == MAC_SCANNING || priv->mac_state == MAC_INIT
- || !priv->curr_bss)
+ if (priv->device_unplugged) {
+ at76_dbg(DBG_DEVSTART, "device unplugged");
+ if (urb)
+ at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
return;
+ }
- /* Not our BSSID, ignore */
- if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
+ if (!priv->rx_skb || !priv->rx_skb->data)
return;
- /* Not for our STA and not broadcast, ignore */
- if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
- && !is_broadcast_ether_addr(mgmt->addr1))
- return;
+ buf = (struct at76_rx_buffer *)priv->rx_skb->data;
- if (priv->mac_state != MAC_ASSOC && priv->mac_state != MAC_CONNECTED
- && priv->mac_state != MAC_JOINING) {
- printk(KERN_INFO "%s: DisAssoc in state %s ignored\n",
- priv->netdev->name, mac_states[priv->mac_state]);
+ if (urb->status != 0) {
+ if (urb->status != -ENOENT && urb->status != -ECONNRESET)
+ at76_dbg(DBG_URB,
+ "%s %s: - nonzero Rx bulk status received: %d",
+ __func__, wiphy_name(priv->hw->wiphy),
+ urb->status);
return;
}
- if (priv->mac_state == MAC_CONNECTED) {
- netif_carrier_off(priv->netdev);
- netif_stop_queue(priv->netdev);
- at76_iwevent_bss_disconnect(priv->netdev);
- }
- cancel_delayed_work(&priv->dwork_get_scan);
- cancel_delayed_work(&priv->dwork_beacon);
- cancel_delayed_work(&priv->dwork_auth);
- cancel_delayed_work(&priv->dwork_assoc);
- at76_set_mac_state(priv, MAC_JOINING);
- schedule_work(&priv->work_join);
+ at76_dbg(DBG_RX_ATMEL_HDR,
+ "%s: rx frame: rate %d rssi %d noise %d link %d",
+ wiphy_name(priv->hw->wiphy), buf->rx_rate, buf->rssi,
+ buf->noise_level, buf->link_quality);
+
+ skb_trim(priv->rx_skb, le16_to_cpu(buf->wlength) + AT76_RX_HDRLEN);
+ at76_dbg_dump(DBG_RX_DATA, &priv->rx_skb->data[AT76_RX_HDRLEN],
+ priv->rx_skb->len, "RX: len=%d",
+ (int)(priv->rx_skb->len - AT76_RX_HDRLEN));
+
+ rx_status.signal = buf->rssi;
+ /* FIXME: is rate_idx still present in structure? */
+ rx_status.rate_idx = buf->rx_rate;
+ rx_status.flag |= RX_FLAG_DECRYPTED;
+ rx_status.flag |= RX_FLAG_IV_STRIPPED;
+
+ skb_pull(priv->rx_skb, AT76_RX_HDRLEN);
+ at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d",
+ priv->rx_skb->len, priv->rx_skb->data_len);
+ ieee80211_rx_irqsafe(priv->hw, priv->rx_skb, &rx_status);
+
+ /* Use a new skb for the next receive */
+ priv->rx_skb = NULL;
+
+ at76_submit_rx_urb(priv);
}
-static void at76_rx_mgmt_auth(struct at76_priv *priv,
- struct at76_rx_buffer *buf)
+/* Load firmware into kernel memory and parse it */
+static struct fwentry *at76_load_firmware(struct usb_device *udev,
+ enum board_type board_type)
{
- struct ieee80211_auth *resp = (struct ieee80211_auth *)buf->packet;
- struct ieee80211_hdr_3addr *mgmt = &resp->header;
- int seq_nr = le16_to_cpu(resp->transaction);
- int alg = le16_to_cpu(resp->algorithm);
- int status = le16_to_cpu(resp->status);
-
- at76_dbg(DBG_RX_MGMT,
- "%s: rx AuthFrame bssid %s alg %d seq_nr %d status %d "
- "destination %s", priv->netdev->name, mac2str(mgmt->addr3),
- alg, seq_nr, status, mac2str(mgmt->addr1));
-
- if (alg == WLAN_AUTH_SHARED_KEY && seq_nr == 2)
- at76_dbg(DBG_RX_MGMT, "%s: AuthFrame challenge %s ...",
- priv->netdev->name, hex2str(resp->info_element, 18));
-
- if (priv->mac_state != MAC_AUTH) {
- printk(KERN_INFO "%s: ignored AuthFrame in state %s\n",
- priv->netdev->name, mac_states[priv->mac_state]);
- return;
- }
- if (priv->auth_mode != alg) {
- printk(KERN_INFO "%s: ignored AuthFrame for alg %d\n",
- priv->netdev->name, alg);
- return;
+ int ret;
+ char *str;
+ struct at76_fw_header *fwh;
+ struct fwentry *fwe = &firmwares[board_type];
+
+ mutex_lock(&fw_mutex);
+
+ if (fwe->loaded) {
+ at76_dbg(DBG_FW, "re-using previously loaded fw");
+ goto exit;
}
- BUG_ON(!priv->curr_bss);
+ at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
+ ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
+ if (ret < 0) {
+ dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
+ fwe->fwname);
+ dev_printk(KERN_ERR, &udev->dev,
+ "you may need to download the firmware from "
+ "http://developer.berlios.de/projects/at76c503a/\n");
+ goto exit;
+ }
- /* Not our BSSID or not for our STA, ignore */
- if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid)
- || compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1))
- return;
+ at76_dbg(DBG_FW, "got it.");
+ fwh = (struct at76_fw_header *)(fwe->fw->data);
- cancel_delayed_work(&priv->dwork_auth);
- if (status != WLAN_STATUS_SUCCESS) {
- /* try to join next bss */
- at76_set_mac_state(priv, MAC_JOINING);
- schedule_work(&priv->work_join);
- return;
+ if (fwe->fw->size <= sizeof(*fwh)) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "firmware is too short (0x%zx)\n", fwe->fw->size);
+ goto exit;
}
- if (priv->auth_mode == WLAN_AUTH_OPEN || seq_nr == 4) {
- priv->retries = ASSOC_RETRIES;
- at76_set_mac_state(priv, MAC_ASSOC);
- at76_assoc_req(priv, priv->curr_bss);
- at76_dbg(DBG_MGMT_TIMER,
- "%s:%d: starting mgmt_timer + HZ", __func__, __LINE__);
- schedule_delayed_work(&priv->dwork_assoc, ASSOC_TIMEOUT);
- return;
+ /* CRC currently not checked */
+ fwe->board_type = le32_to_cpu(fwh->board_type);
+ if (fwe->board_type != board_type) {
+ dev_printk(KERN_ERR, &udev->dev,
+ "board type mismatch, requested %u, got %u\n",
+ board_type, fwe->board_type);
+ goto exit;
}
- WARN_ON(seq_nr != 2);
- at76_auth_req(priv, priv->curr_bss, seq_nr + 1, resp->info_element);
- at76_dbg(DBG_MGMT_TIMER, "%s:%d: starting mgmt_timer + HZ", __func__,
- __LINE__);
- schedule_delayed_work(&priv->dwork_auth, AUTH_TIMEOUT);
-}
+ fwe->fw_version.major = fwh->major;
+ fwe->fw_version.minor = fwh->minor;
+ fwe->fw_version.patch = fwh->patch;
+ fwe->fw_version.build = fwh->build;
-static void at76_rx_mgmt_deauth(struct at76_priv *priv,
- struct at76_rx_buffer *buf)
-{
- struct ieee80211_disassoc *resp =
- (struct ieee80211_disassoc *)buf->packet;
- struct ieee80211_hdr_3addr *mgmt = &resp->header;
-
- at76_dbg(DBG_RX_MGMT | DBG_PROGRESS,
- "%s: rx DeAuth bssid %s reason 0x%04x destination %s",
- priv->netdev->name, mac2str(mgmt->addr3),
- le16_to_cpu(resp->reason), mac2str(mgmt->addr1));
-
- if (priv->mac_state != MAC_AUTH && priv->mac_state != MAC_ASSOC
- && priv->mac_state != MAC_CONNECTED) {
- printk(KERN_INFO "%s: DeAuth in state %s ignored\n",
- priv->netdev->name, mac_states[priv->mac_state]);
- return;
- }
+ str = (char *)fwh + le32_to_cpu(fwh->str_offset);
+ fwe->intfw = (u8 *)fwh + le32_to_cpu(fwh->int_fw_offset);
+ fwe->intfw_size = le32_to_cpu(fwh->int_fw_len);
+ fwe->extfw = (u8 *)fwh + le32_to_cpu(fwh->ext_fw_offset);
+ fwe->extfw_size = le32_to_cpu(fwh->ext_fw_len);
- BUG_ON(!priv->curr_bss);
+ fwe->loaded = 1;
- /* Not our BSSID, ignore */
- if (compare_ether_addr(mgmt->addr3, priv->curr_bss->bssid))
- return;
+ dev_printk(KERN_DEBUG, &udev->dev,
+ "using firmware %s (version %d.%d.%d-%d)\n",
+ fwe->fwname, fwh->major, fwh->minor, fwh->patch, fwh->build);
- /* Not for our STA and not broadcast, ignore */
- if (compare_ether_addr(priv->netdev->dev_addr, mgmt->addr1)
- && !is_broadcast_ether_addr(mgmt->addr1))
- return;
+ at76_dbg(DBG_DEVSTART, "board %u, int %d:%d, ext %d:%d", board_type,
+ le32_to_cpu(fwh->int_fw_offset), le32_to_cpu(fwh->int_fw_len),
+ le32_to_cpu(fwh->ext_fw_offset), le32_to_cpu(fwh->ext_fw_len));
+ at76_dbg(DBG_DEVSTART, "firmware id %s", str);
- if (priv->mac_state == MAC_CONNECTED)
- at76_iwevent_bss_disconnect(priv->netdev);
+exit:
+ mutex_unlock(&fw_mutex);
- at76_set_mac_state(priv, MAC_JOINING);
- schedule_work(&priv->work_join);
- cancel_delayed_work(&priv->dwork_get_scan);
- cancel_delayed_work(&priv->dwork_beacon);
- cancel_delayed_work(&priv->dwork_auth);
- cancel_delayed_work(&priv->dwork_assoc);
+ if (fwe->loaded)
+ return fwe;
+ else
+ return NULL;
}
-static void at76_rx_mgmt_beacon(struct at76_priv *priv,
- struct at76_rx_buffer *buf)
+static void at76_mac80211_tx_callback(struct urb *urb)
{
- int varpar_len;
- /* beacon content */
- struct ieee80211_beacon *bdata = (struct ieee80211_beacon *)buf->packet;
- struct ieee80211_hdr_3addr *mgmt = &bdata->header;
-
- struct list_head *lptr;
- struct bss_info *match; /* entry matching addr3 with its bssid */
- int new_entry = 0;
- int len;
- struct ieee80211_info_element *ie;
- int have_ssid = 0;
- int have_rates = 0;
- int have_channel = 0;
- int keep_going = 1;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->bss_list_spinlock, flags);
- if (priv->mac_state == MAC_CONNECTED) {
- /* in state MAC_CONNECTED we use the mgmt_timer to control
- the beacon of the BSS */
- BUG_ON(!priv->curr_bss);
-
- if (!compare_ether_addr(priv->curr_bss->bssid, mgmt->addr3)) {
- /* We got our AP's beacon, defer the timeout handler.
- Kill pending work first, as schedule_delayed_work()
- won't do it. */
- cancel_delayed_work(&priv->dwork_beacon);
- schedule_delayed_work(&priv->dwork_beacon,
- BEACON_TIMEOUT);
- priv->curr_bss->rssi = buf->rssi;
- priv->beacons_received++;
- goto exit;
- }
- }
+ struct at76_priv *priv = urb->context;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
- /* look if we have this BSS already in the list */
- match = NULL;
+ at76_dbg(DBG_MAC80211, "%s()", __func__);
- if (!list_empty(&priv->bss_list)) {
- list_for_each(lptr, &priv->bss_list) {
- struct bss_info *bss_ptr =
- list_entry(lptr, struct bss_info, list);
- if (!compare_ether_addr(bss_ptr->bssid, mgmt->addr3)) {
- match = bss_ptr;
- break;
- }
- }
+ switch (urb->status) {
+ case 0:
+ /* success */
+ /* FIXME:
+ * is the frame really ACKed when tx_callback is called ? */
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ break;
+ case -ENOENT:
+ case -ECONNRESET:
+ /* fail, urb has been unlinked */
+ /* FIXME: add error message */
+ break;
+ default:
+ at76_dbg(DBG_URB, "%s - nonzero tx status received: %d",
+ __func__, urb->status);
+ break;
}
- if (!match) {
- /* BSS not in the list - append it */
- match = kzalloc(sizeof(struct bss_info), GFP_ATOMIC);
- if (!match) {
- at76_dbg(DBG_BSS_TABLE,
- "%s: cannot kmalloc new bss info (%zd byte)",
- priv->netdev->name, sizeof(struct bss_info));
- goto exit;
- }
- new_entry = 1;
- list_add_tail(&match->list, &priv->bss_list);
- }
+ memset(&info->status, 0, sizeof(info->status));
- match->capa = le16_to_cpu(bdata->capability);
- match->beacon_interval = le16_to_cpu(bdata->beacon_interval);
- match->rssi = buf->rssi;
- match->link_qual = buf->link_quality;
- match->noise_level = buf->noise_level;
- memcpy(match->bssid, mgmt->addr3, ETH_ALEN);
- at76_dbg(DBG_RX_BEACON, "%s: bssid %s", priv->netdev->name,
- mac2str(match->bssid));
-
- ie = bdata->info_element;
-
- /* length of var length beacon parameters */
- varpar_len = min_t(int, le16_to_cpu(buf->wlength) -
- sizeof(struct ieee80211_beacon),
- BEACON_MAX_DATA_LENGTH);
-
- /* This routine steps through the bdata->data array to get
- * some useful information about the access point.
- * Currently, this implementation supports receipt of: SSID,
- * supported transfer rates and channel, in any order, with some
- * tolerance for intermittent unknown codes (although this
- * functionality may not be necessary as the useful information will
- * usually arrive in consecutively, but there have been some
- * reports of some of the useful information fields arriving in a
- * different order).
- * It does not support any more IE types although MFIE_TYPE_TIM may
- * be supported (on my AP at least).
- * The bdata->data array is about 1500 bytes long but only ~36 of those
- * bytes are useful, hence the have_ssid etc optimizations. */
-
- while (keep_going &&
- ((&ie->data[ie->len] - (u8 *)bdata->info_element) <=
- varpar_len)) {
-
- switch (ie->id) {
-
- case MFIE_TYPE_SSID:
- if (have_ssid)
- break;
+ ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb);
- len = min_t(int, IW_ESSID_MAX_SIZE, ie->len);
+ priv->tx_skb = NULL;
- /* we copy only if this is a new entry,
- or the incoming SSID is not a hidden SSID. This
- will protect us from overwriting a real SSID read
- in a ProbeResponse with a hidden one from a
- following beacon. */
- if (!new_entry && at76_is_hidden_ssid(ie->data, len)) {
- have_ssid = 1;
- break;
- }
+ ieee80211_wake_queues(priv->hw);
+}
- match->ssid_len = len;
- memcpy(match->ssid, ie->data, len);
- at76_dbg(DBG_RX_BEACON, "%s: SSID - %.*s",
- priv->netdev->name, len, match->ssid);
- have_ssid = 1;
- break;
+static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+ struct at76_priv *priv = hw->priv;
+ struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ int padding, submit_len, ret;
- case MFIE_TYPE_RATES:
- if (have_rates)
- break;
+ at76_dbg(DBG_MAC80211, "%s()", __func__);
- match->rates_len =
- min_t(int, sizeof(match->rates), ie->len);
- memcpy(match->rates, ie->data, match->rates_len);
- have_rates = 1;
- at76_dbg(DBG_RX_BEACON, "%s: SUPPORTED RATES %s",
- priv->netdev->name,
- hex2str(ie->data, ie->len));
- break;
+ if (priv->tx_urb->status == -EINPROGRESS) {
+ printk(KERN_ERR "%s: %s called while tx urb is pending\n",
+ wiphy_name(priv->hw->wiphy), __func__);
+ return NETDEV_TX_BUSY;
+ }
- case MFIE_TYPE_DS_SET:
- if (have_channel)
- break;
+ ieee80211_stop_queues(hw);
- match->channel = ie->data[0];
- have_channel = 1;
- at76_dbg(DBG_RX_BEACON, "%s: CHANNEL - %d",
- priv->netdev->name, match->channel);
- break;
+ at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
- case MFIE_TYPE_CF_SET:
- case MFIE_TYPE_TIM:
- case MFIE_TYPE_IBSS_SET:
- default:
- at76_dbg(DBG_RX_BEACON, "%s: beacon IE id %d len %d %s",
- priv->netdev->name, ie->id, ie->len,
- hex2str(ie->data, ie->len));
- break;
- }
+ WARN_ON(priv->tx_skb != NULL);
- /* advance to the next informational element */
- next_ie(&ie);
+ priv->tx_skb = skb;
+ padding = at76_calc_padding(skb->len);
+ submit_len = AT76_TX_HDRLEN + skb->len + padding;
- /* Optimization: after all, the bdata->data array is
- * varpar_len bytes long, whereas we get all of the useful
- * information after only ~36 bytes, this saves us a lot of
- * time (and trouble as the remaining portion of the array
- * could be full of junk)
- * Comment this out if you want to see what other information
- * comes from the AP - although little of it may be useful */
- }
+ /* setup 'Atmel' header */
+ memset(tx_buffer, 0, sizeof(*tx_buffer));
+ tx_buffer->padding = padding;
+ tx_buffer->wlength = cpu_to_le16(skb->len);
+ tx_buffer->tx_rate = ieee80211_get_tx_rate(hw, info)->hw_value;
+ if (FIRMWARE_IS_WPA(priv->fw_version) && info->control.hw_key) {
+ tx_buffer->key_id = (info->control.hw_key->keyidx);
+ tx_buffer->cipher_type =
+ priv->keys[info->control.hw_key->keyidx].cipher;
+ tx_buffer->cipher_length =
+ priv->keys[info->control.hw_key->keyidx].keylen;
+ tx_buffer->reserved = 0;
+ } else {
+ tx_buffer->key_id = 0;
+ tx_buffer->cipher_type = 0;
+ tx_buffer->cipher_length = 0;
+ tx_buffer->reserved = 0;
+ };
+ /* memset(tx_buffer->reserved, 0, sizeof(tx_buffer->reserved)); */
+ memcpy(tx_buffer->packet, skb->data, skb->len);
- at76_dbg(DBG_RX_BEACON, "%s: Finished processing beacon data",
- priv->netdev->name);
+ at76_dbg(DBG_TX_DATA, "%s tx: wlen 0x%x pad 0x%x rate %d hdr",
+ wiphy_name(priv->hw->wiphy), le16_to_cpu(tx_buffer->wlength),
+ tx_buffer->padding, tx_buffer->tx_rate);
- match->last_rx = jiffies; /* record last rx of beacon */
+ /* send stuff */
+ at76_dbg_dump(DBG_TX_DATA_CONTENT, tx_buffer, submit_len,
+ "%s(): tx_buffer %d bytes:", __func__, submit_len);
+ usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe, tx_buffer,
+ submit_len, at76_mac80211_tx_callback, priv);
+ ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
+ if (ret) {
+ printk(KERN_ERR "%s: error in tx submit urb: %d\n",
+ wiphy_name(priv->hw->wiphy), ret);
+ if (ret == -EINVAL)
+ printk(KERN_ERR
+ "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n",
+ wiphy_name(priv->hw->wiphy), priv->tx_urb,
+ priv->tx_urb->hcpriv, priv->tx_urb->complete);
+ }
-exit:
- spin_unlock_irqrestore(&priv->bss_list_spinlock, flags);
+ return 0;
}
-/* Calculate the link level from a given rx_buffer */
-static void at76_calc_level(struct at76_priv *priv, struct at76_rx_buffer *buf,
- struct iw_quality *qual)
+static int at76_mac80211_start(struct ieee80211_hw *hw)
{
- /* just a guess for now, might be different for other chips */
- int max_rssi = 42;
+ struct at76_priv *priv = hw->priv;
+ int ret;
- qual->level = (buf->rssi * 100 / max_rssi);
- if (qual->level > 100)
- qual->level = 100;
- qual->updated |= IW_QUAL_LEVEL_UPDATED;
-}
+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-/* Calculate the link quality from a given rx_buffer */
-static void at76_calc_qual(struct at76_priv *priv, struct at76_rx_buffer *buf,
- struct iw_quality *qual)
-{
- if (at76_is_intersil(priv->board_type))
- qual->qual = buf->link_quality;
- else {
- unsigned long elapsed;
+ mutex_lock(&priv->mtx);
- /* Update qual at most once a second */
- elapsed = jiffies - priv->beacons_last_qual;
- if (elapsed < 1 * HZ)
- return;
+ ret = at76_submit_rx_urb(priv);
+ if (ret < 0) {
+ printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n",
+ wiphy_name(priv->hw->wiphy), ret);
+ goto error;
+ }
- qual->qual = qual->level * priv->beacons_received *
- msecs_to_jiffies(priv->beacon_period) / elapsed;
+ at76_startup_device(priv);
- priv->beacons_last_qual = jiffies;
- priv->beacons_received = 0;
- }
- qual->qual = (qual->qual > 100) ? 100 : qual->qual;
- qual->updated |= IW_QUAL_QUAL_UPDATED;
-}
+ at76_start_monitor(priv);
-/* Calculate the noise quality from a given rx_buffer */
-static void at76_calc_noise(struct at76_priv *priv, struct at76_rx_buffer *buf,
- struct iw_quality *qual)
-{
- qual->noise = 0;
- qual->updated |= IW_QUAL_NOISE_INVALID;
+error:
+ mutex_unlock(&priv->mtx);
+
+ return 0;
}
-static void at76_update_wstats(struct at76_priv *priv,
- struct at76_rx_buffer *buf)
+static void at76_mac80211_stop(struct ieee80211_hw *hw)
{
- struct iw_quality *qual = &priv->wstats.qual;
+ struct at76_priv *priv = hw->priv;
- if (buf->rssi && priv->mac_state == MAC_CONNECTED) {
- qual->updated = 0;
- at76_calc_level(priv, buf, qual);
- at76_calc_qual(priv, buf, qual);
- at76_calc_noise(priv, buf, qual);
- } else {
- qual->qual = 0;
- qual->level = 0;
- qual->noise = 0;
- qual->updated = IW_QUAL_ALL_INVALID;
- }
-}
+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-static void at76_rx_mgmt(struct at76_priv *priv, struct at76_rx_buffer *buf)
-{
- struct ieee80211_hdr_3addr *mgmt =
- (struct ieee80211_hdr_3addr *)buf->packet;
- u16 framectl = le16_to_cpu(mgmt->frame_ctl);
-
- /* update wstats */
- if (priv->mac_state != MAC_INIT && priv->mac_state != MAC_SCANNING) {
- /* jal: this is a dirty hack needed by Tim in ad-hoc mode */
- /* Data packets always seem to have a 0 link level, so we
- only read link quality info from management packets.
- Atmel driver actually averages the present, and previous
- values, we just present the raw value at the moment - TJS */
- if (priv->iw_mode == IW_MODE_ADHOC
- || (priv->curr_bss
- && !compare_ether_addr(mgmt->addr3,
- priv->curr_bss->bssid)))
- at76_update_wstats(priv, buf);
- }
+ mutex_lock(&priv->mtx);
- at76_dbg(DBG_RX_MGMT_CONTENT, "%s rx mgmt framectl 0x%x %s",
- priv->netdev->name, framectl,
- hex2str(mgmt, le16_to_cpu(buf->wlength)));
+ if (!priv->device_unplugged) {
+ /* We are called by "ifconfig ethX down", not because the
+ * device is not available anymore. */
+ if (at76_set_radio(priv, 0) == 1)
+ at76_wait_completion(priv, CMD_RADIO_ON);
- switch (framectl & IEEE80211_FCTL_STYPE) {
- case IEEE80211_STYPE_BEACON:
- case IEEE80211_STYPE_PROBE_RESP:
- at76_rx_mgmt_beacon(priv, buf);
- break;
+ /* We unlink rx_urb because at76_open() re-submits it.
+ * If unplugged, at76_delete_device() takes care of it. */
+ usb_kill_urb(priv->rx_urb);
+ }
- case IEEE80211_STYPE_ASSOC_RESP:
- at76_rx_mgmt_assoc(priv, buf);
- break;
+ mutex_unlock(&priv->mtx);
+}
- case IEEE80211_STYPE_DISASSOC:
- at76_rx_mgmt_disassoc(priv, buf);
- break;
+static int at76_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct at76_priv *priv = hw->priv;
+ int ret = 0;
- case IEEE80211_STYPE_AUTH:
- at76_rx_mgmt_auth(priv, buf);
- break;
+ at76_dbg(DBG_MAC80211, "%s()", __func__);
- case IEEE80211_STYPE_DEAUTH:
- at76_rx_mgmt_deauth(priv, buf);
- break;
+ mutex_lock(&priv->mtx);
+ switch (conf->type) {
+ case NL80211_IFTYPE_STATION:
+ priv->iw_mode = IW_MODE_INFRA;
+ break;
default:
- printk(KERN_DEBUG "%s: ignoring frame with framectl 0x%04x\n",
- priv->netdev->name, framectl);
+ ret = -EOPNOTSUPP;
+ goto exit;
}
- return;
+exit:
+ mutex_unlock(&priv->mtx);
+
+ return ret;
}
-/* Convert the 802.11 header into an ethernet-style header, make skb
- * ready for consumption by netif_rx() */
-static void at76_ieee80211_to_eth(struct sk_buff *skb, int iw_mode)
+static void at76_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
- struct ieee80211_hdr_3addr *i802_11_hdr;
- struct ethhdr *eth_hdr_p;
- u8 *src_addr;
- u8 *dest_addr;
+ at76_dbg(DBG_MAC80211, "%s()", __func__);
+}
- i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data;
+static int at76_join(struct at76_priv *priv)
+{
+ struct at76_req_join join;
+ int ret;
- /* That would be the ethernet header if the hardware converted
- * the frame for us. Make sure the source and the destination
- * match the 802.11 header. Which hardware does it? */
- eth_hdr_p = (struct ethhdr *)skb_pull(skb, IEEE80211_3ADDR_LEN);
+ memset(&join, 0, sizeof(struct at76_req_join));
+ memcpy(join.essid, priv->essid, priv->essid_size);
+ join.essid_size = priv->essid_size;
+ memcpy(join.bssid, priv->bssid, ETH_ALEN);
+ join.bss_type = INFRASTRUCTURE_MODE;
+ join.channel = priv->channel;
+ join.timeout = cpu_to_le16(2000);
- dest_addr = i802_11_hdr->addr1;
- if (iw_mode == IW_MODE_ADHOC)
- src_addr = i802_11_hdr->addr2;
- else
- src_addr = i802_11_hdr->addr3;
+ at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
+ ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
+ sizeof(struct at76_req_join));
- if (!compare_ether_addr(eth_hdr_p->h_source, src_addr) &&
- !compare_ether_addr(eth_hdr_p->h_dest, dest_addr))
- /* Yes, we already have an ethernet header */
- skb_reset_mac_header(skb);
- else {
- u16 len;
-
- /* Need to build an ethernet header */
- if (!memcmp(skb->data, snapsig, sizeof(snapsig))) {
- /* SNAP frame - decapsulate, keep proto */
- skb_push(skb, offsetof(struct ethhdr, h_proto) -
- sizeof(rfc1042sig));
- len = 0;
- } else {
- /* 802.3 frame, proto is length */
- len = skb->len;
- skb_push(skb, ETH_HLEN);
- }
+ if (ret < 0) {
+ printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
+ wiphy_name(priv->hw->wiphy), ret);
+ return 0;
+ }
- skb_reset_mac_header(skb);
- eth_hdr_p = eth_hdr(skb);
- /* This needs to be done in this order (eth_hdr_p->h_dest may
- * overlap src_addr) */
- memcpy(eth_hdr_p->h_source, src_addr, ETH_ALEN);
- memcpy(eth_hdr_p->h_dest, dest_addr, ETH_ALEN);
- if (len)
- eth_hdr_p->h_proto = htons(len);
+ ret = at76_wait_completion(priv, CMD_JOIN);
+ at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
+ if (ret != CMD_STATUS_COMPLETE) {
+ printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
+ wiphy_name(priv->hw->wiphy), ret);
+ return 0;
}
- skb->protocol = eth_type_trans(skb, skb->dev);
+ at76_set_tkip_bssid(priv, priv->bssid);
+ at76_set_pm_mode(priv);
+
+ return 0;
}
-/* Check for fragmented data in priv->rx_skb. If the packet was no fragment
- or it was the last of a fragment set a skb containing the whole packet
- is returned for further processing. Otherwise we get NULL and are
- done and the packet is either stored inside the fragment buffer
- or thrown away. Every returned skb starts with the ieee802_11 header
- and contains _no_ FCS at the end */
-static struct sk_buff *at76_check_for_rx_frags(struct at76_priv *priv)
+static void at76_dwork_hw_scan(struct work_struct *work)
{
- struct sk_buff *skb = priv->rx_skb;
- struct at76_rx_buffer *buf = (struct at76_rx_buffer *)skb->data;
- struct ieee80211_hdr_3addr *i802_11_hdr =
- (struct ieee80211_hdr_3addr *)buf->packet;
- /* seq_ctrl, fragment_number, sequence number of new packet */
- u16 sctl = le16_to_cpu(i802_11_hdr->seq_ctl);
- u16 fragnr = sctl & 0xf;
- u16 seqnr = sctl >> 4;
- u16 frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl);
-
- /* Length including the IEEE802.11 header, but without the trailing
- * FCS and without the Atmel Rx header */
- int length = le16_to_cpu(buf->wlength) - IEEE80211_FCS_LEN;
+ struct at76_priv *priv = container_of(work, struct at76_priv,
+ dwork_hw_scan.work);
+ int ret;
- /* where does the data payload start in skb->data ? */
- u8 *data = i802_11_hdr->payload;
+ ret = at76_get_cmd_status(priv->udev, CMD_SCAN);
+ at76_dbg(DBG_MAC80211, "%s: CMD_SCAN status 0x%02x", __func__, ret);
- /* length of payload, excl. the trailing FCS */
- int data_len = length - IEEE80211_3ADDR_LEN;
+ /* FIXME: add maximum time for scan to complete */
- int i;
- struct rx_data_buf *bptr, *optr;
- unsigned long oldest = ~0UL;
-
- at76_dbg(DBG_RX_FRAGS,
- "%s: rx data frame_ctl %04x addr2 %s seq/frag %d/%d "
- "length %d data %d: %s ...", priv->netdev->name, frame_ctl,
- mac2str(i802_11_hdr->addr2), seqnr, fragnr, length, data_len,
- hex2str(data, 32));
-
- at76_dbg(DBG_RX_FRAGS_SKB, "%s: incoming skb: head %p data %p "
- "tail %p end %p len %d", priv->netdev->name, skb->head,
- skb->data, skb_tail_pointer(skb), skb_end_pointer(skb),
- skb->len);
-
- if (data_len < 0) {
- /* make sure data starts in the buffer */
- printk(KERN_INFO "%s: data frame too short\n",
- priv->netdev->name);
- return NULL;
+ if (ret != CMD_STATUS_COMPLETE) {
+ queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
+ SCAN_POLL_INTERVAL);
+ goto exit;
}
- WARN_ON(length <= AT76_RX_HDRLEN);
- if (length <= AT76_RX_HDRLEN)
- return NULL;
+ ieee80211_scan_completed(priv->hw);
- /* remove the at76_rx_buffer header - we don't need it anymore */
- /* we need the IEEE802.11 header (for the addresses) if this packet
- is the first of a chain */
- skb_pull(skb, AT76_RX_HDRLEN);
-
- /* remove FCS at end */
- skb_trim(skb, length);
-
- at76_dbg(DBG_RX_FRAGS_SKB, "%s: trimmed skb: head %p data %p tail %p "
- "end %p len %d data %p data_len %d", priv->netdev->name,
- skb->head, skb->data, skb_tail_pointer(skb),
- skb_end_pointer(skb), skb->len, data, data_len);
-
- if (fragnr == 0 && !(frame_ctl & IEEE80211_FCTL_MOREFRAGS)) {
- /* unfragmented packet received */
- /* Use a new skb for the next receive */
- priv->rx_skb = NULL;
- at76_dbg(DBG_RX_FRAGS, "%s: unfragmented", priv->netdev->name);
- return skb;
+ if (is_valid_ether_addr(priv->bssid)) {
+ ieee80211_wake_queues(priv->hw);
+ at76_join(priv);
}
- /* look if we've got a chain for the sender address.
- afterwards optr points to first free or the oldest entry,
- or, if i < NR_RX_DATA_BUF, bptr points to the entry for the
- sender address */
- /* determining the oldest entry doesn't cope with jiffies wrapping
- but I don't care to delete a young entry at these rare moments ... */
-
- bptr = priv->rx_data;
- optr = NULL;
- for (i = 0; i < NR_RX_DATA_BUF; i++, bptr++) {
- if (!bptr->skb) {
- optr = bptr;
- oldest = 0UL;
- continue;
- }
+ ieee80211_wake_queues(priv->hw);
- if (!compare_ether_addr(i802_11_hdr->addr2, bptr->sender))
- break;
+exit:
+ return;
+}
- if (!optr) {
- optr = bptr;
- oldest = bptr->last_rx;
- } else if (bptr->last_rx < oldest)
- optr = bptr;
- }
+static int at76_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
+{
+ struct at76_priv *priv = hw->priv;
+ struct at76_req_scan scan;
+ int ret;
- if (i < NR_RX_DATA_BUF) {
-
- at76_dbg(DBG_RX_FRAGS, "%s: %d. cacheentry (seq/frag = %d/%d) "
- "matched sender addr",
- priv->netdev->name, i, bptr->seqnr, bptr->fragnr);
-
- /* bptr points to an entry for the sender address */
- if (bptr->seqnr == seqnr) {
- int left;
- /* the fragment has the current sequence number */
- if (((bptr->fragnr + 1) & 0xf) != fragnr) {
- /* wrong fragment number -> ignore it */
- /* is & 0xf necessary above ??? */
- at76_dbg(DBG_RX_FRAGS,
- "%s: frag nr mismatch: %d + 1 != %d",
- priv->netdev->name, bptr->fragnr,
- fragnr);
- return NULL;
- }
- bptr->last_rx = jiffies;
- /* the next following fragment number ->
- add the data at the end */
-
- /* for test only ??? */
- left = skb_tailroom(bptr->skb);
- if (left < data_len)
- printk(KERN_INFO
- "%s: only %d byte free (need %d)\n",
- priv->netdev->name, left, data_len);
- else
- memcpy(skb_put(bptr->skb, data_len), data,
- data_len);
-
- bptr->fragnr = fragnr;
- if (frame_ctl & IEEE80211_FCTL_MOREFRAGS)
- return NULL;
-
- /* this was the last fragment - send it */
- skb = bptr->skb;
- bptr->skb = NULL; /* free the entry */
- at76_dbg(DBG_RX_FRAGS, "%s: last frag of seq %d",
- priv->netdev->name, seqnr);
- return skb;
- }
+ at76_dbg(DBG_MAC80211, "%s():", __func__);
+ at76_dbg_dump(DBG_MAC80211, ssid, len, "ssid %zd bytes:", len);
- /* got another sequence number */
- if (fragnr == 0) {
- /* it's the start of a new chain - replace the
- old one by this */
- /* bptr->sender has the correct value already */
- at76_dbg(DBG_RX_FRAGS,
- "%s: start of new seq %d, removing old seq %d",
- priv->netdev->name, seqnr, bptr->seqnr);
- bptr->seqnr = seqnr;
- bptr->fragnr = 0;
- bptr->last_rx = jiffies;
- /* swap bptr->skb and priv->rx_skb */
- skb = bptr->skb;
- bptr->skb = priv->rx_skb;
- priv->rx_skb = skb;
- } else {
- /* it from the middle of a new chain ->
- delete the old entry and skip the new one */
- at76_dbg(DBG_RX_FRAGS,
- "%s: middle of new seq %d (%d) "
- "removing old seq %d",
- priv->netdev->name, seqnr, fragnr,
- bptr->seqnr);
- dev_kfree_skb(bptr->skb);
- bptr->skb = NULL;
- }
- return NULL;
- }
+ mutex_lock(&priv->mtx);
- /* if we didn't find a chain for the sender address, optr
- points either to the first free or the oldest entry */
+ ieee80211_stop_queues(hw);
- if (fragnr != 0) {
- /* this is not the begin of a fragment chain ... */
- at76_dbg(DBG_RX_FRAGS,
- "%s: no chain for non-first fragment (%d)",
- priv->netdev->name, fragnr);
- return NULL;
+ memset(&scan, 0, sizeof(struct at76_req_scan));
+ memset(scan.bssid, 0xFF, ETH_ALEN);
+ scan.scan_type = SCAN_TYPE_ACTIVE;
+ if (priv->essid_size > 0) {
+ memcpy(scan.essid, ssid, len);
+ scan.essid_size = len;
}
+ scan.min_channel_time = cpu_to_le16(priv->scan_min_time);
+ scan.max_channel_time = cpu_to_le16(priv->scan_max_time);
+ scan.probe_delay = cpu_to_le16(priv->scan_min_time * 1000);
+ scan.international_scan = 0;
- BUG_ON(!optr);
- if (optr->skb) {
- /* swap the skb's */
- skb = optr->skb;
- optr->skb = priv->rx_skb;
- priv->rx_skb = skb;
+ at76_dbg(DBG_MAC80211, "%s: sending CMD_SCAN", __func__);
+ ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
- at76_dbg(DBG_RX_FRAGS,
- "%s: free old contents: sender %s seq/frag %d/%d",
- priv->netdev->name, mac2str(optr->sender),
- optr->seqnr, optr->fragnr);
+ if (ret < 0) {
+ err("CMD_SCAN failed: %d", ret);
+ goto exit;
+ }
- } else {
- /* take the skb from priv->rx_skb */
- optr->skb = priv->rx_skb;
- /* let at76_submit_rx_urb() allocate a new skb */
- priv->rx_skb = NULL;
+ queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
+ SCAN_POLL_INTERVAL);
- at76_dbg(DBG_RX_FRAGS, "%s: use a free entry",
- priv->netdev->name);
- }
- memcpy(optr->sender, i802_11_hdr->addr2, ETH_ALEN);
- optr->seqnr = seqnr;
- optr->fragnr = 0;
- optr->last_rx = jiffies;
+exit:
+ mutex_unlock(&priv->mtx);
- return NULL;
+ return 0;
}
-/* Rx interrupt: we expect the complete data buffer in priv->rx_skb */
-static void at76_rx_data(struct at76_priv *priv)
+static int at76_config(struct ieee80211_hw *hw, u32 changed)
{
- struct net_device *netdev = priv->netdev;
- struct net_device_stats *stats = &priv->stats;
- struct sk_buff *skb = priv->rx_skb;
- struct at76_rx_buffer *buf = (struct at76_rx_buffer *)skb->data;
- struct ieee80211_hdr_3addr *i802_11_hdr;
- int length = le16_to_cpu(buf->wlength);
-
- at76_dbg(DBG_RX_DATA, "%s received data packet: %s", netdev->name,
- hex2str(skb->data, AT76_RX_HDRLEN));
+ struct at76_priv *priv = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
- at76_dbg(DBG_RX_DATA_CONTENT, "rx packet: %s",
- hex2str(skb->data + AT76_RX_HDRLEN, length));
+ at76_dbg(DBG_MAC80211, "%s(): channel %d radio %d",
+ __func__, conf->channel->hw_value, conf->radio_enabled);
+ at76_dbg_dump(DBG_MAC80211, priv->essid, priv->essid_size, "ssid:");
+ at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:");
- skb = at76_check_for_rx_frags(priv);
- if (!skb)
- return;
-
- /* Atmel header and the FCS are already removed */
- i802_11_hdr = (struct ieee80211_hdr_3addr *)skb->data;
-
- skb->dev = netdev;
- skb->ip_summed = CHECKSUM_NONE; /* TODO: should check CRC */
+ mutex_lock(&priv->mtx);
- if (is_broadcast_ether_addr(i802_11_hdr->addr1)) {
- if (!compare_ether_addr(i802_11_hdr->addr1, netdev->broadcast))
- skb->pkt_type = PACKET_BROADCAST;
- else
- skb->pkt_type = PACKET_MULTICAST;
- } else if (compare_ether_addr(i802_11_hdr->addr1, netdev->dev_addr))
- skb->pkt_type = PACKET_OTHERHOST;
+ priv->channel = conf->channel->hw_value;
- at76_ieee80211_to_eth(skb, priv->iw_mode);
+ if (is_valid_ether_addr(priv->bssid)) {
+ at76_join(priv);
+ ieee80211_wake_queues(priv->hw);
+ } else {
+ ieee80211_stop_queues(priv->hw);
+ at76_start_monitor(priv);
+ };
- netdev->last_rx = jiffies;
- netif_rx(skb);
- stats->rx_packets++;
- stats->rx_bytes += length;
+ mutex_unlock(&priv->mtx);
- return;
+ return 0;
}
-static void at76_rx_monitor_mode(struct at76_priv *priv)
+static int at76_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
{
- struct at76_rx_radiotap *rt;
- u8 *payload;
- int skblen;
- struct net_device *netdev = priv->netdev;
- struct at76_rx_buffer *buf =
- (struct at76_rx_buffer *)priv->rx_skb->data;
- /* length including the IEEE802.11 header and the trailing FCS,
- but not at76_rx_buffer */
- int length = le16_to_cpu(buf->wlength);
- struct sk_buff *skb = priv->rx_skb;
- struct net_device_stats *stats = &priv->stats;
+ struct at76_priv *priv = hw->priv;
- if (length < IEEE80211_FCS_LEN) {
- /* buffer contains no data */
- at76_dbg(DBG_MONITOR_MODE,
- "%s: MONITOR MODE: rx skb without data",
- priv->netdev->name);
- return;
- }
+ at76_dbg_dump(DBG_MAC80211, conf->bssid, ETH_ALEN, "bssid:");
- skblen = sizeof(struct at76_rx_radiotap) + length;
+ mutex_lock(&priv->mtx);
- skb = dev_alloc_skb(skblen);
- if (!skb) {
- printk(KERN_ERR "%s: MONITOR MODE: dev_alloc_skb for radiotap "
- "header returned NULL\n", priv->netdev->name);
- return;
- }
+ memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+// memcpy(priv->essid, conf->ssid, conf->ssid_len);
+// priv->essid_size = conf->ssid_len;
- skb_put(skb, skblen);
-
- rt = (struct at76_rx_radiotap *)skb->data;
- payload = skb->data + sizeof(struct at76_rx_radiotap);
-
- rt->rt_hdr.it_version = 0;
- rt->rt_hdr.it_pad = 0;
- rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct at76_rx_radiotap));
- rt->rt_hdr.it_present = cpu_to_le32(AT76_RX_RADIOTAP_PRESENT);
-
- rt->rt_tsft = cpu_to_le64(le32_to_cpu(buf->rx_time));
- rt->rt_rate = hw_rates[buf->rx_rate] & (~0x80);
- rt->rt_signal = buf->rssi;
- rt->rt_noise = buf->noise_level;
- rt->rt_flags = IEEE80211_RADIOTAP_F_FCS;
- if (buf->fragmentation)
- rt->rt_flags |= IEEE80211_RADIOTAP_F_FRAG;
-
- memcpy(payload, buf->packet, length);
- skb->dev = netdev;
- skb->ip_summed = CHECKSUM_NONE;
- skb_reset_mac_header(skb);
- skb->pkt_type = PACKET_OTHERHOST;
- skb->protocol = htons(ETH_P_802_2);
-
- netdev->last_rx = jiffies;
- netif_rx(skb);
- stats->rx_packets++;
- stats->rx_bytes += length;
+ if (is_valid_ether_addr(priv->bssid)) {
+ /* mac80211 is joining a bss */
+ ieee80211_wake_queues(priv->hw);
+ at76_join(priv);
+ } else
+ ieee80211_stop_queues(priv->hw);
+
+ mutex_unlock(&priv->mtx);
+
+ return 0;
}
-/* Check if we spy on the sender address in buf and update stats */
-static void at76_iwspy_update(struct at76_priv *priv,
- struct at76_rx_buffer *buf)
+/* must be atomic */
+static void at76_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags, int mc_count,
+ struct dev_addr_list *mc_list)
{
- struct ieee80211_hdr_3addr *hdr =
- (struct ieee80211_hdr_3addr *)buf->packet;
- struct iw_quality qual;
+ struct at76_priv *priv = hw->priv;
+ int flags;
- /* We can only set the level here */
- qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_NOISE_INVALID;
- qual.level = 0;
- qual.noise = 0;
- at76_calc_level(priv, buf, &qual);
+ at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x "
+ "total_flags=0x%08x mc_count=%d",
+ __func__, changed_flags, *total_flags, mc_count);
- spin_lock_bh(&priv->spy_spinlock);
+ flags = changed_flags & AT76_SUPPORTED_FILTERS;
+ *total_flags = AT76_SUPPORTED_FILTERS;
- if (priv->spy_data.spy_number > 0)
- wireless_spy_update(priv->netdev, hdr->addr2, &qual);
+ /* FIXME: access to priv->promisc should be protected with
+ * priv->mtx, but it's impossible because this function needs to be
+ * atomic */
- spin_unlock_bh(&priv->spy_spinlock);
+ if (flags && !priv->promisc) {
+ /* mac80211 wants us to enable promiscuous mode */
+ priv->promisc = 1;
+ } else if (!flags && priv->promisc) {
+ /* we need to disable promiscuous mode */
+ priv->promisc = 0;
+ } else
+ return;
+
+ queue_work(hw->workqueue, &priv->work_set_promisc);
}
-static void at76_rx_tasklet(unsigned long param)
+static int at76_set_key_oldfw(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key)
{
- struct urb *urb = (struct urb *)param;
- struct at76_priv *priv = urb->context;
- struct net_device *netdev = priv->netdev;
- struct at76_rx_buffer *buf;
- struct ieee80211_hdr_3addr *i802_11_hdr;
- u16 frame_ctl;
+ struct at76_priv *priv = hw->priv;
- if (priv->device_unplugged) {
- at76_dbg(DBG_DEVSTART, "device unplugged");
- if (urb)
- at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
- return;
- }
-
- if (!priv->rx_skb || !netdev || !priv->rx_skb->data)
- return;
+ int i;
- buf = (struct at76_rx_buffer *)priv->rx_skb->data;
+ at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d "
+ "key->keylen %d",
+ __func__, cmd, key->alg, key->keyidx, key->keylen);
- i802_11_hdr = (struct ieee80211_hdr_3addr *)buf->packet;
+ if (key->alg != ALG_WEP)
+ return -EOPNOTSUPP;
- frame_ctl = le16_to_cpu(i802_11_hdr->frame_ctl);
+ key->hw_key_idx = key->keyidx;
- if (urb->status != 0) {
- if (urb->status != -ENOENT && urb->status != -ECONNRESET)
- at76_dbg(DBG_URB,
- "%s %s: - nonzero Rx bulk status received: %d",
- __func__, netdev->name, urb->status);
- return;
- }
+ mutex_lock(&priv->mtx);
- at76_dbg(DBG_RX_ATMEL_HDR,
- "%s: rx frame: rate %d rssi %d noise %d link %d %s",
- priv->netdev->name, buf->rx_rate, buf->rssi, buf->noise_level,
- buf->link_quality, hex2str(i802_11_hdr, 48));
- if (priv->iw_mode == IW_MODE_MONITOR) {
- at76_rx_monitor_mode(priv);
- goto exit;
- }
+ switch (cmd) {
+ case SET_KEY:
+ memcpy(priv->wep_keys[key->keyidx], key->key, key->keylen);
+ priv->wep_keys_len[key->keyidx] = key->keylen;
- /* there is a new bssid around, accept it: */
- if (buf->newbss && priv->iw_mode == IW_MODE_ADHOC) {
- at76_dbg(DBG_PROGRESS, "%s: rx newbss", netdev->name);
- schedule_work(&priv->work_new_bss);
- }
+ /* FIXME: find out how to do this properly */
+ priv->wep_key_id = key->keyidx;
- switch (frame_ctl & IEEE80211_FCTL_FTYPE) {
- case IEEE80211_FTYPE_DATA:
- at76_rx_data(priv);
break;
+ case DISABLE_KEY:
+ default:
+ priv->wep_keys_len[key->keyidx] = 0;
+ break;
+ }
- case IEEE80211_FTYPE_MGMT:
- /* jal: TODO: find out if we can update iwspy also on
- other frames than management (might depend on the
- radio chip / firmware version !) */
+ priv->wep_enabled = 0;
- at76_iwspy_update(priv, buf);
+ for (i = 0; i < WEP_KEYS; i++) {
+ if (priv->wep_keys_len[i] != 0)
+ priv->wep_enabled = 1;
+ }
- at76_rx_mgmt(priv, buf);
- break;
+ at76_startup_device(priv);
- case IEEE80211_FTYPE_CTL:
- at76_dbg(DBG_RX_CTRL, "%s: ignored ctrl frame: %04x",
- priv->netdev->name, frame_ctl);
- break;
+ mutex_unlock(&priv->mtx);
- default:
- printk(KERN_DEBUG "%s: ignoring frame with framectl 0x%04x\n",
- priv->netdev->name, frame_ctl);
- }
-exit:
- at76_submit_rx_urb(priv);
+ return 0;
}
-/* Load firmware into kernel memory and parse it */
-static struct fwentry *at76_load_firmware(struct usb_device *udev,
- enum board_type board_type)
+static int at76_set_key_newfw(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key)
{
- int ret;
- char *str;
- struct at76_fw_header *fwh;
- struct fwentry *fwe = &firmwares[board_type];
+ struct at76_priv *priv = hw->priv;
+ int ret = -EOPNOTSUPP;
- mutex_lock(&fw_mutex);
+ at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d "
+ "key->keylen %d",
+ __func__, cmd, key->alg, key->keyidx, key->keylen);
- if (fwe->loaded) {
- at76_dbg(DBG_FW, "re-using previously loaded fw");
- goto exit;
- }
+ mutex_lock(&priv->mtx);
- at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
- ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
- if (ret < 0) {
- dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
- fwe->fwname);
- dev_printk(KERN_ERR, &udev->dev,
- "you may need to download the firmware from "
- "http://developer.berlios.de/projects/at76c503a/");
- goto exit;
- }
+ priv->mib_buf.type = MIB_MAC_ENCRYPTION;
- at76_dbg(DBG_FW, "got it.");
- fwh = (struct at76_fw_header *)(fwe->fw->data);
+ if (cmd == DISABLE_KEY) {
+ priv->mib_buf.size = CIPHER_KEY_LEN;
+ priv->mib_buf.index = offsetof(struct mib_mac_encryption,
+ cipher_default_keyvalue[key->keyidx]);
+ memset(priv->mib_buf.data.data, 0, CIPHER_KEY_LEN);
+ if (at76_set_mib(priv, &priv->mib_buf) != CMD_STATUS_COMPLETE)
+ ret = -EOPNOTSUPP; /* -EIO would be probably better */
+ else {
- if (fwe->fw->size <= sizeof(*fwh)) {
- dev_printk(KERN_ERR, &udev->dev,
- "firmware is too short (0x%zx)\n", fwe->fw->size);
- goto exit;
- }
+ priv->keys[key->keyidx].cipher = CIPHER_NONE;
+ priv->keys[key->keyidx].keylen = 0;
+ };
+ if (priv->default_group_key == key->keyidx)
+ priv->default_group_key = 0xff;
- /* CRC currently not checked */
- fwe->board_type = le32_to_cpu(fwh->board_type);
- if (fwe->board_type != board_type) {
- dev_printk(KERN_ERR, &udev->dev,
- "board type mismatch, requested %u, got %u\n",
- board_type, fwe->board_type);
+ if (priv->default_pairwise_key == key->keyidx)
+ priv->default_pairwise_key = 0xff;
+ /* If default pairwise key is removed, fall back to
+ * group key? */
+ ret = 0;
goto exit;
- }
+ };
- fwe->fw_version.major = fwh->major;
- fwe->fw_version.minor = fwh->minor;
- fwe->fw_version.patch = fwh->patch;
- fwe->fw_version.build = fwh->build;
+ if (cmd == SET_KEY) {
+ /* store key into MIB */
+ priv->mib_buf.size = CIPHER_KEY_LEN;
+ priv->mib_buf.index = offsetof(struct mib_mac_encryption,
+ cipher_default_keyvalue[key->keyidx]);
+ memset(priv->mib_buf.data.data, 0, CIPHER_KEY_LEN);
+ memcpy(priv->mib_buf.data.data, key->key, key->keylen);
+
+ switch (key->alg) {
+ case ALG_WEP:
+ if (key->keylen == 5) {
+ priv->keys[key->keyidx].cipher =
+ CIPHER_WEP64;
+ priv->keys[key->keyidx].keylen = 8;
+ } else if (key->keylen == 13) {
+ priv->keys[key->keyidx].cipher =
+ CIPHER_WEP128;
+ /* Firmware needs this */
+ priv->keys[key->keyidx].keylen = 8;
+ } else {
+ ret = -EOPNOTSUPP;
+ goto exit;
+ };
+ break;
+ case ALG_TKIP:
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ priv->keys[key->keyidx].cipher = CIPHER_TKIP;
+ priv->keys[key->keyidx].keylen = 12;
+ break;
- str = (char *)fwh + le32_to_cpu(fwh->str_offset);
- fwe->intfw = (u8 *)fwh + le32_to_cpu(fwh->int_fw_offset);
- fwe->intfw_size = le32_to_cpu(fwh->int_fw_len);
- fwe->extfw = (u8 *)fwh + le32_to_cpu(fwh->ext_fw_offset);
- fwe->extfw_size = le32_to_cpu(fwh->ext_fw_len);
+ case ALG_CCMP:
+ if (!at76_is_505a(priv->board_type)) {
+ ret = -EOPNOTSUPP;
+ goto exit;
+ };
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ priv->keys[key->keyidx].cipher = CIPHER_CCMP;
+ priv->keys[key->keyidx].keylen = 16;
+ break;
- fwe->loaded = 1;
+ default:
+ ret = -EOPNOTSUPP;
+ goto exit;
+ };
+
+ priv->mib_buf.data.data[38] = priv->keys[key->keyidx].cipher;
+ priv->mib_buf.data.data[39] = 1; /* Taken from atmelwlandriver,
+ not documented */
+
+ if (is_valid_ether_addr(address))
+ /* Pairwise key */
+ priv->mib_buf.data.data[39] |= (KEY_PAIRWISE | KEY_TX);
+ else if (is_broadcast_ether_addr(address))
+ /* Group key */
+ priv->mib_buf.data.data[39] |= (KEY_TX);
+ else /* Key used only for transmission ??? */
+ priv->mib_buf.data.data[39] |= (KEY_TX);
+
+ if (at76_set_mib(priv, &priv->mib_buf) !=
+ CMD_STATUS_COMPLETE) {
+ ret = -EOPNOTSUPP; /* -EIO would be probably better */
+ goto exit;
+ };
- dev_printk(KERN_DEBUG, &udev->dev,
- "using firmware %s (version %d.%d.%d-%d)\n",
- fwe->fwname, fwh->major, fwh->minor, fwh->patch, fwh->build);
+ if ((key->alg == ALG_TKIP) || (key->alg == ALG_CCMP))
+ at76_reset_rsc(priv);
- at76_dbg(DBG_DEVSTART, "board %u, int %d:%d, ext %d:%d", board_type,
- le32_to_cpu(fwh->int_fw_offset), le32_to_cpu(fwh->int_fw_len),
- le32_to_cpu(fwh->ext_fw_offset), le32_to_cpu(fwh->ext_fw_len));
- at76_dbg(DBG_DEVSTART, "firmware id %s", str);
+ key->hw_key_idx = key->keyidx;
+
+ /* Set up default keys */
+ if (is_broadcast_ether_addr(address))
+ priv->default_group_key = key->keyidx;
+ if (is_valid_ether_addr(address))
+ priv->default_pairwise_key = key->keyidx;
+ /* Set up encryption MIBs */
+
+ /* first block of settings */
+ priv->mib_buf.size = 3;
+ priv->mib_buf.index = offsetof(struct mib_mac_encryption,
+ privacy_invoked);
+ priv->mib_buf.data.data[0] = 1; /* privacy_invoked */
+ priv->mib_buf.data.data[1] = priv->default_pairwise_key;
+ priv->mib_buf.data.data[2] = priv->default_group_key;
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret != CMD_STATUS_COMPLETE)
+ goto exit;
+
+ /* second block of settings */
+ priv->mib_buf.size = 3;
+ priv->mib_buf.index = offsetof(struct mib_mac_encryption,
+ exclude_unencrypted);
+ priv->mib_buf.data.data[0] = 1; /* exclude_unencrypted */
+ priv->mib_buf.data.data[1] = 0; /* wep_encryption_type */
+ priv->mib_buf.data.data[2] = 0; /* ckip_key_permutation */
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+ if (ret != CMD_STATUS_COMPLETE)
+ goto exit;
+ ret = 0;
+ };
exit:
- mutex_unlock(&fw_mutex);
+ at76_dump_mib_mac_encryption(priv);
+ mutex_unlock(&priv->mtx);
+ return ret;
+}
- if (fwe->loaded)
- return fwe;
+static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key)
+{
+ struct at76_priv *priv = hw->priv;
+
+ at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d "
+ "key->keylen %d",
+ __func__, cmd, key->alg, key->keyidx, key->keylen);
+
+ if (FIRMWARE_IS_WPA(priv->fw_version))
+ return at76_set_key_newfw(hw, cmd, local_address, address, key);
else
- return NULL;
+ return at76_set_key_oldfw(hw, cmd, local_address, address, key);
+
}
+static const struct ieee80211_ops at76_ops = {
+ .tx = at76_mac80211_tx,
+ .add_interface = at76_add_interface,
+ .remove_interface = at76_remove_interface,
+ .config = at76_config,
+ .config_interface = at76_config_interface,
+ .configure_filter = at76_configure_filter,
+ .start = at76_mac80211_start,
+ .stop = at76_mac80211_stop,
+ .hw_scan = at76_hw_scan,
+ .set_key = at76_set_key,
+};
+
/* Allocate network device and initialize private data */
static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
{
- struct net_device *netdev;
+ struct ieee80211_hw *hw;
struct at76_priv *priv;
- int i;
- /* allocate memory for our device state and initialize it */
- netdev = alloc_etherdev(sizeof(struct at76_priv));
- if (!netdev) {
- dev_printk(KERN_ERR, &udev->dev, "out of memory\n");
+ hw = ieee80211_alloc_hw(sizeof(struct at76_priv), &at76_ops);
+ if (!hw) {
+ printk(KERN_ERR DRIVER_NAME ": could not register"
+ " ieee80211_hw\n");
return NULL;
}
- priv = netdev_priv(netdev);
+ priv = hw->priv;
+ priv->hw = hw;
priv->udev = udev;
- priv->netdev = netdev;
mutex_init(&priv->mtx);
- INIT_WORK(&priv->work_assoc_done, at76_work_assoc_done);
- INIT_WORK(&priv->work_join, at76_work_join);
- INIT_WORK(&priv->work_new_bss, at76_work_new_bss);
- INIT_WORK(&priv->work_start_scan, at76_work_start_scan);
INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
- INIT_DELAYED_WORK(&priv->dwork_restart, at76_dwork_restart);
- INIT_DELAYED_WORK(&priv->dwork_get_scan, at76_dwork_get_scan);
- INIT_DELAYED_WORK(&priv->dwork_beacon, at76_dwork_beacon);
- INIT_DELAYED_WORK(&priv->dwork_auth, at76_dwork_auth);
- INIT_DELAYED_WORK(&priv->dwork_assoc, at76_dwork_assoc);
-
- spin_lock_init(&priv->mgmt_spinlock);
- priv->next_mgmt_bulk = NULL;
- priv->mac_state = MAC_INIT;
-
- /* initialize empty BSS list */
- priv->curr_bss = NULL;
- INIT_LIST_HEAD(&priv->bss_list);
- spin_lock_init(&priv->bss_list_spinlock);
-
- init_timer(&priv->bss_list_timer);
- priv->bss_list_timer.data = (unsigned long)priv;
- priv->bss_list_timer.function = at76_bss_list_timeout;
-
- spin_lock_init(&priv->spy_spinlock);
-
- /* mark all rx data entries as unused */
- for (i = 0; i < NR_RX_DATA_BUF; i++)
- priv->rx_data[i].skb = NULL;
+ INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan);
priv->rx_tasklet.func = at76_rx_tasklet;
priv->rx_tasklet.data = 0;
@@ -5183,6 +2371,9 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
priv->pm_mode = AT76_PM_OFF;
priv->pm_period = 0;
+ /* unit us */
+ priv->hw->channel_change_time = 100000;
+
return priv;
}
@@ -5245,11 +2436,42 @@ static int at76_alloc_urbs(struct at76_priv *priv,
return 0;
}
+static struct ieee80211_rate at76_rates[] = {
+ { .bitrate = 10, .hw_value = TX_RATE_1MBIT, },
+ { .bitrate = 20, .hw_value = TX_RATE_2MBIT, },
+ { .bitrate = 55, .hw_value = TX_RATE_5_5MBIT, },
+ { .bitrate = 110, .hw_value = TX_RATE_11MBIT, },
+};
+
+static struct ieee80211_channel at76_channels[] = {
+ { .center_freq = 2412, .hw_value = 1 },
+ { .center_freq = 2417, .hw_value = 2 },
+ { .center_freq = 2422, .hw_value = 3 },
+ { .center_freq = 2427, .hw_value = 4 },
+ { .center_freq = 2432, .hw_value = 5 },
+ { .center_freq = 2437, .hw_value = 6 },
+ { .center_freq = 2442, .hw_value = 7 },
+ { .center_freq = 2447, .hw_value = 8 },
+ { .center_freq = 2452, .hw_value = 9 },
+ { .center_freq = 2457, .hw_value = 10 },
+ { .center_freq = 2462, .hw_value = 11 },
+ { .center_freq = 2467, .hw_value = 12 },
+ { .center_freq = 2472, .hw_value = 13 },
+ { .center_freq = 2484, .hw_value = 14 }
+};
+
+static struct ieee80211_supported_band at76_supported_band = {
+ .channels = at76_channels,
+ .n_channels = ARRAY_SIZE(at76_channels),
+ .bitrates = at76_rates,
+ .n_bitrates = ARRAY_SIZE(at76_rates),
+};
+
/* Register network device and initialize the hardware */
static int at76_init_new_device(struct at76_priv *priv,
struct usb_interface *interface)
{
- struct net_device *netdev = priv->netdev;
+ struct device *dev = &interface->dev;
int ret;
/* set up the endpoint information */
@@ -5265,14 +2487,11 @@ static int at76_init_new_device(struct at76_priv *priv,
/* MAC address */
ret = at76_get_hw_config(priv);
if (ret < 0) {
- dev_printk(KERN_ERR, &interface->dev,
- "cannot get MAC address\n");
+ dev_err(dev, "cannot get MAC address\n");
goto exit;
}
priv->domain = at76_get_reg_domain(priv->regulatory_domain);
- /* init. netdev->dev_addr */
- memcpy(netdev->dev_addr, priv->mac_addr, ETH_ALEN);
priv->channel = DEF_CHANNEL;
priv->iw_mode = IW_MODE_INFRA;
@@ -5282,47 +2501,54 @@ static int at76_init_new_device(struct at76_priv *priv,
priv->txrate = TX_RATE_AUTO;
priv->preamble_type = PREAMBLE_TYPE_LONG;
priv->beacon_period = 100;
- priv->beacons_last_qual = jiffies;
priv->auth_mode = WLAN_AUTH_OPEN;
priv->scan_min_time = DEF_SCAN_MIN_TIME;
priv->scan_max_time = DEF_SCAN_MAX_TIME;
priv->scan_mode = SCAN_TYPE_ACTIVE;
+ priv->default_pairwise_key = 0xff;
+ priv->default_group_key = 0xff;
+
+ /* mac80211 initialisation */
+ priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band;
- netdev->flags &= ~IFF_MULTICAST; /* not yet or never */
- netdev->open = at76_open;
- netdev->stop = at76_stop;
- netdev->get_stats = at76_get_stats;
- netdev->ethtool_ops = &at76_ethtool_ops;
-
- /* Add pointers to enable iwspy support. */
- priv->wireless_data.spy_data = &priv->spy_data;
- netdev->wireless_data = &priv->wireless_data;
-
- netdev->hard_start_xmit = at76_tx;
- netdev->tx_timeout = at76_tx_timeout;
- netdev->watchdog_timeo = 2 * HZ;
- netdev->wireless_handlers = &at76_handler_def;
- netdev->set_multicast_list = at76_set_multicast;
- netdev->set_mac_address = at76_set_mac_address;
- dev_alloc_name(netdev, "wlan%d");
-
- ret = register_netdev(priv->netdev);
+ if (FIRMWARE_IS_WPA(priv->fw_version) &&
+ (at76_is_503rfmd(priv->board_type) ||
+ at76_is_505(priv->board_type)))
+ priv->hw->flags = IEEE80211_HW_SIGNAL_UNSPEC;
+ else
+ priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_UNSPEC;
+
+ priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+ SET_IEEE80211_DEV(priv->hw, &interface->dev);
+ SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+
+ ret = ieee80211_register_hw(priv->hw);
if (ret) {
- dev_printk(KERN_ERR, &interface->dev,
- "cannot register netdevice (status %d)!\n", ret);
+ dev_err(dev, "cannot register mac80211 hw (status %d)!\n", ret);
goto exit;
}
- priv->netdev_registered = 1;
- printk(KERN_INFO "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n",
- netdev->name, interface->dev.bus_id, mac2str(priv->mac_addr),
- priv->fw_version.major, priv->fw_version.minor,
- priv->fw_version.patch, priv->fw_version.build);
- printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n", netdev->name,
- priv->regulatory_domain, priv->domain->name);
+ priv->mac80211_registered = 1;
- /* we let this timer run the whole time this driver instance lives */
- mod_timer(&priv->bss_list_timer, jiffies + BSS_LIST_TIMEOUT);
+ dev_info(dev, "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n",
+ wiphy_name(priv->hw->wiphy),
+ dev_name(&interface->dev), mac2str(priv->mac_addr),
+ priv->fw_version.major, priv->fw_version.minor,
+ priv->fw_version.patch, priv->fw_version.build);
+ dev_info(dev, "%s: regulatory domain 0x%02x: %s\n",
+ wiphy_name(priv->hw->wiphy),
+ priv->regulatory_domain, priv->domain->name);
+ dev_info(dev, "%s: WPA support: ", wiphy_name(priv->hw->wiphy));
+ if (!FIRMWARE_IS_WPA(priv->fw_version))
+ printk("none\n");
+ else {
+ if (!at76_is_505a(priv->board_type))
+ printk("TKIP\n");
+ else
+ printk("TKIP, AES/CCMP\n");
+ };
exit:
return ret;
@@ -5330,15 +2556,13 @@ exit:
static void at76_delete_device(struct at76_priv *priv)
{
- int i;
-
at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__);
/* The device is gone, don't bother turning it off */
priv->device_unplugged = 1;
- if (priv->netdev_registered)
- unregister_netdev(priv->netdev);
+ if (priv->mac80211_registered)
+ ieee80211_unregister_hw(priv->hw);
/* assuming we used keventd, it must quiesce too */
flush_scheduled_work();
@@ -5359,25 +2583,11 @@ static void at76_delete_device(struct at76_priv *priv)
if (priv->rx_skb)
kfree_skb(priv->rx_skb);
- at76_free_bss_list(priv);
- del_timer_sync(&priv->bss_list_timer);
- cancel_delayed_work(&priv->dwork_get_scan);
- cancel_delayed_work(&priv->dwork_beacon);
- cancel_delayed_work(&priv->dwork_auth);
- cancel_delayed_work(&priv->dwork_assoc);
-
- if (priv->mac_state == MAC_CONNECTED)
- at76_iwevent_bss_disconnect(priv->netdev);
-
- for (i = 0; i < NR_RX_DATA_BUF; i++)
- if (priv->rx_data[i].skb) {
- dev_kfree_skb(priv->rx_data[i].skb);
- priv->rx_data[i].skb = NULL;
- }
usb_put_dev(priv->udev);
- at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/netdev", __func__);
- free_netdev(priv->netdev); /* priv is in netdev */
+ at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/ieee80211_hw",
+ __func__);
+ ieee80211_free_hw(priv->hw);
at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__);
}
@@ -5411,8 +2621,8 @@ static int at76_probe(struct usb_interface *interface,
we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */
if (op_mode == OPMODE_HW_CONFIG_MODE) {
- dev_printk(KERN_ERR, &interface->dev,
- "cannot handle a device in HW_CONFIG_MODE\n");
+ dev_err(&interface->dev,
+ "cannot handle a device in HW_CONFIG_MODE\n");
ret = -EBUSY;
goto error;
}
@@ -5420,13 +2630,12 @@ static int at76_probe(struct usb_interface *interface,
if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH
&& op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
/* download internal firmware part */
- dev_printk(KERN_DEBUG, &interface->dev,
- "downloading internal firmware\n");
+ dev_dbg(&interface->dev, "downloading internal firmware\n");
ret = at76_load_internal_fw(udev, fwe);
if (ret < 0) {
- dev_printk(KERN_ERR, &interface->dev,
- "error %d downloading internal firmware\n",
- ret);
+ dev_err(&interface->dev,
+ "error %d downloading internal firmware\n",
+ ret);
goto error;
}
usb_put_dev(udev);
@@ -5451,8 +2660,7 @@ static int at76_probe(struct usb_interface *interface,
need_ext_fw = 1;
if (need_ext_fw) {
- dev_printk(KERN_DEBUG, &interface->dev,
- "downloading external firmware\n");
+ dev_dbg(&interface->dev, "downloading external firmware\n");
ret = at76_load_external_fw(udev, fwe);
if (ret)
@@ -5461,8 +2669,8 @@ static int at76_probe(struct usb_interface *interface,
/* Re-check firmware version */
ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
if (ret < 0) {
- dev_printk(KERN_ERR, &interface->dev,
- "error %d getting firmware version\n", ret);
+ dev_err(&interface->dev,
+ "error %d getting firmware version\n", ret);
goto error;
}
}
@@ -5473,7 +2681,6 @@ static int at76_probe(struct usb_interface *interface,
goto error;
}
- SET_NETDEV_DEV(priv->netdev, &interface->dev);
usb_set_intfdata(interface, priv);
memcpy(&priv->fw_version, &fwv, sizeof(struct mib_fw_version));
@@ -5501,7 +2708,7 @@ static void at76_disconnect(struct usb_interface *interface)
if (!priv)
return;
- printk(KERN_INFO "%s: disconnecting\n", priv->netdev->name);
+ printk(KERN_INFO "%s: disconnecting\n", wiphy_name(priv->hw->wiphy));
at76_delete_device(priv);
dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
}
@@ -5557,5 +2764,8 @@ MODULE_AUTHOR("Alex <alex@foogod.com>");
MODULE_AUTHOR("Nick Jones");
MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
+MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
+MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>");
+MODULE_AUTHOR("Milan Plzik <milan.plzik@gmail.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/at76_usb/at76_usb.h b/drivers/staging/at76_usb/at76_usb.h
index b20be9da1fa1..8bb352f16d45 100644
--- a/drivers/staging/at76_usb/at76_usb.h
+++ b/drivers/staging/at76_usb/at76_usb.h
@@ -34,23 +34,6 @@ enum board_type {
BOARD_505AMX = 8
};
-/* our private ioctl's */
-/* preamble length (0 - long, 1 - short, 2 - auto) */
-#define AT76_SET_SHORT_PREAMBLE (SIOCIWFIRSTPRIV + 0)
-#define AT76_GET_SHORT_PREAMBLE (SIOCIWFIRSTPRIV + 1)
-/* which debug channels are enabled */
-#define AT76_SET_DEBUG (SIOCIWFIRSTPRIV + 2)
-#define AT76_GET_DEBUG (SIOCIWFIRSTPRIV + 3)
-/* power save mode (incl. the Atmel proprietary smart save mode) */
-#define AT76_SET_POWERSAVE_MODE (SIOCIWFIRSTPRIV + 4)
-#define AT76_GET_POWERSAVE_MODE (SIOCIWFIRSTPRIV + 5)
-/* min and max channel times for scan */
-#define AT76_SET_SCAN_TIMES (SIOCIWFIRSTPRIV + 6)
-#define AT76_GET_SCAN_TIMES (SIOCIWFIRSTPRIV + 7)
-/* scan mode (0 - active, 1 - passive) */
-#define AT76_SET_SCAN_MODE (SIOCIWFIRSTPRIV + 8)
-#define AT76_GET_SCAN_MODE (SIOCIWFIRSTPRIV + 9)
-
#define CMD_STATUS_IDLE 0x00
#define CMD_STATUS_COMPLETE 0x01
#define CMD_STATUS_UNKNOWN 0x02
@@ -82,6 +65,7 @@ enum board_type {
#define MIB_MAC 0x03
#define MIB_MAC_MGMT 0x05
#define MIB_MAC_WEP 0x06
+#define MIB_MAC_ENCRYPTION 0x06
#define MIB_PHY 0x07
#define MIB_FW_VERSION 0x08
#define MIB_MDOMAIN 0x09
@@ -106,6 +90,26 @@ enum board_type {
#define AT76_PM_ON 2
#define AT76_PM_SMART 3
+/* cipher values for encryption keys */
+#define CIPHER_NONE 0 /* this value is only guessed */
+#define CIPHER_WEP64 1
+#define CIPHER_TKIP 2
+#define CIPHER_CCMP 3
+#define CIPHER_CCX 4 /* for consistency sake only */
+#define CIPHER_WEP128 5
+
+/* bit flags key types for encryption keys */
+#define KEY_PAIRWISE 2
+#define KEY_TX 4
+
+#define CIPHER_KEYS (4)
+#define CIPHER_KEY_LEN (40)
+
+struct key_config {
+ u8 cipher;
+ u8 keylen;
+};
+
struct hwcfg_r505 {
u8 cr39_values[14];
u8 reserved1[14];
@@ -147,6 +151,9 @@ union at76_hwcfg {
#define WEP_SMALL_KEY_LEN (40 / 8)
#define WEP_LARGE_KEY_LEN (104 / 8)
+#define WEP_KEYS (4)
+
+
struct at76_card_config {
u8 exclude_unencrypted;
@@ -161,7 +168,7 @@ struct at76_card_config {
u8 privacy_invoked;
u8 wep_default_key_id; /* 0..3 */
u8 current_ssid[32];
- u8 wep_default_key_value[4][WEP_KEY_LEN];
+ u8 wep_default_key_value[4][WEP_LARGE_KEY_LEN];
u8 ssid_len;
u8 short_preamble;
__le16 beacon_period;
@@ -186,7 +193,7 @@ struct at76_rx_buffer {
u8 link_quality;
u8 noise_level;
__le32 rx_time;
- u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN];
+ u8 packet[IEEE80211_MAX_FRAG_THRESHOLD];
} __attribute__((packed));
/* Length of Atmel-specific Tx header before 802.11 frame */
@@ -196,8 +203,11 @@ struct at76_tx_buffer {
__le16 wlength;
u8 tx_rate;
u8 padding;
- u8 reserved[4];
- u8 packet[IEEE80211_FRAME_LEN + IEEE80211_FCS_LEN];
+ u8 key_id;
+ u8 cipher_type;
+ u8 cipher_length;
+ u8 reserved;
+ u8 packet[IEEE80211_MAX_FRAG_THRESHOLD];
} __attribute__((packed));
/* defines for scan_type below */
@@ -244,6 +254,7 @@ struct set_mib_buffer {
u8 byte;
__le16 word;
u8 addr[ETH_ALEN];
+ u8 data[256]; /* we need more space for mib_mac_encryption */
} data;
} __attribute__((packed));
@@ -317,10 +328,24 @@ struct mib_mac_wep {
u8 exclude_unencrypted;
__le32 wep_icv_error_count;
__le32 wep_excluded_count;
- u8 wep_default_keyvalue[WEP_KEYS][WEP_KEY_LEN];
+ u8 wep_default_keyvalue[WEP_KEYS][WEP_LARGE_KEY_LEN];
u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */
} __attribute__((packed));
+struct mib_mac_encryption {
+ u8 cipher_default_keyvalue[CIPHER_KEYS][CIPHER_KEY_LEN];
+ u8 tkip_bssid[6];
+ u8 privacy_invoked;
+ u8 cipher_default_key_id;
+ u8 cipher_default_group_key_id;
+ u8 exclude_unencrypted;
+ u8 wep_encryption_type;
+ u8 ckip_key_permutation; /* bool */
+ __le32 wep_icv_error_count;
+ __le32 wep_excluded_count;
+ u8 key_rsc[CIPHER_KEYS][8];
+} __attribute__((packed));
+
struct mib_phy {
__le32 ed_threshold;
@@ -364,16 +389,6 @@ struct at76_fw_header {
__le32 ext_fw_len; /* external firmware image length */
} __attribute__((packed));
-enum mac_state {
- MAC_INIT,
- MAC_SCANNING,
- MAC_AUTH,
- MAC_ASSOC,
- MAC_JOINING,
- MAC_CONNECTED,
- MAC_OWN_IBSS
-};
-
/* a description of a regulatory domain and the allowed channels */
struct reg_domain {
u16 code;
@@ -381,47 +396,6 @@ struct reg_domain {
u32 channel_map; /* if bit N is set, channel (N+1) is allowed */
};
-/* how long do we keep a (I)BSS in the bss_list in jiffies
- this should be long enough for the user to retrieve the table
- (by iwlist ?) after the device started, because all entries from
- other channels than the one the device locks on get removed, too */
-#define BSS_LIST_TIMEOUT (120 * HZ)
-/* struct to store BSS info found during scan */
-#define BSS_LIST_MAX_RATE_LEN 32 /* 32 rates should be enough ... */
-
-struct bss_info {
- struct list_head list;
-
- u8 bssid[ETH_ALEN]; /* bssid */
- u8 ssid[IW_ESSID_MAX_SIZE]; /* essid */
- u8 ssid_len; /* length of ssid above */
- u8 channel;
- u16 capa; /* BSS capabilities */
- u16 beacon_interval; /* beacon interval, Kus (1024 microseconds) */
- u8 rates[BSS_LIST_MAX_RATE_LEN]; /* supported rates in units of
- 500 kbps, ORed with 0x80 for
- basic rates */
- u8 rates_len;
-
- /* quality of received beacon */
- u8 rssi;
- u8 link_qual;
- u8 noise_level;
-
- unsigned long last_rx; /* time (jiffies) of last beacon received */
-};
-
-/* a rx data buffer to collect rx fragments */
-struct rx_data_buf {
- u8 sender[ETH_ALEN]; /* sender address */
- u16 seqnr; /* sequence number */
- u16 fragnr; /* last fragment received */
- unsigned long last_rx; /* jiffies of last rx */
- struct sk_buff *skb; /* == NULL if entry is free */
-};
-
-#define NR_RX_DATA_BUF 8
-
/* Data for one loaded firmware file */
struct fwentry {
const char *const fwname;
@@ -438,11 +412,9 @@ struct fwentry {
struct at76_priv {
struct usb_device *udev; /* USB device pointer */
- struct net_device *netdev; /* net device pointer */
- struct net_device_stats stats; /* net device stats */
- struct iw_statistics wstats; /* wireless stats */
struct sk_buff *rx_skb; /* skbuff for receiving data */
+ struct sk_buff *tx_skb; /* skbuff for transmitting data */
void *bulk_out_buffer; /* buffer for sending data */
struct urb *tx_urb; /* URB for sending data */
@@ -454,26 +426,17 @@ struct at76_priv {
struct mutex mtx; /* locks this structure */
/* work queues */
- struct work_struct work_assoc_done;
- struct work_struct work_join;
- struct work_struct work_new_bss;
- struct work_struct work_start_scan;
struct work_struct work_set_promisc;
struct work_struct work_submit_rx;
- struct delayed_work dwork_restart;
- struct delayed_work dwork_get_scan;
- struct delayed_work dwork_beacon;
- struct delayed_work dwork_auth;
- struct delayed_work dwork_assoc;
+ struct delayed_work dwork_hw_scan;
struct tasklet_struct rx_tasklet;
/* the WEP stuff */
int wep_enabled; /* 1 if WEP is enabled */
int wep_key_id; /* key id to be used */
- u8 wep_keys[WEP_KEYS][WEP_KEY_LEN]; /* the four WEP keys,
- 5 or 13 bytes are used */
- u8 wep_keys_len[WEP_KEYS]; /* the length of the above keys */
+ u8 wep_keys[WEP_KEYS][WEP_LARGE_KEY_LEN]; /* WEP keys */
+ u8 wep_keys_len[WEP_KEYS]; /* length of WEP keys */
int channel;
int iw_mode;
@@ -495,44 +458,13 @@ struct at76_priv {
int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
int scan_need_any; /* if set, need to scan for any ESSID */
- /* the list we got from scanning */
- spinlock_t bss_list_spinlock; /* protects bss_list operations */
- struct list_head bss_list; /* list of BSS we got beacons from */
- struct timer_list bss_list_timer; /* timer to purge old entries
- from bss_list */
- struct bss_info *curr_bss; /* current BSS */
u16 assoc_id; /* current association ID, if associated */
- u8 wanted_bssid[ETH_ALEN];
- int wanted_bssid_valid; /* != 0 if wanted_bssid is to be used */
-
- /* some data for infrastructure mode only */
- spinlock_t mgmt_spinlock; /* this spinlock protects access to
- next_mgmt_bulk */
-
- struct at76_tx_buffer *next_mgmt_bulk; /* pending management msg to
- send via bulk out */
- enum mac_state mac_state;
- enum {
- SCAN_IDLE,
- SCAN_IN_PROGRESS,
- SCAN_COMPLETED
- } scan_state;
- time_t last_scan;
-
- int retries; /* remaining retries in case of timeout when
- * sending AuthReq or AssocReq */
u8 pm_mode; /* power management mode */
u32 pm_period; /* power management period in microseconds */
struct reg_domain const *domain; /* reg domain description */
- /* iwspy support */
- spinlock_t spy_spinlock;
- struct iw_spy_data spy_data;
-
- struct iw_public_data wireless_data;
-
/* These fields contain HW config provided by the device (not all of
* these fields are used by all board types) */
u8 mac_addr[ETH_ALEN];
@@ -540,9 +472,6 @@ struct at76_priv {
struct at76_card_config card_config;
- /* store rx fragments until complete */
- struct rx_data_buf rx_data[NR_RX_DATA_BUF];
-
enum board_type board_type;
struct mib_fw_version fw_version;
@@ -550,58 +479,20 @@ struct at76_priv {
unsigned int netdev_registered:1;
struct set_mib_buffer mib_buf; /* global buffer for set_mib calls */
- /* beacon counting */
int beacon_period; /* period of mgmt beacons, Kus */
- int beacons_received;
- unsigned long beacons_last_qual; /* time we restarted counting
- beacons */
-};
-struct at76_rx_radiotap {
- struct ieee80211_radiotap_header rt_hdr;
- __le64 rt_tsft;
- u8 rt_flags;
- u8 rt_rate;
- s8 rt_signal;
- s8 rt_noise;
-};
-
-#define AT76_RX_RADIOTAP_PRESENT \
- ((1 << IEEE80211_RADIOTAP_TSFT) | \
- (1 << IEEE80211_RADIOTAP_FLAGS) | \
- (1 << IEEE80211_RADIOTAP_RATE) | \
- (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | \
- (1 << IEEE80211_RADIOTAP_DB_ANTNOISE))
-
-#define BEACON_MAX_DATA_LENGTH 1500
-
-/* the maximum size of an AssocReq packet */
-#define ASSOCREQ_MAX_SIZE \
- (AT76_TX_HDRLEN + sizeof(struct ieee80211_assoc_request) + \
- 1 + 1 + IW_ESSID_MAX_SIZE + 1 + 1 + 4)
-
-/* for shared secret auth, add the challenge text size */
-#define AUTH_FRAME_SIZE (AT76_TX_HDRLEN + sizeof(struct ieee80211_auth))
+ struct ieee80211_hw *hw;
+ int mac80211_registered;
-/* Maximal number of AuthReq retries */
-#define AUTH_RETRIES 3
-
-/* Maximal number of AssocReq retries */
-#define ASSOC_RETRIES 3
-
-/* Beacon timeout in managed mode when we are connected */
-#define BEACON_TIMEOUT (10 * HZ)
-
-/* Timeout for authentication response */
-#define AUTH_TIMEOUT (1 * HZ)
+ struct key_config keys[4]; /* installed key types */
+ u8 default_pairwise_key;
+ u8 default_group_key;
+};
-/* Timeout for association response */
-#define ASSOC_TIMEOUT (1 * HZ)
+#define AT76_SUPPORTED_FILTERS FIF_PROMISC_IN_BSS
-/* Polling interval when scan is running */
#define SCAN_POLL_INTERVAL (HZ / 4)
-/* Command completion timeout */
#define CMD_COMPLETION_TIMEOUT (5 * HZ)
#define DEF_RTS_THRESHOLD 1536
@@ -611,8 +502,6 @@ struct at76_rx_radiotap {
#define DEF_SCAN_MIN_TIME 10
#define DEF_SCAN_MAX_TIME 120
-#define MAX_RTS_THRESHOLD (MAX_FRAG_THRESHOLD + 1)
-
/* the max padding size for tx in bytes (see calc_padding) */
#define MAX_PADDING_SIZE 53
diff --git a/drivers/staging/benet/Kconfig b/drivers/staging/benet/Kconfig
new file mode 100644
index 000000000000..f6806074f998
--- /dev/null
+++ b/drivers/staging/benet/Kconfig
@@ -0,0 +1,7 @@
+config BENET
+ tristate "ServerEngines 10Gb NIC - BladeEngine"
+ depends on PCI && INET
+ select INET_LRO
+ help
+ This driver implements the NIC functionality for ServerEngines
+ 10Gb network adapter BladeEngine (EC 3210).
diff --git a/drivers/staging/benet/MAINTAINERS b/drivers/staging/benet/MAINTAINERS
new file mode 100644
index 000000000000..d5ce340218b3
--- /dev/null
+++ b/drivers/staging/benet/MAINTAINERS
@@ -0,0 +1,6 @@
+SERVER ENGINES 10Gbe NIC - BLADE-ENGINE
+P: Subbu Seetharaman
+M: subbus@serverengines.com
+L: netdev@vger.kernel.org
+W: http://www.serverengines.com
+S: Supported
diff --git a/drivers/staging/benet/Makefile b/drivers/staging/benet/Makefile
new file mode 100644
index 000000000000..460b923b99bd
--- /dev/null
+++ b/drivers/staging/benet/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile to build the network driver for ServerEngine's BladeEngine
+#
+obj-$(CONFIG_BENET) += benet.o
+
+benet-y := be_init.o \
+ be_int.o \
+ be_netif.o \
+ be_ethtool.o \
+ funcobj.o \
+ cq.o \
+ eq.o \
+ mpu.o \
+ eth.o
diff --git a/drivers/staging/benet/TODO b/drivers/staging/benet/TODO
new file mode 100644
index 000000000000..a51dfb59a62f
--- /dev/null
+++ b/drivers/staging/benet/TODO
@@ -0,0 +1,6 @@
+TODO:
+ - remove wrappers around common iowrite functions
+ - full netdev audit of common problems/issues
+
+Please send all patches and questions to Subbu Seetharaman
+<subbus@serverengines.com> and Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/benet/asyncmesg.h b/drivers/staging/benet/asyncmesg.h
new file mode 100644
index 000000000000..d1e779adb848
--- /dev/null
+++ b/drivers/staging/benet/asyncmesg.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __asyncmesg_amap_h__
+#define __asyncmesg_amap_h__
+#include "fwcmd_common.h"
+
+/* --- ASYNC_EVENT_CODES --- */
+#define ASYNC_EVENT_CODE_LINK_STATE (1)
+#define ASYNC_EVENT_CODE_ISCSI (2)
+
+/* --- ASYNC_LINK_STATES --- */
+#define ASYNC_EVENT_LINK_DOWN (0) /* Link Down on a port */
+#define ASYNC_EVENT_LINK_UP (1) /* Link Up on a port */
+
+/*
+ * The last 4 bytes of the async events have this common format. It allows
+ * the driver to distinguish [link]MCC_CQ_ENTRY[/link] structs from
+ * asynchronous events. Both arrive on the same completion queue. This
+ * structure also contains the common fields used to decode the async event.
+ */
+struct BE_ASYNC_EVENT_TRAILER_AMAP {
+ u8 rsvd0[8]; /* DWORD 0 */
+ u8 event_code[8]; /* DWORD 0 */
+ u8 event_type[8]; /* DWORD 0 */
+ u8 rsvd1[6]; /* DWORD 0 */
+ u8 async_event; /* DWORD 0 */
+ u8 valid; /* DWORD 0 */
+} __packed;
+struct ASYNC_EVENT_TRAILER_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * Applicable in Initiator, Target and NIC modes.
+ * A link state async event is seen by all device drivers as soon they
+ * create an MCC ring. Thereafter, anytime the link status changes the
+ * drivers will receive a link state async event. Notifications continue to
+ * be sent until a driver destroys its MCC ring. A link down event is
+ * reported when either port loses link. A link up event is reported
+ * when either port regains link. When BE's failover mechanism is enabled, a
+ * link down on the active port causes traffic to be diverted to the standby
+ * port by the BE's ARM firmware (assuming the standby port has link). In
+ * this case, the standy port assumes the active status. Note: when link is
+ * restored on the failed port, traffic continues on the currently active
+ * port. The ARM firmware does not attempt to 'fail back' traffic to
+ * the restored port.
+ */
+struct BE_ASYNC_EVENT_LINK_STATE_AMAP {
+ u8 port0_link_status[8];
+ u8 port1_link_status[8];
+ u8 active_port[8];
+ u8 rsvd0[8]; /* DWORD 0 */
+ u8 port0_duplex[8];
+ u8 port0_speed[8];
+ u8 port1_duplex[8];
+ u8 port1_speed[8];
+ u8 port0_fault[8];
+ u8 port1_fault[8];
+ u8 rsvd1[2][8]; /* DWORD 2 */
+ struct BE_ASYNC_EVENT_TRAILER_AMAP trailer;
+} __packed;
+struct ASYNC_EVENT_LINK_STATE_AMAP {
+ u32 dw[4];
+};
+#endif /* __asyncmesg_amap_h__ */
diff --git a/drivers/staging/benet/be_cm.h b/drivers/staging/benet/be_cm.h
new file mode 100644
index 000000000000..b7a1dfd20c36
--- /dev/null
+++ b/drivers/staging/benet/be_cm.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __be_cm_amap_h__
+#define __be_cm_amap_h__
+#include "be_common.h"
+#include "etx_context.h"
+#include "mpu_context.h"
+
+/*
+ * --- CEV_WATERMARK_ENUM ---
+ * CQ/EQ Watermark Encodings. Encoded as number of free entries in
+ * Queue when Watermark is reached.
+ */
+#define CEV_WMARK_0 (0) /* Watermark when Queue full */
+#define CEV_WMARK_16 (1) /* Watermark at 16 free entries */
+#define CEV_WMARK_32 (2) /* Watermark at 32 free entries */
+#define CEV_WMARK_48 (3) /* Watermark at 48 free entries */
+#define CEV_WMARK_64 (4) /* Watermark at 64 free entries */
+#define CEV_WMARK_80 (5) /* Watermark at 80 free entries */
+#define CEV_WMARK_96 (6) /* Watermark at 96 free entries */
+#define CEV_WMARK_112 (7) /* Watermark at 112 free entries */
+#define CEV_WMARK_128 (8) /* Watermark at 128 free entries */
+#define CEV_WMARK_144 (9) /* Watermark at 144 free entries */
+#define CEV_WMARK_160 (10) /* Watermark at 160 free entries */
+#define CEV_WMARK_176 (11) /* Watermark at 176 free entries */
+#define CEV_WMARK_192 (12) /* Watermark at 192 free entries */
+#define CEV_WMARK_208 (13) /* Watermark at 208 free entries */
+#define CEV_WMARK_224 (14) /* Watermark at 224 free entries */
+#define CEV_WMARK_240 (15) /* Watermark at 240 free entries */
+
+/*
+ * --- CQ_CNT_ENUM ---
+ * Completion Queue Count Encodings.
+ */
+#define CEV_CQ_CNT_256 (0) /* CQ has 256 entries */
+#define CEV_CQ_CNT_512 (1) /* CQ has 512 entries */
+#define CEV_CQ_CNT_1024 (2) /* CQ has 1024 entries */
+
+/*
+ * --- EQ_CNT_ENUM ---
+ * Event Queue Count Encodings.
+ */
+#define CEV_EQ_CNT_256 (0) /* EQ has 256 entries (16-byte EQEs only) */
+#define CEV_EQ_CNT_512 (1) /* EQ has 512 entries (16-byte EQEs only) */
+#define CEV_EQ_CNT_1024 (2) /* EQ has 1024 entries (4-byte or */
+ /* 16-byte EQEs only) */
+#define CEV_EQ_CNT_2048 (3) /* EQ has 2048 entries (4-byte or */
+ /* 16-byte EQEs only) */
+#define CEV_EQ_CNT_4096 (4) /* EQ has 4096 entries (4-byte EQEs only) */
+
+/*
+ * --- EQ_SIZE_ENUM ---
+ * Event Queue Entry Size Encoding.
+ */
+#define CEV_EQ_SIZE_4 (0) /* EQE is 4 bytes */
+#define CEV_EQ_SIZE_16 (1) /* EQE is 16 bytes */
+
+/*
+ * Completion Queue Context Table Entry. Contains the state of a CQ.
+ * Located in RAM within the CEV block.
+ */
+struct BE_CQ_CONTEXT_AMAP {
+ u8 Cidx[11]; /* DWORD 0 */
+ u8 Watermark[4]; /* DWORD 0 */
+ u8 NoDelay; /* DWORD 0 */
+ u8 EPIdx[11]; /* DWORD 0 */
+ u8 Count[2]; /* DWORD 0 */
+ u8 valid; /* DWORD 0 */
+ u8 SolEvent; /* DWORD 0 */
+ u8 Eventable; /* DWORD 0 */
+ u8 Pidx[11]; /* DWORD 1 */
+ u8 PD[10]; /* DWORD 1 */
+ u8 EQID[7]; /* DWORD 1 */
+ u8 Func; /* DWORD 1 */
+ u8 WME; /* DWORD 1 */
+ u8 Stalled; /* DWORD 1 */
+ u8 Armed; /* DWORD 1 */
+} __packed;
+struct CQ_CONTEXT_AMAP {
+ u32 dw[2];
+};
+
+/*
+ * Event Queue Context Table Entry. Contains the state of an EQ.
+ * Located in RAM in the CEV block.
+ */
+struct BE_EQ_CONTEXT_AMAP {
+ u8 Cidx[13]; /* DWORD 0 */
+ u8 rsvd0[2]; /* DWORD 0 */
+ u8 Func; /* DWORD 0 */
+ u8 EPIdx[13]; /* DWORD 0 */
+ u8 valid; /* DWORD 0 */
+ u8 rsvd1; /* DWORD 0 */
+ u8 Size; /* DWORD 0 */
+ u8 Pidx[13]; /* DWORD 1 */
+ u8 rsvd2[3]; /* DWORD 1 */
+ u8 PD[10]; /* DWORD 1 */
+ u8 Count[3]; /* DWORD 1 */
+ u8 SolEvent; /* DWORD 1 */
+ u8 Stalled; /* DWORD 1 */
+ u8 Armed; /* DWORD 1 */
+ u8 Watermark[4]; /* DWORD 2 */
+ u8 WME; /* DWORD 2 */
+ u8 rsvd3[3]; /* DWORD 2 */
+ u8 EventVect[6]; /* DWORD 2 */
+ u8 rsvd4[2]; /* DWORD 2 */
+ u8 Delay[8]; /* DWORD 2 */
+ u8 rsvd5[6]; /* DWORD 2 */
+ u8 TMR; /* DWORD 2 */
+ u8 rsvd6; /* DWORD 2 */
+ u8 rsvd7[32]; /* DWORD 3 */
+} __packed;
+struct EQ_CONTEXT_AMAP {
+ u32 dw[4];
+};
+
+#endif /* __be_cm_amap_h__ */
diff --git a/drivers/staging/benet/be_common.h b/drivers/staging/benet/be_common.h
new file mode 100644
index 000000000000..7e63dc5e3348
--- /dev/null
+++ b/drivers/staging/benet/be_common.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __be_common_amap_h__
+#define __be_common_amap_h__
+
+/* Physical Address. */
+struct BE_PHYS_ADDR_AMAP {
+ u8 lo[32]; /* DWORD 0 */
+ u8 hi[32]; /* DWORD 1 */
+} __packed;
+struct PHYS_ADDR_AMAP {
+ u32 dw[2];
+};
+
+/* Virtual Address. */
+struct BE_VIRT_ADDR_AMAP {
+ u8 lo[32]; /* DWORD 0 */
+ u8 hi[32]; /* DWORD 1 */
+} __packed;
+struct VIRT_ADDR_AMAP {
+ u32 dw[2];
+};
+
+/* Scatter gather element. */
+struct BE_SGE_AMAP {
+ u8 addr_hi[32]; /* DWORD 0 */
+ u8 addr_lo[32]; /* DWORD 1 */
+ u8 rsvd0[32]; /* DWORD 2 */
+ u8 len[16]; /* DWORD 3 */
+ u8 rsvd1[16]; /* DWORD 3 */
+} __packed;
+struct SGE_AMAP {
+ u32 dw[4];
+};
+
+#endif /* __be_common_amap_h__ */
diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c
new file mode 100644
index 000000000000..027af85707aa
--- /dev/null
+++ b/drivers/staging/benet/be_ethtool.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * be_ethtool.c
+ *
+ * This file contains various functions that ethtool can use
+ * to talk to the driver and the BE H/W.
+ */
+
+#include "benet.h"
+
+#include <linux/ethtool.h>
+
+static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = {
+/* net_device_stats */
+ "rx_packets",
+ "tx_packets",
+ "rx_bytes",
+ "tx_bytes",
+ "rx_errors",
+ "tx_errors",
+ "rx_dropped",
+ "tx_dropped",
+ "multicast",
+ "collisions",
+ "rx_length_errors",
+ "rx_over_errors",
+ "rx_crc_errors",
+ "rx_frame_errors",
+ "rx_fifo_errors",
+ "rx_missed_errors",
+ "tx_aborted_errors",
+ "tx_carrier_errors",
+ "tx_fifo_errors",
+ "tx_heartbeat_errors",
+ "tx_window_errors",
+ "rx_compressed",
+ "tc_compressed",
+/* BE driver Stats */
+ "bes_tx_reqs",
+ "bes_tx_fails",
+ "bes_fwd_reqs",
+ "bes_tx_wrbs",
+ "bes_interrupts",
+ "bes_events",
+ "bes_tx_events",
+ "bes_rx_events",
+ "bes_tx_compl",
+ "bes_rx_compl",
+ "bes_ethrx_post_fail",
+ "bes_802_3_dropped_frames",
+ "bes_802_3_malformed_frames",
+ "bes_rx_misc_pkts",
+ "bes_eth_tx_rate",
+ "bes_eth_rx_rate",
+ "Num Packets collected",
+ "Num Times Flushed",
+};
+
+#define NET_DEV_STATS_LEN \
+ (sizeof(struct net_device_stats)/sizeof(unsigned long))
+
+#define BENET_STATS_LEN ARRAY_SIZE(benet_gstrings_stats)
+
+static void
+be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+
+ strncpy(drvinfo->driver, be_driver_name, 32);
+ strncpy(drvinfo->version, be_drvr_ver, 32);
+ strncpy(drvinfo->fw_version, be_fw_ver, 32);
+ strcpy(drvinfo->bus_info, pci_name(adapter->pdev));
+ drvinfo->testinfo_len = 0;
+ drvinfo->regdump_len = 0;
+ drvinfo->eedump_len = 0;
+}
+
+static int
+be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+
+ coalesce->rx_max_coalesced_frames = adapter->max_rx_coal;
+
+ coalesce->rx_coalesce_usecs = adapter->cur_eqd;
+ coalesce->rx_coalesce_usecs_high = adapter->max_eqd;
+ coalesce->rx_coalesce_usecs_low = adapter->min_eqd;
+
+ coalesce->tx_coalesce_usecs = adapter->cur_eqd;
+ coalesce->tx_coalesce_usecs_high = adapter->max_eqd;
+ coalesce->tx_coalesce_usecs_low = adapter->min_eqd;
+
+ coalesce->use_adaptive_rx_coalesce = adapter->enable_aic;
+ coalesce->use_adaptive_tx_coalesce = adapter->enable_aic;
+
+ return 0;
+}
+
+/*
+ * This routine is used to set interrup coalescing delay *as well as*
+ * the number of pkts to coalesce for LRO.
+ */
+static int
+be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+ struct be_eq_object *eq_objectp;
+ u32 max, min, cur;
+ int status;
+
+ adapter->max_rx_coal = coalesce->rx_max_coalesced_frames;
+ if (adapter->max_rx_coal >= BE_LRO_MAX_PKTS)
+ adapter->max_rx_coal = BE_LRO_MAX_PKTS;
+
+ if (adapter->enable_aic == 0 &&
+ coalesce->use_adaptive_rx_coalesce == 1) {
+ /* if AIC is being turned on now, start with an EQD of 0 */
+ adapter->cur_eqd = 0;
+ }
+ adapter->enable_aic = coalesce->use_adaptive_rx_coalesce;
+
+ /* round off to nearest multiple of 8 */
+ max = (((coalesce->rx_coalesce_usecs_high + 4) >> 3) << 3);
+ min = (((coalesce->rx_coalesce_usecs_low + 4) >> 3) << 3);
+ cur = (((coalesce->rx_coalesce_usecs + 4) >> 3) << 3);
+
+ if (adapter->enable_aic) {
+ /* accept low and high if AIC is enabled */
+ if (max > MAX_EQD)
+ max = MAX_EQD;
+ if (min > max)
+ min = max;
+ adapter->max_eqd = max;
+ adapter->min_eqd = min;
+ if (adapter->cur_eqd > max)
+ adapter->cur_eqd = max;
+ if (adapter->cur_eqd < min)
+ adapter->cur_eqd = min;
+ } else {
+ /* accept specified coalesce_usecs only if AIC is disabled */
+ if (cur > MAX_EQD)
+ cur = MAX_EQD;
+ eq_objectp = &pnob->event_q_obj;
+ status =
+ be_eq_modify_delay(&pnob->fn_obj, 1, &eq_objectp, &cur,
+ NULL, NULL, NULL);
+ if (status == BE_SUCCESS)
+ adapter->cur_eqd = cur;
+ }
+ return 0;
+}
+
+static u32 be_get_rx_csum(struct net_device *netdev)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+ return adapter->rx_csum;
+}
+
+static int be_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+
+ if (data)
+ adapter->rx_csum = 1;
+ else
+ adapter->rx_csum = 0;
+
+ return 0;
+}
+
+static void
+be_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
+{
+ switch (stringset) {
+ case ETH_SS_STATS:
+ memcpy(data, *benet_gstrings_stats,
+ sizeof(benet_gstrings_stats));
+ break;
+ }
+}
+
+static int be_get_stats_count(struct net_device *netdev)
+{
+ return BENET_STATS_LEN;
+}
+
+static void
+be_get_ethtool_stats(struct net_device *netdev,
+ struct ethtool_stats *stats, uint64_t *data)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+ int i;
+
+ benet_get_stats(netdev);
+
+ for (i = 0; i <= NET_DEV_STATS_LEN; i++)
+ data[i] = ((unsigned long *)&adapter->benet_stats)[i];
+
+ data[i] = adapter->be_stat.bes_tx_reqs;
+ data[i++] = adapter->be_stat.bes_tx_fails;
+ data[i++] = adapter->be_stat.bes_fwd_reqs;
+ data[i++] = adapter->be_stat.bes_tx_wrbs;
+
+ data[i++] = adapter->be_stat.bes_ints;
+ data[i++] = adapter->be_stat.bes_events;
+ data[i++] = adapter->be_stat.bes_tx_events;
+ data[i++] = adapter->be_stat.bes_rx_events;
+ data[i++] = adapter->be_stat.bes_tx_compl;
+ data[i++] = adapter->be_stat.bes_rx_compl;
+ data[i++] = adapter->be_stat.bes_ethrx_post_fail;
+ data[i++] = adapter->be_stat.bes_802_3_dropped_frames;
+ data[i++] = adapter->be_stat.bes_802_3_malformed_frames;
+ data[i++] = adapter->be_stat.bes_rx_misc_pkts;
+ data[i++] = adapter->be_stat.bes_eth_tx_rate;
+ data[i++] = adapter->be_stat.bes_eth_rx_rate;
+ data[i++] = adapter->be_stat.bes_rx_coal;
+ data[i++] = adapter->be_stat.bes_rx_flush;
+
+}
+
+static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+ ecmd->speed = SPEED_10000;
+ ecmd->duplex = DUPLEX_FULL;
+ ecmd->autoneg = AUTONEG_DISABLE;
+ return 0;
+}
+
+/* Get the Ring parameters from the pnob */
+static void
+be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ /* Pre Set Maxims */
+ ring->rx_max_pending = pnob->rx_q_len;
+ ring->rx_mini_max_pending = ring->rx_mini_max_pending;
+ ring->rx_jumbo_max_pending = ring->rx_jumbo_max_pending;
+ ring->tx_max_pending = pnob->tx_q_len;
+
+ /* Current hardware Settings */
+ ring->rx_pending = atomic_read(&pnob->rx_q_posted);
+ ring->rx_mini_pending = ring->rx_mini_pending;
+ ring->rx_jumbo_pending = ring->rx_jumbo_pending;
+ ring->tx_pending = atomic_read(&pnob->tx_q_used);
+
+}
+
+static void
+be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ bool rxfc, txfc;
+ int status;
+
+ status = be_eth_get_flow_control(&pnob->fn_obj, &txfc, &rxfc);
+ if (status != BE_SUCCESS) {
+ dev_info(&netdev->dev, "Unable to get pause frame settings\n");
+ /* return defaults */
+ ecmd->rx_pause = 1;
+ ecmd->tx_pause = 0;
+ ecmd->autoneg = AUTONEG_ENABLE;
+ return;
+ }
+
+ if (txfc == true)
+ ecmd->tx_pause = 1;
+ else
+ ecmd->tx_pause = 0;
+
+ if (rxfc == true)
+ ecmd->rx_pause = 1;
+ else
+ ecmd->rx_pause = 0;
+
+ ecmd->autoneg = AUTONEG_ENABLE;
+}
+
+static int
+be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ bool txfc, rxfc;
+ int status;
+
+ if (ecmd->autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+
+ if (ecmd->tx_pause)
+ txfc = true;
+ else
+ txfc = false;
+
+ if (ecmd->rx_pause)
+ rxfc = true;
+ else
+ rxfc = false;
+
+ status = be_eth_set_flow_control(&pnob->fn_obj, txfc, rxfc);
+ if (status != BE_SUCCESS) {
+ dev_info(&netdev->dev, "Unable to set pause frame settings\n");
+ return -1;
+ }
+ return 0;
+}
+
+struct ethtool_ops be_ethtool_ops = {
+ .get_settings = be_get_settings,
+ .get_drvinfo = be_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_coalesce = be_get_coalesce,
+ .set_coalesce = be_set_coalesce,
+ .get_ringparam = be_get_ringparam,
+ .get_pauseparam = be_get_pauseparam,
+ .set_pauseparam = be_set_pauseparam,
+ .get_rx_csum = be_get_rx_csum,
+ .set_rx_csum = be_set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
+ .get_strings = be_get_strings,
+ .get_stats_count = be_get_stats_count,
+ .get_ethtool_stats = be_get_ethtool_stats,
+};
diff --git a/drivers/staging/benet/be_init.c b/drivers/staging/benet/be_init.c
new file mode 100644
index 000000000000..12a026c3f9e1
--- /dev/null
+++ b/drivers/staging/benet/be_init.c
@@ -0,0 +1,1382 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#include <linux/etherdevice.h>
+#include "benet.h"
+
+#define DRVR_VERSION "1.0.728"
+
+static const struct pci_device_id be_device_id_table[] = {
+ {PCI_DEVICE(0x19a2, 0x0201)},
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, be_device_id_table);
+
+MODULE_VERSION(DRVR_VERSION);
+
+#define DRV_DESCRIPTION "ServerEngines BladeEngine Network Driver Version "
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION DRVR_VERSION);
+MODULE_AUTHOR("ServerEngines");
+MODULE_LICENSE("GPL");
+
+static unsigned int msix = 1;
+module_param(msix, uint, S_IRUGO);
+MODULE_PARM_DESC(msix, "Use MSI-x interrupts");
+
+static unsigned int rxbuf_size = 2048; /* Default RX frag size */
+module_param(rxbuf_size, uint, S_IRUGO);
+MODULE_PARM_DESC(rxbuf_size, "Size of buffers to hold Rx data");
+
+const char be_drvr_ver[] = DRVR_VERSION;
+char be_fw_ver[32]; /* F/W version filled in by be_probe */
+char be_driver_name[] = "benet";
+
+/*
+ * Number of entries in each queue.
+ */
+#define EVENT_Q_LEN 1024
+#define ETH_TXQ_LEN 2048
+#define ETH_TXCQ_LEN 1024
+#define ETH_RXQ_LEN 1024 /* Does not support any other value */
+#define ETH_UC_RXCQ_LEN 1024
+#define ETH_BC_RXCQ_LEN 256
+#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */
+#define MCC_CQ_LEN 256
+
+/* Bit mask describing events of interest to be traced */
+unsigned int trace_level;
+
+static int
+init_pci_be_function(struct be_adapter *adapter, struct pci_dev *pdev)
+{
+ u64 pa;
+
+ /* CSR */
+ pa = pci_resource_start(pdev, 2);
+ adapter->csr_va = ioremap_nocache(pa, pci_resource_len(pdev, 2));
+ if (adapter->csr_va == NULL)
+ return -ENOMEM;
+
+ /* Door Bell */
+ pa = pci_resource_start(pdev, 4);
+ adapter->db_va = ioremap_nocache(pa, (128 * 1024));
+ if (adapter->db_va == NULL) {
+ iounmap(adapter->csr_va);
+ return -ENOMEM;
+ }
+
+ /* PCI */
+ pa = pci_resource_start(pdev, 1);
+ adapter->pci_va = ioremap_nocache(pa, pci_resource_len(pdev, 1));
+ if (adapter->pci_va == NULL) {
+ iounmap(adapter->csr_va);
+ iounmap(adapter->db_va);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*
+ This function enables the interrupt corresponding to the Event
+ queue ID for the given NetObject
+*/
+void be_enable_eq_intr(struct be_net_object *pnob)
+{
+ struct CQ_DB_AMAP cqdb;
+ cqdb.dw[0] = 0;
+ AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1);
+ AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 1);
+ AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0);
+ AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id);
+ PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]);
+}
+
+/*
+ This function disables the interrupt corresponding to the Event
+ queue ID for the given NetObject
+*/
+void be_disable_eq_intr(struct be_net_object *pnob)
+{
+ struct CQ_DB_AMAP cqdb;
+ cqdb.dw[0] = 0;
+ AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1);
+ AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 0);
+ AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0);
+ AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id);
+ PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]);
+}
+
+/*
+ This function enables the interrupt from the network function
+ of the BladeEngine. Use the function be_disable_eq_intr()
+ to enable the interrupt from the event queue of only one specific
+ NetObject
+*/
+void be_enable_intr(struct be_net_object *pnob)
+{
+ struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl;
+ u32 host_intr;
+
+ ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl);
+ host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
+ hostintr, ctrl.dw);
+ if (!host_intr) {
+ AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
+ hostintr, ctrl.dw, 1);
+ PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl,
+ ctrl.dw[0]);
+ }
+}
+
+/*
+ This function disables the interrupt from the network function of
+ the BladeEngine. Use the function be_disable_eq_intr() to
+ disable the interrupt from the event queue of only one specific NetObject
+*/
+void be_disable_intr(struct be_net_object *pnob)
+{
+
+ struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl;
+ u32 host_intr;
+ ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl);
+ host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
+ hostintr, ctrl.dw);
+ if (host_intr) {
+ AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, hostintr,
+ ctrl.dw, 0);
+ PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl,
+ ctrl.dw[0]);
+ }
+}
+
+static int be_enable_msix(struct be_adapter *adapter)
+{
+ int i, ret;
+
+ if (!msix)
+ return -1;
+
+ for (i = 0; i < BE_MAX_REQ_MSIX_VECTORS; i++)
+ adapter->msix_entries[i].entry = i;
+
+ ret = pci_enable_msix(adapter->pdev, adapter->msix_entries,
+ BE_MAX_REQ_MSIX_VECTORS);
+
+ if (ret == 0)
+ adapter->msix_enabled = 1;
+ return ret;
+}
+
+static int be_register_isr(struct be_adapter *adapter,
+ struct be_net_object *pnob)
+{
+ struct net_device *netdev = pnob->netdev;
+ int intx = 0, r;
+
+ netdev->irq = adapter->pdev->irq;
+ r = be_enable_msix(adapter);
+
+ if (r == 0) {
+ r = request_irq(adapter->msix_entries[0].vector,
+ be_int, IRQF_SHARED, netdev->name, netdev);
+ if (r) {
+ printk(KERN_WARNING
+ "MSIX Request IRQ failed - Errno %d\n", r);
+ intx = 1;
+ pci_disable_msix(adapter->pdev);
+ adapter->msix_enabled = 0;
+ }
+ } else {
+ intx = 1;
+ }
+
+ if (intx) {
+ r = request_irq(netdev->irq, be_int, IRQF_SHARED,
+ netdev->name, netdev);
+ if (r) {
+ printk(KERN_WARNING
+ "INTx Request IRQ failed - Errno %d\n", r);
+ return -1;
+ }
+ }
+ adapter->isr_registered = 1;
+ return 0;
+}
+
+static void be_unregister_isr(struct be_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdevp;
+ if (adapter->isr_registered) {
+ if (adapter->msix_enabled) {
+ free_irq(adapter->msix_entries[0].vector, netdev);
+ pci_disable_msix(adapter->pdev);
+ adapter->msix_enabled = 0;
+ } else {
+ free_irq(netdev->irq, netdev);
+ }
+ adapter->isr_registered = 0;
+ }
+}
+
+/*
+ This function processes the Flush Completions that are issued by the
+ ARM F/W, when a Recv Ring is destroyed. A flush completion is
+ identified when a Rx COmpl descriptor has the tcpcksum and udpcksum
+ set and the pktsize is 32. These completions are received on the
+ Rx Completion Queue.
+*/
+static u32 be_process_rx_flush_cmpl(struct be_net_object *pnob)
+{
+ struct ETH_RX_COMPL_AMAP *rxcp;
+ unsigned int i = 0;
+ while ((rxcp = be_get_rx_cmpl(pnob)) != NULL) {
+ be_notify_cmpl(pnob, 1, pnob->rx_cq_id, 1);
+ i++;
+ }
+ return i;
+}
+
+static void be_tx_q_clean(struct be_net_object *pnob)
+{
+ while (atomic_read(&pnob->tx_q_used))
+ process_one_tx_compl(pnob, tx_compl_lastwrb_idx_get(pnob));
+}
+
+static void be_rx_q_clean(struct be_net_object *pnob)
+{
+ if (pnob->rx_ctxt) {
+ int i;
+ struct be_rx_page_info *rx_page_info;
+ for (i = 0; i < pnob->rx_q_len; i++) {
+ rx_page_info = &(pnob->rx_page_info[i]);
+ if (!pnob->rx_pg_shared || rx_page_info->page_offset) {
+ pci_unmap_page(pnob->adapter->pdev,
+ pci_unmap_addr(rx_page_info, bus),
+ pnob->rx_buf_size,
+ PCI_DMA_FROMDEVICE);
+ }
+ if (rx_page_info->page)
+ put_page(rx_page_info->page);
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ }
+ pnob->rx_pg_info_hd = 0;
+ }
+}
+
+static void be_destroy_netobj(struct be_net_object *pnob)
+{
+ int status;
+
+ if (pnob->tx_q_created) {
+ status = be_eth_sq_destroy(&pnob->tx_q_obj);
+ pnob->tx_q_created = 0;
+ }
+
+ if (pnob->rx_q_created) {
+ status = be_eth_rq_destroy(&pnob->rx_q_obj);
+ if (status != 0) {
+ status = be_eth_rq_destroy_options(&pnob->rx_q_obj, 0,
+ NULL, NULL);
+ BUG_ON(status);
+ }
+ pnob->rx_q_created = 0;
+ }
+
+ be_process_rx_flush_cmpl(pnob);
+
+ if (pnob->tx_cq_created) {
+ status = be_cq_destroy(&pnob->tx_cq_obj);
+ pnob->tx_cq_created = 0;
+ }
+
+ if (pnob->rx_cq_created) {
+ status = be_cq_destroy(&pnob->rx_cq_obj);
+ pnob->rx_cq_created = 0;
+ }
+
+ if (pnob->mcc_q_created) {
+ status = be_mcc_ring_destroy(&pnob->mcc_q_obj);
+ pnob->mcc_q_created = 0;
+ }
+ if (pnob->mcc_cq_created) {
+ status = be_cq_destroy(&pnob->mcc_cq_obj);
+ pnob->mcc_cq_created = 0;
+ }
+
+ if (pnob->event_q_created) {
+ status = be_eq_destroy(&pnob->event_q_obj);
+ pnob->event_q_created = 0;
+ }
+ be_function_cleanup(&pnob->fn_obj);
+}
+
+/*
+ * free all resources associated with a pnob
+ * Called at the time of module cleanup as well a any error during
+ * module init. Some resources may be partially allocated in a NetObj.
+ */
+static void netobject_cleanup(struct be_adapter *adapter,
+ struct be_net_object *pnob)
+{
+ struct net_device *netdev = adapter->netdevp;
+
+ if (netif_running(netdev)) {
+ netif_stop_queue(netdev);
+ be_wait_nic_tx_cmplx_cmpl(pnob);
+ be_disable_eq_intr(pnob);
+ }
+
+ be_unregister_isr(adapter);
+
+ if (adapter->tasklet_started) {
+ tasklet_kill(&(adapter->sts_handler));
+ adapter->tasklet_started = 0;
+ }
+ if (pnob->fn_obj_created)
+ be_disable_intr(pnob);
+
+ if (adapter->dev_state != BE_DEV_STATE_NONE)
+ unregister_netdev(netdev);
+
+ if (pnob->fn_obj_created)
+ be_destroy_netobj(pnob);
+
+ adapter->net_obj = NULL;
+ adapter->netdevp = NULL;
+
+ be_rx_q_clean(pnob);
+ if (pnob->rx_ctxt) {
+ kfree(pnob->rx_page_info);
+ kfree(pnob->rx_ctxt);
+ }
+
+ be_tx_q_clean(pnob);
+ kfree(pnob->tx_ctxt);
+
+ if (pnob->mcc_q)
+ pci_free_consistent(adapter->pdev, pnob->mcc_q_size,
+ pnob->mcc_q, pnob->mcc_q_bus);
+
+ if (pnob->mcc_wrb_ctxt)
+ free_pages((unsigned long)pnob->mcc_wrb_ctxt,
+ get_order(pnob->mcc_wrb_ctxt_size));
+
+ if (pnob->mcc_cq)
+ pci_free_consistent(adapter->pdev, pnob->mcc_cq_size,
+ pnob->mcc_cq, pnob->mcc_cq_bus);
+
+ if (pnob->event_q)
+ pci_free_consistent(adapter->pdev, pnob->event_q_size,
+ pnob->event_q, pnob->event_q_bus);
+
+ if (pnob->tx_cq)
+ pci_free_consistent(adapter->pdev, pnob->tx_cq_size,
+ pnob->tx_cq, pnob->tx_cq_bus);
+
+ if (pnob->tx_q)
+ pci_free_consistent(adapter->pdev, pnob->tx_q_size,
+ pnob->tx_q, pnob->tx_q_bus);
+
+ if (pnob->rx_q)
+ pci_free_consistent(adapter->pdev, pnob->rx_q_size,
+ pnob->rx_q, pnob->rx_q_bus);
+
+ if (pnob->rx_cq)
+ pci_free_consistent(adapter->pdev, pnob->rx_cq_size,
+ pnob->rx_cq, pnob->rx_cq_bus);
+
+
+ if (pnob->mb_ptr)
+ pci_free_consistent(adapter->pdev, pnob->mb_size, pnob->mb_ptr,
+ pnob->mb_bus);
+
+ free_netdev(netdev);
+}
+
+
+static int be_nob_ring_alloc(struct be_adapter *adapter,
+ struct be_net_object *pnob)
+{
+ u32 size;
+
+ /* Mail box rd; mailbox pointer needs to be 16 byte aligned */
+ pnob->mb_size = sizeof(struct MCC_MAILBOX_AMAP) + 16;
+ pnob->mb_ptr = pci_alloc_consistent(adapter->pdev, pnob->mb_size,
+ &pnob->mb_bus);
+ if (!pnob->mb_bus)
+ return -1;
+ memset(pnob->mb_ptr, 0, pnob->mb_size);
+ pnob->mb_rd.va = PTR_ALIGN(pnob->mb_ptr, 16);
+ pnob->mb_rd.pa = PTR_ALIGN(pnob->mb_bus, 16);
+ pnob->mb_rd.length = sizeof(struct MCC_MAILBOX_AMAP);
+ /*
+ * Event queue
+ */
+ pnob->event_q_len = EVENT_Q_LEN;
+ pnob->event_q_size = pnob->event_q_len * sizeof(struct EQ_ENTRY_AMAP);
+ pnob->event_q = pci_alloc_consistent(adapter->pdev, pnob->event_q_size,
+ &pnob->event_q_bus);
+ if (!pnob->event_q_bus)
+ return -1;
+ memset(pnob->event_q, 0, pnob->event_q_size);
+ /*
+ * Eth TX queue
+ */
+ pnob->tx_q_len = ETH_TXQ_LEN;
+ pnob->tx_q_port = 0;
+ pnob->tx_q_size = pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP);
+ pnob->tx_q = pci_alloc_consistent(adapter->pdev, pnob->tx_q_size,
+ &pnob->tx_q_bus);
+ if (!pnob->tx_q_bus)
+ return -1;
+ memset(pnob->tx_q, 0, pnob->tx_q_size);
+ /*
+ * Eth TX Compl queue
+ */
+ pnob->txcq_len = ETH_TXCQ_LEN;
+ pnob->tx_cq_size = pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP);
+ pnob->tx_cq = pci_alloc_consistent(adapter->pdev, pnob->tx_cq_size,
+ &pnob->tx_cq_bus);
+ if (!pnob->tx_cq_bus)
+ return -1;
+ memset(pnob->tx_cq, 0, pnob->tx_cq_size);
+ /*
+ * Eth RX queue
+ */
+ pnob->rx_q_len = ETH_RXQ_LEN;
+ pnob->rx_q_size = pnob->rx_q_len * sizeof(struct ETH_RX_D_AMAP);
+ pnob->rx_q = pci_alloc_consistent(adapter->pdev, pnob->rx_q_size,
+ &pnob->rx_q_bus);
+ if (!pnob->rx_q_bus)
+ return -1;
+ memset(pnob->rx_q, 0, pnob->rx_q_size);
+ /*
+ * Eth Unicast RX Compl queue
+ */
+ pnob->rx_cq_len = ETH_UC_RXCQ_LEN;
+ pnob->rx_cq_size = pnob->rx_cq_len *
+ sizeof(struct ETH_RX_COMPL_AMAP);
+ pnob->rx_cq = pci_alloc_consistent(adapter->pdev, pnob->rx_cq_size,
+ &pnob->rx_cq_bus);
+ if (!pnob->rx_cq_bus)
+ return -1;
+ memset(pnob->rx_cq, 0, pnob->rx_cq_size);
+
+ /* TX resources */
+ size = pnob->tx_q_len * sizeof(void **);
+ pnob->tx_ctxt = kzalloc(size, GFP_KERNEL);
+ if (pnob->tx_ctxt == NULL)
+ return -1;
+
+ /* RX resources */
+ size = pnob->rx_q_len * sizeof(void *);
+ pnob->rx_ctxt = kzalloc(size, GFP_KERNEL);
+ if (pnob->rx_ctxt == NULL)
+ return -1;
+
+ size = (pnob->rx_q_len * sizeof(struct be_rx_page_info));
+ pnob->rx_page_info = kzalloc(size, GFP_KERNEL);
+ if (pnob->rx_page_info == NULL)
+ return -1;
+
+ adapter->eth_statsp = kzalloc(sizeof(struct FWCMD_ETH_GET_STATISTICS),
+ GFP_KERNEL);
+ if (adapter->eth_statsp == NULL)
+ return -1;
+ pnob->rx_buf_size = rxbuf_size;
+ return 0;
+}
+
+/*
+ This function initializes the be_net_object for subsequent
+ network operations.
+
+ Before calling this function, the driver must have allocated
+ space for the NetObject structure, initialized the structure,
+ allocated DMAable memory for all the network queues that form
+ part of the NetObject and populated the start address (virtual)
+ and number of entries allocated for each queue in the NetObject structure.
+
+ The driver must also have allocated memory to hold the
+ mailbox structure (MCC_MAILBOX) and post the physical address,
+ virtual addresses and the size of the mailbox memory in the
+ NetObj.mb_rd. This structure is used by BECLIB for
+ initial communication with the embedded MCC processor. BECLIB
+ uses the mailbox until MCC rings are created for more efficient
+ communication with the MCC processor.
+
+ If the driver wants to create multiple network interface for more
+ than one protection domain, it can call be_create_netobj()
+ multiple times once for each protection domain. A Maximum of
+ 32 protection domains are supported.
+
+*/
+static int
+be_create_netobj(struct be_net_object *pnob, u8 __iomem *csr_va,
+ u8 __iomem *db_va, u8 __iomem *pci_va)
+{
+ int status = 0;
+ bool eventable = false, tx_no_delay = false, rx_no_delay = false;
+ struct be_eq_object *eq_objectp = NULL;
+ struct be_function_object *pfob = &pnob->fn_obj;
+ struct ring_desc rd;
+ u32 set_rxbuf_size;
+ u32 tx_cmpl_wm = CEV_WMARK_96; /* 0xffffffff to disable */
+ u32 rx_cmpl_wm = CEV_WMARK_160; /* 0xffffffff to disable */
+ u32 eq_delay = 0; /* delay in 8usec units. 0xffffffff to disable */
+
+ memset(&rd, 0, sizeof(struct ring_desc));
+
+ status = be_function_object_create(csr_va, db_va, pci_va,
+ BE_FUNCTION_TYPE_NETWORK, &pnob->mb_rd, pfob);
+ if (status != BE_SUCCESS)
+ return status;
+ pnob->fn_obj_created = true;
+
+ if (tx_cmpl_wm == 0xffffffff)
+ tx_no_delay = true;
+ if (rx_cmpl_wm == 0xffffffff)
+ rx_no_delay = true;
+ /*
+ * now create the necessary rings
+ * Event Queue first.
+ */
+ if (pnob->event_q_len) {
+ rd.va = pnob->event_q;
+ rd.pa = pnob->event_q_bus;
+ rd.length = pnob->event_q_size;
+
+ status = be_eq_create(pfob, &rd, 4, pnob->event_q_len,
+ (u32) -1, /* CEV_WMARK_* or -1 */
+ eq_delay, /* in 8us units, or -1 */
+ &pnob->event_q_obj);
+ if (status != BE_SUCCESS)
+ goto error_ret;
+ pnob->event_q_id = pnob->event_q_obj.eq_id;
+ pnob->event_q_created = 1;
+ eventable = true;
+ eq_objectp = &pnob->event_q_obj;
+ }
+ /*
+ * Now Eth Tx Compl. queue.
+ */
+ if (pnob->txcq_len) {
+ rd.va = pnob->tx_cq;
+ rd.pa = pnob->tx_cq_bus;
+ rd.length = pnob->tx_cq_size;
+
+ status = be_cq_create(pfob, &rd,
+ pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP),
+ false, /* solicted events, */
+ tx_no_delay, /* nodelay */
+ tx_cmpl_wm, /* Watermark encodings */
+ eq_objectp, &pnob->tx_cq_obj);
+ if (status != BE_SUCCESS)
+ goto error_ret;
+
+ pnob->tx_cq_id = pnob->tx_cq_obj.cq_id;
+ pnob->tx_cq_created = 1;
+ }
+ /*
+ * Eth Tx queue
+ */
+ if (pnob->tx_q_len) {
+ struct be_eth_sq_parameters ex_params = { 0 };
+ u32 type;
+
+ if (pnob->tx_q_port) {
+ /* TXQ to be bound to a specific port */
+ type = BE_ETH_TX_RING_TYPE_BOUND;
+ ex_params.port = pnob->tx_q_port - 1;
+ } else
+ type = BE_ETH_TX_RING_TYPE_STANDARD;
+
+ rd.va = pnob->tx_q;
+ rd.pa = pnob->tx_q_bus;
+ rd.length = pnob->tx_q_size;
+
+ status = be_eth_sq_create_ex(pfob, &rd,
+ pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP),
+ type, 2, &pnob->tx_cq_obj,
+ &ex_params, &pnob->tx_q_obj);
+
+ if (status != BE_SUCCESS)
+ goto error_ret;
+
+ pnob->tx_q_id = pnob->tx_q_obj.bid;
+ pnob->tx_q_created = 1;
+ }
+ /*
+ * Now Eth Rx compl. queue. Always needed.
+ */
+ rd.va = pnob->rx_cq;
+ rd.pa = pnob->rx_cq_bus;
+ rd.length = pnob->rx_cq_size;
+
+ status = be_cq_create(pfob, &rd,
+ pnob->rx_cq_len * sizeof(struct ETH_RX_COMPL_AMAP),
+ false, /* solicted events, */
+ rx_no_delay, /* nodelay */
+ rx_cmpl_wm, /* Watermark encodings */
+ eq_objectp, &pnob->rx_cq_obj);
+ if (status != BE_SUCCESS)
+ goto error_ret;
+
+ pnob->rx_cq_id = pnob->rx_cq_obj.cq_id;
+ pnob->rx_cq_created = 1;
+
+ status = be_eth_rq_set_frag_size(pfob, pnob->rx_buf_size,
+ (u32 *) &set_rxbuf_size);
+ if (status != BE_SUCCESS) {
+ be_eth_rq_get_frag_size(pfob, (u32 *) &pnob->rx_buf_size);
+ if ((pnob->rx_buf_size != 2048) && (pnob->rx_buf_size != 4096)
+ && (pnob->rx_buf_size != 8192))
+ goto error_ret;
+ } else {
+ if (pnob->rx_buf_size != set_rxbuf_size)
+ pnob->rx_buf_size = set_rxbuf_size;
+ }
+ /*
+ * Eth RX queue. be_eth_rq_create() always assumes 2 pages size
+ */
+ rd.va = pnob->rx_q;
+ rd.pa = pnob->rx_q_bus;
+ rd.length = pnob->rx_q_size;
+
+ status = be_eth_rq_create(pfob, &rd, &pnob->rx_cq_obj,
+ &pnob->rx_cq_obj, &pnob->rx_q_obj);
+
+ if (status != BE_SUCCESS)
+ goto error_ret;
+
+ pnob->rx_q_id = pnob->rx_q_obj.rid;
+ pnob->rx_q_created = 1;
+
+ return BE_SUCCESS; /* All required queues created. */
+
+error_ret:
+ be_destroy_netobj(pnob);
+ return status;
+}
+
+static int be_nob_ring_init(struct be_adapter *adapter,
+ struct be_net_object *pnob)
+{
+ int status;
+
+ pnob->event_q_tl = 0;
+
+ pnob->tx_q_hd = 0;
+ pnob->tx_q_tl = 0;
+
+ pnob->tx_cq_tl = 0;
+
+ pnob->rx_cq_tl = 0;
+
+ memset(pnob->event_q, 0, pnob->event_q_size);
+ memset(pnob->tx_cq, 0, pnob->tx_cq_size);
+ memset(pnob->tx_ctxt, 0, pnob->tx_q_len * sizeof(void **));
+ memset(pnob->rx_ctxt, 0, pnob->rx_q_len * sizeof(void *));
+ pnob->rx_pg_info_hd = 0;
+ pnob->rx_q_hd = 0;
+ atomic_set(&pnob->rx_q_posted, 0);
+
+ status = be_create_netobj(pnob, adapter->csr_va, adapter->db_va,
+ adapter->pci_va);
+ if (status != BE_SUCCESS)
+ return -1;
+
+ be_post_eth_rx_buffs(pnob);
+ return 0;
+}
+
+/* This function handles async callback for link status */
+static void
+be_link_status_async_callback(void *context, u32 event_code, void *event)
+{
+ struct ASYNC_EVENT_LINK_STATE_AMAP *link_status = event;
+ struct be_adapter *adapter = context;
+ bool link_enable = false;
+ struct be_net_object *pnob;
+ struct ASYNC_EVENT_TRAILER_AMAP *async_trailer;
+ struct net_device *netdev;
+ u32 async_event_code, async_event_type, active_port;
+ u32 port0_link_status, port1_link_status, port0_duplex, port1_duplex;
+ u32 port0_speed, port1_speed;
+
+ if (event_code != ASYNC_EVENT_CODE_LINK_STATE) {
+ /* Not our event to handle */
+ return;
+ }
+ async_trailer = (struct ASYNC_EVENT_TRAILER_AMAP *)
+ ((u8 *) event + sizeof(struct MCC_CQ_ENTRY_AMAP) -
+ sizeof(struct ASYNC_EVENT_TRAILER_AMAP));
+
+ async_event_code = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_code,
+ async_trailer);
+ BUG_ON(async_event_code != ASYNC_EVENT_CODE_LINK_STATE);
+
+ pnob = adapter->net_obj;
+ netdev = pnob->netdev;
+
+ /* Determine if this event is a switch VLD or a physical link event */
+ async_event_type = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_type,
+ async_trailer);
+ active_port = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
+ active_port, link_status);
+ port0_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
+ port0_link_status, link_status);
+ port1_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
+ port1_link_status, link_status);
+ port0_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
+ port0_duplex, link_status);
+ port1_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
+ port1_duplex, link_status);
+ port0_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
+ port0_speed, link_status);
+ port1_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE,
+ port1_speed, link_status);
+ if (async_event_type == NTWK_LINK_TYPE_VIRTUAL) {
+ adapter->be_stat.bes_link_change_virtual++;
+ if (adapter->be_link_sts->active_port != active_port) {
+ dev_notice(&netdev->dev,
+ "Active port changed due to VLD on switch\n");
+ } else {
+ dev_notice(&netdev->dev, "Link status update\n");
+ }
+
+ } else {
+ adapter->be_stat.bes_link_change_physical++;
+ if (adapter->be_link_sts->active_port != active_port) {
+ dev_notice(&netdev->dev,
+ "Active port changed due to port link"
+ " status change\n");
+ } else {
+ dev_notice(&netdev->dev, "Link status update\n");
+ }
+ }
+
+ memset(adapter->be_link_sts, 0, sizeof(adapter->be_link_sts));
+
+ if ((port0_link_status == ASYNC_EVENT_LINK_UP) ||
+ (port1_link_status == ASYNC_EVENT_LINK_UP)) {
+ if ((adapter->port0_link_sts == BE_PORT_LINK_DOWN) &&
+ (adapter->port1_link_sts == BE_PORT_LINK_DOWN)) {
+ /* Earlier both the ports are down So link is up */
+ link_enable = true;
+ }
+
+ if (port0_link_status == ASYNC_EVENT_LINK_UP) {
+ adapter->port0_link_sts = BE_PORT_LINK_UP;
+ adapter->be_link_sts->mac0_duplex = port0_duplex;
+ adapter->be_link_sts->mac0_speed = port0_speed;
+ if (active_port == NTWK_PORT_A)
+ adapter->be_link_sts->active_port = 0;
+ } else
+ adapter->port0_link_sts = BE_PORT_LINK_DOWN;
+
+ if (port1_link_status == ASYNC_EVENT_LINK_UP) {
+ adapter->port1_link_sts = BE_PORT_LINK_UP;
+ adapter->be_link_sts->mac1_duplex = port1_duplex;
+ adapter->be_link_sts->mac1_speed = port1_speed;
+ if (active_port == NTWK_PORT_B)
+ adapter->be_link_sts->active_port = 1;
+ } else
+ adapter->port1_link_sts = BE_PORT_LINK_DOWN;
+
+ printk(KERN_INFO "Link Properties for %s:\n", netdev->name);
+ dev_info(&netdev->dev, "Link Properties:\n");
+ be_print_link_info(adapter->be_link_sts);
+
+ if (!link_enable)
+ return;
+ /*
+ * Both ports were down previously, but atleast one of
+ * them has come up if this netdevice's carrier is not up,
+ * then indicate to stack
+ */
+ if (!netif_carrier_ok(netdev)) {
+ netif_start_queue(netdev);
+ netif_carrier_on(netdev);
+ }
+ return;
+ }
+
+ /* Now both the ports are down. Tell the stack about it */
+ dev_info(&netdev->dev, "Both ports are down\n");
+ adapter->port0_link_sts = BE_PORT_LINK_DOWN;
+ adapter->port1_link_sts = BE_PORT_LINK_DOWN;
+ if (netif_carrier_ok(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ return;
+}
+
+static int be_mcc_create(struct be_adapter *adapter)
+{
+ struct be_net_object *pnob;
+
+ pnob = adapter->net_obj;
+ /*
+ * Create the MCC ring so that all further communication with
+ * MCC can go thru the ring. we do this at the end since
+ * we do not want to be dealing with interrupts until the
+ * initialization is complete.
+ */
+ pnob->mcc_q_len = MCC_Q_LEN;
+ pnob->mcc_q_size = pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP);
+ pnob->mcc_q = pci_alloc_consistent(adapter->pdev, pnob->mcc_q_size,
+ &pnob->mcc_q_bus);
+ if (!pnob->mcc_q_bus)
+ return -1;
+ /*
+ * space for MCC WRB context
+ */
+ pnob->mcc_wrb_ctxtLen = MCC_Q_LEN;
+ pnob->mcc_wrb_ctxt_size = pnob->mcc_wrb_ctxtLen *
+ sizeof(struct be_mcc_wrb_context);
+ pnob->mcc_wrb_ctxt = (void *)__get_free_pages(GFP_KERNEL,
+ get_order(pnob->mcc_wrb_ctxt_size));
+ if (pnob->mcc_wrb_ctxt == NULL)
+ return -1;
+ /*
+ * Space for MCC compl. ring
+ */
+ pnob->mcc_cq_len = MCC_CQ_LEN;
+ pnob->mcc_cq_size = pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP);
+ pnob->mcc_cq = pci_alloc_consistent(adapter->pdev, pnob->mcc_cq_size,
+ &pnob->mcc_cq_bus);
+ if (!pnob->mcc_cq_bus)
+ return -1;
+ return 0;
+}
+
+/*
+ This function creates the MCC request and completion ring required
+ for communicating with the ARM processor. The caller must have
+ allocated required amount of memory for the MCC ring and MCC
+ completion ring and posted the virtual address and number of
+ entries in the corresponding members (mcc_q and mcc_cq) in the
+ NetObject struture.
+
+ When this call is completed, all further communication with
+ ARM will switch from mailbox to this ring.
+
+ pnob - Pointer to the NetObject structure. This NetObject should
+ have been created using a previous call to be_create_netobj()
+*/
+int be_create_mcc_rings(struct be_net_object *pnob)
+{
+ int status = 0;
+ struct ring_desc rd;
+ struct be_function_object *pfob = &pnob->fn_obj;
+
+ memset(&rd, 0, sizeof(struct ring_desc));
+ if (pnob->mcc_cq_len) {
+ rd.va = pnob->mcc_cq;
+ rd.pa = pnob->mcc_cq_bus;
+ rd.length = pnob->mcc_cq_size;
+
+ status = be_cq_create(pfob, &rd,
+ pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP),
+ false, /* solicted events, */
+ true, /* nodelay */
+ 0, /* 0 Watermark since Nodelay is true */
+ &pnob->event_q_obj,
+ &pnob->mcc_cq_obj);
+
+ if (status != BE_SUCCESS)
+ return status;
+
+ pnob->mcc_cq_id = pnob->mcc_cq_obj.cq_id;
+ pnob->mcc_cq_created = 1;
+ }
+ if (pnob->mcc_q_len) {
+ rd.va = pnob->mcc_q;
+ rd.pa = pnob->mcc_q_bus;
+ rd.length = pnob->mcc_q_size;
+
+ status = be_mcc_ring_create(pfob, &rd,
+ pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP),
+ pnob->mcc_wrb_ctxt, pnob->mcc_wrb_ctxtLen,
+ &pnob->mcc_cq_obj, &pnob->mcc_q_obj);
+
+ if (status != BE_SUCCESS)
+ return status;
+
+ pnob->mcc_q_created = 1;
+ }
+ return BE_SUCCESS;
+}
+
+static int be_mcc_init(struct be_adapter *adapter)
+{
+ u32 r;
+ struct be_net_object *pnob;
+
+ pnob = adapter->net_obj;
+ memset(pnob->mcc_q, 0, pnob->mcc_q_size);
+ pnob->mcc_q_hd = 0;
+
+ memset(pnob->mcc_wrb_ctxt, 0, pnob->mcc_wrb_ctxt_size);
+
+ memset(pnob->mcc_cq, 0, pnob->mcc_cq_size);
+ pnob->mcc_cq_tl = 0;
+
+ r = be_create_mcc_rings(adapter->net_obj);
+ if (r != BE_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+static void be_remove(struct pci_dev *pdev)
+{
+ struct be_net_object *pnob;
+ struct be_adapter *adapter;
+
+ adapter = pci_get_drvdata(pdev);
+ if (!adapter)
+ return;
+
+ pci_set_drvdata(pdev, NULL);
+ pnob = (struct be_net_object *)adapter->net_obj;
+
+ flush_scheduled_work();
+
+ if (pnob) {
+ /* Unregister async callback function for link status updates */
+ if (pnob->mcc_q_created)
+ be_mcc_add_async_event_callback(&pnob->mcc_q_obj,
+ NULL, NULL);
+ netobject_cleanup(adapter, pnob);
+ }
+
+ if (adapter->csr_va)
+ iounmap(adapter->csr_va);
+ if (adapter->db_va)
+ iounmap(adapter->db_va);
+ if (adapter->pci_va)
+ iounmap(adapter->pci_va);
+
+ pci_release_regions(adapter->pdev);
+ pci_disable_device(adapter->pdev);
+
+ kfree(adapter->be_link_sts);
+ kfree(adapter->eth_statsp);
+
+ if (adapter->timer_ctxt.get_stats_timer.function)
+ del_timer_sync(&adapter->timer_ctxt.get_stats_timer);
+ kfree(adapter);
+}
+
+/*
+ * This function is called by the PCI sub-system when it finds a PCI
+ * device with dev/vendor IDs that match with one of our devices.
+ * All of the driver initialization is done in this function.
+ */
+static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
+{
+ int status = 0;
+ struct be_adapter *adapter;
+ struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD get_fwv;
+ struct be_net_object *pnob;
+ struct net_device *netdev;
+
+ status = pci_enable_device(pdev);
+ if (status)
+ goto error;
+
+ status = pci_request_regions(pdev, be_driver_name);
+ if (status)
+ goto error_pci_req;
+
+ pci_set_master(pdev);
+ adapter = kzalloc(sizeof(struct be_adapter), GFP_KERNEL);
+ if (adapter == NULL) {
+ status = -ENOMEM;
+ goto error_adapter;
+ }
+ adapter->dev_state = BE_DEV_STATE_NONE;
+ adapter->pdev = pdev;
+ pci_set_drvdata(pdev, adapter);
+
+ adapter->enable_aic = 1;
+ adapter->max_eqd = MAX_EQD;
+ adapter->min_eqd = 0;
+ adapter->cur_eqd = 0;
+
+ status = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ if (!status) {
+ adapter->dma_64bit_cap = true;
+ } else {
+ adapter->dma_64bit_cap = false;
+ status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (status != 0) {
+ printk(KERN_ERR "Could not set PCI DMA Mask\n");
+ goto cleanup;
+ }
+ }
+
+ status = init_pci_be_function(adapter, pdev);
+ if (status != 0) {
+ printk(KERN_ERR "Failed to map PCI BARS\n");
+ status = -ENOMEM;
+ goto cleanup;
+ }
+
+ be_trace_set_level(DL_ALWAYS | DL_ERR);
+
+ adapter->be_link_sts = kmalloc(sizeof(struct BE_LINK_STATUS),
+ GFP_KERNEL);
+ if (adapter->be_link_sts == NULL) {
+ printk(KERN_ERR "Memory allocation for link status "
+ "buffer failed\n");
+ goto cleanup;
+ }
+ spin_lock_init(&adapter->txq_lock);
+
+ netdev = alloc_etherdev(sizeof(struct be_net_object));
+ if (netdev == NULL) {
+ status = -ENOMEM;
+ goto cleanup;
+ }
+ pnob = netdev_priv(netdev);
+ adapter->net_obj = pnob;
+ adapter->netdevp = netdev;
+ pnob->adapter = adapter;
+ pnob->netdev = netdev;
+
+ status = be_nob_ring_alloc(adapter, pnob);
+ if (status != 0)
+ goto cleanup;
+
+ status = be_nob_ring_init(adapter, pnob);
+ if (status != 0)
+ goto cleanup;
+
+ be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, false,
+ false, false, netdev->dev_addr, NULL, NULL);
+
+ netdev->init = &benet_init;
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ SET_NETDEV_DEV(netdev, &(adapter->pdev->dev));
+
+ netif_napi_add(netdev, &pnob->napi, be_poll, 64);
+
+ /* if the rx_frag size if 2K, one page is shared as two RX frags */
+ pnob->rx_pg_shared =
+ (pnob->rx_buf_size <= PAGE_SIZE / 2) ? true : false;
+ if (pnob->rx_buf_size != rxbuf_size) {
+ printk(KERN_WARNING
+ "Could not set Rx buffer size to %d. Using %d\n",
+ rxbuf_size, pnob->rx_buf_size);
+ rxbuf_size = pnob->rx_buf_size;
+ }
+
+ tasklet_init(&(adapter->sts_handler), be_process_intr,
+ (unsigned long)adapter);
+ adapter->tasklet_started = 1;
+ spin_lock_init(&(adapter->int_lock));
+
+ status = be_register_isr(adapter, pnob);
+ if (status != 0)
+ goto cleanup;
+
+ adapter->rx_csum = 1;
+ adapter->max_rx_coal = BE_LRO_MAX_PKTS;
+
+ memset(&get_fwv, 0,
+ sizeof(struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD));
+ printk(KERN_INFO "BladeEngine Driver version:%s. "
+ "Copyright ServerEngines, Corporation 2005 - 2008\n",
+ be_drvr_ver);
+ status = be_function_get_fw_version(&pnob->fn_obj, &get_fwv, NULL,
+ NULL);
+ if (status == BE_SUCCESS) {
+ strncpy(be_fw_ver, get_fwv.firmware_version_string, 32);
+ printk(KERN_INFO "BladeEngine Firmware Version:%s\n",
+ get_fwv.firmware_version_string);
+ } else {
+ printk(KERN_WARNING "Unable to get BE Firmware Version\n");
+ }
+
+ sema_init(&adapter->get_eth_stat_sem, 0);
+ init_timer(&adapter->timer_ctxt.get_stats_timer);
+ atomic_set(&adapter->timer_ctxt.get_stat_flag, 0);
+ adapter->timer_ctxt.get_stats_timer.function =
+ &be_get_stats_timer_handler;
+
+ status = be_mcc_create(adapter);
+ if (status < 0)
+ goto cleanup;
+ status = be_mcc_init(adapter);
+ if (status < 0)
+ goto cleanup;
+
+
+ status = be_mcc_add_async_event_callback(&adapter->net_obj->mcc_q_obj,
+ be_link_status_async_callback, (void *)adapter);
+ if (status != BE_SUCCESS) {
+ printk(KERN_WARNING "add_async_event_callback failed");
+ printk(KERN_WARNING
+ "Link status changes may not be reflected\n");
+ }
+
+ status = register_netdev(netdev);
+ if (status != 0)
+ goto cleanup;
+ be_update_link_status(adapter);
+ adapter->dev_state = BE_DEV_STATE_INIT;
+ return 0;
+
+cleanup:
+ be_remove(pdev);
+ return status;
+error_adapter:
+ pci_release_regions(pdev);
+error_pci_req:
+ pci_disable_device(pdev);
+error:
+ printk(KERN_ERR "BladeEngine initalization failed\n");
+ return status;
+}
+
+/*
+ * Get the current link status and print the status on console
+ */
+void be_update_link_status(struct be_adapter *adapter)
+{
+ int status;
+ struct be_net_object *pnob = adapter->net_obj;
+
+ status = be_rxf_link_status(&pnob->fn_obj, adapter->be_link_sts, NULL,
+ NULL, NULL);
+ if (status == BE_SUCCESS) {
+ if (adapter->be_link_sts->mac0_speed &&
+ adapter->be_link_sts->mac0_duplex)
+ adapter->port0_link_sts = BE_PORT_LINK_UP;
+ else
+ adapter->port0_link_sts = BE_PORT_LINK_DOWN;
+
+ if (adapter->be_link_sts->mac1_speed &&
+ adapter->be_link_sts->mac1_duplex)
+ adapter->port1_link_sts = BE_PORT_LINK_UP;
+ else
+ adapter->port1_link_sts = BE_PORT_LINK_DOWN;
+
+ dev_info(&pnob->netdev->dev, "Link Properties:\n");
+ be_print_link_info(adapter->be_link_sts);
+ return;
+ }
+ dev_info(&pnob->netdev->dev, "Could not get link status\n");
+ return;
+}
+
+
+#ifdef CONFIG_PM
+static void
+be_pm_cleanup(struct be_adapter *adapter,
+ struct be_net_object *pnob, struct net_device *netdev)
+{
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ be_wait_nic_tx_cmplx_cmpl(pnob);
+ be_disable_eq_intr(pnob);
+
+ if (adapter->tasklet_started) {
+ tasklet_kill(&adapter->sts_handler);
+ adapter->tasklet_started = 0;
+ }
+
+ be_unregister_isr(adapter);
+ be_disable_intr(pnob);
+
+ be_tx_q_clean(pnob);
+ be_rx_q_clean(pnob);
+
+ be_destroy_netobj(pnob);
+}
+
+static int be_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct be_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdevp;
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ adapter->dev_pm_state = adapter->dev_state;
+ adapter->dev_state = BE_DEV_STATE_SUSPEND;
+
+ netif_device_detach(netdev);
+ if (netif_running(netdev))
+ be_pm_cleanup(adapter, pnob, netdev);
+
+ pci_enable_wake(pdev, 3, 1);
+ pci_enable_wake(pdev, 4, 1); /* D3 Cold = 4 */
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+}
+
+static void be_up(struct be_adapter *adapter)
+{
+ struct be_net_object *pnob = adapter->net_obj;
+
+ if (pnob->num_vlans != 0)
+ be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans,
+ pnob->vlan_tag, NULL, NULL, NULL);
+
+}
+
+static int be_resume(struct pci_dev *pdev)
+{
+ int status = 0;
+ struct be_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdevp;
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ netif_device_detach(netdev);
+
+ status = pci_enable_device(pdev);
+ if (status)
+ return status;
+
+ pci_set_power_state(pdev, 0);
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, 3, 0);
+ pci_enable_wake(pdev, 4, 0); /* 4 is D3 cold */
+
+ netif_carrier_on(netdev);
+ netif_start_queue(netdev);
+
+ if (netif_running(netdev)) {
+ be_rxf_mac_address_read_write(&pnob->fn_obj, false, false,
+ false, true, false, netdev->dev_addr, NULL, NULL);
+
+ status = be_nob_ring_init(adapter, pnob);
+ if (status < 0)
+ return status;
+
+ tasklet_init(&(adapter->sts_handler), be_process_intr,
+ (unsigned long)adapter);
+ adapter->tasklet_started = 1;
+
+ if (be_register_isr(adapter, pnob) != 0) {
+ printk(KERN_ERR "be_register_isr failed\n");
+ return status;
+ }
+
+
+ status = be_mcc_init(adapter);
+ if (status < 0) {
+ printk(KERN_ERR "be_mcc_init failed\n");
+ return status;
+ }
+ be_update_link_status(adapter);
+ /*
+ * Register async call back function to handle link
+ * status updates
+ */
+ status = be_mcc_add_async_event_callback(
+ &adapter->net_obj->mcc_q_obj,
+ be_link_status_async_callback, (void *)adapter);
+ if (status != BE_SUCCESS) {
+ printk(KERN_WARNING "add_async_event_callback failed");
+ printk(KERN_WARNING
+ "Link status changes may not be reflected\n");
+ }
+ be_enable_intr(pnob);
+ be_enable_eq_intr(pnob);
+ be_up(adapter);
+ }
+ netif_device_attach(netdev);
+ adapter->dev_state = adapter->dev_pm_state;
+ return 0;
+
+}
+
+#endif
+
+/* Wait until no more pending transmits */
+void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *pnob)
+{
+ int i;
+
+ /* Wait for 20us * 50000 (= 1s) and no more */
+ i = 0;
+ while ((pnob->tx_q_tl != pnob->tx_q_hd) && (i < 50000)) {
+ ++i;
+ udelay(20);
+ }
+
+ /* Check for no more pending transmits */
+ if (i >= 50000) {
+ printk(KERN_WARNING
+ "Did not receive completions for all TX requests\n");
+ }
+}
+
+static struct pci_driver be_driver = {
+ .name = be_driver_name,
+ .id_table = be_device_id_table,
+ .probe = be_probe,
+#ifdef CONFIG_PM
+ .suspend = be_suspend,
+ .resume = be_resume,
+#endif
+ .remove = be_remove
+};
+
+/*
+ * Module init entry point. Registers our our device and return.
+ * Our probe will be called if the device is found.
+ */
+static int __init be_init_module(void)
+{
+ int ret;
+
+ if (rxbuf_size != 8192 && rxbuf_size != 4096 && rxbuf_size != 2048) {
+ printk(KERN_WARNING
+ "Unsupported receive buffer size (%d) requested\n",
+ rxbuf_size);
+ printk(KERN_WARNING
+ "Must be 2048, 4096 or 8192. Defaulting to 2048\n");
+ rxbuf_size = 2048;
+ }
+
+ ret = pci_register_driver(&be_driver);
+
+ return ret;
+}
+
+module_init(be_init_module);
+
+/*
+ * be_exit_module - Driver Exit Cleanup Routine
+ */
+static void __exit be_exit_module(void)
+{
+ pci_unregister_driver(&be_driver);
+}
+
+module_exit(be_exit_module);
diff --git a/drivers/staging/benet/be_int.c b/drivers/staging/benet/be_int.c
new file mode 100644
index 000000000000..cba95d09a8b6
--- /dev/null
+++ b/drivers/staging/benet/be_int.c
@@ -0,0 +1,863 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#include <linux/if_vlan.h>
+#include <linux/inet_lro.h>
+
+#include "benet.h"
+
+/* number of bytes of RX frame that are copied to skb->data */
+#define BE_HDR_LEN 64
+
+#define NETIF_RX(skb) netif_receive_skb(skb)
+#define VLAN_ACCEL_RX(skb, pnob, vt) \
+ vlan_hwaccel_rx(skb, pnob->vlan_grp, vt)
+
+/*
+ This function notifies BladeEngine of the number of completion
+ entries processed from the specified completion queue by writing
+ the number of popped entries to the door bell.
+
+ pnob - Pointer to the NetObject structure
+ n - Number of completion entries processed
+ cq_id - Queue ID of the completion queue for which notification
+ is being done.
+ re_arm - 1 - rearm the completion ring to generate an event.
+ - 0 - dont rearm the completion ring to generate an event
+*/
+void be_notify_cmpl(struct be_net_object *pnob, int n, int cq_id, int re_arm)
+{
+ struct CQ_DB_AMAP cqdb;
+
+ cqdb.dw[0] = 0;
+ AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, cq_id);
+ AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, re_arm);
+ AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, n);
+ PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]);
+}
+
+/*
+ * adds additional receive frags indicated by BE starting from given
+ * frag index (fi) to specified skb's frag list
+ */
+static void
+add_skb_frags(struct be_net_object *pnob, struct sk_buff *skb,
+ u32 nresid, u32 fi)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ u32 sk_frag_idx, n;
+ struct be_rx_page_info *rx_page_info;
+ u32 frag_sz = pnob->rx_buf_size;
+
+ sk_frag_idx = skb_shinfo(skb)->nr_frags;
+ while (nresid) {
+ index_inc(&fi, pnob->rx_q_len);
+
+ rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
+ pnob->rx_ctxt[fi] = NULL;
+ if ((rx_page_info->page_offset) ||
+ (pnob->rx_pg_shared == false)) {
+ pci_unmap_page(adapter->pdev,
+ pci_unmap_addr(rx_page_info, bus),
+ frag_sz, PCI_DMA_FROMDEVICE);
+ }
+
+ n = min(nresid, frag_sz);
+ skb_shinfo(skb)->frags[sk_frag_idx].page = rx_page_info->page;
+ skb_shinfo(skb)->frags[sk_frag_idx].page_offset
+ = rx_page_info->page_offset;
+ skb_shinfo(skb)->frags[sk_frag_idx].size = n;
+
+ sk_frag_idx++;
+ skb->len += n;
+ skb->data_len += n;
+ skb_shinfo(skb)->nr_frags++;
+ nresid -= n;
+
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ atomic_dec(&pnob->rx_q_posted);
+ }
+}
+
+/*
+ * This function processes incoming nic packets over various Rx queues.
+ * This function takes the adapter, the current Rx status descriptor
+ * entry and the Rx completion queue ID as argument.
+ */
+static inline int process_nic_rx_completion(struct be_net_object *pnob,
+ struct ETH_RX_COMPL_AMAP *rxcp)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ struct sk_buff *skb;
+ int udpcksm, tcpcksm;
+ int n;
+ u32 nresid, fi;
+ u32 frag_sz = pnob->rx_buf_size;
+ u8 *va;
+ struct be_rx_page_info *rx_page_info;
+ u32 numfrags, vtp, vtm, vlan_tag, pktsize;
+
+ fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp);
+ BUG_ON(fi >= (int)pnob->rx_q_len);
+ BUG_ON(fi < 0);
+
+ rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
+ BUG_ON(!rx_page_info->page);
+ pnob->rx_ctxt[fi] = NULL;
+
+ /*
+ * If one page is used per fragment or if this is the second half of
+ * of the page, unmap the page here
+ */
+ if ((rx_page_info->page_offset) || (pnob->rx_pg_shared == false)) {
+ pci_unmap_page(adapter->pdev,
+ pci_unmap_addr(rx_page_info, bus), frag_sz,
+ PCI_DMA_FROMDEVICE);
+ }
+
+ atomic_dec(&pnob->rx_q_posted);
+ udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp);
+ tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp);
+ pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp);
+ /*
+ * get rid of RX flush completions first.
+ */
+ if ((tcpcksm) && (udpcksm) && (pktsize == 32)) {
+ put_page(rx_page_info->page);
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ return 0;
+ }
+ skb = netdev_alloc_skb(pnob->netdev, BE_HDR_LEN + NET_IP_ALIGN);
+ if (skb == NULL) {
+ dev_info(&pnob->netdev->dev, "alloc_skb() failed\n");
+ put_page(rx_page_info->page);
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ goto free_frags;
+ }
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ skb->dev = pnob->netdev;
+
+ n = min(pktsize, frag_sz);
+
+ va = page_address(rx_page_info->page) + rx_page_info->page_offset;
+ prefetch(va);
+
+ skb->len = n;
+ skb->data_len = n;
+ if (n <= BE_HDR_LEN) {
+ memcpy(skb->data, va, n);
+ put_page(rx_page_info->page);
+ skb->data_len -= n;
+ skb->tail += n;
+ } else {
+
+ /* Setup the SKB with page buffer information */
+ skb_shinfo(skb)->frags[0].page = rx_page_info->page;
+ skb_shinfo(skb)->nr_frags++;
+
+ /* Copy the header into the skb_data */
+ memcpy(skb->data, va, BE_HDR_LEN);
+ skb_shinfo(skb)->frags[0].page_offset =
+ rx_page_info->page_offset + BE_HDR_LEN;
+ skb_shinfo(skb)->frags[0].size = n - BE_HDR_LEN;
+ skb->data_len -= BE_HDR_LEN;
+ skb->tail += BE_HDR_LEN;
+ }
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ nresid = pktsize - n;
+
+ skb->protocol = eth_type_trans(skb, pnob->netdev);
+
+ if ((tcpcksm || udpcksm) && adapter->rx_csum)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ /*
+ * if we have more bytes left, the frame has been
+ * given to us in multiple fragments. This happens
+ * with Jumbo frames. Add the remaining fragments to
+ * skb->frags[] array.
+ */
+ if (nresid)
+ add_skb_frags(pnob, skb, nresid, fi);
+
+ /* update the the true size of the skb. */
+ skb->truesize = skb->len + sizeof(struct sk_buff);
+
+ /*
+ * If a 802.3 frame or 802.2 LLC frame
+ * (i.e) contains length field in MAC Hdr
+ * and frame len is greater than 64 bytes
+ */
+ if (((skb->protocol == ntohs(ETH_P_802_2)) ||
+ (skb->protocol == ntohs(ETH_P_802_3)))
+ && (pktsize > BE_HDR_LEN)) {
+ /*
+ * If the length given in Mac Hdr is less than frame size
+ * Erraneous frame, Drop it
+ */
+ if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) < pktsize) {
+ /* Increment Non Ether type II frames dropped */
+ adapter->be_stat.bes_802_3_dropped_frames++;
+
+ kfree_skb(skb);
+ return 0;
+ }
+ /*
+ * else if the length given in Mac Hdr is greater than
+ * frame size, should not be seeing this sort of frames
+ * dump the pkt and pass to stack
+ */
+ else if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) > pktsize) {
+ /* Increment Non Ether type II frames malformed */
+ adapter->be_stat.bes_802_3_malformed_frames++;
+ }
+ }
+
+ vtp = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp);
+ vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp);
+ if (vtp && vtm) {
+ /* Vlan tag present in pkt and BE found
+ * that the tag matched an entry in VLAN table
+ */
+ if (!pnob->vlan_grp || pnob->num_vlans == 0) {
+ /* But we have no VLANs configured.
+ * This should never happen. Drop the packet.
+ */
+ dev_info(&pnob->netdev->dev,
+ "BladeEngine: Unexpected vlan tagged packet\n");
+ kfree_skb(skb);
+ return 0;
+ }
+ /* pass the VLAN packet to stack */
+ vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp);
+ VLAN_ACCEL_RX(skb, pnob, be16_to_cpu(vlan_tag));
+
+ } else {
+ NETIF_RX(skb);
+ }
+ return 0;
+
+free_frags:
+ /* free all frags associated with the current rxcp */
+ numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp);
+ while (numfrags-- > 1) {
+ index_inc(&fi, pnob->rx_q_len);
+
+ rx_page_info = (struct be_rx_page_info *)
+ pnob->rx_ctxt[fi];
+ pnob->rx_ctxt[fi] = (void *)NULL;
+ if (rx_page_info->page_offset || !pnob->rx_pg_shared) {
+ pci_unmap_page(adapter->pdev,
+ pci_unmap_addr(rx_page_info, bus),
+ frag_sz, PCI_DMA_FROMDEVICE);
+ }
+
+ put_page(rx_page_info->page);
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ atomic_dec(&pnob->rx_q_posted);
+ }
+ return -ENOMEM;
+}
+
+static void process_nic_rx_completion_lro(struct be_net_object *pnob,
+ struct ETH_RX_COMPL_AMAP *rxcp)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME];
+ unsigned int udpcksm, tcpcksm;
+ u32 numfrags, vlanf, vtm, vlan_tag, nresid;
+ u16 vlant;
+ unsigned int fi, idx, n;
+ struct be_rx_page_info *rx_page_info;
+ u32 frag_sz = pnob->rx_buf_size, pktsize;
+ bool rx_coal = (adapter->max_rx_coal <= 1) ? 0 : 1;
+ u8 err, *va;
+ __wsum csum = 0;
+
+ if (AMAP_GET_BITS_PTR(ETH_RX_COMPL, ipsec, rxcp)) {
+ /* Drop the pkt and move to the next completion. */
+ adapter->be_stat.bes_rx_misc_pkts++;
+ return;
+ }
+ err = AMAP_GET_BITS_PTR(ETH_RX_COMPL, err, rxcp);
+ if (err || !rx_coal) {
+ /* We won't coalesce Rx pkts if the err bit set.
+ * take the path of normal completion processing */
+ process_nic_rx_completion(pnob, rxcp);
+ return;
+ }
+
+ fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp);
+ BUG_ON(fi >= (int)pnob->rx_q_len);
+ BUG_ON(fi < 0);
+ rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
+ BUG_ON(!rx_page_info->page);
+ pnob->rx_ctxt[fi] = (void *)NULL;
+ /* If one page is used per fragment or if this is the
+ * second half of the page, unmap the page here
+ */
+ if (rx_page_info->page_offset || !pnob->rx_pg_shared) {
+ pci_unmap_page(adapter->pdev,
+ pci_unmap_addr(rx_page_info, bus),
+ frag_sz, PCI_DMA_FROMDEVICE);
+ }
+
+ numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp);
+ udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp);
+ tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp);
+ vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp);
+ vlant = be16_to_cpu(vlan_tag);
+ vlanf = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp);
+ vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp);
+ pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp);
+
+ atomic_dec(&pnob->rx_q_posted);
+
+ if (tcpcksm && udpcksm && pktsize == 32) {
+ /* flush completion entries */
+ put_page(rx_page_info->page);
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ return;
+ }
+ /* Only one of udpcksum and tcpcksum can be set */
+ BUG_ON(udpcksm && tcpcksm);
+
+ /* jumbo frames could come in multiple fragments */
+ BUG_ON(numfrags != ((pktsize + (frag_sz - 1)) / frag_sz));
+ n = min(pktsize, frag_sz);
+ nresid = pktsize - n; /* will be useful for jumbo pkts */
+ idx = 0;
+
+ va = page_address(rx_page_info->page) + rx_page_info->page_offset;
+ prefetch(va);
+ rx_frags[idx].page = rx_page_info->page;
+ rx_frags[idx].page_offset = (rx_page_info->page_offset);
+ rx_frags[idx].size = n;
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+
+ /* If we got multiple fragments, we have more data. */
+ while (nresid) {
+ idx++;
+ index_inc(&fi, pnob->rx_q_len);
+
+ rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi];
+ pnob->rx_ctxt[fi] = (void *)NULL;
+ if (rx_page_info->page_offset || !pnob->rx_pg_shared) {
+ pci_unmap_page(adapter->pdev,
+ pci_unmap_addr(rx_page_info, bus),
+ frag_sz, PCI_DMA_FROMDEVICE);
+ }
+
+ n = min(nresid, frag_sz);
+ rx_frags[idx].page = rx_page_info->page;
+ rx_frags[idx].page_offset = (rx_page_info->page_offset);
+ rx_frags[idx].size = n;
+
+ nresid -= n;
+ memset(rx_page_info, 0, sizeof(struct be_rx_page_info));
+ atomic_dec(&pnob->rx_q_posted);
+ }
+
+ if (likely(!(vlanf && vtm))) {
+ lro_receive_frags(&pnob->lro_mgr, rx_frags,
+ pktsize, pktsize,
+ (void *)(unsigned long)csum, csum);
+ } else {
+ /* Vlan tag present in pkt and BE found
+ * that the tag matched an entry in VLAN table
+ */
+ if (unlikely(!pnob->vlan_grp || pnob->num_vlans == 0)) {
+ /* But we have no VLANs configured.
+ * This should never happen. Drop the packet.
+ */
+ dev_info(&pnob->netdev->dev,
+ "BladeEngine: Unexpected vlan tagged packet\n");
+ return;
+ }
+ /* pass the VLAN packet to stack */
+ lro_vlan_hwaccel_receive_frags(&pnob->lro_mgr,
+ rx_frags, pktsize, pktsize,
+ pnob->vlan_grp, vlant,
+ (void *)(unsigned long)csum,
+ csum);
+ }
+
+ adapter->be_stat.bes_rx_coal++;
+}
+
+struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *pnob)
+{
+ struct ETH_RX_COMPL_AMAP *rxcp = &pnob->rx_cq[pnob->rx_cq_tl];
+ u32 valid, ct;
+
+ valid = AMAP_GET_BITS_PTR(ETH_RX_COMPL, valid, rxcp);
+ if (valid == 0)
+ return NULL;
+
+ ct = AMAP_GET_BITS_PTR(ETH_RX_COMPL, ct, rxcp);
+ if (ct != 0) {
+ /* Invalid chute #. treat as error */
+ AMAP_SET_BITS_PTR(ETH_RX_COMPL, err, rxcp, 1);
+ }
+
+ be_adv_rxcq_tl(pnob);
+ AMAP_SET_BITS_PTR(ETH_RX_COMPL, valid, rxcp, 0);
+ return rxcp;
+}
+
+static void update_rx_rate(struct be_adapter *adapter)
+{
+ /* update the rate once in two seconds */
+ if ((jiffies - adapter->eth_rx_jiffies) > 2 * (HZ)) {
+ u32 r;
+ r = adapter->eth_rx_bytes /
+ ((jiffies - adapter->eth_rx_jiffies) / (HZ));
+ r = (r / 1000000); /* MB/Sec */
+
+ /* Mega Bits/Sec */
+ adapter->be_stat.bes_eth_rx_rate = (r * 8);
+ adapter->eth_rx_jiffies = jiffies;
+ adapter->eth_rx_bytes = 0;
+ }
+}
+
+static int process_rx_completions(struct be_net_object *pnob, int max_work)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ struct ETH_RX_COMPL_AMAP *rxcp;
+ u32 nc = 0;
+ unsigned int pktsize;
+
+ while (max_work && (rxcp = be_get_rx_cmpl(pnob))) {
+ prefetch(rxcp);
+ pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp);
+ process_nic_rx_completion_lro(pnob, rxcp);
+ adapter->eth_rx_bytes += pktsize;
+ update_rx_rate(adapter);
+ nc++;
+ max_work--;
+ adapter->be_stat.bes_rx_compl++;
+ }
+ if (likely(adapter->max_rx_coal > 1)) {
+ adapter->be_stat.bes_rx_flush++;
+ lro_flush_all(&pnob->lro_mgr);
+ }
+
+ /* Refill the queue */
+ if (atomic_read(&pnob->rx_q_posted) < 900)
+ be_post_eth_rx_buffs(pnob);
+
+ return nc;
+}
+
+static struct ETH_TX_COMPL_AMAP *be_get_tx_cmpl(struct be_net_object *pnob)
+{
+ struct ETH_TX_COMPL_AMAP *txcp = &pnob->tx_cq[pnob->tx_cq_tl];
+ u32 valid;
+
+ valid = AMAP_GET_BITS_PTR(ETH_TX_COMPL, valid, txcp);
+ if (valid == 0)
+ return NULL;
+
+ AMAP_SET_BITS_PTR(ETH_TX_COMPL, valid, txcp, 0);
+ be_adv_txcq_tl(pnob);
+ return txcp;
+
+}
+
+void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ int cur_index, tx_wrbs_completed = 0;
+ struct sk_buff *skb;
+ u64 busaddr, pa, pa_lo, pa_hi;
+ struct ETH_WRB_AMAP *wrb;
+ u32 frag_len, last_index, j;
+
+ last_index = tx_compl_lastwrb_idx_get(pnob);
+ BUG_ON(last_index != end_idx);
+ pnob->tx_ctxt[pnob->tx_q_tl] = NULL;
+ do {
+ cur_index = pnob->tx_q_tl;
+ wrb = &pnob->tx_q[cur_index];
+ pa_hi = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb);
+ pa_lo = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb);
+ frag_len = AMAP_GET_BITS_PTR(ETH_WRB, frag_len, wrb);
+ busaddr = (pa_hi << 32) | pa_lo;
+ if (busaddr != 0) {
+ pa = le64_to_cpu(busaddr);
+ pci_unmap_single(adapter->pdev, pa,
+ frag_len, PCI_DMA_TODEVICE);
+ }
+ if (cur_index == last_index) {
+ skb = (struct sk_buff *)pnob->tx_ctxt[cur_index];
+ BUG_ON(!skb);
+ for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) {
+ struct skb_frag_struct *frag;
+ frag = &skb_shinfo(skb)->frags[j];
+ pci_unmap_page(adapter->pdev,
+ (ulong) frag->page, frag->size,
+ PCI_DMA_TODEVICE);
+ }
+ kfree_skb(skb);
+ pnob->tx_ctxt[cur_index] = NULL;
+ } else {
+ BUG_ON(pnob->tx_ctxt[cur_index]);
+ }
+ tx_wrbs_completed++;
+ be_adv_txq_tl(pnob);
+ } while (cur_index != last_index);
+ atomic_sub(tx_wrbs_completed, &pnob->tx_q_used);
+}
+
+/* there is no need to take an SMP lock here since currently
+ * we have only one instance of the tasklet that does completion
+ * processing.
+ */
+static void process_nic_tx_completions(struct be_net_object *pnob)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ struct ETH_TX_COMPL_AMAP *txcp;
+ struct net_device *netdev = pnob->netdev;
+ u32 end_idx, num_processed = 0;
+
+ adapter->be_stat.bes_tx_events++;
+
+ while ((txcp = be_get_tx_cmpl(pnob))) {
+ end_idx = AMAP_GET_BITS_PTR(ETH_TX_COMPL, wrb_index, txcp);
+ process_one_tx_compl(pnob, end_idx);
+ num_processed++;
+ adapter->be_stat.bes_tx_compl++;
+ }
+ be_notify_cmpl(pnob, num_processed, pnob->tx_cq_id, 1);
+ /*
+ * We got Tx completions and have usable WRBs.
+ * If the netdev's queue has been stopped
+ * because we had run out of WRBs, wake it now.
+ */
+ spin_lock(&adapter->txq_lock);
+ if (netif_queue_stopped(netdev)
+ && atomic_read(&pnob->tx_q_used) < pnob->tx_q_len / 2) {
+ netif_wake_queue(netdev);
+ }
+ spin_unlock(&adapter->txq_lock);
+}
+
+static u32 post_rx_buffs(struct be_net_object *pnob, struct list_head *rxbl)
+{
+ u32 nposted = 0;
+ struct ETH_RX_D_AMAP *rxd = NULL;
+ struct be_recv_buffer *rxbp;
+ void **rx_ctxp;
+ struct RQ_DB_AMAP rqdb;
+
+ rx_ctxp = pnob->rx_ctxt;
+
+ while (!list_empty(rxbl) &&
+ (rx_ctxp[pnob->rx_q_hd] == NULL) && nposted < 255) {
+
+ rxbp = list_first_entry(rxbl, struct be_recv_buffer, rxb_list);
+ list_del(&rxbp->rxb_list);
+ rxd = pnob->rx_q + pnob->rx_q_hd;
+ AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_lo, rxd, rxbp->rxb_pa_lo);
+ AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_hi, rxd, rxbp->rxb_pa_hi);
+
+ rx_ctxp[pnob->rx_q_hd] = rxbp->rxb_ctxt;
+ be_adv_rxq_hd(pnob);
+ nposted++;
+ }
+
+ if (nposted) {
+ /* Now press the door bell to notify BladeEngine. */
+ rqdb.dw[0] = 0;
+ AMAP_SET_BITS_PTR(RQ_DB, numPosted, &rqdb, nposted);
+ AMAP_SET_BITS_PTR(RQ_DB, rq, &rqdb, pnob->rx_q_id);
+ PD_WRITE(&pnob->fn_obj, erx_rq_db, rqdb.dw[0]);
+ }
+ atomic_add(nposted, &pnob->rx_q_posted);
+ return nposted;
+}
+
+void be_post_eth_rx_buffs(struct be_net_object *pnob)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ u32 num_bufs, r;
+ u64 busaddr = 0, tmp_pa;
+ u32 max_bufs, pg_hd;
+ u32 frag_size;
+ struct be_recv_buffer *rxbp;
+ struct list_head rxbl;
+ struct be_rx_page_info *rx_page_info;
+ struct page *page = NULL;
+ u32 page_order = 0;
+ gfp_t alloc_flags = GFP_ATOMIC;
+
+ BUG_ON(!adapter);
+
+ max_bufs = 64; /* should be even # <= 255. */
+
+ frag_size = pnob->rx_buf_size;
+ page_order = get_order(frag_size);
+
+ if (frag_size == 8192)
+ alloc_flags |= (gfp_t) __GFP_COMP;
+ /*
+ * Form a linked list of RECV_BUFFFER structure to be be posted.
+ * We will post even number of buffer so that pages can be
+ * shared.
+ */
+ INIT_LIST_HEAD(&rxbl);
+
+ for (num_bufs = 0; num_bufs < max_bufs &&
+ !pnob->rx_page_info[pnob->rx_pg_info_hd].page; ++num_bufs) {
+
+ rxbp = &pnob->eth_rx_bufs[num_bufs];
+ pg_hd = pnob->rx_pg_info_hd;
+ rx_page_info = &pnob->rx_page_info[pg_hd];
+
+ if (!page) {
+ page = alloc_pages(alloc_flags, page_order);
+ if (unlikely(page == NULL)) {
+ adapter->be_stat.bes_ethrx_post_fail++;
+ pnob->rxbuf_post_fail++;
+ break;
+ }
+ pnob->rxbuf_post_fail = 0;
+ busaddr = pci_map_page(adapter->pdev, page, 0,
+ frag_size, PCI_DMA_FROMDEVICE);
+ rx_page_info->page_offset = 0;
+ rx_page_info->page = page;
+ /*
+ * If we are sharing a page among two skbs,
+ * alloc a new one on the next iteration
+ */
+ if (pnob->rx_pg_shared == false)
+ page = NULL;
+ } else {
+ get_page(page);
+ rx_page_info->page_offset += frag_size;
+ rx_page_info->page = page;
+ /*
+ * We are finished with the alloced page,
+ * Alloc a new one on the next iteration
+ */
+ page = NULL;
+ }
+ rxbp->rxb_ctxt = (void *)rx_page_info;
+ index_inc(&pnob->rx_pg_info_hd, pnob->rx_q_len);
+
+ pci_unmap_addr_set(rx_page_info, bus, busaddr);
+ tmp_pa = busaddr + rx_page_info->page_offset;
+ rxbp->rxb_pa_lo = (tmp_pa & 0xFFFFFFFF);
+ rxbp->rxb_pa_hi = (tmp_pa >> 32);
+ rxbp->rxb_len = frag_size;
+ list_add_tail(&rxbp->rxb_list, &rxbl);
+ } /* End of for */
+
+ r = post_rx_buffs(pnob, &rxbl);
+ BUG_ON(r != num_bufs);
+ return;
+}
+
+/*
+ * Interrupt service for network function. We just schedule the
+ * tasklet which does all completion processing.
+ */
+irqreturn_t be_int(int irq, void *dev)
+{
+ struct net_device *netdev = dev;
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+ u32 isr;
+
+ isr = CSR_READ(&pnob->fn_obj, cev.isr1);
+ if (unlikely(!isr))
+ return IRQ_NONE;
+
+ spin_lock(&adapter->int_lock);
+ adapter->isr |= isr;
+ spin_unlock(&adapter->int_lock);
+
+ adapter->be_stat.bes_ints++;
+
+ tasklet_schedule(&adapter->sts_handler);
+ return IRQ_HANDLED;
+}
+
+/*
+ * Poll function called by NAPI with a work budget.
+ * We process as many UC. BC and MC receive completions
+ * as the budget allows and return the actual number of
+ * RX ststutses processed.
+ */
+int be_poll(struct napi_struct *napi, int budget)
+{
+ struct be_net_object *pnob =
+ container_of(napi, struct be_net_object, napi);
+ u32 work_done;
+
+ pnob->adapter->be_stat.bes_polls++;
+ work_done = process_rx_completions(pnob, budget);
+ BUG_ON(work_done > budget);
+
+ /* All consumed */
+ if (work_done < budget) {
+ netif_rx_complete(napi);
+ /* enable intr */
+ be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 1);
+ } else {
+ /* More to be consumed; continue with interrupts disabled */
+ be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 0);
+ }
+ return work_done;
+}
+
+static struct EQ_ENTRY_AMAP *get_event(struct be_net_object *pnob)
+{
+ struct EQ_ENTRY_AMAP *eqp = &(pnob->event_q[pnob->event_q_tl]);
+ if (!AMAP_GET_BITS_PTR(EQ_ENTRY, Valid, eqp))
+ return NULL;
+ be_adv_eq_tl(pnob);
+ return eqp;
+}
+
+/*
+ * Processes all valid events in the event ring associated with given
+ * NetObject. Also, notifies BE the number of events processed.
+ */
+static inline u32 process_events(struct be_net_object *pnob)
+{
+ struct be_adapter *adapter = pnob->adapter;
+ struct EQ_ENTRY_AMAP *eqp;
+ u32 rid, num_events = 0;
+ struct net_device *netdev = pnob->netdev;
+
+ while ((eqp = get_event(pnob)) != NULL) {
+ adapter->be_stat.bes_events++;
+ rid = AMAP_GET_BITS_PTR(EQ_ENTRY, ResourceID, eqp);
+ if (rid == pnob->rx_cq_id) {
+ adapter->be_stat.bes_rx_events++;
+ netif_rx_schedule(&pnob->napi);
+ } else if (rid == pnob->tx_cq_id) {
+ process_nic_tx_completions(pnob);
+ } else if (rid == pnob->mcc_cq_id) {
+ be_mcc_process_cq(&pnob->mcc_q_obj, 1);
+ } else {
+ dev_info(&netdev->dev,
+ "Invalid EQ ResourceID %d\n", rid);
+ }
+ AMAP_SET_BITS_PTR(EQ_ENTRY, Valid, eqp, 0);
+ AMAP_SET_BITS_PTR(EQ_ENTRY, ResourceID, eqp, 0);
+ num_events++;
+ }
+ return num_events;
+}
+
+static void update_eqd(struct be_adapter *adapter, struct be_net_object *pnob)
+{
+ int status;
+ struct be_eq_object *eq_objectp;
+
+ /* update once a second */
+ if ((jiffies - adapter->ips_jiffies) > 1 * (HZ)) {
+ /* One second elapsed since last update */
+ u32 r, new_eqd = -1;
+ r = adapter->be_stat.bes_ints - adapter->be_stat.bes_prev_ints;
+ r = r / ((jiffies - adapter->ips_jiffies) / (HZ));
+ adapter->be_stat.bes_ips = r;
+ adapter->ips_jiffies = jiffies;
+ adapter->be_stat.bes_prev_ints = adapter->be_stat.bes_ints;
+ if (r > IPS_HI_WM && adapter->cur_eqd < adapter->max_eqd)
+ new_eqd = (adapter->cur_eqd + 8);
+ if (r < IPS_LO_WM && adapter->cur_eqd > adapter->min_eqd)
+ new_eqd = (adapter->cur_eqd - 8);
+ if (adapter->enable_aic && new_eqd != -1) {
+ eq_objectp = &pnob->event_q_obj;
+ status = be_eq_modify_delay(&pnob->fn_obj, 1,
+ &eq_objectp, &new_eqd, NULL,
+ NULL, NULL);
+ if (status == BE_SUCCESS)
+ adapter->cur_eqd = new_eqd;
+ }
+ }
+}
+
+/*
+ This function notifies BladeEngine of how many events were processed
+ from the event queue by ringing the corresponding door bell and
+ optionally re-arms the event queue.
+ n - number of events processed
+ re_arm - 1 - re-arm the EQ, 0 - do not re-arm the EQ
+
+*/
+static void be_notify_event(struct be_net_object *pnob, int n, int re_arm)
+{
+ struct CQ_DB_AMAP eqdb;
+ eqdb.dw[0] = 0;
+
+ AMAP_SET_BITS_PTR(CQ_DB, qid, &eqdb, pnob->event_q_id);
+ AMAP_SET_BITS_PTR(CQ_DB, rearm, &eqdb, re_arm);
+ AMAP_SET_BITS_PTR(CQ_DB, event, &eqdb, 1);
+ AMAP_SET_BITS_PTR(CQ_DB, num_popped, &eqdb, n);
+ /*
+ * Under some situations we see an interrupt and no valid
+ * EQ entry. To keep going, we need to ring the DB even if
+ * numPOsted is 0.
+ */
+ PD_WRITE(&pnob->fn_obj, cq_db, eqdb.dw[0]);
+ return;
+}
+
+/*
+ * Called from the tasklet scheduled by ISR. All real interrupt processing
+ * is done here.
+ */
+void be_process_intr(unsigned long context)
+{
+ struct be_adapter *adapter = (struct be_adapter *)context;
+ struct be_net_object *pnob = adapter->net_obj;
+ u32 isr, n;
+ ulong flags = 0;
+
+ isr = adapter->isr;
+
+ /*
+ * we create only one NIC event queue in Linux. Event is
+ * expected only in the first event queue
+ */
+ BUG_ON(isr & 0xfffffffe);
+ if ((isr & 1) == 0)
+ return; /* not our interrupt */
+ n = process_events(pnob);
+ /*
+ * Clear the event bit. adapter->isr is set by
+ * hard interrupt. Prevent race with lock.
+ */
+ spin_lock_irqsave(&adapter->int_lock, flags);
+ adapter->isr &= ~1;
+ spin_unlock_irqrestore(&adapter->int_lock, flags);
+ be_notify_event(pnob, n, 1);
+ /*
+ * If previous allocation attempts had failed and
+ * BE has used up all posted buffers, post RX buffers here
+ */
+ if (pnob->rxbuf_post_fail && atomic_read(&pnob->rx_q_posted) == 0)
+ be_post_eth_rx_buffs(pnob);
+ update_eqd(adapter, pnob);
+ return;
+}
diff --git a/drivers/staging/benet/be_netif.c b/drivers/staging/benet/be_netif.c
new file mode 100644
index 000000000000..2b8daf63dc7d
--- /dev/null
+++ b/drivers/staging/benet/be_netif.c
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * be_netif.c
+ *
+ * This file contains various entry points of drivers seen by tcp/ip stack.
+ */
+
+#include <linux/if_vlan.h>
+#include <linux/in.h>
+#include "benet.h"
+#include <linux/ip.h>
+#include <linux/inet_lro.h>
+
+/* Strings to print Link properties */
+static const char *link_speed[] = {
+ "Invalid link Speed Value",
+ "10 Mbps",
+ "100 Mbps",
+ "1 Gbps",
+ "10 Gbps"
+};
+
+static const char *link_duplex[] = {
+ "Invalid Duplex Value",
+ "Half Duplex",
+ "Full Duplex"
+};
+
+static const char *link_state[] = {
+ "",
+ "(active)"
+};
+
+void be_print_link_info(struct BE_LINK_STATUS *lnk_status)
+{
+ u16 si, di, ai;
+
+ /* Port 0 */
+ if (lnk_status->mac0_speed && lnk_status->mac0_duplex) {
+ /* Port is up and running */
+ si = (lnk_status->mac0_speed < 5) ? lnk_status->mac0_speed : 0;
+ di = (lnk_status->mac0_duplex < 3) ?
+ lnk_status->mac0_duplex : 0;
+ ai = (lnk_status->active_port == 0) ? 1 : 0;
+ printk(KERN_INFO "PortNo. 0: Speed - %s %s %s\n",
+ link_speed[si], link_duplex[di], link_state[ai]);
+ } else
+ printk(KERN_INFO "PortNo. 0: Down\n");
+
+ /* Port 1 */
+ if (lnk_status->mac1_speed && lnk_status->mac1_duplex) {
+ /* Port is up and running */
+ si = (lnk_status->mac1_speed < 5) ? lnk_status->mac1_speed : 0;
+ di = (lnk_status->mac1_duplex < 3) ?
+ lnk_status->mac1_duplex : 0;
+ ai = (lnk_status->active_port == 0) ? 1 : 0;
+ printk(KERN_INFO "PortNo. 1: Speed - %s %s %s\n",
+ link_speed[si], link_duplex[di], link_state[ai]);
+ } else
+ printk(KERN_INFO "PortNo. 1: Down\n");
+
+ return;
+}
+
+static int
+be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
+ void **ip_hdr, void **tcpudp_hdr,
+ u64 *hdr_flags, void *priv)
+{
+ struct ethhdr *eh;
+ struct vlan_ethhdr *veh;
+ struct iphdr *iph;
+ u8 *va = page_address(frag->page) + frag->page_offset;
+ unsigned long ll_hlen;
+
+ /* find the mac header, abort if not IPv4 */
+
+ prefetch(va);
+ eh = (struct ethhdr *)va;
+ *mac_hdr = eh;
+ ll_hlen = ETH_HLEN;
+ if (eh->h_proto != htons(ETH_P_IP)) {
+ if (eh->h_proto == htons(ETH_P_8021Q)) {
+ veh = (struct vlan_ethhdr *)va;
+ if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
+ return -1;
+
+ ll_hlen += VLAN_HLEN;
+
+ } else {
+ return -1;
+ }
+ }
+ *hdr_flags = LRO_IPV4;
+
+ iph = (struct iphdr *)(va + ll_hlen);
+ *ip_hdr = iph;
+ if (iph->protocol != IPPROTO_TCP)
+ return -1;
+ *hdr_flags |= LRO_TCP;
+ *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
+
+ return 0;
+}
+
+static int benet_open(struct net_device *netdev)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+ struct net_lro_mgr *lro_mgr;
+
+ if (adapter->dev_state < BE_DEV_STATE_INIT)
+ return -EAGAIN;
+
+ lro_mgr = &pnob->lro_mgr;
+ lro_mgr->dev = netdev;
+
+ lro_mgr->features = LRO_F_NAPI;
+ lro_mgr->ip_summed = CHECKSUM_UNNECESSARY;
+ lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
+ lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS;
+ lro_mgr->lro_arr = pnob->lro_desc;
+ lro_mgr->get_frag_header = be_get_frag_header;
+ lro_mgr->max_aggr = adapter->max_rx_coal;
+ lro_mgr->frag_align_pad = 2;
+ if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
+ lro_mgr->max_aggr = MAX_SKB_FRAGS;
+
+ adapter->max_rx_coal = BE_LRO_MAX_PKTS;
+
+ be_update_link_status(adapter);
+
+ /*
+ * Set carrier on only if Physical Link up
+ * Either of the port link status up signifies this
+ */
+ if ((adapter->port0_link_sts == BE_PORT_LINK_UP) ||
+ (adapter->port1_link_sts == BE_PORT_LINK_UP)) {
+ netif_start_queue(netdev);
+ netif_carrier_on(netdev);
+ }
+
+ adapter->dev_state = BE_DEV_STATE_OPEN;
+ napi_enable(&pnob->napi);
+ be_enable_intr(pnob);
+ be_enable_eq_intr(pnob);
+ /*
+ * RX completion queue may be in dis-armed state. Arm it.
+ */
+ be_notify_cmpl(pnob, 0, pnob->rx_cq_id, 1);
+
+ return 0;
+}
+
+static int benet_close(struct net_device *netdev)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+
+ netif_stop_queue(netdev);
+ synchronize_irq(netdev->irq);
+
+ be_wait_nic_tx_cmplx_cmpl(pnob);
+ adapter->dev_state = BE_DEV_STATE_INIT;
+ netif_carrier_off(netdev);
+
+ adapter->port0_link_sts = BE_PORT_LINK_DOWN;
+ adapter->port1_link_sts = BE_PORT_LINK_DOWN;
+ be_disable_intr(pnob);
+ be_disable_eq_intr(pnob);
+ napi_disable(&pnob->napi);
+
+ return 0;
+}
+
+/*
+ * Setting a Mac Address for BE
+ * Takes netdev and a void pointer as arguments.
+ * The pointer holds the new addres to be used.
+ */
+static int benet_set_mac_addr(struct net_device *netdev, void *p)
+{
+ struct sockaddr *addr = p;
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+ be_rxf_mac_address_read_write(&pnob->fn_obj, 0, 0, false, true, false,
+ netdev->dev_addr, NULL, NULL);
+ /*
+ * Since we are doing Active-Passive failover, both
+ * ports should have matching MAC addresses everytime.
+ */
+ be_rxf_mac_address_read_write(&pnob->fn_obj, 1, 0, false, true, false,
+ netdev->dev_addr, NULL, NULL);
+
+ return 0;
+}
+
+void be_get_stats_timer_handler(unsigned long context)
+{
+ struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context;
+
+ if (atomic_read(&ctxt->get_stat_flag)) {
+ atomic_dec(&ctxt->get_stat_flag);
+ up((void *)ctxt->get_stat_sem_addr);
+ }
+ del_timer(&ctxt->get_stats_timer);
+ return;
+}
+
+void be_get_stat_cb(void *context, int status,
+ struct MCC_WRB_AMAP *optional_wrb)
+{
+ struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context;
+ /*
+ * just up the semaphore if the get_stat_flag
+ * reads 1. so that the waiter can continue.
+ * If it is 0, then it was handled by the timer handler.
+ */
+ del_timer(&ctxt->get_stats_timer);
+ if (atomic_read(&ctxt->get_stat_flag)) {
+ atomic_dec(&ctxt->get_stat_flag);
+ up((void *)ctxt->get_stat_sem_addr);
+ }
+}
+
+struct net_device_stats *benet_get_stats(struct net_device *dev)
+{
+ struct be_net_object *pnob = netdev_priv(dev);
+ struct be_adapter *adapter = pnob->adapter;
+ u64 pa;
+ struct be_timer_ctxt *ctxt = &adapter->timer_ctxt;
+
+ if (adapter->dev_state != BE_DEV_STATE_OPEN) {
+ /* Return previously read stats */
+ return &(adapter->benet_stats);
+ }
+ /* Get Physical Addr */
+ pa = pci_map_single(adapter->pdev, adapter->eth_statsp,
+ sizeof(struct FWCMD_ETH_GET_STATISTICS),
+ PCI_DMA_FROMDEVICE);
+ ctxt->get_stat_sem_addr = (unsigned long)&adapter->get_eth_stat_sem;
+ atomic_inc(&ctxt->get_stat_flag);
+
+ be_rxf_query_eth_statistics(&pnob->fn_obj, adapter->eth_statsp,
+ cpu_to_le64(pa), be_get_stat_cb, ctxt,
+ NULL);
+
+ ctxt->get_stats_timer.data = (unsigned long)ctxt;
+ mod_timer(&ctxt->get_stats_timer, (jiffies + (HZ * 2)));
+ down((void *)ctxt->get_stat_sem_addr); /* callback will unblock us */
+
+ /* Adding port0 and port1 stats. */
+ adapter->benet_stats.rx_packets =
+ adapter->eth_statsp->params.response.p0recvdtotalframes +
+ adapter->eth_statsp->params.response.p1recvdtotalframes;
+ adapter->benet_stats.tx_packets =
+ adapter->eth_statsp->params.response.p0xmitunicastframes +
+ adapter->eth_statsp->params.response.p1xmitunicastframes;
+ adapter->benet_stats.tx_bytes =
+ adapter->eth_statsp->params.response.p0xmitbyteslsd +
+ adapter->eth_statsp->params.response.p1xmitbyteslsd;
+ adapter->benet_stats.rx_errors =
+ adapter->eth_statsp->params.response.p0crcerrors +
+ adapter->eth_statsp->params.response.p1crcerrors;
+ adapter->benet_stats.rx_errors +=
+ adapter->eth_statsp->params.response.p0alignmentsymerrs +
+ adapter->eth_statsp->params.response.p1alignmentsymerrs;
+ adapter->benet_stats.rx_errors +=
+ adapter->eth_statsp->params.response.p0inrangelenerrors +
+ adapter->eth_statsp->params.response.p1inrangelenerrors;
+ adapter->benet_stats.rx_bytes =
+ adapter->eth_statsp->params.response.p0recvdtotalbytesLSD +
+ adapter->eth_statsp->params.response.p1recvdtotalbytesLSD;
+ adapter->benet_stats.rx_crc_errors =
+ adapter->eth_statsp->params.response.p0crcerrors +
+ adapter->eth_statsp->params.response.p1crcerrors;
+
+ adapter->benet_stats.tx_packets +=
+ adapter->eth_statsp->params.response.p0xmitmulticastframes +
+ adapter->eth_statsp->params.response.p1xmitmulticastframes;
+ adapter->benet_stats.tx_packets +=
+ adapter->eth_statsp->params.response.p0xmitbroadcastframes +
+ adapter->eth_statsp->params.response.p1xmitbroadcastframes;
+ adapter->benet_stats.tx_errors = 0;
+
+ adapter->benet_stats.multicast =
+ adapter->eth_statsp->params.response.p0xmitmulticastframes +
+ adapter->eth_statsp->params.response.p1xmitmulticastframes;
+
+ adapter->benet_stats.rx_fifo_errors =
+ adapter->eth_statsp->params.response.p0rxfifooverflowdropped +
+ adapter->eth_statsp->params.response.p1rxfifooverflowdropped;
+ adapter->benet_stats.rx_frame_errors =
+ adapter->eth_statsp->params.response.p0alignmentsymerrs +
+ adapter->eth_statsp->params.response.p1alignmentsymerrs;
+ adapter->benet_stats.rx_length_errors =
+ adapter->eth_statsp->params.response.p0inrangelenerrors +
+ adapter->eth_statsp->params.response.p1inrangelenerrors;
+ adapter->benet_stats.rx_length_errors +=
+ adapter->eth_statsp->params.response.p0outrangeerrors +
+ adapter->eth_statsp->params.response.p1outrangeerrors;
+ adapter->benet_stats.rx_length_errors +=
+ adapter->eth_statsp->params.response.p0frametoolongerrors +
+ adapter->eth_statsp->params.response.p1frametoolongerrors;
+
+ pci_unmap_single(adapter->pdev, (ulong) adapter->eth_statsp,
+ sizeof(struct FWCMD_ETH_GET_STATISTICS),
+ PCI_DMA_FROMDEVICE);
+ return &(adapter->benet_stats);
+
+}
+
+static void be_start_tx(struct be_net_object *pnob, u32 nposted)
+{
+#define CSR_ETH_MAX_SQPOSTS 255
+ struct SQ_DB_AMAP sqdb;
+
+ sqdb.dw[0] = 0;
+
+ AMAP_SET_BITS_PTR(SQ_DB, cid, &sqdb, pnob->tx_q_id);
+ while (nposted) {
+ if (nposted > CSR_ETH_MAX_SQPOSTS) {
+ AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb,
+ CSR_ETH_MAX_SQPOSTS);
+ nposted -= CSR_ETH_MAX_SQPOSTS;
+ } else {
+ AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, nposted);
+ nposted = 0;
+ }
+ PD_WRITE(&pnob->fn_obj, etx_sq_db, sqdb.dw[0]);
+ }
+
+ return;
+}
+
+static void update_tx_rate(struct be_adapter *adapter)
+{
+ /* update the rate once in two seconds */
+ if ((jiffies - adapter->eth_tx_jiffies) > 2 * (HZ)) {
+ u32 r;
+ r = adapter->eth_tx_bytes /
+ ((jiffies - adapter->eth_tx_jiffies) / (HZ));
+ r = (r / 1000000); /* M bytes/s */
+ adapter->be_stat.bes_eth_tx_rate = (r * 8); /* M bits/s */
+ adapter->eth_tx_jiffies = jiffies;
+ adapter->eth_tx_bytes = 0;
+ }
+}
+
+static int wrb_cnt_in_skb(struct sk_buff *skb)
+{
+ int cnt = 0;
+ while (skb) {
+ if (skb->len > skb->data_len)
+ cnt++;
+ cnt += skb_shinfo(skb)->nr_frags;
+ skb = skb_shinfo(skb)->frag_list;
+ }
+ BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT);
+ return cnt;
+}
+
+static void wrb_fill(struct ETH_WRB_AMAP *wrb, u64 addr, int len)
+{
+ AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb, addr >> 32);
+ AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb, addr & 0xFFFFFFFF);
+ AMAP_SET_BITS_PTR(ETH_WRB, frag_len, wrb, len);
+}
+
+static void wrb_fill_extra(struct ETH_WRB_AMAP *wrb, struct sk_buff *skb,
+ struct be_net_object *pnob)
+{
+ wrb->dw[2] = 0;
+ wrb->dw[3] = 0;
+ AMAP_SET_BITS_PTR(ETH_WRB, crc, wrb, 1);
+ if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) {
+ AMAP_SET_BITS_PTR(ETH_WRB, lso, wrb, 1);
+ AMAP_SET_BITS_PTR(ETH_WRB, lso_mss, wrb,
+ skb_shinfo(skb)->gso_size);
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ u8 proto = ((struct iphdr *)ip_hdr(skb))->protocol;
+ if (proto == IPPROTO_TCP)
+ AMAP_SET_BITS_PTR(ETH_WRB, tcpcs, wrb, 1);
+ else if (proto == IPPROTO_UDP)
+ AMAP_SET_BITS_PTR(ETH_WRB, udpcs, wrb, 1);
+ }
+ if (pnob->vlan_grp && vlan_tx_tag_present(skb)) {
+ AMAP_SET_BITS_PTR(ETH_WRB, vlan, wrb, 1);
+ AMAP_SET_BITS_PTR(ETH_WRB, vlan_tag, wrb, vlan_tx_tag_get(skb));
+ }
+}
+
+static inline void wrb_copy_extra(struct ETH_WRB_AMAP *to,
+ struct ETH_WRB_AMAP *from)
+{
+
+ to->dw[2] = from->dw[2];
+ to->dw[3] = from->dw[3];
+}
+
+/* Returns the actual count of wrbs used including a possible dummy */
+static int copy_skb_to_txq(struct be_net_object *pnob, struct sk_buff *skb,
+ u32 wrb_cnt, u32 *copied)
+{
+ u64 busaddr;
+ struct ETH_WRB_AMAP *wrb = NULL, *first = NULL;
+ u32 i;
+ bool dummy = true;
+ struct pci_dev *pdev = pnob->adapter->pdev;
+
+ if (wrb_cnt & 1)
+ wrb_cnt++;
+ else
+ dummy = false;
+
+ atomic_add(wrb_cnt, &pnob->tx_q_used);
+
+ while (skb) {
+ if (skb->len > skb->data_len) {
+ int len = skb->len - skb->data_len;
+ busaddr = pci_map_single(pdev, skb->data, len,
+ PCI_DMA_TODEVICE);
+ busaddr = cpu_to_le64(busaddr);
+ wrb = &pnob->tx_q[pnob->tx_q_hd];
+ if (first == NULL) {
+ wrb_fill_extra(wrb, skb, pnob);
+ first = wrb;
+ } else {
+ wrb_copy_extra(wrb, first);
+ }
+ wrb_fill(wrb, busaddr, len);
+ be_adv_txq_hd(pnob);
+ *copied += len;
+ }
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ struct skb_frag_struct *frag =
+ &skb_shinfo(skb)->frags[i];
+ busaddr = pci_map_page(pdev, frag->page,
+ frag->page_offset, frag->size,
+ PCI_DMA_TODEVICE);
+ busaddr = cpu_to_le64(busaddr);
+ wrb = &pnob->tx_q[pnob->tx_q_hd];
+ if (first == NULL) {
+ wrb_fill_extra(wrb, skb, pnob);
+ first = wrb;
+ } else {
+ wrb_copy_extra(wrb, first);
+ }
+ wrb_fill(wrb, busaddr, frag->size);
+ be_adv_txq_hd(pnob);
+ *copied += frag->size;
+ }
+ skb = skb_shinfo(skb)->frag_list;
+ }
+
+ if (dummy) {
+ wrb = &pnob->tx_q[pnob->tx_q_hd];
+ BUG_ON(first == NULL);
+ wrb_copy_extra(wrb, first);
+ wrb_fill(wrb, 0, 0);
+ be_adv_txq_hd(pnob);
+ }
+ AMAP_SET_BITS_PTR(ETH_WRB, complete, wrb, 1);
+ AMAP_SET_BITS_PTR(ETH_WRB, last, wrb, 1);
+ return wrb_cnt;
+}
+
+/* For each skb transmitted, tx_ctxt stores the num of wrbs in the
+ * start index and skb pointer in the end index
+ */
+static inline void be_tx_wrb_info_remember(struct be_net_object *pnob,
+ struct sk_buff *skb, int wrb_cnt,
+ u32 start)
+{
+ *(u32 *) (&pnob->tx_ctxt[start]) = wrb_cnt;
+ index_adv(&start, wrb_cnt - 1, pnob->tx_q_len);
+ pnob->tx_ctxt[start] = skb;
+}
+
+static int benet_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+ u32 wrb_cnt, copied = 0;
+ u32 start = pnob->tx_q_hd;
+
+ adapter->be_stat.bes_tx_reqs++;
+
+ wrb_cnt = wrb_cnt_in_skb(skb);
+ spin_lock_bh(&adapter->txq_lock);
+ if ((pnob->tx_q_len - 2 - atomic_read(&pnob->tx_q_used)) <= wrb_cnt) {
+ netif_stop_queue(pnob->netdev);
+ spin_unlock_bh(&adapter->txq_lock);
+ adapter->be_stat.bes_tx_fails++;
+ return NETDEV_TX_BUSY;
+ }
+ spin_unlock_bh(&adapter->txq_lock);
+
+ wrb_cnt = copy_skb_to_txq(pnob, skb, wrb_cnt, &copied);
+ be_tx_wrb_info_remember(pnob, skb, wrb_cnt, start);
+
+ be_start_tx(pnob, wrb_cnt);
+
+ adapter->eth_tx_bytes += copied;
+ adapter->be_stat.bes_tx_wrbs += wrb_cnt;
+ update_tx_rate(adapter);
+ netdev->trans_start = jiffies;
+
+ return NETDEV_TX_OK;
+}
+
+/*
+ * This is the driver entry point to change the mtu of the device
+ * Returns 0 for success and errno for failure.
+ */
+static int benet_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ /*
+ * BE supports jumbo frame size upto 9000 bytes including the link layer
+ * header. Considering the different variants of frame formats possible
+ * like VLAN, SNAP/LLC, the maximum possible value for MTU is 8974 bytes
+ */
+
+ if (new_mtu < (ETH_ZLEN + ETH_FCS_LEN) || (new_mtu > BE_MAX_MTU)) {
+ dev_info(&netdev->dev, "Invalid MTU requested. "
+ "Must be between %d and %d bytes\n",
+ (ETH_ZLEN + ETH_FCS_LEN), BE_MAX_MTU);
+ return -EINVAL;
+ }
+ dev_info(&netdev->dev, "MTU changed from %d to %d\n",
+ netdev->mtu, new_mtu);
+ netdev->mtu = new_mtu;
+ return 0;
+}
+
+/*
+ * This is the driver entry point to register a vlan with the device
+ */
+static void benet_vlan_register(struct net_device *netdev,
+ struct vlan_group *grp)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ be_disable_eq_intr(pnob);
+ pnob->vlan_grp = grp;
+ pnob->num_vlans = 0;
+ be_enable_eq_intr(pnob);
+}
+
+/*
+ * This is the driver entry point to add a vlan vlan_id
+ * with the device netdev
+ */
+static void benet_vlan_add_vid(struct net_device *netdev, u16 vlan_id)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ if (pnob->num_vlans == (BE_NUM_VLAN_SUPPORTED - 1)) {
+ /* no way to return an error */
+ dev_info(&netdev->dev,
+ "BladeEngine: Cannot configure more than %d Vlans\n",
+ BE_NUM_VLAN_SUPPORTED);
+ return;
+ }
+ /* The new vlan tag will be in the slot indicated by num_vlans. */
+ pnob->vlan_tag[pnob->num_vlans++] = vlan_id;
+ be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans,
+ pnob->vlan_tag, NULL, NULL, NULL);
+}
+
+/*
+ * This is the driver entry point to remove a vlan vlan_id
+ * with the device netdev
+ */
+static void benet_vlan_rem_vid(struct net_device *netdev, u16 vlan_id)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ u32 i, value;
+
+ /*
+ * In Blade Engine, we support 32 vlan tag filters across both ports.
+ * To program a vlan tag, the RXF_RTPR_CSR register is used.
+ * Each 32-bit value of RXF_RTDR_CSR can address 2 vlan tag entries.
+ * The Vlan table is of depth 16. thus we support 32 tags.
+ */
+
+ value = vlan_id | VLAN_VALID_BIT;
+ for (i = 0; i < BE_NUM_VLAN_SUPPORTED; i++) {
+ if (pnob->vlan_tag[i] == vlan_id)
+ break;
+ }
+
+ if (i == BE_NUM_VLAN_SUPPORTED)
+ return;
+ /* Now compact the vlan tag array by removing hole created. */
+ while ((i + 1) < BE_NUM_VLAN_SUPPORTED) {
+ pnob->vlan_tag[i] = pnob->vlan_tag[i + 1];
+ i++;
+ }
+ if ((i + 1) == BE_NUM_VLAN_SUPPORTED)
+ pnob->vlan_tag[i] = (u16) 0x0;
+ pnob->num_vlans--;
+ be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans,
+ pnob->vlan_tag, NULL, NULL, NULL);
+}
+
+/*
+ * This function is called to program multicast
+ * address in the multicast filter of the ASIC.
+ */
+static void be_set_multicast_filter(struct net_device *netdev)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct dev_mc_list *mc_ptr;
+ u8 mac_addr[32][ETH_ALEN];
+ int i;
+
+ if (netdev->flags & IFF_ALLMULTI) {
+ /* set BE in Multicast promiscuous */
+ be_rxf_multicast_config(&pnob->fn_obj, true, 0, NULL, NULL,
+ NULL, NULL);
+ return;
+ }
+
+ for (mc_ptr = netdev->mc_list, i = 0; mc_ptr;
+ mc_ptr = mc_ptr->next, i++) {
+ memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN);
+ }
+
+ /* reset the promiscuous mode also. */
+ be_rxf_multicast_config(&pnob->fn_obj, false, i,
+ &mac_addr[0][0], NULL, NULL, NULL);
+}
+
+/*
+ * This is the driver entry point to set multicast list
+ * with the device netdev. This function will be used to
+ * set promiscuous mode or multicast promiscuous mode
+ * or multicast mode....
+ */
+static void benet_set_multicast_list(struct net_device *netdev)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+
+ if (netdev->flags & IFF_PROMISC) {
+ be_rxf_promiscuous(&pnob->fn_obj, 1, 1, NULL, NULL, NULL);
+ } else {
+ be_rxf_promiscuous(&pnob->fn_obj, 0, 0, NULL, NULL, NULL);
+ be_set_multicast_filter(netdev);
+ }
+}
+
+int benet_init(struct net_device *netdev)
+{
+ struct be_net_object *pnob = netdev_priv(netdev);
+ struct be_adapter *adapter = pnob->adapter;
+
+ ether_setup(netdev);
+
+ netdev->open = &benet_open;
+ netdev->stop = &benet_close;
+ netdev->hard_start_xmit = &benet_xmit;
+
+ netdev->get_stats = &benet_get_stats;
+
+ netdev->set_multicast_list = &benet_set_multicast_list;
+
+ netdev->change_mtu = &benet_change_mtu;
+ netdev->set_mac_address = &benet_set_mac_addr;
+
+ netdev->vlan_rx_register = benet_vlan_register;
+ netdev->vlan_rx_add_vid = benet_vlan_add_vid;
+ netdev->vlan_rx_kill_vid = benet_vlan_rem_vid;
+
+ netdev->features =
+ NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
+ NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM;
+
+ netdev->flags |= IFF_MULTICAST;
+
+ /* If device is DAC Capable, set the HIGHDMA flag for netdevice. */
+ if (adapter->dma_64bit_cap)
+ netdev->features |= NETIF_F_HIGHDMA;
+
+ SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
+ return 0;
+}
diff --git a/drivers/staging/benet/benet.h b/drivers/staging/benet/benet.h
new file mode 100644
index 000000000000..09a1f0817722
--- /dev/null
+++ b/drivers/staging/benet/benet.h
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#ifndef _BENET_H_
+#define _BENET_H_
+
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/inet_lro.h>
+#include "hwlib.h"
+
+#define _SA_MODULE_NAME "net-driver"
+
+#define VLAN_VALID_BIT 0x8000
+#define BE_NUM_VLAN_SUPPORTED 32
+#define BE_PORT_LINK_DOWN 0000
+#define BE_PORT_LINK_UP 0001
+#define BE_MAX_TX_FRAG_COUNT (30)
+
+/* Flag bits for send operation */
+#define IPCS (1 << 0) /* Enable IP checksum offload */
+#define UDPCS (1 << 1) /* Enable UDP checksum offload */
+#define TCPCS (1 << 2) /* Enable TCP checksum offload */
+#define LSO (1 << 3) /* Enable Large Segment offload */
+#define ETHVLAN (1 << 4) /* Enable VLAN insert */
+#define ETHEVENT (1 << 5) /* Generate event on completion */
+#define ETHCOMPLETE (1 << 6) /* Generate completion when done */
+#define IPSEC (1 << 7) /* Enable IPSEC */
+#define FORWARD (1 << 8) /* Send the packet in forwarding path */
+#define FIN (1 << 9) /* Issue FIN segment */
+
+#define BE_MAX_MTU 8974
+
+#define BE_MAX_LRO_DESCRIPTORS 8
+#define BE_LRO_MAX_PKTS 64
+#define BE_MAX_FRAGS_PER_FRAME 6
+
+extern const char be_drvr_ver[];
+extern char be_fw_ver[];
+extern char be_driver_name[];
+
+extern struct ethtool_ops be_ethtool_ops;
+
+#define BE_DEV_STATE_NONE 0
+#define BE_DEV_STATE_INIT 1
+#define BE_DEV_STATE_OPEN 2
+#define BE_DEV_STATE_SUSPEND 3
+
+/* This structure is used to describe physical fragments to use
+ * for DMAing data from NIC.
+ */
+struct be_recv_buffer {
+ struct list_head rxb_list; /* for maintaining a linked list */
+ void *rxb_va; /* buffer virtual address */
+ u32 rxb_pa_lo; /* low part of physical address */
+ u32 rxb_pa_hi; /* high part of physical address */
+ u32 rxb_len; /* length of recv buffer */
+ void *rxb_ctxt; /* context for OSM driver to use */
+};
+
+/*
+ * fragment list to describe scattered data.
+ */
+struct be_tx_frag_list {
+ u32 txb_len; /* Size of this fragment */
+ u32 txb_pa_lo; /* Lower 32 bits of 64 bit physical addr */
+ u32 txb_pa_hi; /* Higher 32 bits of 64 bit physical addr */
+};
+
+struct be_rx_page_info {
+ struct page *page;
+ dma_addr_t bus;
+ u16 page_offset;
+};
+
+/*
+ * This structure is the main tracking structure for a NIC interface.
+ */
+struct be_net_object {
+ /* MCC Ring - used to send fwcmds to embedded ARM processor */
+ struct MCC_WRB_AMAP *mcc_q; /* VA of the start of the ring */
+ u32 mcc_q_len; /* # of WRB entries in this ring */
+ u32 mcc_q_size;
+ u32 mcc_q_hd; /* MCC ring head */
+ u8 mcc_q_created; /* flag to help cleanup */
+ struct be_mcc_object mcc_q_obj; /* BECLIB's MCC ring Object */
+ dma_addr_t mcc_q_bus; /* DMA'ble bus address */
+
+ /* MCC Completion Ring - FW responses to fwcmds sent from MCC ring */
+ struct MCC_CQ_ENTRY_AMAP *mcc_cq; /* VA of the start of the ring */
+ u32 mcc_cq_len; /* # of compl. entries in this ring */
+ u32 mcc_cq_size;
+ u32 mcc_cq_tl; /* compl. ring tail */
+ u8 mcc_cq_created; /* flag to help cleanup */
+ struct be_cq_object mcc_cq_obj; /* BECLIB's MCC compl. ring object */
+ u32 mcc_cq_id; /* MCC ring ID */
+ dma_addr_t mcc_cq_bus; /* DMA'ble bus address */
+
+ struct ring_desc mb_rd; /* RD for MCC_MAIL_BOX */
+ void *mb_ptr; /* mailbox ptr to be freed */
+ dma_addr_t mb_bus; /* DMA'ble bus address */
+ u32 mb_size;
+
+ /* BEClib uses an array of context objects to track outstanding
+ * requests to the MCC. We need allocate the same number of
+ * conext entries as the number of entries in the MCC WRB ring
+ */
+ u32 mcc_wrb_ctxt_size;
+ void *mcc_wrb_ctxt; /* pointer to the context area */
+ u32 mcc_wrb_ctxtLen; /* Number of entries in the context */
+ /*
+ * NIC send request ring - used for xmitting raw ether frames.
+ */
+ struct ETH_WRB_AMAP *tx_q; /* VA of the start of the ring */
+ u32 tx_q_len; /* # if entries in the send ring */
+ u32 tx_q_size;
+ u32 tx_q_hd; /* Head index. Next req. goes here */
+ u32 tx_q_tl; /* Tail indx. oldest outstanding req. */
+ u8 tx_q_created; /* flag to help cleanup */
+ struct be_ethsq_object tx_q_obj;/* BECLIB's send Q handle */
+ dma_addr_t tx_q_bus; /* DMA'ble bus address */
+ u32 tx_q_id; /* send queue ring ID */
+ u32 tx_q_port; /* 0 no binding, 1 port A, 2 port B */
+ atomic_t tx_q_used; /* # of WRBs used */
+ /* ptr to an array in which we store context info for each send req. */
+ void **tx_ctxt;
+ /*
+ * NIC Send compl. ring - completion status for all NIC frames xmitted.
+ */
+ struct ETH_TX_COMPL_AMAP *tx_cq;/* VA of start of the ring */
+ u32 txcq_len; /* # of entries in the ring */
+ u32 tx_cq_size;
+ /*
+ * index into compl ring where the host expects next completion entry
+ */
+ u32 tx_cq_tl;
+ u32 tx_cq_id; /* completion queue id */
+ u8 tx_cq_created; /* flag to help cleanup */
+ struct be_cq_object tx_cq_obj;
+ dma_addr_t tx_cq_bus; /* DMA'ble bus address */
+ /*
+ * Event Queue - all completion entries post events here.
+ */
+ struct EQ_ENTRY_AMAP *event_q; /* VA of start of event queue */
+ u32 event_q_len; /* # of entries */
+ u32 event_q_size;
+ u32 event_q_tl; /* Tail of the event queue */
+ u32 event_q_id; /* Event queue ID */
+ u8 event_q_created; /* flag to help cleanup */
+ struct be_eq_object event_q_obj; /* Queue handle */
+ dma_addr_t event_q_bus; /* DMA'ble bus address */
+ /*
+ * NIC receive queue - Data buffers to be used for receiving unicast,
+ * broadcast and multi-cast frames are posted here.
+ */
+ struct ETH_RX_D_AMAP *rx_q; /* VA of start of the queue */
+ u32 rx_q_len; /* # of entries */
+ u32 rx_q_size;
+ u32 rx_q_hd; /* Head of the queue */
+ atomic_t rx_q_posted; /* number of posted buffers */
+ u32 rx_q_id; /* queue ID */
+ u8 rx_q_created; /* flag to help cleanup */
+ struct be_ethrq_object rx_q_obj; /* NIC RX queue handle */
+ dma_addr_t rx_q_bus; /* DMA'ble bus address */
+ /*
+ * Pointer to an array of opaque context object for use by OSM driver
+ */
+ void **rx_ctxt;
+ /*
+ * NIC unicast RX completion queue - all unicast ether frame completion
+ * statuses from BE come here.
+ */
+ struct ETH_RX_COMPL_AMAP *rx_cq; /* VA of start of the queue */
+ u32 rx_cq_len; /* # of entries */
+ u32 rx_cq_size;
+ u32 rx_cq_tl; /* Tail of the queue */
+ u32 rx_cq_id; /* queue ID */
+ u8 rx_cq_created; /* flag to help cleanup */
+ struct be_cq_object rx_cq_obj; /* queue handle */
+ dma_addr_t rx_cq_bus; /* DMA'ble bus address */
+ struct be_function_object fn_obj; /* function object */
+ bool fn_obj_created;
+ u32 rx_buf_size; /* Size of the RX buffers */
+
+ struct net_device *netdev;
+ struct be_recv_buffer eth_rx_bufs[256]; /* to pass Rx buffer
+ addresses */
+ struct be_adapter *adapter; /* Pointer to OSM adapter */
+ u32 devno; /* OSM, network dev no. */
+ u32 use_port; /* Current active port */
+ struct be_rx_page_info *rx_page_info; /* Array of Rx buf pages */
+ u32 rx_pg_info_hd; /* Head of queue */
+ int rxbuf_post_fail; /* RxBuff posting fail count */
+ bool rx_pg_shared; /* Is an allocsted page shared as two frags ? */
+ struct vlan_group *vlan_grp;
+ u32 num_vlans; /* Number of vlans in BE's filter */
+ u16 vlan_tag[BE_NUM_VLAN_SUPPORTED]; /* vlans currently configured */
+ struct napi_struct napi;
+ struct net_lro_mgr lro_mgr;
+ struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS];
+};
+
+#define NET_FH(np) (&(np)->fn_obj)
+
+/*
+ * BE driver statistics.
+ */
+struct be_drvr_stat {
+ u32 bes_tx_reqs; /* number of TX requests initiated */
+ u32 bes_tx_fails; /* number of TX requests that failed */
+ u32 bes_fwd_reqs; /* number of send reqs through forwarding i/f */
+ u32 bes_tx_wrbs; /* number of tx WRBs used */
+
+ u32 bes_ints; /* number of interrupts */
+ u32 bes_polls; /* number of times NAPI called poll function */
+ u32 bes_events; /* total evet entries processed */
+ u32 bes_tx_events; /* number of tx completion events */
+ u32 bes_rx_events; /* number of ucast rx completion events */
+ u32 bes_tx_compl; /* number of tx completion entries processed */
+ u32 bes_rx_compl; /* number of rx completion entries
+ processed */
+ u32 bes_ethrx_post_fail; /* number of ethrx buffer alloc
+ failures */
+ /*
+ * number of non ether type II frames dropped where
+ * frame len > length field of Mac Hdr
+ */
+ u32 bes_802_3_dropped_frames;
+ /*
+ * number of non ether type II frames malformed where
+ * in frame len < length field of Mac Hdr
+ */
+ u32 bes_802_3_malformed_frames;
+ u32 bes_ips; /* interrupts / sec */
+ u32 bes_prev_ints; /* bes_ints at last IPS calculation */
+ u16 bes_eth_tx_rate; /* ETH TX rate - Mb/sec */
+ u16 bes_eth_rx_rate; /* ETH RX rate - Mb/sec */
+ u32 bes_rx_coal; /* Num pkts coalasced */
+ u32 bes_rx_flush; /* Num times coalasced */
+ u32 bes_link_change_physical; /*Num of times physical link changed */
+ u32 bes_link_change_virtual; /*Num of times virtual link changed */
+ u32 bes_rx_misc_pkts; /* Misc pkts received */
+};
+
+/* Maximum interrupt delay (in microseconds) allowed */
+#define MAX_EQD 120
+
+/*
+ * timer to prevent system shutdown hang for ever if h/w stops responding
+ */
+struct be_timer_ctxt {
+ atomic_t get_stat_flag;
+ struct timer_list get_stats_timer;
+ unsigned long get_stat_sem_addr;
+} ;
+
+/* This structure is the main BladeEngine driver context. */
+struct be_adapter {
+ struct net_device *netdevp;
+ struct be_drvr_stat be_stat;
+ struct net_device_stats benet_stats;
+
+ /* PCI BAR mapped addresses */
+ u8 __iomem *csr_va; /* CSR */
+ u8 __iomem *db_va; /* Door Bell */
+ u8 __iomem *pci_va; /* PCI Config */
+
+ struct tasklet_struct sts_handler;
+ struct timer_list cq_timer;
+ spinlock_t int_lock; /* to protect the isr field in adapter */
+
+ struct FWCMD_ETH_GET_STATISTICS *eth_statsp;
+ /*
+ * This will enable the use of ethtool to enable or disable
+ * Checksum on Rx pkts to be obeyed or disobeyed.
+ * If this is true = 1, then whatever is the checksum on the
+ * Received pkt as per BE, it will be given to the stack.
+ * Else the stack will re calculate it.
+ */
+ bool rx_csum;
+ /*
+ * This will enable the use of ethtool to enable or disable
+ * Coalese on Rx pkts to be obeyed or disobeyed.
+ * If this is grater than 0 and less than 16 then coalascing
+ * is enabled else it is disabled
+ */
+ u32 max_rx_coal;
+ struct pci_dev *pdev; /* Pointer to OS's PCI dvice */
+
+ spinlock_t txq_lock; /* to stop/wake queue based on tx_q_used */
+
+ u32 isr; /* copy of Intr status reg. */
+
+ u32 port0_link_sts; /* Port 0 link status */
+ u32 port1_link_sts; /* port 1 list status */
+ struct BE_LINK_STATUS *be_link_sts;
+
+ /* pointer to the first netobject of this adapter */
+ struct be_net_object *net_obj;
+
+ /* Flags to indicate what to clean up */
+ bool tasklet_started;
+ bool isr_registered;
+ /*
+ * adaptive interrupt coalescing (AIC) related
+ */
+ bool enable_aic; /* 1 if AIC is enabled */
+ u16 min_eqd; /* minimum EQ delay in usec */
+ u16 max_eqd; /* minimum EQ delay in usec */
+ u16 cur_eqd; /* current EQ delay in usec */
+ /*
+ * book keeping for interrupt / sec and TX/RX rate calculation
+ */
+ ulong ips_jiffies; /* jiffies at last IPS calc */
+ u32 eth_tx_bytes;
+ ulong eth_tx_jiffies;
+ u32 eth_rx_bytes;
+ ulong eth_rx_jiffies;
+
+ struct semaphore get_eth_stat_sem;
+
+ /* timer ctxt to prevent shutdown hanging due to un-responsive BE */
+ struct be_timer_ctxt timer_ctxt;
+
+#define BE_MAX_MSIX_VECTORS 32
+#define BE_MAX_REQ_MSIX_VECTORS 1 /* only one EQ in Linux driver */
+ struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
+ bool msix_enabled;
+ bool dma_64bit_cap; /* the Device DAC capable or not */
+ u8 dev_state; /* The current state of the device */
+ u8 dev_pm_state; /* The State of device before going to suspend */
+};
+
+/*
+ * Every second we look at the ints/sec and adjust eq_delay
+ * between adapter->min_eqd and adapter->max_eqd to keep the ints/sec between
+ * IPS_HI_WM and IPS_LO_WM.
+ */
+#define IPS_HI_WM 18000
+#define IPS_LO_WM 8000
+
+
+static inline void index_adv(u32 *index, u32 val, u32 limit)
+{
+ BUG_ON(limit & (limit-1));
+ *index = (*index + val) & (limit - 1);
+}
+
+static inline void index_inc(u32 *index, u32 limit)
+{
+ BUG_ON(limit & (limit-1));
+ *index = (*index + 1) & (limit - 1);
+}
+
+static inline void be_adv_eq_tl(struct be_net_object *pnob)
+{
+ index_inc(&pnob->event_q_tl, pnob->event_q_len);
+}
+
+static inline void be_adv_txq_hd(struct be_net_object *pnob)
+{
+ index_inc(&pnob->tx_q_hd, pnob->tx_q_len);
+}
+
+static inline void be_adv_txq_tl(struct be_net_object *pnob)
+{
+ index_inc(&pnob->tx_q_tl, pnob->tx_q_len);
+}
+
+static inline void be_adv_txcq_tl(struct be_net_object *pnob)
+{
+ index_inc(&pnob->tx_cq_tl, pnob->txcq_len);
+}
+
+static inline void be_adv_rxq_hd(struct be_net_object *pnob)
+{
+ index_inc(&pnob->rx_q_hd, pnob->rx_q_len);
+}
+
+static inline void be_adv_rxcq_tl(struct be_net_object *pnob)
+{
+ index_inc(&pnob->rx_cq_tl, pnob->rx_cq_len);
+}
+
+static inline u32 tx_compl_lastwrb_idx_get(struct be_net_object *pnob)
+{
+ return (pnob->tx_q_tl + *(u32 *)&pnob->tx_ctxt[pnob->tx_q_tl] - 1)
+ & (pnob->tx_q_len - 1);
+}
+
+int benet_init(struct net_device *);
+int be_ethtool_ioctl(struct net_device *, struct ifreq *);
+struct net_device_stats *benet_get_stats(struct net_device *);
+void be_process_intr(unsigned long context);
+irqreturn_t be_int(int irq, void *dev);
+void be_post_eth_rx_buffs(struct be_net_object *);
+void be_get_stat_cb(void *, int, struct MCC_WRB_AMAP *);
+void be_get_stats_timer_handler(unsigned long);
+void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *);
+void be_print_link_info(struct BE_LINK_STATUS *);
+void be_update_link_status(struct be_adapter *);
+void be_init_procfs(struct be_adapter *);
+void be_cleanup_procfs(struct be_adapter *);
+int be_poll(struct napi_struct *, int);
+struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *);
+void be_notify_cmpl(struct be_net_object *, int, int, int);
+void be_enable_intr(struct be_net_object *);
+void be_enable_eq_intr(struct be_net_object *);
+void be_disable_intr(struct be_net_object *);
+void be_disable_eq_intr(struct be_net_object *);
+int be_set_uc_mac_adr(struct be_net_object *, u8, u8, u8,
+ u8 *, mcc_wrb_cqe_callback, void *);
+int be_get_flow_ctl(struct be_function_object *pFnObj, bool *, bool *);
+void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx);
+
+#endif /* _BENET_H_ */
diff --git a/drivers/staging/benet/bestatus.h b/drivers/staging/benet/bestatus.h
new file mode 100644
index 000000000000..59c7a4b62223
--- /dev/null
+++ b/drivers/staging/benet/bestatus.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#ifndef _BESTATUS_H_
+#define _BESTATUS_H_
+
+#define BE_SUCCESS (0x00000000L)
+/*
+ * MessageId: BE_PENDING
+ * The BladeEngine Driver call succeeded, and pended operation.
+ */
+#define BE_PENDING (0x20070001L)
+#define BE_STATUS_PENDING (BE_PENDING)
+/*
+ * MessageId: BE_NOT_OK
+ * An error occurred.
+ */
+#define BE_NOT_OK (0xE0070002L)
+/*
+ * MessageId: BE_STATUS_SYSTEM_RESOURCES
+ * Insufficient host system resources exist to complete the API.
+ */
+#define BE_STATUS_SYSTEM_RESOURCES (0xE0070003L)
+/*
+ * MessageId: BE_STATUS_CHIP_RESOURCES
+ * Insufficient chip resources exist to complete the API.
+ */
+#define BE_STATUS_CHIP_RESOURCES (0xE0070004L)
+/*
+ * MessageId: BE_STATUS_NO_RESOURCE
+ * Insufficient resources to complete request.
+ */
+#define BE_STATUS_NO_RESOURCE (0xE0070005L)
+/*
+ * MessageId: BE_STATUS_BUSY
+ * Resource is currently busy.
+ */
+#define BE_STATUS_BUSY (0xE0070006L)
+/*
+ * MessageId: BE_STATUS_INVALID_PARAMETER
+ * Invalid Parameter in request.
+ */
+#define BE_STATUS_INVALID_PARAMETER (0xE0000007L)
+/*
+ * MessageId: BE_STATUS_NOT_SUPPORTED
+ * Requested operation is not supported.
+ */
+#define BE_STATUS_NOT_SUPPORTED (0xE000000DL)
+
+/*
+ * ***************************************************************************
+ * E T H E R N E T S T A T U S
+ * ***************************************************************************
+ */
+
+/*
+ * MessageId: BE_ETH_TX_ERROR
+ * The Ethernet device driver failed to transmit a packet.
+ */
+#define BE_ETH_TX_ERROR (0xE0070101L)
+
+/*
+ * ***************************************************************************
+ * S H A R E D S T A T U S
+ * ***************************************************************************
+ */
+
+/*
+ * MessageId: BE_STATUS_VBD_INVALID_VERSION
+ * The device driver is not compatible with this version of the VBD.
+ */
+#define BE_STATUS_INVALID_VERSION (0xE0070402L)
+/*
+ * MessageId: BE_STATUS_DOMAIN_DENIED
+ * The operation failed to complete due to insufficient access
+ * rights for the requesting domain.
+ */
+#define BE_STATUS_DOMAIN_DENIED (0xE0070403L)
+/*
+ * MessageId: BE_STATUS_TCP_NOT_STARTED
+ * The embedded TCP/IP stack has not been started.
+ */
+#define BE_STATUS_TCP_NOT_STARTED (0xE0070409L)
+/*
+ * MessageId: BE_STATUS_NO_MCC_WRB
+ * No free MCC WRB are available for posting the request.
+ */
+#define BE_STATUS_NO_MCC_WRB (0xE0070414L)
+
+#endif /* _BESTATUS_ */
diff --git a/drivers/staging/benet/cev.h b/drivers/staging/benet/cev.h
new file mode 100644
index 000000000000..30996920a544
--- /dev/null
+++ b/drivers/staging/benet/cev.h
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __cev_amap_h__
+#define __cev_amap_h__
+#include "ep.h"
+
+/*
+ * Host Interrupt Status Register 0. The first of four application
+ * interrupt status registers. This register contains the interrupts
+ * for Event Queues EQ0 through EQ31.
+ */
+struct BE_CEV_ISR0_CSR_AMAP {
+ u8 interrupt0; /* DWORD 0 */
+ u8 interrupt1; /* DWORD 0 */
+ u8 interrupt2; /* DWORD 0 */
+ u8 interrupt3; /* DWORD 0 */
+ u8 interrupt4; /* DWORD 0 */
+ u8 interrupt5; /* DWORD 0 */
+ u8 interrupt6; /* DWORD 0 */
+ u8 interrupt7; /* DWORD 0 */
+ u8 interrupt8; /* DWORD 0 */
+ u8 interrupt9; /* DWORD 0 */
+ u8 interrupt10; /* DWORD 0 */
+ u8 interrupt11; /* DWORD 0 */
+ u8 interrupt12; /* DWORD 0 */
+ u8 interrupt13; /* DWORD 0 */
+ u8 interrupt14; /* DWORD 0 */
+ u8 interrupt15; /* DWORD 0 */
+ u8 interrupt16; /* DWORD 0 */
+ u8 interrupt17; /* DWORD 0 */
+ u8 interrupt18; /* DWORD 0 */
+ u8 interrupt19; /* DWORD 0 */
+ u8 interrupt20; /* DWORD 0 */
+ u8 interrupt21; /* DWORD 0 */
+ u8 interrupt22; /* DWORD 0 */
+ u8 interrupt23; /* DWORD 0 */
+ u8 interrupt24; /* DWORD 0 */
+ u8 interrupt25; /* DWORD 0 */
+ u8 interrupt26; /* DWORD 0 */
+ u8 interrupt27; /* DWORD 0 */
+ u8 interrupt28; /* DWORD 0 */
+ u8 interrupt29; /* DWORD 0 */
+ u8 interrupt30; /* DWORD 0 */
+ u8 interrupt31; /* DWORD 0 */
+} __packed;
+struct CEV_ISR0_CSR_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * Host Interrupt Status Register 1. The second of four application
+ * interrupt status registers. This register contains the interrupts
+ * for Event Queues EQ32 through EQ63.
+ */
+struct BE_CEV_ISR1_CSR_AMAP {
+ u8 interrupt32; /* DWORD 0 */
+ u8 interrupt33; /* DWORD 0 */
+ u8 interrupt34; /* DWORD 0 */
+ u8 interrupt35; /* DWORD 0 */
+ u8 interrupt36; /* DWORD 0 */
+ u8 interrupt37; /* DWORD 0 */
+ u8 interrupt38; /* DWORD 0 */
+ u8 interrupt39; /* DWORD 0 */
+ u8 interrupt40; /* DWORD 0 */
+ u8 interrupt41; /* DWORD 0 */
+ u8 interrupt42; /* DWORD 0 */
+ u8 interrupt43; /* DWORD 0 */
+ u8 interrupt44; /* DWORD 0 */
+ u8 interrupt45; /* DWORD 0 */
+ u8 interrupt46; /* DWORD 0 */
+ u8 interrupt47; /* DWORD 0 */
+ u8 interrupt48; /* DWORD 0 */
+ u8 interrupt49; /* DWORD 0 */
+ u8 interrupt50; /* DWORD 0 */
+ u8 interrupt51; /* DWORD 0 */
+ u8 interrupt52; /* DWORD 0 */
+ u8 interrupt53; /* DWORD 0 */
+ u8 interrupt54; /* DWORD 0 */
+ u8 interrupt55; /* DWORD 0 */
+ u8 interrupt56; /* DWORD 0 */
+ u8 interrupt57; /* DWORD 0 */
+ u8 interrupt58; /* DWORD 0 */
+ u8 interrupt59; /* DWORD 0 */
+ u8 interrupt60; /* DWORD 0 */
+ u8 interrupt61; /* DWORD 0 */
+ u8 interrupt62; /* DWORD 0 */
+ u8 interrupt63; /* DWORD 0 */
+} __packed;
+struct CEV_ISR1_CSR_AMAP {
+ u32 dw[1];
+};
+/*
+ * Host Interrupt Status Register 2. The third of four application
+ * interrupt status registers. This register contains the interrupts
+ * for Event Queues EQ64 through EQ95.
+ */
+struct BE_CEV_ISR2_CSR_AMAP {
+ u8 interrupt64; /* DWORD 0 */
+ u8 interrupt65; /* DWORD 0 */
+ u8 interrupt66; /* DWORD 0 */
+ u8 interrupt67; /* DWORD 0 */
+ u8 interrupt68; /* DWORD 0 */
+ u8 interrupt69; /* DWORD 0 */
+ u8 interrupt70; /* DWORD 0 */
+ u8 interrupt71; /* DWORD 0 */
+ u8 interrupt72; /* DWORD 0 */
+ u8 interrupt73; /* DWORD 0 */
+ u8 interrupt74; /* DWORD 0 */
+ u8 interrupt75; /* DWORD 0 */
+ u8 interrupt76; /* DWORD 0 */
+ u8 interrupt77; /* DWORD 0 */
+ u8 interrupt78; /* DWORD 0 */
+ u8 interrupt79; /* DWORD 0 */
+ u8 interrupt80; /* DWORD 0 */
+ u8 interrupt81; /* DWORD 0 */
+ u8 interrupt82; /* DWORD 0 */
+ u8 interrupt83; /* DWORD 0 */
+ u8 interrupt84; /* DWORD 0 */
+ u8 interrupt85; /* DWORD 0 */
+ u8 interrupt86; /* DWORD 0 */
+ u8 interrupt87; /* DWORD 0 */
+ u8 interrupt88; /* DWORD 0 */
+ u8 interrupt89; /* DWORD 0 */
+ u8 interrupt90; /* DWORD 0 */
+ u8 interrupt91; /* DWORD 0 */
+ u8 interrupt92; /* DWORD 0 */
+ u8 interrupt93; /* DWORD 0 */
+ u8 interrupt94; /* DWORD 0 */
+ u8 interrupt95; /* DWORD 0 */
+} __packed;
+struct CEV_ISR2_CSR_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * Host Interrupt Status Register 3. The fourth of four application
+ * interrupt status registers. This register contains the interrupts
+ * for Event Queues EQ96 through EQ127.
+ */
+struct BE_CEV_ISR3_CSR_AMAP {
+ u8 interrupt96; /* DWORD 0 */
+ u8 interrupt97; /* DWORD 0 */
+ u8 interrupt98; /* DWORD 0 */
+ u8 interrupt99; /* DWORD 0 */
+ u8 interrupt100; /* DWORD 0 */
+ u8 interrupt101; /* DWORD 0 */
+ u8 interrupt102; /* DWORD 0 */
+ u8 interrupt103; /* DWORD 0 */
+ u8 interrupt104; /* DWORD 0 */
+ u8 interrupt105; /* DWORD 0 */
+ u8 interrupt106; /* DWORD 0 */
+ u8 interrupt107; /* DWORD 0 */
+ u8 interrupt108; /* DWORD 0 */
+ u8 interrupt109; /* DWORD 0 */
+ u8 interrupt110; /* DWORD 0 */
+ u8 interrupt111; /* DWORD 0 */
+ u8 interrupt112; /* DWORD 0 */
+ u8 interrupt113; /* DWORD 0 */
+ u8 interrupt114; /* DWORD 0 */
+ u8 interrupt115; /* DWORD 0 */
+ u8 interrupt116; /* DWORD 0 */
+ u8 interrupt117; /* DWORD 0 */
+ u8 interrupt118; /* DWORD 0 */
+ u8 interrupt119; /* DWORD 0 */
+ u8 interrupt120; /* DWORD 0 */
+ u8 interrupt121; /* DWORD 0 */
+ u8 interrupt122; /* DWORD 0 */
+ u8 interrupt123; /* DWORD 0 */
+ u8 interrupt124; /* DWORD 0 */
+ u8 interrupt125; /* DWORD 0 */
+ u8 interrupt126; /* DWORD 0 */
+ u8 interrupt127; /* DWORD 0 */
+} __packed;
+struct CEV_ISR3_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Completions and Events block Registers. */
+struct BE_CEV_CSRMAP_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[32]; /* DWORD 1 */
+ u8 rsvd2[32]; /* DWORD 2 */
+ u8 rsvd3[32]; /* DWORD 3 */
+ struct BE_CEV_ISR0_CSR_AMAP isr0;
+ struct BE_CEV_ISR1_CSR_AMAP isr1;
+ struct BE_CEV_ISR2_CSR_AMAP isr2;
+ struct BE_CEV_ISR3_CSR_AMAP isr3;
+ u8 rsvd4[32]; /* DWORD 8 */
+ u8 rsvd5[32]; /* DWORD 9 */
+ u8 rsvd6[32]; /* DWORD 10 */
+ u8 rsvd7[32]; /* DWORD 11 */
+ u8 rsvd8[32]; /* DWORD 12 */
+ u8 rsvd9[32]; /* DWORD 13 */
+ u8 rsvd10[32]; /* DWORD 14 */
+ u8 rsvd11[32]; /* DWORD 15 */
+ u8 rsvd12[32]; /* DWORD 16 */
+ u8 rsvd13[32]; /* DWORD 17 */
+ u8 rsvd14[32]; /* DWORD 18 */
+ u8 rsvd15[32]; /* DWORD 19 */
+ u8 rsvd16[32]; /* DWORD 20 */
+ u8 rsvd17[32]; /* DWORD 21 */
+ u8 rsvd18[32]; /* DWORD 22 */
+ u8 rsvd19[32]; /* DWORD 23 */
+ u8 rsvd20[32]; /* DWORD 24 */
+ u8 rsvd21[32]; /* DWORD 25 */
+ u8 rsvd22[32]; /* DWORD 26 */
+ u8 rsvd23[32]; /* DWORD 27 */
+ u8 rsvd24[32]; /* DWORD 28 */
+ u8 rsvd25[32]; /* DWORD 29 */
+ u8 rsvd26[32]; /* DWORD 30 */
+ u8 rsvd27[32]; /* DWORD 31 */
+ u8 rsvd28[32]; /* DWORD 32 */
+ u8 rsvd29[32]; /* DWORD 33 */
+ u8 rsvd30[192]; /* DWORD 34 */
+ u8 rsvd31[192]; /* DWORD 40 */
+ u8 rsvd32[160]; /* DWORD 46 */
+ u8 rsvd33[160]; /* DWORD 51 */
+ u8 rsvd34[160]; /* DWORD 56 */
+ u8 rsvd35[96]; /* DWORD 61 */
+ u8 rsvd36[192][32]; /* DWORD 64 */
+} __packed;
+struct CEV_CSRMAP_AMAP {
+ u32 dw[256];
+};
+
+#endif /* __cev_amap_h__ */
diff --git a/drivers/staging/benet/cq.c b/drivers/staging/benet/cq.c
new file mode 100644
index 000000000000..650458645433
--- /dev/null
+++ b/drivers/staging/benet/cq.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#include "hwlib.h"
+#include "bestatus.h"
+
+/*
+ * Completion Queue Objects
+ */
+/*
+ *============================================================================
+ * P U B L I C R O U T I N E S
+ *============================================================================
+ */
+
+/*
+ This routine creates a completion queue based on the client completion
+ queue configuration information.
+
+
+ FunctionObject - Handle to a function object
+ CqBaseVa - Base VA for a the CQ ring
+ NumEntries - CEV_CQ_CNT_* values
+ solEventEnable - 0 = All CQEs can generate Events if CQ is eventable
+ 1 = only CQEs with solicited bit set are eventable
+ eventable - Eventable CQ, generates interrupts.
+ nodelay - 1 = Force interrupt, relevent if CQ eventable.
+ Interrupt is asserted immediately after EQE
+ write is confirmed, regardless of EQ Timer
+ or watermark settings.
+ wme - Enable watermark based coalescing
+ wmThresh - High watermark(CQ fullness at which event
+ or interrupt should be asserted). These are the
+ CEV_WATERMARK encoded values.
+ EqObject - EQ Handle to assign to this CQ
+ ppCqObject - Internal CQ Handle returned.
+
+ Returns BE_SUCCESS if successfull, otherwise a useful error code is
+ returned.
+
+ IRQL < DISPATCH_LEVEL
+
+*/
+int be_cq_create(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 length, bool solicited_eventable,
+ bool no_delay, u32 wm_thresh,
+ struct be_eq_object *eq_object, struct be_cq_object *cq_object)
+{
+ int status = BE_SUCCESS;
+ u32 num_entries_encoding;
+ u32 num_entries = length / sizeof(struct MCC_CQ_ENTRY_AMAP);
+ struct FWCMD_COMMON_CQ_CREATE *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ u32 n;
+ unsigned long irql;
+
+ ASSERT(rd);
+ ASSERT(cq_object);
+ ASSERT(length % sizeof(struct MCC_CQ_ENTRY_AMAP) == 0);
+
+ switch (num_entries) {
+ case 256:
+ num_entries_encoding = CEV_CQ_CNT_256;
+ break;
+ case 512:
+ num_entries_encoding = CEV_CQ_CNT_512;
+ break;
+ case 1024:
+ num_entries_encoding = CEV_CQ_CNT_1024;
+ break;
+ default:
+ ASSERT(0);
+ return BE_STATUS_INVALID_PARAMETER;
+ }
+
+ /*
+ * All cq entries all the same size. Use iSCSI version
+ * as a test for the proper rd length.
+ */
+ memset(cq_object, 0, sizeof(*cq_object));
+
+ atomic_set(&cq_object->ref_count, 0);
+ cq_object->parent_function = pfob;
+ cq_object->eq_object = eq_object;
+ cq_object->num_entries = num_entries;
+ /* save for MCC cq processing */
+ cq_object->va = rd->va;
+
+ /* map into UT. */
+ length = num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ ASSERT(wrb);
+ TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_CQ_CREATE);
+
+ fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va),
+ length);
+
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, valid, &fwcmd->params.request.context, 1);
+ n = pfob->pci_function_number;
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, Func, &fwcmd->params.request.context, n);
+
+ n = (eq_object != NULL);
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, Eventable,
+ &fwcmd->params.request.context, n);
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, Armed, &fwcmd->params.request.context, 1);
+
+ n = eq_object ? eq_object->eq_id : 0;
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, EQID, &fwcmd->params.request.context, n);
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, Count,
+ &fwcmd->params.request.context, num_entries_encoding);
+
+ n = 0; /* Protection Domain is always 0 in Linux driver */
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, PD, &fwcmd->params.request.context, n);
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, NoDelay,
+ &fwcmd->params.request.context, no_delay);
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, SolEvent,
+ &fwcmd->params.request.context, solicited_eventable);
+
+ n = (wm_thresh != 0xFFFFFFFF);
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, WME, &fwcmd->params.request.context, n);
+
+ n = (n ? wm_thresh : 0);
+ AMAP_SET_BITS_PTR(CQ_CONTEXT, Watermark,
+ &fwcmd->params.request.context, n);
+ /* Create a page list for the FWCMD. */
+ be_rd_to_pa_list(rd, fwcmd->params.request.pages,
+ ARRAY_SIZE(fwcmd->params.request.pages));
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "MCC to create CQ failed.");
+ goto Error;
+ }
+ /* Remember the CQ id. */
+ cq_object->cq_id = fwcmd->params.response.cq_id;
+
+ /* insert this cq into eq_object reference */
+ if (eq_object) {
+ atomic_inc(&eq_object->ref_count);
+ list_add_tail(&cq_object->cqlist_for_eq,
+ &eq_object->cq_list_head);
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+
+ Deferences the given object. Once the object's reference count drops to
+ zero, the object is destroyed and all resources that are held by this object
+ are released. The on-chip context is also destroyed along with the queue
+ ID, and any mappings made into the UT.
+
+ cq_object - CQ handle returned from cq_object_create.
+
+ returns the current reference count on the object
+
+ IRQL: IRQL < DISPATCH_LEVEL
+*/
+int be_cq_destroy(struct be_cq_object *cq_object)
+{
+ int status = 0;
+
+ /* Nothing should reference this CQ at this point. */
+ ASSERT(atomic_read(&cq_object->ref_count) == 0);
+
+ /* Send fwcmd to destroy the CQ. */
+ status = be_function_ring_destroy(cq_object->parent_function,
+ cq_object->cq_id, FWCMD_RING_TYPE_CQ,
+ NULL, NULL, NULL, NULL);
+ ASSERT(status == 0);
+
+ /* Remove reference if this is an eventable CQ. */
+ if (cq_object->eq_object) {
+ atomic_dec(&cq_object->eq_object->ref_count);
+ list_del(&cq_object->cqlist_for_eq);
+ }
+ return BE_SUCCESS;
+}
+
diff --git a/drivers/staging/benet/descriptors.h b/drivers/staging/benet/descriptors.h
new file mode 100644
index 000000000000..8da438c407d2
--- /dev/null
+++ b/drivers/staging/benet/descriptors.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __descriptors_amap_h__
+#define __descriptors_amap_h__
+
+/*
+ * --- IPC_NODE_ID_ENUM ---
+ * IPC processor id values
+ */
+#define TPOST_NODE_ID (0) /* TPOST ID */
+#define TPRE_NODE_ID (1) /* TPRE ID */
+#define TXULP0_NODE_ID (2) /* TXULP0 ID */
+#define TXULP1_NODE_ID (3) /* TXULP1 ID */
+#define TXULP2_NODE_ID (4) /* TXULP2 ID */
+#define RXULP0_NODE_ID (5) /* RXULP0 ID */
+#define RXULP1_NODE_ID (6) /* RXULP1 ID */
+#define RXULP2_NODE_ID (7) /* RXULP2 ID */
+#define MPU_NODE_ID (15) /* MPU ID */
+
+/*
+ * --- MAC_ID_ENUM ---
+ * Meaning of the mac_id field in rxpp_eth_d
+ */
+#define PORT0_HOST_MAC0 (0) /* PD 0, Port 0, host networking, MAC 0. */
+#define PORT0_HOST_MAC1 (1) /* PD 0, Port 0, host networking, MAC 1. */
+#define PORT0_STORAGE_MAC0 (2) /* PD 0, Port 0, host storage, MAC 0. */
+#define PORT0_STORAGE_MAC1 (3) /* PD 0, Port 0, host storage, MAC 1. */
+#define PORT1_HOST_MAC0 (4) /* PD 0, Port 1 host networking, MAC 0. */
+#define PORT1_HOST_MAC1 (5) /* PD 0, Port 1 host networking, MAC 1. */
+#define PORT1_STORAGE_MAC0 (6) /* PD 0, Port 1 host storage, MAC 0. */
+#define PORT1_STORAGE_MAC1 (7) /* PD 0, Port 1 host storage, MAC 1. */
+#define FIRST_VM_MAC (8) /* PD 1 MAC. Protection domains have IDs */
+ /* from 0x8-0x26, one per PD. */
+#define LAST_VM_MAC (38) /* PD 31 MAC. */
+#define MGMT_MAC (39) /* Management port MAC. */
+#define MARBLE_MAC0 (59) /* Used for flushing function 0 receive */
+ /*
+ * queues before re-using a torn-down
+ * receive ring. the DA =
+ * 00-00-00-00-00-00, and the MSB of the
+ * SA = 00
+ */
+#define MARBLE_MAC1 (60) /* Used for flushing function 1 receive */
+ /*
+ * queues before re-using a torn-down
+ * receive ring. the DA =
+ * 00-00-00-00-00-00, and the MSB of the
+ * SA != 00
+ */
+#define NULL_MAC (61) /* Promiscuous mode, indicates no match */
+#define MCAST_MAC (62) /* Multicast match. */
+#define BCAST_MATCH (63) /* Broadcast match. */
+
+#endif /* __descriptors_amap_h__ */
diff --git a/drivers/staging/benet/doorbells.h b/drivers/staging/benet/doorbells.h
new file mode 100644
index 000000000000..550cc4d5d6f7
--- /dev/null
+++ b/drivers/staging/benet/doorbells.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __doorbells_amap_h__
+#define __doorbells_amap_h__
+
+/* The TX/RDMA send queue doorbell. */
+struct BE_SQ_DB_AMAP {
+ u8 cid[11]; /* DWORD 0 */
+ u8 rsvd0[5]; /* DWORD 0 */
+ u8 numPosted[14]; /* DWORD 0 */
+ u8 rsvd1[2]; /* DWORD 0 */
+} __packed;
+struct SQ_DB_AMAP {
+ u32 dw[1];
+};
+
+/* The receive queue doorbell. */
+struct BE_RQ_DB_AMAP {
+ u8 rq[10]; /* DWORD 0 */
+ u8 rsvd0[13]; /* DWORD 0 */
+ u8 Invalidate; /* DWORD 0 */
+ u8 numPosted[8]; /* DWORD 0 */
+} __packed;
+struct RQ_DB_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * The CQ/EQ doorbell. Software MUST set reserved fields in this
+ * descriptor to zero, otherwise (CEV) hardware will not execute the
+ * doorbell (flagging a bad_db_qid error instead).
+ */
+struct BE_CQ_DB_AMAP {
+ u8 qid[10]; /* DWORD 0 */
+ u8 rsvd0[4]; /* DWORD 0 */
+ u8 rearm; /* DWORD 0 */
+ u8 event; /* DWORD 0 */
+ u8 num_popped[13]; /* DWORD 0 */
+ u8 rsvd1[3]; /* DWORD 0 */
+} __packed;
+struct CQ_DB_AMAP {
+ u32 dw[1];
+};
+
+struct BE_TPM_RQ_DB_AMAP {
+ u8 qid[10]; /* DWORD 0 */
+ u8 rsvd0[6]; /* DWORD 0 */
+ u8 numPosted[11]; /* DWORD 0 */
+ u8 mss_cnt[5]; /* DWORD 0 */
+} __packed;
+struct TPM_RQ_DB_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * Post WRB Queue Doorbell Register used by the host Storage stack
+ * to notify the controller of a posted Work Request Block
+ */
+struct BE_WRB_POST_DB_AMAP {
+ u8 wrb_cid[10]; /* DWORD 0 */
+ u8 rsvd0[6]; /* DWORD 0 */
+ u8 wrb_index[8]; /* DWORD 0 */
+ u8 numberPosted[8]; /* DWORD 0 */
+} __packed;
+struct WRB_POST_DB_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * Update Default PDU Queue Doorbell Register used to communicate
+ * to the controller that the driver has stopped processing the queue
+ * and where in the queue it stopped, this is
+ * a CQ Entry Type. Used by storage driver.
+ */
+struct BE_DEFAULT_PDU_DB_AMAP {
+ u8 qid[10]; /* DWORD 0 */
+ u8 rsvd0[4]; /* DWORD 0 */
+ u8 rearm; /* DWORD 0 */
+ u8 event; /* DWORD 0 */
+ u8 cqproc[14]; /* DWORD 0 */
+ u8 rsvd1[2]; /* DWORD 0 */
+} __packed;
+struct DEFAULT_PDU_DB_AMAP {
+ u32 dw[1];
+};
+
+/* Management Command and Controller default fragment ring */
+struct BE_MCC_DB_AMAP {
+ u8 rid[11]; /* DWORD 0 */
+ u8 rsvd0[5]; /* DWORD 0 */
+ u8 numPosted[14]; /* DWORD 0 */
+ u8 rsvd1[2]; /* DWORD 0 */
+} __packed;
+struct MCC_DB_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * Used for bootstrapping the Host interface. This register is
+ * used for driver communication with the MPU when no MCC Rings exist.
+ * The software must write this register twice to post any MCC
+ * command. First, it writes the register with hi=1 and the upper bits of
+ * the physical address for the MCC_MAILBOX structure. Software must poll
+ * the ready bit until this is acknowledged. Then, sotware writes the
+ * register with hi=0 with the lower bits in the address. It must
+ * poll the ready bit until the MCC command is complete. Upon completion,
+ * the MCC_MAILBOX will contain a valid completion queue entry.
+ */
+struct BE_MPU_MAILBOX_DB_AMAP {
+ u8 ready; /* DWORD 0 */
+ u8 hi; /* DWORD 0 */
+ u8 address[30]; /* DWORD 0 */
+} __packed;
+struct MPU_MAILBOX_DB_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * This is the protection domain doorbell register map. Note that
+ * while this map shows doorbells for all Blade Engine supported
+ * protocols, not all of these may be valid in a given function or
+ * protection domain. It is the responsibility of the application
+ * accessing the doorbells to know which are valid. Each doorbell
+ * occupies 32 bytes of space, but unless otherwise specified,
+ * only the first 4 bytes should be written. There are 32 instances
+ * of these doorbells for the host and 31 virtual machines respectively.
+ * The host and VMs will only map the doorbell pages belonging to its
+ * protection domain. It will not be able to touch the doorbells for
+ * another VM. The doorbells are the only registers directly accessible
+ * by a virtual machine. Similarly, there are 511 additional
+ * doorbells for RDMA protection domains. PD 0 for RDMA shares
+ * the same physical protection domain doorbell page as ETH/iSCSI.
+ *
+ */
+struct BE_PROTECTION_DOMAIN_DBMAP_AMAP {
+ u8 rsvd0[512]; /* DWORD 0 */
+ struct BE_SQ_DB_AMAP rdma_sq_db;
+ u8 rsvd1[7][32]; /* DWORD 17 */
+ struct BE_WRB_POST_DB_AMAP iscsi_wrb_post_db;
+ u8 rsvd2[7][32]; /* DWORD 25 */
+ struct BE_SQ_DB_AMAP etx_sq_db;
+ u8 rsvd3[7][32]; /* DWORD 33 */
+ struct BE_RQ_DB_AMAP rdma_rq_db;
+ u8 rsvd4[7][32]; /* DWORD 41 */
+ struct BE_DEFAULT_PDU_DB_AMAP iscsi_default_pdu_db;
+ u8 rsvd5[7][32]; /* DWORD 49 */
+ struct BE_TPM_RQ_DB_AMAP tpm_rq_db;
+ u8 rsvd6[7][32]; /* DWORD 57 */
+ struct BE_RQ_DB_AMAP erx_rq_db;
+ u8 rsvd7[7][32]; /* DWORD 65 */
+ struct BE_CQ_DB_AMAP cq_db;
+ u8 rsvd8[7][32]; /* DWORD 73 */
+ struct BE_MCC_DB_AMAP mpu_mcc_db;
+ u8 rsvd9[7][32]; /* DWORD 81 */
+ struct BE_MPU_MAILBOX_DB_AMAP mcc_bootstrap_db;
+ u8 rsvd10[935][32]; /* DWORD 89 */
+} __packed;
+struct PROTECTION_DOMAIN_DBMAP_AMAP {
+ u32 dw[1024];
+};
+
+#endif /* __doorbells_amap_h__ */
diff --git a/drivers/staging/benet/ep.h b/drivers/staging/benet/ep.h
new file mode 100644
index 000000000000..72fcf64a9ffb
--- /dev/null
+++ b/drivers/staging/benet/ep.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __ep_amap_h__
+#define __ep_amap_h__
+
+/* General Control and Status Register. */
+struct BE_EP_CONTROL_CSR_AMAP {
+ u8 m0_RxPbuf; /* DWORD 0 */
+ u8 m1_RxPbuf; /* DWORD 0 */
+ u8 m2_RxPbuf; /* DWORD 0 */
+ u8 ff_en; /* DWORD 0 */
+ u8 rsvd0[27]; /* DWORD 0 */
+ u8 CPU_reset; /* DWORD 0 */
+} __packed;
+struct EP_CONTROL_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Semaphore Register. */
+struct BE_EP_SEMAPHORE_CSR_AMAP {
+ u8 value[32]; /* DWORD 0 */
+} __packed;
+struct EP_SEMAPHORE_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Embedded Processor Specific Registers. */
+struct BE_EP_CSRMAP_AMAP {
+ struct BE_EP_CONTROL_CSR_AMAP ep_control;
+ u8 rsvd0[32]; /* DWORD 1 */
+ u8 rsvd1[32]; /* DWORD 2 */
+ u8 rsvd2[32]; /* DWORD 3 */
+ u8 rsvd3[32]; /* DWORD 4 */
+ u8 rsvd4[32]; /* DWORD 5 */
+ u8 rsvd5[8][128]; /* DWORD 6 */
+ u8 rsvd6[32]; /* DWORD 38 */
+ u8 rsvd7[32]; /* DWORD 39 */
+ u8 rsvd8[32]; /* DWORD 40 */
+ u8 rsvd9[32]; /* DWORD 41 */
+ u8 rsvd10[32]; /* DWORD 42 */
+ struct BE_EP_SEMAPHORE_CSR_AMAP ep_semaphore;
+ u8 rsvd11[32]; /* DWORD 44 */
+ u8 rsvd12[19][32]; /* DWORD 45 */
+} __packed;
+struct EP_CSRMAP_AMAP {
+ u32 dw[64];
+};
+
+#endif /* __ep_amap_h__ */
diff --git a/drivers/staging/benet/eq.c b/drivers/staging/benet/eq.c
new file mode 100644
index 000000000000..db92ccd8fed8
--- /dev/null
+++ b/drivers/staging/benet/eq.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#include "hwlib.h"
+#include "bestatus.h"
+/*
+ This routine creates an event queue based on the client completion
+ queue configuration information.
+
+ FunctionObject - Handle to a function object
+ EqBaseVa - Base VA for a the EQ ring
+ SizeEncoding - The encoded size for the EQ entries. This value is
+ either CEV_EQ_SIZE_4 or CEV_EQ_SIZE_16
+ NumEntries - CEV_CQ_CNT_* values.
+ Watermark - Enables watermark based coalescing. This parameter
+ must be of the type CEV_WMARK_* if watermarks
+ are enabled. If watermarks to to be disabled
+ this value should be-1.
+ TimerDelay - If a timer delay is enabled this value should be the
+ time of the delay in 8 microsecond units. If
+ delays are not used this parameter should be
+ set to -1.
+ ppEqObject - Internal EQ Handle returned.
+
+ Returns BE_SUCCESS if successfull,, otherwise a useful error code
+ is returned.
+
+ IRQL < DISPATCH_LEVEL
+*/
+int
+be_eq_create(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 eqe_size, u32 num_entries,
+ u32 watermark, /* CEV_WMARK_* or -1 */
+ u32 timer_delay, /* in 8us units, or -1 */
+ struct be_eq_object *eq_object)
+{
+ int status = BE_SUCCESS;
+ u32 num_entries_encoding, eqe_size_encoding, length;
+ struct FWCMD_COMMON_EQ_CREATE *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ u32 n;
+ unsigned long irql;
+
+ ASSERT(rd);
+ ASSERT(eq_object);
+
+ switch (num_entries) {
+ case 256:
+ num_entries_encoding = CEV_EQ_CNT_256;
+ break;
+ case 512:
+ num_entries_encoding = CEV_EQ_CNT_512;
+ break;
+ case 1024:
+ num_entries_encoding = CEV_EQ_CNT_1024;
+ break;
+ case 2048:
+ num_entries_encoding = CEV_EQ_CNT_2048;
+ break;
+ case 4096:
+ num_entries_encoding = CEV_EQ_CNT_4096;
+ break;
+ default:
+ ASSERT(0);
+ return BE_STATUS_INVALID_PARAMETER;
+ }
+
+ switch (eqe_size) {
+ case 4:
+ eqe_size_encoding = CEV_EQ_SIZE_4;
+ break;
+ case 16:
+ eqe_size_encoding = CEV_EQ_SIZE_16;
+ break;
+ default:
+ ASSERT(0);
+ return BE_STATUS_INVALID_PARAMETER;
+ }
+
+ if ((eqe_size == 4 && num_entries < 1024) ||
+ (eqe_size == 16 && num_entries == 4096)) {
+ TRACE(DL_ERR, "Bad EQ size. eqe_size:%d num_entries:%d",
+ eqe_size, num_entries);
+ ASSERT(0);
+ return BE_STATUS_INVALID_PARAMETER;
+ }
+
+ memset(eq_object, 0, sizeof(*eq_object));
+
+ atomic_set(&eq_object->ref_count, 0);
+ eq_object->parent_function = pfob;
+ eq_object->eq_id = 0xFFFFFFFF;
+
+ INIT_LIST_HEAD(&eq_object->cq_list_head);
+
+ length = num_entries * eqe_size;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ ASSERT(wrb);
+ TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_EQ_CREATE);
+
+ fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va),
+ length);
+ n = pfob->pci_function_number;
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, Func, &fwcmd->params.request.context, n);
+
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, valid, &fwcmd->params.request.context, 1);
+
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, Size,
+ &fwcmd->params.request.context, eqe_size_encoding);
+
+ n = 0; /* Protection Domain is always 0 in Linux driver */
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, PD, &fwcmd->params.request.context, n);
+
+ /* Let the caller ARM the EQ with the doorbell. */
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, Armed, &fwcmd->params.request.context, 0);
+
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, Count, &fwcmd->params.request.context,
+ num_entries_encoding);
+
+ n = pfob->pci_function_number * 32;
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, EventVect,
+ &fwcmd->params.request.context, n);
+ if (watermark != -1) {
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, WME,
+ &fwcmd->params.request.context, 1);
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, Watermark,
+ &fwcmd->params.request.context, watermark);
+ ASSERT(watermark <= CEV_WMARK_240);
+ } else
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, WME,
+ &fwcmd->params.request.context, 0);
+ if (timer_delay != -1) {
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR,
+ &fwcmd->params.request.context, 1);
+
+ ASSERT(timer_delay <= 250); /* max value according to EAS */
+ timer_delay = min(timer_delay, (u32)250);
+
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, Delay,
+ &fwcmd->params.request.context, timer_delay);
+ } else {
+ AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR,
+ &fwcmd->params.request.context, 0);
+ }
+ /* Create a page list for the FWCMD. */
+ be_rd_to_pa_list(rd, fwcmd->params.request.pages,
+ ARRAY_SIZE(fwcmd->params.request.pages));
+
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "MCC to create EQ failed.");
+ goto Error;
+ }
+ /* Get the EQ id. The MPU allocates the IDs. */
+ eq_object->eq_id = fwcmd->params.response.eq_id;
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ Deferences the given object. Once the object's reference count drops to
+ zero, the object is destroyed and all resources that are held by this
+ object are released. The on-chip context is also destroyed along with
+ the queue ID, and any mappings made into the UT.
+
+ eq_object - EQ handle returned from eq_object_create.
+
+ Returns BE_SUCCESS if successfull, otherwise a useful error code
+ is returned.
+
+ IRQL: IRQL < DISPATCH_LEVEL
+*/
+int be_eq_destroy(struct be_eq_object *eq_object)
+{
+ int status = 0;
+
+ ASSERT(atomic_read(&eq_object->ref_count) == 0);
+ /* no CQs should reference this EQ now */
+ ASSERT(list_empty(&eq_object->cq_list_head));
+
+ /* Send fwcmd to destroy the EQ. */
+ status = be_function_ring_destroy(eq_object->parent_function,
+ eq_object->eq_id, FWCMD_RING_TYPE_EQ,
+ NULL, NULL, NULL, NULL);
+ ASSERT(status == 0);
+
+ return BE_SUCCESS;
+}
+/*
+ *---------------------------------------------------------------------------
+ * Function: be_eq_modify_delay
+ * Changes the EQ delay for a group of EQs.
+ * num_eq - The number of EQs in the eq_array to adjust.
+ * This also is the number of delay values in
+ * the eq_delay_array.
+ * eq_array - Array of struct be_eq_object pointers to adjust.
+ * eq_delay_array - Array of "num_eq" timer delays in units
+ * of microseconds. The be_eq_query_delay_range
+ * fwcmd returns the resolution and range of
+ * legal EQ delays.
+ * cb -
+ * cb_context -
+ * q_ctxt - Optional. Pointer to a previously allocated
+ * struct. If the MCC WRB ring is full, this
+ * structure is used to queue the operation. It
+ * will be posted to the MCC ring when space
+ * becomes available. All queued commands will
+ * be posted to the ring in the order they are
+ * received. It is always valid to pass a pointer to
+ * a generic be_generic_q_cntxt. However,
+ * the specific context structs
+ * are generally smaller than the generic struct.
+ * return pend_status - BE_SUCCESS (0) on success.
+ * BE_PENDING (postive value) if the FWCMD
+ * completion is pending. Negative error code on failure.
+ *-------------------------------------------------------------------------
+ */
+int
+be_eq_modify_delay(struct be_function_object *pfob,
+ u32 num_eq, struct be_eq_object **eq_array,
+ u32 *eq_delay_array, mcc_wrb_cqe_callback cb,
+ void *cb_context, struct be_eq_modify_delay_q_ctxt *q_ctxt)
+{
+ struct FWCMD_COMMON_MODIFY_EQ_DELAY *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ struct be_generic_q_ctxt *gen_ctxt = NULL;
+ u32 i;
+ unsigned long irql;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ if (q_ctxt && cb) {
+ wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ gen_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
+ gen_ctxt->context.bytes = sizeof(*q_ctxt);
+ } else {
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MODIFY_EQ_DELAY);
+
+ ASSERT(num_eq > 0);
+ ASSERT(num_eq <= ARRAY_SIZE(fwcmd->params.request.delay));
+ fwcmd->params.request.num_eq = num_eq;
+ for (i = 0; i < num_eq; i++) {
+ fwcmd->params.request.delay[i].eq_id = eq_array[i]->eq_id;
+ fwcmd->params.request.delay[i].delay_in_microseconds =
+ eq_delay_array[i];
+ }
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, gen_ctxt,
+ cb, cb_context, NULL, NULL, fwcmd, NULL);
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
diff --git a/drivers/staging/benet/eth.c b/drivers/staging/benet/eth.c
new file mode 100644
index 000000000000..f641b6260d07
--- /dev/null
+++ b/drivers/staging/benet/eth.c
@@ -0,0 +1,1273 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#include <linux/if_ether.h>
+#include "hwlib.h"
+#include "bestatus.h"
+
+/*
+ *---------------------------------------------------------
+ * Function: be_eth_sq_create_ex
+ * Creates an ethernet send ring - extended version with
+ * additional parameters.
+ * pfob -
+ * rd - ring address
+ * length_in_bytes -
+ * type - The type of ring to create.
+ * ulp - The requested ULP number for the ring.
+ * This should be zero based, i.e. 0,1,2. This must
+ * be valid NIC ULP based on the firmware config.
+ * All doorbells for this ring must be sent to
+ * this ULP. The first network ring allocated for
+ * each ULP are higher performance than subsequent rings.
+ * cq_object - cq object for completions
+ * ex_parameters - Additional parameters (that may increase in
+ * future revisions). These parameters are only used
+ * for certain ring types -- see
+ * struct be_eth_sq_parameters for details.
+ * eth_sq -
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *---------------------------------------------------------
+ */
+int
+be_eth_sq_create_ex(struct be_function_object *pfob, struct ring_desc *rd,
+ u32 length, u32 type, u32 ulp, struct be_cq_object *cq_object,
+ struct be_eth_sq_parameters *ex_parameters,
+ struct be_ethsq_object *eth_sq)
+{
+ struct FWCMD_COMMON_ETH_TX_CREATE *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ u32 n;
+ unsigned long irql;
+
+ ASSERT(rd);
+ ASSERT(eth_sq);
+ ASSERT(ex_parameters);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ memset(eth_sq, 0, sizeof(*eth_sq));
+
+ eth_sq->parent_function = pfob;
+ eth_sq->bid = 0xFFFFFFFF;
+ eth_sq->cq_object = cq_object;
+
+ /* Translate hwlib interface to arm interface. */
+ switch (type) {
+ case BE_ETH_TX_RING_TYPE_FORWARDING:
+ type = ETH_TX_RING_TYPE_FORWARDING;
+ break;
+ case BE_ETH_TX_RING_TYPE_STANDARD:
+ type = ETH_TX_RING_TYPE_STANDARD;
+ break;
+ case BE_ETH_TX_RING_TYPE_BOUND:
+ ASSERT(ex_parameters->port < 2);
+ type = ETH_TX_RING_TYPE_BOUND;
+ break;
+ default:
+ TRACE(DL_ERR, "Invalid eth tx ring type:%d", type);
+ return BE_NOT_OK;
+ break;
+ }
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ ASSERT(wrb);
+ TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ /* NIC must be supported by the current config. */
+ ASSERT(pfob->fw_config.nic_ulp_mask);
+
+ /*
+ * The ulp parameter must select a valid NIC ULP
+ * for the current config.
+ */
+ ASSERT((1 << ulp) & pfob->fw_config.nic_ulp_mask);
+
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_TX_CREATE);
+ fwcmd->header.request.port_number = ex_parameters->port;
+
+ AMAP_SET_BITS_PTR(ETX_CONTEXT, pd_id,
+ &fwcmd->params.request.context, 0);
+
+ n = be_ring_length_to_encoding(length, sizeof(struct ETH_WRB_AMAP));
+ AMAP_SET_BITS_PTR(ETX_CONTEXT, tx_ring_size,
+ &fwcmd->params.request.context, n);
+
+ AMAP_SET_BITS_PTR(ETX_CONTEXT, cq_id_send,
+ &fwcmd->params.request.context, cq_object->cq_id);
+
+ n = pfob->pci_function_number;
+ AMAP_SET_BITS_PTR(ETX_CONTEXT, func, &fwcmd->params.request.context, n);
+
+ fwcmd->params.request.type = type;
+ fwcmd->params.request.ulp_num = (1 << ulp);
+ fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE);
+ ASSERT(PAGES_SPANNED(rd->va, rd->length) >=
+ fwcmd->params.request.num_pages);
+
+ /* Create a page list for the FWCMD. */
+ be_rd_to_pa_list(rd, fwcmd->params.request.pages,
+ ARRAY_SIZE(fwcmd->params.request.pages));
+
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "MCC to create etx queue failed.");
+ goto Error;
+ }
+ /* save the butler ID */
+ eth_sq->bid = fwcmd->params.response.cid;
+
+ /* add a reference to the corresponding CQ */
+ atomic_inc(&cq_object->ref_count);
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+
+/*
+ This routine destroys an ethernet send queue
+
+ EthSq - EthSq Handle returned from EthSqCreate
+
+ This function always return BE_SUCCESS.
+
+ This function frees memory allocated by EthSqCreate for the EthSq Object.
+
+*/
+int be_eth_sq_destroy(struct be_ethsq_object *eth_sq)
+{
+ int status = 0;
+
+ /* Send fwcmd to destroy the queue. */
+ status = be_function_ring_destroy(eth_sq->parent_function, eth_sq->bid,
+ FWCMD_RING_TYPE_ETH_TX, NULL, NULL, NULL, NULL);
+ ASSERT(status == 0);
+
+ /* Derefence any associated CQs. */
+ atomic_dec(&eth_sq->cq_object->ref_count);
+ return status;
+}
+/*
+ This routine attempts to set the transmit flow control parameters.
+
+ FunctionObject - Handle to a function object
+
+ txfc_enable - transmit flow control enable - true for
+ enable, false for disable
+
+ rxfc_enable - receive flow control enable - true for
+ enable, false for disable
+
+ Returns BE_SUCCESS if successfull, otherwise a useful int error
+ code is returned.
+
+ IRQL: < DISPATCH_LEVEL
+
+ This function always fails in non-privileged machine context.
+*/
+int
+be_eth_set_flow_control(struct be_function_object *pfob,
+ bool txfc_enable, bool rxfc_enable)
+{
+ struct FWCMD_COMMON_SET_FLOW_CONTROL *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FLOW_CONTROL);
+
+ fwcmd->params.request.rx_flow_control = rxfc_enable;
+ fwcmd->params.request.tx_flow_control = txfc_enable;
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+
+ if (status != 0) {
+ TRACE(DL_ERR, "set flow control fwcmd failed.");
+ goto error;
+ }
+
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This routine attempts to get the transmit flow control parameters.
+
+ pfob - Handle to a function object
+
+ txfc_enable - transmit flow control enable - true for
+ enable, false for disable
+
+ rxfc_enable - receive flow control enable - true for enable,
+ false for disable
+
+ Returns BE_SUCCESS if successfull, otherwise a useful int error code
+ is returned.
+
+ IRQL: < DISPATCH_LEVEL
+
+ This function always fails in non-privileged machine context.
+*/
+int
+be_eth_get_flow_control(struct be_function_object *pfob,
+ bool *txfc_enable, bool *rxfc_enable)
+{
+ struct FWCMD_COMMON_GET_FLOW_CONTROL *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FLOW_CONTROL);
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+
+ if (status != 0) {
+ TRACE(DL_ERR, "get flow control fwcmd failed.");
+ goto error;
+ }
+
+ *txfc_enable = fwcmd->params.response.tx_flow_control;
+ *rxfc_enable = fwcmd->params.response.rx_flow_control;
+
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ *---------------------------------------------------------
+ * Function: be_eth_set_qos
+ * This function sets the ethernet transmit Quality of Service (QoS)
+ * characteristics of BladeEngine for the domain. All ethernet
+ * transmit rings of the domain will evenly share the bandwidth.
+ * The exeception to sharing is the host primary (super) ethernet
+ * transmit ring as well as the host ethernet forwarding ring
+ * for missed offload data.
+ * pfob -
+ * max_bps - the maximum bits per second in units of
+ * 10 Mbps (valid 0-100)
+ * max_pps - the maximum packets per second in units
+ * of 1 Kpps (0 indicates no limit)
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *---------------------------------------------------------
+ */
+int
+be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps)
+{
+ struct FWCMD_COMMON_SET_QOS *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_QOS);
+
+ /* Set fields in fwcmd */
+ fwcmd->params.request.max_bits_per_second_NIC = max_bps;
+ fwcmd->params.request.max_packets_per_second_NIC = max_pps;
+ fwcmd->params.request.valid_flags = QOS_BITS_NIC | QOS_PKTS_NIC;
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+
+ if (status != 0)
+ TRACE(DL_ERR, "network set qos fwcmd failed.");
+
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ *---------------------------------------------------------
+ * Function: be_eth_get_qos
+ * This function retrieves the ethernet transmit Quality of Service (QoS)
+ * characteristics for the domain.
+ * max_bps - the maximum bits per second in units of
+ * 10 Mbps (valid 0-100)
+ * max_pps - the maximum packets per second in units of
+ * 1 Kpps (0 indicates no limit)
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *---------------------------------------------------------
+ */
+int
+be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps)
+{
+ struct FWCMD_COMMON_GET_QOS *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_QOS);
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+
+ if (status != 0) {
+ TRACE(DL_ERR, "network get qos fwcmd failed.");
+ goto error;
+ }
+
+ *max_bps = fwcmd->params.response.max_bits_per_second_NIC;
+ *max_pps = fwcmd->params.response.max_packets_per_second_NIC;
+
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ *---------------------------------------------------------
+ * Function: be_eth_set_frame_size
+ * This function sets the ethernet maximum frame size. The previous
+ * values are returned.
+ * pfob -
+ * tx_frame_size - maximum transmit frame size in bytes
+ * rx_frame_size - maximum receive frame size in bytes
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *---------------------------------------------------------
+ */
+int
+be_eth_set_frame_size(struct be_function_object *pfob,
+ u32 *tx_frame_size, u32 *rx_frame_size)
+{
+ struct FWCMD_COMMON_SET_FRAME_SIZE *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FRAME_SIZE);
+ fwcmd->params.request.max_tx_frame_size = *tx_frame_size;
+ fwcmd->params.request.max_rx_frame_size = *rx_frame_size;
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+
+ if (status != 0) {
+ TRACE(DL_ERR, "network set frame size fwcmd failed.");
+ goto error;
+ }
+
+ *tx_frame_size = fwcmd->params.response.chip_max_tx_frame_size;
+ *rx_frame_size = fwcmd->params.response.chip_max_rx_frame_size;
+
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+
+/*
+ This routine creates a Ethernet receive ring.
+
+ pfob - handle to a function object
+ rq_base_va - base VA for the default receive ring. this must be
+ exactly 8K in length and continguous physical memory.
+ cq_object - handle to a previously created CQ to be associated
+ with the RQ.
+ pp_eth_rq - pointer to an opqaue handle where an eth
+ receive object is returned.
+ Returns BE_SUCCESS if successfull, , otherwise a useful
+ int error code is returned.
+
+ IRQL: < DISPATCH_LEVEL
+ this function allocates a struct be_ethrq_object *object.
+ there must be no more than 1 of these per function object, unless the
+ function object supports RSS (is networking and on the host).
+ the rq_base_va must point to a buffer of exactly 8K.
+ the erx::host_cqid (or host_stor_cqid) register and erx::ring_page registers
+ will be updated as appropriate on return
+*/
+int
+be_eth_rq_create(struct be_function_object *pfob,
+ struct ring_desc *rd, struct be_cq_object *cq_object,
+ struct be_cq_object *bcmc_cq_object,
+ struct be_ethrq_object *eth_rq)
+{
+ int status = 0;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ struct FWCMD_COMMON_ETH_RX_CREATE *fwcmd = NULL;
+ unsigned long irql;
+
+ /* MPU will set the */
+ ASSERT(rd);
+ ASSERT(eth_rq);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ eth_rq->parent_function = pfob;
+ eth_rq->cq_object = cq_object;
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_RX_CREATE);
+
+ fwcmd->params.request.num_pages = 2; /* required length */
+ fwcmd->params.request.cq_id = cq_object->cq_id;
+
+ if (bcmc_cq_object)
+ fwcmd->params.request.bcmc_cq_id = bcmc_cq_object->cq_id;
+ else
+ fwcmd->params.request.bcmc_cq_id = 0xFFFF;
+
+ /* Create a page list for the FWCMD. */
+ be_rd_to_pa_list(rd, fwcmd->params.request.pages,
+ ARRAY_SIZE(fwcmd->params.request.pages));
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "fwcmd to map eth rxq frags failed.");
+ goto Error;
+ }
+ /* Save the ring ID for cleanup. */
+ eth_rq->rid = fwcmd->params.response.id;
+
+ atomic_inc(&cq_object->ref_count);
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This routine destroys an Ethernet receive queue
+
+ eth_rq - ethernet receive queue handle returned from eth_rq_create
+
+ Returns BE_SUCCESS on success and an appropriate int on failure.
+
+ This function frees resourcs allocated by EthRqCreate.
+ The erx::host_cqid (or host_stor_cqid) register and erx::ring_page
+ registers will be updated as appropriate on return
+ IRQL: < DISPATCH_LEVEL
+*/
+
+static void be_eth_rq_destroy_internal_cb(void *context, int status,
+ struct MCC_WRB_AMAP *wrb)
+{
+ struct be_ethrq_object *eth_rq = (struct be_ethrq_object *) context;
+
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "Destroy eth rq failed in internal callback.\n");
+ } else {
+ /* Dereference any CQs associated with this queue. */
+ atomic_dec(&eth_rq->cq_object->ref_count);
+ }
+
+ return;
+}
+
+int be_eth_rq_destroy(struct be_ethrq_object *eth_rq)
+{
+ int status = BE_SUCCESS;
+
+ /* Send fwcmd to destroy the RQ. */
+ status = be_function_ring_destroy(eth_rq->parent_function,
+ eth_rq->rid, FWCMD_RING_TYPE_ETH_RX, NULL, NULL,
+ be_eth_rq_destroy_internal_cb, eth_rq);
+
+ return status;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * Function: be_eth_rq_destroy_options
+ * Destroys an ethernet receive ring with finer granularity options
+ * than the standard be_eth_rq_destroy() API function.
+ * eth_rq -
+ * flush - Set to 1 to flush the ring, set to 0 to bypass the flush
+ * cb - Callback function on completion
+ * cb_context - Callback context
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *----------------------------------------------------------------------------
+ */
+int
+be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush,
+ mcc_wrb_cqe_callback cb, void *cb_context)
+{
+ struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = BE_SUCCESS;
+ struct be_function_object *pfob = NULL;
+ unsigned long irql;
+
+ pfob = eth_rq->parent_function;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ TRACE(DL_INFO, "Destroy eth_rq ring id:%d, flush:%d", eth_rq->rid,
+ flush);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ ASSERT(wrb);
+ TRACE(DL_ERR, "No free MCC WRBs in destroy eth_rq ring.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY);
+
+ fwcmd->params.request.id = eth_rq->rid;
+ fwcmd->params.request.ring_type = FWCMD_RING_TYPE_ETH_RX;
+ fwcmd->params.request.bypass_flush = ((0 == flush) ? 1 : 0);
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context,
+ be_eth_rq_destroy_internal_cb, eth_rq, fwcmd, NULL);
+
+ if (status != BE_SUCCESS && status != BE_PENDING) {
+ TRACE(DL_ERR, "eth_rq ring destroy failed. id:%d, flush:%d",
+ eth_rq->rid, flush);
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This routine queries the frag size for erx.
+
+ pfob - handle to a function object
+
+ frag_size_bytes - erx frag size in bytes that is/was set.
+
+ Returns BE_SUCCESS if successfull, otherwise a useful int error
+ code is returned.
+
+ IRQL: < DISPATCH_LEVEL
+
+*/
+int
+be_eth_rq_get_frag_size(struct be_function_object *pfob, u32 *frag_size_bytes)
+{
+ struct FWCMD_ETH_GET_RX_FRAG_SIZE *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ ASSERT(frag_size_bytes);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ return BE_STATUS_NO_MCC_WRB;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_GET_RX_FRAG_SIZE);
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+
+ if (status != 0) {
+ TRACE(DL_ERR, "get frag size fwcmd failed.");
+ goto error;
+ }
+
+ *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2;
+
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This routine attempts to set the frag size for erx. If the frag size is
+ already set, the attempt fails and the current frag size is returned.
+
+ pfob - Handle to a function object
+
+ frag_size - Erx frag size in bytes that is/was set.
+
+ current_frag_size_bytes - Pointer to location where currrent frag
+ is to be rturned
+
+ Returns BE_SUCCESS if successfull, otherwise a useful int error
+ code is returned.
+
+ IRQL: < DISPATCH_LEVEL
+
+ This function always fails in non-privileged machine context.
+*/
+int
+be_eth_rq_set_frag_size(struct be_function_object *pfob,
+ u32 frag_size, u32 *frag_size_bytes)
+{
+ struct FWCMD_ETH_SET_RX_FRAG_SIZE *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ ASSERT(frag_size_bytes);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_SET_RX_FRAG_SIZE);
+
+ ASSERT(frag_size >= 128 && frag_size <= 16 * 1024);
+
+ /* This is the log2 of the fragsize. This is not the exact
+ * ERX encoding. */
+ fwcmd->params.request.new_fragsize_log2 = __ilog2_u32(frag_size);
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+
+ if (status != 0) {
+ TRACE(DL_ERR, "set frag size fwcmd failed.");
+ goto error;
+ }
+
+ *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2;
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+
+/*
+ This routine gets or sets a mac address for a domain
+ given the port and mac.
+
+ FunctionObject - Function object handle.
+ port1 - Set to TRUE if this function will set/get the Port 1
+ address. Only the host may set this to TRUE.
+ mac1 - Set to TRUE if this function will set/get the
+ MAC 1 address. Only the host may set this to TRUE.
+ write - Set to TRUE if this function should write the mac address.
+ mac_address - Buffer of the mac address to read or write.
+
+ Returns BE_SUCCESS if successfull, otherwise a useful int is returned.
+
+ IRQL: < DISPATCH_LEVEL
+*/
+int be_rxf_mac_address_read_write(struct be_function_object *pfob,
+ bool port1, /* VM must always set to false */
+ bool mac1, /* VM must always set to false */
+ bool mgmt, bool write,
+ bool permanent, u8 *mac_address,
+ mcc_wrb_cqe_callback cb, /* optional */
+ void *cb_context) /* optional */
+{
+ int status = BE_SUCCESS;
+ union {
+ struct FWCMD_COMMON_NTWK_MAC_QUERY *query;
+ struct FWCMD_COMMON_NTWK_MAC_SET *set;
+ } fwcmd = {NULL};
+ struct MCC_WRB_AMAP *wrb = NULL;
+ u32 type = 0;
+ unsigned long irql;
+ struct be_mcc_wrb_response_copy rc;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ ASSERT(mac_address);
+
+ ASSERT(port1 == false);
+ ASSERT(mac1 == false);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+
+ if (mgmt) {
+ type = MAC_ADDRESS_TYPE_MANAGEMENT;
+ } else {
+ if (pfob->type == BE_FUNCTION_TYPE_NETWORK)
+ type = MAC_ADDRESS_TYPE_NETWORK;
+ else
+ type = MAC_ADDRESS_TYPE_STORAGE;
+ }
+
+ if (write) {
+ /* Prepares an embedded fwcmd, including
+ * request/response sizes.
+ */
+ fwcmd.set = BE_PREPARE_EMBEDDED_FWCMD(pfob,
+ wrb, COMMON_NTWK_MAC_SET);
+
+ fwcmd.set->params.request.invalidate = 0;
+ fwcmd.set->params.request.mac1 = (mac1 ? 1 : 0);
+ fwcmd.set->params.request.port = (port1 ? 1 : 0);
+ fwcmd.set->params.request.type = type;
+
+ /* Copy the mac address to set. */
+ fwcmd.set->params.request.mac.SizeOfStructure =
+ sizeof(fwcmd.set->params.request.mac);
+ memcpy(fwcmd.set->params.request.mac.MACAddress,
+ mac_address, ETH_ALEN);
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL,
+ cb, cb_context, NULL, NULL, fwcmd.set, NULL);
+
+ } else {
+
+ /*
+ * Prepares an embedded fwcmd, including
+ * request/response sizes.
+ */
+ fwcmd.query = BE_PREPARE_EMBEDDED_FWCMD(pfob,
+ wrb, COMMON_NTWK_MAC_QUERY);
+
+ fwcmd.query->params.request.mac1 = (mac1 ? 1 : 0);
+ fwcmd.query->params.request.port = (port1 ? 1 : 0);
+ fwcmd.query->params.request.type = type;
+ fwcmd.query->params.request.permanent = permanent;
+
+ rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_MAC_QUERY,
+ params.response.mac.MACAddress);
+ rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_MAC_QUERY,
+ params.response.mac.MACAddress);
+ rc.va = mac_address;
+ /* Post the f/w command (with a copy for the response) */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb,
+ cb_context, NULL, NULL, fwcmd.query, &rc);
+ }
+
+ if (status < 0) {
+ TRACE(DL_ERR, "mac set/query failed.");
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This routine writes data to context memory.
+
+ pfob - Function object handle.
+ mac_table - Set to the 128-bit multicast address hash table.
+
+ Returns BE_SUCCESS if successfull, otherwise a useful int is returned.
+
+ IRQL: < DISPATCH_LEVEL
+*/
+
+int be_rxf_multicast_config(struct be_function_object *pfob,
+ bool promiscuous, u32 num, u8 *mac_table,
+ mcc_wrb_cqe_callback cb, /* optional */
+ void *cb_context,
+ struct be_multicast_q_ctxt *q_ctxt)
+{
+ int status = BE_SUCCESS;
+ struct FWCMD_COMMON_NTWK_MULTICAST_SET *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ struct be_generic_q_ctxt *generic_ctxt = NULL;
+ unsigned long irql;
+
+ ASSERT(num <= ARRAY_SIZE(fwcmd->params.request.mac));
+
+ if (num > ARRAY_SIZE(fwcmd->params.request.mac)) {
+ TRACE(DL_ERR, "Too many multicast addresses. BE supports %d.",
+ (int) ARRAY_SIZE(fwcmd->params.request.mac));
+ return BE_NOT_OK;
+ }
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ if (q_ctxt && cb) {
+ wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
+ generic_ctxt->context.bytes = sizeof(*q_ctxt);
+ } else {
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_MULTICAST_SET);
+
+ fwcmd->params.request.promiscuous = promiscuous;
+ if (!promiscuous) {
+ fwcmd->params.request.num_mac = num;
+ if (num > 0) {
+ ASSERT(mac_table);
+ memcpy(fwcmd->params.request.mac,
+ mac_table, ETH_ALEN * num);
+ }
+ }
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
+ cb, cb_context, NULL, NULL, fwcmd, NULL);
+ if (status < 0) {
+ TRACE(DL_ERR, "multicast fwcmd failed.");
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This routine adds or removes a vlan tag from the rxf table.
+
+ FunctionObject - Function object handle.
+ VLanTag - VLan tag to add or remove.
+ Add - Set to TRUE if this will add a vlan tag
+
+ Returns BE_SUCCESS if successfull, otherwise a useful int is returned.
+
+ IRQL: < DISPATCH_LEVEL
+*/
+int be_rxf_vlan_config(struct be_function_object *pfob,
+ bool promiscuous, u32 num, u16 *vlan_tag_array,
+ mcc_wrb_cqe_callback cb, /* optional */
+ void *cb_context,
+ struct be_vlan_q_ctxt *q_ctxt) /* optional */
+{
+ int status = BE_SUCCESS;
+ struct FWCMD_COMMON_NTWK_VLAN_CONFIG *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ struct be_generic_q_ctxt *generic_ctxt = NULL;
+ unsigned long irql;
+
+ if (num > ARRAY_SIZE(fwcmd->params.request.vlan_tag)) {
+ TRACE(DL_ERR, "Too many VLAN tags.");
+ return BE_NOT_OK;
+ }
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ if (q_ctxt && cb) {
+ wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
+ generic_ctxt->context.bytes = sizeof(*q_ctxt);
+ } else {
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_VLAN_CONFIG);
+
+ fwcmd->params.request.promiscuous = promiscuous;
+ if (!promiscuous) {
+ fwcmd->params.request.num_vlan = num;
+
+ if (num > 0) {
+ ASSERT(vlan_tag_array);
+ memcpy(fwcmd->params.request.vlan_tag, vlan_tag_array,
+ num * sizeof(vlan_tag_array[0]));
+ }
+ }
+
+ /* Post the commadn */
+ status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
+ cb, cb_context, NULL, NULL, fwcmd, NULL);
+ if (status < 0) {
+ TRACE(DL_ERR, "vlan fwcmd failed.");
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+
+int be_rxf_link_status(struct be_function_object *pfob,
+ struct BE_LINK_STATUS *link_status,
+ mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ struct be_link_status_q_ctxt *q_ctxt)
+{
+ struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ struct be_generic_q_ctxt *generic_ctxt = NULL;
+ unsigned long irql;
+ struct be_mcc_wrb_response_copy rc;
+
+ ASSERT(link_status);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+
+ if (!wrb) {
+ if (q_ctxt && cb) {
+ wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
+ generic_ctxt->context.bytes = sizeof(*q_ctxt);
+ } else {
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb,
+ COMMON_NTWK_LINK_STATUS_QUERY);
+
+ rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY,
+ params.response);
+ rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY,
+ params.response);
+ rc.va = link_status;
+ /* Post or queue the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
+ cb, cb_context, NULL, NULL, fwcmd, &rc);
+
+ if (status < 0) {
+ TRACE(DL_ERR, "link status fwcmd failed.");
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+int
+be_rxf_query_eth_statistics(struct be_function_object *pfob,
+ struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd,
+ u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ struct be_nonembedded_q_ctxt *q_ctxt)
+{
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ struct be_generic_q_ctxt *generic_ctxt = NULL;
+ unsigned long irql;
+
+ ASSERT(va_for_fwcmd);
+ ASSERT(pa_for_fwcmd);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+
+ if (!wrb) {
+ if (q_ctxt && cb) {
+ wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
+ generic_ctxt->context.bytes = sizeof(*q_ctxt);
+ } else {
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ }
+
+ TRACE(DL_INFO, "Query eth stats. fwcmd va:%p pa:0x%08x_%08x",
+ va_for_fwcmd, upper_32_bits(pa_for_fwcmd), (u32)pa_for_fwcmd);
+
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ va_for_fwcmd = BE_PREPARE_NONEMBEDDED_FWCMD(pfob, wrb,
+ va_for_fwcmd, pa_for_fwcmd, ETH_GET_STATISTICS);
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
+ cb, cb_context, NULL, NULL, va_for_fwcmd, NULL);
+ if (status < 0) {
+ TRACE(DL_ERR, "eth stats fwcmd failed.");
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+int
+be_rxf_promiscuous(struct be_function_object *pfob,
+ bool enable_port0, bool enable_port1,
+ mcc_wrb_cqe_callback cb, void *cb_context,
+ struct be_promiscuous_q_ctxt *q_ctxt)
+{
+ struct FWCMD_ETH_PROMISCUOUS *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ struct be_generic_q_ctxt *generic_ctxt = NULL;
+ unsigned long irql;
+
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+
+ if (!wrb) {
+ if (q_ctxt && cb) {
+ wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
+ generic_ctxt->context.bytes = sizeof(*q_ctxt);
+ } else {
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_PROMISCUOUS);
+
+ fwcmd->params.request.port0_promiscuous = enable_port0;
+ fwcmd->params.request.port1_promiscuous = enable_port1;
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
+ cb, cb_context, NULL, NULL, fwcmd, NULL);
+
+ if (status < 0) {
+ TRACE(DL_ERR, "promiscuous fwcmd failed.");
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+
+/*
+ *-------------------------------------------------------------------------
+ * Function: be_rxf_filter_config
+ * Configures BladeEngine ethernet receive filter settings.
+ * pfob -
+ * settings - Pointer to the requested filter settings.
+ * The response from BladeEngine will be placed back
+ * in this structure.
+ * cb - optional
+ * cb_context - optional
+ * q_ctxt - Optional. Pointer to a previously allocated struct.
+ * If the MCC WRB ring is full, this structure is
+ * used to queue the operation. It will be posted
+ * to the MCC ring when space becomes available. All
+ * queued commands will be posted to the ring in
+ * the order they are received. It is always valid
+ * to pass a pointer to a generic
+ * be_generic_q_ctxt. However, the specific
+ * context structs are generally smaller than
+ * the generic struct.
+ * return pend_status - BE_SUCCESS (0) on success.
+ * BE_PENDING (postive value) if the FWCMD
+ * completion is pending. Negative error code on failure.
+ *---------------------------------------------------------------------------
+ */
+int
+be_rxf_filter_config(struct be_function_object *pfob,
+ struct NTWK_RX_FILTER_SETTINGS *settings,
+ mcc_wrb_cqe_callback cb, void *cb_context,
+ struct be_rxf_filter_q_ctxt *q_ctxt)
+{
+ struct FWCMD_COMMON_NTWK_RX_FILTER *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ struct be_generic_q_ctxt *generic_ctxt = NULL;
+ unsigned long irql;
+ struct be_mcc_wrb_response_copy rc;
+
+ ASSERT(settings);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+
+ if (!wrb) {
+ if (q_ctxt && cb) {
+ wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt;
+ generic_ctxt->context.bytes = sizeof(*q_ctxt);
+ } else {
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_RX_FILTER);
+ memcpy(&fwcmd->params.request, settings, sizeof(*settings));
+
+ rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_RX_FILTER,
+ params.response);
+ rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_RX_FILTER,
+ params.response);
+ rc.va = settings;
+ /* Post or queue the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt,
+ cb, cb_context, NULL, NULL, fwcmd, &rc);
+
+ if (status < 0) {
+ TRACE(DL_ERR, "RXF/ERX filter config fwcmd failed.");
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
diff --git a/drivers/staging/benet/etx_context.h b/drivers/staging/benet/etx_context.h
new file mode 100644
index 000000000000..554fbe5d127b
--- /dev/null
+++ b/drivers/staging/benet/etx_context.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __etx_context_amap_h__
+#define __etx_context_amap_h__
+
+/* ETX ring context structure. */
+struct BE_ETX_CONTEXT_AMAP {
+ u8 tx_cidx[11]; /* DWORD 0 */
+ u8 rsvd0[5]; /* DWORD 0 */
+ u8 rsvd1[16]; /* DWORD 0 */
+ u8 tx_pidx[11]; /* DWORD 1 */
+ u8 rsvd2; /* DWORD 1 */
+ u8 tx_ring_size[4]; /* DWORD 1 */
+ u8 pd_id[5]; /* DWORD 1 */
+ u8 pd_id_not_valid; /* DWORD 1 */
+ u8 cq_id_send[10]; /* DWORD 1 */
+ u8 rsvd3[32]; /* DWORD 2 */
+ u8 rsvd4[32]; /* DWORD 3 */
+ u8 cur_bytes[32]; /* DWORD 4 */
+ u8 max_bytes[32]; /* DWORD 5 */
+ u8 time_stamp[32]; /* DWORD 6 */
+ u8 rsvd5[11]; /* DWORD 7 */
+ u8 func; /* DWORD 7 */
+ u8 rsvd6[20]; /* DWORD 7 */
+ u8 cur_txd_count[32]; /* DWORD 8 */
+ u8 max_txd_count[32]; /* DWORD 9 */
+ u8 rsvd7[32]; /* DWORD 10 */
+ u8 rsvd8[32]; /* DWORD 11 */
+ u8 rsvd9[32]; /* DWORD 12 */
+ u8 rsvd10[32]; /* DWORD 13 */
+ u8 rsvd11[32]; /* DWORD 14 */
+ u8 rsvd12[32]; /* DWORD 15 */
+} __packed;
+struct ETX_CONTEXT_AMAP {
+ u32 dw[16];
+};
+
+#endif /* __etx_context_amap_h__ */
diff --git a/drivers/staging/benet/funcobj.c b/drivers/staging/benet/funcobj.c
new file mode 100644
index 000000000000..0f57eb58daef
--- /dev/null
+++ b/drivers/staging/benet/funcobj.c
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#include "hwlib.h"
+#include "bestatus.h"
+
+
+int
+be_function_internal_query_firmware_config(struct be_function_object *pfob,
+ struct BE_FIRMWARE_CONFIG *config)
+{
+ struct FWCMD_COMMON_FIRMWARE_CONFIG *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+ struct be_mcc_wrb_response_copy rc;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_FIRMWARE_CONFIG);
+
+ rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_FIRMWARE_CONFIG,
+ params.response);
+ rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_FIRMWARE_CONFIG,
+ params.response);
+ rc.va = config;
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL,
+ NULL, NULL, NULL, fwcmd, &rc);
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This allocates and initializes a function object based on the information
+ provided by upper layer drivers.
+
+ Returns BE_SUCCESS on success and an appropriate int on failure.
+
+ A function object represents a single BladeEngine (logical) PCI function.
+ That is a function object either represents
+ the networking side of BladeEngine or the iSCSI side of BladeEngine.
+
+ This routine will also detect and create an appropriate PD object for the
+ PCI function as needed.
+*/
+int
+be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va,
+ u8 __iomem *pci_va, u32 function_type,
+ struct ring_desc *mailbox, struct be_function_object *pfob)
+{
+ int status;
+
+ ASSERT(pfob); /* not a magic assert */
+ ASSERT(function_type <= 2);
+
+ TRACE(DL_INFO, "Create function object. type:%s object:0x%p",
+ (function_type == BE_FUNCTION_TYPE_ISCSI ? "iSCSI" :
+ (function_type == BE_FUNCTION_TYPE_NETWORK ? "Network" :
+ "Arm")), pfob);
+
+ memset(pfob, 0, sizeof(*pfob));
+
+ pfob->type = function_type;
+ pfob->csr_va = csr_va;
+ pfob->db_va = db_va;
+ pfob->pci_va = pci_va;
+
+ spin_lock_init(&pfob->cq_lock);
+ spin_lock_init(&pfob->post_lock);
+ spin_lock_init(&pfob->mcc_context_lock);
+
+
+ pfob->pci_function_number = 1;
+
+
+ pfob->emulate = false;
+ TRACE(DL_NOTE, "Non-emulation mode");
+ status = be_drive_POST(pfob);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "BladeEngine POST failed.");
+ goto error;
+ }
+
+ /* Initialize the mailbox */
+ status = be_mpu_init_mailbox(pfob, mailbox);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "Failed to initialize mailbox.");
+ goto error;
+ }
+ /*
+ * Cache the firmware config for ASSERTs in hwclib and later
+ * driver queries.
+ */
+ status = be_function_internal_query_firmware_config(pfob,
+ &pfob->fw_config);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "Failed to query firmware config.");
+ goto error;
+ }
+
+error:
+ if (status != BE_SUCCESS) {
+ /* No cleanup necessary */
+ TRACE(DL_ERR, "Failed to create function.");
+ memset(pfob, 0, sizeof(*pfob));
+ }
+ return status;
+}
+
+/*
+ This routine drops the reference count on a given function object. Once
+ the reference count falls to zero, the function object is destroyed and all
+ resources held are freed.
+
+ FunctionObject - The function object to drop the reference to.
+*/
+int be_function_object_destroy(struct be_function_object *pfob)
+{
+ TRACE(DL_INFO, "Destroy pfob. Object:0x%p",
+ pfob);
+
+
+ ASSERT(pfob->mcc == NULL);
+
+ return BE_SUCCESS;
+}
+
+int be_function_cleanup(struct be_function_object *pfob)
+{
+ int status = 0;
+ u32 isr;
+ u32 host_intr;
+ struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl;
+
+
+ if (pfob->type == BE_FUNCTION_TYPE_NETWORK) {
+ status = be_rxf_multicast_config(pfob, false, 0,
+ NULL, NULL, NULL, NULL);
+ ASSERT(status == BE_SUCCESS);
+ }
+ /* VLAN */
+ status = be_rxf_vlan_config(pfob, false, 0, NULL, NULL, NULL, NULL);
+ ASSERT(status == BE_SUCCESS);
+ /*
+ * MCC Queue -- Switches to mailbox mode. May want to destroy
+ * all but the MCC CQ before this call if polling CQ is much better
+ * performance than polling mailbox register.
+ */
+ if (pfob->mcc)
+ status = be_mcc_ring_destroy(pfob->mcc);
+ /*
+ * If interrupts are disabled, clear any CEV interrupt assertions that
+ * fired after we stopped processing EQs.
+ */
+ ctrl.dw[0] = PCICFG1_READ(pfob, host_timer_int_ctrl);
+ host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR,
+ hostintr, ctrl.dw);
+ if (!host_intr)
+ if (pfob->type == BE_FUNCTION_TYPE_NETWORK)
+ isr = CSR_READ(pfob, cev.isr1);
+ else
+ isr = CSR_READ(pfob, cev.isr0);
+ else
+ /* This should never happen... */
+ TRACE(DL_ERR, "function_cleanup called with interrupt enabled");
+ /* Function object destroy */
+ status = be_function_object_destroy(pfob);
+ ASSERT(status == BE_SUCCESS);
+
+ return status;
+}
+
+
+void *
+be_function_prepare_embedded_fwcmd(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb, u32 payld_len, u32 request_length,
+ u32 response_length, u32 opcode, u32 subsystem)
+{
+ struct FWCMD_REQUEST_HEADER *header = NULL;
+ u32 n;
+
+ ASSERT(wrb);
+
+ n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
+ AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 1);
+ AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, min(payld_len, n));
+ header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n);
+
+ header->timeout = 0;
+ header->domain = 0;
+ header->request_length = max(request_length, response_length);
+ header->opcode = opcode;
+ header->subsystem = subsystem;
+
+ return header;
+}
+
+void *
+be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb,
+ void *fwcmd_va, u64 fwcmd_pa,
+ u32 payld_len,
+ u32 request_length,
+ u32 response_length,
+ u32 opcode, u32 subsystem)
+{
+ struct FWCMD_REQUEST_HEADER *header = NULL;
+ u32 n;
+ struct MCC_WRB_PAYLOAD_AMAP *plp;
+
+ ASSERT(wrb);
+ ASSERT(fwcmd_va);
+
+ header = (struct FWCMD_REQUEST_HEADER *) fwcmd_va;
+
+ AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 0);
+ AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, payld_len);
+
+ /*
+ * Assume one fragment. The caller may override the SGL by
+ * rewriting the 0th length and adding more entries. They
+ * will also need to update the sge_count.
+ */
+ AMAP_SET_BITS_PTR(MCC_WRB, sge_count, wrb, 1);
+
+ n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
+ plp = (struct MCC_WRB_PAYLOAD_AMAP *)((u8 *)wrb + n);
+ AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].length, plp, payld_len);
+ AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_lo, plp, (u32)fwcmd_pa);
+ AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_hi, plp,
+ upper_32_bits(fwcmd_pa));
+
+ header->timeout = 0;
+ header->domain = 0;
+ header->request_length = max(request_length, response_length);
+ header->opcode = opcode;
+ header->subsystem = subsystem;
+
+ return header;
+}
+
+struct MCC_WRB_AMAP *
+be_function_peek_mcc_wrb(struct be_function_object *pfob)
+{
+ struct MCC_WRB_AMAP *wrb = NULL;
+ u32 offset;
+
+ if (pfob->mcc)
+ wrb = _be_mpu_peek_ring_wrb(pfob->mcc, false);
+ else {
+ offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8;
+ wrb = (struct MCC_WRB_AMAP *) ((u8 *) pfob->mailbox.va +
+ offset);
+ }
+
+ if (wrb)
+ memset(wrb, 0, sizeof(struct MCC_WRB_AMAP));
+
+ return wrb;
+}
+
+#if defined(BE_DEBUG)
+void be_function_debug_print_wrb(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb, void *optional_fwcmd_va,
+ struct be_mcc_wrb_context *wrb_context)
+{
+
+ struct FWCMD_REQUEST_HEADER *header = NULL;
+ u8 embedded;
+ u32 n;
+
+ embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, wrb);
+
+ if (embedded) {
+ n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
+ header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n);
+ } else {
+ header = (struct FWCMD_REQUEST_HEADER *) optional_fwcmd_va;
+ }
+
+ /* Save the completed count before posting for a debug assert. */
+
+ if (header) {
+ wrb_context->opcode = header->opcode;
+ wrb_context->subsystem = header->subsystem;
+
+ } else {
+ wrb_context->opcode = 0;
+ wrb_context->subsystem = 0;
+ }
+}
+#else
+#define be_function_debug_print_wrb(a_, b_, c_, d_)
+#endif
+
+int
+be_function_post_mcc_wrb(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb,
+ struct be_generic_q_ctxt *q_ctxt,
+ mcc_wrb_cqe_callback cb, void *cb_context,
+ mcc_wrb_cqe_callback internal_cb,
+ void *internal_cb_context, void *optional_fwcmd_va,
+ struct be_mcc_wrb_response_copy *rc)
+{
+ int status;
+ struct be_mcc_wrb_context *wrb_context = NULL;
+ u64 *p;
+
+ if (q_ctxt) {
+ /* Initialize context. */
+ q_ctxt->context.internal_cb = internal_cb;
+ q_ctxt->context.internal_cb_context = internal_cb_context;
+ q_ctxt->context.cb = cb;
+ q_ctxt->context.cb_context = cb_context;
+ if (rc) {
+ q_ctxt->context.copy.length = rc->length;
+ q_ctxt->context.copy.fwcmd_offset = rc->fwcmd_offset;
+ q_ctxt->context.copy.va = rc->va;
+ } else
+ q_ctxt->context.copy.length = 0;
+
+ q_ctxt->context.optional_fwcmd_va = optional_fwcmd_va;
+
+ /* Queue this request */
+ status = be_function_queue_mcc_wrb(pfob, q_ctxt);
+
+ goto Error;
+ }
+ /*
+ * Allocate a WRB context struct to hold the callback pointers,
+ * status, etc. This is required if commands complete out of order.
+ */
+ wrb_context = _be_mcc_allocate_wrb_context(pfob);
+ if (!wrb_context) {
+ TRACE(DL_WARN, "Failed to allocate MCC WRB context.");
+ status = BE_STATUS_SYSTEM_RESOURCES;
+ goto Error;
+ }
+ /* Initialize context. */
+ memset(wrb_context, 0, sizeof(*wrb_context));
+ wrb_context->internal_cb = internal_cb;
+ wrb_context->internal_cb_context = internal_cb_context;
+ wrb_context->cb = cb;
+ wrb_context->cb_context = cb_context;
+ if (rc) {
+ wrb_context->copy.length = rc->length;
+ wrb_context->copy.fwcmd_offset = rc->fwcmd_offset;
+ wrb_context->copy.va = rc->va;
+ } else
+ wrb_context->copy.length = 0;
+ wrb_context->wrb = wrb;
+
+ /*
+ * Copy the context pointer into the WRB opaque tag field.
+ * Verify assumption of 64-bit tag with a compile time assert.
+ */
+ p = (u64 *) ((u8 *)wrb + offsetof(struct BE_MCC_WRB_AMAP, tag)/8);
+ *p = (u64)(size_t)wrb_context;
+
+ /* Print info about this FWCMD for debug builds. */
+ be_function_debug_print_wrb(pfob, wrb, optional_fwcmd_va, wrb_context);
+
+ /*
+ * issue the WRB to the MPU as appropriate
+ */
+ if (pfob->mcc) {
+ /*
+ * we're in WRB mode, pass to the mcc layer
+ */
+ status = _be_mpu_post_wrb_ring(pfob->mcc, wrb, wrb_context);
+ } else {
+ /*
+ * we're in mailbox mode
+ */
+ status = _be_mpu_post_wrb_mailbox(pfob, wrb, wrb_context);
+
+ /* mailbox mode always completes synchronously */
+ ASSERT(status != BE_STATUS_PENDING);
+ }
+
+Error:
+
+ return status;
+}
+
+int
+be_function_ring_destroy(struct be_function_object *pfob,
+ u32 id, u32 ring_type, mcc_wrb_cqe_callback cb,
+ void *cb_context, mcc_wrb_cqe_callback internal_cb,
+ void *internal_cb_context)
+{
+
+ struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ int status = 0;
+ unsigned long irql;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ TRACE(DL_INFO, "Destroy ring id:%d type:%d", id, ring_type);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ ASSERT(wrb);
+ TRACE(DL_ERR, "No free MCC WRBs in destroy ring.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY);
+
+ fwcmd->params.request.id = id;
+ fwcmd->params.request.ring_type = ring_type;
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context,
+ internal_cb, internal_cb_context, fwcmd, NULL);
+ if (status != BE_SUCCESS && status != BE_PENDING) {
+ TRACE(DL_ERR, "Ring destroy fwcmd failed. id:%d ring_type:%d",
+ id, ring_type);
+ goto Error;
+ }
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+void
+be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, u32 max_num)
+{
+ u32 num_pages = PAGES_SPANNED(rd->va, rd->length);
+ u32 i = 0;
+ u64 pa = rd->pa;
+ __le64 lepa;
+
+ ASSERT(pa_list);
+ ASSERT(pa);
+
+ for (i = 0; i < min(num_pages, max_num); i++) {
+ lepa = cpu_to_le64(pa);
+ pa_list[i].lo = (u32)lepa;
+ pa_list[i].hi = upper_32_bits(lepa);
+ pa += PAGE_SIZE;
+ }
+}
+
+
+
+/*-----------------------------------------------------------------------------
+ * Function: be_function_get_fw_version
+ * Retrieves the firmware version on the adpater. If the callback is
+ * NULL this call executes synchronously. If the callback is not NULL,
+ * the returned status will be BE_PENDING if the command was issued
+ * successfully.
+ * pfob -
+ * fwv - Pointer to response buffer if callback is NULL.
+ * cb - Callback function invoked when the FWCMD completes.
+ * cb_context - Passed to the callback function.
+ * return pend_status - BE_SUCCESS (0) on success.
+ * BE_PENDING (postive value) if the FWCMD
+ * completion is pending. Negative error code on failure.
+ *---------------------------------------------------------------------------
+ */
+int
+be_function_get_fw_version(struct be_function_object *pfob,
+ struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fwv,
+ mcc_wrb_cqe_callback cb, void *cb_context)
+{
+ int status = BE_SUCCESS;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ struct FWCMD_COMMON_GET_FW_VERSION *fwcmd = NULL;
+ unsigned long irql;
+ struct be_mcc_wrb_response_copy rc;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ TRACE(DL_ERR, "MCC wrb peek failed.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto Error;
+ }
+
+ if (!cb && !fwv) {
+ TRACE(DL_ERR, "callback and response buffer NULL!");
+ status = BE_NOT_OK;
+ goto Error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FW_VERSION);
+
+ rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_GET_FW_VERSION,
+ params.response);
+ rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_GET_FW_VERSION,
+ params.response);
+ rc.va = fwv;
+
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb,
+ cb_context, NULL, NULL, fwcmd, &rc);
+
+Error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+int
+be_function_queue_mcc_wrb(struct be_function_object *pfob,
+ struct be_generic_q_ctxt *q_ctxt)
+{
+ int status;
+
+ ASSERT(q_ctxt);
+
+ /*
+ * issue the WRB to the MPU as appropriate
+ */
+ if (pfob->mcc) {
+
+ /* We're in ring mode. Queue this item. */
+ pfob->mcc->backlog_length++;
+ list_add_tail(&q_ctxt->context.list, &pfob->mcc->backlog);
+ status = BE_PENDING;
+ } else {
+ status = BE_NOT_OK;
+ }
+ return status;
+}
+
diff --git a/drivers/staging/benet/fwcmd_common.h b/drivers/staging/benet/fwcmd_common.h
new file mode 100644
index 000000000000..406e0d6fa985
--- /dev/null
+++ b/drivers/staging/benet/fwcmd_common.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __fwcmd_common_amap_h__
+#define __fwcmd_common_amap_h__
+#include "host_struct.h"
+
+/* --- PHY_LINK_DUPLEX_ENUM --- */
+#define PHY_LINK_DUPLEX_NONE (0)
+#define PHY_LINK_DUPLEX_HALF (1)
+#define PHY_LINK_DUPLEX_FULL (2)
+
+/* --- PHY_LINK_SPEED_ENUM --- */
+#define PHY_LINK_SPEED_ZERO (0) /* No link. */
+#define PHY_LINK_SPEED_10MBPS (1) /* 10 Mbps */
+#define PHY_LINK_SPEED_100MBPS (2) /* 100 Mbps */
+#define PHY_LINK_SPEED_1GBPS (3) /* 1 Gbps */
+#define PHY_LINK_SPEED_10GBPS (4) /* 10 Gbps */
+
+/* --- PHY_LINK_FAULT_ENUM --- */
+#define PHY_LINK_FAULT_NONE (0) /* No fault status
+ available or detected */
+#define PHY_LINK_FAULT_LOCAL (1) /* Local fault detected */
+#define PHY_LINK_FAULT_REMOTE (2) /* Remote fault detected */
+
+/* --- BE_ULP_MASK --- */
+#define BE_ULP0_MASK (1)
+#define BE_ULP1_MASK (2)
+#define BE_ULP2_MASK (4)
+
+/* --- NTWK_ACTIVE_PORT --- */
+#define NTWK_PORT_A (0) /* Port A is currently active */
+#define NTWK_PORT_B (1) /* Port B is currently active */
+#define NTWK_NO_ACTIVE_PORT (15) /* Both ports have lost link */
+
+/* --- NTWK_LINK_TYPE --- */
+#define NTWK_LINK_TYPE_PHYSICAL (0) /* link up/down event
+ applies to BladeEngine's
+ Physical Ports
+ */
+#define NTWK_LINK_TYPE_VIRTUAL (1) /* Virtual link up/down event
+ reported by BladeExchange.
+ This applies only when the
+ VLD feature is enabled
+ */
+
+/*
+ * --- FWCMD_MAC_TYPE_ENUM ---
+ * This enum defines the types of MAC addresses in the RXF MAC Address Table.
+ */
+#define MAC_ADDRESS_TYPE_STORAGE (0) /* Storage MAC Address */
+#define MAC_ADDRESS_TYPE_NETWORK (1) /* Network MAC Address */
+#define MAC_ADDRESS_TYPE_PD (2) /* Protection Domain MAC Addr */
+#define MAC_ADDRESS_TYPE_MANAGEMENT (3) /* Managment MAC Address */
+
+
+/* --- FWCMD_RING_TYPE_ENUM --- */
+#define FWCMD_RING_TYPE_ETH_RX (1) /* Ring created with */
+ /* FWCMD_COMMON_ETH_RX_CREATE. */
+#define FWCMD_RING_TYPE_ETH_TX (2) /* Ring created with */
+ /* FWCMD_COMMON_ETH_TX_CREATE. */
+#define FWCMD_RING_TYPE_ISCSI_WRBQ (3) /* Ring created with */
+ /* FWCMD_COMMON_ISCSI_WRBQ_CREATE. */
+#define FWCMD_RING_TYPE_ISCSI_DEFQ (4) /* Ring created with */
+ /* FWCMD_COMMON_ISCSI_DEFQ_CREATE. */
+#define FWCMD_RING_TYPE_TPM_WRBQ (5) /* Ring created with */
+ /* FWCMD_COMMON_TPM_WRBQ_CREATE. */
+#define FWCMD_RING_TYPE_TPM_DEFQ (6) /* Ring created with */
+ /* FWCMD_COMMONTPM_TDEFQ_CREATE. */
+#define FWCMD_RING_TYPE_TPM_RQ (7) /* Ring created with */
+ /* FWCMD_COMMON_TPM_RQ_CREATE. */
+#define FWCMD_RING_TYPE_MCC (8) /* Ring created with */
+ /* FWCMD_COMMON_MCC_CREATE. */
+#define FWCMD_RING_TYPE_CQ (9) /* Ring created with */
+ /* FWCMD_COMMON_CQ_CREATE. */
+#define FWCMD_RING_TYPE_EQ (10) /* Ring created with */
+ /* FWCMD_COMMON_EQ_CREATE. */
+#define FWCMD_RING_TYPE_QP (11) /* Ring created with */
+ /* FWCMD_RDMA_QP_CREATE. */
+
+
+/* --- ETH_TX_RING_TYPE_ENUM --- */
+#define ETH_TX_RING_TYPE_FORWARDING (1) /* Ethernet ring for
+ forwarding packets */
+#define ETH_TX_RING_TYPE_STANDARD (2) /* Ethernet ring for sending
+ network packets. */
+#define ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring bound to the
+ port specified in the command
+ header.port_number field.
+ Rings of this type are
+ NOT subject to the
+ failover logic implemented
+ in the BladeEngine.
+ */
+
+/* --- FWCMD_COMMON_QOS_TYPE_ENUM --- */
+#define QOS_BITS_NIC (1) /* max_bits_per_second_NIC */
+ /* field is valid. */
+#define QOS_PKTS_NIC (2) /* max_packets_per_second_NIC */
+ /* field is valid. */
+#define QOS_IOPS_ISCSI (4) /* max_ios_per_second_iSCSI */
+ /*field is valid. */
+#define QOS_VLAN_TAG (8) /* domain_VLAN_tag field
+ is valid. */
+#define QOS_FABRIC_ID (16) /* fabric_domain_ID field
+ is valid. */
+#define QOS_OEM_PARAMS (32) /* qos_params_oem field
+ is valid. */
+#define QOS_TPUT_ISCSI (64) /* max_bytes_per_second_iSCSI
+ field is valid. */
+
+
+/*
+ * --- FAILOVER_CONFIG_ENUM ---
+ * Failover configuration setting used in FWCMD_COMMON_FORCE_FAILOVER
+ */
+#define FAILOVER_CONFIG_NO_CHANGE (0) /* No change to automatic */
+ /* port failover setting. */
+#define FAILOVER_CONFIG_ON (1) /* Automatic port failover
+ on link down is enabled. */
+#define FAILOVER_CONFIG_OFF (2) /* Automatic port failover
+ on link down is disabled. */
+
+/*
+ * --- FAILOVER_PORT_ENUM ---
+ * Failover port setting used in FWCMD_COMMON_FORCE_FAILOVER
+ */
+#define FAILOVER_PORT_A (0) /* Selects port A. */
+#define FAILOVER_PORT_B (1) /* Selects port B. */
+#define FAILOVER_PORT_NONE (15) /* No port change requested. */
+
+
+/*
+ * --- MGMT_FLASHROM_OPCODE ---
+ * Flash ROM operation code
+ */
+#define MGMT_FLASHROM_OPCODE_FLASH (1) /* Commit downloaded data
+ to Flash ROM */
+#define MGMT_FLASHROM_OPCODE_SAVE (2) /* Save downloaded data to
+ ARM's DDR - do not flash */
+#define MGMT_FLASHROM_OPCODE_CLEAR (3) /* Erase specified component
+ from FlashROM */
+#define MGMT_FLASHROM_OPCODE_REPORT (4) /* Read specified component
+ from Flash ROM */
+#define MGMT_FLASHROM_OPCODE_IMAGE_INFO (5) /* Returns size of a
+ component */
+
+/*
+ * --- MGMT_FLASHROM_OPTYPE ---
+ * Flash ROM operation type
+ */
+#define MGMT_FLASHROM_OPTYPE_CODE_FIRMWARE (0) /* Includes ARM firmware,
+ IPSec (optional) and EP
+ firmware */
+#define MGMT_FLASHROM_OPTYPE_CODE_REDBOOT (1)
+#define MGMT_FLASHROM_OPTYPE_CODE_BIOS (2)
+#define MGMT_FLASHROM_OPTYPE_CODE_PXE_BIOS (3)
+#define MGMT_FLASHROM_OPTYPE_CODE_CTRLS (4)
+#define MGMT_FLASHROM_OPTYPE_CFG_IPSEC (5)
+#define MGMT_FLASHROM_OPTYPE_CFG_INI (6)
+#define MGMT_FLASHROM_OPTYPE_ROM_OFFSET_SPECIFIED (7)
+
+/*
+ * --- FLASHROM_TYPE ---
+ * Flash ROM manufacturers supported in the f/w
+ */
+#define INTEL (0)
+#define SPANSION (1)
+#define MICRON (2)
+
+/* --- DDR_CAS_TYPE --- */
+#define CAS_3 (0)
+#define CAS_4 (1)
+#define CAS_5 (2)
+
+/* --- DDR_SIZE_TYPE --- */
+#define SIZE_256MB (0)
+#define SIZE_512MB (1)
+
+/* --- DDR_MODE_TYPE --- */
+#define DDR_NO_ECC (0)
+#define DDR_ECC (1)
+
+/* --- INTERFACE_10GB_TYPE --- */
+#define CX4_TYPE (0)
+#define XFP_TYPE (1)
+
+/* --- BE_CHIP_MAX_MTU --- */
+#define CHIP_MAX_MTU (9000)
+
+/* --- XAUI_STATE_ENUM --- */
+#define XAUI_STATE_ENABLE (0) /* This MUST be the default
+ value for all requests
+ which set/change
+ equalization parameter. */
+#define XAUI_STATE_DISABLE (255) /* The XAUI for both ports
+ may be disabled for EMI
+ tests. There is no
+ provision for turning off
+ individual ports.
+ */
+/* --- BE_ASIC_REVISION --- */
+#define BE_ASIC_REV_A0 (1)
+#define BE_ASIC_REV_A1 (2)
+
+#endif /* __fwcmd_common_amap_h__ */
diff --git a/drivers/staging/benet/fwcmd_common_bmap.h b/drivers/staging/benet/fwcmd_common_bmap.h
new file mode 100644
index 000000000000..a007cf276500
--- /dev/null
+++ b/drivers/staging/benet/fwcmd_common_bmap.h
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __fwcmd_common_bmap_h__
+#define __fwcmd_common_bmap_h__
+#include "fwcmd_types_bmap.h"
+#include "fwcmd_hdr_bmap.h"
+
+#if defined(__BIG_ENDIAN)
+ /* Physical Address. */
+struct PHYS_ADDR {
+ union {
+ struct {
+ u32 lo; /* DWORD 0 */
+ u32 hi; /* DWORD 1 */
+ } __packed; /* unnamed struct */
+ u32 dw[2]; /* dword union */
+ }; /* unnamed union */
+} __packed ;
+
+
+#else
+ /* Physical Address. */
+struct PHYS_ADDR {
+ union {
+ struct {
+ u32 lo; /* DWORD 0 */
+ u32 hi; /* DWORD 1 */
+ } __packed; /* unnamed struct */
+ u32 dw[2]; /* dword union */
+ }; /* unnamed union */
+} __packed ;
+
+struct BE_LINK_STATUS {
+ u8 mac0_duplex;
+ u8 mac0_speed;
+ u8 mac1_duplex;
+ u8 mac1_speed;
+ u8 mgmt_mac_duplex;
+ u8 mgmt_mac_speed;
+ u8 active_port;
+ u8 rsvd0;
+ u8 mac0_fault;
+ u8 mac1_fault;
+ u16 rsvd1;
+} __packed;
+#endif
+
+struct FWCMD_COMMON_ANON_170_REQUEST {
+ u32 rsvd0;
+} __packed;
+
+union LINK_STATUS_QUERY_PARAMS {
+ struct BE_LINK_STATUS response;
+ struct FWCMD_COMMON_ANON_170_REQUEST request;
+} __packed;
+
+/*
+ * Queries the the link status for all ports. The valid values below
+ * DO NOT indicate that a particular duplex or speed is supported by
+ * BladeEngine. These enumerations simply list all possible duplexes
+ * and speeds for any port. Consult BladeEngine product documentation
+ * for the supported parameters.
+ */
+struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY {
+ union FWCMD_HEADER header;
+ union LINK_STATUS_QUERY_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_171_REQUEST {
+ u8 type;
+ u8 port;
+ u8 mac1;
+ u8 permanent;
+} __packed;
+
+struct FWCMD_COMMON_ANON_172_RESPONSE {
+ struct MAC_ADDRESS_FORMAT mac;
+} __packed;
+
+union NTWK_MAC_QUERY_PARAMS {
+ struct FWCMD_COMMON_ANON_171_REQUEST request;
+ struct FWCMD_COMMON_ANON_172_RESPONSE response;
+} __packed;
+
+/* Queries one MAC address. */
+struct FWCMD_COMMON_NTWK_MAC_QUERY {
+ union FWCMD_HEADER header;
+ union NTWK_MAC_QUERY_PARAMS params;
+} __packed;
+
+struct MAC_SET_PARAMS_IN {
+ u8 type;
+ u8 port;
+ u8 mac1;
+ u8 invalidate;
+ struct MAC_ADDRESS_FORMAT mac;
+} __packed;
+
+struct MAC_SET_PARAMS_OUT {
+ u32 rsvd0;
+} __packed;
+
+union MAC_SET_PARAMS {
+ struct MAC_SET_PARAMS_IN request;
+ struct MAC_SET_PARAMS_OUT response;
+} __packed;
+
+/* Sets a MAC address. */
+struct FWCMD_COMMON_NTWK_MAC_SET {
+ union FWCMD_HEADER header;
+ union MAC_SET_PARAMS params;
+} __packed;
+
+/* MAC address list. */
+struct NTWK_MULTICAST_MAC_LIST {
+ u8 byte[6];
+} __packed;
+
+struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD {
+ u16 num_mac;
+ u8 promiscuous;
+ u8 rsvd0;
+ struct NTWK_MULTICAST_MAC_LIST mac[32];
+} __packed;
+
+struct FWCMD_COMMON_ANON_174_RESPONSE {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_COMMON_ANON_173_PARAMS {
+ struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD request;
+ struct FWCMD_COMMON_ANON_174_RESPONSE response;
+} __packed;
+
+/*
+ * Sets multicast address hash. The MPU will merge the MAC address lists
+ * from all clients, including the networking and storage functions.
+ * This command may fail if the final merged list of MAC addresses exceeds
+ * 32 entries.
+ */
+struct FWCMD_COMMON_NTWK_MULTICAST_SET {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_173_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD {
+ u16 num_vlan;
+ u8 promiscuous;
+ u8 rsvd0;
+ u16 vlan_tag[32];
+} __packed;
+
+struct FWCMD_COMMON_ANON_176_RESPONSE {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_COMMON_ANON_175_PARAMS {
+ struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD request;
+ struct FWCMD_COMMON_ANON_176_RESPONSE response;
+} __packed;
+
+/*
+ * Sets VLAN tag filter. The MPU will merge the VLAN tag list from all
+ * clients, including the networking and storage functions. This command
+ * may fail if the final vlan_tag array (from all functions) is longer
+ * than 32 entries.
+ */
+struct FWCMD_COMMON_NTWK_VLAN_CONFIG {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_175_PARAMS params;
+} __packed;
+
+struct RING_DESTROY_REQUEST {
+ u16 ring_type;
+ u16 id;
+ u8 bypass_flush;
+ u8 rsvd0;
+ u16 rsvd1;
+} __packed;
+
+struct FWCMD_COMMON_ANON_190_RESPONSE {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_COMMON_ANON_189_PARAMS {
+ struct RING_DESTROY_REQUEST request;
+ struct FWCMD_COMMON_ANON_190_RESPONSE response;
+} __packed;
+/*
+ * Command for destroying any ring. The connection(s) using the ring should
+ * be quiesced before destroying the ring.
+ */
+struct FWCMD_COMMON_RING_DESTROY {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_189_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_192_REQUEST {
+ u16 num_pages;
+ u16 rsvd0;
+ struct CQ_CONTEXT_AMAP context;
+ struct PHYS_ADDR pages[4];
+} __packed ;
+
+struct FWCMD_COMMON_ANON_193_RESPONSE {
+ u16 cq_id;
+} __packed ;
+
+union FWCMD_COMMON_ANON_191_PARAMS {
+ struct FWCMD_COMMON_ANON_192_REQUEST request;
+ struct FWCMD_COMMON_ANON_193_RESPONSE response;
+} __packed ;
+
+/*
+ * Command for creating a completion queue. A Completion Queue must span
+ * at least 1 page and at most 4 pages. Each completion queue entry
+ * is 16 bytes regardless of CQ entry format. Thus the ring must be
+ * at least 256 entries deep (corresponding to 1 page) and can be at
+ * most 1024 entries deep (corresponding to 4 pages). The number of
+ * pages posted must contain the CQ ring size as encoded in the context.
+ *
+ */
+struct FWCMD_COMMON_CQ_CREATE {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_191_PARAMS params;
+} __packed ;
+
+struct FWCMD_COMMON_ANON_198_REQUEST {
+ u16 num_pages;
+ u16 rsvd0;
+ struct EQ_CONTEXT_AMAP context;
+ struct PHYS_ADDR pages[8];
+} __packed ;
+
+struct FWCMD_COMMON_ANON_199_RESPONSE {
+ u16 eq_id;
+} __packed ;
+
+union FWCMD_COMMON_ANON_197_PARAMS {
+ struct FWCMD_COMMON_ANON_198_REQUEST request;
+ struct FWCMD_COMMON_ANON_199_RESPONSE response;
+} __packed ;
+
+/*
+ * Command for creating a event queue. An Event Queue must span at least
+ * 1 page and at most 8 pages. The number of pages posted must contain
+ * the EQ ring. The ring is defined by the size of the EQ entries (encoded
+ * in the context) and the number of EQ entries (also encoded in the
+ * context).
+ */
+struct FWCMD_COMMON_EQ_CREATE {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_197_PARAMS params;
+} __packed ;
+
+struct FWCMD_COMMON_ANON_201_REQUEST {
+ u16 cq_id;
+ u16 bcmc_cq_id;
+ u16 num_pages;
+ u16 rsvd0;
+ struct PHYS_ADDR pages[2];
+} __packed;
+
+struct FWCMD_COMMON_ANON_202_RESPONSE {
+ u16 id;
+} __packed;
+
+union FWCMD_COMMON_ANON_200_PARAMS {
+ struct FWCMD_COMMON_ANON_201_REQUEST request;
+ struct FWCMD_COMMON_ANON_202_RESPONSE response;
+} __packed;
+
+/*
+ * Command for creating Ethernet receive ring. An ERX ring contains ETH_RX_D
+ * entries (8 bytes each). An ERX ring must be 1024 entries deep
+ * (corresponding to 2 pages).
+ */
+struct FWCMD_COMMON_ETH_RX_CREATE {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_200_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_204_REQUEST {
+ u16 num_pages;
+ u8 ulp_num;
+ u8 type;
+ struct ETX_CONTEXT_AMAP context;
+ struct PHYS_ADDR pages[8];
+} __packed ;
+
+struct FWCMD_COMMON_ANON_205_RESPONSE {
+ u16 cid;
+ u8 ulp_num;
+ u8 rsvd0;
+} __packed ;
+
+union FWCMD_COMMON_ANON_203_PARAMS {
+ struct FWCMD_COMMON_ANON_204_REQUEST request;
+ struct FWCMD_COMMON_ANON_205_RESPONSE response;
+} __packed ;
+
+/*
+ * Command for creating an Ethernet transmit ring. An ETX ring contains
+ * ETH_WRB entries (16 bytes each). An ETX ring must be at least 256
+ * entries deep (corresponding to 1 page) and at most 2k entries deep
+ * (corresponding to 8 pages).
+ */
+struct FWCMD_COMMON_ETH_TX_CREATE {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_203_PARAMS params;
+} __packed ;
+
+struct FWCMD_COMMON_ANON_222_REQUEST {
+ u16 num_pages;
+ u16 rsvd0;
+ struct MCC_RING_CONTEXT_AMAP context;
+ struct PHYS_ADDR pages[8];
+} __packed ;
+
+struct FWCMD_COMMON_ANON_223_RESPONSE {
+ u16 id;
+} __packed ;
+
+union FWCMD_COMMON_ANON_221_PARAMS {
+ struct FWCMD_COMMON_ANON_222_REQUEST request;
+ struct FWCMD_COMMON_ANON_223_RESPONSE response;
+} __packed ;
+
+/*
+ * Command for creating the MCC ring. An MCC ring must be at least 16
+ * entries deep (corresponding to 1 page) and at most 128 entries deep
+ * (corresponding to 8 pages).
+ */
+struct FWCMD_COMMON_MCC_CREATE {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_221_PARAMS params;
+} __packed ;
+
+struct GET_QOS_IN {
+ u32 qos_params_rsvd;
+} __packed;
+
+struct GET_QOS_OUT {
+ u32 max_bits_per_second_NIC;
+ u32 max_packets_per_second_NIC;
+ u32 max_ios_per_second_iSCSI;
+ u32 max_bytes_per_second_iSCSI;
+ u16 domain_VLAN_tag;
+ u16 fabric_domain_ID;
+ u32 qos_params_oem[4];
+} __packed;
+
+union GET_QOS_PARAMS {
+ struct GET_QOS_IN request;
+ struct GET_QOS_OUT response;
+} __packed;
+
+/* QOS/Bandwidth settings per domain. Applicable only in VMs. */
+struct FWCMD_COMMON_GET_QOS {
+ union FWCMD_HEADER header;
+ union GET_QOS_PARAMS params;
+} __packed;
+
+struct SET_QOS_IN {
+ u32 valid_flags;
+ u32 max_bits_per_second_NIC;
+ u32 max_packets_per_second_NIC;
+ u32 max_ios_per_second_iSCSI;
+ u32 max_bytes_per_second_iSCSI;
+ u16 domain_VLAN_tag;
+ u16 fabric_domain_ID;
+ u32 qos_params_oem[4];
+} __packed;
+
+struct SET_QOS_OUT {
+ u32 qos_params_rsvd;
+} __packed;
+
+union SET_QOS_PARAMS {
+ struct SET_QOS_IN request;
+ struct SET_QOS_OUT response;
+} __packed;
+
+/* QOS/Bandwidth settings per domain. Applicable only in VMs. */
+struct FWCMD_COMMON_SET_QOS {
+ union FWCMD_HEADER header;
+ union SET_QOS_PARAMS params;
+} __packed;
+
+struct SET_FRAME_SIZE_IN {
+ u32 max_tx_frame_size;
+ u32 max_rx_frame_size;
+} __packed;
+
+struct SET_FRAME_SIZE_OUT {
+ u32 chip_max_tx_frame_size;
+ u32 chip_max_rx_frame_size;
+} __packed;
+
+union SET_FRAME_SIZE_PARAMS {
+ struct SET_FRAME_SIZE_IN request;
+ struct SET_FRAME_SIZE_OUT response;
+} __packed;
+
+/* Set frame size command. Only host domain may issue this command. */
+struct FWCMD_COMMON_SET_FRAME_SIZE {
+ union FWCMD_HEADER header;
+ union SET_FRAME_SIZE_PARAMS params;
+} __packed;
+
+struct FORCE_FAILOVER_IN {
+ u32 move_to_port;
+ u32 failover_config;
+} __packed;
+
+struct FWCMD_COMMON_ANON_231_RESPONSE {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_COMMON_ANON_230_PARAMS {
+ struct FORCE_FAILOVER_IN request;
+ struct FWCMD_COMMON_ANON_231_RESPONSE response;
+} __packed;
+
+/*
+ * Use this command to control failover in BladeEngine. It may be used
+ * to failback to a restored port or to forcibly move traffic from
+ * one port to another. It may also be used to enable or disable the
+ * automatic failover feature. This command can only be issued by domain
+ * 0.
+ */
+struct FWCMD_COMMON_FORCE_FAILOVER {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_230_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_240_REQUEST {
+ u64 context;
+} __packed;
+
+struct FWCMD_COMMON_ANON_241_RESPONSE {
+ u64 context;
+} __packed;
+
+union FWCMD_COMMON_ANON_239_PARAMS {
+ struct FWCMD_COMMON_ANON_240_REQUEST request;
+ struct FWCMD_COMMON_ANON_241_RESPONSE response;
+} __packed;
+
+/*
+ * This command can be used by clients as a no-operation request. Typical
+ * uses for drivers are as a heartbeat mechanism, or deferred processing
+ * catalyst. The ARM will always complete this command with a good completion.
+ * The 64-bit parameter is not touched by the ARM processor.
+ */
+struct FWCMD_COMMON_NOP {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_239_PARAMS params;
+} __packed;
+
+struct NTWK_RX_FILTER_SETTINGS {
+ u8 promiscuous;
+ u8 ip_cksum;
+ u8 tcp_cksum;
+ u8 udp_cksum;
+ u8 pass_err;
+ u8 pass_ckerr;
+ u8 strip_crc;
+ u8 mcast_en;
+ u8 bcast_en;
+ u8 mcast_promiscuous_en;
+ u8 unicast_en;
+ u8 vlan_promiscuous;
+} __packed;
+
+union FWCMD_COMMON_ANON_242_PARAMS {
+ struct NTWK_RX_FILTER_SETTINGS request;
+ struct NTWK_RX_FILTER_SETTINGS response;
+} __packed;
+
+/*
+ * This command is used to modify the ethernet receive filter configuration.
+ * Only domain 0 network function drivers may issue this command. The
+ * applied configuration is returned in the response payload. Note:
+ * Some receive packet filter settings are global on BladeEngine and
+ * can affect both the storage and network function clients that the
+ * BladeEngine hardware and firmware serve. Additionaly, depending
+ * on the revision of BladeEngine, some ethernet receive filter settings
+ * are dependent on others. If a dependency exists between settings
+ * for the BladeEngine revision, and the command request settings do
+ * not meet the dependency requirement, the invalid settings will not
+ * be applied despite the comand succeeding. For example: a driver may
+ * request to enable broadcast packets, but not enable multicast packets.
+ * On early revisions of BladeEngine, there may be no distinction between
+ * broadcast and multicast filters, so broadcast could not be enabled
+ * without enabling multicast. In this scenario, the comand would still
+ * succeed, but the response payload would indicate the previously
+ * configured broadcast and multicast setting.
+ */
+struct FWCMD_COMMON_NTWK_RX_FILTER {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_242_PARAMS params;
+} __packed;
+
+
+struct FWCMD_COMMON_ANON_244_REQUEST {
+ u32 rsvd0;
+} __packed;
+
+struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD {
+ u8 firmware_version_string[32];
+ u8 fw_on_flash_version_string[32];
+} __packed;
+
+union FWCMD_COMMON_ANON_243_PARAMS {
+ struct FWCMD_COMMON_ANON_244_REQUEST request;
+ struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD response;
+} __packed;
+
+/* This comand retrieves the firmware version. */
+struct FWCMD_COMMON_GET_FW_VERSION {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_243_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_246_REQUEST {
+ u16 tx_flow_control;
+ u16 rx_flow_control;
+} __packed;
+
+struct FWCMD_COMMON_ANON_247_RESPONSE {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_COMMON_ANON_245_PARAMS {
+ struct FWCMD_COMMON_ANON_246_REQUEST request;
+ struct FWCMD_COMMON_ANON_247_RESPONSE response;
+} __packed;
+
+/*
+ * This comand is used to program BladeEngine flow control behavior.
+ * Only the host networking driver is allowed to use this comand.
+ */
+struct FWCMD_COMMON_SET_FLOW_CONTROL {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_245_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_249_REQUEST {
+ u32 rsvd0;
+} __packed;
+
+struct FWCMD_COMMON_ANON_250_RESPONSE {
+ u16 tx_flow_control;
+ u16 rx_flow_control;
+} __packed;
+
+union FWCMD_COMMON_ANON_248_PARAMS {
+ struct FWCMD_COMMON_ANON_249_REQUEST request;
+ struct FWCMD_COMMON_ANON_250_RESPONSE response;
+} __packed;
+
+/* This comand is used to read BladeEngine flow control settings. */
+struct FWCMD_COMMON_GET_FLOW_CONTROL {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_248_PARAMS params;
+} __packed;
+
+struct EQ_DELAY_PARAMS {
+ u32 eq_id;
+ u32 delay_in_microseconds;
+} __packed;
+
+struct FWCMD_COMMON_ANON_257_REQUEST {
+ u32 num_eq;
+ u32 rsvd0;
+ struct EQ_DELAY_PARAMS delay[16];
+} __packed;
+
+struct FWCMD_COMMON_ANON_258_RESPONSE {
+ u32 delay_resolution_in_microseconds;
+ u32 delay_max_in_microseconds;
+} __packed;
+
+union MODIFY_EQ_DELAY_PARAMS {
+ struct FWCMD_COMMON_ANON_257_REQUEST request;
+ struct FWCMD_COMMON_ANON_258_RESPONSE response;
+} __packed;
+
+/* This comand changes the EQ delay for a given set of EQs. */
+struct FWCMD_COMMON_MODIFY_EQ_DELAY {
+ union FWCMD_HEADER header;
+ union MODIFY_EQ_DELAY_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_260_REQUEST {
+ u32 rsvd0;
+} __packed;
+
+struct BE_FIRMWARE_CONFIG {
+ u16 be_config_number;
+ u16 asic_revision;
+ u32 nic_ulp_mask;
+ u32 tulp_mask;
+ u32 iscsi_ulp_mask;
+ u32 rdma_ulp_mask;
+ u32 rsvd0[4];
+ u32 eth_tx_id_start;
+ u32 eth_tx_id_count;
+ u32 eth_rx_id_start;
+ u32 eth_rx_id_count;
+ u32 tpm_wrbq_id_start;
+ u32 tpm_wrbq_id_count;
+ u32 tpm_defq_id_start;
+ u32 tpm_defq_id_count;
+ u32 iscsi_wrbq_id_start;
+ u32 iscsi_wrbq_id_count;
+ u32 iscsi_defq_id_start;
+ u32 iscsi_defq_id_count;
+ u32 rdma_qp_id_start;
+ u32 rdma_qp_id_count;
+ u32 rsvd1[8];
+} __packed;
+
+union FWCMD_COMMON_ANON_259_PARAMS {
+ struct FWCMD_COMMON_ANON_260_REQUEST request;
+ struct BE_FIRMWARE_CONFIG response;
+} __packed;
+
+/*
+ * This comand queries the current firmware configuration parameters.
+ * The static configuration type is defined by be_config_number. This
+ * differentiates different BladeEngine builds, such as iSCSI Initiator
+ * versus iSCSI Target. For a given static configuration, the Upper
+ * Layer Protocol (ULP) processors may be reconfigured to support different
+ * protocols. Each ULP processor supports one or more protocols. The
+ * masks indicate which processors are configured for each protocol.
+ * For a given static configuration, the number of TCP connections
+ * supported for each protocol may vary. The *_id_start and *_id_count
+ * variables define a linear range of IDs that are available for each
+ * supported protocol. The *_id_count may be used by the driver to allocate
+ * the appropriate number of connection resources. The *_id_start may
+ * be used to map the arbitrary range of IDs to a zero-based range
+ * of indices.
+ */
+struct FWCMD_COMMON_FIRMWARE_CONFIG {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_259_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS {
+ u32 emph_lev_sel_port0;
+ u32 emph_lev_sel_port1;
+ u8 xaui_vo_sel;
+ u8 xaui_state;
+ u16 rsvd0;
+ u32 xaui_eq_vector;
+} __packed;
+
+struct FWCMD_COMMON_ANON_262_REQUEST {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_COMMON_ANON_261_PARAMS {
+ struct FWCMD_COMMON_ANON_262_REQUEST request;
+ struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS response;
+} __packed;
+
+/*
+ * This comand can be used to read XAUI equalization parameters. The
+ * ARM firmware applies default equalization parameters during initialization.
+ * These parameters may be customer-specific when derived from the
+ * SEEPROM. See SEEPROM_DATA for equalization specific fields.
+ */
+struct FWCMD_COMMON_GET_PORT_EQUALIZATION {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_261_PARAMS params;
+} __packed;
+
+struct FWCMD_COMMON_ANON_264_RESPONSE {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_COMMON_ANON_263_PARAMS {
+ struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS request;
+ struct FWCMD_COMMON_ANON_264_RESPONSE response;
+} __packed;
+
+/*
+ * This comand can be used to set XAUI equalization parameters. The ARM
+ * firmware applies default equalization parameters during initialization.
+ * These parameters may be customer-specific when derived from the
+ * SEEPROM. See SEEPROM_DATA for equalization specific fields.
+ */
+struct FWCMD_COMMON_SET_PORT_EQUALIZATION {
+ union FWCMD_HEADER header;
+ union FWCMD_COMMON_ANON_263_PARAMS params;
+} __packed;
+
+#endif /* __fwcmd_common_bmap_h__ */
diff --git a/drivers/staging/benet/fwcmd_eth_bmap.h b/drivers/staging/benet/fwcmd_eth_bmap.h
new file mode 100644
index 000000000000..234b179eace6
--- /dev/null
+++ b/drivers/staging/benet/fwcmd_eth_bmap.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __fwcmd_eth_bmap_h__
+#define __fwcmd_eth_bmap_h__
+#include "fwcmd_hdr_bmap.h"
+#include "fwcmd_types_bmap.h"
+
+struct MIB_ETH_STATISTICS_PARAMS_IN {
+ u32 rsvd0;
+} __packed;
+
+struct BE_RXF_STATS {
+ u32 p0recvdtotalbytesLSD; /* DWORD 0 */
+ u32 p0recvdtotalbytesMSD; /* DWORD 1 */
+ u32 p0recvdtotalframes; /* DWORD 2 */
+ u32 p0recvdunicastframes; /* DWORD 3 */
+ u32 p0recvdmulticastframes; /* DWORD 4 */
+ u32 p0recvdbroadcastframes; /* DWORD 5 */
+ u32 p0crcerrors; /* DWORD 6 */
+ u32 p0alignmentsymerrs; /* DWORD 7 */
+ u32 p0pauseframesrecvd; /* DWORD 8 */
+ u32 p0controlframesrecvd; /* DWORD 9 */
+ u32 p0inrangelenerrors; /* DWORD 10 */
+ u32 p0outrangeerrors; /* DWORD 11 */
+ u32 p0frametoolongerrors; /* DWORD 12 */
+ u32 p0droppedaddressmatch; /* DWORD 13 */
+ u32 p0droppedvlanmismatch; /* DWORD 14 */
+ u32 p0ipdroppedtoosmall; /* DWORD 15 */
+ u32 p0ipdroppedtooshort; /* DWORD 16 */
+ u32 p0ipdroppedhdrtoosmall; /* DWORD 17 */
+ u32 p0tcpdroppedlen; /* DWORD 18 */
+ u32 p0droppedrunt; /* DWORD 19 */
+ u32 p0recvd64; /* DWORD 20 */
+ u32 p0recvd65_127; /* DWORD 21 */
+ u32 p0recvd128_256; /* DWORD 22 */
+ u32 p0recvd256_511; /* DWORD 23 */
+ u32 p0recvd512_1023; /* DWORD 24 */
+ u32 p0recvd1518_1522; /* DWORD 25 */
+ u32 p0recvd1522_2047; /* DWORD 26 */
+ u32 p0recvd2048_4095; /* DWORD 27 */
+ u32 p0recvd4096_8191; /* DWORD 28 */
+ u32 p0recvd8192_9216; /* DWORD 29 */
+ u32 p0rcvdipcksmerrs; /* DWORD 30 */
+ u32 p0recvdtcpcksmerrs; /* DWORD 31 */
+ u32 p0recvdudpcksmerrs; /* DWORD 32 */
+ u32 p0recvdnonrsspackets; /* DWORD 33 */
+ u32 p0recvdippackets; /* DWORD 34 */
+ u32 p0recvdchute1packets; /* DWORD 35 */
+ u32 p0recvdchute2packets; /* DWORD 36 */
+ u32 p0recvdchute3packets; /* DWORD 37 */
+ u32 p0recvdipsecpackets; /* DWORD 38 */
+ u32 p0recvdmanagementpackets; /* DWORD 39 */
+ u32 p0xmitbyteslsd; /* DWORD 40 */
+ u32 p0xmitbytesmsd; /* DWORD 41 */
+ u32 p0xmitunicastframes; /* DWORD 42 */
+ u32 p0xmitmulticastframes; /* DWORD 43 */
+ u32 p0xmitbroadcastframes; /* DWORD 44 */
+ u32 p0xmitpauseframes; /* DWORD 45 */
+ u32 p0xmitcontrolframes; /* DWORD 46 */
+ u32 p0xmit64; /* DWORD 47 */
+ u32 p0xmit65_127; /* DWORD 48 */
+ u32 p0xmit128_256; /* DWORD 49 */
+ u32 p0xmit256_511; /* DWORD 50 */
+ u32 p0xmit512_1023; /* DWORD 51 */
+ u32 p0xmit1518_1522; /* DWORD 52 */
+ u32 p0xmit1522_2047; /* DWORD 53 */
+ u32 p0xmit2048_4095; /* DWORD 54 */
+ u32 p0xmit4096_8191; /* DWORD 55 */
+ u32 p0xmit8192_9216; /* DWORD 56 */
+ u32 p0rxfifooverflowdropped; /* DWORD 57 */
+ u32 p0ipseclookupfaileddropped; /* DWORD 58 */
+ u32 p1recvdtotalbytesLSD; /* DWORD 59 */
+ u32 p1recvdtotalbytesMSD; /* DWORD 60 */
+ u32 p1recvdtotalframes; /* DWORD 61 */
+ u32 p1recvdunicastframes; /* DWORD 62 */
+ u32 p1recvdmulticastframes; /* DWORD 63 */
+ u32 p1recvdbroadcastframes; /* DWORD 64 */
+ u32 p1crcerrors; /* DWORD 65 */
+ u32 p1alignmentsymerrs; /* DWORD 66 */
+ u32 p1pauseframesrecvd; /* DWORD 67 */
+ u32 p1controlframesrecvd; /* DWORD 68 */
+ u32 p1inrangelenerrors; /* DWORD 69 */
+ u32 p1outrangeerrors; /* DWORD 70 */
+ u32 p1frametoolongerrors; /* DWORD 71 */
+ u32 p1droppedaddressmatch; /* DWORD 72 */
+ u32 p1droppedvlanmismatch; /* DWORD 73 */
+ u32 p1ipdroppedtoosmall; /* DWORD 74 */
+ u32 p1ipdroppedtooshort; /* DWORD 75 */
+ u32 p1ipdroppedhdrtoosmall; /* DWORD 76 */
+ u32 p1tcpdroppedlen; /* DWORD 77 */
+ u32 p1droppedrunt; /* DWORD 78 */
+ u32 p1recvd64; /* DWORD 79 */
+ u32 p1recvd65_127; /* DWORD 80 */
+ u32 p1recvd128_256; /* DWORD 81 */
+ u32 p1recvd256_511; /* DWORD 82 */
+ u32 p1recvd512_1023; /* DWORD 83 */
+ u32 p1recvd1518_1522; /* DWORD 84 */
+ u32 p1recvd1522_2047; /* DWORD 85 */
+ u32 p1recvd2048_4095; /* DWORD 86 */
+ u32 p1recvd4096_8191; /* DWORD 87 */
+ u32 p1recvd8192_9216; /* DWORD 88 */
+ u32 p1rcvdipcksmerrs; /* DWORD 89 */
+ u32 p1recvdtcpcksmerrs; /* DWORD 90 */
+ u32 p1recvdudpcksmerrs; /* DWORD 91 */
+ u32 p1recvdnonrsspackets; /* DWORD 92 */
+ u32 p1recvdippackets; /* DWORD 93 */
+ u32 p1recvdchute1packets; /* DWORD 94 */
+ u32 p1recvdchute2packets; /* DWORD 95 */
+ u32 p1recvdchute3packets; /* DWORD 96 */
+ u32 p1recvdipsecpackets; /* DWORD 97 */
+ u32 p1recvdmanagementpackets; /* DWORD 98 */
+ u32 p1xmitbyteslsd; /* DWORD 99 */
+ u32 p1xmitbytesmsd; /* DWORD 100 */
+ u32 p1xmitunicastframes; /* DWORD 101 */
+ u32 p1xmitmulticastframes; /* DWORD 102 */
+ u32 p1xmitbroadcastframes; /* DWORD 103 */
+ u32 p1xmitpauseframes; /* DWORD 104 */
+ u32 p1xmitcontrolframes; /* DWORD 105 */
+ u32 p1xmit64; /* DWORD 106 */
+ u32 p1xmit65_127; /* DWORD 107 */
+ u32 p1xmit128_256; /* DWORD 108 */
+ u32 p1xmit256_511; /* DWORD 109 */
+ u32 p1xmit512_1023; /* DWORD 110 */
+ u32 p1xmit1518_1522; /* DWORD 111 */
+ u32 p1xmit1522_2047; /* DWORD 112 */
+ u32 p1xmit2048_4095; /* DWORD 113 */
+ u32 p1xmit4096_8191; /* DWORD 114 */
+ u32 p1xmit8192_9216; /* DWORD 115 */
+ u32 p1rxfifooverflowdropped; /* DWORD 116 */
+ u32 p1ipseclookupfaileddropped; /* DWORD 117 */
+ u32 pxdroppednopbuf; /* DWORD 118 */
+ u32 pxdroppednotxpb; /* DWORD 119 */
+ u32 pxdroppednoipsecbuf; /* DWORD 120 */
+ u32 pxdroppednoerxdescr; /* DWORD 121 */
+ u32 pxdroppednotpredescr; /* DWORD 122 */
+ u32 pxrecvdmanagementportpackets; /* DWORD 123 */
+ u32 pxrecvdmanagementportbytes; /* DWORD 124 */
+ u32 pxrecvdmanagementportpauseframes; /* DWORD 125 */
+ u32 pxrecvdmanagementporterrors; /* DWORD 126 */
+ u32 pxxmitmanagementportpackets; /* DWORD 127 */
+ u32 pxxmitmanagementportbytes; /* DWORD 128 */
+ u32 pxxmitmanagementportpause; /* DWORD 129 */
+ u32 pxxmitmanagementportrxfifooverflow; /* DWORD 130 */
+ u32 pxrecvdipsecipcksmerrs; /* DWORD 131 */
+ u32 pxrecvdtcpsecipcksmerrs; /* DWORD 132 */
+ u32 pxrecvdudpsecipcksmerrs; /* DWORD 133 */
+ u32 pxipsecrunt; /* DWORD 134 */
+ u32 pxipsecaddressmismatchdropped; /* DWORD 135 */
+ u32 pxipsecrxfifooverflowdropped; /* DWORD 136 */
+ u32 pxipsecframestoolong; /* DWORD 137 */
+ u32 pxipsectotalipframes; /* DWORD 138 */
+ u32 pxipseciptoosmall; /* DWORD 139 */
+ u32 pxipseciptooshort; /* DWORD 140 */
+ u32 pxipseciphdrtoosmall; /* DWORD 141 */
+ u32 pxipsectcphdrbad; /* DWORD 142 */
+ u32 pxrecvdipsecchute1; /* DWORD 143 */
+ u32 pxrecvdipsecchute2; /* DWORD 144 */
+ u32 pxrecvdipsecchute3; /* DWORD 145 */
+ u32 pxdropped7frags; /* DWORD 146 */
+ u32 pxdroppedfrags; /* DWORD 147 */
+ u32 pxdroppedinvalidfragring; /* DWORD 148 */
+ u32 pxnumforwardedpackets; /* DWORD 149 */
+} __packed;
+
+union MIB_ETH_STATISTICS_PARAMS {
+ struct MIB_ETH_STATISTICS_PARAMS_IN request;
+ struct BE_RXF_STATS response;
+} __packed;
+
+/*
+ * Query ethernet statistics. All domains may issue this command. The
+ * host domain drivers may optionally reset internal statistic counters
+ * with a query.
+ */
+struct FWCMD_ETH_GET_STATISTICS {
+ union FWCMD_HEADER header;
+ union MIB_ETH_STATISTICS_PARAMS params;
+} __packed;
+
+
+struct FWCMD_ETH_ANON_175_REQUEST {
+ u8 port0_promiscuous;
+ u8 port1_promiscuous;
+ u16 rsvd0;
+} __packed;
+
+struct FWCMD_ETH_ANON_176_RESPONSE {
+ u32 rsvd0;
+} __packed;
+
+union FWCMD_ETH_ANON_174_PARAMS {
+ struct FWCMD_ETH_ANON_175_REQUEST request;
+ struct FWCMD_ETH_ANON_176_RESPONSE response;
+} __packed;
+
+/* Enables/Disables promiscuous ethernet receive mode. */
+struct FWCMD_ETH_PROMISCUOUS {
+ union FWCMD_HEADER header;
+ union FWCMD_ETH_ANON_174_PARAMS params;
+} __packed;
+
+struct FWCMD_ETH_ANON_178_REQUEST {
+ u32 new_fragsize_log2;
+} __packed;
+
+struct FWCMD_ETH_ANON_179_RESPONSE {
+ u32 actual_fragsize_log2;
+} __packed;
+
+union FWCMD_ETH_ANON_177_PARAMS {
+ struct FWCMD_ETH_ANON_178_REQUEST request;
+ struct FWCMD_ETH_ANON_179_RESPONSE response;
+} __packed;
+
+/*
+ * Sets the Ethernet RX fragment size. Only host (domain 0) networking
+ * drivers may issue this command. This call will fail for non-host
+ * protection domains. In this situation the MCC CQ status will indicate
+ * a failure due to insufficient priviledges. The response should be
+ * ignored, and the driver should use the FWCMD_ETH_GET_FRAG_SIZE to
+ * query the existing ethernet receive fragment size. It must use this
+ * fragment size for all fragments in the ethernet receive ring. If
+ * the command succeeds, the driver must use the frag size indicated
+ * in the command response since the requested frag size may not be applied
+ * until the next reboot. When the requested fragsize matches the response
+ * fragsize, this indicates the request was applied immediately.
+ */
+struct FWCMD_ETH_SET_RX_FRAG_SIZE {
+ union FWCMD_HEADER header;
+ union FWCMD_ETH_ANON_177_PARAMS params;
+} __packed;
+
+struct FWCMD_ETH_ANON_181_REQUEST {
+ u32 rsvd0;
+} __packed;
+
+struct FWCMD_ETH_ANON_182_RESPONSE {
+ u32 actual_fragsize_log2;
+} __packed;
+
+union FWCMD_ETH_ANON_180_PARAMS {
+ struct FWCMD_ETH_ANON_181_REQUEST request;
+ struct FWCMD_ETH_ANON_182_RESPONSE response;
+} __packed;
+
+/*
+ * Queries the Ethernet RX fragment size. All domains may issue this
+ * command. The driver should call this command to determine the minimum
+ * required fragment size for the ethernet RX ring buffers. Drivers
+ * may choose to use a larger size for each fragment buffer, but BladeEngine
+ * will use up to the configured minimum required fragsize in each ethernet
+ * receive fragment buffer. For example, if the ethernet receive fragment
+ * size is configured to 4kB, and a driver uses 8kB fragments, a 6kB
+ * ethernet packet received by BladeEngine will be split accross two
+ * of the driver's receive framgents (4kB in one fragment buffer, and
+ * 2kB in the subsequent fragment buffer).
+ */
+struct FWCMD_ETH_GET_RX_FRAG_SIZE {
+ union FWCMD_HEADER header;
+ union FWCMD_ETH_ANON_180_PARAMS params;
+} __packed;
+
+#endif /* __fwcmd_eth_bmap_h__ */
diff --git a/drivers/staging/benet/fwcmd_hdr_bmap.h b/drivers/staging/benet/fwcmd_hdr_bmap.h
new file mode 100644
index 000000000000..28b45328fe7b
--- /dev/null
+++ b/drivers/staging/benet/fwcmd_hdr_bmap.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __fwcmd_hdr_bmap_h__
+#define __fwcmd_hdr_bmap_h__
+
+struct FWCMD_REQUEST_HEADER {
+ u8 opcode;
+ u8 subsystem;
+ u8 port_number;
+ u8 domain;
+ u32 timeout;
+ u32 request_length;
+ u32 rsvd0;
+} __packed;
+
+struct FWCMD_RESPONSE_HEADER {
+ u8 opcode;
+ u8 subsystem;
+ u8 rsvd0;
+ u8 domain;
+ u8 status;
+ u8 additional_status;
+ u16 rsvd1;
+ u32 response_length;
+ u32 actual_response_length;
+} __packed;
+
+/*
+ * The firmware/driver overwrites the input FWCMD_REQUEST_HEADER with
+ * the output FWCMD_RESPONSE_HEADER.
+ */
+union FWCMD_HEADER {
+ struct FWCMD_REQUEST_HEADER request;
+ struct FWCMD_RESPONSE_HEADER response;
+} __packed;
+
+#endif /* __fwcmd_hdr_bmap_h__ */
diff --git a/drivers/staging/benet/fwcmd_mcc.h b/drivers/staging/benet/fwcmd_mcc.h
new file mode 100644
index 000000000000..9eeca878c1fb
--- /dev/null
+++ b/drivers/staging/benet/fwcmd_mcc.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __fwcmd_mcc_amap_h__
+#define __fwcmd_mcc_amap_h__
+#include "fwcmd_opcodes.h"
+/*
+ * Where applicable, a WRB, may contain a list of Scatter-gather elements.
+ * Each element supports a 64 bit address and a 32bit length field.
+ */
+struct BE_MCC_SGE_AMAP {
+ u8 pa_lo[32]; /* DWORD 0 */
+ u8 pa_hi[32]; /* DWORD 1 */
+ u8 length[32]; /* DWORD 2 */
+} __packed;
+struct MCC_SGE_AMAP {
+ u32 dw[3];
+};
+/*
+ * The design of an MCC_SGE allows up to 19 elements to be embedded
+ * in a WRB, supporting 64KB data transfers (assuming a 4KB page size).
+ */
+struct BE_MCC_WRB_PAYLOAD_AMAP {
+ union {
+ struct BE_MCC_SGE_AMAP sgl[19];
+ u8 embedded[59][32]; /* DWORD 0 */
+ };
+} __packed;
+struct MCC_WRB_PAYLOAD_AMAP {
+ u32 dw[59];
+};
+
+/*
+ * This is the structure of the MCC Command WRB for commands
+ * sent to the Management Processing Unit (MPU). See section
+ * for usage in embedded and non-embedded modes.
+ */
+struct BE_MCC_WRB_AMAP {
+ u8 embedded; /* DWORD 0 */
+ u8 rsvd0[2]; /* DWORD 0 */
+ u8 sge_count[5]; /* DWORD 0 */
+ u8 rsvd1[16]; /* DWORD 0 */
+ u8 special[8]; /* DWORD 0 */
+ u8 payload_length[32]; /* DWORD 1 */
+ u8 tag[2][32]; /* DWORD 2 */
+ u8 rsvd2[32]; /* DWORD 4 */
+ struct BE_MCC_WRB_PAYLOAD_AMAP payload;
+} __packed;
+struct MCC_WRB_AMAP {
+ u32 dw[64];
+};
+
+/* This is the structure of the MCC Completion queue entry */
+struct BE_MCC_CQ_ENTRY_AMAP {
+ u8 completion_status[16]; /* DWORD 0 */
+ u8 extended_status[16]; /* DWORD 0 */
+ u8 mcc_tag[2][32]; /* DWORD 1 */
+ u8 rsvd0[27]; /* DWORD 3 */
+ u8 consumed; /* DWORD 3 */
+ u8 completed; /* DWORD 3 */
+ u8 hpi_buffer_completion; /* DWORD 3 */
+ u8 async_event; /* DWORD 3 */
+ u8 valid; /* DWORD 3 */
+} __packed;
+struct MCC_CQ_ENTRY_AMAP {
+ u32 dw[4];
+};
+
+/* Mailbox structures used by the MPU during bootstrap */
+struct BE_MCC_MAILBOX_AMAP {
+ struct BE_MCC_WRB_AMAP wrb;
+ struct BE_MCC_CQ_ENTRY_AMAP cq;
+} __packed;
+struct MCC_MAILBOX_AMAP {
+ u32 dw[68];
+};
+
+#endif /* __fwcmd_mcc_amap_h__ */
diff --git a/drivers/staging/benet/fwcmd_opcodes.h b/drivers/staging/benet/fwcmd_opcodes.h
new file mode 100644
index 000000000000..23d569386b46
--- /dev/null
+++ b/drivers/staging/benet/fwcmd_opcodes.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __fwcmd_opcodes_amap_h__
+#define __fwcmd_opcodes_amap_h__
+
+/*
+ * --- FWCMD_SUBSYSTEMS ---
+ * The commands are grouped into the following subsystems. The subsystem
+ * code along with the opcode uniquely identify a particular fwcmd.
+ */
+#define FWCMD_SUBSYSTEM_RSVD (0) /* This subsystem is reserved. It is */
+ /* never used. */
+#define FWCMD_SUBSYSTEM_COMMON (1) /* CMDs in this group are common to
+ * all subsystems. See
+ * COMMON_SUBSYSTEM_OPCODES for opcodes
+ * and Common Host Configuration CMDs
+ * for the FWCMD descriptions.
+ */
+#define FWCMD_SUBSYSTEM_COMMON_ISCSI (2) /* CMDs in this group are */
+ /*
+ * common to Initiator and Target. See
+ * COMMON_ISCSI_SUBSYSTEM_OPCODES and
+ * Common iSCSI Initiator and Target
+ * CMDs for the command descriptions.
+ */
+#define FWCMD_SUBSYSTEM_ETH (3) /* This subsystem is used to
+ execute Ethernet commands. */
+
+#define FWCMD_SUBSYSTEM_TPM (4) /* This subsystem is used
+ to execute TPM commands. */
+#define FWCMD_SUBSYSTEM_PXE_UNDI (5) /* This subsystem is used
+ * to execute PXE
+ * and UNDI specific commands.
+ */
+
+#define FWCMD_SUBSYSTEM_ISCSI_INI (6) /* This subsystem is used to
+ execute ISCSI Initiator
+ specific commands.
+ */
+#define FWCMD_SUBSYSTEM_ISCSI_TGT (7) /* This subsystem is used
+ to execute iSCSI Target
+ specific commands.between
+ PTL and ARM firmware.
+ */
+#define FWCMD_SUBSYSTEM_MILI_PTL (8) /* This subsystem is used to
+ execute iSCSI Target specific
+ commands.between MILI
+ and PTL. */
+#define FWCMD_SUBSYSTEM_MILI_TMD (9) /* This subsystem is used to
+ execute iSCSI Target specific
+ commands between MILI
+ and TMD. */
+#define FWCMD_SUBSYSTEM_PROXY (11) /* This subsystem is used
+ to execute proxied commands
+ within the host at the
+ explicit request of a
+ non priviledged domain.
+ This 'subsystem' is entirely
+ virtual from the controller
+ and firmware perspective as
+ it is implemented in host
+ drivers.
+ */
+
+/*
+ * --- COMMON_SUBSYSTEM_OPCODES ---
+ * These opcodes are common to both networking and storage PCI
+ * functions. They are used to reserve resources and configure
+ * BladeEngine. These opcodes all use the FWCMD_SUBSYSTEM_COMMON
+ * subsystem code.
+ */
+#define OPCODE_COMMON_NTWK_MAC_QUERY (1)
+#define SUBSYSTEM_COMMON_NTWK_MAC_QUERY (1)
+#define SUBSYSTEM_COMMON_NTWK_MAC_SET (1)
+#define SUBSYSTEM_COMMON_NTWK_MULTICAST_SET (1)
+#define SUBSYSTEM_COMMON_NTWK_VLAN_CONFIG (1)
+#define SUBSYSTEM_COMMON_NTWK_LINK_STATUS_QUERY (1)
+#define SUBSYSTEM_COMMON_READ_FLASHROM (1)
+#define SUBSYSTEM_COMMON_WRITE_FLASHROM (1)
+#define SUBSYSTEM_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (1)
+#define SUBSYSTEM_COMMON_ADD_PAGE_TABLES (1)
+#define SUBSYSTEM_COMMON_REMOVE_PAGE_TABLES (1)
+#define SUBSYSTEM_COMMON_RING_DESTROY (1)
+#define SUBSYSTEM_COMMON_CQ_CREATE (1)
+#define SUBSYSTEM_COMMON_EQ_CREATE (1)
+#define SUBSYSTEM_COMMON_ETH_RX_CREATE (1)
+#define SUBSYSTEM_COMMON_ETH_TX_CREATE (1)
+#define SUBSYSTEM_COMMON_ISCSI_DEFQ_CREATE (1)
+#define SUBSYSTEM_COMMON_ISCSI_WRBQ_CREATE (1)
+#define SUBSYSTEM_COMMON_MCC_CREATE (1)
+#define SUBSYSTEM_COMMON_JELL_CONFIG (1)
+#define SUBSYSTEM_COMMON_FORCE_FAILOVER (1)
+#define SUBSYSTEM_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (1)
+#define SUBSYSTEM_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (1)
+#define SUBSYSTEM_COMMON_POST_ZERO_BUFFER (1)
+#define SUBSYSTEM_COMMON_GET_QOS (1)
+#define SUBSYSTEM_COMMON_SET_QOS (1)
+#define SUBSYSTEM_COMMON_TCP_GET_STATISTICS (1)
+#define SUBSYSTEM_COMMON_SEEPROM_READ (1)
+#define SUBSYSTEM_COMMON_TCP_STATE_QUERY (1)
+#define SUBSYSTEM_COMMON_GET_CNTL_ATTRIBUTES (1)
+#define SUBSYSTEM_COMMON_NOP (1)
+#define SUBSYSTEM_COMMON_NTWK_RX_FILTER (1)
+#define SUBSYSTEM_COMMON_GET_FW_VERSION (1)
+#define SUBSYSTEM_COMMON_SET_FLOW_CONTROL (1)
+#define SUBSYSTEM_COMMON_GET_FLOW_CONTROL (1)
+#define SUBSYSTEM_COMMON_SET_TCP_PARAMETERS (1)
+#define SUBSYSTEM_COMMON_SET_FRAME_SIZE (1)
+#define SUBSYSTEM_COMMON_GET_FAT (1)
+#define SUBSYSTEM_COMMON_MODIFY_EQ_DELAY (1)
+#define SUBSYSTEM_COMMON_FIRMWARE_CONFIG (1)
+#define SUBSYSTEM_COMMON_ENABLE_DISABLE_DOMAINS (1)
+#define SUBSYSTEM_COMMON_GET_DOMAIN_CONFIG (1)
+#define SUBSYSTEM_COMMON_SET_VLD_CONFIG (1)
+#define SUBSYSTEM_COMMON_GET_VLD_CONFIG (1)
+#define SUBSYSTEM_COMMON_GET_PORT_EQUALIZATION (1)
+#define SUBSYSTEM_COMMON_SET_PORT_EQUALIZATION (1)
+#define SUBSYSTEM_COMMON_RED_CONFIG (1)
+#define OPCODE_COMMON_NTWK_MAC_SET (2)
+#define OPCODE_COMMON_NTWK_MULTICAST_SET (3)
+#define OPCODE_COMMON_NTWK_VLAN_CONFIG (4)
+#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY (5)
+#define OPCODE_COMMON_READ_FLASHROM (6)
+#define OPCODE_COMMON_WRITE_FLASHROM (7)
+#define OPCODE_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (8)
+#define OPCODE_COMMON_ADD_PAGE_TABLES (9)
+#define OPCODE_COMMON_REMOVE_PAGE_TABLES (10)
+#define OPCODE_COMMON_RING_DESTROY (11)
+#define OPCODE_COMMON_CQ_CREATE (12)
+#define OPCODE_COMMON_EQ_CREATE (13)
+#define OPCODE_COMMON_ETH_RX_CREATE (14)
+#define OPCODE_COMMON_ETH_TX_CREATE (15)
+#define OPCODE_COMMON_NET_RESERVED0 (16) /* Reserved */
+#define OPCODE_COMMON_NET_RESERVED1 (17) /* Reserved */
+#define OPCODE_COMMON_NET_RESERVED2 (18) /* Reserved */
+#define OPCODE_COMMON_ISCSI_DEFQ_CREATE (19)
+#define OPCODE_COMMON_ISCSI_WRBQ_CREATE (20)
+#define OPCODE_COMMON_MCC_CREATE (21)
+#define OPCODE_COMMON_JELL_CONFIG (22)
+#define OPCODE_COMMON_FORCE_FAILOVER (23)
+#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (24)
+#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (25)
+#define OPCODE_COMMON_POST_ZERO_BUFFER (26)
+#define OPCODE_COMMON_GET_QOS (27)
+#define OPCODE_COMMON_SET_QOS (28)
+#define OPCODE_COMMON_TCP_GET_STATISTICS (29)
+#define OPCODE_COMMON_SEEPROM_READ (30)
+#define OPCODE_COMMON_TCP_STATE_QUERY (31)
+#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES (32)
+#define OPCODE_COMMON_NOP (33)
+#define OPCODE_COMMON_NTWK_RX_FILTER (34)
+#define OPCODE_COMMON_GET_FW_VERSION (35)
+#define OPCODE_COMMON_SET_FLOW_CONTROL (36)
+#define OPCODE_COMMON_GET_FLOW_CONTROL (37)
+#define OPCODE_COMMON_SET_TCP_PARAMETERS (38)
+#define OPCODE_COMMON_SET_FRAME_SIZE (39)
+#define OPCODE_COMMON_GET_FAT (40)
+#define OPCODE_COMMON_MODIFY_EQ_DELAY (41)
+#define OPCODE_COMMON_FIRMWARE_CONFIG (42)
+#define OPCODE_COMMON_ENABLE_DISABLE_DOMAINS (43)
+#define OPCODE_COMMON_GET_DOMAIN_CONFIG (44)
+#define OPCODE_COMMON_SET_VLD_CONFIG (45)
+#define OPCODE_COMMON_GET_VLD_CONFIG (46)
+#define OPCODE_COMMON_GET_PORT_EQUALIZATION (47)
+#define OPCODE_COMMON_SET_PORT_EQUALIZATION (48)
+#define OPCODE_COMMON_RED_CONFIG (49)
+
+
+
+/*
+ * --- ETH_SUBSYSTEM_OPCODES ---
+ * These opcodes are used for configuring the Ethernet interfaces. These
+ * opcodes all use the FWCMD_SUBSYSTEM_ETH subsystem code.
+ */
+#define OPCODE_ETH_RSS_CONFIG (1)
+#define OPCODE_ETH_ACPI_CONFIG (2)
+#define SUBSYSTEM_ETH_RSS_CONFIG (3)
+#define SUBSYSTEM_ETH_ACPI_CONFIG (3)
+#define OPCODE_ETH_PROMISCUOUS (3)
+#define SUBSYSTEM_ETH_PROMISCUOUS (3)
+#define SUBSYSTEM_ETH_GET_STATISTICS (3)
+#define SUBSYSTEM_ETH_GET_RX_FRAG_SIZE (3)
+#define SUBSYSTEM_ETH_SET_RX_FRAG_SIZE (3)
+#define OPCODE_ETH_GET_STATISTICS (4)
+#define OPCODE_ETH_GET_RX_FRAG_SIZE (5)
+#define OPCODE_ETH_SET_RX_FRAG_SIZE (6)
+
+
+
+
+
+/*
+ * --- MCC_STATUS_CODE ---
+ * These are the global status codes used by all subsystems
+ */
+#define MCC_STATUS_SUCCESS (0) /* Indicates a successful
+ completion of the command */
+#define MCC_STATUS_INSUFFICIENT_PRIVILEGES (1) /* The client does not have
+ sufficient privileges to
+ execute the command */
+#define MCC_STATUS_INVALID_PARAMETER (2) /* A parameter in the command
+ was invalid. The extended
+ status contains the index
+ of the parameter */
+#define MCC_STATUS_INSUFFICIENT_RESOURCES (3) /* There are insufficient
+ chip resources to execute
+ the command */
+#define MCC_STATUS_QUEUE_FLUSHING (4) /* The command is completing
+ because the queue was
+ getting flushed */
+#define MCC_STATUS_DMA_FAILED (5) /* The command is completing
+ with a DMA error */
+
+/*
+ * --- MGMT_ERROR_CODES ---
+ * Error Codes returned in the status field of the FWCMD response header
+ */
+#define MGMT_STATUS_SUCCESS (0) /* The FWCMD completed
+ without errors */
+#define MGMT_STATUS_FAILED (1) /* Error status in the Status
+ field of the
+ struct FWCMD_RESPONSE_HEADER */
+#define MGMT_STATUS_ILLEGAL_REQUEST (2) /* Invalid FWCMD opcode */
+#define MGMT_STATUS_ILLEGAL_FIELD (3) /* Invalid parameter in
+ the FWCMD payload */
+
+#endif /* __fwcmd_opcodes_amap_h__ */
diff --git a/drivers/staging/benet/fwcmd_types_bmap.h b/drivers/staging/benet/fwcmd_types_bmap.h
new file mode 100644
index 000000000000..92217aff3a16
--- /dev/null
+++ b/drivers/staging/benet/fwcmd_types_bmap.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __fwcmd_types_bmap_h__
+#define __fwcmd_types_bmap_h__
+
+/* MAC address format */
+struct MAC_ADDRESS_FORMAT {
+ u16 SizeOfStructure;
+ u8 MACAddress[6];
+} __packed;
+
+#endif /* __fwcmd_types_bmap_h__ */
diff --git a/drivers/staging/benet/host_struct.h b/drivers/staging/benet/host_struct.h
new file mode 100644
index 000000000000..3de6722b980f
--- /dev/null
+++ b/drivers/staging/benet/host_struct.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __host_struct_amap_h__
+#define __host_struct_amap_h__
+#include "be_cm.h"
+#include "be_common.h"
+#include "descriptors.h"
+
+/* --- EQ_COMPLETION_MAJOR_CODE_ENUM --- */
+#define EQ_MAJOR_CODE_COMPLETION (0) /* Completion event on a */
+ /* qcompletion ueue. */
+#define EQ_MAJOR_CODE_ETH (1) /* Affiliated Ethernet Event. */
+#define EQ_MAJOR_CODE_RESERVED (2) /* Reserved */
+#define EQ_MAJOR_CODE_RDMA (3) /* Affiliated RDMA Event. */
+#define EQ_MAJOR_CODE_ISCSI (4) /* Affiliated ISCSI Event */
+#define EQ_MAJOR_CODE_UNAFFILIATED (5) /* Unaffiliated Event */
+
+/* --- EQ_COMPLETION_MINOR_CODE_ENUM --- */
+#define EQ_MINOR_CODE_COMPLETION (0) /* Completion event on a */
+ /* completion queue. */
+#define EQ_MINOR_CODE_OTHER (1) /* Other Event (TBD). */
+
+/* Queue Entry Definition for all 4 byte event queue types. */
+struct BE_EQ_ENTRY_AMAP {
+ u8 Valid; /* DWORD 0 */
+ u8 MajorCode[3]; /* DWORD 0 */
+ u8 MinorCode[12]; /* DWORD 0 */
+ u8 ResourceID[16]; /* DWORD 0 */
+} __packed;
+struct EQ_ENTRY_AMAP {
+ u32 dw[1];
+};
+
+/*
+ * --- ETH_EVENT_CODE ---
+ * These codes are returned by the MPU when one of these events has occurred,
+ * and the event is configured to report to an Event Queue when an event
+ * is detected.
+ */
+#define ETH_EQ_LINK_STATUS (0) /* Link status change event */
+ /* detected. */
+#define ETH_EQ_WATERMARK (1) /* watermark event detected. */
+#define ETH_EQ_MAGIC_PKT (2) /* magic pkt event detected. */
+#define ETH_EQ_ACPI_PKT0 (3) /* ACPI interesting packet */
+ /* detected. */
+#define ETH_EQ_ACPI_PKT1 (3) /* ACPI interesting packet */
+ /* detected. */
+#define ETH_EQ_ACPI_PKT2 (3) /* ACPI interesting packet */
+ /* detected. */
+#define ETH_EQ_ACPI_PKT3 (3) /* ACPI interesting packet */
+ /* detected. */
+
+/*
+ * --- ETH_TX_COMPL_STATUS_ENUM ---
+ * Status codes contained in Ethernet TX completion descriptors.
+ */
+#define ETH_COMP_VALID (0)
+#define ETH_COMP_ERROR (1)
+#define ETH_COMP_INVALID (15)
+
+/*
+ * --- ETH_TX_COMPL_PORT_ENUM ---
+ * Port indicator contained in Ethernet TX completion descriptors.
+ */
+#define ETH_COMP_PORT0 (0)
+#define ETH_COMP_PORT1 (1)
+#define ETH_COMP_MGMT (2)
+
+/*
+ * --- ETH_TX_COMPL_CT_ENUM ---
+ * Completion type indicator contained in Ethernet TX completion descriptors.
+ */
+#define ETH_COMP_ETH (0)
+
+/*
+ * Work request block that the driver issues to the chip for
+ * Ethernet transmissions. All control fields must be valid in each WRB for
+ * a message. The controller, as specified by the flags, optionally writes
+ * an entry to the Completion Ring and generate an event.
+ */
+struct BE_ETH_WRB_AMAP {
+ u8 frag_pa_hi[32]; /* DWORD 0 */
+ u8 frag_pa_lo[32]; /* DWORD 1 */
+ u8 complete; /* DWORD 2 */
+ u8 event; /* DWORD 2 */
+ u8 crc; /* DWORD 2 */
+ u8 forward; /* DWORD 2 */
+ u8 ipsec; /* DWORD 2 */
+ u8 mgmt; /* DWORD 2 */
+ u8 ipcs; /* DWORD 2 */
+ u8 udpcs; /* DWORD 2 */
+ u8 tcpcs; /* DWORD 2 */
+ u8 lso; /* DWORD 2 */
+ u8 last; /* DWORD 2 */
+ u8 vlan; /* DWORD 2 */
+ u8 dbg[3]; /* DWORD 2 */
+ u8 hash_val[3]; /* DWORD 2 */
+ u8 lso_mss[14]; /* DWORD 2 */
+ u8 frag_len[16]; /* DWORD 3 */
+ u8 vlan_tag[16]; /* DWORD 3 */
+} __packed;
+struct ETH_WRB_AMAP {
+ u32 dw[4];
+};
+
+/* This is an Ethernet transmit completion descriptor */
+struct BE_ETH_TX_COMPL_AMAP {
+ u8 user_bytes[16]; /* DWORD 0 */
+ u8 nwh_bytes[8]; /* DWORD 0 */
+ u8 lso; /* DWORD 0 */
+ u8 rsvd0[7]; /* DWORD 0 */
+ u8 wrb_index[16]; /* DWORD 1 */
+ u8 ct[2]; /* DWORD 1 */
+ u8 port[2]; /* DWORD 1 */
+ u8 rsvd1[8]; /* DWORD 1 */
+ u8 status[4]; /* DWORD 1 */
+ u8 rsvd2[16]; /* DWORD 2 */
+ u8 ringid[11]; /* DWORD 2 */
+ u8 hash_val[4]; /* DWORD 2 */
+ u8 valid; /* DWORD 2 */
+ u8 rsvd3[32]; /* DWORD 3 */
+} __packed;
+struct ETH_TX_COMPL_AMAP {
+ u32 dw[4];
+};
+
+/* Ethernet Receive Buffer descriptor */
+struct BE_ETH_RX_D_AMAP {
+ u8 fragpa_hi[32]; /* DWORD 0 */
+ u8 fragpa_lo[32]; /* DWORD 1 */
+} __packed;
+struct ETH_RX_D_AMAP {
+ u32 dw[2];
+};
+
+/* This is an Ethernet Receive Completion Descriptor */
+struct BE_ETH_RX_COMPL_AMAP {
+ u8 vlan_tag[16]; /* DWORD 0 */
+ u8 pktsize[14]; /* DWORD 0 */
+ u8 port; /* DWORD 0 */
+ u8 rsvd0; /* DWORD 0 */
+ u8 err; /* DWORD 1 */
+ u8 rsshp; /* DWORD 1 */
+ u8 ipf; /* DWORD 1 */
+ u8 tcpf; /* DWORD 1 */
+ u8 udpf; /* DWORD 1 */
+ u8 ipcksm; /* DWORD 1 */
+ u8 tcpcksm; /* DWORD 1 */
+ u8 udpcksm; /* DWORD 1 */
+ u8 macdst[6]; /* DWORD 1 */
+ u8 vtp; /* DWORD 1 */
+ u8 vtm; /* DWORD 1 */
+ u8 fragndx[10]; /* DWORD 1 */
+ u8 ct[2]; /* DWORD 1 */
+ u8 ipsec; /* DWORD 1 */
+ u8 numfrags[3]; /* DWORD 1 */
+ u8 rsvd1[31]; /* DWORD 2 */
+ u8 valid; /* DWORD 2 */
+ u8 rsshash[32]; /* DWORD 3 */
+} __packed;
+struct ETH_RX_COMPL_AMAP {
+ u32 dw[4];
+};
+
+#endif /* __host_struct_amap_h__ */
diff --git a/drivers/staging/benet/hwlib.h b/drivers/staging/benet/hwlib.h
new file mode 100644
index 000000000000..afedf4dc5903
--- /dev/null
+++ b/drivers/staging/benet/hwlib.h
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#ifndef __hwlib_h__
+#define __hwlib_h__
+
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "regmap.h" /* srcgen array map output */
+
+#include "asyncmesg.h"
+#include "fwcmd_opcodes.h"
+#include "post_codes.h"
+#include "fwcmd_mcc.h"
+
+#include "fwcmd_types_bmap.h"
+#include "fwcmd_common_bmap.h"
+#include "fwcmd_eth_bmap.h"
+#include "bestatus.h"
+/*
+ *
+ * Macros for reading/writing a protection domain or CSR registers
+ * in BladeEngine.
+ */
+#define PD_READ(fo, field) ioread32((fo)->db_va + \
+ offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8)
+
+#define PD_WRITE(fo, field, val) iowrite32(val, (fo)->db_va + \
+ offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8)
+
+#define CSR_READ(fo, field) ioread32((fo)->csr_va + \
+ offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8)
+
+#define CSR_WRITE(fo, field, val) iowrite32(val, (fo)->csr_va + \
+ offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8)
+
+#define PCICFG0_READ(fo, field) ioread32((fo)->pci_va + \
+ offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8)
+
+#define PCICFG0_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \
+ offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8)
+
+#define PCICFG1_READ(fo, field) ioread32((fo)->pci_va + \
+ offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8)
+
+#define PCICFG1_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \
+ offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8)
+
+#ifdef BE_DEBUG
+#define ASSERT(c) BUG_ON(!(c));
+#else
+#define ASSERT(c)
+#endif
+
+/* debug levels */
+enum BE_DEBUG_LEVELS {
+ DL_ALWAYS = 0, /* cannot be masked */
+ DL_ERR = 0x1, /* errors that should never happen */
+ DL_WARN = 0x2, /* something questionable.
+ recoverable errors */
+ DL_NOTE = 0x4, /* infrequent, important debug info */
+ DL_INFO = 0x8, /* debug information */
+ DL_VERBOSE = 0x10, /* detailed info, such as buffer traces */
+ BE_DL_MIN_VALUE = 0x1, /* this is the min value used */
+ BE_DL_MAX_VALUE = 0x80 /* this is the higheset value used */
+} ;
+
+extern unsigned int trace_level;
+
+#define TRACE(lm, fmt, args...) { \
+ if (trace_level & lm) { \
+ printk(KERN_NOTICE "BE: %s:%d \n" fmt, \
+ __FILE__ , __LINE__ , ## args); \
+ } \
+ }
+
+static inline unsigned int be_trace_set_level(unsigned int level)
+{
+ unsigned int old_level = trace_level;
+ trace_level = level;
+ return old_level;
+}
+
+#define be_trace_get_level() trace_level
+/*
+ * Returns number of pages spanned by the size of data
+ * starting at the given address.
+ */
+#define PAGES_SPANNED(_address, _size) \
+ ((u32)((((size_t)(_address) & (PAGE_SIZE - 1)) + \
+ (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+/* Byte offset into the page corresponding to given address */
+#define OFFSET_IN_PAGE(_addr_) ((size_t)(_addr_) & (PAGE_SIZE-1))
+
+/*
+ * circular subtract.
+ * Returns a - b assuming a circular number system, where a and b are
+ * in range (0, maxValue-1). If a==b, zero is returned so the
+ * highest value possible with this subtraction is maxValue-1.
+ */
+static inline u32 be_subc(u32 a, u32 b, u32 max)
+{
+ ASSERT(a <= max && b <= max);
+ ASSERT(max > 0);
+ return a >= b ? (a - b) : (max - b + a);
+}
+
+static inline u32 be_addc(u32 a, u32 b, u32 max)
+{
+ ASSERT(a < max);
+ ASSERT(max > 0);
+ return (max - a > b) ? (a + b) : (b + a - max);
+}
+
+/* descriptor for a physically contiguous memory used for ring */
+struct ring_desc {
+ u32 length; /* length in bytes */
+ void *va; /* virtual address */
+ u64 pa; /* bus address */
+} ;
+
+/*
+ * This structure stores information about a ring shared between hardware
+ * and software. Each ring is allocated by the driver in the uncached
+ * extension and mapped into BladeEngine's unified table.
+ */
+struct mp_ring {
+ u32 pages; /* queue size in pages */
+ u32 id; /* queue id assigned by beklib */
+ u32 num; /* number of elements in queue */
+ u32 cidx; /* consumer index */
+ u32 pidx; /* producer index -- not used by most rings */
+ u32 itemSize; /* size in bytes of one object */
+
+ void *va; /* The virtual address of the ring.
+ This should be last to allow 32 & 64
+ bit debugger extensions to work. */
+} ;
+
+/*----------- amap bit filed get / set macros and functions -----*/
+/*
+ * Structures defined in the map header files (under fw/amap/) with names
+ * in the format BE_<name>_AMAP are pseudo structures with members
+ * of type u8. These structures are templates that are used in
+ * conjuntion with the structures with names in the format
+ * <name>_AMAP to calculate the bit masks and bit offsets to get or set
+ * bit fields in structures. The structures <name>_AMAP are arrays
+ * of 32 bits words and have the correct size. The following macros
+ * provide convenient ways to get and set the various members
+ * in the structures without using strucctures with bit fields.
+ * Always use the macros AMAP_GET_BITS_PTR and AMAP_SET_BITS_PTR
+ * macros to extract and set various members.
+ */
+
+/*
+ * Returns the a bit mask for the register that is NOT shifted into location.
+ * That means return values always look like: 0x1, 0xFF, 0x7FF, etc...
+ */
+static inline u32 amap_mask(u32 bit_size)
+{
+ return bit_size == 32 ? 0xFFFFFFFF : (1 << bit_size) - 1;
+}
+
+#define AMAP_BIT_MASK(_struct_, field) \
+ amap_mask(AMAP_BIT_SIZE(_struct_, field))
+
+/*
+ * non-optimized set bits function. First clears the bits and then assigns them.
+ * This does not require knowledge of the particular DWORD you are setting.
+ * e.g. AMAP_SET_BITS_PTR (struct, field1, &contextMemory, 123);
+ */
+static inline void
+amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value)
+{
+ u32 *dw = (u32 *)ptr;
+ *(dw + dw_offset) &= ~(mask << offset);
+ *(dw + dw_offset) |= (mask & value) << offset;
+}
+
+#define AMAP_SET_BITS_PTR(_struct_, field, _structPtr_, val) \
+ amap_set(_structPtr_, AMAP_WORD_OFFSET(_struct_, field),\
+ AMAP_BIT_MASK(_struct_, field), \
+ AMAP_BIT_OFFSET(_struct_, field), val)
+/*
+ * Non-optimized routine that gets the bits without knowing the correct DWORD.
+ * e.g. fieldValue = AMAP_GET_BITS_PTR (struct, field1, &contextMemory);
+ */
+static inline u32
+amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset)
+{
+ u32 *dw = (u32 *)ptr;
+ return mask & (*(dw + dw_offset) >> offset);
+}
+#define AMAP_GET_BITS_PTR(_struct_, field, _structPtr_) \
+ amap_get(_structPtr_, AMAP_WORD_OFFSET(_struct_, field), \
+ AMAP_BIT_MASK(_struct_, field), \
+ AMAP_BIT_OFFSET(_struct_, field))
+
+/* Returns 0-31 representing bit offset within a DWORD of a bitfield. */
+#define AMAP_BIT_OFFSET(_struct_, field) \
+ (offsetof(struct BE_ ## _struct_ ## _AMAP, field) % 32)
+
+/* Returns 0-n representing DWORD offset of bitfield within the structure. */
+#define AMAP_WORD_OFFSET(_struct_, field) \
+ (offsetof(struct BE_ ## _struct_ ## _AMAP, field)/32)
+
+/* Returns size of bitfield in bits. */
+#define AMAP_BIT_SIZE(_struct_, field) \
+ sizeof(((struct BE_ ## _struct_ ## _AMAP*)0)->field)
+
+struct be_mcc_wrb_response_copy {
+ u16 length; /* bytes in response */
+ u16 fwcmd_offset; /* offset within the wrb of the response */
+ void *va; /* user's va to copy response into */
+
+} ;
+typedef void (*mcc_wrb_cqe_callback) (void *context, int status,
+ struct MCC_WRB_AMAP *optional_wrb);
+struct be_mcc_wrb_context {
+
+ mcc_wrb_cqe_callback internal_cb; /* Function to call on
+ completion */
+ void *internal_cb_context; /* Parameter to pass
+ to completion function */
+
+ mcc_wrb_cqe_callback cb; /* Function to call on completion */
+ void *cb_context; /* Parameter to pass to completion function */
+
+ int *users_final_status; /* pointer to a local
+ variable for synchronous
+ commands */
+ struct MCC_WRB_AMAP *wrb; /* pointer to original wrb for embedded
+ commands only */
+ struct list_head next; /* links context structs together in
+ free list */
+
+ struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy
+ embedded response to user's va */
+
+#if defined(BE_DEBUG)
+ u16 subsystem, opcode; /* Track this FWCMD for debug builds. */
+ struct MCC_WRB_AMAP *ring_wrb;
+ u32 consumed_count;
+#endif
+} ;
+
+/*
+ Represents a function object for network or storage. This
+ is used to manage per-function resources like MCC CQs, etc.
+*/
+struct be_function_object {
+
+ u32 magic; /*!< magic for detecting memory corruption. */
+
+ /* PCI BAR mapped addresses */
+ u8 __iomem *csr_va; /* CSR */
+ u8 __iomem *db_va; /* Door Bell */
+ u8 __iomem *pci_va; /* PCI config space */
+ u32 emulate; /* if set, MPU is not available.
+ Emulate everything. */
+ u32 pend_queue_driving; /* if set, drive the queued WRBs
+ after releasing the WRB lock */
+
+ spinlock_t post_lock; /* lock for verifying one thread posting wrbs */
+ spinlock_t cq_lock; /* lock for verifying one thread
+ processing cq */
+ spinlock_t mcc_context_lock; /* lock for protecting mcc
+ context free list */
+ unsigned long post_irq;
+ unsigned long cq_irq;
+
+ u32 type;
+ u32 pci_function_number;
+
+ struct be_mcc_object *mcc; /* mcc rings. */
+
+ struct {
+ struct MCC_MAILBOX_AMAP *va; /* VA to the mailbox */
+ u64 pa; /* PA to the mailbox */
+ u32 length; /* byte length of mailbox */
+
+ /* One default context struct used for posting at
+ * least one MCC_WRB
+ */
+ struct be_mcc_wrb_context default_context;
+ bool default_context_allocated;
+ } mailbox;
+
+ struct {
+
+ /* Wake on lans configured. */
+ u32 wol_bitmask; /* bits 0,1,2,3 are set if
+ corresponding index is enabled */
+ } config;
+
+
+ struct BE_FIRMWARE_CONFIG fw_config;
+} ;
+
+/*
+ Represents an Event Queue
+*/
+struct be_eq_object {
+ u32 magic;
+ atomic_t ref_count;
+
+ struct be_function_object *parent_function;
+
+ struct list_head eq_list;
+ struct list_head cq_list_head;
+
+ u32 eq_id;
+ void *cb_context;
+
+} ;
+
+/*
+ Manages a completion queue
+*/
+struct be_cq_object {
+ u32 magic;
+ atomic_t ref_count;
+
+ struct be_function_object *parent_function;
+ struct be_eq_object *eq_object;
+
+ struct list_head cq_list;
+ struct list_head cqlist_for_eq;
+
+ void *va;
+ u32 num_entries;
+
+ void *cb_context;
+
+ u32 cq_id;
+
+} ;
+
+/*
+ Manages an ethernet send queue
+*/
+struct be_ethsq_object {
+ u32 magic;
+
+ struct list_head list;
+
+ struct be_function_object *parent_function;
+ struct be_cq_object *cq_object;
+ u32 bid;
+
+} ;
+
+/*
+@brief
+ Manages an ethernet receive queue
+*/
+struct be_ethrq_object {
+ u32 magic;
+ struct list_head list;
+ struct be_function_object *parent_function;
+ u32 rid;
+ struct be_cq_object *cq_object;
+ struct be_cq_object *rss_cq_object[4];
+
+} ;
+
+/*
+ Manages an MCC
+*/
+typedef void (*mcc_async_event_callback) (void *context, u32 event_code,
+ void *event);
+struct be_mcc_object {
+ u32 magic;
+
+ struct be_function_object *parent_function;
+ struct list_head mcc_list;
+
+ struct be_cq_object *cq_object;
+
+ /* Async event callback for MCC CQ. */
+ mcc_async_event_callback async_cb;
+ void *async_context;
+
+ struct {
+ struct be_mcc_wrb_context *base;
+ u32 num;
+ struct list_head list_head;
+ } wrb_context;
+
+ struct {
+ struct ring_desc *rd;
+ struct mp_ring ring;
+ } sq;
+
+ struct {
+ struct mp_ring ring;
+ } cq;
+
+ u32 processing; /* flag indicating that one thread
+ is processing CQ */
+ u32 rearm; /* doorbell rearm setting to make
+ sure the active processing thread */
+ /* rearms the CQ if any of the threads requested it. */
+
+ struct list_head backlog;
+ u32 backlog_length;
+ u32 driving_backlog;
+ u32 consumed_index;
+
+} ;
+
+
+/* Queue context header -- the required software information for
+ * queueing a WRB.
+ */
+struct be_queue_driver_context {
+ mcc_wrb_cqe_callback internal_cb; /* Function to call on
+ completion */
+ void *internal_cb_context; /* Parameter to pass
+ to completion function */
+
+ mcc_wrb_cqe_callback cb; /* Function to call on completion */
+ void *cb_context; /* Parameter to pass to completion function */
+
+ struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy
+ embedded response to user's va */
+ void *optional_fwcmd_va;
+ struct list_head list;
+ u32 bytes;
+} ;
+
+/*
+ * Common MCC WRB header that all commands require.
+ */
+struct be_mcc_wrb_header {
+ u8 rsvd[offsetof(struct BE_MCC_WRB_AMAP, payload)/8];
+} ;
+
+/*
+ * All non embedded commands supported by hwlib functions only allow
+ * 1 SGE. This queue context handles them all.
+ */
+struct be_nonembedded_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct MCC_SGE_AMAP sge[1];
+} ;
+
+/*
+ * ------------------------------------------------------------------------
+ * This section contains the specific queue struct for each command.
+ * The user could always provide a be_generic_q_ctxt but this is a
+ * rather large struct. By using the specific struct, memory consumption
+ * can be reduced.
+ * ------------------------------------------------------------------------
+ */
+
+struct be_link_status_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY fwcmd;
+} ;
+
+struct be_multicast_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct FWCMD_COMMON_NTWK_MULTICAST_SET fwcmd;
+} ;
+
+
+struct be_vlan_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct FWCMD_COMMON_NTWK_VLAN_CONFIG fwcmd;
+} ;
+
+struct be_promiscuous_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct FWCMD_ETH_PROMISCUOUS fwcmd;
+} ;
+
+struct be_force_failover_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct FWCMD_COMMON_FORCE_FAILOVER fwcmd;
+} ;
+
+
+struct be_rxf_filter_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct FWCMD_COMMON_NTWK_RX_FILTER fwcmd;
+} ;
+
+struct be_eq_modify_delay_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct FWCMD_COMMON_MODIFY_EQ_DELAY fwcmd;
+} ;
+
+/*
+ * The generic context is the largest size that would be required.
+ * It is the software context plus an entire WRB.
+ */
+struct be_generic_q_ctxt {
+ struct be_queue_driver_context context;
+ struct be_mcc_wrb_header wrb_header;
+ struct MCC_WRB_PAYLOAD_AMAP payload;
+} ;
+
+/*
+ * Types for the BE_QUEUE_CONTEXT object.
+ */
+#define BE_QUEUE_INVALID (0)
+#define BE_QUEUE_LINK_STATUS (0xA006)
+#define BE_QUEUE_ETH_STATS (0xA007)
+#define BE_QUEUE_TPM_STATS (0xA008)
+#define BE_QUEUE_TCP_STATS (0xA009)
+#define BE_QUEUE_MULTICAST (0xA00A)
+#define BE_QUEUE_VLAN (0xA00B)
+#define BE_QUEUE_RSS (0xA00C)
+#define BE_QUEUE_FORCE_FAILOVER (0xA00D)
+#define BE_QUEUE_PROMISCUOUS (0xA00E)
+#define BE_QUEUE_WAKE_ON_LAN (0xA00F)
+#define BE_QUEUE_NOP (0xA010)
+
+/* --- BE_FUNCTION_ENUM --- */
+#define BE_FUNCTION_TYPE_ISCSI (0)
+#define BE_FUNCTION_TYPE_NETWORK (1)
+#define BE_FUNCTION_TYPE_ARM (2)
+
+/* --- BE_ETH_TX_RING_TYPE_ENUM --- */
+#define BE_ETH_TX_RING_TYPE_FORWARDING (1) /* Ether ring for forwarding */
+#define BE_ETH_TX_RING_TYPE_STANDARD (2) /* Ether ring for sending */
+ /* network packets. */
+#define BE_ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring for sending */
+ /* network packets, bound */
+ /* to a physical port. */
+/*
+ * ----------------------------------------------------------------------
+ * API MACROS
+ * ----------------------------------------------------------------------
+ */
+#define BE_FWCMD_NAME(_short_name_) struct FWCMD_##_short_name_
+#define BE_OPCODE_NAME(_short_name_) OPCODE_##_short_name_
+#define BE_SUBSYSTEM_NAME(_short_name_) SUBSYSTEM_##_short_name_
+
+
+#define BE_PREPARE_EMBEDDED_FWCMD(_pfob_, _wrb_, _short_name_) \
+ ((BE_FWCMD_NAME(_short_name_) *) \
+ be_function_prepare_embedded_fwcmd(_pfob_, _wrb_, \
+ sizeof(BE_FWCMD_NAME(_short_name_)), \
+ FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \
+ FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \
+ BE_OPCODE_NAME(_short_name_), \
+ BE_SUBSYSTEM_NAME(_short_name_)));
+
+#define BE_PREPARE_NONEMBEDDED_FWCMD(_pfob_, _wrb_, _iva_, _ipa_, _short_name_)\
+ ((BE_FWCMD_NAME(_short_name_) *) \
+ be_function_prepare_nonembedded_fwcmd(_pfob_, _wrb_, (_iva_), (_ipa_), \
+ sizeof(BE_FWCMD_NAME(_short_name_)), \
+ FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \
+ FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \
+ BE_OPCODE_NAME(_short_name_), \
+ BE_SUBSYSTEM_NAME(_short_name_)));
+
+int be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va,
+ u8 __iomem *pci_va, u32 function_type, struct ring_desc *mailbox_rd,
+ struct be_function_object *pfob);
+
+int be_function_object_destroy(struct be_function_object *pfob);
+int be_function_cleanup(struct be_function_object *pfob);
+
+
+int be_function_get_fw_version(struct be_function_object *pfob,
+ struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fw_version,
+ mcc_wrb_cqe_callback cb, void *cb_context);
+
+
+int be_eq_modify_delay(struct be_function_object *pfob,
+ u32 num_eq, struct be_eq_object **eq_array,
+ u32 *eq_delay_array, mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ struct be_eq_modify_delay_q_ctxt *q_ctxt);
+
+
+
+int be_eq_create(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 eqe_size, u32 num_entries,
+ u32 watermark, u32 timer_delay, struct be_eq_object *eq_object);
+
+int be_eq_destroy(struct be_eq_object *eq);
+
+int be_cq_create(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 length,
+ bool solicited_eventable, bool no_delay,
+ u32 wm_thresh, struct be_eq_object *eq_object,
+ struct be_cq_object *cq_object);
+
+int be_cq_destroy(struct be_cq_object *cq);
+
+int be_mcc_ring_create(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 length,
+ struct be_mcc_wrb_context *context_array,
+ u32 num_context_entries,
+ struct be_cq_object *cq, struct be_mcc_object *mcc);
+int be_mcc_ring_destroy(struct be_mcc_object *mcc_object);
+
+int be_mcc_process_cq(struct be_mcc_object *mcc_object, bool rearm);
+
+int be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object,
+ mcc_async_event_callback cb, void *cb_context);
+
+int be_pci_soft_reset(struct be_function_object *pfob);
+
+
+int be_drive_POST(struct be_function_object *pfob);
+
+
+int be_eth_sq_create(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 length_in_bytes,
+ u32 type, u32 ulp, struct be_cq_object *cq_object,
+ struct be_ethsq_object *eth_sq);
+
+struct be_eth_sq_parameters {
+ u32 port;
+ u32 rsvd0[2];
+} ;
+
+int be_eth_sq_create_ex(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 length_in_bytes,
+ u32 type, u32 ulp, struct be_cq_object *cq_object,
+ struct be_eth_sq_parameters *ex_parameters,
+ struct be_ethsq_object *eth_sq);
+int be_eth_sq_destroy(struct be_ethsq_object *eth_sq);
+
+int be_eth_set_flow_control(struct be_function_object *pfob,
+ bool txfc_enable, bool rxfc_enable);
+
+int be_eth_get_flow_control(struct be_function_object *pfob,
+ bool *txfc_enable, bool *rxfc_enable);
+int be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps);
+
+int be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps);
+
+int be_eth_set_frame_size(struct be_function_object *pfob,
+ u32 *tx_frame_size, u32 *rx_frame_size);
+
+int be_eth_rq_create(struct be_function_object *pfob,
+ struct ring_desc *rd, struct be_cq_object *cq_object,
+ struct be_cq_object *bcmc_cq_object,
+ struct be_ethrq_object *eth_rq);
+
+int be_eth_rq_destroy(struct be_ethrq_object *eth_rq);
+
+int be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush,
+ mcc_wrb_cqe_callback cb, void *cb_context);
+int be_eth_rq_set_frag_size(struct be_function_object *pfob,
+ u32 new_frag_size_bytes, u32 *actual_frag_size_bytes);
+int be_eth_rq_get_frag_size(struct be_function_object *pfob,
+ u32 *frag_size_bytes);
+
+void *be_function_prepare_embedded_fwcmd(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb,
+ u32 payload_length, u32 request_length,
+ u32 response_length, u32 opcode, u32 subsystem);
+void *be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb, void *fwcmd_header_va, u64 fwcmd_header_pa,
+ u32 payload_length, u32 request_length, u32 response_length,
+ u32 opcode, u32 subsystem);
+
+
+struct MCC_WRB_AMAP *
+be_function_peek_mcc_wrb(struct be_function_object *pfob);
+
+int be_rxf_mac_address_read_write(struct be_function_object *pfob,
+ bool port1, bool mac1, bool mgmt,
+ bool write, bool permanent, u8 *mac_address,
+ mcc_wrb_cqe_callback cb,
+ void *cb_context);
+
+int be_rxf_multicast_config(struct be_function_object *pfob,
+ bool promiscuous, u32 num, u8 *mac_table,
+ mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ struct be_multicast_q_ctxt *q_ctxt);
+
+int be_rxf_vlan_config(struct be_function_object *pfob,
+ bool promiscuous, u32 num, u16 *vlan_tag_array,
+ mcc_wrb_cqe_callback cb, void *cb_context,
+ struct be_vlan_q_ctxt *q_ctxt);
+
+
+int be_rxf_link_status(struct be_function_object *pfob,
+ struct BE_LINK_STATUS *link_status,
+ mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ struct be_link_status_q_ctxt *q_ctxt);
+
+
+int be_rxf_query_eth_statistics(struct be_function_object *pfob,
+ struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd,
+ u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ struct be_nonembedded_q_ctxt *q_ctxt);
+
+int be_rxf_promiscuous(struct be_function_object *pfob,
+ bool enable_port0, bool enable_port1,
+ mcc_wrb_cqe_callback cb, void *cb_context,
+ struct be_promiscuous_q_ctxt *q_ctxt);
+
+
+int be_rxf_filter_config(struct be_function_object *pfob,
+ struct NTWK_RX_FILTER_SETTINGS *settings,
+ mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ struct be_rxf_filter_q_ctxt *q_ctxt);
+
+/*
+ * ------------------------------------------------------
+ * internal functions used by hwlib
+ * ------------------------------------------------------
+ */
+
+
+int be_function_ring_destroy(struct be_function_object *pfob,
+ u32 id, u32 ring_type, mcc_wrb_cqe_callback cb,
+ void *cb_context,
+ mcc_wrb_cqe_callback internal_cb,
+ void *internal_callback_context);
+
+int be_function_post_mcc_wrb(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb,
+ struct be_generic_q_ctxt *q_ctxt,
+ mcc_wrb_cqe_callback cb, void *cb_context,
+ mcc_wrb_cqe_callback internal_cb,
+ void *internal_cb_context, void *optional_fwcmd_va,
+ struct be_mcc_wrb_response_copy *response_copy);
+
+int be_function_queue_mcc_wrb(struct be_function_object *pfob,
+ struct be_generic_q_ctxt *q_ctxt);
+
+/*
+ * ------------------------------------------------------
+ * MCC QUEUE
+ * ------------------------------------------------------
+ */
+
+int be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *rd);
+
+
+struct MCC_WRB_AMAP *
+_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue);
+
+struct be_mcc_wrb_context *
+_be_mcc_allocate_wrb_context(struct be_function_object *pfob);
+
+void _be_mcc_free_wrb_context(struct be_function_object *pfob,
+ struct be_mcc_wrb_context *context);
+
+int _be_mpu_post_wrb_mailbox(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context);
+
+int _be_mpu_post_wrb_ring(struct be_mcc_object *mcc,
+ struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context);
+
+void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc);
+
+
+/*
+ * ------------------------------------------------------
+ * Ring Sizes
+ * ------------------------------------------------------
+ */
+static inline u32 be_ring_encoding_to_length(u32 encoding, u32 object_size)
+{
+
+ ASSERT(encoding != 1); /* 1 is rsvd */
+ ASSERT(encoding < 16);
+ ASSERT(object_size > 0);
+
+ if (encoding == 0) /* 32k deep */
+ encoding = 16;
+
+ return (1 << (encoding - 1)) * object_size;
+}
+
+static inline
+u32 be_ring_length_to_encoding(u32 length_in_bytes, u32 object_size)
+{
+
+ u32 count, encoding;
+
+ ASSERT(object_size > 0);
+ ASSERT(length_in_bytes % object_size == 0);
+
+ count = length_in_bytes / object_size;
+
+ ASSERT(count > 1);
+ ASSERT(count <= 32 * 1024);
+ ASSERT(length_in_bytes <= 8 * PAGE_SIZE); /* max ring size in UT */
+
+ encoding = __ilog2_u32(count) + 1;
+
+ if (encoding == 16)
+ encoding = 0; /* 32k deep */
+
+ return encoding;
+}
+
+void be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list,
+ u32 max_num);
+#endif /* __hwlib_h__ */
diff --git a/drivers/staging/benet/mpu.c b/drivers/staging/benet/mpu.c
new file mode 100644
index 000000000000..269cc11d3055
--- /dev/null
+++ b/drivers/staging/benet/mpu.c
@@ -0,0 +1,1364 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+#include <linux/delay.h>
+#include "hwlib.h"
+#include "bestatus.h"
+
+static
+inline void mp_ring_create(struct mp_ring *ring, u32 num, u32 size, void *va)
+{
+ ASSERT(ring);
+ memset(ring, 0, sizeof(struct mp_ring));
+ ring->num = num;
+ ring->pages = DIV_ROUND_UP(num * size, PAGE_SIZE);
+ ring->itemSize = size;
+ ring->va = va;
+}
+
+/*
+ * -----------------------------------------------------------------------
+ * Interface for 2 index rings. i.e. consumer/producer rings
+ * --------------------------------------------------------------------------
+ */
+
+/* Returns number items pending on ring. */
+static inline u32 mp_ring_num_pending(struct mp_ring *ring)
+{
+ ASSERT(ring);
+ if (ring->num == 0)
+ return 0;
+ return be_subc(ring->pidx, ring->cidx, ring->num);
+}
+
+/* Returns number items free on ring. */
+static inline u32 mp_ring_num_empty(struct mp_ring *ring)
+{
+ ASSERT(ring);
+ return ring->num - 1 - mp_ring_num_pending(ring);
+}
+
+/* Consume 1 item */
+static inline void mp_ring_consume(struct mp_ring *ring)
+{
+ ASSERT(ring);
+ ASSERT(ring->pidx != ring->cidx);
+
+ ring->cidx = be_addc(ring->cidx, 1, ring->num);
+}
+
+/* Produce 1 item */
+static inline void mp_ring_produce(struct mp_ring *ring)
+{
+ ASSERT(ring);
+ ring->pidx = be_addc(ring->pidx, 1, ring->num);
+}
+
+/* Consume count items */
+static inline void mp_ring_consume_multiple(struct mp_ring *ring, u32 count)
+{
+ ASSERT(ring);
+ ASSERT(mp_ring_num_pending(ring) >= count);
+ ring->cidx = be_addc(ring->cidx, count, ring->num);
+}
+
+static inline void *mp_ring_item(struct mp_ring *ring, u32 index)
+{
+ ASSERT(ring);
+ ASSERT(index < ring->num);
+ ASSERT(ring->itemSize > 0);
+ return (u8 *) ring->va + index * ring->itemSize;
+}
+
+/* Ptr to produce item */
+static inline void *mp_ring_producer_ptr(struct mp_ring *ring)
+{
+ ASSERT(ring);
+ return mp_ring_item(ring, ring->pidx);
+}
+
+/*
+ * Returns a pointer to the current location in the ring.
+ * This is used for rings with 1 index.
+ */
+static inline void *mp_ring_current(struct mp_ring *ring)
+{
+ ASSERT(ring);
+ ASSERT(ring->pidx == 0); /* not used */
+
+ return mp_ring_item(ring, ring->cidx);
+}
+
+/*
+ * Increment index for rings with only 1 index.
+ * This is used for rings with 1 index.
+ */
+static inline void *mp_ring_next(struct mp_ring *ring)
+{
+ ASSERT(ring);
+ ASSERT(ring->num > 0);
+ ASSERT(ring->pidx == 0); /* not used */
+
+ ring->cidx = be_addc(ring->cidx, 1, ring->num);
+ return mp_ring_current(ring);
+}
+
+/*
+ This routine waits for a previously posted mailbox WRB to be completed.
+ Specifically it waits for the mailbox to say that it's ready to accept
+ more data by setting the LSB of the mailbox pd register to 1.
+
+ pcontroller - The function object to post this data to
+
+ IRQL < DISPATCH_LEVEL
+*/
+static void be_mcc_mailbox_wait(struct be_function_object *pfob)
+{
+ struct MPU_MAILBOX_DB_AMAP mailbox_db;
+ u32 i = 0;
+ u32 ready;
+
+ if (pfob->emulate) {
+ /* No waiting for mailbox in emulated mode. */
+ return;
+ }
+
+ mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db);
+ ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db);
+
+ while (ready == false) {
+ if ((++i & 0x3FFFF) == 0) {
+ TRACE(DL_WARN, "Waiting for mailbox ready - %dk polls",
+ i / 1000);
+ }
+ udelay(1);
+ mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db);
+ ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db);
+ }
+}
+
+/*
+ This routine tells the MCC mailbox that there is data to processed
+ in the mailbox. It does this by setting the physical address for the
+ mailbox location and clearing the LSB. This routine returns immediately
+ and does not wait for the WRB to be processed.
+
+ pcontroller - The function object to post this data to
+
+ IRQL < DISPATCH_LEVEL
+
+*/
+static void be_mcc_mailbox_notify(struct be_function_object *pfob)
+{
+ struct MPU_MAILBOX_DB_AMAP mailbox_db;
+ u32 pa;
+
+ ASSERT(pfob->mailbox.pa);
+ ASSERT(pfob->mailbox.va);
+
+ /* If emulated, do not ring the mailbox */
+ if (pfob->emulate) {
+ TRACE(DL_WARN, "MPU disabled. Skipping mailbox notify.");
+ return;
+ }
+
+ /* form the higher bits in the address */
+ mailbox_db.dw[0] = 0; /* init */
+ AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 1);
+ AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0);
+
+ /* bits 34 to 63 */
+ pa = (u32) (pfob->mailbox.pa >> 34);
+ AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa);
+
+ /* Wait for the MPU to be ready */
+ be_mcc_mailbox_wait(pfob);
+
+ /* Ring doorbell 1st time */
+ PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]);
+
+ /* Wait for 1st write to be acknowledged. */
+ be_mcc_mailbox_wait(pfob);
+
+ /* lower bits 30 bits from 4th bit (bits 4 to 33)*/
+ pa = (u32) (pfob->mailbox.pa >> 4) & 0x3FFFFFFF;
+
+ AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 0);
+ AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0);
+ AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa);
+
+ /* Ring doorbell 2nd time */
+ PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]);
+}
+
+/*
+ This routine tells the MCC mailbox that there is data to processed
+ in the mailbox. It does this by setting the physical address for the
+ mailbox location and clearing the LSB. This routine spins until the
+ MPU writes a 1 into the LSB indicating that the data has been received
+ and is ready to be processed.
+
+ pcontroller - The function object to post this data to
+
+ IRQL < DISPATCH_LEVEL
+*/
+static void
+be_mcc_mailbox_notify_and_wait(struct be_function_object *pfob)
+{
+ /*
+ * Notify it
+ */
+ be_mcc_mailbox_notify(pfob);
+ /*
+ * Now wait for completion of WRB
+ */
+ be_mcc_mailbox_wait(pfob);
+}
+
+void
+be_mcc_process_cqe(struct be_function_object *pfob,
+ struct MCC_CQ_ENTRY_AMAP *cqe)
+{
+ struct be_mcc_wrb_context *wrb_context = NULL;
+ u32 offset, status;
+ u8 *p;
+
+ ASSERT(cqe);
+ /*
+ * A command completed. Commands complete out-of-order.
+ * Determine which command completed from the TAG.
+ */
+ offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8;
+ p = (u8 *) cqe + offset;
+ wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p);
+ ASSERT(wrb_context);
+
+ /*
+ * Perform a response copy if requested.
+ * Only copy data if the FWCMD is successful.
+ */
+ status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, cqe);
+ if (status == MGMT_STATUS_SUCCESS && wrb_context->copy.length > 0) {
+ ASSERT(wrb_context->wrb);
+ ASSERT(wrb_context->copy.va);
+ p = (u8 *)wrb_context->wrb +
+ offsetof(struct BE_MCC_WRB_AMAP, payload)/8;
+ memcpy(wrb_context->copy.va,
+ (u8 *)p + wrb_context->copy.fwcmd_offset,
+ wrb_context->copy.length);
+ }
+
+ if (status)
+ status = BE_NOT_OK;
+ /* internal callback */
+ if (wrb_context->internal_cb) {
+ wrb_context->internal_cb(wrb_context->internal_cb_context,
+ status, wrb_context->wrb);
+ }
+
+ /* callback */
+ if (wrb_context->cb) {
+ wrb_context->cb(wrb_context->cb_context,
+ status, wrb_context->wrb);
+ }
+ /* Free the context structure */
+ _be_mcc_free_wrb_context(pfob, wrb_context);
+}
+
+void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc)
+{
+ struct be_function_object *pfob = NULL;
+ int status = BE_PENDING;
+ struct be_generic_q_ctxt *q_ctxt;
+ struct MCC_WRB_AMAP *wrb;
+ struct MCC_WRB_AMAP *queue_wrb;
+ u32 length, payload_length, sge_count, embedded;
+ unsigned long irql;
+
+ BUILD_BUG_ON((sizeof(struct be_generic_q_ctxt) <
+ sizeof(struct be_queue_driver_context) +
+ sizeof(struct MCC_WRB_AMAP)));
+ pfob = mcc->parent_function;
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ if (mcc->driving_backlog) {
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return;
+ }
+ /* Acquire the flag to limit 1 thread to redrive posts. */
+ mcc->driving_backlog = 1;
+
+ while (!list_empty(&mcc->backlog)) {
+ wrb = _be_mpu_peek_ring_wrb(mcc, true); /* Driving the queue */
+ if (!wrb)
+ break; /* No space in the ring yet. */
+ /* Get the next queued entry to process. */
+ q_ctxt = list_first_entry(&mcc->backlog,
+ struct be_generic_q_ctxt, context.list);
+ list_del(&q_ctxt->context.list);
+ pfob->mcc->backlog_length--;
+ /*
+ * Compute the required length of the WRB.
+ * Since the queue element may be smaller than
+ * the complete WRB, copy only the required number of bytes.
+ */
+ queue_wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header;
+ embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, queue_wrb);
+ if (embedded) {
+ payload_length = AMAP_GET_BITS_PTR(MCC_WRB,
+ payload_length, queue_wrb);
+ length = sizeof(struct be_mcc_wrb_header) +
+ payload_length;
+ } else {
+ sge_count = AMAP_GET_BITS_PTR(MCC_WRB, sge_count,
+ queue_wrb);
+ ASSERT(sge_count == 1); /* only 1 frag. */
+ length = sizeof(struct be_mcc_wrb_header) +
+ sge_count * sizeof(struct MCC_SGE_AMAP);
+ }
+
+ /*
+ * Truncate the length based on the size of the
+ * queue element. Some elements that have output parameters
+ * can be smaller than the payload_length field would
+ * indicate. We really only need to copy the request
+ * parameters, not the response.
+ */
+ length = min(length, (u32) (q_ctxt->context.bytes -
+ offsetof(struct be_generic_q_ctxt, wrb_header)));
+
+ /* Copy the queue element WRB into the ring. */
+ memcpy(wrb, &q_ctxt->wrb_header, length);
+
+ /* Post the wrb. This should not fail assuming we have
+ * enough context structs. */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL,
+ q_ctxt->context.cb, q_ctxt->context.cb_context,
+ q_ctxt->context.internal_cb,
+ q_ctxt->context.internal_cb_context,
+ q_ctxt->context.optional_fwcmd_va,
+ &q_ctxt->context.copy);
+
+ if (status == BE_SUCCESS) {
+ /*
+ * Synchronous completion. Since it was queued,
+ * we will invoke the callback.
+ * To the user, this is an asynchronous request.
+ */
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+
+ ASSERT(q_ctxt->context.cb);
+
+ q_ctxt->context.cb(
+ q_ctxt->context.cb_context,
+ BE_SUCCESS, NULL);
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ } else if (status != BE_PENDING) {
+ /*
+ * Another resource failed. Should never happen
+ * if we have sufficient MCC_WRB_CONTEXT structs.
+ * Return to head of the queue.
+ */
+ TRACE(DL_WARN, "Failed to post a queued WRB. 0x%x",
+ status);
+ list_add(&q_ctxt->context.list, &mcc->backlog);
+ pfob->mcc->backlog_length++;
+ break;
+ }
+ }
+
+ /* Free the flag to limit 1 thread to redrive posts. */
+ mcc->driving_backlog = 0;
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+}
+
+/* This function asserts that the WRB was consumed in order. */
+#ifdef BE_DEBUG
+u32 be_mcc_wrb_consumed_in_order(struct be_mcc_object *mcc,
+ struct MCC_CQ_ENTRY_AMAP *cqe)
+{
+ struct be_mcc_wrb_context *wrb_context = NULL;
+ u32 wrb_index;
+ u32 wrb_consumed_in_order;
+ u32 offset;
+ u8 *p;
+
+ ASSERT(cqe);
+ /*
+ * A command completed. Commands complete out-of-order.
+ * Determine which command completed from the TAG.
+ */
+ offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8;
+ p = (u8 *) cqe + offset;
+ wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p);
+
+ ASSERT(wrb_context);
+
+ wrb_index = (u32) (((u64)(size_t)wrb_context->ring_wrb -
+ (u64)(size_t)mcc->sq.ring.va) / sizeof(struct MCC_WRB_AMAP));
+
+ ASSERT(wrb_index < mcc->sq.ring.num);
+
+ wrb_consumed_in_order = (u32) (wrb_index == mcc->consumed_index);
+ mcc->consumed_index = be_addc(mcc->consumed_index, 1, mcc->sq.ring.num);
+ return wrb_consumed_in_order;
+}
+#endif
+
+int be_mcc_process_cq(struct be_mcc_object *mcc, bool rearm)
+{
+ struct be_function_object *pfob = NULL;
+ struct MCC_CQ_ENTRY_AMAP *cqe;
+ struct CQ_DB_AMAP db;
+ struct mp_ring *cq_ring = &mcc->cq.ring;
+ struct mp_ring *mp_ring = &mcc->sq.ring;
+ u32 num_processed = 0;
+ u32 consumed = 0, valid, completed, cqe_consumed, async_event;
+
+ pfob = mcc->parent_function;
+
+ spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq);
+
+ /*
+ * Verify that only one thread is processing the CQ at once.
+ * We cannot hold the lock while processing the CQ due to
+ * the callbacks into the OS. Therefore, this flag is used
+ * to control it. If any of the threads want to
+ * rearm the CQ, we need to honor that.
+ */
+ if (mcc->processing != 0) {
+ mcc->rearm = mcc->rearm || rearm;
+ goto Error;
+ } else {
+ mcc->processing = 1; /* lock processing for this thread. */
+ mcc->rearm = rearm; /* set our rearm setting */
+ }
+
+ spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq);
+
+ cqe = mp_ring_current(cq_ring);
+ valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe);
+ while (valid) {
+
+ if (num_processed >= 8) {
+ /* coalesce doorbells, but free space in cq
+ * ring while processing. */
+ db.dw[0] = 0; /* clear */
+ AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id);
+ AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, false);
+ AMAP_SET_BITS_PTR(CQ_DB, event, &db, false);
+ AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db,
+ num_processed);
+ num_processed = 0;
+
+ PD_WRITE(pfob, cq_db, db.dw[0]);
+ }
+
+ async_event = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, async_event, cqe);
+ if (async_event) {
+ /* This is an asynchronous event. */
+ struct ASYNC_EVENT_TRAILER_AMAP *async_trailer =
+ (struct ASYNC_EVENT_TRAILER_AMAP *)
+ ((u8 *) cqe + sizeof(struct MCC_CQ_ENTRY_AMAP) -
+ sizeof(struct ASYNC_EVENT_TRAILER_AMAP));
+ u32 event_code;
+ async_event = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER,
+ async_event, async_trailer);
+ ASSERT(async_event == 1);
+
+
+ valid = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER,
+ valid, async_trailer);
+ ASSERT(valid == 1);
+
+ /* Call the async event handler if it is installed. */
+ if (mcc->async_cb) {
+ event_code =
+ AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER,
+ event_code, async_trailer);
+ mcc->async_cb(mcc->async_context,
+ (u32) event_code, (void *) cqe);
+ }
+
+ } else {
+ /* This is a completion entry. */
+
+ /* No vm forwarding in this driver. */
+
+ cqe_consumed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY,
+ consumed, cqe);
+ if (cqe_consumed) {
+ /*
+ * A command on the MCC ring was consumed.
+ * Update the consumer index.
+ * These occur in order.
+ */
+ ASSERT(be_mcc_wrb_consumed_in_order(mcc, cqe));
+ consumed++;
+ }
+
+ completed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY,
+ completed, cqe);
+ if (completed) {
+ /* A command completed. Use tag to
+ * determine which command. */
+ be_mcc_process_cqe(pfob, cqe);
+ }
+ }
+
+ /* Reset the CQE */
+ AMAP_SET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe, false);
+ num_processed++;
+
+ /* Update our tracking for the CQ ring. */
+ cqe = mp_ring_next(cq_ring);
+ valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe);
+ }
+
+ TRACE(DL_INFO, "num_processed:0x%x, and consumed:0x%x",
+ num_processed, consumed);
+ /*
+ * Grab the CQ lock to synchronize the "rearm" setting for
+ * the doorbell, and for clearing the "processing" flag.
+ */
+ spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq);
+
+ /*
+ * Rearm the cq. This is done based on the global mcc->rearm
+ * flag which combines the rearm parameter from the current
+ * call to process_cq and any other threads
+ * that tried to process the CQ while this one was active.
+ * This handles the situation where a sync. fwcmd was processing
+ * the CQ while the interrupt/dpc tries to process it.
+ * The sync process gets to continue -- but it is now
+ * responsible for the rearming.
+ */
+ if (num_processed > 0 || mcc->rearm == true) {
+ db.dw[0] = 0; /* clear */
+ AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id);
+ AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, mcc->rearm);
+ AMAP_SET_BITS_PTR(CQ_DB, event, &db, false);
+ AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, num_processed);
+
+ PD_WRITE(pfob, cq_db, db.dw[0]);
+ }
+ /*
+ * Update the consumer index after ringing the CQ doorbell.
+ * We don't want another thread to post more WRBs before we
+ * have CQ space available.
+ */
+ mp_ring_consume_multiple(mp_ring, consumed);
+
+ /* Clear the processing flag. */
+ mcc->processing = 0;
+
+Error:
+ spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq);
+ /*
+ * Use the local variable to detect if the current thread
+ * holds the WRB post lock. If rearm is false, this is
+ * either a synchronous command, or the upper layer driver is polling
+ * from a thread. We do not drive the queue from that
+ * context since the driver may hold the
+ * wrb post lock already.
+ */
+ if (rearm)
+ be_drive_mcc_wrb_queue(mcc);
+ else
+ pfob->pend_queue_driving = 1;
+
+ return BE_SUCCESS;
+}
+
+/*
+ *============================================================================
+ * P U B L I C R O U T I N E S
+ *============================================================================
+ */
+
+/*
+ This routine creates an MCC object. This object contains an MCC send queue
+ and a CQ private to the MCC.
+
+ pcontroller - Handle to a function object
+
+ EqObject - EQ object that will be used to dispatch this MCC
+
+ ppMccObject - Pointer to an internal Mcc Object returned.
+
+ Returns BE_SUCCESS if successfull,, otherwise a useful error code
+ is returned.
+
+ IRQL < DISPATCH_LEVEL
+
+*/
+int
+be_mcc_ring_create(struct be_function_object *pfob,
+ struct ring_desc *rd, u32 length,
+ struct be_mcc_wrb_context *context_array,
+ u32 num_context_entries,
+ struct be_cq_object *cq, struct be_mcc_object *mcc)
+{
+ int status = 0;
+
+ struct FWCMD_COMMON_MCC_CREATE *fwcmd = NULL;
+ struct MCC_WRB_AMAP *wrb = NULL;
+ u32 num_entries_encoded, n, i;
+ void *va = NULL;
+ unsigned long irql;
+
+ if (length < sizeof(struct MCC_WRB_AMAP) * 2) {
+ TRACE(DL_ERR, "Invalid MCC ring length:%d", length);
+ return BE_NOT_OK;
+ }
+ /*
+ * Reduce the actual ring size to be less than the number
+ * of context entries. This ensures that we run out of
+ * ring WRBs first so the queuing works correctly. We never
+ * queue based on context structs.
+ */
+ if (num_context_entries + 1 <
+ length / sizeof(struct MCC_WRB_AMAP) - 1) {
+
+ u32 max_length =
+ (num_context_entries + 2) * sizeof(struct MCC_WRB_AMAP);
+
+ if (is_power_of_2(max_length))
+ length = __roundup_pow_of_two(max_length+1) / 2;
+ else
+ length = __roundup_pow_of_two(max_length) / 2;
+
+ ASSERT(length <= max_length);
+
+ TRACE(DL_WARN,
+ "MCC ring length reduced based on context entries."
+ " length:%d wrbs:%d context_entries:%d", length,
+ (int) (length / sizeof(struct MCC_WRB_AMAP)),
+ num_context_entries);
+ }
+
+ spin_lock_irqsave(&pfob->post_lock, irql);
+
+ num_entries_encoded =
+ be_ring_length_to_encoding(length, sizeof(struct MCC_WRB_AMAP));
+
+ /* Init MCC object. */
+ memset(mcc, 0, sizeof(*mcc));
+ mcc->parent_function = pfob;
+ mcc->cq_object = cq;
+
+ INIT_LIST_HEAD(&mcc->backlog);
+
+ wrb = be_function_peek_mcc_wrb(pfob);
+ if (!wrb) {
+ ASSERT(wrb);
+ TRACE(DL_ERR, "No free MCC WRBs in create EQ.");
+ status = BE_STATUS_NO_MCC_WRB;
+ goto error;
+ }
+ /* Prepares an embedded fwcmd, including request/response sizes. */
+ fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MCC_CREATE);
+
+ fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE);
+ /*
+ * Program MCC ring context
+ */
+ AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, pdid,
+ &fwcmd->params.request.context, 0);
+ AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, invalid,
+ &fwcmd->params.request.context, false);
+ AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, ring_size,
+ &fwcmd->params.request.context, num_entries_encoded);
+
+ n = cq->cq_id;
+ AMAP_SET_BITS_PTR(MCC_RING_CONTEXT,
+ cq_id, &fwcmd->params.request.context, n);
+ be_rd_to_pa_list(rd, fwcmd->params.request.pages,
+ ARRAY_SIZE(fwcmd->params.request.pages));
+ /* Post the f/w command */
+ status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL,
+ NULL, NULL, fwcmd, NULL);
+ if (status != BE_SUCCESS) {
+ TRACE(DL_ERR, "MCC to create CQ failed.");
+ goto error;
+ }
+ /*
+ * Create a linked list of context structures
+ */
+ mcc->wrb_context.base = context_array;
+ mcc->wrb_context.num = num_context_entries;
+ INIT_LIST_HEAD(&mcc->wrb_context.list_head);
+ memset(context_array, 0,
+ sizeof(struct be_mcc_wrb_context) * num_context_entries);
+ for (i = 0; i < mcc->wrb_context.num; i++) {
+ list_add_tail(&context_array[i].next,
+ &mcc->wrb_context.list_head);
+ }
+
+ /*
+ *
+ * Create an mcc_ring for tracking WRB hw ring
+ */
+ va = rd->va;
+ ASSERT(va);
+ mp_ring_create(&mcc->sq.ring, length / sizeof(struct MCC_WRB_AMAP),
+ sizeof(struct MCC_WRB_AMAP), va);
+ mcc->sq.ring.id = fwcmd->params.response.id;
+ /*
+ * Init a mcc_ring for tracking the MCC CQ.
+ */
+ ASSERT(cq->va);
+ mp_ring_create(&mcc->cq.ring, cq->num_entries,
+ sizeof(struct MCC_CQ_ENTRY_AMAP), cq->va);
+ mcc->cq.ring.id = cq->cq_id;
+
+ /* Force zeroing of CQ. */
+ memset(cq->va, 0, cq->num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP));
+
+ /* Initialize debug index. */
+ mcc->consumed_index = 0;
+
+ atomic_inc(&cq->ref_count);
+ pfob->mcc = mcc;
+
+ TRACE(DL_INFO, "MCC ring created. id:%d bytes:%d cq_id:%d cq_entries:%d"
+ " num_context:%d", mcc->sq.ring.id, length,
+ cq->cq_id, cq->num_entries, num_context_entries);
+
+error:
+ spin_unlock_irqrestore(&pfob->post_lock, irql);
+ if (pfob->pend_queue_driving && pfob->mcc) {
+ pfob->pend_queue_driving = 0;
+ be_drive_mcc_wrb_queue(pfob->mcc);
+ }
+ return status;
+}
+
+/*
+ This routine destroys an MCC send queue
+
+ MccObject - Internal Mcc Object to be destroyed.
+
+ Returns BE_SUCCESS if successfull, otherwise an error code is returned.
+
+ IRQL < DISPATCH_LEVEL
+
+ The caller of this routine must ensure that no other WRB may be posted
+ until this routine returns.
+
+*/
+int be_mcc_ring_destroy(struct be_mcc_object *mcc)
+{
+ int status = 0;
+ struct be_function_object *pfob = mcc->parent_function;
+
+
+ ASSERT(mcc->processing == 0);
+
+ /*
+ * Remove the ring from the function object.
+ * This transitions back to mailbox mode.
+ */
+ pfob->mcc = NULL;
+
+ /* Send fwcmd to destroy the queue. (Using the mailbox.) */
+ status = be_function_ring_destroy(mcc->parent_function, mcc->sq.ring.id,
+ FWCMD_RING_TYPE_MCC, NULL, NULL, NULL, NULL);
+ ASSERT(status == 0);
+
+ /* Release the SQ reference to the CQ */
+ atomic_dec(&mcc->cq_object->ref_count);
+
+ return status;
+}
+
+static void
+mcc_wrb_sync_cb(void *context, int staus, struct MCC_WRB_AMAP *wrb)
+{
+ struct be_mcc_wrb_context *wrb_context =
+ (struct be_mcc_wrb_context *) context;
+ ASSERT(wrb_context);
+ *wrb_context->users_final_status = staus;
+}
+
+/*
+ This routine posts a command to the MCC send queue
+
+ mcc - Internal Mcc Object to be destroyed.
+
+ wrb - wrb to post.
+
+ Returns BE_SUCCESS if successfull, otherwise an error code is returned.
+
+ IRQL < DISPATCH_LEVEL if CompletionCallback is not NULL
+ IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL
+
+ If this routine is called with CompletionCallback != NULL the
+ call is considered to be asynchronous and will return as soon
+ as the WRB is posted to the MCC with BE_PENDING.
+
+ If CompletionCallback is NULL, then this routine will not return until
+ a completion for this MCC command has been processed.
+ If called at DISPATCH_LEVEL the CompletionCallback must be NULL.
+
+ This routine should only be called if the MPU has been boostraped past
+ mailbox mode.
+
+
+*/
+int
+_be_mpu_post_wrb_ring(struct be_mcc_object *mcc, struct MCC_WRB_AMAP *wrb,
+ struct be_mcc_wrb_context *wrb_context)
+{
+
+ struct MCC_WRB_AMAP *ring_wrb = NULL;
+ int status = BE_PENDING;
+ int final_status = BE_PENDING;
+ mcc_wrb_cqe_callback cb = NULL;
+ struct MCC_DB_AMAP mcc_db;
+ u32 embedded;
+
+ ASSERT(mp_ring_num_empty(&mcc->sq.ring) > 0);
+ /*
+ * Input wrb is most likely the next wrb in the ring, since the client
+ * can peek at the address.
+ */
+ ring_wrb = mp_ring_producer_ptr(&mcc->sq.ring);
+ if (wrb != ring_wrb) {
+ /* If not equal, copy it into the ring. */
+ memcpy(ring_wrb, wrb, sizeof(struct MCC_WRB_AMAP));
+ }
+#ifdef BE_DEBUG
+ wrb_context->ring_wrb = ring_wrb;
+#endif
+ embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, ring_wrb);
+ if (embedded) {
+ /* embedded commands will have the response within the WRB. */
+ wrb_context->wrb = ring_wrb;
+ } else {
+ /*
+ * non-embedded commands will not have the response
+ * within the WRB, and they may complete out-of-order.
+ * The WRB will not be valid to inspect
+ * during the completion.
+ */
+ wrb_context->wrb = NULL;
+ }
+ cb = wrb_context->cb;
+
+ if (cb == NULL) {
+ /* Assign our internal callback if this is a
+ * synchronous call. */
+ wrb_context->cb = mcc_wrb_sync_cb;
+ wrb_context->cb_context = wrb_context;
+ wrb_context->users_final_status = &final_status;
+ }
+ /* Increment producer index */
+
+ mcc_db.dw[0] = 0; /* initialize */
+ AMAP_SET_BITS_PTR(MCC_DB, rid, &mcc_db, mcc->sq.ring.id);
+ AMAP_SET_BITS_PTR(MCC_DB, numPosted, &mcc_db, 1);
+
+ mp_ring_produce(&mcc->sq.ring);
+ PD_WRITE(mcc->parent_function, mpu_mcc_db, mcc_db.dw[0]);
+ TRACE(DL_INFO, "pidx: %x and cidx: %x.", mcc->sq.ring.pidx,
+ mcc->sq.ring.cidx);
+
+ if (cb == NULL) {
+ int polls = 0; /* At >= 1 us per poll */
+ /* Wait until this command completes, polling the CQ. */
+ do {
+ TRACE(DL_INFO, "FWCMD submitted in the poll mode.");
+ /* Do not rearm CQ in this context. */
+ be_mcc_process_cq(mcc, false);
+
+ if (final_status == BE_PENDING) {
+ if ((++polls & 0x7FFFF) == 0) {
+ TRACE(DL_WARN,
+ "Warning : polling MCC CQ for %d"
+ "ms.", polls / 1000);
+ }
+
+ udelay(1);
+ }
+
+ /* final_status changed when the command completes */
+ } while (final_status == BE_PENDING);
+
+ status = final_status;
+ }
+
+ return status;
+}
+
+struct MCC_WRB_AMAP *
+_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue)
+{
+ /* If we have queued items, do not allow a post to bypass the queue. */
+ if (!driving_queue && !list_empty(&mcc->backlog))
+ return NULL;
+
+ if (mp_ring_num_empty(&mcc->sq.ring) <= 0)
+ return NULL;
+ return (struct MCC_WRB_AMAP *) mp_ring_producer_ptr(&mcc->sq.ring);
+}
+
+int
+be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *mailbox)
+{
+ ASSERT(mailbox);
+ pfob->mailbox.va = mailbox->va;
+ pfob->mailbox.pa = cpu_to_le64(mailbox->pa);
+ pfob->mailbox.length = mailbox->length;
+
+ ASSERT(((u32)(size_t)pfob->mailbox.va & 0xf) == 0);
+ ASSERT(((u32)(size_t)pfob->mailbox.pa & 0xf) == 0);
+ /*
+ * Issue the WRB to set MPU endianness
+ */
+ {
+ u64 *endian_check = (u64 *) (pfob->mailbox.va +
+ offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8);
+ *endian_check = 0xFF1234FFFF5678FFULL;
+ }
+
+ be_mcc_mailbox_notify_and_wait(pfob);
+
+ return BE_SUCCESS;
+}
+
+
+/*
+ This routine posts a command to the MCC mailbox.
+
+ FuncObj - Function Object to post the WRB on behalf of.
+ wrb - wrb to post.
+ CompletionCallback - Address of a callback routine to invoke once the WRB
+ is completed.
+ CompletionCallbackContext - Opaque context to be passed during the call to
+ the CompletionCallback.
+ Returns BE_SUCCESS if successfull, otherwise an error code is returned.
+
+ IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL
+
+ This routine will block until a completion for this MCC command has been
+ processed. If called at DISPATCH_LEVEL the CompletionCallback must be NULL.
+
+ This routine should only be called if the MPU has not been boostraped past
+ mailbox mode.
+*/
+int
+_be_mpu_post_wrb_mailbox(struct be_function_object *pfob,
+ struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context)
+{
+ struct MCC_MAILBOX_AMAP *mailbox = NULL;
+ struct MCC_WRB_AMAP *mb_wrb;
+ struct MCC_CQ_ENTRY_AMAP *mb_cq;
+ u32 offset, status;
+
+ ASSERT(pfob->mcc == NULL);
+ mailbox = pfob->mailbox.va;
+ ASSERT(mailbox);
+
+ offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8;
+ mb_wrb = (struct MCC_WRB_AMAP *) (u8 *)mailbox + offset;
+ if (mb_wrb != wrb) {
+ memset(mailbox, 0, sizeof(*mailbox));
+ memcpy(mb_wrb, wrb, sizeof(struct MCC_WRB_AMAP));
+ }
+ /* The callback can inspect the final WRB to get output parameters. */
+ wrb_context->wrb = mb_wrb;
+
+ be_mcc_mailbox_notify_and_wait(pfob);
+
+ /* A command completed. Use tag to determine which command. */
+ offset = offsetof(struct BE_MCC_MAILBOX_AMAP, cq)/8;
+ mb_cq = (struct MCC_CQ_ENTRY_AMAP *) ((u8 *)mailbox + offset);
+ be_mcc_process_cqe(pfob, mb_cq);
+
+ status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, mb_cq);
+ if (status)
+ status = BE_NOT_OK;
+ return status;
+}
+
+struct be_mcc_wrb_context *
+_be_mcc_allocate_wrb_context(struct be_function_object *pfob)
+{
+ struct be_mcc_wrb_context *context = NULL;
+ unsigned long irq;
+
+ spin_lock_irqsave(&pfob->mcc_context_lock, irq);
+
+ if (!pfob->mailbox.default_context_allocated) {
+ /* Use the single default context that we
+ * always have allocated. */
+ pfob->mailbox.default_context_allocated = true;
+ context = &pfob->mailbox.default_context;
+ } else if (pfob->mcc) {
+ /* Get a context from the free list. If any are available. */
+ if (!list_empty(&pfob->mcc->wrb_context.list_head)) {
+ context = list_first_entry(
+ &pfob->mcc->wrb_context.list_head,
+ struct be_mcc_wrb_context, next);
+ }
+ }
+
+ spin_unlock_irqrestore(&pfob->mcc_context_lock, irq);
+
+ return context;
+}
+
+void
+_be_mcc_free_wrb_context(struct be_function_object *pfob,
+ struct be_mcc_wrb_context *context)
+{
+ unsigned long irq;
+
+ ASSERT(context);
+ /*
+ * Zero during free to try and catch any bugs where the context
+ * is accessed after a free.
+ */
+ memset(context, 0, sizeof(context));
+
+ spin_lock_irqsave(&pfob->mcc_context_lock, irq);
+
+ if (context == &pfob->mailbox.default_context) {
+ /* Free the default context. */
+ ASSERT(pfob->mailbox.default_context_allocated);
+ pfob->mailbox.default_context_allocated = false;
+ } else {
+ /* Add to free list. */
+ ASSERT(pfob->mcc);
+ list_add_tail(&context->next,
+ &pfob->mcc->wrb_context.list_head);
+ }
+
+ spin_unlock_irqrestore(&pfob->mcc_context_lock, irq);
+}
+
+int
+be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object,
+ mcc_async_event_callback cb, void *cb_context)
+{
+ /* Lock against anyone trying to change the callback/context pointers
+ * while being used. */
+ spin_lock_irqsave(&mcc_object->parent_function->cq_lock,
+ mcc_object->parent_function->cq_irq);
+
+ /* Assign the async callback. */
+ mcc_object->async_context = cb_context;
+ mcc_object->async_cb = cb;
+
+ spin_unlock_irqrestore(&mcc_object->parent_function->cq_lock,
+ mcc_object->parent_function->cq_irq);
+
+ return BE_SUCCESS;
+}
+
+#define MPU_EP_CONTROL 0
+#define MPU_EP_SEMAPHORE 0xac
+
+/*
+ *-------------------------------------------------------------------
+ * Function: be_wait_for_POST_complete
+ * Waits until the BladeEngine POST completes (either in error or success).
+ * pfob -
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *-------------------------------------------------------------------
+ */
+static int be_wait_for_POST_complete(struct be_function_object *pfob)
+{
+ struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status;
+ int s;
+ u32 post_error, post_stage;
+
+ const u32 us_per_loop = 1000; /* 1000us */
+ const u32 print_frequency_loops = 1000000 / us_per_loop;
+ const u32 max_loops = 60 * print_frequency_loops;
+ u32 loops = 0;
+
+ /*
+ * Wait for arm fw indicating it is done or a fatal error happened.
+ * Note: POST can take some time to complete depending on configuration
+ * settings (consider ARM attempts to acquire an IP address
+ * over DHCP!!!).
+ *
+ */
+ do {
+ status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE);
+ post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
+ error, &status);
+ post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
+ stage, &status);
+ if (0 == (loops % print_frequency_loops)) {
+ /* Print current status */
+ TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)",
+ status.dw[0], post_stage);
+ }
+ udelay(us_per_loop);
+ } while ((post_error != 1) &&
+ (post_stage != POST_STAGE_ARMFW_READY) &&
+ (++loops < max_loops));
+
+ if (post_error == 1) {
+ TRACE(DL_ERR, "POST error! Status = 0x%x (stage = 0x%x)",
+ status.dw[0], post_stage);
+ s = BE_NOT_OK;
+ } else if (post_stage != POST_STAGE_ARMFW_READY) {
+ TRACE(DL_ERR, "POST time-out! Status = 0x%x (stage = 0x%x)",
+ status.dw[0], post_stage);
+ s = BE_NOT_OK;
+ } else {
+ s = BE_SUCCESS;
+ }
+ return s;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * Function: be_kickoff_and_wait_for_POST
+ * Interacts with the BladeEngine management processor to initiate POST, and
+ * subsequently waits until POST completes (either in error or success).
+ * The caller must acquire the reset semaphore before initiating POST
+ * to prevent multiple drivers interacting with the management processor.
+ * Once POST is complete the caller must release the reset semaphore.
+ * Callers who only want to wait for POST complete may call
+ * be_wait_for_POST_complete.
+ * pfob -
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *-------------------------------------------------------------------
+ */
+static int
+be_kickoff_and_wait_for_POST(struct be_function_object *pfob)
+{
+ struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status;
+ int s;
+
+ const u32 us_per_loop = 1000; /* 1000us */
+ const u32 print_frequency_loops = 1000000 / us_per_loop;
+ const u32 max_loops = 5 * print_frequency_loops;
+ u32 loops = 0;
+ u32 post_error, post_stage;
+
+ /* Wait for arm fw awaiting host ready or a fatal error happened. */
+ TRACE(DL_INFO, "Wait for BladeEngine ready to POST");
+ do {
+ status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE);
+ post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
+ error, &status);
+ post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT,
+ stage, &status);
+ if (0 == (loops % print_frequency_loops)) {
+ /* Print current status */
+ TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)",
+ status.dw[0], post_stage);
+ }
+ udelay(us_per_loop);
+ } while ((post_error != 1) &&
+ (post_stage < POST_STAGE_AWAITING_HOST_RDY) &&
+ (++loops < max_loops));
+
+ if (post_error == 1) {
+ TRACE(DL_ERR, "Pre-POST error! Status = 0x%x (stage = 0x%x)",
+ status.dw[0], post_stage);
+ s = BE_NOT_OK;
+ } else if (post_stage == POST_STAGE_AWAITING_HOST_RDY) {
+ iowrite32(POST_STAGE_HOST_RDY, pfob->csr_va + MPU_EP_SEMAPHORE);
+
+ /* Wait for POST to complete */
+ s = be_wait_for_POST_complete(pfob);
+ } else {
+ /*
+ * Either a timeout waiting for host ready signal or POST has
+ * moved ahead without requiring a host ready signal.
+ * Might as well give POST a chance to complete
+ * (or timeout again).
+ */
+ s = be_wait_for_POST_complete(pfob);
+ }
+ return s;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * Function: be_pci_soft_reset
+ * This function is called to issue a BladeEngine soft reset.
+ * Callers should acquire the soft reset semaphore before calling this
+ * function. Additionaly, callers should ensure they cannot be pre-empted
+ * while the routine executes. Upon completion of this routine, callers
+ * should release the reset semaphore. This routine implicitly waits
+ * for BladeEngine POST to complete.
+ * pfob -
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *-------------------------------------------------------------------
+ */
+int be_pci_soft_reset(struct be_function_object *pfob)
+{
+ struct PCICFG_SOFT_RESET_CSR_AMAP soft_reset;
+ struct PCICFG_ONLINE0_CSR_AMAP pciOnline0;
+ struct PCICFG_ONLINE1_CSR_AMAP pciOnline1;
+ struct EP_CONTROL_CSR_AMAP epControlCsr;
+ int status = BE_SUCCESS;
+ u32 i, soft_reset_bit;
+
+ TRACE(DL_NOTE, "PCI reset...");
+
+ /* Issue soft reset #1 to get BladeEngine into a known state. */
+ soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset);
+ AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1);
+ PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]);
+ /*
+ * wait til soft reset is deasserted - hardware
+ * deasserts after some time.
+ */
+ i = 0;
+ do {
+ udelay(50);
+ soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset);
+ soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR,
+ softreset, soft_reset.dw);
+ } while (soft_reset_bit && (i++ < 1024));
+ if (soft_reset_bit != 0) {
+ TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected.");
+ status = BE_NOT_OK;
+ goto Error_label;
+ }
+ /* Mask everything */
+ PCICFG0_WRITE(pfob, ue_status_low_mask, 0xFFFFFFFF);
+ PCICFG0_WRITE(pfob, ue_status_hi_mask, 0xFFFFFFFF);
+ /*
+ * Set everything offline except MPU IRAM (it is offline with
+ * the soft-reset, but soft-reset does not reset the PCICFG registers!)
+ */
+ pciOnline0.dw[0] = 0;
+ pciOnline1.dw[0] = 0;
+ AMAP_SET_BITS_PTR(PCICFG_ONLINE1_CSR, mpu_iram_online,
+ pciOnline1.dw, 1);
+ PCICFG0_WRITE(pfob, online0, pciOnline0.dw[0]);
+ PCICFG0_WRITE(pfob, online1, pciOnline1.dw[0]);
+
+ udelay(20000);
+
+ /* Issue soft reset #2. */
+ AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1);
+ PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]);
+ /*
+ * wait til soft reset is deasserted - hardware
+ * deasserts after some time.
+ */
+ i = 0;
+ do {
+ udelay(50);
+ soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset);
+ soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR,
+ softreset, soft_reset.dw);
+ } while (soft_reset_bit && (i++ < 1024));
+ if (soft_reset_bit != 0) {
+ TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected.");
+ status = BE_NOT_OK;
+ goto Error_label;
+ }
+
+
+ udelay(20000);
+
+ /* Take MPU out of reset. */
+
+ epControlCsr.dw[0] = ioread32(pfob->csr_va + MPU_EP_CONTROL);
+ AMAP_SET_BITS_PTR(EP_CONTROL_CSR, CPU_reset, &epControlCsr, 0);
+ iowrite32((u32)epControlCsr.dw[0], pfob->csr_va + MPU_EP_CONTROL);
+
+ /* Kickoff BE POST and wait for completion */
+ status = be_kickoff_and_wait_for_POST(pfob);
+
+Error_label:
+ return status;
+}
+
+
+/*
+ *-------------------------------------------------------------------
+ * Function: be_pci_reset_required
+ * This private function is called to detect if a host entity is
+ * required to issue a PCI soft reset and subsequently drive
+ * BladeEngine POST. Scenarios where this is required:
+ * 1) BIOS-less configuration
+ * 2) Hot-swap/plug/power-on
+ * pfob -
+ * return true if a reset is required, false otherwise
+ *-------------------------------------------------------------------
+ */
+static bool be_pci_reset_required(struct be_function_object *pfob)
+{
+ struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status;
+ bool do_reset = false;
+ u32 post_error, post_stage;
+
+ /*
+ * Read the POST status register
+ */
+ status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE);
+ post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, error,
+ &status);
+ post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, stage,
+ &status);
+ if (post_stage <= POST_STAGE_AWAITING_HOST_RDY) {
+ /*
+ * If BladeEngine is waiting for host ready indication,
+ * we want to do a PCI reset.
+ */
+ do_reset = true;
+ }
+
+ return do_reset;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * Function: be_drive_POST
+ * This function is called to drive BladeEngine POST. The
+ * caller should ensure they cannot be pre-empted while this routine executes.
+ * pfob -
+ * return status - BE_SUCCESS (0) on success. Negative error code on failure.
+ *-------------------------------------------------------------------
+ */
+int be_drive_POST(struct be_function_object *pfob)
+{
+ int status;
+
+ if (false != be_pci_reset_required(pfob)) {
+ /* PCI reset is needed (implicitly starts and waits for POST) */
+ status = be_pci_soft_reset(pfob);
+ } else {
+ /* No PCI reset is needed, start POST */
+ status = be_kickoff_and_wait_for_POST(pfob);
+ }
+
+ return status;
+}
diff --git a/drivers/staging/benet/mpu.h b/drivers/staging/benet/mpu.h
new file mode 100644
index 000000000000..41f3f87516e5
--- /dev/null
+++ b/drivers/staging/benet/mpu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __mpu_amap_h__
+#define __mpu_amap_h__
+#include "ep.h"
+
+/* Provide control parameters for the Managment Processor Unit. */
+struct BE_MPU_CSRMAP_AMAP {
+ struct BE_EP_CSRMAP_AMAP ep;
+ u8 rsvd0[128]; /* DWORD 64 */
+ u8 rsvd1[32]; /* DWORD 68 */
+ u8 rsvd2[192]; /* DWORD 69 */
+ u8 rsvd3[192]; /* DWORD 75 */
+ u8 rsvd4[32]; /* DWORD 81 */
+ u8 rsvd5[32]; /* DWORD 82 */
+ u8 rsvd6[32]; /* DWORD 83 */
+ u8 rsvd7[32]; /* DWORD 84 */
+ u8 rsvd8[32]; /* DWORD 85 */
+ u8 rsvd9[32]; /* DWORD 86 */
+ u8 rsvd10[32]; /* DWORD 87 */
+ u8 rsvd11[32]; /* DWORD 88 */
+ u8 rsvd12[32]; /* DWORD 89 */
+ u8 rsvd13[32]; /* DWORD 90 */
+ u8 rsvd14[32]; /* DWORD 91 */
+ u8 rsvd15[32]; /* DWORD 92 */
+ u8 rsvd16[32]; /* DWORD 93 */
+ u8 rsvd17[32]; /* DWORD 94 */
+ u8 rsvd18[32]; /* DWORD 95 */
+ u8 rsvd19[32]; /* DWORD 96 */
+ u8 rsvd20[32]; /* DWORD 97 */
+ u8 rsvd21[32]; /* DWORD 98 */
+ u8 rsvd22[32]; /* DWORD 99 */
+ u8 rsvd23[32]; /* DWORD 100 */
+ u8 rsvd24[32]; /* DWORD 101 */
+ u8 rsvd25[32]; /* DWORD 102 */
+ u8 rsvd26[32]; /* DWORD 103 */
+ u8 rsvd27[32]; /* DWORD 104 */
+ u8 rsvd28[96]; /* DWORD 105 */
+ u8 rsvd29[32]; /* DWORD 108 */
+ u8 rsvd30[32]; /* DWORD 109 */
+ u8 rsvd31[32]; /* DWORD 110 */
+ u8 rsvd32[32]; /* DWORD 111 */
+ u8 rsvd33[32]; /* DWORD 112 */
+ u8 rsvd34[96]; /* DWORD 113 */
+ u8 rsvd35[32]; /* DWORD 116 */
+ u8 rsvd36[32]; /* DWORD 117 */
+ u8 rsvd37[32]; /* DWORD 118 */
+ u8 rsvd38[32]; /* DWORD 119 */
+ u8 rsvd39[32]; /* DWORD 120 */
+ u8 rsvd40[32]; /* DWORD 121 */
+ u8 rsvd41[134][32]; /* DWORD 122 */
+} __packed;
+struct MPU_CSRMAP_AMAP {
+ u32 dw[256];
+};
+
+#endif /* __mpu_amap_h__ */
diff --git a/drivers/staging/benet/mpu_context.h b/drivers/staging/benet/mpu_context.h
new file mode 100644
index 000000000000..8ce90f9c46c2
--- /dev/null
+++ b/drivers/staging/benet/mpu_context.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __mpu_context_amap_h__
+#define __mpu_context_amap_h__
+
+/*
+ * Management command and control ring context. The MPUs BTLR_CTRL1 CSR
+ * controls the writeback behavior of the producer and consumer index values.
+ */
+struct BE_MCC_RING_CONTEXT_AMAP {
+ u8 con_index[16]; /* DWORD 0 */
+ u8 ring_size[4]; /* DWORD 0 */
+ u8 cq_id[11]; /* DWORD 0 */
+ u8 rsvd0; /* DWORD 0 */
+ u8 prod_index[16]; /* DWORD 1 */
+ u8 pdid[15]; /* DWORD 1 */
+ u8 invalid; /* DWORD 1 */
+ u8 cmd_pending_current[7]; /* DWORD 2 */
+ u8 rsvd1[25]; /* DWORD 2 */
+ u8 hpi_port_cq_id[11]; /* DWORD 3 */
+ u8 rsvd2[5]; /* DWORD 3 */
+ u8 cmd_pending_max[7]; /* DWORD 3 */
+ u8 rsvd3[9]; /* DWORD 3 */
+} __packed;
+struct MCC_RING_CONTEXT_AMAP {
+ u32 dw[4];
+};
+
+#endif /* __mpu_context_amap_h__ */
diff --git a/drivers/staging/benet/pcicfg.h b/drivers/staging/benet/pcicfg.h
new file mode 100644
index 000000000000..7c15684adf4a
--- /dev/null
+++ b/drivers/staging/benet/pcicfg.h
@@ -0,0 +1,825 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __pcicfg_amap_h__
+#define __pcicfg_amap_h__
+
+/* Vendor and Device ID Register. */
+struct BE_PCICFG_ID_CSR_AMAP {
+ u8 vendorid[16]; /* DWORD 0 */
+ u8 deviceid[16]; /* DWORD 0 */
+} __packed;
+struct PCICFG_ID_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* IO Bar Register. */
+struct BE_PCICFG_IOBAR_CSR_AMAP {
+ u8 iospace; /* DWORD 0 */
+ u8 rsvd0[7]; /* DWORD 0 */
+ u8 iobar[24]; /* DWORD 0 */
+} __packed;
+struct PCICFG_IOBAR_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Memory BAR 0 Register. */
+struct BE_PCICFG_MEMBAR0_CSR_AMAP {
+ u8 memspace; /* DWORD 0 */
+ u8 type[2]; /* DWORD 0 */
+ u8 pf; /* DWORD 0 */
+ u8 rsvd0[10]; /* DWORD 0 */
+ u8 membar0[18]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MEMBAR0_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Memory BAR 1 - Low Address Register. */
+struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP {
+ u8 memspace; /* DWORD 0 */
+ u8 type[2]; /* DWORD 0 */
+ u8 pf; /* DWORD 0 */
+ u8 rsvd0[13]; /* DWORD 0 */
+ u8 membar1lo[15]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MEMBAR1_LO_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Memory BAR 1 - High Address Register. */
+struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP {
+ u8 membar1hi[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MEMBAR1_HI_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Memory BAR 2 - Low Address Register. */
+struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP {
+ u8 memspace; /* DWORD 0 */
+ u8 type[2]; /* DWORD 0 */
+ u8 pf; /* DWORD 0 */
+ u8 rsvd0[17]; /* DWORD 0 */
+ u8 membar2lo[11]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MEMBAR2_LO_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Memory BAR 2 - High Address Register. */
+struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP {
+ u8 membar2hi[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MEMBAR2_HI_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Subsystem Vendor and ID (Function 0) Register. */
+struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP {
+ u8 subsys_vendor_id[16]; /* DWORD 0 */
+ u8 subsys_id[16]; /* DWORD 0 */
+} __packed;
+struct PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Subsystem Vendor and ID (Function 1) Register. */
+struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP {
+ u8 subsys_vendor_id[16]; /* DWORD 0 */
+ u8 subsys_id[16]; /* DWORD 0 */
+} __packed;
+struct PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Semaphore Register. */
+struct BE_PCICFG_SEMAPHORE_CSR_AMAP {
+ u8 locked; /* DWORD 0 */
+ u8 rsvd0[31]; /* DWORD 0 */
+} __packed;
+struct PCICFG_SEMAPHORE_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Soft Reset Register. */
+struct BE_PCICFG_SOFT_RESET_CSR_AMAP {
+ u8 rsvd0[7]; /* DWORD 0 */
+ u8 softreset; /* DWORD 0 */
+ u8 rsvd1[16]; /* DWORD 0 */
+ u8 nec_ll_rcvdetect_i[8]; /* DWORD 0 */
+} __packed;
+struct PCICFG_SOFT_RESET_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Unrecoverable Error Status (Low) Register. Each bit corresponds to
+ * an internal Unrecoverable Error. These are set by hardware and may be
+ * cleared by writing a one to the respective bit(s) to be cleared. Any
+ * bit being set that is also unmasked will result in Unrecoverable Error
+ * interrupt notification to the host CPU and/or Server Management chip
+ * and the transitioning of BladeEngine to an Offline state.
+ */
+struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP {
+ u8 cev_ue_status; /* DWORD 0 */
+ u8 ctx_ue_status; /* DWORD 0 */
+ u8 dbuf_ue_status; /* DWORD 0 */
+ u8 erx_ue_status; /* DWORD 0 */
+ u8 host_ue_status; /* DWORD 0 */
+ u8 mpu_ue_status; /* DWORD 0 */
+ u8 ndma_ue_status; /* DWORD 0 */
+ u8 ptc_ue_status; /* DWORD 0 */
+ u8 rdma_ue_status; /* DWORD 0 */
+ u8 rxf_ue_status; /* DWORD 0 */
+ u8 rxips_ue_status; /* DWORD 0 */
+ u8 rxulp0_ue_status; /* DWORD 0 */
+ u8 rxulp1_ue_status; /* DWORD 0 */
+ u8 rxulp2_ue_status; /* DWORD 0 */
+ u8 tim_ue_status; /* DWORD 0 */
+ u8 tpost_ue_status; /* DWORD 0 */
+ u8 tpre_ue_status; /* DWORD 0 */
+ u8 txips_ue_status; /* DWORD 0 */
+ u8 txulp0_ue_status; /* DWORD 0 */
+ u8 txulp1_ue_status; /* DWORD 0 */
+ u8 uc_ue_status; /* DWORD 0 */
+ u8 wdma_ue_status; /* DWORD 0 */
+ u8 txulp2_ue_status; /* DWORD 0 */
+ u8 host1_ue_status; /* DWORD 0 */
+ u8 p0_ob_link_ue_status; /* DWORD 0 */
+ u8 p1_ob_link_ue_status; /* DWORD 0 */
+ u8 host_gpio_ue_status; /* DWORD 0 */
+ u8 mbox_netw_ue_status; /* DWORD 0 */
+ u8 mbox_stor_ue_status; /* DWORD 0 */
+ u8 axgmac0_ue_status; /* DWORD 0 */
+ u8 axgmac1_ue_status; /* DWORD 0 */
+ u8 mpu_intpend_ue_status; /* DWORD 0 */
+} __packed;
+struct PCICFG_UE_STATUS_LOW_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Unrecoverable Error Status (High) Register. Each bit corresponds to
+ * an internal Unrecoverable Error. These are set by hardware and may be
+ * cleared by writing a one to the respective bit(s) to be cleared. Any
+ * bit being set that is also unmasked will result in Unrecoverable Error
+ * interrupt notification to the host CPU and/or Server Management chip;
+ * and the transitioning of BladeEngine to an Offline state.
+ */
+struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP {
+ u8 jtag_ue_status; /* DWORD 0 */
+ u8 lpcmemhost_ue_status; /* DWORD 0 */
+ u8 mgmt_mac_ue_status; /* DWORD 0 */
+ u8 mpu_iram_ue_status; /* DWORD 0 */
+ u8 pcs0online_ue_status; /* DWORD 0 */
+ u8 pcs1online_ue_status; /* DWORD 0 */
+ u8 pctl0_ue_status; /* DWORD 0 */
+ u8 pctl1_ue_status; /* DWORD 0 */
+ u8 pmem_ue_status; /* DWORD 0 */
+ u8 rr_ue_status; /* DWORD 0 */
+ u8 rxpp_ue_status; /* DWORD 0 */
+ u8 txpb_ue_status; /* DWORD 0 */
+ u8 txp_ue_status; /* DWORD 0 */
+ u8 xaui_ue_status; /* DWORD 0 */
+ u8 arm_ue_status; /* DWORD 0 */
+ u8 ipc_ue_status; /* DWORD 0 */
+ u8 rsvd0[16]; /* DWORD 0 */
+} __packed;
+struct PCICFG_UE_STATUS_HI_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Unrecoverable Error Mask (Low) Register. Each bit, when set to one,
+ * will mask the associated Unrecoverable Error status bit from notification
+ * of Unrecoverable Error to the host CPU and/or Server Managment chip and the
+ * transitioning of all BladeEngine units to an Offline state.
+ */
+struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP {
+ u8 cev_ue_mask; /* DWORD 0 */
+ u8 ctx_ue_mask; /* DWORD 0 */
+ u8 dbuf_ue_mask; /* DWORD 0 */
+ u8 erx_ue_mask; /* DWORD 0 */
+ u8 host_ue_mask; /* DWORD 0 */
+ u8 mpu_ue_mask; /* DWORD 0 */
+ u8 ndma_ue_mask; /* DWORD 0 */
+ u8 ptc_ue_mask; /* DWORD 0 */
+ u8 rdma_ue_mask; /* DWORD 0 */
+ u8 rxf_ue_mask; /* DWORD 0 */
+ u8 rxips_ue_mask; /* DWORD 0 */
+ u8 rxulp0_ue_mask; /* DWORD 0 */
+ u8 rxulp1_ue_mask; /* DWORD 0 */
+ u8 rxulp2_ue_mask; /* DWORD 0 */
+ u8 tim_ue_mask; /* DWORD 0 */
+ u8 tpost_ue_mask; /* DWORD 0 */
+ u8 tpre_ue_mask; /* DWORD 0 */
+ u8 txips_ue_mask; /* DWORD 0 */
+ u8 txulp0_ue_mask; /* DWORD 0 */
+ u8 txulp1_ue_mask; /* DWORD 0 */
+ u8 uc_ue_mask; /* DWORD 0 */
+ u8 wdma_ue_mask; /* DWORD 0 */
+ u8 txulp2_ue_mask; /* DWORD 0 */
+ u8 host1_ue_mask; /* DWORD 0 */
+ u8 p0_ob_link_ue_mask; /* DWORD 0 */
+ u8 p1_ob_link_ue_mask; /* DWORD 0 */
+ u8 host_gpio_ue_mask; /* DWORD 0 */
+ u8 mbox_netw_ue_mask; /* DWORD 0 */
+ u8 mbox_stor_ue_mask; /* DWORD 0 */
+ u8 axgmac0_ue_mask; /* DWORD 0 */
+ u8 axgmac1_ue_mask; /* DWORD 0 */
+ u8 mpu_intpend_ue_mask; /* DWORD 0 */
+} __packed;
+struct PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Unrecoverable Error Mask (High) Register. Each bit, when set to one,
+ * will mask the associated Unrecoverable Error status bit from notification
+ * of Unrecoverable Error to the host CPU and/or Server Managment chip and the
+ * transitioning of all BladeEngine units to an Offline state.
+ */
+struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP {
+ u8 jtag_ue_mask; /* DWORD 0 */
+ u8 lpcmemhost_ue_mask; /* DWORD 0 */
+ u8 mgmt_mac_ue_mask; /* DWORD 0 */
+ u8 mpu_iram_ue_mask; /* DWORD 0 */
+ u8 pcs0online_ue_mask; /* DWORD 0 */
+ u8 pcs1online_ue_mask; /* DWORD 0 */
+ u8 pctl0_ue_mask; /* DWORD 0 */
+ u8 pctl1_ue_mask; /* DWORD 0 */
+ u8 pmem_ue_mask; /* DWORD 0 */
+ u8 rr_ue_mask; /* DWORD 0 */
+ u8 rxpp_ue_mask; /* DWORD 0 */
+ u8 txpb_ue_mask; /* DWORD 0 */
+ u8 txp_ue_mask; /* DWORD 0 */
+ u8 xaui_ue_mask; /* DWORD 0 */
+ u8 arm_ue_mask; /* DWORD 0 */
+ u8 ipc_ue_mask; /* DWORD 0 */
+ u8 rsvd0[16]; /* DWORD 0 */
+} __packed;
+struct PCICFG_UE_STATUS_HI_MASK_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Online Control Register 0. This register controls various units within
+ * BladeEngine being in an Online or Offline state.
+ */
+struct BE_PCICFG_ONLINE0_CSR_AMAP {
+ u8 cev_online; /* DWORD 0 */
+ u8 ctx_online; /* DWORD 0 */
+ u8 dbuf_online; /* DWORD 0 */
+ u8 erx_online; /* DWORD 0 */
+ u8 host_online; /* DWORD 0 */
+ u8 mpu_online; /* DWORD 0 */
+ u8 ndma_online; /* DWORD 0 */
+ u8 ptc_online; /* DWORD 0 */
+ u8 rdma_online; /* DWORD 0 */
+ u8 rxf_online; /* DWORD 0 */
+ u8 rxips_online; /* DWORD 0 */
+ u8 rxulp0_online; /* DWORD 0 */
+ u8 rxulp1_online; /* DWORD 0 */
+ u8 rxulp2_online; /* DWORD 0 */
+ u8 tim_online; /* DWORD 0 */
+ u8 tpost_online; /* DWORD 0 */
+ u8 tpre_online; /* DWORD 0 */
+ u8 txips_online; /* DWORD 0 */
+ u8 txulp0_online; /* DWORD 0 */
+ u8 txulp1_online; /* DWORD 0 */
+ u8 uc_online; /* DWORD 0 */
+ u8 wdma_online; /* DWORD 0 */
+ u8 txulp2_online; /* DWORD 0 */
+ u8 host1_online; /* DWORD 0 */
+ u8 p0_ob_link_online; /* DWORD 0 */
+ u8 p1_ob_link_online; /* DWORD 0 */
+ u8 host_gpio_online; /* DWORD 0 */
+ u8 mbox_netw_online; /* DWORD 0 */
+ u8 mbox_stor_online; /* DWORD 0 */
+ u8 axgmac0_online; /* DWORD 0 */
+ u8 axgmac1_online; /* DWORD 0 */
+ u8 mpu_intpend_online; /* DWORD 0 */
+} __packed;
+struct PCICFG_ONLINE0_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Online Control Register 1. This register controls various units within
+ * BladeEngine being in an Online or Offline state.
+ */
+struct BE_PCICFG_ONLINE1_CSR_AMAP {
+ u8 jtag_online; /* DWORD 0 */
+ u8 lpcmemhost_online; /* DWORD 0 */
+ u8 mgmt_mac_online; /* DWORD 0 */
+ u8 mpu_iram_online; /* DWORD 0 */
+ u8 pcs0online_online; /* DWORD 0 */
+ u8 pcs1online_online; /* DWORD 0 */
+ u8 pctl0_online; /* DWORD 0 */
+ u8 pctl1_online; /* DWORD 0 */
+ u8 pmem_online; /* DWORD 0 */
+ u8 rr_online; /* DWORD 0 */
+ u8 rxpp_online; /* DWORD 0 */
+ u8 txpb_online; /* DWORD 0 */
+ u8 txp_online; /* DWORD 0 */
+ u8 xaui_online; /* DWORD 0 */
+ u8 arm_online; /* DWORD 0 */
+ u8 ipc_online; /* DWORD 0 */
+ u8 rsvd0[16]; /* DWORD 0 */
+} __packed;
+struct PCICFG_ONLINE1_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Host Timer Register. */
+struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP {
+ u8 hosttimer[24]; /* DWORD 0 */
+ u8 hostintr; /* DWORD 0 */
+ u8 rsvd0[7]; /* DWORD 0 */
+} __packed;
+struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* Scratchpad Register (for software use). */
+struct BE_PCICFG_SCRATCHPAD_CSR_AMAP {
+ u8 scratchpad[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_SCRATCHPAD_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express Capabilities Register. */
+struct BE_PCICFG_PCIE_CAP_CSR_AMAP {
+ u8 capid[8]; /* DWORD 0 */
+ u8 nextcap[8]; /* DWORD 0 */
+ u8 capver[4]; /* DWORD 0 */
+ u8 devport[4]; /* DWORD 0 */
+ u8 rsvd0[6]; /* DWORD 0 */
+ u8 rsvd1[2]; /* DWORD 0 */
+} __packed;
+struct PCICFG_PCIE_CAP_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express Device Capabilities Register. */
+struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP {
+ u8 payload[3]; /* DWORD 0 */
+ u8 rsvd0[3]; /* DWORD 0 */
+ u8 lo_lat[3]; /* DWORD 0 */
+ u8 l1_lat[3]; /* DWORD 0 */
+ u8 rsvd1[3]; /* DWORD 0 */
+ u8 rsvd2[3]; /* DWORD 0 */
+ u8 pwr_value[8]; /* DWORD 0 */
+ u8 pwr_scale[2]; /* DWORD 0 */
+ u8 rsvd3[4]; /* DWORD 0 */
+} __packed;
+struct PCICFG_PCIE_DEVCAP_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express Device Control/Status Registers. */
+struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP {
+ u8 CorrErrReportEn; /* DWORD 0 */
+ u8 NonFatalErrReportEn; /* DWORD 0 */
+ u8 FatalErrReportEn; /* DWORD 0 */
+ u8 UnsuppReqReportEn; /* DWORD 0 */
+ u8 EnableRelaxOrder; /* DWORD 0 */
+ u8 Max_Payload_Size[3]; /* DWORD 0 */
+ u8 ExtendTagFieldEnable; /* DWORD 0 */
+ u8 PhantomFnEnable; /* DWORD 0 */
+ u8 AuxPwrPMEnable; /* DWORD 0 */
+ u8 EnableNoSnoop; /* DWORD 0 */
+ u8 Max_Read_Req_Size[3]; /* DWORD 0 */
+ u8 rsvd0; /* DWORD 0 */
+ u8 CorrErrDetect; /* DWORD 0 */
+ u8 NonFatalErrDetect; /* DWORD 0 */
+ u8 FatalErrDetect; /* DWORD 0 */
+ u8 UnsuppReqDetect; /* DWORD 0 */
+ u8 AuxPwrDetect; /* DWORD 0 */
+ u8 TransPending; /* DWORD 0 */
+ u8 rsvd1[10]; /* DWORD 0 */
+} __packed;
+struct PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express Link Capabilities Register. */
+struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP {
+ u8 MaxLinkSpeed[4]; /* DWORD 0 */
+ u8 MaxLinkWidth[6]; /* DWORD 0 */
+ u8 ASPMSupport[2]; /* DWORD 0 */
+ u8 L0sExitLat[3]; /* DWORD 0 */
+ u8 L1ExitLat[3]; /* DWORD 0 */
+ u8 rsvd0[6]; /* DWORD 0 */
+ u8 PortNum[8]; /* DWORD 0 */
+} __packed;
+struct PCICFG_PCIE_LINK_CAP_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express Link Status Register. */
+struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP {
+ u8 ASPMCtl[2]; /* DWORD 0 */
+ u8 rsvd0; /* DWORD 0 */
+ u8 ReadCmplBndry; /* DWORD 0 */
+ u8 LinkDisable; /* DWORD 0 */
+ u8 RetrainLink; /* DWORD 0 */
+ u8 CommonClkConfig; /* DWORD 0 */
+ u8 ExtendSync; /* DWORD 0 */
+ u8 rsvd1[8]; /* DWORD 0 */
+ u8 LinkSpeed[4]; /* DWORD 0 */
+ u8 NegLinkWidth[6]; /* DWORD 0 */
+ u8 LinkTrainErr; /* DWORD 0 */
+ u8 LinkTrain; /* DWORD 0 */
+ u8 SlotClkConfig; /* DWORD 0 */
+ u8 rsvd2[3]; /* DWORD 0 */
+} __packed;
+struct PCICFG_PCIE_LINK_STATUS_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express MSI Configuration Register. */
+struct BE_PCICFG_MSI_CSR_AMAP {
+ u8 capid[8]; /* DWORD 0 */
+ u8 nextptr[8]; /* DWORD 0 */
+ u8 tablesize[11]; /* DWORD 0 */
+ u8 rsvd0[3]; /* DWORD 0 */
+ u8 funcmask; /* DWORD 0 */
+ u8 en; /* DWORD 0 */
+} __packed;
+struct PCICFG_MSI_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* MSI-X Table Offset Register. */
+struct BE_PCICFG_MSIX_TABLE_CSR_AMAP {
+ u8 tablebir[3]; /* DWORD 0 */
+ u8 offset[29]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MSIX_TABLE_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* MSI-X PBA Offset Register. */
+struct BE_PCICFG_MSIX_PBA_CSR_AMAP {
+ u8 pbabir[3]; /* DWORD 0 */
+ u8 offset[29]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MSIX_PBA_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express MSI-X Message Vector Control Register. */
+struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP {
+ u8 vector_control; /* DWORD 0 */
+ u8 rsvd0[31]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express MSI-X Message Data Register. */
+struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP {
+ u8 data[16]; /* DWORD 0 */
+ u8 rsvd0[16]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MSIX_MSG_DATA_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express MSI-X Message Address Register - High Part. */
+struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP {
+ u8 addr[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP {
+ u32 dw[1];
+};
+
+/* PCI Express MSI-X Message Address Register - Low Part. */
+struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP {
+ u8 rsvd0[2]; /* DWORD 0 */
+ u8 addr[30]; /* DWORD 0 */
+} __packed;
+struct PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP {
+ u32 dw[1];
+};
+
+struct BE_PCICFG_ANON_18_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_ANON_18_RSVD_AMAP {
+ u32 dw[1];
+};
+
+struct BE_PCICFG_ANON_19_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_ANON_19_RSVD_AMAP {
+ u32 dw[1];
+};
+
+struct BE_PCICFG_ANON_20_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[25][32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_20_RSVD_AMAP {
+ u32 dw[26];
+};
+
+struct BE_PCICFG_ANON_21_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[1919][32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_21_RSVD_AMAP {
+ u32 dw[1920];
+};
+
+struct BE_PCICFG_ANON_22_MESSAGE_AMAP {
+ struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl;
+ struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data;
+ struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi;
+ struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low;
+} __packed;
+struct PCICFG_ANON_22_MESSAGE_AMAP {
+ u32 dw[4];
+};
+
+struct BE_PCICFG_ANON_23_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[895][32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_23_RSVD_AMAP {
+ u32 dw[896];
+};
+
+/* These PCI Configuration Space registers are for the Storage Function of
+ * BladeEngine (Function 0). In the memory map of the registers below their
+ * table,
+ */
+struct BE_PCICFG0_CSRMAP_AMAP {
+ struct BE_PCICFG_ID_CSR_AMAP id;
+ u8 rsvd0[32]; /* DWORD 1 */
+ u8 rsvd1[32]; /* DWORD 2 */
+ u8 rsvd2[32]; /* DWORD 3 */
+ struct BE_PCICFG_IOBAR_CSR_AMAP iobar;
+ struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0;
+ struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo;
+ struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi;
+ struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo;
+ struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi;
+ u8 rsvd3[32]; /* DWORD 10 */
+ struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP subsystem_id;
+ u8 rsvd4[32]; /* DWORD 12 */
+ u8 rsvd5[32]; /* DWORD 13 */
+ u8 rsvd6[32]; /* DWORD 14 */
+ u8 rsvd7[32]; /* DWORD 15 */
+ struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4];
+ struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset;
+ u8 rsvd8[32]; /* DWORD 21 */
+ struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad;
+ u8 rsvd9[32]; /* DWORD 23 */
+ u8 rsvd10[32]; /* DWORD 24 */
+ u8 rsvd11[32]; /* DWORD 25 */
+ u8 rsvd12[32]; /* DWORD 26 */
+ u8 rsvd13[32]; /* DWORD 27 */
+ u8 rsvd14[2][32]; /* DWORD 28 */
+ u8 rsvd15[32]; /* DWORD 30 */
+ u8 rsvd16[32]; /* DWORD 31 */
+ u8 rsvd17[8][32]; /* DWORD 32 */
+ struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low;
+ struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi;
+ struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask;
+ struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask;
+ struct BE_PCICFG_ONLINE0_CSR_AMAP online0;
+ struct BE_PCICFG_ONLINE1_CSR_AMAP online1;
+ u8 rsvd18[32]; /* DWORD 46 */
+ u8 rsvd19[32]; /* DWORD 47 */
+ u8 rsvd20[32]; /* DWORD 48 */
+ u8 rsvd21[32]; /* DWORD 49 */
+ struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl;
+ u8 rsvd22[32]; /* DWORD 51 */
+ struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap;
+ struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap;
+ struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status;
+ struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap;
+ struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status;
+ struct BE_PCICFG_MSI_CSR_AMAP msi;
+ struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset;
+ struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset;
+ u8 rsvd23[32]; /* DWORD 60 */
+ u8 rsvd24[32]; /* DWORD 61 */
+ u8 rsvd25[32]; /* DWORD 62 */
+ u8 rsvd26[32]; /* DWORD 63 */
+ u8 rsvd27[32]; /* DWORD 64 */
+ u8 rsvd28[32]; /* DWORD 65 */
+ u8 rsvd29[32]; /* DWORD 66 */
+ u8 rsvd30[32]; /* DWORD 67 */
+ u8 rsvd31[32]; /* DWORD 68 */
+ u8 rsvd32[32]; /* DWORD 69 */
+ u8 rsvd33[32]; /* DWORD 70 */
+ u8 rsvd34[32]; /* DWORD 71 */
+ u8 rsvd35[32]; /* DWORD 72 */
+ u8 rsvd36[32]; /* DWORD 73 */
+ u8 rsvd37[32]; /* DWORD 74 */
+ u8 rsvd38[32]; /* DWORD 75 */
+ u8 rsvd39[32]; /* DWORD 76 */
+ u8 rsvd40[32]; /* DWORD 77 */
+ u8 rsvd41[32]; /* DWORD 78 */
+ u8 rsvd42[32]; /* DWORD 79 */
+ u8 rsvd43[32]; /* DWORD 80 */
+ u8 rsvd44[32]; /* DWORD 81 */
+ u8 rsvd45[32]; /* DWORD 82 */
+ u8 rsvd46[32]; /* DWORD 83 */
+ u8 rsvd47[32]; /* DWORD 84 */
+ u8 rsvd48[32]; /* DWORD 85 */
+ u8 rsvd49[32]; /* DWORD 86 */
+ u8 rsvd50[32]; /* DWORD 87 */
+ u8 rsvd51[32]; /* DWORD 88 */
+ u8 rsvd52[32]; /* DWORD 89 */
+ u8 rsvd53[32]; /* DWORD 90 */
+ u8 rsvd54[32]; /* DWORD 91 */
+ u8 rsvd55[32]; /* DWORD 92 */
+ u8 rsvd56[832]; /* DWORD 93 */
+ u8 rsvd57[32]; /* DWORD 119 */
+ u8 rsvd58[32]; /* DWORD 120 */
+ u8 rsvd59[32]; /* DWORD 121 */
+ u8 rsvd60[32]; /* DWORD 122 */
+ u8 rsvd61[32]; /* DWORD 123 */
+ u8 rsvd62[32]; /* DWORD 124 */
+ u8 rsvd63[32]; /* DWORD 125 */
+ u8 rsvd64[32]; /* DWORD 126 */
+ u8 rsvd65[32]; /* DWORD 127 */
+ u8 rsvd66[61440]; /* DWORD 128 */
+ struct BE_PCICFG_ANON_22_MESSAGE_AMAP message[32];
+ u8 rsvd67[28672]; /* DWORD 2176 */
+ u8 rsvd68[32]; /* DWORD 3072 */
+ u8 rsvd69[1023][32]; /* DWORD 3073 */
+} __packed;
+struct PCICFG0_CSRMAP_AMAP {
+ u32 dw[4096];
+};
+
+struct BE_PCICFG_ANON_24_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_ANON_24_RSVD_AMAP {
+ u32 dw[1];
+};
+
+struct BE_PCICFG_ANON_25_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_ANON_25_RSVD_AMAP {
+ u32 dw[1];
+};
+
+struct BE_PCICFG_ANON_26_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+} __packed;
+struct PCICFG_ANON_26_RSVD_AMAP {
+ u32 dw[1];
+};
+
+struct BE_PCICFG_ANON_27_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_27_RSVD_AMAP {
+ u32 dw[2];
+};
+
+struct BE_PCICFG_ANON_28_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[3][32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_28_RSVD_AMAP {
+ u32 dw[4];
+};
+
+struct BE_PCICFG_ANON_29_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[36][32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_29_RSVD_AMAP {
+ u32 dw[37];
+};
+
+struct BE_PCICFG_ANON_30_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[1930][32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_30_RSVD_AMAP {
+ u32 dw[1931];
+};
+
+struct BE_PCICFG_ANON_31_MESSAGE_AMAP {
+ struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl;
+ struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data;
+ struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi;
+ struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low;
+} __packed;
+struct PCICFG_ANON_31_MESSAGE_AMAP {
+ u32 dw[4];
+};
+
+struct BE_PCICFG_ANON_32_RSVD_AMAP {
+ u8 rsvd0[32]; /* DWORD 0 */
+ u8 rsvd1[895][32]; /* DWORD 1 */
+} __packed;
+struct PCICFG_ANON_32_RSVD_AMAP {
+ u32 dw[896];
+};
+
+/* This PCI configuration space register map is for the Networking Function of
+ * BladeEngine (Function 1).
+ */
+struct BE_PCICFG1_CSRMAP_AMAP {
+ struct BE_PCICFG_ID_CSR_AMAP id;
+ u8 rsvd0[32]; /* DWORD 1 */
+ u8 rsvd1[32]; /* DWORD 2 */
+ u8 rsvd2[32]; /* DWORD 3 */
+ struct BE_PCICFG_IOBAR_CSR_AMAP iobar;
+ struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0;
+ struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo;
+ struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi;
+ struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo;
+ struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi;
+ u8 rsvd3[32]; /* DWORD 10 */
+ struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP subsystem_id;
+ u8 rsvd4[32]; /* DWORD 12 */
+ u8 rsvd5[32]; /* DWORD 13 */
+ u8 rsvd6[32]; /* DWORD 14 */
+ u8 rsvd7[32]; /* DWORD 15 */
+ struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4];
+ struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset;
+ u8 rsvd8[32]; /* DWORD 21 */
+ struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad;
+ u8 rsvd9[32]; /* DWORD 23 */
+ u8 rsvd10[32]; /* DWORD 24 */
+ u8 rsvd11[32]; /* DWORD 25 */
+ u8 rsvd12[32]; /* DWORD 26 */
+ u8 rsvd13[32]; /* DWORD 27 */
+ u8 rsvd14[2][32]; /* DWORD 28 */
+ u8 rsvd15[32]; /* DWORD 30 */
+ u8 rsvd16[32]; /* DWORD 31 */
+ u8 rsvd17[8][32]; /* DWORD 32 */
+ struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low;
+ struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi;
+ struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask;
+ struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask;
+ struct BE_PCICFG_ONLINE0_CSR_AMAP online0;
+ struct BE_PCICFG_ONLINE1_CSR_AMAP online1;
+ u8 rsvd18[32]; /* DWORD 46 */
+ u8 rsvd19[32]; /* DWORD 47 */
+ u8 rsvd20[32]; /* DWORD 48 */
+ u8 rsvd21[32]; /* DWORD 49 */
+ struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl;
+ u8 rsvd22[32]; /* DWORD 51 */
+ struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap;
+ struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap;
+ struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status;
+ struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap;
+ struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status;
+ struct BE_PCICFG_MSI_CSR_AMAP msi;
+ struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset;
+ struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset;
+ u8 rsvd23[64]; /* DWORD 60 */
+ u8 rsvd24[32]; /* DWORD 62 */
+ u8 rsvd25[32]; /* DWORD 63 */
+ u8 rsvd26[32]; /* DWORD 64 */
+ u8 rsvd27[32]; /* DWORD 65 */
+ u8 rsvd28[32]; /* DWORD 66 */
+ u8 rsvd29[32]; /* DWORD 67 */
+ u8 rsvd30[32]; /* DWORD 68 */
+ u8 rsvd31[32]; /* DWORD 69 */
+ u8 rsvd32[32]; /* DWORD 70 */
+ u8 rsvd33[32]; /* DWORD 71 */
+ u8 rsvd34[32]; /* DWORD 72 */
+ u8 rsvd35[32]; /* DWORD 73 */
+ u8 rsvd36[32]; /* DWORD 74 */
+ u8 rsvd37[128]; /* DWORD 75 */
+ u8 rsvd38[32]; /* DWORD 79 */
+ u8 rsvd39[1184]; /* DWORD 80 */
+ u8 rsvd40[61792]; /* DWORD 117 */
+ struct BE_PCICFG_ANON_31_MESSAGE_AMAP message[32];
+ u8 rsvd41[28672]; /* DWORD 2176 */
+ u8 rsvd42[32]; /* DWORD 3072 */
+ u8 rsvd43[1023][32]; /* DWORD 3073 */
+} __packed;
+struct PCICFG1_CSRMAP_AMAP {
+ u32 dw[4096];
+};
+
+#endif /* __pcicfg_amap_h__ */
diff --git a/drivers/staging/benet/post_codes.h b/drivers/staging/benet/post_codes.h
new file mode 100644
index 000000000000..6d1621f5f5fb
--- /dev/null
+++ b/drivers/staging/benet/post_codes.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __post_codes_amap_h__
+#define __post_codes_amap_h__
+
+/* --- MGMT_HBA_POST_STAGE_ENUM --- */
+#define POST_STAGE_POWER_ON_RESET (0) /* State after a cold or warm boot. */
+#define POST_STAGE_AWAITING_HOST_RDY (1) /* ARM boot code awaiting a
+ go-ahed from the host. */
+#define POST_STAGE_HOST_RDY (2) /* Host has given go-ahed to ARM. */
+#define POST_STAGE_BE_RESET (3) /* Host wants to reset chip, this is a chip
+ workaround */
+#define POST_STAGE_SEEPROM_CS_START (256) /* SEEPROM checksum
+ test start. */
+#define POST_STAGE_SEEPROM_CS_DONE (257) /* SEEPROM checksum test
+ done. */
+#define POST_STAGE_DDR_CONFIG_START (512) /* DDR configuration start. */
+#define POST_STAGE_DDR_CONFIG_DONE (513) /* DDR configuration done. */
+#define POST_STAGE_DDR_CALIBRATE_START (768) /* DDR calibration start. */
+#define POST_STAGE_DDR_CALIBRATE_DONE (769) /* DDR calibration done. */
+#define POST_STAGE_DDR_TEST_START (1024) /* DDR memory test start. */
+#define POST_STAGE_DDR_TEST_DONE (1025) /* DDR memory test done. */
+#define POST_STAGE_REDBOOT_INIT_START (1536) /* Redboot starts execution. */
+#define POST_STAGE_REDBOOT_INIT_DONE (1537) /* Redboot done execution. */
+#define POST_STAGE_FW_IMAGE_LOAD_START (1792) /* Firmware image load to
+ DDR start. */
+#define POST_STAGE_FW_IMAGE_LOAD_DONE (1793) /* Firmware image load
+ to DDR done. */
+#define POST_STAGE_ARMFW_START (2048) /* ARMfw runtime code
+ starts execution. */
+#define POST_STAGE_DHCP_QUERY_START (2304) /* DHCP server query start. */
+#define POST_STAGE_DHCP_QUERY_DONE (2305) /* DHCP server query done. */
+#define POST_STAGE_BOOT_TARGET_DISCOVERY_START (2560) /* Boot Target
+ Discovery Start. */
+#define POST_STAGE_BOOT_TARGET_DISCOVERY_DONE (2561) /* Boot Target
+ Discovery Done. */
+#define POST_STAGE_RC_OPTION_SET (2816) /* Remote configuration
+ option is set in SEEPROM */
+#define POST_STAGE_SWITCH_LINK (2817) /* Wait for link up on switch */
+#define POST_STAGE_SEND_ICDS_MESSAGE (2818) /* Send the ICDS message
+ to switch */
+#define POST_STAGE_PERFROM_TFTP (2819) /* Download xml using TFTP */
+#define POST_STAGE_PARSE_XML (2820) /* Parse XML file */
+#define POST_STAGE_DOWNLOAD_IMAGE (2821) /* Download IMAGE from
+ TFTP server */
+#define POST_STAGE_FLASH_IMAGE (2822) /* Flash the IMAGE */
+#define POST_STAGE_RC_DONE (2823) /* Remote configuration
+ complete */
+#define POST_STAGE_REBOOT_SYSTEM (2824) /* Upgrade IMAGE done,
+ reboot required */
+#define POST_STAGE_MAC_ADDRESS (3072) /* MAC Address Check */
+#define POST_STAGE_ARMFW_READY (49152) /* ARMfw is done with POST
+ and ready. */
+#define POST_STAGE_ARMFW_UE (61440) /* ARMfw has asserted an
+ unrecoverable error. The
+ lower 3 hex digits of the
+ stage code identify the
+ unique error code.
+ */
+
+/* This structure defines the format of the MPU semaphore
+ * register when used for POST.
+ */
+struct BE_MGMT_HBA_POST_STATUS_STRUCT_AMAP {
+ u8 stage[16]; /* DWORD 0 */
+ u8 rsvd0[10]; /* DWORD 0 */
+ u8 iscsi_driver_loaded; /* DWORD 0 */
+ u8 option_rom_installed; /* DWORD 0 */
+ u8 iscsi_ip_conflict; /* DWORD 0 */
+ u8 iscsi_no_ip; /* DWORD 0 */
+ u8 backup_fw; /* DWORD 0 */
+ u8 error; /* DWORD 0 */
+} __packed;
+struct MGMT_HBA_POST_STATUS_STRUCT_AMAP {
+ u32 dw[1];
+};
+
+/* --- MGMT_HBA_POST_DUMMY_BITS_ENUM --- */
+#define POST_BIT_ISCSI_LOADED (26)
+#define POST_BIT_OPTROM_INST (27)
+#define POST_BIT_BAD_IP_ADDR (28)
+#define POST_BIT_NO_IP_ADDR (29)
+#define POST_BIT_BACKUP_FW (30)
+#define POST_BIT_ERROR (31)
+
+/* --- MGMT_HBA_POST_DUMMY_VALUES_ENUM --- */
+#define POST_ISCSI_DRIVER_LOADED (67108864)
+#define POST_OPTROM_INSTALLED (134217728)
+#define POST_ISCSI_IP_ADDRESS_CONFLICT (268435456)
+#define POST_ISCSI_NO_IP_ADDRESS (536870912)
+#define POST_BACKUP_FW_LOADED (1073741824)
+#define POST_FATAL_ERROR (2147483648)
+
+#endif /* __post_codes_amap_h__ */
diff --git a/drivers/staging/benet/regmap.h b/drivers/staging/benet/regmap.h
new file mode 100644
index 000000000000..e816ba210e83
--- /dev/null
+++ b/drivers/staging/benet/regmap.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2005 - 2008 ServerEngines
+ * All rights reserved.
+ *
+ * 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. The full GNU General
+ * Public License is included in this distribution in the file called COPYING.
+ *
+ * Contact Information:
+ * linux-drivers@serverengines.com
+ *
+ * ServerEngines
+ * 209 N. Fair Oaks Ave
+ * Sunnyvale, CA 94085
+ */
+/*
+ * Autogenerated by srcgen version: 0127
+ */
+#ifndef __regmap_amap_h__
+#define __regmap_amap_h__
+#include "pcicfg.h"
+#include "ep.h"
+#include "cev.h"
+#include "mpu.h"
+#include "doorbells.h"
+
+/*
+ * This is the control and status register map for BladeEngine, showing
+ * the relative size and offset of each sub-module. The CSR registers
+ * are identical for the network and storage PCI functions. The
+ * CSR map is shown below, followed by details of each block,
+ * in sub-sections. The sub-sections begin with a description
+ * of CSRs that are instantiated in multiple blocks.
+ */
+struct BE_BLADE_ENGINE_CSRMAP_AMAP {
+ struct BE_MPU_CSRMAP_AMAP mpu;
+ u8 rsvd0[8192]; /* DWORD 256 */
+ u8 rsvd1[8192]; /* DWORD 512 */
+ struct BE_CEV_CSRMAP_AMAP cev;
+ u8 rsvd2[8192]; /* DWORD 1024 */
+ u8 rsvd3[8192]; /* DWORD 1280 */
+ u8 rsvd4[8192]; /* DWORD 1536 */
+ u8 rsvd5[8192]; /* DWORD 1792 */
+ u8 rsvd6[8192]; /* DWORD 2048 */
+ u8 rsvd7[8192]; /* DWORD 2304 */
+ u8 rsvd8[8192]; /* DWORD 2560 */
+ u8 rsvd9[8192]; /* DWORD 2816 */
+ u8 rsvd10[8192]; /* DWORD 3072 */
+ u8 rsvd11[8192]; /* DWORD 3328 */
+ u8 rsvd12[8192]; /* DWORD 3584 */
+ u8 rsvd13[8192]; /* DWORD 3840 */
+ u8 rsvd14[8192]; /* DWORD 4096 */
+ u8 rsvd15[8192]; /* DWORD 4352 */
+ u8 rsvd16[8192]; /* DWORD 4608 */
+ u8 rsvd17[8192]; /* DWORD 4864 */
+ u8 rsvd18[8192]; /* DWORD 5120 */
+ u8 rsvd19[8192]; /* DWORD 5376 */
+ u8 rsvd20[8192]; /* DWORD 5632 */
+ u8 rsvd21[8192]; /* DWORD 5888 */
+ u8 rsvd22[8192]; /* DWORD 6144 */
+ u8 rsvd23[17152][32]; /* DWORD 6400 */
+} __packed;
+struct BLADE_ENGINE_CSRMAP_AMAP {
+ u32 dw[23552];
+};
+
+#endif /* __regmap_amap_h__ */
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
new file mode 100644
index 000000000000..b47ca1e7e383
--- /dev/null
+++ b/drivers/staging/comedi/Kconfig
@@ -0,0 +1,28 @@
+config COMEDI
+ tristate "Data Acquision support (comedi)"
+ default N
+ depends on m
+ ---help---
+ Enable support a wide range of data acquision devices
+ for Linux.
+
+config COMEDI_RT
+ tristate "Comedi Real-time support"
+ depends on COMEDI && RT
+ default N
+ ---help---
+ Enable Real time support for the Comedi core.
+
+config COMEDI_PCI_DRIVERS
+ tristate "Comedi PCI drivers"
+ depends on COMEDI && PCI
+ default N
+ ---help---
+ Enable lots of comedi PCI drivers to be built
+
+config COMEDI_USB_DRIVERS
+ tristate "Comedi USB drivers"
+ depends on COMEDI && USB
+ default N
+ ---help---
+ Enable lots of comedi USB drivers to be built
diff --git a/drivers/staging/comedi/Makefile b/drivers/staging/comedi/Makefile
new file mode 100644
index 000000000000..afd1a19c1b87
--- /dev/null
+++ b/drivers/staging/comedi/Makefile
@@ -0,0 +1,17 @@
+obj-$(CONFIG_COMEDI) += comedi.o
+obj-$(CONFIG_COMEDI_RT) += comedi_rt.o
+
+obj-$(CONFIG_COMEDI) += kcomedilib/
+obj-$(CONFIG_COMEDI) += drivers/
+
+comedi-objs := \
+ comedi_fops.o \
+ proc.o \
+ range.o \
+ drivers.o \
+ comedi_compat32.o \
+ comedi_ksyms.o \
+
+comedi_rt-objs := \
+ rt_pend_tq.o \
+ rt.o
diff --git a/drivers/staging/comedi/TODO b/drivers/staging/comedi/TODO
new file mode 100644
index 000000000000..557812958464
--- /dev/null
+++ b/drivers/staging/comedi/TODO
@@ -0,0 +1,14 @@
+TODO:
+ - checkpatch.pl cleanups
+ - Lindent
+ - remove all wrappers
+ - remove typedefs
+ - audit userspace interface
+ - reserve major number
+ - cleanup the individual comedi drivers as well
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
+copy:
+ Ian Abbott <abbotti@mev.co.uk>
+ Frank Mori Hess <fmhess@users.sourceforge.net>
+ David Schleef <ds@schleef.org>
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h
new file mode 100644
index 000000000000..36d2e1b01e78
--- /dev/null
+++ b/drivers/staging/comedi/comedi.h
@@ -0,0 +1,916 @@
+/*
+ include/comedi.h (installed as /usr/include/comedi.h)
+ header file for comedi
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _COMEDI_H
+#define _COMEDI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COMEDI_MAJORVERSION 0
+#define COMEDI_MINORVERSION 7
+#define COMEDI_MICROVERSION 76
+#define VERSION "0.7.76"
+
+/* comedi's major device number */
+#define COMEDI_MAJOR 98
+
+/*
+ maximum number of minor devices. This can be increased, although
+ kernel structures are currently statically allocated, thus you
+ don't want this to be much more than you actually use.
+ */
+#define COMEDI_NDEVICES 16
+
+/* number of config options in the config structure */
+#define COMEDI_NDEVCONFOPTS 32
+/*length of nth chunk of firmware data*/
+#define COMEDI_DEVCONF_AUX_DATA3_LENGTH 25
+#define COMEDI_DEVCONF_AUX_DATA2_LENGTH 26
+#define COMEDI_DEVCONF_AUX_DATA1_LENGTH 27
+#define COMEDI_DEVCONF_AUX_DATA0_LENGTH 28
+#define COMEDI_DEVCONF_AUX_DATA_HI 29 /* most significant 32 bits of pointer address (if needed) */
+#define COMEDI_DEVCONF_AUX_DATA_LO 30 /* least significant 32 bits of pointer address */
+#define COMEDI_DEVCONF_AUX_DATA_LENGTH 31 /* total data length */
+
+/* max length of device and driver names */
+#define COMEDI_NAMELEN 20
+
+ typedef unsigned int lsampl_t;
+ typedef unsigned short sampl_t;
+
+/* packs and unpacks a channel/range number */
+
+#define CR_PACK(chan, rng, aref) ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan))
+#define CR_PACK_FLAGS(chan, range, aref, flags) (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK))
+
+#define CR_CHAN(a) ((a)&0xffff)
+#define CR_RANGE(a) (((a)>>16)&0xff)
+#define CR_AREF(a) (((a)>>24)&0x03)
+
+#define CR_FLAGS_MASK 0xfc000000
+#define CR_ALT_FILTER (1<<26)
+#define CR_DITHER CR_ALT_FILTER
+#define CR_DEGLITCH CR_ALT_FILTER
+#define CR_ALT_SOURCE (1<<27)
+#define CR_EDGE (1<<30)
+#define CR_INVERT (1<<31)
+
+#define AREF_GROUND 0x00 /* analog ref = analog ground */
+#define AREF_COMMON 0x01 /* analog ref = analog common */
+#define AREF_DIFF 0x02 /* analog ref = differential */
+#define AREF_OTHER 0x03 /* analog ref = other (undefined) */
+
+/* counters -- these are arbitrary values */
+#define GPCT_RESET 0x0001
+#define GPCT_SET_SOURCE 0x0002
+#define GPCT_SET_GATE 0x0004
+#define GPCT_SET_DIRECTION 0x0008
+#define GPCT_SET_OPERATION 0x0010
+#define GPCT_ARM 0x0020
+#define GPCT_DISARM 0x0040
+#define GPCT_GET_INT_CLK_FRQ 0x0080
+
+#define GPCT_INT_CLOCK 0x0001
+#define GPCT_EXT_PIN 0x0002
+#define GPCT_NO_GATE 0x0004
+#define GPCT_UP 0x0008
+#define GPCT_DOWN 0x0010
+#define GPCT_HWUD 0x0020
+#define GPCT_SIMPLE_EVENT 0x0040
+#define GPCT_SINGLE_PERIOD 0x0080
+#define GPCT_SINGLE_PW 0x0100
+#define GPCT_CONT_PULSE_OUT 0x0200
+#define GPCT_SINGLE_PULSE_OUT 0x0400
+
+/* instructions */
+
+#define INSN_MASK_WRITE 0x8000000
+#define INSN_MASK_READ 0x4000000
+#define INSN_MASK_SPECIAL 0x2000000
+
+#define INSN_READ (0 | INSN_MASK_READ)
+#define INSN_WRITE (1 | INSN_MASK_WRITE)
+#define INSN_BITS (2 | INSN_MASK_READ|INSN_MASK_WRITE)
+#define INSN_CONFIG (3 | INSN_MASK_READ|INSN_MASK_WRITE)
+#define INSN_GTOD (4 | INSN_MASK_READ|INSN_MASK_SPECIAL)
+#define INSN_WAIT (5 | INSN_MASK_WRITE|INSN_MASK_SPECIAL)
+#define INSN_INTTRIG (6 | INSN_MASK_WRITE|INSN_MASK_SPECIAL)
+
+/* trigger flags */
+/* These flags are used in comedi_trig structures */
+
+#define TRIG_BOGUS 0x0001 /* do the motions */
+#define TRIG_DITHER 0x0002 /* enable dithering */
+#define TRIG_DEGLITCH 0x0004 /* enable deglitching */
+/*#define TRIG_RT 0x0008 */ /* perform op in real time */
+#define TRIG_CONFIG 0x0010 /* perform configuration, not triggering */
+#define TRIG_WAKE_EOS 0x0020 /* wake up on end-of-scan events */
+/*#define TRIG_WRITE 0x0040*/ /* write to bidirectional devices */
+
+/* command flags */
+/* These flags are used in comedi_cmd structures */
+
+#define CMDF_PRIORITY 0x00000008 /* try to use a real-time interrupt while performing command */
+
+#define TRIG_RT CMDF_PRIORITY /* compatibility definition */
+
+#define CMDF_WRITE 0x00000040
+#define TRIG_WRITE CMDF_WRITE /* compatibility definition */
+
+#define CMDF_RAWDATA 0x00000080
+
+#define COMEDI_EV_START 0x00040000
+#define COMEDI_EV_SCAN_BEGIN 0x00080000
+#define COMEDI_EV_CONVERT 0x00100000
+#define COMEDI_EV_SCAN_END 0x00200000
+#define COMEDI_EV_STOP 0x00400000
+
+#define TRIG_ROUND_MASK 0x00030000
+#define TRIG_ROUND_NEAREST 0x00000000
+#define TRIG_ROUND_DOWN 0x00010000
+#define TRIG_ROUND_UP 0x00020000
+#define TRIG_ROUND_UP_NEXT 0x00030000
+
+/* trigger sources */
+
+#define TRIG_ANY 0xffffffff
+#define TRIG_INVALID 0x00000000
+
+#define TRIG_NONE 0x00000001 /* never trigger */
+#define TRIG_NOW 0x00000002 /* trigger now + N ns */
+#define TRIG_FOLLOW 0x00000004 /* trigger on next lower level trig */
+#define TRIG_TIME 0x00000008 /* trigger at time N ns */
+#define TRIG_TIMER 0x00000010 /* trigger at rate N ns */
+#define TRIG_COUNT 0x00000020 /* trigger when count reaches N */
+#define TRIG_EXT 0x00000040 /* trigger on external signal N */
+#define TRIG_INT 0x00000080 /* trigger on comedi-internal signal N */
+#define TRIG_OTHER 0x00000100 /* driver defined */
+
+/* subdevice flags */
+
+#define SDF_BUSY 0x0001 /* device is busy */
+#define SDF_BUSY_OWNER 0x0002 /* device is busy with your job */
+#define SDF_LOCKED 0x0004 /* subdevice is locked */
+#define SDF_LOCK_OWNER 0x0008 /* you own lock */
+#define SDF_MAXDATA 0x0010 /* maxdata depends on channel */
+#define SDF_FLAGS 0x0020 /* flags depend on channel */
+#define SDF_RANGETYPE 0x0040 /* range type depends on channel */
+#define SDF_MODE0 0x0080 /* can do mode 0 */
+#define SDF_MODE1 0x0100 /* can do mode 1 */
+#define SDF_MODE2 0x0200 /* can do mode 2 */
+#define SDF_MODE3 0x0400 /* can do mode 3 */
+#define SDF_MODE4 0x0800 /* can do mode 4 */
+#define SDF_CMD 0x1000 /* can do commands (deprecated) */
+#define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */
+#define SDF_CMD_WRITE 0x4000 /* can do output commands */
+#define SDF_CMD_READ 0x8000 /* can do input commands */
+
+#define SDF_READABLE 0x00010000 /* subdevice can be read (e.g. analog input) */
+#define SDF_WRITABLE 0x00020000 /* subdevice can be written (e.g. analog output) */
+#define SDF_WRITEABLE SDF_WRITABLE /* spelling error in API */
+#define SDF_INTERNAL 0x00040000 /* subdevice does not have externally visible lines */
+#define SDF_RT 0x00080000 /* DEPRECATED: subdevice is RT capable */
+#define SDF_GROUND 0x00100000 /* can do aref=ground */
+#define SDF_COMMON 0x00200000 /* can do aref=common */
+#define SDF_DIFF 0x00400000 /* can do aref=diff */
+#define SDF_OTHER 0x00800000 /* can do aref=other */
+#define SDF_DITHER 0x01000000 /* can do dithering */
+#define SDF_DEGLITCH 0x02000000 /* can do deglitching */
+#define SDF_MMAP 0x04000000 /* can do mmap() */
+#define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */
+#define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */
+#define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */
+/* re recyle these flags for PWM */
+#define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */
+#define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */
+
+
+
+/* subdevice types */
+
+enum comedi_subdevice_type {
+ COMEDI_SUBD_UNUSED, /* unused by driver */
+ COMEDI_SUBD_AI, /* analog input */
+ COMEDI_SUBD_AO, /* analog output */
+ COMEDI_SUBD_DI, /* digital input */
+ COMEDI_SUBD_DO, /* digital output */
+ COMEDI_SUBD_DIO, /* digital input/output */
+ COMEDI_SUBD_COUNTER, /* counter */
+ COMEDI_SUBD_TIMER, /* timer */
+ COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */
+ COMEDI_SUBD_CALIB, /* calibration DACs */
+ COMEDI_SUBD_PROC, /* processor, DSP */
+ COMEDI_SUBD_SERIAL, /* serial IO */
+ COMEDI_SUBD_PWM /* PWM */
+};
+
+/* configuration instructions */
+
+enum configuration_ids {
+ INSN_CONFIG_DIO_INPUT = 0,
+ INSN_CONFIG_DIO_OUTPUT = 1,
+ INSN_CONFIG_DIO_OPENDRAIN = 2,
+ INSN_CONFIG_ANALOG_TRIG = 16,
+/* INSN_CONFIG_WAVEFORM = 17, */
+/* INSN_CONFIG_TRIG = 18, */
+/* INSN_CONFIG_COUNTER = 19, */
+ INSN_CONFIG_ALT_SOURCE = 20,
+ INSN_CONFIG_DIGITAL_TRIG = 21,
+ INSN_CONFIG_BLOCK_SIZE = 22,
+ INSN_CONFIG_TIMER_1 = 23,
+ INSN_CONFIG_FILTER = 24,
+ INSN_CONFIG_CHANGE_NOTIFY = 25,
+
+ /*ALPHA*/ INSN_CONFIG_SERIAL_CLOCK = 26,
+ INSN_CONFIG_BIDIRECTIONAL_DATA = 27,
+ INSN_CONFIG_DIO_QUERY = 28,
+ INSN_CONFIG_PWM_OUTPUT = 29,
+ INSN_CONFIG_GET_PWM_OUTPUT = 30,
+ INSN_CONFIG_ARM = 31,
+ INSN_CONFIG_DISARM = 32,
+ INSN_CONFIG_GET_COUNTER_STATUS = 33,
+ INSN_CONFIG_RESET = 34,
+ INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, /* Use CTR as single pulsegenerator */
+ INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, /* Use CTR as pulsetraingenerator */
+ INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, /* Use the counter as encoder */
+ INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */
+ INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */
+ INSN_CONFIG_SET_CLOCK_SRC = 2003, /* Set master clock source */
+ INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */
+ INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */
+/* INSN_CONFIG_GET_OTHER_SRC = 2006,*/ /* Get other source */
+ INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE, /* Get size in bytes of
+ subdevice's on-board fifos
+ used during streaming
+ input/output */
+ INSN_CONFIG_SET_COUNTER_MODE = 4097,
+ INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */
+ INSN_CONFIG_8254_READ_STATUS = 4098,
+ INSN_CONFIG_SET_ROUTING = 4099,
+ INSN_CONFIG_GET_ROUTING = 4109,
+/* PWM */
+ INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */
+ INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */
+ INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */
+ INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, /* sets H bridge: duty cycle and sign bit for a relay at the same time*/
+ INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 /* gets H bridge data: duty cycle and the sign bit */
+};
+
+enum comedi_io_direction {
+ COMEDI_INPUT = 0,
+ COMEDI_OUTPUT = 1,
+ COMEDI_OPENDRAIN = 2
+};
+
+enum comedi_support_level {
+ COMEDI_UNKNOWN_SUPPORT = 0,
+ COMEDI_SUPPORTED,
+ COMEDI_UNSUPPORTED
+};
+
+/* ioctls */
+
+#define CIO 'd'
+#define COMEDI_DEVCONFIG _IOW(CIO, 0, comedi_devconfig)
+#define COMEDI_DEVINFO _IOR(CIO, 1, comedi_devinfo)
+#define COMEDI_SUBDINFO _IOR(CIO, 2, comedi_subdinfo)
+#define COMEDI_CHANINFO _IOR(CIO, 3, comedi_chaninfo)
+#define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig)
+#define COMEDI_LOCK _IO(CIO, 5)
+#define COMEDI_UNLOCK _IO(CIO, 6)
+#define COMEDI_CANCEL _IO(CIO, 7)
+#define COMEDI_RANGEINFO _IOR(CIO, 8, comedi_rangeinfo)
+#define COMEDI_CMD _IOR(CIO, 9, comedi_cmd)
+#define COMEDI_CMDTEST _IOR(CIO, 10, comedi_cmd)
+#define COMEDI_INSNLIST _IOR(CIO, 11, comedi_insnlist)
+#define COMEDI_INSN _IOR(CIO, 12, comedi_insn)
+#define COMEDI_BUFCONFIG _IOR(CIO, 13, comedi_bufconfig)
+#define COMEDI_BUFINFO _IOWR(CIO, 14, comedi_bufinfo)
+#define COMEDI_POLL _IO(CIO, 15)
+
+/* structures */
+
+typedef struct comedi_trig_struct comedi_trig;
+typedef struct comedi_cmd_struct comedi_cmd;
+typedef struct comedi_insn_struct comedi_insn;
+typedef struct comedi_insnlist_struct comedi_insnlist;
+typedef struct comedi_chaninfo_struct comedi_chaninfo;
+typedef struct comedi_subdinfo_struct comedi_subdinfo;
+typedef struct comedi_devinfo_struct comedi_devinfo;
+typedef struct comedi_devconfig_struct comedi_devconfig;
+typedef struct comedi_rangeinfo_struct comedi_rangeinfo;
+typedef struct comedi_krange_struct comedi_krange;
+typedef struct comedi_bufconfig_struct comedi_bufconfig;
+typedef struct comedi_bufinfo_struct comedi_bufinfo;
+
+struct comedi_trig_struct {
+ unsigned int subdev; /* subdevice */
+ unsigned int mode; /* mode */
+ unsigned int flags;
+ unsigned int n_chan; /* number of channels */
+ unsigned int *chanlist; /* channel/range list */
+ sampl_t *data; /* data list, size depends on subd flags */
+ unsigned int n; /* number of scans */
+ unsigned int trigsrc;
+ unsigned int trigvar;
+ unsigned int trigvar1;
+ unsigned int data_len;
+ unsigned int unused[3];
+};
+
+struct comedi_insn_struct {
+ unsigned int insn;
+ unsigned int n;
+ lsampl_t *data;
+ unsigned int subdev;
+ unsigned int chanspec;
+ unsigned int unused[3];
+};
+
+struct comedi_insnlist_struct {
+ unsigned int n_insns;
+ comedi_insn *insns;
+};
+
+struct comedi_cmd_struct {
+ unsigned int subdev;
+ unsigned int flags;
+
+ unsigned int start_src;
+ unsigned int start_arg;
+
+ unsigned int scan_begin_src;
+ unsigned int scan_begin_arg;
+
+ unsigned int convert_src;
+ unsigned int convert_arg;
+
+ unsigned int scan_end_src;
+ unsigned int scan_end_arg;
+
+ unsigned int stop_src;
+ unsigned int stop_arg;
+
+ unsigned int *chanlist; /* channel/range list */
+ unsigned int chanlist_len;
+
+ sampl_t *data; /* data list, size depends on subd flags */
+ unsigned int data_len;
+};
+
+struct comedi_chaninfo_struct {
+ unsigned int subdev;
+ lsampl_t *maxdata_list;
+ unsigned int *flaglist;
+ unsigned int *rangelist;
+ unsigned int unused[4];
+};
+
+struct comedi_rangeinfo_struct {
+ unsigned int range_type;
+ void *range_ptr;
+};
+
+struct comedi_krange_struct {
+ int min; /* fixed point, multiply by 1e-6 */
+ int max; /* fixed point, multiply by 1e-6 */
+ unsigned int flags;
+};
+
+
+struct comedi_subdinfo_struct {
+ unsigned int type;
+ unsigned int n_chan;
+ unsigned int subd_flags;
+ unsigned int timer_type;
+ unsigned int len_chanlist;
+ lsampl_t maxdata;
+ unsigned int flags; /* channel flags */
+ unsigned int range_type; /* lookup in kernel */
+ unsigned int settling_time_0;
+ unsigned insn_bits_support; /* see support_level enum for values*/
+ unsigned int unused[8];
+};
+
+struct comedi_devinfo_struct {
+ unsigned int version_code;
+ unsigned int n_subdevs;
+ char driver_name[COMEDI_NAMELEN];
+ char board_name[COMEDI_NAMELEN];
+ int read_subdevice;
+ int write_subdevice;
+ int unused[30];
+};
+
+struct comedi_devconfig_struct {
+ char board_name[COMEDI_NAMELEN];
+ int options[COMEDI_NDEVCONFOPTS];
+};
+
+struct comedi_bufconfig_struct {
+ unsigned int subdevice;
+ unsigned int flags;
+
+ unsigned int maximum_size;
+ unsigned int size;
+
+ unsigned int unused[4];
+};
+
+struct comedi_bufinfo_struct {
+ unsigned int subdevice;
+ unsigned int bytes_read;
+
+ unsigned int buf_write_ptr;
+ unsigned int buf_read_ptr;
+ unsigned int buf_write_count;
+ unsigned int buf_read_count;
+
+ unsigned int bytes_written;
+
+ unsigned int unused[4];
+};
+
+/* range stuff */
+
+#define __RANGE(a, b) ((((a)&0xffff)<<16)|((b)&0xffff))
+
+#define RANGE_OFFSET(a) (((a)>>16)&0xffff)
+#define RANGE_LENGTH(b) ((b)&0xffff)
+
+#define RF_UNIT(flags) ((flags)&0xff)
+#define RF_EXTERNAL (1<<8)
+
+#define UNIT_volt 0
+#define UNIT_mA 1
+#define UNIT_none 2
+
+#define COMEDI_MIN_SPEED ((unsigned int)0xffffffff)
+
+/* callback stuff */
+/* only relevant to kernel modules. */
+
+#define COMEDI_CB_EOS 1 /* end of scan */
+#define COMEDI_CB_EOA 2 /* end of acquisition */
+#define COMEDI_CB_BLOCK 4 /* DEPRECATED: convenient block size */
+#define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */
+#define COMEDI_CB_ERROR 16 /* card error during acquisition */
+#define COMEDI_CB_OVERFLOW 32 /* buffer overflow/underflow */
+
+/**********************************************************/
+/* everything after this line is ALPHA */
+/**********************************************************/
+
+/*
+ 8254 specific configuration.
+
+ It supports two config commands:
+
+ 0 ID: INSN_CONFIG_SET_COUNTER_MODE
+ 1 8254 Mode
+ I8254_MODE0, I8254_MODE1, ..., I8254_MODE5
+ OR'ed with:
+ I8254_BCD, I8254_BINARY
+
+ 0 ID: INSN_CONFIG_8254_READ_STATUS
+ 1 <-- Status byte returned here.
+ B7 = Output
+ B6 = NULL Count
+ B5 - B0 Current mode.
+
+*/
+
+enum i8254_mode {
+ I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */
+ I8254_MODE1 = (1 << 1), /* Hardware retriggerable one-shot */
+ I8254_MODE2 = (2 << 1), /* Rate generator */
+ I8254_MODE3 = (3 << 1), /* Square wave mode */
+ I8254_MODE4 = (4 << 1), /* Software triggered strobe */
+ I8254_MODE5 = (5 << 1), /* Hardware triggered strobe (retriggerable) */
+ I8254_BCD = 1, /* use binary-coded decimal instead of binary (pretty useless) */
+ I8254_BINARY = 0
+};
+
+static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel)
+{
+ if (pfi_channel < 10)
+ return 0x1 + pfi_channel;
+ else
+ return 0xb + pfi_channel;
+}
+static inline unsigned NI_USUAL_RTSI_SELECT(unsigned rtsi_channel)
+{
+ if (rtsi_channel < 7)
+ return 0xb + rtsi_channel;
+ else
+ return 0x1b;
+}
+/* mode bits for NI general-purpose counters, set with
+ * INSN_CONFIG_SET_COUNTER_MODE */
+#define NI_GPCT_COUNTING_MODE_SHIFT 16
+#define NI_GPCT_INDEX_PHASE_BITSHIFT 20
+#define NI_GPCT_COUNTING_DIRECTION_SHIFT 24
+enum ni_gpct_mode_bits {
+ NI_GPCT_GATE_ON_BOTH_EDGES_BIT = 0x4,
+ NI_GPCT_EDGE_GATE_MODE_MASK = 0x18,
+ NI_GPCT_EDGE_GATE_STARTS_STOPS_BITS = 0x0,
+ NI_GPCT_EDGE_GATE_STOPS_STARTS_BITS = 0x8,
+ NI_GPCT_EDGE_GATE_STARTS_BITS = 0x10,
+ NI_GPCT_EDGE_GATE_NO_STARTS_NO_STOPS_BITS = 0x18,
+ NI_GPCT_STOP_MODE_MASK = 0x60,
+ NI_GPCT_STOP_ON_GATE_BITS = 0x00,
+ NI_GPCT_STOP_ON_GATE_OR_TC_BITS = 0x20,
+ NI_GPCT_STOP_ON_GATE_OR_SECOND_TC_BITS = 0x40,
+ NI_GPCT_LOAD_B_SELECT_BIT = 0x80,
+ NI_GPCT_OUTPUT_MODE_MASK = 0x300,
+ NI_GPCT_OUTPUT_TC_PULSE_BITS = 0x100,
+ NI_GPCT_OUTPUT_TC_TOGGLE_BITS = 0x200,
+ NI_GPCT_OUTPUT_TC_OR_GATE_TOGGLE_BITS = 0x300,
+ NI_GPCT_HARDWARE_DISARM_MASK = 0xc00,
+ NI_GPCT_NO_HARDWARE_DISARM_BITS = 0x000,
+ NI_GPCT_DISARM_AT_TC_BITS = 0x400,
+ NI_GPCT_DISARM_AT_GATE_BITS = 0x800,
+ NI_GPCT_DISARM_AT_TC_OR_GATE_BITS = 0xc00,
+ NI_GPCT_LOADING_ON_TC_BIT = 0x1000,
+ NI_GPCT_LOADING_ON_GATE_BIT = 0x4000,
+ NI_GPCT_COUNTING_MODE_MASK = 0x7 << NI_GPCT_COUNTING_MODE_SHIFT,
+ NI_GPCT_COUNTING_MODE_NORMAL_BITS =
+ 0x0 << NI_GPCT_COUNTING_MODE_SHIFT,
+ NI_GPCT_COUNTING_MODE_QUADRATURE_X1_BITS =
+ 0x1 << NI_GPCT_COUNTING_MODE_SHIFT,
+ NI_GPCT_COUNTING_MODE_QUADRATURE_X2_BITS =
+ 0x2 << NI_GPCT_COUNTING_MODE_SHIFT,
+ NI_GPCT_COUNTING_MODE_QUADRATURE_X4_BITS =
+ 0x3 << NI_GPCT_COUNTING_MODE_SHIFT,
+ NI_GPCT_COUNTING_MODE_TWO_PULSE_BITS =
+ 0x4 << NI_GPCT_COUNTING_MODE_SHIFT,
+ NI_GPCT_COUNTING_MODE_SYNC_SOURCE_BITS =
+ 0x6 << NI_GPCT_COUNTING_MODE_SHIFT,
+ NI_GPCT_INDEX_PHASE_MASK = 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT,
+ NI_GPCT_INDEX_PHASE_LOW_A_LOW_B_BITS =
+ 0x0 << NI_GPCT_INDEX_PHASE_BITSHIFT,
+ NI_GPCT_INDEX_PHASE_LOW_A_HIGH_B_BITS =
+ 0x1 << NI_GPCT_INDEX_PHASE_BITSHIFT,
+ NI_GPCT_INDEX_PHASE_HIGH_A_LOW_B_BITS =
+ 0x2 << NI_GPCT_INDEX_PHASE_BITSHIFT,
+ NI_GPCT_INDEX_PHASE_HIGH_A_HIGH_B_BITS =
+ 0x3 << NI_GPCT_INDEX_PHASE_BITSHIFT,
+ NI_GPCT_INDEX_ENABLE_BIT = 0x400000,
+ NI_GPCT_COUNTING_DIRECTION_MASK =
+ 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT,
+ NI_GPCT_COUNTING_DIRECTION_DOWN_BITS =
+ 0x00 << NI_GPCT_COUNTING_DIRECTION_SHIFT,
+ NI_GPCT_COUNTING_DIRECTION_UP_BITS =
+ 0x1 << NI_GPCT_COUNTING_DIRECTION_SHIFT,
+ NI_GPCT_COUNTING_DIRECTION_HW_UP_DOWN_BITS =
+ 0x2 << NI_GPCT_COUNTING_DIRECTION_SHIFT,
+ NI_GPCT_COUNTING_DIRECTION_HW_GATE_BITS =
+ 0x3 << NI_GPCT_COUNTING_DIRECTION_SHIFT,
+ NI_GPCT_RELOAD_SOURCE_MASK = 0xc000000,
+ NI_GPCT_RELOAD_SOURCE_FIXED_BITS = 0x0,
+ NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS = 0x4000000,
+ NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS = 0x8000000,
+ NI_GPCT_OR_GATE_BIT = 0x10000000,
+ NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000
+};
+
+/* Bits for setting a clock source with
+ * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */
+enum ni_gpct_clock_source_bits {
+ NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f,
+ NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0,
+ NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1,
+ NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2,
+ NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3,
+ NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4,
+ NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5,
+ NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, /* NI 660x-specific */
+ NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7,
+ NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8,
+ NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9,
+ NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000,
+ NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0,
+ NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, /* divide source by 2 */
+ NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, /* divide source by 8 */
+ NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000
+};
+static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n)
+{
+ /* NI 660x-specific */
+ return 0x10 + n;
+}
+static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n)
+{
+ return 0x18 + n;
+}
+static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n)
+{
+ /* no pfi on NI 660x */
+ return 0x20 + n;
+}
+
+/* Possibilities for setting a gate source with
+INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters.
+May be bitwise-or'd with CR_EDGE or CR_INVERT. */
+enum ni_gpct_gate_select {
+ /* m-series gates */
+ NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0,
+ NI_GPCT_AI_START2_GATE_SELECT = 0x12,
+ NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT = 0x13,
+ NI_GPCT_NEXT_OUT_GATE_SELECT = 0x14,
+ NI_GPCT_AI_START1_GATE_SELECT = 0x1c,
+ NI_GPCT_NEXT_SOURCE_GATE_SELECT = 0x1d,
+ NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT = 0x1e,
+ NI_GPCT_LOGIC_LOW_GATE_SELECT = 0x1f,
+ /* more gates for 660x */
+ NI_GPCT_SOURCE_PIN_i_GATE_SELECT = 0x100,
+ NI_GPCT_GATE_PIN_i_GATE_SELECT = 0x101,
+ /* more gates for 660x "second gate" */
+ NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201,
+ NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e,
+ /* m-series "second gate" sources are unknown,
+ we should add them here with an offset of 0x300 when known. */
+ NI_GPCT_DISABLED_GATE_SELECT = 0x8000,
+};
+static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n)
+{
+ return 0x102 + n;
+}
+static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n)
+{
+ return NI_USUAL_RTSI_SELECT(n);
+}
+static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n)
+{
+ return NI_USUAL_PFI_SELECT(n);
+}
+static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n)
+{
+ return 0x202 + n;
+}
+
+/* Possibilities for setting a source with
+INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */
+enum ni_gpct_other_index {
+ NI_GPCT_SOURCE_ENCODER_A,
+ NI_GPCT_SOURCE_ENCODER_B,
+ NI_GPCT_SOURCE_ENCODER_Z
+};
+enum ni_gpct_other_select {
+ /* m-series gates */
+ /* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */
+ NI_GPCT_DISABLED_OTHER_SELECT = 0x8000,
+};
+static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n)
+{
+ return NI_USUAL_PFI_SELECT(n);
+}
+
+/* start sources for ni general-purpose counters for use with
+INSN_CONFIG_ARM */
+enum ni_gpct_arm_source {
+ NI_GPCT_ARM_IMMEDIATE = 0x0,
+ NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter and
+ the adjacent paired counter
+ simultaneously */
+ /* NI doesn't document bits for selecting hardware arm triggers. If
+ * the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least
+ * significant bits (3 bits for 660x or 5 bits for m-series) through to
+ * the hardware. This will at least allow someone to figure out what
+ * the bits do later. */
+ NI_GPCT_ARM_UNKNOWN = 0x1000,
+};
+
+/* digital filtering options for ni 660x for use with INSN_CONFIG_FILTER. */
+enum ni_gpct_filter_select {
+ NI_GPCT_FILTER_OFF = 0x0,
+ NI_GPCT_FILTER_TIMEBASE_3_SYNC = 0x1,
+ NI_GPCT_FILTER_100x_TIMEBASE_1 = 0x2,
+ NI_GPCT_FILTER_20x_TIMEBASE_1 = 0x3,
+ NI_GPCT_FILTER_10x_TIMEBASE_1 = 0x4,
+ NI_GPCT_FILTER_2x_TIMEBASE_1 = 0x5,
+ NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6
+};
+
+/* PFI digital filtering options for ni m-series for use with
+ * INSN_CONFIG_FILTER. */
+enum ni_pfi_filter_select {
+ NI_PFI_FILTER_OFF = 0x0,
+ NI_PFI_FILTER_125ns = 0x1,
+ NI_PFI_FILTER_6425ns = 0x2,
+ NI_PFI_FILTER_2550us = 0x3
+};
+
+/* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */
+enum ni_mio_clock_source {
+ NI_MIO_INTERNAL_CLOCK = 0,
+ NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use
+ NI_MIO_PLL_RTSI_CLOCK() */
+ /* the NI_MIO_PLL_* sources are m-series only */
+ NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2,
+ NI_MIO_PLL_PXI10_CLOCK = 3,
+ NI_MIO_PLL_RTSI0_CLOCK = 4
+};
+static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel)
+{
+ return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel;
+}
+
+/* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING.
+ The numbers assigned are not arbitrary, they correspond to the bits required
+ to program the board. */
+enum ni_rtsi_routing {
+ NI_RTSI_OUTPUT_ADR_START1 = 0,
+ NI_RTSI_OUTPUT_ADR_START2 = 1,
+ NI_RTSI_OUTPUT_SCLKG = 2,
+ NI_RTSI_OUTPUT_DACUPDN = 3,
+ NI_RTSI_OUTPUT_DA_START1 = 4,
+ NI_RTSI_OUTPUT_G_SRC0 = 5,
+ NI_RTSI_OUTPUT_G_GATE0 = 6,
+ NI_RTSI_OUTPUT_RGOUT0 = 7,
+ NI_RTSI_OUTPUT_RTSI_BRD_0 = 8,
+ NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI clock
+ on line 7 */
+};
+static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n)
+{
+ return NI_RTSI_OUTPUT_RTSI_BRD_0 + n;
+}
+
+/* Signals which can be routed to an NI PFI pin on an m-series board with
+ * INSN_CONFIG_SET_ROUTING. These numbers are also returned by
+ * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing
+ * cannot be changed. The numbers assigned are not arbitrary, they correspond
+ * to the bits required to program the board. */
+enum ni_pfi_routing {
+ NI_PFI_OUTPUT_PFI_DEFAULT = 0,
+ NI_PFI_OUTPUT_AI_START1 = 1,
+ NI_PFI_OUTPUT_AI_START2 = 2,
+ NI_PFI_OUTPUT_AI_CONVERT = 3,
+ NI_PFI_OUTPUT_G_SRC1 = 4,
+ NI_PFI_OUTPUT_G_GATE1 = 5,
+ NI_PFI_OUTPUT_AO_UPDATE_N = 6,
+ NI_PFI_OUTPUT_AO_START1 = 7,
+ NI_PFI_OUTPUT_AI_START_PULSE = 8,
+ NI_PFI_OUTPUT_G_SRC0 = 9,
+ NI_PFI_OUTPUT_G_GATE0 = 10,
+ NI_PFI_OUTPUT_EXT_STROBE = 11,
+ NI_PFI_OUTPUT_AI_EXT_MUX_CLK = 12,
+ NI_PFI_OUTPUT_GOUT0 = 13,
+ NI_PFI_OUTPUT_GOUT1 = 14,
+ NI_PFI_OUTPUT_FREQ_OUT = 15,
+ NI_PFI_OUTPUT_PFI_DO = 16,
+ NI_PFI_OUTPUT_I_ATRIG = 17,
+ NI_PFI_OUTPUT_RTSI0 = 18,
+ NI_PFI_OUTPUT_PXI_STAR_TRIGGER_IN = 26,
+ NI_PFI_OUTPUT_SCXI_TRIG1 = 27,
+ NI_PFI_OUTPUT_DIO_CHANGE_DETECT_RTSI = 28,
+ NI_PFI_OUTPUT_CDI_SAMPLE = 29,
+ NI_PFI_OUTPUT_CDO_UPDATE = 30
+};
+static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel)
+{
+ return NI_PFI_OUTPUT_RTSI0 + rtsi_channel;
+}
+
+/* Signals which can be routed to output on a NI PFI pin on a 660x board
+ with INSN_CONFIG_SET_ROUTING. The numbers assigned are
+ not arbitrary, they correspond to the bits required
+ to program the board. Lines 0 to 7 can only be set to
+ NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to
+ NI_660X_PFI_OUTPUT_COUNTER. */
+enum ni_660x_pfi_routing {
+ NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */
+ NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */
+};
+
+/* NI External Trigger lines. These values are not arbitrary, but are related
+ * to the bits required to program the board (offset by 1 for historical
+ * reasons). */
+static inline unsigned NI_EXT_PFI(unsigned pfi_channel)
+{
+ return NI_USUAL_PFI_SELECT(pfi_channel) - 1;
+}
+static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel)
+{
+ return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1;
+}
+
+/* status bits for INSN_CONFIG_GET_COUNTER_STATUS */
+enum comedi_counter_status_flags {
+ COMEDI_COUNTER_ARMED = 0x1,
+ COMEDI_COUNTER_COUNTING = 0x2,
+ COMEDI_COUNTER_TERMINAL_COUNT = 0x4,
+};
+
+/* Clock sources for CDIO subdevice on NI m-series boards. Used as the
+ * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd
+ * with CR_INVERT to change polarity. */
+enum ni_m_series_cdio_scan_begin_src {
+ NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0,
+ NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18,
+ NI_CDIO_SCAN_BEGIN_SRC_AI_CONVERT = 19,
+ NI_CDIO_SCAN_BEGIN_SRC_PXI_STAR_TRIGGER = 20,
+ NI_CDIO_SCAN_BEGIN_SRC_G0_OUT = 28,
+ NI_CDIO_SCAN_BEGIN_SRC_G1_OUT = 29,
+ NI_CDIO_SCAN_BEGIN_SRC_ANALOG_TRIGGER = 30,
+ NI_CDIO_SCAN_BEGIN_SRC_AO_UPDATE = 31,
+ NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32,
+ NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33
+};
+static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel)
+{
+ return NI_USUAL_PFI_SELECT(pfi_channel);
+}
+static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel)
+{
+ return NI_USUAL_RTSI_SELECT(rtsi_channel);
+}
+
+/* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI
+ * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to
+ * change polarity. */
+static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel)
+{
+ return NI_USUAL_PFI_SELECT(pfi_channel);
+}
+static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel)
+{
+ return NI_USUAL_RTSI_SELECT(rtsi_channel);
+}
+
+/* Bits for setting a clock source with
+ * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */
+enum ni_freq_out_clock_source_bits {
+ NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */
+ NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */
+};
+
+/* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for
+ * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */
+ enum amplc_dio_clock_source {
+ AMPLC_DIO_CLK_CLKN, /* per channel external clock
+ input/output pin (pin is only an
+ input when clock source set to this
+ value, otherwise it is an output) */
+ AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */
+ AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */
+ AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */
+ AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */
+ AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */
+ AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel
+ (for channel 0, preceding counter
+ channel is channel 2 on preceding
+ counter subdevice, for first counter
+ subdevice, preceding counter
+ subdevice is the last counter
+ subdevice) */
+ AMPLC_DIO_CLK_EXT /* per chip external input pin */
+ };
+
+/* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for
+ * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */
+ enum amplc_dio_gate_source {
+ AMPLC_DIO_GAT_VCC, /* internal high logic level */
+ AMPLC_DIO_GAT_GND, /* internal low logic level */
+ AMPLC_DIO_GAT_GATN, /* per channel external gate input */
+ AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel
+ minus 2 (for channels 0 or 1,
+ channel minus 2 is channel 1 or 2 on
+ the preceding counter subdevice, for
+ the first counter subdevice the
+ preceding counter subdevice is the
+ last counter subdevice) */
+ AMPLC_DIO_GAT_RESERVED4,
+ AMPLC_DIO_GAT_RESERVED5,
+ AMPLC_DIO_GAT_RESERVED6,
+ AMPLC_DIO_GAT_RESERVED7
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COMEDI_H */
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
new file mode 100644
index 000000000000..7d0116bcb9ff
--- /dev/null
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -0,0 +1,597 @@
+/*
+ comedi/comedi_compat32.c
+ 32-bit ioctl compatibility for 64-bit comedi kernel module.
+
+ Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk>
+ Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/>
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define __NO_VERSION__
+#include "comedi.h"
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+
+#include "comedi_compat32.h"
+
+#ifdef CONFIG_COMPAT
+
+#ifndef HAVE_COMPAT_IOCTL
+#include <linux/ioctl32.h> /* for (un)register_ioctl32_conversion */
+#endif
+
+#define COMEDI32_CHANINFO _IOR(CIO,3,comedi32_chaninfo)
+#define COMEDI32_RANGEINFO _IOR(CIO,8,comedi32_rangeinfo)
+/* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
+ * It's too late to change it now, but it only affects the command number. */
+#define COMEDI32_CMD _IOR(CIO,9,comedi32_cmd)
+/* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR.
+ * It's too late to change it now, but it only affects the command number. */
+#define COMEDI32_CMDTEST _IOR(CIO,10,comedi32_cmd)
+#define COMEDI32_INSNLIST _IOR(CIO,11,comedi32_insnlist)
+#define COMEDI32_INSN _IOR(CIO,12,comedi32_insn)
+
+typedef struct comedi32_chaninfo_struct {
+ unsigned int subdev;
+ compat_uptr_t maxdata_list; /* 32-bit 'lsampl_t *' */
+ compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */
+ compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */
+ unsigned int unused[4];
+} comedi32_chaninfo;
+
+typedef struct comedi32_rangeinfo_struct {
+ unsigned int range_type;
+ compat_uptr_t range_ptr; /* 32-bit 'void *' */
+} comedi32_rangeinfo;
+
+typedef struct comedi32_cmd_struct {
+ unsigned int subdev;
+ unsigned int flags;
+ unsigned int start_src;
+ unsigned int start_arg;
+ unsigned int scan_begin_src;
+ unsigned int scan_begin_arg;
+ unsigned int convert_src;
+ unsigned int convert_arg;
+ unsigned int scan_end_src;
+ unsigned int scan_end_arg;
+ unsigned int stop_src;
+ unsigned int stop_arg;
+ compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */
+ unsigned int chanlist_len;
+ compat_uptr_t data; /* 32-bit 'sampl_t *' */
+ unsigned int data_len;
+} comedi32_cmd;
+
+typedef struct comedi32_insn_struct {
+ unsigned int insn;
+ unsigned int n;
+ compat_uptr_t data; /* 32-bit 'lsampl_t *' */
+ unsigned int subdev;
+ unsigned int chanspec;
+ unsigned int unused[3];
+} comedi32_insn;
+
+typedef struct comedi32_insnlist_struct {
+ unsigned int n_insns;
+ compat_uptr_t insns; /* 32-bit 'comedi_insn *' */
+} comedi32_insnlist;
+
+/* Handle translated ioctl. */
+static int translated_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ if (!file->f_op) {
+ return -ENOTTY;
+ }
+#ifdef HAVE_UNLOCKED_IOCTL
+ if (file->f_op->unlocked_ioctl) {
+ int rc = (int)(*file->f_op->unlocked_ioctl)(file, cmd, arg);
+ if (rc == -ENOIOCTLCMD) {
+ rc = -ENOTTY;
+ }
+ return rc;
+ }
+#endif
+ if (file->f_op->ioctl) {
+ int rc;
+ lock_kernel();
+ rc = (*file->f_op->ioctl)(file->f_dentry->d_inode,
+ file, cmd, arg);
+ unlock_kernel();
+ return rc;
+ }
+ return -ENOTTY;
+}
+
+/* Handle 32-bit COMEDI_CHANINFO ioctl. */
+static int compat_chaninfo(struct file *file, unsigned long arg)
+{
+ comedi_chaninfo __user *chaninfo;
+ comedi32_chaninfo __user *chaninfo32;
+ int err;
+ union {
+ unsigned int uint;
+ compat_uptr_t uptr;
+ } temp;
+
+ chaninfo32 = compat_ptr(arg);
+ chaninfo = compat_alloc_user_space(sizeof(*chaninfo));
+
+ /* Copy chaninfo structure. Ignore unused members. */
+ if (!access_ok(VERIFY_READ, chaninfo32, sizeof(*chaninfo32))
+ || !access_ok(VERIFY_WRITE, chaninfo,
+ sizeof(*chaninfo))) {
+ return -EFAULT;
+ }
+ err = 0;
+ err |= __get_user(temp.uint, &chaninfo32->subdev);
+ err |= __put_user(temp.uint, &chaninfo->subdev);
+ err |= __get_user(temp.uptr, &chaninfo32->maxdata_list);
+ err |= __put_user(compat_ptr(temp.uptr), &chaninfo->maxdata_list);
+ err |= __get_user(temp.uptr, &chaninfo32->flaglist);
+ err |= __put_user(compat_ptr(temp.uptr), &chaninfo->flaglist);
+ err |= __get_user(temp.uptr, &chaninfo32->rangelist);
+ err |= __put_user(compat_ptr(temp.uptr), &chaninfo->rangelist);
+ if (err) {
+ return -EFAULT;
+ }
+
+ return translated_ioctl(file, COMEDI_CHANINFO, (unsigned long)chaninfo);
+}
+
+/* Handle 32-bit COMEDI_RANGEINFO ioctl. */
+static int compat_rangeinfo(struct file *file, unsigned long arg)
+{
+ comedi_rangeinfo __user *rangeinfo;
+ comedi32_rangeinfo __user *rangeinfo32;
+ int err;
+ union {
+ unsigned int uint;
+ compat_uptr_t uptr;
+ } temp;
+
+ rangeinfo32 = compat_ptr(arg);
+ rangeinfo = compat_alloc_user_space(sizeof(*rangeinfo));
+
+ /* Copy rangeinfo structure. */
+ if (!access_ok(VERIFY_READ, rangeinfo32, sizeof(*rangeinfo32))
+ || !access_ok(VERIFY_WRITE, rangeinfo,
+ sizeof(*rangeinfo))) {
+ return -EFAULT;
+ }
+ err = 0;
+ err |= __get_user(temp.uint, &rangeinfo32->range_type);
+ err |= __put_user(temp.uint, &rangeinfo->range_type);
+ err |= __get_user(temp.uptr, &rangeinfo32->range_ptr);
+ err |= __put_user(compat_ptr(temp.uptr), &rangeinfo->range_ptr);
+ if (err) {
+ return -EFAULT;
+ }
+
+ return translated_ioctl(file, COMEDI_RANGEINFO,
+ (unsigned long)rangeinfo);
+}
+
+/* Copy 32-bit cmd structure to native cmd structure. */
+static int get_compat_cmd(comedi_cmd __user *cmd,
+ comedi32_cmd __user *cmd32)
+{
+ int err;
+ union {
+ unsigned int uint;
+ compat_uptr_t uptr;
+ } temp;
+
+ /* Copy cmd structure. */
+ if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32))
+ || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) {
+ return -EFAULT;
+ }
+ err = 0;
+ err |= __get_user(temp.uint, &cmd32->subdev);
+ err |= __put_user(temp.uint, &cmd->subdev);
+ err |= __get_user(temp.uint, &cmd32->flags);
+ err |= __put_user(temp.uint, &cmd->flags);
+ err |= __get_user(temp.uint, &cmd32->start_src);
+ err |= __put_user(temp.uint, &cmd->start_src);
+ err |= __get_user(temp.uint, &cmd32->start_arg);
+ err |= __put_user(temp.uint, &cmd->start_arg);
+ err |= __get_user(temp.uint, &cmd32->scan_begin_src);
+ err |= __put_user(temp.uint, &cmd->scan_begin_src);
+ err |= __get_user(temp.uint, &cmd32->scan_begin_arg);
+ err |= __put_user(temp.uint, &cmd->scan_begin_arg);
+ err |= __get_user(temp.uint, &cmd32->convert_src);
+ err |= __put_user(temp.uint, &cmd->convert_src);
+ err |= __get_user(temp.uint, &cmd32->convert_arg);
+ err |= __put_user(temp.uint, &cmd->convert_arg);
+ err |= __get_user(temp.uint, &cmd32->scan_end_src);
+ err |= __put_user(temp.uint, &cmd->scan_end_src);
+ err |= __get_user(temp.uint, &cmd32->scan_end_arg);
+ err |= __put_user(temp.uint, &cmd->scan_end_arg);
+ err |= __get_user(temp.uint, &cmd32->stop_src);
+ err |= __put_user(temp.uint, &cmd->stop_src);
+ err |= __get_user(temp.uint, &cmd32->stop_arg);
+ err |= __put_user(temp.uint, &cmd->stop_arg);
+ err |= __get_user(temp.uptr, &cmd32->chanlist);
+ err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist);
+ err |= __get_user(temp.uint, &cmd32->chanlist_len);
+ err |= __put_user(temp.uint, &cmd->chanlist_len);
+ err |= __get_user(temp.uptr, &cmd32->data);
+ err |= __put_user(compat_ptr(temp.uptr), &cmd->data);
+ err |= __get_user(temp.uint, &cmd32->data_len);
+ err |= __put_user(temp.uint, &cmd->data_len);
+ return err ? -EFAULT : 0;
+}
+
+/* Copy native cmd structure to 32-bit cmd structure. */
+static int put_compat_cmd(comedi32_cmd __user *cmd32, comedi_cmd __user *cmd)
+{
+ int err;
+ unsigned int temp;
+
+ /* Copy back most of cmd structure. */
+ /* Assume the pointer values are already valid. */
+ /* (Could use ptr_to_compat() to set them, but that wasn't implemented
+ * until kernel version 2.6.11.) */
+ if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd))
+ || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) {
+ return -EFAULT;
+ }
+ err = 0;
+ err |= __get_user(temp, &cmd->subdev);
+ err |= __put_user(temp, &cmd32->subdev);
+ err |= __get_user(temp, &cmd->flags);
+ err |= __put_user(temp, &cmd32->flags);
+ err |= __get_user(temp, &cmd->start_src);
+ err |= __put_user(temp, &cmd32->start_src);
+ err |= __get_user(temp, &cmd->start_arg);
+ err |= __put_user(temp, &cmd32->start_arg);
+ err |= __get_user(temp, &cmd->scan_begin_src);
+ err |= __put_user(temp, &cmd32->scan_begin_src);
+ err |= __get_user(temp, &cmd->scan_begin_arg);
+ err |= __put_user(temp, &cmd32->scan_begin_arg);
+ err |= __get_user(temp, &cmd->convert_src);
+ err |= __put_user(temp, &cmd32->convert_src);
+ err |= __get_user(temp, &cmd->convert_arg);
+ err |= __put_user(temp, &cmd32->convert_arg);
+ err |= __get_user(temp, &cmd->scan_end_src);
+ err |= __put_user(temp, &cmd32->scan_end_src);
+ err |= __get_user(temp, &cmd->scan_end_arg);
+ err |= __put_user(temp, &cmd32->scan_end_arg);
+ err |= __get_user(temp, &cmd->stop_src);
+ err |= __put_user(temp, &cmd32->stop_src);
+ err |= __get_user(temp, &cmd->stop_arg);
+ err |= __put_user(temp, &cmd32->stop_arg);
+ /* Assume chanlist pointer is unchanged. */
+ err |= __get_user(temp, &cmd->chanlist_len);
+ err |= __put_user(temp, &cmd32->chanlist_len);
+ /* Assume data pointer is unchanged. */
+ err |= __get_user(temp, &cmd->data_len);
+ err |= __put_user(temp, &cmd32->data_len);
+ return err ? -EFAULT : 0;
+}
+
+/* Handle 32-bit COMEDI_CMD ioctl. */
+static int compat_cmd(struct file *file, unsigned long arg)
+{
+ comedi_cmd __user *cmd;
+ comedi32_cmd __user *cmd32;
+ int rc;
+
+ cmd32 = compat_ptr(arg);
+ cmd = compat_alloc_user_space(sizeof(*cmd));
+
+ rc = get_compat_cmd(cmd, cmd32);
+ if (rc) {
+ return rc;
+ }
+
+ return translated_ioctl(file, COMEDI_CMD, (unsigned long)cmd);
+}
+
+/* Handle 32-bit COMEDI_CMDTEST ioctl. */
+static int compat_cmdtest(struct file *file, unsigned long arg)
+{
+ comedi_cmd __user *cmd;
+ comedi32_cmd __user *cmd32;
+ int rc, err;
+
+ cmd32 = compat_ptr(arg);
+ cmd = compat_alloc_user_space(sizeof(*cmd));
+
+ rc = get_compat_cmd(cmd, cmd32);
+ if (rc) {
+ return rc;
+ }
+
+ rc = translated_ioctl(file, COMEDI_CMDTEST, (unsigned long)cmd);
+ if (rc < 0) {
+ return rc;
+ }
+
+ err = put_compat_cmd(cmd32, cmd);
+ if (err) {
+ rc = err;
+ }
+ return rc;
+}
+
+/* Copy 32-bit insn structure to native insn structure. */
+static int get_compat_insn(comedi_insn __user *insn,
+ comedi32_insn __user *insn32)
+{
+ int err;
+ union {
+ unsigned int uint;
+ compat_uptr_t uptr;
+ } temp;
+
+ /* Copy insn structure. Ignore the unused members. */
+ err = 0;
+ if (!access_ok(VERIFY_READ, insn32, sizeof(*insn32))
+ || !access_ok(VERIFY_WRITE, insn, sizeof(*insn))) {
+ return -EFAULT;
+ }
+ err |= __get_user(temp.uint, &insn32->insn);
+ err |= __put_user(temp.uint, &insn->insn);
+ err |= __get_user(temp.uint, &insn32->n);
+ err |= __put_user(temp.uint, &insn->n);
+ err |= __get_user(temp.uptr, &insn32->data);
+ err |= __put_user(compat_ptr(temp.uptr), &insn->data);
+ err |= __get_user(temp.uint, &insn32->subdev);
+ err |= __put_user(temp.uint, &insn->subdev);
+ err |= __get_user(temp.uint, &insn32->chanspec);
+ err |= __put_user(temp.uint, &insn->chanspec);
+ return err ? -EFAULT : 0;
+}
+
+/* Handle 32-bit COMEDI_INSNLIST ioctl. */
+static int compat_insnlist(struct file *file, unsigned long arg)
+{
+ struct combined_insnlist {
+ comedi_insnlist insnlist;
+ comedi_insn insn[1];
+ } __user *s;
+ comedi32_insnlist __user *insnlist32;
+ comedi32_insn __user *insn32;
+ compat_uptr_t uptr;
+ unsigned int n_insns, n;
+ int err, rc;
+
+ insnlist32 = compat_ptr(arg);
+
+ /* Get 32-bit insnlist structure. */
+ if (!access_ok(VERIFY_READ, insnlist32, sizeof(*insnlist32))) {
+ return -EFAULT;
+ }
+ err = 0;
+ err |= __get_user(n_insns, &insnlist32->n_insns);
+ err |= __get_user(uptr, &insnlist32->insns);
+ insn32 = compat_ptr(uptr);
+ if (err) {
+ return -EFAULT;
+ }
+
+ /* Allocate user memory to copy insnlist and insns into. */
+ s = compat_alloc_user_space(offsetof(struct combined_insnlist,
+ insn[n_insns]));
+
+ /* Set native insnlist structure. */
+ if (!access_ok(VERIFY_WRITE, &s->insnlist, sizeof(s->insnlist))) {
+ return -EFAULT;
+ }
+ err |= __put_user(n_insns, &s->insnlist.n_insns);
+ err |= __put_user(&s->insn[0], &s->insnlist.insns);
+ if (err) {
+ return -EFAULT;
+ }
+
+ /* Copy insn structures. */
+ for (n = 0; n < n_insns; n++) {
+ rc = get_compat_insn(&s->insn[n], &insn32[n]);
+ if (rc) {
+ return rc;
+ }
+ }
+
+ return translated_ioctl(file, COMEDI_INSNLIST,
+ (unsigned long)&s->insnlist);
+}
+
+/* Handle 32-bit COMEDI_INSN ioctl. */
+static int compat_insn(struct file *file, unsigned long arg)
+{
+ comedi_insn __user *insn;
+ comedi32_insn __user *insn32;
+ int rc;
+
+ insn32 = compat_ptr(arg);
+ insn = compat_alloc_user_space(sizeof(*insn));
+
+ rc = get_compat_insn(insn, insn32);
+ if (rc) {
+ return rc;
+ }
+
+ return translated_ioctl(file, COMEDI_INSN, (unsigned long)insn);
+}
+
+/* Process untranslated ioctl. */
+/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
+static inline int raw_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int rc;
+
+ switch (cmd) {
+ case COMEDI_DEVCONFIG:
+ case COMEDI_DEVINFO:
+ case COMEDI_SUBDINFO:
+ case COMEDI_BUFCONFIG:
+ case COMEDI_BUFINFO:
+ /* Just need to translate the pointer argument. */
+ arg = (unsigned long)compat_ptr(arg);
+ rc = translated_ioctl(file, cmd, arg);
+ break;
+ case COMEDI_LOCK:
+ case COMEDI_UNLOCK:
+ case COMEDI_CANCEL:
+ case COMEDI_POLL:
+ /* No translation needed. */
+ rc = translated_ioctl(file, cmd, arg);
+ break;
+ case COMEDI32_CHANINFO:
+ rc = compat_chaninfo(file, arg);
+ break;
+ case COMEDI32_RANGEINFO:
+ rc = compat_rangeinfo(file, arg);
+ break;
+ case COMEDI32_CMD:
+ rc = compat_cmd(file, arg);
+ break;
+ case COMEDI32_CMDTEST:
+ rc = compat_cmdtest(file, arg);
+ break;
+ case COMEDI32_INSNLIST:
+ rc = compat_insnlist(file, arg);
+ break;
+ case COMEDI32_INSN:
+ rc = compat_insn(file, arg);
+ break;
+ default:
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ return rc;
+}
+
+#ifdef HAVE_COMPAT_IOCTL /* defined in <linux/fs.h> 2.6.11 onwards */
+
+/* compat_ioctl file operation. */
+/* Returns -ENOIOCTLCMD for unrecognised ioctl codes. */
+long comedi_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ return raw_ioctl(file, cmd, arg);
+}
+
+#else /* HAVE_COMPAT_IOCTL */
+
+/*
+ * Brain-dead ioctl compatibility for 2.6.10 and earlier.
+ *
+ * It's brain-dead because cmd numbers need to be unique system-wide!
+ * The comedi driver could end up attempting to execute ioctls for non-Comedi
+ * devices because it registered the system-wide cmd code first. Similarly,
+ * another driver could end up attempting to execute ioctls for a Comedi
+ * device because it registered the cmd code first. Chaos ensues.
+ */
+
+/* Handler for all 32-bit ioctl codes registered by this driver. */
+static int mapped_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
+ struct file *file)
+{
+ int rc;
+
+ /* Make sure we are dealing with a Comedi device. */
+ if (imajor(file->f_dentry->d_inode) != COMEDI_MAJOR) {
+ return -ENOTTY;
+ }
+ rc = raw_ioctl(file, cmd, arg);
+ /* Do not return -ENOIOCTLCMD. */
+ if (rc == -ENOIOCTLCMD) {
+ rc = -ENOTTY;
+ }
+ return rc;
+}
+
+struct ioctl32_map {
+ unsigned int cmd;
+ int (*handler)(unsigned int, unsigned int, unsigned long,
+ struct file *);
+ int registered;
+};
+
+static struct ioctl32_map comedi_ioctl32_map[] = {
+ { COMEDI_DEVCONFIG, mapped_ioctl, 0 },
+ { COMEDI_DEVINFO, mapped_ioctl, 0 },
+ { COMEDI_SUBDINFO, mapped_ioctl, 0 },
+ { COMEDI_BUFCONFIG, mapped_ioctl, 0 },
+ { COMEDI_BUFINFO, mapped_ioctl, 0 },
+ { COMEDI_LOCK, mapped_ioctl, 0 },
+ { COMEDI_UNLOCK, mapped_ioctl, 0 },
+ { COMEDI_CANCEL, mapped_ioctl, 0 },
+ { COMEDI_POLL, mapped_ioctl, 0 },
+ { COMEDI32_CHANINFO, mapped_ioctl, 0 },
+ { COMEDI32_RANGEINFO, mapped_ioctl, 0 },
+ { COMEDI32_CMD, mapped_ioctl, 0 },
+ { COMEDI32_CMDTEST, mapped_ioctl, 0 },
+ { COMEDI32_INSNLIST, mapped_ioctl, 0 },
+ { COMEDI32_INSN, mapped_ioctl, 0 },
+};
+
+#define NUM_IOCTL32_MAPS ARRAY_SIZE(comedi_ioctl32_map)
+
+/* Register system-wide 32-bit ioctl handlers. */
+void comedi_register_ioctl32(void)
+{
+ int n, rc;
+
+ for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
+ rc = register_ioctl32_conversion(comedi_ioctl32_map[n].cmd,
+ comedi_ioctl32_map[n].handler);
+ if (rc) {
+ printk(KERN_WARNING
+ "comedi: failed to register 32-bit "
+ "compatible ioctl handler for 0x%X - "
+ "expect bad things to happen!\n",
+ comedi_ioctl32_map[n].cmd);
+ }
+ comedi_ioctl32_map[n].registered = !rc;
+ }
+}
+
+/* Unregister system-wide 32-bit ioctl translations. */
+void comedi_unregister_ioctl32(void)
+{
+ int n, rc;
+
+ for (n = 0; n < NUM_IOCTL32_MAPS; n++) {
+ if (comedi_ioctl32_map[n].registered) {
+ rc = unregister_ioctl32_conversion(
+ comedi_ioctl32_map[n].cmd,
+ comedi_ioctl32_map[n].handler);
+ if (rc) {
+ printk(KERN_ERR
+ "comedi: failed to unregister 32-bit "
+ "compatible ioctl handler for 0x%X - "
+ "expect kernel Oops!\n",
+ comedi_ioctl32_map[n].cmd);
+ } else {
+ comedi_ioctl32_map[n].registered = 0;
+ }
+ }
+ }
+}
+
+#endif /* HAVE_COMPAT_IOCTL */
+
+#endif /* CONFIG_COMPAT */
diff --git a/drivers/staging/comedi/comedi_compat32.h b/drivers/staging/comedi/comedi_compat32.h
new file mode 100644
index 000000000000..0ca01642c165
--- /dev/null
+++ b/drivers/staging/comedi/comedi_compat32.h
@@ -0,0 +1,58 @@
+/*
+ comedi/comedi_compat32.h
+ 32-bit ioctl compatibility for 64-bit comedi kernel module.
+
+ Author: Ian Abbott, MEV Ltd. <abbotti@mev.co.uk>
+ Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/>
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2007 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _COMEDI_COMPAT32_H
+#define _COMEDI_COMPAT32_H
+
+#include <linux/compat.h>
+#include <linux/fs.h> /* For HAVE_COMPAT_IOCTL and HAVE_UNLOCKED_IOCTL */
+
+#ifdef CONFIG_COMPAT
+
+#ifdef HAVE_COMPAT_IOCTL
+
+extern long comedi_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg);
+#define comedi_register_ioctl32() do {} while (0)
+#define comedi_unregister_ioctl32() do {} while (0)
+
+#else /* HAVE_COMPAT_IOCTL */
+
+#define comedi_compat_ioctl 0 /* NULL */
+extern void comedi_register_ioctl32(void);
+extern void comedi_unregister_ioctl32(void);
+
+#endif /* HAVE_COMPAT_IOCTL */
+
+#else /* CONFIG_COMPAT */
+
+#define comedi_compat_ioctl 0 /* NULL */
+#define comedi_register_ioctl32() do {} while (0)
+#define comedi_unregister_ioctl32() do {} while (0)
+
+#endif /* CONFIG_COMPAT */
+
+#endif /* _COMEDI_COMPAT32_H */
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
new file mode 100644
index 000000000000..018c964396df
--- /dev/null
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -0,0 +1,2244 @@
+/*
+ comedi/comedi_fops.c
+ comedi kernel module
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#undef DEBUG
+
+#define __NO_VERSION__
+#include "comedi_fops.h"
+#include "comedi_compat32.h"
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include "comedidev.h"
+#include <linux/cdev.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+/* #include "kvmem.h" */
+
+MODULE_AUTHOR("http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi core module");
+MODULE_LICENSE("GPL");
+
+#ifdef CONFIG_COMEDI_DEBUG
+int comedi_debug;
+module_param(comedi_debug, int, 0644);
+#endif
+
+static DEFINE_SPINLOCK(comedi_file_info_table_lock);
+static struct comedi_device_file_info
+ *comedi_file_info_table[COMEDI_NUM_MINORS];
+
+static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg);
+static int do_bufconfig_ioctl(comedi_device *dev, void *arg);
+static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
+ struct file *file);
+static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
+ void *file);
+static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg);
+static int do_bufinfo_ioctl(comedi_device *dev, void *arg);
+static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file);
+static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file);
+static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file);
+static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file);
+static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file);
+static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file);
+static int do_insn_ioctl(comedi_device *dev, void *arg, void *file);
+static int do_poll_ioctl(comedi_device *dev, unsigned int subd, void *file);
+
+extern void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s);
+static int do_cancel(comedi_device *dev, comedi_subdevice *s);
+
+static int comedi_fasync(int fd, struct file *file, int on);
+
+static int is_device_busy(comedi_device *dev);
+
+#ifdef HAVE_UNLOCKED_IOCTL
+static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+#else
+static int comedi_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+#endif
+{
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_device *dev = dev_file_info->device;
+ int rc;
+
+ mutex_lock(&dev->mutex);
+
+ /* Device config is special, because it must work on
+ * an unconfigured device. */
+ if (cmd == COMEDI_DEVCONFIG) {
+ rc = do_devconfig_ioctl(dev, (void *)arg);
+ goto done;
+ }
+
+ if (!dev->attached) {
+ DPRINTK("no driver configured on /dev/comedi%i\n", dev->minor);
+ rc = -ENODEV;
+ goto done;
+ }
+
+ switch (cmd) {
+ case COMEDI_BUFCONFIG:
+ rc = do_bufconfig_ioctl(dev, (void *)arg);
+ break;
+ case COMEDI_DEVINFO:
+ rc = do_devinfo_ioctl(dev, (void *)arg, file);
+ break;
+ case COMEDI_SUBDINFO:
+ rc = do_subdinfo_ioctl(dev, (void *)arg, file);
+ break;
+ case COMEDI_CHANINFO:
+ rc = do_chaninfo_ioctl(dev, (void *)arg);
+ break;
+ case COMEDI_RANGEINFO:
+ rc = do_rangeinfo_ioctl(dev, (void *)arg);
+ break;
+ case COMEDI_BUFINFO:
+ rc = do_bufinfo_ioctl(dev, (void *)arg);
+ break;
+ case COMEDI_LOCK:
+ rc = do_lock_ioctl(dev, arg, file);
+ break;
+ case COMEDI_UNLOCK:
+ rc = do_unlock_ioctl(dev, arg, file);
+ break;
+ case COMEDI_CANCEL:
+ rc = do_cancel_ioctl(dev, arg, file);
+ break;
+ case COMEDI_CMD:
+ rc = do_cmd_ioctl(dev, (void *)arg, file);
+ break;
+ case COMEDI_CMDTEST:
+ rc = do_cmdtest_ioctl(dev, (void *)arg, file);
+ break;
+ case COMEDI_INSNLIST:
+ rc = do_insnlist_ioctl(dev, (void *)arg, file);
+ break;
+ case COMEDI_INSN:
+ rc = do_insn_ioctl(dev, (void *)arg, file);
+ break;
+ case COMEDI_POLL:
+ rc = do_poll_ioctl(dev, arg, file);
+ break;
+ default:
+ rc = -ENOTTY;
+ break;
+ }
+
+done:
+ mutex_unlock(&dev->mutex);
+ return rc;
+}
+
+/*
+ COMEDI_DEVCONFIG
+ device config ioctl
+
+ arg:
+ pointer to devconfig structure
+
+ reads:
+ devconfig structure at arg
+
+ writes:
+ none
+*/
+static int do_devconfig_ioctl(comedi_device *dev, comedi_devconfig *arg)
+{
+ comedi_devconfig it;
+ int ret;
+ unsigned char *aux_data = NULL;
+ int aux_len;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (arg == NULL) {
+ if (is_device_busy(dev))
+ return -EBUSY;
+ if (dev->attached) {
+ struct module *driver_module = dev->driver->module;
+ comedi_device_detach(dev);
+ module_put(driver_module);
+ }
+ return 0;
+ }
+
+ if (copy_from_user(&it, arg, sizeof(comedi_devconfig)))
+ return -EFAULT;
+
+ it.board_name[COMEDI_NAMELEN - 1] = 0;
+
+ if (comedi_aux_data(it.options, 0) &&
+ it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
+ int bit_shift;
+ aux_len = it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
+ if (aux_len < 0)
+ return -EFAULT;
+
+ aux_data = vmalloc(aux_len);
+ if (!aux_data)
+ return -ENOMEM;
+
+ if (copy_from_user(aux_data,
+ comedi_aux_data(it.options, 0), aux_len)) {
+ vfree(aux_data);
+ return -EFAULT;
+ }
+ it.options[COMEDI_DEVCONF_AUX_DATA_LO] =
+ (unsigned long)aux_data;
+ if (sizeof(void *) > sizeof(int)) {
+ bit_shift = sizeof(int) * 8;
+ it.options[COMEDI_DEVCONF_AUX_DATA_HI] =
+ ((unsigned long)aux_data) >> bit_shift;
+ } else
+ it.options[COMEDI_DEVCONF_AUX_DATA_HI] = 0;
+ }
+
+ ret = comedi_device_attach(dev, &it);
+ if (ret == 0) {
+ if (!try_module_get(dev->driver->module)) {
+ comedi_device_detach(dev);
+ return -ENOSYS;
+ }
+ }
+
+ if (aux_data)
+ vfree(aux_data);
+
+ return ret;
+}
+
+/*
+ COMEDI_BUFCONFIG
+ buffer configuration ioctl
+
+ arg:
+ pointer to bufconfig structure
+
+ reads:
+ bufconfig at arg
+
+ writes:
+ modified bufconfig at arg
+
+*/
+static int do_bufconfig_ioctl(comedi_device *dev, void *arg)
+{
+ comedi_bufconfig bc;
+ comedi_async *async;
+ comedi_subdevice *s;
+ int ret = 0;
+
+ if (copy_from_user(&bc, arg, sizeof(comedi_bufconfig)))
+ return -EFAULT;
+
+ if (bc.subdevice >= dev->n_subdevices || bc.subdevice < 0)
+ return -EINVAL;
+
+ s = dev->subdevices + bc.subdevice;
+ async = s->async;
+
+ if (!async) {
+ DPRINTK("subdevice does not have async capability\n");
+ bc.size = 0;
+ bc.maximum_size = 0;
+ goto copyback;
+ }
+
+ if (bc.maximum_size) {
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ async->max_bufsize = bc.maximum_size;
+ }
+
+ if (bc.size) {
+ if (bc.size > async->max_bufsize)
+ return -EPERM;
+
+ if (s->busy) {
+ DPRINTK("subdevice is busy, cannot resize buffer\n");
+ return -EBUSY;
+ }
+ if (async->mmap_count) {
+ DPRINTK("subdevice is mmapped, cannot resize buffer\n");
+ return -EBUSY;
+ }
+
+ if (!async->prealloc_buf)
+ return -EINVAL;
+
+ /* make sure buffer is an integral number of pages
+ * (we round up) */
+ bc.size = (bc.size + PAGE_SIZE - 1) & PAGE_MASK;
+
+ ret = comedi_buf_alloc(dev, s, bc.size);
+ if (ret < 0)
+ return ret;
+
+ if (s->buf_change) {
+ ret = s->buf_change(dev, s, bc.size);
+ if (ret < 0)
+ return ret;
+ }
+
+ DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
+ dev->minor, bc.subdevice, async->prealloc_bufsz);
+ }
+
+ bc.size = async->prealloc_bufsz;
+ bc.maximum_size = async->max_bufsize;
+
+copyback:
+ if (copy_to_user(arg, &bc, sizeof(comedi_bufconfig)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ COMEDI_DEVINFO
+ device info ioctl
+
+ arg:
+ pointer to devinfo structure
+
+ reads:
+ none
+
+ writes:
+ devinfo structure
+
+*/
+static int do_devinfo_ioctl(comedi_device *dev, comedi_devinfo *arg,
+ struct file *file)
+{
+ comedi_devinfo devinfo;
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_subdevice *read_subdev =
+ comedi_get_read_subdevice(dev_file_info);
+ comedi_subdevice *write_subdev =
+ comedi_get_write_subdevice(dev_file_info);
+
+ memset(&devinfo, 0, sizeof(devinfo));
+
+ /* fill devinfo structure */
+ devinfo.version_code = COMEDI_VERSION_CODE;
+ devinfo.n_subdevs = dev->n_subdevices;
+ memcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
+ memcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
+
+ if (read_subdev)
+ devinfo.read_subdevice = read_subdev - dev->subdevices;
+ else
+ devinfo.read_subdevice = -1;
+
+ if (write_subdev)
+ devinfo.write_subdevice = write_subdev - dev->subdevices;
+ else
+ devinfo.write_subdevice = -1;
+
+ if (copy_to_user(arg, &devinfo, sizeof(comedi_devinfo)))
+ return -EFAULT;
+
+ return 0;
+}
+
+/*
+ COMEDI_SUBDINFO
+ subdevice info ioctl
+
+ arg:
+ pointer to array of subdevice info structures
+
+ reads:
+ none
+
+ writes:
+ array of subdevice info structures at arg
+
+*/
+static int do_subdinfo_ioctl(comedi_device *dev, comedi_subdinfo *arg,
+ void *file)
+{
+ int ret, i;
+ comedi_subdinfo *tmp, *us;
+ comedi_subdevice *s;
+
+ tmp = kcalloc(dev->n_subdevices, sizeof(comedi_subdinfo), GFP_KERNEL);
+ if (!tmp)
+ return -ENOMEM;
+
+ /* fill subdinfo structs */
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = dev->subdevices + i;
+ us = tmp + i;
+
+ us->type = s->type;
+ us->n_chan = s->n_chan;
+ us->subd_flags = s->subdev_flags;
+ if (comedi_get_subdevice_runflags(s) & SRF_RUNNING)
+ us->subd_flags |= SDF_RUNNING;
+#define TIMER_nanosec 5 /* backwards compatibility */
+ us->timer_type = TIMER_nanosec;
+ us->len_chanlist = s->len_chanlist;
+ us->maxdata = s->maxdata;
+ if (s->range_table) {
+ us->range_type =
+ (i << 24) | (0 << 16) | (s->range_table->length);
+ } else {
+ us->range_type = 0; /* XXX */
+ }
+ us->flags = s->flags;
+
+ if (s->busy)
+ us->subd_flags |= SDF_BUSY;
+ if (s->busy == file)
+ us->subd_flags |= SDF_BUSY_OWNER;
+ if (s->lock)
+ us->subd_flags |= SDF_LOCKED;
+ if (s->lock == file)
+ us->subd_flags |= SDF_LOCK_OWNER;
+ if (!s->maxdata && s->maxdata_list)
+ us->subd_flags |= SDF_MAXDATA;
+ if (s->flaglist)
+ us->subd_flags |= SDF_FLAGS;
+ if (s->range_table_list)
+ us->subd_flags |= SDF_RANGETYPE;
+ if (s->do_cmd)
+ us->subd_flags |= SDF_CMD;
+
+ if (s->insn_bits != &insn_inval)
+ us->insn_bits_support = COMEDI_SUPPORTED;
+ else
+ us->insn_bits_support = COMEDI_UNSUPPORTED;
+
+ us->settling_time_0 = s->settling_time_0;
+ }
+
+ ret = copy_to_user(arg, tmp,
+ dev->n_subdevices * sizeof(comedi_subdinfo));
+
+ kfree(tmp);
+
+ return ret ? -EFAULT : 0;
+}
+
+/*
+ COMEDI_CHANINFO
+ subdevice info ioctl
+
+ arg:
+ pointer to chaninfo structure
+
+ reads:
+ chaninfo structure at arg
+
+ writes:
+ arrays at elements of chaninfo structure
+
+*/
+static int do_chaninfo_ioctl(comedi_device *dev, comedi_chaninfo *arg)
+{
+ comedi_subdevice *s;
+ comedi_chaninfo it;
+
+ if (copy_from_user(&it, arg, sizeof(comedi_chaninfo)))
+ return -EFAULT;
+
+ if (it.subdev >= dev->n_subdevices)
+ return -EINVAL;
+ s = dev->subdevices + it.subdev;
+
+ if (it.maxdata_list) {
+ if (s->maxdata || !s->maxdata_list)
+ return -EINVAL;
+ if (copy_to_user(it.maxdata_list, s->maxdata_list,
+ s->n_chan * sizeof(lsampl_t)))
+ return -EFAULT;
+ }
+
+ if (it.flaglist) {
+ if (!s->flaglist)
+ return -EINVAL;
+ if (copy_to_user(it.flaglist, s->flaglist,
+ s->n_chan * sizeof(unsigned int)))
+ return -EFAULT;
+ }
+
+ if (it.rangelist) {
+ int i;
+
+ if (!s->range_table_list)
+ return -EINVAL;
+ for (i = 0; i < s->n_chan; i++) {
+ int x;
+
+ x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) |
+ (s->range_table_list[i]->length);
+ put_user(x, it.rangelist + i);
+ }
+#if 0
+ if (copy_to_user(it.rangelist, s->range_type_list,
+ s->n_chan*sizeof(unsigned int)))
+ return -EFAULT;
+#endif
+ }
+
+ return 0;
+}
+
+ /*
+ COMEDI_BUFINFO
+ buffer information ioctl
+
+ arg:
+ pointer to bufinfo structure
+
+ reads:
+ bufinfo at arg
+
+ writes:
+ modified bufinfo at arg
+
+ */
+static int do_bufinfo_ioctl(comedi_device *dev, void *arg)
+{
+ comedi_bufinfo bi;
+ comedi_subdevice *s;
+ comedi_async *async;
+
+ if (copy_from_user(&bi, arg, sizeof(comedi_bufinfo)))
+ return -EFAULT;
+
+ if (bi.subdevice >= dev->n_subdevices || bi.subdevice < 0)
+ return -EINVAL;
+
+ s = dev->subdevices + bi.subdevice;
+ async = s->async;
+
+ if (!async) {
+ DPRINTK("subdevice does not have async capability\n");
+ bi.buf_write_ptr = 0;
+ bi.buf_read_ptr = 0;
+ bi.buf_write_count = 0;
+ bi.buf_read_count = 0;
+ goto copyback;
+ }
+
+ if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
+ bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
+ comedi_buf_read_free(async, bi.bytes_read);
+
+ if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR |
+ SRF_RUNNING))
+ && async->buf_write_count == async->buf_read_count) {
+ do_become_nonbusy(dev, s);
+ }
+ }
+
+ if (bi.bytes_written && (s->subdev_flags & SDF_CMD_WRITE)) {
+ bi.bytes_written =
+ comedi_buf_write_alloc(async, bi.bytes_written);
+ comedi_buf_write_free(async, bi.bytes_written);
+ }
+
+ bi.buf_write_count = async->buf_write_count;
+ bi.buf_write_ptr = async->buf_write_ptr;
+ bi.buf_read_count = async->buf_read_count;
+ bi.buf_read_ptr = async->buf_read_ptr;
+
+copyback:
+ if (copy_to_user(arg, &bi, sizeof(comedi_bufinfo)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
+ void *file);
+/*
+ * COMEDI_INSNLIST
+ * synchronous instructions
+ *
+ * arg:
+ * pointer to sync cmd structure
+ *
+ * reads:
+ * sync cmd struct at arg
+ * instruction list
+ * data (for writes)
+ *
+ * writes:
+ * data (for reads)
+ */
+/* arbitrary limits */
+#define MAX_SAMPLES 256
+static int do_insnlist_ioctl(comedi_device *dev, void *arg, void *file)
+{
+ comedi_insnlist insnlist;
+ comedi_insn *insns = NULL;
+ lsampl_t *data = NULL;
+ int i = 0;
+ int ret = 0;
+
+ if (copy_from_user(&insnlist, arg, sizeof(comedi_insnlist)))
+ return -EFAULT;
+
+ data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
+ if (!data) {
+ DPRINTK("kmalloc failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ insns = kmalloc(sizeof(comedi_insn) * insnlist.n_insns, GFP_KERNEL);
+ if (!insns) {
+ DPRINTK("kmalloc failed\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (copy_from_user(insns, insnlist.insns,
+ sizeof(comedi_insn) * insnlist.n_insns)) {
+ DPRINTK("copy_from_user failed\n");
+ ret = -EFAULT;
+ goto error;
+ }
+
+ for (i = 0; i < insnlist.n_insns; i++) {
+ if (insns[i].n > MAX_SAMPLES) {
+ DPRINTK("number of samples too large\n");
+ ret = -EINVAL;
+ goto error;
+ }
+ if (insns[i].insn & INSN_MASK_WRITE) {
+ if (copy_from_user(data, insns[i].data,
+ insns[i].n * sizeof(lsampl_t))) {
+ DPRINTK("copy_from_user failed\n");
+ ret = -EFAULT;
+ goto error;
+ }
+ }
+ ret = parse_insn(dev, insns + i, data, file);
+ if (ret < 0)
+ goto error;
+ if (insns[i].insn & INSN_MASK_READ) {
+ if (copy_to_user(insns[i].data, data,
+ insns[i].n * sizeof(lsampl_t))) {
+ DPRINTK("copy_to_user failed\n");
+ ret = -EFAULT;
+ goto error;
+ }
+ }
+ if (need_resched())
+ schedule();
+ }
+
+error:
+ kfree(insns);
+ kfree(data);
+
+ if (ret < 0)
+ return ret;
+ return i;
+}
+
+static int check_insn_config_length(comedi_insn *insn, lsampl_t *data)
+{
+ if (insn->n < 1)
+ return -EINVAL;
+
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_OUTPUT:
+ case INSN_CONFIG_DIO_INPUT:
+ case INSN_CONFIG_DISARM:
+ case INSN_CONFIG_RESET:
+ if (insn->n == 1)
+ return 0;
+ break;
+ case INSN_CONFIG_ARM:
+ case INSN_CONFIG_DIO_QUERY:
+ case INSN_CONFIG_BLOCK_SIZE:
+ case INSN_CONFIG_FILTER:
+ case INSN_CONFIG_SERIAL_CLOCK:
+ case INSN_CONFIG_BIDIRECTIONAL_DATA:
+ case INSN_CONFIG_ALT_SOURCE:
+ case INSN_CONFIG_SET_COUNTER_MODE:
+ case INSN_CONFIG_8254_READ_STATUS:
+ case INSN_CONFIG_SET_ROUTING:
+ case INSN_CONFIG_GET_ROUTING:
+ case INSN_CONFIG_GET_PWM_STATUS:
+ case INSN_CONFIG_PWM_SET_PERIOD:
+ case INSN_CONFIG_PWM_GET_PERIOD:
+ if (insn->n == 2)
+ return 0;
+ break;
+ case INSN_CONFIG_SET_GATE_SRC:
+ case INSN_CONFIG_GET_GATE_SRC:
+ case INSN_CONFIG_SET_CLOCK_SRC:
+ case INSN_CONFIG_GET_CLOCK_SRC:
+ case INSN_CONFIG_SET_OTHER_SRC:
+ case INSN_CONFIG_GET_COUNTER_STATUS:
+ case INSN_CONFIG_PWM_SET_H_BRIDGE:
+ case INSN_CONFIG_PWM_GET_H_BRIDGE:
+ case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
+ if (insn->n == 3)
+ return 0;
+ break;
+ case INSN_CONFIG_PWM_OUTPUT:
+ case INSN_CONFIG_ANALOG_TRIG:
+ if (insn->n == 5)
+ return 0;
+ break;
+ /* by default we allow the insn since we don't have checks for
+ * all possible cases yet */
+ default:
+ rt_printk("comedi: no check for data length of config insn id "
+ "%i is implemented.\n"
+ " Add a check to %s in %s.\n"
+ " Assuming n=%i is correct.\n", data[0], __func__,
+ __FILE__, insn->n);
+ return 0;
+ break;
+ }
+ return -EINVAL;
+}
+
+static int parse_insn(comedi_device *dev, comedi_insn *insn, lsampl_t *data,
+ void *file)
+{
+ comedi_subdevice *s;
+ int ret = 0;
+ int i;
+
+ if (insn->insn & INSN_MASK_SPECIAL) {
+ /* a non-subdevice instruction */
+
+ switch (insn->insn) {
+ case INSN_GTOD:
+ {
+ struct timeval tv;
+
+ if (insn->n != 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ do_gettimeofday(&tv);
+ data[0] = tv.tv_sec;
+ data[1] = tv.tv_usec;
+ ret = 2;
+
+ break;
+ }
+ case INSN_WAIT:
+ if (insn->n != 1 || data[0] >= 100000) {
+ ret = -EINVAL;
+ break;
+ }
+ udelay(data[0] / 1000);
+ ret = 1;
+ break;
+ case INSN_INTTRIG:
+ if (insn->n != 1) {
+ ret = -EINVAL;
+ break;
+ }
+ if (insn->subdev >= dev->n_subdevices) {
+ DPRINTK("%d not usable subdevice\n",
+ insn->subdev);
+ ret = -EINVAL;
+ break;
+ }
+ s = dev->subdevices + insn->subdev;
+ if (!s->async) {
+ DPRINTK("no async\n");
+ ret = -EINVAL;
+ break;
+ }
+ if (!s->async->inttrig) {
+ DPRINTK("no inttrig\n");
+ ret = -EAGAIN;
+ break;
+ }
+ ret = s->async->inttrig(dev, s, insn->data[0]);
+ if (ret >= 0)
+ ret = 1;
+ break;
+ default:
+ DPRINTK("invalid insn\n");
+ ret = -EINVAL;
+ break;
+ }
+ } else {
+ /* a subdevice instruction */
+ lsampl_t maxdata;
+
+ if (insn->subdev >= dev->n_subdevices) {
+ DPRINTK("subdevice %d out of range\n", insn->subdev);
+ ret = -EINVAL;
+ goto out;
+ }
+ s = dev->subdevices + insn->subdev;
+
+ if (s->type == COMEDI_SUBD_UNUSED) {
+ DPRINTK("%d not usable subdevice\n", insn->subdev);
+ ret = -EIO;
+ goto out;
+ }
+
+ /* are we locked? (ioctl lock) */
+ if (s->lock && s->lock != file) {
+ DPRINTK("device locked\n");
+ ret = -EACCES;
+ goto out;
+ }
+
+ ret = check_chanlist(s, 1, &insn->chanspec);
+ if (ret < 0) {
+ ret = -EINVAL;
+ DPRINTK("bad chanspec\n");
+ goto out;
+ }
+
+ if (s->busy) {
+ ret = -EBUSY;
+ goto out;
+ }
+ /* This looks arbitrary. It is. */
+ s->busy = &parse_insn;
+ switch (insn->insn) {
+ case INSN_READ:
+ ret = s->insn_read(dev, s, insn, data);
+ break;
+ case INSN_WRITE:
+ maxdata = s->maxdata_list
+ ? s->maxdata_list[CR_CHAN(insn->chanspec)]
+ : s->maxdata;
+ for (i = 0; i < insn->n; ++i) {
+ if (data[i] > maxdata) {
+ ret = -EINVAL;
+ DPRINTK("bad data value(s)\n");
+ break;
+ }
+ }
+ if (ret == 0)
+ ret = s->insn_write(dev, s, insn, data);
+ break;
+ case INSN_BITS:
+ if (insn->n != 2) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = s->insn_bits(dev, s, insn, data);
+ break;
+ case INSN_CONFIG:
+ ret = check_insn_config_length(insn, data);
+ if (ret)
+ break;
+ ret = s->insn_config(dev, s, insn, data);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ s->busy = NULL;
+ }
+
+out:
+ return ret;
+}
+
+/*
+ * COMEDI_INSN
+ * synchronous instructions
+ *
+ * arg:
+ * pointer to insn
+ *
+ * reads:
+ * comedi_insn struct at arg
+ * data (for writes)
+ *
+ * writes:
+ * data (for reads)
+ */
+static int do_insn_ioctl(comedi_device *dev, void *arg, void *file)
+{
+ comedi_insn insn;
+ lsampl_t *data = NULL;
+ int ret = 0;
+
+ data = kmalloc(sizeof(lsampl_t) * MAX_SAMPLES, GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ if (copy_from_user(&insn, arg, sizeof(comedi_insn))) {
+ ret = -EFAULT;
+ goto error;
+ }
+
+ /* This is where the behavior of insn and insnlist deviate. */
+ if (insn.n > MAX_SAMPLES)
+ insn.n = MAX_SAMPLES;
+ if (insn.insn & INSN_MASK_WRITE) {
+ if (copy_from_user(data, insn.data, insn.n * sizeof(lsampl_t))) {
+ ret = -EFAULT;
+ goto error;
+ }
+ }
+ ret = parse_insn(dev, &insn, data, file);
+ if (ret < 0)
+ goto error;
+ if (insn.insn & INSN_MASK_READ) {
+ if (copy_to_user(insn.data, data, insn.n * sizeof(lsampl_t))) {
+ ret = -EFAULT;
+ goto error;
+ }
+ }
+ ret = insn.n;
+
+error:
+ kfree(data);
+
+ return ret;
+}
+
+/*
+ COMEDI_CMD
+ command ioctl
+
+ arg:
+ pointer to cmd structure
+
+ reads:
+ cmd structure at arg
+ channel/range list
+
+ writes:
+ modified cmd structure at arg
+
+*/
+static int do_cmd_ioctl(comedi_device *dev, void *arg, void *file)
+{
+ comedi_cmd user_cmd;
+ comedi_subdevice *s;
+ comedi_async *async;
+ int ret = 0;
+ unsigned int *chanlist_saver = NULL;
+
+ if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) {
+ DPRINTK("bad cmd address\n");
+ return -EFAULT;
+ }
+ /* save user's chanlist pointer so it can be restored later */
+ chanlist_saver = user_cmd.chanlist;
+
+ if (user_cmd.subdev >= dev->n_subdevices) {
+ DPRINTK("%d no such subdevice\n", user_cmd.subdev);
+ return -ENODEV;
+ }
+
+ s = dev->subdevices + user_cmd.subdev;
+ async = s->async;
+
+ if (s->type == COMEDI_SUBD_UNUSED) {
+ DPRINTK("%d not valid subdevice\n", user_cmd.subdev);
+ return -EIO;
+ }
+
+ if (!s->do_cmd || !s->do_cmdtest || !s->async) {
+ DPRINTK("subdevice %i does not support commands\n",
+ user_cmd.subdev);
+ return -EIO;
+ }
+
+ /* are we locked? (ioctl lock) */
+ if (s->lock && s->lock != file) {
+ DPRINTK("subdevice locked\n");
+ return -EACCES;
+ }
+
+ /* are we busy? */
+ if (s->busy) {
+ DPRINTK("subdevice busy\n");
+ return -EBUSY;
+ }
+ s->busy = file;
+
+ /* make sure channel/gain list isn't too long */
+ if (user_cmd.chanlist_len > s->len_chanlist) {
+ DPRINTK("channel/gain list too long %u > %d\n",
+ user_cmd.chanlist_len, s->len_chanlist);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ /* make sure channel/gain list isn't too short */
+ if (user_cmd.chanlist_len < 1) {
+ DPRINTK("channel/gain list too short %u < 1\n",
+ user_cmd.chanlist_len);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ kfree(async->cmd.chanlist);
+ async->cmd = user_cmd;
+ async->cmd.data = NULL;
+ /* load channel/gain list */
+ async->cmd.chanlist =
+ kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
+ if (!async->cmd.chanlist) {
+ DPRINTK("allocation failed\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ if (copy_from_user(async->cmd.chanlist, user_cmd.chanlist,
+ async->cmd.chanlist_len * sizeof(int))) {
+ DPRINTK("fault reading chanlist\n");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ /* make sure each element in channel/gain list is valid */
+ ret = check_chanlist(s, async->cmd.chanlist_len, async->cmd.chanlist);
+ if (ret < 0) {
+ DPRINTK("bad chanlist\n");
+ goto cleanup;
+ }
+
+ ret = s->do_cmdtest(dev, s, &async->cmd);
+
+ if (async->cmd.flags & TRIG_BOGUS || ret) {
+ DPRINTK("test returned %d\n", ret);
+ user_cmd = async->cmd;
+ /* restore chanlist pointer before copying back */
+ user_cmd.chanlist = chanlist_saver;
+ user_cmd.data = NULL;
+ if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) {
+ DPRINTK("fault writing cmd\n");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ ret = -EAGAIN;
+ goto cleanup;
+ }
+
+ if (!async->prealloc_bufsz) {
+ ret = -ENOMEM;
+ DPRINTK("no buffer (?)\n");
+ goto cleanup;
+ }
+
+ comedi_reset_async_buf(async);
+
+ async->cb_mask =
+ COMEDI_CB_EOA | COMEDI_CB_BLOCK | COMEDI_CB_ERROR |
+ COMEDI_CB_OVERFLOW;
+ if (async->cmd.flags & TRIG_WAKE_EOS)
+ async->cb_mask |= COMEDI_CB_EOS;
+
+ comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
+
+#ifdef CONFIG_COMEDI_RT
+ if (async->cmd.flags & TRIG_RT) {
+ if (comedi_switch_to_rt(dev) == 0)
+ comedi_set_subdevice_runflags(s, SRF_RT, SRF_RT);
+ }
+#endif
+
+ ret = s->do_cmd(dev, s);
+ if (ret == 0)
+ return 0;
+
+cleanup:
+ do_become_nonbusy(dev, s);
+
+ return ret;
+}
+
+/*
+ COMEDI_CMDTEST
+ command testing ioctl
+
+ arg:
+ pointer to cmd structure
+
+ reads:
+ cmd structure at arg
+ channel/range list
+
+ writes:
+ modified cmd structure at arg
+
+*/
+static int do_cmdtest_ioctl(comedi_device *dev, void *arg, void *file)
+{
+ comedi_cmd user_cmd;
+ comedi_subdevice *s;
+ int ret = 0;
+ unsigned int *chanlist = NULL;
+ unsigned int *chanlist_saver = NULL;
+
+ if (copy_from_user(&user_cmd, arg, sizeof(comedi_cmd))) {
+ DPRINTK("bad cmd address\n");
+ return -EFAULT;
+ }
+ /* save user's chanlist pointer so it can be restored later */
+ chanlist_saver = user_cmd.chanlist;
+
+ if (user_cmd.subdev >= dev->n_subdevices) {
+ DPRINTK("%d no such subdevice\n", user_cmd.subdev);
+ return -ENODEV;
+ }
+
+ s = dev->subdevices + user_cmd.subdev;
+ if (s->type == COMEDI_SUBD_UNUSED) {
+ DPRINTK("%d not valid subdevice\n", user_cmd.subdev);
+ return -EIO;
+ }
+
+ if (!s->do_cmd || !s->do_cmdtest) {
+ DPRINTK("subdevice %i does not support commands\n",
+ user_cmd.subdev);
+ return -EIO;
+ }
+
+ /* make sure channel/gain list isn't too long */
+ if (user_cmd.chanlist_len > s->len_chanlist) {
+ DPRINTK("channel/gain list too long %d > %d\n",
+ user_cmd.chanlist_len, s->len_chanlist);
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ /* load channel/gain list */
+ if (user_cmd.chanlist) {
+ chanlist =
+ kmalloc(user_cmd.chanlist_len * sizeof(int), GFP_KERNEL);
+ if (!chanlist) {
+ DPRINTK("allocation failed\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+
+ if (copy_from_user(chanlist, user_cmd.chanlist,
+ user_cmd.chanlist_len * sizeof(int))) {
+ DPRINTK("fault reading chanlist\n");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ /* make sure each element in channel/gain list is valid */
+ ret = check_chanlist(s, user_cmd.chanlist_len, chanlist);
+ if (ret < 0) {
+ DPRINTK("bad chanlist\n");
+ goto cleanup;
+ }
+
+ user_cmd.chanlist = chanlist;
+ }
+
+ ret = s->do_cmdtest(dev, s, &user_cmd);
+
+ /* restore chanlist pointer before copying back */
+ user_cmd.chanlist = chanlist_saver;
+
+ if (copy_to_user(arg, &user_cmd, sizeof(comedi_cmd))) {
+ DPRINTK("bad cmd address\n");
+ ret = -EFAULT;
+ goto cleanup;
+ }
+cleanup:
+ kfree(chanlist);
+
+ return ret;
+}
+
+/*
+ COMEDI_LOCK
+ lock subdevice
+
+ arg:
+ subdevice number
+
+ reads:
+ none
+
+ writes:
+ none
+
+*/
+
+static int do_lock_ioctl(comedi_device *dev, unsigned int arg, void *file)
+{
+ int ret = 0;
+ unsigned long flags;
+ comedi_subdevice *s;
+
+ if (arg >= dev->n_subdevices)
+ return -EINVAL;
+ s = dev->subdevices + arg;
+
+ comedi_spin_lock_irqsave(&s->spin_lock, flags);
+ if (s->busy || s->lock)
+ ret = -EBUSY;
+ else
+ s->lock = file;
+ comedi_spin_unlock_irqrestore(&s->spin_lock, flags);
+
+ if (ret < 0)
+ return ret;
+
+#if 0
+ if (s->lock_f)
+ ret = s->lock_f(dev, s);
+#endif
+
+ return ret;
+}
+
+/*
+ COMEDI_UNLOCK
+ unlock subdevice
+
+ arg:
+ subdevice number
+
+ reads:
+ none
+
+ writes:
+ none
+
+ This function isn't protected by the semaphore, since
+ we already own the lock.
+*/
+static int do_unlock_ioctl(comedi_device *dev, unsigned int arg, void *file)
+{
+ comedi_subdevice *s;
+
+ if (arg >= dev->n_subdevices)
+ return -EINVAL;
+ s = dev->subdevices + arg;
+
+ if (s->busy)
+ return -EBUSY;
+
+ if (s->lock && s->lock != file)
+ return -EACCES;
+
+ if (s->lock == file) {
+#if 0
+ if (s->unlock)
+ s->unlock(dev, s);
+#endif
+
+ s->lock = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ COMEDI_CANCEL
+ cancel acquisition ioctl
+
+ arg:
+ subdevice number
+
+ reads:
+ nothing
+
+ writes:
+ nothing
+
+*/
+static int do_cancel_ioctl(comedi_device *dev, unsigned int arg, void *file)
+{
+ comedi_subdevice *s;
+
+ if (arg >= dev->n_subdevices)
+ return -EINVAL;
+ s = dev->subdevices + arg;
+ if (s->async == NULL)
+ return -EINVAL;
+
+ if (s->lock && s->lock != file)
+ return -EACCES;
+
+ if (!s->busy)
+ return 0;
+
+ if (s->busy != file)
+ return -EBUSY;
+
+ return do_cancel(dev, s);
+}
+
+/*
+ COMEDI_POLL ioctl
+ instructs driver to synchronize buffers
+
+ arg:
+ subdevice number
+
+ reads:
+ nothing
+
+ writes:
+ nothing
+
+*/
+static int do_poll_ioctl(comedi_device *dev, unsigned int arg, void *file)
+{
+ comedi_subdevice *s;
+
+ if (arg >= dev->n_subdevices)
+ return -EINVAL;
+ s = dev->subdevices + arg;
+
+ if (s->lock && s->lock != file)
+ return -EACCES;
+
+ if (!s->busy)
+ return 0;
+
+ if (s->busy != file)
+ return -EBUSY;
+
+ if (s->poll)
+ return s->poll(dev, s);
+
+ return -EINVAL;
+}
+
+static int do_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+ int ret = 0;
+
+ if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) && s->cancel)
+ ret = s->cancel(dev, s);
+
+ do_become_nonbusy(dev, s);
+
+ return ret;
+}
+
+void comedi_unmap(struct vm_area_struct *area)
+{
+ comedi_async *async;
+ comedi_device *dev;
+
+ async = area->vm_private_data;
+ dev = async->subdevice->device;
+
+ mutex_lock(&dev->mutex);
+ async->mmap_count--;
+ mutex_unlock(&dev->mutex);
+}
+
+static struct vm_operations_struct comedi_vm_ops = {
+ .close = comedi_unmap,
+};
+
+static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_device *dev = dev_file_info->device;
+ comedi_async *async = NULL;
+ unsigned long start = vma->vm_start;
+ unsigned long size;
+ int n_pages;
+ int i;
+ int retval;
+ comedi_subdevice *s;
+
+ mutex_lock(&dev->mutex);
+ if (!dev->attached) {
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
+ retval = -ENODEV;
+ goto done;
+ }
+ if (vma->vm_flags & VM_WRITE)
+ s = comedi_get_write_subdevice(dev_file_info);
+ else
+ s = comedi_get_read_subdevice(dev_file_info);
+
+ if (s == NULL) {
+ retval = -EINVAL;
+ goto done;
+ }
+ async = s->async;
+ if (async == NULL) {
+ retval = -EINVAL;
+ goto done;
+ }
+
+ if (vma->vm_pgoff != 0) {
+ DPRINTK("comedi: mmap() offset must be 0.\n");
+ retval = -EINVAL;
+ goto done;
+ }
+
+ size = vma->vm_end - vma->vm_start;
+ if (size > async->prealloc_bufsz) {
+ retval = -EFAULT;
+ goto done;
+ }
+ if (size & (~PAGE_MASK)) {
+ retval = -EFAULT;
+ goto done;
+ }
+
+ n_pages = size >> PAGE_SHIFT;
+ for (i = 0; i < n_pages; ++i) {
+ if (remap_pfn_range(vma, start,
+ page_to_pfn(virt_to_page(async->
+ buf_page_list[i].
+ virt_addr)),
+ PAGE_SIZE, PAGE_SHARED)) {
+ retval = -EAGAIN;
+ goto done;
+ }
+ start += PAGE_SIZE;
+ }
+
+ vma->vm_ops = &comedi_vm_ops;
+ vma->vm_private_data = async;
+
+ async->mmap_count++;
+
+ retval = 0;
+done:
+ mutex_unlock(&dev->mutex);
+ return retval;
+}
+
+static unsigned int comedi_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_device *dev = dev_file_info->device;
+ comedi_subdevice *read_subdev;
+ comedi_subdevice *write_subdev;
+
+ mutex_lock(&dev->mutex);
+ if (!dev->attached) {
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
+ mutex_unlock(&dev->mutex);
+ return 0;
+ }
+
+ mask = 0;
+ read_subdev = comedi_get_read_subdevice(dev_file_info);
+ if (read_subdev) {
+ poll_wait(file, &read_subdev->async->wait_head, wait);
+ if (!read_subdev->busy
+ || comedi_buf_read_n_available(read_subdev->async) > 0
+ || !(comedi_get_subdevice_runflags(read_subdev) &
+ SRF_RUNNING)) {
+ mask |= POLLIN | POLLRDNORM;
+ }
+ }
+ write_subdev = comedi_get_write_subdevice(dev_file_info);
+ if (write_subdev) {
+ poll_wait(file, &write_subdev->async->wait_head, wait);
+ comedi_buf_write_alloc(write_subdev->async,
+ write_subdev->async->prealloc_bufsz);
+ if (!write_subdev->busy
+ || !(comedi_get_subdevice_runflags(write_subdev) &
+ SRF_RUNNING)
+ || comedi_buf_write_n_allocated(write_subdev->async) >=
+ bytes_per_sample(write_subdev->async->subdevice)) {
+ mask |= POLLOUT | POLLWRNORM;
+ }
+ }
+
+ mutex_unlock(&dev->mutex);
+ return mask;
+}
+
+static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
+ loff_t *offset)
+{
+ comedi_subdevice *s;
+ comedi_async *async;
+ int n, m, count = 0, retval = 0;
+ DECLARE_WAITQUEUE(wait, current);
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_device *dev = dev_file_info->device;
+
+ if (!dev->attached) {
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
+ retval = -ENODEV;
+ goto done;
+ }
+
+ s = comedi_get_write_subdevice(dev_file_info);
+ if (s == NULL) {
+ retval = -EIO;
+ goto done;
+ }
+ async = s->async;
+
+ if (!nbytes) {
+ retval = 0;
+ goto done;
+ }
+ if (!s->busy) {
+ retval = 0;
+ goto done;
+ }
+ if (s->busy != file) {
+ retval = -EACCES;
+ goto done;
+ }
+ add_wait_queue(&async->wait_head, &wait);
+ while (nbytes > 0 && !retval) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ n = nbytes;
+
+ m = n;
+ if (async->buf_write_ptr + m > async->prealloc_bufsz)
+ m = async->prealloc_bufsz - async->buf_write_ptr;
+ comedi_buf_write_alloc(async, async->prealloc_bufsz);
+ if (m > comedi_buf_write_n_allocated(async))
+ m = comedi_buf_write_n_allocated(async);
+ if (m < n)
+ n = m;
+
+ if (n == 0) {
+ if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+ if (comedi_get_subdevice_runflags(s) &
+ SRF_ERROR) {
+ retval = -EPIPE;
+ } else {
+ retval = 0;
+ }
+ do_become_nonbusy(dev, s);
+ break;
+ }
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ if (!s->busy)
+ break;
+ if (s->busy != file) {
+ retval = -EACCES;
+ break;
+ }
+ continue;
+ }
+
+ m = copy_from_user(async->prealloc_buf + async->buf_write_ptr,
+ buf, n);
+ if (m) {
+ n -= m;
+ retval = -EFAULT;
+ }
+ comedi_buf_write_free(async, n);
+
+ count += n;
+ nbytes -= n;
+
+ buf += n;
+ break; /* makes device work like a pipe */
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&async->wait_head, &wait);
+
+done:
+ return count ? count : retval;
+}
+
+static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+ loff_t *offset)
+{
+ comedi_subdevice *s;
+ comedi_async *async;
+ int n, m, count = 0, retval = 0;
+ DECLARE_WAITQUEUE(wait, current);
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_device *dev = dev_file_info->device;
+
+ if (!dev->attached) {
+ DPRINTK("no driver configured on comedi%i\n", dev->minor);
+ retval = -ENODEV;
+ goto done;
+ }
+
+ s = comedi_get_read_subdevice(dev_file_info);
+ if (s == NULL) {
+ retval = -EIO;
+ goto done;
+ }
+ async = s->async;
+ if (!nbytes) {
+ retval = 0;
+ goto done;
+ }
+ if (!s->busy) {
+ retval = 0;
+ goto done;
+ }
+ if (s->busy != file) {
+ retval = -EACCES;
+ goto done;
+ }
+
+ add_wait_queue(&async->wait_head, &wait);
+ while (nbytes > 0 && !retval) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ n = nbytes;
+
+ m = comedi_buf_read_n_available(async);
+ /* printk("%d available\n",m); */
+ if (async->buf_read_ptr + m > async->prealloc_bufsz)
+ m = async->prealloc_bufsz - async->buf_read_ptr;
+ /* printk("%d contiguous\n",m); */
+ if (m < n)
+ n = m;
+
+ if (n == 0) {
+ if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+ do_become_nonbusy(dev, s);
+ if (comedi_get_subdevice_runflags(s) &
+ SRF_ERROR) {
+ retval = -EPIPE;
+ } else {
+ retval = 0;
+ }
+ break;
+ }
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ if (!s->busy) {
+ retval = 0;
+ break;
+ }
+ if (s->busy != file) {
+ retval = -EACCES;
+ break;
+ }
+ continue;
+ }
+ m = copy_to_user(buf, async->prealloc_buf +
+ async->buf_read_ptr, n);
+ if (m) {
+ n -= m;
+ retval = -EFAULT;
+ }
+
+ comedi_buf_read_alloc(async, n);
+ comedi_buf_read_free(async, n);
+
+ count += n;
+ nbytes -= n;
+
+ buf += n;
+ break; /* makes device work like a pipe */
+ }
+ if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING)) &&
+ async->buf_read_count - async->buf_write_count == 0) {
+ do_become_nonbusy(dev, s);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&async->wait_head, &wait);
+
+done:
+ return count ? count : retval;
+}
+
+/*
+ This function restores a subdevice to an idle state.
+ */
+void do_become_nonbusy(comedi_device *dev, comedi_subdevice *s)
+{
+ comedi_async *async = s->async;
+
+ comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
+#ifdef CONFIG_COMEDI_RT
+ if (comedi_get_subdevice_runflags(s) & SRF_RT) {
+ comedi_switch_to_non_rt(dev);
+ comedi_set_subdevice_runflags(s, SRF_RT, 0);
+ }
+#endif
+ if (async) {
+ comedi_reset_async_buf(async);
+ async->inttrig = NULL;
+ } else {
+ printk(KERN_ERR
+ "BUG: (?) do_become_nonbusy called with async=0\n");
+ }
+
+ s->busy = NULL;
+}
+
+static int comedi_open(struct inode *inode, struct file *file)
+{
+ char mod[32];
+ const unsigned minor = iminor(inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_device *dev = dev_file_info->device;
+ if (dev == NULL) {
+ DPRINTK("invalid minor number\n");
+ return -ENODEV;
+ }
+
+ /* This is slightly hacky, but we want module autoloading
+ * to work for root.
+ * case: user opens device, attached -> ok
+ * case: user opens device, unattached, in_request_module=0 -> autoload
+ * case: user opens device, unattached, in_request_module=1 -> fail
+ * case: root opens device, attached -> ok
+ * case: root opens device, unattached, in_request_module=1 -> ok
+ * (typically called from modprobe)
+ * case: root opens device, unattached, in_request_module=0 -> autoload
+ *
+ * The last could be changed to "-> ok", which would deny root
+ * autoloading.
+ */
+ mutex_lock(&dev->mutex);
+ if (dev->attached)
+ goto ok;
+ if (!capable(CAP_SYS_MODULE) && dev->in_request_module) {
+ DPRINTK("in request module\n");
+ mutex_unlock(&dev->mutex);
+ return -ENODEV;
+ }
+ if (capable(CAP_SYS_MODULE) && dev->in_request_module)
+ goto ok;
+
+ dev->in_request_module = 1;
+
+ sprintf(mod, "char-major-%i-%i", COMEDI_MAJOR, dev->minor);
+#ifdef CONFIG_KMOD
+ mutex_unlock(&dev->mutex);
+ request_module(mod);
+ mutex_lock(&dev->mutex);
+#endif
+
+ dev->in_request_module = 0;
+
+ if (!dev->attached && !capable(CAP_SYS_MODULE)) {
+ DPRINTK("not attached and not CAP_SYS_MODULE\n");
+ mutex_unlock(&dev->mutex);
+ return -ENODEV;
+ }
+ok:
+ __module_get(THIS_MODULE);
+
+ if (dev->attached) {
+ if (!try_module_get(dev->driver->module)) {
+ module_put(THIS_MODULE);
+ mutex_unlock(&dev->mutex);
+ return -ENOSYS;
+ }
+ }
+
+ if (dev->attached && dev->use_count == 0 && dev->open)
+ dev->open(dev);
+
+ dev->use_count++;
+
+ mutex_unlock(&dev->mutex);
+
+ return 0;
+}
+
+static int comedi_close(struct inode *inode, struct file *file)
+{
+ const unsigned minor = iminor(inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+ comedi_device *dev = dev_file_info->device;
+ comedi_subdevice *s = NULL;
+ int i;
+
+ mutex_lock(&dev->mutex);
+
+ if (dev->subdevices) {
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = dev->subdevices + i;
+
+ if (s->busy == file)
+ do_cancel(dev, s);
+ if (s->lock == file)
+ s->lock = NULL;
+ }
+ }
+ if (dev->attached && dev->use_count == 1 && dev->close)
+ dev->close(dev);
+
+ module_put(THIS_MODULE);
+ if (dev->attached)
+ module_put(dev->driver->module);
+
+ dev->use_count--;
+
+ mutex_unlock(&dev->mutex);
+
+ if (file->f_flags & FASYNC)
+ comedi_fasync(-1, file, 0);
+
+ return 0;
+}
+
+static int comedi_fasync(int fd, struct file *file, int on)
+{
+ const unsigned minor = iminor(file->f_dentry->d_inode);
+ struct comedi_device_file_info *dev_file_info =
+ comedi_get_device_file_info(minor);
+
+ comedi_device *dev = dev_file_info->device;
+
+ return fasync_helper(fd, file, on, &dev->async_queue);
+}
+
+const struct file_operations comedi_fops = {
+ .owner = THIS_MODULE,
+#ifdef HAVE_UNLOCKED_IOCTL
+ .unlocked_ioctl = comedi_unlocked_ioctl,
+#else
+ .ioctl = comedi_ioctl,
+#endif
+#ifdef HAVE_COMPAT_IOCTL
+ .compat_ioctl = comedi_compat_ioctl,
+#endif
+ .open = comedi_open,
+ .release = comedi_close,
+ .read = comedi_read,
+ .write = comedi_write,
+ .mmap = comedi_mmap,
+ .poll = comedi_poll,
+ .fasync = comedi_fasync,
+};
+
+struct class *comedi_class;
+static struct cdev comedi_cdev;
+
+static void comedi_cleanup_legacy_minors(void)
+{
+ unsigned i;
+
+ for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++)
+ comedi_free_board_minor(i);
+}
+
+static int __init comedi_init(void)
+{
+ int i;
+ int retval;
+
+ printk(KERN_INFO "comedi: version " COMEDI_RELEASE
+ " - http://www.comedi.org\n");
+
+ memset(comedi_file_info_table, 0,
+ sizeof(struct comedi_device_file_info *) * COMEDI_NUM_MINORS);
+
+ retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS, "comedi");
+ if (retval)
+ return -EIO;
+ cdev_init(&comedi_cdev, &comedi_fops);
+ comedi_cdev.owner = THIS_MODULE;
+ kobject_set_name(&comedi_cdev.kobj, "comedi");
+ if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) {
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS);
+ return -EIO;
+ }
+ comedi_class = class_create(THIS_MODULE, "comedi");
+ if (IS_ERR(comedi_class)) {
+ printk("comedi: failed to create class");
+ cdev_del(&comedi_cdev);
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS);
+ return PTR_ERR(comedi_class);
+ }
+
+ /* XXX requires /proc interface */
+ comedi_proc_init();
+
+ /* create devices files for legacy/manual use */
+ for (i = 0; i < COMEDI_NUM_LEGACY_MINORS; i++) {
+ int minor;
+ minor = comedi_alloc_board_minor(NULL);
+ if (minor < 0) {
+ comedi_cleanup_legacy_minors();
+ cdev_del(&comedi_cdev);
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
+ COMEDI_NUM_MINORS);
+ return minor;
+ }
+ }
+
+ comedi_rt_init();
+
+ comedi_register_ioctl32();
+
+ return 0;
+}
+
+static void __exit comedi_cleanup(void)
+{
+ int i;
+
+ comedi_cleanup_legacy_minors();
+ for (i = 0; i < COMEDI_NUM_MINORS; ++i)
+ BUG_ON(comedi_file_info_table[i]);
+
+
+ class_destroy(comedi_class);
+ cdev_del(&comedi_cdev);
+ unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
+
+ comedi_proc_cleanup();
+
+ comedi_rt_cleanup();
+
+ comedi_unregister_ioctl32();
+}
+
+module_init(comedi_init);
+module_exit(comedi_cleanup);
+
+void comedi_error(const comedi_device *dev, const char *s)
+{
+ rt_printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name,
+ s);
+}
+
+void comedi_event(comedi_device *dev, comedi_subdevice *s)
+{
+ comedi_async *async = s->async;
+ unsigned runflags = 0;
+ unsigned runflags_mask = 0;
+
+ /* DPRINTK("comedi_event 0x%x\n",mask); */
+
+ if ((comedi_get_subdevice_runflags(s) & SRF_RUNNING) == 0)
+ return;
+
+ if (s->async->
+ events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
+ runflags_mask |= SRF_RUNNING;
+ }
+ /* remember if an error event has occured, so an error
+ * can be returned the next time the user does a read() */
+ if (s->async->events & (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW)) {
+ runflags_mask |= SRF_ERROR;
+ runflags |= SRF_ERROR;
+ }
+ if (runflags_mask) {
+ /*sets SRF_ERROR and SRF_RUNNING together atomically */
+ comedi_set_subdevice_runflags(s, runflags_mask, runflags);
+ }
+
+ if (async->cb_mask & s->async->events) {
+ if (comedi_get_subdevice_runflags(s) & SRF_USER) {
+
+ if (dev->rt) {
+#ifdef CONFIG_COMEDI_RT
+ /* pend wake up */
+ comedi_rt_pend_wakeup(&async->wait_head);
+#else
+ printk
+ ("BUG: comedi_event() code unreachable\n");
+#endif
+ } else {
+ wake_up_interruptible(&async->wait_head);
+ if (s->subdev_flags & SDF_CMD_READ) {
+ kill_fasync(&dev->async_queue, SIGIO,
+ POLL_IN);
+ }
+ if (s->subdev_flags & SDF_CMD_WRITE) {
+ kill_fasync(&dev->async_queue, SIGIO,
+ POLL_OUT);
+ }
+ }
+ } else {
+ if (async->cb_func)
+ async->cb_func(s->async->events, async->cb_arg);
+ /* XXX bug here. If subdevice A is rt, and
+ * subdevice B tries to callback to a normal
+ * linux kernel function, it will be at the
+ * wrong priority. Since this isn't very
+ * common, I'm not going to worry about it. */
+ }
+ }
+ s->async->events = 0;
+}
+
+void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
+ unsigned bits)
+{
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&s->spin_lock, flags);
+ s->runflags &= ~mask;
+ s->runflags |= (bits & mask);
+ comedi_spin_unlock_irqrestore(&s->spin_lock, flags);
+}
+
+unsigned comedi_get_subdevice_runflags(comedi_subdevice *s)
+{
+ unsigned long flags;
+ unsigned runflags;
+
+ comedi_spin_lock_irqsave(&s->spin_lock, flags);
+ runflags = s->runflags;
+ comedi_spin_unlock_irqrestore(&s->spin_lock, flags);
+ return runflags;
+}
+
+static int is_device_busy(comedi_device *dev)
+{
+ comedi_subdevice *s;
+ int i;
+
+ if (!dev->attached)
+ return 0;
+
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = dev->subdevices + i;
+ if (s->busy)
+ return 1;
+ if (s->async && s->async->mmap_count)
+ return 1;
+ }
+
+ return 0;
+}
+
+void comedi_device_init(comedi_device *dev)
+{
+ memset(dev, 0, sizeof(comedi_device));
+ spin_lock_init(&dev->spinlock);
+ mutex_init(&dev->mutex);
+ dev->minor = -1;
+}
+
+void comedi_device_cleanup(comedi_device *dev)
+{
+ if (dev == NULL)
+ return;
+ mutex_lock(&dev->mutex);
+ comedi_device_detach(dev);
+ mutex_unlock(&dev->mutex);
+ mutex_destroy(&dev->mutex);
+}
+
+int comedi_alloc_board_minor(struct device *hardware_device)
+{
+ unsigned long flags;
+ struct comedi_device_file_info *info;
+ device_create_result_type *csdev;
+ unsigned i;
+
+ info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+ if (info == NULL)
+ return -ENOMEM;
+ info->device = kzalloc(sizeof(comedi_device), GFP_KERNEL);
+ if (info->device == NULL) {
+ kfree(info);
+ return -ENOMEM;
+ }
+ comedi_device_init(info->device);
+ comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) {
+ if (comedi_file_info_table[i] == NULL) {
+ comedi_file_info_table[i] = info;
+ break;
+ }
+ }
+ comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ if (i == COMEDI_NUM_BOARD_MINORS) {
+ comedi_device_cleanup(info->device);
+ kfree(info->device);
+ kfree(info);
+ rt_printk
+ ("comedi: error: ran out of minor numbers for board device files.\n");
+ return -EBUSY;
+ }
+ info->device->minor = i;
+ csdev = COMEDI_DEVICE_CREATE(comedi_class, NULL,
+ MKDEV(COMEDI_MAJOR, i), NULL,
+ hardware_device, "comedi%i", i);
+ if (!IS_ERR(csdev))
+ info->device->class_dev = csdev;
+
+ return i;
+}
+
+void comedi_free_board_minor(unsigned minor)
+{
+ unsigned long flags;
+ struct comedi_device_file_info *info;
+
+ BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
+ comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ info = comedi_file_info_table[minor];
+ comedi_file_info_table[minor] = NULL;
+ comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+
+ if (info) {
+ comedi_device *dev = info->device;
+ if (dev) {
+ if (dev->class_dev) {
+ device_destroy(comedi_class,
+ MKDEV(COMEDI_MAJOR, dev->minor));
+ }
+ comedi_device_cleanup(dev);
+ kfree(dev);
+ }
+ kfree(info);
+ }
+}
+
+int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s)
+{
+ unsigned long flags;
+ struct comedi_device_file_info *info;
+ device_create_result_type *csdev;
+ unsigned i;
+
+ info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
+ if (info == NULL)
+ return -ENOMEM;
+ info->device = dev;
+ info->read_subdevice = s;
+ info->write_subdevice = s;
+ comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_BOARD_MINORS; ++i) {
+ if (comedi_file_info_table[i] == NULL) {
+ comedi_file_info_table[i] = info;
+ break;
+ }
+ }
+ comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ if (i == COMEDI_NUM_MINORS) {
+ kfree(info);
+ rt_printk
+ ("comedi: error: ran out of minor numbers for board device files.\n");
+ return -EBUSY;
+ }
+ s->minor = i;
+ csdev = COMEDI_DEVICE_CREATE(comedi_class, dev->class_dev,
+ MKDEV(COMEDI_MAJOR, i), NULL, NULL,
+ "comedi%i_subd%i", dev->minor,
+ (int)(s - dev->subdevices));
+ if (!IS_ERR(csdev))
+ s->class_dev = csdev;
+
+ return i;
+}
+
+void comedi_free_subdevice_minor(comedi_subdevice *s)
+{
+ unsigned long flags;
+ struct comedi_device_file_info *info;
+
+ if (s == NULL)
+ return;
+ if (s->minor < 0)
+ return;
+
+ BUG_ON(s->minor >= COMEDI_NUM_MINORS);
+ BUG_ON(s->minor < COMEDI_FIRST_SUBDEVICE_MINOR);
+
+ comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ info = comedi_file_info_table[s->minor];
+ comedi_file_info_table[s->minor] = NULL;
+ comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+
+ if (s->class_dev) {
+ device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
+ s->class_dev = NULL;
+ }
+ kfree(info);
+}
+
+struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
+{
+ unsigned long flags;
+ struct comedi_device_file_info *info;
+
+ BUG_ON(minor >= COMEDI_NUM_MINORS);
+ comedi_spin_lock_irqsave(&comedi_file_info_table_lock, flags);
+ info = comedi_file_info_table[minor];
+ comedi_spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
+ return info;
+}
diff --git a/drivers/staging/comedi/comedi_fops.h b/drivers/staging/comedi/comedi_fops.h
new file mode 100644
index 000000000000..63f8df558e85
--- /dev/null
+++ b/drivers/staging/comedi/comedi_fops.h
@@ -0,0 +1,8 @@
+
+#ifndef _COMEDI_FOPS_H
+#define _COMEDI_FOPS_H
+
+extern struct class *comedi_class;
+extern const struct file_operations comedi_fops;
+
+#endif /* _COMEDI_FOPS_H */
diff --git a/drivers/staging/comedi/comedi_ksyms.c b/drivers/staging/comedi/comedi_ksyms.c
new file mode 100644
index 000000000000..90d57282efb8
--- /dev/null
+++ b/drivers/staging/comedi/comedi_ksyms.c
@@ -0,0 +1,77 @@
+/*
+ module/exp_ioctl.c
+ exported comedi functions
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define __NO_VERSION__
+#ifndef EXPORT_SYMTAB
+#define EXPORT_SYMTAB
+#endif
+
+#include "comedidev.h"
+
+/* for drivers */
+EXPORT_SYMBOL(comedi_driver_register);
+EXPORT_SYMBOL(comedi_driver_unregister);
+//EXPORT_SYMBOL(comedi_bufcheck);
+//EXPORT_SYMBOL(comedi_done);
+//EXPORT_SYMBOL(comedi_error_done);
+EXPORT_SYMBOL(comedi_error);
+//EXPORT_SYMBOL(comedi_eobuf);
+//EXPORT_SYMBOL(comedi_eos);
+EXPORT_SYMBOL(comedi_event);
+EXPORT_SYMBOL(comedi_get_subdevice_runflags);
+EXPORT_SYMBOL(comedi_set_subdevice_runflags);
+EXPORT_SYMBOL(range_bipolar10);
+EXPORT_SYMBOL(range_bipolar5);
+EXPORT_SYMBOL(range_bipolar2_5);
+EXPORT_SYMBOL(range_unipolar10);
+EXPORT_SYMBOL(range_unipolar5);
+EXPORT_SYMBOL(range_unknown);
+#ifdef CONFIG_COMEDI_RT
+EXPORT_SYMBOL(comedi_free_irq);
+EXPORT_SYMBOL(comedi_request_irq);
+EXPORT_SYMBOL(comedi_switch_to_rt);
+EXPORT_SYMBOL(comedi_switch_to_non_rt);
+EXPORT_SYMBOL(rt_pend_call);
+#endif
+#ifdef CONFIG_COMEDI_DEBUG
+EXPORT_SYMBOL(comedi_debug);
+#endif
+EXPORT_SYMBOL_GPL(comedi_alloc_board_minor);
+EXPORT_SYMBOL_GPL(comedi_free_board_minor);
+EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
+EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
+
+/* for kcomedilib */
+EXPORT_SYMBOL(check_chanlist);
+EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
+
+EXPORT_SYMBOL(comedi_buf_put);
+EXPORT_SYMBOL(comedi_buf_get);
+EXPORT_SYMBOL(comedi_buf_read_n_available);
+EXPORT_SYMBOL(comedi_buf_write_free);
+EXPORT_SYMBOL(comedi_buf_write_alloc);
+EXPORT_SYMBOL(comedi_buf_read_free);
+EXPORT_SYMBOL(comedi_buf_read_alloc);
+EXPORT_SYMBOL(comedi_buf_memcpy_to);
+EXPORT_SYMBOL(comedi_buf_memcpy_from);
+EXPORT_SYMBOL(comedi_reset_async_buf);
diff --git a/drivers/staging/comedi/comedi_rt.h b/drivers/staging/comedi/comedi_rt.h
new file mode 100644
index 000000000000..61852bf5adcc
--- /dev/null
+++ b/drivers/staging/comedi/comedi_rt.h
@@ -0,0 +1,150 @@
+/*
+ module/comedi_rt.h
+ header file for real-time structures, variables, and constants
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _COMEDI_RT_H
+#define _COMEDI_RT_H
+
+#ifndef _COMEDIDEV_H
+#error comedi_rt.h should only be included by comedidev.h
+#endif
+
+#include <linux/version.h>
+#include <linux/kdev_t.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_COMEDI_RT
+
+#ifdef CONFIG_COMEDI_RTAI
+#include <rtai.h>
+#include <rtai_sched.h>
+#include <rtai_version.h>
+#endif
+#ifdef CONFIG_COMEDI_RTL
+#include <rtl_core.h>
+#include <rtl_time.h>
+/* #ifdef RTLINUX_VERSION_CODE */
+#include <rtl_sync.h>
+/* #endif */
+#define rt_printk rtl_printf
+#endif
+#ifdef CONFIG_COMEDI_FUSION
+#define rt_printk(format, args...) printk(format , ## args)
+#endif /* CONFIG_COMEDI_FUSION */
+#ifdef CONFIG_PRIORITY_IRQ
+#define rt_printk printk
+#endif
+
+int comedi_request_irq(unsigned int irq, irqreturn_t(*handler) (int,
+ void *PT_REGS_ARG), unsigned long flags, const char *device,
+ comedi_device *dev_id);
+void comedi_free_irq(unsigned int irq, comedi_device *dev_id);
+void comedi_rt_init(void);
+void comedi_rt_cleanup(void);
+int comedi_switch_to_rt(comedi_device *dev);
+void comedi_switch_to_non_rt(comedi_device *dev);
+void comedi_rt_pend_wakeup(wait_queue_head_t *q);
+extern int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1,
+ void *arg2);
+
+#else
+
+#define comedi_request_irq(a, b, c, d, e) request_irq(a, b, c, d, e)
+#define comedi_free_irq(a, b) free_irq(a, b)
+#define comedi_rt_init() do {} while (0)
+#define comedi_rt_cleanup() do {} while (0)
+#define comedi_switch_to_rt(a) (-1)
+#define comedi_switch_to_non_rt(a) do {} while (0)
+#define comedi_rt_pend_wakeup(a) do {} while (0)
+
+#define rt_printk(format, args...) printk(format, ##args)
+
+#endif
+
+/* Define a spin_lock_irqsave function that will work with rt or without.
+ * Use inline functions instead of just macros to enforce some type checking.
+ */
+#define comedi_spin_lock_irqsave(lock_ptr, flags) \
+ (flags = __comedi_spin_lock_irqsave(lock_ptr))
+
+static inline unsigned long __comedi_spin_lock_irqsave(spinlock_t *lock_ptr)
+{
+ unsigned long flags;
+
+#if defined(CONFIG_COMEDI_RTAI)
+ flags = rt_spin_lock_irqsave(lock_ptr);
+
+#elif defined(CONFIG_COMEDI_RTL)
+ rtl_spin_lock_irqsave(lock_ptr, flags);
+
+#elif defined(CONFIG_COMEDI_RTL_V1)
+ rtl_spin_lock_irqsave(lock_ptr, flags);
+
+#elif defined(CONFIG_COMEDI_FUSION)
+ rthal_spin_lock_irqsave(lock_ptr, flags);
+#else
+ spin_lock_irqsave(lock_ptr, flags);
+
+#endif
+
+ return flags;
+}
+
+static inline void comedi_spin_unlock_irqrestore(spinlock_t *lock_ptr,
+ unsigned long flags)
+{
+
+#if defined(CONFIG_COMEDI_RTAI)
+ rt_spin_unlock_irqrestore(flags, lock_ptr);
+
+#elif defined(CONFIG_COMEDI_RTL)
+ rtl_spin_unlock_irqrestore(lock_ptr, flags);
+
+#elif defined(CONFIG_COMEDI_RTL_V1)
+ rtl_spin_unlock_irqrestore(lock_ptr, flags);
+#elif defined(CONFIG_COMEDI_FUSION)
+ rthal_spin_unlock_irqrestore(lock_ptr, flags);
+#else
+ spin_unlock_irqrestore(lock_ptr, flags);
+
+#endif
+
+}
+
+/* define a RT safe udelay */
+static inline void comedi_udelay(unsigned int usec)
+{
+#if defined(CONFIG_COMEDI_RTAI)
+ static const int nanosec_per_usec = 1000;
+ rt_busy_sleep(usec * nanosec_per_usec);
+#elif defined(CONFIG_COMEDI_RTL)
+ static const int nanosec_per_usec = 1000;
+ rtl_delay(usec * nanosec_per_usec);
+#else
+ udelay(usec);
+#endif
+}
+
+#endif
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h
new file mode 100644
index 000000000000..3735355d3c58
--- /dev/null
+++ b/drivers/staging/comedi/comedidev.h
@@ -0,0 +1,537 @@
+/*
+ include/linux/comedidev.h
+ header file for kernel-only structures, variables, and constants
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _COMEDIDEV_H
+#define _COMEDIDEV_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kdev_t.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include "interrupt.h"
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include "comedi.h"
+
+#define DPRINTK(format, args...) do { \
+ if (comedi_debug) \
+ printk(KERN_DEBUG "comedi: " format , ## args); \
+} while (0)
+
+#define COMEDI_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
+#define COMEDI_VERSION_CODE COMEDI_VERSION(COMEDI_MAJORVERSION, COMEDI_MINORVERSION, COMEDI_MICROVERSION)
+#define COMEDI_RELEASE VERSION
+
+#define COMEDI_INITCLEANUP_NOMODULE(x) \
+ static int __init x ## _init_module(void) \
+ {return comedi_driver_register(&(x));} \
+ static void __exit x ## _cleanup_module(void) \
+ {comedi_driver_unregister(&(x));} \
+ module_init(x ## _init_module); \
+ module_exit(x ## _cleanup_module); \
+
+#define COMEDI_MODULE_MACROS \
+ MODULE_AUTHOR("Comedi http://www.comedi.org"); \
+ MODULE_DESCRIPTION("Comedi low-level driver"); \
+ MODULE_LICENSE("GPL"); \
+
+#define COMEDI_INITCLEANUP(x) \
+ COMEDI_MODULE_MACROS \
+ COMEDI_INITCLEANUP_NOMODULE(x)
+
+#define COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) \
+ static int __devinit comedi_driver ## _pci_probe(struct pci_dev *dev, \
+ const struct pci_device_id *ent) \
+ { \
+ return comedi_pci_auto_config(dev, comedi_driver.driver_name); \
+ } \
+ static void __devexit comedi_driver ## _pci_remove(struct pci_dev *dev) \
+ { \
+ comedi_pci_auto_unconfig(dev); \
+ } \
+ static struct pci_driver comedi_driver ## _pci_driver = \
+ { \
+ .id_table = pci_id_table, \
+ .probe = &comedi_driver ## _pci_probe, \
+ .remove = __devexit_p(&comedi_driver ## _pci_remove) \
+ }; \
+ static int __init comedi_driver ## _init_module(void) \
+ { \
+ int retval; \
+ retval = comedi_driver_register(&comedi_driver); \
+ if (retval < 0) \
+ return retval; \
+ comedi_driver ## _pci_driver.name = (char *)comedi_driver.driver_name; \
+ return pci_register_driver(&comedi_driver ## _pci_driver); \
+ } \
+ static void __exit comedi_driver ## _cleanup_module(void) \
+ { \
+ pci_unregister_driver(&comedi_driver ## _pci_driver); \
+ comedi_driver_unregister(&comedi_driver); \
+ } \
+ module_init(comedi_driver ## _init_module); \
+ module_exit(comedi_driver ## _cleanup_module);
+
+#define COMEDI_PCI_INITCLEANUP(comedi_driver, pci_id_table) \
+ COMEDI_MODULE_MACROS \
+ COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table)
+
+#define PCI_VENDOR_ID_INOVA 0x104c
+#define PCI_VENDOR_ID_NATINST 0x1093
+#define PCI_VENDOR_ID_DATX 0x1116
+#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
+#define PCI_VENDOR_ID_ADVANTECH 0x13fe
+#define PCI_VENDOR_ID_RTD 0x1435
+#define PCI_VENDOR_ID_AMPLICON 0x14dc
+#define PCI_VENDOR_ID_ADLINK 0x144a
+#define PCI_VENDOR_ID_ICP 0x104c
+#define PCI_VENDOR_ID_CONTEC 0x1221
+#define PCI_VENDOR_ID_MEILHAUS 0x1402
+
+#define COMEDI_NUM_MINORS 0x100
+#define COMEDI_NUM_LEGACY_MINORS 0x10
+#define COMEDI_NUM_BOARD_MINORS 0x30
+#define COMEDI_FIRST_SUBDEVICE_MINOR COMEDI_NUM_BOARD_MINORS
+
+typedef struct comedi_device_struct comedi_device;
+typedef struct comedi_subdevice_struct comedi_subdevice;
+typedef struct comedi_async_struct comedi_async;
+typedef struct comedi_driver_struct comedi_driver;
+typedef struct comedi_lrange_struct comedi_lrange;
+
+typedef struct device device_create_result_type;
+
+#define COMEDI_DEVICE_CREATE(cs, parent, devt, drvdata, device, fmt...) \
+ device_create(cs, ((parent) ? (parent) : (device)), devt, drvdata, fmt)
+
+struct comedi_subdevice_struct {
+ comedi_device *device;
+ int type;
+ int n_chan;
+ volatile int subdev_flags;
+ int len_chanlist; /* maximum length of channel/gain list */
+
+ void *private;
+
+ comedi_async *async;
+
+ void *lock;
+ void *busy;
+ unsigned runflags;
+ spinlock_t spin_lock;
+
+ int io_bits;
+
+ lsampl_t maxdata; /* if maxdata==0, use list */
+ const lsampl_t *maxdata_list; /* list is channel specific */
+
+ unsigned int flags;
+ const unsigned int *flaglist;
+
+ unsigned int settling_time_0;
+
+ const comedi_lrange *range_table;
+ const comedi_lrange *const *range_table_list;
+
+ unsigned int *chanlist; /* driver-owned chanlist (not used) */
+
+ int (*insn_read) (comedi_device *, comedi_subdevice *, comedi_insn *,
+ lsampl_t *);
+ int (*insn_write) (comedi_device *, comedi_subdevice *, comedi_insn *,
+ lsampl_t *);
+ int (*insn_bits) (comedi_device *, comedi_subdevice *, comedi_insn *,
+ lsampl_t *);
+ int (*insn_config) (comedi_device *, comedi_subdevice *, comedi_insn *,
+ lsampl_t *);
+
+ int (*do_cmd) (comedi_device *, comedi_subdevice *);
+ int (*do_cmdtest) (comedi_device *, comedi_subdevice *, comedi_cmd *);
+ int (*poll) (comedi_device *, comedi_subdevice *);
+ int (*cancel) (comedi_device *, comedi_subdevice *);
+ /* int (*do_lock)(comedi_device *,comedi_subdevice *); */
+ /* int (*do_unlock)(comedi_device *,comedi_subdevice *); */
+
+ /* called when the buffer changes */
+ int (*buf_change) (comedi_device *dev, comedi_subdevice *s,
+ unsigned long new_size);
+
+ void (*munge) (comedi_device *dev, comedi_subdevice *s, void *data,
+ unsigned int num_bytes, unsigned int start_chan_index);
+ enum dma_data_direction async_dma_dir;
+
+ unsigned int state;
+
+ device_create_result_type *class_dev;
+ int minor;
+};
+
+struct comedi_buf_page {
+ void *virt_addr;
+ dma_addr_t dma_addr;
+};
+
+struct comedi_async_struct {
+ comedi_subdevice *subdevice;
+
+ void *prealloc_buf; /* pre-allocated buffer */
+ unsigned int prealloc_bufsz; /* buffer size, in bytes */
+ struct comedi_buf_page *buf_page_list; /* virtual and dma address of each page */
+ unsigned n_buf_pages; /* num elements in buf_page_list */
+
+ unsigned int max_bufsize; /* maximum buffer size, bytes */
+ unsigned int mmap_count; /* current number of mmaps of prealloc_buf */
+
+ unsigned int buf_write_count; /* byte count for writer (write completed) */
+ unsigned int buf_write_alloc_count; /* byte count for writer (allocated for writing) */
+ unsigned int buf_read_count; /* byte count for reader (read completed) */
+ unsigned int buf_read_alloc_count; /* byte count for reader (allocated for reading) */
+
+ unsigned int buf_write_ptr; /* buffer marker for writer */
+ unsigned int buf_read_ptr; /* buffer marker for reader */
+
+ unsigned int cur_chan; /* useless channel marker for interrupt */
+ /* number of bytes that have been received for current scan */
+ unsigned int scan_progress;
+ /* keeps track of where we are in chanlist as for munging */
+ unsigned int munge_chan;
+ /* number of bytes that have been munged */
+ unsigned int munge_count;
+ /* buffer marker for munging */
+ unsigned int munge_ptr;
+
+ unsigned int events; /* events that have occurred */
+
+ comedi_cmd cmd;
+
+ wait_queue_head_t wait_head;
+
+ /* callback stuff */
+ unsigned int cb_mask;
+ int (*cb_func) (unsigned int flags, void *);
+ void *cb_arg;
+
+ int (*inttrig) (comedi_device *dev, comedi_subdevice *s,
+ unsigned int x);
+};
+
+struct comedi_driver_struct {
+ struct comedi_driver_struct *next;
+
+ const char *driver_name;
+ struct module *module;
+ int (*attach) (comedi_device *, comedi_devconfig *);
+ int (*detach) (comedi_device *);
+
+ /* number of elements in board_name and board_id arrays */
+ unsigned int num_names;
+ const char *const *board_name;
+ /* offset in bytes from one board name pointer to the next */
+ int offset;
+};
+
+struct comedi_device_struct {
+ int use_count;
+ comedi_driver *driver;
+ void *private;
+
+ device_create_result_type *class_dev;
+ int minor;
+ /* hw_dev is passed to dma_alloc_coherent when allocating async buffers
+ * for subdevices that have async_dma_dir set to something other than
+ * DMA_NONE */
+ struct device *hw_dev;
+
+ const char *board_name;
+ const void *board_ptr;
+ int attached;
+ int rt;
+ spinlock_t spinlock;
+ struct mutex mutex;
+ int in_request_module;
+
+ int n_subdevices;
+ comedi_subdevice *subdevices;
+
+ /* dumb */
+ unsigned long iobase;
+ unsigned int irq;
+
+ comedi_subdevice *read_subdev;
+ comedi_subdevice *write_subdev;
+
+ struct fasync_struct *async_queue;
+
+ void (*open) (comedi_device *dev);
+ void (*close) (comedi_device *dev);
+};
+
+struct comedi_device_file_info {
+ comedi_device *device;
+ comedi_subdevice *read_subdevice;
+ comedi_subdevice *write_subdevice;
+};
+
+#ifdef CONFIG_COMEDI_DEBUG
+extern int comedi_debug;
+#else
+static const int comedi_debug;
+#endif
+
+/*
+ * function prototypes
+ */
+
+void comedi_event(comedi_device *dev, comedi_subdevice *s);
+void comedi_error(const comedi_device *dev, const char *s);
+
+/* we can expand the number of bits used to encode devices/subdevices into
+ the minor number soon, after more distros support > 8 bit minor numbers
+ (like after Debian Etch gets released) */
+enum comedi_minor_bits {
+ COMEDI_DEVICE_MINOR_MASK = 0xf,
+ COMEDI_SUBDEVICE_MINOR_MASK = 0xf0
+};
+static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4;
+static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1;
+
+struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor);
+
+static inline comedi_subdevice *comedi_get_read_subdevice(
+ const struct comedi_device_file_info *info)
+{
+ if (info->read_subdevice)
+ return info->read_subdevice;
+ if (info->device == NULL)
+ return NULL;
+ return info->device->read_subdev;
+}
+
+static inline comedi_subdevice *comedi_get_write_subdevice(
+ const struct comedi_device_file_info *info)
+{
+ if (info->write_subdevice)
+ return info->write_subdevice;
+ if (info->device == NULL)
+ return NULL;
+ return info->device->write_subdev;
+}
+
+void comedi_device_detach(comedi_device *dev);
+int comedi_device_attach(comedi_device *dev, comedi_devconfig *it);
+int comedi_driver_register(comedi_driver *);
+int comedi_driver_unregister(comedi_driver *);
+
+void init_polling(void);
+void cleanup_polling(void);
+void start_polling(comedi_device *);
+void stop_polling(comedi_device *);
+
+int comedi_buf_alloc(comedi_device *dev, comedi_subdevice *s, unsigned long
+ new_size);
+
+#ifdef CONFIG_PROC_FS
+void comedi_proc_init(void);
+void comedi_proc_cleanup(void);
+#else
+static inline void comedi_proc_init(void)
+{
+}
+static inline void comedi_proc_cleanup(void)
+{
+}
+#endif
+
+/* subdevice runflags */
+enum subdevice_runflags {
+ SRF_USER = 0x00000001,
+ SRF_RT = 0x00000002,
+ /* indicates an COMEDI_CB_ERROR event has occurred since the last
+ * command was started */
+ SRF_ERROR = 0x00000004,
+ SRF_RUNNING = 0x08000000
+};
+
+/*
+ various internal comedi functions
+ */
+
+int do_rangeinfo_ioctl(comedi_device *dev, comedi_rangeinfo *arg);
+int check_chanlist(comedi_subdevice *s, int n, unsigned int *chanlist);
+void comedi_set_subdevice_runflags(comedi_subdevice *s, unsigned mask,
+ unsigned bits);
+unsigned comedi_get_subdevice_runflags(comedi_subdevice *s);
+int insn_inval(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data);
+
+/* range stuff */
+
+#define RANGE(a, b) {(a)*1e6, (b)*1e6, 0}
+#define RANGE_ext(a, b) {(a)*1e6, (b)*1e6, RF_EXTERNAL}
+#define RANGE_mA(a, b) {(a)*1e6, (b)*1e6, UNIT_mA}
+#define RANGE_unitless(a, b) {(a)*1e6, (b)*1e6, 0} /* XXX */
+#define BIP_RANGE(a) {-(a)*1e6, (a)*1e6, 0}
+#define UNI_RANGE(a) {0, (a)*1e6, 0}
+
+extern const comedi_lrange range_bipolar10;
+extern const comedi_lrange range_bipolar5;
+extern const comedi_lrange range_bipolar2_5;
+extern const comedi_lrange range_unipolar10;
+extern const comedi_lrange range_unipolar5;
+extern const comedi_lrange range_unknown;
+
+#define range_digital range_unipolar5
+
+#if __GNUC__ >= 3
+#define GCC_ZERO_LENGTH_ARRAY
+#else
+#define GCC_ZERO_LENGTH_ARRAY 0
+#endif
+
+struct comedi_lrange_struct {
+ int length;
+ comedi_krange range[GCC_ZERO_LENGTH_ARRAY];
+};
+
+/* some silly little inline functions */
+
+static inline int alloc_subdevices(comedi_device *dev,
+ unsigned int num_subdevices)
+{
+ unsigned i;
+
+ dev->n_subdevices = num_subdevices;
+ dev->subdevices =
+ kcalloc(num_subdevices, sizeof(comedi_subdevice), GFP_KERNEL);
+ if (!dev->subdevices)
+ return -ENOMEM;
+ for (i = 0; i < num_subdevices; ++i) {
+ dev->subdevices[i].device = dev;
+ dev->subdevices[i].async_dma_dir = DMA_NONE;
+ spin_lock_init(&dev->subdevices[i].spin_lock);
+ dev->subdevices[i].minor = -1;
+ }
+ return 0;
+}
+
+static inline int alloc_private(comedi_device *dev, int size)
+{
+ dev->private = kzalloc(size, GFP_KERNEL);
+ if (!dev->private)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline unsigned int bytes_per_sample(const comedi_subdevice *subd)
+{
+ if (subd->subdev_flags & SDF_LSAMPL)
+ return sizeof(lsampl_t);
+ else
+ return sizeof(sampl_t);
+}
+
+/* must be used in attach to set dev->hw_dev if you wish to dma directly
+into comedi's buffer */
+static inline void comedi_set_hw_dev(comedi_device *dev, struct device *hw_dev)
+{
+ if (dev->hw_dev)
+ put_device(dev->hw_dev);
+
+ dev->hw_dev = hw_dev;
+ if (dev->hw_dev) {
+ dev->hw_dev = get_device(dev->hw_dev);
+ BUG_ON(dev->hw_dev == NULL);
+ }
+}
+
+int comedi_buf_put(comedi_async *async, sampl_t x);
+int comedi_buf_get(comedi_async *async, sampl_t *x);
+
+unsigned int comedi_buf_write_n_available(comedi_async *async);
+unsigned int comedi_buf_write_alloc(comedi_async *async, unsigned int nbytes);
+unsigned int comedi_buf_write_alloc_strict(comedi_async *async,
+ unsigned int nbytes);
+unsigned comedi_buf_write_free(comedi_async *async, unsigned int nbytes);
+unsigned comedi_buf_read_alloc(comedi_async *async, unsigned nbytes);
+unsigned comedi_buf_read_free(comedi_async *async, unsigned int nbytes);
+unsigned int comedi_buf_read_n_available(comedi_async *async);
+void comedi_buf_memcpy_to(comedi_async *async, unsigned int offset,
+ const void *source, unsigned int num_bytes);
+void comedi_buf_memcpy_from(comedi_async *async, unsigned int offset,
+ void *destination, unsigned int num_bytes);
+static inline unsigned comedi_buf_write_n_allocated(comedi_async *async)
+{
+ return async->buf_write_alloc_count - async->buf_write_count;
+}
+static inline unsigned comedi_buf_read_n_allocated(comedi_async *async)
+{
+ return async->buf_read_alloc_count - async->buf_read_count;
+}
+
+void comedi_reset_async_buf(comedi_async *async);
+
+static inline void *comedi_aux_data(int options[], int n)
+{
+ unsigned long address;
+ unsigned long addressLow;
+ int bit_shift;
+ if (sizeof(int) >= sizeof(void *))
+ address = options[COMEDI_DEVCONF_AUX_DATA_LO];
+ else {
+ address = options[COMEDI_DEVCONF_AUX_DATA_HI];
+ bit_shift = sizeof(int) * 8;
+ address <<= bit_shift;
+ addressLow = options[COMEDI_DEVCONF_AUX_DATA_LO];
+ addressLow &= (1UL << bit_shift) - 1;
+ address |= addressLow;
+ }
+ if (n >= 1)
+ address += options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
+ if (n >= 2)
+ address += options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
+ if (n >= 3)
+ address += options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
+ BUG_ON(n > 3);
+ return (void *)address;
+}
+
+int comedi_alloc_board_minor(struct device *hardware_device);
+void comedi_free_board_minor(unsigned minor);
+int comedi_alloc_subdevice_minor(comedi_device *dev, comedi_subdevice *s);
+void comedi_free_subdevice_minor(comedi_subdevice *s);
+int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
+void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
+
+#include "comedi_rt.h"
+
+#endif /* _COMEDIDEV_H */
diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h
new file mode 100644
index 000000000000..fc5fc015726b
--- /dev/null
+++ b/drivers/staging/comedi/comedilib.h
@@ -0,0 +1,192 @@
+/*
+ linux/include/comedilib.h
+ header file for kcomedilib
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1998-2001 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _LINUX_COMEDILIB_H
+#define _LINUX_COMEDILIB_H
+
+#include "comedi.h"
+
+/* Kernel internal stuff. Needed by real-time modules and such. */
+
+#ifndef __KERNEL__
+#error linux/comedilib.h should not be included by non-kernel-space code
+#endif
+
+/* exported functions */
+
+#ifndef KCOMEDILIB_DEPRECATED
+
+typedef void comedi_t;
+
+/* these functions may not be called at real-time priority */
+
+comedi_t *comedi_open(const char *path);
+int comedi_close(comedi_t *dev);
+
+/* these functions may be called at any priority, but may fail at
+ real-time priority */
+
+int comedi_lock(comedi_t *dev, unsigned int subdev);
+int comedi_unlock(comedi_t *dev, unsigned int subdev);
+
+/* these functions may be called at any priority, but you must hold
+ the lock for the subdevice */
+
+int comedi_loglevel(int loglevel);
+void comedi_perror(const char *s);
+char *comedi_strerror(int errnum);
+int comedi_errno(void);
+int comedi_fileno(comedi_t *dev);
+
+int comedi_cancel(comedi_t *dev, unsigned int subdev);
+int comedi_register_callback(comedi_t *dev, unsigned int subdev,
+ unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
+
+int comedi_command(comedi_t *dev, comedi_cmd *cmd);
+int comedi_command_test(comedi_t *dev, comedi_cmd *cmd);
+int comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
+int __comedi_trigger(comedi_t *dev, unsigned int subdev, comedi_trig *it);
+int comedi_data_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ unsigned int range, unsigned int aref, lsampl_t data);
+int comedi_data_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ unsigned int range, unsigned int aref, lsampl_t *data);
+int comedi_data_read_hint(comedi_t *dev, unsigned int subdev,
+ unsigned int chan, unsigned int range, unsigned int aref);
+int comedi_data_read_delayed(comedi_t *dev, unsigned int subdev,
+ unsigned int chan, unsigned int range, unsigned int aref,
+ lsampl_t *data, unsigned int nano_sec);
+int comedi_dio_config(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ unsigned int io);
+int comedi_dio_read(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ unsigned int *val);
+int comedi_dio_write(comedi_t *dev, unsigned int subdev, unsigned int chan,
+ unsigned int val);
+int comedi_dio_bitfield(comedi_t *dev, unsigned int subdev, unsigned int mask,
+ unsigned int *bits);
+int comedi_get_n_subdevices(comedi_t *dev);
+int comedi_get_version_code(comedi_t *dev);
+const char *comedi_get_driver_name(comedi_t *dev);
+const char *comedi_get_board_name(comedi_t *dev);
+int comedi_get_subdevice_type(comedi_t *dev, unsigned int subdevice);
+int comedi_find_subdevice_by_type(comedi_t *dev, int type, unsigned int subd);
+int comedi_get_n_channels(comedi_t *dev, unsigned int subdevice);
+lsampl_t comedi_get_maxdata(comedi_t *dev, unsigned int subdevice, unsigned
+ int chan);
+int comedi_get_n_ranges(comedi_t *dev, unsigned int subdevice, unsigned int
+ chan);
+int comedi_do_insn(comedi_t *dev, comedi_insn *insn);
+int comedi_poll(comedi_t *dev, unsigned int subdev);
+
+/* DEPRECATED functions */
+int comedi_get_rangetype(comedi_t *dev, unsigned int subdevice,
+ unsigned int chan);
+
+/* ALPHA functions */
+unsigned int comedi_get_subdevice_flags(comedi_t *dev, unsigned int subdevice);
+int comedi_get_len_chanlist(comedi_t *dev, unsigned int subdevice);
+int comedi_get_krange(comedi_t *dev, unsigned int subdevice, unsigned int
+ chan, unsigned int range, comedi_krange *krange);
+unsigned int comedi_get_buf_head_pos(comedi_t *dev, unsigned int subdevice);
+int comedi_set_user_int_count(comedi_t *dev, unsigned int subdevice,
+ unsigned int buf_user_count);
+int comedi_map(comedi_t *dev, unsigned int subdev, void *ptr);
+int comedi_unmap(comedi_t *dev, unsigned int subdev);
+int comedi_get_buffer_size(comedi_t *dev, unsigned int subdev);
+int comedi_mark_buffer_read(comedi_t *dev, unsigned int subdevice,
+ unsigned int num_bytes);
+int comedi_mark_buffer_written(comedi_t *d, unsigned int subdevice,
+ unsigned int num_bytes);
+int comedi_get_buffer_contents(comedi_t *dev, unsigned int subdevice);
+int comedi_get_buffer_offset(comedi_t *dev, unsigned int subdevice);
+
+#else
+
+/* these functions may not be called at real-time priority */
+
+int comedi_open(unsigned int minor);
+void comedi_close(unsigned int minor);
+
+/* these functions may be called at any priority, but may fail at
+ real-time priority */
+
+int comedi_lock(unsigned int minor, unsigned int subdev);
+int comedi_unlock(unsigned int minor, unsigned int subdev);
+
+/* these functions may be called at any priority, but you must hold
+ the lock for the subdevice */
+
+int comedi_cancel(unsigned int minor, unsigned int subdev);
+int comedi_register_callback(unsigned int minor, unsigned int subdev,
+ unsigned int mask, int (*cb) (unsigned int, void *), void *arg);
+
+int comedi_command(unsigned int minor, comedi_cmd *cmd);
+int comedi_command_test(unsigned int minor, comedi_cmd *cmd);
+int comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
+int __comedi_trigger(unsigned int minor, unsigned int subdev, comedi_trig *it);
+int comedi_data_write(unsigned int dev, unsigned int subdev, unsigned int chan,
+ unsigned int range, unsigned int aref, lsampl_t data);
+int comedi_data_read(unsigned int dev, unsigned int subdev, unsigned int chan,
+ unsigned int range, unsigned int aref, lsampl_t *data);
+int comedi_dio_config(unsigned int dev, unsigned int subdev, unsigned int chan,
+ unsigned int io);
+int comedi_dio_read(unsigned int dev, unsigned int subdev, unsigned int chan,
+ unsigned int *val);
+int comedi_dio_write(unsigned int dev, unsigned int subdev, unsigned int chan,
+ unsigned int val);
+int comedi_dio_bitfield(unsigned int dev, unsigned int subdev,
+ unsigned int mask, unsigned int *bits);
+int comedi_get_n_subdevices(unsigned int dev);
+int comedi_get_version_code(unsigned int dev);
+char *comedi_get_driver_name(unsigned int dev);
+char *comedi_get_board_name(unsigned int minor);
+int comedi_get_subdevice_type(unsigned int minor, unsigned int subdevice);
+int comedi_find_subdevice_by_type(unsigned int minor, int type,
+ unsigned int subd);
+int comedi_get_n_channels(unsigned int minor, unsigned int subdevice);
+lsampl_t comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned
+ int chan);
+int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int
+ chan);
+int comedi_do_insn(unsigned int minor, comedi_insn *insn);
+int comedi_poll(unsigned int minor, unsigned int subdev);
+
+/* DEPRECATED functions */
+int comedi_get_rangetype(unsigned int minor, unsigned int subdevice,
+ unsigned int chan);
+
+/* ALPHA functions */
+unsigned int comedi_get_subdevice_flags(unsigned int minor, unsigned int
+ subdevice);
+int comedi_get_len_chanlist(unsigned int minor, unsigned int subdevice);
+int comedi_get_krange(unsigned int minor, unsigned int subdevice, unsigned int
+ chan, unsigned int range, comedi_krange *krange);
+unsigned int comedi_get_buf_head_pos(unsigned int minor, unsigned int
+ subdevice);
+int comedi_set_user_int_count(unsigned int minor, unsigned int subdevice,
+ unsigned int buf_user_count);
+int comedi_map(unsigned int minor, unsigned int subdev, void **ptr);
+int comedi_unmap(unsigned int minor, unsigned int subdev);
+
+#endif
+
+#endif
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
new file mode 100644
index 000000000000..36a93b95e3f2
--- /dev/null
+++ b/drivers/staging/comedi/drivers.c
@@ -0,0 +1,846 @@
+/*
+ module/drivers.c
+ functions for manipulating drivers
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define _GNU_SOURCE
+
+#define __NO_VERSION__
+#include "comedi_fops.h"
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include "comedidev.h"
+#include "wrapper.h"
+#include <linux/highmem.h> /* for SuSE brokenness */
+#include <linux/vmalloc.h>
+#include <linux/cdev.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+static int postconfig(comedi_device * dev);
+static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static void *comedi_recognize(comedi_driver * driv, const char *name);
+static void comedi_report_boards(comedi_driver * driv);
+static int poll_invalid(comedi_device * dev, comedi_subdevice * s);
+int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
+ unsigned long new_size);
+
+comedi_driver *comedi_drivers;
+
+int comedi_modprobe(int minor)
+{
+ return -EINVAL;
+}
+
+static void cleanup_device(comedi_device * dev)
+{
+ int i;
+ comedi_subdevice *s;
+
+ if (dev->subdevices) {
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = dev->subdevices + i;
+ comedi_free_subdevice_minor(s);
+ if (s->async) {
+ comedi_buf_alloc(dev, s, 0);
+ kfree(s->async);
+ }
+ }
+ kfree(dev->subdevices);
+ dev->subdevices = NULL;
+ dev->n_subdevices = 0;
+ }
+ if (dev->private) {
+ kfree(dev->private);
+ dev->private = NULL;
+ }
+ dev->driver = 0;
+ dev->board_name = NULL;
+ dev->board_ptr = NULL;
+ dev->iobase = 0;
+ dev->irq = 0;
+ dev->read_subdev = NULL;
+ dev->write_subdev = NULL;
+ dev->open = NULL;
+ dev->close = NULL;
+ comedi_set_hw_dev(dev, NULL);
+}
+
+static void __comedi_device_detach(comedi_device * dev)
+{
+ dev->attached = 0;
+ if (dev->driver) {
+ dev->driver->detach(dev);
+ } else {
+ printk("BUG: dev->driver=NULL in comedi_device_detach()\n");
+ }
+ cleanup_device(dev);
+}
+
+void comedi_device_detach(comedi_device * dev)
+{
+ if (!dev->attached)
+ return;
+ __comedi_device_detach(dev);
+}
+
+int comedi_device_attach(comedi_device * dev, comedi_devconfig * it)
+{
+ comedi_driver *driv;
+ int ret;
+
+ if (dev->attached)
+ return -EBUSY;
+
+ for (driv = comedi_drivers; driv; driv = driv->next) {
+ if (!try_module_get(driv->module)) {
+ printk("comedi: failed to increment module count, skipping\n");
+ continue;
+ }
+ if (driv->num_names) {
+ dev->board_ptr = comedi_recognize(driv, it->board_name);
+ if (dev->board_ptr == NULL) {
+ module_put(driv->module);
+ continue;
+ }
+ } else {
+ if (strcmp(driv->driver_name, it->board_name)) {
+ module_put(driv->module);
+ continue;
+ }
+ }
+ //initialize dev->driver here so comedi_error() can be called from attach
+ dev->driver = driv;
+ ret = driv->attach(dev, it);
+ if (ret < 0) {
+ module_put(dev->driver->module);
+ __comedi_device_detach(dev);
+ return ret;
+ }
+ goto attached;
+ }
+
+ // recognize has failed if we get here
+ // report valid board names before returning error
+ for (driv = comedi_drivers; driv; driv = driv->next) {
+ if (!try_module_get(driv->module)) {
+ printk("comedi: failed to increment module count\n");
+ continue;
+ }
+ comedi_report_boards(driv);
+ module_put(driv->module);
+ }
+ return -EIO;
+
+attached:
+ /* do a little post-config cleanup */
+ ret = postconfig(dev);
+ module_put(dev->driver->module);
+ if (ret < 0) {
+ __comedi_device_detach(dev);
+ return ret;
+ }
+
+ if (!dev->board_name) {
+ printk("BUG: dev->board_name=<%p>\n", dev->board_name);
+ dev->board_name = "BUG";
+ }
+ smp_wmb();
+ dev->attached = 1;
+
+ return 0;
+}
+
+int comedi_driver_register(comedi_driver * driver)
+{
+ driver->next = comedi_drivers;
+ comedi_drivers = driver;
+
+ return 0;
+}
+
+int comedi_driver_unregister(comedi_driver * driver)
+{
+ comedi_driver *prev;
+ int i;
+
+ /* check for devices using this driver */
+ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+ struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
+ comedi_device *dev;
+
+ if(dev_file_info == NULL) continue;
+ dev = dev_file_info->device;
+
+ mutex_lock(&dev->mutex);
+ if (dev->attached && dev->driver == driver) {
+ if (dev->use_count)
+ printk("BUG! detaching device with use_count=%d\n", dev->use_count);
+ comedi_device_detach(dev);
+ }
+ mutex_unlock(&dev->mutex);
+ }
+
+ if (comedi_drivers == driver) {
+ comedi_drivers = driver->next;
+ return 0;
+ }
+
+ for (prev = comedi_drivers; prev->next; prev = prev->next) {
+ if (prev->next == driver) {
+ prev->next = driver->next;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int postconfig(comedi_device * dev)
+{
+ int i;
+ comedi_subdevice *s;
+ comedi_async *async = NULL;
+ int ret;
+
+ for (i = 0; i < dev->n_subdevices; i++) {
+ s = dev->subdevices + i;
+
+ if (s->type == COMEDI_SUBD_UNUSED)
+ continue;
+
+ if (s->len_chanlist == 0)
+ s->len_chanlist = 1;
+
+ if (s->do_cmd) {
+ BUG_ON((s->subdev_flags & (SDF_CMD_READ |
+ SDF_CMD_WRITE)) == 0);
+ BUG_ON(!s->do_cmdtest);
+
+ async = kzalloc(sizeof(comedi_async), GFP_KERNEL);
+ if (async == NULL) {
+ printk("failed to allocate async struct\n");
+ return -ENOMEM;
+ }
+ init_waitqueue_head(&async->wait_head);
+ async->subdevice = s;
+ s->async = async;
+
+#define DEFAULT_BUF_MAXSIZE (64*1024)
+#define DEFAULT_BUF_SIZE (64*1024)
+
+ async->max_bufsize = DEFAULT_BUF_MAXSIZE;
+
+ async->prealloc_buf = NULL;
+ async->prealloc_bufsz = 0;
+ if (comedi_buf_alloc(dev, s, DEFAULT_BUF_SIZE) < 0) {
+ printk("Buffer allocation failed\n");
+ return -ENOMEM;
+ }
+ if (s->buf_change) {
+ ret = s->buf_change(dev, s, DEFAULT_BUF_SIZE);
+ if (ret < 0)
+ return ret;
+ }
+ comedi_alloc_subdevice_minor(dev, s);
+ }
+
+ if (!s->range_table && !s->range_table_list)
+ s->range_table = &range_unknown;
+
+ if (!s->insn_read && s->insn_bits)
+ s->insn_read = insn_rw_emulate_bits;
+ if (!s->insn_write && s->insn_bits)
+ s->insn_write = insn_rw_emulate_bits;
+
+ if (!s->insn_read)
+ s->insn_read = insn_inval;
+ if (!s->insn_write)
+ s->insn_write = insn_inval;
+ if (!s->insn_bits)
+ s->insn_bits = insn_inval;
+ if (!s->insn_config)
+ s->insn_config = insn_inval;
+
+ if (!s->poll)
+ s->poll = poll_invalid;
+ }
+
+ return 0;
+}
+
+// generic recognize function for drivers that register their supported board names
+void *comedi_recognize(comedi_driver * driv, const char *name)
+{
+ unsigned i;
+ const char *const *name_ptr = driv->board_name;
+ for (i = 0; i < driv->num_names; i++) {
+ if (strcmp(*name_ptr, name) == 0)
+ return (void *)name_ptr;
+ name_ptr =
+ (const char *const *)((const char *)name_ptr +
+ driv->offset);
+ }
+
+ return NULL;
+}
+
+void comedi_report_boards(comedi_driver * driv)
+{
+ unsigned int i;
+ const char *const *name_ptr;
+
+ printk("comedi: valid board names for %s driver are:\n",
+ driv->driver_name);
+
+ name_ptr = driv->board_name;
+ for (i = 0; i < driv->num_names; i++) {
+ printk(" %s\n", *name_ptr);
+ name_ptr = (const char **)((char *)name_ptr + driv->offset);
+ }
+
+ if (driv->num_names == 0)
+ printk(" %s\n", driv->driver_name);
+}
+
+static int poll_invalid(comedi_device * dev, comedi_subdevice * s)
+{
+ return -EINVAL;
+}
+
+int insn_inval(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ return -EINVAL;
+}
+
+static int insn_rw_emulate_bits(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ comedi_insn new_insn;
+ int ret;
+ static const unsigned channels_per_bitfield = 32;
+
+ unsigned chan = CR_CHAN(insn->chanspec);
+ const unsigned base_bitfield_channel =
+ (chan < channels_per_bitfield) ? 0 : chan;
+ lsampl_t new_data[2];
+ memset(new_data, 0, sizeof(new_data));
+ memset(&new_insn, 0, sizeof(new_insn));
+ new_insn.insn = INSN_BITS;
+ new_insn.chanspec = base_bitfield_channel;
+ new_insn.n = 2;
+ new_insn.data = new_data;
+ new_insn.subdev = insn->subdev;
+
+ if (insn->insn == INSN_WRITE) {
+ if (!(s->subdev_flags & SDF_WRITABLE))
+ return -EINVAL;
+ new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */
+ new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel)) : 0; /* bits */
+ }
+
+ ret = s->insn_bits(dev, s, &new_insn, new_data);
+ if (ret < 0)
+ return ret;
+
+ if (insn->insn == INSN_READ) {
+ data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1;
+ }
+
+ return 1;
+}
+
+static inline unsigned long uvirt_to_kva(pgd_t * pgd, unsigned long adr)
+{
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+ pud_t *pud;
+
+ if (!pgd_none(*pgd)) {
+ pud = pud_offset(pgd, adr);
+ pmd = pmd_offset(pud, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset_kernel(pmd, adr);
+ pte = *ptep;
+ if (pte_present(pte)) {
+ ret = (unsigned long)
+ page_address(pte_page(pte));
+ ret |= (adr & (PAGE_SIZE - 1));
+ }
+ }
+ }
+ return ret;
+}
+
+static inline unsigned long kvirt_to_kva(unsigned long adr)
+{
+ unsigned long va, kva;
+
+ va = adr;
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+
+ return kva;
+}
+
+int comedi_buf_alloc(comedi_device * dev, comedi_subdevice * s,
+ unsigned long new_size)
+{
+ comedi_async *async = s->async;
+
+ /* Round up new_size to multiple of PAGE_SIZE */
+ new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
+
+ /* if no change is required, do nothing */
+ if (async->prealloc_buf && async->prealloc_bufsz == new_size) {
+ return 0;
+ }
+ // deallocate old buffer
+ if (async->prealloc_buf) {
+ vunmap(async->prealloc_buf);
+ async->prealloc_buf = NULL;
+ async->prealloc_bufsz = 0;
+ }
+ if (async->buf_page_list) {
+ unsigned i;
+ for (i = 0; i < async->n_buf_pages; ++i) {
+ if (async->buf_page_list[i].virt_addr) {
+ mem_map_unreserve(virt_to_page(async->
+ buf_page_list[i].virt_addr));
+ if (s->async_dma_dir != DMA_NONE) {
+ dma_free_coherent(dev->hw_dev,
+ PAGE_SIZE,
+ async->buf_page_list[i].
+ virt_addr,
+ async->buf_page_list[i].
+ dma_addr);
+ } else {
+ free_page((unsigned long)async->
+ buf_page_list[i].virt_addr);
+ }
+ }
+ }
+ vfree(async->buf_page_list);
+ async->buf_page_list = NULL;
+ async->n_buf_pages = 0;
+ }
+ // allocate new buffer
+ if (new_size) {
+ unsigned i = 0;
+ unsigned n_pages = new_size >> PAGE_SHIFT;
+ struct page **pages = NULL;
+
+ async->buf_page_list =
+ vmalloc(sizeof(struct comedi_buf_page) * n_pages);
+ if (async->buf_page_list) {
+ memset(async->buf_page_list, 0,
+ sizeof(struct comedi_buf_page) * n_pages);
+ pages = vmalloc(sizeof(struct page *) * n_pages);
+ }
+ if (pages) {
+ for (i = 0; i < n_pages; i++) {
+ if (s->async_dma_dir != DMA_NONE) {
+ async->buf_page_list[i].virt_addr =
+ dma_alloc_coherent(dev->hw_dev,
+ PAGE_SIZE,
+ &async->buf_page_list[i].
+ dma_addr,
+ GFP_KERNEL | __GFP_COMP);
+ } else {
+ async->buf_page_list[i].virt_addr =
+ (void *)
+ get_zeroed_page(GFP_KERNEL);
+ }
+ if (async->buf_page_list[i].virt_addr == NULL) {
+ break;
+ }
+ mem_map_reserve(virt_to_page(async->
+ buf_page_list[i].virt_addr));
+ pages[i] =
+ virt_to_page(async->buf_page_list[i].
+ virt_addr);
+ }
+ }
+ if (i == n_pages) {
+ async->prealloc_buf =
+ vmap(pages, n_pages, VM_MAP,
+ PAGE_KERNEL_NOCACHE);
+ }
+ if (pages) {
+ vfree(pages);
+ }
+ if (async->prealloc_buf == NULL) {
+ /* Some allocation failed above. */
+ if (async->buf_page_list) {
+ for (i = 0; i < n_pages; i++) {
+ if (async->buf_page_list[i].virt_addr ==
+ NULL) {
+ break;
+ }
+ mem_map_unreserve(virt_to_page(async->
+ buf_page_list[i].
+ virt_addr));
+ if (s->async_dma_dir != DMA_NONE) {
+ dma_free_coherent(dev->hw_dev,
+ PAGE_SIZE,
+ async->buf_page_list[i].
+ virt_addr,
+ async->buf_page_list[i].
+ dma_addr);
+ } else {
+ free_page((unsigned long)async->
+ buf_page_list[i].
+ virt_addr);
+ }
+ }
+ vfree(async->buf_page_list);
+ async->buf_page_list = NULL;
+ }
+ return -ENOMEM;
+ }
+ async->n_buf_pages = n_pages;
+ }
+ async->prealloc_bufsz = new_size;
+
+ return 0;
+}
+
+/* munging is applied to data by core as it passes between user
+ * and kernel space */
+unsigned int comedi_buf_munge(comedi_async * async, unsigned int num_bytes)
+{
+ comedi_subdevice *s = async->subdevice;
+ unsigned int count = 0;
+ const unsigned num_sample_bytes = bytes_per_sample(s);
+
+ if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) {
+ async->munge_count += num_bytes;
+ if ((int)(async->munge_count - async->buf_write_count) > 0)
+ BUG();
+ return num_bytes;
+ }
+ /* don't munge partial samples */
+ num_bytes -= num_bytes % num_sample_bytes;
+ while (count < num_bytes) {
+ int block_size;
+
+ block_size = num_bytes - count;
+ if (block_size < 0) {
+ rt_printk("%s: %s: bug! block_size is negative\n",
+ __FILE__, __func__);
+ break;
+ }
+ if ((int)(async->munge_ptr + block_size -
+ async->prealloc_bufsz) > 0)
+ block_size = async->prealloc_bufsz - async->munge_ptr;
+
+ s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
+ block_size, async->munge_chan);
+
+ smp_wmb(); //barrier insures data is munged in buffer before munge_count is incremented
+
+ async->munge_chan += block_size / num_sample_bytes;
+ async->munge_chan %= async->cmd.chanlist_len;
+ async->munge_count += block_size;
+ async->munge_ptr += block_size;
+ async->munge_ptr %= async->prealloc_bufsz;
+ count += block_size;
+ }
+ if ((int)(async->munge_count - async->buf_write_count) > 0)
+ BUG();
+ return count;
+}
+
+unsigned int comedi_buf_write_n_available(comedi_async * async)
+{
+ unsigned int free_end;
+ unsigned int nbytes;
+
+ if (async == NULL)
+ return 0;
+
+ free_end = async->buf_read_count + async->prealloc_bufsz;
+ nbytes = free_end - async->buf_write_alloc_count;
+ nbytes -= nbytes % bytes_per_sample(async->subdevice);
+ /* barrier insures the read of buf_read_count in this
+ query occurs before any following writes to the buffer which
+ might be based on the return value from this query.
+ */
+ smp_mb();
+ return nbytes;
+}
+
+/* allocates chunk for the writer from free buffer space */
+unsigned int comedi_buf_write_alloc(comedi_async * async, unsigned int nbytes)
+{
+ unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+
+ if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0) {
+ nbytes = free_end - async->buf_write_alloc_count;
+ }
+ async->buf_write_alloc_count += nbytes;
+ /* barrier insures the read of buf_read_count above occurs before
+ we write data to the write-alloc'ed buffer space */
+ smp_mb();
+ return nbytes;
+}
+
+/* allocates nothing unless it can completely fulfill the request */
+unsigned int comedi_buf_write_alloc_strict(comedi_async * async,
+ unsigned int nbytes)
+{
+ unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
+
+ if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0) {
+ nbytes = 0;
+ }
+ async->buf_write_alloc_count += nbytes;
+ /* barrier insures the read of buf_read_count above occurs before
+ we write data to the write-alloc'ed buffer space */
+ smp_mb();
+ return nbytes;
+}
+
+/* transfers a chunk from writer to filled buffer space */
+unsigned comedi_buf_write_free(comedi_async * async, unsigned int nbytes)
+{
+ if ((int)(async->buf_write_count + nbytes -
+ async->buf_write_alloc_count) > 0) {
+ rt_printk
+ ("comedi: attempted to write-free more bytes than have been write-allocated.\n");
+ nbytes = async->buf_write_alloc_count - async->buf_write_count;
+ }
+ async->buf_write_count += nbytes;
+ async->buf_write_ptr += nbytes;
+ comedi_buf_munge(async, async->buf_write_count - async->munge_count);
+ if (async->buf_write_ptr >= async->prealloc_bufsz) {
+ async->buf_write_ptr %= async->prealloc_bufsz;
+ }
+ return nbytes;
+}
+
+/* allocates a chunk for the reader from filled (and munged) buffer space */
+unsigned comedi_buf_read_alloc(comedi_async * async, unsigned nbytes)
+{
+ if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) >
+ 0) {
+ nbytes = async->munge_count - async->buf_read_alloc_count;
+ }
+ async->buf_read_alloc_count += nbytes;
+ /* barrier insures read of munge_count occurs before we actually read
+ data out of buffer */
+ smp_rmb();
+ return nbytes;
+}
+
+/* transfers control of a chunk from reader to free buffer space */
+unsigned comedi_buf_read_free(comedi_async * async, unsigned int nbytes)
+{
+ // barrier insures data has been read out of buffer before read count is incremented
+ smp_mb();
+ if ((int)(async->buf_read_count + nbytes -
+ async->buf_read_alloc_count) > 0) {
+ rt_printk
+ ("comedi: attempted to read-free more bytes than have been read-allocated.\n");
+ nbytes = async->buf_read_alloc_count - async->buf_read_count;
+ }
+ async->buf_read_count += nbytes;
+ async->buf_read_ptr += nbytes;
+ async->buf_read_ptr %= async->prealloc_bufsz;
+ return nbytes;
+}
+
+void comedi_buf_memcpy_to(comedi_async * async, unsigned int offset,
+ const void *data, unsigned int num_bytes)
+{
+ unsigned int write_ptr = async->buf_write_ptr + offset;
+
+ if (write_ptr >= async->prealloc_bufsz)
+ write_ptr %= async->prealloc_bufsz;
+
+ while (num_bytes) {
+ unsigned int block_size;
+
+ if (write_ptr + num_bytes > async->prealloc_bufsz)
+ block_size = async->prealloc_bufsz - write_ptr;
+ else
+ block_size = num_bytes;
+
+ memcpy(async->prealloc_buf + write_ptr, data, block_size);
+
+ data += block_size;
+ num_bytes -= block_size;
+
+ write_ptr = 0;
+ }
+}
+
+void comedi_buf_memcpy_from(comedi_async * async, unsigned int offset,
+ void *dest, unsigned int nbytes)
+{
+ void *src;
+ unsigned int read_ptr = async->buf_read_ptr + offset;
+
+ if (read_ptr >= async->prealloc_bufsz)
+ read_ptr %= async->prealloc_bufsz;
+
+ while (nbytes) {
+ unsigned int block_size;
+
+ src = async->prealloc_buf + read_ptr;
+
+ if (nbytes >= async->prealloc_bufsz - read_ptr)
+ block_size = async->prealloc_bufsz - read_ptr;
+ else
+ block_size = nbytes;
+
+ memcpy(dest, src, block_size);
+ nbytes -= block_size;
+ dest += block_size;
+ read_ptr = 0;
+ }
+}
+
+unsigned int comedi_buf_read_n_available(comedi_async * async)
+{
+ unsigned num_bytes;
+
+ if (async == NULL)
+ return 0;
+ num_bytes = async->munge_count - async->buf_read_count;
+ /* barrier insures the read of munge_count in this
+ query occurs before any following reads of the buffer which
+ might be based on the return value from this query.
+ */
+ smp_rmb();
+ return num_bytes;
+}
+
+int comedi_buf_get(comedi_async * async, sampl_t * x)
+{
+ unsigned int n = comedi_buf_read_n_available(async);
+
+ if (n < sizeof(sampl_t))
+ return 0;
+ comedi_buf_read_alloc(async, sizeof(sampl_t));
+ *x = *(sampl_t *) (async->prealloc_buf + async->buf_read_ptr);
+ comedi_buf_read_free(async, sizeof(sampl_t));
+ return 1;
+}
+
+int comedi_buf_put(comedi_async * async, sampl_t x)
+{
+ unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(sampl_t));
+
+ if (n < sizeof(sampl_t)) {
+ async->events |= COMEDI_CB_ERROR;
+ return 0;
+ }
+ *(sampl_t *) (async->prealloc_buf + async->buf_write_ptr) = x;
+ comedi_buf_write_free(async, sizeof(sampl_t));
+ return 1;
+}
+
+void comedi_reset_async_buf(comedi_async * async)
+{
+ async->buf_write_alloc_count = 0;
+ async->buf_write_count = 0;
+ async->buf_read_alloc_count = 0;
+ async->buf_read_count = 0;
+
+ async->buf_write_ptr = 0;
+ async->buf_read_ptr = 0;
+
+ async->cur_chan = 0;
+ async->scan_progress = 0;
+ async->munge_chan = 0;
+ async->munge_count = 0;
+ async->munge_ptr = 0;
+
+ async->events = 0;
+}
+
+int comedi_auto_config(struct device *hardware_device, const char *board_name, const int *options, unsigned num_options)
+{
+ comedi_devconfig it;
+ int minor;
+ struct comedi_device_file_info *dev_file_info;
+ int retval;
+
+ minor = comedi_alloc_board_minor(hardware_device);
+ if(minor < 0) return minor;
+ dev_set_drvdata(hardware_device, (void*)(unsigned long)minor);
+
+ dev_file_info = comedi_get_device_file_info(minor);
+
+ memset(&it, 0, sizeof(it));
+ strncpy(it.board_name, board_name, COMEDI_NAMELEN);
+ it.board_name[COMEDI_NAMELEN - 1] = '\0';
+ BUG_ON(num_options > COMEDI_NDEVCONFOPTS);
+ memcpy(it.options, options, num_options * sizeof(int));
+
+ mutex_lock(&dev_file_info->device->mutex);
+ retval = comedi_device_attach(dev_file_info->device, &it);
+ mutex_unlock(&dev_file_info->device->mutex);
+ if(retval < 0)
+ {
+ comedi_free_board_minor(minor);
+ }
+ return retval;
+}
+
+void comedi_auto_unconfig(struct device *hardware_device)
+{
+ unsigned long minor = (unsigned long)dev_get_drvdata(hardware_device);
+
+ BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
+
+ comedi_free_board_minor(minor);
+}
+
+int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
+{
+ int options[2];
+
+ // pci bus
+ options[0] = pcidev->bus->number;
+ // pci slot
+ options[1] = PCI_SLOT(pcidev->devfn);
+
+ return comedi_auto_config(&pcidev->dev, board_name, options, sizeof(options) / sizeof(options[0]));
+}
+
+void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
+{
+ comedi_auto_unconfig(&pcidev->dev);
+}
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile
new file mode 100644
index 000000000000..eb7a615e0859
--- /dev/null
+++ b/drivers/staging/comedi/drivers/Makefile
@@ -0,0 +1,21 @@
+# Makefile for individual comedi drivers
+#
+
+# Comedi "helper" modules
+obj-$(CONFIG_COMEDI) += comedi_fc.o
+obj-$(CONFIG_COMEDI) += comedi_bond.o
+obj-$(CONFIG_COMEDI) += comedi_test.o
+obj-$(CONFIG_COMEDI) += comedi_parport.o
+
+# Comedi PCI drivers
+obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o
+obj-$(CONFIG_COMEDI_PCI_DRIVERS) += icp_multi.o
+obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me_daq.o
+obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me4000.o
+obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rtd520.o
+obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s626.o
+
+# Comedi USB drivers
+obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o
+obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbduxfast.o
+obj-$(CONFIG_COMEDI_USB_DRIVERS) += dt9812.o
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
new file mode 100644
index 000000000000..9e5496f4f1ae
--- /dev/null
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -0,0 +1,535 @@
+/*
+ comedi/drivers/comedi_bond.c
+ A Comedi driver to 'bond' or merge multiple drivers and devices as one.
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ Copyright (C) 2005 Calin A. Culianu <calin@ajvar.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+/*
+Driver: comedi_bond
+Description: A driver to 'bond' (merge) multiple subdevices from multiple
+ devices together as one.
+Devices:
+Author: ds
+Updated: Mon, 10 Oct 00:18:25 -0500
+Status: works
+
+This driver allows you to 'bond' (merge) multiple comedi subdevices
+(coming from possibly difference boards and/or drivers) together. For
+example, if you had a board with 2 different DIO subdevices, and
+another with 1 DIO subdevice, you could 'bond' them with this driver
+so that they look like one big fat DIO subdevice. This makes writing
+applications slightly easier as you don't have to worry about managing
+different subdevices in the application -- you just worry about
+indexing one linear array of channel id's.
+
+Right now only DIO subdevices are supported as that's the personal itch
+I am scratching with this driver. If you want to add support for AI and AO
+subdevs, go right on ahead and do so!
+
+Commands aren't supported -- although it would be cool if they were.
+
+Configuration Options:
+ List of comedi-minors to bond. All subdevices of the same type
+ within each minor will be concatenated together in the order given here.
+*/
+
+/*
+ * The previous block comment is used to automatically generate
+ * documentation in Comedi and Comedilib. The fields:
+ *
+ * Driver: the name of the driver
+ * Description: a short phrase describing the driver. Don't list boards.
+ * Devices: a full list of the boards that attempt to be supported by
+ * the driver. Format is "(manufacturer) board name [comedi name]",
+ * where comedi_name is the name that is used to configure the board.
+ * See the comment near board_name: in the comedi_driver structure
+ * below. If (manufacturer) or [comedi name] is missing, the previous
+ * value is used.
+ * Author: you
+ * Updated: date when the _documentation_ was last updated. Use 'date -R'
+ * to get a value for this.
+ * Status: a one-word description of the status. Valid values are:
+ * works - driver works correctly on most boards supported, and
+ * passes comedi_test.
+ * unknown - unknown. Usually put there by ds.
+ * experimental - may not work in any particular release. Author
+ * probably wants assistance testing it.
+ * bitrotten - driver has not been update in a long time, probably
+ * doesn't work, and probably is missing support for significant
+ * Comedi interface features.
+ * untested - author probably wrote it "blind", and is believed to
+ * work, but no confirmation.
+ *
+ * These headers should be followed by a blank line, and any comments
+ * you wish to say about the driver. The comment area is the place
+ * to put any known bugs, limitations, unsupported features, supported
+ * command triggers, whether or not commands are supported on particular
+ * subdevices, etc.
+ *
+ * Somewhere in the comment should be information about configuration
+ * options that are used with comedi_config.
+ */
+
+#include "../comedilib.h"
+#include "../comedidev.h"
+#include <linux/string.h>
+
+/* The maxiumum number of channels per subdevice. */
+#define MAX_CHANS 256
+
+#define MODULE_NAME "comedi_bond"
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+#ifndef STR
+# define STR1(x) #x
+# define STR(x) STR1(x)
+#endif
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful"
+ "only to developers.");
+
+#define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x)
+#define DEBUG(x...) \
+ do { \
+ if (debug) \
+ printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \
+ } while (0)
+#define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x)
+#define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x)
+MODULE_AUTHOR("Calin A. Culianu");
+MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI "
+ "devices together as one. In the words of John Lennon: "
+ "'And the world will live as one...'");
+
+/*
+ * Board descriptions for two imaginary boards. Describing the
+ * boards in this way is optional, and completely driver-dependent.
+ * Some drivers use arrays such as this, other do not.
+ */
+struct BondingBoard {
+ const char *name;
+};
+
+static const struct BondingBoard bondingBoards[] = {
+ {
+ .name = MODULE_NAME,
+ },
+};
+
+/*
+ * Useful for shorthand access to the particular board structure
+ */
+#define thisboard ((const struct BondingBoard *)dev->board_ptr)
+
+struct BondedDevice {
+ comedi_t *dev;
+ unsigned minor;
+ unsigned subdev;
+ unsigned subdev_type;
+ unsigned nchans;
+ unsigned chanid_offset; /* The offset into our unified linear
+ channel-id's of chanid 0 on this
+ subdevice. */
+};
+
+/* this structure is for data unique to this hardware driver. If
+ several hardware drivers keep similar information in this structure,
+ feel free to suggest moving the variable to the comedi_device struct. */
+struct Private {
+# define MAX_BOARD_NAME 256
+ char name[MAX_BOARD_NAME];
+ struct BondedDevice **devs;
+ unsigned ndevs;
+ struct BondedDevice *chanIdDevMap[MAX_CHANS];
+ unsigned nchans;
+};
+
+/*
+ * most drivers define the following macro to make it easy to
+ * access the private structure.
+ */
+#define devpriv ((struct Private *)dev->private)
+
+/*
+ * The comedi_driver structure tells the Comedi core module
+ * which functions to call to configure/deconfigure (attach/detach)
+ * the board, and also about the kernel module that contains
+ * the device code.
+ */
+static int bonding_attach(comedi_device *dev, comedi_devconfig *it);
+static int bonding_detach(comedi_device *dev);
+/** Build Private array of all devices.. */
+static int doDevConfig(comedi_device *dev, comedi_devconfig *it);
+static void doDevUnconfig(comedi_device *dev);
+/* Ugly implementation of realloc that always copies memory around -- I'm lazy,
+ * what can I say? I like to do wasteful memcopies.. :) */
+static void *Realloc(const void *ptr, size_t len, size_t old_len);
+
+static comedi_driver driver_bonding = {
+ .driver_name = MODULE_NAME,
+ .module = THIS_MODULE,
+ .attach = bonding_attach,
+ .detach = bonding_detach,
+ /* It is not necessary to implement the following members if you are
+ * writing a driver for a ISA PnP or PCI card */
+ /* Most drivers will support multiple types of boards by
+ * having an array of board structures. These were defined
+ * in skel_boards[] above. Note that the element 'name'
+ * was first in the structure -- Comedi uses this fact to
+ * extract the name of the board without knowing any details
+ * about the structure except for its length.
+ * When a device is attached (by comedi_config), the name
+ * of the device is given to Comedi, and Comedi tries to
+ * match it by going through the list of board names. If
+ * there is a match, the address of the pointer is put
+ * into dev->board_ptr and driver->attach() is called.
+ *
+ * Note that these are not necessary if you can determine
+ * the type of board in software. ISA PnP, PCI, and PCMCIA
+ * devices are such boards.
+ */
+ .board_name = &bondingBoards[0].name,
+ .offset = sizeof(struct BondingBoard),
+ .num_names = sizeof(bondingBoards) / sizeof(struct BondingBoard),
+};
+
+static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data);
+static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data);
+
+/*
+ * Attach is called by the Comedi core to configure the driver
+ * for a particular board. If you specified a board_name array
+ * in the driver structure, dev->board_ptr contains that
+ * address.
+ */
+static int bonding_attach(comedi_device *dev, comedi_devconfig *it)
+{
+ comedi_subdevice *s;
+
+ LOG_MSG("comedi%d\n", dev->minor);
+
+ /*
+ * Allocate the private structure area. alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_private(dev, sizeof(struct Private)) < 0)
+ return -ENOMEM;
+
+ /*
+ * Setup our bonding from config params.. sets up our Private struct..
+ */
+ if (!doDevConfig(dev, it))
+ return -EINVAL;
+
+ /*
+ * Initialize dev->board_name. Note that we can use the "thisboard"
+ * macro now, since we just initialized it in the last line.
+ */
+ dev->board_name = devpriv->name;
+
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_subdevices(dev, 1) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = devpriv->nchans;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = bonding_dio_insn_bits;
+ s->insn_config = bonding_dio_insn_config;
+
+ LOG_MSG("attached with %u DIO channels coming from %u different "
+ "subdevices all bonded together. "
+ "John Lennon would be proud!\n",
+ devpriv->nchans, devpriv->ndevs);
+
+ return 1;
+}
+
+/*
+ * _detach is called to deconfigure a device. It should deallocate
+ * resources.
+ * This function is also called when _attach() fails, so it should be
+ * careful not to release resources that were not necessarily
+ * allocated by _attach(). dev->private and dev->subdevices are
+ * deallocated automatically by the core.
+ */
+static int bonding_detach(comedi_device *dev)
+{
+ LOG_MSG("comedi%d: remove\n", dev->minor);
+ doDevUnconfig(dev);
+ return 0;
+}
+
+/* DIO devices are slightly special. Although it is possible to
+ * implement the insn_read/insn_write interface, it is much more
+ * useful to applications if you implement the insn_bits interface.
+ * This allows packed reading/writing of the DIO channels. The
+ * comedi core can convert between insn_bits and insn_read/write */
+static int bonding_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+#define LSAMPL_BITS (sizeof(lsampl_t)*8)
+ unsigned nchans = LSAMPL_BITS, num_done = 0, i;
+ if (insn->n != 2)
+ return -EINVAL;
+
+ if (devpriv->nchans < nchans)
+ nchans = devpriv->nchans;
+
+ /* The insn data is a mask in data[0] and the new data
+ * in data[1], each channel cooresponding to a bit. */
+ for (i = 0; num_done < nchans && i < devpriv->ndevs; ++i) {
+ struct BondedDevice *bdev = devpriv->devs[i];
+ /* Grab the channel mask and data of only the bits corresponding
+ to this subdevice.. need to shift them to zero position of
+ course. */
+ /* Bits corresponding to this subdev. */
+ lsampl_t subdevMask = ((1 << bdev->nchans) - 1);
+ lsampl_t writeMask, dataBits;
+
+ /* Argh, we have >= LSAMPL_BITS chans.. take all bits */
+ if (bdev->nchans >= LSAMPL_BITS)
+ subdevMask = (lsampl_t) (-1);
+
+ writeMask = (data[0] >> num_done) & subdevMask;
+ dataBits = (data[1] >> num_done) & subdevMask;
+
+ /* Read/Write the new digital lines */
+ if (comedi_dio_bitfield(bdev->dev, bdev->subdev, writeMask,
+ &dataBits) != 2)
+ return -EINVAL;
+
+ /* Make room for the new bits in data[1], the return value */
+ data[1] &= ~(subdevMask << num_done);
+ /* Put the bits in the return value */
+ data[1] |= (dataBits & subdevMask) << num_done;
+ /* Save the new bits to the saved state.. */
+ s->state = data[1];
+
+ num_done += bdev->nchans;
+ }
+
+ return insn->n;
+}
+
+static int bonding_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
+ unsigned int io;
+ struct BondedDevice *bdev;
+
+ if (chan < 0 || chan >= devpriv->nchans)
+ return -EINVAL;
+ bdev = devpriv->chanIdDevMap[chan];
+
+ /* The input or output configuration of each digital line is
+ * configured by a special insn_config instruction. chanspec
+ * contains the channel to be changed, and data[0] contains the
+ * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_OUTPUT:
+ io = COMEDI_OUTPUT; /* is this really necessary? */
+ io_bits |= 1 << chan;
+ break;
+ case INSN_CONFIG_DIO_INPUT:
+ io = COMEDI_INPUT; /* is this really necessary? */
+ io_bits &= ~(1 << chan);
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] =
+ (io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ return insn->n;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ /* 'real' channel id for this subdev.. */
+ chan -= bdev->chanid_offset;
+ ret = comedi_dio_config(bdev->dev, bdev->subdev, chan, io);
+ if (ret != 1)
+ return -EINVAL;
+ /* Finally, save the new io_bits values since we didn't get
+ an error above. */
+ s->io_bits = io_bits;
+ return insn->n;
+}
+
+static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
+{
+ void *newmem = kmalloc(newlen, GFP_KERNEL);
+
+ if (newmem && oldmem)
+ memcpy(newmem, oldmem, min(oldlen, newlen));
+ kfree(oldmem);
+ return newmem;
+}
+
+static int doDevConfig(comedi_device *dev, comedi_devconfig *it)
+{
+ int i;
+ comedi_t *devs_opened[COMEDI_NUM_BOARD_MINORS];
+
+ memset(devs_opened, 0, sizeof(devs_opened));
+ devpriv->name[0] = 0;;
+ /* Loop through all comedi devices specified on the command-line,
+ building our device list */
+ for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) {
+ char file[] = "/dev/comediXXXXXX";
+ int minor = it->options[i];
+ comedi_t *d;
+ int sdev = -1, nchans, tmp;
+ struct BondedDevice *bdev = NULL;
+
+ if (minor < 0 || minor > COMEDI_NUM_BOARD_MINORS) {
+ ERROR("Minor %d is invalid!\n", minor);
+ return 0;
+ }
+ if (minor == dev->minor) {
+ ERROR("Cannot bond this driver to itself!\n");
+ return 0;
+ }
+ if (devs_opened[minor]) {
+ ERROR("Minor %d specified more than once!\n", minor);
+ return 0;
+ }
+
+ snprintf(file, sizeof(file), "/dev/comedi%u", minor);
+ file[sizeof(file) - 1] = 0;
+
+ d = devs_opened[minor] = comedi_open(file);
+
+ if (!d) {
+ ERROR("Minor %u could not be opened\n", minor);
+ return 0;
+ }
+
+ /* Do DIO, as that's all we support now.. */
+ while ((sdev = comedi_find_subdevice_by_type(d, COMEDI_SUBD_DIO,
+ sdev + 1)) > -1) {
+ nchans = comedi_get_n_channels(d, sdev);
+ if (nchans <= 0) {
+ ERROR("comedi_get_n_channels() returned %d "
+ "on minor %u subdev %d!\n",
+ nchans, minor, sdev);
+ return 0;
+ }
+ bdev = kmalloc(sizeof(*bdev), GFP_KERNEL);
+ if (!bdev) {
+ ERROR("Out of memory.\n");
+ return 0;
+ }
+ bdev->dev = d;
+ bdev->minor = minor;
+ bdev->subdev = sdev;
+ bdev->subdev_type = COMEDI_SUBD_DIO;
+ bdev->nchans = nchans;
+ bdev->chanid_offset = devpriv->nchans;
+
+ /* map channel id's to BondedDevice * pointer.. */
+ while (nchans--)
+ devpriv->chanIdDevMap[devpriv->nchans++] = bdev;
+
+ /* Now put bdev pointer at end of devpriv->devs array
+ * list.. */
+
+ /* ergh.. ugly.. we need to realloc :( */
+ tmp = devpriv->ndevs * sizeof(bdev);
+ devpriv->devs =
+ Realloc(devpriv->devs,
+ ++devpriv->ndevs * sizeof(bdev), tmp);
+ if (!devpriv->devs) {
+ ERROR("Could not allocate memory. "
+ "Out of memory?");
+ return 0;
+ }
+
+ devpriv->devs[devpriv->ndevs - 1] = bdev;
+ {
+ /** Append dev:subdev to devpriv->name */
+ char buf[20];
+ int left =
+ MAX_BOARD_NAME - strlen(devpriv->name) -
+ 1;
+ snprintf(buf, sizeof(buf), "%d:%d ", dev->minor,
+ bdev->subdev);
+ buf[sizeof(buf) - 1] = 0;
+ strncat(devpriv->name, buf, left);
+ }
+
+ }
+ }
+
+ if (!devpriv->nchans) {
+ ERROR("No channels found!\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static void doDevUnconfig(comedi_device *dev)
+{
+ unsigned long devs_closed = 0;
+
+ if (devpriv) {
+ while (devpriv->ndevs-- && devpriv->devs) {
+ struct BondedDevice *bdev;
+
+ bdev = devpriv->devs[devpriv->ndevs];
+ if (!bdev)
+ continue;
+ if (!(devs_closed & (0x1 << bdev->minor))) {
+ comedi_close(bdev->dev);
+ devs_closed |= (0x1 << bdev->minor);
+ }
+ kfree(bdev);
+ }
+ kfree(devpriv->devs);
+ devpriv->devs = NULL;
+ kfree(devpriv);
+ dev->private = NULL;
+ }
+}
+
+static int __init init(void)
+{
+ return comedi_driver_register(&driver_bonding);
+}
+
+static void __exit cleanup(void)
+{
+ comedi_driver_unregister(&driver_bonding);
+}
+
+module_init(init);
+module_exit(cleanup);
diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c
new file mode 100644
index 000000000000..cd74dbe5417d
--- /dev/null
+++ b/drivers/staging/comedi/drivers/comedi_fc.c
@@ -0,0 +1,118 @@
+/*
+ comedi/drivers/comedi_fc.c
+
+ This is a place for code driver writers wish to share between
+ two or more drivers. fc is short
+ for frank-common.
+
+ Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ Copyright (C) 2002 Frank Mori Hess
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+************************************************************************/
+
+#include "../comedidev.h"
+
+#include "comedi_fc.h"
+
+static void increment_scan_progress(comedi_subdevice *subd,
+ unsigned int num_bytes)
+{
+ comedi_async *async = subd->async;
+ unsigned int scan_length = cfc_bytes_per_scan(subd);
+
+ async->scan_progress += num_bytes;
+ if (async->scan_progress >= scan_length) {
+ async->scan_progress %= scan_length;
+ async->events |= COMEDI_CB_EOS;
+ }
+}
+
+/* Writes an array of data points to comedi's buffer */
+unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd, void *data,
+ unsigned int num_bytes)
+{
+ comedi_async *async = subd->async;
+ unsigned int retval;
+
+ if (num_bytes == 0)
+ return 0;
+
+ retval = comedi_buf_write_alloc(async, num_bytes);
+ if (retval != num_bytes) {
+ rt_printk("comedi: buffer overrun\n");
+ async->events |= COMEDI_CB_OVERFLOW;
+ return 0;
+ }
+
+ comedi_buf_memcpy_to(async, 0, data, num_bytes);
+ comedi_buf_write_free(async, num_bytes);
+ increment_scan_progress(subd, num_bytes);
+ async->events |= COMEDI_CB_BLOCK;
+
+ return num_bytes;
+}
+EXPORT_SYMBOL(cfc_write_array_to_buffer);
+
+unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd, void *data,
+ unsigned int num_bytes)
+{
+ comedi_async *async = subd->async;
+
+ if (num_bytes == 0)
+ return 0;
+
+ num_bytes = comedi_buf_read_alloc(async, num_bytes);
+ comedi_buf_memcpy_from(async, 0, data, num_bytes);
+ comedi_buf_read_free(async, num_bytes);
+ increment_scan_progress(subd, num_bytes);
+ async->events |= COMEDI_CB_BLOCK;
+
+ return num_bytes;
+}
+EXPORT_SYMBOL(cfc_read_array_from_buffer);
+
+unsigned int cfc_handle_events(comedi_device *dev, comedi_subdevice *subd)
+{
+ unsigned int events = subd->async->events;
+
+ if (events == 0)
+ return events;
+
+ if (events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
+ subd->cancel(dev, subd);
+
+ comedi_event(dev, subd);
+
+ return events;
+}
+EXPORT_SYMBOL(cfc_handle_events);
+
+MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");
+MODULE_DESCRIPTION("Shared functions for Comedi low-level drivers");
+MODULE_LICENSE("GPL");
+
+static int __init comedi_fc_init_module(void)
+{
+ return 0;
+}
+
+static void __exit comedi_fc_cleanup_module(void)
+{
+}
+
+module_init(comedi_fc_init_module);
+module_exit(comedi_fc_cleanup_module);
diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h
new file mode 100644
index 000000000000..6952fe20f273
--- /dev/null
+++ b/drivers/staging/comedi/drivers/comedi_fc.h
@@ -0,0 +1,76 @@
+/*
+ comedi_fc.h
+
+ This is a place for code driver writers wish to share between
+ two or more drivers. These functions are meant to be used only
+ by drivers, they are NOT part of the kcomedilib API!
+
+ Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ Copyright (C) 2002 Frank Mori Hess
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+************************************************************************/
+
+#ifndef _COMEDI_FC_H
+#define _COMEDI_FC_H
+
+#include "../comedidev.h"
+
+/* Writes an array of data points to comedi's buffer */
+extern unsigned int cfc_write_array_to_buffer(comedi_subdevice *subd,
+ void *data,
+ unsigned int num_bytes);
+
+static inline unsigned int cfc_write_to_buffer(comedi_subdevice *subd,
+ sampl_t data)
+{
+ return cfc_write_array_to_buffer(subd, &data, sizeof(data));
+};
+
+static inline unsigned int cfc_write_long_to_buffer(comedi_subdevice *subd,
+ lsampl_t data)
+{
+ return cfc_write_array_to_buffer(subd, &data, sizeof(data));
+};
+
+extern unsigned int cfc_read_array_from_buffer(comedi_subdevice *subd,
+ void *data,
+ unsigned int num_bytes);
+
+extern unsigned int cfc_handle_events(comedi_device *dev,
+ comedi_subdevice *subd);
+
+static inline unsigned int cfc_bytes_per_scan(comedi_subdevice *subd)
+{
+ int num_samples;
+ int bits_per_sample;
+
+ switch (subd->type) {
+ case COMEDI_SUBD_DI:
+ case COMEDI_SUBD_DO:
+ case COMEDI_SUBD_DIO:
+ bits_per_sample = 8 * bytes_per_sample(subd);
+ num_samples = (subd->async->cmd.chanlist_len +
+ bits_per_sample - 1) / bits_per_sample;
+ break;
+ default:
+ num_samples = subd->async->cmd.chanlist_len;
+ break;
+ }
+ return num_samples * bytes_per_sample(subd);
+}
+
+#endif /* _COMEDI_FC_H */
diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c
new file mode 100644
index 000000000000..ba838fffa29e
--- /dev/null
+++ b/drivers/staging/comedi/drivers/comedi_parport.c
@@ -0,0 +1,390 @@
+/*
+ comedi/drivers/comedi_parport.c
+ hardware driver for standard parallel port
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1998,2001 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+/*
+Driver: comedi_parport
+Description: Standard PC parallel port
+Author: ds
+Status: works in immediate mode
+Devices: [standard] parallel port (comedi_parport)
+Updated: Tue, 30 Apr 2002 21:11:45 -0700
+
+A cheap and easy way to get a few more digital I/O lines. Steal
+additional parallel ports from old computers or your neighbors'
+computers.
+
+Option list:
+ 0: I/O port base for the parallel port.
+ 1: IRQ
+
+Parallel Port Lines:
+
+pin subdev chan aka
+--- ------ ---- ---
+1 2 0 strobe
+2 0 0 data 0
+3 0 1 data 1
+4 0 2 data 2
+5 0 3 data 3
+6 0 4 data 4
+7 0 5 data 5
+8 0 6 data 6
+9 0 7 data 7
+10 1 3 acknowledge
+11 1 4 busy
+12 1 2 output
+13 1 1 printer selected
+14 2 1 auto LF
+15 1 0 error
+16 2 2 init
+17 2 3 select printer
+18-25 ground
+
+Notes:
+
+Subdevices 0 is digital I/O, subdevice 1 is digital input, and
+subdevice 2 is digital output. Unlike other Comedi devices,
+subdevice 0 defaults to output.
+
+Pins 13 and 14 are inverted once by Comedi and once by the
+hardware, thus cancelling the effect.
+
+Pin 1 is a strobe, thus acts like one. There's no way in software
+to change this, at least on a standard parallel port.
+
+Subdevice 3 pretends to be a digital input subdevice, but it always
+returns 0 when read. However, if you run a command with
+scan_begin_src=TRIG_EXT, it uses pin 10 as a external triggering
+pin, which can be used to wake up tasks.
+*/
+/*
+ see http://www.beyondlogic.org/ for information.
+ or http://www.linux-magazin.de/ausgabe/1999/10/IO/io.html
+ */
+
+#include "../comedidev.h"
+#include <linux/ioport.h>
+
+#define PARPORT_SIZE 3
+
+#define PARPORT_A 0
+#define PARPORT_B 1
+#define PARPORT_C 2
+
+static int parport_attach(comedi_device *dev, comedi_devconfig *it);
+static int parport_detach(comedi_device *dev);
+static comedi_driver driver_parport = {
+ .driver_name = "comedi_parport",
+ .module = THIS_MODULE,
+ .attach = parport_attach,
+ .detach = parport_detach,
+};
+
+COMEDI_INITCLEANUP(driver_parport);
+
+struct parport_private {
+ unsigned int a_data;
+ unsigned int c_data;
+ int enable_irq;
+};
+#define devpriv ((struct parport_private *)(dev->private))
+
+static int parport_insn_a(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ if (data[0]) {
+ devpriv->a_data &= ~data[0];
+ devpriv->a_data |= (data[0] & data[1]);
+
+ outb(devpriv->a_data, dev->iobase + PARPORT_A);
+ }
+
+ data[1] = inb(dev->iobase + PARPORT_A);
+
+ return 2;
+}
+
+static int parport_insn_config_a(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ if (data[0]) {
+ s->io_bits = 0xff;
+ devpriv->c_data &= ~(1 << 5);
+ } else {
+ s->io_bits = 0;
+ devpriv->c_data |= (1 << 5);
+ }
+ outb(devpriv->c_data, dev->iobase + PARPORT_C);
+
+ return 1;
+}
+
+static int parport_insn_b(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ if (data[0]) {
+ /* should writes be ignored? */
+ /* anyone??? */
+ }
+
+ data[1] = (inb(dev->iobase + PARPORT_B) >> 3);
+
+ return 2;
+}
+
+static int parport_insn_c(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ data[0] &= 0x0f;
+ if (data[0]) {
+ devpriv->c_data &= ~data[0];
+ devpriv->c_data |= (data[0] & data[1]);
+
+ outb(devpriv->c_data, dev->iobase + PARPORT_C);
+ }
+
+ data[1] = devpriv->c_data & 0xf;
+
+ return 2;
+}
+
+static int parport_intr_insn(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ if (insn->n < 1)
+ return -EINVAL;
+
+ data[1] = 0;
+ return 2;
+}
+
+static int parport_intr_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ comedi_cmd *cmd)
+{
+ int err = 0;
+ int tmp;
+
+ /* step 1 */
+
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW;
+ if (!cmd->start_src || tmp != cmd->start_src)
+ err++;
+
+ tmp = cmd->scan_begin_src;
+ cmd->scan_begin_src &= TRIG_EXT;
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+ err++;
+
+ tmp = cmd->convert_src;
+ cmd->convert_src &= TRIG_FOLLOW;
+ if (!cmd->convert_src || tmp != cmd->convert_src)
+ err++;
+
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+ err++;
+
+ tmp = cmd->stop_src;
+ cmd->stop_src &= TRIG_NONE;
+ if (!cmd->stop_src || tmp != cmd->stop_src)
+ err++;
+
+ if (err)
+ return 1;
+
+ /* step 2: ignored */
+
+ if (err)
+ return 2;
+
+ /* step 3: */
+
+ if (cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+ if (cmd->scan_begin_arg != 0) {
+ cmd->scan_begin_arg = 0;
+ err++;
+ }
+ if (cmd->convert_arg != 0) {
+ cmd->convert_arg = 0;
+ err++;
+ }
+ if (cmd->scan_end_arg != 1) {
+ cmd->scan_end_arg = 1;
+ err++;
+ }
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+
+ if (err)
+ return 3;
+
+ /* step 4: ignored */
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int parport_intr_cmd(comedi_device *dev, comedi_subdevice *s)
+{
+ devpriv->c_data |= 0x10;
+ outb(devpriv->c_data, dev->iobase + PARPORT_C);
+
+ devpriv->enable_irq = 1;
+
+ return 0;
+}
+
+static int parport_intr_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+ printk(KERN_DEBUG "parport_intr_cancel()\n");
+
+ devpriv->c_data &= ~0x10;
+ outb(devpriv->c_data, dev->iobase + PARPORT_C);
+
+ devpriv->enable_irq = 0;
+
+ return 0;
+}
+
+static irqreturn_t parport_interrupt(int irq, void *d PT_REGS_ARG)
+{
+ comedi_device *dev = d;
+ comedi_subdevice *s = dev->subdevices + 3;
+
+ if (!devpriv->enable_irq) {
+ printk(KERN_ERR "comedi_parport: bogus irq, ignored\n");
+ return IRQ_NONE;
+ }
+
+ comedi_buf_put(s->async, 0);
+ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+
+ comedi_event(dev, s);
+ return IRQ_HANDLED;
+}
+
+static int parport_attach(comedi_device *dev, comedi_devconfig *it)
+{
+ int ret;
+ unsigned int irq;
+ unsigned long iobase;
+ comedi_subdevice *s;
+
+ iobase = it->options[0];
+ printk(KERN_INFO "comedi%d: parport: 0x%04lx ", dev->minor, iobase);
+ if (!request_region(iobase, PARPORT_SIZE, "parport (comedi)")) {
+ printk("I/O port conflict\n");
+ return -EIO;
+ }
+ dev->iobase = iobase;
+
+ irq = it->options[1];
+ if (irq) {
+ printk(" irq=%u", irq);
+ ret = comedi_request_irq(irq, parport_interrupt, 0,
+ "comedi_parport", dev);
+ if (ret < 0) {
+ printk(" irq not available\n");
+ return -EINVAL;
+ }
+ dev->irq = irq;
+ }
+ dev->board_name = "parport";
+
+ ret = alloc_subdevices(dev, 4);
+ if (ret < 0)
+ return ret;
+ ret = alloc_private(dev, sizeof(struct parport_private));
+ if (ret < 0)
+ return ret;
+
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_insn_a;
+ s->insn_config = parport_insn_config_a;
+
+ s = dev->subdevices + 1;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 5;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_insn_b;
+
+ s = dev->subdevices + 2;
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_insn_c;
+
+ s = dev->subdevices + 3;
+ if (irq) {
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->n_chan = 1;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = parport_intr_insn;
+ s->do_cmdtest = parport_intr_cmdtest;
+ s->do_cmd = parport_intr_cmd;
+ s->cancel = parport_intr_cancel;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ devpriv->a_data = 0;
+ outb(devpriv->a_data, dev->iobase + PARPORT_A);
+ devpriv->c_data = 0;
+ outb(devpriv->c_data, dev->iobase + PARPORT_C);
+
+ printk("\n");
+ return 1;
+}
+
+static int parport_detach(comedi_device *dev)
+{
+ printk("comedi%d: parport: remove\n", dev->minor);
+
+ if (dev->iobase)
+ release_region(dev->iobase, PARPORT_SIZE);
+
+ if (dev->irq)
+ comedi_free_irq(dev->irq, dev);
+
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/comedi_pci.h b/drivers/staging/comedi/drivers/comedi_pci.h
new file mode 100644
index 000000000000..c14a036a0536
--- /dev/null
+++ b/drivers/staging/comedi/drivers/comedi_pci.h
@@ -0,0 +1,60 @@
+/*
+ comedi/drivers/comedi_pci.h
+ Various PCI functions for drivers.
+
+ Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/>
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _COMEDI_PCI_H_
+#define _COMEDI_PCI_H_
+
+#include <linux/pci.h>
+
+/*
+ * Enable the PCI device and request the regions.
+ */
+static inline int comedi_pci_enable(struct pci_dev *pdev, const char *res_name)
+{
+ int rc;
+
+ rc = pci_enable_device(pdev);
+ if (rc < 0)
+ return rc;
+
+ rc = pci_request_regions(pdev, res_name);
+ if (rc < 0)
+ pci_disable_device(pdev);
+
+ return rc;
+}
+
+/*
+ * Release the regions and disable the PCI device.
+ *
+ * This must be matched with a previous successful call to comedi_pci_enable().
+ */
+static inline void comedi_pci_disable(struct pci_dev *pdev)
+{
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+#endif
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
new file mode 100644
index 000000000000..4b4c37d07482
--- /dev/null
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -0,0 +1,527 @@
+/*
+ comedi/drivers/comedi_test.c
+
+ Generates fake waveform signals that can be read through
+ the command interface. It does _not_ read from any board;
+ it just generates deterministic waveforms.
+ Useful for various testing purposes.
+
+ Copyright (C) 2002 Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>
+ Copyright (C) 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+************************************************************************/
+/*
+Driver: comedi_test
+Description: generates fake waveforms
+Author: Joachim Wuttke <Joachim.Wuttke@icn.siemens.de>, Frank Mori Hess
+ <fmhess@users.sourceforge.net>, ds
+Devices:
+Status: works
+Updated: Sat, 16 Mar 2002 17:34:48 -0800
+
+This driver is mainly for testing purposes, but can also be used to
+generate sample waveforms on systems that don't have data acquisition
+hardware.
+
+Configuration options:
+ [0] - Amplitude in microvolts for fake waveforms (default 1 volt)
+ [1] - Period in microseconds for fake waveforms (default 0.1 sec)
+
+Generates a sawtooth wave on channel 0, square wave on channel 1, additional
+waveforms could be added to other channels (currently they return flatline
+zero volts).
+
+*/
+
+#include "../comedidev.h"
+
+#include <asm/div64.h>
+
+#include "comedi_fc.h"
+
+/* Board descriptions */
+struct waveform_board {
+ const char *name;
+ int ai_chans;
+ int ai_bits;
+ int have_dio;
+};
+
+#define N_CHANS 8
+
+static const struct waveform_board waveform_boards[] = {
+ {
+ .name = "comedi_test",
+ .ai_chans = N_CHANS,
+ .ai_bits = 16,
+ .have_dio = 0,
+ },
+};
+
+#define thisboard ((const struct waveform_board *)dev->board_ptr)
+
+/* Data unique to this driver */
+struct waveform_private {
+ struct timer_list timer;
+ struct timeval last; /* time at which last timer interrupt occured */
+ unsigned int uvolt_amplitude; /* waveform amplitude in microvolts */
+ unsigned long usec_period; /* waveform period in microseconds */
+ unsigned long usec_current; /* current time (modulo waveform period) */
+ unsigned long usec_remainder; /* usec since last scan; */
+ unsigned long ai_count; /* number of conversions remaining */
+ unsigned int scan_period; /* scan period in usec */
+ unsigned int convert_period; /* conversion period in usec */
+ unsigned timer_running:1;
+ lsampl_t ao_loopbacks[N_CHANS];
+};
+#define devpriv ((struct waveform_private *)dev->private)
+
+static int waveform_attach(comedi_device *dev, comedi_devconfig *it);
+static int waveform_detach(comedi_device *dev);
+static comedi_driver driver_waveform = {
+ .driver_name = "comedi_test",
+ .module = THIS_MODULE,
+ .attach = waveform_attach,
+ .detach = waveform_detach,
+ .board_name = &waveform_boards[0].name,
+ .offset = sizeof(struct waveform_board),
+ .num_names = sizeof(waveform_boards) / sizeof(struct waveform_board),
+};
+
+COMEDI_INITCLEANUP(driver_waveform);
+
+static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ comedi_cmd *cmd);
+static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s);
+static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s);
+static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data);
+static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data);
+static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range,
+ unsigned long current_time);
+static sampl_t fake_squarewave(comedi_device *dev, unsigned int range,
+ unsigned long current_time);
+static sampl_t fake_flatline(comedi_device *dev, unsigned int range,
+ unsigned long current_time);
+static sampl_t fake_waveform(comedi_device *dev, unsigned int channel,
+ unsigned int range, unsigned long current_time);
+
+/* 1000 nanosec in a microsec */
+static const int nano_per_micro = 1000;
+
+/* fake analog input ranges */
+static const comedi_lrange waveform_ai_ranges = {
+ 2,
+ {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ }
+};
+
+/*
+ This is the background routine used to generate arbitrary data.
+ It should run in the background; therefore it is scheduled by
+ a timer mechanism.
+*/
+static void waveform_ai_interrupt(unsigned long arg)
+{
+ comedi_device *dev = (comedi_device *) arg;
+ comedi_async *async = dev->read_subdev->async;
+ comedi_cmd *cmd = &async->cmd;
+ unsigned int i, j;
+ /* all times in microsec */
+ unsigned long elapsed_time;
+ unsigned int num_scans;
+ struct timeval now;
+
+ do_gettimeofday(&now);
+
+ elapsed_time =
+ 1000000 * (now.tv_sec - devpriv->last.tv_sec) + now.tv_usec -
+ devpriv->last.tv_usec;
+ devpriv->last = now;
+ num_scans =
+ (devpriv->usec_remainder + elapsed_time) / devpriv->scan_period;
+ devpriv->usec_remainder =
+ (devpriv->usec_remainder + elapsed_time) % devpriv->scan_period;
+ async->events = 0;
+
+ for (i = 0; i < num_scans; i++) {
+ for (j = 0; j < cmd->chanlist_len; j++) {
+ cfc_write_to_buffer(dev->read_subdev,
+ fake_waveform(dev, CR_CHAN(cmd->chanlist[j]),
+ CR_RANGE(cmd->chanlist[j]),
+ devpriv->usec_current +
+ i * devpriv->scan_period +
+ j * devpriv->convert_period));
+ }
+ devpriv->ai_count++;
+ if (cmd->stop_src == TRIG_COUNT
+ && devpriv->ai_count >= cmd->stop_arg) {
+ async->events |= COMEDI_CB_EOA;
+ break;
+ }
+ }
+
+ devpriv->usec_current += elapsed_time;
+ devpriv->usec_current %= devpriv->usec_period;
+
+ if ((async->events & COMEDI_CB_EOA) == 0 && devpriv->timer_running)
+ mod_timer(&devpriv->timer, jiffies + 1);
+ else
+ del_timer(&devpriv->timer);
+
+ comedi_event(dev, dev->read_subdev);
+}
+
+static int waveform_attach(comedi_device *dev, comedi_devconfig *it)
+{
+ comedi_subdevice *s;
+ int amplitude = it->options[0];
+ int period = it->options[1];
+ int i;
+
+ dev->board_name = thisboard->name;
+
+ if (alloc_private(dev, sizeof(struct waveform_private)) < 0)
+ return -ENOMEM;
+
+ /* set default amplitude and period */
+ if (amplitude <= 0)
+ amplitude = 1000000; /* 1 volt */
+ if (period <= 0)
+ period = 100000; /* 0.1 sec */
+
+ devpriv->uvolt_amplitude = amplitude;
+ devpriv->usec_period = period;
+
+ dev->n_subdevices = 2;
+ if (alloc_subdevices(dev, dev->n_subdevices) < 0)
+ return -ENOMEM;
+
+ s = dev->subdevices + 0;
+ dev->read_subdev = s;
+ /* analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
+ s->n_chan = thisboard->ai_chans;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = &waveform_ai_ranges;
+ s->len_chanlist = s->n_chan * 2;
+ s->insn_read = waveform_ai_insn_read;
+ s->do_cmd = waveform_ai_cmd;
+ s->do_cmdtest = waveform_ai_cmdtest;
+ s->cancel = waveform_ai_cancel;
+
+ s = dev->subdevices + 1;
+ dev->write_subdev = s;
+ /* analog output subdevice (loopback) */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
+ s->n_chan = thisboard->ai_chans;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = &waveform_ai_ranges;
+ s->len_chanlist = s->n_chan * 2;
+ s->insn_write = waveform_ao_insn_write;
+ s->do_cmd = NULL;
+ s->do_cmdtest = NULL;
+ s->cancel = NULL;
+
+ /* Our default loopback value is just a 0V flatline */
+ for (i = 0; i < s->n_chan; i++)
+ devpriv->ao_loopbacks[i] = s->maxdata / 2;
+
+ init_timer(&(devpriv->timer));
+ devpriv->timer.function = waveform_ai_interrupt;
+ devpriv->timer.data = (unsigned long)dev;
+
+ printk(KERN_INFO "comedi%d: comedi_test: "
+ "%i microvolt, %li microsecond waveform attached\n", dev->minor,
+ devpriv->uvolt_amplitude, devpriv->usec_period);
+ return 1;
+}
+
+static int waveform_detach(comedi_device *dev)
+{
+ printk("comedi%d: comedi_test: remove\n", dev->minor);
+
+ if (dev->private)
+ waveform_ai_cancel(dev, dev->read_subdev);
+
+ return 0;
+}
+
+static int waveform_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ comedi_cmd *cmd)
+{
+ int err = 0;
+ int tmp;
+
+ /* step 1: make sure trigger sources are trivially valid */
+
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW;
+ if (!cmd->start_src || tmp != cmd->start_src)
+ err++;
+
+ tmp = cmd->scan_begin_src;
+ cmd->scan_begin_src &= TRIG_TIMER;
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+ err++;
+
+ tmp = cmd->convert_src;
+ cmd->convert_src &= TRIG_NOW | TRIG_TIMER;
+ if (!cmd->convert_src || tmp != cmd->convert_src)
+ err++;
+
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+ err++;
+
+ tmp = cmd->stop_src;
+ cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+ if (!cmd->stop_src || tmp != cmd->stop_src)
+ err++;
+
+ if (err)
+ return 1;
+
+ /*
+ * step 2: make sure trigger sources are unique and mutually compatible
+ */
+
+ if (cmd->convert_src != TRIG_NOW && cmd->convert_src != TRIG_TIMER)
+ err++;
+ if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
+ err++;
+
+ if (err)
+ return 2;
+
+ /* step 3: make sure arguments are trivially compatible */
+
+ if (cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+ if (cmd->convert_src == TRIG_NOW) {
+ if (cmd->convert_arg != 0) {
+ cmd->convert_arg = 0;
+ err++;
+ }
+ }
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ if (cmd->scan_begin_arg < nano_per_micro) {
+ cmd->scan_begin_arg = nano_per_micro;
+ err++;
+ }
+ if (cmd->convert_src == TRIG_TIMER &&
+ cmd->scan_begin_arg <
+ cmd->convert_arg * cmd->chanlist_len) {
+ cmd->scan_begin_arg =
+ cmd->convert_arg * cmd->chanlist_len;
+ err++;
+ }
+ }
+ /*
+ * XXX these checks are generic and should go in core if not there
+ * already
+ */
+ if (!cmd->chanlist_len) {
+ cmd->chanlist_len = 1;
+ err++;
+ }
+ if (cmd->scan_end_arg != cmd->chanlist_len) {
+ cmd->scan_end_arg = cmd->chanlist_len;
+ err++;
+ }
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ if (!cmd->stop_arg) {
+ cmd->stop_arg = 1;
+ err++;
+ }
+ } else { /* TRIG_NONE */
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+ }
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ tmp = cmd->scan_begin_arg;
+ /* round to nearest microsec */
+ cmd->scan_begin_arg =
+ nano_per_micro * ((tmp +
+ (nano_per_micro / 2)) / nano_per_micro);
+ if (tmp != cmd->scan_begin_arg)
+ err++;
+ }
+ if (cmd->convert_src == TRIG_TIMER) {
+ tmp = cmd->convert_arg;
+ /* round to nearest microsec */
+ cmd->convert_arg =
+ nano_per_micro * ((tmp +
+ (nano_per_micro / 2)) / nano_per_micro);
+ if (tmp != cmd->convert_arg)
+ err++;
+ }
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int waveform_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+{
+ comedi_cmd *cmd = &s->async->cmd;
+
+ if (cmd->flags & TRIG_RT) {
+ comedi_error(dev,
+ "commands at RT priority not supported in this driver");
+ return -1;
+ }
+
+ devpriv->timer_running = 1;
+ devpriv->ai_count = 0;
+ devpriv->scan_period = cmd->scan_begin_arg / nano_per_micro;
+
+ if (cmd->convert_src == TRIG_NOW)
+ devpriv->convert_period = 0;
+ else if (cmd->convert_src == TRIG_TIMER)
+ devpriv->convert_period = cmd->convert_arg / nano_per_micro;
+ else {
+ comedi_error(dev, "bug setting conversion period");
+ return -1;
+ }
+
+ do_gettimeofday(&devpriv->last);
+ devpriv->usec_current = devpriv->last.tv_usec % devpriv->usec_period;
+ devpriv->usec_remainder = 0;
+
+ devpriv->timer.expires = jiffies + 1;
+ add_timer(&devpriv->timer);
+ return 0;
+}
+
+static int waveform_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+ devpriv->timer_running = 0;
+ del_timer(&devpriv->timer);
+ return 0;
+}
+
+static sampl_t fake_sawtooth(comedi_device *dev, unsigned int range_index,
+ unsigned long current_time)
+{
+ comedi_subdevice *s = dev->read_subdev;
+ unsigned int offset = s->maxdata / 2;
+ u64 value;
+ const comedi_krange *krange = &s->range_table->range[range_index];
+ u64 binary_amplitude;
+
+ binary_amplitude = s->maxdata;
+ binary_amplitude *= devpriv->uvolt_amplitude;
+ do_div(binary_amplitude, krange->max - krange->min);
+
+ current_time %= devpriv->usec_period;
+ value = current_time;
+ value *= binary_amplitude * 2;
+ do_div(value, devpriv->usec_period);
+ value -= binary_amplitude; /* get rid of sawtooth's dc offset */
+
+ return offset + value;
+}
+static sampl_t fake_squarewave(comedi_device *dev, unsigned int range_index,
+ unsigned long current_time)
+{
+ comedi_subdevice *s = dev->read_subdev;
+ unsigned int offset = s->maxdata / 2;
+ u64 value;
+ const comedi_krange *krange = &s->range_table->range[range_index];
+ current_time %= devpriv->usec_period;
+
+ value = s->maxdata;
+ value *= devpriv->uvolt_amplitude;
+ do_div(value, krange->max - krange->min);
+
+ if (current_time < devpriv->usec_period / 2)
+ value *= -1;
+
+ return offset + value;
+}
+
+static sampl_t fake_flatline(comedi_device *dev, unsigned int range_index,
+ unsigned long current_time)
+{
+ return dev->read_subdev->maxdata / 2;
+}
+
+/* generates a different waveform depending on what channel is read */
+static sampl_t fake_waveform(comedi_device *dev, unsigned int channel,
+ unsigned int range, unsigned long current_time)
+{
+ enum {
+ SAWTOOTH_CHAN,
+ SQUARE_CHAN,
+ };
+ switch (channel) {
+ case SAWTOOTH_CHAN:
+ return fake_sawtooth(dev, range, current_time);
+ break;
+ case SQUARE_CHAN:
+ return fake_squarewave(dev, range, current_time);
+ break;
+ default:
+ break;
+ }
+
+ return fake_flatline(dev, range, current_time);
+}
+
+static int waveform_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int i, chan = CR_CHAN(insn->chanspec);
+
+ for (i = 0; i < insn->n; i++)
+ data[i] = devpriv->ao_loopbacks[chan];
+
+ return insn->n;
+}
+
+static int waveform_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int i, chan = CR_CHAN(insn->chanspec);
+
+ for (i = 0; i < insn->n; i++)
+ devpriv->ao_loopbacks[chan] = data[i];
+
+ return insn->n;
+}
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
new file mode 100644
index 000000000000..f2d2173d7219
--- /dev/null
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -0,0 +1,1162 @@
+/*
+ * comedi/drivers/dt9812.c
+ * COMEDI driver for DataTranslation DT9812 USB module
+ *
+ * Copyright (C) 2005 Anders Blomdell <anders.blomdell@control.lth.se>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+Driver: dt9812
+Description: Data Translation DT9812 USB module
+Author: anders.blomdell@control.lth.se (Anders Blomdell)
+Status: in development
+Devices: [Data Translation] DT9812 (dt9812)
+Updated: Sun Nov 20 20:18:34 EST 2005
+
+This driver works, but bulk transfers not implemented. Might be a starting point
+for someone else. I found out too late that USB has too high latencies (>1 ms)
+for my needs.
+*/
+
+/*
+ * Nota Bene:
+ * 1. All writes to command pipe has to be 32 bytes (ISP1181B SHRTP=0 ?)
+ * 2. The DDK source (as of sep 2005) is in error regarding the
+ * input MUX bits (example code says P4, but firmware schematics
+ * says P1).
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+
+#include "../comedidev.h"
+
+#define DT9812_DIAGS_BOARD_INFO_ADDR 0xFBFF
+#define DT9812_MAX_WRITE_CMD_PIPE_SIZE 32
+#define DT9812_MAX_READ_CMD_PIPE_SIZE 32
+
+/*
+ * See Silican Laboratories C8051F020/1/2/3 manual
+ */
+#define F020_SFR_P4 0x84
+#define F020_SFR_P1 0x90
+#define F020_SFR_P2 0xa0
+#define F020_SFR_P3 0xb0
+#define F020_SFR_AMX0CF 0xba
+#define F020_SFR_AMX0SL 0xbb
+#define F020_SFR_ADC0CF 0xbc
+#define F020_SFR_ADC0L 0xbe
+#define F020_SFR_ADC0H 0xbf
+#define F020_SFR_DAC0L 0xd2
+#define F020_SFR_DAC0H 0xd3
+#define F020_SFR_DAC0CN 0xd4
+#define F020_SFR_DAC1L 0xd5
+#define F020_SFR_DAC1H 0xd6
+#define F020_SFR_DAC1CN 0xd7
+#define F020_SFR_ADC0CN 0xe8
+
+#define F020_MASK_ADC0CF_AMP0GN0 0x01
+#define F020_MASK_ADC0CF_AMP0GN1 0x02
+#define F020_MASK_ADC0CF_AMP0GN2 0x04
+
+#define F020_MASK_ADC0CN_AD0EN 0x80
+#define F020_MASK_ADC0CN_AD0INT 0x20
+#define F020_MASK_ADC0CN_AD0BUSY 0x10
+
+#define F020_MASK_DACxCN_DACxEN 0x80
+
+enum {
+ /* A/D D/A DI DO CT */
+ DT9812_DEVID_DT9812_10, /* 8 2 8 8 1 +/- 10V */
+ DT9812_DEVID_DT9812_2PT5,/* 8 2 8 8 1 0-2.44V */
+#if 0
+ DT9812_DEVID_DT9813, /* 16 2 4 4 1 +/- 10V */
+ DT9812_DEVID_DT9814 /* 24 2 0 0 1 +/- 10V */
+#endif
+};
+
+enum dt9812_gain {
+ DT9812_GAIN_0PT25 = 1,
+ DT9812_GAIN_0PT5 = 2,
+ DT9812_GAIN_1 = 4,
+ DT9812_GAIN_2 = 8,
+ DT9812_GAIN_4 = 16,
+ DT9812_GAIN_8 = 32,
+ DT9812_GAIN_16 = 64,
+};
+
+enum {
+ DT9812_LEAST_USB_FIRMWARE_CMD_CODE = 0,
+ /* Write Flash memory */
+ DT9812_W_FLASH_DATA = 0,
+ /* Read Flash memory misc config info */
+ DT9812_R_FLASH_DATA = 1,
+
+ /*
+ * Register read/write commands for processor
+ */
+
+ /* Read a single byte of USB memory */
+ DT9812_R_SINGLE_BYTE_REG = 2,
+ /* Write a single byte of USB memory */
+ DT9812_W_SINGLE_BYTE_REG = 3,
+ /* Multiple Reads of USB memory */
+ DT9812_R_MULTI_BYTE_REG = 4,
+ /* Multiple Writes of USB memory */
+ DT9812_W_MULTI_BYTE_REG = 5,
+ /* Read, (AND) with mask, OR value, then write (single) */
+ DT9812_RMW_SINGLE_BYTE_REG = 6,
+ /* Read, (AND) with mask, OR value, then write (multiple) */
+ DT9812_RMW_MULTI_BYTE_REG = 7,
+
+ /*
+ * Register read/write commands for SMBus
+ */
+
+ /* Read a single byte of SMBus */
+ DT9812_R_SINGLE_BYTE_SMBUS = 8,
+ /* Write a single byte of SMBus */
+ DT9812_W_SINGLE_BYTE_SMBUS = 9,
+ /* Multiple Reads of SMBus */
+ DT9812_R_MULTI_BYTE_SMBUS = 10,
+ /* Multiple Writes of SMBus */
+ DT9812_W_MULTI_BYTE_SMBUS = 11,
+
+ /*
+ * Register read/write commands for a device
+ */
+
+ /* Read a single byte of a device */
+ DT9812_R_SINGLE_BYTE_DEV = 12,
+ /* Write a single byte of a device */
+ DT9812_W_SINGLE_BYTE_DEV = 13,
+ /* Multiple Reads of a device */
+ DT9812_R_MULTI_BYTE_DEV = 14,
+ /* Multiple Writes of a device */
+ DT9812_W_MULTI_BYTE_DEV = 15,
+
+ /* Not sure if we'll need this */
+ DT9812_W_DAC_THRESHOLD = 16,
+
+ /* Set interrupt on change mask */
+ DT9812_W_INT_ON_CHANGE_MASK = 17,
+
+ /* Write (or Clear) the CGL for the ADC */
+ DT9812_W_CGL = 18,
+ /* Multiple Reads of USB memory */
+ DT9812_R_MULTI_BYTE_USBMEM = 19,
+ /* Multiple Writes to USB memory */
+ DT9812_W_MULTI_BYTE_USBMEM = 20,
+
+ /* Issue a start command to a given subsystem */
+ DT9812_START_SUBSYSTEM = 21,
+ /* Issue a stop command to a given subsystem */
+ DT9812_STOP_SUBSYSTEM = 22,
+
+ /* calibrate the board using CAL_POT_CMD */
+ DT9812_CALIBRATE_POT = 23,
+ /* set the DAC FIFO size */
+ DT9812_W_DAC_FIFO_SIZE = 24,
+ /* Write or Clear the CGL for the DAC */
+ DT9812_W_CGL_DAC = 25,
+ /* Read a single value from a subsystem */
+ DT9812_R_SINGLE_VALUE_CMD = 26,
+ /* Write a single value to a subsystem */
+ DT9812_W_SINGLE_VALUE_CMD = 27,
+ /* Valid DT9812_USB_FIRMWARE_CMD_CODE's will be less than this number */
+ DT9812_MAX_USB_FIRMWARE_CMD_CODE,
+};
+
+struct dt9812_flash_data {
+ u16 numbytes;
+ u16 address;
+};
+
+#define DT9812_MAX_NUM_MULTI_BYTE_RDS \
+ ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / sizeof(u8))
+
+struct dt9812_read_multi {
+ u8 count;
+ u8 address[DT9812_MAX_NUM_MULTI_BYTE_RDS];
+};
+
+struct dt9812_write_byte {
+ u8 address;
+ u8 value;
+};
+
+#define DT9812_MAX_NUM_MULTI_BYTE_WRTS \
+ ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / \
+ sizeof(struct dt9812_write_byte))
+
+struct dt9812_write_multi {
+ u8 count;
+ struct dt9812_write_byte write[DT9812_MAX_NUM_MULTI_BYTE_WRTS];
+};
+
+struct dt9812_rmw_byte {
+ u8 address;
+ u8 and_mask;
+ u8 or_value;
+};
+
+#define DT9812_MAX_NUM_MULTI_BYTE_RMWS \
+ ((DT9812_MAX_WRITE_CMD_PIPE_SIZE - 4 - 1) / sizeof(struct dt9812_rmw_byte))
+
+struct dt9812_rmw_multi {
+ u8 count;
+ struct dt9812_rmw_byte rmw[DT9812_MAX_NUM_MULTI_BYTE_RMWS];
+};
+
+struct dt9812_usb_cmd {
+ u32 cmd;
+ union {
+ struct dt9812_flash_data flash_data_info;
+ struct dt9812_read_multi read_multi_info;
+ struct dt9812_write_multi write_multi_info;
+ struct dt9812_rmw_multi rmw_multi_info;
+ } u;
+#if 0
+ WRITE_BYTE_INFO WriteByteInfo;
+ READ_BYTE_INFO ReadByteInfo;
+ WRITE_MULTI_INFO WriteMultiInfo;
+ READ_MULTI_INFO ReadMultiInfo;
+ RMW_BYTE_INFO RMWByteInfo;
+ RMW_MULTI_INFO RMWMultiInfo;
+ DAC_THRESHOLD_INFO DacThresholdInfo;
+ INT_ON_CHANGE_MASK_INFO IntOnChangeMaskInfo;
+ CGL_INFO CglInfo;
+ SUBSYSTEM_INFO SubsystemInfo;
+ CAL_POT_CMD CalPotCmd;
+ WRITE_DEV_BYTE_INFO WriteDevByteInfo;
+ READ_DEV_BYTE_INFO ReadDevByteInfo;
+ WRITE_DEV_MULTI_INFO WriteDevMultiInfo;
+ READ_DEV_MULTI_INFO ReadDevMultiInfo;
+ READ_SINGLE_VALUE_INFO ReadSingleValueInfo;
+ WRITE_SINGLE_VALUE_INFO WriteSingleValueInfo;
+#endif
+};
+
+#define DT9812_NUM_SLOTS 16
+
+static DECLARE_MUTEX(dt9812_mutex);
+
+static struct usb_device_id dt9812_table[] = {
+ {USB_DEVICE(0x0867, 0x9812)},
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, dt9812_table);
+
+struct usb_dt9812 {
+ struct slot_dt9812 *slot;
+ struct usb_device *udev;
+ struct usb_interface *interface;
+ u16 vendor;
+ u16 product;
+ u16 device;
+ u32 serial;
+ struct {
+ __u8 addr;
+ size_t size;
+ } message_pipe, command_write, command_read, write_stream, read_stream;
+ struct kref kref;
+ u16 analog_out_shadow[2];
+ u8 digital_out_shadow;
+};
+
+struct comedi_dt9812 {
+ struct slot_dt9812 *slot;
+ u32 serial;
+};
+
+struct slot_dt9812 {
+ struct semaphore mutex;
+ u32 serial;
+ struct usb_dt9812 *usb;
+ struct comedi_dt9812 *comedi;
+};
+
+static const comedi_lrange dt9812_10_ain_range = { 1, {
+ BIP_RANGE(10),
+ }
+};
+
+static const comedi_lrange dt9812_2pt5_ain_range = { 1, {
+ UNI_RANGE(2.5),
+ }
+};
+
+static const comedi_lrange dt9812_10_aout_range = { 1, {
+ BIP_RANGE(10),
+ }
+};
+
+static const comedi_lrange dt9812_2pt5_aout_range = { 1, {
+ UNI_RANGE(2.5),
+ }
+};
+
+static struct slot_dt9812 dt9812[DT9812_NUM_SLOTS];
+
+/* Useful shorthand access to private data */
+#define devpriv ((struct comedi_dt9812 *)dev->private)
+
+static inline struct usb_dt9812 *to_dt9812_dev(struct kref *d)
+{
+ return container_of(d, struct usb_dt9812, kref);
+}
+
+static void dt9812_delete(struct kref *kref)
+{
+ struct usb_dt9812 *dev = to_dt9812_dev(kref);
+
+ usb_put_dev(dev->udev);
+ kfree(dev);
+}
+
+static int dt9812_read_info(struct usb_dt9812 *dev, int offset, void *buf,
+ size_t buf_size)
+{
+ struct dt9812_usb_cmd cmd;
+ int count, retval;
+
+ cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA);
+ cmd.u.flash_data_info.address =
+ cpu_to_le16(DT9812_DIAGS_BOARD_INFO_ADDR + offset);
+ cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size);
+
+ /* DT9812 only responds to 32 byte writes!! */
+ count = 32;
+ retval = usb_bulk_msg(dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->command_write.addr),
+ &cmd, 32, &count, HZ * 1);
+ if (retval)
+ return retval;
+ retval = usb_bulk_msg(dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->command_read.addr),
+ buf, buf_size, &count, HZ * 1);
+ return retval;
+}
+
+static int dt9812_read_multiple_registers(struct usb_dt9812 *dev, int reg_count,
+ u8 *address, u8 *value)
+{
+ struct dt9812_usb_cmd cmd;
+ int i, count, retval;
+
+ cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG);
+ cmd.u.read_multi_info.count = reg_count;
+ for (i = 0; i < reg_count; i++)
+ cmd.u.read_multi_info.address[i] = address[i];
+
+ /* DT9812 only responds to 32 byte writes!! */
+ count = 32;
+ retval = usb_bulk_msg(dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->command_write.addr),
+ &cmd, 32, &count, HZ * 1);
+ if (retval)
+ return retval;
+ retval = usb_bulk_msg(dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->command_read.addr),
+ value, reg_count, &count, HZ * 1);
+ return retval;
+}
+
+static int dt9812_write_multiple_registers(struct usb_dt9812 *dev,
+ int reg_count, u8 *address,
+ u8 *value)
+{
+ struct dt9812_usb_cmd cmd;
+ int i, count, retval;
+
+ cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG);
+ cmd.u.read_multi_info.count = reg_count;
+ for (i = 0; i < reg_count; i++) {
+ cmd.u.write_multi_info.write[i].address = address[i];
+ cmd.u.write_multi_info.write[i].value = value[i];
+ }
+ /* DT9812 only responds to 32 byte writes!! */
+ retval = usb_bulk_msg(dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->command_write.addr),
+ &cmd, 32, &count, HZ * 1);
+ return retval;
+}
+
+static int dt9812_rmw_multiple_registers(struct usb_dt9812 *dev, int reg_count,
+ struct dt9812_rmw_byte *rmw)
+{
+ struct dt9812_usb_cmd cmd;
+ int i, count, retval;
+
+ cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG);
+ cmd.u.rmw_multi_info.count = reg_count;
+ for (i = 0; i < reg_count; i++)
+ cmd.u.rmw_multi_info.rmw[i] = rmw[i];
+
+ /* DT9812 only responds to 32 byte writes!! */
+ retval = usb_bulk_msg(dev->udev,
+ usb_sndbulkpipe(dev->udev,
+ dev->command_write.addr),
+ &cmd, 32, &count, HZ * 1);
+ return retval;
+}
+
+static int dt9812_digital_in(struct slot_dt9812 *slot, u8 *bits)
+{
+ int result = -ENODEV;
+
+ down(&slot->mutex);
+ if (slot->usb) {
+ u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
+ u8 value[2];
+
+ result = dt9812_read_multiple_registers(slot->usb, 2, reg,
+ value);
+ if (result == 0) {
+ /*
+ * bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital
+ * input port bit 3 in F020_SFR_P1 is bit 7 in the
+ * digital input port
+ */
+ *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
+ /* printk("%2.2x, %2.2x -> %2.2x\n",
+ value[0], value[1], *bits); */
+ }
+ }
+ up(&slot->mutex);
+
+ return result;
+}
+
+static int dt9812_digital_out(struct slot_dt9812 *slot, u8 bits)
+{
+ int result = -ENODEV;
+
+ down(&slot->mutex);
+ if (slot->usb) {
+ u8 reg[1];
+ u8 value[1];
+
+ reg[0] = F020_SFR_P2;
+ value[0] = bits;
+ result = dt9812_write_multiple_registers(slot->usb, 1, reg,
+ value);
+ slot->usb->digital_out_shadow = bits;
+ }
+ up(&slot->mutex);
+ return result;
+}
+
+static int dt9812_digital_out_shadow(struct slot_dt9812 *slot, u8 *bits)
+{
+ int result = -ENODEV;
+
+ down(&slot->mutex);
+ if (slot->usb) {
+ *bits = slot->usb->digital_out_shadow;
+ result = 0;
+ }
+ up(&slot->mutex);
+ return result;
+}
+
+static void dt9812_configure_mux(struct usb_dt9812 *dev,
+ struct dt9812_rmw_byte *rmw, int channel)
+{
+ if (dev->device == DT9812_DEVID_DT9812_10) {
+ /* In the DT9812/10V MUX is selected by P1.5-7 */
+ rmw->address = F020_SFR_P1;
+ rmw->and_mask = 0xe0;
+ rmw->or_value = channel << 5;
+ } else {
+ /* In the DT9812/2.5V, internal mux is selected by bits 0:2 */
+ rmw->address = F020_SFR_AMX0SL;
+ rmw->and_mask = 0xff;
+ rmw->or_value = channel & 0x07;
+ }
+}
+
+static void dt9812_configure_gain(struct usb_dt9812 *dev,
+ struct dt9812_rmw_byte *rmw,
+ enum dt9812_gain gain)
+{
+ if (dev->device == DT9812_DEVID_DT9812_10) {
+ /* In the DT9812/10V, there is an external gain of 0.5 */
+ gain <<= 1;
+ }
+
+ rmw->address = F020_SFR_ADC0CF;
+ rmw->and_mask = F020_MASK_ADC0CF_AMP0GN2 |
+ F020_MASK_ADC0CF_AMP0GN1 |
+ F020_MASK_ADC0CF_AMP0GN0;
+ switch (gain) {
+ /*
+ * 000 -> Gain = 1
+ * 001 -> Gain = 2
+ * 010 -> Gain = 4
+ * 011 -> Gain = 8
+ * 10x -> Gain = 16
+ * 11x -> Gain = 0.5
+ */
+ case DT9812_GAIN_0PT5:
+ rmw->or_value = F020_MASK_ADC0CF_AMP0GN2 ||
+ F020_MASK_ADC0CF_AMP0GN1;
+ break;
+ case DT9812_GAIN_1:
+ rmw->or_value = 0x00;
+ break;
+ case DT9812_GAIN_2:
+ rmw->or_value = F020_MASK_ADC0CF_AMP0GN0;
+ break;
+ case DT9812_GAIN_4:
+ rmw->or_value = F020_MASK_ADC0CF_AMP0GN1;
+ break;
+ case DT9812_GAIN_8:
+ rmw->or_value = F020_MASK_ADC0CF_AMP0GN1 ||
+ F020_MASK_ADC0CF_AMP0GN0;
+ break;
+ case DT9812_GAIN_16:
+ rmw->or_value = F020_MASK_ADC0CF_AMP0GN2;
+ break;
+ default:
+ err("Illegal gain %d\n", gain);
+
+ }
+}
+
+static int dt9812_analog_in(struct slot_dt9812 *slot, int channel, u16 *value,
+ enum dt9812_gain gain)
+{
+ struct dt9812_rmw_byte rmw[3];
+ u8 reg[3] = {
+ F020_SFR_ADC0CN,
+ F020_SFR_ADC0H,
+ F020_SFR_ADC0L
+ };
+ u8 val[3];
+ int result = -ENODEV;
+
+ down(&slot->mutex);
+ if (!slot->usb)
+ goto exit;
+
+ /* 1 select the gain */
+ dt9812_configure_gain(slot->usb, &rmw[0], gain);
+
+ /* 2 set the MUX to select the channel */
+ dt9812_configure_mux(slot->usb, &rmw[1], channel);
+
+ /* 3 start conversion */
+ rmw[2].address = F020_SFR_ADC0CN;
+ rmw[2].and_mask = 0xff;
+ rmw[2].or_value = F020_MASK_ADC0CN_AD0EN | F020_MASK_ADC0CN_AD0BUSY;
+
+ result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
+ if (result)
+ goto exit;
+
+ /* read the status and ADC */
+ result = dt9812_read_multiple_registers(slot->usb, 3, reg, val);
+ if (result)
+ goto exit;
+ /*
+ * An ADC conversion takes 16 SAR clocks cycles, i.e. about 9us.
+ * Therefore, between the instant that AD0BUSY was set via
+ * dt9812_rmw_multiple_registers and the read of AD0BUSY via
+ * dt9812_read_multiple_registers, the conversion should be complete
+ * since these two operations require two USB transactions each taking
+ * at least a millisecond to complete. However, lets make sure that
+ * conversion is finished.
+ */
+ if ((val[0] & (F020_MASK_ADC0CN_AD0INT | F020_MASK_ADC0CN_AD0BUSY)) ==
+ F020_MASK_ADC0CN_AD0INT) {
+ switch (slot->usb->device) {
+ case DT9812_DEVID_DT9812_10:
+ /*
+ * For DT9812-10V the personality module set the
+ * encoding to 2's complement. Hence, convert it before
+ * returning it
+ */
+ *value = ((val[1] << 8) | val[2]) + 0x800;
+ break;
+ case DT9812_DEVID_DT9812_2PT5:
+ *value = (val[1] << 8) | val[2];
+ break;
+ }
+ }
+
+exit:
+ up(&slot->mutex);
+ return result;
+}
+
+static int dt9812_analog_out_shadow(struct slot_dt9812 *slot, int channel,
+ u16 *value)
+{
+ int result = -ENODEV;
+
+ down(&slot->mutex);
+ if (slot->usb) {
+ *value = slot->usb->analog_out_shadow[channel];
+ result = 0;
+ }
+ up(&slot->mutex);
+
+ return result;
+}
+
+static int dt9812_analog_out(struct slot_dt9812 *slot, int channel, u16 value)
+{
+ int result = -ENODEV;
+
+ down(&slot->mutex);
+ if (slot->usb) {
+ struct dt9812_rmw_byte rmw[3];
+
+ switch (channel) {
+ case 0:
+ /* 1. Set DAC mode */
+ rmw[0].address = F020_SFR_DAC0CN;
+ rmw[0].and_mask = 0xff;
+ rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
+
+ /* 2 load low byte of DAC value first */
+ rmw[1].address = F020_SFR_DAC0L;
+ rmw[1].and_mask = 0xff;
+ rmw[1].or_value = value & 0xff;
+
+ /* 3 load high byte of DAC value next to latch the
+ 12-bit value */
+ rmw[2].address = F020_SFR_DAC0H;
+ rmw[2].and_mask = 0xff;
+ rmw[2].or_value = (value >> 8) & 0xf;
+ break;
+
+ case 1:
+ /* 1. Set DAC mode */
+ rmw[0].address = F020_SFR_DAC1CN;
+ rmw[0].and_mask = 0xff;
+ rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
+
+ /* 2 load low byte of DAC value first */
+ rmw[1].address = F020_SFR_DAC1L;
+ rmw[1].and_mask = 0xff;
+ rmw[1].or_value = value & 0xff;
+
+ /* 3 load high byte of DAC value next to latch the
+ 12-bit value */
+ rmw[2].address = F020_SFR_DAC1H;
+ rmw[2].and_mask = 0xff;
+ rmw[2].or_value = (value >> 8) & 0xf;
+ break;
+ }
+ result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
+ slot->usb->analog_out_shadow[channel] = value;
+ }
+ up(&slot->mutex);
+
+ return result;
+}
+
+/*
+ * USB framework functions
+ */
+
+static int dt9812_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ int retval = -ENOMEM;
+ struct usb_dt9812 *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+ u8 fw;
+
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ dev_err(&interface->dev, "Out of memory\n");
+ goto error;
+ }
+ kref_init(&dev->kref);
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+ dev->interface = interface;
+
+ /* Check endpoints */
+ iface_desc = interface->cur_altsetting;
+
+ if (iface_desc->desc.bNumEndpoints != 5) {
+ err("Wrong number of endpints.");
+ retval = -ENODEV;
+ goto error;
+ }
+
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ int direction = -1;
+ endpoint = &iface_desc->endpoint[i].desc;
+ switch (i) {
+ case 0:
+ direction = USB_DIR_IN;
+ dev->message_pipe.addr = endpoint->bEndpointAddress;
+ dev->message_pipe.size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+
+ break;
+ case 1:
+ direction = USB_DIR_OUT;
+ dev->command_write.addr = endpoint->bEndpointAddress;
+ dev->command_write.size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ break;
+ case 2:
+ direction = USB_DIR_IN;
+ dev->command_read.addr = endpoint->bEndpointAddress;
+ dev->command_read.size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ break;
+ case 3:
+ direction = USB_DIR_OUT;
+ dev->write_stream.addr = endpoint->bEndpointAddress;
+ dev->write_stream.size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ break;
+ case 4:
+ direction = USB_DIR_IN;
+ dev->read_stream.addr = endpoint->bEndpointAddress;
+ dev->read_stream.size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ break;
+ }
+ if ((endpoint->bEndpointAddress & USB_DIR_IN) != direction) {
+ dev_err(&interface->dev,
+ "Endpoint has wrong direction.\n");
+ retval = -ENODEV;
+ goto error;
+ }
+ }
+ if (dt9812_read_info(dev, 0, &fw, sizeof(fw)) != 0) {
+ /*
+ * Seems like a configuration reset is necessary if driver is
+ * reloaded while device is attached
+ */
+ usb_reset_configuration(dev->udev);
+ for (i = 0; i < 10; i++) {
+ retval = dt9812_read_info(dev, 1, &fw, sizeof(fw));
+ if (retval == 0) {
+ dev_info(&interface->dev,
+ "usb_reset_configuration succeded "
+ "after %d iterations\n", i);
+ break;
+ }
+ }
+ }
+
+ if (dt9812_read_info(dev, 1, &dev->vendor, sizeof(dev->vendor)) != 0) {
+ err("Failed to read vendor.");
+ retval = -ENODEV;
+ goto error;
+ }
+ if (dt9812_read_info(dev, 3, &dev->product,
+ sizeof(dev->product)) != 0) {
+ err("Failed to read product.");
+ retval = -ENODEV;
+ goto error;
+ }
+ if (dt9812_read_info(dev, 5, &dev->device, sizeof(dev->device)) != 0) {
+ err("Failed to read device.");
+ retval = -ENODEV;
+ goto error;
+ }
+ if (dt9812_read_info(dev, 7, &dev->serial, sizeof(dev->serial)) != 0) {
+ err("Failed to read serial.");
+ retval = -ENODEV;
+ goto error;
+ }
+
+ dev->vendor = le16_to_cpu(dev->vendor);
+ dev->product = le16_to_cpu(dev->product);
+ dev->device = le16_to_cpu(dev->device);
+ dev->serial = le32_to_cpu(dev->serial);
+ switch (dev->device) {
+ case DT9812_DEVID_DT9812_10:
+ dev->analog_out_shadow[0] = 0x0800;
+ dev->analog_out_shadow[1] = 0x800;
+ break;
+ case DT9812_DEVID_DT9812_2PT5:
+ dev->analog_out_shadow[0] = 0x0000;
+ dev->analog_out_shadow[1] = 0x0000;
+ break;
+ }
+ dev->digital_out_shadow = 0;
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, dev);
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&interface->dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n",
+ dev->vendor, dev->product, dev->device, dev->serial);
+
+ down(&dt9812_mutex);
+ {
+ /* Find a slot for the USB device */
+ struct slot_dt9812 *first = NULL;
+ struct slot_dt9812 *best = NULL;
+
+ for (i = 0; i < DT9812_NUM_SLOTS; i++) {
+ if (!first && !dt9812[i].usb && dt9812[i].serial == 0)
+ first = &dt9812[i];
+ if (!best && dt9812[i].serial == dev->serial)
+ best = &dt9812[i];
+ }
+
+ if (!best)
+ best = first;
+
+ if (best) {
+ down(&best->mutex);
+ best->usb = dev;
+ dev->slot = best;
+ up(&best->mutex);
+ }
+ }
+ up(&dt9812_mutex);
+
+ return 0;
+
+error:
+ if (dev)
+ kref_put(&dev->kref, dt9812_delete);
+ return retval;
+}
+
+static void dt9812_disconnect(struct usb_interface *interface)
+{
+ struct usb_dt9812 *dev;
+ int minor = interface->minor;
+
+ down(&dt9812_mutex);
+ dev = usb_get_intfdata(interface);
+ if (dev->slot) {
+ down(&dev->slot->mutex);
+ dev->slot->usb = NULL;
+ up(&dev->slot->mutex);
+ dev->slot = NULL;
+ }
+ usb_set_intfdata(interface, NULL);
+ up(&dt9812_mutex);
+
+ /* queue final destruction */
+ kref_put(&dev->kref, dt9812_delete);
+
+ dev_info(&interface->dev, "USB Dt9812 #%d now disconnected\n", minor);
+}
+
+static struct usb_driver dt9812_usb_driver = {
+ .name = "dt9812",
+ .probe = dt9812_probe,
+ .disconnect = dt9812_disconnect,
+ .id_table = dt9812_table,
+};
+
+/*
+ * Comedi functions
+ */
+
+static void dt9812_comedi_open(comedi_device *dev)
+{
+ down(&devpriv->slot->mutex);
+ if (devpriv->slot->usb) {
+ /* We have an attached device, fill in current range info */
+ comedi_subdevice *s;
+
+ s = &dev->subdevices[0];
+ s->n_chan = 8;
+ s->maxdata = 1;
+
+ s = &dev->subdevices[1];
+ s->n_chan = 8;
+ s->maxdata = 1;
+
+ s = &dev->subdevices[2];
+ s->n_chan = 8;
+ switch (devpriv->slot->usb->device) {
+ case 0:{
+ s->maxdata = 4095;
+ s->range_table = &dt9812_10_ain_range;
+ }
+ break;
+ case 1:{
+ s->maxdata = 4095;
+ s->range_table = &dt9812_2pt5_ain_range;
+ }
+ break;
+ }
+
+ s = &dev->subdevices[3];
+ s->n_chan = 2;
+ switch (devpriv->slot->usb->device) {
+ case 0:{
+ s->maxdata = 4095;
+ s->range_table = &dt9812_10_aout_range;
+ }
+ break;
+ case 1:{
+ s->maxdata = 4095;
+ s->range_table = &dt9812_2pt5_aout_range;
+ }
+ break;
+ }
+ }
+ up(&devpriv->slot->mutex);
+}
+
+static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int n;
+ u8 bits = 0;
+
+ dt9812_digital_in(devpriv->slot, &bits);
+ for (n = 0; n < insn->n; n++)
+ data[n] = ((1 << insn->chanspec) & bits) != 0;
+ return n;
+}
+
+static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int n;
+ u8 bits = 0;
+
+ dt9812_digital_out_shadow(devpriv->slot, &bits);
+ for (n = 0; n < insn->n; n++) {
+ u8 mask = 1 << insn->chanspec;
+
+ bits &= ~mask;
+ if (data[n])
+ bits |= mask;
+ }
+ dt9812_digital_out(devpriv->slot, bits);
+ return n;
+}
+
+static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int n;
+
+ for (n = 0; n < insn->n; n++) {
+ u16 value = 0;
+
+ dt9812_analog_in(devpriv->slot, insn->chanspec, &value,
+ DT9812_GAIN_1);
+ data[n] = value;
+ }
+ return n;
+}
+
+static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int n;
+ u16 value;
+
+ for (n = 0; n < insn->n; n++) {
+ value = 0;
+ dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value);
+ data[n] = value;
+ }
+ return n;
+}
+
+static int dt9812_ao_winsn(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int n;
+
+ for (n = 0; n < insn->n; n++)
+ dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]);
+ return n;
+}
+
+static int dt9812_attach(comedi_device *dev, comedi_devconfig *it)
+{
+ int i;
+ comedi_subdevice *s;
+
+ dev->board_name = "dt9812";
+
+ if (alloc_private(dev, sizeof(struct comedi_dt9812)) < 0)
+ return -ENOMEM;
+
+ /*
+ * Special open routine, since USB unit may be unattached at
+ * comedi_config time, hence range can not be determined
+ */
+ dev->open = dt9812_comedi_open;
+
+ devpriv->serial = it->options[0];
+
+ /* Allocate subdevices */
+ if (alloc_subdevices(dev, 4) < 0)
+ return -ENOMEM;
+
+ /* digital input subdevice */
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 0;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_read = &dt9812_di_rinsn;
+
+ /* digital output subdevice */
+ s = dev->subdevices + 1;
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 0;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_write = &dt9812_do_winsn;
+
+ /* analog input subdevice */
+ s = dev->subdevices + 2;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = 0;
+ s->maxdata = 1;
+ s->range_table = NULL;
+ s->insn_read = &dt9812_ai_rinsn;
+
+ /* analog output subdevice */
+ s = dev->subdevices + 3;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE;
+ s->n_chan = 0;
+ s->maxdata = 1;
+ s->range_table = NULL;
+ s->insn_write = &dt9812_ao_winsn;
+ s->insn_read = &dt9812_ao_rinsn;
+
+ printk(KERN_INFO "comedi%d: successfully attached to dt9812.\n",
+ dev->minor);
+
+ down(&dt9812_mutex);
+ /* Find a slot for the comedi device */
+ {
+ struct slot_dt9812 *first = NULL;
+ struct slot_dt9812 *best = NULL;
+ for (i = 0; i < DT9812_NUM_SLOTS; i++) {
+ if (!first && !dt9812[i].comedi) {
+ /* First free slot from comedi side */
+ first = &dt9812[i];
+ }
+ if (!best &&
+ dt9812[i].usb &&
+ dt9812[i].usb->serial == devpriv->serial) {
+ /* We have an attaced device with matching ID */
+ best = &dt9812[i];
+ }
+ }
+ if (!best)
+ best = first;
+ if (best) {
+ down(&best->mutex);
+ best->comedi = devpriv;
+ best->serial = devpriv->serial;
+ devpriv->slot = best;
+ up(&best->mutex);
+ }
+ }
+ up(&dt9812_mutex);
+
+ return 0;
+}
+
+static int dt9812_detach(comedi_device *dev)
+{
+ return 0;
+}
+
+static comedi_driver dt9812_comedi_driver = {
+ .module = THIS_MODULE,
+ .driver_name = "dt9812",
+ .attach = dt9812_attach,
+ .detach = dt9812_detach,
+};
+
+static int __init usb_dt9812_init(void)
+{
+ int result, i;
+
+ /* Initialize all driver slots */
+ for (i = 0; i < DT9812_NUM_SLOTS; i++) {
+ init_MUTEX(&dt9812[i].mutex);
+ dt9812[i].serial = 0;
+ dt9812[i].usb = NULL;
+ dt9812[i].comedi = NULL;
+ }
+ dt9812[12].serial = 0x0;
+
+ /* register with the USB subsystem */
+ result = usb_register(&dt9812_usb_driver);
+ if (result) {
+ printk(KERN_ERR KBUILD_MODNAME
+ ": usb_register failed. Error number %d\n", result);
+ return result;
+ }
+ /* register with comedi */
+ result = comedi_driver_register(&dt9812_comedi_driver);
+ if (result) {
+ usb_deregister(&dt9812_usb_driver);
+ err("comedi_driver_register failed. Error number %d", result);
+ }
+
+ return result;
+}
+
+static void __exit usb_dt9812_exit(void)
+{
+ /* unregister with comedi */
+ comedi_driver_unregister(&dt9812_comedi_driver);
+
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&dt9812_usb_driver);
+}
+
+module_init(usb_dt9812_init);
+module_exit(usb_dt9812_exit);
+
+MODULE_AUTHOR("Anders Blomdell <anders.blomdell@control.lth.se>");
+MODULE_DESCRIPTION("Comedi DT9812 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
new file mode 100644
index 000000000000..59144d7cb0bc
--- /dev/null
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -0,0 +1,1085 @@
+/*
+ comedi/drivers/icp_multi.c
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/*
+Driver: icp_multi
+Description: Inova ICP_MULTI
+Author: Anne Smorthit <anne.smorthit@sfwte.ch>
+Devices: [Inova] ICP_MULTI (icp_multi)
+Status: works
+
+The driver works for analog input and output and digital input and output.
+It does not work with interrupts or with the counters. Currently no support
+for DMA.
+
+It has 16 single-ended or 8 differential Analogue Input channels with 12-bit
+resolution. Ranges : 5V, 10V, +/-5V, +/-10V, 0..20mA and 4..20mA. Input
+ranges can be individually programmed for each channel. Voltage or current
+measurement is selected by jumper.
+
+There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V
+
+16 x Digital Inputs, 24V
+
+8 x Digital Outputs, 24V, 1A
+
+4 x 16-bit counters
+
+Options:
+ [0] - PCI bus number - if bus number and slot number are 0,
+ then driver search for first unused card
+ [1] - PCI slot number
+*/
+
+#include "../comedidev.h"
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include "icp_multi.h"
+
+#define DEVICE_ID 0x8000 /* Device ID */
+
+#define ICP_MULTI_EXTDEBUG
+
+// Hardware types of the cards
+#define TYPE_ICP_MULTI 0
+
+#define IORANGE_ICP_MULTI 32
+
+#define ICP_MULTI_ADC_CSR 0 /* R/W: ADC command/status register */
+#define ICP_MULTI_AI 2 /* R: Analogue input data */
+#define ICP_MULTI_DAC_CSR 4 /* R/W: DAC command/status register */
+#define ICP_MULTI_AO 6 /* R/W: Analogue output data */
+#define ICP_MULTI_DI 8 /* R/W: Digital inouts */
+#define ICP_MULTI_DO 0x0A /* R/W: Digital outputs */
+#define ICP_MULTI_INT_EN 0x0C /* R/W: Interrupt enable register */
+#define ICP_MULTI_INT_STAT 0x0E /* R/W: Interrupt status register */
+#define ICP_MULTI_CNTR0 0x10 /* R/W: Counter 0 */
+#define ICP_MULTI_CNTR1 0x12 /* R/W: counter 1 */
+#define ICP_MULTI_CNTR2 0x14 /* R/W: Counter 2 */
+#define ICP_MULTI_CNTR3 0x16 /* R/W: Counter 3 */
+
+#define ICP_MULTI_SIZE 0x20 /* 32 bytes */
+
+// Define bits from ADC command/status register
+#define ADC_ST 0x0001 /* Start ADC */
+#define ADC_BSY 0x0001 /* ADC busy */
+#define ADC_BI 0x0010 /* Bipolar input range 1 = bipolar */
+#define ADC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */
+#define ADC_DI 0x0040 /* Differential input mode 1 = differential */
+
+// Define bits from DAC command/status register
+#define DAC_ST 0x0001 /* Start DAC */
+#define DAC_BSY 0x0001 /* DAC busy */
+#define DAC_BI 0x0010 /* Bipolar input range 1 = bipolar */
+#define DAC_RA 0x0020 /* Input range 0 = 5V, 1 = 10V */
+
+// Define bits from interrupt enable/status registers
+#define ADC_READY 0x0001 /* A/d conversion ready interrupt */
+#define DAC_READY 0x0002 /* D/a conversion ready interrupt */
+#define DOUT_ERROR 0x0004 /* Digital output error interrupt */
+#define DIN_STATUS 0x0008 /* Digital input status change interrupt */
+#define CIE0 0x0010 /* Counter 0 overrun interrupt */
+#define CIE1 0x0020 /* Counter 1 overrun interrupt */
+#define CIE2 0x0040 /* Counter 2 overrun interrupt */
+#define CIE3 0x0080 /* Counter 3 overrun interrupt */
+
+// Useful definitions
+#define Status_IRQ 0x00ff // All interrupts
+
+// Define analogue range
+static const comedi_lrange range_analog = { 4, {
+ UNI_RANGE(5),
+ UNI_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(10)
+ }
+};
+
+static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
+
+/*
+==============================================================================
+ Forward declarations
+==============================================================================
+*/
+static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it);
+static int icp_multi_detach(comedi_device * dev);
+
+/*
+==============================================================================
+ Data & Structure declarations
+==============================================================================
+*/
+static unsigned short pci_list_builded = 0; /*>0 list of card is known */
+
+typedef struct {
+ const char *name; // driver name
+ int device_id;
+ int iorange; // I/O range len
+ char have_irq; // 1=card support IRQ
+ char cardtype; // 0=ICP Multi
+ int n_aichan; // num of A/D chans
+ int n_aichand; // num of A/D chans in diff mode
+ int n_aochan; // num of D/A chans
+ int n_dichan; // num of DI chans
+ int n_dochan; // num of DO chans
+ int n_ctrs; // num of counters
+ int ai_maxdata; // resolution of A/D
+ int ao_maxdata; // resolution of D/A
+ const comedi_lrange *rangelist_ai; // rangelist for A/D
+ const char *rangecode; // range codes for programming
+ const comedi_lrange *rangelist_ao; // rangelist for D/A
+} boardtype;
+
+static const boardtype boardtypes[] = {
+ {"icp_multi", // Driver name
+ DEVICE_ID, // PCI device ID
+ IORANGE_ICP_MULTI, // I/O range length
+ 1, // 1=Card supports interrupts
+ TYPE_ICP_MULTI, // Card type = ICP MULTI
+ 16, // Num of A/D channels
+ 8, // Num of A/D channels in diff mode
+ 4, // Num of D/A channels
+ 16, // Num of digital inputs
+ 8, // Num of digital outputs
+ 4, // Num of counters
+ 0x0fff, // Resolution of A/D
+ 0x0fff, // Resolution of D/A
+ &range_analog, // Rangelist for A/D
+ range_codes_analog, // Range codes for programming
+ &range_analog}, // Rangelist for D/A
+};
+
+#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
+
+static comedi_driver driver_icp_multi = {
+ driver_name:"icp_multi",
+ module:THIS_MODULE,
+ attach:icp_multi_attach,
+ detach:icp_multi_detach,
+ num_names:n_boardtypes,
+ board_name:&boardtypes[0].name,
+ offset:sizeof(boardtype),
+};
+
+COMEDI_INITCLEANUP(driver_icp_multi);
+
+typedef struct {
+ struct pcilst_struct *card; // pointer to card
+ char valid; // card is usable
+ void *io_addr; // Pointer to mapped io address
+ resource_size_t phys_iobase; // Physical io address
+ unsigned int AdcCmdStatus; // ADC Command/Status register
+ unsigned int DacCmdStatus; // DAC Command/Status register
+ unsigned int IntEnable; // Interrupt Enable register
+ unsigned int IntStatus; // Interrupt Status register
+ unsigned int act_chanlist[32]; // list of scaned channel
+ unsigned char act_chanlist_len; // len of scanlist
+ unsigned char act_chanlist_pos; // actual position in MUX list
+ unsigned int *ai_chanlist; // actaul chanlist
+ sampl_t *ai_data; // data buffer
+ sampl_t ao_data[4]; // data output buffer
+ sampl_t di_data; // Digital input data
+ unsigned int do_data; // Remember digital output data
+} icp_multi_private;
+
+#define devpriv ((icp_multi_private *)dev->private)
+#define this_board ((const boardtype *)dev->board_ptr)
+
+/*
+==============================================================================
+ More forward declarations
+==============================================================================
+*/
+
+#if 0
+static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
+ unsigned int *chanlist, unsigned int n_chan);
+#endif
+static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
+ unsigned int *chanlist, unsigned int n_chan);
+static int icp_multi_reset(comedi_device * dev);
+
+/*
+==============================================================================
+ Functions
+==============================================================================
+*/
+
+/*
+==============================================================================
+
+ Name: icp_multi_insn_read_ai
+
+ Description:
+ This function reads a single analogue input.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ comedi_insn *insn Pointer to current comedi instruction
+ lsampl_t *data Pointer to analogue input data
+
+ Returns:int Nmuber of instructions executed
+
+==============================================================================
+*/
+static int icp_multi_insn_read_ai(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ int n, timeout;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: BGN: icp_multi_insn_read_ai(...)\n");
+#endif
+ // Disable A/D conversion ready interrupt
+ devpriv->IntEnable &= ~ADC_READY;
+ writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+
+ // Clear interrupt status
+ devpriv->IntStatus |= ADC_READY;
+ writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+
+ // Set up appropriate channel, mode and range data, for specified channel
+ setup_channel_list(dev, s, &insn->chanspec, 1);
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp_multi A ST=%4x IO=%p\n",
+ readw(devpriv->io_addr + ICP_MULTI_ADC_CSR),
+ devpriv->io_addr + ICP_MULTI_ADC_CSR);
+#endif
+
+ for (n = 0; n < insn->n; n++) {
+ // Set start ADC bit
+ devpriv->AdcCmdStatus |= ADC_ST;
+ writew(devpriv->AdcCmdStatus,
+ devpriv->io_addr + ICP_MULTI_ADC_CSR);
+ devpriv->AdcCmdStatus &= ~ADC_ST;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi B n=%d ST=%4x\n", n,
+ readw(devpriv->io_addr + ICP_MULTI_ADC_CSR));
+#endif
+
+ comedi_udelay(1);
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi C n=%d ST=%4x\n", n,
+ readw(devpriv->io_addr + ICP_MULTI_ADC_CSR));
+#endif
+
+ // Wait for conversion to complete, or get fed up waiting
+ timeout = 100;
+ while (timeout--) {
+ if (!(readw(devpriv->io_addr +
+ ICP_MULTI_ADC_CSR) & ADC_BSY))
+ goto conv_finish;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ if (!(timeout % 10))
+ printk("icp multi D n=%d tm=%d ST=%4x\n", n,
+ timeout,
+ readw(devpriv->io_addr +
+ ICP_MULTI_ADC_CSR));
+#endif
+
+ comedi_udelay(1);
+ }
+
+ // If we reach here, a timeout has occurred
+ comedi_error(dev, "A/D insn timeout");
+
+ // Disable interrupt
+ devpriv->IntEnable &= ~ADC_READY;
+ writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+
+ // Clear interrupt status
+ devpriv->IntStatus |= ADC_READY;
+ writew(devpriv->IntStatus,
+ devpriv->io_addr + ICP_MULTI_INT_STAT);
+
+ // Clear data received
+ data[n] = 0;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n);
+#endif
+ return -ETIME;
+
+ conv_finish:
+ data[n] =
+ (readw(devpriv->io_addr + ICP_MULTI_AI) >> 4) & 0x0fff;
+ }
+
+ // Disable interrupt
+ devpriv->IntEnable &= ~ADC_READY;
+ writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+
+ // Clear interrupt status
+ devpriv->IntStatus |= ADC_READY;
+ writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: icp_multi_insn_read_ai(...) n=%d\n", n);
+#endif
+ return n;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_insn_write_ao
+
+ Description:
+ This function writes a single analogue output.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ comedi_insn *insn Pointer to current comedi instruction
+ lsampl_t *data Pointer to analogue output data
+
+ Returns:int Nmuber of instructions executed
+
+==============================================================================
+*/
+static int icp_multi_insn_write_ao(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ int n, chan, range, timeout;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: BGN: icp_multi_insn_write_ao(...)\n");
+#endif
+ // Disable D/A conversion ready interrupt
+ devpriv->IntEnable &= ~DAC_READY;
+ writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+
+ // Clear interrupt status
+ devpriv->IntStatus |= DAC_READY;
+ writew(devpriv->IntStatus, devpriv->io_addr + ICP_MULTI_INT_STAT);
+
+ // Get channel number and range
+ chan = CR_CHAN(insn->chanspec);
+ range = CR_RANGE(insn->chanspec);
+
+ // Set up range and channel data
+ // Bit 4 = 1 : Bipolar
+ // Bit 5 = 0 : 5V
+ // Bit 5 = 1 : 10V
+ // Bits 8-9 : Channel number
+ devpriv->DacCmdStatus &= 0xfccf;
+ devpriv->DacCmdStatus |= this_board->rangecode[range];
+ devpriv->DacCmdStatus |= (chan << 8);
+
+ writew(devpriv->DacCmdStatus, devpriv->io_addr + ICP_MULTI_DAC_CSR);
+
+ for (n = 0; n < insn->n; n++) {
+ // Wait for analogue output data register to be ready for new data, or get fed up waiting
+ timeout = 100;
+ while (timeout--) {
+ if (!(readw(devpriv->io_addr +
+ ICP_MULTI_DAC_CSR) & DAC_BSY))
+ goto dac_ready;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ if (!(timeout % 10))
+ printk("icp multi A n=%d tm=%d ST=%4x\n", n,
+ timeout,
+ readw(devpriv->io_addr +
+ ICP_MULTI_DAC_CSR));
+#endif
+
+ comedi_udelay(1);
+ }
+
+ // If we reach here, a timeout has occurred
+ comedi_error(dev, "D/A insn timeout");
+
+ // Disable interrupt
+ devpriv->IntEnable &= ~DAC_READY;
+ writew(devpriv->IntEnable, devpriv->io_addr + ICP_MULTI_INT_EN);
+
+ // Clear interrupt status
+ devpriv->IntStatus |= DAC_READY;
+ writew(devpriv->IntStatus,
+ devpriv->io_addr + ICP_MULTI_INT_STAT);
+
+ // Clear data received
+ devpriv->ao_data[chan] = 0;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n);
+#endif
+ return -ETIME;
+
+ dac_ready:
+ // Write data to analogue output data register
+ writew(data[n], devpriv->io_addr + ICP_MULTI_AO);
+
+ // Set DAC_ST bit to write the data to selected channel
+ devpriv->DacCmdStatus |= DAC_ST;
+ writew(devpriv->DacCmdStatus,
+ devpriv->io_addr + ICP_MULTI_DAC_CSR);
+ devpriv->DacCmdStatus &= ~DAC_ST;
+
+ // Save analogue output data
+ devpriv->ao_data[chan] = data[n];
+ }
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: icp_multi_insn_write_ao(...) n=%d\n", n);
+#endif
+ return n;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_insn_read_ao
+
+ Description:
+ This function reads a single analogue output.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ comedi_insn *insn Pointer to current comedi instruction
+ lsampl_t *data Pointer to analogue output data
+
+ Returns:int Nmuber of instructions executed
+
+==============================================================================
+*/
+static int icp_multi_insn_read_ao(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ int n, chan;
+
+ // Get channel number
+ chan = CR_CHAN(insn->chanspec);
+
+ // Read analogue outputs
+ for (n = 0; n < insn->n; n++)
+ data[n] = devpriv->ao_data[chan];
+
+ return n;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_insn_bits_di
+
+ Description:
+ This function reads the digital inputs.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ comedi_insn *insn Pointer to current comedi instruction
+ lsampl_t *data Pointer to analogue output data
+
+ Returns:int Nmuber of instructions executed
+
+==============================================================================
+*/
+static int icp_multi_insn_bits_di(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+
+ return 2;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_insn_bits_do
+
+ Description:
+ This function writes the appropriate digital outputs.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ comedi_insn *insn Pointer to current comedi instruction
+ lsampl_t *data Pointer to analogue output data
+
+ Returns:int Nmuber of instructions executed
+
+==============================================================================
+*/
+static int icp_multi_insn_bits_do(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: BGN: icp_multi_insn_bits_do(...)\n");
+#endif
+
+ if (data[0]) {
+ s->state &= ~data[0];
+ s->state |= (data[0] & data[1]);
+
+ printk("Digital outputs = %4x \n", s->state);
+
+ writew(s->state, devpriv->io_addr + ICP_MULTI_DO);
+ }
+
+ data[1] = readw(devpriv->io_addr + ICP_MULTI_DI);
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: icp_multi_insn_bits_do(...)\n");
+#endif
+ return 2;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_insn_read_ctr
+
+ Description:
+ This function reads the specified counter.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ comedi_insn *insn Pointer to current comedi instruction
+ lsampl_t *data Pointer to counter data
+
+ Returns:int Nmuber of instructions executed
+
+==============================================================================
+*/
+static int icp_multi_insn_read_ctr(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ return 0;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_insn_write_ctr
+
+ Description:
+ This function write to the specified counter.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ comedi_insn *insn Pointer to current comedi instruction
+ lsampl_t *data Pointer to counter data
+
+ Returns:int Nmuber of instructions executed
+
+==============================================================================
+*/
+static int icp_multi_insn_write_ctr(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ return 0;
+}
+
+/*
+==============================================================================
+
+ Name: interrupt_service_icp_multi
+
+ Description:
+ This function is the interrupt service routine for all
+ interrupts generated by the icp multi board.
+
+ Parameters:
+ int irq
+ void *d Pointer to current device
+
+==============================================================================
+*/
+static irqreturn_t interrupt_service_icp_multi(int irq, void *d PT_REGS_ARG)
+{
+ comedi_device *dev = d;
+ int int_no;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: BGN: interrupt_service_icp_multi(%d,...)\n",
+ irq);
+#endif
+
+ // Is this interrupt from our board?
+ int_no = readw(devpriv->io_addr + ICP_MULTI_INT_STAT) & Status_IRQ;
+ if (!int_no)
+ // No, exit
+ return IRQ_NONE;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: interrupt_service_icp_multi() ST: %4x\n",
+ readw(devpriv->io_addr + ICP_MULTI_INT_STAT));
+#endif
+
+ // Determine which interrupt is active & handle it
+ switch (int_no) {
+ case ADC_READY:
+ break;
+ case DAC_READY:
+ break;
+ case DOUT_ERROR:
+ break;
+ case DIN_STATUS:
+ break;
+ case CIE0:
+ break;
+ case CIE1:
+ break;
+ case CIE2:
+ break;
+ case CIE3:
+ break;
+ default:
+ break;
+
+ }
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: interrupt_service_icp_multi(...)\n");
+#endif
+ return IRQ_HANDLED;
+}
+
+#if 0
+/*
+==============================================================================
+
+ Name: check_channel_list
+
+ Description:
+ This function checks if the channel list, provided by user
+ is built correctly
+
+ Parameters:
+ comedi_device *dev Pointer to current sevice structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ unsigned int *chanlist Pointer to packed channel list
+ unsigned int n_chan Number of channels to scan
+
+ Returns:int 0 = failure
+ 1 = success
+
+==============================================================================
+*/
+static int check_channel_list(comedi_device * dev, comedi_subdevice * s,
+ unsigned int *chanlist, unsigned int n_chan)
+{
+ unsigned int i;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: check_channel_list(...,%d)\n", n_chan);
+#endif
+ // Check that we at least have one channel to check
+ if (n_chan < 1) {
+ comedi_error(dev, "range/channel list is empty!");
+ return 0;
+ }
+ // Check all channels
+ for (i = 0; i < n_chan; i++) {
+ // Check that channel number is < maximum
+ if (CR_AREF(chanlist[i]) == AREF_DIFF) {
+ if (CR_CHAN(chanlist[i]) > this_board->n_aichand) {
+ comedi_error(dev,
+ "Incorrect differential ai channel number");
+ return 0;
+ }
+ } else {
+ if (CR_CHAN(chanlist[i]) > this_board->n_aichan) {
+ comedi_error(dev,
+ "Incorrect ai channel number");
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+#endif
+
+/*
+==============================================================================
+
+ Name: setup_channel_list
+
+ Description:
+ This function sets the appropriate channel selection,
+ differential input mode and range bits in the ADC Command/
+ Status register.
+
+ Parameters:
+ comedi_device *dev Pointer to current sevice structure
+ comedi_subdevice *s Pointer to current subdevice structure
+ unsigned int *chanlist Pointer to packed channel list
+ unsigned int n_chan Number of channels to scan
+
+ Returns:Void
+
+==============================================================================
+*/
+static void setup_channel_list(comedi_device * dev, comedi_subdevice * s,
+ unsigned int *chanlist, unsigned int n_chan)
+{
+ unsigned int i, range, chanprog;
+ unsigned int diff;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: setup_channel_list(...,%d)\n", n_chan);
+#endif
+ devpriv->act_chanlist_len = n_chan;
+ devpriv->act_chanlist_pos = 0;
+
+ for (i = 0; i < n_chan; i++) {
+ // Get channel
+ chanprog = CR_CHAN(chanlist[i]);
+
+ // Determine if it is a differential channel (Bit 15 = 1)
+ if (CR_AREF(chanlist[i]) == AREF_DIFF) {
+ diff = 1;
+ chanprog &= 0x0007;
+ } else {
+ diff = 0;
+ chanprog &= 0x000f;
+ }
+
+ // Clear channel, range and input mode bits in A/D command/status register
+ devpriv->AdcCmdStatus &= 0xf00f;
+
+ // Set channel number and differential mode status bit
+ if (diff) {
+ // Set channel number, bits 9-11 & mode, bit 6
+ devpriv->AdcCmdStatus |= (chanprog << 9);
+ devpriv->AdcCmdStatus |= ADC_DI;
+ } else
+ // Set channel number, bits 8-11
+ devpriv->AdcCmdStatus |= (chanprog << 8);
+
+ // Get range for current channel
+ range = this_board->rangecode[CR_RANGE(chanlist[i])];
+ // Set range. bits 4-5
+ devpriv->AdcCmdStatus |= range;
+
+ /* Output channel, range, mode to ICP Multi */
+ writew(devpriv->AdcCmdStatus,
+ devpriv->io_addr + ICP_MULTI_ADC_CSR);
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
+ devpriv->act_chanlist[i]);
+#endif
+ }
+
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_reset
+
+ Description:
+ This function resets the icp multi device to a 'safe' state
+
+ Parameters:
+ comedi_device *dev Pointer to current sevice structure
+
+ Returns:int 0 = success
+
+==============================================================================
+*/
+static int icp_multi_reset(comedi_device * dev)
+{
+ unsigned int i;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp_multi EDBG: BGN: icp_multi_reset(...)\n");
+#endif
+ // Clear INT enables and requests
+ writew(0, devpriv->io_addr + ICP_MULTI_INT_EN);
+ writew(0x00ff, devpriv->io_addr + ICP_MULTI_INT_STAT);
+
+ if (this_board->n_aochan)
+ // Set DACs to 0..5V range and 0V output
+ for (i = 0; i < this_board->n_aochan; i++) {
+ devpriv->DacCmdStatus &= 0xfcce;
+
+ // Set channel number
+ devpriv->DacCmdStatus |= (i << 8);
+
+ // Output 0V
+ writew(0, devpriv->io_addr + ICP_MULTI_AO);
+
+ // Set start conversion bit
+ devpriv->DacCmdStatus |= DAC_ST;
+
+ // Output to command / status register
+ writew(devpriv->DacCmdStatus,
+ devpriv->io_addr + ICP_MULTI_DAC_CSR);
+
+ // Delay to allow DAC time to recover
+ comedi_udelay(1);
+ }
+ // Digital outputs to 0
+ writew(0, devpriv->io_addr + ICP_MULTI_DO);
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: icp_multi_reset(...)\n");
+#endif
+ return 0;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_attach
+
+ Description:
+ This function sets up all the appropriate data for the current
+ device.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+ comedi_devconfig *it Pointer to current device configuration
+
+ Returns:int 0 = success
+
+==============================================================================
+*/
+static int icp_multi_attach(comedi_device * dev, comedi_devconfig * it)
+{
+ comedi_subdevice *s;
+ int ret, subdev, n_subdevices;
+ unsigned int irq;
+ struct pcilst_struct *card = NULL;
+ resource_size_t io_addr[5], iobase;
+ unsigned char pci_bus, pci_slot, pci_func;
+
+ printk("icp_multi EDBG: BGN: icp_multi_attach(...)\n");
+
+ // Alocate private data storage space
+ if ((ret = alloc_private(dev, sizeof(icp_multi_private))) < 0)
+ return ret;
+
+ // Initialise list of PCI cards in system, if not already done so
+ if (pci_list_builded++ == 0) {
+ pci_card_list_init(PCI_VENDOR_ID_ICP,
+#ifdef ICP_MULTI_EXTDEBUG
+ 1
+#else
+ 0
+#endif
+ );
+ }
+
+ printk("Anne's comedi%d: icp_multi: board=%s", dev->minor,
+ this_board->name);
+
+ if ((card = select_and_alloc_pci_card(PCI_VENDOR_ID_ICP,
+ this_board->device_id, it->options[0],
+ it->options[1])) == NULL)
+ return -EIO;
+
+ devpriv->card = card;
+
+ if ((pci_card_data(card, &pci_bus, &pci_slot, &pci_func, &io_addr[0],
+ &irq)) < 0) {
+ printk(" - Can't get configuration data!\n");
+ return -EIO;
+ }
+
+ iobase = io_addr[2];
+ devpriv->phys_iobase = iobase;
+
+ printk(", b:s:f=%d:%d:%d, io=0x%8llx \n", pci_bus, pci_slot, pci_func,
+ (unsigned long long)iobase);
+
+ devpriv->io_addr = ioremap(iobase, ICP_MULTI_SIZE);
+
+ if (devpriv->io_addr == NULL) {
+ printk("ioremap failed.\n");
+ return -ENOMEM;
+ }
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("0x%08llx mapped to %p, ", (unsigned long long)iobase,
+ devpriv->io_addr);
+#endif
+
+ dev->board_name = this_board->name;
+
+ n_subdevices = 0;
+ if (this_board->n_aichan)
+ n_subdevices++;
+ if (this_board->n_aochan)
+ n_subdevices++;
+ if (this_board->n_dichan)
+ n_subdevices++;
+ if (this_board->n_dochan)
+ n_subdevices++;
+ if (this_board->n_ctrs)
+ n_subdevices++;
+
+ if ((ret = alloc_subdevices(dev, n_subdevices)) < 0) {
+ return ret;
+ }
+
+ icp_multi_reset(dev);
+
+ if (this_board->have_irq) {
+ if (irq) {
+ if (comedi_request_irq(irq, interrupt_service_icp_multi,
+ IRQF_SHARED, "Inova Icp Multi", dev)) {
+ printk(", unable to allocate IRQ %u, DISABLING IT", irq);
+ irq = 0; /* Can't use IRQ */
+ } else
+ printk(", irq=%u", irq);
+ } else
+ printk(", IRQ disabled");
+ } else
+ irq = 0;
+
+ dev->irq = irq;
+
+ printk(".\n");
+
+ subdev = 0;
+
+ if (this_board->n_aichan) {
+ s = dev->subdevices + subdev;
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
+ if (this_board->n_aichand)
+ s->subdev_flags |= SDF_DIFF;
+ s->n_chan = this_board->n_aichan;
+ s->maxdata = this_board->ai_maxdata;
+ s->len_chanlist = this_board->n_aichan;
+ s->range_table = this_board->rangelist_ai;
+ s->insn_read = icp_multi_insn_read_ai;
+ subdev++;
+ }
+
+ if (this_board->n_aochan) {
+ s = dev->subdevices + subdev;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = this_board->n_aochan;
+ s->maxdata = this_board->ao_maxdata;
+ s->len_chanlist = this_board->n_aochan;
+ s->range_table = this_board->rangelist_ao;
+ s->insn_write = icp_multi_insn_write_ao;
+ s->insn_read = icp_multi_insn_read_ao;
+ subdev++;
+ }
+
+ if (this_board->n_dichan) {
+ s = dev->subdevices + subdev;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = this_board->n_dichan;
+ s->maxdata = 1;
+ s->len_chanlist = this_board->n_dichan;
+ s->range_table = &range_digital;
+ s->io_bits = 0;
+ s->insn_bits = icp_multi_insn_bits_di;
+ subdev++;
+ }
+
+ if (this_board->n_dochan) {
+ s = dev->subdevices + subdev;
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = this_board->n_dochan;
+ s->maxdata = 1;
+ s->len_chanlist = this_board->n_dochan;
+ s->range_table = &range_digital;
+ s->io_bits = (1 << this_board->n_dochan) - 1;
+ s->state = 0;
+ s->insn_bits = icp_multi_insn_bits_do;
+ subdev++;
+ }
+
+ if (this_board->n_ctrs) {
+ s = dev->subdevices + subdev;
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = this_board->n_ctrs;
+ s->maxdata = 0xffff;
+ s->len_chanlist = this_board->n_ctrs;
+ s->state = 0;
+ s->insn_read = icp_multi_insn_read_ctr;
+ s->insn_write = icp_multi_insn_write_ctr;
+ subdev++;
+ }
+
+ devpriv->valid = 1;
+
+#ifdef ICP_MULTI_EXTDEBUG
+ printk("icp multi EDBG: END: icp_multi_attach(...)\n");
+#endif
+
+ return 0;
+}
+
+/*
+==============================================================================
+
+ Name: icp_multi_detach
+
+ Description:
+ This function releases all the resources used by the current
+ device.
+
+ Parameters:
+ comedi_device *dev Pointer to current device structure
+
+ Returns:int 0 = success
+
+==============================================================================
+*/
+static int icp_multi_detach(comedi_device * dev)
+{
+
+ if (dev->private)
+ if (devpriv->valid)
+ icp_multi_reset(dev);
+
+ if (dev->irq)
+ comedi_free_irq(dev->irq, dev);
+
+ if (dev->private && devpriv->io_addr)
+ iounmap(devpriv->io_addr);
+
+ if (dev->private && devpriv->card)
+ pci_card_free(devpriv->card);
+
+ if (--pci_list_builded == 0) {
+ pci_card_list_cleanup(PCI_VENDOR_ID_ICP);
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/icp_multi.h b/drivers/staging/comedi/drivers/icp_multi.h
new file mode 100644
index 000000000000..6df4a8d15ff2
--- /dev/null
+++ b/drivers/staging/comedi/drivers/icp_multi.h
@@ -0,0 +1,278 @@
+/*
+ comedi/drivers/icp_multi.h
+
+ Stuff for ICP Multi
+
+ Author: Anne Smorthit <anne.smorthit@sfwte.ch>
+
+*/
+
+#ifndef _ICP_MULTI_H_
+#define _ICP_MULTI_H_
+
+#include "../comedidev.h"
+#include "comedi_pci.h"
+
+/****************************************************************************/
+
+struct pcilst_struct {
+ struct pcilst_struct *next;
+ int used;
+ struct pci_dev *pcidev;
+ unsigned short vendor;
+ unsigned short device;
+ unsigned char pci_bus;
+ unsigned char pci_slot;
+ unsigned char pci_func;
+ resource_size_t io_addr[5];
+ unsigned int irq;
+};
+
+struct pcilst_struct *inova_devices; // ptr to root list of all Inova devices
+
+/****************************************************************************/
+
+static void pci_card_list_init(unsigned short pci_vendor, char display);
+static void pci_card_list_cleanup(unsigned short pci_vendor);
+static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
+ vendor_id, unsigned short device_id);
+static int find_free_pci_card_by_position(unsigned short vendor_id,
+ unsigned short device_id, unsigned short pci_bus,
+ unsigned short pci_slot, struct pcilst_struct **card);
+static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
+ unsigned short device_id, unsigned short pci_bus,
+ unsigned short pci_slot);
+
+static int pci_card_alloc(struct pcilst_struct *amcc);
+static int pci_card_free(struct pcilst_struct *amcc);
+static void pci_card_list_display(void);
+static int pci_card_data(struct pcilst_struct *amcc,
+ unsigned char *pci_bus, unsigned char *pci_slot,
+ unsigned char *pci_func, resource_size_t * io_addr, unsigned int *irq);
+
+/****************************************************************************/
+
+/* build list of Inova cards in this system */
+static void pci_card_list_init(unsigned short pci_vendor, char display)
+{
+ struct pci_dev *pcidev;
+ struct pcilst_struct *inova, *last;
+ int i;
+
+ inova_devices = NULL;
+ last = NULL;
+
+ for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ pcidev != NULL;
+ pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+ if (pcidev->vendor == pci_vendor) {
+ inova = kmalloc(sizeof(*inova), GFP_KERNEL);
+ if (!inova) {
+ printk("icp_multi: pci_card_list_init: allocation failed\n");
+ pci_dev_put(pcidev);
+ break;
+ }
+ memset(inova, 0, sizeof(*inova));
+
+ inova->pcidev = pci_dev_get(pcidev);
+ if (last) {
+ last->next = inova;
+ } else {
+ inova_devices = inova;
+ }
+ last = inova;
+
+ inova->vendor = pcidev->vendor;
+ inova->device = pcidev->device;
+ inova->pci_bus = pcidev->bus->number;
+ inova->pci_slot = PCI_SLOT(pcidev->devfn);
+ inova->pci_func = PCI_FUNC(pcidev->devfn);
+ /* Note: resources may be invalid if PCI device
+ * not enabled, but they are corrected in
+ * pci_card_alloc. */
+ for (i = 0; i < 5; i++)
+ inova->io_addr[i] =
+ pci_resource_start(pcidev, i);
+ inova->irq = pcidev->irq;
+ }
+ }
+
+ if (display)
+ pci_card_list_display();
+}
+
+/****************************************************************************/
+/* free up list of amcc cards in this system */
+static void pci_card_list_cleanup(unsigned short pci_vendor)
+{
+ struct pcilst_struct *inova, *next;
+
+ for (inova = inova_devices; inova; inova = next) {
+ next = inova->next;
+ pci_dev_put(inova->pcidev);
+ kfree(inova);
+ }
+
+ inova_devices = NULL;
+}
+
+/****************************************************************************/
+/* find first unused card with this device_id */
+static struct pcilst_struct *find_free_pci_card_by_device(unsigned short
+ vendor_id, unsigned short device_id)
+{
+ struct pcilst_struct *inova, *next;
+
+ for (inova = inova_devices; inova; inova = next) {
+ next = inova->next;
+ if ((!inova->used) && (inova->device == device_id)
+ && (inova->vendor == vendor_id))
+ return inova;
+
+ }
+
+ return NULL;
+}
+
+/****************************************************************************/
+/* find card on requested position */
+static int find_free_pci_card_by_position(unsigned short vendor_id,
+ unsigned short device_id, unsigned short pci_bus,
+ unsigned short pci_slot, struct pcilst_struct **card)
+{
+ struct pcilst_struct *inova, *next;
+
+ *card = NULL;
+ for (inova = inova_devices; inova; inova = next) {
+ next = inova->next;
+ if ((inova->vendor == vendor_id) && (inova->device == device_id)
+ && (inova->pci_bus == pci_bus)
+ && (inova->pci_slot == pci_slot)) {
+ if (!(inova->used)) {
+ *card = inova;
+ return 0; // ok, card is found
+ } else {
+ return 2; // card exist but is used
+ }
+ }
+ }
+
+ return 1; // no card found
+}
+
+/****************************************************************************/
+/* mark card as used */
+static int pci_card_alloc(struct pcilst_struct *inova)
+{
+ int i;
+
+ if (!inova) {
+ rt_printk(" - BUG!! inova is NULL!\n");
+ return -1;
+ }
+
+ if (inova->used)
+ return 1;
+ if (comedi_pci_enable(inova->pcidev, "icp_multi")) {
+ rt_printk(" - Can't enable PCI device and request regions!\n");
+ return -1;
+ }
+ /* Resources will be accurate now. */
+ for (i = 0; i < 5; i++)
+ inova->io_addr[i] = pci_resource_start(inova->pcidev, i);
+ inova->irq = inova->pcidev->irq;
+ inova->used = 1;
+ return 0;
+}
+
+/****************************************************************************/
+/* mark card as free */
+static int pci_card_free(struct pcilst_struct *inova)
+{
+ if (!inova)
+ return -1;
+
+ if (!inova->used)
+ return 1;
+ inova->used = 0;
+ comedi_pci_disable(inova->pcidev);
+ return 0;
+}
+
+/****************************************************************************/
+/* display list of found cards */
+static void pci_card_list_display(void)
+{
+ struct pcilst_struct *inova, *next;
+
+ printk("Anne's List of pci cards\n");
+ printk("bus:slot:func vendor device io_inova io_daq irq used\n");
+
+ for (inova = inova_devices; inova; inova = next) {
+ next = inova->next;
+ printk("%2d %2d %2d 0x%4x 0x%4x 0x%8llx 0x%8llx %2u %2d\n", inova->pci_bus, inova->pci_slot, inova->pci_func, inova->vendor, inova->device, (unsigned long long)inova->io_addr[0], (unsigned long long)inova->io_addr[2], inova->irq, inova->used);
+
+ }
+}
+
+/****************************************************************************/
+/* return all card information for driver */
+static int pci_card_data(struct pcilst_struct *inova,
+ unsigned char *pci_bus, unsigned char *pci_slot,
+ unsigned char *pci_func, resource_size_t * io_addr, unsigned int *irq)
+{
+ int i;
+
+ if (!inova)
+ return -1;
+ *pci_bus = inova->pci_bus;
+ *pci_slot = inova->pci_slot;
+ *pci_func = inova->pci_func;
+ for (i = 0; i < 5; i++)
+ io_addr[i] = inova->io_addr[i];
+ *irq = inova->irq;
+ return 0;
+}
+
+/****************************************************************************/
+/* select and alloc card */
+static struct pcilst_struct *select_and_alloc_pci_card(unsigned short vendor_id,
+ unsigned short device_id, unsigned short pci_bus,
+ unsigned short pci_slot)
+{
+ struct pcilst_struct *card;
+ int err;
+
+ if ((pci_bus < 1) & (pci_slot < 1)) { // use autodetection
+ if ((card = find_free_pci_card_by_device(vendor_id,
+ device_id)) == NULL) {
+ rt_printk(" - Unused card not found in system!\n");
+ return NULL;
+ }
+ } else {
+ switch (find_free_pci_card_by_position(vendor_id, device_id,
+ pci_bus, pci_slot, &card)) {
+ case 1:
+ rt_printk
+ (" - Card not found on requested position b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return NULL;
+ case 2:
+ rt_printk
+ (" - Card on requested position is used b:s %d:%d!\n",
+ pci_bus, pci_slot);
+ return NULL;
+ }
+ }
+
+ if ((err = pci_card_alloc(card)) != 0) {
+ if (err > 0)
+ rt_printk(" - Can't allocate card!\n");
+ /* else: error already printed. */
+ return NULL;
+ }
+
+ return card;
+}
+
+#endif
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
new file mode 100644
index 000000000000..b432aa7d7644
--- /dev/null
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -0,0 +1,2362 @@
+/*
+ comedi/drivers/me4000.c
+ Source code for the Meilhaus ME-4000 board family.
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+/*
+Driver: me4000
+Description: Meilhaus ME-4000 series boards
+Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
+Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
+Updated: Mon, 18 Mar 2002 15:34:01 -0800
+Status: broken (no support for loading firmware)
+
+Supports:
+
+ - Analog Input
+ - Analog Output
+ - Digital I/O
+ - Counter
+
+Configuration Options:
+
+ [0] - PCI bus number (optional)
+ [1] - PCI slot number (optional)
+
+ If bus/slot is not specified, the first available PCI
+ device will be used.
+
+The firmware required by these boards is available in the
+comedi_nonfree_firmware tarball available from
+http://www.comedi.org. However, the driver's support for
+loading the firmware through comedi_config is currently
+broken.
+
+ */
+
+#include "../comedidev.h"
+
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "comedi_pci.h"
+#include "me4000.h"
+#if 0
+/* file removed due to GPL incompatibility */
+#include "me4000_fw.h"
+#endif
+
+/*=============================================================================
+ PCI device table.
+ This is used by modprobe to translate PCI IDs to drivers.
+ ===========================================================================*/
+
+static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
+ {PCI_VENDOR_ID_MEILHAUS, 0x4650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4661, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4662, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, 0x4680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4681, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4682, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, 0x4683, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, me4000_pci_table);
+
+static const me4000_board_t me4000_boards[] = {
+ {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}},
+
+ {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
+ {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
+ {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
+ {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
+
+ {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
+ {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
+ {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
+ {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
+
+ {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
+ {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
+ {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
+ {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
+
+ {0},
+};
+
+#define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(me4000_board_t) - 1)
+
+/*-----------------------------------------------------------------------------
+ Comedi function prototypes
+ ---------------------------------------------------------------------------*/
+static int me4000_attach(comedi_device * dev, comedi_devconfig * it);
+static int me4000_detach(comedi_device * dev);
+static comedi_driver driver_me4000 = {
+ driver_name:"me4000",
+ module:THIS_MODULE,
+ attach:me4000_attach,
+ detach:me4000_detach,
+};
+
+/*-----------------------------------------------------------------------------
+ Meilhaus function prototypes
+ ---------------------------------------------------------------------------*/
+static int me4000_probe(comedi_device * dev, comedi_devconfig * it);
+static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p);
+static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p);
+static int init_ao_context(comedi_device * dev);
+static int init_ai_context(comedi_device * dev);
+static int init_dio_context(comedi_device * dev);
+static int init_cnt_context(comedi_device * dev);
+static int xilinx_download(comedi_device * dev);
+static int reset_board(comedi_device * dev);
+
+static int me4000_dio_insn_bits(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+static int me4000_dio_insn_config(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+static int cnt_reset(comedi_device * dev, unsigned int channel);
+
+static int cnt_config(comedi_device * dev,
+ unsigned int channel, unsigned int mode);
+
+static int me4000_cnt_insn_config(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+static int me4000_cnt_insn_write(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+static int me4000_cnt_insn_read(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+static int me4000_ai_insn_read(comedi_device * dev,
+ comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data);
+
+static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+
+static int ai_check_chanlist(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd);
+
+static int ai_round_cmd_args(comedi_device * dev,
+ comedi_subdevice * s,
+ comedi_cmd * cmd,
+ unsigned int *init_ticks,
+ unsigned int *scan_ticks, unsigned int *chan_ticks);
+
+static int ai_prepare(comedi_device * dev,
+ comedi_subdevice * s,
+ comedi_cmd * cmd,
+ unsigned int init_ticks,
+ unsigned int scan_ticks, unsigned int chan_ticks);
+
+static int ai_write_chanlist(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd);
+
+static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG);
+
+static int me4000_ai_do_cmd_test(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd);
+
+static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s);
+
+static int me4000_ao_insn_write(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+static int me4000_ao_insn_read(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
+
+/*-----------------------------------------------------------------------------
+ Meilhaus inline functions
+ ---------------------------------------------------------------------------*/
+
+static inline void me4000_outb(comedi_device * dev, unsigned char value,
+ unsigned long port)
+{
+ PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
+ outb(value, port);
+}
+
+static inline void me4000_outl(comedi_device * dev, unsigned long value,
+ unsigned long port)
+{
+ PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
+ outl(value, port);
+}
+
+static inline unsigned long me4000_inl(comedi_device * dev, unsigned long port)
+{
+ unsigned long value;
+ value = inl(port);
+ PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port);
+ return value;
+}
+
+static inline unsigned char me4000_inb(comedi_device * dev, unsigned long port)
+{
+ unsigned char value;
+ value = inb(port);
+ PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port);
+ return value;
+}
+
+static const comedi_lrange me4000_ai_range = {
+ 4,
+ {
+ UNI_RANGE(2.5),
+ UNI_RANGE(10),
+ BIP_RANGE(2.5),
+ BIP_RANGE(10),
+ }
+};
+
+static const comedi_lrange me4000_ao_range = {
+ 1,
+ {
+ BIP_RANGE(10),
+ }
+};
+
+static int me4000_attach(comedi_device * dev, comedi_devconfig * it)
+{
+ comedi_subdevice *s;
+ int result;
+
+ CALL_PDEBUG("In me4000_attach()\n");
+
+ result = me4000_probe(dev, it);
+ if (result)
+ return result;
+
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h. It relies on
+ * n_subdevices being set correctly.
+ */
+ if (alloc_subdevices(dev, 4) < 0)
+ return -ENOMEM;
+
+ /*=========================================================================
+ Analog input subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 0;
+
+ if (thisboard->ai.count) {
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags =
+ SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
+ s->n_chan = thisboard->ai.count;
+ s->maxdata = 0xFFFF; // 16 bit ADC
+ s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
+ s->range_table = &me4000_ai_range;
+ s->insn_read = me4000_ai_insn_read;
+
+ if (info->irq > 0) {
+ if (comedi_request_irq(info->irq, me4000_ai_isr,
+ IRQF_SHARED, "ME-4000", dev)) {
+ printk("comedi%d: me4000: me4000_attach(): Unable to allocate irq\n", dev->minor);
+ } else {
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->cancel = me4000_ai_cancel;
+ s->do_cmdtest = me4000_ai_do_cmd_test;
+ s->do_cmd = me4000_ai_do_cmd;
+ }
+ } else {
+ printk(KERN_WARNING
+ "comedi%d: me4000: me4000_attach(): No interrupt available\n",
+ dev->minor);
+ }
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /*=========================================================================
+ Analog output subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 1;
+
+ if (thisboard->ao.count) {
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
+ s->n_chan = thisboard->ao.count;
+ s->maxdata = 0xFFFF; // 16 bit DAC
+ s->range_table = &me4000_ao_range;
+ s->insn_write = me4000_ao_insn_write;
+ s->insn_read = me4000_ao_insn_read;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /*=========================================================================
+ Digital I/O subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 2;
+
+ if (thisboard->dio.count) {
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = thisboard->dio.count * 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = me4000_dio_insn_bits;
+ s->insn_config = me4000_dio_insn_config;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ /*
+ * Check for optoisolated ME-4000 version. If one the first
+ * port is a fixed output port and the second is a fixed input port.
+ */
+ if (!me4000_inl(dev, info->dio_context.dir_reg)) {
+ s->io_bits |= 0xFF;
+ me4000_outl(dev, ME4000_DIO_CTRL_BIT_MODE_0,
+ info->dio_context.dir_reg);
+ }
+
+ /*=========================================================================
+ Counter subdevice
+ ========================================================================*/
+
+ s = dev->subdevices + 3;
+
+ if (thisboard->cnt.count) {
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = thisboard->cnt.count;
+ s->maxdata = 0xFFFF; // 16 bit counters
+ s->insn_read = me4000_cnt_insn_read;
+ s->insn_write = me4000_cnt_insn_write;
+ s->insn_config = me4000_cnt_insn_config;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ return 0;
+}
+
+static int me4000_probe(comedi_device * dev, comedi_devconfig * it)
+{
+ struct pci_dev *pci_device;
+ int result, i;
+ me4000_board_t *board;
+
+ CALL_PDEBUG("In me4000_probe()\n");
+
+ /* Allocate private memory */
+ if (alloc_private(dev, sizeof(me4000_info_t)) < 0) {
+ return -ENOMEM;
+ }
+ /*
+ * Probe the device to determine what device in the series it is.
+ */
+ for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ pci_device != NULL;
+ pci_device =
+ pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
+ if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
+ for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
+ if (me4000_boards[i].device_id ==
+ pci_device->device) {
+ /* Was a particular bus/slot requested? */
+ if ((it->options[0] != 0)
+ || (it->options[1] != 0)) {
+ /* Are we on the wrong bus/slot? */
+ if (pci_device->bus->number !=
+ it->options[0]
+ || PCI_SLOT(pci_device->
+ devfn) !=
+ it->options[1]) {
+ continue;
+ }
+ }
+ dev->board_ptr = me4000_boards + i;
+ board = (me4000_board_t *) dev->
+ board_ptr;
+ info->pci_dev_p = pci_device;
+ goto found;
+ }
+ }
+ }
+ }
+
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): No supported board found (req. bus/slot : %d/%d)\n",
+ dev->minor, it->options[0], it->options[1]);
+ return -ENODEV;
+
+ found:
+
+ printk(KERN_INFO
+ "comedi%d: me4000: me4000_probe(): Found %s at PCI bus %d, slot %d\n",
+ dev->minor, me4000_boards[i].name, pci_device->bus->number,
+ PCI_SLOT(pci_device->devfn));
+
+ /* Set data in device structure */
+ dev->board_name = board->name;
+
+ /* Enable PCI device and request regions */
+ result = comedi_pci_enable(pci_device, dev->board_name);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Cannot enable PCI device and request I/O regions\n",
+ dev->minor);
+ return result;
+ }
+
+ /* Get the PCI base registers */
+ result = get_registers(dev, pci_device);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Cannot get registers\n",
+ dev->minor);
+ return result;
+ }
+ /* Initialize board info */
+ result = init_board_info(dev, pci_device);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Cannot init baord info\n",
+ dev->minor);
+ return result;
+ }
+
+ /* Init analog output context */
+ result = init_ao_context(dev);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Cannot init ao context\n",
+ dev->minor);
+ return result;
+ }
+
+ /* Init analog input context */
+ result = init_ai_context(dev);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Cannot init ai context\n",
+ dev->minor);
+ return result;
+ }
+
+ /* Init digital I/O context */
+ result = init_dio_context(dev);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Cannot init dio context\n",
+ dev->minor);
+ return result;
+ }
+
+ /* Init counter context */
+ result = init_cnt_context(dev);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Cannot init cnt context\n",
+ dev->minor);
+ return result;
+ }
+
+ /* Download the xilinx firmware */
+ result = xilinx_download(dev);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Can't download firmware\n",
+ dev->minor);
+ return result;
+ }
+
+ /* Make a hardware reset */
+ result = reset_board(dev);
+ if (result) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_probe(): Can't reset board\n",
+ dev->minor);
+ return result;
+ }
+
+ return 0;
+}
+
+static int get_registers(comedi_device * dev, struct pci_dev *pci_dev_p)
+{
+
+ CALL_PDEBUG("In get_registers()\n");
+
+ /*--------------------------- plx regbase ---------------------------------*/
+
+ info->plx_regbase = pci_resource_start(pci_dev_p, 1);
+ if (info->plx_regbase == 0) {
+ printk(KERN_ERR
+ "comedi%d: me4000: get_registers(): PCI base address 1 is not available\n",
+ dev->minor);
+ return -ENODEV;
+ }
+ info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
+
+ /*--------------------------- me4000 regbase ------------------------------*/
+
+ info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
+ if (info->me4000_regbase == 0) {
+ printk(KERN_ERR
+ "comedi%d: me4000: get_registers(): PCI base address 2 is not available\n",
+ dev->minor);
+ return -ENODEV;
+ }
+ info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
+
+ /*--------------------------- timer regbase ------------------------------*/
+
+ info->timer_regbase = pci_resource_start(pci_dev_p, 3);
+ if (info->timer_regbase == 0) {
+ printk(KERN_ERR
+ "comedi%d: me4000: get_registers(): PCI base address 3 is not available\n",
+ dev->minor);
+ return -ENODEV;
+ }
+ info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
+
+ /*--------------------------- program regbase ------------------------------*/
+
+ info->program_regbase = pci_resource_start(pci_dev_p, 5);
+ if (info->program_regbase == 0) {
+ printk(KERN_ERR
+ "comedi%d: me4000: get_registers(): PCI base address 5 is not available\n",
+ dev->minor);
+ return -ENODEV;
+ }
+ info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
+
+ return 0;
+}
+
+static int init_board_info(comedi_device * dev, struct pci_dev *pci_dev_p)
+{
+ int result;
+
+ CALL_PDEBUG("In init_board_info()\n");
+
+ /* Init spin locks */
+ //spin_lock_init(&info->preload_lock);
+ //spin_lock_init(&info->ai_ctrl_lock);
+
+ /* Get the serial number */
+ result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ return result;
+ }
+
+ /* Get the hardware revision */
+ result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
+ if (result != PCIBIOS_SUCCESSFUL) {
+ return result;
+ }
+
+ /* Get the vendor id */
+ info->vendor_id = pci_dev_p->vendor;
+
+ /* Get the device id */
+ info->device_id = pci_dev_p->device;
+
+ /* Get the irq assigned to the board */
+ info->irq = pci_dev_p->irq;
+
+ return 0;
+}
+
+static int init_ao_context(comedi_device * dev)
+{
+ int i;
+
+ CALL_PDEBUG("In init_ao_context()\n");
+
+ for (i = 0; i < thisboard->ao.count; i++) {
+ //spin_lock_init(&info->ao_context[i].use_lock);
+ info->ao_context[i].irq = info->irq;
+
+ switch (i) {
+ case 0:
+ info->ao_context[i].ctrl_reg =
+ info->me4000_regbase + ME4000_AO_00_CTRL_REG;
+ info->ao_context[i].status_reg =
+ info->me4000_regbase + ME4000_AO_00_STATUS_REG;
+ info->ao_context[i].fifo_reg =
+ info->me4000_regbase + ME4000_AO_00_FIFO_REG;
+ info->ao_context[i].single_reg =
+ info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
+ info->ao_context[i].timer_reg =
+ info->me4000_regbase + ME4000_AO_00_TIMER_REG;
+ info->ao_context[i].irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ info->ao_context[i].preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ case 1:
+ info->ao_context[i].ctrl_reg =
+ info->me4000_regbase + ME4000_AO_01_CTRL_REG;
+ info->ao_context[i].status_reg =
+ info->me4000_regbase + ME4000_AO_01_STATUS_REG;
+ info->ao_context[i].fifo_reg =
+ info->me4000_regbase + ME4000_AO_01_FIFO_REG;
+ info->ao_context[i].single_reg =
+ info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
+ info->ao_context[i].timer_reg =
+ info->me4000_regbase + ME4000_AO_01_TIMER_REG;
+ info->ao_context[i].irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ info->ao_context[i].preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ case 2:
+ info->ao_context[i].ctrl_reg =
+ info->me4000_regbase + ME4000_AO_02_CTRL_REG;
+ info->ao_context[i].status_reg =
+ info->me4000_regbase + ME4000_AO_02_STATUS_REG;
+ info->ao_context[i].fifo_reg =
+ info->me4000_regbase + ME4000_AO_02_FIFO_REG;
+ info->ao_context[i].single_reg =
+ info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
+ info->ao_context[i].timer_reg =
+ info->me4000_regbase + ME4000_AO_02_TIMER_REG;
+ info->ao_context[i].irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ info->ao_context[i].preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ case 3:
+ info->ao_context[i].ctrl_reg =
+ info->me4000_regbase + ME4000_AO_03_CTRL_REG;
+ info->ao_context[i].status_reg =
+ info->me4000_regbase + ME4000_AO_03_STATUS_REG;
+ info->ao_context[i].fifo_reg =
+ info->me4000_regbase + ME4000_AO_03_FIFO_REG;
+ info->ao_context[i].single_reg =
+ info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
+ info->ao_context[i].timer_reg =
+ info->me4000_regbase + ME4000_AO_03_TIMER_REG;
+ info->ao_context[i].irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ info->ao_context[i].preload_reg =
+ info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int init_ai_context(comedi_device * dev)
+{
+
+ CALL_PDEBUG("In init_ai_context()\n");
+
+ info->ai_context.irq = info->irq;
+
+ info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
+ info->ai_context.status_reg =
+ info->me4000_regbase + ME4000_AI_STATUS_REG;
+ info->ai_context.channel_list_reg =
+ info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
+ info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
+ info->ai_context.chan_timer_reg =
+ info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
+ info->ai_context.chan_pre_timer_reg =
+ info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
+ info->ai_context.scan_timer_low_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
+ info->ai_context.scan_timer_high_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
+ info->ai_context.scan_pre_timer_low_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
+ info->ai_context.scan_pre_timer_high_reg =
+ info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
+ info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
+ info->ai_context.irq_status_reg =
+ info->me4000_regbase + ME4000_IRQ_STATUS_REG;
+ info->ai_context.sample_counter_reg =
+ info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
+
+ return 0;
+}
+
+static int init_dio_context(comedi_device * dev)
+{
+
+ CALL_PDEBUG("In init_dio_context()\n");
+
+ info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
+ info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
+ info->dio_context.port_0_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_0_REG;
+ info->dio_context.port_1_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_1_REG;
+ info->dio_context.port_2_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_2_REG;
+ info->dio_context.port_3_reg =
+ info->me4000_regbase + ME4000_DIO_PORT_3_REG;
+
+ return 0;
+}
+
+static int init_cnt_context(comedi_device * dev)
+{
+
+ CALL_PDEBUG("In init_cnt_context()\n");
+
+ info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG;
+ info->cnt_context.counter_0_reg =
+ info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
+ info->cnt_context.counter_1_reg =
+ info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
+ info->cnt_context.counter_2_reg =
+ info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
+
+ return 0;
+}
+
+#define FIRMWARE_NOT_AVAILABLE 1
+#if FIRMWARE_NOT_AVAILABLE
+extern unsigned char *xilinx_firm;
+#endif
+
+static int xilinx_download(comedi_device * dev)
+{
+ u32 value = 0;
+ wait_queue_head_t queue;
+ int idx = 0;
+ int size = 0;
+
+ CALL_PDEBUG("In xilinx_download()\n");
+
+ init_waitqueue_head(&queue);
+
+ /*
+ * Set PLX local interrupt 2 polarity to high.
+ * Interrupt is thrown by init pin of xilinx.
+ */
+ outl(0x10, info->plx_regbase + PLX_INTCSR);
+
+ /* Set /CS and /WRITE of the Xilinx */
+ value = inl(info->plx_regbase + PLX_ICR);
+ value |= 0x100;
+ outl(value, info->plx_regbase + PLX_ICR);
+
+ /* Init Xilinx with CS1 */
+ inb(info->program_regbase + 0xC8);
+
+ /* Wait until /INIT pin is set */
+ udelay(20);
+ if (!inl(info->plx_regbase + PLX_INTCSR) & 0x20) {
+ printk(KERN_ERR
+ "comedi%d: me4000: xilinx_download(): Can't init Xilinx\n",
+ dev->minor);
+ return -EIO;
+ }
+
+ /* Reset /CS and /WRITE of the Xilinx */
+ value = inl(info->plx_regbase + PLX_ICR);
+ value &= ~0x100;
+ outl(value, info->plx_regbase + PLX_ICR);
+ if (FIRMWARE_NOT_AVAILABLE) {
+ comedi_error(dev,
+ "xilinx firmware unavailable due to licensing, aborting");
+ return -EIO;
+ } else {
+ /* Download Xilinx firmware */
+ size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
+ (xilinx_firm[2] << 8) + xilinx_firm[3];
+ udelay(10);
+
+ for (idx = 0; idx < size; idx++) {
+ outb(xilinx_firm[16 + idx], info->program_regbase);
+ udelay(10);
+
+ /* Check if BUSY flag is low */
+ if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
+ printk(KERN_ERR
+ "comedi%d: me4000: xilinx_download(): Xilinx is still busy (idx = %d)\n",
+ dev->minor, idx);
+ return -EIO;
+ }
+ }
+ }
+
+ /* If done flag is high download was successful */
+ if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
+ } else {
+ printk(KERN_ERR
+ "comedi%d: me4000: xilinx_download(): DONE flag is not set\n",
+ dev->minor);
+ printk(KERN_ERR
+ "comedi%d: me4000: xilinx_download(): Download not succesful\n",
+ dev->minor);
+ return -EIO;
+ }
+
+ /* Set /CS and /WRITE */
+ value = inl(info->plx_regbase + PLX_ICR);
+ value |= 0x100;
+ outl(value, info->plx_regbase + PLX_ICR);
+
+ return 0;
+}
+
+static int reset_board(comedi_device * dev)
+{
+ unsigned long icr;
+
+ CALL_PDEBUG("In reset_board()\n");
+
+ /* Make a hardware reset */
+ icr = me4000_inl(dev, info->plx_regbase + PLX_ICR);
+ icr |= 0x40000000;
+ me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
+ icr &= ~0x40000000;
+ me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
+
+ /* 0x8000 to the DACs means an output voltage of 0V */
+ me4000_outl(dev, 0x8000,
+ info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
+ me4000_outl(dev, 0x8000,
+ info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
+ me4000_outl(dev, 0x8000,
+ info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
+ me4000_outl(dev, 0x8000,
+ info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
+
+ /* Set both stop bits in the analog input control register */
+ me4000_outl(dev,
+ ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AI_CTRL_REG);
+
+ /* Set both stop bits in the analog output control register */
+ me4000_outl(dev,
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_00_CTRL_REG);
+ me4000_outl(dev,
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_01_CTRL_REG);
+ me4000_outl(dev,
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_02_CTRL_REG);
+ me4000_outl(dev,
+ ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
+ info->me4000_regbase + ME4000_AO_03_CTRL_REG);
+
+ /* Enable interrupts on the PLX */
+ me4000_outl(dev, 0x43, info->plx_regbase + PLX_INTCSR);
+
+ /* Set the adustment register for AO demux */
+ me4000_outl(dev, ME4000_AO_DEMUX_ADJUST_VALUE,
+ info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
+
+ /* Set digital I/O direction for port 0 to output on isolated versions */
+ if (!(me4000_inl(dev, info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) {
+ me4000_outl(dev, 0x1,
+ info->me4000_regbase + ME4000_DIO_CTRL_REG);
+ }
+
+ return 0;
+}
+
+static int me4000_detach(comedi_device * dev)
+{
+ CALL_PDEBUG("In me4000_detach()\n");
+
+ if (info) {
+ if (info->pci_dev_p) {
+ reset_board(dev);
+ if (info->plx_regbase) {
+ comedi_pci_disable(info->pci_dev_p);
+ }
+ pci_dev_put(info->pci_dev_p);
+ }
+ }
+
+ return 0;
+}
+
+/*=============================================================================
+ Analog input section
+ ===========================================================================*/
+
+static int me4000_ai_insn_read(comedi_device * dev,
+ comedi_subdevice * subdevice, comedi_insn * insn, lsampl_t * data)
+{
+
+ int chan = CR_CHAN(insn->chanspec);
+ int rang = CR_RANGE(insn->chanspec);
+ int aref = CR_AREF(insn->chanspec);
+
+ unsigned long entry = 0;
+ unsigned long tmp;
+ long lval;
+
+ CALL_PDEBUG("In me4000_ai_insn_read()\n");
+
+ if (insn->n == 0) {
+ return 0;
+ } else if (insn->n > 1) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_insn_read(): Invalid instruction length %d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ switch (rang) {
+ case 0:
+ entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
+ break;
+ case 1:
+ entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
+ break;
+ case 2:
+ entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
+ break;
+ case 3:
+ entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_insn_read(): Invalid range specified\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ switch (aref) {
+ case AREF_GROUND:
+ case AREF_COMMON:
+ if (chan >= thisboard->ai.count) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
+ dev->minor);
+ return -EINVAL;
+ }
+ entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
+ break;
+
+ case AREF_DIFF:
+ if (rang == 0 || rang == 1) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_insn_read(): Range must be bipolar when aref = diff\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ if (chan >= thisboard->ai.diff_count) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
+ dev->minor);
+ return -EINVAL;
+ }
+ entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_insn_read(): Invalid aref specified\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ entry |= ME4000_AI_LIST_LAST_ENTRY;
+
+ /* Clear channel list, data fifo and both stop bits */
+ tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
+ tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
+ ME4000_AI_CTRL_BIT_DATA_FIFO |
+ ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
+ me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
+
+ /* Set the acquisition mode to single */
+ tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
+ ME4000_AI_CTRL_BIT_MODE_2);
+ me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
+
+ /* Enable channel list and data fifo */
+ tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
+ me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
+
+ /* Generate channel list entry */
+ me4000_outl(dev, entry, info->ai_context.channel_list_reg);
+
+ /* Set the timer to maximum sample rate */
+ me4000_outl(dev, ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
+ me4000_outl(dev, ME4000_AI_MIN_TICKS,
+ info->ai_context.chan_pre_timer_reg);
+
+ /* Start conversion by dummy read */
+ me4000_inl(dev, info->ai_context.start_reg);
+
+ /* Wait until ready */
+ udelay(10);
+ if (!(me4000_inl(dev, info->ai_context.
+ status_reg) & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_insn_read(): Value not available after wait\n",
+ dev->minor);
+ return -EIO;
+ }
+
+ /* Read value from data fifo */
+ lval = me4000_inl(dev, info->ai_context.data_reg) & 0xFFFF;
+ data[0] = lval ^ 0x8000;
+
+ return 1;
+}
+
+static int me4000_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+{
+ unsigned long tmp;
+
+ CALL_PDEBUG("In me4000_ai_cancel()\n");
+
+ /* Stop any running conversion */
+ tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
+ tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
+ me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
+
+ /* Clear the control register */
+ me4000_outl(dev, 0x0, info->ai_context.ctrl_reg);
+
+ return 0;
+}
+
+static int ai_check_chanlist(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd)
+{
+ int aref;
+ int i;
+
+ CALL_PDEBUG("In ai_check_chanlist()\n");
+
+ /* Check whether a channel list is available */
+ if (!cmd->chanlist_len) {
+ printk(KERN_ERR
+ "comedi%d: me4000: ai_check_chanlist(): No channel list available\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ /* Check the channel list size */
+ if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
+ printk(KERN_ERR
+ "comedi%d: me4000: ai_check_chanlist(): Channel list is to large\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ /* Check the pointer */
+ if (!cmd->chanlist) {
+ printk(KERN_ERR
+ "comedi%d: me4000: ai_check_chanlist(): NULL pointer to channel list\n",
+ dev->minor);
+ return -EFAULT;
+ }
+
+ /* Check whether aref is equal for all entries */
+ aref = CR_AREF(cmd->chanlist[0]);
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ if (CR_AREF(cmd->chanlist[i]) != aref) {
+ printk(KERN_ERR
+ "comedi%d: me4000: ai_check_chanlist(): Mode is not equal for all entries\n",
+ dev->minor);
+ return -EINVAL;
+ }
+ }
+
+ /* Check whether channels are available for this ending */
+ if (aref == SDF_DIFF) {
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ if (CR_CHAN(cmd->chanlist[i]) >=
+ thisboard->ai.diff_count) {
+ printk(KERN_ERR
+ "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
+ dev->minor);
+ return -EINVAL;
+ }
+ }
+ } else {
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) {
+ printk(KERN_ERR
+ "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
+ dev->minor);
+ return -EINVAL;
+ }
+ }
+ }
+
+ /* Check if bipolar is set for all entries when in differential mode */
+ if (aref == SDF_DIFF) {
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ if (CR_RANGE(cmd->chanlist[i]) != 1 &&
+ CR_RANGE(cmd->chanlist[i]) != 2) {
+ printk(KERN_ERR
+ "comedi%d: me4000: ai_check_chanlist(): Bipolar is not selected in differential mode\n",
+ dev->minor);
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int ai_round_cmd_args(comedi_device * dev,
+ comedi_subdevice * s,
+ comedi_cmd * cmd,
+ unsigned int *init_ticks,
+ unsigned int *scan_ticks, unsigned int *chan_ticks)
+{
+
+ int rest;
+
+ CALL_PDEBUG("In ai_round_cmd_args()\n");
+
+ *init_ticks = 0;
+ *scan_ticks = 0;
+ *chan_ticks = 0;
+
+ PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd->start_arg);
+ PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n",
+ cmd->scan_begin_arg);
+ PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd->convert_arg);
+
+ if (cmd->start_arg) {
+ *init_ticks = (cmd->start_arg * 33) / 1000;
+ rest = (cmd->start_arg * 33) % 1000;
+
+ if (cmd->flags & TRIG_ROUND_NEAREST) {
+ if (rest > 33) {
+ (*init_ticks)++;
+ }
+ } else if (cmd->flags & TRIG_ROUND_UP) {
+ if (rest)
+ (*init_ticks)++;
+ }
+ }
+
+ if (cmd->scan_begin_arg) {
+ *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
+ rest = (cmd->scan_begin_arg * 33) % 1000;
+
+ if (cmd->flags & TRIG_ROUND_NEAREST) {
+ if (rest > 33) {
+ (*scan_ticks)++;
+ }
+ } else if (cmd->flags & TRIG_ROUND_UP) {
+ if (rest)
+ (*scan_ticks)++;
+ }
+ }
+
+ if (cmd->convert_arg) {
+ *chan_ticks = (cmd->convert_arg * 33) / 1000;
+ rest = (cmd->convert_arg * 33) % 1000;
+
+ if (cmd->flags & TRIG_ROUND_NEAREST) {
+ if (rest > 33) {
+ (*chan_ticks)++;
+ }
+ } else if (cmd->flags & TRIG_ROUND_UP) {
+ if (rest)
+ (*chan_ticks)++;
+ }
+ }
+
+ PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks);
+ PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks);
+ PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks);
+
+ return 0;
+}
+
+static void ai_write_timer(comedi_device * dev,
+ unsigned int init_ticks,
+ unsigned int scan_ticks, unsigned int chan_ticks)
+{
+
+ CALL_PDEBUG("In ai_write_timer()\n");
+
+ me4000_outl(dev, init_ticks - 1,
+ info->ai_context.scan_pre_timer_low_reg);
+ me4000_outl(dev, 0x0, info->ai_context.scan_pre_timer_high_reg);
+
+ if (scan_ticks) {
+ me4000_outl(dev, scan_ticks - 1,
+ info->ai_context.scan_timer_low_reg);
+ me4000_outl(dev, 0x0, info->ai_context.scan_timer_high_reg);
+ }
+
+ me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
+ me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg);
+}
+
+static int ai_prepare(comedi_device * dev,
+ comedi_subdevice * s,
+ comedi_cmd * cmd,
+ unsigned int init_ticks,
+ unsigned int scan_ticks, unsigned int chan_ticks)
+{
+
+ unsigned long tmp = 0;
+
+ CALL_PDEBUG("In ai_prepare()\n");
+
+ /* Write timer arguments */
+ ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
+
+ /* Reset control register */
+ me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
+
+ /* Start sources */
+ if ((cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_TIMER &&
+ cmd->convert_src == TRIG_TIMER) ||
+ (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_FOLLOW &&
+ cmd->convert_src == TRIG_TIMER)) {
+ tmp = ME4000_AI_CTRL_BIT_MODE_1 |
+ ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
+ ME4000_AI_CTRL_BIT_DATA_FIFO;
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_EXT &&
+ cmd->convert_src == TRIG_TIMER) {
+ tmp = ME4000_AI_CTRL_BIT_MODE_2 |
+ ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
+ ME4000_AI_CTRL_BIT_DATA_FIFO;
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_EXT &&
+ cmd->convert_src == TRIG_EXT) {
+ tmp = ME4000_AI_CTRL_BIT_MODE_0 |
+ ME4000_AI_CTRL_BIT_MODE_1 |
+ ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
+ ME4000_AI_CTRL_BIT_DATA_FIFO;
+ } else {
+ tmp = ME4000_AI_CTRL_BIT_MODE_0 |
+ ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
+ ME4000_AI_CTRL_BIT_DATA_FIFO;
+ }
+
+ /* Stop triggers */
+ if (cmd->stop_src == TRIG_COUNT) {
+ me4000_outl(dev, cmd->chanlist_len * cmd->stop_arg,
+ info->ai_context.sample_counter_reg);
+ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
+ } else if (cmd->stop_src == TRIG_NONE &&
+ cmd->scan_end_src == TRIG_COUNT) {
+ me4000_outl(dev, cmd->scan_end_arg,
+ info->ai_context.sample_counter_reg);
+ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
+ } else {
+ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
+ }
+
+ /* Write the setup to the control register */
+ me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
+
+ /* Write the channel list */
+ ai_write_chanlist(dev, s, cmd);
+
+ return 0;
+}
+
+static int ai_write_chanlist(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd)
+{
+ unsigned int entry;
+ unsigned int chan;
+ unsigned int rang;
+ unsigned int aref;
+ int i;
+
+ CALL_PDEBUG("In ai_write_chanlist()\n");
+
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ chan = CR_CHAN(cmd->chanlist[i]);
+ rang = CR_RANGE(cmd->chanlist[i]);
+ aref = CR_AREF(cmd->chanlist[i]);
+
+ entry = chan;
+
+ if (rang == 0) {
+ entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
+ } else if (rang == 1) {
+ entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
+ } else if (rang == 2) {
+ entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
+ } else {
+ entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
+ }
+
+ if (aref == SDF_DIFF) {
+ entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
+ } else {
+ entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
+ }
+
+ me4000_outl(dev, entry, info->ai_context.channel_list_reg);
+ }
+
+ return 0;
+}
+
+static int me4000_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
+{
+ int err;
+ unsigned int init_ticks = 0;
+ unsigned int scan_ticks = 0;
+ unsigned int chan_ticks = 0;
+ comedi_cmd *cmd = &s->async->cmd;
+
+ CALL_PDEBUG("In me4000_ai_do_cmd()\n");
+
+ /* Reset the analog input */
+ err = me4000_ai_cancel(dev, s);
+ if (err)
+ return err;
+
+ /* Round the timer arguments */
+ err = ai_round_cmd_args(dev,
+ s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
+ if (err)
+ return err;
+
+ /* Prepare the AI for acquisition */
+ err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
+ if (err)
+ return err;
+
+ /* Start acquistion by dummy read */
+ me4000_inl(dev, info->ai_context.start_reg);
+
+ return 0;
+}
+
+/*
+ * me4000_ai_do_cmd_test():
+ *
+ * The demo cmd.c in ./comedilib/demo specifies 6 return values:
+ * - success
+ * - invalid source
+ * - source conflict
+ * - invalid argument
+ * - argument conflict
+ * - invalid chanlist
+ * So I tried to adopt this scheme.
+ */
+static int me4000_ai_do_cmd_test(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd)
+{
+
+ unsigned int init_ticks;
+ unsigned int chan_ticks;
+ unsigned int scan_ticks;
+ int err = 0;
+
+ CALL_PDEBUG("In me4000_ai_do_cmd_test()\n");
+
+ PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd->subdev);
+ PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd->flags);
+ PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n",
+ cmd->start_src);
+ PDEBUG("me4000_ai_do_cmd_test(): start_arg = %d\n",
+ cmd->start_arg);
+ PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n",
+ cmd->scan_begin_src);
+ PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n",
+ cmd->scan_begin_arg);
+ PDEBUG("me4000_ai_do_cmd_test(): convert_src = %08X\n",
+ cmd->convert_src);
+ PDEBUG("me4000_ai_do_cmd_test(): convert_arg = %d\n",
+ cmd->convert_arg);
+ PDEBUG("me4000_ai_do_cmd_test(): scan_end_src = %08X\n",
+ cmd->scan_end_src);
+ PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg = %d\n",
+ cmd->scan_end_arg);
+ PDEBUG("me4000_ai_do_cmd_test(): stop_src = %08X\n",
+ cmd->stop_src);
+ PDEBUG("me4000_ai_do_cmd_test(): stop_arg = %d\n", cmd->stop_arg);
+ PDEBUG("me4000_ai_do_cmd_test(): chanlist = %d\n",
+ (unsigned int)cmd->chanlist);
+ PDEBUG("me4000_ai_do_cmd_test(): chanlist_len = %d\n",
+ cmd->chanlist_len);
+
+ /* Only rounding flags are implemented */
+ cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
+
+ /* Round the timer arguments */
+ ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
+
+ /*
+ * Stage 1. Check if the trigger sources are generally valid.
+ */
+ switch (cmd->start_src) {
+ case TRIG_NOW:
+ case TRIG_EXT:
+ break;
+ case TRIG_ANY:
+ cmd->start_src &= TRIG_NOW | TRIG_EXT;
+ err++;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start source\n",
+ dev->minor);
+ cmd->start_src = TRIG_NOW;
+ err++;
+ }
+ switch (cmd->scan_begin_src) {
+ case TRIG_FOLLOW:
+ case TRIG_TIMER:
+ case TRIG_EXT:
+ break;
+ case TRIG_ANY:
+ cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
+ err++;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan begin source\n",
+ dev->minor);
+ cmd->scan_begin_src = TRIG_FOLLOW;
+ err++;
+ }
+ switch (cmd->convert_src) {
+ case TRIG_TIMER:
+ case TRIG_EXT:
+ break;
+ case TRIG_ANY:
+ cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
+ err++;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert source\n",
+ dev->minor);
+ cmd->convert_src = TRIG_TIMER;
+ err++;
+ }
+ switch (cmd->scan_end_src) {
+ case TRIG_NONE:
+ case TRIG_COUNT:
+ break;
+ case TRIG_ANY:
+ cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
+ err++;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end source\n",
+ dev->minor);
+ cmd->scan_end_src = TRIG_NONE;
+ err++;
+ }
+ switch (cmd->stop_src) {
+ case TRIG_NONE:
+ case TRIG_COUNT:
+ break;
+ case TRIG_ANY:
+ cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
+ err++;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop source\n",
+ dev->minor);
+ cmd->stop_src = TRIG_NONE;
+ err++;
+ }
+ if (err) {
+ return 1;
+ }
+
+ /*
+ * Stage 2. Check for trigger source conflicts.
+ */
+ if (cmd->start_src == TRIG_NOW &&
+ cmd->scan_begin_src == TRIG_TIMER &&
+ cmd->convert_src == TRIG_TIMER) {
+ } else if (cmd->start_src == TRIG_NOW &&
+ cmd->scan_begin_src == TRIG_FOLLOW &&
+ cmd->convert_src == TRIG_TIMER) {
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_TIMER &&
+ cmd->convert_src == TRIG_TIMER) {
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_FOLLOW &&
+ cmd->convert_src == TRIG_TIMER) {
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_EXT &&
+ cmd->convert_src == TRIG_TIMER) {
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_EXT &&
+ cmd->convert_src == TRIG_EXT) {
+ } else {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start trigger combination\n",
+ dev->minor);
+ cmd->start_src = TRIG_NOW;
+ cmd->scan_begin_src = TRIG_FOLLOW;
+ cmd->convert_src = TRIG_TIMER;
+ err++;
+ }
+
+ if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
+ } else if (cmd->stop_src == TRIG_COUNT &&
+ cmd->scan_end_src == TRIG_NONE) {
+ } else if (cmd->stop_src == TRIG_NONE &&
+ cmd->scan_end_src == TRIG_COUNT) {
+ } else if (cmd->stop_src == TRIG_COUNT &&
+ cmd->scan_end_src == TRIG_COUNT) {
+ } else {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop trigger combination\n",
+ dev->minor);
+ cmd->stop_src = TRIG_NONE;
+ cmd->scan_end_src = TRIG_NONE;
+ err++;
+ }
+ if (err) {
+ return 2;
+ }
+
+ /*
+ * Stage 3. Check if arguments are generally valid.
+ */
+ if (cmd->chanlist_len < 1) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): No channel list\n",
+ dev->minor);
+ cmd->chanlist_len = 1;
+ err++;
+ }
+ if (init_ticks < 66) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Start arg to low\n",
+ dev->minor);
+ cmd->start_arg = 2000;
+ err++;
+ }
+ if (scan_ticks && scan_ticks < 67) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Scan begin arg to low\n",
+ dev->minor);
+ cmd->scan_begin_arg = 2031;
+ err++;
+ }
+ if (chan_ticks < 66) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Convert arg to low\n",
+ dev->minor);
+ cmd->convert_arg = 2000;
+ err++;
+ }
+ if (err) {
+ return 3;
+ }
+
+ /*
+ * Stage 4. Check for argument conflicts.
+ */
+ if (cmd->start_src == TRIG_NOW &&
+ cmd->scan_begin_src == TRIG_TIMER &&
+ cmd->convert_src == TRIG_TIMER) {
+
+ /* Check timer arguments */
+ if (init_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ dev->minor);
+ cmd->start_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ dev->minor);
+ cmd->convert_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
+ dev->minor);
+ cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; // At least one tick more
+ err++;
+ }
+ } else if (cmd->start_src == TRIG_NOW &&
+ cmd->scan_begin_src == TRIG_FOLLOW &&
+ cmd->convert_src == TRIG_TIMER) {
+
+ /* Check timer arguments */
+ if (init_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ dev->minor);
+ cmd->start_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ dev->minor);
+ cmd->convert_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_TIMER &&
+ cmd->convert_src == TRIG_TIMER) {
+
+ /* Check timer arguments */
+ if (init_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ dev->minor);
+ cmd->start_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ dev->minor);
+ cmd->convert_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
+ dev->minor);
+ cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; // At least one tick more
+ err++;
+ }
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_FOLLOW &&
+ cmd->convert_src == TRIG_TIMER) {
+
+ /* Check timer arguments */
+ if (init_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ dev->minor);
+ cmd->start_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ dev->minor);
+ cmd->convert_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_EXT &&
+ cmd->convert_src == TRIG_TIMER) {
+
+ /* Check timer arguments */
+ if (init_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ dev->minor);
+ cmd->start_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
+ dev->minor);
+ cmd->convert_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ } else if (cmd->start_src == TRIG_EXT &&
+ cmd->scan_begin_src == TRIG_EXT &&
+ cmd->convert_src == TRIG_EXT) {
+
+ /* Check timer arguments */
+ if (init_ticks < ME4000_AI_MIN_TICKS) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
+ dev->minor);
+ cmd->start_arg = 2000; // 66 ticks at least
+ err++;
+ }
+ }
+ if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_arg == 0) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop arg\n",
+ dev->minor);
+ cmd->stop_arg = 1;
+ err++;
+ }
+ }
+ if (cmd->scan_end_src == TRIG_COUNT) {
+ if (cmd->scan_end_arg == 0) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
+ dev->minor);
+ cmd->scan_end_arg = 1;
+ err++;
+ }
+ }
+ if (err) {
+ return 4;
+ }
+
+ /*
+ * Stage 5. Check the channel list.
+ */
+ if (ai_check_chanlist(dev, s, cmd))
+ return 5;
+
+ return 0;
+}
+
+static irqreturn_t me4000_ai_isr(int irq, void *dev_id PT_REGS_ARG)
+{
+ unsigned int tmp;
+ comedi_device *dev = dev_id;
+ comedi_subdevice *s = dev->subdevices;
+ me4000_ai_context_t *ai_context = &info->ai_context;
+ int i;
+ int c = 0;
+ long lval;
+
+ ISR_PDEBUG("me4000_ai_isr() is executed\n");
+
+ if (!dev->attached) {
+ ISR_PDEBUG("me4000_ai_isr() premature interrupt\n");
+ return IRQ_NONE;
+ }
+
+ /* Reset all events */
+ s->async->events = 0;
+
+ /* Check if irq number is right */
+ if (irq != ai_context->irq) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_isr(): Incorrect interrupt num: %d\n",
+ dev->minor, irq);
+ return IRQ_HANDLED;
+ }
+
+ if (me4000_inl(dev,
+ ai_context->
+ irq_status_reg) & ME4000_IRQ_STATUS_BIT_AI_HF) {
+ ISR_PDEBUG
+ ("me4000_ai_isr(): Fifo half full interrupt occured\n");
+
+ /* Read status register to find out what happened */
+ tmp = me4000_inl(dev, ai_context->ctrl_reg);
+
+ if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
+ !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
+ (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG("me4000_ai_isr(): Fifo full\n");
+ c = ME4000_AI_FIFO_COUNT;
+
+ /* FIFO overflow, so stop conversion and disable all interrupts */
+ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
+ ME4000_AI_CTRL_BIT_SC_IRQ);
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+
+ s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_isr(): FIFO overflow\n",
+ dev->minor);
+ } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
+ && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
+ && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n");
+
+ s->async->events |= COMEDI_CB_BLOCK;
+
+ c = ME4000_AI_FIFO_COUNT / 2;
+ } else {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_isr(): Can't determine state of fifo\n",
+ dev->minor);
+ c = 0;
+
+ /* Undefined state, so stop conversion and disable all interrupts */
+ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
+ ME4000_AI_CTRL_BIT_SC_IRQ);
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+
+ s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
+
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_isr(): Undefined FIFO state\n",
+ dev->minor);
+ }
+
+ ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c);
+
+ for (i = 0; i < c; i++) {
+ /* Read value from data fifo */
+ lval = inl(ai_context->data_reg) & 0xFFFF;
+ lval ^= 0x8000;
+
+ if (!comedi_buf_put(s->async, lval)) {
+ /* Buffer overflow, so stop conversion and disable all interrupts */
+ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
+ ME4000_AI_CTRL_BIT_SC_IRQ);
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+
+ s->async->events |= COMEDI_CB_OVERFLOW;
+
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
+ dev->minor);
+
+ break;
+ }
+ }
+
+ /* Work is done, so reset the interrupt */
+ ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n");
+ tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+ }
+
+ if (me4000_inl(dev,
+ ai_context->
+ irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
+ ISR_PDEBUG
+ ("me4000_ai_isr(): Sample counter interrupt occured\n");
+
+ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
+
+ /* Acquisition is complete, so stop conversion and disable all interrupts */
+ tmp = me4000_inl(dev, ai_context->ctrl_reg);
+ tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
+ tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+
+ /* Poll data until fifo empty */
+ while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
+ /* Read value from data fifo */
+ lval = inl(ai_context->data_reg) & 0xFFFF;
+ lval ^= 0x8000;
+
+ if (!comedi_buf_put(s->async, lval)) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
+ dev->minor);
+ s->async->events |= COMEDI_CB_OVERFLOW;
+ break;
+ }
+ }
+
+ /* Work is done, so reset the interrupt */
+ ISR_PDEBUG
+ ("me4000_ai_isr(): Reset interrupt from sample counter\n");
+ tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+ tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+ me4000_outl(dev, tmp, ai_context->ctrl_reg);
+ }
+
+ ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s->async->events);
+
+ if (s->async->events)
+ comedi_event(dev, s);
+
+ return IRQ_HANDLED;
+}
+
+/*=============================================================================
+ Analog output section
+ ===========================================================================*/
+
+static int me4000_ao_insn_write(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+ int chan = CR_CHAN(insn->chanspec);
+ int rang = CR_RANGE(insn->chanspec);
+ int aref = CR_AREF(insn->chanspec);
+ unsigned long tmp;
+
+ CALL_PDEBUG("In me4000_ao_insn_write()\n");
+
+ if (insn->n == 0) {
+ return 0;
+ } else if (insn->n > 1) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ao_insn_write(): Invalid instruction length %d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ if (chan >= thisboard->ao.count) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ao_insn_write(): Invalid channel %d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ if (rang != 0) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ao_insn_write(): Invalid range %d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ if (aref != AREF_GROUND && aref != AREF_COMMON) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_ao_insn_write(): Invalid aref %d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ /* Stop any running conversion */
+ tmp = me4000_inl(dev, info->ao_context[chan].ctrl_reg);
+ tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ me4000_outl(dev, tmp, info->ao_context[chan].ctrl_reg);
+
+ /* Clear control register and set to single mode */
+ me4000_outl(dev, 0x0, info->ao_context[chan].ctrl_reg);
+
+ /* Write data value */
+ me4000_outl(dev, data[0], info->ao_context[chan].single_reg);
+
+ /* Store in the mirror */
+ info->ao_context[chan].mirror = data[0];
+
+ return 1;
+}
+
+static int me4000_ao_insn_read(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ int chan = CR_CHAN(insn->chanspec);
+
+ if (insn->n == 0) {
+ return 0;
+ } else if (insn->n > 1) {
+ printk("comedi%d: me4000: me4000_ao_insn_read(): Invalid instruction length\n", dev->minor);
+ return -EINVAL;
+ }
+
+ data[0] = info->ao_context[chan].mirror;
+
+ return 1;
+}
+
+/*=============================================================================
+ Digital I/O section
+ ===========================================================================*/
+
+static int me4000_dio_insn_bits(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+ CALL_PDEBUG("In me4000_dio_insn_bits()\n");
+
+ /* Length of data must be 2 (mask and new data, see below) */
+ if (insn->n == 0) {
+ return 0;
+ }
+ if (insn->n != 2) {
+ printk("comedi%d: me4000: me4000_dio_insn_bits(): Invalid instruction length\n", dev->minor);
+ return -EINVAL;
+ }
+
+ /*
+ * The insn data consists of a mask in data[0] and the new data
+ * in data[1]. The mask defines which bits we are concerning about.
+ * The new data must be anded with the mask.
+ * Each channel corresponds to a bit.
+ */
+ if (data[0]) {
+ /* Check if requested ports are configured for output */
+ if ((s->io_bits & data[0]) != data[0])
+ return -EIO;
+
+ s->state &= ~data[0];
+ s->state |= data[0] & data[1];
+
+ /* Write out the new digital output lines */
+ me4000_outl(dev, (s->state >> 0) & 0xFF,
+ info->dio_context.port_0_reg);
+ me4000_outl(dev, (s->state >> 8) & 0xFF,
+ info->dio_context.port_1_reg);
+ me4000_outl(dev, (s->state >> 16) & 0xFF,
+ info->dio_context.port_2_reg);
+ me4000_outl(dev, (s->state >> 24) & 0xFF,
+ info->dio_context.port_3_reg);
+ }
+
+ /* On return, data[1] contains the value of
+ the digital input and output lines. */
+ data[1] =
+ ((me4000_inl(dev, info->dio_context.port_0_reg) & 0xFF) << 0) |
+ ((me4000_inl(dev, info->dio_context.port_1_reg) & 0xFF) << 8) |
+ ((me4000_inl(dev, info->dio_context.port_2_reg) & 0xFF) << 16) |
+ ((me4000_inl(dev, info->dio_context.port_3_reg) & 0xFF) << 24);
+
+ return 2;
+}
+
+static int me4000_dio_insn_config(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ unsigned long tmp;
+ int chan = CR_CHAN(insn->chanspec);
+
+ CALL_PDEBUG("In me4000_dio_insn_config()\n");
+
+ if (data[0] == INSN_CONFIG_DIO_QUERY) {
+ data[1] =
+ (s->
+ io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ return insn->n;
+ }
+
+ /*
+ * The input or output configuration of each digital line is
+ * configured by a special insn_config instruction. chanspec
+ * contains the channel to be changed, and data[0] contains the
+ * value COMEDI_INPUT or COMEDI_OUTPUT.
+ * On the ME-4000 it is only possible to switch port wise (8 bit)
+ */
+
+ tmp = me4000_inl(dev, info->dio_context.ctrl_reg);
+
+ if (data[0] == COMEDI_OUTPUT) {
+ if (chan < 8) {
+ s->io_bits |= 0xFF;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
+ ME4000_DIO_CTRL_BIT_MODE_1);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
+ } else if (chan < 16) {
+ /*
+ * Chech for optoisolated ME-4000 version. If one the first
+ * port is a fixed output port and the second is a fixed input port.
+ */
+ if (!me4000_inl(dev, info->dio_context.dir_reg))
+ return -ENODEV;
+
+ s->io_bits |= 0xFF00;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
+ ME4000_DIO_CTRL_BIT_MODE_3);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
+ } else if (chan < 24) {
+ s->io_bits |= 0xFF0000;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
+ ME4000_DIO_CTRL_BIT_MODE_5);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
+ } else if (chan < 32) {
+ s->io_bits |= 0xFF000000;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
+ ME4000_DIO_CTRL_BIT_MODE_7);
+ tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
+ } else {
+ return -EINVAL;
+ }
+ } else {
+ if (chan < 8) {
+ /*
+ * Chech for optoisolated ME-4000 version. If one the first
+ * port is a fixed output port and the second is a fixed input port.
+ */
+ if (!me4000_inl(dev, info->dio_context.dir_reg))
+ return -ENODEV;
+
+ s->io_bits &= ~0xFF;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
+ ME4000_DIO_CTRL_BIT_MODE_1);
+ } else if (chan < 16) {
+ s->io_bits &= ~0xFF00;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
+ ME4000_DIO_CTRL_BIT_MODE_3);
+ } else if (chan < 24) {
+ s->io_bits &= ~0xFF0000;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
+ ME4000_DIO_CTRL_BIT_MODE_5);
+ } else if (chan < 32) {
+ s->io_bits &= ~0xFF000000;
+ tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
+ ME4000_DIO_CTRL_BIT_MODE_7);
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ me4000_outl(dev, tmp, info->dio_context.ctrl_reg);
+
+ return 1;
+}
+
+/*=============================================================================
+ Counter section
+ ===========================================================================*/
+
+static int cnt_reset(comedi_device * dev, unsigned int channel)
+{
+
+ CALL_PDEBUG("In cnt_reset()\n");
+
+ switch (channel) {
+ case 0:
+ me4000_outb(dev, 0x30, info->cnt_context.ctrl_reg);
+ me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
+ me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
+ break;
+ case 1:
+ me4000_outb(dev, 0x70, info->cnt_context.ctrl_reg);
+ me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
+ me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
+ break;
+ case 2:
+ me4000_outb(dev, 0xB0, info->cnt_context.ctrl_reg);
+ me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
+ me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: cnt_reset(): Invalid channel\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int cnt_config(comedi_device * dev, unsigned int channel,
+ unsigned int mode)
+{
+ int tmp = 0;
+
+ CALL_PDEBUG("In cnt_config()\n");
+
+ switch (channel) {
+ case 0:
+ tmp |= ME4000_CNT_COUNTER_0;
+ break;
+ case 1:
+ tmp |= ME4000_CNT_COUNTER_1;
+ break;
+ case 2:
+ tmp |= ME4000_CNT_COUNTER_2;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: cnt_config(): Invalid channel\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ switch (mode) {
+ case 0:
+ tmp |= ME4000_CNT_MODE_0;
+ break;
+ case 1:
+ tmp |= ME4000_CNT_MODE_1;
+ break;
+ case 2:
+ tmp |= ME4000_CNT_MODE_2;
+ break;
+ case 3:
+ tmp |= ME4000_CNT_MODE_3;
+ break;
+ case 4:
+ tmp |= ME4000_CNT_MODE_4;
+ break;
+ case 5:
+ tmp |= ME4000_CNT_MODE_5;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ /* Write the control word */
+ tmp |= 0x30;
+ me4000_outb(dev, tmp, info->cnt_context.ctrl_reg);
+
+ return 0;
+}
+
+static int me4000_cnt_insn_config(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+ int err;
+
+ CALL_PDEBUG("In me4000_cnt_insn_config()\n");
+
+ switch (data[0]) {
+ case GPCT_RESET:
+ if (insn->n != 1) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ err = cnt_reset(dev, insn->chanspec);
+ if (err)
+ return err;
+ break;
+ case GPCT_SET_OPERATION:
+ if (insn->n != 2) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ err = cnt_config(dev, insn->chanspec, data[1]);
+ if (err)
+ return err;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction\n",
+ dev->minor);
+ return -EINVAL;
+ }
+
+ return 2;
+}
+
+static int me4000_cnt_insn_read(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+ unsigned short tmp;
+
+ CALL_PDEBUG("In me4000_cnt_insn_read()\n");
+
+ if (insn->n == 0) {
+ return 0;
+ }
+ if (insn->n > 1) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_cnt_insn_read(): Invalid instruction length %d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ switch (insn->chanspec) {
+ case 0:
+ tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
+ data[0] = tmp;
+ tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
+ data[0] |= tmp << 8;
+ break;
+ case 1:
+ tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
+ data[0] = tmp;
+ tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
+ data[0] |= tmp << 8;
+ break;
+ case 2:
+ tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
+ data[0] = tmp;
+ tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
+ data[0] |= tmp << 8;
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_cnt_insn_read(): Invalid channel %d\n",
+ dev->minor, insn->chanspec);
+ return -EINVAL;
+ }
+
+ return 1;
+}
+
+static int me4000_cnt_insn_write(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+
+ unsigned short tmp;
+
+ CALL_PDEBUG("In me4000_cnt_insn_write()\n");
+
+ if (insn->n == 0) {
+ return 0;
+ } else if (insn->n > 1) {
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_cnt_insn_write(): Invalid instruction length %d\n",
+ dev->minor, insn->n);
+ return -EINVAL;
+ }
+
+ switch (insn->chanspec) {
+ case 0:
+ tmp = data[0] & 0xFF;
+ me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
+ tmp = (data[0] >> 8) & 0xFF;
+ me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
+ break;
+ case 1:
+ tmp = data[0] & 0xFF;
+ me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
+ tmp = (data[0] >> 8) & 0xFF;
+ me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
+ break;
+ case 2:
+ tmp = data[0] & 0xFF;
+ me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
+ tmp = (data[0] >> 8) & 0xFF;
+ me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
+ break;
+ default:
+ printk(KERN_ERR
+ "comedi%d: me4000: me4000_cnt_insn_write(): Invalid channel %d\n",
+ dev->minor, insn->chanspec);
+ return -EINVAL;
+ }
+
+ return 1;
+}
+
+COMEDI_PCI_INITCLEANUP(driver_me4000, me4000_pci_table);
diff --git a/drivers/staging/comedi/drivers/me4000.h b/drivers/staging/comedi/drivers/me4000.h
new file mode 100644
index 000000000000..f12b8873ec3c
--- /dev/null
+++ b/drivers/staging/comedi/drivers/me4000.h
@@ -0,0 +1,446 @@
+/*
+ me4000.h
+ Register descriptions and defines for the ME-4000 board family
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1998-9 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _ME4000_H_
+#define _ME4000_H_
+
+/*=============================================================================
+ Debug section
+ ===========================================================================*/
+
+#undef ME4000_CALL_DEBUG // Debug function entry and exit
+#undef ME4000_PORT_DEBUG // Debug port access
+#undef ME4000_ISR_DEBUG // Debug the interrupt service routine
+#undef ME4000_DEBUG // General purpose debug masseges
+
+#ifdef ME4000_CALL_DEBUG
+#undef CALL_PDEBUG
+#define CALL_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args)
+#else
+# define CALL_PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+#ifdef ME4000_PORT_DEBUG
+#undef PORT_PDEBUG
+#define PORT_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args)
+#else
+#define PORT_PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+#ifdef ME4000_ISR_DEBUG
+#undef ISR_PDEBUG
+#define ISR_PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args)
+#else
+#define ISR_PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+#ifdef ME4000_DEBUG
+#undef PDEBUG
+#define PDEBUG(fmt, args...) printk(KERN_DEBUG"comedi%d: me4000: " fmt, dev->minor, ##args)
+#else
+#define PDEBUG(fmt, args...) // no debugging, do nothing
+#endif
+
+/*=============================================================================
+ PCI vendor and device IDs
+ ===========================================================================*/
+
+#define PCI_VENDOR_ID_MEILHAUS 0x1402
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 // Low Cost version
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 // Isolated version with Sample and Hold
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 // Isolated version with Sample and Hold
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 // Isolated version with Sample and Hold
+
+/*=============================================================================
+ ME-4000 base register offsets
+ ===========================================================================*/
+
+#define ME4000_AO_00_CTRL_REG 0x00 // R/W
+#define ME4000_AO_00_STATUS_REG 0x04 // R/_
+#define ME4000_AO_00_FIFO_REG 0x08 // _/W
+#define ME4000_AO_00_SINGLE_REG 0x0C // R/W
+#define ME4000_AO_00_TIMER_REG 0x10 // _/W
+
+#define ME4000_AO_01_CTRL_REG 0x18 // R/W
+#define ME4000_AO_01_STATUS_REG 0x1C // R/_
+#define ME4000_AO_01_FIFO_REG 0x20 // _/W
+#define ME4000_AO_01_SINGLE_REG 0x24 // R/W
+#define ME4000_AO_01_TIMER_REG 0x28 // _/W
+
+#define ME4000_AO_02_CTRL_REG 0x30 // R/W
+#define ME4000_AO_02_STATUS_REG 0x34 // R/_
+#define ME4000_AO_02_FIFO_REG 0x38 // _/W
+#define ME4000_AO_02_SINGLE_REG 0x3C // R/W
+#define ME4000_AO_02_TIMER_REG 0x40 // _/W
+
+#define ME4000_AO_03_CTRL_REG 0x48 // R/W
+#define ME4000_AO_03_STATUS_REG 0x4C // R/_
+#define ME4000_AO_03_FIFO_REG 0x50 // _/W
+#define ME4000_AO_03_SINGLE_REG 0x54 // R/W
+#define ME4000_AO_03_TIMER_REG 0x58 // _/W
+
+#define ME4000_AI_CTRL_REG 0x74 // _/W
+#define ME4000_AI_STATUS_REG 0x74 // R/_
+#define ME4000_AI_CHANNEL_LIST_REG 0x78 // _/W
+#define ME4000_AI_DATA_REG 0x7C // R/_
+#define ME4000_AI_CHAN_TIMER_REG 0x80 // _/W
+#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84 // _/W
+#define ME4000_AI_SCAN_TIMER_LOW_REG 0x88 // _/W
+#define ME4000_AI_SCAN_TIMER_HIGH_REG 0x8C // _/W
+#define ME4000_AI_SCAN_PRE_TIMER_LOW_REG 0x90 // _/W
+#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 // _/W
+#define ME4000_AI_START_REG 0x98 // R/_
+
+#define ME4000_IRQ_STATUS_REG 0x9C // R/_
+
+#define ME4000_DIO_PORT_0_REG 0xA0 // R/W
+#define ME4000_DIO_PORT_1_REG 0xA4 // R/W
+#define ME4000_DIO_PORT_2_REG 0xA8 // R/W
+#define ME4000_DIO_PORT_3_REG 0xAC // R/W
+#define ME4000_DIO_DIR_REG 0xB0 // R/W
+
+#define ME4000_AO_LOADSETREG_XX 0xB4 // R/W
+
+#define ME4000_DIO_CTRL_REG 0xB8 // R/W
+
+#define ME4000_AO_DEMUX_ADJUST_REG 0xBC // -/W
+
+#define ME4000_AI_SAMPLE_COUNTER_REG 0xC0 // _/W
+
+/*=============================================================================
+ Value to adjust Demux
+ ===========================================================================*/
+
+#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4C
+
+/*=============================================================================
+ Counter base register offsets
+ ===========================================================================*/
+
+#define ME4000_CNT_COUNTER_0_REG 0x00
+#define ME4000_CNT_COUNTER_1_REG 0x01
+#define ME4000_CNT_COUNTER_2_REG 0x02
+#define ME4000_CNT_CTRL_REG 0x03
+
+/*=============================================================================
+ PLX base register offsets
+ ===========================================================================*/
+
+#define PLX_INTCSR 0x4C // Interrupt control and status register
+#define PLX_ICR 0x50 // Initialization control register
+
+/*=============================================================================
+ Bits for the PLX_ICSR register
+ ===========================================================================*/
+
+#define PLX_INTCSR_LOCAL_INT1_EN 0x01 // If set, local interrupt 1 is enabled (r/w)
+#define PLX_INTCSR_LOCAL_INT1_POL 0x02 // If set, local interrupt 1 polarity is active high (r/w)
+#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 // If set, local interrupt 1 is active (r/_)
+#define PLX_INTCSR_LOCAL_INT2_EN 0x08 // If set, local interrupt 2 is enabled (r/w)
+#define PLX_INTCSR_LOCAL_INT2_POL 0x10 // If set, local interrupt 2 polarity is active high (r/w)
+#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 // If set, local interrupt 2 is active (r/_)
+#define PLX_INTCSR_PCI_INT_EN 0x40 // If set, PCI interrupt is enabled (r/w)
+#define PLX_INTCSR_SOFT_INT 0x80 // If set, a software interrupt is generated (r/w)
+
+/*=============================================================================
+ Bits for the PLX_ICR register
+ ===========================================================================*/
+
+#define PLX_ICR_BIT_EEPROM_CLOCK_SET 0x01000000
+#define PLX_ICR_BIT_EEPROM_CHIP_SELECT 0x02000000
+#define PLX_ICR_BIT_EEPROM_WRITE 0x04000000
+#define PLX_ICR_BIT_EEPROM_READ 0x08000000
+#define PLX_ICR_BIT_EEPROM_VALID 0x10000000
+
+#define PLX_ICR_MASK_EEPROM 0x1F000000
+
+#define EEPROM_DELAY 1
+
+/*=============================================================================
+ Bits for the ME4000_AO_CTRL_REG register
+ ===========================================================================*/
+
+#define ME4000_AO_CTRL_BIT_MODE_0 0x001
+#define ME4000_AO_CTRL_BIT_MODE_1 0x002
+#define ME4000_AO_CTRL_MASK_MODE 0x003
+#define ME4000_AO_CTRL_BIT_STOP 0x004
+#define ME4000_AO_CTRL_BIT_ENABLE_FIFO 0x008
+#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG 0x010
+#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE 0x020
+#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP 0x080
+#define ME4000_AO_CTRL_BIT_ENABLE_DO 0x100
+#define ME4000_AO_CTRL_BIT_ENABLE_IRQ 0x200
+#define ME4000_AO_CTRL_BIT_RESET_IRQ 0x400
+
+/*=============================================================================
+ Bits for the ME4000_AO_STATUS_REG register
+ ===========================================================================*/
+
+#define ME4000_AO_STATUS_BIT_FSM 0x01
+#define ME4000_AO_STATUS_BIT_FF 0x02
+#define ME4000_AO_STATUS_BIT_HF 0x04
+#define ME4000_AO_STATUS_BIT_EF 0x08
+
+/*=============================================================================
+ Bits for the ME4000_AI_CTRL_REG register
+ ===========================================================================*/
+
+#define ME4000_AI_CTRL_BIT_MODE_0 0x00000001
+#define ME4000_AI_CTRL_BIT_MODE_1 0x00000002
+#define ME4000_AI_CTRL_BIT_MODE_2 0x00000004
+#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD 0x00000008
+#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP 0x00000010
+#define ME4000_AI_CTRL_BIT_STOP 0x00000020
+#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO 0x00000040
+#define ME4000_AI_CTRL_BIT_DATA_FIFO 0x00000080
+#define ME4000_AI_CTRL_BIT_FULLSCALE 0x00000100
+#define ME4000_AI_CTRL_BIT_OFFSET 0x00000200
+#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG 0x00000400
+#define ME4000_AI_CTRL_BIT_EX_TRIG 0x00000800
+#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING 0x00001000
+#define ME4000_AI_CTRL_BIT_EX_IRQ 0x00002000
+#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET 0x00004000
+#define ME4000_AI_CTRL_BIT_LE_IRQ 0x00008000
+#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET 0x00010000
+#define ME4000_AI_CTRL_BIT_HF_IRQ 0x00020000
+#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET 0x00040000
+#define ME4000_AI_CTRL_BIT_SC_IRQ 0x00080000
+#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET 0x00100000
+#define ME4000_AI_CTRL_BIT_SC_RELOAD 0x00200000
+#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH 0x80000000
+
+/*=============================================================================
+ Bits for the ME4000_AI_STATUS_REG register
+ ===========================================================================*/
+
+#define ME4000_AI_STATUS_BIT_EF_CHANNEL 0x00400000
+#define ME4000_AI_STATUS_BIT_HF_CHANNEL 0x00800000
+#define ME4000_AI_STATUS_BIT_FF_CHANNEL 0x01000000
+#define ME4000_AI_STATUS_BIT_EF_DATA 0x02000000
+#define ME4000_AI_STATUS_BIT_HF_DATA 0x04000000
+#define ME4000_AI_STATUS_BIT_FF_DATA 0x08000000
+#define ME4000_AI_STATUS_BIT_LE 0x10000000
+#define ME4000_AI_STATUS_BIT_FSM 0x20000000
+
+/*=============================================================================
+ Bits for the ME4000_IRQ_STATUS_REG register
+ ===========================================================================*/
+
+#define ME4000_IRQ_STATUS_BIT_EX 0x01
+#define ME4000_IRQ_STATUS_BIT_LE 0x02
+#define ME4000_IRQ_STATUS_BIT_AI_HF 0x04
+#define ME4000_IRQ_STATUS_BIT_AO_0_HF 0x08
+#define ME4000_IRQ_STATUS_BIT_AO_1_HF 0x10
+#define ME4000_IRQ_STATUS_BIT_AO_2_HF 0x20
+#define ME4000_IRQ_STATUS_BIT_AO_3_HF 0x40
+#define ME4000_IRQ_STATUS_BIT_SC 0x80
+
+/*=============================================================================
+ Bits for the ME4000_DIO_CTRL_REG register
+ ===========================================================================*/
+
+#define ME4000_DIO_CTRL_BIT_MODE_0 0x0001
+#define ME4000_DIO_CTRL_BIT_MODE_1 0x0002
+#define ME4000_DIO_CTRL_BIT_MODE_2 0x0004
+#define ME4000_DIO_CTRL_BIT_MODE_3 0x0008
+#define ME4000_DIO_CTRL_BIT_MODE_4 0x0010
+#define ME4000_DIO_CTRL_BIT_MODE_5 0x0020
+#define ME4000_DIO_CTRL_BIT_MODE_6 0x0040
+#define ME4000_DIO_CTRL_BIT_MODE_7 0x0080
+
+#define ME4000_DIO_CTRL_BIT_FUNCTION_0 0x0100
+#define ME4000_DIO_CTRL_BIT_FUNCTION_1 0x0200
+
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 0x0400
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 0x0800
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 0x1000
+#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 0x2000
+
+/*=============================================================================
+ Information about the hardware capabilities
+ ===========================================================================*/
+
+typedef struct me4000_ao_info {
+ int count;
+ int fifo_count;
+} me4000_ao_info_t;
+
+typedef struct me4000_ai_info {
+ int count;
+ int sh_count;
+ int diff_count;
+ int ex_trig_analog;
+} me4000_ai_info_t;
+
+typedef struct me4000_dio_info {
+ int count;
+} me4000_dio_info_t;
+
+typedef struct me4000_cnt_info {
+ int count;
+} me4000_cnt_info_t;
+
+typedef struct me4000_board {
+ const char *name;
+ unsigned short device_id;
+ me4000_ao_info_t ao;
+ me4000_ai_info_t ai;
+ me4000_dio_info_t dio;
+ me4000_cnt_info_t cnt;
+} me4000_board_t;
+
+#define thisboard ((const me4000_board_t *)dev->board_ptr)
+
+/*=============================================================================
+ Global board and subdevice information structures
+ ===========================================================================*/
+
+typedef struct me4000_ao_context {
+ int irq;
+
+ unsigned long mirror; // Store the last written value
+
+ unsigned long ctrl_reg;
+ unsigned long status_reg;
+ unsigned long fifo_reg;
+ unsigned long single_reg;
+ unsigned long timer_reg;
+ unsigned long irq_status_reg;
+ unsigned long preload_reg;
+} me4000_ao_context_t;
+
+typedef struct me4000_ai_context {
+ int irq;
+
+ unsigned long ctrl_reg;
+ unsigned long status_reg;
+ unsigned long channel_list_reg;
+ unsigned long data_reg;
+ unsigned long chan_timer_reg;
+ unsigned long chan_pre_timer_reg;
+ unsigned long scan_timer_low_reg;
+ unsigned long scan_timer_high_reg;
+ unsigned long scan_pre_timer_low_reg;
+ unsigned long scan_pre_timer_high_reg;
+ unsigned long start_reg;
+ unsigned long irq_status_reg;
+ unsigned long sample_counter_reg;
+} me4000_ai_context_t;
+
+typedef struct me4000_dio_context {
+ unsigned long dir_reg;
+ unsigned long ctrl_reg;
+ unsigned long port_0_reg;
+ unsigned long port_1_reg;
+ unsigned long port_2_reg;
+ unsigned long port_3_reg;
+} me4000_dio_context_t;
+
+typedef struct me4000_cnt_context {
+ unsigned long ctrl_reg;
+ unsigned long counter_0_reg;
+ unsigned long counter_1_reg;
+ unsigned long counter_2_reg;
+} me4000_cnt_context_t;
+
+typedef struct me4000_info {
+ unsigned long plx_regbase; // PLX configuration space base address
+ unsigned long me4000_regbase; // Base address of the ME4000
+ unsigned long timer_regbase; // Base address of the timer circuit
+ unsigned long program_regbase; // Base address to set the program pin for the xilinx
+
+ unsigned long plx_regbase_size; // PLX register set space
+ unsigned long me4000_regbase_size; // ME4000 register set space
+ unsigned long timer_regbase_size; // Timer circuit register set space
+ unsigned long program_regbase_size; // Size of program base address of the ME4000
+
+ unsigned int serial_no; // Serial number of the board
+ unsigned char hw_revision; // Hardware revision of the board
+ unsigned short vendor_id; // Meilhaus vendor id
+ unsigned short device_id; // Device id
+
+ struct pci_dev *pci_dev_p; // General PCI information
+
+ unsigned int irq; // IRQ assigned from the PCI BIOS
+
+ struct me4000_ai_context ai_context; // Analog input specific context
+ struct me4000_ao_context ao_context[4]; // Vector with analog output specific context
+ struct me4000_dio_context dio_context; // Digital I/O specific context
+ struct me4000_cnt_context cnt_context; // Counter specific context
+} me4000_info_t;
+
+#define info ((me4000_info_t *)dev->private)
+
+/*-----------------------------------------------------------------------------
+ Defines for analog input
+ ----------------------------------------------------------------------------*/
+
+/* General stuff */
+#define ME4000_AI_FIFO_COUNT 2048
+
+#define ME4000_AI_MIN_TICKS 66
+#define ME4000_AI_MIN_SAMPLE_TIME 2000 // Minimum sample time [ns]
+#define ME4000_AI_BASE_FREQUENCY (unsigned int) 33E6
+
+/* Channel list defines and masks */
+#define ME4000_AI_CHANNEL_LIST_COUNT 1024
+
+#define ME4000_AI_LIST_INPUT_SINGLE_ENDED 0x000
+#define ME4000_AI_LIST_INPUT_DIFFERENTIAL 0x020
+
+#define ME4000_AI_LIST_RANGE_BIPOLAR_10 0x000
+#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 0x040
+#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 0x080
+#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 0x0C0
+
+#define ME4000_AI_LIST_LAST_ENTRY 0x100
+
+/*-----------------------------------------------------------------------------
+ Defines for counters
+ ----------------------------------------------------------------------------*/
+
+#define ME4000_CNT_COUNTER_0 0x00
+#define ME4000_CNT_COUNTER_1 0x40
+#define ME4000_CNT_COUNTER_2 0x80
+
+#define ME4000_CNT_MODE_0 0x00 // Change state if zero crossing
+#define ME4000_CNT_MODE_1 0x02 // Retriggerable One-Shot
+#define ME4000_CNT_MODE_2 0x04 // Asymmetrical divider
+#define ME4000_CNT_MODE_3 0x06 // Symmetrical divider
+#define ME4000_CNT_MODE_4 0x08 // Counter start by software trigger
+#define ME4000_CNT_MODE_5 0x0A // Counter start by hardware trigger
+
+#endif
diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c
new file mode 100644
index 000000000000..6accec20a0f9
--- /dev/null
+++ b/drivers/staging/comedi/drivers/me_daq.c
@@ -0,0 +1,845 @@
+/*
+
+ comedi/drivers/me_daq.c
+
+ Hardware driver for Meilhaus data acquisition cards:
+
+ ME-2000i, ME-2600i, ME-3000vm1
+
+ Copyright (C) 2002 Michael Hillmann <hillmann@syscongroup.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+Driver: me_daq
+Description: Meilhaus PCI data acquisition cards
+Author: Michael Hillmann <hillmann@syscongroup.de>
+Devices: [Meilhaus] ME-2600i (me_daq), ME-2000i
+Status: experimental
+
+Supports:
+
+ Analog Output
+
+Configuration options:
+
+ [0] - PCI bus number (optional)
+ [1] - PCI slot number (optional)
+
+ If bus/slot is not specified, the first available PCI
+ device will be used.
+
+The 2600 requires a firmware upload, which can be accomplished
+using the -i or --init-data option of comedi_config.
+The firmware can be
+found in the comedi_nonfree_firmware tarball available
+from http://www.comedi.org
+
+*/
+
+#include "../comedidev.h"
+
+#include "comedi_pci.h"
+
+/*#include "me2600_fw.h" */
+
+#define ME_DRIVER_NAME "me_daq"
+
+#define ME2000_DEVICE_ID 0x2000
+#define ME2600_DEVICE_ID 0x2600
+
+#define PLX_INTCSR 0x4C /* PLX interrupt status register */
+#define XILINX_DOWNLOAD_RESET 0x42 /* Xilinx registers */
+
+#define ME_CONTROL_1 0x0000 /* - | W */
+#define INTERRUPT_ENABLE (1<<15)
+#define COUNTER_B_IRQ (1<<12)
+#define COUNTER_A_IRQ (1<<11)
+#define CHANLIST_READY_IRQ (1<<10)
+#define EXT_IRQ (1<<9)
+#define ADFIFO_HALFFULL_IRQ (1<<8)
+#define SCAN_COUNT_ENABLE (1<<5)
+#define SIMULTANEOUS_ENABLE (1<<4)
+#define TRIGGER_FALLING_EDGE (1<<3)
+#define CONTINUOUS_MODE (1<<2)
+#define DISABLE_ADC (0<<0)
+#define SOFTWARE_TRIGGERED_ADC (1<<0)
+#define SCAN_TRIGGERED_ADC (2<<0)
+#define EXT_TRIGGERED_ADC (3<<0)
+#define ME_ADC_START 0x0000 /* R | - */
+#define ME_CONTROL_2 0x0002 /* - | W */
+#define ENABLE_ADFIFO (1<<10)
+#define ENABLE_CHANLIST (1<<9)
+#define ENABLE_PORT_B (1<<7)
+#define ENABLE_PORT_A (1<<6)
+#define ENABLE_COUNTER_B (1<<4)
+#define ENABLE_COUNTER_A (1<<3)
+#define ENABLE_DAC (1<<1)
+#define BUFFERED_DAC (1<<0)
+#define ME_DAC_UPDATE 0x0002 /* R | - */
+#define ME_STATUS 0x0004 /* R | - */
+#define COUNTER_B_IRQ_PENDING (1<<12)
+#define COUNTER_A_IRQ_PENDING (1<<11)
+#define CHANLIST_READY_IRQ_PENDING (1<<10)
+#define EXT_IRQ_PENDING (1<<9)
+#define ADFIFO_HALFFULL_IRQ_PENDING (1<<8)
+#define ADFIFO_FULL (1<<4)
+#define ADFIFO_HALFFULL (1<<3)
+#define ADFIFO_EMPTY (1<<2)
+#define CHANLIST_FULL (1<<1)
+#define FST_ACTIVE (1<<0)
+#define ME_RESET_INTERRUPT 0x0004 /* - | W */
+#define ME_DIO_PORT_A 0x0006 /* R | W */
+#define ME_DIO_PORT_B 0x0008 /* R | W */
+#define ME_TIMER_DATA_0 0x000A /* - | W */
+#define ME_TIMER_DATA_1 0x000C /* - | W */
+#define ME_TIMER_DATA_2 0x000E /* - | W */
+#define ME_CHANNEL_LIST 0x0010 /* - | W */
+#define ADC_UNIPOLAR (1<<6)
+#define ADC_GAIN_0 (0<<4)
+#define ADC_GAIN_1 (1<<4)
+#define ADC_GAIN_2 (2<<4)
+#define ADC_GAIN_3 (3<<4)
+#define ME_READ_AD_FIFO 0x0010 /* R | - */
+#define ME_DAC_CONTROL 0x0012 /* - | W */
+#define DAC_UNIPOLAR_D (0<<4)
+#define DAC_BIPOLAR_D (1<<4)
+#define DAC_UNIPOLAR_C (0<<5)
+#define DAC_BIPOLAR_C (1<<5)
+#define DAC_UNIPOLAR_B (0<<6)
+#define DAC_BIPOLAR_B (1<<6)
+#define DAC_UNIPOLAR_A (0<<7)
+#define DAC_BIPOLAR_A (1<<7)
+#define DAC_GAIN_0_D (0<<8)
+#define DAC_GAIN_1_D (1<<8)
+#define DAC_GAIN_0_C (0<<9)
+#define DAC_GAIN_1_C (1<<9)
+#define DAC_GAIN_0_B (0<<10)
+#define DAC_GAIN_1_B (1<<10)
+#define DAC_GAIN_0_A (0<<11)
+#define DAC_GAIN_1_A (1<<11)
+#define ME_DAC_CONTROL_UPDATE 0x0012 /* R | - */
+#define ME_DAC_DATA_A 0x0014 /* - | W */
+#define ME_DAC_DATA_B 0x0016 /* - | W */
+#define ME_DAC_DATA_C 0x0018 /* - | W */
+#define ME_DAC_DATA_D 0x001A /* - | W */
+#define ME_COUNTER_ENDDATA_A 0x001C /* - | W */
+#define ME_COUNTER_ENDDATA_B 0x001E /* - | W */
+#define ME_COUNTER_STARTDATA_A 0x0020 /* - | W */
+#define ME_COUNTER_VALUE_A 0x0020 /* R | - */
+#define ME_COUNTER_STARTDATA_B 0x0022 /* - | W */
+#define ME_COUNTER_VALUE_B 0x0022 /* R | - */
+
+/* Function prototypes */
+static int me_attach(comedi_device *dev, comedi_devconfig *it);
+static int me_detach(comedi_device *dev);
+
+static const comedi_lrange me2000_ai_range = {
+ 8,
+ {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2.5),
+ UNI_RANGE(1.25)
+ }
+};
+
+static const comedi_lrange me2600_ai_range = {
+ 8,
+ {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ BIP_RANGE(2.5),
+ BIP_RANGE(1.25),
+ UNI_RANGE(10),
+ UNI_RANGE(5),
+ UNI_RANGE(2.5),
+ UNI_RANGE(1.25)
+ }
+};
+
+static const comedi_lrange me2600_ao_range = {
+ 3,
+ {
+ BIP_RANGE(10),
+ BIP_RANGE(5),
+ UNI_RANGE(10)
+ }
+};
+
+static DEFINE_PCI_DEVICE_TABLE(me_pci_table) = {
+ {PCI_VENDOR_ID_MEILHAUS, ME2600_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ 0},
+ {PCI_VENDOR_ID_MEILHAUS, ME2000_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ 0},
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, me_pci_table);
+
+/* Board specification structure */
+struct me_board {
+ const char *name; /* driver name */
+ int device_id;
+ int ao_channel_nbr; /* DA config */
+ int ao_resolution;
+ int ao_resolution_mask;
+ const comedi_lrange *ao_range_list;
+ int ai_channel_nbr; /* AD config */
+ int ai_resolution;
+ int ai_resolution_mask;
+ const comedi_lrange *ai_range_list;
+ int dio_channel_nbr; /* DIO config */
+};
+
+static const struct me_board me_boards[] = {
+ {
+ /* -- ME-2600i -- */
+ .name = ME_DRIVER_NAME,
+ .device_id = ME2600_DEVICE_ID,
+ /* Analog Output */
+ .ao_channel_nbr = 4,
+ .ao_resolution = 12,
+ .ao_resolution_mask = 0x0fff,
+ .ao_range_list = &me2600_ao_range,
+ .ai_channel_nbr = 16,
+ /* Analog Input */
+ .ai_resolution = 12,
+ .ai_resolution_mask = 0x0fff,
+ .ai_range_list = &me2600_ai_range,
+ .dio_channel_nbr = 32,
+ },
+ {
+ /* -- ME-2000i -- */
+ .name = ME_DRIVER_NAME,
+ .device_id = ME2000_DEVICE_ID,
+ /* Analog Output */
+ .ao_channel_nbr = 0,
+ .ao_resolution = 0,
+ .ao_resolution_mask = 0,
+ .ao_range_list = NULL,
+ .ai_channel_nbr = 16,
+ /* Analog Input */
+ .ai_resolution = 12,
+ .ai_resolution_mask = 0x0fff,
+ .ai_range_list = &me2000_ai_range,
+ .dio_channel_nbr = 32,
+ }
+};
+
+#define me_board_nbr (sizeof(me_boards)/sizeof(struct me_board))
+
+static comedi_driver me_driver = {
+ .driver_name = ME_DRIVER_NAME,
+ .module = THIS_MODULE,
+ .attach = me_attach,
+ .detach = me_detach,
+};
+COMEDI_PCI_INITCLEANUP(me_driver, me_pci_table);
+
+/* Private data structure */
+struct me_private_data {
+ struct pci_dev *pci_device;
+ void __iomem *plx_regbase; /* PLX configuration base address */
+ void __iomem *me_regbase; /* Base address of the Meilhaus card */
+ unsigned long plx_regbase_size; /* Size of PLX configuration space */
+ unsigned long me_regbase_size; /* Size of Meilhaus space */
+
+ unsigned short control_1; /* Mirror of CONTROL_1 register */
+ unsigned short control_2; /* Mirror of CONTROL_2 register */
+ unsigned short dac_control; /* Mirror of the DAC_CONTROL register */
+ int ao_readback[4]; /* Mirror of analog output data */
+};
+
+#define dev_private ((struct me_private_data *)dev->private)
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * Helpful functions
+ *
+ * ------------------------------------------------------------------
+ */
+static inline void sleep(unsigned sec)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(sec * HZ);
+}
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * DIGITAL INPUT/OUTPUT SECTION
+ *
+ * ------------------------------------------------------------------
+ */
+static int me_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int bits;
+ int mask = 1 << CR_CHAN(insn->chanspec);
+
+ /* calculate port */
+ if (mask & 0x0000ffff) { /* Port A in use */
+ bits = 0x0000ffff;
+
+ /* Enable Port A */
+ dev_private->control_2 |= ENABLE_PORT_A;
+ writew(dev_private->control_2,
+ dev_private->me_regbase + ME_CONTROL_2);
+ } else { /* Port B in use */
+
+ bits = 0xffff0000;
+
+ /* Enable Port B */
+ dev_private->control_2 |= ENABLE_PORT_B;
+ writew(dev_private->control_2,
+ dev_private->me_regbase + ME_CONTROL_2);
+ }
+
+ if (data[0]) {
+ /* Config port as output */
+ s->io_bits |= bits;
+ } else {
+ /* Config port as input */
+ s->io_bits &= ~bits;
+ }
+
+ return 1;
+}
+
+/* Digital instant input/outputs */
+static int me_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ unsigned int mask = data[0];
+ s->state &= ~mask;
+ s->state |= (mask & data[1]);
+
+ mask &= s->io_bits;
+ if (mask & 0x0000ffff) { /* Port A */
+ writew((s->state & 0xffff),
+ dev_private->me_regbase + ME_DIO_PORT_A);
+ } else {
+ data[1] &= ~0x0000ffff;
+ data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_A);
+ }
+
+ if (mask & 0xffff0000) { /* Port B */
+ writew(((s->state >> 16) & 0xffff),
+ dev_private->me_regbase + ME_DIO_PORT_B);
+ } else {
+ data[1] &= ~0xffff0000;
+ data[1] |= readw(dev_private->me_regbase + ME_DIO_PORT_B) << 16;
+ }
+
+ return 2;
+}
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * ANALOG INPUT SECTION
+ *
+ * ------------------------------------------------------------------
+ */
+
+/* Analog instant input */
+static int me_ai_insn_read(comedi_device *dev, comedi_subdevice *subdevice,
+ comedi_insn *insn, lsampl_t *data)
+{
+ unsigned short value;
+ int chan = CR_CHAN((&insn->chanspec)[0]);
+ int rang = CR_RANGE((&insn->chanspec)[0]);
+ int aref = CR_AREF((&insn->chanspec)[0]);
+ int i;
+
+ /* stop any running conversion */
+ dev_private->control_1 &= 0xFFFC;
+ writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
+
+ /* clear chanlist and ad fifo */
+ dev_private->control_2 &= ~(ENABLE_ADFIFO | ENABLE_CHANLIST);
+ writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+
+ /* reset any pending interrupt */
+ writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
+
+ /* enable the chanlist and ADC fifo */
+ dev_private->control_2 |= (ENABLE_ADFIFO | ENABLE_CHANLIST);
+ writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+
+ /* write to channel list fifo */
+ /* b3:b0 are the channel number */
+ value = chan & 0x0f;
+ /* b5:b4 are the channel gain */
+ value |= (rang & 0x03) << 4;
+ /* b6 channel polarity */
+ value |= (rang & 0x04) << 4;
+ /* b7 single or differential */
+ value |= ((aref & AREF_DIFF) ? 0x80 : 0);
+ writew(value & 0xff, dev_private->me_regbase + ME_CHANNEL_LIST);
+
+ /* set ADC mode to software trigger */
+ dev_private->control_1 |= SOFTWARE_TRIGGERED_ADC;
+ writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
+
+ /* start conversion by reading from ADC_START */
+ readw(dev_private->me_regbase + ME_ADC_START);
+
+ /* wait for ADC fifo not empty flag */
+ for (i = 100000; i > 0; i--)
+ if (!(readw(dev_private->me_regbase + ME_STATUS) & 0x0004))
+ break;
+
+ /* get value from ADC fifo */
+ if (i) {
+ data[0] =
+ (readw(dev_private->me_regbase +
+ ME_READ_AD_FIFO) ^ 0x800) & 0x0FFF;
+ } else {
+ printk(KERN_ERR "comedi%d: Cannot get single value\n",
+ dev->minor);
+ return -EIO;
+ }
+
+ /* stop any running conversion */
+ dev_private->control_1 &= 0xFFFC;
+ writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
+
+ return 1;
+}
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * HARDWARE TRIGGERED ANALOG INPUT SECTION
+ *
+ * ------------------------------------------------------------------
+ */
+
+/* Cancel analog input autoscan */
+static int me_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+ /* disable interrupts */
+
+ /* stop any running conversion */
+ dev_private->control_1 &= 0xFFFC;
+ writew(dev_private->control_1, dev_private->me_regbase + ME_CONTROL_1);
+
+ return 0;
+}
+
+/* Test analog input command */
+static int me_ai_do_cmd_test(comedi_device *dev, comedi_subdevice *s,
+ comedi_cmd *cmd)
+{
+ return 0;
+}
+
+/* Analog input command */
+static int me_ai_do_cmd(comedi_device *dev, comedi_subdevice *subdevice)
+{
+ return 0;
+}
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * ANALOG OUTPUT SECTION
+ *
+ * ------------------------------------------------------------------
+ */
+
+/* Analog instant output */
+static int me_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int chan;
+ int rang;
+ int i;
+
+ /* Enable all DAC */
+ dev_private->control_2 |= ENABLE_DAC;
+ writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+
+ /* and set DAC to "buffered" mode */
+ dev_private->control_2 |= BUFFERED_DAC;
+ writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
+
+ /* Set dac-control register */
+ for (i = 0; i < insn->n; i++) {
+ chan = CR_CHAN((&insn->chanspec)[i]);
+ rang = CR_RANGE((&insn->chanspec)[i]);
+
+ /* clear bits for this channel */
+ dev_private->dac_control &= ~(0x0880 >> chan);
+ if (rang == 0)
+ dev_private->dac_control |=
+ ((DAC_BIPOLAR_A | DAC_GAIN_1_A) >> chan);
+ else if (rang == 1)
+ dev_private->dac_control |=
+ ((DAC_BIPOLAR_A | DAC_GAIN_0_A) >> chan);
+ }
+ writew(dev_private->dac_control,
+ dev_private->me_regbase + ME_DAC_CONTROL);
+
+ /* Update dac-control register */
+ readw(dev_private->me_regbase + ME_DAC_CONTROL_UPDATE);
+
+ /* Set data register */
+ for (i = 0; i < insn->n; i++) {
+ chan = CR_CHAN((&insn->chanspec)[i]);
+ writew((data[0] & s->maxdata),
+ dev_private->me_regbase + ME_DAC_DATA_A + (chan << 1));
+ dev_private->ao_readback[chan] = (data[0] & s->maxdata);
+ }
+
+ /* Update dac with data registers */
+ readw(dev_private->me_regbase + ME_DAC_UPDATE);
+
+ return i;
+}
+
+/* Analog output readback */
+static int me_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int i;
+
+ for (i = 0; i < insn->n; i++) {
+ data[i] =
+ dev_private->ao_readback[CR_CHAN((&insn->chanspec)[i])];
+ }
+
+ return 1;
+}
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * INITIALISATION SECTION
+ *
+ * ------------------------------------------------------------------
+ */
+
+/* Xilinx firmware download for card: ME-2600i */
+static int me2600_xilinx_download(comedi_device *dev,
+ unsigned char *me2600_firmware,
+ unsigned int length)
+{
+ unsigned int value;
+ unsigned int file_length;
+ unsigned int i;
+
+ /* disable irq's on PLX */
+ writel(0x00, dev_private->plx_regbase + PLX_INTCSR);
+
+ /* First, make a dummy read to reset xilinx */
+ value = readw(dev_private->me_regbase + XILINX_DOWNLOAD_RESET);
+
+ /* Wait until reset is over */
+ sleep(1);
+
+ /* Write a dummy value to Xilinx */
+ writeb(0x00, dev_private->me_regbase + 0x0);
+ sleep(1);
+
+ /*
+ * Format of the firmware
+ * Build longs from the byte-wise coded header
+ * Byte 1-3: length of the array
+ * Byte 4-7: version
+ * Byte 8-11: date
+ * Byte 12-15: reserved
+ */
+ if (length < 16)
+ return -EINVAL;
+ file_length = (((unsigned int)me2600_firmware[0] & 0xff) << 24) +
+ (((unsigned int)me2600_firmware[1] & 0xff) << 16) +
+ (((unsigned int)me2600_firmware[2] & 0xff) << 8) +
+ ((unsigned int)me2600_firmware[3] & 0xff);
+
+ /*
+ * Loop for writing firmware byte by byte to xilinx
+ * Firmware data start at offfset 16
+ */
+ for (i = 0; i < file_length; i++)
+ writeb((me2600_firmware[16 + i] & 0xff),
+ dev_private->me_regbase + 0x0);
+
+ /* Write 5 dummy values to xilinx */
+ for (i = 0; i < 5; i++)
+ writeb(0x00, dev_private->me_regbase + 0x0);
+
+ /* Test if there was an error during download -> INTB was thrown */
+ value = readl(dev_private->plx_regbase + PLX_INTCSR);
+ if (value & 0x20) {
+ /* Disable interrupt */
+ writel(0x00, dev_private->plx_regbase + PLX_INTCSR);
+ printk(KERN_ERR "comedi%d: Xilinx download failed\n",
+ dev->minor);
+ return -EIO;
+ }
+
+ /* Wait until the Xilinx is ready for real work */
+ sleep(1);
+
+ /* Enable PLX-Interrupts */
+ writel(0x43, dev_private->plx_regbase + PLX_INTCSR);
+
+ return 0;
+}
+
+/* Reset device */
+static int me_reset(comedi_device *dev)
+{
+ /* Reset board */
+ writew(0x00, dev_private->me_regbase + ME_CONTROL_1);
+ writew(0x00, dev_private->me_regbase + ME_CONTROL_2);
+ writew(0x00, dev_private->me_regbase + ME_RESET_INTERRUPT);
+ writew(0x00, dev_private->me_regbase + ME_DAC_CONTROL);
+
+ /* Save values in the board context */
+ dev_private->dac_control = 0;
+ dev_private->control_1 = 0;
+ dev_private->control_2 = 0;
+
+ return 0;
+}
+
+/*
+ * Attach
+ *
+ * - Register PCI device
+ * - Declare device driver capability
+ */
+static int me_attach(comedi_device *dev, comedi_devconfig *it)
+{
+ struct pci_dev *pci_device;
+ comedi_subdevice *subdevice;
+ struct me_board *board;
+ resource_size_t plx_regbase_tmp;
+ unsigned long plx_regbase_size_tmp;
+ resource_size_t me_regbase_tmp;
+ unsigned long me_regbase_size_tmp;
+ resource_size_t swap_regbase_tmp;
+ unsigned long swap_regbase_size_tmp;
+ resource_size_t regbase_tmp;
+ int result, error, i;
+
+ /* Allocate private memory */
+ if (alloc_private(dev, sizeof(struct me_private_data)) < 0)
+ return -ENOMEM;
+
+ /* Probe the device to determine what device in the series it is. */
+ for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ pci_device != NULL;
+ pci_device =
+ pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
+ if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
+ for (i = 0; i < me_board_nbr; i++) {
+ if (me_boards[i].device_id ==
+ pci_device->device) {
+ /*
+ * was a particular bus/slot requested?
+ */
+ if ((it->options[0] != 0)
+ || (it->options[1] != 0)) {
+ /*
+ * are we on the wrong bus/slot?
+ */
+ if (pci_device->bus->number !=
+ it->options[0]
+ || PCI_SLOT(pci_device->
+ devfn) !=
+ it->options[1]) {
+ continue;
+ }
+ }
+
+ dev->board_ptr = me_boards + i;
+ board = (struct me_board *) dev->
+ board_ptr;
+ dev_private->pci_device = pci_device;
+ goto found;
+ }
+ }
+ }
+ }
+
+ printk(KERN_ERR
+ "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
+ dev->minor, it->options[0], it->options[1]);
+ return -EIO;
+
+found:
+ printk(KERN_INFO "comedi%d: found %s at PCI bus %d, slot %d\n",
+ dev->minor, me_boards[i].name,
+ pci_device->bus->number, PCI_SLOT(pci_device->devfn));
+
+ /* Enable PCI device and request PCI regions */
+ if (comedi_pci_enable(pci_device, ME_DRIVER_NAME) < 0) {
+ printk(KERN_ERR "comedi%d: Failed to enable PCI device and "
+ "request regions\n", dev->minor);
+ return -EIO;
+ }
+
+ /* Set data in device structure */
+ dev->board_name = board->name;
+
+ /* Read PLX register base address [PCI_BASE_ADDRESS #0]. */
+ plx_regbase_tmp = pci_resource_start(pci_device, 0);
+ plx_regbase_size_tmp = pci_resource_len(pci_device, 0);
+ dev_private->plx_regbase =
+ ioremap(plx_regbase_tmp, plx_regbase_size_tmp);
+ dev_private->plx_regbase_size = plx_regbase_size_tmp;
+ if (!dev_private->plx_regbase) {
+ printk("comedi%d: Failed to remap I/O memory\n", dev->minor);
+ return -ENOMEM;
+ }
+
+ /* Read Swap base address [PCI_BASE_ADDRESS #5]. */
+
+ swap_regbase_tmp = pci_resource_start(pci_device, 5);
+ swap_regbase_size_tmp = pci_resource_len(pci_device, 5);
+
+ if (!swap_regbase_tmp)
+ printk(KERN_ERR "comedi%d: Swap not present\n", dev->minor);
+
+ /*---------------------------------------------- Workaround start ---*/
+ if (plx_regbase_tmp & 0x0080) {
+ printk(KERN_ERR "comedi%d: PLX-Bug detected\n", dev->minor);
+
+ if (swap_regbase_tmp) {
+ regbase_tmp = plx_regbase_tmp;
+ plx_regbase_tmp = swap_regbase_tmp;
+ swap_regbase_tmp = regbase_tmp;
+
+ result = pci_write_config_dword(pci_device,
+ PCI_BASE_ADDRESS_0, plx_regbase_tmp);
+ if (result != PCIBIOS_SUCCESSFUL)
+ return -EIO;
+
+ result = pci_write_config_dword(pci_device,
+ PCI_BASE_ADDRESS_5, swap_regbase_tmp);
+ if (result != PCIBIOS_SUCCESSFUL)
+ return -EIO;
+ } else {
+ plx_regbase_tmp -= 0x80;
+ result = pci_write_config_dword(pci_device,
+ PCI_BASE_ADDRESS_0, plx_regbase_tmp);
+ if (result != PCIBIOS_SUCCESSFUL)
+ return -EIO;
+ }
+ }
+ /*--------------------------------------------- Workaround end -----*/
+
+ /* Read Meilhaus register base address [PCI_BASE_ADDRESS #2]. */
+
+ me_regbase_tmp = pci_resource_start(pci_device, 2);
+ me_regbase_size_tmp = pci_resource_len(pci_device, 2);
+ dev_private->me_regbase_size = me_regbase_size_tmp;
+ dev_private->me_regbase = ioremap(me_regbase_tmp, me_regbase_size_tmp);
+ if (!dev_private->me_regbase) {
+ printk(KERN_ERR "comedi%d: Failed to remap I/O memory\n",
+ dev->minor);
+ return -ENOMEM;
+ }
+ /* Download firmware and reset card */
+ if (board->device_id == ME2600_DEVICE_ID) {
+ unsigned char *aux_data;
+ int aux_len;
+
+ aux_data = comedi_aux_data(it->options, 0);
+ aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH];
+
+ if (!aux_data || aux_len < 1) {
+ comedi_error(dev, "You must provide me2600 firmware "
+ "using the --init-data option of "
+ "comedi_config");
+ return -EINVAL;
+ }
+ me2600_xilinx_download(dev, aux_data, aux_len);
+ }
+
+ me_reset(dev);
+
+ /* device driver capabilities */
+ error = alloc_subdevices(dev, 3);
+ if (error < 0)
+ return error;
+
+ subdevice = dev->subdevices + 0;
+ subdevice->type = COMEDI_SUBD_AI;
+ subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
+ subdevice->n_chan = board->ai_channel_nbr;
+ subdevice->maxdata = board->ai_resolution_mask;
+ subdevice->len_chanlist = board->ai_channel_nbr;
+ subdevice->range_table = board->ai_range_list;
+ subdevice->cancel = me_ai_cancel;
+ subdevice->insn_read = me_ai_insn_read;
+ subdevice->do_cmdtest = me_ai_do_cmd_test;
+ subdevice->do_cmd = me_ai_do_cmd;
+
+ subdevice = dev->subdevices + 1;
+ subdevice->type = COMEDI_SUBD_AO;
+ subdevice->subdev_flags = SDF_WRITEABLE | SDF_COMMON;
+ subdevice->n_chan = board->ao_channel_nbr;
+ subdevice->maxdata = board->ao_resolution_mask;
+ subdevice->len_chanlist = board->ao_channel_nbr;
+ subdevice->range_table = board->ao_range_list;
+ subdevice->insn_read = me_ao_insn_read;
+ subdevice->insn_write = me_ao_insn_write;
+
+ subdevice = dev->subdevices + 2;
+ subdevice->type = COMEDI_SUBD_DIO;
+ subdevice->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
+ subdevice->n_chan = board->dio_channel_nbr;
+ subdevice->maxdata = 1;
+ subdevice->len_chanlist = board->dio_channel_nbr;
+ subdevice->range_table = &range_digital;
+ subdevice->insn_bits = me_dio_insn_bits;
+ subdevice->insn_config = me_dio_insn_config;
+ subdevice->io_bits = 0;
+
+ printk(KERN_INFO "comedi%d: "ME_DRIVER_NAME" attached.\n", dev->minor);
+ return 0;
+}
+
+/* Detach */
+static int me_detach(comedi_device *dev)
+{
+ if (dev_private) {
+ if (dev_private->me_regbase) {
+ me_reset(dev);
+ iounmap(dev_private->me_regbase);
+ }
+ if (dev_private->plx_regbase)
+ iounmap(dev_private->plx_regbase);
+ if (dev_private->pci_device) {
+ if (dev_private->plx_regbase_size)
+ comedi_pci_disable(dev_private->pci_device);
+
+ pci_dev_put(dev_private->pci_device);
+ }
+ }
+ return 0;
+}
diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c
new file mode 100644
index 000000000000..9cc527424d04
--- /dev/null
+++ b/drivers/staging/comedi/drivers/mite.c
@@ -0,0 +1,809 @@
+/*
+ comedi/drivers/mite.c
+ Hardware driver for NI Mite PCI interface chip
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/*
+ The PCI-MIO E series driver was originally written by
+ Tomasz Motylewski <...>, and ported to comedi by ds.
+
+ References for specifications:
+
+ 321747b.pdf Register Level Programmer Manual (obsolete)
+ 321747c.pdf Register Level Programmer Manual (new)
+ DAQ-STC reference manual
+
+ Other possibly relevant info:
+
+ 320517c.pdf User manual (obsolete)
+ 320517f.pdf User manual (new)
+ 320889a.pdf delete
+ 320906c.pdf maximum signal ratings
+ 321066a.pdf about 16x
+ 321791a.pdf discontinuation of at-mio-16e-10 rev. c
+ 321808a.pdf about at-mio-16e-10 rev P
+ 321837a.pdf discontinuation of at-mio-16de-10 rev d
+ 321838a.pdf about at-mio-16de-10 rev N
+
+ ISSUES:
+
+*/
+
+//#define USE_KMALLOC
+
+#include "mite.h"
+
+#include "comedi_fc.h"
+#include "comedi_pci.h"
+#include "../comedidev.h"
+
+#include <asm/system.h>
+
+#define PCI_MITE_SIZE 4096
+#define PCI_DAQ_SIZE 4096
+#define PCI_DAQ_SIZE_660X 8192
+
+MODULE_LICENSE("GPL");
+
+struct mite_struct *mite_devices = NULL;
+
+#define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))
+
+void mite_init(void)
+{
+ struct pci_dev *pcidev;
+ struct mite_struct *mite;
+
+ for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
+ pcidev != NULL;
+ pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
+ if (pcidev->vendor == PCI_VENDOR_ID_NATINST) {
+ unsigned i;
+
+ mite = kzalloc(sizeof(*mite), GFP_KERNEL);
+ if (!mite) {
+ printk("mite: allocation failed\n");
+ pci_dev_put(pcidev);
+ return;
+ }
+ spin_lock_init(&mite->lock);
+ mite->pcidev = pci_dev_get(pcidev);
+ for (i = 0; i < MAX_MITE_DMA_CHANNELS; ++i) {
+ mite->channels[i].mite = mite;
+ mite->channels[i].channel = i;
+ mite->channels[i].done = 1;
+ }
+ mite->next = mite_devices;
+ mite_devices = mite;
+ }
+ }
+}
+
+static void dump_chip_signature(u32 csigr_bits)
+{
+ printk("mite: version = %i, type = %i, mite mode = %i, interface mode = %i\n", mite_csigr_version(csigr_bits), mite_csigr_type(csigr_bits), mite_csigr_mmode(csigr_bits), mite_csigr_imode(csigr_bits));
+ printk("mite: num channels = %i, write post fifo depth = %i, wins = %i, iowins = %i\n", mite_csigr_dmac(csigr_bits), mite_csigr_wpdep(csigr_bits), mite_csigr_wins(csigr_bits), mite_csigr_iowins(csigr_bits));
+}
+
+unsigned mite_fifo_size(struct mite_struct * mite, unsigned channel)
+{
+ unsigned fcr_bits = readl(mite->mite_io_addr +
+ MITE_FCR(channel));
+ unsigned empty_count = (fcr_bits >> 16) & 0xff;
+ unsigned full_count = fcr_bits & 0xff;
+ return empty_count + full_count;
+}
+
+int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1)
+{
+ unsigned long length;
+ resource_size_t addr;
+ int i;
+ u32 csigr_bits;
+ unsigned unknown_dma_burst_bits;
+
+ if (comedi_pci_enable(mite->pcidev, "mite")) {
+ printk("error enabling mite and requesting io regions\n");
+ return -EIO;
+ }
+ pci_set_master(mite->pcidev);
+
+ addr = pci_resource_start(mite->pcidev, 0);
+ mite->mite_phys_addr = addr;
+ mite->mite_io_addr = ioremap(addr, PCI_MITE_SIZE);
+ if (!mite->mite_io_addr) {
+ printk("failed to remap mite io memory address\n");
+ return -ENOMEM;
+ }
+ printk("MITE:0x%08llx mapped to %p ",
+ (unsigned long long)mite->mite_phys_addr, mite->mite_io_addr);
+
+ addr = pci_resource_start(mite->pcidev, 1);
+ mite->daq_phys_addr = addr;
+ length = pci_resource_len(mite->pcidev, 1);
+ // In case of a 660x board, DAQ size is 8k instead of 4k (see as shown by lspci output)
+ mite->daq_io_addr = ioremap(mite->daq_phys_addr, length);
+ if (!mite->daq_io_addr) {
+ printk("failed to remap daq io memory address\n");
+ return -ENOMEM;
+ }
+ printk("DAQ:0x%08llx mapped to %p\n",
+ (unsigned long long)mite->daq_phys_addr, mite->daq_io_addr);
+
+ if (use_iodwbsr_1) {
+ writel(0, mite->mite_io_addr + MITE_IODWBSR);
+ printk("mite: using I/O Window Base Size register 1\n");
+ writel(mite->
+ daq_phys_addr | WENAB |
+ MITE_IODWBSR_1_WSIZE_bits(length),
+ mite->mite_io_addr + MITE_IODWBSR_1);
+ writel(0, mite->mite_io_addr + MITE_IODWCR_1);
+ } else {
+ writel(mite->daq_phys_addr | WENAB,
+ mite->mite_io_addr + MITE_IODWBSR);
+ }
+ /* make sure dma bursts work. I got this from running a bus analyzer
+ on a pxi-6281 and a pxi-6713. 6713 powered up with register value
+ of 0x61f and bursts worked. 6281 powered up with register value of
+ 0x1f and bursts didn't work. The NI windows driver reads the register,
+ then does a bitwise-or of 0x600 with it and writes it back.
+ */
+ unknown_dma_burst_bits =
+ readl(mite->mite_io_addr + MITE_UNKNOWN_DMA_BURST_REG);
+ unknown_dma_burst_bits |= UNKNOWN_DMA_BURST_ENABLE_BITS;
+ writel(unknown_dma_burst_bits,
+ mite->mite_io_addr + MITE_UNKNOWN_DMA_BURST_REG);
+
+ csigr_bits = readl(mite->mite_io_addr + MITE_CSIGR);
+ mite->num_channels = mite_csigr_dmac(csigr_bits);
+ if (mite->num_channels > MAX_MITE_DMA_CHANNELS) {
+ printk("mite: bug? chip claims to have %i dma channels. Setting to %i.\n", mite->num_channels, MAX_MITE_DMA_CHANNELS);
+ mite->num_channels = MAX_MITE_DMA_CHANNELS;
+ }
+ dump_chip_signature(csigr_bits);
+ for (i = 0; i < mite->num_channels; i++) {
+ writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR(i));
+ /* disable interrupts */
+ writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE |
+ CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE |
+ CHCR_CLR_LC_IE | CHCR_CLR_CONT_RB_IE,
+ mite->mite_io_addr + MITE_CHCR(i));
+ }
+ mite->fifo_size = mite_fifo_size(mite, 0);
+ printk("mite: fifo size is %i.\n", mite->fifo_size);
+ mite->used = 1;
+
+ return 0;
+}
+
+int mite_setup(struct mite_struct *mite)
+{
+ return mite_setup2(mite, 0);
+}
+
+void mite_cleanup(void)
+{
+ struct mite_struct *mite, *next;
+
+ for (mite = mite_devices; mite; mite = next) {
+ pci_dev_put(mite->pcidev);
+ next = mite->next;
+ kfree(mite);
+ }
+}
+
+void mite_unsetup(struct mite_struct *mite)
+{
+ //unsigned long offset, start, length;
+
+ if (!mite)
+ return;
+
+ if (mite->mite_io_addr) {
+ iounmap(mite->mite_io_addr);
+ mite->mite_io_addr = NULL;
+ }
+ if (mite->daq_io_addr) {
+ iounmap(mite->daq_io_addr);
+ mite->daq_io_addr = NULL;
+ }
+ if (mite->mite_phys_addr) {
+ comedi_pci_disable(mite->pcidev);
+ mite->mite_phys_addr = 0;
+ }
+
+ mite->used = 0;
+}
+
+void mite_list_devices(void)
+{
+ struct mite_struct *mite, *next;
+
+ printk("Available NI device IDs:");
+ if (mite_devices)
+ for (mite = mite_devices; mite; mite = next) {
+ next = mite->next;
+ printk(" 0x%04x", mite_device_id(mite));
+ if (mite->used)
+ printk("(used)");
+ }
+ printk("\n");
+
+}
+
+struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
+ struct mite_dma_descriptor_ring *ring, unsigned min_channel,
+ unsigned max_channel)
+{
+ int i;
+ unsigned long flags;
+ struct mite_channel *channel = NULL;
+
+ // spin lock so mite_release_channel can be called safely from interrupts
+ comedi_spin_lock_irqsave(&mite->lock, flags);
+ for (i = min_channel; i <= max_channel; ++i) {
+ if (mite->channel_allocated[i] == 0) {
+ mite->channel_allocated[i] = 1;
+ channel = &mite->channels[i];
+ channel->ring = ring;
+ break;
+ }
+ }
+ comedi_spin_unlock_irqrestore(&mite->lock, flags);
+ return channel;
+}
+
+void mite_release_channel(struct mite_channel *mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ unsigned long flags;
+
+ // spin lock to prevent races with mite_request_channel
+ comedi_spin_lock_irqsave(&mite->lock, flags);
+ if (mite->channel_allocated[mite_chan->channel]) {
+ mite_dma_disarm(mite_chan);
+ mite_dma_reset(mite_chan);
+/* disable all channel's interrupts (do it after disarm/reset so
+MITE_CHCR reg isn't changed while dma is still active!) */
+ writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE |
+ CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE |
+ CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE |
+ CHCR_CLR_LC_IE | CHCR_CLR_CONT_RB_IE,
+ mite->mite_io_addr + MITE_CHCR(mite_chan->channel));
+ mite->channel_allocated[mite_chan->channel] = 0;
+ mite_chan->ring = NULL;
+ mmiowb();
+ }
+ comedi_spin_unlock_irqrestore(&mite->lock, flags);
+}
+
+void mite_dma_arm(struct mite_channel *mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ int chor;
+ unsigned long flags;
+
+ MDPRINTK("mite_dma_arm ch%i\n", channel);
+ /* memory barrier is intended to insure any twiddling with the buffer
+ is done before writing to the mite to arm dma transfer */
+ smp_mb();
+ /* arm */
+ chor = CHOR_START;
+ comedi_spin_lock_irqsave(&mite->lock, flags);
+ mite_chan->done = 0;
+ writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+ mmiowb();
+ comedi_spin_unlock_irqrestore(&mite->lock, flags);
+// mite_dma_tcr(mite, channel);
+}
+
+/**************************************/
+
+int mite_buf_change(struct mite_dma_descriptor_ring *ring, comedi_async * async)
+{
+ unsigned int n_links;
+ int i;
+
+ if (ring->descriptors) {
+ dma_free_coherent(ring->hw_dev,
+ ring->n_links * sizeof(struct mite_dma_descriptor),
+ ring->descriptors, ring->descriptors_dma_addr);
+ }
+ ring->descriptors = NULL;
+ ring->descriptors_dma_addr = 0;
+ ring->n_links = 0;
+
+ if (async->prealloc_bufsz == 0) {
+ return 0;
+ }
+ n_links = async->prealloc_bufsz >> PAGE_SHIFT;
+
+ MDPRINTK("ring->hw_dev=%p, n_links=0x%04x\n", ring->hw_dev, n_links);
+
+ ring->descriptors =
+ dma_alloc_coherent(ring->hw_dev,
+ n_links * sizeof(struct mite_dma_descriptor),
+ &ring->descriptors_dma_addr, GFP_KERNEL);
+ if (!ring->descriptors) {
+ printk("mite: ring buffer allocation failed\n");
+ return -ENOMEM;
+ }
+ ring->n_links = n_links;
+
+ for (i = 0; i < n_links; i++) {
+ ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE);
+ ring->descriptors[i].addr =
+ cpu_to_le32(async->buf_page_list[i].dma_addr);
+ ring->descriptors[i].next =
+ cpu_to_le32(ring->descriptors_dma_addr + (i +
+ 1) * sizeof(struct mite_dma_descriptor));
+ }
+ ring->descriptors[n_links - 1].next =
+ cpu_to_le32(ring->descriptors_dma_addr);
+ /* barrier is meant to insure that all the writes to the dma descriptors
+ have completed before the dma controller is commanded to read them */
+ smp_wmb();
+ return 0;
+}
+
+void mite_prep_dma(struct mite_channel *mite_chan,
+ unsigned int num_device_bits, unsigned int num_memory_bits)
+{
+ unsigned int chor, chcr, mcr, dcr, lkcr;
+ struct mite_struct *mite = mite_chan->mite;
+
+ MDPRINTK("mite_prep_dma ch%i\n", mite_chan->channel);
+
+ /* reset DMA and FIFO */
+ chor = CHOR_DMARESET | CHOR_FRESET;
+ writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+
+ /* short link chaining mode */
+ chcr = CHCR_SET_DMA_IE | CHCR_LINKSHORT | CHCR_SET_DONE_IE |
+ CHCR_BURSTEN;
+ /*
+ * Link Complete Interrupt: interrupt every time a link
+ * in MITE_RING is completed. This can generate a lot of
+ * extra interrupts, but right now we update the values
+ * of buf_int_ptr and buf_int_count at each interrupt. A
+ * better method is to poll the MITE before each user
+ * "read()" to calculate the number of bytes available.
+ */
+ chcr |= CHCR_SET_LC_IE;
+ if (num_memory_bits == 32 && num_device_bits == 16) {
+ /* Doing a combined 32 and 16 bit byteswap gets the 16 bit samples into the fifo in the right order.
+ Tested doing 32 bit memory to 16 bit device transfers to the analog out of a pxi-6281,
+ which has mite version = 1, type = 4. This also works for dma reads from the counters
+ on e-series boards. */
+ chcr |= CHCR_BYTE_SWAP_DEVICE | CHCR_BYTE_SWAP_MEMORY;
+ }
+ if (mite_chan->dir == COMEDI_INPUT) {
+ chcr |= CHCR_DEV_TO_MEM;
+ }
+ writel(chcr, mite->mite_io_addr + MITE_CHCR(mite_chan->channel));
+
+ /* to/from memory */
+ mcr = CR_RL(64) | CR_ASEQUP;
+ switch (num_memory_bits) {
+ case 8:
+ mcr |= CR_PSIZE8;
+ break;
+ case 16:
+ mcr |= CR_PSIZE16;
+ break;
+ case 32:
+ mcr |= CR_PSIZE32;
+ break;
+ default:
+ rt_printk
+ ("mite: bug! invalid mem bit width for dma transfer\n");
+ break;
+ }
+ writel(mcr, mite->mite_io_addr + MITE_MCR(mite_chan->channel));
+
+ /* from/to device */
+ dcr = CR_RL(64) | CR_ASEQUP;
+ dcr |= CR_PORTIO | CR_AMDEVICE | CR_REQSDRQ(mite_chan->channel);
+ switch (num_device_bits) {
+ case 8:
+ dcr |= CR_PSIZE8;
+ break;
+ case 16:
+ dcr |= CR_PSIZE16;
+ break;
+ case 32:
+ dcr |= CR_PSIZE32;
+ break;
+ default:
+ rt_printk
+ ("mite: bug! invalid dev bit width for dma transfer\n");
+ break;
+ }
+ writel(dcr, mite->mite_io_addr + MITE_DCR(mite_chan->channel));
+
+ /* reset the DAR */
+ writel(0, mite->mite_io_addr + MITE_DAR(mite_chan->channel));
+
+ /* the link is 32bits */
+ lkcr = CR_RL(64) | CR_ASEQUP | CR_PSIZE32;
+ writel(lkcr, mite->mite_io_addr + MITE_LKCR(mite_chan->channel));
+
+ /* starting address for link chaining */
+ writel(mite_chan->ring->descriptors_dma_addr,
+ mite->mite_io_addr + MITE_LKAR(mite_chan->channel));
+
+ MDPRINTK("exit mite_prep_dma\n");
+}
+
+u32 mite_device_bytes_transferred(struct mite_channel *mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ return readl(mite->mite_io_addr + MITE_DAR(mite_chan->channel));
+}
+
+u32 mite_bytes_in_transit(struct mite_channel * mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ return readl(mite->mite_io_addr +
+ MITE_FCR(mite_chan->channel)) & 0x000000FF;
+}
+
+// returns lower bound for number of bytes transferred from device to memory
+u32 mite_bytes_written_to_memory_lb(struct mite_channel * mite_chan)
+{
+ u32 device_byte_count;
+
+ device_byte_count = mite_device_bytes_transferred(mite_chan);
+ return device_byte_count - mite_bytes_in_transit(mite_chan);
+}
+
+// returns upper bound for number of bytes transferred from device to memory
+u32 mite_bytes_written_to_memory_ub(struct mite_channel * mite_chan)
+{
+ u32 in_transit_count;
+
+ in_transit_count = mite_bytes_in_transit(mite_chan);
+ return mite_device_bytes_transferred(mite_chan) - in_transit_count;
+}
+
+// returns lower bound for number of bytes read from memory for transfer to device
+u32 mite_bytes_read_from_memory_lb(struct mite_channel * mite_chan)
+{
+ u32 device_byte_count;
+
+ device_byte_count = mite_device_bytes_transferred(mite_chan);
+ return device_byte_count + mite_bytes_in_transit(mite_chan);
+}
+
+// returns upper bound for number of bytes read from memory for transfer to device
+u32 mite_bytes_read_from_memory_ub(struct mite_channel * mite_chan)
+{
+ u32 in_transit_count;
+
+ in_transit_count = mite_bytes_in_transit(mite_chan);
+ return mite_device_bytes_transferred(mite_chan) + in_transit_count;
+}
+
+unsigned mite_dma_tcr(struct mite_channel *mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ int tcr;
+ int lkar;
+
+ lkar = readl(mite->mite_io_addr + MITE_LKAR(mite_chan->channel));
+ tcr = readl(mite->mite_io_addr + MITE_TCR(mite_chan->channel));
+ MDPRINTK("mite_dma_tcr ch%i, lkar=0x%08x tcr=%d\n", mite_chan->channel,
+ lkar, tcr);
+
+ return tcr;
+}
+
+void mite_dma_disarm(struct mite_channel *mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ unsigned chor;
+
+ /* disarm */
+ chor = CHOR_ABORT;
+ writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+}
+
+int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async)
+{
+ int count;
+ unsigned int nbytes, old_alloc_count;
+ const unsigned bytes_per_scan = cfc_bytes_per_scan(async->subdevice);
+
+ old_alloc_count = async->buf_write_alloc_count;
+ // write alloc as much as we can
+ comedi_buf_write_alloc(async, async->prealloc_bufsz);
+
+ nbytes = mite_bytes_written_to_memory_lb(mite_chan);
+ if ((int)(mite_bytes_written_to_memory_ub(mite_chan) -
+ old_alloc_count) > 0) {
+ rt_printk("mite: DMA overwrite of free area\n");
+ async->events |= COMEDI_CB_OVERFLOW;
+ return -1;
+ }
+
+ count = nbytes - async->buf_write_count;
+ /* it's possible count will be negative due to
+ * conservative value returned by mite_bytes_written_to_memory_lb */
+ if (count <= 0) {
+ return 0;
+ }
+ comedi_buf_write_free(async, count);
+
+ async->scan_progress += count;
+ if (async->scan_progress >= bytes_per_scan) {
+ async->scan_progress %= bytes_per_scan;
+ async->events |= COMEDI_CB_EOS;
+ }
+ async->events |= COMEDI_CB_BLOCK;
+ return 0;
+}
+
+int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async)
+{
+ int count;
+ u32 nbytes_ub, nbytes_lb;
+ unsigned int old_alloc_count;
+ u32 stop_count =
+ async->cmd.stop_arg * cfc_bytes_per_scan(async->subdevice);
+
+ old_alloc_count = async->buf_read_alloc_count;
+ // read alloc as much as we can
+ comedi_buf_read_alloc(async, async->prealloc_bufsz);
+ nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan);
+ if (async->cmd.stop_src == TRIG_COUNT &&
+ (int)(nbytes_lb - stop_count) > 0)
+ nbytes_lb = stop_count;
+ nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan);
+ if (async->cmd.stop_src == TRIG_COUNT &&
+ (int)(nbytes_ub - stop_count) > 0)
+ nbytes_ub = stop_count;
+ if ((int)(nbytes_ub - old_alloc_count) > 0) {
+ rt_printk("mite: DMA underrun\n");
+ async->events |= COMEDI_CB_OVERFLOW;
+ return -1;
+ }
+ count = nbytes_lb - async->buf_read_count;
+ if (count <= 0) {
+ return 0;
+ }
+ if (count) {
+ comedi_buf_read_free(async, count);
+ async->events |= COMEDI_CB_BLOCK;
+ }
+ return 0;
+}
+
+unsigned mite_get_status(struct mite_channel *mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ unsigned status;
+ unsigned long flags;
+
+ comedi_spin_lock_irqsave(&mite->lock, flags);
+ status = readl(mite->mite_io_addr + MITE_CHSR(mite_chan->channel));
+ if (status & CHSR_DONE) {
+ mite_chan->done = 1;
+ writel(CHOR_CLRDONE,
+ mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+ }
+ mmiowb();
+ comedi_spin_unlock_irqrestore(&mite->lock, flags);
+ return status;
+}
+
+int mite_done(struct mite_channel *mite_chan)
+{
+ struct mite_struct *mite = mite_chan->mite;
+ unsigned long flags;
+ int done;
+
+ mite_get_status(mite_chan);
+ comedi_spin_lock_irqsave(&mite->lock, flags);
+ done = mite_chan->done;
+ comedi_spin_unlock_irqrestore(&mite->lock, flags);
+ return done;
+}
+
+#ifdef DEBUG_MITE
+
+static void mite_decode(char **bit_str, unsigned int bits);
+
+/* names of bits in mite registers */
+
+static const char *const mite_CHOR_strings[] = {
+ "start", "cont", "stop", "abort",
+ "freset", "clrlc", "clrrb", "clrdone",
+ "clr_lpause", "set_lpause", "clr_send_tc",
+ "set_send_tc", "12", "13", "14",
+ "15", "16", "17", "18",
+ "19", "20", "21", "22",
+ "23", "24", "25", "26",
+ "27", "28", "29", "30",
+ "dmareset",
+};
+
+static const char *const mite_CHCR_strings[] = {
+ "continue", "ringbuff", "2", "3",
+ "4", "5", "6", "7",
+ "8", "9", "10", "11",
+ "12", "13", "bursten", "fifodis",
+ "clr_cont_rb_ie", "set_cont_rb_ie", "clr_lc_ie", "set_lc_ie",
+ "clr_drdy_ie", "set_drdy_ie", "clr_mrdy_ie", "set_mrdy_ie",
+ "clr_done_ie", "set_done_ie", "clr_sar_ie", "set_sar_ie",
+ "clr_linkp_ie", "set_linkp_ie", "clr_dma_ie", "set_dma_ie",
+};
+
+static const char *const mite_MCR_strings[] = {
+ "amdevice", "1", "2", "3",
+ "4", "5", "portio", "portvxi",
+ "psizebyte", "psizehalf (byte & half = word)", "aseqxp1", "11",
+ "12", "13", "blocken", "berhand",
+ "reqsintlim/reqs0", "reqs1", "reqs2", "rd32",
+ "rd512", "rl1", "rl2", "rl8",
+ "24", "25", "26", "27",
+ "28", "29", "30", "stopen",
+};
+
+static const char *const mite_DCR_strings[] = {
+ "amdevice", "1", "2", "3",
+ "4", "5", "portio", "portvxi",
+ "psizebyte", "psizehalf (byte & half = word)", "aseqxp1", "aseqxp2",
+ "aseqxp8", "13", "blocken", "berhand",
+ "reqsintlim", "reqs1", "reqs2", "rd32",
+ "rd512", "rl1", "rl2", "rl8",
+ "23", "24", "25", "27",
+ "28", "wsdevc", "wsdevs", "rwdevpack",
+};
+
+static const char *const mite_LKCR_strings[] = {
+ "amdevice", "1", "2", "3",
+ "4", "5", "portio", "portvxi",
+ "psizebyte", "psizehalf (byte & half = word)", "asequp", "aseqdown",
+ "12", "13", "14", "berhand",
+ "16", "17", "18", "rd32",
+ "rd512", "rl1", "rl2", "rl8",
+ "24", "25", "26", "27",
+ "28", "29", "30", "chngend",
+};
+
+static const char *const mite_CHSR_strings[] = {
+ "d.err0", "d.err1", "m.err0", "m.err1",
+ "l.err0", "l.err1", "drq0", "drq1",
+ "end", "xferr", "operr0", "operr1",
+ "stops", "habort", "sabort", "error",
+ "16", "conts_rb", "18", "linkc",
+ "20", "drdy", "22", "mrdy",
+ "24", "done", "26", "sars",
+ "28", "lpauses", "30", "int",
+};
+
+void mite_dump_regs(struct mite_channel *mite_chan)
+{
+ unsigned long mite_io_addr =
+ (unsigned long)mite_chan->mite->mite_io_addr;
+ unsigned long addr = 0;
+ unsigned long temp = 0;
+
+ printk("mite_dump_regs ch%i\n", mite_chan->channel);
+ printk("mite address is =0x%08lx\n", mite_io_addr);
+
+ addr = mite_io_addr + MITE_CHOR(channel);
+ printk("mite status[CHOR]at 0x%08lx =0x%08lx\n", addr, temp =
+ readl(addr));
+ mite_decode(mite_CHOR_strings, temp);
+ addr = mite_io_addr + MITE_CHCR(channel);
+ printk("mite status[CHCR]at 0x%08lx =0x%08lx\n", addr, temp =
+ readl(addr));
+ mite_decode(mite_CHCR_strings, temp);
+ addr = mite_io_addr + MITE_TCR(channel);
+ printk("mite status[TCR] at 0x%08lx =0x%08x\n", addr, readl(addr));
+ addr = mite_io_addr + MITE_MCR(channel);
+ printk("mite status[MCR] at 0x%08lx =0x%08lx\n", addr, temp =
+ readl(addr));
+ mite_decode(mite_MCR_strings, temp);
+
+ addr = mite_io_addr + MITE_MAR(channel);
+ printk("mite status[MAR] at 0x%08lx =0x%08x\n", addr, readl(addr));
+ addr = mite_io_addr + MITE_DCR(channel);
+ printk("mite status[DCR] at 0x%08lx =0x%08lx\n", addr, temp =
+ readl(addr));
+ mite_decode(mite_DCR_strings, temp);
+ addr = mite_io_addr + MITE_DAR(channel);
+ printk("mite status[DAR] at 0x%08lx =0x%08x\n", addr, readl(addr));
+ addr = mite_io_addr + MITE_LKCR(channel);
+ printk("mite status[LKCR]at 0x%08lx =0x%08lx\n", addr, temp =
+ readl(addr));
+ mite_decode(mite_LKCR_strings, temp);
+ addr = mite_io_addr + MITE_LKAR(channel);
+ printk("mite status[LKAR]at 0x%08lx =0x%08x\n", addr, readl(addr));
+
+ addr = mite_io_addr + MITE_CHSR(channel);
+ printk("mite status[CHSR]at 0x%08lx =0x%08lx\n", addr, temp =
+ readl(addr));
+ mite_decode(mite_CHSR_strings, temp);
+ addr = mite_io_addr + MITE_FCR(channel);
+ printk("mite status[FCR] at 0x%08lx =0x%08x\n\n", addr, readl(addr));
+}
+
+static void mite_decode(char **bit_str, unsigned int bits)
+{
+ int i;
+
+ for (i = 31; i >= 0; i--) {
+ if (bits & (1 << i)) {
+ printk(" %s", bit_str[i]);
+ }
+ }
+ printk("\n");
+}
+#endif
+
+#ifdef MODULE
+int __init init_module(void)
+{
+ mite_init();
+ mite_list_devices();
+
+ return 0;
+}
+
+void __exit cleanup_module(void)
+{
+ mite_cleanup();
+}
+
+EXPORT_SYMBOL(mite_dma_tcr);
+EXPORT_SYMBOL(mite_dma_arm);
+EXPORT_SYMBOL(mite_dma_disarm);
+EXPORT_SYMBOL(mite_sync_input_dma);
+EXPORT_SYMBOL(mite_sync_output_dma);
+EXPORT_SYMBOL(mite_setup);
+EXPORT_SYMBOL(mite_setup2);
+EXPORT_SYMBOL(mite_unsetup);
+#if 0
+EXPORT_SYMBOL(mite_kvmem_segment_load);
+EXPORT_SYMBOL(mite_ll_from_kvmem);
+EXPORT_SYMBOL(mite_setregs);
+#endif
+EXPORT_SYMBOL(mite_devices);
+EXPORT_SYMBOL(mite_list_devices);
+EXPORT_SYMBOL(mite_request_channel_in_range);
+EXPORT_SYMBOL(mite_release_channel);
+EXPORT_SYMBOL(mite_prep_dma);
+EXPORT_SYMBOL(mite_buf_change);
+EXPORT_SYMBOL(mite_bytes_written_to_memory_lb);
+EXPORT_SYMBOL(mite_bytes_written_to_memory_ub);
+EXPORT_SYMBOL(mite_bytes_read_from_memory_lb);
+EXPORT_SYMBOL(mite_bytes_read_from_memory_ub);
+EXPORT_SYMBOL(mite_bytes_in_transit);
+EXPORT_SYMBOL(mite_get_status);
+EXPORT_SYMBOL(mite_done);
+#ifdef DEBUG_MITE
+EXPORT_SYMBOL(mite_decode);
+EXPORT_SYMBOL(mite_dump_regs);
+#endif
+
+#endif
diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h
new file mode 100644
index 000000000000..b84eafa6ff2b
--- /dev/null
+++ b/drivers/staging/comedi/drivers/mite.h
@@ -0,0 +1,453 @@
+/*
+ module/mite.h
+ Hardware driver for NI Mite PCI interface chip
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1999 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef _MITE_H_
+#define _MITE_H_
+
+#include <linux/pci.h>
+#include "../comedidev.h"
+
+#define PCI_VENDOR_ID_NATINST 0x1093
+
+// #define DEBUG_MITE
+#define PCIMIO_COMPAT
+
+#ifdef DEBUG_MITE
+#define MDPRINTK(format,args...) printk(format , ## args )
+#else
+#define MDPRINTK(format,args...)
+#endif
+
+#define MAX_MITE_DMA_CHANNELS 8
+
+struct mite_dma_descriptor {
+ u32 count;
+ u32 addr;
+ u32 next;
+ u32 dar;
+};
+
+struct mite_dma_descriptor_ring {
+ struct device *hw_dev;
+ unsigned int n_links;
+ struct mite_dma_descriptor *descriptors;
+ dma_addr_t descriptors_dma_addr;
+};
+
+struct mite_channel {
+ struct mite_struct *mite;
+ unsigned channel;
+ int dir;
+ int done;
+ struct mite_dma_descriptor_ring *ring;
+};
+
+struct mite_struct {
+ struct mite_struct *next;
+ int used;
+
+ struct pci_dev *pcidev;
+ resource_size_t mite_phys_addr;
+ void *mite_io_addr;
+ resource_size_t daq_phys_addr;
+ void *daq_io_addr;
+
+ struct mite_channel channels[MAX_MITE_DMA_CHANNELS];
+ short channel_allocated[MAX_MITE_DMA_CHANNELS];
+ int num_channels;
+ unsigned fifo_size;
+ spinlock_t lock;
+};
+
+static inline struct mite_dma_descriptor_ring *mite_alloc_ring(struct
+ mite_struct *mite)
+{
+ struct mite_dma_descriptor_ring *ring =
+ kmalloc(sizeof(struct mite_dma_descriptor_ring), GFP_KERNEL);
+ if (ring == NULL)
+ return ring;
+ ring->hw_dev = get_device(&mite->pcidev->dev);
+ if (ring->hw_dev == NULL) {
+ kfree(ring);
+ return NULL;
+ }
+ ring->n_links = 0;
+ ring->descriptors = NULL;
+ ring->descriptors_dma_addr = 0;
+ return ring;
+};
+
+static inline void mite_free_ring(struct mite_dma_descriptor_ring *ring)
+{
+ if (ring) {
+ if (ring->descriptors) {
+ dma_free_coherent(ring->hw_dev,
+ ring->n_links *
+ sizeof(struct mite_dma_descriptor),
+ ring->descriptors, ring->descriptors_dma_addr);
+ }
+ put_device(ring->hw_dev);
+ kfree(ring);
+ }
+};
+
+extern struct mite_struct *mite_devices;
+
+static inline unsigned int mite_irq(struct mite_struct *mite)
+{
+ return mite->pcidev->irq;
+};
+static inline unsigned int mite_device_id(struct mite_struct *mite)
+{
+ return mite->pcidev->device;
+};
+
+void mite_init(void);
+void mite_cleanup(void);
+int mite_setup(struct mite_struct *mite);
+int mite_setup2(struct mite_struct *mite, unsigned use_iodwbsr_1);
+void mite_unsetup(struct mite_struct *mite);
+void mite_list_devices(void);
+struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite,
+ struct mite_dma_descriptor_ring *ring, unsigned min_channel,
+ unsigned max_channel);
+static inline struct mite_channel *mite_request_channel(struct mite_struct
+ *mite, struct mite_dma_descriptor_ring *ring)
+{
+ return mite_request_channel_in_range(mite, ring, 0,
+ mite->num_channels - 1);
+}
+void mite_release_channel(struct mite_channel *mite_chan);
+
+unsigned mite_dma_tcr(struct mite_channel *mite_chan);
+void mite_dma_arm(struct mite_channel *mite_chan);
+void mite_dma_disarm(struct mite_channel *mite_chan);
+int mite_sync_input_dma(struct mite_channel *mite_chan, comedi_async * async);
+int mite_sync_output_dma(struct mite_channel *mite_chan, comedi_async * async);
+u32 mite_bytes_written_to_memory_lb(struct mite_channel *mite_chan);
+u32 mite_bytes_written_to_memory_ub(struct mite_channel *mite_chan);
+u32 mite_bytes_read_from_memory_lb(struct mite_channel *mite_chan);
+u32 mite_bytes_read_from_memory_ub(struct mite_channel *mite_chan);
+u32 mite_bytes_in_transit(struct mite_channel *mite_chan);
+unsigned mite_get_status(struct mite_channel *mite_chan);
+int mite_done(struct mite_channel *mite_chan);
+
+#if 0
+unsigned long mite_ll_from_kvmem(struct mite_struct *mite, comedi_async * async,
+ int len);
+void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan,
+ int dir);
+#endif
+
+void mite_prep_dma(struct mite_channel *mite_chan,
+ unsigned int num_device_bits, unsigned int num_memory_bits);
+int mite_buf_change(struct mite_dma_descriptor_ring *ring,
+ comedi_async * async);
+
+#ifdef DEBUG_MITE
+void mite_print_chsr(unsigned int chsr);
+void mite_dump_regs(struct mite_channel *mite_chan);
+#endif
+
+static inline int CHAN_OFFSET(int channel)
+{
+ return 0x500 + 0x100 * channel;
+};
+
+enum mite_registers {
+ /* The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be
+ written and read back. The bits 0x1f always read as 1.
+ The rest always read as zero. */
+ MITE_UNKNOWN_DMA_BURST_REG = 0x28,
+ MITE_IODWBSR = 0xc0, //IO Device Window Base Size Register
+ MITE_IODWBSR_1 = 0xc4, // IO Device Window Base Size Register 1
+ MITE_IODWCR_1 = 0xf4,
+ MITE_PCI_CONFIG_OFFSET = 0x300,
+ MITE_CSIGR = 0x460 //chip signature
+};
+static inline int MITE_CHOR(int channel) // channel operation
+{
+ return CHAN_OFFSET(channel) + 0x0;
+};
+static inline int MITE_CHCR(int channel) // channel control
+{
+ return CHAN_OFFSET(channel) + 0x4;
+};
+static inline int MITE_TCR(int channel) // transfer count
+{
+ return CHAN_OFFSET(channel) + 0x8;
+};
+static inline int MITE_MCR(int channel) // memory configuration
+{
+ return CHAN_OFFSET(channel) + 0xc;
+};
+static inline int MITE_MAR(int channel) // memory address
+{
+ return CHAN_OFFSET(channel) + 0x10;
+};
+static inline int MITE_DCR(int channel) // device configuration
+{
+ return CHAN_OFFSET(channel) + 0x14;
+};
+static inline int MITE_DAR(int channel) // device address
+{
+ return CHAN_OFFSET(channel) + 0x18;
+};
+static inline int MITE_LKCR(int channel) // link configuration
+{
+ return CHAN_OFFSET(channel) + 0x1c;
+};
+static inline int MITE_LKAR(int channel) // link address
+{
+ return CHAN_OFFSET(channel) + 0x20;
+};
+static inline int MITE_LLKAR(int channel) // see mite section of tnt5002 manual
+{
+ return CHAN_OFFSET(channel) + 0x24;
+};
+static inline int MITE_BAR(int channel) // base address
+{
+ return CHAN_OFFSET(channel) + 0x28;
+};
+static inline int MITE_BCR(int channel) // base count
+{
+ return CHAN_OFFSET(channel) + 0x2c;
+};
+static inline int MITE_SAR(int channel) // ? address
+{
+ return CHAN_OFFSET(channel) + 0x30;
+};
+static inline int MITE_WSCR(int channel) // ?
+{
+ return CHAN_OFFSET(channel) + 0x34;
+};
+static inline int MITE_WSER(int channel) // ?
+{
+ return CHAN_OFFSET(channel) + 0x38;
+};
+static inline int MITE_CHSR(int channel) // channel status
+{
+ return CHAN_OFFSET(channel) + 0x3c;
+};
+static inline int MITE_FCR(int channel) // fifo count
+{
+ return CHAN_OFFSET(channel) + 0x40;
+};
+
+enum MITE_IODWBSR_bits {
+ WENAB = 0x80, // window enable
+};
+
+static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size)
+{
+ unsigned order = 0;
+ while (size >>= 1)
+ ++order;
+ BUG_ON(order < 1);
+ return (order - 1) & 0x1f;
+}
+
+enum MITE_UNKNOWN_DMA_BURST_bits {
+ UNKNOWN_DMA_BURST_ENABLE_BITS = 0x600
+};
+
+static inline int mite_csigr_version(u32 csigr_bits)
+{
+ return csigr_bits & 0xf;
+};
+static inline int mite_csigr_type(u32 csigr_bits)
+{ // original mite = 0, minimite = 1
+ return (csigr_bits >> 4) & 0xf;
+};
+static inline int mite_csigr_mmode(u32 csigr_bits)
+{ // mite mode, minimite = 1
+ return (csigr_bits >> 8) & 0x3;
+};
+static inline int mite_csigr_imode(u32 csigr_bits)
+{ // cpu port interface mode, pci = 0x3
+ return (csigr_bits >> 12) & 0x3;
+};
+static inline int mite_csigr_dmac(u32 csigr_bits)
+{ // number of dma channels
+ return (csigr_bits >> 16) & 0xf;
+};
+static inline int mite_csigr_wpdep(u32 csigr_bits)
+{ // write post fifo depth
+ unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7;
+ if (wpdep_bits == 0)
+ return 0;
+ else
+ return 1 << (wpdep_bits - 1);
+};
+static inline int mite_csigr_wins(u32 csigr_bits)
+{
+ return (csigr_bits >> 24) & 0x1f;
+};
+static inline int mite_csigr_iowins(u32 csigr_bits)
+{ // number of io windows
+ return (csigr_bits >> 29) & 0x7;
+};
+
+enum MITE_MCR_bits {
+ MCRPON = 0,
+};
+
+enum MITE_DCR_bits {
+ DCR_NORMAL = (1 << 29),
+ DCRPON = 0,
+};
+
+enum MITE_CHOR_bits {
+ CHOR_DMARESET = (1 << 31),
+ CHOR_SET_SEND_TC = (1 << 11),
+ CHOR_CLR_SEND_TC = (1 << 10),
+ CHOR_SET_LPAUSE = (1 << 9),
+ CHOR_CLR_LPAUSE = (1 << 8),
+ CHOR_CLRDONE = (1 << 7),
+ CHOR_CLRRB = (1 << 6),
+ CHOR_CLRLC = (1 << 5),
+ CHOR_FRESET = (1 << 4),
+ CHOR_ABORT = (1 << 3), /* stop without emptying fifo */
+ CHOR_STOP = (1 << 2), /* stop after emptying fifo */
+ CHOR_CONT = (1 << 1),
+ CHOR_START = (1 << 0),
+ CHOR_PON = (CHOR_CLR_SEND_TC | CHOR_CLR_LPAUSE),
+};
+
+enum MITE_CHCR_bits {
+ CHCR_SET_DMA_IE = (1 << 31),
+ CHCR_CLR_DMA_IE = (1 << 30),
+ CHCR_SET_LINKP_IE = (1 << 29),
+ CHCR_CLR_LINKP_IE = (1 << 28),
+ CHCR_SET_SAR_IE = (1 << 27),
+ CHCR_CLR_SAR_IE = (1 << 26),
+ CHCR_SET_DONE_IE = (1 << 25),
+ CHCR_CLR_DONE_IE = (1 << 24),
+ CHCR_SET_MRDY_IE = (1 << 23),
+ CHCR_CLR_MRDY_IE = (1 << 22),
+ CHCR_SET_DRDY_IE = (1 << 21),
+ CHCR_CLR_DRDY_IE = (1 << 20),
+ CHCR_SET_LC_IE = (1 << 19),
+ CHCR_CLR_LC_IE = (1 << 18),
+ CHCR_SET_CONT_RB_IE = (1 << 17),
+ CHCR_CLR_CONT_RB_IE = (1 << 16),
+ CHCR_FIFODIS = (1 << 15),
+ CHCR_FIFO_ON = 0,
+ CHCR_BURSTEN = (1 << 14),
+ CHCR_NO_BURSTEN = 0,
+ CHCR_BYTE_SWAP_DEVICE = (1 << 6),
+ CHCR_BYTE_SWAP_MEMORY = (1 << 4),
+ CHCR_DIR = (1 << 3),
+ CHCR_DEV_TO_MEM = CHCR_DIR,
+ CHCR_MEM_TO_DEV = 0,
+ CHCR_NORMAL = (0 << 0),
+ CHCR_CONTINUE = (1 << 0),
+ CHCR_RINGBUFF = (2 << 0),
+ CHCR_LINKSHORT = (4 << 0),
+ CHCR_LINKLONG = (5 << 0),
+ CHCRPON =
+ (CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE |
+ CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE |
+ CHCR_CLR_LC_IE | CHCR_CLR_CONT_RB_IE),
+};
+
+enum ConfigRegister_bits {
+ CR_REQS_MASK = 0x7 << 16,
+ CR_ASEQDONT = 0x0 << 10,
+ CR_ASEQUP = 0x1 << 10,
+ CR_ASEQDOWN = 0x2 << 10,
+ CR_ASEQ_MASK = 0x3 << 10,
+ CR_PSIZE8 = (1 << 8),
+ CR_PSIZE16 = (2 << 8),
+ CR_PSIZE32 = (3 << 8),
+ CR_PORTCPU = (0 << 6),
+ CR_PORTIO = (1 << 6),
+ CR_PORTVXI = (2 << 6),
+ CR_PORTMXI = (3 << 6),
+ CR_AMDEVICE = (1 << 0),
+};
+static inline int CR_REQS(int source)
+{
+ return (source & 0x7) << 16;
+};
+static inline int CR_REQSDRQ(unsigned drq_line)
+{
+ /* This also works on m-series when
+ using channels (drq_line) 4 or 5. */
+ return CR_REQS((drq_line & 0x3) | 0x4);
+}
+static inline int CR_RL(unsigned int retry_limit)
+{
+ int value = 0;
+
+ while (retry_limit) {
+ retry_limit >>= 1;
+ value++;
+ }
+ if (value > 0x7)
+ rt_printk("comedi: bug! retry_limit too large\n");
+ return (value & 0x7) << 21;
+}
+
+enum CHSR_bits {
+ CHSR_INT = (1 << 31),
+ CHSR_LPAUSES = (1 << 29),
+ CHSR_SARS = (1 << 27),
+ CHSR_DONE = (1 << 25),
+ CHSR_MRDY = (1 << 23),
+ CHSR_DRDY = (1 << 21),
+ CHSR_LINKC = (1 << 19),
+ CHSR_CONTS_RB = (1 << 17),
+ CHSR_ERROR = (1 << 15),
+ CHSR_SABORT = (1 << 14),
+ CHSR_HABORT = (1 << 13),
+ CHSR_STOPS = (1 << 12),
+ CHSR_OPERR_mask = (3 << 10),
+ CHSR_OPERR_NOERROR = (0 << 10),
+ CHSR_OPERR_FIFOERROR = (1 << 10),
+ CHSR_OPERR_LINKERROR = (1 << 10), /* ??? */
+ CHSR_XFERR = (1 << 9),
+ CHSR_END = (1 << 8),
+ CHSR_DRQ1 = (1 << 7),
+ CHSR_DRQ0 = (1 << 6),
+ CHSR_LxERR_mask = (3 << 4),
+ CHSR_LBERR = (1 << 4),
+ CHSR_LRERR = (2 << 4),
+ CHSR_LOERR = (3 << 4),
+ CHSR_MxERR_mask = (3 << 2),
+ CHSR_MBERR = (1 << 2),
+ CHSR_MRERR = (2 << 2),
+ CHSR_MOERR = (3 << 2),
+ CHSR_DxERR_mask = (3 << 0),
+ CHSR_DBERR = (1 << 0),
+ CHSR_DRERR = (2 << 0),
+ CHSR_DOERR = (3 << 0),
+};
+
+static inline void mite_dma_reset(struct mite_channel *mite_chan)
+{
+ writel(CHOR_DMARESET | CHOR_FRESET,
+ mite_chan->mite->mite_io_addr + MITE_CHOR(mite_chan->channel));
+};
+
+#endif
diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h
new file mode 100644
index 000000000000..a5a1a6808c5d
--- /dev/null
+++ b/drivers/staging/comedi/drivers/plx9080.h
@@ -0,0 +1,429 @@
+/* plx9080.h
+ *
+ * Copyright (C) 2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * I modified this file from the plx9060.h header for the
+ * wanXL device driver in the linux kernel,
+ * for the register offsets and bit definitions. Made minor modifications,
+ * added plx9080 registers and
+ * stripped out stuff that was specifically for the wanXL driver.
+ * Note: I've only made sure the definitions are correct as far
+ * as I make use of them. There are still various plx9060-isms
+ * left in this header file.
+ *
+ ********************************************************************
+ *
+ * Copyright (C) 1999 RG Studio s.c., http://www.rgstudio.com.pl/
+ * Written by Krzysztof Halasa <khc@rgstudio.com.pl>
+ *
+ * Portions (C) SBE Inc., used by permission.
+ *
+ * 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 __COMEDI_PLX9080_H
+#define __COMEDI_PLX9080_H
+
+// descriptor block used for chained dma transfers
+struct plx_dma_desc {
+ volatile uint32_t pci_start_addr;
+ volatile uint32_t local_start_addr;
+ /* transfer_size is in bytes, only first 23 bits of register are used */
+ volatile uint32_t transfer_size;
+ /* address of next descriptor (quad word aligned), plus some
+ * additional bits (see PLX_DMA0_DESCRIPTOR_REG) */
+ volatile uint32_t next;
+};
+
+/**********************************************************************
+** Register Offsets and Bit Definitions
+**
+** Note: All offsets zero relative. IE. Some standard base address
+** must be added to the Register Number to properly access the register.
+**
+**********************************************************************/
+
+#define PLX_LAS0RNG_REG 0x0000 /* L, Local Addr Space 0 Range Register */
+#define PLX_LAS1RNG_REG 0x00f0 /* L, Local Addr Space 1 Range Register */
+#define LRNG_IO 0x00000001 /* Map to: 1=I/O, 0=Mem */
+#define LRNG_ANY32 0x00000000 /* Locate anywhere in 32 bit */
+#define LRNG_LT1MB 0x00000002 /* Locate in 1st meg */
+#define LRNG_ANY64 0x00000004 /* Locate anywhere in 64 bit */
+#define LRNG_MEM_MASK 0xfffffff0 // bits that specify range for memory io
+#define LRNG_IO_MASK 0xfffffffa // bits that specify range for normal io
+
+#define PLX_LAS0MAP_REG 0x0004 /* L, Local Addr Space 0 Remap Register */
+#define PLX_LAS1MAP_REG 0x00f4 /* L, Local Addr Space 1 Remap Register */
+#define LMAP_EN 0x00000001 /* Enable slave decode */
+#define LMAP_MEM_MASK 0xfffffff0 // bits that specify decode for memory io
+#define LMAP_IO_MASK 0xfffffffa // bits that specify decode bits for normal io
+
+/* Mode/Arbitration Register.
+*/
+#define PLX_MARB_REG 0x8 /* L, Local Arbitration Register */
+#define PLX_DMAARB_REG 0xac
+enum marb_bits {
+ MARB_LLT_MASK = 0x000000ff, /* Local Bus Latency Timer */
+ MARB_LPT_MASK = 0x0000ff00, /* Local Bus Pause Timer */
+ MARB_LTEN = 0x00010000, /* Latency Timer Enable */
+ MARB_LPEN = 0x00020000, /* Pause Timer Enable */
+ MARB_BREQ = 0x00040000, /* Local Bus BREQ Enable */
+ MARB_DMA_PRIORITY_MASK = 0x00180000,
+ MARB_LBDS_GIVE_UP_BUS_MODE = 0x00200000, /* local bus direct slave give up bus mode */
+ MARB_DS_LLOCK_ENABLE = 0x00400000, /* direct slave LLOCKo# enable */
+ MARB_PCI_REQUEST_MODE = 0x00800000,
+ MARB_PCIv21_MODE = 0x01000000, /* pci specification v2.1 mode */
+ MARB_PCI_READ_NO_WRITE_MODE = 0x02000000,
+ MARB_PCI_READ_WITH_WRITE_FLUSH_MODE = 0x04000000,
+ MARB_GATE_TIMER_WITH_BREQ = 0x08000000, /* gate local bus latency timer with BREQ */
+ MARB_PCI_READ_NO_FLUSH_MODE = 0x10000000,
+ MARB_USE_SUBSYSTEM_IDS = 0x20000000,
+};
+
+#define PLX_BIGEND_REG 0xc
+enum bigend_bits {
+ BIGEND_CONFIG = 0x1, /* use big endian ordering for configuration register accesses */
+ BIGEND_DIRECT_MASTER = 0x2,
+ BIGEND_DIRECT_SLAVE_LOCAL0 = 0x4,
+ BIGEND_ROM = 0x8,
+ BIGEND_BYTE_LANE = 0x10, /* use byte lane consisting of most significant bits instead of least significant */
+ BIGEND_DIRECT_SLAVE_LOCAL1 = 0x20,
+ BIGEND_DMA1 = 0x40,
+ BIGEND_DMA0 = 0x80,
+};
+
+/* Note: The Expansion ROM stuff is only relevant to the PC environment.
+** This expansion ROM code is executed by the host CPU at boot time.
+** For this reason no bit definitions are provided here.
+*/
+#define PLX_ROMRNG_REG 0x0010 /* L, Expn ROM Space Range Register */
+#define PLX_ROMMAP_REG 0x0014 /* L, Local Addr Space Range Register */
+
+#define PLX_REGION0_REG 0x0018 /* L, Local Bus Region 0 Descriptor */
+#define RGN_WIDTH 0x00000002 /* Local bus width bits */
+#define RGN_8BITS 0x00000000 /* 08 bit Local Bus */
+#define RGN_16BITS 0x00000001 /* 16 bit Local Bus */
+#define RGN_32BITS 0x00000002 /* 32 bit Local Bus */
+#define RGN_MWS 0x0000003C /* Memory Access Wait States */
+#define RGN_0MWS 0x00000000
+#define RGN_1MWS 0x00000004
+#define RGN_2MWS 0x00000008
+#define RGN_3MWS 0x0000000C
+#define RGN_4MWS 0x00000010
+#define RGN_6MWS 0x00000018
+#define RGN_8MWS 0x00000020
+#define RGN_MRE 0x00000040 /* Memory Space Ready Input Enable */
+#define RGN_MBE 0x00000080 /* Memory Space Bterm Input Enable */
+#define RGN_READ_PREFETCH_DISABLE 0x00000100
+#define RGN_ROM_PREFETCH_DISABLE 0x00000200
+#define RGN_READ_PREFETCH_COUNT_ENABLE 0x00000400
+#define RGN_RWS 0x003C0000 /* Expn ROM Wait States */
+#define RGN_RRE 0x00400000 /* ROM Space Ready Input Enable */
+#define RGN_RBE 0x00800000 /* ROM Space Bterm Input Enable */
+#define RGN_MBEN 0x01000000 /* Memory Space Burst Enable */
+#define RGN_RBEN 0x04000000 /* ROM Space Burst Enable */
+#define RGN_THROT 0x08000000 /* De-assert TRDY when FIFO full */
+#define RGN_TRD 0xF0000000 /* Target Ready Delay /8 */
+
+#define PLX_REGION1_REG 0x00f8 /* L, Local Bus Region 1 Descriptor */
+
+#define PLX_DMRNG_REG 0x001C /* L, Direct Master Range Register */
+
+#define PLX_LBAPMEM_REG 0x0020 /* L, Lcl Base Addr for PCI mem space */
+
+#define PLX_LBAPIO_REG 0x0024 /* L, Lcl Base Addr for PCI I/O space */
+
+#define PLX_DMMAP_REG 0x0028 /* L, Direct Master Remap Register */
+#define DMM_MAE 0x00000001 /* Direct Mstr Memory Acc Enable */
+#define DMM_IAE 0x00000002 /* Direct Mstr I/O Acc Enable */
+#define DMM_LCK 0x00000004 /* LOCK Input Enable */
+#define DMM_PF4 0x00000008 /* Prefetch 4 Mode Enable */
+#define DMM_THROT 0x00000010 /* Assert IRDY when read FIFO full */
+#define DMM_PAF0 0x00000000 /* Programmable Almost fill level */
+#define DMM_PAF1 0x00000020 /* Programmable Almost fill level */
+#define DMM_PAF2 0x00000040 /* Programmable Almost fill level */
+#define DMM_PAF3 0x00000060 /* Programmable Almost fill level */
+#define DMM_PAF4 0x00000080 /* Programmable Almost fill level */
+#define DMM_PAF5 0x000000A0 /* Programmable Almost fill level */
+#define DMM_PAF6 0x000000C0 /* Programmable Almost fill level */
+#define DMM_PAF7 0x000000D0 /* Programmable Almost fill level */
+#define DMM_MAP 0xFFFF0000 /* Remap Address Bits */
+
+#define PLX_CAR_REG 0x002C /* L, Configuration Address Register */
+#define CAR_CT0 0x00000000 /* Config Type 0 */
+#define CAR_CT1 0x00000001 /* Config Type 1 */
+#define CAR_REG 0x000000FC /* Register Number Bits */
+#define CAR_FUN 0x00000700 /* Function Number Bits */
+#define CAR_DEV 0x0000F800 /* Device Number Bits */
+#define CAR_BUS 0x00FF0000 /* Bus Number Bits */
+#define CAR_CFG 0x80000000 /* Config Spc Access Enable */
+
+#define PLX_DBR_IN_REG 0x0060 /* L, PCI to Local Doorbell Register */
+
+#define PLX_DBR_OUT_REG 0x0064 /* L, Local to PCI Doorbell Register */
+
+#define PLX_INTRCS_REG 0x0068 /* L, Interrupt Control/Status Reg */
+#define ICS_AERR 0x00000001 /* Assert LSERR on ABORT */
+#define ICS_PERR 0x00000002 /* Assert LSERR on Parity Error */
+#define ICS_SERR 0x00000004 /* Generate PCI SERR# */
+#define ICS_MBIE 0x00000008 // mailbox interrupt enable
+#define ICS_PIE 0x00000100 /* PCI Interrupt Enable */
+#define ICS_PDIE 0x00000200 /* PCI Doorbell Interrupt Enable */
+#define ICS_PAIE 0x00000400 /* PCI Abort Interrupt Enable */
+#define ICS_PLIE 0x00000800 /* PCI Local Int Enable */
+#define ICS_RAE 0x00001000 /* Retry Abort Enable */
+#define ICS_PDIA 0x00002000 /* PCI Doorbell Interrupt Active */
+#define ICS_PAIA 0x00004000 /* PCI Abort Interrupt Active */
+#define ICS_LIA 0x00008000 /* Local Interrupt Active */
+#define ICS_LIE 0x00010000 /* Local Interrupt Enable */
+#define ICS_LDIE 0x00020000 /* Local Doorbell Int Enable */
+#define ICS_DMA0_E 0x00040000 /* DMA #0 Interrupt Enable */
+#define ICS_DMA1_E 0x00080000 /* DMA #1 Interrupt Enable */
+#define ICS_LDIA 0x00100000 /* Local Doorbell Int Active */
+#define ICS_DMA0_A 0x00200000 /* DMA #0 Interrupt Active */
+#define ICS_DMA1_A 0x00400000 /* DMA #1 Interrupt Active */
+#define ICS_BIA 0x00800000 /* BIST Interrupt Active */
+#define ICS_TA_DM 0x01000000 /* Target Abort - Direct Master */
+#define ICS_TA_DMA0 0x02000000 /* Target Abort - DMA #0 */
+#define ICS_TA_DMA1 0x04000000 /* Target Abort - DMA #1 */
+#define ICS_TA_RA 0x08000000 /* Target Abort - Retry Timeout */
+#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) // mailbox x is active
+
+#define PLX_CONTROL_REG 0x006C /* L, EEPROM Cntl & PCI Cmd Codes */
+#define CTL_RDMA 0x0000000E /* DMA Read Command */
+#define CTL_WDMA 0x00000070 /* DMA Write Command */
+#define CTL_RMEM 0x00000600 /* Memory Read Command */
+#define CTL_WMEM 0x00007000 /* Memory Write Command */
+#define CTL_USERO 0x00010000 /* USERO output pin control bit */
+#define CTL_USERI 0x00020000 /* USERI input pin bit */
+#define CTL_EE_CLK 0x01000000 /* EEPROM Clock line */
+#define CTL_EE_CS 0x02000000 /* EEPROM Chip Select */
+#define CTL_EE_W 0x04000000 /* EEPROM Write bit */
+#define CTL_EE_R 0x08000000 /* EEPROM Read bit */
+#define CTL_EECHK 0x10000000 /* EEPROM Present bit */
+#define CTL_EERLD 0x20000000 /* EEPROM Reload Register */
+#define CTL_RESET 0x40000000 /* !! Adapter Reset !! */
+#define CTL_READY 0x80000000 /* Local Init Done */
+
+#define PLX_ID_REG 0x70 // hard-coded plx vendor and device ids
+
+#define PLX_REVISION_REG 0x74 // silicon revision
+
+#define PLX_DMA0_MODE_REG 0x80 // dma channel 0 mode register
+#define PLX_DMA1_MODE_REG 0x94 // dma channel 0 mode register
+#define PLX_LOCAL_BUS_16_WIDE_BITS 0x1
+#define PLX_LOCAL_BUS_32_WIDE_BITS 0x3
+#define PLX_LOCAL_BUS_WIDTH_MASK 0x3
+#define PLX_DMA_EN_READYIN_BIT 0x40 // enable ready in input
+#define PLX_EN_BTERM_BIT 0x80 // enable BTERM# input
+#define PLX_DMA_LOCAL_BURST_EN_BIT 0x100 // enable local burst mode
+#define PLX_EN_CHAIN_BIT 0x200 // enables chaining
+#define PLX_EN_DMA_DONE_INTR_BIT 0x400 // enables interrupt on dma done
+#define PLX_LOCAL_ADDR_CONST_BIT 0x800 // hold local address constant (don't increment)
+#define PLX_DEMAND_MODE_BIT 0x1000 // enables demand-mode for dma transfer
+#define PLX_EOT_ENABLE_BIT 0x4000
+#define PLX_STOP_MODE_BIT 0x8000
+#define PLX_DMA_INTR_PCI_BIT 0x20000 // routes dma interrupt to pci bus (instead of local bus)
+
+#define PLX_DMA0_PCI_ADDRESS_REG 0x84 // pci address that dma transfers start at
+#define PLX_DMA1_PCI_ADDRESS_REG 0x98
+
+#define PLX_DMA0_LOCAL_ADDRESS_REG 0x88 // local address that dma transfers start at
+#define PLX_DMA1_LOCAL_ADDRESS_REG 0x9c
+
+#define PLX_DMA0_TRANSFER_SIZE_REG 0x8c // number of bytes to transfer (first 23 bits)
+#define PLX_DMA1_TRANSFER_SIZE_REG 0xa0
+
+#define PLX_DMA0_DESCRIPTOR_REG 0x90 // descriptor pointer register
+#define PLX_DMA1_DESCRIPTOR_REG 0xa4
+#define PLX_DESC_IN_PCI_BIT 0x1 // descriptor is located in pci space (not local space)
+#define PLX_END_OF_CHAIN_BIT 0x2 // end of chain bit
+#define PLX_INTR_TERM_COUNT 0x4 // interrupt when this descriptor's transfer is finished
+#define PLX_XFER_LOCAL_TO_PCI 0x8 // transfer from local to pci bus (not pci to local)
+
+#define PLX_DMA0_CS_REG 0xa8 // command status register
+#define PLX_DMA1_CS_REG 0xa9
+#define PLX_DMA_EN_BIT 0x1 // enable dma channel
+#define PLX_DMA_START_BIT 0x2 // start dma transfer
+#define PLX_DMA_ABORT_BIT 0x4 // abort dma transfer
+#define PLX_CLEAR_DMA_INTR_BIT 0x8 // clear dma interrupt
+#define PLX_DMA_DONE_BIT 0x10 // transfer done status bit
+
+#define PLX_DMA0_THRESHOLD_REG 0xb0 // command status register
+
+/*
+ * Accesses near the end of memory can cause the PLX chip
+ * to pre-fetch data off of end-of-ram. Limit the size of
+ * memory so host-side accesses cannot occur.
+ */
+
+#define PLX_PREFETCH 32
+
+/*
+ * The PCI Interface, via the PCI-9060 Chip, has up to eight (8) Mailbox
+ * Registers. The PUTS (Power-Up Test Suite) handles the board-side
+ * interface/interaction using the first 4 registers. Specifications for
+ * the use of the full PUTS' command and status interface is contained
+ * within a separate SBE PUTS Manual. The Host-Side Device Driver only
+ * uses a subset of the full PUTS interface.
+ */
+
+/*****************************************/
+/*** MAILBOX #(-1) - MEM ACCESS STS ***/
+/*****************************************/
+
+#define MBX_STS_VALID 0x57584744 /* 'WXGD' */
+#define MBX_STS_DILAV 0x44475857 /* swapped = 'DGXW' */
+
+/*****************************************/
+/*** MAILBOX #0 - PUTS STATUS ***/
+/*****************************************/
+
+#define MBX_STS_MASK 0x000000ff /* PUTS Status Register bits */
+#define MBX_STS_TMASK 0x0000000f /* register bits for TEST number */
+
+#define MBX_STS_PCIRESET 0x00000100 /* Host issued PCI reset request */
+#define MBX_STS_BUSY 0x00000080 /* PUTS is in progress */
+#define MBX_STS_ERROR 0x00000040 /* PUTS has failed */
+#define MBX_STS_RESERVED 0x000000c0 /* Undefined -> status in transition.
+ We are in process of changing
+ bits; we SET Error bit before
+ RESET of Busy bit */
+
+#define MBX_RESERVED_5 0x00000020 /* FYI: reserved/unused bit */
+#define MBX_RESERVED_4 0x00000010 /* FYI: reserved/unused bit */
+
+/******************************************/
+/*** MAILBOX #1 - PUTS COMMANDS ***/
+/******************************************/
+
+/*
+ * Any attempt to execute an unimplement command results in the PUTS
+ * interface executing a NOOP and continuing as if the offending command
+ * completed normally. Note: this supplies a simple method to interrogate
+ * mailbox command processing functionality.
+ */
+
+#define MBX_CMD_MASK 0xffff0000 /* PUTS Command Register bits */
+
+#define MBX_CMD_ABORTJ 0x85000000 /* abort and jump */
+#define MBX_CMD_RESETP 0x86000000 /* reset and pause at start */
+#define MBX_CMD_PAUSE 0x87000000 /* pause immediately */
+#define MBX_CMD_PAUSEC 0x88000000 /* pause on completion */
+#define MBX_CMD_RESUME 0x89000000 /* resume operation */
+#define MBX_CMD_STEP 0x8a000000 /* single step tests */
+
+#define MBX_CMD_BSWAP 0x8c000000 /* identify byte swap scheme */
+#define MBX_CMD_BSWAP_0 0x8c000000 /* use scheme 0 */
+#define MBX_CMD_BSWAP_1 0x8c000001 /* use scheme 1 */
+
+#define MBX_CMD_SETHMS 0x8d000000 /* setup host memory access window
+ size */
+#define MBX_CMD_SETHBA 0x8e000000 /* setup host memory access base
+ address */
+#define MBX_CMD_MGO 0x8f000000 /* perform memory setup and continue
+ (IE. Done) */
+#define MBX_CMD_NOOP 0xFF000000 /* dummy, illegal command */
+
+/*****************************************/
+/*** MAILBOX #2 - MEMORY SIZE ***/
+/*****************************************/
+
+#define MBX_MEMSZ_MASK 0xffff0000 /* PUTS Memory Size Register bits */
+
+#define MBX_MEMSZ_128KB 0x00020000 /* 128 kilobyte board */
+#define MBX_MEMSZ_256KB 0x00040000 /* 256 kilobyte board */
+#define MBX_MEMSZ_512KB 0x00080000 /* 512 kilobyte board */
+#define MBX_MEMSZ_1MB 0x00100000 /* 1 megabyte board */
+#define MBX_MEMSZ_2MB 0x00200000 /* 2 megabyte board */
+#define MBX_MEMSZ_4MB 0x00400000 /* 4 megabyte board */
+#define MBX_MEMSZ_8MB 0x00800000 /* 8 megabyte board */
+#define MBX_MEMSZ_16MB 0x01000000 /* 16 megabyte board */
+
+/***************************************/
+/*** MAILBOX #2 - BOARD TYPE ***/
+/***************************************/
+
+#define MBX_BTYPE_MASK 0x0000ffff /* PUTS Board Type Register */
+#define MBX_BTYPE_FAMILY_MASK 0x0000ff00 /* PUTS Board Family Register */
+#define MBX_BTYPE_SUBTYPE_MASK 0x000000ff /* PUTS Board Subtype */
+
+#define MBX_BTYPE_PLX9060 0x00000100 /* PLX family type */
+#define MBX_BTYPE_PLX9080 0x00000300 /* PLX wanXL100s family type */
+
+#define MBX_BTYPE_WANXL_4 0x00000104 /* wanXL400, 4-port */
+#define MBX_BTYPE_WANXL_2 0x00000102 /* wanXL200, 2-port */
+#define MBX_BTYPE_WANXL_1s 0x00000301 /* wanXL100s, 1-port */
+#define MBX_BTYPE_WANXL_1t 0x00000401 /* wanXL100T1, 1-port */
+
+/*****************************************/
+/*** MAILBOX #3 - SHMQ MAILBOX ***/
+/*****************************************/
+
+#define MBX_SMBX_MASK 0x000000ff /* PUTS SHMQ Mailbox bits */
+
+/***************************************/
+/*** GENERIC HOST-SIDE DRIVER ***/
+/***************************************/
+
+#define MBX_ERR 0
+#define MBX_OK 1
+
+/* mailbox check routine - type of testing */
+#define MBXCHK_STS 0x00 /* check for PUTS status */
+#define MBXCHK_NOWAIT 0x01 /* dont care about PUTS status */
+
+/* system allocates this many bytes for address mapping mailbox space */
+#define MBX_ADDR_SPACE_360 0x80 /* wanXL100s/200/400 */
+#define MBX_ADDR_MASK_360 (MBX_ADDR_SPACE_360-1)
+
+static inline int plx9080_abort_dma(void *iobase, unsigned int channel)
+{
+ void *dma_cs_addr;
+ uint8_t dma_status;
+ const int timeout = 10000;
+ unsigned int i;
+
+ if (channel)
+ dma_cs_addr = iobase + PLX_DMA1_CS_REG;
+ else
+ dma_cs_addr = iobase + PLX_DMA0_CS_REG;
+
+ // abort dma transfer if necessary
+ dma_status = readb(dma_cs_addr);
+ if ((dma_status & PLX_DMA_EN_BIT) == 0) {
+ return 0;
+ }
+ // wait to make sure done bit is zero
+ for (i = 0; (dma_status & PLX_DMA_DONE_BIT) && i < timeout; i++) {
+ comedi_udelay(1);
+ dma_status = readb(dma_cs_addr);
+ }
+ if (i == timeout) {
+ rt_printk
+ ("plx9080: cancel() timed out waiting for dma %i done clear\n",
+ channel);
+ return -ETIMEDOUT;
+ }
+ // disable and abort channel
+ writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
+ // wait for dma done bit
+ dma_status = readb(dma_cs_addr);
+ for (i = 0; (dma_status & PLX_DMA_DONE_BIT) == 0 && i < timeout; i++) {
+ comedi_udelay(1);
+ dma_status = readb(dma_cs_addr);
+ }
+ if (i == timeout) {
+ rt_printk
+ ("plx9080: cancel() timed out waiting for dma %i done set\n",
+ channel);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+#endif /* __COMEDI_PLX9080_H */
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
new file mode 100644
index 000000000000..65d5242a2585
--- /dev/null
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -0,0 +1,2283 @@
+/*
+ comedi/drivers/rtd520.c
+ Comedi driver for Real Time Devices (RTD) PCI4520/DM7520
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2001 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+Driver: rtd520
+Description: Real Time Devices PCI4520/DM7520
+Author: Dan Christian
+Devices: [Real Time Devices] DM7520HR-1 (rtd520), DM7520HR-8,
+ PCI4520, PCI4520-8
+Status: Works. Only tested on DM7520-8. Not SMP safe.
+
+Configuration options:
+ [0] - PCI bus of device (optional)
+ If bus/slot is not specified, the first available PCI
+ device will be used.
+ [1] - PCI slot of device (optional)
+*/
+/*
+ Created by Dan Christian, NASA Ames Research Center.
+
+ The PCI4520 is a PCI card. The DM7520 is a PC/104-plus card.
+ Both have:
+ 8/16 12 bit ADC with FIFO and channel gain table
+ 8 bits high speed digital out (for external MUX) (or 8 in or 8 out)
+ 8 bits high speed digital in with FIFO and interrupt on change (or 8 IO)
+ 2 12 bit DACs with FIFOs
+ 2 bits output
+ 2 bits input
+ bus mastering DMA
+ timers: ADC sample, pacer, burst, about, delay, DA1, DA2
+ sample counter
+ 3 user timer/counters (8254)
+ external interrupt
+
+ The DM7520 has slightly fewer features (fewer gain steps).
+
+ These boards can support external multiplexors and multi-board
+ synchronization, but this driver doesn't support that.
+
+ Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm
+ Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf
+ Example source: http://www.rtdusa.com/examples/dm/dm7520.zip
+ Call them and ask for the register level manual.
+ PCI chip: http://www.plxtech.com/products/toolbox/9080.htm
+
+ Notes:
+ This board is memory mapped. There is some IO stuff, but it isn't needed.
+
+ I use a pretty loose naming style within the driver (rtd_blah).
+ All externally visible names should be rtd520_blah.
+ I use camelCase for structures (and inside them).
+ I may also use upper CamelCase for function names (old habit).
+
+ This board is somewhat related to the RTD PCI4400 board.
+
+ I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and
+ das1800, since they have the best documented code. Driver
+ cb_pcidas64.c uses the same DMA controller.
+
+ As far as I can tell, the About interrupt doesnt work if Sample is
+ also enabled. It turns out that About really isn't needed, since
+ we always count down samples read.
+
+ There was some timer/counter code, but it didn't follow the right API.
+
+*/
+
+/*
+ driver status:
+
+ Analog-In supports instruction and command mode.
+
+ With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2
+ (single channel, 64K read buffer). I get random system lockups when
+ using DMA with ALI-15xx based systems. I haven't been able to test
+ any other chipsets. The lockups happen soon after the start of an
+ acquistion, not in the middle of a long run.
+
+ Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2
+ (with a 256K read buffer).
+
+ Digital-IO and Analog-Out only support instruction mode.
+
+*/
+
+#include <linux/delay.h>
+
+#include "../comedidev.h"
+#include "comedi_pci.h"
+
+#define DRV_NAME "rtd520"
+
+/*======================================================================
+ Driver specific stuff (tunable)
+======================================================================*/
+/* Enable this to test the new DMA support. You may get hard lock ups */
+/*#define USE_DMA*/
+
+/* We really only need 2 buffers. More than that means being much
+ smarter about knowing which ones are full. */
+#define DMA_CHAIN_COUNT 2 /* max DMA segments/buffers in a ring (min 2) */
+
+/* Target period for periodic transfers. This sets the user read latency. */
+/* Note: There are certain rates where we give this up and transfer 1/2 FIFO */
+/* If this is too low, efficiency is poor */
+#define TRANS_TARGET_PERIOD 10000000 /* 10 ms (in nanoseconds) */
+
+/* Set a practical limit on how long a list to support (affects memory use) */
+/* The board support a channel list up to the FIFO length (1K or 8K) */
+#define RTD_MAX_CHANLIST 128 /* max channel list that we allow */
+
+/* tuning for ai/ao instruction done polling */
+#ifdef FAST_SPIN
+#define WAIT_QUIETLY /* as nothing, spin on done bit */
+#define RTD_ADC_TIMEOUT 66000 /* 2 msec at 33mhz bus rate */
+#define RTD_DAC_TIMEOUT 66000
+#define RTD_DMA_TIMEOUT 33000 /* 1 msec */
+#else
+/* by delaying, power and electrical noise are reduced somewhat */
+#define WAIT_QUIETLY comedi_udelay (1)
+#define RTD_ADC_TIMEOUT 2000 /* in usec */
+#define RTD_DAC_TIMEOUT 2000 /* in usec */
+#define RTD_DMA_TIMEOUT 1000 /* in usec */
+#endif
+
+/*======================================================================
+ Board specific stuff
+======================================================================*/
+
+/* registers */
+#define PCI_VENDOR_ID_RTD 0x1435
+/*
+ The board has three memory windows: las0, las1, and lcfg (the PCI chip)
+ Las1 has the data and can be burst DMAed 32bits at a time.
+*/
+#define LCFG_PCIINDEX 0
+/* PCI region 1 is a 256 byte IO space mapping. Use??? */
+#define LAS0_PCIINDEX 2 /* PCI memory resources */
+#define LAS1_PCIINDEX 3
+#define LCFG_PCISIZE 0x100
+#define LAS0_PCISIZE 0x200
+#define LAS1_PCISIZE 0x10
+
+#define RTD_CLOCK_RATE 8000000 /* 8Mhz onboard clock */
+#define RTD_CLOCK_BASE 125 /* clock period in ns */
+
+/* Note: these speed are slower than the spec, but fit the counter resolution*/
+#define RTD_MAX_SPEED 1625 /* when sampling, in nanoseconds */
+/* max speed if we don't have to wait for settling */
+#define RTD_MAX_SPEED_1 875 /* if single channel, in nanoseconds */
+
+#define RTD_MIN_SPEED 2097151875 /* (24bit counter) in nanoseconds */
+/* min speed when only 1 channel (no burst counter) */
+#define RTD_MIN_SPEED_1 5000000 /* 200Hz, in nanoseconds */
+
+#include "rtd520.h"
+#include "plx9080.h"
+
+/* Setup continuous ring of 1/2 FIFO transfers. See RTD manual p91 */
+#define DMA_MODE_BITS (\
+ PLX_LOCAL_BUS_16_WIDE_BITS \
+ | PLX_DMA_EN_READYIN_BIT \
+ | PLX_DMA_LOCAL_BURST_EN_BIT \
+ | PLX_EN_CHAIN_BIT \
+ | PLX_DMA_INTR_PCI_BIT \
+ | PLX_LOCAL_ADDR_CONST_BIT \
+ | PLX_DEMAND_MODE_BIT)
+
+#define DMA_TRANSFER_BITS (\
+/* descriptors in PCI memory*/ PLX_DESC_IN_PCI_BIT \
+/* interrupt at end of block */ | PLX_INTR_TERM_COUNT \
+/* from board to PCI */ | PLX_XFER_LOCAL_TO_PCI)
+
+/*======================================================================
+ Comedi specific stuff
+======================================================================*/
+
+/*
+ The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128)
+*/
+static const comedi_lrange rtd_ai_7520_range = { 18, {
+ /* +-5V input range gain steps */
+ BIP_RANGE(5.0),
+ BIP_RANGE(5.0 / 2),
+ BIP_RANGE(5.0 / 4),
+ BIP_RANGE(5.0 / 8),
+ BIP_RANGE(5.0 / 16),
+ BIP_RANGE(5.0 / 32),
+ /* +-10V input range gain steps */
+ BIP_RANGE(10.0),
+ BIP_RANGE(10.0 / 2),
+ BIP_RANGE(10.0 / 4),
+ BIP_RANGE(10.0 / 8),
+ BIP_RANGE(10.0 / 16),
+ BIP_RANGE(10.0 / 32),
+ /* +10V input range gain steps */
+ UNI_RANGE(10.0),
+ UNI_RANGE(10.0 / 2),
+ UNI_RANGE(10.0 / 4),
+ UNI_RANGE(10.0 / 8),
+ UNI_RANGE(10.0 / 16),
+ UNI_RANGE(10.0 / 32),
+
+ }
+};
+
+/* PCI4520 has two more gains (6 more entries) */
+static const comedi_lrange rtd_ai_4520_range = { 24, {
+ /* +-5V input range gain steps */
+ BIP_RANGE(5.0),
+ BIP_RANGE(5.0 / 2),
+ BIP_RANGE(5.0 / 4),
+ BIP_RANGE(5.0 / 8),
+ BIP_RANGE(5.0 / 16),
+ BIP_RANGE(5.0 / 32),
+ BIP_RANGE(5.0 / 64),
+ BIP_RANGE(5.0 / 128),
+ /* +-10V input range gain steps */
+ BIP_RANGE(10.0),
+ BIP_RANGE(10.0 / 2),
+ BIP_RANGE(10.0 / 4),
+ BIP_RANGE(10.0 / 8),
+ BIP_RANGE(10.0 / 16),
+ BIP_RANGE(10.0 / 32),
+ BIP_RANGE(10.0 / 64),
+ BIP_RANGE(10.0 / 128),
+ /* +10V input range gain steps */
+ UNI_RANGE(10.0),
+ UNI_RANGE(10.0 / 2),
+ UNI_RANGE(10.0 / 4),
+ UNI_RANGE(10.0 / 8),
+ UNI_RANGE(10.0 / 16),
+ UNI_RANGE(10.0 / 32),
+ UNI_RANGE(10.0 / 64),
+ UNI_RANGE(10.0 / 128),
+ }
+};
+
+/* Table order matches range values */
+static const comedi_lrange rtd_ao_range = { 4, {
+ RANGE(0, 5),
+ RANGE(0, 10),
+ RANGE(-5, 5),
+ RANGE(-10, 10),
+ }
+};
+
+/*
+ Board descriptions
+ */
+typedef struct rtdBoard_struct {
+ const char *name; /* must be first */
+ int device_id;
+ int aiChans;
+ int aiBits;
+ int aiMaxGain;
+ int range10Start; /* start of +-10V range */
+ int rangeUniStart; /* start of +10V range */
+} rtdBoard;
+
+static const rtdBoard rtd520Boards[] = {
+ {
+ name: "DM7520",
+ device_id:0x7520,
+ aiChans: 16,
+ aiBits: 12,
+ aiMaxGain:32,
+ range10Start:6,
+ rangeUniStart:12,
+ },
+ {
+ name: "PCI4520",
+ device_id:0x4520,
+ aiChans: 16,
+ aiBits: 12,
+ aiMaxGain:128,
+ range10Start:8,
+ rangeUniStart:16,
+ },
+};
+
+static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
+ {PCI_VENDOR_ID_RTD, 0x7520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_RTD, 0x4520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
+
+/*
+ * Useful for shorthand access to the particular board structure
+ */
+#define thisboard ((const rtdBoard *)dev->board_ptr)
+
+/*
+ This structure is for data unique to this hardware driver.
+ This is also unique for each board in the system.
+*/
+typedef struct {
+ /* memory mapped board structures */
+ void *las0;
+ void *las1;
+ void *lcfg;
+
+ unsigned long intCount; /* interrupt count */
+ long aiCount; /* total transfer size (samples) */
+ int transCount; /* # to tranfer data. 0->1/2FIFO */
+ int flags; /* flag event modes */
+
+ /* PCI device info */
+ struct pci_dev *pci_dev;
+ int got_regions; /* non-zero if PCI regions owned */
+
+ /* channel list info */
+ /* chanBipolar tracks whether a channel is bipolar (and needs +2048) */
+ unsigned char chanBipolar[RTD_MAX_CHANLIST / 8]; /* bit array */
+
+ /* read back data */
+ lsampl_t aoValue[2]; /* Used for AO read back */
+
+ /* timer gate (when enabled) */
+ u8 utcGate[4]; /* 1 extra allows simple range check */
+
+ /* shadow registers affect other registers, but cant be read back */
+ /* The macros below update these on writes */
+ u16 intMask; /* interrupt mask */
+ u16 intClearMask; /* interrupt clear mask */
+ u8 utcCtrl[4]; /* crtl mode for 3 utc + read back */
+ u8 dioStatus; /* could be read back (dio0Ctrl) */
+#ifdef USE_DMA
+ /* Always DMA 1/2 FIFO. Buffer (dmaBuff?) is (at least) twice that size.
+ After transferring, interrupt processes 1/2 FIFO and passes to comedi */
+ s16 dma0Offset; /* current processing offset (0, 1/2) */
+ uint16_t *dma0Buff[DMA_CHAIN_COUNT]; /* DMA buffers (for ADC) */
+ dma_addr_t dma0BuffPhysAddr[DMA_CHAIN_COUNT]; /* physical addresses */
+ struct plx_dma_desc *dma0Chain; /* DMA descriptor ring for dmaBuff */
+ dma_addr_t dma0ChainPhysAddr; /* physical addresses */
+ /* shadow registers */
+ u8 dma0Control;
+ u8 dma1Control;
+#endif /* USE_DMA */
+ unsigned fifoLen;
+} rtdPrivate;
+
+/* bit defines for "flags" */
+#define SEND_EOS 0x01 /* send End Of Scan events */
+#define DMA0_ACTIVE 0x02 /* DMA0 is active */
+#define DMA1_ACTIVE 0x04 /* DMA1 is active */
+
+/* Macros for accessing channel list bit array */
+#define CHAN_ARRAY_TEST(array,index) \
+ (((array)[(index)/8] >> ((index) & 0x7)) & 0x1)
+#define CHAN_ARRAY_SET(array,index) \
+ (((array)[(index)/8] |= 1 << ((index) & 0x7)))
+#define CHAN_ARRAY_CLEAR(array,index) \
+ (((array)[(index)/8] &= ~(1 << ((index) & 0x7))))
+
+/*
+ * most drivers define the following macro to make it easy to
+ * access the private structure.
+ */
+#define devpriv ((rtdPrivate *)dev->private)
+
+/* Macros to access registers */
+
+/* Reset board */
+#define RtdResetBoard(dev) \
+ writel (0, devpriv->las0+LAS0_BOARD_RESET)
+
+/* Reset channel gain table read pointer */
+#define RtdResetCGT(dev) \
+ writel (0, devpriv->las0+LAS0_CGT_RESET)
+
+/* Reset channel gain table read and write pointers */
+#define RtdClearCGT(dev) \
+ writel (0, devpriv->las0+LAS0_CGT_CLEAR)
+
+/* Reset channel gain table read and write pointers */
+#define RtdEnableCGT(dev,v) \
+ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)
+
+/* Write channel gain table entry */
+#define RtdWriteCGTable(dev,v) \
+ writel (v, devpriv->las0+LAS0_CGT_WRITE)
+
+/* Write Channel Gain Latch */
+#define RtdWriteCGLatch(dev,v) \
+ writel (v, devpriv->las0+LAS0_CGL_WRITE)
+
+/* Reset ADC FIFO */
+#define RtdAdcClearFifo(dev) \
+ writel (0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)
+
+/* Set ADC start conversion source select (write only) */
+#define RtdAdcConversionSource(dev,v) \
+ writel (v, devpriv->las0+LAS0_ADC_CONVERSION)
+
+/* Set burst start source select (write only) */
+#define RtdBurstStartSource(dev,v) \
+ writel (v, devpriv->las0+LAS0_BURST_START)
+
+/* Set Pacer start source select (write only) */
+#define RtdPacerStartSource(dev,v) \
+ writel (v, devpriv->las0+LAS0_PACER_START)
+
+/* Set Pacer stop source select (write only) */
+#define RtdPacerStopSource(dev,v) \
+ writel (v, devpriv->las0+LAS0_PACER_STOP)
+
+/* Set Pacer clock source select (write only) 0=external 1=internal */
+#define RtdPacerClockSource(dev,v) \
+ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)
+
+/* Set sample counter source select (write only) */
+#define RtdAdcSampleCounterSource(dev,v) \
+ writel (v, devpriv->las0+LAS0_ADC_SCNT_SRC)
+
+/* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */
+#define RtdPacerTriggerMode(dev,v) \
+ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)
+
+/* Set About counter stop enable (write only) */
+#define RtdAboutStopEnable(dev,v) \
+ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)
+
+/* Set external trigger polarity (write only) 0=positive edge, 1=negative */
+#define RtdTriggerPolarity(dev,v) \
+ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)
+
+/* Start single ADC conversion */
+#define RtdAdcStart(dev) \
+ writew (0, devpriv->las0+LAS0_ADC)
+
+/* Read one ADC data value (12bit (with sign extend) as 16bit) */
+/* Note: matches what DMA would get. Actual value >> 3 */
+#define RtdAdcFifoGet(dev) \
+ readw (devpriv->las1+LAS1_ADC_FIFO)
+
+/* Read two ADC data values (DOESNT WORK) */
+#define RtdAdcFifoGet2(dev) \
+ readl (devpriv->las1+LAS1_ADC_FIFO)
+
+/* FIFO status */
+#define RtdFifoStatus(dev) \
+ readl (devpriv->las0+LAS0_ADC)
+
+/* pacer start/stop read=start, write=stop*/
+#define RtdPacerStart(dev) \
+ readl (devpriv->las0+LAS0_PACER)
+#define RtdPacerStop(dev) \
+ writel (0, devpriv->las0+LAS0_PACER)
+
+/* Interrupt status */
+#define RtdInterruptStatus(dev) \
+ readw (devpriv->las0+LAS0_IT)
+
+/* Interrupt mask */
+#define RtdInterruptMask(dev,v) \
+ writew ((devpriv->intMask = (v)),devpriv->las0+LAS0_IT)
+
+/* Interrupt status clear (only bits set in mask) */
+#define RtdInterruptClear(dev) \
+ readw (devpriv->las0+LAS0_CLEAR)
+
+/* Interrupt clear mask */
+#define RtdInterruptClearMask(dev,v) \
+ writew ((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)
+
+/* Interrupt overrun status */
+#define RtdInterruptOverrunStatus(dev) \
+ readl (devpriv->las0+LAS0_OVERRUN)
+
+/* Interrupt overrun clear */
+#define RtdInterruptOverrunClear(dev) \
+ writel (0, devpriv->las0+LAS0_OVERRUN)
+
+/* Pacer counter, 24bit */
+#define RtdPacerCount(dev) \
+ readl (devpriv->las0+LAS0_PCLK)
+#define RtdPacerCounter(dev,v) \
+ writel ((v) & 0xffffff,devpriv->las0+LAS0_PCLK)
+
+/* Burst counter, 10bit */
+#define RtdBurstCount(dev) \
+ readl (devpriv->las0+LAS0_BCLK)
+#define RtdBurstCounter(dev,v) \
+ writel ((v) & 0x3ff,devpriv->las0+LAS0_BCLK)
+
+/* Delay counter, 16bit */
+#define RtdDelayCount(dev) \
+ readl (devpriv->las0+LAS0_DCLK)
+#define RtdDelayCounter(dev,v) \
+ writel ((v) & 0xffff, devpriv->las0+LAS0_DCLK)
+
+/* About counter, 16bit */
+#define RtdAboutCount(dev) \
+ readl (devpriv->las0+LAS0_ACNT)
+#define RtdAboutCounter(dev,v) \
+ writel ((v) & 0xffff, devpriv->las0+LAS0_ACNT)
+
+/* ADC sample counter, 10bit */
+#define RtdAdcSampleCount(dev) \
+ readl (devpriv->las0+LAS0_ADC_SCNT)
+#define RtdAdcSampleCounter(dev,v) \
+ writel ((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)
+
+/* User Timer/Counter (8254) */
+#define RtdUtcCounterGet(dev,n) \
+ readb (devpriv->las0 \
+ + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
+
+#define RtdUtcCounterPut(dev,n,v) \
+ writeb ((v) & 0xff, devpriv->las0 \
+ + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
+
+/* Set UTC (8254) control byte */
+#define RtdUtcCtrlPut(dev,n,v) \
+ writeb (devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \
+ devpriv->las0 + LAS0_UTC_CTRL)
+
+/* Set UTCn clock source (write only) */
+#define RtdUtcClockSource(dev,n,v) \
+ writew (v, devpriv->las0 \
+ + ((n <= 0) ? LAS0_UTC0_CLOCK : \
+ ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))
+
+/* Set UTCn gate source (write only) */
+#define RtdUtcGateSource(dev,n,v) \
+ writew (v, devpriv->las0 \
+ + ((n <= 0) ? LAS0_UTC0_GATE : \
+ ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))
+
+/* User output N source select (write only) */
+#define RtdUsrOutSource(dev,n,v) \
+ writel (v,devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
+
+/* Digital IO */
+#define RtdDio0Read(dev) \
+ (readw (devpriv->las0+LAS0_DIO0) & 0xff)
+#define RtdDio0Write(dev,v) \
+ writew ((v) & 0xff, devpriv->las0+LAS0_DIO0)
+
+#define RtdDio1Read(dev) \
+ (readw (devpriv->las0+LAS0_DIO1) & 0xff)
+#define RtdDio1Write(dev,v) \
+ writew ((v) & 0xff, devpriv->las0+LAS0_DIO1)
+
+#define RtdDioStatusRead(dev) \
+ (readw (devpriv->las0+LAS0_DIO_STATUS) & 0xff)
+#define RtdDioStatusWrite(dev,v) \
+ writew ((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)
+
+#define RtdDio0CtrlRead(dev) \
+ (readw (devpriv->las0+LAS0_DIO0_CTRL) & 0xff)
+#define RtdDio0CtrlWrite(dev,v) \
+ writew ((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)
+
+/* Digital to Analog converter */
+/* Write one data value (sign + 12bit + marker bits) */
+/* Note: matches what DMA would put. Actual value << 3 */
+#define RtdDacFifoPut(dev,n,v) \
+ writew ((v), devpriv->las1 +(((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
+
+/* Start single DAC conversion */
+#define RtdDacUpdate(dev,n) \
+ writew (0, devpriv->las0 +(((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))
+
+/* Start single DAC conversion on both DACs */
+#define RtdDacBothUpdate(dev) \
+ writew (0, devpriv->las0+LAS0_DAC)
+
+/* Set DAC output type and range */
+#define RtdDacRange(dev,n,v) \
+ writew ((v) & 7, devpriv->las0 \
+ +(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))
+
+/* Reset DAC FIFO */
+#define RtdDacClearFifo(dev,n) \
+ writel (0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
+
+/* Set source for DMA 0 (write only, shadow?) */
+#define RtdDma0Source(dev,n) \
+ writel ((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)
+
+/* Set source for DMA 1 (write only, shadow?) */
+#define RtdDma1Source(dev,n) \
+ writel ((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)
+
+/* Reset board state for DMA 0 */
+#define RtdDma0Reset(dev) \
+ writel (0, devpriv->las0+LAS0_DMA0_RESET)
+
+/* Reset board state for DMA 1 */
+#define RtdDma1Reset(dev) \
+ writel (0, devpriv->las0+LAS0_DMA1_SRC)
+
+/* PLX9080 interrupt mask and status */
+#define RtdPlxInterruptRead(dev) \
+ readl (devpriv->lcfg+LCFG_ITCSR)
+#define RtdPlxInterruptWrite(dev,v) \
+ writel (v, devpriv->lcfg+LCFG_ITCSR)
+
+/* Set mode for DMA 0 */
+#define RtdDma0Mode(dev,m) \
+ writel ((m), devpriv->lcfg+LCFG_DMAMODE0)
+
+/* Set PCI address for DMA 0 */
+#define RtdDma0PciAddr(dev,a) \
+ writel ((a), devpriv->lcfg+LCFG_DMAPADR0)
+
+/* Set local address for DMA 0 */
+#define RtdDma0LocalAddr(dev,a) \
+ writel ((a), devpriv->lcfg+LCFG_DMALADR0)
+
+/* Set byte count for DMA 0 */
+#define RtdDma0Count(dev,c) \
+ writel ((c), devpriv->lcfg+LCFG_DMASIZ0)
+
+/* Set next descriptor for DMA 0 */
+#define RtdDma0Next(dev,a) \
+ writel ((a), devpriv->lcfg+LCFG_DMADPR0)
+
+/* Set mode for DMA 1 */
+#define RtdDma1Mode(dev,m) \
+ writel ((m), devpriv->lcfg+LCFG_DMAMODE1)
+
+/* Set PCI address for DMA 1 */
+#define RtdDma1PciAddr(dev,a) \
+ writel ((a), devpriv->lcfg+LCFG_DMAADR1)
+
+/* Set local address for DMA 1 */
+#define RtdDma1LocalAddr(dev,a) \
+ writel ((a), devpriv->lcfg+LCFG_DMALADR1)
+
+/* Set byte count for DMA 1 */
+#define RtdDma1Count(dev,c) \
+ writel ((c), devpriv->lcfg+LCFG_DMASIZ1)
+
+/* Set next descriptor for DMA 1 */
+#define RtdDma1Next(dev,a) \
+ writel ((a), devpriv->lcfg+LCFG_DMADPR1)
+
+/* Set control for DMA 0 (write only, shadow?) */
+#define RtdDma0Control(dev,n) \
+ writeb (devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)
+
+/* Get status for DMA 0 */
+#define RtdDma0Status(dev) \
+ readb (devpriv->lcfg+LCFG_DMACSR0)
+
+/* Set control for DMA 1 (write only, shadow?) */
+#define RtdDma1Control(dev,n) \
+ writeb (devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)
+
+/* Get status for DMA 1 */
+#define RtdDma1Status(dev) \
+ readb (devpriv->lcfg+LCFG_DMACSR1)
+
+/*
+ * The comedi_driver structure tells the Comedi core module
+ * which functions to call to configure/deconfigure (attac/detach)
+ * the board, and also about the kernel module that contains
+ * the device code.
+ */
+static int rtd_attach(comedi_device * dev, comedi_devconfig * it);
+static int rtd_detach(comedi_device * dev);
+
+static comedi_driver rtd520Driver = {
+ driver_name: DRV_NAME,
+ module:THIS_MODULE,
+ attach:rtd_attach,
+ detach:rtd_detach,
+};
+
+static int rtd_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int rtd_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int rtd_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int rtd_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int rtd_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int rtd_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ comedi_cmd * cmd);
+static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+//static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s);
+static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
+static irqreturn_t rtd_interrupt(int irq, void *d PT_REGS_ARG);
+static int rtd520_probe_fifo_depth(comedi_device *dev);
+
+/*
+ * Attach is called by the Comedi core to configure the driver
+ * for a particular board. If you specified a board_name array
+ * in the driver structure, dev->board_ptr contains that
+ * address.
+ */
+static int rtd_attach(comedi_device * dev, comedi_devconfig * it)
+{ /* board name and options flags */
+ comedi_subdevice *s;
+ struct pci_dev *pcidev;
+ int ret;
+ resource_size_t physLas0; /* configuation */
+ resource_size_t physLas1; /* data area */
+ resource_size_t physLcfg; /* PLX9080 */
+#ifdef USE_DMA
+ int index;
+#endif
+
+ printk("comedi%d: rtd520 attaching.\n", dev->minor);
+
+#if defined (CONFIG_COMEDI_DEBUG) && defined (USE_DMA)
+ /* You can set this a load time: modprobe comedi comedi_debug=1 */
+ if (0 == comedi_debug) /* force DMA debug printks */
+ comedi_debug = 1;
+#endif
+
+ /*
+ * Allocate the private structure area. alloc_private() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_private(dev, sizeof(rtdPrivate)) < 0)
+ return -ENOMEM;
+
+ /*
+ * Probe the device to determine what device in the series it is.
+ */
+ for (pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, NULL);
+ pcidev != NULL;
+ pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, pcidev)) {
+ int i;
+
+ if (it->options[0] || it->options[1]) {
+ if (pcidev->bus->number != it->options[0]
+ || PCI_SLOT(pcidev->devfn) !=
+ it->options[1]) {
+ continue;
+ }
+ }
+ for(i = 0; i < sizeof(rtd520Boards) / sizeof(rtd520Boards[0]); ++i)
+ {
+ if(pcidev->device == rtd520Boards[i].device_id)
+ {
+ dev->board_ptr = &rtd520Boards[i];
+ break;
+ }
+ }
+ if(dev->board_ptr) break; /* found one */
+ }
+ if (!pcidev) {
+ if (it->options[0] && it->options[1]) {
+ printk("No RTD card at bus=%d slot=%d.\n",
+ it->options[0], it->options[1]);
+ } else {
+ printk("No RTD card found.\n");
+ }
+ return -EIO;
+ }
+ devpriv->pci_dev = pcidev;
+ dev->board_name = thisboard->name;
+
+ if ((ret = comedi_pci_enable(pcidev, DRV_NAME)) < 0) {
+ printk("Failed to enable PCI device and request regions.\n");
+ return ret;
+ }
+ devpriv->got_regions = 1;
+
+ /*
+ * Initialize base addresses
+ */
+ /* Get the physical address from PCI config */
+ physLas0 = pci_resource_start(devpriv->pci_dev, LAS0_PCIINDEX);
+ physLas1 = pci_resource_start(devpriv->pci_dev, LAS1_PCIINDEX);
+ physLcfg = pci_resource_start(devpriv->pci_dev, LCFG_PCIINDEX);
+ /* Now have the kernel map this into memory */
+ /* ASSUME page aligned */
+ devpriv->las0 = ioremap_nocache(physLas0, LAS0_PCISIZE);
+ devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE);
+ devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE);
+
+ if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) {
+ return -ENOMEM;
+ }
+
+ DPRINTK("%s: LAS0=%llx, LAS1=%llx, CFG=%llx.\n", dev->board_name,
+ (unsigned long long)physLas0, (unsigned long long)physLas1,
+ (unsigned long long)physLcfg);
+ { /* The RTD driver does this */
+ unsigned char pci_latency;
+ u16 revision;
+ /*uint32_t epld_version; */
+
+ pci_read_config_word(devpriv->pci_dev, PCI_REVISION_ID,
+ &revision);
+ DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision);
+
+ pci_read_config_byte(devpriv->pci_dev,
+ PCI_LATENCY_TIMER, &pci_latency);
+ if (pci_latency < 32) {
+ printk("%s: PCI latency changed from %d to %d\n",
+ dev->board_name, pci_latency, 32);
+ pci_write_config_byte(devpriv->pci_dev,
+ PCI_LATENCY_TIMER, 32);
+ } else {
+ DPRINTK("rtd520: PCI latency = %d\n", pci_latency);
+ }
+
+ /* Undocumented EPLD version (doesnt match RTD driver results) */
+ /*DPRINTK ("rtd520: Reading epld from %p\n",
+ devpriv->las0+0);
+ epld_version = readl (devpriv->las0+0);
+ if ((epld_version & 0xF0) >> 4 == 0x0F) {
+ DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version);
+ } else {
+ DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4);
+ } */
+ }
+
+ /* Show board configuration */
+ printk("%s:", dev->board_name);
+
+ /*
+ * Allocate the subdevice structures. alloc_subdevice() is a
+ * convenient macro defined in comedidev.h.
+ */
+ if (alloc_subdevices(dev, 4) < 0) {
+ return -ENOMEM;
+ }
+
+ s = dev->subdevices + 0;
+ dev->read_subdev = s;
+ /* analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags =
+ SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF |
+ SDF_CMD_READ;
+ s->n_chan = thisboard->aiChans;
+ s->maxdata = (1 << thisboard->aiBits) - 1;
+ if (thisboard->aiMaxGain <= 32) {
+ s->range_table = &rtd_ai_7520_range;
+ } else {
+ s->range_table = &rtd_ai_4520_range;
+ }
+ s->len_chanlist = RTD_MAX_CHANLIST; /* devpriv->fifoLen */
+ s->insn_read = rtd_ai_rinsn;
+ s->do_cmd = rtd_ai_cmd;
+ s->do_cmdtest = rtd_ai_cmdtest;
+ s->cancel = rtd_ai_cancel;
+ /*s->poll = rtd_ai_poll; *//* not ready yet */
+
+ s = dev->subdevices + 1;
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 2;
+ s->maxdata = (1 << thisboard->aiBits) - 1;
+ s->range_table = &rtd_ao_range;
+ s->insn_write = rtd_ao_winsn;
+ s->insn_read = rtd_ao_rinsn;
+
+ s = dev->subdevices + 2;
+ /* digital i/o subdevice */
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ /* we only support port 0 right now. Ignoring port 1 and user IO */
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = rtd_dio_insn_bits;
+ s->insn_config = rtd_dio_insn_config;
+
+ /* timer/counter subdevices (not currently supported) */
+ s = dev->subdevices + 3;
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 3;
+ s->maxdata = 0xffff;
+
+ /* initialize board, per RTD spec */
+ /* also, initialize shadow registers */
+ RtdResetBoard(dev);
+ comedi_udelay(100); /* needed? */
+ RtdPlxInterruptWrite(dev, 0);
+ RtdInterruptMask(dev, 0); /* and sets shadow */
+ RtdInterruptClearMask(dev, ~0); /* and sets shadow */
+ RtdInterruptClear(dev); /* clears bits set by mask */
+ RtdInterruptOverrunClear(dev);
+ RtdClearCGT(dev);
+ RtdAdcClearFifo(dev);
+ RtdDacClearFifo(dev, 0);
+ RtdDacClearFifo(dev, 1);
+ /* clear digital IO fifo */
+ RtdDioStatusWrite(dev, 0); /* safe state, set shadow */
+ RtdUtcCtrlPut(dev, 0, 0x30); /* safe state, set shadow */
+ RtdUtcCtrlPut(dev, 1, 0x30); /* safe state, set shadow */
+ RtdUtcCtrlPut(dev, 2, 0x30); /* safe state, set shadow */
+ RtdUtcCtrlPut(dev, 3, 0); /* safe state, set shadow */
+ /* TODO: set user out source ??? */
+
+ /* check if our interrupt is available and get it */
+ if ((ret = comedi_request_irq(devpriv->pci_dev->irq, rtd_interrupt,
+ IRQF_SHARED, DRV_NAME, dev)) < 0) {
+ printk("Could not get interrupt! (%u)\n",
+ devpriv->pci_dev->irq);
+ return ret;
+ }
+ dev->irq = devpriv->pci_dev->irq;
+ printk("( irq=%u )", dev->irq);
+
+ ret = rtd520_probe_fifo_depth(dev);
+ if(ret < 0) {
+ return ret;
+ }
+ devpriv->fifoLen = ret;
+ printk("( fifoLen=%d )", devpriv->fifoLen);
+
+#ifdef USE_DMA
+ if (dev->irq > 0) {
+ printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT);
+ /* The PLX9080 has 2 DMA controllers, but there could be 4 sources:
+ ADC, digital, DAC1, and DAC2. Since only the ADC supports cmd mode
+ right now, this isn't an issue (yet) */
+ devpriv->dma0Offset = 0;
+
+ for (index = 0; index < DMA_CHAIN_COUNT; index++) {
+ devpriv->dma0Buff[index] =
+ pci_alloc_consistent(devpriv->pci_dev,
+ sizeof(u16) * devpriv->fifoLen / 2,
+ &devpriv->dma0BuffPhysAddr[index]);
+ if (devpriv->dma0Buff[index] == NULL) {
+ ret = -ENOMEM;
+ goto rtd_attach_die_error;
+ }
+ /*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n",
+ index,
+ devpriv->dma0Buff[index], devpriv->dma0BuffPhysAddr[index]); */
+ }
+
+ /* setup DMA descriptor ring (use cpu_to_le32 for byte ordering?) */
+ devpriv->dma0Chain =
+ pci_alloc_consistent(devpriv->pci_dev,
+ sizeof(struct plx_dma_desc) * DMA_CHAIN_COUNT,
+ &devpriv->dma0ChainPhysAddr);
+ for (index = 0; index < DMA_CHAIN_COUNT; index++) {
+ devpriv->dma0Chain[index].pci_start_addr =
+ devpriv->dma0BuffPhysAddr[index];
+ devpriv->dma0Chain[index].local_start_addr =
+ DMALADDR_ADC;
+ devpriv->dma0Chain[index].transfer_size =
+ sizeof(u16) * devpriv->fifoLen / 2;
+ devpriv->dma0Chain[index].next =
+ (devpriv->dma0ChainPhysAddr + ((index +
+ 1) % (DMA_CHAIN_COUNT))
+ * sizeof(devpriv->dma0Chain[0]))
+ | DMA_TRANSFER_BITS;
+ /*DPRINTK ("ring[%d] @%lx PCI: %x, local: %x, N: 0x%x, next: %x\n",
+ index,
+ ((long)devpriv->dma0ChainPhysAddr
+ + (index * sizeof(devpriv->dma0Chain[0]))),
+ devpriv->dma0Chain[index].pci_start_addr,
+ devpriv->dma0Chain[index].local_start_addr,
+ devpriv->dma0Chain[index].transfer_size,
+ devpriv->dma0Chain[index].next); */
+ }
+
+ if (devpriv->dma0Chain == NULL) {
+ ret = -ENOMEM;
+ goto rtd_attach_die_error;
+ }
+
+ RtdDma0Mode(dev, DMA_MODE_BITS);
+ RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); /* set DMA trigger source */
+ } else {
+ printk("( no IRQ->no DMA )");
+ }
+#endif /* USE_DMA */
+
+ if (dev->irq) { /* enable plx9080 interrupts */
+ RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE);
+ }
+
+ printk("\ncomedi%d: rtd520 driver attached.\n", dev->minor);
+
+ return 1;
+
+#if 0
+ /* hit an error, clean up memory and return ret */
+//rtd_attach_die_error:
+#ifdef USE_DMA
+ for (index = 0; index < DMA_CHAIN_COUNT; index++) {
+ if (NULL != devpriv->dma0Buff[index]) { /* free buffer memory */
+ pci_free_consistent(devpriv->pci_dev,
+ sizeof(u16) * devpriv->fifoLen / 2,
+ devpriv->dma0Buff[index],
+ devpriv->dma0BuffPhysAddr[index]);
+ devpriv->dma0Buff[index] = NULL;
+ }
+ }
+ if (NULL != devpriv->dma0Chain) {
+ pci_free_consistent(devpriv->pci_dev,
+ sizeof(struct plx_dma_desc)
+ * DMA_CHAIN_COUNT,
+ devpriv->dma0Chain, devpriv->dma0ChainPhysAddr);
+ devpriv->dma0Chain = NULL;
+ }
+#endif /* USE_DMA */
+ /* subdevices and priv are freed by the core */
+ if (dev->irq) {
+ /* disable interrupt controller */
+ RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev)
+ & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E));
+ comedi_free_irq(dev->irq, dev);
+ }
+
+ /* release all regions that were allocated */
+ if (devpriv->las0) {
+ iounmap(devpriv->las0);
+ }
+ if (devpriv->las1) {
+ iounmap(devpriv->las1);
+ }
+ if (devpriv->lcfg) {
+ iounmap(devpriv->lcfg);
+ }
+ if (devpriv->pci_dev) {
+ pci_dev_put(devpriv->pci_dev);
+ }
+ return ret;
+#endif
+}
+
+/*
+ * _detach is called to deconfigure a device. It should deallocate
+ * resources.
+ * This function is also called when _attach() fails, so it should be
+ * careful not to release resources that were not necessarily
+ * allocated by _attach(). dev->private and dev->subdevices are
+ * deallocated automatically by the core.
+ */
+static int rtd_detach(comedi_device * dev)
+{
+#ifdef USE_DMA
+ int index;
+#endif
+
+ DPRINTK("comedi%d: rtd520: removing (%ld ints)\n",
+ dev->minor, (devpriv ? devpriv->intCount : 0L));
+ if (devpriv && devpriv->lcfg) {
+ DPRINTK("(int status 0x%x, overrun status 0x%x, fifo status 0x%x)...\n", 0xffff & RtdInterruptStatus(dev), 0xffff & RtdInterruptOverrunStatus(dev), (0xffff & RtdFifoStatus(dev)) ^ 0x6666);
+ }
+
+ if (devpriv) {
+ /* Shut down any board ops by resetting it */
+#ifdef USE_DMA
+ if (devpriv->lcfg) {
+ RtdDma0Control(dev, 0); /* disable DMA */
+ RtdDma1Control(dev, 0); /* disable DMA */
+ RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE);
+ }
+#endif /* USE_DMA */
+ if (devpriv->las0) {
+ RtdResetBoard(dev);
+ RtdInterruptMask(dev, 0);
+ RtdInterruptClearMask(dev, ~0);
+ RtdInterruptClear(dev); /* clears bits set by mask */
+ }
+#ifdef USE_DMA
+ /* release DMA */
+ for (index = 0; index < DMA_CHAIN_COUNT; index++) {
+ if (NULL != devpriv->dma0Buff[index]) {
+ pci_free_consistent(devpriv->pci_dev,
+ sizeof(u16) * devpriv->fifoLen / 2,
+ devpriv->dma0Buff[index],
+ devpriv->dma0BuffPhysAddr[index]);
+ devpriv->dma0Buff[index] = NULL;
+ }
+ }
+ if (NULL != devpriv->dma0Chain) {
+ pci_free_consistent(devpriv->pci_dev,
+ sizeof(struct plx_dma_desc) * DMA_CHAIN_COUNT,
+ devpriv->dma0Chain, devpriv->dma0ChainPhysAddr);
+ devpriv->dma0Chain = NULL;
+ }
+#endif /* USE_DMA */
+
+ /* release IRQ */
+ if (dev->irq) {
+ /* disable interrupt controller */
+ RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev)
+ & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E));
+ comedi_free_irq(dev->irq, dev);
+ }
+
+ /* release all regions that were allocated */
+ if (devpriv->las0) {
+ iounmap(devpriv->las0);
+ }
+ if (devpriv->las1) {
+ iounmap(devpriv->las1);
+ }
+ if (devpriv->lcfg) {
+ iounmap(devpriv->lcfg);
+ }
+ if (devpriv->pci_dev) {
+ if (devpriv->got_regions) {
+ comedi_pci_disable(devpriv->pci_dev);
+ }
+ pci_dev_put(devpriv->pci_dev);
+ }
+ }
+
+ printk("comedi%d: rtd520: removed.\n", dev->minor);
+
+ return 0;
+}
+
+/*
+ Convert a single comedi channel-gain entry to a RTD520 table entry
+*/
+static unsigned short rtdConvertChanGain(comedi_device * dev,
+ unsigned int comediChan, int chanIndex)
+{ /* index in channel list */
+ unsigned int chan, range, aref;
+ unsigned short r = 0;
+
+ chan = CR_CHAN(comediChan);
+ range = CR_RANGE(comediChan);
+ aref = CR_AREF(comediChan);
+
+ r |= chan & 0xf;
+
+ /* Note: we also setup the channel list bipolar flag array */
+ if (range < thisboard->range10Start) { /* first batch are +-5 */
+ r |= 0x000; /* +-5 range */
+ r |= (range & 0x7) << 4; /* gain */
+ CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
+ } else if (range < thisboard->rangeUniStart) { /* second batch are +-10 */
+ r |= 0x100; /* +-10 range */
+ r |= ((range - thisboard->range10Start) & 0x7) << 4; /* gain */
+ CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
+ } else { /* last batch is +10 */
+ r |= 0x200; /* +10 range */
+ r |= ((range - thisboard->rangeUniStart) & 0x7) << 4; /* gain */
+ CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
+ }
+
+ switch (aref) {
+ case AREF_GROUND: /* on-board ground */
+ break;
+
+ case AREF_COMMON:
+ r |= 0x80; /* ref external analog common */
+ break;
+
+ case AREF_DIFF:
+ r |= 0x400; /* differential inputs */
+ break;
+
+ case AREF_OTHER: /* ??? */
+ break;
+ }
+ /*printk ("chan=%d r=%d a=%d -> 0x%x\n",
+ chan, range, aref, r); */
+ return r;
+}
+
+/*
+ Setup the channel-gain table from a comedi list
+*/
+static void rtd_load_channelgain_list(comedi_device * dev,
+ unsigned int n_chan, unsigned int *list)
+{
+ if (n_chan > 1) { /* setup channel gain table */
+ int ii;
+ RtdClearCGT(dev);
+ RtdEnableCGT(dev, 1); /* enable table */
+ for (ii = 0; ii < n_chan; ii++) {
+ RtdWriteCGTable(dev, rtdConvertChanGain(dev, list[ii],
+ ii));
+ }
+ } else { /* just use the channel gain latch */
+ RtdEnableCGT(dev, 0); /* disable table, enable latch */
+ RtdWriteCGLatch(dev, rtdConvertChanGain(dev, list[0], 0));
+ }
+}
+
+/* determine fifo size by doing adc conversions until the fifo half
+empty status flag clears */
+static int rtd520_probe_fifo_depth(comedi_device *dev)
+{
+ lsampl_t chanspec = CR_PACK(0, 0, AREF_GROUND);
+ unsigned i;
+ static const unsigned limit = 0x2000;
+ unsigned fifo_size = 0;
+
+ RtdAdcClearFifo(dev);
+ rtd_load_channelgain_list(dev, 1, &chanspec);
+ RtdAdcConversionSource(dev, 0); /* software */
+ /* convert samples */
+ for (i = 0; i < limit; ++i) {
+ unsigned fifo_status;
+ /* trigger conversion */
+ RtdAdcStart(dev);
+ comedi_udelay(1);
+ fifo_status = RtdFifoStatus(dev);
+ if((fifo_status & FS_ADC_HEMPTY) == 0) {
+ fifo_size = 2 * i;
+ break;
+ }
+ }
+ if(i == limit)
+ {
+ rt_printk("\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
+ return -EIO;
+ }
+ RtdAdcClearFifo(dev);
+ if(fifo_size != 0x400 || fifo_size != 0x2000)
+ {
+ rt_printk("\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
+ DRV_NAME, fifo_size);
+ return -EIO;
+ }
+ return fifo_size;
+}
+
+/*
+ "instructions" read/write data in "one-shot" or "software-triggered"
+ mode (simplest case).
+ This doesnt use interrupts.
+
+ Note, we don't do any settling delays. Use a instruction list to
+ select, delay, then read.
+ */
+static int rtd_ai_rinsn(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ int n, ii;
+ int stat;
+
+ /* clear any old fifo data */
+ RtdAdcClearFifo(dev);
+
+ /* write channel to multiplexer and clear channel gain table */
+ rtd_load_channelgain_list(dev, 1, &insn->chanspec);
+
+ /* set conversion source */
+ RtdAdcConversionSource(dev, 0); /* software */
+
+ /* convert n samples */
+ for (n = 0; n < insn->n; n++) {
+ s16 d;
+ /* trigger conversion */
+ RtdAdcStart(dev);
+
+ for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) {
+ stat = RtdFifoStatus(dev);
+ if (stat & FS_ADC_NOT_EMPTY) /* 1 -> not empty */
+ break;
+ WAIT_QUIETLY;
+ }
+ if (ii >= RTD_ADC_TIMEOUT) {
+ DPRINTK("rtd520: Error: ADC never finished! FifoStatus=0x%x\n", stat ^ 0x6666);
+ return -ETIMEDOUT;
+ }
+
+ /* read data */
+ d = RtdAdcFifoGet(dev); /* get 2s comp value */
+ /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */
+ d = d >> 3; /* low 3 bits are marker lines */
+ if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0)) {
+ data[n] = d + 2048; /* convert to comedi unsigned data */
+ } else {
+ data[n] = d;
+ }
+ }
+
+ /* return the number of samples read/written */
+ return n;
+}
+
+/*
+ Get what we know is there.... Fast!
+ This uses 1/2 the bus cycles of read_dregs (below).
+
+ The manual claims that we can do a lword read, but it doesn't work here.
+*/
+static int ai_read_n(comedi_device * dev, comedi_subdevice * s, int count)
+{
+ int ii;
+
+ for (ii = 0; ii < count; ii++) {
+ sampl_t sample;
+ s16 d;
+
+ if (0 == devpriv->aiCount) { /* done */
+ d = RtdAdcFifoGet(dev); /* Read N and discard */
+ continue;
+ }
+#if 0
+ if (0 == (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY)) { /* DEBUG */
+ DPRINTK("comedi: READ OOPS on %d of %d\n", ii + 1,
+ count);
+ break;
+ }
+#endif
+ d = RtdAdcFifoGet(dev); /* get 2s comp value */
+
+ d = d >> 3; /* low 3 bits are marker lines */
+ if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+ sample = d + 2048; /* convert to comedi unsigned data */
+ } else {
+ sample = d;
+ }
+ if (!comedi_buf_put(s->async, sample))
+ return -1;
+
+ if (devpriv->aiCount > 0) /* < 0, means read forever */
+ devpriv->aiCount--;
+ }
+ return 0;
+}
+
+/*
+ unknown amout of data is waiting in fifo.
+*/
+static int ai_read_dregs(comedi_device * dev, comedi_subdevice * s)
+{
+ while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */
+ sampl_t sample;
+ s16 d = RtdAdcFifoGet(dev); /* get 2s comp value */
+
+ if (0 == devpriv->aiCount) { /* done */
+ continue; /* read rest */
+ }
+
+ d = d >> 3; /* low 3 bits are marker lines */
+ if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+ sample = d + 2048; /* convert to comedi unsigned data */
+ } else {
+ sample = d;
+ }
+ if (!comedi_buf_put(s->async, sample))
+ return -1;
+
+ if (devpriv->aiCount > 0) /* < 0, means read forever */
+ devpriv->aiCount--;
+ }
+ return 0;
+}
+
+#ifdef USE_DMA
+/*
+ Terminate a DMA transfer and wait for everything to quiet down
+*/
+void abort_dma(comedi_device * dev, unsigned int channel)
+{ /* DMA channel 0, 1 */
+ unsigned long dma_cs_addr; /* the control/status register */
+ uint8_t status;
+ unsigned int ii;
+ //unsigned long flags;
+
+ dma_cs_addr = (unsigned long)devpriv->lcfg
+ + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1);
+
+ // spinlock for plx dma control/status reg
+ //comedi_spin_lock_irqsave( &dev->spinlock, flags );
+
+ // abort dma transfer if necessary
+ status = readb(dma_cs_addr);
+ if ((status & PLX_DMA_EN_BIT) == 0) { /* not enabled (Error?) */
+ DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n",
+ channel, status);
+ goto abortDmaExit;
+ }
+
+ /* wait to make sure done bit is zero (needed?) */
+ for (ii = 0; (status & PLX_DMA_DONE_BIT) && ii < RTD_DMA_TIMEOUT; ii++) {
+ WAIT_QUIETLY;
+ status = readb(dma_cs_addr);
+ }
+ if (status & PLX_DMA_DONE_BIT) {
+ printk("rtd520: Timeout waiting for dma %i done clear\n",
+ channel);
+ goto abortDmaExit;
+ }
+
+ /* disable channel (required) */
+ writeb(0, dma_cs_addr);
+ comedi_udelay(1); /* needed?? */
+ /* set abort bit for channel */
+ writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
+
+ // wait for dma done bit to be set
+ status = readb(dma_cs_addr);
+ for (ii = 0;
+ (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT;
+ ii++) {
+ status = readb(dma_cs_addr);
+ WAIT_QUIETLY;
+ }
+ if ((status & PLX_DMA_DONE_BIT) == 0) {
+ printk("rtd520: Timeout waiting for dma %i done set\n",
+ channel);
+ }
+
+ abortDmaExit:
+ //comedi_spin_unlock_irqrestore( &dev->spinlock, flags );
+}
+
+/*
+ Process what is in the DMA transfer buffer and pass to comedi
+ Note: this is not re-entrant
+*/
+static int ai_process_dma(comedi_device * dev, comedi_subdevice * s)
+{
+ int ii, n;
+ s16 *dp;
+
+ if (devpriv->aiCount == 0) /* transfer already complete */
+ return 0;
+
+ dp = devpriv->dma0Buff[devpriv->dma0Offset];
+ for (ii = 0; ii < devpriv->fifoLen / 2;) { /* convert samples */
+ sampl_t sample;
+
+ if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+ sample = (*dp >> 3) + 2048; /* convert to comedi unsigned data */
+ } else {
+ sample = *dp >> 3; /* low 3 bits are marker lines */
+ }
+ *dp++ = sample; /* put processed value back */
+
+ if (++s->async->cur_chan >= s->async->cmd.chanlist_len)
+ s->async->cur_chan = 0;
+
+ ++ii; /* number ready to transfer */
+ if (devpriv->aiCount > 0) { /* < 0, means read forever */
+ if (--devpriv->aiCount == 0) { /* done */
+ /*DPRINTK ("rtd520: Final %d samples\n", ii); */
+ break;
+ }
+ }
+ }
+
+ /* now pass the whole array to the comedi buffer */
+ dp = devpriv->dma0Buff[devpriv->dma0Offset];
+ n = comedi_buf_write_alloc(s->async, ii * sizeof(s16));
+ if (n < (ii * sizeof(s16))) { /* any residual is an error */
+ DPRINTK("rtd520:ai_process_dma buffer overflow %d samples!\n",
+ ii - (n / sizeof(s16)));
+ s->async->events |= COMEDI_CB_ERROR;
+ return -1;
+ }
+ comedi_buf_memcpy_to(s->async, 0, dp, n);
+ comedi_buf_write_free(s->async, n);
+
+ /* always at least 1 scan -- 1/2 FIFO is larger than our max scan list */
+ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
+
+ if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) { /* next buffer */
+ devpriv->dma0Offset = 0;
+ }
+ return 0;
+}
+#endif /* USE_DMA */
+
+/*
+ Handle all rtd520 interrupts.
+ Runs atomically and is never re-entered.
+ This is a "slow handler"; other interrupts may be active.
+ The data conversion may someday happen in a "bottom half".
+*/
+static irqreturn_t rtd_interrupt(int irq, /* interrupt number (ignored) */
+ void *d /* our data */
+ PT_REGS_ARG)
+{ /* cpu context (ignored) */
+ comedi_device *dev = d; /* must be called "dev" for devpriv */
+ u16 status;
+ u16 fifoStatus;
+ comedi_subdevice *s = dev->subdevices + 0; /* analog in subdevice */
+
+ if (!dev->attached) {
+ return IRQ_NONE;
+ }
+
+ devpriv->intCount++; /* DEBUG statistics */
+
+ fifoStatus = RtdFifoStatus(dev);
+ /* check for FIFO full, this automatically halts the ADC! */
+ if (!(fifoStatus & FS_ADC_NOT_FULL)) { /* 0 -> full */
+ DPRINTK("rtd520: FIFO full! fifo_status=0x%x\n", (fifoStatus ^ 0x6666) & 0x7777); /* should be all 0s */
+ goto abortTransfer;
+ }
+#ifdef USE_DMA
+ if (devpriv->flags & DMA0_ACTIVE) { /* Check DMA */
+ u32 istatus = RtdPlxInterruptRead(dev);
+
+ if (istatus & ICS_DMA0_A) {
+ if (ai_process_dma(dev, s) < 0) {
+ DPRINTK("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n", devpriv->aiCount);
+ RtdDma0Control(dev,
+ (devpriv->
+ dma0Control &
+ ~PLX_DMA_START_BIT)
+ | PLX_CLEAR_DMA_INTR_BIT);
+ goto abortTransfer;
+ }
+
+ /*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n",
+ devpriv->aiCount, istatus); */
+ RtdDma0Control(dev,
+ (devpriv->dma0Control & ~PLX_DMA_START_BIT)
+ | PLX_CLEAR_DMA_INTR_BIT);
+ if (0 == devpriv->aiCount) { /* counted down */
+ DPRINTK("rtd520: Samples Done (DMA).\n");
+ goto transferDone;
+ }
+ comedi_event(dev, s);
+ } else {
+ /*DPRINTK ("rtd520: No DMA ready: istatus %x\n", istatus); */
+ }
+ }
+ /* Fall through and check for other interrupt sources */
+#endif /* USE_DMA */
+
+ status = RtdInterruptStatus(dev);
+ /* if interrupt was not caused by our board, or handled above */
+ if (0 == status) {
+ return IRQ_HANDLED;
+ }
+
+ if (status & IRQM_ADC_ABOUT_CNT) { /* sample count -> read FIFO */
+ /* since the priority interrupt controller may have queued a sample
+ counter interrupt, even though we have already finished,
+ we must handle the possibility that there is no data here */
+ if (!(fifoStatus & FS_ADC_HEMPTY)) { /* 0 -> 1/2 full */
+ /*DPRINTK("rtd520: Sample int, reading 1/2FIFO. fifo_status 0x%x\n",
+ (fifoStatus ^ 0x6666) & 0x7777); */
+ if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0) {
+ DPRINTK("rtd520: comedi read buffer overflow (1/2FIFO) with %ld to go!\n", devpriv->aiCount);
+ goto abortTransfer;
+ }
+ if (0 == devpriv->aiCount) { /* counted down */
+ DPRINTK("rtd520: Samples Done (1/2). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777); /* should be all 0s */
+ goto transferDone;
+ }
+ comedi_event(dev, s);
+ } else if (devpriv->transCount > 0) { /* read often */
+ /*DPRINTK("rtd520: Sample int, reading %d fifo_status 0x%x\n",
+ devpriv->transCount, (fifoStatus ^ 0x6666) & 0x7777); */
+ if (fifoStatus & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */
+ if (ai_read_n(dev, s, devpriv->transCount) < 0) {
+ DPRINTK("rtd520: comedi read buffer overflow (N) with %ld to go!\n", devpriv->aiCount);
+ goto abortTransfer;
+ }
+ if (0 == devpriv->aiCount) { /* counted down */
+ DPRINTK("rtd520: Samples Done (N). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);
+ goto transferDone;
+ }
+ comedi_event(dev, s);
+ }
+ } else { /* wait for 1/2 FIFO (old) */
+ DPRINTK("rtd520: Sample int. Wait for 1/2. fifo_status 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);
+ }
+ } else {
+ DPRINTK("rtd520: unknown interrupt source!\n");
+ }
+
+ if (0xffff & RtdInterruptOverrunStatus(dev)) { /* interrupt overrun */
+ DPRINTK("rtd520: Interrupt overrun with %ld to go! over_status=0x%x\n", devpriv->aiCount, 0xffff & RtdInterruptOverrunStatus(dev));
+ goto abortTransfer;
+ }
+
+ /* clear the interrupt */
+ RtdInterruptClearMask(dev, status);
+ RtdInterruptClear(dev);
+ return IRQ_HANDLED;
+
+ abortTransfer:
+ RtdAdcClearFifo(dev); /* clears full flag */
+ s->async->events |= COMEDI_CB_ERROR;
+ devpriv->aiCount = 0; /* stop and don't transfer any more */
+ /* fall into transferDone */
+
+ transferDone:
+ RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */
+ RtdPacerStop(dev); /* Stop PACER */
+ RtdAdcConversionSource(dev, 0); /* software trigger only */
+ RtdInterruptMask(dev, 0); /* mask out SAMPLE */
+#ifdef USE_DMA
+ if (devpriv->flags & DMA0_ACTIVE) {
+ RtdPlxInterruptWrite(dev, /* disable any more interrupts */
+ RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
+ abort_dma(dev, 0);
+ devpriv->flags &= ~DMA0_ACTIVE;
+ /* if Using DMA, then we should have read everything by now */
+ if (devpriv->aiCount > 0) {
+ DPRINTK("rtd520: Lost DMA data! %ld remain\n",
+ devpriv->aiCount);
+ }
+ }
+#endif /* USE_DMA */
+
+ if (devpriv->aiCount > 0) { /* there shouldn't be anything left */
+ fifoStatus = RtdFifoStatus(dev);
+ DPRINTK("rtd520: Finishing up. %ld remain, fifoStat=%x\n", devpriv->aiCount, (fifoStatus ^ 0x6666) & 0x7777); /* should read all 0s */
+ ai_read_dregs(dev, s); /* read anything left in FIFO */
+ }
+
+ s->async->events |= COMEDI_CB_EOA; /* signal end to comedi */
+ comedi_event(dev, s);
+
+ /* clear the interrupt */
+ status = RtdInterruptStatus(dev);
+ RtdInterruptClearMask(dev, status);
+ RtdInterruptClear(dev);
+
+ fifoStatus = RtdFifoStatus(dev); /* DEBUG */
+ DPRINTK("rtd520: Acquisition complete. %ld ints, intStat=%x, overStat=%x\n", devpriv->intCount, status, 0xffff & RtdInterruptOverrunStatus(dev));
+
+ return IRQ_HANDLED;
+}
+
+#if 0
+/*
+ return the number of samples available
+*/
+static int rtd_ai_poll(comedi_device * dev, comedi_subdevice * s)
+{
+ /* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
+ /* Not sure what to do if DMA is active */
+ return s->async->buf_write_count - s->async->buf_read_count;
+}
+#endif
+
+/*
+ cmdtest tests a particular command to see if it is valid.
+ Using the cmdtest ioctl, a user can create a valid cmd
+ and then have it executed by the cmd ioctl (asyncronously).
+
+ cmdtest returns 1,2,3,4 or 0, depending on which tests
+ the command passes.
+*/
+
+static int rtd_ai_cmdtest(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd)
+{
+ int err = 0;
+ int tmp;
+
+ /* step 1: make sure trigger sources are trivially valid */
+
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW;
+ if (!cmd->start_src || tmp != cmd->start_src) {
+ err++;
+ }
+
+ tmp = cmd->scan_begin_src;
+ cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) {
+ err++;
+ }
+
+ tmp = cmd->convert_src;
+ cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
+ if (!cmd->convert_src || tmp != cmd->convert_src) {
+ err++;
+ }
+
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src) {
+ err++;
+ }
+
+ tmp = cmd->stop_src;
+ cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+ if (!cmd->stop_src || tmp != cmd->stop_src) {
+ err++;
+ }
+
+ if (err)
+ return 1;
+
+ /* step 2: make sure trigger sources are unique
+ and mutually compatible */
+ /* note that mutual compatiblity is not an issue here */
+ if (cmd->scan_begin_src != TRIG_TIMER &&
+ cmd->scan_begin_src != TRIG_EXT) {
+ err++;
+ }
+ if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) {
+ err++;
+ }
+ if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) {
+ err++;
+ }
+
+ if (err) {
+ return 2;
+ }
+
+ /* step 3: make sure arguments are trivially compatible */
+
+ if (cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ /* Note: these are time periods, not actual rates */
+ if (1 == cmd->chanlist_len) { /* no scanning */
+ if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) {
+ cmd->scan_begin_arg = RTD_MAX_SPEED_1;
+ rtd_ns_to_timer(&cmd->scan_begin_arg,
+ TRIG_ROUND_UP);
+ err++;
+ }
+ if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) {
+ cmd->scan_begin_arg = RTD_MIN_SPEED_1;
+ rtd_ns_to_timer(&cmd->scan_begin_arg,
+ TRIG_ROUND_DOWN);
+ err++;
+ }
+ } else {
+ if (cmd->scan_begin_arg < RTD_MAX_SPEED) {
+ cmd->scan_begin_arg = RTD_MAX_SPEED;
+ rtd_ns_to_timer(&cmd->scan_begin_arg,
+ TRIG_ROUND_UP);
+ err++;
+ }
+ if (cmd->scan_begin_arg > RTD_MIN_SPEED) {
+ cmd->scan_begin_arg = RTD_MIN_SPEED;
+ rtd_ns_to_timer(&cmd->scan_begin_arg,
+ TRIG_ROUND_DOWN);
+ err++;
+ }
+ }
+ } else {
+ /* external trigger */
+ /* should be level/edge, hi/lo specification here */
+ /* should specify multiple external triggers */
+ if (cmd->scan_begin_arg > 9) {
+ cmd->scan_begin_arg = 9;
+ err++;
+ }
+ }
+ if (cmd->convert_src == TRIG_TIMER) {
+ if (1 == cmd->chanlist_len) { /* no scanning */
+ if (cmd->convert_arg < RTD_MAX_SPEED_1) {
+ cmd->convert_arg = RTD_MAX_SPEED_1;
+ rtd_ns_to_timer(&cmd->convert_arg,
+ TRIG_ROUND_UP);
+ err++;
+ }
+ if (cmd->convert_arg > RTD_MIN_SPEED_1) {
+ cmd->convert_arg = RTD_MIN_SPEED_1;
+ rtd_ns_to_timer(&cmd->convert_arg,
+ TRIG_ROUND_DOWN);
+ err++;
+ }
+ } else {
+ if (cmd->convert_arg < RTD_MAX_SPEED) {
+ cmd->convert_arg = RTD_MAX_SPEED;
+ rtd_ns_to_timer(&cmd->convert_arg,
+ TRIG_ROUND_UP);
+ err++;
+ }
+ if (cmd->convert_arg > RTD_MIN_SPEED) {
+ cmd->convert_arg = RTD_MIN_SPEED;
+ rtd_ns_to_timer(&cmd->convert_arg,
+ TRIG_ROUND_DOWN);
+ err++;
+ }
+ }
+ } else {
+ /* external trigger */
+ /* see above */
+ if (cmd->convert_arg > 9) {
+ cmd->convert_arg = 9;
+ err++;
+ }
+ }
+
+#if 0
+ if (cmd->scan_end_arg != cmd->chanlist_len) {
+ cmd->scan_end_arg = cmd->chanlist_len;
+ err++;
+ }
+#endif
+ if (cmd->stop_src == TRIG_COUNT) {
+ /* TODO check for rounding error due to counter wrap */
+
+ } else {
+ /* TRIG_NONE */
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+ }
+
+ if (err) {
+ return 3;
+ }
+
+ /* step 4: fix up any arguments */
+
+ if (cmd->chanlist_len > RTD_MAX_CHANLIST) {
+ cmd->chanlist_len = RTD_MAX_CHANLIST;
+ err++;
+ }
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ tmp = cmd->scan_begin_arg;
+ rtd_ns_to_timer(&cmd->scan_begin_arg,
+ cmd->flags & TRIG_ROUND_MASK);
+ if (tmp != cmd->scan_begin_arg) {
+ err++;
+ }
+ }
+ if (cmd->convert_src == TRIG_TIMER) {
+ tmp = cmd->convert_arg;
+ rtd_ns_to_timer(&cmd->convert_arg,
+ cmd->flags & TRIG_ROUND_MASK);
+ if (tmp != cmd->convert_arg) {
+ err++;
+ }
+ if (cmd->scan_begin_src == TRIG_TIMER
+ && (cmd->scan_begin_arg
+ < (cmd->convert_arg * cmd->scan_end_arg))) {
+ cmd->scan_begin_arg =
+ cmd->convert_arg * cmd->scan_end_arg;
+ err++;
+ }
+ }
+
+ if (err) {
+ return 4;
+ }
+
+ return 0;
+}
+
+/*
+ Execute a analog in command with many possible triggering options.
+ The data get stored in the async structure of the subdevice.
+ This is usually done by an interrupt handler.
+ Userland gets to the data using read calls.
+*/
+static int rtd_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+{
+ comedi_cmd *cmd = &s->async->cmd;
+ int timer;
+
+ /* stop anything currently running */
+ RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */
+ RtdPacerStop(dev); /* make sure PACER is stopped */
+ RtdAdcConversionSource(dev, 0); /* software trigger only */
+ RtdInterruptMask(dev, 0);
+#ifdef USE_DMA
+ if (devpriv->flags & DMA0_ACTIVE) { /* cancel anything running */
+ RtdPlxInterruptWrite(dev, /* disable any more interrupts */
+ RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
+ abort_dma(dev, 0);
+ devpriv->flags &= ~DMA0_ACTIVE;
+ if (RtdPlxInterruptRead(dev) & ICS_DMA0_A) { /*clear pending int */
+ RtdDma0Control(dev, PLX_CLEAR_DMA_INTR_BIT);
+ }
+ }
+ RtdDma0Reset(dev); /* reset onboard state */
+#endif /* USE_DMA */
+ RtdAdcClearFifo(dev); /* clear any old data */
+ RtdInterruptOverrunClear(dev);
+ devpriv->intCount = 0;
+
+ if (!dev->irq) { /* we need interrupts for this */
+ DPRINTK("rtd520: ERROR! No interrupt available!\n");
+ return -ENXIO;
+ }
+
+ /* start configuration */
+ /* load channel list and reset CGT */
+ rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
+
+ /* setup the common case and override if needed */
+ if (cmd->chanlist_len > 1) {
+ /*DPRINTK ("rtd520: Multi channel setup\n"); */
+ RtdPacerStartSource(dev, 0); /* software triggers pacer */
+ RtdBurstStartSource(dev, 1); /* PACER triggers burst */
+ RtdAdcConversionSource(dev, 2); /* BURST triggers ADC */
+ } else { /* single channel */
+ /*DPRINTK ("rtd520: single channel setup\n"); */
+ RtdPacerStartSource(dev, 0); /* software triggers pacer */
+ RtdAdcConversionSource(dev, 1); /* PACER triggers ADC */
+ }
+ RtdAboutCounter(dev, devpriv->fifoLen / 2 - 1); /* 1/2 FIFO */
+
+ if (TRIG_TIMER == cmd->scan_begin_src) {
+ /* scan_begin_arg is in nanoseconds */
+ /* find out how many samples to wait before transferring */
+ if (cmd->flags & TRIG_WAKE_EOS) {
+ /* this may generate un-sustainable interrupt rates */
+ /* the application is responsible for doing the right thing */
+ devpriv->transCount = cmd->chanlist_len;
+ devpriv->flags |= SEND_EOS;
+ } else {
+ /* arrange to transfer data periodically */
+ devpriv->transCount
+ =
+ (TRANS_TARGET_PERIOD * cmd->chanlist_len) /
+ cmd->scan_begin_arg;
+ if (devpriv->transCount < cmd->chanlist_len) {
+ /* tranfer after each scan (and avoid 0) */
+ devpriv->transCount = cmd->chanlist_len;
+ } else { /* make a multiple of scan length */
+ devpriv->transCount =
+ (devpriv->transCount +
+ cmd->chanlist_len - 1)
+ / cmd->chanlist_len;
+ devpriv->transCount *= cmd->chanlist_len;
+ }
+ devpriv->flags |= SEND_EOS;
+ }
+ if (devpriv->transCount >= (devpriv->fifoLen / 2)) {
+ /* out of counter range, use 1/2 fifo instead */
+ devpriv->transCount = 0;
+ devpriv->flags &= ~SEND_EOS;
+ } else {
+ /* interrupt for each tranfer */
+ RtdAboutCounter(dev, devpriv->transCount - 1);
+ }
+
+ DPRINTK("rtd520: scanLen=%d tranferCount=%d fifoLen=%d\n scanTime(ns)=%d flags=0x%x\n", cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen, cmd->scan_begin_arg, devpriv->flags);
+ } else { /* unknown timing, just use 1/2 FIFO */
+ devpriv->transCount = 0;
+ devpriv->flags &= ~SEND_EOS;
+ }
+ RtdPacerClockSource(dev, 1); /* use INTERNAL 8Mhz clock source */
+ RtdAboutStopEnable(dev, 1); /* just interrupt, dont stop */
+
+ /* BUG??? these look like enumerated values, but they are bit fields */
+
+ /* First, setup when to stop */
+ switch (cmd->stop_src) {
+ case TRIG_COUNT: /* stop after N scans */
+ devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len;
+ if ((devpriv->transCount > 0)
+ && (devpriv->transCount > devpriv->aiCount)) {
+ devpriv->transCount = devpriv->aiCount;
+ }
+ break;
+
+ case TRIG_NONE: /* stop when cancel is called */
+ devpriv->aiCount = -1; /* read forever */
+ break;
+
+ default:
+ DPRINTK("rtd520: Warning! ignoring stop_src mode %d\n",
+ cmd->stop_src);
+ }
+
+ /* Scan timing */
+ switch (cmd->scan_begin_src) {
+ case TRIG_TIMER: /* periodic scanning */
+ timer = rtd_ns_to_timer(&cmd->scan_begin_arg,
+ TRIG_ROUND_NEAREST);
+ /* set PACER clock */
+ /*DPRINTK ("rtd520: loading %d into pacer\n", timer); */
+ RtdPacerCounter(dev, timer);
+
+ break;
+
+ case TRIG_EXT:
+ RtdPacerStartSource(dev, 1); /* EXTERNALy trigger pacer */
+ break;
+
+ default:
+ DPRINTK("rtd520: Warning! ignoring scan_begin_src mode %d\n",
+ cmd->scan_begin_src);
+ }
+
+ /* Sample timing within a scan */
+ switch (cmd->convert_src) {
+ case TRIG_TIMER: /* periodic */
+ if (cmd->chanlist_len > 1) { /* only needed for multi-channel */
+ timer = rtd_ns_to_timer(&cmd->convert_arg,
+ TRIG_ROUND_NEAREST);
+ /* setup BURST clock */
+ /*DPRINTK ("rtd520: loading %d into burst\n", timer); */
+ RtdBurstCounter(dev, timer);
+ }
+
+ break;
+
+ case TRIG_EXT: /* external */
+ RtdBurstStartSource(dev, 2); /* EXTERNALy trigger burst */
+ break;
+
+ default:
+ DPRINTK("rtd520: Warning! ignoring convert_src mode %d\n",
+ cmd->convert_src);
+ }
+ /* end configuration */
+
+ /* This doesn't seem to work. There is no way to clear an interrupt
+ that the priority controller has queued! */
+ RtdInterruptClearMask(dev, ~0); /* clear any existing flags */
+ RtdInterruptClear(dev);
+
+ /* TODO: allow multiple interrupt sources */
+ if (devpriv->transCount > 0) { /* transfer every N samples */
+ RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
+ DPRINTK("rtd520: Transferring every %d\n", devpriv->transCount);
+ } else { /* 1/2 FIFO transfers */
+#ifdef USE_DMA
+ devpriv->flags |= DMA0_ACTIVE;
+
+ /* point to first transfer in ring */
+ devpriv->dma0Offset = 0;
+ RtdDma0Mode(dev, DMA_MODE_BITS);
+ RtdDma0Next(dev, /* point to first block */
+ devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next);
+ RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL); /* set DMA trigger source */
+
+ RtdPlxInterruptWrite(dev, /* enable interrupt */
+ RtdPlxInterruptRead(dev) | ICS_DMA0_E);
+ /* Must be 2 steps. See PLX app note about "Starting a DMA transfer" */
+ RtdDma0Control(dev, PLX_DMA_EN_BIT); /* enable DMA (clear INTR?) */
+ RtdDma0Control(dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT); /*start DMA */
+ DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n",
+ RtdPlxInterruptRead(dev), devpriv->intMask);
+#else /* USE_DMA */
+ RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
+ DPRINTK("rtd520: Transferring every 1/2 FIFO\n");
+#endif /* USE_DMA */
+ }
+
+ /* BUG: start_src is ASSUMED to be TRIG_NOW */
+ /* BUG? it seems like things are running before the "start" */
+ RtdPacerStart(dev); /* Start PACER */
+ return 0;
+}
+
+/*
+ Stop a running data aquisition.
+*/
+static int rtd_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+{
+ u16 status;
+
+ RtdPacerStopSource(dev, 0); /* stop on SOFTWARE stop */
+ RtdPacerStop(dev); /* Stop PACER */
+ RtdAdcConversionSource(dev, 0); /* software trigger only */
+ RtdInterruptMask(dev, 0);
+ devpriv->aiCount = 0; /* stop and don't transfer any more */
+#ifdef USE_DMA
+ if (devpriv->flags & DMA0_ACTIVE) {
+ RtdPlxInterruptWrite(dev, /* disable any more interrupts */
+ RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
+ abort_dma(dev, 0);
+ devpriv->flags &= ~DMA0_ACTIVE;
+ }
+#endif /* USE_DMA */
+ status = RtdInterruptStatus(dev);
+ DPRINTK("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n", devpriv->intCount, status, 0xffff & RtdInterruptOverrunStatus(dev));
+ return 0;
+}
+
+/*
+ Given a desired period and the clock period (both in ns),
+ return the proper counter value (divider-1).
+ Sets the original period to be the true value.
+ Note: you have to check if the value is larger than the counter range!
+*/
+static int rtd_ns_to_timer_base(unsigned int *nanosec, /* desired period (in ns) */
+ int round_mode, int base)
+{ /* clock period (in ns) */
+ int divider;
+
+ switch (round_mode) {
+ case TRIG_ROUND_NEAREST:
+ default:
+ divider = (*nanosec + base / 2) / base;
+ break;
+ case TRIG_ROUND_DOWN:
+ divider = (*nanosec) / base;
+ break;
+ case TRIG_ROUND_UP:
+ divider = (*nanosec + base - 1) / base;
+ break;
+ }
+ if (divider < 2)
+ divider = 2; /* min is divide by 2 */
+
+ /* Note: we don't check for max, because different timers
+ have different ranges */
+
+ *nanosec = base * divider;
+ return divider - 1; /* countdown is divisor+1 */
+}
+
+/*
+ Given a desired period (in ns),
+ return the proper counter value (divider-1) for the internal clock.
+ Sets the original period to be the true value.
+*/
+static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
+{
+ return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE);
+}
+
+/*
+ Output one (or more) analog values to a single port as fast as possible.
+*/
+static int rtd_ao_winsn(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ int i;
+ int chan = CR_CHAN(insn->chanspec);
+ int range = CR_RANGE(insn->chanspec);
+
+ /* Configure the output range (table index matches the range values) */
+ RtdDacRange(dev, chan, range);
+
+ /* Writing a list of values to an AO channel is probably not
+ * very useful, but that's how the interface is defined. */
+ for (i = 0; i < insn->n; ++i) {
+ int val = data[i] << 3;
+ int stat = 0; /* initialize to avoid bogus warning */
+ int ii;
+
+ /* VERIFY: comedi range and offset conversions */
+
+ if ((range > 1) /* bipolar */
+ &&(data[i] < 2048)) {
+ /* offset and sign extend */
+ val = (((int)data[i]) - 2048) << 3;
+ } else { /* unipolor */
+ val = data[i] << 3;
+ }
+
+ DPRINTK("comedi: rtd520 DAC chan=%d range=%d writing %d as 0x%x\n", chan, range, data[i], val);
+
+ /* a typical programming sequence */
+ RtdDacFifoPut(dev, chan, val); /* put the value in */
+ RtdDacUpdate(dev, chan); /* trigger the conversion */
+
+ devpriv->aoValue[chan] = data[i]; /* save for read back */
+
+ for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) {
+ stat = RtdFifoStatus(dev);
+ /* 1 -> not empty */
+ if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY :
+ FS_DAC2_NOT_EMPTY))
+ break;
+ WAIT_QUIETLY;
+ }
+ if (ii >= RTD_DAC_TIMEOUT) {
+ DPRINTK("rtd520: Error: DAC never finished! FifoStatus=0x%x\n", stat ^ 0x6666);
+ return -ETIMEDOUT;
+ }
+ }
+
+ /* return the number of samples read/written */
+ return i;
+}
+
+/* AO subdevices should have a read insn as well as a write insn.
+ * Usually this means copying a value stored in devpriv. */
+static int rtd_ao_rinsn(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ int i;
+ int chan = CR_CHAN(insn->chanspec);
+
+ for (i = 0; i < insn->n; i++) {
+ data[i] = devpriv->aoValue[chan];
+ }
+
+ return i;
+}
+
+/*
+ Write a masked set of bits and the read back the port.
+ We track what the bits should be (i.e. we don't read the port first).
+
+ DIO devices are slightly special. Although it is possible to
+ * implement the insn_read/insn_write interface, it is much more
+ * useful to applications if you implement the insn_bits interface.
+ * This allows packed reading/writing of the DIO channels. The
+ * comedi core can convert between insn_bits and insn_read/write
+ */
+static int rtd_dio_insn_bits(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ if (insn->n != 2)
+ return -EINVAL;
+
+ /* The insn data is a mask in data[0] and the new data
+ * in data[1], each channel cooresponding to a bit. */
+ if (data[0]) {
+ s->state &= ~data[0];
+ s->state |= data[0] & data[1];
+
+ /* Write out the new digital output lines */
+ RtdDio0Write(dev, s->state);
+ }
+ /* on return, data[1] contains the value of the digital
+ * input lines. */
+ data[1] = RtdDio0Read(dev);
+
+ /*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */
+
+ return 2;
+}
+
+/*
+ Configure one bit on a IO port as Input or Output (hence the name :-).
+*/
+static int rtd_dio_insn_config(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ int chan = CR_CHAN(insn->chanspec);
+
+ /* The input or output configuration of each digital line is
+ * configured by a special insn_config instruction. chanspec
+ * contains the channel to be changed, and data[0] contains the
+ * value COMEDI_INPUT or COMEDI_OUTPUT. */
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_OUTPUT:
+ s->io_bits |= 1 << chan; /* 1 means Out */
+ break;
+ case INSN_CONFIG_DIO_INPUT:
+ s->io_bits &= ~(1 << chan);
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] =
+ (s->
+ io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ return insn->n;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits);
+ /* TODO support digital match interrupts and strobes */
+ RtdDioStatusWrite(dev, 0x01); /* make Dio0Ctrl point to direction */
+ RtdDio0CtrlWrite(dev, s->io_bits); /* set direction 1 means Out */
+ RtdDioStatusWrite(dev, 0); /* make Dio0Ctrl clear interrupts */
+
+ /* port1 can only be all input or all output */
+
+ /* there are also 2 user input lines and 2 user output lines */
+
+ return 1;
+}
+
+/*
+ * A convenient macro that defines init_module() and cleanup_module(),
+ * as necessary.
+ */
+COMEDI_PCI_INITCLEANUP(rtd520Driver, rtd520_pci_table);
diff --git a/drivers/staging/comedi/drivers/rtd520.h b/drivers/staging/comedi/drivers/rtd520.h
new file mode 100644
index 000000000000..0eb50b8e605e
--- /dev/null
+++ b/drivers/staging/comedi/drivers/rtd520.h
@@ -0,0 +1,412 @@
+/*
+ comedi/drivers/rtd520.h
+ Comedi driver defines for Real Time Devices (RTD) PCI4520/DM7520
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2001 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ Created by Dan Christian, NASA Ames Research Center.
+ See board notes in rtd520.c
+*/
+
+/*
+ LAS0 Runtime Area
+ Local Address Space 0 Offset Read Function Write Function
+*/
+#define LAS0_SPARE_00 0x0000 // - -
+#define LAS0_SPARE_04 0x0004 // - -
+#define LAS0_USER_IO 0x0008 // Read User Inputs Write User Outputs
+#define LAS0_SPARE_0C 0x000C // - -
+#define LAS0_ADC 0x0010 // Read FIFO Status Software A/D Start
+#define LAS0_DAC1 0x0014 // - Software D/A1 Update
+#define LAS0_DAC2 0x0018 // - Software D/A2 Update
+#define LAS0_SPARE_1C 0x001C // - -
+#define LAS0_SPARE_20 0x0020 // - -
+#define LAS0_DAC 0x0024 // - Software Simultaneous D/A1 and D/A2 Update
+#define LAS0_PACER 0x0028 // Software Pacer Start Software Pacer Stop
+#define LAS0_TIMER 0x002C // Read Timer Counters Status HDIN Software Trigger
+#define LAS0_IT 0x0030 // Read Interrupt Status Write Interrupt Enable Mask Register
+#define LAS0_CLEAR 0x0034 // Clear ITs set by Clear Mask Set Interrupt Clear Mask
+#define LAS0_OVERRUN 0x0038 // Read pending interrupts Clear Overrun Register
+#define LAS0_SPARE_3C 0x003C // - -
+
+/*
+ LAS0 Runtime Area Timer/Counter,Dig.IO
+ Name Local Address Function
+*/
+#define LAS0_PCLK 0x0040 // Pacer Clock value (24bit) Pacer Clock load (24bit)
+#define LAS0_BCLK 0x0044 // Burst Clock value (10bit) Burst Clock load (10bit)
+#define LAS0_ADC_SCNT 0x0048 // A/D Sample counter value (10bit) A/D Sample counter load (10bit)
+#define LAS0_DAC1_UCNT 0x004C // D/A1 Update counter value (10 bit) D/A1 Update counter load (10bit)
+#define LAS0_DAC2_UCNT 0x0050 // D/A2 Update counter value (10 bit) D/A2 Update counter load (10bit)
+#define LAS0_DCNT 0x0054 // Delay counter value (16 bit) Delay counter load (16bit)
+#define LAS0_ACNT 0x0058 // About counter value (16 bit) About counter load (16bit)
+#define LAS0_DAC_CLK 0x005C // DAC clock value (16bit) DAC clock load (16bit)
+#define LAS0_UTC0 0x0060 // 8254 TC Counter 0 User TC 0 value Load count in TC Counter 0
+#define LAS0_UTC1 0x0064 // 8254 TC Counter 1 User TC 1 value Load count in TC Counter 1
+#define LAS0_UTC2 0x0068 // 8254 TC Counter 2 User TC 2 value Load count in TC Counter 2
+#define LAS0_UTC_CTRL 0x006C // 8254 TC Control Word Program counter mode for TC
+#define LAS0_DIO0 0x0070 // Digital I/O Port 0 Read Port Digital I/O Port 0 Write Port
+#define LAS0_DIO1 0x0074 // Digital I/O Port 1 Read Port Digital I/O Port 1 Write Port
+#define LAS0_DIO0_CTRL 0x0078 // Clear digital IRQ status flag/read Clear digital chip/program Port 0
+#define LAS0_DIO_STATUS 0x007C // Read Digital I/O Status word Program digital control register &
+
+/*
+ LAS0 Setup Area
+ Name Local Address Function
+*/
+#define LAS0_BOARD_RESET 0x0100 // Board reset
+#define LAS0_DMA0_SRC 0x0104 // DMA 0 Sources select
+#define LAS0_DMA1_SRC 0x0108 // DMA 1 Sources select
+#define LAS0_ADC_CONVERSION 0x010C // A/D Conversion Signal select
+#define LAS0_BURST_START 0x0110 // Burst Clock Start Trigger select
+#define LAS0_PACER_START 0x0114 // Pacer Clock Start Trigger select
+#define LAS0_PACER_STOP 0x0118 // Pacer Clock Stop Trigger select
+#define LAS0_ACNT_STOP_ENABLE 0x011C // About Counter Stop Enable
+#define LAS0_PACER_REPEAT 0x0120 // Pacer Start Trigger Mode select
+#define LAS0_DIN_START 0x0124 // High Speed Digital Input Sampling Signal select
+#define LAS0_DIN_FIFO_CLEAR 0x0128 // Digital Input FIFO Clear
+#define LAS0_ADC_FIFO_CLEAR 0x012C // A/D FIFO Clear
+#define LAS0_CGT_WRITE 0x0130 // Channel Gain Table Write
+#define LAS0_CGL_WRITE 0x0134 // Channel Gain Latch Write
+#define LAS0_CG_DATA 0x0138 // Digital Table Write
+#define LAS0_CGT_ENABLE 0x013C // Channel Gain Table Enable
+#define LAS0_CG_ENABLE 0x0140 // Digital Table Enable
+#define LAS0_CGT_PAUSE 0x0144 // Table Pause Enable
+#define LAS0_CGT_RESET 0x0148 // Reset Channel Gain Table
+#define LAS0_CGT_CLEAR 0x014C // Clear Channel Gain Table
+#define LAS0_DAC1_CTRL 0x0150 // D/A1 output type/range
+#define LAS0_DAC1_SRC 0x0154 // D/A1 update source
+#define LAS0_DAC1_CYCLE 0x0158 // D/A1 cycle mode
+#define LAS0_DAC1_RESET 0x015C // D/A1 FIFO reset
+#define LAS0_DAC1_FIFO_CLEAR 0x0160 // D/A1 FIFO clear
+#define LAS0_DAC2_CTRL 0x0164 // D/A2 output type/range
+#define LAS0_DAC2_SRC 0x0168 // D/A2 update source
+#define LAS0_DAC2_CYCLE 0x016C // D/A2 cycle mode
+#define LAS0_DAC2_RESET 0x0170 // D/A2 FIFO reset
+#define LAS0_DAC2_FIFO_CLEAR 0x0174 // D/A2 FIFO clear
+#define LAS0_ADC_SCNT_SRC 0x0178 // A/D Sample Counter Source select
+#define LAS0_PACER_SELECT 0x0180 // Pacer Clock select
+#define LAS0_SBUS0_SRC 0x0184 // SyncBus 0 Source select
+#define LAS0_SBUS0_ENABLE 0x0188 // SyncBus 0 enable
+#define LAS0_SBUS1_SRC 0x018C // SyncBus 1 Source select
+#define LAS0_SBUS1_ENABLE 0x0190 // SyncBus 1 enable
+#define LAS0_SBUS2_SRC 0x0198 // SyncBus 2 Source select
+#define LAS0_SBUS2_ENABLE 0x019C // SyncBus 2 enable
+#define LAS0_ETRG_POLARITY 0x01A4 // External Trigger polarity select
+#define LAS0_EINT_POLARITY 0x01A8 // External Interrupt polarity select
+#define LAS0_UTC0_CLOCK 0x01AC // UTC0 Clock select
+#define LAS0_UTC0_GATE 0x01B0 // UTC0 Gate select
+#define LAS0_UTC1_CLOCK 0x01B4 // UTC1 Clock select
+#define LAS0_UTC1_GATE 0x01B8 // UTC1 Gate select
+#define LAS0_UTC2_CLOCK 0x01BC // UTC2 Clock select
+#define LAS0_UTC2_GATE 0x01C0 // UTC2 Gate select
+#define LAS0_UOUT0_SELECT 0x01C4 // User Output 0 source select
+#define LAS0_UOUT1_SELECT 0x01C8 // User Output 1 source select
+#define LAS0_DMA0_RESET 0x01CC // DMA0 Request state machine reset
+#define LAS0_DMA1_RESET 0x01D0 // DMA1 Request state machine reset
+
+/*
+ LAS1
+ Name Local Address Function
+*/
+#define LAS1_ADC_FIFO 0x0000 // Read A/D FIFO (16bit) -
+#define LAS1_HDIO_FIFO 0x0004 // Read High Speed Digital Input FIFO (16bit) -
+#define LAS1_DAC1_FIFO 0x0008 // - Write D/A1 FIFO (16bit)
+#define LAS1_DAC2_FIFO 0x000C // - Write D/A2 FIFO (16bit)
+
+/*
+ LCFG: PLX 9080 local config & runtime registers
+ Name Local Address Function
+*/
+#define LCFG_ITCSR 0x0068 // INTCSR, Interrupt Control/Status Register
+#define LCFG_DMAMODE0 0x0080 // DMA Channel 0 Mode Register
+#define LCFG_DMAPADR0 0x0084 // DMA Channel 0 PCI Address Register
+#define LCFG_DMALADR0 0x0088 // DMA Channel 0 Local Address Reg
+#define LCFG_DMASIZ0 0x008C // DMA Channel 0 Transfer Size (Bytes) Register
+#define LCFG_DMADPR0 0x0090 // DMA Channel 0 Descriptor Pointer Register
+#define LCFG_DMAMODE1 0x0094 // DMA Channel 1 Mode Register
+#define LCFG_DMAPADR1 0x0098 // DMA Channel 1 PCI Address Register
+#define LCFG_DMALADR1 0x009C // DMA Channel 1 Local Address Register
+#define LCFG_DMASIZ1 0x00A0 // DMA Channel 1 Transfer Size (Bytes) Register
+#define LCFG_DMADPR1 0x00A4 // DMA Channel 1 Descriptor Pointer Register
+#define LCFG_DMACSR0 0x00A8 // DMA Channel 0 Command/Status Register
+#define LCFG_DMACSR1 0x00A9 // DMA Channel 0 Command/Status Register
+#define LCFG_DMAARB 0x00AC // DMA Arbitration Register
+#define LCFG_DMATHR 0x00B0 // DMA Threshold Register
+
+/*======================================================================
+ Resister bit definitions
+======================================================================*/
+
+// FIFO Status Word Bits (RtdFifoStatus)
+#define FS_DAC1_NOT_EMPTY 0x0001 // D0 - DAC1 FIFO not empty
+#define FS_DAC1_HEMPTY 0x0002 // D1 - DAC1 FIFO half empty
+#define FS_DAC1_NOT_FULL 0x0004 // D2 - DAC1 FIFO not full
+#define FS_DAC2_NOT_EMPTY 0x0010 // D4 - DAC2 FIFO not empty
+#define FS_DAC2_HEMPTY 0x0020 // D5 - DAC2 FIFO half empty
+#define FS_DAC2_NOT_FULL 0x0040 // D6 - DAC2 FIFO not full
+#define FS_ADC_NOT_EMPTY 0x0100 // D8 - ADC FIFO not empty
+#define FS_ADC_HEMPTY 0x0200 // D9 - ADC FIFO half empty
+#define FS_ADC_NOT_FULL 0x0400 // D10 - ADC FIFO not full
+#define FS_DIN_NOT_EMPTY 0x1000 // D12 - DIN FIFO not empty
+#define FS_DIN_HEMPTY 0x2000 // D13 - DIN FIFO half empty
+#define FS_DIN_NOT_FULL 0x4000 // D14 - DIN FIFO not full
+
+// Timer Status Word Bits (GetTimerStatus)
+#define TS_PCLK_GATE 0x0001
+// D0 - Pacer Clock Gate [0 - gated, 1 - enabled]
+#define TS_BCLK_GATE 0x0002
+// D1 - Burst Clock Gate [0 - disabled, 1 - running]
+#define TS_DCNT_GATE 0x0004
+// D2 - Pacer Clock Delayed Start Trigger [0 - delay over, 1 - delay in
+// progress]
+#define TS_ACNT_GATE 0x0008
+// D3 - Pacer Clock About Trigger [0 - completed, 1 - in progress]
+#define TS_PCLK_RUN 0x0010
+// D4 - Pacer Clock Shutdown Flag [0 - Pacer Clock cannot be start
+// triggered only by Software Pacer Start Command, 1 - Pacer Clock can
+// be start triggered]
+
+// External Trigger polarity select
+// External Interrupt polarity select
+#define POL_POSITIVE 0x0 // positive edge
+#define POL_NEGATIVE 0x1 // negative edge
+
+// User Output Signal select (SetUout0Source, SetUout1Source)
+#define UOUT_ADC 0x0 // A/D Conversion Signal
+#define UOUT_DAC1 0x1 // D/A1 Update
+#define UOUT_DAC2 0x2 // D/A2 Update
+#define UOUT_SOFTWARE 0x3 // Software Programmable
+
+// Pacer clock select (SetPacerSource)
+#define PCLK_INTERNAL 1 // Internal Pacer Clock
+#define PCLK_EXTERNAL 0 // External Pacer Clock
+
+// A/D Sample Counter Sources (SetAdcntSource, SetupSampleCounter)
+#define ADC_SCNT_CGT_RESET 0x0 // needs restart with StartPacer
+#define ADC_SCNT_FIFO_WRITE 0x1
+
+// A/D Conversion Signal Select (for SetConversionSelect)
+#define ADC_START_SOFTWARE 0x0 // Software A/D Start
+#define ADC_START_PCLK 0x1 // Pacer Clock (Ext. Int. see Func.509)
+#define ADC_START_BCLK 0x2 // Burst Clock
+#define ADC_START_DIGITAL_IT 0x3 // Digital Interrupt
+#define ADC_START_DAC1_MARKER1 0x4 // D/A 1 Data Marker 1
+#define ADC_START_DAC2_MARKER1 0x5 // D/A 2 Data Marker 1
+#define ADC_START_SBUS0 0x6 // SyncBus 0
+#define ADC_START_SBUS1 0x7 // SyncBus 1
+#define ADC_START_SBUS2 0x8 // SyncBus 2
+
+// Burst Clock start trigger select (SetBurstStart)
+#define BCLK_START_SOFTWARE 0x0 // Software A/D Start (StartBurst)
+#define BCLK_START_PCLK 0x1 // Pacer Clock
+#define BCLK_START_ETRIG 0x2 // External Trigger
+#define BCLK_START_DIGITAL_IT 0x3 // Digital Interrupt
+#define BCLK_START_SBUS0 0x4 // SyncBus 0
+#define BCLK_START_SBUS1 0x5 // SyncBus 1
+#define BCLK_START_SBUS2 0x6 // SyncBus 2
+
+// Pacer Clock start trigger select (SetPacerStart)
+#define PCLK_START_SOFTWARE 0x0 // Software Pacer Start (StartPacer)
+#define PCLK_START_ETRIG 0x1 // External trigger
+#define PCLK_START_DIGITAL_IT 0x2 // Digital interrupt
+#define PCLK_START_UTC2 0x3 // User TC 2 out
+#define PCLK_START_SBUS0 0x4 // SyncBus 0
+#define PCLK_START_SBUS1 0x5 // SyncBus 1
+#define PCLK_START_SBUS2 0x6 // SyncBus 2
+#define PCLK_START_D_SOFTWARE 0x8 // Delayed Software Pacer Start
+#define PCLK_START_D_ETRIG 0x9 // Delayed external trigger
+#define PCLK_START_D_DIGITAL_IT 0xA // Delayed digital interrupt
+#define PCLK_START_D_UTC2 0xB // Delayed User TC 2 out
+#define PCLK_START_D_SBUS0 0xC // Delayed SyncBus 0
+#define PCLK_START_D_SBUS1 0xD // Delayed SyncBus 1
+#define PCLK_START_D_SBUS2 0xE // Delayed SyncBus 2
+#define PCLK_START_ETRIG_GATED 0xF // External Trigger Gated controlled mode
+
+// Pacer Clock Stop Trigger select (SetPacerStop)
+#define PCLK_STOP_SOFTWARE 0x0 // Software Pacer Stop (StopPacer)
+#define PCLK_STOP_ETRIG 0x1 // External Trigger
+#define PCLK_STOP_DIGITAL_IT 0x2 // Digital Interrupt
+#define PCLK_STOP_ACNT 0x3 // About Counter
+#define PCLK_STOP_UTC2 0x4 // User TC2 out
+#define PCLK_STOP_SBUS0 0x5 // SyncBus 0
+#define PCLK_STOP_SBUS1 0x6 // SyncBus 1
+#define PCLK_STOP_SBUS2 0x7 // SyncBus 2
+#define PCLK_STOP_A_SOFTWARE 0x8 // About Software Pacer Stop
+#define PCLK_STOP_A_ETRIG 0x9 // About External Trigger
+#define PCLK_STOP_A_DIGITAL_IT 0xA // About Digital Interrupt
+#define PCLK_STOP_A_UTC2 0xC // About User TC2 out
+#define PCLK_STOP_A_SBUS0 0xD // About SyncBus 0
+#define PCLK_STOP_A_SBUS1 0xE // About SyncBus 1
+#define PCLK_STOP_A_SBUS2 0xF // About SyncBus 2
+
+// About Counter Stop Enable
+#define ACNT_STOP 0x0 // stop enable
+#define ACNT_NO_STOP 0x1 // stop disabled
+
+// DAC update source (SetDAC1Start & SetDAC2Start)
+#define DAC_START_SOFTWARE 0x0 // Software Update
+#define DAC_START_CGT 0x1 // CGT controlled Update
+#define DAC_START_DAC_CLK 0x2 // D/A Clock
+#define DAC_START_EPCLK 0x3 // External Pacer Clock
+#define DAC_START_SBUS0 0x4 // SyncBus 0
+#define DAC_START_SBUS1 0x5 // SyncBus 1
+#define DAC_START_SBUS2 0x6 // SyncBus 2
+
+// DAC Cycle Mode (SetDAC1Cycle, SetDAC2Cycle, SetupDAC)
+#define DAC_CYCLE_SINGLE 0x0 // not cycle
+#define DAC_CYCLE_MULTI 0x1 // cycle
+
+// 8254 Operation Modes (Set8254Mode, SetupTimerCounter)
+#define M8254_EVENT_COUNTER 0 // Event Counter
+#define M8254_HW_ONE_SHOT 1 // Hardware-Retriggerable One-Shot
+#define M8254_RATE_GENERATOR 2 // Rate Generator
+#define M8254_SQUARE_WAVE 3 // Square Wave Mode
+#define M8254_SW_STROBE 4 // Software Triggered Strobe
+#define M8254_HW_STROBE 5 // Hardware Triggered Strobe (Retriggerable)
+
+// User Timer/Counter 0 Clock Select (SetUtc0Clock)
+#define CUTC0_8MHZ 0x0 // 8MHz
+#define CUTC0_EXT_TC_CLOCK1 0x1 // Ext. TC Clock 1
+#define CUTC0_EXT_TC_CLOCK2 0x2 // Ext. TC Clock 2
+#define CUTC0_EXT_PCLK 0x3 // Ext. Pacer Clock
+
+// User Timer/Counter 1 Clock Select (SetUtc1Clock)
+#define CUTC1_8MHZ 0x0 // 8MHz
+#define CUTC1_EXT_TC_CLOCK1 0x1 // Ext. TC Clock 1
+#define CUTC1_EXT_TC_CLOCK2 0x2 // Ext. TC Clock 2
+#define CUTC1_EXT_PCLK 0x3 // Ext. Pacer Clock
+#define CUTC1_UTC0_OUT 0x4 // User Timer/Counter 0 out
+#define CUTC1_DIN_SIGNAL 0x5 // High-Speed Digital Input Sampling signal
+
+// User Timer/Counter 2 Clock Select (SetUtc2Clock)
+#define CUTC2_8MHZ 0x0 // 8MHz
+#define CUTC2_EXT_TC_CLOCK1 0x1 // Ext. TC Clock 1
+#define CUTC2_EXT_TC_CLOCK2 0x2 // Ext. TC Clock 2
+#define CUTC2_EXT_PCLK 0x3 // Ext. Pacer Clock
+#define CUTC2_UTC1_OUT 0x4 // User Timer/Counter 1 out
+
+// User Timer/Counter 0 Gate Select (SetUtc0Gate)
+#define GUTC0_NOT_GATED 0x0 // Not gated
+#define GUTC0_GATED 0x1 // Gated
+#define GUTC0_EXT_TC_GATE1 0x2 // Ext. TC Gate 1
+#define GUTC0_EXT_TC_GATE2 0x3 // Ext. TC Gate 2
+
+// User Timer/Counter 1 Gate Select (SetUtc1Gate)
+#define GUTC1_NOT_GATED 0x0 // Not gated
+#define GUTC1_GATED 0x1 // Gated
+#define GUTC1_EXT_TC_GATE1 0x2 // Ext. TC Gate 1
+#define GUTC1_EXT_TC_GATE2 0x3 // Ext. TC Gate 2
+#define GUTC1_UTC0_OUT 0x4 // User Timer/Counter 0 out
+
+// User Timer/Counter 2 Gate Select (SetUtc2Gate)
+#define GUTC2_NOT_GATED 0x0 // Not gated
+#define GUTC2_GATED 0x1 // Gated
+#define GUTC2_EXT_TC_GATE1 0x2 // Ext. TC Gate 1
+#define GUTC2_EXT_TC_GATE2 0x3 // Ext. TC Gate 2
+#define GUTC2_UTC1_OUT 0x4 // User Timer/Counter 1 out
+
+// Interrupt Source Masks (SetITMask, ClearITMask, GetITStatus)
+#define IRQM_ADC_FIFO_WRITE 0x0001 // ADC FIFO Write
+#define IRQM_CGT_RESET 0x0002 // Reset CGT
+#define IRQM_CGT_PAUSE 0x0008 // Pause CGT
+#define IRQM_ADC_ABOUT_CNT 0x0010 // About Counter out
+#define IRQM_ADC_DELAY_CNT 0x0020 // Delay Counter out
+#define IRQM_ADC_SAMPLE_CNT 0x0040 // ADC Sample Counter
+#define IRQM_DAC1_UCNT 0x0080 // DAC1 Update Counter
+#define IRQM_DAC2_UCNT 0x0100 // DAC2 Update Counter
+#define IRQM_UTC1 0x0200 // User TC1 out
+#define IRQM_UTC1_INV 0x0400 // User TC1 out, inverted
+#define IRQM_UTC2 0x0800 // User TC2 out
+#define IRQM_DIGITAL_IT 0x1000 // Digital Interrupt
+#define IRQM_EXTERNAL_IT 0x2000 // External Interrupt
+#define IRQM_ETRIG_RISING 0x4000 // External Trigger rising-edge
+#define IRQM_ETRIG_FALLING 0x8000 // External Trigger falling-edge
+
+// DMA Request Sources (LAS0)
+#define DMAS_DISABLED 0x0 // DMA Disabled
+#define DMAS_ADC_SCNT 0x1 // ADC Sample Counter
+#define DMAS_DAC1_UCNT 0x2 // D/A1 Update Counter
+#define DMAS_DAC2_UCNT 0x3 // D/A2 Update Counter
+#define DMAS_UTC1 0x4 // User TC1 out
+#define DMAS_ADFIFO_HALF_FULL 0x8 // A/D FIFO half full
+#define DMAS_DAC1_FIFO_HALF_EMPTY 0x9 // D/A1 FIFO half empty
+#define DMAS_DAC2_FIFO_HALF_EMPTY 0xA // D/A2 FIFO half empty
+
+// DMA Local Addresses (0x40000000+LAS1 offset)
+#define DMALADDR_ADC 0x40000000 // A/D FIFO
+#define DMALADDR_HDIN 0x40000004 // High Speed Digital Input FIFO
+#define DMALADDR_DAC1 0x40000008 // D/A1 FIFO
+#define DMALADDR_DAC2 0x4000000C // D/A2 FIFO
+
+// Port 0 compare modes (SetDIO0CompareMode)
+#define DIO_MODE_EVENT 0 // Event Mode
+#define DIO_MODE_MATCH 1 // Match Mode
+
+// Digital Table Enable (Port 1 disable)
+#define DTBL_DISABLE 0 // Enable Digital Table
+#define DTBL_ENABLE 1 // Disable Digital Table
+
+// Sampling Signal for High Speed Digital Input (SetHdinStart)
+#define HDIN_SOFTWARE 0x0 // Software Trigger
+#define HDIN_ADC 0x1 // A/D Conversion Signal
+#define HDIN_UTC0 0x2 // User TC out 0
+#define HDIN_UTC1 0x3 // User TC out 1
+#define HDIN_UTC2 0x4 // User TC out 2
+#define HDIN_EPCLK 0x5 // External Pacer Clock
+#define HDIN_ETRG 0x6 // External Trigger
+
+// Channel Gain Table / Channel Gain Latch
+#define CSC_LATCH 0 // Channel Gain Latch mode
+#define CSC_CGT 1 // Channel Gain Table mode
+
+// Channel Gain Table Pause Enable
+#define CGT_PAUSE_DISABLE 0 // Channel Gain Table Pause Disable
+#define CGT_PAUSE_ENABLE 1 // Channel Gain Table Pause Enable
+
+// DAC output type/range (p63)
+#define AOUT_UNIP5 0 // 0..+5 Volt
+#define AOUT_UNIP10 1 // 0..+10 Volt
+#define AOUT_BIP5 2 // -5..+5 Volt
+#define AOUT_BIP10 3 // -10..+10 Volt
+
+// Ghannel Gain Table field definitions (p61)
+// Gain
+#define GAIN1 0
+#define GAIN2 1
+#define GAIN4 2
+#define GAIN8 3
+#define GAIN16 4
+#define GAIN32 5
+#define GAIN64 6
+#define GAIN128 7
+
+// Input range/polarity
+#define AIN_BIP5 0 // -5..+5 Volt
+#define AIN_BIP10 1 // -10..+10 Volt
+#define AIN_UNIP10 2 // 0..+10 Volt
+
+// non referenced single ended select bit
+#define NRSE_AGND 0 // AGND referenced SE input
+#define NRSE_AINS 1 // AIN SENSE referenced SE input
+
+// single ended vs differential
+#define GND_SE 0 // Single-Ended
+#define GND_DIFF 1 // Differential
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
new file mode 100644
index 000000000000..469ee8c474c9
--- /dev/null
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -0,0 +1,3254 @@
+/*
+ comedi/drivers/s626.c
+ Sensoray s626 Comedi driver
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+
+ Based on Sensoray Model 626 Linux driver Version 0.2
+ Copyright (C) 2002-2004 Sensoray Co., Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/*
+Driver: s626
+Description: Sensoray 626 driver
+Devices: [Sensoray] 626 (s626)
+Authors: Gianluca Palli <gpalli@deis.unibo.it>,
+Updated: Fri, 15 Feb 2008 10:28:42 +0000
+Status: experimental
+
+Configuration options:
+ [0] - PCI bus of device (optional)
+ [1] - PCI slot of device (optional)
+ If bus/slot is not specified, the first supported
+ PCI device found will be used.
+
+INSN_CONFIG instructions:
+ analog input:
+ none
+
+ analog output:
+ none
+
+ digital channel:
+ s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
+ supported configuration options:
+ INSN_CONFIG_DIO_QUERY
+ COMEDI_INPUT
+ COMEDI_OUTPUT
+
+ encoder:
+ Every channel must be configured before reading.
+
+ Example code
+
+ insn.insn=INSN_CONFIG; //configuration instruction
+ insn.n=1; //number of operation (must be 1)
+ insn.data=&initialvalue; //initial value loaded into encoder
+ //during configuration
+ insn.subdev=5; //encoder subdevice
+ insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
+ //to configure
+
+ comedi_do_insn(cf,&insn); //executing configuration
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "../comedidev.h"
+
+#include "comedi_pci.h"
+
+#include "comedi_fc.h"
+#include "s626.h"
+
+MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>");
+MODULE_DESCRIPTION("Sensoray 626 Comedi driver module");
+MODULE_LICENSE("GPL");
+
+typedef struct s626_board_struct {
+ const char *name;
+ int ai_chans;
+ int ai_bits;
+ int ao_chans;
+ int ao_bits;
+ int dio_chans;
+ int dio_banks;
+ int enc_chans;
+} s626_board;
+
+static const s626_board s626_boards[] = {
+ {
+ name: "s626",
+ ai_chans:S626_ADC_CHANNELS,
+ ai_bits: 14,
+ ao_chans:S626_DAC_CHANNELS,
+ ao_bits: 13,
+ dio_chans:S626_DIO_CHANNELS,
+ dio_banks:S626_DIO_BANKS,
+ enc_chans:S626_ENCODER_CHANNELS,
+ }
+};
+
+#define thisboard ((const s626_board *)dev->board_ptr)
+#define PCI_VENDOR_ID_S626 0x1131
+#define PCI_DEVICE_ID_S626 0x7146
+
+static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
+ {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ 0},
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, s626_pci_table);
+
+static int s626_attach(comedi_device * dev, comedi_devconfig * it);
+static int s626_detach(comedi_device * dev);
+
+static comedi_driver driver_s626 = {
+ driver_name:"s626",
+ module:THIS_MODULE,
+ attach:s626_attach,
+ detach:s626_detach,
+};
+
+typedef struct {
+ struct pci_dev *pdev;
+ void *base_addr;
+ int got_regions;
+ short allocatedBuf;
+ uint8_t ai_cmd_running; // ai_cmd is running
+ uint8_t ai_continous; // continous aquisition
+ int ai_sample_count; // number of samples to aquire
+ unsigned int ai_sample_timer; // time between samples in
+ // units of the timer
+ int ai_convert_count; // conversion counter
+ unsigned int ai_convert_timer; // time between conversion in
+ // units of the timer
+ uint16_t CounterIntEnabs; //Counter interrupt enable
+ //mask for MISC2 register.
+ uint8_t AdcItems; //Number of items in ADC poll
+ //list.
+ DMABUF RPSBuf; //DMA buffer used to hold ADC
+ //(RPS1) program.
+ DMABUF ANABuf; //DMA buffer used to receive
+ //ADC data and hold DAC data.
+ uint32_t *pDacWBuf; //Pointer to logical adrs of
+ //DMA buffer used to hold DAC
+ //data.
+ uint16_t Dacpol; //Image of DAC polarity
+ //register.
+ uint8_t TrimSetpoint[12]; //Images of TrimDAC setpoints.
+ //registers.
+ uint16_t ChargeEnabled; //Image of MISC2 Battery
+ //Charge Enabled (0 or
+ //WRMISC2_CHARGE_ENABLE).
+ uint16_t WDInterval; //Image of MISC2 watchdog
+ //interval control bits.
+ uint32_t I2CAdrs; //I2C device address for
+ //onboard EEPROM (board rev
+ //dependent).
+ // short I2Cards;
+ lsampl_t ao_readback[S626_DAC_CHANNELS];
+} s626_private;
+
+typedef struct {
+ uint16_t RDDIn;
+ uint16_t WRDOut;
+ uint16_t RDEdgSel;
+ uint16_t WREdgSel;
+ uint16_t RDCapSel;
+ uint16_t WRCapSel;
+ uint16_t RDCapFlg;
+ uint16_t RDIntSel;
+ uint16_t WRIntSel;
+} dio_private;
+
+static dio_private dio_private_A = {
+ RDDIn:LP_RDDINA,
+ WRDOut:LP_WRDOUTA,
+ RDEdgSel:LP_RDEDGSELA,
+ WREdgSel:LP_WREDGSELA,
+ RDCapSel:LP_RDCAPSELA,
+ WRCapSel:LP_WRCAPSELA,
+ RDCapFlg:LP_RDCAPFLGA,
+ RDIntSel:LP_RDINTSELA,
+ WRIntSel:LP_WRINTSELA,
+};
+
+static dio_private dio_private_B = {
+ RDDIn:LP_RDDINB,
+ WRDOut:LP_WRDOUTB,
+ RDEdgSel:LP_RDEDGSELB,
+ WREdgSel:LP_WREDGSELB,
+ RDCapSel:LP_RDCAPSELB,
+ WRCapSel:LP_WRCAPSELB,
+ RDCapFlg:LP_RDCAPFLGB,
+ RDIntSel:LP_RDINTSELB,
+ WRIntSel:LP_WRINTSELB,
+};
+
+static dio_private dio_private_C = {
+ RDDIn:LP_RDDINC,
+ WRDOut:LP_WRDOUTC,
+ RDEdgSel:LP_RDEDGSELC,
+ WREdgSel:LP_WREDGSELC,
+ RDCapSel:LP_RDCAPSELC,
+ WRCapSel:LP_WRCAPSELC,
+ RDCapFlg:LP_RDCAPFLGC,
+ RDIntSel:LP_RDINTSELC,
+ WRIntSel:LP_WRINTSELC,
+};
+
+/* to group dio devices (48 bits mask and data are not allowed ???)
+static dio_private *dio_private_word[]={
+ &dio_private_A,
+ &dio_private_B,
+ &dio_private_C,
+};
+*/
+
+#define devpriv ((s626_private *)dev->private)
+#define diopriv ((dio_private *)s->private)
+
+COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table);
+
+//ioctl routines
+static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); */
+static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s);
+static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ comedi_cmd * cmd);
+static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s);
+static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_dio_set_irq(comedi_device * dev, unsigned int chan);
+static int s626_dio_reset_irq(comedi_device * dev, unsigned int gruop,
+ unsigned int mask);
+static int s626_dio_clear_irq(comedi_device * dev);
+static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data);
+static int s626_ns_to_timer(int *nanosec, int round_mode);
+static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd);
+static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
+ unsigned int trignum);
+static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG);
+static lsampl_t s626_ai_reg_to_uint(int data);
+/* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data); */
+
+//end ioctl routines
+
+//internal routines
+static void s626_dio_init(comedi_device * dev);
+static void ResetADC(comedi_device * dev, uint8_t * ppl);
+static void LoadTrimDACs(comedi_device * dev);
+static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan,
+ uint8_t DacData);
+static uint8_t I2Cread(comedi_device * dev, uint8_t addr);
+static uint32_t I2Chandshake(comedi_device * dev, uint32_t val);
+static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata);
+static void SendDAC(comedi_device * dev, uint32_t val);
+static void WriteMISC2(comedi_device * dev, uint16_t NewImage);
+static void DEBItransfer(comedi_device * dev);
+static uint16_t DEBIread(comedi_device * dev, uint16_t addr);
+static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata);
+static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask,
+ uint16_t wdata);
+static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize);
+
+// COUNTER OBJECT ------------------------------------------------
+typedef struct enc_private_struct {
+ // Pointers to functions that differ for A and B counters:
+ uint16_t(*GetEnable) (comedi_device * dev, struct enc_private_struct *); //Return clock enable.
+ uint16_t(*GetIntSrc) (comedi_device * dev, struct enc_private_struct *); //Return interrupt source.
+ uint16_t(*GetLoadTrig) (comedi_device * dev, struct enc_private_struct *); //Return preload trigger source.
+ uint16_t(*GetMode) (comedi_device * dev, struct enc_private_struct *); //Return standardized operating mode.
+ void (*PulseIndex) (comedi_device * dev, struct enc_private_struct *); //Generate soft index strobe.
+ void (*SetEnable) (comedi_device * dev, struct enc_private_struct *, uint16_t enab); //Program clock enable.
+ void (*SetIntSrc) (comedi_device * dev, struct enc_private_struct *, uint16_t IntSource); //Program interrupt source.
+ void (*SetLoadTrig) (comedi_device * dev, struct enc_private_struct *, uint16_t Trig); //Program preload trigger source.
+ void (*SetMode) (comedi_device * dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc); //Program standardized operating mode.
+ void (*ResetCapFlags) (comedi_device * dev, struct enc_private_struct *); //Reset event capture flags.
+
+ uint16_t MyCRA; // Address of CRA register.
+ uint16_t MyCRB; // Address of CRB register.
+ uint16_t MyLatchLsw; // Address of Latch least-significant-word
+ // register.
+ uint16_t MyEventBits[4]; // Bit translations for IntSrc -->RDMISC2.
+} enc_private; //counter object
+
+#define encpriv ((enc_private *)(dev->subdevices+5)->private)
+
+//counters routines
+static void s626_timer_load(comedi_device * dev, enc_private * k, int tick);
+static uint32_t ReadLatch(comedi_device * dev, enc_private * k);
+static void ResetCapFlags_A(comedi_device * dev, enc_private * k);
+static void ResetCapFlags_B(comedi_device * dev, enc_private * k);
+static uint16_t GetMode_A(comedi_device * dev, enc_private * k);
+static uint16_t GetMode_B(comedi_device * dev, enc_private * k);
+static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup,
+ uint16_t DisableIntSrc);
+static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup,
+ uint16_t DisableIntSrc);
+static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab);
+static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab);
+static uint16_t GetEnable_A(comedi_device * dev, enc_private * k);
+static uint16_t GetEnable_B(comedi_device * dev, enc_private * k);
+static void SetLatchSource(comedi_device * dev, enc_private * k,
+ uint16_t value);
+/* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ); */
+static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig);
+static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig);
+static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k);
+static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k);
+static void SetIntSrc_B(comedi_device * dev, enc_private * k,
+ uint16_t IntSource);
+static void SetIntSrc_A(comedi_device * dev, enc_private * k,
+ uint16_t IntSource);
+static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k);
+static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k);
+/* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) ; */
+/* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) ; */
+/* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ); */
+/* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) ; */
+/* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */
+/* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ); */
+/* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */
+/* static uint16_t GetIndexSrc( comedi_device *dev,enc_private *k ); */
+static void PulseIndex_A(comedi_device * dev, enc_private * k);
+static void PulseIndex_B(comedi_device * dev, enc_private * k);
+static void Preload(comedi_device * dev, enc_private * k, uint32_t value);
+static void CountersInit(comedi_device * dev);
+//end internal routines
+
+/////////////////////////////////////////////////////////////////////////
+// Counter objects constructor.
+
+// Counter overflow/index event flag masks for RDMISC2.
+#define INDXMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 - 1 ) : ( (C) * 2 + 4 ) ) )
+#define OVERMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 + 5 ) : ( (C) * 2 + 10 ) ) )
+#define EVBITS(C) { 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) }
+
+// Translation table to map IntSrc into equivalent RDMISC2 event flag
+// bits.
+//static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) };
+
+/* enc_private; */
+static enc_private enc_private_data[] = {
+ {
+ GetEnable:GetEnable_A,
+ GetIntSrc:GetIntSrc_A,
+ GetLoadTrig:GetLoadTrig_A,
+ GetMode: GetMode_A,
+ PulseIndex:PulseIndex_A,
+ SetEnable:SetEnable_A,
+ SetIntSrc:SetIntSrc_A,
+ SetLoadTrig:SetLoadTrig_A,
+ SetMode: SetMode_A,
+ ResetCapFlags:ResetCapFlags_A,
+ MyCRA: LP_CR0A,
+ MyCRB: LP_CR0B,
+ MyLatchLsw:LP_CNTR0ALSW,
+ MyEventBits:EVBITS(0),
+ },
+ {
+ GetEnable:GetEnable_A,
+ GetIntSrc:GetIntSrc_A,
+ GetLoadTrig:GetLoadTrig_A,
+ GetMode: GetMode_A,
+ PulseIndex:PulseIndex_A,
+ SetEnable:SetEnable_A,
+ SetIntSrc:SetIntSrc_A,
+ SetLoadTrig:SetLoadTrig_A,
+ SetMode: SetMode_A,
+ ResetCapFlags:ResetCapFlags_A,
+ MyCRA: LP_CR1A,
+ MyCRB: LP_CR1B,
+ MyLatchLsw:LP_CNTR1ALSW,
+ MyEventBits:EVBITS(1),
+ },
+ {
+ GetEnable:GetEnable_A,
+ GetIntSrc:GetIntSrc_A,
+ GetLoadTrig:GetLoadTrig_A,
+ GetMode: GetMode_A,
+ PulseIndex:PulseIndex_A,
+ SetEnable:SetEnable_A,
+ SetIntSrc:SetIntSrc_A,
+ SetLoadTrig:SetLoadTrig_A,
+ SetMode: SetMode_A,
+ ResetCapFlags:ResetCapFlags_A,
+ MyCRA: LP_CR2A,
+ MyCRB: LP_CR2B,
+ MyLatchLsw:LP_CNTR2ALSW,
+ MyEventBits:EVBITS(2),
+ },
+ {
+ GetEnable:GetEnable_B,
+ GetIntSrc:GetIntSrc_B,
+ GetLoadTrig:GetLoadTrig_B,
+ GetMode: GetMode_B,
+ PulseIndex:PulseIndex_B,
+ SetEnable:SetEnable_B,
+ SetIntSrc:SetIntSrc_B,
+ SetLoadTrig:SetLoadTrig_B,
+ SetMode: SetMode_B,
+ ResetCapFlags:ResetCapFlags_B,
+ MyCRA: LP_CR0A,
+ MyCRB: LP_CR0B,
+ MyLatchLsw:LP_CNTR0BLSW,
+ MyEventBits:EVBITS(3),
+ },
+ {
+ GetEnable:GetEnable_B,
+ GetIntSrc:GetIntSrc_B,
+ GetLoadTrig:GetLoadTrig_B,
+ GetMode: GetMode_B,
+ PulseIndex:PulseIndex_B,
+ SetEnable:SetEnable_B,
+ SetIntSrc:SetIntSrc_B,
+ SetLoadTrig:SetLoadTrig_B,
+ SetMode: SetMode_B,
+ ResetCapFlags:ResetCapFlags_B,
+ MyCRA: LP_CR1A,
+ MyCRB: LP_CR1B,
+ MyLatchLsw:LP_CNTR1BLSW,
+ MyEventBits:EVBITS(4),
+ },
+ {
+ GetEnable:GetEnable_B,
+ GetIntSrc:GetIntSrc_B,
+ GetLoadTrig:GetLoadTrig_B,
+ GetMode: GetMode_B,
+ PulseIndex:PulseIndex_B,
+ SetEnable:SetEnable_B,
+ SetIntSrc:SetIntSrc_B,
+ SetLoadTrig:SetLoadTrig_B,
+ SetMode: SetMode_B,
+ ResetCapFlags:ResetCapFlags_B,
+ MyCRA: LP_CR2A,
+ MyCRB: LP_CR2B,
+ MyLatchLsw:LP_CNTR2BLSW,
+ MyEventBits:EVBITS(5),
+ },
+};
+
+// enab/disable a function or test status bit(s) that are accessed
+// through Main Control Registers 1 or 2.
+#define MC_ENABLE( REGADRS, CTRLWORD ) writel( ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ),devpriv->base_addr+( REGADRS ) )
+
+#define MC_DISABLE( REGADRS, CTRLWORD ) writel( (uint32_t)( CTRLWORD ) << 16 , devpriv->base_addr+( REGADRS ) )
+
+#define MC_TEST( REGADRS, CTRLWORD ) ( ( readl(devpriv->base_addr+( REGADRS )) & CTRLWORD ) != 0 )
+
+/* #define WR7146(REGARDS,CTRLWORD)
+ writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */
+#define WR7146(REGARDS,CTRLWORD) writel(CTRLWORD,devpriv->base_addr+(REGARDS))
+
+/* #define RR7146(REGARDS)
+ readl((uint32_t)(devpriv->base_addr+(REGARDS))) */
+#define RR7146(REGARDS) readl(devpriv->base_addr+(REGARDS))
+
+#define BUGFIX_STREG(REGADRS) ( REGADRS - 4 )
+
+// Write a time slot control record to TSL2.
+#define VECTPORT( VECTNUM ) (P_TSL2 + ( (VECTNUM) << 2 ))
+#define SETVECT( VECTNUM, VECTVAL ) WR7146(VECTPORT( VECTNUM ), (VECTVAL))
+
+// Code macros used for constructing I2C command bytes.
+#define I2C_B2(ATTR,VAL) ( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+#define I2C_B1(ATTR,VAL) ( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+#define I2C_B0(ATTR,VAL) ( ( (ATTR) << 2 ) | ( (VAL) << 8 ) )
+
+static const comedi_lrange s626_range_table = { 2, {
+ RANGE(-5, 5),
+ RANGE(-10, 10),
+ }
+};
+
+static int s626_attach(comedi_device * dev, comedi_devconfig * it)
+{
+/* uint8_t PollList; */
+/* uint16_t AdcData; */
+/* uint16_t StartVal; */
+/* uint16_t index; */
+/* unsigned int data[16]; */
+ int result;
+ int i;
+ int ret;
+ resource_size_t resourceStart;
+ dma_addr_t appdma;
+ comedi_subdevice *s;
+ struct pci_dev *pdev;
+
+ if (alloc_private(dev, sizeof(s626_private)) < 0)
+ return -ENOMEM;
+
+ for (pdev = pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626,
+ NULL); pdev != NULL;
+ pdev = pci_get_device(PCI_VENDOR_ID_S626,
+ PCI_DEVICE_ID_S626, pdev)) {
+ if (it->options[0] || it->options[1]) {
+ if (pdev->bus->number == it->options[0] &&
+ PCI_SLOT(pdev->devfn) == it->options[1]) {
+ /* matches requested bus/slot */
+ break;
+ }
+ } else {
+ /* no bus/slot specified */
+ break;
+ }
+ }
+ devpriv->pdev = pdev;
+
+ if (pdev == NULL) {
+ printk("s626_attach: Board not present!!!\n");
+ return -ENODEV;
+ }
+
+ if ((result = comedi_pci_enable(pdev, "s626")) < 0) {
+ printk("s626_attach: comedi_pci_enable fails\n");
+ return -ENODEV;
+ }
+ devpriv->got_regions = 1;
+
+ resourceStart = pci_resource_start(devpriv->pdev, 0);
+
+ devpriv->base_addr = ioremap(resourceStart, SIZEOF_ADDRESS_SPACE);
+ if (devpriv->base_addr == NULL) {
+ printk("s626_attach: IOREMAP failed\n");
+ return -ENODEV;
+ }
+
+ if (devpriv->base_addr) {
+ //disable master interrupt
+ writel(0, devpriv->base_addr + P_IER);
+
+ //soft reset
+ writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1);
+
+ //DMA FIXME DMA//
+ DEBUG("s626_attach: DMA ALLOCATION\n");
+
+ //adc buffer allocation
+ devpriv->allocatedBuf = 0;
+
+ if ((devpriv->ANABuf.LogicalBase =
+ pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE,
+ &appdma)) == NULL) {
+ printk("s626_attach: DMA Memory mapping error\n");
+ return -ENOMEM;
+ }
+
+ devpriv->ANABuf.PhysicalBase = appdma;
+
+ DEBUG("s626_attach: AllocDMAB ADC Logical=%p, bsize=%d, Physical=0x%x\n", devpriv->ANABuf.LogicalBase, DMABUF_SIZE, (uint32_t) devpriv->ANABuf.PhysicalBase);
+
+ devpriv->allocatedBuf++;
+
+ if ((devpriv->RPSBuf.LogicalBase =
+ pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE,
+ &appdma)) == NULL) {
+ printk("s626_attach: DMA Memory mapping error\n");
+ return -ENOMEM;
+ }
+
+ devpriv->RPSBuf.PhysicalBase = appdma;
+
+ DEBUG("s626_attach: AllocDMAB RPS Logical=%p, bsize=%d, Physical=0x%x\n", devpriv->RPSBuf.LogicalBase, DMABUF_SIZE, (uint32_t) devpriv->RPSBuf.PhysicalBase);
+
+ devpriv->allocatedBuf++;
+
+ }
+
+ dev->board_ptr = s626_boards;
+ dev->board_name = thisboard->name;
+
+ if (alloc_subdevices(dev, 6) < 0)
+ return -ENOMEM;
+
+ dev->iobase = (unsigned long)devpriv->base_addr;
+ dev->irq = devpriv->pdev->irq;
+
+ //set up interrupt handler
+ if (dev->irq == 0) {
+ printk(" unknown irq (bad)\n");
+ } else {
+ if ((ret = comedi_request_irq(dev->irq, s626_irq_handler,
+ IRQF_SHARED, "s626", dev)) < 0) {
+ printk(" irq not available\n");
+ dev->irq = 0;
+ }
+ }
+
+ DEBUG("s626_attach: -- it opts %d,%d -- \n",
+ it->options[0], it->options[1]);
+
+ s = dev->subdevices + 0;
+ /* analog input subdevice */
+ dev->read_subdev = s;
+ /* we support single-ended (ground) and differential */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ;
+ s->n_chan = thisboard->ai_chans;
+ s->maxdata = (0xffff >> 2);
+ s->range_table = &s626_range_table;
+ s->len_chanlist = thisboard->ai_chans; /* This is the maximum chanlist
+ length that the board can
+ handle */
+ s->insn_config = s626_ai_insn_config;
+ s->insn_read = s626_ai_insn_read;
+ s->do_cmd = s626_ai_cmd;
+ s->do_cmdtest = s626_ai_cmdtest;
+ s->cancel = s626_ai_cancel;
+
+ s = dev->subdevices + 1;
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = thisboard->ao_chans;
+ s->maxdata = (0x3fff);
+ s->range_table = &range_bipolar10;
+ s->insn_write = s626_ao_winsn;
+ s->insn_read = s626_ao_rinsn;
+
+ s = dev->subdevices + 2;
+ /* digital I/O subdevice */
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = S626_DIO_CHANNELS;
+ s->maxdata = 1;
+ s->io_bits = 0xffff;
+ s->private = &dio_private_A;
+ s->range_table = &range_digital;
+ s->insn_config = s626_dio_insn_config;
+ s->insn_bits = s626_dio_insn_bits;
+
+ s = dev->subdevices + 3;
+ /* digital I/O subdevice */
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->io_bits = 0xffff;
+ s->private = &dio_private_B;
+ s->range_table = &range_digital;
+ s->insn_config = s626_dio_insn_config;
+ s->insn_bits = s626_dio_insn_bits;
+
+ s = dev->subdevices + 4;
+ /* digital I/O subdevice */
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->io_bits = 0xffff;
+ s->private = &dio_private_C;
+ s->range_table = &range_digital;
+ s->insn_config = s626_dio_insn_config;
+ s->insn_bits = s626_dio_insn_bits;
+
+ s = dev->subdevices + 5;
+ /* encoder (counter) subdevice */
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL;
+ s->n_chan = thisboard->enc_chans;
+ s->private = enc_private_data;
+ s->insn_config = s626_enc_insn_config;
+ s->insn_read = s626_enc_insn_read;
+ s->insn_write = s626_enc_insn_write;
+ s->maxdata = 0xffffff;
+ s->range_table = &range_unknown;
+
+ //stop ai_command
+ devpriv->ai_cmd_running = 0;
+
+ if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) {
+ dma_addr_t pPhysBuf;
+ uint16_t chan;
+
+ // enab DEBI and audio pins, enable I2C interface.
+ MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C);
+ // Configure DEBI operating mode.
+ WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 // Local bus is 16
+ // bits wide.
+ | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) // Declare DEBI
+ // transfer timeout
+ // interval.
+ | DEBI_SWAP // Set up byte lane
+ // steering.
+ | DEBI_CFG_INTEL); // Intel-compatible
+ // local bus (DEBI
+ // never times out).
+ DEBUG("s626_attach: %d debi init -- %d\n",
+ DEBI_CFG_SLAVE16 | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) |
+ DEBI_SWAP | DEBI_CFG_INTEL,
+ DEBI_CFG_INTEL | DEBI_CFG_TOQ | DEBI_CFG_INCQ |
+ DEBI_CFG_16Q);
+
+ //DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ
+ //| DEBI_CFG_INCQ| DEBI_CFG_16Q); //end
+
+ // Paging is disabled.
+ WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); // Disable MMU paging.
+
+ // Init GPIO so that ADC Start* is negated.
+ WR7146(P_GPIO, GPIO_BASE | GPIO1_HI);
+
+ //IsBoardRevA is a boolean that indicates whether the board is
+ //RevA.
+
+ // VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC
+ // EEPROM ADDRESS SELECTION. Initialize the I2C interface, which
+ // is used to access the onboard serial EEPROM. The EEPROM's I2C
+ // DeviceAddress is hardwired to a value that is dependent on the
+ // 626 board revision. On all board revisions, the EEPROM stores
+ // TrimDAC calibration constants for analog I/O. On RevB and
+ // higher boards, the DeviceAddress is hardwired to 0 to enable
+ // the EEPROM to also store the PCI SubVendorID and SubDeviceID;
+ // this is the address at which the SAA7146 expects a
+ // configuration EEPROM to reside. On RevA boards, the EEPROM
+ // device address, which is hardwired to 4, prevents the SAA7146
+ // from retrieving PCI sub-IDs, so the SAA7146 uses its built-in
+ // default values, instead.
+
+ // devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM
+ // DeviceType (0xA0)
+ // and DeviceAddress<<1.
+
+ devpriv->I2CAdrs = 0xA0; // I2C device address for onboard
+ // eeprom(revb)
+
+ // Issue an I2C ABORT command to halt any I2C operation in
+ //progress and reset BUSY flag.
+ WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT); // Write I2C control:
+ // abort any I2C
+ // activity.
+ MC_ENABLE(P_MC2, MC2_UPLD_IIC); // Invoke command
+ // upload
+ while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) ; // and wait for
+ // upload to
+ // complete.
+
+ // Per SAA7146 data sheet, write to STATUS reg twice to reset all
+ // I2C error flags.
+ for (i = 0; i < 2; i++) {
+ WR7146(P_I2CSTAT, I2C_CLKSEL); // Write I2C control: reset
+ // error flags.
+ MC_ENABLE(P_MC2, MC2_UPLD_IIC); // Invoke command upload
+ while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ; // and wait for
+ // upload to
+ // complete.
+ }
+
+ // Init audio interface functional attributes: set DAC/ADC serial
+ // clock rates, invert DAC serial clock so that DAC data setup
+ // times are satisfied, enable DAC serial clock out.
+ WR7146(P_ACON2, ACON2_INIT);
+
+ // Set up TSL1 slot list, which is used to control the
+ // accumulation of ADC data: RSD1 = shift data in on SD1. SIB_A1
+ // = store data uint8_t at next available location in FB BUFFER1
+ // register.
+ WR7146(P_TSL1, RSD1 | SIB_A1); // Fetch ADC high data
+ // uint8_t.
+ WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS); // Fetch ADC low data
+ // uint8_t; end of
+ // TSL1.
+
+ // enab TSL1 slot list so that it executes all the time.
+ WR7146(P_ACON1, ACON1_ADCSTART);
+
+ // Initialize RPS registers used for ADC.
+
+ //Physical start of RPS program.
+ WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
+
+ WR7146(P_RPSPAGE1, 0); // RPS program performs no
+ // explicit mem writes.
+ WR7146(P_RPS1_TOUT, 0); // Disable RPS timeouts.
+
+ // SAA7146 BUG WORKAROUND. Initialize SAA7146 ADC interface to a
+ // known state by invoking ADCs until FB BUFFER 1 register shows
+ // that it is correctly receiving ADC data. This is necessary
+ // because the SAA7146 ADC interface does not start up in a
+ // defined state after a PCI reset.
+
+/* PollList = EOPL; // Create a simple polling */
+/* // list for analog input */
+/* // channel 0. */
+/* ResetADC( dev, &PollList ); */
+
+/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */
+/* //Get initial ADC */
+/* //value. */
+
+/* StartVal = data[0]; */
+
+/* // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */
+/* // Invoke ADCs until the new ADC value differs from the initial */
+/* // value or a timeout occurs. The timeout protects against the */
+/* // possibility that the driver is restarting and the ADC data is a */
+/* // fixed value resulting from the applied ADC analog input being */
+/* // unusually quiet or at the rail. */
+
+/* for ( index = 0; index < 500; index++ ) */
+/* { */
+/* s626_ai_rinsn(dev,dev->subdevices,NULL,data); */
+/* AdcData = data[0]; //ReadADC( &AdcData ); */
+/* if ( AdcData != StartVal ) */
+/* break; */
+/* } */
+
+ // end initADC
+
+ // init the DAC interface
+
+ // Init Audio2's output DMAC attributes: burst length = 1 DWORD,
+ // threshold = 1 DWORD.
+ WR7146(P_PCI_BT_A, 0);
+
+ // Init Audio2's output DMA physical addresses. The protection
+ // address is set to 1 DWORD past the base address so that a
+ // single DWORD will be transferred each time a DMA transfer is
+ // enabled.
+
+ pPhysBuf =
+ devpriv->ANABuf.PhysicalBase +
+ (DAC_WDMABUF_OS * sizeof(uint32_t));
+
+ WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); // Buffer base adrs.
+ WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); // Protection address.
+
+ // Cache Audio2's output DMA buffer logical address. This is
+ // where DAC data is buffered for A2 output DMA transfers.
+ devpriv->pDacWBuf =
+ (uint32_t *) devpriv->ANABuf.LogicalBase +
+ DAC_WDMABUF_OS;
+
+ // Audio2's output channels does not use paging. The protection
+ // violation handling bit is set so that the DMAC will
+ // automatically halt and its PCI address pointer will be reset
+ // when the protection address is reached.
+ WR7146(P_PAGEA2_OUT, 8);
+
+ // Initialize time slot list 2 (TSL2), which is used to control
+ // the clock generation for and serialization of data to be sent
+ // to the DAC devices. Slot 0 is a NOP that is used to trap TSL
+ // execution; this permits other slots to be safely modified
+ // without first turning off the TSL sequencer (which is
+ // apparently impossible to do). Also, SD3 (which is driven by a
+ // pull-up resistor) is shifted in and stored to the MSB of
+ // FB_BUFFER2 to be used as evidence that the slot sequence has
+ // not yet finished executing.
+ SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS); // Slot 0: Trap TSL
+ // execution, shift 0xFF
+ // into FB_BUFFER2.
+
+ // Initialize slot 1, which is constant. Slot 1 causes a DWORD to
+ // be transferred from audio channel 2's output FIFO to the FIFO's
+ // output buffer so that it can be serialized and sent to the DAC
+ // during subsequent slots. All remaining slots are dynamically
+ // populated as required by the target DAC device.
+ SETVECT(1, LF_A2); // Slot 1: Fetch DWORD from Audio2's
+ // output FIFO.
+
+ // Start DAC's audio interface (TSL2) running.
+ WR7146(P_ACON1, ACON1_DACSTART);
+
+ ////////////////////////////////////////////////////////
+
+ // end init DAC interface
+
+ // Init Trim DACs to calibrated values. Do it twice because the
+ // SAA7146 audio channel does not always reset properly and
+ // sometimes causes the first few TrimDAC writes to malfunction.
+
+ LoadTrimDACs(dev);
+ LoadTrimDACs(dev); // Insurance.
+
+ //////////////////////////////////////////////////////////////////
+ // Manually init all gate array hardware in case this is a soft
+ // reset (we have no way of determining whether this is a warm or
+ // cold start). This is necessary because the gate array will
+ // reset only in response to a PCI hard reset; there is no soft
+ // reset function.
+
+ // Init all DAC outputs to 0V and init all DAC setpoint and
+ // polarity images.
+ for (chan = 0; chan < S626_DAC_CHANNELS; chan++)
+ SetDAC(dev, chan, 0);
+
+ // Init image of WRMISC2 Battery Charger Enabled control bit.
+ // This image is used when the state of the charger control bit,
+ // which has no direct hardware readback mechanism, is queried.
+ devpriv->ChargeEnabled = 0;
+
+ // Init image of watchdog timer interval in WRMISC2. This image
+ // maintains the value of the control bits of MISC2 are
+ // continuously reset to zero as long as the WD timer is disabled.
+ devpriv->WDInterval = 0;
+
+ // Init Counter Interrupt enab mask for RDMISC2. This mask is
+ // applied against MISC2 when testing to determine which timer
+ // events are requesting interrupt service.
+ devpriv->CounterIntEnabs = 0;
+
+ // Init counters.
+ CountersInit(dev);
+
+ // Without modifying the state of the Battery Backup enab, disable
+ // the watchdog timer, set DIO channels 0-5 to operate in the
+ // standard DIO (vs. counter overflow) mode, disable the battery
+ // charger, and reset the watchdog interval selector to zero.
+ WriteMISC2(dev, (uint16_t) (DEBIread(dev,
+ LP_RDMISC2) & MISC2_BATT_ENABLE));
+
+ // Initialize the digital I/O subsystem.
+ s626_dio_init(dev);
+
+ //enable interrupt test
+ // writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER);
+ }
+
+ DEBUG("s626_attach: comedi%d s626 attached %04x\n", dev->minor,
+ (uint32_t) devpriv->base_addr);
+
+ return 1;
+}
+
+static lsampl_t s626_ai_reg_to_uint(int data)
+{
+ lsampl_t tempdata;
+
+ tempdata = (data >> 18);
+ if (tempdata & 0x2000)
+ tempdata &= 0x1fff;
+ else
+ tempdata += (1 << 13);
+
+ return tempdata;
+}
+
+/* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data){ */
+/* return 0; */
+/* } */
+
+static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG)
+{
+ comedi_device *dev = d;
+ comedi_subdevice *s;
+ comedi_cmd *cmd;
+ enc_private *k;
+ unsigned long flags;
+ int32_t *readaddr;
+ uint32_t irqtype, irqstatus;
+ int i = 0;
+ sampl_t tempdata;
+ uint8_t group;
+ uint16_t irqbit;
+
+ DEBUG("s626_irq_handler: interrupt request recieved!!!\n");
+
+ if (dev->attached == 0)
+ return IRQ_NONE;
+ // lock to avoid race with comedi_poll
+ comedi_spin_lock_irqsave(&dev->spinlock, flags);
+
+ //save interrupt enable register state
+ irqstatus = readl(devpriv->base_addr + P_IER);
+
+ //read interrupt type
+ irqtype = readl(devpriv->base_addr + P_ISR);
+
+ //disable master interrupt
+ writel(0, devpriv->base_addr + P_IER);
+
+ //clear interrupt
+ writel(irqtype, devpriv->base_addr + P_ISR);
+
+ //do somethings
+ DEBUG("s626_irq_handler: interrupt type %d\n", irqtype);
+
+ switch (irqtype) {
+ case IRQ_RPS1: // end_of_scan occurs
+
+ DEBUG("s626_irq_handler: RPS1 irq detected\n");
+
+ // manage ai subdevice
+ s = dev->subdevices;
+ cmd = &(s->async->cmd);
+
+ // Init ptr to DMA buffer that holds new ADC data. We skip the
+ // first uint16_t in the buffer because it contains junk data from
+ // the final ADC of the previous poll list scan.
+ readaddr = (int32_t *) devpriv->ANABuf.LogicalBase + 1;
+
+ // get the data and hand it over to comedi
+ for (i = 0; i < (s->async->cmd.chanlist_len); i++) {
+ // Convert ADC data to 16-bit integer values and copy to application
+ // buffer.
+ tempdata = s626_ai_reg_to_uint((int)*readaddr);
+ readaddr++;
+
+ //put data into read buffer
+ // comedi_buf_put(s->async, tempdata);
+ if (cfc_write_to_buffer(s, tempdata) == 0)
+ printk("s626_irq_handler: cfc_write_to_buffer error!\n");
+
+ DEBUG("s626_irq_handler: ai channel %d acquired: %d\n",
+ i, tempdata);
+ }
+
+ //end of scan occurs
+ s->async->events |= COMEDI_CB_EOS;
+
+ if (!(devpriv->ai_continous))
+ devpriv->ai_sample_count--;
+ if (devpriv->ai_sample_count <= 0) {
+ devpriv->ai_cmd_running = 0;
+
+ // Stop RPS program.
+ MC_DISABLE(P_MC1, MC1_ERPS1);
+
+ //send end of acquisition
+ s->async->events |= COMEDI_CB_EOA;
+
+ //disable master interrupt
+ irqstatus = 0;
+ }
+
+ if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT) {
+ DEBUG("s626_irq_handler: enable interrupt on dio channel %d\n", cmd->scan_begin_arg);
+
+ s626_dio_set_irq(dev, cmd->scan_begin_arg);
+
+ DEBUG("s626_irq_handler: External trigger is set!!!\n");
+ }
+ // tell comedi that data is there
+ DEBUG("s626_irq_handler: events %d\n", s->async->events);
+ comedi_event(dev, s);
+ break;
+ case IRQ_GPIO3: //check dio and conter interrupt
+
+ DEBUG("s626_irq_handler: GPIO3 irq detected\n");
+
+ // manage ai subdevice
+ s = dev->subdevices;
+ cmd = &(s->async->cmd);
+
+ //s626_dio_clear_irq(dev);
+
+ for (group = 0; group < S626_DIO_BANKS; group++) {
+ irqbit = 0;
+ //read interrupt type
+ irqbit = DEBIread(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->RDCapFlg);
+
+ //check if interrupt is generated from dio channels
+ if (irqbit) {
+ s626_dio_reset_irq(dev, group, irqbit);
+ DEBUG("s626_irq_handler: check interrupt on dio group %d %d\n", group, i);
+ if (devpriv->ai_cmd_running) {
+ //check if interrupt is an ai acquisition start trigger
+ if ((irqbit >> (cmd->start_arg -
+ (16 * group)))
+ == 1
+ && cmd->start_src == TRIG_EXT) {
+ DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->start_arg);
+
+ // Start executing the RPS program.
+ MC_ENABLE(P_MC1, MC1_ERPS1);
+
+ DEBUG("s626_irq_handler: aquisition start triggered!!!\n");
+
+ if (cmd->scan_begin_src ==
+ TRIG_EXT) {
+ DEBUG("s626_ai_cmd: enable interrupt on dio channel %d\n", cmd->scan_begin_arg);
+
+ s626_dio_set_irq(dev,
+ cmd->
+ scan_begin_arg);
+
+ DEBUG("s626_irq_handler: External scan trigger is set!!!\n");
+ }
+ }
+ if ((irqbit >> (cmd->scan_begin_arg -
+ (16 * group)))
+ == 1
+ && cmd->scan_begin_src ==
+ TRIG_EXT) {
+ DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->scan_begin_arg);
+
+ // Trigger ADC scan loop start by setting RPS Signal 0.
+ MC_ENABLE(P_MC2, MC2_ADC_RPS);
+
+ DEBUG("s626_irq_handler: scan triggered!!! %d\n", devpriv->ai_sample_count);
+ if (cmd->convert_src ==
+ TRIG_EXT) {
+
+ DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n", cmd->convert_arg - (16 * group), group);
+
+ devpriv->
+ ai_convert_count
+ =
+ cmd->
+ chanlist_len;
+
+ s626_dio_set_irq(dev,
+ cmd->
+ convert_arg);
+
+ DEBUG("s626_irq_handler: External convert trigger is set!!!\n");
+ }
+
+ if (cmd->convert_src ==
+ TRIG_TIMER) {
+ k = &encpriv[5];
+ devpriv->
+ ai_convert_count
+ =
+ cmd->
+ chanlist_len;
+ k->SetEnable(dev, k,
+ CLKENAB_ALWAYS);
+ }
+ }
+ if ((irqbit >> (cmd->convert_arg -
+ (16 * group)))
+ == 1
+ && cmd->convert_src ==
+ TRIG_EXT) {
+ DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->convert_arg);
+
+ // Trigger ADC scan loop start by setting RPS Signal 0.
+ MC_ENABLE(P_MC2, MC2_ADC_RPS);
+
+ DEBUG("s626_irq_handler: adc convert triggered!!!\n");
+
+ devpriv->ai_convert_count--;
+
+ if (devpriv->ai_convert_count >
+ 0) {
+
+ DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n", cmd->convert_arg - (16 * group), group);
+
+ s626_dio_set_irq(dev,
+ cmd->
+ convert_arg);
+
+ DEBUG("s626_irq_handler: External trigger is set!!!\n");
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ //read interrupt type
+ irqbit = DEBIread(dev, LP_RDMISC2);
+
+ //check interrupt on counters
+ DEBUG("s626_irq_handler: check counters interrupt %d\n",
+ irqbit);
+
+ if (irqbit & IRQ_COINT1A) {
+ DEBUG("s626_irq_handler: interrupt on counter 1A overflow\n");
+ k = &encpriv[0];
+
+ //clear interrupt capture flag
+ k->ResetCapFlags(dev, k);
+ }
+ if (irqbit & IRQ_COINT2A) {
+ DEBUG("s626_irq_handler: interrupt on counter 2A overflow\n");
+ k = &encpriv[1];
+
+ //clear interrupt capture flag
+ k->ResetCapFlags(dev, k);
+ }
+ if (irqbit & IRQ_COINT3A) {
+ DEBUG("s626_irq_handler: interrupt on counter 3A overflow\n");
+ k = &encpriv[2];
+
+ //clear interrupt capture flag
+ k->ResetCapFlags(dev, k);
+ }
+ if (irqbit & IRQ_COINT1B) {
+ DEBUG("s626_irq_handler: interrupt on counter 1B overflow\n");
+ k = &encpriv[3];
+
+ //clear interrupt capture flag
+ k->ResetCapFlags(dev, k);
+ }
+ if (irqbit & IRQ_COINT2B) {
+ DEBUG("s626_irq_handler: interrupt on counter 2B overflow\n");
+ k = &encpriv[4];
+
+ //clear interrupt capture flag
+ k->ResetCapFlags(dev, k);
+
+ if (devpriv->ai_convert_count > 0) {
+ devpriv->ai_convert_count--;
+ if (devpriv->ai_convert_count == 0)
+ k->SetEnable(dev, k, CLKENAB_INDEX);
+
+ if (cmd->convert_src == TRIG_TIMER) {
+ DEBUG("s626_irq_handler: conver timer trigger!!! %d\n", devpriv->ai_convert_count);
+
+ // Trigger ADC scan loop start by setting RPS Signal 0.
+ MC_ENABLE(P_MC2, MC2_ADC_RPS);
+ }
+ }
+ }
+ if (irqbit & IRQ_COINT3B) {
+ DEBUG("s626_irq_handler: interrupt on counter 3B overflow\n");
+ k = &encpriv[5];
+
+ //clear interrupt capture flag
+ k->ResetCapFlags(dev, k);
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ DEBUG("s626_irq_handler: scan timer trigger!!!\n");
+
+ // Trigger ADC scan loop start by setting RPS Signal 0.
+ MC_ENABLE(P_MC2, MC2_ADC_RPS);
+ }
+
+ if (cmd->convert_src == TRIG_TIMER) {
+ DEBUG("s626_irq_handler: convert timer trigger is set\n");
+ k = &encpriv[4];
+ devpriv->ai_convert_count = cmd->chanlist_len;
+ k->SetEnable(dev, k, CLKENAB_ALWAYS);
+ }
+ }
+ }
+
+ //enable interrupt
+ writel(irqstatus, devpriv->base_addr + P_IER);
+
+ DEBUG("s626_irq_handler: exit interrupt service routine.\n");
+
+ comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+ return IRQ_HANDLED;
+}
+
+static int s626_detach(comedi_device * dev)
+{
+ if (devpriv) {
+ //stop ai_command
+ devpriv->ai_cmd_running = 0;
+
+ if (devpriv->base_addr) {
+ //interrupt mask
+ WR7146(P_IER, 0); // Disable master interrupt.
+ WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1); // Clear board's IRQ status flag.
+
+ // Disable the watchdog timer and battery charger.
+ WriteMISC2(dev, 0);
+
+ // Close all interfaces on 7146 device.
+ WR7146(P_MC1, MC1_SHUTDOWN);
+ WR7146(P_ACON1, ACON1_BASE);
+
+ CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE);
+ CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE);
+ }
+
+ if (dev->irq) {
+ comedi_free_irq(dev->irq, dev);
+ }
+
+ if (devpriv->base_addr) {
+ iounmap(devpriv->base_addr);
+ }
+
+ if (devpriv->pdev) {
+ if (devpriv->got_regions) {
+ comedi_pci_disable(devpriv->pdev);
+ }
+ pci_dev_put(devpriv->pdev);
+ }
+ }
+
+ DEBUG("s626_detach: S626 detached!\n");
+
+ return 0;
+}
+
+/*
+ * this functions build the RPS program for hardware driven acquistion
+ */
+void ResetADC(comedi_device * dev, uint8_t * ppl)
+{
+ register uint32_t *pRPS;
+ uint32_t JmpAdrs;
+ uint16_t i;
+ uint16_t n;
+ uint32_t LocalPPL;
+ comedi_cmd *cmd = &(dev->subdevices->async->cmd);
+
+ // Stop RPS program in case it is currently running.
+ MC_DISABLE(P_MC1, MC1_ERPS1);
+
+ // Set starting logical address to write RPS commands.
+ pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase;
+
+ // Initialize RPS instruction pointer.
+ WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase);
+
+ // Construct RPS program in RPSBuf DMA buffer
+
+ if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) {
+ DEBUG("ResetADC: scan_begin pause inserted\n");
+ // Wait for Start trigger.
+ *pRPS++ = RPS_PAUSE | RPS_SIGADC;
+ *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
+ }
+ // SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary
+ // because the first RPS DEBI Write following a non-RPS DEBI write
+ // seems to always fail. If we don't do this dummy write, the ADC
+ // gain might not be set to the value required for the first slot in
+ // the poll list; the ADC gain would instead remain unchanged from
+ // the previously programmed value.
+ *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI Write command
+ // and address to shadow RAM.
+ *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
+ *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI immediate data
+ // to shadow RAM:
+ *pRPS++ = GSEL_BIPOLAR5V; // arbitrary immediate data
+ // value.
+ *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM
+ // uploaded" flag.
+ *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload.
+ *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to finish.
+
+ // Digitize all slots in the poll list. This is implemented as a
+ // for loop to limit the slot count to 16 in case the application
+ // forgot to set the EOPL flag in the final slot.
+ for (devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++) {
+ // Convert application's poll list item to private board class
+ // format. Each app poll list item is an uint8_t with form
+ // (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 =
+ // +-10V, 1 = +-5V, and EOPL = End of Poll List marker.
+ LocalPPL =
+ (*ppl << 8) | (*ppl & 0x10 ? GSEL_BIPOLAR5V :
+ GSEL_BIPOLAR10V);
+
+ // Switch ADC analog gain.
+ *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI command
+ // and address to
+ // shadow RAM.
+ *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL;
+ *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI
+ // immediate data to
+ // shadow RAM.
+ *pRPS++ = LocalPPL;
+ *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM uploaded"
+ // flag.
+ *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload.
+ *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to
+ // finish.
+
+ // Select ADC analog input channel.
+ *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI command
+ // and address to
+ // shadow RAM.
+ *pRPS++ = DEBI_CMD_WRWORD | LP_ISEL;
+ *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI
+ // immediate data to
+ // shadow RAM.
+ *pRPS++ = LocalPPL;
+ *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM uploaded"
+ // flag.
+ *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload.
+ *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to
+ // finish.
+
+ // Delay at least 10 microseconds for analog input settling.
+ // Instead of padding with NOPs, we use RPS_JUMP instructions
+ // here; this allows us to produce a longer delay than is
+ // possible with NOPs because each RPS_JUMP flushes the RPS'
+ // instruction prefetch pipeline.
+ JmpAdrs =
+ (uint32_t) devpriv->RPSBuf.PhysicalBase +
+ (uint32_t) ((unsigned long)pRPS -
+ (unsigned long)devpriv->RPSBuf.LogicalBase);
+ for (i = 0; i < (10 * RPSCLK_PER_US / 2); i++) {
+ JmpAdrs += 8; // Repeat to implement time delay:
+ *pRPS++ = RPS_JUMP; // Jump to next RPS instruction.
+ *pRPS++ = JmpAdrs;
+ }
+
+ if (cmd != NULL && cmd->convert_src != TRIG_NOW) {
+ DEBUG("ResetADC: convert pause inserted\n");
+ // Wait for Start trigger.
+ *pRPS++ = RPS_PAUSE | RPS_SIGADC;
+ *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC;
+ }
+ // Start ADC by pulsing GPIO1.
+ *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // Begin ADC Start pulse.
+ *pRPS++ = GPIO_BASE | GPIO1_LO;
+ *pRPS++ = RPS_NOP;
+ // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE.
+ *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // End ADC Start pulse.
+ *pRPS++ = GPIO_BASE | GPIO1_HI;
+
+ // Wait for ADC to complete (GPIO2 is asserted high when ADC not
+ // busy) and for data from previous conversion to shift into FB
+ // BUFFER 1 register.
+ *pRPS++ = RPS_PAUSE | RPS_GPIO2; // Wait for ADC done.
+
+ // Transfer ADC data from FB BUFFER 1 register to DMA buffer.
+ *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2);
+ *pRPS++ =
+ (uint32_t) devpriv->ANABuf.PhysicalBase +
+ (devpriv->AdcItems << 2);
+
+ // If this slot's EndOfPollList flag is set, all channels have
+ // now been processed.
+ if (*ppl++ & EOPL) {
+ devpriv->AdcItems++; // Adjust poll list item count.
+ break; // Exit poll list processing loop.
+ }
+ }
+ DEBUG("ResetADC: ADC items %d \n", devpriv->AdcItems);
+
+ // VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the
+ // ADC to stabilize for 2 microseconds before starting the final
+ // (dummy) conversion. This delay is necessary to allow sufficient
+ // time between last conversion finished and the start of the dummy
+ // conversion. Without this delay, the last conversion's data value
+ // is sometimes set to the previous conversion's data value.
+ for (n = 0; n < (2 * RPSCLK_PER_US); n++)
+ *pRPS++ = RPS_NOP;
+
+ // Start a dummy conversion to cause the data from the last
+ // conversion of interest to be shifted in.
+ *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // Begin ADC Start pulse.
+ *pRPS++ = GPIO_BASE | GPIO1_LO;
+ *pRPS++ = RPS_NOP;
+ // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE.
+ *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // End ADC Start pulse.
+ *pRPS++ = GPIO_BASE | GPIO1_HI;
+
+ // Wait for the data from the last conversion of interest to arrive
+ // in FB BUFFER 1 register.
+ *pRPS++ = RPS_PAUSE | RPS_GPIO2; // Wait for ADC done.
+
+ // Transfer final ADC data from FB BUFFER 1 register to DMA buffer.
+ *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); //
+ *pRPS++ =
+ (uint32_t) devpriv->ANABuf.PhysicalBase +
+ (devpriv->AdcItems << 2);
+
+ // Indicate ADC scan loop is finished.
+ // *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ; // Signal ReadADC() that scan is done.
+
+ //invoke interrupt
+ if (devpriv->ai_cmd_running == 1) {
+ DEBUG("ResetADC: insert irq in ADC RPS task\n");
+ *pRPS++ = RPS_IRQ;
+ }
+ // Restart RPS program at its beginning.
+ *pRPS++ = RPS_JUMP; // Branch to start of RPS program.
+ *pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase;
+
+ // End of RPS program build
+ // ------------------------------------------------------------
+}
+
+/* TO COMPLETE, IF NECESSARY */
+static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+
+ return -EINVAL;
+}
+
+/* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) */
+/* { */
+/* register uint8_t i; */
+/* register int32_t *readaddr; */
+
+/* DEBUG("as626_ai_rinsn: ai_rinsn enter \n"); */
+
+/* // Trigger ADC scan loop start by setting RPS Signal 0. */
+/* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */
+
+/* // Wait until ADC scan loop is finished (RPS Signal 0 reset). */
+/* while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */
+
+/* // Init ptr to DMA buffer that holds new ADC data. We skip the */
+/* // first uint16_t in the buffer because it contains junk data from */
+/* // the final ADC of the previous poll list scan. */
+/* readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */
+
+/* // Convert ADC data to 16-bit integer values and copy to application */
+/* // buffer. */
+/* for ( i = 0; i < devpriv->AdcItems; i++ ) { */
+/* *data = s626_ai_reg_to_uint( *readaddr++ ); */
+/* DEBUG("s626_ai_rinsn: data %d \n",*data); */
+/* data++; */
+/* } */
+
+/* DEBUG("s626_ai_rinsn: ai_rinsn escape \n"); */
+/* return i; */
+/* } */
+
+static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ uint16_t chan = CR_CHAN(insn->chanspec);
+ uint16_t range = CR_RANGE(insn->chanspec);
+ uint16_t AdcSpec = 0;
+ uint32_t GpioImage;
+ int n;
+
+/* //interrupt call test */
+/* writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); //Writing a logical 1 */
+/* //into any of the RPS_PSR */
+/* //bits causes the */
+/* //corresponding interrupt */
+/* //to be generated if */
+/* //enabled */
+
+ DEBUG("s626_ai_insn_read: entering\n");
+
+ // Convert application's ADC specification into form
+ // appropriate for register programming.
+ if (range == 0)
+ AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V);
+ else
+ AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V);
+
+ // Switch ADC analog gain.
+ DEBIwrite(dev, LP_GSEL, AdcSpec); // Set gain.
+
+ // Select ADC analog input channel.
+ DEBIwrite(dev, LP_ISEL, AdcSpec); // Select channel.
+
+ for (n = 0; n < insn->n; n++) {
+
+ // Delay 10 microseconds for analog input settling.
+ comedi_udelay(10);
+
+ // Start ADC by pulsing GPIO1 low.
+ GpioImage = RR7146(P_GPIO);
+ // Assert ADC Start command
+ WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ // and stretch it out.
+ WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ // Negate ADC Start command.
+ WR7146(P_GPIO, GpioImage | GPIO1_HI);
+
+ // Wait for ADC to complete (GPIO2 is asserted high when
+ // ADC not busy) and for data from previous conversion to
+ // shift into FB BUFFER 1 register.
+
+ // Wait for ADC done.
+ while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
+
+ // Fetch ADC data.
+ if (n != 0)
+ data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
+
+ // Allow the ADC to stabilize for 4 microseconds before
+ // starting the next (final) conversion. This delay is
+ // necessary to allow sufficient time between last
+ // conversion finished and the start of the next
+ // conversion. Without this delay, the last conversion's
+ // data value is sometimes set to the previous
+ // conversion's data value.
+ comedi_udelay(4);
+ }
+
+ // Start a dummy conversion to cause the data from the
+ // previous conversion to be shifted in.
+ GpioImage = RR7146(P_GPIO);
+
+ //Assert ADC Start command
+ WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ // and stretch it out.
+ WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ WR7146(P_GPIO, GpioImage & ~GPIO1_HI);
+ // Negate ADC Start command.
+ WR7146(P_GPIO, GpioImage | GPIO1_HI);
+
+ // Wait for the data to arrive in FB BUFFER 1 register.
+
+ // Wait for ADC done.
+ while (!(RR7146(P_PSR) & PSR_GPIO2)) ;
+
+ // Fetch ADC data from audio interface's input shift
+ // register.
+
+ // Fetch ADC data.
+ if (n != 0)
+ data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1));
+
+ DEBUG("s626_ai_insn_read: samples %d, data %d\n", n, data[n - 1]);
+
+ return n;
+}
+
+static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd)
+{
+
+ int n;
+
+ for (n = 0; n < cmd->chanlist_len; n++) {
+ if (CR_RANGE((cmd->chanlist)[n]) == 0)
+ ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_5V);
+ else
+ ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_10V);
+ }
+ ppl[n - 1] |= EOPL;
+
+ return n;
+}
+
+static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s,
+ unsigned int trignum)
+{
+ if (trignum != 0)
+ return -EINVAL;
+
+ DEBUG("s626_ai_inttrig: trigger adc start...");
+
+ // Start executing the RPS program.
+ MC_ENABLE(P_MC1, MC1_ERPS1);
+
+ s->async->inttrig = NULL;
+
+ DEBUG(" done\n");
+
+ return 1;
+}
+
+/* TO COMPLETE */
+static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+{
+
+ uint8_t ppl[16];
+ comedi_cmd *cmd = &s->async->cmd;
+ enc_private *k;
+ int tick;
+
+ DEBUG("s626_ai_cmd: entering command function\n");
+
+ if (devpriv->ai_cmd_running) {
+ printk("s626_ai_cmd: Another ai_cmd is running %d\n",
+ dev->minor);
+ return -EBUSY;
+ }
+ //disable interrupt
+ writel(0, devpriv->base_addr + P_IER);
+
+ //clear interrupt request
+ writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->base_addr + P_ISR);
+
+ //clear any pending interrupt
+ s626_dio_clear_irq(dev);
+ // s626_enc_clear_irq(dev);
+
+ //reset ai_cmd_running flag
+ devpriv->ai_cmd_running = 0;
+
+ // test if cmd is valid
+ if (cmd == NULL) {
+ DEBUG("s626_ai_cmd: NULL command\n");
+ return -EINVAL;
+ } else {
+ DEBUG("s626_ai_cmd: command recieved!!!\n");
+ }
+
+ if (dev->irq == 0) {
+ comedi_error(dev,
+ "s626_ai_cmd: cannot run command without an irq");
+ return -EIO;
+ }
+
+ s626_ai_load_polllist(ppl, cmd);
+ devpriv->ai_cmd_running = 1;
+ devpriv->ai_convert_count = 0;
+
+ switch (cmd->scan_begin_src) {
+ case TRIG_FOLLOW:
+ break;
+ case TRIG_TIMER:
+ // set a conter to generate adc trigger at scan_begin_arg interval
+ k = &encpriv[5];
+ tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg,
+ cmd->flags & TRIG_ROUND_MASK);
+
+ //load timer value and enable interrupt
+ s626_timer_load(dev, k, tick);
+ k->SetEnable(dev, k, CLKENAB_ALWAYS);
+
+ DEBUG("s626_ai_cmd: scan trigger timer is set with value %d\n",
+ tick);
+
+ break;
+ case TRIG_EXT:
+ // set the digital line and interrupt for scan trigger
+ if (cmd->start_src != TRIG_EXT)
+ s626_dio_set_irq(dev, cmd->scan_begin_arg);
+
+ DEBUG("s626_ai_cmd: External scan trigger is set!!!\n");
+
+ break;
+ }
+
+ switch (cmd->convert_src) {
+ case TRIG_NOW:
+ break;
+ case TRIG_TIMER:
+ // set a conter to generate adc trigger at convert_arg interval
+ k = &encpriv[4];
+ tick = s626_ns_to_timer((int *)&cmd->convert_arg,
+ cmd->flags & TRIG_ROUND_MASK);
+
+ //load timer value and enable interrupt
+ s626_timer_load(dev, k, tick);
+ k->SetEnable(dev, k, CLKENAB_INDEX);
+
+ DEBUG("s626_ai_cmd: convert trigger timer is set with value %d\n", tick);
+ break;
+ case TRIG_EXT:
+ // set the digital line and interrupt for convert trigger
+ if (cmd->scan_begin_src != TRIG_EXT
+ && cmd->start_src == TRIG_EXT)
+ s626_dio_set_irq(dev, cmd->convert_arg);
+
+ DEBUG("s626_ai_cmd: External convert trigger is set!!!\n");
+
+ break;
+ }
+
+ switch (cmd->stop_src) {
+ case TRIG_COUNT:
+ // data arrives as one packet
+ devpriv->ai_sample_count = cmd->stop_arg;
+ devpriv->ai_continous = 0;
+ break;
+ case TRIG_NONE:
+ // continous aquisition
+ devpriv->ai_continous = 1;
+ devpriv->ai_sample_count = 0;
+ break;
+ }
+
+ ResetADC(dev, ppl);
+
+ switch (cmd->start_src) {
+ case TRIG_NOW:
+ // Trigger ADC scan loop start by setting RPS Signal 0.
+ // MC_ENABLE( P_MC2, MC2_ADC_RPS );
+
+ // Start executing the RPS program.
+ MC_ENABLE(P_MC1, MC1_ERPS1);
+
+ DEBUG("s626_ai_cmd: ADC triggered\n");
+ s->async->inttrig = NULL;
+ break;
+ case TRIG_EXT:
+ //configure DIO channel for acquisition trigger
+ s626_dio_set_irq(dev, cmd->start_arg);
+
+ DEBUG("s626_ai_cmd: External start trigger is set!!!\n");
+
+ s->async->inttrig = NULL;
+ break;
+ case TRIG_INT:
+ s->async->inttrig = s626_ai_inttrig;
+ break;
+ }
+
+ //enable interrupt
+ writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER);
+
+ DEBUG("s626_ai_cmd: command function terminated\n");
+
+ return 0;
+}
+
+static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
+ comedi_cmd * cmd)
+{
+ int err = 0;
+ int tmp;
+
+ /* cmdtest tests a particular command to see if it is valid. Using
+ * the cmdtest ioctl, a user can create a valid cmd and then have it
+ * executes by the cmd ioctl.
+ *
+ * cmdtest returns 1,2,3,4 or 0, depending on which tests the
+ * command passes. */
+
+ /* step 1: make sure trigger sources are trivially valid */
+
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT;
+ if (!cmd->start_src || tmp != cmd->start_src)
+ err++;
+
+ tmp = cmd->scan_begin_src;
+ cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+ err++;
+
+ tmp = cmd->convert_src;
+ cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
+ if (!cmd->convert_src || tmp != cmd->convert_src)
+ err++;
+
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+ err++;
+
+ tmp = cmd->stop_src;
+ cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+ if (!cmd->stop_src || tmp != cmd->stop_src)
+ err++;
+
+ if (err)
+ return 1;
+
+ /* step 2: make sure trigger sources are unique and mutually
+ compatible */
+
+ /* note that mutual compatiblity is not an issue here */
+ if (cmd->scan_begin_src != TRIG_TIMER &&
+ cmd->scan_begin_src != TRIG_EXT
+ && cmd->scan_begin_src != TRIG_FOLLOW)
+ err++;
+ if (cmd->convert_src != TRIG_TIMER &&
+ cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
+ err++;
+ if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
+ err++;
+
+ if (err)
+ return 2;
+
+ /* step 3: make sure arguments are trivially compatible */
+
+ if (cmd->start_src != TRIG_EXT && cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+
+ if (cmd->start_src == TRIG_EXT && cmd->start_arg < 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+
+ if (cmd->start_src == TRIG_EXT && cmd->start_arg > 39) {
+ cmd->start_arg = 39;
+ err++;
+ }
+
+ if (cmd->scan_begin_src == TRIG_EXT && cmd->scan_begin_arg < 0) {
+ cmd->scan_begin_arg = 0;
+ err++;
+ }
+
+ if (cmd->scan_begin_src == TRIG_EXT && cmd->scan_begin_arg > 39) {
+ cmd->scan_begin_arg = 39;
+ err++;
+ }
+
+ if (cmd->convert_src == TRIG_EXT && cmd->convert_arg < 0) {
+ cmd->convert_arg = 0;
+ err++;
+ }
+
+ if (cmd->convert_src == TRIG_EXT && cmd->convert_arg > 39) {
+ cmd->convert_arg = 39;
+ err++;
+ }
+#define MAX_SPEED 200000 /* in nanoseconds */
+#define MIN_SPEED 2000000000 /* in nanoseconds */
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ if (cmd->scan_begin_arg < MAX_SPEED) {
+ cmd->scan_begin_arg = MAX_SPEED;
+ err++;
+ }
+ if (cmd->scan_begin_arg > MIN_SPEED) {
+ cmd->scan_begin_arg = MIN_SPEED;
+ err++;
+ }
+ } else {
+ /* external trigger */
+ /* should be level/edge, hi/lo specification here */
+ /* should specify multiple external triggers */
+/* if(cmd->scan_begin_arg>9){ */
+/* cmd->scan_begin_arg=9; */
+/* err++; */
+/* } */
+ }
+ if (cmd->convert_src == TRIG_TIMER) {
+ if (cmd->convert_arg < MAX_SPEED) {
+ cmd->convert_arg = MAX_SPEED;
+ err++;
+ }
+ if (cmd->convert_arg > MIN_SPEED) {
+ cmd->convert_arg = MIN_SPEED;
+ err++;
+ }
+ } else {
+ /* external trigger */
+ /* see above */
+/* if(cmd->convert_arg>9){ */
+/* cmd->convert_arg=9; */
+/* err++; */
+/* } */
+ }
+
+ if (cmd->scan_end_arg != cmd->chanlist_len) {
+ cmd->scan_end_arg = cmd->chanlist_len;
+ err++;
+ }
+ if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_arg > 0x00ffffff) {
+ cmd->stop_arg = 0x00ffffff;
+ err++;
+ }
+ } else {
+ /* TRIG_NONE */
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+ }
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ tmp = cmd->scan_begin_arg;
+ s626_ns_to_timer((int *)&cmd->scan_begin_arg,
+ cmd->flags & TRIG_ROUND_MASK);
+ if (tmp != cmd->scan_begin_arg)
+ err++;
+ }
+ if (cmd->convert_src == TRIG_TIMER) {
+ tmp = cmd->convert_arg;
+ s626_ns_to_timer((int *)&cmd->convert_arg,
+ cmd->flags & TRIG_ROUND_MASK);
+ if (tmp != cmd->convert_arg)
+ err++;
+ if (cmd->scan_begin_src == TRIG_TIMER &&
+ cmd->scan_begin_arg <
+ cmd->convert_arg * cmd->scan_end_arg) {
+ cmd->scan_begin_arg =
+ cmd->convert_arg * cmd->scan_end_arg;
+ err++;
+ }
+ }
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+{
+ // Stop RPS program in case it is currently running.
+ MC_DISABLE(P_MC1, MC1_ERPS1);
+
+ //disable master interrupt
+ writel(0, devpriv->base_addr + P_IER);
+
+ devpriv->ai_cmd_running = 0;
+
+ return 0;
+}
+
+/* This function doesn't require a particular form, this is just what
+ * happens to be used in some of the drivers. It should convert ns
+ * nanoseconds to a counter value suitable for programming the device.
+ * Also, it should adjust ns so that it cooresponds to the actual time
+ * that the device will use. */
+static int s626_ns_to_timer(int *nanosec, int round_mode)
+{
+ int divider, base;
+
+ base = 500; //2MHz internal clock
+
+ switch (round_mode) {
+ case TRIG_ROUND_NEAREST:
+ default:
+ divider = (*nanosec + base / 2) / base;
+ break;
+ case TRIG_ROUND_DOWN:
+ divider = (*nanosec) / base;
+ break;
+ case TRIG_ROUND_UP:
+ divider = (*nanosec + base - 1) / base;
+ break;
+ }
+
+ *nanosec = base * divider;
+ return divider - 1;
+}
+
+static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+
+ int i;
+ uint16_t chan = CR_CHAN(insn->chanspec);
+ int16_t dacdata;
+
+ for (i = 0; i < insn->n; i++) {
+ dacdata = (int16_t) data[i];
+ devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[i];
+ dacdata -= (0x1fff);
+
+ SetDAC(dev, chan, dacdata);
+ }
+
+ return i;
+}
+
+static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ int i;
+
+ for (i = 0; i < insn->n; i++) {
+ data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
+ }
+
+ return i;
+}
+
+/////////////////////////////////////////////////////////////////////
+/////////////// DIGITAL I/O FUNCTIONS /////////////////////////////
+/////////////////////////////////////////////////////////////////////
+// All DIO functions address a group of DIO channels by means of
+// "group" argument. group may be 0, 1 or 2, which correspond to DIO
+// ports A, B and C, respectively.
+/////////////////////////////////////////////////////////////////////
+
+static void s626_dio_init(comedi_device * dev)
+{
+ uint16_t group;
+ comedi_subdevice *s;
+
+ // Prepare to treat writes to WRCapSel as capture disables.
+ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+
+ // For each group of sixteen channels ...
+ for (group = 0; group < S626_DIO_BANKS; group++) {
+ s = dev->subdevices + 2 + group;
+ DEBIwrite(dev, diopriv->WRIntSel, 0); // Disable all interrupts.
+ DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF); // Disable all event
+ // captures.
+ DEBIwrite(dev, diopriv->WREdgSel, 0); // Init all DIOs to
+ // default edge
+ // polarity.
+ DEBIwrite(dev, diopriv->WRDOut, 0); // Program all outputs
+ // to inactive state.
+ }
+ DEBUG("s626_dio_init: DIO initialized \n");
+}
+
+/* DIO devices are slightly special. Although it is possible to
+ * implement the insn_read/insn_write interface, it is much more
+ * useful to applications if you implement the insn_bits interface.
+ * This allows packed reading/writing of the DIO channels. The comedi
+ * core can convert between insn_bits and insn_read/write */
+
+static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+
+ /* Length of data must be 2 (mask and new data, see below) */
+ if (insn->n == 0) {
+ return 0;
+ }
+ if (insn->n != 2) {
+ printk("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n", dev->minor);
+ return -EINVAL;
+ }
+
+ /*
+ * The insn data consists of a mask in data[0] and the new data in
+ * data[1]. The mask defines which bits we are concerning about.
+ * The new data must be anded with the mask. Each channel
+ * corresponds to a bit.
+ */
+ if (data[0]) {
+ /* Check if requested ports are configured for output */
+ if ((s->io_bits & data[0]) != data[0])
+ return -EIO;
+
+ s->state &= ~data[0];
+ s->state |= data[0] & data[1];
+
+ /* Write out the new digital output lines */
+
+ DEBIwrite(dev, diopriv->WRDOut, s->state);
+ }
+ data[1] = DEBIread(dev, diopriv->RDDIn);
+
+ return 2;
+}
+
+static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] =
+ (s->io_bits & (1 << CR_CHAN(insn->
+ chanspec))) ? COMEDI_OUTPUT :
+ COMEDI_INPUT;
+ return insn->n;
+ break;
+ case COMEDI_INPUT:
+ s->io_bits &= ~(1 << CR_CHAN(insn->chanspec));
+ break;
+ case COMEDI_OUTPUT:
+ s->io_bits |= 1 << CR_CHAN(insn->chanspec);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ DEBIwrite(dev, diopriv->WRDOut, s->io_bits);
+
+ return 1;
+}
+
+static int s626_dio_set_irq(comedi_device * dev, unsigned int chan)
+{
+ unsigned int group;
+ unsigned int bitmask;
+ unsigned int status;
+
+ //select dio bank
+ group = chan / 16;
+ bitmask = 1 << (chan - (16 * group));
+ DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n",
+ chan - (16 * group), group);
+
+ //set channel to capture positive edge
+ status = DEBIread(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->RDEdgSel);
+ DEBIwrite(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->WREdgSel, bitmask | status);
+
+ //enable interrupt on selected channel
+ status = DEBIread(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->RDIntSel);
+ DEBIwrite(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->WRIntSel, bitmask | status);
+
+ //enable edge capture write command
+ DEBIwrite(dev, LP_MISC1, MISC1_EDCAP);
+
+ //enable edge capture on selected channel
+ status = DEBIread(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->RDCapSel);
+ DEBIwrite(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->WRCapSel, bitmask | status);
+
+ return 0;
+}
+
+static int s626_dio_reset_irq(comedi_device * dev, unsigned int group,
+ unsigned int mask)
+{
+ DEBUG("s626_dio_reset_irq: disable interrupt on dio channel %d group %d\n", mask, group);
+
+ //disable edge capture write command
+ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+
+ //enable edge capture on selected channel
+ DEBIwrite(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->WRCapSel, mask);
+
+ return 0;
+}
+
+static int s626_dio_clear_irq(comedi_device * dev)
+{
+ unsigned int group;
+
+ //disable edge capture write command
+ DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
+
+ for (group = 0; group < S626_DIO_BANKS; group++) {
+ //clear pending events and interrupt
+ DEBIwrite(dev,
+ ((dio_private *) (dev->subdevices + 2 +
+ group)->private)->WRCapSel, 0xffff);
+ }
+
+ return 0;
+}
+
+/* Now this function initializes the value of the counter (data[0])
+ and set the subdevice. To complete with trigger and interrupt
+ configuration */
+static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+ uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon
+ // index.
+ (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index.
+ (CLKSRC_COUNTER << BF_CLKSRC) | // Operating mode is Counter.
+ (CLKPOL_POS << BF_CLKPOL) | // Active high clock.
+ //( CNTDIR_UP << BF_CLKPOL ) | // Count direction is Down.
+ (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x.
+ (CLKENAB_INDEX << BF_CLKENAB);
+ /* uint16_t DisableIntSrc=TRUE; */
+ // uint32_t Preloadvalue; //Counter initial value
+ uint16_t valueSrclatch = LATCHSRC_AB_READ;
+ uint16_t enab = CLKENAB_ALWAYS;
+ enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+
+ DEBUG("s626_enc_insn_config: encoder config\n");
+
+ // (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]);
+
+ k->SetMode(dev, k, Setup, TRUE);
+ Preload(dev, k, *(insn->data));
+ k->PulseIndex(dev, k);
+ SetLatchSource(dev, k, valueSrclatch);
+ k->SetEnable(dev, k, (uint16_t) (enab != 0));
+
+ return insn->n;
+}
+
+static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+
+ int n;
+ enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+
+ DEBUG("s626_enc_insn_read: encoder read channel %d \n",
+ CR_CHAN(insn->chanspec));
+
+ for (n = 0; n < insn->n; n++)
+ data[n] = ReadLatch(dev, k);
+
+ DEBUG("s626_enc_insn_read: encoder sample %d\n", data[n]);
+
+ return n;
+}
+
+static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s,
+ comedi_insn * insn, lsampl_t * data)
+{
+
+ enc_private *k = &encpriv[CR_CHAN(insn->chanspec)];
+
+ DEBUG("s626_enc_insn_write: encoder write channel %d \n",
+ CR_CHAN(insn->chanspec));
+
+ // Set the preload register
+ Preload(dev, k, data[0]);
+
+ // Software index pulse forces the preload register to load
+ // into the counter
+ k->SetLoadTrig(dev, k, 0);
+ k->PulseIndex(dev, k);
+ k->SetLoadTrig(dev, k, 2);
+
+ DEBUG("s626_enc_insn_write: End encoder write\n");
+
+ return 1;
+}
+
+static void s626_timer_load(comedi_device * dev, enc_private * k, int tick)
+{
+ uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon
+ // index.
+ (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index.
+ (CLKSRC_TIMER << BF_CLKSRC) | // Operating mode is Timer.
+ (CLKPOL_POS << BF_CLKPOL) | // Active high clock.
+ (CNTDIR_DOWN << BF_CLKPOL) | // Count direction is Down.
+ (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x.
+ (CLKENAB_INDEX << BF_CLKENAB);
+ uint16_t valueSrclatch = LATCHSRC_A_INDXA;
+ // uint16_t enab=CLKENAB_ALWAYS;
+
+ k->SetMode(dev, k, Setup, FALSE);
+
+ // Set the preload register
+ Preload(dev, k, tick);
+
+ // Software index pulse forces the preload register to load
+ // into the counter
+ k->SetLoadTrig(dev, k, 0);
+ k->PulseIndex(dev, k);
+
+ //set reload on counter overflow
+ k->SetLoadTrig(dev, k, 1);
+
+ //set interrupt on overflow
+ k->SetIntSrc(dev, k, INTSRC_OVER);
+
+ SetLatchSource(dev, k, valueSrclatch);
+ // k->SetEnable(dev,k,(uint16_t)(enab != 0));
+}
+
+///////////////////////////////////////////////////////////////////////
+///////////////////// DAC FUNCTIONS /////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+
+// Slot 0 base settings.
+#define VECT0 ( XSD2 | RSD3 | SIB_A2 ) // Slot 0 always shifts in
+ // 0xFF and store it to
+ // FB_BUFFER2.
+
+// TrimDac LogicalChan-to-PhysicalChan mapping table.
+static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 };
+
+// TrimDac LogicalChan-to-EepromAdrs mapping table.
+static uint8_t trimadrs[] =
+ { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 };
+
+static void LoadTrimDACs(comedi_device * dev)
+{
+ register uint8_t i;
+
+ // Copy TrimDac setpoint values from EEPROM to TrimDacs.
+ for (i = 0; i < (sizeof(trimchan) / sizeof(trimchan[0])); i++)
+ WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i]));
+}
+
+static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan,
+ uint8_t DacData)
+{
+ uint32_t chan;
+
+ // Save the new setpoint in case the application needs to read it back later.
+ devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData;
+
+ // Map logical channel number to physical channel number.
+ chan = (uint32_t) trimchan[LogicalChan];
+
+ // Set up TSL2 records for TrimDac write operation. All slots shift
+ // 0xFF in from pulled-up SD3 so that the end of the slot sequence
+ // can be detected.
+ SETVECT(2, XSD2 | XFIFO_1 | WS3); // Slot 2: Send high uint8_t
+ // to target TrimDac.
+ SETVECT(3, XSD2 | XFIFO_0 | WS3); // Slot 3: Send low uint8_t to
+ // target TrimDac.
+ SETVECT(4, XSD2 | XFIFO_3 | WS1); // Slot 4: Send NOP high
+ // uint8_t to DAC0 to keep
+ // clock running.
+ SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS); // Slot 5: Send NOP low
+ // uint8_t to DAC0.
+
+ // Construct and transmit target DAC's serial packet: ( 0000 AAAA
+ // ),( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the DAC
+ // channel's address, and D<7:0> is the DAC setpoint. Append a WORD
+ // value (that writes a channel 0 NOP command to a non-existent main
+ // DAC channel) that serves to keep the clock running after the
+ // packet has been sent to the target DAC.
+
+ SendDAC(dev, ((uint32_t) chan << 8) // Address the DAC channel
+ // within the trimdac device.
+ | (uint32_t) DacData); // Include DAC setpoint data.
+}
+
+/////////////////////////////////////////////////////////////////////////
+//////////////// EEPROM ACCESS FUNCTIONS //////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////
+// Read uint8_t from EEPROM.
+
+static uint8_t I2Cread(comedi_device * dev, uint8_t addr)
+{
+ uint8_t rtnval;
+
+ // Send EEPROM target address.
+ if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW) // Byte2 = I2C
+ // command:
+ // write to
+ // I2C EEPROM
+ // device.
+ | I2C_B1(I2C_ATTRSTOP, addr) // Byte1 = EEPROM
+ // internal target
+ // address.
+ | I2C_B0(I2C_ATTRNOP, 0))) // Byte0 = Not
+ // sent.
+ {
+ // Abort function and declare error if handshake failed.
+ DEBUG("I2Cread: error handshake I2Cread a\n");
+ return 0;
+ }
+ // Execute EEPROM read.
+ if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR) // Byte2 = I2C
+ // command: read
+ // from I2C EEPROM
+ // device.
+ | I2C_B1(I2C_ATTRSTOP, 0) // Byte1 receives
+ // uint8_t from
+ // EEPROM.
+ | I2C_B0(I2C_ATTRNOP, 0))) // Byte0 = Not
+ // sent.
+ {
+ // Abort function and declare error if handshake failed.
+ DEBUG("I2Cread: error handshake I2Cread b\n");
+ return 0;
+ }
+ // Return copy of EEPROM value.
+ rtnval = (uint8_t) (RR7146(P_I2CCTRL) >> 16);
+ return rtnval;
+}
+
+static uint32_t I2Chandshake(comedi_device * dev, uint32_t val)
+{
+ // Write I2C command to I2C Transfer Control shadow register.
+ WR7146(P_I2CCTRL, val);
+
+ // Upload I2C shadow registers into working registers and wait for
+ // upload confirmation.
+
+ MC_ENABLE(P_MC2, MC2_UPLD_IIC);
+ while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ;
+
+ // Wait until I2C bus transfer is finished or an error occurs.
+ while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) ;
+
+ // Return non-zero if I2C error occured.
+ return RR7146(P_I2CCTRL) & I2C_ERR;
+
+}
+
+// Private helper function: Write setpoint to an application DAC channel.
+
+static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata)
+{
+ register uint16_t signmask;
+ register uint32_t WSImage;
+
+ // Adjust DAC data polarity and set up Polarity Control Register
+ // image.
+ signmask = 1 << chan;
+ if (dacdata < 0) {
+ dacdata = -dacdata;
+ devpriv->Dacpol |= signmask;
+ } else
+ devpriv->Dacpol &= ~signmask;
+
+ // Limit DAC setpoint value to valid range.
+ if ((uint16_t) dacdata > 0x1FFF)
+ dacdata = 0x1FFF;
+
+ // Set up TSL2 records (aka "vectors") for DAC update. Vectors V2
+ // and V3 transmit the setpoint to the target DAC. V4 and V5 send
+ // data to a non-existent TrimDac channel just to keep the clock
+ // running after sending data to the target DAC. This is necessary
+ // to eliminate the clock glitch that would otherwise occur at the
+ // end of the target DAC's serial data stream. When the sequence
+ // restarts at V0 (after executing V5), the gate array automatically
+ // disables gating for the DAC clock and all DAC chip selects.
+ WSImage = (chan & 2) ? WS1 : WS2; // Choose DAC chip select to
+ // be asserted.
+ SETVECT(2, XSD2 | XFIFO_1 | WSImage); // Slot 2: Transmit high
+ // data byte to target DAC.
+ SETVECT(3, XSD2 | XFIFO_0 | WSImage); // Slot 3: Transmit low data
+ // byte to target DAC.
+ SETVECT(4, XSD2 | XFIFO_3 | WS3); // Slot 4: Transmit to
+ // non-existent TrimDac
+ // channel to keep clock
+ SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS); // Slot 5: running after
+ // writing target DAC's
+ // low data byte.
+
+ // Construct and transmit target DAC's serial packet: ( A10D DDDD
+ // ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, and D<12:0>
+ // is the DAC setpoint. Append a WORD value (that writes to a
+ // non-existent TrimDac channel) that serves to keep the clock
+ // running after the packet has been sent to the target DAC.
+ SendDAC(dev, 0x0F000000 //Continue clock after target DAC
+ //data (write to non-existent
+ //trimdac).
+ | 0x00004000 // Address the two main dual-DAC
+ // devices (TSL's chip select enables
+ // target device).
+ | ((uint32_t) (chan & 1) << 15) // Address the DAC
+ // channel within the
+ // device.
+ | (uint32_t) dacdata); // Include DAC setpoint data.
+
+}
+
+////////////////////////////////////////////////////////
+// Private helper function: Transmit serial data to DAC via Audio
+// channel 2. Assumes: (1) TSL2 slot records initialized, and (2)
+// Dacpol contains valid target image.
+
+static void SendDAC(comedi_device * dev, uint32_t val)
+{
+
+ // START THE SERIAL CLOCK RUNNING -------------
+
+ // Assert DAC polarity control and enable gating of DAC serial clock
+ // and audio bit stream signals. At this point in time we must be
+ // assured of being in time slot 0. If we are not in slot 0, the
+ // serial clock and audio stream signals will be disabled; this is
+ // because the following DEBIwrite statement (which enables signals
+ // to be passed through the gate array) would execute before the
+ // trailing edge of WS1/WS3 (which turns off the signals), thus
+ // causing the signals to be inactive during the DAC write.
+ DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol);
+
+ // TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ----------------
+
+ // Copy DAC setpoint value to DAC's output DMA buffer.
+
+ //WR7146( (uint32_t)devpriv->pDacWBuf, val );
+ *devpriv->pDacWBuf = val;
+
+ // enab the output DMA transfer. This will cause the DMAC to copy
+ // the DAC's data value to A2's output FIFO. The DMA transfer will
+ // then immediately terminate because the protection address is
+ // reached upon transfer of the first DWORD value.
+ MC_ENABLE(P_MC1, MC1_A2OUT);
+
+ // While the DMA transfer is executing ...
+
+ // Reset Audio2 output FIFO's underflow flag (along with any other
+ // FIFO underflow/overflow flags). When set, this flag will
+ // indicate that we have emerged from slot 0.
+ WR7146(P_ISR, ISR_AFOU);
+
+ // Wait for the DMA transfer to finish so that there will be data
+ // available in the FIFO when time slot 1 tries to transfer a DWORD
+ // from the FIFO to the output buffer register. We test for DMA
+ // Done by polling the DMAC enable flag; this flag is automatically
+ // cleared when the transfer has finished.
+ while ((RR7146(P_MC1) & MC1_A2OUT) != 0) ;
+
+ // START THE OUTPUT STREAM TO THE TARGET DAC --------------------
+
+ // FIFO data is now available, so we enable execution of time slots
+ // 1 and higher by clearing the EOS flag in slot 0. Note that SD3
+ // will be shifted in and stored in FB_BUFFER2 for end-of-slot-list
+ // detection.
+ SETVECT(0, XSD2 | RSD3 | SIB_A2);
+
+ // Wait for slot 1 to execute to ensure that the Packet will be
+ // transmitted. This is detected by polling the Audio2 output FIFO
+ // underflow flag, which will be set when slot 1 execution has
+ // finished transferring the DAC's data DWORD from the output FIFO
+ // to the output buffer register.
+ while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) ;
+
+ // Set up to trap execution at slot 0 when the TSL sequencer cycles
+ // back to slot 0 after executing the EOS in slot 5. Also,
+ // simultaneously shift out and in the 0x00 that is ALWAYS the value
+ // stored in the last byte to be shifted out of the FIFO's DWORD
+ // buffer register.
+ SETVECT(0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS);
+
+ // WAIT FOR THE TRANSACTION TO FINISH -----------------------
+
+ // Wait for the TSL to finish executing all time slots before
+ // exiting this function. We must do this so that the next DAC
+ // write doesn't start, thereby enabling clock/chip select signals:
+ // 1. Before the TSL sequence cycles back to slot 0, which disables
+ // the clock/cs signal gating and traps slot // list execution. If
+ // we have not yet finished slot 5 then the clock/cs signals are
+ // still gated and we have // not finished transmitting the stream.
+ // 2. While slots 2-5 are executing due to a late slot 0 trap. In
+ // this case, the slot sequence is currently // repeating, but with
+ // clock/cs signals disabled. We must wait for slot 0 to trap
+ // execution before setting // up the next DAC setpoint DMA transfer
+ // and enabling the clock/cs signals. To detect the end of slot 5,
+ // we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If
+ // the TSL has not yet finished executing slot 5 ...
+ if ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) {
+ // The trap was set on time and we are still executing somewhere
+ // in slots 2-5, so we now wait for slot 0 to execute and trap
+ // TSL execution. This is detected when FB_BUFFER2 MSB changes
+ // from 0xFF to 0x00, which slot 0 causes to happen by shifting
+ // out/in on SD2 the 0x00 that is always referenced by slot 5.
+ while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) ;
+ }
+ // Either (1) we were too late setting the slot 0 trap; the TSL
+ // sequencer restarted slot 0 before we could set the EOS trap flag,
+ // or (2) we were not late and execution is now trapped at slot 0.
+ // In either case, we must now change slot 0 so that it will store
+ // value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes.
+ // In order to do this, we reprogram slot 0 so that it will shift in
+ // SD3, which is driven only by a pull-up resistor.
+ SETVECT(0, RSD3 | SIB_A2 | EOS);
+
+ // Wait for slot 0 to execute, at which time the TSL is setup for
+ // the next DAC write. This is detected when FB_BUFFER2 MSB changes
+ // from 0x00 to 0xFF.
+ while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) ;
+}
+
+static void WriteMISC2(comedi_device * dev, uint16_t NewImage)
+{
+ DEBIwrite(dev, LP_MISC1, MISC1_WENABLE); // enab writes to
+ // MISC2 register.
+ DEBIwrite(dev, LP_WRMISC2, NewImage); // Write new image to MISC2.
+ DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE); // Disable writes to MISC2.
+}
+
+/////////////////////////////////////////////////////////////////////
+// Initialize the DEBI interface for all transfers.
+
+static uint16_t DEBIread(comedi_device * dev, uint16_t addr)
+{
+ uint16_t retval;
+
+ // Set up DEBI control register value in shadow RAM.
+ WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr);
+
+ // Execute the DEBI transfer.
+ DEBItransfer(dev);
+
+ // Fetch target register value.
+ retval = (uint16_t) RR7146(P_DEBIAD);
+
+ // Return register value.
+ return retval;
+}
+
+// Execute a DEBI transfer. This must be called from within a
+// critical section.
+static void DEBItransfer(comedi_device * dev)
+{
+ // Initiate upload of shadow RAM to DEBI control register.
+ MC_ENABLE(P_MC2, MC2_UPLD_DEBI);
+
+ // Wait for completion of upload from shadow RAM to DEBI control
+ // register.
+ while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) ;
+
+ // Wait until DEBI transfer is done.
+ while (RR7146(P_PSR) & PSR_DEBI_S) ;
+}
+
+// Write a value to a gate array register.
+static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata)
+{
+
+ // Set up DEBI control register value in shadow RAM.
+ WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr);
+ WR7146(P_DEBIAD, wdata);
+
+ // Execute the DEBI transfer.
+ DEBItransfer(dev);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Replace the specified bits in a gate array register. Imports: mask
+// specifies bits that are to be preserved, wdata is new value to be
+// or'd with the masked original.
+static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask,
+ uint16_t wdata)
+{
+
+ // Copy target gate array register into P_DEBIAD register.
+ WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); // Set up DEBI control
+ // reg value in shadow
+ // RAM.
+ DEBItransfer(dev); // Execute the DEBI
+ // Read transfer.
+
+ // Write back the modified image.
+ WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); // Set up DEBI control
+ // reg value in shadow
+ // RAM.
+
+ WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask)); // Modify the register image.
+ DEBItransfer(dev); // Execute the DEBI Write transfer.
+}
+
+static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize)
+{
+ void *vbptr;
+ dma_addr_t vpptr;
+
+ DEBUG("CloseDMAB: Entering S626DRV_CloseDMAB():\n");
+ if (pdma == NULL)
+ return;
+ //find the matching allocation from the board struct
+
+ vbptr = pdma->LogicalBase;
+ vpptr = pdma->PhysicalBase;
+ if (vbptr) {
+ pci_free_consistent(devpriv->pdev, bsize, vbptr, vpptr);
+ pdma->LogicalBase = 0;
+ pdma->PhysicalBase = 0;
+
+ DEBUG("CloseDMAB(): Logical=%p, bsize=%d, Physical=0x%x\n",
+ vbptr, bsize, (uint32_t) vpptr);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+///////////////// COUNTER FUNCTIONS //////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+// All counter functions address a specific counter by means of the
+// "Counter" argument, which is a logical counter number. The Counter
+// argument may have any of the following legal values: 0=0A, 1=1A,
+// 2=2A, 3=0B, 4=1B, 5=2B.
+////////////////////////////////////////////////////////////////////////
+
+// Forward declarations for functions that are common to both A and B
+// counters:
+
+/////////////////////////////////////////////////////////////////////
+//////////////////// PRIVATE COUNTER FUNCTIONS /////////////////////
+/////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////
+// Read a counter's output latch.
+
+static uint32_t ReadLatch(comedi_device * dev, enc_private * k)
+{
+ register uint32_t value;
+ //DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n");
+
+ // Latch counts and fetch LSW of latched counts value.
+ value = (uint32_t) DEBIread(dev, k->MyLatchLsw);
+
+ // Fetch MSW of latched counts and combine with LSW.
+ value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16);
+
+ // DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n");
+
+ // Return latched counts.
+ return value;
+}
+
+///////////////////////////////////////////////////////////////////
+// Reset a counter's index and overflow event capture flags.
+
+static void ResetCapFlags_A(comedi_device * dev, enc_private * k)
+{
+ DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
+}
+
+static void ResetCapFlags_B(comedi_device * dev, enc_private * k)
+{
+ DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B);
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Return counter setup in a format (COUNTER_SETUP) that is consistent
+// for both A and B counters.
+
+static uint16_t GetMode_A(comedi_device * dev, enc_private * k)
+{
+ register uint16_t cra;
+ register uint16_t crb;
+ register uint16_t setup;
+
+ // Fetch CRA and CRB register images.
+ cra = DEBIread(dev, k->MyCRA);
+ crb = DEBIread(dev, k->MyCRB);
+
+ // Populate the standardized counter setup bit fields. Note:
+ // IndexSrc is restricted to ENC_X or IndxPol.
+ setup = ((cra & STDMSK_LOADSRC) // LoadSrc = LoadSrcA.
+ | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) // LatchSrc = LatchSrcA.
+ | ((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC) // IntSrc = IntSrcA.
+ | ((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC) // IndxSrc = IndxSrcA<1>.
+ | ((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL) // IndxPol = IndxPolA.
+ | ((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB)); // ClkEnab = ClkEnabA.
+
+ // Adjust mode-dependent parameters.
+ if (cra & (2 << CRABIT_CLKSRC_A)) // If Timer mode (ClkSrcA<1> == 1):
+ setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) // Indicate Timer mode.
+ | ((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL) // Set ClkPol to indicate count direction (ClkSrcA<0>).
+ | (MULT_X1 << STDBIT_CLKMULT)); // ClkMult must be 1x in Timer mode.
+
+ else // If Counter mode (ClkSrcA<1> == 0):
+ setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) // Indicate Counter mode.
+ | ((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL) // Pass through ClkPol.
+ | (((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ? // Force ClkMult to 1x if not legal, else pass through.
+ (MULT_X1 << STDBIT_CLKMULT) :
+ ((cra >> (CRABIT_CLKMULT_A -
+ STDBIT_CLKMULT)) &
+ STDMSK_CLKMULT)));
+
+ // Return adjusted counter setup.
+ return setup;
+}
+
+static uint16_t GetMode_B(comedi_device * dev, enc_private * k)
+{
+ register uint16_t cra;
+ register uint16_t crb;
+ register uint16_t setup;
+
+ // Fetch CRA and CRB register images.
+ cra = DEBIread(dev, k->MyCRA);
+ crb = DEBIread(dev, k->MyCRB);
+
+ // Populate the standardized counter setup bit fields. Note:
+ // IndexSrc is restricted to ENC_X or IndxPol.
+ setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC) // IntSrc = IntSrcB.
+ | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) // LatchSrc = LatchSrcB.
+ | ((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC) // LoadSrc = LoadSrcB.
+ | ((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL) // IndxPol = IndxPolB.
+ | ((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB) // ClkEnab = ClkEnabB.
+ | ((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC)); // IndxSrc = IndxSrcB<1>.
+
+ // Adjust mode-dependent parameters.
+ if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B)) // If Extender mode (ClkMultB == MULT_X0):
+ setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC) // Indicate Extender mode.
+ | (MULT_X1 << STDBIT_CLKMULT) // Indicate multiplier is 1x.
+ | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); // Set ClkPol equal to Timer count direction (ClkSrcB<0>).
+
+ else if (cra & (2 << CRABIT_CLKSRC_B)) // If Timer mode (ClkSrcB<1> == 1):
+ setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) // Indicate Timer mode.
+ | (MULT_X1 << STDBIT_CLKMULT) // Indicate multiplier is 1x.
+ | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); // Set ClkPol equal to Timer count direction (ClkSrcB<0>).
+
+ else // If Counter mode (ClkSrcB<1> == 0):
+ setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) // Indicate Timer mode.
+ | ((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT) // Clock multiplier is passed through.
+ | ((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL)); // Clock polarity is passed through.
+
+ // Return adjusted counter setup.
+ return setup;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Set the operating mode for the specified counter. The setup
+// parameter is treated as a COUNTER_SETUP data type. The following
+// parameters are programmable (all other parms are ignored): ClkMult,
+// ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc.
+
+static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup,
+ uint16_t DisableIntSrc)
+{
+ register uint16_t cra;
+ register uint16_t crb;
+ register uint16_t setup = Setup; // Cache the Standard Setup.
+
+ // Initialize CRA and CRB images.
+ cra = ((setup & CRAMSK_LOADSRC_A) // Preload trigger is passed through.
+ | ((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1)))); // IndexSrc is restricted to ENC_X or IndxPol.
+
+ crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A // Reset any pending CounterA event captures.
+ | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB))); // Clock enable is passed through.
+
+ // Force IntSrc to Disabled if DisableIntSrc is asserted.
+ if (!DisableIntSrc)
+ cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
+ CRABIT_INTSRC_A));
+
+ // Populate all mode-dependent attributes of CRA & CRB images.
+ switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
+ case CLKSRC_EXTENDER: // Extender Mode: Force to Timer mode
+ // (Extender valid only for B counters).
+
+ case CLKSRC_TIMER: // Timer Mode:
+ cra |= ((2 << CRABIT_CLKSRC_A) // ClkSrcA<1> selects system clock
+ | ((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) // with count direction (ClkSrcA<0>) obtained from ClkPol.
+ | (1 << CRABIT_CLKPOL_A) // ClkPolA behaves as always-on clock enable.
+ | (MULT_X1 << CRABIT_CLKMULT_A)); // ClkMult must be 1x.
+ break;
+
+ default: // Counter Mode:
+ cra |= (CLKSRC_COUNTER // Select ENC_C and ENC_D as clock/direction inputs.
+ | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) // Clock polarity is passed through.
+ | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? // Force multiplier to x1 if not legal, otherwise pass through.
+ (MULT_X1 << CRABIT_CLKMULT_A) :
+ ((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A -
+ STDBIT_CLKMULT))));
+ }
+
+ // Force positive index polarity if IndxSrc is software-driven only,
+ // otherwise pass it through.
+ if (~setup & STDMSK_INDXSRC)
+ cra |= ((setup & STDMSK_INDXPOL) << (CRABIT_INDXPOL_A -
+ STDBIT_INDXPOL));
+
+ // If IntSrc has been forced to Disabled, update the MISC2 interrupt
+ // enable mask to indicate the counter interrupt is disabled.
+ if (DisableIntSrc)
+ devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
+
+ // While retaining CounterB and LatchSrc configurations, program the
+ // new counter operating mode.
+ DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra);
+ DEBIreplace(dev, k->MyCRB,
+ (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb);
+}
+
+static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup,
+ uint16_t DisableIntSrc)
+{
+ register uint16_t cra;
+ register uint16_t crb;
+ register uint16_t setup = Setup; // Cache the Standard Setup.
+
+ // Initialize CRA and CRB images.
+ cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)); // IndexSrc field is restricted to ENC_X or IndxPol.
+
+ crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B // Reset event captures and disable interrupts.
+ | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) // Clock enable is passed through.
+ | ((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B))); // Preload trigger source is passed through.
+
+ // Force IntSrc to Disabled if DisableIntSrc is asserted.
+ if (!DisableIntSrc)
+ crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC -
+ CRBBIT_INTSRC_B));
+
+ // Populate all mode-dependent attributes of CRA & CRB images.
+ switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) {
+ case CLKSRC_TIMER: // Timer Mode:
+ cra |= ((2 << CRABIT_CLKSRC_B) // ClkSrcB<1> selects system clock
+ | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); // with direction (ClkSrcB<0>) obtained from ClkPol.
+ crb |= ((1 << CRBBIT_CLKPOL_B) // ClkPolB behaves as always-on clock enable.
+ | (MULT_X1 << CRBBIT_CLKMULT_B)); // ClkMultB must be 1x.
+ break;
+
+ case CLKSRC_EXTENDER: // Extender Mode:
+ cra |= ((2 << CRABIT_CLKSRC_B) // ClkSrcB source is OverflowA (same as "timer")
+ | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); // with direction obtained from ClkPol.
+ crb |= ((1 << CRBBIT_CLKPOL_B) // ClkPolB controls IndexB -- always set to active.
+ | (MULT_X0 << CRBBIT_CLKMULT_B)); // ClkMultB selects OverflowA as the clock source.
+ break;
+
+ default: // Counter Mode:
+ cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B); // Select ENC_C and ENC_D as clock/direction inputs.
+ crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) // ClkPol is passed through.
+ | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? // Force ClkMult to x1 if not legal, otherwise pass through.
+ (MULT_X1 << CRBBIT_CLKMULT_B) :
+ ((setup & STDMSK_CLKMULT) << (CRBBIT_CLKMULT_B -
+ STDBIT_CLKMULT))));
+ }
+
+ // Force positive index polarity if IndxSrc is software-driven only,
+ // otherwise pass it through.
+ if (~setup & STDMSK_INDXSRC)
+ crb |= ((setup & STDMSK_INDXPOL) >> (STDBIT_INDXPOL -
+ CRBBIT_INDXPOL_B));
+
+ // If IntSrc has been forced to Disabled, update the MISC2 interrupt
+ // enable mask to indicate the counter interrupt is disabled.
+ if (DisableIntSrc)
+ devpriv->CounterIntEnabs &= ~k->MyEventBits[3];
+
+ // While retaining CounterA and LatchSrc configurations, program the
+ // new counter operating mode.
+ DEBIreplace(dev, k->MyCRA,
+ (uint16_t) (~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B)), cra);
+ DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb);
+}
+
+////////////////////////////////////////////////////////////////////////
+// Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index.
+
+static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab)
+{
+ DEBUG("SetEnable_A: SetEnable_A enter 3541\n");
+ DEBIreplace(dev, k->MyCRB,
+ (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)),
+ (uint16_t) (enab << CRBBIT_CLKENAB_A));
+}
+
+static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab)
+{
+ DEBIreplace(dev, k->MyCRB,
+ (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)),
+ (uint16_t) (enab << CRBBIT_CLKENAB_B));
+}
+
+static uint16_t GetEnable_A(comedi_device * dev, enc_private * k)
+{
+ return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1;
+}
+
+static uint16_t GetEnable_B(comedi_device * dev, enc_private * k)
+{
+ return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1;
+}
+
+////////////////////////////////////////////////////////////////////////
+// Return/set a counter pair's latch trigger source. 0: On read
+// access, 1: A index latches A, 2: B index latches B, 3: A overflow
+// latches B.
+
+static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value)
+{
+ DEBUG("SetLatchSource: SetLatchSource enter 3550 \n");
+ DEBIreplace(dev, k->MyCRB,
+ (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC)),
+ (uint16_t) (value << CRBBIT_LATCHSRC));
+
+ DEBUG("SetLatchSource: SetLatchSource exit \n");
+}
+
+/* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ) */
+/* { */
+/* return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3; */
+/* } */
+
+/////////////////////////////////////////////////////////////////////////
+// Return/set the event that will trigger transfer of the preload
+// register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow,
+// 2=OverflowA (B counters only), 3=disabled.
+
+static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig)
+{
+ DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A),
+ (uint16_t) (Trig << CRABIT_LOADSRC_A));
+}
+
+static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig)
+{
+ DEBIreplace(dev, k->MyCRB,
+ (uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)),
+ (uint16_t) (Trig << CRBBIT_LOADSRC_B));
+}
+
+static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k)
+{
+ return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3;
+}
+
+static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k)
+{
+ return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3;
+}
+
+////////////////////
+// Return/set counter interrupt source and clear any captured
+// index/overflow events. IntSource: 0=Disabled, 1=OverflowOnly,
+// 2=IndexOnly, 3=IndexAndOverflow.
+
+static void SetIntSrc_A(comedi_device * dev, enc_private * k,
+ uint16_t IntSource)
+{
+ // Reset any pending counter overflow or index captures.
+ DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL),
+ CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A);
+
+ // Program counter interrupt source.
+ DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A,
+ (uint16_t) (IntSource << CRABIT_INTSRC_A));
+
+ // Update MISC2 interrupt enable mask.
+ devpriv->CounterIntEnabs =
+ (devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k->
+ MyEventBits[IntSource];
+}
+
+static void SetIntSrc_B(comedi_device * dev, enc_private * k,
+ uint16_t IntSource)
+{
+ uint16_t crb;
+
+ // Cache writeable CRB register image.
+ crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL;
+
+ // Reset any pending counter overflow or index captures.
+ DEBIwrite(dev, k->MyCRB,
+ (uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B));
+
+ // Program counter interrupt source.
+ DEBIwrite(dev, k->MyCRB,
+ (uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource <<
+ CRBBIT_INTSRC_B)));
+
+ // Update MISC2 interrupt enable mask.
+ devpriv->CounterIntEnabs =
+ (devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k->
+ MyEventBits[IntSource];
+}
+
+static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k)
+{
+ return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3;
+}
+
+static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k)
+{
+ return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Return/set the clock multiplier.
+
+/* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) */
+/* { */
+/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */
+/* } */
+
+/* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) */
+/* { */
+/* return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */
+/* } */
+
+/* ////////////////////////////////////////////////////////////////////////// */
+/* // Return/set the clock polarity. */
+
+/* static void SetClkPol( comedi_device *dev,enc_private *k, uint16_t value ) */
+/* { */
+/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */
+/* } */
+
+/* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) */
+/* { */
+/* return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */
+/* } */
+
+/* /////////////////////////////////////////////////////////////////////// */
+/* // Return/set the clock source. */
+
+/* static void SetClkSrc( comedi_device *dev,enc_private *k, uint16_t value ) */
+/* { */
+/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */
+/* } */
+
+/* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ) */
+/* { */
+/* return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */
+/* } */
+
+/* //////////////////////////////////////////////////////////////////////// */
+/* // Return/set the index polarity. */
+
+/* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ) */
+/* { */
+/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */
+/* } */
+
+/* static uint16_t GetIndexPol(comedi_device *dev, enc_private *k ) */
+/* { */
+/* return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */
+/* } */
+
+/* //////////////////////////////////////////////////////////////////////// */
+/* // Return/set the index source. */
+
+/* static void SetIndexSrc(comedi_device *dev, enc_private *k, uint16_t value ) */
+/* { */
+/* DEBUG("SetIndexSrc: set index src enter 3700\n"); */
+/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */
+/* } */
+
+/* static uint16_t GetIndexSrc(comedi_device *dev, enc_private *k ) */
+/* { */
+/* return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */
+/* } */
+
+///////////////////////////////////////////////////////////////////
+// Generate an index pulse.
+
+static void PulseIndex_A(comedi_device * dev, enc_private * k)
+{
+ register uint16_t cra;
+
+ DEBUG("PulseIndex_A: pulse index enter\n");
+
+ cra = DEBIread(dev, k->MyCRA); // Pulse index.
+ DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A));
+ DEBUG("PulseIndex_A: pulse index step1\n");
+ DEBIwrite(dev, k->MyCRA, cra);
+}
+
+static void PulseIndex_B(comedi_device * dev, enc_private * k)
+{
+ register uint16_t crb;
+
+ crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; // Pulse index.
+ DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B));
+ DEBIwrite(dev, k->MyCRB, crb);
+}
+
+/////////////////////////////////////////////////////////
+// Write value into counter preload register.
+
+static void Preload(comedi_device * dev, enc_private * k, uint32_t value)
+{
+ DEBUG("Preload: preload enter\n");
+ DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value); // Write value to preload register.
+ DEBUG("Preload: preload step 1\n");
+ DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2),
+ (uint16_t) (value >> 16));
+}
+
+static void CountersInit(comedi_device * dev)
+{
+ int chan;
+ enc_private *k;
+ uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon
+ // index.
+ (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index.
+ (CLKSRC_COUNTER << BF_CLKSRC) | // Operating mode is counter.
+ (CLKPOL_POS << BF_CLKPOL) | // Active high clock.
+ (CNTDIR_UP << BF_CLKPOL) | // Count direction is up.
+ (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x.
+ (CLKENAB_INDEX << BF_CLKENAB); // Enabled by index
+
+ // Disable all counter interrupts and clear any captured counter events.
+ for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) {
+ k = &encpriv[chan];
+ k->SetMode(dev, k, Setup, TRUE);
+ k->SetIntSrc(dev, k, 0);
+ k->ResetCapFlags(dev, k);
+ k->SetEnable(dev, k, CLKENAB_ALWAYS);
+ }
+ DEBUG("CountersInit: counters initialized \n");
+
+}
diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h
new file mode 100644
index 000000000000..11d8b1ceb0b8
--- /dev/null
+++ b/drivers/staging/comedi/drivers/s626.h
@@ -0,0 +1,802 @@
+/*
+ comedi/drivers/s626.h
+ Sensoray s626 Comedi driver, header file
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+
+ Based on Sensoray Model 626 Linux driver Version 0.2
+ Copyright (C) 2002-2004 Sensoray Co., Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/*
+ Driver: s626.o (s626.ko)
+ Description: Sensoray 626 driver
+ Devices: Sensoray s626
+ Authors: Gianluca Palli <gpalli@deis.unibo.it>,
+ Updated: Thu, 12 Jul 2005
+ Status: experimental
+
+ Configuration Options:
+ analog input:
+ none
+
+ analog output:
+ none
+
+ digital channel:
+ s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels
+ supported configuration options:
+ INSN_CONFIG_DIO_QUERY
+ COMEDI_INPUT
+ COMEDI_OUTPUT
+
+ encoder:
+ Every channel must be configured before reading.
+
+ Example code
+
+ insn.insn=INSN_CONFIG; //configuration instruction
+ insn.n=1; //number of operation (must be 1)
+ insn.data=&initialvalue; //initial value loaded into encoder
+ //during configuration
+ insn.subdev=5; //encoder subdevice
+ insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel
+ //to configure
+
+ comedi_do_insn(cf,&insn); //executing configuration
+*/
+
+#ifdef _DEBUG_
+#define DEBUG(...); rt_printk(__VA_ARGS__);
+#else
+#define DEBUG(...)
+#endif
+
+#if !defined(TRUE)
+#define TRUE (1)
+#endif
+
+#if !defined(FALSE)
+#define FALSE (0)
+#endif
+
+#if !defined(EXTERN)
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+#else
+#define EXTERN extern
+#endif
+#endif
+
+#if !defined(INLINE)
+#define INLINE static __inline
+#endif
+
+/////////////////////////////////////////////////////
+#include<linux/slab.h>
+
+#define S626_SIZE 0x0200
+#define SIZEOF_ADDRESS_SPACE 0x0200
+#define DMABUF_SIZE 4096 // 4k pages
+
+#define S626_ADC_CHANNELS 16
+#define S626_DAC_CHANNELS 4
+#define S626_ENCODER_CHANNELS 6
+#define S626_DIO_CHANNELS 48
+#define S626_DIO_BANKS 3 // Number of DIO groups.
+#define S626_DIO_EXTCHANS 40 // Number of
+ // extended-capability
+ // DIO channels.
+
+#define NUM_TRIMDACS 12 // Number of valid TrimDAC channels.
+
+// PCI bus interface types.
+#define INTEL 1 // Intel bus type.
+#define MOTOROLA 2 // Motorola bus type.
+
+//////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////
+#define PLATFORM INTEL // *** SELECT PLATFORM TYPE ***
+//////////////////////////////////////////////////////////
+
+#define RANGE_5V 0x10 // +/-5V range
+#define RANGE_10V 0x00 // +/-10V range
+
+#define EOPL 0x80 // End of ADC poll list marker.
+#define GSEL_BIPOLAR5V 0x00F0 // LP_GSEL setting for 5V bipolar range.
+#define GSEL_BIPOLAR10V 0x00A0 // LP_GSEL setting for 10V bipolar range.
+
+// Error codes that must be visible to this base class.
+#define ERR_ILLEGAL_PARM 0x00010000 // Illegal function parameter value was specified.
+#define ERR_I2C 0x00020000 // I2C error.
+#define ERR_COUNTERSETUP 0x00200000 // Illegal setup specified for counter channel.
+#define ERR_DEBI_TIMEOUT 0x00400000 // DEBI transfer timed out.
+
+// Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF.
+#define ADC_DMABUF_DWORDS 40 // ADC DMA buffer must hold 16 samples, plus pre/post garbage samples.
+#define DAC_WDMABUF_DWORDS 1 // DAC output DMA buffer holds a single sample.
+
+// All remaining space in 4KB DMA buffer is available for the RPS1 program.
+
+// Address offsets, in DWORDS, from base of DMA buffer.
+#define DAC_WDMABUF_OS ADC_DMABUF_DWORDS
+
+// Interrupt enab bit in ISR and IER.
+#define IRQ_GPIO3 0x00000040 // IRQ enable for GPIO3.
+#define IRQ_RPS1 0x10000000
+#define ISR_AFOU 0x00000800 // Audio fifo
+ // under/overflow
+ // detected.
+#define IRQ_COINT1A 0x0400 // conter 1A overflow
+ // interrupt mask
+#define IRQ_COINT1B 0x0800 // conter 1B overflow
+ // interrupt mask
+#define IRQ_COINT2A 0x1000 // conter 2A overflow
+ // interrupt mask
+#define IRQ_COINT2B 0x2000 // conter 2B overflow
+ // interrupt mask
+#define IRQ_COINT3A 0x4000 // conter 3A overflow
+ // interrupt mask
+#define IRQ_COINT3B 0x8000 // conter 3B overflow
+ // interrupt mask
+
+// RPS command codes.
+#define RPS_CLRSIGNAL 0x00000000 // CLEAR SIGNAL
+#define RPS_SETSIGNAL 0x10000000 // SET SIGNAL
+#define RPS_NOP 0x00000000 // NOP
+#define RPS_PAUSE 0x20000000 // PAUSE
+#define RPS_UPLOAD 0x40000000 // UPLOAD
+#define RPS_JUMP 0x80000000 // JUMP
+#define RPS_LDREG 0x90000100 // LDREG (1 uint32_t only)
+#define RPS_STREG 0xA0000100 // STREG (1 uint32_t only)
+#define RPS_STOP 0x50000000 // STOP
+#define RPS_IRQ 0x60000000 // IRQ
+
+#define RPS_LOGICAL_OR 0x08000000 // Logical OR conditionals.
+#define RPS_INVERT 0x04000000 // Test for negated semaphores.
+#define RPS_DEBI 0x00000002 // DEBI done
+
+#define RPS_SIG0 0x00200000 // RPS semaphore 0 (used by ADC).
+#define RPS_SIG1 0x00400000 // RPS semaphore 1 (used by DAC).
+#define RPS_SIG2 0x00800000 // RPS semaphore 2 (not used).
+#define RPS_GPIO2 0x00080000 // RPS GPIO2
+#define RPS_GPIO3 0x00100000 // RPS GPIO3
+
+#define RPS_SIGADC RPS_SIG0 // Trigger/status for ADC's RPS program.
+#define RPS_SIGDAC RPS_SIG1 // Trigger/status for DAC's RPS program.
+
+// RPS clock parameters.
+#define RPSCLK_SCALAR 8 // This is apparent ratio of PCI/RPS clks (undocumented!!).
+#define RPSCLK_PER_US ( 33 / RPSCLK_SCALAR ) // Number of RPS clocks in one microsecond.
+
+// Event counter source addresses.
+#define SBA_RPS_A0 0x27 // Time of RPS0 busy, in PCI clocks.
+
+// GPIO constants.
+#define GPIO_BASE 0x10004000 // GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out.
+#define GPIO1_LO 0x00000000 // GPIO1 set to LOW.
+#define GPIO1_HI 0x00001000 // GPIO1 set to HIGH.
+
+// Primary Status Register (PSR) constants.
+#define PSR_DEBI_E 0x00040000 // DEBI event flag.
+#define PSR_DEBI_S 0x00080000 // DEBI status flag.
+#define PSR_A2_IN 0x00008000 // Audio output DMA2 protection address reached.
+#define PSR_AFOU 0x00000800 // Audio FIFO under/overflow detected.
+#define PSR_GPIO2 0x00000020 // GPIO2 input pin: 0=AdcBusy, 1=AdcIdle.
+#define PSR_EC0S 0x00000001 // Event counter 0 threshold reached.
+
+// Secondary Status Register (SSR) constants.
+#define SSR_AF2_OUT 0x00000200 // Audio 2 output FIFO under/overflow detected.
+
+// Master Control Register 1 (MC1) constants.
+#define MC1_SOFT_RESET 0x80000000 // Invoke 7146 soft reset.
+#define MC1_SHUTDOWN 0x3FFF0000 // Shut down all MC1-controlled enables.
+
+#define MC1_ERPS1 0x2000 // enab/disable RPS task 1.
+#define MC1_ERPS0 0x1000 // enab/disable RPS task 0.
+#define MC1_DEBI 0x0800 // enab/disable DEBI pins.
+#define MC1_AUDIO 0x0200 // enab/disable audio port pins.
+#define MC1_I2C 0x0100 // enab/disable I2C interface.
+#define MC1_A2OUT 0x0008 // enab/disable transfer on A2 out.
+#define MC1_A2IN 0x0004 // enab/disable transfer on A2 in.
+#define MC1_A1IN 0x0001 // enab/disable transfer on A1 in.
+
+// Master Control Register 2 (MC2) constants.
+#define MC2_UPLD_DEBIq 0x00020002 // Upload DEBI registers.
+#define MC2_UPLD_IICq 0x00010001 // Upload I2C registers.
+#define MC2_RPSSIG2_ONq 0x20002000 // Assert RPS_SIG2.
+#define MC2_RPSSIG1_ONq 0x10001000 // Assert RPS_SIG1.
+#define MC2_RPSSIG0_ONq 0x08000800 // Assert RPS_SIG0.
+#define MC2_UPLD_DEBI_MASKq 0x00000002 // Upload DEBI mask.
+#define MC2_UPLD_IIC_MASKq 0x00000001 // Upload I2C mask.
+#define MC2_RPSSIG2_MASKq 0x00002000 // RPS_SIG2 bit mask.
+#define MC2_RPSSIG1_MASKq 0x00001000 // RPS_SIG1 bit mask.
+#define MC2_RPSSIG0_MASKq 0x00000800 // RPS_SIG0 bit mask.
+
+#define MC2_DELAYTRIG_4USq MC2_RPSSIG1_ON
+#define MC2_DELAYBUSY_4USq MC2_RPSSIG1_MASK
+
+#define MC2_DELAYTRIG_6USq MC2_RPSSIG2_ON
+#define MC2_DELAYBUSY_6USq MC2_RPSSIG2_MASK
+
+#define MC2_UPLD_DEBI 0x0002 // Upload DEBI.
+#define MC2_UPLD_IIC 0x0001 // Upload I2C.
+#define MC2_RPSSIG2 0x2000 // RPS signal 2 (not used).
+#define MC2_RPSSIG1 0x1000 // RPS signal 1 (DAC RPS busy).
+#define MC2_RPSSIG0 0x0800 // RPS signal 0 (ADC RPS busy).
+
+#define MC2_ADC_RPS MC2_RPSSIG0 // ADC RPS busy.
+#define MC2_DAC_RPS MC2_RPSSIG1 // DAC RPS busy.
+
+///////////////////oldies///////////
+#define MC2_UPLD_DEBIQ 0x00020002 // Upload DEBI registers.
+#define MC2_UPLD_IICQ 0x00010001 // Upload I2C registers.
+////////////////////////////////////////
+
+// PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS ////////////////////////
+#define P_PCI_BT_A 0x004C // Audio DMA
+ // burst/threshold
+ // control.
+#define P_DEBICFG 0x007C // DEBI configuration.
+#define P_DEBICMD 0x0080 // DEBI command.
+#define P_DEBIPAGE 0x0084 // DEBI page.
+#define P_DEBIAD 0x0088 // DEBI target address.
+#define P_I2CCTRL 0x008C // I2C control.
+#define P_I2CSTAT 0x0090 // I2C status.
+#define P_BASEA2_IN 0x00AC // Audio input 2 base
+ // physical DMAbuf
+ // address.
+#define P_PROTA2_IN 0x00B0 // Audio input 2
+ // physical DMAbuf
+ // protection address.
+#define P_PAGEA2_IN 0x00B4 // Audio input 2
+ // paging attributes.
+#define P_BASEA2_OUT 0x00B8 // Audio output 2 base
+ // physical DMAbuf
+ // address.
+#define P_PROTA2_OUT 0x00BC // Audio output 2
+ // physical DMAbuf
+ // protection address.
+#define P_PAGEA2_OUT 0x00C0 // Audio output 2
+ // paging attributes.
+#define P_RPSPAGE0 0x00C4 // RPS0 page.
+#define P_RPSPAGE1 0x00C8 // RPS1 page.
+#define P_RPS0_TOUT 0x00D4 // RPS0 time-out.
+#define P_RPS1_TOUT 0x00D8 // RPS1 time-out.
+#define P_IER 0x00DC // Interrupt enable.
+#define P_GPIO 0x00E0 // General-purpose I/O.
+#define P_EC1SSR 0x00E4 // Event counter set 1
+ // source select.
+#define P_ECT1R 0x00EC // Event counter
+ // threshold set 1.
+#define P_ACON1 0x00F4 // Audio control 1.
+#define P_ACON2 0x00F8 // Audio control 2.
+#define P_MC1 0x00FC // Master control 1.
+#define P_MC2 0x0100 // Master control 2.
+#define P_RPSADDR0 0x0104 // RPS0 instruction pointer.
+#define P_RPSADDR1 0x0108 // RPS1 instruction pointer.
+#define P_ISR 0x010C // Interrupt status.
+#define P_PSR 0x0110 // Primary status.
+#define P_SSR 0x0114 // Secondary status.
+#define P_EC1R 0x0118 // Event counter set 1.
+#define P_ADP4 0x0138 // Logical audio DMA
+ // pointer of audio
+ // input FIFO A2_IN.
+#define P_FB_BUFFER1 0x0144 // Audio feedback buffer 1.
+#define P_FB_BUFFER2 0x0148 // Audio feedback buffer 2.
+#define P_TSL1 0x0180 // Audio time slot list 1.
+#define P_TSL2 0x01C0 // Audio time slot list 2.
+
+// LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS /////////////////
+// Analog I/O registers:
+#define LP_DACPOL 0x0082 // Write DAC polarity.
+#define LP_GSEL 0x0084 // Write ADC gain.
+#define LP_ISEL 0x0086 // Write ADC channel select.
+// Digital I/O (write only):
+#define LP_WRINTSELA 0x0042 // Write A interrupt enable.
+#define LP_WREDGSELA 0x0044 // Write A edge selection.
+#define LP_WRCAPSELA 0x0046 // Write A capture enable.
+#define LP_WRDOUTA 0x0048 // Write A digital output.
+#define LP_WRINTSELB 0x0052 // Write B interrupt enable.
+#define LP_WREDGSELB 0x0054 // Write B edge selection.
+#define LP_WRCAPSELB 0x0056 // Write B capture enable.
+#define LP_WRDOUTB 0x0058 // Write B digital output.
+#define LP_WRINTSELC 0x0062 // Write C interrupt enable.
+#define LP_WREDGSELC 0x0064 // Write C edge selection.
+#define LP_WRCAPSELC 0x0066 // Write C capture enable.
+#define LP_WRDOUTC 0x0068 // Write C digital output.
+
+// Digital I/O (read only):
+#define LP_RDDINA 0x0040 // Read digital input.
+#define LP_RDCAPFLGA 0x0048 // Read edges captured.
+#define LP_RDINTSELA 0x004A // Read interrupt
+ // enable register.
+#define LP_RDEDGSELA 0x004C // Read edge
+ // selection
+ // register.
+#define LP_RDCAPSELA 0x004E // Read capture
+ // enable register.
+#define LP_RDDINB 0x0050 // Read digital input.
+#define LP_RDCAPFLGB 0x0058 // Read edges captured.
+#define LP_RDINTSELB 0x005A // Read interrupt
+ // enable register.
+#define LP_RDEDGSELB 0x005C // Read edge
+ // selection
+ // register.
+#define LP_RDCAPSELB 0x005E // Read capture
+ // enable register.
+#define LP_RDDINC 0x0060 // Read digital input.
+#define LP_RDCAPFLGC 0x0068 // Read edges captured.
+#define LP_RDINTSELC 0x006A // Read interrupt
+ // enable register.
+#define LP_RDEDGSELC 0x006C // Read edge
+ // selection
+ // register.
+#define LP_RDCAPSELC 0x006E // Read capture
+ // enable register.
+// Counter Registers (read/write):
+#define LP_CR0A 0x0000 // 0A setup register.
+#define LP_CR0B 0x0002 // 0B setup register.
+#define LP_CR1A 0x0004 // 1A setup register.
+#define LP_CR1B 0x0006 // 1B setup register.
+#define LP_CR2A 0x0008 // 2A setup register.
+#define LP_CR2B 0x000A // 2B setup register.
+// Counter PreLoad (write) and Latch (read) Registers:
+#define LP_CNTR0ALSW 0x000C // 0A lsw.
+#define LP_CNTR0AMSW 0x000E // 0A msw.
+#define LP_CNTR0BLSW 0x0010 // 0B lsw.
+#define LP_CNTR0BMSW 0x0012 // 0B msw.
+#define LP_CNTR1ALSW 0x0014 // 1A lsw.
+#define LP_CNTR1AMSW 0x0016 // 1A msw.
+#define LP_CNTR1BLSW 0x0018 // 1B lsw.
+#define LP_CNTR1BMSW 0x001A // 1B msw.
+#define LP_CNTR2ALSW 0x001C // 2A lsw.
+#define LP_CNTR2AMSW 0x001E // 2A msw.
+#define LP_CNTR2BLSW 0x0020 // 2B lsw.
+#define LP_CNTR2BMSW 0x0022 // 2B msw.
+// Miscellaneous Registers (read/write):
+#define LP_MISC1 0x0088 // Read/write Misc1.
+#define LP_WRMISC2 0x0090 // Write Misc2.
+#define LP_RDMISC2 0x0082 // Read Misc2.
+
+// Bit masks for MISC1 register that are the same for reads and writes.
+#define MISC1_WENABLE 0x8000 // enab writes to
+ // MISC2 (except Clear
+ // Watchdog bit).
+#define MISC1_WDISABLE 0x0000 // Disable writes to MISC2.
+#define MISC1_EDCAP 0x1000 // enab edge capture
+ // on DIO chans
+ // specified by
+ // LP_WRCAPSELx.
+#define MISC1_NOEDCAP 0x0000 // Disable edge
+ // capture on
+ // specified DIO
+ // chans.
+
+// Bit masks for MISC1 register reads.
+#define RDMISC1_WDTIMEOUT 0x4000 // Watchdog timer timed out.
+
+// Bit masks for MISC2 register writes.
+#define WRMISC2_WDCLEAR 0x8000 // Reset watchdog
+ // timer to zero.
+#define WRMISC2_CHARGE_ENABLE 0x4000 // enab battery
+ // trickle charging.
+
+// Bit masks for MISC2 register that are the same for reads and writes.
+#define MISC2_BATT_ENABLE 0x0008 // Backup battery enable.
+#define MISC2_WDENABLE 0x0004 // Watchdog timer enable.
+#define MISC2_WDPERIOD_MASK 0x0003 // Watchdog interval
+ // select mask.
+
+// Bit masks for ACON1 register.
+#define A2_RUN 0x40000000 // Run A2 based on TSL2.
+#define A1_RUN 0x20000000 // Run A1 based on TSL1.
+#define A1_SWAP 0x00200000 // Use big-endian for A1.
+#define A2_SWAP 0x00100000 // Use big-endian for A2.
+#define WS_MODES 0x00019999 // WS0 = TSL1 trigger
+ // input, WS1-WS4 =
+ // CS* outputs.
+
+#if PLATFORM == INTEL // Base ACON1 config:
+ // always run A1 based
+ // on TSL1.
+#define ACON1_BASE ( WS_MODES | A1_RUN )
+#elif PLATFORM == MOTOROLA
+#define ACON1_BASE ( WS_MODES | A1_RUN | A1_SWAP | A2_SWAP )
+#endif
+
+#define ACON1_ADCSTART ACON1_BASE // Start ADC: run A1
+ // based on TSL1.
+#define ACON1_DACSTART ( ACON1_BASE | A2_RUN ) // Start
+ // transmit to
+ // DAC: run A2
+ // based on
+ // TSL2.
+#define ACON1_DACSTOP ACON1_BASE // Halt A2.
+
+// Bit masks for ACON2 register.
+#define A1_CLKSRC_BCLK1 0x00000000 // A1 bit rate = BCLK1 (ADC).
+#define A2_CLKSRC_X1 0x00800000 // A2 bit rate = ACLK/1 (DACs).
+#define A2_CLKSRC_X2 0x00C00000 // A2 bit rate = ACLK/2 (DACs).
+#define A2_CLKSRC_X4 0x01400000 // A2 bit rate = ACLK/4 (DACs).
+#define INVERT_BCLK2 0x00100000 // Invert BCLK2 (DACs).
+#define BCLK2_OE 0x00040000 // enab BCLK2 (DACs).
+#define ACON2_XORMASK 0x000C0000 // XOR mask for ACON2
+ // active-low bits.
+
+#define ACON2_INIT ( ACON2_XORMASK ^ ( A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE ) )
+
+// Bit masks for timeslot records.
+#define WS1 0x40000000 // WS output to assert.
+#define WS2 0x20000000
+#define WS3 0x10000000
+#define WS4 0x08000000
+#define RSD1 0x01000000 // Shift A1 data in on SD1.
+#define SDW_A1 0x00800000 // Store rcv'd char at
+ // next char slot of
+ // DWORD1 buffer.
+#define SIB_A1 0x00400000 // Store rcv'd char at
+ // next char slot of
+ // FB1 buffer.
+#define SF_A1 0x00200000 // Write unsigned long
+ // buffer to input
+ // FIFO.
+
+//Select parallel-to-serial converter's data source:
+#define XFIFO_0 0x00000000 // Data fifo byte 0.
+#define XFIFO_1 0x00000010 // Data fifo byte 1.
+#define XFIFO_2 0x00000020 // Data fifo byte 2.
+#define XFIFO_3 0x00000030 // Data fifo byte 3.
+#define XFB0 0x00000040 // FB_BUFFER byte 0.
+#define XFB1 0x00000050 // FB_BUFFER byte 1.
+#define XFB2 0x00000060 // FB_BUFFER byte 2.
+#define XFB3 0x00000070 // FB_BUFFER byte 3.
+#define SIB_A2 0x00000200 // Store next dword
+ // from A2's input
+ // shifter to FB2
+ // buffer.
+#define SF_A2 0x00000100 // Store next dword
+ // from A2's input
+ // shifter to its
+ // input fifo.
+#define LF_A2 0x00000080 // Load next dword
+ // from A2's output
+ // fifo into its
+ // output dword
+ // buffer.
+#define XSD2 0x00000008 // Shift data out on SD2.
+#define RSD3 0x00001800 // Shift data in on SD3.
+#define RSD2 0x00001000 // Shift data in on SD2.
+#define LOW_A2 0x00000002 // Drive last SD low
+ // for 7 clks, then
+ // tri-state.
+#define EOS 0x00000001 // End of superframe.
+
+//////////////////////
+
+// I2C configuration constants.
+#define I2C_CLKSEL 0x0400 // I2C bit rate =
+ // PCIclk/480 = 68.75
+ // KHz.
+#define I2C_BITRATE 68.75 // I2C bus data bit
+ // rate (determined by
+ // I2C_CLKSEL) in KHz.
+#define I2C_WRTIME 15.0 // Worst case time,in
+ // msec, for EEPROM
+ // internal write op.
+
+// I2C manifest constants.
+
+// Max retries to wait for EEPROM write.
+#define I2C_RETRIES ( I2C_WRTIME * I2C_BITRATE / 9.0 )
+#define I2C_ERR 0x0002 // I2C control/status
+ // flag ERROR.
+#define I2C_BUSY 0x0001 // I2C control/status
+ // flag BUSY.
+#define I2C_ABORT 0x0080 // I2C status flag ABORT.
+#define I2C_ATTRSTART 0x3 // I2C attribute START.
+#define I2C_ATTRCONT 0x2 // I2C attribute CONT.
+#define I2C_ATTRSTOP 0x1 // I2C attribute STOP.
+#define I2C_ATTRNOP 0x0 // I2C attribute NOP.
+
+// I2C read command | EEPROM address.
+#define I2CR ( devpriv->I2CAdrs | 1 )
+
+// I2C write command | EEPROM address.
+#define I2CW ( devpriv->I2CAdrs )
+
+// Code macros used for constructing I2C command bytes.
+#define I2C_B2(ATTR,VAL) ( ( (ATTR) << 6 ) | ( (VAL) << 24 ) )
+#define I2C_B1(ATTR,VAL) ( ( (ATTR) << 4 ) | ( (VAL) << 16 ) )
+#define I2C_B0(ATTR,VAL) ( ( (ATTR) << 2 ) | ( (VAL) << 8 ) )
+
+////////////////////////////////////////////////////////
+//oldest
+#define P_DEBICFGq 0x007C // DEBI configuration.
+#define P_DEBICMDq 0x0080 // DEBI command.
+#define P_DEBIPAGEq 0x0084 // DEBI page.
+#define P_DEBIADq 0x0088 // DEBI target address.
+
+#define DEBI_CFG_TOQ 0x03C00000 // timeout (15 PCI cycles)
+#define DEBI_CFG_FASTQ 0x10000000 // fast mode enable
+#define DEBI_CFG_16Q 0x00080000 // 16-bit access enable
+#define DEBI_CFG_INCQ 0x00040000 // enable address increment
+#define DEBI_CFG_TIMEROFFQ 0x00010000 // disable timer
+#define DEBI_CMD_RDQ 0x00050000 // read immediate 2 bytes
+#define DEBI_CMD_WRQ 0x00040000 // write immediate 2 bytes
+#define DEBI_PAGE_DISABLEQ 0x00000000 // paging disable
+
+///////////////////////////////////////////
+// DEBI command constants.
+#define DEBI_CMD_SIZE16 ( 2 << 17 ) // Transfer size is
+ // always 2 bytes.
+#define DEBI_CMD_READ 0x00010000 // Read operation.
+#define DEBI_CMD_WRITE 0x00000000 // Write operation.
+
+// Read immediate 2 bytes.
+#define DEBI_CMD_RDWORD ( DEBI_CMD_READ | DEBI_CMD_SIZE16 )
+
+// Write immediate 2 bytes.
+#define DEBI_CMD_WRWORD ( DEBI_CMD_WRITE | DEBI_CMD_SIZE16 )
+
+// DEBI configuration constants.
+#define DEBI_CFG_XIRQ_EN 0x80000000 // enab external
+ // interrupt on GPIO3.
+#define DEBI_CFG_XRESUME 0x40000000 // Resume block
+ // transfer when XIRQ
+ // deasserted.
+#define DEBI_CFG_FAST 0x10000000 // Fast mode enable.
+
+// 4-bit field that specifies DEBI timeout value in PCI clock cycles:
+#define DEBI_CFG_TOUT_BIT 22 // Finish DEBI cycle after
+ // this many clocks.
+
+// 2-bit field that specifies Endian byte lane steering:
+#define DEBI_CFG_SWAP_NONE 0x00000000 // Straight - don't
+ // swap any bytes
+ // (Intel).
+#define DEBI_CFG_SWAP_2 0x00100000 // 2-byte swap (Motorola).
+#define DEBI_CFG_SWAP_4 0x00200000 // 4-byte swap.
+#define DEBI_CFG_16 0x00080000 // Slave is able to
+ // serve 16-bit
+ // cycles.
+
+#define DEBI_CFG_SLAVE16 0x00080000 // Slave is able to
+ // serve 16-bit
+ // cycles.
+#define DEBI_CFG_INC 0x00040000 // enab address
+ // increment for block
+ // transfers.
+#define DEBI_CFG_INTEL 0x00020000 // Intel style local bus.
+#define DEBI_CFG_TIMEROFF 0x00010000 // Disable timer.
+
+#if PLATFORM == INTEL
+
+#define DEBI_TOUT 7 // Wait 7 PCI clocks
+ // (212 ns) before
+ // polling RDY.
+
+// Intel byte lane steering (pass through all byte lanes).
+#define DEBI_SWAP DEBI_CFG_SWAP_NONE
+
+#elif PLATFORM == MOTOROLA
+
+#define DEBI_TOUT 15 // Wait 15 PCI clocks (454 ns)
+ // maximum before timing out.
+#define DEBI_SWAP DEBI_CFG_SWAP_2 // Motorola byte lane steering.
+
+#endif
+
+// DEBI page table constants.
+#define DEBI_PAGE_DISABLE 0x00000000 // Paging disable.
+
+///////////////////EXTRA FROM OTHER SANSORAY * .h////////
+
+// LoadSrc values:
+#define LOADSRC_INDX 0 // Preload core in response to
+ // Index.
+#define LOADSRC_OVER 1 // Preload core in response to
+ // Overflow.
+#define LOADSRCB_OVERA 2 // Preload B core in response
+ // to A Overflow.
+#define LOADSRC_NONE 3 // Never preload core.
+
+// IntSrc values:
+#define INTSRC_NONE 0 // Interrupts disabled.
+#define INTSRC_OVER 1 // Interrupt on Overflow.
+#define INTSRC_INDX 2 // Interrupt on Index.
+#define INTSRC_BOTH 3 // Interrupt on Index or Overflow.
+
+// LatchSrc values:
+#define LATCHSRC_AB_READ 0 // Latch on read.
+#define LATCHSRC_A_INDXA 1 // Latch A on A Index.
+#define LATCHSRC_B_INDXB 2 // Latch B on B Index.
+#define LATCHSRC_B_OVERA 3 // Latch B on A Overflow.
+
+// IndxSrc values:
+#define INDXSRC_HARD 0 // Hardware or software index.
+#define INDXSRC_SOFT 1 // Software index only.
+
+// IndxPol values:
+#define INDXPOL_POS 0 // Index input is active high.
+#define INDXPOL_NEG 1 // Index input is active low.
+
+// ClkSrc values:
+#define CLKSRC_COUNTER 0 // Counter mode.
+#define CLKSRC_TIMER 2 // Timer mode.
+#define CLKSRC_EXTENDER 3 // Extender mode.
+
+// ClkPol values:
+#define CLKPOL_POS 0 // Counter/Extender clock is
+ // active high.
+#define CLKPOL_NEG 1 // Counter/Extender clock is
+ // active low.
+#define CNTDIR_UP 0 // Timer counts up.
+#define CNTDIR_DOWN 1 // Timer counts down.
+
+// ClkEnab values:
+#define CLKENAB_ALWAYS 0 // Clock always enabled.
+#define CLKENAB_INDEX 1 // Clock is enabled by index.
+
+// ClkMult values:
+#define CLKMULT_4X 0 // 4x clock multiplier.
+#define CLKMULT_2X 1 // 2x clock multiplier.
+#define CLKMULT_1X 2 // 1x clock multiplier.
+
+// Bit Field positions in COUNTER_SETUP structure:
+#define BF_LOADSRC 9 // Preload trigger.
+#define BF_INDXSRC 7 // Index source.
+#define BF_INDXPOL 6 // Index polarity.
+#define BF_CLKSRC 4 // Clock source.
+#define BF_CLKPOL 3 // Clock polarity/count direction.
+#define BF_CLKMULT 1 // Clock multiplier.
+#define BF_CLKENAB 0 // Clock enable.
+
+// Enumerated counter operating modes specified by ClkSrc bit field in
+// a COUNTER_SETUP.
+
+#define CLKSRC_COUNTER 0 // Counter: ENC_C clock, ENC_D
+ // direction.
+#define CLKSRC_TIMER 2 // Timer: SYS_C clock,
+ // direction specified by
+ // ClkPol.
+#define CLKSRC_EXTENDER 3 // Extender: OVR_A clock,
+ // ENC_D direction.
+
+// Enumerated counter clock multipliers.
+
+#define MULT_X0 0x0003 // Supports no multipliers;
+ // fixed physical multiplier =
+ // 3.
+#define MULT_X1 0x0002 // Supports multiplier x1;
+ // fixed physical multiplier =
+ // 2.
+#define MULT_X2 0x0001 // Supports multipliers x1,
+ // x2; physical multipliers =
+ // 1 or 2.
+#define MULT_X4 0x0000 // Supports multipliers x1,
+ // x2, x4; physical
+ // multipliers = 0, 1 or 2.
+
+// Sanity-check limits for parameters.
+
+#define NUM_COUNTERS 6 // Maximum valid counter
+ // logical channel number.
+#define NUM_INTSOURCES 4
+#define NUM_LATCHSOURCES 4
+#define NUM_CLKMULTS 4
+#define NUM_CLKSOURCES 4
+#define NUM_CLKPOLS 2
+#define NUM_INDEXPOLS 2
+#define NUM_INDEXSOURCES 2
+#define NUM_LOADTRIGS 4
+
+// Bit field positions in CRA and CRB counter control registers.
+
+// Bit field positions in CRA:
+#define CRABIT_INDXSRC_B 14 // B index source.
+#define CRABIT_CLKSRC_B 12 // B clock source.
+#define CRABIT_INDXPOL_A 11 // A index polarity.
+#define CRABIT_LOADSRC_A 9 // A preload trigger.
+#define CRABIT_CLKMULT_A 7 // A clock multiplier.
+#define CRABIT_INTSRC_A 5 // A interrupt source.
+#define CRABIT_CLKPOL_A 4 // A clock polarity.
+#define CRABIT_INDXSRC_A 2 // A index source.
+#define CRABIT_CLKSRC_A 0 // A clock source.
+
+// Bit field positions in CRB:
+#define CRBBIT_INTRESETCMD 15 // Interrupt reset command.
+#define CRBBIT_INTRESET_B 14 // B interrupt reset enable.
+#define CRBBIT_INTRESET_A 13 // A interrupt reset enable.
+#define CRBBIT_CLKENAB_A 12 // A clock enable.
+#define CRBBIT_INTSRC_B 10 // B interrupt source.
+#define CRBBIT_LATCHSRC 8 // A/B latch source.
+#define CRBBIT_LOADSRC_B 6 // B preload trigger.
+#define CRBBIT_CLKMULT_B 3 // B clock multiplier.
+#define CRBBIT_CLKENAB_B 2 // B clock enable.
+#define CRBBIT_INDXPOL_B 1 // B index polarity.
+#define CRBBIT_CLKPOL_B 0 // B clock polarity.
+
+// Bit field masks for CRA and CRB.
+
+#define CRAMSK_INDXSRC_B ( (uint16_t)( 3 << CRABIT_INDXSRC_B) )
+#define CRAMSK_CLKSRC_B ( (uint16_t)( 3 << CRABIT_CLKSRC_B) )
+#define CRAMSK_INDXPOL_A ( (uint16_t)( 1 << CRABIT_INDXPOL_A) )
+#define CRAMSK_LOADSRC_A ( (uint16_t)( 3 << CRABIT_LOADSRC_A) )
+#define CRAMSK_CLKMULT_A ( (uint16_t)( 3 << CRABIT_CLKMULT_A) )
+#define CRAMSK_INTSRC_A ( (uint16_t)( 3 << CRABIT_INTSRC_A) )
+#define CRAMSK_CLKPOL_A ( (uint16_t)( 3 << CRABIT_CLKPOL_A) )
+#define CRAMSK_INDXSRC_A ( (uint16_t)( 3 << CRABIT_INDXSRC_A) )
+#define CRAMSK_CLKSRC_A ( (uint16_t)( 3 << CRABIT_CLKSRC_A) )
+
+#define CRBMSK_INTRESETCMD ( (uint16_t)( 1 << CRBBIT_INTRESETCMD) )
+#define CRBMSK_INTRESET_B ( (uint16_t)( 1 << CRBBIT_INTRESET_B) )
+#define CRBMSK_INTRESET_A ( (uint16_t)( 1 << CRBBIT_INTRESET_A) )
+#define CRBMSK_CLKENAB_A ( (uint16_t)( 1 << CRBBIT_CLKENAB_A) )
+#define CRBMSK_INTSRC_B ( (uint16_t)( 3 << CRBBIT_INTSRC_B) )
+#define CRBMSK_LATCHSRC ( (uint16_t)( 3 << CRBBIT_LATCHSRC) )
+#define CRBMSK_LOADSRC_B ( (uint16_t)( 3 << CRBBIT_LOADSRC_B) )
+#define CRBMSK_CLKMULT_B ( (uint16_t)( 3 << CRBBIT_CLKMULT_B) )
+#define CRBMSK_CLKENAB_B ( (uint16_t)( 1 << CRBBIT_CLKENAB_B) )
+#define CRBMSK_INDXPOL_B ( (uint16_t)( 1 << CRBBIT_INDXPOL_B) )
+#define CRBMSK_CLKPOL_B ( (uint16_t)( 1 << CRBBIT_CLKPOL_B) )
+
+#define CRBMSK_INTCTRL ( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B ) // Interrupt reset control bits.
+
+// Bit field positions for standardized SETUP structure.
+
+#define STDBIT_INTSRC 13
+#define STDBIT_LATCHSRC 11
+#define STDBIT_LOADSRC 9
+#define STDBIT_INDXSRC 7
+#define STDBIT_INDXPOL 6
+#define STDBIT_CLKSRC 4
+#define STDBIT_CLKPOL 3
+#define STDBIT_CLKMULT 1
+#define STDBIT_CLKENAB 0
+
+// Bit field masks for standardized SETUP structure.
+
+#define STDMSK_INTSRC ( (uint16_t)( 3 << STDBIT_INTSRC ) )
+#define STDMSK_LATCHSRC ( (uint16_t)( 3 << STDBIT_LATCHSRC ) )
+#define STDMSK_LOADSRC ( (uint16_t)( 3 << STDBIT_LOADSRC ) )
+#define STDMSK_INDXSRC ( (uint16_t)( 1 << STDBIT_INDXSRC ) )
+#define STDMSK_INDXPOL ( (uint16_t)( 1 << STDBIT_INDXPOL ) )
+#define STDMSK_CLKSRC ( (uint16_t)( 3 << STDBIT_CLKSRC ) )
+#define STDMSK_CLKPOL ( (uint16_t)( 1 << STDBIT_CLKPOL ) )
+#define STDMSK_CLKMULT ( (uint16_t)( 3 << STDBIT_CLKMULT ) )
+#define STDMSK_CLKENAB ( (uint16_t)( 1 << STDBIT_CLKENAB ) )
+
+//////////////////////////////////////////////////////////
+
+/* typedef struct indexCounter */
+/* { */
+/* unsigned int ao; */
+/* unsigned int ai; */
+/* unsigned int digout; */
+/* unsigned int digin; */
+/* unsigned int enc; */
+/* }CallCounter; */
+
+typedef struct bufferDMA {
+ dma_addr_t PhysicalBase;
+ void *LogicalBase;
+ uint32_t DMAHandle;
+} DMABUF;
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
new file mode 100644
index 000000000000..35138257be7f
--- /dev/null
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -0,0 +1,2932 @@
+#define DRIVER_VERSION "v2.1"
+#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
+#define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"
+/*
+ comedi/drivers/usbdux.c
+ Copyright (C) 2003-2007 Bernd Porr, Bernd.Porr@f2s.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ */
+/*
+Driver: usbdux
+Description: University of Stirling USB DAQ & INCITE Technology Limited
+Devices: [ITL] USB-DUX (usbdux.o)
+Author: Bernd Porr <BerndPorr@f2s.com>
+Updated: 25 Nov 2007
+Status: Testing
+Configuration options:
+ You have to upload firmware with the -i option. The
+ firmware is usually installed under /usr/share/usb or
+ /usr/local/share/usb or /lib/firmware.
+
+Connection scheme for the counter at the digital port:
+ 0=/CLK0, 1=UP/DOWN0, 2=RESET0, 4=/CLK1, 5=UP/DOWN1, 6=RESET1.
+ The sampling rate of the counter is approximately 500Hz.
+
+Please note that under USB2.0 the length of the channel list determines
+the max sampling rate. If you sample only one channel you get 8kHz
+sampling rate. If you sample two channels you get 4kHz and so on.
+*/
+/*
+ * I must give credit here to Chris Baugher who
+ * wrote the driver for AT-MIO-16d. I used some parts of this
+ * driver. I also must give credits to David Brownell
+ * who supported me with the USB development.
+ *
+ * Bernd Porr
+ *
+ *
+ * Revision history:
+ * 0.94: D/A output should work now with any channel list combinations
+ * 0.95: .owner commented out for kernel vers below 2.4.19
+ * sanity checks in ai/ao_cmd
+ * 0.96: trying to get it working with 2.6, moved all memory alloc to comedi's
+ * attach final USB IDs
+ * moved memory allocation completely to the corresponding comedi
+ * functions firmware upload is by fxload and no longer by comedi (due to
+ * enumeration)
+ * 0.97: USB IDs received, adjusted table
+ * 0.98: SMP, locking, memroy alloc: moved all usb memory alloc
+ * to the usb subsystem and moved all comedi related memory
+ * alloc to comedi.
+ * | kernel | registration | usbdux-usb | usbdux-comedi | comedi |
+ * 0.99: USB 2.0: changed protocol to isochronous transfer
+ * IRQ transfer is too buggy and too risky in 2.0
+ * for the high speed ISO transfer is now a working version
+ * available
+ * 0.99b: Increased the iso transfer buffer for high sp.to 10 buffers. Some VIA
+ * chipsets miss out IRQs. Deeper buffering is needed.
+ * 1.00: full USB 2.0 support for the A/D converter. Now: max 8kHz sampling
+ * rate.
+ * Firmware vers 1.00 is needed for this.
+ * Two 16 bit up/down/reset counter with a sampling rate of 1kHz
+ * And loads of cleaning up, in particular streamlining the
+ * bulk transfers.
+ * 1.1: moved EP4 transfers to EP1 to make space for a PWM output on EP4
+ * 1.2: added PWM suport via EP4
+ * 2.0: PWM seems to be stable and is not interfering with the other functions
+ * 2.1: changed PWM API
+ *
+ */
+
+/* generates loads of debug info */
+/* #define NOISY_DUX_DEBUGBUG */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+#include <linux/fcntl.h>
+#include <linux/compiler.h>
+
+#include "../comedidev.h"
+
+#define BOARDNAME "usbdux"
+
+/* timeout for the USB-transfer */
+#define EZTIMEOUT 30
+
+/* constants for "firmware" upload and download */
+#define USBDUXSUB_FIRMWARE 0xA0
+#define VENDOR_DIR_IN 0xC0
+#define VENDOR_DIR_OUT 0x40
+
+/* internal adresses of the 8051 processor */
+#define USBDUXSUB_CPUCS 0xE600
+
+/*
+ * the minor device number, major is 180 only for debugging purposes and to
+ * upload special firmware (programming the eeprom etc) which is not compatible
+ * with the comedi framwork
+ */
+#define USBDUXSUB_MINOR 32
+
+/* max lenghth of the transfer-buffer for software upload */
+#define TB_LEN 0x2000
+
+/* Input endpoint number: ISO/IRQ */
+#define ISOINEP 6
+
+/* Output endpoint number: ISO/IRQ */
+#define ISOOUTEP 2
+
+/* This EP sends DUX commands to USBDUX */
+#define COMMAND_OUT_EP 1
+
+/* This EP receives the DUX commands from USBDUX */
+#define COMMAND_IN_EP 8
+
+/* Output endpoint for PWM */
+#define PWM_EP 4
+
+/* 300Hz max frequ under PWM */
+#define MIN_PWM_PERIOD ((long)(1E9/300))
+
+/* Default PWM frequency */
+#define PWM_DEFAULT_PERIOD ((long)(1E9/100))
+
+/* Number of channels */
+#define NUMCHANNELS 8
+
+/* Size of one A/D value */
+#define SIZEADIN ((sizeof(int16_t)))
+
+/*
+ * Size of the input-buffer IN BYTES
+ * Always multiple of 8 for 8 microframes which is needed in the highspeed mode
+ */
+#define SIZEINBUF ((8*SIZEADIN))
+
+/* 16 bytes. */
+#define SIZEINSNBUF 16
+
+/* Number of DA channels */
+#define NUMOUTCHANNELS 8
+
+/* size of one value for the D/A converter: channel and value */
+#define SIZEDAOUT ((sizeof(int8_t)+sizeof(int16_t)))
+
+/*
+ * Size of the output-buffer in bytes
+ * Actually only the first 4 triplets are used but for the
+ * high speed mode we need to pad it to 8 (microframes).
+ */
+#define SIZEOUTBUF ((8*SIZEDAOUT))
+
+/*
+ * Size of the buffer for the dux commands: just now max size is determined
+ * by the analogue out + command byte + panic bytes...
+ */
+#define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2))
+
+/* Number of in-URBs which receive the data: min=2 */
+#define NUMOFINBUFFERSFULL 5
+
+/* Number of out-URBs which send the data: min=2 */
+#define NUMOFOUTBUFFERSFULL 5
+
+/* Number of in-URBs which receive the data: min=5 */
+/* must have more buffers due to buggy USB ctr */
+#define NUMOFINBUFFERSHIGH 10
+
+/* Number of out-URBs which send the data: min=5 */
+/* must have more buffers due to buggy USB ctr */
+#define NUMOFOUTBUFFERSHIGH 10
+
+/* Total number of usbdux devices */
+#define NUMUSBDUX 16
+
+/* Analogue in subdevice */
+#define SUBDEV_AD 0
+
+/* Analogue out subdevice */
+#define SUBDEV_DA 1
+
+/* Digital I/O */
+#define SUBDEV_DIO 2
+
+/* counter */
+#define SUBDEV_COUNTER 3
+
+/* timer aka pwm output */
+#define SUBDEV_PWM 4
+
+/* number of retries to get the right dux command */
+#define RETRIES 10
+
+/**************************************************/
+/* comedi constants */
+static const comedi_lrange range_usbdux_ai_range = { 4, {
+ BIP_RANGE(4.096),
+ BIP_RANGE(4.096 / 2),
+ UNI_RANGE(4.096),
+ UNI_RANGE(4.096 / 2)
+ }
+};
+
+static const comedi_lrange range_usbdux_ao_range = { 2, {
+ BIP_RANGE(4.096),
+ UNI_RANGE(4.096),
+ }
+};
+
+/*
+ * private structure of one subdevice
+ */
+
+/*
+ * This is the structure which holds all the data of
+ * this driver one sub device just now: A/D
+ */
+struct usbduxsub {
+ /* attached? */
+ int attached;
+ /* is it associated with a subdevice? */
+ int probed;
+ /* pointer to the usb-device */
+ struct usb_device *usbdev;
+ /* actual number of in-buffers */
+ int numOfInBuffers;
+ /* actual number of out-buffers */
+ int numOfOutBuffers;
+ /* ISO-transfer handling: buffers */
+ struct urb **urbIn;
+ struct urb **urbOut;
+ /* pwm-transfer handling */
+ struct urb *urbPwm;
+ /* PWM period */
+ lsampl_t pwmPeriod;
+ /* PWM internal delay for the GPIF in the FX2 */
+ int8_t pwmDelay;
+ /* size of the PWM buffer which holds the bit pattern */
+ int sizePwmBuf;
+ /* input buffer for the ISO-transfer */
+ int16_t *inBuffer;
+ /* input buffer for single insn */
+ int16_t *insnBuffer;
+ /* output buffer for single DA outputs */
+ int16_t *outBuffer;
+ /* interface number */
+ int ifnum;
+ /* interface structure in 2.6 */
+ struct usb_interface *interface;
+ /* comedi device for the interrupt context */
+ comedi_device *comedidev;
+ /* is it USB_SPEED_HIGH or not? */
+ short int high_speed;
+ /* asynchronous command is running */
+ short int ai_cmd_running;
+ short int ao_cmd_running;
+ /* pwm is running */
+ short int pwm_cmd_running;
+ /* continous aquisition */
+ short int ai_continous;
+ short int ao_continous;
+ /* number of samples to aquire */
+ int ai_sample_count;
+ int ao_sample_count;
+ /* time between samples in units of the timer */
+ unsigned int ai_timer;
+ unsigned int ao_timer;
+ /* counter between aquisitions */
+ unsigned int ai_counter;
+ unsigned int ao_counter;
+ /* interval in frames/uframes */
+ unsigned int ai_interval;
+ /* D/A commands */
+ int8_t *dac_commands;
+ /* commands */
+ int8_t *dux_commands;
+ struct semaphore sem;
+};
+
+/*
+ * The pointer to the private usb-data of the driver is also the private data
+ * for the comedi-device. This has to be global as the usb subsystem needs
+ * global variables. The other reason is that this structure must be there
+ * _before_ any comedi command is issued. The usb subsystem must be initialised
+ * before comedi can access it.
+ */
+static struct usbduxsub usbduxsub[NUMUSBDUX];
+
+static DECLARE_MUTEX(start_stop_sem);
+
+/*
+ * Stops the data acquision
+ * It should be safe to call this function from any context
+ */
+static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp)
+{
+ int i = 0;
+ int err = 0;
+
+ if (usbduxsub_tmp && usbduxsub_tmp->urbIn) {
+ for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
+ if (usbduxsub_tmp->urbIn[i]) {
+ /* We wait here until all transfers have been
+ * cancelled. */
+ usb_kill_urb(usbduxsub_tmp->urbIn[i]);
+ }
+ dev_dbg(&usbduxsub_tmp->interface->dev,
+ "comedi: usbdux: unlinked InURB %d, err=%d\n",
+ i, err);
+ }
+ }
+ return err;
+}
+
+/*
+ * This will stop a running acquisition operation
+ * Is called from within this driver from both the
+ * interrupt context and from comedi
+ */
+static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+{
+ int ret = 0;
+
+ if (!this_usbduxsub) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n");
+ return -EFAULT;
+ }
+ dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n");
+
+ if (do_unlink) {
+ /* stop aquistion */
+ ret = usbduxsub_unlink_InURBs(this_usbduxsub);
+ }
+
+ this_usbduxsub->ai_cmd_running = 0;
+
+ return ret;
+}
+
+/*
+ * This will cancel a running acquisition operation.
+ * This is called by comedi but never from inside the driver.
+ */
+static int usbdux_ai_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+ struct usbduxsub *this_usbduxsub;
+ int res = 0;
+
+ /* force unlink of all urbs */
+ this_usbduxsub = dev->private;
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n");
+
+ /* prevent other CPUs from submitting new commands just now */
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ /* unlink only if the urb really has been submitted */
+ res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running);
+ up(&this_usbduxsub->sem);
+ return res;
+}
+
+/* analogue IN - interrupt service routine */
+static void usbduxsub_ai_IsocIrq(struct urb *urb)
+{
+ int i, err, n;
+ struct usbduxsub *this_usbduxsub;
+ comedi_device *this_comedidev;
+ comedi_subdevice *s;
+
+ /* the context variable points to the subdevice */
+ this_comedidev = urb->context;
+ /* the private structure of the subdevice is struct usbduxsub */
+ this_usbduxsub = this_comedidev->private;
+ /* subdevice which is the AD converter */
+ s = this_comedidev->subdevices + SUBDEV_AD;
+
+ /* first we test if something unusual has just happened */
+ switch (urb->status) {
+ case 0:
+ /* copy the result in the transfer buffer */
+ memcpy(this_usbduxsub->inBuffer,
+ urb->transfer_buffer, SIZEINBUF);
+ break;
+ case -EILSEQ:
+ /* error in the ISOchronous data */
+ /* we don't copy the data into the transfer buffer */
+ /* and recycle the last data byte */
+ dev_dbg(&urb->dev->dev,
+ "comedi%d: usbdux: CRC error in ISO IN stream.\n",
+ this_usbduxsub->comedidev->minor);
+
+ break;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNABORTED:
+ /* happens after an unlink command */
+ if (this_usbduxsub->ai_cmd_running) {
+ /* we are still running a command */
+ /* tell this comedi */
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_ERROR;
+ comedi_event(this_usbduxsub->comedidev, s);
+ /* stop the transfer w/o unlink */
+ usbdux_ai_stop(this_usbduxsub, 0);
+ }
+ return;
+
+ default:
+ /* a real error on the bus */
+ /* pass error to comedi if we are really running a command */
+ if (this_usbduxsub->ai_cmd_running) {
+ dev_err(&urb->dev->dev,
+ "Non-zero urb status received in ai intr "
+ "context: %d\n", urb->status);
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_ERROR;
+ comedi_event(this_usbduxsub->comedidev, s);
+ /* don't do an unlink here */
+ usbdux_ai_stop(this_usbduxsub, 0);
+ }
+ return;
+ }
+
+ /*
+ * at this point we are reasonably sure that nothing dodgy has happened
+ * are we running a command?
+ */
+ if (unlikely((!(this_usbduxsub->ai_cmd_running)))) {
+ /*
+ * not running a command, do not continue execution if no
+ * asynchronous command is running in particular not resubmit
+ */
+ return;
+ }
+
+ urb->dev = this_usbduxsub->usbdev;
+
+ /* resubmit the urb */
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(err < 0)) {
+ dev_err(&urb->dev->dev,
+ "comedi_: urb resubmit failed in int-context! err=%d\n",
+ err);
+ if (err == -EL2NSYNC)
+ dev_err(&urb->dev->dev,
+ "buggy USB host controller or bug in IRQ "
+ "handler!\n");
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_ERROR;
+ comedi_event(this_usbduxsub->comedidev, s);
+ /* don't do an unlink here */
+ usbdux_ai_stop(this_usbduxsub, 0);
+ return;
+ }
+
+ this_usbduxsub->ai_counter--;
+ if (likely(this_usbduxsub->ai_counter > 0))
+ return;
+
+ /* timer zero, transfer measurements to comedi */
+ this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+
+ /* test, if we transmit only a fixed number of samples */
+ if (!(this_usbduxsub->ai_continous)) {
+ /* not continous, fixed number of samples */
+ this_usbduxsub->ai_sample_count--;
+ /* all samples received? */
+ if (this_usbduxsub->ai_sample_count < 0) {
+ /* prevent a resubmit next time */
+ usbdux_ai_stop(this_usbduxsub, 0);
+ /* say comedi that the acquistion is over */
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(this_usbduxsub->comedidev, s);
+ return;
+ }
+ }
+ /* get the data from the USB bus and hand it over to comedi */
+ n = s->async->cmd.chanlist_len;
+ for (i = 0; i < n; i++) {
+ /* transfer data */
+ if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) {
+ comedi_buf_put
+ (s->async,
+ le16_to_cpu(this_usbduxsub->
+ inBuffer[i]) ^ 0x800);
+ } else {
+ comedi_buf_put
+ (s->async,
+ le16_to_cpu(this_usbduxsub->inBuffer[i]));
+ }
+ }
+ /* tell comedi that data is there */
+ comedi_event(this_usbduxsub->comedidev, s);
+}
+
+static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp)
+{
+ int i = 0;
+ int err = 0;
+
+ if (usbduxsub_tmp && usbduxsub_tmp->urbOut) {
+ for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
+ if (usbduxsub_tmp->urbOut[i])
+ usb_kill_urb(usbduxsub_tmp->urbOut[i]);
+
+ dev_dbg(&usbduxsub_tmp->interface->dev,
+ "comedi: usbdux: unlinked OutURB %d: res=%d\n",
+ i, err);
+ }
+ }
+ return err;
+}
+
+/* This will cancel a running acquisition operation
+ * in any context.
+ */
+static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+{
+ int ret = 0;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+ dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n");
+
+ if (do_unlink)
+ ret = usbduxsub_unlink_OutURBs(this_usbduxsub);
+
+ this_usbduxsub->ao_cmd_running = 0;
+
+ return ret;
+}
+
+/* force unlink, is called by comedi */
+static int usbdux_ao_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int res = 0;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ /* prevent other CPUs from submitting a command just now */
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ /* unlink only if it is really running */
+ res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running);
+ up(&this_usbduxsub->sem);
+ return res;
+}
+
+static void usbduxsub_ao_IsocIrq(struct urb *urb)
+{
+ int i, ret;
+ int8_t *datap;
+ struct usbduxsub *this_usbduxsub;
+ comedi_device *this_comedidev;
+ comedi_subdevice *s;
+
+ /* the context variable points to the subdevice */
+ this_comedidev = urb->context;
+ /* the private structure of the subdevice is struct usbduxsub */
+ this_usbduxsub = this_comedidev->private;
+
+ s = this_comedidev->subdevices + SUBDEV_DA;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNABORTED:
+ /* after an unlink command, unplug, ... etc */
+ /* no unlink needed here. Already shutting down. */
+ if (this_usbduxsub->ao_cmd_running) {
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(this_usbduxsub->comedidev, s);
+ usbdux_ao_stop(this_usbduxsub, 0);
+ }
+ return;
+
+ default:
+ /* a real error */
+ if (this_usbduxsub->ao_cmd_running) {
+ dev_err(&urb->dev->dev,
+ "comedi_: Non-zero urb status received in ao "
+ "intr context: %d\n", urb->status);
+ s->async->events |= COMEDI_CB_ERROR;
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(this_usbduxsub->comedidev, s);
+ /* we do an unlink if we are in the high speed mode */
+ usbdux_ao_stop(this_usbduxsub, 0);
+ }
+ return;
+ }
+
+ /* are we actually running? */
+ if (!(this_usbduxsub->ao_cmd_running))
+ return;
+
+ /* normal operation: executing a command in this subdevice */
+ this_usbduxsub->ao_counter--;
+ if (this_usbduxsub->ao_counter <= 0) {
+ /* timer zero */
+ this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+
+ /* handle non continous aquisition */
+ if (!(this_usbduxsub->ao_continous)) {
+ /* fixed number of samples */
+ this_usbduxsub->ao_sample_count--;
+ if (this_usbduxsub->ao_sample_count < 0) {
+ /* all samples transmitted */
+ usbdux_ao_stop(this_usbduxsub, 0);
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(this_usbduxsub->comedidev, s);
+ /* no resubmit of the urb */
+ return;
+ }
+ }
+ /* transmit data to the USB bus */
+ ((uint8_t *) (urb->transfer_buffer))[0] =
+ s->async->cmd.chanlist_len;
+ for (i = 0; i < s->async->cmd.chanlist_len; i++) {
+ sampl_t temp;
+ if (i >= NUMOUTCHANNELS)
+ break;
+
+ /* pointer to the DA */
+ datap =
+ (&(((int8_t *)urb->transfer_buffer)[i * 3 + 1]));
+ /* get the data from comedi */
+ ret = comedi_buf_get(s->async, &temp);
+ datap[0] = temp;
+ datap[1] = temp >> 8;
+ datap[2] = this_usbduxsub->dac_commands[i];
+ /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */
+ /* datap[0],datap[1],datap[2]); */
+ if (ret < 0) {
+ dev_err(&urb->dev->dev,
+ "comedi: buffer underflow\n");
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_OVERFLOW;
+ }
+ /* transmit data to comedi */
+ s->async->events |= COMEDI_CB_BLOCK;
+ comedi_event(this_usbduxsub->comedidev, s);
+ }
+ }
+ urb->transfer_buffer_length = SIZEOUTBUF;
+ urb->dev = this_usbduxsub->usbdev;
+ urb->status = 0;
+ if (this_usbduxsub->ao_cmd_running) {
+ if (this_usbduxsub->high_speed) {
+ /* uframes */
+ urb->interval = 8;
+ } else {
+ /* frames */
+ urb->interval = 1;
+ }
+ urb->number_of_packets = 1;
+ urb->iso_frame_desc[0].offset = 0;
+ urb->iso_frame_desc[0].length = SIZEOUTBUF;
+ urb->iso_frame_desc[0].status = 0;
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
+ dev_err(&urb->dev->dev,
+ "comedi_: ao urb resubm failed in int-cont. "
+ "ret=%d", ret);
+ if (ret == EL2NSYNC)
+ dev_err(&urb->dev->dev,
+ "buggy USB host controller or bug in "
+ "IRQ handling!\n");
+
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_ERROR;
+ comedi_event(this_usbduxsub->comedidev, s);
+ /* don't do an unlink here */
+ usbdux_ao_stop(this_usbduxsub, 0);
+ }
+ }
+}
+
+static int usbduxsub_start(struct usbduxsub *usbduxsub)
+{
+ int errcode = 0;
+ uint8_t local_transfer_buffer[16];
+
+ if (usbduxsub->probed) {
+ /* 7f92 to zero */
+ local_transfer_buffer[0] = 0;
+ errcode = usb_control_msg(usbduxsub->usbdev,
+ /* create a pipe for a control transfer */
+ usb_sndctrlpipe(usbduxsub->usbdev, 0),
+ /* bRequest, "Firmware" */
+ USBDUXSUB_FIRMWARE,
+ /* bmRequestType */
+ VENDOR_DIR_OUT,
+ /* Value */
+ USBDUXSUB_CPUCS,
+ /* Index */
+ 0x0000,
+ /* address of the transfer buffer */
+ local_transfer_buffer,
+ /* Length */
+ 1,
+ /* Timeout */
+ EZTIMEOUT);
+ if (errcode < 0) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: control msg failed (start)\n");
+ return errcode;
+ }
+ }
+ return 0;
+}
+
+static int usbduxsub_stop(struct usbduxsub *usbduxsub)
+{
+ int errcode = 0;
+
+ uint8_t local_transfer_buffer[16];
+ if (usbduxsub->probed) {
+ /* 7f92 to one */
+ local_transfer_buffer[0] = 1;
+ errcode = usb_control_msg(usbduxsub->usbdev,
+ usb_sndctrlpipe(usbduxsub->usbdev, 0),
+ /* bRequest, "Firmware" */
+ USBDUXSUB_FIRMWARE,
+ /* bmRequestType */
+ VENDOR_DIR_OUT,
+ /* Value */
+ USBDUXSUB_CPUCS,
+ /* Index */
+ 0x0000, local_transfer_buffer,
+ /* Length */
+ 1,
+ /* Timeout */
+ EZTIMEOUT);
+ if (errcode < 0) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: control msg failed (stop)\n");
+ return errcode;
+ }
+ }
+ return 0;
+}
+
+static int usbduxsub_upload(struct usbduxsub *usbduxsub,
+ uint8_t *local_transfer_buffer,
+ unsigned int startAddr, unsigned int len)
+{
+ int errcode;
+
+ if (usbduxsub->probed) {
+ dev_dbg(&usbduxsub->interface->dev,
+ "comedi%d: usbdux: uploading %d bytes"
+ " to addr %d, first byte=%d.\n",
+ usbduxsub->comedidev->minor, len,
+ startAddr, local_transfer_buffer[0]);
+ errcode = usb_control_msg(usbduxsub->usbdev,
+ usb_sndctrlpipe(usbduxsub->usbdev, 0),
+ /* brequest, firmware */
+ USBDUXSUB_FIRMWARE,
+ /* bmRequestType */
+ VENDOR_DIR_OUT,
+ /* value */
+ startAddr,
+ /* index */
+ 0x0000,
+ /* our local safe buffer */
+ local_transfer_buffer,
+ /* length */
+ len,
+ /* timeout */
+ EZTIMEOUT);
+ dev_dbg(&usbduxsub->interface->dev,
+ "comedi_: result=%d\n", errcode);
+ if (errcode < 0) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: upload failed\n");
+ return errcode;
+ }
+ } else {
+ /* no device on the bus for this index */
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int firmwareUpload(struct usbduxsub *usbduxsub, uint8_t *firmwareBinary,
+ int sizeFirmware)
+{
+ int ret;
+
+ if (!firmwareBinary)
+ return 0;
+
+ ret = usbduxsub_stop(usbduxsub);
+ if (ret < 0) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: can not stop firmware\n");
+ return ret;
+ }
+ ret = usbduxsub_upload(usbduxsub, firmwareBinary, 0, sizeFirmware);
+ if (ret < 0) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: firmware upload failed\n");
+ return ret;
+ }
+ ret = usbduxsub_start(usbduxsub);
+ if (ret < 0) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: can not start firmware\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub)
+{
+ int i, errFlag;
+
+ if (!usbduxsub)
+ return -EFAULT;
+
+ /* Submit all URBs and start the transfer on the bus */
+ for (i = 0; i < usbduxsub->numOfInBuffers; i++) {
+ /* in case of a resubmission after an unlink... */
+ usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval;
+ usbduxsub->urbIn[i]->context = usbduxsub->comedidev;
+ usbduxsub->urbIn[i]->dev = usbduxsub->usbdev;
+ usbduxsub->urbIn[i]->status = 0;
+ usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP;
+ dev_dbg(&usbduxsub->interface->dev,
+ "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n",
+ usbduxsub->comedidev->minor, i,
+ (usbduxsub->urbIn[i]->context),
+ (usbduxsub->urbIn[i]->dev),
+ (usbduxsub->urbIn[i]->interval));
+ errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC);
+ if (errFlag) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: ai: usb_submit_urb(%d) error %d\n",
+ i, errFlag);
+ return errFlag;
+ }
+ }
+ return 0;
+}
+
+static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub)
+{
+ int i, errFlag;
+
+ if (!usbduxsub)
+ return -EFAULT;
+
+ for (i = 0; i < usbduxsub->numOfOutBuffers; i++) {
+ dev_dbg(&usbduxsub->interface->dev,
+ "comedi_: submitting out-urb[%d]\n", i);
+ /* in case of a resubmission after an unlink... */
+ usbduxsub->urbOut[i]->context = usbduxsub->comedidev;
+ usbduxsub->urbOut[i]->dev = usbduxsub->usbdev;
+ usbduxsub->urbOut[i]->status = 0;
+ usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP;
+ errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC);
+ if (errFlag) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: ao: usb_submit_urb(%d) error %d\n",
+ i, errFlag);
+ return errFlag;
+ }
+ }
+ return 0;
+}
+
+static int usbdux_ai_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ comedi_cmd *cmd)
+{
+ int err = 0, tmp, i;
+ unsigned int tmpTimer;
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!(this_usbduxsub->probed))
+ return -ENODEV;
+
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ai_cmdtest\n", dev->minor);
+
+ /* make sure triggers are valid */
+ /* Only immediate triggers are allowed */
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW | TRIG_INT;
+ if (!cmd->start_src || tmp != cmd->start_src)
+ err++;
+
+ /* trigger should happen timed */
+ tmp = cmd->scan_begin_src;
+ /* start a new _scan_ with a timer */
+ cmd->scan_begin_src &= TRIG_TIMER;
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+ err++;
+
+ /* scanning is continous */
+ tmp = cmd->convert_src;
+ cmd->convert_src &= TRIG_NOW;
+ if (!cmd->convert_src || tmp != cmd->convert_src)
+ err++;
+
+ /* issue a trigger when scan is finished and start a new scan */
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+ err++;
+
+ /* trigger at the end of count events or not, stop condition or not */
+ tmp = cmd->stop_src;
+ cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+ if (!cmd->stop_src || tmp != cmd->stop_src)
+ err++;
+
+ if (err)
+ return 1;
+
+ /*
+ * step 2: make sure trigger sources are unique and mutually compatible
+ * note that mutual compatiblity is not an issue here
+ */
+ if (cmd->scan_begin_src != TRIG_FOLLOW &&
+ cmd->scan_begin_src != TRIG_EXT &&
+ cmd->scan_begin_src != TRIG_TIMER)
+ err++;
+ if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
+ err++;
+
+ if (err)
+ return 2;
+
+ /* step 3: make sure arguments are trivially compatible */
+ if (cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+
+ if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ /* internal trigger */
+ if (cmd->scan_begin_arg != 0) {
+ cmd->scan_begin_arg = 0;
+ err++;
+ }
+ }
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ if (this_usbduxsub->high_speed) {
+ /*
+ * In high speed mode microframes are possible.
+ * However, during one microframe we can roughly
+ * sample one channel. Thus, the more channels
+ * are in the channel list the more time we need.
+ */
+ i = 1;
+ /* find a power of 2 for the number of channels */
+ while (i < (cmd->chanlist_len))
+ i = i * 2;
+
+ if (cmd->scan_begin_arg < (1000000 / 8 * i)) {
+ cmd->scan_begin_arg = 1000000 / 8 * i;
+ err++;
+ }
+ /* now calc the real sampling rate with all the
+ * rounding errors */
+ tmpTimer =
+ ((unsigned int)(cmd->scan_begin_arg / 125000)) *
+ 125000;
+ if (cmd->scan_begin_arg != tmpTimer) {
+ cmd->scan_begin_arg = tmpTimer;
+ err++;
+ }
+ } else {
+ /* full speed */
+ /* 1kHz scans every USB frame */
+ if (cmd->scan_begin_arg < 1000000) {
+ cmd->scan_begin_arg = 1000000;
+ err++;
+ }
+ /*
+ * calc the real sampling rate with the rounding errors
+ */
+ tmpTimer = ((unsigned int)(cmd->scan_begin_arg /
+ 1000000)) * 1000000;
+ if (cmd->scan_begin_arg != tmpTimer) {
+ cmd->scan_begin_arg = tmpTimer;
+ err++;
+ }
+ }
+ }
+ /* the same argument */
+ if (cmd->scan_end_arg != cmd->chanlist_len) {
+ cmd->scan_end_arg = cmd->chanlist_len;
+ err++;
+ }
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ /* any count is allowed */
+ } else {
+ /* TRIG_NONE */
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+ }
+
+ if (err)
+ return 3;
+
+ return 0;
+}
+
+/*
+ * creates the ADC command for the MAX1271
+ * range is the range value from comedi
+ */
+static int8_t create_adc_command(unsigned int chan, int range)
+{
+ int8_t p = (range <= 1);
+ int8_t r = ((range % 2) == 0);
+ return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3);
+}
+
+/* bulk transfers to usbdux */
+
+#define SENDADCOMMANDS 0
+#define SENDDACOMMANDS 1
+#define SENDDIOCONFIGCOMMAND 2
+#define SENDDIOBITSCOMMAND 3
+#define SENDSINGLEAD 4
+#define READCOUNTERCOMMAND 5
+#define WRITECOUNTERCOMMAND 6
+#define SENDPWMON 7
+#define SENDPWMOFF 8
+
+static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type)
+{
+ int result, nsent;
+
+ this_usbduxsub->dux_commands[0] = cmd_type;
+#ifdef NOISY_DUX_DEBUGBUG
+ printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ",
+ this_usbduxsub->comedidev->minor);
+ for (result = 0; result < SIZEOFDUXBUFFER; result++)
+ printk(" %02x", this_usbduxsub->dux_commands[result]);
+ printk("\n");
+#endif
+ result = usb_bulk_msg(this_usbduxsub->usbdev,
+ usb_sndbulkpipe(this_usbduxsub->usbdev,
+ COMMAND_OUT_EP),
+ this_usbduxsub->dux_commands, SIZEOFDUXBUFFER,
+ &nsent, 10);
+ if (result < 0)
+ dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
+ "could not transmit dux_command to the usb-device, "
+ "err=%d\n", this_usbduxsub->comedidev->minor, result);
+
+ return result;
+}
+
+static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command)
+{
+ int result = (-EFAULT);
+ int nrec;
+ int i;
+
+ for (i = 0; i < RETRIES; i++) {
+ result = usb_bulk_msg(this_usbduxsub->usbdev,
+ usb_rcvbulkpipe(this_usbduxsub->usbdev,
+ COMMAND_IN_EP),
+ this_usbduxsub->insnBuffer, SIZEINSNBUF,
+ &nrec, 1);
+ if (result < 0) {
+ dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
+ "insn: USB error %d while receiving DUX command"
+ "\n", this_usbduxsub->comedidev->minor, result);
+ return result;
+ }
+ if (le16_to_cpu(this_usbduxsub->insnBuffer[0]) == command)
+ return result;
+ }
+ /* this is only reached if the data has been requested a couple of
+ * times */
+ dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: "
+ "wrong data returned from firmware: want cmd %d, got cmd %d.\n",
+ this_usbduxsub->comedidev->minor, command,
+ le16_to_cpu(this_usbduxsub->insnBuffer[0]));
+ return -EFAULT;
+}
+
+static int usbdux_ai_inttrig(comedi_device *dev, comedi_subdevice *s,
+ unsigned int trignum)
+{
+ int ret;
+ struct usbduxsub *this_usbduxsub = dev->private;
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ai_inttrig\n", dev->minor);
+
+ if (trignum != 0) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ai_inttrig: invalid trignum\n",
+ dev->minor);
+ up(&this_usbduxsub->sem);
+ return -EINVAL;
+ }
+ if (!(this_usbduxsub->ai_cmd_running)) {
+ this_usbduxsub->ai_cmd_running = 1;
+ ret = usbduxsub_submit_InURBs(this_usbduxsub);
+ if (ret < 0) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ai_inttrig: "
+ "urbSubmit: err=%d\n", dev->minor, ret);
+ this_usbduxsub->ai_cmd_running = 0;
+ up(&this_usbduxsub->sem);
+ return ret;
+ }
+ s->async->inttrig = NULL;
+ } else {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: ai_inttrig but acqu is already running\n",
+ dev->minor);
+ }
+ up(&this_usbduxsub->sem);
+ return 1;
+}
+
+static int usbdux_ai_cmd(comedi_device *dev, comedi_subdevice *s)
+{
+ comedi_cmd *cmd = &s->async->cmd;
+ unsigned int chan, range;
+ int i, ret;
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int result;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ai_cmd\n", dev->minor);
+
+ /* block other CPUs from starting an ai_cmd */
+ down(&this_usbduxsub->sem);
+
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ if (this_usbduxsub->ai_cmd_running) {
+ dev_err(&this_usbduxsub->interface->dev, "comedi%d: "
+ "ai_cmd not possible. Another ai_cmd is running.\n",
+ dev->minor);
+ up(&this_usbduxsub->sem);
+ return -EBUSY;
+ }
+ /* set current channel of the running aquisition to zero */
+ s->async->cur_chan = 0;
+
+ this_usbduxsub->dux_commands[1] = cmd->chanlist_len;
+ for (i = 0; i < cmd->chanlist_len; ++i) {
+ chan = CR_CHAN(cmd->chanlist[i]);
+ range = CR_RANGE(cmd->chanlist[i]);
+ if (i >= NUMCHANNELS) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: channel list too long\n",
+ dev->minor);
+ break;
+ }
+ this_usbduxsub->dux_commands[i + 2] =
+ create_adc_command(chan, range);
+ }
+
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi %d: sending commands to the usb device: size=%u\n",
+ dev->minor, NUMCHANNELS);
+
+ result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS);
+ if (result < 0) {
+ up(&this_usbduxsub->sem);
+ return result;
+ }
+
+ if (this_usbduxsub->high_speed) {
+ /*
+ * every channel gets a time window of 125us. Thus, if we
+ * sample all 8 channels we need 1ms. If we sample only one
+ * channel we need only 125us
+ */
+ this_usbduxsub->ai_interval = 1;
+ /* find a power of 2 for the interval */
+ while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) {
+ this_usbduxsub->ai_interval =
+ (this_usbduxsub->ai_interval) * 2;
+ }
+ this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 *
+ (this_usbduxsub->ai_interval));
+ } else {
+ /* interval always 1ms */
+ this_usbduxsub->ai_interval = 1;
+ this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000;
+ }
+ if (this_usbduxsub->ai_timer < 1) {
+ dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: "
+ "timer=%d, scan_begin_arg=%d. "
+ "Not properly tested by cmdtest?\n", dev->minor,
+ this_usbduxsub->ai_timer, cmd->scan_begin_arg);
+ up(&this_usbduxsub->sem);
+ return -EINVAL;
+ }
+ this_usbduxsub->ai_counter = this_usbduxsub->ai_timer;
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ /* data arrives as one packet */
+ this_usbduxsub->ai_sample_count = cmd->stop_arg;
+ this_usbduxsub->ai_continous = 0;
+ } else {
+ /* continous aquisition */
+ this_usbduxsub->ai_continous = 1;
+ this_usbduxsub->ai_sample_count = 0;
+ }
+
+ if (cmd->start_src == TRIG_NOW) {
+ /* enable this acquisition operation */
+ this_usbduxsub->ai_cmd_running = 1;
+ ret = usbduxsub_submit_InURBs(this_usbduxsub);
+ if (ret < 0) {
+ this_usbduxsub->ai_cmd_running = 0;
+ /* fixme: unlink here?? */
+ up(&this_usbduxsub->sem);
+ return ret;
+ }
+ s->async->inttrig = NULL;
+ } else {
+ /* TRIG_INT */
+ /* don't enable the acquision operation */
+ /* wait for an internal signal */
+ s->async->inttrig = usbdux_ai_inttrig;
+ }
+ up(&this_usbduxsub->sem);
+ return 0;
+}
+
+/* Mode 0 is used to get a single conversion on demand */
+static int usbdux_ai_insn_read(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int i;
+ lsampl_t one = 0;
+ int chan, range;
+ int err;
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!this_usbduxsub)
+ return 0;
+
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
+ dev->minor, insn->n, insn->subdev);
+
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ if (this_usbduxsub->ai_cmd_running) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: ai_insn_read not possible. "
+ "Async Command is running.\n", dev->minor);
+ up(&this_usbduxsub->sem);
+ return 0;
+ }
+
+ /* sample one channel */
+ chan = CR_CHAN(insn->chanspec);
+ range = CR_RANGE(insn->chanspec);
+ /* set command for the first channel */
+ this_usbduxsub->dux_commands[1] = create_adc_command(chan, range);
+
+ /* adc commands */
+ err = send_dux_commands(this_usbduxsub, SENDSINGLEAD);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return err;
+ }
+
+ for (i = 0; i < insn->n; i++) {
+ err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return 0;
+ }
+ one = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
+ if (CR_RANGE(insn->chanspec) <= 1)
+ one = one ^ 0x800;
+
+ data[i] = one;
+ }
+ up(&this_usbduxsub->sem);
+ return i;
+}
+
+/************************************/
+/* analog out */
+
+static int usbdux_ao_insn_read(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int i;
+ int chan = CR_CHAN(insn->chanspec);
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ for (i = 0; i < insn->n; i++)
+ data[i] = this_usbduxsub->outBuffer[chan];
+
+ up(&this_usbduxsub->sem);
+ return i;
+}
+
+static int usbdux_ao_insn_write(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int i, err;
+ int chan = CR_CHAN(insn->chanspec);
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: ao_insn_write\n", dev->minor);
+
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ if (this_usbduxsub->ao_cmd_running) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: ao_insn_write: "
+ "ERROR: asynchronous ao_cmd is running\n", dev->minor);
+ up(&this_usbduxsub->sem);
+ return 0;
+ }
+
+ for (i = 0; i < insn->n; i++) {
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n",
+ dev->minor, chan, i, data[i]);
+
+ /* number of channels: 1 */
+ this_usbduxsub->dux_commands[1] = 1;
+ /* one 16 bit value */
+ *((int16_t *) (this_usbduxsub->dux_commands + 2)) =
+ cpu_to_le16(data[i]);
+ this_usbduxsub->outBuffer[chan] = data[i];
+ /* channel number */
+ this_usbduxsub->dux_commands[4] = (chan << 6);
+ err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return err;
+ }
+ }
+ up(&this_usbduxsub->sem);
+
+ return i;
+}
+
+static int usbdux_ao_inttrig(comedi_device *dev, comedi_subdevice *s,
+ unsigned int trignum)
+{
+ int ret;
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ if (trignum != 0) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ao_inttrig: invalid trignum\n",
+ dev->minor);
+ return -EINVAL;
+ }
+ if (!(this_usbduxsub->ao_cmd_running)) {
+ this_usbduxsub->ao_cmd_running = 1;
+ ret = usbduxsub_submit_OutURBs(this_usbduxsub);
+ if (ret < 0) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ao_inttrig: submitURB: "
+ "err=%d\n", dev->minor, ret);
+ this_usbduxsub->ao_cmd_running = 0;
+ up(&this_usbduxsub->sem);
+ return ret;
+ }
+ s->async->inttrig = NULL;
+ } else {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: ao_inttrig but acqu is already running.\n",
+ dev->minor);
+ }
+ up(&this_usbduxsub->sem);
+ return 1;
+}
+
+static int usbdux_ao_cmdtest(comedi_device *dev, comedi_subdevice *s,
+ comedi_cmd *cmd)
+{
+ int err = 0, tmp;
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ if (!(this_usbduxsub->probed))
+ return -ENODEV;
+
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux_ao_cmdtest\n", dev->minor);
+
+ /* make sure triggers are valid */
+ /* Only immediate triggers are allowed */
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW | TRIG_INT;
+ if (!cmd->start_src || tmp != cmd->start_src)
+ err++;
+
+ /* trigger should happen timed */
+ tmp = cmd->scan_begin_src;
+ /* just now we scan also in the high speed mode every frame */
+ /* this is due to ehci driver limitations */
+ if (0) { /* (this_usbduxsub->high_speed) */
+ /* start immidiately a new scan */
+ /* the sampling rate is set by the coversion rate */
+ cmd->scan_begin_src &= TRIG_FOLLOW;
+ } else {
+ /* start a new scan (output at once) with a timer */
+ cmd->scan_begin_src &= TRIG_TIMER;
+ }
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+ err++;
+
+ /* scanning is continous */
+ tmp = cmd->convert_src;
+ /* we always output at 1kHz just now all channels at once */
+ if (0) { /* (this_usbduxsub->high_speed) */
+ /*
+ * in usb-2.0 only one conversion it tranmitted but with 8kHz/n
+ */
+ cmd->convert_src &= TRIG_TIMER;
+ } else {
+ /* all conversion events happen simultaneously with a rate of
+ * 1kHz/n */
+ cmd->convert_src &= TRIG_NOW;
+ }
+ if (!cmd->convert_src || tmp != cmd->convert_src)
+ err++;
+
+ /* issue a trigger when scan is finished and start a new scan */
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+ err++;
+
+ /* trigger at the end of count events or not, stop condition or not */
+ tmp = cmd->stop_src;
+ cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
+ if (!cmd->stop_src || tmp != cmd->stop_src)
+ err++;
+
+ if (err)
+ return 1;
+
+ /*
+ * step 2: make sure trigger sources are unique and mutually compatible
+ * note that mutual compatiblity is not an issue here
+ */
+ if (cmd->scan_begin_src != TRIG_FOLLOW &&
+ cmd->scan_begin_src != TRIG_EXT &&
+ cmd->scan_begin_src != TRIG_TIMER)
+ err++;
+ if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
+ err++;
+
+ if (err)
+ return 2;
+
+ /* step 3: make sure arguments are trivially compatible */
+
+ if (cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+
+ if (cmd->scan_begin_src == TRIG_FOLLOW) {
+ /* internal trigger */
+ if (cmd->scan_begin_arg != 0) {
+ cmd->scan_begin_arg = 0;
+ err++;
+ }
+ }
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ /* timer */
+ if (cmd->scan_begin_arg < 1000000) {
+ cmd->scan_begin_arg = 1000000;
+ err++;
+ }
+ }
+ /* not used now, is for later use */
+ if (cmd->convert_src == TRIG_TIMER) {
+ if (cmd->convert_arg < 125000) {
+ cmd->convert_arg = 125000;
+ err++;
+ }
+ }
+
+ /* the same argument */
+ if (cmd->scan_end_arg != cmd->chanlist_len) {
+ cmd->scan_end_arg = cmd->chanlist_len;
+ err++;
+ }
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ /* any count is allowed */
+ } else {
+ /* TRIG_NONE */
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+ }
+
+ dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: err=%d, "
+ "scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, "
+ "convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src,
+ cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg);
+
+ if (err)
+ return 3;
+
+ return 0;
+}
+
+static int usbdux_ao_cmd(comedi_device *dev, comedi_subdevice *s)
+{
+ comedi_cmd *cmd = &s->async->cmd;
+ unsigned int chan, gain;
+ int i, ret;
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ down(&this_usbduxsub->sem);
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: %s\n", dev->minor, __func__);
+
+ /* set current channel of the running aquisition to zero */
+ s->async->cur_chan = 0;
+ for (i = 0; i < cmd->chanlist_len; ++i) {
+ chan = CR_CHAN(cmd->chanlist[i]);
+ gain = CR_RANGE(cmd->chanlist[i]);
+ if (i >= NUMOUTCHANNELS) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: %s: channel list too long\n",
+ dev->minor, __func__);
+ break;
+ }
+ this_usbduxsub->dac_commands[i] = (chan << 6);
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: dac command for ch %d is %x\n",
+ dev->minor, i, this_usbduxsub->dac_commands[i]);
+ }
+
+ /* we count in steps of 1ms (125us) */
+ /* 125us mode not used yet */
+ if (0) { /* (this_usbduxsub->high_speed) */
+ /* 125us */
+ /* timing of the conversion itself: every 125 us */
+ this_usbduxsub->ao_timer = cmd->convert_arg / 125000;
+ } else {
+ /* 1ms */
+ /* timing of the scan: we get all channels at once */
+ this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000;
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, "
+ "convert_src=%d, convert_arg=%d\n", dev->minor,
+ cmd->scan_begin_src, cmd->scan_begin_arg,
+ cmd->convert_src, cmd->convert_arg);
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: ao_timer=%d (ms)\n",
+ dev->minor, this_usbduxsub->ao_timer);
+ if (this_usbduxsub->ao_timer < 1) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: usbdux: ao_timer=%d, "
+ "scan_begin_arg=%d. "
+ "Not properly tested by cmdtest?\n",
+ dev->minor, this_usbduxsub->ao_timer,
+ cmd->scan_begin_arg);
+ up(&this_usbduxsub->sem);
+ return -EINVAL;
+ }
+ }
+ this_usbduxsub->ao_counter = this_usbduxsub->ao_timer;
+
+ if (cmd->stop_src == TRIG_COUNT) {
+ /* not continous */
+ /* counter */
+ /* high speed also scans everything at once */
+ if (0) { /* (this_usbduxsub->high_speed) */
+ this_usbduxsub->ao_sample_count =
+ (cmd->stop_arg) * (cmd->scan_end_arg);
+ } else {
+ /* there's no scan as the scan has been */
+ /* perf inside the FX2 */
+ /* data arrives as one packet */
+ this_usbduxsub->ao_sample_count = cmd->stop_arg;
+ }
+ this_usbduxsub->ao_continous = 0;
+ } else {
+ /* continous aquisition */
+ this_usbduxsub->ao_continous = 1;
+ this_usbduxsub->ao_sample_count = 0;
+ }
+
+ if (cmd->start_src == TRIG_NOW) {
+ /* enable this acquisition operation */
+ this_usbduxsub->ao_cmd_running = 1;
+ ret = usbduxsub_submit_OutURBs(this_usbduxsub);
+ if (ret < 0) {
+ this_usbduxsub->ao_cmd_running = 0;
+ /* fixme: unlink here?? */
+ up(&this_usbduxsub->sem);
+ return ret;
+ }
+ s->async->inttrig = NULL;
+ } else {
+ /* TRIG_INT */
+ /* submit the urbs later */
+ /* wait for an internal signal */
+ s->async->inttrig = usbdux_ao_inttrig;
+ }
+
+ up(&this_usbduxsub->sem);
+ return 0;
+}
+
+static int usbdux_dio_insn_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ int chan = CR_CHAN(insn->chanspec);
+
+ /* The input or output configuration of each digital line is
+ * configured by a special insn_config instruction. chanspec
+ * contains the channel to be changed, and data[0] contains the
+ * value COMEDI_INPUT or COMEDI_OUTPUT. */
+
+ switch (data[0]) {
+ case INSN_CONFIG_DIO_OUTPUT:
+ s->io_bits |= 1 << chan; /* 1 means Out */
+ break;
+ case INSN_CONFIG_DIO_INPUT:
+ s->io_bits &= ~(1 << chan);
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ data[1] =
+ (s->
+ io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ /* we don't tell the firmware here as it would take 8 frames */
+ /* to submit the information. We do it in the insn_bits. */
+ return insn->n;
+}
+
+static int usbdux_dio_insn_bits(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int err;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+
+ if (insn->n != 2)
+ return -EINVAL;
+
+ down(&this_usbduxsub->sem);
+
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+
+ /* The insn data is a mask in data[0] and the new data
+ * in data[1], each channel cooresponding to a bit. */
+ s->state &= ~data[0];
+ s->state |= data[0] & data[1];
+ this_usbduxsub->dux_commands[1] = s->io_bits;
+ this_usbduxsub->dux_commands[2] = s->state;
+
+ /* This command also tells the firmware to return */
+ /* the digital input lines */
+ err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return err;
+ }
+ err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return err;
+ }
+
+ data[1] = le16_to_cpu(this_usbduxsub->insnBuffer[1]);
+ up(&this_usbduxsub->sem);
+ return 2;
+}
+
+/* reads the 4 counters, only two are used just now */
+static int usbdux_counter_read(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int chan = insn->chanspec;
+ int err;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ down(&this_usbduxsub->sem);
+
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+
+ err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return err;
+ }
+
+ err = receive_dux_commands(this_usbduxsub, READCOUNTERCOMMAND);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return err;
+ }
+
+ data[0] = le16_to_cpu(this_usbduxsub->insnBuffer[chan + 1]);
+ up(&this_usbduxsub->sem);
+ return 1;
+}
+
+static int usbdux_counter_write(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int err;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ down(&this_usbduxsub->sem);
+
+ if (!(this_usbduxsub->probed)) {
+ up(&this_usbduxsub->sem);
+ return -ENODEV;
+ }
+
+ this_usbduxsub->dux_commands[1] = insn->chanspec;
+ *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data);
+
+ err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND);
+ if (err < 0) {
+ up(&this_usbduxsub->sem);
+ return err;
+ }
+
+ up(&this_usbduxsub->sem);
+
+ return 1;
+}
+
+static int usbdux_counter_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ /* nothing to do so far */
+ return 2;
+}
+
+/***********************************/
+/* PWM */
+
+static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp)
+{
+ int err = 0;
+
+ if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) {
+ if (usbduxsub_tmp->urbPwm)
+ usb_kill_urb(usbduxsub_tmp->urbPwm);
+ dev_dbg(&usbduxsub_tmp->interface->dev,
+ "comedi: unlinked PwmURB: res=%d\n", err);
+ }
+ return err;
+}
+
+/* This cancels a running acquisition operation
+ * in any context.
+ */
+static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink)
+{
+ int ret = 0;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__);
+ if (do_unlink)
+ ret = usbduxsub_unlink_PwmURBs(this_usbduxsub);
+
+
+ this_usbduxsub->pwm_cmd_running = 0;
+
+ return ret;
+}
+
+/* force unlink - is called by comedi */
+static int usbdux_pwm_cancel(comedi_device *dev, comedi_subdevice *s)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int res = 0;
+
+ /* unlink only if it is really running */
+ res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running);
+
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi %d: sending pwm off command to the usb device.\n",
+ dev->minor);
+ res = send_dux_commands(this_usbduxsub, SENDPWMOFF);
+ if (res < 0)
+ return res;
+
+ return res;
+}
+
+static void usbduxsub_pwm_irq(struct urb *urb)
+{
+ int ret;
+ struct usbduxsub *this_usbduxsub;
+ comedi_device *this_comedidev;
+ comedi_subdevice *s;
+
+ /* printk(KERN_DEBUG "PWM: IRQ\n"); */
+
+ /* the context variable points to the subdevice */
+ this_comedidev = urb->context;
+ /* the private structure of the subdevice is struct usbduxsub */
+ this_usbduxsub = this_comedidev->private;
+
+ s = this_comedidev->subdevices + SUBDEV_DA;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNABORTED:
+ /*
+ * after an unlink command, unplug, ... etc
+ * no unlink needed here. Already shutting down.
+ */
+ if (this_usbduxsub->pwm_cmd_running)
+ usbdux_pwm_stop(this_usbduxsub, 0);
+
+ return;
+
+ default:
+ /* a real error */
+ if (this_usbduxsub->pwm_cmd_running) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi_: Non-zero urb status received in "
+ "pwm intr context: %d\n", urb->status);
+ usbdux_pwm_stop(this_usbduxsub, 0);
+ }
+ return;
+ }
+
+ /* are we actually running? */
+ if (!(this_usbduxsub->pwm_cmd_running))
+ return;
+
+ urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf;
+ urb->dev = this_usbduxsub->usbdev;
+ urb->status = 0;
+ if (this_usbduxsub->pwm_cmd_running) {
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi_: pwm urb resubm failed in int-cont. "
+ "ret=%d", ret);
+ if (ret == EL2NSYNC)
+ dev_err(&this_usbduxsub->interface->dev,
+ "buggy USB host controller or bug in "
+ "IRQ handling!\n");
+
+ /* don't do an unlink here */
+ usbdux_pwm_stop(this_usbduxsub, 0);
+ }
+ }
+}
+
+static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub)
+{
+ int errFlag;
+
+ if (!usbduxsub)
+ return -EFAULT;
+
+ dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n");
+
+ /* in case of a resubmission after an unlink... */
+ usb_fill_bulk_urb(usbduxsub->urbPwm,
+ usbduxsub->usbdev,
+ usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP),
+ usbduxsub->urbPwm->transfer_buffer,
+ usbduxsub->sizePwmBuf, usbduxsub_pwm_irq, usbduxsub->comedidev);
+
+ errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC);
+ if (errFlag) {
+ dev_err(&usbduxsub->interface->dev,
+ "comedi_: usbdux: pwm: usb_submit_urb error %d\n",
+ errFlag);
+ return errFlag;
+ }
+ return 0;
+}
+
+static int usbdux_pwm_period(comedi_device *dev, comedi_subdevice *s,
+ lsampl_t period)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int fx2delay = 255;
+
+ if (period < MIN_PWM_PERIOD) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: illegal period setting for pwm.\n",
+ dev->minor);
+ return -EAGAIN;
+ } else {
+ fx2delay = period / ((int)(6*512*(1.0/0.033))) - 6;
+ if (fx2delay > 255) {
+ dev_err(&this_usbduxsub->interface->dev,
+ "comedi%d: period %d for pwm is too low.\n",
+ dev->minor, period);
+ return -EAGAIN;
+ }
+ }
+ this_usbduxsub->pwmDelay = fx2delay;
+ this_usbduxsub->pwmPeriod = period;
+ dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n",
+ __func__, period, fx2delay);
+ return 0;
+}
+
+/* is called from insn so there's no need to do all the sanity checks */
+static int usbdux_pwm_start(comedi_device *dev, comedi_subdevice *s)
+{
+ int ret, i;
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n",
+ dev->minor, __func__);
+
+ if (this_usbduxsub->pwm_cmd_running) {
+ /* already running */
+ return 0;
+ }
+
+ this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwmDelay);
+ ret = send_dux_commands(this_usbduxsub, SENDPWMON);
+ if (ret < 0)
+ return ret;
+
+ /* initalise the buffer */
+ for (i = 0; i < this_usbduxsub->sizePwmBuf; i++)
+ ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0;
+
+ this_usbduxsub->pwm_cmd_running = 1;
+ ret = usbduxsub_submit_PwmURBs(this_usbduxsub);
+ if (ret < 0) {
+ this_usbduxsub->pwm_cmd_running = 0;
+ return ret;
+ }
+ return 0;
+}
+
+/* generates the bit pattern for PWM with the optional sign bit */
+static int usbdux_pwm_pattern(comedi_device *dev, comedi_subdevice *s,
+ int channel, lsampl_t value, lsampl_t sign)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+ int i, szbuf;
+ char *pBuf;
+ char pwm_mask;
+ char sgn_mask;
+ char c;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ /* this is the DIO bit which carries the PWM data */
+ pwm_mask = (1 << channel);
+ /* this is the DIO bit which carries the optional direction bit */
+ sgn_mask = (16 << channel);
+ /* this is the buffer which will be filled with the with bit */
+ /* pattern for one period */
+ szbuf = this_usbduxsub->sizePwmBuf;
+ pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer);
+ for (i = 0; i < szbuf; i++) {
+ c = *pBuf;
+ /* reset bits */
+ c = c & (~pwm_mask);
+ /* set the bit as long as the index is lower than the value */
+ if (i < value)
+ c = c | pwm_mask;
+ /* set the optional sign bit for a relay */
+ if (!sign) {
+ /* positive value */
+ c = c & (~sgn_mask);
+ } else {
+ /* negative value */
+ c = c | sgn_mask;
+ }
+ *(pBuf++) = c;
+ }
+ return 1;
+}
+
+static int usbdux_pwm_write(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+
+ if (!this_usbduxsub)
+ return -EFAULT;
+
+ if ((insn->n) != 1) {
+ /*
+ * doesn't make sense to have more than one value here because
+ * it would just overwrite the PWM buffer a couple of times
+ */
+ return -EINVAL;
+ }
+
+ /*
+ * the sign is set via a special INSN only, this gives us 8 bits for
+ * normal operation
+ * relay sign 0 by default
+ */
+ return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec),
+ data[0], 0);
+}
+
+static int usbdux_pwm_read(comedi_device *x1, comedi_subdevice *x2,
+ comedi_insn *x3, lsampl_t *x4)
+{
+ /* not needed */
+ return -EINVAL;
+};
+
+/* switches on/off PWM */
+static int usbdux_pwm_config(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ struct usbduxsub *this_usbduxsub = dev->private;
+ switch (data[0]) {
+ case INSN_CONFIG_ARM:
+ /* switch it on */
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: %s: pwm on\n", dev->minor, __func__);
+ /*
+ * if not zero the PWM is limited to a certain time which is
+ * not supported here
+ */
+ if (data[1] != 0)
+ return -EINVAL;
+ return usbdux_pwm_start(dev, s);
+ case INSN_CONFIG_DISARM:
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: %s: pwm off\n", dev->minor, __func__);
+ return usbdux_pwm_cancel(dev, s);
+ case INSN_CONFIG_GET_PWM_STATUS:
+ /*
+ * to check if the USB transmission has failed or in case PWM
+ * was limited to n cycles to check if it has terminated
+ */
+ data[1] = this_usbduxsub->pwm_cmd_running;
+ return 0;
+ case INSN_CONFIG_PWM_SET_PERIOD:
+ dev_dbg(&this_usbduxsub->interface->dev,
+ "comedi%d: %s: setting period\n", dev->minor, __func__);
+ return usbdux_pwm_period(dev, s, data[1]);
+ case INSN_CONFIG_PWM_GET_PERIOD:
+ data[1] = this_usbduxsub->pwmPeriod;
+ return 0;
+ case INSN_CONFIG_PWM_SET_H_BRIDGE:
+ /* value in the first byte and the sign in the second for a
+ relay */
+ return usbdux_pwm_pattern(dev, s,
+ /* the channel number */
+ CR_CHAN(insn->chanspec),
+ /* actual PWM data */
+ data[1],
+ /* just a sign */
+ (data[2] != 0));
+ case INSN_CONFIG_PWM_GET_H_BRIDGE:
+ /* values are not kept in this driver, nothing to return here */
+ return -EINVAL;
+ }
+ return -EINVAL;
+}
+
+/* end of PWM */
+/*****************************************************************/
+
+static void tidy_up(struct usbduxsub *usbduxsub_tmp)
+{
+ int i;
+
+ if (!usbduxsub_tmp)
+ return;
+ dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n");
+
+ /* shows the usb subsystem that the driver is down */
+ if (usbduxsub_tmp->interface)
+ usb_set_intfdata(usbduxsub_tmp->interface, NULL);
+
+ usbduxsub_tmp->probed = 0;
+
+ if (usbduxsub_tmp->urbIn) {
+ if (usbduxsub_tmp->ai_cmd_running) {
+ usbduxsub_tmp->ai_cmd_running = 0;
+ usbduxsub_unlink_InURBs(usbduxsub_tmp);
+ }
+ for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) {
+ kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer);
+ usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL;
+ usb_kill_urb(usbduxsub_tmp->urbIn[i]);
+ usb_free_urb(usbduxsub_tmp->urbIn[i]);
+ usbduxsub_tmp->urbIn[i] = NULL;
+ }
+ kfree(usbduxsub_tmp->urbIn);
+ usbduxsub_tmp->urbIn = NULL;
+ }
+ if (usbduxsub_tmp->urbOut) {
+ if (usbduxsub_tmp->ao_cmd_running) {
+ usbduxsub_tmp->ao_cmd_running = 0;
+ usbduxsub_unlink_OutURBs(usbduxsub_tmp);
+ }
+ for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
+ if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
+ kfree(usbduxsub_tmp->urbOut[i]->
+ transfer_buffer);
+ usbduxsub_tmp->urbOut[i]->transfer_buffer =
+ NULL;
+ }
+ if (usbduxsub_tmp->urbOut[i]) {
+ usb_kill_urb(usbduxsub_tmp->urbOut[i]);
+ usb_free_urb(usbduxsub_tmp->urbOut[i]);
+ usbduxsub_tmp->urbOut[i] = NULL;
+ }
+ }
+ kfree(usbduxsub_tmp->urbOut);
+ usbduxsub_tmp->urbOut = NULL;
+ }
+ if (usbduxsub_tmp->urbPwm) {
+ if (usbduxsub_tmp->pwm_cmd_running) {
+ usbduxsub_tmp->pwm_cmd_running = 0;
+ usbduxsub_unlink_PwmURBs(usbduxsub_tmp);
+ }
+ kfree(usbduxsub_tmp->urbPwm->transfer_buffer);
+ usbduxsub_tmp->urbPwm->transfer_buffer = NULL;
+ usb_kill_urb(usbduxsub_tmp->urbPwm);
+ usb_free_urb(usbduxsub_tmp->urbPwm);
+ usbduxsub_tmp->urbPwm = NULL;
+ }
+ kfree(usbduxsub_tmp->inBuffer);
+ usbduxsub_tmp->inBuffer = NULL;
+ kfree(usbduxsub_tmp->insnBuffer);
+ usbduxsub_tmp->insnBuffer = NULL;
+ kfree(usbduxsub_tmp->inBuffer);
+ usbduxsub_tmp->inBuffer = NULL;
+ kfree(usbduxsub_tmp->dac_commands);
+ usbduxsub_tmp->dac_commands = NULL;
+ kfree(usbduxsub_tmp->dux_commands);
+ usbduxsub_tmp->dux_commands = NULL;
+ usbduxsub_tmp->ai_cmd_running = 0;
+ usbduxsub_tmp->ao_cmd_running = 0;
+ usbduxsub_tmp->pwm_cmd_running = 0;
+}
+
+static unsigned hex2unsigned(char *h)
+{
+ unsigned hi, lo;
+
+ if (h[0] > '9')
+ hi = h[0] - 'A' + 0x0a;
+ else
+ hi = h[0] - '0';
+
+ if (h[1] > '9')
+ lo = h[1] - 'A' + 0x0a;
+ else
+ lo = h[1] - '0';
+
+ return hi * 0x10 + lo;
+}
+
+/* for FX2 */
+#define FIRMWARE_MAX_LEN 0x2000
+
+/* taken from David Brownell's fxload and adjusted for this driver */
+static int read_firmware(struct usbduxsub *usbduxsub, void *firmwarePtr,
+ long size)
+{
+ struct device *dev = &usbduxsub->interface->dev;
+ int i = 0;
+ unsigned char *fp = (char *)firmwarePtr;
+ unsigned char *firmwareBinary = NULL;
+ int res = 0;
+ int maxAddr = 0;
+
+ firmwareBinary = kzalloc(FIRMWARE_MAX_LEN, GFP_KERNEL);
+ if (!firmwareBinary) {
+ dev_err(dev, "comedi_: mem alloc for firmware failed\n");
+ return -ENOMEM;
+ }
+
+ for (;;) {
+ char buf[256], *cp;
+ char type;
+ int len;
+ int idx, off;
+ int j = 0;
+
+ /* get one line */
+ while ((i < size) && (fp[i] != 13) && (fp[i] != 10)) {
+ buf[j] = fp[i];
+ i++;
+ j++;
+ if (j >= sizeof(buf)) {
+ dev_err(dev, "comedi_: bogus firmware file!\n");
+ return -1;
+ }
+ }
+ /* get rid of LF/CR/... */
+ while ((i < size) && ((fp[i] == 13) || (fp[i] == 10)
+ || (fp[i] == 0))) {
+ i++;
+ }
+
+ buf[j] = 0;
+ /* dev_dbg(dev, "comedi_: buf=%s\n", buf); */
+
+ /*
+ * EXTENSION:
+ * "# comment-till-end-of-line", for copyrights etc
+ */
+ if (buf[0] == '#')
+ continue;
+
+ if (buf[0] != ':') {
+ dev_err(dev, "comedi_: upload: not an ihex record: %s",
+ buf);
+ return -EFAULT;
+ }
+
+ /* Read the length field (up to 16 bytes) */
+ len = hex2unsigned(buf + 1);
+
+ /* Read the target offset */
+ off = (hex2unsigned(buf + 3) * 0x0100) + hex2unsigned(buf + 5);
+
+ if ((off + len) > maxAddr)
+ maxAddr = off + len;
+
+
+ if (maxAddr >= FIRMWARE_MAX_LEN) {
+ dev_err(dev, "comedi_: firmware upload goes "
+ "beyond FX2 RAM boundaries.\n");
+ return -EFAULT;
+ }
+ /* dev_dbg(dev, "comedi_: off=%x, len=%x:\n", off, len); */
+
+ /* Read the record type */
+ type = hex2unsigned(buf + 7);
+
+ /* If this is an EOF record, then make it so. */
+ if (type == 1)
+ break;
+
+
+ if (type != 0) {
+ dev_err(dev, "comedi_: unsupported record type: %u\n",
+ type);
+ return -EFAULT;
+ }
+
+ for (idx = 0, cp = buf + 9; idx < len; idx += 1, cp += 2) {
+ firmwareBinary[idx + off] = hex2unsigned(cp);
+ /*printk("%02x ",firmwareBinary[idx+off]); */
+ }
+ /*printk("\n"); */
+
+ if (i >= size) {
+ dev_err(dev, "comedi_: unexpected end of hex file\n");
+ break;
+ }
+
+ }
+ res = firmwareUpload(usbduxsub, firmwareBinary, maxAddr + 1);
+ kfree(firmwareBinary);
+ return res;
+}
+
+/* allocate memory for the urbs and initialise them */
+static int usbduxsub_probe(struct usb_interface *uinterf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(uinterf);
+ struct device *dev = &uinterf->dev;
+ int i;
+ int index;
+
+ dev_dbg(dev, "comedi_: usbdux_: "
+ "finding a free structure for the usb-device\n");
+
+ down(&start_stop_sem);
+ /* look for a free place in the usbdux array */
+ index = -1;
+ for (i = 0; i < NUMUSBDUX; i++) {
+ if (!(usbduxsub[i].probed)) {
+ index = i;
+ break;
+ }
+ }
+
+ /* no more space */
+ if (index == -1) {
+ dev_err(dev, "Too many usbdux-devices connected.\n");
+ up(&start_stop_sem);
+ return -EMFILE;
+ }
+ dev_dbg(dev, "comedi_: usbdux: "
+ "usbduxsub[%d] is ready to connect to comedi.\n", index);
+
+ init_MUTEX(&(usbduxsub[index].sem));
+ /* save a pointer to the usb device */
+ usbduxsub[index].usbdev = udev;
+
+ /* 2.6: save the interface itself */
+ usbduxsub[index].interface = uinterf;
+ /* get the interface number from the interface */
+ usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
+ /* hand the private data over to the usb subsystem */
+ /* will be needed for disconnect */
+ usb_set_intfdata(uinterf, &(usbduxsub[index]));
+
+ dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum);
+
+ /* test if it is high speed (USB 2.0) */
+ usbduxsub[index].high_speed =
+ (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH);
+
+ /* create space for the commands of the DA converter */
+ usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL);
+ if (!usbduxsub[index].dac_commands) {
+ dev_err(dev, "comedi_: usbdux: "
+ "error alloc space for dac commands\n");
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ /* create space for the commands going to the usb device */
+ usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL);
+ if (!usbduxsub[index].dux_commands) {
+ dev_err(dev, "comedi_: usbdux: "
+ "error alloc space for dac commands\n");
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ /* create space for the in buffer and set it to zero */
+ usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL);
+ if (!(usbduxsub[index].inBuffer)) {
+ dev_err(dev, "comedi_: usbdux: "
+ "could not alloc space for inBuffer\n");
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ /* create space of the instruction buffer */
+ usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL);
+ if (!(usbduxsub[index].insnBuffer)) {
+ dev_err(dev, "comedi_: usbdux: "
+ "could not alloc space for insnBuffer\n");
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ /* create space for the outbuffer */
+ usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL);
+ if (!(usbduxsub[index].outBuffer)) {
+ dev_err(dev, "comedi_: usbdux: "
+ "could not alloc space for outBuffer\n");
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ /* setting to alternate setting 3: enabling iso ep and bulk ep. */
+ i = usb_set_interface(usbduxsub[index].usbdev,
+ usbduxsub[index].ifnum, 3);
+ if (i < 0) {
+ dev_err(dev, "comedi_: usbdux%d: "
+ "could not set alternate setting 3 in high speed.\n",
+ index);
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENODEV;
+ }
+ if (usbduxsub[index].high_speed)
+ usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH;
+ else
+ usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL;
+
+ usbduxsub[index].urbIn =
+ kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers,
+ GFP_KERNEL);
+ if (!(usbduxsub[index].urbIn)) {
+ dev_err(dev, "comedi_: usbdux: Could not alloc. urbIn array\n");
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) {
+ /* one frame: 1ms */
+ usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL);
+ if (usbduxsub[index].urbIn[i] == NULL) {
+ dev_err(dev, "comedi_: usbdux%d: "
+ "Could not alloc. urb(%d)\n", index, i);
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev;
+ /* will be filled later with a pointer to the comedi-device */
+ /* and ONLY then the urb should be submitted */
+ usbduxsub[index].urbIn[i]->context = NULL;
+ usbduxsub[index].urbIn[i]->pipe =
+ usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP);
+ usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP;
+ usbduxsub[index].urbIn[i]->transfer_buffer =
+ kzalloc(SIZEINBUF, GFP_KERNEL);
+ if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) {
+ dev_err(dev, "comedi_: usbdux%d: "
+ "could not alloc. transb.\n", index);
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq;
+ usbduxsub[index].urbIn[i]->number_of_packets = 1;
+ usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF;
+ usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0;
+ usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = SIZEINBUF;
+ }
+
+ /* out */
+ if (usbduxsub[index].high_speed)
+ usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH;
+ else
+ usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL;
+
+ usbduxsub[index].urbOut =
+ kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers,
+ GFP_KERNEL);
+ if (!(usbduxsub[index].urbOut)) {
+ dev_err(dev, "comedi_: usbdux: "
+ "Could not alloc. urbOut array\n");
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) {
+ /* one frame: 1ms */
+ usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL);
+ if (usbduxsub[index].urbOut[i] == NULL) {
+ dev_err(dev, "comedi_: usbdux%d: "
+ "Could not alloc. urb(%d)\n", index, i);
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev;
+ /* will be filled later with a pointer to the comedi-device */
+ /* and ONLY then the urb should be submitted */
+ usbduxsub[index].urbOut[i]->context = NULL;
+ usbduxsub[index].urbOut[i]->pipe =
+ usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP);
+ usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP;
+ usbduxsub[index].urbOut[i]->transfer_buffer =
+ kzalloc(SIZEOUTBUF, GFP_KERNEL);
+ if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) {
+ dev_err(dev, "comedi_: usbdux%d: "
+ "could not alloc. transb.\n", index);
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq;
+ usbduxsub[index].urbOut[i]->number_of_packets = 1;
+ usbduxsub[index].urbOut[i]->transfer_buffer_length = SIZEOUTBUF;
+ usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0;
+ usbduxsub[index].urbOut[i]->iso_frame_desc[0].length =
+ SIZEOUTBUF;
+ if (usbduxsub[index].high_speed) {
+ /* uframes */
+ usbduxsub[index].urbOut[i]->interval = 8;
+ } else {
+ /* frames */
+ usbduxsub[index].urbOut[i]->interval = 1;
+ }
+ }
+
+ /* pwm */
+ if (usbduxsub[index].high_speed) {
+ /* max bulk ep size in high speed */
+ usbduxsub[index].sizePwmBuf = 512;
+ usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL);
+ if (usbduxsub[index].urbPwm == NULL) {
+ dev_err(dev, "comedi_: usbdux%d: "
+ "Could not alloc. pwm urb\n", index);
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ usbduxsub[index].urbPwm->transfer_buffer =
+ kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL);
+ if (!(usbduxsub[index].urbPwm->transfer_buffer)) {
+ dev_err(dev, "comedi_: usbdux%d: "
+ "could not alloc. transb. for pwm\n", index);
+ tidy_up(&(usbduxsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ } else {
+ usbduxsub[index].urbPwm = NULL;
+ usbduxsub[index].sizePwmBuf = 0;
+ }
+
+ usbduxsub[index].ai_cmd_running = 0;
+ usbduxsub[index].ao_cmd_running = 0;
+ usbduxsub[index].pwm_cmd_running = 0;
+
+ /* we've reached the bottom of the function */
+ usbduxsub[index].probed = 1;
+ up(&start_stop_sem);
+ dev_info(dev, "comedi_: usbdux%d "
+ "has been successfully initialised.\n", index);
+ /* success */
+ return 0;
+}
+
+static void usbduxsub_disconnect(struct usb_interface *intf)
+{
+ struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf);
+ struct usb_device *udev = interface_to_usbdev(intf);
+
+ if (!usbduxsub_tmp) {
+ dev_err(&intf->dev,
+ "comedi_: disconnect called with null pointer.\n");
+ return;
+ }
+ if (usbduxsub_tmp->usbdev != udev) {
+ dev_err(&intf->dev,
+ "comedi_: BUG! called with wrong ptr!!!\n");
+ return;
+ }
+ down(&start_stop_sem);
+ down(&usbduxsub_tmp->sem);
+ tidy_up(usbduxsub_tmp);
+ up(&usbduxsub_tmp->sem);
+ up(&start_stop_sem);
+ dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n");
+}
+
+/* is called when comedi-config is called */
+static int usbdux_attach(comedi_device *dev, comedi_devconfig *it)
+{
+ int ret;
+ int index;
+ int i;
+ struct usbduxsub *udev;
+
+ comedi_subdevice *s = NULL;
+ dev->private = NULL;
+
+ down(&start_stop_sem);
+ /* find a valid device which has been detected by the probe function of
+ * the usb */
+ index = -1;
+ for (i = 0; i < NUMUSBDUX; i++) {
+ if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0) {
+ printk(KERN_ERR "comedi%d: usbdux: error: attach failed, no "
+ "usbdux devs connected to the usb bus.\n", dev->minor);
+ up(&start_stop_sem);
+ return -ENODEV;
+ }
+
+ udev = &usbduxsub[index];
+ down(&udev->sem);
+ /* pointer back to the corresponding comedi device */
+ udev->comedidev = dev;
+
+ /* trying to upload the firmware into the chip */
+ if (comedi_aux_data(it->options, 0) &&
+ it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
+ read_firmware(udev, comedi_aux_data(it->options, 0),
+ it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
+ }
+
+ dev->board_name = BOARDNAME;
+
+ /* set number of subdevices */
+ if (udev->high_speed) {
+ /* with pwm */
+ dev->n_subdevices = 5;
+ } else {
+ /* without pwm */
+ dev->n_subdevices = 4;
+ }
+
+ /* allocate space for the subdevices */
+ ret = alloc_subdevices(dev, dev->n_subdevices);
+ if (ret < 0) {
+ dev_err(&udev->interface->dev,
+ "comedi%d: error alloc space for subdev\n", dev->minor);
+ up(&start_stop_sem);
+ return ret;
+ }
+
+ dev_info(&udev->interface->dev,
+ "comedi%d: usb-device %d is attached to comedi.\n",
+ dev->minor, index);
+ /* private structure is also simply the usb-structure */
+ dev->private = udev;
+
+ /* the first subdevice is the A/D converter */
+ s = dev->subdevices + SUBDEV_AD;
+ /* the URBs get the comedi subdevice */
+ /* which is responsible for reading */
+ /* this is the subdevice which reads data */
+ dev->read_subdev = s;
+ /* the subdevice receives as private structure the */
+ /* usb-structure */
+ s->private = NULL;
+ /* analog input */
+ s->type = COMEDI_SUBD_AI;
+ /* readable and ref is to ground */
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
+ /* 8 channels */
+ s->n_chan = 8;
+ /* length of the channellist */
+ s->len_chanlist = 8;
+ /* callback functions */
+ s->insn_read = usbdux_ai_insn_read;
+ s->do_cmdtest = usbdux_ai_cmdtest;
+ s->do_cmd = usbdux_ai_cmd;
+ s->cancel = usbdux_ai_cancel;
+ /* max value from the A/D converter (12bit) */
+ s->maxdata = 0xfff;
+ /* range table to convert to physical units */
+ s->range_table = (&range_usbdux_ai_range);
+
+ /* analog out */
+ s = dev->subdevices + SUBDEV_DA;
+ /* analog out */
+ s->type = COMEDI_SUBD_AO;
+ /* backward pointer */
+ dev->write_subdev = s;
+ /* the subdevice receives as private structure the */
+ /* usb-structure */
+ s->private = NULL;
+ /* are writable */
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
+ /* 4 channels */
+ s->n_chan = 4;
+ /* length of the channellist */
+ s->len_chanlist = 4;
+ /* 12 bit resolution */
+ s->maxdata = 0x0fff;
+ /* bipolar range */
+ s->range_table = (&range_usbdux_ao_range);
+ /* callback */
+ s->do_cmdtest = usbdux_ao_cmdtest;
+ s->do_cmd = usbdux_ao_cmd;
+ s->cancel = usbdux_ao_cancel;
+ s->insn_read = usbdux_ao_insn_read;
+ s->insn_write = usbdux_ao_insn_write;
+
+ /* digital I/O */
+ s = dev->subdevices + SUBDEV_DIO;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 8;
+ s->maxdata = 1;
+ s->range_table = (&range_digital);
+ s->insn_bits = usbdux_dio_insn_bits;
+ s->insn_config = usbdux_dio_insn_config;
+ /* we don't use it */
+ s->private = NULL;
+
+ /* counter */
+ s = dev->subdevices + SUBDEV_COUNTER;
+ s->type = COMEDI_SUBD_COUNTER;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = 4;
+ s->maxdata = 0xFFFF;
+ s->insn_read = usbdux_counter_read;
+ s->insn_write = usbdux_counter_write;
+ s->insn_config = usbdux_counter_config;
+
+ if (udev->high_speed) {
+ /* timer / pwm */
+ s = dev->subdevices + SUBDEV_PWM;
+ s->type = COMEDI_SUBD_PWM;
+ s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE;
+ s->n_chan = 8;
+ /* this defines the max duty cycle resolution */
+ s->maxdata = udev->sizePwmBuf;
+ s->insn_write = usbdux_pwm_write;
+ s->insn_read = usbdux_pwm_read;
+ s->insn_config = usbdux_pwm_config;
+ usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD);
+ }
+ /* finally decide that it's attached */
+ udev->attached = 1;
+
+ up(&udev->sem);
+
+ up(&start_stop_sem);
+
+ dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n",
+ dev->minor);
+
+ return 0;
+}
+
+static int usbdux_detach(comedi_device *dev)
+{
+ struct usbduxsub *usbduxsub_tmp;
+
+ if (!dev) {
+ printk(KERN_ERR
+ "comedi?: usbdux: detach without dev variable...\n");
+ return -EFAULT;
+ }
+
+ usbduxsub_tmp = dev->private;
+ if (!usbduxsub_tmp) {
+ printk(KERN_ERR
+ "comedi?: usbdux: detach without ptr to usbduxsub[]\n");
+ return -EFAULT;
+ }
+
+ dev_dbg(&usbduxsub_tmp->interface->dev, "comedi%d: detach usb device\n",
+ dev->minor);
+
+ down(&usbduxsub_tmp->sem);
+ /* Don't allow detach to free the private structure */
+ /* It's one entry of of usbduxsub[] */
+ dev->private = NULL;
+ usbduxsub_tmp->attached = 0;
+ usbduxsub_tmp->comedidev = NULL;
+ dev_dbg(&usbduxsub_tmp->interface->dev,
+ "comedi%d: detach: successfully removed\n", dev->minor);
+ up(&usbduxsub_tmp->sem);
+ return 0;
+}
+
+/* main driver struct */
+static comedi_driver driver_usbdux = {
+ .driver_name = "usbdux",
+ .module = THIS_MODULE,
+ .attach = usbdux_attach,
+ .detach = usbdux_detach,
+};
+
+static void init_usb_devices(void)
+{
+ int index;
+
+ /* all devices entries are invalid to begin with */
+ /* they will become valid by the probe function */
+ /* and then finally by the attach-function */
+ for (index = 0; index < NUMUSBDUX; index++) {
+ memset(&(usbduxsub[index]), 0x00, sizeof(usbduxsub[index]));
+ init_MUTEX(&(usbduxsub[index].sem));
+ }
+}
+
+/* Table with the USB-devices: just now only testing IDs */
+static struct usb_device_id usbduxsub_table[] = {
+ {USB_DEVICE(0x13d8, 0x0001) },
+ {USB_DEVICE(0x13d8, 0x0002) },
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, usbduxsub_table);
+
+/* The usbduxsub-driver */
+static struct usb_driver usbduxsub_driver = {
+ .name = BOARDNAME,
+ .probe = usbduxsub_probe,
+ .disconnect = usbduxsub_disconnect,
+ .id_table = usbduxsub_table,
+};
+
+/* Can't use the nice macro as I have also to initialise the USB */
+/* subsystem: */
+/* registering the usb-system _and_ the comedi-driver */
+static int init_usbdux(void)
+{
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ DRIVER_VERSION ":" DRIVER_DESC "\n");
+ init_usb_devices();
+ usb_register(&usbduxsub_driver);
+ comedi_driver_register(&driver_usbdux);
+ return 0;
+}
+
+/* deregistering the comedi driver and the usb-subsystem */
+static void exit_usbdux(void)
+{
+ comedi_driver_unregister(&driver_usbdux);
+ usb_deregister(&usbduxsub_driver);
+}
+
+module_init(init_usbdux);
+module_exit(exit_usbdux);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
new file mode 100644
index 000000000000..3a00ff0cfc5a
--- /dev/null
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -0,0 +1,1778 @@
+#define DRIVER_VERSION "v0.99a"
+#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com"
+#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com"
+/*
+ comedi/drivers/usbduxfast.c
+ Copyright (C) 2004 Bernd Porr, Bernd.Porr@f2s.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+Driver: usbduxfast
+Description: ITL USB-DUXfast
+Devices: [ITL] USB-DUX (usbduxfast.o)
+Author: Bernd Porr <BerndPorr@f2s.com>
+Updated: 04 Dec 2006
+Status: testing
+*/
+
+/*
+ * I must give credit here to Chris Baugher who
+ * wrote the driver for AT-MIO-16d. I used some parts of this
+ * driver. I also must give credits to David Brownell
+ * who supported me with the USB development.
+ *
+ * Bernd Porr
+ *
+ *
+ * Revision history:
+ * 0.9: Dropping the first data packet which seems to be from the last transfer.
+ * Buffer overflows in the FX2 are handed over to comedi.
+ * 0.92: Dropping now 4 packets. The quad buffer has to be emptied.
+ * Added insn command basically for testing. Sample rate is 1MHz/16ch=62.5kHz
+ * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks!
+ * 0.99a: added external trigger.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+#include <linux/fcntl.h>
+#include <linux/compiler.h>
+#include "comedi_fc.h"
+#include "../comedidev.h"
+
+// (un)comment this if you want to have debug info.
+//#define CONFIG_COMEDI_DEBUG
+#undef CONFIG_COMEDI_DEBUG
+
+#define BOARDNAME "usbduxfast"
+
+// timeout for the USB-transfer
+#define EZTIMEOUT 30
+
+// constants for "firmware" upload and download
+#define USBDUXFASTSUB_FIRMWARE 0xA0
+#define VENDOR_DIR_IN 0xC0
+#define VENDOR_DIR_OUT 0x40
+
+// internal adresses of the 8051 processor
+#define USBDUXFASTSUB_CPUCS 0xE600
+
+// max lenghth of the transfer-buffer for software upload
+#define TB_LEN 0x2000
+
+// Input endpoint number
+#define BULKINEP 6
+
+// Endpoint for the A/D channellist: bulk OUT
+#define CHANNELLISTEP 4
+
+// Number of channels
+#define NUMCHANNELS 32
+
+// size of the waveform descriptor
+#define WAVESIZE 0x20
+
+// Size of one A/D value
+#define SIZEADIN ((sizeof(int16_t)))
+
+// Size of the input-buffer IN BYTES
+#define SIZEINBUF 512
+
+// 16 bytes.
+#define SIZEINSNBUF 512
+
+// Size of the buffer for the dux commands
+#define SIZEOFDUXBUFFER 256 // bytes
+
+// Number of in-URBs which receive the data: min=5
+#define NUMOFINBUFFERSHIGH 10
+
+// Total number of usbduxfast devices
+#define NUMUSBDUXFAST 16
+
+// Number of subdevices
+#define N_SUBDEVICES 1
+
+// Analogue in subdevice
+#define SUBDEV_AD 0
+
+// min delay steps for more than one channel
+// basically when the mux gives up. ;-)
+#define MIN_SAMPLING_PERIOD 9 // steps at 30MHz in the FX2
+
+// Max number of 1/30MHz delay steps:
+#define MAX_SAMPLING_PERIOD 500
+
+// Number of received packets to ignore before we start handing data over to comedi.
+// It's quad buffering and we have to ignore 4 packets.
+#define PACKETS_TO_IGNORE 4
+
+/////////////////////////////////////////////
+// comedi constants
+static const comedi_lrange range_usbduxfast_ai_range = { 2, {
+ BIP_RANGE(0.75),
+ BIP_RANGE(0.5),
+ }
+};
+
+/*
+ * private structure of one subdevice
+ */
+
+// This is the structure which holds all the data of this driver
+// one sub device just now: A/D
+typedef struct {
+ // attached?
+ int attached;
+ // is it associated with a subdevice?
+ int probed;
+ // pointer to the usb-device
+ struct usb_device *usbdev;
+ // BULK-transfer handling: urb
+ struct urb *urbIn;
+ int8_t *transfer_buffer;
+ // input buffer for single insn
+ int16_t *insnBuffer;
+ // interface number
+ int ifnum;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ // interface structure in 2.6
+ struct usb_interface *interface;
+#endif
+ // comedi device for the interrupt context
+ comedi_device *comedidev;
+ // asynchronous command is running
+ short int ai_cmd_running;
+ // continous aquisition
+ short int ai_continous;
+ // number of samples to aquire
+ long int ai_sample_count;
+ // commands
+ uint8_t *dux_commands;
+ // counter which ignores the first buffers
+ int ignore;
+ struct semaphore sem;
+} usbduxfastsub_t;
+
+// The pointer to the private usb-data of the driver
+// is also the private data for the comedi-device.
+// This has to be global as the usb subsystem needs
+// global variables. The other reason is that this
+// structure must be there _before_ any comedi
+// command is issued. The usb subsystem must be
+// initialised before comedi can access it.
+static usbduxfastsub_t usbduxfastsub[NUMUSBDUXFAST];
+
+static DECLARE_MUTEX(start_stop_sem);
+
+// bulk transfers to usbduxfast
+
+#define SENDADCOMMANDS 0
+#define SENDINITEP6 1
+
+static int send_dux_commands(usbduxfastsub_t * this_usbduxfastsub, int cmd_type)
+{
+ int result, nsent;
+ this_usbduxfastsub->dux_commands[0] = cmd_type;
+#ifdef CONFIG_COMEDI_DEBUG
+ int i;
+ printk("comedi%d: usbduxfast: dux_commands: ",
+ this_usbduxfastsub->comedidev->minor);
+ for (i = 0; i < SIZEOFDUXBUFFER; i++) {
+ printk(" %02x", this_usbduxfastsub->dux_commands[i]);
+ }
+ printk("\n");
+#endif
+ result = usb_bulk_msg(this_usbduxfastsub->usbdev,
+ usb_sndbulkpipe(this_usbduxfastsub->usbdev,
+ CHANNELLISTEP),
+ this_usbduxfastsub->dux_commands, SIZEOFDUXBUFFER,
+ &nsent, 10000);
+ if (result < 0) {
+ printk("comedi%d: could not transmit dux_commands to the usb-device, err=%d\n", this_usbduxfastsub->comedidev->minor, result);
+ }
+ return result;
+}
+
+// Stops the data acquision
+// It should be safe to call this function from any context
+static int usbduxfastsub_unlink_InURBs(usbduxfastsub_t * usbduxfastsub_tmp)
+{
+ int j = 0;
+ int err = 0;
+
+ if (usbduxfastsub_tmp && usbduxfastsub_tmp->urbIn) {
+ usbduxfastsub_tmp->ai_cmd_running = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
+ j = usb_unlink_urb(usbduxfastsub_tmp->urbIn);
+ if (j < 0) {
+ err = j;
+ }
+#else
+ // waits until a running transfer is over
+ usb_kill_urb(usbduxfastsub_tmp->urbIn);
+ j = 0;
+#endif
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi: usbduxfast: unlinked InURB: res=%d\n", j);
+#endif
+ return err;
+}
+
+/* This will stop a running acquisition operation */
+// Is called from within this driver from both the
+// interrupt context and from comedi
+static int usbduxfast_ai_stop(usbduxfastsub_t * this_usbduxfastsub,
+ int do_unlink)
+{
+ int ret = 0;
+
+ if (!this_usbduxfastsub) {
+ printk("comedi?: usbduxfast_ai_stop: this_usbduxfastsub=NULL!\n");
+ return -EFAULT;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi: usbduxfast_ai_stop\n");
+#endif
+
+ this_usbduxfastsub->ai_cmd_running = 0;
+
+ if (do_unlink) {
+ // stop aquistion
+ ret = usbduxfastsub_unlink_InURBs(this_usbduxfastsub);
+ }
+
+ return ret;
+}
+
+// This will cancel a running acquisition operation.
+// This is called by comedi but never from inside the
+// driver.
+static int usbduxfast_ai_cancel(comedi_device * dev, comedi_subdevice * s)
+{
+ usbduxfastsub_t *this_usbduxfastsub;
+ int res = 0;
+
+ // force unlink of all urbs
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi: usbduxfast_ai_cancel\n");
+#endif
+ this_usbduxfastsub = dev->private;
+ if (!this_usbduxfastsub) {
+ printk("comedi: usbduxfast_ai_cancel: this_usbduxfastsub=NULL\n");
+ return -EFAULT;
+ }
+ down(&this_usbduxfastsub->sem);
+ if (!(this_usbduxfastsub->probed)) {
+ up(&this_usbduxfastsub->sem);
+ return -ENODEV;
+ }
+ // unlink
+ res = usbduxfast_ai_stop(this_usbduxfastsub, 1);
+ up(&this_usbduxfastsub->sem);
+
+ return res;
+}
+
+// analogue IN
+// interrupt service routine
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+static void usbduxfastsub_ai_Irq(struct urb *urb)
+#else
+static void usbduxfastsub_ai_Irq(struct urb *urb PT_REGS_ARG)
+#endif
+{
+ int n, err;
+ usbduxfastsub_t *this_usbduxfastsub;
+ comedi_device *this_comedidev;
+ comedi_subdevice *s;
+ uint16_t *p;
+
+ // sanity checks
+ // is the urb there?
+ if (!urb) {
+ printk("comedi_: usbduxfast_: ao int-handler called with urb=NULL!\n");
+ return;
+ }
+ // the context variable points to the subdevice
+ this_comedidev = urb->context;
+ if (!this_comedidev) {
+ printk("comedi_: usbduxfast_: urb context is a NULL pointer!\n");
+ return;
+ }
+ // the private structure of the subdevice is usbduxfastsub_t
+ this_usbduxfastsub = this_comedidev->private;
+ if (!this_usbduxfastsub) {
+ printk("comedi_: usbduxfast_: private of comedi subdev is a NULL pointer!\n");
+ return;
+ }
+ // are we running a command?
+ if (unlikely(!(this_usbduxfastsub->ai_cmd_running))) {
+ // not running a command
+ // do not continue execution if no asynchronous command is running
+ // in particular not resubmit
+ return;
+ }
+
+ if (unlikely(!(this_usbduxfastsub->attached))) {
+ // no comedi device there
+ return;
+ }
+ // subdevice which is the AD converter
+ s = this_comedidev->subdevices + SUBDEV_AD;
+
+ // first we test if something unusual has just happened
+ switch (urb->status) {
+ case 0:
+ break;
+
+ // happens after an unlink command or when the device is plugged out
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNABORTED:
+ // tell this comedi
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_ERROR;
+ comedi_event(this_usbduxfastsub->comedidev, s);
+ // stop the transfer w/o unlink
+ usbduxfast_ai_stop(this_usbduxfastsub, 0);
+ return;
+
+ default:
+ printk("comedi%d: usbduxfast: non-zero urb status received in ai intr context: %d\n", this_usbduxfastsub->comedidev->minor, urb->status);
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_ERROR;
+ comedi_event(this_usbduxfastsub->comedidev, s);
+ usbduxfast_ai_stop(this_usbduxfastsub, 0);
+ return;
+ }
+
+ p = urb->transfer_buffer;
+ if (!this_usbduxfastsub->ignore) {
+ if (!(this_usbduxfastsub->ai_continous)) {
+ // not continous, fixed number of samples
+ n = urb->actual_length / sizeof(uint16_t);
+ if (unlikely(this_usbduxfastsub->ai_sample_count < n)) {
+ // we have send only a fraction of the bytes received
+ cfc_write_array_to_buffer(s,
+ urb->transfer_buffer,
+ this_usbduxfastsub->ai_sample_count *
+ sizeof(uint16_t));
+ usbduxfast_ai_stop(this_usbduxfastsub, 0);
+ // say comedi that the acquistion is over
+ s->async->events |= COMEDI_CB_EOA;
+ comedi_event(this_usbduxfastsub->comedidev, s);
+ return;
+ }
+ this_usbduxfastsub->ai_sample_count -= n;
+ }
+ // write the full buffer to comedi
+ cfc_write_array_to_buffer(s,
+ urb->transfer_buffer, urb->actual_length);
+
+ // tell comedi that data is there
+ comedi_event(this_usbduxfastsub->comedidev, s);
+
+ } else {
+ // ignore this packet
+ this_usbduxfastsub->ignore--;
+ }
+
+ // command is still running
+ // resubmit urb for BULK transfer
+ urb->dev = this_usbduxfastsub->usbdev;
+ urb->status = 0;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ printk("comedi%d: usbduxfast: urb resubm failed: %d",
+ this_usbduxfastsub->comedidev->minor, err);
+ s->async->events |= COMEDI_CB_EOA;
+ s->async->events |= COMEDI_CB_ERROR;
+ comedi_event(this_usbduxfastsub->comedidev, s);
+ usbduxfast_ai_stop(this_usbduxfastsub, 0);
+ }
+}
+
+static int usbduxfastsub_start(usbduxfastsub_t * usbduxfastsub)
+{
+ int errcode = 0;
+ unsigned char local_transfer_buffer[16];
+
+ if (usbduxfastsub->probed) {
+ // 7f92 to zero
+ local_transfer_buffer[0] = 0;
+ errcode = usb_control_msg(usbduxfastsub->usbdev,
+ // create a pipe for a control transfer
+ usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
+ // bRequest, "Firmware"
+ USBDUXFASTSUB_FIRMWARE,
+ // bmRequestType
+ VENDOR_DIR_OUT,
+ // Value
+ USBDUXFASTSUB_CPUCS,
+ // Index
+ 0x0000,
+ // address of the transfer buffer
+ local_transfer_buffer,
+ // Length
+ 1,
+ // Timeout
+ EZTIMEOUT);
+ if (errcode < 0) {
+ printk("comedi_: usbduxfast_: control msg failed (start)\n");
+ return errcode;
+ }
+ }
+ return 0;
+}
+
+static int usbduxfastsub_stop(usbduxfastsub_t * usbduxfastsub)
+{
+ int errcode = 0;
+
+ unsigned char local_transfer_buffer[16];
+ if (usbduxfastsub->probed) {
+ // 7f92 to one
+ local_transfer_buffer[0] = 1;
+ errcode = usb_control_msg(usbduxfastsub->usbdev,
+ usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
+ // bRequest, "Firmware"
+ USBDUXFASTSUB_FIRMWARE,
+ // bmRequestType
+ VENDOR_DIR_OUT,
+ // Value
+ USBDUXFASTSUB_CPUCS,
+ // Index
+ 0x0000, local_transfer_buffer,
+ // Length
+ 1,
+ // Timeout
+ EZTIMEOUT);
+ if (errcode < 0) {
+ printk("comedi_: usbduxfast: control msg failed (stop)\n");
+ return errcode;
+ }
+ }
+ return 0;
+}
+
+static int usbduxfastsub_upload(usbduxfastsub_t * usbduxfastsub,
+ unsigned char *local_transfer_buffer,
+ unsigned int startAddr, unsigned int len)
+{
+ int errcode;
+
+ if (usbduxfastsub->probed) {
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast: uploading %d bytes",
+ usbduxfastsub->comedidev->minor, len);
+ printk(" to addr %d, first byte=%d.\n",
+ startAddr, local_transfer_buffer[0]);
+#endif
+ errcode = usb_control_msg(usbduxfastsub->usbdev,
+ usb_sndctrlpipe(usbduxfastsub->usbdev, 0),
+ // brequest, firmware
+ USBDUXFASTSUB_FIRMWARE,
+ // bmRequestType
+ VENDOR_DIR_OUT,
+ // value
+ startAddr,
+ // index
+ 0x0000,
+ // our local safe buffer
+ local_transfer_buffer,
+ // length
+ len,
+ // timeout
+ EZTIMEOUT);
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi_: usbduxfast: result=%d\n", errcode);
+#endif
+ if (errcode < 0) {
+ printk("comedi_: usbduxfast: uppload failed\n");
+ return errcode;
+ }
+ } else {
+ // no device on the bus for this index
+ return -EFAULT;
+ }
+ return 0;
+}
+
+int firmwareUpload(usbduxfastsub_t * usbduxfastsub,
+ unsigned char *firmwareBinary, int sizeFirmware)
+{
+ int ret;
+
+ if (!firmwareBinary) {
+ return 0;
+ }
+ ret = usbduxfastsub_stop(usbduxfastsub);
+ if (ret < 0) {
+ printk("comedi_: usbduxfast: can not stop firmware\n");
+ return ret;
+ }
+ ret = usbduxfastsub_upload(usbduxfastsub,
+ firmwareBinary, 0, sizeFirmware);
+ if (ret < 0) {
+ printk("comedi_: usbduxfast: firmware upload failed\n");
+ return ret;
+ }
+ ret = usbduxfastsub_start(usbduxfastsub);
+ if (ret < 0) {
+ printk("comedi_: usbduxfast: can not start firmware\n");
+ return ret;
+ }
+ return 0;
+}
+
+int usbduxfastsub_submit_InURBs(usbduxfastsub_t * usbduxfastsub)
+{
+ int errFlag;
+
+ if (!usbduxfastsub) {
+ return -EFAULT;
+ }
+ usb_fill_bulk_urb(usbduxfastsub->urbIn,
+ usbduxfastsub->usbdev,
+ usb_rcvbulkpipe(usbduxfastsub->usbdev, BULKINEP),
+ usbduxfastsub->transfer_buffer,
+ SIZEINBUF, usbduxfastsub_ai_Irq, usbduxfastsub->comedidev);
+
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast: submitting in-urb: %x,%x\n",
+ usbduxfastsub->comedidev->minor,
+ (int)(usbduxfastsub->urbIn->context),
+ (int)(usbduxfastsub->urbIn->dev));
+#endif
+ errFlag = usb_submit_urb(usbduxfastsub->urbIn, GFP_ATOMIC);
+ if (errFlag) {
+ printk("comedi_: usbduxfast: ai: usb_submit_urb error %d\n",
+ errFlag);
+ return errFlag;
+ }
+ return 0;
+}
+
+static int usbduxfast_ai_cmdtest(comedi_device * dev,
+ comedi_subdevice * s, comedi_cmd * cmd)
+{
+ int err = 0, stop_mask = 0;
+ long int steps, tmp = 0;
+ int minSamplPer;
+ usbduxfastsub_t *this_usbduxfastsub = dev->private;
+ if (!(this_usbduxfastsub->probed)) {
+ return -ENODEV;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast_ai_cmdtest\n", dev->minor);
+ printk("comedi%d: usbduxfast: convert_arg=%u scan_begin_arg=%u\n",
+ dev->minor, cmd->convert_arg, cmd->scan_begin_arg);
+#endif
+ /* step 1: make sure trigger sources are trivially valid */
+
+ tmp = cmd->start_src;
+ cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
+ if (!cmd->start_src || tmp != cmd->start_src)
+ err++;
+
+ tmp = cmd->scan_begin_src;
+ cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;
+ if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
+ err++;
+
+ tmp = cmd->convert_src;
+ cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
+ if (!cmd->convert_src || tmp != cmd->convert_src)
+ err++;
+
+ tmp = cmd->scan_end_src;
+ cmd->scan_end_src &= TRIG_COUNT;
+ if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
+ err++;
+
+ tmp = cmd->stop_src;
+ stop_mask = TRIG_COUNT | TRIG_NONE;
+ cmd->stop_src &= stop_mask;
+ if (!cmd->stop_src || tmp != cmd->stop_src)
+ err++;
+
+ if (err)
+ return 1;
+
+ /* step 2: make sure trigger sources are unique and mutually compatible */
+
+ if (cmd->start_src != TRIG_NOW &&
+ cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT)
+ err++;
+ if (cmd->scan_begin_src != TRIG_TIMER &&
+ cmd->scan_begin_src != TRIG_FOLLOW &&
+ cmd->scan_begin_src != TRIG_EXT)
+ err++;
+ if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
+ err++;
+ if (cmd->stop_src != TRIG_COUNT &&
+ cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
+ err++;
+
+ // can't have external stop and start triggers at once
+ if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
+ err++;
+
+ if (err)
+ return 2;
+
+ /* step 3: make sure arguments are trivially compatible */
+
+ if (cmd->start_src == TRIG_NOW && cmd->start_arg != 0) {
+ cmd->start_arg = 0;
+ err++;
+ }
+
+ if (!cmd->chanlist_len) {
+ err++;
+ }
+ if (cmd->scan_end_arg != cmd->chanlist_len) {
+ cmd->scan_end_arg = cmd->chanlist_len;
+ err++;
+ }
+
+ if (cmd->chanlist_len == 1) {
+ minSamplPer = 1;
+ } else {
+ minSamplPer = MIN_SAMPLING_PERIOD;
+ }
+
+ if (cmd->convert_src == TRIG_TIMER) {
+ steps = cmd->convert_arg * 30;
+ if (steps < (minSamplPer * 1000)) {
+ steps = minSamplPer * 1000;
+ }
+ if (steps > (MAX_SAMPLING_PERIOD * 1000)) {
+ steps = MAX_SAMPLING_PERIOD * 1000;
+ }
+ // calc arg again
+ tmp = steps / 30;
+ if (cmd->convert_arg != tmp) {
+ cmd->convert_arg = tmp;
+ err++;
+ }
+ }
+
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ err++;
+ }
+ // stop source
+ switch (cmd->stop_src) {
+ case TRIG_COUNT:
+ if (!cmd->stop_arg) {
+ cmd->stop_arg = 1;
+ err++;
+ }
+ break;
+ case TRIG_NONE:
+ if (cmd->stop_arg != 0) {
+ cmd->stop_arg = 0;
+ err++;
+ }
+ break;
+ // TRIG_EXT doesn't care since it doesn't trigger off a numbered channel
+ default:
+ break;
+ }
+
+ if (err)
+ return 3;
+
+ /* step 4: fix up any arguments */
+
+ return 0;
+
+}
+
+static int usbduxfast_ai_inttrig(comedi_device * dev,
+ comedi_subdevice * s, unsigned int trignum)
+{
+ int ret;
+ usbduxfastsub_t *this_usbduxfastsub = dev->private;
+ if (!this_usbduxfastsub) {
+ return -EFAULT;
+ }
+ down(&this_usbduxfastsub->sem);
+ if (!(this_usbduxfastsub->probed)) {
+ up(&this_usbduxfastsub->sem);
+ return -ENODEV;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast_ai_inttrig\n", dev->minor);
+#endif
+
+ if (trignum != 0) {
+ printk("comedi%d: usbduxfast_ai_inttrig: invalid trignum\n",
+ dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EINVAL;
+ }
+ if (!(this_usbduxfastsub->ai_cmd_running)) {
+ this_usbduxfastsub->ai_cmd_running = 1;
+ ret = usbduxfastsub_submit_InURBs(this_usbduxfastsub);
+ if (ret < 0) {
+ printk("comedi%d: usbduxfast_ai_inttrig: urbSubmit: err=%d\n", dev->minor, ret);
+ this_usbduxfastsub->ai_cmd_running = 0;
+ up(&this_usbduxfastsub->sem);
+ return ret;
+ }
+ s->async->inttrig = NULL;
+ } else {
+ printk("comedi%d: ai_inttrig but acqu is already running\n",
+ dev->minor);
+ }
+ up(&this_usbduxfastsub->sem);
+ return 1;
+}
+
+// offsets for the GPIF bytes
+// the first byte is the command byte
+#define LENBASE 1+0x00
+#define OPBASE 1+0x08
+#define OUTBASE 1+0x10
+#define LOGBASE 1+0x18
+
+static int usbduxfast_ai_cmd(comedi_device * dev, comedi_subdevice * s)
+{
+ comedi_cmd *cmd = &s->async->cmd;
+ unsigned int chan, gain, rngmask = 0xff;
+ int i, j, ret;
+ usbduxfastsub_t *this_usbduxfastsub = dev->private;
+ int result;
+ long steps, steps_tmp;
+
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast_ai_cmd\n", dev->minor);
+#endif
+ if (!this_usbduxfastsub) {
+ return -EFAULT;
+ }
+ down(&this_usbduxfastsub->sem);
+ if (!(this_usbduxfastsub->probed)) {
+ up(&this_usbduxfastsub->sem);
+ return -ENODEV;
+ }
+ if (this_usbduxfastsub->ai_cmd_running) {
+ printk("comedi%d: ai_cmd not possible. Another ai_cmd is running.\n", dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EBUSY;
+ }
+ // set current channel of the running aquisition to zero
+ s->async->cur_chan = 0;
+
+ // ignore the first buffers from the device if there is an error condition
+ this_usbduxfastsub->ignore = PACKETS_TO_IGNORE;
+
+ if (cmd->chanlist_len > 0) {
+ gain = CR_RANGE(cmd->chanlist[0]);
+ for (i = 0; i < cmd->chanlist_len; ++i) {
+ chan = CR_CHAN(cmd->chanlist[i]);
+ if (chan != i) {
+ printk("comedi%d: cmd is accepting only consecutive channels.\n", dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EINVAL;
+ }
+ if ((gain != CR_RANGE(cmd->chanlist[i]))
+ && (cmd->chanlist_len > 3)) {
+ printk("comedi%d: the gain must be the same for all channels.\n", dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EINVAL;
+ }
+ if (i >= NUMCHANNELS) {
+ printk("comedi%d: channel list too long\n",
+ dev->minor);
+ break;
+ }
+ }
+ }
+ steps = 0;
+ if (cmd->scan_begin_src == TRIG_TIMER) {
+ printk("comedi%d: usbduxfast: scan_begin_src==TRIG_TIMER not valid.\n", dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EINVAL;
+ }
+ if (cmd->convert_src == TRIG_TIMER) {
+ steps = (cmd->convert_arg * 30) / 1000;
+ }
+ if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) {
+ printk("comedi%d: usbduxfast: ai_cmd: steps=%ld, scan_begin_arg=%d. Not properly tested by cmdtest?\n", dev->minor, steps, cmd->scan_begin_arg);
+ up(&this_usbduxfastsub->sem);
+ return -EINVAL;
+ }
+ if (steps > MAX_SAMPLING_PERIOD) {
+ printk("comedi%d: usbduxfast: ai_cmd: sampling rate too low.\n",
+ dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EINVAL;
+ }
+ if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1)
+ && (cmd->chanlist_len != 16)) {
+ printk("comedi%d: usbduxfast: ai_cmd: TRIG_EXT only with 1 or 16 channels possible.\n", dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EINVAL;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast: steps=%ld, convert_arg=%u, ai_timer=%u\n",
+ dev->minor,
+ steps, cmd->convert_arg, this_usbduxfastsub->ai_timer);
+#endif
+
+ switch (cmd->chanlist_len) {
+ // one channel
+ case 1:
+ if (CR_RANGE(cmd->chanlist[0]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+
+ // for external trigger: looping in this state until the RDY0 pin
+ // becomes zero
+ if (cmd->start_src == TRIG_EXT) { // we loop here until ready has been set
+ this_usbduxfastsub->dux_commands[LENBASE + 0] = 0x01; // branch back to state 0
+ this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x01; // deceision state w/o data
+ this_usbduxfastsub->dux_commands[OUTBASE + 0] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0x00; // RDY0 = 0
+ } else { // we just proceed to state 1
+ this_usbduxfastsub->dux_commands[LENBASE + 0] = 1;
+ this_usbduxfastsub->dux_commands[OPBASE + 0] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 0] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
+ }
+
+ if (steps < MIN_SAMPLING_PERIOD) {
+ // for fast single channel aqu without mux
+ if (steps <= 1) {
+ // we just stay here at state 1 and rexecute the same state
+ // this gives us 30MHz sampling rate
+ this_usbduxfastsub->dux_commands[LENBASE + 1] = 0x89; // branch back to state 1
+ this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x03; // deceision state with data
+ this_usbduxfastsub->dux_commands[OUTBASE + 1] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0xFF; // doesn't matter
+ } else {
+ // we loop through two states: data and delay: max rate is 15Mhz
+ this_usbduxfastsub->dux_commands[LENBASE + 1] =
+ steps - 1;
+ this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x02; // data
+ this_usbduxfastsub->dux_commands[OUTBASE + 1] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0; // doesn't matter
+
+ this_usbduxfastsub->dux_commands[LENBASE + 2] = 0x09; // branch back to state 1
+ this_usbduxfastsub->dux_commands[OPBASE + 2] = 0x01; // deceision state w/o data
+ this_usbduxfastsub->dux_commands[OUTBASE + 2] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0xFF; // doesn't matter
+ }
+ } else {
+ // we loop through 3 states: 2x delay and 1x data. This gives a min
+ // sampling rate of 60kHz.
+
+ // we have 1 state with duration 1
+ steps = steps - 1;
+
+ // do the first part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + 1] =
+ steps / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 1] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 1] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
+
+ // and the second part
+ this_usbduxfastsub->dux_commands[LENBASE + 2] =
+ steps - steps / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 2] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 2] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
+
+ // get the data and branch back
+ this_usbduxfastsub->dux_commands[LENBASE + 3] = 0x09; // branch back to state 1
+ this_usbduxfastsub->dux_commands[OPBASE + 3] = 0x03; // deceision state w data
+ this_usbduxfastsub->dux_commands[OUTBASE + 3] =
+ 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0xFF; // doesn't matter
+ }
+ break;
+
+ case 2:
+ // two channels
+ // commit data to the FIFO
+ if (CR_RANGE(cmd->chanlist[0]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ this_usbduxfastsub->dux_commands[LENBASE + 0] = 1;
+ this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x02; // data
+ this_usbduxfastsub->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
+
+ // we have 1 state with duration 1: state 0
+ steps_tmp = steps - 1;
+
+ if (CR_RANGE(cmd->chanlist[1]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ // do the first part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + 1] = steps_tmp / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 1] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFE & rngmask; //count
+ this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
+
+ // and the second part
+ this_usbduxfastsub->dux_commands[LENBASE + 2] =
+ steps_tmp - steps_tmp / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 2] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
+
+ this_usbduxfastsub->dux_commands[LENBASE + 3] = 1;
+ this_usbduxfastsub->dux_commands[OPBASE + 3] = 0x02; // data
+ this_usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0;
+
+ // we have 2 states with duration 1: step 6 and the IDLE state
+ steps_tmp = steps - 2;
+
+ if (CR_RANGE(cmd->chanlist[0]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ // do the first part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + 4] = steps_tmp / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 4] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 4] = (0xFF - 0x02) & rngmask; //reset
+ this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0;
+
+ // and the second part
+ this_usbduxfastsub->dux_commands[LENBASE + 5] =
+ steps_tmp - steps_tmp / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 5] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 5] = 0;
+
+ this_usbduxfastsub->dux_commands[LENBASE + 6] = 1;
+ this_usbduxfastsub->dux_commands[OPBASE + 6] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 6] = 0;
+ break;
+
+ case 3:
+ // three channels
+ for (j = 0; j < 1; j++) {
+ if (CR_RANGE(cmd->chanlist[j]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ // commit data to the FIFO and do the first part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + j * 2] =
+ steps / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + j * 2] = 0x02; // data
+ this_usbduxfastsub->dux_commands[OUTBASE + j * 2] = 0xFF & rngmask; // no change
+ this_usbduxfastsub->dux_commands[LOGBASE + j * 2] = 0;
+
+ if (CR_RANGE(cmd->chanlist[j + 1]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ // do the second part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + j * 2 + 1] =
+ steps - steps / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + j * 2 + 1] = 0; // no data
+ this_usbduxfastsub->dux_commands[OUTBASE + j * 2 + 1] = 0xFE & rngmask; //count
+ this_usbduxfastsub->dux_commands[LOGBASE + j * 2 + 1] =
+ 0;
+ }
+
+ // 2 steps with duration 1: the idele step and step 6:
+ steps_tmp = steps - 2;
+ // commit data to the FIFO and do the first part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + 4] = steps_tmp / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 4] = 0x02; // data
+ this_usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFF & rngmask; // no change
+ this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0;
+
+ if (CR_RANGE(cmd->chanlist[0]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ // do the second part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + 5] =
+ steps_tmp - steps_tmp / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 5] = 0; // no data
+ this_usbduxfastsub->dux_commands[OUTBASE + 5] = (0xFF - 0x02) & rngmask; // reset
+ this_usbduxfastsub->dux_commands[LOGBASE + 5] = 0;
+
+ this_usbduxfastsub->dux_commands[LENBASE + 6] = 1;
+ this_usbduxfastsub->dux_commands[OPBASE + 6] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 6] = 0;
+
+ case 16:
+ if (CR_RANGE(cmd->chanlist[0]) > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ if (cmd->start_src == TRIG_EXT) { // we loop here until ready has been set
+ this_usbduxfastsub->dux_commands[LENBASE + 0] = 0x01; // branch back to state 0
+ this_usbduxfastsub->dux_commands[OPBASE + 0] = 0x01; // deceision state w/o data
+ this_usbduxfastsub->dux_commands[OUTBASE + 0] = (0xFF - 0x02) & rngmask; // reset
+ this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0x00; // RDY0 = 0
+ } else { // we just proceed to state 1
+ this_usbduxfastsub->dux_commands[LENBASE + 0] = 255; // 30us reset pulse
+ this_usbduxfastsub->dux_commands[OPBASE + 0] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 0] = (0xFF - 0x02) & rngmask; // reset
+ this_usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
+ }
+
+ // commit data to the FIFO
+ this_usbduxfastsub->dux_commands[LENBASE + 1] = 1;
+ this_usbduxfastsub->dux_commands[OPBASE + 1] = 0x02; // data
+ this_usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
+
+ // we have 2 states with duration 1
+ steps = steps - 2;
+
+ // do the first part of the delay
+ this_usbduxfastsub->dux_commands[LENBASE + 2] = steps / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 2] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
+
+ // and the second part
+ this_usbduxfastsub->dux_commands[LENBASE + 3] =
+ steps - steps / 2;
+ this_usbduxfastsub->dux_commands[OPBASE + 3] = 0;
+ this_usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 3] = 0;
+
+ this_usbduxfastsub->dux_commands[LENBASE + 4] = 0x09; // branch back to state 1
+ this_usbduxfastsub->dux_commands[OPBASE + 4] = 0x01; // deceision state w/o data
+ this_usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFF & rngmask;
+ this_usbduxfastsub->dux_commands[LOGBASE + 4] = 0xFF; // doesn't matter
+
+ break;
+
+ default:
+ printk("comedi %d: unsupported combination of channels\n",
+ dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EFAULT;
+ }
+
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi %d: sending commands to the usb device\n", dev->minor);
+#endif
+ // 0 means that the AD commands are sent
+ result = send_dux_commands(this_usbduxfastsub, SENDADCOMMANDS);
+ if (result < 0) {
+ printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return result;
+ }
+ if (cmd->stop_src == TRIG_COUNT) {
+ this_usbduxfastsub->ai_sample_count =
+ (cmd->stop_arg) * (cmd->scan_end_arg);
+ if (usbduxfastsub->ai_sample_count < 1) {
+ printk("comedi%d: (cmd->stop_arg)*(cmd->scan_end_arg)<1, aborting.\n", dev->minor);
+ up(&this_usbduxfastsub->sem);
+ return -EFAULT;
+ }
+ this_usbduxfastsub->ai_continous = 0;
+ } else {
+ // continous aquisition
+ this_usbduxfastsub->ai_continous = 1;
+ this_usbduxfastsub->ai_sample_count = 0;
+ }
+
+ if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) {
+ // enable this acquisition operation
+ this_usbduxfastsub->ai_cmd_running = 1;
+ ret = usbduxfastsub_submit_InURBs(this_usbduxfastsub);
+ if (ret < 0) {
+ this_usbduxfastsub->ai_cmd_running = 0;
+ // fixme: unlink here??
+ up(&this_usbduxfastsub->sem);
+ return ret;
+ }
+ s->async->inttrig = NULL;
+ } else {
+ /* TRIG_INT */
+ // don't enable the acquision operation
+ // wait for an internal signal
+ s->async->inttrig = usbduxfast_ai_inttrig;
+ }
+ up(&this_usbduxfastsub->sem);
+
+ return 0;
+}
+
+/* Mode 0 is used to get a single conversion on demand */
+static int usbduxfast_ai_insn_read(comedi_device * dev,
+ comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
+{
+ int i, j, n, actual_length;
+ int chan, range, rngmask;
+ int err;
+ usbduxfastsub_t *usbduxfastsub = dev->private;
+
+ if (!usbduxfastsub) {
+ printk("comedi%d: ai_insn_read: no usb dev.\n", dev->minor);
+ return -ENODEV;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n",
+ dev->minor, insn->n, insn->subdev);
+#endif
+ down(&usbduxfastsub->sem);
+ if (!(usbduxfastsub->probed)) {
+ up(&usbduxfastsub->sem);
+ return -ENODEV;
+ }
+ if (usbduxfastsub->ai_cmd_running) {
+ printk("comedi%d: ai_insn_read not possible. Async Command is running.\n", dev->minor);
+ up(&usbduxfastsub->sem);
+ return -EBUSY;
+ }
+ // sample one channel
+ chan = CR_CHAN(insn->chanspec);
+ range = CR_RANGE(insn->chanspec);
+ // set command for the first channel
+
+ if (range > 0)
+ rngmask = 0xff - 0x04;
+ else
+ rngmask = 0xff;
+ // commit data to the FIFO
+ usbduxfastsub->dux_commands[LENBASE + 0] = 1;
+ usbduxfastsub->dux_commands[OPBASE + 0] = 0x02; // data
+ usbduxfastsub->dux_commands[OUTBASE + 0] = 0xFF & rngmask;
+ usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
+
+ // do the first part of the delay
+ usbduxfastsub->dux_commands[LENBASE + 1] = 12;
+ usbduxfastsub->dux_commands[OPBASE + 1] = 0;
+ usbduxfastsub->dux_commands[OUTBASE + 1] = 0xFE & rngmask;
+ usbduxfastsub->dux_commands[LOGBASE + 1] = 0;
+
+ usbduxfastsub->dux_commands[LENBASE + 2] = 1;
+ usbduxfastsub->dux_commands[OPBASE + 2] = 0;
+ usbduxfastsub->dux_commands[OUTBASE + 2] = 0xFE & rngmask;
+ usbduxfastsub->dux_commands[LOGBASE + 2] = 0;
+
+ usbduxfastsub->dux_commands[LENBASE + 3] = 1;
+ usbduxfastsub->dux_commands[OPBASE + 3] = 0;
+ usbduxfastsub->dux_commands[OUTBASE + 3] = 0xFE & rngmask;
+ usbduxfastsub->dux_commands[LOGBASE + 3] = 0;
+
+ usbduxfastsub->dux_commands[LENBASE + 4] = 1;
+ usbduxfastsub->dux_commands[OPBASE + 4] = 0;
+ usbduxfastsub->dux_commands[OUTBASE + 4] = 0xFE & rngmask;
+ usbduxfastsub->dux_commands[LOGBASE + 4] = 0;
+
+ // second part
+ usbduxfastsub->dux_commands[LENBASE + 5] = 12;
+ usbduxfastsub->dux_commands[OPBASE + 5] = 0;
+ usbduxfastsub->dux_commands[OUTBASE + 5] = 0xFF & rngmask;
+ usbduxfastsub->dux_commands[LOGBASE + 5] = 0;
+
+ usbduxfastsub->dux_commands[LENBASE + 6] = 1;
+ usbduxfastsub->dux_commands[OPBASE + 6] = 0;
+ usbduxfastsub->dux_commands[OUTBASE + 6] = 0xFF & rngmask;
+ usbduxfastsub->dux_commands[LOGBASE + 0] = 0;
+
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi %d: sending commands to the usb device\n", dev->minor);
+#endif
+ // 0 means that the AD commands are sent
+ err = send_dux_commands(usbduxfastsub, SENDADCOMMANDS);
+ if (err < 0) {
+ printk("comedi%d: adc command could not be submitted. Aborting...\n", dev->minor);
+ up(&usbduxfastsub->sem);
+ return err;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast: submitting in-urb: %x,%x\n",
+ usbduxfastsub->comedidev->minor,
+ (int)(usbduxfastsub->urbIn->context),
+ (int)(usbduxfastsub->urbIn->dev));
+#endif
+ for (i = 0; i < PACKETS_TO_IGNORE; i++) {
+ err = usb_bulk_msg(usbduxfastsub->usbdev,
+ usb_rcvbulkpipe(usbduxfastsub->usbdev,
+ BULKINEP),
+ usbduxfastsub->transfer_buffer, SIZEINBUF,
+ &actual_length, 10000);
+ if (err < 0) {
+ printk("comedi%d: insn timeout. No data.\n",
+ dev->minor);
+ up(&usbduxfastsub->sem);
+ return err;
+ }
+ }
+ // data points
+ for (i = 0; i < insn->n;) {
+ err = usb_bulk_msg(usbduxfastsub->usbdev,
+ usb_rcvbulkpipe(usbduxfastsub->usbdev,
+ BULKINEP),
+ usbduxfastsub->transfer_buffer, SIZEINBUF,
+ &actual_length, 10000);
+ if (err < 0) {
+ printk("comedi%d: insn data error: %d\n",
+ dev->minor, err);
+ up(&usbduxfastsub->sem);
+ return err;
+ }
+ n = actual_length / sizeof(uint16_t);
+ if ((n % 16) != 0) {
+ printk("comedi%d: insn data packet corrupted.\n",
+ dev->minor);
+ up(&usbduxfastsub->sem);
+ return -EINVAL;
+ }
+ for (j = chan; (j < n) && (i < insn->n); j = j + 16) {
+ data[i] =
+ ((uint16_t *) (usbduxfastsub->
+ transfer_buffer))[j];
+ i++;
+ }
+ }
+ up(&usbduxfastsub->sem);
+ return i;
+}
+
+static unsigned hex2unsigned(char *h)
+{
+ unsigned hi, lo;
+ if (h[0] > '9') {
+ hi = h[0] - 'A' + 0x0a;
+ } else {
+ hi = h[0] - '0';
+ }
+ if (h[1] > '9') {
+ lo = h[1] - 'A' + 0x0a;
+ } else {
+ lo = h[1] - '0';
+ }
+ return hi * 0x10 + lo;
+}
+
+// for FX2
+#define FIRMWARE_MAX_LEN 0x2000
+
+// taken from David Brownell's fxload and adjusted for this driver
+static int read_firmware(usbduxfastsub_t * usbduxfastsub, void *firmwarePtr,
+ long size)
+{
+ int i = 0;
+ unsigned char *fp = (char *)firmwarePtr;
+ unsigned char *firmwareBinary = NULL;
+ int res = 0;
+ int maxAddr = 0;
+
+ firmwareBinary = kmalloc(FIRMWARE_MAX_LEN, GFP_KERNEL);
+ if (!firmwareBinary) {
+ printk("comedi_: usbduxfast: mem alloc for firmware failed\n");
+ return -ENOMEM;
+ }
+
+ for (;;) {
+ char buf[256], *cp;
+ char type;
+ int len;
+ int idx, off;
+ int j = 0;
+
+ // get one line
+ while ((i < size) && (fp[i] != 13) && (fp[i] != 10)) {
+ buf[j] = fp[i];
+ i++;
+ j++;
+ if (j >= sizeof(buf)) {
+ printk("comedi_: usbduxfast: bogus firmware file!\n");
+ return -1;
+ }
+ }
+ // get rid of LF/CR/...
+ while ((i < size) && ((fp[i] == 13) || (fp[i] == 10)
+ || (fp[i] == 0))) {
+ i++;
+ }
+
+ buf[j] = 0;
+ //printk("comedi_: buf=%s\n",buf);
+
+ /* EXTENSION: "# comment-till-end-of-line", for copyrights etc */
+ if (buf[0] == '#')
+ continue;
+
+ if (buf[0] != ':') {
+ printk("comedi_: usbduxfast: upload: not an ihex record: %s", buf);
+ return -EFAULT;
+ }
+
+ /* Read the length field (up to 16 bytes) */
+ len = hex2unsigned(buf + 1);
+
+ /* Read the target offset */
+ off = (hex2unsigned(buf + 3) * 0x0100) + hex2unsigned(buf + 5);
+
+ if ((off + len) > maxAddr) {
+ maxAddr = off + len;
+ }
+
+ if (maxAddr >= FIRMWARE_MAX_LEN) {
+ printk("comedi_: usbduxfast: firmware upload goes beyond FX2 RAM boundaries.");
+ return -EFAULT;
+ }
+ //printk("comedi_: usbduxfast: off=%x, len=%x:",off,len);
+
+ /* Read the record type */
+ type = hex2unsigned(buf + 7);
+
+ /* If this is an EOF record, then make it so. */
+ if (type == 1) {
+ break;
+ }
+
+ if (type != 0) {
+ printk("comedi_: usbduxfast: unsupported record type: %u\n", type);
+ return -EFAULT;
+ }
+
+ for (idx = 0, cp = buf + 9; idx < len; idx += 1, cp += 2) {
+ firmwareBinary[idx + off] = hex2unsigned(cp);
+ //printk("%02x ",firmwareBinary[idx+off]);
+ }
+ //printk("\n");
+
+ if (i >= size) {
+ printk("comedi_: usbduxfast: unexpected end of hex file\n");
+ break;
+ }
+
+ }
+ res = firmwareUpload(usbduxfastsub, firmwareBinary, maxAddr + 1);
+ kfree(firmwareBinary);
+ return res;
+}
+
+static void tidy_up(usbduxfastsub_t * usbduxfastsub_tmp)
+{
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi_: usbduxfast: tiding up\n");
+#endif
+ if (!usbduxfastsub_tmp) {
+ return;
+ }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ // shows the usb subsystem that the driver is down
+ if (usbduxfastsub_tmp->interface) {
+ usb_set_intfdata(usbduxfastsub_tmp->interface, NULL);
+ }
+#endif
+
+ usbduxfastsub_tmp->probed = 0;
+
+ if (usbduxfastsub_tmp->urbIn) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
+ // waits until a running transfer is over
+ // thus, under 2.4 hotplugging while a command
+ // is running is not safe
+ usb_kill_urb(usbduxfastsub_tmp->urbIn);
+#endif
+ if (usbduxfastsub_tmp->transfer_buffer) {
+ kfree(usbduxfastsub_tmp->transfer_buffer);
+ usbduxfastsub_tmp->transfer_buffer = NULL;
+ }
+ usb_free_urb(usbduxfastsub_tmp->urbIn);
+ usbduxfastsub_tmp->urbIn = NULL;
+ }
+ if (usbduxfastsub_tmp->insnBuffer) {
+ kfree(usbduxfastsub_tmp->insnBuffer);
+ usbduxfastsub_tmp->insnBuffer = NULL;
+ }
+ if (usbduxfastsub_tmp->dux_commands) {
+ kfree(usbduxfastsub_tmp->dux_commands);
+ usbduxfastsub_tmp->dux_commands = NULL;
+ }
+ usbduxfastsub_tmp->ai_cmd_running = 0;
+}
+
+// allocate memory for the urbs and initialise them
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+static void *usbduxfastsub_probe(struct usb_device *udev,
+ unsigned int interfnum, const struct usb_device_id *id)
+{
+#else
+static int usbduxfastsub_probe(struct usb_interface *uinterf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(uinterf);
+#endif
+ int i;
+ int index;
+
+ if (udev->speed != USB_SPEED_HIGH) {
+ printk("comedi_: usbduxfast_: This driver needs USB 2.0 to operate. Aborting...\n");
+ return -ENODEV;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi_: usbduxfast_: finding a free structure for the usb-device\n");
+#endif
+ down(&start_stop_sem);
+ // look for a free place in the usbduxfast array
+ index = -1;
+ for (i = 0; i < NUMUSBDUXFAST; i++) {
+ if (!(usbduxfastsub[i].probed)) {
+ index = i;
+ break;
+ }
+ }
+
+ // no more space
+ if (index == -1) {
+ printk("Too many usbduxfast-devices connected.\n");
+ up(&start_stop_sem);
+ return -EMFILE;
+ }
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi_: usbduxfast: usbduxfastsub[%d] is ready to connect to comedi.\n", index);
+#endif
+
+ init_MUTEX(&(usbduxfastsub[index].sem));
+ // save a pointer to the usb device
+ usbduxfastsub[index].usbdev = udev;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ // save the interface number
+ usbduxfastsub[index].ifnum = interfnum;
+#else
+ // 2.6: save the interface itself
+ usbduxfastsub[index].interface = uinterf;
+ // get the interface number from the interface
+ usbduxfastsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber;
+ // hand the private data over to the usb subsystem
+ // will be needed for disconnect
+ usb_set_intfdata(uinterf, &(usbduxfastsub[index]));
+#endif
+
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi_: usbduxfast: ifnum=%d\n", usbduxfastsub[index].ifnum);
+#endif
+ // create space for the commands going to the usb device
+ usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER,
+ GFP_KERNEL);
+ if (!usbduxfastsub[index].dux_commands) {
+ printk("comedi_: usbduxfast: error alloc space for dac commands\n");
+ tidy_up(&(usbduxfastsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ // create space of the instruction buffer
+ usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL);
+ if (!(usbduxfastsub[index].insnBuffer)) {
+ printk("comedi_: usbduxfast: could not alloc space for insnBuffer\n");
+ tidy_up(&(usbduxfastsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ // setting to alternate setting 1: enabling bulk ep
+ i = usb_set_interface(usbduxfastsub[index].usbdev,
+ usbduxfastsub[index].ifnum, 1);
+ if (i < 0) {
+ printk("comedi_: usbduxfast%d: could not switch to alternate setting 1.\n", index);
+ tidy_up(&(usbduxfastsub[index]));
+ up(&start_stop_sem);
+ return -ENODEV;
+ }
+ usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL);
+ if (usbduxfastsub[index].urbIn == NULL) {
+ printk("comedi_: usbduxfast%d: Could not alloc. urb\n", index);
+ tidy_up(&(usbduxfastsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL);
+ if (!(usbduxfastsub[index].transfer_buffer)) {
+ printk("comedi_: usbduxfast%d: could not alloc. transb.\n",
+ index);
+ tidy_up(&(usbduxfastsub[index]));
+ up(&start_stop_sem);
+ return -ENOMEM;
+ }
+ // we've reached the bottom of the function
+ usbduxfastsub[index].probed = 1;
+ up(&start_stop_sem);
+ printk("comedi_: usbduxfast%d has been successfully initialized.\n",
+ index);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ return (void *)(&usbduxfastsub[index]);
+#else
+ // success
+ return 0;
+#endif
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+static void usbduxfastsub_disconnect(struct usb_device *udev, void *ptr)
+{
+ usbduxfastsub_t *usbduxfastsub_tmp = (usbduxfastsub_t *) ptr;
+#else
+static void usbduxfastsub_disconnect(struct usb_interface *intf)
+{
+ usbduxfastsub_t *usbduxfastsub_tmp = usb_get_intfdata(intf);
+ struct usb_device *udev = interface_to_usbdev(intf);
+#endif
+ if (!usbduxfastsub_tmp) {
+ printk("comedi_: usbduxfast: disconnect called with null pointer.\n");
+ return;
+ }
+ if (usbduxfastsub_tmp->usbdev != udev) {
+ printk("comedi_: usbduxfast: BUG! called with wrong ptr!!!\n");
+ return;
+ }
+ down(&start_stop_sem);
+ down(&usbduxfastsub_tmp->sem);
+ tidy_up(usbduxfastsub_tmp);
+ up(&usbduxfastsub_tmp->sem);
+ up(&start_stop_sem);
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi_: usbduxfast: disconnected from the usb\n");
+#endif
+}
+
+// is called when comedi-config is called
+static int usbduxfast_attach(comedi_device * dev, comedi_devconfig * it)
+{
+ int ret;
+ int index;
+ int i;
+ comedi_subdevice *s = NULL;
+ dev->private = NULL;
+
+ down(&start_stop_sem);
+ // find a valid device which has been detected by the probe function of the usb
+ index = -1;
+ for (i = 0; i < NUMUSBDUXFAST; i++) {
+ if ((usbduxfastsub[i].probed) && (!usbduxfastsub[i].attached)) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index < 0) {
+ printk("comedi%d: usbduxfast: error: attach failed, no usbduxfast devs connected to the usb bus.\n", dev->minor);
+ up(&start_stop_sem);
+ return -ENODEV;
+ }
+
+ down(&(usbduxfastsub[index].sem));
+ // pointer back to the corresponding comedi device
+ usbduxfastsub[index].comedidev = dev;
+
+ // trying to upload the firmware into the chip
+ if (comedi_aux_data(it->options, 0) &&
+ it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
+ read_firmware(usbduxfastsub,
+ comedi_aux_data(it->options, 0),
+ it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]);
+ }
+
+ dev->board_name = BOARDNAME;
+
+ /* set number of subdevices */
+ dev->n_subdevices = N_SUBDEVICES;
+
+ // allocate space for the subdevices
+ if ((ret = alloc_subdevices(dev, N_SUBDEVICES)) < 0) {
+ printk("comedi%d: usbduxfast: error alloc space for subdev\n",
+ dev->minor);
+ up(&start_stop_sem);
+ return ret;
+ }
+
+ printk("comedi%d: usbduxfast: usb-device %d is attached to comedi.\n",
+ dev->minor, index);
+ // private structure is also simply the usb-structure
+ dev->private = usbduxfastsub + index;
+ // the first subdevice is the A/D converter
+ s = dev->subdevices + SUBDEV_AD;
+ // the URBs get the comedi subdevice
+ // which is responsible for reading
+ // this is the subdevice which reads data
+ dev->read_subdev = s;
+ // the subdevice receives as private structure the
+ // usb-structure
+ s->private = NULL;
+ // analog input
+ s->type = COMEDI_SUBD_AI;
+ // readable and ref is to ground
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
+ // 16 channels
+ s->n_chan = 16;
+ // length of the channellist
+ s->len_chanlist = 16;
+ // callback functions
+ s->insn_read = usbduxfast_ai_insn_read;
+ s->do_cmdtest = usbduxfast_ai_cmdtest;
+ s->do_cmd = usbduxfast_ai_cmd;
+ s->cancel = usbduxfast_ai_cancel;
+ // max value from the A/D converter (12bit+1 bit for overflow)
+ s->maxdata = 0x1000;
+ // range table to convert to physical units
+ s->range_table = &range_usbduxfast_ai_range;
+
+ // finally decide that it's attached
+ usbduxfastsub[index].attached = 1;
+
+ up(&(usbduxfastsub[index].sem));
+
+ up(&start_stop_sem);
+
+ printk("comedi%d: successfully attached to usbduxfast.\n", dev->minor);
+
+ return 0;
+}
+
+static int usbduxfast_detach(comedi_device * dev)
+{
+ usbduxfastsub_t *usbduxfastsub_tmp;
+
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast: detach usb device\n", dev->minor);
+#endif
+
+ if (!dev) {
+ printk("comedi?: usbduxfast: detach without dev variable...\n");
+ return -EFAULT;
+ }
+
+ usbduxfastsub_tmp = dev->private;
+ if (!usbduxfastsub_tmp) {
+ printk("comedi?: usbduxfast: detach without ptr to usbduxfastsub[]\n");
+ return -EFAULT;
+ }
+
+ down(&usbduxfastsub_tmp->sem);
+ down(&start_stop_sem);
+ // Don't allow detach to free the private structure
+ // It's one entry of of usbduxfastsub[]
+ dev->private = NULL;
+ usbduxfastsub_tmp->attached = 0;
+ usbduxfastsub_tmp->comedidev = NULL;
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi%d: usbduxfast: detach: successfully removed\n",
+ dev->minor);
+#endif
+ up(&start_stop_sem);
+ up(&usbduxfastsub_tmp->sem);
+ return 0;
+}
+
+/* main driver struct */
+static comedi_driver driver_usbduxfast = {
+ driver_name:"usbduxfast",
+ module:THIS_MODULE,
+ attach:usbduxfast_attach,
+ detach:usbduxfast_detach,
+};
+
+static void init_usb_devices(void)
+{
+ int index;
+#ifdef CONFIG_COMEDI_DEBUG
+ printk("comedi_: usbduxfast: setting all possible devs to invalid\n");
+#endif
+ // all devices entries are invalid to begin with
+ // they will become valid by the probe function
+ // and then finally by the attach-function
+ for (index = 0; index < NUMUSBDUXFAST; index++) {
+ memset(&(usbduxfastsub[index]), 0x00,
+ sizeof(usbduxfastsub[index]));
+ init_MUTEX(&(usbduxfastsub[index].sem));
+ }
+}
+
+// Table with the USB-devices: just now only testing IDs
+static struct usb_device_id usbduxfastsub_table[] = {
+ // { USB_DEVICE(0x4b4, 0x8613), //testing
+ // },
+ {USB_DEVICE(0x13d8, 0x0010) //real ID
+ },
+ {USB_DEVICE(0x13d8, 0x0011) //real ID
+ },
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, usbduxfastsub_table);
+
+// The usbduxfastsub-driver
+static struct usb_driver usbduxfastsub_driver = {
+#ifdef COMEDI_HAVE_USB_DRIVER_OWNER
+ owner:THIS_MODULE,
+#endif
+ name:BOARDNAME,
+ probe:usbduxfastsub_probe,
+ disconnect:usbduxfastsub_disconnect,
+ id_table:usbduxfastsub_table,
+};
+
+// Can't use the nice macro as I have also to initialise the USB
+// subsystem:
+// registering the usb-system _and_ the comedi-driver
+static int init_usbduxfast(void)
+{
+ printk(KERN_INFO KBUILD_MODNAME ": "
+ DRIVER_VERSION ":" DRIVER_DESC "\n");
+ init_usb_devices();
+ usb_register(&usbduxfastsub_driver);
+ comedi_driver_register(&driver_usbduxfast);
+ return 0;
+}
+
+// deregistering the comedi driver and the usb-subsystem
+static void exit_usbduxfast(void)
+{
+ comedi_driver_unregister(&driver_usbduxfast);
+ usb_deregister(&usbduxfastsub_driver);
+}
+
+module_init(init_usbduxfast);
+module_exit(exit_usbduxfast);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/interrupt.h b/drivers/staging/comedi/interrupt.h
new file mode 100644
index 000000000000..3038e461948a
--- /dev/null
+++ b/drivers/staging/comedi/interrupt.h
@@ -0,0 +1,60 @@
+/*
+ linux/interrupt.h compatibility header
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __COMPAT_LINUX_INTERRUPT_H_
+#define __COMPAT_LINUX_INTERRUPT_H_
+
+#include <linux/interrupt.h>
+
+#include <linux/version.h>
+
+#ifndef IRQ_NONE
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#define IRQ_RETVAL(x) (void)(x)
+#endif
+
+#ifndef IRQF_DISABLED
+#define IRQF_DISABLED SA_INTERRUPT
+#define IRQF_SAMPLE_RANDOM SA_SAMPLE_RANDOM
+#define IRQF_SHARED SA_SHIRQ
+#define IRQF_PROBE_SHARED SA_PROBEIRQ
+#define IRQF_PERCPU SA_PERCPU
+#ifdef SA_TRIGGER_MASK
+#define IRQF_TRIGGER_NONE 0
+#define IRQF_TRIGGER_LOW SA_TRIGGER_LOW
+#define IRQF_TRIGGER_HIGH SA_TRIGGER_HIGH
+#define IRQF_TRIGGER_FALLING SA_TRIGGER_FALLING
+#define IRQF_TRIGGER_RISING SA_TRIGGER_RISING
+#define IRQF_TRIGGER_MASK SA_TRIGGER_MASK
+#else
+#define IRQF_TRIGGER_NONE 0
+#define IRQF_TRIGGER_LOW 0
+#define IRQF_TRIGGER_HIGH 0
+#define IRQF_TRIGGER_FALLING 0
+#define IRQF_TRIGGER_RISING 0
+#define IRQF_TRIGGER_MASK 0
+#endif
+#endif
+
+#define PT_REGS_ARG
+#define PT_REGS_CALL
+#define PT_REGS_NULL
+
+#endif
diff --git a/drivers/staging/comedi/kcomedilib/Makefile b/drivers/staging/comedi/kcomedilib/Makefile
new file mode 100644
index 000000000000..ffcc9ad32adb
--- /dev/null
+++ b/drivers/staging/comedi/kcomedilib/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_COMEDI) += kcomedilib.o
+
+kcomedilib-objs := \
+ data.o \
+ ksyms.o \
+ dio.o \
+ kcomedilib_main.o \
+ get.o
diff --git a/drivers/staging/comedi/kcomedilib/data.c b/drivers/staging/comedi/kcomedilib/data.c
new file mode 100644
index 000000000000..79aec2041150
--- /dev/null
+++ b/drivers/staging/comedi/kcomedilib/data.c
@@ -0,0 +1,89 @@
+/*
+ kcomedilib/data.c
+ implements comedi_data_*() functions
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "../comedi.h"
+#include "../comedilib.h"
+#include "../comedidev.h" /* for comedi_udelay() */
+
+#include <linux/string.h>
+
+int comedi_data_write(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ unsigned int range, unsigned int aref, lsampl_t data)
+{
+ comedi_insn insn;
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_WRITE;
+ insn.n = 1;
+ insn.data = &data;
+ insn.subdev = subdev;
+ insn.chanspec = CR_PACK(chan, range, aref);
+
+ return comedi_do_insn(dev, &insn);
+}
+
+int comedi_data_read(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ unsigned int range, unsigned int aref, lsampl_t * data)
+{
+ comedi_insn insn;
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_READ;
+ insn.n = 1;
+ insn.data = data;
+ insn.subdev = subdev;
+ insn.chanspec = CR_PACK(chan, range, aref);
+
+ return comedi_do_insn(dev, &insn);
+}
+
+int comedi_data_read_hint(comedi_t * dev, unsigned int subdev,
+ unsigned int chan, unsigned int range, unsigned int aref)
+{
+ comedi_insn insn;
+ lsampl_t dummy_data;
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_READ;
+ insn.n = 0;
+ insn.data = &dummy_data;
+ insn.subdev = subdev;
+ insn.chanspec = CR_PACK(chan, range, aref);
+
+ return comedi_do_insn(dev, &insn);
+}
+
+int comedi_data_read_delayed(comedi_t * dev, unsigned int subdev,
+ unsigned int chan, unsigned int range, unsigned int aref,
+ lsampl_t * data, unsigned int nano_sec)
+{
+ int retval;
+
+ retval = comedi_data_read_hint(dev, subdev, chan, range, aref);
+ if (retval < 0)
+ return retval;
+
+ comedi_udelay((nano_sec + 999) / 1000);
+
+ return comedi_data_read(dev, subdev, chan, range, aref, data);
+}
diff --git a/drivers/staging/comedi/kcomedilib/dio.c b/drivers/staging/comedi/kcomedilib/dio.c
new file mode 100644
index 000000000000..a9f488aed369
--- /dev/null
+++ b/drivers/staging/comedi/kcomedilib/dio.c
@@ -0,0 +1,95 @@
+/*
+ kcomedilib/dio.c
+ implements comedi_dio_*() functions
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "../comedi.h"
+#include "../comedilib.h"
+
+#include <linux/string.h>
+
+int comedi_dio_config(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ unsigned int io)
+{
+ comedi_insn insn;
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_CONFIG;
+ insn.n = 1;
+ insn.data = &io;
+ insn.subdev = subdev;
+ insn.chanspec = CR_PACK(chan, 0, 0);
+
+ return comedi_do_insn(dev, &insn);
+}
+
+int comedi_dio_read(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ unsigned int *val)
+{
+ comedi_insn insn;
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_READ;
+ insn.n = 1;
+ insn.data = val;
+ insn.subdev = subdev;
+ insn.chanspec = CR_PACK(chan, 0, 0);
+
+ return comedi_do_insn(dev, &insn);
+}
+
+int comedi_dio_write(comedi_t * dev, unsigned int subdev, unsigned int chan,
+ unsigned int val)
+{
+ comedi_insn insn;
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_WRITE;
+ insn.n = 1;
+ insn.data = &val;
+ insn.subdev = subdev;
+ insn.chanspec = CR_PACK(chan, 0, 0);
+
+ return comedi_do_insn(dev, &insn);
+}
+
+int comedi_dio_bitfield(comedi_t * dev, unsigned int subdev, unsigned int mask,
+ unsigned int *bits)
+{
+ comedi_insn insn;
+ lsampl_t data[2];
+ int ret;
+
+ memset(&insn, 0, sizeof(insn));
+ insn.insn = INSN_BITS;
+ insn.n = 2;
+ insn.data = data;
+ insn.subdev = subdev;
+
+ data[0] = mask;
+ data[1] = *bits;
+
+ ret = comedi_do_insn(dev, &insn);
+
+ *bits = data[1];
+
+ return ret;
+}
diff --git a/drivers/staging/comedi/kcomedilib/get.c b/drivers/staging/comedi/kcomedilib/get.c
new file mode 100644
index 000000000000..2004ad4480c0
--- /dev/null
+++ b/drivers/staging/comedi/kcomedilib/get.c
@@ -0,0 +1,294 @@
+/*
+ kcomedilib/get.c
+ a comedlib interface for kernel modules
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define __NO_VERSION__
+#include "../comedi.h"
+#include "../comedilib.h"
+#include "../comedidev.h"
+
+int comedi_get_n_subdevices(comedi_t * d)
+{
+ comedi_device *dev = (comedi_device *) d;
+
+ return dev->n_subdevices;
+}
+
+int comedi_get_version_code(comedi_t * d)
+{
+ return COMEDI_VERSION_CODE;
+}
+
+const char *comedi_get_driver_name(comedi_t * d)
+{
+ comedi_device *dev = (comedi_device *) d;
+
+ return dev->driver->driver_name;
+}
+
+const char *comedi_get_board_name(comedi_t * d)
+{
+ comedi_device *dev = (comedi_device *) d;
+
+ return dev->board_name;
+}
+
+int comedi_get_subdevice_type(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+
+ return s->type;
+}
+
+unsigned int comedi_get_subdevice_flags(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+
+ return s->subdev_flags;
+}
+
+int comedi_find_subdevice_by_type(comedi_t * d, int type, unsigned int subd)
+{
+ comedi_device *dev = (comedi_device *) d;
+
+ if (subd > dev->n_subdevices)
+ return -ENODEV;
+
+ for (; subd < dev->n_subdevices; subd++) {
+ if (dev->subdevices[subd].type == type)
+ return subd;
+ }
+ return -1;
+}
+
+int comedi_get_n_channels(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+
+ return s->n_chan;
+}
+
+int comedi_get_len_chanlist(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+
+ return s->len_chanlist;
+}
+
+lsampl_t comedi_get_maxdata(comedi_t * d, unsigned int subdevice,
+ unsigned int chan)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+
+ if (s->maxdata_list)
+ return s->maxdata_list[chan];
+
+ return s->maxdata;
+}
+
+#ifdef KCOMEDILIB_DEPRECATED
+int comedi_get_rangetype(comedi_t * d, unsigned int subdevice,
+ unsigned int chan)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ int ret;
+
+ if (s->range_table_list) {
+ ret = s->range_table_list[chan]->length;
+ } else {
+ ret = s->range_table->length;
+ }
+
+ ret = ret | (dev->minor << 28) | (subdevice << 24) | (chan << 16);
+
+ return ret;
+}
+#endif
+
+int comedi_get_n_ranges(comedi_t * d, unsigned int subdevice, unsigned int chan)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ int ret;
+
+ if (s->range_table_list) {
+ ret = s->range_table_list[chan]->length;
+ } else {
+ ret = s->range_table->length;
+ }
+
+ return ret;
+}
+
+/*
+ * ALPHA (non-portable)
+*/
+int comedi_get_krange(comedi_t * d, unsigned int subdevice, unsigned int chan,
+ unsigned int range, comedi_krange * krange)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ const comedi_lrange *lr;
+
+ if (s->range_table_list) {
+ lr = s->range_table_list[chan];
+ } else {
+ lr = s->range_table;
+ }
+ if (range >= lr->length) {
+ return -EINVAL;
+ }
+ memcpy(krange, lr->range + range, sizeof(comedi_krange));
+
+ return 0;
+}
+
+/*
+ * ALPHA (may be renamed)
+*/
+unsigned int comedi_get_buf_head_pos(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ comedi_async *async;
+
+ async = s->async;
+ if (async == NULL)
+ return 0;
+
+ return async->buf_write_count;
+}
+
+int comedi_get_buffer_contents(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ comedi_async *async;
+ unsigned int num_bytes;
+
+ if (subdevice >= dev->n_subdevices)
+ return -1;
+ async = s->async;
+ if (async == NULL)
+ return 0;
+ num_bytes = comedi_buf_read_n_available(s->async);
+ return num_bytes;
+}
+
+/*
+ * ALPHA
+*/
+int comedi_set_user_int_count(comedi_t * d, unsigned int subdevice,
+ unsigned int buf_user_count)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ comedi_async *async;
+ int num_bytes;
+
+ async = s->async;
+ if (async == NULL)
+ return -1;
+
+ num_bytes = buf_user_count - async->buf_read_count;
+ if (num_bytes < 0)
+ return -1;
+ comedi_buf_read_alloc(async, num_bytes);
+ comedi_buf_read_free(async, num_bytes);
+
+ return 0;
+}
+
+int comedi_mark_buffer_read(comedi_t * d, unsigned int subdevice,
+ unsigned int num_bytes)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ comedi_async *async;
+
+ if (subdevice >= dev->n_subdevices)
+ return -1;
+ async = s->async;
+ if (async == NULL)
+ return -1;
+
+ comedi_buf_read_alloc(async, num_bytes);
+ comedi_buf_read_free(async, num_bytes);
+
+ return 0;
+}
+
+int comedi_mark_buffer_written(comedi_t * d, unsigned int subdevice,
+ unsigned int num_bytes)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ comedi_async *async;
+ int bytes_written;
+
+ if (subdevice >= dev->n_subdevices)
+ return -1;
+ async = s->async;
+ if (async == NULL)
+ return -1;
+ bytes_written = comedi_buf_write_alloc(async, num_bytes);
+ comedi_buf_write_free(async, bytes_written);
+ if (bytes_written != num_bytes)
+ return -1;
+ return 0;
+}
+
+int comedi_get_buffer_size(comedi_t * d, unsigned int subdev)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdev;
+ comedi_async *async;
+
+ if (subdev >= dev->n_subdevices)
+ return -1;
+ async = s->async;
+ if (async == NULL)
+ return 0;
+
+ return async->prealloc_bufsz;
+}
+
+int comedi_get_buffer_offset(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices + subdevice;
+ comedi_async *async;
+
+ if (subdevice >= dev->n_subdevices)
+ return -1;
+ async = s->async;
+ if (async == NULL)
+ return 0;
+
+ return async->buf_read_ptr;
+}
diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
new file mode 100644
index 000000000000..510fbdcec493
--- /dev/null
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -0,0 +1,567 @@
+/*
+ kcomedilib/kcomedilib.c
+ a comedlib interface for kernel modules
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define __NO_VERSION__
+#include <linux/module.h>
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#include "../comedi.h"
+#include "../comedilib.h"
+#include "../comedidev.h"
+
+MODULE_AUTHOR("David Schleef <ds@schleef.org>");
+MODULE_DESCRIPTION("Comedi kernel library");
+MODULE_LICENSE("GPL");
+
+comedi_t *comedi_open(const char *filename)
+{
+ struct comedi_device_file_info *dev_file_info;
+ comedi_device *dev;
+ unsigned int minor;
+
+ if (strncmp(filename, "/dev/comedi", 11) != 0)
+ return NULL;
+
+ minor = simple_strtoul(filename + 11, NULL, 0);
+
+ if (minor >= COMEDI_NUM_BOARD_MINORS)
+ return NULL;
+
+ dev_file_info = comedi_get_device_file_info(minor);
+ if(dev_file_info == NULL)
+ return NULL;
+ dev = dev_file_info->device;
+
+ if(dev == NULL || !dev->attached)
+ return NULL;
+
+ if (!try_module_get(dev->driver->module))
+ return NULL;
+
+ return (comedi_t *) dev;
+}
+
+comedi_t *comedi_open_old(unsigned int minor)
+{
+ struct comedi_device_file_info *dev_file_info;
+ comedi_device *dev;
+
+ if (minor >= COMEDI_NUM_MINORS)
+ return NULL;
+
+ dev_file_info = comedi_get_device_file_info(minor);
+ if(dev_file_info == NULL)
+ return NULL;
+ dev = dev_file_info->device;
+
+ if(dev == NULL || !dev->attached)
+ return NULL;
+
+ return (comedi_t *) dev;
+}
+
+int comedi_close(comedi_t * d)
+{
+ comedi_device *dev = (comedi_device *) d;
+
+ module_put(dev->driver->module);
+
+ return 0;
+}
+
+int comedi_loglevel(int newlevel)
+{
+ return 0;
+}
+
+void comedi_perror(const char *message)
+{
+ rt_printk("%s: unknown error\n", message);
+}
+
+char *comedi_strerror(int err)
+{
+ return "unknown error";
+}
+
+int comedi_fileno(comedi_t * d)
+{
+ comedi_device *dev = (comedi_device *) d;
+
+ /* return something random */
+ return dev->minor;
+}
+
+int comedi_command(comedi_t * d, comedi_cmd * cmd)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+ comedi_async *async;
+ unsigned runflags;
+
+ if (cmd->subdev >= dev->n_subdevices)
+ return -ENODEV;
+
+ s = dev->subdevices + cmd->subdev;
+ if (s->type == COMEDI_SUBD_UNUSED)
+ return -EIO;
+
+ async = s->async;
+ if (async == NULL)
+ return -ENODEV;
+
+ if (s->busy)
+ return -EBUSY;
+ s->busy = d;
+
+ if (async->cb_mask & COMEDI_CB_EOS)
+ cmd->flags |= TRIG_WAKE_EOS;
+
+ async->cmd = *cmd;
+
+ runflags = SRF_RUNNING;
+
+#ifdef CONFIG_COMEDI_RT
+ if (comedi_switch_to_rt(dev) == 0)
+ runflags |= SRF_RT;
+#endif
+ comedi_set_subdevice_runflags(s, ~0, runflags);
+
+ comedi_reset_async_buf(async);
+
+ return s->do_cmd(dev, s);
+}
+
+int comedi_command_test(comedi_t * d, comedi_cmd * cmd)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+
+ if (cmd->subdev >= dev->n_subdevices)
+ return -ENODEV;
+
+ s = dev->subdevices + cmd->subdev;
+ if (s->type == COMEDI_SUBD_UNUSED)
+ return -EIO;
+
+ if (s->async == NULL)
+ return -ENODEV;
+
+ return s->do_cmdtest(dev, s, cmd);
+}
+
+/*
+ * COMEDI_INSN
+ * perform an instruction
+ */
+int comedi_do_insn(comedi_t * d, comedi_insn * insn)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+ int ret = 0;
+
+ if (insn->insn & INSN_MASK_SPECIAL) {
+ switch (insn->insn) {
+ case INSN_GTOD:
+ {
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+ insn->data[0] = tv.tv_sec;
+ insn->data[1] = tv.tv_usec;
+ ret = 2;
+
+ break;
+ }
+ case INSN_WAIT:
+ /* XXX isn't the value supposed to be nanosecs? */
+ if (insn->n != 1 || insn->data[0] >= 100) {
+ ret = -EINVAL;
+ break;
+ }
+ comedi_udelay(insn->data[0]);
+ ret = 1;
+ break;
+ case INSN_INTTRIG:
+ if (insn->n != 1) {
+ ret = -EINVAL;
+ break;
+ }
+ if (insn->subdev >= dev->n_subdevices) {
+ rt_printk("%d not usable subdevice\n",
+ insn->subdev);
+ ret = -EINVAL;
+ break;
+ }
+ s = dev->subdevices + insn->subdev;
+ if (!s->async) {
+ rt_printk("no async\n");
+ ret = -EINVAL;
+ break;
+ }
+ if (!s->async->inttrig) {
+ rt_printk("no inttrig\n");
+ ret = -EAGAIN;
+ break;
+ }
+ ret = s->async->inttrig(dev, s, insn->data[0]);
+ if (ret >= 0)
+ ret = 1;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ } else {
+ /* a subdevice instruction */
+ if (insn->subdev >= dev->n_subdevices) {
+ ret = -EINVAL;
+ goto error;
+ }
+ s = dev->subdevices + insn->subdev;
+
+ if (s->type == COMEDI_SUBD_UNUSED) {
+ rt_printk("%d not useable subdevice\n", insn->subdev);
+ ret = -EIO;
+ goto error;
+ }
+
+ /* XXX check lock */
+
+ if ((ret = check_chanlist(s, 1, &insn->chanspec)) < 0) {
+ rt_printk("bad chanspec\n");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ if (s->busy) {
+ ret = -EBUSY;
+ goto error;
+ }
+ s->busy = d;
+
+ switch (insn->insn) {
+ case INSN_READ:
+ ret = s->insn_read(dev, s, insn, insn->data);
+ break;
+ case INSN_WRITE:
+ ret = s->insn_write(dev, s, insn, insn->data);
+ break;
+ case INSN_BITS:
+ ret = s->insn_bits(dev, s, insn, insn->data);
+ break;
+ case INSN_CONFIG:
+ /* XXX should check instruction length */
+ ret = s->insn_config(dev, s, insn, insn->data);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ s->busy = NULL;
+ }
+ if (ret < 0)
+ goto error;
+#if 0
+ /* XXX do we want this? -- abbotti #if'ed it out for now. */
+ if (ret != insn->n) {
+ rt_printk("BUG: result of insn != insn.n\n");
+ ret = -EINVAL;
+ goto error;
+ }
+#endif
+ error:
+
+ return ret;
+}
+
+/*
+ COMEDI_LOCK
+ lock subdevice
+
+ arg:
+ subdevice number
+
+ reads:
+ none
+
+ writes:
+ none
+
+ necessary locking:
+ - ioctl/rt lock (this type)
+ - lock while subdevice busy
+ - lock while subdevice being programmed
+
+*/
+int comedi_lock(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+ unsigned long flags;
+ int ret = 0;
+
+ if (subdevice >= dev->n_subdevices) {
+ return -EINVAL;
+ }
+ s = dev->subdevices + subdevice;
+
+ comedi_spin_lock_irqsave(&s->spin_lock, flags);
+
+ if (s->busy) {
+ ret = -EBUSY;
+ } else {
+ if (s->lock) {
+ ret = -EBUSY;
+ } else {
+ s->lock = d;
+ }
+ }
+
+ comedi_spin_unlock_irqrestore(&s->spin_lock, flags);
+
+ return ret;
+}
+
+/*
+ COMEDI_UNLOCK
+ unlock subdevice
+
+ arg:
+ subdevice number
+
+ reads:
+ none
+
+ writes:
+ none
+
+*/
+int comedi_unlock(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+ unsigned long flags;
+ comedi_async *async;
+ int ret;
+
+ if (subdevice >= dev->n_subdevices) {
+ return -EINVAL;
+ }
+ s = dev->subdevices + subdevice;
+
+ async = s->async;
+
+ comedi_spin_lock_irqsave(&s->spin_lock, flags);
+
+ if (s->busy) {
+ ret = -EBUSY;
+ } else if (s->lock && s->lock != (void *)d) {
+ ret = -EACCES;
+ } else {
+ s->lock = NULL;
+
+ if (async) {
+ async->cb_mask = 0;
+ async->cb_func = NULL;
+ async->cb_arg = NULL;
+ }
+
+ ret = 0;
+ }
+
+ comedi_spin_unlock_irqrestore(&s->spin_lock, flags);
+
+ return ret;
+}
+
+/*
+ COMEDI_CANCEL
+ cancel acquisition ioctl
+
+ arg:
+ subdevice number
+
+ reads:
+ nothing
+
+ writes:
+ nothing
+
+*/
+int comedi_cancel(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+ int ret = 0;
+
+ if (subdevice >= dev->n_subdevices) {
+ return -EINVAL;
+ }
+ s = dev->subdevices + subdevice;
+
+ if (s->lock && s->lock != d)
+ return -EACCES;
+
+#if 0
+ if (!s->busy)
+ return 0;
+
+ if (s->busy != d)
+ return -EBUSY;
+#endif
+
+ if (!s->cancel || !s->async)
+ return -EINVAL;
+
+ if ((ret = s->cancel(dev, s)))
+ return ret;
+
+#ifdef CONFIG_COMEDI_RT
+ if (comedi_get_subdevice_runflags(s) & SRF_RT) {
+ comedi_switch_to_non_rt(dev);
+ }
+#endif
+ comedi_set_subdevice_runflags(s, SRF_RUNNING | SRF_RT, 0);
+ s->async->inttrig = NULL;
+ s->busy = NULL;
+
+ return 0;
+}
+
+/*
+ registration of callback functions
+ */
+int comedi_register_callback(comedi_t * d, unsigned int subdevice,
+ unsigned int mask, int (*cb) (unsigned int, void *), void *arg)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+ comedi_async *async;
+
+ if (subdevice >= dev->n_subdevices) {
+ return -EINVAL;
+ }
+ s = dev->subdevices + subdevice;
+
+ async = s->async;
+ if (s->type == COMEDI_SUBD_UNUSED || !async)
+ return -EIO;
+
+ /* are we locked? (ioctl lock) */
+ if (s->lock && s->lock != d)
+ return -EACCES;
+
+ /* are we busy? */
+ if (s->busy)
+ return -EBUSY;
+
+ if (!mask) {
+ async->cb_mask = 0;
+ async->cb_func = NULL;
+ async->cb_arg = NULL;
+ } else {
+ async->cb_mask = mask;
+ async->cb_func = cb;
+ async->cb_arg = arg;
+ }
+
+ return 0;
+}
+
+int comedi_poll(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s = dev->subdevices;
+ comedi_async *async;
+
+ if (subdevice >= dev->n_subdevices) {
+ return -EINVAL;
+ }
+ s = dev->subdevices + subdevice;
+
+ async = s->async;
+ if (s->type == COMEDI_SUBD_UNUSED || !async)
+ return -EIO;
+
+ /* are we locked? (ioctl lock) */
+ if (s->lock && s->lock != d)
+ return -EACCES;
+
+ /* are we running? XXX wrong? */
+ if (!s->busy)
+ return -EIO;
+
+ return s->poll(dev, s);
+}
+
+/* WARNING: not portable */
+int comedi_map(comedi_t * d, unsigned int subdevice, void *ptr)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+
+ if (subdevice >= dev->n_subdevices) {
+ return -EINVAL;
+ }
+ s = dev->subdevices + subdevice;
+
+ if (!s->async)
+ return -EINVAL;
+
+ if (ptr) {
+ *((void **)ptr) = s->async->prealloc_buf;
+ }
+
+ /* XXX no reference counting */
+
+ return 0;
+}
+
+/* WARNING: not portable */
+int comedi_unmap(comedi_t * d, unsigned int subdevice)
+{
+ comedi_device *dev = (comedi_device *) d;
+ comedi_subdevice *s;
+
+ if (subdevice >= dev->n_subdevices) {
+ return -EINVAL;
+ }
+ s = dev->subdevices + subdevice;
+
+ if (!s->async)
+ return -EINVAL;
+
+ /* XXX no reference counting */
+
+ return 0;
+}
diff --git a/drivers/staging/comedi/kcomedilib/ksyms.c b/drivers/staging/comedi/kcomedilib/ksyms.c
new file mode 100644
index 000000000000..76b45063a9fc
--- /dev/null
+++ b/drivers/staging/comedi/kcomedilib/ksyms.c
@@ -0,0 +1,144 @@
+/*
+ comedi/kcomedilib/ksyms.c
+ a comedlib interface for kernel modules
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef EXPORT_SYMTAB
+#define EXPORT_SYMTAB
+#endif
+
+#include "../comedi.h"
+#include "../comedilib.h"
+#include "../comedidev.h"
+
+#include <linux/module.h>
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#if LINUX_VERSION_CODE >= 0x020200
+
+/* functions specific to kcomedilib */
+
+EXPORT_SYMBOL(comedi_register_callback);
+EXPORT_SYMBOL(comedi_get_krange);
+EXPORT_SYMBOL(comedi_get_buf_head_pos);
+EXPORT_SYMBOL(comedi_set_user_int_count);
+EXPORT_SYMBOL(comedi_map);
+EXPORT_SYMBOL(comedi_unmap);
+
+/* This list comes from user-space comedilib, to show which
+ * functions are not ported yet. */
+
+EXPORT_SYMBOL(comedi_open);
+EXPORT_SYMBOL(comedi_close);
+
+/* logging */
+EXPORT_SYMBOL(comedi_loglevel);
+EXPORT_SYMBOL(comedi_perror);
+EXPORT_SYMBOL(comedi_strerror);
+//EXPORT_SYMBOL(comedi_errno);
+EXPORT_SYMBOL(comedi_fileno);
+
+/* device queries */
+EXPORT_SYMBOL(comedi_get_n_subdevices);
+EXPORT_SYMBOL(comedi_get_version_code);
+EXPORT_SYMBOL(comedi_get_driver_name);
+EXPORT_SYMBOL(comedi_get_board_name);
+
+/* subdevice queries */
+EXPORT_SYMBOL(comedi_get_subdevice_type);
+EXPORT_SYMBOL(comedi_find_subdevice_by_type);
+EXPORT_SYMBOL(comedi_get_subdevice_flags);
+EXPORT_SYMBOL(comedi_get_n_channels);
+//EXPORT_SYMBOL(comedi_range_is_chan_specific);
+//EXPORT_SYMBOL(comedi_maxdata_is_chan_specific);
+
+/* channel queries */
+EXPORT_SYMBOL(comedi_get_maxdata);
+#ifdef KCOMEDILIB_DEPRECATED
+EXPORT_SYMBOL(comedi_get_rangetype);
+#endif
+EXPORT_SYMBOL(comedi_get_n_ranges);
+//EXPORT_SYMBOL(comedi_find_range);
+
+/* buffer queries */
+EXPORT_SYMBOL(comedi_get_buffer_size);
+//EXPORT_SYMBOL(comedi_get_max_buffer_size);
+//EXPORT_SYMBOL(comedi_set_buffer_size);
+EXPORT_SYMBOL(comedi_get_buffer_contents);
+EXPORT_SYMBOL(comedi_get_buffer_offset);
+
+/* low-level stuff */
+//EXPORT_SYMBOL(comedi_trigger);
+//EXPORT_SYMBOL(comedi_do_insnlist);
+EXPORT_SYMBOL(comedi_do_insn);
+EXPORT_SYMBOL(comedi_lock);
+EXPORT_SYMBOL(comedi_unlock);
+
+/* physical units */
+//EXPORT_SYMBOL(comedi_to_phys);
+//EXPORT_SYMBOL(comedi_from_phys);
+
+/* synchronous stuff */
+EXPORT_SYMBOL(comedi_data_read);
+EXPORT_SYMBOL(comedi_data_read_hint);
+EXPORT_SYMBOL(comedi_data_read_delayed);
+EXPORT_SYMBOL(comedi_data_write);
+EXPORT_SYMBOL(comedi_dio_config);
+EXPORT_SYMBOL(comedi_dio_read);
+EXPORT_SYMBOL(comedi_dio_write);
+EXPORT_SYMBOL(comedi_dio_bitfield);
+
+/* slowly varying stuff */
+//EXPORT_SYMBOL(comedi_sv_init);
+//EXPORT_SYMBOL(comedi_sv_update);
+//EXPORT_SYMBOL(comedi_sv_measure);
+
+/* commands */
+//EXPORT_SYMBOL(comedi_get_cmd_src_mask);
+//EXPORT_SYMBOL(comedi_get_cmd_generic_timed);
+EXPORT_SYMBOL(comedi_cancel);
+EXPORT_SYMBOL(comedi_command);
+EXPORT_SYMBOL(comedi_command_test);
+EXPORT_SYMBOL(comedi_poll);
+
+/* buffer configuration */
+EXPORT_SYMBOL(comedi_mark_buffer_read);
+EXPORT_SYMBOL(comedi_mark_buffer_written);
+
+//EXPORT_SYMBOL(comedi_get_range);
+EXPORT_SYMBOL(comedi_get_len_chanlist);
+
+/* deprecated */
+//EXPORT_SYMBOL(comedi_get_timer);
+//EXPORT_SYMBOL(comedi_timed_1chan);
+
+/* alpha */
+//EXPORT_SYMBOL(comedi_set_global_oor_behavior);
+
+#endif
diff --git a/drivers/staging/comedi/pci_ids.h b/drivers/staging/comedi/pci_ids.h
new file mode 100644
index 000000000000..c61ba90f9601
--- /dev/null
+++ b/drivers/staging/comedi/pci_ids.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ * *
+ * 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 __COMPAT_LINUX_PCI_IDS_H
+#define __COMPAT_LINUX_PCI_IDS_H
+
+#include <linux/pci_ids.h>
+
+#ifndef PCI_VENDOR_ID_AMCC
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#endif
+
+#ifndef PCI_VENDOR_ID_CBOARDS
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#endif
+
+#ifndef PCI_VENDOR_ID_QUANCOM
+#define PCI_VENDOR_ID_QUANCOM 0x8008
+#endif
+
+#ifndef PCI_DEVICE_ID_QUANCOM_GPIB
+#define PCI_DEVICE_ID_QUANCOM_GPIB 0x3302
+#endif
+
+#endif // __COMPAT_LINUX_PCI_IDS_H
diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c
new file mode 100644
index 000000000000..5a2b72d87572
--- /dev/null
+++ b/drivers/staging/comedi/proc.c
@@ -0,0 +1,102 @@
+/*
+ module/proc.c
+ /proc interface for comedi
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1998 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/*
+ This is some serious bloatware.
+
+ Taken from Dave A.'s PCL-711 driver, 'cuz I thought it
+ was cool.
+*/
+
+#define __NO_VERSION__
+#include "comedidev.h"
+#include <linux/proc_fs.h>
+//#include <linux/string.h>
+
+int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ int *eof, void *data);
+
+extern comedi_driver *comedi_drivers;
+
+int comedi_read_procmem(char *buf, char **start, off_t offset, int len,
+ int *eof, void *data)
+{
+ int i;
+ int devices_q = 0;
+ int l = 0;
+ comedi_driver *driv;
+
+ l += sprintf(buf + l,
+ "comedi version " COMEDI_RELEASE "\n"
+ "format string: %s\n",
+ "\"%2d: %-20s %-20s %4d\",i,driver_name,board_name,n_subdevices");
+
+ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+ struct comedi_device_file_info *dev_file_info = comedi_get_device_file_info(i);
+ comedi_device *dev;
+
+ if(dev_file_info == NULL) continue;
+ dev = dev_file_info->device;
+
+ if (dev->attached) {
+ devices_q = 1;
+ l += sprintf(buf + l, "%2d: %-20s %-20s %4d\n",
+ i,
+ dev->driver->driver_name,
+ dev->board_name, dev->n_subdevices);
+ }
+ }
+ if (!devices_q) {
+ l += sprintf(buf + l, "no devices\n");
+ }
+
+ for (driv = comedi_drivers; driv; driv = driv->next) {
+ l += sprintf(buf + l, "%s:\n", driv->driver_name);
+ for (i = 0; i < driv->num_names; i++) {
+ l += sprintf(buf + l, " %s\n",
+ *(char **)((char *)driv->board_name +
+ i * driv->offset));
+ }
+ if (!driv->num_names) {
+ l += sprintf(buf + l, " %s\n", driv->driver_name);
+ }
+ }
+
+ return l;
+}
+
+#ifdef CONFIG_PROC_FS
+void comedi_proc_init(void)
+{
+ struct proc_dir_entry *comedi_proc;
+
+ comedi_proc = create_proc_entry("comedi", S_IFREG | S_IRUGO, 0);
+ if (comedi_proc)
+ comedi_proc->read_proc = comedi_read_procmem;
+}
+
+void comedi_proc_cleanup(void)
+{
+ remove_proc_entry("comedi", 0);
+}
+#endif
diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
new file mode 100644
index 000000000000..61dc3cd6a9fd
--- /dev/null
+++ b/drivers/staging/comedi/range.c
@@ -0,0 +1,161 @@
+/*
+ module/range.c
+ comedi routines for voltage ranges
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "comedidev.h"
+#include <asm/uaccess.h>
+
+const comedi_lrange range_bipolar10 = { 1, {BIP_RANGE(10)} };
+const comedi_lrange range_bipolar5 = { 1, {BIP_RANGE(5)} };
+const comedi_lrange range_bipolar2_5 = { 1, {BIP_RANGE(2.5)} };
+const comedi_lrange range_unipolar10 = { 1, {UNI_RANGE(10)} };
+const comedi_lrange range_unipolar5 = { 1, {UNI_RANGE(5)} };
+const comedi_lrange range_unknown = { 1, {{0, 1000000, UNIT_none}} };
+
+/*
+ COMEDI_RANGEINFO
+ range information ioctl
+
+ arg:
+ pointer to rangeinfo structure
+
+ reads:
+ range info structure
+
+ writes:
+ n comedi_krange structures to rangeinfo->range_ptr
+*/
+int do_rangeinfo_ioctl(comedi_device * dev, comedi_rangeinfo * arg)
+{
+ comedi_rangeinfo it;
+ int subd, chan;
+ const comedi_lrange *lr;
+ comedi_subdevice *s;
+
+ if (copy_from_user(&it, arg, sizeof(comedi_rangeinfo)))
+ return -EFAULT;
+ subd = (it.range_type >> 24) & 0xf;
+ chan = (it.range_type >> 16) & 0xff;
+
+ if (!dev->attached)
+ return -EINVAL;
+ if (subd >= dev->n_subdevices)
+ return -EINVAL;
+ s = dev->subdevices + subd;
+ if (s->range_table) {
+ lr = s->range_table;
+ } else if (s->range_table_list) {
+ if (chan >= s->n_chan)
+ return -EINVAL;
+ lr = s->range_table_list[chan];
+ } else {
+ return -EINVAL;
+ }
+
+ if (RANGE_LENGTH(it.range_type) != lr->length) {
+ DPRINTK("wrong length %d should be %d (0x%08x)\n",
+ RANGE_LENGTH(it.range_type), lr->length, it.range_type);
+ return -EINVAL;
+ }
+
+ if (copy_to_user(it.range_ptr, lr->range,
+ sizeof(comedi_krange) * lr->length))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int aref_invalid(comedi_subdevice * s, unsigned int chanspec)
+{
+ unsigned int aref;
+
+ // disable reporting invalid arefs... maybe someday
+ return 0;
+
+ aref = CR_AREF(chanspec);
+ switch (aref) {
+ case AREF_DIFF:
+ if (s->subdev_flags & SDF_DIFF)
+ return 0;
+ break;
+ case AREF_COMMON:
+ if (s->subdev_flags & SDF_COMMON)
+ return 0;
+ break;
+ case AREF_GROUND:
+ if (s->subdev_flags & SDF_GROUND)
+ return 0;
+ break;
+ case AREF_OTHER:
+ if (s->subdev_flags & SDF_OTHER)
+ return 0;
+ break;
+ default:
+ break;
+ }
+ DPRINTK("subdevice does not support aref %i", aref);
+ return 1;
+}
+
+/*
+ This function checks each element in a channel/gain list to make
+ make sure it is valid.
+*/
+int check_chanlist(comedi_subdevice * s, int n, unsigned int *chanlist)
+{
+ int i;
+ int chan;
+
+ if (s->range_table) {
+ for (i = 0; i < n; i++)
+ if (CR_CHAN(chanlist[i]) >= s->n_chan ||
+ CR_RANGE(chanlist[i]) >= s->range_table->length
+ || aref_invalid(s, chanlist[i])) {
+ rt_printk
+ ("bad chanlist[%d]=0x%08x n_chan=%d range length=%d\n",
+ i, chanlist[i], s->n_chan,
+ s->range_table->length);
+#if 0
+ for (i = 0; i < n; i++) {
+ printk("[%d]=0x%08x\n", i, chanlist[i]);
+ }
+#endif
+ return -EINVAL;
+ }
+ } else if (s->range_table_list) {
+ for (i = 0; i < n; i++) {
+ chan = CR_CHAN(chanlist[i]);
+ if (chan >= s->n_chan ||
+ CR_RANGE(chanlist[i]) >=
+ s->range_table_list[chan]->length
+ || aref_invalid(s, chanlist[i])) {
+ rt_printk("bad chanlist[%d]=0x%08x\n", i,
+ chanlist[i]);
+ return -EINVAL;
+ }
+ }
+ } else {
+ rt_printk("comedi: (bug) no range type list!\n");
+ return -EINVAL;
+ }
+ return 0;
+}
diff --git a/drivers/staging/comedi/rt.c b/drivers/staging/comedi/rt.c
new file mode 100644
index 000000000000..385b81b94ac5
--- /dev/null
+++ b/drivers/staging/comedi/rt.c
@@ -0,0 +1,412 @@
+/*
+ comedi/rt.c
+ comedi kernel module
+
+ COMEDI - Linux Control and Measurement Device Interface
+ Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#undef DEBUG
+
+#define __NO_VERSION__
+#include <linux/comedidev.h>
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#include "rt_pend_tq.h"
+
+#ifdef CONFIG_COMEDI_RTAI
+#include <rtai.h>
+#endif
+
+#ifdef CONFIG_COMEDI_FUSION
+#include <nucleus/asm/hal.h>
+#endif
+
+#ifdef CONFIG_COMEDI_RTL
+#include <rtl_core.h>
+#include <rtl_sync.h>
+#endif
+
+struct comedi_irq_struct {
+ int rt;
+ int irq;
+ irqreturn_t(*handler) (int irq, void *dev_id PT_REGS_ARG);
+ unsigned long flags;
+ const char *device;
+ comedi_device *dev_id;
+};
+
+static int comedi_rt_get_irq(struct comedi_irq_struct *it);
+static int comedi_rt_release_irq(struct comedi_irq_struct *it);
+
+static struct comedi_irq_struct *comedi_irqs[NR_IRQS];
+
+int comedi_request_irq(unsigned irq, irqreturn_t(*handler) (int,
+ void *PT_REGS_ARG), unsigned long flags, const char *device,
+ comedi_device * dev_id)
+{
+ struct comedi_irq_struct *it;
+ int ret;
+ /* null shared interrupt flag, since rt interrupt handlers do not
+ * support it, and this version of comedi_request_irq() is only
+ * called for kernels with rt support */
+ unsigned long unshared_flags = flags & ~IRQF_SHARED;
+
+ ret = request_irq(irq, handler, unshared_flags, device, dev_id);
+ if (ret < 0) {
+ // we failed, so fall back on allowing shared interrupt (which we won't ever make RT)
+ if (flags & IRQF_SHARED) {
+ rt_printk
+ ("comedi: cannot get unshared interrupt, will not use RT interrupts.\n");
+ ret = request_irq(irq, handler, flags, device, dev_id);
+ }
+ if (ret < 0) {
+ return ret;
+ }
+ } else {
+ it = kzalloc(sizeof(struct comedi_irq_struct), GFP_KERNEL);
+ if (!it)
+ return -ENOMEM;
+
+ it->handler = handler;
+ it->irq = irq;
+ it->dev_id = dev_id;
+ it->device = device;
+ it->flags = unshared_flags;
+ comedi_irqs[irq] = it;
+ }
+ return 0;
+}
+
+void comedi_free_irq(unsigned int irq, comedi_device * dev_id)
+{
+ struct comedi_irq_struct *it;
+
+ free_irq(irq, dev_id);
+
+ it = comedi_irqs[irq];
+ if (it == NULL)
+ return;
+
+ if (it->rt) {
+ printk("real-time IRQ allocated at board removal (ignore)\n");
+ comedi_rt_release_irq(it);
+ }
+
+ kfree(it);
+ comedi_irqs[irq] = NULL;
+}
+
+int comedi_switch_to_rt(comedi_device * dev)
+{
+ struct comedi_irq_struct *it;
+ unsigned long flags;
+
+ it = comedi_irqs[dev->irq];
+ /* drivers might not be using an interrupt for commands,
+ or we might not have been able to get an unshared irq */
+ if (it == NULL)
+ return -1;
+
+ comedi_spin_lock_irqsave(&dev->spinlock, flags);
+
+ if (!dev->rt)
+ comedi_rt_get_irq(it);
+
+ dev->rt++;
+ it->rt = 1;
+
+ comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+
+ return 0;
+}
+
+void comedi_switch_to_non_rt(comedi_device * dev)
+{
+ struct comedi_irq_struct *it;
+ unsigned long flags;
+
+ it = comedi_irqs[dev->irq];
+ if (it == NULL)
+ return;
+
+ comedi_spin_lock_irqsave(&dev->spinlock, flags);
+
+ dev->rt--;
+ if (!dev->rt)
+ comedi_rt_release_irq(it);
+
+ it->rt = 0;
+
+ comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
+}
+
+void wake_up_int_handler(int arg1, void *arg2)
+{
+ wake_up_interruptible((wait_queue_head_t *) arg2);
+}
+
+void comedi_rt_pend_wakeup(wait_queue_head_t * q)
+{
+ rt_pend_call(wake_up_int_handler, 0, q);
+}
+
+/* RTAI section */
+#ifdef CONFIG_COMEDI_RTAI
+
+#ifndef HAVE_RT_REQUEST_IRQ_WITH_ARG
+#define DECLARE_VOID_IRQ(irq) \
+static void handle_void_irq_ ## irq (void){ handle_void_irq(irq);}
+
+static void handle_void_irq(int irq)
+{
+ struct comedi_irq_struct *it;
+
+ it = comedi_irqs[irq];
+ if (it == NULL) {
+ rt_printk("comedi: null irq struct?\n");
+ return;
+ }
+ it->handler(irq, it->dev_id PT_REGS_NULL);
+ rt_enable_irq(irq); //needed by rtai-adeos, seems like it shouldn't hurt earlier versions
+}
+
+DECLARE_VOID_IRQ(0);
+DECLARE_VOID_IRQ(1);
+DECLARE_VOID_IRQ(2);
+DECLARE_VOID_IRQ(3);
+DECLARE_VOID_IRQ(4);
+DECLARE_VOID_IRQ(5);
+DECLARE_VOID_IRQ(6);
+DECLARE_VOID_IRQ(7);
+DECLARE_VOID_IRQ(8);
+DECLARE_VOID_IRQ(9);
+DECLARE_VOID_IRQ(10);
+DECLARE_VOID_IRQ(11);
+DECLARE_VOID_IRQ(12);
+DECLARE_VOID_IRQ(13);
+DECLARE_VOID_IRQ(14);
+DECLARE_VOID_IRQ(15);
+DECLARE_VOID_IRQ(16);
+DECLARE_VOID_IRQ(17);
+DECLARE_VOID_IRQ(18);
+DECLARE_VOID_IRQ(19);
+DECLARE_VOID_IRQ(20);
+DECLARE_VOID_IRQ(21);
+DECLARE_VOID_IRQ(22);
+DECLARE_VOID_IRQ(23);
+
+typedef void (*V_FP_V) (void);
+static V_FP_V handle_void_irq_ptrs[] = {
+ handle_void_irq_0,
+ handle_void_irq_1,
+ handle_void_irq_2,
+ handle_void_irq_3,
+ handle_void_irq_4,
+ handle_void_irq_5,
+ handle_void_irq_6,
+ handle_void_irq_7,
+ handle_void_irq_8,
+ handle_void_irq_9,
+ handle_void_irq_10,
+ handle_void_irq_11,
+ handle_void_irq_12,
+ handle_void_irq_13,
+ handle_void_irq_14,
+ handle_void_irq_15,
+ handle_void_irq_16,
+ handle_void_irq_17,
+ handle_void_irq_18,
+ handle_void_irq_19,
+ handle_void_irq_20,
+ handle_void_irq_21,
+ handle_void_irq_22,
+ handle_void_irq_23,
+};
+
+static int comedi_rt_get_irq(struct comedi_irq_struct *it)
+{
+ rt_request_global_irq(it->irq, handle_void_irq_ptrs[it->irq]);
+ rt_startup_irq(it->irq);
+
+ return 0;
+}
+
+static int comedi_rt_release_irq(struct comedi_irq_struct *it)
+{
+ rt_shutdown_irq(it->irq);
+ rt_free_global_irq(it->irq);
+ return 0;
+}
+#else
+
+static int comedi_rt_get_irq(struct comedi_irq_struct *it)
+{
+ int ret;
+
+ ret = rt_request_global_irq_arg(it->irq, it->handler, it->flags,
+ it->device, it->dev_id);
+ if (ret < 0) {
+ rt_printk("rt_request_global_irq_arg() returned %d\n", ret);
+ return ret;
+ }
+ rt_startup_irq(it->irq);
+
+ return 0;
+}
+
+static int comedi_rt_release_irq(struct comedi_irq_struct *it)
+{
+ rt_shutdown_irq(it->irq);
+ rt_free_global_irq(it->irq);
+ return 0;
+}
+#endif
+
+void comedi_rt_init(void)
+{
+ rt_mount_rtai();
+ rt_pend_tq_init();
+}
+
+void comedi_rt_cleanup(void)
+{
+ rt_umount_rtai();
+ rt_pend_tq_cleanup();
+}
+
+#endif
+
+/* Fusion section */
+#ifdef CONFIG_COMEDI_FUSION
+
+static void fusion_handle_irq(unsigned int irq, void *cookie)
+{
+ struct comedi_irq_struct *it = cookie;
+
+ it->handler(irq, it->dev_id PT_REGS_NULL);
+ rthal_irq_enable(irq);
+}
+
+static int comedi_rt_get_irq(struct comedi_irq_struct *it)
+{
+ rthal_irq_request(it->irq, fusion_handle_irq, it);
+ rthal_irq_enable(it->irq);
+ return 0;
+}
+
+static int comedi_rt_release_irq(struct comedi_irq_struct *it)
+{
+ rthal_irq_disable(it->irq);
+ rthal_irq_release(it->irq);
+ return 0;
+}
+
+void comedi_rt_init(void)
+{
+ rt_pend_tq_init();
+}
+
+void comedi_rt_cleanup(void)
+{
+ rt_pend_tq_cleanup();
+}
+
+#endif /*CONFIG_COMEDI_FUSION */
+
+/* RTLinux section */
+#ifdef CONFIG_COMEDI_RTL
+
+static unsigned int handle_rtl_irq(unsigned int irq PT_REGS_ARG)
+{
+ struct comedi_irq_struct *it;
+
+ it = comedi_irqs[irq];
+ if (it == NULL)
+ return 0;
+ it->handler(irq, it->dev_id PT_REGS_NULL);
+ rtl_hard_enable_irq(irq);
+ return 0;
+}
+
+static int comedi_rt_get_irq(struct comedi_irq_struct *it)
+{
+ rtl_request_global_irq(it->irq, handle_rtl_irq);
+ return 0;
+}
+
+static int comedi_rt_release_irq(struct comedi_irq_struct *it)
+{
+ rtl_free_global_irq(it->irq);
+ return 0;
+}
+
+void comedi_rt_init(void)
+{
+ rt_pend_tq_init();
+}
+
+void comedi_rt_cleanup(void)
+{
+ rt_pend_tq_cleanup();
+}
+
+#endif
+
+#ifdef CONFIG_COMEDI_PIRQ
+static int comedi_rt_get_irq(struct comedi_irq_struct *it)
+{
+ int ret;
+
+ free_irq(it->irq, it->dev_id);
+ ret = request_irq(it->irq, it->handler, it->flags | SA_PRIORITY,
+ it->device, it->dev_id);
+
+ return ret;
+}
+
+static int comedi_rt_release_irq(struct comedi_irq_struct *it)
+{
+ int ret;
+
+ free_irq(it->irq, it->dev_id);
+ ret = request_irq(it->irq, it->handler, it->flags,
+ it->device, it->dev_id);
+
+ return ret;
+}
+
+void comedi_rt_init(void)
+{
+ //rt_pend_tq_init();
+}
+
+void comedi_rt_cleanup(void)
+{
+ //rt_pend_tq_cleanup();
+}
+#endif
diff --git a/drivers/staging/comedi/rt_pend_tq.c b/drivers/staging/comedi/rt_pend_tq.c
new file mode 100644
index 000000000000..995f076e0af3
--- /dev/null
+++ b/drivers/staging/comedi/rt_pend_tq.c
@@ -0,0 +1,113 @@
+#define __NO_VERSION__
+/* rt_pend_tq.c */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include "comedidev.h" // for rt spinlocks
+#include "rt_pend_tq.h"
+#ifdef CONFIG_COMEDI_RTAI
+#include <rtai.h>
+#endif
+#ifdef CONFIG_COMEDI_FUSION
+#include <nucleus/asm/hal.h>
+#endif
+#ifdef CONFIG_COMEDI_RTL
+#include <rtl_core.h>
+#endif
+
+#ifdef standalone
+#include <linux/module.h>
+#define rt_pend_tq_init init_module
+#define rt_pend_tq_cleanup cleanup_module
+#endif
+
+volatile static struct rt_pend_tq rt_pend_tq[RT_PEND_TQ_SIZE];
+volatile static struct rt_pend_tq *volatile rt_pend_head = rt_pend_tq,
+ *volatile rt_pend_tail = rt_pend_tq;
+int rt_pend_tq_irq = 0;
+spinlock_t rt_pend_tq_lock = SPIN_LOCK_UNLOCKED;
+
+// WARNING: following code not checked against race conditions yet.
+#define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0)
+#define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0)
+
+int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2)
+{
+ unsigned long flags;
+
+ if (func == NULL)
+ return -EINVAL;
+ if (rt_pend_tq_irq <= 0)
+ return -ENODEV;
+ comedi_spin_lock_irqsave(&rt_pend_tq_lock, flags);
+ INC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE);
+ if (rt_pend_head == rt_pend_tail) {
+ // overflow, we just refuse to take this request
+ DEC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE);
+ comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags);
+ return -EAGAIN;
+ }
+ rt_pend_head->func = func;
+ rt_pend_head->arg1 = arg1;
+ rt_pend_head->arg2 = arg2;
+ comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags);
+#ifdef CONFIG_COMEDI_RTAI
+ rt_pend_linux_srq(rt_pend_tq_irq);
+#endif
+#ifdef CONFIG_COMEDI_FUSION
+ rthal_apc_schedule(rt_pend_tq_irq);
+#endif
+#ifdef CONFIG_COMEDI_RTL
+ rtl_global_pend_irq(rt_pend_tq_irq);
+
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_COMEDI_RTAI
+void rt_pend_irq_handler(void)
+#elif defined(CONFIG_COMEDI_FUSION)
+void rt_pend_irq_handler(void *cookie)
+#elif defined(CONFIG_COMEDI_RTL)
+void rt_pend_irq_handler(int irq, void *dev PT_REGS_ARG)
+#endif
+{
+ while (rt_pend_head != rt_pend_tail) {
+ INC_CIRCULAR_PTR(rt_pend_tail, rt_pend_tq, RT_PEND_TQ_SIZE);
+ rt_pend_tail->func(rt_pend_tail->arg1, rt_pend_tail->arg2);
+ }
+}
+
+int rt_pend_tq_init(void)
+{
+ rt_pend_head = rt_pend_tail = rt_pend_tq;
+#ifdef CONFIG_COMEDI_RTAI
+ rt_pend_tq_irq = rt_request_srq(0, rt_pend_irq_handler, NULL);
+#endif
+#ifdef CONFIG_COMEDI_FUSION
+ rt_pend_tq_irq =
+ rthal_apc_alloc("comedi APC", rt_pend_irq_handler, NULL);
+#endif
+#ifdef CONFIG_COMEDI_RTL
+ rt_pend_tq_irq = rtl_get_soft_irq(rt_pend_irq_handler, "rt_pend_irq");
+#endif
+ if (rt_pend_tq_irq > 0)
+ printk("rt_pend_tq: RT bottom half scheduler initialized OK\n");
+ else
+ printk("rt_pend_tq: rtl_get_soft_irq failed\n");
+ return 0;
+}
+
+void rt_pend_tq_cleanup(void)
+{
+ printk("rt_pend_tq: unloading\n");
+#ifdef CONFIG_COMEDI_RTAI
+ rt_free_srq(rt_pend_tq_irq);
+#endif
+#ifdef CONFIG_COMEDI_FUSION
+ rthal_apc_free(rt_pend_tq_irq);
+#endif
+#ifdef CONFIG_COMEDI_RTL
+ free_irq(rt_pend_tq_irq, NULL);
+#endif
+}
diff --git a/drivers/staging/comedi/rt_pend_tq.h b/drivers/staging/comedi/rt_pend_tq.h
new file mode 100644
index 000000000000..01ed71bf409d
--- /dev/null
+++ b/drivers/staging/comedi/rt_pend_tq.h
@@ -0,0 +1,10 @@
+#define RT_PEND_TQ_SIZE 16
+struct rt_pend_tq {
+ void (*func) (int arg1, void *arg2);
+ int arg1;
+ void *arg2;
+};
+extern int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1,
+ void *arg2);
+extern int rt_pend_tq_init(void);
+extern void rt_pend_tq_cleanup(void);
diff --git a/drivers/staging/comedi/wrapper.h b/drivers/staging/comedi/wrapper.h
new file mode 100644
index 000000000000..77fc673900e9
--- /dev/null
+++ b/drivers/staging/comedi/wrapper.h
@@ -0,0 +1,25 @@
+/*
+ linux/wrapper.h compatibility header
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __COMPAT_LINUX_WRAPPER_H_
+#define __COMPAT_LINUX_WRAPPER_H_
+
+#define mem_map_reserve(p) set_bit(PG_reserved, &((p)->flags))
+#define mem_map_unreserve(p) clear_bit(PG_reserved, &((p)->flags))
+
+#endif /* __COMPAT_LINUX_WRAPPER_H_ */
diff --git a/drivers/staging/echo/TODO b/drivers/staging/echo/TODO
index 1ca09afd603e..f6d8580a0baa 100644
--- a/drivers/staging/echo/TODO
+++ b/drivers/staging/echo/TODO
@@ -1,7 +1,5 @@
TODO:
- checkpatch.pl cleanups
- - Lindent
- - typedef removals
- handle bit_operations.h (merge in or make part of common code?)
- remove proc interface, only use echo.h interface (proc interface is
racy and not correct.)
diff --git a/drivers/staging/echo/echo.h b/drivers/staging/echo/echo.h
index 9fb9543c4f13..34fb816b15c8 100644
--- a/drivers/staging/echo/echo.h
+++ b/drivers/staging/echo/echo.h
@@ -149,8 +149,8 @@ struct oslec_state {
int Lbgn, Lbgn_acc, Lbgn_upper, Lbgn_upper_acc;
/* foreground and background filter states */
- fir16_state_t fir_state;
- fir16_state_t fir_state_bg;
+ struct fir16_state_t fir_state;
+ struct fir16_state_t fir_state_bg;
int16_t *fir_taps16[2];
/* DC blocking filter states */
diff --git a/drivers/staging/echo/fir.h b/drivers/staging/echo/fir.h
index 5645cb1b2f90..d35f16805f4b 100644
--- a/drivers/staging/echo/fir.h
+++ b/drivers/staging/echo/fir.h
@@ -72,37 +72,37 @@
16 bit integer FIR descriptor. This defines the working state for a single
instance of an FIR filter using 16 bit integer coefficients.
*/
-typedef struct {
+struct fir16_state_t {
int taps;
int curr_pos;
const int16_t *coeffs;
int16_t *history;
-} fir16_state_t;
+};
/*!
32 bit integer FIR descriptor. This defines the working state for a single
instance of an FIR filter using 32 bit integer coefficients, and filtering
16 bit integer data.
*/
-typedef struct {
+struct fir32_state_t {
int taps;
int curr_pos;
const int32_t *coeffs;
int16_t *history;
-} fir32_state_t;
+};
/*!
Floating point FIR descriptor. This defines the working state for a single
instance of an FIR filter using floating point coefficients and data.
*/
-typedef struct {
+struct fir_float_state_t {
int taps;
int curr_pos;
const float *coeffs;
float *history;
-} fir_float_state_t;
+};
-static __inline__ const int16_t *fir16_create(fir16_state_t * fir,
+static __inline__ const int16_t *fir16_create(struct fir16_state_t *fir,
const int16_t * coeffs, int taps)
{
fir->taps = taps;
@@ -116,7 +116,7 @@ static __inline__ const int16_t *fir16_create(fir16_state_t * fir,
return fir->history;
}
-static __inline__ void fir16_flush(fir16_state_t * fir)
+static __inline__ void fir16_flush(struct fir16_state_t *fir)
{
#if defined(USE_MMX) || defined(USE_SSE2) || defined(__bfin__)
memset(fir->history, 0, 2 * fir->taps * sizeof(int16_t));
@@ -125,7 +125,7 @@ static __inline__ void fir16_flush(fir16_state_t * fir)
#endif
}
-static __inline__ void fir16_free(fir16_state_t * fir)
+static __inline__ void fir16_free(struct fir16_state_t *fir)
{
kfree(fir->history);
}
@@ -157,19 +157,19 @@ static inline int32_t dot_asm(short *x, short *y, int len)
}
#endif
-static __inline__ int16_t fir16(fir16_state_t * fir, int16_t sample)
+static __inline__ int16_t fir16(struct fir16_state_t *fir, int16_t sample)
{
int32_t y;
#if defined(USE_MMX)
int i;
- mmx_t *mmx_coeffs;
- mmx_t *mmx_hist;
+ union mmx_t *mmx_coeffs;
+ union mmx_t *mmx_hist;
fir->history[fir->curr_pos] = sample;
fir->history[fir->curr_pos + fir->taps] = sample;
- mmx_coeffs = (mmx_t *) fir->coeffs;
- mmx_hist = (mmx_t *) & fir->history[fir->curr_pos];
+ mmx_coeffs = (union mmx_t *)fir->coeffs;
+ mmx_hist = (union mmx_t *)&fir->history[fir->curr_pos];
i = fir->taps;
pxor_r2r(mm4, mm4);
/* 8 samples per iteration, so the filter must be a multiple of 8 long. */
@@ -193,14 +193,14 @@ static __inline__ int16_t fir16(fir16_state_t * fir, int16_t sample)
emms();
#elif defined(USE_SSE2)
int i;
- xmm_t *xmm_coeffs;
- xmm_t *xmm_hist;
+ union xmm_t *xmm_coeffs;
+ union xmm_t *xmm_hist;
fir->history[fir->curr_pos] = sample;
fir->history[fir->curr_pos + fir->taps] = sample;
- xmm_coeffs = (xmm_t *) fir->coeffs;
- xmm_hist = (xmm_t *) & fir->history[fir->curr_pos];
+ xmm_coeffs = (union xmm_t *)fir->coeffs;
+ xmm_hist = (union xmm_t *)&fir->history[fir->curr_pos];
i = fir->taps;
pxor_r2r(xmm4, xmm4);
/* 16 samples per iteration, so the filter must be a multiple of 16 long. */
@@ -250,7 +250,7 @@ static __inline__ int16_t fir16(fir16_state_t * fir, int16_t sample)
return (int16_t) (y >> 15);
}
-static __inline__ const int16_t *fir32_create(fir32_state_t * fir,
+static __inline__ const int16_t *fir32_create(struct fir32_state_t *fir,
const int32_t * coeffs, int taps)
{
fir->taps = taps;
@@ -260,17 +260,17 @@ static __inline__ const int16_t *fir32_create(fir32_state_t * fir,
return fir->history;
}
-static __inline__ void fir32_flush(fir32_state_t * fir)
+static __inline__ void fir32_flush(struct fir32_state_t *fir)
{
memset(fir->history, 0, fir->taps * sizeof(int16_t));
}
-static __inline__ void fir32_free(fir32_state_t * fir)
+static __inline__ void fir32_free(struct fir32_state_t *fir)
{
kfree(fir->history);
}
-static __inline__ int16_t fir32(fir32_state_t * fir, int16_t sample)
+static __inline__ int16_t fir32(struct fir32_state_t *fir, int16_t sample)
{
int i;
int32_t y;
diff --git a/drivers/staging/echo/mmx.h b/drivers/staging/echo/mmx.h
index 35412efe61ce..44e5cfebc18f 100644
--- a/drivers/staging/echo/mmx.h
+++ b/drivers/staging/echo/mmx.h
@@ -27,7 +27,7 @@
* values by ULL, lest they be truncated by the compiler)
*/
-typedef union {
+union mmx_t {
long long q; /* Quadword (64-bit) value */
unsigned long long uq; /* Unsigned Quadword */
int d[2]; /* 2 Doubleword (32-bit) values */
@@ -37,12 +37,12 @@ typedef union {
char b[8]; /* 8 Byte (8-bit) values */
unsigned char ub[8]; /* 8 Unsigned Byte */
float s[2]; /* Single-precision (32-bit) value */
-} mmx_t; /* On an 8-byte (64-bit) boundary */
+}; /* On an 8-byte (64-bit) boundary */
/* SSE registers */
-typedef union {
+union xmm_t {
char b[16];
-} xmm_t;
+};
#define mmx_i2r(op,imm,reg) \
__asm__ __volatile__ (#op " %0, %%" #reg \
diff --git a/drivers/staging/epl/Benchmark.h b/drivers/staging/epl/Benchmark.h
new file mode 100644
index 000000000000..62dee3b14373
--- /dev/null
+++ b/drivers/staging/epl/Benchmark.h
@@ -0,0 +1,437 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: header file for benchmarking
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: Benchmark.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ ...
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/08/16 d.k.: start of implementation
+
+****************************************************************************/
+
+#ifndef _BENCHMARK_H_
+#define _BENCHMARK_H_
+
+#include "global.h"
+
+#if (TARGET_SYSTEM == _NO_OS_) && (DEV_SYSTEM == _DEV_GNU_CF548X_)
+#include "common.h"
+
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+
+// #include <linux/config.h>
+#include <linux/kernel.h>
+
+#ifdef CONFIG_COLDFIRE
+#include <asm/coldfire.h>
+#include <asm/m5485gpio.h>
+
+#define BENCHMARK_SET(x) MCF_GPIO_PODR_PCIBG |= (1 << (x)) // (x+1)
+#define BENCHMARK_RESET(x) MCF_GPIO_PODR_PCIBG &= ~(1 << (x)) // (x+1)
+#define BENCHMARK_TOGGLE(x) MCF_GPIO_PODR_PCIBR ^= (1 << (x - 5))
+#else
+#undef BENCHMARK_MODULES
+#define BENCHMARK_MODULES 0x00000000
+#endif
+
+#else
+ // disable Benchmarking
+#undef BENCHMARK_MODULES
+#define BENCHMARK_MODULES 0x00000000
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef BENCHMARK_MODULES
+#define BENCHMARK_MODULES 0x00000000
+#endif
+
+#define BENCHMARK_MOD_01 0x00000001
+#define BENCHMARK_MOD_02 0x00000002
+#define BENCHMARK_MOD_03 0x00000004
+#define BENCHMARK_MOD_04 0x00000008
+#define BENCHMARK_MOD_05 0x00000010
+#define BENCHMARK_MOD_06 0x00000020
+#define BENCHMARK_MOD_07 0x00000040
+#define BENCHMARK_MOD_08 0x00000080
+#define BENCHMARK_MOD_09 0x00000100
+#define BENCHMARK_MOD_10 0x00000200
+#define BENCHMARK_MOD_11 0x00000400
+#define BENCHMARK_MOD_12 0x00000800
+#define BENCHMARK_MOD_13 0x00001000
+#define BENCHMARK_MOD_14 0x00002000
+#define BENCHMARK_MOD_15 0x00004000
+#define BENCHMARK_MOD_16 0x00008000
+#define BENCHMARK_MOD_17 0x00010000
+#define BENCHMARK_MOD_18 0x00020000
+#define BENCHMARK_MOD_19 0x00040000
+#define BENCHMARK_MOD_20 0x00080000
+#define BENCHMARK_MOD_21 0x00100000
+#define BENCHMARK_MOD_22 0x00200000
+#define BENCHMARK_MOD_23 0x00400000
+#define BENCHMARK_MOD_24 0x00800000
+#define BENCHMARK_MOD_25 0x01000000
+#define BENCHMARK_MOD_26 0x02000000
+#define BENCHMARK_MOD_27 0x04000000
+#define BENCHMARK_MOD_28 0x08000000
+#define BENCHMARK_MOD_29 0x10000000
+#define BENCHMARK_MOD_30 0x20000000
+#define BENCHMARK_MOD_31 0x40000000
+#define BENCHMARK_MOD_32 0x80000000
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_01)
+#define BENCHMARK_MOD_01_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_01_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_01_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_01_SET(x)
+#define BENCHMARK_MOD_01_RESET(x)
+#define BENCHMARK_MOD_01_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_02)
+#define BENCHMARK_MOD_02_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_02_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_02_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_02_SET(x)
+#define BENCHMARK_MOD_02_RESET(x)
+#define BENCHMARK_MOD_02_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_03)
+#define BENCHMARK_MOD_03_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_03_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_03_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_03_SET(x)
+#define BENCHMARK_MOD_03_RESET(x)
+#define BENCHMARK_MOD_03_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_04)
+#define BENCHMARK_MOD_04_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_04_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_04_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_04_SET(x)
+#define BENCHMARK_MOD_04_RESET(x)
+#define BENCHMARK_MOD_04_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_05)
+#define BENCHMARK_MOD_05_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_05_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_05_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_05_SET(x)
+#define BENCHMARK_MOD_05_RESET(x)
+#define BENCHMARK_MOD_05_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_06)
+#define BENCHMARK_MOD_06_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_06_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_06_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_06_SET(x)
+#define BENCHMARK_MOD_06_RESET(x)
+#define BENCHMARK_MOD_06_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_07)
+#define BENCHMARK_MOD_07_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_07_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_07_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_07_SET(x)
+#define BENCHMARK_MOD_07_RESET(x)
+#define BENCHMARK_MOD_07_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_08)
+#define BENCHMARK_MOD_08_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_08_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_08_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_08_SET(x)
+#define BENCHMARK_MOD_08_RESET(x)
+#define BENCHMARK_MOD_08_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_09)
+#define BENCHMARK_MOD_09_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_09_RESET(x) BENCHMARK_RESET(x)
+#define BENCHMARK_MOD_09_TOGGLE(x) BENCHMARK_TOGGLE(x)
+#else
+#define BENCHMARK_MOD_09_SET(x)
+#define BENCHMARK_MOD_09_RESET(x)
+#define BENCHMARK_MOD_09_TOGGLE(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_10)
+#define BENCHMARK_MOD_10_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_10_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_10_SET(x)
+#define BENCHMARK_MOD_10_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_11)
+#define BENCHMARK_MOD_11_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_11_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_11_SET(x)
+#define BENCHMARK_MOD_11_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_12)
+#define BENCHMARK_MOD_12_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_12_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_12_SET(x)
+#define BENCHMARK_MOD_12_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_13)
+#define BENCHMARK_MOD_13_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_13_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_13_SET(x)
+#define BENCHMARK_MOD_13_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_14)
+#define BENCHMARK_MOD_14_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_14_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_14_SET(x)
+#define BENCHMARK_MOD_14_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_15)
+#define BENCHMARK_MOD_15_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_15_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_15_SET(x)
+#define BENCHMARK_MOD_15_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_16)
+#define BENCHMARK_MOD_16_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_16_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_16_SET(x)
+#define BENCHMARK_MOD_16_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_17)
+#define BENCHMARK_MOD_17_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_17_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_17_SET(x)
+#define BENCHMARK_MOD_17_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_18)
+#define BENCHMARK_MOD_18_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_18_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_18_SET(x)
+#define BENCHMARK_MOD_18_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_19)
+#define BENCHMARK_MOD_19_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_19_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_19_SET(x)
+#define BENCHMARK_MOD_19_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_20)
+#define BENCHMARK_MOD_20_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_20_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_20_SET(x)
+#define BENCHMARK_MOD_20_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_21)
+#define BENCHMARK_MOD_21_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_21_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_21_SET(x)
+#define BENCHMARK_MOD_21_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_22)
+#define BENCHMARK_MOD_22_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_22_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_22_SET(x)
+#define BENCHMARK_MOD_22_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_23)
+#define BENCHMARK_MOD_23_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_23_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_23_SET(x)
+#define BENCHMARK_MOD_23_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_24)
+#define BENCHMARK_MOD_24_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_24_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_24_SET(x)
+#define BENCHMARK_MOD_24_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_25)
+#define BENCHMARK_MOD_25_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_25_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_25_SET(x)
+#define BENCHMARK_MOD_25_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_26)
+#define BENCHMARK_MOD_26_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_26_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_26_SET(x)
+#define BENCHMARK_MOD_26_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_27)
+#define BENCHMARK_MOD_27_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_27_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_27_SET(x)
+#define BENCHMARK_MOD_27_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_28)
+#define BENCHMARK_MOD_28_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_28_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_28_SET(x)
+#define BENCHMARK_MOD_28_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_29)
+#define BENCHMARK_MOD_29_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_29_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_29_SET(x)
+#define BENCHMARK_MOD_29_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_30)
+#define BENCHMARK_MOD_30_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_30_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_30_SET(x)
+#define BENCHMARK_MOD_30_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_31)
+#define BENCHMARK_MOD_31_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_31_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_31_SET(x)
+#define BENCHMARK_MOD_31_RESET(x)
+#endif
+
+#if (BENCHMARK_MODULES & BENCHMARK_MOD_32)
+#define BENCHMARK_MOD_32_SET(x) BENCHMARK_SET(x)
+#define BENCHMARK_MOD_32_RESET(x) BENCHMARK_RESET(x)
+#else
+#define BENCHMARK_MOD_32_SET(x)
+#define BENCHMARK_MOD_32_RESET(x)
+#endif
+
+//---------------------------------------------------------------------------
+// modul global types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+#endif // _BENCHMARK_H_
diff --git a/drivers/staging/epl/Debug.h b/drivers/staging/epl/Debug.h
new file mode 100644
index 000000000000..05de9d541fd6
--- /dev/null
+++ b/drivers/staging/epl/Debug.h
@@ -0,0 +1,734 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: Debug interface
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: Debug.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ ...
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+****************************************************************************/
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+#include "global.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// global const defines
+//---------------------------------------------------------------------------
+
+// These definitions are important for level-debug traces.
+// A macro DEBUG_GLB_LVL() defines the current debug-level using following bis.
+// If the corresponding bit is set then trace message will be printed out
+// (only if NDEBUG is not defined). The upper debug-levels are reserved for
+// the debug-levels ALWAYS, ERROR and ASSERT.
+#define DEBUG_LVL_01 0x00000001
+#define DEBUG_LVL_02 0x00000002
+#define DEBUG_LVL_03 0x00000004
+#define DEBUG_LVL_04 0x00000008
+#define DEBUG_LVL_05 0x00000010
+#define DEBUG_LVL_06 0x00000020
+#define DEBUG_LVL_07 0x00000040
+#define DEBUG_LVL_08 0x00000080
+#define DEBUG_LVL_09 0x00000100
+#define DEBUG_LVL_10 0x00000200
+#define DEBUG_LVL_11 0x00000400
+#define DEBUG_LVL_12 0x00000800
+#define DEBUG_LVL_13 0x00001000
+#define DEBUG_LVL_14 0x00002000
+#define DEBUG_LVL_15 0x00004000
+#define DEBUG_LVL_16 0x00008000
+#define DEBUG_LVL_17 0x00010000
+#define DEBUG_LVL_18 0x00020000
+#define DEBUG_LVL_19 0x00040000
+#define DEBUG_LVL_20 0x00080000
+#define DEBUG_LVL_21 0x00100000
+#define DEBUG_LVL_22 0x00200000
+#define DEBUG_LVL_23 0x00400000
+#define DEBUG_LVL_24 0x00800000
+#define DEBUG_LVL_25 0x01000000
+#define DEBUG_LVL_26 0x02000000
+#define DEBUG_LVL_27 0x04000000
+#define DEBUG_LVL_28 0x08000000
+#define DEBUG_LVL_29 0x10000000
+#define DEBUG_LVL_ASSERT 0x20000000
+#define DEBUG_LVL_ERROR 0x40000000
+#define DEBUG_LVL_ALWAYS 0x80000000
+
+//---------------------------------------------------------------------------
+// global types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// global vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// global function prototypes
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// global macros
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// this macro defines a version string
+
+
+//---------------------------------------------------------------------------
+// this macro defines a build info string (e.g. for using in printf())
+#define DEBUG_MAKE_BUILD_INFO(prefix,product,prodid,descr,verstr,author) "\n" \
+ prefix "***************************************************\n" \
+ prefix "Project: " product ", " prodid "\n" \
+ prefix "Descript.: " descr "\n" \
+ prefix "Author: " author "\n" \
+ prefix "Date: " __DATE__ "\n" \
+ prefix "Version: " verstr "\n" \
+ prefix "***************************************************\n\n"
+
+//---------------------------------------------------------------------------
+// The default debug-level is: ERROR and ALWAYS.
+// You can define an other debug-level in project settings.
+#ifndef DEF_DEBUG_LVL
+#define DEF_DEBUG_LVL (DEBUG_LVL_ALWAYS | DEBUG_LVL_ERROR)
+#endif
+#ifndef DEBUG_GLB_LVL
+#define DEBUG_GLB_LVL() (DEF_DEBUG_LVL)
+#endif
+
+//---------------------------------------------------------------------------
+#if (DEV_SYSTEM == _DEV_WIN32_) && defined (TRACE_MSG)
+
+ // For WIN32 the macro DEBUG_TRACE0 can be defined as function call TraceLvl()
+ // or as macro TRACE().
+ //
+ // Here the parameter 'lvl' can be used with more than one
+ // debug-level (using OR).
+ //
+ // Example: DEBUG_TRACE1(DEBUG_LVL_30 | DEBUG_LVL_02, "Hello %d", bCount);
+
+#define DEBUG_TRACE0(lvl,str) TraceLvl((lvl),str)
+#define DEBUG_TRACE1(lvl,str,p1) TraceLvl((lvl),str,p1)
+#define DEBUG_TRACE2(lvl,str,p1,p2) TraceLvl((lvl),str,p1,p2)
+#define DEBUG_TRACE3(lvl,str,p1,p2,p3) TraceLvl((lvl),str,p1,p2,p3)
+#define DEBUG_TRACE4(lvl,str,p1,p2,p3,p4) TraceLvl((lvl),str,p1,p2,p3,p4)
+#define DEBUG_GLB_LVL() dwDebugLevel_g
+
+#else
+
+ // At microcontrollers we do reduce the memory usage by deleting DEBUG_TRACE-lines
+ // (compiler does delete the lines).
+ //
+ // Here the parameter 'lvl' can only be used with one debug-level.
+ //
+ // Example: DEBUG_TRACE1(DEBUG_LVL_ERROR, "error code %d", dwRet);
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_ALWAYS)
+#define DEBUG_LVL_ALWAYS_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_ALWAYS_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_ALWAYS_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_ALWAYS_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_ALWAYS_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_ALWAYS_TRACE0(str)
+#define DEBUG_LVL_ALWAYS_TRACE1(str,p1)
+#define DEBUG_LVL_ALWAYS_TRACE2(str,p1,p2)
+#define DEBUG_LVL_ALWAYS_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_ALWAYS_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_ERROR)
+#define DEBUG_LVL_ERROR_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_ERROR_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_ERROR_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_ERROR_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_ERROR_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_ERROR_TRACE0(str)
+#define DEBUG_LVL_ERROR_TRACE1(str,p1)
+#define DEBUG_LVL_ERROR_TRACE2(str,p1,p2)
+#define DEBUG_LVL_ERROR_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_ERROR_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT)
+#define DEBUG_LVL_ASSERT_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_ASSERT_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_ASSERT_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_ASSERT_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_ASSERT_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_ASSERT_TRACE0(str)
+#define DEBUG_LVL_ASSERT_TRACE1(str,p1)
+#define DEBUG_LVL_ASSERT_TRACE2(str,p1,p2)
+#define DEBUG_LVL_ASSERT_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_ASSERT_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_29)
+#define DEBUG_LVL_29_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_29_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_29_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_29_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_29_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_29_TRACE0(str)
+#define DEBUG_LVL_29_TRACE1(str,p1)
+#define DEBUG_LVL_29_TRACE2(str,p1,p2)
+#define DEBUG_LVL_29_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_29_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_28)
+#define DEBUG_LVL_28_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_28_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_28_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_28_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_28_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_28_TRACE0(str)
+#define DEBUG_LVL_28_TRACE1(str,p1)
+#define DEBUG_LVL_28_TRACE2(str,p1,p2)
+#define DEBUG_LVL_28_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_28_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_27)
+#define DEBUG_LVL_27_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_27_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_27_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_27_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_27_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_27_TRACE0(str)
+#define DEBUG_LVL_27_TRACE1(str,p1)
+#define DEBUG_LVL_27_TRACE2(str,p1,p2)
+#define DEBUG_LVL_27_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_27_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_26)
+#define DEBUG_LVL_26_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_26_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_26_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_26_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_26_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_26_TRACE0(str)
+#define DEBUG_LVL_26_TRACE1(str,p1)
+#define DEBUG_LVL_26_TRACE2(str,p1,p2)
+#define DEBUG_LVL_26_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_26_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_25)
+#define DEBUG_LVL_25_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_25_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_25_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_25_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_25_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_25_TRACE0(str)
+#define DEBUG_LVL_25_TRACE1(str,p1)
+#define DEBUG_LVL_25_TRACE2(str,p1,p2)
+#define DEBUG_LVL_25_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_25_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_24)
+#define DEBUG_LVL_24_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_24_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_24_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_24_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_24_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_24_TRACE0(str)
+#define DEBUG_LVL_24_TRACE1(str,p1)
+#define DEBUG_LVL_24_TRACE2(str,p1,p2)
+#define DEBUG_LVL_24_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_24_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_23)
+#define DEBUG_LVL_23_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_23_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_23_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_23_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_23_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_23_TRACE0(str)
+#define DEBUG_LVL_23_TRACE1(str,p1)
+#define DEBUG_LVL_23_TRACE2(str,p1,p2)
+#define DEBUG_LVL_23_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_23_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_22)
+#define DEBUG_LVL_22_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_22_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_22_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_22_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_22_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_22_TRACE0(str)
+#define DEBUG_LVL_22_TRACE1(str,p1)
+#define DEBUG_LVL_22_TRACE2(str,p1,p2)
+#define DEBUG_LVL_22_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_22_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_21)
+#define DEBUG_LVL_21_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_21_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_21_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_21_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_21_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_21_TRACE0(str)
+#define DEBUG_LVL_21_TRACE1(str,p1)
+#define DEBUG_LVL_21_TRACE2(str,p1,p2)
+#define DEBUG_LVL_21_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_21_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_20)
+#define DEBUG_LVL_20_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_20_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_20_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_20_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_20_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_20_TRACE0(str)
+#define DEBUG_LVL_20_TRACE1(str,p1)
+#define DEBUG_LVL_20_TRACE2(str,p1,p2)
+#define DEBUG_LVL_20_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_20_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_19)
+#define DEBUG_LVL_19_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_19_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_19_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_19_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_19_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_19_TRACE0(str)
+#define DEBUG_LVL_19_TRACE1(str,p1)
+#define DEBUG_LVL_19_TRACE2(str,p1,p2)
+#define DEBUG_LVL_19_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_19_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_18)
+#define DEBUG_LVL_18_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_18_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_18_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_18_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_18_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_18_TRACE0(str)
+#define DEBUG_LVL_18_TRACE1(str,p1)
+#define DEBUG_LVL_18_TRACE2(str,p1,p2)
+#define DEBUG_LVL_18_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_18_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_17)
+#define DEBUG_LVL_17_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_17_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_17_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_17_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_17_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_17_TRACE0(str)
+#define DEBUG_LVL_17_TRACE1(str,p1)
+#define DEBUG_LVL_17_TRACE2(str,p1,p2)
+#define DEBUG_LVL_17_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_17_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_16)
+#define DEBUG_LVL_16_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_16_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_16_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_16_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_16_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_16_TRACE0(str)
+#define DEBUG_LVL_16_TRACE1(str,p1)
+#define DEBUG_LVL_16_TRACE2(str,p1,p2)
+#define DEBUG_LVL_16_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_16_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_15)
+#define DEBUG_LVL_15_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_15_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_15_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_15_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_15_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_15_TRACE0(str)
+#define DEBUG_LVL_15_TRACE1(str,p1)
+#define DEBUG_LVL_15_TRACE2(str,p1,p2)
+#define DEBUG_LVL_15_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_15_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_14)
+#define DEBUG_LVL_14_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_14_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_14_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_14_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_14_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_14_TRACE0(str)
+#define DEBUG_LVL_14_TRACE1(str,p1)
+#define DEBUG_LVL_14_TRACE2(str,p1,p2)
+#define DEBUG_LVL_14_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_14_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_13)
+#define DEBUG_LVL_13_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_13_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_13_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_13_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_13_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_13_TRACE0(str)
+#define DEBUG_LVL_13_TRACE1(str,p1)
+#define DEBUG_LVL_13_TRACE2(str,p1,p2)
+#define DEBUG_LVL_13_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_13_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_12)
+#define DEBUG_LVL_12_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_12_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_12_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_12_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_12_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_12_TRACE0(str)
+#define DEBUG_LVL_12_TRACE1(str,p1)
+#define DEBUG_LVL_12_TRACE2(str,p1,p2)
+#define DEBUG_LVL_12_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_12_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_11)
+#define DEBUG_LVL_11_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_11_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_11_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_11_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_11_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_11_TRACE0(str)
+#define DEBUG_LVL_11_TRACE1(str,p1)
+#define DEBUG_LVL_11_TRACE2(str,p1,p2)
+#define DEBUG_LVL_11_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_11_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_10)
+#define DEBUG_LVL_10_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_10_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_10_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_10_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_10_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_10_TRACE0(str)
+#define DEBUG_LVL_10_TRACE1(str,p1)
+#define DEBUG_LVL_10_TRACE2(str,p1,p2)
+#define DEBUG_LVL_10_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_10_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_09)
+#define DEBUG_LVL_09_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_09_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_09_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_09_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_09_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_09_TRACE0(str)
+#define DEBUG_LVL_09_TRACE1(str,p1)
+#define DEBUG_LVL_09_TRACE2(str,p1,p2)
+#define DEBUG_LVL_09_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_09_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_08)
+#define DEBUG_LVL_08_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_08_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_08_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_08_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_08_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_08_TRACE0(str)
+#define DEBUG_LVL_08_TRACE1(str,p1)
+#define DEBUG_LVL_08_TRACE2(str,p1,p2)
+#define DEBUG_LVL_08_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_08_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_07)
+#define DEBUG_LVL_07_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_07_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_07_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_07_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_07_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_07_TRACE0(str)
+#define DEBUG_LVL_07_TRACE1(str,p1)
+#define DEBUG_LVL_07_TRACE2(str,p1,p2)
+#define DEBUG_LVL_07_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_07_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_06)
+#define DEBUG_LVL_06_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_06_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_06_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_06_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_06_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_06_TRACE0(str)
+#define DEBUG_LVL_06_TRACE1(str,p1)
+#define DEBUG_LVL_06_TRACE2(str,p1,p2)
+#define DEBUG_LVL_06_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_06_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_05)
+#define DEBUG_LVL_05_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_05_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_05_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_05_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_05_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_05_TRACE0(str)
+#define DEBUG_LVL_05_TRACE1(str,p1)
+#define DEBUG_LVL_05_TRACE2(str,p1,p2)
+#define DEBUG_LVL_05_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_05_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_04)
+#define DEBUG_LVL_04_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_04_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_04_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_04_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_04_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_04_TRACE0(str)
+#define DEBUG_LVL_04_TRACE1(str,p1)
+#define DEBUG_LVL_04_TRACE2(str,p1,p2)
+#define DEBUG_LVL_04_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_04_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_03)
+#define DEBUG_LVL_03_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_03_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_03_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_03_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_03_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_03_TRACE0(str)
+#define DEBUG_LVL_03_TRACE1(str,p1)
+#define DEBUG_LVL_03_TRACE2(str,p1,p2)
+#define DEBUG_LVL_03_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_03_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_02)
+#define DEBUG_LVL_02_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_02_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_02_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_02_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_02_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_02_TRACE0(str)
+#define DEBUG_LVL_02_TRACE1(str,p1)
+#define DEBUG_LVL_02_TRACE2(str,p1,p2)
+#define DEBUG_LVL_02_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_02_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#if (DEBUG_GLB_LVL() & DEBUG_LVL_01)
+#define DEBUG_LVL_01_TRACE0(str) TRACE0(str)
+#define DEBUG_LVL_01_TRACE1(str,p1) TRACE1(str,p1)
+#define DEBUG_LVL_01_TRACE2(str,p1,p2) TRACE2(str,p1,p2)
+#define DEBUG_LVL_01_TRACE3(str,p1,p2,p3) TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_01_TRACE4(str,p1,p2,p3,p4) TRACE4(str,p1,p2,p3,p4)
+#else
+#define DEBUG_LVL_01_TRACE0(str)
+#define DEBUG_LVL_01_TRACE1(str,p1)
+#define DEBUG_LVL_01_TRACE2(str,p1,p2)
+#define DEBUG_LVL_01_TRACE3(str,p1,p2,p3)
+#define DEBUG_LVL_01_TRACE4(str,p1,p2,p3,p4)
+#endif
+
+#define DEBUG_TRACE0(lvl,str) lvl##_TRACE0(str)
+#define DEBUG_TRACE1(lvl,str,p1) lvl##_TRACE1(str,p1)
+#define DEBUG_TRACE2(lvl,str,p1,p2) lvl##_TRACE2(str,p1,p2)
+#define DEBUG_TRACE3(lvl,str,p1,p2,p3) lvl##_TRACE3(str,p1,p2,p3)
+#define DEBUG_TRACE4(lvl,str,p1,p2,p3,p4) lvl##_TRACE4(str,p1,p2,p3,p4)
+
+#endif
+
+//---------------------------------------------------------------------------
+// The macro DEBUG_DUMP_DATA() can be used with the same debug-levels to dump
+// out data bytes. Function DumpData() has to be included.
+// NOTE: DUMP_DATA has to be defined in project settings.
+#if (!defined (NDEBUG) && defined (DUMP_DATA)) || (DEV_SYSTEM == _DEV_WIN32_)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ void DumpData(char *szStr_p, BYTE MEM * pbData_p, WORD wSize_p);
+
+#ifdef __cplusplus
+} // von extern "C"
+#endif
+#define DEBUG_DUMP_DATA(lvl,str,ptr,siz) if ((DEBUG_GLB_LVL() & (lvl))==(lvl)) \
+ DumpData (str, (BYTE MEM*) (ptr), (WORD) (siz));
+#else
+
+#define DEBUG_DUMP_DATA(lvl,str,ptr,siz)
+
+#endif
+
+//---------------------------------------------------------------------------
+// The macro DEBUG_ASSERT() can be used to print out an error string if the
+// parametered expresion does not result TRUE.
+// NOTE: If DEBUG_KEEP_ASSERT is defined, then DEBUG_ASSERT-line will not be
+// deleted from compiler (in release version too).
+#if !defined (NDEBUG) || defined (DEBUG_KEEP_ASSERT)
+
+#if (DEV_SYSTEM == _DEV_WIN32_)
+
+ // For WIN32 process will be killed after closing message box.
+
+#define DEBUG_ASSERT0(expr,str) if (!(expr ) && ((DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT)!=0)) { \
+ MessageBox (NULL, \
+ "Assertion failed: line " __LINE__ " file " __FILE__ \
+ "\n -> " str "\n"); \
+ ExitProcess (-1); }
+
+#define DEBUG_ASSERT1(expr,str,p1) if (!(expr ) && ((DEBUG_GLB_LVL() & DEBUG_LVL_ASSERT)!=0)) { \
+ MessageBox (NULL, \
+ "Assertion failed: line " __LINE__ " file " __FILE__ \
+ "\n -> " str "\n"); \
+ ExitProcess (-1); }
+
+#else
+
+ // For microcontrollers process will be stopped using endless loop.
+
+#define DEBUG_ASSERT0(expr,str) if (!(expr )) { \
+ DEBUG_LVL_ASSERT_TRACE3 ( \
+ "Assertion failed: line %d file '%s'\n" \
+ " -> '%s'\n", __LINE__, __FILE__, str); \
+ while (1); }
+
+#define DEBUG_ASSERT1(expr,str,p1) if (!(expr )) { \
+ DEBUG_LVL_ASSERT_TRACE4 ( \
+ "Assertion failed: line %d file '%s'\n" \
+ " -> '%s'\n" \
+ " -> 0x%08lX\n", __LINE__, __FILE__, str, (DWORD) p1); \
+ while (1); }
+
+#endif
+
+#else
+
+#define DEBUG_ASSERT0(expr,str)
+#define DEBUG_ASSERT1(expr,str,p1)
+
+#endif
+
+//---------------------------------------------------------------------------
+// The macro DEBUG_ONLY() implements code, if NDEBUG is not defined.
+#if !defined (DEBUG_ONLY)
+#if !defined (NDEBUG)
+
+#define DEBUG_ONLY(expr) expr
+
+#else
+
+#define DEBUG_ONLY(expr)
+
+#endif
+#endif
+
+#endif // _DEBUG_H_
diff --git a/drivers/staging/epl/Edrv8139.c b/drivers/staging/epl/Edrv8139.c
new file mode 100644
index 000000000000..296354aaa9c7
--- /dev/null
+++ b/drivers/staging/epl/Edrv8139.c
@@ -0,0 +1,1252 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: Ethernet driver for Realtek RTL8139 chips
+ except the RTL8139C+, because it has a different
+ Tx descriptor handling.
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: Edrv8139.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.10 $ $Date: 2008/11/21 09:00:38 $
+
+ $State: Exp $
+
+ Build Environment:
+ Dev C++ and GNU-Compiler for m68k
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2008/02/05 d.k.: start of implementation
+
+****************************************************************************/
+
+#include "global.h"
+#include "EplInc.h"
+#include "edrv.h"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+// Buffer handling:
+// All buffers are created statically (i.e. at compile time resp. at
+// initialisation via kmalloc() ) and not dynamically on request (i.e. via
+// EdrvAllocTxMsgBuffer().
+// EdrvAllocTxMsgBuffer() searches for an unused buffer which is large enough.
+// EdrvInit() may allocate some buffers with sizes less than maximum frame
+// size (i.e. 1514 bytes), e.g. for SoC, SoA, StatusResponse, IdentResponse,
+// NMT requests / commands. The less the size of the buffer the less the
+// number of the buffer.
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef EDRV_MAX_TX_BUFFERS
+#define EDRV_MAX_TX_BUFFERS 20
+#endif
+
+#define EDRV_MAX_FRAME_SIZE 0x600
+
+#define EDRV_RX_BUFFER_SIZE 0x8610 // 32 kB + 16 Byte + 1,5 kB (WRAP is enabled)
+#define EDRV_RX_BUFFER_LENGTH (EDRV_RX_BUFFER_SIZE & 0xF800) // buffer size cut down to 2 kB alignment
+
+#define EDRV_TX_BUFFER_SIZE (EDRV_MAX_TX_BUFFERS * EDRV_MAX_FRAME_SIZE) // n * (MTU + 14 + 4)
+
+#define DRV_NAME "epl"
+
+#define EDRV_REGW_INT_MASK 0x3C // interrupt mask register
+#define EDRV_REGW_INT_STATUS 0x3E // interrupt status register
+#define EDRV_REGW_INT_ROK 0x0001 // Receive OK interrupt
+#define EDRV_REGW_INT_RER 0x0002 // Receive error interrupt
+#define EDRV_REGW_INT_TOK 0x0004 // Transmit OK interrupt
+#define EDRV_REGW_INT_TER 0x0008 // Transmit error interrupt
+#define EDRV_REGW_INT_RXOVW 0x0010 // Rx buffer overflow interrupt
+#define EDRV_REGW_INT_PUN 0x0020 // Packet underrun/ link change interrupt
+#define EDRV_REGW_INT_FOVW 0x0040 // Rx FIFO overflow interrupt
+#define EDRV_REGW_INT_LENCHG 0x2000 // Cable length change interrupt
+#define EDRV_REGW_INT_TIMEOUT 0x4000 // Time out interrupt
+#define EDRV_REGW_INT_SERR 0x8000 // System error interrupt
+#define EDRV_REGW_INT_MASK_DEF (EDRV_REGW_INT_ROK \
+ | EDRV_REGW_INT_RER \
+ | EDRV_REGW_INT_TOK \
+ | EDRV_REGW_INT_TER \
+ | EDRV_REGW_INT_RXOVW \
+ | EDRV_REGW_INT_FOVW \
+ | EDRV_REGW_INT_PUN \
+ | EDRV_REGW_INT_TIMEOUT \
+ | EDRV_REGW_INT_SERR) // default interrupt mask
+
+#define EDRV_REGB_COMMAND 0x37 // command register
+#define EDRV_REGB_COMMAND_RST 0x10
+#define EDRV_REGB_COMMAND_RE 0x08
+#define EDRV_REGB_COMMAND_TE 0x04
+#define EDRV_REGB_COMMAND_BUFE 0x01
+
+#define EDRV_REGB_CMD9346 0x50 // 93C46 command register
+#define EDRV_REGB_CMD9346_LOCK 0x00 // lock configuration registers
+#define EDRV_REGB_CMD9346_UNLOCK 0xC0 // unlock configuration registers
+
+#define EDRV_REGDW_RCR 0x44 // Rx configuration register
+#define EDRV_REGDW_RCR_NO_FTH 0x0000E000 // no receive FIFO threshold
+#define EDRV_REGDW_RCR_RBLEN32K 0x00001000 // 32 kB receive buffer
+#define EDRV_REGDW_RCR_MXDMAUNL 0x00000700 // unlimited maximum DMA burst size
+#define EDRV_REGDW_RCR_NOWRAP 0x00000080 // do not wrap frame at end of buffer
+#define EDRV_REGDW_RCR_AER 0x00000020 // accept error frames (CRC, alignment, collided)
+#define EDRV_REGDW_RCR_AR 0x00000010 // accept runt
+#define EDRV_REGDW_RCR_AB 0x00000008 // accept broadcast frames
+#define EDRV_REGDW_RCR_AM 0x00000004 // accept multicast frames
+#define EDRV_REGDW_RCR_APM 0x00000002 // accept physical match frames
+#define EDRV_REGDW_RCR_AAP 0x00000001 // accept all frames
+#define EDRV_REGDW_RCR_DEF (EDRV_REGDW_RCR_NO_FTH \
+ | EDRV_REGDW_RCR_RBLEN32K \
+ | EDRV_REGDW_RCR_MXDMAUNL \
+ | EDRV_REGDW_RCR_NOWRAP \
+ | EDRV_REGDW_RCR_AB \
+ | EDRV_REGDW_RCR_AM \
+ | EDRV_REGDW_RCR_APM) // default value
+
+#define EDRV_REGDW_TCR 0x40 // Tx configuration register
+#define EDRV_REGDW_TCR_VER_MASK 0x7CC00000 // mask for hardware version
+#define EDRV_REGDW_TCR_VER_C 0x74000000 // RTL8139C
+#define EDRV_REGDW_TCR_VER_D 0x74400000 // RTL8139D
+#define EDRV_REGDW_TCR_IFG96 0x03000000 // default interframe gap (960 ns)
+#define EDRV_REGDW_TCR_CRC 0x00010000 // disable appending of CRC by the controller
+#define EDRV_REGDW_TCR_MXDMAUNL 0x00000700 // maximum DMA burst size of 2048 b
+#define EDRV_REGDW_TCR_TXRETRY 0x00000000 // 16 retries
+#define EDRV_REGDW_TCR_DEF (EDRV_REGDW_TCR_IFG96 \
+ | EDRV_REGDW_TCR_MXDMAUNL \
+ | EDRV_REGDW_TCR_TXRETRY)
+
+#define EDRV_REGW_MULINT 0x5C // multiple interrupt select register
+
+#define EDRV_REGDW_MPC 0x4C // missed packet counter register
+
+#define EDRV_REGDW_TSAD0 0x20 // Transmit start address of descriptor 0
+#define EDRV_REGDW_TSAD1 0x24 // Transmit start address of descriptor 1
+#define EDRV_REGDW_TSAD2 0x28 // Transmit start address of descriptor 2
+#define EDRV_REGDW_TSAD3 0x2C // Transmit start address of descriptor 3
+#define EDRV_REGDW_TSD0 0x10 // Transmit status of descriptor 0
+#define EDRV_REGDW_TSD_CRS 0x80000000 // Carrier sense lost
+#define EDRV_REGDW_TSD_TABT 0x40000000 // Transmit Abort
+#define EDRV_REGDW_TSD_OWC 0x20000000 // Out of window collision
+#define EDRV_REGDW_TSD_TXTH_DEF 0x00020000 // Transmit FIFO threshold of 64 bytes
+#define EDRV_REGDW_TSD_TOK 0x00008000 // Transmit OK
+#define EDRV_REGDW_TSD_TUN 0x00004000 // Transmit FIFO underrun
+#define EDRV_REGDW_TSD_OWN 0x00002000 // Owner
+
+#define EDRV_REGDW_RBSTART 0x30 // Receive buffer start address
+
+#define EDRV_REGW_CAPR 0x38 // Current address of packet read
+
+#define EDRV_REGDW_IDR0 0x00 // ID register 0
+#define EDRV_REGDW_IDR4 0x04 // ID register 4
+
+#define EDRV_REGDW_MAR0 0x08 // Multicast address register 0
+#define EDRV_REGDW_MAR4 0x0C // Multicast address register 4
+
+// defines for the status word in the receive buffer
+#define EDRV_RXSTAT_MAR 0x8000 // Multicast address received
+#define EDRV_RXSTAT_PAM 0x4000 // Physical address matched
+#define EDRV_RXSTAT_BAR 0x2000 // Broadcast address received
+#define EDRV_RXSTAT_ISE 0x0020 // Invalid symbol error
+#define EDRV_RXSTAT_RUNT 0x0010 // Runt packet received
+#define EDRV_RXSTAT_LONG 0x0008 // Long packet
+#define EDRV_RXSTAT_CRC 0x0004 // CRC error
+#define EDRV_RXSTAT_FAE 0x0002 // Frame alignment error
+#define EDRV_RXSTAT_ROK 0x0001 // Receive OK
+
+#define EDRV_REGDW_WRITE(dwReg, dwVal) writel(dwVal, EdrvInstance_l.m_pIoAddr + dwReg)
+#define EDRV_REGW_WRITE(dwReg, wVal) writew(wVal, EdrvInstance_l.m_pIoAddr + dwReg)
+#define EDRV_REGB_WRITE(dwReg, bVal) writeb(bVal, EdrvInstance_l.m_pIoAddr + dwReg)
+#define EDRV_REGDW_READ(dwReg) readl(EdrvInstance_l.m_pIoAddr + dwReg)
+#define EDRV_REGW_READ(dwReg) readw(EdrvInstance_l.m_pIoAddr + dwReg)
+#define EDRV_REGB_READ(dwReg) readb(EdrvInstance_l.m_pIoAddr + dwReg)
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#define TGT_DBG_POST_TRACE_VALUE(v)
+#endif
+
+#define EDRV_COUNT_SEND TGT_DBG_SIGNAL_TRACE_POINT(2)
+#define EDRV_COUNT_TIMEOUT TGT_DBG_SIGNAL_TRACE_POINT(3)
+#define EDRV_COUNT_PCI_ERR TGT_DBG_SIGNAL_TRACE_POINT(4)
+#define EDRV_COUNT_TX TGT_DBG_SIGNAL_TRACE_POINT(5)
+#define EDRV_COUNT_RX TGT_DBG_SIGNAL_TRACE_POINT(6)
+#define EDRV_COUNT_LATECOLLISION TGT_DBG_SIGNAL_TRACE_POINT(10)
+#define EDRV_COUNT_TX_COL_RL TGT_DBG_SIGNAL_TRACE_POINT(11)
+#define EDRV_COUNT_TX_FUN TGT_DBG_SIGNAL_TRACE_POINT(12)
+#define EDRV_COUNT_TX_ERR TGT_DBG_SIGNAL_TRACE_POINT(13)
+#define EDRV_COUNT_RX_CRC TGT_DBG_SIGNAL_TRACE_POINT(14)
+#define EDRV_COUNT_RX_ERR TGT_DBG_SIGNAL_TRACE_POINT(15)
+#define EDRV_COUNT_RX_FOVW TGT_DBG_SIGNAL_TRACE_POINT(16)
+#define EDRV_COUNT_RX_PUN TGT_DBG_SIGNAL_TRACE_POINT(17)
+#define EDRV_COUNT_RX_FAE TGT_DBG_SIGNAL_TRACE_POINT(18)
+#define EDRV_COUNT_RX_OVW TGT_DBG_SIGNAL_TRACE_POINT(19)
+
+#define EDRV_TRACE_CAPR(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x06000000)
+#define EDRV_TRACE_RX_CRC(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x0E000000)
+#define EDRV_TRACE_RX_ERR(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x0F000000)
+#define EDRV_TRACE_RX_PUN(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF) | 0x11000000)
+#define EDRV_TRACE(x) TGT_DBG_POST_TRACE_VALUE(((x) & 0xFFFF0000) | 0x0000FEC0)
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+/*
+typedef struct
+{
+ BOOL m_fUsed;
+ unsigned int m_uiSize;
+ MCD_bufDescFec *m_pBufDescr;
+
+} tEdrvTxBufferIntern;
+*/
+
+// Private structure
+typedef struct {
+ struct pci_dev *m_pPciDev; // pointer to PCI device structure
+ void *m_pIoAddr; // pointer to register space of Ethernet controller
+ BYTE *m_pbRxBuf; // pointer to Rx buffer
+ dma_addr_t m_pRxBufDma;
+ BYTE *m_pbTxBuf; // pointer to Tx buffer
+ dma_addr_t m_pTxBufDma;
+ BOOL m_afTxBufUsed[EDRV_MAX_TX_BUFFERS];
+ unsigned int m_uiCurTxDesc;
+
+ tEdrvInitParam m_InitParam;
+ tEdrvTxBuffer *m_pLastTransmittedTxBuffer;
+
+} tEdrvInstance;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static int EdrvInitOne(struct pci_dev *pPciDev,
+ const struct pci_device_id *pId);
+
+static void EdrvRemoveOne(struct pci_dev *pPciDev);
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+// buffers and buffer descriptors and pointers
+
+static struct pci_device_id aEdrvPciTbl[] = {
+ {0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, aEdrvPciTbl);
+
+static tEdrvInstance EdrvInstance_l;
+
+static struct pci_driver EdrvDriver = {
+ .name = DRV_NAME,
+ .id_table = aEdrvPciTbl,
+ .probe = EdrvInitOne,
+ .remove = EdrvRemoveOne,
+};
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <edrv> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static BYTE EdrvCalcHash(BYTE * pbMAC_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvInit
+//
+// Description: function for init of the Ethernet controller
+//
+// Parameters: pEdrvInitParam_p = pointer to struct including the init-parameters
+//
+// Returns: Errorcode = kEplSuccessful
+// = kEplNoResource
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvInit(tEdrvInitParam * pEdrvInitParam_p)
+{
+ tEplKernel Ret;
+ int iResult;
+
+ Ret = kEplSuccessful;
+
+ // clear instance structure
+ EPL_MEMSET(&EdrvInstance_l, 0, sizeof(EdrvInstance_l));
+
+ // save the init data
+ EdrvInstance_l.m_InitParam = *pEdrvInitParam_p;
+
+ // register PCI driver
+ iResult = pci_register_driver(&EdrvDriver);
+ if (iResult != 0) {
+ printk("%s pci_register_driver failed with %d\n", __func__,
+ iResult);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ if (EdrvInstance_l.m_pPciDev == NULL) {
+ printk("%s m_pPciDev=NULL\n", __func__);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+ // read MAC address from controller
+ printk("%s local MAC = ", __func__);
+ for (iResult = 0; iResult < 6; iResult++) {
+ pEdrvInitParam_p->m_abMyMacAddr[iResult] =
+ EDRV_REGB_READ((EDRV_REGDW_IDR0 + iResult));
+ printk("%02X ",
+ (unsigned int)pEdrvInitParam_p->m_abMyMacAddr[iResult]);
+ }
+ printk("\n");
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvShutdown
+//
+// Description: Shutdown the Ethernet controller
+//
+// Parameters: void
+//
+// Returns: Errorcode = kEplSuccessful
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvShutdown(void)
+{
+
+ // unregister PCI driver
+ printk("%s calling pci_unregister_driver()\n", __func__);
+ pci_unregister_driver(&EdrvDriver);
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvDefineRxMacAddrEntry
+//
+// Description: Set a multicast entry into the Ethernet controller
+//
+// Parameters: pbMacAddr_p = pointer to multicast entry to set
+//
+// Returns: Errorcode = kEplSuccessful
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvDefineRxMacAddrEntry(BYTE * pbMacAddr_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ DWORD dwData;
+ BYTE bHash;
+
+ bHash = EdrvCalcHash(pbMacAddr_p);
+/*
+ dwData = ether_crc(6, pbMacAddr_p);
+
+ printk("EdrvDefineRxMacAddrEntry('%02X:%02X:%02X:%02X:%02X:%02X') hash = %u / %u ether_crc = 0x%08lX\n",
+ (WORD) pbMacAddr_p[0], (WORD) pbMacAddr_p[1], (WORD) pbMacAddr_p[2],
+ (WORD) pbMacAddr_p[3], (WORD) pbMacAddr_p[4], (WORD) pbMacAddr_p[5],
+ (WORD) bHash, (WORD) (dwData >> 26), dwData);
+*/
+ if (bHash > 31) {
+ dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR4);
+ dwData |= 1 << (bHash - 32);
+ EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, dwData);
+ } else {
+ dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR0);
+ dwData |= 1 << bHash;
+ EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, dwData);
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvUndefineRxMacAddrEntry
+//
+// Description: Reset a multicast entry in the Ethernet controller
+//
+// Parameters: pbMacAddr_p = pointer to multicast entry to reset
+//
+// Returns: Errorcode = kEplSuccessful
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvUndefineRxMacAddrEntry(BYTE * pbMacAddr_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ DWORD dwData;
+ BYTE bHash;
+
+ bHash = EdrvCalcHash(pbMacAddr_p);
+
+ if (bHash > 31) {
+ dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR4);
+ dwData &= ~(1 << (bHash - 32));
+ EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, dwData);
+ } else {
+ dwData = EDRV_REGDW_READ(EDRV_REGDW_MAR0);
+ dwData &= ~(1 << bHash);
+ EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, dwData);
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvAllocTxMsgBuffer
+//
+// Description: Register a Tx-Buffer
+//
+// Parameters: pBuffer_p = pointer to Buffer structure
+//
+// Returns: Errorcode = kEplSuccessful
+// = kEplEdrvNoFreeBufEntry
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvAllocTxMsgBuffer(tEdrvTxBuffer * pBuffer_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ DWORD i;
+
+ if (pBuffer_p->m_uiMaxBufferLen > EDRV_MAX_FRAME_SIZE) {
+ Ret = kEplEdrvNoFreeBufEntry;
+ goto Exit;
+ }
+ // search a free Tx buffer with appropriate size
+ for (i = 0; i < EDRV_MAX_TX_BUFFERS; i++) {
+ if (EdrvInstance_l.m_afTxBufUsed[i] == FALSE) {
+ // free channel found
+ EdrvInstance_l.m_afTxBufUsed[i] = TRUE;
+ pBuffer_p->m_uiBufferNumber = i;
+ pBuffer_p->m_pbBuffer =
+ EdrvInstance_l.m_pbTxBuf +
+ (i * EDRV_MAX_FRAME_SIZE);
+ pBuffer_p->m_uiMaxBufferLen = EDRV_MAX_FRAME_SIZE;
+ break;
+ }
+ }
+ if (i >= EDRV_MAX_TX_BUFFERS) {
+ Ret = kEplEdrvNoFreeBufEntry;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvReleaseTxMsgBuffer
+//
+// Description: Register a Tx-Buffer
+//
+// Parameters: pBuffer_p = pointer to Buffer structure
+//
+// Returns: Errorcode = kEplSuccessful
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvReleaseTxMsgBuffer(tEdrvTxBuffer * pBuffer_p)
+{
+ unsigned int uiBufferNumber;
+
+ uiBufferNumber = pBuffer_p->m_uiBufferNumber;
+
+ if (uiBufferNumber < EDRV_MAX_TX_BUFFERS) {
+ EdrvInstance_l.m_afTxBufUsed[uiBufferNumber] = FALSE;
+ }
+
+ return kEplSuccessful;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvSendTxMsg
+//
+// Description: immediately starts the transmission of the buffer
+//
+// Parameters: pBuffer_p = buffer descriptor to transmit
+//
+// Returns: Errorcode = kEplSuccessful
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvSendTxMsg(tEdrvTxBuffer * pBuffer_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiBufferNumber;
+ DWORD dwTemp;
+
+ uiBufferNumber = pBuffer_p->m_uiBufferNumber;
+
+ if ((uiBufferNumber >= EDRV_MAX_TX_BUFFERS)
+ || (EdrvInstance_l.m_afTxBufUsed[uiBufferNumber] == FALSE)) {
+ Ret = kEplEdrvBufNotExisting;
+ goto Exit;
+ }
+
+ if (EdrvInstance_l.m_pLastTransmittedTxBuffer != NULL) { // transmission is already active
+ Ret = kEplInvalidOperation;
+ dwTemp =
+ EDRV_REGDW_READ((EDRV_REGDW_TSD0 +
+ (EdrvInstance_l.m_uiCurTxDesc *
+ sizeof(DWORD))));
+ printk("%s InvOp TSD%u = 0x%08lX", __func__,
+ EdrvInstance_l.m_uiCurTxDesc, dwTemp);
+ printk(" Cmd = 0x%02X\n",
+ (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
+ goto Exit;
+ }
+ // save pointer to buffer structure for TxHandler
+ EdrvInstance_l.m_pLastTransmittedTxBuffer = pBuffer_p;
+
+ EDRV_COUNT_SEND;
+
+ // pad with zeros if necessary, because controller does not do it
+ if (pBuffer_p->m_uiTxMsgLen < MIN_ETH_SIZE) {
+ EPL_MEMSET(pBuffer_p->m_pbBuffer + pBuffer_p->m_uiTxMsgLen, 0,
+ MIN_ETH_SIZE - pBuffer_p->m_uiTxMsgLen);
+ pBuffer_p->m_uiTxMsgLen = MIN_ETH_SIZE;
+ }
+ // set DMA address of buffer
+ EDRV_REGDW_WRITE((EDRV_REGDW_TSAD0 +
+ (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))),
+ (EdrvInstance_l.m_pTxBufDma +
+ (uiBufferNumber * EDRV_MAX_FRAME_SIZE)));
+ dwTemp =
+ EDRV_REGDW_READ((EDRV_REGDW_TSAD0 +
+ (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))));
+// printk("%s TSAD%u = 0x%08lX", __func__, EdrvInstance_l.m_uiCurTxDesc, dwTemp);
+
+ // start transmission
+ EDRV_REGDW_WRITE((EDRV_REGDW_TSD0 +
+ (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))),
+ (EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen));
+ dwTemp =
+ EDRV_REGDW_READ((EDRV_REGDW_TSD0 +
+ (EdrvInstance_l.m_uiCurTxDesc * sizeof(DWORD))));
+// printk(" TSD%u = 0x%08lX / 0x%08lX\n", EdrvInstance_l.m_uiCurTxDesc, dwTemp, (DWORD)(EDRV_REGDW_TSD_TXTH_DEF | pBuffer_p->m_uiTxMsgLen));
+
+ Exit:
+ return Ret;
+}
+
+#if 0
+//---------------------------------------------------------------------------
+//
+// Function: EdrvTxMsgReady
+//
+// Description: starts copying the buffer to the ethernet controller's FIFO
+//
+// Parameters: pbBuffer_p - bufferdescriptor to transmit
+//
+// Returns: Errorcode - kEplSuccessful
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvTxMsgReady(tEdrvTxBuffer * pBuffer_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiBufferNumber;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvTxMsgStart
+//
+// Description: starts transmission of the ethernet controller's FIFO
+//
+// Parameters: pbBuffer_p - bufferdescriptor to transmit
+//
+// Returns: Errorcode - kEplSuccessful
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel EdrvTxMsgStart(tEdrvTxBuffer * pBuffer_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ return Ret;
+}
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvReinitRx
+//
+// Description: reinitialize the Rx process, because of error
+//
+// Parameters: void
+//
+// Returns: void
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static void EdrvReinitRx(void)
+{
+ BYTE bCmd;
+
+ // simply switch off and on the receiver
+ // this will reset the CAPR register
+ bCmd = EDRV_REGB_READ(EDRV_REGB_COMMAND);
+ EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (bCmd & ~EDRV_REGB_COMMAND_RE));
+ EDRV_REGB_WRITE(EDRV_REGB_COMMAND, bCmd);
+
+ // set receive configuration register
+ EDRV_REGDW_WRITE(EDRV_REGDW_RCR, EDRV_REGDW_RCR_DEF);
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvInterruptHandler
+//
+// Description: interrupt handler
+//
+// Parameters: void
+//
+// Returns: void
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if 0
+void EdrvInterruptHandler(void)
+{
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p)
+#else
+static int TgtEthIsr(int nIrqNum_p, void *ppDevInstData_p,
+ struct pt_regs *ptRegs_p)
+#endif
+{
+// EdrvInterruptHandler();
+ tEdrvRxBuffer RxBuffer;
+ tEdrvTxBuffer *pTxBuffer;
+ WORD wStatus;
+ DWORD dwTxStatus;
+ DWORD dwRxStatus;
+ WORD wCurRx;
+ BYTE *pbRxBuf;
+ unsigned int uiLength;
+ int iHandled = IRQ_HANDLED;
+
+// printk("");
+
+ // read the interrupt status
+ wStatus = EDRV_REGW_READ(EDRV_REGW_INT_STATUS);
+
+ // acknowledge the interrupts
+ EDRV_REGW_WRITE(EDRV_REGW_INT_STATUS, wStatus);
+
+ if (wStatus == 0) {
+ iHandled = IRQ_NONE;
+ goto Exit;
+ }
+ // process tasks
+ if ((wStatus & (EDRV_REGW_INT_TER | EDRV_REGW_INT_TOK)) != 0) { // transmit interrupt
+
+ if (EdrvInstance_l.m_pbTxBuf == NULL) {
+ printk("%s Tx buffers currently not allocated\n",
+ __func__);
+ goto Exit;
+ }
+ // read transmit status
+ dwTxStatus =
+ EDRV_REGDW_READ((EDRV_REGDW_TSD0 +
+ (EdrvInstance_l.m_uiCurTxDesc *
+ sizeof(DWORD))));
+ if ((dwTxStatus & (EDRV_REGDW_TSD_TOK | EDRV_REGDW_TSD_TABT | EDRV_REGDW_TSD_TUN)) != 0) { // transmit finished
+ EdrvInstance_l.m_uiCurTxDesc =
+ (EdrvInstance_l.m_uiCurTxDesc + 1) & 0x03;
+ pTxBuffer = EdrvInstance_l.m_pLastTransmittedTxBuffer;
+ EdrvInstance_l.m_pLastTransmittedTxBuffer = NULL;
+
+ if ((dwTxStatus & EDRV_REGDW_TSD_TOK) != 0) {
+ EDRV_COUNT_TX;
+ } else if ((dwTxStatus & EDRV_REGDW_TSD_TUN) != 0) {
+ EDRV_COUNT_TX_FUN;
+ } else { // assume EDRV_REGDW_TSD_TABT
+ EDRV_COUNT_TX_COL_RL;
+ }
+
+// printk("T");
+ if (pTxBuffer != NULL) {
+ // call Tx handler of Data link layer
+ EdrvInstance_l.m_InitParam.
+ m_pfnTxHandler(pTxBuffer);
+ }
+ } else {
+ EDRV_COUNT_TX_ERR;
+ }
+ }
+
+ if ((wStatus & (EDRV_REGW_INT_RER | EDRV_REGW_INT_FOVW | EDRV_REGW_INT_RXOVW | EDRV_REGW_INT_PUN)) != 0) { // receive error interrupt
+
+ if ((wStatus & EDRV_REGW_INT_FOVW) != 0) {
+ EDRV_COUNT_RX_FOVW;
+ } else if ((wStatus & EDRV_REGW_INT_RXOVW) != 0) {
+ EDRV_COUNT_RX_OVW;
+ } else if ((wStatus & EDRV_REGW_INT_PUN) != 0) { // Packet underrun
+ EDRV_TRACE_RX_PUN(wStatus);
+ EDRV_COUNT_RX_PUN;
+ } else { /*if ((wStatus & EDRV_REGW_INT_RER) != 0) */
+
+ EDRV_TRACE_RX_ERR(wStatus);
+ EDRV_COUNT_RX_ERR;
+ }
+
+ // reinitialize Rx process
+ EdrvReinitRx();
+ }
+
+ if ((wStatus & EDRV_REGW_INT_ROK) != 0) { // receive interrupt
+
+ if (EdrvInstance_l.m_pbRxBuf == NULL) {
+ printk("%s Rx buffers currently not allocated\n",
+ __func__);
+ goto Exit;
+ }
+ // read current offset in receive buffer
+ wCurRx =
+ (EDRV_REGW_READ(EDRV_REGW_CAPR) +
+ 0x10) % EDRV_RX_BUFFER_LENGTH;
+
+ while ((EDRV_REGB_READ(EDRV_REGB_COMMAND) & EDRV_REGB_COMMAND_BUFE) == 0) { // frame available
+
+ // calculate pointer to current frame in receive buffer
+ pbRxBuf = EdrvInstance_l.m_pbRxBuf + wCurRx;
+
+ // read receive status DWORD
+ dwRxStatus = le32_to_cpu(*((DWORD *) pbRxBuf));
+
+ // calculate length of received frame
+ uiLength = dwRxStatus >> 16;
+
+ if (uiLength == 0xFFF0) { // frame is unfinished (maybe early Rx interrupt is active)
+ break;
+ }
+
+ if ((dwRxStatus & EDRV_RXSTAT_ROK) == 0) { // error occured while receiving this frame
+ // ignore it
+ if ((dwRxStatus & EDRV_RXSTAT_FAE) != 0) {
+ EDRV_COUNT_RX_FAE;
+ } else if ((dwRxStatus & EDRV_RXSTAT_CRC) != 0) {
+ EDRV_TRACE_RX_CRC(dwRxStatus);
+ EDRV_COUNT_RX_CRC;
+ } else {
+ EDRV_TRACE_RX_ERR(dwRxStatus);
+ EDRV_COUNT_RX_ERR;
+ }
+
+ // reinitialize Rx process
+ EdrvReinitRx();
+
+ break;
+ } else { // frame is OK
+ RxBuffer.m_BufferInFrame =
+ kEdrvBufferLastInFrame;
+ RxBuffer.m_uiRxMsgLen = uiLength - ETH_CRC_SIZE;
+ RxBuffer.m_pbBuffer =
+ pbRxBuf + sizeof(dwRxStatus);
+
+// printk("R");
+ EDRV_COUNT_RX;
+
+ // call Rx handler of Data link layer
+ EdrvInstance_l.m_InitParam.
+ m_pfnRxHandler(&RxBuffer);
+ }
+
+ // calulate new offset (DWORD aligned)
+ wCurRx =
+ (WORD) ((wCurRx + uiLength + sizeof(dwRxStatus) +
+ 3) & ~0x3);
+ EDRV_TRACE_CAPR(wCurRx - 0x10);
+ EDRV_REGW_WRITE(EDRV_REGW_CAPR, wCurRx - 0x10);
+
+ // reread current offset in receive buffer
+ wCurRx =
+ (EDRV_REGW_READ(EDRV_REGW_CAPR) +
+ 0x10) % EDRV_RX_BUFFER_LENGTH;
+
+ }
+ }
+
+ if ((wStatus & EDRV_REGW_INT_SERR) != 0) { // PCI error
+ EDRV_COUNT_PCI_ERR;
+ }
+
+ if ((wStatus & EDRV_REGW_INT_TIMEOUT) != 0) { // Timeout
+ EDRV_COUNT_TIMEOUT;
+ }
+
+ Exit:
+ return iHandled;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvInitOne
+//
+// Description: initializes one PCI device
+//
+// Parameters: pPciDev = pointer to corresponding PCI device structure
+// pId = PCI device ID
+//
+// Returns: (int) = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static int EdrvInitOne(struct pci_dev *pPciDev, const struct pci_device_id *pId)
+{
+ int iResult = 0;
+ DWORD dwTemp;
+
+ if (EdrvInstance_l.m_pPciDev != NULL) { // Edrv is already connected to a PCI device
+ printk("%s device %s discarded\n", __func__,
+ pci_name(pPciDev));
+ iResult = -ENODEV;
+ goto Exit;
+ }
+
+ if (pPciDev->revision >= 0x20) {
+ printk
+ ("%s device %s is an enhanced 8139C+ version, which is not supported\n",
+ __func__, pci_name(pPciDev));
+ iResult = -ENODEV;
+ goto Exit;
+ }
+
+ EdrvInstance_l.m_pPciDev = pPciDev;
+
+ // enable device
+ printk("%s enable device\n", __func__);
+ iResult = pci_enable_device(pPciDev);
+ if (iResult != 0) {
+ goto Exit;
+ }
+
+ if ((pci_resource_flags(pPciDev, 1) & IORESOURCE_MEM) == 0) {
+ iResult = -ENODEV;
+ goto Exit;
+ }
+
+ printk("%s request regions\n", __func__);
+ iResult = pci_request_regions(pPciDev, DRV_NAME);
+ if (iResult != 0) {
+ goto Exit;
+ }
+
+ printk("%s ioremap\n", __func__);
+ EdrvInstance_l.m_pIoAddr =
+ ioremap(pci_resource_start(pPciDev, 1),
+ pci_resource_len(pPciDev, 1));
+ if (EdrvInstance_l.m_pIoAddr == NULL) { // remap of controller's register space failed
+ iResult = -EIO;
+ goto Exit;
+ }
+ // enable PCI busmaster
+ printk("%s enable busmaster\n", __func__);
+ pci_set_master(pPciDev);
+
+ // reset controller
+ printk("%s reset controller\n", __func__);
+ EDRV_REGB_WRITE(EDRV_REGB_COMMAND, EDRV_REGB_COMMAND_RST);
+
+ // wait until reset has finished
+ for (iResult = 500; iResult > 0; iResult--) {
+ if ((EDRV_REGB_READ(EDRV_REGB_COMMAND) & EDRV_REGB_COMMAND_RST)
+ == 0) {
+ break;
+ }
+
+ schedule_timeout(10);
+ }
+
+ // check hardware version, i.e. chip ID
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TCR);
+ if (((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_C)
+ && ((dwTemp & EDRV_REGDW_TCR_VER_MASK) != EDRV_REGDW_TCR_VER_D)) { // unsupported chip
+ printk("%s Unsupported chip! TCR = 0x%08lX\n", __func__,
+ dwTemp);
+ iResult = -ENODEV;
+ goto Exit;
+ }
+ // disable interrupts
+ printk("%s disable interrupts\n", __func__);
+ EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, 0);
+ // acknowledge all pending interrupts
+ EDRV_REGW_WRITE(EDRV_REGW_INT_STATUS,
+ EDRV_REGW_READ(EDRV_REGW_INT_STATUS));
+
+ // install interrupt handler
+ printk("%s install interrupt handler\n", __func__);
+ iResult =
+ request_irq(pPciDev->irq, TgtEthIsr, IRQF_SHARED,
+ DRV_NAME /*pPciDev->dev.name */ , pPciDev);
+ if (iResult != 0) {
+ goto Exit;
+ }
+
+/*
+ // unlock configuration registers
+ printk("%s unlock configuration registers\n", __func__);
+ EDRV_REGB_WRITE(EDRV_REGB_CMD9346, EDRV_REGB_CMD9346_UNLOCK);
+
+ // check if user specified a MAC address
+ printk("%s check specified MAC address\n", __func__);
+ for (iResult = 0; iResult < 6; iResult++)
+ {
+ if (EdrvInstance_l.m_InitParam.m_abMyMacAddr[iResult] != 0)
+ {
+ printk("%s set local MAC address\n", __func__);
+ // write this MAC address to controller
+ EDRV_REGDW_WRITE(EDRV_REGDW_IDR0,
+ le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[0])));
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR0);
+
+ EDRV_REGDW_WRITE(EDRV_REGDW_IDR4,
+ le32_to_cpu(*((DWORD*)&EdrvInstance_l.m_InitParam.m_abMyMacAddr[4])));
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_IDR4);
+ break;
+ }
+ }
+ iResult = 0;
+
+ // lock configuration registers
+ EDRV_REGB_WRITE(EDRV_REGB_CMD9346, EDRV_REGB_CMD9346_LOCK);
+*/
+
+ // allocate buffers
+ printk("%s allocate buffers\n", __func__);
+ EdrvInstance_l.m_pbTxBuf =
+ pci_alloc_consistent(pPciDev, EDRV_TX_BUFFER_SIZE,
+ &EdrvInstance_l.m_pTxBufDma);
+ if (EdrvInstance_l.m_pbTxBuf == NULL) {
+ iResult = -ENOMEM;
+ goto Exit;
+ }
+
+ EdrvInstance_l.m_pbRxBuf =
+ pci_alloc_consistent(pPciDev, EDRV_RX_BUFFER_SIZE,
+ &EdrvInstance_l.m_pRxBufDma);
+ if (EdrvInstance_l.m_pbRxBuf == NULL) {
+ iResult = -ENOMEM;
+ goto Exit;
+ }
+ // reset pointers for Tx buffers
+ printk("%s reset pointers fo Tx buffers\n", __func__);
+ EDRV_REGDW_WRITE(EDRV_REGDW_TSAD0, 0);
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD0);
+ EDRV_REGDW_WRITE(EDRV_REGDW_TSAD1, 0);
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD1);
+ EDRV_REGDW_WRITE(EDRV_REGDW_TSAD2, 0);
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD2);
+ EDRV_REGDW_WRITE(EDRV_REGDW_TSAD3, 0);
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_TSAD3);
+
+ printk(" Command = 0x%02X\n",
+ (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
+
+ // set pointer for receive buffer in controller
+ printk("%s set pointer to Rx buffer\n", __func__);
+ EDRV_REGDW_WRITE(EDRV_REGDW_RBSTART, EdrvInstance_l.m_pRxBufDma);
+
+ // enable transmitter and receiver
+ printk("%s enable Tx and Rx", __func__);
+ EDRV_REGB_WRITE(EDRV_REGB_COMMAND,
+ (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE));
+ printk(" Command = 0x%02X\n",
+ (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
+
+ // clear missed packet counter to enable Rx/Tx process
+ EDRV_REGDW_WRITE(EDRV_REGDW_MPC, 0);
+
+ // set transmit configuration register
+ printk("%s set Tx conf register", __func__);
+ EDRV_REGDW_WRITE(EDRV_REGDW_TCR, EDRV_REGDW_TCR_DEF);
+ printk(" = 0x%08X\n", EDRV_REGDW_READ(EDRV_REGDW_TCR));
+
+ // set receive configuration register
+ printk("%s set Rx conf register", __func__);
+ EDRV_REGDW_WRITE(EDRV_REGDW_RCR, EDRV_REGDW_RCR_DEF);
+ printk(" = 0x%08X\n", EDRV_REGDW_READ(EDRV_REGDW_RCR));
+
+ // reset multicast MAC address filter
+ EDRV_REGDW_WRITE(EDRV_REGDW_MAR0, 0);
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_MAR0);
+ EDRV_REGDW_WRITE(EDRV_REGDW_MAR4, 0);
+ dwTemp = EDRV_REGDW_READ(EDRV_REGDW_MAR4);
+
+/*
+ // enable transmitter and receiver
+ printk("%s enable Tx and Rx", __func__);
+ EDRV_REGB_WRITE(EDRV_REGB_COMMAND, (EDRV_REGB_COMMAND_RE | EDRV_REGB_COMMAND_TE));
+ printk(" Command = 0x%02X\n", (WORD) EDRV_REGB_READ(EDRV_REGB_COMMAND));
+*/
+ // disable early interrupts
+ EDRV_REGW_WRITE(EDRV_REGW_MULINT, 0);
+
+ // enable interrupts
+ printk("%s enable interrupts\n", __func__);
+ EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, EDRV_REGW_INT_MASK_DEF);
+
+ Exit:
+ printk("%s finished with %d\n", __func__, iResult);
+ return iResult;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvRemoveOne
+//
+// Description: shuts down one PCI device
+//
+// Parameters: pPciDev = pointer to corresponding PCI device structure
+//
+// Returns: (void)
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static void EdrvRemoveOne(struct pci_dev *pPciDev)
+{
+
+ if (EdrvInstance_l.m_pPciDev != pPciDev) { // trying to remove unknown device
+ BUG_ON(EdrvInstance_l.m_pPciDev != pPciDev);
+ goto Exit;
+ }
+ // disable transmitter and receiver
+ EDRV_REGB_WRITE(EDRV_REGB_COMMAND, 0);
+
+ // disable interrupts
+ EDRV_REGW_WRITE(EDRV_REGW_INT_MASK, 0);
+
+ // remove interrupt handler
+ free_irq(pPciDev->irq, pPciDev);
+
+ // free buffers
+ if (EdrvInstance_l.m_pbTxBuf != NULL) {
+ pci_free_consistent(pPciDev, EDRV_TX_BUFFER_SIZE,
+ EdrvInstance_l.m_pbTxBuf,
+ EdrvInstance_l.m_pTxBufDma);
+ EdrvInstance_l.m_pbTxBuf = NULL;
+ }
+
+ if (EdrvInstance_l.m_pbRxBuf != NULL) {
+ pci_free_consistent(pPciDev, EDRV_RX_BUFFER_SIZE,
+ EdrvInstance_l.m_pbRxBuf,
+ EdrvInstance_l.m_pRxBufDma);
+ EdrvInstance_l.m_pbRxBuf = NULL;
+ }
+ // unmap controller's register space
+ if (EdrvInstance_l.m_pIoAddr != NULL) {
+ iounmap(EdrvInstance_l.m_pIoAddr);
+ }
+ // disable the PCI device
+ pci_disable_device(pPciDev);
+
+ // release memory regions
+ pci_release_regions(pPciDev);
+
+ EdrvInstance_l.m_pPciDev = NULL;
+
+ Exit:;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EdrvCalcHash
+//
+// Description: function calculates the entry for the hash-table from MAC
+// address
+//
+// Parameters: pbMAC_p - pointer to MAC address
+//
+// Returns: hash value
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#define HASH_BITS 6 // used bits in hash
+#define CRC32_POLY 0x04C11DB6 //
+//#define CRC32_POLY 0xEDB88320 //
+// G(x) = x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1
+
+static BYTE EdrvCalcHash(BYTE * pbMAC_p)
+{
+ DWORD dwByteCounter;
+ DWORD dwBitCounter;
+ DWORD dwData;
+ DWORD dwCrc;
+ DWORD dwCarry;
+ BYTE *pbData;
+ BYTE bHash;
+
+ pbData = pbMAC_p;
+
+ // calculate crc32 value of mac address
+ dwCrc = 0xFFFFFFFF;
+
+ for (dwByteCounter = 0; dwByteCounter < 6; dwByteCounter++) {
+ dwData = *pbData;
+ pbData++;
+ for (dwBitCounter = 0; dwBitCounter < 8;
+ dwBitCounter++, dwData >>= 1) {
+ dwCarry = (((dwCrc >> 31) ^ dwData) & 1);
+ dwCrc = dwCrc << 1;
+ if (dwCarry != 0) {
+ dwCrc = (dwCrc ^ CRC32_POLY) | dwCarry;
+ }
+ }
+ }
+
+// printk("MyCRC = 0x%08lX\n", dwCrc);
+ // only upper 6 bits (HASH_BITS) are used
+ // which point to specific bit in the hash registers
+ bHash = (BYTE) ((dwCrc >> (32 - HASH_BITS)) & 0x3f);
+
+ return bHash;
+}
diff --git a/drivers/staging/epl/EdrvFec.h b/drivers/staging/epl/EdrvFec.h
new file mode 100644
index 000000000000..5f252fbed744
--- /dev/null
+++ b/drivers/staging/epl/EdrvFec.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: interface for ethernetdriver
+ "fast ethernet controller" (FEC)
+ freescale coldfire MCF528x and compatible FEC
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EdrvFec.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ Dev C++ and GNU-Compiler for m68k
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2005/08/01 m.b.: start of implementation
+
+****************************************************************************/
+
+#ifndef _EDRVFEC_H_
+#define _EDRVFEC_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+// do this in config header
+#define TARGET_HARDWARE TGTHW_SPLC_CF54
+
+// base addresses
+#if ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5282)
+
+#elif ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5485)
+
+#else
+
+#error 'ERROR: Target was never implemented!'
+
+#endif
+
+//---------------------------------------------------------------------------
+// types
+//---------------------------------------------------------------------------
+
+// Rx and Tx buffer descriptor format
+typedef struct {
+ WORD m_wStatus; // control / status --- used by edrv, do not change in application
+ WORD m_wLength; // transfer length
+ BYTE *m_pbData; // buffer address
+} tBufferDescr;
+
+#if ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5282)
+
+#elif ((TARGET_HARDWARE & TGT_CPU_MASK_) == TGT_CPU_5485)
+
+#endif
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EDRV_FEC_H_
diff --git a/drivers/staging/epl/EdrvFec5282.h b/drivers/staging/epl/EdrvFec5282.h
new file mode 100644
index 000000000000..a16bb1d4da79
--- /dev/null
+++ b/drivers/staging/epl/EdrvFec5282.h
@@ -0,0 +1,340 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: interface for ethernetdriver
+ "fast ethernet controller" (FEC)
+ freescale coldfire MCF528x and compatible FEC
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EdrvFec5282.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ Dev C++ and GNU-Compiler for m68k
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2005/08/01 m.b.: start of implementation
+
+****************************************************************************/
+
+#ifndef _EDRVFEC_H_
+#define _EDRVFEC_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+// base addresses
+#define FEC0_ADDR 0x0000
+#define FEC1_ADDR 0x0000 //tbd
+
+// control / status registers
+#define FEC_EIR 0x1004 // interrupt event register
+#define FEC_EIMR 0x1008 // interrupt mask register
+#define FEC_RDAR 0x1010 // receive descriptor active register
+#define FEC_TDAR 0x1014 // transmit descriptor active register
+#define FEC_ECR 0x1024 // ethernet control register
+#define FEC_MMFR 0x1040 // MII data register
+#define FEC_MSCR 0x1044 // MII speed register
+#define FEC_MIBC 0x1064 // MIB control/status register
+#define FEC_RCR 0x1084 // receive control register
+#define FEC_TCR 0x10C4 // transmit control register
+#define FEC_PALR 0x10E4 // physical address low register
+#define FEC_PAUR 0x10E8 // physical address high + type register
+#define FEC_OPD 0x10EC // opcode + pause register
+#define FEC_IAUR 0x1118 // upper 32 bit of individual hash table
+#define FEC_IALR 0x111C // lower 32 bit of individual hash table
+#define FEC_GAUR 0x1120 // upper 32 bit of group hash table
+#define FEC_GALR 0x1124 // lower 32 bit of group hash table
+#define FEC_TFWR 0x1144 // transmit FIFO watermark
+#define FEC_FRBR 0x114C // FIFO receive bound register
+#define FEC_FRSR 0x1150 // FIFO receive FIFO start register
+#define FEC_ERDSR 0x1180 // pointer to receive descriptor ring
+#define FEC_ETDSR 0x1184 // pointer to transmit descriptor ring
+#define FEC_EMRBR 0x1188 // maximum receive buffer size
+
+// mib block counters memory map
+#define FEC_RMON_T_DROP 0x1200 // count of frames not counted correctly
+#define FEC_RMON_T_PACKETS 0x1204 // RMON tx packet count
+#define FEC_RMON_T_BC_PKT 0x1208 // RMON tx broadcast packets
+#define FEC_RMON_T_MC_PKT 0x120C // RMON tx multicast packets
+#define FEC_RMON_T_CRC_ALIGN 0x1210 // RMON tx packets w CRC/align error
+#define FEC_RMON_T_UNDERSIZE 0x1214 // RMON tx packets < 64 bytes, good CRC
+#define FEC_RMON_T_OVERSIZE 0x1218 // RMON tx packets > MAX_FL bytes, good CRC
+#define FEC_RMON_T_FRAG 0x121C // RMON tx packets < 64 bytes, bad CRC
+#define FEC_RMON_T_JAB 0x1220 // RMON tx packets > MAX_FL bytes, bad CRC
+#define FEC_RMON_T_COL 0x1224 // RMON tx collision count
+#define FEC_RMON_T_P64 0x1228 // RMON tx 64 byte packets
+#define FEC_RMON_T_P65TO127 0x122C // RMON tx 65 to 127 byte packets
+#define FEC_RMON_T_P128TO255 0x1230 // RMON tx 128 to 255 byte packets
+#define FEC_RMON_T_P256TO511 0x1234 // RMON tx 256 to 511 byte packets
+#define FEC_RMON_T_P512TO1023 0x1238 // RMON tx 512 to 1023 byte packets
+#define FEC_RMON_T_P1024TO2047 0x123C // RMON tx 1024 to 2047 byte packets
+#define FEC_RMON_T_P_GTE2048 0x1240 // RMON tx w > 2048 bytes
+#define FEC_RMON_T_OCTETS 0x1244 // RMON tx octets
+#define FEC_IEEE_T_DROP 0x1248 // count of frames not counted correctly
+#define FEC_IEEE_T_FRAME_OK 0x124C // frames transmitted OK
+#define FEC_IEEE_T_1COL 0x1250 // frames transmitted with single collision
+#define FEC_IEEE_T_MCOL 0x1254 // frames transmitted with multiple collisions
+#define FEC_IEEE_T_DEF 0x1258 // frames transmitted after deferral delay
+#define FEC_IEEE_T_LCOL 0x125C // frames transmitted with late collisions
+#define FEC_IEEE_T_EXCOL 0x1260 // frames transmitted with excessive collisions
+#define FEC_IEEE_T_MACERR 0x1264 // frames transmitted with tx-FIFO underrun
+#define FEC_IEEE_T_CSERR 0x1268 // frames transmitted with carrier sense error
+#define FEC_IEEE_T_SQE 0x126C // frames transmitted with SQE error
+#define FEC_IEEE_T_FDXFC 0x1270 // flow control pause frames transmitted
+#define FEC_IEEE_T_OCTETS_OK 0x1274 // octet count for frames transmitted w/o error
+#define FEC_RMON_R_PACKETS 0x1284 // RMON rx packet count
+#define FEC_RMON_R_BC_PKT 0x1288 // RMON rx broadcast packets
+#define FEC_RMON_R_MC_PKT 0x128C // RMON rx multicast packets
+#define FEC_RMON_R_CRC_ALIGN 0x1290 // RMON rx packets w CRC/align error
+#define FEC_RMON_R_UNDERSIZE 0x1294 // RMON rx packets < 64 bytes, good CRC
+#define FEC_RMON_R_OVERSIZE 0x1298 // RMON rx packets > MAX_FL bytes, good CRC
+#define FEC_RMON_R_FRAG 0x129C // RMON rx packets < 64 bytes, bad CRC
+#define FEC_RMON_R_JAB 0x12A0 // RMON rx packets > MAX_FL bytes, bad CRC
+#define FEC_RMON_R_RESVD_0 0x12A4 //
+#define FEC_RMON_R_P64 0x12A8 // RMON rx 64 byte packets
+#define FEC_RMON_R_P65T0127 0x12AC // RMON rx 65 to 127 byte packets
+#define FEC_RMON_R_P128TO255 0x12B0 // RMON rx 128 to 255 byte packets
+#define FEC_RMON_R_P256TO511 0x12B4 // RMON rx 256 to 511 byte packets
+#define FEC_RMON_R_P512TO1023 0x12B8 // RMON rx 512 to 1023 byte packets
+#define FEC_RMON_R_P1024TO2047 0x12BC // RMON rx 1024 to 2047 byte packets
+#define FEC_RMON_R_GTE2048 0x12C0 // RMON rx w > 2048 bytes
+#define FEC_RMON_R_OCTETS 0x12C4 // RMON rx octets
+#define FEC_IEEE_R_DROP 0x12C8 // count of frames not counted correctly
+#define FEC_IEEE_R_FRAME_OK 0x12CC // frames received OK
+#define FEC_IEEE_R_CRC 0x12D0 // frames received with CRC error
+#define FEC_IEEE_R_ALIGN 0x12D4 // frames received with alignment error
+#define FEC_IEEE_R_MACERR 0x12D8 // receive FIFO overflow count
+#define FEC_IEEE_R_FDXFC 0x12DC // flow control pause frames received
+#define FEC_IEEE_R_OCTETS_OK 0x12E0 // octet count for frames rcvd w/o error
+
+// register bit definitions and macros
+#define FEC_EIR_UN (0x00080000)
+#define FEC_EIR_RL (0x00100000)
+#define FEC_EIR_LC (0x00200000)
+#define FEC_EIR_EBERR (0x00400000)
+#define FEC_EIR_MII (0x00800000)
+#define FEC_EIR_RXB (0x01000000)
+#define FEC_EIR_RXF (0x02000000)
+#define FEC_EIR_TXB (0x04000000)
+#define FEC_EIR_TXF (0x08000000)
+#define FEC_EIR_GRA (0x10000000)
+#define FEC_EIR_BABT (0x20000000)
+#define FEC_EIR_BABR (0x40000000)
+#define FEC_EIR_HBERR (0x80000000)
+
+#define FEC_EIMR_UN (0x00080000)
+#define FEC_EIMR_RL (0x00100000)
+#define FEC_EIMR_LC (0x00200000)
+#define FEC_EIMR_EBERR (0x00400000)
+#define FEC_EIMR_MII (0x00800000)
+#define FEC_EIMR_RXB (0x01000000)
+#define FEC_EIMR_RXF (0x02000000)
+#define FEC_EIMR_TXB (0x04000000)
+#define FEC_EIMR_TXF (0x08000000)
+#define FEC_EIMR_GRA (0x10000000)
+#define FEC_EIMR_BABT (0x20000000)
+#define FEC_EIMR_BABR (0x40000000)
+#define FEC_EIMR_HBERR (0x80000000)
+
+#define FEC_RDAR_R_DES_ACTIVE (0x01000000)
+
+#define FEC_TDAR_X_DES_ACTIVE (0x01000000)
+
+#define FEC_ECR_RESET (0x00000001)
+#define FEC_ECR_ETHER_EN (0x00000002)
+
+#define FEC_MMFR_DATA(x) (((x) & 0xFFFF))
+#define FEC_MMFR_TA (0x00020000)
+#define FEC_MMFR_RA(x) (((x) & 0x1F) << 18)
+#define FEC_MMFR_PA(x) (((x) & 0x1F) << 23)
+#define FEC_MMFR_OP_WR (0x10000000)
+#define FEC_MMFR_OP_RD (0x20000000)
+#define FEC_MMFR_ST (0x40000000)
+
+#define FEC_MSCR_MII_SPEED(x) (((x) & 0x1F) << 1)
+#define FEC_MSCR_DIS_PREAMBLE (0x00000008)
+
+#define FEC_MIBC_MIB_IDLE (0x40000000)
+#define FEC_MIBC_MIB_DISABLE (0x80000000)
+
+#define FEC_RCR_LOOP (0x00000001)
+#define FEC_RCR_DRT (0x00000002)
+#define FEC_RCR_MII_MODE (0x00000004)
+#define FEC_RCR_PROM (0x00000008)
+#define FEC_RCR_BC_REJ (0x00000010)
+#define FEC_RCR_FCE (0x00000020)
+#define FEC_RCR_MAX_FL(x) (((x) & 0x07FF) << 16)
+
+#define FEC_TCR_GTS (0x00000001)
+#define FEC_TCR_HBC (0x00000002)
+#define FEC_TCR_FDEN (0x00000004)
+#define FEC_TCR_TFC_PAUSE (0x00000008)
+#define FEC_TCR_RFC_PAUSE (0x00000010)
+
+#define FEC_PALR_BYTE3(x) (((x) & 0xFF) << 0)
+#define FEC_PALR_BYTE2(x) (((x) & 0xFF) << 8)
+#define FEC_PALR_BYTE1(x) (((x) & 0xFF) << 16)
+#define FEC_PALR_BYTE0(x) (((x) & 0xFF) << 24)
+
+//#define FEC_PAUR_TYPE(x) (((x) & 0xFFFF) << 0)
+#define FEC_PAUR_BYTE5(x) (((x) & 0xFF) << 16)
+#define FEC_PAUR_BYTE4(x) (((x) & 0xFF) << 24)
+
+#define FEC_OPD_PAUSE_DUR(x) (((x) & 0xFFFF))
+//#define FEC_OPD_OPCODE(x) (((x) & 0xFFFF) << 16)
+
+//m.b.
+#define FEC_IAUR_BYTE7(x) (((x) & 0xFF) << 0)
+#define FEC_IAUR_BYTE6(x) (((x) & 0xFF) << 8)
+#define FEC_IAUR_BYTE5(x) (((x) & 0xFF) << 16)
+#define FEC_IAUR_BYTE4(x) (((x) & 0xFF) << 24)
+
+#define FEC_IALR_BYTE3(x) (((x) & 0xFF) << 0)
+#define FEC_IALR_BYTE2(x) (((x) & 0xFF) << 8)
+#define FEC_IALR_BYTE1(x) (((x) & 0xFF) << 16)
+#define FEC_IALR_BYTE0(x) (((x) & 0xFF) << 24)
+
+#define FEC_GAUR_BYTE7(x) (((x) & 0xFF) << 0)
+#define FEC_GAUR_BYTE6(x) (((x) & 0xFF) << 8)
+#define FEC_GAUR_BYTE5(x) (((x) & 0xFF) << 16)
+#define FEC_GAUR_BYTE4(x) (((x) & 0xFF) << 24)
+
+#define FEC_GALR_BYTE3(x) (((x) & 0xFF) << 0)
+#define FEC_GALR_BYTE2(x) (((x) & 0xFF) << 8)
+#define FEC_GALR_BYTE1(x) (((x) & 0xFF) << 16)
+#define FEC_GALR_BYTE0(x) (((x) & 0xFF) << 24)
+// ^^^^
+
+#define FEC_TFWR_X_WMRK_64 (0x00000001)
+#define FEC_TFWR_X_WMRK_128 (0x00000002)
+#define FEC_TFWR_X_WMRK_192 (0x00000003)
+
+//m.b.
+#define FEC_FRBR_R_BOUND(x) (((x) & 0xFF) << 2)
+
+//m.b.
+#define FEC_FRSR_R_FSTART(x) (((x) & 0xFF) << 2)
+
+//m.b.
+#define FEC_ERDSR_R_DES_START(x) (((x) & 0x3FFFFFFF) << 2)
+
+//m.b.
+#define FEC_ETSDR_X_DES_START(x) (((x) & 0x3FFFFFFF) << 2)
+
+#define FEC_EMRBR_R_BUF_SIZE(x) (((x) & 0x7F) << 4)
+
+#define FEC_RxBD_TR 0x0001
+#define FEC_RxBD_OV 0x0002
+#define FEC_RxBD_CR 0x0004
+#define FEC_RxBD_NO 0x0010
+#define FEC_RxBD_LG 0x0020
+#define FEC_RxBD_MC 0x0040
+#define FEC_RxBD_BC 0x0080
+#define FEC_RxBD_M 0x0100
+#define FEC_RxBD_L 0x0800
+#define FEC_RxBD_R02 0x1000
+#define FEC_RxBD_W 0x2000
+#define FEC_RxBD_R01 0x4000
+#define FEC_RxBD_INUSE 0x4000
+#define FEC_RxBD_E 0x8000
+
+//m.b.
+//#define FEC_TxBD_CSL 0x0001
+//#define FEC_TxBD_UN 0x0002
+//#define FEC_TxBD_RL 0x0040
+//#define FEC_TxBD_LC 0x0080
+//#define FEC_TxBD_HB 0x0100
+//#define FEC_TxBD_DEF 0x0200
+#define FEC_TxBD_ABC 0x0200
+// ^^^^
+#define FEC_TxBD_TC 0x0400
+#define FEC_TxBD_L 0x0800
+#define FEC_TxBD_TO2 0x1000
+#define FEC_TxBD_W 0x2000
+#define FEC_TxBD_TO1 0x4000
+#define FEC_TxBD_INUSE 0x4000
+#define FEC_TxBD_R 0x8000
+
+//---------------------------------------------------------------------------
+// types
+//---------------------------------------------------------------------------
+
+// Rx and Tx buffer descriptor format
+typedef struct {
+ WORD m_wStatus; // control / status --- used by edrv, do not change in application
+ WORD m_wLength; // transfer length
+ BYTE *m_pbData; // buffer address
+} tBufferDescr;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if (NO_OF_INSTANCES > 1)
+#define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[off]) = val)
+#define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[off]))
+#else
+#if (EDRV_USED_ETH_CTRL == 0)
+#define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[FEC0_ADDR+off]) = val)
+#define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[FEC0_ADDR+off]))
+#else
+#define ECI_WRITE_DW_REG(off,val) (*(DWORD *)(void *)(&__IPSBAR[FEC1_ADDR+off]) = val)
+#define ECI_READ_DW_REG(off) (*(DWORD *)(void *)(&__IPSBAR[FEC1_ADDR+off]))
+#endif
+#endif
+
+#endif // #ifndef _EDRV_FEC_H_
diff --git a/drivers/staging/epl/EdrvSim.h b/drivers/staging/epl/EdrvSim.h
new file mode 100644
index 000000000000..39300e321d6c
--- /dev/null
+++ b/drivers/staging/epl/EdrvSim.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: interface for ethernet driver simulation
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EdrvSim.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ Dev C++ and GNU-Compiler for m68k
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/15 d.k.: start of implementation
+
+****************************************************************************/
+
+#ifndef _EDRVSIM_H_
+#define _EDRVSIM_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+void EdrvRxInterruptHandler(BYTE bBufferInFrame_p, BYTE * pbEthernetData_p,
+ WORD wDataLen_p);
+
+#endif // #ifndef _EDRVSIM_H_
diff --git a/drivers/staging/epl/Epl.h b/drivers/staging/epl/Epl.h
new file mode 100644
index 000000000000..be60f771b63a
--- /dev/null
+++ b/drivers/staging/epl/Epl.h
@@ -0,0 +1,273 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for EPL API layer
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: Epl.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_API_H_
+#define _EPL_API_H_
+
+#include "EplInc.h"
+#include "EplSdo.h"
+#include "EplObd.h"
+#include "EplLed.h"
+#include "EplEvent.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef struct {
+ unsigned int m_uiNodeId;
+ tEplNmtState m_NmtState;
+ tEplNmtNodeEvent m_NodeEvent;
+ WORD m_wErrorCode; // EPL error code if m_NodeEvent == kEplNmtNodeEventError
+ BOOL m_fMandatory;
+
+} tEplApiEventNode;
+
+typedef struct {
+ tEplNmtState m_NmtState; // local NMT state
+ tEplNmtBootEvent m_BootEvent;
+ WORD m_wErrorCode; // EPL error code if m_BootEvent == kEplNmtBootEventError
+
+} tEplApiEventBoot;
+
+typedef struct {
+ tEplLedType m_LedType; // type of the LED (e.g. Status or Error)
+ BOOL m_fOn; // state of the LED (e.g. on or off)
+
+} tEplApiEventLed;
+
+typedef enum {
+ kEplApiEventNmtStateChange = 0x10, // m_NmtStateChange
+// kEplApiEventRequestNmt = 0x11, // m_bNmtCmd
+ kEplApiEventCriticalError = 0x12, // m_InternalError, Stack halted
+ kEplApiEventWarning = 0x13, // m_InternalError, Stack running
+ kEplApiEventNode = 0x20, // m_Node
+ kEplApiEventBoot = 0x21, // m_Boot
+ kEplApiEventSdo = 0x62, // m_Sdo
+ kEplApiEventObdAccess = 0x69, // m_ObdCbParam
+ kEplApiEventLed = 0x70, // m_Led
+
+} tEplApiEventType;
+
+typedef union {
+ tEplEventNmtStateChange m_NmtStateChange;
+ tEplEventError m_InternalError;
+ tEplSdoComFinished m_Sdo;
+ tEplObdCbParam m_ObdCbParam;
+ tEplApiEventNode m_Node;
+ tEplApiEventBoot m_Boot;
+ tEplApiEventLed m_Led;
+
+} tEplApiEventArg;
+
+typedef tEplKernel(PUBLIC ROM * tEplApiCbEvent) (tEplApiEventType EventType_p, // IN: event type (enum)
+ tEplApiEventArg * pEventArg_p, // IN: event argument (union)
+ void GENERIC * pUserArg_p);
+
+typedef struct {
+ unsigned int m_uiSizeOfStruct;
+ BOOL m_fAsyncOnly; // do not need to register PRes
+ unsigned int m_uiNodeId; // local node ID
+ BYTE m_abMacAddress[6]; // local MAC address
+
+ // 0x1F82: NMT_FeatureFlags_U32
+ DWORD m_dwFeatureFlags;
+ // Cycle Length (0x1006: NMT_CycleLen_U32) in [us]
+ DWORD m_dwCycleLen; // required for error detection
+ // 0x1F98: NMT_CycleTiming_REC
+ // 0x1F98.1: IsochrTxMaxPayload_U16
+ unsigned int m_uiIsochrTxMaxPayload; // const
+ // 0x1F98.2: IsochrRxMaxPayload_U16
+ unsigned int m_uiIsochrRxMaxPayload; // const
+ // 0x1F98.3: PResMaxLatency_U32
+ DWORD m_dwPresMaxLatency; // const in [ns], only required for IdentRes
+ // 0x1F98.4: PReqActPayloadLimit_U16
+ unsigned int m_uiPreqActPayloadLimit; // required for initialisation (+28 bytes)
+ // 0x1F98.5: PResActPayloadLimit_U16
+ unsigned int m_uiPresActPayloadLimit; // required for initialisation of Pres frame (+28 bytes)
+ // 0x1F98.6: ASndMaxLatency_U32
+ DWORD m_dwAsndMaxLatency; // const in [ns], only required for IdentRes
+ // 0x1F98.7: MultiplCycleCnt_U8
+ unsigned int m_uiMultiplCycleCnt; // required for error detection
+ // 0x1F98.8: AsyncMTU_U16
+ unsigned int m_uiAsyncMtu; // required to set up max frame size
+ // 0x1F98.9: Prescaler_U16
+ unsigned int m_uiPrescaler; // required for sync
+ // $$$ Multiplexed Slot
+
+ // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns]
+ DWORD m_dwLossOfFrameTolerance;
+
+ // 0x1F8A: NMT_MNCycleTiming_REC
+ // 0x1F8A.1: WaitSoCPReq_U32 in [ns]
+ DWORD m_dwWaitSocPreq;
+
+ // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns]
+ DWORD m_dwAsyncSlotTimeout;
+
+ DWORD m_dwDeviceType; // NMT_DeviceType_U32
+ DWORD m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32
+ DWORD m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32
+ DWORD m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32
+ DWORD m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32
+ QWORD m_qwVendorSpecificExt1;
+ DWORD m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
+ DWORD m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
+ DWORD m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
+ DWORD m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
+ DWORD m_dwIpAddress;
+ DWORD m_dwSubnetMask;
+ DWORD m_dwDefaultGateway;
+ BYTE m_sHostname[32];
+ BYTE m_abVendorSpecificExt2[48];
+
+ char *m_pszDevName; // NMT_ManufactDevName_VS (0x1008/0 local OD)
+ char *m_pszHwVersion; // NMT_ManufactHwVers_VS (0x1009/0 local OD)
+ char *m_pszSwVersion; // NMT_ManufactSwVers_VS (0x100A/0 local OD)
+
+ tEplApiCbEvent m_pfnCbEvent;
+ void *m_pEventUserArg;
+ tEplSyncCb m_pfnCbSync;
+
+} tEplApiInitParam;
+
+typedef struct {
+ void *m_pImage;
+ unsigned int m_uiSize;
+
+} tEplApiProcessImage;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p);
+
+tEplKernel PUBLIC EplApiShutdown(void);
+
+tEplKernel PUBLIC EplApiReadObject(tEplSdoComConHdl * pSdoComConHdl_p,
+ unsigned int uiNodeId_p,
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pDstData_le_p,
+ unsigned int *puiSize_p,
+ tEplSdoType SdoType_p, void *pUserArg_p);
+
+tEplKernel PUBLIC EplApiWriteObject(tEplSdoComConHdl * pSdoComConHdl_p,
+ unsigned int uiNodeId_p,
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pSrcData_le_p,
+ unsigned int uiSize_p,
+ tEplSdoType SdoType_p, void *pUserArg_p);
+
+tEplKernel PUBLIC EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p);
+
+tEplKernel PUBLIC EplApiReadLocalObject(unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pDstData_p,
+ unsigned int *puiSize_p);
+
+tEplKernel PUBLIC EplApiWriteLocalObject(unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pSrcData_p,
+ unsigned int uiSize_p);
+
+tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p);
+
+tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p,
+ void *pVar_p,
+ unsigned int *puiVarEntries_p,
+ tEplObdSize * pEntrySize_p,
+ unsigned int uiFirstSubindex_p);
+
+tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p);
+
+tEplKernel PUBLIC EplApiProcess(void);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p,
+ tEplNmtNodeCommand NodeCommand_p);
+#endif
+
+tEplKernel PUBLIC EplApiGetIdentResponse(unsigned int uiNodeId_p,
+ tEplIdentResponse **
+ ppIdentResponse_p);
+
+// functions for process image will be implemented in separate file
+tEplKernel PUBLIC EplApiProcessImageSetup(void);
+tEplKernel PUBLIC EplApiProcessImageExchangeIn(tEplApiProcessImage * pPI_p);
+tEplKernel PUBLIC EplApiProcessImageExchangeOut(tEplApiProcessImage * pPI_p);
+
+#endif // #ifndef _EPL_API_H_
diff --git a/drivers/staging/epl/EplAmi.h b/drivers/staging/epl/EplAmi.h
new file mode 100644
index 000000000000..6fa04a4f0a13
--- /dev/null
+++ b/drivers/staging/epl/EplAmi.h
@@ -0,0 +1,362 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: Definitions for Abstract Memory Interface
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplAmi.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.2 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 06.03.2000 -rs
+ Implementation
+
+ 16.09.2002 -as
+ To save code space the functions AmiSetByte and AmiGetByte
+ are replaced by macros. For targets which assign BYTE by
+ an 16Bit type, the definition of macros must changed to
+ functions.
+
+ 23.02.2005 r.d.:
+ Functions included for extended data types such as UNSIGNED24,
+ UNSIGNED40, ...
+
+ 13.06.2006 d.k.:
+ Extended the interface for EPL with the different functions
+ for little endian and big endian
+
+****************************************************************************/
+
+#ifndef _EPLAMI_H_
+#define _EPLAMI_H_
+
+#if ((DEV_SYSTEM & _DEV_64BIT_SUPPORT_) == 0)
+// #ifdef USE_VAR64
+#error 'ERROR: development system does not support 64 bit operations!'
+// #endif
+#endif
+
+//---------------------------------------------------------------------------
+// types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Prototypen
+//---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (TARGET_SYSTEM == _WIN32_)
+#if defined(INLINE_FUNCTION_DEF)
+#undef INLINE_FUNCTION
+#define INLINE_FUNCTION INLINE_FUNCTION_DEF
+#define INLINE_ENABLED TRUE
+#define EPL_AMI_INLINED
+#include "../EplStack/amix86.c"
+#endif
+
+#elif (TARGET_SYSTEM == _LINUX_)
+#if defined(__m68k__) // it is an big endian machine
+#if defined(INLINE_FUNCTION_DEF)
+#undef INLINE_FUNCTION
+#define INLINE_FUNCTION INLINE_FUNCTION_DEF
+#define INLINE_ENABLED TRUE
+#define EPL_AMI_INLINED
+#include "../EplStack/amibe.c"
+#endif
+#endif
+#endif
+
+//---------------------------------------------------------------------------
+//
+// write functions
+//
+// To save code space the function AmiSetByte is replaced by
+// an macro.
+// void PUBLIC AmiSetByte (void FAR* pAddr_p, BYTE bByteVal_p);
+
+#define AmiSetByteToBe(pAddr_p, bByteVal_p) {*(BYTE FAR*)(pAddr_p) = (bByteVal_p);}
+#define AmiSetByteToLe(pAddr_p, bByteVal_p) {*(BYTE FAR*)(pAddr_p) = (bByteVal_p);}
+
+#if !defined(INLINE_ENABLED)
+ void PUBLIC AmiSetWordToBe(void FAR * pAddr_p, WORD wWordVal_p);
+ void PUBLIC AmiSetDwordToBe(void FAR * pAddr_p, DWORD dwDwordVal_p);
+ void PUBLIC AmiSetWordToLe(void FAR * pAddr_p, WORD wWordVal_p);
+ void PUBLIC AmiSetDwordToLe(void FAR * pAddr_p, DWORD dwDwordVal_p);
+#endif
+
+//---------------------------------------------------------------------------
+//
+// read functions
+//
+// To save code space the function AmiGetByte is replaced by
+// an macro.
+// BYTE PUBLIC AmiGetByte (void FAR* pAddr_p);
+
+#define AmiGetByteFromBe(pAddr_p) (*(BYTE FAR*)(pAddr_p))
+#define AmiGetByteFromLe(pAddr_p) (*(BYTE FAR*)(pAddr_p))
+
+#if !defined(INLINE_ENABLED)
+
+ WORD PUBLIC AmiGetWordFromBe(void FAR * pAddr_p);
+ DWORD PUBLIC AmiGetDwordFromBe(void FAR * pAddr_p);
+ WORD PUBLIC AmiGetWordFromLe(void FAR * pAddr_p);
+ DWORD PUBLIC AmiGetDwordFromLe(void FAR * pAddr_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetDword24()
+//
+// Description: sets a 24 bit value to a buffer
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// dwDwordVal_p = value to set
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ void PUBLIC AmiSetDword24ToBe(void FAR * pAddr_p, DWORD dwDwordVal_p);
+ void PUBLIC AmiSetDword24ToLe(void FAR * pAddr_p, DWORD dwDwordVal_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetDword24()
+//
+// Description: reads a 24 bit value from a buffer
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: DWORD = read value
+//
+//---------------------------------------------------------------------------
+
+ DWORD PUBLIC AmiGetDword24FromBe(void FAR * pAddr_p);
+ DWORD PUBLIC AmiGetDword24FromLe(void FAR * pAddr_p);
+
+//#ifdef USE_VAR64
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword40()
+//
+// Description: sets a 40 bit value to a buffer
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ void PUBLIC AmiSetQword40ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+ void PUBLIC AmiSetQword40ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword40()
+//
+// Description: reads a 40 bit value from a buffer
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+//---------------------------------------------------------------------------
+
+ QWORD PUBLIC AmiGetQword40FromBe(void FAR * pAddr_p);
+ QWORD PUBLIC AmiGetQword40FromLe(void FAR * pAddr_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword48()
+//
+// Description: sets a 48 bit value to a buffer
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ void PUBLIC AmiSetQword48ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+ void PUBLIC AmiSetQword48ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword48()
+//
+// Description: reads a 48 bit value from a buffer
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+//---------------------------------------------------------------------------
+
+ QWORD PUBLIC AmiGetQword48FromBe(void FAR * pAddr_p);
+ QWORD PUBLIC AmiGetQword48FromLe(void FAR * pAddr_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword56()
+//
+// Description: sets a 56 bit value to a buffer
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ void PUBLIC AmiSetQword56ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+ void PUBLIC AmiSetQword56ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword56()
+//
+// Description: reads a 56 bit value from a buffer
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+//---------------------------------------------------------------------------
+
+ QWORD PUBLIC AmiGetQword56FromBe(void FAR * pAddr_p);
+ QWORD PUBLIC AmiGetQword56FromLe(void FAR * pAddr_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword64()
+//
+// Description: sets a 64 bit value to a buffer
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ void PUBLIC AmiSetQword64ToBe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+ void PUBLIC AmiSetQword64ToLe(void FAR * pAddr_p, QWORD qwQwordVal_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword64()
+//
+// Description: reads a 64 bit value from a buffer
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ QWORD PUBLIC AmiGetQword64FromBe(void FAR * pAddr_p);
+ QWORD PUBLIC AmiGetQword64FromLe(void FAR * pAddr_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetTimeOfDay()
+//
+// Description: sets a TIME_OF_DAY (CANopen) value to a buffer
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// pTimeOfDay_p = pointer to struct TIME_OF_DAY
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ void PUBLIC AmiSetTimeOfDay(void FAR * pAddr_p,
+ tTimeOfDay FAR * pTimeOfDay_p);
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetTimeOfDay()
+//
+// Description: reads a TIME_OF_DAY (CANopen) value from a buffer
+//
+// Parameters: pAddr_p = pointer to source buffer
+// pTimeOfDay_p = pointer to struct TIME_OF_DAY
+//
+// Return: void
+//
+//---------------------------------------------------------------------------
+
+ void PUBLIC AmiGetTimeOfDay(void FAR * pAddr_p,
+ tTimeOfDay FAR * pTimeOfDay_p);
+
+#endif
+
+#undef INLINE_ENABLED // disable actual inlining of functions
+#define EPL_AMI_INCLUDED
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ifndef _EPLAMI_H_
+// Die letzte Zeile mu unbedingt eine leere Zeile sein, weil manche Compiler// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder).
diff --git a/drivers/staging/epl/EplApiGeneric.c b/drivers/staging/epl/EplApiGeneric.c
new file mode 100644
index 000000000000..ae19e34cd7b3
--- /dev/null
+++ b/drivers/staging/epl/EplApiGeneric.c
@@ -0,0 +1,2060 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for generic EPL API module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplApiGeneric.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.21 $ $Date: 2008/11/21 09:00:38 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/09/05 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "Epl.h"
+#include "kernel/EplDllk.h"
+#include "kernel/EplErrorHandlerk.h"
+#include "kernel/EplEventk.h"
+#include "kernel/EplNmtk.h"
+#include "kernel/EplObdk.h"
+#include "kernel/EplTimerk.h"
+#include "kernel/EplDllkCal.h"
+#include "kernel/EplPdokCal.h"
+#include "user/EplDlluCal.h"
+#include "user/EplLedu.h"
+#include "user/EplNmtCnu.h"
+#include "user/EplNmtMnu.h"
+#include "user/EplSdoComu.h"
+#include "user/EplIdentu.h"
+#include "user/EplStatusu.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+#include "kernel/EplPdok.h"
+#endif
+
+#include "SharedBuff.h"
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0)
+#error "EPL API layer needs EPL module OBDK!"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplApi */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ tEplApiInitParam m_InitParam;
+
+} tEplApiInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+static tEplApiInstance EplApiInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+// NMT state change event callback function
+static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange
+ NmtStateChange_p);
+
+// update DLL configuration from OD
+static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p);
+
+// update OD from init param
+static tEplKernel PUBLIC EplApiUpdateObd(void);
+
+// process events from user event queue
+static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent * pEplEvent_p);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+// callback function of SDO module
+static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished * pSdoComFinished_p);
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+// callback functions of NmtMnu module
+static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p,
+ tEplNmtNodeEvent NodeEvent_p,
+ tEplNmtState NmtState_p,
+ WORD wErrorCode_p,
+ BOOL fMandatory_p);
+
+static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p,
+ tEplNmtState NmtState_p,
+ WORD wErrorCode_p);
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+// callback function of Ledu module
+static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p,
+ BOOL fOn_p);
+#endif
+
+// OD initialization function (implemented in Objdict.c)
+tEplKernel PUBLIC EplObdInitRam(tEplObdInitParam MEM * pInitParam_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiInitialize()
+//
+// Description: add and initialize new instance of EPL stack.
+// After return from this function the application must start
+// the NMT state machine via
+// EplApiExecNmtCommand(kEplNmtEventSwReset)
+// and thereby the whole EPL stack :-)
+//
+// Parameters: pInitParam_p = initialisation parameters
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiInitialize(tEplApiInitParam * pInitParam_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplObdInitParam ObdInitParam;
+ tEplDllkInitParam DllkInitParam;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+#endif
+
+ // reset instance structure
+ EPL_MEMSET(&EplApiInstance_g, 0, sizeof(EplApiInstance_g));
+
+ EPL_MEMCPY(&EplApiInstance_g.m_InitParam, pInitParam_p,
+ min(sizeof(tEplApiInitParam),
+ pInitParam_p->m_uiSizeOfStruct));
+
+ // check event callback function pointer
+ if (EplApiInstance_g.m_InitParam.m_pfnCbEvent == NULL) { // application must always have an event callback function
+ Ret = kEplApiInvalidParam;
+ goto Exit;
+ }
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ // init OD
+// FIXME
+// Ret = EplObdInitRam(&ObdInitParam);
+// if (Ret != kEplSuccessful)
+// {
+// goto Exit;
+// }
+
+ // initialize EplObd module
+ Ret = EplObdInit(&ObdInitParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+#ifndef EPL_NO_FIFO
+ ShbError = ShbInit();
+ if (ShbError != kShbOk) {
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+#endif
+
+ // initialize EplEventk module
+ Ret = EplEventkInit(EplApiInstance_g.m_InitParam.m_pfnCbSync);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // initialize EplEventu module
+ Ret = EplEventuInit(EplApiProcessEvent);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // init EplTimerk module
+ Ret = EplTimerkInit();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // initialize EplNmtk module before DLL
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+ Ret = EplNmtkInit();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // initialize EplDllk module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ EPL_MEMCPY(DllkInitParam.m_be_abSrcMac,
+ EplApiInstance_g.m_InitParam.m_abMacAddress, 6);
+ Ret = EplDllkAddInstance(&DllkInitParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // initialize EplErrorHandlerk module
+ Ret = EplErrorHandlerkInit();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // initialize EplDllkCal module
+ Ret = EplDllkCalAddInstance();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // initialize EplDlluCal module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ Ret = EplDlluCalAddInstance();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // initialize EplPdok module
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ Ret = EplPdokAddInstance();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret = EplPdokCalAddInstance();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // initialize EplNmtCnu module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0)
+ Ret = EplNmtCnuAddInstance(EplApiInstance_g.m_InitParam.m_uiNodeId);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // initialize EplNmtu module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret = EplNmtuInit();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // register NMT event callback function
+ Ret = EplNmtuRegisterStateChangeCb(EplApiCbNmtStateChange);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // initialize EplNmtMnu module
+ Ret = EplNmtMnuInit(EplApiCbNodeEvent, EplApiCbBootEvent);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // initialize EplIdentu module
+ Ret = EplIdentuInit();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // initialize EplStatusu module
+ Ret = EplStatusuInit();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // initialize EplLedu module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+ Ret = EplLeduInit(EplApiCbLedStateChange);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // init SDO module
+#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) || \
+ (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0))
+ // init sdo command layer
+ Ret = EplSdoComInit();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // the application must start NMT state machine
+ // via EplApiExecNmtCommand(kEplNmtEventSwReset)
+ // and thereby the whole EPL stack
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiShutdown()
+//
+// Description: deletes an instance of EPL stack
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiShutdown(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // $$$ d.k.: check if NMT state is NMT_GS_OFF
+
+ // $$$ d.k.: maybe delete event queues at first, but this implies that
+ // no other module must not use the event queues for communication
+ // during shutdown.
+
+ // delete instance for all modules
+
+ // deinitialize EplSdoCom module
+#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0) || \
+ (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0))
+ Ret = EplSdoComDelInstance();
+// PRINTF1("EplSdoComDelInstance(): 0x%X\n", Ret);
+#endif
+
+ // deinitialize EplLedu module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+ Ret = EplLeduDelInstance();
+// PRINTF1("EplLeduDelInstance(): 0x%X\n", Ret);
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // deinitialize EplNmtMnu module
+ Ret = EplNmtMnuDelInstance();
+// PRINTF1("EplNmtMnuDelInstance(): 0x%X\n", Ret);
+
+ // deinitialize EplIdentu module
+ Ret = EplIdentuDelInstance();
+// PRINTF1("EplIdentuDelInstance(): 0x%X\n", Ret);
+
+ // deinitialize EplStatusu module
+ Ret = EplStatusuDelInstance();
+// PRINTF1("EplStatusuDelInstance(): 0x%X\n", Ret);
+#endif
+
+ // deinitialize EplNmtCnu module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0)
+ Ret = EplNmtCnuDelInstance();
+// PRINTF1("EplNmtCnuDelInstance(): 0x%X\n", Ret);
+#endif
+
+ // deinitialize EplNmtu module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret = EplNmtuDelInstance();
+// PRINTF1("EplNmtuDelInstance(): 0x%X\n", Ret);
+#endif
+
+ // deinitialize EplDlluCal module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ Ret = EplDlluCalDelInstance();
+// PRINTF1("EplDlluCalDelInstance(): 0x%X\n", Ret);
+
+#endif
+
+ // deinitialize EplEventu module
+ Ret = EplEventuDelInstance();
+// PRINTF1("EplEventuDelInstance(): 0x%X\n", Ret);
+
+ // deinitialize EplNmtk module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+ Ret = EplNmtkDelInstance();
+// PRINTF1("EplNmtkDelInstance(): 0x%X\n", Ret);
+#endif
+
+ // deinitialize EplDllk module
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ Ret = EplDllkDelInstance();
+// PRINTF1("EplDllkDelInstance(): 0x%X\n", Ret);
+
+ // deinitialize EplDllkCal module
+ Ret = EplDllkCalDelInstance();
+// PRINTF1("EplDllkCalDelInstance(): 0x%X\n", Ret);
+#endif
+
+ // deinitialize EplEventk module
+ Ret = EplEventkDelInstance();
+// PRINTF1("EplEventkDelInstance(): 0x%X\n", Ret);
+
+ // deinitialize EplTimerk module
+ Ret = EplTimerkDelInstance();
+// PRINTF1("EplTimerkDelInstance(): 0x%X\n", Ret);
+
+#ifndef EPL_NO_FIFO
+ ShbExit();
+#endif
+
+ return Ret;
+}
+
+//----------------------------------------------------------------------------
+// Function: EplApiExecNmtCommand()
+//
+// Description: executes a NMT command, i.e. post the NMT command/event to the
+// NMTk module. NMT commands which are not appropriate in the current
+// NMT state are silently ignored. Please keep in mind that the
+// NMT state may change until the NMT command is actually executed.
+//
+// Parameters: NmtEvent_p = NMT command/event
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiExecNmtCommand(tEplNmtEvent NmtEvent_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret = EplNmtuNmtEvent(NmtEvent_p);
+#endif
+
+ return Ret;
+}
+
+//----------------------------------------------------------------------------
+// Function: EplApiLinkObject()
+//
+// Description: Function maps array of application variables onto specified object in OD
+//
+// Parameters: uiObjIndex_p = Function maps variables for this object index
+// pVar_p = Pointer to data memory area for the specified object
+// puiVarEntries_p = IN: pointer to number of entries to map
+// OUT: pointer to number of actually used entries
+// pEntrySize_p = IN: pointer to size of one entry;
+// if size is zero, the actual size will be read from OD
+// OUT: pointer to entire size of all entries mapped
+// uiFirstSubindex_p = This is the first subindex to be mapped.
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiLinkObject(unsigned int uiObjIndex_p,
+ void *pVar_p,
+ unsigned int *puiVarEntries_p,
+ tEplObdSize * pEntrySize_p,
+ unsigned int uiFirstSubindex_p)
+{
+ BYTE bVarEntries;
+ BYTE bIndexEntries;
+ BYTE MEM *pbData;
+ unsigned int uiSubindex;
+ tEplVarParam VarParam;
+ tEplObdSize EntrySize;
+ tEplObdSize UsedSize;
+
+ tEplKernel RetCode = kEplSuccessful;
+
+ if ((pVar_p == NULL)
+ || (puiVarEntries_p == NULL)
+ || (*puiVarEntries_p == 0)
+ || (pEntrySize_p == NULL)) {
+ RetCode = kEplApiInvalidParam;
+ goto Exit;
+ }
+
+ pbData = (BYTE MEM *) pVar_p;
+ bVarEntries = (BYTE) * puiVarEntries_p;
+ UsedSize = 0;
+
+ // init VarParam structure with default values
+ VarParam.m_uiIndex = uiObjIndex_p;
+ VarParam.m_ValidFlag = kVarValidAll;
+
+ if (uiFirstSubindex_p != 0) { // check if object exists by reading subindex 0x00,
+ // because user wants to link a variable to a subindex unequal 0x00
+ // read number of entries
+ EntrySize = (tEplObdSize) sizeof(bIndexEntries);
+ RetCode = EplObdReadEntry(uiObjIndex_p,
+ 0x00,
+ (void GENERIC *)&bIndexEntries,
+ &EntrySize);
+
+ if ((RetCode != kEplSuccessful) || (bIndexEntries == 0x00)) {
+ // Object doesn't exist or invalid entry number
+ RetCode = kEplObdIndexNotExist;
+ goto Exit;
+ }
+ } else { // user wants to link a variable to subindex 0x00
+ // that's OK
+ bIndexEntries = 0;
+ }
+
+ // Correct number of entries if number read from OD is greater
+ // than the specified number.
+ // This is done, so that we do not set more entries than subindexes the
+ // object actually has.
+ if ((bIndexEntries > (bVarEntries + uiFirstSubindex_p - 1)) &&
+ (bVarEntries != 0x00)) {
+ bIndexEntries = (BYTE) (bVarEntries + uiFirstSubindex_p - 1);
+ }
+ // map entries
+ for (uiSubindex = uiFirstSubindex_p; uiSubindex <= bIndexEntries;
+ uiSubindex++) {
+ // if passed entry size is 0, then get size from OD
+ if (*pEntrySize_p == 0x00) {
+ // read entry size
+ EntrySize = EplObdGetDataSize(uiObjIndex_p, uiSubindex);
+
+ if (EntrySize == 0x00) {
+ // invalid entry size (maybe object doesn't exist or entry of type DOMAIN is empty)
+ RetCode = kEplObdSubindexNotExist;
+ break;
+ }
+ } else { // use passed entry size
+ EntrySize = *pEntrySize_p;
+ }
+
+ VarParam.m_uiSubindex = uiSubindex;
+
+ // set pointer to user var
+ VarParam.m_Size = EntrySize;
+ VarParam.m_pData = pbData;
+
+ UsedSize += EntrySize;
+ pbData += EntrySize;
+
+ RetCode = EplObdDefineVar(&VarParam);
+ if (RetCode != kEplSuccessful) {
+ break;
+ }
+ }
+
+ // set number of mapped entries and entry size
+ *puiVarEntries_p = ((bIndexEntries - uiFirstSubindex_p) + 1);
+ *pEntrySize_p = UsedSize;
+
+ Exit:
+
+ return (RetCode);
+
+}
+
+// ----------------------------------------------------------------------------
+//
+// Function: EplApiReadObject()
+//
+// Description: reads the specified entry from the OD of the specified node.
+// If this node is a remote node, it performs a SDO transfer, which
+// means this function returns kEplApiTaskDeferred and the application
+// is informed via the event callback function when the task is completed.
+//
+// Parameters: pSdoComConHdl_p = INOUT: pointer to SDO connection handle (may be NULL in case of local OD access)
+// uiNodeId_p = IN: node ID (0 = itself)
+// uiIndex_p = IN: index of object in OD
+// uiSubindex_p = IN: sub-index of object in OD
+// pDstData_le_p = OUT: pointer to data in little endian
+// puiSize_p = INOUT: pointer to size of data
+// SdoType_p = IN: type of SDO transfer
+// pUserArg_p = IN: user-definable argument pointer,
+// which will be passed to the event callback function
+//
+// Return: tEplKernel = error code
+//
+// ----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiReadObject(tEplSdoComConHdl * pSdoComConHdl_p,
+ unsigned int uiNodeId_p,
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pDstData_le_p,
+ unsigned int *puiSize_p,
+ tEplSdoType SdoType_p, void *pUserArg_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if ((uiIndex_p == 0) || (pDstData_le_p == NULL) || (puiSize_p == NULL)
+ || (*puiSize_p == 0)) {
+ Ret = kEplApiInvalidParam;
+ goto Exit;
+ }
+
+ if (uiNodeId_p == 0 || uiNodeId_p == EplObdGetNodeId()) { // local OD access can be performed
+ tEplObdSize ObdSize;
+
+ ObdSize = (tEplObdSize) * puiSize_p;
+ Ret =
+ EplObdReadEntryToLe(uiIndex_p, uiSubindex_p, pDstData_le_p,
+ &ObdSize);
+ *puiSize_p = (unsigned int)ObdSize;
+ } else { // perform SDO transfer
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ tEplSdoComTransParamByIndex TransParamByIndex;
+// tEplSdoComConHdl SdoComConHdl;
+
+ // check if application provides space for handle
+ if (pSdoComConHdl_p == NULL) {
+ Ret = kEplApiInvalidParam;
+ goto Exit;
+// pSdoComConHdl_p = &SdoComConHdl;
+ }
+ // init command layer connection
+ Ret = EplSdoComDefineCon(pSdoComConHdl_p, uiNodeId_p, // target node id
+ SdoType_p); // SDO type
+ if ((Ret != kEplSuccessful) && (Ret != kEplSdoComHandleExists)) {
+ goto Exit;
+ }
+ TransParamByIndex.m_pData = pDstData_le_p;
+ TransParamByIndex.m_SdoAccessType = kEplSdoAccessTypeRead;
+ TransParamByIndex.m_SdoComConHdl = *pSdoComConHdl_p;
+ TransParamByIndex.m_uiDataSize = *puiSize_p;
+ TransParamByIndex.m_uiIndex = uiIndex_p;
+ TransParamByIndex.m_uiSubindex = uiSubindex_p;
+ TransParamByIndex.m_pfnSdoFinishedCb = EplApiCbSdoCon;
+ TransParamByIndex.m_pUserArg = pUserArg_p;
+
+ Ret = EplSdoComInitTransferByIndex(&TransParamByIndex);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ Ret = kEplApiTaskDeferred;
+
+#else
+ Ret = kEplApiInvalidParam;
+#endif
+ }
+
+ Exit:
+ return Ret;
+}
+
+// ----------------------------------------------------------------------------
+//
+// Function: EplApiWriteObject()
+//
+// Description: writes the specified entry to the OD of the specified node.
+// If this node is a remote node, it performs a SDO transfer, which
+// means this function returns kEplApiTaskDeferred and the application
+// is informed via the event callback function when the task is completed.
+//
+// Parameters: pSdoComConHdl_p = INOUT: pointer to SDO connection handle (may be NULL in case of local OD access)
+// uiNodeId_p = IN: node ID (0 = itself)
+// uiIndex_p = IN: index of object in OD
+// uiSubindex_p = IN: sub-index of object in OD
+// pSrcData_le_p = IN: pointer to data in little endian
+// uiSize_p = IN: size of data in bytes
+// SdoType_p = IN: type of SDO transfer
+// pUserArg_p = IN: user-definable argument pointer,
+// which will be passed to the event callback function
+//
+// Return: tEplKernel = error code
+//
+// ----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiWriteObject(tEplSdoComConHdl * pSdoComConHdl_p,
+ unsigned int uiNodeId_p,
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pSrcData_le_p,
+ unsigned int uiSize_p,
+ tEplSdoType SdoType_p, void *pUserArg_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if ((uiIndex_p == 0) || (pSrcData_le_p == NULL) || (uiSize_p == 0)) {
+ Ret = kEplApiInvalidParam;
+ goto Exit;
+ }
+
+ if (uiNodeId_p == 0 || uiNodeId_p == EplObdGetNodeId()) { // local OD access can be performed
+
+ Ret =
+ EplObdWriteEntryFromLe(uiIndex_p, uiSubindex_p,
+ pSrcData_le_p, uiSize_p);
+ } else { // perform SDO transfer
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ tEplSdoComTransParamByIndex TransParamByIndex;
+// tEplSdoComConHdl SdoComConHdl;
+
+ // check if application provides space for handle
+ if (pSdoComConHdl_p == NULL) {
+ Ret = kEplApiInvalidParam;
+ goto Exit;
+// pSdoComConHdl_p = &SdoComConHdl;
+ }
+ // d.k.: How to recycle command layer connection?
+ // Try to redefine it, which will return kEplSdoComHandleExists
+ // and the existing command layer handle.
+ // If the returned handle is busy, EplSdoComInitTransferByIndex()
+ // will return with error.
+ // $$$ d.k.: Collisions may occur with Configuration Manager, if both the application and
+ // Configuration Manager, are trying to communicate with the very same node.
+ // possible solution: disallow communication by application if Configuration Manager is busy
+
+ // init command layer connection
+ Ret = EplSdoComDefineCon(pSdoComConHdl_p, uiNodeId_p, // target node id
+ SdoType_p); // SDO type
+ if ((Ret != kEplSuccessful) && (Ret != kEplSdoComHandleExists)) {
+ goto Exit;
+ }
+ TransParamByIndex.m_pData = pSrcData_le_p;
+ TransParamByIndex.m_SdoAccessType = kEplSdoAccessTypeWrite;
+ TransParamByIndex.m_SdoComConHdl = *pSdoComConHdl_p;
+ TransParamByIndex.m_uiDataSize = uiSize_p;
+ TransParamByIndex.m_uiIndex = uiIndex_p;
+ TransParamByIndex.m_uiSubindex = uiSubindex_p;
+ TransParamByIndex.m_pfnSdoFinishedCb = EplApiCbSdoCon;
+ TransParamByIndex.m_pUserArg = pUserArg_p;
+
+ Ret = EplSdoComInitTransferByIndex(&TransParamByIndex);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ Ret = kEplApiTaskDeferred;
+
+#else
+ Ret = kEplApiInvalidParam;
+#endif
+ }
+
+ Exit:
+ return Ret;
+}
+
+// ----------------------------------------------------------------------------
+//
+// Function: EplApiFreeSdoChannel()
+//
+// Description: frees the specified SDO channel.
+// This function must be called after each call to EplApiReadObject()/EplApiWriteObject()
+// which returns kEplApiTaskDeferred and the application
+// is informed via the event callback function when the task is completed.
+//
+// Parameters: SdoComConHdl_p = IN: SDO connection handle
+//
+// Return: tEplKernel = error code
+//
+// ----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiFreeSdoChannel(tEplSdoComConHdl SdoComConHdl_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+
+ // init command layer connection
+ Ret = EplSdoComUndefineCon(SdoComConHdl_p);
+
+#else
+ Ret = kEplApiInvalidParam;
+#endif
+
+ return Ret;
+}
+
+// ----------------------------------------------------------------------------
+//
+// Function: EplApiReadLocalObject()
+//
+// Description: reads the specified entry from the local OD.
+//
+// Parameters: uiIndex_p = IN: index of object in OD
+// uiSubindex_p = IN: sub-index of object in OD
+// pDstData_p = OUT: pointer to data in platform byte order
+// puiSize_p = INOUT: pointer to size of data
+//
+// Return: tEplKernel = error code
+//
+// ----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiReadLocalObject(unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pDstData_p,
+ unsigned int *puiSize_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplObdSize ObdSize;
+
+ ObdSize = (tEplObdSize) * puiSize_p;
+ Ret = EplObdReadEntry(uiIndex_p, uiSubindex_p, pDstData_p, &ObdSize);
+ *puiSize_p = (unsigned int)ObdSize;
+
+ return Ret;
+}
+
+// ----------------------------------------------------------------------------
+//
+// Function: EplApiWriteLocalObject()
+//
+// Description: writes the specified entry to the local OD.
+//
+// Parameters: uiIndex_p = IN: index of object in OD
+// uiSubindex_p = IN: sub-index of object in OD
+// pSrcData_p = IN: pointer to data in platform byte order
+// uiSize_p = IN: size of data in bytes
+//
+// Return: tEplKernel = error code
+//
+// ----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiWriteLocalObject(unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ void *pSrcData_p,
+ unsigned int uiSize_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ Ret =
+ EplObdWriteEntry(uiIndex_p, uiSubindex_p, pSrcData_p,
+ (tEplObdSize) uiSize_p);
+
+ return Ret;
+}
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+// ----------------------------------------------------------------------------
+//
+// Function: EplApiMnTriggerStateChange()
+//
+// Description: triggers the specified node command for the specified node.
+//
+// Parameters: uiNodeId_p = node ID for which the node command will be executed
+// NodeCommand_p = node command
+//
+// Return: tEplKernel = error code
+//
+// ----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiMnTriggerStateChange(unsigned int uiNodeId_p,
+ tEplNmtNodeCommand NodeCommand_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ Ret = EplNmtMnuTriggerStateChange(uiNodeId_p, NodeCommand_p);
+
+ return Ret;
+}
+
+#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiCbObdAccess
+//
+// Description: callback function for OD accesses
+//
+// Parameters: pParam_p = OBD parameter
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiCbObdAccess(tEplObdCbParam MEM * pParam_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+#if (EPL_API_OBD_FORWARD_EVENT != FALSE)
+ tEplApiEventArg EventArg;
+
+ // call user callback
+ // must be disabled for EplApiLinuxKernel.c, because of reentrancy problem
+ // for local OD access. This is not so bad as user callback function in
+ // application does not use OD callbacks at the moment.
+ EventArg.m_ObdCbParam = *pParam_p;
+ Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventObdAccess,
+ &EventArg,
+ EplApiInstance_g.
+ m_InitParam.
+ m_pEventUserArg);
+#endif
+
+ switch (pParam_p->m_uiIndex) {
+ //case 0x1006: // NMT_CycleLen_U32 (valid on reset)
+ case 0x1C14: // DLL_LossOfFrameTolerance_U32
+ //case 0x1F98: // NMT_CycleTiming_REC (valid on reset)
+ {
+ if (pParam_p->m_ObdEvent == kEplObdEvPostWrite) {
+ // update DLL configuration
+ Ret = EplApiUpdateDllConfig(FALSE);
+ }
+ break;
+ }
+
+ case 0x1020: // CFM_VerifyConfiguration_REC.ConfId_U32 != 0
+ {
+ if ((pParam_p->m_ObdEvent == kEplObdEvPostWrite)
+ && (pParam_p->m_uiSubIndex == 3)
+ && (*((DWORD *) pParam_p->m_pArg) != 0)) {
+ DWORD dwVerifyConfInvalid = 0;
+ // set CFM_VerifyConfiguration_REC.VerifyConfInvalid_U32 to 0
+ Ret =
+ EplObdWriteEntry(0x1020, 4,
+ &dwVerifyConfInvalid, 4);
+ // ignore any error because this objekt is optional
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+
+ case 0x1F9E: // NMT_ResetCmd_U8
+ {
+ if (pParam_p->m_ObdEvent == kEplObdEvPreWrite) {
+ BYTE bNmtCommand;
+
+ bNmtCommand = *((BYTE *) pParam_p->m_pArg);
+ // check value range
+ switch ((tEplNmtCommand) bNmtCommand) {
+ case kEplNmtCmdResetNode:
+ case kEplNmtCmdResetCommunication:
+ case kEplNmtCmdResetConfiguration:
+ case kEplNmtCmdSwReset:
+ case kEplNmtCmdInvalidService:
+ // valid command identifier specified
+ break;
+
+ default:
+ pParam_p->m_dwAbortCode =
+ EPL_SDOAC_VALUE_RANGE_EXCEEDED;
+ Ret = kEplObdAccessViolation;
+ break;
+ }
+ } else if (pParam_p->m_ObdEvent == kEplObdEvPostWrite) {
+ BYTE bNmtCommand;
+
+ bNmtCommand = *((BYTE *) pParam_p->m_pArg);
+ // check value range
+ switch ((tEplNmtCommand) bNmtCommand) {
+ case kEplNmtCmdResetNode:
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventResetNode);
+#endif
+ break;
+
+ case kEplNmtCmdResetCommunication:
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventResetCom);
+#endif
+ break;
+
+ case kEplNmtCmdResetConfiguration:
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventResetConfig);
+#endif
+ break;
+
+ case kEplNmtCmdSwReset:
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventSwReset);
+#endif
+ break;
+
+ case kEplNmtCmdInvalidService:
+ break;
+
+ default:
+ pParam_p->m_dwAbortCode =
+ EPL_SDOAC_VALUE_RANGE_EXCEEDED;
+ Ret = kEplObdAccessViolation;
+ break;
+ }
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+//Exit:
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiProcessEvent
+//
+// Description: processes events from event queue and forwards these to
+// the application's event callback function
+//
+// Parameters: pEplEvent_p = pointer to event
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplApiProcessEvent(tEplEvent * pEplEvent_p)
+{
+ tEplKernel Ret;
+ tEplEventError *pEventError;
+ tEplApiEventType EventType;
+
+ Ret = kEplSuccessful;
+
+ // process event
+ switch (pEplEvent_p->m_EventType) {
+ // error event
+ case kEplEventTypeError:
+ {
+ pEventError = (tEplEventError *) pEplEvent_p->m_pArg;
+ switch (pEventError->m_EventSource) {
+ // treat the errors from the following sources as critical
+ case kEplEventSourceEventk:
+ case kEplEventSourceEventu:
+ case kEplEventSourceDllk:
+ {
+ EventType = kEplApiEventCriticalError;
+ // halt the stack by entering NMT state Off
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventCriticalError);
+ break;
+ }
+
+ // the other errors are just warnings
+ default:
+ {
+ EventType = kEplApiEventWarning;
+ break;
+ }
+ }
+
+ // call user callback
+ Ret =
+ EplApiInstance_g.m_InitParam.m_pfnCbEvent(EventType,
+ (tEplApiEventArg
+ *)
+ pEventError,
+ EplApiInstance_g.
+ m_InitParam.
+ m_pEventUserArg);
+ // discard error from callback function, because this could generate an endless loop
+ Ret = kEplSuccessful;
+ break;
+ }
+
+ // at present, there are no other events for this module
+ default:
+ break;
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiCbNmtStateChange
+//
+// Description: callback function for NMT state changes
+//
+// Parameters: NmtStateChange_p = NMT state change event
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplApiCbNmtStateChange(tEplEventNmtStateChange
+ NmtStateChange_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ BYTE bNmtState;
+ tEplApiEventArg EventArg;
+
+ // save NMT state in OD
+ bNmtState = (BYTE) NmtStateChange_p.m_NewNmtState;
+ Ret = EplObdWriteEntry(0x1F8C, 0, &bNmtState, 1);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // do work which must be done in that state
+ switch (NmtStateChange_p.m_NewNmtState) {
+ // EPL stack is not running
+ case kEplNmtGsOff:
+ break;
+
+ // first init of the hardware
+ case kEplNmtGsInitialising:
+#if 0
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ // configure SDO via UDP (i.e. bind it to the EPL ethernet interface)
+ Ret =
+ EplSdoUdpuConfig(EplApiInstance_g.m_InitParam.m_dwIpAddress,
+ EPL_C_SDO_EPL_PORT);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+#endif
+
+ break;
+
+ // init of the manufacturer-specific profile area and the
+ // standardised device profile area
+ case kEplNmtGsResetApplication:
+ {
+ // reset application part of OD
+ Ret = EplObdAccessOdPart(kEplObdPartApp,
+ kEplObdDirLoad);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ break;
+ }
+
+ // init of the communication profile area
+ case kEplNmtGsResetCommunication:
+ {
+ // reset communication part of OD
+ Ret = EplObdAccessOdPart(kEplObdPartGen,
+ kEplObdDirLoad);
+
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // $$$ d.k.: update OD only if OD was not loaded from non-volatile memory
+ Ret = EplApiUpdateObd();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ break;
+ }
+
+ // build the configuration with infos from OD
+ case kEplNmtGsResetConfiguration:
+ {
+
+ Ret = EplApiUpdateDllConfig(TRUE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ break;
+ }
+
+ //-----------------------------------------------------------
+ // CN part of the state machine
+
+ // node liste for EPL-Frames and check timeout
+ case kEplNmtCsNotActive:
+ {
+ // indicate completion of reset in NMT_ResetCmd_U8
+ bNmtState = (BYTE) kEplNmtCmdInvalidService;
+ Ret = EplObdWriteEntry(0x1F9E, 0, &bNmtState, 1);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ break;
+ }
+
+ // node process only async frames
+ case kEplNmtCsPreOperational1:
+ {
+ break;
+ }
+
+ // node process isochronus and asynchronus frames
+ case kEplNmtCsPreOperational2:
+ {
+ break;
+ }
+
+ // node should be configured und application is ready
+ case kEplNmtCsReadyToOperate:
+ {
+ break;
+ }
+
+ // normal work state
+ case kEplNmtCsOperational:
+ {
+ break;
+ }
+
+ // node stopped by MN
+ // -> only process asynchronus frames
+ case kEplNmtCsStopped:
+ {
+ break;
+ }
+
+ // no EPL cycle
+ // -> normal ethernet communication
+ case kEplNmtCsBasicEthernet:
+ {
+ break;
+ }
+
+ //-----------------------------------------------------------
+ // MN part of the state machine
+
+ // node listens for EPL-Frames and check timeout
+ case kEplNmtMsNotActive:
+ {
+ break;
+ }
+
+ // node processes only async frames
+ case kEplNmtMsPreOperational1:
+ {
+ break;
+ }
+
+ // node processes isochronous and asynchronous frames
+ case kEplNmtMsPreOperational2:
+ {
+ break;
+ }
+
+ // node should be configured und application is ready
+ case kEplNmtMsReadyToOperate:
+ {
+ break;
+ }
+
+ // normal work state
+ case kEplNmtMsOperational:
+ {
+ break;
+ }
+
+ // no EPL cycle
+ // -> normal ethernet communication
+ case kEplNmtMsBasicEthernet:
+ {
+ break;
+ }
+
+ default:
+ {
+ TRACE0
+ ("EplApiCbNmtStateChange(): unhandled NMT state\n");
+ }
+ }
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+ // forward event to Led module
+ Ret = EplLeduCbNmtStateChange(NmtStateChange_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // forward event to NmtMn module
+ Ret = EplNmtMnuCbNmtStateChange(NmtStateChange_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // call user callback
+ EventArg.m_NmtStateChange = NmtStateChange_p;
+ Ret =
+ EplApiInstance_g.m_InitParam.
+ m_pfnCbEvent(kEplApiEventNmtStateChange, &EventArg,
+ EplApiInstance_g.m_InitParam.m_pEventUserArg);
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiUpdateDllConfig
+//
+// Description: update configuration of DLL
+//
+// Parameters: fUpdateIdentity_p = TRUE, if identity must be updated
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplApiUpdateDllConfig(BOOL fUpdateIdentity_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplDllConfigParam DllConfigParam;
+ tEplDllIdentParam DllIdentParam;
+ tEplObdSize ObdSize;
+ WORD wTemp;
+ BYTE bTemp;
+
+ // configure Dll
+ EPL_MEMSET(&DllConfigParam, 0, sizeof(DllConfigParam));
+ DllConfigParam.m_uiNodeId = EplObdGetNodeId();
+
+ // Cycle Length (0x1006: NMT_CycleLen_U32) in [us]
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1006, 0, &DllConfigParam.m_dwCycleLen, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // 0x1F82: NMT_FeatureFlags_U32
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1F82, 0, &DllConfigParam.m_dwFeatureFlags,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // d.k. There is no dependance between FeatureFlags and async-only CN
+ DllConfigParam.m_fAsyncOnly = EplApiInstance_g.m_InitParam.m_fAsyncOnly;
+
+ // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns]
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1C14, 0, &DllConfigParam.m_dwLossOfFrameTolerance,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // 0x1F98: NMT_CycleTiming_REC
+ // 0x1F98.1: IsochrTxMaxPayload_U16
+ ObdSize = 2;
+ Ret = EplObdReadEntry(0x1F98, 1, &wTemp, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ DllConfigParam.m_uiIsochrTxMaxPayload = wTemp;
+
+ // 0x1F98.2: IsochrRxMaxPayload_U16
+ ObdSize = 2;
+ Ret = EplObdReadEntry(0x1F98, 2, &wTemp, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ DllConfigParam.m_uiIsochrRxMaxPayload = wTemp;
+
+ // 0x1F98.3: PResMaxLatency_U32
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1F98, 3, &DllConfigParam.m_dwPresMaxLatency,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // 0x1F98.4: PReqActPayloadLimit_U16
+ ObdSize = 2;
+ Ret = EplObdReadEntry(0x1F98, 4, &wTemp, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ DllConfigParam.m_uiPreqActPayloadLimit = wTemp;
+
+ // 0x1F98.5: PResActPayloadLimit_U16
+ ObdSize = 2;
+ Ret = EplObdReadEntry(0x1F98, 5, &wTemp, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ DllConfigParam.m_uiPresActPayloadLimit = wTemp;
+
+ // 0x1F98.6: ASndMaxLatency_U32
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1F98, 6, &DllConfigParam.m_dwAsndMaxLatency,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // 0x1F98.7: MultiplCycleCnt_U8
+ ObdSize = 1;
+ Ret = EplObdReadEntry(0x1F98, 7, &bTemp, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ DllConfigParam.m_uiMultiplCycleCnt = bTemp;
+
+ // 0x1F98.8: AsyncMTU_U16
+ ObdSize = 2;
+ Ret = EplObdReadEntry(0x1F98, 8, &wTemp, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ DllConfigParam.m_uiAsyncMtu = wTemp;
+
+ // $$$ Prescaler
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // 0x1F8A.1: WaitSoCPReq_U32 in [ns]
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1F8A, 1, &DllConfigParam.m_dwWaitSocPreq,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns] (optional)
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1F8A, 2, &DllConfigParam.m_dwAsyncSlotTimeout,
+ &ObdSize);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+#endif
+
+ DllConfigParam.m_uiSizeOfStruct = sizeof(DllConfigParam);
+ Ret = EplDllkConfig(&DllConfigParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if (fUpdateIdentity_p != FALSE) {
+ // configure Identity
+ EPL_MEMSET(&DllIdentParam, 0, sizeof(DllIdentParam));
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1000, 0, &DllIdentParam.m_dwDeviceType,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1018, 1, &DllIdentParam.m_dwVendorId,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1018, 2, &DllIdentParam.m_dwProductCode,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1018, 3,
+ &DllIdentParam.m_dwRevisionNumber,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1018, 4, &DllIdentParam.m_dwSerialNumber,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ DllIdentParam.m_dwIpAddress =
+ EplApiInstance_g.m_InitParam.m_dwIpAddress;
+ DllIdentParam.m_dwSubnetMask =
+ EplApiInstance_g.m_InitParam.m_dwSubnetMask;
+ EPL_MEMCPY(DllIdentParam.m_sHostname,
+ EplApiInstance_g.m_InitParam.m_sHostname,
+ sizeof(DllIdentParam.m_sHostname));
+
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1020, 1,
+ &DllIdentParam.m_dwVerifyConfigurationDate,
+ &ObdSize);
+ // ignore any error, because this object is optional
+
+ ObdSize = 4;
+ Ret =
+ EplObdReadEntry(0x1020, 2,
+ &DllIdentParam.m_dwVerifyConfigurationTime,
+ &ObdSize);
+ // ignore any error, because this object is optional
+
+ // $$$ d.k.: fill rest of ident structure
+
+ DllIdentParam.m_uiSizeOfStruct = sizeof(DllIdentParam);
+ Ret = EplDllkSetIdentity(&DllIdentParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiUpdateObd
+//
+// Description: update OD from init param
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplApiUpdateObd(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+ WORD wTemp;
+ BYTE bTemp;
+
+ // set node id in OD
+ Ret = EplObdSetNodeId(EplApiInstance_g.m_InitParam.m_uiNodeId, // node id
+ kEplObdNodeIdHardware); // set by hardware
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_dwCycleLen != -1) {
+ Ret =
+ EplObdWriteEntry(0x1006, 0,
+ &EplApiInstance_g.m_InitParam.m_dwCycleLen,
+ 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_dwLossOfFrameTolerance != -1) {
+ Ret =
+ EplObdWriteEntry(0x1C14, 0,
+ &EplApiInstance_g.m_InitParam.
+ m_dwLossOfFrameTolerance, 4);
+ /* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ } */
+ }
+ // d.k. There is no dependance between FeatureFlags and async-only CN.
+ if (EplApiInstance_g.m_InitParam.m_dwFeatureFlags != -1) {
+ Ret =
+ EplObdWriteEntry(0x1F82, 0,
+ &EplApiInstance_g.m_InitParam.
+ m_dwFeatureFlags, 4);
+ /* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ } */
+ }
+
+ wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrTxMaxPayload;
+ Ret = EplObdWriteEntry(0x1F98, 1, &wTemp, 2);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+
+ wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiIsochrRxMaxPayload;
+ Ret = EplObdWriteEntry(0x1F98, 2, &wTemp, 2);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+
+ Ret =
+ EplObdWriteEntry(0x1F98, 3,
+ &EplApiInstance_g.m_InitParam.m_dwPresMaxLatency,
+ 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+
+ if (EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit <=
+ EPL_C_DLL_ISOCHR_MAX_PAYL) {
+ wTemp =
+ (WORD) EplApiInstance_g.m_InitParam.m_uiPreqActPayloadLimit;
+ Ret = EplObdWriteEntry(0x1F98, 4, &wTemp, 2);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit <=
+ EPL_C_DLL_ISOCHR_MAX_PAYL) {
+ wTemp =
+ (WORD) EplApiInstance_g.m_InitParam.m_uiPresActPayloadLimit;
+ Ret = EplObdWriteEntry(0x1F98, 5, &wTemp, 2);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ Ret =
+ EplObdWriteEntry(0x1F98, 6,
+ &EplApiInstance_g.m_InitParam.m_dwAsndMaxLatency,
+ 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+
+ if (EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt <= 0xFF) {
+ bTemp = (BYTE) EplApiInstance_g.m_InitParam.m_uiMultiplCycleCnt;
+ Ret = EplObdWriteEntry(0x1F98, 7, &bTemp, 1);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_uiAsyncMtu <=
+ EPL_C_DLL_MAX_ASYNC_MTU) {
+ wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiAsyncMtu;
+ Ret = EplObdWriteEntry(0x1F98, 8, &wTemp, 2);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_uiPrescaler <= 1000) {
+ wTemp = (WORD) EplApiInstance_g.m_InitParam.m_uiPrescaler;
+ Ret = EplObdWriteEntry(0x1F98, 9, &wTemp, 2);
+ // ignore return code
+ Ret = kEplSuccessful;
+ }
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (EplApiInstance_g.m_InitParam.m_dwWaitSocPreq != -1) {
+ Ret =
+ EplObdWriteEntry(0x1F8A, 1,
+ &EplApiInstance_g.m_InitParam.
+ m_dwWaitSocPreq, 4);
+ /* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ } */
+ }
+
+ if ((EplApiInstance_g.m_InitParam.m_dwAsyncSlotTimeout != 0)
+ && (EplApiInstance_g.m_InitParam.m_dwAsyncSlotTimeout != -1)) {
+ Ret =
+ EplObdWriteEntry(0x1F8A, 2,
+ &EplApiInstance_g.m_InitParam.
+ m_dwAsyncSlotTimeout, 4);
+ /* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ } */
+ }
+#endif
+
+ // configure Identity
+ if (EplApiInstance_g.m_InitParam.m_dwDeviceType != -1) {
+ Ret =
+ EplObdWriteEntry(0x1000, 0,
+ &EplApiInstance_g.m_InitParam.
+ m_dwDeviceType, 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_dwVendorId != -1) {
+ Ret =
+ EplObdWriteEntry(0x1018, 1,
+ &EplApiInstance_g.m_InitParam.m_dwVendorId,
+ 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_dwProductCode != -1) {
+ Ret =
+ EplObdWriteEntry(0x1018, 2,
+ &EplApiInstance_g.m_InitParam.
+ m_dwProductCode, 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_dwRevisionNumber != -1) {
+ Ret =
+ EplObdWriteEntry(0x1018, 3,
+ &EplApiInstance_g.m_InitParam.
+ m_dwRevisionNumber, 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_dwSerialNumber != -1) {
+ Ret =
+ EplObdWriteEntry(0x1018, 4,
+ &EplApiInstance_g.m_InitParam.
+ m_dwSerialNumber, 4);
+/* if(Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_pszDevName != NULL) {
+ // write Device Name (0x1008)
+ Ret =
+ EplObdWriteEntry(0x1008, 0,
+ (void GENERIC *)EplApiInstance_g.
+ m_InitParam.m_pszDevName,
+ (tEplObdSize) strlen(EplApiInstance_g.
+ m_InitParam.
+ m_pszDevName));
+/* if (Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_pszHwVersion != NULL) {
+ // write Hardware version (0x1009)
+ Ret =
+ EplObdWriteEntry(0x1009, 0,
+ (void GENERIC *)EplApiInstance_g.
+ m_InitParam.m_pszHwVersion,
+ (tEplObdSize) strlen(EplApiInstance_g.
+ m_InitParam.
+ m_pszHwVersion));
+/* if (Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ if (EplApiInstance_g.m_InitParam.m_pszSwVersion != NULL) {
+ // write Software version (0x100A)
+ Ret =
+ EplObdWriteEntry(0x100A, 0,
+ (void GENERIC *)EplApiInstance_g.
+ m_InitParam.m_pszSwVersion,
+ (tEplObdSize) strlen(EplApiInstance_g.
+ m_InitParam.
+ m_pszSwVersion));
+/* if (Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiCbSdoCon
+//
+// Description: callback function for SDO transfers
+//
+// Parameters: pSdoComFinished_p = SDO parameter
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+static tEplKernel PUBLIC EplApiCbSdoCon(tEplSdoComFinished * pSdoComFinished_p)
+{
+ tEplKernel Ret;
+ tEplApiEventArg EventArg;
+
+ Ret = kEplSuccessful;
+
+ // call user callback
+ EventArg.m_Sdo = *pSdoComFinished_p;
+ Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventSdo,
+ &EventArg,
+ EplApiInstance_g.
+ m_InitParam.
+ m_pEventUserArg);
+
+ return Ret;
+
+}
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiCbNodeEvent
+//
+// Description: callback function for node events
+//
+// Parameters: uiNodeId_p = node ID of the CN
+// NodeEvent_p = event from the specified CN
+// NmtState_p = current NMT state of the CN
+// wErrorCode_p = EPL error code if NodeEvent_p==kEplNmtNodeEventError
+// fMandatory_p = flag if CN is mandatory
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplApiCbNodeEvent(unsigned int uiNodeId_p,
+ tEplNmtNodeEvent NodeEvent_p,
+ tEplNmtState NmtState_p,
+ WORD wErrorCode_p, BOOL fMandatory_p)
+{
+ tEplKernel Ret;
+ tEplApiEventArg EventArg;
+
+ Ret = kEplSuccessful;
+
+ // call user callback
+ EventArg.m_Node.m_uiNodeId = uiNodeId_p;
+ EventArg.m_Node.m_NodeEvent = NodeEvent_p;
+ EventArg.m_Node.m_NmtState = NmtState_p;
+ EventArg.m_Node.m_wErrorCode = wErrorCode_p;
+ EventArg.m_Node.m_fMandatory = fMandatory_p;
+
+ Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventNode,
+ &EventArg,
+ EplApiInstance_g.
+ m_InitParam.
+ m_pEventUserArg);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiCbBootEvent
+//
+// Description: callback function for boot events
+//
+// Parameters: BootEvent_p = event from the boot-up process
+// NmtState_p = current local NMT state
+// wErrorCode_p = EPL error code if BootEvent_p==kEplNmtBootEventError
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplApiCbBootEvent(tEplNmtBootEvent BootEvent_p,
+ tEplNmtState NmtState_p,
+ WORD wErrorCode_p)
+{
+ tEplKernel Ret;
+ tEplApiEventArg EventArg;
+
+ Ret = kEplSuccessful;
+
+ // call user callback
+ EventArg.m_Boot.m_BootEvent = BootEvent_p;
+ EventArg.m_Boot.m_NmtState = NmtState_p;
+ EventArg.m_Boot.m_wErrorCode = wErrorCode_p;
+
+ Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventBoot,
+ &EventArg,
+ EplApiInstance_g.
+ m_InitParam.
+ m_pEventUserArg);
+
+ return Ret;
+
+}
+
+#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiCbLedStateChange
+//
+// Description: callback function for LED change events.
+//
+// Parameters: LedType_p = type of LED
+// fOn_p = state of LED
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplApiCbLedStateChange(tEplLedType LedType_p,
+ BOOL fOn_p)
+{
+ tEplKernel Ret;
+ tEplApiEventArg EventArg;
+
+ Ret = kEplSuccessful;
+
+ // call user callback
+ EventArg.m_Led.m_LedType = LedType_p;
+ EventArg.m_Led.m_fOn = fOn_p;
+
+ Ret = EplApiInstance_g.m_InitParam.m_pfnCbEvent(kEplApiEventLed,
+ &EventArg,
+ EplApiInstance_g.
+ m_InitParam.
+ m_pEventUserArg);
+
+ return Ret;
+
+}
+
+#endif
+
+// EOF
diff --git a/drivers/staging/epl/EplApiLinux.h b/drivers/staging/epl/EplApiLinux.h
new file mode 100644
index 000000000000..92cd12532a62
--- /dev/null
+++ b/drivers/staging/epl/EplApiLinux.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for EPL API layer for Linux (kernel and user space)
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplApiLinux.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/08/25 12:17:41 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/10/11 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_API_LINUX_H_
+#define _EPL_API_LINUX_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define EPLLIN_DEV_NAME "epl" // used for "/dev" and "/proc" entry
+
+//---------------------------------------------------------------------------
+// Commands for <ioctl>
+//---------------------------------------------------------------------------
+
+#define EPLLIN_CMD_INITIALIZE 0 // ulArg_p ~ tEplApiInitParam*
+#define EPLLIN_CMD_PI_IN 1 // ulArg_p ~ tEplApiProcessImage*
+#define EPLLIN_CMD_PI_OUT 2 // ulArg_p ~ tEplApiProcessImage*
+#define EPLLIN_CMD_WRITE_OBJECT 3 // ulArg_p ~ tEplLinSdoObject*
+#define EPLLIN_CMD_READ_OBJECT 4 // ulArg_p ~ tEplLinSdoObject*
+#define EPLLIN_CMD_WRITE_LOCAL_OBJECT 5 // ulArg_p ~ tEplLinLocalObject*
+#define EPLLIN_CMD_READ_LOCAL_OBJECT 6 // ulArg_p ~ tEplLinLocalObject*
+#define EPLLIN_CMD_FREE_SDO_CHANNEL 7 // ulArg_p ~ tEplSdoComConHdl
+#define EPLLIN_CMD_NMT_COMMAND 8 // ulArg_p ~ tEplNmtEvent
+#define EPLLIN_CMD_GET_EVENT 9 // ulArg_p ~ tEplLinEvent*
+#define EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE 10 // ulArg_p ~ tEplLinNodeCmdObject*
+#define EPLLIN_CMD_PI_SETUP 11 // ulArg_p ~ 0
+#define EPLLIN_CMD_SHUTDOWN 12 // ulArg_p ~ 0
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef struct {
+ unsigned int m_uiEventArgSize;
+ tEplApiEventArg *m_pEventArg;
+ tEplApiEventType *m_pEventType;
+ tEplKernel m_RetCbEvent;
+
+} tEplLinEvent;
+
+typedef struct {
+ tEplSdoComConHdl m_SdoComConHdl;
+ BOOL m_fValidSdoComConHdl;
+ unsigned int m_uiNodeId;
+ unsigned int m_uiIndex;
+ unsigned int m_uiSubindex;
+ void *m_le_pData;
+ unsigned int m_uiSize;
+ tEplSdoType m_SdoType;
+ void *m_pUserArg;
+
+} tEplLinSdoObject;
+
+typedef struct {
+ unsigned int m_uiIndex;
+ unsigned int m_uiSubindex;
+ void *m_pData;
+ unsigned int m_uiSize;
+
+} tEplLinLocalObject;
+
+typedef struct {
+ unsigned int m_uiNodeId;
+ tEplNmtNodeCommand m_NodeCommand;
+
+} tEplLinNodeCmdObject;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_API_LINUX_H_
diff --git a/drivers/staging/epl/EplApiLinuxKernel.c b/drivers/staging/epl/EplApiLinuxKernel.c
new file mode 100644
index 000000000000..05ca0628d6ae
--- /dev/null
+++ b/drivers/staging/epl/EplApiLinuxKernel.c
@@ -0,0 +1,1260 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: Linux kernel module as wrapper of EPL API layer,
+ i.e. counterpart to a Linux application
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplApiLinuxKernel.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.9 $ $Date: 2008/11/21 09:00:38 $
+
+ $State: Exp $
+
+ Build Environment:
+ GNU-Compiler for m68k
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/10/11 d.k.: Initial Version
+ 2008/04/10 m.u.: Changed to new char driver init
+
+****************************************************************************/
+
+// kernel modul and driver
+
+//#include <linux/version.h>
+//#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/types.h>
+
+//#include <linux/module.h>
+//#include <linux/kernel.h>
+//#include <linux/init.h>
+//#include <linux/errno.h>
+
+// scheduling
+#include <linux/sched.h>
+
+// memory access
+#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+
+#ifdef CONFIG_DEVFS_FS
+#include <linux/major.h>
+#include <linux/devfs_fs_kernel.h>
+#endif
+
+#include "Epl.h"
+#include "EplApiLinux.h"
+//#include "kernel/EplPdokCal.h"
+#include "proc_fs.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ // remove ("make invisible") obsolete symbols for kernel versions 2.6
+ // and higher
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#define EXPORT_NO_SYMBOLS
+#else
+#error "This driver needs a 2.6.x kernel or higher"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+// Metainformation
+MODULE_LICENSE("Dual BSD/GPL");
+#ifdef MODULE_AUTHOR
+MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
+MODULE_DESCRIPTION("EPL API driver");
+#endif
+
+//---------------------------------------------------------------------------
+// Configuration
+//---------------------------------------------------------------------------
+
+#define EPLLIN_DRV_NAME "systec_epl" // used for <register_chrdev>
+
+//---------------------------------------------------------------------------
+// Constant definitions
+//---------------------------------------------------------------------------
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#endif
+
+#define EVENT_STATE_INIT 0
+#define EVENT_STATE_IOCTL 1 // ioctl entered and ready to receive EPL event
+#define EVENT_STATE_READY 2 // EPL event can be forwarded to user application
+#define EVENT_STATE_TERM 3 // terminate processing
+
+#define EPL_STATE_NOTOPEN 0
+#define EPL_STATE_NOTINIT 1
+#define EPL_STATE_RUNNING 2
+#define EPL_STATE_SHUTDOWN 3
+
+//---------------------------------------------------------------------------
+// Global variables
+//---------------------------------------------------------------------------
+
+#ifdef CONFIG_DEVFS_FS
+
+ // driver major number
+static int nDrvMajorNumber_g;
+
+#else
+
+ // device number (major and minor)
+static dev_t nDevNum_g;
+static struct cdev *pEpl_cdev_g;
+
+#endif
+
+static volatile unsigned int uiEplState_g = EPL_STATE_NOTOPEN;
+
+static struct semaphore SemaphoreCbEvent_g; // semaphore for EplLinCbEvent
+static wait_queue_head_t WaitQueueCbEvent_g; // wait queue EplLinCbEvent
+static wait_queue_head_t WaitQueueProcess_g; // wait queue for EplApiProcess (user process)
+static wait_queue_head_t WaitQueueRelease_g; // wait queue for EplLinRelease
+static atomic_t AtomicEventState_g = ATOMIC_INIT(EVENT_STATE_INIT);
+static tEplApiEventType EventType_g; // event type (enum)
+static tEplApiEventArg *pEventArg_g; // event argument (union)
+static tEplKernel RetCbEvent_g; // return code from event callback function
+static wait_queue_head_t WaitQueueCbSync_g; // wait queue EplLinCbSync
+static wait_queue_head_t WaitQueuePI_In_g; // wait queue for EplApiProcessImageExchangeIn (user process)
+static atomic_t AtomicSyncState_g = ATOMIC_INIT(EVENT_STATE_INIT);
+
+//---------------------------------------------------------------------------
+// Local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ void *m_pUserArg;
+ void *m_pData;
+
+} tEplLinSdoBufHeader;
+
+//---------------------------------------------------------------------------
+// Local variables
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Prototypes of internal functions
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
+ tEplApiEventArg * pEventArg_p, // IN: event argument (union)
+ void GENERIC * pUserArg_p);
+
+tEplKernel PUBLIC EplLinCbSync(void);
+
+static int __init EplLinInit(void);
+static void __exit EplLinExit(void);
+
+static int EplLinOpen(struct inode *pDeviceFile_p, struct file *pInstance_p);
+static int EplLinRelease(struct inode *pDeviceFile_p, struct file *pInstance_p);
+static ssize_t EplLinRead(struct file *pInstance_p, char *pDstBuff_p,
+ size_t BuffSize_p, loff_t * pFileOffs_p);
+static ssize_t EplLinWrite(struct file *pInstance_p, const char *pSrcBuff_p,
+ size_t BuffSize_p, loff_t * pFileOffs_p);
+static int EplLinIoctl(struct inode *pDeviceFile_p, struct file *pInstance_p,
+ unsigned int uiIoctlCmd_p, unsigned long ulArg_p);
+
+//---------------------------------------------------------------------------
+// Kernel Module specific Data Structures
+//---------------------------------------------------------------------------
+
+EXPORT_NO_SYMBOLS;
+
+module_init(EplLinInit);
+module_exit(EplLinExit);
+
+static struct file_operations EplLinFileOps_g = {
+ .owner = THIS_MODULE,
+ .open = EplLinOpen,
+ .release = EplLinRelease,
+ .read = EplLinRead,
+ .write = EplLinWrite,
+ .ioctl = EplLinIoctl,
+
+};
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// Initailize Driver
+//---------------------------------------------------------------------------
+// -> insmod driver
+//---------------------------------------------------------------------------
+
+static int __init EplLinInit(void)
+{
+
+ tEplKernel EplRet;
+ int iErr;
+ int iRet;
+#ifdef CONFIG_DEVFS_FS
+ int nMinorNumber;
+#endif
+
+ TRACE0("EPL: + EplLinInit...\n");
+ TRACE2("EPL: Driver build: %s / %s\n", __DATE__, __TIME__);
+
+ iRet = 0;
+
+ // initialize global variables
+ atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
+ sema_init(&SemaphoreCbEvent_g, 1);
+ init_waitqueue_head(&WaitQueueCbEvent_g);
+ init_waitqueue_head(&WaitQueueProcess_g);
+ init_waitqueue_head(&WaitQueueRelease_g);
+
+#ifdef CONFIG_DEVFS_FS
+
+ // register character device handler
+ TRACE2("EPL: Installing Driver '%s', Version %s...\n",
+ EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
+ TRACE0("EPL: (using dynamic major number assignment)\n");
+ nDrvMajorNumber_g =
+ register_chrdev(0, EPLLIN_DRV_NAME, &EplLinFileOps_g);
+ if (nDrvMajorNumber_g != 0) {
+ TRACE2
+ ("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n",
+ EPLLIN_DRV_NAME, nDrvMajorNumber_g);
+ } else {
+ TRACE1
+ ("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n",
+ EPLLIN_DRV_NAME);
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ // create device node in DEVFS
+ nMinorNumber = 0;
+ TRACE1("EPL: Creating device node '/dev/%s'...\n", EPLLIN_DEV_NAME);
+ iErr =
+ devfs_mk_cdev(MKDEV(nDrvMajorNumber_g, nMinorNumber),
+ S_IFCHR | S_IRUGO | S_IWUGO, EPLLIN_DEV_NAME);
+ if (iErr == 0) {
+ TRACE1("EPL: Device node '/dev/%s' created successful.\n",
+ EPLLIN_DEV_NAME);
+ } else {
+ TRACE1("EPL: ERROR: unable to create device node '/dev/%s'\n",
+ EPLLIN_DEV_NAME);
+ iRet = -EIO;
+ goto Exit;
+ }
+
+#else
+
+ // register character device handler
+ // only one Minor required
+ TRACE2("EPL: Installing Driver '%s', Version %s...\n",
+ EPLLIN_DRV_NAME, EPL_PRODUCT_VERSION);
+ iRet = alloc_chrdev_region(&nDevNum_g, 0, 1, EPLLIN_DRV_NAME);
+ if (iRet == 0) {
+ TRACE2
+ ("EPL: Driver '%s' installed successful, assigned MajorNumber=%d\n",
+ EPLLIN_DRV_NAME, MAJOR(nDevNum_g));
+ } else {
+ TRACE1
+ ("EPL: ERROR: Driver '%s' is unable to get a free MajorNumber!\n",
+ EPLLIN_DRV_NAME);
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ // register cdev structure
+ pEpl_cdev_g = cdev_alloc();
+ pEpl_cdev_g->ops = &EplLinFileOps_g;
+ pEpl_cdev_g->owner = THIS_MODULE;
+ iErr = cdev_add(pEpl_cdev_g, nDevNum_g, 1);
+ if (iErr) {
+ TRACE2("EPL: ERROR %d: Driver '%s' could not be added!\n",
+ iErr, EPLLIN_DRV_NAME);
+ iRet = -EIO;
+ goto Exit;
+ }
+#endif
+
+ // create device node in PROCFS
+ EplRet = EplLinProcInit();
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Exit:
+
+ TRACE1("EPL: - EplLinInit (iRet=%d)\n", iRet);
+ return (iRet);
+
+}
+
+//---------------------------------------------------------------------------
+// Remove Driver
+//---------------------------------------------------------------------------
+// -> rmmod driver
+//---------------------------------------------------------------------------
+
+static void __exit EplLinExit(void)
+{
+
+ tEplKernel EplRet;
+
+ // delete instance for all modules
+// EplRet = EplApiShutdown();
+// printk("EplApiShutdown(): 0x%X\n", EplRet);
+
+ // deinitialize proc fs
+ EplRet = EplLinProcFree();
+ printk("EplLinProcFree(): 0x%X\n", EplRet);
+
+ TRACE0("EPL: + EplLinExit...\n");
+
+#ifdef CONFIG_DEVFS_FS
+
+ // remove device node from DEVFS
+ devfs_remove(EPLLIN_DEV_NAME);
+ TRACE1("EPL: Device node '/dev/%s' removed.\n", EPLLIN_DEV_NAME);
+
+ // unregister character device handler
+ unregister_chrdev(nDrvMajorNumber_g, EPLLIN_DRV_NAME);
+
+#else
+
+ // remove cdev structure
+ cdev_del(pEpl_cdev_g);
+
+ // unregister character device handler
+ unregister_chrdev_region(nDevNum_g, 1);
+
+#endif
+
+ TRACE1("EPL: Driver '%s' removed.\n", EPLLIN_DRV_NAME);
+
+ TRACE0("EPL: - EplLinExit\n");
+
+}
+
+//---------------------------------------------------------------------------
+// Open Driver
+//---------------------------------------------------------------------------
+// -> open("/dev/driver", O_RDWR)...
+//---------------------------------------------------------------------------
+
+static int EplLinOpen(struct inode *pDeviceFile_p, // information about the device to open
+ struct file *pInstance_p) // information about driver instance
+{
+
+ int iRet;
+
+ TRACE0("EPL: + EplLinOpen...\n");
+
+ MOD_INC_USE_COUNT;
+
+ if (uiEplState_g != EPL_STATE_NOTOPEN) { // stack already initialized
+ iRet = -EALREADY;
+ } else {
+ atomic_set(&AtomicEventState_g, EVENT_STATE_INIT);
+ sema_init(&SemaphoreCbEvent_g, 1);
+ init_waitqueue_head(&WaitQueueCbEvent_g);
+ init_waitqueue_head(&WaitQueueProcess_g);
+ init_waitqueue_head(&WaitQueueRelease_g);
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_INIT);
+ init_waitqueue_head(&WaitQueueCbSync_g);
+ init_waitqueue_head(&WaitQueuePI_In_g);
+
+ uiEplState_g = EPL_STATE_NOTINIT;
+ iRet = 0;
+ }
+
+ TRACE1("EPL: - EplLinOpen (iRet=%d)\n", iRet);
+ return (iRet);
+
+}
+
+//---------------------------------------------------------------------------
+// Close Driver
+//---------------------------------------------------------------------------
+// -> close(device)...
+//---------------------------------------------------------------------------
+
+static int EplLinRelease(struct inode *pDeviceFile_p, // information about the device to open
+ struct file *pInstance_p) // information about driver instance
+{
+
+ tEplKernel EplRet = kEplSuccessful;
+ int iRet;
+
+ TRACE0("EPL: + EplLinRelease...\n");
+
+ if (uiEplState_g != EPL_STATE_NOTINIT) {
+ // pass control to sync kernel thread, but signal termination
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbSync_g);
+ wake_up_interruptible(&WaitQueuePI_In_g);
+
+ // pass control to event queue kernel thread
+ atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbEvent_g);
+
+ if (uiEplState_g == EPL_STATE_RUNNING) { // post NmtEventSwitchOff
+ EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
+
+ }
+
+ if (EplRet == kEplSuccessful) {
+ TRACE0("EPL: waiting for NMT_GS_OFF\n");
+ wait_event_interruptible(WaitQueueRelease_g,
+ (uiEplState_g ==
+ EPL_STATE_SHUTDOWN));
+ } else { // post NmtEventSwitchOff failed
+ TRACE0("EPL: event post failed\n");
+ }
+
+ // $$$ d.k.: What if waiting was interrupted by signal?
+
+ TRACE0("EPL: call EplApiShutdown()\n");
+ // EPL stack can be safely shut down
+ // delete instance for all EPL modules
+ EplRet = EplApiShutdown();
+ printk("EplApiShutdown(): 0x%X\n", EplRet);
+ }
+
+ uiEplState_g = EPL_STATE_NOTOPEN;
+ iRet = 0;
+
+ MOD_DEC_USE_COUNT;
+
+ TRACE1("EPL: - EplLinRelease (iRet=%d)\n", iRet);
+ return (iRet);
+
+}
+
+//---------------------------------------------------------------------------
+// Read Data from Driver
+//---------------------------------------------------------------------------
+// -> read(...)
+//---------------------------------------------------------------------------
+
+static ssize_t EplLinRead(struct file *pInstance_p, // information about driver instance
+ char *pDstBuff_p, // address of buffer to fill with data
+ size_t BuffSize_p, // length of the buffer
+ loff_t * pFileOffs_p) // offset in the file
+{
+
+ int iRet;
+
+ TRACE0("EPL: + EplLinRead...\n");
+
+ TRACE0("EPL: Sorry, this operation isn't supported.\n");
+ iRet = -EINVAL;
+
+ TRACE1("EPL: - EplLinRead (iRet=%d)\n", iRet);
+ return (iRet);
+
+}
+
+//---------------------------------------------------------------------------
+// Write Data to Driver
+//---------------------------------------------------------------------------
+// -> write(...)
+//---------------------------------------------------------------------------
+
+static ssize_t EplLinWrite(struct file *pInstance_p, // information about driver instance
+ const char *pSrcBuff_p, // address of buffer to get data from
+ size_t BuffSize_p, // length of the buffer
+ loff_t * pFileOffs_p) // offset in the file
+{
+
+ int iRet;
+
+ TRACE0("EPL: + EplLinWrite...\n");
+
+ TRACE0("EPL: Sorry, this operation isn't supported.\n");
+ iRet = -EINVAL;
+
+ TRACE1("EPL: - EplLinWrite (iRet=%d)\n", iRet);
+ return (iRet);
+
+}
+
+//---------------------------------------------------------------------------
+// Generic Access to Driver
+//---------------------------------------------------------------------------
+// -> ioctl(...)
+//---------------------------------------------------------------------------
+
+static int EplLinIoctl(struct inode *pDeviceFile_p, // information about the device to open
+ struct file *pInstance_p, // information about driver instance
+ unsigned int uiIoctlCmd_p, // Ioctl command to execute
+ unsigned long ulArg_p) // Ioctl command specific argument/parameter
+{
+
+ tEplKernel EplRet;
+ int iErr;
+ int iRet;
+
+// TRACE1("EPL: + EplLinIoctl (uiIoctlCmd_p=%d)...\n", uiIoctlCmd_p);
+
+ iRet = -EINVAL;
+
+ switch (uiIoctlCmd_p) {
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_INITIALIZE:
+ {
+ tEplApiInitParam EplApiInitParam;
+
+ iErr =
+ copy_from_user(&EplApiInitParam,
+ (const void *)ulArg_p,
+ sizeof(EplApiInitParam));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ EplApiInitParam.m_pfnCbEvent = EplLinCbEvent;
+ EplApiInitParam.m_pfnCbSync = EplLinCbSync;
+
+ EplRet = EplApiInitialize(&EplApiInitParam);
+
+ uiEplState_g = EPL_STATE_RUNNING;
+
+ iRet = (int)EplRet;
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_SHUTDOWN:
+ { // shutdown the threads
+
+ // pass control to sync kernel thread, but signal termination
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbSync_g);
+ wake_up_interruptible(&WaitQueuePI_In_g);
+
+ // pass control to event queue kernel thread
+ atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbEvent_g);
+
+ if (uiEplState_g == EPL_STATE_RUNNING) { // post NmtEventSwitchOff
+ EplRet =
+ EplApiExecNmtCommand(kEplNmtEventSwitchOff);
+
+ }
+
+ iRet = 0;
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_READ_LOCAL_OBJECT:
+ {
+ tEplLinLocalObject LocalObject;
+ void *pData;
+
+ iErr =
+ copy_from_user(&LocalObject, (const void *)ulArg_p,
+ sizeof(LocalObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if ((LocalObject.m_pData == NULL)
+ || (LocalObject.m_uiSize == 0)) {
+ iRet = (int)kEplApiInvalidParam;
+ goto Exit;
+ }
+
+ pData = vmalloc(LocalObject.m_uiSize);
+ if (pData == NULL) { // no memory available
+ iRet = -ENOMEM;
+ goto Exit;
+ }
+
+ EplRet =
+ EplApiReadLocalObject(LocalObject.m_uiIndex,
+ LocalObject.m_uiSubindex,
+ pData, &LocalObject.m_uiSize);
+
+ if (EplRet == kEplSuccessful) {
+ iErr =
+ copy_to_user(LocalObject.m_pData, pData,
+ LocalObject.m_uiSize);
+
+ vfree(pData);
+
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+ // return actual size (LocalObject.m_uiSize)
+ iErr = put_user(LocalObject.m_uiSize,
+ (unsigned int *)(ulArg_p +
+ (unsigned long)
+ &LocalObject.
+ m_uiSize -
+ (unsigned long)
+ &LocalObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ } else {
+ vfree(pData);
+ }
+
+ iRet = (int)EplRet;
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_WRITE_LOCAL_OBJECT:
+ {
+ tEplLinLocalObject LocalObject;
+ void *pData;
+
+ iErr =
+ copy_from_user(&LocalObject, (const void *)ulArg_p,
+ sizeof(LocalObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if ((LocalObject.m_pData == NULL)
+ || (LocalObject.m_uiSize == 0)) {
+ iRet = (int)kEplApiInvalidParam;
+ goto Exit;
+ }
+
+ pData = vmalloc(LocalObject.m_uiSize);
+ if (pData == NULL) { // no memory available
+ iRet = -ENOMEM;
+ goto Exit;
+ }
+ iErr =
+ copy_from_user(pData, LocalObject.m_pData,
+ LocalObject.m_uiSize);
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ EplRet =
+ EplApiWriteLocalObject(LocalObject.m_uiIndex,
+ LocalObject.m_uiSubindex,
+ pData, LocalObject.m_uiSize);
+
+ vfree(pData);
+
+ iRet = (int)EplRet;
+ break;
+ }
+
+ case EPLLIN_CMD_READ_OBJECT:
+ {
+ tEplLinSdoObject SdoObject;
+ void *pData;
+ tEplLinSdoBufHeader *pBufHeader;
+ tEplSdoComConHdl *pSdoComConHdl;
+
+ iErr =
+ copy_from_user(&SdoObject, (const void *)ulArg_p,
+ sizeof(SdoObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if ((SdoObject.m_le_pData == NULL)
+ || (SdoObject.m_uiSize == 0)) {
+ iRet = (int)kEplApiInvalidParam;
+ goto Exit;
+ }
+
+ pBufHeader =
+ (tEplLinSdoBufHeader *)
+ vmalloc(sizeof(tEplLinSdoBufHeader) +
+ SdoObject.m_uiSize);
+ if (pBufHeader == NULL) { // no memory available
+ iRet = -ENOMEM;
+ goto Exit;
+ }
+ // initiate temporary buffer
+ pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
+ pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
+ pData = pBufHeader + sizeof(tEplLinSdoBufHeader);
+
+ if (SdoObject.m_fValidSdoComConHdl != FALSE) {
+ pSdoComConHdl = &SdoObject.m_SdoComConHdl;
+ } else {
+ pSdoComConHdl = NULL;
+ }
+
+ EplRet =
+ EplApiReadObject(pSdoComConHdl,
+ SdoObject.m_uiNodeId,
+ SdoObject.m_uiIndex,
+ SdoObject.m_uiSubindex, pData,
+ &SdoObject.m_uiSize,
+ SdoObject.m_SdoType, pBufHeader);
+
+ // return actual SDO handle (SdoObject.m_SdoComConHdl)
+ iErr = put_user(SdoObject.m_SdoComConHdl,
+ (unsigned int *)(ulArg_p +
+ (unsigned long)
+ &SdoObject.
+ m_SdoComConHdl -
+ (unsigned long)
+ &SdoObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if (EplRet == kEplSuccessful) {
+ iErr =
+ copy_to_user(SdoObject.m_le_pData, pData,
+ SdoObject.m_uiSize);
+
+ vfree(pBufHeader);
+
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+ // return actual size (SdoObject.m_uiSize)
+ iErr = put_user(SdoObject.m_uiSize,
+ (unsigned int *)(ulArg_p +
+ (unsigned long)
+ &SdoObject.
+ m_uiSize -
+ (unsigned long)
+ &SdoObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+ } else if (EplRet != kEplApiTaskDeferred) { // error ocurred
+ vfree(pBufHeader);
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+ }
+
+ iRet = (int)EplRet;
+ break;
+ }
+
+ case EPLLIN_CMD_WRITE_OBJECT:
+ {
+ tEplLinSdoObject SdoObject;
+ void *pData;
+ tEplLinSdoBufHeader *pBufHeader;
+ tEplSdoComConHdl *pSdoComConHdl;
+
+ iErr =
+ copy_from_user(&SdoObject, (const void *)ulArg_p,
+ sizeof(SdoObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if ((SdoObject.m_le_pData == NULL)
+ || (SdoObject.m_uiSize == 0)) {
+ iRet = (int)kEplApiInvalidParam;
+ goto Exit;
+ }
+
+ pBufHeader =
+ (tEplLinSdoBufHeader *)
+ vmalloc(sizeof(tEplLinSdoBufHeader) +
+ SdoObject.m_uiSize);
+ if (pBufHeader == NULL) { // no memory available
+ iRet = -ENOMEM;
+ goto Exit;
+ }
+ // initiate temporary buffer
+ pBufHeader->m_pUserArg = SdoObject.m_pUserArg; // original user argument pointer
+ pBufHeader->m_pData = SdoObject.m_le_pData; // original data pointer from app
+ pData = pBufHeader + sizeof(tEplLinSdoBufHeader);
+
+ iErr =
+ copy_from_user(pData, SdoObject.m_le_pData,
+ SdoObject.m_uiSize);
+
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if (SdoObject.m_fValidSdoComConHdl != FALSE) {
+ pSdoComConHdl = &SdoObject.m_SdoComConHdl;
+ } else {
+ pSdoComConHdl = NULL;
+ }
+
+ EplRet =
+ EplApiWriteObject(pSdoComConHdl,
+ SdoObject.m_uiNodeId,
+ SdoObject.m_uiIndex,
+ SdoObject.m_uiSubindex, pData,
+ SdoObject.m_uiSize,
+ SdoObject.m_SdoType, pBufHeader);
+
+ // return actual SDO handle (SdoObject.m_SdoComConHdl)
+ iErr = put_user(SdoObject.m_SdoComConHdl,
+ (unsigned int *)(ulArg_p +
+ (unsigned long)
+ &SdoObject.
+ m_SdoComConHdl -
+ (unsigned long)
+ &SdoObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if (EplRet != kEplApiTaskDeferred) { // succeeded or error ocurred, but task not deferred
+ vfree(pBufHeader);
+ }
+
+ iRet = (int)EplRet;
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_FREE_SDO_CHANNEL:
+ {
+ // forward SDO handle to EPL stack
+ EplRet =
+ EplApiFreeSdoChannel((tEplSdoComConHdl) ulArg_p);
+
+ iRet = (int)EplRet;
+ break;
+ }
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_MN_TRIGGER_STATE_CHANGE:
+ {
+ tEplLinNodeCmdObject NodeCmdObject;
+
+ iErr =
+ copy_from_user(&NodeCmdObject,
+ (const void *)ulArg_p,
+ sizeof(NodeCmdObject));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ EplRet =
+ EplApiMnTriggerStateChange(NodeCmdObject.m_uiNodeId,
+ NodeCmdObject.
+ m_NodeCommand);
+ iRet = (int)EplRet;
+ break;
+ }
+#endif
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_GET_EVENT:
+ {
+ tEplLinEvent Event;
+
+ // save event structure
+ iErr =
+ copy_from_user(&Event, (const void *)ulArg_p,
+ sizeof(Event));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+ // save return code from application's event callback function
+ RetCbEvent_g = Event.m_RetCbEvent;
+
+ if (RetCbEvent_g == kEplShutdown) {
+ // pass control to event queue kernel thread, but signal termination
+ atomic_set(&AtomicEventState_g,
+ EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbEvent_g);
+ // exit with error -> EplApiProcess() will leave the infinite loop
+ iRet = 1;
+ goto Exit;
+ }
+ // pass control to event queue kernel thread
+ atomic_set(&AtomicEventState_g, EVENT_STATE_IOCTL);
+ wake_up_interruptible(&WaitQueueCbEvent_g);
+
+ // fall asleep itself in own wait queue
+ iErr = wait_event_interruptible(WaitQueueProcess_g,
+ (atomic_read
+ (&AtomicEventState_g)
+ == EVENT_STATE_READY)
+ ||
+ (atomic_read
+ (&AtomicEventState_g)
+ == EVENT_STATE_TERM));
+ if (iErr != 0) { // waiting was interrupted by signal
+ // pass control to event queue kernel thread, but signal termination
+ atomic_set(&AtomicEventState_g,
+ EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbEvent_g);
+ // exit with this error -> EplApiProcess() will leave the infinite loop
+ iRet = iErr;
+ goto Exit;
+ } else if (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM) { // termination in progress
+ // pass control to event queue kernel thread, but signal termination
+ wake_up_interruptible(&WaitQueueCbEvent_g);
+ // exit with this error -> EplApiProcess() will leave the infinite loop
+ iRet = 1;
+ goto Exit;
+ }
+ // copy event to user space
+ iErr =
+ copy_to_user(Event.m_pEventType, &EventType_g,
+ sizeof(EventType_g));
+ if (iErr != 0) { // not all data could be copied
+ iRet = -EIO;
+ goto Exit;
+ }
+ // $$$ d.k. perform SDO event processing
+ if (EventType_g == kEplApiEventSdo) {
+ void *pData;
+ tEplLinSdoBufHeader *pBufHeader;
+
+ pBufHeader =
+ (tEplLinSdoBufHeader *) pEventArg_g->m_Sdo.
+ m_pUserArg;
+ pData =
+ pBufHeader + sizeof(tEplLinSdoBufHeader);
+
+ if (pEventArg_g->m_Sdo.m_SdoAccessType ==
+ kEplSdoAccessTypeRead) {
+ // copy read data to user space
+ iErr =
+ copy_to_user(pBufHeader->m_pData,
+ pData,
+ pEventArg_g->m_Sdo.
+ m_uiTransferredByte);
+ if (iErr != 0) { // not all data could be copied
+ iRet = -EIO;
+ goto Exit;
+ }
+ }
+ pEventArg_g->m_Sdo.m_pUserArg =
+ pBufHeader->m_pUserArg;
+ vfree(pBufHeader);
+ }
+
+ iErr =
+ copy_to_user(Event.m_pEventArg, pEventArg_g,
+ min(sizeof(tEplApiEventArg),
+ Event.m_uiEventArgSize));
+ if (iErr != 0) { // not all data could be copied
+ iRet = -EIO;
+ goto Exit;
+ }
+ // return to EplApiProcess(), which will call the application's event callback function
+ iRet = 0;
+
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_PI_SETUP:
+ {
+ EplRet = EplApiProcessImageSetup();
+ iRet = (int)EplRet;
+
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_PI_IN:
+ {
+ tEplApiProcessImage ProcessImageIn;
+
+ // save process image structure
+ iErr =
+ copy_from_user(&ProcessImageIn,
+ (const void *)ulArg_p,
+ sizeof(ProcessImageIn));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+ // pass control to event queue kernel thread
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_IOCTL);
+
+ // fall asleep itself in own wait queue
+ iErr = wait_event_interruptible(WaitQueuePI_In_g,
+ (atomic_read
+ (&AtomicSyncState_g) ==
+ EVENT_STATE_READY)
+ ||
+ (atomic_read
+ (&AtomicSyncState_g) ==
+ EVENT_STATE_TERM));
+ if (iErr != 0) { // waiting was interrupted by signal
+ // pass control to sync kernel thread, but signal termination
+ atomic_set(&AtomicSyncState_g,
+ EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbSync_g);
+ // exit with this error -> application will leave the infinite loop
+ iRet = iErr;
+ goto Exit;
+ } else if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM) { // termination in progress
+ // pass control to sync kernel thread, but signal termination
+ wake_up_interruptible(&WaitQueueCbSync_g);
+ // exit with this error -> application will leave the infinite loop
+ iRet = 1;
+ goto Exit;
+ }
+ // exchange process image
+ EplRet = EplApiProcessImageExchangeIn(&ProcessImageIn);
+
+ // return to EplApiProcessImageExchangeIn()
+ iRet = (int)EplRet;
+
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_PI_OUT:
+ {
+ tEplApiProcessImage ProcessImageOut;
+
+ // save process image structure
+ iErr =
+ copy_from_user(&ProcessImageOut,
+ (const void *)ulArg_p,
+ sizeof(ProcessImageOut));
+ if (iErr != 0) {
+ iRet = -EIO;
+ goto Exit;
+ }
+
+ if (atomic_read(&AtomicSyncState_g) !=
+ EVENT_STATE_READY) {
+ iRet = (int)kEplInvalidOperation;
+ goto Exit;
+ }
+ // exchange process image
+ EplRet =
+ EplApiProcessImageExchangeOut(&ProcessImageOut);
+
+ // pass control to sync kernel thread
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_TERM);
+ wake_up_interruptible(&WaitQueueCbSync_g);
+
+ // return to EplApiProcessImageExchangeout()
+ iRet = (int)EplRet;
+
+ break;
+ }
+
+ // ----------------------------------------------------------
+ case EPLLIN_CMD_NMT_COMMAND:
+ {
+ // forward NMT command to EPL stack
+ EplRet = EplApiExecNmtCommand((tEplNmtEvent) ulArg_p);
+
+ iRet = (int)EplRet;
+
+ break;
+ }
+
+ // ----------------------------------------------------------
+ default:
+ {
+ break;
+ }
+ }
+
+ Exit:
+
+// TRACE1("EPL: - EplLinIoctl (iRet=%d)\n", iRet);
+ return (iRet);
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+tEplKernel PUBLIC EplLinCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
+ tEplApiEventArg * pEventArg_p, // IN: event argument (union)
+ void GENERIC * pUserArg_p)
+{
+ tEplKernel EplRet = kEplSuccessful;
+ int iErr;
+
+ // block any further call to this function, i.e. enter critical section
+ iErr = down_interruptible(&SemaphoreCbEvent_g);
+ if (iErr != 0) { // waiting was interrupted by signal
+ EplRet = kEplShutdown;
+ goto Exit;
+ }
+ // wait for EplApiProcess() to call ioctl
+ // normally it should be waiting already for us to pass a new event
+ iErr = wait_event_interruptible(WaitQueueCbEvent_g,
+ (atomic_read(&AtomicEventState_g) ==
+ EVENT_STATE_IOCTL)
+ || (atomic_read(&AtomicEventState_g) ==
+ EVENT_STATE_TERM));
+ if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)) { // waiting was interrupted by signal
+ EplRet = kEplShutdown;
+ goto LeaveCriticalSection;
+ }
+ // save event information for ioctl
+ EventType_g = EventType_p;
+ pEventArg_g = pEventArg_p;
+
+ // pass control to application's event callback function, i.e. EplApiProcess()
+ atomic_set(&AtomicEventState_g, EVENT_STATE_READY);
+ wake_up_interruptible(&WaitQueueProcess_g);
+
+ // now, the application's event callback function processes the event
+
+ // wait for completion of application's event callback function, i.e. EplApiProcess() calls ioctl again
+ iErr = wait_event_interruptible(WaitQueueCbEvent_g,
+ (atomic_read(&AtomicEventState_g) ==
+ EVENT_STATE_IOCTL)
+ || (atomic_read(&AtomicEventState_g) ==
+ EVENT_STATE_TERM));
+ if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_TERM)) { // waiting was interrupted by signal
+ EplRet = kEplShutdown;
+ goto LeaveCriticalSection;
+ }
+ // read return code from application's event callback function
+ EplRet = RetCbEvent_g;
+
+ LeaveCriticalSection:
+ up(&SemaphoreCbEvent_g);
+
+ Exit:
+ // check if NMT_GS_OFF is reached
+ if (EventType_p == kEplApiEventNmtStateChange) {
+ if (pEventArg_p->m_NmtStateChange.m_NewNmtState == kEplNmtGsOff) { // NMT state machine was shut down
+ TRACE0("EPL: EplLinCbEvent(NMT_GS_OFF)\n");
+ uiEplState_g = EPL_STATE_SHUTDOWN;
+ atomic_set(&AtomicEventState_g, EVENT_STATE_TERM);
+ wake_up(&WaitQueueRelease_g);
+ } else { // NMT state machine is running
+ uiEplState_g = EPL_STATE_RUNNING;
+ }
+ }
+
+ return EplRet;
+}
+
+tEplKernel PUBLIC EplLinCbSync(void)
+{
+ tEplKernel EplRet = kEplSuccessful;
+ int iErr;
+
+ // check if user process waits for sync
+ if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL) {
+ // pass control to application, i.e. EplApiProcessImageExchangeIn()
+ atomic_set(&AtomicSyncState_g, EVENT_STATE_READY);
+ wake_up_interruptible(&WaitQueuePI_In_g);
+
+ // now, the application processes the sync event
+
+ // wait for call of EplApiProcessImageExchangeOut()
+ iErr = wait_event_interruptible(WaitQueueCbSync_g,
+ (atomic_read(&AtomicSyncState_g)
+ == EVENT_STATE_IOCTL)
+ ||
+ (atomic_read(&AtomicSyncState_g)
+ == EVENT_STATE_TERM));
+ if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)) { // waiting was interrupted by signal or application called wrong function
+ EplRet = kEplShutdown;
+ }
+ } else { // application is currently not waiting for sync
+ // continue without interruption
+ // TPDO are set valid by caller (i.e. EplEventkProcess())
+ }
+
+ TGT_DBG_SIGNAL_TRACE_POINT(1);
+
+ return EplRet;
+}
+
+// EOF
diff --git a/drivers/staging/epl/EplApiProcessImage.c b/drivers/staging/epl/EplApiProcessImage.c
new file mode 100644
index 000000000000..2b2fdf229a75
--- /dev/null
+++ b/drivers/staging/epl/EplApiProcessImage.c
@@ -0,0 +1,347 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for EPL API module (process image)
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplApiProcessImage.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.7 $ $Date: 2008/11/13 17:13:09 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/10/10 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "Epl.h"
+//#include "kernel/EplPdokCal.h"
+
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+#include <asm/uaccess.h>
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplApi */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+#if ((EPL_API_PROCESS_IMAGE_SIZE_IN > 0) || (EPL_API_PROCESS_IMAGE_SIZE_OUT > 0))
+typedef struct {
+#if EPL_API_PROCESS_IMAGE_SIZE_IN > 0
+ BYTE m_abProcessImageInput[EPL_API_PROCESS_IMAGE_SIZE_IN];
+#endif
+#if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0
+ BYTE m_abProcessImageOutput[EPL_API_PROCESS_IMAGE_SIZE_OUT];
+#endif
+
+} tEplApiProcessImageInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+static tEplApiProcessImageInstance EplApiProcessImageInstance_g;
+#endif
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplApiProcessImageSetup()
+//
+// Description: sets up static process image
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiProcessImageSetup(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+#if ((EPL_API_PROCESS_IMAGE_SIZE_IN > 0) || (EPL_API_PROCESS_IMAGE_SIZE_OUT > 0))
+ unsigned int uiVarEntries;
+ tEplObdSize ObdSize;
+#endif
+
+#if EPL_API_PROCESS_IMAGE_SIZE_IN > 0
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN;
+ ObdSize = 1;
+ Ret = EplApiLinkObject(0x2000,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageInput, &uiVarEntries, &ObdSize,
+ 1);
+
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN;
+ ObdSize = 1;
+ Ret = EplApiLinkObject(0x2001,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageInput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 2;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize;
+ Ret = EplApiLinkObject(0x2010,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageInput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 2;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize;
+ Ret = EplApiLinkObject(0x2011,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageInput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 4;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize;
+ Ret = EplApiLinkObject(0x2020,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageInput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 4;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_IN / ObdSize;
+ Ret = EplApiLinkObject(0x2021,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageInput, &uiVarEntries, &ObdSize,
+ 1);
+#endif
+
+#if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT;
+ ObdSize = 1;
+ Ret = EplApiLinkObject(0x2030,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageOutput, &uiVarEntries, &ObdSize,
+ 1);
+
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT;
+ ObdSize = 1;
+ Ret = EplApiLinkObject(0x2031,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageOutput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 2;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize;
+ Ret = EplApiLinkObject(0x2040,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageOutput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 2;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize;
+ Ret = EplApiLinkObject(0x2041,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageOutput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 4;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize;
+ Ret = EplApiLinkObject(0x2050,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageOutput, &uiVarEntries, &ObdSize,
+ 1);
+
+ ObdSize = 4;
+ uiVarEntries = EPL_API_PROCESS_IMAGE_SIZE_OUT / ObdSize;
+ Ret = EplApiLinkObject(0x2051,
+ EplApiProcessImageInstance_g.
+ m_abProcessImageOutput, &uiVarEntries, &ObdSize,
+ 1);
+#endif
+
+ return Ret;
+}
+
+//----------------------------------------------------------------------------
+// Function: EplApiProcessImageExchangeIn()
+//
+// Description: replaces passed input process image with the one of EPL stack
+//
+// Parameters: pPI_p = input process image
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiProcessImageExchangeIn(tEplApiProcessImage * pPI_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+#if EPL_API_PROCESS_IMAGE_SIZE_IN > 0
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ copy_to_user(pPI_p->m_pImage,
+ EplApiProcessImageInstance_g.m_abProcessImageInput,
+ min(pPI_p->m_uiSize,
+ sizeof(EplApiProcessImageInstance_g.
+ m_abProcessImageInput)));
+#else
+ EPL_MEMCPY(pPI_p->m_pImage,
+ EplApiProcessImageInstance_g.m_abProcessImageInput,
+ min(pPI_p->m_uiSize,
+ sizeof(EplApiProcessImageInstance_g.
+ m_abProcessImageInput)));
+#endif
+#endif
+
+ return Ret;
+}
+
+//----------------------------------------------------------------------------
+// Function: EplApiProcessImageExchangeOut()
+//
+// Description: copies passed output process image to EPL stack.
+//
+// Parameters: pPI_p = output process image
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//----------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplApiProcessImageExchangeOut(tEplApiProcessImage * pPI_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+#if EPL_API_PROCESS_IMAGE_SIZE_OUT > 0
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ copy_from_user(EplApiProcessImageInstance_g.m_abProcessImageOutput,
+ pPI_p->m_pImage,
+ min(pPI_p->m_uiSize,
+ sizeof(EplApiProcessImageInstance_g.
+ m_abProcessImageOutput)));
+#else
+ EPL_MEMCPY(EplApiProcessImageInstance_g.m_abProcessImageOutput,
+ pPI_p->m_pImage,
+ min(pPI_p->m_uiSize,
+ sizeof(EplApiProcessImageInstance_g.
+ m_abProcessImageOutput)));
+#endif
+#endif
+
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+// EOF
diff --git a/drivers/staging/epl/EplCfg.h b/drivers/staging/epl/EplCfg.h
new file mode 100644
index 000000000000..38e958a042a8
--- /dev/null
+++ b/drivers/staging/epl/EplCfg.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: configuration file
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplCfg.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ ...
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/06 k.t.: Start of Implementation
+
+****************************************************************************/
+
+#ifndef _EPLCFG_H_
+#define _EPLCFG_H_
+
+// =========================================================================
+// generic defines which for whole EPL Stack
+// =========================================================================
+#define EPL_USE_DELETEINST_FUNC TRUE
+
+// needed to support datatypes over 32 bit by global.h
+#define USE_VAR64
+
+// EPL_MAX_INSTANCES specifies count of instances of all EPL modules.
+// If it is greater than 1 the first parameter of all
+// functions is the instance number.
+#define EPL_MAX_INSTANCES 1
+
+// This defines the target hardware. Here is encoded wich CPU and wich external
+// peripherals are connected. For possible values refere to target.h. If
+// necessary value is not available EPL stack has to
+// be adapted and tested.
+#define TARGET_HARDWARE TGTHW_PC_WRAPP
+
+// use no FIFOs, make direct calls
+//#define EPL_NO_FIFO
+
+// use no IPC between user- and kernelspace modules, make direct calls
+#define EPL_NO_USER_KERNEL
+
+#ifndef BENCHMARK_MODULES
+#define BENCHMARK_MODULES 0 //0xEE800042L
+#endif
+
+// Default defug level:
+// Only debug traces of these modules will be compiled which flags are set in define DEF_DEBUG_LVL.
+#ifndef DEF_DEBUG_LVL
+#define DEF_DEBUG_LVL 0xEC000000L
+#endif
+// EPL_DBGLVL_OBD = 0x00000004L
+// * EPL_DBGLVL_ASSERT = 0x20000000L
+// * EPL_DBGLVL_ERROR = 0x40000000L
+// * EPL_DBGLVL_ALWAYS = 0x80000000L
+
+// EPL_MODULE_INTEGRATION defines all modules which are included in
+// EPL application. Please add or delete modules for your application.
+#define EPL_MODULE_INTEGRATION EPL_MODULE_OBDK \
+ | EPL_MODULE_PDOK \
+ | EPL_MODULE_NMT_MN \
+ | EPL_MODULE_SDOS \
+ | EPL_MODULE_SDOC \
+ | EPL_MODULE_SDO_ASND \
+ | EPL_MODULE_SDO_UDP \
+ | EPL_MODULE_NMT_CN \
+ | EPL_MODULE_NMTU \
+ | EPL_MODULE_NMTK \
+ | EPL_MODULE_DLLK \
+ | EPL_MODULE_DLLU \
+ | EPL_MODULE_VETH
+// | EPL_MODULE_OBDU
+
+// =========================================================================
+// EPL ethernet driver (Edrv) specific defines
+// =========================================================================
+
+// switch this define to TRUE if Edrv supports fast tx frames
+#define EDRV_FAST_TXFRAMES FALSE
+//#define EDRV_FAST_TXFRAMES TRUE
+
+// switch this define to TRUE if Edrv supports early receive interrupts
+#define EDRV_EARLY_RX_INT FALSE
+//#define EDRV_EARLY_RX_INT TRUE
+
+// enables setting of several port pins for benchmarking purposes
+#define EDRV_BENCHMARK FALSE
+//#define EDRV_BENCHMARK TRUE // MCF_GPIO_PODR_PCIBR
+
+// Call Tx handler (i.e. EplDllCbFrameTransmitted()) already if DMA has finished,
+// otherwise call the Tx handler if frame was actually transmitted over ethernet.
+#define EDRV_DMA_TX_HANDLER FALSE
+//#define EDRV_DMA_TX_HANDLER TRUE
+
+// number of used ethernet controller
+//#define EDRV_USED_ETH_CTRL 1
+
+// =========================================================================
+// Data Link Layer (DLL) specific defines
+// =========================================================================
+
+// switch this define to TRUE if Edrv supports fast tx frames
+// and DLL shall pass PRes as ready to Edrv after SoC
+#define EPL_DLL_PRES_READY_AFTER_SOC FALSE
+//#define EPL_DLL_PRES_READY_AFTER_SOC TRUE
+
+// switch this define to TRUE if Edrv supports fast tx frames
+// and DLL shall pass PRes as ready to Edrv after SoA
+#define EPL_DLL_PRES_READY_AFTER_SOA FALSE
+//#define EPL_DLL_PRES_READY_AFTER_SOA TRUE
+
+// =========================================================================
+// OBD specific defines
+// =========================================================================
+
+// switch this define to TRUE if Epl should compare object range
+// automaticly
+#define EPL_OBD_CHECK_OBJECT_RANGE FALSE
+//#define EPL_OBD_CHECK_OBJECT_RANGE TRUE
+
+// set this define to TRUE if there are strings or domains in OD, which
+// may be changed in object size and/or object data pointer by its object
+// callback function (called event kObdEvWrStringDomain)
+//#define EPL_OBD_USE_STRING_DOMAIN_IN_RAM FALSE
+#define EPL_OBD_USE_STRING_DOMAIN_IN_RAM TRUE
+
+#define EPL_OBD_USE_VARIABLE_SUBINDEX_TAB TRUE
+
+// =========================================================================
+// Timer module specific defines
+// =========================================================================
+
+// if TRUE it uses the Timer module implementation of EPL user also in EPL kernel
+#define EPL_TIMER_USE_USER TRUE
+
+// if TRUE the high resolution timer module will be used
+#define EPL_TIMER_USE_HIGHRES TRUE
+//#define EPL_TIMER_USE_HIGHRES FALSE
+
+#endif //_EPLCFG_H_
diff --git a/drivers/staging/epl/EplDef.h b/drivers/staging/epl/EplDef.h
new file mode 100644
index 000000000000..1dc8108449c5
--- /dev/null
+++ b/drivers/staging/epl/EplDef.h
@@ -0,0 +1,355 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for EPL default constants
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDef.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.15 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_DEF_H_
+#define _EPL_DEF_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define EPL_C_ADR_BROADCAST 0xFF // EPL broadcast address
+#define EPL_C_ADR_DIAG_DEF_NODE_ID 0xFD // EPL default address of dignostic device
+#define EPL_C_ADR_DUMMY_NODE_ID 0xFC // EPL dummy node address
+#define EPL_C_ADR_INVALID 0x00 // invalid EPL address
+#define EPL_C_ADR_MN_DEF_NODE_ID 0xF0 // EPL default address of MN
+#define EPL_C_ADR_RT1_DEF_NODE_ID 0xFE // EPL default address of router type 1
+#define EPL_C_DLL_ASND_PRIO_NMTRQST 7 // increased ASnd request priority to be used by NMT Requests
+#define EPL_C_DLL_ASND_PRIO_STD 0 // standard ASnd request priority
+#define EPL_C_DLL_ETHERTYPE_EPL 0x88AB
+#define EPL_C_DLL_ISOCHR_MAX_PAYL 1490 // Byte: maximum size of PReq and PRes payload data, requires C_IP_MAX_MTU
+#define EPL_C_DLL_MAX_ASYNC_MTU 1500 // Byte: maximum asynchronous payload in bytes
+#define EPL_C_DLL_MAX_PAYL_OFFSET 1499 // Byte: maximum offset of Ethernet frame payload, requires C_IP_MAX_MTU
+#define EPL_C_DLL_MAX_RS 7
+#define EPL_C_DLL_MIN_ASYNC_MTU 282 // Byte: minimum asynchronous payload in bytes.
+#define EPL_C_DLL_MIN_PAYL_OFFSET 45 // Byte: minimum offset of Ethernet frame payload
+#define EPL_C_DLL_MULTICAST_ASND 0x01111E000004LL // EPL ASnd multicast MAC address, canonical form
+#define EPL_C_DLL_MULTICAST_PRES 0x01111E000002LL // EPL PRes multicast MAC address, canonical form
+#define EPL_C_DLL_MULTICAST_SOA 0x01111E000003LL // EPL SoA multicast MAC address, canonical form
+#define EPL_C_DLL_MULTICAST_SOC 0x01111E000001LL // EPL Soc multicast MAC address, canonical form
+#define EPL_C_DLL_PREOP1_START_CYCLES 10 // number of unassigning SoA frames at start of NMT_MS_PRE_OPERATIONAL_1
+#define EPL_C_DLL_T_BITTIME 10 // ns: Transmission time per bit on 100 Mbit/s network
+#define EPL_C_DLL_T_EPL_PDO_HEADER 10 // Byte: size of PReq and PRes EPL PDO message header
+#define EPL_C_DLL_T_ETH2_WRAPPER 18 // Byte: size of Ethernet type II wrapper consisting of header and checksum
+#define EPL_C_DLL_T_IFG 640 // ns: Ethernet Interframe Gap
+#define EPL_C_DLL_T_MIN_FRAME 5120 // ns: Size of minimum Ethernet frame (without preamble)
+#define EPL_C_DLL_T_PREAMBLE 960 // ns: Size of Ethernet frame preamble
+
+#define EPL_C_DLL_MINSIZE_SOC 36 // minimum size of SoC without padding and CRC
+#define EPL_C_DLL_MINSIZE_PREQ 60 // minimum size of PRec without CRC
+#define EPL_C_DLL_MINSIZE_PRES 60 // minimum size of PRes without CRC
+#define EPL_C_DLL_MINSIZE_SOA 24 // minimum size of SoA without padding and CRC
+#define EPL_C_DLL_MINSIZE_IDENTRES 176 // minimum size of IdentResponse without CRC
+#define EPL_C_DLL_MINSIZE_STATUSRES 72 // minimum size of StatusResponse without CRC
+#define EPL_C_DLL_MINSIZE_NMTCMD 20 // minimum size of NmtCommand without CommandData, padding and CRC
+#define EPL_C_DLL_MINSIZE_NMTCMDEXT 52 // minimum size of NmtCommand without padding and CRC
+#define EPL_C_DLL_MINSIZE_NMTREQ 20 // minimum size of NmtRequest without CommandData, padding and CRC
+#define EPL_C_DLL_MINSIZE_NMTREQEXT 52 // minimum size of NmtRequest without padding and CRC
+
+#define EPL_C_ERR_MONITOR_DELAY 10 // Error monitoring start delay (not used in DS 1.0.0)
+#define EPL_C_IP_ADR_INVALID 0x00000000L // invalid IP address (0.0.0.0) used to indicate no change
+#define EPL_C_IP_INVALID_MTU 0 // Byte: invalid MTU size used to indicate no change
+#define EPL_C_IP_MAX_MTU 1518 // Byte: maximum size in bytes of the IP stack which must be processed.
+#define EPL_C_IP_MIN_MTU 300 // Byte: minimum size in bytes of the IP stack which must be processed.
+#define EPL_C_NMT_STATE_TOLERANCE 5 // Cycles: maximum reaction time to NMT state commands
+#define EPL_C_NMT_STATREQ_CYCLE 5 // sec: StatusRequest cycle time to be applied to AsyncOnly CNs
+#define EPL_C_SDO_EPL_PORT 3819
+
+#define EPL_C_DLL_MAX_ASND_SERVICE_IDS 5 // see tEplDllAsndServiceId in EplDll.h
+
+// Default configuration
+// ======================
+
+#ifndef EPL_D_PDO_Granularity_U8
+#define EPL_D_PDO_Granularity_U8 8 // minimum size of objects to be mapped in bits UNSIGNED8 O O 1 1
+#endif
+
+#ifndef EPL_NMT_MAX_NODE_ID
+#define EPL_NMT_MAX_NODE_ID 254 // maximum node-ID
+#endif
+
+#ifndef EPL_D_NMT_MaxCNNumber_U8
+#define EPL_D_NMT_MaxCNNumber_U8 239 // maximum number of supported regular CNs in the Node ID range 1 .. 239 UNSIGNED8 O O 239 239
+#endif
+
+// defines for EPL API layer static process image
+#ifndef EPL_API_PROCESS_IMAGE_SIZE_IN
+#define EPL_API_PROCESS_IMAGE_SIZE_IN 0
+#endif
+
+#ifndef EPL_API_PROCESS_IMAGE_SIZE_OUT
+#define EPL_API_PROCESS_IMAGE_SIZE_OUT 0
+#endif
+
+// configure whether OD access events shall be forwarded
+// to user callback function.
+// Because of reentrancy for local OD accesses, this has to be disabled
+// when application resides in other address space as the stack (e.g. if
+// EplApiLinuxUser.c and EplApiLinuxKernel.c are used)
+#ifndef EPL_API_OBD_FORWARD_EVENT
+#define EPL_API_OBD_FORWARD_EVENT TRUE
+#endif
+
+#ifndef EPL_OBD_MAX_STRING_SIZE
+#define EPL_OBD_MAX_STRING_SIZE 32 // is used for objects 0x1008/0x1009/0x100A
+#endif
+
+#ifndef EPL_OBD_USE_STORE_RESTORE
+#define EPL_OBD_USE_STORE_RESTORE FALSE
+#endif
+
+#ifndef EPL_OBD_CHECK_OBJECT_RANGE
+#define EPL_OBD_CHECK_OBJECT_RANGE TRUE
+#endif
+
+#ifndef EPL_OBD_USE_STRING_DOMAIN_IN_RAM
+#define EPL_OBD_USE_STRING_DOMAIN_IN_RAM TRUE
+#endif
+
+#ifndef EPL_OBD_USE_VARIABLE_SUBINDEX_TAB
+#define EPL_OBD_USE_VARIABLE_SUBINDEX_TAB TRUE
+#endif
+
+#ifndef EPL_OBD_USE_KERNEL
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0)
+#define EPL_OBD_USE_KERNEL TRUE
+#else
+#define EPL_OBD_USE_KERNEL FALSE
+#endif
+#endif
+
+#ifndef EPL_OBD_INCLUDE_A000_TO_DEVICE_PART
+#define EPL_OBD_INCLUDE_A000_TO_DEVICE_PART FALSE
+#endif
+
+#ifndef EPL_VETH_NAME
+#define EPL_VETH_NAME "epl" // name of net device in Linux
+#endif
+
+/*
+#define EPL_D_CFG_ConfigManager_BOOL // Ability of a MN node to perform Configuration Manager functions BOOLEAN O - N -
+#define EPL_D_CFM_VerifyConf_BOOL // Support of objects CFM_VerifyConfiguration_REC, CFM_ExpConfDateList_AU32, CFM_ExpConfTimeList_AU32 BOOLEAN O O N N
+#define EPL_D_CFM_VerifyConfId_BOOL // Support of objects CFM_VerifyConfiguration_REC.ConfId_U32 and CFM_ExpConfIdList_AU32 BOOLEAN O O N N
+#define EPL_D_DLL_CNFeatureIsochr_BOOL // CNs ability to perform isochronous functions BOOLEAN - O - Y
+#define EPL_D_DLL_CNFeatureMultiplex_BOOL // nodes ability to perform control of multiplexed isochronous communication BOOLEAN - O - N
+#define EPL_D_DLL_FeatureCN_BOOL // nodes ability to perform CN functions BOOLEAN O O Y Y
+#define EPL_D_DLL_FeatureMN_BOOL // nodes ability to perform MN functions BOOLEAN M O - N
+#define EPL_D_DLL_MNFeatureMultiplex_BOOL // MNs ability to perform control of multiplexed isochronous communication BOOLEAN O - Y -
+#define EPL_D_DLL_MNFeaturePResTx_BOOL // MNs ability to transmit PRes BOOLEAN O - Y -
+#define EPL_D_NMT_ASndRxMaxPayload_U16 // size of ASnd frame receive buffer UNSIGNED16 M M - -
+#define EPL_D_NMT_ASndTxMaxPayload_U16 // size of ASnd frame transmit buffer UNSIGNED16 M M - -
+#define EPL_D_NMT_CNASnd2SoC_U32 // minimum delay between end of reception of ASnd and start of reception of SoC UNSIGNED32 - M - -
+#define EPL_D_NMT_CNASndMaxLatency_U32 // delay between end of SoA reception and start of ASnd transmission UNSIGNED32 - M - -
+#define EPL_D_NMT_CNPResMaxLatency_U32 // delay between end of PReq reception and start of PRes transmission UNSIGNED32 - M - -
+#define EPL_D_NMT_CNSoC2PReq_U32 // CN SoC handling maximum time, a subsequent PReq wont be handled before SoC handling was finished UNSIGNED32 - M - -
+#define EPL_D_NMT_DeviceType_U32 // Device Type ID UNSIGNED32 M M - -
+#define EPL_D_NMT_EPLVers_U8 EPL // Version implemented by the device UNSIGNED8 M M - -
+#define EPL_D_NMT_ExtStateCmd_BOOL // abitilty to support Extended NMT State Commands BOOLEAN O O Y Y
+#define EPL_D_NMT_InfoSvc_BOOL // ability to support NMT Info Services BOOLEAN O - Y -
+#define EPL_D_NMT_InterfaceAddr_Xh_OSTR // Physical Address of Interface No. Xh OCTET_STRING M M - -
+#define EPL_D_NMT_InterfaceDescr_Xh_VSTR // Description text of Interface No. Xh VISIBLE_STRINGM M - -
+#define EPL_D_NMT_InterfaceMtu_Xh_U32 // MTU of Interface No. Xh UNSIGNED32 M M - -
+#define EPL_D_NMT_InterfaceType_Xh_U8 // Type of Interface No. Xh UNSIGNED8 M M - -
+#define EPL_D_NMT_IsochrRxMaxPayload_U16 // size of isochronous frame receive buffer UNSIGNED16 M M - -
+#define EPL_D_NMT_IsochrTxMaxPayload_U16 // size of isochronous frame transmit buffer UNSIGNED16 M M - -
+#define EPL_D_NMT_ManufactDevName_VS // Manufacturer Device Name VISIBLE_STRING O O - -
+#define EPL_D_NMT_ManufactHwVers_VS // Manufacturer HW version VISIBLE_STRING O O - -
+#define EPL_D_NMT_ManufactSwVers_VS // Manufacturer SW version VISIBLE_STRING O O - -
+#define EPL_D_NMT_MaxCNNodeID_U8 // maximum Node ID available for regular CNs the entry provides an upper limit to the NodeID available for cross traffic PDO reception from a regular CN UNSIGNED8 O O 239 239
+#define EPL_D_NMT_MaxCNNumber_U8 // maximum number of supported regular CNs in the Node ID range 1 .. 239 UNSIGNED8 O O 239 239
+#define EPL_D_NMT_MaxHeartbeats_U8 // number of guard channels UNSIGNED8 O O 254 254
+#define EPL_D_NMT_MNASnd2SoC_U32 // minimum delay between end of reception of ASnd and start of transmission of SoC UNSIGNED32 M - - -
+#define EPL_D_NMT_MNMultiplCycMax_U8 // maximum number of EPL cycles per multiplexed cycle UNSIGNED8 O - 0 -
+#define EPL_D_NMT_MNPRes2PReq_U32 // delay between end of PRes reception and start of PReq transmission UNSIGNED32 M - - -
+#define EPL_D_NMT_MNPRes2PRes_U32 // delay between end of reception of PRes from CNn and start of transmission of PRes by MN UNSIGNED32 M - - -
+#define EPL_D_NMT_MNPResRx2SoA_U32 // delay between end of reception of PRes from CNn and start of transmission of SoA by MN UNSIGNED32 M - - -
+#define EPL_D_NMT_MNPResTx2SoA_U32 // delay between end of PRes transmission by MN and start of transmission of SoA by MN UNSIGNED32 M - - -
+#define EPL_D_NMT_MNSoA2ASndTx_U32 // delay between end of transmission of SoA and start of transmission of ASnd by MN UNSIGNED32 M - - -
+#define EPL_D_NMT_MNSoC2PReq_U32 // MN minimum delay between end of SoC transmission and start of PReq transmission UNSIGNED32 M - - -
+#define EPL_D_NMT_NMTSvcViaUDPIP_BOOL // Ability of a node to perform NMT services via UDP/IP BOOLEAN O - Y -
+#define EPL_D_NMT_NodeIDByHW_BOOL // Ability of a node to support NodeID setup by HW BOOLEAN O O Y Y
+#define EPL_D_NMT_NodeIDBySW_BOOL // Ability of a node to support NodeID setup by SW BOOLEAN O O N N
+#define EPL_D_NMT_ProductCode_U32 // Identity Object Product Code UNSIGNED32 M M - -
+#define EPL_D_NMT_RevisionNo_U32 // Identity Object Revision Number UNSIGNED32 M M - -
+#define EPL_D_NMT_SerialNo_U32 // Identity Object Serial Number UNSIGNED32 M M - -
+#define EPL_D_NMT_SimpleBoot_BOOL // Ability of a MN node to perform Simple Boot Process, if not set Indivual Boot Process shall be proviced BOOLEAN M - - -
+#define EPL_D_NMT_VendorID_U32 // Identity Object Vendor ID UNSIGNED32 M M - -
+#define EPL_D_NWL_Forward_BOOL // Ability of node to forward datagrams BOOLEAN O O N N
+#define EPL_D_NWL_IPSupport_BOOL // Ability of the node cummunicate via IP BOOLEAN - - Y Y
+#define EPL_D_PDO_DynamicMapping_BOOL // Ability of a node to perform dynamic PDO mapping BOOLEAN O O Y Y
+#define EPL_D_PDO_MaxDescrMem_U32 // maximum cumulative memory consumption of TPDO and RPDO describing objects in byte UNSIGNED32 O O MAX_U32 MAX_U32
+#define EPL_D_PDO_RPDOChannels_U8 // number of supported RPDO channels UNSIGNED8 O O 256 256
+#define EPL_D_PDO_RPDOMaxMem_U32 // Maximum memory available for RPDO data per EPL cycle in byte UNSIGNED32 O O MAX_U32 MAX_U32
+#define EPL_D_PDO_RPDOObjects_U8 // Number of supported mapped objects per RPDO channel UNSIGNED8 O O 254 254
+#define EPL_D_PDO_TPDOChannels_U8 // number of supported TPDO channels UNSIGNED8 O - 256 -
+#define EPL_D_PDO_TPDOMaxMem_U32 // Maximum memory available for TPDO data per EPL cycle in byte UNSIGNED32 O O MAX_U32 MAX_U32
+#define EPL_D_PDO_TPDOObjects_U8 // Number of supported mapped objects per TPDO channel UNSIGNED8 O O 254 254
+#define EPL_D_SDO_ViaASnd_BOOL // Ability of a CN to perform SDO transfer by EPL ASnd BOOLEAN - M - -
+#define EPL_D_SDO_ViaPDO_BOOL // Ability of a node to perform SDO transfer by PDO BOOLEAN O O N N
+#define EPL_D_SDO_ViaUDPIP_BOOL // Ability of a CN to perform SDO transfer by UDP/IP BOOLEAN - M - -
+#define EPL_D_SYN_OptimizedSync_BOOL // Ability of node to perform optimized synchronisation BOOLEAN O O N N
+*/
+
+// Emergency error codes
+// ======================
+#define EPL_E_NO_ERROR 0x0000
+// 0xFxxx manufacturer specific error codes
+#define EPL_E_NMT_NO_IDENT_RES 0xF001
+#define EPL_E_NMT_NO_STATUS_RES 0xF002
+
+// 0x816x HW errors
+#define EPL_E_DLL_BAD_PHYS_MODE 0x8161
+#define EPL_E_DLL_COLLISION 0x8162
+#define EPL_E_DLL_COLLISION_TH 0x8163
+#define EPL_E_DLL_CRC_TH 0x8164
+#define EPL_E_DLL_LOSS_OF_LINK 0x8165
+#define EPL_E_DLL_MAC_BUFFER 0x8166
+// 0x82xx Protocol errors
+#define EPL_E_DLL_ADDRESS_CONFLICT 0x8201
+#define EPL_E_DLL_MULTIPLE_MN 0x8202
+// 0x821x Frame size errors
+#define EPL_E_PDO_SHORT_RX 0x8210
+#define EPL_E_PDO_MAP_VERS 0x8211
+#define EPL_E_NMT_ASND_MTU_DIF 0x8212
+#define EPL_E_NMT_ASND_MTU_LIM 0x8213
+#define EPL_E_NMT_ASND_TX_LIM 0x8214
+// 0x823x Timing errors
+#define EPL_E_NMT_CYCLE_LEN 0x8231
+#define EPL_E_DLL_CYCLE_EXCEED 0x8232
+#define EPL_E_DLL_CYCLE_EXCEED_TH 0x8233
+#define EPL_E_NMT_IDLE_LIM 0x8234
+#define EPL_E_DLL_JITTER_TH 0x8235
+#define EPL_E_DLL_LATE_PRES_TH 0x8236
+#define EPL_E_NMT_PREQ_CN 0x8237
+#define EPL_E_NMT_PREQ_LIM 0x8238
+#define EPL_E_NMT_PRES_CN 0x8239
+#define EPL_E_NMT_PRES_RX_LIM 0x823A
+#define EPL_E_NMT_PRES_TX_LIM 0x823B
+// 0x824x Frame errors
+#define EPL_E_DLL_INVALID_FORMAT 0x8241
+#define EPL_E_DLL_LOSS_PREQ_TH 0x8242
+#define EPL_E_DLL_LOSS_PRES_TH 0x8243
+#define EPL_E_DLL_LOSS_SOA_TH 0x8244
+#define EPL_E_DLL_LOSS_SOC_TH 0x8245
+// 0x84xx BootUp Errors
+#define EPL_E_NMT_BA1 0x8410 // other MN in MsNotActive active
+#define EPL_E_NMT_BA1_NO_MN_SUPPORT 0x8411 // MN is not supported
+#define EPL_E_NMT_BPO1 0x8420 // mandatory CN was not found or failed in BootStep1
+#define EPL_E_NMT_BPO1_GET_IDENT 0x8421 // IdentRes was not received
+#define EPL_E_NMT_BPO1_DEVICE_TYPE 0x8422 // wrong device type
+#define EPL_E_NMT_BPO1_VENDOR_ID 0x8423 // wrong vendor ID
+#define EPL_E_NMT_BPO1_PRODUCT_CODE 0x8424 // wrong product code
+#define EPL_E_NMT_BPO1_REVISION_NO 0x8425 // wrong revision number
+#define EPL_E_NMT_BPO1_SERIAL_NO 0x8426 // wrong serial number
+#define EPL_E_NMT_BPO1_CF_VERIFY 0x8428 // verification of configuration failed
+#define EPL_E_NMT_BPO2 0x8430 // mandatory CN failed in BootStep2
+#define EPL_E_NMT_BRO 0x8440 // CheckCommunication failed for mandatory CN
+#define EPL_E_NMT_WRONG_STATE 0x8480 // mandatory CN has wrong NMT state
+
+// Defines for object 0x1F80 NMT_StartUp_U32
+// ==========================================
+#define EPL_NMTST_STARTALLNODES 0x00000002L // Bit 1
+#define EPL_NMTST_NO_AUTOSTART 0x00000004L // Bit 2
+#define EPL_NMTST_NO_STARTNODE 0x00000008L // Bit 3
+#define EPL_NMTST_RESETALL_MAND_CN 0x00000010L // Bit 4
+#define EPL_NMTST_STOPALL_MAND_CN 0x00000040L // Bit 6
+#define EPL_NMTST_NO_AUTOPREOP2 0x00000080L // Bit 7
+#define EPL_NMTST_NO_AUTOREADYTOOP 0x00000100L // Bit 8
+#define EPL_NMTST_EXT_CNIDENTCHECK 0x00000200L // Bit 9
+#define EPL_NMTST_SWVERSIONCHECK 0x00000400L // Bit 10
+#define EPL_NMTST_CONFCHECK 0x00000800L // Bit 11
+#define EPL_NMTST_NO_RETURN_PREOP1 0x00001000L // Bit 12
+#define EPL_NMTST_BASICETHERNET 0x00002000L // Bit 13
+
+// Defines for object 0x1F81 NMT_NodeAssignment_AU32
+// ==================================================
+#define EPL_NODEASSIGN_NODE_EXISTS 0x00000001L // Bit 0
+#define EPL_NODEASSIGN_NODE_IS_CN 0x00000002L // Bit 1
+#define EPL_NODEASSIGN_START_CN 0x00000004L // Bit 2
+#define EPL_NODEASSIGN_MANDATORY_CN 0x00000008L // Bit 3
+#define EPL_NODEASSIGN_KEEPALIVE 0x00000010L //currently not used in EPL V2 standard
+#define EPL_NODEASSIGN_SWVERSIONCHECK 0x00000020L // Bit 5
+#define EPL_NODEASSIGN_SWUPDATE 0x00000040L // Bit 6
+#define EPL_NODEASSIGN_ASYNCONLY_NODE 0x00000100L // Bit 8
+#define EPL_NODEASSIGN_MULTIPLEXED_CN 0x00000200L // Bit 9
+#define EPL_NODEASSIGN_RT1 0x00000400L // Bit 10
+#define EPL_NODEASSIGN_RT2 0x00000800L // Bit 11
+#define EPL_NODEASSIGN_MN_PRES 0x00001000L // Bit 12
+#define EPL_NODEASSIGN_VALID 0x80000000L // Bit 31
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_DEF_H_
diff --git a/drivers/staging/epl/EplDll.h b/drivers/staging/epl/EplDll.h
new file mode 100644
index 000000000000..36657f2daf8b
--- /dev/null
+++ b/drivers/staging/epl/EplDll.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for DLL module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDll.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/08 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_DLL_H_
+#define _EPL_DLL_H_
+
+#include "EplInc.h"
+#include "EplFrame.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef EPL_DLL_MAX_ASND_SERVICE_ID
+#define EPL_DLL_MAX_ASND_SERVICE_ID (EPL_C_DLL_MAX_ASND_SERVICE_IDS + 1) // last is kEplDllAsndSdo == 5
+#endif
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef enum {
+ kEplDllAsndNotDefined = 0x00,
+ kEplDllAsndIdentResponse = 0x01,
+ kEplDllAsndStatusResponse = 0x02,
+ kEplDllAsndNmtRequest = 0x03,
+ kEplDllAsndNmtCommand = 0x04,
+ kEplDllAsndSdo = 0x05
+} tEplDllAsndServiceId;
+
+typedef enum {
+ kEplDllAsndFilterNone = 0x00,
+ kEplDllAsndFilterLocal = 0x01, // receive only ASnd frames with local or broadcast node ID
+ kEplDllAsndFilterAny = 0x02, // receive any ASnd frame
+} tEplDllAsndFilter;
+
+typedef enum {
+ kEplDllReqServiceNo = 0x00,
+ kEplDllReqServiceIdent = 0x01,
+ kEplDllReqServiceStatus = 0x02,
+ kEplDllReqServiceNmtRequest = 0x03,
+ kEplDllReqServiceUnspecified = 0xFF,
+
+} tEplDllReqServiceId;
+
+typedef enum {
+ kEplDllAsyncReqPrioNmt = 0x07, // PRIO_NMT_REQUEST
+ kEplDllAsyncReqPrio6 = 0x06,
+ kEplDllAsyncReqPrio5 = 0x05,
+ kEplDllAsyncReqPrio4 = 0x04,
+ kEplDllAsyncReqPrioGeneric = 0x03, // PRIO_GENERIC_REQUEST
+ kEplDllAsyncReqPrio2 = 0x02, // till WSP 0.1.3: PRIO_ABOVE_GENERIC
+ kEplDllAsyncReqPrio1 = 0x01, // till WSP 0.1.3: PRIO_BELOW_GENERIC
+ kEplDllAsyncReqPrio0 = 0x00, // till WSP 0.1.3: PRIO_GENERIC_REQUEST
+
+} tEplDllAsyncReqPriority;
+
+typedef struct {
+ unsigned int m_uiFrameSize;
+ tEplFrame *m_pFrame;
+ tEplNetTime m_NetTime;
+
+} tEplFrameInfo;
+
+typedef struct {
+ unsigned int m_uiSizeOfStruct;
+ BOOL m_fAsyncOnly; // do not need to register PRes-Frame
+ unsigned int m_uiNodeId; // local node ID
+
+ // 0x1F82: NMT_FeatureFlags_U32
+ DWORD m_dwFeatureFlags;
+ // Cycle Length (0x1006: NMT_CycleLen_U32) in [us]
+ DWORD m_dwCycleLen; // required for error detection
+ // 0x1F98: NMT_CycleTiming_REC
+ // 0x1F98.1: IsochrTxMaxPayload_U16
+ unsigned int m_uiIsochrTxMaxPayload; // const
+ // 0x1F98.2: IsochrRxMaxPayload_U16
+ unsigned int m_uiIsochrRxMaxPayload; // const
+ // 0x1F98.3: PResMaxLatency_U32
+ DWORD m_dwPresMaxLatency; // const in [ns], only required for IdentRes
+ // 0x1F98.4: PReqActPayloadLimit_U16
+ unsigned int m_uiPreqActPayloadLimit; // required for initialisation (+24 bytes)
+ // 0x1F98.5: PResActPayloadLimit_U16
+ unsigned int m_uiPresActPayloadLimit; // required for initialisation of Pres frame (+24 bytes)
+ // 0x1F98.6: ASndMaxLatency_U32
+ DWORD m_dwAsndMaxLatency; // const in [ns], only required for IdentRes
+ // 0x1F98.7: MultiplCycleCnt_U8
+ unsigned int m_uiMultiplCycleCnt; // required for error detection
+ // 0x1F98.8: AsyncMTU_U16
+ unsigned int m_uiAsyncMtu; // required to set up max frame size
+ // $$$ 0x1F98.9: Prescaler_U16
+ // $$$ Multiplexed Slot
+
+ // 0x1C14: DLL_LossOfFrameTolerance_U32 in [ns]
+ DWORD m_dwLossOfFrameTolerance;
+
+ // 0x1F8A: NMT_MNCycleTiming_REC
+ // 0x1F8A.1: WaitSoCPReq_U32 in [ns]
+ DWORD m_dwWaitSocPreq;
+
+ // 0x1F8A.2: AsyncSlotTimeout_U32 in [ns]
+ DWORD m_dwAsyncSlotTimeout;
+
+} tEplDllConfigParam;
+
+typedef struct {
+ unsigned int m_uiSizeOfStruct;
+ DWORD m_dwDeviceType; // NMT_DeviceType_U32
+ DWORD m_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32
+ DWORD m_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32
+ DWORD m_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32
+ DWORD m_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32
+ QWORD m_qwVendorSpecificExt1;
+ DWORD m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
+ DWORD m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
+ DWORD m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
+ DWORD m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
+ DWORD m_dwIpAddress;
+ DWORD m_dwSubnetMask;
+ DWORD m_dwDefaultGateway;
+ BYTE m_sHostname[32];
+ BYTE m_abVendorSpecificExt2[48];
+
+} tEplDllIdentParam;
+
+typedef struct {
+ unsigned int m_uiNodeId;
+ WORD m_wPreqPayloadLimit; // object 0x1F8B: NMT_MNPReqPayloadLimitList_AU16
+ WORD m_wPresPayloadLimit; // object 0x1F8D: NMT_PResPayloadLimitList_AU16
+ DWORD m_dwPresTimeout; // object 0x1F92: NMT_MNCNPResTimeout_AU32
+
+} tEplDllNodeInfo;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_DLL_H_
diff --git a/drivers/staging/epl/EplDllCal.h b/drivers/staging/epl/EplDllCal.h
new file mode 100644
index 000000000000..24460087e987
--- /dev/null
+++ b/drivers/staging/epl/EplDllCal.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for DLL Communication Abstraction Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDllCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/20 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_DLLCAL_H_
+#define _EPL_DLLCAL_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+/*#ifndef EPL_DLLCAL_BUFFER_ID_RX
+#define EPL_DLLCAL_BUFFER_ID_RX "EplSblDllCalRx"
+#endif
+
+#ifndef EPL_DLLCAL_BUFFER_SIZE_RX
+#define EPL_DLLCAL_BUFFER_SIZE_RX 32767
+#endif
+*/
+#ifndef EPL_DLLCAL_BUFFER_ID_TX_NMT
+#define EPL_DLLCAL_BUFFER_ID_TX_NMT "EplSblDllCalTxNmt"
+#endif
+
+#ifndef EPL_DLLCAL_BUFFER_SIZE_TX_NMT
+#define EPL_DLLCAL_BUFFER_SIZE_TX_NMT 32767
+#endif
+
+#ifndef EPL_DLLCAL_BUFFER_ID_TX_GEN
+#define EPL_DLLCAL_BUFFER_ID_TX_GEN "EplSblDllCalTxGen"
+#endif
+
+#ifndef EPL_DLLCAL_BUFFER_SIZE_TX_GEN
+#define EPL_DLLCAL_BUFFER_SIZE_TX_GEN 32767
+#endif
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef struct {
+ tEplDllAsndServiceId m_ServiceId;
+ tEplDllAsndFilter m_Filter;
+
+} tEplDllCalAsndServiceIdFilter;
+
+typedef struct {
+ tEplDllReqServiceId m_Service;
+ unsigned int m_uiNodeId;
+ BYTE m_bSoaFlag1;
+
+} tEplDllCalIssueRequest;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_DLLKCAL_H_
diff --git a/drivers/staging/epl/EplDllk.c b/drivers/staging/epl/EplDllk.c
new file mode 100644
index 000000000000..9e22641055c6
--- /dev/null
+++ b/drivers/staging/epl/EplDllk.c
@@ -0,0 +1,4054 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for kernel DLL module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDllk.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.21 $ $Date: 2008/11/13 17:13:09 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/12 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "kernel/EplDllk.h"
+#include "kernel/EplDllkCal.h"
+#include "kernel/EplEventk.h"
+#include "kernel/EplNmtk.h"
+#include "edrv.h"
+#include "Benchmark.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+#include "kernel/EplPdok.h"
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
+#include "kernel/VirtualEthernet.h"
+#endif
+
+//#if EPL_TIMER_USE_HIGHRES != FALSE
+#include "kernel/EplTimerHighResk.h"
+//#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) == 0)
+#error "EPL module DLLK needs EPL module NMTK!"
+#endif
+
+#if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) && (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
+#error "EPL module DLLK: select only one of EPL_DLL_PRES_READY_AFTER_SOA and EPL_DLL_PRES_READY_AFTER_SOC."
+#endif
+
+#if ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)) \
+ && (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0)
+#error "EPL module DLLK: currently, EPL_DLL_PRES_READY_AFTER_* is not supported if EPL_MODULE_NMT_MN is enabled."
+#endif
+
+#if (EDRV_FAST_TXFRAMES == FALSE) && \
+ ((EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE))
+#error "EPL module DLLK: EPL_DLL_PRES_READY_AFTER_* is enabled, but not EDRV_FAST_TXFRAMES."
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#define TGT_DBG_POST_TRACE_VALUE(v)
+#endif
+#define EPL_DLLK_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
+ TGT_DBG_POST_TRACE_VALUE((kEplEventSinkDllk << 28) | (Event_p << 24) \
+ | (uiNodeId_p << 16) | wErrorCode_p)
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplDllk */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// defines for indexes of tEplDllInstance.m_pTxFrameInfo
+#define EPL_DLLK_TXFRAME_IDENTRES 0 // IdentResponse on CN / MN
+#define EPL_DLLK_TXFRAME_STATUSRES 1 // StatusResponse on CN / MN
+#define EPL_DLLK_TXFRAME_NMTREQ 2 // NMT Request from FIFO on CN / MN
+#define EPL_DLLK_TXFRAME_NONEPL 3 // non-EPL frame from FIFO on CN / MN
+#define EPL_DLLK_TXFRAME_PRES 4 // PRes on CN / MN
+#define EPL_DLLK_TXFRAME_SOC 5 // SoC on MN
+#define EPL_DLLK_TXFRAME_SOA 6 // SoA on MN
+#define EPL_DLLK_TXFRAME_PREQ 7 // PReq on MN
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+#define EPL_DLLK_TXFRAME_COUNT (7 + EPL_D_NMT_MaxCNNumber_U8 + 2) // on MN: 7 + MaxPReq of regular CNs + 1 Diag + 1 Router
+#else
+#define EPL_DLLK_TXFRAME_COUNT 5 // on CN: 5
+#endif
+
+#define EPL_DLLK_BUFLEN_EMPTY 0 // buffer is empty
+#define EPL_DLLK_BUFLEN_FILLING 1 // just the buffer is being filled
+#define EPL_DLLK_BUFLEN_MIN 60 // minimum ethernet frame length
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef enum {
+ kEplDllGsInit = 0x00, // MN/CN: initialisation (< PreOp2)
+ kEplDllCsWaitPreq = 0x01, // CN: wait for PReq frame
+ kEplDllCsWaitSoc = 0x02, // CN: wait for SoC frame
+ kEplDllCsWaitSoa = 0x03, // CN: wait for SoA frame
+ kEplDllMsNonCyclic = 0x04, // MN: reduced EPL cycle (PreOp1)
+ kEplDllMsWaitSocTrig = 0x05, // MN: wait for SoC trigger (cycle timer)
+ kEplDllMsWaitPreqTrig = 0x06, // MN: wait for (first) PReq trigger (WaitSoCPReq_U32)
+ kEplDllMsWaitPres = 0x07, // MN: wait for PRes frame from CN
+ kEplDllMsWaitSoaTrig = 0x08, // MN: wait for SoA trigger (PRes transmitted)
+ kEplDllMsWaitAsndTrig = 0x09, // MN: wait for ASnd trigger (SoA transmitted)
+ kEplDllMsWaitAsnd = 0x0A, // MN: wait for ASnd frame if SoA contained invitation
+
+} tEplDllState;
+
+typedef struct {
+ BYTE m_be_abSrcMac[6];
+ tEdrvTxBuffer *m_pTxBuffer; // Buffers for Tx-Frames
+ unsigned int m_uiMaxTxFrames;
+ BYTE m_bFlag1; // Flag 1 with EN, EC for PRes, StatusRes
+ BYTE m_bMnFlag1; // Flag 1 with EA, ER from PReq, SoA of MN
+ BYTE m_bFlag2; // Flag 2 with PR and RS for PRes, StatusRes, IdentRes
+ tEplDllConfigParam m_DllConfigParam;
+ tEplDllIdentParam m_DllIdentParam;
+ tEplDllState m_DllState;
+ tEplDllkCbAsync m_pfnCbAsync;
+ tEplDllAsndFilter m_aAsndFilter[EPL_DLL_MAX_ASND_SERVICE_ID];
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ tEplDllkNodeInfo *m_pFirstNodeInfo;
+ tEplDllkNodeInfo *m_pCurNodeInfo;
+ tEplDllkNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID];
+ tEplDllReqServiceId m_LastReqServiceId;
+ unsigned int m_uiLastTargetNodeId;
+#endif
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ tEplTimerHdl m_TimerHdlCycle; // used for EPL cycle monitoring on CN and generation on MN
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ tEplTimerHdl m_TimerHdlResponse; // used for CN response monitoring
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+#endif
+
+ unsigned int m_uiCycleCount; // cycle counter (needed for multiplexed cycle support)
+ unsigned long long m_ullFrameTimeout; // frame timeout (cycle length + loss of frame tolerance)
+
+} tEplDllkInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+// if no dynamic memory allocation shall be used
+// define structures statically
+static tEplDllkInstance EplDllkInstance_g;
+
+static tEdrvTxBuffer aEplDllkTxBuffer_l[EPL_DLLK_TXFRAME_COUNT];
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+// change DLL state on event
+static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
+ tEplNmtState NmtState_p);
+
+// called from EdrvInterruptHandler()
+static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p);
+
+// called from EdrvInterruptHandler()
+static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p);
+
+// check frame and set missing information
+static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
+ unsigned int uiFrameSize_p);
+
+// called by high resolution timer module to monitor EPL cycle as CN
+#if EPL_TIMER_USE_HIGHRES != FALSE
+static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p);
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+// MN: returns internal node info structure
+static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p);
+
+// transmit SoA
+static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
+ tEplDllState * pDllStateProposed_p,
+ BOOL fEnableInvitation_p);
+
+static tEplKernel EplDllkMnSendSoc(void);
+
+static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
+ tEplDllState * pDllStateProposed_p);
+
+static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
+ ReqServiceId_p,
+ unsigned int uiNodeId_p);
+
+static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p);
+
+static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg *
+ pEventArg_p);
+
+#endif
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkAddInstance()
+//
+// Description: add and initialize new instance of EPL stack
+//
+// Parameters: pInitParam_p = initialisation parameters like MAC address
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiIndex;
+ tEdrvInitParam EdrvInitParam;
+
+ // reset instance structure
+ EPL_MEMSET(&EplDllkInstance_g, 0, sizeof(EplDllkInstance_g));
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ Ret = EplTimerHighReskInit();
+ if (Ret != kEplSuccessful) { // error occured while initializing high resolution timer module
+ goto Exit;
+ }
+#endif
+
+ // if dynamic memory allocation available
+ // allocate instance structure
+ // allocate TPDO and RPDO table with default size
+
+ // initialize and link pointers in instance structure to frame tables
+ EplDllkInstance_g.m_pTxBuffer = aEplDllkTxBuffer_l;
+ EplDllkInstance_g.m_uiMaxTxFrames =
+ sizeof(aEplDllkTxBuffer_l) / sizeof(tEdrvTxBuffer);
+
+ // initialize state
+ EplDllkInstance_g.m_DllState = kEplDllGsInit;
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // set up node info structure
+ for (uiIndex = 0; uiIndex < tabentries(EplDllkInstance_g.m_aNodeInfo);
+ uiIndex++) {
+ EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
+ EplDllkInstance_g.m_aNodeInfo[uiIndex].m_wPresPayloadLimit =
+ 0xFFFF;
+ }
+#endif
+
+ // initialize Edrv
+ EPL_MEMCPY(EdrvInitParam.m_abMyMacAddr, pInitParam_p->m_be_abSrcMac, 6);
+ EdrvInitParam.m_pfnRxHandler = EplDllkCbFrameReceived;
+ EdrvInitParam.m_pfnTxHandler = EplDllkCbFrameTransmitted;
+ Ret = EdrvInit(&EdrvInitParam);
+ if (Ret != kEplSuccessful) { // error occured while initializing ethernet driver
+ goto Exit;
+ }
+ // copy local MAC address from Ethernet driver back to local instance structure
+ // because Ethernet driver may have read it from controller EEPROM
+ EPL_MEMCPY(EplDllkInstance_g.m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr,
+ 6);
+ EPL_MEMCPY(pInitParam_p->m_be_abSrcMac, EdrvInitParam.m_abMyMacAddr, 6);
+
+ // initialize TxBuffer array
+ for (uiIndex = 0; uiIndex < EplDllkInstance_g.m_uiMaxTxFrames;
+ uiIndex++) {
+ EplDllkInstance_g.m_pTxBuffer[uiIndex].m_pbBuffer = NULL;
+ }
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
+ Ret = VEthAddInstance(pInitParam_p);
+#endif
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkDelInstance()
+//
+// Description: deletes an instance of EPL stack
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkDelInstance(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // reset state
+ EplDllkInstance_g.m_DllState = kEplDllGsInit;
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ Ret = EplTimerHighReskDelInstance();
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
+ Ret = VEthDelInstance();
+#endif
+
+ Ret = EdrvShutdown();
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCreateTxFrame
+//
+// Description: creates the buffer for a Tx frame and registers it to the
+// ethernet driver
+//
+// Parameters: puiHandle_p = OUT: handle to frame buffer
+// ppFrame_p = OUT: pointer to pointer of EPL frame
+// puiFrameSize_p = IN/OUT: pointer to size of frame
+// returned size is always equal or larger than
+// requested size, if that is not possible
+// an error will be returned
+// MsgType_p = EPL message type
+// ServiceId_p = Service ID in case of ASnd frame, otherwise
+// kEplDllAsndNotDefined
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p,
+ tEplFrame ** ppFrame_p,
+ unsigned int *puiFrameSize_p,
+ tEplMsgType MsgType_p,
+ tEplDllAsndServiceId ServiceId_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplFrame *pTxFrame;
+ unsigned int uiHandle = EplDllkInstance_g.m_uiMaxTxFrames;
+ tEdrvTxBuffer *pTxBuffer = NULL;
+
+ if (MsgType_p == kEplMsgTypeAsnd) {
+ // search for fixed Tx buffers
+ if (ServiceId_p == kEplDllAsndIdentResponse) {
+ uiHandle = EPL_DLLK_TXFRAME_IDENTRES;
+ } else if (ServiceId_p == kEplDllAsndStatusResponse) {
+ uiHandle = EPL_DLLK_TXFRAME_STATUSRES;
+ } else if ((ServiceId_p == kEplDllAsndNmtRequest)
+ || (ServiceId_p == kEplDllAsndNmtCommand)) {
+ uiHandle = EPL_DLLK_TXFRAME_NMTREQ;
+ }
+
+ if (uiHandle >= EplDllkInstance_g.m_uiMaxTxFrames) { // look for free entry
+ uiHandle = EPL_DLLK_TXFRAME_PREQ;
+ pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
+ for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames;
+ uiHandle++, pTxBuffer++) {
+ if (pTxBuffer->m_pbBuffer == NULL) { // free entry found
+ break;
+ }
+ }
+ }
+ } else if (MsgType_p == kEplMsgTypeNonEpl) {
+ uiHandle = EPL_DLLK_TXFRAME_NONEPL;
+ } else if (MsgType_p == kEplMsgTypePres) {
+ uiHandle = EPL_DLLK_TXFRAME_PRES;
+ } else if (MsgType_p == kEplMsgTypeSoc) {
+ uiHandle = EPL_DLLK_TXFRAME_SOC;
+ } else if (MsgType_p == kEplMsgTypeSoa) {
+ uiHandle = EPL_DLLK_TXFRAME_SOA;
+ } else { // look for free entry
+ uiHandle = EPL_DLLK_TXFRAME_PREQ;
+ pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
+ for (; uiHandle < EplDllkInstance_g.m_uiMaxTxFrames;
+ uiHandle++, pTxBuffer++) {
+ if (pTxBuffer->m_pbBuffer == NULL) { // free entry found
+ break;
+ }
+ }
+ if (pTxBuffer->m_pbBuffer != NULL) {
+ Ret = kEplEdrvNoFreeBufEntry;
+ goto Exit;
+ }
+ }
+
+ // test if requested entry is free
+ pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle];
+ if (pTxBuffer->m_pbBuffer != NULL) { // entry is not free
+ Ret = kEplEdrvNoFreeBufEntry;
+ goto Exit;
+ }
+ // setup Tx buffer
+ pTxBuffer->m_EplMsgType = MsgType_p;
+ pTxBuffer->m_uiMaxBufferLen = *puiFrameSize_p;
+
+ Ret = EdrvAllocTxMsgBuffer(pTxBuffer);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+ // because buffer size may be larger than requested
+ // memorize real length of frame
+ pTxBuffer->m_uiTxMsgLen = *puiFrameSize_p;
+
+ // fill whole frame with 0
+ EPL_MEMSET(pTxBuffer->m_pbBuffer, 0, pTxBuffer->m_uiMaxBufferLen);
+
+ pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
+
+ if (MsgType_p != kEplMsgTypeNonEpl) { // fill out Frame only if it is an EPL frame
+ // ethertype
+ AmiSetWordToBe(&pTxFrame->m_be_wEtherType,
+ EPL_C_DLL_ETHERTYPE_EPL);
+ // source node ID
+ AmiSetByteToLe(&pTxFrame->m_le_bSrcNodeId,
+ (BYTE) EplDllkInstance_g.m_DllConfigParam.
+ m_uiNodeId);
+ // source MAC address
+ EPL_MEMCPY(&pTxFrame->m_be_abSrcMac[0],
+ &EplDllkInstance_g.m_be_abSrcMac[0], 6);
+ switch (MsgType_p) {
+ case kEplMsgTypeAsnd:
+ // destination MAC address
+ AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
+ EPL_C_DLL_MULTICAST_ASND);
+ // destination node ID
+ switch (ServiceId_p) {
+ case kEplDllAsndIdentResponse:
+ case kEplDllAsndStatusResponse:
+ { // IdentResponses and StatusResponses are Broadcast
+ AmiSetByteToLe(&pTxFrame->
+ m_le_bDstNodeId,
+ (BYTE)
+ EPL_C_ADR_BROADCAST);
+ break;
+ }
+
+ default:
+ break;
+ }
+ // ASnd Service ID
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_le_bServiceId,
+ ServiceId_p);
+ break;
+
+ case kEplMsgTypeSoc:
+ // destination MAC address
+ AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
+ EPL_C_DLL_MULTICAST_SOC);
+ // destination node ID
+ AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
+ (BYTE) EPL_C_ADR_BROADCAST);
+ // reset Flags
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag1, (BYTE) 0);
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Soc.m_le_bFlag2, (BYTE) 0);
+ break;
+
+ case kEplMsgTypeSoa:
+ // destination MAC address
+ AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
+ EPL_C_DLL_MULTICAST_SOA);
+ // destination node ID
+ AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
+ (BYTE) EPL_C_ADR_BROADCAST);
+ // reset Flags
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag1, (BYTE) 0);
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bFlag2, (BYTE) 0);
+ // EPL profile version
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bEplVersion,
+ (BYTE) EPL_SPEC_VERSION);
+ break;
+
+ case kEplMsgTypePres:
+ // destination MAC address
+ AmiSetQword48ToBe(&pTxFrame->m_be_abDstMac[0],
+ EPL_C_DLL_MULTICAST_PRES);
+ // destination node ID
+ AmiSetByteToLe(&pTxFrame->m_le_bDstNodeId,
+ (BYTE) EPL_C_ADR_BROADCAST);
+ // reset Flags
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag1, (BYTE) 0);
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bFlag2, (BYTE) 0);
+ // PDO size
+ //AmiSetWordToLe(&pTxFrame->m_Data.m_Pres.m_le_wSize, 0);
+ break;
+
+ case kEplMsgTypePreq:
+ // reset Flags
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, (BYTE) 0);
+ //AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag2, (BYTE) 0);
+ // PDO size
+ //AmiSetWordToLe(&pTxFrame->m_Data.m_Preq.m_le_wSize, 0);
+ break;
+
+ default:
+ break;
+ }
+ // EPL message type
+ AmiSetByteToLe(&pTxFrame->m_le_bMessageType, (BYTE) MsgType_p);
+ }
+
+ *ppFrame_p = pTxFrame;
+ *puiFrameSize_p = pTxBuffer->m_uiMaxBufferLen;
+ *puiHandle_p = uiHandle;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkDeleteTxFrame
+//
+// Description: deletes the buffer for a Tx frame and frees it in the
+// ethernet driver
+//
+// Parameters: uiHandle_p = IN: handle to frame buffer
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkDeleteTxFrame(unsigned int uiHandle_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEdrvTxBuffer *pTxBuffer = NULL;
+
+ if (uiHandle_p >= EplDllkInstance_g.m_uiMaxTxFrames) { // handle is not valid
+ Ret = kEplDllIllegalHdl;
+ goto Exit;
+ }
+
+ pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[uiHandle_p];
+
+ // mark buffer as free so that frame will not be send in future anymore
+ // $$$ d.k. What's up with running transmissions?
+ pTxBuffer->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
+ pTxBuffer->m_pbBuffer = NULL;
+
+ // delete Tx buffer
+ Ret = EdrvReleaseTxMsgBuffer(pTxBuffer);
+ if (Ret != kEplSuccessful) { // error occured while releasing Tx frame
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkProcess
+//
+// Description: process the passed event
+//
+// Parameters: pEvent_p = event to be processed
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkProcess(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplFrame *pTxFrame;
+ tEdrvTxBuffer *pTxBuffer;
+ unsigned int uiHandle;
+ unsigned int uiFrameSize;
+ BYTE abMulticastMac[6];
+ tEplDllAsyncReqPriority AsyncReqPriority;
+ unsigned int uiFrameCount;
+ tEplNmtState NmtState;
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ tEplFrameInfo FrameInfo;
+#endif
+
+ switch (pEvent_p->m_EventType) {
+ case kEplEventTypeDllkCreate:
+ {
+ // $$$ reset ethernet driver
+
+ NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
+
+ // initialize flags for PRes and StatusRes
+ EplDllkInstance_g.m_bFlag1 = EPL_FRAME_FLAG1_EC;
+ EplDllkInstance_g.m_bMnFlag1 = 0;
+ EplDllkInstance_g.m_bFlag2 = 0;
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // initialize linked node list
+ EplDllkInstance_g.m_pFirstNodeInfo = NULL;
+#endif
+
+ // register TxFrames in Edrv
+
+ // IdentResponse
+ uiFrameSize = EPL_C_DLL_MINSIZE_IDENTRES;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
+ &uiFrameSize, kEplMsgTypeAsnd,
+ kEplDllAsndIdentResponse);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+ // EPL profile version
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_bEplProfileVersion,
+ (BYTE) EPL_SPEC_VERSION);
+ // FeatureFlags
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwFeatureFlags,
+ EplDllkInstance_g.m_DllConfigParam.
+ m_dwFeatureFlags);
+ // MTU
+ AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_wMtu,
+ (WORD) EplDllkInstance_g.
+ m_DllConfigParam.m_uiAsyncMtu);
+ // PollInSize
+ AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_wPollInSize,
+ (WORD) EplDllkInstance_g.
+ m_DllConfigParam.
+ m_uiPreqActPayloadLimit);
+ // PollOutSize
+ AmiSetWordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_wPollOutSize,
+ (WORD) EplDllkInstance_g.
+ m_DllConfigParam.
+ m_uiPresActPayloadLimit);
+ // ResponseTime / PresMaxLatency
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwResponseTime,
+ EplDllkInstance_g.m_DllConfigParam.
+ m_dwPresMaxLatency);
+ // DeviceType
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwDeviceType,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwDeviceType);
+ // VendorId
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwVendorId,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwVendorId);
+ // ProductCode
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwProductCode,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwProductCode);
+ // RevisionNumber
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwRevisionNumber,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwRevisionNumber);
+ // SerialNumber
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwSerialNumber,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwSerialNumber);
+ // VendorSpecificExt1
+ AmiSetQword64ToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.
+ m_le_qwVendorSpecificExt1,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_qwVendorSpecificExt1);
+ // VerifyConfigurationDate
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.
+ m_le_dwVerifyConfigurationDate,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwVerifyConfigurationDate);
+ // VerifyConfigurationTime
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.
+ m_le_dwVerifyConfigurationTime,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwVerifyConfigurationTime);
+ // ApplicationSwDate
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.
+ m_le_dwApplicationSwDate,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwApplicationSwDate);
+ // ApplicationSwTime
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.
+ m_le_dwApplicationSwTime,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwApplicationSwTime);
+ // IPAddress
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwIpAddress,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwIpAddress);
+ // SubnetMask
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwSubnetMask,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwSubnetMask);
+ // DefaultGateway
+ AmiSetDwordToLe(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_dwDefaultGateway,
+ EplDllkInstance_g.m_DllIdentParam.
+ m_dwDefaultGateway);
+ // HostName
+ EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_sHostname[0],
+ &EplDllkInstance_g.m_DllIdentParam.
+ m_sHostname[0],
+ sizeof(EplDllkInstance_g.m_DllIdentParam.
+ m_sHostname));
+ // VendorSpecificExt2
+ EPL_MEMCPY(&pTxFrame->m_Data.m_Asnd.m_Payload.
+ m_IdentResponse.m_le_abVendorSpecificExt2[0],
+ &EplDllkInstance_g.m_DllIdentParam.
+ m_abVendorSpecificExt2[0],
+ sizeof(EplDllkInstance_g.m_DllIdentParam.
+ m_abVendorSpecificExt2));
+
+ // StatusResponse
+ uiFrameSize = EPL_C_DLL_MINSIZE_STATUSRES;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
+ &uiFrameSize, kEplMsgTypeAsnd,
+ kEplDllAsndStatusResponse);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+ // PRes $$$ maybe move this to PDO module
+ if ((EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly ==
+ FALSE)
+ && (EplDllkInstance_g.m_DllConfigParam.m_uiPresActPayloadLimit >= 36)) { // it is not configured as async-only CN,
+ // so take part in isochronous phase and register PRes frame
+ uiFrameSize =
+ EplDllkInstance_g.m_DllConfigParam.
+ m_uiPresActPayloadLimit + 24;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
+ &uiFrameSize,
+ kEplMsgTypePres,
+ kEplDllAsndNotDefined);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ // initially encode TPDO -> inform PDO module
+ FrameInfo.m_pFrame = pTxFrame;
+ FrameInfo.m_uiFrameSize = uiFrameSize;
+ Ret = EplPdokCbPdoTransmitted(&FrameInfo);
+#endif
+ // reset cycle counter
+ EplDllkInstance_g.m_uiCycleCount = 0;
+ } else { // it is an async-only CN
+ // fool EplDllkChangeState() to think that PRes was not expected
+ EplDllkInstance_g.m_uiCycleCount = 1;
+ }
+
+ // NMT request
+ uiFrameSize = EPL_C_IP_MAX_MTU;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
+ &uiFrameSize, kEplMsgTypeAsnd,
+ kEplDllAsndNmtRequest);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+ // mark Tx buffer as empty
+ EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
+ EPL_DLLK_BUFLEN_EMPTY;
+
+ // non-EPL frame
+ uiFrameSize = EPL_C_IP_MAX_MTU;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
+ &uiFrameSize,
+ kEplMsgTypeNonEpl,
+ kEplDllAsndNotDefined);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+ // mark Tx buffer as empty
+ EplDllkInstance_g.m_pTxBuffer[uiHandle].m_uiTxMsgLen =
+ EPL_DLLK_BUFLEN_EMPTY;
+
+ // register multicast MACs in ethernet driver
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_SOC);
+ Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_SOA);
+ Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_PRES);
+ Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_ASND);
+ Ret = EdrvDefineRxMacAddrEntry(abMulticastMac);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (NmtState >= kEplNmtMsNotActive) { // local node is MN
+ unsigned int uiIndex;
+
+ // SoC
+ uiFrameSize = EPL_C_DLL_MINSIZE_SOC;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
+ &uiFrameSize,
+ kEplMsgTypeSoc,
+ kEplDllAsndNotDefined);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+ // SoA
+ uiFrameSize = EPL_C_DLL_MINSIZE_SOA;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pTxFrame,
+ &uiFrameSize,
+ kEplMsgTypeSoa,
+ kEplDllAsndNotDefined);
+ if (Ret != kEplSuccessful) { // error occured while registering Tx frame
+ goto Exit;
+ }
+
+ for (uiIndex = 0;
+ uiIndex <
+ tabentries(EplDllkInstance_g.m_aNodeInfo);
+ uiIndex++) {
+// EplDllkInstance_g.m_aNodeInfo[uiIndex].m_uiNodeId = uiIndex + 1;
+ EplDllkInstance_g.m_aNodeInfo[uiIndex].
+ m_wPresPayloadLimit =
+ (WORD) EplDllkInstance_g.
+ m_DllConfigParam.
+ m_uiIsochrRxMaxPayload;
+ }
+
+ // calculate cycle length
+ EplDllkInstance_g.m_ullFrameTimeout = 1000LL
+ *
+ ((unsigned long long)EplDllkInstance_g.
+ m_DllConfigParam.m_dwCycleLen);
+ }
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+ Ret = EplDllkCalAsyncClearBuffer();
+
+ break;
+ }
+
+ case kEplEventTypeDllkDestroy:
+ {
+ // destroy all data structures
+
+ NmtState = *((tEplNmtState *) pEvent_p->m_pArg);
+
+ // delete Tx frames
+ Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_IDENTRES);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+
+ Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_STATUSRES);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+
+ Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_PRES);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+
+ Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NMTREQ);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+
+ Ret = EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_NONEPL);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (NmtState >= kEplNmtMsNotActive) { // local node was MN
+ unsigned int uiIndex;
+
+ Ret =
+ EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOC);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+
+ Ret =
+ EplDllkDeleteTxFrame(EPL_DLLK_TXFRAME_SOA);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+
+ for (uiIndex = 0;
+ uiIndex <
+ tabentries(EplDllkInstance_g.m_aNodeInfo);
+ uiIndex++) {
+ if (EplDllkInstance_g.
+ m_aNodeInfo[uiIndex].
+ m_pPreqTxBuffer != NULL) {
+ uiHandle =
+ EplDllkInstance_g.
+ m_aNodeInfo[uiIndex].
+ m_pPreqTxBuffer -
+ EplDllkInstance_g.
+ m_pTxBuffer;
+ EplDllkInstance_g.
+ m_aNodeInfo[uiIndex].
+ m_pPreqTxBuffer = NULL;
+ Ret =
+ EplDllkDeleteTxFrame
+ (uiHandle);
+ if (Ret != kEplSuccessful) { // error occured while deregistering Tx frame
+ goto Exit;
+ }
+
+ }
+ EplDllkInstance_g.m_aNodeInfo[uiIndex].
+ m_wPresPayloadLimit = 0xFFFF;
+ }
+ }
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+ // deregister multicast MACs in ethernet driver
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_SOC);
+ Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_SOA);
+ Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_PRES);
+ Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
+ AmiSetQword48ToBe(&abMulticastMac[0],
+ EPL_C_DLL_MULTICAST_ASND);
+ Ret = EdrvUndefineRxMacAddrEntry(abMulticastMac);
+
+ // delete timer
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ Ret =
+ EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
+ m_TimerHdlCycle);
+#endif
+
+ break;
+ }
+
+ case kEplEventTypeDllkFillTx:
+ {
+ // fill TxBuffer of specified priority with new frame if empty
+
+ pTxFrame = NULL;
+ AsyncReqPriority =
+ *((tEplDllAsyncReqPriority *) pEvent_p->m_pArg);
+ switch (AsyncReqPriority) {
+ case kEplDllAsyncReqPrioNmt: // NMT request priority
+ {
+ pTxBuffer =
+ &EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ];
+ if (pTxBuffer->m_pbBuffer != NULL) { // NmtRequest does exist
+ // check if frame is empty and not being filled
+ if (pTxBuffer->m_uiTxMsgLen ==
+ EPL_DLLK_BUFLEN_EMPTY) {
+ // mark Tx buffer as filling is in process
+ pTxBuffer->
+ m_uiTxMsgLen =
+ EPL_DLLK_BUFLEN_FILLING;
+ // set max buffer size as input parameter
+ uiFrameSize =
+ pTxBuffer->
+ m_uiMaxBufferLen;
+ // copy frame from shared loop buffer to Tx buffer
+ Ret =
+ EplDllkCalAsyncGetTxFrame
+ (pTxBuffer->
+ m_pbBuffer,
+ &uiFrameSize,
+ AsyncReqPriority);
+ if (Ret ==
+ kEplSuccessful) {
+ pTxFrame =
+ (tEplFrame
+ *)
+ pTxBuffer->
+ m_pbBuffer;
+ Ret =
+ EplDllkCheckFrame
+ (pTxFrame,
+ uiFrameSize);
+
+ // set buffer valid
+ pTxBuffer->
+ m_uiTxMsgLen
+ =
+ uiFrameSize;
+ } else if (Ret == kEplDllAsyncTxBufferEmpty) { // empty Tx buffer is not a real problem
+ // so just ignore it
+ Ret =
+ kEplSuccessful;
+ // mark Tx buffer as empty
+ pTxBuffer->
+ m_uiTxMsgLen
+ =
+ EPL_DLLK_BUFLEN_EMPTY;
+ }
+ }
+ }
+ break;
+ }
+
+ default: // generic priority
+ {
+ pTxBuffer =
+ &EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NONEPL];
+ if (pTxBuffer->m_pbBuffer != NULL) { // non-EPL frame does exist
+ // check if frame is empty and not being filled
+ if (pTxBuffer->m_uiTxMsgLen ==
+ EPL_DLLK_BUFLEN_EMPTY) {
+ // mark Tx buffer as filling is in process
+ pTxBuffer->
+ m_uiTxMsgLen =
+ EPL_DLLK_BUFLEN_FILLING;
+ // set max buffer size as input parameter
+ uiFrameSize =
+ pTxBuffer->
+ m_uiMaxBufferLen;
+ // copy frame from shared loop buffer to Tx buffer
+ Ret =
+ EplDllkCalAsyncGetTxFrame
+ (pTxBuffer->
+ m_pbBuffer,
+ &uiFrameSize,
+ AsyncReqPriority);
+ if (Ret ==
+ kEplSuccessful) {
+ pTxFrame =
+ (tEplFrame
+ *)
+ pTxBuffer->
+ m_pbBuffer;
+ Ret =
+ EplDllkCheckFrame
+ (pTxFrame,
+ uiFrameSize);
+
+ // set buffer valid
+ pTxBuffer->
+ m_uiTxMsgLen
+ =
+ uiFrameSize;
+ } else if (Ret == kEplDllAsyncTxBufferEmpty) { // empty Tx buffer is not a real problem
+ // so just ignore it
+ Ret =
+ kEplSuccessful;
+ // mark Tx buffer as empty
+ pTxBuffer->
+ m_uiTxMsgLen
+ =
+ EPL_DLLK_BUFLEN_EMPTY;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ NmtState = EplNmtkGetNmtState();
+
+ if ((NmtState == kEplNmtCsBasicEthernet) || (NmtState == kEplNmtMsBasicEthernet)) { // send frame immediately
+ if (pTxFrame != NULL) { // frame is present
+ // padding is done by Edrv or ethernet controller
+ Ret = EdrvSendTxMsg(pTxBuffer);
+ } else { // no frame moved to TxBuffer
+ // check if TxBuffers contain unsent frames
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // NMT request Tx buffer contains a frame
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ]);
+ } else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // non-EPL Tx buffer contains a frame
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NONEPL]);
+ }
+ if (Ret == kEplInvalidOperation) { // ignore error if caused by already active transmission
+ Ret = kEplSuccessful;
+ }
+ }
+ // reset PRes flag 2
+ EplDllkInstance_g.m_bFlag2 = 0;
+ } else {
+ // update Flag 2 (PR, RS)
+ Ret =
+ EplDllkCalAsyncGetTxCount(&AsyncReqPriority,
+ &uiFrameCount);
+ if (AsyncReqPriority == kEplDllAsyncReqPrioNmt) { // non-empty FIFO with hightest priority is for NMT requests
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // NMT request Tx buffer contains a frame
+ // add one more frame
+ uiFrameCount++;
+ }
+ } else { // non-empty FIFO with highest priority is for generic frames
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // NMT request Tx buffer contains a frame
+ // use NMT request FIFO, because of higher priority
+ uiFrameCount = 1;
+ AsyncReqPriority =
+ kEplDllAsyncReqPrioNmt;
+ } else if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_uiTxMsgLen > EPL_DLLK_BUFLEN_EMPTY) { // non-EPL Tx buffer contains a frame
+ // use NMT request FIFO, because of higher priority
+ // add one more frame
+ uiFrameCount++;
+ }
+ }
+
+ if (uiFrameCount > 7) { // limit frame request to send counter to 7
+ uiFrameCount = 7;
+ }
+ if (uiFrameCount > 0) {
+ EplDllkInstance_g.m_bFlag2 =
+ (BYTE) (((AsyncReqPriority <<
+ EPL_FRAME_FLAG2_PR_SHIFT)
+ & EPL_FRAME_FLAG2_PR)
+ | (uiFrameCount &
+ EPL_FRAME_FLAG2_RS));
+ } else {
+ EplDllkInstance_g.m_bFlag2 = 0;
+ }
+ }
+
+ break;
+ }
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ case kEplEventTypeDllkStartReducedCycle:
+ {
+ // start the reduced cycle by programming the cycle timer
+ // it is issued by NMT MN module, when PreOp1 is entered
+
+ // clear the asynchronous queues
+ Ret = EplDllkCalAsyncClearQueues();
+
+ // reset cycle counter (everytime a SoA is triggerd in PreOp1 the counter is incremented
+ // and when it reaches EPL_C_DLL_PREOP1_START_CYCLES the SoA may contain invitations)
+ EplDllkInstance_g.m_uiCycleCount = 0;
+
+ // remove any CN from isochronous phase
+ while (EplDllkInstance_g.m_pFirstNodeInfo != NULL) {
+ EplDllkDeleteNode(EplDllkInstance_g.
+ m_pFirstNodeInfo->m_uiNodeId);
+ }
+
+ // change state to NonCyclic,
+ // hence EplDllkChangeState() will not ignore the next call
+ EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ if (EplDllkInstance_g.m_DllConfigParam.
+ m_dwAsyncSlotTimeout != 0) {
+ Ret =
+ EplTimerHighReskModifyTimerNs
+ (&EplDllkInstance_g.m_TimerHdlCycle,
+ EplDllkInstance_g.m_DllConfigParam.
+ m_dwAsyncSlotTimeout,
+ EplDllkCbMnTimerCycle, 0L, FALSE);
+ }
+#endif
+
+ break;
+ }
+#endif
+
+#if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
+ case kEplEventTypeDllkPresReady:
+ {
+ // post PRes to transmit FIFO
+
+ NmtState = EplNmtkGetNmtState();
+
+ if (NmtState != kEplNmtCsBasicEthernet) {
+ // Does PRes exist?
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].m_pbBuffer != NULL) { // PRes does exist
+ pTxFrame =
+ (tEplFrame *) EplDllkInstance_g.
+ m_pTxBuffer[EPL_DLLK_TXFRAME_PRES].
+ m_pbBuffer;
+ // update frame (NMT state, RD, RS, PR, MS, EN flags)
+ if (NmtState < kEplNmtCsPreOperational2) { // NMT state is not PreOp2, ReadyToOp or Op
+ // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
+ NmtState =
+ kEplNmtCsPreOperational2;
+ }
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bFlag2,
+ EplDllkInstance_g.
+ m_bFlag2);
+ if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
+ // $$$ reset only RD flag; set other flags appropriately
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Pres.
+ m_le_bFlag1, 0);
+ }
+ // $$$ make function that updates Pres, StatusRes
+ // mark PRes frame as ready for transmission
+ Ret =
+ EdrvTxMsgReady(&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_PRES]);
+ }
+ }
+
+ break;
+ }
+#endif
+ default:
+ {
+ ASSERTMSG(FALSE,
+ "EplDllkProcess(): unhandled event type!\n");
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkConfig
+//
+// Description: configure parameters of DLL
+//
+// Parameters: pDllConfigParam_p = configuration parameters
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+// d.k. check of NMT state disabled, because CycleLen is programmed at run time by MN without reset of CN
+/*tEplNmtState NmtState;
+
+ NmtState = EplNmtkGetNmtState();
+
+ if (NmtState > kEplNmtGsResetConfiguration)
+ { // only allowed in state DLL_GS_INIT
+ Ret = kEplInvalidOperation;
+ goto Exit;
+ }
+*/
+ EPL_MEMCPY(&EplDllkInstance_g.m_DllConfigParam, pDllConfigParam_p,
+ (pDllConfigParam_p->m_uiSizeOfStruct <
+ sizeof(tEplDllConfigParam) ? pDllConfigParam_p->
+ m_uiSizeOfStruct : sizeof(tEplDllConfigParam)));
+
+ if ((EplDllkInstance_g.m_DllConfigParam.m_dwCycleLen != 0)
+ && (EplDllkInstance_g.m_DllConfigParam.m_dwLossOfFrameTolerance != 0)) { // monitor EPL cycle, calculate frame timeout
+ EplDllkInstance_g.m_ullFrameTimeout = (1000LL
+ *
+ ((unsigned long long)
+ EplDllkInstance_g.
+ m_DllConfigParam.
+ m_dwCycleLen))
+ +
+ ((unsigned long long)EplDllkInstance_g.m_DllConfigParam.
+ m_dwLossOfFrameTolerance);
+ } else {
+ EplDllkInstance_g.m_ullFrameTimeout = 0LL;
+ }
+
+ if (EplDllkInstance_g.m_DllConfigParam.m_fAsyncOnly != FALSE) { // it is configured as async-only CN
+ // disable multiplexed cycle, that m_uiCycleCount will not be incremented spuriously on SoC
+ EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt = 0;
+ }
+//Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkSetIdentity
+//
+// Description: configure identity of local node for IdentResponse
+//
+// Parameters: pDllIdentParam_p = identity
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ EPL_MEMCPY(&EplDllkInstance_g.m_DllIdentParam, pDllIdentParam_p,
+ (pDllIdentParam_p->m_uiSizeOfStruct <
+ sizeof(tEplDllIdentParam) ? pDllIdentParam_p->
+ m_uiSizeOfStruct : sizeof(tEplDllIdentParam)));
+
+ // $$$ if IdentResponse frame exists update it
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkRegAsyncHandler
+//
+// Description: registers handler for non-EPL frames
+//
+// Parameters: pfnDllkCbAsync_p = pointer to callback function
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (EplDllkInstance_g.m_pfnCbAsync == NULL) { // no handler registered yet
+ EplDllkInstance_g.m_pfnCbAsync = pfnDllkCbAsync_p;
+ } else { // handler already registered
+ Ret = kEplDllCbAsyncRegistered;
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkDeregAsyncHandler
+//
+// Description: deregisters handler for non-EPL frames
+//
+// Parameters: pfnDllkCbAsync_p = pointer to callback function
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (EplDllkInstance_g.m_pfnCbAsync == pfnDllkCbAsync_p) { // same handler is registered
+ // deregister it
+ EplDllkInstance_g.m_pfnCbAsync = NULL;
+ } else { // wrong handler or no handler registered
+ Ret = kEplDllCbAsyncRegistered;
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkSetAsndServiceIdFilter()
+//
+// Description: sets the specified node ID filter for the specified
+// AsndServiceId. It registers C_DLL_MULTICAST_ASND in ethernet
+// driver if any AsndServiceId is open.
+//
+// Parameters: ServiceId_p = ASnd Service ID
+// Filter_p = node ID filter
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p,
+ tEplDllAsndFilter Filter_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (ServiceId_p < tabentries(EplDllkInstance_g.m_aAsndFilter)) {
+ EplDllkInstance_g.m_aAsndFilter[ServiceId_p] = Filter_p;
+ }
+
+ return Ret;
+}
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkSetFlag1OfNode()
+//
+// Description: sets Flag1 (for PReq and SoA) of the specified node ID.
+//
+// Parameters: uiNodeId_p = node ID
+// bSoaFlag1_p = flag1
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplDllkNodeInfo *pNodeInfo;
+
+ pNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
+ if (pNodeInfo == NULL) { // no node info structure available
+ Ret = kEplDllNoNodeInfo;
+ goto Exit;
+ }
+ // store flag1 in internal node info structure
+ pNodeInfo->m_bSoaFlag1 = bSoaFlag1_p;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkGetFirstNodeInfo()
+//
+// Description: returns first info structure of first node in isochronous phase.
+// It is only useful for ErrorHandlerk module.
+//
+// Parameters: ppNodeInfo_p = pointer to pointer of internal node info structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ *ppNodeInfo_p = EplDllkInstance_g.m_pFirstNodeInfo;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkAddNode()
+//
+// Description: adds the specified node to the isochronous phase.
+//
+// Parameters: pNodeInfo_p = pointer of node info structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplDllkNodeInfo *pIntNodeInfo;
+ tEplDllkNodeInfo **ppIntNodeInfo;
+ unsigned int uiHandle;
+ tEplFrame *pFrame;
+ unsigned int uiFrameSize;
+
+ pIntNodeInfo = EplDllkGetNodeInfo(pNodeInfo_p->m_uiNodeId);
+ if (pIntNodeInfo == NULL) { // no node info structure available
+ Ret = kEplDllNoNodeInfo;
+ goto Exit;
+ }
+
+ EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkAddNode,
+ pNodeInfo_p->m_uiNodeId, 0);
+
+ // copy node configuration
+ pIntNodeInfo->m_dwPresTimeout = pNodeInfo_p->m_dwPresTimeout;
+ pIntNodeInfo->m_wPresPayloadLimit = pNodeInfo_p->m_wPresPayloadLimit;
+
+ // $$$ d.k.: actually add node only if MN. On CN it is sufficient to update the node configuration
+ if (pNodeInfo_p->m_uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) { // we shall send PRes ourself
+ // insert our node at the end of the list
+ ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
+ while ((*ppIntNodeInfo != NULL)
+ && ((*ppIntNodeInfo)->m_pNextNodeInfo != NULL)) {
+ ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
+ }
+ if (*ppIntNodeInfo != NULL) {
+ if ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId) { // node was already added to list
+ // $$$ d.k. maybe this should be an error
+ goto Exit;
+ } else { // add our node at the end of the list
+ ppIntNodeInfo =
+ &(*ppIntNodeInfo)->m_pNextNodeInfo;
+ }
+ }
+ // set "PReq"-TxBuffer to PRes-TxBuffer
+ pIntNodeInfo->m_pPreqTxBuffer =
+ &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
+ } else { // normal CN shall be added to isochronous phase
+ // insert node into list in ascending order
+ ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
+ while ((*ppIntNodeInfo != NULL)
+ && ((*ppIntNodeInfo)->m_uiNodeId <
+ pNodeInfo_p->m_uiNodeId)
+ && ((*ppIntNodeInfo)->m_uiNodeId !=
+ EplDllkInstance_g.m_DllConfigParam.m_uiNodeId)) {
+ ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
+ }
+ if ((*ppIntNodeInfo != NULL) && ((*ppIntNodeInfo)->m_uiNodeId == pNodeInfo_p->m_uiNodeId)) { // node was already added to list
+ // $$$ d.k. maybe this should be an error
+ goto Exit;
+ }
+ }
+
+ // initialize elements of internal node info structure
+ pIntNodeInfo->m_bSoaFlag1 = 0;
+ pIntNodeInfo->m_fSoftDelete = FALSE;
+ pIntNodeInfo->m_NmtState = kEplNmtCsNotActive;
+ if (pIntNodeInfo->m_pPreqTxBuffer == NULL) { // create TxBuffer entry
+ uiFrameSize = pNodeInfo_p->m_wPreqPayloadLimit + 24;
+ Ret =
+ EplDllkCreateTxFrame(&uiHandle, &pFrame, &uiFrameSize,
+ kEplMsgTypePreq,
+ kEplDllAsndNotDefined);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ pIntNodeInfo->m_pPreqTxBuffer =
+ &EplDllkInstance_g.m_pTxBuffer[uiHandle];
+ AmiSetByteToLe(&pFrame->m_le_bDstNodeId,
+ (BYTE) pNodeInfo_p->m_uiNodeId);
+
+ // set up destination MAC address
+ EPL_MEMCPY(pFrame->m_be_abDstMac, pIntNodeInfo->m_be_abMacAddr,
+ 6);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ {
+ tEplFrameInfo FrameInfo;
+
+ // initially encode TPDO -> inform PDO module
+ FrameInfo.m_pFrame = pFrame;
+ FrameInfo.m_uiFrameSize = uiFrameSize;
+ Ret = EplPdokCbPdoTransmitted(&FrameInfo);
+ }
+#endif
+ }
+ pIntNodeInfo->m_ulDllErrorEvents = 0L;
+ // add node to list
+ pIntNodeInfo->m_pNextNodeInfo = *ppIntNodeInfo;
+ *ppIntNodeInfo = pIntNodeInfo;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkDeleteNode()
+//
+// Description: removes the specified node from the isochronous phase.
+//
+// Parameters: uiNodeId_p = node ID
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplDllkNodeInfo *pIntNodeInfo;
+ tEplDllkNodeInfo **ppIntNodeInfo;
+ unsigned int uiHandle;
+
+ pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
+ if (pIntNodeInfo == NULL) { // no node info structure available
+ Ret = kEplDllNoNodeInfo;
+ goto Exit;
+ }
+
+ EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkDelNode, uiNodeId_p, 0);
+
+ // search node in whole list
+ ppIntNodeInfo = &EplDllkInstance_g.m_pFirstNodeInfo;
+ while ((*ppIntNodeInfo != NULL)
+ && ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) {
+ ppIntNodeInfo = &(*ppIntNodeInfo)->m_pNextNodeInfo;
+ }
+ if ((*ppIntNodeInfo == NULL) || ((*ppIntNodeInfo)->m_uiNodeId != uiNodeId_p)) { // node was not found in list
+ // $$$ d.k. maybe this should be an error
+ goto Exit;
+ }
+ // remove node from list
+ *ppIntNodeInfo = pIntNodeInfo->m_pNextNodeInfo;
+
+ if ((pIntNodeInfo->m_pPreqTxBuffer != NULL)
+ && (pIntNodeInfo->m_pPreqTxBuffer != &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) { // delete TxBuffer entry
+ uiHandle =
+ pIntNodeInfo->m_pPreqTxBuffer -
+ EplDllkInstance_g.m_pTxBuffer;
+ pIntNodeInfo->m_pPreqTxBuffer = NULL;
+ Ret = EplDllkDeleteTxFrame(uiHandle);
+/* if (Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }*/
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkSoftDeleteNode()
+//
+// Description: removes the specified node not immediately from the isochronous phase.
+// Instead the will be removed after error (late/loss PRes) without
+// charging the error.
+//
+// Parameters: uiNodeId_p = node ID
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplDllkNodeInfo *pIntNodeInfo;
+
+ pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId_p);
+ if (pIntNodeInfo == NULL) { // no node info structure available
+ Ret = kEplDllNoNodeInfo;
+ goto Exit;
+ }
+
+ EPL_DLLK_DBG_POST_TRACE_VALUE(kEplEventTypeDllkSoftDelNode,
+ uiNodeId_p, 0);
+
+ pIntNodeInfo->m_fSoftDelete = TRUE;
+
+ Exit:
+ return Ret;
+}
+
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkChangeState
+//
+// Description: change DLL state on event and diagnose some communication errors
+//
+// Parameters: NmtEvent_p = DLL event (wrapped in NMT event)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDllkChangeState(tEplNmtEvent NmtEvent_p,
+ tEplNmtState NmtState_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+ tEplErrorHandlerkEvent DllEvent;
+
+ DllEvent.m_ulDllErrorEvents = 0;
+ DllEvent.m_uiNodeId = 0;
+ DllEvent.m_NmtState = NmtState_p;
+
+ switch (NmtState_p) {
+ case kEplNmtGsOff:
+ case kEplNmtGsInitialising:
+ case kEplNmtGsResetApplication:
+ case kEplNmtGsResetCommunication:
+ case kEplNmtGsResetConfiguration:
+ case kEplNmtCsBasicEthernet:
+ // enter DLL_GS_INIT
+ EplDllkInstance_g.m_DllState = kEplDllGsInit;
+ break;
+
+ case kEplNmtCsNotActive:
+ case kEplNmtCsPreOperational1:
+ // reduced EPL cycle is active
+ if (NmtEvent_p == kEplNmtEventDllCeSoc) { // SoC received
+ // enter DLL_CS_WAIT_PREQ
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
+ } else {
+ // enter DLL_GS_INIT
+ EplDllkInstance_g.m_DllState = kEplDllGsInit;
+ }
+ break;
+
+ case kEplNmtCsPreOperational2:
+ case kEplNmtCsReadyToOperate:
+ case kEplNmtCsOperational:
+ // full EPL cycle is active
+
+ switch (EplDllkInstance_g.m_DllState) {
+ case kEplDllCsWaitPreq:
+ switch (NmtEvent_p) {
+ // DLL_CT2
+ case kEplNmtEventDllCePreq:
+ // enter DLL_CS_WAIT_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_RECVD_PREQ;
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
+ break;
+
+ // DLL_CT8
+ case kEplNmtEventDllCeFrameTimeout:
+ if (NmtState_p == kEplNmtCsPreOperational2) { // ignore frame timeout in PreOp2,
+ // because the previously configured cycle len
+ // may be wrong.
+ // 2008/10/15 d.k. If it would not be ignored,
+ // we would go cyclically to PreOp1 and on next
+ // SoC back to PreOp2.
+ break;
+ }
+ // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA |
+ EPL_DLL_ERR_CN_LOSS_SOC;
+
+ // enter DLL_CS_WAIT_SOC
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
+ break;
+
+ case kEplNmtEventDllCeSoa:
+ // check if multiplexed and PReq should have been received in this cycle
+ // and if >= NMT_CS_READY_TO_OPERATE
+ if ((EplDllkInstance_g.m_uiCycleCount == 0)
+ && (NmtState_p >= kEplNmtCsReadyToOperate)) { // report DLL_CEV_LOSS_OF_PREQ
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_PREQ;
+ }
+ // enter DLL_CS_WAIT_SOC
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
+ break;
+
+ // DLL_CT7
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeAsnd:
+ // report DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA;
+
+ case kEplNmtEventDllCePres:
+ default:
+ // remain in this state
+ break;
+ }
+ break;
+
+ case kEplDllCsWaitSoc:
+ switch (NmtEvent_p) {
+ // DLL_CT1
+ case kEplNmtEventDllCeSoc:
+ // start of cycle and isochronous phase
+ // enter DLL_CS_WAIT_PREQ
+ EplDllkInstance_g.m_DllState =
+ kEplDllCsWaitPreq;
+ break;
+
+ // DLL_CT4
+// case kEplNmtEventDllCePres:
+ case kEplNmtEventDllCeFrameTimeout:
+ if (NmtState_p == kEplNmtCsPreOperational2) { // ignore frame timeout in PreOp2,
+ // because the previously configured cycle len
+ // may be wrong.
+ // 2008/10/15 d.k. If it would not be ignored,
+ // we would go cyclically to PreOp1 and on next
+ // SoC back to PreOp2.
+ break;
+ }
+ // fall through
+
+ case kEplNmtEventDllCePreq:
+ case kEplNmtEventDllCeSoa:
+ // report DLL_CEV_LOSS_SOC
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOC;
+
+ case kEplNmtEventDllCeAsnd:
+ default:
+ // remain in this state
+ break;
+ }
+ break;
+
+ case kEplDllCsWaitSoa:
+ switch (NmtEvent_p) {
+ case kEplNmtEventDllCeFrameTimeout:
+ // DLL_CT3
+ if (NmtState_p == kEplNmtCsPreOperational2) { // ignore frame timeout in PreOp2,
+ // because the previously configured cycle len
+ // may be wrong.
+ // 2008/10/15 d.k. If it would not be ignored,
+ // we would go cyclically to PreOp1 and on next
+ // SoC back to PreOp2.
+ break;
+ }
+ // fall through
+
+ case kEplNmtEventDllCePreq:
+ // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA |
+ EPL_DLL_ERR_CN_LOSS_SOC;
+
+ case kEplNmtEventDllCeSoa:
+ // enter DLL_CS_WAIT_SOC
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
+ break;
+
+ // DLL_CT9
+ case kEplNmtEventDllCeSoc:
+ // report DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA;
+
+ // enter DLL_CS_WAIT_PREQ
+ EplDllkInstance_g.m_DllState =
+ kEplDllCsWaitPreq;
+ break;
+
+ // DLL_CT10
+ case kEplNmtEventDllCeAsnd:
+ // report DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA;
+
+ case kEplNmtEventDllCePres:
+ default:
+ // remain in this state
+ break;
+ }
+ break;
+
+ case kEplDllGsInit:
+ // enter DLL_CS_WAIT_PREQ
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitPreq;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case kEplNmtCsStopped:
+ // full EPL cycle is active, but without PReq/PRes
+
+ switch (EplDllkInstance_g.m_DllState) {
+ case kEplDllCsWaitPreq:
+ switch (NmtEvent_p) {
+ // DLL_CT2
+ case kEplNmtEventDllCePreq:
+ // enter DLL_CS_WAIT_SOA
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
+ break;
+
+ // DLL_CT8
+ case kEplNmtEventDllCeFrameTimeout:
+ // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA |
+ EPL_DLL_ERR_CN_LOSS_SOC;
+
+ case kEplNmtEventDllCeSoa:
+ // NMT_CS_STOPPED active
+ // it is Ok if no PReq was received
+
+ // enter DLL_CS_WAIT_SOC
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
+ break;
+
+ // DLL_CT7
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeAsnd:
+ // report DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA;
+
+ case kEplNmtEventDllCePres:
+ default:
+ // remain in this state
+ break;
+ }
+ break;
+
+ case kEplDllCsWaitSoc:
+ switch (NmtEvent_p) {
+ // DLL_CT1
+ case kEplNmtEventDllCeSoc:
+ // start of cycle and isochronous phase
+ // enter DLL_CS_WAIT_SOA
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
+ break;
+
+ // DLL_CT4
+// case kEplNmtEventDllCePres:
+ case kEplNmtEventDllCePreq:
+ case kEplNmtEventDllCeSoa:
+ case kEplNmtEventDllCeFrameTimeout:
+ // report DLL_CEV_LOSS_SOC
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOC;
+
+ case kEplNmtEventDllCeAsnd:
+ default:
+ // remain in this state
+ break;
+ }
+ break;
+
+ case kEplDllCsWaitSoa:
+ switch (NmtEvent_p) {
+ // DLL_CT3
+ case kEplNmtEventDllCeFrameTimeout:
+ // report DLL_CEV_LOSS_SOC and DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA |
+ EPL_DLL_ERR_CN_LOSS_SOC;
+
+ case kEplNmtEventDllCeSoa:
+ // enter DLL_CS_WAIT_SOC
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoc;
+ break;
+
+ // DLL_CT9
+ case kEplNmtEventDllCeSoc:
+ // report DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA;
+ // remain in DLL_CS_WAIT_SOA
+ break;
+
+ // DLL_CT10
+ case kEplNmtEventDllCeAsnd:
+ // report DLL_CEV_LOSS_SOA
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOA;
+
+ case kEplNmtEventDllCePreq:
+ // NMT_CS_STOPPED active and we do not expect any PReq
+ // so just ignore it
+ case kEplNmtEventDllCePres:
+ default:
+ // remain in this state
+ break;
+ }
+ break;
+
+ case kEplDllGsInit:
+ default:
+ // enter DLL_CS_WAIT_PREQ
+ EplDllkInstance_g.m_DllState = kEplDllCsWaitSoa;
+ break;
+ }
+ break;
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ case kEplNmtMsNotActive:
+ case kEplNmtMsBasicEthernet:
+ break;
+
+ case kEplNmtMsPreOperational1:
+ // reduced EPL cycle is active
+ if (EplDllkInstance_g.m_DllState != kEplDllMsNonCyclic) { // stop cycle timer
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ Ret =
+ EplTimerHighReskDeleteTimer(&EplDllkInstance_g.
+ m_TimerHdlCycle);
+#endif
+ EplDllkInstance_g.m_DllState = kEplDllMsNonCyclic;
+
+ // stop further processing,
+ // because it will be restarted by NMT MN module
+ break;
+ }
+
+ switch (NmtEvent_p) {
+ case kEplNmtEventDllMeSocTrig:
+ case kEplNmtEventDllCeAsnd:
+ { // because of reduced EPL cycle SoA shall be triggered, not SoC
+ tEplDllState DummyDllState;
+
+ Ret =
+ EplDllkAsyncFrameNotReceived
+ (EplDllkInstance_g.m_LastReqServiceId,
+ EplDllkInstance_g.m_uiLastTargetNodeId);
+
+ // go ahead and send SoA
+ Ret = EplDllkMnSendSoa(NmtState_p,
+ &DummyDllState,
+ (EplDllkInstance_g.
+ m_uiCycleCount >=
+ EPL_C_DLL_PREOP1_START_CYCLES));
+ // increment cycle counter to detect if EPL_C_DLL_PREOP1_START_CYCLES empty cycles are elapsed
+ EplDllkInstance_g.m_uiCycleCount++;
+
+ // reprogram timer
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ if (EplDllkInstance_g.m_DllConfigParam.
+ m_dwAsyncSlotTimeout != 0) {
+ Ret =
+ EplTimerHighReskModifyTimerNs
+ (&EplDllkInstance_g.m_TimerHdlCycle,
+ EplDllkInstance_g.m_DllConfigParam.
+ m_dwAsyncSlotTimeout,
+ EplDllkCbMnTimerCycle, 0L, FALSE);
+ }
+#endif
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+
+ case kEplNmtMsPreOperational2:
+ case kEplNmtMsReadyToOperate:
+ case kEplNmtMsOperational:
+ // full EPL cycle is active
+ switch (NmtEvent_p) {
+ case kEplNmtEventDllMeSocTrig:
+ {
+ // update cycle counter
+ if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) { // multiplexed cycle active
+ EplDllkInstance_g.m_uiCycleCount =
+ (EplDllkInstance_g.m_uiCycleCount +
+ 1) %
+ EplDllkInstance_g.m_DllConfigParam.
+ m_uiMultiplCycleCnt;
+ // $$$ check multiplexed cycle restart
+ // -> toggle MC flag
+ // -> change node linked list
+ } else { // non-multiplexed cycle active
+ // start with first node in isochronous phase
+ EplDllkInstance_g.m_pCurNodeInfo = NULL;
+ }
+
+ switch (EplDllkInstance_g.m_DllState) {
+ case kEplDllMsNonCyclic:
+ { // start continuous cycle timer
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ Ret =
+ EplTimerHighReskModifyTimerNs
+ (&EplDllkInstance_g.
+ m_TimerHdlCycle,
+ EplDllkInstance_g.
+ m_ullFrameTimeout,
+ EplDllkCbMnTimerCycle, 0L,
+ TRUE);
+#endif
+ // continue with sending SoC
+ }
+
+ case kEplDllMsWaitAsnd:
+ case kEplDllMsWaitSocTrig:
+ { // if m_LastReqServiceId is still valid,
+ // SoA was not correctly answered
+ // and user part has to be informed
+ Ret =
+ EplDllkAsyncFrameNotReceived
+ (EplDllkInstance_g.
+ m_LastReqServiceId,
+ EplDllkInstance_g.
+ m_uiLastTargetNodeId);
+
+ // send SoC
+ Ret = EplDllkMnSendSoc();
+
+ // new DLL state
+ EplDllkInstance_g.m_DllState =
+ kEplDllMsWaitPreqTrig;
+
+ // start WaitSoCPReq Timer
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ Ret =
+ EplTimerHighReskModifyTimerNs
+ (&EplDllkInstance_g.
+ m_TimerHdlResponse,
+ EplDllkInstance_g.
+ m_DllConfigParam.
+ m_dwWaitSocPreq,
+ EplDllkCbMnTimerResponse,
+ 0L, FALSE);
+#endif
+ break;
+ }
+
+ default:
+ { // wrong DLL state / cycle time exceeded
+ DllEvent.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_MN_CYCTIMEEXCEED;
+ EplDllkInstance_g.m_DllState =
+ kEplDllMsWaitSocTrig;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case kEplNmtEventDllMePresTimeout:
+ {
+
+ switch (EplDllkInstance_g.m_DllState) {
+ case kEplDllMsWaitPres:
+ { // PRes not received
+
+ if (EplDllkInstance_g.m_pCurNodeInfo->m_fSoftDelete == FALSE) { // normal isochronous CN
+ DllEvent.
+ m_ulDllErrorEvents
+ |=
+ EPL_DLL_ERR_MN_CN_LOSS_PRES;
+ DllEvent.m_uiNodeId =
+ EplDllkInstance_g.
+ m_pCurNodeInfo->
+ m_uiNodeId;
+ } else { // CN shall be deleted softly
+ Event.m_EventSink =
+ kEplEventSinkDllkCal;
+ Event.m_EventType =
+ kEplEventTypeDllkSoftDelNode;
+ // $$$ d.k. set Event.m_NetTime to current time
+ Event.m_uiSize =
+ sizeof(unsigned
+ int);
+ Event.m_pArg =
+ &EplDllkInstance_g.
+ m_pCurNodeInfo->
+ m_uiNodeId;
+ Ret =
+ EplEventkPost
+ (&Event);
+ }
+
+ // continue with sending next PReq
+ }
+
+ case kEplDllMsWaitPreqTrig:
+ {
+ // send next PReq
+ Ret =
+ EplDllkMnSendPreq
+ (NmtState_p,
+ &EplDllkInstance_g.
+ m_DllState);
+
+ break;
+ }
+
+ default:
+ { // wrong DLL state
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case kEplNmtEventDllCePres:
+ {
+
+ switch (EplDllkInstance_g.m_DllState) {
+ case kEplDllMsWaitPres:
+ { // PRes received
+ // send next PReq
+ Ret =
+ EplDllkMnSendPreq
+ (NmtState_p,
+ &EplDllkInstance_g.
+ m_DllState);
+
+ break;
+ }
+
+ default:
+ { // wrong DLL state
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case kEplNmtEventDllMeSoaTrig:
+ {
+
+ switch (EplDllkInstance_g.m_DllState) {
+ case kEplDllMsWaitSoaTrig:
+ { // MN PRes sent
+ // send SoA
+ Ret =
+ EplDllkMnSendSoa(NmtState_p,
+ &EplDllkInstance_g.
+ m_DllState,
+ TRUE);
+
+ break;
+ }
+
+ default:
+ { // wrong DLL state
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case kEplNmtEventDllCeAsnd:
+ { // ASnd has been received, but it may be not the requested one
+/*
+ // report if SoA was correctly answered
+ Ret = EplDllkAsyncFrameNotReceived(EplDllkInstance_g.m_LastReqServiceId,
+ EplDllkInstance_g.m_uiLastTargetNodeId);
+*/
+ if (EplDllkInstance_g.m_DllState ==
+ kEplDllMsWaitAsnd) {
+ EplDllkInstance_g.m_DllState =
+ kEplDllMsWaitSocTrig;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+ default:
+ break;
+ }
+
+ if (DllEvent.m_ulDllErrorEvents != 0) { // error event set -> post it to error handler
+ Event.m_EventSink = kEplEventSinkErrk;
+ Event.m_EventType = kEplEventTypeDllError;
+ // $$$ d.k. set Event.m_NetTime to current time
+ Event.m_uiSize = sizeof(DllEvent);
+ Event.m_pArg = &DllEvent;
+ Ret = EplEventkPost(&Event);
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCbFrameReceived()
+//
+// Description: called from EdrvInterruptHandler()
+//
+// Parameters: pRxBuffer_p = receive buffer structure
+//
+// Returns: (none)
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static void EplDllkCbFrameReceived(tEdrvRxBuffer * pRxBuffer_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplNmtState NmtState;
+ tEplNmtEvent NmtEvent = kEplNmtEventNoEvent;
+ tEplEvent Event;
+ tEplFrame *pFrame;
+ tEplFrame *pTxFrame;
+ tEdrvTxBuffer *pTxBuffer = NULL;
+ tEplFrameInfo FrameInfo;
+ tEplMsgType MsgType;
+ tEplDllReqServiceId ReqServiceId;
+ unsigned int uiAsndServiceId;
+ unsigned int uiNodeId;
+ BYTE bFlag1;
+
+ BENCHMARK_MOD_02_SET(3);
+ NmtState = EplNmtkGetNmtState();
+
+ if (NmtState <= kEplNmtGsResetConfiguration) {
+ goto Exit;
+ }
+
+ pFrame = (tEplFrame *) pRxBuffer_p->m_pbBuffer;
+
+#if EDRV_EARLY_RX_INT != FALSE
+ switch (pRxBuffer_p->m_BufferInFrame) {
+ case kEdrvBufferFirstInFrame:
+ {
+ MsgType =
+ (tEplMsgType) AmiGetByteFromLe(&pFrame->
+ m_le_bMessageType);
+ if (MsgType == kEplMsgTypePreq) {
+ if (EplDllkInstance_g.m_DllState == kEplDllCsWaitPreq) { // PReq expected and actually received
+ // d.k.: The condition above is sufficent, because EPL cycle is active
+ // and no non-EPL frame shall be received in isochronous phase.
+ // start transmission PRes
+ // $$$ What if Tx buffer is invalid?
+ pTxBuffer =
+ &EplDllkInstance_g.
+ m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
+#if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
+ Ret = EdrvTxMsgStart(pTxBuffer);
+#else
+ pTxFrame =
+ (tEplFrame *) pTxBuffer->m_pbBuffer;
+ // update frame (NMT state, RD, RS, PR, MS, EN flags)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bFlag2,
+ EplDllkInstance_g.
+ m_bFlag2);
+ if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
+ // $$$ reset only RD flag; set other flags appropriately
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Pres.
+ m_le_bFlag1, 0);
+ }
+ // $$$ make function that updates Pres, StatusRes
+ // send PRes frame
+ Ret = EdrvSendTxMsg(pTxBuffer);
+#endif
+ }
+ }
+ goto Exit;
+ }
+
+ case kEdrvBufferMiddleInFrame:
+ {
+ goto Exit;
+ }
+
+ case kEdrvBufferLastInFrame:
+ {
+ break;
+ }
+ }
+#endif
+
+ FrameInfo.m_pFrame = pFrame;
+ FrameInfo.m_uiFrameSize = pRxBuffer_p->m_uiRxMsgLen;
+ FrameInfo.m_NetTime.m_dwNanoSec = pRxBuffer_p->m_NetTime.m_dwNanoSec;
+ FrameInfo.m_NetTime.m_dwSec = pRxBuffer_p->m_NetTime.m_dwSec;
+
+ if (AmiGetWordFromBe(&pFrame->m_be_wEtherType) != EPL_C_DLL_ETHERTYPE_EPL) { // non-EPL frame
+ //TRACE2("EplDllkCbFrameReceived: pfnCbAsync=0x%p SrcMAC=0x%llx\n", EplDllkInstance_g.m_pfnCbAsync, AmiGetQword48FromBe(pFrame->m_be_abSrcMac));
+ if (EplDllkInstance_g.m_pfnCbAsync != NULL) { // handler for async frames is registered
+ EplDllkInstance_g.m_pfnCbAsync(&FrameInfo);
+ }
+
+ goto Exit;
+ }
+
+ MsgType = (tEplMsgType) AmiGetByteFromLe(&pFrame->m_le_bMessageType);
+ switch (MsgType) {
+ case kEplMsgTypePreq:
+ {
+ // PReq frame
+ // d.k.: (we assume that this PReq frame is intended for us and don't check DstNodeId)
+ if (AmiGetByteFromLe(&pFrame->m_le_bDstNodeId) != EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) { // this PReq is not intended for us
+ goto Exit;
+ }
+ NmtEvent = kEplNmtEventDllCePreq;
+
+ if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
+ break;
+ }
+#if EDRV_EARLY_RX_INT == FALSE
+ if (NmtState >= kEplNmtCsPreOperational2) { // respond to and process PReq frames only in PreOp2, ReadyToOp and Op
+ // Does PRes exist?
+ pTxBuffer =
+ &EplDllkInstance_g.
+ m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
+ if (pTxBuffer->m_pbBuffer != NULL) { // PRes does exist
+#if (EPL_DLL_PRES_READY_AFTER_SOA != FALSE) || (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
+ EdrvTxMsgStart(pTxBuffer);
+#else
+ pTxFrame =
+ (tEplFrame *) pTxBuffer->m_pbBuffer;
+ // update frame (NMT state, RD, RS, PR, MS, EN flags)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bFlag2,
+ EplDllkInstance_g.
+ m_bFlag2);
+ bFlag1 =
+ AmiGetByteFromLe(&pFrame->m_Data.
+ m_Preq.
+ m_le_bFlag1);
+ // save EA flag
+ EplDllkInstance_g.m_bMnFlag1 =
+ (EplDllkInstance_g.
+ m_bMnFlag1 & ~EPL_FRAME_FLAG1_EA)
+ | (bFlag1 & EPL_FRAME_FLAG1_EA);
+ // preserve MS flag
+ bFlag1 &= EPL_FRAME_FLAG1_MS;
+ // add EN flag from Error signaling module
+ bFlag1 |=
+ EplDllkInstance_g.
+ m_bFlag1 & EPL_FRAME_FLAG1_EN;
+ if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
+ // reset only RD flag
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Pres.
+ m_le_bFlag1,
+ bFlag1);
+ } else { // leave RD flag untouched
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Pres.
+ m_le_bFlag1,
+ (AmiGetByteFromLe
+ (&pTxFrame->
+ m_Data.m_Pres.
+ m_le_bFlag1) &
+ EPL_FRAME_FLAG1_RD)
+ | bFlag1);
+ }
+ // $$$ update EPL_DLL_PRES_READY_AFTER_* code
+ // send PRes frame
+ Ret = EdrvSendTxMsg(pTxBuffer);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+ }
+#endif
+ // inform PDO module
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ if (NmtState >= kEplNmtCsReadyToOperate) { // inform PDO module only in ReadyToOp and Op
+ if (NmtState != kEplNmtCsOperational) {
+ // reset RD flag and all other flags, but that does not matter, because they were processed above
+ AmiSetByteToLe(&pFrame->m_Data.
+ m_Preq.
+ m_le_bFlag1, 0);
+ }
+ // compares real frame size and PDO size
+ if ((unsigned
+ int)(AmiGetWordFromLe(&pFrame->
+ m_Data.
+ m_Preq.
+ m_le_wSize) +
+ 24)
+ > FrameInfo.m_uiFrameSize) { // format error
+ tEplErrorHandlerkEvent DllEvent;
+
+ DllEvent.m_ulDllErrorEvents =
+ EPL_DLL_ERR_INVALID_FORMAT;
+ DllEvent.m_uiNodeId =
+ AmiGetByteFromLe(&pFrame->
+ m_le_bSrcNodeId);
+ DllEvent.m_NmtState = NmtState;
+ Event.m_EventSink =
+ kEplEventSinkErrk;
+ Event.m_EventType =
+ kEplEventTypeDllError;
+ Event.m_NetTime =
+ FrameInfo.m_NetTime;
+ Event.m_uiSize =
+ sizeof(DllEvent);
+ Event.m_pArg = &DllEvent;
+ Ret = EplEventkPost(&Event);
+ break;
+ }
+ // forward PReq frame as RPDO to PDO module
+ Ret = EplPdokCbPdoReceived(&FrameInfo);
+
+ }
+#if (EPL_DLL_PRES_READY_AFTER_SOC != FALSE)
+ if (pTxBuffer->m_pbBuffer != NULL) { // PRes does exist
+ // inform PDO module about PRes after PReq
+ FrameInfo.m_pFrame =
+ (tEplFrame *) pTxBuffer->m_pbBuffer;
+ FrameInfo.m_uiFrameSize =
+ pTxBuffer->m_uiMaxBufferLen;
+ Ret =
+ EplPdokCbPdoTransmitted(&FrameInfo);
+ }
+#endif
+#endif
+
+#if EDRV_EARLY_RX_INT == FALSE
+ // $$$ inform emergency protocol handling (error signaling module) about flags
+ }
+#endif
+
+ // reset cycle counter
+ EplDllkInstance_g.m_uiCycleCount = 0;
+
+ break;
+ }
+
+ case kEplMsgTypePres:
+ {
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ tEplDllkNodeInfo *pIntNodeInfo;
+ tEplHeartbeatEvent HeartbeatEvent;
+#endif
+
+ // PRes frame
+ NmtEvent = kEplNmtEventDllCePres;
+
+ uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
+
+ if ((NmtState >= kEplNmtCsPreOperational2)
+ && (NmtState <= kEplNmtCsOperational)) { // process PRes frames only in PreOp2, ReadyToOp and Op of CN
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ pIntNodeInfo = EplDllkGetNodeInfo(uiNodeId);
+ if (pIntNodeInfo == NULL) { // no node info structure available
+ Ret = kEplDllNoNodeInfo;
+ goto Exit;
+ }
+ } else if (EplDllkInstance_g.m_DllState == kEplDllMsWaitPres) { // or process PRes frames in MsWaitPres
+
+ pIntNodeInfo = EplDllkInstance_g.m_pCurNodeInfo;
+ if ((pIntNodeInfo == NULL) || (pIntNodeInfo->m_uiNodeId != uiNodeId)) { // ignore PRes, because it is from wrong CN
+ // $$$ maybe post event to NmtMn module
+ goto Exit;
+ }
+ // forward Flag2 to asynchronous scheduler
+ bFlag1 =
+ AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.
+ m_Payload.m_StatusResponse.
+ m_le_bFlag2);
+ Ret =
+ EplDllkCalAsyncSetPendingRequests(uiNodeId,
+ ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), (bFlag1 & EPL_FRAME_FLAG2_RS));
+
+#endif
+ } else { // ignore PRes, because it was received in wrong NMT state
+ // but execute EplDllkChangeState() and post event to NMT module
+ break;
+ }
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ { // check NMT state of CN
+ HeartbeatEvent.m_wErrorCode = EPL_E_NO_ERROR;
+ HeartbeatEvent.m_NmtState =
+ (tEplNmtState) (AmiGetByteFromLe
+ (&pFrame->m_Data.m_Pres.
+ m_le_bNmtStatus) |
+ EPL_NMT_TYPE_CS);
+ if (pIntNodeInfo->m_NmtState != HeartbeatEvent.m_NmtState) { // NMT state of CN has changed -> post event to NmtMnu module
+ if (pIntNodeInfo->m_fSoftDelete == FALSE) { // normal isochronous CN
+ HeartbeatEvent.m_uiNodeId =
+ uiNodeId;
+ Event.m_EventSink =
+ kEplEventSinkNmtMnu;
+ Event.m_EventType =
+ kEplEventTypeHeartbeat;
+ Event.m_uiSize =
+ sizeof(HeartbeatEvent);
+ Event.m_pArg = &HeartbeatEvent;
+ } else { // CN shall be deleted softly
+ Event.m_EventSink =
+ kEplEventSinkDllkCal;
+ Event.m_EventType =
+ kEplEventTypeDllkSoftDelNode;
+ Event.m_uiSize =
+ sizeof(unsigned int);
+ Event.m_pArg =
+ &pIntNodeInfo->m_uiNodeId;
+ }
+ Event.m_NetTime = FrameInfo.m_NetTime;
+ Ret = EplEventkPost(&Event);
+
+ // save current NMT state of CN in internal node structure
+ pIntNodeInfo->m_NmtState =
+ HeartbeatEvent.m_NmtState;
+ }
+ }
+#endif
+
+ // inform PDO module
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ if ((NmtState != kEplNmtCsPreOperational2)
+ && (NmtState != kEplNmtMsPreOperational2)) { // inform PDO module only in ReadyToOp and Op
+ // compare real frame size and PDO size?
+ if (((unsigned
+ int)(AmiGetWordFromLe(&pFrame->m_Data.
+ m_Pres.m_le_wSize) +
+ 24)
+ > FrameInfo.m_uiFrameSize)
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ ||
+ (AmiGetWordFromLe
+ (&pFrame->m_Data.m_Pres.m_le_wSize) >
+ pIntNodeInfo->m_wPresPayloadLimit)
+#endif
+ ) { // format error
+ tEplErrorHandlerkEvent DllEvent;
+
+ DllEvent.m_ulDllErrorEvents =
+ EPL_DLL_ERR_INVALID_FORMAT;
+ DllEvent.m_uiNodeId = uiNodeId;
+ DllEvent.m_NmtState = NmtState;
+ Event.m_EventSink = kEplEventSinkErrk;
+ Event.m_EventType =
+ kEplEventTypeDllError;
+ Event.m_NetTime = FrameInfo.m_NetTime;
+ Event.m_uiSize = sizeof(DllEvent);
+ Event.m_pArg = &DllEvent;
+ Ret = EplEventkPost(&Event);
+ break;
+ }
+ if ((NmtState != kEplNmtCsOperational)
+ && (NmtState != kEplNmtMsOperational)) {
+ // reset RD flag and all other flags, but that does not matter, because they were processed above
+ AmiSetByteToLe(&pFrame->m_Data.m_Pres.
+ m_le_bFlag1, 0);
+ }
+ Ret = EplPdokCbPdoReceived(&FrameInfo);
+ }
+#endif
+
+ break;
+ }
+
+ case kEplMsgTypeSoc:
+ {
+ // SoC frame
+ NmtEvent = kEplNmtEventDllCeSoc;
+
+ if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
+ break;
+ }
+#if EPL_DLL_PRES_READY_AFTER_SOC != FALSE
+ // post PRes to transmit FIFO of the ethernet controller, but don't start
+ // transmission over bus
+ pTxBuffer =
+ &EplDllkInstance_g.
+ m_pTxBuffer[EPL_DLLK_TXFRAME_PRES];
+ // Does PRes exist?
+ if (pTxBuffer->m_pbBuffer != NULL) { // PRes does exist
+ pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
+ // update frame (NMT state, RD, RS, PR, MS, EN flags)
+ if (NmtState < kEplNmtCsPreOperational2) { // NMT state is not PreOp2, ReadyToOp or Op
+ // fake NMT state PreOp2, because PRes will be sent only in PreOp2 or greater
+ NmtState = kEplNmtCsPreOperational2;
+ }
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bFlag2,
+ EplDllkInstance_g.m_bFlag2);
+ if (NmtState != kEplNmtCsOperational) { // mark PDO as invalid in NMT state Op
+ // $$$ reset only RD flag; set other flags appropriately
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.
+ m_le_bFlag1, 0);
+ }
+ // $$$ make function that updates Pres, StatusRes
+ // mark PRes frame as ready for transmission
+ Ret = EdrvTxMsgReady(pTxBuffer);
+ }
+#endif
+
+ if (NmtState >= kEplNmtCsPreOperational2) { // SoC frames only in PreOp2, ReadyToOp and Op
+ // trigger synchronous task
+ Event.m_EventSink = kEplEventSinkSync;
+ Event.m_EventType = kEplEventTypeSync;
+ Event.m_uiSize = 0;
+ Ret = EplEventkPost(&Event);
+
+ // update cycle counter
+ if (EplDllkInstance_g.m_DllConfigParam.m_uiMultiplCycleCnt > 0) { // multiplexed cycle active
+ EplDllkInstance_g.m_uiCycleCount =
+ (EplDllkInstance_g.m_uiCycleCount +
+ 1) %
+ EplDllkInstance_g.m_DllConfigParam.
+ m_uiMultiplCycleCnt;
+ }
+ }
+ // reprogram timer
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ if (EplDllkInstance_g.m_ullFrameTimeout != 0) {
+ Ret =
+ EplTimerHighReskModifyTimerNs
+ (&EplDllkInstance_g.m_TimerHdlCycle,
+ EplDllkInstance_g.m_ullFrameTimeout,
+ EplDllkCbCnTimer, 0L, FALSE);
+ }
+#endif
+
+ break;
+ }
+
+ case kEplMsgTypeSoa:
+ {
+ // SoA frame
+ NmtEvent = kEplNmtEventDllCeSoa;
+
+ if (NmtState >= kEplNmtMsNotActive) { // MN is active -> wrong msg type
+ break;
+ }
+
+ pTxFrame = NULL;
+
+ if ((NmtState & EPL_NMT_SUPERSTATE_MASK) != EPL_NMT_CS_EPLMODE) { // do not respond, if NMT state is < PreOp1 (i.e. not EPL_MODE)
+ break;
+ }
+ // check TargetNodeId
+ uiNodeId =
+ AmiGetByteFromLe(&pFrame->m_Data.m_Soa.
+ m_le_bReqServiceTarget);
+ if (uiNodeId == EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) { // local node is the target of the current request
+
+ // check ServiceId
+ ReqServiceId =
+ (tEplDllReqServiceId)
+ AmiGetByteFromLe(&pFrame->m_Data.m_Soa.
+ m_le_bReqServiceId);
+ if (ReqServiceId == kEplDllReqServiceStatus) { // StatusRequest
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) { // StatusRes does exist
+
+ pTxFrame =
+ (tEplFrame *)
+ EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_STATUSRES].
+ m_pbBuffer;
+ // update StatusRes frame (NMT state, EN, EC, RS, PR flags)
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Asnd.
+ m_Payload.
+ m_StatusResponse.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Asnd.
+ m_Payload.
+ m_StatusResponse.
+ m_le_bFlag1,
+ EplDllkInstance_g.
+ m_bFlag1);
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Asnd.
+ m_Payload.
+ m_StatusResponse.
+ m_le_bFlag2,
+ EplDllkInstance_g.
+ m_bFlag2);
+ // send StatusRes
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_STATUSRES]);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ TGT_DBG_SIGNAL_TRACE_POINT(8);
+
+ // update error signaling
+ bFlag1 =
+ AmiGetByteFromLe(&pFrame->
+ m_Data.
+ m_Soa.
+ m_le_bFlag1);
+ if (((bFlag1 ^ EplDllkInstance_g.m_bMnFlag1) & EPL_FRAME_FLAG1_ER) != 0) { // exception reset flag was changed by MN
+ // assume same state for EC in next cycle (clear all other bits)
+ if ((bFlag1 &
+ EPL_FRAME_FLAG1_ER)
+ != 0) {
+ // set EC and reset rest
+ EplDllkInstance_g.
+ m_bFlag1 =
+ EPL_FRAME_FLAG1_EC;
+ } else {
+ // reset complete flag 1 (including EC and EN)
+ EplDllkInstance_g.
+ m_bFlag1 =
+ 0;
+ }
+ }
+ // save flag 1 from MN for Status request response cycle
+ EplDllkInstance_g.m_bMnFlag1 =
+ bFlag1;
+ }
+ } else if (ReqServiceId == kEplDllReqServiceIdent) { // IdentRequest
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) { // IdentRes does exist
+ pTxFrame =
+ (tEplFrame *)
+ EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_IDENTRES].
+ m_pbBuffer;
+ // update IdentRes frame (NMT state, RS, PR flags)
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Asnd.
+ m_Payload.
+ m_IdentResponse.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->
+ m_Data.m_Asnd.
+ m_Payload.
+ m_IdentResponse.
+ m_le_bFlag2,
+ EplDllkInstance_g.
+ m_bFlag2);
+ // send IdentRes
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_IDENTRES]);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ TGT_DBG_SIGNAL_TRACE_POINT(7);
+ }
+ } else if (ReqServiceId == kEplDllReqServiceNmtRequest) { // NmtRequest
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) { // NmtRequest does exist
+ // check if frame is not empty and not being filled
+ if (EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ].
+ m_uiTxMsgLen >
+ EPL_DLLK_BUFLEN_FILLING) {
+ /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
+ { // pad frame
+ EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
+ } */
+ // memorize transmission
+ pTxFrame =
+ (tEplFrame *) 1;
+ // send NmtRequest
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ]);
+ if (Ret !=
+ kEplSuccessful) {
+ goto Exit;
+ }
+
+ }
+ }
+
+ } else if (ReqServiceId == kEplDllReqServiceUnspecified) { // unspecified invite
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) { // non-EPL frame does exist
+ // check if frame is not empty and not being filled
+ if (EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NONEPL].
+ m_uiTxMsgLen >
+ EPL_DLLK_BUFLEN_FILLING) {
+ /*if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen < EPL_DLLK_BUFLEN_MIN)
+ { // pad frame
+ EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_uiTxMsgLen = EPL_DLLK_BUFLEN_MIN;
+ } */
+ // memorize transmission
+ pTxFrame =
+ (tEplFrame *) 1;
+ // send non-EPL frame
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NONEPL]);
+ if (Ret !=
+ kEplSuccessful) {
+ goto Exit;
+ }
+
+ }
+ }
+
+ } else if (ReqServiceId == kEplDllReqServiceNo) { // no async service requested -> do nothing
+ }
+ }
+#if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
+ if (pTxFrame == NULL) { // signal process function readiness of PRes frame
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkPresReady;
+ Event.m_uiSize = 0;
+ Event.m_pArg = NULL;
+ Ret = EplEventkPost(&Event);
+ }
+#endif
+
+ // inform PDO module
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+// Ret = EplPdokCbSoa(&FrameInfo);
+#endif
+
+ // $$$ put SrcNodeId, NMT state and NetTime as HeartbeatEvent into eventqueue
+
+ // $$$ inform emergency protocol handling about flags
+ break;
+ }
+
+ case kEplMsgTypeAsnd:
+ {
+ // ASnd frame
+ NmtEvent = kEplNmtEventDllCeAsnd;
+
+ // ASnd service registered?
+ uiAsndServiceId =
+ (unsigned int)AmiGetByteFromLe(&pFrame->m_Data.
+ m_Asnd.
+ m_le_bServiceId);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if ((EplDllkInstance_g.m_DllState >= kEplDllMsNonCyclic)
+ &&
+ ((((tEplDllAsndServiceId) uiAsndServiceId) ==
+ kEplDllAsndStatusResponse)
+ || (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse))) { // StatusRes or IdentRes received
+ uiNodeId =
+ AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
+ if ((EplDllkInstance_g.m_LastReqServiceId ==
+ ((tEplDllReqServiceId) uiAsndServiceId))
+ && (uiNodeId == EplDllkInstance_g.m_uiLastTargetNodeId)) { // mark request as responded
+ EplDllkInstance_g.m_LastReqServiceId =
+ kEplDllReqServiceNo;
+ }
+ if (((tEplDllAsndServiceId) uiAsndServiceId) == kEplDllAsndIdentResponse) { // memorize MAC address of CN for PReq
+ tEplDllkNodeInfo *pIntNodeInfo;
+
+ pIntNodeInfo =
+ EplDllkGetNodeInfo(uiNodeId);
+ if (pIntNodeInfo == NULL) { // no node info structure available
+ Ret = kEplDllNoNodeInfo;
+ } else {
+ EPL_MEMCPY(pIntNodeInfo->
+ m_be_abMacAddr,
+ pFrame->
+ m_be_abSrcMac, 6);
+ }
+ }
+ // forward Flag2 to asynchronous scheduler
+ bFlag1 =
+ AmiGetByteFromLe(&pFrame->m_Data.m_Asnd.
+ m_Payload.m_StatusResponse.
+ m_le_bFlag2);
+ Ret =
+ EplDllkCalAsyncSetPendingRequests(uiNodeId,
+ ((tEplDllAsyncReqPriority) ((bFlag1 & EPL_FRAME_FLAG2_PR) >> EPL_FRAME_FLAG2_PR_SHIFT)), (bFlag1 & EPL_FRAME_FLAG2_RS));
+ }
+#endif
+
+ if (uiAsndServiceId < EPL_DLL_MAX_ASND_SERVICE_ID) { // ASnd service ID is valid
+ if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterAny) { // ASnd service ID is registered
+ // forward frame via async receive FIFO to userspace
+ Ret =
+ EplDllkCalAsyncFrameReceived
+ (&FrameInfo);
+ } else if (EplDllkInstance_g.m_aAsndFilter[uiAsndServiceId] == kEplDllAsndFilterLocal) { // ASnd service ID is registered, but only local node ID or broadcasts
+ // shall be forwarded
+ uiNodeId =
+ AmiGetByteFromLe(&pFrame->
+ m_le_bDstNodeId);
+ if ((uiNodeId ==
+ EplDllkInstance_g.m_DllConfigParam.
+ m_uiNodeId)
+ || (uiNodeId == EPL_C_ADR_BROADCAST)) { // ASnd frame is intended for us
+ // forward frame via async receive FIFO to userspace
+ Ret =
+ EplDllkCalAsyncFrameReceived
+ (&FrameInfo);
+ }
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ if (NmtEvent != kEplNmtEventNoEvent) { // event for DLL and NMT state machine generated
+ Ret = EplDllkChangeState(NmtEvent, NmtState);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if ((NmtEvent != kEplNmtEventDllCeAsnd)
+ && ((NmtState <= kEplNmtCsPreOperational1) || (NmtEvent != kEplNmtEventDllCePres))) { // NMT state machine is not interested in ASnd frames and PRes frames when not CsNotActive or CsPreOp1
+ // inform NMT module
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType = kEplEventTypeNmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Event.m_pArg = &NmtEvent;
+ Ret = EplEventkPost(&Event);
+ }
+ }
+
+ Exit:
+ if (Ret != kEplSuccessful) {
+ DWORD dwArg;
+
+ BENCHMARK_MOD_02_TOGGLE(9);
+
+ dwArg = EplDllkInstance_g.m_DllState | (NmtEvent << 8);
+
+ // Error event for API layer
+ Ret = EplEventkPostError(kEplEventSourceDllk,
+ Ret, sizeof(dwArg), &dwArg);
+ }
+ BENCHMARK_MOD_02_RESET(3);
+ return;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCbFrameTransmitted()
+//
+// Description: called from EdrvInterruptHandler().
+// It signals
+//
+// Parameters: pRxBuffer_p = receive buffer structure
+//
+// Returns: (none)
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static void EplDllkCbFrameTransmitted(tEdrvTxBuffer * pTxBuffer_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+ tEplDllAsyncReqPriority Priority;
+ tEplNmtState NmtState;
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
+ && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)
+ tEplFrameInfo FrameInfo;
+#endif
+
+ NmtState = EplNmtkGetNmtState();
+
+ if (NmtState <= kEplNmtGsResetConfiguration) {
+ goto Exit;
+ }
+
+ if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NMTREQ) { // frame from NMT request FIFO sent
+ // mark Tx-buffer as empty
+ pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
+
+ // post event to DLL
+ Priority = kEplDllAsyncReqPrioNmt;
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkFillTx;
+ EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
+ Event.m_pArg = &Priority;
+ Event.m_uiSize = sizeof(Priority);
+ Ret = EplEventkPost(&Event);
+ } else if ((pTxBuffer_p - EplDllkInstance_g.m_pTxBuffer) == EPL_DLLK_TXFRAME_NONEPL) { // frame from generic priority FIFO sent
+ // mark Tx-buffer as empty
+ pTxBuffer_p->m_uiTxMsgLen = EPL_DLLK_BUFLEN_EMPTY;
+
+ // post event to DLL
+ Priority = kEplDllAsyncReqPrioGeneric;
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkFillTx;
+ EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
+ Event.m_pArg = &Priority;
+ Event.m_uiSize = sizeof(Priority);
+ Ret = EplEventkPost(&Event);
+ }
+#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
+ && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE)) \
+ || (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ else if ((pTxBuffer_p->m_EplMsgType == kEplMsgTypePreq)
+ || (pTxBuffer_p->m_EplMsgType == kEplMsgTypePres)) { // PRes resp. PReq frame sent
+
+#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) \
+ && (EPL_DLL_PRES_READY_AFTER_SOC == FALSE))
+ {
+ // inform PDO module
+ FrameInfo.m_pFrame =
+ (tEplFrame *) pTxBuffer_p->m_pbBuffer;
+ FrameInfo.m_uiFrameSize = pTxBuffer_p->m_uiMaxBufferLen;
+ Ret = EplPdokCbPdoTransmitted(&FrameInfo);
+ }
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ {
+ // if own Pres on MN, trigger SoA
+ if ((NmtState >= kEplNmtMsPreOperational2)
+ && (pTxBuffer_p ==
+ &EplDllkInstance_g.
+ m_pTxBuffer[EPL_DLLK_TXFRAME_PRES])) {
+ Ret =
+ EplDllkChangeState(kEplNmtEventDllMeSoaTrig,
+ NmtState);
+ }
+ }
+#endif
+
+#if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
+ goto Exit;
+#endif
+ }
+#endif
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ else if (pTxBuffer_p->m_EplMsgType == kEplMsgTypeSoa) { // SoA frame sent
+ tEplNmtEvent NmtEvent = kEplNmtEventDllMeSoaSent;
+
+ // check if we are invited
+ if (EplDllkInstance_g.m_uiLastTargetNodeId ==
+ EplDllkInstance_g.m_DllConfigParam.m_uiNodeId) {
+ tEplFrame *pTxFrame;
+
+ if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceStatus) { // StatusRequest
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_STATUSRES].m_pbBuffer != NULL) { // StatusRes does exist
+
+ pTxFrame =
+ (tEplFrame *) EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_STATUSRES].
+ m_pbBuffer;
+ // update StatusRes frame (NMT state, EN, EC, RS, PR flags)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
+ m_Payload.
+ m_StatusResponse.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
+ m_Payload.
+ m_StatusResponse.
+ m_le_bFlag1,
+ EplDllkInstance_g.
+ m_bFlag1);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
+ m_Payload.
+ m_StatusResponse.
+ m_le_bFlag2,
+ EplDllkInstance_g.
+ m_bFlag2);
+ // send StatusRes
+ Ret =
+ EdrvSendTxMsg(&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_STATUSRES]);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ TGT_DBG_SIGNAL_TRACE_POINT(8);
+
+ }
+ } else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceIdent) { // IdentRequest
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_IDENTRES].m_pbBuffer != NULL) { // IdentRes does exist
+ pTxFrame =
+ (tEplFrame *) EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_IDENTRES].
+ m_pbBuffer;
+ // update IdentRes frame (NMT state, RS, PR flags)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
+ m_Payload.
+ m_IdentResponse.
+ m_le_bNmtStatus,
+ (BYTE) NmtState);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Asnd.
+ m_Payload.
+ m_IdentResponse.
+ m_le_bFlag2,
+ EplDllkInstance_g.
+ m_bFlag2);
+ // send IdentRes
+ Ret =
+ EdrvSendTxMsg(&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_IDENTRES]);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ TGT_DBG_SIGNAL_TRACE_POINT(7);
+ }
+ } else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceNmtRequest) { // NmtRequest
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NMTREQ].m_pbBuffer != NULL) { // NmtRequest does exist
+ // check if frame is not empty and not being filled
+ if (EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ].
+ m_uiTxMsgLen >
+ EPL_DLLK_BUFLEN_FILLING) {
+ // check if this frame is a NMT command,
+ // then forward this frame back to NmtMnu module,
+ // because it needs the time, when this frame is
+ // actually sent, to start the timer for monitoring
+ // the NMT state change.
+
+ pTxFrame =
+ (tEplFrame *)
+ EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ].
+ m_pbBuffer;
+ if ((AmiGetByteFromLe
+ (&pTxFrame->
+ m_le_bMessageType)
+ == (BYTE) kEplMsgTypeAsnd)
+ &&
+ (AmiGetByteFromLe
+ (&pTxFrame->m_Data.m_Asnd.
+ m_le_bServiceId)
+ == (BYTE) kEplDllAsndNmtCommand)) { // post event directly to NmtMnu module
+ Event.m_EventSink =
+ kEplEventSinkNmtMnu;
+ Event.m_EventType =
+ kEplEventTypeNmtMnuNmtCmdSent;
+ Event.m_uiSize =
+ EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ].
+ m_uiTxMsgLen;
+ Event.m_pArg = pTxFrame;
+ Ret =
+ EplEventkPost
+ (&Event);
+
+ }
+ // send NmtRequest
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NMTREQ]);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ }
+ }
+
+ } else if (EplDllkInstance_g.m_LastReqServiceId == kEplDllReqServiceUnspecified) { // unspecified invite
+ if (EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_NONEPL].m_pbBuffer != NULL) { // non-EPL frame does exist
+ // check if frame is not empty and not being filled
+ if (EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NONEPL].
+ m_uiTxMsgLen >
+ EPL_DLLK_BUFLEN_FILLING) {
+ // send non-EPL frame
+ Ret =
+ EdrvSendTxMsg
+ (&EplDllkInstance_g.
+ m_pTxBuffer
+ [EPL_DLLK_TXFRAME_NONEPL]);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ }
+ }
+ }
+ // ASnd frame was sent, remove the request
+ EplDllkInstance_g.m_LastReqServiceId =
+ kEplDllReqServiceNo;
+ }
+ // forward event to ErrorHandler and PDO module
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType = kEplEventTypeNmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Event.m_pArg = &NmtEvent;
+ Ret = EplEventkPost(&Event);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+#endif
+
+#if EPL_DLL_PRES_READY_AFTER_SOA != FALSE
+ else { // d.k.: Why that else? on CN it is entered on IdentRes and StatusRes
+ goto Exit;
+ }
+
+ // signal process function readiness of PRes frame
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkPresReady;
+ Event.m_uiSize = 0;
+ Event.m_pArg = NULL;
+ Ret = EplEventkPost(&Event);
+
+#endif
+
+ Exit:
+ if (Ret != kEplSuccessful) {
+ DWORD dwArg;
+
+ BENCHMARK_MOD_02_TOGGLE(9);
+
+ dwArg =
+ EplDllkInstance_g.m_DllState | (pTxBuffer_p->
+ m_EplMsgType << 16);
+
+ // Error event for API layer
+ Ret = EplEventkPostError(kEplEventSourceDllk,
+ Ret, sizeof(dwArg), &dwArg);
+ }
+
+ return;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCheckFrame()
+//
+// Description: check frame and set missing information
+//
+// Parameters: pFrame_p = ethernet frame
+// uiFrameSize_p = size of frame
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDllkCheckFrame(tEplFrame * pFrame_p,
+ unsigned int uiFrameSize_p)
+{
+ tEplMsgType MsgType;
+ WORD wEtherType;
+
+ // check frame
+ if (pFrame_p != NULL) {
+ // check SrcMAC
+ if (AmiGetQword48FromBe(pFrame_p->m_be_abSrcMac) == 0) {
+ // source MAC address
+ EPL_MEMCPY(&pFrame_p->m_be_abSrcMac[0],
+ &EplDllkInstance_g.m_be_abSrcMac[0], 6);
+ }
+ // check ethertype
+ wEtherType = AmiGetWordFromBe(&pFrame_p->m_be_wEtherType);
+ if (wEtherType == 0) {
+ // assume EPL frame
+ wEtherType = EPL_C_DLL_ETHERTYPE_EPL;
+ AmiSetWordToBe(&pFrame_p->m_be_wEtherType, wEtherType);
+ }
+
+ if (wEtherType == EPL_C_DLL_ETHERTYPE_EPL) {
+ // source node ID
+ AmiSetByteToLe(&pFrame_p->m_le_bSrcNodeId,
+ (BYTE) EplDllkInstance_g.
+ m_DllConfigParam.m_uiNodeId);
+
+ // check message type
+ MsgType =
+ AmiGetByteFromLe(&pFrame_p->m_le_bMessageType);
+ if (MsgType == 0) {
+ MsgType = kEplMsgTypeAsnd;
+ AmiSetByteToLe(&pFrame_p->m_le_bMessageType,
+ (BYTE) MsgType);
+ }
+
+ if (MsgType == kEplMsgTypeAsnd) {
+ // destination MAC address
+ AmiSetQword48ToBe(&pFrame_p->m_be_abDstMac[0],
+ EPL_C_DLL_MULTICAST_ASND);
+ }
+
+ }
+ }
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCbCnTimer()
+//
+// Description: called by timer module. It monitors the EPL cycle when it is a CN.
+//
+// Parameters: pEventArg_p = timer event argument
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+static tEplKernel PUBLIC EplDllkCbCnTimer(tEplTimerEventArg * pEventArg_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplNmtState NmtState;
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) { // zombie callback
+ // just exit
+ goto Exit;
+ }
+#endif
+
+ NmtState = EplNmtkGetNmtState();
+
+ if (NmtState <= kEplNmtGsResetConfiguration) {
+ goto Exit;
+ }
+
+ Ret = EplDllkChangeState(kEplNmtEventDllCeFrameTimeout, NmtState);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // 2008/10/15 d.k. reprogramming of timer not necessary,
+ // because it will be programmed, when SoC is received.
+/*
+ // reprogram timer
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ if ((NmtState > kEplNmtCsPreOperational1)
+ && (EplDllkInstance_g.m_ullFrameTimeout != 0))
+ {
+ Ret = EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.m_TimerHdlCycle, EplDllkInstance_g.m_ullFrameTimeout, EplDllkCbCnTimer, 0L, FALSE);
+ }
+#endif
+*/
+
+ Exit:
+ if (Ret != kEplSuccessful) {
+ DWORD dwArg;
+
+ BENCHMARK_MOD_02_TOGGLE(9);
+
+ dwArg =
+ EplDllkInstance_g.
+ m_DllState | (kEplNmtEventDllCeFrameTimeout << 8);
+
+ // Error event for API layer
+ Ret = EplEventkPostError(kEplEventSourceDllk,
+ Ret, sizeof(dwArg), &dwArg);
+ }
+
+ return Ret;
+}
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCbMnTimerCycle()
+//
+// Description: called by timer module. It triggers the SoC when it is a MN.
+//
+// Parameters: pEventArg_p = timer event argument
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplDllkCbMnTimerCycle(tEplTimerEventArg * pEventArg_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplNmtState NmtState;
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlCycle) { // zombie callback
+ // just exit
+ goto Exit;
+ }
+#endif
+
+ NmtState = EplNmtkGetNmtState();
+
+ if (NmtState <= kEplNmtGsResetConfiguration) {
+ goto Exit;
+ }
+
+ Ret = EplDllkChangeState(kEplNmtEventDllMeSocTrig, NmtState);
+
+ Exit:
+ if (Ret != kEplSuccessful) {
+ DWORD dwArg;
+
+ BENCHMARK_MOD_02_TOGGLE(9);
+
+ dwArg =
+ EplDllkInstance_g.
+ m_DllState | (kEplNmtEventDllMeSocTrig << 8);
+
+ // Error event for API layer
+ Ret = EplEventkPostError(kEplEventSourceDllk,
+ Ret, sizeof(dwArg), &dwArg);
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCbMnTimerResponse()
+//
+// Description: called by timer module. It monitors the PRes timeout.
+//
+// Parameters: pEventArg_p = timer event argument
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplDllkCbMnTimerResponse(tEplTimerEventArg *
+ pEventArg_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplNmtState NmtState;
+
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ if (pEventArg_p->m_TimerHdl != EplDllkInstance_g.m_TimerHdlResponse) { // zombie callback
+ // just exit
+ goto Exit;
+ }
+#endif
+
+ NmtState = EplNmtkGetNmtState();
+
+ if (NmtState <= kEplNmtGsResetConfiguration) {
+ goto Exit;
+ }
+
+ Ret = EplDllkChangeState(kEplNmtEventDllMePresTimeout, NmtState);
+
+ Exit:
+ if (Ret != kEplSuccessful) {
+ DWORD dwArg;
+
+ BENCHMARK_MOD_02_TOGGLE(9);
+
+ dwArg =
+ EplDllkInstance_g.
+ m_DllState | (kEplNmtEventDllMePresTimeout << 8);
+
+ // Error event for API layer
+ Ret = EplEventkPostError(kEplEventSourceDllk,
+ Ret, sizeof(dwArg), &dwArg);
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkGetNodeInfo()
+//
+// Description: returns node info structure of the specified node.
+//
+// Parameters: uiNodeId_p = node ID
+//
+// Returns: tEplDllkNodeInfo* = pointer to internal node info structure
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplDllkNodeInfo *EplDllkGetNodeInfo(unsigned int uiNodeId_p)
+{
+ // $$$ d.k.: use hash algorithm to retrieve the appropriate node info structure
+ // if size of array is less than 254.
+ uiNodeId_p--; // node ID starts at 1 but array at 0
+ if (uiNodeId_p >= tabentries(EplDllkInstance_g.m_aNodeInfo)) {
+ return NULL;
+ } else {
+ return &EplDllkInstance_g.m_aNodeInfo[uiNodeId_p];
+ }
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkMnSendSoa()
+//
+// Description: it updates and transmits the SoA.
+//
+// Parameters: NmtState_p = current NMT state
+// pDllStateProposed_p = proposed DLL state
+// fEnableInvitation_p = enable invitation for asynchronous phase
+// it will be disabled for EPL_C_DLL_PREOP1_START_CYCLES SoAs
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDllkMnSendSoa(tEplNmtState NmtState_p,
+ tEplDllState * pDllStateProposed_p,
+ BOOL fEnableInvitation_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEdrvTxBuffer *pTxBuffer = NULL;
+ tEplFrame *pTxFrame;
+ tEplDllkNodeInfo *pNodeInfo;
+
+ *pDllStateProposed_p = kEplDllMsNonCyclic;
+
+ pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOA];
+ if (pTxBuffer->m_pbBuffer != NULL) { // SoA does exist
+ pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
+
+ if (fEnableInvitation_p != FALSE) { // fetch target of asynchronous phase
+ if (EplDllkInstance_g.m_bFlag2 == 0) { // own queues are empty
+ EplDllkInstance_g.m_LastReqServiceId =
+ kEplDllReqServiceNo;
+ } else if (((tEplDllAsyncReqPriority) (EplDllkInstance_g.m_bFlag2 >> EPL_FRAME_FLAG2_PR_SHIFT)) == kEplDllAsyncReqPrioNmt) { // frames in own NMT request queue available
+ EplDllkInstance_g.m_LastReqServiceId =
+ kEplDllReqServiceNmtRequest;
+ } else {
+ EplDllkInstance_g.m_LastReqServiceId =
+ kEplDllReqServiceUnspecified;
+ }
+ Ret =
+ EplDllkCalAsyncGetSoaRequest(&EplDllkInstance_g.
+ m_LastReqServiceId,
+ &EplDllkInstance_g.
+ m_uiLastTargetNodeId);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ if (EplDllkInstance_g.m_LastReqServiceId != kEplDllReqServiceNo) { // asynchronous phase will be assigned to one node
+ if (EplDllkInstance_g.m_uiLastTargetNodeId == EPL_C_ADR_INVALID) { // exchange invalid node ID with local node ID
+ EplDllkInstance_g.m_uiLastTargetNodeId =
+ EplDllkInstance_g.m_DllConfigParam.
+ m_uiNodeId;
+ // d.k. DLL state WaitAsndTrig is not helpful;
+ // so just step over to WaitSocTrig,
+ // because own ASnd is sent automatically in CbFrameTransmitted() after SoA.
+ //*pDllStateProposed_p = kEplDllMsWaitAsndTrig;
+ *pDllStateProposed_p =
+ kEplDllMsWaitSocTrig;
+ } else { // assignment to CN
+ *pDllStateProposed_p =
+ kEplDllMsWaitAsnd;
+ }
+
+ pNodeInfo =
+ EplDllkGetNodeInfo(EplDllkInstance_g.
+ m_uiLastTargetNodeId);
+ if (pNodeInfo == NULL) { // no node info structure available
+ Ret = kEplDllNoNodeInfo;
+ goto Exit;
+ }
+ // update frame (EA, ER flags)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
+ m_le_bFlag1,
+ pNodeInfo->
+ m_bSoaFlag1 & (EPL_FRAME_FLAG1_EA
+ |
+ EPL_FRAME_FLAG1_ER));
+ } else { // no assignment of asynchronous phase
+ *pDllStateProposed_p = kEplDllMsWaitSocTrig;
+ EplDllkInstance_g.m_uiLastTargetNodeId =
+ EPL_C_ADR_INVALID;
+ }
+
+ // update frame (target)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
+ m_le_bReqServiceId,
+ (BYTE) EplDllkInstance_g.
+ m_LastReqServiceId);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
+ m_le_bReqServiceTarget,
+ (BYTE) EplDllkInstance_g.
+ m_uiLastTargetNodeId);
+
+ } else { // invite nobody
+ // update frame (target)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
+ m_le_bReqServiceId, (BYTE) 0);
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.
+ m_le_bReqServiceTarget, (BYTE) 0);
+ }
+
+ // update frame (NMT state)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Soa.m_le_bNmtStatus,
+ (BYTE) NmtState_p);
+
+ // send SoA frame
+ Ret = EdrvSendTxMsg(pTxBuffer);
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkMnSendSoc()
+//
+// Description: it updates and transmits the SoA.
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDllkMnSendSoc(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEdrvTxBuffer *pTxBuffer = NULL;
+ tEplFrame *pTxFrame;
+ tEplEvent Event;
+
+ pTxBuffer = &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_SOC];
+ if (pTxBuffer->m_pbBuffer != NULL) { // SoC does exist
+ pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
+
+ // $$$ update NetTime
+
+ // send SoC frame
+ Ret = EdrvSendTxMsg(pTxBuffer);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // trigger synchronous task
+ Event.m_EventSink = kEplEventSinkSync;
+ Event.m_EventType = kEplEventTypeSync;
+ Event.m_uiSize = 0;
+ Ret = EplEventkPost(&Event);
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkMnSendPreq()
+//
+// Description: it updates and transmits the PReq for the next isochronous CN
+// or own PRes if enabled.
+//
+// Parameters: NmtState_p = current NMT state
+// pDllStateProposed_p = proposed DLL state
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDllkMnSendPreq(tEplNmtState NmtState_p,
+ tEplDllState * pDllStateProposed_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEdrvTxBuffer *pTxBuffer = NULL;
+ tEplFrame *pTxFrame;
+ BYTE bFlag1 = 0;
+
+ if (EplDllkInstance_g.m_pCurNodeInfo == NULL) { // start with first isochronous CN
+ EplDllkInstance_g.m_pCurNodeInfo =
+ EplDllkInstance_g.m_pFirstNodeInfo;
+ } else { // iterate to next isochronous CN
+ EplDllkInstance_g.m_pCurNodeInfo =
+ EplDllkInstance_g.m_pCurNodeInfo->m_pNextNodeInfo;
+ }
+
+ if (EplDllkInstance_g.m_pCurNodeInfo == NULL) { // last isochronous CN reached
+ Ret = EplDllkMnSendSoa(NmtState_p, pDllStateProposed_p, TRUE);
+ goto Exit;
+ } else {
+ pTxBuffer = EplDllkInstance_g.m_pCurNodeInfo->m_pPreqTxBuffer;
+ bFlag1 =
+ EplDllkInstance_g.m_pCurNodeInfo->
+ m_bSoaFlag1 & EPL_FRAME_FLAG1_EA;
+ *pDllStateProposed_p = kEplDllMsWaitPres;
+
+ // start PRes Timer
+ // $$$ d.k.: maybe move this call to CbFrameTransmitted(), because the time should run from there
+#if EPL_TIMER_USE_HIGHRES != FALSE
+ Ret =
+ EplTimerHighReskModifyTimerNs(&EplDllkInstance_g.
+ m_TimerHdlResponse,
+ EplDllkInstance_g.
+ m_pCurNodeInfo->
+ m_dwPresTimeout,
+ EplDllkCbMnTimerResponse, 0L,
+ FALSE);
+#endif
+ }
+
+ if (pTxBuffer == NULL) { // PReq does not exist
+ Ret = kEplDllTxBufNotReady;
+ goto Exit;
+ }
+
+ pTxFrame = (tEplFrame *) pTxBuffer->m_pbBuffer;
+
+ if (pTxFrame != NULL) { // PReq does exist
+ if (NmtState_p == kEplNmtMsOperational) { // leave RD flag untouched
+ bFlag1 |=
+ AmiGetByteFromLe(&pTxFrame->m_Data.m_Preq.
+ m_le_bFlag1) & EPL_FRAME_FLAG1_RD;
+ }
+
+ if (pTxBuffer == &EplDllkInstance_g.m_pTxBuffer[EPL_DLLK_TXFRAME_PRES]) { // PRes of MN will be sent
+ // update NMT state
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Pres.m_le_bNmtStatus,
+ (BYTE) NmtState_p);
+ *pDllStateProposed_p = kEplDllMsWaitSoaTrig;
+ }
+ // $$$ d.k. set EPL_FRAME_FLAG1_MS if necessary
+ // update frame (Flag1)
+ AmiSetByteToLe(&pTxFrame->m_Data.m_Preq.m_le_bFlag1, bFlag1);
+
+ // calculate frame size from payload size
+ pTxBuffer->m_uiTxMsgLen =
+ AmiGetWordFromLe(&pTxFrame->m_Data.m_Preq.m_le_wSize) + 24;
+
+ // send PReq frame
+ Ret = EdrvSendTxMsg(pTxBuffer);
+ } else {
+ Ret = kEplDllTxFrameInvalid;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkAsyncFrameNotReceived()
+//
+// Description: passes empty ASnd frame to receive FIFO.
+// It will be called only for frames with registered AsndServiceIds
+// (only kEplDllAsndFilterAny).
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDllkAsyncFrameNotReceived(tEplDllReqServiceId
+ ReqServiceId_p,
+ unsigned int uiNodeId_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ BYTE abBuffer[18];
+ tEplFrame *pFrame = (tEplFrame *) abBuffer;
+ tEplFrameInfo FrameInfo;
+
+ // check if previous SoA invitation was not answered
+ switch (ReqServiceId_p) {
+ case kEplDllReqServiceIdent:
+ case kEplDllReqServiceStatus:
+ // ASnd service registered?
+ if (EplDllkInstance_g.m_aAsndFilter[ReqServiceId_p] == kEplDllAsndFilterAny) { // ASnd service ID is registered
+ AmiSetByteToLe(&pFrame->m_le_bSrcNodeId,
+ (BYTE) uiNodeId_p);
+ // EPL MsgType ASnd
+ AmiSetByteToLe(&pFrame->m_le_bMessageType,
+ (BYTE) kEplMsgTypeAsnd);
+ // ASnd Service ID
+ AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId,
+ (BYTE) ReqServiceId_p);
+ // create frame info structure
+ FrameInfo.m_pFrame = pFrame;
+ FrameInfo.m_uiFrameSize = 18; // empty non existing ASnd frame
+ // forward frame via async receive FIFO to userspace
+ Ret = EplDllkCalAsyncFrameReceived(&FrameInfo);
+ }
+ break;
+ default:
+ // no invitation issued or it was successfully answered or it is uninteresting
+ break;
+ }
+
+ return Ret;
+}
+
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+// EOF
diff --git a/drivers/staging/epl/EplDllkCal.c b/drivers/staging/epl/EplDllkCal.c
new file mode 100644
index 000000000000..359083ebe12d
--- /dev/null
+++ b/drivers/staging/epl/EplDllkCal.c
@@ -0,0 +1,1260 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for kernel DLL Communication Abstraction Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDllkCal.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.7 $ $Date: 2008/11/13 17:13:09 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/15 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "kernel/EplDllkCal.h"
+#include "kernel/EplDllk.h"
+#include "kernel/EplEventk.h"
+
+#include "EplDllCal.h"
+#ifndef EPL_NO_FIFO
+#include "SharedBuff.h"
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplDllkCal */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define EPL_DLLKCAL_MAX_QUEUES 5 // CnGenReq, CnNmtReq, {MnGenReq, MnNmtReq}, MnIdentReq, MnStatusReq
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+#ifndef EPL_NO_FIFO
+// tShbInstance m_ShbInstanceRx; // FIFO for Rx ASnd frames
+ tShbInstance m_ShbInstanceTxNmt; // FIFO for Tx frames with NMT request priority
+ tShbInstance m_ShbInstanceTxGen; // FIFO for Tx frames with generic priority
+#else
+ unsigned int m_uiFrameSizeNmt;
+ BYTE m_abFrameNmt[1500];
+ unsigned int m_uiFrameSizeGen;
+ BYTE m_abFrameGen[1500];
+#endif
+
+ tEplDllkCalStatistics m_Statistics;
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // IdentRequest queue with CN node IDs
+ unsigned int m_auiQueueIdentReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty
+ unsigned int m_uiWriteIdentReq;
+ unsigned int m_uiReadIdentReq;
+
+ // StatusRequest queue with CN node IDs
+ unsigned int m_auiQueueStatusReq[EPL_D_NMT_MaxCNNumber_U8 + 1]; // 1 entry is reserved to distinguish between full and empty
+ unsigned int m_uiWriteStatusReq;
+ unsigned int m_uiReadStatusReq;
+
+ unsigned int m_auiQueueCnRequests[254 * 2];
+ // first 254 entries represent the generic requests of the corresponding node
+ // second 254 entries represent the NMT requests of the corresponding node
+ unsigned int m_uiNextQueueCnRequest;
+ unsigned int m_uiNextRequestQueue;
+#endif
+
+} tEplDllkCalInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+// if no dynamic memory allocation shall be used
+// define structures statically
+static tEplDllkCalInstance EplDllkCalInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAddInstance()
+//
+// Description: add and initialize new instance of DLL CAL module
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAddInstance()
+{
+ tEplKernel Ret = kEplSuccessful;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+ unsigned int fShbNewCreated;
+
+/* ShbError = ShbCirAllocBuffer (EPL_DLLCAL_BUFFER_SIZE_RX, EPL_DLLCAL_BUFFER_ID_RX,
+ &EplDllkCalInstance_g.m_ShbInstanceRx, &fShbNewCreated);
+ // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
+
+ if (ShbError != kShbOk)
+ {
+ Ret = kEplNoResource;
+ }
+*/
+ ShbError =
+ ShbCirAllocBuffer(EPL_DLLCAL_BUFFER_SIZE_TX_NMT,
+ EPL_DLLCAL_BUFFER_ID_TX_NMT,
+ &EplDllkCalInstance_g.m_ShbInstanceTxNmt,
+ &fShbNewCreated);
+ // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
+
+ if (ShbError != kShbOk) {
+ Ret = kEplNoResource;
+ }
+
+/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxNmt, EplDllkCalTxNmtSignalHandler, kShbPriorityNormal);
+ // returns kShbOk, kShbAlreadySignaling or kShbInvalidArg
+
+ if (ShbError != kShbOk)
+ {
+ Ret = kEplNoResource;
+ }
+*/
+ ShbError =
+ ShbCirAllocBuffer(EPL_DLLCAL_BUFFER_SIZE_TX_GEN,
+ EPL_DLLCAL_BUFFER_ID_TX_GEN,
+ &EplDllkCalInstance_g.m_ShbInstanceTxGen,
+ &fShbNewCreated);
+ // returns kShbOk, kShbOpenMismatch, kShbOutOfMem or kShbInvalidArg
+
+ if (ShbError != kShbOk) {
+ Ret = kEplNoResource;
+ }
+
+/* ShbError = ShbCirSetSignalHandlerNewData (EplDllkCalInstance_g.m_ShbInstanceTxGen, EplDllkCalTxGenSignalHandler, kShbPriorityNormal);
+ // returns kShbOk, kShbAlreadySignaling or kShbInvalidArg
+
+ if (ShbError != kShbOk)
+ {
+ Ret = kEplNoResource;
+ }
+*/
+#else
+ EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
+ EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalDelInstance()
+//
+// Description: deletes instance of DLL CAL module
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalDelInstance()
+{
+ tEplKernel Ret = kEplSuccessful;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+
+/* ShbError = ShbCirReleaseBuffer (EplDllkCalInstance_g.m_ShbInstanceRx);
+ if (ShbError != kShbOk)
+ {
+ Ret = kEplNoResource;
+ }
+ EplDllkCalInstance_g.m_ShbInstanceRx = NULL;
+*/
+ ShbError = ShbCirReleaseBuffer(EplDllkCalInstance_g.m_ShbInstanceTxNmt);
+ if (ShbError != kShbOk) {
+ Ret = kEplNoResource;
+ }
+ EplDllkCalInstance_g.m_ShbInstanceTxNmt = NULL;
+
+ ShbError = ShbCirReleaseBuffer(EplDllkCalInstance_g.m_ShbInstanceTxGen);
+ if (ShbError != kShbOk) {
+ Ret = kEplNoResource;
+ }
+ EplDllkCalInstance_g.m_ShbInstanceTxGen = NULL;
+
+#else
+ EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
+ EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalProcess
+//
+// Description: process the passed configuration
+//
+// Parameters: pEvent_p = event containing configuration options
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalProcess(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ switch (pEvent_p->m_EventType) {
+ case kEplEventTypeDllkServFilter:
+ {
+ tEplDllCalAsndServiceIdFilter *pServFilter;
+
+ pServFilter =
+ (tEplDllCalAsndServiceIdFilter *) pEvent_p->m_pArg;
+ Ret =
+ EplDllkSetAsndServiceIdFilter(pServFilter->
+ m_ServiceId,
+ pServFilter->
+ m_Filter);
+ break;
+ }
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ case kEplEventTypeDllkIssueReq:
+ {
+ tEplDllCalIssueRequest *pIssueReq;
+
+ pIssueReq = (tEplDllCalIssueRequest *) pEvent_p->m_pArg;
+ Ret =
+ EplDllkCalIssueRequest(pIssueReq->m_Service,
+ pIssueReq->m_uiNodeId,
+ pIssueReq->m_bSoaFlag1);
+ break;
+ }
+
+ case kEplEventTypeDllkAddNode:
+ {
+ tEplDllNodeInfo *pNodeInfo;
+
+ pNodeInfo = (tEplDllNodeInfo *) pEvent_p->m_pArg;
+ Ret = EplDllkAddNode(pNodeInfo);
+ break;
+ }
+
+ case kEplEventTypeDllkDelNode:
+ {
+ unsigned int *puiNodeId;
+
+ puiNodeId = (unsigned int *)pEvent_p->m_pArg;
+ Ret = EplDllkDeleteNode(*puiNodeId);
+ break;
+ }
+
+ case kEplEventTypeDllkSoftDelNode:
+ {
+ unsigned int *puiNodeId;
+
+ puiNodeId = (unsigned int *)pEvent_p->m_pArg;
+ Ret = EplDllkSoftDeleteNode(*puiNodeId);
+ break;
+ }
+#endif
+
+ case kEplEventTypeDllkIdentity:
+ {
+ tEplDllIdentParam *pIdentParam;
+
+ pIdentParam = (tEplDllIdentParam *) pEvent_p->m_pArg;
+ if (pIdentParam->m_uiSizeOfStruct > pEvent_p->m_uiSize) {
+ pIdentParam->m_uiSizeOfStruct =
+ pEvent_p->m_uiSize;
+ }
+ Ret = EplDllkSetIdentity(pIdentParam);
+ break;
+ }
+
+ case kEplEventTypeDllkConfig:
+ {
+ tEplDllConfigParam *pConfigParam;
+
+ pConfigParam = (tEplDllConfigParam *) pEvent_p->m_pArg;
+ if (pConfigParam->m_uiSizeOfStruct > pEvent_p->m_uiSize) {
+ pConfigParam->m_uiSizeOfStruct =
+ pEvent_p->m_uiSize;
+ }
+ Ret = EplDllkConfig(pConfigParam);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+//Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncGetTxCount()
+//
+// Description: returns count of Tx frames of FIFO with highest priority
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAsyncGetTxCount(tEplDllAsyncReqPriority * pPriority_p,
+ unsigned int *puiCount_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+ unsigned long ulFrameCount;
+
+ // get frame count of Tx FIFO with NMT request priority
+ ShbError =
+ ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxNmt,
+ &ulFrameCount);
+ // returns kShbOk, kShbInvalidArg
+
+ // error handling
+ if (ShbError != kShbOk) {
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ if (ulFrameCount >
+ EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt) {
+ EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt =
+ ulFrameCount;
+ }
+
+ if (ulFrameCount != 0) { // NMT requests are in queue
+ *pPriority_p = kEplDllAsyncReqPrioNmt;
+ *puiCount_p = (unsigned int)ulFrameCount;
+ goto Exit;
+ }
+ // get frame count of Tx FIFO with generic priority
+ ShbError =
+ ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxGen,
+ &ulFrameCount);
+ // returns kShbOk, kShbInvalidArg
+
+ // error handling
+ if (ShbError != kShbOk) {
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ if (ulFrameCount >
+ EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen) {
+ EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen =
+ ulFrameCount;
+ }
+
+ *pPriority_p = kEplDllAsyncReqPrioGeneric;
+ *puiCount_p = (unsigned int)ulFrameCount;
+
+ Exit:
+#else
+ if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0) {
+ *pPriority_p = kEplDllAsyncReqPrioNmt;
+ *puiCount_p = 1;
+ } else if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0) {
+ *pPriority_p = kEplDllAsyncReqPrioGeneric;
+ *puiCount_p = 1;
+ } else {
+ *pPriority_p = kEplDllAsyncReqPrioGeneric;
+ *puiCount_p = 0;
+ }
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncGetTxFrame()
+//
+// Description: returns Tx frames from FIFO with specified priority
+//
+// Parameters: pFrame_p = IN: pointer to buffer
+// puiFrameSize_p = IN: max size of buffer
+// OUT: actual size of frame
+// Priority_p = IN: priority
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAsyncGetTxFrame(void *pFrame_p,
+ unsigned int *puiFrameSize_p,
+ tEplDllAsyncReqPriority Priority_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+ unsigned long ulFrameSize;
+
+ switch (Priority_p) {
+ case kEplDllAsyncReqPrioNmt: // NMT request priority
+ ShbError =
+ ShbCirReadDataBlock(EplDllkCalInstance_g.m_ShbInstanceTxNmt,
+ (BYTE *) pFrame_p, *puiFrameSize_p,
+ &ulFrameSize);
+ // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData
+ break;
+
+ default: // generic priority
+ ShbError =
+ ShbCirReadDataBlock(EplDllkCalInstance_g.m_ShbInstanceTxGen,
+ (BYTE *) pFrame_p, *puiFrameSize_p,
+ &ulFrameSize);
+ // returns kShbOk, kShbDataTruncated, kShbInvalidArg, kShbNoReadableData
+ break;
+
+ }
+
+ // error handling
+ if (ShbError != kShbOk) {
+ if (ShbError == kShbNoReadableData) {
+ Ret = kEplDllAsyncTxBufferEmpty;
+ } else { // other error
+ Ret = kEplNoResource;
+ }
+ goto Exit;
+ }
+
+ *puiFrameSize_p = (unsigned int)ulFrameSize;
+
+ Exit:
+#else
+ switch (Priority_p) {
+ case kEplDllAsyncReqPrioNmt: // NMT request priority
+ *puiFrameSize_p =
+ min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeNmt);
+ EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameNmt,
+ *puiFrameSize_p);
+ EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
+ break;
+
+ default: // generic priority
+ *puiFrameSize_p =
+ min(*puiFrameSize_p, EplDllkCalInstance_g.m_uiFrameSizeGen);
+ EPL_MEMCPY(pFrame_p, EplDllkCalInstance_g.m_abFrameGen,
+ *puiFrameSize_p);
+ EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
+ break;
+ }
+
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncFrameReceived()
+//
+// Description: passes ASnd frame to receive FIFO.
+// It will be called only for frames with registered AsndServiceIds.
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAsyncFrameReceived(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+
+ Event.m_EventSink = kEplEventSinkDlluCal;
+ Event.m_EventType = kEplEventTypeAsndRx;
+ Event.m_pArg = pFrameInfo_p->m_pFrame;
+ Event.m_uiSize = pFrameInfo_p->m_uiFrameSize;
+ // pass NetTime of frame to userspace
+ Event.m_NetTime = pFrameInfo_p->m_NetTime;
+
+ Ret = EplEventkPost(&Event);
+ if (Ret != kEplSuccessful) {
+ EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount++;
+ } else {
+ EplDllkCalInstance_g.m_Statistics.m_ulMaxRxFrameCount++;
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncSend()
+//
+// Description: puts the given frame into the transmit FIFO with the specified
+// priority.
+//
+// Parameters: pFrameInfo_p = frame info structure
+// Priority_p = priority
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAsyncSend(tEplFrameInfo * pFrameInfo_p,
+ tEplDllAsyncReqPriority Priority_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+
+ switch (Priority_p) {
+ case kEplDllAsyncReqPrioNmt: // NMT request priority
+ ShbError =
+ ShbCirWriteDataBlock(EplDllkCalInstance_g.
+ m_ShbInstanceTxNmt,
+ pFrameInfo_p->m_pFrame,
+ pFrameInfo_p->m_uiFrameSize);
+ // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg
+ break;
+
+ default: // generic priority
+ ShbError =
+ ShbCirWriteDataBlock(EplDllkCalInstance_g.
+ m_ShbInstanceTxGen,
+ pFrameInfo_p->m_pFrame,
+ pFrameInfo_p->m_uiFrameSize);
+ // returns kShbOk, kShbExceedDataSizeLimit, kShbBufferFull, kShbInvalidArg
+ break;
+
+ }
+
+ // error handling
+ switch (ShbError) {
+ case kShbOk:
+ break;
+
+ case kShbExceedDataSizeLimit:
+ Ret = kEplDllAsyncTxBufferFull;
+ break;
+
+ case kShbBufferFull:
+ Ret = kEplDllAsyncTxBufferFull;
+ break;
+
+ case kShbInvalidArg:
+ default:
+ Ret = kEplNoResource;
+ break;
+ }
+
+#else
+
+ switch (Priority_p) {
+ case kEplDllAsyncReqPrioNmt: // NMT request priority
+ if (EplDllkCalInstance_g.m_uiFrameSizeNmt == 0) {
+ EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameNmt,
+ pFrameInfo_p->m_pFrame,
+ pFrameInfo_p->m_uiFrameSize);
+ EplDllkCalInstance_g.m_uiFrameSizeNmt =
+ pFrameInfo_p->m_uiFrameSize;
+ } else {
+ Ret = kEplDllAsyncTxBufferFull;
+ goto Exit;
+ }
+ break;
+
+ default: // generic priority
+ if (EplDllkCalInstance_g.m_uiFrameSizeGen == 0) {
+ EPL_MEMCPY(EplDllkCalInstance_g.m_abFrameGen,
+ pFrameInfo_p->m_pFrame,
+ pFrameInfo_p->m_uiFrameSize);
+ EplDllkCalInstance_g.m_uiFrameSizeGen =
+ pFrameInfo_p->m_uiFrameSize;
+ } else {
+ Ret = kEplDllAsyncTxBufferFull;
+ goto Exit;
+ }
+ break;
+ }
+
+#endif
+
+ // post event to DLL
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkFillTx;
+ EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
+ Event.m_pArg = &Priority_p;
+ Event.m_uiSize = sizeof(Priority_p);
+ Ret = EplEventkPost(&Event);
+
+#ifdef EPL_NO_FIFO
+ Exit:
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncClearBuffer()
+//
+// Description: clears the transmit buffer
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAsyncClearBuffer(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+
+ ShbError =
+ ShbCirResetBuffer(EplDllkCalInstance_g.m_ShbInstanceTxNmt, 1000,
+ NULL);
+ ShbError =
+ ShbCirResetBuffer(EplDllkCalInstance_g.m_ShbInstanceTxGen, 1000,
+ NULL);
+
+#else
+ EplDllkCalInstance_g.m_uiFrameSizeNmt = 0;
+ EplDllkCalInstance_g.m_uiFrameSizeGen = 0;
+#endif
+
+// EPL_MEMSET(&EplDllkCalInstance_g.m_Statistics, 0, sizeof (tEplDllkCalStatistics));
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncClearQueues()
+//
+// Description: clears the transmit buffer
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+tEplKernel EplDllkCalAsyncClearQueues(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // clear MN asynchronous queues
+ EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0;
+ EplDllkCalInstance_g.m_uiNextRequestQueue = 0;
+ EplDllkCalInstance_g.m_uiReadIdentReq = 0;
+ EplDllkCalInstance_g.m_uiWriteIdentReq = 0;
+ EplDllkCalInstance_g.m_uiReadStatusReq = 0;
+ EplDllkCalInstance_g.m_uiWriteStatusReq = 0;
+
+ return Ret;
+}
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalGetStatistics()
+//
+// Description: returns statistics of the asynchronous queues.
+//
+// Parameters: ppStatistics = statistics structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalGetStatistics(tEplDllkCalStatistics ** ppStatistics)
+{
+ tEplKernel Ret = kEplSuccessful;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+
+ ShbError =
+ ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxNmt,
+ &EplDllkCalInstance_g.m_Statistics.
+ m_ulCurTxFrameCountNmt);
+ ShbError =
+ ShbCirGetReadBlockCount(EplDllkCalInstance_g.m_ShbInstanceTxGen,
+ &EplDllkCalInstance_g.m_Statistics.
+ m_ulCurTxFrameCountGen);
+// ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceRx, &EplDllkCalInstance_g.m_Statistics.m_ulCurRxFrameCount);
+
+#else
+ if (EplDllkCalInstance_g.m_uiFrameSizeNmt > 0) {
+ EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 1;
+ } else {
+ EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountNmt = 0;
+ }
+ if (EplDllkCalInstance_g.m_uiFrameSizeGen > 0) {
+ EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 1;
+ } else {
+ EplDllkCalInstance_g.m_Statistics.m_ulCurTxFrameCountGen = 0;
+ }
+#endif
+
+ *ppStatistics = &EplDllkCalInstance_g.m_Statistics;
+ return Ret;
+}
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalIssueRequest()
+//
+// Description: issues a StatusRequest or a IdentRequest to the specified node.
+//
+// Parameters: Service_p = request service ID
+// uiNodeId_p = node ID
+// bSoaFlag1_p = flag1 for this node (transmit in SoA and PReq)
+// If 0xFF this flag is ignored.
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p,
+ unsigned int uiNodeId_p, BYTE bSoaFlag1_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (bSoaFlag1_p != 0xFF) {
+ Ret = EplDllkSetFlag1OfNode(uiNodeId_p, bSoaFlag1_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+ // add node to appropriate request queue
+ switch (Service_p) {
+ case kEplDllReqServiceIdent:
+ {
+ if (((EplDllkCalInstance_g.m_uiWriteIdentReq +
+ 1) %
+ tabentries(EplDllkCalInstance_g.
+ m_auiQueueIdentReq))
+ == EplDllkCalInstance_g.m_uiReadIdentReq) { // queue is full
+ Ret = kEplDllAsyncTxBufferFull;
+ goto Exit;
+ }
+ EplDllkCalInstance_g.
+ m_auiQueueIdentReq[EplDllkCalInstance_g.
+ m_uiWriteIdentReq] = uiNodeId_p;
+ EplDllkCalInstance_g.m_uiWriteIdentReq =
+ (EplDllkCalInstance_g.m_uiWriteIdentReq +
+ 1) %
+ tabentries(EplDllkCalInstance_g.m_auiQueueIdentReq);
+ break;
+ }
+
+ case kEplDllReqServiceStatus:
+ {
+ if (((EplDllkCalInstance_g.m_uiWriteStatusReq +
+ 1) %
+ tabentries(EplDllkCalInstance_g.
+ m_auiQueueStatusReq))
+ == EplDllkCalInstance_g.m_uiReadStatusReq) { // queue is full
+ Ret = kEplDllAsyncTxBufferFull;
+ goto Exit;
+ }
+ EplDllkCalInstance_g.
+ m_auiQueueStatusReq[EplDllkCalInstance_g.
+ m_uiWriteStatusReq] =
+ uiNodeId_p;
+ EplDllkCalInstance_g.m_uiWriteStatusReq =
+ (EplDllkCalInstance_g.m_uiWriteStatusReq +
+ 1) %
+ tabentries(EplDllkCalInstance_g.
+ m_auiQueueStatusReq);
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplDllInvalidParam;
+ goto Exit;
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncGetSoaRequest()
+//
+// Description: returns next request for SoA. This function is called by DLLk module.
+//
+// Parameters: pReqServiceId_p = pointer to request service ID
+// IN: available request for MN NMT or generic request queue (Flag2.PR)
+// or kEplDllReqServiceNo if queues are empty
+// OUT: next request
+// puiNodeId_p = OUT: pointer to node ID of next request
+// = EPL_C_ADR_INVALID, if request is self addressed
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAsyncGetSoaRequest(tEplDllReqServiceId * pReqServiceId_p,
+ unsigned int *puiNodeId_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiCount;
+
+// *pReqServiceId_p = kEplDllReqServiceNo;
+
+ for (uiCount = EPL_DLLKCAL_MAX_QUEUES; uiCount > 0; uiCount--) {
+ switch (EplDllkCalInstance_g.m_uiNextRequestQueue) {
+ case 0:
+ { // CnGenReq
+ for (;
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest <
+ (tabentries
+ (EplDllkCalInstance_g.
+ m_auiQueueCnRequests) / 2);
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest++) {
+ if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0) { // non empty queue found
+ // remove one request from queue
+ EplDllkCalInstance_g.
+ m_auiQueueCnRequests
+ [EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest]--;
+ *puiNodeId_p =
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest + 1;
+ *pReqServiceId_p =
+ kEplDllReqServiceUnspecified;
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest++;
+ if (EplDllkCalInstance_g.m_uiNextQueueCnRequest >= (tabentries(EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) { // last node reached
+ // continue with CnNmtReq queue at next SoA
+ EplDllkCalInstance_g.
+ m_uiNextRequestQueue
+ = 1;
+ }
+ goto Exit;
+ }
+ }
+ // all CnGenReq queues are empty -> continue with CnNmtReq queue
+ EplDllkCalInstance_g.m_uiNextRequestQueue = 1;
+ break;
+ }
+
+ case 1:
+ { // CnNmtReq
+ for (;
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest <
+ tabentries(EplDllkCalInstance_g.
+ m_auiQueueCnRequests);
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest++) {
+ if (EplDllkCalInstance_g.m_auiQueueCnRequests[EplDllkCalInstance_g.m_uiNextQueueCnRequest] > 0) { // non empty queue found
+ // remove one request from queue
+ EplDllkCalInstance_g.
+ m_auiQueueCnRequests
+ [EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest]--;
+ *puiNodeId_p =
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest + 1 -
+ (tabentries
+ (EplDllkCalInstance_g.
+ m_auiQueueCnRequests) /
+ 2);
+ *pReqServiceId_p =
+ kEplDllReqServiceNmtRequest;
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest++;
+ if (EplDllkCalInstance_g.m_uiNextQueueCnRequest > tabentries(EplDllkCalInstance_g.m_auiQueueCnRequests)) { // last node reached
+ // restart CnGenReq queue
+ EplDllkCalInstance_g.
+ m_uiNextQueueCnRequest
+ = 0;
+ // continue with MnGenReq queue at next SoA
+ EplDllkCalInstance_g.
+ m_uiNextRequestQueue
+ = 2;
+ }
+ goto Exit;
+ }
+ }
+ // restart CnGenReq queue
+ EplDllkCalInstance_g.m_uiNextQueueCnRequest = 0;
+ // all CnNmtReq queues are empty -> continue with MnGenReq queue
+ EplDllkCalInstance_g.m_uiNextRequestQueue = 2;
+ break;
+ }
+
+ case 2:
+ { // MnNmtReq and MnGenReq
+ // next queue will be MnIdentReq queue
+ EplDllkCalInstance_g.m_uiNextRequestQueue = 3;
+ if (*pReqServiceId_p != kEplDllReqServiceNo) {
+ *puiNodeId_p = EPL_C_ADR_INVALID; // DLLk must exchange this with the actual node ID
+ goto Exit;
+ }
+ break;
+ }
+
+ case 3:
+ { // MnIdentReq
+ // next queue will be MnStatusReq queue
+ EplDllkCalInstance_g.m_uiNextRequestQueue = 4;
+ if (EplDllkCalInstance_g.m_uiReadIdentReq != EplDllkCalInstance_g.m_uiWriteIdentReq) { // queue is not empty
+ *puiNodeId_p =
+ EplDllkCalInstance_g.
+ m_auiQueueIdentReq
+ [EplDllkCalInstance_g.
+ m_uiReadIdentReq];
+ EplDllkCalInstance_g.m_uiReadIdentReq =
+ (EplDllkCalInstance_g.
+ m_uiReadIdentReq +
+ 1) %
+ tabentries(EplDllkCalInstance_g.
+ m_auiQueueIdentReq);
+ *pReqServiceId_p =
+ kEplDllReqServiceIdent;
+ goto Exit;
+ }
+ break;
+ }
+
+ case 4:
+ { // MnStatusReq
+ // next queue will be CnGenReq queue
+ EplDllkCalInstance_g.m_uiNextRequestQueue = 0;
+ if (EplDllkCalInstance_g.m_uiReadStatusReq != EplDllkCalInstance_g.m_uiWriteStatusReq) { // queue is not empty
+ *puiNodeId_p =
+ EplDllkCalInstance_g.
+ m_auiQueueStatusReq
+ [EplDllkCalInstance_g.
+ m_uiReadStatusReq];
+ EplDllkCalInstance_g.m_uiReadStatusReq =
+ (EplDllkCalInstance_g.
+ m_uiReadStatusReq +
+ 1) %
+ tabentries(EplDllkCalInstance_g.
+ m_auiQueueStatusReq);
+ *pReqServiceId_p =
+ kEplDllReqServiceStatus;
+ goto Exit;
+ }
+ break;
+ }
+
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDllkCalAsyncSetPendingRequests()
+//
+// Description: sets the pending asynchronous frame requests of the specified node.
+// This will add the node to the asynchronous request scheduler.
+//
+// Parameters: uiNodeId_p = node ID
+// AsyncReqPrio_p = asynchronous request priority
+// uiCount_p = count of asynchronous frames
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDllkCalAsyncSetPendingRequests(unsigned int uiNodeId_p,
+ tEplDllAsyncReqPriority
+ AsyncReqPrio_p,
+ unsigned int uiCount_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // add node to appropriate request queue
+ switch (AsyncReqPrio_p) {
+ case kEplDllAsyncReqPrioNmt:
+ {
+ uiNodeId_p--;
+ if (uiNodeId_p >=
+ (tabentries
+ (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) {
+ Ret = kEplDllInvalidParam;
+ goto Exit;
+ }
+ uiNodeId_p +=
+ tabentries(EplDllkCalInstance_g.
+ m_auiQueueCnRequests) / 2;
+ EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] =
+ uiCount_p;
+ break;
+ }
+
+ default:
+ {
+ uiNodeId_p--;
+ if (uiNodeId_p >=
+ (tabentries
+ (EplDllkCalInstance_g.m_auiQueueCnRequests) / 2)) {
+ Ret = kEplDllInvalidParam;
+ goto Exit;
+ }
+ EplDllkCalInstance_g.m_auiQueueCnRequests[uiNodeId_p] =
+ uiCount_p;
+ break;
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// Callback handler for new data signaling
+//---------------------------------------------------------------------------
+
+#ifndef EPL_NO_FIFO
+/*static void EplDllkCalTxNmtSignalHandler (
+ tShbInstance pShbRxInstance_p,
+ unsigned long ulDataSize_p)
+{
+tEplKernel Ret = kEplSuccessful;
+tEplEvent Event;
+tEplDllAsyncReqPriority Priority;
+#ifndef EPL_NO_FIFO
+tShbError ShbError;
+unsigned long ulBlockCount;
+
+ ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxNmt, &ulBlockCount);
+ if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt)
+ {
+ EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountNmt = ulBlockCount;
+ }
+
+#endif
+
+ // post event to DLL
+ Priority = kEplDllAsyncReqPrioNmt;
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkFillTx;
+ EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
+ Event.m_pArg = &Priority;
+ Event.m_uiSize = sizeof(Priority);
+ Ret = EplEventkPost(&Event);
+
+}
+
+static void EplDllkCalTxGenSignalHandler (
+ tShbInstance pShbRxInstance_p,
+ unsigned long ulDataSize_p)
+{
+tEplKernel Ret = kEplSuccessful;
+tEplEvent Event;
+tEplDllAsyncReqPriority Priority;
+#ifndef EPL_NO_FIFO
+tShbError ShbError;
+unsigned long ulBlockCount;
+
+ ShbError = ShbCirGetReadBlockCount (EplDllkCalInstance_g.m_ShbInstanceTxGen, &ulBlockCount);
+ if (ulBlockCount > EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen)
+ {
+ EplDllkCalInstance_g.m_Statistics.m_ulMaxTxFrameCountGen = ulBlockCount;
+ }
+
+#endif
+
+ // post event to DLL
+ Priority = kEplDllAsyncReqPrioGeneric;
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkFillTx;
+ EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
+ Event.m_pArg = &Priority;
+ Event.m_uiSize = sizeof(Priority);
+ Ret = EplEventkPost(&Event);
+
+}
+*/
+#endif
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplDlluCal.c b/drivers/staging/epl/EplDlluCal.c
new file mode 100644
index 000000000000..7f4a17450237
--- /dev/null
+++ b/drivers/staging/epl/EplDlluCal.c
@@ -0,0 +1,529 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for DLL Communication Abstraction Layer module in EPL user part
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDlluCal.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.7 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/20 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "user/EplDlluCal.h"
+#include "user/EplEventu.h"
+
+#include "EplDllCal.h"
+
+// include only if direct call between user- and kernelspace is enabled
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+#include "kernel/EplDllkCal.h"
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplDlluCal */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ tEplDlluCbAsnd m_apfnDlluCbAsnd[EPL_DLL_MAX_ASND_SERVICE_ID];
+
+} tEplDlluCalInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+// if no dynamic memory allocation shall be used
+// define structures statically
+static tEplDlluCalInstance EplDlluCalInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDlluCalSetAsndServiceIdFilter(tEplDllAsndServiceId
+ ServiceId_p,
+ tEplDllAsndFilter Filter_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalAddInstance()
+//
+// Description: add and initialize new instance of DLL CAL module
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalAddInstance()
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // reset instance structure
+ EPL_MEMSET(&EplDlluCalInstance_g, 0, sizeof(EplDlluCalInstance_g));
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalDelInstance()
+//
+// Description: deletes an instance of DLL CAL module
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalDelInstance()
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // reset instance structure
+ EPL_MEMSET(&EplDlluCalInstance_g, 0, sizeof(EplDlluCalInstance_g));
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalProcess
+//
+// Description: process the passed asynch frame
+//
+// Parameters: pEvent_p = event containing frame to be processed
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalProcess(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplMsgType MsgType;
+ unsigned int uiAsndServiceId;
+ tEplFrameInfo FrameInfo;
+
+ if (pEvent_p->m_EventType == kEplEventTypeAsndRx) {
+ FrameInfo.m_pFrame = (tEplFrame *) pEvent_p->m_pArg;
+ FrameInfo.m_uiFrameSize = pEvent_p->m_uiSize;
+ // extract NetTime
+ FrameInfo.m_NetTime = pEvent_p->m_NetTime;
+
+ MsgType =
+ (tEplMsgType) AmiGetByteFromLe(&FrameInfo.m_pFrame->
+ m_le_bMessageType);
+ if (MsgType != kEplMsgTypeAsnd) {
+ Ret = kEplInvalidOperation;
+ goto Exit;
+ }
+
+ uiAsndServiceId =
+ (unsigned int)AmiGetByteFromLe(&FrameInfo.m_pFrame->m_Data.
+ m_Asnd.m_le_bServiceId);
+ if (uiAsndServiceId < EPL_DLL_MAX_ASND_SERVICE_ID) { // ASnd service ID is valid
+ if (EplDlluCalInstance_g.m_apfnDlluCbAsnd[uiAsndServiceId] != NULL) { // handler was registered
+ Ret =
+ EplDlluCalInstance_g.
+ m_apfnDlluCbAsnd[uiAsndServiceId]
+ (&FrameInfo);
+ }
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalRegAsndService()
+//
+// Description: registers the specified handler for the specified
+// AsndServiceId with the specified node ID filter.
+//
+// Parameters: ServiceId_p = ASnd Service ID
+// pfnDlluCbAsnd_p = callback function
+// Filter_p = node ID filter
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalRegAsndService(tEplDllAsndServiceId ServiceId_p,
+ tEplDlluCbAsnd pfnDlluCbAsnd_p,
+ tEplDllAsndFilter Filter_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (ServiceId_p < tabentries(EplDlluCalInstance_g.m_apfnDlluCbAsnd)) {
+ // memorize function pointer
+ EplDlluCalInstance_g.m_apfnDlluCbAsnd[ServiceId_p] =
+ pfnDlluCbAsnd_p;
+
+ if (pfnDlluCbAsnd_p == NULL) { // close filter
+ Filter_p = kEplDllAsndFilterNone;
+ }
+ // set filter in DLL module in kernel part
+ Ret = EplDlluCalSetAsndServiceIdFilter(ServiceId_p, Filter_p);
+
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalAsyncSend()
+//
+// Description: sends the frame with the specified priority.
+//
+// Parameters: pFrameInfo_p = frame
+// m_uiFrameSize does not include the
+// ethernet header (14 bytes)
+// Priority_p = priority
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalAsyncSend(tEplFrameInfo * pFrameInfo_p,
+ tEplDllAsyncReqPriority Priority_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ pFrameInfo_p->m_uiFrameSize += 14; // add size of ethernet header
+ Ret = EplDllkCalAsyncSend(pFrameInfo_p, Priority_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+}
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalIssueRequest()
+//
+// Description: issues a StatusRequest or a IdentRequest to the specified node.
+//
+// Parameters: Service_p = request service ID
+// uiNodeId_p = node ID
+// bSoaFlag1_p = flag1 for this node (transmit in SoA and PReq)
+// If 0xFF this flag is ignored.
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalIssueRequest(tEplDllReqServiceId Service_p,
+ unsigned int uiNodeId_p, BYTE bSoaFlag1_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // add node to appropriate request queue
+ switch (Service_p) {
+ case kEplDllReqServiceIdent:
+ case kEplDllReqServiceStatus:
+ {
+ tEplEvent Event;
+ tEplDllCalIssueRequest IssueReq;
+
+ Event.m_EventSink = kEplEventSinkDllkCal;
+ Event.m_EventType = kEplEventTypeDllkIssueReq;
+ IssueReq.m_Service = Service_p;
+ IssueReq.m_uiNodeId = uiNodeId_p;
+ IssueReq.m_bSoaFlag1 = bSoaFlag1_p;
+ Event.m_pArg = &IssueReq;
+ Event.m_uiSize = sizeof(IssueReq);
+
+ Ret = EplEventuPost(&Event);
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplDllInvalidParam;
+ goto Exit;
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalAddNode()
+//
+// Description: adds the specified node to the isochronous phase.
+//
+// Parameters: pNodeInfo_p = pointer of node info structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalAddNode(tEplDllNodeInfo * pNodeInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+
+ Event.m_EventSink = kEplEventSinkDllkCal;
+ Event.m_EventType = kEplEventTypeDllkAddNode;
+ Event.m_pArg = pNodeInfo_p;
+ Event.m_uiSize = sizeof(tEplDllNodeInfo);
+
+ Ret = EplEventuPost(&Event);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalDeleteNode()
+//
+// Description: removes the specified node from the isochronous phase.
+//
+// Parameters: uiNodeId_p = node ID
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalDeleteNode(unsigned int uiNodeId_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+
+ Event.m_EventSink = kEplEventSinkDllkCal;
+ Event.m_EventType = kEplEventTypeDllkDelNode;
+ Event.m_pArg = &uiNodeId_p;
+ Event.m_uiSize = sizeof(uiNodeId_p);
+
+ Ret = EplEventuPost(&Event);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalSoftDeleteNode()
+//
+// Description: removes the specified node softly from the isochronous phase.
+//
+// Parameters: uiNodeId_p = node ID
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalSoftDeleteNode(unsigned int uiNodeId_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+
+ Event.m_EventSink = kEplEventSinkDllkCal;
+ Event.m_EventType = kEplEventTypeDllkSoftDelNode;
+ Event.m_pArg = &uiNodeId_p;
+ Event.m_uiSize = sizeof(uiNodeId_p);
+
+ Ret = EplEventuPost(&Event);
+
+ return Ret;
+}
+
+#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplDlluCalSetAsndServiceIdFilter()
+//
+// Description: forwards call to EplDllkSetAsndServiceIdFilter() in kernel part
+//
+// Parameters: ServiceId_p = ASnd Service ID
+// Filter_p = node ID filter
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplDlluCalSetAsndServiceIdFilter(tEplDllAsndServiceId
+ ServiceId_p,
+ tEplDllAsndFilter Filter_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+ tEplDllCalAsndServiceIdFilter ServFilter;
+
+ Event.m_EventSink = kEplEventSinkDllkCal;
+ Event.m_EventType = kEplEventTypeDllkServFilter;
+ ServFilter.m_ServiceId = ServiceId_p;
+ ServFilter.m_Filter = Filter_p;
+ Event.m_pArg = &ServFilter;
+ Event.m_uiSize = sizeof(ServFilter);
+
+ Ret = EplEventuPost(&Event);
+
+ return Ret;
+}
+
+#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplErrDef.h b/drivers/staging/epl/EplErrDef.h
new file mode 100644
index 000000000000..2aee12cfd28c
--- /dev/null
+++ b/drivers/staging/epl/EplErrDef.h
@@ -0,0 +1,294 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: definitions for all EPL-function return codes
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplErrDef.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.9 $ $Date: 2008/06/23 14:56:33 $
+
+ $State: Exp $
+
+ Build Environment:
+ all
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2005/12/05 -as: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_ERRORDEF_H_
+#define _EPL_ERRORDEF_H_
+
+//---------------------------------------------------------------------------
+// return codes
+//---------------------------------------------------------------------------
+
+typedef enum {
+ // area for generic errors 0x0000 - 0x000F
+ kEplSuccessful = 0x0000, // no error/successful run
+ kEplIllegalInstance = 0x0001, // the called Instanz does not exist
+ kEplInvalidInstanceParam = 0x0002, //
+ kEplNoFreeInstance = 0x0003, // XxxAddInstance was called but no free instance is available
+ kEplWrongSignature = 0x0004, // wrong signature while writing to object 0x1010 or 0x1011
+ kEplInvalidOperation = 0x0005, // operation not allowed in this situation
+ kEplInvalidNodeId = 0x0007, // invalid NodeId was specified
+ kEplNoResource = 0x0008, // resource could not be created (Windows, PxROS, ...)
+ kEplShutdown = 0x0009, // stack is shutting down
+ kEplReject = 0x000A, // reject the subsequent command
+
+ // area for EDRV module 0x0010 - 0x001F
+// kEplEdrvNoFrame = 0x0010, // no CAN message was received
+// kEplEdrvMsgHigh = 0x0011, // CAN message with high priority was received
+// kEplEdrvMsgLow = 0x0012, // CAN message with low priority was received
+ kEplEdrvInitError = 0x0013, // initialisation error
+ kEplEdrvNoFreeBufEntry = 0x0014, // no free entry in internal buffer table for Tx frames
+ kEplEdrvBufNotExisting = 0x0015, // specified Tx buffer does not exist
+// kEplEdrvNoFreeChannel = 0x0014, // CAN controller has not a free channel
+// kEplEdrvTxBuffHighOverrun = 0x0015, // buffer for high priority CAN transmit messages has overrun
+// kEplEdrvTxBuffLowOverrun = 0x0016, // buffer for low priority CAN transmit messages has overrun
+// kEplEdrvIllegalBdi = 0x0017, // unsupported baudrate within baudrate table
+// kEplEdrvBusy = 0x0018, // remote frame can not be updated because no bus contact or CAN
+ // transmission is activ
+// kEplEdrvInvalidDriverType = 0x0019, // (PC: Windows or Linux) invalid driver type
+// kEplEdrvDriverNotFound = 0x001A, // (PC: Windows or Linux) driver (DLL) could not be found
+// kEplEdrvInvalidBaseAddress = 0x001B, // (PC: Windows or Linux) driver could not found the CAN controller
+// kEplEdrvInvalidParam = 0x001C, // invalid param in function call
+
+ // area for COB module 0x0020 - 0x002F
+/* kEplCobNoFreeEntry = 0x0020, // no free entry in RX- or TX-COB table
+ kEplCobAlreadyExist = 0x0021, // COB-ID already exists in RX- resp. TX-COB table
+ */
+ kEplDllIllegalHdl = 0x0022, // illegal handle for a TxFrame was passed
+ kEplDllCbAsyncRegistered = 0x0023, // handler for non-EPL frames was already registered before
+// kEplDllAsyncRxBufferFull = 0x0024, // receive buffer for asynchronous frames is full
+ kEplDllAsyncTxBufferEmpty = 0x0025, // transmit buffer for asynchronous frames is empty
+ kEplDllAsyncTxBufferFull = 0x0026, // transmit buffer for asynchronous frames is full
+ kEplDllNoNodeInfo = 0x0027, // MN: too less space in the internal node info structure
+ kEplDllInvalidParam = 0x0028, // invalid parameters passed to function
+ kEplDllTxBufNotReady = 0x002E, // TxBuffer (e.g. for PReq) is not ready yet
+ kEplDllTxFrameInvalid = 0x002F, // TxFrame (e.g. for PReq) is invalid or does not exist
+/* kEplCobIllegalCanId = 0x0023, // COB-ID is not allowed (like 0x000 is reserved for NMT, ...)
+ kEplCobInvalidCanId = 0x0024, // COB-ID is switched off
+ kEplCobCdrvStateSet = 0x0025, // at least one bit of CAN driver state is set
+ kEplCobNoFreeEntryHighBuf = 0x0026, // no free entry in high priotity RX- or TX-COB table
+ kEplCobOwnId = 0x0027, // COB-ID already exists in own module which calls CobDefine() or CobCheck()
+*/
+ // area for OBD module 0x0030 - 0x003F
+ kEplObdIllegalPart = 0x0030, // unknown OD part
+ kEplObdIndexNotExist = 0x0031, // object index does not exist in OD
+ kEplObdSubindexNotExist = 0x0032, // subindex does not exist in object index
+ kEplObdReadViolation = 0x0033, // read access to a write-only object
+ kEplObdWriteViolation = 0x0034, // write access to a read-only object
+ kEplObdAccessViolation = 0x0035, // access not allowed
+ kEplObdUnknownObjectType = 0x0036, // object type not defined/known
+ kEplObdVarEntryNotExist = 0x0037, // object does not contain VarEntry structure
+ kEplObdValueTooLow = 0x0038, // value to write to an object is too low
+ kEplObdValueTooHigh = 0x0039, // value to write to an object is too high
+ kEplObdValueLengthError = 0x003A, // value to write is to long or to short
+// kEplObdIllegalFloat = 0x003B, // illegal float variable
+// kEplObdWrongOdBuilderKey = 0x003F, // OD was generated with demo version of tool ODBuilder
+
+ // area for NMT module 0x0040 - 0x004F
+ kEplNmtUnknownCommand = 0x0040, // unknown NMT command
+ kEplNmtInvalidFramePointer = 0x0041, // pointer to the frame is not valid
+ kEplNmtInvalidEvent = 0x0042, // invalid event send to NMT-modul
+ kEplNmtInvalidState = 0x0043, // unknown state in NMT-State-Maschine
+ kEplNmtInvalidParam = 0x0044, // invalid parameters specified
+
+ // area for SDO/UDP module 0x0050 - 0x005F
+ kEplSdoUdpMissCb = 0x0050, // missing callback-function pointer during inti of
+ // module
+ kEplSdoUdpNoSocket = 0x0051, // error during init of socket
+ kEplSdoUdpSocketError = 0x0052, // error during usage of socket
+ kEplSdoUdpThreadError = 0x0053, // error during start of listen thread
+ kEplSdoUdpNoFreeHandle = 0x0054, // no free connection handle for Udp
+ kEplSdoUdpSendError = 0x0055, // Error during send of frame
+ kEplSdoUdpInvalidHdl = 0x0056, // the connection handle is invalid
+
+ // area for SDO Sequence layer module 0x0060 - 0x006F
+ kEplSdoSeqMissCb = 0x0060, // no callback-function assign
+ kEplSdoSeqNoFreeHandle = 0x0061, // no free handle for connection
+ kEplSdoSeqInvalidHdl = 0x0062, // invalid handle in SDO sequence layer
+ kEplSdoSeqUnsupportedProt = 0x0063, // unsupported Protocol selected
+ kEplSdoSeqNoFreeHistory = 0x0064, // no free entry in history
+ kEplSdoSeqFrameSizeError = 0x0065, // the size of the frames is not correct
+ kEplSdoSeqRequestAckNeeded = 0x0066, // indeicates that the history buffer is full
+ // and a ack request is needed
+ kEplSdoSeqInvalidFrame = 0x0067, // frame not valid
+ kEplSdoSeqConnectionBusy = 0x0068, // connection is busy -> retry later
+ kEplSdoSeqInvalidEvent = 0x0069, // invalid event received
+
+ // area for SDO Command Layer Module 0x0070 - 0x007F
+ kEplSdoComUnsupportedProt = 0x0070, // unsupported Protocol selected
+ kEplSdoComNoFreeHandle = 0x0071, // no free handle for connection
+ kEplSdoComInvalidServiceType = 0x0072, // invalid SDO service type specified
+ kEplSdoComInvalidHandle = 0x0073, // handle invalid
+ kEplSdoComInvalidSendType = 0x0074, // the stated to of frame to send is
+ // not possible
+ kEplSdoComNotResponsible = 0x0075, // internal error: command layer handle is
+ // not responsible for this event from sequence layer
+ kEplSdoComHandleExists = 0x0076, // handle to same node already exists
+ kEplSdoComHandleBusy = 0x0077, // transfer via this handle is already running
+ kEplSdoComInvalidParam = 0x0078, // invalid parameters passed to function
+
+ // area for EPL Event-Modul 0x0080 - 0x008F
+ kEplEventUnknownSink = 0x0080, // unknown sink for event
+ kEplEventPostError = 0x0081, // error during post of event
+
+ // area for EPL Timer Modul 0x0090 - 0x009F
+ kEplTimerInvalidHandle = 0x0090, // invalid handle for timer
+ kEplTimerNoTimerCreated = 0x0091, // no timer was created caused by
+ // an error
+
+ // area for EPL SDO/Asnd Module 0x00A0 - 0x0AF
+ kEplSdoAsndInvalidNodeId = 0x00A0, //0 node id is invalid
+ kEplSdoAsndNoFreeHandle = 0x00A1, // no free handle for connection
+ kEplSdoAsndInvalidHandle = 0x00A2, // handle for connection is invalid
+
+ // area for PDO module 0x00B0 - 0x00BF
+ kEplPdoNotExist = 0x00B0, // selected PDO does not exist
+ kEplPdoLengthExceeded = 0x00B1, // length of PDO mapping exceedes 64 bis
+ kEplPdoGranularityMismatch = 0x00B2, // configured PDO granularity is not equal to supported granularity
+ kEplPdoInitError = 0x00B3, // error during initialisation of PDO module
+ kEplPdoErrorPdoEncode = 0x00B4, // error during encoding a PDO
+ kEplPdoErrorPdoDecode = 0x00B5, // error during decoding a PDO
+ kEplPdoErrorSend = 0x00B6, // error during sending a PDO
+ kEplPdoErrorSyncWin = 0x00B7, // the SYNC window runs out during sending SYNC-PDOs
+ kEplPdoErrorMapp = 0x00B8, // invalid PDO mapping
+ kEplPdoVarNotFound = 0x00B9, // variable was not found in function PdoSignalVar()
+ kEplPdoErrorEmcyPdoLen = 0x00BA, // the length of a received PDO is unequal to the expected value
+ kEplPdoWriteConstObject = 0x00BB, // constant object can not be written
+ // (only TxType, Inhibit-, Event Time for CANopen Kit)
+
+ // area for LSS slave module
+/* kEplLsssResetNode = 0x0080, // NMT command "reset node" has to be processed after LSS configuration
+ // new of NodeId
+ kEplLsssInvalidNodeId = 0x0081, // no valid NodeId is configured -> wait until it is configured with
+ // LSS service before calling CcmConnectToNet()
+*/
+ // area for emergency consumer module 0x0090 - 0x009F
+/* kEplEmccNoFreeProducerEntry = 0x0090, // no free entry to add a Emergency Producer
+ kEplEmccNodeIdNotExist = 0x0091, // selected NodeId was never added
+ kEplEmccNodeIdInvalid = 0x0092, // selected NodeId is outside of range (0x01 until 0x7F)
+ kEplEmccNodeIdExist = 0x0093, // selected NodeId already exist
+*/
+ // area for dynamic OD 0x00A0 - 0x00AF
+/* kEplDynNoMemory = 0x00A0, // no memory available
+ kEplDynInvalidConfig = 0x00A1, // invalid configuration in segment container
+*/
+ // area for hertbeat consumer module 0x00B0 - 0x00BF
+/* kEplHbcEntryNotExist = 0x00B0, // Heartbeat Producer node not configured
+ kEplHbcEntryAlreadyExist = 0x00B1, // NodeId was already defined in heartbeat consumer table (object 0x1016)
+*/
+ // Configuration manager module 0x00C0 - 0x00CF
+ kEplCfgMaConfigError = 0x00C0, // error in configuration manager
+ kEplCfgMaSdocTimeOutError = 0x00C1, // error in configuration manager, Sdo timeout
+ kEplCfgMaInvalidDcf = 0x00C2, // configration file not valid
+ kEplCfgMaUnsupportedDcf = 0x00C3, // unsupported Dcf format
+ kEplCfgMaConfigWithErrors = 0x00C4, // configuration finished with errors
+ kEplCfgMaNoFreeConfig = 0x00C5, // no free configuration entry
+ kEplCfgMaNoConfigData = 0x00C6, // no configuration data present
+ kEplCfgMaUnsuppDatatypeDcf = 0x00C7, // unsupported datatype found in dcf
+ // -> this entry was not configured
+
+ // area for LSS master module 0x00D0 - 0x00DF
+/* kEplLssmIllegalMode = 0x00D0, // illegal LSS mode (operation / configuration)
+ kEplLssmIllegalState = 0x00D1, // function was called in illegal state of LSS master
+ kEplLssmBusy = 0x00D2, // LSS process is busy with an previous service
+ kEplLssmIllegalCmd = 0x00D3, // illegal command code was set for function LssmInquireIdentity()
+ kEplLssmTimeout = 0x00D4, // LSS slave did not answer a LSS service
+ kEplLssmErrorInConfirm = 0x00D5, // LSS slave replied an error code for a LSS service
+*/
+ // area for CCM modules 0x00E0 - 0xEF
+/* kEplCcmStoreUnvalidState = 0x00E0, // memory device not available due device state
+ kEplCcmStoreHwError = 0x00E1, // hw error due device access
+*/
+ // area for SRDO module 0x0100 - 0x011F
+/* kEplSrdoNotExist = 0x0100, // selected SRDO does not exist
+ kEplSrdoGranularityMismatch = 0x0101, // configured SRDO granularity is not equal to supported granularity
+ kEplSrdoCfgTimingError = 0x0102, // configuration is not ok (Timing)
+ kEplSrdoCfgIdError = 0x0103, // configuration is not ok (CobIds)
+ kEplSrdoCfgCrcError = 0x0104, // configuration is not ok (CRC)
+ kEplSrdoNmtError = 0x0105, // an action was tried in a wrong NMT state
+ kEplSrdoInvalidCfg = 0x0106, // an action was tried with an invald SRDO configuration
+ kEplSrdoInvalid = 0x0107, // an action was tried with an invald SRDO
+ kEplSrdoRxTxConflict = 0x0108, // an transmission was tried with an receive SRDO (or the other way)
+ kEplSrdoIllegalCanId = 0x0109, // the CanId is invalid
+ kEplSrdoCanIdAlreadyInUse = 0x010A, // the CanId is already in use
+ kEplSrdoNotInOrder = 0x010B, // the two messages of a SRDO are not in order
+ kEplSrdoSctTimeout = 0x010C, // timeout of SCT
+ kEplSrdoSrvtTimeout = 0x010D, // timeout of SRVT
+ kEplSrdoCanIdNotValid = 0x010E, // one of received CAN-IDs are not equal to configured one
+ kEplSrdoDlcNotValid = 0x010F, // one of received CAN-DLC are not equal to configured one
+ kEplSrdoErrorMapp = 0x0110, // wrong values in mapping found
+ kEplSrdoDataError = 0x0111, // data of CAN messages are not invers
+ kEplSrdoLengthExceeded = 0x0112, // length of SRDO mapping exceedes 64 bit per CAN-message
+ kEplSrdoNotHandledInApp = 0x0113, // the SRDO error was not handled in AppSrdoError()
+ kEplSrdoOverrun = 0x0114 // a RxSRDO was received but the pevious one was not else processed
+*/
+
+ kEplApiTaskDeferred = 0x0140, // EPL performs task in background and informs the application (or vice-versa), when it is finished
+ kEplApiInvalidParam = 0x0142, // passed invalid parameters to a function (e.g. invalid node id)
+
+ // area untill 0x07FF is reserved
+ // area for user application from 0x0800 to 0x7FFF
+
+} tEplKernel;
+
+#endif
+//EOF
+
+// Die letzte Zeile mu unbedingt eine leere Zeile sein, weil manche Compiler
+// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder).
diff --git a/drivers/staging/epl/EplErrorHandlerk.c b/drivers/staging/epl/EplErrorHandlerk.c
new file mode 100644
index 000000000000..d12521fc99a4
--- /dev/null
+++ b/drivers/staging/epl/EplErrorHandlerk.c
@@ -0,0 +1,810 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for error handler module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplErrorHandlerk.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.9 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/10/02 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "kernel/EplErrorHandlerk.h"
+#include "EplNmt.h"
+#include "kernel/EplEventk.h"
+#include "kernel/EplObdk.h" // function prototyps of the EplOBD-Modul
+#include "kernel/EplDllk.h"
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0)
+#error "EPL ErrorHandler module needs EPL module OBDK!"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ DWORD m_dwCumulativeCnt; // subindex 1
+ DWORD m_dwThresholdCnt; // subindex 2
+ DWORD m_dwThreshold; // subindex 3
+
+} tEplErrorHandlerkErrorCounter;
+
+typedef struct {
+ tEplErrorHandlerkErrorCounter m_CnLossSoc; // object 0x1C0B
+ tEplErrorHandlerkErrorCounter m_CnLossPreq; // object 0x1C0D
+ tEplErrorHandlerkErrorCounter m_CnCrcErr; // object 0x1C0F
+ unsigned long m_ulDllErrorEvents;
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ tEplErrorHandlerkErrorCounter m_MnCrcErr; // object 0x1C00
+ tEplErrorHandlerkErrorCounter m_MnCycTimeExceed; // object 0x1C02
+ DWORD m_adwMnCnLossPresCumCnt[254]; // object 0x1C07
+ DWORD m_adwMnCnLossPresThrCnt[254]; // object 0x1C08
+ DWORD m_adwMnCnLossPresThreshold[254]; // object 0x1C09
+ BOOL m_afMnCnLossPresEvent[254];
+#endif
+
+} tEplErrorHandlerkInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+static tEplErrorHandlerkInstance EplErrorHandlerkInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplKernel EplErrorHandlerkLinkErrorCounter(tEplErrorHandlerkErrorCounter
+ * pErrorCounter_p,
+ unsigned int uiIndex_p);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+static tEplKernel EplErrorHandlerkLinkArray(DWORD * pdwValue_p,
+ unsigned int uiValueCount_p,
+ unsigned int uiIndex_p);
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <Epl-Kernelspace-Error-Handler> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplErrorHandlerkInit
+//
+// Description: function initialize the first instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplErrorHandlerkInit(void)
+{
+ tEplKernel Ret;
+
+ Ret = EplErrorHandlerkAddInstance();
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplErrorHandlerkAddInstance
+//
+// Description: function add one more instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplErrorHandlerkAddInstance(void)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // reset only event variable,
+ // all other instance members are reset by OD or may keep their current value
+ // d.k.: this is necessary for the cumulative counters, which shall not be reset
+ EplErrorHandlerkInstance_g.m_ulDllErrorEvents = 0;
+
+ // link counters to OD
+ // $$$ d.k. if OD resides in userspace, fetch pointer to shared memory,
+ // which shall have the same structure as the instance (needs to be declared globally).
+ // Other idea: error counter shall belong to the process image
+ // (reset of counters by SDO write are a little bit tricky).
+
+ Ret =
+ EplErrorHandlerkLinkErrorCounter(&EplErrorHandlerkInstance_g.
+ m_CnLossSoc, 0x1C0B);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret =
+ EplErrorHandlerkLinkErrorCounter(&EplErrorHandlerkInstance_g.
+ m_CnLossPreq, 0x1C0D);
+ // ignore return code, because object 0x1C0D is conditional
+
+ Ret =
+ EplErrorHandlerkLinkErrorCounter(&EplErrorHandlerkInstance_g.
+ m_CnCrcErr, 0x1C0F);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ Ret =
+ EplErrorHandlerkLinkErrorCounter(&EplErrorHandlerkInstance_g.
+ m_MnCrcErr, 0x1C00);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret =
+ EplErrorHandlerkLinkErrorCounter(&EplErrorHandlerkInstance_g.
+ m_MnCycTimeExceed, 0x1C02);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret =
+ EplErrorHandlerkLinkArray(EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresCumCnt,
+ tabentries(EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresCumCnt),
+ 0x1C07);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret =
+ EplErrorHandlerkLinkArray(EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThrCnt,
+ tabentries(EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThrCnt),
+ 0x1C08);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret =
+ EplErrorHandlerkLinkArray(EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThreshold,
+ tabentries(EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThreshold),
+ 0x1C09);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplErrorHandlerkDelInstance
+//
+// Description: function delete instance an free the bufferstructure
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplErrorHandlerkDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplErrorHandlerkProcess
+//
+// Description: processes error events from DLL
+//
+//
+//
+// Parameters: pEvent_p = pointer to event-structur from buffer
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplErrorHandlerkProcess(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+ unsigned long ulDllErrorEvents;
+ tEplEvent Event;
+ tEplNmtEvent NmtEvent;
+
+ Ret = kEplSuccessful;
+
+ // check m_EventType
+ switch (pEvent_p->m_EventType) {
+ case kEplEventTypeDllError:
+ {
+ tEplErrorHandlerkEvent *pErrHandlerEvent =
+ (tEplErrorHandlerkEvent *) pEvent_p->m_pArg;
+
+ ulDllErrorEvents = pErrHandlerEvent->m_ulDllErrorEvents;
+
+ // check the several error events
+ if ((EplErrorHandlerkInstance_g.m_CnLossSoc.
+ m_dwThreshold > 0)
+ && ((ulDllErrorEvents & EPL_DLL_ERR_CN_LOSS_SOC) != 0)) { // loss of SoC event occured
+ // increment cumulative counter by 1
+ EplErrorHandlerkInstance_g.m_CnLossSoc.
+ m_dwCumulativeCnt++;
+ // increment threshold counter by 8
+ EplErrorHandlerkInstance_g.m_CnLossSoc.
+ m_dwThresholdCnt += 8;
+ if (EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThresholdCnt >= EplErrorHandlerkInstance_g.m_CnLossSoc.m_dwThreshold) { // threshold is reached
+ // $$$ d.k.: generate error history entry E_DLL_LOSS_SOC_TH
+
+ // post event to NMT state machine
+ NmtEvent = kEplNmtEventNmtCycleError;
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType =
+ kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Ret = EplEventkPost(&Event);
+ }
+ EplErrorHandlerkInstance_g.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_LOSS_SOC;
+ }
+
+ if ((EplErrorHandlerkInstance_g.m_CnLossPreq.
+ m_dwThreshold > 0)
+ && ((ulDllErrorEvents & EPL_DLL_ERR_CN_LOSS_PREQ) != 0)) { // loss of PReq event occured
+ // increment cumulative counter by 1
+ EplErrorHandlerkInstance_g.m_CnLossPreq.
+ m_dwCumulativeCnt++;
+ // increment threshold counter by 8
+ EplErrorHandlerkInstance_g.m_CnLossPreq.
+ m_dwThresholdCnt += 8;
+ if (EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThresholdCnt >= EplErrorHandlerkInstance_g.m_CnLossPreq.m_dwThreshold) { // threshold is reached
+ // $$$ d.k.: generate error history entry E_DLL_LOSS_PREQ_TH
+
+ // post event to NMT state machine
+ NmtEvent = kEplNmtEventNmtCycleError;
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType =
+ kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Ret = EplEventkPost(&Event);
+ }
+ }
+
+ if ((EplErrorHandlerkInstance_g.m_CnLossPreq.
+ m_dwThresholdCnt > 0)
+ && ((ulDllErrorEvents & EPL_DLL_ERR_CN_RECVD_PREQ) != 0)) { // PReq correctly received
+ // decrement threshold counter by 1
+ EplErrorHandlerkInstance_g.m_CnLossPreq.
+ m_dwThresholdCnt--;
+ }
+
+ if ((EplErrorHandlerkInstance_g.m_CnCrcErr.
+ m_dwThreshold > 0)
+ && ((ulDllErrorEvents & EPL_DLL_ERR_CN_CRC) != 0)) { // CRC error event occured
+ // increment cumulative counter by 1
+ EplErrorHandlerkInstance_g.m_CnCrcErr.
+ m_dwCumulativeCnt++;
+ // increment threshold counter by 8
+ EplErrorHandlerkInstance_g.m_CnCrcErr.
+ m_dwThresholdCnt += 8;
+ if (EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThresholdCnt >= EplErrorHandlerkInstance_g.m_CnCrcErr.m_dwThreshold) { // threshold is reached
+ // $$$ d.k.: generate error history entry E_DLL_CRC_TH
+
+ // post event to NMT state machine
+ NmtEvent = kEplNmtEventNmtCycleError;
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType =
+ kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Ret = EplEventkPost(&Event);
+ }
+ EplErrorHandlerkInstance_g.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_CN_CRC;
+ }
+
+ if ((ulDllErrorEvents & EPL_DLL_ERR_INVALID_FORMAT) != 0) { // invalid format error occured (only direct reaction)
+ // $$$ d.k.: generate error history entry E_DLL_INVALID_FORMAT
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (pErrHandlerEvent->m_NmtState >= kEplNmtMsNotActive) { // MN is active
+ if (pErrHandlerEvent->m_uiNodeId != 0) {
+ tEplHeartbeatEvent
+ HeartbeatEvent;
+
+ // remove node from isochronous phase
+ Ret =
+ EplDllkDeleteNode
+ (pErrHandlerEvent->
+ m_uiNodeId);
+
+ // inform NmtMnu module about state change, which shall send NMT command ResetNode to this CN
+ HeartbeatEvent.m_uiNodeId =
+ pErrHandlerEvent->
+ m_uiNodeId;
+ HeartbeatEvent.m_NmtState =
+ kEplNmtCsNotActive;
+ HeartbeatEvent.m_wErrorCode =
+ EPL_E_DLL_INVALID_FORMAT;
+ Event.m_EventSink =
+ kEplEventSinkNmtMnu;
+ Event.m_EventType =
+ kEplEventTypeHeartbeat;
+ Event.m_uiSize =
+ sizeof(HeartbeatEvent);
+ Event.m_pArg = &HeartbeatEvent;
+ Ret = EplEventkPost(&Event);
+ }
+ // $$$ and else should lead to InternComError
+ } else
+#endif
+ { // CN is active
+ // post event to NMT state machine
+ NmtEvent = kEplNmtEventInternComError;
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType =
+ kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Ret = EplEventkPost(&Event);
+ }
+ }
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if ((EplErrorHandlerkInstance_g.m_MnCrcErr.
+ m_dwThreshold > 0)
+ && ((ulDllErrorEvents & EPL_DLL_ERR_MN_CRC) != 0)) { // CRC error event occured
+ // increment cumulative counter by 1
+ EplErrorHandlerkInstance_g.m_MnCrcErr.
+ m_dwCumulativeCnt++;
+ // increment threshold counter by 8
+ EplErrorHandlerkInstance_g.m_MnCrcErr.
+ m_dwThresholdCnt += 8;
+ if (EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThresholdCnt >= EplErrorHandlerkInstance_g.m_MnCrcErr.m_dwThreshold) { // threshold is reached
+ // $$$ d.k.: generate error history entry E_DLL_CRC_TH
+
+ // post event to NMT state machine
+ NmtEvent = kEplNmtEventNmtCycleError;
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType =
+ kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Ret = EplEventkPost(&Event);
+ }
+ EplErrorHandlerkInstance_g.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_MN_CRC;
+ }
+
+ if ((EplErrorHandlerkInstance_g.m_MnCycTimeExceed.
+ m_dwThreshold > 0)
+ && ((ulDllErrorEvents & EPL_DLL_ERR_MN_CYCTIMEEXCEED) != 0)) { // cycle time exceeded event occured
+ // increment cumulative counter by 1
+ EplErrorHandlerkInstance_g.m_MnCycTimeExceed.
+ m_dwCumulativeCnt++;
+ // increment threshold counter by 8
+ EplErrorHandlerkInstance_g.m_MnCycTimeExceed.
+ m_dwThresholdCnt += 8;
+ if (EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThresholdCnt >= EplErrorHandlerkInstance_g.m_MnCycTimeExceed.m_dwThreshold) { // threshold is reached
+ // $$$ d.k.: generate error history entry E_DLL_CYCLE_EXCEED_TH
+
+ // post event to NMT state machine
+ NmtEvent = kEplNmtEventNmtCycleError;
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_EventType =
+ kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Ret = EplEventkPost(&Event);
+ }
+ // $$$ d.k.: else generate error history entry E_DLL_CYCLE_EXCEED
+ EplErrorHandlerkInstance_g.m_ulDllErrorEvents |=
+ EPL_DLL_ERR_MN_CYCTIMEEXCEED;
+ }
+
+ if ((ulDllErrorEvents & EPL_DLL_ERR_MN_CN_LOSS_PRES) != 0) { // CN loss PRes event occured
+ unsigned int uiNodeId;
+
+ uiNodeId = pErrHandlerEvent->m_uiNodeId - 1;
+ if ((uiNodeId <
+ tabentries(EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresCumCnt))
+ && (EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThreshold[uiNodeId] >
+ 0)) {
+ // increment cumulative counter by 1
+ EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresCumCnt[uiNodeId]++;
+ // increment threshold counter by 8
+ EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThrCnt[uiNodeId] +=
+ 8;
+ if (EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThrCnt[uiNodeId]
+ >= EplErrorHandlerkInstance_g.m_adwMnCnLossPresThreshold[uiNodeId]) { // threshold is reached
+ tEplHeartbeatEvent
+ HeartbeatEvent;
+
+ // $$$ d.k.: generate error history entry E_DLL_LOSS_PRES_TH
+
+ // remove node from isochronous phase
+ Ret =
+ EplDllkDeleteNode
+ (pErrHandlerEvent->
+ m_uiNodeId);
+
+ // inform NmtMnu module about state change, which shall send NMT command ResetNode to this CN
+ HeartbeatEvent.m_uiNodeId =
+ pErrHandlerEvent->
+ m_uiNodeId;
+ HeartbeatEvent.m_NmtState =
+ kEplNmtCsNotActive;
+ HeartbeatEvent.m_wErrorCode =
+ EPL_E_DLL_LOSS_PRES_TH;
+ Event.m_EventSink =
+ kEplEventSinkNmtMnu;
+ Event.m_EventType =
+ kEplEventTypeHeartbeat;
+ Event.m_uiSize =
+ sizeof(HeartbeatEvent);
+ Event.m_pArg = &HeartbeatEvent;
+ Ret = EplEventkPost(&Event);
+ }
+ EplErrorHandlerkInstance_g.
+ m_afMnCnLossPresEvent[uiNodeId] =
+ TRUE;
+ }
+ }
+#endif
+
+ break;
+ }
+
+ // NMT event
+ case kEplEventTypeNmtEvent:
+ {
+ if ((*(tEplNmtEvent *) pEvent_p->m_pArg) == kEplNmtEventDllCeSoa) { // SoA event of CN -> decrement threshold counters
+
+ if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_CN_LOSS_SOC) == 0) { // decrement loss of SoC threshold counter, because it didn't occur last cycle
+ if (EplErrorHandlerkInstance_g.
+ m_CnLossSoc.m_dwThresholdCnt > 0) {
+ EplErrorHandlerkInstance_g.
+ m_CnLossSoc.
+ m_dwThresholdCnt--;
+ }
+ }
+
+ if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_CN_CRC) == 0) { // decrement CRC threshold counter, because it didn't occur last cycle
+ if (EplErrorHandlerkInstance_g.
+ m_CnCrcErr.m_dwThresholdCnt > 0) {
+ EplErrorHandlerkInstance_g.
+ m_CnCrcErr.
+ m_dwThresholdCnt--;
+ }
+ }
+ }
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ else if ((*(tEplNmtEvent *) pEvent_p->m_pArg) == kEplNmtEventDllMeSoaSent) { // SoA event of MN -> decrement threshold counters
+ tEplDllkNodeInfo *pIntNodeInfo;
+ unsigned int uiNodeId;
+
+ Ret = EplDllkGetFirstNodeInfo(&pIntNodeInfo);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ // iterate through node info structure list
+ while (pIntNodeInfo != NULL) {
+ uiNodeId = pIntNodeInfo->m_uiNodeId - 1;
+ if (uiNodeId <
+ tabentries
+ (EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresCumCnt)) {
+ if (EplErrorHandlerkInstance_g.
+ m_afMnCnLossPresEvent
+ [uiNodeId] == FALSE) {
+ if (EplErrorHandlerkInstance_g.m_adwMnCnLossPresThrCnt[uiNodeId] > 0) {
+ EplErrorHandlerkInstance_g.
+ m_adwMnCnLossPresThrCnt
+ [uiNodeId]--;
+ }
+ } else {
+ EplErrorHandlerkInstance_g.
+ m_afMnCnLossPresEvent
+ [uiNodeId] = FALSE;
+ }
+ }
+ pIntNodeInfo =
+ pIntNodeInfo->m_pNextNodeInfo;
+ }
+
+ if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_MN_CRC) == 0) { // decrement CRC threshold counter, because it didn't occur last cycle
+ if (EplErrorHandlerkInstance_g.
+ m_MnCrcErr.m_dwThresholdCnt > 0) {
+ EplErrorHandlerkInstance_g.
+ m_MnCrcErr.
+ m_dwThresholdCnt--;
+ }
+ }
+
+ if ((EplErrorHandlerkInstance_g.m_ulDllErrorEvents & EPL_DLL_ERR_MN_CYCTIMEEXCEED) == 0) { // decrement cycle exceed threshold counter, because it didn't occur last cycle
+ if (EplErrorHandlerkInstance_g.
+ m_MnCycTimeExceed.m_dwThresholdCnt >
+ 0) {
+ EplErrorHandlerkInstance_g.
+ m_MnCycTimeExceed.
+ m_dwThresholdCnt--;
+ }
+ }
+ }
+#endif
+
+ // reset error events
+ EplErrorHandlerkInstance_g.m_ulDllErrorEvents = 0L;
+
+ break;
+ }
+
+ // unknown type
+ default:
+ {
+ }
+
+ } // end of switch(pEvent_p->m_EventType)
+
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplErrorHandlerkLinkErrorCounter
+//
+// Description: link specified error counter structure to OD entry
+//
+// Parameters: pErrorCounter_p = pointer to error counter structure
+// uiIndex_p = OD index
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplErrorHandlerkLinkErrorCounter(tEplErrorHandlerkErrorCounter
+ * pErrorCounter_p,
+ unsigned int uiIndex_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplVarParam VarParam;
+
+ VarParam.m_pData = &pErrorCounter_p->m_dwCumulativeCnt;
+ VarParam.m_Size = sizeof(DWORD);
+ VarParam.m_uiIndex = uiIndex_p;
+ VarParam.m_uiSubindex = 0x01;
+ VarParam.m_ValidFlag = kVarValidAll;
+ Ret = EplObdDefineVar(&VarParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ VarParam.m_pData = &pErrorCounter_p->m_dwThresholdCnt;
+ VarParam.m_Size = sizeof(DWORD);
+ VarParam.m_uiIndex = uiIndex_p;
+ VarParam.m_uiSubindex = 0x02;
+ VarParam.m_ValidFlag = kVarValidAll;
+ Ret = EplObdDefineVar(&VarParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ VarParam.m_pData = &pErrorCounter_p->m_dwThreshold;
+ VarParam.m_Size = sizeof(DWORD);
+ VarParam.m_uiIndex = uiIndex_p;
+ VarParam.m_uiSubindex = 0x03;
+ VarParam.m_ValidFlag = kVarValidAll;
+ Ret = EplObdDefineVar(&VarParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplErrorHandlerkLinkErrorCounter
+//
+// Description: link specified error counter structure to OD entry
+//
+// Parameters: pErrorCounter_p = pointer to error counter structure
+// uiIndex_p = OD index
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+static tEplKernel EplErrorHandlerkLinkArray(DWORD * pdwValue_p,
+ unsigned int uiValueCount_p,
+ unsigned int uiIndex_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplVarParam VarParam;
+ tEplObdSize EntrySize;
+ BYTE bIndexEntries;
+
+ EntrySize = (tEplObdSize) sizeof(bIndexEntries);
+ Ret = EplObdReadEntry(uiIndex_p,
+ 0x00, (void GENERIC *)&bIndexEntries, &EntrySize);
+
+ if ((Ret != kEplSuccessful) || (bIndexEntries == 0x00)) {
+ // Object doesn't exist or invalid entry number
+ Ret = kEplObdIndexNotExist;
+ goto Exit;
+ }
+
+ if (bIndexEntries < uiValueCount_p) {
+ uiValueCount_p = bIndexEntries;
+ }
+
+ VarParam.m_Size = sizeof(DWORD);
+ VarParam.m_uiIndex = uiIndex_p;
+ VarParam.m_ValidFlag = kVarValidAll;
+
+ for (VarParam.m_uiSubindex = 0x01;
+ VarParam.m_uiSubindex <= uiValueCount_p; VarParam.m_uiSubindex++) {
+ VarParam.m_pData = pdwValue_p;
+ Ret = EplObdDefineVar(&VarParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ pdwValue_p++;
+ }
+
+ Exit:
+ return Ret;
+}
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplEvent.h b/drivers/staging/epl/EplEvent.h
new file mode 100644
index 000000000000..b6dc1b9b2ab1
--- /dev/null
+++ b/drivers/staging/epl/EplEvent.h
@@ -0,0 +1,279 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for event module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplEvent.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/12 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_EVENT_H_
+#define _EPL_EVENT_H_
+
+#include "EplInc.h"
+#include "EplNmt.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// name and size of event queues
+#define EPL_EVENT_NAME_SHB_KERNEL_TO_USER "ShbKernelToUser"
+#ifndef EPL_EVENT_SIZE_SHB_KERNEL_TO_USER
+#define EPL_EVENT_SIZE_SHB_KERNEL_TO_USER 32768 // 32 kByte
+#endif
+
+#define EPL_EVENT_NAME_SHB_USER_TO_KERNEL "ShbUserToKernel"
+#ifndef EPL_EVENT_SIZE_SHB_USER_TO_KERNEL
+#define EPL_EVENT_SIZE_SHB_USER_TO_KERNEL 32768 // 32 kByte
+#endif
+
+// max size of event argument
+#ifndef EPL_MAX_EVENT_ARG_SIZE
+#define EPL_MAX_EVENT_ARG_SIZE 256 // because of PDO
+#endif
+
+#define EPL_DLL_ERR_MN_CRC 0x00000001L // object 0x1C00
+#define EPL_DLL_ERR_MN_COLLISION 0x00000002L // object 0x1C01
+#define EPL_DLL_ERR_MN_CYCTIMEEXCEED 0x00000004L // object 0x1C02
+#define EPL_DLL_ERR_MN_LOSS_LINK 0x00000008L // object 0x1C03
+#define EPL_DLL_ERR_MN_CN_LATE_PRES 0x00000010L // objects 0x1C04-0x1C06
+#define EPL_DLL_ERR_MN_CN_LOSS_PRES 0x00000080L // objects 0x1C07-0x1C09
+#define EPL_DLL_ERR_CN_COLLISION 0x00000400L // object 0x1C0A
+#define EPL_DLL_ERR_CN_LOSS_SOC 0x00000800L // object 0x1C0B
+#define EPL_DLL_ERR_CN_LOSS_SOA 0x00001000L // object 0x1C0C
+#define EPL_DLL_ERR_CN_LOSS_PREQ 0x00002000L // object 0x1C0D
+#define EPL_DLL_ERR_CN_RECVD_PREQ 0x00004000L // decrement object 0x1C0D/2
+#define EPL_DLL_ERR_CN_SOC_JITTER 0x00008000L // object 0x1C0E
+#define EPL_DLL_ERR_CN_CRC 0x00010000L // object 0x1C0F
+#define EPL_DLL_ERR_CN_LOSS_LINK 0x00020000L // object 0x1C10
+#define EPL_DLL_ERR_MN_LOSS_STATRES 0x00040000L // objects 0x1C15-0x1C17 (should be operated by NmtMnu module)
+#define EPL_DLL_ERR_BAD_PHYS_MODE 0x00080000L // no object
+#define EPL_DLL_ERR_MAC_BUFFER 0x00100000L // no object (NMT_GT6)
+#define EPL_DLL_ERR_INVALID_FORMAT 0x00200000L // no object (NMT_GT6)
+#define EPL_DLL_ERR_ADDRESS_CONFLICT 0x00400000L // no object (remove CN from configuration)
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+// EventType determines the argument of the event
+typedef enum {
+ kEplEventTypeNmtEvent = 0x01, // NMT event
+ // arg is pointer to tEplNmtEvent
+ kEplEventTypePdoRx = 0x02, // PDO frame received event (PRes/PReq)
+ // arg is pointer to tEplFrame
+ kEplEventTypePdoTx = 0x03, // PDO frame transmitted event (PRes/PReq)
+ // arg is pointer to tEplFrameInfo
+ kEplEventTypePdoSoa = 0x04, // SoA frame received event (isochronous phase completed)
+ // arg is pointer to nothing
+ kEplEventTypeSync = 0x05, // Sync event (e.g. SoC or anticipated SoC)
+ // arg is pointer to nothing
+ kEplEventTypeTimer = 0x06, // Timer event
+ // arg is pointer to tEplTimerEventArg
+ kEplEventTypeHeartbeat = 0x07, // Heartbeat event
+ // arg is pointer to tEplHeartbeatEvent
+ kEplEventTypeDllkCreate = 0x08, // DLL kernel create event
+ // arg is pointer to the new tEplNmtState
+ kEplEventTypeDllkDestroy = 0x09, // DLL kernel destroy event
+ // arg is pointer to the old tEplNmtState
+ kEplEventTypeDllkFillTx = 0x0A, // DLL kernel fill TxBuffer event
+ // arg is pointer to tEplDllAsyncReqPriority
+ kEplEventTypeDllkPresReady = 0x0B, // DLL kernel PRes ready event
+ // arg is pointer to nothing
+ kEplEventTypeError = 0x0C, // Error event for API layer
+ // arg is pointer to tEplEventError
+ kEplEventTypeNmtStateChange = 0x0D, // indicate change of NMT-State
+ // arg is pointer to tEplEventNmtStateChange
+ kEplEventTypeDllError = 0x0E, // DLL error event for Error handler
+ // arg is pointer to tEplErrorHandlerkEvent
+ kEplEventTypeAsndRx = 0x0F, // received ASnd frame for DLL user module
+ // arg is pointer to tEplFrame
+ kEplEventTypeDllkServFilter = 0x10, // configure ServiceIdFilter
+ // arg is pointer to tEplDllCalServiceIdFilter
+ kEplEventTypeDllkIdentity = 0x11, // configure Identity
+ // arg is pointer to tEplDllIdentParam
+ kEplEventTypeDllkConfig = 0x12, // configure ConfigParam
+ // arg is pointer to tEplDllConfigParam
+ kEplEventTypeDllkIssueReq = 0x13, // issue Ident/Status request
+ // arg is pointer to tEplDllCalIssueRequest
+ kEplEventTypeDllkAddNode = 0x14, // add node to isochronous phase
+ // arg is pointer to tEplDllNodeInfo
+ kEplEventTypeDllkDelNode = 0x15, // remove node from isochronous phase
+ // arg is pointer to unsigned int
+ kEplEventTypeDllkSoftDelNode = 0x16, // remove node softly from isochronous phase
+ // arg is pointer to unsigned int
+ kEplEventTypeDllkStartReducedCycle = 0x17, // start reduced EPL cycle on MN
+ // arg is pointer to nothing
+ kEplEventTypeNmtMnuNmtCmdSent = 0x18, // NMT command was actually sent
+ // arg is pointer to tEplFrame
+
+} tEplEventType;
+
+// EventSink determines the consumer of the event
+typedef enum {
+ kEplEventSinkSync = 0x00, // Sync event for application or kernel EPL module
+ kEplEventSinkNmtk = 0x01, // events for Nmtk module
+ kEplEventSinkDllk = 0x02, // events for Dllk module
+ kEplEventSinkDlluCal = 0x03, // events for DlluCal module
+ kEplEventSinkDllkCal = 0x04, // events for DllkCal module
+ kEplEventSinkPdok = 0x05, // events for Pdok module
+ kEplEventSinkNmtu = 0x06, // events for Nmtu module
+ kEplEventSinkErrk = 0x07, // events for Error handler module
+ kEplEventSinkErru = 0x08, // events for Error signaling module
+ kEplEventSinkSdoAsySeq = 0x09, // events for asyncronous SDO Sequence Layer module
+ kEplEventSinkNmtMnu = 0x0A, // events for NmtMnu module
+ kEplEventSinkLedu = 0x0B, // events for Ledu module
+ kEplEventSinkApi = 0x0F, // events for API module
+
+} tEplEventSink;
+
+// EventSource determines the source of an errorevent
+typedef enum {
+ // kernelspace modules
+ kEplEventSourceDllk = 0x01, // Dllk module
+ kEplEventSourceNmtk = 0x02, // Nmtk module
+ kEplEventSourceObdk = 0x03, // Obdk module
+ kEplEventSourcePdok = 0x04, // Pdok module
+ kEplEventSourceTimerk = 0x05, // Timerk module
+ kEplEventSourceEventk = 0x06, // Eventk module
+ kEplEventSourceSyncCb = 0x07, // sync-Cb
+ kEplEventSourceErrk = 0x08, // Error handler module
+
+ // userspace modules
+ kEplEventSourceDllu = 0x10, // Dllu module
+ kEplEventSourceNmtu = 0x11, // Nmtu module
+ kEplEventSourceNmtCnu = 0x12, // NmtCnu module
+ kEplEventSourceNmtMnu = 0x13, // NmtMnu module
+ kEplEventSourceObdu = 0x14, // Obdu module
+ kEplEventSourceSdoUdp = 0x15, // Sdo/Udp module
+ kEplEventSourceSdoAsnd = 0x16, // Sdo/Asnd module
+ kEplEventSourceSdoAsySeq = 0x17, // Sdo asynchronus Sequence Layer module
+ kEplEventSourceSdoCom = 0x18, // Sdo command layer module
+ kEplEventSourceTimeru = 0x19, // Timeru module
+ kEplEventSourceCfgMau = 0x1A, // CfgMau module
+ kEplEventSourceEventu = 0x1B, // Eventu module
+ kEplEventSourceEplApi = 0x1C, // Api module
+ kEplEventSourceLedu = 0x1D, // Ledu module
+
+} tEplEventSource;
+
+// structure of EPL event (element order must not be changed!)
+typedef struct {
+ tEplEventType m_EventType /*:28 */ ; // event type
+ tEplEventSink m_EventSink /*:4 */ ; // event sink
+ tEplNetTime m_NetTime; // timestamp
+ unsigned int m_uiSize; // size of argument
+ void *m_pArg; // argument of event
+
+} tEplEvent;
+
+// short structure of EPL event without argument and its size (element order must not be changed!)
+typedef struct {
+ tEplEventType m_EventType /*:28 */ ; // event type
+ tEplEventSink m_EventSink /*:4 */ ; // event sink
+ tEplNetTime m_NetTime; // timestamp
+
+} tEplEventShort;
+
+typedef struct {
+ unsigned int m_uiIndex;
+ unsigned int m_uiSubIndex;
+
+} tEplEventObdError;
+
+// structure for kEplEventTypeError
+typedef struct {
+ tEplEventSource m_EventSource; // module which posted this error event
+ tEplKernel m_EplError; // EPL error which occured
+ union {
+ BYTE m_bArg;
+ DWORD m_dwArg;
+ tEplEventSource m_EventSource; // from Eventk/u module (originating error source)
+ tEplEventObdError m_ObdError; // from Obd module
+// tEplErrHistoryEntry m_HistoryEntry; // from Nmtk/u module
+
+ } m_Arg;
+
+} tEplEventError;
+
+// structure for kEplEventTypeDllError
+typedef struct {
+ unsigned long m_ulDllErrorEvents; // EPL_DLL_ERR_*
+ unsigned int m_uiNodeId;
+ tEplNmtState m_NmtState;
+
+} tEplErrorHandlerkEvent;
+
+// callback function to get informed about sync event
+typedef tEplKernel(PUBLIC * tEplSyncCb) (void);
+
+// callback function for generic events
+typedef tEplKernel(PUBLIC * tEplProcessEventCb) (tEplEvent * pEplEvent_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_EVENT_H_
diff --git a/drivers/staging/epl/EplEventk.c b/drivers/staging/epl/EplEventk.c
new file mode 100644
index 000000000000..8068a6c5a0d0
--- /dev/null
+++ b/drivers/staging/epl/EplEventk.c
@@ -0,0 +1,853 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for Epl-Kernelspace-Event-Modul
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplEventk.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.9 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/20 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "kernel/EplEventk.h"
+#include "kernel/EplNmtk.h"
+#include "kernel/EplDllk.h"
+#include "kernel/EplDllkCal.h"
+#include "kernel/EplErrorHandlerk.h"
+#include "Benchmark.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+#include "kernel/EplPdok.h"
+#include "kernel/EplPdokCal.h"
+#endif
+
+#ifdef EPL_NO_FIFO
+#include "user/EplEventu.h"
+#else
+#include "SharedBuff.h"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#define TGT_DBG_POST_TRACE_VALUE(v)
+#endif
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+#ifndef EPL_NO_FIFO
+ tShbInstance m_pShbKernelToUserInstance;
+ tShbInstance m_pShbUserToKernelInstance;
+#else
+
+#endif
+ tEplSyncCb m_pfnCbSync;
+ unsigned int m_uiUserToKernelFullCount;
+
+} tEplEventkInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+static tEplEventkInstance EplEventkInstance_g;
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+// callback function for incoming events
+#ifndef EPL_NO_FIFO
+static void EplEventkRxSignalHandlerCb(tShbInstance pShbRxInstance_p,
+ unsigned long ulDataSize_p);
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <Epl-Kernelspace-Event> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventkInit
+//
+// Description: function initializes the first instance
+//
+// Parameters: pfnCbSync_p = callback-function for sync event
+//
+// Returns: tEpKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplEventkInit(tEplSyncCb pfnCbSync_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplEventkAddInstance(pfnCbSync_p);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventkAddInstance
+//
+// Description: function adds one more instance
+//
+// Parameters: pfnCbSync_p = callback-function for sync event
+//
+// Returns: tEpKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplEventkAddInstance(tEplSyncCb pfnCbSync_p)
+{
+ tEplKernel Ret;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+ unsigned int fShbNewCreated;
+#endif
+
+ Ret = kEplSuccessful;
+
+ // init instance structure
+ EplEventkInstance_g.m_uiUserToKernelFullCount = 0;
+
+ // save cb-function
+ EplEventkInstance_g.m_pfnCbSync = pfnCbSync_p;
+
+#ifndef EPL_NO_FIFO
+ // init shared loop buffer
+ // kernel -> user
+ ShbError = ShbCirAllocBuffer(EPL_EVENT_SIZE_SHB_KERNEL_TO_USER,
+ EPL_EVENT_NAME_SHB_KERNEL_TO_USER,
+ &EplEventkInstance_g.
+ m_pShbKernelToUserInstance,
+ &fShbNewCreated);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkAddInstance(): ShbCirAllocBuffer(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+ // user -> kernel
+ ShbError = ShbCirAllocBuffer(EPL_EVENT_SIZE_SHB_USER_TO_KERNEL,
+ EPL_EVENT_NAME_SHB_USER_TO_KERNEL,
+ &EplEventkInstance_g.
+ m_pShbUserToKernelInstance,
+ &fShbNewCreated);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkAddInstance(): ShbCirAllocBuffer(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+ // register eventhandler
+ ShbError =
+ ShbCirSetSignalHandlerNewData(EplEventkInstance_g.
+ m_pShbUserToKernelInstance,
+ EplEventkRxSignalHandlerCb,
+ kshbPriorityHigh);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkAddInstance(): ShbCirSetSignalHandlerNewData(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ Exit:
+#endif
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventkDelInstance
+//
+// Description: function deletes instance and frees the buffers
+//
+// Parameters: void
+//
+// Returns: tEpKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplEventkDelInstance()
+{
+ tEplKernel Ret;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+#endif
+
+ Ret = kEplSuccessful;
+
+#ifndef EPL_NO_FIFO
+ // set eventhandler to NULL
+ ShbError =
+ ShbCirSetSignalHandlerNewData(EplEventkInstance_g.
+ m_pShbUserToKernelInstance, NULL,
+ kShbPriorityNormal);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkDelInstance(): ShbCirSetSignalHandlerNewData(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ }
+ // free buffer User -> Kernel
+ ShbError =
+ ShbCirReleaseBuffer(EplEventkInstance_g.m_pShbUserToKernelInstance);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkDelInstance(): ShbCirReleaseBuffer(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ } else {
+ EplEventkInstance_g.m_pShbUserToKernelInstance = NULL;
+ }
+
+ // free buffer Kernel -> User
+ ShbError =
+ ShbCirReleaseBuffer(EplEventkInstance_g.m_pShbKernelToUserInstance);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkDelInstance(): ShbCirReleaseBuffer(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ } else {
+ EplEventkInstance_g.m_pShbKernelToUserInstance = NULL;
+ }
+#endif
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventkProcess
+//
+// Description: Kernelthread that dispatches events in kernel part
+//
+// Parameters: pEvent_p = pointer to event-structure from buffer
+//
+// Returns: tEpKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplEventkProcess(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+ tEplEventSource EventSource;
+
+ Ret = kEplSuccessful;
+
+ // error handling if event queue is full
+ if (EplEventkInstance_g.m_uiUserToKernelFullCount > 0) { // UserToKernel event queue has run out of space -> kEplNmtEventInternComError
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+ tEplEvent Event;
+ tEplNmtEvent NmtEvent;
+#endif
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+#endif
+
+ // directly call NMTk process function, because event queue is full
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+ NmtEvent = kEplNmtEventInternComError;
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_NetTime.m_dwNanoSec = 0;
+ Event.m_NetTime.m_dwSec = 0;
+ Event.m_EventType = kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent;
+ Event.m_uiSize = sizeof(NmtEvent);
+ Ret = EplNmtkProcess(&Event);
+#endif
+
+ // NMT state machine changed to reset (i.e. NMT_GS_RESET_COMMUNICATION)
+ // now, it is safe to reset the counter and empty the event queue
+#ifndef EPL_NO_FIFO
+ ShbError =
+ ShbCirResetBuffer(EplEventkInstance_g.
+ m_pShbUserToKernelInstance, 1000, NULL);
+#endif
+
+ EplEventkInstance_g.m_uiUserToKernelFullCount = 0;
+ TGT_DBG_SIGNAL_TRACE_POINT(22);
+
+ // also discard the current event (it doesn't matter if we lose another event)
+ goto Exit;
+ }
+ // check m_EventSink
+ switch (pEvent_p->m_EventSink) {
+ case kEplEventSinkSync:
+ {
+ if (EplEventkInstance_g.m_pfnCbSync != NULL) {
+ Ret = EplEventkInstance_g.m_pfnCbSync();
+ if (Ret == kEplSuccessful) {
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ // mark TPDOs as valid
+ Ret = EplPdokCalSetTpdosValid(TRUE);
+#endif
+ } else if ((Ret != kEplReject)
+ && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceSyncCb;
+
+ // Error event for API layer
+ EplEventkPostError
+ (kEplEventSourceEventk, Ret,
+ sizeof(EventSource), &EventSource);
+ }
+ }
+ break;
+ }
+
+ // NMT-Kernel-Modul
+ case kEplEventSinkNmtk:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+ Ret = EplNmtkProcess(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceNmtk;
+
+ // Error event for API layer
+ EplEventkPostError(kEplEventSourceEventk,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+#endif
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ if ((pEvent_p->m_EventType == kEplEventTypeNmtEvent)
+ &&
+ ((*((tEplNmtEvent *) pEvent_p->m_pArg) ==
+ kEplNmtEventDllCeSoa)
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ || (*((tEplNmtEvent *) pEvent_p->m_pArg) ==
+ kEplNmtEventDllMeSoaSent)
+#endif
+ )) { // forward SoA event to error handler
+ Ret = EplErrorHandlerkProcess(pEvent_p);
+ if ((Ret != kEplSuccessful)
+ && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceErrk;
+
+ // Error event for API layer
+ EplEventkPostError
+ (kEplEventSourceEventk, Ret,
+ sizeof(EventSource), &EventSource);
+ }
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ // forward SoA event to PDO module
+ pEvent_p->m_EventType = kEplEventTypePdoSoa;
+ Ret = EplPdokProcess(pEvent_p);
+ if ((Ret != kEplSuccessful)
+ && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourcePdok;
+
+ // Error event for API layer
+ EplEventkPostError
+ (kEplEventSourceEventk, Ret,
+ sizeof(EventSource), &EventSource);
+ }
+#endif
+
+ }
+ break;
+#endif
+ }
+
+ // events for Dllk module
+ case kEplEventSinkDllk:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ Ret = EplDllkProcess(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceDllk;
+
+ // Error event for API layer
+ EplEventkPostError(kEplEventSourceEventk,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+#endif
+ break;
+ }
+
+ // events for DllkCal module
+ case kEplEventSinkDllkCal:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ Ret = EplDllkCalProcess(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceDllk;
+
+ // Error event for API layer
+ EplEventkPostError(kEplEventSourceEventk,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+#endif
+ break;
+ }
+
+ //
+ case kEplEventSinkPdok:
+ {
+ // PDO-Module
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+ Ret = EplPdokProcess(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourcePdok;
+
+ // Error event for API layer
+ EplEventkPostError(kEplEventSourceEventk,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+#endif
+ break;
+ }
+
+ // events for Error handler module
+ case kEplEventSinkErrk:
+ {
+ // only call error handler if DLL is present
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ Ret = EplErrorHandlerkProcess(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceErrk;
+
+ // Error event for API layer
+ EplEventkPostError(kEplEventSourceEventk,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+ break;
+#endif
+ }
+
+ // unknown sink
+ default:
+ {
+ Ret = kEplEventUnknownSink;
+ }
+
+ } // end of switch(pEvent_p->m_EventSink)
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventkPost
+//
+// Description: post events from kernel part
+//
+// Parameters: pEvent_p = pointer to event-structure from buffer
+//
+// Returns: tEpKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplEventkPost(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+ tShbCirChunk ShbCirChunk;
+ unsigned long ulDataSize;
+ unsigned int fBufferCompleted;
+#endif
+
+ Ret = kEplSuccessful;
+
+ // the event must be posted by using the abBuffer
+ // it is neede because the Argument must by copied
+ // to the buffer too and not only the pointer
+
+#ifndef EPL_NO_FIFO
+ // 2006/08/03 d.k.: Event and argument are posted as separate chunks to the event queue.
+ ulDataSize =
+ sizeof(tEplEvent) +
+ ((pEvent_p->m_pArg != NULL) ? pEvent_p->m_uiSize : 0);
+#endif
+
+ // decide in which buffer the event have to write
+ switch (pEvent_p->m_EventSink) {
+ // kernelspace modules
+ case kEplEventSinkSync:
+ case kEplEventSinkNmtk:
+ case kEplEventSinkDllk:
+ case kEplEventSinkDllkCal:
+ case kEplEventSinkPdok:
+ case kEplEventSinkErrk:
+ {
+#ifndef EPL_NO_FIFO
+ // post message
+ BENCHMARK_MOD_27_SET(2);
+ ShbError =
+ ShbCirAllocDataBlock(EplEventkInstance_g.
+ m_pShbUserToKernelInstance,
+ &ShbCirChunk, ulDataSize);
+ switch (ShbError) {
+ case kShbOk:
+ break;
+
+ case kShbBufferFull:
+ {
+ EplEventkInstance_g.
+ m_uiUserToKernelFullCount++;
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+
+ default:
+ {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkPost(): ShbCirAllocDataBlock(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ }
+ ShbError =
+ ShbCirWriteDataChunk(EplEventkInstance_g.
+ m_pShbUserToKernelInstance,
+ &ShbCirChunk, pEvent_p,
+ sizeof(tEplEvent),
+ &fBufferCompleted);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkPost(): ShbCirWriteDataChunk(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ if (fBufferCompleted == FALSE) {
+ ShbError =
+ ShbCirWriteDataChunk(EplEventkInstance_g.
+ m_pShbUserToKernelInstance,
+ &ShbCirChunk,
+ pEvent_p->m_pArg,
+ (unsigned long)
+ pEvent_p->m_uiSize,
+ &fBufferCompleted);
+ if ((ShbError != kShbOk)
+ || (fBufferCompleted == FALSE)) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkPost(): ShbCirWriteDataChunk2(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ }
+ BENCHMARK_MOD_27_RESET(2);
+
+#else
+ Ret = EplEventkProcess(pEvent_p);
+#endif
+
+ break;
+ }
+
+ // userspace modules
+ case kEplEventSinkNmtu:
+ case kEplEventSinkNmtMnu:
+ case kEplEventSinkSdoAsySeq:
+ case kEplEventSinkApi:
+ case kEplEventSinkDlluCal:
+ case kEplEventSinkErru:
+ {
+#ifndef EPL_NO_FIFO
+ // post message
+// BENCHMARK_MOD_27_SET(3); // 74 s until reset
+ ShbError =
+ ShbCirAllocDataBlock(EplEventkInstance_g.
+ m_pShbKernelToUserInstance,
+ &ShbCirChunk, ulDataSize);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkPost(): ShbCirAllocDataBlock(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ ShbError =
+ ShbCirWriteDataChunk(EplEventkInstance_g.
+ m_pShbKernelToUserInstance,
+ &ShbCirChunk, pEvent_p,
+ sizeof(tEplEvent),
+ &fBufferCompleted);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkPost(): ShbCirWriteDataChunk(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ if (fBufferCompleted == FALSE) {
+ ShbError =
+ ShbCirWriteDataChunk(EplEventkInstance_g.
+ m_pShbKernelToUserInstance,
+ &ShbCirChunk,
+ pEvent_p->m_pArg,
+ (unsigned long)
+ pEvent_p->m_uiSize,
+ &fBufferCompleted);
+ if ((ShbError != kShbOk)
+ || (fBufferCompleted == FALSE)) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventkPost(): ShbCirWriteDataChunk2(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ }
+// BENCHMARK_MOD_27_RESET(3); // 82 s until ShbCirGetReadDataSize() in EplEventu
+
+#else
+ Ret = EplEventuProcess(pEvent_p);
+#endif
+
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplEventUnknownSink;
+ }
+
+ } // end of switch(pEvent_p->m_EventSink)
+
+#ifndef EPL_NO_FIFO
+ Exit:
+#endif
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventkPostError
+//
+// Description: post error event from kernel part to API layer
+//
+// Parameters: EventSource_p = source-module of the error event
+// EplError_p = code of occured error
+// ArgSize_p = size of the argument
+// pArg_p = pointer to the argument
+//
+// Returns: tEpKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplEventkPostError(tEplEventSource EventSource_p,
+ tEplKernel EplError_p,
+ unsigned int uiArgSize_p, void *pArg_p)
+{
+ tEplKernel Ret;
+ BYTE abBuffer[EPL_MAX_EVENT_ARG_SIZE];
+ tEplEventError *pEventError = (tEplEventError *) abBuffer;
+ tEplEvent EplEvent;
+
+ Ret = kEplSuccessful;
+
+ // create argument
+ pEventError->m_EventSource = EventSource_p;
+ pEventError->m_EplError = EplError_p;
+ EPL_MEMCPY(&pEventError->m_Arg, pArg_p, uiArgSize_p);
+
+ // create event
+ EplEvent.m_EventType = kEplEventTypeError;
+ EplEvent.m_EventSink = kEplEventSinkApi;
+ EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(EplEvent.m_NetTime));
+ EplEvent.m_uiSize =
+ (sizeof(EventSource_p) + sizeof(EplError_p) + uiArgSize_p);
+ EplEvent.m_pArg = &abBuffer[0];
+
+ // post errorevent
+ Ret = EplEventkPost(&EplEvent);
+
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventkRxSignalHandlerCb()
+//
+// Description: Callback-function for events from user and kernel part
+//
+// Parameters: pShbRxInstance_p = Instance-pointer of buffer
+// ulDataSize_p = size of data
+//
+// Returns: void
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#ifndef EPL_NO_FIFO
+static void EplEventkRxSignalHandlerCb(tShbInstance pShbRxInstance_p,
+ unsigned long ulDataSize_p)
+{
+ tEplEvent *pEplEvent;
+ tShbError ShbError;
+//unsigned long ulBlockCount;
+//unsigned long ulDataSize;
+ BYTE abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE];
+ // d.k.: abDataBuffer contains the complete tEplEvent structure
+ // and behind this the argument
+
+ TGT_DBG_SIGNAL_TRACE_POINT(20);
+
+ BENCHMARK_MOD_27_RESET(0);
+ // copy data from event queue
+ ShbError = ShbCirReadDataBlock(pShbRxInstance_p,
+ &abDataBuffer[0],
+ sizeof(abDataBuffer), &ulDataSize_p);
+ if (ShbError != kShbOk) {
+ // error goto exit
+ goto Exit;
+ }
+ // resolve the pointer to the event structure
+ pEplEvent = (tEplEvent *) abDataBuffer;
+ // set Datasize
+ pEplEvent->m_uiSize = (ulDataSize_p - sizeof(tEplEvent));
+ if (pEplEvent->m_uiSize > 0) {
+ // set pointer to argument
+ pEplEvent->m_pArg = &abDataBuffer[sizeof(tEplEvent)];
+ } else {
+ //set pointer to NULL
+ pEplEvent->m_pArg = NULL;
+ }
+
+ BENCHMARK_MOD_27_SET(0);
+ // call processfunction
+ EplEventkProcess(pEplEvent);
+
+ Exit:
+ return;
+}
+#endif
+
+// EOF
diff --git a/drivers/staging/epl/EplEventu.c b/drivers/staging/epl/EplEventu.c
new file mode 100644
index 000000000000..815f9a87abf8
--- /dev/null
+++ b/drivers/staging/epl/EplEventu.c
@@ -0,0 +1,814 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for Epl-Userspace-Event-Modul
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplEventu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/20 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplEventu.h"
+#include "user/EplNmtu.h"
+#include "user/EplNmtMnu.h"
+#include "user/EplSdoAsySequ.h"
+#include "user/EplDlluCal.h"
+#include "user/EplLedu.h"
+#include "Benchmark.h"
+
+#ifdef EPL_NO_FIFO
+#include "kernel/EplEventk.h"
+#else
+#include "SharedBuff.h"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#define TGT_DBG_POST_TRACE_VALUE(v)
+#endif
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+#ifndef EPL_NO_FIFO
+ tShbInstance m_pShbKernelToUserInstance;
+ tShbInstance m_pShbUserToKernelInstance;
+#endif
+ tEplProcessEventCb m_pfnApiProcessEventCb;
+
+} tEplEventuInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//#ifndef EPL_NO_FIFO
+static tEplEventuInstance EplEventuInstance_g;
+//#endif
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+#ifndef EPL_NO_FIFO
+// callback function for incomming events
+static void EplEventuRxSignalHandlerCb(tShbInstance pShbRxInstance_p,
+ unsigned long ulDataSize_p);
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <Epl-User-Event> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventuInit
+//
+// Description: function initialize the first instance
+//
+//
+//
+// Parameters: pfnApiProcessEventCb_p = function pointer for API event callback
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplEventuAddInstance(pfnApiProcessEventCb_p);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventuAddInstance
+//
+// Description: function add one more instance
+//
+//
+//
+// Parameters: pfnApiProcessEventCb_p = function pointer for API event callback
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplEventuAddInstance(tEplProcessEventCb
+ pfnApiProcessEventCb_p)
+{
+ tEplKernel Ret;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+ unsigned int fShbNewCreated;
+#endif
+
+ Ret = kEplSuccessful;
+
+ // init instance variables
+ EplEventuInstance_g.m_pfnApiProcessEventCb = pfnApiProcessEventCb_p;
+
+#ifndef EPL_NO_FIFO
+ // init shared loop buffer
+ // kernel -> user
+ ShbError = ShbCirAllocBuffer(EPL_EVENT_SIZE_SHB_KERNEL_TO_USER,
+ EPL_EVENT_NAME_SHB_KERNEL_TO_USER,
+ &EplEventuInstance_g.
+ m_pShbKernelToUserInstance,
+ &fShbNewCreated);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuAddInstance(): ShbCirAllocBuffer(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ // user -> kernel
+ ShbError = ShbCirAllocBuffer(EPL_EVENT_SIZE_SHB_USER_TO_KERNEL,
+ EPL_EVENT_NAME_SHB_USER_TO_KERNEL,
+ &EplEventuInstance_g.
+ m_pShbUserToKernelInstance,
+ &fShbNewCreated);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuAddInstance(): ShbCirAllocBuffer(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+ // register eventhandler
+ ShbError =
+ ShbCirSetSignalHandlerNewData(EplEventuInstance_g.
+ m_pShbKernelToUserInstance,
+ EplEventuRxSignalHandlerCb,
+ kShbPriorityNormal);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuAddInstance(): ShbCirSetSignalHandlerNewData(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ Exit:
+#endif
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventuDelInstance
+//
+// Description: function delete instance an free the bufferstructure
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplEventuDelInstance()
+{
+ tEplKernel Ret;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+#endif
+
+ Ret = kEplSuccessful;
+
+#ifndef EPL_NO_FIFO
+ // set eventhandler to NULL
+ ShbError =
+ ShbCirSetSignalHandlerNewData(EplEventuInstance_g.
+ m_pShbKernelToUserInstance, NULL,
+ kShbPriorityNormal);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuDelInstance(): ShbCirSetSignalHandlerNewData(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ }
+ // free buffer User -> Kernel
+ ShbError =
+ ShbCirReleaseBuffer(EplEventuInstance_g.m_pShbUserToKernelInstance);
+ if ((ShbError != kShbOk) && (ShbError != kShbMemUsedByOtherProcs)) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuDelInstance(): ShbCirReleaseBuffer(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ } else {
+ EplEventuInstance_g.m_pShbUserToKernelInstance = NULL;
+ }
+
+ // free buffer Kernel -> User
+ ShbError =
+ ShbCirReleaseBuffer(EplEventuInstance_g.m_pShbKernelToUserInstance);
+ if ((ShbError != kShbOk) && (ShbError != kShbMemUsedByOtherProcs)) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuDelInstance(): ShbCirReleaseBuffer(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplNoResource;
+ } else {
+ EplEventuInstance_g.m_pShbKernelToUserInstance = NULL;
+ }
+
+#endif
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventuProcess
+//
+// Description: Kernelthread that dispatches events in kernelspace
+//
+//
+//
+// Parameters: pEvent_p = pointer to event-structur from buffer
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplEventuProcess(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+ tEplEventSource EventSource;
+
+ Ret = kEplSuccessful;
+
+ // check m_EventSink
+ switch (pEvent_p->m_EventSink) {
+ // NMT-User-Module
+ case kEplEventSinkNmtu:
+ {
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret = EplNmtuProcessEvent(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceNmtu;
+
+ // Error event for API layer
+ EplEventuPostError(kEplEventSourceEventu,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+#endif
+ break;
+ }
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // NMT-MN-User-Module
+ case kEplEventSinkNmtMnu:
+ {
+ Ret = EplNmtMnuProcessEvent(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceNmtMnu;
+
+ // Error event for API layer
+ EplEventuPostError(kEplEventSourceEventu,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+ break;
+ }
+#endif
+
+#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0) \
+ || (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0))
+ // events for asynchronus SDO Sequence Layer
+ case kEplEventSinkSdoAsySeq:
+ {
+ Ret = EplSdoAsySeqProcessEvent(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceSdoAsySeq;
+
+ // Error event for API layer
+ EplEventuPostError(kEplEventSourceEventu,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+ break;
+ }
+#endif
+
+ // LED user part module
+ case kEplEventSinkLedu:
+ {
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+ Ret = EplLeduProcessEvent(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceLedu;
+
+ // Error event for API layer
+ EplEventuPostError(kEplEventSourceEventu,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+#endif
+ break;
+ }
+
+ // event for EPL api
+ case kEplEventSinkApi:
+ {
+ if (EplEventuInstance_g.m_pfnApiProcessEventCb != NULL) {
+ Ret =
+ EplEventuInstance_g.
+ m_pfnApiProcessEventCb(pEvent_p);
+ if ((Ret != kEplSuccessful)
+ && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceEplApi;
+
+ // Error event for API layer
+ EplEventuPostError
+ (kEplEventSourceEventu, Ret,
+ sizeof(EventSource), &EventSource);
+ }
+ }
+ break;
+
+ }
+
+ case kEplEventSinkDlluCal:
+ {
+ Ret = EplDlluCalProcess(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) {
+ EventSource = kEplEventSourceDllu;
+
+ // Error event for API layer
+ EplEventuPostError(kEplEventSourceEventu,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+ break;
+
+ }
+
+ case kEplEventSinkErru:
+ {
+ /*
+ Ret = EplErruProcess(pEvent_p);
+ if ((Ret != kEplSuccessful) && (Ret != kEplShutdown))
+ {
+ EventSource = kEplEventSourceErru;
+
+ // Error event for API layer
+ EplEventuPostError(kEplEventSourceEventu,
+ Ret,
+ sizeof(EventSource),
+ &EventSource);
+ }
+ */
+ break;
+
+ }
+
+ // unknown sink
+ default:
+ {
+ Ret = kEplEventUnknownSink;
+ }
+
+ } // end of switch(pEvent_p->m_EventSink)
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventuPost
+//
+// Description: post events from userspace
+//
+//
+//
+// Parameters: pEvent_p = pointer to event-structur from buffer
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplEventuPost(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+#ifndef EPL_NO_FIFO
+ tShbError ShbError;
+ tShbCirChunk ShbCirChunk;
+ unsigned long ulDataSize;
+ unsigned int fBufferCompleted;
+#endif
+
+ Ret = kEplSuccessful;
+
+#ifndef EPL_NO_FIFO
+ // 2006/08/03 d.k.: Event and argument are posted as separate chunks to the event queue.
+ ulDataSize =
+ sizeof(tEplEvent) +
+ ((pEvent_p->m_pArg != NULL) ? pEvent_p->m_uiSize : 0);
+#endif
+
+ // decide in which buffer the event have to write
+ switch (pEvent_p->m_EventSink) {
+ // kernelspace modules
+ case kEplEventSinkSync:
+ case kEplEventSinkNmtk:
+ case kEplEventSinkDllk:
+ case kEplEventSinkDllkCal:
+ case kEplEventSinkPdok:
+ case kEplEventSinkErrk:
+ {
+#ifndef EPL_NO_FIFO
+ // post message
+ ShbError =
+ ShbCirAllocDataBlock(EplEventuInstance_g.
+ m_pShbUserToKernelInstance,
+ &ShbCirChunk, ulDataSize);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuPost(): ShbCirAllocDataBlock(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ ShbError =
+ ShbCirWriteDataChunk(EplEventuInstance_g.
+ m_pShbUserToKernelInstance,
+ &ShbCirChunk, pEvent_p,
+ sizeof(tEplEvent),
+ &fBufferCompleted);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuPost(): ShbCirWriteDataChunk(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ if (fBufferCompleted == FALSE) {
+ ShbError =
+ ShbCirWriteDataChunk(EplEventuInstance_g.
+ m_pShbUserToKernelInstance,
+ &ShbCirChunk,
+ pEvent_p->m_pArg,
+ (unsigned long)
+ pEvent_p->m_uiSize,
+ &fBufferCompleted);
+ if ((ShbError != kShbOk)
+ || (fBufferCompleted == FALSE)) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuPost(): ShbCirWriteDataChunk2(U2K) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ }
+#else
+ Ret = EplEventkProcess(pEvent_p);
+#endif
+
+ break;
+ }
+
+ // userspace modules
+ case kEplEventSinkNmtMnu:
+ case kEplEventSinkNmtu:
+ case kEplEventSinkSdoAsySeq:
+ case kEplEventSinkApi:
+ case kEplEventSinkDlluCal:
+ case kEplEventSinkErru:
+ case kEplEventSinkLedu:
+ {
+#ifndef EPL_NO_FIFO
+ // post message
+ ShbError =
+ ShbCirAllocDataBlock(EplEventuInstance_g.
+ m_pShbKernelToUserInstance,
+ &ShbCirChunk, ulDataSize);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuPost(): ShbCirAllocDataBlock(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ ShbError =
+ ShbCirWriteDataChunk(EplEventuInstance_g.
+ m_pShbKernelToUserInstance,
+ &ShbCirChunk, pEvent_p,
+ sizeof(tEplEvent),
+ &fBufferCompleted);
+ if (ShbError != kShbOk) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuPost(): ShbCirWriteDataChunk(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ if (fBufferCompleted == FALSE) {
+ ShbError =
+ ShbCirWriteDataChunk(EplEventuInstance_g.
+ m_pShbKernelToUserInstance,
+ &ShbCirChunk,
+ pEvent_p->m_pArg,
+ (unsigned long)
+ pEvent_p->m_uiSize,
+ &fBufferCompleted);
+ if ((ShbError != kShbOk)
+ || (fBufferCompleted == FALSE)) {
+ EPL_DBGLVL_EVENTK_TRACE1
+ ("EplEventuPost(): ShbCirWriteDataChunk2(K2U) -> 0x%X\n",
+ ShbError);
+ Ret = kEplEventPostError;
+ goto Exit;
+ }
+ }
+#else
+ Ret = EplEventuProcess(pEvent_p);
+#endif
+
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplEventUnknownSink;
+ }
+
+ } // end of switch(pEvent_p->m_EventSink)
+
+#ifndef EPL_NO_FIFO
+ Exit:
+#endif
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventuPostError
+//
+// Description: post errorevent from userspace
+//
+//
+//
+// Parameters: EventSource_p = source-module of the errorevent
+// EplError_p = code of occured error
+// uiArgSize_p = size of the argument
+// pArg_p = pointer to the argument
+//
+//
+// Returns: tEpKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplEventuPostError(tEplEventSource EventSource_p,
+ tEplKernel EplError_p,
+ unsigned int uiArgSize_p, void *pArg_p)
+{
+ tEplKernel Ret;
+ BYTE abBuffer[EPL_MAX_EVENT_ARG_SIZE];
+ tEplEventError *pEventError = (tEplEventError *) abBuffer;
+ tEplEvent EplEvent;
+
+ Ret = kEplSuccessful;
+
+ // create argument
+ pEventError->m_EventSource = EventSource_p;
+ pEventError->m_EplError = EplError_p;
+ EPL_MEMCPY(&pEventError->m_Arg, pArg_p, uiArgSize_p);
+
+ // create event
+ EplEvent.m_EventType = kEplEventTypeError;
+ EplEvent.m_EventSink = kEplEventSinkApi;
+ EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(EplEvent.m_NetTime));
+ EplEvent.m_uiSize =
+ (sizeof(EventSource_p) + sizeof(EplError_p) + uiArgSize_p);
+ EplEvent.m_pArg = &abBuffer[0];
+
+ // post errorevent
+ Ret = EplEventuPost(&EplEvent);
+
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEventuRxSignalHandlerCb()
+//
+// Description: Callback-function for evets from kernelspace
+//
+//
+//
+// Parameters: pShbRxInstance_p = Instance-pointer for buffer
+// ulDataSize_p = size of data
+//
+//
+// Returns: void
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#ifndef EPL_NO_FIFO
+static void EplEventuRxSignalHandlerCb(tShbInstance pShbRxInstance_p,
+ unsigned long ulDataSize_p)
+{
+ tEplEvent *pEplEvent;
+ tShbError ShbError;
+//unsigned long ulBlockCount;
+//unsigned long ulDataSize;
+ BYTE abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE];
+ // d.k.: abDataBuffer contains the complete tEplEvent structure
+ // and behind this the argument
+
+ TGT_DBG_SIGNAL_TRACE_POINT(21);
+
+// d.k. not needed because it is already done in SharedBuff
+/* do
+ {
+ BENCHMARK_MOD_28_SET(1); // 4 s until reset
+ // get messagesize
+ ShbError = ShbCirGetReadDataSize (pShbRxInstance_p, &ulDataSize);
+ if(ShbError != kShbOk)
+ {
+ // error goto exit
+ goto Exit;
+ }
+
+ BENCHMARK_MOD_28_RESET(1); // 14 s until set
+*/
+ // copy data from event queue
+ ShbError = ShbCirReadDataBlock(pShbRxInstance_p,
+ &abDataBuffer[0],
+ sizeof(abDataBuffer), &ulDataSize_p);
+ if (ShbError != kShbOk) {
+ // error goto exit
+ goto Exit;
+ }
+ // resolve the pointer to the event structure
+ pEplEvent = (tEplEvent *) abDataBuffer;
+ // set Datasize
+ pEplEvent->m_uiSize = (ulDataSize_p - sizeof(tEplEvent));
+ if (pEplEvent->m_uiSize > 0) {
+ // set pointer to argument
+ pEplEvent->m_pArg = &abDataBuffer[sizeof(tEplEvent)];
+ } else {
+ //set pointer to NULL
+ pEplEvent->m_pArg = NULL;
+ }
+
+ BENCHMARK_MOD_28_SET(1);
+ // call processfunction
+ EplEventuProcess(pEplEvent);
+
+ BENCHMARK_MOD_28_RESET(1);
+ // read number of left messages to process
+// d.k. not needed because it is already done in SharedBuff
+/* ShbError = ShbCirGetReadBlockCount (pShbRxInstance_p, &ulBlockCount);
+ if (ShbError != kShbOk)
+ {
+ // error goto exit
+ goto Exit;
+ }
+ } while (ulBlockCount > 0);
+*/
+ Exit:
+ return;
+}
+#endif
+
+// EOF
diff --git a/drivers/staging/epl/EplFrame.h b/drivers/staging/epl/EplFrame.h
new file mode 100644
index 000000000000..9a7f8b9f594e
--- /dev/null
+++ b/drivers/staging/epl/EplFrame.h
@@ -0,0 +1,344 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for EPL frames
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplFrame.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/06/23 14:56:33 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_FRAME_H_
+#define _EPL_FRAME_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// defines for EplFrame.m_wFlag
+#define EPL_FRAME_FLAG1_RD 0x01 // ready (PReq, PRes)
+#define EPL_FRAME_FLAG1_ER 0x02 // exception reset (error signalling) (SoA)
+#define EPL_FRAME_FLAG1_EA 0x04 // exception acknowledge (error signalling) (PReq, SoA)
+#define EPL_FRAME_FLAG1_EC 0x08 // exception clear (error signalling) (StatusRes)
+#define EPL_FRAME_FLAG1_EN 0x10 // exception new (error signalling) (PRes, StatusRes)
+#define EPL_FRAME_FLAG1_MS 0x20 // multiplexed slot (PReq)
+#define EPL_FRAME_FLAG1_PS 0x40 // prescaled slot (SoC)
+#define EPL_FRAME_FLAG1_MC 0x80 // multiplexed cycle completed (SoC)
+#define EPL_FRAME_FLAG2_RS 0x07 // number of pending requests to send (PRes, StatusRes, IdentRes)
+#define EPL_FRAME_FLAG2_PR 0x38 // priority of requested asynch. frame (PRes, StatusRes, IdentRes)
+#define EPL_FRAME_FLAG2_PR_SHIFT 3 // shift of priority of requested asynch. frame
+
+// error history/status entry types
+#define EPL_ERR_ENTRYTYPE_STATUS 0x8000
+#define EPL_ERR_ENTRYTYPE_HISTORY 0x0000
+#define EPL_ERR_ENTRYTYPE_EMCY 0x4000
+#define EPL_ERR_ENTRYTYPE_MODE_ACTIVE 0x1000
+#define EPL_ERR_ENTRYTYPE_MODE_CLEARED 0x2000
+#define EPL_ERR_ENTRYTYPE_MODE_OCCURRED 0x3000
+#define EPL_ERR_ENTRYTYPE_MODE_MASK 0x3000
+#define EPL_ERR_ENTRYTYPE_PROF_VENDOR 0x0001
+#define EPL_ERR_ENTRYTYPE_PROF_EPL 0x0002
+#define EPL_ERR_ENTRYTYPE_PROF_MASK 0x0FFF
+
+// defines for EPL version / PDO version
+#define EPL_VERSION_SUB 0x0F // sub version
+#define EPL_VERSION_MAIN 0xF0 // main version
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+// $$$ d.k.: move this definition to global.h
+// byte-align structures
+#ifdef _MSC_VER
+# pragma pack( push, packing )
+# pragma pack( 1 )
+# define PACK_STRUCT
+#elif defined( __GNUC__ )
+# define PACK_STRUCT __attribute__((packed))
+#else
+# error you must byte-align these structures with the appropriate compiler directives
+#endif
+
+typedef struct {
+ // Offset 17
+ BYTE m_le_bRes1; // reserved
+ // Offset 18
+ BYTE m_le_bFlag1; // Flags: MC, PS
+ // Offset 19
+ BYTE m_le_bFlag2; // Flags: res
+ // Offset 20
+ tEplNetTime m_le_NetTime; // supported if D_NMT_NetTimeIsRealTime_BOOL is set
+ // Offset 28
+ QWORD m_le_RelativeTime; // in us (supported if D_NMT_RelativeTime_BOOL is set)
+
+} PACK_STRUCT tEplSocFrame;
+
+typedef struct {
+ // Offset 17
+ BYTE m_le_bRes1; // reserved
+ // Offset 18
+ BYTE m_le_bFlag1; // Flags: MS, EA, RD
+ // Offset 19
+ BYTE m_le_bFlag2; // Flags: res
+ // Offset 20
+ BYTE m_le_bPdoVersion;
+ // Offset 21
+ BYTE m_le_bRes2; // reserved
+ // Offset 22
+ WORD m_le_wSize;
+ // Offset 24
+ BYTE m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16 */ ];
+
+} PACK_STRUCT tEplPreqFrame;
+
+typedef struct {
+ // Offset 17
+ BYTE m_le_bNmtStatus; // NMT state
+ // Offset 18
+ BYTE m_le_bFlag1; // Flags: MS, EN, RD
+ // Offset 19
+ BYTE m_le_bFlag2; // Flags: PR, RS
+ // Offset 20
+ BYTE m_le_bPdoVersion;
+ // Offset 21
+ BYTE m_le_bRes2; // reserved
+ // Offset 22
+ WORD m_le_wSize;
+ // Offset 24
+ BYTE m_le_abPayload[256 /*D_NMT_IsochrRxMaxPayload_U16
+ / D_NMT_IsochrTxMaxPayload_U16 */ ];
+
+} PACK_STRUCT tEplPresFrame;
+
+typedef struct {
+ // Offset 17
+ BYTE m_le_bNmtStatus; // NMT state
+ // Offset 18
+ BYTE m_le_bFlag1; // Flags: EA, ER
+ // Offset 19
+ BYTE m_le_bFlag2; // Flags: res
+ // Offset 20
+ BYTE m_le_bReqServiceId;
+ // Offset 21
+ BYTE m_le_bReqServiceTarget;
+ // Offset 22
+ BYTE m_le_bEplVersion;
+
+} PACK_STRUCT tEplSoaFrame;
+
+typedef struct {
+ WORD m_wEntryType;
+ WORD m_wErrorCode;
+ tEplNetTime m_TimeStamp;
+ BYTE m_abAddInfo[8];
+
+} PACK_STRUCT tEplErrHistoryEntry;
+
+typedef struct {
+ // Offset 18
+ BYTE m_le_bFlag1; // Flags: EN, EC
+ BYTE m_le_bFlag2; // Flags: PR, RS
+ BYTE m_le_bNmtStatus; // NMT state
+ BYTE m_le_bRes1[3];
+ QWORD m_le_qwStaticError; // static error bit field
+ tEplErrHistoryEntry m_le_aErrHistoryEntry[14];
+
+} PACK_STRUCT tEplStatusResponse;
+
+typedef struct {
+ // Offset 18
+ BYTE m_le_bFlag1; // Flags: res
+ BYTE m_le_bFlag2; // Flags: PR, RS
+ BYTE m_le_bNmtStatus; // NMT state
+ BYTE m_le_bIdentRespFlags; // Flags: FW
+ BYTE m_le_bEplProfileVersion;
+ BYTE m_le_bRes1;
+ DWORD m_le_dwFeatureFlags; // NMT_FeatureFlags_U32
+ WORD m_le_wMtu; // NMT_CycleTiming_REC.AsyncMTU_U16: C_IP_MIN_MTU - C_IP_MAX_MTU
+ WORD m_le_wPollInSize; // NMT_CycleTiming_REC.PReqActPayload_U16
+ WORD m_le_wPollOutSize; // NMT_CycleTiming_REC.PResActPayload_U16
+ DWORD m_le_dwResponseTime; // NMT_CycleTiming_REC.PResMaxLatency_U32
+ WORD m_le_wRes2;
+ DWORD m_le_dwDeviceType; // NMT_DeviceType_U32
+ DWORD m_le_dwVendorId; // NMT_IdentityObject_REC.VendorId_U32
+ DWORD m_le_dwProductCode; // NMT_IdentityObject_REC.ProductCode_U32
+ DWORD m_le_dwRevisionNumber; // NMT_IdentityObject_REC.RevisionNo_U32
+ DWORD m_le_dwSerialNumber; // NMT_IdentityObject_REC.SerialNo_U32
+ QWORD m_le_qwVendorSpecificExt1;
+ DWORD m_le_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
+ DWORD m_le_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
+ DWORD m_le_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
+ DWORD m_le_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
+ DWORD m_le_dwIpAddress;
+ DWORD m_le_dwSubnetMask;
+ DWORD m_le_dwDefaultGateway;
+ BYTE m_le_sHostname[32];
+ BYTE m_le_abVendorSpecificExt2[48];
+
+} PACK_STRUCT tEplIdentResponse;
+
+typedef struct {
+ // Offset 18
+ BYTE m_le_bNmtCommandId;
+ BYTE m_le_bRes1;
+ BYTE m_le_abNmtCommandData[32];
+
+} PACK_STRUCT tEplNmtCommandService;
+
+typedef struct {
+ BYTE m_le_bReserved;
+ BYTE m_le_bTransactionId;
+ BYTE m_le_bFlags;
+ BYTE m_le_bCommandId;
+ WORD m_le_wSegmentSize;
+ WORD m_le_wReserved;
+ BYTE m_le_abCommandData[8]; // just reserve a minimum number of bytes as a placeholder
+
+} PACK_STRUCT tEplAsySdoCom;
+
+// asynchronous SDO Sequence Header
+typedef struct {
+ BYTE m_le_bRecSeqNumCon;
+ BYTE m_le_bSendSeqNumCon;
+ BYTE m_le_abReserved[2];
+ tEplAsySdoCom m_le_abSdoSeqPayload;
+
+} PACK_STRUCT tEplAsySdoSeq;
+
+typedef struct {
+ // Offset 18
+ BYTE m_le_bNmtCommandId;
+ BYTE m_le_bTargetNodeId;
+ BYTE m_le_abNmtCommandData[32];
+
+} PACK_STRUCT tEplNmtRequestService;
+
+typedef union {
+ // Offset 18
+ tEplStatusResponse m_StatusResponse;
+ tEplIdentResponse m_IdentResponse;
+ tEplNmtCommandService m_NmtCommandService;
+ tEplNmtRequestService m_NmtRequestService;
+ tEplAsySdoSeq m_SdoSequenceFrame;
+ BYTE m_le_abPayload[256 /*D_NMT_ASndTxMaxPayload_U16
+ / D_NMT_ASndRxMaxPayload_U16 */ ];
+
+} tEplAsndPayload;
+
+typedef struct {
+ // Offset 17
+ BYTE m_le_bServiceId;
+ // Offset 18
+ tEplAsndPayload m_Payload;
+
+} PACK_STRUCT tEplAsndFrame;
+
+typedef union {
+ // Offset 17
+ tEplSocFrame m_Soc;
+ tEplPreqFrame m_Preq;
+ tEplPresFrame m_Pres;
+ tEplSoaFrame m_Soa;
+ tEplAsndFrame m_Asnd;
+
+} tEplFrameData;
+
+typedef struct {
+ // Offset 0
+ BYTE m_be_abDstMac[6]; // MAC address of the addressed nodes
+ // Offset 6
+ BYTE m_be_abSrcMac[6]; // MAC address of the transmitting node
+ // Offset 12
+ WORD m_be_wEtherType; // Ethernet message type (big endian)
+ // Offset 14
+ BYTE m_le_bMessageType; // EPL message type
+ // Offset 15
+ BYTE m_le_bDstNodeId; // EPL node ID of the addressed nodes
+ // Offset 16
+ BYTE m_le_bSrcNodeId; // EPL node ID of the transmitting node
+ // Offset 17
+ tEplFrameData m_Data;
+
+} PACK_STRUCT tEplFrame;
+
+// un-byte-align structures
+#ifdef _MSC_VER
+# pragma pack( pop, packing )
+#endif
+
+typedef enum {
+ kEplMsgTypeNonEpl = 0x00,
+ kEplMsgTypeSoc = 0x01,
+ kEplMsgTypePreq = 0x03,
+ kEplMsgTypePres = 0x04,
+ kEplMsgTypeSoa = 0x05,
+ kEplMsgTypeAsnd = 0x06,
+
+} tEplMsgType;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_FRAME_H_
diff --git a/drivers/staging/epl/EplIdentu.c b/drivers/staging/epl/EplIdentu.c
new file mode 100644
index 000000000000..ce59ef09ccdf
--- /dev/null
+++ b/drivers/staging/epl/EplIdentu.c
@@ -0,0 +1,488 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for Identu-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplIdentu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/11/21 09:00:38 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/11/15 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplIdentu.h"
+#include "user/EplDlluCal.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <xxxxx> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ tEplIdentResponse *m_apIdentResponse[254]; // the IdentResponse are managed dynamically
+ tEplIdentuCbResponse m_apfnCbResponse[254];
+
+} tEplIdentuInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+static tEplIdentuInstance EplIdentuInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplIdentuCbIdentResponse(tEplFrameInfo * pFrameInfo_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuInit
+//
+// Description: init first instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplIdentuInit()
+{
+ tEplKernel Ret;
+
+ Ret = EplIdentuAddInstance();
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuAddInstance
+//
+// Description: init other instances of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplIdentuAddInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // reset instance structure
+ EPL_MEMSET(&EplIdentuInstance_g, 0, sizeof(EplIdentuInstance_g));
+
+ // register IdentResponse callback function
+ Ret =
+ EplDlluCalRegAsndService(kEplDllAsndIdentResponse,
+ EplIdentuCbIdentResponse,
+ kEplDllAsndFilterAny);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuDelInstance
+//
+// Description: delete instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplIdentuDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // deregister IdentResponse callback function
+ Ret =
+ EplDlluCalRegAsndService(kEplDllAsndIdentResponse, NULL,
+ kEplDllAsndFilterNone);
+
+ Ret = EplIdentuReset();
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuReset
+//
+// Description: resets this instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplIdentuReset()
+{
+ tEplKernel Ret;
+ int iIndex;
+
+ Ret = kEplSuccessful;
+
+ for (iIndex = 0;
+ iIndex < tabentries(EplIdentuInstance_g.m_apIdentResponse);
+ iIndex++) {
+ if (EplIdentuInstance_g.m_apIdentResponse[iIndex] != NULL) { // free memory
+ EPL_FREE(EplIdentuInstance_g.m_apIdentResponse[iIndex]);
+ }
+ }
+
+ EPL_MEMSET(&EplIdentuInstance_g, 0, sizeof(EplIdentuInstance_g));
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuGetIdentResponse
+//
+// Description: returns the IdentResponse for the specified node.
+//
+// Parameters: uiNodeId_p = IN: node ID
+// ppIdentResponse_p = OUT: pointer to pointer of IdentResponse
+// equals NULL, if no IdentResponse available
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplIdentuGetIdentResponse(unsigned int uiNodeId_p,
+ tEplIdentResponse **
+ ppIdentResponse_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // decrement node ID, because array is zero based
+ uiNodeId_p--;
+ if (uiNodeId_p < tabentries(EplIdentuInstance_g.m_apIdentResponse)) {
+ *ppIdentResponse_p =
+ EplIdentuInstance_g.m_apIdentResponse[uiNodeId_p];
+ } else { // invalid node ID specified
+ *ppIdentResponse_p = NULL;
+ Ret = kEplInvalidNodeId;
+ }
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuRequestIdentResponse
+//
+// Description: returns the IdentResponse for the specified node.
+//
+// Parameters: uiNodeId_p = IN: node ID
+// pfnCbResponse_p = IN: function pointer to callback function
+// which will be called if IdentResponse is received
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplIdentuRequestIdentResponse(unsigned int uiNodeId_p,
+ tEplIdentuCbResponse
+ pfnCbResponse_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // decrement node ID, because array is zero based
+ uiNodeId_p--;
+ if (uiNodeId_p < tabentries(EplIdentuInstance_g.m_apfnCbResponse)) {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (EplIdentuInstance_g.m_apfnCbResponse[uiNodeId_p] != NULL) { // request already issued (maybe by someone else)
+ Ret = kEplInvalidOperation;
+ } else {
+ EplIdentuInstance_g.m_apfnCbResponse[uiNodeId_p] =
+ pfnCbResponse_p;
+ Ret =
+ EplDlluCalIssueRequest(kEplDllReqServiceIdent,
+ (uiNodeId_p + 1), 0xFF);
+ }
+#else
+ Ret = kEplInvalidOperation;
+#endif
+ } else { // invalid node ID specified
+ Ret = kEplInvalidNodeId;
+ }
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuGetRunningRequests
+//
+// Description: returns a bit field with the running requests for node-ID 1-32
+// just for debugging purposes
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void)
+{
+ DWORD dwReqs = 0;
+ unsigned int uiIndex;
+
+ for (uiIndex = 0; uiIndex < 32; uiIndex++) {
+ if (EplIdentuInstance_g.m_apfnCbResponse[uiIndex] != NULL) {
+ dwReqs |= (1 << uiIndex);
+ }
+ }
+
+ return dwReqs;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplIdentuCbIdentResponse
+//
+// Description: callback funktion for IdentResponse
+//
+//
+//
+// Parameters: pFrameInfo_p = Frame with the IdentResponse
+//
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplIdentuCbIdentResponse(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiNodeId;
+ unsigned int uiIndex;
+ tEplIdentuCbResponse pfnCbResponse;
+
+ uiNodeId = AmiGetByteFromLe(&pFrameInfo_p->m_pFrame->m_le_bSrcNodeId);
+
+ uiIndex = uiNodeId - 1;
+
+ if (uiIndex < tabentries(EplIdentuInstance_g.m_apfnCbResponse)) {
+ // memorize pointer to callback function
+ pfnCbResponse = EplIdentuInstance_g.m_apfnCbResponse[uiIndex];
+ // reset callback function pointer so that caller may issue next request immediately
+ EplIdentuInstance_g.m_apfnCbResponse[uiIndex] = NULL;
+
+ if (pFrameInfo_p->m_uiFrameSize < EPL_C_DLL_MINSIZE_IDENTRES) { // IdentResponse not received or it has invalid size
+ if (pfnCbResponse == NULL) { // response was not requested
+ goto Exit;
+ }
+ Ret = pfnCbResponse(uiNodeId, NULL);
+ } else { // IdentResponse received
+ if (EplIdentuInstance_g.m_apIdentResponse[uiIndex] == NULL) { // memory for IdentResponse must be allocated
+ EplIdentuInstance_g.m_apIdentResponse[uiIndex] =
+ EPL_MALLOC(sizeof(tEplIdentResponse));
+ if (EplIdentuInstance_g.m_apIdentResponse[uiIndex] == NULL) { // malloc failed
+ if (pfnCbResponse == NULL) { // response was not requested
+ goto Exit;
+ }
+ Ret =
+ pfnCbResponse(uiNodeId,
+ &pFrameInfo_p->
+ m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_IdentResponse);
+ goto Exit;
+ }
+ }
+ // copy IdentResponse to instance structure
+ EPL_MEMCPY(EplIdentuInstance_g.
+ m_apIdentResponse[uiIndex],
+ &pFrameInfo_p->m_pFrame->m_Data.m_Asnd.
+ m_Payload.m_IdentResponse,
+ sizeof(tEplIdentResponse));
+ if (pfnCbResponse == NULL) { // response was not requested
+ goto Exit;
+ }
+ Ret =
+ pfnCbResponse(uiNodeId,
+ EplIdentuInstance_g.
+ m_apIdentResponse[uiIndex]);
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+// EOF
diff --git a/drivers/staging/epl/EplInc.h b/drivers/staging/epl/EplInc.h
new file mode 100644
index 000000000000..77f93d144166
--- /dev/null
+++ b/drivers/staging/epl/EplInc.h
@@ -0,0 +1,385 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: basic include file for internal EPL stack modules
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplInc.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/11/17 16:40:39 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_INC_H_
+#define _EPL_INC_H_
+
+// ============================================================================
+// include files
+// ============================================================================
+#if defined(WIN32) || defined(_WIN32)
+
+#ifdef UNDER_RTSS
+ // RTX header
+#include <windows.h>
+#include <process.h>
+#include <rtapi.h>
+
+#elif __BORLANDC__
+ // borland C header
+#include <windows.h>
+#include <process.h>
+
+#elif WINCE
+#include <windows.h>
+
+#else
+ // MSVC needs to include windows.h at first
+ // the following defines ar necessary for function prototypes for waitable timers
+#define _WIN32_WINDOWS 0x0401
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <process.h>
+#endif
+
+#endif
+
+// defines for module integration
+// possible other include file needed
+// These constants defines modules which can be included in the Epl application.
+// Use this constants for define EPL_MODULE_INTEGRATION in file EplCfg.h.
+#define EPL_MODULE_OBDK 0x00000001L // OBD kernel part module
+#define EPL_MODULE_PDOK 0x00000002L // PDO kernel part module
+#define EPL_MODULE_NMT_MN 0x00000004L // NMT MN module
+#define EPL_MODULE_SDOS 0x00000008L // SDO Server module
+#define EPL_MODULE_SDOC 0x00000010L // SDO Client module
+#define EPL_MODULE_SDO_ASND 0x00000020L // SDO over Asnd module
+#define EPL_MODULE_SDO_UDP 0x00000040L // SDO over UDP module
+#define EPL_MODULE_SDO_PDO 0x00000080L // SDO in PDO module
+#define EPL_MODULE_NMT_CN 0x00000100L // NMT CN module
+#define EPL_MODULE_NMTU 0x00000200L // NMT user part module
+#define EPL_MODULE_NMTK 0x00000400L // NMT kernel part module
+#define EPL_MODULE_DLLK 0x00000800L // DLL kernel part module
+#define EPL_MODULE_DLLU 0x00001000L // DLL user part module
+#define EPL_MODULE_OBDU 0x00002000L // OBD user part module
+#define EPL_MODULE_CFGMA 0x00004000L // Configuartioan Manager module
+#define EPL_MODULE_VETH 0x00008000L // virtual ethernet driver module
+#define EPL_MODULE_PDOU 0x00010000L // PDO user part module
+#define EPL_MODULE_LEDU 0x00020000L // LED user part module
+
+#include "EplCfg.h" // EPL configuration file (configuration from application)
+
+#include "global.h" // global definitions
+
+#include "EplDef.h" // EPL configuration file (default configuration)
+#include "EplInstDef.h" // defines macros for instance types and table
+#include "Debug.h" // debug definitions
+
+#include "EplErrDef.h" // EPL error codes for API funtions
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+// IEEE 1588 conformant net time structure
+typedef struct {
+ DWORD m_dwSec;
+ DWORD m_dwNanoSec;
+
+} tEplNetTime;
+
+#include "EplTarget.h" // target specific functions and definitions
+
+#include "EplAmi.h"
+
+// -------------------------------------------------------------------------
+// macros
+// -------------------------------------------------------------------------
+
+#define EPL_SPEC_VERSION 0x20 // ETHERNET Powerlink V. 2.0
+#define EPL_STACK_VERSION(ver,rev,rel) ((((DWORD)(ver)) & 0xFF)|((((DWORD)(rev))&0xFF)<<8)|(((DWORD)(rel))<<16))
+#define EPL_OBJ1018_VERSION(ver,rev,rel) ((((DWORD)(ver))<<16) |(((DWORD)(rev))&0xFFFF))
+#define EPL_STRING_VERSION(ver,rev,rel) "V" #ver "." #rev " r" #rel
+
+#include "EplVersion.h"
+
+// defines for EPL FeatureFlags
+#define EPL_FEATURE_ISOCHR 0x00000001
+#define EPL_FEATURE_SDO_UDP 0x00000002
+#define EPL_FEATURE_SDO_ASND 0x00000004
+#define EPL_FEATURE_SDO_PDO 0x00000008
+#define EPL_FEATURE_NMT_INFO 0x00000010
+#define EPL_FEATURE_NMT_EXT 0x00000020
+#define EPL_FEATURE_PDO_DYN 0x00000040
+#define EPL_FEATURE_NMT_UDP 0x00000080
+#define EPL_FEATURE_CFGMA 0x00000100
+#define EPL_FEATURE_DLL_MULTIPLEX 0x00000200
+#define EPL_FEATURE_NODEID_SW 0x00000400
+#define EPL_FEATURE_NMT_BASICETH 0x00000800
+#define EPL_FEATURE_RT1 0x00001000
+#define EPL_FEATURE_RT2 0x00002000
+
+// generate EPL NMT_FeatureFlags_U32
+#ifndef EPL_DEF_FEATURE_ISOCHR
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+#define EPL_DEF_FEATURE_ISOCHR (EPL_FEATURE_ISOCHR)
+#else
+#define EPL_DEF_FEATURE_ISOCHR 0
+#endif
+#endif
+
+#ifndef EPL_DEF_FEATURE_SDO_ASND
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+#define EPL_DEF_FEATURE_SDO_ASND (EPL_FEATURE_SDO_ASND)
+#else
+#define EPL_DEF_FEATURE_SDO_ASND 0
+#endif
+#endif
+
+#ifndef EPL_DEF_FEATURE_SDO_UDP
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+#define EPL_DEF_FEATURE_SDO_UDP (EPL_FEATURE_SDO_UDP)
+#else
+#define EPL_DEF_FEATURE_SDO_UDP 0
+#endif
+#endif
+
+#ifndef EPL_DEF_FEATURE_SDO_PDO
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_PDO)) != 0)
+#define EPL_DEF_FEATURE_SDO_PDO (EPL_FEATURE_SDO_PDO)
+#else
+#define EPL_DEF_FEATURE_SDO_PDO 0
+#endif
+#endif
+
+#ifndef EPL_DEF_FEATURE_PDO_DYN
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+#define EPL_DEF_FEATURE_PDO_DYN (EPL_FEATURE_PDO_DYN)
+#else
+#define EPL_DEF_FEATURE_PDO_DYN 0
+#endif
+#endif
+
+#ifndef EPL_DEF_FEATURE_CFGMA
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0)
+#define EPL_DEF_FEATURE_CFGMA (EPL_FEATURE_CFGMA)
+#else
+#define EPL_DEF_FEATURE_CFGMA 0
+#endif
+#endif
+
+#define EPL_DEF_FEATURE_FLAGS (EPL_DEF_FEATURE_ISOCHR \
+ | EPL_DEF_FEATURE_SDO_ASND \
+ | EPL_DEF_FEATURE_SDO_UDP \
+ | EPL_DEF_FEATURE_SDO_PDO \
+ | EPL_DEF_FEATURE_PDO_DYN \
+ | EPL_DEF_FEATURE_CFGMA)
+
+#ifndef tabentries
+#define tabentries(a) (sizeof(a)/sizeof(*(a)))
+#endif
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// definitions for DLL export
+#if ((DEV_SYSTEM == _DEV_WIN32_) || (DEV_SYSTEM == _DEV_WIN_CE_)) && defined (COP_LIB)
+
+#define EPLDLLEXPORT __declspec (dllexport)
+
+#else
+
+#define EPLDLLEXPORT
+
+#endif
+
+// ============================================================================
+// common debug macros
+// ============================================================================
+// for using macro DEBUG_TRACEx()
+//
+// Example:
+// DEBUG_TRACE1 (EPL_DBGLVL_OBD, "Value is %d\n" , wObjectIndex);
+//
+// This message only will be printed if:
+// - NDEBUG is not defined AND !!!
+// - flag 0x00000004L is set in DEF_DEBUG_LVL (can be defined in copcfg.h)
+//
+// default level is defined in copdef.h
+
+// debug-level and TRACE-macros // standard-level // flags for DEF_DEBUG_LVL
+#define EPL_DBGLVL_EDRV DEBUG_LVL_01 // 0x00000001L
+#define EPL_DBGLVL_EDRV_TRACE0 DEBUG_LVL_01_TRACE0
+#define EPL_DBGLVL_EDRV_TRACE1 DEBUG_LVL_01_TRACE1
+#define EPL_DBGLVL_EDRV_TRACE2 DEBUG_LVL_01_TRACE2
+#define EPL_DBGLVL_EDRV_TRACE3 DEBUG_LVL_01_TRACE3
+#define EPL_DBGLVL_EDRV_TRACE4 DEBUG_LVL_01_TRACE4
+
+#define EPL_DBGLVL_DLL DEBUG_LVL_02 // 0x00000002L
+#define EPL_DBGLVL_DLL_TRACE0 DEBUG_LVL_02_TRACE0
+#define EPL_DBGLVL_DLL_TRACE1 DEBUG_LVL_02_TRACE1
+#define EPL_DBGLVL_DLL_TRACE2 DEBUG_LVL_02_TRACE2
+#define EPL_DBGLVL_DLL_TRACE3 DEBUG_LVL_02_TRACE3
+#define EPL_DBGLVL_DLL_TRACE4 DEBUG_LVL_02_TRACE4
+
+#define EPL_DBGLVL_OBD DEBUG_LVL_03 // 0x00000004L
+#define EPL_DBGLVL_OBD_TRACE0 DEBUG_LVL_03_TRACE0
+#define EPL_DBGLVL_OBD_TRACE1 DEBUG_LVL_03_TRACE1
+#define EPL_DBGLVL_OBD_TRACE2 DEBUG_LVL_03_TRACE2
+#define EPL_DBGLVL_OBD_TRACE3 DEBUG_LVL_03_TRACE3
+#define EPL_DBGLVL_OBD_TRACE4 DEBUG_LVL_03_TRACE4
+
+#define EPL_DBGLVL_NMTK DEBUG_LVL_04 // 0x00000008L
+#define EPL_DBGLVL_NMTK_TRACE0 DEBUG_LVL_04_TRACE0
+#define EPL_DBGLVL_NMTK_TRACE1 DEBUG_LVL_04_TRACE1
+#define EPL_DBGLVL_NMTK_TRACE2 DEBUG_LVL_04_TRACE2
+#define EPL_DBGLVL_NMTK_TRACE3 DEBUG_LVL_04_TRACE3
+#define EPL_DBGLVL_NMTK_TRACE4 DEBUG_LVL_04_TRACE4
+
+#define EPL_DBGLVL_NMTCN DEBUG_LVL_05 // 0x00000010L
+#define EPL_DBGLVL_NMTCN_TRACE0 DEBUG_LVL_05_TRACE0
+#define EPL_DBGLVL_NMTCN_TRACE1 DEBUG_LVL_05_TRACE1
+#define EPL_DBGLVL_NMTCN_TRACE2 DEBUG_LVL_05_TRACE2
+#define EPL_DBGLVL_NMTCN_TRACE3 DEBUG_LVL_05_TRACE3
+#define EPL_DBGLVL_NMTCN_TRACE4 DEBUG_LVL_05_TRACE4
+
+#define EPL_DBGLVL_NMTU DEBUG_LVL_06 // 0x00000020L
+#define EPL_DBGLVL_NMTU_TRACE0 DEBUG_LVL_06_TRACE0
+#define EPL_DBGLVL_NMTU_TRACE1 DEBUG_LVL_06_TRACE1
+#define EPL_DBGLVL_NMTU_TRACE2 DEBUG_LVL_06_TRACE2
+#define EPL_DBGLVL_NMTU_TRACE3 DEBUG_LVL_06_TRACE3
+#define EPL_DBGLVL_NMTU_TRACE4 DEBUG_LVL_06_TRACE4
+
+#define EPL_DBGLVL_NMTMN DEBUG_LVL_07 // 0x00000040L
+#define EPL_DBGLVL_NMTMN_TRACE0 DEBUG_LVL_07_TRACE0
+#define EPL_DBGLVL_NMTMN_TRACE1 DEBUG_LVL_07_TRACE1
+#define EPL_DBGLVL_NMTMN_TRACE2 DEBUG_LVL_07_TRACE2
+#define EPL_DBGLVL_NMTMN_TRACE3 DEBUG_LVL_07_TRACE3
+#define EPL_DBGLVL_NMTMN_TRACE4 DEBUG_LVL_07_TRACE4
+
+//...
+
+#define EPL_DBGLVL_SDO DEBUG_LVL_25 // 0x01000000
+#define EPL_DBGLVL_SDO_TRACE0 DEBUG_LVL_25_TRACE0
+#define EPL_DBGLVL_SDO_TRACE1 DEBUG_LVL_25_TRACE1
+#define EPL_DBGLVL_SDO_TRACE2 DEBUG_LVL_25_TRACE2
+#define EPL_DBGLVL_SDO_TRACE3 DEBUG_LVL_25_TRACE3
+#define EPL_DBGLVL_SDO_TRACE4 DEBUG_LVL_25_TRACE4
+
+#define EPL_DBGLVL_VETH DEBUG_LVL_26 // 0x02000000
+#define EPL_DBGLVL_VETH_TRACE0 DEBUG_LVL_26_TRACE0
+#define EPL_DBGLVL_VETH_TRACE1 DEBUG_LVL_26_TRACE1
+#define EPL_DBGLVL_VETH_TRACE2 DEBUG_LVL_26_TRACE2
+#define EPL_DBGLVL_VETH_TRACE3 DEBUG_LVL_26_TRACE3
+#define EPL_DBGLVL_VETH_TRACE4 DEBUG_LVL_26_TRACE4
+
+#define EPL_DBGLVL_EVENTK DEBUG_LVL_27 // 0x04000000
+#define EPL_DBGLVL_EVENTK_TRACE0 DEBUG_LVL_27_TRACE0
+#define EPL_DBGLVL_EVENTK_TRACE1 DEBUG_LVL_27_TRACE1
+#define EPL_DBGLVL_EVENTK_TRACE2 DEBUG_LVL_27_TRACE2
+#define EPL_DBGLVL_EVENTK_TRACE3 DEBUG_LVL_27_TRACE3
+#define EPL_DBGLVL_EVENTK_TRACE4 DEBUG_LVL_27_TRACE4
+
+#define EPL_DBGLVL_EVENTU DEBUG_LVL_28 // 0x08000000
+#define EPL_DBGLVL_EVENTU_TRACE0 DEBUG_LVL_28_TRACE0
+#define EPL_DBGLVL_EVENTU_TRACE1 DEBUG_LVL_28_TRACE1
+#define EPL_DBGLVL_EVENTU_TRACE2 DEBUG_LVL_28_TRACE2
+#define EPL_DBGLVL_EVENTU_TRACE3 DEBUG_LVL_28_TRACE3
+#define EPL_DBGLVL_EVENTU_TRACE4 DEBUG_LVL_28_TRACE4
+
+// SharedBuff
+#define EPL_DBGLVL_SHB DEBUG_LVL_29 // 0x10000000
+#define EPL_DBGLVL_SHB_TRACE0 DEBUG_LVL_29_TRACE0
+#define EPL_DBGLVL_SHB_TRACE1 DEBUG_LVL_29_TRACE1
+#define EPL_DBGLVL_SHB_TRACE2 DEBUG_LVL_29_TRACE2
+#define EPL_DBGLVL_SHB_TRACE3 DEBUG_LVL_29_TRACE3
+#define EPL_DBGLVL_SHB_TRACE4 DEBUG_LVL_29_TRACE4
+
+#define EPL_DBGLVL_ASSERT DEBUG_LVL_ASSERT // 0x20000000L
+#define EPL_DBGLVL_ASSERT_TRACE0 DEBUG_LVL_ASSERT_TRACE0
+#define EPL_DBGLVL_ASSERT_TRACE1 DEBUG_LVL_ASSERT_TRACE1
+#define EPL_DBGLVL_ASSERT_TRACE2 DEBUG_LVL_ASSERT_TRACE2
+#define EPL_DBGLVL_ASSERT_TRACE3 DEBUG_LVL_ASSERT_TRACE3
+#define EPL_DBGLVL_ASSERT_TRACE4 DEBUG_LVL_ASSERT_TRACE4
+
+#define EPL_DBGLVL_ERROR DEBUG_LVL_ERROR // 0x40000000L
+#define EPL_DBGLVL_ERROR_TRACE0 DEBUG_LVL_ERROR_TRACE0
+#define EPL_DBGLVL_ERROR_TRACE1 DEBUG_LVL_ERROR_TRACE1
+#define EPL_DBGLVL_ERROR_TRACE2 DEBUG_LVL_ERROR_TRACE2
+#define EPL_DBGLVL_ERROR_TRACE3 DEBUG_LVL_ERROR_TRACE3
+#define EPL_DBGLVL_ERROR_TRACE4 DEBUG_LVL_ERROR_TRACE4
+
+#define EPL_DBGLVL_ALWAYS DEBUG_LVL_ALWAYS // 0x80000000L
+#define EPL_DBGLVL_ALWAYS_TRACE0 DEBUG_LVL_ALWAYS_TRACE0
+#define EPL_DBGLVL_ALWAYS_TRACE1 DEBUG_LVL_ALWAYS_TRACE1
+#define EPL_DBGLVL_ALWAYS_TRACE2 DEBUG_LVL_ALWAYS_TRACE2
+#define EPL_DBGLVL_ALWAYS_TRACE3 DEBUG_LVL_ALWAYS_TRACE3
+#define EPL_DBGLVL_ALWAYS_TRACE4 DEBUG_LVL_ALWAYS_TRACE4
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_INC_H_
diff --git a/drivers/staging/epl/EplInstDef.h b/drivers/staging/epl/EplInstDef.h
new file mode 100644
index 000000000000..89efbf278264
--- /dev/null
+++ b/drivers/staging/epl/EplInstDef.h
@@ -0,0 +1,377 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: definitions for generating instances
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplInstDef.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ ...
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ r.d.: first implementation
+
+****************************************************************************/
+
+#ifndef _EPLINSTDEF_H_
+#define _EPLINSTDEF_H_
+
+// =========================================================================
+// types and macros for generating instances
+// =========================================================================
+
+typedef enum {
+ kStateUnused = 0,
+ kStateDeleted = 1,
+ kStateUsed = 0xFF
+} tInstState;
+
+//------------------------------------------------------------------------------------------
+
+typedef void MEM *tEplPtrInstance;
+typedef BYTE tEplInstanceHdl;
+
+// define const for illegale values
+#define CCM_ILLINSTANCE NULL
+#define CCM_ILLINSTANCE_HDL 0xFF
+
+//------------------------------------------------------------------------------------------
+// if more than one instance then use this macros
+#if (EPL_MAX_INSTANCES > 1)
+
+ //--------------------------------------------------------------------------------------
+ // macro definition for instance table definition
+ //--------------------------------------------------------------------------------------
+
+ // memory attributes for instance table
+#define INST_NEAR // faster access to variables
+#define INST_FAR // variables wich have to located in xdata
+#define STATIC // prevent warnings for variables with same name
+
+#define INSTANCE_TYPE_BEGIN typedef struct {
+#define INSTANCE_TYPE_END } tEplInstanceInfo;
+
+ //--------------------------------------------------------------------------------------
+ // macro definition for API interface
+ //--------------------------------------------------------------------------------------
+
+ // declaration:
+
+ // macros for declaration within function header or prototype of API functions
+#define CCM_DECL_INSTANCE_HDL tEplInstanceHdl InstanceHandle
+#define CCM_DECL_INSTANCE_HDL_ tEplInstanceHdl InstanceHandle,
+
+ // macros for declaration of pointer to instance handle within function header or prototype of API functions
+#define CCM_DECL_PTR_INSTANCE_HDL tEplInstanceHdl MEM* pInstanceHandle
+#define CCM_DECL_PTR_INSTANCE_HDL_ tEplInstanceHdl MEM* pInstanceHandle,
+
+ // macros for declaration instance as lokacl variable within functions
+#define CCM_DECL_INSTANCE_PTR_LOCAL tCcmInstanceInfo MEM* pInstance;
+#define CCM_DECL_PTR_INSTANCE_HDL_LOCAL tEplInstanceHdl MEM* pInstanceHandle;
+
+ // reference:
+
+ // macros for reference of instance handle for function parameters
+#define CCM_INSTANCE_HDL InstanceHandle
+#define CCM_INSTANCE_HDL_ InstanceHandle,
+
+ // macros for reference of instance parameter for function parameters
+#define CCM_INSTANCE_PARAM(par) par
+#define CCM_INSTANCE_PARAM_(par) par,
+
+ // macros for reference of instance parameter for writing or reading values
+#define CCM_INST_ENTRY (*((tEplPtrInstance)pInstance))
+
+ // processing:
+
+ // macros for process instance handle
+#define CCM_CHECK_INSTANCE_HDL() if (InstanceHandle >= EPL_MAX_INSTANCES) \
+ {return (kEplIllegalInstance);}
+
+ // macros for process pointer to instance handle
+#define CCM_CHECK_PTR_INSTANCE_HDL() if (pInstanceHandle == NULL) \
+ {return (kEplInvalidInstanceParam);}
+
+ // This macro returned the handle and pointer to next free instance.
+#define CCM_GET_FREE_INSTANCE_AND_HDL() pInstance = CcmGetFreeInstanceAndHandle (pInstanceHandle); \
+ ASSERT (*pInstanceHandle != CCM_ILLINSTANCE_HDL);
+
+#define CCM_CHECK_INSTANCE_PTR() if (pInstance == CCM_ILLINSTANCE) \
+ {return (kEplNoFreeInstance);}
+
+#define CCM_GET_INSTANCE_PTR() pInstance = CcmGetInstancePtr (InstanceHandle);
+#define CCM_GET_FREE_INSTANCE_PTR() pInstance = GetFreeInstance (); \
+ ASSERT (pInstance != CCM_ILLINSTANCE);
+
+ //--------------------------------------------------------------------------------------
+ // macro definition for stack interface
+ //--------------------------------------------------------------------------------------
+
+ // macros for declaration within the function header, prototype or local var list
+ // Declaration of pointers within function paramater list must defined as void MEM*
+ // pointer.
+#define EPL_MCO_DECL_INSTANCE_PTR void MEM* pInstance
+#define EPL_MCO_DECL_INSTANCE_PTR_ void MEM* pInstance,
+#define EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplPtrInstance pInstance;
+
+ // macros for reference of pointer to instance
+ // These macros are used for parameter passing to called function.
+#define EPL_MCO_INSTANCE_PTR pInstance
+#define EPL_MCO_INSTANCE_PTR_ pInstance,
+#define EPL_MCO_ADDR_INSTANCE_PTR_ &pInstance,
+
+ // macro for access of struct members of one instance
+ // An access to a member of instance table must be casted by the local
+ // defined type of instance table.
+#define EPL_MCO_INST_ENTRY (*(tEplPtrInstance)pInstance)
+#define EPL_MCO_GLB_VAR(var) (((tEplPtrInstance)pInstance)->var)
+
+ // macros for process pointer to instance
+#define EPL_MCO_GET_INSTANCE_PTR() pInstance = (tEplPtrInstance) GetInstancePtr (InstanceHandle);
+#define EPL_MCO_GET_FREE_INSTANCE_PTR() pInstance = (tEplPtrInstance) GetFreeInstance (); \
+ ASSERT (pInstance != CCM_ILLINSTANCE);
+
+ // This macro should be used to check the passed pointer to an public function
+#define EPL_MCO_CHECK_INSTANCE_STATE() ASSERT (pInstance != NULL); \
+ ASSERT (((tEplPtrInstance)pInstance)->m_InstState == kStateUsed);
+
+ // macros for declaration of pointer to instance pointer
+#define EPL_MCO_DECL_PTR_INSTANCE_PTR void MEM* MEM* pInstancePtr
+#define EPL_MCO_DECL_PTR_INSTANCE_PTR_ void MEM* MEM* pInstancePtr,
+
+ // macros for reference of pointer to instance pointer
+ // These macros are used for parameter passing to called function.
+#define EPL_MCO_PTR_INSTANCE_PTR pInstancePtr
+#define EPL_MCO_PTR_INSTANCE_PTR_ pInstancePtr,
+
+ // macros for process pointer to instance pointer
+#define EPL_MCO_CHECK_PTR_INSTANCE_PTR() ASSERT (pInstancePtr != NULL);
+#define EPL_MCO_SET_PTR_INSTANCE_PTR() (*pInstancePtr = pInstance);
+
+#define EPL_MCO_INSTANCE_PARAM(a) (a)
+#define EPL_MCO_INSTANCE_PARAM_(a) (a),
+#define EPL_MCO_INSTANCE_PARAM_IDX_() EPL_MCO_INSTANCE_PARAM_ (EPL_MCO_GLB_VAR (m_bInstIndex))
+#define EPL_MCO_INSTANCE_PARAM_IDX() EPL_MCO_INSTANCE_PARAM (EPL_MCO_GLB_VAR (m_bInstIndex))
+#define EPL_MCO_WRITE_INSTANCE_STATE(a) EPL_MCO_GLB_VAR (m_InstState) = a;
+
+ // this macro deletes all instance entries as unused
+#define EPL_MCO_DELETE_INSTANCE_TABLE() \
+ { \
+ tEplInstanceInfo MEM* pInstance = &aEplInstanceTable_g[0]; \
+ tFastByte InstNumber = 0; \
+ tFastByte i = EPL_MAX_INSTANCES; \
+ do { \
+ pInstance->m_InstState = (BYTE) kStateUnused; \
+ pInstance->m_bInstIndex = (BYTE) InstNumber; \
+ pInstance++; InstNumber++; i--; \
+ } while (i != 0); \
+ }
+
+ // definition of functions which has to be defined in each module of CANopen stack
+#define EPL_MCO_DEFINE_INSTANCE_FCT() \
+ static tEplPtrInstance GetInstancePtr (tEplInstanceHdl InstHandle_p); \
+ static tEplPtrInstance GetFreeInstance (void);
+#define EPL_MCO_DECL_INSTANCE_FCT() \
+ static tEplPtrInstance GetInstancePtr (tEplInstanceHdl InstHandle_p) { \
+ return &aEplInstanceTable_g[InstHandle_p]; } \
+ static tEplPtrInstance GetFreeInstance (void) { \
+ tEplInstanceInfo MEM* pInstance = &aEplInstanceTable_g[0]; \
+ tFastByte i = EPL_MAX_INSTANCES; \
+ do { if (pInstance->m_InstState != kStateUsed) { \
+ return (tEplPtrInstance) pInstance; } \
+ pInstance++; i--; } \
+ while (i != 0); \
+ return CCM_ILLINSTANCE; }
+
+ // this macro defines the instance table. Each entry is reserved for an instance of CANopen.
+#define EPL_MCO_DECL_INSTANCE_VAR() \
+ static tEplInstanceInfo MEM aEplInstanceTable_g [EPL_MAX_INSTANCES];
+
+ // this macro defines member variables in instance table which are needed in
+ // all modules of Epl stack
+#define EPL_MCO_DECL_INSTANCE_MEMBER() \
+ STATIC BYTE m_InstState; \
+ STATIC BYTE m_bInstIndex;
+
+#define EPL_MCO_INSTANCE_PARAM_IDX_() EPL_MCO_INSTANCE_PARAM_ (EPL_MCO_GLB_VAR (m_bInstIndex))
+#define EPL_MCO_INSTANCE_PARAM_IDX() EPL_MCO_INSTANCE_PARAM (EPL_MCO_GLB_VAR (m_bInstIndex))
+
+#else // only one instance is used
+
+ // Memory attributes for instance table.
+#define INST_NEAR NEAR // faster access to variables
+#define INST_FAR MEM // variables wich have to located in xdata
+#define STATIC static // prevent warnings for variables with same name
+
+#define INSTANCE_TYPE_BEGIN
+#define INSTANCE_TYPE_END
+
+// macros for declaration, initializing and member access for instance handle
+// This class of macros are used by API function to inform CCM-modul which
+// instance is to be used.
+
+ // macros for reference of instance handle
+ // These macros are used for parameter passing to CANopen API function.
+#define CCM_INSTANCE_HDL
+#define CCM_INSTANCE_HDL_
+
+#define CCM_DECL_INSTANCE_PTR_LOCAL
+
+ // macros for declaration within the function header or prototype
+#define CCM_DECL_INSTANCE_HDL void
+#define CCM_DECL_INSTANCE_HDL_
+
+ // macros for process instance handle
+#define CCM_CHECK_INSTANCE_HDL()
+
+ // macros for declaration of pointer to instance handle
+#define CCM_DECL_PTR_INSTANCE_HDL void
+#define CCM_DECL_PTR_INSTANCE_HDL_
+
+ // macros for process pointer to instance handle
+#define CCM_CHECK_PTR_INSTANCE_HDL()
+
+ // This macro returned the handle and pointer to next free instance.
+#define CCM_GET_FREE_INSTANCE_AND_HDL()
+
+#define CCM_CHECK_INSTANCE_PTR()
+
+#define CCM_GET_INSTANCE_PTR()
+#define CCM_GET_FREE_INSTANCE_PTR()
+
+#define CCM_INSTANCE_PARAM(par)
+#define CCM_INSTANCE_PARAM_(par)
+
+#define CCM_INST_ENTRY aCcmInstanceTable_g[0]
+
+// macros for declaration, initializing and member access for instance pointer
+// This class of macros are used by CANopen internal function to point to one instance.
+
+ // macros for declaration within the function header, prototype or local var list
+#define EPL_MCO_DECL_INSTANCE_PTR void
+#define EPL_MCO_DECL_INSTANCE_PTR_
+#define EPL_MCO_DECL_INSTANCE_PTR_LOCAL
+
+ // macros for reference of pointer to instance
+ // These macros are used for parameter passing to called function.
+#define EPL_MCO_INSTANCE_PTR
+#define EPL_MCO_INSTANCE_PTR_
+#define EPL_MCO_ADDR_INSTANCE_PTR_
+
+ // macros for process pointer to instance
+#define EPL_MCO_GET_INSTANCE_PTR()
+#define EPL_MCO_GET_FREE_INSTANCE_PTR()
+
+ // This macro should be used to check the passed pointer to an public function
+#define EPL_MCO_CHECK_INSTANCE_STATE()
+
+ // macros for declaration of pointer to instance pointer
+#define EPL_MCO_DECL_PTR_INSTANCE_PTR void
+#define EPL_MCO_DECL_PTR_INSTANCE_PTR_
+
+ // macros for reference of pointer to instance pointer
+ // These macros are used for parameter passing to called function.
+#define EPL_MCO_PTR_INSTANCE_PTR
+#define EPL_MCO_PTR_INSTANCE_PTR_
+
+ // macros for process pointer to instance pointer
+#define EPL_MCO_CHECK_PTR_INSTANCE_PTR()
+#define EPL_MCO_SET_PTR_INSTANCE_PTR()
+
+#define EPL_MCO_INSTANCE_PARAM(a)
+#define EPL_MCO_INSTANCE_PARAM_(a)
+#define EPL_MCO_INSTANCE_PARAM_IDX_()
+#define EPL_MCO_INSTANCE_PARAM_IDX()
+
+ // macro for access of struct members of one instance
+#define EPL_MCO_INST_ENTRY aEplInstanceTable_g[0]
+#define EPL_MCO_GLB_VAR(var) (var)
+#define EPL_MCO_WRITE_INSTANCE_STATE(a)
+
+ // this macro deletes all instance entries as unused
+#define EPL_MCO_DELETE_INSTANCE_TABLE()
+
+ // definition of functions which has to be defined in each module of CANopen stack
+#define EPL_MCO_DEFINE_INSTANCE_FCT()
+#define EPL_MCO_DECL_INSTANCE_FCT()
+
+ // this macro defines the instance table. Each entry is reserved for an instance of CANopen.
+#define EPL_MCO_DECL_INSTANCE_VAR()
+
+ // this macro defines member variables in instance table which are needed in
+ // all modules of CANopen stack
+#define EPL_MCO_DECL_INSTANCE_MEMBER()
+
+#endif
+
+/*
+#if (CDRV_MAX_INSTANCES > 1)
+
+ #define CDRV_REENTRANT REENTRANT
+
+#else
+
+ #define CDRV_REENTRANT
+
+#endif
+*/
+
+#endif // _EPLINSTDEF_H_
+
+// Die letzte Zeile mu unbedingt eine leere Zeile sein, weil manche Compiler
+// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder).
diff --git a/drivers/staging/epl/EplLed.h b/drivers/staging/epl/EplLed.h
new file mode 100644
index 000000000000..6a29aed303a2
--- /dev/null
+++ b/drivers/staging/epl/EplLed.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for status and error LED
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplLed.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.1 $ $Date: 2008/11/17 16:40:39 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2008/11/17 d.k.: start of the implementation
+
+****************************************************************************/
+
+#ifndef _EPLLED_H_
+#define _EPLLED_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef enum {
+ kEplLedTypeStatus = 0x00,
+ kEplLedTypeError = 0x01,
+
+} tEplLedType;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPLLED_H_
diff --git a/drivers/staging/epl/EplNmt.h b/drivers/staging/epl/EplNmt.h
new file mode 100644
index 000000000000..4c11e5bc74aa
--- /dev/null
+++ b/drivers/staging/epl/EplNmt.h
@@ -0,0 +1,230 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: global include file for EPL-NMT-Modules
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmt.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/11/17 16:40:39 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#ifndef _EPLNMT_H_
+#define _EPLNMT_H_
+
+#include "EplInc.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// define super-states and masks to identify a super-state
+#define EPL_NMT_GS_POWERED 0x0008 // super state
+#define EPL_NMT_GS_INITIALISATION 0x0009 // super state
+#define EPL_NMT_GS_COMMUNICATING 0x000C // super state
+#define EPL_NMT_CS_EPLMODE 0x000D // super state
+#define EPL_NMT_MS_EPLMODE 0x000D // super state
+
+#define EPL_NMT_SUPERSTATE_MASK 0x000F // mask to select state
+
+#define EPL_NMT_TYPE_UNDEFINED 0x0000 // type of NMT state is still undefined
+#define EPL_NMT_TYPE_CS 0x0100 // CS type of NMT state
+#define EPL_NMT_TYPE_MS 0x0200 // MS type of NMT state
+#define EPL_NMT_TYPE_MASK 0x0300 // mask to select type of NMT state (i.e. CS or MS)
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+// the lower Byte of the NMT-State is encoded
+// like the values in the EPL-Standard
+// the higher byte is used to encode MN
+// (Bit 1 of the higher byte = 1) or CN (Bit 0 of the
+// higher byte = 1)
+// the super-states are not mentioned in this
+// enum because they are no real states
+// --> there are masks defined to indentify the
+// super-states
+
+typedef enum {
+ kEplNmtGsOff = 0x0000,
+ kEplNmtGsInitialising = 0x0019,
+ kEplNmtGsResetApplication = 0x0029,
+ kEplNmtGsResetCommunication = 0x0039,
+ kEplNmtGsResetConfiguration = 0x0079,
+ kEplNmtCsNotActive = 0x011C,
+ kEplNmtCsPreOperational1 = 0x011D,
+ kEplNmtCsStopped = 0x014D,
+ kEplNmtCsPreOperational2 = 0x015D,
+ kEplNmtCsReadyToOperate = 0x016D,
+ kEplNmtCsOperational = 0x01FD,
+ kEplNmtCsBasicEthernet = 0x011E,
+ kEplNmtMsNotActive = 0x021C,
+ kEplNmtMsPreOperational1 = 0x021D,
+ kEplNmtMsPreOperational2 = 0x025D,
+ kEplNmtMsReadyToOperate = 0x026D,
+ kEplNmtMsOperational = 0x02FD,
+ kEplNmtMsBasicEthernet = 0x021E
+} tEplNmtState;
+
+// NMT-events
+typedef enum {
+ // Events from DLL
+ // Events defined by EPL V2 specification
+ kEplNmtEventNoEvent = 0x00,
+// kEplNmtEventDllMePres = 0x01,
+ kEplNmtEventDllMePresTimeout = 0x02,
+// kEplNmtEventDllMeAsnd = 0x03,
+// kEplNmtEventDllMeAsndTimeout = 0x04,
+ kEplNmtEventDllMeSoaSent = 0x04,
+ kEplNmtEventDllMeSocTrig = 0x05,
+ kEplNmtEventDllMeSoaTrig = 0x06,
+ kEplNmtEventDllCeSoc = 0x07,
+ kEplNmtEventDllCePreq = 0x08,
+ kEplNmtEventDllCePres = 0x09,
+ kEplNmtEventDllCeSoa = 0x0A,
+ kEplNmtEventDllCeAsnd = 0x0B,
+ kEplNmtEventDllCeFrameTimeout = 0x0C,
+
+ // Events triggered by NMT-Commands
+ kEplNmtEventSwReset = 0x10, // NMT_GT1, NMT_GT2, NMT_GT8
+ kEplNmtEventResetNode = 0x11,
+ kEplNmtEventResetCom = 0x12,
+ kEplNmtEventResetConfig = 0x13,
+ kEplNmtEventEnterPreOperational2 = 0x14,
+ kEplNmtEventEnableReadyToOperate = 0x15,
+ kEplNmtEventStartNode = 0x16, // NMT_CT7
+ kEplNmtEventStopNode = 0x17,
+
+ // Events triggered by higher layer
+ kEplNmtEventEnterResetApp = 0x20,
+ kEplNmtEventEnterResetCom = 0x21,
+ kEplNmtEventInternComError = 0x22, // NMT_GT6, internal communication error -> enter ResetCommunication
+ kEplNmtEventEnterResetConfig = 0x23,
+ kEplNmtEventEnterCsNotActive = 0x24,
+ kEplNmtEventEnterMsNotActive = 0x25,
+ kEplNmtEventTimerBasicEthernet = 0x26, // NMT_CT3; timer triggered state change (NotActive -> BasicEth)
+ kEplNmtEventTimerMsPreOp1 = 0x27, // enter PreOp1 on MN (NotActive -> MsPreOp1)
+ kEplNmtEventNmtCycleError = 0x28, // NMT_CT11, NMT_MT6; error during cycle -> enter PreOp1
+ kEplNmtEventTimerMsPreOp2 = 0x29, // enter PreOp2 on MN (MsPreOp1 -> MsPreOp2 if kEplNmtEventAllMandatoryCNIdent)
+ kEplNmtEventAllMandatoryCNIdent = 0x2A, // enter PreOp2 on MN if kEplNmtEventTimerMsPreOp2
+ kEplNmtEventEnterReadyToOperate = 0x2B, // application ready for the state ReadyToOp
+ kEplNmtEventEnterMsOperational = 0x2C, // enter Operational on MN
+ kEplNmtEventSwitchOff = 0x2D, // enter state Off
+ kEplNmtEventCriticalError = 0x2E, // enter state Off because of critical error
+
+} tEplNmtEvent;
+
+// type for argument of event kEplEventTypeNmtStateChange
+typedef struct {
+ tEplNmtState m_NewNmtState;
+ tEplNmtEvent m_NmtEvent;
+
+} tEplEventNmtStateChange;
+
+// structure for kEplEventTypeHeartbeat
+typedef struct {
+ unsigned int m_uiNodeId; // NodeId
+ tEplNmtState m_NmtState; // NMT state (remember distinguish between MN / CN)
+ WORD m_wErrorCode; // EPL error code in case of NMT state NotActive
+
+} tEplHeartbeatEvent;
+
+typedef enum {
+ kEplNmtNodeEventFound = 0x00,
+ kEplNmtNodeEventUpdateSw = 0x01, // application shall update software on CN
+ kEplNmtNodeEventCheckConf = 0x02, // application / Configuration Manager shall check and update configuration on CN
+ kEplNmtNodeEventUpdateConf = 0x03, // application / Configuration Manager shall update configuration on CN (check was done by NmtMn module)
+ kEplNmtNodeEventVerifyConf = 0x04, // application / Configuration Manager shall verify configuration of CN
+ kEplNmtNodeEventReadyToStart = 0x05, // issued if EPL_NMTST_NO_STARTNODE set
+ // application must call EplNmtMnuSendNmtCommand(kEplNmtCmdStartNode) manually
+ kEplNmtNodeEventNmtState = 0x06,
+ kEplNmtNodeEventError = 0x07, // NMT error of CN
+
+} tEplNmtNodeEvent;
+
+typedef enum {
+ kEplNmtNodeCommandBoot = 0x01, // if EPL_NODEASSIGN_START_CN not set it must be issued after kEplNmtNodeEventFound
+ kEplNmtNodeCommandSwOk = 0x02, // application updated software on CN successfully
+ kEplNmtNodeCommandSwUpdated = 0x03, // application updated software on CN successfully
+ kEplNmtNodeCommandConfOk = 0x04, // application / Configuration Manager has updated configuration on CN successfully
+ kEplNmtNodeCommandConfReset = 0x05, // application / Configuration Manager has updated configuration on CN successfully
+ // and CN needs ResetConf so that the configuration gets actived
+ kEplNmtNodeCommandConfErr = 0x06, // application / Configuration Manager failed on updating configuration on CN
+ kEplNmtNodeCommandStart = 0x07, // if EPL_NMTST_NO_STARTNODE set it must be issued after kEplNmtNodeEventReadyToStart
+
+} tEplNmtNodeCommand;
+
+typedef enum {
+ kEplNmtBootEventBootStep1Finish = 0x00, // PreOp2 is possible
+ kEplNmtBootEventBootStep2Finish = 0x01, // ReadyToOp is possible
+ kEplNmtBootEventCheckComFinish = 0x02, // Operational is possible
+ kEplNmtBootEventOperational = 0x03, // all mandatory CNs are Operational
+ kEplNmtBootEventError = 0x04, // boot process halted because of an error
+
+} tEplNmtBootEvent;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPLNMT_H_
diff --git a/drivers/staging/epl/EplNmtCnu.c b/drivers/staging/epl/EplNmtCnu.c
new file mode 100644
index 000000000000..f2f46da08c7d
--- /dev/null
+++ b/drivers/staging/epl/EplNmtCnu.c
@@ -0,0 +1,704 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for NMT-CN-Userspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtCnu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "user/EplNmtCnu.h"
+#include "user/EplDlluCal.h"
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0)
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ unsigned int m_uiNodeId;
+ tEplNmtuCheckEventCallback m_pfnCheckEventCb;
+
+} tEplNmtCnuInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+static tEplNmtCnuInstance EplNmtCnuInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplNmtCommand EplNmtCnuGetNmtCommand(tEplFrameInfo * pFrameInfo_p);
+
+static BOOL EplNmtCnuNodeIdList(BYTE * pbNmtCommandDate_p);
+
+static tEplKernel PUBLIC EplNmtCnuCommandCb(tEplFrameInfo * pFrameInfo_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuInit
+//
+// Description: init the first instance of the module
+//
+//
+//
+// Parameters: uiNodeId_p = NodeId of the local node
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuInit(unsigned int uiNodeId_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplNmtCnuAddInstance(uiNodeId_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuAddInstance
+//
+// Description: init the add new instance of the module
+//
+//
+//
+// Parameters: uiNodeId_p = NodeId of the local node
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuAddInstance(unsigned int uiNodeId_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // reset instance structure
+ EPL_MEMSET(&EplNmtCnuInstance_g, 0, sizeof(EplNmtCnuInstance_g));
+
+ // save nodeid
+ EplNmtCnuInstance_g.m_uiNodeId = uiNodeId_p;
+
+ // register callback-function for NMT-commands
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ Ret = EplDlluCalRegAsndService(kEplDllAsndNmtCommand,
+ EplNmtCnuCommandCb,
+ kEplDllAsndFilterLocal);
+#endif
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuDelInstance
+//
+// Description: delte instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ // deregister callback function from DLL
+ Ret = EplDlluCalRegAsndService(kEplDllAsndNmtCommand,
+ NULL, kEplDllAsndFilterNone);
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuSendNmtRequest
+//
+// Description: Send an NMT-Request to the MN
+//
+//
+//
+// Parameters: uiNodeId_p = NodeId of the local node
+// NmtCommand_p = requested NMT-Command
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p,
+ tEplNmtCommand
+ NmtCommand_p)
+{
+ tEplKernel Ret;
+ tEplFrameInfo NmtRequestFrameInfo;
+ tEplFrame NmtRequestFrame;
+
+ Ret = kEplSuccessful;
+
+ // build frame
+ EPL_MEMSET(&NmtRequestFrame.m_be_abDstMac[0], 0x00, sizeof(NmtRequestFrame.m_be_abDstMac)); // set by DLL
+ EPL_MEMSET(&NmtRequestFrame.m_be_abSrcMac[0], 0x00, sizeof(NmtRequestFrame.m_be_abSrcMac)); // set by DLL
+ AmiSetWordToBe(&NmtRequestFrame.m_be_wEtherType,
+ EPL_C_DLL_ETHERTYPE_EPL);
+ AmiSetByteToLe(&NmtRequestFrame.m_le_bDstNodeId, (BYTE) EPL_C_ADR_MN_DEF_NODE_ID); // node id of the MN
+ AmiSetByteToLe(&NmtRequestFrame.m_le_bMessageType,
+ (BYTE) kEplMsgTypeAsnd);
+ AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_le_bServiceId,
+ (BYTE) kEplDllAsndNmtRequest);
+ AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.
+ m_NmtRequestService.m_le_bNmtCommandId,
+ (BYTE) NmtCommand_p);
+ AmiSetByteToLe(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.m_le_bTargetNodeId, (BYTE) uiNodeId_p); // target for the nmt command
+ EPL_MEMSET(&NmtRequestFrame.m_Data.m_Asnd.m_Payload.m_NmtRequestService.
+ m_le_abNmtCommandData[0], 0x00,
+ sizeof(NmtRequestFrame.m_Data.m_Asnd.m_Payload.
+ m_NmtRequestService.m_le_abNmtCommandData));
+
+ // build info-structure
+ NmtRequestFrameInfo.m_NetTime.m_dwNanoSec = 0;
+ NmtRequestFrameInfo.m_NetTime.m_dwSec = 0;
+ NmtRequestFrameInfo.m_pFrame = &NmtRequestFrame;
+ NmtRequestFrameInfo.m_uiFrameSize = EPL_C_DLL_MINSIZE_NMTREQ; // sizeof(NmtRequestFrame);
+
+ // send NMT-Request
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ Ret = EplDlluCalAsyncSend(&NmtRequestFrameInfo, // pointer to frameinfo
+ kEplDllAsyncReqPrioNmt); // priority
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuRegisterStateChangeCb
+//
+// Description: register Callback-function go get informed about a
+// NMT-Change-State-Event
+//
+//
+//
+// Parameters: pfnEplNmtStateChangeCb_p = functionpointer
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC
+EplNmtCnuRegisterCheckEventCb(tEplNmtuCheckEventCallback
+ pfnEplNmtCheckEventCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // save callback-function in modul global var
+ EplNmtCnuInstance_g.m_pfnCheckEventCb = pfnEplNmtCheckEventCb_p;
+
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuCommandCb
+//
+// Description: callback funktion for NMT-Commands
+//
+//
+//
+// Parameters: pFrameInfo_p = Frame with the NMT-Commando
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel PUBLIC EplNmtCnuCommandCb(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplNmtCommand NmtCommand;
+ BOOL fNodeIdInList;
+ tEplNmtEvent NmtEvent = kEplNmtEventNoEvent;
+
+ if (pFrameInfo_p == NULL) {
+ Ret = kEplNmtInvalidFramePointer;
+ goto Exit;
+ }
+
+ NmtCommand = EplNmtCnuGetNmtCommand(pFrameInfo_p);
+
+ // check NMT-Command
+ switch (NmtCommand) {
+
+ //------------------------------------------------------------------------
+ // plain NMT state commands
+ case kEplNmtCmdStartNode:
+ { // send NMT-Event to state maschine kEplNmtEventStartNode
+ NmtEvent = kEplNmtEventStartNode;
+ break;
+ }
+
+ case kEplNmtCmdStopNode:
+ { // send NMT-Event to state maschine kEplNmtEventStopNode
+ NmtEvent = kEplNmtEventStopNode;
+ break;
+ }
+
+ case kEplNmtCmdEnterPreOperational2:
+ { // send NMT-Event to state maschine kEplNmtEventEnterPreOperational2
+ NmtEvent = kEplNmtEventEnterPreOperational2;
+ break;
+ }
+
+ case kEplNmtCmdEnableReadyToOperate:
+ { // send NMT-Event to state maschine kEplNmtEventEnableReadyToOperate
+ NmtEvent = kEplNmtEventEnableReadyToOperate;
+ break;
+ }
+
+ case kEplNmtCmdResetNode:
+ { // send NMT-Event to state maschine kEplNmtEventResetNode
+ NmtEvent = kEplNmtEventResetNode;
+ break;
+ }
+
+ case kEplNmtCmdResetCommunication:
+ { // send NMT-Event to state maschine kEplNmtEventResetCom
+ NmtEvent = kEplNmtEventResetCom;
+ break;
+ }
+
+ case kEplNmtCmdResetConfiguration:
+ { // send NMT-Event to state maschine kEplNmtEventResetConfig
+ NmtEvent = kEplNmtEventResetConfig;
+ break;
+ }
+
+ case kEplNmtCmdSwReset:
+ { // send NMT-Event to state maschine kEplNmtEventSwReset
+ NmtEvent = kEplNmtEventSwReset;
+ break;
+ }
+
+ //------------------------------------------------------------------------
+ // extended NMT state commands
+
+ case kEplNmtCmdStartNodeEx:
+ {
+ // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&
+ (pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]));
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventStartNode;
+ }
+ break;
+ }
+
+ case kEplNmtCmdStopNodeEx:
+ { // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]);
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventStopNode;
+ }
+ break;
+ }
+
+ case kEplNmtCmdEnterPreOperational2Ex:
+ { // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]);
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventEnterPreOperational2;
+ }
+ break;
+ }
+
+ case kEplNmtCmdEnableReadyToOperateEx:
+ { // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]);
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventEnableReadyToOperate;
+ }
+ break;
+ }
+
+ case kEplNmtCmdResetNodeEx:
+ { // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]);
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventResetNode;
+ }
+ break;
+ }
+
+ case kEplNmtCmdResetCommunicationEx:
+ { // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]);
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventResetCom;
+ }
+ break;
+ }
+
+ case kEplNmtCmdResetConfigurationEx:
+ { // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]);
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventResetConfig;
+ }
+ break;
+ }
+
+ case kEplNmtCmdSwResetEx:
+ { // check if own nodeid is in EPL node list
+ fNodeIdInList =
+ EplNmtCnuNodeIdList(&pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_abNmtCommandData[0]);
+ if (fNodeIdInList != FALSE) { // own nodeid in list
+ // send event to process command
+ NmtEvent = kEplNmtEventSwReset;
+ }
+ break;
+ }
+
+ //------------------------------------------------------------------------
+ // NMT managing commands
+
+ // TODO: add functions to process managing command (optional)
+
+ case kEplNmtCmdNetHostNameSet:
+ {
+ break;
+ }
+
+ case kEplNmtCmdFlushArpEntry:
+ {
+ break;
+ }
+
+ //------------------------------------------------------------------------
+ // NMT info services
+
+ // TODO: forward event with infos to the application (optional)
+
+ case kEplNmtCmdPublishConfiguredCN:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishActiveCN:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishPreOperational1:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishPreOperational2:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishReadyToOperate:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishOperational:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishStopped:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishEmergencyNew:
+ {
+ break;
+ }
+
+ case kEplNmtCmdPublishTime:
+ {
+ break;
+ }
+
+ //-----------------------------------------------------------------------
+ // error from MN
+ // -> requested command not supported by MN
+ case kEplNmtCmdInvalidService:
+ {
+
+ // TODO: errorevent to application
+ break;
+ }
+
+ //------------------------------------------------------------------------
+ // default
+ default:
+ {
+ Ret = kEplNmtUnknownCommand;
+ goto Exit;
+ }
+
+ } // end of switch(NmtCommand)
+
+ if (NmtEvent != kEplNmtEventNoEvent) {
+ if (EplNmtCnuInstance_g.m_pfnCheckEventCb != NULL) {
+ Ret = EplNmtCnuInstance_g.m_pfnCheckEventCb(NmtEvent);
+ if (Ret == kEplReject) {
+ Ret = kEplSuccessful;
+ goto Exit;
+ } else if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+ Ret = EplNmtuNmtEvent(NmtEvent);
+#endif
+ }
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuGetNmtCommand()
+//
+// Description: returns the NMT-Command from the frame
+//
+//
+//
+// Parameters: pFrameInfo_p = pointer to the Frame
+// with the NMT-Command
+//
+//
+// Returns: tEplNmtCommand = NMT-Command
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplNmtCommand EplNmtCnuGetNmtCommand(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplNmtCommand NmtCommand;
+ tEplNmtCommandService *pNmtCommandService;
+
+ pNmtCommandService =
+ &pFrameInfo_p->m_pFrame->m_Data.m_Asnd.m_Payload.
+ m_NmtCommandService;
+
+ NmtCommand =
+ (tEplNmtCommand) AmiGetByteFromLe(&pNmtCommandService->
+ m_le_bNmtCommandId);
+
+ return NmtCommand;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtCnuNodeIdList()
+//
+// Description: check if the own nodeid is set in EPL Node List
+//
+//
+//
+// Parameters: pbNmtCommandDate_p = pointer to the data of the NMT Command
+//
+//
+// Returns: BOOL = TRUE if nodeid is set in EPL Node List
+// FALSE if nodeid not set in EPL Node List
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static BOOL EplNmtCnuNodeIdList(BYTE * pbNmtCommandDate_p)
+{
+ BOOL fNodeIdInList;
+ unsigned int uiByteOffset;
+ BYTE bBitOffset;
+ BYTE bNodeListByte;
+
+ // get byte-offset of the own nodeid in NodeIdList
+ // devide though 8
+ uiByteOffset = (unsigned int)(EplNmtCnuInstance_g.m_uiNodeId >> 3);
+ // get bitoffset
+ bBitOffset = (BYTE) EplNmtCnuInstance_g.m_uiNodeId % 8;
+
+ bNodeListByte = AmiGetByteFromLe(&pbNmtCommandDate_p[uiByteOffset]);
+ if ((bNodeListByte & bBitOffset) == 0) {
+ fNodeIdInList = FALSE;
+ } else {
+ fNodeIdInList = TRUE;
+ }
+
+ return fNodeIdInList;
+}
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplNmtMnu.c b/drivers/staging/epl/EplNmtMnu.c
new file mode 100644
index 000000000000..4ed0b6ce487c
--- /dev/null
+++ b/drivers/staging/epl/EplNmtMnu.c
@@ -0,0 +1,2835 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for NMT-MN-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtMnu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.18 $ $Date: 2008/11/19 09:52:24 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplNmtMnu.h"
+#include "user/EplTimeru.h"
+#include "user/EplIdentu.h"
+#include "user/EplStatusu.h"
+#include "user/EplObdu.h"
+#include "user/EplDlluCal.h"
+#include "Benchmark.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
+#error "EPL NmtMnu module needs EPL module OBDU or OBDK!"
+#endif
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#define TGT_DBG_POST_TRACE_VALUE(v)
+#endif
+#define EPL_NMTMNU_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
+ TGT_DBG_POST_TRACE_VALUE((kEplEventSinkNmtMnu << 28) | (Event_p << 24) \
+ | (uiNodeId_p << 16) | wErrorCode_p)
+
+// defines for flags in node info structure
+#define EPL_NMTMNU_NODE_FLAG_ISOCHRON 0x0001 // CN is being accessed isochronously
+#define EPL_NMTMNU_NODE_FLAG_NOT_SCANNED 0x0002 // CN was not scanned once -> decrement SignalCounter and reset flag
+#define EPL_NMTMNU_NODE_FLAG_HALTED 0x0004 // boot process for this CN is halted
+#define EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED 0x0008 // NMT command was just issued, wrong NMT states will be tolerated
+#define EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ 0x0300 // counter for StatusRequest timer handle
+#define EPL_NMTMNU_NODE_FLAG_COUNT_LONGER 0x0C00 // counter for longer timeouts timer handle
+#define EPL_NMTMNU_NODE_FLAG_INC_STATREQ 0x0100 // increment for StatusRequest timer handle
+#define EPL_NMTMNU_NODE_FLAG_INC_LONGER 0x0400 // increment for longer timeouts timer handle
+ // These counters will be incremented at every timer start
+ // and copied to timerarg. When the timer event occures
+ // both will be compared and if unequal the timer event
+ // will be discarded, because it is an old one.
+
+// defines for timer arguments to draw a distinction between serveral events
+#define EPL_NMTMNU_TIMERARG_NODE_MASK 0x000000FFL // mask that contains the node-ID
+#define EPL_NMTMNU_TIMERARG_IDENTREQ 0x00010000L // timer event is for IdentRequest
+#define EPL_NMTMNU_TIMERARG_STATREQ 0x00020000L // timer event is for StatusRequest
+#define EPL_NMTMNU_TIMERARG_LONGER 0x00040000L // timer event is for longer timeouts
+#define EPL_NMTMNU_TIMERARG_STATE_MON 0x00080000L // timer event for StatusRequest to monitor execution of NMT state changes
+#define EPL_NMTMNU_TIMERARG_COUNT_SR 0x00000300L // counter for StatusRequest
+#define EPL_NMTMNU_TIMERARG_COUNT_LO 0x00000C00L // counter for longer timeouts
+ // The counters must have the same position as in the node flags above.
+
+#define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
+ pNodeInfo_p->m_wFlags = \
+ ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
+ & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
+ | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
+ TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p | \
+ (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
+ TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
+
+#define EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
+ pNodeInfo_p->m_wFlags = \
+ ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
+ & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
+ | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
+ TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p | \
+ (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
+ TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
+
+#define EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
+ pNodeInfo_p->m_wFlags = \
+ ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_LONGER) \
+ & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) \
+ | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \
+ TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p | \
+ (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \
+ TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
+
+#define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
+ pNodeInfo_p->m_wFlags = \
+ ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
+ & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
+ | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
+ TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATE_MON | uiNodeId_p | \
+ (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
+ TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
+
+// defines for global flags
+#define EPL_NMTMNU_FLAG_HALTED 0x0001 // boot process is halted
+#define EPL_NMTMNU_FLAG_APP_INFORMED 0x0002 // application was informed about possible NMT state change
+
+// return pointer to node info structure for specified node ID
+// d.k. may be replaced by special (hash) function if node ID array is smaller than 254
+#define EPL_NMTMNU_GET_NODEINFO(uiNodeId_p) (&EplNmtMnuInstance_g.m_aNodeInfo[uiNodeId_p - 1])
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef enum {
+ kEplNmtMnuIntNodeEventNoIdentResponse = 0x00,
+ kEplNmtMnuIntNodeEventIdentResponse = 0x01,
+ kEplNmtMnuIntNodeEventBoot = 0x02,
+ kEplNmtMnuIntNodeEventExecReset = 0x03,
+ kEplNmtMnuIntNodeEventConfigured = 0x04,
+ kEplNmtMnuIntNodeEventNoStatusResponse = 0x05,
+ kEplNmtMnuIntNodeEventStatusResponse = 0x06,
+ kEplNmtMnuIntNodeEventHeartbeat = 0x07,
+ kEplNmtMnuIntNodeEventNmtCmdSent = 0x08,
+ kEplNmtMnuIntNodeEventTimerIdentReq = 0x09,
+ kEplNmtMnuIntNodeEventTimerStatReq = 0x0A,
+ kEplNmtMnuIntNodeEventTimerStateMon = 0x0B,
+ kEplNmtMnuIntNodeEventTimerLonger = 0x0C,
+ kEplNmtMnuIntNodeEventError = 0x0D,
+
+} tEplNmtMnuIntNodeEvent;
+
+typedef enum {
+ kEplNmtMnuNodeStateUnknown = 0x00,
+ kEplNmtMnuNodeStateIdentified = 0x01,
+ kEplNmtMnuNodeStateResetConf = 0x02, // CN reset after configuration update
+ kEplNmtMnuNodeStateConfigured = 0x03, // BootStep1 completed
+ kEplNmtMnuNodeStateReadyToOp = 0x04, // BootStep2 completed
+ kEplNmtMnuNodeStateComChecked = 0x05, // Communication checked successfully
+ kEplNmtMnuNodeStateOperational = 0x06, // CN is in NMT state OPERATIONAL
+
+} tEplNmtMnuNodeState;
+
+typedef struct {
+ tEplTimerHdl m_TimerHdlStatReq; // timer to delay StatusRequests and IdentRequests
+ tEplTimerHdl m_TimerHdlLonger; // 2nd timer for NMT command EnableReadyToOp and CheckCommunication
+ tEplNmtMnuNodeState m_NodeState; // internal node state (kind of sub state of NMT state)
+ DWORD m_dwNodeCfg; // subindex from 0x1F81
+ WORD m_wFlags; // flags: CN is being accessed isochronously
+
+} tEplNmtMnuNodeInfo;
+
+typedef struct {
+ tEplNmtMnuNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID];
+ tEplTimerHdl m_TimerHdlNmtState; // timeout for stay in NMT state
+ unsigned int m_uiMandatorySlaveCount;
+ unsigned int m_uiSignalSlaveCount;
+ unsigned long m_ulStatusRequestDelay; // in [ms] (object 0x1006 * EPL_C_NMT_STATREQ_CYCLE)
+ unsigned long m_ulTimeoutReadyToOp; // in [ms] (object 0x1F89/5)
+ unsigned long m_ulTimeoutCheckCom; // in [ms] (object 0x1006 * MultiplexedCycleCount)
+ WORD m_wFlags; // global flags
+ DWORD m_dwNmtStartup; // object 0x1F80 NMT_StartUp_U32
+ tEplNmtMnuCbNodeEvent m_pfnCbNodeEvent;
+ tEplNmtMnuCbBootEvent m_pfnCbBootEvent;
+
+} tEplNmtMnuInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+static tEplNmtMnuInstance EplNmtMnuInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p);
+
+static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
+ tEplIdentResponse *
+ pIdentResponse_p);
+
+static tEplKernel PUBLIC EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
+ tEplStatusResponse *
+ pStatusResponse_p);
+
+static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
+ tEplNmtMnuNodeInfo * pNodeInfo_p,
+ tEplNmtState NodeNmtState_p,
+ WORD wErrorCode_p,
+ tEplNmtState LocalNmtState_p);
+
+static tEplKernel EplNmtMnuStartBootStep1(void);
+
+static tEplKernel EplNmtMnuStartBootStep2(void);
+
+static tEplKernel EplNmtMnuStartCheckCom(void);
+
+static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
+ tEplNmtMnuNodeInfo * pNodeInfo_p);
+
+static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
+ tEplNmtMnuNodeInfo * pNodeInfo_p);
+
+static tEplKernel EplNmtMnuStartNodes(void);
+
+static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
+ tEplNmtState NodeNmtState_p,
+ WORD wErrorCode_p,
+ tEplNmtMnuIntNodeEvent
+ NodeEvent_p);
+
+static tEplKernel EplNmtMnuReset(void);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuInit
+//
+// Description: init first instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
+ tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplNmtMnuAddInstance(pfnCbNodeEvent_p, pfnCbBootEvent_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuAddInstance
+//
+// Description: init other instances of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
+ tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // reset instance structure
+ EPL_MEMSET(&EplNmtMnuInstance_g, 0, sizeof(EplNmtMnuInstance_g));
+
+ if ((pfnCbNodeEvent_p == NULL) || (pfnCbBootEvent_p == NULL)) {
+ Ret = kEplNmtInvalidParam;
+ goto Exit;
+ }
+ EplNmtMnuInstance_g.m_pfnCbNodeEvent = pfnCbNodeEvent_p;
+ EplNmtMnuInstance_g.m_pfnCbBootEvent = pfnCbBootEvent_p;
+
+ // initialize StatusRequest delay
+ EplNmtMnuInstance_g.m_ulStatusRequestDelay = 5000L;
+
+ // register NmtMnResponse callback function
+ Ret =
+ EplDlluCalRegAsndService(kEplDllAsndNmtRequest,
+ EplNmtMnuCbNmtRequest,
+ kEplDllAsndFilterLocal);
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuDelInstance
+//
+// Description: delete instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplNmtMnuDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // deregister NmtMnResponse callback function
+ Ret =
+ EplDlluCalRegAsndService(kEplDllAsndNmtRequest, NULL,
+ kEplDllAsndFilterNone);
+
+ Ret = EplNmtMnuReset();
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuSendNmtCommandEx
+//
+// Description: sends the specified NMT command to the specified node.
+//
+// Parameters: uiNodeId_p = node ID to which the NMT command will be sent
+// NmtCommand_p = NMT command
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p,
+ tEplNmtCommand NmtCommand_p,
+ void *pNmtCommandData_p,
+ unsigned int uiDataSize_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplFrameInfo FrameInfo;
+ BYTE abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT];
+ tEplFrame *pFrame = (tEplFrame *) abBuffer;
+ BOOL fSoftDeleteNode = FALSE;
+
+ if ((uiNodeId_p == 0) || (uiNodeId_p > EPL_C_ADR_BROADCAST)) { // invalid node ID specified
+ Ret = kEplInvalidNodeId;
+ goto Exit;
+ }
+
+ if ((pNmtCommandData_p != NULL)
+ && (uiDataSize_p >
+ (EPL_C_DLL_MINSIZE_NMTCMDEXT - EPL_C_DLL_MINSIZE_NMTCMD))) {
+ Ret = kEplNmtInvalidParam;
+ goto Exit;
+ }
+ // $$$ d.k. may be check in future versions if the caller wants to perform prohibited state transitions
+ // the CN should not perform these transitions, but the expected NMT state will be changed and never fullfilled.
+
+ // build frame
+ EPL_MEMSET(pFrame, 0x00, sizeof(abBuffer));
+ AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (BYTE) uiNodeId_p);
+ AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId,
+ (BYTE) kEplDllAsndNmtCommand);
+ AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
+ m_le_bNmtCommandId, (BYTE) NmtCommand_p);
+ if ((pNmtCommandData_p != NULL) && (uiDataSize_p > 0)) { // copy command data to frame
+ EPL_MEMCPY(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
+ m_le_abNmtCommandData[0], pNmtCommandData_p,
+ uiDataSize_p);
+ }
+ // build info structure
+ FrameInfo.m_NetTime.m_dwNanoSec = 0;
+ FrameInfo.m_NetTime.m_dwSec = 0;
+ FrameInfo.m_pFrame = pFrame;
+ FrameInfo.m_uiFrameSize = sizeof(abBuffer);
+
+ // send NMT-Request
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ Ret = EplDlluCalAsyncSend(&FrameInfo, // pointer to frameinfo
+ kEplDllAsyncReqPrioNmt); // priority
+#endif
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ EPL_DBGLVL_NMTMN_TRACE2("NMTCmd(%02X->%02X)\n", NmtCommand_p,
+ uiNodeId_p);
+
+ switch (NmtCommand_p) {
+ case kEplNmtCmdStartNode:
+ case kEplNmtCmdEnterPreOperational2:
+ case kEplNmtCmdEnableReadyToOperate:
+ {
+ // nothing left to do,
+ // because any further processing is done
+ // when the NMT command is actually sent
+ goto Exit;
+ }
+
+ case kEplNmtCmdStopNode:
+ {
+ fSoftDeleteNode = TRUE;
+ break;
+ }
+
+ case kEplNmtCmdResetNode:
+ case kEplNmtCmdResetCommunication:
+ case kEplNmtCmdResetConfiguration:
+ case kEplNmtCmdSwReset:
+ {
+ break;
+ }
+
+ default:
+ goto Exit;
+ }
+
+ // remove CN from isochronous phase;
+ // This must be done here and not when NMT command is actually sent
+ // because it will be too late and may cause unwanted errors
+ if (uiNodeId_p != EPL_C_ADR_BROADCAST) {
+ if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
+ Ret = EplDlluCalDeleteNode(uiNodeId_p);
+ } else { // remove CN from isochronous phase softly
+ Ret = EplDlluCalSoftDeleteNode(uiNodeId_p);
+ }
+ } else { // do it for all active CNs
+ for (uiNodeId_p = 1;
+ uiNodeId_p <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
+ uiNodeId_p++) {
+ if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId_p)->
+ m_dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN |
+ EPL_NODEASSIGN_NODE_EXISTS)) != 0) {
+ if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
+ Ret = EplDlluCalDeleteNode(uiNodeId_p);
+ } else { // remove CN from isochronous phase softly
+ Ret =
+ EplDlluCalSoftDeleteNode
+ (uiNodeId_p);
+ }
+ }
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuSendNmtCommand
+//
+// Description: sends the specified NMT command to the specified node.
+//
+// Parameters: uiNodeId_p = node ID to which the NMT command will be sent
+// NmtCommand_p = NMT command
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p,
+ tEplNmtCommand NmtCommand_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ Ret = EplNmtMnuSendNmtCommandEx(uiNodeId_p, NmtCommand_p, NULL, 0);
+
+//Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuTriggerStateChange
+//
+// Description: triggers the specified node command for the specified node.
+//
+// Parameters: uiNodeId_p = node ID for which the node command will be executed
+// NodeCommand_p = node command
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p,
+ tEplNmtNodeCommand NodeCommand_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplNmtMnuIntNodeEvent NodeEvent;
+ tEplObdSize ObdSize;
+ BYTE bNmtState;
+ WORD wErrorCode = EPL_E_NO_ERROR;
+
+ if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) {
+ Ret = kEplInvalidNodeId;
+ goto Exit;
+ }
+
+ switch (NodeCommand_p) {
+ case kEplNmtNodeCommandBoot:
+ {
+ NodeEvent = kEplNmtMnuIntNodeEventBoot;
+ break;
+ }
+
+ case kEplNmtNodeCommandConfOk:
+ {
+ NodeEvent = kEplNmtMnuIntNodeEventConfigured;
+ break;
+ }
+
+ case kEplNmtNodeCommandConfErr:
+ {
+ NodeEvent = kEplNmtMnuIntNodeEventError;
+ wErrorCode = EPL_E_NMT_BPO1_CF_VERIFY;
+ break;
+ }
+
+ case kEplNmtNodeCommandConfReset:
+ {
+ NodeEvent = kEplNmtMnuIntNodeEventExecReset;
+ break;
+ }
+
+ default:
+ { // invalid node command
+ goto Exit;
+ }
+ }
+
+ // fetch current NMT state
+ ObdSize = 1;
+ Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtState, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
+ (tEplNmtState) (bNmtState |
+ EPL_NMT_TYPE_CS),
+ wErrorCode, NodeEvent);
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuCbNmtStateChange
+//
+// Description: callback function for NMT state changes
+//
+// Parameters: NmtStateChange_p = NMT state change event
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange
+ NmtStateChange_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // do work which must be done in that state
+ switch (NmtStateChange_p.m_NewNmtState) {
+ // EPL stack is not running
+/* case kEplNmtGsOff:
+ break;
+
+ // first init of the hardware
+ case kEplNmtGsInitialising:
+ break;
+
+ // init of the manufacturer-specific profile area and the
+ // standardised device profile area
+ case kEplNmtGsResetApplication:
+ {
+ break;
+ }
+
+ // init of the communication profile area
+ case kEplNmtGsResetCommunication:
+ {
+ break;
+ }
+*/
+ // build the configuration with infos from OD
+ case kEplNmtGsResetConfiguration:
+ {
+ DWORD dwTimeout;
+ tEplObdSize ObdSize;
+
+ // read object 0x1F80 NMT_StartUp_U32
+ ObdSize = 4;
+ Ret =
+ EplObduReadEntry(0x1F80, 0,
+ &EplNmtMnuInstance_g.
+ m_dwNmtStartup, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ // compute StatusReqDelay = object 0x1006 * EPL_C_NMT_STATREQ_CYCLE
+ ObdSize = sizeof(dwTimeout);
+ Ret = EplObduReadEntry(0x1006, 0, &dwTimeout, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ if (dwTimeout != 0L) {
+ EplNmtMnuInstance_g.m_ulStatusRequestDelay =
+ dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
+ if (EplNmtMnuInstance_g.
+ m_ulStatusRequestDelay == 0L) {
+ EplNmtMnuInstance_g.m_ulStatusRequestDelay = 1L; // at least 1 ms
+ }
+ // $$$ fetch and use MultiplexedCycleCount from OD
+ EplNmtMnuInstance_g.m_ulTimeoutCheckCom =
+ dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
+ if (EplNmtMnuInstance_g.m_ulTimeoutCheckCom ==
+ 0L) {
+ EplNmtMnuInstance_g.m_ulTimeoutCheckCom = 1L; // at least 1 ms
+ }
+ }
+ // fetch ReadyToOp Timeout from OD
+ ObdSize = sizeof(dwTimeout);
+ Ret = EplObduReadEntry(0x1F89, 5, &dwTimeout, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ if (dwTimeout != 0L) {
+ // convert [us] to [ms]
+ dwTimeout /= 1000L;
+ if (dwTimeout == 0L) {
+ dwTimeout = 1L; // at least 1 ms
+ }
+ EplNmtMnuInstance_g.m_ulTimeoutReadyToOp =
+ dwTimeout;
+ } else {
+ EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 0L;
+ }
+ break;
+ }
+/*
+ //-----------------------------------------------------------
+ // CN part of the state machine
+
+ // node liste for EPL-Frames and check timeout
+ case kEplNmtCsNotActive:
+ {
+ break;
+ }
+
+ // node process only async frames
+ case kEplNmtCsPreOperational1:
+ {
+ break;
+ }
+
+ // node process isochronus and asynchronus frames
+ case kEplNmtCsPreOperational2:
+ {
+ break;
+ }
+
+ // node should be configured und application is ready
+ case kEplNmtCsReadyToOperate:
+ {
+ break;
+ }
+
+ // normal work state
+ case kEplNmtCsOperational:
+ {
+ break;
+ }
+
+ // node stopped by MN
+ // -> only process asynchronus frames
+ case kEplNmtCsStopped:
+ {
+ break;
+ }
+
+ // no EPL cycle
+ // -> normal ethernet communication
+ case kEplNmtCsBasicEthernet:
+ {
+ break;
+ }
+*/
+ //-----------------------------------------------------------
+ // MN part of the state machine
+
+ // node listens for EPL-Frames and check timeout
+ case kEplNmtMsNotActive:
+ {
+ break;
+ }
+
+ // node processes only async frames
+ case kEplNmtMsPreOperational1:
+ {
+ DWORD dwTimeout;
+ tEplTimerArg TimerArg;
+ tEplObdSize ObdSize;
+ tEplEvent Event;
+
+ // clear global flags, e.g. reenable boot process
+ EplNmtMnuInstance_g.m_wFlags = 0;
+
+ // reset IdentResponses and running IdentRequests and StatusRequests
+ Ret = EplIdentuReset();
+ Ret = EplStatusuReset();
+
+ // reset timers
+ Ret = EplNmtMnuReset();
+
+ // 2008/11/18 d.k. reset internal node info is not necessary,
+ // because timer flags are important and other
+ // things are reset by EplNmtMnuStartBootStep1().
+/*
+ EPL_MEMSET(EplNmtMnuInstance_g.m_aNodeInfo,
+ 0,
+ sizeof (EplNmtMnuInstance_g.m_aNodeInfo));
+*/
+
+ // inform DLL about NMT state change,
+ // so that it can clear the asynchonous queues and start the reduced cycle
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkStartReducedCycle;
+ EPL_MEMSET(&Event.m_NetTime, 0x00,
+ sizeof(Event.m_NetTime));
+ Event.m_pArg = NULL;
+ Event.m_uiSize = 0;
+ Ret = EplEventuPost(&Event);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ // reset all nodes
+ // d.k.: skip this step if was just done before, e.g. because of a ResetNode command from a diagnostic node
+ if (NmtStateChange_p.m_NmtEvent ==
+ kEplNmtEventTimerMsPreOp1) {
+ BENCHMARK_MOD_07_TOGGLE(9);
+
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
+ EPL_C_ADR_BROADCAST,
+ kEplNmtCmdResetNode);
+
+ Ret =
+ EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
+ kEplNmtCmdResetNode);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ }
+ // start network scan
+ Ret = EplNmtMnuStartBootStep1();
+
+ // start timer for 0x1F89/2 MNTimeoutPreOp1_U32
+ ObdSize = sizeof(dwTimeout);
+ Ret = EplObduReadEntry(0x1F89, 2, &dwTimeout, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ if (dwTimeout != 0L) {
+ dwTimeout /= 1000L;
+ if (dwTimeout == 0L) {
+ dwTimeout = 1L; // at least 1 ms
+ }
+ TimerArg.m_EventSink = kEplEventSinkNmtMnu;
+ TimerArg.m_ulArg = 0;
+ Ret =
+ EplTimeruModifyTimerMs(&EplNmtMnuInstance_g.
+ m_TimerHdlNmtState,
+ dwTimeout, TimerArg);
+ }
+ break;
+ }
+
+ // node processes isochronous and asynchronous frames
+ case kEplNmtMsPreOperational2:
+ {
+ // add identified CNs to isochronous phase
+ // send EnableReadyToOp to all identified CNs
+ Ret = EplNmtMnuStartBootStep2();
+
+ // wait for NMT state change of CNs
+ break;
+ }
+
+ // node should be configured und application is ready
+ case kEplNmtMsReadyToOperate:
+ {
+ // check if PRes of CNs are OK
+ // d.k. that means wait CycleLength * MultiplexCycleCount (i.e. start timer)
+ // because Dllk checks PRes of CNs automatically in ReadyToOp
+ Ret = EplNmtMnuStartCheckCom();
+ break;
+ }
+
+ // normal work state
+ case kEplNmtMsOperational:
+ {
+ // send StartNode to CNs
+ // wait for NMT state change of CNs
+ Ret = EplNmtMnuStartNodes();
+ break;
+ }
+
+ // no EPL cycle
+ // -> normal ethernet communication
+ case kEplNmtMsBasicEthernet:
+ {
+ break;
+ }
+
+ default:
+ {
+// TRACE0("EplNmtMnuCbNmtStateChange(): unhandled NMT state\n");
+ }
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuCbCheckEvent
+//
+// Description: callback funktion for NMT events before they are actually executed.
+// The EPL API layer must forward NMT events from NmtCnu module.
+// This module will reject some NMT commands while MN.
+//
+// Parameters: NmtEvent_p = outstanding NMT event for approval
+//
+// Returns: tEplKernel = error code
+// kEplReject = reject the NMT event
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuProcessEvent
+//
+// Description: processes events from event queue
+//
+// Parameters: pEvent_p = pointer to event
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // process event
+ switch (pEvent_p->m_EventType) {
+ // timer event
+ case kEplEventTypeTimer:
+ {
+ tEplTimerEventArg *pTimerEventArg =
+ (tEplTimerEventArg *) pEvent_p->m_pArg;
+ unsigned int uiNodeId;
+
+ uiNodeId =
+ (unsigned int)(pTimerEventArg->
+ m_ulArg &
+ EPL_NMTMNU_TIMERARG_NODE_MASK);
+ if (uiNodeId != 0) {
+ tEplObdSize ObdSize;
+ BYTE bNmtState;
+ tEplNmtMnuNodeInfo *pNodeInfo;
+
+ pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId);
+
+ ObdSize = 1;
+ Ret =
+ EplObduReadEntry(0x1F8E, uiNodeId,
+ &bNmtState, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+
+ if ((pTimerEventArg->
+ m_ulArg & EPL_NMTMNU_TIMERARG_IDENTREQ) !=
+ 0L) {
+ if ((pNodeInfo->
+ m_wFlags &
+ EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
+ != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
+ // but not the current timer
+ // so discard it
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (kEplNmtMnuIntNodeEventTimerIdentReq,
+ uiNodeId,
+ ((pNodeInfo->
+ m_NodeState << 8)
+ | 0xFF));
+
+ break;
+ }
+/*
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerIdentReq,
+ uiNodeId,
+ ((pNodeInfo->m_NodeState << 8)
+ | 0x80
+ | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
+ | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
+*/
+ Ret =
+ EplNmtMnuProcessInternalEvent
+ (uiNodeId,
+ (tEplNmtState) (bNmtState |
+ EPL_NMT_TYPE_CS),
+ EPL_E_NO_ERROR,
+ kEplNmtMnuIntNodeEventTimerIdentReq);
+ }
+
+ else if ((pTimerEventArg->
+ m_ulArg & EPL_NMTMNU_TIMERARG_STATREQ)
+ != 0L) {
+ if ((pNodeInfo->
+ m_wFlags &
+ EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
+ != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
+ // but not the current timer
+ // so discard it
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (kEplNmtMnuIntNodeEventTimerStatReq,
+ uiNodeId,
+ ((pNodeInfo->
+ m_NodeState << 8)
+ | 0xFF));
+
+ break;
+ }
+/*
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
+ uiNodeId,
+ ((pNodeInfo->m_NodeState << 8)
+ | 0x80
+ | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
+ | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
+*/
+ Ret =
+ EplNmtMnuProcessInternalEvent
+ (uiNodeId,
+ (tEplNmtState) (bNmtState |
+ EPL_NMT_TYPE_CS),
+ EPL_E_NO_ERROR,
+ kEplNmtMnuIntNodeEventTimerStatReq);
+ }
+
+ else if ((pTimerEventArg->
+ m_ulArg &
+ EPL_NMTMNU_TIMERARG_STATE_MON) !=
+ 0L) {
+ if ((pNodeInfo->
+ m_wFlags &
+ EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
+ != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
+ // but not the current timer
+ // so discard it
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (kEplNmtMnuIntNodeEventTimerStateMon,
+ uiNodeId,
+ ((pNodeInfo->
+ m_NodeState << 8)
+ | 0xFF));
+
+ break;
+ }
+/*
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
+ uiNodeId,
+ ((pNodeInfo->m_NodeState << 8)
+ | 0x80
+ | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
+ | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
+*/
+ Ret =
+ EplNmtMnuProcessInternalEvent
+ (uiNodeId,
+ (tEplNmtState) (bNmtState |
+ EPL_NMT_TYPE_CS),
+ EPL_E_NO_ERROR,
+ kEplNmtMnuIntNodeEventTimerStateMon);
+ }
+
+ else if ((pTimerEventArg->
+ m_ulArg & EPL_NMTMNU_TIMERARG_LONGER)
+ != 0L) {
+ if ((pNodeInfo->
+ m_wFlags &
+ EPL_NMTMNU_NODE_FLAG_COUNT_LONGER)
+ != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO)) { // this is an old (already deleted or modified) timer
+ // but not the current timer
+ // so discard it
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (kEplNmtMnuIntNodeEventTimerLonger,
+ uiNodeId,
+ ((pNodeInfo->
+ m_NodeState << 8)
+ | 0xFF));
+
+ break;
+ }
+/*
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerLonger,
+ uiNodeId,
+ ((pNodeInfo->m_NodeState << 8)
+ | 0x80
+ | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) >> 6)
+ | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO) >> 8)));
+*/
+ Ret =
+ EplNmtMnuProcessInternalEvent
+ (uiNodeId,
+ (tEplNmtState) (bNmtState |
+ EPL_NMT_TYPE_CS),
+ EPL_E_NO_ERROR,
+ kEplNmtMnuIntNodeEventTimerLonger);
+ }
+
+ } else { // global timer event
+ }
+ break;
+ }
+
+ case kEplEventTypeHeartbeat:
+ {
+ tEplHeartbeatEvent *pHeartbeatEvent =
+ (tEplHeartbeatEvent *) pEvent_p->m_pArg;
+
+ Ret =
+ EplNmtMnuProcessInternalEvent(pHeartbeatEvent->
+ m_uiNodeId,
+ pHeartbeatEvent->
+ m_NmtState,
+ pHeartbeatEvent->
+ m_wErrorCode,
+ kEplNmtMnuIntNodeEventHeartbeat);
+ break;
+ }
+
+ case kEplEventTypeNmtMnuNmtCmdSent:
+ {
+ tEplFrame *pFrame = (tEplFrame *) pEvent_p->m_pArg;
+ unsigned int uiNodeId;
+ tEplNmtCommand NmtCommand;
+ BYTE bNmtState;
+
+ uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
+ NmtCommand =
+ (tEplNmtCommand) AmiGetByteFromLe(&pFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_NmtCommandService.
+ m_le_bNmtCommandId);
+
+ switch (NmtCommand) {
+ case kEplNmtCmdStartNode:
+ bNmtState =
+ (BYTE) (kEplNmtCsOperational & 0xFF);
+ break;
+
+ case kEplNmtCmdStopNode:
+ bNmtState = (BYTE) (kEplNmtCsStopped & 0xFF);
+ break;
+
+ case kEplNmtCmdEnterPreOperational2:
+ bNmtState =
+ (BYTE) (kEplNmtCsPreOperational2 & 0xFF);
+ break;
+
+ case kEplNmtCmdEnableReadyToOperate:
+ // d.k. do not change expected node state, because of DS 1.0.0 7.3.1.2.1 Plain NMT State Command
+ // and because node may not change NMT state within EPL_C_NMT_STATE_TOLERANCE
+ bNmtState =
+ (BYTE) (kEplNmtCsPreOperational2 & 0xFF);
+ break;
+
+ case kEplNmtCmdResetNode:
+ case kEplNmtCmdResetCommunication:
+ case kEplNmtCmdResetConfiguration:
+ case kEplNmtCmdSwReset:
+ bNmtState = (BYTE) (kEplNmtCsNotActive & 0xFF);
+ // EplNmtMnuProcessInternalEvent() sets internal node state to kEplNmtMnuNodeStateUnknown
+ // after next unresponded IdentRequest/StatusRequest
+ break;
+
+ default:
+ goto Exit;
+ }
+
+ // process as internal event which update expected NMT state in OD
+ if (uiNodeId != EPL_C_ADR_BROADCAST) {
+ Ret = EplNmtMnuProcessInternalEvent(uiNodeId,
+ (tEplNmtState)
+ (bNmtState |
+ EPL_NMT_TYPE_CS),
+ 0,
+ kEplNmtMnuIntNodeEventNmtCmdSent);
+
+ } else { // process internal event for all active nodes (except myself)
+
+ for (uiNodeId = 1;
+ uiNodeId <=
+ tabentries(EplNmtMnuInstance_g.
+ m_aNodeInfo); uiNodeId++) {
+ if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId)->
+ m_dwNodeCfg &
+ (EPL_NODEASSIGN_NODE_IS_CN |
+ EPL_NODEASSIGN_NODE_EXISTS)) !=
+ 0) {
+ Ret =
+ EplNmtMnuProcessInternalEvent
+ (uiNodeId,
+ (tEplNmtState) (bNmtState |
+ EPL_NMT_TYPE_CS),
+ 0,
+ kEplNmtMnuIntNodeEventNmtCmdSent);
+
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplNmtInvalidEvent;
+ }
+
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuGetRunningTimerStatReq
+//
+// Description: returns a bit field with running StatReq timers
+// just for debugging purposes
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int
+ *puiMandatorySlaveCount_p,
+ unsigned int
+ *puiSignalSlaveCount_p,
+ WORD * pwFlags_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if ((puiMandatorySlaveCount_p == NULL)
+ || (puiSignalSlaveCount_p == NULL)
+ || (pwFlags_p == NULL)) {
+ Ret = kEplNmtInvalidParam;
+ goto Exit;
+ }
+
+ *puiMandatorySlaveCount_p = EplNmtMnuInstance_g.m_uiMandatorySlaveCount;
+ *puiSignalSlaveCount_p = EplNmtMnuInstance_g.m_uiSignalSlaveCount;
+ *pwFlags_p = EplNmtMnuInstance_g.m_wFlags;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuGetRunningTimerStatReq
+//
+// Description: returns a bit field with running StatReq timers
+// just for debugging purposes
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+/*
+DWORD EplNmtMnuGetRunningTimerStatReq(void)
+{
+tEplKernel Ret = kEplSuccessful;
+unsigned int uiIndex;
+tEplNmtMnuNodeInfo* pNodeInfo;
+
+ pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
+ for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++)
+ {
+ if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateConfigured)
+ {
+ // reset flag "scanned once"
+ pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_SCANNED;
+
+ Ret = EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
+ if (Ret != kEplSuccessful)
+ {
+ goto Exit;
+ }
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
+ // signal slave counter shall be decremented if StatusRequest was sent once to a CN
+ // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
+ }
+ }
+
+Exit:
+ return Ret;
+}
+*/
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuCbNmtRequest
+//
+// Description: callback funktion for NmtRequest
+//
+// Parameters: pFrameInfo_p = Frame with the NmtRequest
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // $$$ perform NMTRequest
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuCbIdentResponse
+//
+// Description: callback funktion for IdentResponse
+//
+// Parameters: uiNodeId_p = node ID for which IdentReponse was received
+// pIdentResponse_p = pointer to IdentResponse
+// is NULL if node did not answer
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
+ tEplIdentResponse *
+ pIdentResponse_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (pIdentResponse_p == NULL) { // node did not answer
+ Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_IDENT_RES, // was EPL_E_NO_ERROR
+ kEplNmtMnuIntNodeEventNoIdentResponse);
+ } else { // node answered IdentRequest
+ tEplObdSize ObdSize;
+ DWORD dwDevType;
+ WORD wErrorCode = EPL_E_NO_ERROR;
+ tEplNmtState NmtState =
+ (tEplNmtState) (AmiGetByteFromLe
+ (&pIdentResponse_p->
+ m_le_bNmtStatus) | EPL_NMT_TYPE_CS);
+
+ // check IdentResponse $$$ move to ProcessIntern, because this function may be called also if CN
+
+ // check DeviceType (0x1F84)
+ ObdSize = 4;
+ Ret =
+ EplObduReadEntry(0x1F84, uiNodeId_p, &dwDevType, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ if (dwDevType != 0L) { // actually compare it with DeviceType from IdentResponse
+ if (AmiGetDwordFromLe(&pIdentResponse_p->m_le_dwDeviceType) != dwDevType) { // wrong DeviceType
+ NmtState = kEplNmtCsNotActive;
+ wErrorCode = EPL_E_NMT_BPO1_DEVICE_TYPE;
+ }
+ }
+
+ Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
+ NmtState,
+ wErrorCode,
+ kEplNmtMnuIntNodeEventIdentResponse);
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuCbStatusResponse
+//
+// Description: callback funktion for StatusResponse
+//
+// Parameters: uiNodeId_p = node ID for which IdentReponse was received
+// pIdentResponse_p = pointer to IdentResponse
+// is NULL if node did not answer
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
+ tEplStatusResponse *
+ pStatusResponse_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (pStatusResponse_p == NULL) { // node did not answer
+ Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_STATUS_RES, // was EPL_E_NO_ERROR
+ kEplNmtMnuIntNodeEventNoStatusResponse);
+ } else { // node answered StatusRequest
+ Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
+ (tEplNmtState)
+ (AmiGetByteFromLe
+ (&pStatusResponse_p->
+ m_le_bNmtStatus) |
+ EPL_NMT_TYPE_CS),
+ EPL_E_NO_ERROR,
+ kEplNmtMnuIntNodeEventStatusResponse);
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuStartBootStep1
+//
+// Description: starts BootStep1
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuStartBootStep1(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiSubIndex;
+ unsigned int uiLocalNodeId;
+ DWORD dwNodeCfg;
+ tEplObdSize ObdSize;
+
+ // $$$ d.k.: save current time for 0x1F89/2 MNTimeoutPreOp1_U32
+
+ // start network scan
+ EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
+ // check 0x1F81
+ uiLocalNodeId = EplObduGetNodeId();
+ for (uiSubIndex = 1; uiSubIndex <= 254; uiSubIndex++) {
+ ObdSize = 4;
+ Ret =
+ EplObduReadEntry(0x1F81, uiSubIndex, &dwNodeCfg, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ if (uiSubIndex != uiLocalNodeId) {
+ // reset flags "not scanned" and "isochronous"
+ EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags &=
+ ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON |
+ EPL_NMTMNU_NODE_FLAG_NOT_SCANNED);
+
+ if (uiSubIndex == EPL_C_ADR_DIAG_DEF_NODE_ID) { // diagnostic node must be scanned by MN in any case
+ dwNodeCfg |=
+ (EPL_NODEASSIGN_NODE_IS_CN |
+ EPL_NODEASSIGN_NODE_EXISTS);
+ // and it must be isochronously accessed
+ dwNodeCfg &= ~EPL_NODEASSIGN_ASYNCONLY_NODE;
+ }
+ // save node config in local node info structure
+ EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_dwNodeCfg =
+ dwNodeCfg;
+ EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_NodeState =
+ kEplNmtMnuNodeStateUnknown;
+
+ if ((dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // node is configured as CN
+ // identify the node
+ Ret =
+ EplIdentuRequestIdentResponse(uiSubIndex,
+ EplNmtMnuCbIdentResponse);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // set flag "not scanned"
+ EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags |=
+ EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
+ // signal slave counter shall be decremented if IdentRequest was sent once to a CN
+
+ if ((dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
+ EplNmtMnuInstance_g.
+ m_uiMandatorySlaveCount++;
+ // mandatory slave counter shall be decremented if mandatory CN was configured successfully
+ }
+ }
+ } else { // subindex of MN
+ if ((dwNodeCfg & (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // MN shall send PRes
+ tEplDllNodeInfo DllNodeInfo;
+
+ EPL_MEMSET(&DllNodeInfo, 0,
+ sizeof(DllNodeInfo));
+ DllNodeInfo.m_uiNodeId = uiLocalNodeId;
+
+ Ret = EplDlluCalAddNode(&DllNodeInfo);
+ }
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuStartBootStep2
+//
+// Description: starts BootStep2.
+// That means add nodes to isochronous phase and send
+// NMT EnableReadyToOp.
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuStartBootStep2(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiIndex;
+ tEplNmtMnuNodeInfo *pNodeInfo;
+
+ if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
+ // add nodes to isochronous phase and send NMT EnableReadyToOp
+ EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
+ // reset flag that application was informed about possible state change
+ EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
+
+ pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
+ for (uiIndex = 1;
+ uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
+ uiIndex++, pNodeInfo++) {
+ if (pNodeInfo->m_NodeState ==
+ kEplNmtMnuNodeStateConfigured) {
+ Ret =
+ EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // set flag "not scanned"
+ pNodeInfo->m_wFlags |=
+ EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
+ // signal slave counter shall be decremented if StatusRequest was sent once to a CN
+
+ if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
+ EplNmtMnuInstance_g.
+ m_uiMandatorySlaveCount++;
+ }
+ // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
+ }
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuNodeBootStep2
+//
+// Description: starts BootStep2 for the specified node.
+// This means the CN is added to isochronous phase if not
+// async-only and it gets the NMT command EnableReadyToOp.
+// The CN must be in node state Configured, when it enters
+// BootStep2. When BootStep2 finishes, the CN is in node state
+// ReadyToOp.
+// If TimeoutReadyToOp in object 0x1F89/5 is configured,
+// TimerHdlLonger will be started with this timeout.
+//
+// Parameters: uiNodeId_p = node ID
+// pNodeInfo_p = pointer to internal node info structure
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
+ tEplNmtMnuNodeInfo * pNodeInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplDllNodeInfo DllNodeInfo;
+ DWORD dwNodeCfg;
+ tEplObdSize ObdSize;
+ tEplTimerArg TimerArg;
+
+ dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
+ if ((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0) { // add node to isochronous phase
+ DllNodeInfo.m_uiNodeId = uiNodeId_p;
+ ObdSize = 4;
+ Ret =
+ EplObduReadEntry(0x1F92, uiNodeId_p,
+ &DllNodeInfo.m_dwPresTimeout, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = 2;
+ Ret =
+ EplObduReadEntry(0x1F8B, uiNodeId_p,
+ &DllNodeInfo.m_wPreqPayloadLimit,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = 2;
+ Ret =
+ EplObduReadEntry(0x1F8D, uiNodeId_p,
+ &DllNodeInfo.m_wPresPayloadLimit,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ pNodeInfo_p->m_wFlags |= EPL_NMTMNU_NODE_FLAG_ISOCHRON;
+
+ Ret = EplDlluCalAddNode(&DllNodeInfo);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ }
+
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
+ uiNodeId_p,
+ kEplNmtCmdEnableReadyToOperate);
+
+ Ret =
+ EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdEnableReadyToOperate);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if (EplNmtMnuInstance_g.m_ulTimeoutReadyToOp != 0L) { // start timer
+ // when the timer expires the CN must be ReadyToOp
+ EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
+ TimerArg);
+// TimerArg.m_EventSink = kEplEventSinkNmtMnu;
+// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
+ Ret =
+ EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
+ EplNmtMnuInstance_g.
+ m_ulTimeoutReadyToOp, TimerArg);
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuStartCheckCom
+//
+// Description: starts CheckCommunication
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuStartCheckCom(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiIndex;
+ tEplNmtMnuNodeInfo *pNodeInfo;
+
+ if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
+ // wait some time and check that no communication error occurs
+ EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
+ // reset flag that application was informed about possible state change
+ EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
+
+ pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
+ for (uiIndex = 1;
+ uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
+ uiIndex++, pNodeInfo++) {
+ if (pNodeInfo->m_NodeState ==
+ kEplNmtMnuNodeStateReadyToOp) {
+ Ret = EplNmtMnuNodeCheckCom(uiIndex, pNodeInfo);
+ if (Ret == kEplReject) { // timer was started
+ // wait until it expires
+ if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
+ EplNmtMnuInstance_g.
+ m_uiMandatorySlaveCount++;
+ }
+ } else if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // set flag "not scanned"
+ pNodeInfo->m_wFlags |=
+ EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
+ // signal slave counter shall be decremented if timeout elapsed and regardless of an error
+ // mandatory slave counter shall be decremented if timeout elapsed and no error occured
+ }
+ }
+ }
+
+ Ret = kEplSuccessful;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuNodeCheckCom
+//
+// Description: checks communication of the specified node.
+// That means wait some time and if no error occured everything
+// is OK.
+//
+// Parameters: uiNodeId_p = node ID
+// pNodeInfo_p = pointer to internal node info structure
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
+ tEplNmtMnuNodeInfo * pNodeInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ DWORD dwNodeCfg;
+ tEplTimerArg TimerArg;
+
+ dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
+ if (((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0)
+ && (EplNmtMnuInstance_g.m_ulTimeoutCheckCom != 0L)) { // CN is not async-only and timeout for CheckCom was set
+
+ // check communication,
+ // that means wait some time and if no error occured everything is OK;
+
+ // start timer (when the timer expires the CN must be still ReadyToOp)
+ EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
+ TimerArg);
+// TimerArg.m_EventSink = kEplEventSinkNmtMnu;
+// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
+ Ret =
+ EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
+ EplNmtMnuInstance_g.
+ m_ulTimeoutCheckCom, TimerArg);
+
+ // update mandatory slave counter, because timer was started
+ if (Ret == kEplSuccessful) {
+ Ret = kEplReject;
+ }
+ } else { // timer was not started
+ // assume everything is OK
+ pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateComChecked;
+ }
+
+//Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuStartNodes
+//
+// Description: really starts all nodes which are ReadyToOp and CheckCom did not fail
+//
+// Parameters: (none)
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuStartNodes(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiIndex;
+ tEplNmtMnuNodeInfo *pNodeInfo;
+
+ if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
+ // send NMT command Start Node
+ EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
+ // reset flag that application was informed about possible state change
+ EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
+
+ pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
+ for (uiIndex = 1;
+ uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
+ uiIndex++, pNodeInfo++) {
+ if (pNodeInfo->m_NodeState ==
+ kEplNmtMnuNodeStateComChecked) {
+ if ((EplNmtMnuInstance_g.
+ m_dwNmtStartup & EPL_NMTST_STARTALLNODES)
+ == 0) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
+ uiIndex,
+ kEplNmtCmdStartNode);
+
+ Ret =
+ EplNmtMnuSendNmtCommand(uiIndex,
+ kEplNmtCmdStartNode);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+
+ if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
+ EplNmtMnuInstance_g.
+ m_uiMandatorySlaveCount++;
+ }
+ // set flag "not scanned"
+ pNodeInfo->m_wFlags |=
+ EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
+ // signal slave counter shall be decremented if StatusRequest was sent once to a CN
+ // mandatory slave counter shall be decremented if mandatory CN is OPERATIONAL
+ }
+ }
+
+ // $$$ inform application if EPL_NMTST_NO_STARTNODE is set
+
+ if ((EplNmtMnuInstance_g.
+ m_dwNmtStartup & EPL_NMTST_STARTALLNODES) != 0) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, EPL_C_ADR_BROADCAST,
+ kEplNmtCmdStartNode);
+
+ Ret =
+ EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
+ kEplNmtCmdStartNode);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuProcessInternalEvent
+//
+// Description: processes internal node events
+//
+// Parameters: uiNodeId_p = node ID
+// NodeNmtState_p = NMT state of CN
+// NodeEvent_p = occured events
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
+ tEplNmtState NodeNmtState_p,
+ WORD wErrorCode_p,
+ tEplNmtMnuIntNodeEvent
+ NodeEvent_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplNmtState NmtState;
+ tEplNmtMnuNodeInfo *pNodeInfo;
+ tEplTimerArg TimerArg;
+
+ pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId_p);
+ NmtState = EplNmtuGetNmtState();
+ if (NmtState <= kEplNmtMsNotActive) { // MN is not active
+ goto Exit;
+ }
+
+ switch (NodeEvent_p) {
+ case kEplNmtMnuIntNodeEventIdentResponse:
+ {
+ BYTE bNmtState;
+
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
+ uiNodeId_p,
+ pNodeInfo->m_NodeState);
+
+ if (pNodeInfo->m_NodeState !=
+ kEplNmtMnuNodeStateResetConf) {
+ pNodeInfo->m_NodeState =
+ kEplNmtMnuNodeStateIdentified;
+ }
+ // reset flags ISOCHRON and NMT_CMD_ISSUED
+ pNodeInfo->m_wFlags &= ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON
+ |
+ EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED);
+
+ if ((NmtState == kEplNmtMsPreOperational1)
+ &&
+ ((pNodeInfo->
+ m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
+ 0)) {
+ // decrement only signal slave count
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
+ pNodeInfo->m_wFlags &=
+ ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ }
+ // update object 0x1F8F NMT_MNNodeExpState_AU8 to PreOp1 (even if local state >= PreOp2)
+ bNmtState = (BYTE) (kEplNmtCsPreOperational1 & 0xFF);
+ Ret =
+ EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
+ 1);
+
+ // check NMT state of CN
+ Ret =
+ EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
+ NodeNmtState_p, wErrorCode_p,
+ NmtState);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+ // request StatusResponse immediately,
+ // because we want a fast boot-up of CNs
+ Ret =
+ EplStatusuRequestStatusResponse(uiNodeId_p,
+ EplNmtMnuCbStatusResponse);
+ if (Ret != kEplSuccessful) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
+ uiNodeId_p,
+ Ret);
+
+ if (Ret == kEplInvalidOperation) { // the only situation when this should happen is, when
+ // StatusResponse was already requested from within
+ // the StatReq timer event.
+ // so ignore this error.
+ Ret = kEplSuccessful;
+ } else {
+ break;
+ }
+ }
+
+ if (pNodeInfo->m_NodeState !=
+ kEplNmtMnuNodeStateResetConf) {
+ // inform application
+ Ret =
+ EplNmtMnuInstance_g.
+ m_pfnCbNodeEvent(uiNodeId_p,
+ kEplNmtNodeEventFound,
+ NodeNmtState_p,
+ EPL_E_NO_ERROR,
+ (pNodeInfo->
+ m_dwNodeCfg &
+ EPL_NODEASSIGN_MANDATORY_CN)
+ != 0);
+ if (Ret == kEplReject) { // interrupt boot process on user request
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (NodeEvent_p, uiNodeId_p,
+ ((pNodeInfo->m_NodeState << 8)
+ | Ret));
+
+ Ret = kEplSuccessful;
+ break;
+ } else if (Ret != kEplSuccessful) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (NodeEvent_p, uiNodeId_p,
+ ((pNodeInfo->m_NodeState << 8)
+ | Ret));
+
+ break;
+ }
+ }
+ // continue BootStep1
+ }
+
+ case kEplNmtMnuIntNodeEventBoot:
+ {
+
+ // $$$ check identification (vendor ID, product code, revision no, serial no)
+
+ if (pNodeInfo->m_NodeState ==
+ kEplNmtMnuNodeStateIdentified) {
+ // $$$ check software
+
+ // check/start configuration
+ // inform application
+ Ret =
+ EplNmtMnuInstance_g.
+ m_pfnCbNodeEvent(uiNodeId_p,
+ kEplNmtNodeEventCheckConf,
+ NodeNmtState_p,
+ EPL_E_NO_ERROR,
+ (pNodeInfo->
+ m_dwNodeCfg &
+ EPL_NODEASSIGN_MANDATORY_CN)
+ != 0);
+ if (Ret == kEplReject) { // interrupt boot process on user request
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (kEplNmtMnuIntNodeEventBoot,
+ uiNodeId_p,
+ ((pNodeInfo->m_NodeState << 8)
+ | Ret));
+
+ Ret = kEplSuccessful;
+ break;
+ } else if (Ret != kEplSuccessful) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (kEplNmtMnuIntNodeEventBoot,
+ uiNodeId_p,
+ ((pNodeInfo->m_NodeState << 8)
+ | Ret));
+
+ break;
+ }
+ } else if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) { // wrong CN state
+ // ignore event
+ break;
+ }
+ // $$$ d.k.: currently we assume configuration is OK
+
+ // continue BootStep1
+ }
+
+ case kEplNmtMnuIntNodeEventConfigured:
+ {
+ if ((pNodeInfo->m_NodeState !=
+ kEplNmtMnuNodeStateIdentified)
+ && (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf)) { // wrong CN state
+ // ignore event
+ break;
+ }
+
+ pNodeInfo->m_NodeState = kEplNmtMnuNodeStateConfigured;
+
+ if (NmtState == kEplNmtMsPreOperational1) {
+ if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // decrement mandatory CN counter
+ EplNmtMnuInstance_g.
+ m_uiMandatorySlaveCount--;
+ }
+ } else {
+ // put optional node to next step (BootStep2)
+ Ret =
+ EplNmtMnuNodeBootStep2(uiNodeId_p,
+ pNodeInfo);
+ }
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventNoIdentResponse:
+ {
+ if ((NmtState == kEplNmtMsPreOperational1)
+ &&
+ ((pNodeInfo->
+ m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
+ 0)) {
+ // decrement only signal slave count
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
+ pNodeInfo->m_wFlags &=
+ ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ }
+
+ if (pNodeInfo->m_NodeState !=
+ kEplNmtMnuNodeStateResetConf) {
+ pNodeInfo->m_NodeState =
+ kEplNmtMnuNodeStateUnknown;
+ }
+ // $$$ d.k. check start time for 0x1F89/2 MNTimeoutPreOp1_U32
+ // $$$ d.k. check individual timeout 0x1F89/6 MNIdentificationTimeout_U32
+ // if mandatory node and timeout elapsed -> halt boot procedure
+ // trigger IdentRequest again (if >= PreOp2, after delay)
+ if (NmtState >= kEplNmtMsPreOperational2) { // start timer
+ EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
+ (pNodeInfo, uiNodeId_p, TimerArg);
+// TimerArg.m_EventSink = kEplEventSinkNmtMnu;
+// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p;
+/*
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventNoIdentResponse,
+ uiNodeId_p,
+ ((pNodeInfo->m_NodeState << 8)
+ | 0x80
+ | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
+ | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
+*/
+ Ret =
+ EplTimeruModifyTimerMs(&pNodeInfo->
+ m_TimerHdlStatReq,
+ EplNmtMnuInstance_g.
+ m_ulStatusRequestDelay,
+ TimerArg);
+ } else { // trigger IdentRequest immediately
+ Ret =
+ EplIdentuRequestIdentResponse(uiNodeId_p,
+ EplNmtMnuCbIdentResponse);
+ }
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventStatusResponse:
+ {
+ if ((NmtState >= kEplNmtMsPreOperational2)
+ &&
+ ((pNodeInfo->
+ m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
+ 0)) {
+ // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
+ pNodeInfo->m_wFlags &=
+ ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ }
+ // check NMT state of CN
+ Ret =
+ EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
+ NodeNmtState_p, wErrorCode_p,
+ NmtState);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+
+ if (NmtState == kEplNmtMsPreOperational1) {
+ // request next StatusResponse immediately
+ Ret =
+ EplStatusuRequestStatusResponse(uiNodeId_p,
+ EplNmtMnuCbStatusResponse);
+ if (Ret != kEplSuccessful) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (NodeEvent_p, uiNodeId_p, Ret);
+ }
+
+ } else if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_ISOCHRON) == 0) { // start timer
+ // not isochronously accessed CN (e.g. async-only or stopped CN)
+ EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo,
+ uiNodeId_p,
+ TimerArg);
+// TimerArg.m_EventSink = kEplEventSinkNmtMnu;
+// TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p;
+/*
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventStatusResponse,
+ uiNodeId_p,
+ ((pNodeInfo->m_NodeState << 8)
+ | 0x80
+ | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
+ | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
+*/
+ Ret =
+ EplTimeruModifyTimerMs(&pNodeInfo->
+ m_TimerHdlStatReq,
+ EplNmtMnuInstance_g.
+ m_ulStatusRequestDelay,
+ TimerArg);
+ }
+
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventNoStatusResponse:
+ {
+ // function CheckNmtState sets node state to unknown if necessary
+/*
+ if ((NmtState >= kEplNmtMsPreOperational2)
+ && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
+ {
+ // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
+ pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ }
+*/
+ // check NMT state of CN
+ Ret =
+ EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
+ NodeNmtState_p, wErrorCode_p,
+ NmtState);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventError:
+ { // currently only issued on kEplNmtNodeCommandConfErr
+
+ if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
+ // ignore event
+ break;
+ }
+ // check NMT state of CN
+ Ret =
+ EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
+ kEplNmtCsNotActive,
+ wErrorCode_p, NmtState);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventExecReset:
+ {
+ if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
+ // ignore event
+ break;
+ }
+
+ pNodeInfo->m_NodeState = kEplNmtMnuNodeStateResetConf;
+
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
+ uiNodeId_p,
+ (((NodeNmtState_p &
+ 0xFF) << 8)
+ |
+ kEplNmtCmdResetConfiguration));
+
+ // send NMT reset configuration to CN for activation of configuration
+ Ret =
+ EplNmtMnuSendNmtCommand(uiNodeId_p,
+ kEplNmtCmdResetConfiguration);
+
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventHeartbeat:
+ {
+/*
+ if ((NmtState >= kEplNmtMsPreOperational2)
+ && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
+ {
+ // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
+ pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ }
+*/
+ // check NMT state of CN
+ Ret =
+ EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
+ NodeNmtState_p, wErrorCode_p,
+ NmtState);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventTimerIdentReq:
+ {
+ EPL_DBGLVL_NMTMN_TRACE1
+ ("TimerStatReq->IdentReq(%02X)\n", uiNodeId_p);
+ // trigger IdentRequest again
+ Ret =
+ EplIdentuRequestIdentResponse(uiNodeId_p,
+ EplNmtMnuCbIdentResponse);
+ if (Ret != kEplSuccessful) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
+ uiNodeId_p,
+ (((NodeNmtState_p & 0xFF) << 8)
+ | Ret));
+ if (Ret == kEplInvalidOperation) { // this can happen because of a bug in EplTimeruLinuxKernel.c
+ // so ignore this error.
+ Ret = kEplSuccessful;
+ }
+ }
+
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventTimerStateMon:
+ {
+ // reset NMT state change flag
+ // because from now on the CN must have the correct NMT state
+ pNodeInfo->m_wFlags &=
+ ~EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
+
+ // continue with normal StatReq processing
+ }
+
+ case kEplNmtMnuIntNodeEventTimerStatReq:
+ {
+ EPL_DBGLVL_NMTMN_TRACE1("TimerStatReq->StatReq(%02X)\n",
+ uiNodeId_p);
+ // request next StatusResponse
+ Ret =
+ EplStatusuRequestStatusResponse(uiNodeId_p,
+ EplNmtMnuCbStatusResponse);
+ if (Ret != kEplSuccessful) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
+ uiNodeId_p,
+ (((NodeNmtState_p & 0xFF) << 8)
+ | Ret));
+ if (Ret == kEplInvalidOperation) { // the only situation when this should happen is, when
+ // StatusResponse was already requested while processing
+ // event IdentResponse.
+ // so ignore this error.
+ Ret = kEplSuccessful;
+ }
+ }
+
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventTimerLonger:
+ {
+ switch (pNodeInfo->m_NodeState) {
+ case kEplNmtMnuNodeStateConfigured:
+ { // node should be ReadyToOp but it is not
+
+ // check NMT state which shall be intentionally wrong, so that ERROR_TREATMENT will be started
+ Ret =
+ EplNmtMnuCheckNmtState(uiNodeId_p,
+ pNodeInfo,
+ kEplNmtCsNotActive,
+ EPL_E_NMT_BPO2,
+ NmtState);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+
+ break;
+ }
+
+ case kEplNmtMnuNodeStateReadyToOp:
+ { // CheckCom finished successfully
+
+ pNodeInfo->m_NodeState =
+ kEplNmtMnuNodeStateComChecked;
+
+ if ((pNodeInfo->
+ m_wFlags &
+ EPL_NMTMNU_NODE_FLAG_NOT_SCANNED)
+ != 0) {
+ // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
+ EplNmtMnuInstance_g.
+ m_uiSignalSlaveCount--;
+ pNodeInfo->m_wFlags &=
+ ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ }
+
+ if ((pNodeInfo->
+ m_dwNodeCfg &
+ EPL_NODEASSIGN_MANDATORY_CN) !=
+ 0) {
+ // decrement mandatory slave counter
+ EplNmtMnuInstance_g.
+ m_uiMandatorySlaveCount--;
+ }
+ if (NmtState != kEplNmtMsReadyToOperate) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE
+ (NodeEvent_p, uiNodeId_p,
+ (((NodeNmtState_p & 0xFF)
+ << 8)
+ | kEplNmtCmdStartNode));
+
+ // start optional CN
+ Ret =
+ EplNmtMnuSendNmtCommand
+ (uiNodeId_p,
+ kEplNmtCmdStartNode);
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+
+ case kEplNmtMnuIntNodeEventNmtCmdSent:
+ {
+ BYTE bNmtState;
+
+ // update expected NMT state with the one that results
+ // from the sent NMT command
+ bNmtState = (BYTE) (NodeNmtState_p & 0xFF);
+
+ // write object 0x1F8F NMT_MNNodeExpState_AU8
+ Ret =
+ EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
+ 1);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if (NodeNmtState_p == kEplNmtCsNotActive) { // restart processing with IdentRequest
+ EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
+ (pNodeInfo, uiNodeId_p, TimerArg);
+ } else { // monitor NMT state change with StatusRequest after
+ // the corresponding delay;
+ // until then wrong NMT states will be ignored
+ EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON
+ (pNodeInfo, uiNodeId_p, TimerArg);
+
+ // set NMT state change flag
+ pNodeInfo->m_wFlags |=
+ EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
+ }
+
+ Ret =
+ EplTimeruModifyTimerMs(&pNodeInfo->
+ m_TimerHdlStatReq,
+ EplNmtMnuInstance_g.
+ m_ulStatusRequestDelay,
+ TimerArg);
+
+ // finish processing, because NmtState_p is the expected and not the current state
+ goto Exit;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ // check if network is ready to change local NMT state and this was not done before
+ if ((EplNmtMnuInstance_g.m_wFlags & (EPL_NMTMNU_FLAG_HALTED | EPL_NMTMNU_FLAG_APP_INFORMED)) == 0) { // boot process is not halted
+ switch (NmtState) {
+ case kEplNmtMsPreOperational1:
+ {
+ if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
+ 0)
+ && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs scanned once and all mandatory CNs configured successfully
+ EplNmtMnuInstance_g.m_wFlags |=
+ EPL_NMTMNU_FLAG_APP_INFORMED;
+ // inform application
+ Ret =
+ EplNmtMnuInstance_g.
+ m_pfnCbBootEvent
+ (kEplNmtBootEventBootStep1Finish,
+ NmtState, EPL_E_NO_ERROR);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ // wait for application
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+ // enter PreOp2
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventAllMandatoryCNIdent);
+ }
+ break;
+ }
+
+ case kEplNmtMsPreOperational2:
+ {
+ if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
+ 0)
+ && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs checked once for ReadyToOp and all mandatory CNs are ReadyToOp
+ EplNmtMnuInstance_g.m_wFlags |=
+ EPL_NMTMNU_FLAG_APP_INFORMED;
+ // inform application
+ Ret =
+ EplNmtMnuInstance_g.
+ m_pfnCbBootEvent
+ (kEplNmtBootEventBootStep2Finish,
+ NmtState, EPL_E_NO_ERROR);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ // wait for application
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+ // enter ReadyToOp
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterReadyToOperate);
+ }
+ break;
+ }
+
+ case kEplNmtMsReadyToOperate:
+ {
+ if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
+ 0)
+ && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all CNs checked for errorless communication
+ EplNmtMnuInstance_g.m_wFlags |=
+ EPL_NMTMNU_FLAG_APP_INFORMED;
+ // inform application
+ Ret =
+ EplNmtMnuInstance_g.
+ m_pfnCbBootEvent
+ (kEplNmtBootEventCheckComFinish,
+ NmtState, EPL_E_NO_ERROR);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ // wait for application
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+ // enter Operational
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterMsOperational);
+ }
+ break;
+ }
+
+ case kEplNmtMsOperational:
+ {
+ if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
+ 0)
+ && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs scanned once and all mandatory CNs are OPERATIONAL
+ EplNmtMnuInstance_g.m_wFlags |=
+ EPL_NMTMNU_FLAG_APP_INFORMED;
+ // inform application
+ Ret =
+ EplNmtMnuInstance_g.
+ m_pfnCbBootEvent
+ (kEplNmtBootEventOperational,
+ NmtState, EPL_E_NO_ERROR);
+ if (Ret != kEplSuccessful) {
+ if (Ret == kEplReject) {
+ // ignore error code
+ Ret = kEplSuccessful;
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuCheckNmtState
+//
+// Description: checks the NMT state, i.e. evaluates it with object 0x1F8F
+// NMT_MNNodeExpState_AU8 and updates object 0x1F8E
+// NMT_MNNodeCurrState_AU8.
+// It manipulates m_NodeState in internal node info structure.
+//
+// Parameters: uiNodeId_p = node ID
+// NodeNmtState_p = NMT state of CN
+//
+// Returns: tEplKernel = error code
+// kEplReject = CN was in wrong state and has been reset
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
+ tEplNmtMnuNodeInfo * pNodeInfo_p,
+ tEplNmtState NodeNmtState_p,
+ WORD wErrorCode_p,
+ tEplNmtState LocalNmtState_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplObdSize ObdSize;
+ BYTE bNmtState;
+ BYTE bNmtStatePrev;
+ tEplNmtState ExpNmtState;
+
+ ObdSize = 1;
+ // read object 0x1F8F NMT_MNNodeExpState_AU8
+ Ret = EplObduReadEntry(0x1F8F, uiNodeId_p, &bNmtState, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // compute expected NMT state
+ ExpNmtState = (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS);
+ // compute BYTE of current NMT state
+ bNmtState = ((BYTE) NodeNmtState_p & 0xFF);
+
+ if (ExpNmtState == kEplNmtCsNotActive) { // ignore the current state, because the CN shall be not active
+ Ret = kEplReject;
+ goto Exit;
+ } else if ((ExpNmtState == kEplNmtCsPreOperational2)
+ && (NodeNmtState_p == kEplNmtCsReadyToOperate)) { // CN switched to ReadyToOp
+ // delete timer for timeout handling
+ Ret = EplTimeruDeleteTimer(&pNodeInfo_p->m_TimerHdlLonger);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateReadyToOp;
+
+ // update object 0x1F8F NMT_MNNodeExpState_AU8 to ReadyToOp
+ Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter
+ EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
+ }
+ if (LocalNmtState_p >= kEplNmtMsReadyToOperate) { // start procedure CheckCommunication for this node
+ Ret = EplNmtMnuNodeCheckCom(uiNodeId_p, pNodeInfo_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if ((LocalNmtState_p == kEplNmtMsOperational)
+ && (pNodeInfo_p->m_NodeState ==
+ kEplNmtMnuNodeStateComChecked)) {
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, uiNodeId_p,
+ (((NodeNmtState_p & 0xFF) << 8)
+ |
+ kEplNmtCmdStartNode));
+
+ // immediately start optional CN, because communication is always OK (e.g. async-only CN)
+ Ret =
+ EplNmtMnuSendNmtCommand(uiNodeId_p,
+ kEplNmtCmdStartNode);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+ }
+
+ } else if ((ExpNmtState == kEplNmtCsReadyToOperate)
+ && (NodeNmtState_p == kEplNmtCsOperational)) { // CN switched to OPERATIONAL
+ pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateOperational;
+
+ if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter
+ EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
+ }
+
+ } else if ((ExpNmtState != NodeNmtState_p)
+ && !((ExpNmtState == kEplNmtCsPreOperational1)
+ && (NodeNmtState_p == kEplNmtCsPreOperational2))) { // CN is not in expected NMT state (without the exceptions above)
+ WORD wbeErrorCode;
+
+ if ((pNodeInfo_p->
+ m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0) {
+ // decrement only signal slave count if checked once
+ EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
+ pNodeInfo_p->m_wFlags &=
+ ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
+ }
+
+ if (pNodeInfo_p->m_NodeState == kEplNmtMnuNodeStateUnknown) { // CN is already in state unknown, which means that it got
+ // NMT reset command earlier
+ goto Exit;
+ }
+ // -> CN is in wrong NMT state
+ pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateUnknown;
+
+ if (wErrorCode_p == 0) { // assume wrong NMT state error
+ if ((pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED) != 0) { // NMT command has been just issued;
+ // ignore wrong NMT state until timer expires;
+ // other errors like LOSS_PRES_TH are still processed
+ goto Exit;
+ }
+
+ wErrorCode_p = EPL_E_NMT_WRONG_STATE;
+ }
+
+ BENCHMARK_MOD_07_TOGGLE(9);
+
+ // $$$ start ERROR_TREATMENT and inform application
+ Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
+ kEplNmtNodeEventError,
+ NodeNmtState_p,
+ wErrorCode_p,
+ (pNodeInfo_p->
+ m_dwNodeCfg &
+ EPL_NODEASSIGN_MANDATORY_CN)
+ != 0);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
+ uiNodeId_p,
+ (((NodeNmtState_p & 0xFF) << 8)
+ | kEplNmtCmdResetNode));
+
+ // reset CN
+ // store error code in NMT command data for diagnostic purpose
+ AmiSetWordToLe(&wbeErrorCode, wErrorCode_p);
+ Ret =
+ EplNmtMnuSendNmtCommandEx(uiNodeId_p, kEplNmtCmdResetNode,
+ &wbeErrorCode,
+ sizeof(wbeErrorCode));
+ if (Ret == kEplSuccessful) {
+ Ret = kEplReject;
+ }
+
+ goto Exit;
+ }
+ // check if NMT_MNNodeCurrState_AU8 has to be changed
+ ObdSize = 1;
+ Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtStatePrev, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ if (bNmtState != bNmtStatePrev) {
+ // update object 0x1F8E NMT_MNNodeCurrState_AU8
+ Ret = EplObduWriteEntry(0x1F8E, uiNodeId_p, &bNmtState, 1);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
+ kEplNmtNodeEventNmtState,
+ NodeNmtState_p,
+ wErrorCode_p,
+ (pNodeInfo_p->
+ m_dwNodeCfg &
+ EPL_NODEASSIGN_MANDATORY_CN)
+ != 0);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtMnuReset
+//
+// Description: reset internal structures, e.g. timers
+//
+// Parameters: void
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplNmtMnuReset(void)
+{
+ tEplKernel Ret;
+ int iIndex;
+
+ Ret = EplTimeruDeleteTimer(&EplNmtMnuInstance_g.m_TimerHdlNmtState);
+
+ for (iIndex = 1; iIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
+ iIndex++) {
+ // delete timer handles
+ Ret =
+ EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
+ m_TimerHdlStatReq);
+ Ret =
+ EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
+ m_TimerHdlLonger);
+ }
+
+ return Ret;
+}
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplNmtk.c b/drivers/staging/epl/EplNmtk.c
new file mode 100644
index 000000000000..4e2d0e15e947
--- /dev/null
+++ b/drivers/staging/epl/EplNmtk.c
@@ -0,0 +1,1842 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for NMT-Kernelspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtk.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.12 $ $Date: 2008/11/13 17:13:09 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "kernel/EplNmtk.h"
+#include "kernel/EplTimerk.h"
+
+#include "kernel/EplDllk.h" // for EplDllkProcess()
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#define TGT_DBG_POST_TRACE_VALUE(v)
+#endif
+#define EPL_NMTK_DBG_POST_TRACE_VALUE(NmtEvent_p, OldNmtState_p, NewNmtState_p) \
+ TGT_DBG_POST_TRACE_VALUE((kEplEventSinkNmtk << 28) | (NmtEvent_p << 16) \
+ | ((OldNmtState_p & 0xFF) << 8) \
+ | (NewNmtState_p & 0xFF))
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+// struct for instance table
+INSTANCE_TYPE_BEGIN EPL_MCO_DECL_INSTANCE_MEMBER()
+
+STATIC volatile tEplNmtState INST_FAR m_NmtState;
+STATIC volatile BOOL INST_FAR m_fEnableReadyToOperate;
+STATIC volatile BOOL INST_FAR m_fAppReadyToOperate;
+STATIC volatile BOOL INST_FAR m_fTimerMsPreOp2;
+STATIC volatile BOOL INST_FAR m_fAllMandatoryCNIdent;
+STATIC volatile BOOL INST_FAR m_fFrozen;
+
+INSTANCE_TYPE_END
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+// This macro replace the unspecific pointer to an instance through
+// the modul specific type for the local instance table. This macro
+// must defined in each modul.
+//#define tEplPtrInstance tEplInstanceInfo MEM*
+EPL_MCO_DECL_INSTANCE_VAR()
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+EPL_MCO_DEFINE_INSTANCE_FCT()
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <NMT_Kernel-Module> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: This module realize the NMT-State-Machine of the EPL-Stack
+//
+//
+/***************************************************************************/
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtkInit
+//
+// Description: initializes the first instance
+//
+//
+//
+// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer
+// uiNodeId_p = Node Id of the lokal node
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR)
+{
+ tEplKernel Ret;
+
+ Ret = EplNmtkAddInstance(EPL_MCO_PTR_INSTANCE_PTR);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtkAddInstance
+//
+// Description: adds a new instance
+//
+//
+//
+// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR)
+{
+ EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret;
+//tEplEvent Event;
+//tEplEventNmtStateChange NmtStateChange;
+
+ // check if pointer to instance pointer valid
+ // get free instance and set the globale instance pointer
+ // set also the instance addr to parameterlist
+ EPL_MCO_CHECK_PTR_INSTANCE_PTR();
+ EPL_MCO_GET_FREE_INSTANCE_PTR();
+ EPL_MCO_SET_PTR_INSTANCE_PTR();
+
+ // sign instance as used
+ EPL_MCO_WRITE_INSTANCE_STATE(kStateUsed);
+
+ Ret = kEplSuccessful;
+
+ // initialize intern vaiables
+ // 2006/07/31 d.k.: set NMT-State to kEplNmtGsOff
+ EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff;
+ // set NMT-State to kEplNmtGsInitialising
+ //EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising;
+
+ // set flags to FALSE
+ EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE;
+ EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE;
+ EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) = FALSE;
+ EPL_MCO_GLB_VAR(m_fAllMandatoryCNIdent) = FALSE;
+ EPL_MCO_GLB_VAR(m_fFrozen) = FALSE;
+
+// EPL_MCO_GLB_VAR(m_TimerHdl) = 0;
+
+ // inform higher layer about state change
+ // 2006/07/31 d.k.: The EPL API layer/application has to start NMT state
+ // machine via NmtEventSwReset after initialisation of
+ // all modules has been completed. DLL has to be initialised
+ // after NMTk because NMT state shall not be uninitialised
+ // at that time.
+/* NmtStateChange.m_NewNmtState = EPL_MCO_GLB_VAR(m_NmtState);
+ NmtStateChange.m_NmtEvent = kEplNmtEventNoEvent;
+ Event.m_EventSink = kEplEventSinkNmtu;
+ Event.m_EventType = kEplEventTypeNmtStateChange;
+ EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
+ Event.m_pArg = &NmtStateChange;
+ Event.m_uiSize = sizeof(NmtStateChange);
+ Ret = EplEventkPost(&Event);
+*/
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtkDelInstance
+//
+// Description: delete instance
+//
+//
+//
+// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if (EPL_USE_DELETEINST_FUNC != FALSE)
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR)
+{
+ tEplKernel Ret = kEplSuccessful;
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ // set NMT-State to kEplNmtGsOff
+ EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff;
+
+ // sign instance as unused
+ EPL_MCO_WRITE_INSTANCE_STATE(kStateUnused);
+
+ // delete timer
+// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl));
+
+ return Ret;
+}
+#endif // (EPL_USE_DELETEINST_FUNC != FALSE)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtkProcess
+//
+// Description: main process function
+// -> process NMT-State-Maschine und read NMT-Events from Queue
+//
+//
+//
+// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR_ = Instance pointer
+// pEvent_p = Epl-Event with NMT-event to process
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_
+ tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+ tEplNmtState OldNmtState;
+ tEplNmtEvent NmtEvent;
+ tEplEvent Event;
+ tEplEventNmtStateChange NmtStateChange;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ Ret = kEplSuccessful;
+
+ switch (pEvent_p->m_EventType) {
+ case kEplEventTypeNmtEvent:
+ {
+ NmtEvent = *((tEplNmtEvent *) pEvent_p->m_pArg);
+ break;
+ }
+
+ case kEplEventTypeTimer:
+ {
+ NmtEvent =
+ (tEplNmtEvent) ((tEplTimerEventArg *) pEvent_p->
+ m_pArg)->m_ulArg;
+ break;
+ }
+ default:
+ {
+ Ret = kEplNmtInvalidEvent;
+ goto Exit;
+ }
+ }
+
+ // save NMT-State
+ // needed for later comparison to
+ // inform hgher layer about state change
+ OldNmtState = EPL_MCO_GLB_VAR(m_NmtState);
+
+ // NMT-State-Maschine
+ switch (EPL_MCO_GLB_VAR(m_NmtState)) {
+ //-----------------------------------------------------------
+ // general part of the statemaschine
+
+ // first init of the hardware
+ case kEplNmtGsOff:
+ {
+ // leave this state only if higher layer says so
+ if (NmtEvent == kEplNmtEventSwReset) { // new state kEplNmtGsInitialising
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ }
+ break;
+ }
+
+ // first init of the hardware
+ case kEplNmtGsInitialising:
+ {
+ // leave this state only if higher layer says so
+
+ // check events
+ switch (NmtEvent) {
+ // 2006/07/31 d.k.: react also on NMT reset commands in ResetApp state
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // new state kEplNmtGsResetApplication
+ case kEplNmtEventEnterResetApp:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+
+ // init of the manufacturer-specific profile area and the
+ // standardised device profile area
+ case kEplNmtGsResetApplication:
+ {
+ // check events
+ switch (NmtEvent) {
+ // 2006/07/31 d.k.: react also on NMT reset commands in ResetApp state
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // leave this state only if higher layer
+ // say so
+ case kEplNmtEventEnterResetCom:
+ {
+ // new state kEplNmtGsResetCommunication
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+
+ // init of the communication profile area
+ case kEplNmtGsResetCommunication:
+ {
+ // check events
+ switch (NmtEvent) {
+ // 2006/07/31 d.k.: react also on NMT reset commands in ResetComm state
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // leave this state only if higher layer
+ // say so
+ case kEplNmtEventEnterResetConfig:
+ {
+ // new state kEplNmtGsResetCommunication
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+
+ // build the configuration with infos from OD
+ case kEplNmtGsResetConfiguration:
+ {
+ // reset flags
+ EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE;
+ EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE;
+ EPL_MCO_GLB_VAR(m_fFrozen) = FALSE;
+
+ // check events
+ switch (NmtEvent) {
+ // 2006/07/31 d.k.: react also on NMT reset commands in ResetConf state
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ case kEplNmtEventResetCom:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // leave this state only if higher layer says so
+ case kEplNmtEventEnterCsNotActive:
+ { // Node should be CN
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsNotActive;
+ break;
+
+ }
+
+ case kEplNmtEventEnterMsNotActive:
+ { // Node should be CN
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0)
+ // no MN functionality
+ // TODO: -create error E_NMT_BA1_NO_MN_SUPPORT
+ EPL_MCO_GLB_VAR(m_fFrozen) = TRUE;
+#else
+
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsNotActive;
+#endif
+ break;
+
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+
+ //-----------------------------------------------------------
+ // CN part of the statemaschine
+
+ // node liste for EPL-Frames and check timeout
+ case kEplNmtCsNotActive:
+ {
+
+ // check events
+ switch (NmtEvent) {
+ // 2006/07/31 d.k.: react also on NMT reset commands in NotActive state
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl));
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl));
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl));
+ break;
+ }
+
+ // NMT Command Reset Configuration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl));
+ break;
+ }
+
+ // see if SoA or SoC received
+ // k.t. 20.07.2006: only SoA forces change of state
+ // see EPL V2 DS 1.0.0 p.267
+ // case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeSoa:
+ { // new state PRE_OPERATIONAL1
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational1;
+// Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl));
+ break;
+ }
+ // timeout for SoA and Soc
+ case kEplNmtEventTimerBasicEthernet:
+ {
+ // new state BASIC_ETHERNET
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsBasicEthernet;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ } // end of switch(NmtEvent)
+
+ break;
+ }
+
+ // node processes only async frames
+ case kEplNmtCsPreOperational1:
+ {
+
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command Reset Configuration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // NMT Command StopNode
+ case kEplNmtEventStopNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsStopped;
+ break;
+ }
+
+ // check if SoC received
+ case kEplNmtEventDllCeSoc:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational2;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+
+ break;
+ }
+
+ // node processes isochronous and asynchronous frames
+ case kEplNmtCsPreOperational2:
+ {
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command Reset Configuration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // NMT Command StopNode
+ case kEplNmtEventStopNode:
+ {
+ // reset flags
+ EPL_MCO_GLB_VAR(m_fEnableReadyToOperate)
+ = FALSE;
+ EPL_MCO_GLB_VAR(m_fAppReadyToOperate) =
+ FALSE;
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsStopped;
+ break;
+ }
+
+ // error occured
+ case kEplNmtEventNmtCycleError:
+ {
+ // reset flags
+ EPL_MCO_GLB_VAR(m_fEnableReadyToOperate)
+ = FALSE;
+ EPL_MCO_GLB_VAR(m_fAppReadyToOperate) =
+ FALSE;
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational1;
+ break;
+ }
+
+ // check if application is ready to operate
+ case kEplNmtEventEnterReadyToOperate:
+ {
+ // check if command NMTEnableReadyToOperate from MN was received
+ if (EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) == TRUE) { // reset flags
+ EPL_MCO_GLB_VAR
+ (m_fEnableReadyToOperate) =
+ FALSE;
+ EPL_MCO_GLB_VAR
+ (m_fAppReadyToOperate) =
+ FALSE;
+ // change state
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsReadyToOperate;
+ } else { // set Flag
+ EPL_MCO_GLB_VAR
+ (m_fAppReadyToOperate) =
+ TRUE;
+ }
+ break;
+ }
+
+ // NMT Commando EnableReadyToOperate
+ case kEplNmtEventEnableReadyToOperate:
+ {
+ // check if application is ready
+ if (EPL_MCO_GLB_VAR(m_fAppReadyToOperate) == TRUE) { // reset flags
+ EPL_MCO_GLB_VAR
+ (m_fEnableReadyToOperate) =
+ FALSE;
+ EPL_MCO_GLB_VAR
+ (m_fAppReadyToOperate) =
+ FALSE;
+ // change state
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsReadyToOperate;
+ } else { // set Flag
+ EPL_MCO_GLB_VAR
+ (m_fEnableReadyToOperate) =
+ TRUE;
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+ break;
+ }
+
+ // node should be configured und application is ready
+ case kEplNmtCsReadyToOperate:
+ {
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // NMT Command StopNode
+ case kEplNmtEventStopNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsStopped;
+ break;
+ }
+
+ // error occured
+ case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational1;
+ break;
+ }
+
+ // NMT Command StartNode
+ case kEplNmtEventStartNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsOperational;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+ break;
+ }
+
+ // normal work state
+ case kEplNmtCsOperational:
+ {
+
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // NMT Command StopNode
+ case kEplNmtEventStopNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsStopped;
+ break;
+ }
+
+ // NMT Command EnterPreOperational2
+ case kEplNmtEventEnterPreOperational2:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational2;
+ break;
+ }
+
+ // error occured
+ case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational1;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+ break;
+ }
+
+ // node stopped by MN
+ // -> only process asynchronous frames
+ case kEplNmtCsStopped:
+ {
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // NMT Command EnterPreOperational2
+ case kEplNmtEventEnterPreOperational2:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational2;
+ break;
+ }
+
+ // error occured
+ case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational1;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+ break;
+ }
+
+ // no epl cycle
+ // -> normal ethernet communication
+ case kEplNmtCsBasicEthernet:
+ {
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // error occured
+ // d.k.: how does this error occur? on CRC errors
+/* case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1;
+ break;
+ }
+*/
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCePreq:
+ case kEplNmtEventDllCePres:
+ case kEplNmtEventDllCeSoa:
+ { // Epl-Frame on net -> stop any communication
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtCsPreOperational1;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+
+ break;
+ }
+
+ //-----------------------------------------------------------
+ // MN part of the statemaschine
+
+ // MN listen to network
+ // -> if no EPL traffic go to next state
+ case kEplNmtMsNotActive:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0)
+ // no MN functionality
+ // TODO: -create error E_NMT_BA1_NO_MN_SUPPORT
+ EPL_MCO_GLB_VAR(m_fFrozen) = TRUE;
+#else
+
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // EPL frames received
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeSoa:
+ { // other MN in network
+ // $$$ d.k.: generate error history entry
+ EPL_MCO_GLB_VAR(m_fFrozen) = TRUE;
+ break;
+ }
+
+ // timeout event
+ case kEplNmtEventTimerBasicEthernet:
+ {
+ if (EPL_MCO_GLB_VAR(m_fFrozen) == FALSE) { // new state BasicEthernet
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsBasicEthernet;
+ }
+ break;
+ }
+
+ // timeout event
+ case kEplNmtEventTimerMsPreOp1:
+ {
+ if (EPL_MCO_GLB_VAR(m_fFrozen) == FALSE) { // new state PreOp1
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsPreOperational1;
+ EPL_MCO_GLB_VAR
+ (m_fTimerMsPreOp2) = FALSE;
+ EPL_MCO_GLB_VAR
+ (m_fAllMandatoryCNIdent) =
+ FALSE;
+
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+
+#endif // ((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0)
+
+ break;
+ }
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // MN process reduces epl cycle
+ case kEplNmtMsPreOperational1:
+ {
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // EPL frames received
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeSoa:
+ { // other MN in network
+ // $$$ d.k.: generate error history entry
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // error occured
+ // d.k. MSPreOp1->CSPreOp1: nonsense -> keep state
+ /*
+ case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1;
+ break;
+ }
+ */
+
+ case kEplNmtEventAllMandatoryCNIdent:
+ { // all mandatory CN identified
+ if (EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) !=
+ FALSE) {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsPreOperational2;
+ } else {
+ EPL_MCO_GLB_VAR
+ (m_fAllMandatoryCNIdent) =
+ TRUE;
+ }
+ break;
+ }
+
+ case kEplNmtEventTimerMsPreOp2:
+ { // residence time for PreOp1 is elapsed
+ if (EPL_MCO_GLB_VAR
+ (m_fAllMandatoryCNIdent) != FALSE) {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsPreOperational2;
+ } else {
+ EPL_MCO_GLB_VAR
+ (m_fTimerMsPreOp2) = TRUE;
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+ break;
+ }
+
+ // MN process full epl cycle
+ case kEplNmtMsPreOperational2:
+ {
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // EPL frames received
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeSoa:
+ { // other MN in network
+ // $$$ d.k.: generate error history entry
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // error occured
+ case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsPreOperational1;
+ break;
+ }
+
+ case kEplNmtEventEnterReadyToOperate:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsReadyToOperate;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+
+ break;
+ }
+
+ // all madatory nodes ready to operate
+ // -> MN process full epl cycle
+ case kEplNmtMsReadyToOperate:
+ {
+
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // EPL frames received
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeSoa:
+ { // other MN in network
+ // $$$ d.k.: generate error history entry
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // error occured
+ case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsPreOperational1;
+ break;
+ }
+
+ case kEplNmtEventEnterMsOperational:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsOperational;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+
+ break;
+ }
+
+ // normal eplcycle processing
+ case kEplNmtMsOperational:
+ {
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // EPL frames received
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeSoa:
+ { // other MN in network
+ // $$$ d.k.: generate error history entry
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // error occured
+ case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtMsPreOperational1;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+ break;
+ }
+
+ // normal ethernet traffic
+ case kEplNmtMsBasicEthernet:
+ {
+
+ // check events
+ switch (NmtEvent) {
+ // NMT Command SwitchOff
+ case kEplNmtEventCriticalError:
+ case kEplNmtEventSwitchOff:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsOff;
+ break;
+ }
+
+ // NMT Command SwReset
+ case kEplNmtEventSwReset:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsInitialising;
+ break;
+ }
+
+ // NMT Command ResetNode
+ case kEplNmtEventResetNode:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetApplication;
+ break;
+ }
+
+ // NMT Command ResetCommunication
+ // or internal Communication error
+ case kEplNmtEventResetCom:
+ case kEplNmtEventInternComError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // NMT Command ResetConfiguration
+ case kEplNmtEventResetConfig:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetConfiguration;
+ break;
+ }
+
+ // EPL frames received
+ case kEplNmtEventDllCeSoc:
+ case kEplNmtEventDllCeSoa:
+ { // other MN in network
+ // $$$ d.k.: generate error history entry
+ EPL_MCO_GLB_VAR(m_NmtState) =
+ kEplNmtGsResetCommunication;
+ break;
+ }
+
+ // error occured
+ // d.k. BE->PreOp1 on cycle error? No
+/* case kEplNmtEventNmtCycleError:
+ {
+ EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1;
+ break;
+ }
+*/
+ default:
+ {
+ break;
+ }
+
+ } // end of switch(NmtEvent)
+ break;
+ }
+#endif //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+ default:
+ {
+ //DEBUG_EPL_DBGLVL_NMTK_TRACE0(EPL_DBGLVL_NMT ,"Error in EplNmtProcess: Unknown NMT-State");
+ //EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication;
+ Ret = kEplNmtInvalidState;
+ goto Exit;
+ }
+
+ } // end of switch(NmtEvent)
+
+ // inform higher layer about State-Change if needed
+ if (OldNmtState != EPL_MCO_GLB_VAR(m_NmtState)) {
+ EPL_NMTK_DBG_POST_TRACE_VALUE(NmtEvent, OldNmtState,
+ EPL_MCO_GLB_VAR(m_NmtState));
+
+ // d.k.: memorize NMT state before posting any events
+ NmtStateChange.m_NewNmtState = EPL_MCO_GLB_VAR(m_NmtState);
+
+ // inform DLL
+ if ((OldNmtState > kEplNmtGsResetConfiguration)
+ && (EPL_MCO_GLB_VAR(m_NmtState) <=
+ kEplNmtGsResetConfiguration)) {
+ // send DLL DEINIT
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkDestroy;
+ EPL_MEMSET(&Event.m_NetTime, 0x00,
+ sizeof(Event.m_NetTime));
+ Event.m_pArg = &OldNmtState;
+ Event.m_uiSize = sizeof(OldNmtState);
+ // d.k.: directly call DLLk process function, because
+ // 1. execution of process function is still synchonized and serialized,
+ // 2. it is the same as without event queues (i.e. well tested),
+ // 3. DLLk will get those necessary events even if event queue is full,
+ // 4. event queue is very inefficient
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ Ret = EplDllkProcess(&Event);
+#else
+ Ret = EplEventkPost(&Event);
+#endif
+ } else if ((OldNmtState <= kEplNmtGsResetConfiguration)
+ && (EPL_MCO_GLB_VAR(m_NmtState) >
+ kEplNmtGsResetConfiguration)) {
+ // send DLL INIT
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkCreate;
+ EPL_MEMSET(&Event.m_NetTime, 0x00,
+ sizeof(Event.m_NetTime));
+ Event.m_pArg = &NmtStateChange.m_NewNmtState;
+ Event.m_uiSize = sizeof(NmtStateChange.m_NewNmtState);
+ // d.k.: directly call DLLk process function, because
+ // 1. execution of process function is still synchonized and serialized,
+ // 2. it is the same as without event queues (i.e. well tested),
+ // 3. DLLk will get those necessary events even if event queue is full
+ // 4. event queue is very inefficient
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ Ret = EplDllkProcess(&Event);
+#else
+ Ret = EplEventkPost(&Event);
+#endif
+ } else
+ if ((EPL_MCO_GLB_VAR(m_NmtState) == kEplNmtCsBasicEthernet)
+ || (EPL_MCO_GLB_VAR(m_NmtState) ==
+ kEplNmtMsBasicEthernet)) {
+ tEplDllAsyncReqPriority AsyncReqPriority;
+
+ // send DLL Fill Async Tx Buffer, because state BasicEthernet was entered
+ Event.m_EventSink = kEplEventSinkDllk;
+ Event.m_EventType = kEplEventTypeDllkFillTx;
+ EPL_MEMSET(&Event.m_NetTime, 0x00,
+ sizeof(Event.m_NetTime));
+ AsyncReqPriority = kEplDllAsyncReqPrioGeneric;
+ Event.m_pArg = &AsyncReqPriority;
+ Event.m_uiSize = sizeof(AsyncReqPriority);
+ // d.k.: directly call DLLk process function, because
+ // 1. execution of process function is still synchonized and serialized,
+ // 2. it is the same as without event queues (i.e. well tested),
+ // 3. DLLk will get those necessary events even if event queue is full
+ // 4. event queue is very inefficient
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+ Ret = EplDllkProcess(&Event);
+#else
+ Ret = EplEventkPost(&Event);
+#endif
+ }
+ // inform higher layer about state change
+ NmtStateChange.m_NmtEvent = NmtEvent;
+ Event.m_EventSink = kEplEventSinkNmtu;
+ Event.m_EventType = kEplEventTypeNmtStateChange;
+ EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime));
+ Event.m_pArg = &NmtStateChange;
+ Event.m_uiSize = sizeof(NmtStateChange);
+ Ret = EplEventkPost(&Event);
+ EPL_DBGLVL_NMTK_TRACE2
+ ("EplNmtkProcess(NMT-Event = 0x%04X): New NMT-State = 0x%03X\n",
+ NmtEvent, NmtStateChange.m_NewNmtState);
+
+ }
+
+ Exit:
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtkGetNmtState
+//
+// Description: return the actuell NMT-State and the bits
+// to for MN- or CN-mode
+//
+//
+//
+// Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR_ = Instancepointer
+//
+//
+// Returns: tEplNmtState = NMT-State
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplNmtState PUBLIC
+EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR)
+{
+ tEplNmtState NmtState;
+
+ NmtState = EPL_MCO_GLB_VAR(m_NmtState);
+
+ return NmtState;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+EPL_MCO_DECL_INSTANCE_FCT()
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+// EOF
diff --git a/drivers/staging/epl/EplNmtkCal.c b/drivers/staging/epl/EplNmtkCal.c
new file mode 100644
index 000000000000..4ad71a71e013
--- /dev/null
+++ b/drivers/staging/epl/EplNmtkCal.c
@@ -0,0 +1,149 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for communication abstraction layer of the
+ NMT-Kernel-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtkCal.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/16 -k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "kernel/EplNmtkCal.h"
+
+// TODO: init function needed to prepare EplNmtkGetNmtState for
+// io-controll-call from EplNmtuCal-Modul
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+// EOF
diff --git a/drivers/staging/epl/EplNmtu.c b/drivers/staging/epl/EplNmtu.c
new file mode 100644
index 000000000000..3de16a1eff5e
--- /dev/null
+++ b/drivers/staging/epl/EplNmtu.c
@@ -0,0 +1,708 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for NMT-Userspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/11/10 17:17:42 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "user/EplNmtu.h"
+#include "user/EplObdu.h"
+#include "user/EplTimeru.h"
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+#include "kernel/EplNmtk.h"
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ tEplNmtuStateChangeCallback m_pfnNmtChangeCb;
+ tEplTimerHdl m_TimerHdl;
+
+} tEplNmtuInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+static tEplNmtuInstance EplNmtuInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuInit
+//
+// Description: init first instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit()
+{
+ tEplKernel Ret;
+
+ Ret = EplNmtuAddInstance();
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuAddInstance
+//
+// Description: init other instances of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ EplNmtuInstance_g.m_pfnNmtChangeCb = NULL;
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuDelInstance
+//
+// Description: delete instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ EplNmtuInstance_g.m_pfnNmtChangeCb = NULL;
+
+ // delete timer
+ Ret = EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuNmtEvent
+//
+// Description: sends the NMT-Event to the NMT-State-Maschine
+//
+//
+//
+// Parameters: NmtEvent_p = NMT-Event to send
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p)
+{
+ tEplKernel Ret;
+ tEplEvent Event;
+
+ Event.m_EventSink = kEplEventSinkNmtk;
+ Event.m_NetTime.m_dwNanoSec = 0;
+ Event.m_NetTime.m_dwSec = 0;
+ Event.m_EventType = kEplEventTypeNmtEvent;
+ Event.m_pArg = &NmtEvent_p;
+ Event.m_uiSize = sizeof(NmtEvent_p);
+
+ Ret = EplEventuPost(&Event);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuGetNmtState
+//
+// Description: returns the actuell NMT-State
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplNmtState = NMT-State
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState()
+{
+ tEplNmtState NmtState;
+
+ // $$$ call function of communication abstraction layer
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+ NmtState = EplNmtkGetNmtState();
+#else
+ NmtState = 0;
+#endif
+
+ return NmtState;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuProcessEvent
+//
+// Description: processes events from event queue
+//
+//
+//
+// Parameters: pEplEvent_p = pointer to event
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // process event
+ switch (pEplEvent_p->m_EventType) {
+ // state change of NMT-Module
+ case kEplEventTypeNmtStateChange:
+ {
+ tEplEventNmtStateChange *pNmtStateChange;
+
+ // delete timer
+ Ret =
+ EplTimeruDeleteTimer(&EplNmtuInstance_g.m_TimerHdl);
+
+ pNmtStateChange =
+ (tEplEventNmtStateChange *) pEplEvent_p->m_pArg;
+
+ // call cb-functions to inform higher layer
+ if (EplNmtuInstance_g.m_pfnNmtChangeCb != NULL) {
+ Ret =
+ EplNmtuInstance_g.
+ m_pfnNmtChangeCb(*pNmtStateChange);
+ }
+
+ if (Ret == kEplSuccessful) { // everything is OK, so switch to next state if necessary
+ switch (pNmtStateChange->m_NewNmtState) {
+ // EPL stack is not running
+ case kEplNmtGsOff:
+ break;
+
+ // first init of the hardware
+ case kEplNmtGsInitialising:
+ {
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterResetApp);
+ break;
+ }
+
+ // init of the manufacturer-specific profile area and the
+ // standardised device profile area
+ case kEplNmtGsResetApplication:
+ {
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterResetCom);
+ break;
+ }
+
+ // init of the communication profile area
+ case kEplNmtGsResetCommunication:
+ {
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterResetConfig);
+ break;
+ }
+
+ // build the configuration with infos from OD
+ case kEplNmtGsResetConfiguration:
+ {
+ unsigned int uiNodeId;
+
+ // get node ID from OD
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
+ uiNodeId =
+ EplObduGetNodeId
+ (EPL_MCO_PTR_INSTANCE_PTR);
+#else
+ uiNodeId = 0;
+#endif
+ //check node ID if not should be master or slave
+ if (uiNodeId == EPL_C_ADR_MN_DEF_NODE_ID) { // node shall be MN
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterMsNotActive);
+#else
+ TRACE0
+ ("EplNmtuProcess(): no MN functionality implemented\n");
+#endif
+ } else { // node shall be CN
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterCsNotActive);
+ }
+ break;
+ }
+
+ //-----------------------------------------------------------
+ // CN part of the state machine
+
+ // node listens for EPL-Frames and check timeout
+ case kEplNmtCsNotActive:
+ {
+ DWORD dwBuffer;
+ tEplObdSize ObdSize;
+ tEplTimerArg TimerArg;
+
+ // create timer to switch automatically to BasicEthernet if no MN available in network
+
+ // read NMT_CNBasicEthernetTimerout_U32 from OD
+ ObdSize = sizeof(dwBuffer);
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
+ Ret =
+ EplObduReadEntry
+ (EPL_MCO_PTR_INSTANCE_PTR_
+ 0x1F99, 0x00, &dwBuffer,
+ &ObdSize);
+#else
+ Ret = kEplObdIndexNotExist;
+#endif
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ if (dwBuffer != 0) { // BasicEthernet is enabled
+ // convert us into ms
+ dwBuffer =
+ dwBuffer / 1000;
+ if (dwBuffer == 0) { // timer was below one ms
+ // set one ms
+ dwBuffer = 1;
+ }
+ TimerArg.m_EventSink =
+ kEplEventSinkNmtk;
+ TimerArg.m_ulArg =
+ (unsigned long)
+ kEplNmtEventTimerBasicEthernet;
+ Ret =
+ EplTimeruModifyTimerMs
+ (&EplNmtuInstance_g.
+ m_TimerHdl,
+ (unsigned long)
+ dwBuffer,
+ TimerArg);
+ // potential error is forwarded to event queue which generates error event
+ }
+ break;
+ }
+
+ // node processes only async frames
+ case kEplNmtCsPreOperational1:
+ {
+ break;
+ }
+
+ // node processes isochronous and asynchronous frames
+ case kEplNmtCsPreOperational2:
+ {
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventEnterReadyToOperate);
+ break;
+ }
+
+ // node should be configured und application is ready
+ case kEplNmtCsReadyToOperate:
+ {
+ break;
+ }
+
+ // normal work state
+ case kEplNmtCsOperational:
+ {
+ break;
+ }
+
+ // node stopped by MN
+ // -> only process asynchronous frames
+ case kEplNmtCsStopped:
+ {
+ break;
+ }
+
+ // no EPL cycle
+ // -> normal ethernet communication
+ case kEplNmtCsBasicEthernet:
+ {
+ break;
+ }
+
+ //-----------------------------------------------------------
+ // MN part of the state machine
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // node listens for EPL-Frames and check timeout
+ case kEplNmtMsNotActive:
+ {
+ DWORD dwBuffer;
+ tEplObdSize ObdSize;
+ tEplTimerArg TimerArg;
+
+ // create timer to switch automatically to BasicEthernet/PreOp1 if no other MN active in network
+
+ // check NMT_StartUp_U32.Bit13
+ // read NMT_StartUp_U32 from OD
+ ObdSize = sizeof(dwBuffer);
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
+ Ret =
+ EplObduReadEntry
+ (EPL_MCO_PTR_INSTANCE_PTR_
+ 0x1F80, 0x00, &dwBuffer,
+ &ObdSize);
+#else
+ Ret = kEplObdIndexNotExist;
+#endif
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+
+ if ((dwBuffer & EPL_NMTST_BASICETHERNET) == 0) { // NMT_StartUp_U32.Bit13 == 0
+ // new state PreOperational1
+ TimerArg.m_ulArg =
+ (unsigned long)
+ kEplNmtEventTimerMsPreOp1;
+ } else { // NMT_StartUp_U32.Bit13 == 1
+ // new state BasicEthernet
+ TimerArg.m_ulArg =
+ (unsigned long)
+ kEplNmtEventTimerBasicEthernet;
+ }
+
+ // read NMT_BootTime_REC.MNWaitNotAct_U32 from OD
+ ObdSize = sizeof(dwBuffer);
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
+ Ret =
+ EplObduReadEntry
+ (EPL_MCO_PTR_INSTANCE_PTR_
+ 0x1F89, 0x01, &dwBuffer,
+ &ObdSize);
+#else
+ Ret = kEplObdIndexNotExist;
+#endif
+ if (Ret != kEplSuccessful) {
+ break;
+ }
+ // convert us into ms
+ dwBuffer = dwBuffer / 1000;
+ if (dwBuffer == 0) { // timer was below one ms
+ // set one ms
+ dwBuffer = 1;
+ }
+ TimerArg.m_EventSink =
+ kEplEventSinkNmtk;
+ Ret =
+ EplTimeruModifyTimerMs
+ (&EplNmtuInstance_g.
+ m_TimerHdl,
+ (unsigned long)dwBuffer,
+ TimerArg);
+ // potential error is forwarded to event queue which generates error event
+ break;
+ }
+
+ // node processes only async frames
+ case kEplNmtMsPreOperational1:
+ {
+ DWORD dwBuffer = 0;
+ tEplObdSize ObdSize;
+ tEplTimerArg TimerArg;
+
+ // create timer to switch automatically to PreOp2 if MN identified all mandatory CNs
+
+ // read NMT_BootTime_REC.MNWaitPreOp1_U32 from OD
+ ObdSize = sizeof(dwBuffer);
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) || (EPL_OBD_USE_KERNEL != FALSE)
+ Ret =
+ EplObduReadEntry
+ (EPL_MCO_PTR_INSTANCE_PTR_
+ 0x1F89, 0x03, &dwBuffer,
+ &ObdSize);
+ if (Ret != kEplSuccessful) {
+ // ignore error, because this timeout is optional
+ dwBuffer = 0;
+ }
+#endif
+ if (dwBuffer == 0) { // delay is deactivated
+ // immediately post timer event
+ Ret =
+ EplNmtuNmtEvent
+ (kEplNmtEventTimerMsPreOp2);
+ break;
+ }
+ // convert us into ms
+ dwBuffer = dwBuffer / 1000;
+ if (dwBuffer == 0) { // timer was below one ms
+ // set one ms
+ dwBuffer = 1;
+ }
+ TimerArg.m_EventSink =
+ kEplEventSinkNmtk;
+ TimerArg.m_ulArg =
+ (unsigned long)
+ kEplNmtEventTimerMsPreOp2;
+ Ret =
+ EplTimeruModifyTimerMs
+ (&EplNmtuInstance_g.
+ m_TimerHdl,
+ (unsigned long)dwBuffer,
+ TimerArg);
+ // potential error is forwarded to event queue which generates error event
+ break;
+ }
+
+ // node processes isochronous and asynchronous frames
+ case kEplNmtMsPreOperational2:
+ {
+ break;
+ }
+
+ // node should be configured und application is ready
+ case kEplNmtMsReadyToOperate:
+ {
+ break;
+ }
+
+ // normal work state
+ case kEplNmtMsOperational:
+ {
+ break;
+ }
+
+ // no EPL cycle
+ // -> normal ethernet communication
+ case kEplNmtMsBasicEthernet:
+ {
+ break;
+ }
+#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+ default:
+ {
+ TRACE1
+ ("EplNmtuProcess(): unhandled NMT state 0x%X\n",
+ pNmtStateChange->
+ m_NewNmtState);
+ }
+ }
+ } else if (Ret == kEplReject) { // application wants to change NMT state itself
+ // it's OK
+ Ret = kEplSuccessful;
+ }
+
+ EPL_DBGLVL_NMTU_TRACE0
+ ("EplNmtuProcessEvent(): NMT-State-Maschine announce change of NMT State\n");
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplNmtInvalidEvent;
+ }
+
+ }
+
+//Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtuRegisterStateChangeCb
+//
+// Description: register Callback-function go get informed about a
+// NMT-Change-State-Event
+//
+//
+//
+// Parameters: pfnEplNmtStateChangeCb_p = functionpointer
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC
+EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback
+ pfnEplNmtStateChangeCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // save callback-function in modul global var
+ EplNmtuInstance_g.m_pfnNmtChangeCb = pfnEplNmtStateChangeCb_p;
+
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplNmtuCal.c b/drivers/staging/epl/EplNmtuCal.c
new file mode 100644
index 000000000000..4a29ef58bf9b
--- /dev/null
+++ b/drivers/staging/epl/EplNmtuCal.c
@@ -0,0 +1,158 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for communication abstraction layer of the
+ NMT-Userspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtuCal.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/16 -k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplNmtuCal.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplNmtkCalGetNmtState
+//
+// Description: return current NMT-State
+// -> encapsulate access to kernelspace
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplNmtState = current NMT-State
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkCalGetNmtState()
+{
+ tEplNmtState NmtState;
+ // for test direkt call for EplNmtkGetNmtState()
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+ NmtState = EplNmtkGetNmtState();
+#else
+ NmtState = 0;
+#endif
+ return NmtState;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+// EOF
diff --git a/drivers/staging/epl/EplObd.c b/drivers/staging/epl/EplObd.c
new file mode 100644
index 000000000000..efbb1967a5dc
--- /dev/null
+++ b/drivers/staging/epl/EplObd.c
@@ -0,0 +1,3262 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for api function of EplOBD-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObd.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.12 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ Microsoft VC7
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/02 k.t.: start of the implementation, version 1.00
+ ->based on CANopen OBD-Modul
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "kernel/EplObdk.h" // function prototyps of the EplOBD-Modul
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// float definitions and macros
+#define _SHIFTED_EXPONENT_MASK_SP 0xff
+#define _BIAS_SP 126
+#define T_SP 23
+#define EXPONENT_DENORM_SP (-_BIAS_SP)
+#define BASE_TO_THE_T_SP ((float) 8388608.0)
+#define GET_EXPONENT_SP(x) ((((x) >> T_SP) & _SHIFTED_EXPONENT_MASK_SP) - _BIAS_SP)
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+// struct for instance table
+INSTANCE_TYPE_BEGIN EPL_MCO_DECL_INSTANCE_MEMBER()
+
+STATIC tEplObdInitParam INST_FAR m_ObdInitParam;
+STATIC tEplObdStoreLoadObjCallback INST_NEAR m_fpStoreLoadObjCallback;
+
+INSTANCE_TYPE_END
+// decomposition of float
+typedef union {
+ tEplObdReal32 m_flRealPart;
+ int m_nIntegerPart;
+
+} tEplObdRealParts;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+// This macro replace the unspecific pointer to an instance through
+// the modul specific type for the local instance table. This macro
+// must defined in each modul.
+//#define tEplPtrInstance tEplInstanceInfo MEM*
+
+EPL_MCO_DECL_INSTANCE_VAR()
+
+BYTE MEM abEplObdTrashObject_g[8];
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+EPL_MCO_DEFINE_INSTANCE_FCT()
+
+static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdCallback fpCallback_p,
+ tEplObdCbParam MEM * pCbParam_p);
+
+static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p);
+
+static tEplObdSize EplObdGetStrLen(void *pObjData_p,
+ tEplObdSize ObjLen_p, tEplObdType ObjType_p);
+
+#if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
+static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
+ void *pData_p);
+#endif
+
+static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
+ tEplObdVarEntry MEM ** ppVarEntry_p);
+
+static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdEntryPtr * ppObdEntry_p,
+ tEplObdSubEntryPtr * ppObdSubEntry_p);
+
+static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p);
+
+static tEplKernel EplObdGetIndexIntern(tEplObdInitParam MEM * pInitParam_p,
+ unsigned int uiIndex_p,
+ tEplObdEntryPtr * ppObdEntry_p);
+
+static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
+ unsigned int uiSubIndex_p,
+ tEplObdSubEntryPtr * ppObdSubEntry_p);
+
+static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdPart CurrentOdPart_p,
+ tEplObdEntryPtr pObdEnty_p,
+ tEplObdDir Direction_p);
+
+static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p);
+static void MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p);
+
+#if (EPL_OBD_USE_STORE_RESTORE != FALSE)
+
+static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdCbStoreParam MEM *
+ pCbStoreParam_p);
+
+#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
+
+static void EplObdCopyObjectData(void MEM * pDstData_p,
+ void *pSrcData_p,
+ tEplObdSize ObjSize_p, tEplObdType ObjType_p);
+
+void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p);
+
+static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
+ BOOL * pfEntryNumerical_p);
+
+static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ void **ppDstData_p,
+ tEplObdSize Size_p,
+ tEplObdEntryPtr * ppObdEntry_p,
+ tEplObdSubEntryPtr * ppSubEntry_p,
+ tEplObdCbParam MEM * pCbParam_p,
+ tEplObdSize * pObdSize_p);
+
+static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdEntryPtr pObdEntry_p,
+ tEplObdSubEntryPtr pSubEntry_p,
+ tEplObdCbParam MEM * pCbParam_p,
+ void *pSrcData_p,
+ void *pDstData_p,
+ tEplObdSize ObdSize_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdInit()
+//
+// Description: initializes the first instance
+//
+// Parameters: pInitParam_p = init parameter
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_
+ tEplObdInitParam MEM * pInitParam_p)
+{
+
+ tEplKernel Ret;
+ EPL_MCO_DELETE_INSTANCE_TABLE();
+
+ if (pInitParam_p == NULL) {
+ Ret = kEplSuccessful;
+ goto Exit;
+ }
+
+ Ret = EplObdAddInstance(EPL_MCO_PTR_INSTANCE_PTR_ pInitParam_p);
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdAddInstance()
+//
+// Description: adds a new instance
+//
+// Parameters: pInitParam_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_
+ tEplObdInitParam MEM *
+ pInitParam_p)
+{
+
+ EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret;
+
+ // check if pointer to instance pointer valid
+ // get free instance and set the globale instance pointer
+ // set also the instance addr to parameterlist
+ EPL_MCO_CHECK_PTR_INSTANCE_PTR();
+ EPL_MCO_GET_FREE_INSTANCE_PTR();
+ EPL_MCO_SET_PTR_INSTANCE_PTR();
+
+ // save init parameters
+ EPL_MEMCPY(&EPL_MCO_GLB_VAR(m_ObdInitParam), pInitParam_p,
+ sizeof(tEplObdInitParam));
+
+ // clear callback function for command LOAD and STORE
+ EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = NULL;
+
+ // sign instance as used
+ EPL_MCO_WRITE_INSTANCE_STATE(kStateUsed);
+
+ // initialize object dictionary
+ // so all all VarEntries will be initialized to trash object and default values will be set to current data
+ Ret = EplObdAccessOdPart(EPL_MCO_INSTANCE_PTR_
+ kEplObdPartAll, kEplObdDirInit);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdDeleteInstance()
+//
+// Description: delete instance
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if (EPL_USE_DELETEINST_FUNC != FALSE)
+EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR)
+{
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ // sign instance as unused
+ EPL_MCO_WRITE_INSTANCE_STATE(kStateUnused);
+
+ return kEplSuccessful;
+
+}
+#endif // (EPL_USE_DELETEINST_FUNC != FALSE)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdWriteEntry()
+//
+// Description: Function writes data to an OBD entry. Strings
+// are stored with added '\0' character.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p)
+{
+
+ tEplKernel Ret;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pSubEntry;
+ tEplObdCbParam MEM CbParam;
+ void MEM *pDstData;
+ tEplObdSize ObdSize;
+
+ Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
+ uiIndex_p,
+ uiSubIndex_p,
+ pSrcData_p,
+ &pDstData,
+ Size_p,
+ &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
+ pObdEntry,
+ pSubEntry,
+ &CbParam, pSrcData_p, pDstData, ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdReadEntry()
+//
+// Description: The function reads an object entry. The application
+// can always read the data even if attrib kEplObdAccRead
+// is not set. The attrib is only checked up for SDO transfer.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index oof the OD entry to read
+// uiSubIndex_p = Subindex to read
+// pDstData_p = pointer to the buffer for data
+// Offset_p = offset in data for read access
+// pSize_p = IN: Size of the buffer
+// OUT: number of readed Bytes
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p)
+{
+
+ tEplKernel Ret;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pSubEntry;
+ tEplObdCbParam MEM CbParam;
+ void *pSrcData;
+ tEplObdSize ObdSize;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ ASSERT(pDstData_p != NULL);
+ ASSERT(pSize_p != NULL);
+
+ // get address of index and subindex entry
+ Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
+ uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get pointer to object data
+ pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
+
+ // check source pointer
+ if (pSrcData == NULL) {
+ Ret = kEplObdReadViolation;
+ goto Exit;
+ }
+ //------------------------------------------------------------------------
+ // address of source data to structure of callback parameters
+ // so callback function can change this data before reading
+ CbParam.m_uiIndex = uiIndex_p;
+ CbParam.m_uiSubIndex = uiSubIndex_p;
+ CbParam.m_pArg = pSrcData;
+ CbParam.m_ObdEvent = kEplObdEvPreRead;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry->m_fpCallback, &CbParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get size of data and check if application has reserved enough memory
+ ObdSize = EplObdGetDataSizeIntern(pSubEntry);
+ // check if offset given and calc correct number of bytes to read
+ if (*pSize_p < ObdSize) {
+ Ret = kEplObdValueLengthError;
+ goto Exit;
+ }
+ // read value from object
+ EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
+ *pSize_p = ObdSize;
+
+ // write address of destination data to structure of callback parameters
+ // so callback function can change this data after reading
+ CbParam.m_pArg = pDstData_p;
+ CbParam.m_ObdEvent = kEplObdEvPostRead;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry->m_fpCallback, &CbParam);
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdAccessOdPart()
+//
+// Description: restores default values of one part of OD
+//
+// Parameters: ObdPart_p
+// Direction_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdPart ObdPart_p,
+ tEplObdDir Direction_p)
+{
+
+ tEplKernel Ret = kEplSuccessful;
+ BOOL fPartFount;
+ tEplObdEntryPtr pObdEntry;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ // part always has to be unequal to NULL
+ pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pPart);
+ ASSERTMSG(pObdEntry != NULL,
+ "EplObdAccessOdPart(): no OD part is defined!\n");
+
+ // if ObdPart_p is not valid fPartFound keeps FALSE and function returns kEplObdIllegalPart
+ fPartFount = FALSE;
+
+ // access to part
+ if ((ObdPart_p & kEplObdPartGen) != 0) {
+ fPartFount = TRUE;
+
+ Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
+ kEplObdPartGen, pObdEntry,
+ Direction_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+ // access to manufacturer part
+ pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pManufacturerPart);
+
+ if (((ObdPart_p & kEplObdPartMan) != 0) && (pObdEntry != NULL)) {
+ fPartFount = TRUE;
+
+ Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
+ kEplObdPartMan, pObdEntry,
+ Direction_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+ // access to device part
+ pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pDevicePart);
+
+ if (((ObdPart_p & kEplObdPartDev) != 0) && (pObdEntry != NULL)) {
+ fPartFount = TRUE;
+
+ Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
+ kEplObdPartDev, pObdEntry,
+ Direction_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+ {
+ // access to user part
+ pObdEntry = EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart);
+
+ if (((ObdPart_p & kEplObdPartUsr) != 0) && (pObdEntry != NULL)) {
+ fPartFount = TRUE;
+
+ Ret = EplObdAccessOdPartIntern(EPL_MCO_INSTANCE_PTR_
+ kEplObdPartUsr,
+ pObdEntry, Direction_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+ }
+#endif
+
+ // no access to an OD part was done? illegal OD part was specified!
+ if (fPartFount == FALSE) {
+ Ret = kEplObdIllegalPart;
+ }
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdDefineVar()
+//
+// Description: defines a variable in OD
+//
+// Parameters: pEplVarParam_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplVarParam MEM * pVarParam_p)
+{
+
+ tEplKernel Ret;
+ tEplObdVarEntry MEM *pVarEntry;
+ tEplVarParamValid VarValid;
+ tEplObdSubEntryPtr pSubindexEntry;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ ASSERT(pVarParam_p != NULL); // is not allowed to be NULL
+
+ // get address of subindex entry
+ Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
+ pVarParam_p->m_uiIndex,
+ pVarParam_p->m_uiSubindex, NULL, &pSubindexEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get var entry
+ Ret = EplObdGetVarEntry(pSubindexEntry, &pVarEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ VarValid = pVarParam_p->m_ValidFlag;
+
+ // copy only this values, which valid flag is set
+ if ((VarValid & kVarValidSize) != 0) {
+ if (pSubindexEntry->m_Type != kEplObdTypDomain) {
+ tEplObdSize DataSize;
+
+ // check passed size parameter
+ DataSize = EplObdGetObjectSize(pSubindexEntry);
+ if (DataSize != pVarParam_p->m_Size) { // size of variable does not match
+ Ret = kEplObdValueLengthError;
+ goto Exit;
+ }
+ } else { // size can be set only for objects of type DOMAIN
+ pVarEntry->m_Size = pVarParam_p->m_Size;
+ }
+ }
+
+ if ((VarValid & kVarValidData) != 0) {
+ pVarEntry->m_pData = pVarParam_p->m_pData;
+ }
+/*
+ #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
+ {
+ if ((VarValid & kVarValidCallback) != 0)
+ {
+ pVarEntry->m_fpCallback = pVarParam_p->m_fpCallback;
+ }
+
+ if ((VarValid & kVarValidArg) != 0)
+ {
+ pVarEntry->m_pArg = pVarParam_p->m_pArg;
+ }
+ }
+ #endif
+*/
+ // Ret is already set to kEplSuccessful from ObdGetVarIntern()
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetObjectDataPtr()
+//
+// Description: It returnes the current data pointer. But if object is an
+// constant object it returnes the default pointer.
+//
+// Parameters: uiIndex_p = Index of the entry
+// uiSubindex_p = Subindex of the entry
+//
+// Return: void * = pointer to object data
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT void *PUBLIC EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p)
+{
+ tEplKernel Ret;
+ void *pData;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pObdSubEntry;
+
+ // get pointer to index structure
+ Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
+ uiIndex_p, &pObdEntry);
+ if (Ret != kEplSuccessful) {
+ pData = NULL;
+ goto Exit;
+ }
+ // get pointer to subindex structure
+ Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
+ if (Ret != kEplSuccessful) {
+ pData = NULL;
+ goto Exit;
+ }
+ // get Datapointer
+ pData = EplObdGetObjectDataPtrIntern(pObdSubEntry);
+
+ Exit:
+ return pData;
+
+}
+
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdRegisterUserOd()
+//
+// Description: function registers the user OD
+//
+// Parameters: pUserOd_p =pointer to user ODd
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdEntryPtr pUserOd_p)
+{
+
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ EPL_MCO_GLB_VAR(m_ObdInitParam.m_pUserPart) = pUserOd_p;
+
+ return kEplSuccessful;
+
+}
+
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdInitVarEntry()
+//
+// Description: function to initialize VarEntry dependened on object type
+//
+// Parameters: pVarEntry_p = pointer to var entry structure
+// Type_p = object type
+// ObdSize_p = size of object data
+//
+// Returns: none
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT void PUBLIC EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdVarEntry MEM * pVarEntry_p,
+ tEplObdType Type_p,
+ tEplObdSize ObdSize_p)
+{
+/*
+ #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
+ {
+ // reset pointer to VAR callback and argument
+ pVarEntry_p->m_fpCallback = NULL;
+ pVarEntry_p->m_pArg = NULL;
+ }
+ #endif
+*/
+
+// 10-dec-2004 r.d.: this function will not be used for strings
+ if ((Type_p == kEplObdTypDomain))
+// (bType_p == kEplObdTypVString) /* ||
+// (bType_p == kEplObdTypOString) ||
+// (bType_p == kEplObdTypUString) */ )
+ {
+ // variables which are defined as DOMAIN or VSTRING should not point to
+ // trash object, because this trash object contains only 8 bytes. DOMAINS or
+ // STRINGS can be longer.
+ pVarEntry_p->m_pData = NULL;
+ pVarEntry_p->m_Size = 0;
+ } else {
+ // set address to variable data to trash object
+ // This prevents an access violation if user forgets to call EplObdDefineVar()
+ // for this variable but mappes it in a PDO.
+ pVarEntry_p->m_pData = &abEplObdTrashObject_g[0];
+ pVarEntry_p->m_Size = ObdSize_p;
+ }
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetDataSize()
+//
+// Description: function to initialize VarEntry dependened on object type
+//
+// gets the data size of an object
+// for string objects it returnes the string length
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
+// uiIndex_p = Index
+// uiSubIndex_p= Subindex
+//
+// Return: tEplObdSize
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p)
+{
+ tEplKernel Ret;
+ tEplObdSize ObdSize;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pObdSubEntry;
+
+ // get pointer to index structure
+ Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
+ uiIndex_p, &pObdEntry);
+ if (Ret != kEplSuccessful) {
+ ObdSize = 0;
+ goto Exit;
+ }
+ // get pointer to subindex structure
+ Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
+ if (Ret != kEplSuccessful) {
+ ObdSize = 0;
+ goto Exit;
+ }
+ // get size
+ ObdSize = EplObdGetDataSizeIntern(pObdSubEntry);
+ Exit:
+ return ObdSize;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetNodeId()
+//
+// Description: function returns nodeid from entry 0x1F93
+//
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR = Instancepointer
+//
+// Return: unsigned int = Node Id
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR)
+{
+ tEplKernel Ret;
+ tEplObdSize ObdSize;
+ BYTE bNodeId;
+
+ bNodeId = 0;
+ ObdSize = sizeof(bNodeId);
+ Ret = EplObdReadEntry(EPL_MCO_PTR_INSTANCE_PTR_
+ EPL_OBD_NODE_ID_INDEX,
+ EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ bNodeId = EPL_C_ADR_INVALID;
+ goto Exit;
+ }
+
+ Exit:
+ return (unsigned int)bNodeId;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdSetNodeId()
+//
+// Description: function sets nodeid in entry 0x1F93
+//
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
+// uiNodeId_p = Node Id to set
+// NodeIdType_p= Type on which way the Node Id was set
+//
+// Return: tEplKernel = Errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_PTR_INSTANCE_PTR_
+ unsigned int uiNodeId_p,
+ tEplObdNodeIdType NodeIdType_p)
+{
+ tEplKernel Ret;
+ tEplObdSize ObdSize;
+ BYTE fHwBool;
+ BYTE bNodeId;
+
+ // check Node Id
+ if (uiNodeId_p == EPL_C_ADR_INVALID) {
+ Ret = kEplInvalidNodeId;
+ goto Exit;
+ }
+ bNodeId = (BYTE) uiNodeId_p;
+ ObdSize = sizeof(BYTE);
+ // write NodeId to OD entry
+ Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR_
+ EPL_OBD_NODE_ID_INDEX,
+ EPL_OBD_NODE_ID_SUBINDEX, &bNodeId, ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // set HWBOOL-Flag in Subindex EPL_OBD_NODE_ID_HWBOOL_SUBINDEX
+ switch (NodeIdType_p) {
+ // type unknown
+ case kEplObdNodeIdUnknown:
+ {
+ fHwBool = OBD_FALSE;
+ break;
+ }
+
+ case kEplObdNodeIdSoftware:
+ {
+ fHwBool = OBD_FALSE;
+ break;
+ }
+
+ case kEplObdNodeIdHardware:
+ {
+ fHwBool = OBD_TRUE;
+ break;
+ }
+
+ default:
+ {
+ fHwBool = OBD_FALSE;
+ }
+
+ } // end of switch (NodeIdType_p)
+
+ // write flag
+ ObdSize = sizeof(fHwBool);
+ Ret = EplObdWriteEntry(EPL_MCO_PTR_INSTANCE_PTR
+ EPL_OBD_NODE_ID_INDEX,
+ EPL_OBD_NODE_ID_HWBOOL_SUBINDEX,
+ &fHwBool, ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdIsNumerical()
+//
+// Description: function checks if a entry is numerical or not
+//
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
+// uiIndex_p = Index
+// uiSubIndex_p = Subindex
+// pfEntryNumerical_p = pointer to BOOL for returnvalue
+// -> TRUE if entry a numerical value
+// -> FALSE if entry not a numerical value
+//
+// Return: tEplKernel = Errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ BOOL * pfEntryNumerical_p)
+{
+ tEplKernel Ret;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pObdSubEntry;
+
+ // get pointer to index structure
+ Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
+ uiIndex_p, &pObdEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get pointer to subindex structure
+ Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Ret = EplObdIsNumericalIntern(pObdSubEntry, pfEntryNumerical_p);
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdReadEntryToLe()
+//
+// Description: The function reads an object entry from the byteoder
+// of the system to the little endian byteorder for numerical values.
+// For other types a normal read will be processed. This is usefull for
+// the PDO and SDO module. The application
+// can always read the data even if attrib kEplObdAccRead
+// is not set. The attrib is only checked up for SDO transfer.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry to read
+// uiSubIndex_p = Subindex to read
+// pDstData_p = pointer to the buffer for data
+// Offset_p = offset in data for read access
+// pSize_p = IN: Size of the buffer
+// OUT: number of readed Bytes
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p)
+{
+ tEplKernel Ret;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pSubEntry;
+ tEplObdCbParam MEM CbParam;
+ void *pSrcData;
+ tEplObdSize ObdSize;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ ASSERT(pDstData_p != NULL);
+ ASSERT(pSize_p != NULL);
+
+ // get address of index and subindex entry
+ Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
+ uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get pointer to object data
+ pSrcData = EplObdGetObjectDataPtrIntern(pSubEntry);
+
+ // check source pointer
+ if (pSrcData == NULL) {
+ Ret = kEplObdReadViolation;
+ goto Exit;
+ }
+ //------------------------------------------------------------------------
+ // address of source data to structure of callback parameters
+ // so callback function can change this data before reading
+ CbParam.m_uiIndex = uiIndex_p;
+ CbParam.m_uiSubIndex = uiSubIndex_p;
+ CbParam.m_pArg = pSrcData;
+ CbParam.m_ObdEvent = kEplObdEvPreRead;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry->m_fpCallback, &CbParam);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get size of data and check if application has reserved enough memory
+ ObdSize = EplObdGetDataSizeIntern(pSubEntry);
+ // check if offset given and calc correct number of bytes to read
+ if (*pSize_p < ObdSize) {
+ Ret = kEplObdValueLengthError;
+ goto Exit;
+ }
+ // check if numerical type
+ switch (pSubEntry->m_Type) {
+ //-----------------------------------------------
+ // types without ami
+ case kEplObdTypVString:
+ case kEplObdTypOString:
+ case kEplObdTypDomain:
+ default:
+ {
+ // read value from object
+ EPL_MEMCPY(pDstData_p, pSrcData, ObdSize);
+ break;
+ }
+
+ //-----------------------------------------------
+ // numerical type which needs ami-write
+ // 8 bit or smaller values
+ case kEplObdTypBool:
+ case kEplObdTypInt8:
+ case kEplObdTypUInt8:
+ {
+ AmiSetByteToLe(pDstData_p, *((BYTE *) pSrcData));
+ break;
+ }
+
+ // 16 bit values
+ case kEplObdTypInt16:
+ case kEplObdTypUInt16:
+ {
+ AmiSetWordToLe(pDstData_p, *((WORD *) pSrcData));
+ break;
+ }
+
+ // 24 bit values
+ case kEplObdTypInt24:
+ case kEplObdTypUInt24:
+ {
+ AmiSetDword24ToLe(pDstData_p, *((DWORD *) pSrcData));
+ break;
+ }
+
+ // 32 bit values
+ case kEplObdTypInt32:
+ case kEplObdTypUInt32:
+ case kEplObdTypReal32:
+ {
+ AmiSetDwordToLe(pDstData_p, *((DWORD *) pSrcData));
+ break;
+ }
+
+ // 40 bit values
+ case kEplObdTypInt40:
+ case kEplObdTypUInt40:
+ {
+ AmiSetQword40ToLe(pDstData_p, *((QWORD *) pSrcData));
+ break;
+ }
+
+ // 48 bit values
+ case kEplObdTypInt48:
+ case kEplObdTypUInt48:
+ {
+ AmiSetQword48ToLe(pDstData_p, *((QWORD *) pSrcData));
+ break;
+ }
+
+ // 56 bit values
+ case kEplObdTypInt56:
+ case kEplObdTypUInt56:
+ {
+ AmiSetQword56ToLe(pDstData_p, *((QWORD *) pSrcData));
+ break;
+ }
+
+ // 64 bit values
+ case kEplObdTypInt64:
+ case kEplObdTypUInt64:
+ case kEplObdTypReal64:
+ {
+ AmiSetQword64ToLe(pDstData_p, *((QWORD *) pSrcData));
+ break;
+ }
+
+ // time of day
+ case kEplObdTypTimeOfDay:
+ case kEplObdTypTimeDiff:
+ {
+ AmiSetTimeOfDay(pDstData_p, ((tTimeOfDay *) pSrcData));
+ break;
+ }
+
+ } // end of switch(pSubEntry->m_Type)
+
+ *pSize_p = ObdSize;
+
+ // write address of destination data to structure of callback parameters
+ // so callback function can change this data after reading
+ CbParam.m_pArg = pDstData_p;
+ CbParam.m_ObdEvent = kEplObdEvPostRead;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry->m_fpCallback, &CbParam);
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdWriteEntryFromLe()
+//
+// Description: Function writes data to an OBD entry from a source with
+// little endian byteorder to the od with system specuific
+// byteorder. Not numerical values will only by copied. Strings
+// are stored with added '\0' character.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p)
+{
+ tEplKernel Ret;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pSubEntry;
+ tEplObdCbParam MEM CbParam;
+ void MEM *pDstData;
+ tEplObdSize ObdSize;
+ QWORD qwBuffer;
+ void *pBuffer = &qwBuffer;
+
+ Ret = EplObdWriteEntryPre(EPL_MCO_INSTANCE_PTR_
+ uiIndex_p,
+ uiSubIndex_p,
+ pSrcData_p,
+ &pDstData,
+ Size_p,
+ &pObdEntry, &pSubEntry, &CbParam, &ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ // check if numerical type
+ switch (pSubEntry->m_Type) {
+ //-----------------------------------------------
+ // types without ami
+ default:
+ { // do nothing, i.e. use the given source pointer
+ pBuffer = pSrcData_p;
+ break;
+ }
+
+ //-----------------------------------------------
+ // numerical type which needs ami-write
+ // 8 bit or smaller values
+ case kEplObdTypBool:
+ case kEplObdTypInt8:
+ case kEplObdTypUInt8:
+ {
+ *((BYTE *) pBuffer) = AmiGetByteFromLe(pSrcData_p);
+ break;
+ }
+
+ // 16 bit values
+ case kEplObdTypInt16:
+ case kEplObdTypUInt16:
+ {
+ *((WORD *) pBuffer) = AmiGetWordFromLe(pSrcData_p);
+ break;
+ }
+
+ // 24 bit values
+ case kEplObdTypInt24:
+ case kEplObdTypUInt24:
+ {
+ *((DWORD *) pBuffer) = AmiGetDword24FromLe(pSrcData_p);
+ break;
+ }
+
+ // 32 bit values
+ case kEplObdTypInt32:
+ case kEplObdTypUInt32:
+ case kEplObdTypReal32:
+ {
+ *((DWORD *) pBuffer) = AmiGetDwordFromLe(pSrcData_p);
+ break;
+ }
+
+ // 40 bit values
+ case kEplObdTypInt40:
+ case kEplObdTypUInt40:
+ {
+ *((QWORD *) pBuffer) = AmiGetQword40FromLe(pSrcData_p);
+ break;
+ }
+
+ // 48 bit values
+ case kEplObdTypInt48:
+ case kEplObdTypUInt48:
+ {
+ *((QWORD *) pBuffer) = AmiGetQword48FromLe(pSrcData_p);
+ break;
+ }
+
+ // 56 bit values
+ case kEplObdTypInt56:
+ case kEplObdTypUInt56:
+ {
+ *((QWORD *) pBuffer) = AmiGetQword56FromLe(pSrcData_p);
+ break;
+ }
+
+ // 64 bit values
+ case kEplObdTypInt64:
+ case kEplObdTypUInt64:
+ case kEplObdTypReal64:
+ {
+ *((QWORD *) pBuffer) = AmiGetQword64FromLe(pSrcData_p);
+ break;
+ }
+
+ // time of day
+ case kEplObdTypTimeOfDay:
+ case kEplObdTypTimeDiff:
+ {
+ AmiGetTimeOfDay(pBuffer, ((tTimeOfDay *) pSrcData_p));
+ break;
+ }
+
+ } // end of switch(pSubEntry->m_Type)
+
+ Ret = EplObdWriteEntryPost(EPL_MCO_INSTANCE_PTR_
+ pObdEntry,
+ pSubEntry,
+ &CbParam, pBuffer, pDstData, ObdSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetAccessType()
+//
+// Description: Function returns accesstype of the entry
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pAccessTyp_p = pointer to buffer to store accesstype
+//
+// Return: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ tEplObdAccess * pAccessTyp_p)
+{
+ tEplKernel Ret;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pObdSubEntry;
+
+ // get pointer to index structure
+ Ret = EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam),
+ uiIndex_p, &pObdEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get pointer to subindex structure
+ Ret = EplObdGetSubindexIntern(pObdEntry, uiSubIndex_p, &pObdSubEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get accessType
+ *pAccessTyp_p = pObdSubEntry->m_Access;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdSearchVarEntry()
+//
+// Description: gets variable from OD
+//
+// Parameters: uiIndex_p = index of the var entry to search
+// uiSubindex_p = subindex of var entry to search
+// ppVarEntry_p = pointer to the pointer to the varentry
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdVarEntry MEM ** ppVarEntry_p)
+{
+
+ tEplKernel Ret;
+ tEplObdSubEntryPtr pSubindexEntry;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ // get address of subindex entry
+ Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
+ uiIndex_p, uiSubindex_p, NULL, &pSubindexEntry);
+ if (Ret == kEplSuccessful) {
+ // get var entry
+ Ret = EplObdGetVarEntry(pSubindexEntry, ppVarEntry_p);
+ }
+
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+EPL_MCO_DECL_INSTANCE_FCT()
+//---------------------------------------------------------------------------
+//
+// Function: EplObdCallObjectCallback()
+//
+// Description: calls callback function of an object or of a variable
+//
+// Parameters: fpCallback_p
+// pCbParam_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplObdCallObjectCallback(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdCallback fpCallback_p,
+ tEplObdCbParam MEM * pCbParam_p)
+{
+
+ tEplKernel Ret;
+ tEplObdCallback MEM fpCallback;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ ASSERT(pCbParam_p != NULL);
+
+ Ret = kEplSuccessful;
+
+ // check address of callback function before calling it
+ if (fpCallback_p != NULL) {
+ // KEIL C51 V6.01 has a bug.
+ // Therefore the parameter fpCallback_p has to be copied in local variable fpCallback.
+ fpCallback = fpCallback_p;
+
+ // call callback function for this object
+ Ret = fpCallback(EPL_MCO_INSTANCE_PARAM_IDX_()
+ pCbParam_p);
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetDataSizeIntern()
+//
+// Description: gets the data size of an object
+// for string objects it returnes the string length
+//
+// Parameters: pSubIndexEntry_p
+//
+// Return: tEplObdSize
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplObdSize EplObdGetDataSizeIntern(tEplObdSubEntryPtr pSubIndexEntry_p)
+{
+
+ tEplObdSize DataSize;
+ void MEM *pData;
+
+ // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
+ // then the current pointer is always NULL. The function
+ // returns the length of default string.
+ DataSize = EplObdGetObjectSize(pSubIndexEntry_p);
+
+ if (pSubIndexEntry_p->m_Type == kEplObdTypVString) {
+ // The pointer to current value can be received from EplObdGetObjectCurrentPtr()
+ pData =
+ ((void MEM *)EplObdGetObjectCurrentPtr(pSubIndexEntry_p));
+ if (pData != NULL) {
+ DataSize =
+ EplObdGetStrLen((void *)pData, DataSize,
+ pSubIndexEntry_p->m_Type);
+ }
+
+ }
+
+ return DataSize;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetStrLen()
+//
+// Description: The function calculates the length of string. The '\0'
+// character is included!!
+//
+// Parameters: pObjData_p = pointer to string
+// ObjLen_p = max. length of objectr entry
+// bObjType_p = object type (VSTRING, ...)
+//
+// Returns: string length + 1
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplObdSize EplObdGetStrLen(void *pObjData_p,
+ tEplObdSize ObjLen_p, tEplObdType ObjType_p)
+{
+
+ tEplObdSize StrLen = 0;
+ BYTE *pbString;
+
+ if (pObjData_p == NULL) {
+ goto Exit;
+ }
+ //----------------------------------------
+ // Visible String: data format byte
+ if (ObjType_p == kEplObdTypVString) {
+ pbString = pObjData_p;
+
+ for (StrLen = 0; StrLen < ObjLen_p; StrLen++) {
+ if (*pbString == '\0') {
+ StrLen++;
+ break;
+ }
+
+ pbString++;
+ }
+ }
+ //----------------------------------------
+ // other string types ...
+
+ Exit:
+ return (StrLen);
+
+}
+
+#if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdCheckObjectRange()
+//
+// Description: function to check value range of object data
+//
+// NOTICE: The pointer of data (pData_p) must point out to an even address,
+// if ObjType is unequal to kEplObdTypInt8 or kEplObdTypUInt8! But it is
+// always realiced because pointer m_pDefault points always to an
+// array of the SPECIFIED type.
+//
+// Parameters: pSubindexEntry_p
+// pData_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplObdCheckObjectRange(tEplObdSubEntryPtr pSubindexEntry_p,
+ void *pData_p)
+{
+
+ tEplKernel Ret;
+ void *pRangeData;
+
+ ASSERTMSG(pSubindexEntry_p != NULL,
+ "EplObdCheckObjectRange(): no address to subindex struct!\n");
+
+ Ret = kEplSuccessful;
+
+ // check if data range has to be checked
+ if ((pSubindexEntry_p->m_Access & kEplObdAccRange) == 0) {
+ goto Exit;
+ }
+ // get address of default data
+ pRangeData = pSubindexEntry_p->m_pDefault;
+
+ // jump to called object type
+ switch ((tEplObdType) pSubindexEntry_p->m_Type) {
+ // -----------------------------------------------------------------
+ // ObdType kEplObdTypBool will not be checked because there are only
+ // two possible values 0 or 1.
+
+ // -----------------------------------------------------------------
+ // ObdTypes which has to be check up because numerical values
+ case kEplObdTypInt8:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdInteger8 *) pData_p) <
+ *((tEplObdInteger8 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdInteger8 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdInteger8 *) pData_p) >
+ *((tEplObdInteger8 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ case kEplObdTypUInt8:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdUnsigned8 *) pData_p) <
+ *((tEplObdUnsigned8 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdUnsigned8 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdUnsigned8 *) pData_p) >
+ *((tEplObdUnsigned8 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ case kEplObdTypInt16:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdInteger16 *) pData_p) <
+ *((tEplObdInteger16 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdInteger16 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdInteger16 *) pData_p) >
+ *((tEplObdInteger16 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ case kEplObdTypUInt16:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdUnsigned16 *) pData_p) <
+ *((tEplObdUnsigned16 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdUnsigned16 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdUnsigned16 *) pData_p) >
+ *((tEplObdUnsigned16 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ case kEplObdTypInt32:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdInteger32 *) pData_p) <
+ *((tEplObdInteger32 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdInteger32 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdInteger32 *) pData_p) >
+ *((tEplObdInteger32 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ case kEplObdTypUInt32:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdUnsigned32 *) pData_p) <
+ *((tEplObdUnsigned32 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdUnsigned32 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdUnsigned32 *) pData_p) >
+ *((tEplObdUnsigned32 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ case kEplObdTypReal32:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdReal32 *) pData_p) <
+ *((tEplObdReal32 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdReal32 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdReal32 *) pData_p) >
+ *((tEplObdReal32 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt40:
+ case kEplObdTypInt48:
+ case kEplObdTypInt56:
+ case kEplObdTypInt64:
+
+ // switch to lower limit
+ pRangeData = ((signed QWORD *)pRangeData) + 1;
+
+ // check if value is to low
+ if (*((signed QWORD *)pData_p) < *((signed QWORD *)pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((signed QWORD *)pRangeData) + 1;
+
+ // check if value is to high
+ if (*((signed QWORD *)pData_p) > *((signed QWORD *)pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypUInt40:
+ case kEplObdTypUInt48:
+ case kEplObdTypUInt56:
+ case kEplObdTypUInt64:
+
+ // switch to lower limit
+ pRangeData = ((unsigned QWORD *)pRangeData) + 1;
+
+ // check if value is to low
+ if (*((unsigned QWORD *)pData_p) <
+ *((unsigned QWORD *)pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((unsigned QWORD *)pRangeData) + 1;
+
+ // check if value is to high
+ if (*((unsigned QWORD *)pData_p) >
+ *((unsigned QWORD *)pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypReal64:
+
+ // switch to lower limit
+ pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
+
+ // check if value is to low
+ if (*((tEplObdReal64 *) pData_p) <
+ *((tEplObdReal64 *) pRangeData)) {
+ Ret = kEplObdValueTooLow;
+ break;
+ }
+ // switch to higher limit
+ pRangeData = ((tEplObdReal64 *) pRangeData) + 1;
+
+ // check if value is to high
+ if (*((tEplObdReal64 *) pData_p) >
+ *((tEplObdReal64 *) pRangeData)) {
+ Ret = kEplObdValueTooHigh;
+ }
+
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypTimeOfDay:
+ case kEplObdTypTimeDiff:
+ break;
+
+ // -----------------------------------------------------------------
+ // ObdTypes kEplObdTypXString and kEplObdTypDomain can not be checkt because
+ // they have no numerical value.
+ default:
+
+ Ret = kEplObdUnknownObjectType;
+ break;
+ }
+
+ Exit:
+
+ return Ret;
+
+}
+#endif // (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdWriteEntryPre()
+//
+// Description: Function prepares write of data to an OBD entry. Strings
+// are stored with added '\0' character.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplObdWriteEntryPre(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ void **ppDstData_p,
+ tEplObdSize Size_p,
+ tEplObdEntryPtr * ppObdEntry_p,
+ tEplObdSubEntryPtr * ppSubEntry_p,
+ tEplObdCbParam MEM * pCbParam_p,
+ tEplObdSize * pObdSize_p)
+{
+
+ tEplKernel Ret;
+ tEplObdEntryPtr pObdEntry;
+ tEplObdSubEntryPtr pSubEntry;
+ tEplObdAccess Access;
+ void MEM *pDstData;
+ tEplObdSize ObdSize;
+ BOOL fEntryNumerical;
+
+#if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
+ tEplObdVStringDomain MEM MemVStringDomain;
+ void MEM *pCurrData;
+#endif
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ ASSERT(pSrcData_p != NULL); // should never be NULL
+
+ //------------------------------------------------------------------------
+ // get address of index and subindex entry
+ Ret = EplObdGetEntry(EPL_MCO_INSTANCE_PTR_
+ uiIndex_p, uiSubIndex_p, &pObdEntry, &pSubEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // get pointer to object data
+ pDstData = (void MEM *)EplObdGetObjectDataPtrIntern(pSubEntry);
+
+ Access = (tEplObdAccess) pSubEntry->m_Access;
+
+ // check access for write
+ // access violation if adress to current value is NULL
+ if (((Access & kEplObdAccConst) != 0) || (pDstData == NULL)) {
+ Ret = kEplObdAccessViolation;
+ goto Exit;
+ }
+ //------------------------------------------------------------------------
+ // get size of object
+ // -as ObdSize = ObdGetObjectSize (pSubEntry);
+
+ //------------------------------------------------------------------------
+ // To use the same callback function for ObdWriteEntry as well as for
+ // an SDO download call at first (kEplObdEvPre...) the callback function
+ // with the argument pointer to object size.
+ pCbParam_p->m_uiIndex = uiIndex_p;
+ pCbParam_p->m_uiSubIndex = uiSubIndex_p;
+
+ // Because object size and object pointer are
+ // adapted by user callback function, re-read
+ // this values.
+ ObdSize = EplObdGetObjectSize(pSubEntry);
+ pDstData = (void MEM *)EplObdGetObjectDataPtrIntern(pSubEntry);
+
+ // 09-dec-2004 r.d.:
+ // Function EplObdWriteEntry() calls new event kEplObdEvWrStringDomain
+ // for String or Domain which lets called module directly change
+ // the data pointer or size. This prevents a recursive call to
+ // the callback function if it calls EplObdGetEntry().
+#if (EPL_OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
+ if ((pSubEntry->m_Type == kEplObdTypVString) ||
+ (pSubEntry->m_Type == kEplObdTypDomain) ||
+ (pSubEntry->m_Type == kEplObdTypOString)) {
+ if (pSubEntry->m_Type == kEplObdTypVString) {
+ // reserve one byte for 0-termination
+ // -as ObdSize -= 1;
+ Size_p += 1;
+ }
+ // fill out new arg-struct
+ MemVStringDomain.m_DownloadSize = Size_p;
+ MemVStringDomain.m_ObjSize = ObdSize;
+ MemVStringDomain.m_pData = pDstData;
+
+ pCbParam_p->m_ObdEvent = kEplObdEvWrStringDomain;
+ pCbParam_p->m_pArg = &MemVStringDomain;
+ // call user callback
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry->m_fpCallback,
+ pCbParam_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // write back new settings
+ pCurrData = pSubEntry->m_pCurrent;
+ if ((pSubEntry->m_Type == kEplObdTypVString)
+ || (pSubEntry->m_Type == kEplObdTypOString)) {
+ ((tEplObdVString MEM *) pCurrData)->m_Size =
+ MemVStringDomain.m_ObjSize;
+ ((tEplObdVString MEM *) pCurrData)->m_pString =
+ MemVStringDomain.m_pData;
+ } else // if (pSdosTableEntry_p->m_bObjType == kEplObdTypDomain)
+ {
+ ((tEplObdVarEntry MEM *) pCurrData)->m_Size =
+ MemVStringDomain.m_ObjSize;
+ ((tEplObdVarEntry MEM *) pCurrData)->m_pData =
+ (void MEM *)MemVStringDomain.m_pData;
+ }
+
+ // Because object size and object pointer are
+ // adapted by user callback function, re-read
+ // this values.
+ ObdSize = MemVStringDomain.m_ObjSize;
+ pDstData = (void MEM *)MemVStringDomain.m_pData;
+ }
+#endif //#if (OBD_USE_STRING_DOMAIN_IN_RAM != FALSE)
+
+ // 07-dec-2004 r.d.: size from application is needed because callback function can change the object size
+ // -as 16.11.04 CbParam.m_pArg = &ObdSize;
+ // 09-dec-2004 r.d.: CbParam.m_pArg = &Size_p;
+ pCbParam_p->m_pArg = &ObdSize;
+ pCbParam_p->m_ObdEvent = kEplObdEvInitWrite;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry->m_fpCallback, pCbParam_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if (Size_p > ObdSize) {
+ Ret = kEplObdValueLengthError;
+ goto Exit;
+ }
+
+ if (pSubEntry->m_Type == kEplObdTypVString) {
+ if (((char MEM *)pSrcData_p)[Size_p - 1] == '\0') { // last byte of source string contains null character
+
+ // reserve one byte in destination for 0-termination
+ Size_p -= 1;
+ } else if (Size_p >= ObdSize) { // source string is not 0-terminated
+ // and destination buffer is too short
+ Ret = kEplObdValueLengthError;
+ goto Exit;
+ }
+ }
+
+ Ret = EplObdIsNumericalIntern(pSubEntry, &fEntryNumerical);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if ((fEntryNumerical != FALSE)
+ && (Size_p != ObdSize)) {
+ // type is numerical, therefor size has to fit, but it does not.
+ Ret = kEplObdValueLengthError;
+ goto Exit;
+ }
+ // use given size, because non-numerical objects can be written with shorter values
+ ObdSize = Size_p;
+
+ // set output parameters
+ *pObdSize_p = ObdSize;
+ *ppObdEntry_p = pObdEntry;
+ *ppSubEntry_p = pSubEntry;
+ *ppDstData_p = pDstData;
+
+ // all checks are done
+ // the caller may now convert the numerial source value to platform byte order in a temporary buffer
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdWriteEntryPost()
+//
+// Description: Function finishes write of data to an OBD entry. Strings
+// are stored with added '\0' character.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplObdWriteEntryPost(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdEntryPtr pObdEntry_p,
+ tEplObdSubEntryPtr pSubEntry_p,
+ tEplObdCbParam MEM * pCbParam_p,
+ void *pSrcData_p,
+ void *pDstData_p,
+ tEplObdSize ObdSize_p)
+{
+
+ tEplKernel Ret;
+
+ // caller converted the source value to platform byte order
+ // now the range of the value may be checked
+
+#if (EPL_OBD_CHECK_OBJECT_RANGE != FALSE)
+ {
+ // check data range
+ Ret = EplObdCheckObjectRange(pSubEntry_p, pSrcData_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+#endif
+
+ // now call user callback function to check value
+ // write address of source data to structure of callback parameters
+ // so callback function can check this data
+ pCbParam_p->m_pArg = pSrcData_p;
+ pCbParam_p->m_ObdEvent = kEplObdEvPreWrite;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry_p->m_fpCallback, pCbParam_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // copy object data to OBD
+ EPL_MEMCPY(pDstData_p, pSrcData_p, ObdSize_p);
+
+ // terminate string with 0
+ if (pSubEntry_p->m_Type == kEplObdTypVString) {
+ ((char MEM *)pDstData_p)[ObdSize_p] = '\0';
+ }
+ // write address of destination to structure of callback parameters
+ // so callback function can change data subsequently
+ pCbParam_p->m_pArg = pDstData_p;
+ pCbParam_p->m_ObdEvent = kEplObdEvPostWrite;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry_p->m_fpCallback, pCbParam_p);
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetObjectSize()
+//
+// Description: function to get size of object
+// The function determines if an object type an fixed data type (BYTE, WORD, ...)
+// or non fixed object (string, domain). This information is used to decide
+// if download data are stored temporary or not. For objects with fixed data length
+// and types a value range checking can process.
+// For strings the function returns the whole object size not the
+// length of string.
+//
+// Parameters: pSubIndexEntry_p
+//
+// Return: tEplObdSize
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplObdSize EplObdGetObjectSize(tEplObdSubEntryPtr pSubIndexEntry_p)
+{
+
+ tEplObdSize DataSize = 0;
+ void *pData;
+
+ switch (pSubIndexEntry_p->m_Type) {
+ // -----------------------------------------------------------------
+ case kEplObdTypBool:
+
+ DataSize = 1;
+ break;
+
+ // -----------------------------------------------------------------
+ // ObdTypes which has to be check because numerical values
+ case kEplObdTypInt8:
+ DataSize = sizeof(tEplObdInteger8);
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypUInt8:
+ DataSize = sizeof(tEplObdUnsigned8);
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt16:
+ DataSize = sizeof(tEplObdInteger16);
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypUInt16:
+ DataSize = sizeof(tEplObdUnsigned16);
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt32:
+ DataSize = sizeof(tEplObdInteger32);
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypUInt32:
+ DataSize = sizeof(tEplObdUnsigned32);
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypReal32:
+ DataSize = sizeof(tEplObdReal32);
+ break;
+
+ // -----------------------------------------------------------------
+ // ObdTypes which has to be not checked because not NUM values
+ case kEplObdTypDomain:
+
+ pData = (void *)pSubIndexEntry_p->m_pCurrent;
+ if ((void MEM *)pData != (void MEM *)NULL) {
+ DataSize = ((tEplObdVarEntry MEM *) pData)->m_Size;
+ }
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypVString:
+ //case kEplObdTypUString:
+
+ // If OD entry is defined by macro EPL_OBD_SUBINDEX_ROM_VSTRING
+ // then the current pointer is always NULL. The function
+ // returns the length of default string.
+ pData = (void *)pSubIndexEntry_p->m_pCurrent;
+ if ((void MEM *)pData != (void MEM *)NULL) {
+ // The max. size of strings defined by STRING-Macro is stored in
+ // tEplObdVString of current value.
+ // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
+ DataSize = ((tEplObdVString MEM *) pData)->m_Size;
+ } else {
+ // The current position is not decleared. The string
+ // is located in ROM, therefor use default pointer.
+ pData = (void *)pSubIndexEntry_p->m_pDefault;
+ if ((CONST void ROM *)pData != (CONST void ROM *)NULL) {
+ // The max. size of strings defined by STRING-Macro is stored in
+ // tEplObdVString of default value.
+ DataSize =
+ ((CONST tEplObdVString ROM *) pData)->
+ m_Size;
+ }
+ }
+
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypOString:
+
+ pData = (void *)pSubIndexEntry_p->m_pCurrent;
+ if ((void MEM *)pData != (void MEM *)NULL) {
+ // The max. size of strings defined by STRING-Macro is stored in
+ // tEplObdVString of current value.
+ // (types tEplObdVString, tEplObdOString and tEplObdUString has the same members)
+ DataSize = ((tEplObdOString MEM *) pData)->m_Size;
+ } else {
+ // The current position is not decleared. The string
+ // is located in ROM, therefor use default pointer.
+ pData = (void *)pSubIndexEntry_p->m_pDefault;
+ if ((CONST void ROM *)pData != (CONST void ROM *)NULL) {
+ // The max. size of strings defined by STRING-Macro is stored in
+ // tEplObdVString of default value.
+ DataSize =
+ ((CONST tEplObdOString ROM *) pData)->
+ m_Size;
+ }
+ }
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt24:
+ case kEplObdTypUInt24:
+
+ DataSize = 3;
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt40:
+ case kEplObdTypUInt40:
+
+ DataSize = 5;
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt48:
+ case kEplObdTypUInt48:
+
+ DataSize = 6;
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt56:
+ case kEplObdTypUInt56:
+
+ DataSize = 7;
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypInt64:
+ case kEplObdTypUInt64:
+ case kEplObdTypReal64:
+
+ DataSize = 8;
+ break;
+
+ // -----------------------------------------------------------------
+ case kEplObdTypTimeOfDay:
+ case kEplObdTypTimeDiff:
+
+ DataSize = 6;
+ break;
+
+ // -----------------------------------------------------------------
+ default:
+ break;
+ }
+
+ return DataSize;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetObjectDefaultPtr()
+//
+// Description: function to get the default pointer (type specific)
+//
+// Parameters: pSubIndexEntry_p = pointer to subindex structure
+//
+// Returns: (void *) = pointer to default value
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static void *EplObdGetObjectDefaultPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
+{
+
+ void *pDefault;
+ tEplObdType Type;
+
+ ASSERTMSG(pSubIndexEntry_p != NULL,
+ "EplObdGetObjectDefaultPtr(): pointer to SubEntry not valid!\n");
+
+ // get address to default data from default pointer
+ pDefault = pSubIndexEntry_p->m_pDefault;
+ if (pDefault != NULL) {
+ // there are some special types, whose default pointer always is NULL or has to get from other structure
+ // get type from subindex structure
+ Type = pSubIndexEntry_p->m_Type;
+
+ // check if object type is a string value
+ if ((Type == kEplObdTypVString) /* ||
+ (Type == kEplObdTypUString) */ ) {
+
+ // EPL_OBD_SUBINDEX_RAM_VSTRING
+ // tEplObdSize m_Size; --> size of default string
+ // char * m_pDefString; --> pointer to default string
+ // char * m_pString; --> pointer to string in RAM
+ //
+ pDefault =
+ (void *)((tEplObdVString *) pDefault)->m_pString;
+ } else if (Type == kEplObdTypOString) {
+ pDefault =
+ (void *)((tEplObdOString *) pDefault)->m_pString;
+ }
+ }
+
+ return pDefault;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetVarEntry()
+//
+// Description: gets a variable entry of an object
+//
+// Parameters: pSubindexEntry_p
+// ppVarEntry_p
+//
+// Return: tCopKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplObdGetVarEntry(tEplObdSubEntryPtr pSubindexEntry_p,
+ tEplObdVarEntry MEM ** ppVarEntry_p)
+{
+
+ tEplKernel Ret = kEplObdVarEntryNotExist;
+
+ ASSERT(ppVarEntry_p != NULL); // is not allowed to be NULL
+ ASSERT(pSubindexEntry_p != NULL);
+
+ // check VAR-Flag - only this object points to variables
+ if ((pSubindexEntry_p->m_Access & kEplObdAccVar) != 0) {
+ // check if object is an array
+ if ((pSubindexEntry_p->m_Access & kEplObdAccArray) != 0) {
+ *ppVarEntry_p =
+ &((tEplObdVarEntry MEM *) pSubindexEntry_p->
+ m_pCurrent)[pSubindexEntry_p->m_uiSubIndex - 1];
+ } else {
+ *ppVarEntry_p =
+ (tEplObdVarEntry MEM *) pSubindexEntry_p->
+ m_pCurrent;
+ }
+
+ Ret = kEplSuccessful;
+ }
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetEntry()
+//
+// Description: gets a index entry from OD
+//
+// Parameters: uiIndex_p = Index number
+// uiSubindex_p = Subindex number
+// ppObdEntry_p = pointer to the pointer to the entry
+// ppObdSubEntry_p = pointer to the pointer to the subentry
+//
+// Return: tEplKernel
+
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplObdGetEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdEntryPtr * ppObdEntry_p,
+ tEplObdSubEntryPtr * ppObdSubEntry_p)
+{
+
+ tEplObdEntryPtr pObdEntry;
+ tEplObdCbParam MEM CbParam;
+ tEplKernel Ret;
+
+ // check for all API function if instance is valid
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ //------------------------------------------------------------------------
+ // get address of entry of index
+ Ret =
+ EplObdGetIndexIntern(&EPL_MCO_GLB_VAR(m_ObdInitParam), uiIndex_p,
+ &pObdEntry);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ //------------------------------------------------------------------------
+ // get address of entry of subindex
+ Ret = EplObdGetSubindexIntern(pObdEntry, uiSubindex_p, ppObdSubEntry_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ //------------------------------------------------------------------------
+ // call callback function to inform user/stack that an object will be searched
+ // if the called module returnes an error then we abort the searching with kEplObdIndexNotExist
+ CbParam.m_uiIndex = uiIndex_p;
+ CbParam.m_uiSubIndex = uiSubindex_p;
+ CbParam.m_pArg = NULL;
+ CbParam.m_ObdEvent = kEplObdEvCheckExist;
+ Ret = EplObdCallObjectCallback(EPL_MCO_INSTANCE_PTR_
+ pObdEntry->m_fpCallback, &CbParam);
+ if (Ret != kEplSuccessful) {
+ Ret = kEplObdIndexNotExist;
+ goto Exit;
+ }
+ //------------------------------------------------------------------------
+ // it is allowed to set ppObdEntry_p to NULL
+ // if so, no address will be written to calling function
+ if (ppObdEntry_p != NULL) {
+ *ppObdEntry_p = pObdEntry;
+ }
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetObjectCurrentPtr()
+//
+// Description: function to get Current pointer (type specific)
+//
+// Parameters: pSubIndexEntry_p
+//
+// Return: void MEM*
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static void MEM *EplObdGetObjectCurrentPtr(tEplObdSubEntryPtr pSubIndexEntry_p)
+{
+
+ void MEM *pData;
+ unsigned int uiArrayIndex;
+ tEplObdSize Size;
+
+ pData = pSubIndexEntry_p->m_pCurrent;
+
+ // check if constant object
+ if (pData != NULL) {
+ // check if object is an array
+ if ((pSubIndexEntry_p->m_Access & kEplObdAccArray) != 0) {
+ // calculate correct data pointer
+ uiArrayIndex = pSubIndexEntry_p->m_uiSubIndex - 1;
+ if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
+ Size = sizeof(tEplObdVarEntry);
+ } else {
+ Size = EplObdGetObjectSize(pSubIndexEntry_p);
+ }
+ pData = ((BYTE MEM *) pData) + (Size * uiArrayIndex);
+ }
+ // check if VarEntry
+ if ((pSubIndexEntry_p->m_Access & kEplObdAccVar) != 0) {
+ // The data pointer is stored in VarEntry->pData
+ pData = ((tEplObdVarEntry MEM *) pData)->m_pData;
+ }
+ // the default pointer is stored for strings in tEplObdVString
+ else if ((pSubIndexEntry_p->m_Type == kEplObdTypVString) /* ||
+ (pSubIndexEntry_p->m_Type == kEplObdTypUString) */
+ ) {
+ pData =
+ (void MEM *)((tEplObdVString MEM *) pData)->
+ m_pString;
+ } else if (pSubIndexEntry_p->m_Type == kEplObdTypOString) {
+ pData =
+ (void MEM *)((tEplObdOString MEM *) pData)->
+ m_pString;
+ }
+ }
+
+ return pData;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetIndexIntern()
+//
+// Description: gets a index entry from OD
+//
+// Parameters: pInitParam_p
+// uiIndex_p
+// ppObdEntry_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplObdGetIndexIntern(tEplObdInitParam MEM * pInitParam_p,
+ unsigned int uiIndex_p,
+ tEplObdEntryPtr * ppObdEntry_p)
+{
+
+ tEplObdEntryPtr pObdEntry;
+ tEplKernel Ret;
+ unsigned int uiIndex;
+
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+
+ unsigned int nLoop;
+
+ // if user OD is used then objekts also has to be searched in user OD
+ // there is less code need if we do this in a loop
+ nLoop = 2;
+
+#endif
+
+ ASSERTMSG(ppObdEntry_p != NULL,
+ "EplObdGetIndexIntern(): pointer to index entry is NULL!\n");
+
+ Ret = kEplObdIndexNotExist;
+
+ // get start address of OD part
+ // start address depends on object index because
+ // object dictionary is divided in 3 parts
+ if ((uiIndex_p >= 0x1000) && (uiIndex_p < 0x2000)) {
+ pObdEntry = pInitParam_p->m_pPart;
+ } else if ((uiIndex_p >= 0x2000) && (uiIndex_p < 0x6000)) {
+ pObdEntry = pInitParam_p->m_pManufacturerPart;
+ }
+ // index range 0xA000 to 0xFFFF is reserved for DSP-405
+ // DS-301 defines that range 0x6000 to 0x9FFF (!!!) is stored if "store" was written to 0x1010/3.
+ // Therefore default configuration is OBD_INCLUDE_A000_TO_DEVICE_PART = FALSE.
+ // But a CANopen Application which does not implement dynamic OD or user-OD but wants to use static objets 0xA000...
+ // should set OBD_INCLUDE_A000_TO_DEVICE_PART to TRUE.
+
+#if (EPL_OBD_INCLUDE_A000_TO_DEVICE_PART == FALSE)
+ else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0x9FFF))
+#else
+ else if ((uiIndex_p >= 0x6000) && (uiIndex_p < 0xFFFF))
+#endif
+ {
+ pObdEntry = pInitParam_p->m_pDevicePart;
+ }
+
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+
+ // if index does not match in static OD then index only has to be searched in user OD
+ else {
+ // begin from first entry of user OD part
+ pObdEntry = pInitParam_p->m_pUserPart;
+
+ // no user OD is available
+ if (pObdEntry == NULL) {
+ goto Exit;
+ }
+ // loop must only run once
+ nLoop = 1;
+ }
+
+ do {
+
+#else
+
+ // no user OD is available
+ // so other object can be found in OD
+ else {
+ Ret = kEplObdIllegalPart;
+ goto Exit;
+ }
+
+#endif
+
+ // note:
+ // The end of Index table is marked with m_uiIndex = 0xFFFF.
+ // If this function will be called with wIndex_p = 0xFFFF, entry
+ // should not be found. Therefor it is important to use
+ // while{} instead of do{}while !!!
+
+ // get first index of index table
+ uiIndex = pObdEntry->m_uiIndex;
+
+ // search Index in OD part
+ while (uiIndex != EPL_OBD_TABLE_INDEX_END) {
+ // go to the end of this function if index is found
+ if (uiIndex_p == uiIndex) {
+ // write address of OD entry to calling function
+ *ppObdEntry_p = pObdEntry;
+ Ret = kEplSuccessful;
+ goto Exit;
+ }
+ // objects are sorted in OD
+ // if the current index in OD is greater than the index which is to search then break loop
+ // in this case user OD has to be search too
+ if (uiIndex_p < uiIndex) {
+ break;
+ }
+ // next entry in index table
+ pObdEntry++;
+
+ // get next index of index table
+ uiIndex = pObdEntry->m_uiIndex;
+ }
+
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+
+ // begin from first entry of user OD part
+ pObdEntry = pInitParam_p->m_pUserPart;
+
+ // no user OD is available
+ if (pObdEntry == NULL) {
+ goto Exit;
+ }
+ // switch next loop for user OD
+ nLoop--;
+
+}
+
+while (nLoop > 0) ;
+
+#endif
+
+ // in this line Index was not found
+
+Exit:
+
+return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetSubindexIntern()
+//
+// Description: gets a subindex entry from a index entry
+//
+// Parameters: pObdEntry_p
+// bSubIndex_p
+// ppObdSubEntry_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplObdGetSubindexIntern(tEplObdEntryPtr pObdEntry_p,
+ unsigned int uiSubIndex_p,
+ tEplObdSubEntryPtr * ppObdSubEntry_p)
+{
+
+ tEplObdSubEntryPtr pSubEntry;
+ unsigned int nSubIndexCount;
+ tEplKernel Ret;
+
+ ASSERTMSG(pObdEntry_p != NULL,
+ "EplObdGetSubindexIntern(): pointer to index is NULL!\n");
+ ASSERTMSG(ppObdSubEntry_p != NULL,
+ "EplObdGetSubindexIntern(): pointer to subindex is NULL!\n");
+
+ Ret = kEplObdSubindexNotExist;
+
+ // get start address of subindex table and count of subindices
+ pSubEntry = pObdEntry_p->m_pSubIndex;
+ nSubIndexCount = pObdEntry_p->m_uiCount;
+ ASSERTMSG((pSubEntry != NULL) && (nSubIndexCount > 0), "ObdGetSubindexIntern(): invalid subindex table within index table!\n"); // should never be NULL
+
+ // search subindex in subindex table
+ while (nSubIndexCount > 0) {
+ // check if array is found
+ if ((pSubEntry->m_Access & kEplObdAccArray) != 0) {
+ // check if subindex is in range
+ if (uiSubIndex_p < pObdEntry_p->m_uiCount) {
+ // update subindex number (subindex entry of an array is always in RAM !!!)
+ pSubEntry->m_uiSubIndex = uiSubIndex_p;
+ *ppObdSubEntry_p = pSubEntry;
+ Ret = kEplSuccessful;
+ goto Exit;
+ }
+ }
+ // go to the end of this function if subindex is found
+ else if (uiSubIndex_p == pSubEntry->m_uiSubIndex) {
+ *ppObdSubEntry_p = pSubEntry;
+ Ret = kEplSuccessful;
+ goto Exit;
+ }
+ // objects are sorted in OD
+ // if the current subindex in OD is greater than the subindex which is to search then break loop
+ // in this case user OD has to be search too
+ if (uiSubIndex_p < pSubEntry->m_uiSubIndex) {
+ break;
+ }
+
+ pSubEntry++;
+ nSubIndexCount--;
+ }
+
+ // in this line SubIndex was not fount
+
+ Exit:
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdSetStoreLoadObjCallback()
+//
+// Description: function set address to callbackfunction for command Store and Load
+//
+// Parameters: fpCallback_p
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if (EPL_OBD_USE_STORE_RESTORE != FALSE)
+EPLDLLEXPORT tEplKernel PUBLIC
+EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdStoreLoadObjCallback fpCallback_p)
+{
+
+ EPL_MCO_CHECK_INSTANCE_STATE();
+
+ // set new address of callback function
+ EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) = fpCallback_p;
+
+ return kEplSuccessful;
+
+}
+#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdAccessOdPartIntern()
+//
+// Description: runs through OD and executes a job
+//
+// Parameters: CurrentOdPart_p
+// pObdEnty_p
+// Direction_p = what is to do (load values from flash or EEPROM, store, ...)
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplObdAccessOdPartIntern(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdPart CurrentOdPart_p,
+ tEplObdEntryPtr pObdEnty_p,
+ tEplObdDir Direction_p)
+{
+
+ tEplObdSubEntryPtr pSubIndex;
+ unsigned int nSubIndexCount;
+ tEplObdAccess Access;
+ void MEM *pDstData;
+ void *pDefault;
+ tEplObdSize ObjSize;
+ tEplKernel Ret;
+ tEplObdCbStoreParam MEM CbStore;
+ tEplObdVarEntry MEM *pVarEntry;
+
+ ASSERT(pObdEnty_p != NULL);
+
+ Ret = kEplSuccessful;
+
+ // prepare structure for STORE RESTORE callback function
+ CbStore.m_bCurrentOdPart = (BYTE) CurrentOdPart_p;
+ CbStore.m_pData = NULL;
+ CbStore.m_ObjSize = 0;
+
+ // command of first action depends on direction to access
+#if (EPL_OBD_USE_STORE_RESTORE != FALSE)
+ if (Direction_p == kEplObdDirLoad) {
+ CbStore.m_bCommand = (BYTE) kEplObdCommOpenRead;
+
+ // call callback function for previous command
+ Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // set command for index and subindex loop
+ CbStore.m_bCommand = (BYTE) kEplObdCommReadObj;
+ } else if (Direction_p == kEplObdDirStore) {
+ CbStore.m_bCommand = (BYTE) kEplObdCommOpenWrite;
+
+ // call callback function for previous command
+ Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // set command for index and subindex loop
+ CbStore.m_bCommand = (BYTE) kEplObdCommWriteObj;
+ }
+#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
+
+ // we should not restore the OD values here
+ // the next NMT command "Reset Node" or "Reset Communication" resets the OD data
+ if (Direction_p != kEplObdDirRestore) {
+ // walk through OD part till end is found
+ while (pObdEnty_p->m_uiIndex != EPL_OBD_TABLE_INDEX_END) {
+ // get address to subindex table and count of subindices
+ pSubIndex = pObdEnty_p->m_pSubIndex;
+ nSubIndexCount = pObdEnty_p->m_uiCount;
+ ASSERT((pSubIndex != NULL) && (nSubIndexCount > 0)); // should never be NULL
+
+ // walk through subindex table till all subinices were restored
+ while (nSubIndexCount != 0) {
+ Access = (tEplObdAccess) pSubIndex->m_Access;
+
+ // get pointer to current and default data
+ pDefault = EplObdGetObjectDefaultPtr(pSubIndex);
+ pDstData = EplObdGetObjectCurrentPtr(pSubIndex);
+
+ // NOTE (for kEplObdTypVString):
+ // The function returnes the max. number of bytes for a
+ // current string.
+ // r.d.: For stings the default-size will be read in other lines following (kEplObdDirInit).
+ ObjSize = EplObdGetObjectSize(pSubIndex);
+
+ // switch direction of OD access
+ switch (Direction_p) {
+ // --------------------------------------------------------------------------
+ // VarEntry structures has to be initialized
+ case kEplObdDirInit:
+
+ // If VAR-Flag is set, m_pCurrent means not address of data
+ // but address of tEplObdVarEntry. Address of data has to be get from
+ // this structure.
+ if ((Access & kEplObdAccVar) != 0) {
+ EplObdGetVarEntry(pSubIndex,
+ &pVarEntry);
+ EplObdInitVarEntry(pVarEntry,
+ pSubIndex->
+ m_Type,
+ ObjSize);
+/*
+ if ((Access & kEplObdAccArray) == 0)
+ {
+ EplObdInitVarEntry (pSubIndex->m_pCurrent, pSubIndex->m_Type, ObjSize);
+ }
+ else
+ {
+ EplObdInitVarEntry ((tEplObdVarEntry MEM*) (((BYTE MEM*) pSubIndex->m_pCurrent) + (sizeof (tEplObdVarEntry) * pSubIndex->m_uiSubIndex)),
+ pSubIndex->m_Type, ObjSize);
+ }
+*/
+ // at this time no application variable is defined !!!
+ // therefore data can not be copied.
+ break;
+ } else if (pSubIndex->m_Type ==
+ kEplObdTypVString) {
+ // If pointer m_pCurrent is not equal to NULL then the
+ // string was defined with EPL_OBD_SUBINDEX_RAM_VSTRING. The current
+ // pointer points to struct tEplObdVString located in MEM.
+ // The element size includes the max. number of
+ // bytes. The element m_pString includes the pointer
+ // to string in MEM. The memory location of default string
+ // must be copied to memory location of current string.
+
+ pDstData =
+ pSubIndex->m_pCurrent;
+ if (pDstData != NULL) {
+ // 08-dec-2004: code optimization !!!
+ // entries ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_pString
+ // and ((tEplObdVStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read
+ // twice. thats not necessary!
+
+ // For copying data we have to set the destination pointer to the real RAM string. This
+ // pointer to RAM string is located in default string info structure. (translated r.d.)
+ pDstData =
+ (void MEM
+ *)((tEplObdVStringDef ROM *) pSubIndex->m_pDefault)->m_pString;
+ ObjSize =
+ ((tEplObdVStringDef
+ ROM *) pSubIndex->
+ m_pDefault)->
+ m_Size;
+
+ ((tEplObdVString MEM *)
+ pSubIndex->
+ m_pCurrent)->
+ m_pString = pDstData;
+ ((tEplObdVString MEM *)
+ pSubIndex->
+ m_pCurrent)->m_Size =
+ ObjSize;
+ }
+
+ } else if (pSubIndex->m_Type ==
+ kEplObdTypOString) {
+ pDstData =
+ pSubIndex->m_pCurrent;
+ if (pDstData != NULL) {
+ // 08-dec-2004: code optimization !!!
+ // entries ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_pString
+ // and ((tEplObdOStringDef ROM*) pSubIndex->m_pDefault)->m_Size were read
+ // twice. thats not necessary!
+
+ // For copying data we have to set the destination pointer to the real RAM string. This
+ // pointer to RAM string is located in default string info structure. (translated r.d.)
+ pDstData =
+ (void MEM
+ *)((tEplObdOStringDef ROM *) pSubIndex->m_pDefault)->m_pString;
+ ObjSize =
+ ((tEplObdOStringDef
+ ROM *) pSubIndex->
+ m_pDefault)->
+ m_Size;
+
+ ((tEplObdOString MEM *)
+ pSubIndex->
+ m_pCurrent)->
+ m_pString = pDstData;
+ ((tEplObdOString MEM *)
+ pSubIndex->
+ m_pCurrent)->m_Size =
+ ObjSize;
+ }
+
+ }
+
+ // no break !! because copy of data has to done too.
+
+ // --------------------------------------------------------------------------
+ // all objects has to be restored with default values
+ case kEplObdDirRestore:
+
+ // 09-dec-2004 r.d.: optimization! the same code for kEplObdDirRestore and kEplObdDirLoad
+ // is replaced to function ObdCopyObjectData() with a new parameter.
+
+ // restore object data for init phase
+ EplObdCopyObjectData(pDstData, pDefault,
+ ObjSize,
+ pSubIndex->m_Type);
+ break;
+
+ // --------------------------------------------------------------------------
+ // objects with attribute kEplObdAccStore has to be load from EEPROM or from a file
+ case kEplObdDirLoad:
+
+ // restore object data for init phase
+ EplObdCopyObjectData(pDstData, pDefault,
+ ObjSize,
+ pSubIndex->m_Type);
+
+ // no break !! because callback function has to be called too.
+
+ // --------------------------------------------------------------------------
+ // objects with attribute kEplObdAccStore has to be stored in EEPROM or in a file
+ case kEplObdDirStore:
+
+ // when attribute kEplObdAccStore is set, then call callback function
+#if (EPL_OBD_USE_STORE_RESTORE != FALSE)
+ if ((Access & kEplObdAccStore) != 0) {
+ // fill out data pointer and size of data
+ CbStore.m_pData = pDstData;
+ CbStore.m_ObjSize = ObjSize;
+
+ // call callback function for read or write object
+ Ret =
+ ObdCallStoreCallback
+ (EPL_MCO_INSTANCE_PTR_ &
+ CbStore);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ }
+#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
+ break;
+
+ // --------------------------------------------------------------------------
+ // if OD Builder key has to be checked no access to subindex and data should be made
+ case kEplObdDirOBKCheck:
+
+ // no break !! because we want to break the second loop too.
+
+ // --------------------------------------------------------------------------
+ // unknown Direction
+ default:
+
+ // so we can break the second loop earler
+ nSubIndexCount = 1;
+ break;
+ }
+
+ nSubIndexCount--;
+
+ // next subindex entry
+ if ((Access & kEplObdAccArray) == 0) {
+ pSubIndex++;
+ if ((nSubIndexCount > 0)
+ &&
+ ((pSubIndex->
+ m_Access & kEplObdAccArray) !=
+ 0)) {
+ // next subindex points to an array
+ // reset subindex number
+ pSubIndex->m_uiSubIndex = 1;
+ }
+ } else {
+ if (nSubIndexCount > 0) {
+ // next subindex points to an array
+ // increment subindex number
+ pSubIndex->m_uiSubIndex++;
+ }
+ }
+ }
+
+ // next index entry
+ pObdEnty_p++;
+ }
+ }
+ // -----------------------------------------------------------------------------------------
+ // command of last action depends on direction to access
+ if (Direction_p == kEplObdDirOBKCheck) {
+
+ goto Exit;
+ }
+#if (EPL_OBD_USE_STORE_RESTORE != FALSE)
+ else {
+ if (Direction_p == kEplObdDirLoad) {
+ CbStore.m_bCommand = (BYTE) kEplObdCommCloseRead;
+ } else if (Direction_p == kEplObdDirStore) {
+ CbStore.m_bCommand = (BYTE) kEplObdCommCloseWrite;
+ } else if (Direction_p == kEplObdDirRestore) {
+ CbStore.m_bCommand = (BYTE) kEplObdCommClear;
+ } else {
+ goto Exit;
+ }
+
+ // call callback function for last command
+ Ret = EplObdCallStoreCallback(EPL_MCO_INSTANCE_PTR_ & CbStore);
+ }
+#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
+
+// goto Exit;
+
+ Exit:
+
+ return Ret;
+
+}
+
+// ----------------------------------------------------------------------------
+// Function: EplObdCopyObjectData()
+//
+// Description: checks pointers to object data and copy them from source to destination
+//
+// Parameters: pDstData_p = destination pointer
+// pSrcData_p = source pointer
+// ObjSize_p = size of object
+// ObjType_p =
+//
+// Returns: tEplKernel = error code
+// ----------------------------------------------------------------------------
+
+static void EplObdCopyObjectData(void MEM * pDstData_p,
+ void *pSrcData_p,
+ tEplObdSize ObjSize_p, tEplObdType ObjType_p)
+{
+
+ tEplObdSize StrSize = 0;
+
+ // it is allowed to set default and current address to NULL (nothing to copy)
+ if (pDstData_p != NULL) {
+
+ if (ObjType_p == kEplObdTypVString) {
+ // The function calculates the really number of characters of string. The
+ // object entry size can be bigger as string size of default string.
+ // The '\0'-termination is included. A string with no characters has a
+ // size of 1.
+ StrSize =
+ EplObdGetStrLen((void *)pSrcData_p, ObjSize_p,
+ kEplObdTypVString);
+
+ // If the string length is greater than or equal to the entry size in OD then only copy
+ // entry size - 1 and always set the '\0'-termination.
+ if (StrSize >= ObjSize_p) {
+ StrSize = ObjSize_p - 1;
+ }
+ }
+
+ if (pSrcData_p != NULL) {
+ // copy data
+ EPL_MEMCPY(pDstData_p, pSrcData_p, ObjSize_p);
+
+ if (ObjType_p == kEplObdTypVString) {
+ ((char MEM *)pDstData_p)[StrSize] = '\0';
+ }
+ }
+ }
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdIsNumericalIntern()
+//
+// Description: function checks if a entry is numerical or not
+//
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = Instancepointer
+// uiIndex_p = Index
+// uiSubIndex_p = Subindex
+// pfEntryNumerical_p = pointer to BOOL for returnvalue
+// -> TRUE if entry a numerical value
+// -> FALSE if entry not a numerical value
+//
+// Return: tEplKernel = Errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplObdIsNumericalIntern(tEplObdSubEntryPtr pObdSubEntry_p,
+ BOOL * pfEntryNumerical_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // get Type
+ if ((pObdSubEntry_p->m_Type == kEplObdTypVString)
+ || (pObdSubEntry_p->m_Type == kEplObdTypOString)
+ || (pObdSubEntry_p->m_Type == kEplObdTypDomain)) { // not numerical types
+ *pfEntryNumerical_p = FALSE;
+ } else { // numerical types
+ *pfEntryNumerical_p = TRUE;
+ }
+
+ return Ret;
+
+}
+
+// -------------------------------------------------------------------------
+// function to classify object type (fixed/non fixed)
+// -------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// Function: EplObdCallStoreCallback()
+//
+// Description: checks address to callback function and calles it when unequal
+// to NULL
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_ = (instance pointer)
+// pCbStoreParam_p = address to callback parameters
+//
+// Returns: tEplKernel = error code
+// ----------------------------------------------------------------------------
+#if (EPL_OBD_USE_STORE_RESTORE != FALSE)
+static tEplKernel EplObdCallStoreCallback(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdCbStoreParam MEM *
+ pCbStoreParam_p)
+{
+
+ tEplKernel Ret = kEplSuccessful;
+
+ ASSERT(pCbStoreParam_p != NULL);
+
+ // check if function pointer is NULL - if so, no callback should be called
+ if (EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback) != NULL) {
+ Ret =
+ EPL_MCO_GLB_VAR(m_fpStoreLoadObjCallback)
+ (EPL_MCO_INSTANCE_PARAM_IDX_()
+ pCbStoreParam_p);
+ }
+
+ return Ret;
+
+}
+#endif // (EPL_OBD_USE_STORE_RESTORE != FALSE)
+//---------------------------------------------------------------------------
+//
+// Function: EplObdGetObjectDataPtrIntern()
+//
+// Description: Function gets the data pointer of an object.
+// It returnes the current data pointer. But if object is an
+// constant object it returnes the default pointer.
+//
+// Parameters: pSubindexEntry_p = pointer to subindex entry
+//
+// Return: void * = pointer to object data
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+void *EplObdGetObjectDataPtrIntern(tEplObdSubEntryPtr pSubindexEntry_p)
+{
+
+ void *pData;
+ tEplObdAccess Access;
+
+ ASSERTMSG(pSubindexEntry_p != NULL,
+ "EplObdGetObjectDataPtrIntern(): pointer to SubEntry not valid!\n");
+
+ // there are are some objects whose data pointer has to get from other structure
+ // get access type for this object
+ Access = pSubindexEntry_p->m_Access;
+
+ // If object has access type = const,
+ // for data only exists default values.
+ if ((Access & kEplObdAccConst) != 0) {
+ // The pointer to defualt value can be received from ObdGetObjectDefaultPtr()
+ pData = ((void *)EplObdGetObjectDefaultPtr(pSubindexEntry_p));
+ } else {
+ // The pointer to current value can be received from ObdGetObjectCurrentPtr()
+ pData = ((void *)EplObdGetObjectCurrentPtr(pSubindexEntry_p));
+ }
+
+ return pData;
+
+}
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+// EOF
diff --git a/drivers/staging/epl/EplObd.h b/drivers/staging/epl/EplObd.h
new file mode 100644
index 000000000000..88cc11e34ccd
--- /dev/null
+++ b/drivers/staging/epl/EplObd.h
@@ -0,0 +1,464 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for api function of EplOBD-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObd.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ Microsoft VC7
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/02 k.t.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "EplInc.h"
+
+#ifndef _EPLOBD_H_
+#define _EPLOBD_H_
+
+// ============================================================================
+// defines
+// ============================================================================
+
+#define EPL_OBD_TABLE_INDEX_END 0xFFFF
+
+// for the usage of BOOLEAN in OD
+#define OBD_TRUE 0x01
+#define OBD_FALSE 0x00
+
+// default OD index for Node id
+#define EPL_OBD_NODE_ID_INDEX 0x1F93
+// default subindex for NodeId in OD
+#define EPL_OBD_NODE_ID_SUBINDEX 0x01
+// default subindex for NodeIDByHW_BOOL
+#define EPL_OBD_NODE_ID_HWBOOL_SUBINDEX 0x02
+
+// ============================================================================
+// enums
+// ============================================================================
+
+// directions for access to object dictionary
+typedef enum {
+ kEplObdDirInit = 0x00, // initialising after power on
+ kEplObdDirStore = 0x01, // store all object values to non volatile memory
+ kEplObdDirLoad = 0x02, // load all object values from non volatile memory
+ kEplObdDirRestore = 0x03, // deletes non volatile memory (restore)
+ kEplObdDirOBKCheck = 0xFF // reserved
+} tEplObdDir;
+
+// commands for store
+typedef enum {
+ kEplObdCommNothing = 0x00,
+ kEplObdCommOpenWrite = 0x01,
+ kEplObdCommWriteObj = 0x02,
+ kEplObdCommCloseWrite = 0x03,
+ kEplObdCommOpenRead = 0x04,
+ kEplObdCommReadObj = 0x05,
+ kEplObdCommCloseRead = 0x06,
+ kEplObdCommClear = 0x07,
+ kEplObdCommUnknown = 0xFF
+} tEplObdCommand;
+
+//-----------------------------------------------------------------------------------------------------------
+// events of object callback function
+typedef enum {
+// m_pArg points to
+// ---------------------
+ kEplObdEvCheckExist = 0x06, // checking if object does exist (reading and writing) NULL
+ kEplObdEvPreRead = 0x00, // before reading an object source data buffer in OD
+ kEplObdEvPostRead = 0x01, // after reading an object destination data buffer from caller
+ kEplObdEvWrStringDomain = 0x07, // event for changing string/domain data pointer or size struct tEplObdVStringDomain in RAM
+ kEplObdEvInitWrite = 0x04, // initializes writing an object (checking object size) size of object in OD (tEplObdSize)
+ kEplObdEvPreWrite = 0x02, // before writing an object source data buffer from caller
+ kEplObdEvPostWrite = 0x03, // after writing an object destination data buffer in OD
+// kEplObdEvAbortSdo = 0x05 // after an abort of an SDO transfer
+
+} tEplObdEvent;
+
+// part of OD (bit oriented)
+typedef unsigned int tEplObdPart;
+
+#define kEplObdPartNo 0x00 // nothing
+#define kEplObdPartGen 0x01 // part (0x1000 - 0x1FFF)
+#define kEplObdPartMan 0x02 // manufacturer part (0x2000 - 0x5FFF)
+#define kEplObdPartDev 0x04 // device part (0x6000 - 0x9FFF)
+#define kEplObdPartUsr 0x08 // dynamic part e.g. for ICE61131-3
+
+// combinations
+#define kEplObdPartApp ( kEplObdPartMan | kEplObdPartDev | kEplObdPartUsr) // manufacturer and device part (0x2000 - 0x9FFF) and user OD
+#define kEplObdPartAll (kEplObdPartGen | kEplObdPartMan | kEplObdPartDev | kEplObdPartUsr) // whole OD
+
+//-----------------------------------------------------------------------------------------------------------
+// access types for objects
+// must be a difine because bit-flags
+typedef unsigned int tEplObdAccess;
+
+#define kEplObdAccRead 0x01 // object can be read
+#define kEplObdAccWrite 0x02 // object can be written
+#define kEplObdAccConst 0x04 // object contains a constant value
+#define kEplObdAccPdo 0x08 // object can be mapped in a PDO
+#define kEplObdAccArray 0x10 // object contains an array of numerical values
+#define kEplObdAccRange 0x20 // object contains lower and upper limit
+#define kEplObdAccVar 0x40 // object data is placed in application
+#define kEplObdAccStore 0x80 // object data can be stored to non volatile memory
+
+// combinations (not all combinations are required)
+#define kEplObdAccR (0 | 0 | 0 | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccW (0 | 0 | 0 | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccRW (0 | 0 | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccCR (0 | 0 | 0 | 0 | kEplObdAccConst | 0 | kEplObdAccRead)
+#define kEplObdAccGR (0 | 0 | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccGW (0 | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccGRW (0 | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccVR (0 | kEplObdAccVar | 0 | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccVW (0 | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccVRW (0 | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccVPR (0 | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccVPW (0 | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccVPRW (0 | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccVGR (0 | kEplObdAccVar | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccVGW (0 | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccVGRW (0 | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccVGPR (0 | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccVGPW (0 | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccVGPRW (0 | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccSR (kEplObdAccStore | 0 | 0 | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccSW (kEplObdAccStore | 0 | 0 | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccSRW (kEplObdAccStore | 0 | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccSCR (kEplObdAccStore | 0 | 0 | 0 | kEplObdAccConst | 0 | kEplObdAccRead)
+#define kEplObdAccSGR (kEplObdAccStore | 0 | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccSGW (kEplObdAccStore | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccSGRW (kEplObdAccStore | 0 | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccSVR (kEplObdAccStore | kEplObdAccVar | 0 | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccSVW (kEplObdAccStore | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccSVRW (kEplObdAccStore | kEplObdAccVar | 0 | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccSVPR (kEplObdAccStore | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccSVPW (kEplObdAccStore | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccSVPRW (kEplObdAccStore | kEplObdAccVar | 0 | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccSVGR (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | 0 | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccSVGW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccSVGRW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | 0 | 0 | kEplObdAccWrite | kEplObdAccRead)
+#define kEplObdAccSVGPR (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | 0 | kEplObdAccRead)
+#define kEplObdAccSVGPW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | 0 )
+#define kEplObdAccSVGPRW (kEplObdAccStore | kEplObdAccVar | kEplObdAccRange | kEplObdAccPdo | 0 | kEplObdAccWrite | kEplObdAccRead)
+
+typedef unsigned int tEplObdSize; // For all objects as objects size are used an unsigned int.
+
+// -------------------------------------------------------------------------
+// types for data types defined in DS301
+// -------------------------------------------------------------------------
+
+// types of objects in object dictionary
+// DS-301 defines these types as WORD
+typedef enum {
+// types which are always supported
+ kEplObdTypBool = 0x0001,
+
+ kEplObdTypInt8 = 0x0002,
+ kEplObdTypInt16 = 0x0003,
+ kEplObdTypInt32 = 0x0004,
+ kEplObdTypUInt8 = 0x0005,
+ kEplObdTypUInt16 = 0x0006,
+ kEplObdTypUInt32 = 0x0007,
+ kEplObdTypReal32 = 0x0008,
+ kEplObdTypVString = 0x0009,
+ kEplObdTypOString = 0x000A,
+ kEplObdTypDomain = 0x000F,
+
+ kEplObdTypInt24 = 0x0010,
+ kEplObdTypUInt24 = 0x0016,
+
+ kEplObdTypReal64 = 0x0011,
+ kEplObdTypInt40 = 0x0012,
+ kEplObdTypInt48 = 0x0013,
+ kEplObdTypInt56 = 0x0014,
+ kEplObdTypInt64 = 0x0015,
+ kEplObdTypUInt40 = 0x0018,
+ kEplObdTypUInt48 = 0x0019,
+ kEplObdTypUInt56 = 0x001A,
+ kEplObdTypUInt64 = 0x001B,
+ kEplObdTypTimeOfDay = 0x000C,
+ kEplObdTypTimeDiff = 0x000D
+} tEplObdType;
+// other types are not supported in this version
+
+// -------------------------------------------------------------------------
+// types for data types defined in DS301
+// -------------------------------------------------------------------------
+
+typedef unsigned char tEplObdBoolean; // 0001
+typedef signed char tEplObdInteger8; // 0002
+typedef signed short int tEplObdInteger16; // 0003
+typedef signed long tEplObdInteger32; // 0004
+typedef unsigned char tEplObdUnsigned8; // 0005
+typedef unsigned short int tEplObdUnsigned16; // 0006
+typedef unsigned long tEplObdUnsigned32; // 0007
+typedef float tEplObdReal32; // 0008
+typedef unsigned char tEplObdDomain; // 000F
+typedef signed long tEplObdInteger24; // 0010
+typedef unsigned long tEplObdUnsigned24; // 0016
+
+typedef signed QWORD tEplObdInteger40; // 0012
+typedef signed QWORD tEplObdInteger48; // 0013
+typedef signed QWORD tEplObdInteger56; // 0014
+typedef signed QWORD tEplObdInteger64; // 0015
+
+typedef unsigned QWORD tEplObdUnsigned40; // 0018
+typedef unsigned QWORD tEplObdUnsigned48; // 0019
+typedef unsigned QWORD tEplObdUnsigned56; // 001A
+typedef unsigned QWORD tEplObdUnsigned64; // 001B
+
+typedef double tEplObdReal64; // 0011
+
+typedef tTimeOfDay tEplObdTimeOfDay; // 000C
+typedef tTimeOfDay tEplObdTimeDifference; // 000D
+
+// -------------------------------------------------------------------------
+// structur for defining a variable
+// -------------------------------------------------------------------------
+// -------------------------------------------------------------------------
+typedef enum {
+ kVarValidSize = 0x01,
+ kVarValidData = 0x02,
+// kVarValidCallback = 0x04,
+// kVarValidArg = 0x08,
+
+ kVarValidAll = 0x03 // currently only size and data are implemented and used
+} tEplVarParamValid;
+
+typedef tEplKernel(PUBLIC ROM * tEplVarCallback) (CCM_DECL_INSTANCE_HDL_
+ void *pParam_p);
+
+typedef struct {
+ tEplVarParamValid m_ValidFlag;
+ unsigned int m_uiIndex;
+ unsigned int m_uiSubindex;
+ tEplObdSize m_Size;
+ void MEM *m_pData;
+// tEplVarCallback m_fpCallback;
+// void * m_pArg;
+
+} tEplVarParam;
+
+typedef struct {
+ void MEM *m_pData;
+ tEplObdSize m_Size;
+/*
+ #if (EPL_PDO_USE_STATIC_MAPPING == FALSE)
+ tEplVarCallback m_fpCallback;
+ void * m_pArg;
+ #endif
+*/
+} tEplObdVarEntry;
+
+typedef struct {
+ tEplObdSize m_Size;
+ BYTE *m_pString;
+
+} tEplObdOString; // 000C
+
+typedef struct {
+ tEplObdSize m_Size;
+ char *m_pString;
+} tEplObdVString; // 000D
+
+typedef struct {
+ tEplObdSize m_Size;
+ char *m_pDefString; // $$$ d.k. it is unused, so we could delete it
+ char *m_pString;
+
+} tEplObdVStringDef;
+
+typedef struct {
+ tEplObdSize m_Size;
+ BYTE *m_pDefString; // $$$ d.k. it is unused, so we could delete it
+ BYTE *m_pString;
+
+} tEplObdOStringDef;
+
+//r.d. parameter struct for changing object size and/or pointer to data of Strings or Domains
+typedef struct {
+ tEplObdSize m_DownloadSize; // download size from SDO or APP
+ tEplObdSize m_ObjSize; // current object size from OD - should be changed from callback function
+ void *m_pData; // current object ptr from OD - should be changed from callback function
+
+} tEplObdVStringDomain; // 000D
+
+// ============================================================================
+// types
+// ============================================================================
+// -------------------------------------------------------------------------
+// subindexstruct
+// -------------------------------------------------------------------------
+
+// Change not the order for this struct!!!
+typedef struct {
+ unsigned int m_uiSubIndex;
+ tEplObdType m_Type;
+ tEplObdAccess m_Access;
+ void *m_pDefault;
+ void MEM *m_pCurrent; // points always to RAM
+
+} tEplObdSubEntry;
+
+// r.d.: has always to be because new OBD-Macros for arrays
+typedef tEplObdSubEntry *tEplObdSubEntryPtr;
+
+// -------------------------------------------------------------------------
+// callback function for objdictionary modul
+// -------------------------------------------------------------------------
+
+// parameters for callback function
+typedef struct {
+ tEplObdEvent m_ObdEvent;
+ unsigned int m_uiIndex;
+ unsigned int m_uiSubIndex;
+ void *m_pArg;
+ DWORD m_dwAbortCode;
+
+} tEplObdCbParam;
+
+// define type for callback function: pParam_p points to tEplObdCbParam
+typedef tEplKernel(PUBLIC ROM * tEplObdCallback) (CCM_DECL_INSTANCE_HDL_
+ tEplObdCbParam MEM *
+ pParam_p);
+
+// do not change the order for this struct!!!
+
+typedef struct {
+ unsigned int m_uiIndex;
+ tEplObdSubEntryPtr m_pSubIndex;
+ unsigned int m_uiCount;
+ tEplObdCallback m_fpCallback; // function is called back if object access
+
+} tEplObdEntry;
+
+// allways pointer
+typedef tEplObdEntry *tEplObdEntryPtr;
+
+// -------------------------------------------------------------------------
+// structur to initialize OBD module
+// -------------------------------------------------------------------------
+
+typedef struct {
+ tEplObdEntryPtr m_pPart;
+ tEplObdEntryPtr m_pManufacturerPart;
+ tEplObdEntryPtr m_pDevicePart;
+
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+
+ tEplObdEntryPtr m_pUserPart;
+
+#endif
+
+} tEplObdInitParam;
+
+// -------------------------------------------------------------------------
+// structur for parameters of STORE RESTORE command
+// -------------------------------------------------------------------------
+
+typedef struct {
+ tEplObdCommand m_bCommand;
+ tEplObdPart m_bCurrentOdPart;
+ void MEM *m_pData;
+ tEplObdSize m_ObjSize;
+
+} tEplObdCbStoreParam;
+
+typedef tEplKernel(PUBLIC ROM * tInitTabEntryCallback) (void MEM * pTabEntry_p,
+ unsigned int
+ uiObjIndex_p);
+
+typedef tEplKernel(PUBLIC ROM *
+ tEplObdStoreLoadObjCallback) (CCM_DECL_INSTANCE_HDL_
+ tEplObdCbStoreParam MEM *
+ pCbStoreParam_p);
+
+// -------------------------------------------------------------------------
+// this stucture is used for parameters for function ObdInitModuleTab()
+// -------------------------------------------------------------------------
+typedef struct {
+ unsigned int m_uiLowerObjIndex; // lower limit of ObjIndex
+ unsigned int m_uiUpperObjIndex; // upper limit of ObjIndex
+ tInitTabEntryCallback m_fpInitTabEntry; // will be called if ObjIndex was found
+ void MEM *m_pTabBase; // base address of table
+ unsigned int m_uiEntrySize; // size of table entry // 25-feb-2005 r.d.: expansion from BYTE to WORD necessary for PDO bit mapping
+ unsigned int m_uiMaxEntries; // max. tabel entries
+
+} tEplObdModulTabParam;
+
+//-------------------------------------------------------------------
+// enum for function EplObdSetNodeId
+//-------------------------------------------------------------------
+typedef enum {
+ kEplObdNodeIdUnknown = 0x00, // unknown how the node id was set
+ kEplObdNodeIdSoftware = 0x01, // node id set by software
+ kEplObdNodeIdHardware = 0x02 // node id set by hardware
+} tEplObdNodeIdType;
+
+// ============================================================================
+// global variables
+// ============================================================================
+
+// ============================================================================
+// public functions
+// ============================================================================
+
+#endif // #ifndef _EPLOBD_H_
diff --git a/drivers/staging/epl/EplObdMacro.h b/drivers/staging/epl/EplObdMacro.h
new file mode 100644
index 000000000000..23f2ad80dde8
--- /dev/null
+++ b/drivers/staging/epl/EplObdMacro.h
@@ -0,0 +1,354 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for macros of EplOBD-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObdMacro.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/05 k.t.: start of the implementation
+ -> based on CANopen ObdMacro.h
+
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#if defined (EPL_OBD_DEFINE_MACRO)
+
+ //-------------------------------------------------------------------------------------------
+#if defined (EPL_OBD_CREATE_ROM_DATA)
+
+// #pragma message ("EPL_OBD_CREATE_ROM_DATA")
+
+#define EPL_OBD_BEGIN() static DWORD dwObd_OBK_g = 0x0000;
+#define EPL_OBD_END()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_PART_GENERIC()
+#define EPL_OBD_BEGIN_PART_MANUFACTURER()
+#define EPL_OBD_BEGIN_PART_DEVICE()
+#define EPL_OBD_END_PART()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call)
+#define EPL_OBD_END_INDEX(ind)
+#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdUnsigned8 xDef##ind##_0x00_g = (cnt); \
+ static dtyp xDef##ind##_0x01_g = (def);
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdUnsigned8 xDef##ind##_0x00_g = (cnt); \
+ static dtyp xDef##ind##_0x01_g = (def);
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdUnsigned8 xDef##ind##_0x00_g = (cnt);
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) static dtyp xDef##ind##_##sub##_g = val;
+#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp xDef##ind##_##sub##_g[3] = {val,low,high};
+#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name)
+#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static char MEM szCur##ind##_##sub##_g[size+1]; \
+ static tEplObdVStringDef xDef##ind##_##sub##_g = {size, val, szCur##ind##_##sub##_g};
+
+#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static BYTE MEM bCur##ind##_##sub##_g[size]; \
+ static tEplObdOStringDef xDef##ind##_##sub##_g = {size, ((BYTE*)""), bCur##ind##_##sub##_g};
+#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) static dtyp xDef##ind##_##sub##_g = val;
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp xDef##ind##_##sub##_g[3] = {val,low,high};
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name)
+
+//-------------------------------------------------------------------------------------------
+#elif defined (EPL_OBD_CREATE_RAM_DATA)
+
+// #pragma message ("EPL_OBD_CREATE_RAM_DATA")
+
+#define EPL_OBD_BEGIN()
+#define EPL_OBD_END()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_PART_GENERIC()
+#define EPL_OBD_BEGIN_PART_MANUFACTURER()
+#define EPL_OBD_BEGIN_PART_DEVICE()
+#define EPL_OBD_END_PART()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call)
+#define EPL_OBD_END_INDEX(ind)
+#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static dtyp MEM axCur##ind##_g[cnt];
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdVarEntry MEM aVarEntry##ind##_g[cnt];
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdVarEntry MEM aVarEntry##ind##_g[cnt];
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) static dtyp MEM xCur##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static dtyp MEM xCur##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) static tEplObdVString MEM xCur##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) static tEplObdOString MEM xCur##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) static dtyp MEM xCur##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g;
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) static tEplObdVarEntry MEM VarEntry##ind##_##sub##_g;
+
+ //-------------------------------------------------------------------------------------------
+#elif defined (EPL_OBD_CREATE_SUBINDEX_TAB)
+
+// #pragma message ("EPL_OBD_CREATE_SUBINDEX_TAB")
+
+#define EPL_OBD_BEGIN()
+#define EPL_OBD_END()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_PART_GENERIC()
+#define EPL_OBD_BEGIN_PART_MANUFACTURER()
+#define EPL_OBD_BEGIN_PART_DEVICE()
+#define EPL_OBD_END_PART()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[cnt]= {
+#define EPL_OBD_END_INDEX(ind) EPL_OBD_END_SUBINDEX()};
+#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \
+ {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \
+ {1, typ, (acc)|kEplObdAccArray, &xDef##ind##_0x01_g, &axCur##ind##_g[0]}, \
+ EPL_OBD_END_SUBINDEX()};
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \
+ {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \
+ {1, typ, (acc)|kEplObdAccArray|kEplObdAccVar, &xDef##ind##_0x01_g, &aVarEntry##ind##_g[0]}, \
+ EPL_OBD_END_SUBINDEX()};
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) static tEplObdSubEntry MEM aObdSubEntry##ind##Ram_g[]= { \
+ {0, kEplObdTypUInt8, kEplObdAccCR, &xDef##ind##_0x00_g, NULL}, \
+ {1, typ, (acc)|kEplObdAccArray|kEplObdAccVar, NULL, &aVarEntry##ind##_g[0]}, \
+ EPL_OBD_END_SUBINDEX()};
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val) {sub,typ, (acc), &xDef##ind##_##sub##_g, &xCur##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high) {sub,typ, (acc)|kEplObdAccRange, &xDef##ind##_##sub##_g[0],&xCur##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name) {sub,typ, (acc), NULL, &xCur##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val) {sub,kEplObdTypVString,(acc)/*|kEplObdAccVar*/, &xDef##ind##_##sub##_g, &xCur##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size) {sub,kEplObdTypOString,(acc)/*|kEplObdAccVar*/, &xDef##ind##_##sub##_g, &xCur##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name) {sub,kEplObdTypDomain, (acc)|kEplObdAccVar, NULL, &VarEntry##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val) {sub,typ, (acc)|kEplObdAccVar, &xDef##ind##_##sub##_g, &VarEntry##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high) {sub,typ, (acc)|kEplObdAccVar|kEplObdAccRange,&xDef##ind##_##sub##_g[0],&VarEntry##ind##_##sub##_g},
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name) {sub,typ, (acc)|kEplObdAccVar, NULL, &VarEntry##ind##_##sub##_g},
+
+ //-------------------------------------------------------------------------------------------
+#elif defined (EPL_OBD_CREATE_INDEX_TAB)
+
+// #pragma message ("EPL_OBD_CREATE_INDEX_TAB")
+
+#define EPL_OBD_BEGIN()
+#define EPL_OBD_END()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_PART_GENERIC() static tEplObdEntry aObdTab_g[] = {
+#define EPL_OBD_BEGIN_PART_MANUFACTURER() static tEplObdEntry aObdTabManufacturer_g[] = {
+#define EPL_OBD_BEGIN_PART_DEVICE() static tEplObdEntry aObdTabDevice_g[] = {
+#define EPL_OBD_END_PART() {EPL_OBD_TABLE_INDEX_END,(tEplObdSubEntryPtr)&dwObd_OBK_g,0,NULL}};
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],cnt,(tEplObdCallback)call},
+#define EPL_OBD_END_INDEX(ind)
+#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],(cnt)+1,(tEplObdCallback)call},
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],(cnt)+1,(tEplObdCallback)call},
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) {ind,(tEplObdSubEntryPtr)&aObdSubEntry##ind##Ram_g[0],(cnt)+1,(tEplObdCallback)call},
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val)
+#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size)
+#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name)
+#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name)
+
+ //-------------------------------------------------------------------------------------------
+#elif defined (EPL_OBD_CREATE_INIT_FUNCTION)
+
+// #pragma message ("EPL_OBD_CREATE_INIT_FUNCTION")
+
+#define EPL_OBD_BEGIN()
+#define EPL_OBD_END()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_PART_GENERIC() pInitParam->m_pPart = (tEplObdEntryPtr) &aObdTab_g[0];
+#define EPL_OBD_BEGIN_PART_MANUFACTURER() pInitParam->m_pManufacturerPart = (tEplObdEntryPtr) &aObdTabManufacturer_g[0];
+#define EPL_OBD_BEGIN_PART_DEVICE() pInitParam->m_pDevicePart = (tEplObdEntryPtr) &aObdTabDevice_g[0];
+#define EPL_OBD_END_PART()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call)
+#define EPL_OBD_END_INDEX(ind)
+#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def)
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def)
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name)
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val)
+#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size)
+#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name)
+#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name)
+
+ //-------------------------------------------------------------------------------------------
+#elif defined (EPL_OBD_CREATE_INIT_SUBINDEX)
+
+// #pragma message ("EPL_OBD_CREATE_INIT_SUBINDEX")
+
+#define EPL_OBD_BEGIN()
+#define EPL_OBD_END()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_PART_GENERIC()
+#define EPL_OBD_BEGIN_PART_MANUFACTURER()
+#define EPL_OBD_BEGIN_PART_DEVICE()
+#define EPL_OBD_END_PART()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call) //CCM_SUBINDEX_RAM_ONLY (EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g)));
+#define EPL_OBD_END_INDEX(ind)
+#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def) //EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g));
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def) //EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g));
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name) //EPL_MEMCPY (&aObdSubEntry##ind##Ram_g[0],&aObdSubEntry##ind##Rom_g[0],sizeof(aObdSubEntry##ind##Ram_g));
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,size,val)
+#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size)
+#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name)
+#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name)
+
+ //-------------------------------------------------------------------------------------------
+#else
+
+// #pragma message ("ELSE OF DEFINE")
+
+#define EPL_OBD_BEGIN()
+#define EPL_OBD_END()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_PART_GENERIC()
+#define EPL_OBD_BEGIN_PART_MANUFACTURER()
+#define EPL_OBD_BEGIN_PART_DEVICE()
+#define EPL_OBD_END_PART()
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_BEGIN_INDEX_RAM(ind,cnt,call)
+#define EPL_OBD_END_INDEX(ind)
+#define EPL_OBD_RAM_INDEX_RAM_ARRAY(ind,cnt,call,typ,acc,dtyp,name,def)
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY(ind,cnt,call,typ,acc,dtyp,name,def)
+#define EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT(ind,cnt,call,typ,acc,dtyp,name)
+
+ //---------------------------------------------------------------------------------------
+#define EPL_OBD_SUBINDEX_RAM_VAR(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_VAR_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_VSTRING(ind,sub,acc,name,sizes,val)
+#define EPL_OBD_SUBINDEX_RAM_OSTRING(ind,sub,acc,name,size)
+#define EPL_OBD_SUBINDEX_RAM_VAR_NOINIT(ind,sub,typ,acc,dtyp,name)
+#define EPL_OBD_SUBINDEX_RAM_DOMAIN(ind,sub,acc,name)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF(ind,sub,typ,acc,dtyp,name,val)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_RG(ind,sub,typ,acc,dtyp,name,val,low,high)
+#define EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT(ind,sub,typ,acc,dtyp,name)
+
+#endif
+
+ //-------------------------------------------------------------------------------------------
+#elif defined (EPL_OBD_UNDEFINE_MACRO)
+
+// #pragma message ("EPL_OBD_UNDEFINE_MACRO")
+
+#undef EPL_OBD_BEGIN
+#undef EPL_OBD_END
+
+ //---------------------------------------------------------------------------------------
+#undef EPL_OBD_BEGIN_PART_GENERIC
+#undef EPL_OBD_BEGIN_PART_MANUFACTURER
+#undef EPL_OBD_BEGIN_PART_DEVICE
+#undef EPL_OBD_END_PART
+
+ //---------------------------------------------------------------------------------------
+#undef EPL_OBD_BEGIN_INDEX_RAM
+#undef EPL_OBD_END_INDEX
+#undef EPL_OBD_RAM_INDEX_RAM_ARRAY
+#undef EPL_OBD_RAM_INDEX_RAM_VARARRAY
+#undef EPL_OBD_RAM_INDEX_RAM_VARARRAY_NOINIT
+
+ //---------------------------------------------------------------------------------------
+#undef EPL_OBD_SUBINDEX_RAM_VAR
+#undef EPL_OBD_SUBINDEX_RAM_VAR_RG
+#undef EPL_OBD_SUBINDEX_RAM_VSTRING
+#undef EPL_OBD_SUBINDEX_RAM_OSTRING
+#undef EPL_OBD_SUBINDEX_RAM_VAR_NOINIT
+#undef EPL_OBD_SUBINDEX_RAM_DOMAIN
+#undef EPL_OBD_SUBINDEX_RAM_USERDEF
+#undef EPL_OBD_SUBINDEX_RAM_USERDEF_RG
+#undef EPL_OBD_SUBINDEX_RAM_USERDEF_NOINIT
+
+#else
+
+#error "nothing defined"
+
+#endif
diff --git a/drivers/staging/epl/EplObdkCal.c b/drivers/staging/epl/EplObdkCal.c
new file mode 100644
index 000000000000..4c9af89719ed
--- /dev/null
+++ b/drivers/staging/epl/EplObdkCal.c
@@ -0,0 +1,147 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for communication abstraction layer
+ for the Epl-Obd-Kernelspace-Modul
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObdkCal.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/19 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "kernel/EplObdkCal.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+// EOF
diff --git a/drivers/staging/epl/EplObdu.c b/drivers/staging/epl/EplObdu.c
new file mode 100644
index 000000000000..218d152897cf
--- /dev/null
+++ b/drivers/staging/epl/EplObdu.c
@@ -0,0 +1,517 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for Epl-Obd-Userspace-module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObdu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/19 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "user/EplObdu.h"
+#include "user/EplObduCal.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduWriteEntry()
+//
+// Description: Function writes data to an OBD entry. Strings
+// are stored with added '\0' character.
+//
+// Parameters: uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplObduCalWriteEntry(uiIndex_p, uiSubIndex_p, pSrcData_p, Size_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduReadEntry()
+//
+// Description: The function reads an object entry. The application
+// can always read the data even if attrib kEplObdAccRead
+// is not set. The attrib is only checked up for SDO transfer.
+//
+// Parameters: uiIndex_p = Index oof the OD entry to read
+// uiSubIndex_p = Subindex to read
+// pDstData_p = pointer to the buffer for data
+// Offset_p = offset in data for read access
+// pSize_p = IN: Size of the buffer
+// OUT: number of readed Bytes
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplObduCalReadEntry(uiIndex_p, uiSubIndex_p, pDstData_p, pSize_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdAccessOdPart()
+//
+// Description: restores default values of one part of OD
+//
+// Parameters: ObdPart_p = od-part to reset
+// Direction_p = directory flag for
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduAccessOdPart(tEplObdPart ObdPart_p,
+ tEplObdDir Direction_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplObduCalAccessOdPart(ObdPart_p, Direction_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduDefineVar()
+//
+// Description: defines a variable in OD
+//
+// Parameters: pEplVarParam_p = varentry
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduDefineVar(tEplVarParam MEM * pVarParam_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplObduCalDefineVar(pVarParam_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduGetObjectDataPtr()
+//
+// Description: It returnes the current data pointer. But if object is an
+// constant object it returnes the default pointer.
+//
+// Parameters: uiIndex_p = Index of the entry
+// uiSubindex_p = Subindex of the entry
+//
+// Return: void * = pointer to object data
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT void *PUBLIC EplObduGetObjectDataPtr(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p)
+{
+ void *pData;
+
+ pData = EplObduCalGetObjectDataPtr(uiIndex_p, uiSubIndex_p);
+
+ return pData;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduRegisterUserOd()
+//
+// Description: function registers the user OD
+//
+// Parameters: pUserOd_p =pointer to user ODd
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+EPLDLLEXPORT tEplKernel PUBLIC EplObduRegisterUserOd(tEplObdEntryPtr pUserOd_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplObduCalRegisterUserOd(pUserOd_p);
+
+ return Ret;
+
+}
+#endif
+//---------------------------------------------------------------------------
+//
+// Function: EplObduInitVarEntry()
+//
+// Description: function to initialize VarEntry dependened on object type
+//
+// Parameters: pVarEntry_p = pointer to var entry structure
+// bType_p = object type
+// ObdSize_p = size of object data
+//
+// Returns: none
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT void PUBLIC EplObduInitVarEntry(tEplObdVarEntry MEM * pVarEntry_p,
+ BYTE bType_p,
+ tEplObdSize ObdSize_p)
+{
+ EplObduCalInitVarEntry(pVarEntry_p, bType_p, ObdSize_p);
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduGetDataSize()
+//
+// Description: function to initialize VarEntry dependened on object type
+//
+// gets the data size of an object
+// for string objects it returnes the string length
+//
+// Parameters: uiIndex_p = Index
+// uiSubIndex_p= Subindex
+//
+// Return: tEplObdSize
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplObdSize PUBLIC EplObduGetDataSize(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p)
+{
+ tEplObdSize Size;
+
+ Size = EplObduCalGetDataSize(uiIndex_p, uiSubIndex_p);
+
+ return Size;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduGetNodeId()
+//
+// Description: function returns nodeid from entry 0x1F93
+//
+//
+// Parameters:
+//
+// Return: unsigned int = Node Id
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT unsigned int PUBLIC EplObduGetNodeId()
+{
+ unsigned int uiNodeId;
+
+ uiNodeId = EplObduCalGetNodeId();
+
+ return uiNodeId;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduSetNodeId()
+//
+// Description: function sets nodeid in entry 0x1F93
+//
+//
+// Parameters: uiNodeId_p = Node Id to set
+// NodeIdType_p= Type on which way the Node Id was set
+//
+// Return: tEplKernel = Errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduSetNodeId(unsigned int uiNodeId_p,
+ tEplObdNodeIdType NodeIdType_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplObduCalSetNodeId(uiNodeId_p, NodeIdType_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduGetAccessType()
+//
+// Description: Function returns accesstype of the entry
+//
+// Parameters: uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pAccessTyp_p = pointer to buffer to store accesstyp
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduGetAccessType(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ tEplObdAccess *
+ pAccessTyp_p)
+{
+ tEplObdAccess AccessType;
+
+ AccessType =
+ EplObduCalGetAccessType(uiIndex_p, uiSubIndex_p, pAccessTyp_p);
+
+ return AccessType;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObdReaduEntryToLe()
+//
+// Description: The function reads an object entry from the byteoder
+// of the system to the little endian byteorder for numeric values.
+// For other types a normal read will be processed. This is usefull for
+// the PDO and SDO module. The application
+// can always read the data even if attrib kEplObdAccRead
+// is not set. The attrib is only checked up for SDO transfer.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry to read
+// uiSubIndex_p = Subindex to read
+// pDstData_p = pointer to the buffer for data
+// Offset_p = offset in data for read access
+// pSize_p = IN: Size of the buffer
+// OUT: number of readed Bytes
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntryToLe(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p)
+{
+ tEplKernel Ret;
+
+ Ret =
+ EplObduCalReadEntryToLe(uiIndex_p, uiSubIndex_p, pDstData_p,
+ pSize_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduWriteEntryFromLe()
+//
+// Description: Function writes data to an OBD entry from a source with
+// little endian byteorder to the od with system specuific
+// byteorder. Not numeric values will only by copied. Strings
+// are stored with added '\0' character.
+//
+// Parameters: EPL_MCO_DECL_INSTANCE_PTR_
+// uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntryFromLe(unsigned int uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p)
+{
+ tEplKernel Ret;
+
+ Ret =
+ EplObduCalWriteEntryFromLe(uiIndex_p, uiSubIndex_p, pSrcData_p,
+ Size_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduSearchVarEntry()
+//
+// Description: gets variable from OD
+//
+// Parameters: uiIndex_p = index of the var entry to search
+// uiSubindex_p = subindex of var entry to search
+// ppVarEntry_p = pointer to the pointer to the varentry
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdVarEntry MEM **
+ ppVarEntry_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplObduCalSearchVarEntry(uiIndex_p, uiSubindex_p, ppVarEntry_p);
+
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplObduCal.c b/drivers/staging/epl/EplObduCal.c
new file mode 100644
index 000000000000..85b3df0886b1
--- /dev/null
+++ b/drivers/staging/epl/EplObduCal.c
@@ -0,0 +1,558 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for communication abstraction layer
+ for the Epl-Obd-Userspace-Modul
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObduCal.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/19 k.t.: start of the implementation
+
+****************************************************************************/
+#include "EplInc.h"
+#include "user/EplObduCal.h"
+#include "kernel/EplObdk.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0) && (EPL_OBD_USE_KERNEL != FALSE)
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalWriteEntry()
+//
+// Description: Function encapsulate access of function EplObdWriteEntry
+//
+// Parameters: uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdWriteEntry(uiIndex_p, uiSubIndex_p, pSrcData_p, Size_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalReadEntry()
+//
+// Description: Function encapsulate access of function EplObdReadEntry
+//
+// Parameters: uiIndex_p = Index oof the OD entry to read
+// uiSubIndex_p = Subindex to read
+// pDstData_p = pointer to the buffer for data
+// Offset_p = offset in data for read access
+// pSize_p = IN: Size of the buffer
+// OUT: number of readed Bytes
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdReadEntry(uiIndex_p, uiSubIndex_p, pDstData_p, pSize_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalAccessOdPart()
+//
+// Description: Function encapsulate access of function EplObdAccessOdPart
+//
+// Parameters: ObdPart_p = od-part to reset
+// Direction_p = directory flag for
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalAccessOdPart(tEplObdPart ObdPart_p,
+ tEplObdDir Direction_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdAccessOdPart(ObdPart_p, Direction_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalDefineVar()
+//
+// Description: Function encapsulate access of function EplObdDefineVar
+//
+// Parameters: pEplVarParam_p = varentry
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalDefineVar(tEplVarParam MEM *
+ pVarParam_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdDefineVar(pVarParam_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalGetObjectDataPtr()
+//
+// Description: Function encapsulate access of function EplObdGetObjectDataPtr
+//
+// Parameters: uiIndex_p = Index of the entry
+// uiSubindex_p = Subindex of the entry
+//
+// Return: void * = pointer to object data
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT void *PUBLIC EplObduCalGetObjectDataPtr(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p)
+{
+ void *pData;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ pData = EplObdGetObjectDataPtr(uiIndex_p, uiSubIndex_p);
+#else
+ pData = NULL;
+#endif
+
+ return pData;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalRegisterUserOd()
+//
+// Description: Function encapsulate access of function EplObdRegisterUserOd
+//
+// Parameters: pUserOd_p = pointer to user OD
+//
+// Return: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalRegisterUserOd(tEplObdEntryPtr
+ pUserOd_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdRegisterUserOd(pUserOd_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+
+}
+#endif
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalInitVarEntry()
+//
+// Description: Function encapsulate access of function EplObdInitVarEntry
+//
+// Parameters: pVarEntry_p = pointer to var entry structure
+// bType_p = object type
+// ObdSize_p = size of object data
+//
+// Returns: none
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT void PUBLIC EplObduCalInitVarEntry(tEplObdVarEntry MEM *
+ pVarEntry_p, BYTE bType_p,
+ tEplObdSize ObdSize_p)
+{
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ EplObdInitVarEntry(pVarEntry_p, bType_p, ObdSize_p);
+#endif
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalGetDataSize()
+//
+// Description: Function encapsulate access of function EplObdGetDataSize
+//
+// gets the data size of an object
+// for string objects it returnes the string length
+//
+// Parameters: uiIndex_p = Index
+// uiSubIndex_p= Subindex
+//
+// Return: tEplObdSize
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplObdSize PUBLIC EplObduCalGetDataSize(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p)
+{
+ tEplObdSize Size;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Size = EplObdGetDataSize(uiIndex_p, uiSubIndex_p);
+#else
+ Size = 0;
+#endif
+
+ return Size;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalGetNodeId()
+//
+// Description: Function encapsulate access of function EplObdGetNodeId
+//
+//
+// Parameters:
+//
+// Return: unsigned int = Node Id
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT unsigned int PUBLIC EplObduCalGetNodeId()
+{
+ unsigned int uiNodeId;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ uiNodeId = EplObdGetNodeId();
+#else
+ uiNodeId = 0;
+#endif
+
+ return uiNodeId;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalSetNodeId()
+//
+// Description: Function encapsulate access of function EplObdSetNodeId
+//
+//
+// Parameters: uiNodeId_p = Node Id to set
+// NodeIdType_p= Type on which way the Node Id was set
+//
+// Return: tEplKernel = Errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSetNodeId(unsigned int uiNodeId_p,
+ tEplObdNodeIdType
+ NodeIdType_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdSetNodeId(uiNodeId_p, NodeIdType_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalGetAccessType()
+//
+// Description: Function encapsulate access of function EplObdGetAccessType
+//
+// Parameters: uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pAccessTyp_p = pointer to buffer to store accesstype
+//
+// Return: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalGetAccessType(unsigned int uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ tEplObdAccess *
+ pAccessTyp_p)
+{
+ tEplObdAccess AccesType;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ AccesType = EplObdGetAccessType(uiIndex_p, uiSubIndex_p, pAccessTyp_p);
+#else
+ AccesType = 0;
+#endif
+
+ return AccesType;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalReadEntryToLe()
+//
+// Description: Function encapsulate access of function EplObdReadEntryToLe
+//
+// Parameters: uiIndex_p = Index of the OD entry to read
+// uiSubIndex_p = Subindex to read
+// pDstData_p = pointer to the buffer for data
+// Offset_p = offset in data for read access
+// pSize_p = IN: Size of the buffer
+// OUT: number of readed Bytes
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntryToLe(unsigned int uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdReadEntryToLe(uiIndex_p, uiSubIndex_p, pDstData_p, pSize_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalWriteEntryFromLe()
+//
+// Description: Function encapsulate access of function EplObdWriteEntryFromLe
+//
+// Parameters: uiIndex_p = Index of the OD entry
+// uiSubIndex_p = Subindex of the OD Entry
+// pSrcData_p = Pointer to the data to write
+// Size_p = Size of the data in Byte
+//
+// Return: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntryFromLe(unsigned int
+ uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret =
+ EplObdWriteEntryFromLe(uiIndex_p, uiSubIndex_p, pSrcData_p, Size_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplObduCalSearchVarEntry()
+//
+// Description: gets variable from OD
+//
+// Parameters: uiIndex_p = index of the var entry to search
+// uiSubindex_p = subindex of var entry to search
+// ppVarEntry_p = pointer to the pointer to the varentry
+//
+// Return: tEplKernel
+//
+// State:
+//
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC
+EplObduCalSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdVarEntry MEM ** ppVarEntry_p)
+{
+ tEplKernel Ret;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+ Ret = EplObdSearchVarEntry(uiIndex_p, uiSubindex_p, ppVarEntry_p);
+#else
+ Ret = kEplSuccessful;
+#endif
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplObjDef.h b/drivers/staging/epl/EplObjDef.h
new file mode 100644
index 000000000000..7713125a3e8d
--- /dev/null
+++ b/drivers/staging/epl/EplObjDef.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: defines objdict dictionary
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObjDef.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/06 k.t.: take ObjDef.h from CANopen and modify for EPL
+
+****************************************************************************/
+
+#ifndef _EPLOBJDEF_H_
+#define _EPLOBJDEF_H_
+
+//---------------------------------------------------------------------------
+// security checks
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// macros to help building OD
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+#if (defined (EPL_OBD_USE_VARIABLE_SUBINDEX_TAB) && (EPL_OBD_USE_VARIABLE_SUBINDEX_TAB != FALSE))
+
+#define CCM_SUBINDEX_RAM_ONLY(a) a;
+#define CCM_SUBINDEX_RAM_ONEOF(a,b) a
+
+#else
+
+#define CCM_SUBINDEX_RAM_ONLY(a)
+#define CCM_SUBINDEX_RAM_ONEOF(a,b) b
+
+#endif
+
+//---------------------------------------------------------------------------
+// To prevent unused memory in subindex tables we need this macro.
+// But not all compilers support to preset the last struct value followed by a comma.
+// Compilers which does not support a comma after last struct value has to place in a dummy subindex.
+#if ((DEV_SYSTEM & _DEV_COMMA_EXT_) != 0)
+
+#define EPL_OBD_END_SUBINDEX()
+#define EPL_OBD_MAX_ARRAY_SUBENTRIES 2
+
+#else
+
+#define EPL_OBD_END_SUBINDEX() {0,0,0,NULL,NULL}
+#define EPL_OBD_MAX_ARRAY_SUBENTRIES 3
+
+#endif
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+// globale vars
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+// -------------------------------------------------------------------------
+// creation of data in ROM memory
+// -------------------------------------------------------------------------
+#define EPL_OBD_CREATE_ROM_DATA
+#include "objdict.h"
+#undef EPL_OBD_CREATE_ROM_DATA
+
+// -------------------------------------------------------------------------
+// creation of data in RAM memory
+// -------------------------------------------------------------------------
+
+#define EPL_OBD_CREATE_RAM_DATA
+#include "objdict.h"
+#undef EPL_OBD_CREATE_RAM_DATA
+
+// -------------------------------------------------------------------------
+// creation of subindex tables in ROM and RAM
+// -------------------------------------------------------------------------
+
+#define EPL_OBD_CREATE_SUBINDEX_TAB
+#include "objdict.h"
+#undef EPL_OBD_CREATE_SUBINDEX_TAB
+
+// -------------------------------------------------------------------------
+// creation of index tables for generic, manufacturer and device part
+// -------------------------------------------------------------------------
+
+#define EPL_OBD_CREATE_INDEX_TAB
+#include "objdict.h"
+#undef EPL_OBD_CREATE_INDEX_TAB
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+// ----------------------------------------------------------------------------
+//
+// Function: EPL_OBD_INIT_RAM_NAME()
+//
+// Description: function to initialize object dictionary
+//
+// Parameters: pInitParam_p = pointer to init param struct of Epl
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+// ----------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EPL_OBD_INIT_RAM_NAME(tEplObdInitParam MEM *
+ pInitParam_p)
+{
+
+ tEplObdInitParam MEM *pInitParam = pInitParam_p;
+
+ // check if pointer to parameter structure is valid
+ // if not then only copy subindex tables below
+ if (pInitParam != NULL) {
+ // at first delete all parameters (all pointers will be set zu NULL)
+ EPL_MEMSET(pInitParam, 0, sizeof(tEplObdInitParam));
+
+#define EPL_OBD_CREATE_INIT_FUNCTION
+ {
+ // inserts code to init pointer to index tables
+#include "objdict.h"
+ }
+#undef EPL_OBD_CREATE_INIT_FUNCTION
+
+#if (defined (EPL_OBD_USER_OD) && (EPL_OBD_USER_OD != FALSE))
+ {
+ // to begin no user OD is defined
+ pInitParam_p->m_pUserPart = NULL;
+ }
+#endif
+ }
+#define EPL_OBD_CREATE_INIT_SUBINDEX
+ {
+ // inserts code to copy subindex tables
+#include "objdict.h"
+ }
+#undef EPL_OBD_CREATE_INIT_SUBINDEX
+
+ return kEplSuccessful;
+
+}
+
+#endif // _EPLOBJDEF_H_
+
+// Die letzte Zeile mu unbedingt eine leere Zeile sein, weil manche Compiler
+// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder).
diff --git a/drivers/staging/epl/EplPdo.h b/drivers/staging/epl/EplPdo.h
new file mode 100644
index 000000000000..d22ac86e85b6
--- /dev/null
+++ b/drivers/staging/epl/EplPdo.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for PDO module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplPdo.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_PDO_H_
+#define _EPL_PDO_H_
+
+#include "EplInc.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// invalid PDO-NodeId
+#define EPL_PDO_INVALID_NODE_ID 0xFF
+// NodeId for PReq RPDO
+#define EPL_PDO_PREQ_NODE_ID 0x00
+// NodeId for PRes TPDO
+#define EPL_PDO_PRES_NODE_ID 0x00
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef struct {
+ void *m_pVar;
+ WORD m_wOffset; // in Bits
+ WORD m_wSize; // in Bits
+ BOOL m_fNumeric; // numeric value -> use AMI functions
+
+} tEplPdoMapping;
+
+typedef struct {
+ unsigned int m_uiSizeOfStruct;
+ unsigned int m_uiPdoId;
+ unsigned int m_uiNodeId;
+ // 0xFF=invalid, RPDO: 0x00=PReq, localNodeId=PRes, remoteNodeId=PRes
+ // TPDO: 0x00=PRes, MN: CnNodeId=PReq
+
+ BOOL m_fTxRx;
+ BYTE m_bMappingVersion;
+ unsigned int m_uiMaxMappingEntries; // maximum number of mapping entries, i.e. size of m_aPdoMapping
+ tEplPdoMapping m_aPdoMapping[1];
+
+} tEplPdoParam;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPL_PDO_H_
diff --git a/drivers/staging/epl/EplPdok.c b/drivers/staging/epl/EplPdok.c
new file mode 100644
index 000000000000..15999b4f5750
--- /dev/null
+++ b/drivers/staging/epl/EplPdok.c
@@ -0,0 +1,694 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for kernel PDO module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplPdok.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "kernel/EplPdok.h"
+#include "kernel/EplPdokCal.h"
+#include "kernel/EplEventk.h"
+#include "kernel/EplObdk.h"
+
+#if (DEV_SYSTEM == _DEV_GNU_CF548X_)
+#include "plccore.h"
+#define PDO_LED 0x08
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) == 0)
+
+#error 'ERROR: Missing DLLk-Modul!'
+
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0)
+
+#error 'ERROR: Missing OBDk-Modul!'
+
+#endif
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define EPL_PDOK_OBD_IDX_RX_COMM_PARAM 0x1400
+#define EPL_PDOK_OBD_IDX_RX_MAPP_PARAM 0x1600
+#define EPL_PDOK_OBD_IDX_TX_COMM_PARAM 0x1800
+#define EPL_PDOK_OBD_IDX_TX_MAPP_PARAM 0x1A00
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplPdok */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokAddInstance()
+//
+// Description: add and initialize new instance of EPL stack
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokAddInstance(void)
+{
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokDelInstance()
+//
+// Description: deletes an instance of EPL stack
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokDelInstance(void)
+{
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokCbPdoReceived
+//
+// Description: This function is called by DLL if PRes or PReq frame was
+// received. It posts the frame to the event queue.
+// It is called in states NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
+// The passed PDO needs not to be valid.
+//
+// Parameters: pFrameInfo_p = pointer to frame info structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+
+#if (DEV_SYSTEM == _DEV_GNU_CF548X_)
+ // reset LED
+// MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level
+#endif
+
+ Event.m_EventSink = kEplEventSinkPdok;
+ Event.m_EventType = kEplEventTypePdoRx;
+ // limit copied data to size of PDO (because from some CNs the frame is larger than necessary)
+ Event.m_uiSize = AmiGetWordFromLe(&pFrameInfo_p->m_pFrame->m_Data.m_Pres.m_le_wSize) + 24; // pFrameInfo_p->m_uiFrameSize;
+ Event.m_pArg = pFrameInfo_p->m_pFrame;
+ Ret = EplEventkPost(&Event);
+
+#if (DEV_SYSTEM == _DEV_GNU_CF548X_)
+ // set LED
+// MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokCbPdoTransmitted
+//
+// Description: This function is called by DLL if PRes or PReq frame was
+// sent. It posts the pointer to the frame to the event queue.
+// It is called in NMT_CS_PRE_OPERATIONAL_2,
+// NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
+//
+// Parameters: pFrameInfo_p = pointer to frame info structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCbPdoTransmitted(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+
+#if (DEV_SYSTEM == _DEV_GNU_CF548X_)
+ // reset LED
+ MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level
+#endif
+
+ Event.m_EventSink = kEplEventSinkPdok;
+ Event.m_EventType = kEplEventTypePdoTx;
+ Event.m_uiSize = sizeof(tEplFrameInfo);
+ Event.m_pArg = pFrameInfo_p;
+ Ret = EplEventkPost(&Event);
+
+#if (DEV_SYSTEM == _DEV_GNU_CF548X_)
+ // set LED
+ MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokCbSoa
+//
+// Description: This function is called by DLL if SoA frame was
+// received resp. sent. It posts this event to the event queue.
+//
+// Parameters: pFrameInfo_p = pointer to frame info structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCbSoa(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplEvent Event;
+
+ Event.m_EventSink = kEplEventSinkPdok;
+ Event.m_EventType = kEplEventTypePdoSoa;
+ Event.m_uiSize = 0;
+ Event.m_pArg = NULL;
+ Ret = EplEventkPost(&Event);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokProcess
+//
+// Description: This function processes all received and transmitted PDOs.
+// This function must not be interrupted by any other task
+// except ISRs (like the ethernet driver ISR, which may call
+// EplPdokCbFrameReceived() or EplPdokCbFrameTransmitted()).
+//
+// Parameters: pEvent_p = pointer to event structure
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokProcess(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ WORD wPdoSize;
+ WORD wBitOffset;
+ WORD wBitSize;
+ WORD wVarSize;
+ QWORD qwObjectMapping;
+ BYTE bMappSubindex;
+ BYTE bObdSubindex;
+ WORD wObdMappIndex;
+ WORD wObdCommIndex;
+ WORD wPdoId;
+ BYTE bObdData;
+ BYTE bObjectCount;
+ BYTE bFrameData;
+ BOOL fValid;
+ tEplObdSize ObdSize;
+ tEplFrame *pFrame;
+ tEplFrameInfo *pFrameInfo;
+ unsigned int uiNodeId;
+ tEplMsgType MsgType;
+
+ // 0xFF=invalid, RPDO: 0x00=PReq, localNodeId=PRes, remoteNodeId=PRes
+ // TPDO: 0x00=PRes, MN: CnNodeId=PReq
+
+ switch (pEvent_p->m_EventType) {
+ case kEplEventTypePdoRx: // RPDO received
+ pFrame = (tEplFrame *) pEvent_p->m_pArg;
+
+ // check if received RPDO is valid
+ bFrameData =
+ AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1);
+ if ((bFrameData & EPL_FRAME_FLAG1_RD) == 0) { // RPDO invalid
+ goto Exit;
+ }
+ // retrieve EPL message type
+ MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType);
+ if (MsgType == kEplMsgTypePreq) { // RPDO is PReq frame
+ uiNodeId = EPL_PDO_PREQ_NODE_ID; // 0x00
+ } else { // RPDO is PRes frame
+ // retrieve node ID
+ uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
+ }
+
+ // search for appropriate valid RPDO in OD
+ wObdMappIndex = EPL_PDOK_OBD_IDX_RX_MAPP_PARAM;
+ for (wObdCommIndex = EPL_PDOK_OBD_IDX_RX_COMM_PARAM;
+ wObdCommIndex < (EPL_PDOK_OBD_IDX_RX_COMM_PARAM + 0x00FF);
+ wObdCommIndex++, wObdMappIndex++) {
+ ObdSize = 1;
+ // read node ID from OD
+ Ret =
+ EplObdReadEntry(wObdCommIndex, 0x01, &bObdData,
+ &ObdSize);
+ if ((Ret == kEplObdIndexNotExist)
+ || (Ret == kEplObdSubindexNotExist)
+ || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
+ Ret = kEplSuccessful;
+ goto Exit;
+ } else if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // entry read successfully
+ if (bObdData != uiNodeId) { // node ID does not equal - wrong PDO, try next PDO in OD
+ continue;
+ }
+ ObdSize = 1;
+ // read number of mapped objects from OD; this indicates if the PDO is valid
+ Ret =
+ EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount,
+ &ObdSize);
+ if ((Ret == kEplObdIndexNotExist)
+ || (Ret == kEplObdSubindexNotExist)
+ || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
+ Ret = kEplSuccessful;
+ goto Exit;
+ } else if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // entry read successfully
+ if (bObjectCount == 0) { // PDO in OD not valid, try next PDO in OD
+ continue;
+ }
+
+ ObdSize = 1;
+ // check PDO mapping version
+ Ret =
+ EplObdReadEntry(wObdCommIndex, 0x02, &bObdData,
+ &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // entry read successfully
+ // retrieve PDO version from frame
+ bFrameData =
+ AmiGetByteFromLe(&pFrame->m_Data.m_Pres.
+ m_le_bPdoVersion);
+ if ((bObdData & EPL_VERSION_MAIN) != (bFrameData & EPL_VERSION_MAIN)) { // PDO versions do not match
+ // $$$ raise PDO error
+ // termiate processing of this RPDO
+ goto Exit;
+ }
+ // valid RPDO found
+
+ // retrieve PDO size
+ wPdoSize =
+ AmiGetWordFromLe(&pFrame->m_Data.m_Pres.m_le_wSize);
+
+ // process mapping
+ for (bMappSubindex = 1; bMappSubindex <= bObjectCount;
+ bMappSubindex++) {
+ ObdSize = 8; // QWORD
+ // read object mapping from OD
+ Ret =
+ EplObdReadEntry(wObdMappIndex,
+ bMappSubindex,
+ &qwObjectMapping, &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
+ if (qwObjectMapping == 0) { // invalid entry, continue with next entry
+ continue;
+ }
+ // decode object mapping
+ wObdCommIndex =
+ (WORD) (qwObjectMapping &
+ 0x000000000000FFFFLL);
+ bObdSubindex =
+ (BYTE) ((qwObjectMapping &
+ 0x0000000000FF0000LL) >> 16);
+ wBitOffset =
+ (WORD) ((qwObjectMapping &
+ 0x0000FFFF00000000LL) >> 32);
+ wBitSize =
+ (WORD) ((qwObjectMapping &
+ 0xFFFF000000000000LL) >> 48);
+
+ // check if object exceeds PDO size
+ if (((wBitOffset + wBitSize) >> 3) > wPdoSize) { // wrong object mapping; PDO size is too low
+ // $$$ raise PDO error
+ // terminate processing of this RPDO
+ goto Exit;
+ }
+ // copy object from RPDO to process/OD variable
+ ObdSize = wBitSize >> 3;
+ Ret =
+ EplObdWriteEntryFromLe(wObdCommIndex,
+ bObdSubindex,
+ &pFrame->m_Data.
+ m_Pres.
+ m_le_abPayload[(wBitOffset >> 3)], ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+
+ }
+
+ // processing finished successfully
+ goto Exit;
+ }
+ break;
+
+ case kEplEventTypePdoTx: // TPDO transmitted
+ pFrameInfo = (tEplFrameInfo *) pEvent_p->m_pArg;
+ pFrame = pFrameInfo->m_pFrame;
+
+ // set TPDO invalid, so that only fully processed TPDOs are sent as valid
+ bFrameData =
+ AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1);
+ AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bFlag1,
+ (bFrameData & ~EPL_FRAME_FLAG1_RD));
+
+ // retrieve EPL message type
+ MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType);
+ if (MsgType == kEplMsgTypePres) { // TPDO is PRes frame
+ uiNodeId = EPL_PDO_PRES_NODE_ID; // 0x00
+ } else { // TPDO is PReq frame
+ // retrieve node ID
+ uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
+ }
+
+ // search for appropriate valid TPDO in OD
+ wObdMappIndex = EPL_PDOK_OBD_IDX_TX_MAPP_PARAM;
+ wObdCommIndex = EPL_PDOK_OBD_IDX_TX_COMM_PARAM;
+ for (wPdoId = 0;; wPdoId++, wObdCommIndex++, wObdMappIndex++) {
+ ObdSize = 1;
+ // read node ID from OD
+ Ret =
+ EplObdReadEntry(wObdCommIndex, 0x01, &bObdData,
+ &ObdSize);
+ if ((Ret == kEplObdIndexNotExist)
+ || (Ret == kEplObdSubindexNotExist)
+ || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
+ Ret = kEplSuccessful;
+ goto Exit;
+ } else if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // entry read successfully
+ if (bObdData != uiNodeId) { // node ID does not equal - wrong PDO, try next PDO in OD
+ continue;
+ }
+ ObdSize = 1;
+ // read number of mapped objects from OD; this indicates if the PDO is valid
+ Ret =
+ EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount,
+ &ObdSize);
+ if ((Ret == kEplObdIndexNotExist)
+ || (Ret == kEplObdSubindexNotExist)
+ || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
+ Ret = kEplSuccessful;
+ goto Exit;
+ } else if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // entry read successfully
+ if (bObjectCount == 0) { // PDO in OD not valid, try next PDO in OD
+ continue;
+ }
+ // valid TPDO found
+
+ ObdSize = 1;
+ // get PDO mapping version from OD
+ Ret =
+ EplObdReadEntry(wObdCommIndex, 0x02, &bObdData,
+ &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // entry read successfully
+ // set PDO version in frame
+ AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bPdoVersion,
+ bObdData);
+
+ // calculate PDO size
+ wPdoSize = 0;
+
+ // process mapping
+ for (bMappSubindex = 1; bMappSubindex <= bObjectCount;
+ bMappSubindex++) {
+ ObdSize = 8; // QWORD
+ // read object mapping from OD
+ Ret =
+ EplObdReadEntry(wObdMappIndex,
+ bMappSubindex,
+ &qwObjectMapping, &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+ // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
+ if (qwObjectMapping == 0) { // invalid entry, continue with next entry
+ continue;
+ }
+ // decode object mapping
+ wObdCommIndex =
+ (WORD) (qwObjectMapping &
+ 0x000000000000FFFFLL);
+ bObdSubindex =
+ (BYTE) ((qwObjectMapping &
+ 0x0000000000FF0000LL) >> 16);
+ wBitOffset =
+ (WORD) ((qwObjectMapping &
+ 0x0000FFFF00000000LL) >> 32);
+ wBitSize =
+ (WORD) ((qwObjectMapping &
+ 0xFFFF000000000000LL) >> 48);
+
+ // calculate max PDO size
+ ObdSize = wBitSize >> 3;
+ wVarSize = (wBitOffset >> 3) + (WORD) ObdSize;
+ if ((unsigned int)(wVarSize + 24) > pFrameInfo->m_uiFrameSize) { // TPDO is too short
+ // $$$ raise PDO error, set Ret
+ goto Exit;
+ }
+ if (wVarSize > wPdoSize) { // memorize new PDO size
+ wPdoSize = wVarSize;
+ }
+ // copy object from process/OD variable to TPDO
+ Ret =
+ EplObdReadEntryToLe(wObdCommIndex,
+ bObdSubindex,
+ &pFrame->m_Data.m_Pres.
+ m_le_abPayload[(wBitOffset >> 3)], &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ goto Exit;
+ }
+
+ }
+
+ // set PDO size in frame
+ AmiSetWordToLe(&pFrame->m_Data.m_Pres.m_le_wSize,
+ wPdoSize);
+
+ Ret = EplPdokCalAreTpdosValid(&fValid);
+ if (fValid != FALSE) {
+ // set TPDO valid
+ bFrameData =
+ AmiGetByteFromLe(&pFrame->m_Data.m_Pres.
+ m_le_bFlag1);
+ AmiSetByteToLe(&pFrame->m_Data.m_Pres.
+ m_le_bFlag1,
+ (bFrameData |
+ EPL_FRAME_FLAG1_RD));
+ }
+ // processing finished successfully
+
+ goto Exit;
+ }
+ break;
+
+ case kEplEventTypePdoSoa: // SoA received
+
+ // invalidate TPDOs
+ Ret = EplPdokCalSetTpdosValid(FALSE);
+ break;
+
+ default:
+ {
+ ASSERTMSG(FALSE,
+ "EplPdokProcess(): unhandled event type!\n");
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplPdokCal.c b/drivers/staging/epl/EplPdokCal.c
new file mode 100644
index 000000000000..f44c47578002
--- /dev/null
+++ b/drivers/staging/epl/EplPdokCal.c
@@ -0,0 +1,266 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for kernel PDO Communication Abstraction Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplPdokCal.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/27 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "kernel/EplPdokCal.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplPdokCal */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ BOOL m_fTpdosValid;
+
+} tEplPdokCalInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+static tEplPdokCalInstance EplPdokCalInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokCalAddInstance()
+//
+// Description: add and initialize new instance of EPL stack
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCalAddInstance(void)
+{
+
+ EPL_MEMSET(&EplPdokCalInstance_g, 0, sizeof(EplPdokCalInstance_g));
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokCalDelInstance()
+//
+// Description: deletes an instance of EPL stack
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCalDelInstance(void)
+{
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokCalSetTpdosValid()
+//
+// Description: This function sets the validity flag for TPDOs to the
+// specified value.
+//
+// Parameters: fValid_p = validity flag
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCalSetTpdosValid(BOOL fValid_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ EplPdokCalInstance_g.m_fTpdosValid = fValid_p;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdokCalAreTpdosValid()
+//
+// Description: This function returns the validity flag for TPDOs.
+//
+// Parameters: pfValid_p = OUT: validity flag
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCalAreTpdosValid(BOOL * pfValid_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ *pfValid_p = EplPdokCalInstance_g.m_fTpdosValid;
+
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+#endif
+
+// EOF
diff --git a/drivers/staging/epl/EplPdou.c b/drivers/staging/epl/EplPdou.c
new file mode 100644
index 000000000000..e7b10653a0ed
--- /dev/null
+++ b/drivers/staging/epl/EplPdou.c
@@ -0,0 +1,565 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for user PDO module
+ Currently, this module just implements a OD callback function
+ to check if the PDO configuration is valid.
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplPdou.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#include "EplInc.h"
+//#include "user/EplPdouCal.h"
+#include "user/EplObdu.h"
+#include "user/EplPdou.h"
+#include "EplSdoAc.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0)
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
+#error "EPL PDOu module needs EPL module OBDU or OBDK!"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define EPL_PDOU_OBD_IDX_RX_COMM_PARAM 0x1400
+#define EPL_PDOU_OBD_IDX_RX_MAPP_PARAM 0x1600
+#define EPL_PDOU_OBD_IDX_TX_COMM_PARAM 0x1800
+#define EPL_PDOU_OBD_IDX_TX_MAPP_PARAM 0x1A00
+#define EPL_PDOU_OBD_IDX_MAPP_PARAM 0x0200
+#define EPL_PDOU_OBD_IDX_MASK 0xFF00
+#define EPL_PDOU_PDO_ID_MASK 0x00FF
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S EplPdou */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM * pParam_p,
+ unsigned int uiIndex_p);
+
+static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p,
+ unsigned int *puiIndex_p,
+ unsigned int *puiSubIndex_p,
+ unsigned int *puiBitOffset_p,
+ unsigned int *puiBitSize_p);
+
+static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p,
+ tEplObdAccess AccessType_p,
+ DWORD * pdwAbortCode_p,
+ unsigned int *puiPdoSize_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdouAddInstance()
+//
+// Description: add and initialize new instance of EPL stack
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdouAddInstance(void)
+{
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdouDelInstance()
+//
+// Description: deletes an instance of EPL stack
+//
+// Parameters: none
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdouDelInstance(void)
+{
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdouCbObdAccess
+//
+// Description: callback function for OD accesses
+//
+// Parameters: pParam_p = OBD parameter
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiPdoId;
+ unsigned int uiIndexType;
+ tEplObdSize ObdSize;
+ BYTE bObjectCount;
+ QWORD qwObjectMapping;
+ tEplObdAccess AccessType;
+ BYTE bMappSubindex;
+ unsigned int uiCurPdoSize;
+ WORD wMaxPdoSize;
+ unsigned int uiSubIndex;
+
+ // fetch PDO ID
+ uiPdoId = pParam_p->m_uiIndex & EPL_PDOU_PDO_ID_MASK;
+
+ // fetch object index type
+ uiIndexType = pParam_p->m_uiIndex & EPL_PDOU_OBD_IDX_MASK;
+
+ if (pParam_p->m_ObdEvent != kEplObdEvPreWrite) { // read accesses, post write events etc. are OK
+ pParam_p->m_dwAbortCode = 0;
+ goto Exit;
+ }
+ // check index type
+ switch (uiIndexType) {
+ case EPL_PDOU_OBD_IDX_RX_COMM_PARAM:
+ // RPDO communication parameter accessed
+ case EPL_PDOU_OBD_IDX_TX_COMM_PARAM:
+ { // TPDO communication parameter accessed
+ Ret = EplPdouCheckPdoValidity(pParam_p,
+ (EPL_PDOU_OBD_IDX_MAPP_PARAM
+ | pParam_p->m_uiIndex));
+ if (Ret != kEplSuccessful) { // PDO is valid or does not exist
+ goto Exit;
+ }
+
+ goto Exit;
+ }
+
+ case EPL_PDOU_OBD_IDX_RX_MAPP_PARAM:
+ { // RPDO mapping parameter accessed
+
+ AccessType = kEplObdAccWrite;
+ break;
+ }
+
+ case EPL_PDOU_OBD_IDX_TX_MAPP_PARAM:
+ { // TPDO mapping parameter accessed
+
+ AccessType = kEplObdAccRead;
+ break;
+ }
+
+ default:
+ { // this callback function is only for
+ // PDO mapping and communication parameters
+ pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
+ goto Exit;
+ }
+ }
+
+ // RPDO and TPDO mapping parameter accessed
+
+ if (pParam_p->m_uiSubIndex == 0) { // object mapping count accessed
+
+ // PDO is enabled or disabled
+ bObjectCount = *((BYTE *) pParam_p->m_pArg);
+
+ if (bObjectCount == 0) { // PDO shall be disabled
+
+ // that is always possible
+ goto Exit;
+ }
+ // PDO shall be enabled
+ // it should have been disabled for this operation
+ Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex);
+ if (Ret != kEplSuccessful) { // PDO is valid or does not exist
+ goto Exit;
+ }
+
+ if (AccessType == kEplObdAccWrite) {
+ uiSubIndex = 0x04; // PReqActPayloadLimit_U16
+ } else {
+ uiSubIndex = 0x05; // PResActPayloadLimit_U16
+ }
+
+ // fetch maximum PDO size from Object 1F98h: NMT_CycleTiming_REC
+ ObdSize = sizeof(wMaxPdoSize);
+ Ret =
+ EplObduReadEntry(0x1F98, uiSubIndex, &wMaxPdoSize,
+ &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
+ goto Exit;
+ }
+ // check all objectmappings
+ for (bMappSubindex = 1; bMappSubindex <= bObjectCount;
+ bMappSubindex++) {
+ // read object mapping from OD
+ ObdSize = sizeof(qwObjectMapping); // QWORD
+ Ret = EplObduReadEntry(pParam_p->m_uiIndex,
+ bMappSubindex, &qwObjectMapping,
+ &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ pParam_p->m_dwAbortCode =
+ EPL_SDOAC_GENERAL_ERROR;
+ goto Exit;
+ }
+ // check object mapping
+ Ret = EplPdouCheckObjectMapping(qwObjectMapping,
+ AccessType,
+ &pParam_p->
+ m_dwAbortCode,
+ &uiCurPdoSize);
+ if (Ret != kEplSuccessful) { // illegal object mapping
+ goto Exit;
+ }
+
+ if (uiCurPdoSize > wMaxPdoSize) { // mapping exceeds object size
+ pParam_p->m_dwAbortCode =
+ EPL_SDOAC_GENERAL_ERROR;
+ Ret = kEplPdoVarNotFound;
+ }
+
+ }
+
+ } else { // ObjectMapping
+ Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex);
+ if (Ret != kEplSuccessful) { // PDO is valid or does not exist
+ goto Exit;
+ }
+ // check existence of object and validity of object length
+
+ qwObjectMapping = *((QWORD *) pParam_p->m_pArg);
+
+ Ret = EplPdouCheckObjectMapping(qwObjectMapping,
+ AccessType,
+ &pParam_p->m_dwAbortCode,
+ &uiCurPdoSize);
+
+ }
+
+ Exit:
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdouCheckPdoValidity
+//
+// Description: check if PDO is valid
+//
+// Parameters: pParam_p = OBD parameter
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM * pParam_p,
+ unsigned int uiIndex_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplObdSize ObdSize;
+ BYTE bObjectCount;
+
+ ObdSize = 1;
+ // read number of mapped objects from OD; this indicates if the PDO is valid
+ Ret = EplObduReadEntry(uiIndex_p, 0x00, &bObjectCount, &ObdSize);
+ if (Ret != kEplSuccessful) { // other fatal error occured
+ pParam_p->m_dwAbortCode =
+ EPL_SDOAC_GEN_INTERNAL_INCOMPATIBILITY;
+ goto Exit;
+ }
+ // entry read successfully
+ if (bObjectCount != 0) { // PDO in OD is still valid
+ pParam_p->m_dwAbortCode = EPL_SDOAC_GEN_PARAM_INCOMPATIBILITY;
+ Ret = kEplPdoNotExist;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdouDecodeObjectMapping
+//
+// Description: decodes the given object mapping entry into index, subindex,
+// bit offset and bit size.
+//
+// Parameters: qwObjectMapping_p = object mapping entry
+// puiIndex_p = [OUT] pointer to object index
+// puiSubIndex_p = [OUT] pointer to subindex
+// puiBitOffset_p = [OUT] pointer to bit offset
+// puiBitSize_p = [OUT] pointer to bit size
+//
+// Returns: (void)
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p,
+ unsigned int *puiIndex_p,
+ unsigned int *puiSubIndex_p,
+ unsigned int *puiBitOffset_p,
+ unsigned int *puiBitSize_p)
+{
+ *puiIndex_p = (unsigned int)
+ (qwObjectMapping_p & 0x000000000000FFFFLL);
+
+ *puiSubIndex_p = (unsigned int)
+ ((qwObjectMapping_p & 0x0000000000FF0000LL) >> 16);
+
+ *puiBitOffset_p = (unsigned int)
+ ((qwObjectMapping_p & 0x0000FFFF00000000LL) >> 32);
+
+ *puiBitSize_p = (unsigned int)
+ ((qwObjectMapping_p & 0xFFFF000000000000LL) >> 48);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplPdouCheckObjectMapping
+//
+// Description: checks the given object mapping entry.
+//
+// Parameters: qwObjectMapping_p = object mapping entry
+// AccessType_p = access type to mapped object:
+// write = RPDO and read = TPDO
+// puiPdoSize_p = [OUT] pointer to covered PDO size
+// (offset + size) in byte;
+// 0 if mapping failed
+// pdwAbortCode_p = [OUT] pointer to SDO abort code;
+// 0 if mapping is possible
+//
+// Returns: tEplKernel = error code
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p,
+ tEplObdAccess AccessType_p,
+ DWORD * pdwAbortCode_p,
+ unsigned int *puiPdoSize_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplObdSize ObdSize;
+ unsigned int uiIndex;
+ unsigned int uiSubIndex;
+ unsigned int uiBitOffset;
+ unsigned int uiBitSize;
+ tEplObdAccess AccessType;
+ BOOL fNumerical;
+
+ if (qwObjectMapping_p == 0) { // discard zero value
+ *puiPdoSize_p = 0;
+ goto Exit;
+ }
+ // decode object mapping
+ EplPdouDecodeObjectMapping(qwObjectMapping_p,
+ &uiIndex,
+ &uiSubIndex, &uiBitOffset, &uiBitSize);
+
+ if ((uiBitOffset & 0x7) != 0x0) { // bit mapping is not supported
+ *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
+ Ret = kEplPdoGranularityMismatch;
+ goto Exit;
+ }
+
+ if ((uiBitSize & 0x7) != 0x0) { // bit mapping is not supported
+ *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
+ Ret = kEplPdoGranularityMismatch;
+ goto Exit;
+ }
+ // check access type
+ Ret = EplObduGetAccessType(uiIndex, uiSubIndex, &AccessType);
+ if (Ret != kEplSuccessful) { // entry doesn't exist
+ *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST;
+ goto Exit;
+ }
+
+ if ((AccessType & kEplObdAccPdo) == 0) { // object is not mappable
+ *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE;
+ Ret = kEplPdoVarNotFound;
+ goto Exit;
+ }
+
+ if ((AccessType & AccessType_p) == 0) { // object is not writeable (RPDO) or readable (TPDO) respectively
+ *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE;
+ Ret = kEplPdoVarNotFound;
+ goto Exit;
+ }
+
+ ObdSize = EplObduGetDataSize(uiIndex, uiSubIndex);
+ if (ObdSize < (uiBitSize >> 3)) { // object does not exist or has smaller size
+ *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
+ Ret = kEplPdoVarNotFound;
+ }
+
+ Ret = EplObduIsNumerical(uiIndex, uiSubIndex, &fNumerical);
+ if (Ret != kEplSuccessful) { // entry doesn't exist
+ *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST;
+ goto Exit;
+ }
+
+ if ((fNumerical != FALSE)
+ && ((uiBitSize >> 3) != ObdSize)) {
+ // object is numerical,
+ // therefor size has to fit, but it does not.
+ *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
+ Ret = kEplPdoVarNotFound;
+ goto Exit;
+ }
+ // calucaled needed PDO size
+ *puiPdoSize_p = (uiBitOffset >> 3) + (uiBitSize >> 3);
+
+ Exit:
+ return Ret;
+}
+
+#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplSdo.h b/drivers/staging/epl/EplSdo.h
new file mode 100644
index 000000000000..1cb3f2de4a3c
--- /dev/null
+++ b/drivers/staging/epl/EplSdo.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for api function of the sdo module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdo.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "EplFrame.h"
+#include "EplSdoAc.h"
+
+#ifndef _EPLSDO_H_
+#define _EPLSDO_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+// global defines
+#ifndef EPL_SDO_MAX_PAYLOAD
+#define EPL_SDO_MAX_PAYLOAD 256
+#endif
+
+// handle between Protocol Abstraction Layer and asynchronous SDO Sequence Layer
+#define EPL_SDO_UDP_HANDLE 0x8000
+#define EPL_SDO_ASND_HANDLE 0x4000
+#define EPL_SDO_ASY_HANDLE_MASK 0xC000
+#define EPL_SDO_ASY_INVALID_HDL 0x3FFF
+
+// handle between SDO Sequence Layer and sdo command layer
+#define EPL_SDO_ASY_HANDLE 0x8000
+#define EPL_SDO_PDO_HANDLE 0x4000
+#define EPL_SDO_SEQ_HANDLE_MASK 0xC000
+#define EPL_SDO_SEQ_INVALID_HDL 0x3FFF
+
+#define EPL_ASND_HEADER_SIZE 4
+//#define EPL_SEQ_HEADER_SIZE 4
+#define EPL_ETHERNET_HEADER_SIZE 14
+
+#define EPL_SEQ_NUM_MASK 0xFC
+
+// size for send buffer and history
+#define EPL_MAX_SDO_FRAME_SIZE EPL_C_IP_MIN_MTU
+// size for receive frame
+// -> needed because SND-Kit sends up to 1518 Byte
+// without Sdo-Command: Maximum Segment Size
+#define EPL_MAX_SDO_REC_FRAME_SIZE EPL_C_IP_MAX_MTU
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+// handle between Protocol Abstraction Layer and asynchronuus SDO Sequence Layer
+typedef unsigned int tEplSdoConHdl;
+
+// callback function pointer for Protocol Abstraction Layer to call
+// asynchronuus SDO Sequence Layer
+typedef tEplKernel(PUBLIC * tEplSequLayerReceiveCb) (tEplSdoConHdl ConHdl_p,
+ tEplAsySdoSeq *
+ pSdoSeqData_p,
+ unsigned int uiDataSize_p);
+
+// handle between asynchronuus SDO Sequence Layer and SDO Command layer
+typedef unsigned int tEplSdoSeqConHdl;
+
+// callback function pointer for asynchronuus SDO Sequence Layer to call
+// SDO Command layer for received data
+typedef tEplKernel(PUBLIC *
+ tEplSdoComReceiveCb) (tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplAsySdoCom * pAsySdoCom_p,
+ unsigned int uiDataSize_p);
+
+// status of connection
+typedef enum {
+ kAsySdoConStateConnected = 0x00,
+ kAsySdoConStateInitError = 0x01,
+ kAsySdoConStateConClosed = 0x02,
+ kAsySdoConStateAckReceived = 0x03,
+ kAsySdoConStateFrameSended = 0x04,
+ kAsySdoConStateTimeout = 0x05
+} tEplAsySdoConState;
+
+// callback function pointer for asynchronuus SDO Sequence Layer to call
+// SDO Command layer for connection status
+typedef tEplKernel(PUBLIC * tEplSdoComConCb) (tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplAsySdoConState
+ AsySdoConState_p);
+
+// handle between SDO Command layer and application
+typedef unsigned int tEplSdoComConHdl;
+
+// status of connection
+typedef enum {
+ kEplSdoComTransferNotActive = 0x00,
+ kEplSdoComTransferRunning = 0x01,
+ kEplSdoComTransferTxAborted = 0x02,
+ kEplSdoComTransferRxAborted = 0x03,
+ kEplSdoComTransferFinished = 0x04,
+ kEplSdoComTransferLowerLayerAbort = 0x05
+} tEplSdoComConState;
+
+// SDO Services and Command-Ids from DS 1.0.0 p.152
+typedef enum {
+ kEplSdoServiceNIL = 0x00,
+ kEplSdoServiceWriteByIndex = 0x01,
+ kEplSdoServiceReadByIndex = 0x02
+ //--------------------------------
+ // the following services are optional and
+ // not supported now
+/*
+ kEplSdoServiceWriteAllByIndex = 0x03,
+ kEplSdoServiceReadAllByIndex = 0x04,
+ kEplSdoServiceWriteByName = 0x05,
+ kEplSdoServiceReadByName = 0x06,
+
+ kEplSdoServiceFileWrite = 0x20,
+ kEplSdoServiceFileRead = 0x21,
+
+ kEplSdoServiceWriteMultiByIndex = 0x31,
+ kEplSdoServiceReadMultiByIndex = 0x32,
+
+ kEplSdoServiceMaxSegSize = 0x70
+
+ // 0x80 - 0xFF manufacturer specific
+
+ */
+} tEplSdoServiceType;
+
+// describes if read or write access
+typedef enum {
+ kEplSdoAccessTypeRead = 0x00,
+ kEplSdoAccessTypeWrite = 0x01
+} tEplSdoAccessType;
+
+typedef enum {
+ kEplSdoTypeAuto = 0x00,
+ kEplSdoTypeUdp = 0x01,
+ kEplSdoTypeAsnd = 0x02,
+ kEplSdoTypePdo = 0x03
+} tEplSdoType;
+
+typedef enum {
+ kEplSdoTransAuto = 0x00,
+ kEplSdoTransExpedited = 0x01,
+ kEplSdoTransSegmented = 0x02
+} tEplSdoTransType;
+
+// structure to inform application about finish of SDO transfer
+typedef struct {
+ tEplSdoComConHdl m_SdoComConHdl;
+ tEplSdoComConState m_SdoComConState;
+ DWORD m_dwAbortCode;
+ tEplSdoAccessType m_SdoAccessType;
+ unsigned int m_uiNodeId; // NodeId of the target
+ unsigned int m_uiTargetIndex; // index which was accessed
+ unsigned int m_uiTargetSubIndex; // subindex which was accessed
+ unsigned int m_uiTransferredByte; // number of bytes transferred
+ void *m_pUserArg; // user definable argument pointer
+
+} tEplSdoComFinished;
+
+// callback function pointer to inform application about connection
+typedef tEplKernel(PUBLIC * tEplSdoFinishedCb) (tEplSdoComFinished *
+ pSdoComFinished_p);
+
+// structure to init SDO transfer to Read or Write by Index
+typedef struct {
+ tEplSdoComConHdl m_SdoComConHdl;
+ unsigned int m_uiIndex;
+ unsigned int m_uiSubindex;
+ void *m_pData;
+ unsigned int m_uiDataSize;
+ unsigned int m_uiTimeout; // not used in this version
+ tEplSdoAccessType m_SdoAccessType;
+ tEplSdoFinishedCb m_pfnSdoFinishedCb;
+ void *m_pUserArg; // user definable argument pointer
+
+} tEplSdoComTransParamByIndex;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPLSDO_H_
diff --git a/drivers/staging/epl/EplSdoAc.h b/drivers/staging/epl/EplSdoAc.h
new file mode 100644
index 000000000000..400fb38ce3e9
--- /dev/null
+++ b/drivers/staging/epl/EplSdoAc.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: definitions for SDO Abort codes
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoAc.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ ...
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/30 k.t.: first implementation
+
+****************************************************************************/
+
+#ifndef _EPLSDOAC_H_
+#define _EPLSDOAC_H_
+
+// =========================================================================
+// SDO abort codes
+// =========================================================================
+
+#define EPL_SDOAC_TIME_OUT 0x05040000L
+#define EPL_SDOAC_UNKNOWN_COMMAND_SPECIFIER 0x05040001L
+#define EPL_SDOAC_INVALID_BLOCK_SIZE 0x05040002L
+#define EPL_SDOAC_INVALID_SEQUENCE_NUMBER 0x05040003L
+#define EPL_SDOAC_OUT_OF_MEMORY 0x05040005L
+#define EPL_SDOAC_UNSUPPORTED_ACCESS 0x06010000L
+#define EPL_SDOAC_READ_TO_WRITE_ONLY_OBJ 0x06010001L
+#define EPL_SDOAC_WRITE_TO_READ_ONLY_OBJ 0x06010002L
+#define EPL_SDOAC_OBJECT_NOT_EXIST 0x06020000L
+#define EPL_SDOAC_OBJECT_NOT_MAPPABLE 0x06040041L
+#define EPL_SDOAC_PDO_LENGTH_EXCEEDED 0x06040042L
+#define EPL_SDOAC_GEN_PARAM_INCOMPATIBILITY 0x06040043L
+#define EPL_SDOAC_INVALID_HEARTBEAT_DEC 0x06040044L
+#define EPL_SDOAC_GEN_INTERNAL_INCOMPATIBILITY 0x06040047L
+#define EPL_SDOAC_ACCESS_FAILED_DUE_HW_ERROR 0x06060000L
+#define EPL_SDOAC_DATA_TYPE_LENGTH_NOT_MATCH 0x06070010L
+#define EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH 0x06070012L
+#define EPL_SDOAC_DATA_TYPE_LENGTH_TOO_LOW 0x06070013L
+#define EPL_SDOAC_SUB_INDEX_NOT_EXIST 0x06090011L
+#define EPL_SDOAC_VALUE_RANGE_EXCEEDED 0x06090030L
+#define EPL_SDOAC_VALUE_RANGE_TOO_HIGH 0x06090031L
+#define EPL_SDOAC_VALUE_RANGE_TOO_LOW 0x06090032L
+#define EPL_SDOAC_MAX_VALUE_LESS_MIN_VALUE 0x06090036L
+#define EPL_SDOAC_GENERAL_ERROR 0x08000000L
+#define EPL_SDOAC_DATA_NOT_TRANSF_OR_STORED 0x08000020L
+#define EPL_SDOAC_DATA_NOT_TRANSF_DUE_LOCAL_CONTROL 0x08000021L
+#define EPL_SDOAC_DATA_NOT_TRANSF_DUE_DEVICE_STATE 0x08000022L
+#define EPL_SDOAC_OBJECT_DICTIONARY_NOT_EXIST 0x08000023L
+#define EPL_SDOAC_CONFIG_DATA_EMPTY 0x08000024L
+
+#endif // _EPLSDOAC_H_
+
+// Die letzte Zeile mu unbedingt eine leere Zeile sein, weil manche Compiler
+// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder).
diff --git a/drivers/staging/epl/EplSdoAsndu.c b/drivers/staging/epl/EplSdoAsndu.c
new file mode 100644
index 000000000000..05a00c9a731e
--- /dev/null
+++ b/drivers/staging/epl/EplSdoAsndu.c
@@ -0,0 +1,483 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for SDO/Asnd-Protocolabstractionlayer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoAsndu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.7 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/07 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplSdoAsndu.h"
+#include "user/EplDlluCal.h"
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef EPL_SDO_MAX_CONNECTION_ASND
+#define EPL_SDO_MAX_CONNECTION_ASND 5
+#endif
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+// instance table
+typedef struct {
+ unsigned int m_auiSdoAsndConnection[EPL_SDO_MAX_CONNECTION_ASND];
+ tEplSequLayerReceiveCb m_fpSdoAsySeqCb;
+
+} tEplSdoAsndInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+static tEplSdoAsndInstance SdoAsndInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p);
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <EPL SDO-Asnd Protocolabstraction layer> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: EPL SDO-Asnd Protocolabstraction layer
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsnduInit
+//
+// Description: init first instance of the module
+//
+//
+//
+// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer
+// callback-function
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplSdoAsnduAddInstance(fpReceiveCb_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsnduAddInstance
+//
+// Description: init additional instance of the module
+//
+//
+//
+// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer
+// callback-function
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // init control structure
+ EPL_MEMSET(&SdoAsndInstance_g, 0x00, sizeof(SdoAsndInstance_g));
+
+ // save pointer to callback-function
+ if (fpReceiveCb_p != NULL) {
+ SdoAsndInstance_g.m_fpSdoAsySeqCb = fpReceiveCb_p;
+ } else {
+ Ret = kEplSdoUdpMissCb;
+ }
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ Ret = EplDlluCalRegAsndService(kEplDllAsndSdo,
+ EplSdoAsnduCb, kEplDllAsndFilterLocal);
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsnduDelInstance
+//
+// Description: del instance of the module
+// del socket and del Listen-Thread
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsnduDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ // deregister callback function from DLL
+ Ret = EplDlluCalRegAsndService(kEplDllAsndSdo,
+ NULL, kEplDllAsndFilterNone);
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsnduInitCon
+//
+// Description: init a new connect
+//
+//
+//
+// Parameters: pSdoConHandle_p = pointer for the new connection handle
+// uiTargetNodeId_p = NodeId of the target node
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl * pSdoConHandle_p,
+ unsigned int uiTargetNodeId_p)
+{
+ tEplKernel Ret;
+ unsigned int uiCount;
+ unsigned int uiFreeCon;
+ unsigned int *puiConnection;
+
+ Ret = kEplSuccessful;
+
+ if ((uiTargetNodeId_p == EPL_C_ADR_INVALID)
+ || (uiTargetNodeId_p >= EPL_C_ADR_BROADCAST)) {
+ Ret = kEplSdoAsndInvalidNodeId;
+ goto Exit;
+ }
+ // get free entry in control structure
+ uiCount = 0;
+ uiFreeCon = EPL_SDO_MAX_CONNECTION_ASND;
+ puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[0];
+ while (uiCount < EPL_SDO_MAX_CONNECTION_ASND) {
+ if (*puiConnection == uiTargetNodeId_p) { // existing connection to target node found
+ // save handle for higher layer
+ *pSdoConHandle_p = (uiCount | EPL_SDO_ASND_HANDLE);
+
+ goto Exit;
+ } else if (*puiConnection == 0) { // free entry-> save target nodeId
+ uiFreeCon = uiCount;
+ }
+ uiCount++;
+ puiConnection++;
+ }
+
+ if (uiFreeCon == EPL_SDO_MAX_CONNECTION_ASND) {
+ // no free connection
+ Ret = kEplSdoAsndNoFreeHandle;
+ } else {
+ puiConnection =
+ &SdoAsndInstance_g.m_auiSdoAsndConnection[uiFreeCon];
+ *puiConnection = uiTargetNodeId_p;
+ // save handle for higher layer
+ *pSdoConHandle_p = (uiFreeCon | EPL_SDO_ASND_HANDLE);
+
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsnduSendData
+//
+// Description: send data using exisiting connection
+//
+//
+//
+// Parameters: SdoConHandle_p = connection handle
+// pSrcData_p = pointer to data
+// dwDataSize_p = number of databyte
+// -> without asnd-header!!!
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p,
+ tEplFrame * pSrcData_p,
+ DWORD dwDataSize_p)
+{
+ tEplKernel Ret;
+ unsigned int uiArray;
+ tEplFrameInfo FrameInfo;
+
+ Ret = kEplSuccessful;
+
+ uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
+
+ if (uiArray > EPL_SDO_MAX_CONNECTION_ASND) {
+ Ret = kEplSdoAsndInvalidHandle;
+ goto Exit;
+ }
+ // fillout Asnd header
+ // own node id not needed -> filled by DLL
+
+ // set message type
+ AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, (BYTE) kEplMsgTypeAsnd); // ASnd == 0x06
+ // target node id
+ AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId,
+ (BYTE) SdoAsndInstance_g.
+ m_auiSdoAsndConnection[uiArray]);
+ // set source-nodeid (filled by DLL 0)
+ AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00);
+
+ // calc size
+ dwDataSize_p += EPL_ASND_HEADER_SIZE;
+
+ // send function of DLL
+ FrameInfo.m_uiFrameSize = dwDataSize_p;
+ FrameInfo.m_pFrame = pSrcData_p;
+ EPL_MEMSET(&FrameInfo.m_NetTime, 0x00, sizeof(tEplNetTime));
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+ Ret = EplDlluCalAsyncSend(&FrameInfo, kEplDllAsyncReqPrioGeneric);
+#endif
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsnduDelCon
+//
+// Description: delete connection from intern structure
+//
+//
+//
+// Parameters: SdoConHandle_p = connection handle
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p)
+{
+ tEplKernel Ret;
+ unsigned int uiArray;
+
+ Ret = kEplSuccessful;
+
+ uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
+ // check parameter
+ if (uiArray > EPL_SDO_MAX_CONNECTION_ASND) {
+ Ret = kEplSdoAsndInvalidHandle;
+ goto Exit;
+ }
+ // set target nodeId to 0
+ SdoAsndInstance_g.m_auiSdoAsndConnection[uiArray] = 0;
+
+ Exit:
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsnduCb
+//
+// Description: callback function for SDO ASnd frames
+//
+//
+//
+// Parameters: pFrameInfo_p = Frame with SDO payload
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsnduCb(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiCount;
+ unsigned int *puiConnection;
+ unsigned int uiNodeId;
+ unsigned int uiFreeEntry = 0xFFFF;
+ tEplSdoConHdl SdoConHdl;
+ tEplFrame *pFrame;
+
+ pFrame = pFrameInfo_p->m_pFrame;
+
+ uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
+
+ // search corresponding entry in control structure
+ uiCount = 0;
+ puiConnection = &SdoAsndInstance_g.m_auiSdoAsndConnection[0];
+ while (uiCount < EPL_SDO_MAX_CONNECTION_ASND) {
+ if (uiNodeId == *puiConnection) {
+ break;
+ } else if ((*puiConnection == 0)
+ && (uiFreeEntry == 0xFFFF)) { // free entry
+ uiFreeEntry = uiCount;
+ }
+ uiCount++;
+ puiConnection++;
+ }
+
+ if (uiCount == EPL_SDO_MAX_CONNECTION_ASND) {
+ if (uiFreeEntry != 0xFFFF) {
+ puiConnection =
+ &SdoAsndInstance_g.
+ m_auiSdoAsndConnection[uiFreeEntry];
+ *puiConnection = uiNodeId;
+ uiCount = uiFreeEntry;
+ } else {
+ EPL_DBGLVL_SDO_TRACE0
+ ("EplSdoAsnduCb(): no free handle\n");
+ goto Exit;
+ }
+ }
+// if (uiNodeId == *puiConnection)
+ { // entry found or created
+ SdoConHdl = (uiCount | EPL_SDO_ASND_HANDLE);
+
+ SdoAsndInstance_g.m_fpSdoAsySeqCb(SdoConHdl,
+ &pFrame->m_Data.m_Asnd.
+ m_Payload.m_SdoSequenceFrame,
+ (pFrameInfo_p->m_uiFrameSize -
+ 18));
+ }
+
+ Exit:
+ return Ret;
+
+}
+
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+// EOF
diff --git a/drivers/staging/epl/EplSdoAsySequ.c b/drivers/staging/epl/EplSdoAsySequ.c
new file mode 100644
index 000000000000..6b6a9975d78b
--- /dev/null
+++ b/drivers/staging/epl/EplSdoAsySequ.c
@@ -0,0 +1,2522 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for asychronous SDO Sequence Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoAsySequ.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.10 $ $Date: 2008/11/13 17:13:09 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplSdoAsySequ.h"
+
+#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) == 0) &&\
+ (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) == 0) )
+
+#error 'ERROR: At least UDP or Asnd module needed!'
+
+#endif
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define EPL_SDO_HISTORY_SIZE 5
+
+#ifndef EPL_MAX_SDO_SEQ_CON
+#define EPL_MAX_SDO_SEQ_CON 10
+#endif
+
+#define EPL_SEQ_DEFAULT_TIMEOUT 5000 // in [ms] => 5 sec
+
+#define EPL_SEQ_RETRY_COUNT 5 // => max. Timeout 30 sec
+
+#define EPL_SEQ_NUM_THRESHOLD 100 // threshold which distinguishes between old and new sequence numbers
+
+// define frame with size of Asnd-Header-, SDO Sequenze Header size, SDO Command header
+// and Ethernet-Header size
+#define EPL_SEQ_FRAME_SIZE 24
+// size of the header of the asynchronus SDO Sequence layer
+#define EPL_SEQ_HEADER_SIZE 4
+
+// buffersize for one frame in history
+#define EPL_SEQ_HISTROY_FRAME_SIZE EPL_MAX_SDO_FRAME_SIZE
+
+// mask to get scon and rcon
+#define EPL_ASY_SDO_CON_MASK 0x03
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+// events for processfunction
+typedef enum {
+ kAsySdoSeqEventNoEvent = 0x00, // no Event
+ kAsySdoSeqEventInitCon = 0x01, // init connection
+ kAsySdoSeqEventFrameRec = 0x02, // frame received
+ kAsySdoSeqEventFrameSend = 0x03, // frame to send
+ kAsySdoSeqEventTimeout = 0x04, // Timeout for connection
+ kAsySdoSeqEventCloseCon = 0x05 // higher layer close connection
+} tEplAsySdoSeqEvent;
+
+// structure for History-Buffer
+typedef struct {
+ BYTE m_bFreeEntries;
+ BYTE m_bWrite; // index of the next free buffer entry
+ BYTE m_bAck; // index of the next message which should become acknowledged
+ BYTE m_bRead; // index between m_bAck and m_bWrite to the next message for retransmission
+ BYTE m_aabHistoryFrame[EPL_SDO_HISTORY_SIZE]
+ [EPL_SEQ_HISTROY_FRAME_SIZE];
+ unsigned int m_auiFrameSize[EPL_SDO_HISTORY_SIZE];
+
+} tEplAsySdoConHistory;
+
+// state of the statemaschine
+typedef enum {
+ kEplAsySdoStateIdle = 0x00,
+ kEplAsySdoStateInit1 = 0x01,
+ kEplAsySdoStateInit2 = 0x02,
+ kEplAsySdoStateInit3 = 0x03,
+ kEplAsySdoStateConnected = 0x04,
+ kEplAsySdoStateWaitAck = 0x05
+} tEplAsySdoState;
+
+// connection control structure
+typedef struct {
+ tEplSdoConHdl m_ConHandle;
+ tEplAsySdoState m_SdoState;
+ BYTE m_bRecSeqNum; // name from view of the communication partner
+ BYTE m_bSendSeqNum; // name from view of the communication partner
+ tEplAsySdoConHistory m_SdoConHistory;
+ tEplTimerHdl m_EplTimerHdl;
+ unsigned int m_uiRetryCount; // retry counter
+ unsigned int m_uiUseCount; // one sequence layer connection may be used by
+ // multiple command layer connections
+
+} tEplAsySdoSeqCon;
+
+// instance structure
+typedef struct {
+ tEplAsySdoSeqCon m_AsySdoConnection[EPL_MAX_SDO_SEQ_CON];
+ tEplSdoComReceiveCb m_fpSdoComReceiveCb;
+ tEplSdoComConCb m_fpSdoComConCb;
+
+#if defined(WIN32) || defined(_WIN32)
+ LPCRITICAL_SECTION m_pCriticalSection;
+ CRITICAL_SECTION m_CriticalSection;
+
+ LPCRITICAL_SECTION m_pCriticalSectionReceive;
+ CRITICAL_SECTION m_CriticalSectionReceive;
+#endif
+
+} tEplAsySdoSequInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+static tEplAsySdoSequInstance AsySdoSequInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplKernel EplSdoAsySeqProcess(unsigned int uiHandle_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pData_p,
+ tEplAsySdoSeq * pRecFrame_p,
+ tEplAsySdoSeqEvent Event_p);
+
+static tEplKernel EplSdoAsySeqSendIntern(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pData_p,
+ BOOL fFrameInHistory);
+
+static tEplKernel EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pEplFrame_p);
+
+tEplKernel PUBLIC EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p,
+ tEplAsySdoSeq * pSdoSeqData_p,
+ unsigned int uiDataSize_p);
+
+static tEplKernel EplSdoAsyInitHistory(void);
+
+static tEplKernel EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ tEplFrame * pFrame_p,
+ unsigned int uiSize_p);
+
+static tEplKernel EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ BYTE bRecSeqNumber_p);
+
+static tEplKernel EplSdoAsyReadFromHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ tEplFrame ** ppFrame_p,
+ unsigned int *puiSize_p,
+ BOOL fInitRead);
+
+static unsigned int EplSdoAsyGetFreeEntriesFromHistory(tEplAsySdoSeqCon *
+ pAsySdoSeqCon_p);
+
+static tEplKernel EplSdoAsySeqSetTimer(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ unsigned long ulTimeout);
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <EPL asychronus SDO Sequence layer> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: this module contains the asynchronus SDO Sequence Layer for
+// the EPL SDO service
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqInit
+//
+// Description: init first instance
+//
+//
+//
+// Parameters: fpSdoComCb_p = callback function to inform Command layer
+// about new frames
+// fpSdoComConCb_p = callback function to inform command layer
+// about connection state
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p,
+ tEplSdoComConCb fpSdoComConCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplSdoAsySeqAddInstance(fpSdoComCb_p, fpSdoComConCb_p);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqAddInstance
+//
+// Description: init following instances
+//
+//
+//
+// Parameters: fpSdoComCb_p = callback function to inform Command layer
+// about new frames
+// fpSdoComConCb_p = callback function to inform command layer
+// about connection state
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p,
+ tEplSdoComConCb fpSdoComConCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // check functionpointer
+ if (fpSdoComCb_p == NULL) {
+ Ret = kEplSdoSeqMissCb;
+ goto Exit;
+ } else {
+ AsySdoSequInstance_g.m_fpSdoComReceiveCb = fpSdoComCb_p;
+ }
+
+ // check functionpointer
+ if (fpSdoComConCb_p == NULL) {
+ Ret = kEplSdoSeqMissCb;
+ goto Exit;
+ } else {
+ AsySdoSequInstance_g.m_fpSdoComConCb = fpSdoComConCb_p;
+ }
+
+ // set controllstructure to 0
+ EPL_MEMSET(&AsySdoSequInstance_g.m_AsySdoConnection[0], 0x00,
+ sizeof(AsySdoSequInstance_g.m_AsySdoConnection));
+
+ // init History
+ Ret = EplSdoAsyInitHistory();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#if defined(WIN32) || defined(_WIN32)
+ // create critical section for process function
+ AsySdoSequInstance_g.m_pCriticalSection =
+ &AsySdoSequInstance_g.m_CriticalSection;
+ InitializeCriticalSection(AsySdoSequInstance_g.m_pCriticalSection);
+
+ // init critical section for receive cb function
+ AsySdoSequInstance_g.m_pCriticalSectionReceive =
+ &AsySdoSequInstance_g.m_CriticalSectionReceive;
+ InitializeCriticalSection(AsySdoSequInstance_g.
+ m_pCriticalSectionReceive);
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ // init lower layer
+ Ret = EplSdoUdpuAddInstance(EplSdoAsyReceiveCb);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+ // init lower layer
+ Ret = EplSdoAsnduAddInstance(EplSdoAsyReceiveCb);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqDelInstance
+//
+// Description: delete instances
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqDelInstance()
+{
+ tEplKernel Ret;
+ unsigned int uiCount;
+ tEplAsySdoSeqCon *pAsySdoSeqCon;
+
+ Ret = kEplSuccessful;
+
+ // delete timer of open connections
+ uiCount = 0;
+ pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[0];
+ while (uiCount < EPL_MAX_SDO_SEQ_CON) {
+ if (pAsySdoSeqCon->m_ConHandle != 0) {
+ EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl);
+ }
+ uiCount++;
+ pAsySdoSeqCon++;
+ }
+
+#if defined(WIN32) || defined(_WIN32)
+ // delete critical section for process function
+ DeleteCriticalSection(AsySdoSequInstance_g.m_pCriticalSection);
+#endif
+
+ // set instance-table to 0
+ EPL_MEMSET(&AsySdoSequInstance_g, 0x00, sizeof(AsySdoSequInstance_g));
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ // delete lower layer
+ Ret = EplSdoUdpuDelInstance();
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+ // delete lower layer
+ Ret = EplSdoAsnduDelInstance();
+#endif
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqInitCon
+//
+// Description: start initialization of a sequence layer connection.
+// It tries to reuse an existing connection to the same node.
+//
+//
+// Parameters: pSdoSeqConHdl_p = pointer to the variable for the connection handle
+// uiNodeId_p = Node Id of the target
+// SdoType = Type of the SDO connection
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqInitCon(tEplSdoSeqConHdl * pSdoSeqConHdl_p,
+ unsigned int uiNodeId_p,
+ tEplSdoType SdoType)
+{
+ tEplKernel Ret;
+ unsigned int uiCount;
+ unsigned int uiFreeCon;
+ tEplSdoConHdl ConHandle;
+ tEplAsySdoSeqCon *pAsySdoSeqCon;
+ Ret = kEplSuccessful;
+
+ // check SdoType
+ // call init function of the protcol abstraction layer
+ // which tries to find an existing connection to the same node
+ switch (SdoType) {
+ // SDO over UDP
+ case kEplSdoTypeUdp:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ Ret = EplSdoUdpuInitCon(&ConHandle, uiNodeId_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#else
+ Ret = kEplSdoSeqUnsupportedProt;
+#endif
+ break;
+ }
+
+ // SDO over Asnd
+ case kEplSdoTypeAsnd:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+ Ret = EplSdoAsnduInitCon(&ConHandle, uiNodeId_p);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#else
+ Ret = kEplSdoSeqUnsupportedProt;
+#endif
+ break;
+ }
+
+ // unsupported protocols
+ // -> auto should be replaced by command layer
+ case kEplSdoTypeAuto:
+ case kEplSdoTypePdo:
+ default:
+ {
+ Ret = kEplSdoSeqUnsupportedProt;
+ goto Exit;
+ }
+
+ } // end of switch(SdoType)
+
+ // find existing connection to the same node or find empty entry for connection
+ uiCount = 0;
+ uiFreeCon = EPL_MAX_SDO_SEQ_CON;
+ pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[0];
+
+ while (uiCount < EPL_MAX_SDO_SEQ_CON) {
+ if (pAsySdoSeqCon->m_ConHandle == ConHandle) { // existing connection found
+ break;
+ }
+ if (pAsySdoSeqCon->m_ConHandle == 0) {
+ uiFreeCon = uiCount;
+ }
+ uiCount++;
+ pAsySdoSeqCon++;
+ }
+
+ if (uiCount == EPL_MAX_SDO_SEQ_CON) {
+ if (uiFreeCon == EPL_MAX_SDO_SEQ_CON) { // no free entry found
+ switch (SdoType) {
+ // SDO over UDP
+ case kEplSdoTypeUdp:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ Ret = EplSdoUdpuDelCon(ConHandle);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+ break;
+ }
+
+ // SDO over Asnd
+ case kEplSdoTypeAsnd:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+ Ret = EplSdoAsnduDelCon(ConHandle);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+ break;
+ }
+
+ // unsupported protocols
+ // -> auto should be replaced by command layer
+ case kEplSdoTypeAuto:
+ case kEplSdoTypePdo:
+ default:
+ {
+ Ret = kEplSdoSeqUnsupportedProt;
+ goto Exit;
+ }
+
+ } // end of switch(SdoType)
+
+ Ret = kEplSdoSeqNoFreeHandle;
+ goto Exit;
+ } else { // free entry found
+ pAsySdoSeqCon =
+ &AsySdoSequInstance_g.m_AsySdoConnection[uiFreeCon];
+ pAsySdoSeqCon->m_ConHandle = ConHandle;
+ uiCount = uiFreeCon;
+ }
+ }
+ // set handle
+ *pSdoSeqConHdl_p = (uiCount | EPL_SDO_ASY_HANDLE);
+
+ // increment use counter
+ pAsySdoSeqCon->m_uiUseCount++;
+
+ // call intern process function
+ Ret = EplSdoAsySeqProcess(uiCount,
+ 0, NULL, NULL, kAsySdoSeqEventInitCon);
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqSendData
+//
+// Description: send sata unsing a established connection
+//
+//
+//
+// Parameters: pSdoSeqConHdl_p = connection handle
+// uiDataSize_p = Size of Frame to send
+// -> wihtout SDO sequence layer header, Asnd header
+// and ethernetnet
+// ==> SDO Sequence layer payload
+// SdoType = Type of the SDO connection
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pabData_p)
+{
+ tEplKernel Ret;
+ unsigned int uiHandle;
+
+ uiHandle = (SdoSeqConHdl_p & ~EPL_SDO_SEQ_HANDLE_MASK);
+
+ // check if connection ready
+ if (AsySdoSequInstance_g.m_AsySdoConnection[uiHandle].m_SdoState ==
+ kEplAsySdoStateIdle) {
+ // no connection with this handle
+ Ret = kEplSdoSeqInvalidHdl;
+ goto Exit;
+ } else if (AsySdoSequInstance_g.m_AsySdoConnection[uiHandle].
+ m_SdoState != kEplAsySdoStateConnected) {
+ Ret = kEplSdoSeqConnectionBusy;
+ goto Exit;
+ }
+
+ Ret = EplSdoAsySeqProcess(uiHandle,
+ uiDataSize_p,
+ pabData_p, NULL, kAsySdoSeqEventFrameSend);
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqProcessEvent
+//
+// Description: function processes extern events
+// -> later needed for timeout controll with timer-module
+//
+//
+//
+// Parameters: pEvent_p = pointer to event
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqProcessEvent(tEplEvent * pEvent_p)
+{
+ tEplKernel Ret;
+ tEplTimerEventArg *pTimerEventArg;
+ tEplAsySdoSeqCon *pAsySdoSeqCon;
+ tEplTimerHdl EplTimerHdl;
+ unsigned int uiCount;
+
+ Ret = kEplSuccessful;
+ // check parameter
+ if (pEvent_p == NULL) {
+ Ret = kEplSdoSeqInvalidEvent;
+ goto Exit;
+ }
+
+ if (pEvent_p->m_EventType != kEplEventTypeTimer) {
+ Ret = kEplSdoSeqInvalidEvent;
+ goto Exit;
+ }
+ // get timerhdl
+ pTimerEventArg = (tEplTimerEventArg *) pEvent_p->m_pArg;
+ EplTimerHdl = pTimerEventArg->m_TimerHdl;
+
+ // get pointer to intern control structure of connection
+ if (pTimerEventArg->m_ulArg == 0) {
+ goto Exit;
+ }
+ pAsySdoSeqCon = (tEplAsySdoSeqCon *) pTimerEventArg->m_ulArg;
+
+ // check if time is current
+ if (EplTimerHdl != pAsySdoSeqCon->m_EplTimerHdl) {
+ // delete timer
+ EplTimeruDeleteTimer(&EplTimerHdl);
+ goto Exit;
+ }
+ // delete timer
+ EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl);
+
+ // get indexnumber of control structure
+ uiCount = 0;
+ while ((&AsySdoSequInstance_g.m_AsySdoConnection[uiCount]) !=
+ pAsySdoSeqCon) {
+ uiCount++;
+ if (uiCount > EPL_MAX_SDO_SEQ_CON) {
+ goto Exit;
+ }
+ }
+
+ // process event and call processfunction if needed
+ Ret = EplSdoAsySeqProcess(uiCount,
+ 0, NULL, NULL, kAsySdoSeqEventTimeout);
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqDelCon
+//
+// Description: del and close one connection
+//
+//
+//
+// Parameters: SdoSeqConHdl_p = handle of connection
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiHandle;
+ tEplAsySdoSeqCon *pAsySdoSeqCon;
+
+ uiHandle = (SdoSeqConHdl_p & ~EPL_SDO_SEQ_HANDLE_MASK);
+
+ // check if handle invalid
+ if (uiHandle >= EPL_MAX_SDO_SEQ_CON) {
+ Ret = kEplSdoSeqInvalidHdl;
+ goto Exit;
+ }
+ // get pointer to connection
+ pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiHandle];
+
+ // decrement use counter
+ pAsySdoSeqCon->m_uiUseCount--;
+
+ if (pAsySdoSeqCon->m_uiUseCount == 0) {
+ // process close in processfunction
+ Ret = EplSdoAsySeqProcess(uiHandle,
+ 0,
+ NULL, NULL, kAsySdoSeqEventCloseCon);
+
+ //check protocol
+ if ((pAsySdoSeqCon->m_ConHandle & EPL_SDO_ASY_HANDLE_MASK) ==
+ EPL_SDO_UDP_HANDLE) {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ // call close function of lower layer
+ EplSdoUdpuDelCon(pAsySdoSeqCon->m_ConHandle);
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ } else {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+ // call close function of lower layer
+ EplSdoAsnduDelCon(pAsySdoSeqCon->m_ConHandle);
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+ }
+
+ // delete timer
+ EplTimeruDeleteTimer(&pAsySdoSeqCon->m_EplTimerHdl);
+
+ // clean controllstructure
+ EPL_MEMSET(pAsySdoSeqCon, 0x00, sizeof(tEplAsySdoSeqCon));
+ pAsySdoSeqCon->m_SdoConHistory.m_bFreeEntries =
+ EPL_SDO_HISTORY_SIZE;
+ }
+
+ Exit:
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplEplSdoAsySeqProcess
+//
+// Description: intern function to process the asynchronus SDO Sequence Layer
+// state maschine
+//
+//
+//
+// Parameters: uiHandle_p = index of the control structure of the connection
+// uiDataSize_p = size of data frame to process (can be 0)
+// -> without size of sequence header and Asnd header!!!
+//
+// pData_p = pointer to frame to send (can be NULL)
+// pRecFrame_p = pointer to received frame (can be NULL)
+// Event_p = Event to process
+//
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsySeqProcess(unsigned int uiHandle_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pData_p,
+ tEplAsySdoSeq * pRecFrame_p,
+ tEplAsySdoSeqEvent Event_p)
+{
+ tEplKernel Ret;
+ unsigned int uiFrameSize;
+ tEplFrame *pEplFrame;
+ tEplAsySdoSeqCon *pAsySdoSeqCon;
+ tEplSdoSeqConHdl SdoSeqConHdl;
+ unsigned int uiFreeEntries;
+
+#if defined(WIN32) || defined(_WIN32)
+ // enter critical section for process function
+ EnterCriticalSection(AsySdoSequInstance_g.m_pCriticalSection);
+#endif
+
+ Ret = kEplSuccessful;
+
+ // get handle for hinger layer
+ SdoSeqConHdl = uiHandle_p | EPL_SDO_ASY_HANDLE;
+
+ // check if handle invalid
+ if ((SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) ==
+ EPL_SDO_SEQ_INVALID_HDL) {
+ Ret = kEplSdoSeqInvalidHdl;
+ goto Exit;
+ }
+ // get pointer to connection
+ pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiHandle_p];
+
+ // check size
+ if ((pData_p == NULL) && (pRecFrame_p == NULL) && (uiDataSize_p != 0)) {
+ Ret = kEplSdoSeqInvalidFrame;
+ goto Exit;
+ }
+ // check state
+ switch (pAsySdoSeqCon->m_SdoState) {
+ // idle state
+ case kEplAsySdoStateIdle:
+ {
+ // check event
+ switch (Event_p) {
+ // new connection
+ // -> send init frame and change to
+ // kEplAsySdoStateInit1
+ case kAsySdoSeqEventInitCon:
+ {
+ // set sending scon to 1
+ pAsySdoSeqCon->m_bRecSeqNum = 0x01;
+ // set set send rcon to 0
+ pAsySdoSeqCon->m_bSendSeqNum = 0x00;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL, FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // change state
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateInit1;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer(pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+
+ break;
+ }
+
+ // init con from extern
+ // check rcon and scon
+ // -> send answer
+ case kAsySdoSeqEventFrameRec:
+ {
+/*
+ PRINTF3("%s scon=%u rcon=%u\n",
+ __func__,
+ pRecFrame_p->m_le_bSendSeqNumCon,
+ pRecFrame_p->m_le_bRecSeqNumCon);
+*/
+ // check if scon == 1 and rcon == 0
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) == 0x00)
+ &&
+ ((pRecFrame_p->
+ m_le_bSendSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) == 0x01)) {
+ // save sequence numbers
+ pAsySdoSeqCon->m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+ // create answer and send answer
+ // set rcon to 1 (in send direction own scon)
+ pAsySdoSeqCon->m_bRecSeqNum++;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // change state to kEplAsySdoStateInit2
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateInit2;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+ } else { // error -> close
+ // delete timer
+ EplTimeruDeleteTimer
+ (&pAsySdoSeqCon->
+ m_EplTimerHdl);
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) !=
+ 0x00)
+ || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
+ // save sequence numbers
+ pAsySdoSeqCon->
+ m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->
+ m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+ // set rcon and scon to 0
+ pAsySdoSeqCon->
+ m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->
+ m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0,
+ NULL, FALSE);
+ }
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateInitError);
+ }
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(Event_p)
+ break;
+ }
+
+ // init connection step 1
+ // wait for frame with scon = 1
+ // and rcon = 1
+ case kEplAsySdoStateInit1:
+ {
+// PRINTF0("EplSdoAsySequ: StateInit1\n");
+
+ // check event
+ switch (Event_p) {
+ // frame received
+ case kAsySdoSeqEventFrameRec:
+ {
+ // check scon == 1 and rcon == 1
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) == 0x01)
+ && ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x01)) { // create answer own scon = 2
+ // save sequence numbers
+ pAsySdoSeqCon->m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+
+ pAsySdoSeqCon->m_bRecSeqNum++;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // change state to kEplAsySdoStateInit3
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateInit3;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+
+ }
+ // check if scon == 1 and rcon == 0, i.e. other side wants me to be server
+ else if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) ==
+ 0x00)
+ &&
+ ((pRecFrame_p->
+ m_le_bSendSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) ==
+ 0x01)) {
+ // save sequence numbers
+ pAsySdoSeqCon->m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+ // create answer and send answer
+ // set rcon to 1 (in send direction own scon)
+ pAsySdoSeqCon->m_bRecSeqNum++;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // change state to kEplAsySdoStateInit2
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateInit2;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+ } else { // error -> Close
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // delete timer
+ EplTimeruDeleteTimer
+ (&pAsySdoSeqCon->
+ m_EplTimerHdl);
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) !=
+ 0x00)
+ || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
+ // save sequence numbers
+ pAsySdoSeqCon->
+ m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->
+ m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+
+ // set rcon and scon to 0
+ pAsySdoSeqCon->
+ m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->
+ m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0,
+ NULL, FALSE);
+ }
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateInitError);
+ }
+ break;
+ }
+
+ // timeout
+ case kAsySdoSeqEventTimeout:
+ { // error -> Close
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+
+ // set rcon and scon to 0
+ pAsySdoSeqCon->m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern(pAsySdoSeqCon,
+ 0, NULL, FALSE);
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb(SdoSeqConHdl,
+ kAsySdoConStateInitError);
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(Event_p)
+ break;
+ }
+
+ // init connection step 2
+ case kEplAsySdoStateInit2:
+ {
+// PRINTF0("EplSdoAsySequ: StateInit2\n");
+
+ // check event
+ switch (Event_p) {
+ // frame received
+ case kAsySdoSeqEventFrameRec:
+ {
+ // check scon == 2 and rcon == 1
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) == 0x01)
+ && ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x02)) { // create answer own rcon = 2
+ // save sequence numbers
+ pAsySdoSeqCon->m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+
+ pAsySdoSeqCon->m_bRecSeqNum++;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // change state to kEplAsySdoStateConnected
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateConnected;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateConnected);
+
+ }
+ // check scon == 1 and rcon == 1, i.e. other side wants me to initiate the connection
+ else if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) ==
+ 0x01)
+ &&
+ ((pRecFrame_p->
+ m_le_bSendSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) ==
+ 0x01)) {
+ // save sequence numbers
+ pAsySdoSeqCon->m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+ // create answer and send answer
+ // set rcon to 1 (in send direction own scon)
+ pAsySdoSeqCon->m_bRecSeqNum++;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+ // change state to kEplAsySdoStateInit3
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateInit3;
+
+ } else { // error -> Close
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // delete timer
+ EplTimeruDeleteTimer
+ (&pAsySdoSeqCon->
+ m_EplTimerHdl);
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) !=
+ 0x00)
+ || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
+ // save sequence numbers
+ pAsySdoSeqCon->
+ m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->
+ m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+ // set rcon and scon to 0
+ pAsySdoSeqCon->
+ m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->
+ m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0,
+ NULL, FALSE);
+ }
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateInitError);
+ }
+ break;
+ }
+
+ // timeout
+ case kAsySdoSeqEventTimeout:
+ { // error -> Close
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // set rcon and scon to 0
+ pAsySdoSeqCon->m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern(pAsySdoSeqCon,
+ 0, NULL, FALSE);
+
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb(SdoSeqConHdl,
+ kAsySdoConStateInitError);
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(Event_p)
+ break;
+ }
+
+ // init connection step 3
+ case kEplAsySdoStateInit3:
+ {
+ // check event
+ switch (Event_p) {
+ // frame received
+ case kAsySdoSeqEventFrameRec:
+ {
+ // check scon == 2 and rcon == 2
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) == 0x02)
+ &&
+ ((pRecFrame_p->
+ m_le_bSendSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) == 0x02)) {
+ // save sequence numbers
+ pAsySdoSeqCon->m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+ // change state to kEplAsySdoStateConnected
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateConnected;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateConnected);
+
+ }
+ // check scon == 2 and rcon == 1
+ else if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) ==
+ 0x01)
+ && ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 0x02)) { // create answer own rcon = 2
+ // save sequence numbers
+ pAsySdoSeqCon->m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+
+ pAsySdoSeqCon->m_bRecSeqNum++;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // change state to kEplAsySdoStateConnected
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateConnected;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateConnected);
+
+ } else { // error -> Close
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // delete timer
+ EplTimeruDeleteTimer
+ (&pAsySdoSeqCon->
+ m_EplTimerHdl);
+ if (((pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) !=
+ 0x00)
+ || ((pRecFrame_p->m_le_bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
+ // save sequence numbers
+ pAsySdoSeqCon->
+ m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->
+ m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+ // set rcon and scon to 0
+ pAsySdoSeqCon->
+ m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->
+ m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0,
+ NULL, FALSE);
+ }
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateInitError);
+ }
+ break;
+ }
+
+ // timeout
+ case kAsySdoSeqEventTimeout:
+ { // error -> Close
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // set rcon and scon to 0
+ pAsySdoSeqCon->m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern(pAsySdoSeqCon,
+ 0, NULL, FALSE);
+
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb(SdoSeqConHdl,
+ kAsySdoConStateInitError);
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(Event_p)
+ break;
+ }
+
+ // connection established
+ case kEplAsySdoStateConnected:
+ {
+ // check event
+ switch (Event_p) {
+
+ // frame to send
+ case kAsySdoSeqEventFrameSend:
+ {
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer(pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+ // check if data frame or ack
+ if (pData_p == NULL) { // send ack
+ // inc scon
+ //pAsySdoSeqCon->m_bRecSeqNum += 4;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ } else { // send dataframe
+ // increment send sequence number
+ pAsySdoSeqCon->m_bRecSeqNum +=
+ 4;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon,
+ uiDataSize_p, pData_p,
+ TRUE);
+ if (Ret == kEplSdoSeqRequestAckNeeded) { // request ack
+ // change state to wait ack
+ pAsySdoSeqCon->
+ m_SdoState =
+ kEplAsySdoStateWaitAck;
+ // set Ret to kEplSuccessful, because no error
+ // for higher layer
+ Ret = kEplSuccessful;
+
+ } else if (Ret !=
+ kEplSuccessful) {
+ goto Exit;
+ } else {
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateFrameSended);
+ }
+ }
+ break;
+ } // end of case kAsySdoSeqEventFrameSend
+
+ // frame received
+ case kAsySdoSeqEventFrameRec:
+ {
+ BYTE bSendSeqNumCon =
+ AmiGetByteFromLe(&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer(pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+ // check scon
+ switch (bSendSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) {
+ // close from other node
+ case 0:
+ case 1:
+ {
+ // return to idle
+ pAsySdoSeqCon->
+ m_SdoState =
+ kEplAsySdoStateIdle;
+ // delete timer
+ EplTimeruDeleteTimer
+ (&pAsySdoSeqCon->
+ m_EplTimerHdl);
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateConClosed);
+
+ break;
+ }
+
+ // Request Ack or Error Ack
+ // possible contain data
+ case 3:
+ // normal frame
+ case 2:
+ {
+ if ((AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon)
+ &
+ EPL_ASY_SDO_CON_MASK)
+ == 3) {
+// PRINTF0("EplSdoAsySequ: error response received\n");
+
+ // error response (retransmission request)
+ // resend frames from history
+
+ // read frame from history
+ Ret =
+ EplSdoAsyReadFromHistory
+ (pAsySdoSeqCon,
+ &pEplFrame,
+ &uiFrameSize,
+ TRUE);
+ if (Ret !=
+ kEplSuccessful)
+ {
+ goto Exit;
+ }
+
+ while ((pEplFrame != NULL)
+ &&
+ (uiFrameSize
+ != 0)) {
+ // send frame
+ Ret =
+ EplSdoAsySeqSendLowerLayer
+ (pAsySdoSeqCon,
+ uiFrameSize,
+ pEplFrame);
+ if (Ret
+ !=
+ kEplSuccessful)
+ {
+ goto Exit;
+ }
+ // read next frame from history
+ Ret =
+ EplSdoAsyReadFromHistory
+ (pAsySdoSeqCon,
+ &pEplFrame,
+ &uiFrameSize,
+ FALSE);
+ if (Ret
+ !=
+ kEplSuccessful)
+ {
+ goto Exit;
+ }
+ } // end of while((pabFrame != NULL)
+ } // end of if (error response)
+
+ if (((pAsySdoSeqCon->m_bSendSeqNum + 4) & EPL_SEQ_NUM_MASK) == (bSendSeqNumCon & EPL_SEQ_NUM_MASK)) { // next frame of sequence received
+ // save send sequence number (without ack request)
+ pAsySdoSeqCon->
+ m_bSendSeqNum
+ =
+ bSendSeqNumCon
+ & ~0x01;
+
+ // check if ack or data-frame
+ //ignore ack -> already processed
+ if (uiDataSize_p
+ >
+ EPL_SEQ_HEADER_SIZE)
+ {
+ AsySdoSequInstance_g.
+ m_fpSdoComReceiveCb
+ (SdoSeqConHdl,
+ ((tEplAsySdoCom *) & pRecFrame_p->m_le_abSdoSeqPayload), (uiDataSize_p - EPL_SEQ_HEADER_SIZE));
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateFrameSended);
+
+ } else {
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateAckReceived);
+ }
+ } else if (((bSendSeqNumCon - pAsySdoSeqCon->m_bSendSeqNum - 4) & EPL_SEQ_NUM_MASK) < EPL_SEQ_NUM_THRESHOLD) { // frame of sequence was lost,
+ // because difference of received and old value
+ // is less then halve of the values range.
+
+ // send error frame with own rcon = 3
+ pAsySdoSeqCon->
+ m_bSendSeqNum
+ |= 0x03;
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon,
+ 0, NULL,
+ FALSE);
+ // restore send sequence number
+ pAsySdoSeqCon->
+ m_bSendSeqNum
+ =
+ (pAsySdoSeqCon->
+ m_bSendSeqNum
+ &
+ EPL_SEQ_NUM_MASK)
+ | 0x02;
+ if (Ret !=
+ kEplSuccessful)
+ {
+ goto Exit;
+ }
+ // break here, because a requested acknowledge
+ // was sent implicitly above
+ break;
+ }
+ // else, ignore repeated frame
+
+ if ((bSendSeqNumCon & EPL_ASY_SDO_CON_MASK) == 3) { // ack request received
+
+ // create ack with own scon = 2
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon,
+ 0, NULL,
+ FALSE);
+ if (Ret !=
+ kEplSuccessful)
+ {
+ goto Exit;
+ }
+ }
+
+ break;
+ }
+
+ } // switch(pAsySdoSeqCon->m_bSendSeqNum & EPL_ASY_SDO_CON_MASK)
+ break;
+ } // end of case kAsySdoSeqEventFrameRec:
+
+ //close event from higher layer
+ case kAsySdoSeqEventCloseCon:
+ {
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // set rcon and scon to 0
+ pAsySdoSeqCon->m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern(pAsySdoSeqCon,
+ 0, NULL, FALSE);
+
+ // delete timer
+ EplTimeruDeleteTimer(&pAsySdoSeqCon->
+ m_EplTimerHdl);
+ // call Command Layer Cb is not necessary, because the event came from there
+// AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl,
+// kAsySdoConStateInitError);
+ break;
+ }
+
+ // timeout
+ case kAsySdoSeqEventTimeout:
+ {
+
+ uiFreeEntries =
+ EplSdoAsyGetFreeEntriesFromHistory
+ (pAsySdoSeqCon);
+ if ((uiFreeEntries <
+ EPL_SDO_HISTORY_SIZE)
+ && (pAsySdoSeqCon->m_uiRetryCount < EPL_SEQ_RETRY_COUNT)) { // unacknowlegded frames in history
+ // and retry counter not exceeded
+
+ // resend data with acknowledge request
+
+ // increment retry counter
+ pAsySdoSeqCon->m_uiRetryCount++;
+
+ // set timer
+ Ret =
+ EplSdoAsySeqSetTimer
+ (pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+
+ // read first frame from history
+ Ret =
+ EplSdoAsyReadFromHistory
+ (pAsySdoSeqCon, &pEplFrame,
+ &uiFrameSize, TRUE);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ if ((pEplFrame != NULL)
+ && (uiFrameSize != 0)) {
+
+ // set ack request in scon
+ AmiSetByteToLe
+ (&pEplFrame->m_Data.
+ m_Asnd.m_Payload.
+ m_SdoSequenceFrame.
+ m_le_bSendSeqNumCon,
+ AmiGetByteFromLe
+ (&pEplFrame->
+ m_Data.m_Asnd.
+ m_Payload.
+ m_SdoSequenceFrame.
+ m_le_bSendSeqNumCon)
+ | 0x03);
+
+ // send frame
+ Ret =
+ EplSdoAsySeqSendLowerLayer
+ (pAsySdoSeqCon,
+ uiFrameSize,
+ pEplFrame);
+ if (Ret !=
+ kEplSuccessful) {
+ goto Exit;
+ }
+
+ }
+ } else {
+ // timeout, because of no traffic -> Close
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // set rcon and scon to 0
+ pAsySdoSeqCon->m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->m_bRecSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon, 0, NULL,
+ FALSE);
+
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateTimeout);
+ }
+
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(Event_p)
+ break;
+ }
+
+ // wait for Acknowledge (history buffer full)
+ case kEplAsySdoStateWaitAck:
+ {
+ PRINTF0("EplSdoAsySequ: StateWaitAck\n");
+
+ // set timer
+ Ret = EplSdoAsySeqSetTimer(pAsySdoSeqCon,
+ EPL_SEQ_DEFAULT_TIMEOUT);
+
+ //TODO: retry of acknowledge
+ if (Event_p == kAsySdoSeqEventFrameRec) {
+ // check rcon
+ switch (pRecFrame_p->
+ m_le_bRecSeqNumCon &
+ EPL_ASY_SDO_CON_MASK) {
+ // close-frome other node
+ case 0:
+ {
+ // return to idle
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateIdle;
+ // delete timer
+ EplTimeruDeleteTimer
+ (&pAsySdoSeqCon->
+ m_EplTimerHdl);
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateConClosed);
+
+ break;
+ }
+
+ // normal frame
+ case 2:
+ {
+ // should be ack
+ // -> change to state kEplAsySdoStateConnected
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateConnected;
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateAckReceived);
+ // send data to higher layer if needed
+ if (uiDataSize_p >
+ EPL_SEQ_HEADER_SIZE) {
+ AsySdoSequInstance_g.
+ m_fpSdoComReceiveCb
+ (SdoSeqConHdl,
+ ((tEplAsySdoCom *)
+ & pRecFrame_p->
+ m_le_abSdoSeqPayload),
+ (uiDataSize_p -
+ EPL_SEQ_HEADER_SIZE));
+ }
+ break;
+ }
+
+ // Request Ack or Error Ack
+ case 3:
+ {
+ // -> change to state kEplAsySdoStateConnected
+ pAsySdoSeqCon->m_SdoState =
+ kEplAsySdoStateConnected;
+
+ if (pRecFrame_p->m_le_bRecSeqNumCon == pAsySdoSeqCon->m_bRecSeqNum) { // ack request
+ // -> send ack
+ // save sequence numbers
+ pAsySdoSeqCon->
+ m_bRecSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bRecSeqNumCon);
+ pAsySdoSeqCon->
+ m_bSendSeqNum =
+ AmiGetByteFromLe
+ (&pRecFrame_p->
+ m_le_bSendSeqNumCon);
+
+ // create answer own rcon = 2
+ pAsySdoSeqCon->
+ m_bRecSeqNum--;
+
+ // check if ack or data-frame
+ if (uiDataSize_p >
+ EPL_SEQ_HEADER_SIZE)
+ {
+ AsySdoSequInstance_g.
+ m_fpSdoComReceiveCb
+ (SdoSeqConHdl,
+ ((tEplAsySdoCom *) & pRecFrame_p->m_le_abSdoSeqPayload), (uiDataSize_p - EPL_SEQ_HEADER_SIZE));
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb
+ (SdoSeqConHdl,
+ kAsySdoConStateFrameSended);
+
+ } else {
+ Ret =
+ EplSdoAsySeqSendIntern
+ (pAsySdoSeqCon,
+ 0, NULL,
+ FALSE);
+ if (Ret !=
+ kEplSuccessful)
+ {
+ goto Exit;
+ }
+ }
+
+ } else {
+ // error ack
+ // resend frames from history
+
+ // read frame from history
+ Ret =
+ EplSdoAsyReadFromHistory
+ (pAsySdoSeqCon,
+ &pEplFrame,
+ &uiFrameSize,
+ TRUE);
+ while ((pEplFrame !=
+ NULL)
+ && (uiFrameSize
+ != 0)) {
+ // send frame
+ Ret =
+ EplSdoAsySeqSendLowerLayer
+ (pAsySdoSeqCon,
+ uiFrameSize,
+ pEplFrame);
+ if (Ret !=
+ kEplSuccessful)
+ {
+ goto Exit;
+ }
+ // read next frame
+
+ // read frame from history
+ Ret =
+ EplSdoAsyReadFromHistory
+ (pAsySdoSeqCon,
+ &pEplFrame,
+ &uiFrameSize,
+ FALSE);
+ } // end of while((pabFrame != NULL)
+ }
+ break;
+ }
+ } // end of switch(pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK)
+
+ } else if (Event_p == kAsySdoSeqEventTimeout) { // error -> Close
+ pAsySdoSeqCon->m_SdoState = kEplAsySdoStateIdle;
+ // set rcon and scon to 0
+ pAsySdoSeqCon->m_bSendSeqNum &=
+ EPL_SEQ_NUM_MASK;
+ pAsySdoSeqCon->m_bRecSeqNum &= EPL_SEQ_NUM_MASK;
+ // send frame
+ EplSdoAsySeqSendIntern(pAsySdoSeqCon,
+ 0, NULL, FALSE);
+
+ // call Command Layer Cb
+ AsySdoSequInstance_g.
+ m_fpSdoComConCb(SdoSeqConHdl,
+ kAsySdoConStateTimeout);
+ }
+
+ break;
+ }
+
+ // unknown state
+ default:
+ {
+ EPL_DBGLVL_SDO_TRACE0
+ ("Error: Unknown State in EplSdoAsySeqProcess\n");
+
+ }
+ } // end of switch(pAsySdoSeqCon->m_SdoState)
+
+ Exit:
+
+#if defined(WIN32) || defined(_WIN32)
+ // leave critical section for process function
+ LeaveCriticalSection(AsySdoSequInstance_g.m_pCriticalSection);
+#endif
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqSendIntern
+//
+// Description: intern function to create and send a frame
+// -> if uiDataSize_p == 0 create a frame with infos from
+// pAsySdoSeqCon_p
+//
+//
+//
+// Parameters: pAsySdoSeqCon_p = pointer to control structure of the connection
+// uiDataSize_p = size of data frame to process (can be 0)
+// -> without size of sequence header and Asnd header!!!
+// pData_p = pointer to frame to process (can be NULL)
+// fFrameInHistory = if TRUE frame is saved to history else not
+//
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsySeqSendIntern(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pData_p,
+ BOOL fFrameInHistory_p)
+{
+ tEplKernel Ret;
+ BYTE abFrame[EPL_SEQ_FRAME_SIZE];
+ tEplFrame *pEplFrame;
+ unsigned int uiFreeEntries;
+
+ if (pData_p == NULL) { // set pointer to own frame
+ EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
+ pEplFrame = (tEplFrame *) & abFrame[0];
+ } else { // set pointer to frame from calling function
+ pEplFrame = pData_p;
+ }
+
+ if (fFrameInHistory_p != FALSE) {
+ // check if only one free entry in history buffer
+ uiFreeEntries =
+ EplSdoAsyGetFreeEntriesFromHistory(pAsySdoSeqCon_p);
+ if (uiFreeEntries == 1) { // request an acknowledge in dataframe
+ // own scon = 3
+ pAsySdoSeqCon_p->m_bRecSeqNum |= 0x03;
+ }
+ }
+ // fillin header informations
+ // set service id sdo
+ AmiSetByteToLe(&pEplFrame->m_Data.m_Asnd.m_le_bServiceId, 0x05);
+ AmiSetByteToLe(&pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
+ m_le_abReserved, 0x00);
+ // set receive sequence number and rcon
+ AmiSetByteToLe(&pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
+ m_le_bRecSeqNumCon, pAsySdoSeqCon_p->m_bSendSeqNum);
+ // set send sequence number and scon
+ AmiSetByteToLe(&pEplFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
+ m_le_bSendSeqNumCon, pAsySdoSeqCon_p->m_bRecSeqNum);
+
+ // add size
+ uiDataSize_p += EPL_SEQ_HEADER_SIZE;
+
+ // forward frame to appropriate lower layer
+ Ret = EplSdoAsySeqSendLowerLayer(pAsySdoSeqCon_p, uiDataSize_p, pEplFrame); // pointer to frame
+
+ // check if all allright
+ if ((Ret == kEplSuccessful)
+ && (fFrameInHistory_p != FALSE)) {
+ // set own scon to 2 if needed
+ if ((pAsySdoSeqCon_p->m_bRecSeqNum & 0x03) == 0x03) {
+ pAsySdoSeqCon_p->m_bRecSeqNum--;
+ }
+ // save frame to history
+ Ret = EplSdoAsyAddFrameToHistory(pAsySdoSeqCon_p,
+ pEplFrame, uiDataSize_p);
+ if (Ret == kEplSdoSeqNoFreeHistory) { // request Ack needed
+ Ret = kEplSdoSeqRequestAckNeeded;
+ }
+
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqSendLowerLayer
+//
+// Description: intern function to send a previously created frame to lower layer
+//
+// Parameters: pAsySdoSeqCon_p = pointer to control structure of the connection
+// uiDataSize_p = size of data frame to process (can be 0)
+// -> without size of Asnd header!!!
+// pData_p = pointer to frame to process (can be NULL)
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pEplFrame_p)
+{
+ tEplKernel Ret;
+
+ // call send-function
+ // check handle for UDP or Asnd
+ if ((pAsySdoSeqCon_p->m_ConHandle & EPL_SDO_ASY_HANDLE_MASK) == EPL_SDO_UDP_HANDLE) { // send over UDP
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+ Ret = EplSdoUdpuSendData(pAsySdoSeqCon_p->m_ConHandle, pEplFrame_p, // pointer to frame
+ uiDataSize_p);
+#else
+ Ret = kEplSdoSeqUnsupportedProt;
+#endif
+
+ } else if ((pAsySdoSeqCon_p->m_ConHandle & EPL_SDO_ASY_HANDLE_MASK) == EPL_SDO_ASND_HANDLE) { // ASND
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+ Ret = EplSdoAsnduSendData(pAsySdoSeqCon_p->m_ConHandle, pEplFrame_p, // pointer to frame
+ uiDataSize_p);
+#else
+ Ret = kEplSdoSeqUnsupportedProt;
+#endif
+ } else { // error
+ Ret = kEplSdoSeqInvalidHdl;
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsyReceiveCb
+//
+// Description: callback-function for received frames from lower layer
+//
+//
+//
+// Parameters: ConHdl_p = handle of the connection
+// pSdoSeqData_p = pointer to frame
+// uiDataSize_p = size of frame
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p,
+ tEplAsySdoSeq * pSdoSeqData_p,
+ unsigned int uiDataSize_p)
+{
+ tEplKernel Ret;
+ unsigned int uiCount = 0;
+ unsigned int uiFreeEntry = EPL_MAX_SDO_SEQ_CON;
+ tEplAsySdoSeqCon *pAsySdoSeqCon;
+
+#if defined(WIN32) || defined(_WIN32)
+ // enter critical section
+ EnterCriticalSection(AsySdoSequInstance_g.m_pCriticalSectionReceive);
+#endif
+
+ EPL_DBGLVL_SDO_TRACE2("Handle: 0x%x , First Databyte 0x%x\n", ConHdl_p,
+ ((BYTE *) pSdoSeqData_p)[0]);
+
+ // search controll structure for this connection
+ pAsySdoSeqCon = &AsySdoSequInstance_g.m_AsySdoConnection[uiCount];
+ while (uiCount < EPL_MAX_SDO_SEQ_CON) {
+ if (pAsySdoSeqCon->m_ConHandle == ConHdl_p) {
+ break;
+ } else if ((pAsySdoSeqCon->m_ConHandle == 0)
+ && (uiFreeEntry == EPL_MAX_SDO_SEQ_CON)) {
+ // free entry
+ uiFreeEntry = uiCount;
+ }
+ uiCount++;
+ pAsySdoSeqCon++;
+ }
+
+ if (uiCount == EPL_MAX_SDO_SEQ_CON) { // new connection
+ if (uiFreeEntry == EPL_MAX_SDO_SEQ_CON) {
+ Ret = kEplSdoSeqNoFreeHandle;
+ goto Exit;
+ } else {
+ pAsySdoSeqCon =
+ &AsySdoSequInstance_g.
+ m_AsySdoConnection[uiFreeEntry];
+ // save handle from lower layer
+ pAsySdoSeqCon->m_ConHandle = ConHdl_p;
+ // increment use counter
+ pAsySdoSeqCon->m_uiUseCount++;
+ uiCount = uiFreeEntry;
+ }
+ }
+ // call history ack function
+ Ret = EplSdoAsyAckFrameToHistory(pAsySdoSeqCon,
+ (AmiGetByteFromLe
+ (&pSdoSeqData_p->
+ m_le_bRecSeqNumCon) &
+ EPL_SEQ_NUM_MASK));
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#if defined(WIN32) || defined(_WIN32)
+ // leave critical section
+ LeaveCriticalSection(AsySdoSequInstance_g.m_pCriticalSectionReceive);
+#endif
+
+ // call process function with pointer of frame and event kAsySdoSeqEventFrameRec
+ Ret = EplSdoAsySeqProcess(uiCount,
+ uiDataSize_p,
+ NULL, pSdoSeqData_p, kAsySdoSeqEventFrameRec);
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsyInitHistory
+//
+// Description: inti function for history buffer
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsyInitHistory(void)
+{
+ tEplKernel Ret;
+ unsigned int uiCount;
+
+ Ret = kEplSuccessful;
+ // init m_bFreeEntries in history-buffer
+ for (uiCount = 0; uiCount < EPL_MAX_SDO_SEQ_CON; uiCount++) {
+ AsySdoSequInstance_g.m_AsySdoConnection[uiCount].
+ m_SdoConHistory.m_bFreeEntries = EPL_SDO_HISTORY_SIZE;
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsyAddFrameToHistory
+//
+// Description: function to add a frame to the history buffer
+//
+//
+//
+// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
+// pFrame_p = pointer to frame
+// uiSize_p = size of the frame
+// -> without size of the ethernet header
+// and the asnd header
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ tEplFrame * pFrame_p,
+ unsigned int uiSize_p)
+{
+ tEplKernel Ret;
+ tEplAsySdoConHistory *pHistory;
+
+ Ret = kEplSuccessful;
+
+ // add frame to history buffer
+
+ // check size
+ // $$$ d.k. EPL_SEQ_HISTORY_FRAME_SIZE includes the header size, but uiSize_p does not!!!
+ if (uiSize_p > EPL_SEQ_HISTROY_FRAME_SIZE) {
+ Ret = kEplSdoSeqFrameSizeError;
+ goto Exit;
+ }
+ // save pointer to history
+ pHistory = &pAsySdoSeqCon_p->m_SdoConHistory;
+
+ // check if a free entry is available
+ if (pHistory->m_bFreeEntries > 0) { // write message in free entry
+ EPL_MEMCPY(&
+ ((tEplFrame *) pHistory->
+ m_aabHistoryFrame[pHistory->m_bWrite])->
+ m_le_bMessageType, &pFrame_p->m_le_bMessageType,
+ uiSize_p + EPL_ASND_HEADER_SIZE);
+ // store size
+ pHistory->m_auiFrameSize[pHistory->m_bWrite] = uiSize_p;
+
+ // decremend number of free bufferentries
+ pHistory->m_bFreeEntries--;
+
+ // increment writeindex
+ pHistory->m_bWrite++;
+
+ // check if write-index run over array-boarder
+ if (pHistory->m_bWrite == EPL_SDO_HISTORY_SIZE) {
+ pHistory->m_bWrite = 0;
+ }
+
+ } else { // no free entry
+ Ret = kEplSdoSeqNoFreeHistory;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsyAckFrameToHistory
+//
+// Description: function to delete acknowledged frames fron history buffer
+//
+//
+//
+// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
+// bRecSeqNumber_p = receive sequence number of the received frame
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ BYTE bRecSeqNumber_p)
+{
+ tEplKernel Ret;
+ tEplAsySdoConHistory *pHistory;
+ BYTE bAckIndex;
+ BYTE bCurrentSeqNum;
+
+ Ret = kEplSuccessful;
+
+ // get pointer to history buffer
+ pHistory = &pAsySdoSeqCon_p->m_SdoConHistory;
+
+ // release all acknowledged frames from history buffer
+
+ // check if there are entries in history
+ if (pHistory->m_bFreeEntries < EPL_SDO_HISTORY_SIZE) {
+ bAckIndex = pHistory->m_bAck;
+ do {
+ bCurrentSeqNum =
+ (((tEplFrame *) pHistory->
+ m_aabHistoryFrame[bAckIndex])->m_Data.m_Asnd.
+ m_Payload.m_SdoSequenceFrame.
+ m_le_bSendSeqNumCon & EPL_SEQ_NUM_MASK);
+ if (((bRecSeqNumber_p -
+ bCurrentSeqNum) & EPL_SEQ_NUM_MASK)
+ < EPL_SEQ_NUM_THRESHOLD) {
+ pHistory->m_auiFrameSize[bAckIndex] = 0;
+ bAckIndex++;
+ pHistory->m_bFreeEntries++;
+ if (bAckIndex == EPL_SDO_HISTORY_SIZE) { // read index run over array-boarder
+ bAckIndex = 0;
+ }
+ } else { // nothing to do anymore,
+ // because any further frame in history has larger sequence
+ // number than the acknowledge
+ goto Exit;
+ }
+ }
+ while ((((bRecSeqNumber_p - 1 -
+ bCurrentSeqNum) & EPL_SEQ_NUM_MASK)
+ < EPL_SEQ_NUM_THRESHOLD)
+ && (pHistory->m_bWrite != bAckIndex));
+
+ // store local read-index to global var
+ pHistory->m_bAck = bAckIndex;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsyReadFromHistory
+//
+// Description: function to one frame from history
+//
+//
+//
+// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
+// ppFrame_p = pointer to pointer to the buffer of the stored frame
+// puiSize_p = OUT: size of the frame
+// fInitRead = bool which indicate a start of retransmission
+// -> return last not acknowledged message if TRUE
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsyReadFromHistory(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ tEplFrame ** ppFrame_p,
+ unsigned int *puiSize_p,
+ BOOL fInitRead_p)
+{
+ tEplKernel Ret;
+ tEplAsySdoConHistory *pHistory;
+
+ Ret = kEplSuccessful;
+
+ // read one message from History
+
+ // get pointer to history buffer
+ pHistory = &pAsySdoSeqCon_p->m_SdoConHistory;
+
+ // check if init
+ if (fInitRead_p != FALSE) { // initialize read index to the index which shall be acknowledged next
+ pHistory->m_bRead = pHistory->m_bAck;
+ }
+ // check if entries are available for reading
+ if ((pHistory->m_bFreeEntries < EPL_SDO_HISTORY_SIZE)
+ && (pHistory->m_bWrite != pHistory->m_bRead)) {
+// PRINTF4("EplSdoAsyReadFromHistory(): init = %d, read = %u, write = %u, ack = %u", (int) fInitRead_p, (WORD)pHistory->m_bRead, (WORD)pHistory->m_bWrite, (WORD)pHistory->m_bAck);
+// PRINTF2(", free entries = %u, next frame size = %u\n", (WORD)pHistory->m_bFreeEntries, pHistory->m_auiFrameSize[pHistory->m_bRead]);
+
+ // return pointer to stored frame
+ *ppFrame_p =
+ (tEplFrame *) pHistory->m_aabHistoryFrame[pHistory->
+ m_bRead];
+
+ // save size
+ *puiSize_p = pHistory->m_auiFrameSize[pHistory->m_bRead];
+
+ pHistory->m_bRead++;
+ if (pHistory->m_bRead == EPL_SDO_HISTORY_SIZE) {
+ pHistory->m_bRead = 0;
+ }
+
+ } else {
+// PRINTF3("EplSdoAsyReadFromHistory(): read = %u, ack = %u, free entries = %u, no frame\n", (WORD)pHistory->m_bRead, (WORD)pHistory->m_bAck, (WORD)pHistory->m_bFreeEntries);
+
+ // no more frames to send
+ // return null pointer
+ *ppFrame_p = NULL;
+
+ *puiSize_p = 0;
+ }
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsyGetFreeEntriesFromHistory
+//
+// Description: function returns the number of free histroy entries
+//
+//
+//
+// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
+//
+//
+// Returns: unsigned int = number of free entries
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static unsigned int EplSdoAsyGetFreeEntriesFromHistory(tEplAsySdoSeqCon *
+ pAsySdoSeqCon_p)
+{
+ unsigned int uiFreeEntries;
+
+ uiFreeEntries =
+ (unsigned int)pAsySdoSeqCon_p->m_SdoConHistory.m_bFreeEntries;
+
+ return uiFreeEntries;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoAsySeqSetTimer
+//
+// Description: function sets or modify timer in timermosule
+//
+//
+//
+// Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
+// ulTimeout = timeout in ms
+//
+//
+// Returns: unsigned int = number of free entries
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoAsySeqSetTimer(tEplAsySdoSeqCon * pAsySdoSeqCon_p,
+ unsigned long ulTimeout)
+{
+ tEplKernel Ret;
+ tEplTimerArg TimerArg;
+
+ TimerArg.m_EventSink = kEplEventSinkSdoAsySeq;
+ TimerArg.m_ulArg = (unsigned long)pAsySdoSeqCon_p;
+
+ if (pAsySdoSeqCon_p->m_EplTimerHdl == 0) { // create new timer
+ Ret = EplTimeruSetTimerMs(&pAsySdoSeqCon_p->m_EplTimerHdl,
+ ulTimeout, TimerArg);
+ } else { // modify exisiting timer
+ Ret = EplTimeruModifyTimerMs(&pAsySdoSeqCon_p->m_EplTimerHdl,
+ ulTimeout, TimerArg);
+
+ }
+
+ return Ret;
+}
+
+// EOF
diff --git a/drivers/staging/epl/EplSdoComu.c b/drivers/staging/epl/EplSdoComu.c
new file mode 100644
index 000000000000..ce0eb33f4c41
--- /dev/null
+++ b/drivers/staging/epl/EplSdoComu.c
@@ -0,0 +1,3346 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for SDO Command Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoComu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.14 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplSdoComu.h"
+
+#if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) == 0) &&\
+ (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) == 0) )
+
+#error 'ERROR: At least SDO Server or SDO Client should be activate!'
+
+#endif
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
+
+#error 'ERROR: SDO Server needs OBDu module!'
+
+#endif
+
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef EPL_MAX_SDO_COM_CON
+#define EPL_MAX_SDO_COM_CON 5
+#endif
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+// intern events
+typedef enum {
+ kEplSdoComConEventSendFirst = 0x00, // first frame to send
+ kEplSdoComConEventRec = 0x01, // frame received
+ kEplSdoComConEventConEstablished = 0x02, // connection established
+ kEplSdoComConEventConClosed = 0x03, // connection closed
+ kEplSdoComConEventAckReceived = 0x04, // acknowledge received by lower layer
+ // -> continue sending
+ kEplSdoComConEventFrameSended = 0x05, // lower has send a frame
+ kEplSdoComConEventInitError = 0x06, // error duringinitialisiation
+ // of the connection
+ kEplSdoComConEventTimeout = 0x07 // timeout in lower layer
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ ,
+
+ kEplSdoComConEventInitCon = 0x08, // init connection (only client)
+ kEplSdoComConEventAbort = 0x09 // abort sdo transfer (only client)
+#endif
+} tEplSdoComConEvent;
+
+typedef enum {
+ kEplSdoComSendTypeReq = 0x00, // send a request
+ kEplSdoComSendTypeAckRes = 0x01, // send a resonse without data
+ kEplSdoComSendTypeRes = 0x02, // send response with data
+ kEplSdoComSendTypeAbort = 0x03 // send abort
+} tEplSdoComSendType;
+
+// state of the state maschine
+typedef enum {
+ // General State
+ kEplSdoComStateIdle = 0x00, // idle state
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+ // Server States
+ kEplSdoComStateServerSegmTrans = 0x01, // send following frames
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ // Client States
+ kEplSdoComStateClientWaitInit = 0x10, // wait for init connection
+ // on lower layer
+ kEplSdoComStateClientConnected = 0x11, // connection established
+ kEplSdoComStateClientSegmTrans = 0x12 // send following frames
+#endif
+} tEplSdoComState;
+
+// control structure for transaction
+typedef struct {
+ tEplSdoSeqConHdl m_SdoSeqConHdl; // if != 0 -> entry used
+ tEplSdoComState m_SdoComState;
+ BYTE m_bTransactionId;
+ unsigned int m_uiNodeId; // NodeId of the target
+ // -> needed to reinit connection
+ // after timeout
+ tEplSdoTransType m_SdoTransType; // Auto, Expedited, Segmented
+ tEplSdoServiceType m_SdoServiceType; // WriteByIndex, ReadByIndex
+ tEplSdoType m_SdoProtType; // protocol layer: Auto, Udp, Asnd, Pdo
+ BYTE *m_pData; // pointer to data
+ unsigned int m_uiTransSize; // number of bytes
+ // to transfer
+ unsigned int m_uiTransferredByte; // number of bytes
+ // already transferred
+ tEplSdoFinishedCb m_pfnTransferFinished; // callback function of the
+ // application
+ // -> called in the end of
+ // the SDO transfer
+ void *m_pUserArg; // user definable argument pointer
+
+ DWORD m_dwLastAbortCode; // save the last abort code
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ // only for client
+ unsigned int m_uiTargetIndex; // index to access
+ unsigned int m_uiTargetSubIndex; // subiondex to access
+
+ // for future use
+ unsigned int m_uiTimeout; // timeout for this connection
+
+#endif
+
+} tEplSdoComCon;
+
+// instance table
+typedef struct {
+ tEplSdoComCon m_SdoComCon[EPL_MAX_SDO_COM_CON];
+
+#if defined(WIN32) || defined(_WIN32)
+ LPCRITICAL_SECTION m_pCriticalSection;
+ CRITICAL_SECTION m_CriticalSection;
+#endif
+
+} tEplSdoComInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+static tEplSdoComInstance SdoComInstance_g;
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplAsySdoCom * pAsySdoCom_p,
+ unsigned int uiDataSize_p);
+
+tEplKernel PUBLIC EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplAsySdoConState AsySdoConState_p);
+
+static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplSdoComConEvent SdoComConEvent_p,
+ tEplAsySdoCom * pAsySdoCom_p);
+
+static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p,
+ tEplSdoComConEvent SdoComConEvent_p,
+ tEplAsySdoCom * pAsySdoCom_p);
+
+static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p,
+ tEplSdoComCon * pSdoComCon_p,
+ tEplSdoComConState
+ SdoComConState_p);
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p,
+ tEplAsySdoCom * pAsySdoCom_p);
+
+static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p,
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ tEplSdoComSendType SendType_p);
+
+static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p,
+ tEplAsySdoCom * pAsySdoCom_p);
+#endif
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+
+static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p);
+
+static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p,
+ tEplAsySdoCom * pAsySdoCom_p);
+
+static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p,
+ DWORD dwAbortCode_p);
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <SDO Command Layer> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: SDO Command layer Modul
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComInit
+//
+// Description: Init first instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoComInit(void)
+{
+ tEplKernel Ret;
+
+ Ret = EplSdoComAddInstance();
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComAddInstance
+//
+// Description: Init additional instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoComAddInstance(void)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // init controll structure
+ EPL_MEMSET(&SdoComInstance_g, 0x00, sizeof(SdoComInstance_g));
+
+ // init instance of lower layer
+ Ret = EplSdoAsySeqAddInstance(EplSdoComReceiveCb, EplSdoComConCb);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+#if defined(WIN32) || defined(_WIN32)
+ // create critical section for process function
+ SdoComInstance_g.m_pCriticalSection =
+ &SdoComInstance_g.m_CriticalSection;
+ InitializeCriticalSection(SdoComInstance_g.m_pCriticalSection);
+#endif
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComDelInstance
+//
+// Description: delete instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoComDelInstance(void)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+#if defined(WIN32) || defined(_WIN32)
+ // delete critical section for process function
+ DeleteCriticalSection(SdoComInstance_g.m_pCriticalSection);
+#endif
+
+ Ret = EplSdoAsySeqDelInstance();
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComDefineCon
+//
+// Description: function defines a SDO connection to another node
+// -> init lower layer and returns a handle for the connection.
+// Two client connections to the same node via the same protocol
+// are not allowed. If this function detects such a situation
+// it will return kEplSdoComHandleExists and the handle of
+// the existing connection in pSdoComConHdl_p.
+// Using of existing server connections is possible.
+//
+// Parameters: pSdoComConHdl_p = pointer to the buffer of the handle
+// uiTargetNodeId_p = NodeId of the targetnode
+// ProtType_p = type of protocol to use for connection
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl * pSdoComConHdl_p,
+ unsigned int uiTargetNodeId_p,
+ tEplSdoType ProtType_p)
+{
+ tEplKernel Ret;
+ unsigned int uiCount;
+ unsigned int uiFreeHdl;
+ tEplSdoComCon *pSdoComCon;
+
+ // check Parameter
+ ASSERT(pSdoComConHdl_p != NULL);
+
+ // check NodeId
+ if ((uiTargetNodeId_p == EPL_C_ADR_INVALID)
+ || (uiTargetNodeId_p >= EPL_C_ADR_BROADCAST)) {
+ Ret = kEplInvalidNodeId;
+
+ }
+ // search free control structure
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[0];
+ uiCount = 0;
+ uiFreeHdl = EPL_MAX_SDO_COM_CON;
+ while (uiCount < EPL_MAX_SDO_COM_CON) {
+ if (pSdoComCon->m_SdoSeqConHdl == 0) { // free entry
+ uiFreeHdl = uiCount;
+ } else if ((pSdoComCon->m_uiNodeId == uiTargetNodeId_p)
+ && (pSdoComCon->m_SdoProtType == ProtType_p)) { // existing client connection with same node ID and same protocol type
+ *pSdoComConHdl_p = uiCount;
+ Ret = kEplSdoComHandleExists;
+ goto Exit;
+ }
+ uiCount++;
+ pSdoComCon++;
+ }
+
+ if (uiFreeHdl == EPL_MAX_SDO_COM_CON) {
+ Ret = kEplSdoComNoFreeHandle;
+ goto Exit;
+ }
+
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[uiFreeHdl];
+ // save handle for application
+ *pSdoComConHdl_p = uiFreeHdl;
+ // save parameters
+ pSdoComCon->m_SdoProtType = ProtType_p;
+ pSdoComCon->m_uiNodeId = uiTargetNodeId_p;
+
+ // set Transaction Id
+ pSdoComCon->m_bTransactionId = 0;
+
+ // check protocol
+ switch (ProtType_p) {
+ // udp
+ case kEplSdoTypeUdp:
+ {
+ // call connection int function of lower layer
+ Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
+ pSdoComCon->m_uiNodeId,
+ kEplSdoTypeUdp);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ break;
+ }
+
+ // Asend
+ case kEplSdoTypeAsnd:
+ {
+ // call connection int function of lower layer
+ Ret = EplSdoAsySeqInitCon(&pSdoComCon->m_SdoSeqConHdl,
+ pSdoComCon->m_uiNodeId,
+ kEplSdoTypeAsnd);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ break;
+ }
+
+ // Pdo -> not supported
+ case kEplSdoTypePdo:
+ default:
+ {
+ Ret = kEplSdoComUnsupportedProt;
+ goto Exit;
+ }
+ } // end of switch(m_ProtType_p)
+
+ // call process function
+ Ret = EplSdoComProcessIntern(uiFreeHdl,
+ kEplSdoComConEventInitCon, NULL);
+
+ Exit:
+ return Ret;
+}
+#endif
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComInitTransferByIndex
+//
+// Description: function init SDO Transfer for a defined connection
+//
+//
+//
+// Parameters: SdoComTransParam_p = Structure with parameters for connection
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex *
+ pSdoComTransParam_p)
+{
+ tEplKernel Ret;
+ tEplSdoComCon *pSdoComCon;
+
+ // check parameter
+ if ((pSdoComTransParam_p->m_uiSubindex >= 0xFF)
+ || (pSdoComTransParam_p->m_uiIndex == 0)
+ || (pSdoComTransParam_p->m_uiIndex > 0xFFFF)
+ || (pSdoComTransParam_p->m_pData == NULL)
+ || (pSdoComTransParam_p->m_uiDataSize == 0)) {
+ Ret = kEplSdoComInvalidParam;
+ goto Exit;
+ }
+
+ if (pSdoComTransParam_p->m_SdoComConHdl >= EPL_MAX_SDO_COM_CON) {
+ Ret = kEplSdoComInvalidHandle;
+ goto Exit;
+ }
+ // get pointer to control structure of connection
+ pSdoComCon =
+ &SdoComInstance_g.m_SdoComCon[pSdoComTransParam_p->m_SdoComConHdl];
+
+ // check if handle ok
+ if (pSdoComCon->m_SdoSeqConHdl == 0) {
+ Ret = kEplSdoComInvalidHandle;
+ goto Exit;
+ }
+ // check if command layer is idle
+ if ((pSdoComCon->m_uiTransferredByte + pSdoComCon->m_uiTransSize) > 0) { // handle is not idle
+ Ret = kEplSdoComHandleBusy;
+ goto Exit;
+ }
+ // save parameter
+ // callback function for end of transfer
+ pSdoComCon->m_pfnTransferFinished =
+ pSdoComTransParam_p->m_pfnSdoFinishedCb;
+ pSdoComCon->m_pUserArg = pSdoComTransParam_p->m_pUserArg;
+
+ // set type of SDO command
+ if (pSdoComTransParam_p->m_SdoAccessType == kEplSdoAccessTypeRead) {
+ pSdoComCon->m_SdoServiceType = kEplSdoServiceReadByIndex;
+ } else {
+ pSdoComCon->m_SdoServiceType = kEplSdoServiceWriteByIndex;
+
+ }
+ // save pointer to data
+ pSdoComCon->m_pData = pSdoComTransParam_p->m_pData;
+ // maximal bytes to transfer
+ pSdoComCon->m_uiTransSize = pSdoComTransParam_p->m_uiDataSize;
+ // bytes already transfered
+ pSdoComCon->m_uiTransferredByte = 0;
+
+ // reset parts of control structure
+ pSdoComCon->m_dwLastAbortCode = 0;
+ pSdoComCon->m_SdoTransType = kEplSdoTransAuto;
+ // save timeout
+ //pSdoComCon->m_uiTimeout = SdoComTransParam_p.m_uiTimeout;
+
+ // save index and subindex
+ pSdoComCon->m_uiTargetIndex = pSdoComTransParam_p->m_uiIndex;
+ pSdoComCon->m_uiTargetSubIndex = pSdoComTransParam_p->m_uiSubindex;
+
+ // call process function
+ Ret = EplSdoComProcessIntern(pSdoComTransParam_p->m_SdoComConHdl, kEplSdoComConEventSendFirst, // event to start transfer
+ NULL);
+
+ Exit:
+ return Ret;
+
+}
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComUndefineCon
+//
+// Description: function undefine a SDO connection
+//
+//
+//
+// Parameters: SdoComConHdl_p = handle for the connection
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p)
+{
+ tEplKernel Ret;
+ tEplSdoComCon *pSdoComCon;
+
+ Ret = kEplSuccessful;
+
+ if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) {
+ Ret = kEplSdoComInvalidHandle;
+ goto Exit;
+ }
+ // get pointer to control structure
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
+
+ // $$$ d.k. abort a running transfer before closing the sequence layer
+
+ if (((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) !=
+ EPL_SDO_SEQ_INVALID_HDL)
+ && (pSdoComCon->m_SdoSeqConHdl != 0)) {
+ // close connection in lower layer
+ switch (pSdoComCon->m_SdoProtType) {
+ case kEplSdoTypeAsnd:
+ case kEplSdoTypeUdp:
+ {
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ break;
+ }
+
+ case kEplSdoTypePdo:
+ case kEplSdoTypeAuto:
+ default:
+ {
+ Ret = kEplSdoComUnsupportedProt;
+ goto Exit;
+ }
+
+ } // end of switch(pSdoComCon->m_SdoProtType)
+ }
+
+ // clean controll structure
+ EPL_MEMSET(pSdoComCon, 0x00, sizeof(tEplSdoComCon));
+ Exit:
+ return Ret;
+}
+#endif
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComGetState
+//
+// Description: function returns the state fo the connection
+//
+//
+//
+// Parameters: SdoComConHdl_p = handle for the connection
+// pSdoComFinished_p = pointer to structur for sdo state
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p,
+ tEplSdoComFinished * pSdoComFinished_p)
+{
+ tEplKernel Ret;
+ tEplSdoComCon *pSdoComCon;
+
+ Ret = kEplSuccessful;
+
+ if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) {
+ Ret = kEplSdoComInvalidHandle;
+ goto Exit;
+ }
+ // get pointer to control structure
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
+
+ // check if handle ok
+ if (pSdoComCon->m_SdoSeqConHdl == 0) {
+ Ret = kEplSdoComInvalidHandle;
+ goto Exit;
+ }
+
+ pSdoComFinished_p->m_pUserArg = pSdoComCon->m_pUserArg;
+ pSdoComFinished_p->m_uiNodeId = pSdoComCon->m_uiNodeId;
+ pSdoComFinished_p->m_uiTargetIndex = pSdoComCon->m_uiTargetIndex;
+ pSdoComFinished_p->m_uiTargetSubIndex = pSdoComCon->m_uiTargetSubIndex;
+ pSdoComFinished_p->m_uiTransferredByte =
+ pSdoComCon->m_uiTransferredByte;
+ pSdoComFinished_p->m_dwAbortCode = pSdoComCon->m_dwLastAbortCode;
+ pSdoComFinished_p->m_SdoComConHdl = SdoComConHdl_p;
+ if (pSdoComCon->m_SdoServiceType == kEplSdoServiceWriteByIndex) {
+ pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeWrite;
+ } else {
+ pSdoComFinished_p->m_SdoAccessType = kEplSdoAccessTypeRead;
+ }
+
+ if (pSdoComCon->m_dwLastAbortCode != 0) { // sdo abort
+ pSdoComFinished_p->m_SdoComConState =
+ kEplSdoComTransferRxAborted;
+
+ // delete abort code
+ pSdoComCon->m_dwLastAbortCode = 0;
+
+ } else if ((pSdoComCon->m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) == EPL_SDO_SEQ_INVALID_HDL) { // check state
+ pSdoComFinished_p->m_SdoComConState =
+ kEplSdoComTransferLowerLayerAbort;
+ } else if (pSdoComCon->m_SdoComState == kEplSdoComStateClientWaitInit) {
+ // finished
+ pSdoComFinished_p->m_SdoComConState =
+ kEplSdoComTransferNotActive;
+ } else if (pSdoComCon->m_uiTransSize == 0) { // finished
+ pSdoComFinished_p->m_SdoComConState =
+ kEplSdoComTransferFinished;
+ }
+
+ Exit:
+ return Ret;
+
+}
+#endif
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComSdoAbort
+//
+// Description: function abort a sdo transfer
+//
+//
+//
+// Parameters: SdoComConHdl_p = handle for the connection
+// dwAbortCode_p = abort code
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p,
+ DWORD dwAbortCode_p)
+{
+ tEplKernel Ret;
+ tEplSdoComCon *pSdoComCon;
+
+ if (SdoComConHdl_p >= EPL_MAX_SDO_COM_CON) {
+ Ret = kEplSdoComInvalidHandle;
+ goto Exit;
+ }
+ // get pointer to control structure of connection
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComConHdl_p];
+
+ // check if handle ok
+ if (pSdoComCon->m_SdoSeqConHdl == 0) {
+ Ret = kEplSdoComInvalidHandle;
+ goto Exit;
+ }
+ // save pointer to abort code
+ pSdoComCon->m_pData = (BYTE *) & dwAbortCode_p;
+
+ Ret = EplSdoComProcessIntern(SdoComConHdl_p,
+ kEplSdoComConEventAbort,
+ (tEplAsySdoCom *) NULL);
+
+ Exit:
+ return Ret;
+}
+#endif
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComReceiveCb
+//
+// Description: callback function for SDO Sequence Layer
+// -> indicates new data
+//
+//
+//
+// Parameters: SdoSeqConHdl_p = Handle for connection
+// pAsySdoCom_p = pointer to data
+// uiDataSize_p = size of data ($$$ not used yet, but it should)
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoComReceiveCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplAsySdoCom * pAsySdoCom_p,
+ unsigned int uiDataSize_p)
+{
+ tEplKernel Ret;
+
+ // search connection internally
+ Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p,
+ kEplSdoComConEventRec, pAsySdoCom_p);
+
+ EPL_DBGLVL_SDO_TRACE3
+ ("EplSdoComReceiveCb SdoSeqConHdl: 0x%X, First Byte of pAsySdoCom_p: 0x%02X, uiDataSize_p: 0x%04X\n",
+ SdoSeqConHdl_p, (WORD) pAsySdoCom_p->m_le_abCommandData[0],
+ uiDataSize_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComConCb
+//
+// Description: callback function called by SDO Sequence Layer to inform
+// command layer about state change of connection
+//
+//
+//
+// Parameters: SdoSeqConHdl_p = Handle of the connection
+// AsySdoConState_p = Event of the connection
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoComConCb(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplAsySdoConState AsySdoConState_p)
+{
+ tEplKernel Ret;
+ tEplSdoComConEvent SdoComConEvent = kEplSdoComConEventSendFirst;
+
+ Ret = kEplSuccessful;
+
+ // check state
+ switch (AsySdoConState_p) {
+ case kAsySdoConStateConnected:
+ {
+ EPL_DBGLVL_SDO_TRACE0("Connection established\n");
+ SdoComConEvent = kEplSdoComConEventConEstablished;
+ // start transmission if needed
+ break;
+ }
+
+ case kAsySdoConStateInitError:
+ {
+ EPL_DBGLVL_SDO_TRACE0("Error during initialisation\n");
+ SdoComConEvent = kEplSdoComConEventInitError;
+ // inform app about error and close sequence layer handle
+ break;
+ }
+
+ case kAsySdoConStateConClosed:
+ {
+ EPL_DBGLVL_SDO_TRACE0("Connection closed\n");
+ SdoComConEvent = kEplSdoComConEventConClosed;
+ // close sequence layer handle
+ break;
+ }
+
+ case kAsySdoConStateAckReceived:
+ {
+ EPL_DBGLVL_SDO_TRACE0("Acknowlage received\n");
+ SdoComConEvent = kEplSdoComConEventAckReceived;
+ // continue transmission
+ break;
+ }
+
+ case kAsySdoConStateFrameSended:
+ {
+ EPL_DBGLVL_SDO_TRACE0("One Frame sent\n");
+ SdoComConEvent = kEplSdoComConEventFrameSended;
+ // to continue transmission
+ break;
+
+ }
+
+ case kAsySdoConStateTimeout:
+ {
+ EPL_DBGLVL_SDO_TRACE0("Timeout\n");
+ SdoComConEvent = kEplSdoComConEventTimeout;
+ // close sequence layer handle
+ break;
+
+ }
+ } // end of switch(AsySdoConState_p)
+
+ Ret = EplSdoComSearchConIntern(SdoSeqConHdl_p,
+ SdoComConEvent, (tEplAsySdoCom *) NULL);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComSearchConIntern
+//
+// Description: search a Sdo Sequence Layer connection handle in the
+// control structure of the Command Layer
+//
+// Parameters: SdoSeqConHdl_p = Handle to search
+// SdoComConEvent_p = event to process
+// pAsySdoCom_p = pointer to received frame
+//
+// Returns: tEplKernel
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoComSearchConIntern(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ tEplSdoComConEvent SdoComConEvent_p,
+ tEplAsySdoCom * pAsySdoCom_p)
+{
+ tEplKernel Ret;
+ tEplSdoComCon *pSdoComCon;
+ tEplSdoComConHdl HdlCount;
+ tEplSdoComConHdl HdlFree;
+
+ Ret = kEplSdoComNotResponsible;
+
+ // get pointer to first element of the array
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[0];
+ HdlCount = 0;
+ HdlFree = 0xFFFF;
+ while (HdlCount < EPL_MAX_SDO_COM_CON) {
+ if (pSdoComCon->m_SdoSeqConHdl == SdoSeqConHdl_p) { // matching command layer handle found
+ Ret = EplSdoComProcessIntern(HdlCount,
+ SdoComConEvent_p,
+ pAsySdoCom_p);
+ } else if ((pSdoComCon->m_SdoSeqConHdl == 0)
+ && (HdlFree == 0xFFFF)) {
+ HdlFree = HdlCount;
+ }
+
+ pSdoComCon++;
+ HdlCount++;
+ }
+
+ if (Ret == kEplSdoComNotResponsible) { // no responsible command layer handle found
+ if (HdlFree == 0xFFFF) { // no free handle
+ // delete connection immediately
+ // 2008/04/14 m.u./d.k. This connection actually does not exist.
+ // pSdoComCon is invalid.
+ // Ret = EplSdoAsySeqDelCon(pSdoComCon->m_SdoSeqConHdl);
+ Ret = kEplSdoComNoFreeHandle;
+ } else { // create new handle
+ HdlCount = HdlFree;
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[HdlCount];
+ pSdoComCon->m_SdoSeqConHdl = SdoSeqConHdl_p;
+ Ret = EplSdoComProcessIntern(HdlCount,
+ SdoComConEvent_p,
+ pAsySdoCom_p);
+ }
+ }
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComProcessIntern
+//
+// Description: search a Sdo Sequence Layer connection handle in the
+// control structer of the Command Layer
+//
+//
+//
+// Parameters: SdoComCon_p = index of control structure of connection
+// SdoComConEvent_p = event to process
+// pAsySdoCom_p = pointer to received frame
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoComProcessIntern(tEplSdoComConHdl SdoComCon_p,
+ tEplSdoComConEvent SdoComConEvent_p,
+ tEplAsySdoCom * pAsySdoCom_p)
+{
+ tEplKernel Ret;
+ tEplSdoComCon *pSdoComCon;
+ BYTE bFlag;
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+ DWORD dwAbortCode;
+ unsigned int uiSize;
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+ // enter critical section for process function
+ EnterCriticalSection(SdoComInstance_g.m_pCriticalSection);
+ EPL_DBGLVL_SDO_TRACE0
+ ("\n\tEnterCiticalSection EplSdoComProcessIntern\n\n");
+#endif
+
+ Ret = kEplSuccessful;
+
+ // get pointer to control structure
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p];
+
+ // process state maschine
+ switch (pSdoComCon->m_SdoComState) {
+ // idle state
+ case kEplSdoComStateIdle:
+ {
+ // check events
+ switch (SdoComConEvent_p) {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ // init con for client
+ case kEplSdoComConEventInitCon:
+ {
+
+ // call of the init function already
+ // processed in EplSdoComDefineCon()
+ // only change state to kEplSdoComStateClientWaitInit
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientWaitInit;
+ break;
+ }
+#endif
+
+ // int con for server
+ case kEplSdoComConEventRec:
+ {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+ // check if init of an transfer and no SDO abort
+ if ((pAsySdoCom_p->m_le_bFlags & 0x80) == 0) { // SDO request
+ if ((pAsySdoCom_p->m_le_bFlags & 0x40) == 0) { // no SDO abort
+ // save tansaction id
+ pSdoComCon->
+ m_bTransactionId =
+ AmiGetByteFromLe
+ (&pAsySdoCom_p->
+ m_le_bTransactionId);
+ // check command
+ switch (pAsySdoCom_p->
+ m_le_bCommandId)
+ {
+ case kEplSdoServiceNIL:
+ { // simply acknowlegde NIL command on sequence layer
+
+ Ret =
+ EplSdoAsySeqSendData
+ (pSdoComCon->
+ m_SdoSeqConHdl,
+ 0,
+ (tEplFrame
+ *)
+ NULL);
+
+ break;
+ }
+
+ case kEplSdoServiceReadByIndex:
+ { // read by index
+
+ // search entry an start transfer
+ EplSdoComServerInitReadByIndex
+ (pSdoComCon,
+ pAsySdoCom_p);
+ // check next state
+ if (pSdoComCon->m_uiTransSize == 0) { // ready -> stay idle
+ pSdoComCon->
+ m_SdoComState
+ =
+ kEplSdoComStateIdle;
+ // reset abort code
+ pSdoComCon->
+ m_dwLastAbortCode
+ =
+ 0;
+ } else { // segmented transfer
+ pSdoComCon->
+ m_SdoComState
+ =
+ kEplSdoComStateServerSegmTrans;
+ }
+
+ break;
+ }
+
+ case kEplSdoServiceWriteByIndex:
+ {
+
+ // search entry an start write
+ EplSdoComServerInitWriteByIndex
+ (pSdoComCon,
+ pAsySdoCom_p);
+ // check next state
+ if (pSdoComCon->m_uiTransSize == 0) { // already -> stay idle
+ pSdoComCon->
+ m_SdoComState
+ =
+ kEplSdoComStateIdle;
+ // reset abort code
+ pSdoComCon->
+ m_dwLastAbortCode
+ =
+ 0;
+ } else { // segmented transfer
+ pSdoComCon->
+ m_SdoComState
+ =
+ kEplSdoComStateServerSegmTrans;
+ }
+
+ break;
+ }
+
+ default:
+ {
+ // unsupported command
+ // -> abort senden
+ dwAbortCode
+ =
+ EPL_SDOAC_UNKNOWN_COMMAND_SPECIFIER;
+ // send abort
+ pSdoComCon->
+ m_pData
+ =
+ (BYTE
+ *)
+ &
+ dwAbortCode;
+ Ret =
+ EplSdoComServerSendFrameIntern
+ (pSdoComCon,
+ 0,
+ 0,
+ kEplSdoComSendTypeAbort);
+
+ }
+
+ } // end of switch(pAsySdoCom_p->m_le_bCommandId)
+ }
+ } else { // this command layer handle is not responsible
+ // (wrong direction or wrong transaction ID)
+ Ret = kEplSdoComNotResponsible;
+ goto Exit;
+ }
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+
+ break;
+ }
+
+ // connection closed
+ case kEplSdoComConEventInitError:
+ case kEplSdoComConEventTimeout:
+ case kEplSdoComConEventConClosed:
+ {
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ // clean control structure
+ EPL_MEMSET(pSdoComCon, 0x00,
+ sizeof(tEplSdoComCon));
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+ } // end of switch(SdoComConEvent_p)
+ break;
+ }
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+ //-------------------------------------------------------------------------
+ // SDO Server part
+ // segmented transfer
+ case kEplSdoComStateServerSegmTrans:
+ {
+ // check events
+ switch (SdoComConEvent_p) {
+ // send next frame
+ case kEplSdoComConEventAckReceived:
+ case kEplSdoComConEventFrameSended:
+ {
+ // check if it is a read
+ if (pSdoComCon->m_SdoServiceType ==
+ kEplSdoServiceReadByIndex) {
+ // send next frame
+ EplSdoComServerSendFrameIntern
+ (pSdoComCon, 0, 0,
+ kEplSdoComSendTypeRes);
+ // if all send -> back to idle
+ if (pSdoComCon->m_uiTransSize == 0) { // back to idle
+ pSdoComCon->
+ m_SdoComState =
+ kEplSdoComStateIdle;
+ // reset abort code
+ pSdoComCon->
+ m_dwLastAbortCode =
+ 0;
+ }
+
+ }
+ break;
+ }
+
+ // process next frame
+ case kEplSdoComConEventRec:
+ {
+ // check if the frame is a SDO response and has the right transaction ID
+ bFlag =
+ AmiGetByteFromLe(&pAsySdoCom_p->
+ m_le_bFlags);
+ if (((bFlag & 0x80) != 0)
+ &&
+ (AmiGetByteFromLe
+ (&pAsySdoCom_p->
+ m_le_bTransactionId) ==
+ pSdoComCon->m_bTransactionId)) {
+ // check if it is a abort
+ if ((bFlag & 0x40) != 0) { // SDO abort
+ // clear control structure
+ pSdoComCon->
+ m_uiTransSize = 0;
+ pSdoComCon->
+ m_uiTransferredByte
+ = 0;
+ // change state
+ pSdoComCon->
+ m_SdoComState =
+ kEplSdoComStateIdle;
+ // reset abort code
+ pSdoComCon->
+ m_dwLastAbortCode =
+ 0;
+ // d.k.: do not execute anything further on this command
+ break;
+ }
+ // check if it is a write
+ if (pSdoComCon->
+ m_SdoServiceType ==
+ kEplSdoServiceWriteByIndex)
+ {
+ // write data to OD
+ uiSize =
+ AmiGetWordFromLe
+ (&pAsySdoCom_p->
+ m_le_wSegmentSize);
+ if (pSdoComCon->
+ m_dwLastAbortCode ==
+ 0) {
+ EPL_MEMCPY
+ (pSdoComCon->
+ m_pData,
+ &pAsySdoCom_p->
+ m_le_abCommandData
+ [0],
+ uiSize);
+ }
+ // update counter
+ pSdoComCon->
+ m_uiTransferredByte
+ += uiSize;
+ pSdoComCon->
+ m_uiTransSize -=
+ uiSize;
+
+ // update pointer
+ if (pSdoComCon->
+ m_dwLastAbortCode ==
+ 0) {
+ ( /*(BYTE*) */
+ pSdoComCon->
+ m_pData) +=
+ uiSize;
+ }
+ // check end of transfer
+ if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x30) { // transfer ready
+ pSdoComCon->
+ m_uiTransSize
+ = 0;
+
+ if (pSdoComCon->
+ m_dwLastAbortCode
+ == 0) {
+ // send response
+ // send next frame
+ EplSdoComServerSendFrameIntern
+ (pSdoComCon,
+ 0,
+ 0,
+ kEplSdoComSendTypeRes);
+ // if all send -> back to idle
+ if (pSdoComCon->m_uiTransSize == 0) { // back to idle
+ pSdoComCon->
+ m_SdoComState
+ =
+ kEplSdoComStateIdle;
+ // reset abort code
+ pSdoComCon->
+ m_dwLastAbortCode
+ =
+ 0;
+ }
+ } else { // send dabort code
+ // send abort
+ pSdoComCon->
+ m_pData
+ =
+ (BYTE
+ *)
+ &
+ pSdoComCon->
+ m_dwLastAbortCode;
+ Ret =
+ EplSdoComServerSendFrameIntern
+ (pSdoComCon,
+ 0,
+ 0,
+ kEplSdoComSendTypeAbort);
+
+ // reset abort code
+ pSdoComCon->
+ m_dwLastAbortCode
+ = 0;
+
+ }
+ } else {
+ // send acknowledge without any Command layer data
+ Ret =
+ EplSdoAsySeqSendData
+ (pSdoComCon->
+ m_SdoSeqConHdl,
+ 0,
+ (tEplFrame
+ *) NULL);
+ }
+ }
+ } else { // this command layer handle is not responsible
+ // (wrong direction or wrong transaction ID)
+ Ret = kEplSdoComNotResponsible;
+ goto Exit;
+ }
+ break;
+ }
+
+ // connection closed
+ case kEplSdoComConEventInitError:
+ case kEplSdoComConEventTimeout:
+ case kEplSdoComConEventConClosed:
+ {
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ // clean control structure
+ EPL_MEMSET(pSdoComCon, 0x00,
+ sizeof(tEplSdoComCon));
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+ } // end of switch(SdoComConEvent_p)
+
+ break;
+ }
+#endif // endif of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ //-------------------------------------------------------------------------
+ // SDO Client part
+ // wait for finish of establishing connection
+ case kEplSdoComStateClientWaitInit:
+ {
+
+ // if connection handle is invalid reinit connection
+ // d.k.: this will be done only on new events (i.e. InitTransfer)
+ if ((pSdoComCon->
+ m_SdoSeqConHdl & ~EPL_SDO_SEQ_HANDLE_MASK) ==
+ EPL_SDO_SEQ_INVALID_HDL) {
+ // check kind of connection to reinit
+ // check protocol
+ switch (pSdoComCon->m_SdoProtType) {
+ // udp
+ case kEplSdoTypeUdp:
+ {
+ // call connection int function of lower layer
+ Ret =
+ EplSdoAsySeqInitCon
+ (&pSdoComCon->
+ m_SdoSeqConHdl,
+ pSdoComCon->m_uiNodeId,
+ kEplSdoTypeUdp);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ break;
+ }
+
+ // Asend -> not supported
+ case kEplSdoTypeAsnd:
+ {
+ // call connection int function of lower layer
+ Ret =
+ EplSdoAsySeqInitCon
+ (&pSdoComCon->
+ m_SdoSeqConHdl,
+ pSdoComCon->m_uiNodeId,
+ kEplSdoTypeAsnd);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ break;
+ }
+
+ // Pdo -> not supported
+ case kEplSdoTypePdo:
+ default:
+ {
+ Ret = kEplSdoComUnsupportedProt;
+ goto Exit;
+ }
+ } // end of switch(m_ProtType_p)
+ // d.k.: reset transaction ID, because new sequence layer connection was initialized
+ // $$$ d.k. is this really necessary?
+ //pSdoComCon->m_bTransactionId = 0;
+ }
+ // check events
+ switch (SdoComConEvent_p) {
+ // connection established
+ case kEplSdoComConEventConEstablished:
+ {
+ //send first frame if needed
+ if ((pSdoComCon->m_uiTransSize > 0)
+ && (pSdoComCon->m_uiTargetIndex != 0)) { // start SDO transfer
+ Ret =
+ EplSdoComClientSend
+ (pSdoComCon);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // check if segemted transfer
+ if (pSdoComCon->
+ m_SdoTransType ==
+ kEplSdoTransSegmented) {
+ pSdoComCon->
+ m_SdoComState =
+ kEplSdoComStateClientSegmTrans;
+ goto Exit;
+ }
+ }
+ // goto state kEplSdoComStateClientConnected
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientConnected;
+ goto Exit;
+ }
+
+ case kEplSdoComConEventSendFirst:
+ {
+ // infos for transfer already saved by function EplSdoComInitTransferByIndex
+ break;
+ }
+
+ case kEplSdoComConEventConClosed:
+ case kEplSdoComConEventInitError:
+ case kEplSdoComConEventTimeout:
+ {
+ // close sequence layer handle
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ pSdoComCon->m_SdoSeqConHdl |=
+ EPL_SDO_SEQ_INVALID_HDL;
+ // call callback function
+ if (SdoComConEvent_p ==
+ kEplSdoComConEventTimeout) {
+ pSdoComCon->m_dwLastAbortCode =
+ EPL_SDOAC_TIME_OUT;
+ } else {
+ pSdoComCon->m_dwLastAbortCode =
+ 0;
+ }
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferLowerLayerAbort);
+ // d.k.: do not clean control structure
+ break;
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(SdoComConEvent_p)
+ break;
+ }
+
+ // connected
+ case kEplSdoComStateClientConnected:
+ {
+ // check events
+ switch (SdoComConEvent_p) {
+ // send a frame
+ case kEplSdoComConEventSendFirst:
+ case kEplSdoComConEventAckReceived:
+ case kEplSdoComConEventFrameSended:
+ {
+ Ret = EplSdoComClientSend(pSdoComCon);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // check if read transfer finished
+ if ((pSdoComCon->m_uiTransSize == 0)
+ && (pSdoComCon->
+ m_uiTransferredByte != 0)
+ && (pSdoComCon->m_SdoServiceType ==
+ kEplSdoServiceReadByIndex)) {
+ // inc transaction id
+ pSdoComCon->m_bTransactionId++;
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode =
+ 0;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferFinished);
+
+ goto Exit;
+ }
+ // check if segemted transfer
+ if (pSdoComCon->m_SdoTransType ==
+ kEplSdoTransSegmented) {
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientSegmTrans;
+ goto Exit;
+ }
+ break;
+ }
+
+ // frame received
+ case kEplSdoComConEventRec:
+ {
+ // check if the frame is a SDO response and has the right transaction ID
+ bFlag =
+ AmiGetByteFromLe(&pAsySdoCom_p->
+ m_le_bFlags);
+ if (((bFlag & 0x80) != 0)
+ &&
+ (AmiGetByteFromLe
+ (&pAsySdoCom_p->
+ m_le_bTransactionId) ==
+ pSdoComCon->m_bTransactionId)) {
+ // check if abort or not
+ if ((bFlag & 0x40) != 0) {
+ // send acknowledge without any Command layer data
+ Ret =
+ EplSdoAsySeqSendData
+ (pSdoComCon->
+ m_SdoSeqConHdl, 0,
+ (tEplFrame *)
+ NULL);
+ // inc transaction id
+ pSdoComCon->
+ m_bTransactionId++;
+ // save abort code
+ pSdoComCon->
+ m_dwLastAbortCode =
+ AmiGetDwordFromLe
+ (&pAsySdoCom_p->
+ m_le_abCommandData
+ [0]);
+ // call callback of application
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p,
+ pSdoComCon,
+ kEplSdoComTransferRxAborted);
+
+ goto Exit;
+ } else { // normal frame received
+ // check frame
+ Ret =
+ EplSdoComClientProcessFrame
+ (SdoComCon_p,
+ pAsySdoCom_p);
+
+ // check if transfer ready
+ if (pSdoComCon->
+ m_uiTransSize ==
+ 0) {
+ // send acknowledge without any Command layer data
+ Ret =
+ EplSdoAsySeqSendData
+ (pSdoComCon->
+ m_SdoSeqConHdl,
+ 0,
+ (tEplFrame
+ *) NULL);
+ // inc transaction id
+ pSdoComCon->
+ m_bTransactionId++;
+ // call callback of application
+ pSdoComCon->
+ m_dwLastAbortCode
+ = 0;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p,
+ pSdoComCon,
+ kEplSdoComTransferFinished);
+
+ goto Exit;
+ }
+
+ }
+ } else { // this command layer handle is not responsible
+ // (wrong direction or wrong transaction ID)
+ Ret = kEplSdoComNotResponsible;
+ goto Exit;
+ }
+ break;
+ }
+
+ // connection closed event go back to kEplSdoComStateClientWaitInit
+ case kEplSdoComConEventConClosed:
+ { // connection closed by communication partner
+ // close sequence layer handle
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ // set handle to invalid and enter kEplSdoComStateClientWaitInit
+ pSdoComCon->m_SdoSeqConHdl |=
+ EPL_SDO_SEQ_INVALID_HDL;
+ // change state
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientWaitInit;
+
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode = 0;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferLowerLayerAbort);
+
+ goto Exit;
+
+ break;
+ }
+
+ // abort to send from higher layer
+ case kEplSdoComConEventAbort:
+ {
+ EplSdoComClientSendAbort(pSdoComCon,
+ *((DWORD *)
+ pSdoComCon->
+ m_pData));
+
+ // inc transaction id
+ pSdoComCon->m_bTransactionId++;
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode =
+ *((DWORD *) pSdoComCon->m_pData);
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferTxAborted);
+
+ break;
+ }
+
+ case kEplSdoComConEventInitError:
+ case kEplSdoComConEventTimeout:
+ {
+ // close sequence layer handle
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ pSdoComCon->m_SdoSeqConHdl |=
+ EPL_SDO_SEQ_INVALID_HDL;
+ // change state
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientWaitInit;
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode =
+ EPL_SDOAC_TIME_OUT;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferLowerLayerAbort);
+
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(SdoComConEvent_p)
+
+ break;
+ }
+
+ // process segmented transfer
+ case kEplSdoComStateClientSegmTrans:
+ {
+ // check events
+ switch (SdoComConEvent_p) {
+ // sned a frame
+ case kEplSdoComConEventSendFirst:
+ case kEplSdoComConEventAckReceived:
+ case kEplSdoComConEventFrameSended:
+ {
+ Ret = EplSdoComClientSend(pSdoComCon);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+ // check if read transfer finished
+ if ((pSdoComCon->m_uiTransSize == 0)
+ && (pSdoComCon->m_SdoServiceType ==
+ kEplSdoServiceReadByIndex)) {
+ // inc transaction id
+ pSdoComCon->m_bTransactionId++;
+ // change state
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientConnected;
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode =
+ 0;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferFinished);
+
+ goto Exit;
+ }
+
+ break;
+ }
+
+ // frame received
+ case kEplSdoComConEventRec:
+ {
+ // check if the frame is a response
+ bFlag =
+ AmiGetByteFromLe(&pAsySdoCom_p->
+ m_le_bFlags);
+ if (((bFlag & 0x80) != 0)
+ &&
+ (AmiGetByteFromLe
+ (&pAsySdoCom_p->
+ m_le_bTransactionId) ==
+ pSdoComCon->m_bTransactionId)) {
+ // check if abort or not
+ if ((bFlag & 0x40) != 0) {
+ // send acknowledge without any Command layer data
+ Ret =
+ EplSdoAsySeqSendData
+ (pSdoComCon->
+ m_SdoSeqConHdl, 0,
+ (tEplFrame *)
+ NULL);
+ // inc transaction id
+ pSdoComCon->
+ m_bTransactionId++;
+ // change state
+ pSdoComCon->
+ m_SdoComState =
+ kEplSdoComStateClientConnected;
+ // save abort code
+ pSdoComCon->
+ m_dwLastAbortCode =
+ AmiGetDwordFromLe
+ (&pAsySdoCom_p->
+ m_le_abCommandData
+ [0]);
+ // call callback of application
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p,
+ pSdoComCon,
+ kEplSdoComTransferRxAborted);
+
+ goto Exit;
+ } else { // normal frame received
+ // check frame
+ Ret =
+ EplSdoComClientProcessFrame
+ (SdoComCon_p,
+ pAsySdoCom_p);
+
+ // check if transfer ready
+ if (pSdoComCon->
+ m_uiTransSize ==
+ 0) {
+ // send acknowledge without any Command layer data
+ Ret =
+ EplSdoAsySeqSendData
+ (pSdoComCon->
+ m_SdoSeqConHdl,
+ 0,
+ (tEplFrame
+ *) NULL);
+ // inc transaction id
+ pSdoComCon->
+ m_bTransactionId++;
+ // change state
+ pSdoComCon->
+ m_SdoComState
+ =
+ kEplSdoComStateClientConnected;
+ // call callback of application
+ pSdoComCon->
+ m_dwLastAbortCode
+ = 0;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p,
+ pSdoComCon,
+ kEplSdoComTransferFinished);
+
+ }
+
+ }
+ }
+ break;
+ }
+
+ // connection closed event go back to kEplSdoComStateClientWaitInit
+ case kEplSdoComConEventConClosed:
+ { // connection closed by communication partner
+ // close sequence layer handle
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ // set handle to invalid and enter kEplSdoComStateClientWaitInit
+ pSdoComCon->m_SdoSeqConHdl |=
+ EPL_SDO_SEQ_INVALID_HDL;
+ // change state
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientWaitInit;
+ // inc transaction id
+ pSdoComCon->m_bTransactionId++;
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode = 0;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferFinished);
+
+ break;
+ }
+
+ // abort to send from higher layer
+ case kEplSdoComConEventAbort:
+ {
+ EplSdoComClientSendAbort(pSdoComCon,
+ *((DWORD *)
+ pSdoComCon->
+ m_pData));
+
+ // inc transaction id
+ pSdoComCon->m_bTransactionId++;
+ // change state
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientConnected;
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode =
+ *((DWORD *) pSdoComCon->m_pData);
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferTxAborted);
+
+ break;
+ }
+
+ case kEplSdoComConEventInitError:
+ case kEplSdoComConEventTimeout:
+ {
+ // close sequence layer handle
+ Ret =
+ EplSdoAsySeqDelCon(pSdoComCon->
+ m_SdoSeqConHdl);
+ pSdoComCon->m_SdoSeqConHdl |=
+ EPL_SDO_SEQ_INVALID_HDL;
+ // change state
+ pSdoComCon->m_SdoComState =
+ kEplSdoComStateClientWaitInit;
+ // call callback of application
+ pSdoComCon->m_dwLastAbortCode =
+ EPL_SDOAC_TIME_OUT;
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferLowerLayerAbort);
+
+ }
+
+ default:
+ // d.k. do nothing
+ break;
+
+ } // end of switch(SdoComConEvent_p)
+
+ break;
+ }
+#endif // endo of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+
+ } // end of switch(pSdoComCon->m_SdoComState)
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+ Exit:
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+ // leave critical section for process function
+ EPL_DBGLVL_SDO_TRACE0
+ ("\n\tLeaveCriticalSection EplSdoComProcessIntern\n\n");
+ LeaveCriticalSection(SdoComInstance_g.m_pCriticalSection);
+
+#endif
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComServerInitReadByIndex
+//
+// Description: function start the processing of an read by index command
+//
+//
+//
+// Parameters: pSdoComCon_p = pointer to control structure of connection
+// pAsySdoCom_p = pointer to received frame
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+static tEplKernel EplSdoComServerInitReadByIndex(tEplSdoComCon * pSdoComCon_p,
+ tEplAsySdoCom * pAsySdoCom_p)
+{
+ tEplKernel Ret;
+ unsigned int uiIndex;
+ unsigned int uiSubindex;
+ tEplObdSize EntrySize;
+ tEplObdAccess AccessType;
+ DWORD dwAbortCode;
+
+ dwAbortCode = 0;
+
+ // a init of a read could not be a segmented transfer
+ // -> no variable part of header
+
+ // get index and subindex
+ uiIndex = AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
+ uiSubindex = AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]);
+
+ // check accesstype of entry
+ // existens of entry
+//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType);
+/*#else
+ Ret = kEplObdSubindexNotExist;
+ AccessType = 0;
+#endif*/
+ if (Ret == kEplObdSubindexNotExist) { // subentry doesn't exist
+ dwAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST;
+ // send abort
+ pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort);
+ goto Exit;
+ } else if (Ret != kEplSuccessful) { // entry doesn't exist
+ dwAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST;
+ // send abort
+ pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort);
+ goto Exit;
+ }
+ // compare accesstype must be read or const
+ if (((AccessType & kEplObdAccRead) == 0)
+ && ((AccessType & kEplObdAccConst) == 0)) {
+
+ if ((AccessType & kEplObdAccWrite) != 0) {
+ // entry read a write only object
+ dwAbortCode = EPL_SDOAC_READ_TO_WRITE_ONLY_OBJ;
+ } else {
+ dwAbortCode = EPL_SDOAC_UNSUPPORTED_ACCESS;
+ }
+ // send abort
+ pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort);
+ goto Exit;
+ }
+ // save service
+ pSdoComCon_p->m_SdoServiceType = kEplSdoServiceReadByIndex;
+
+ // get size of object to see iof segmented or expedited transfer
+//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ EntrySize = EplObduGetDataSize(uiIndex, uiSubindex);
+/*#else
+ EntrySize = 0;
+#endif*/
+ if (EntrySize > EPL_SDO_MAX_PAYLOAD) { // segmented transfer
+ pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented;
+ // get pointer to object-entry data
+//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ pSdoComCon_p->m_pData =
+ EplObduGetObjectDataPtr(uiIndex, uiSubindex);
+//#endif
+ } else { // expedited transfer
+ pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
+ }
+
+ pSdoComCon_p->m_uiTransSize = EntrySize;
+ pSdoComCon_p->m_uiTransferredByte = 0;
+
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex, kEplSdoComSendTypeRes);
+ if (Ret != kEplSuccessful) {
+ // error -> abort
+ dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
+ // send abort
+ pSdoComCon_p->m_pData = (BYTE *) & dwAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort);
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComServerSendFrameIntern();
+//
+// Description: function creats and send a frame for server
+//
+//
+//
+// Parameters: pSdoComCon_p = pointer to control structure of connection
+// uiIndex_p = index to send if expedited transfer else 0
+// uiSubIndex_p = subindex to send if expedited transfer else 0
+// SendType_p = to of frame to send
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+static tEplKernel EplSdoComServerSendFrameIntern(tEplSdoComCon * pSdoComCon_p,
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ tEplSdoComSendType SendType_p)
+{
+ tEplKernel Ret;
+ BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE];
+ tEplFrame *pFrame;
+ tEplAsySdoCom *pCommandFrame;
+ unsigned int uiSizeOfFrame;
+ BYTE bFlag;
+
+ Ret = kEplSuccessful;
+
+ pFrame = (tEplFrame *) & abFrame[0];
+
+ EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
+
+ // build generic part of frame
+ // get pointer to command layerpart of frame
+ pCommandFrame =
+ &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
+ m_le_abSdoSeqPayload;
+ AmiSetByteToLe(&pCommandFrame->m_le_bCommandId,
+ pSdoComCon_p->m_SdoServiceType);
+ AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId,
+ pSdoComCon_p->m_bTransactionId);
+
+ // set size to header size
+ uiSizeOfFrame = 8;
+
+ // check SendType
+ switch (SendType_p) {
+ // requestframe to send
+ case kEplSdoComSendTypeReq:
+ {
+ // nothing to do for server
+ //-> error
+ Ret = kEplSdoComInvalidSendType;
+ break;
+ }
+
+ // response without data to send
+ case kEplSdoComSendTypeAckRes:
+ {
+ // set response flag
+ AmiSetByteToLe(&pCommandFrame->m_le_bFlags, 0x80);
+
+ // send frame
+ Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
+ uiSizeOfFrame, pFrame);
+
+ break;
+ }
+
+ // responsframe to send
+ case kEplSdoComSendTypeRes:
+ {
+ // set response flag
+ bFlag = AmiGetByteFromLe(&pCommandFrame->m_le_bFlags);
+ bFlag |= 0x80;
+ AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag);
+
+ // check type of resonse
+ if (pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) { // Expedited transfer
+ // copy data in frame
+//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ Ret = EplObduReadEntryToLe(uiIndex_p,
+ uiSubIndex_p,
+ &pCommandFrame->
+ m_le_abCommandData
+ [0],
+ (tEplObdSize *) &
+ pSdoComCon_p->
+ m_uiTransSize);
+ if (Ret != kEplSuccessful) {
+ goto Exit;
+ }
+//#endif
+
+ // set size of frame
+ AmiSetWordToLe(&pCommandFrame->
+ m_le_wSegmentSize,
+ (WORD) pSdoComCon_p->
+ m_uiTransSize);
+
+ // correct byte-counter
+ uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
+ pSdoComCon_p->m_uiTransferredByte +=
+ pSdoComCon_p->m_uiTransSize;
+ pSdoComCon_p->m_uiTransSize = 0;
+
+ // send frame
+ uiSizeOfFrame += pSdoComCon_p->m_uiTransSize;
+ Ret =
+ EplSdoAsySeqSendData(pSdoComCon_p->
+ m_SdoSeqConHdl,
+ uiSizeOfFrame, pFrame);
+ } else if (pSdoComCon_p->m_SdoTransType == kEplSdoTransSegmented) { // segmented transfer
+ // distinguish between init, segment and complete
+ if (pSdoComCon_p->m_uiTransferredByte == 0) { // init
+ // set init flag
+ bFlag =
+ AmiGetByteFromLe(&pCommandFrame->
+ m_le_bFlags);
+ bFlag |= 0x10;
+ AmiSetByteToLe(&pCommandFrame->
+ m_le_bFlags, bFlag);
+ // init variable header
+ AmiSetDwordToLe(&pCommandFrame->
+ m_le_abCommandData[0],
+ pSdoComCon_p->
+ m_uiTransSize);
+ // copy data in frame
+ EPL_MEMCPY(&pCommandFrame->
+ m_le_abCommandData[4],
+ pSdoComCon_p->m_pData,
+ (EPL_SDO_MAX_PAYLOAD - 4));
+
+ // correct byte-counter
+ pSdoComCon_p->m_uiTransSize -=
+ (EPL_SDO_MAX_PAYLOAD - 4);
+ pSdoComCon_p->m_uiTransferredByte +=
+ (EPL_SDO_MAX_PAYLOAD - 4);
+ // move data pointer
+ pSdoComCon_p->m_pData +=
+ (EPL_SDO_MAX_PAYLOAD - 4);
+
+ // set segment size
+ AmiSetWordToLe(&pCommandFrame->
+ m_le_wSegmentSize,
+ (EPL_SDO_MAX_PAYLOAD -
+ 4));
+
+ // send frame
+ uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
+ Ret =
+ EplSdoAsySeqSendData(pSdoComCon_p->
+ m_SdoSeqConHdl,
+ uiSizeOfFrame,
+ pFrame);
+
+ } else
+ if ((pSdoComCon_p->m_uiTransferredByte > 0)
+ && (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD)) { // segment
+ // set segment flag
+ bFlag =
+ AmiGetByteFromLe(&pCommandFrame->
+ m_le_bFlags);
+ bFlag |= 0x20;
+ AmiSetByteToLe(&pCommandFrame->
+ m_le_bFlags, bFlag);
+
+ // copy data in frame
+ EPL_MEMCPY(&pCommandFrame->
+ m_le_abCommandData[0],
+ pSdoComCon_p->m_pData,
+ EPL_SDO_MAX_PAYLOAD);
+
+ // correct byte-counter
+ pSdoComCon_p->m_uiTransSize -=
+ EPL_SDO_MAX_PAYLOAD;
+ pSdoComCon_p->m_uiTransferredByte +=
+ EPL_SDO_MAX_PAYLOAD;
+ // move data pointer
+ pSdoComCon_p->m_pData +=
+ EPL_SDO_MAX_PAYLOAD;
+
+ // set segment size
+ AmiSetWordToLe(&pCommandFrame->
+ m_le_wSegmentSize,
+ EPL_SDO_MAX_PAYLOAD);
+
+ // send frame
+ uiSizeOfFrame += EPL_SDO_MAX_PAYLOAD;
+ Ret =
+ EplSdoAsySeqSendData(pSdoComCon_p->
+ m_SdoSeqConHdl,
+ uiSizeOfFrame,
+ pFrame);
+ } else {
+ if ((pSdoComCon_p->m_uiTransSize == 0)
+ && (pSdoComCon_p->
+ m_SdoServiceType !=
+ kEplSdoServiceWriteByIndex)) {
+ goto Exit;
+ }
+ // complete
+ // set segment complete flag
+ bFlag =
+ AmiGetByteFromLe(&pCommandFrame->
+ m_le_bFlags);
+ bFlag |= 0x30;
+ AmiSetByteToLe(&pCommandFrame->
+ m_le_bFlags, bFlag);
+
+ // copy data in frame
+ EPL_MEMCPY(&pCommandFrame->
+ m_le_abCommandData[0],
+ pSdoComCon_p->m_pData,
+ pSdoComCon_p->m_uiTransSize);
+
+ // correct byte-counter
+ pSdoComCon_p->m_uiTransferredByte +=
+ pSdoComCon_p->m_uiTransSize;
+
+ // move data pointer
+ pSdoComCon_p->m_pData +=
+ pSdoComCon_p->m_uiTransSize;
+
+ // set segment size
+ AmiSetWordToLe(&pCommandFrame->
+ m_le_wSegmentSize,
+ (WORD) pSdoComCon_p->
+ m_uiTransSize);
+
+ // send frame
+ uiSizeOfFrame +=
+ pSdoComCon_p->m_uiTransSize;
+ pSdoComCon_p->m_uiTransSize = 0;
+ Ret =
+ EplSdoAsySeqSendData(pSdoComCon_p->
+ m_SdoSeqConHdl,
+ uiSizeOfFrame,
+ pFrame);
+ }
+
+ }
+ break;
+ }
+ // abort to send
+ case kEplSdoComSendTypeAbort:
+ {
+ // set response and abort flag
+ bFlag = AmiGetByteFromLe(&pCommandFrame->m_le_bFlags);
+ bFlag |= 0xC0;
+ AmiSetByteToLe(&pCommandFrame->m_le_bFlags, bFlag);
+
+ // copy abortcode to frame
+ AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0],
+ *((DWORD *) pSdoComCon_p->m_pData));
+
+ // set size of segment
+ AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize,
+ sizeof(DWORD));
+
+ // update counter
+ pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD);
+ pSdoComCon_p->m_uiTransSize = 0;
+
+ // calc framesize
+ uiSizeOfFrame += sizeof(DWORD);
+ Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
+ uiSizeOfFrame, pFrame);
+ break;
+ }
+ } // end of switch(SendType_p)
+
+ Exit:
+ return Ret;
+}
+#endif
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComServerInitWriteByIndex
+//
+// Description: function start the processing of an write by index command
+//
+//
+//
+// Parameters: pSdoComCon_p = pointer to control structure of connection
+// pAsySdoCom_p = pointer to received frame
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOS)) != 0)
+static tEplKernel EplSdoComServerInitWriteByIndex(tEplSdoComCon * pSdoComCon_p,
+ tEplAsySdoCom * pAsySdoCom_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiIndex;
+ unsigned int uiSubindex;
+ unsigned int uiBytesToTransfer;
+ tEplObdSize EntrySize;
+ tEplObdAccess AccessType;
+ DWORD dwAbortCode;
+ BYTE *pbSrcData;
+
+ dwAbortCode = 0;
+
+ // a init of a write
+ // -> variable part of header possible
+
+ // check if expedited or segmented transfer
+ if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x10) { // initiate segmented transfer
+ pSdoComCon_p->m_SdoTransType = kEplSdoTransSegmented;
+ // get index and subindex
+ uiIndex =
+ AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[4]);
+ uiSubindex =
+ AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[6]);
+ // get source-pointer for copy
+ pbSrcData = &pAsySdoCom_p->m_le_abCommandData[8];
+ // save size
+ pSdoComCon_p->m_uiTransSize =
+ AmiGetDwordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
+
+ } else if ((pAsySdoCom_p->m_le_bFlags & 0x30) == 0x00) { // expedited transfer
+ pSdoComCon_p->m_SdoTransType = kEplSdoTransExpedited;
+ // get index and subindex
+ uiIndex =
+ AmiGetWordFromLe(&pAsySdoCom_p->m_le_abCommandData[0]);
+ uiSubindex =
+ AmiGetByteFromLe(&pAsySdoCom_p->m_le_abCommandData[2]);
+ // get source-pointer for copy
+ pbSrcData = &pAsySdoCom_p->m_le_abCommandData[4];
+ // save size
+ pSdoComCon_p->m_uiTransSize =
+ AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
+ // subtract header
+ pSdoComCon_p->m_uiTransSize -= 4;
+
+ } else {
+ // just ignore any other transfer type
+ goto Exit;
+ }
+
+ // check accesstype of entry
+ // existens of entry
+//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ Ret = EplObduGetAccessType(uiIndex, uiSubindex, &AccessType);
+/*#else
+ Ret = kEplObdSubindexNotExist;
+ AccessType = 0;
+#endif*/
+ if (Ret == kEplObdSubindexNotExist) { // subentry doesn't exist
+ pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_SUB_INDEX_NOT_EXIST;
+ // send abort
+ // d.k. This is wrong: k.t. not needed send abort on end of write
+ /*pSdoComCon_p->m_pData = (BYTE*)pSdoComCon_p->m_dwLastAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort); */
+ goto Abort;
+ } else if (Ret != kEplSuccessful) { // entry doesn't exist
+ pSdoComCon_p->m_dwLastAbortCode = EPL_SDOAC_OBJECT_NOT_EXIST;
+ // send abort
+ // d.k. This is wrong: k.t. not needed send abort on end of write
+ /*
+ pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort); */
+ goto Abort;
+ }
+ // compare accesstype must be read
+ if ((AccessType & kEplObdAccWrite) == 0) {
+
+ if ((AccessType & kEplObdAccRead) != 0) {
+ // entry write a read only object
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_WRITE_TO_READ_ONLY_OBJ;
+ } else {
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_UNSUPPORTED_ACCESS;
+ }
+ // send abort
+ // d.k. This is wrong: k.t. not needed send abort on end of write
+ /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort); */
+ goto Abort;
+ }
+ // save service
+ pSdoComCon_p->m_SdoServiceType = kEplSdoServiceWriteByIndex;
+
+ pSdoComCon_p->m_uiTransferredByte = 0;
+
+ // write data to OD
+ if (pSdoComCon_p->m_SdoTransType == kEplSdoTransExpedited) { // expedited transfer
+ // size checking is done by EplObduWriteEntryFromLe()
+
+//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ Ret = EplObduWriteEntryFromLe(uiIndex,
+ uiSubindex,
+ pbSrcData,
+ pSdoComCon_p->m_uiTransSize);
+ switch (Ret) {
+ case kEplSuccessful:
+ {
+ break;
+ }
+
+ case kEplObdAccessViolation:
+ {
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_UNSUPPORTED_ACCESS;
+ // send abort
+ goto Abort;
+ }
+
+ case kEplObdValueLengthError:
+ {
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_DATA_TYPE_LENGTH_NOT_MATCH;
+ // send abort
+ goto Abort;
+ }
+
+ case kEplObdValueTooHigh:
+ {
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_VALUE_RANGE_TOO_HIGH;
+ // send abort
+ goto Abort;
+ }
+
+ case kEplObdValueTooLow:
+ {
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_VALUE_RANGE_TOO_LOW;
+ // send abort
+ goto Abort;
+ }
+
+ default:
+ {
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_GENERAL_ERROR;
+ // send abort
+ goto Abort;
+ }
+ }
+//#endif
+ // send command acknowledge
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ 0,
+ 0,
+ kEplSdoComSendTypeAckRes);
+
+ pSdoComCon_p->m_uiTransSize = 0;
+ goto Exit;
+ } else {
+ // get size of the object to check if it fits
+ // because we directly write to the destination memory
+ // d.k. no one calls the user OD callback function
+
+ //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ EntrySize = EplObduGetDataSize(uiIndex, uiSubindex);
+ /*#else
+ EntrySize = 0;
+ #endif */
+ if (EntrySize < pSdoComCon_p->m_uiTransSize) { // parameter too big
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH;
+ // send abort
+ // d.k. This is wrong: k.t. not needed send abort on end of write
+ /*pSdoComCon_p->m_pData = (BYTE*)&dwAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort); */
+ goto Abort;
+ }
+
+ uiBytesToTransfer =
+ AmiGetWordFromLe(&pAsySdoCom_p->m_le_wSegmentSize);
+ // eleminate header (Command header (8) + variable part (4) + Command header (4))
+ uiBytesToTransfer -= 16;
+ // get pointer to object entry
+//#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+ pSdoComCon_p->m_pData = EplObduGetObjectDataPtr(uiIndex,
+ uiSubindex);
+//#endif
+ if (pSdoComCon_p->m_pData == NULL) {
+ pSdoComCon_p->m_dwLastAbortCode =
+ EPL_SDOAC_GENERAL_ERROR;
+ // send abort
+ // d.k. This is wrong: k.t. not needed send abort on end of write
+/* pSdoComCon_p->m_pData = (BYTE*)&pSdoComCon_p->m_dwLastAbortCode;
+ Ret = EplSdoComServerSendFrameIntern(pSdoComCon_p,
+ uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort);*/
+ goto Abort;
+ }
+ // copy data
+ EPL_MEMCPY(pSdoComCon_p->m_pData, pbSrcData, uiBytesToTransfer);
+
+ // update internal counter
+ pSdoComCon_p->m_uiTransferredByte = uiBytesToTransfer;
+ pSdoComCon_p->m_uiTransSize -= uiBytesToTransfer;
+
+ // update target pointer
+ ( /*(BYTE*) */ pSdoComCon_p->m_pData) += uiBytesToTransfer;
+
+ // send acknowledge without any Command layer data
+ Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
+ 0, (tEplFrame *) NULL);
+ goto Exit;
+ }
+
+ Abort:
+ if (pSdoComCon_p->m_dwLastAbortCode != 0) {
+ // send abort
+ pSdoComCon_p->m_pData =
+ (BYTE *) & pSdoComCon_p->m_dwLastAbortCode;
+ Ret =
+ EplSdoComServerSendFrameIntern(pSdoComCon_p, uiIndex,
+ uiSubindex,
+ kEplSdoComSendTypeAbort);
+
+ // reset abort code
+ pSdoComCon_p->m_dwLastAbortCode = 0;
+ pSdoComCon_p->m_uiTransSize = 0;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComClientSend
+//
+// Description: function starts an sdo transfer an send all further frames
+//
+//
+//
+// Parameters: pSdoComCon_p = pointer to control structure of connection
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+static tEplKernel EplSdoComClientSend(tEplSdoComCon * pSdoComCon_p)
+{
+ tEplKernel Ret;
+ BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE];
+ tEplFrame *pFrame;
+ tEplAsySdoCom *pCommandFrame;
+ unsigned int uiSizeOfFrame;
+ BYTE bFlags;
+ BYTE *pbPayload;
+
+ Ret = kEplSuccessful;
+
+ pFrame = (tEplFrame *) & abFrame[0];
+
+ EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
+
+ // build generic part of frame
+ // get pointer to command layerpart of frame
+ pCommandFrame =
+ &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
+ m_le_abSdoSeqPayload;
+ AmiSetByteToLe(&pCommandFrame->m_le_bCommandId,
+ pSdoComCon_p->m_SdoServiceType);
+ AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId,
+ pSdoComCon_p->m_bTransactionId);
+
+ // set size constant part of header
+ uiSizeOfFrame = 8;
+
+ // check if first frame to send -> command header needed
+ if (pSdoComCon_p->m_uiTransSize > 0) {
+ if (pSdoComCon_p->m_uiTransferredByte == 0) { // start SDO transfer
+ // check if segmented or expedited transfer
+ // only for write commands
+ switch (pSdoComCon_p->m_SdoServiceType) {
+ case kEplSdoServiceReadByIndex:
+ { // first frame of read access always expedited
+ pSdoComCon_p->m_SdoTransType =
+ kEplSdoTransExpedited;
+ pbPayload =
+ &pCommandFrame->
+ m_le_abCommandData[0];
+ // fill rest of header
+ AmiSetWordToLe(&pCommandFrame->
+ m_le_wSegmentSize, 4);
+
+ // create command header
+ AmiSetWordToLe(pbPayload,
+ (WORD) pSdoComCon_p->
+ m_uiTargetIndex);
+ pbPayload += 2;
+ AmiSetByteToLe(pbPayload,
+ (BYTE) pSdoComCon_p->
+ m_uiTargetSubIndex);
+ // calc size
+ uiSizeOfFrame += 4;
+
+ // set pSdoComCon_p->m_uiTransferredByte to one
+ pSdoComCon_p->m_uiTransferredByte = 1;
+ break;
+ }
+
+ case kEplSdoServiceWriteByIndex:
+ {
+ if (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD) { // segmented transfer
+ // -> variable part of header needed
+ // save that transfer is segmented
+ pSdoComCon_p->m_SdoTransType =
+ kEplSdoTransSegmented;
+ // fill variable part of header
+ AmiSetDwordToLe(&pCommandFrame->
+ m_le_abCommandData
+ [0],
+ pSdoComCon_p->
+ m_uiTransSize);
+ // set pointer to real payload
+ pbPayload =
+ &pCommandFrame->
+ m_le_abCommandData[4];
+ // fill rest of header
+ AmiSetWordToLe(&pCommandFrame->
+ m_le_wSegmentSize,
+ EPL_SDO_MAX_PAYLOAD);
+ bFlags = 0x10;
+ AmiSetByteToLe(&pCommandFrame->
+ m_le_bFlags,
+ bFlags);
+ // create command header
+ AmiSetWordToLe(pbPayload,
+ (WORD)
+ pSdoComCon_p->
+ m_uiTargetIndex);
+ pbPayload += 2;
+ AmiSetByteToLe(pbPayload,
+ (BYTE)
+ pSdoComCon_p->
+ m_uiTargetSubIndex);
+ // on byte for reserved
+ pbPayload += 2;
+ // calc size
+ uiSizeOfFrame +=
+ EPL_SDO_MAX_PAYLOAD;
+
+ // copy payload
+ EPL_MEMCPY(pbPayload,
+ pSdoComCon_p->
+ m_pData,
+ (EPL_SDO_MAX_PAYLOAD
+ - 8));
+ pSdoComCon_p->m_pData +=
+ (EPL_SDO_MAX_PAYLOAD - 8);
+ // correct intern counter
+ pSdoComCon_p->m_uiTransSize -=
+ (EPL_SDO_MAX_PAYLOAD - 8);
+ pSdoComCon_p->
+ m_uiTransferredByte =
+ (EPL_SDO_MAX_PAYLOAD - 8);
+
+ } else { // expedited trandsfer
+ // save that transfer is expedited
+ pSdoComCon_p->m_SdoTransType =
+ kEplSdoTransExpedited;
+ pbPayload =
+ &pCommandFrame->
+ m_le_abCommandData[0];
+
+ // create command header
+ AmiSetWordToLe(pbPayload,
+ (WORD)
+ pSdoComCon_p->
+ m_uiTargetIndex);
+ pbPayload += 2;
+ AmiSetByteToLe(pbPayload,
+ (BYTE)
+ pSdoComCon_p->
+ m_uiTargetSubIndex);
+ // + 2 -> one byte for subindex and one byte reserved
+ pbPayload += 2;
+ // copy data
+ EPL_MEMCPY(pbPayload,
+ pSdoComCon_p->
+ m_pData,
+ pSdoComCon_p->
+ m_uiTransSize);
+ // calc size
+ uiSizeOfFrame +=
+ (4 +
+ pSdoComCon_p->
+ m_uiTransSize);
+ // fill rest of header
+ AmiSetWordToLe(&pCommandFrame->
+ m_le_wSegmentSize,
+ (WORD) (4 +
+ pSdoComCon_p->
+ m_uiTransSize));
+
+ pSdoComCon_p->
+ m_uiTransferredByte =
+ pSdoComCon_p->m_uiTransSize;
+ pSdoComCon_p->m_uiTransSize = 0;
+ }
+ break;
+ }
+
+ case kEplSdoServiceNIL:
+ default:
+ // invalid service requested
+ Ret = kEplSdoComInvalidServiceType;
+ goto Exit;
+ } // end of switch(pSdoComCon_p->m_SdoServiceType)
+ } else // (pSdoComCon_p->m_uiTransferredByte > 0)
+ { // continue SDO transfer
+ switch (pSdoComCon_p->m_SdoServiceType) {
+ // for expedited read is nothing to do
+ // -> server sends data
+
+ case kEplSdoServiceWriteByIndex:
+ { // send next frame
+ if (pSdoComCon_p->m_SdoTransType ==
+ kEplSdoTransSegmented) {
+ if (pSdoComCon_p->m_uiTransSize > EPL_SDO_MAX_PAYLOAD) { // next segment
+ pbPayload =
+ &pCommandFrame->
+ m_le_abCommandData
+ [0];
+ // fill rest of header
+ AmiSetWordToLe
+ (&pCommandFrame->
+ m_le_wSegmentSize,
+ EPL_SDO_MAX_PAYLOAD);
+ bFlags = 0x20;
+ AmiSetByteToLe
+ (&pCommandFrame->
+ m_le_bFlags,
+ bFlags);
+ // copy data
+ EPL_MEMCPY(pbPayload,
+ pSdoComCon_p->
+ m_pData,
+ EPL_SDO_MAX_PAYLOAD);
+ pSdoComCon_p->m_pData +=
+ EPL_SDO_MAX_PAYLOAD;
+ // correct intern counter
+ pSdoComCon_p->
+ m_uiTransSize -=
+ EPL_SDO_MAX_PAYLOAD;
+ pSdoComCon_p->
+ m_uiTransferredByte
+ =
+ EPL_SDO_MAX_PAYLOAD;
+ // calc size
+ uiSizeOfFrame +=
+ EPL_SDO_MAX_PAYLOAD;
+
+ } else { // end of transfer
+ pbPayload =
+ &pCommandFrame->
+ m_le_abCommandData
+ [0];
+ // fill rest of header
+ AmiSetWordToLe
+ (&pCommandFrame->
+ m_le_wSegmentSize,
+ (WORD)
+ pSdoComCon_p->
+ m_uiTransSize);
+ bFlags = 0x30;
+ AmiSetByteToLe
+ (&pCommandFrame->
+ m_le_bFlags,
+ bFlags);
+ // copy data
+ EPL_MEMCPY(pbPayload,
+ pSdoComCon_p->
+ m_pData,
+ pSdoComCon_p->
+ m_uiTransSize);
+ pSdoComCon_p->m_pData +=
+ pSdoComCon_p->
+ m_uiTransSize;
+ // calc size
+ uiSizeOfFrame +=
+ pSdoComCon_p->
+ m_uiTransSize;
+ // correct intern counter
+ pSdoComCon_p->
+ m_uiTransSize = 0;
+ pSdoComCon_p->
+ m_uiTransferredByte
+ =
+ pSdoComCon_p->
+ m_uiTransSize;
+
+ }
+ } else {
+ goto Exit;
+ }
+ break;
+ }
+ default:
+ {
+ goto Exit;
+ }
+ } // end of switch(pSdoComCon_p->m_SdoServiceType)
+ }
+ } else {
+ goto Exit;
+ }
+
+ // call send function of lower layer
+ switch (pSdoComCon_p->m_SdoProtType) {
+ case kEplSdoTypeAsnd:
+ case kEplSdoTypeUdp:
+ {
+ Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
+ uiSizeOfFrame, pFrame);
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplSdoComUnsupportedProt;
+ }
+ } // end of switch(pSdoComCon_p->m_SdoProtType)
+
+ Exit:
+ return Ret;
+
+}
+#endif
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComClientProcessFrame
+//
+// Description: function process a received frame
+//
+//
+//
+// Parameters: SdoComCon_p = connection handle
+// pAsySdoCom_p = pointer to frame to process
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+static tEplKernel EplSdoComClientProcessFrame(tEplSdoComConHdl SdoComCon_p,
+ tEplAsySdoCom * pAsySdoCom_p)
+{
+ tEplKernel Ret;
+ BYTE bBuffer;
+ unsigned int uiBuffer;
+ unsigned int uiDataSize;
+ unsigned long ulBuffer;
+ tEplSdoComCon *pSdoComCon;
+
+ Ret = kEplSuccessful;
+
+ // get pointer to control structure
+ pSdoComCon = &SdoComInstance_g.m_SdoComCon[SdoComCon_p];
+
+ // check if transaction Id fit
+ bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bTransactionId);
+ if (pSdoComCon->m_bTransactionId != bBuffer) {
+ // incorrect transaction id
+
+ // if running transfer
+ if ((pSdoComCon->m_uiTransferredByte != 0)
+ && (pSdoComCon->m_uiTransSize != 0)) {
+ pSdoComCon->m_dwLastAbortCode = EPL_SDOAC_GENERAL_ERROR;
+ // -> send abort
+ EplSdoComClientSendAbort(pSdoComCon,
+ pSdoComCon->m_dwLastAbortCode);
+ // call callback of application
+ Ret =
+ EplSdoComTransferFinished(SdoComCon_p, pSdoComCon,
+ kEplSdoComTransferTxAborted);
+ }
+
+ } else { // check if correct command
+ bBuffer = AmiGetByteFromLe(&pAsySdoCom_p->m_le_bCommandId);
+ if (pSdoComCon->m_SdoServiceType != bBuffer) {
+ // incorrect command
+ // if running transfer
+ if ((pSdoComCon->m_uiTransferredByte != 0)
+ && (pSdoComCon->m_uiTransSize != 0)) {
+ pSdoComCon->m_dwLastAbortCode =
+ EPL_SDOAC_GENERAL_ERROR;
+ // -> send abort
+ EplSdoComClientSendAbort(pSdoComCon,
+ pSdoComCon->
+ m_dwLastAbortCode);
+ // call callback of application
+ Ret =
+ EplSdoComTransferFinished(SdoComCon_p,
+ pSdoComCon,
+ kEplSdoComTransferTxAborted);
+ }
+
+ } else { // switch on command
+ switch (pSdoComCon->m_SdoServiceType) {
+ case kEplSdoServiceWriteByIndex:
+ { // check if confirmation from server
+ // nothing more to do
+ break;
+ }
+
+ case kEplSdoServiceReadByIndex:
+ { // check if it is an segmented or an expedited transfer
+ bBuffer =
+ AmiGetByteFromLe(&pAsySdoCom_p->
+ m_le_bFlags);
+ // mask uninteressting bits
+ bBuffer &= 0x30;
+ switch (bBuffer) {
+ // expedited transfer
+ case 0x00:
+ {
+ // check size of buffer
+ uiBuffer =
+ AmiGetWordFromLe
+ (&pAsySdoCom_p->
+ m_le_wSegmentSize);
+ if (uiBuffer > pSdoComCon->m_uiTransSize) { // buffer provided by the application is to small
+ // copy only a part
+ uiDataSize =
+ pSdoComCon->
+ m_uiTransSize;
+ } else { // buffer fits
+ uiDataSize =
+ uiBuffer;
+ }
+
+ // copy data
+ EPL_MEMCPY(pSdoComCon->
+ m_pData,
+ &pAsySdoCom_p->
+ m_le_abCommandData
+ [0],
+ uiDataSize);
+
+ // correct counter
+ pSdoComCon->
+ m_uiTransSize = 0;
+ pSdoComCon->
+ m_uiTransferredByte
+ = uiDataSize;
+ break;
+ }
+
+ // start of a segmented transfer
+ case 0x10:
+ { // get total size of transfer
+ ulBuffer =
+ AmiGetDwordFromLe
+ (&pAsySdoCom_p->
+ m_le_abCommandData
+ [0]);
+ if (ulBuffer <= pSdoComCon->m_uiTransSize) { // buffer fit
+ pSdoComCon->
+ m_uiTransSize
+ =
+ (unsigned
+ int)
+ ulBuffer;
+ } else { // buffer to small
+ // send abort
+ pSdoComCon->
+ m_dwLastAbortCode
+ =
+ EPL_SDOAC_DATA_TYPE_LENGTH_TOO_HIGH;
+ // -> send abort
+ EplSdoComClientSendAbort
+ (pSdoComCon,
+ pSdoComCon->
+ m_dwLastAbortCode);
+ // call callback of application
+ Ret =
+ EplSdoComTransferFinished
+ (SdoComCon_p,
+ pSdoComCon,
+ kEplSdoComTransferRxAborted);
+ goto Exit;
+ }
+
+ // get segment size
+ // check size of buffer
+ uiBuffer =
+ AmiGetWordFromLe
+ (&pAsySdoCom_p->
+ m_le_wSegmentSize);
+ // subtract size of vaiable header from datasize
+ uiBuffer -= 4;
+ // copy data
+ EPL_MEMCPY(pSdoComCon->
+ m_pData,
+ &pAsySdoCom_p->
+ m_le_abCommandData
+ [4],
+ uiBuffer);
+
+ // correct counter an pointer
+ pSdoComCon->m_pData +=
+ uiBuffer;
+ pSdoComCon->
+ m_uiTransferredByte
+ += uiBuffer;
+ pSdoComCon->
+ m_uiTransSize -=
+ uiBuffer;
+
+ break;
+ }
+
+ // segment
+ case 0x20:
+ {
+ // get segment size
+ // check size of buffer
+ uiBuffer =
+ AmiGetWordFromLe
+ (&pAsySdoCom_p->
+ m_le_wSegmentSize);
+ // check if data to copy fit to buffer
+ if (uiBuffer >= pSdoComCon->m_uiTransSize) { // to much data
+ uiBuffer =
+ (pSdoComCon->
+ m_uiTransSize
+ - 1);
+ }
+ // copy data
+ EPL_MEMCPY(pSdoComCon->
+ m_pData,
+ &pAsySdoCom_p->
+ m_le_abCommandData
+ [0],
+ uiBuffer);
+
+ // correct counter an pointer
+ pSdoComCon->m_pData +=
+ uiBuffer;
+ pSdoComCon->
+ m_uiTransferredByte
+ += uiBuffer;
+ pSdoComCon->
+ m_uiTransSize -=
+ uiBuffer;
+ break;
+ }
+
+ // last segment
+ case 0x30:
+ {
+ // get segment size
+ // check size of buffer
+ uiBuffer =
+ AmiGetWordFromLe
+ (&pAsySdoCom_p->
+ m_le_wSegmentSize);
+ // check if data to copy fit to buffer
+ if (uiBuffer > pSdoComCon->m_uiTransSize) { // to much data
+ uiBuffer =
+ (pSdoComCon->
+ m_uiTransSize
+ - 1);
+ }
+ // copy data
+ EPL_MEMCPY(pSdoComCon->
+ m_pData,
+ &pAsySdoCom_p->
+ m_le_abCommandData
+ [0],
+ uiBuffer);
+
+ // correct counter an pointer
+ pSdoComCon->m_pData +=
+ uiBuffer;
+ pSdoComCon->
+ m_uiTransferredByte
+ += uiBuffer;
+ pSdoComCon->
+ m_uiTransSize = 0;
+
+ break;
+ }
+ } // end of switch(bBuffer & 0x30)
+
+ break;
+ }
+
+ case kEplSdoServiceNIL:
+ default:
+ // invalid service requested
+ // $$$ d.k. What should we do?
+ break;
+ } // end of switch(pSdoComCon->m_SdoServiceType)
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComClientSendAbort
+//
+// Description: function send a abort message
+//
+//
+//
+// Parameters: pSdoComCon_p = pointer to control structure of connection
+// dwAbortCode_p = Sdo abort code
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+static tEplKernel EplSdoComClientSendAbort(tEplSdoComCon * pSdoComCon_p,
+ DWORD dwAbortCode_p)
+{
+ tEplKernel Ret;
+ BYTE abFrame[EPL_MAX_SDO_FRAME_SIZE];
+ tEplFrame *pFrame;
+ tEplAsySdoCom *pCommandFrame;
+ unsigned int uiSizeOfFrame;
+
+ Ret = kEplSuccessful;
+
+ pFrame = (tEplFrame *) & abFrame[0];
+
+ EPL_MEMSET(&abFrame[0], 0x00, sizeof(abFrame));
+
+ // build generic part of frame
+ // get pointer to command layerpart of frame
+ pCommandFrame =
+ &pFrame->m_Data.m_Asnd.m_Payload.m_SdoSequenceFrame.
+ m_le_abSdoSeqPayload;
+ AmiSetByteToLe(&pCommandFrame->m_le_bCommandId,
+ pSdoComCon_p->m_SdoServiceType);
+ AmiSetByteToLe(&pCommandFrame->m_le_bTransactionId,
+ pSdoComCon_p->m_bTransactionId);
+
+ uiSizeOfFrame = 8;
+
+ // set response and abort flag
+ pCommandFrame->m_le_bFlags |= 0x40;
+
+ // copy abortcode to frame
+ AmiSetDwordToLe(&pCommandFrame->m_le_abCommandData[0], dwAbortCode_p);
+
+ // set size of segment
+ AmiSetWordToLe(&pCommandFrame->m_le_wSegmentSize, sizeof(DWORD));
+
+ // update counter
+ pSdoComCon_p->m_uiTransferredByte = sizeof(DWORD);
+ pSdoComCon_p->m_uiTransSize = 0;
+
+ // calc framesize
+ uiSizeOfFrame += sizeof(DWORD);
+
+ // save abort code
+ pSdoComCon_p->m_dwLastAbortCode = dwAbortCode_p;
+
+ // call send function of lower layer
+ switch (pSdoComCon_p->m_SdoProtType) {
+ case kEplSdoTypeAsnd:
+ case kEplSdoTypeUdp:
+ {
+ Ret = EplSdoAsySeqSendData(pSdoComCon_p->m_SdoSeqConHdl,
+ uiSizeOfFrame, pFrame);
+ break;
+ }
+
+ default:
+ {
+ Ret = kEplSdoComUnsupportedProt;
+ }
+ } // end of switch(pSdoComCon_p->m_SdoProtType)
+
+ return Ret;
+}
+#endif
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoComTransferFinished
+//
+// Description: calls callback function of application if available
+// and clears entry in control structure
+//
+// Parameters: pSdoComCon_p = pointer to control structure of connection
+// SdoComConState_p = state of SDO transfer
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel EplSdoComTransferFinished(tEplSdoComConHdl SdoComCon_p,
+ tEplSdoComCon * pSdoComCon_p,
+ tEplSdoComConState SdoComConState_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ if (pSdoComCon_p->m_pfnTransferFinished != NULL) {
+ tEplSdoFinishedCb pfnTransferFinished;
+ tEplSdoComFinished SdoComFinished;
+
+ SdoComFinished.m_pUserArg = pSdoComCon_p->m_pUserArg;
+ SdoComFinished.m_uiNodeId = pSdoComCon_p->m_uiNodeId;
+ SdoComFinished.m_uiTargetIndex = pSdoComCon_p->m_uiTargetIndex;
+ SdoComFinished.m_uiTargetSubIndex =
+ pSdoComCon_p->m_uiTargetSubIndex;
+ SdoComFinished.m_uiTransferredByte =
+ pSdoComCon_p->m_uiTransferredByte;
+ SdoComFinished.m_dwAbortCode = pSdoComCon_p->m_dwLastAbortCode;
+ SdoComFinished.m_SdoComConHdl = SdoComCon_p;
+ SdoComFinished.m_SdoComConState = SdoComConState_p;
+ if (pSdoComCon_p->m_SdoServiceType ==
+ kEplSdoServiceWriteByIndex) {
+ SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeWrite;
+ } else {
+ SdoComFinished.m_SdoAccessType = kEplSdoAccessTypeRead;
+ }
+
+ // reset transfer state so this handle is not busy anymore
+ pSdoComCon_p->m_uiTransferredByte = 0;
+ pSdoComCon_p->m_uiTransSize = 0;
+
+ pfnTransferFinished = pSdoComCon_p->m_pfnTransferFinished;
+ // delete function pointer to inform application only once for each transfer
+ pSdoComCon_p->m_pfnTransferFinished = NULL;
+
+ // call application's callback function
+ pfnTransferFinished(&SdoComFinished);
+
+ }
+
+ return Ret;
+}
+
+// EOF
diff --git a/drivers/staging/epl/EplSdoUdpu.c b/drivers/staging/epl/EplSdoUdpu.c
new file mode 100644
index 000000000000..be52233b3ee8
--- /dev/null
+++ b/drivers/staging/epl/EplSdoUdpu.c
@@ -0,0 +1,790 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for SDO/UDP-Protocolabstractionlayer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoUdpu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplSdoUdpu.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+#include "SocketLinuxKernel.h"
+#include <linux/completion.h>
+#include <linux/sched.h>
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef EPL_SDO_MAX_CONNECTION_UDP
+#define EPL_SDO_MAX_CONNECTION_UDP 5
+#endif
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ unsigned long m_ulIpAddr; // in network byte order
+ unsigned int m_uiPort; // in network byte order
+
+} tEplSdoUdpCon;
+
+// instance table
+typedef struct {
+ tEplSdoUdpCon m_aSdoAbsUdpConnection[EPL_SDO_MAX_CONNECTION_UDP];
+ tEplSequLayerReceiveCb m_fpSdoAsySeqCb;
+ SOCKET m_UdpSocket;
+
+#if (TARGET_SYSTEM == _WIN32_)
+ HANDLE m_ThreadHandle;
+ LPCRITICAL_SECTION m_pCriticalSection;
+ CRITICAL_SECTION m_CriticalSection;
+
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ struct completion m_CompletionUdpThread;
+ int m_ThreadHandle;
+ int m_iTerminateThread;
+#endif
+
+} tEplSdoUdpInstance;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+static tEplSdoUdpInstance SdoUdpInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+#if (TARGET_SYSTEM == _WIN32_)
+static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter);
+
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+static int EplSdoUdpThread(void *pArg_p);
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <EPL-SDO-UDP-Layer> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: Protocolabstraction layer for UDP
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpuInit
+//
+// Description: init first instance of the module
+//
+//
+//
+// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer
+// callback-function
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p)
+{
+ tEplKernel Ret;
+
+ Ret = EplSdoUdpuAddInstance(fpReceiveCb_p);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpuAddInstance
+//
+// Description: init additional instance of the module
+// nit socket and start Listen-Thread
+//
+//
+//
+// Parameters: pReceiveCb_p = functionpointer to Sdo-Sequence layer
+// callback-function
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p)
+{
+ tEplKernel Ret;
+
+#if (TARGET_SYSTEM == _WIN32_)
+ int iError;
+ WSADATA Wsa;
+
+#endif
+
+ // set instance variables to 0
+ EPL_MEMSET(&SdoUdpInstance_g, 0x00, sizeof(SdoUdpInstance_g));
+
+ Ret = kEplSuccessful;
+
+ // save pointer to callback-function
+ if (fpReceiveCb_p != NULL) {
+ SdoUdpInstance_g.m_fpSdoAsySeqCb = fpReceiveCb_p;
+ } else {
+ Ret = kEplSdoUdpMissCb;
+ goto Exit;
+ }
+
+#if (TARGET_SYSTEM == _WIN32_)
+ // start winsock2 for win32
+ // windows specific start of socket
+ iError = WSAStartup(MAKEWORD(2, 0), &Wsa);
+ if (iError != 0) {
+ Ret = kEplSdoUdpNoSocket;
+ goto Exit;
+ }
+ // create critical section for acccess of instnace variables
+ SdoUdpInstance_g.m_pCriticalSection =
+ &SdoUdpInstance_g.m_CriticalSection;
+ InitializeCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
+
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ init_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
+ SdoUdpInstance_g.m_iTerminateThread = 0;
+#endif
+
+ SdoUdpInstance_g.m_ThreadHandle = 0;
+ SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
+
+ Ret = EplSdoUdpuConfig(INADDR_ANY, 0);
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpuDelInstance
+//
+// Description: del instance of the module
+// del socket and del Listen-Thread
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoUdpuDelInstance()
+{
+ tEplKernel Ret;
+
+#if (TARGET_SYSTEM == _WIN32_)
+ BOOL fTermError;
+#endif
+
+ Ret = kEplSuccessful;
+
+ if (SdoUdpInstance_g.m_ThreadHandle != 0) { // listen thread was started
+ // close thread
+#if (TARGET_SYSTEM == _WIN32_)
+ fTermError =
+ TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0);
+ if (fTermError == FALSE) {
+ Ret = kEplSdoUdpThreadError;
+ goto Exit;
+ }
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ SdoUdpInstance_g.m_iTerminateThread = 1;
+ /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */
+ send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1);
+ wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
+#endif
+
+ SdoUdpInstance_g.m_ThreadHandle = 0;
+ }
+
+ if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) {
+ // close socket
+ closesocket(SdoUdpInstance_g.m_UdpSocket);
+ SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
+ }
+#if (TARGET_SYSTEM == _WIN32_)
+ // delete critical section
+ DeleteCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
+#endif
+
+#if (TARGET_SYSTEM == _WIN32_)
+ // for win 32
+ WSACleanup();
+#endif
+
+#if (TARGET_SYSTEM == _WIN32_)
+ Exit:
+#endif
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpuConfig
+//
+// Description: reconfigurate socket with new IP-Address
+// -> needed for NMT ResetConfiguration
+//
+// Parameters: ulIpAddr_p = IpAddress in platform byte order
+// uiPort_p = port number in platform byte order
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p,
+ unsigned int uiPort_p)
+{
+ tEplKernel Ret;
+ struct sockaddr_in Addr;
+ int iError;
+
+#if (TARGET_SYSTEM == _WIN32_)
+ BOOL fTermError;
+ unsigned long ulThreadId;
+#endif
+
+ Ret = kEplSuccessful;
+
+ if (uiPort_p == 0) { // set UDP port to default port number
+ uiPort_p = EPL_C_SDO_EPL_PORT;
+ } else if (uiPort_p > 65535) {
+ Ret = kEplSdoUdpSocketError;
+ goto Exit;
+ }
+
+ if (SdoUdpInstance_g.m_ThreadHandle != 0) { // listen thread was started
+
+ // close old thread
+#if (TARGET_SYSTEM == _WIN32_)
+ fTermError =
+ TerminateThread(SdoUdpInstance_g.m_ThreadHandle, 0);
+ if (fTermError == FALSE) {
+ Ret = kEplSdoUdpThreadError;
+ goto Exit;
+ }
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ SdoUdpInstance_g.m_iTerminateThread = 1;
+ /* kill_proc(SdoUdpInstance_g.m_ThreadHandle, SIGTERM, 1 ); */
+ send_sig(SIGTERM, SdoUdpInstance_g.m_ThreadHandle, 1);
+ wait_for_completion(&SdoUdpInstance_g.m_CompletionUdpThread);
+ SdoUdpInstance_g.m_iTerminateThread = 0;
+#endif
+
+ SdoUdpInstance_g.m_ThreadHandle = 0;
+ }
+
+ if (SdoUdpInstance_g.m_UdpSocket != INVALID_SOCKET) {
+ // close socket
+ iError = closesocket(SdoUdpInstance_g.m_UdpSocket);
+ SdoUdpInstance_g.m_UdpSocket = INVALID_SOCKET;
+ if (iError != 0) {
+ Ret = kEplSdoUdpSocketError;
+ goto Exit;
+ }
+ }
+ // create Socket
+ SdoUdpInstance_g.m_UdpSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (SdoUdpInstance_g.m_UdpSocket == INVALID_SOCKET) {
+ Ret = kEplSdoUdpNoSocket;
+ EPL_DBGLVL_SDO_TRACE0("EplSdoUdpuConfig: socket() failed\n");
+ goto Exit;
+ }
+ // bind socket
+ Addr.sin_family = AF_INET;
+ Addr.sin_port = htons((unsigned short)uiPort_p);
+ Addr.sin_addr.s_addr = htonl(ulIpAddr_p);
+ iError =
+ bind(SdoUdpInstance_g.m_UdpSocket, (struct sockaddr *)&Addr,
+ sizeof(Addr));
+ if (iError < 0) {
+ //iError = WSAGetLastError();
+ EPL_DBGLVL_SDO_TRACE1
+ ("EplSdoUdpuConfig: bind() finished with %i\n", iError);
+ Ret = kEplSdoUdpNoSocket;
+ goto Exit;
+ }
+ // create Listen-Thread
+#if (TARGET_SYSTEM == _WIN32_)
+ // for win32
+
+ // create thread
+ SdoUdpInstance_g.m_ThreadHandle = CreateThread(NULL,
+ 0,
+ EplSdoUdpThread,
+ &SdoUdpInstance_g,
+ 0, &ulThreadId);
+ if (SdoUdpInstance_g.m_ThreadHandle == NULL) {
+ Ret = kEplSdoUdpThreadError;
+ goto Exit;
+ }
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+
+ SdoUdpInstance_g.m_ThreadHandle =
+ kernel_thread(EplSdoUdpThread, &SdoUdpInstance_g, CLONE_KERNEL);
+ if (SdoUdpInstance_g.m_ThreadHandle == 0) {
+ Ret = kEplSdoUdpThreadError;
+ goto Exit;
+ }
+#endif
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpuInitCon
+//
+// Description: init a new connect
+//
+//
+//
+// Parameters: pSdoConHandle_p = pointer for the new connection handle
+// uiTargetNodeId_p = NodeId of the target node
+//
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl * pSdoConHandle_p,
+ unsigned int uiTargetNodeId_p)
+{
+ tEplKernel Ret;
+ unsigned int uiCount;
+ unsigned int uiFreeCon;
+ tEplSdoUdpCon *pSdoUdpCon;
+
+ Ret = kEplSuccessful;
+
+ // get free entry in control structure
+ uiCount = 0;
+ uiFreeCon = EPL_SDO_MAX_CONNECTION_UDP;
+ pSdoUdpCon = &SdoUdpInstance_g.m_aSdoAbsUdpConnection[0];
+ while (uiCount < EPL_SDO_MAX_CONNECTION_UDP) {
+ if ((pSdoUdpCon->m_ulIpAddr & htonl(0xFF)) == htonl(uiTargetNodeId_p)) { // existing connection to target node found
+ // set handle
+ *pSdoConHandle_p = (uiCount | EPL_SDO_UDP_HANDLE);
+
+ goto Exit;
+ } else if ((pSdoUdpCon->m_ulIpAddr == 0)
+ && (pSdoUdpCon->m_uiPort == 0)) {
+ uiFreeCon = uiCount;
+ }
+ uiCount++;
+ pSdoUdpCon++;
+ }
+
+ if (uiFreeCon == EPL_SDO_MAX_CONNECTION_UDP) {
+ // error no free handle
+ Ret = kEplSdoUdpNoFreeHandle;
+ } else {
+ pSdoUdpCon =
+ &SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiFreeCon];
+ // save infos for connection
+ pSdoUdpCon->m_uiPort = htons(EPL_C_SDO_EPL_PORT);
+ pSdoUdpCon->m_ulIpAddr = htonl(0xC0A86400 | uiTargetNodeId_p); // 192.168.100.uiTargetNodeId_p
+
+ // set handle
+ *pSdoConHandle_p = (uiFreeCon | EPL_SDO_UDP_HANDLE);
+
+ }
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpuSendData
+//
+// Description: send data using exisiting connection
+//
+//
+//
+// Parameters: SdoConHandle_p = connection handle
+// pSrcData_p = pointer to data
+// dwDataSize_p = number of databyte
+// -> without asend-header!!!
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p,
+ tEplFrame * pSrcData_p, DWORD dwDataSize_p)
+{
+ tEplKernel Ret;
+ int iError;
+ unsigned int uiArray;
+ struct sockaddr_in Addr;
+
+ Ret = kEplSuccessful;
+
+ uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
+ if (uiArray >= EPL_SDO_MAX_CONNECTION_UDP) {
+ Ret = kEplSdoUdpInvalidHdl;
+ goto Exit;
+ }
+ //set message type
+ AmiSetByteToLe(&pSrcData_p->m_le_bMessageType, 0x06); // SDO
+ // target node id (for Udp = 0)
+ AmiSetByteToLe(&pSrcData_p->m_le_bDstNodeId, 0x00);
+ // set source-nodeid (for Udp = 0)
+ AmiSetByteToLe(&pSrcData_p->m_le_bSrcNodeId, 0x00);
+
+ // calc size
+ dwDataSize_p += EPL_ASND_HEADER_SIZE;
+
+ // call sendto
+ Addr.sin_family = AF_INET;
+#if (TARGET_SYSTEM == _WIN32_)
+ // enter critical section for process function
+ EnterCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
+#endif
+
+ Addr.sin_port =
+ (unsigned short)SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].
+ m_uiPort;
+ Addr.sin_addr.s_addr =
+ SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr;
+
+#if (TARGET_SYSTEM == _WIN32_)
+ // leave critical section for process function
+ LeaveCriticalSection(SdoUdpInstance_g.m_pCriticalSection);
+#endif
+
+ iError = sendto(SdoUdpInstance_g.m_UdpSocket, // sockethandle
+ (const char *)&pSrcData_p->m_le_bMessageType, // data to send
+ dwDataSize_p, // number of bytes to send
+ 0, // flags
+ (struct sockaddr *)&Addr, // target
+ sizeof(struct sockaddr_in)); // sizeof targetadress
+ if (iError < 0) {
+ EPL_DBGLVL_SDO_TRACE1
+ ("EplSdoUdpuSendData: sendto() finished with %i\n", iError);
+ Ret = kEplSdoUdpSendError;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpuDelCon
+//
+// Description: delete connection from intern structure
+//
+//
+//
+// Parameters: SdoConHandle_p = connection handle
+//
+// Returns: tEplKernel = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p)
+{
+ tEplKernel Ret;
+ unsigned int uiArray;
+
+ uiArray = (SdoConHandle_p & ~EPL_SDO_ASY_HANDLE_MASK);
+
+ if (uiArray >= EPL_SDO_MAX_CONNECTION_UDP) {
+ Ret = kEplSdoUdpInvalidHdl;
+ goto Exit;
+ } else {
+ Ret = kEplSuccessful;
+ }
+
+ // delete connection
+ SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_ulIpAddr = 0;
+ SdoUdpInstance_g.m_aSdoAbsUdpConnection[uiArray].m_uiPort = 0;
+
+ Exit:
+ return Ret;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoUdpThread
+//
+// Description: thread check socket for new data
+//
+//
+//
+// Parameters: lpParameter = pointer to parameter type tEplSdoUdpThreadPara
+//
+//
+// Returns: DWORD = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+#if (TARGET_SYSTEM == _WIN32_)
+static DWORD PUBLIC EplSdoUdpThread(LPVOID lpParameter)
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+static int EplSdoUdpThread(void *pArg_p)
+#endif
+{
+
+ tEplSdoUdpInstance *pInstance;
+ struct sockaddr_in RemoteAddr;
+ int iError;
+ int iCount;
+ int iFreeEntry;
+ BYTE abBuffer[EPL_MAX_SDO_REC_FRAME_SIZE];
+ unsigned int uiSize;
+ tEplSdoConHdl SdoConHdl;
+
+#if (TARGET_SYSTEM == _WIN32_)
+ pInstance = (tEplSdoUdpInstance *) lpParameter;
+
+ for (;;)
+#elif (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ pInstance = (tEplSdoUdpInstance *) pArg_p;
+ daemonize("EplSdoUdpThread");
+ allow_signal(SIGTERM);
+
+ for (; pInstance->m_iTerminateThread == 0;)
+#endif
+
+ {
+ // wait for data
+ uiSize = sizeof(struct sockaddr);
+ iError = recvfrom(pInstance->m_UdpSocket, // Socket
+ (char *)&abBuffer[0], // buffer for data
+ sizeof(abBuffer), // size of the buffer
+ 0, // flags
+ (struct sockaddr *)&RemoteAddr,
+ (int *)&uiSize);
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ if (iError == -ERESTARTSYS) {
+ break;
+ }
+#endif
+ if (iError > 0) {
+ // get handle for higher layer
+ iCount = 0;
+ iFreeEntry = 0xFFFF;
+#if (TARGET_SYSTEM == _WIN32_)
+ // enter critical section for process function
+ EnterCriticalSection(SdoUdpInstance_g.
+ m_pCriticalSection);
+#endif
+ while (iCount < EPL_SDO_MAX_CONNECTION_UDP) {
+ // check if this connection is already known
+ if ((pInstance->m_aSdoAbsUdpConnection[iCount].
+ m_ulIpAddr == RemoteAddr.sin_addr.s_addr)
+ && (pInstance->
+ m_aSdoAbsUdpConnection[iCount].
+ m_uiPort == RemoteAddr.sin_port)) {
+ break;
+ }
+
+ if ((pInstance->m_aSdoAbsUdpConnection[iCount].
+ m_ulIpAddr == 0)
+ && (pInstance->
+ m_aSdoAbsUdpConnection[iCount].
+ m_uiPort == 0)
+ && (iFreeEntry == 0xFFFF))
+ {
+ iFreeEntry = iCount;
+ }
+
+ iCount++;
+ }
+
+ if (iCount == EPL_SDO_MAX_CONNECTION_UDP) {
+ // connection unknown
+ // see if there is a free handle
+ if (iFreeEntry != 0xFFFF) {
+ // save adress infos
+ pInstance->
+ m_aSdoAbsUdpConnection[iFreeEntry].
+ m_ulIpAddr =
+ RemoteAddr.sin_addr.s_addr;
+ pInstance->
+ m_aSdoAbsUdpConnection[iFreeEntry].
+ m_uiPort = RemoteAddr.sin_port;
+#if (TARGET_SYSTEM == _WIN32_)
+ // leave critical section for process function
+ LeaveCriticalSection(SdoUdpInstance_g.
+ m_pCriticalSection);
+#endif
+ // call callback
+ SdoConHdl = iFreeEntry;
+ SdoConHdl |= EPL_SDO_UDP_HANDLE;
+ // offset 4 -> start of SDO Sequence header
+ pInstance->m_fpSdoAsySeqCb(SdoConHdl,
+ (tEplAsySdoSeq
+ *) &
+ abBuffer[4],
+ (iError -
+ 4));
+ } else {
+ EPL_DBGLVL_SDO_TRACE0
+ ("Error in EplSdoUdpThread() no free handle\n");
+#if (TARGET_SYSTEM == _WIN32_)
+ // leave critical section for process function
+ LeaveCriticalSection(SdoUdpInstance_g.
+ m_pCriticalSection);
+#endif
+ }
+
+ } else {
+ // known connection
+ // call callback with correct handle
+ SdoConHdl = iCount;
+ SdoConHdl |= EPL_SDO_UDP_HANDLE;
+#if (TARGET_SYSTEM == _WIN32_)
+ // leave critical section for process function
+ LeaveCriticalSection(SdoUdpInstance_g.
+ m_pCriticalSection);
+#endif
+ // offset 4 -> start of SDO Sequence header
+ pInstance->m_fpSdoAsySeqCb(SdoConHdl,
+ (tEplAsySdoSeq *) &
+ abBuffer[4],
+ (iError - 4));
+ }
+ } // end of if(iError!=SOCKET_ERROR)
+ } // end of for(;;)
+
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+ complete_and_exit(&SdoUdpInstance_g.m_CompletionUdpThread, 0);
+#endif
+
+ return 0;
+}
+
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+
+// EOF
diff --git a/drivers/staging/epl/EplStatusu.c b/drivers/staging/epl/EplStatusu.c
new file mode 100644
index 000000000000..689f9124ae29
--- /dev/null
+++ b/drivers/staging/epl/EplStatusu.c
@@ -0,0 +1,380 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for Statusu-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplStatusu.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/11/15 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplStatusu.h"
+#include "user/EplDlluCal.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <xxxxx> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description:
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P R I V A T E D E F I N I T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ tEplStatusuCbResponse m_apfnCbResponse[254];
+
+} tEplStatusuInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+static tEplStatusuInstance EplStatusuInstance_g;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static tEplKernel PUBLIC EplStatusuCbStatusResponse(tEplFrameInfo *
+ pFrameInfo_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplStatusuInit
+//
+// Description: init first instance of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplStatusuInit()
+{
+ tEplKernel Ret;
+
+ Ret = EplStatusuAddInstance();
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplStatusuAddInstance
+//
+// Description: init other instances of the module
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplStatusuAddInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // reset instance structure
+ EPL_MEMSET(&EplStatusuInstance_g, 0, sizeof(EplStatusuInstance_g));
+
+ // register StatusResponse callback function
+ Ret =
+ EplDlluCalRegAsndService(kEplDllAsndStatusResponse,
+ EplStatusuCbStatusResponse,
+ kEplDllAsndFilterAny);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplStatusuDelInstance
+//
+// Description: delete instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplStatusuDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // deregister StatusResponse callback function
+ Ret =
+ EplDlluCalRegAsndService(kEplDllAsndStatusResponse, NULL,
+ kEplDllAsndFilterNone);
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplStatusuReset
+//
+// Description: resets this instance
+//
+// Parameters:
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+EPLDLLEXPORT tEplKernel PUBLIC EplStatusuReset()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // reset instance structure
+ EPL_MEMSET(&EplStatusuInstance_g, 0, sizeof(EplStatusuInstance_g));
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplStatusuRequestStatusResponse
+//
+// Description: returns the StatusResponse for the specified node.
+//
+// Parameters: uiNodeId_p = IN: node ID
+// pfnCbResponse_p = IN: function pointer to callback function
+// which will be called if StatusResponse is received
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplStatusuRequestStatusResponse(unsigned int uiNodeId_p,
+ tEplStatusuCbResponse
+ pfnCbResponse_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // decrement node ID, because array is zero based
+ uiNodeId_p--;
+ if (uiNodeId_p < tabentries(EplStatusuInstance_g.m_apfnCbResponse)) {
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (EplStatusuInstance_g.m_apfnCbResponse[uiNodeId_p] != NULL) { // request already issued (maybe by someone else)
+ Ret = kEplInvalidOperation;
+ } else {
+ EplStatusuInstance_g.m_apfnCbResponse[uiNodeId_p] =
+ pfnCbResponse_p;
+ Ret =
+ EplDlluCalIssueRequest(kEplDllReqServiceStatus,
+ (uiNodeId_p + 1), 0xFF);
+ }
+#else
+ Ret = kEplInvalidOperation;
+#endif
+ } else { // invalid node ID specified
+ Ret = kEplInvalidNodeId;
+ }
+
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplStatusuCbStatusResponse
+//
+// Description: callback funktion for StatusResponse
+//
+//
+//
+// Parameters: pFrameInfo_p = Frame with the StatusResponse
+//
+//
+// Returns: tEplKernel = error code
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static tEplKernel PUBLIC EplStatusuCbStatusResponse(tEplFrameInfo *
+ pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiNodeId;
+ unsigned int uiIndex;
+ tEplStatusuCbResponse pfnCbResponse;
+
+ uiNodeId = AmiGetByteFromLe(&pFrameInfo_p->m_pFrame->m_le_bSrcNodeId);
+
+ uiIndex = uiNodeId - 1;
+
+ if (uiIndex < tabentries(EplStatusuInstance_g.m_apfnCbResponse)) {
+ // memorize pointer to callback function
+ pfnCbResponse = EplStatusuInstance_g.m_apfnCbResponse[uiIndex];
+ if (pfnCbResponse == NULL) { // response was not requested
+ goto Exit;
+ }
+ // reset callback function pointer so that caller may issue next request
+ EplStatusuInstance_g.m_apfnCbResponse[uiIndex] = NULL;
+
+ if (pFrameInfo_p->m_uiFrameSize < EPL_C_DLL_MINSIZE_STATUSRES) { // StatusResponse not received or it has invalid size
+ Ret = pfnCbResponse(uiNodeId, NULL);
+ } else { // StatusResponse received
+ Ret =
+ pfnCbResponse(uiNodeId,
+ &pFrameInfo_p->m_pFrame->m_Data.
+ m_Asnd.m_Payload.m_StatusResponse);
+ }
+ }
+
+ Exit:
+ return Ret;
+}
+
+// EOF
diff --git a/drivers/staging/epl/EplTarget.h b/drivers/staging/epl/EplTarget.h
new file mode 100644
index 000000000000..b2b66f82c035
--- /dev/null
+++ b/drivers/staging/epl/EplTarget.h
@@ -0,0 +1,233 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for target api function
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTarget.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2005/12/05 -as: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPLTARGET_H_
+#define _EPLTARGET_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+// =========================================================================
+// macros for memory access (depends on target system)
+// =========================================================================
+
+// NOTE:
+// The following macros are used to combine standard library definitions. Some
+// applications needs to use one common library function (e.g. memcpy()). So
+// you can set (or change) it here.
+
+#if (TARGET_SYSTEM == _WIN32_)
+
+#define _WIN32_WINDOWS 0x0401
+#define _WIN32_WINNT 0x0400
+
+#include <stdlib.h>
+#include <stdio.h>
+
+ //29.11.2004 f.j. sonst ist memcpy und memset unbekannt
+#include <string.h>
+
+#define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz));
+#define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz));
+
+ // f.j.: die Funktionen fr <MemAlloc> und <MemFree> sind in WinMem.c definiert
+ //definition der Prototypen
+void FAR *MemAlloc(DWORD dwMemSize_p);
+void MemFree(void FAR * pMem_p);
+
+#define EPL_MALLOC(siz) malloc((size_t)(siz))
+#define EPL_FREE(ptr) free((void *)ptr)
+
+#ifndef PRINTF0
+void trace(const char *fmt, ...);
+#define PRINTF TRACE
+#define PRINTF0(arg) TRACE0(arg)
+#define PRINTF1(arg,p1) TRACE1(arg,p1)
+#define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2)
+#define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3)
+#define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4)
+ //#define PRINTF printf
+ //#define PRINTF0(arg) PRINTF(arg)
+ //#define PRINTF1(arg,p1) PRINTF(arg,p1)
+ //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2)
+ //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3)
+ //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4)
+#endif
+
+#ifdef ASSERTMSG
+#undef ASSERTMSG
+#endif
+
+#define ASSERTMSG(expr,string) if (!(expr)) { \
+ MessageBox (NULL, string, "Assertion failed", MB_OK | MB_ICONERROR); \
+ exit (-1);}
+
+#elif (TARGET_SYSTEM == _NO_OS_)
+
+#include <stdlib.h>
+#include <stdio.h>
+
+ //29.11.2004 f.j. sonst ist memcpy und memset unbekannt
+// #include <string.h>
+
+#define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz));
+#define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz));
+
+#define EPL_MALLOC(siz) malloc((size_t)(siz))
+#define EPL_FREE(ptr) free((void *)ptr)
+
+#ifndef PRINTF0
+#define PRINTF TRACE
+#define PRINTF0(arg) TRACE0(arg)
+#define PRINTF1(arg,p1) TRACE1(arg,p1)
+#define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2)
+#define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3)
+#define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4)
+ //#define PRINTF printf
+ //#define PRINTF0(arg) PRINTF(arg)
+ //#define PRINTF1(arg,p1) PRINTF(arg,p1)
+ //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2)
+ //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3)
+ //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4)
+#endif
+
+#elif (TARGET_SYSTEM == _LINUX_)
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#include <stdio.h>
+#else
+// #include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/version.h>
+#endif
+
+ //29.11.2004 f.j. sonst ist memcpy und memset unbekannt
+// #include <string.h>
+
+#define EPL_MEMCPY(dst,src,siz) memcpy((void*)(dst),(const void*)(src),(size_t)(siz));
+#define EPL_MEMSET(dst,val,siz) memset((void*)(dst),(int)(val),(size_t)(siz));
+
+#ifndef __KERNEL__
+#define EPL_MALLOC(siz) malloc((size_t)(siz))
+#define EPL_FREE(ptr) free((void *)ptr)
+#else
+#define EPL_MALLOC(siz) kmalloc((size_t)(siz), GFP_KERNEL)
+#define EPL_FREE(ptr) kfree((void *)ptr)
+#endif
+
+#ifndef PRINTF0
+#define PRINTF TRACE
+#define PRINTF0(arg) TRACE0(arg)
+#define PRINTF1(arg,p1) TRACE1(arg,p1)
+#define PRINTF2(arg,p1,p2) TRACE2(arg,p1,p2)
+#define PRINTF3(arg,p1,p2,p3) TRACE3(arg,p1,p2,p3)
+#define PRINTF4(arg,p1,p2,p3,p4) TRACE4(arg,p1,p2,p3,p4)
+ //#define PRINTF printf
+ //#define PRINTF0(arg) PRINTF(arg)
+ //#define PRINTF1(arg,p1) PRINTF(arg,p1)
+ //#define PRINTF2(arg,p1,p2) PRINTF(arg,p1,p2)
+ //#define PRINTF3(arg,p1,p2,p3) PRINTF(arg,p1,p2,p3)
+ //#define PRINTF4(arg,p1,p2,p3,p4) PRINTF(arg,p1,p2,p3,p4)
+#endif
+
+#endif
+
+#define EPL_TGT_INTMASK_ETH 0x0001 // ethernet interrupt
+#define EPL_TGT_INTMASK_DMA 0x0002 // DMA interrupt
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+// currently no Timer functions are needed by EPL stack
+// so they are not implemented yet
+//void PUBLIC TgtTimerInit(void);
+//DWORD PUBLIC TgtGetTickCount(void);
+//void PUBLIC TgtGetNetTime(tEplNetTime * pNetTime_p);
+
+// functions for ethernet driver
+tEplKernel PUBLIC TgtInitEthIsr(void);
+void PUBLIC TgtFreeEthIsr(void);
+void PUBLIC TgtEnableGlobalInterrupt(BYTE fEnable_p);
+void PUBLIC TgtEnableEthInterrupt0(BYTE fEnable_p,
+ unsigned int uiInterruptMask_p);
+void PUBLIC TgtEnableEthInterrupt1(BYTE fEnable_p,
+ unsigned int uiInterruptMask_p);
+
+#endif // #ifndef _EPLTARGET_H_
diff --git a/drivers/staging/epl/EplTimer.h b/drivers/staging/epl/EplTimer.h
new file mode 100644
index 000000000000..facbfd8740e6
--- /dev/null
+++ b/drivers/staging/epl/EplTimer.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for Epl Timer-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTimer.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/06 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "EplEvent.h"
+
+#ifndef _EPLTIMER_H_
+#define _EPLTIMER_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+// type for timer handle
+typedef unsigned long tEplTimerHdl;
+
+typedef struct {
+ tEplEventSink m_EventSink;
+ unsigned long m_ulArg; // d.k.: converted to unsigned long because
+ // it is never accessed as a pointer by the
+ // timer module and the data the
+ // pointer points to is not saved in any way.
+ // It is just a value. The user is responsible
+ // to store the data statically and convert
+ // the pointer between address spaces.
+
+} tEplTimerArg;
+
+typedef struct {
+ tEplTimerHdl m_TimerHdl;
+ unsigned long m_ulArg; // d.k.: converted to unsigned long because
+ // it is never accessed as a pointer by the
+ // timer module and the data the
+ // pointer points to is not saved in any way.
+ // It is just a value.
+
+} tEplTimerEventArg;
+
+typedef tEplKernel(PUBLIC * tEplTimerkCallback) (tEplTimerEventArg *
+ pEventArg_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPLTIMER_H_
diff --git a/drivers/staging/epl/EplTimeruLinuxKernel.c b/drivers/staging/epl/EplTimeruLinuxKernel.c
new file mode 100644
index 000000000000..08820d184055
--- /dev/null
+++ b/drivers/staging/epl/EplTimeruLinuxKernel.c
@@ -0,0 +1,446 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for EPL User Timermodule for Linux kernel module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTimeruLinuxKernel.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/09/12 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplTimeru.h"
+#include <linux/timer.h>
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+typedef struct {
+ struct timer_list m_Timer;
+ tEplTimerArg TimerArgument;
+
+} tEplTimeruData;
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p);
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <Epl Userspace-Timermodule for Linux Kernel> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: Epl Userspace-Timermodule for Linux Kernel
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruInit
+//
+// Description: function inits first instance
+//
+// Parameters: void
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimeruInit()
+{
+ tEplKernel Ret;
+
+ Ret = EplTimeruAddInstance();
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruAddInstance
+//
+// Description: function inits additional instance
+//
+// Parameters: void
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimeruAddInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruDelInstance
+//
+// Description: function deletes instance
+// -> under Linux nothing to do
+// -> no instance table needed
+//
+// Parameters: void
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimeruDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruSetTimerMs
+//
+// Description: function creates a timer and returns the corresponding handle
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+// ulTime_p = time for timer in ms
+// Argument_p = argument for timer
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplTimeruData *pData;
+
+ // check pointer to handle
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ pData = (tEplTimeruData *) EPL_MALLOC(sizeof(tEplTimeruData));
+ if (pData == NULL) {
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ init_timer(&pData->m_Timer);
+ pData->m_Timer.function = EplTimeruCbMs;
+ pData->m_Timer.data = (unsigned long)pData;
+ pData->m_Timer.expires = jiffies + ulTime_p * HZ / 1000;
+
+ EPL_MEMCPY(&pData->TimerArgument, &Argument_p, sizeof(tEplTimerArg));
+
+ add_timer(&pData->m_Timer);
+
+ *pTimerHdl_p = (tEplTimerHdl) pData;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruModifyTimerMs
+//
+// Description: function changes a timer and returns the corresponding handle
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+// ulTime_p = time for timer in ms
+// Argument_p = argument for timer
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplTimeruData *pData;
+
+ // check pointer to handle
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+ // check handle itself, i.e. was the handle initialized before
+ if (*pTimerHdl_p == 0) {
+ Ret = EplTimeruSetTimerMs(pTimerHdl_p, ulTime_p, Argument_p);
+ goto Exit;
+ }
+ pData = (tEplTimeruData *) * pTimerHdl_p;
+ if ((tEplTimeruData *) pData->m_Timer.data != pData) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ mod_timer(&pData->m_Timer, (jiffies + ulTime_p * HZ / 1000));
+
+ // copy the TimerArg after the timer is restarted,
+ // so that a timer occured immediately before mod_timer
+ // won't use the new TimerArg and
+ // therefore the old timer cannot be distinguished from the new one.
+ // But if the new timer is too fast, it may get lost.
+ EPL_MEMCPY(&pData->TimerArgument, &Argument_p, sizeof(tEplTimerArg));
+
+ // check if timer is really running
+ if (timer_pending(&pData->m_Timer) == 0) { // timer is not running
+ // retry starting it
+ add_timer(&pData->m_Timer);
+ }
+ // set handle to pointer of tEplTimeruData
+// *pTimerHdl_p = (tEplTimerHdl) pData;
+
+ Exit:
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruDeleteTimer
+//
+// Description: function deletes a timer
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+//
+// Returns: tEplKernel = errorcode
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplTimeruData *pData;
+
+ // check pointer to handle
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+ // check handle itself, i.e. was the handle initialized before
+ if (*pTimerHdl_p == 0) {
+ Ret = kEplSuccessful;
+ goto Exit;
+ }
+ pData = (tEplTimeruData *) * pTimerHdl_p;
+ if ((tEplTimeruData *) pData->m_Timer.data != pData) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+/* if (del_timer(&pData->m_Timer) == 1)
+ {
+ kfree(pData);
+ }
+*/
+ // try to delete the timer
+ del_timer(&pData->m_Timer);
+ // free memory in any case
+ kfree(pData);
+
+ // uninitialize handle
+ *pTimerHdl_p = 0;
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruIsTimerActive
+//
+// Description: checks if the timer referenced by the handle is currently
+// active.
+//
+// Parameters: TimerHdl_p = handle of the timer to check
+//
+// Returns: BOOL = TRUE, if active;
+// FALSE, otherwise
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p)
+{
+ BOOL fActive = FALSE;
+ tEplTimeruData *pData;
+
+ // check handle itself, i.e. was the handle initialized before
+ if (TimerHdl_p == 0) { // timer was not created yet, so it is not active
+ goto Exit;
+ }
+ pData = (tEplTimeruData *) TimerHdl_p;
+ if ((tEplTimeruData *) pData->m_Timer.data != pData) { // invalid timer
+ goto Exit;
+ }
+ // check if timer is running
+ if (timer_pending(&pData->m_Timer) == 0) { // timer is not running
+ goto Exit;
+ }
+
+ fActive = TRUE;
+
+ Exit:
+ return fActive;
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruCbMs
+//
+// Description: function to process timer
+//
+//
+//
+// Parameters: lpParameter = pointer to structur of type tEplTimeruData
+//
+//
+// Returns: (none)
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static void PUBLIC EplTimeruCbMs(unsigned long ulParameter_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplTimeruData *pData;
+ tEplEvent EplEvent;
+ tEplTimerEventArg TimerEventArg;
+
+ pData = (tEplTimeruData *) ulParameter_p;
+
+ // call event function
+ TimerEventArg.m_TimerHdl = (tEplTimerHdl) pData;
+ TimerEventArg.m_ulArg = pData->TimerArgument.m_ulArg;
+
+ EplEvent.m_EventSink = pData->TimerArgument.m_EventSink;
+ EplEvent.m_EventType = kEplEventTypeTimer;
+ EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime));
+ EplEvent.m_pArg = &TimerEventArg;
+ EplEvent.m_uiSize = sizeof(TimerEventArg);
+
+ Ret = EplEventuPost(&EplEvent);
+
+ // d.k. do not free memory, user has to call EplTimeruDeleteTimer()
+ //kfree(pData);
+
+}
+
+// EOF
diff --git a/drivers/staging/epl/EplTimeruNull.c b/drivers/staging/epl/EplTimeruNull.c
new file mode 100644
index 000000000000..40ce403cbd03
--- /dev/null
+++ b/drivers/staging/epl/EplTimeruNull.c
@@ -0,0 +1,312 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for Epl Userspace-Timermodule NULL-Implementation
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTimeruNull.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/06 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplTimeru.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <Epl Userspace-Timermodule NULL-Implementation> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: Epl Userspace-Timermodule NULL-Implementation
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruInit
+//
+// Description: function init first instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruInit()
+{
+ tEplKernel Ret;
+
+ Ret = EplTimeruAddInstance();
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruAddInstance
+//
+// Description: function init additional instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruAddInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruDelInstance
+//
+// Description: function delte instance
+// -> under Win32 nothing to do
+// -> no instnace table needed
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruSetTimerMs
+//
+// Description: function create a timer and return a handle to the pointer
+//
+//
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+// ulTime_p = time for timer in ms
+// Argument_p = argument for timer
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // check handle
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+ //---------------------------------------------------------------------------
+//
+// Function: EplTimeruModifyTimerMs
+//
+// Description: function change a timer and return a handle to the pointer
+//
+//
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+// ulTime_p = time for timer in ms
+// Argument_p = argument for timer
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // check parameter
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+ //---------------------------------------------------------------------------
+//
+// Function: EplTimeruDeleteTimer
+//
+// Description: function delte a timer
+//
+//
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p)
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // check parameter
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+ // set handle invalide
+ *pTimerHdl_p = 0;
+
+ Exit:
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+// EOF
diff --git a/drivers/staging/epl/EplTimeruWin32.c b/drivers/staging/epl/EplTimeruWin32.c
new file mode 100644
index 000000000000..a967b4e59d4b
--- /dev/null
+++ b/drivers/staging/epl/EplTimeruWin32.c
@@ -0,0 +1,513 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: source file for Epl Userspace-Timermodule for Win32
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTimeruWin32.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/06 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "user/EplTimeru.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+typedef struct {
+ tEplTimerArg TimerArgument;
+ HANDLE DelteHandle;
+ unsigned long ulTimeout;
+
+} tEplTimeruThread;
+
+typedef struct {
+ LPCRITICAL_SECTION m_pCriticalSection;
+ CRITICAL_SECTION m_CriticalSection;
+} tEplTimeruInstance;
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+static tEplTimeruInstance EplTimeruInstance_g;
+static tEplTimeruThread ThreadData_l;
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter);
+
+/***************************************************************************/
+/* */
+/* */
+/* C L A S S <Epl Userspace-Timermodule for Win32> */
+/* */
+/* */
+/***************************************************************************/
+//
+// Description: Epl Userspace-Timermodule for Win32
+//
+//
+/***************************************************************************/
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruInit
+//
+// Description: function init first instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruInit()
+{
+ tEplKernel Ret;
+
+ Ret = EplTimeruAddInstance();
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruAddInstance
+//
+// Description: function init additional instance
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruAddInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ // create critical section
+ EplTimeruInstance_g.m_pCriticalSection =
+ &EplTimeruInstance_g.m_CriticalSection;
+ InitializeCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruDelInstance
+//
+// Description: function delte instance
+// -> under Win32 nothing to do
+// -> no instnace table needed
+//
+//
+//
+// Parameters:
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruDelInstance()
+{
+ tEplKernel Ret;
+
+ Ret = kEplSuccessful;
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimeruSetTimerMs
+//
+// Description: function create a timer and return a handle to the pointer
+//
+//
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+// ulTime_p = time for timer in ms
+// Argument_p = argument for timer
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p)
+{
+ tEplKernel Ret;
+ HANDLE DeleteHandle;
+ HANDLE ThreadHandle;
+ DWORD ThreadId;
+
+ Ret = kEplSuccessful;
+
+ // check handle
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+ // enter critical section
+ EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
+
+ // first create event to delete timer
+ DeleteHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (DeleteHandle == NULL) {
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+ // set handle for caller
+ *pTimerHdl_p = (tEplTimerHdl) DeleteHandle;
+
+ // fill data for thread
+ ThreadData_l.DelteHandle = DeleteHandle;
+ EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p,
+ sizeof(tEplTimerArg));
+ ThreadData_l.ulTimeout = ulTime_p;
+
+ // create thread to create waitable timer and wait for timer
+ ThreadHandle = CreateThread(NULL,
+ 0,
+ EplSdoTimeruThreadms,
+ &ThreadData_l, 0, &ThreadId);
+ if (ThreadHandle == NULL) {
+ // leave critical section
+ LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
+
+ // delte handle
+ CloseHandle(DeleteHandle);
+
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+ //---------------------------------------------------------------------------
+//
+// Function: EplTimeruModifyTimerMs
+//
+// Description: function change a timer and return a handle to the pointer
+//
+//
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+// ulTime_p = time for timer in ms
+// Argument_p = argument for timer
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p)
+{
+ tEplKernel Ret;
+ HANDLE DeleteHandle;
+ HANDLE ThreadHandle;
+ DWORD ThreadId;
+
+ Ret = kEplSuccessful;
+
+ // check parameter
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ DeleteHandle = (HANDLE) (*pTimerHdl_p);
+
+ // set event to end timer task for this timer
+ SetEvent(DeleteHandle);
+
+ // create new timer
+ // first create event to delete timer
+ DeleteHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (DeleteHandle == NULL) {
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+ // set handle for caller
+ *pTimerHdl_p = (tEplTimerHdl) DeleteHandle;
+
+ // enter critical section
+ EnterCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
+
+ // fill data for thread
+ ThreadData_l.DelteHandle = DeleteHandle;
+ EPL_MEMCPY(&ThreadData_l.TimerArgument, &Argument_p,
+ sizeof(tEplTimerArg));
+ ThreadData_l.ulTimeout = ulTime_p;
+
+ // create thread to create waitable timer and wait for timer
+ ThreadHandle = CreateThread(NULL,
+ 0,
+ EplSdoTimeruThreadms,
+ &ThreadData_l, 0, &ThreadId);
+ if (ThreadHandle == NULL) {
+ // leave critical section
+ LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
+
+ // delte handle
+
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+ //---------------------------------------------------------------------------
+//
+// Function: EplTimeruDeleteTimer
+//
+// Description: function delte a timer
+//
+//
+//
+// Parameters: pTimerHdl_p = pointer to a buffer to fill in the handle
+//
+//
+// Returns: tEplKernel = errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p)
+{
+ tEplKernel Ret;
+ HANDLE DeleteHandle;
+
+ Ret = kEplSuccessful;
+
+ // check parameter
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ DeleteHandle = (HANDLE) (*pTimerHdl_p);
+
+ // set event to end timer task for this timer
+ SetEvent(DeleteHandle);
+
+ // set handle invalide
+ *pTimerHdl_p = 0;
+
+ Exit:
+ return Ret;
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplSdoTimeruThreadms
+//
+// Description: function to process timer as thread
+//
+//
+//
+// Parameters: lpParameter = pointer to structur of type tEplTimeruThread
+//
+//
+// Returns: DWORD = Errorcode
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+DWORD PUBLIC EplSdoTimeruThreadms(LPVOID lpParameter)
+{
+ tEplKernel Ret;
+ tEplTimeruThread *pThreadData;
+ HANDLE aHandles[2];
+ BOOL fReturn;
+ LARGE_INTEGER TimeoutTime;
+ unsigned long ulEvent;
+ tEplEvent EplEvent;
+ tEplTimeruThread ThreadData;
+ tEplTimerEventArg TimerEventArg;
+
+ Ret = kEplSuccessful;
+
+ // get pointer to data
+ pThreadData = (tEplTimeruThread *) lpParameter;
+ // copy thread data
+ EPL_MEMCPY(&ThreadData, pThreadData, sizeof(ThreadData));
+ pThreadData = &ThreadData;
+
+ // leave critical section
+ LeaveCriticalSection(EplTimeruInstance_g.m_pCriticalSection);
+
+ // create waitable timer
+ aHandles[1] = CreateWaitableTimer(NULL, FALSE, NULL);
+ if (aHandles[1] == NULL) {
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+ // set timer
+ // set timeout interval -> needed to be negativ
+ // -> because relative timeout
+ // -> multiply by 10000 for 100 ns timebase of function
+ TimeoutTime.QuadPart = (((long long)pThreadData->ulTimeout) * -10000);
+ fReturn = SetWaitableTimer(aHandles[1],
+ &TimeoutTime, 0, NULL, NULL, FALSE);
+ if (fReturn == 0) {
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+ // save delte event handle in handle array
+ aHandles[0] = pThreadData->DelteHandle;
+
+ // wait for one of the events
+ ulEvent = WaitForMultipleObjects(2, &aHandles[0], FALSE, INFINITE);
+ if (ulEvent == WAIT_OBJECT_0) { // delte event
+
+ // close handels
+ CloseHandle(aHandles[1]);
+ // terminate thread
+ goto Exit;
+ } else if (ulEvent == (WAIT_OBJECT_0 + 1)) { // timer event
+ // call event function
+ TimerEventArg.m_TimerHdl =
+ (tEplTimerHdl) pThreadData->DelteHandle;
+ TimerEventArg.m_ulArg = pThreadData->TimerArgument.m_ulArg;
+
+ EplEvent.m_EventSink = pThreadData->TimerArgument.m_EventSink;
+ EplEvent.m_EventType = kEplEventTypeTimer;
+ EPL_MEMSET(&EplEvent.m_NetTime, 0x00, sizeof(tEplNetTime));
+ EplEvent.m_pArg = &TimerEventArg;
+ EplEvent.m_uiSize = sizeof(TimerEventArg);
+
+ Ret = EplEventuPost(&EplEvent);
+
+ // close handels
+ CloseHandle(aHandles[1]);
+ // terminate thread
+ goto Exit;
+
+ } else { // error
+ ulEvent = GetLastError();
+ TRACE1("Error in WaitForMultipleObjects Errorcode: 0x%x\n",
+ ulEvent);
+ // terminate thread
+ goto Exit;
+ }
+
+ Exit:
+ return Ret;
+}
+
+// EOF
diff --git a/drivers/staging/epl/EplVersion.h b/drivers/staging/epl/EplVersion.h
new file mode 100644
index 000000000000..75570d56b865
--- /dev/null
+++ b/drivers/staging/epl/EplVersion.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: This file defines the EPL version for the stack, as string
+ and for object 0x1018 within object dictionary.
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplVersion.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ all
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+****************************************************************************/
+
+#ifndef _EPL_VERSION_H_
+#define _EPL_VERSION_H_
+
+// NOTE:
+// All version macros should contain the same version number. But do not use
+// defines instead of the numbers. Because the macro EPL_STRING_VERSION() can not
+// convert a define to a string.
+//
+// Format: maj.min.build
+// maj = major version
+// min = minor version (will be set to 0 if major version will be incremented)
+// build = current build (will be set to 0 if minor version will be incremented)
+//
+#define DEFINED_STACK_VERSION EPL_STACK_VERSION (1, 3, 0)
+#define DEFINED_OBJ1018_VERSION EPL_OBJ1018_VERSION (1, 3, 0)
+#define DEFINED_STRING_VERSION EPL_STRING_VERSION (1, 3, 0)
+
+// -----------------------------------------------------------------------------
+#define EPL_PRODUCT_NAME "EPL V2"
+#define EPL_PRODUCT_VERSION DEFINED_STRING_VERSION
+#define EPL_PRODUCT_MANUFACTURER "SYS TEC electronic GmbH"
+
+#define EPL_PRODUCT_KEY "SO-1083"
+#define EPL_PRODUCT_DESCRIPTION "openPOWERLINK Protocol Stack Source"
+
+#endif // _EPL_VERSION_H_
+
+// Die letzte Zeile mu unbedingt eine leere Zeile sein, weil manche Compiler
+// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder).
diff --git a/drivers/staging/epl/Kconfig b/drivers/staging/epl/Kconfig
new file mode 100644
index 000000000000..9f939d5874ac
--- /dev/null
+++ b/drivers/staging/epl/Kconfig
@@ -0,0 +1,6 @@
+config EPL
+ tristate "openPOWERLINK protocol stack"
+ depends on NET && HIGH_RES_TIMERS && X86
+ default N
+ ---help---
+ Enable support for the openPOWERLINK network protocol stack.
diff --git a/drivers/staging/epl/Makefile b/drivers/staging/epl/Makefile
new file mode 100644
index 000000000000..a2c824187d21
--- /dev/null
+++ b/drivers/staging/epl/Makefile
@@ -0,0 +1,41 @@
+obj-$(CONFIG_EPL) += epl.o
+
+epl-objs := \
+ EplApiGeneric.o \
+ EplApiLinuxKernel.o \
+ EplApiProcessImage.o \
+ EplDllk.o \
+ EplDllkCal.o \
+ EplDlluCal.o \
+ EplErrorHandlerk.o \
+ EplEventk.o \
+ EplEventu.o \
+ EplIdentu.o \
+ EplNmtCnu.o \
+ EplNmtk.o \
+ EplNmtkCal.o \
+ EplNmtMnu.o \
+ EplNmtu.o \
+ EplNmtuCal.o \
+ EplObd.o \
+ EplObdkCal.o \
+ EplObdu.o \
+ EplObduCal.o \
+ EplPdok.o \
+ EplPdokCal.o \
+ EplPdou.o \
+ EplSdoAsndu.o \
+ EplSdoAsySequ.o \
+ EplSdoComu.o \
+ EplSdoUdpu.o \
+ EplStatusu.o \
+ EplTimeruLinuxKernel.o \
+ amix86.o \
+ SharedBuff.o \
+ ShbIpc-LinuxKernel.o \
+ TimerHighReskX86.o \
+ VirtualEthernetLinux.o \
+ SocketLinuxKernel.o \
+ proc_fs.o \
+ demo_main.o \
+ Edrv8139.o \
diff --git a/drivers/staging/epl/SharedBuff.c b/drivers/staging/epl/SharedBuff.c
new file mode 100644
index 000000000000..9fb09d6bc28e
--- /dev/null
+++ b/drivers/staging/epl/SharedBuff.c
@@ -0,0 +1,1799 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: Project independend shared buffer (linear + circular)
+
+ Description: Implementation of platform independend part for the
+ shared buffer
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ 2006/06/27 -rs: V 1.00 (initial version)
+
+****************************************************************************/
+
+#if defined(WIN32) || defined(_WIN32)
+
+#ifdef UNDER_RTSS
+ // RTX header
+#include <windows.h>
+#include <process.h>
+#include <rtapi.h>
+
+#elif __BORLANDC__
+ // borland C header
+#include <windows.h>
+#include <process.h>
+
+#elif WINCE
+#include <windows.h>
+
+#else
+ // MSVC needs to include windows.h at first
+ // the following defines ar necessary for function prototypes for waitable timers
+#define _WIN32_WINDOWS 0x0401
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <process.h>
+#endif
+
+#endif
+
+#include "global.h"
+#include "SharedBuff.h"
+#include "ShbIpc.h"
+
+// d.k. Linux kernel modules needs other header files for memcpy()
+#if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Configuration
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Constant definitions
+//---------------------------------------------------------------------------
+
+#define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
+#define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
+
+//---------------------------------------------------------------------------
+// Local types
+//---------------------------------------------------------------------------
+
+// structure to administrate circular shared buffer head
+typedef struct {
+ unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
+ unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
+ unsigned long m_ulBufferDataSize; // size of complete data area
+ unsigned long m_ulWrIndex; // current write index (set bevore write)
+ unsigned long m_ulRdIndex; // current read index (set after read)
+ unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
+ unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
+ unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
+ unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
+ unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
+ unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
+ tShbCirSigHndlrNewData m_pfnSigHndlrNewData; // application handler to signal new data
+ unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
+ tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
+ unsigned char m_Data; // start of data area (the real data size is unknown at this time)
+
+} tShbCirBuff;
+
+// structure to administrate linear shared buffer head
+typedef struct {
+ unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
+ unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
+ unsigned long m_ulBufferDataSize; // size of complete data area
+ unsigned char m_Data; // start of data area (the real data size is unknown at this time)
+
+} tShbLinBuff;
+
+// type to save size of a single data block inside the circular shared buffer
+typedef struct {
+ unsigned int m_uiFullBlockSize:28; // a single block must not exceed a length of 256MByte :-)
+ unsigned int m_uiAlignFillBytes:4;
+
+} tShbCirBlockSize;
+
+#define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
+#define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
+
+#define SBL_BLOCK_ALIGNMENT 4
+#define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
+
+//---------------------------------------------------------------------------
+// Global variables
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Local variables
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Prototypes of internal functions
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Get pointer to Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+
+ pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
+ ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
+
+ return (pShbCirBuff);
+
+}
+
+//---------------------------------------------------------------------------
+// Get pointer to Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p)
+{
+
+ tShbLinBuff *pShbLinBuff;
+
+ pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
+ ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
+
+ return (pShbLinBuff);
+
+}
+
+// not inlined internal functions
+int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p);
+void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
+ unsigned int fTimeOut_p);
+
+#endif
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+#if !defined(INLINE_ENABLED)
+// not inlined external functions
+
+//---------------------------------------------------------------------------
+// Initialize Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbInit(void)
+{
+
+ tShbError ShbError;
+
+ ShbError = ShbIpcInit();
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Deinitialize Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbExit(void)
+{
+
+ tShbError ShbError;
+
+ ShbError = ShbIpcExit();
+
+ return (ShbError);
+
+}
+
+//-------------------------------------------------------------------------//
+// //
+// C i r c u l a r S h a r e d B u f f e r //
+// //
+//-------------------------------------------------------------------------//
+
+//---------------------------------------------------------------------------
+// Allocate Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
+ const char *pszBufferID_p,
+ tShbInstance * ppShbInstance_p,
+ unsigned int *pfShbNewCreated_p)
+{
+
+ tShbInstance pShbInstance;
+ tShbCirBuff *pShbCirBuff;
+ unsigned int fShbNewCreated;
+ unsigned long ulBufferDataSize;
+ unsigned long ulBufferTotalSize;
+ tShbError ShbError;
+
+ // check arguments
+ if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+
+ // calculate length of memory to allocate
+ ulBufferDataSize =
+ (ulBufferSize_p +
+ (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
+ ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
+
+ // allocate a new or open an existing shared buffer
+ ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
+ &pShbInstance, &fShbNewCreated);
+ if (ShbError != kShbOk) {
+ goto Exit;
+ }
+
+ if (pShbInstance == NULL) {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+
+ // get pointer to shared buffer
+ pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance);
+
+ // if the shared buffer was new created, than this process has
+ // to initialize it, otherwise the buffer is already in use
+ // and *must not* be reseted
+ if (fShbNewCreated) {
+#ifndef NDEBUG
+ {
+ memset(pShbCirBuff, 0xCC, ulBufferTotalSize);
+ }
+#endif
+
+ pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
+ pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
+ pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
+ pShbCirBuff->m_ulWrIndex = 0;
+ pShbCirBuff->m_ulRdIndex = 0;
+ pShbCirBuff->m_ulNumOfWriteJobs = 0;
+ pShbCirBuff->m_ulDataInUse = 0;
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+ pShbCirBuff->m_ulDataReadable = 0;
+ pShbCirBuff->m_ulBlocksReadable = 0;
+ pShbCirBuff->m_pfnSigHndlrNewData = NULL;
+ pShbCirBuff->m_fBufferLocked = FALSE;
+ pShbCirBuff->m_pfnSigHndlrReset = NULL;
+ } else {
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+ }
+
+ Exit:
+
+ *ppShbInstance_p = pShbInstance;
+ *pfShbNewCreated_p = fShbNewCreated;
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Release Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p)
+{
+
+ tShbError ShbError;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+#endif // !defined(INLINE_ENABLED)
+
+#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Reset Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
+ unsigned long ulTimeOut_p,
+ tShbCirSigHndlrReset
+ pfnSignalHandlerReset_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
+ tShbError ShbError;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ // start reset job by setting request request in buffer header
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ if (!pShbCirBuff->m_fBufferLocked) {
+ ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
+
+ pShbCirBuff->m_fBufferLocked = TRUE;
+ pShbCirBuff->m_pfnSigHndlrReset =
+ pfnSignalHandlerReset_p;
+ } else {
+ ShbError = kShbAlreadyReseting;
+ }
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ if (ShbError != kShbOk) {
+ goto Exit;
+ }
+
+ // if there is currently no running write operation then reset buffer
+ // immediately, otherwise wait until the last write job is ready by
+ // starting a signal process
+ if (ulNumOfWriteJobs == 0) {
+ // there is currently no running write operation
+ // -> reset buffer immediately
+ ShbCirSignalHandlerReset(pShbInstance_p, FALSE);
+ ShbError = kShbOk;
+ } else {
+ // there is currently at least one running write operation
+ // -> starting signal process to wait until the last write job is ready
+ ShbError =
+ ShbIpcStartSignalingJobReady(pShbInstance_p, ulTimeOut_p,
+ ShbCirSignalHandlerReset);
+ }
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Write data block to Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
+ const void *pSrcDataBlock_p,
+ unsigned long ulDataBlockSize_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ tShbCirBlockSize ShbCirBlockSize;
+ unsigned int uiFullBlockSize;
+ unsigned int uiAlignFillBytes;
+ unsigned char *pShbCirDataPtr;
+ unsigned char *pScrDataPtr;
+ unsigned long ulDataSize;
+ unsigned long ulChunkSize;
+ unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
+ unsigned int fSignalNewData;
+ unsigned int fSignalReset;
+ tShbError ShbError;
+ tShbError ShbError2;
+ int fRes;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
+ fSignalNewData = FALSE;
+ fSignalReset = FALSE;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ // calculate data block size in circular buffer
+ ulDataSize =
+ (ulDataBlockSize_p +
+ (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
+ uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
+ uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
+
+ ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
+ ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
+
+ // reserve the needed memory for the write operation to do now
+ // and make necessary adjustments in the circular buffer header
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ // check if there is sufficient memory available to store
+ // the new data
+ fRes =
+ uiFullBlockSize <=
+ (pShbCirBuff->m_ulBufferDataSize -
+ pShbCirBuff->m_ulDataInUse);
+ if (fRes) {
+ // set write pointer for the write operation to do now
+ // to the current write pointer of the circular buffer
+ ulWrIndex = pShbCirBuff->m_ulWrIndex;
+
+ // reserve the needed memory for the write operation to do now
+ pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
+
+ // set new write pointer behind the reserved memory
+ // for the write operation to do now
+ pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
+ pShbCirBuff->m_ulWrIndex %=
+ pShbCirBuff->m_ulBufferDataSize;
+
+ // increment number of currently (parallel running)
+ // write operations
+ pShbCirBuff->m_ulNumOfWriteJobs++;
+ }
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ if (!fRes) {
+ ShbError = kShbBufferFull;
+ goto Exit;
+ }
+
+ // copy the data to the circular buffer
+ // (the copy process itself will be done outside of any
+ // critical/locked section)
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+
+ // write real size of current block (incl. alignment fill bytes)
+ *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
+ ulWrIndex += sizeof(tShbCirBlockSize);
+ ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) {
+ // linear write operation
+ memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
+ ulDataBlockSize_p);
+ } else {
+ // wrap-around write operation
+ ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
+ memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
+ memcpy(pShbCirDataPtr, pScrDataPtr + ulChunkSize,
+ ulDataBlockSize_p - ulChunkSize);
+ }
+
+ // adjust header information for circular buffer with properties
+ // of the wiritten data block
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ pShbCirBuff->m_ulDataApended += uiFullBlockSize;
+ pShbCirBuff->m_ulBlocksApended++;
+
+ // decrement number of currently (parallel running) write operations
+ if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
+ // if there is no other write process running then
+ // set new size of readable (complete written) data and
+ // adjust number of readable blocks
+ pShbCirBuff->m_ulDataReadable +=
+ pShbCirBuff->m_ulDataApended;
+ pShbCirBuff->m_ulBlocksReadable +=
+ pShbCirBuff->m_ulBlocksApended;
+
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+
+ fSignalNewData = TRUE;
+ fSignalReset = pShbCirBuff->m_fBufferLocked;
+ }
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ // signal new data event to a potentially reading application
+ if (fSignalNewData) {
+ ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
+ if (ShbError == kShbOk) {
+ ShbError = ShbError2;
+ }
+ }
+ // signal that the last write job has been finished to allow
+ // a waiting application to reset the buffer now
+ if (fSignalReset) {
+ ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
+ if (ShbError == kShbOk) {
+ ShbError = ShbError2;
+ }
+ }
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Allocate block within the Circular Shared Buffer for chunk writing
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
+ tShbCirChunk * pShbCirChunk_p,
+ unsigned long ulDataBufferSize_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ tShbCirBlockSize ShbCirBlockSize;
+ unsigned int uiFullBlockSize;
+ unsigned int uiAlignFillBytes;
+ unsigned char *pShbCirDataPtr;
+ unsigned long ulDataSize;
+ unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
+ tShbError ShbError;
+ int fRes;
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if (ulDataBufferSize_p == 0) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ // calculate data block size in circular buffer
+ ulDataSize =
+ (ulDataBufferSize_p +
+ (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
+ uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
+ uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
+
+ ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
+ ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
+
+ // reserve the needed memory for the write operation to do now
+ // and make necessary adjustments in the circular buffer header
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ // check if there is sufficient memory available to store
+ // the new data
+ fRes =
+ (uiFullBlockSize <=
+ (pShbCirBuff->m_ulBufferDataSize -
+ pShbCirBuff->m_ulDataInUse));
+ if (fRes) {
+ // set write pointer for the write operation to do now
+ // to the current write pointer of the circular buffer
+ ulWrIndex = pShbCirBuff->m_ulWrIndex;
+
+ // reserve the needed memory for the write operation to do now
+ pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
+
+ // set new write pointer behind the reserved memory
+ // for the write operation to do now
+ pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
+ pShbCirBuff->m_ulWrIndex %=
+ pShbCirBuff->m_ulBufferDataSize;
+
+ // increment number of currently (parallel running)
+ // write operations
+ pShbCirBuff->m_ulNumOfWriteJobs++;
+ }
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ if (!fRes) {
+ ShbError = kShbBufferFull;
+ goto Exit;
+ }
+
+ // setup header information for allocated buffer
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+
+ // write real size of current block (incl. alignment fill bytes)
+ *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
+ ulWrIndex += sizeof(tShbCirBlockSize);
+ ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // setup chunk descriptor
+ pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
+ pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
+ pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
+ pShbCirChunk_p->m_fBufferCompleted = FALSE;
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Write data chunk into an allocated buffer of the Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
+ tShbCirChunk * pShbCirChunk_p,
+ const void *pSrcDataChunk_p,
+ unsigned long ulDataChunkSize_p,
+ unsigned int
+ *pfBufferCompleted_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ unsigned char *pShbCirDataPtr;
+ unsigned char *pScrDataPtr;
+ unsigned long ulSubChunkSize;
+ unsigned long ulWrIndex;
+ unsigned int fBufferCompleted;
+ unsigned int fSignalNewData;
+ unsigned int fSignalReset;
+ tShbError ShbError;
+ tShbError ShbError2;
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)
+ || (pfBufferCompleted_p == NULL)) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if (pShbCirChunk_p->m_fBufferCompleted) {
+ ShbError = kShbBufferAlreadyCompleted;
+ goto Exit;
+ }
+
+ if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ pScrDataPtr = (unsigned char *)pSrcDataChunk_p;
+ fSignalNewData = FALSE;
+ fSignalReset = FALSE;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
+
+ // copy the data to the circular buffer
+ // (the copy process itself will be done outside of any
+ // critical/locked section)
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+
+ if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) {
+ // linear write operation
+ memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
+ ulDataChunkSize_p);
+ } else {
+ // wrap-around write operation
+ ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
+ memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
+ memcpy(pShbCirDataPtr, pScrDataPtr + ulSubChunkSize,
+ ulDataChunkSize_p - ulSubChunkSize);
+ }
+
+ // adjust chunk descriptor
+ ulWrIndex += ulDataChunkSize_p;
+ ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
+ pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
+
+ fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
+ pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
+
+ // if the complete allocated buffer is filled with data then
+ // adjust header information for circular buffer with properties
+ // of the wiritten data block
+ if (fBufferCompleted) {
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ pShbCirBuff->m_ulDataApended +=
+ pShbCirChunk_p->m_uiFullBlockSize;
+ pShbCirBuff->m_ulBlocksApended++;
+
+ // decrement number of currently (parallel running) write operations
+ if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
+ // if there is no other write process running then
+ // set new size of readable (complete written) data and
+ // adjust number of readable blocks
+ pShbCirBuff->m_ulDataReadable +=
+ pShbCirBuff->m_ulDataApended;
+ pShbCirBuff->m_ulBlocksReadable +=
+ pShbCirBuff->m_ulBlocksApended;
+
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+
+ fSignalNewData = TRUE;
+ fSignalReset = pShbCirBuff->m_fBufferLocked;
+ }
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+ }
+
+ // signal new data event to a potentially reading application
+ if (fSignalNewData) {
+ ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
+ if (ShbError == kShbOk) {
+ ShbError = ShbError2;
+ }
+ }
+ // signal that the last write job has been finished to allow
+ // a waiting application to reset the buffer now
+ if (fSignalReset) {
+ ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
+ if (ShbError == kShbOk) {
+ ShbError = ShbError2;
+ }
+ }
+
+ *pfBufferCompleted_p = fBufferCompleted;
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Read data block from Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
+ void *pDstDataBlock_p,
+ unsigned long ulRdBuffSize_p,
+ unsigned long *pulDataBlockSize_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ tShbCirBlockSize ShbCirBlockSize;
+ unsigned long ulDataReadable;
+ unsigned char *pShbCirDataPtr;
+ unsigned char *pDstDataPtr;
+ unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
+ unsigned long ulChunkSize;
+ unsigned long ulRdIndex;
+ tShbError ShbError;
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+
+ if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ ShbError = kShbOk;
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ pDstDataPtr = (unsigned char *)pDstDataBlock_p;
+ ulDataSize = 0;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ // get total number of readable bytes for the whole circular buffer
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ ulDataReadable = pShbCirBuff->m_ulDataReadable;
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ // if there are readable data available, then there must be at least
+ // one complete readable data block
+ if (ulDataReadable > 0) {
+ // get pointer to start of data area and current read index
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+ ulRdIndex = pShbCirBuff->m_ulRdIndex;
+
+ // get real size of current block (incl. alignment fill bytes)
+ ShbCirBlockSize =
+ *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
+ ulRdIndex += sizeof(tShbCirBlockSize);
+ ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // get size of user data inside the current block
+ ulDataSize =
+ ShbCirBlockSize.m_uiFullBlockSize -
+ ShbCirBlockSize.m_uiAlignFillBytes;
+ ulDataSize -= sizeof(tShbCirBlockSize);
+ }
+
+ // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
+ if (ulDataSize > ulRdBuffSize_p) {
+ ulDataSize = ulRdBuffSize_p;
+ ShbError = kShbDataTruncated;
+ }
+
+ if (ulDataSize == 0) {
+ // nothing to do here
+ ShbError = kShbNoReadableData;
+ goto Exit;
+ }
+
+ // copy the data from the circular buffer
+ // (the copy process itself will be done outside of any
+ // critical/locked section)
+ if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
+ // linear read operation
+ memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
+ } else {
+ // wrap-around read operation
+ ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
+ memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
+ memcpy(pDstDataPtr + ulChunkSize, pShbCirDataPtr,
+ ulDataSize - ulChunkSize);
+ }
+
+#ifndef NDEBUG
+ {
+ tShbCirBlockSize ClrShbCirBlockSize;
+
+ if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
+ // linear buffer
+ memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
+ } else {
+ // wrap-around read operation
+ ulChunkSize =
+ pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
+ memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
+ memset(pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
+ }
+
+ ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int) */ -1; // -1 = xFFFFFFF
+ ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int) */ -1; // -1 = Fxxxxxxx
+ *(tShbCirBlockSize *) (pShbCirDataPtr +
+ pShbCirBuff->m_ulRdIndex) =
+ ClrShbCirBlockSize;
+ }
+#endif // #ifndef NDEBUG
+
+ // set new size of readable data, data in use, new read index
+ // and adjust number of readable blocks
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
+ pShbCirBuff->m_ulDataReadable -=
+ ShbCirBlockSize.m_uiFullBlockSize;
+ pShbCirBuff->m_ulBlocksReadable--;
+
+ //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ if ((pShbCirBuff->m_ulDataInUse == 0)
+ && (pShbCirBuff->m_ulDataReadable == 0)) {
+ ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
+
+ pShbCirBuff->m_ulWrIndex = 0;
+ pShbCirBuff->m_ulRdIndex = 0;
+ } else
+ //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+ {
+ pShbCirBuff->m_ulRdIndex +=
+ ShbCirBlockSize.m_uiFullBlockSize;
+ pShbCirBuff->m_ulRdIndex %=
+ pShbCirBuff->m_ulBufferDataSize;
+ }
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ Exit:
+
+ *pulDataBlockSize_p = ulDataSize;
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Get data size of next readable block from Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
+ unsigned long
+ *pulDataBlockSize_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ unsigned long ulDataReadable;
+ unsigned char *pShbCirDataPtr;
+ tShbCirBlockSize ShbCirBlockSize;
+ unsigned long ulDataSize;
+ tShbError ShbError;
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ ulDataSize = 0;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ // get total number of readable bytes for the whole circular buffer
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ ulDataReadable = pShbCirBuff->m_ulDataReadable;
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ // if there are readable data available, then there must be at least
+ // one complete readable data block
+ if (ulDataReadable > 0) {
+ pShbCirDataPtr =
+ &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
+
+ // get real size of current block (incl. alignment fill bytes)
+ ShbCirBlockSize = *(tShbCirBlockSize *) pShbCirDataPtr;
+
+ // get size of user data inside the current block
+ ulDataSize =
+ ShbCirBlockSize.m_uiFullBlockSize -
+ ShbCirBlockSize.m_uiAlignFillBytes;
+ ulDataSize -= sizeof(tShbCirBlockSize);
+ }
+
+ Exit:
+
+ *pulDataBlockSize_p = ulDataSize;
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Get number of readable blocks from Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
+ unsigned long
+ *pulDataBlockCount_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ unsigned long ulBlockCount;
+ tShbError ShbError;
+
+ // check arguments
+ if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ ulBlockCount = 0;
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ *pulDataBlockCount_p = ulBlockCount;
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Set application handler to signal new data for Circular Shared Buffer
+// d.k.: new parameter priority as enum
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData(tShbInstance
+ pShbInstance_p,
+ tShbCirSigHndlrNewData
+ pfnSignalHandlerNewData_p,
+ tShbPriority
+ ShbPriority_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ tShbError ShbError;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ if (pfnSignalHandlerNewData_p != NULL) {
+ // set a new signal handler
+ if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
+ ShbError = kShbAlreadySignaling;
+ goto Exit;
+ }
+
+ pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
+ ShbError =
+ ShbIpcStartSignalingNewData(pShbInstance_p,
+ ShbCirSignalHandlerNewData,
+ ShbPriority_p);
+ } else {
+ // remove existing signal handler
+ ShbError = ShbIpcStopSignalingNewData(pShbInstance_p);
+ if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
+ pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p, 0);
+ }
+ pShbCirBuff->m_pfnSigHndlrNewData = NULL;
+ }
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+#endif
+
+#if !defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// DEBUG: Trace Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+#ifndef NDEBUG
+tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ char szMagigID[sizeof(SBC_MAGIC_ID) + 1];
+ tShbCirBlockSize ShbCirBlockSize;
+ unsigned long ulDataReadable;
+ unsigned char *pShbCirDataPtr;
+ unsigned long ulBlockIndex;
+ unsigned int nBlockCount;
+ unsigned long ulDataSize;
+ unsigned long ulChunkSize;
+ unsigned long ulRdIndex;
+ tShbError ShbError;
+
+ TRACE0("\n\n##### Circular Shared Buffer #####\n");
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
+ (unsigned long)pShbInstance_p);
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ *(unsigned long *)&szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
+ szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
+
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ TRACE1("\nBuffer Address: 0x%08lX\n",
+ (unsigned long)pShbCirBuff);
+
+ TRACE0("\nHeader Info:");
+ TRACE2("\nMagigID: '%s' (%08lX)", szMagigID,
+ pShbCirBuff->m_ShbCirMagicID);
+ TRACE1("\nBufferTotalSize: %4lu [Bytes]",
+ pShbCirBuff->m_ulBufferTotalSize);
+ TRACE1("\nBufferDataSize: %4lu [Bytes]",
+ pShbCirBuff->m_ulBufferDataSize);
+ TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
+ TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
+ TRACE1("\nNumOfWriteJobs: %4lu",
+ pShbCirBuff->m_ulNumOfWriteJobs);
+ TRACE1("\nDataInUse: %4lu [Bytes]",
+ pShbCirBuff->m_ulDataInUse);
+ TRACE1("\nDataApended: %4lu [Bytes]",
+ pShbCirBuff->m_ulDataApended);
+ TRACE1("\nBlocksApended: %4lu",
+ pShbCirBuff->m_ulBlocksApended);
+ TRACE1("\nDataReadable: %4lu [Bytes]",
+ pShbCirBuff->m_ulDataReadable);
+ TRACE1("\nBlocksReadable: %4lu",
+ pShbCirBuff->m_ulBlocksReadable);
+ TRACE1("\nSigHndlrNewData: %08lX",
+ (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
+ TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
+ TRACE1("\nSigHndlrReset: %08lX",
+ (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
+
+ ShbTraceDump(&pShbCirBuff->m_Data,
+ pShbCirBuff->m_ulBufferDataSize, 0x00000000L,
+ "\nData Area:");
+
+ ulDataReadable = pShbCirBuff->m_ulDataReadable;
+ nBlockCount = 1;
+ ulBlockIndex = pShbCirBuff->m_ulRdIndex;
+
+ while (ulDataReadable > 0) {
+ TRACE1("\n\n--- Block #%u ---", nBlockCount);
+
+ // get pointer to start of data area and current read index
+ pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
+ ulRdIndex = ulBlockIndex;
+
+ // get real size of current block (incl. alignment fill bytes)
+ ShbCirBlockSize =
+ *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
+ ulRdIndex += sizeof(tShbCirBlockSize);
+ ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ // get size of user data inside the current block
+ ulDataSize =
+ ShbCirBlockSize.m_uiFullBlockSize -
+ ShbCirBlockSize.m_uiAlignFillBytes;
+ ulDataSize -= sizeof(tShbCirBlockSize);
+
+ TRACE1
+ ("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)",
+ ShbCirBlockSize.m_uiFullBlockSize);
+ TRACE1("\nUser Data Size: %4lu [Bytes]",
+ ulDataSize);
+ TRACE1("\nAlignment Fill Bytes: %4u [Bytes]",
+ ShbCirBlockSize.m_uiAlignFillBytes);
+
+ if (ulRdIndex + ulDataSize <=
+ pShbCirBuff->m_ulBufferDataSize) {
+ // linear data buffer
+ ShbTraceDump(pShbCirDataPtr + ulRdIndex,
+ ulDataSize, 0x00000000L, NULL);
+ } else {
+ // wrap-around data buffer
+ ulChunkSize =
+ pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
+ ShbTraceDump(pShbCirDataPtr + ulRdIndex,
+ ulChunkSize, 0x00000000L, NULL);
+ ShbTraceDump(pShbCirDataPtr,
+ ulDataSize - ulChunkSize,
+ ulChunkSize, NULL);
+ }
+
+ nBlockCount++;
+
+ ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
+ ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
+
+ ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
+ }
+
+ ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount - 1);
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ Exit:
+
+ return (ShbError);
+
+}
+#endif
+
+//-------------------------------------------------------------------------//
+// //
+// L i n e a r S h a r e d B u f f e r //
+// //
+//-------------------------------------------------------------------------//
+
+//---------------------------------------------------------------------------
+// Allocate Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
+ const char *pszBufferID_p,
+ tShbInstance * ppShbInstance_p,
+ unsigned int *pfShbNewCreated_p)
+{
+
+ tShbInstance pShbInstance;
+ tShbLinBuff *pShbLinBuff;
+ unsigned int fShbNewCreated;
+ unsigned long ulBufferDataSize;
+ unsigned long ulBufferTotalSize;
+ tShbError ShbError;
+
+ // check arguments
+ if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+
+ // calculate length of memory to allocate
+ ulBufferDataSize =
+ (ulBufferSize_p +
+ (SBL_BLOCK_ALIGNMENT - 1)) & ~(SBL_BLOCK_ALIGNMENT - 1);
+ ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
+
+ // allocate a new or open an existing shared buffer
+ ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
+ &pShbInstance, &fShbNewCreated);
+ if (ShbError != kShbOk) {
+ goto Exit;
+ }
+
+ if (pShbInstance == NULL) {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+
+ // get pointer to shared buffer
+ pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance);
+
+ // if the shared buffer was new created, than this process has
+ // to initialize it, otherwise the buffer is already in use
+ // and *must not* be reseted
+ if (fShbNewCreated) {
+#ifndef NDEBUG
+ {
+ memset(pShbLinBuff, 0xCC, ulBufferTotalSize);
+ }
+#endif
+
+ pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
+ pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
+ pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
+ } else {
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+ }
+
+ Exit:
+
+ *ppShbInstance_p = pShbInstance;
+ *pfShbNewCreated_p = fShbNewCreated;
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Release Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p)
+{
+
+ tShbError ShbError;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+#endif // !defined(INLINE_ENABLED)
+
+#if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Write data block to Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
+ unsigned long ulDstBufferOffs_p,
+ const void *pSrcDataBlock_p,
+ unsigned long ulDataBlockSize_p)
+{
+
+ tShbLinBuff *pShbLinBuff;
+ unsigned char *pShbLinDataPtr;
+ unsigned char *pScrDataPtr;
+ unsigned long ulBufferDataSize;
+ tShbError ShbError;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+ pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
+ pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
+ ShbError = kShbOk;
+
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ // check if offeset and size for the write operation matches with
+ // the size of the shared buffer
+ ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
+ if ((ulDstBufferOffs_p > ulBufferDataSize) ||
+ (ulDataBlockSize_p > ulBufferDataSize) ||
+ ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
+ ShbError = kShbDataOutsideBufferArea;
+ goto Exit;
+ }
+
+ // copy the data to the linear buffer
+ // (the copy process will be done inside of any critical/locked section)
+ pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
+ pShbLinDataPtr += ulDstBufferOffs_p;
+
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ memcpy(pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Read data block from Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
+ void *pDstDataBlock_p,
+ unsigned long ulSrcBufferOffs_p,
+ unsigned long ulDataBlockSize_p)
+{
+
+ tShbLinBuff *pShbLinBuff;
+ unsigned char *pShbLinDataPtr;
+ unsigned char *pDstDataPtr;
+ unsigned long ulBufferDataSize;
+ tShbError ShbError;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
+ // nothing to do here
+ ShbError = kShbOk;
+ goto Exit;
+ }
+
+ if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
+ ShbError = kShbExceedDataSizeLimit;
+ goto Exit;
+ }
+
+ pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
+ pDstDataPtr = (unsigned char *)pDstDataBlock_p;
+ ShbError = kShbOk;
+
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ // check if offeset and size for the read operation matches with
+ // the size of the shared buffer
+ ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
+ if ((ulSrcBufferOffs_p > ulBufferDataSize) ||
+ (ulDataBlockSize_p > ulBufferDataSize) ||
+ ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
+ ShbError = kShbDataOutsideBufferArea;
+ goto Exit;
+ }
+
+ // copy the data to the linear buffer
+ // (the copy process will be done inside of any critical/locked section)
+ pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
+ pShbLinDataPtr += ulSrcBufferOffs_p;
+
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ memcpy(pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+#endif
+
+#if !defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// DEBUG: Trace Linear Shared Buffer
+//---------------------------------------------------------------------------
+
+#ifndef NDEBUG
+tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p)
+{
+
+ tShbLinBuff *pShbLinBuff;
+ char szMagigID[sizeof(SBL_MAGIC_ID) + 1];
+ tShbError ShbError;
+
+ TRACE0("\n\n##### Linear Shared Buffer #####\n");
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
+ (unsigned long)pShbInstance_p);
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+
+ pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
+ ShbError = kShbInvalidBufferType;
+ goto Exit;
+ }
+
+ *(unsigned int *)&szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
+ szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
+
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ TRACE1("\nBuffer Address: 0x%08lX\n",
+ (unsigned long)pShbLinBuff);
+
+ TRACE0("\nHeader Info:");
+ TRACE2("\nMagigID: '%s' (%08X)", szMagigID,
+ pShbLinBuff->m_ShbLinMagicID);
+ TRACE1("\nBufferTotalSize: %4lu [Bytes]",
+ pShbLinBuff->m_ulBufferTotalSize);
+ TRACE1("\nBufferDataSize: %4lu [Bytes]",
+ pShbLinBuff->m_ulBufferDataSize);
+
+ ShbTraceDump(&pShbLinBuff->m_Data,
+ pShbLinBuff->m_ulBufferDataSize, 0x00000000L,
+ "\nData Area:");
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ Exit:
+
+ return (ShbError);
+
+}
+#endif
+
+//---------------------------------------------------------------------------
+// Dump buffer contents
+//---------------------------------------------------------------------------
+
+#ifndef NDEBUG
+tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
+ unsigned long ulDataSize_p,
+ unsigned long ulAddrOffset_p, const char *pszInfoText_p)
+{
+
+ const unsigned char *pabBuffData;
+ unsigned long ulBuffSize;
+ unsigned char bData;
+ int nRow;
+ int nCol;
+
+ // get pointer to buffer and length of buffer
+ pabBuffData = pabStartAddr_p;
+ ulBuffSize = ulDataSize_p;
+
+ if (pszInfoText_p != NULL) {
+ TRACE0(pszInfoText_p);
+ }
+ // dump buffer contents
+ for (nRow = 0;; nRow++) {
+ TRACE1("\n%08lX: ",
+ (unsigned long)(nRow * 0x10) + ulAddrOffset_p);
+
+ for (nCol = 0; nCol < 16; nCol++) {
+ if ((unsigned long)nCol < ulBuffSize) {
+ TRACE1("%02X ",
+ (unsigned int)*(pabBuffData + nCol));
+ } else {
+ TRACE0(" ");
+ }
+ }
+
+ TRACE0(" ");
+
+ for (nCol = 0; nCol < 16; nCol++) {
+ bData = *pabBuffData++;
+ if ((unsigned long)nCol < ulBuffSize) {
+ if ((bData >= 0x20) && (bData < 0x7F)) {
+ TRACE1("%c", bData);
+ } else {
+ TRACE0(".");
+ }
+ } else {
+ TRACE0(" ");
+ }
+ }
+
+ if (ulBuffSize > 16) {
+ ulBuffSize -= 16;
+ } else {
+ break;
+ }
+ }
+
+ return (kShbOk);
+
+}
+#endif // #ifndef NDEBUG
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+// Handler to signal new data event for Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+ unsigned long ulDataSize;
+ unsigned long ulBlockCount;
+ tShbError ShbError;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ return FALSE;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ return FALSE;
+ }
+
+ // call application handler
+ if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
+/* do
+ {*/
+ ShbError = ShbCirGetReadDataSize(pShbInstance_p, &ulDataSize);
+ if ((ulDataSize > 0) && (ShbError == kShbOk)) {
+ pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p,
+ ulDataSize);
+ }
+
+ ShbError =
+ ShbCirGetReadBlockCount(pShbInstance_p, &ulBlockCount);
+/* }
+ while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
+ }
+ // Return TRUE if there are pending blocks.
+ // In that case ShbIpc tries to call this function again immediately if there
+ // is no other filled shared buffer with higher priority.
+ return ((ulBlockCount > 0) && (ShbError == kShbOk));
+
+}
+
+//---------------------------------------------------------------------------
+// Handler to reset Circular Shared Buffer
+//---------------------------------------------------------------------------
+
+void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
+ unsigned int fTimeOut_p)
+{
+
+ tShbCirBuff *pShbCirBuff;
+
+ // check arguments
+ if (pShbInstance_p == NULL) {
+ return;
+ }
+
+ pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
+ if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
+ return;
+ }
+
+ // reset buffer header
+ if (!fTimeOut_p) {
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ pShbCirBuff->m_ulWrIndex = 0;
+ pShbCirBuff->m_ulRdIndex = 0;
+ pShbCirBuff->m_ulNumOfWriteJobs = 0;
+ pShbCirBuff->m_ulDataInUse = 0;
+ pShbCirBuff->m_ulDataApended = 0;
+ pShbCirBuff->m_ulBlocksApended = 0;
+ pShbCirBuff->m_ulDataReadable = 0;
+ pShbCirBuff->m_ulBlocksReadable = 0;
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+#ifndef NDEBUG
+ {
+ memset(&pShbCirBuff->m_Data, 0xCC,
+ pShbCirBuff->m_ulBufferDataSize);
+ }
+#endif
+ }
+
+ // call application handler
+ if (pShbCirBuff->m_pfnSigHndlrReset != NULL) {
+ pShbCirBuff->m_pfnSigHndlrReset(pShbInstance_p, fTimeOut_p);
+ }
+
+ // unlock buffer
+ ShbIpcEnterAtomicSection(pShbInstance_p);
+ {
+ pShbCirBuff->m_fBufferLocked = FALSE;
+ pShbCirBuff->m_pfnSigHndlrReset = NULL;
+ }
+ ShbIpcLeaveAtomicSection(pShbInstance_p);
+
+ return;
+
+}
+
+#endif
+
+// EOF
diff --git a/drivers/staging/epl/SharedBuff.h b/drivers/staging/epl/SharedBuff.h
new file mode 100644
index 000000000000..0ec1b4b9e6ae
--- /dev/null
+++ b/drivers/staging/epl/SharedBuff.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: Project independend shared buffer (linear + circular)
+
+ Description: Declaration of platform independend part for the
+ shared buffer
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ 2006/06/27 -rs: V 1.00 (initial version)
+
+****************************************************************************/
+
+#ifndef _SHAREDBUFF_H_
+#define _SHAREDBUFF_H_
+
+//---------------------------------------------------------------------------
+// Type definitions
+//---------------------------------------------------------------------------
+
+typedef enum {
+ kShbOk = 0,
+ kShbNoReadableData = 1,
+ kShbDataTruncated = 2,
+ kShbBufferFull = 3,
+ kShbDataOutsideBufferArea = 4,
+ kShbBufferAlreadyCompleted = 5,
+ kShbMemUsedByOtherProcs = 6,
+ kShbOpenMismatch = 7,
+ kShbInvalidBufferType = 8,
+ kShbInvalidArg = 9,
+ kShbBufferInvalid = 10,
+ kShbOutOfMem = 11,
+ kShbAlreadyReseting = 12,
+ kShbAlreadySignaling = 13,
+ kShbExceedDataSizeLimit = 14,
+
+} tShbError;
+
+// 2006/08/24 d.k.: Priority for threads (new data, job signaling)
+typedef enum {
+ kShbPriorityLow = 0,
+ kShbPriorityNormal = 1,
+ kshbPriorityHigh = 2
+} tShbPriority;
+
+typedef struct {
+ unsigned int m_uiFullBlockSize; // real size of allocated block (incl. alignment fill bytes)
+ unsigned long m_ulAvailableSize; // still available size for data
+ unsigned long m_ulWrIndex; // current write index
+ unsigned int m_fBufferCompleted; // TRUE if allocated block is complete filled with data
+
+} tShbCirChunk;
+
+typedef void *tShbInstance;
+
+typedef void (*tShbCirSigHndlrNewData) (tShbInstance pShbInstance_p,
+ unsigned long ulDataBlockSize_p);
+typedef void (*tShbCirSigHndlrReset) (tShbInstance pShbInstance_p,
+ unsigned int fTimeOut_p);
+
+//---------------------------------------------------------------------------
+// Prototypes
+//---------------------------------------------------------------------------
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*#if defined(INLINE_FUNCTION_DEF)
+ #undef INLINE_FUNCTION
+ #define INLINE_FUNCTION INLINE_FUNCTION_DEF
+ #define INLINE_ENABLED TRUE
+ #define SHAREDBUFF_INLINED
+ #include "SharedBuff.c"
+#endif
+*/
+
+ tShbError ShbInit(void);
+ tShbError ShbExit(void);
+
+// Circular Shared Buffer
+ tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
+ const char *pszBufferID_p,
+ tShbInstance * ppShbInstance_p,
+ unsigned int *pfShbNewCreated_p);
+ tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p);
+
+#if !defined(INLINE_ENABLED)
+
+ tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
+ unsigned long ulTimeOut_p,
+ tShbCirSigHndlrReset
+ pfnSignalHandlerReset_p);
+ tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
+ const void *pSrcDataBlock_p,
+ unsigned long ulDataBlockSize_p);
+ tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
+ tShbCirChunk * pShbCirChunk_p,
+ unsigned long ulDataBufferSize_p);
+ tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
+ tShbCirChunk * pShbCirChunk_p,
+ const void *pSrcDataChunk_p,
+ unsigned long ulDataChunkSize_p,
+ unsigned int *pfBufferCompleted_p);
+ tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
+ void *pDstDataBlock_p,
+ unsigned long ulRdBuffSize_p,
+ unsigned long *pulDataBlockSize_p);
+ tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
+ unsigned long *pulDataBlockSize_p);
+ tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
+ unsigned long *pulDataBlockCount_p);
+ tShbError ShbCirSetSignalHandlerNewData(tShbInstance pShbInstance_p,
+ tShbCirSigHndlrNewData
+ pfnShbSignalHandlerNewData_p,
+ tShbPriority ShbPriority_p);
+
+#endif
+
+// Linear Shared Buffer
+ tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
+ const char *pszBufferID_p,
+ tShbInstance * ppShbInstance_p,
+ unsigned int *pfShbNewCreated_p);
+ tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p);
+
+#if !defined(INLINE_ENABLED)
+
+ tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
+ unsigned long ulDstBufferOffs_p,
+ const void *pSrcDataBlock_p,
+ unsigned long ulDataBlockSize_p);
+ tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
+ void *pDstDataBlock_p,
+ unsigned long ulSrcBufferOffs_p,
+ unsigned long ulDataBlockSize_p);
+
+#endif
+
+#ifndef NDEBUG
+ tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p);
+ tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p);
+ tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
+ unsigned long ulDataSize_p,
+ unsigned long ulAddrOffset_p,
+ const char *pszInfoText_p);
+#else
+#define ShbCirTraceBuffer(p0)
+#define ShbLinTraceBuffer(p0)
+#define ShbTraceDump(p0, p1, p2, p3)
+#endif
+
+#undef INLINE_ENABLED // disable actual inlining of functions
+#undef INLINE_FUNCTION
+#define INLINE_FUNCTION // define INLINE_FUNCTION to nothing
+
+#ifdef __cplusplus
+}
+#endif
+#endif // #ifndef _SHAREDBUFF_H_
diff --git a/drivers/staging/epl/ShbIpc-LinuxKernel.c b/drivers/staging/epl/ShbIpc-LinuxKernel.c
new file mode 100644
index 000000000000..1d3cb3f13de1
--- /dev/null
+++ b/drivers/staging/epl/ShbIpc-LinuxKernel.c
@@ -0,0 +1,966 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: Project independend shared buffer (linear + circular)
+
+ Description: Implementation of platform specific part for the
+ shared buffer
+ (Implementation for Linux KernelSpace)
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ 2006/06/28 -rs: V 1.00 (initial version)
+
+****************************************************************************/
+
+#include "global.h"
+#include "SharedBuff.h"
+#include "ShbIpc.h"
+#include "ShbLinuxKernel.h"
+#include "Debug.h"
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/processor.h>
+//#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Configuration
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Constant definitions
+//---------------------------------------------------------------------------
+
+#define MAX_LEN_BUFFER_ID 256
+
+#define TIMEOUT_ENTER_ATOMIC 1000 // (ms) for debgging: INFINITE
+#define TIMEOUT_TERM_THREAD 1000
+#define INFINITE 3600
+
+#define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
+#define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
+
+#define INVALID_ID -1
+
+#define TABLE_SIZE 10
+
+//---------------------------------------------------------------------------
+// Local types
+//---------------------------------------------------------------------------
+
+// This structure is the common header for the shared memory region used
+// by all processes attached this shared memory. It includes common
+// information to administrate/manage the shared buffer from a couple of
+// separated processes (e.g. the refernce counter). This structure is
+// located at the start of the shared memory region itself and exists
+// consequently only one times per shared memory instance.
+typedef struct {
+
+ unsigned long m_ulShMemSize;
+ unsigned long m_ulRefCount;
+ int m_iBufferId;
+// int m_iUserSpaceMem; //0 for userspace mem !=0 kernelspace mem
+ spinlock_t m_SpinlockBuffAccess;
+ BOOL m_fNewData;
+ BOOL m_fJobReady;
+ wait_queue_head_t m_WaitQueueNewData;
+ wait_queue_head_t m_WaitQueueJobReady;
+
+#ifndef NDEBUG
+ unsigned long m_ulOwnerProcID;
+#endif
+
+} tShbMemHeader;
+
+// This structure is the "external entry point" from a separate process
+// to get access to a shared buffer. This structure includes all platform
+// resp. target specific information to administrate/manage the shared
+// buffer from a separate process. Every process attached to the shared
+// buffer has its own runtime instance of this structure with its individual
+// runtime data (e.g. the scope of an event handle is limitted to the
+// owner process only). The structure member <m_pShbMemHeader> points
+// to the (process specific) start address of the shared memory region
+// itself.
+typedef struct {
+ unsigned long m_SbiMagicID; // magic ID ("SBI+")
+// void* m_pSharedMem;
+ int m_tThreadNewDataId;
+ long m_lThreadNewDataNice; // nice value of the new data thread
+ int m_tThreadJobReadyId;
+ unsigned long m_ulFlagsBuffAccess; // d.k. moved from tShbMemHeader, because each
+ // process needs to store the interrupt flags separately
+ tSigHndlrNewData m_pfnSigHndlrNewData;
+ unsigned long m_ulTimeOutJobReady;
+ tSigHndlrJobReady m_pfnSigHndlrJobReady;
+ tShbMemHeader *m_pShbMemHeader;
+ int m_iThreadTermFlag;
+ struct completion m_CompletionNewData;
+/*
+ struct semaphore *m_pSemBuffAccess;
+ struct semaphore *m_pSemNewData;
+ struct semaphore *m_pSemStopSignalingNewData;
+ struct semaphore *m_pSemJobReady;
+*/
+#ifndef NDEBUG
+ unsigned long m_ulThreadIDNewData;
+ unsigned long m_ulThreadIDJobReady;
+#endif
+} tShbMemInst;
+
+//---------------------------------------------------------------------------
+// Prototypes of internal functions
+//---------------------------------------------------------------------------
+
+//tShbMemInst* ShbIpcGetShbMemInst (tShbInstance pShbInstance_p);
+//tShbMemHeader* ShbIpcGetShbMemHeader (tShbMemInst* pShbMemInst_p);
+
+//---------------------------------------------------------------------------
+// Get pointer to process local information structure
+//---------------------------------------------------------------------------
+
+static inline tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+
+ pShbMemInst = (tShbMemInst *) pShbInstance_p;
+
+ return (pShbMemInst);
+
+}
+
+//---------------------------------------------------------------------------
+// Get pointer to shared memory header
+//---------------------------------------------------------------------------
+
+static inline tShbMemHeader *ShbIpcGetShbMemHeader(tShbMemInst * pShbMemInst_p)
+{
+
+ tShbMemHeader *pShbMemHeader;
+
+ pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
+
+ return (pShbMemHeader);
+
+}
+
+// Get pointer to process local information structure
+//#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p)
+
+// Get pointer to shared memory header
+//#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader)
+
+// not inlined internal functions
+int ShbIpcThreadSignalNewData(void *pvThreadParam_p);
+int ShbIpcThreadSignalJobReady(void *pvThreadParam_p);
+#endif
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+#if !defined(SHBIPC_INLINE_ENABLED)
+struct sShbMemTable *psMemTableElementFirst_g;
+
+static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
+static int ShbIpcFindListElement(int iBufferId,
+ struct sShbMemTable
+ **ppsReturnMemTableElement);
+static void ShbIpcAppendListElement(struct sShbMemTable *sNewMemTableElement);
+static void ShbIpcDeleteListElement(int iBufferId);
+static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256]);
+static unsigned long ShbIpcCrc32GetCrc(const char *pcString,
+ unsigned long aulCrcTable[256]);
+
+#endif
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+#if !defined(SHBIPC_INLINE_ENABLED)
+// not inlined external functions
+
+//---------------------------------------------------------------------------
+// Initialize IPC for Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcInit(void)
+{
+ psMemTableElementFirst_g = NULL;
+ return (kShbOk);
+
+}
+
+//---------------------------------------------------------------------------
+// Deinitialize IPC for Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcExit(void)
+{
+
+ return (kShbOk);
+
+}
+
+//---------------------------------------------------------------------------
+// Allocate Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
+ const char *pszBufferID_p,
+ tShbInstance * ppShbInstance_p,
+ unsigned int *pfShbNewCreated_p)
+{
+ tShbError ShbError;
+ int iBufferId = 0;
+ unsigned long ulCrc32 = 0;
+ unsigned int uiFirstProcess = 0;
+ unsigned long ulShMemSize;
+ tShbMemHeader *pShbMemHeader;
+ tShbMemInst *pShbMemInst = NULL;
+ tShbInstance pShbInstance;
+ unsigned int fShMemNewCreated = FALSE;
+ void *pSharedMem = NULL;
+ unsigned long aulCrcTable[256];
+ struct sShbMemTable *psMemTableElement;
+
+ DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n");
+ ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
+
+ //create Buffer ID
+ ShbIpcCrc32GenTable(aulCrcTable);
+ ulCrc32 = ShbIpcCrc32GetCrc(pszBufferID_p, aulCrcTable);
+ iBufferId = ulCrc32;
+ DEBUG_LVL_29_TRACE2
+ ("ShbIpcAllocBuffer BufferSize:%d sizeof(tShb..):%d\n",
+ ulBufferSize_p, sizeof(tShbMemHeader));
+ DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferId:%d MemSize:%d\n",
+ iBufferId, ulShMemSize);
+ //---------------------------------------------------------------
+ // (1) open an existing or create a new shared memory
+ //---------------------------------------------------------------
+ //test if buffer already exists
+ if (ShbIpcFindListElement(iBufferId, &psMemTableElement) == 0) {
+ //Buffer already exists
+ fShMemNewCreated = FALSE;
+ pSharedMem = psMemTableElement->m_pBuffer;
+ DEBUG_LVL_29_TRACE1
+ ("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",
+ pSharedMem);
+ uiFirstProcess = 1;
+ } else {
+ //create new Buffer
+ fShMemNewCreated = TRUE;
+ uiFirstProcess = 0;
+ pSharedMem = kmalloc(ulShMemSize, GFP_KERNEL);
+ DEBUG_LVL_29_TRACE2
+ ("ShbIpcAllocBuffer Create New Buffer at:%p Id:%d\n",
+ pSharedMem, iBufferId);
+ if (pSharedMem == NULL) {
+ //unable to create mem
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+ DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n");
+ // append Element to Mem Table
+ psMemTableElement =
+ kmalloc(sizeof(struct sShbMemTable), GFP_KERNEL);
+ psMemTableElement->m_iBufferId = iBufferId;
+ psMemTableElement->m_pBuffer = pSharedMem;
+ psMemTableElement->m_psNextMemTableElement = NULL;
+ ShbIpcAppendListElement(psMemTableElement);
+ }
+
+ DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n");
+ //update header
+ pShbMemHeader = (tShbMemHeader *) pSharedMem;
+ DEBUG_LVL_29_TRACE1
+ ("ShbIpcAllocBuffer 0 pShbMemHeader->m_ulShMemSize: %d\n",
+ pShbMemHeader->m_ulShMemSize);
+ // allocate a memory block from process specific mempool to save
+ // process local information to administrate/manage the shared buffer
+ DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n");
+ pShbMemInst =
+ (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst));
+ if (pShbMemInst == NULL) {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+ // reset complete header to default values
+ //pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
+// pShbMemInst->m_pSharedMem = pSharedMem;
+ pShbMemInst->m_tThreadNewDataId = INVALID_ID;
+ pShbMemInst->m_tThreadJobReadyId = INVALID_ID;
+ pShbMemInst->m_pfnSigHndlrNewData = NULL;
+ pShbMemInst->m_ulTimeOutJobReady = 0;
+ pShbMemInst->m_pfnSigHndlrJobReady = NULL;
+ pShbMemInst->m_pShbMemHeader = pShbMemHeader;
+ pShbMemInst->m_iThreadTermFlag = 0;
+
+ // initialize completion etc.
+ init_completion(&pShbMemInst->m_CompletionNewData);
+
+ ShbError = kShbOk;
+ if (fShMemNewCreated) {
+ // this process was the first who wanted to use the shared memory,
+ // so a new shared memory was created
+ // -> setup new header information inside the shared memory region
+ // itself
+ pShbMemHeader->m_ulShMemSize = ulShMemSize;
+ pShbMemHeader->m_ulRefCount = 1;
+ pShbMemHeader->m_iBufferId = iBufferId;
+ // initialize spinlock
+ spin_lock_init(&pShbMemHeader->m_SpinlockBuffAccess);
+ // initialize wait queues
+ init_waitqueue_head(&pShbMemHeader->m_WaitQueueNewData);
+ init_waitqueue_head(&pShbMemHeader->m_WaitQueueJobReady);
+ } else {
+ // any other process has created the shared memory and this
+ // process only has to attach to it
+ // -> check and update existing header information inside the
+ // shared memory region itself
+ if (pShbMemHeader->m_ulShMemSize != ulShMemSize) {
+ ShbError = kShbOpenMismatch;
+ goto Exit;
+ }
+ pShbMemHeader->m_ulRefCount++;
+ }
+
+ Exit:
+ pShbInstance = (tShbInstance *) pShbMemInst;
+ *pfShbNewCreated_p = fShMemNewCreated;
+ *ppShbInstance_p = pShbInstance;
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Release Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
+{
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ tShbError ShbError;
+ tShbError ShbError2;
+
+ DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p);
+ if (pShbInstance_p == NULL) {
+ return (kShbOk);
+ }
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+
+ // stop threads in any case, because they are bound to that specific instance
+ ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p);
+ // d.k.: Whats up with JobReady thread?
+ // Just wake it up, but without setting the semaphore variable
+ wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
+
+ if (!--pShbMemHeader->m_ulRefCount) {
+ ShbError = kShbOk;
+ // delete mem table element
+ ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId);
+ // delete shared mem
+ kfree(pShbMemInst->m_pShbMemHeader);
+ } else {
+ ShbError = kShbMemUsedByOtherProcs;
+ }
+ //delete privat mem
+ kfree(pShbMemInst);
+ return (ShbError);
+}
+
+#endif // !defined(SHBIPC_INLINE_ENABLED)
+
+#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Enter atomic section for Shared Buffer access
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ tShbError ShbError = kShbOk;
+
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+ DEBUG_LVL_29_TRACE0("enter atomic\n");
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+
+ // lock interrupts
+ spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess,
+ pShbMemInst->m_ulFlagsBuffAccess);
+
+ Exit:
+ return ShbError;
+
+}
+
+//---------------------------------------------------------------------------
+// Leave atomic section for Shared Buffer access
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ tShbError ShbError = kShbOk;
+
+ if (pShbInstance_p == NULL) {
+ ShbError = kShbInvalidArg;
+ goto Exit;
+ }
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+ // unlock interrupts
+ spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess,
+ pShbMemInst->m_ulFlagsBuffAccess);
+
+ Exit:
+ DEBUG_LVL_29_TRACE0("Leave Atomic \n");
+ return ShbError;
+
+}
+
+//---------------------------------------------------------------------------
+// Start signaling of new data (called from reading process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
+ pShbInstance_p,
+ tSigHndlrNewData
+ pfnSignalHandlerNewData_p,
+ tShbPriority
+ ShbPriority_p)
+{
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ tShbError ShbError;
+
+ DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n");
+ if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+ ShbError = kShbOk;
+
+ if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID)
+ || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
+ ShbError = kShbAlreadySignaling;
+ goto Exit;
+ }
+ DEBUG_LVL_26_TRACE2
+ ("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n",
+ pShbInstance_p, pfnSignalHandlerNewData_p);
+ pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
+ pShbMemHeader->m_fNewData = FALSE;
+ pShbMemInst->m_iThreadTermFlag = 0;
+
+ switch (ShbPriority_p) {
+ case kShbPriorityLow:
+ pShbMemInst->m_lThreadNewDataNice = -2;
+ break;
+
+ case kShbPriorityNormal:
+ pShbMemInst->m_lThreadNewDataNice = -9;
+ break;
+
+ case kshbPriorityHigh:
+ pShbMemInst->m_lThreadNewDataNice = -20;
+ break;
+
+ }
+
+ //create thread for signalling new data
+ pShbMemInst->m_tThreadNewDataId =
+ kernel_thread(ShbIpcThreadSignalNewData, pShbInstance_p,
+ CLONE_KERNEL);
+
+ Exit:
+ return ShbError;
+
+}
+
+//---------------------------------------------------------------------------
+// Stop signaling of new data (called from reading process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
+ pShbInstance_p)
+{
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ tShbError ShbError;
+
+ DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n");
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+ ShbError = kShbOk;
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+
+ DEBUG_LVL_26_TRACE2
+ ("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n",
+ pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData);
+ if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { // signal handler was set before
+ int iErr;
+ //set termination flag in mem header
+ pShbMemInst->m_iThreadTermFlag = 1;
+
+ // check if thread is still running at all by sending the null-signal to this thread
+ /* iErr = kill_proc(pShbMemInst->m_tThreadNewDataId, 0, 1); */
+ iErr = send_sig(0, pShbMemInst->m_tThreadNewDataId, 1);
+ if (iErr == 0) {
+ // wake up thread, because it is still running
+ wake_up_interruptible(&pShbMemHeader->
+ m_WaitQueueNewData);
+
+ //wait for termination of thread
+ wait_for_completion(&pShbMemInst->m_CompletionNewData);
+ }
+
+ pShbMemInst->m_pfnSigHndlrNewData = NULL;
+ pShbMemInst->m_tThreadNewDataId = INVALID_ID;
+ }
+
+ return ShbError;
+
+}
+
+//---------------------------------------------------------------------------
+// Signal new data (called from writing process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
+{
+ tShbMemHeader *pShbMemHeader;
+
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+ pShbMemHeader =
+ ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
+ //set semaphore
+ pShbMemHeader->m_fNewData = TRUE;
+ DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n");
+
+ wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
+ return (kShbOk);
+}
+
+//---------------------------------------------------------------------------
+// Start signaling for job ready (called from waiting process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
+ pShbInstance_p,
+ unsigned long
+ ulTimeOut_p,
+ tSigHndlrJobReady
+ pfnSignalHandlerJobReady_p)
+{
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ tShbError ShbError;
+
+ if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+
+ ShbError = kShbOk;
+ if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID)
+ || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
+ ShbError = kShbAlreadySignaling;
+ goto Exit;
+ }
+ pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
+ pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
+ pShbMemHeader->m_fJobReady = FALSE;
+ //create thread for signalling new data
+ pShbMemInst->m_tThreadJobReadyId =
+ kernel_thread(ShbIpcThreadSignalJobReady, pShbInstance_p,
+ CLONE_KERNEL);
+ Exit:
+ return ShbError;
+}
+
+//---------------------------------------------------------------------------
+// Signal job ready (called from executing process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
+{
+ tShbMemHeader *pShbMemHeader;
+
+ DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n");
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+ pShbMemHeader =
+ ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
+ //set semaphore
+ pShbMemHeader->m_fJobReady = TRUE;
+ DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n");
+
+ wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
+ return (kShbOk);
+}
+
+//---------------------------------------------------------------------------
+// Get pointer to common used share memory area
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
+{
+
+ tShbMemHeader *pShbMemHeader;
+ void *pShbShMemPtr;
+
+ pShbMemHeader =
+ ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
+ if (pShbMemHeader != NULL) {
+ pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
+ } else {
+ pShbShMemPtr = NULL;
+ }
+
+ return (pShbShMemPtr);
+
+}
+
+#endif
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+#if !defined(SHBIPC_INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Get pointer to process local information structure
+//---------------------------------------------------------------------------
+
+/*tShbMemInst* ShbIpcGetShbMemInst (
+ tShbInstance pShbInstance_p)
+{
+
+tShbMemInst* pShbMemInst;
+
+ pShbMemInst = (tShbMemInst*)pShbInstance_p;
+
+ return (pShbMemInst);
+
+}
+*/
+
+//---------------------------------------------------------------------------
+// Get pointer to shared memory header
+//---------------------------------------------------------------------------
+
+/*tShbMemHeader* ShbIpcGetShbMemHeader (
+ tShbMemInst* pShbMemInst_p)
+{
+
+tShbMemHeader* pShbMemHeader;
+
+ pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
+
+ return (pShbMemHeader);
+
+}
+*/
+
+//---------------------------------------------------------------------------
+// Allocate a memory block from process specific mempool
+//---------------------------------------------------------------------------
+
+static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
+{
+ tShbError ShbError;
+ void *pMem;
+
+ DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n");
+ //get private mem
+ pMem = kmalloc(ulMemSize_p, GFP_KERNEL);
+ if (pMem == NULL) {
+ //unable to create mem
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+ Exit:
+ return (pMem);
+
+}
+
+//---------------------------------------------------------------------------
+// Thread for new data signaling
+//---------------------------------------------------------------------------
+
+int ShbIpcThreadSignalNewData(void *pvThreadParam_p)
+{
+ tShbInstance pShbInstance;
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ int iRetVal = -1;
+ int fCallAgain;
+
+ daemonize("ShbND%p", pvThreadParam_p);
+ allow_signal(SIGTERM);
+ pShbInstance = (tShbMemInst *) pvThreadParam_p;
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+
+ DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n", pvThreadParam_p);
+
+ set_user_nice(current, pShbMemInst->m_lThreadNewDataNice);
+
+// DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData);
+ do {
+ iRetVal =
+ wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData,
+ (pShbMemInst->m_iThreadTermFlag !=
+ 0)
+ || (pShbMemHeader->m_fNewData !=
+ FALSE));
+
+ if (iRetVal != 0) { // signal pending
+ break;
+ }
+
+ if (pShbMemHeader->m_fNewData != FALSE) {
+ pShbMemHeader->m_fNewData = FALSE;
+ do {
+ fCallAgain =
+ pShbMemInst->
+ m_pfnSigHndlrNewData(pShbInstance);
+ // call scheduler, which will execute any task with higher priority
+ schedule();
+ } while (fCallAgain != FALSE);
+ }
+ } while (pShbMemInst->m_iThreadTermFlag == 0);
+ DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalNewData terminated \n");
+ //set thread completed
+ complete_and_exit(&pShbMemInst->m_CompletionNewData, 0);
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+// Thread for new data Job Ready signaling
+//---------------------------------------------------------------------------
+
+int ShbIpcThreadSignalJobReady(void *pvThreadParam_p)
+{
+ tShbInstance pShbInstance;
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ long lTimeOut;
+ int iRetVal = -1;
+
+ daemonize("ShbJR%p", pvThreadParam_p);
+ allow_signal(SIGTERM);
+ pShbInstance = (tShbMemInst *) pvThreadParam_p;
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
+
+ DEBUG_LVL_29_TRACE0
+ ("ShbIpcThreadSignalJobReady wait for job ready Sem\n");
+ if (pShbMemInst->m_ulTimeOutJobReady != 0) {
+ lTimeOut = (long)pShbMemInst->m_ulTimeOutJobReady;
+ //wait for job ready semaphore
+ iRetVal =
+ wait_event_interruptible_timeout(pShbMemHeader->
+ m_WaitQueueJobReady,
+ (pShbMemHeader->
+ m_fJobReady != FALSE),
+ lTimeOut);
+ } else {
+ //wait for job ready semaphore
+ iRetVal =
+ wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady,
+ (pShbMemHeader->m_fJobReady !=
+ FALSE));
+ }
+
+ if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
+ //call Handler
+ pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance,
+ !pShbMemHeader->m_fJobReady);
+ }
+
+ pShbMemInst->m_pfnSigHndlrJobReady = NULL;
+ return 0;
+}
+
+//Build the crc table
+static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256])
+{
+ unsigned long ulCrc, ulPoly;
+ int iIndexI, iIndexJ;
+
+ ulPoly = 0xEDB88320L;
+ for (iIndexI = 0; iIndexI < 256; iIndexI++) {
+ ulCrc = iIndexI;
+ for (iIndexJ = 8; iIndexJ > 0; iIndexJ--) {
+ if (ulCrc & 1) {
+ ulCrc = (ulCrc >> 1) ^ ulPoly;
+ } else {
+ ulCrc >>= 1;
+ }
+ }
+ aulCrcTable[iIndexI] = ulCrc;
+ }
+}
+
+//Calculate the crc value
+static unsigned long ShbIpcCrc32GetCrc(const char *pcString,
+ unsigned long aulCrcTable[256])
+{
+ unsigned long ulCrc;
+ int iIndex;
+
+ ulCrc = 0xFFFFFFFF;
+ for (iIndex = 0; iIndex < strlen(pcString); iIndex++) {
+ ulCrc =
+ ((ulCrc >> 8) & 0x00FFFFFF) ^
+ aulCrcTable[(ulCrc ^ pcString[iIndex]) & 0xFF];
+ }
+ return (ulCrc ^ 0xFFFFFFFF);
+
+}
+
+static void ShbIpcAppendListElement(struct sShbMemTable *psNewMemTableElement)
+{
+ struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
+ psNewMemTableElement->m_psNextMemTableElement = NULL;
+
+ if (psMemTableElementFirst_g != NULL) { /* sind Elemente vorhanden */
+ while (psMemTableElement->m_psNextMemTableElement != NULL) { /* suche das letzte Element */
+ psMemTableElement =
+ psMemTableElement->m_psNextMemTableElement;
+ }
+ psMemTableElement->m_psNextMemTableElement = psNewMemTableElement; /* Haenge das Element hinten an */
+ } else { /* wenn die liste leer ist, bin ich das erste Element */
+ psMemTableElementFirst_g = psNewMemTableElement;
+ }
+}
+
+static int ShbIpcFindListElement(int iBufferId,
+ struct sShbMemTable **ppsReturnMemTableElement)
+{
+ struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
+ while (psMemTableElement != NULL) {
+ if (psMemTableElement->m_iBufferId == iBufferId) {
+//printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",psMemTableElement->m_pBuffer,psMemTableElement->m_iBufferId);
+ *ppsReturnMemTableElement = psMemTableElement;
+//printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",(*ppsReturnMemTableElement)->m_pBuffer,(*ppsReturnMemTableElement)->m_iBufferId);
+ return 0;
+ }
+ psMemTableElement = psMemTableElement->m_psNextMemTableElement;
+ }
+ return -1;
+}
+
+static void ShbIpcDeleteListElement(int iBufferId)
+{
+ struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
+ struct sShbMemTable *psMemTableElementOld = psMemTableElementFirst_g;
+ if (psMemTableElement != NULL) {
+ while ((psMemTableElement != NULL)
+ && (psMemTableElement->m_iBufferId != iBufferId)) {
+ psMemTableElementOld = psMemTableElement;
+ psMemTableElement =
+ psMemTableElement->m_psNextMemTableElement;
+ }
+ if (psMemTableElement != NULL) {
+ if (psMemTableElement != psMemTableElementFirst_g) {
+ psMemTableElementOld->m_psNextMemTableElement =
+ psMemTableElement->m_psNextMemTableElement;
+ kfree(psMemTableElement);
+ } else {
+ kfree(psMemTableElement);
+ psMemTableElementFirst_g = NULL;
+ }
+
+ }
+ }
+
+}
+
+#endif
diff --git a/drivers/staging/epl/ShbIpc-Win32.c b/drivers/staging/epl/ShbIpc-Win32.c
new file mode 100644
index 000000000000..b9181471ae0b
--- /dev/null
+++ b/drivers/staging/epl/ShbIpc-Win32.c
@@ -0,0 +1,1202 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: Project independend shared buffer (linear + circular)
+
+ Description: Implementation of platform specific part for the
+ shared buffer
+ (Implementation for Win32)
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ 2006/06/27 -rs: V 1.00 (initial version)
+
+****************************************************************************/
+
+#define WINVER 0x0400 // #defines necessary for usage of
+#define _WIN32_WINNT 0x0400 // function <SignalObjectAndWait>
+
+#include <windows.h>
+#include <stdio.h>
+#include "global.h"
+#include "sharedbuff.h"
+#include "shbipc.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Configuration
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Constant definitions
+//---------------------------------------------------------------------------
+
+#define MAX_LEN_BUFFER_ID MAX_PATH
+
+#define IDX_EVENT_NEW_DATA 0
+#define IDX_EVENT_TERM_REQU 1
+#define IDX_EVENT_TERM_RESP 2
+
+#define NAME_MUTEX_BUFF_ACCESS "BuffAccess"
+#define NAME_EVENT_NEW_DATA "NewData"
+#define NAME_EVENT_TERM_REQU "TermRequ"
+#define NAME_EVENT_TERM_RESP "TermResp"
+#define NAME_EVENT_JOB_READY "JobReady"
+
+#define TIMEOUT_ENTER_ATOMIC 1000 // for debgging: INFINITE
+#define TIMEOUT_TERM_THREAD 2000
+
+#define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
+#define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
+
+//---------------------------------------------------------------------------
+// Local types
+//---------------------------------------------------------------------------
+
+// This structure is the common header for the shared memory region used
+// by all processes attached this shared memory. It includes common
+// information to administrate/manage the shared buffer from a couple of
+// separated processes (e.g. the refernce counter). This structure is
+// located at the start of the shared memory region itself and exists
+// consequently only one times per shared memory instance.
+typedef struct {
+ unsigned long m_SbhMagicID; // magic ID ("SBH*")
+ unsigned long m_ulShMemSize;
+ unsigned long m_ulRefCount;
+ char m_szBufferID[MAX_LEN_BUFFER_ID];
+
+#ifndef NDEBUG
+ unsigned long m_ulOwnerProcID;
+#endif
+
+} tShbMemHeader;
+
+// This structure is the "external entry point" from a separate process
+// to get access to a shared buffer. This structure includes all platform
+// resp. target specific information to administrate/manage the shared
+// buffer from a separate process. Every process attached to the shared
+// buffer has its own runtime instance of this structure with its individual
+// runtime data (e.g. the scope of an event handle is limitted to the
+// owner process only). The structure member <m_pShbMemHeader> points
+// to the (process specific) start address of the shared memory region
+// itself.
+typedef struct {
+ unsigned long m_SbiMagicID; // magic ID ("SBI+")
+ HANDLE m_hSharedMem;
+ HANDLE m_hMutexBuffAccess;
+ HANDLE m_hThreadNewData; // thraed to signal that new data are available
+ HANDLE m_ahEventNewData[3]; // IDX_EVENT_NEW_DATA + IDX_EVENT_TERM_REQU + ID_EVENT_TERM_RESP
+ tSigHndlrNewData m_pfnSigHndlrNewData;
+ HANDLE m_hThreadJobReady; // thread to signal that a job/operation is ready now (e.g. reset buffer)
+ HANDLE m_hEventJobReady;
+ unsigned long m_ulTimeOutJobReady;
+ tSigHndlrJobReady m_pfnSigHndlrJobReady;
+ tShbMemHeader *m_pShbMemHeader;
+
+#ifndef NDEBUG
+ unsigned long m_ulThreadIDNewData;
+ unsigned long m_ulThreadIDJobReady;
+#endif
+
+} tShbMemInst;
+
+//---------------------------------------------------------------------------
+// Global variables
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Local variables
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Prototypes of internal functions
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Get pointer to process local information structure
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+
+ pShbMemInst = (tShbMemInst *) pShbInstance_p;
+ ASSERT(pShbMemInst->m_SbiMagicID == SBI_MAGIC_ID);
+
+ return (pShbMemInst);
+
+}
+
+//---------------------------------------------------------------------------
+// Get pointer to shared memory header
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbMemHeader *ShbIpcGetShbMemHeader(tShbInstance
+ pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = pShbMemInst->m_pShbMemHeader;
+ ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID);
+
+ return (pShbMemHeader);
+
+}
+
+// not inlined internal functions
+DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p);
+DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p);
+const char *ShbIpcGetUniformObjectName(const char *pszEventJobName_p,
+ const char *pszBufferID_p,
+ BOOL fGlobalObject_p);
+
+#endif
+
+#if !defined(SHBIPC_INLINE_ENABLED)
+// true internal functions (not inlined)
+static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
+static void ShbIpcReleasePrivateMem(void *pMem_p);
+#endif
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+#if !defined(SHBIPC_INLINE_ENABLED)
+// not inlined external functions
+
+//---------------------------------------------------------------------------
+// Initialize IPC for Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcInit(void)
+{
+
+ return (kShbOk);
+
+}
+
+//---------------------------------------------------------------------------
+// Deinitialize IPC for Shared Buffer Module
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcExit(void)
+{
+
+ return (kShbOk);
+
+}
+
+//---------------------------------------------------------------------------
+// Allocate Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
+ const char *pszBufferID_p,
+ tShbInstance * ppShbInstance_p,
+ unsigned int *pfShbNewCreated_p)
+{
+
+ HANDLE hSharedMem;
+ LPVOID pSharedMem;
+ unsigned long ulShMemSize;
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ tShbInstance pShbInstance;
+ unsigned int fShMemNewCreated;
+ const char *pszObjectName;
+ HANDLE hMutexBuffAccess;
+ HANDLE hEventNewData;
+ HANDLE hEventJobReady;
+ tShbError ShbError;
+
+ ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
+ pSharedMem = NULL;
+ pShbInstance = NULL;
+ fShMemNewCreated = FALSE;
+ ShbError = kShbOk;
+
+ //---------------------------------------------------------------
+ // (1) open an existing or create a new shared memory
+ //---------------------------------------------------------------
+ // try to open an already existing shared memory
+ // (created by an another process)
+ hSharedMem = OpenFileMapping(FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess
+ FALSE, // BOOL bInheritHandle
+ pszBufferID_p); // LPCTSTR lpName
+ if (hSharedMem != NULL) {
+ // a shared memory already exists
+ fShMemNewCreated = FALSE;
+ } else {
+ // it seams that this process is the first who wants to use the
+ // shared memory, so it has to create a new shared memory
+ hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE, // HANDLE hFile
+ NULL, // LPSECURITY_ATTRIBUTES lpAttributes
+ PAGE_READWRITE, // DWORD flProtect
+ 0, // DWORD dwMaximumSizeHigh
+ ulShMemSize, // DWORD dwMaximumSizeLow
+ pszBufferID_p); // LPCTSTR lpName
+
+ fShMemNewCreated = TRUE;
+ }
+
+ if (hSharedMem == NULL) {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+
+ //---------------------------------------------------------------
+ // (2) get the pointer to the shared memory
+ //---------------------------------------------------------------
+ pSharedMem = MapViewOfFile(hSharedMem, // HANDLE hFileMappingObject
+ FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess,
+ 0, // DWORD dwFileOffsetHigh,
+ 0, // DWORD dwFileOffsetLow,
+ ulShMemSize); // SIZE_T dwNumberOfBytesToMap
+
+ if (pSharedMem == NULL) {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+
+ //---------------------------------------------------------------
+ // (3) setup or update header and management information
+ //---------------------------------------------------------------
+ pShbMemHeader = (tShbMemHeader *) pSharedMem;
+
+ // allocate a memory block from process specific mempool to save
+ // process local information to administrate/manage the shared buffer
+ pShbMemInst =
+ (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst));
+ if (pShbMemInst == NULL) {
+ ShbError = kShbOutOfMem;
+ goto Exit;
+ }
+ // reset complete header to default values
+ pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
+ pShbMemInst->m_hSharedMem = hSharedMem;
+ pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
+ pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
+ INVALID_HANDLE_VALUE;
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
+ INVALID_HANDLE_VALUE;
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
+ INVALID_HANDLE_VALUE;
+ pShbMemInst->m_pfnSigHndlrNewData = NULL;
+ pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
+ pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE;
+ pShbMemInst->m_ulTimeOutJobReady = 0;
+ pShbMemInst->m_pfnSigHndlrJobReady = NULL;
+ pShbMemInst->m_pShbMemHeader = pShbMemHeader;
+
+#ifndef NDEBUG
+ {
+ pShbMemInst->m_ulThreadIDNewData = 0;
+ pShbMemInst->m_ulThreadIDJobReady = 0;
+ }
+#endif
+
+ // create mutex for buffer access
+ pszObjectName =
+ ShbIpcGetUniformObjectName(NAME_MUTEX_BUFF_ACCESS, pszBufferID_p,
+ TRUE);
+ hMutexBuffAccess = CreateMutex(NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes
+ FALSE, // BOOL bInitialOwner
+ pszObjectName); // LPCTSTR lpName
+ pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess;
+ ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL);
+
+ // The EventNewData is used for signaling of new data after a write
+ // operation (SetEvent) as well as for waiting for new data on the
+ // reader side (WaitForMultipleObjects). Because it's not known if
+ // this process will be read or write data, the event will be
+ // always created here.
+ pszObjectName =
+ ShbIpcGetUniformObjectName(NAME_EVENT_NEW_DATA, pszBufferID_p,
+ TRUE);
+ hEventNewData = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
+ FALSE, // BOOL bManualReset
+ FALSE, // BOOL bInitialState
+ pszObjectName); // LPCTSTR lpName
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData;
+ ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL);
+
+ // The EventJobReady is used for signaling that a job is done (SetEvent)
+ // as well as for waiting for finishing of a job (WaitForMultipleObjects).
+ // Because it's not known if this process will signal or wait, the event
+ // will be always created here.
+ pszObjectName =
+ ShbIpcGetUniformObjectName(NAME_EVENT_JOB_READY, pszBufferID_p,
+ TRUE);
+ hEventJobReady = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
+ FALSE, // BOOL bManualReset
+ FALSE, // BOOL bInitialState
+ pszObjectName); // LPCTSTR lpName
+ pShbMemInst->m_hEventJobReady = hEventJobReady;
+ ASSERT(pShbMemInst->m_hEventJobReady != NULL);
+
+ if (fShMemNewCreated) {
+ // this process was the first who wanted to use the shared memory,
+ // so a new shared memory was created
+ // -> setup new header information inside the shared memory region
+ // itself
+ pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID;
+ pShbMemHeader->m_ulShMemSize = ulShMemSize;
+ pShbMemHeader->m_ulRefCount = 1;
+ strncpy(pShbMemHeader->m_szBufferID, pszBufferID_p,
+ sizeof(pShbMemHeader->m_szBufferID) - 1);
+
+#ifndef NDEBUG
+ {
+ pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId();
+ }
+#endif
+ } else {
+ // any other process has created the shared memory and this
+ // process has only attached to it
+ // -> check and update existing header information inside the
+ // shared memory region itself
+ if (pShbMemHeader->m_ulShMemSize != ulShMemSize) {
+ ShbError = kShbOpenMismatch;
+ goto Exit;
+ }
+#ifndef NDEBUG
+ {
+ if (strncmp
+ (pShbMemHeader->m_szBufferID, pszBufferID_p,
+ sizeof(pShbMemHeader->m_szBufferID) - 1)) {
+ ShbError = kShbOpenMismatch;
+ goto Exit;
+ }
+ }
+#endif
+
+ pShbMemHeader->m_ulRefCount++;
+ }
+
+ // set abstarct "handle" for returning to application
+ pShbInstance = (tShbInstance *) pShbMemInst;
+
+ Exit:
+
+ if (ShbError != kShbOk) {
+ if (pShbMemInst != NULL) {
+ ShbIpcReleasePrivateMem(pShbMemInst);
+ }
+ if (pSharedMem != NULL) {
+ UnmapViewOfFile(pSharedMem);
+ }
+ if (hSharedMem != NULL) {
+ CloseHandle(hSharedMem);
+ }
+ }
+
+ *pfShbNewCreated_p = fShMemNewCreated;
+ *ppShbInstance_p = pShbInstance;
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Release Shared Buffer
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ HANDLE hEventNewData;
+ HANDLE hMutexBuffAccess;
+ tShbError ShbError;
+ tShbError ShbError2;
+
+ if (pShbInstance_p == NULL) {
+ return (kShbOk);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
+
+ if (!--pShbMemHeader->m_ulRefCount) {
+ ShbError = kShbOk;
+ } else {
+ ShbError = kShbMemUsedByOtherProcs;
+ }
+
+ ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p);
+ hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
+ if (hEventNewData != INVALID_HANDLE_VALUE) {
+ CloseHandle(hEventNewData);
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
+ INVALID_HANDLE_VALUE;
+ }
+
+ hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
+ if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
+ CloseHandle(hMutexBuffAccess);
+ pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
+ }
+
+ UnmapViewOfFile(pShbMemHeader);
+ if (pShbMemInst->m_hSharedMem != INVALID_HANDLE_VALUE) {
+ CloseHandle(pShbMemInst->m_hSharedMem);
+ pShbMemInst->m_hSharedMem = INVALID_HANDLE_VALUE;
+ }
+
+ ShbIpcReleasePrivateMem(pShbMemInst);
+
+ if (ShbError == kShbOk) {
+ ShbError = ShbError2;
+ }
+
+ return (ShbError);
+
+}
+
+#endif // !defined(SHBIPC_INLINE_ENABLED)
+
+#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Enter atomic section for Shared Buffer access
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ HANDLE hMutexBuffAccess;
+ DWORD dwWaitResult;
+ tShbError ShbError;
+
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ ShbError = kShbOk;
+
+ hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
+ if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
+ dwWaitResult =
+ WaitForSingleObject(hMutexBuffAccess, TIMEOUT_ENTER_ATOMIC);
+ switch (dwWaitResult) {
+ case WAIT_OBJECT_0 + 0:
+ {
+ break;
+ }
+
+ case WAIT_TIMEOUT:
+ {
+ TRACE0
+ ("\nShbIpcEnterAtomicSection(): WAIT_TIMEOUT");
+ ASSERT(0);
+ ShbError = kShbBufferInvalid;
+ break;
+ }
+
+ case WAIT_ABANDONED:
+ {
+ TRACE0
+ ("\nShbIpcEnterAtomicSection(): WAIT_ABANDONED");
+ ASSERT(0);
+ ShbError = kShbBufferInvalid;
+ break;
+ }
+
+ case WAIT_FAILED:
+ {
+ TRACE1
+ ("\nShbIpcEnterAtomicSection(): WAIT_FAILED -> LastError=%ld",
+ GetLastError());
+ ASSERT(0);
+ ShbError = kShbBufferInvalid;
+ break;
+ }
+
+ default:
+ {
+ TRACE1
+ ("\nShbIpcEnterAtomicSection(): unknown error -> LastError=%ld",
+ GetLastError());
+ ASSERT(0);
+ ShbError = kShbBufferInvalid;
+ break;
+ }
+ }
+ } else {
+ ShbError = kShbBufferInvalid;
+ }
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Leave atomic section for Shared Buffer access
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ HANDLE hMutexBuffAccess;
+ BOOL fRes;
+ tShbError ShbError;
+
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ ShbError = kShbOk;
+
+ hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
+ if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
+ fRes = ReleaseMutex(hMutexBuffAccess);
+ ASSERT(fRes);
+ } else {
+ ShbError = kShbBufferInvalid;
+ }
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Start signaling of new data (called from reading process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
+ pShbInstance_p,
+ tSigHndlrNewData
+ pfnSignalHandlerNewData_p,
+ tShbPriority
+ ShbPriority_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ const char *pszObjectName;
+ HANDLE hEventTermRequ;
+ HANDLE hEventTermResp;
+ HANDLE hThreadNewData;
+ unsigned long ulThreadIDNewData;
+ tShbError ShbError;
+ int iPriority;
+
+ if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if ((pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) ||
+ (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
+ INVALID_HANDLE_VALUE)
+ || (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
+ INVALID_HANDLE_VALUE)
+ || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
+ ShbError = kShbAlreadySignaling;
+ goto Exit;
+ }
+
+ pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
+
+ // Because the event <pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]>
+ // is used for signaling of new data after a write operation too (using
+ // SetEvent), it is always created here (see <ShbIpcAllocBuffer>).
+
+ pszObjectName =
+ ShbIpcGetUniformObjectName(NAME_EVENT_TERM_REQU,
+ pShbMemHeader->m_szBufferID, FALSE);
+ hEventTermRequ = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
+ FALSE, // BOOL bManualReset
+ FALSE, // BOOL bInitialState
+ pszObjectName); // LPCTSTR lpName
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = hEventTermRequ;
+ ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != NULL);
+
+ pszObjectName =
+ ShbIpcGetUniformObjectName(NAME_EVENT_TERM_RESP,
+ pShbMemHeader->m_szBufferID, FALSE);
+ hEventTermResp = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
+ FALSE, // BOOL bManualReset
+ FALSE, // BOOL bInitialState
+ pszObjectName); // LPCTSTR lpName
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = hEventTermResp;
+ ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != NULL);
+
+ hThreadNewData = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
+ 0, // SIZE_T dwStackSize
+ ShbIpcThreadSignalNewData, // LPTHREAD_START_ROUTINE lpStartAddress
+ pShbInstance_p, // LPVOID lpParameter
+ 0, // DWORD dwCreationFlags
+ &ulThreadIDNewData); // LPDWORD lpThreadId
+
+ switch (ShbPriority_p) {
+ case kShbPriorityLow:
+ iPriority = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+
+ case kShbPriorityNormal:
+ iPriority = THREAD_PRIORITY_NORMAL;
+ break;
+
+ case kshbPriorityHigh:
+ iPriority = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+
+ }
+
+ ASSERT(pShbMemInst->m_hThreadNewData != NULL);
+
+ SetThreadPriority(hThreadNewData, iPriority);
+
+ pShbMemInst->m_hThreadNewData = hThreadNewData;
+
+#ifndef NDEBUG
+ {
+ pShbMemInst->m_ulThreadIDNewData = ulThreadIDNewData;
+ }
+#endif
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Stop signaling of new data (called from reading process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
+ pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ HANDLE hEventTermRequ;
+ HANDLE hEventTermResp;
+ DWORD dwWaitResult;
+
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+
+ // terminate new data signaling thread
+ // (set event <hEventTermRequ> to wakeup the thread and dispose it
+ // to exit, then wait for confirmation using event <hEventTermResp>)
+ hEventTermRequ = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU];
+ hEventTermResp = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP];
+ if ((hEventTermRequ != INVALID_HANDLE_VALUE) &&
+ (hEventTermResp != INVALID_HANDLE_VALUE)) {
+ TRACE0("\nShbIpcStopSignalingNewData(): enter wait state");
+ dwWaitResult = SignalObjectAndWait(hEventTermRequ, // HANDLE hObjectToSignal
+ hEventTermResp, // HANDLE hObjectToWaitOn
+ TIMEOUT_TERM_THREAD, // DWORD dwMilliseconds
+ FALSE); // BOOL bAlertable
+ TRACE0
+ ("\nShbIpcStopSignalingNewData(): wait state leaved: ---> ");
+ switch (dwWaitResult) {
+ case WAIT_OBJECT_0 + 0: // event "new data signaling thread terminated"
+ {
+ TRACE0("Event = WAIT_OBJECT_0+0");
+ break;
+ }
+
+ default:
+ {
+ TRACE0("Unhandled Event");
+ ASSERT(0);
+ break;
+ }
+ }
+ }
+
+ if (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) {
+ CloseHandle(pShbMemInst->m_hThreadNewData);
+ pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
+ }
+
+ if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
+ INVALID_HANDLE_VALUE) {
+ CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]);
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
+ INVALID_HANDLE_VALUE;
+ }
+
+ if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
+ INVALID_HANDLE_VALUE) {
+ CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
+ pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
+ INVALID_HANDLE_VALUE;
+ }
+
+ pShbMemInst->m_pfnSigHndlrNewData = NULL;
+
+ return (kShbOk);
+
+}
+
+//---------------------------------------------------------------------------
+// Signal new data (called from writing process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ HANDLE hEventNewData;
+ BOOL fRes;
+
+ // TRACE0("\nShbIpcSignalNewData(): enter\n");
+
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+
+ ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] !=
+ INVALID_HANDLE_VALUE);
+ hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
+ if (hEventNewData != INVALID_HANDLE_VALUE) {
+ fRes = SetEvent(hEventNewData);
+ // TRACE1("\nShbIpcSignalNewData(): EventNewData set (Result=%d)\n", (int)fRes);
+ ASSERT(fRes);
+ }
+ // TRACE0("\nShbIpcSignalNewData(): leave\n");
+ return (kShbOk);
+
+}
+
+//---------------------------------------------------------------------------
+// Start signaling for job ready (called from waiting process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
+ pShbInstance_p,
+ unsigned long
+ ulTimeOut_p,
+ tSigHndlrJobReady
+ pfnSignalHandlerJobReady_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ tShbMemHeader *pShbMemHeader;
+ HANDLE hThreadJobReady;
+ unsigned long ulThreadIDJobReady;
+ tShbError ShbError;
+
+ if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
+ ShbError = kShbOk;
+
+ if ((pShbMemInst->m_hThreadJobReady != INVALID_HANDLE_VALUE) ||
+ (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
+ ShbError = kShbAlreadySignaling;
+ goto Exit;
+ }
+
+ pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
+ pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
+
+ // Because the event <pShbMemInst->m_ahEventJobReady> is used for
+ // signaling of a finished job too (using SetEvent), it is always
+ // created here (see <ShbIpcAllocBuffer>).
+
+ hThreadJobReady = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
+ 0, // SIZE_T dwStackSize
+ ShbIpcThreadSignalJobReady, // LPTHREAD_START_ROUTINE lpStartAddress
+ pShbInstance_p, // LPVOID lpParameter
+ 0, // DWORD dwCreationFlags
+ &ulThreadIDJobReady); // LPDWORD lpThreadId
+
+ pShbMemInst->m_hThreadJobReady = hThreadJobReady;
+ ASSERT(pShbMemInst->m_hThreadJobReady != NULL);
+
+#ifndef NDEBUG
+ {
+ pShbMemInst->m_ulThreadIDJobReady = ulThreadIDJobReady;
+ }
+#endif
+
+ Exit:
+
+ return (ShbError);
+
+}
+
+//---------------------------------------------------------------------------
+// Signal job ready (called from executing process)
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
+{
+
+ tShbMemInst *pShbMemInst;
+ HANDLE hEventJobReady;
+ BOOL fRes;
+
+ // TRACE0("\nShbIpcSignalJobReady(): enter\n");
+
+ if (pShbInstance_p == NULL) {
+ return (kShbInvalidArg);
+ }
+
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
+
+ ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE);
+ hEventJobReady = pShbMemInst->m_hEventJobReady;
+ if (hEventJobReady != INVALID_HANDLE_VALUE) {
+ fRes = SetEvent(hEventJobReady);
+ // TRACE1("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes);
+ ASSERT(fRes);
+ }
+ // TRACE0("\nShbIpcSignalJobReady(): leave\n");
+ return (kShbOk);
+
+}
+
+//---------------------------------------------------------------------------
+// Get pointer to common used share memory area
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
+{
+
+ tShbMemHeader *pShbMemHeader;
+ void *pShbShMemPtr;
+
+ pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
+ if (pShbMemHeader != NULL) {
+ pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
+ } else {
+ pShbShMemPtr = NULL;
+ }
+
+ return (pShbShMemPtr);
+
+}
+
+#endif
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+#if !defined(SHBIPC_INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// Allocate a memory block from process specific mempool
+//---------------------------------------------------------------------------
+
+static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
+{
+
+ HGLOBAL hMem;
+ void *pMem;
+
+ hMem = GlobalAlloc(GMEM_FIXED, ulMemSize_p + sizeof(HGLOBAL));
+ pMem = GlobalLock(hMem);
+ if (pMem != NULL) {
+ *(HGLOBAL *) pMem = hMem;
+ (BYTE *) pMem += sizeof(HGLOBAL);
+ }
+
+#ifndef NDEBUG
+ {
+ memset(pMem, 0xaa, ulMemSize_p);
+ }
+#endif
+
+ return (pMem);
+
+}
+
+//---------------------------------------------------------------------------
+// Release a memory block from process specific mempool
+//---------------------------------------------------------------------------
+
+static void ShbIpcReleasePrivateMem(void *pMem_p)
+{
+
+ HGLOBAL hMem;
+
+ if (pMem_p == NULL) {
+ return;
+ }
+
+ (BYTE *) pMem_p -= sizeof(HGLOBAL);
+ hMem = *(HGLOBAL *) pMem_p;
+
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+
+ return;
+
+}
+
+//---------------------------------------------------------------------------
+// Create uniform object name (needed for inter-process communication)
+//---------------------------------------------------------------------------
+
+const char *ShbIpcGetUniformObjectName(const char *pszObjectJobName_p,
+ const char *pszBufferID_p,
+ BOOL fGlobalObject_p)
+{
+
+ static char szObjectName[MAX_PATH];
+ char szObjectPrefix[MAX_PATH];
+
+ if (fGlobalObject_p) {
+ strncpy(szObjectPrefix, "Global\\", sizeof(szObjectPrefix));
+ } else {
+ _snprintf(szObjectPrefix, sizeof(szObjectPrefix), "PID%08lX_",
+ (unsigned long)GetCurrentProcessId());
+ }
+
+ _snprintf(szObjectName, sizeof(szObjectName), "%s%s#%s",
+ szObjectPrefix, pszBufferID_p, pszObjectJobName_p);
+
+ return (szObjectName);
+
+}
+
+//---------------------------------------------------------------------------
+// Thread for new data signaling
+//---------------------------------------------------------------------------
+
+DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p)
+{
+
+ tShbInstance pShbInstance;
+ tShbMemInst *pShbMemInst;
+ DWORD dwWaitResult;
+ BOOL fTermRequ;
+ int fCallAgain;
+
+ TRACE1
+ ("\nShbIpcThreadSignalNewData(): SignalThread started (pShbInstance=0x%08lX)\n",
+ (DWORD) pvThreadParam_p);
+
+ pShbInstance = (tShbMemInst *) pvThreadParam_p;
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
+ fTermRequ = FALSE;
+
+ do {
+ ASSERT((pShbMemInst->m_ahEventNewData[0] !=
+ INVALID_HANDLE_VALUE)
+ && (pShbMemInst->m_ahEventNewData[0] != NULL));
+ ASSERT((pShbMemInst->m_ahEventNewData[1] !=
+ INVALID_HANDLE_VALUE)
+ && (pShbMemInst->m_ahEventNewData[1] != NULL));
+
+ TRACE0("\nShbIpcThreadSignalNewData(): enter wait state");
+ dwWaitResult = WaitForMultipleObjects(2, // DWORD nCount
+ pShbMemInst->m_ahEventNewData, // const HANDLE* lpHandles
+ FALSE, // BOOL bWaitAll
+ INFINITE); // DWORD dwMilliseconds
+ TRACE0
+ ("\nShbIpcThreadSignalNewData(): wait state leaved: ---> ");
+ switch (dwWaitResult) {
+ case WAIT_OBJECT_0 + 0: // event "new data"
+ {
+ TRACE0("Event = WAIT_OBJECT_0+0");
+ if (pShbMemInst->m_pfnSigHndlrNewData != NULL) {
+ TRACE0
+ ("\nShbIpcThreadSignalNewData(): calling SignalHandlerNewData");
+ do {
+ fCallAgain =
+ pShbMemInst->
+ m_pfnSigHndlrNewData
+ (pShbInstance);
+ // d.k.: try to run any shared buffer which has higher priority.
+ // under Windows this is not really necessary because the Windows scheduler
+ // already preempts tasks with lower priority.
+ } while (fCallAgain != FALSE);
+ }
+ break;
+ }
+
+ case WAIT_OBJECT_0 + 1: // event "terminate"
+ {
+ TRACE0("Event = WAIT_OBJECT_0+1");
+ fTermRequ = TRUE;
+ break;
+ }
+
+ default:
+ {
+ TRACE0("Unhandled Event");
+ ASSERT(0);
+ fTermRequ = TRUE;
+ break;
+ }
+ }
+ }
+ while (!fTermRequ);
+
+ if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
+ INVALID_HANDLE_VALUE) {
+ SetEvent(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
+ }
+
+ TRACE1
+ ("\nShbIpcThreadSignalNewData(): SignalThread terminated (pShbInstance=0x%08lX)\n",
+ (DWORD) pShbInstance);
+
+ ExitThread(0);
+
+}
+
+//---------------------------------------------------------------------------
+// Thread for new data signaling
+//---------------------------------------------------------------------------
+
+DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p)
+{
+
+ tShbInstance *pShbInstance;
+ tShbMemInst *pShbMemInst;
+ DWORD ulTimeOut;
+ DWORD dwWaitResult;
+ unsigned int fTimeOut;
+
+ TRACE1
+ ("\nShbIpcThreadSignalJobReady(): SignalThread started (pShbInstance=0x%08lX)\n",
+ (DWORD) pvThreadParam_p);
+
+ pShbInstance = (tShbInstance *) pvThreadParam_p;
+ pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
+ fTimeOut = FALSE;
+
+ if (pShbMemInst->m_ulTimeOutJobReady != 0) {
+ ulTimeOut = pShbMemInst->m_ulTimeOutJobReady;
+ } else {
+ ulTimeOut = INFINITE;
+ }
+
+ ASSERT((pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE)
+ && (pShbMemInst->m_hEventJobReady != NULL));
+
+ TRACE0("\nShbIpcThreadSignalJobReady(): enter wait state");
+ dwWaitResult = WaitForSingleObject(pShbMemInst->m_hEventJobReady, // HANDLE hHandle
+ ulTimeOut); // DWORD dwMilliseconds
+ TRACE0("\nShbIpcThreadSignalJobReady(): wait state leaved: ---> ");
+ switch (dwWaitResult) {
+ case WAIT_OBJECT_0 + 0: // event "new data"
+ {
+ TRACE0("Event = WAIT_OBJECT_0+0");
+ fTimeOut = FALSE;
+ break;
+ }
+
+ case WAIT_TIMEOUT:
+ {
+ TRACE0("\nEvent = WAIT_TIMEOUT");
+ fTimeOut = TRUE;
+ // ASSERT(0);
+ break;
+ }
+
+ default:
+ {
+ TRACE0("Unhandled Event");
+ fTimeOut = TRUE;
+ ASSERT(0);
+ break;
+ }
+ }
+
+ if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
+ TRACE0
+ ("\nShbIpcThreadSignalJobReady(): calling SignalHandlerJobReady");
+ pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, fTimeOut);
+ }
+
+ pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
+ pShbMemInst->m_pfnSigHndlrJobReady = NULL;
+
+ TRACE1
+ ("\nShbIpcThreadSignalJobReady(): SignalThread terminated (pShbInstance=0x%08lX)\n",
+ (DWORD) pShbInstance);
+
+ ExitThread(0);
+
+}
+
+#endif
+
+// EOF
diff --git a/drivers/staging/epl/ShbIpc.h b/drivers/staging/epl/ShbIpc.h
new file mode 100644
index 000000000000..cad8846a0824
--- /dev/null
+++ b/drivers/staging/epl/ShbIpc.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: Project independend shared buffer (linear + circular)
+
+ Description: Declaration of platform specific part for the
+ shared buffer
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ 2006/06/27 -rs: V 1.00 (initial version)
+
+****************************************************************************/
+
+#ifndef _SHBIPC_H_
+#define _SHBIPC_H_
+
+//---------------------------------------------------------------------------
+// Type definitions
+//---------------------------------------------------------------------------
+
+typedef int (*tSigHndlrNewData) (tShbInstance pShbInstance_p);
+typedef void (*tSigHndlrJobReady) (tShbInstance pShbInstance_p,
+ unsigned int fTimeOut_p);
+
+#if (TARGET_SYSTEM == _WIN32_)
+#if defined(INLINE_FUNCTION_DEF)
+#undef INLINE_FUNCTION
+#define INLINE_FUNCTION INLINE_FUNCTION_DEF
+#define SHBIPC_INLINE_ENABLED TRUE
+#define SHBIPC_INLINED
+#include "ShbIpc-Win32.c"
+#endif
+
+#elif (TARGET_SYSTEM == _LINUX_)
+#if defined(INLINE_FUNCTION_DEF)
+#undef INLINE_FUNCTION
+#define INLINE_FUNCTION INLINE_FUNCTION_DEF
+#define SHBIPC_INLINE_ENABLED TRUE
+#define SHBIPC_INLINED
+#include "ShbIpc-LinuxKernel.c"
+#endif
+#endif
+
+//---------------------------------------------------------------------------
+// Prototypes
+//---------------------------------------------------------------------------
+
+tShbError ShbIpcInit(void);
+tShbError ShbIpcExit(void);
+
+tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
+ const char *pszBufferID_p,
+ tShbInstance * ppShbInstance_p,
+ unsigned int *pfShbNewCreated_p);
+tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p);
+
+#if !defined(SHBIPC_INLINE_ENABLED)
+
+tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p);
+tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p);
+
+tShbError ShbIpcStartSignalingNewData(tShbInstance pShbInstance_p,
+ tSigHndlrNewData
+ pfnSignalHandlerNewData_p,
+ tShbPriority ShbPriority_p);
+tShbError ShbIpcStopSignalingNewData(tShbInstance pShbInstance_p);
+tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p);
+
+tShbError ShbIpcStartSignalingJobReady(tShbInstance pShbInstance_p,
+ unsigned long ulTimeOut_p,
+ tSigHndlrJobReady
+ pfnSignalHandlerJobReady_p);
+tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p);
+
+void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p);
+#endif
+
+#undef SHBIPC_INLINE_ENABLED // disable actual inlining of functions
+#undef INLINE_FUNCTION
+#define INLINE_FUNCTION // define INLINE_FUNCTION to nothing
+
+#endif // #ifndef _SHBIPC_H_
diff --git a/drivers/staging/epl/ShbLinuxKernel.h b/drivers/staging/epl/ShbLinuxKernel.h
new file mode 100644
index 000000000000..812702add4f0
--- /dev/null
+++ b/drivers/staging/epl/ShbLinuxKernel.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: Project independend shared buffer (linear + circular)
+
+ Description: Declaration of platform specific part for the
+ shared buffer
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ 2006/07/20 -rs: V 1.00 (initial version)
+
+****************************************************************************/
+
+#ifndef _SHBLINUXKERNEL_H_
+#define _SHBLINUXKERNEL_H_
+
+struct sShbMemTable {
+ int m_iBufferId;
+ void *m_pBuffer;
+ struct sShbMemTable *m_psNextMemTableElement;
+};
+
+extern struct sShbMemTable *psMemTableElementFirst_g;
+
+#endif // _SHBLINUXKERNEL_H_
diff --git a/drivers/staging/epl/SocketLinuxKernel.c b/drivers/staging/epl/SocketLinuxKernel.c
new file mode 100644
index 000000000000..562bc4a3e562
--- /dev/null
+++ b/drivers/staging/epl/SocketLinuxKernel.c
@@ -0,0 +1,197 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: Wrapper for BSD socket API for Linux kernel
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: SocketLinuxKernel.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ Dev C++ and GNU-Compiler for m68k
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/08/25 d.k.: start of implementation
+
+****************************************************************************/
+
+#include <linux/net.h>
+#include <linux/in.h>
+#include "SocketLinuxKernel.h"
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Kernel Module specific Data Structures
+//---------------------------------------------------------------------------
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+SOCKET socket(int af, int type, int protocol)
+{
+ int rc;
+ SOCKET socket;
+
+ rc = sock_create_kern(af, type, protocol, &socket);
+ if (rc < 0) {
+ socket = NULL;
+ goto Exit;
+ }
+
+ Exit:
+ return socket;
+}
+
+int bind(SOCKET socket_p, const struct sockaddr *addr, int addrlen)
+{
+ int rc;
+
+ rc = socket_p->ops->bind(socket_p, (struct sockaddr *)addr, addrlen);
+
+ return rc;
+}
+
+int closesocket(SOCKET socket_p)
+{
+ sock_release(socket_p);
+
+ return 0;
+}
+
+int recvfrom(SOCKET socket_p, char *buf, int len, int flags,
+ struct sockaddr *from, int *fromlen)
+{
+ int rc;
+ struct msghdr msg;
+ struct kvec iov;
+
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_name = from; // will be struct sock_addr
+ msg.msg_namelen = *fromlen;
+ iov.iov_len = len;
+ iov.iov_base = buf;
+
+ rc = kernel_recvmsg(socket_p, &msg, &iov, 1, iov.iov_len, 0);
+
+ return rc;
+}
+
+int sendto(SOCKET socket_p, const char *buf, int len, int flags,
+ const struct sockaddr *to, int tolen)
+{
+ int rc;
+ struct msghdr msg;
+ struct kvec iov;
+
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_name = (struct sockaddr *)to; // will be struct sock_addr
+ msg.msg_namelen = tolen;
+ msg.msg_flags = 0;
+ iov.iov_len = len;
+ iov.iov_base = (char *)buf;
+
+ rc = kernel_sendmsg(socket_p, &msg, &iov, 1, len);
+
+ return rc;
+}
+
+// EOF
diff --git a/drivers/staging/epl/SocketLinuxKernel.h b/drivers/staging/epl/SocketLinuxKernel.h
new file mode 100644
index 000000000000..6e1d61989607
--- /dev/null
+++ b/drivers/staging/epl/SocketLinuxKernel.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for BSD socket API for Linux kernel
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: SocketLinuxKernel.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/08/25 d.k.: start of the implementation
+
+****************************************************************************/
+
+#ifndef _SOCKETLINUXKERNEL_H_
+#define _SOCKETLINUXKERNEL_H_
+
+#include <linux/net.h>
+#include <linux/in.h>
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define INVALID_SOCKET 0
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef struct socket *SOCKET;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+int bind(SOCKET s, const struct sockaddr *addr, int addrlen);
+
+int closesocket(SOCKET s);
+
+int recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from,
+ int *fromlen);
+
+int sendto(SOCKET s, const char *buf, int len, int flags,
+ const struct sockaddr *to, int tolen);
+
+SOCKET socket(int af, int type, int protocol);
+
+#endif // #ifndef _SOCKETLINUXKERNEL_H_
diff --git a/drivers/staging/epl/TimerHighReskX86.c b/drivers/staging/epl/TimerHighReskX86.c
new file mode 100644
index 000000000000..82eee4702aa6
--- /dev/null
+++ b/drivers/staging/epl/TimerHighReskX86.c
@@ -0,0 +1,522 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: target specific implementation of
+ high resolution timer module for X86 under Linux
+ The Linux kernel has to be compiled with high resolution
+ timers enabled. This is done by configuring the kernel
+ with CONFIG_HIGH_RES_TIMERS enabled.
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: TimerHighReskX86.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:38:01 $
+
+ $State: Exp $
+
+ Build Environment:
+ GNU
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+****************************************************************************/
+
+#include "EplInc.h"
+#include "kernel/EplTimerHighResk.h"
+#include "Benchmark.h"
+
+//#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#define TIMER_COUNT 2 /* max 15 timers selectable */
+#define TIMER_MIN_VAL_SINGLE 5000 /* min 5us */
+#define TIMER_MIN_VAL_CYCLE 100000 /* min 100us */
+
+#define PROVE_OVERRUN
+
+#ifndef CONFIG_HIGH_RES_TIMERS
+#error "Kernel symbol CONFIG_HIGH_RES_TIMERS is required."
+#endif
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#define TGT_DBG_POST_TRACE_VALUE(v)
+#endif
+#define HRT_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
+ TGT_DBG_POST_TRACE_VALUE((0xE << 28) | (Event_p << 24) \
+ | (uiNodeId_p << 16) | wErrorCode_p)
+
+#define TIMERHDL_MASK 0x0FFFFFFF
+#define TIMERHDL_SHIFT 28
+#define HDL_TO_IDX(Hdl) ((Hdl >> TIMERHDL_SHIFT) - 1)
+#define HDL_INIT(Idx) ((Idx + 1) << TIMERHDL_SHIFT)
+#define HDL_INC(Hdl) (((Hdl + 1) & TIMERHDL_MASK) \
+ | (Hdl & ~TIMERHDL_MASK))
+
+//---------------------------------------------------------------------------
+// modul global types
+//---------------------------------------------------------------------------
+
+typedef struct {
+ tEplTimerEventArg m_EventArg;
+ tEplTimerkCallback m_pfnCallback;
+ struct hrtimer m_Timer;
+ BOOL m_fContinuously;
+ unsigned long long m_ullPeriod;
+
+} tEplTimerHighReskTimerInfo;
+
+typedef struct {
+ tEplTimerHighReskTimerInfo m_aTimerInfo[TIMER_COUNT];
+
+} tEplTimerHighReskInstance;
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+static tEplTimerHighReskInstance EplTimerHighReskInstance_l;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+enum hrtimer_restart EplTimerHighReskCallback(struct hrtimer *pTimer_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimerHighReskInit()
+//
+// Description: initializes the high resolution timer module.
+//
+// Parameters: void
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimerHighReskInit(void)
+{
+ tEplKernel Ret;
+
+ Ret = EplTimerHighReskAddInstance();
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimerHighReskAddInstance()
+//
+// Description: initializes the high resolution timer module.
+//
+// Parameters: void
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimerHighReskAddInstance(void)
+{
+ tEplKernel Ret;
+ unsigned int uiIndex;
+
+ Ret = kEplSuccessful;
+
+ EPL_MEMSET(&EplTimerHighReskInstance_l, 0,
+ sizeof(EplTimerHighReskInstance_l));
+
+#ifndef CONFIG_HIGH_RES_TIMERS
+ printk
+ ("EplTimerHighResk: Kernel symbol CONFIG_HIGH_RES_TIMERS is required.\n");
+ Ret = kEplNoResource;
+ return Ret;
+#endif
+
+ /*
+ * Initialize hrtimer structures for all usable timers.
+ */
+ for (uiIndex = 0; uiIndex < TIMER_COUNT; uiIndex++) {
+ tEplTimerHighReskTimerInfo *pTimerInfo;
+ struct hrtimer *pTimer;
+
+ pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[uiIndex];
+ pTimer = &pTimerInfo->m_Timer;
+ hrtimer_init(pTimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+
+ pTimer->function = EplTimerHighReskCallback;
+ }
+
+ return Ret;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimerHighReskDelInstance()
+//
+// Description: shuts down the high resolution timer module.
+//
+// Parameters: void
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimerHighReskDelInstance(void)
+{
+ tEplTimerHighReskTimerInfo *pTimerInfo;
+ tEplKernel Ret;
+ unsigned int uiIndex;
+
+ Ret = kEplSuccessful;
+
+ for (uiIndex = 0; uiIndex < TIMER_COUNT; uiIndex++) {
+ pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[0];
+ pTimerInfo->m_pfnCallback = NULL;
+ pTimerInfo->m_EventArg.m_TimerHdl = 0;
+ /*
+ * In this case we can not just try to cancel the timer.
+ * We actually have to wait until its callback function
+ * has returned.
+ */
+ hrtimer_cancel(&pTimerInfo->m_Timer);
+ }
+
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimerHighReskModifyTimerNs()
+//
+// Description: modifies the timeout of the timer with the specified handle.
+// If the handle the pointer points to is zero, the timer must
+// be created first.
+// If it is not possible to stop the old timer,
+// this function always assures that the old timer does not
+// trigger the callback function with the same handle as the new
+// timer. That means the callback function must check the passed
+// handle with the one returned by this function. If these are
+// unequal, the call can be discarded.
+//
+// Parameters: pTimerHdl_p = pointer to timer handle
+// ullTimeNs_p = relative timeout in [ns]
+// pfnCallback_p = callback function, which is called mutual
+// exclusive with the Edrv callback functions
+// (Rx and Tx).
+// ulArgument_p = user-specific argument
+// fContinuously_p = if TRUE, callback function will be called
+// continuously;
+// otherwise, it is a oneshot timer.
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimerHighReskModifyTimerNs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long long ullTimeNs_p,
+ tEplTimerkCallback
+ pfnCallback_p,
+ unsigned long ulArgument_p,
+ BOOL fContinuously_p)
+{
+ tEplKernel Ret;
+ unsigned int uiIndex;
+ tEplTimerHighReskTimerInfo *pTimerInfo;
+ ktime_t RelTime;
+
+ Ret = kEplSuccessful;
+
+ // check pointer to handle
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ if (*pTimerHdl_p == 0) { // no timer created yet
+
+ // search free timer info structure
+ pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[0];
+ for (uiIndex = 0; uiIndex < TIMER_COUNT;
+ uiIndex++, pTimerInfo++) {
+ if (pTimerInfo->m_EventArg.m_TimerHdl == 0) { // free structure found
+ break;
+ }
+ }
+ if (uiIndex >= TIMER_COUNT) { // no free structure found
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+
+ pTimerInfo->m_EventArg.m_TimerHdl = HDL_INIT(uiIndex);
+ } else {
+ uiIndex = HDL_TO_IDX(*pTimerHdl_p);
+ if (uiIndex >= TIMER_COUNT) { // invalid handle
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[uiIndex];
+ }
+
+ /*
+ * increment timer handle
+ * (if timer expires right after this statement, the user
+ * would detect an unknown timer handle and discard it)
+ */
+ pTimerInfo->m_EventArg.m_TimerHdl =
+ HDL_INC(pTimerInfo->m_EventArg.m_TimerHdl);
+ *pTimerHdl_p = pTimerInfo->m_EventArg.m_TimerHdl;
+
+ // reject too small time values
+ if ((fContinuously_p && (ullTimeNs_p < TIMER_MIN_VAL_CYCLE))
+ || (!fContinuously_p && (ullTimeNs_p < TIMER_MIN_VAL_SINGLE))) {
+ Ret = kEplTimerNoTimerCreated;
+ goto Exit;
+ }
+
+ pTimerInfo->m_EventArg.m_ulArg = ulArgument_p;
+ pTimerInfo->m_pfnCallback = pfnCallback_p;
+ pTimerInfo->m_fContinuously = fContinuously_p;
+ pTimerInfo->m_ullPeriod = ullTimeNs_p;
+
+ /*
+ * HRTIMER_MODE_REL does not influence general handling of this timer.
+ * It only sets relative mode for this start operation.
+ * -> Expire time is calculated by: Now + RelTime
+ * hrtimer_start also skips pending timer events.
+ * The state HRTIMER_STATE_CALLBACK is ignored.
+ * We have to cope with that in our callback function.
+ */
+ RelTime = ktime_add_ns(ktime_set(0, 0), ullTimeNs_p);
+ hrtimer_start(&pTimerInfo->m_Timer, RelTime, HRTIMER_MODE_REL);
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimerHighReskDeleteTimer()
+//
+// Description: deletes the timer with the specified handle. Afterward the
+// handle is set to zero.
+//
+// Parameters: pTimerHdl_p = pointer to timer handle
+//
+// Return: tEplKernel = error code
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimerHighReskDeleteTimer(tEplTimerHdl * pTimerHdl_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ unsigned int uiIndex;
+ tEplTimerHighReskTimerInfo *pTimerInfo;
+
+ // check pointer to handle
+ if (pTimerHdl_p == NULL) {
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+
+ if (*pTimerHdl_p == 0) { // no timer created yet
+ goto Exit;
+ } else {
+ uiIndex = HDL_TO_IDX(*pTimerHdl_p);
+ if (uiIndex >= TIMER_COUNT) { // invalid handle
+ Ret = kEplTimerInvalidHandle;
+ goto Exit;
+ }
+ pTimerInfo = &EplTimerHighReskInstance_l.m_aTimerInfo[uiIndex];
+ if (pTimerInfo->m_EventArg.m_TimerHdl != *pTimerHdl_p) { // invalid handle
+ goto Exit;
+ }
+ }
+
+ *pTimerHdl_p = 0;
+ pTimerInfo->m_EventArg.m_TimerHdl = 0;
+ pTimerInfo->m_pfnCallback = NULL;
+
+ /*
+ * Three return cases of hrtimer_try_to_cancel have to be tracked:
+ * 1 - timer has been removed
+ * 0 - timer was not active
+ * We need not do anything. hrtimer timers just consist of
+ * a hrtimer struct, which we might enqueue in the hrtimers
+ * event list by calling hrtimer_start().
+ * If a timer is not enqueued, it is not present in hrtimers.
+ * -1 - callback function is running
+ * In this case we have to ensure that the timer is not
+ * continuously restarted. This has been done by clearing
+ * its handle.
+ */
+ hrtimer_try_to_cancel(&pTimerInfo->m_Timer);
+
+ Exit:
+ return Ret;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: EplTimerHighReskCallback()
+//
+// Description: Callback function commonly used for all timers.
+//
+// Parameters: pTimer_p = pointer to hrtimer
+//
+// Return:
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+enum hrtimer_restart EplTimerHighReskCallback(struct hrtimer *pTimer_p)
+{
+ unsigned int uiIndex;
+ tEplTimerHighReskTimerInfo *pTimerInfo;
+ tEplTimerHdl OrgTimerHdl;
+ enum hrtimer_restart Ret;
+
+ BENCHMARK_MOD_24_SET(4);
+
+ Ret = HRTIMER_NORESTART;
+ pTimerInfo =
+ container_of(pTimer_p, tEplTimerHighReskTimerInfo, m_Timer);
+ uiIndex = HDL_TO_IDX(pTimerInfo->m_EventArg.m_TimerHdl);
+ if (uiIndex >= TIMER_COUNT) { // invalid handle
+ goto Exit;
+ }
+
+ /*
+ * We store the timer handle before calling the callback function
+ * as the timer can be modified inside it.
+ */
+ OrgTimerHdl = pTimerInfo->m_EventArg.m_TimerHdl;
+
+ if (pTimerInfo->m_pfnCallback != NULL) {
+ pTimerInfo->m_pfnCallback(&pTimerInfo->m_EventArg);
+ }
+
+ if (pTimerInfo->m_fContinuously) {
+ ktime_t Interval;
+#ifdef PROVE_OVERRUN
+ ktime_t Now;
+ unsigned long Overruns;
+#endif
+
+ if (OrgTimerHdl != pTimerInfo->m_EventArg.m_TimerHdl) {
+ /* modified timer has already been restarted */
+ goto Exit;
+ }
+#ifdef PROVE_OVERRUN
+ Now = ktime_get();
+ Interval =
+ ktime_add_ns(ktime_set(0, 0), pTimerInfo->m_ullPeriod);
+ Overruns = hrtimer_forward(pTimer_p, Now, Interval);
+ if (Overruns > 1) {
+ printk
+ ("EplTimerHighResk: Continuous timer (handle 0x%lX) had to skip %lu interval(s)!\n",
+ pTimerInfo->m_EventArg.m_TimerHdl, Overruns - 1);
+ }
+#else
+ pTimer_p->expires = ktime_add_ns(pTimer_p->expires,
+ pTimerInfo->m_ullPeriod);
+#endif
+
+ Ret = HRTIMER_RESTART;
+ }
+
+ Exit:
+ BENCHMARK_MOD_24_RESET(4);
+ return Ret;
+}
diff --git a/drivers/staging/epl/VirtualEthernetLinux.c b/drivers/staging/epl/VirtualEthernetLinux.c
new file mode 100644
index 000000000000..5d838dbf73a7
--- /dev/null
+++ b/drivers/staging/epl/VirtualEthernetLinux.c
@@ -0,0 +1,342 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: Virtual Ethernet Driver for Linux
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: VirtualEthernetLinux.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/11/20 17:06:51 $
+
+ $State: Exp $
+
+ Build Environment:
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/12 -ar: start of the implementation, version 1.00
+
+ 2006/09/18 d.k.: integration into EPL DLLk module
+
+ ToDo:
+
+ void netif_carrier_off(struct net_device *dev);
+ void netif_carrier_on(struct net_device *dev);
+
+****************************************************************************/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include <net/protocol.h>
+#include <net/pkt_sched.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/skbuff.h> /* for struct sk_buff */
+
+#include "kernel/VirtualEthernet.h"
+#include "kernel/EplDllkCal.h"
+#include "kernel/EplDllk.h"
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef EPL_VETH_TX_TIMEOUT
+//#define EPL_VETH_TX_TIMEOUT (2*HZ)
+#define EPL_VETH_TX_TIMEOUT 0 // d.k.: we use no timeout
+#endif
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+static struct net_device *pVEthNetDevice_g = NULL;
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static int VEthOpen(struct net_device *pNetDevice_p);
+static int VEthClose(struct net_device *pNetDevice_p);
+static int VEthXmit(struct sk_buff *pSkb_p, struct net_device *pNetDevice_p);
+static struct net_device_stats *VEthGetStats(struct net_device *pNetDevice_p);
+static void VEthTimeout(struct net_device *pNetDevice_p);
+static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+static int VEthOpen(struct net_device *pNetDevice_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ //open the device
+// struct net_device_stats* pStats = netdev_priv(pNetDevice_p);
+
+ //start the interface queue for the network subsystem
+ netif_start_queue(pNetDevice_p);
+
+ // register callback function in DLL
+ Ret = EplDllkRegAsyncHandler(VEthRecvFrame);
+
+ EPL_DBGLVL_VETH_TRACE1
+ ("VEthOpen: EplDllkRegAsyncHandler returned 0x%02X\n", Ret);
+
+ return 0;
+}
+
+static int VEthClose(struct net_device *pNetDevice_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ EPL_DBGLVL_VETH_TRACE0("VEthClose\n");
+
+ Ret = EplDllkDeregAsyncHandler(VEthRecvFrame);
+
+ //stop the interface queue for the network subsystem
+ netif_stop_queue(pNetDevice_p);
+ return 0;
+}
+
+static int VEthXmit(struct sk_buff *pSkb_p, struct net_device *pNetDevice_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ tEplFrameInfo FrameInfo;
+
+ //transmit function
+ struct net_device_stats *pStats = netdev_priv(pNetDevice_p);
+
+ //save timestemp
+ pNetDevice_p->trans_start = jiffies;
+
+ FrameInfo.m_pFrame = (tEplFrame *) pSkb_p->data;
+ FrameInfo.m_uiFrameSize = pSkb_p->len;
+
+ //call send fkt on DLL
+ Ret = EplDllkCalAsyncSend(&FrameInfo, kEplDllAsyncReqPrioGeneric);
+ if (Ret != kEplSuccessful) {
+ EPL_DBGLVL_VETH_TRACE1
+ ("VEthXmit: EplDllkCalAsyncSend returned 0x%02X\n", Ret);
+ netif_stop_queue(pNetDevice_p);
+ goto Exit;
+ } else {
+ EPL_DBGLVL_VETH_TRACE0("VEthXmit: frame passed to DLL\n");
+ dev_kfree_skb(pSkb_p);
+
+ //set stats for the device
+ pStats->tx_packets++;
+ pStats->tx_bytes += FrameInfo.m_uiFrameSize;
+ }
+
+ Exit:
+ return 0;
+
+}
+
+static struct net_device_stats *VEthGetStats(struct net_device *pNetDevice_p)
+{
+ EPL_DBGLVL_VETH_TRACE0("VEthGetStats\n");
+
+ return netdev_priv(pNetDevice_p);
+}
+
+static void VEthTimeout(struct net_device *pNetDevice_p)
+{
+ EPL_DBGLVL_VETH_TRACE0("VEthTimeout(\n");
+
+ // $$$ d.k.: move to extra function, which is called by DLL when new space is available in TxFifo
+ if (netif_queue_stopped(pNetDevice_p)) {
+ netif_wake_queue(pNetDevice_p);
+ }
+}
+
+static tEplKernel VEthRecvFrame(tEplFrameInfo * pFrameInfo_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+ struct net_device *pNetDevice = pVEthNetDevice_g;
+ struct net_device_stats *pStats = netdev_priv(pNetDevice);
+ struct sk_buff *pSkb;
+
+ EPL_DBGLVL_VETH_TRACE1("VEthRecvFrame: FrameSize=%u\n",
+ pFrameInfo_p->m_uiFrameSize);
+
+ pSkb = dev_alloc_skb(pFrameInfo_p->m_uiFrameSize + 2);
+ if (pSkb == NULL) {
+ pStats->rx_dropped++;
+ goto Exit;
+ }
+ pSkb->dev = pNetDevice;
+
+ skb_reserve(pSkb, 2);
+
+ memcpy((void *)skb_put(pSkb, pFrameInfo_p->m_uiFrameSize),
+ pFrameInfo_p->m_pFrame, pFrameInfo_p->m_uiFrameSize);
+
+ pSkb->protocol = eth_type_trans(pSkb, pNetDevice);
+ pSkb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ // call netif_rx with skb
+ netif_rx(pSkb);
+
+ EPL_DBGLVL_VETH_TRACE1("VEthRecvFrame: SrcMAC=0x%llx\n",
+ AmiGetQword48FromBe(pFrameInfo_p->m_pFrame->
+ m_be_abSrcMac));
+
+ // update receive statistics
+ pStats->rx_packets++;
+ pStats->rx_bytes += pFrameInfo_p->m_uiFrameSize;
+
+ Exit:
+ return Ret;
+}
+
+tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ // allocate net device structure with priv pointing to stats structure
+ pVEthNetDevice_g =
+ alloc_netdev(sizeof(struct net_device_stats), EPL_VETH_NAME,
+ ether_setup);
+// pVEthNetDevice_g = alloc_etherdev(sizeof (struct net_device_stats));
+
+ if (pVEthNetDevice_g == NULL) {
+ Ret = kEplNoResource;
+ goto Exit;
+ }
+
+ pVEthNetDevice_g->open = VEthOpen;
+ pVEthNetDevice_g->stop = VEthClose;
+ pVEthNetDevice_g->get_stats = VEthGetStats;
+ pVEthNetDevice_g->hard_start_xmit = VEthXmit;
+ pVEthNetDevice_g->tx_timeout = VEthTimeout;
+ pVEthNetDevice_g->watchdog_timeo = EPL_VETH_TX_TIMEOUT;
+ pVEthNetDevice_g->destructor = free_netdev;
+
+ // copy own MAC address to net device structure
+ memcpy(pVEthNetDevice_g->dev_addr, pInitParam_p->m_be_abSrcMac, 6);
+
+ //register VEth to the network subsystem
+ if (register_netdev(pVEthNetDevice_g)) {
+ EPL_DBGLVL_VETH_TRACE0
+ ("VEthAddInstance: Could not register VEth...\n");
+ } else {
+ EPL_DBGLVL_VETH_TRACE0
+ ("VEthAddInstance: Register VEth successfull...\n");
+ }
+
+ Exit:
+ return Ret;
+}
+
+tEplKernel PUBLIC VEthDelInstance(void)
+{
+ tEplKernel Ret = kEplSuccessful;
+
+ if (pVEthNetDevice_g != NULL) {
+ //unregister VEth from the network subsystem
+ unregister_netdev(pVEthNetDevice_g);
+ // destructor was set to free_netdev,
+ // so we do not need to call free_netdev here
+ pVEthNetDevice_g = NULL;
+ }
+
+ return Ret;
+}
+
+#endif // (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
diff --git a/drivers/staging/epl/amix86.c b/drivers/staging/epl/amix86.c
new file mode 100644
index 000000000000..9f742384dac0
--- /dev/null
+++ b/drivers/staging/epl/amix86.c
@@ -0,0 +1,905 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: Abstract Memory Interface for x86 compatible
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: amix86.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ ...
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ r.s.: first implemetation
+
+ 2006-06-13 d.k.: duplicate functions for little endian and big endian
+
+****************************************************************************/
+
+//#include "global.h"
+//#include "EplAmi.h"
+#include "EplInc.h"
+
+#if (!defined(EPL_AMI_INLINED)) || defined(INLINE_ENABLED)
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef struct {
+ WORD m_wWord;
+
+} twStruct;
+
+typedef struct {
+ DWORD m_dwDword;
+
+} tdwStruct;
+
+typedef struct {
+ QWORD m_qwQword;
+
+} tqwStruct;
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetXXXToBe()
+//
+// Description: writes the specified value to the absolute address in
+// big endian
+//
+// Parameters: pAddr_p = absolute address
+// xXXXVal_p = value
+//
+// Returns: (none)
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+//------------< write BYTE in big endian >--------------------------
+/*
+void PUBLIC AmiSetByteToBe (void FAR* pAddr_p, BYTE bByteVal_p)
+{
+
+ *(BYTE FAR*)pAddr_p = bByteVal_p;
+
+}
+*/
+
+//------------< write WORD in big endian >--------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetWordToBe(void FAR * pAddr_p, WORD wWordVal_p)
+{
+ twStruct FAR *pwStruct;
+ twStruct wValue;
+
+ wValue.m_wWord = (WORD) ((wWordVal_p & 0x00FF) << 8); //LSB to MSB
+ wValue.m_wWord |= (WORD) ((wWordVal_p & 0xFF00) >> 8); //MSB to LSB
+
+ pwStruct = (twStruct FAR *) pAddr_p;
+ pwStruct->m_wWord = wValue.m_wWord;
+
+}
+
+//------------< write DWORD in big endian >-------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetDwordToBe(void FAR * pAddr_p,
+ DWORD dwDwordVal_p)
+{
+ tdwStruct FAR *pdwStruct;
+ tdwStruct dwValue;
+
+ dwValue.m_dwDword = ((dwDwordVal_p & 0x000000FF) << 24); //LSB to MSB
+ dwValue.m_dwDword |= ((dwDwordVal_p & 0x0000FF00) << 8);
+ dwValue.m_dwDword |= ((dwDwordVal_p & 0x00FF0000) >> 8);
+ dwValue.m_dwDword |= ((dwDwordVal_p & 0xFF000000) >> 24); //MSB to LSB
+
+ pdwStruct = (tdwStruct FAR *) pAddr_p;
+ pdwStruct->m_dwDword = dwValue.m_dwDword;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetXXXToLe()
+//
+// Description: writes the specified value to the absolute address in
+// little endian
+//
+// Parameters: pAddr_p = absolute address
+// xXXXVal_p = value
+//
+// Returns: (none)
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+//------------< write BYTE in little endian >--------------------------
+/*
+void PUBLIC AmiSetByteToLe (void FAR* pAddr_p, BYTE bByteVal_p)
+{
+
+ *(BYTE FAR*)pAddr_p = bByteVal_p;
+
+}
+*/
+
+//------------< write WORD in little endian >--------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetWordToLe(void FAR * pAddr_p, WORD wWordVal_p)
+{
+ twStruct FAR *pwStruct;
+
+ pwStruct = (twStruct FAR *) pAddr_p;
+ pwStruct->m_wWord = wWordVal_p;
+
+}
+
+//------------< write DWORD in little endian >-------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetDwordToLe(void FAR * pAddr_p,
+ DWORD dwDwordVal_p)
+{
+ tdwStruct FAR *pdwStruct;
+
+ pdwStruct = (tdwStruct FAR *) pAddr_p;
+ pdwStruct->m_dwDword = dwDwordVal_p;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetXXXFromBe()
+//
+// Description: reads the specified value from the absolute address in
+// big endian
+//
+// Parameters: pAddr_p = absolute address
+//
+// Returns: XXX = value
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+//------------< read BYTE in big endian >---------------------------
+/*
+BYTE PUBLIC AmiGetByteFromBe (void FAR* pAddr_p)
+{
+
+ return ( *(BYTE FAR*)pAddr_p );
+
+}
+*/
+
+//------------< read WORD in big endian >---------------------------
+
+INLINE_FUNCTION WORD PUBLIC AmiGetWordFromBe(void FAR * pAddr_p)
+{
+ twStruct FAR *pwStruct;
+ twStruct wValue;
+
+ pwStruct = (twStruct FAR *) pAddr_p;
+
+ wValue.m_wWord = (WORD) ((pwStruct->m_wWord & 0x00FF) << 8); //LSB to MSB
+ wValue.m_wWord |= (WORD) ((pwStruct->m_wWord & 0xFF00) >> 8); //MSB to LSB
+
+ return (wValue.m_wWord);
+
+}
+
+//------------< read DWORD in big endian >--------------------------
+
+INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromBe(void FAR * pAddr_p)
+{
+ tdwStruct FAR *pdwStruct;
+ tdwStruct dwValue;
+
+ pdwStruct = (tdwStruct FAR *) pAddr_p;
+
+ dwValue.m_dwDword = ((pdwStruct->m_dwDword & 0x000000FF) << 24); //LSB to MSB
+ dwValue.m_dwDword |= ((pdwStruct->m_dwDword & 0x0000FF00) << 8);
+ dwValue.m_dwDword |= ((pdwStruct->m_dwDword & 0x00FF0000) >> 8);
+ dwValue.m_dwDword |= ((pdwStruct->m_dwDword & 0xFF000000) >> 24); //MSB to LSB
+
+ return (dwValue.m_dwDword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetXXXFromLe()
+//
+// Description: reads the specified value from the absolute address in
+// little endian
+//
+// Parameters: pAddr_p = absolute address
+//
+// Returns: XXX = value
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+//------------< read BYTE in little endian >---------------------------
+/*
+BYTE PUBLIC AmiGetByteFromLe (void FAR* pAddr_p)
+{
+
+ return ( *(BYTE FAR*)pAddr_p );
+
+}
+*/
+
+//------------< read WORD in little endian >---------------------------
+
+INLINE_FUNCTION WORD PUBLIC AmiGetWordFromLe(void FAR * pAddr_p)
+{
+ twStruct FAR *pwStruct;
+
+ pwStruct = (twStruct FAR *) pAddr_p;
+ return (pwStruct->m_wWord);
+
+}
+
+//------------< read DWORD in little endian >--------------------------
+
+INLINE_FUNCTION DWORD PUBLIC AmiGetDwordFromLe(void FAR * pAddr_p)
+{
+ tdwStruct FAR *pdwStruct;
+
+ pdwStruct = (tdwStruct FAR *) pAddr_p;
+ return (pdwStruct->m_dwDword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetDword24ToBe()
+//
+// Description: sets a 24 bit value to a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// dwDwordVal_p = value to set
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetDword24ToBe(void FAR * pAddr_p,
+ DWORD dwDwordVal_p)
+{
+
+ ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & dwDwordVal_p)[2];
+ ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & dwDwordVal_p)[1];
+ ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & dwDwordVal_p)[0];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetDword24ToLe()
+//
+// Description: sets a 24 bit value to a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// dwDwordVal_p = value to set
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetDword24ToLe(void FAR * pAddr_p,
+ DWORD dwDwordVal_p)
+{
+
+ ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & dwDwordVal_p)[0];
+ ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & dwDwordVal_p)[1];
+ ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & dwDwordVal_p)[2];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetDword24FromBe()
+//
+// Description: reads a 24 bit value from a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: DWORD = read value
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromBe(void FAR * pAddr_p)
+{
+
+ tdwStruct dwStruct;
+
+ dwStruct.m_dwDword = AmiGetDwordFromBe(pAddr_p);
+ dwStruct.m_dwDword >>= 8;
+
+ return (dwStruct.m_dwDword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetDword24FromLe()
+//
+// Description: reads a 24 bit value from a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: DWORD = read value
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION DWORD PUBLIC AmiGetDword24FromLe(void FAR * pAddr_p)
+{
+
+ tdwStruct dwStruct;
+
+ dwStruct.m_dwDword = AmiGetDwordFromLe(pAddr_p);
+ dwStruct.m_dwDword &= 0x00FFFFFF;
+
+ return (dwStruct.m_dwDword);
+
+}
+
+//#ifdef USE_VAR64
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword64ToBe()
+//
+// Description: sets a 64 bit value to a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword64ToBe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[7];
+ ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[6];
+ ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[5];
+ ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[4];
+ ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[3];
+ ((BYTE FAR *) pAddr_p)[5] = ((BYTE FAR *) & qwQwordVal_p)[2];
+ ((BYTE FAR *) pAddr_p)[6] = ((BYTE FAR *) & qwQwordVal_p)[1];
+ ((BYTE FAR *) pAddr_p)[7] = ((BYTE FAR *) & qwQwordVal_p)[0];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword64ToLe()
+//
+// Description: sets a 64 bit value to a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword64ToLe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ QWORD FAR *pqwDst;
+
+ pqwDst = (QWORD FAR *) pAddr_p;
+ *pqwDst = qwQwordVal_p;
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword64FromBe()
+//
+// Description: reads a 64 bit value from a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromBe(void FAR * pAddr_p)
+{
+
+ tqwStruct qwStruct;
+
+ ((BYTE FAR *) & qwStruct.m_qwQword)[0] = ((BYTE FAR *) pAddr_p)[7];
+ ((BYTE FAR *) & qwStruct.m_qwQword)[1] = ((BYTE FAR *) pAddr_p)[6];
+ ((BYTE FAR *) & qwStruct.m_qwQword)[2] = ((BYTE FAR *) pAddr_p)[5];
+ ((BYTE FAR *) & qwStruct.m_qwQword)[3] = ((BYTE FAR *) pAddr_p)[4];
+ ((BYTE FAR *) & qwStruct.m_qwQword)[4] = ((BYTE FAR *) pAddr_p)[3];
+ ((BYTE FAR *) & qwStruct.m_qwQword)[5] = ((BYTE FAR *) pAddr_p)[2];
+ ((BYTE FAR *) & qwStruct.m_qwQword)[6] = ((BYTE FAR *) pAddr_p)[1];
+ ((BYTE FAR *) & qwStruct.m_qwQword)[7] = ((BYTE FAR *) pAddr_p)[0];
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword64FromLe()
+//
+// Description: reads a 64 bit value from a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword64FromLe(void FAR * pAddr_p)
+{
+
+ tqwStruct FAR *pqwStruct;
+ tqwStruct qwStruct;
+
+ pqwStruct = (tqwStruct FAR *) pAddr_p;
+ qwStruct.m_qwQword = pqwStruct->m_qwQword;
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword40ToBe()
+//
+// Description: sets a 40 bit value to a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword40ToBe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[4];
+ ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[3];
+ ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[2];
+ ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[1];
+ ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[0];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword40ToLe()
+//
+// Description: sets a 40 bit value to a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword40ToLe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ ((DWORD FAR *) pAddr_p)[0] = ((DWORD FAR *) & qwQwordVal_p)[0];
+ ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[4];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword40FromBe()
+//
+// Description: reads a 40 bit value from a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromBe(void FAR * pAddr_p)
+{
+
+ tqwStruct qwStruct;
+
+ qwStruct.m_qwQword = AmiGetQword64FromBe(pAddr_p);
+ qwStruct.m_qwQword >>= 24;
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword40FromLe()
+//
+// Description: reads a 40 bit value from a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword40FromLe(void FAR * pAddr_p)
+{
+
+ tqwStruct qwStruct;
+
+ qwStruct.m_qwQword = AmiGetQword64FromLe(pAddr_p);
+ qwStruct.m_qwQword &= 0x000000FFFFFFFFFFLL;
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword48ToBe()
+//
+// Description: sets a 48 bit value to a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword48ToBe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[5];
+ ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[4];
+ ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[3];
+ ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[2];
+ ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[1];
+ ((BYTE FAR *) pAddr_p)[5] = ((BYTE FAR *) & qwQwordVal_p)[0];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword48ToLe()
+//
+// Description: sets a 48 bit value to a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword48ToLe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ ((DWORD FAR *) pAddr_p)[0] = ((DWORD FAR *) & qwQwordVal_p)[0];
+ ((WORD FAR *) pAddr_p)[2] = ((WORD FAR *) & qwQwordVal_p)[2];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword48FromBe()
+//
+// Description: reads a 48 bit value from a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromBe(void FAR * pAddr_p)
+{
+
+ tqwStruct qwStruct;
+
+ qwStruct.m_qwQword = AmiGetQword64FromBe(pAddr_p);
+ qwStruct.m_qwQword >>= 16;
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword48FromLe()
+//
+// Description: reads a 48 bit value from a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword48FromLe(void FAR * pAddr_p)
+{
+
+ tqwStruct qwStruct;
+
+ qwStruct.m_qwQword = AmiGetQword64FromLe(pAddr_p);
+ qwStruct.m_qwQword &= 0x0000FFFFFFFFFFFFLL;
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword56ToBe()
+//
+// Description: sets a 56 bit value to a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword56ToBe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ ((BYTE FAR *) pAddr_p)[0] = ((BYTE FAR *) & qwQwordVal_p)[6];
+ ((BYTE FAR *) pAddr_p)[1] = ((BYTE FAR *) & qwQwordVal_p)[5];
+ ((BYTE FAR *) pAddr_p)[2] = ((BYTE FAR *) & qwQwordVal_p)[4];
+ ((BYTE FAR *) pAddr_p)[3] = ((BYTE FAR *) & qwQwordVal_p)[3];
+ ((BYTE FAR *) pAddr_p)[4] = ((BYTE FAR *) & qwQwordVal_p)[2];
+ ((BYTE FAR *) pAddr_p)[5] = ((BYTE FAR *) & qwQwordVal_p)[1];
+ ((BYTE FAR *) pAddr_p)[6] = ((BYTE FAR *) & qwQwordVal_p)[0];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetQword56ToLe()
+//
+// Description: sets a 56 bit value to a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// qwQwordVal_p = quadruple word value
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetQword56ToLe(void FAR * pAddr_p,
+ QWORD qwQwordVal_p)
+{
+
+ ((DWORD FAR *) pAddr_p)[0] = ((DWORD FAR *) & qwQwordVal_p)[0];
+ ((WORD FAR *) pAddr_p)[2] = ((WORD FAR *) & qwQwordVal_p)[2];
+ ((BYTE FAR *) pAddr_p)[6] = ((BYTE FAR *) & qwQwordVal_p)[6];
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword56FromBe()
+//
+// Description: reads a 56 bit value from a buffer in big endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromBe(void FAR * pAddr_p)
+{
+
+ tqwStruct qwStruct;
+
+ qwStruct.m_qwQword = AmiGetQword64FromBe(pAddr_p);
+ qwStruct.m_qwQword >>= 8;
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetQword56FromLe()
+//
+// Description: reads a 56 bit value from a buffer in little endian
+//
+// Parameters: pAddr_p = pointer to source buffer
+//
+// Return: QWORD
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION QWORD PUBLIC AmiGetQword56FromLe(void FAR * pAddr_p)
+{
+
+ tqwStruct qwStruct;
+
+ qwStruct.m_qwQword = AmiGetQword64FromLe(pAddr_p);
+ qwStruct.m_qwQword &= 0x00FFFFFFFFFFFFFFLL;
+
+ return (qwStruct.m_qwQword);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiSetTimeOfDay()
+//
+// Description: sets a TIME_OF_DAY (CANopen) value to a buffer
+//
+// Parameters: pAddr_p = pointer to destination buffer
+// pTimeOfDay_p = pointer to struct TIME_OF_DAY
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiSetTimeOfDay(void FAR * pAddr_p,
+ tTimeOfDay FAR * pTimeOfDay_p)
+{
+
+ AmiSetDwordToLe(((BYTE FAR *) pAddr_p),
+ pTimeOfDay_p->m_dwMs & 0x0FFFFFFF);
+ AmiSetWordToLe(((BYTE FAR *) pAddr_p) + 4, pTimeOfDay_p->m_wDays);
+
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AmiGetTimeOfDay()
+//
+// Description: reads a TIME_OF_DAY (CANopen) value from a buffer
+//
+// Parameters: pAddr_p = pointer to source buffer
+// pTimeOfDay_p = pointer to struct TIME_OF_DAY
+//
+// Return: void
+//
+// State: not tested
+//
+//---------------------------------------------------------------------------
+
+INLINE_FUNCTION void PUBLIC AmiGetTimeOfDay(void FAR * pAddr_p,
+ tTimeOfDay FAR * pTimeOfDay_p)
+{
+
+ pTimeOfDay_p->m_dwMs =
+ AmiGetDwordFromLe(((BYTE FAR *) pAddr_p)) & 0x0FFFFFFF;
+ pTimeOfDay_p->m_wDays = AmiGetWordFromLe(((BYTE FAR *) pAddr_p) + 4);
+
+}
+
+#endif
+
+// EOF
+
+// Die letzte Zeile mu unbedingt eine leere Zeile sein, weil manche Compiler
+// damit ein Problem haben, wenn das nicht so ist (z.B. GNU oder Borland C++ Builder).
diff --git a/drivers/staging/epl/demo_main.c b/drivers/staging/epl/demo_main.c
new file mode 100644
index 000000000000..263fa042291d
--- /dev/null
+++ b/drivers/staging/epl/demo_main.c
@@ -0,0 +1,961 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: demoapplication for EPL MN (with SDO over UDP)
+ under Linux on X86 with RTL8139 Ethernet controller
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: demo_main.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.10 $ $Date: 2008/11/19 18:11:43 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/09/01 d.k.: start of implementation
+
+****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/sched.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+
+#include "Epl.h"
+#include "proc_fs.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ // remove ("make invisible") obsolete symbols for kernel versions 2.6
+ // and higher
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#define EXPORT_NO_SYMBOLS
+#else
+#error "This driver needs a 2.6.x kernel or higher"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+// Metainformation
+MODULE_LICENSE("Dual BSD/GPL");
+#ifdef MODULE_AUTHOR
+MODULE_AUTHOR("Daniel.Krueger@SYSTEC-electronic.com");
+MODULE_DESCRIPTION("EPL MN demo");
+#endif
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+// TracePoint support for realtime-debugging
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+#define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
+#else
+#define TGT_DBG_SIGNAL_TRACE_POINT(p)
+#endif
+
+#define NODEID 0xF0 //=> MN
+#define CYCLE_LEN 5000 // [us]
+#define IP_ADDR 0xc0a86401 // 192.168.100.1
+#define SUBNET_MASK 0xFFFFFF00 // 255.255.255.0
+#define HOSTNAME "SYS TEC electronic EPL Stack "
+#define IF_ETH EPL_VETH_NAME
+
+// LIGHT EFFECT
+#define DEFAULT_MAX_CYCLE_COUNT 20 // 6 is very fast
+#define APP_DEFAULT_MODE 0x01
+#define APP_LED_COUNT 5 // number of LEDs in one row
+#define APP_LED_MASK ((1 << APP_LED_COUNT) - 1)
+#define APP_DOUBLE_LED_MASK ((1 << (APP_LED_COUNT * 2)) - 1)
+#define APP_MODE_COUNT 5
+#define APP_MODE_MASK ((1 << APP_MODE_COUNT) - 1)
+
+//---------------------------------------------------------------------------
+// local types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// modul globale vars
+//---------------------------------------------------------------------------
+
+CONST BYTE abMacAddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+BYTE bVarIn1_l;
+BYTE bVarOut1_l;
+BYTE bVarOut1Old_l;
+BYTE bModeSelect_l; // state of the pushbuttons to select the mode
+BYTE bSpeedSelect_l; // state of the pushbuttons to increase/decrease the speed
+BYTE bSpeedSelectOld_l; // old state of the pushbuttons
+DWORD dwLeds_l; // current state of all LEDs
+BYTE bLedsRow1_l; // current state of the LEDs in row 1
+BYTE bLedsRow2_l; // current state of the LEDs in row 2
+BYTE abSelect_l[3]; // pushbuttons from CNs
+
+DWORD dwMode_l; // current mode
+int iCurCycleCount_l; // current cycle count
+int iMaxCycleCount_l; // maximum cycle count (i.e. number of cycles until next light movement step)
+int iToggle; // indicates the light movement direction
+
+BYTE abDomain_l[3000];
+
+static wait_queue_head_t WaitQueueShutdown_g; // wait queue for tEplNmtEventSwitchOff
+static atomic_t AtomicShutdown_g = ATOMIC_INIT(FALSE);
+
+static DWORD dw_le_CycleLen_g;
+
+static uint uiNodeId_g = EPL_C_ADR_INVALID;
+module_param_named(nodeid, uiNodeId_g, uint, 0);
+
+static uint uiCycleLen_g = CYCLE_LEN;
+module_param_named(cyclelen, uiCycleLen_g, uint, 0);
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+// This function is the entry point for your object dictionary. It is defined
+// in OBJDICT.C by define EPL_OBD_INIT_RAM_NAME. Use this function name to define
+// this function prototype here. If you want to use more than one Epl
+// instances then the function name of each object dictionary has to differ.
+
+tEplKernel PUBLIC EplObdInitRam(tEplObdInitParam MEM * pInitParam_p);
+
+tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
+ tEplApiEventArg * pEventArg_p, // IN: event argument (union)
+ void GENERIC * pUserArg_p);
+
+tEplKernel PUBLIC AppCbSync(void);
+
+static int __init EplLinInit(void);
+static void __exit EplLinExit(void);
+
+//---------------------------------------------------------------------------
+// Kernel Module specific Data Structures
+//---------------------------------------------------------------------------
+
+EXPORT_NO_SYMBOLS;
+
+//module_init(EplLinInit);
+//module_exit(EplLinExit);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function:
+//
+// Description:
+//
+//
+//
+// Parameters:
+//
+//
+// Returns:
+//
+//
+// State:
+//
+//---------------------------------------------------------------------------
+static int __init EplLinInit(void)
+{
+ tEplKernel EplRet;
+ int iRet;
+ static tEplApiInitParam EplApiInitParam = { 0 };
+ char *sHostname = HOSTNAME;
+ char *argv[4], *envp[3];
+ char sBuffer[16];
+ unsigned int uiVarEntries;
+ tEplObdSize ObdSize;
+
+ atomic_set(&AtomicShutdown_g, TRUE);
+
+ // get node ID from insmod command line
+ EplApiInitParam.m_uiNodeId = uiNodeId_g;
+
+ if (EplApiInitParam.m_uiNodeId == EPL_C_ADR_INVALID) { // invalid node ID set
+ // set default node ID
+ EplApiInitParam.m_uiNodeId = NODEID;
+ }
+
+ uiNodeId_g = EplApiInitParam.m_uiNodeId;
+
+ // calculate IP address
+ EplApiInitParam.m_dwIpAddress =
+ (0xFFFFFF00 & IP_ADDR) | EplApiInitParam.m_uiNodeId;
+
+ EplApiInitParam.m_fAsyncOnly = FALSE;
+
+ EplApiInitParam.m_uiSizeOfStruct = sizeof(EplApiInitParam);
+ EPL_MEMCPY(EplApiInitParam.m_abMacAddress, abMacAddr,
+ sizeof(EplApiInitParam.m_abMacAddress));
+// EplApiInitParam.m_abMacAddress[5] = (BYTE) EplApiInitParam.m_uiNodeId;
+ EplApiInitParam.m_dwFeatureFlags = -1;
+ EplApiInitParam.m_dwCycleLen = uiCycleLen_g; // required for error detection
+ EplApiInitParam.m_uiIsochrTxMaxPayload = 100; // const
+ EplApiInitParam.m_uiIsochrRxMaxPayload = 100; // const
+ EplApiInitParam.m_dwPresMaxLatency = 50000; // const; only required for IdentRes
+ EplApiInitParam.m_uiPreqActPayloadLimit = 36; // required for initialisation (+28 bytes)
+ EplApiInitParam.m_uiPresActPayloadLimit = 36; // required for initialisation of Pres frame (+28 bytes)
+ EplApiInitParam.m_dwAsndMaxLatency = 150000; // const; only required for IdentRes
+ EplApiInitParam.m_uiMultiplCycleCnt = 0; // required for error detection
+ EplApiInitParam.m_uiAsyncMtu = 1500; // required to set up max frame size
+ EplApiInitParam.m_uiPrescaler = 2; // required for sync
+ EplApiInitParam.m_dwLossOfFrameTolerance = 500000;
+ EplApiInitParam.m_dwAsyncSlotTimeout = 3000000;
+ EplApiInitParam.m_dwWaitSocPreq = 150000;
+ EplApiInitParam.m_dwDeviceType = -1; // NMT_DeviceType_U32
+ EplApiInitParam.m_dwVendorId = -1; // NMT_IdentityObject_REC.VendorId_U32
+ EplApiInitParam.m_dwProductCode = -1; // NMT_IdentityObject_REC.ProductCode_U32
+ EplApiInitParam.m_dwRevisionNumber = -1; // NMT_IdentityObject_REC.RevisionNo_U32
+ EplApiInitParam.m_dwSerialNumber = -1; // NMT_IdentityObject_REC.SerialNo_U32
+ EplApiInitParam.m_dwSubnetMask = SUBNET_MASK;
+ EplApiInitParam.m_dwDefaultGateway = 0;
+ EPL_MEMCPY(EplApiInitParam.m_sHostname, sHostname,
+ sizeof(EplApiInitParam.m_sHostname));
+
+ // currently unset parameters left at default value 0
+ //EplApiInitParam.m_qwVendorSpecificExt1;
+ //EplApiInitParam.m_dwVerifyConfigurationDate; // CFM_VerifyConfiguration_REC.ConfDate_U32
+ //EplApiInitParam.m_dwVerifyConfigurationTime; // CFM_VerifyConfiguration_REC.ConfTime_U32
+ //EplApiInitParam.m_dwApplicationSwDate; // PDL_LocVerApplSw_REC.ApplSwDate_U32 on programmable device or date portion of NMT_ManufactSwVers_VS on non-programmable device
+ //EplApiInitParam.m_dwApplicationSwTime; // PDL_LocVerApplSw_REC.ApplSwTime_U32 on programmable device or time portion of NMT_ManufactSwVers_VS on non-programmable device
+ //EplApiInitParam.m_abVendorSpecificExt2[48];
+
+ // set callback functions
+ EplApiInitParam.m_pfnCbEvent = AppCbEvent;
+ EplApiInitParam.m_pfnCbSync = AppCbSync;
+
+ printk
+ ("\n\n Hello, I'm a simple POWERLINK node running as %s!\n (build: %s / %s)\n\n",
+ (uiNodeId_g ==
+ EPL_C_ADR_MN_DEF_NODE_ID ? "Managing Node" : "Controlled Node"),
+ __DATE__, __TIME__);
+
+ // initialize the Linux a wait queue for shutdown of this module
+ init_waitqueue_head(&WaitQueueShutdown_g);
+
+ // initialize the procfs device
+ EplRet = EplLinProcInit();
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+ // initialize POWERLINK stack
+ EplRet = EplApiInitialize(&EplApiInitParam);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+ // link process variables used by CN to object dictionary
+ ObdSize = sizeof(bVarIn1_l);
+ uiVarEntries = 1;
+ EplRet =
+ EplApiLinkObject(0x6000, &bVarIn1_l, &uiVarEntries, &ObdSize, 0x01);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bVarOut1_l);
+ uiVarEntries = 1;
+ EplRet =
+ EplApiLinkObject(0x6200, &bVarOut1_l, &uiVarEntries, &ObdSize,
+ 0x01);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+ // link process variables used by MN to object dictionary
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ ObdSize = sizeof(bLedsRow1_l);
+ uiVarEntries = 1;
+ EplRet =
+ EplApiLinkObject(0x2000, &bLedsRow1_l, &uiVarEntries, &ObdSize,
+ 0x01);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bLedsRow2_l);
+ uiVarEntries = 1;
+ EplRet =
+ EplApiLinkObject(0x2000, &bLedsRow2_l, &uiVarEntries, &ObdSize,
+ 0x02);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bSpeedSelect_l);
+ uiVarEntries = 1;
+ EplRet =
+ EplApiLinkObject(0x2000, &bSpeedSelect_l, &uiVarEntries, &ObdSize,
+ 0x03);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(bSpeedSelectOld_l);
+ uiVarEntries = 1;
+ EplRet =
+ EplApiLinkObject(0x2000, &bSpeedSelectOld_l, &uiVarEntries,
+ &ObdSize, 0x04);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+
+ ObdSize = sizeof(abSelect_l[0]);
+ uiVarEntries = sizeof(abSelect_l);
+ EplRet =
+ EplApiLinkObject(0x2200, &abSelect_l[0], &uiVarEntries, &ObdSize,
+ 0x01);
+ if (EplRet != kEplSuccessful) {
+ goto Exit;
+ }
+#endif
+
+ // link a DOMAIN to object 0x6100, but do not exit, if it is missing
+ ObdSize = sizeof(abDomain_l);
+ uiVarEntries = 1;
+ EplRet =
+ EplApiLinkObject(0x6100, &abDomain_l, &uiVarEntries, &ObdSize,
+ 0x00);
+ if (EplRet != kEplSuccessful) {
+ printk("EplApiLinkObject(0x6100): returns 0x%X\n", EplRet);
+ }
+ // reset old process variables
+ bVarOut1Old_l = 0;
+ bSpeedSelectOld_l = 0;
+ dwMode_l = APP_DEFAULT_MODE;
+ iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
+
+ // configure IP address of virtual network interface
+ // for TCP/IP communication over the POWERLINK network
+ sprintf(sBuffer, "%lu.%lu.%lu.%lu",
+ (EplApiInitParam.m_dwIpAddress >> 24),
+ ((EplApiInitParam.m_dwIpAddress >> 16) & 0xFF),
+ ((EplApiInitParam.m_dwIpAddress >> 8) & 0xFF),
+ (EplApiInitParam.m_dwIpAddress & 0xFF));
+ /* set up a minimal environment */
+ iRet = 0;
+ envp[iRet++] = "HOME=/";
+ envp[iRet++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+ envp[iRet] = NULL;
+
+ /* set up the argument list */
+ iRet = 0;
+ argv[iRet++] = "/sbin/ifconfig";
+ argv[iRet++] = IF_ETH;
+ argv[iRet++] = sBuffer;
+ argv[iRet] = NULL;
+
+ /* call ifconfig to configure the virtual network interface */
+ iRet = call_usermodehelper(argv[0], argv, envp, 1);
+ printk("ifconfig %s %s returned %d\n", argv[1], argv[2], iRet);
+
+ // start the NMT state machine
+ EplRet = EplApiExecNmtCommand(kEplNmtEventSwReset);
+ atomic_set(&AtomicShutdown_g, FALSE);
+
+ Exit:
+ printk("EplLinInit(): returns 0x%X\n", EplRet);
+ return EplRet;
+}
+
+static void __exit EplLinExit(void)
+{
+ tEplKernel EplRet;
+
+ // halt the NMT state machine
+ // so the processing of POWERLINK frames stops
+ EplRet = EplApiExecNmtCommand(kEplNmtEventSwitchOff);
+
+ // wait until NMT state machine is shut down
+ wait_event_interruptible(WaitQueueShutdown_g,
+ (atomic_read(&AtomicShutdown_g) == TRUE));
+/* if ((iErr != 0) || (atomic_read(&AtomicShutdown_g) == EVENT_STATE_IOCTL))
+ { // waiting was interrupted by signal or application called wrong function
+ EplRet = kEplShutdown;
+ }*/
+ // delete instance for all modules
+ EplRet = EplApiShutdown();
+ printk("EplApiShutdown(): 0x%X\n", EplRet);
+
+ // deinitialize proc fs
+ EplRet = EplLinProcFree();
+ printk("EplLinProcFree(): 0x%X\n", EplRet);
+
+}
+
+//=========================================================================//
+// //
+// P R I V A T E F U N C T I O N S //
+// //
+//=========================================================================//
+
+//---------------------------------------------------------------------------
+//
+// Function: AppCbEvent
+//
+// Description: event callback function called by EPL API layer within
+// user part (low priority).
+//
+// Parameters: EventType_p = event type
+// pEventArg_p = pointer to union, which describes
+// the event in detail
+// pUserArg_p = user specific argument
+//
+// Returns: tEplKernel = error code,
+// kEplSuccessful = no error
+// kEplReject = reject further processing
+// otherwise = post error event to API layer
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC AppCbEvent(tEplApiEventType EventType_p, // IN: event type (enum)
+ tEplApiEventArg * pEventArg_p, // IN: event argument (union)
+ void GENERIC * pUserArg_p)
+{
+ tEplKernel EplRet = kEplSuccessful;
+
+ // check if NMT_GS_OFF is reached
+ switch (EventType_p) {
+ case kEplApiEventNmtStateChange:
+ {
+ switch (pEventArg_p->m_NmtStateChange.m_NewNmtState) {
+ case kEplNmtGsOff:
+ { // NMT state machine was shut down,
+ // because of user signal (CTRL-C) or critical EPL stack error
+ // -> also shut down EplApiProcess() and main()
+ EplRet = kEplShutdown;
+
+ printk
+ ("AppCbEvent(kEplNmtGsOff) originating event = 0x%X\n",
+ pEventArg_p->m_NmtStateChange.
+ m_NmtEvent);
+
+ // wake up EplLinExit()
+ atomic_set(&AtomicShutdown_g, TRUE);
+ wake_up_interruptible
+ (&WaitQueueShutdown_g);
+ break;
+ }
+
+ case kEplNmtGsResetCommunication:
+ {
+ DWORD dwBuffer;
+
+ // configure OD for MN in state ResetComm after reseting the OD
+ // TODO: setup your own network configuration here
+ dwBuffer = (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS); // 0x00000003L
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x01,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x02,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x03,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x04,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x05,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x06,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x07,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x08,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x20,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0xFE,
+ &dwBuffer,
+ 4);
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0x6E,
+ &dwBuffer,
+ 4);
+
+// dwBuffer |= EPL_NODEASSIGN_MANDATORY_CN; // 0x0000000BL
+// EplRet = EplApiWriteLocalObject(0x1F81, 0x6E, &dwBuffer, 4);
+ dwBuffer = (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS); // 0x00010001L
+ EplRet =
+ EplApiWriteLocalObject(0x1F81, 0xF0,
+ &dwBuffer,
+ 4);
+
+ // continue
+ }
+
+ case kEplNmtGsResetConfiguration:
+ {
+ unsigned int uiSize;
+
+ // fetch object 0x1006 NMT_CycleLen_U32 from local OD (in little endian byte order)
+ // for configuration of remote CN
+ uiSize = 4;
+ EplRet =
+ EplApiReadObject(NULL, 0, 0x1006,
+ 0x00,
+ &dw_le_CycleLen_g,
+ &uiSize,
+ kEplSdoTypeAsnd,
+ NULL);
+ if (EplRet != kEplSuccessful) { // local OD access failed
+ break;
+ }
+ // continue
+ }
+
+ case kEplNmtMsPreOperational1:
+ {
+ printk
+ ("AppCbEvent(0x%X) originating event = 0x%X\n",
+ pEventArg_p->m_NmtStateChange.
+ m_NewNmtState,
+ pEventArg_p->m_NmtStateChange.
+ m_NmtEvent);
+
+ // continue
+ }
+
+ case kEplNmtGsInitialising:
+ case kEplNmtGsResetApplication:
+ case kEplNmtMsNotActive:
+ case kEplNmtCsNotActive:
+ case kEplNmtCsPreOperational1:
+ {
+ break;
+ }
+
+ case kEplNmtCsOperational:
+ case kEplNmtMsOperational:
+ {
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+/*
+ switch (pEventArg_p->m_NmtStateChange.m_NmtEvent)
+ {
+ case kEplNmtEventSwReset:
+ case kEplNmtEventResetNode:
+ case kEplNmtEventResetCom:
+ case kEplNmtEventResetConfig:
+ case kEplNmtEventInternComError:
+ case kEplNmtEventNmtCycleError:
+ {
+ printk("AppCbEvent(0x%X) originating event = 0x%X\n",
+ pEventArg_p->m_NmtStateChange.m_NewNmtState,
+ pEventArg_p->m_NmtStateChange.m_NmtEvent);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+*/
+ break;
+ }
+
+ case kEplApiEventCriticalError:
+ case kEplApiEventWarning:
+ { // error or warning occured within the stack or the application
+ // on error the API layer stops the NMT state machine
+
+ printk
+ ("AppCbEvent(Err/Warn): Source=%02X EplError=0x%03X",
+ pEventArg_p->m_InternalError.m_EventSource,
+ pEventArg_p->m_InternalError.m_EplError);
+ // check additional argument
+ switch (pEventArg_p->m_InternalError.m_EventSource) {
+ case kEplEventSourceEventk:
+ case kEplEventSourceEventu:
+ { // error occured within event processing
+ // either in kernel or in user part
+ printk(" OrgSource=%02X\n",
+ pEventArg_p->m_InternalError.
+ m_Arg.m_EventSource);
+ break;
+ }
+
+ case kEplEventSourceDllk:
+ { // error occured within the data link layer (e.g. interrupt processing)
+ // the DWORD argument contains the DLL state and the NMT event
+ printk(" val=%lX\n",
+ pEventArg_p->m_InternalError.
+ m_Arg.m_dwArg);
+ break;
+ }
+
+ default:
+ {
+ printk("\n");
+ break;
+ }
+ }
+ break;
+ }
+
+ case kEplApiEventNode:
+ {
+// printk("AppCbEvent(Node): Source=%02X EplError=0x%03X", pEventArg_p->m_InternalError.m_EventSource, pEventArg_p->m_InternalError.m_EplError);
+ // check additional argument
+ switch (pEventArg_p->m_Node.m_NodeEvent) {
+ case kEplNmtNodeEventCheckConf:
+ {
+ tEplSdoComConHdl SdoComConHdl;
+ // update object 0x1006 on CN
+ EplRet =
+ EplApiWriteObject(&SdoComConHdl,
+ pEventArg_p->
+ m_Node.m_uiNodeId,
+ 0x1006, 0x00,
+ &dw_le_CycleLen_g,
+ 4,
+ kEplSdoTypeAsnd,
+ NULL);
+ if (EplRet == kEplApiTaskDeferred) { // SDO transfer started
+ EplRet = kEplReject;
+ } else if (EplRet == kEplSuccessful) { // local OD access (should not occur)
+ printk
+ ("AppCbEvent(Node) write to local OD\n");
+ } else { // error occured
+ TGT_DBG_SIGNAL_TRACE_POINT(1);
+
+ EplRet =
+ EplApiFreeSdoChannel
+ (SdoComConHdl);
+ SdoComConHdl = 0;
+
+ EplRet =
+ EplApiWriteObject
+ (&SdoComConHdl,
+ pEventArg_p->m_Node.
+ m_uiNodeId, 0x1006, 0x00,
+ &dw_le_CycleLen_g, 4,
+ kEplSdoTypeAsnd, NULL);
+ if (EplRet == kEplApiTaskDeferred) { // SDO transfer started
+ EplRet = kEplReject;
+ } else {
+ printk
+ ("AppCbEvent(Node): EplApiWriteObject() returned 0x%02X\n",
+ EplRet);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ break;
+ }
+
+ case kEplApiEventSdo:
+ { // SDO transfer finished
+ EplRet =
+ EplApiFreeSdoChannel(pEventArg_p->m_Sdo.
+ m_SdoComConHdl);
+ if (EplRet != kEplSuccessful) {
+ break;
+ }
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ if (pEventArg_p->m_Sdo.m_SdoComConState == kEplSdoComTransferFinished) { // continue boot-up of CN with NMT command Reset Configuration
+ EplRet =
+ EplApiMnTriggerStateChange(pEventArg_p->
+ m_Sdo.m_uiNodeId,
+ kEplNmtNodeCommandConfReset);
+ } else { // indicate configuration error CN
+ EplRet =
+ EplApiMnTriggerStateChange(pEventArg_p->
+ m_Sdo.m_uiNodeId,
+ kEplNmtNodeCommandConfErr);
+ }
+#endif
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return EplRet;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: AppCbSync
+//
+// Description: sync event callback function called by event module within
+// kernel part (high priority).
+// This function sets the outputs, reads the inputs and runs
+// the control loop.
+//
+// Parameters: void
+//
+// Returns: tEplKernel = error code,
+// kEplSuccessful = no error
+// otherwise = post error event to API layer
+//
+// State:
+//
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC AppCbSync(void)
+{
+ tEplKernel EplRet = kEplSuccessful;
+
+ if (bVarOut1Old_l != bVarOut1_l) { // output variable has changed
+ bVarOut1Old_l = bVarOut1_l;
+ // set LEDs
+
+// printk("bVarIn = 0x%02X bVarOut = 0x%02X\n", (WORD) bVarIn_l, (WORD) bVarOut_l);
+ }
+ if (uiNodeId_g != EPL_C_ADR_MN_DEF_NODE_ID) {
+ bVarIn1_l++;
+ }
+
+ if (uiNodeId_g == EPL_C_ADR_MN_DEF_NODE_ID) { // we are the master and must run the control loop
+
+ // collect inputs from CNs and own input
+ bSpeedSelect_l = (bVarIn1_l | abSelect_l[0]) & 0x07;
+
+ bModeSelect_l = abSelect_l[1] | abSelect_l[2];
+
+ if ((bModeSelect_l & APP_MODE_MASK) != 0) {
+ dwMode_l = bModeSelect_l & APP_MODE_MASK;
+ }
+
+ iCurCycleCount_l--;
+
+ if (iCurCycleCount_l <= 0) {
+ if ((dwMode_l & 0x01) != 0) { // fill-up
+ if (iToggle) {
+ if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
+ 0x00) {
+ dwLeds_l = 0x01;
+ } else {
+ dwLeds_l <<= 1;
+ dwLeds_l++;
+ if (dwLeds_l >=
+ APP_DOUBLE_LED_MASK) {
+ iToggle = 0;
+ }
+ }
+ } else {
+ dwLeds_l <<= 1;
+ if ((dwLeds_l & APP_DOUBLE_LED_MASK) ==
+ 0x00) {
+ iToggle = 1;
+ }
+ }
+ bLedsRow1_l =
+ (unsigned char)(dwLeds_l & APP_LED_MASK);
+ bLedsRow2_l =
+ (unsigned char)((dwLeds_l >> APP_LED_COUNT)
+ & APP_LED_MASK);
+ }
+
+ else if ((dwMode_l & 0x02) != 0) { // running light forward
+ dwLeds_l <<= 1;
+ if ((dwLeds_l > APP_DOUBLE_LED_MASK)
+ || (dwLeds_l == 0x00000000L)) {
+ dwLeds_l = 0x01;
+ }
+ bLedsRow1_l =
+ (unsigned char)(dwLeds_l & APP_LED_MASK);
+ bLedsRow2_l =
+ (unsigned char)((dwLeds_l >> APP_LED_COUNT)
+ & APP_LED_MASK);
+ }
+
+ else if ((dwMode_l & 0x04) != 0) { // running light backward
+ dwLeds_l >>= 1;
+ if ((dwLeds_l > APP_DOUBLE_LED_MASK)
+ || (dwLeds_l == 0x00000000L)) {
+ dwLeds_l = 1 << (APP_LED_COUNT * 2);
+ }
+ bLedsRow1_l =
+ (unsigned char)(dwLeds_l & APP_LED_MASK);
+ bLedsRow2_l =
+ (unsigned char)((dwLeds_l >> APP_LED_COUNT)
+ & APP_LED_MASK);
+ }
+
+ else if ((dwMode_l & 0x08) != 0) { // Knightrider
+ if (bLedsRow1_l == 0x00) {
+ bLedsRow1_l = 0x01;
+ iToggle = 1;
+ } else if (iToggle) {
+ bLedsRow1_l <<= 1;
+ if (bLedsRow1_l >=
+ (1 << (APP_LED_COUNT - 1))) {
+ iToggle = 0;
+ }
+ } else {
+ bLedsRow1_l >>= 1;
+ if (bLedsRow1_l <= 0x01) {
+ iToggle = 1;
+ }
+ }
+ bLedsRow2_l = bLedsRow1_l;
+ }
+
+ else if ((dwMode_l & 0x10) != 0) { // Knightrider
+ if ((bLedsRow1_l == 0x00)
+ || (bLedsRow2_l == 0x00)
+ || ((bLedsRow2_l & ~APP_LED_MASK) != 0)) {
+ bLedsRow1_l = 0x01;
+ bLedsRow2_l =
+ (1 << (APP_LED_COUNT - 1));
+ iToggle = 1;
+ } else if (iToggle) {
+ bLedsRow1_l <<= 1;
+ bLedsRow2_l >>= 1;
+ if (bLedsRow1_l >=
+ (1 << (APP_LED_COUNT - 1))) {
+ iToggle = 0;
+ }
+ } else {
+ bLedsRow1_l >>= 1;
+ bLedsRow2_l <<= 1;
+ if (bLedsRow1_l <= 0x01) {
+ iToggle = 1;
+ }
+ }
+ }
+ // set own output
+ bVarOut1_l = bLedsRow1_l;
+// bVarOut1_l = (bLedsRow1_l & 0x03) | (bLedsRow2_l << 2);
+
+ // restart cycle counter
+ iCurCycleCount_l = iMaxCycleCount_l;
+ }
+
+ if (bSpeedSelectOld_l == 0) {
+ if ((bSpeedSelect_l & 0x01) != 0) {
+ if (iMaxCycleCount_l < 200) {
+ iMaxCycleCount_l++;
+ }
+ bSpeedSelectOld_l = bSpeedSelect_l;
+ } else if ((bSpeedSelect_l & 0x02) != 0) {
+ if (iMaxCycleCount_l > 1) {
+ iMaxCycleCount_l--;
+ }
+ bSpeedSelectOld_l = bSpeedSelect_l;
+ } else if ((bSpeedSelect_l & 0x04) != 0) {
+ iMaxCycleCount_l = DEFAULT_MAX_CYCLE_COUNT;
+ bSpeedSelectOld_l = bSpeedSelect_l;
+ }
+ } else if (bSpeedSelect_l == 0) {
+ bSpeedSelectOld_l = 0;
+ }
+ }
+
+ TGT_DBG_SIGNAL_TRACE_POINT(1);
+
+ return EplRet;
+}
+
+// EOF
diff --git a/drivers/staging/epl/edrv.h b/drivers/staging/epl/edrv.h
new file mode 100644
index 000000000000..a45984dfb092
--- /dev/null
+++ b/drivers/staging/epl/edrv.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: interface for ethernetdriver
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: edrv.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ Dev C++ and GNU-Compiler for m68k
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2005/08/01 m.b.: start of implementation
+
+****************************************************************************/
+
+#ifndef _EDRV_H_
+#define _EDRV_H_
+
+#include "EplInc.h"
+#include "EplFrame.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+// --------------------------------------------------------------------------
+#define MAX_ETH_DATA_SIZE 1500
+#define MIN_ETH_DATA_SIZE 46
+
+#define ETH_HDR_OFFSET 0 // Ethernet header at the top of the frame
+#define ETH_HDR_SIZE 14 // size of Ethernet header
+#define MIN_ETH_SIZE (MIN_ETH_DATA_SIZE + ETH_HDR_SIZE) // without CRC
+
+#define ETH_CRC_SIZE 4 // size of Ethernet CRC, i.e. FCS
+
+//---------------------------------------------------------------------------
+// types
+//---------------------------------------------------------------------------
+
+// position of a buffer in an ethernet-frame
+typedef enum {
+ kEdrvBufferFirstInFrame = 0x01, // first data buffer in an ethernet frame
+ kEdrvBufferMiddleInFrame = 0x02, // a middle data buffer in an ethernet frame
+ kEdrvBufferLastInFrame = 0x04 // last data buffer in an ethernet frame
+} tEdrvBufferInFrame;
+
+// format of a tx-buffer
+typedef struct _tEdrvTxBuffer {
+ tEplMsgType m_EplMsgType; // IN: type of EPL message, set by calling function
+ unsigned int m_uiTxMsgLen; // IN: length of message to be send (set for each transmit call)
+ // ----------------------
+ unsigned int m_uiBufferNumber; // OUT: number of the buffer, set by ethernetdriver
+ BYTE *m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver
+ tEplNetTime m_NetTime; // OUT: Timestamp of end of transmission, set by ethernetdriver
+ // ----------------------
+ unsigned int m_uiMaxBufferLen; // IN/OUT: maximum length of the buffer
+} tEdrvTxBuffer;
+
+// format of a rx-buffer
+typedef struct _tEdrvRxBuffer {
+ tEdrvBufferInFrame m_BufferInFrame; // OUT position of received buffer in an ethernet-frame
+ unsigned int m_uiRxMsgLen; // OUT: length of received buffer (without CRC)
+ BYTE *m_pbBuffer; // OUT: pointer to the buffer, set by ethernetdriver
+ tEplNetTime m_NetTime; // OUT: Timestamp of end of receiption
+
+} tEdrvRxBuffer;
+
+//typedef void (*tEdrvRxHandler) (BYTE bBufferInFrame_p, tBufferDescr * pbBuffer_p);
+//typedef void (*tEdrvRxHandler) (BYTE bBufferInFrame_p, BYTE * pbEthernetData_p, WORD wDataLen_p);
+typedef void (*tEdrvRxHandler) (tEdrvRxBuffer * pRxBuffer_p);
+typedef void (*tEdrvTxHandler) (tEdrvTxBuffer * pTxBuffer_p);
+
+// format of init structure
+typedef struct {
+ BYTE m_abMyMacAddr[6]; // the own MAC address
+
+// BYTE m_bNoOfRxBuffDescr; // number of entries in rx bufferdescriptor table
+// tBufferDescr * m_pRxBuffDescrTable; // rx bufferdescriptor table
+// WORD m_wRxBufferSize; // size of the whole rx buffer
+
+ tEdrvRxHandler m_pfnRxHandler;
+ tEdrvTxHandler m_pfnTxHandler;
+
+} tEdrvInitParam;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel EdrvInit(tEdrvInitParam * pEdrvInitParam_p);
+
+tEplKernel EdrvShutdown(void);
+
+tEplKernel EdrvDefineRxMacAddrEntry(BYTE * pbMacAddr_p);
+tEplKernel EdrvUndefineRxMacAddrEntry(BYTE * pbMacAddr_p);
+
+//tEplKernel EdrvDefineUnicastEntry (BYTE * pbUCEntry_p);
+//tEplKernel EdrvUndfineUnicastEntry (BYTE * pbUCEntry_p);
+
+tEplKernel EdrvAllocTxMsgBuffer(tEdrvTxBuffer * pBuffer_p);
+tEplKernel EdrvReleaseTxMsgBuffer(tEdrvTxBuffer * pBuffer_p);
+
+//tEplKernel EdrvWriteMsg (tBufferDescr * pbBuffer_p);
+tEplKernel EdrvSendTxMsg(tEdrvTxBuffer * pBuffer_p);
+tEplKernel EdrvTxMsgReady(tEdrvTxBuffer * pBuffer_p);
+tEplKernel EdrvTxMsgStart(tEdrvTxBuffer * pBuffer_p);
+
+//tEplKernel EdrvReadMsg (void);
+
+// interrupt handler called by target specific interrupt handler
+void EdrvInterruptHandler(void);
+
+#endif // #ifndef _EDRV_H_
diff --git a/drivers/staging/epl/global.h b/drivers/staging/epl/global.h
new file mode 100644
index 000000000000..fe167165a836
--- /dev/null
+++ b/drivers/staging/epl/global.h
@@ -0,0 +1,1391 @@
+/****************************************************************************
+
+ global project definition file
+
+ 12.06.1998 -rs
+ 11.02.2002 r.d. Erweiterungen, Ergaenzungen
+ 20.08.2002 SYS TEC electronic -as
+ Definition Schluesselwort 'GENERIC'
+ fuer das Erzeugen von Generic Pointer
+ 28.08.2002 r.d. erweiterter SYS TEC Debug Code
+ 16.09.2002 r.d. komplette Uebersetzung in Englisch
+ 11.04.2003 f.j. Ergaenzung fuer Mitsubishi NC30 Compiler
+ 17.06.2003 -rs Definition von Basistypen in <#ifndef _WINDEF_> gesetzt
+ 16.04.2004 r.d. Ergaenzung fuer Borland C++ Builder
+ 30.08.2004 -rs TRACE5 eingefgt
+ 23.12.2005 d.k. Definitions for IAR compiler
+
+ $Id: global.h,v 1.6 2008/11/07 13:55:56 D.Krueger Exp $
+
+****************************************************************************/
+
+#ifndef _GLOBAL_H_
+#define _GLOBAL_H_
+
+//---------------------------------------------------------------------------
+// elements of defines for development system
+//---------------------------------------------------------------------------
+
+// these defines are necessary to check some of characteristics of the development system
+#define _DEV_BIGEND_ 0x80000000L // big endian (motorolla format)
+#define _DEV_ALIGNMENT_4_ 0x00400000L // the CPU needs alignment of 4 bytes
+#define _DEV_ONLY_INT_MAIN_ 0x00004000L // the compiler needs "int main(int)" instead of "void main(void)"
+#define _DEV_COMMA_EXT_ 0x00002000L // support of last comma in struct predefinition
+#define _DEV_64BIT_SUPPORT_ 0x00001000L // support of 64 bit operations
+#define _DEV_BIT64_ 0x00000400L // count of bits: 64 bit
+#define _DEV_BIT32_ 0x00000300L // 32 bit
+#define _DEV_BIT16_ 0x00000200L // 16 bit
+#define _DEV_BIT8_ 0x00000100L // 8 bit
+#define _DEV_RVCT_ARM_ 0x0000001CL // RealView ARM
+#define _DEV_RENESASM32C 0x0000001BL // compiler from: Renesas
+#define _DEV_GNUC_MIPS2_ 0x0000001AL // GNU for MIPS2
+#define _DEV_MPLAB_C30_ 0x00000019L // MPLAB C30 for Microchip dsPIC33F series
+#define _DEV_GNUC_TC_ 0x00000018L // GNU for Infineon TriCore
+#define _DEV_GNUC_X86_ 0x00000017L // GNU for I386
+#define _DEV_IAR_ARM_ 0x00000016L // ARM IAR C/C++ Compiler
+#define _DEV_PARADGM_X86 0x00000015L // Paradigm C/C++ for Beck 1x3
+#define _DEV_GNUC_CF_ 0x00000014L // GNU for Coldfire
+#define _DEV_KEIL_ARM_ 0x00000013L // Keil ARM
+#define _DEV_MSEVC_ 0x00000012L // Microsoft embedded Visual C/C++
+#define _DEV_HIGHTEC_GNUC_X86_ 0x00000011L // Hightec elf386 gcc
+#define _DEV_MSVC_RTX_ 0x00000010L // VC600 + RTX
+#define _DEV_MSVC_V1_5_ 0x0000000FL // Microsoft Visual C/C++ V1.5
+#define _DEV_GNUC_ARM7_ 0x0000000EL // GNU Compiler gcc for ARM7
+#define _DEV_METROWERKS_CW_ 0x0000000DL // Metrowerks Code Warrior
+#define _DEV_MITSUBISHIM16C_ 0x0000000CL //compiler from: Mitsubishi
+#define _DEV_GNUC_C16X_ 0x0000000BL // GNU Compiler gcc166 for Infineon C16x
+#define _DEV_LINUX_GCC_ 0x0000000AL // Linux GNU Compiler gcc
+#define _DEV_GNUC_MPC5X5 0x00000009L // GNU for Motorola PPC5x5
+#define _DEV_TASKINGM16C_ 0x00000008L // Tasking for Mitsubishi M16C
+#define _DEV_FUJITSU_ 0x00000007L // Fujitsu
+#define _DEV_TASKING8_ 0x00000006L // Tasking 8051
+#define _DEV_TASKING16_ 0x00000005L // Tasking 166
+#define _DEV_KEIL8_ 0x00000004L // Keil C51
+#define _DEV_KEIL16_ 0x00000003L // Keil C166
+#define _DEV_BORLANDC_ 0x00000002L // Borland C/C++
+#define _DEV_MSVC16_ 0x00000001L // Microsoft Visual C/C++
+#define _DEV_MSVC32_ 0x00000000L // Microsoft Visual C/C++
+
+// these defines can be used to mask previous elements
+#define _DEV_MASK_COMPILER 0x000000FFL
+#define _DEV_MASK_BITCOUNT 0x00000F00L
+#define _DEV_MASK_ADDSUPPORT 0x0000F000L
+#define _DEV_MASK_ALIGNMENT 0x00F00000L
+
+//---------------------------------------------------------------------------
+// defines for development system (DEV_SYSTEM) including previous elements
+//---------------------------------------------------------------------------
+
+#define _DEV_WIN16_ (_DEV_BIT16_ | _DEV_MSVC16_ )
+#define _DEV_WIN32_ (_DEV_BIT32_ | _DEV_MSVC32_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_MSVC_DOS_ (_DEV_BIT32_ | _DEV_MSVC_V1_5_ )
+#define _DEV_BORLAND_DOS_ (_DEV_BIT32_ | _DEV_BORLANDC_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_KEIL_C51X_ (_DEV_BIT8_ | _DEV_KEIL8_ | _DEV_BIGEND_ | _DEV_COMMA_EXT_) // at least C51 version 7.05 supports comma extension
+#define _DEV_KEIL_C16X_ (_DEV_BIT16_ | _DEV_KEIL16_ | _DEV_COMMA_EXT_) // at least C166 version 5.03 supports comma extension
+#define _DEV_TASKING_C51X_ (_DEV_BIT8_ | _DEV_TASKING8_ | _DEV_BIGEND_)
+#define _DEV_TASKING_C16X_ (_DEV_BIT16_ | _DEV_TASKING16_ )
+#define _DEV_FUJITSU_F590_ (_DEV_BIT8_ | _DEV_FUJITSU_ | _DEV_COMMA_EXT_) // softune is not able to support 64 bit variables QWORD !!!
+//f.j.29.04.03 M16C kann effektiv mit Bytes umgehen
+//#define _DEV_TASKING_M16C_ (_DEV_BIT16_ | _DEV_TASKINGM16C_ )
+#define _DEV_TASKING_M16C_ (_DEV_BIT8_ | _DEV_TASKINGM16C_ )
+#define _DEV_MITSUBISHI_M16C_ (_DEV_BIT8_ | _DEV_MITSUBISHIM16C_ )
+#define _DEV_GNU_MPC5X5_ (_DEV_BIT32_ | _DEV_GNUC_MPC5X5| _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_LINUX_ (_DEV_BIT32_ | _DEV_LINUX_GCC_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_GNU_C16X_ (_DEV_BIT16_ | _DEV_GNUC_C16X_ ) //| _DEV_COMMA_EXT_)
+#define _DEV_MCW_MPC5X5_ (_DEV_BIT32_ | _DEV_METROWERKS_CW_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_GNU_ARM7_ (_DEV_BIT32_ | _DEV_GNUC_ARM7_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_)
+#define _DEV_WIN32_RTX_ (_DEV_BIT32_ | _DEV_MSVC_RTX_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_HIGHTEC_X86_ (_DEV_BIT32_ | _DEV_HIGHTEC_GNUC_X86_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_WIN_CE_ (_DEV_BIT32_ | _DEV_MSEVC_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_KEIL_CARM_ (_DEV_BIT32_ | _DEV_KEIL_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_IAR_CARM_ (_DEV_BIT32_ | _DEV_IAR_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_RVCT_CARM_ (_DEV_BIT32_ | _DEV_RVCT_ARM_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_)
+#define _DEV_MCW_MCF5XXX_ (_DEV_BIT32_ | _DEV_METROWERKS_CW_ ) //| _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_GNU_CF5282_ (_DEV_BIT32_ | _DEV_GNUC_CF_ | _DEV_BIGEND_)
+#define _DEV_PAR_BECK1X3_ (_DEV_BIT16_ | _DEV_PARADGM_X86)
+#define _DEV_GNU_CF548X_ (_DEV_BIT32_ | _DEV_GNUC_CF_ | _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_)
+#define _DEV_GNU_I386_ (_DEV_BIT32_ | _DEV_GNUC_X86_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_)
+#define _DEV_GNU_TRICORE_ (_DEV_BIT32_ | _DEV_GNUC_TC_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_ | _DEV_ALIGNMENT_4_)
+#define _DEV_MPLAB_DSPIC33F_ (_DEV_BIT16_ | _DEV_MPLAB_C30_ ) //| _DEV_COMMA_EXT_)
+#define _DEV_GNU_MIPSEL_ (_DEV_BIT32_ | _DEV_GNUC_MIPS2_ | _DEV_BIGEND_ | _DEV_64BIT_SUPPORT_ | _DEV_COMMA_EXT_ | _DEV_ONLY_INT_MAIN_)
+
+#define _DEV_RENESAS_M32C_ (_DEV_BIT32_ | _DEV_RENESASM32C)
+
+//---------------------------------------------------------------------------
+// usefull macros
+//---------------------------------------------------------------------------
+
+#define CHECK_IF_ONLY_INT_MAIN() (DEV_SYSTEM & _DEV_ONLY_INT_MAIN_)
+#define CHECK_MEMORY_ALINMENT() (DEV_SYSTEM & _DEV_MASK_ALIGNMENT)
+
+//---------------------------------------------------------------------------
+// defines for target system (TARGET_SYSTEM)
+//---------------------------------------------------------------------------
+
+#define _DOS_ (16 + 0x10000)
+#define _WIN16_ 16
+#define _WIN32_ 32
+#define _WINCE_ (32 + 0x20000)
+#define _NO_OS_ 0
+#define _LINUX_ 1
+#define _PXROS_ 2
+#define _ECOSPRO_ 3
+
+//---------------------------------------------------------------------------
+// definitions for function inlining
+//---------------------------------------------------------------------------
+
+#define INLINE_FUNCTION // empty define
+#undef INLINE_ENABLED // disable actual inlining of functions
+#undef INLINE_FUNCTION_DEF // disable inlining for all compilers per default
+
+//---------------------------------------------------------------------------
+// definitions for Keil C51
+//---------------------------------------------------------------------------
+
+#ifdef __C51__
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_KEIL_C51X_
+
+#pragma DEBUG OBJECTEXTEND
+#pragma WARNINGLEVEL(2) // maximum warning level
+
+#define NEAR idata // variables mapped to internal data storage location
+#define FAR xdata // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM code // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC xdata // hardware access through external memory (i.e. CAN)
+#define LARGE large // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM xdata // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT reentrant
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for GNU Compiler for Infineon C16x
+// - it have to be befor Keil (it has __C166__ too)
+//---------------------------------------------------------------------------
+#elif defined (__GNUC__) && defined (__C166__)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_GNU_C16X_
+
+// #define NEAR idata // variables mapped to internal data storage location
+#define NEAR near // variables mapped to internal data storage location
+// #define FAR xhuge // variables mapped to external data storage location
+#define FAR huge // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+// #define HWACC sdata // hardware access through external memory (i.e. CAN)
+#define HWACC huge // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+// #define GENERIC xhuge // generic pointer to point to application data
+#define GENERIC huge // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+
+#define ASSERT(p) \
+ if (p) \
+ { \
+ ; \
+ } \
+ else \
+ { \
+ PRINTF0("Assert failed: " #p " (file %s line %d)\n", __FILE__, (int) __LINE__ ); \
+ while (1); \
+ }
+#else
+#define ASSERT(p)
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Keil C166
+//---------------------------------------------------------------------------
+#elif defined (__C166__) // 24.01.2005 r.d.: Keil ARM7 needs directive 'defined'
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_KEIL_C16X_
+
+#pragma CODE
+#pragma MOD167
+#pragma NOINIT
+#pragma DEBUG
+#pragma WARNINGLEVEL(3) // maximum warning level
+#pragma WARNING DISABLE = 47 // warning <unreferenced parameter> = OFF
+#pragma WARNING DISABLE = 38 // warning <empty translation unit> = OFF
+// #pragma WARNING DISABLE = 102 // warning <different const/volatile qualifiers> = OFF
+#pragma WARNING DISABLE = 174 // warning <unreferenced 'static' function> = OFF
+#pragma WARNING DISABLE = 183 // warning <dead assignement eliminated> = OFF
+
+#define NEAR idata // variables mapped to internal data storage location
+#define FAR xhuge // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+// #define HWACC sdata // hardware access through external memory (i.e. CAN)
+#define HWACC huge // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC xhuge // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for MPLAB C30 for dsPIC33F series
+//---------------------------------------------------------------------------
+#elif defined (__C30__)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_MPLAB_DSPIC33F_
+
+#define NEAR // variables mapped to internal data storage location
+#define FAR // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+// #ifndef QWORD
+// #define QWORD long long
+// #endif
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Keil ARM
+//---------------------------------------------------------------------------
+#elif defined (__CA__)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_KEIL_CARM_
+
+#define NEAR // variables mapped to internal data storage location
+#define FAR // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef QWORD
+#define QWORD long long
+#endif
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for RealView ARM compilation tools (provided by recent Keil Microcontroller Development Kits)
+//---------------------------------------------------------------------------
+#elif defined (__ARMCC_VERSION)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_RVCT_CARM_
+
+#define NEAR // variables mapped to internal data storage location
+#define FAR // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef QWORD
+#define QWORD long long
+#endif
+
+#ifndef NDEBUG
+#define ASSERT(expr) if (!(expr)) {\
+ TRACE0 ("Assertion failed: " #expr );\
+ while (1);}
+#else
+#define ASSERT(expr)
+#endif
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for ARM IAR C Compiler
+//---------------------------------------------------------------------------
+#elif defined (__ICCARM__)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_IAR_CARM_
+
+#define NEAR // variables mapped to internal data storage location
+#define FAR // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef QWORD
+#define QWORD long long
+#endif
+
+ // Workaround:
+ // If we use IAR and want to debug but don't want to use C-Spy Debugger
+ // assert() doesn't work in debug mode because it needs support for FILE descriptors
+ // (_DLIB_FILE_DESCRIPTOR == 1).
+#ifndef NDEBUG
+#define ASSERT(expr) if (!(expr)) {\
+ TRACE0 ("Assertion failed: " #expr );\
+ while (1);}
+#else
+#define ASSERT(expr)
+#endif
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+// #define TRACE PRINTF4
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Tasking 8051
+//---------------------------------------------------------------------------
+
+#elif defined (_CC51)
+
+#include <cc51.h>
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_TASKING_C51X_
+
+#define NEAR _data // variables mapped to internal data storage location
+#define FAR _xdat // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC _xdat // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM _xdat // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT _reentrant
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Tasking C167CR and C164CI
+//---------------------------------------------------------------------------
+
+#elif defined (_C166)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_TASKING_C16X_
+
+#define NEAR near // variables mapped to internal data storage location
+#define FAR far // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC /* to be defined */ // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+ // Stdio.h has to be alway included here. If printf() is used stdio.h defines NULL
+ // without checking if it is already included. So an error occurs while compiling.
+ // (r.d.)
+#include <stdio.h> // prototype printf() (for TRACE)
+#ifndef NDEBUG
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for FUJITSU FFMC-16LX MB90590
+//---------------------------------------------------------------------------
+
+//#elif (defined (F590) || defined (F543) || defined (F598) || defined (F495) || defined (F350))
+#elif defined(__COMPILER_FCC907__)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_FUJITSU_F590_
+
+#define NEAR /* to be defined */ // variables mapped to internal data storage location
+#define FAR /* to be defined */ // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM /* to be defined */ // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC /* to be defined */ // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+ // softune is not able to support 64 bit variables QWORD !!!
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Mitsubishi M16C family for TASKING Compiler CM16
+//---------------------------------------------------------------------------
+
+#elif defined (_CM16C)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_TASKING_M16C_
+
+#define NEAR _near // variables mapped to internal data storage location
+#define FAR _far // variables mapped to external data storage location
+#define CONST _farrom // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC _near // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC _far // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+ // do you use memory model SMALL, than you have to set _far
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+ // Stdio.h has to be alway included here. If printf() is used stdio.h defines NULL
+ // without checking if it is already included. So an error occurs while compiling.
+ // (r.d.)
+#include <stdio.h> // prototype printf() (for TRACE)
+#ifndef NDEBUG
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Mitsubishi M16C family for Mitsubishi Compiler NC30
+//---------------------------------------------------------------------------
+// name NC30, andere Form will der Compiler nicht !!
+#elif defined (NC30)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_MITSUBISHI_M16C_
+
+#define NEAR near // variables mapped to internal data storage location
+#define FAR far // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC near // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC far // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Renesas M32C family for Renesas Compiler
+//---------------------------------------------------------------------------
+#elif defined (NC308)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_RENESAS_M32C_
+
+#define NEAR near // variables mapped to internal data storage location
+#define FAR far // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+#define HWACC // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM far // Memory attribute to optimize speed and code of pointer access.
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+// #error ("RENESAS o.k.")
+
+//---------------------------------------------------------------------------
+// definitions for ARM7 family with GNU compiler
+//---------------------------------------------------------------------------
+
+#elif defined(__GNUC__) && defined(__arm__) && !defined(__LINUX_ARM_ARCH__)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_GNU_ARM7_
+
+#define NEAR // variables mapped to internal data storage location
+#define FAR // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef QWORD
+#define QWORD long long // i.A. durch Herr Kuschel
+#endif
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for Motorola PowerPC family 5x5 (555/565)
+// definitions Linux-PC
+//---------------------------------------------------------------------------
+
+#elif defined (__GNUC__)
+
+#if defined (LINUX) || defined (linux) || defined (__linux__)
+#define LINUX_SYSTEM // define 'LINUX_SYSTEM' uniform for all Linux based systems
+ // r.d.: We will need an other solution here! There are two sections here which do check the preproc-definitions:
+ // LINUX and __linux__ . The first one was Linux for PC, the second one is this section for embedded Linux (MCF5xxx).
+ // But Linux for PC does not need the definitions for embedded Linux.
+#endif
+
+ // GNU C compiler supports function inlining
+#define INLINE_FUNCTION_DEF extern inline
+
+ // to actually enable inlining just include the following three lines
+ // #undef INLINE_FUNCTION
+ // #define INLINE_FUNCTION INLINE_FUNCTION_DEF
+ // #define INLINE_ENABLED TRUE
+
+#ifdef PXROS
+#define TARGET_SYSTEM _PXROS_
+#ifdef __i386__
+#undef LINUX // this define seems to be set from compiler
+#define DEV_SYSTEM _DEV_HIGHTEC_X86_
+#elif defined (__tricore__)
+#define DEV_SYSTEM _DEV_GNU_TRICORE_
+#else // MPC5x5
+#define DEV_SYSTEM _DEV_GNU_MPC5X5_
+#endif
+
+#elif defined (LINUX) || defined (__linux__)
+#define TARGET_SYSTEM _LINUX_ // Linux definition
+#define DEV_SYSTEM _DEV_LINUX_
+
+#elif defined (GNU_CF5282)
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_GNU_CF5282_
+
+#elif defined (ECOSPRO_I386_PEAK_PCI)
+#define TARGET_SYSTEM _ECOSPRO_
+#define DEV_SYSTEM _DEV_GNU_I386_
+
+#elif defined (GNU_CF548X)
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_GNU_CF548X_
+#else
+#error 'ERROR: DEV_SYSTEM not found!'
+#endif
+
+#ifndef QWORD
+#define QWORD long long int
+#endif
+
+#if (TARGET_SYSTEM == _PXROS_)
+
+#ifndef __KERNEL__
+#include <string.h>
+#endif
+
+#define NEAR // variables mapped to internal data storage location
+#define FAR // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM /* to be defined */ // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef QWORD
+#define QWORD long long int
+#endif
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+#endif
+
+ // ------------------ GNUC for I386 ---------------------------------------------
+
+#if (TARGET_SYSTEM == _LINUX_) || (TARGET_SYSTEM == _ECOSPRO_)
+
+#ifndef __KERNEL__
+#include <string.h>
+#endif
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#ifndef NEAR
+#define NEAR // variables mapped to internal data storage location
+#endif
+
+#ifndef FAR
+#define FAR // variables mapped to external data storage location
+#endif
+
+#ifndef CONST
+#define CONST const // variables mapped to ROM (i.e. flash)
+#endif
+
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#ifndef __KERNEL__
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#else
+#define TRACE printk
+#endif
+#endif
+#endif
+
+ // ------------------ GNU without OS ---------------------------------------------
+
+#if (TARGET_SYSTEM == _NO_OS_)
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#ifndef NEAR
+#define NEAR // variables mapped to internal data storage location
+#endif
+
+#ifndef FAR
+#define FAR // variables mapped to external data storage location
+#endif
+
+#ifndef CONST
+#define CONST const // variables mapped to ROM (i.e. flash)
+#endif
+
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+// #include "xuartdrv.h"
+// #include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+// #define TRACE mprintf
+// #ifndef TRACE
+// #define TRACE trace
+// void trace (char *fmt, ...);
+// #endif
+#endif
+
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for MPC565
+//---------------------------------------------------------------------------
+#elif __MWERKS__
+
+#ifdef __MC68K__
+
+#define TARGET_SYSTEM = _MCF548X_
+#define DEV_SYSTEM _DEV_MCW_MCF5XXX_
+
+#else
+#define TARGET_SYSTEM = _MPC565_
+#define DEV_SYSTEM _DEV_MCW_MPC5X5_
+#endif
+
+#define NEAR // variables mapped to internal data storage location
+#define FAR // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define LARGE // functions set parameters to external data storage location
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#include <stdio.h> // prototype printf() (for TRACE)
+#define TRACE printf
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for BECK 1x3
+//---------------------------------------------------------------------------
+#elif defined (__BORLANDC__) && defined (__PARADIGM__)
+
+#define TARGET_SYSTEM _NO_OS_
+#define DEV_SYSTEM _DEV_PAR_BECK1X3_
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+#define NEAR __near // variables mapped to internal data storage location
+#define FAR __far // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#ifndef TRACE
+#include <stdio.h>
+#define TRACE printf
+#endif
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for PC
+//---------------------------------------------------------------------------
+
+#elif defined (__BORLANDC__)
+
+ // ------------------ definition target system --------------------------
+
+#ifdef _WIN32
+#define TARGET_SYSTEM _WIN32_ // WIN32 definition
+#define DEV_SYSTEM _DEV_WIN32_
+#else
+#define TARGET_SYSTEM _DOS_
+#define DEV_SYSTEM _DEV_BORLAND_DOS_
+#endif
+
+ // ------------------ WIN32 ---------------------------------------------
+
+#if (TARGET_SYSTEM == _WIN32_)
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#ifndef NEAR
+#define NEAR // variables mapped to internal data storage location
+#endif
+
+#ifndef FAR
+#define FAR // variables mapped to external data storage location
+#endif
+
+#ifndef CONST
+#define CONST const // variables mapped to ROM (i.e. flash)
+#endif
+
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC __stdcall
+
+#ifndef NDEBUG
+#ifndef TRACE
+#include <stdio.h>
+#define TRACE printf
+#endif
+#endif
+
+#elif (TARGET_SYSTEM == _DOS_)
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+#define NEAR near // variables mapped to internal data storage location
+#define FAR far // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#ifndef TRACE
+#include <stdio.h>
+#define TRACE printf
+#endif
+#endif
+
+#endif
+
+#elif (_MSC_VER == 800) // PC MS Visual C/C++ for DOS applications
+
+#define TARGET_SYSTEM _DOS_
+#define DEV_SYSTEM _DEV_MSVC_DOS_
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC near // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+#define NEAR near // variables mapped to internal data storage location
+#define FAR far // variables mapped to external data storage location
+#define CONST const // variables mapped to ROM (i.e. flash)
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC
+
+#ifndef NDEBUG
+#ifndef TRACE
+#include <stdio.h>
+#define TRACE printf
+#endif
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for RTX under WIN32
+//---------------------------------------------------------------------------
+#elif (defined (UNDER_RTSS) && defined (WIN32))
+
+ // ------------------ definition target system --------------------------
+#define TARGET_SYSTEM _WIN32_RTX_
+#define DEV_SYSTEM _DEV_WIN32_RTX_
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#ifndef NEAR
+#define NEAR // variables mapped to internal data storage location
+#endif
+
+#ifndef FAR
+#define FAR // variables mapped to external data storage location
+#endif
+
+#ifndef CONST
+#define CONST const // variables mapped to ROM (i.e. flash)
+#endif
+
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC __stdcall
+
+#ifndef NDEBUG
+#ifndef TRACE
+#define TRACE RtPrintf
+#endif
+#endif
+
+//---------------------------------------------------------------------------
+// definitions for WinCE
+//---------------------------------------------------------------------------
+#elif defined (_WIN32_WCE)
+
+ // ------------------ definition target system --------------------------
+#define TARGET_SYSTEM _WINCE_
+#define DEV_SYSTEM _DEV_WIN_CE_
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#ifndef NEAR
+#define NEAR // variables mapped to internal data storage location
+#endif
+
+#ifndef FAR
+#define FAR // variables mapped to external data storage location
+#endif
+
+#ifndef CONST
+#define CONST const // variables mapped to ROM (i.e. flash)
+#endif
+
+#define LARGE
+
+#ifndef QWORD
+ //#define QWORD long long int // MSVC .NET can use "long long int" too (like GNU)
+#define QWORD __int64
+#endif
+
+#define REENTRANT
+#define PUBLIC __cdecl
+
+#ifdef ASSERTMSG
+#undef ASSERTMSG
+#endif
+
+#ifndef NDEBUG
+#ifndef TRACE
+#define TRACE printf
+// void trace (char *fmt, ...);
+#endif
+#endif
+
+#else // ===> PC MS Visual C/C++
+
+ // ------------------ definition target system --------------------------
+
+#ifdef _WIN32
+#define TARGET_SYSTEM _WIN32_ // WIN32 definition
+#define DEV_SYSTEM _DEV_WIN32_
+#else
+#define TARGET_SYSTEM _WIN16_ // WIN16 definition
+#define DEV_SYSTEM _DEV_WIN16_
+#endif
+
+ // ------------------ WIN16 ---------------------------------------------
+
+#if (TARGET_SYSTEM == _WIN16_)
+
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+
+ // These types can be adjusted by users to match application requirements. The goal is to
+ // minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external
+ // or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+
+#ifndef NEAR
+#define NEAR // variables mapped to internal data storage location
+#endif
+
+#ifndef FAR
+#define FAR far // variables mapped to external data storage location
+#endif
+
+#ifndef CONST
+#define CONST const // variables mapped to ROM (i.e. flash)
+#endif
+
+#define LARGE
+
+#define REENTRANT
+#define PUBLIC _far _pascal _export
+
+#ifndef NDEBUG
+#ifndef TRACE
+#define TRACE trace
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void trace(const char *fmt, ...);
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+#endif
+ // ------------------ WIN32 ---------------------------------------------
+#if (TARGET_SYSTEM == _WIN32_)
+#define ROM // code or variables mapped to ROM (i.e. flash)
+ // usage: CONST BYTE ROM foo = 0x00;
+#define HWACC // hardware access through external memory (i.e. CAN)
+ // These types can be adjusted by users to match application requirements. The goal is to// minimize code memory and maximize speed.
+#define GENERIC // generic pointer to point to application data
+ // Variables with this attribute can be located in external// or internal data memory.
+#define MEM // Memory attribute to optimize speed and code of pointer access.
+#ifndef NEAR
+#define NEAR // variables mapped to internal data storage location
+#endif
+#ifndef FAR
+#define FAR // variables mapped to external data storage location
+#endif
+#ifndef CONST
+#define CONST const // variables mapped to ROM (i.e. flash)
+#endif
+#define LARGE
+#define REENTRANT
+#define PUBLIC __stdcall
+#ifndef QWORD
+ //#define QWORD long long int // MSVC .NET can use "long long int" too (like GNU)
+#define QWORD __int64
+#endif
+#ifndef NDEBUG
+#ifndef TRACE
+#define TRACE trace
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void trace(const char *fmt, ...);
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+ // MS Visual C++ compiler supports function inlining
+#define INLINE_FUNCTION_DEF __forceinline
+ // to actually enable inlining just include the following two lines// #define INLINE_FUNCTION INLINE_FUNCTION_DEF// #define INLINE_ENABLED TRUE
+#endif
+#endif // ===> PC
+//---------------------------------------------------------------------------// definitions of basic types//---------------------------------------------------------------------------
+#ifndef _WINDEF_ // defined in WINDEF.H, included by <windows.h>
+ // --- arithmetic types ---
+#ifndef SHORT
+#define SHORT short int
+#endif
+#ifndef USHORT
+#define USHORT unsigned short int
+#endif
+#ifndef INT
+#define INT int
+#endif
+#ifndef UINT
+#define UINT unsigned int
+#endif
+#ifndef LONG
+#define LONG long int
+#endif
+#ifndef ULONG
+#define ULONG unsigned long int
+#endif
+ // --- logic types ---
+#ifndef BYTE
+#define BYTE unsigned char
+#endif
+#ifndef WORD
+#define WORD unsigned short int
+#endif
+#ifndef DWORD
+#define DWORD unsigned long int
+#endif
+#ifndef BOOL
+#define BOOL unsigned char
+#endif
+ // --- alias types ---
+#ifndef TRUE
+#define TRUE 0xFF
+#endif
+#ifndef FALSE
+#define FALSE 0x00
+#endif
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+#endif
+#ifndef _TIME_OF_DAY_DEFINED_
+typedef struct {
+ unsigned long int m_dwMs;
+ unsigned short int m_wDays;
+
+} tTimeOfDay;
+
+#define _TIME_OF_DAY_DEFINED_
+
+#endif
+
+//---------------------------------------------------------------------------
+// Definition von TRACE
+//---------------------------------------------------------------------------
+
+#ifndef NDEBUG
+
+#ifndef TRACE0
+#define TRACE0(p0) TRACE(p0)
+#endif
+
+#ifndef TRACE1
+#define TRACE1(p0, p1) TRACE(p0, p1)
+#endif
+
+#ifndef TRACE2
+#define TRACE2(p0, p1, p2) TRACE(p0, p1, p2)
+#endif
+
+#ifndef TRACE3
+#define TRACE3(p0, p1, p2, p3) TRACE(p0, p1, p2, p3)
+#endif
+
+#ifndef TRACE4
+#define TRACE4(p0, p1, p2, p3, p4) TRACE(p0, p1, p2, p3, p4)
+#endif
+
+#ifndef TRACE5
+#define TRACE5(p0, p1, p2, p3, p4, p5) TRACE(p0, p1, p2, p3, p4, p5)
+#endif
+
+#ifndef TRACE6
+#define TRACE6(p0, p1, p2, p3, p4, p5, p6) TRACE(p0, p1, p2, p3, p4, p5, p6)
+#endif
+
+#else
+
+#ifndef TRACE0
+#define TRACE0(p0)
+#endif
+
+#ifndef TRACE1
+#define TRACE1(p0, p1)
+#endif
+
+#ifndef TRACE2
+#define TRACE2(p0, p1, p2)
+#endif
+
+#ifndef TRACE3
+#define TRACE3(p0, p1, p2, p3)
+#endif
+
+#ifndef TRACE4
+#define TRACE4(p0, p1, p2, p3, p4)
+#endif
+
+#ifndef TRACE5
+#define TRACE5(p0, p1, p2, p3, p4, p5)
+#endif
+
+#ifndef TRACE6
+#define TRACE6(p0, p1, p2, p3, p4, p5, p6)
+#endif
+
+#endif
+
+//---------------------------------------------------------------------------
+// definition of ASSERT
+//---------------------------------------------------------------------------
+
+#ifndef ASSERT
+#if !defined (__linux__) && !defined (__KERNEL__)
+#include <assert.h>
+#ifndef ASSERT
+#define ASSERT(p) assert(p)
+#endif
+#else
+#define ASSERT(p)
+#endif
+#endif
+
+//---------------------------------------------------------------------------
+// SYS TEC extensions
+//---------------------------------------------------------------------------
+
+// This macro doesn't print out C-file and line number of the failed assertion
+// but a string, which exactly names the mistake.
+#ifndef NDEBUG
+
+#define ASSERTMSG(expr,string) if (!(expr)) {\
+ PRINTF0 ("Assertion failed: " string );\
+ while (1);}
+#else
+#define ASSERTMSG(expr,string)
+#endif
+
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _GLOBAL_H_
+
+// Please keep an empty line at the end of this file.
diff --git a/drivers/staging/epl/kernel/EplDllk.h b/drivers/staging/epl/kernel/EplDllk.h
new file mode 100644
index 000000000000..588e871a922b
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplDllk.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for kernelspace DLL module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDllk.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/08 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_DLLK_H_
+#define _EPL_DLLK_H_
+
+#include "../EplDll.h"
+#include "../EplEvent.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef tEplKernel(*tEplDllkCbAsync) (tEplFrameInfo * pFrameInfo_p);
+
+typedef struct {
+ BYTE m_be_abSrcMac[6];
+
+} tEplDllkInitParam;
+
+// forward declaration
+struct _tEdrvTxBuffer;
+
+struct _tEplDllkNodeInfo {
+ struct _tEplDllkNodeInfo *m_pNextNodeInfo;
+ struct _tEdrvTxBuffer *m_pPreqTxBuffer;
+ unsigned int m_uiNodeId;
+ DWORD m_dwPresTimeout;
+ unsigned long m_ulDllErrorEvents;
+ tEplNmtState m_NmtState;
+ WORD m_wPresPayloadLimit;
+ BYTE m_be_abMacAddr[6];
+ BYTE m_bSoaFlag1;
+ BOOL m_fSoftDelete; // delete node after error and ignore error
+
+};
+
+typedef struct _tEplDllkNodeInfo tEplDllkNodeInfo;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+tEplKernel EplDllkAddInstance(tEplDllkInitParam * pInitParam_p);
+
+tEplKernel EplDllkDelInstance(void);
+
+// called before NMT_GS_COMMUNICATING will be entered to configure fixed parameters
+tEplKernel EplDllkConfig(tEplDllConfigParam * pDllConfigParam_p);
+
+// set identity of local node (may be at any time, e.g. in case of hostname change)
+tEplKernel EplDllkSetIdentity(tEplDllIdentParam * pDllIdentParam_p);
+
+// process internal events and do work that cannot be done in interrupt-context
+tEplKernel EplDllkProcess(tEplEvent * pEvent_p);
+
+// registers handler for non-EPL frames
+tEplKernel EplDllkRegAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p);
+
+// deregisters handler for non-EPL frames
+tEplKernel EplDllkDeregAsyncHandler(tEplDllkCbAsync pfnDllkCbAsync_p);
+
+// register C_DLL_MULTICAST_ASND in ethernet driver if any AsndServiceId is registered
+tEplKernel EplDllkSetAsndServiceIdFilter(tEplDllAsndServiceId ServiceId_p,
+ tEplDllAsndFilter Filter_p);
+
+// creates the buffer for a Tx frame and registers it to the ethernet driver
+tEplKernel EplDllkCreateTxFrame(unsigned int *puiHandle_p,
+ tEplFrame ** ppFrame_p,
+ unsigned int *puiFrameSize_p,
+ tEplMsgType MsgType_p,
+ tEplDllAsndServiceId ServiceId_p);
+
+tEplKernel EplDllkDeleteTxFrame(unsigned int uiHandle_p);
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+tEplKernel EplDllkAddNode(tEplDllNodeInfo * pNodeInfo_p);
+
+tEplKernel EplDllkDeleteNode(unsigned int uiNodeId_p);
+
+tEplKernel EplDllkSoftDeleteNode(unsigned int uiNodeId_p);
+
+tEplKernel EplDllkSetFlag1OfNode(unsigned int uiNodeId_p, BYTE bSoaFlag1_p);
+
+tEplKernel EplDllkGetFirstNodeInfo(tEplDllkNodeInfo ** ppNodeInfo_p);
+
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+#endif // #ifndef _EPL_DLLK_H_
diff --git a/drivers/staging/epl/kernel/EplDllkCal.h b/drivers/staging/epl/kernel/EplDllkCal.h
new file mode 100644
index 000000000000..6c4dc7e4a80d
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplDllkCal.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for kernelspace DLL Communication Abstraction Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDllkCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/11/13 17:13:09 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/13 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_DLLKCAL_H_
+#define _EPL_DLLKCAL_H_
+
+#include "../EplDll.h"
+#include "../EplEvent.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef struct {
+ unsigned long m_ulCurTxFrameCountGen;
+ unsigned long m_ulCurTxFrameCountNmt;
+ unsigned long m_ulCurRxFrameCount;
+ unsigned long m_ulMaxTxFrameCountGen;
+ unsigned long m_ulMaxTxFrameCountNmt;
+ unsigned long m_ulMaxRxFrameCount;
+
+} tEplDllkCalStatistics;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+tEplKernel EplDllkCalAddInstance(void);
+
+tEplKernel EplDllkCalDelInstance(void);
+
+tEplKernel EplDllkCalAsyncGetTxCount(tEplDllAsyncReqPriority * pPriority_p,
+ unsigned int *puiCount_p);
+tEplKernel EplDllkCalAsyncGetTxFrame(void *pFrame_p,
+ unsigned int *puiFrameSize_p,
+ tEplDllAsyncReqPriority Priority_p);
+// only frames with registered AsndServiceIds are passed to CAL
+tEplKernel EplDllkCalAsyncFrameReceived(tEplFrameInfo * pFrameInfo_p);
+
+tEplKernel EplDllkCalAsyncSend(tEplFrameInfo * pFrameInfo_p,
+ tEplDllAsyncReqPriority Priority_p);
+
+tEplKernel EplDllkCalAsyncClearBuffer(void);
+
+tEplKernel EplDllkCalGetStatistics(tEplDllkCalStatistics ** ppStatistics);
+
+tEplKernel EplDllkCalProcess(tEplEvent * pEvent_p);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+tEplKernel EplDllkCalAsyncClearQueues(void);
+
+tEplKernel EplDllkCalIssueRequest(tEplDllReqServiceId Service_p,
+ unsigned int uiNodeId_p, BYTE bSoaFlag1_p);
+
+tEplKernel EplDllkCalAsyncGetSoaRequest(tEplDllReqServiceId * pReqServiceId_p,
+ unsigned int *puiNodeId_p);
+
+tEplKernel EplDllkCalAsyncSetPendingRequests(unsigned int uiNodeId_p,
+ tEplDllAsyncReqPriority
+ AsyncReqPrio_p,
+ unsigned int uiCount_p);
+
+#endif //(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0)
+
+#endif // #ifndef _EPL_DLLKCAL_H_
diff --git a/drivers/staging/epl/kernel/EplErrorHandlerk.h b/drivers/staging/epl/kernel/EplErrorHandlerk.h
new file mode 100644
index 000000000000..4a67ef88b97a
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplErrorHandlerk.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for kernel error handler module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplErrorHandlerk.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/10/02 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_ERRORHANDLERK_H_
+#define _EPL_ERRORHANDLERK_H_
+
+#include "../EplEvent.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+// init function
+tEplKernel PUBLIC EplErrorHandlerkInit(void);
+
+// add instance
+tEplKernel PUBLIC EplErrorHandlerkAddInstance(void);
+
+// delete instance
+tEplKernel PUBLIC EplErrorHandlerkDelInstance(void);
+
+// processes error events
+tEplKernel PUBLIC EplErrorHandlerkProcess(tEplEvent * pEvent_p);
+
+#endif // #ifndef _EPL_ERRORHANDLERK_H_
diff --git a/drivers/staging/epl/kernel/EplEventk.h b/drivers/staging/epl/kernel/EplEventk.h
new file mode 100644
index 000000000000..1d25aaa2ed49
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplEventk.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for kernel event module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplEventk.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/12 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_EVENTK_H_
+#define _EPL_EVENTK_H_
+
+#include "../EplEvent.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+// init function
+tEplKernel PUBLIC EplEventkInit(tEplSyncCb fpSyncCb);
+
+// add instance
+tEplKernel PUBLIC EplEventkAddInstance(tEplSyncCb fpSyncCb);
+
+// delete instance
+tEplKernel PUBLIC EplEventkDelInstance(void);
+
+// Kernelthread that dispatches events in kernelspace
+tEplKernel PUBLIC EplEventkProcess(tEplEvent * pEvent_p);
+
+// post events from kernelspace
+tEplKernel PUBLIC EplEventkPost(tEplEvent * pEvent_p);
+
+// post errorevents from kernelspace
+tEplKernel PUBLIC EplEventkPostError(tEplEventSource EventSource_p,
+ tEplKernel EplError_p,
+ unsigned int uiArgSize_p, void *pArg_p);
+
+#endif // #ifndef _EPL_EVENTK_H_
diff --git a/drivers/staging/epl/kernel/EplNmtk.h b/drivers/staging/epl/kernel/EplNmtk.h
new file mode 100644
index 000000000000..53409cc89921
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplNmtk.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for NMT-Kernelspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtk.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#ifndef _EPLNMTK_H_
+#define _EPLNMTK_H_
+
+#include "../EplNmt.h"
+#include "EplEventk.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR);
+
+EPLDLLEXPORT tEplKernel PUBLIC
+EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR);
+
+EPLDLLEXPORT tEplKernel PUBLIC
+EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_
+ tEplEvent * pEvent_p);
+
+EPLDLLEXPORT tEplNmtState PUBLIC
+EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR);
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0)
+
+#endif // #ifndef _EPLNMTK_H_
diff --git a/drivers/staging/epl/kernel/EplNmtkCal.h b/drivers/staging/epl/kernel/EplNmtkCal.h
new file mode 100644
index 000000000000..9edeafca4920
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplNmtkCal.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for communication abstraction layer of the
+ NMT-Kernel-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtkCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/16 -k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplNmtk.h"
+
+#ifndef _EPLNMTKCAL_H_
+#define _EPLNMTKCAL_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPLNMTKCAL_H_
diff --git a/drivers/staging/epl/kernel/EplObdk.h b/drivers/staging/epl/kernel/EplObdk.h
new file mode 100644
index 000000000000..cf9f5837dd38
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplObdk.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for Epl-Obd-Kernel-Modul
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObdk.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/19 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplObd.h"
+
+#ifndef _EPLOBDK_H_
+#define _EPLOBDK_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// global variables
+//---------------------------------------------------------------------------
+
+extern BYTE MEM abEplObdTrashObject_g[8];
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdInit(EPL_MCO_DECL_PTR_INSTANCE_PTR_
+ tEplObdInitParam MEM * pInitParam_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR_
+ tEplObdInitParam MEM *
+ pInitParam_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdDeleteInstance(EPL_MCO_DECL_INSTANCE_PTR);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC
+EplObdSetStoreLoadObjCallback(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdStoreLoadObjCallback fpCallback_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdAccessOdPart(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdPart ObdPart_p,
+ tEplObdDir Direction_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdDefineVar(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplVarParam MEM * pVarParam_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT void *PUBLIC EplObdGetObjectDataPtr(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p);
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdRegisterUserOd(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdEntryPtr pUserOd_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT void PUBLIC EplObdInitVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ tEplObdVarEntry MEM * pVarEntry_p,
+ tEplObdType Type_p,
+ tEplObdSize ObdSize_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplObdSize PUBLIC EplObdGetDataSize(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT unsigned int PUBLIC EplObdGetNodeId(EPL_MCO_DECL_INSTANCE_PTR);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdSetNodeId(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiNodeId_p,
+ tEplObdNodeIdType NodeIdType_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdIsNumerical(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ BOOL * pfEntryNumerical);
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdWriteEntryFromLe(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdReadEntryToLe(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdGetAccessType(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ tEplObdAccess *
+ pAccessTyp_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObdSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdVarEntry MEM **
+ ppVarEntry_p);
+
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) != 0)
+
+#endif // #ifndef _EPLOBDK_H_
diff --git a/drivers/staging/epl/kernel/EplObdkCal.h b/drivers/staging/epl/kernel/EplObdkCal.h
new file mode 100644
index 000000000000..c173a950054f
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplObdkCal.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for communication abstraction layer
+ for the Epl-Obd-Kernelspace-Modul
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObdkCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/19 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplObd.h"
+
+#ifndef _EPLOBDKCAL_H_
+#define _EPLOBDKCAL_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#endif // #ifndef _EPLOBDKCAL_H_
diff --git a/drivers/staging/epl/kernel/EplPdok.h b/drivers/staging/epl/kernel/EplPdok.h
new file mode 100644
index 000000000000..b5b18f4cf687
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplPdok.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for kernel PDO module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplPdok.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/06/23 14:56:33 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_PDOK_H_
+#define _EPL_PDOK_H_
+
+#include "../EplPdo.h"
+#include "../EplEvent.h"
+#include "../EplDll.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+// process events from queue (PDOs/frames and SoA for synchronization)
+tEplKernel EplPdokProcess(tEplEvent * pEvent_p);
+
+// copies RPDO to event queue for processing
+// is called by DLL in NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL
+// PDO needs not to be valid
+tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p);
+
+// posts pointer and size of TPDO to event queue
+// is called by DLL in NMT_CS_PRE_OPERATIONAL_2,
+// NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL
+tEplKernel EplPdokCbPdoTransmitted(tEplFrameInfo * pFrameInfo_p);
+
+// posts SoA event to queue
+tEplKernel EplPdokCbSoa(tEplFrameInfo * pFrameInfo_p);
+
+tEplKernel EplPdokAddInstance(void);
+
+tEplKernel EplPdokDelInstance(void);
+
+#endif // #ifndef _EPL_PDOK_H_
diff --git a/drivers/staging/epl/kernel/EplPdokCal.h b/drivers/staging/epl/kernel/EplPdokCal.h
new file mode 100644
index 000000000000..6a183ebe81ef
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplPdokCal.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for kernel PDO Communication Abstraction Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplPdokCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_PDOKCAL_H_
+#define _EPL_PDOKCAL_H_
+
+#include "../EplInc.h"
+//#include "EplPdo.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdokCalAddInstance(void);
+
+tEplKernel EplPdokCalDelInstance(void);
+
+// sets flag for validity of TPDOs in shared memory
+tEplKernel EplPdokCalSetTpdosValid(BOOL fValid_p);
+
+// gets flag for validity of TPDOs from shared memory
+tEplKernel EplPdokCalAreTpdosValid(BOOL * pfValid_p);
+
+#endif // #ifndef _EPL_PDOKCAL_H_
diff --git a/drivers/staging/epl/kernel/EplTimerHighResk.h b/drivers/staging/epl/kernel/EplTimerHighResk.h
new file mode 100644
index 000000000000..d5d046d4d370
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplTimerHighResk.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for EPL high resolution Timermodule
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTimerHighResk.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/09/29 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplTimer.h"
+
+#ifndef _EPLTIMERHIGHRESK_H_
+#define _EPLTIMERHIGHRESK_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimerHighReskInit(void);
+
+tEplKernel PUBLIC EplTimerHighReskAddInstance(void);
+
+tEplKernel PUBLIC EplTimerHighReskDelInstance(void);
+
+tEplKernel PUBLIC EplTimerHighReskSetTimerNs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long long ullTimeNs_p,
+ tEplTimerkCallback pfnCallback_p,
+ unsigned long ulArgument_p,
+ BOOL fContinuously_p);
+
+tEplKernel PUBLIC EplTimerHighReskModifyTimerNs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long long ullTimeNs_p,
+ tEplTimerkCallback
+ pfnCallback_p,
+ unsigned long ulArgument_p,
+ BOOL fContinuously_p);
+
+tEplKernel PUBLIC EplTimerHighReskDeleteTimer(tEplTimerHdl * pTimerHdl_p);
+
+#endif // #ifndef _EPLTIMERHIGHRESK_H_
diff --git a/drivers/staging/epl/kernel/EplTimerk.h b/drivers/staging/epl/kernel/EplTimerk.h
new file mode 100644
index 000000000000..9160e7260de8
--- /dev/null
+++ b/drivers/staging/epl/kernel/EplTimerk.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for EPL Kernel-Timermodule
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTimerk.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/06 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplTimer.h"
+#include "../user/EplEventu.h"
+
+#ifndef _EPLTIMERK_H_
+#define _EPLTIMERK_H_
+
+#if EPL_TIMER_USE_USER != FALSE
+#include "../user/EplTimeru.h"
+#endif
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#if EPL_TIMER_USE_USER != FALSE
+#define EplTimerkInit EplTimeruInit
+#define EplTimerkAddInstance EplTimeruAddInstance
+#define EplTimerkDelInstance EplTimeruDelInstance
+#define EplTimerkSetTimerMs EplTimeruSetTimerMs
+#define EplTimerkModifyTimerMs EplTimeruModifyTimerMs
+#define EplTimerkDeleteTimer EplTimeruDeleteTimer
+#endif
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+#if EPL_TIMER_USE_USER == FALSE
+tEplKernel PUBLIC EplTimerkInit(void);
+
+tEplKernel PUBLIC EplTimerkAddInstance(void);
+
+tEplKernel PUBLIC EplTimerkDelInstance(void);
+
+tEplKernel PUBLIC EplTimerkSetTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p);
+
+tEplKernel PUBLIC EplTimerkModifyTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p);
+
+tEplKernel PUBLIC EplTimerkDeleteTimer(tEplTimerHdl * pTimerHdl_p);
+#endif
+#endif // #ifndef _EPLTIMERK_H_
diff --git a/drivers/staging/epl/kernel/VirtualEthernet.h b/drivers/staging/epl/kernel/VirtualEthernet.h
new file mode 100644
index 000000000000..deff8720e37f
--- /dev/null
+++ b/drivers/staging/epl/kernel/VirtualEthernet.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for virtual ethernet driver module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: VirtualEthernet.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ KEIL uVision 2
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/09/19 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_VETH_H_
+#define _EPL_VETH_H_
+
+#include "EplDllk.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
+
+tEplKernel PUBLIC VEthAddInstance(tEplDllkInitParam * pInitParam_p);
+
+tEplKernel PUBLIC VEthDelInstance(void);
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_VETH)) != 0)
+
+#endif // #ifndef _EPL_VETH_H_
diff --git a/drivers/staging/epl/proc_fs.c b/drivers/staging/epl/proc_fs.c
new file mode 100644
index 000000000000..f4910332d3c6
--- /dev/null
+++ b/drivers/staging/epl/proc_fs.c
@@ -0,0 +1,409 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: proc fs entry with diagnostic information under Linux
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: proc_fs.c,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.13 $ $Date: 2008/11/07 13:55:56 $
+
+ $State: Exp $
+
+ Build Environment:
+ GNU
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/31 d.k.: start of implementation
+
+****************************************************************************/
+
+#include "kernel/EplNmtk.h"
+#include "user/EplNmtu.h"
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+#include "user/EplNmtMnu.h"
+#endif
+
+#include "kernel/EplDllkCal.h"
+
+//#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/version.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_COLDFIRE
+#include <asm/coldfire.h>
+#include "fec.h"
+#endif
+
+/***************************************************************************/
+/* */
+/* */
+/* G L O B A L D E F I N I T I O N S */
+/* */
+/* */
+/***************************************************************************/
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+#ifndef EPL_PROC_DEV_NAME
+#define EPL_PROC_DEV_NAME "epl"
+#endif
+
+#ifndef DBG_TRACE_POINTS
+#define DBG_TRACE_POINTS 23 // # of supported debug trace points
+#endif
+
+#ifndef DBG_TRACE_VALUES
+#define DBG_TRACE_VALUES 24 // # of supported debug trace values (size of circular buffer)
+#endif
+
+//---------------------------------------------------------------------------
+// modul global types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// local vars
+//---------------------------------------------------------------------------
+
+#ifdef _DBG_TRACE_POINTS_
+atomic_t aatmDbgTracePoint_l[DBG_TRACE_POINTS];
+DWORD adwDbgTraceValue_l[DBG_TRACE_VALUES];
+DWORD dwDbgTraceValueOld_l;
+unsigned int uiDbgTraceValuePos_l;
+spinlock_t spinlockDbgTraceValue_l;
+unsigned long ulDbTraceValueFlags_l;
+#endif
+
+//---------------------------------------------------------------------------
+// local function prototypes
+//---------------------------------------------------------------------------
+
+static int EplLinProcRead(char *pcBuffer_p, char **ppcStart_p, off_t Offset_p,
+ int nBufferSize_p, int *pEof_p, void *pData_p);
+static int EplLinProcWrite(struct file *file, const char __user * buffer,
+ unsigned long count, void *data);
+
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
+
+EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void);
+
+//=========================================================================//
+// //
+// P U B L I C F U N C T I O N S //
+// //
+//=========================================================================//
+
+tEplKernel EplLinProcInit(void)
+{
+ struct proc_dir_entry *pProcDirEntry;
+ pProcDirEntry = create_proc_entry(EPL_PROC_DEV_NAME, S_IRUGO, NULL);
+ if (pProcDirEntry != NULL) {
+ pProcDirEntry->read_proc = EplLinProcRead;
+ pProcDirEntry->write_proc = EplLinProcWrite;
+ pProcDirEntry->data = NULL; // device number or something else
+
+ } else {
+ return kEplNoResource;
+ }
+
+#ifdef _DBG_TRACE_POINTS_
+ // initialize spinlock and circular buffer position
+ spin_lock_init(&spinlockDbgTraceValue_l);
+ uiDbgTraceValuePos_l = 0;
+ dwDbgTraceValueOld_l = 0;
+#endif
+
+ return kEplSuccessful;
+}
+
+tEplKernel EplLinProcFree(void)
+{
+ remove_proc_entry(EPL_PROC_DEV_NAME, NULL);
+
+ return kEplSuccessful;
+}
+
+//---------------------------------------------------------------------------
+// Target specific event signaling (FEC Tx-/Rx-Interrupt, used by Edrv)
+//---------------------------------------------------------------------------
+
+#ifdef _DBG_TRACE_POINTS_
+void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p)
+{
+
+ if (bTracePointNumber_p >=
+ (sizeof(aatmDbgTracePoint_l) / sizeof(aatmDbgTracePoint_l[0]))) {
+ goto Exit;
+ }
+
+ atomic_inc(&aatmDbgTracePoint_l[bTracePointNumber_p]);
+
+ Exit:
+
+ return;
+
+}
+
+void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p)
+{
+
+ spin_lock_irqsave(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l);
+ if (dwDbgTraceValueOld_l != dwTraceValue_p) {
+ adwDbgTraceValue_l[uiDbgTraceValuePos_l] = dwTraceValue_p;
+ uiDbgTraceValuePos_l =
+ (uiDbgTraceValuePos_l + 1) % DBG_TRACE_VALUES;
+ dwDbgTraceValueOld_l = dwTraceValue_p;
+ }
+ spin_unlock_irqrestore(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l);
+
+ return;
+
+}
+#endif
+
+//---------------------------------------------------------------------------
+// Read function for PROC-FS read access
+//---------------------------------------------------------------------------
+
+static int EplLinProcRead(char *pcBuffer_p,
+ char **ppcStart_p,
+ off_t Offset_p,
+ int nBufferSize_p, int *pEof_p, void *pData_p)
+{
+
+ int nSize;
+ int Eof;
+ tEplDllkCalStatistics *pDllkCalStats;
+
+ nSize = 0;
+ Eof = 0;
+
+ // count calls of this function
+#ifdef _DBG_TRACE_POINTS_
+ TgtDbgSignalTracePoint(0);
+#endif
+
+ //---------------------------------------------------------------
+ // generate static information
+ //---------------------------------------------------------------
+
+ // ---- Driver information ----
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "%s %s (c) 2006 %s\n",
+ EPL_PRODUCT_NAME, EPL_PRODUCT_VERSION,
+ EPL_PRODUCT_MANUFACTURER);
+
+ //---------------------------------------------------------------
+ // generate process information
+ //---------------------------------------------------------------
+
+ // ---- EPL state ----
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "NMT state: 0x%04X\n",
+ (WORD) EplNmtkGetNmtState());
+
+ EplDllkCalGetStatistics(&pDllkCalStats);
+
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "CurAsyncTxGen=%lu CurAsyncTxNmt=%lu CurAsyncRx=%lu\nMaxAsyncTxGen=%lu MaxAsyncTxNmt=%lu MaxAsyncRx=%lu\n",
+ pDllkCalStats->m_ulCurTxFrameCountGen,
+ pDllkCalStats->m_ulCurTxFrameCountNmt,
+ pDllkCalStats->m_ulCurRxFrameCount,
+ pDllkCalStats->m_ulMaxTxFrameCountGen,
+ pDllkCalStats->m_ulMaxTxFrameCountNmt,
+ pDllkCalStats->m_ulMaxRxFrameCount);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+ // fetch running IdentRequests
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "running IdentRequests: 0x%08lX\n",
+ EplIdentuGetRunningRequests());
+
+ // fetch state of NmtMnu module
+ {
+ unsigned int uiMandatorySlaveCount;
+ unsigned int uiSignalSlaveCount;
+ WORD wFlags;
+
+ EplNmtMnuGetDiagnosticInfo(&uiMandatorySlaveCount,
+ &uiSignalSlaveCount, &wFlags);
+
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "MN MandSlaveCount: %u SigSlaveCount: %u Flags: 0x%X\n",
+ uiMandatorySlaveCount, uiSignalSlaveCount,
+ wFlags);
+
+ }
+#endif
+
+ // ---- FEC state ----
+#ifdef CONFIG_COLDFIRE
+ {
+ // Receive the base address
+ unsigned long base_addr;
+#if (EDRV_USED_ETH_CTRL == 0)
+ // Set the base address of FEC0
+ base_addr = FEC_BASE_ADDR_FEC0;
+#else
+ // Set the base address of FEC1
+ base_addr = FEC_BASE_ADDR_FEC1;
+#endif
+
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "FEC_ECR = 0x%08X FEC_EIR = 0x%08X FEC_EIMR = 0x%08X\nFEC_TCR = 0x%08X FECTFSR = 0x%08X FECRFSR = 0x%08X\n",
+ FEC_ECR(base_addr), FEC_EIR(base_addr),
+ FEC_EIMR(base_addr), FEC_TCR(base_addr),
+ FEC_FECTFSR(base_addr),
+ FEC_FECRFSR(base_addr));
+ }
+#endif
+
+ // ---- DBG: TracePoints ----
+#ifdef _DBG_TRACE_POINTS_
+ {
+ int nNum;
+
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "DbgTracePoints:\n");
+ for (nNum = 0;
+ nNum < (sizeof(aatmDbgTracePoint_l) / sizeof(atomic_t));
+ nNum++) {
+ nSize +=
+ snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ " TracePoint[%2d]: %d\n", (int)nNum,
+ atomic_read(&aatmDbgTracePoint_l[nNum]));
+ }
+
+ nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "DbgTraceValues:\n");
+ for (nNum = 0; nNum < DBG_TRACE_VALUES; nNum++) {
+ if (nNum == uiDbgTraceValuePos_l) { // next value will be stored at that position
+ nSize +=
+ snprintf(pcBuffer_p + nSize,
+ nBufferSize_p - nSize, "*%08lX",
+ adwDbgTraceValue_l[nNum]);
+ } else {
+ nSize +=
+ snprintf(pcBuffer_p + nSize,
+ nBufferSize_p - nSize, " %08lX",
+ adwDbgTraceValue_l[nNum]);
+ }
+ if ((nNum & 0x00000007) == 0x00000007) { // 8 values printed -> end of line reached
+ nSize +=
+ snprintf(pcBuffer_p + nSize,
+ nBufferSize_p - nSize, "\n");
+ }
+ }
+ if ((nNum & 0x00000007) != 0x00000007) { // number of values printed is not a multiple of 8 -> print new line
+ nSize +=
+ snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
+ "\n");
+ }
+ }
+#endif
+
+ Eof = 1;
+ goto Exit;
+
+ Exit:
+
+ *pEof_p = Eof;
+
+ return (nSize);
+
+}
+
+//---------------------------------------------------------------------------
+// Write function for PROC-FS write access
+//---------------------------------------------------------------------------
+
+static int EplLinProcWrite(struct file *file, const char __user * buffer,
+ unsigned long count, void *data)
+{
+ char abBuffer[count + 1];
+ int iErr;
+ int iVal = 0;
+ tEplNmtEvent NmtEvent;
+
+ if (count > 0) {
+ iErr = copy_from_user(abBuffer, buffer, count);
+ if (iErr != 0) {
+ return count;
+ }
+ abBuffer[count] = '\0';
+
+ iErr = sscanf(abBuffer, "%i", &iVal);
+ }
+ if ((iVal <= 0) || (iVal > 0x2F)) {
+ NmtEvent = kEplNmtEventSwReset;
+ } else {
+ NmtEvent = (tEplNmtEvent) iVal;
+ }
+ // execute specified NMT command on write access of /proc/epl
+ EplNmtuNmtEvent(NmtEvent);
+
+ return count;
+}
diff --git a/drivers/staging/epl/proc_fs.h b/drivers/staging/epl/proc_fs.h
new file mode 100644
index 000000000000..0586f499553a
--- /dev/null
+++ b/drivers/staging/epl/proc_fs.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: interface for proc fs entry under Linux
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: proc_fs.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:33 $
+
+ $State: Exp $
+
+ Build Environment:
+ GNU
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/31 d.k.: start of implementation
+
+****************************************************************************/
+
+#ifndef _EPLPROCFS_H_
+#define _EPLPROCFS_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// types
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel EplLinProcInit(void);
+tEplKernel EplLinProcFree(void);
+
+#endif // #ifndef _EPLPROCFS_H_
diff --git a/drivers/staging/epl/user/EplCfgMau.h b/drivers/staging/epl/user/EplCfgMau.h
new file mode 100644
index 000000000000..d25a1e9d36cf
--- /dev/null
+++ b/drivers/staging/epl/user/EplCfgMau.h
@@ -0,0 +1,284 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for Epl Configuration Manager Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplCfgMau.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ VC7
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/14 k.t.: start of the implementation
+ -> based on CANopen CfgMa-Modul (CANopen version 5.34)
+
+****************************************************************************/
+
+#include "../EplInc.h"
+
+#ifndef _EPLCFGMA_H_
+#define _EPLCFGMA_H_
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0)
+
+#include "EplObdu.h"
+#include "EplSdoComu.h"
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+//define max number of timeouts for configuration of 1 device
+#define EPL_CFGMA_MAX_TIMEOUT 3
+
+//callbackfunction, called if configuration is finished
+typedef void (PUBLIC * tfpEplCfgMaCb) (unsigned int uiNodeId_p,
+ tEplKernel Errorstate_p);
+
+//State for configuartion manager Statemachine
+typedef enum {
+ // general states
+ kEplCfgMaIdle = 0x0000, // Configurationsprocess
+ // is idle
+ kEplCfgMaWaitForSdocEvent = 0x0001, // wait until the last
+ // SDOC is finisched
+ kEplCfgMaSkipMappingSub0 = 0x0002, // write Sub0 of mapping
+ // parameter with 0
+
+ kEplCfgMaFinished = 0x0004 // configuartion is finished
+} tEplCfgState;
+
+typedef enum {
+ kEplCfgMaDcfTypSystecSeg = 0x00,
+ kEplCfgMaDcfTypConDcf = 0x01,
+ kEplCfgMaDcfTypDcf = 0x02, // not supported
+ kEplCfgMaDcfTypXdc = 0x03 // not supported
+} tEplCfgMaDcfTyp;
+
+typedef enum {
+ kEplCfgMaCommon = 0, // all other index
+ kEplCfgMaPdoComm = 1, // communication index
+ kEplCfgMaPdoMapp = 2, // mapping index
+ kEplCfgMaPdoCommAfterMapp = 3, // write PDO Cob-Id after mapping subindex 0(set PDO valid)
+
+} tEplCfgMaIndexType;
+
+//bitcoded answer about the last sdo transfer saved in m_SdocState
+// also used to singal start of the State Maschine
+typedef enum {
+ kEplCfgMaSdocBusy = 0x00, // SDOC activ
+ kEplCfgMaSdocReady = 0x01, // SDOC finished
+ kEplCfgMaSdocTimeout = 0x02, // SDOC Timeout
+ kEplCfgMaSdocAbortReceived = 0x04, // SDOC Abort, see Abortcode
+ kEplCfgMaSdocStart = 0x08 // start State Mschine
+} tEplSdocState;
+
+//internal structure (instancetable for modul configuration manager)
+typedef struct {
+ tEplCfgState m_CfgState; // state of the configuration state maschine
+ tEplSdoComConHdl m_SdoComConHdl; // handle for sdo connection
+ DWORD m_dwLastAbortCode;
+ unsigned int m_uiLastIndex; // last index of configuration, to compair with actual index
+ BYTE *m_pbConcise; // Ptr to concise DCF
+ BYTE *m_pbActualIndex; // Ptr to actual index in the DCF segment
+ tfpEplCfgMaCb m_pfnCfgMaCb; // Ptr to CfgMa Callback, is call if configuration finished
+ tEplKernel m_EplKernelError; // errorcode
+ DWORD m_dwNumValueCopy; // numeric values are copied in this variable
+ unsigned int m_uiPdoNodeId; // buffer for PDO node id
+ BYTE m_bNrOfMappedObject; // number of mapped objects
+ unsigned int m_uiNodeId; // Epl node addresse
+ tEplSdocState m_SdocState; // bitcoded state of the SDO transfer
+ unsigned int m_uiLastSubIndex; // last subindex of configuration
+ BOOL m_fOneTranferOk; // atleased one transfer was successful
+ BYTE m_bEventFlag; // for Eventsignaling to the State Maschine
+ DWORD m_dwCntObjectInDcf; // number of Objects in DCF
+ tEplCfgMaIndexType m_SkipCfg; // TRUE if a adsitional Configurationprocess
+ // have to insert e.g. PDO-mapping
+ WORD m_wTimeOutCnt; // Timeout Counter, break configuration is
+ // m_wTimeOutCnt == CFGMA_MAX_TIMEOUT
+
+} tEplCfgMaNode;
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// Function: EplCfgMaInit()
+//
+// Description: Function creates first instance of Configuration Manager
+//
+// Parameters:
+//
+// Returns: tEplKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaInit();
+
+//---------------------------------------------------------------------------
+// Function: EplCfgMaAddInstance()
+//
+// Description: Function creates additional instance of Configuration Manager
+//
+// Parameters:
+//
+// Returns: tEplKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaAddInstance();
+
+//---------------------------------------------------------------------------
+// Function: EplCfgMaDelInstance()
+//
+// Description: Function delete instance of Configuration Manager
+//
+// Parameters:
+//
+// Returns: tEplKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaDelInstance();
+
+//---------------------------------------------------------------------------
+// Function: EplCfgMaStartConfig()
+//
+// Description: Function starts the configuration process
+// initialization the statemachine for CfgMa- process
+//
+// Parameters: uiNodeId_p = NodeId of the node to configure
+// pbConcise_p = pointer to DCF
+// fpCfgMaCb_p = pointer to callback function (should not be NULL)
+// SizeOfConcise_p = size of DCF in BYTE -> for future use
+// DcfType_p = type of the DCF
+//
+// Returns: tCopKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaStartConfig(unsigned int uiNodeId_p,
+ BYTE * pbConcise_p,
+ tfpEplCfgMaCb fpCfgMaCb_p,
+ tEplObdSize SizeOfConcise_p,
+ tEplCfgMaDcfTyp DcfType_p);
+
+//---------------------------------------------------------------------------
+// Function: CfgMaStartConfigurationNode()
+//
+// Description: Function started the configuration process
+// with the DCF from according OD-entry Subindex == bNodeId_p
+//
+// Parameters: uiNodeId_p = NodeId of the node to configure
+// fpCfgMaCb_p = pointer to callback function (should not be NULL)
+// DcfType_p = type of the DCF
+//
+// Returns: tCopKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaStartConfigNode(unsigned int uiNodeId_p,
+ tfpEplCfgMaCb fpCfgMaCb_p,
+ tEplCfgMaDcfTyp DcfType_p);
+
+//---------------------------------------------------------------------------
+// Function: EplCfgMaStartConfigNodeDcf()
+//
+// Description: Function starts the configuration process
+// and links the configuration data to the OD
+//
+// Parameters: uiNodeId_p = NodeId of the node to configure
+// pbConcise_p = pointer to DCF
+// fpCfgMaCb_p = pointer to callback function (should not be NULL)
+// SizeOfConcise_p = size of DCF in BYTE -> for future use
+// DcfType_p = type of the DCF
+//
+// Returns: tCopKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaStartConfigNodeDcf(unsigned int uiNodeId_p,
+ BYTE * pbConcise_p,
+ tfpEplCfgMaCb fpCfgMaCb_p,
+ tEplObdSize SizeOfConcise_p,
+ tEplCfgMaDcfTyp DcfType_p);
+
+//---------------------------------------------------------------------------
+// Function: EplCfgMaLinkDcf()
+//
+// Description: Function links the configuration data to the OD
+//
+// Parameters: uiNodeId_p = NodeId of the node to configure
+// pbConcise_p = pointer to DCF
+// SizeOfConcise_p = size of DCF in BYTE -> for future use
+// DcfType_p = type of the DCF
+//
+// Returns: tCopKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaLinkDcf(unsigned int uiNodeId_p,
+ BYTE * pbConcise_p,
+ tEplObdSize SizeOfConcise_p,
+ tEplCfgMaDcfTyp DcfType_p);
+
+//---------------------------------------------------------------------------
+// Function: EplCfgMaCheckDcf()
+//
+// Description: Function check if there is allready a configuration file linked
+// to the OD (type is given by DcfType_p)
+//
+// Parameters: uiNodeId_p = NodeId
+// DcfType_p = type of the DCF
+//
+// Returns: tCopKernel = error code
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplCfgMaCheckDcf(unsigned int uiNodeId_p,
+ tEplCfgMaDcfTyp DcfType_p);
+
+#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_CFGMA)) != 0)
+
+#endif // _EPLCFGMA_H_
+
+// EOF
diff --git a/drivers/staging/epl/user/EplDllu.h b/drivers/staging/epl/user/EplDllu.h
new file mode 100644
index 000000000000..36f8bb76f7ca
--- /dev/null
+++ b/drivers/staging/epl/user/EplDllu.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for userspace DLL module for asynchronous communication
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDllu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/20 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_DLLU_H_
+#define _EPL_DLLU_H_
+
+#include "../EplDll.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef tEplKernel(PUBLIC * tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+
+tEplKernel EplDlluAddInstance(void);
+
+tEplKernel EplDlluDelInstance(void);
+
+tEplKernel EplDlluRegAsndService(tEplDllAsndServiceId ServiceId_p,
+ tEplDlluCbAsnd pfnDlluCbAsnd_p,
+ tEplDllAsndFilter Filter_p);
+
+tEplKernel EplDlluAsyncSend(tEplFrameInfo * pFrameInfo_p,
+ tEplDllAsyncReqPriority Priority_p);
+
+// processes asynch frames
+tEplKernel EplDlluProcess(tEplFrameInfo * pFrameInfo_p);
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
+
+#endif // #ifndef _EPL_DLLU_H_
diff --git a/drivers/staging/epl/user/EplDlluCal.h b/drivers/staging/epl/user/EplDlluCal.h
new file mode 100644
index 000000000000..b1dcd0609573
--- /dev/null
+++ b/drivers/staging/epl/user/EplDlluCal.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for DLL Communication Abstraction Layer module in EPL user part
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplDlluCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/20 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_DLLUCAL_H_
+#define _EPL_DLLUCAL_H_
+
+#include "../EplDll.h"
+#include "../EplEvent.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef tEplKernel(PUBLIC * tEplDlluCbAsnd) (tEplFrameInfo * pFrameInfo_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel EplDlluCalAddInstance(void);
+
+tEplKernel EplDlluCalDelInstance(void);
+
+tEplKernel EplDlluCalRegAsndService(tEplDllAsndServiceId ServiceId_p,
+ tEplDlluCbAsnd pfnDlluCbAsnd_p,
+ tEplDllAsndFilter Filter_p);
+
+tEplKernel EplDlluCalAsyncSend(tEplFrameInfo * pFrameInfo,
+ tEplDllAsyncReqPriority Priority_p);
+
+tEplKernel EplDlluCalProcess(tEplEvent * pEvent_p);
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+tEplKernel EplDlluCalAddNode(tEplDllNodeInfo * pNodeInfo_p);
+
+tEplKernel EplDlluCalDeleteNode(unsigned int uiNodeId_p);
+
+tEplKernel EplDlluCalSoftDeleteNode(unsigned int uiNodeId_p);
+
+tEplKernel EplDlluCalIssueRequest(tEplDllReqServiceId Service_p,
+ unsigned int uiNodeId_p, BYTE bSoaFlag1_p);
+
+#endif
+
+#endif // #ifndef _EPL_DLLUCAL_H_
diff --git a/drivers/staging/epl/user/EplEventu.h b/drivers/staging/epl/user/EplEventu.h
new file mode 100644
index 000000000000..322cffd11874
--- /dev/null
+++ b/drivers/staging/epl/user/EplEventu.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for kernel event module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplEventu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/12 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_EVENTU_H_
+#define _EPL_EVENTU_H_
+
+#include "../EplEvent.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+// init function
+tEplKernel PUBLIC EplEventuInit(tEplProcessEventCb pfnApiProcessEventCb_p);
+
+// add instance
+tEplKernel PUBLIC EplEventuAddInstance(tEplProcessEventCb
+ pfnApiProcessEventCb_p);
+
+// delete instance
+tEplKernel PUBLIC EplEventuDelInstance(void);
+
+// Task that dispatches events in userspace
+tEplKernel PUBLIC EplEventuProcess(tEplEvent * pEvent_p);
+
+// post events from userspace
+tEplKernel PUBLIC EplEventuPost(tEplEvent * pEvent_p);
+
+// post errorevents from userspace
+tEplKernel PUBLIC EplEventuPostError(tEplEventSource EventSource_p,
+ tEplKernel EplError_p,
+ unsigned int uiArgSize_p, void *pArg_p);
+
+#endif // #ifndef _EPL_EVENTU_H_
diff --git a/drivers/staging/epl/user/EplIdentu.h b/drivers/staging/epl/user/EplIdentu.h
new file mode 100644
index 000000000000..e7302106c741
--- /dev/null
+++ b/drivers/staging/epl/user/EplIdentu.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for Identu-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplIdentu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/11/15 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplDll.h"
+
+#ifndef _EPLIDENTU_H_
+#define _EPLIDENTU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef tEplKernel(PUBLIC * tEplIdentuCbResponse) (unsigned int uiNodeId_p,
+ tEplIdentResponse *
+ pIdentResponse_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplIdentuInit(void);
+
+tEplKernel PUBLIC EplIdentuAddInstance(void);
+
+tEplKernel PUBLIC EplIdentuDelInstance(void);
+
+tEplKernel PUBLIC EplIdentuReset(void);
+
+tEplKernel PUBLIC EplIdentuGetIdentResponse(unsigned int uiNodeId_p,
+ tEplIdentResponse **
+ ppIdentResponse_p);
+
+tEplKernel PUBLIC EplIdentuRequestIdentResponse(unsigned int uiNodeId_p,
+ tEplIdentuCbResponse
+ pfnCbResponse_p);
+
+#endif // #ifndef _EPLIDENTU_H_
diff --git a/drivers/staging/epl/user/EplLedu.h b/drivers/staging/epl/user/EplLedu.h
new file mode 100644
index 000000000000..78e70d064459
--- /dev/null
+++ b/drivers/staging/epl/user/EplLedu.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for status and error LED user part module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplLedu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.1 $ $Date: 2008/11/17 16:40:39 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2008/11/17 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplLed.h"
+#include "../EplNmt.h"
+#include "EplEventu.h"
+
+#ifndef _EPLLEDU_H_
+#define _EPLLEDU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef tEplKernel(PUBLIC * tEplLeduStateChangeCallback) (tEplLedType LedType_p,
+ BOOL fOn_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+
+tEplKernel PUBLIC EplLeduInit(tEplLeduStateChangeCallback pfnCbStateChange_p);
+
+tEplKernel PUBLIC EplLeduAddInstance(tEplLeduStateChangeCallback
+ pfnCbStateChange_p);
+
+tEplKernel PUBLIC EplLeduDelInstance(void);
+
+tEplKernel PUBLIC EplLeduCbNmtStateChange(tEplEventNmtStateChange
+ NmtStateChange_p);
+
+tEplKernel PUBLIC EplLeduProcessEvent(tEplEvent * pEplEvent_p);
+
+#endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_LEDU)) != 0)
+
+#endif // #ifndef _EPLLEDU_H_
diff --git a/drivers/staging/epl/user/EplNmtCnu.h b/drivers/staging/epl/user/EplNmtCnu.h
new file mode 100644
index 000000000000..e508055b5b8f
--- /dev/null
+++ b/drivers/staging/epl/user/EplNmtCnu.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for NMT-CN-Userspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtCnu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplNmtu.h"
+#include "../EplDll.h"
+#include "../EplFrame.h"
+
+#ifndef _EPLNMTCNU_H_
+#define _EPLNMTCNU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0)
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuInit(unsigned int uiNodeId_p);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuAddInstance(unsigned int uiNodeId_p);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuDelInstance(void);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtCnuSendNmtRequest(unsigned int uiNodeId_p,
+ tEplNmtCommand
+ NmtCommand_p);
+
+EPLDLLEXPORT tEplKernel PUBLIC
+EplNmtCnuRegisterCheckEventCb(tEplNmtuCheckEventCallback
+ pfnEplNmtCheckEventCb_p);
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_CN)) != 0)
+
+#endif // #ifndef _EPLNMTCNU_H_
diff --git a/drivers/staging/epl/user/EplNmtMnu.h b/drivers/staging/epl/user/EplNmtMnu.h
new file mode 100644
index 000000000000..c54efeba303f
--- /dev/null
+++ b/drivers/staging/epl/user/EplNmtMnu.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for NMT-MN-Userspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtMnu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplNmtu.h"
+
+#ifndef _EPLNMTMNU_H_
+#define _EPLNMTMNU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef tEplKernel(PUBLIC * tEplNmtMnuCbNodeEvent) (unsigned int uiNodeId_p,
+ tEplNmtNodeEvent
+ NodeEvent_p,
+ tEplNmtState NmtState_p,
+ WORD wErrorCode_p,
+ BOOL fMandatory_p);
+
+typedef tEplKernel(PUBLIC *
+ tEplNmtMnuCbBootEvent) (tEplNmtBootEvent BootEvent_p,
+ tEplNmtState NmtState_p,
+ WORD wErrorCode_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
+
+tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
+ tEplNmtMnuCbBootEvent pfnCbBootEvent_p);
+
+tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
+ tEplNmtMnuCbBootEvent pfnCbBootEvent_p);
+
+tEplKernel EplNmtMnuDelInstance(void);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p);
+
+tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p,
+ tEplNmtCommand NmtCommand_p);
+
+tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p,
+ tEplNmtNodeCommand NodeCommand_p);
+
+tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange
+ NmtStateChange_p);
+
+tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p);
+
+tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int
+ *puiMandatorySlaveCount_p,
+ unsigned int
+ *puiSignalSlaveCount_p,
+ WORD * pwFlags_p);
+
+#endif
+
+#endif // #ifndef _EPLNMTMNU_H_
diff --git a/drivers/staging/epl/user/EplNmtu.h b/drivers/staging/epl/user/EplNmtu.h
new file mode 100644
index 000000000000..5a56c5830603
--- /dev/null
+++ b/drivers/staging/epl/user/EplNmtu.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for NMT-Userspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/09 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplNmt.h"
+#include "EplEventu.h"
+
+#ifndef _EPLNMTU_H_
+#define _EPLNMTU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+// nmt commands
+typedef enum {
+ // requestable ASnd ServiceIds 0x01..0x1F
+ kEplNmtCmdIdentResponse = 0x01,
+ kEplNmtCmdStatusResponse = 0x02,
+ // plain NMT state commands 0x20..0x3F
+ kEplNmtCmdStartNode = 0x21,
+ kEplNmtCmdStopNode = 0x22,
+ kEplNmtCmdEnterPreOperational2 = 0x23,
+ kEplNmtCmdEnableReadyToOperate = 0x24,
+ kEplNmtCmdResetNode = 0x28,
+ kEplNmtCmdResetCommunication = 0x29,
+ kEplNmtCmdResetConfiguration = 0x2A,
+ kEplNmtCmdSwReset = 0x2B,
+ // extended NMT state commands 0x40..0x5F
+ kEplNmtCmdStartNodeEx = 0x41,
+ kEplNmtCmdStopNodeEx = 0x42,
+ kEplNmtCmdEnterPreOperational2Ex = 0x43,
+ kEplNmtCmdEnableReadyToOperateEx = 0x44,
+ kEplNmtCmdResetNodeEx = 0x48,
+ kEplNmtCmdResetCommunicationEx = 0x49,
+ kEplNmtCmdResetConfigurationEx = 0x4A,
+ kEplNmtCmdSwResetEx = 0x4B,
+ // NMT managing commands 0x60..0x7F
+ kEplNmtCmdNetHostNameSet = 0x62,
+ kEplNmtCmdFlushArpEntry = 0x63,
+ // NMT info services 0x80..0xBF
+ kEplNmtCmdPublishConfiguredCN = 0x80,
+ kEplNmtCmdPublishActiveCN = 0x90,
+ kEplNmtCmdPublishPreOperational1 = 0x91,
+ kEplNmtCmdPublishPreOperational2 = 0x92,
+ kEplNmtCmdPublishReadyToOperate = 0x93,
+ kEplNmtCmdPublishOperational = 0x94,
+ kEplNmtCmdPublishStopped = 0x95,
+ kEplNmtCmdPublishEmergencyNew = 0xA0,
+ kEplNmtCmdPublishTime = 0xB0,
+
+ kEplNmtCmdInvalidService = 0xFF
+} tEplNmtCommand;
+
+typedef tEplKernel(PUBLIC *
+ tEplNmtuStateChangeCallback) (tEplEventNmtStateChange
+ NmtStateChange_p);
+
+typedef tEplKernel(PUBLIC *
+ tEplNmtuCheckEventCallback) (tEplNmtEvent NmtEvent_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuInit(void);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuAddInstance(void);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuDelInstance(void);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuNmtEvent(tEplNmtEvent NmtEvent_p);
+
+EPLDLLEXPORT tEplNmtState PUBLIC EplNmtuGetNmtState(void);
+
+EPLDLLEXPORT tEplKernel PUBLIC EplNmtuProcessEvent(tEplEvent * pEplEvent_p);
+
+EPLDLLEXPORT tEplKernel PUBLIC
+EplNmtuRegisterStateChangeCb(tEplNmtuStateChangeCallback
+ pfnEplNmtStateChangeCb_p);
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTU)) != 0)
+
+#endif // #ifndef _EPLNMTU_H_
diff --git a/drivers/staging/epl/user/EplNmtuCal.h b/drivers/staging/epl/user/EplNmtuCal.h
new file mode 100644
index 000000000000..c881582702bb
--- /dev/null
+++ b/drivers/staging/epl/user/EplNmtuCal.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for communication abstraction layer of the
+ NMT-Userspace-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplNmtuCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/16 -k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "EplNmtu.h"
+#include "../kernel/EplNmtk.h"
+
+#ifndef _EPLNMTUCAL_H_
+#define _EPLNMTUCAL_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkCalGetNmtState(void);
+
+#endif // #ifndef _EPLNMTUCAL_H_
diff --git a/drivers/staging/epl/user/EplObdu.h b/drivers/staging/epl/user/EplObdu.h
new file mode 100644
index 000000000000..bc1e17303017
--- /dev/null
+++ b/drivers/staging/epl/user/EplObdu.h
@@ -0,0 +1,192 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for Epl-Obd-Userspace-module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObdu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/19 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplObd.h"
+
+#ifndef _EPLOBDU_H_
+#define _EPLOBDU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+
+#if EPL_OBD_USE_KERNEL != FALSE
+#error "EPL OBDu module enabled, but OBD_USE_KERNEL == TRUE"
+#endif
+
+EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduAccessOdPart(tEplObdPart ObdPart_p,
+ tEplObdDir Direction_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduDefineVar(tEplVarParam MEM * pVarParam_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT void *PUBLIC EplObduGetObjectDataPtr(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p);
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduRegisterUserOd(tEplObdEntryPtr pUserOd_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT void PUBLIC EplObduInitVarEntry(tEplObdVarEntry MEM * pVarEntry_p,
+ BYTE bType_p,
+ tEplObdSize ObdSize_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplObdSize PUBLIC EplObduGetDataSize(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT unsigned int PUBLIC EplObduGetNodeId(void);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduSetNodeId(unsigned int uiNodeId_p,
+ tEplObdNodeIdType NodeIdType_p);
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduGetAccessType(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ tEplObdAccess *
+ pAccessTyp_p);
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduReadEntryToLe(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p);
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduWriteEntryFromLe(unsigned int uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p);
+
+// ---------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_
+ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdVarEntry MEM **
+ ppVarEntry_p);
+
+#elif EPL_OBD_USE_KERNEL != FALSE
+#include "../kernel/EplObdk.h"
+
+#define EplObduWriteEntry EplObdWriteEntry
+
+#define EplObduReadEntry EplObdReadEntry
+
+#define EplObduAccessOdPart EplObdAccessOdPart
+
+#define EplObduDefineVar EplObdDefineVar
+
+#define EplObduGetObjectDataPtr EplObdGetObjectDataPtr
+
+#define EplObduRegisterUserOd EplObdRegisterUserOd
+
+#define EplObduInitVarEntry EplObdInitVarEntry
+
+#define EplObduGetDataSize EplObdGetDataSize
+
+#define EplObduGetNodeId EplObdGetNodeId
+
+#define EplObduSetNodeId EplObdSetNodeId
+
+#define EplObduGetAccessType EplObdGetAccessType
+
+#define EplObduReadEntryToLe EplObdReadEntryToLe
+
+#define EplObduWriteEntryFromLe EplObdWriteEntryFromLe
+
+#define EplObduSearchVarEntry EplObdSearchVarEntry
+
+#define EplObduIsNumerical EplObdIsNumerical
+
+#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) != 0)
+
+#endif // #ifndef _EPLOBDU_H_
diff --git a/drivers/staging/epl/user/EplObduCal.h b/drivers/staging/epl/user/EplObduCal.h
new file mode 100644
index 000000000000..498e0112fac3
--- /dev/null
+++ b/drivers/staging/epl/user/EplObduCal.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for communication abstraction layer
+ for the Epl-Obd-Userspace-Modul
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplObduCal.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/19 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplObd.h"
+
+#ifndef _EPLOBDUCAL_H_
+#define _EPLOBDUCAL_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntry(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalAccessOdPart(tEplObdPart ObdPart_p,
+ tEplObdDir Direction_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalDefineVar(tEplVarParam MEM *
+ pVarParam_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT void *PUBLIC EplObduCalGetObjectDataPtr(unsigned int uiIndex_p,
+ unsigned int uiSubIndex_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalRegisterUserOd(tEplObdEntryPtr
+ pUserOd_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT void PUBLIC EplObduCalInitVarEntry(tEplObdVarEntry MEM *
+ pVarEntry_p, BYTE bType_p,
+ tEplObdSize ObdSize_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplObdSize PUBLIC EplObduCalGetDataSize(unsigned int uiIndex_p,
+ unsigned int
+ uiSubIndex_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT unsigned int PUBLIC EplObduCalGetNodeId(void);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalSetNodeId(unsigned int uiNodeId_p,
+ tEplObdNodeIdType
+ NodeIdType_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalGetAccessType(unsigned int uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ tEplObdAccess *
+ pAccessTyp_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalReadEntryToLe(unsigned int uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ void *pDstData_p,
+ tEplObdSize * pSize_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC EplObduCalWriteEntryFromLe(unsigned int
+ uiIndex_p,
+ unsigned int
+ uiSubIndex_p,
+ void *pSrcData_p,
+ tEplObdSize Size_p);
+//---------------------------------------------------------------------------
+EPLDLLEXPORT tEplKernel PUBLIC
+EplObduCalSearchVarEntry(EPL_MCO_DECL_INSTANCE_PTR_ unsigned int uiIndex_p,
+ unsigned int uiSubindex_p,
+ tEplObdVarEntry MEM ** ppVarEntry_p);
+
+#endif // #ifndef _EPLOBDUCAL_H_
diff --git a/drivers/staging/epl/user/EplPdou.h b/drivers/staging/epl/user/EplPdou.h
new file mode 100644
index 000000000000..11de4862e8bb
--- /dev/null
+++ b/drivers/staging/epl/user/EplPdou.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for userspace PDO module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplPdou.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/11/19 17:14:38 $
+
+ $State: Exp $
+
+ Build Environment:
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/05/22 d.k.: start of the implementation, version 1.00
+
+****************************************************************************/
+
+#ifndef _EPL_PDOU_H_
+#define _EPL_PDOU_H_
+
+#include "../EplPdo.h"
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel EplPdouAddInstance(void);
+
+tEplKernel EplPdouDelInstance(void);
+
+#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0)
+tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p);
+#else
+#define EplPdouCbObdAccess NULL
+#endif
+
+// returns error if bPdoId_p is already valid
+/*
+tEplKernel EplPdouSetMapping(
+ BYTE bPdoId_p, BOOL fTxRx_p, BYTE bNodeId, BYTE bMappingVersion,
+ tEplPdoMapping * pMapping_p, BYTE bMaxEntries_p);
+
+tEplKernel EplPdouGetMapping(
+ BYTE bPdoId_p, BOOL fTxRx_p, BYTE * pbNodeId, BYTE * pbMappingVersion,
+ tEplPdoMapping * pMapping_p, BYTE * pbMaxEntries_p);
+*/
+
+#endif // #ifndef _EPL_PDOU_H_
diff --git a/drivers/staging/epl/user/EplSdoAsndu.h b/drivers/staging/epl/user/EplSdoAsndu.h
new file mode 100644
index 000000000000..e34959f42792
--- /dev/null
+++ b/drivers/staging/epl/user/EplSdoAsndu.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for SDO/Asnd-Protocolabstractionlayer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoAsndu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.6 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/07 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplSdo.h"
+#include "../EplDll.h"
+
+#ifndef _EPLSDOASNDU_H_
+#define _EPLSDOASNDU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+
+tEplKernel PUBLIC EplSdoAsnduInit(tEplSequLayerReceiveCb fpReceiveCb_p);
+
+tEplKernel PUBLIC EplSdoAsnduAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p);
+
+tEplKernel PUBLIC EplSdoAsnduDelInstance(void);
+
+tEplKernel PUBLIC EplSdoAsnduInitCon(tEplSdoConHdl * pSdoConHandle_p,
+ unsigned int uiTargetNodeId_p);
+
+tEplKernel PUBLIC EplSdoAsnduSendData(tEplSdoConHdl SdoConHandle_p,
+ tEplFrame * pSrcData_p,
+ DWORD dwDataSize_p);
+
+tEplKernel PUBLIC EplSdoAsnduDelCon(tEplSdoConHdl SdoConHandle_p);
+
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
+
+#endif // #ifndef _EPLSDOASNDU_H_
diff --git a/drivers/staging/epl/user/EplSdoAsySequ.h b/drivers/staging/epl/user/EplSdoAsySequ.h
new file mode 100644
index 000000000000..4658b5f8c538
--- /dev/null
+++ b/drivers/staging/epl/user/EplSdoAsySequ.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for asychrionus SDO Sequence Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoAsySequ.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.4 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplSdo.h"
+#include "EplSdoUdpu.h"
+#include "EplSdoAsndu.h"
+#include "../EplEvent.h"
+#include "EplTimeru.h"
+
+#ifndef _EPLSDOASYSEQU_H_
+#define _EPLSDOASYSEQU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p,
+ tEplSdoComConCb fpSdoComConCb_p);
+
+tEplKernel PUBLIC EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p,
+ tEplSdoComConCb fpSdoComConCb_p);
+
+tEplKernel PUBLIC EplSdoAsySeqDelInstance(void);
+
+tEplKernel PUBLIC EplSdoAsySeqInitCon(tEplSdoSeqConHdl * pSdoSeqConHdl_p,
+ unsigned int uiNodeId_p,
+ tEplSdoType SdoType);
+
+tEplKernel PUBLIC EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p,
+ unsigned int uiDataSize_p,
+ tEplFrame * pData_p);
+
+tEplKernel PUBLIC EplSdoAsySeqProcessEvent(tEplEvent * pEvent_p);
+
+tEplKernel PUBLIC EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p);
+
+#endif // #ifndef _EPLSDOASYSEQU_H_
diff --git a/drivers/staging/epl/user/EplSdoComu.h b/drivers/staging/epl/user/EplSdoComu.h
new file mode 100644
index 000000000000..3e454c7a3559
--- /dev/null
+++ b/drivers/staging/epl/user/EplSdoComu.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for SDO Command Layer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoComu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplSdo.h"
+#include "../EplObd.h"
+#include "../EplSdoAc.h"
+#include "EplObdu.h"
+#include "EplSdoAsySequ.h"
+
+#ifndef _EPLSDOCOMU_H_
+#define _EPLSDOCOMU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+tEplKernel PUBLIC EplSdoComInit(void);
+
+tEplKernel PUBLIC EplSdoComAddInstance(void);
+
+tEplKernel PUBLIC EplSdoComDelInstance(void);
+
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDOC)) != 0)
+
+tEplKernel PUBLIC EplSdoComDefineCon(tEplSdoComConHdl * pSdoComConHdl_p,
+ unsigned int uiTargetNodeId_p,
+ tEplSdoType ProtType_p);
+
+tEplKernel PUBLIC EplSdoComInitTransferByIndex(tEplSdoComTransParamByIndex *
+ pSdoComTransParam_p);
+
+tEplKernel PUBLIC EplSdoComUndefineCon(tEplSdoComConHdl SdoComConHdl_p);
+
+tEplKernel PUBLIC EplSdoComGetState(tEplSdoComConHdl SdoComConHdl_p,
+ tEplSdoComFinished * pSdoComFinished_p);
+
+tEplKernel PUBLIC EplSdoComSdoAbort(tEplSdoComConHdl SdoComConHdl_p,
+ DWORD dwAbortCode_p);
+
+#endif
+
+// for future extention
+/*
+tEplKernel PUBLIC EplSdoComInitTransferAllByIndex(tEplSdoComTransParamAllByIndex* pSdoComTransParam_p);
+
+tEplKernel PUBLIC EplSdoComInitTransferByName(tEplSdoComTransParamByName* pSdoComTransParam_p);
+
+tEplKernel PUBLIC EplSdoComInitTransferFile(tEplSdoComTransParamFile* pSdoComTransParam_p);
+
+*/
+
+#endif // #ifndef _EPLSDOCOMU_H_
diff --git a/drivers/staging/epl/user/EplSdoUdpu.h b/drivers/staging/epl/user/EplSdoUdpu.h
new file mode 100644
index 000000000000..2d77b6fff199
--- /dev/null
+++ b/drivers/staging/epl/user/EplSdoUdpu.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for SDO/UDP-Protocollabstractionlayer module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplSdoUdpu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/06/26 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplSdo.h"
+
+#ifndef _EPLSDOUDPU_H_
+#define _EPLSDOUDPU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+
+tEplKernel PUBLIC EplSdoUdpuInit(tEplSequLayerReceiveCb fpReceiveCb_p);
+
+tEplKernel PUBLIC EplSdoUdpuAddInstance(tEplSequLayerReceiveCb fpReceiveCb_p);
+
+tEplKernel PUBLIC EplSdoUdpuDelInstance(void);
+
+tEplKernel PUBLIC EplSdoUdpuConfig(unsigned long ulIpAddr_p,
+ unsigned int uiPort_p);
+
+tEplKernel PUBLIC EplSdoUdpuInitCon(tEplSdoConHdl * pSdoConHandle_p,
+ unsigned int uiTargetNodeId_p);
+
+tEplKernel PUBLIC EplSdoUdpuSendData(tEplSdoConHdl SdoConHandle_p,
+ tEplFrame * pSrcData_p,
+ DWORD dwDataSize_p);
+
+tEplKernel PUBLIC EplSdoUdpuDelCon(tEplSdoConHdl SdoConHandle_p);
+
+#endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
+
+#endif // #ifndef _EPLSDOUDPU_H_
diff --git a/drivers/staging/epl/user/EplStatusu.h b/drivers/staging/epl/user/EplStatusu.h
new file mode 100644
index 000000000000..d211935f0e83
--- /dev/null
+++ b/drivers/staging/epl/user/EplStatusu.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for Statusu-Module
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplStatusu.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.3 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/11/15 d.k.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplDll.h"
+
+#ifndef _EPLSTATUSU_H_
+#define _EPLSTATUSU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+typedef tEplKernel(PUBLIC * tEplStatusuCbResponse) (unsigned int uiNodeId_p,
+ tEplStatusResponse *
+ pStatusResponse_p);
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplStatusuInit(void);
+
+tEplKernel PUBLIC EplStatusuAddInstance(void);
+
+tEplKernel PUBLIC EplStatusuDelInstance(void);
+
+tEplKernel PUBLIC EplStatusuReset(void);
+
+tEplKernel PUBLIC EplStatusuRequestStatusResponse(unsigned int uiNodeId_p,
+ tEplStatusuCbResponse
+ pfnCbResponse_p);
+
+#endif // #ifndef _EPLSTATUSU_H_
diff --git a/drivers/staging/epl/user/EplTimeru.h b/drivers/staging/epl/user/EplTimeru.h
new file mode 100644
index 000000000000..404495501b8d
--- /dev/null
+++ b/drivers/staging/epl/user/EplTimeru.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+
+ (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
+ www.systec-electronic.com
+
+ Project: openPOWERLINK
+
+ Description: include file for Epl Userspace-Timermodule
+
+ License:
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of SYSTEC electronic GmbH nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without prior written permission. For written
+ permission, please contact info@systec-electronic.com.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Severability Clause:
+
+ If a provision of this License is or becomes illegal, invalid or
+ unenforceable in any jurisdiction, that shall not affect:
+ 1. the validity or enforceability in that jurisdiction of any other
+ provision of this License; or
+ 2. the validity or enforceability in other jurisdictions of that or
+ any other provision of this License.
+
+ -------------------------------------------------------------------------
+
+ $RCSfile: EplTimeru.h,v $
+
+ $Author: D.Krueger $
+
+ $Revision: 1.5 $ $Date: 2008/04/17 21:36:32 $
+
+ $State: Exp $
+
+ Build Environment:
+ GCC V3.4
+
+ -------------------------------------------------------------------------
+
+ Revision History:
+
+ 2006/07/06 k.t.: start of the implementation
+
+****************************************************************************/
+
+#include "../EplTimer.h"
+#include "EplEventu.h"
+
+#ifndef _EPLTIMERU_H_
+#define _EPLTIMERU_H_
+
+//---------------------------------------------------------------------------
+// const defines
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// typedef
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// function prototypes
+//---------------------------------------------------------------------------
+
+tEplKernel PUBLIC EplTimeruInit(void);
+
+tEplKernel PUBLIC EplTimeruAddInstance(void);
+
+tEplKernel PUBLIC EplTimeruDelInstance(void);
+
+tEplKernel PUBLIC EplTimeruSetTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p);
+
+tEplKernel PUBLIC EplTimeruModifyTimerMs(tEplTimerHdl * pTimerHdl_p,
+ unsigned long ulTime_p,
+ tEplTimerArg Argument_p);
+
+tEplKernel PUBLIC EplTimeruDeleteTimer(tEplTimerHdl * pTimerHdl_p);
+
+BOOL PUBLIC EplTimeruIsTimerActive(tEplTimerHdl TimerHdl_p);
+
+#endif // #ifndef _EPLTIMERU_H_
diff --git a/drivers/staging/et131x/et1310_tx.c b/drivers/staging/et131x/et1310_tx.c
index a95c2608a0c0..30eaac4c8707 100644
--- a/drivers/staging/et131x/et1310_tx.c
+++ b/drivers/staging/et131x/et1310_tx.c
@@ -1345,7 +1345,6 @@ void et131x_free_busy_send_packets(struct et131x_adapter *pAdapter)
{
PMP_TCB pMpTcb;
struct list_head *pEntry;
- struct sk_buff *pPacket = NULL;
unsigned long lockflags;
uint32_t FreeCounter = 0;
@@ -1358,8 +1357,6 @@ void et131x_free_busy_send_packets(struct et131x_adapter *pAdapter)
spin_unlock_irqrestore(&pAdapter->SendWaitLock, lockflags);
pEntry = pAdapter->TxRing.SendWaitQueue.next;
-
- pPacket = NULL;
}
pAdapter->TxRing.nWaitSend = 0;
diff --git a/drivers/staging/et131x/et131x_debug.h b/drivers/staging/et131x/et131x_debug.h
index dab608031d0b..994108eca663 100644
--- a/drivers/staging/et131x/et131x_debug.h
+++ b/drivers/staging/et131x/et131x_debug.h
@@ -82,11 +82,11 @@
#define DBG_LVL 3
#endif /* DBG_LVL */
-#define DBG_DEFAULTS (DBG_ERROR_ON | DBG_WARNING_ON | DBG_BREAK_ON )
+#define DBG_DEFAULTS (DBG_ERROR_ON | DBG_WARNING_ON | DBG_BREAK_ON)
-#define DBG_FLAGS(A) (A)->dbgFlags
-#define DBG_NAME(A) (A)->dbgName
-#define DBG_LEVEL(A) (A)->dbgLevel
+#define DBG_FLAGS(A) ((A)->dbgFlags)
+#define DBG_NAME(A) ((A)->dbgName)
+#define DBG_LEVEL(A) ((A)->dbgLevel)
#ifndef DBG_PRINT
#define DBG_PRINT(S...) printk(KERN_DEBUG S)
@@ -108,56 +108,110 @@
#define _DBG_LEAVE(A) printk(KERN_DEBUG "%s:%.*s:%s\n", DBG_NAME(A), \
DBG_LEVEL(A)--, _LEAVE_STR, __func__)
-#define DBG_ENTER(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \
- _DBG_ENTER(A);}
+#define DBG_ENTER(A) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_TRACE_ON) \
+ _DBG_ENTER(A); \
+ } while (0)
+
+#define DBG_LEAVE(A) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_TRACE_ON) \
+ _DBG_LEAVE(A); \
+ } while (0)
+
+#define DBG_PARAM(A, N, F, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_PARAM_ON) \
+ DBG_PRINT(" %s -- "F" ", N, S); \
+ } while (0)
+
+#define DBG_ERROR(A, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_ERROR_ON) { \
+ DBG_PRINT("%s:ERROR:%s ", DBG_NAME(A), __func__);\
+ DBG_PRINTC(S); \
+ DBG_TRAP; \
+ } \
+ } while (0)
+
+#define DBG_WARNING(A, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_WARNING_ON) { \
+ DBG_PRINT("%s:WARNING:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ } \
+ } while (0)
+
+#define DBG_NOTICE(A, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_NOTICE_ON) { \
+ DBG_PRINT("%s:NOTICE:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ } \
+ } while (0)
+
+#define DBG_TRACE(A, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_TRACE_ON) { \
+ DBG_PRINT("%s:TRACE:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ } \
+ } while (0)
+
+#define DBG_VERBOSE(A, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_VERBOSE_ON) { \
+ DBG_PRINT("%s:VERBOSE:%s ", DBG_NAME(A), __func__); \
+ DBG_PRINTC(S); \
+ } \
+ } while (0)
+
+#define DBG_RX(A, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_RX_ON) \
+ DBG_PRINT(S); \
+ } while (0)
+
+#define DBG_RX_ENTER(A) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_RX_ON) \
+ _DBG_ENTER(A); \
+ } while (0)
+
+#define DBG_RX_LEAVE(A) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_RX_ON) \
+ _DBG_LEAVE(A); \
+ } while (0)
+
+#define DBG_TX(A, S...) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_TX_ON) \
+ DBG_PRINT(S); \
+ } while (0)
+
+#define DBG_TX_ENTER(A) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_TX_ON) \
+ _DBG_ENTER(A); \
+ } while (0)
+
+#define DBG_TX_LEAVE(A) \
+ do { \
+ if (DBG_FLAGS(A) & DBG_TX_ON) \
+ _DBG_LEAVE(A); \
+ } while (0)
+
+#define DBG_ASSERT(C) \
+ do { \
+ if (!(C)) { \
+ DBG_PRINT("ASSERT(%s) -- %s#%d (%s) ", \
+ #C, __FILE__, __LINE__, __func__); \
+ DBG_TRAP; \
+ } \
+ } while (0)
-#define DBG_LEAVE(A) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \
- _DBG_LEAVE(A);}
-
-#define DBG_PARAM(A,N,F,S...) {if (DBG_FLAGS(A) & DBG_PARAM_ON) \
- DBG_PRINT(" %s -- "F"\n",N,S);}
-
-#define DBG_ERROR(A,S...) \
- if (DBG_FLAGS(A) & DBG_ERROR_ON) { \
- DBG_PRINT("%s:ERROR:%s ",DBG_NAME(A), __func__); \
- DBG_PRINTC(S); \
- DBG_TRAP; \
- }
-
-#define DBG_WARNING(A,S...) {if (DBG_FLAGS(A) & DBG_WARNING_ON) \
- {DBG_PRINT("%s:WARNING:%s ",DBG_NAME(A),__func__);DBG_PRINTC(S);}}
-
-#define DBG_NOTICE(A,S...) {if (DBG_FLAGS(A) & DBG_NOTICE_ON) \
- {DBG_PRINT("%s:NOTICE:%s ",DBG_NAME(A),__func__);DBG_PRINTC(S);}}
-
-#define DBG_TRACE(A,S...) {if (DBG_FLAGS(A) & DBG_TRACE_ON) \
- {DBG_PRINT("%s:TRACE:%s ",DBG_NAME(A), __func__);DBG_PRINTC(S);}}
-
-#define DBG_VERBOSE(A,S...) {if (DBG_FLAGS(A) & DBG_VERBOSE_ON) \
- {DBG_PRINT("%s:VERBOSE:%s ",DBG_NAME(A), __func__);DBG_PRINTC(S);}}
-
-#define DBG_RX(A,S...) {if (DBG_FLAGS(A) & DBG_RX_ON) \
- {DBG_PRINT(S);}}
-
-#define DBG_RX_ENTER(A) {if (DBG_FLAGS(A) & DBG_RX_ON) \
- _DBG_ENTER(A);}
-
-#define DBG_RX_LEAVE(A) {if (DBG_FLAGS(A) & DBG_RX_ON) \
- _DBG_LEAVE(A);}
-
-#define DBG_TX(A,S...) {if (DBG_FLAGS(A) & DBG_TX_ON) \
- {DBG_PRINT(S);}}
-
-#define DBG_TX_ENTER(A) {if (DBG_FLAGS(A) & DBG_TX_ON) \
- _DBG_ENTER(A);}
-
-#define DBG_TX_LEAVE(A) {if (DBG_FLAGS(A) & DBG_TX_ON) \
- _DBG_LEAVE(A);}
-
-#define DBG_ASSERT(C) {if (!(C)) \
- {DBG_PRINT("ASSERT(%s) -- %s#%d (%s)\n", \
- #C,__FILE__,__LINE__,__func__); \
- DBG_TRAP;}}
#define STATIC
typedef struct {
diff --git a/drivers/staging/frontier/Kconfig b/drivers/staging/frontier/Kconfig
new file mode 100644
index 000000000000..7121853bd397
--- /dev/null
+++ b/drivers/staging/frontier/Kconfig
@@ -0,0 +1,6 @@
+config TRANZPORT
+ tristate "Frontier Tranzport and Alphatrack support"
+ depends on USB
+ default N
+ ---help---
+ Enable support for the Frontier Tranzport and Alphatrack devices.
diff --git a/drivers/staging/frontier/Makefile b/drivers/staging/frontier/Makefile
new file mode 100644
index 000000000000..2d2ac97492dd
--- /dev/null
+++ b/drivers/staging/frontier/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_TRANZPORT) += tranzport.o
+obj-$(CONFIG_TRANZPORT) += alphatrack.o
diff --git a/drivers/staging/frontier/README b/drivers/staging/frontier/README
new file mode 100644
index 000000000000..07c9ef9b8fc4
--- /dev/null
+++ b/drivers/staging/frontier/README
@@ -0,0 +1,28 @@
+This directory contains the USB Tranzport and Alphatrack Kernel drivers for Linux.
+
+At present the tranzport does reads/writes of 8 byte cmds to /dev/tranzport0 to control
+the lights and screen and wheel
+
+At present the alphatrack accepts reads/writes of 12 byte cmds to /dev/tranzport0 to control
+the lights and screen and fader.
+
+Both drivers also have some sysfs hooks that are non-functional at the moment.
+
+The API is currently closely tied to the ardour revision and WILL change.
+
+A sysfs interface is PERFECT for simple userspace apps to do fun things with the
+lights and screen. It's fairly lousy for handling input events and very lousy
+for watching the state of the shuttle wheel.
+
+A linux input events interface is great for the input events and shuttle wheel. It's
+theoretically OK on LEDs. A Fader can be mapped to an absolute mouse device.
+But there is no LCD support at all.
+
+In the end this is going to be driven by a midi layer, which handles all those
+cases via a defined API, but - among other things - is slow, doesn't do
+flow control, and is a LOT of extra work. Frankly, I'd like to keep the
+core driver simple because the only realtime work really required is
+the bottom half interrupt handler and the output overlapping.
+
+Exposing some sort of clean aio api to userspace would be perfect. What that
+API looks like? Gah. beats me.
diff --git a/drivers/staging/frontier/TODO b/drivers/staging/frontier/TODO
new file mode 100644
index 000000000000..3620ad2df3ee
--- /dev/null
+++ b/drivers/staging/frontier/TODO
@@ -0,0 +1,9 @@
+TODO:
+ - checkpatch.pl clean
+ - sparse clean
+ - fix userspace interface to be sane
+ - possibly just port to userspace with libusb
+ - review by the USB developer community
+
+Please send any patches for this driver to Greg Kroah-Hartman <greg@kroah.com>
+and David Taht <d@teklibre.com>.
diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c
new file mode 100644
index 000000000000..6136e3f8762d
--- /dev/null
+++ b/drivers/staging/frontier/alphatrack.c
@@ -0,0 +1,853 @@
+/*
+ * Frontier Designs Alphatrack driver
+ *
+ * Copyright (C) 2007 Michael Taht (m@taht.net)
+ *
+ * Based on the usbled driver and ldusb drivers by
+ *
+ * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
+ *
+ * The ldusb driver was, in turn, derived from Lego USB Tower driver
+ * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
+ * 2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+/**
+ * This driver uses a ring buffer for time critical reading of
+ * interrupt in reports and provides read and write methods for
+ * raw interrupt reports.
+ */
+
+/* Note: this currently uses a dumb ringbuffer for reads and writes.
+ * A more optimal driver would cache and kill off outstanding urbs that are
+ * now invalid, and ignore ones that already were in the queue but valid
+ * as we only have 30 commands for the alphatrack. In particular this is
+ * key for getting lights to flash in time as otherwise many commands
+ * can be buffered up before the light change makes it to the interface.
+*/
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/version.h>
+
+#include <asm/uaccess.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+
+#include "surface_sysfs.h"
+
+/* make this work on older kernel versions */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+#include "frontier_compat.h"
+#endif /* older kernel versions */
+
+#include "alphatrack.h"
+
+#define VENDOR_ID 0x165b
+#define PRODUCT_ID 0xfad1
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define USB_ALPHATRACK_MINOR_BASE 0
+#else
+// FIXME 176 - is another driver's minor - apply for that
+// #define USB_ALPHATRACK_MINOR_BASE 177
+#define USB_ALPHATRACK_MINOR_BASE 176
+#endif
+
+/* table of devices that work with this driver */
+static struct usb_device_id usb_alphatrack_table [] = {
+ { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, usb_alphatrack_table);
+MODULE_VERSION("0.40");
+MODULE_AUTHOR("Mike Taht <m@taht.net>");
+MODULE_DESCRIPTION("Alphatrack USB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Frontier Designs Alphatrack Control Surface");
+
+/* These aren't done yet */
+
+#define SUPPRESS_EXTRA_ONLINE_EVENTS 0
+#define BUFFERED_WRITES 0
+#define SUPPRESS_EXTRA_OFFLINE_EVENTS 0
+#define COMPRESS_FADER_EVENTS 0
+
+#define BUFFERED_READS 1
+#define RING_BUFFER_SIZE 512
+#define WRITE_BUFFER_SIZE 34
+#define ALPHATRACK_USB_TIMEOUT 10
+#define OUTPUT_CMD_SIZE 8
+#define INPUT_CMD_SIZE 12
+
+
+static int debug = 0;
+
+/* Use our own dbg macro */
+#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
+
+#define alphatrack_ocmd_info(dev, cmd, format, arg...)
+
+#define alphatrack_icmd_info(dev, cmd, format, arg...)
+
+
+/* Module parameters */
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+/* All interrupt in transfers are collected in a ring buffer to
+ * avoid racing conditions and get better performance of the driver.
+ */
+
+static int ring_buffer_size = RING_BUFFER_SIZE;
+
+module_param(ring_buffer_size, int, S_IRUGO);
+MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size");
+
+/* The write_buffer can one day contain more than one interrupt out transfer.
+ */
+
+static int write_buffer_size = WRITE_BUFFER_SIZE;
+module_param(write_buffer_size, int, S_IRUGO);
+MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
+
+/*
+ * Increase the interval for debugging purposes.
+ * or set to 1 to use the standard interval from the endpoint descriptors.
+ */
+
+static int min_interrupt_in_interval = ALPHATRACK_USB_TIMEOUT;
+module_param(min_interrupt_in_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms");
+
+static int min_interrupt_out_interval = ALPHATRACK_USB_TIMEOUT;
+module_param(min_interrupt_out_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms");
+
+
+
+/* Structure to hold all of our device specific stuff */
+
+struct usb_alphatrack {
+ struct semaphore sem; /* locks this structure */
+ struct usb_interface* intf; /* save off the usb interface pointer */
+ int open_count; /* number of times this port has been opened */
+
+ struct alphatrack_icmd (*ring_buffer)[RING_BUFFER_SIZE]; /* just make c happy */
+ struct alphatrack_ocmd (*write_buffer)[WRITE_BUFFER_SIZE]; /* just make c happy */
+ unsigned int ring_head;
+ unsigned int ring_tail;
+
+ wait_queue_head_t read_wait;
+ wait_queue_head_t write_wait;
+
+ unsigned char* interrupt_in_buffer;
+ unsigned char* oldi_buffer;
+ struct usb_endpoint_descriptor* interrupt_in_endpoint;
+ struct urb* interrupt_in_urb;
+ int interrupt_in_interval;
+ size_t interrupt_in_endpoint_size;
+ int interrupt_in_running;
+ int interrupt_in_done;
+
+ char* interrupt_out_buffer;
+ struct usb_endpoint_descriptor* interrupt_out_endpoint;
+ struct urb* interrupt_out_urb;
+ int interrupt_out_interval;
+ size_t interrupt_out_endpoint_size;
+ int interrupt_out_busy;
+
+ atomic_t writes_pending;
+ int event; /* alternate interface to events */
+ int fader; /* 10 bits */
+ int lights; /* 23 bits */
+ unsigned char dump_state; /* 0 if disabled 1 if enabled */
+ unsigned char enable; /* 0 if disabled 1 if enabled */
+ unsigned char offline; /* if the device is out of range or asleep */
+ unsigned char verbose; /* be verbose in error reporting */
+ unsigned char last_cmd[OUTPUT_CMD_SIZE];
+ unsigned char screen[32];
+};
+
+/* prevent races between open() and disconnect() */
+static DEFINE_MUTEX(disconnect_mutex);
+
+/* forward declaration */
+
+static struct usb_driver usb_alphatrack_driver;
+
+/**
+ * usb_alphatrack_abort_transfers
+ * aborts transfers and frees associated data structures
+ */
+static void usb_alphatrack_abort_transfers(struct usb_alphatrack *dev)
+{
+ /* shutdown transfer */
+ if (dev->interrupt_in_running) {
+ dev->interrupt_in_running = 0;
+ if (dev->intf)
+ usb_kill_urb(dev->interrupt_in_urb);
+ }
+ if (dev->interrupt_out_busy)
+ if (dev->intf)
+ usb_kill_urb(dev->interrupt_out_urb);
+}
+
+/**
+ * usb_alphatrack_delete
+ */
+static void usb_alphatrack_delete(struct usb_alphatrack *dev)
+{
+ usb_alphatrack_abort_transfers(dev);
+ usb_free_urb(dev->interrupt_in_urb);
+ usb_free_urb(dev->interrupt_out_urb);
+ kfree(dev->ring_buffer);
+ kfree(dev->interrupt_in_buffer);
+ kfree(dev->interrupt_out_buffer);
+ kfree(dev); // fixme oldi_buffer
+}
+
+/**
+ * usb_alphatrack_interrupt_in_callback
+ */
+
+static void usb_alphatrack_interrupt_in_callback(struct urb *urb)
+{
+ struct usb_alphatrack *dev = urb->context;
+ unsigned int next_ring_head;
+ int retval = -1;
+
+ if (urb->status) {
+ if (urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN) {
+ goto exit;
+ } else {
+ dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
+ __func__, urb->status);
+ goto resubmit; /* maybe we can recover */
+ }
+ }
+
+ if (urb->actual_length != INPUT_CMD_SIZE) {
+ dev_warn(&dev->intf->dev,
+ "Urb length was %d bytes!! Do something intelligent \n", urb->actual_length);
+ } else {
+ alphatrack_ocmd_info(&dev->intf->dev,&(*dev->ring_buffer)[dev->ring_tail].cmd,"%s", "bla");
+ if(memcmp(dev->interrupt_in_buffer,dev->oldi_buffer,INPUT_CMD_SIZE)==0) {
+ goto resubmit;
+ }
+ memcpy(dev->oldi_buffer,dev->interrupt_in_buffer,INPUT_CMD_SIZE);
+
+#if SUPPRESS_EXTRA_OFFLINE_EVENTS
+ if(dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) { goto resubmit; }
+ if(dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 2; goto resubmit; }
+/* Always pass one offline event up the stack */
+ if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; }
+ if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; }
+#endif
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail);
+ next_ring_head = (dev->ring_head+1) % ring_buffer_size;
+
+ if (next_ring_head != dev->ring_tail) {
+ memcpy(&((*dev->ring_buffer)[dev->ring_head]),
+ dev->interrupt_in_buffer, urb->actual_length);
+ dev->ring_head = next_ring_head;
+ retval = 0;
+ memset(dev->interrupt_in_buffer, 0, urb->actual_length);
+ } else {
+ dev_warn(&dev->intf->dev,
+ "Ring buffer overflow, %d bytes dropped\n",
+ urb->actual_length);
+ memset(dev->interrupt_in_buffer, 0, urb->actual_length);
+ }
+ }
+
+resubmit:
+ /* resubmit if we're still running */
+ if (dev->interrupt_in_running && dev->intf) {
+ retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&dev->intf->dev,
+ "usb_submit_urb failed (%d)\n", retval);
+ }
+
+exit:
+ dev->interrupt_in_done = 1;
+ wake_up_interruptible(&dev->read_wait);
+}
+
+/**
+ * usb_alphatrack_interrupt_out_callback
+ */
+static void usb_alphatrack_interrupt_out_callback(struct urb *urb)
+{
+ struct usb_alphatrack *dev = urb->context;
+
+ /* sync/async unlink faults aren't errors */
+ if (urb->status && !(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ dbg_info(&dev->intf->dev,
+ "%s - nonzero write interrupt status received: %d\n",
+ __func__, urb->status);
+ atomic_dec(&dev->writes_pending);
+ dev->interrupt_out_busy = 0;
+ wake_up_interruptible(&dev->write_wait);
+}
+
+/**
+ * usb_alphatrack_open
+ */
+static int usb_alphatrack_open(struct inode *inode, struct file *file)
+{
+ struct usb_alphatrack *dev;
+ int subminor;
+ int retval = 0;
+ struct usb_interface *interface;
+
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
+
+ mutex_lock(&disconnect_mutex);
+
+ interface = usb_find_interface(&usb_alphatrack_driver, subminor);
+
+ if (!interface) {
+ err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto unlock_disconnect_exit;
+ }
+
+ dev = usb_get_intfdata(interface);
+
+ if (!dev) {
+ retval = -ENODEV;
+ goto unlock_disconnect_exit;
+ }
+
+ /* lock this device */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto unlock_disconnect_exit;
+ }
+
+ /* allow opening only once */
+ if (dev->open_count) {
+ retval = -EBUSY;
+ goto unlock_exit;
+ }
+ dev->open_count = 1;
+
+ /* initialize in direction */
+ dev->ring_head = 0;
+ dev->ring_tail = 0;
+ usb_fill_int_urb(dev->interrupt_in_urb,
+ interface_to_usbdev(interface),
+ usb_rcvintpipe(interface_to_usbdev(interface),
+ dev->interrupt_in_endpoint->bEndpointAddress),
+ dev->interrupt_in_buffer,
+ dev->interrupt_in_endpoint_size,
+ usb_alphatrack_interrupt_in_callback,
+ dev,
+ dev->interrupt_in_interval);
+
+ dev->interrupt_in_running = 1;
+ dev->interrupt_in_done = 0;
+ dev->enable = 1;
+ dev->offline = 0;
+
+ retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval);
+ dev->interrupt_in_running = 0;
+ dev->open_count = 0;
+ goto unlock_exit;
+ }
+
+ /* save device in the file's private structure */
+ file->private_data = dev;
+
+
+unlock_exit:
+ up(&dev->sem);
+
+unlock_disconnect_exit:
+ mutex_unlock(&disconnect_mutex);
+
+ return retval;
+}
+
+/**
+ * usb_alphatrack_release
+ */
+static int usb_alphatrack_release(struct inode *inode, struct file *file)
+{
+ struct usb_alphatrack *dev;
+ int retval = 0;
+
+ dev = file->private_data;
+
+ if (dev == NULL) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ if (dev->open_count != 1) {
+ retval = -ENODEV;
+ goto unlock_exit;
+ }
+
+ if (dev->intf == NULL) {
+ /* the device was unplugged before the file was released */
+ up(&dev->sem);
+ /* unlock here as usb_alphatrack_delete frees dev */
+ usb_alphatrack_delete(dev);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ /* wait until write transfer is finished */
+ if (dev->interrupt_out_busy)
+ wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ);
+ usb_alphatrack_abort_transfers(dev);
+ dev->open_count = 0;
+
+unlock_exit:
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/**
+ * usb_alphatrack_poll
+ */
+static unsigned int usb_alphatrack_poll(struct file *file, poll_table *wait)
+{
+ struct usb_alphatrack *dev;
+ unsigned int mask = 0;
+
+ dev = file->private_data;
+
+ poll_wait(file, &dev->read_wait, wait);
+ poll_wait(file, &dev->write_wait, wait);
+
+ if (dev->ring_head != dev->ring_tail)
+ mask |= POLLIN | POLLRDNORM;
+ if (!dev->interrupt_out_busy)
+ mask |= POLLOUT | POLLWRNORM;
+
+ return mask;
+}
+
+/**
+ * usb_alphatrack_read
+ */
+static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct usb_alphatrack *dev;
+ int retval = 0;
+
+ int c = 0;
+
+ dev = file->private_data;
+
+ /* verify that we actually have some data to read */
+ if (count == 0)
+ goto exit;
+
+ /* lock this object */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* verify that the device wasn't unplugged */
+ if (dev->intf == NULL) {
+ retval = -ENODEV;
+ err("No device or device unplugged %d\n", retval);
+ goto unlock_exit;
+ }
+
+ while (dev->ring_head == dev->ring_tail) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto unlock_exit;
+ }
+ dev->interrupt_in_done = 0 ;
+ retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
+ if (retval < 0) {
+ goto unlock_exit;
+ }
+ }
+
+ alphatrack_ocmd_info(&dev->intf->dev, &(*dev->ring_buffer)[dev->ring_tail].cmd, "%s", ": copying to userspace");
+
+ c = 0;
+ while((c < count) && (dev->ring_tail != dev->ring_head)) {
+ if (copy_to_user(&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], INPUT_CMD_SIZE)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+ dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
+ c+=INPUT_CMD_SIZE;
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail);
+ }
+ retval = c;
+
+unlock_exit:
+ /* unlock the device */
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/**
+ * usb_alphatrack_write
+ */
+static ssize_t usb_alphatrack_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct usb_alphatrack *dev;
+ size_t bytes_to_write;
+ int retval = 0;
+
+ dev = file->private_data;
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ goto exit;
+
+ /* lock this object */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* verify that the device wasn't unplugged */
+ if (dev->intf == NULL) {
+ retval = -ENODEV;
+ err("No device or device unplugged %d\n", retval);
+ goto unlock_exit;
+ }
+
+ /* wait until previous transfer is finished */
+ if (dev->interrupt_out_busy) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto unlock_exit;
+ }
+ retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy);
+ if (retval < 0) {
+ goto unlock_exit;
+ }
+ }
+
+ /* write the data into interrupt_out_buffer from userspace */
+ /* FIXME - if you write more than 12 bytes this breaks */
+ bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
+ if (bytes_to_write < count)
+ dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
+
+ dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write);
+
+ if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+
+ if (dev->interrupt_out_endpoint == NULL) {
+ err("Endpoint should not be be null! \n");
+ goto unlock_exit;
+ }
+
+ /* send off the urb */
+ usb_fill_int_urb(dev->interrupt_out_urb,
+ interface_to_usbdev(dev->intf),
+ usb_sndintpipe(interface_to_usbdev(dev->intf),
+ dev->interrupt_out_endpoint->bEndpointAddress),
+ dev->interrupt_out_buffer,
+ bytes_to_write,
+ usb_alphatrack_interrupt_out_callback,
+ dev,
+ dev->interrupt_out_interval);
+ dev->interrupt_out_busy = 1;
+ atomic_inc(&dev->writes_pending);
+ wmb();
+
+ retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
+ if (retval) {
+ dev->interrupt_out_busy = 0;
+ err("Couldn't submit interrupt_out_urb %d\n", retval);
+ atomic_dec(&dev->writes_pending);
+ goto unlock_exit;
+ }
+ retval = bytes_to_write;
+
+unlock_exit:
+ /* unlock the device */
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/* file operations needed when we register this driver */
+static const struct file_operations usb_alphatrack_fops = {
+ .owner = THIS_MODULE,
+ .read = usb_alphatrack_read,
+ .write = usb_alphatrack_write,
+ .open = usb_alphatrack_open,
+ .release = usb_alphatrack_release,
+ .poll = usb_alphatrack_poll,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+
+static struct usb_class_driver usb_alphatrack_class = {
+ .name = "alphatrack%d",
+ .fops = &usb_alphatrack_fops,
+ .minor_base = USB_ALPHATRACK_MINOR_BASE,
+};
+
+
+/**
+ * usb_alphatrack_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int usb_alphatrack_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_alphatrack *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+ int true_size;
+ int retval = -ENOMEM;
+
+ /* allocate memory for our device state and intialize it */
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ dev_err(&intf->dev, "Out of memory\n");
+ goto exit;
+ }
+ init_MUTEX(&dev->sem);
+ dev->intf = intf;
+ init_waitqueue_head(&dev->read_wait);
+ init_waitqueue_head(&dev->write_wait);
+
+ iface_desc = intf->cur_altsetting;
+
+ /* set up the endpoint information */
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (usb_endpoint_is_int_in(endpoint))
+ dev->interrupt_in_endpoint = endpoint;
+
+ if (usb_endpoint_is_int_out(endpoint))
+ dev->interrupt_out_endpoint = endpoint;
+ }
+ if (dev->interrupt_in_endpoint == NULL) {
+ dev_err(&intf->dev, "Interrupt in endpoint not found\n");
+ goto error;
+ }
+ if (dev->interrupt_out_endpoint == NULL)
+ dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
+
+ dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
+
+ if (dev->interrupt_in_endpoint_size != 64)
+ dev_warn(&intf->dev, "Interrupt in endpoint size is not 64!\n");
+
+ if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; }
+
+ true_size = min(ring_buffer_size,RING_BUFFER_SIZE);
+
+ /* FIXME - there are more usb_alloc routines for dma correctness. Needed? */
+
+// dev->ring_buffer = kmalloc((true_size*sizeof(struct alphatrack_icmd))+12, GFP_KERNEL);
+ dev->ring_buffer = kmalloc((true_size*sizeof(struct alphatrack_icmd)), GFP_KERNEL);
+
+ if (!dev->ring_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate input ring_buffer of size %d\n",true_size);
+ goto error;
+ }
+
+ dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
+
+ if (!dev->interrupt_in_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n");
+ goto error;
+ }
+ dev->oldi_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
+ if (!dev->oldi_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate old buffer\n");
+ goto error;
+ }
+ dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->interrupt_in_urb) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
+ goto error;
+ }
+
+ dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) :
+ udev->descriptor.bMaxPacketSize0;
+
+ if (dev->interrupt_out_endpoint_size !=64)
+ dev_warn(&intf->dev, "Interrupt out endpoint size is not 64!)\n");
+
+ if(write_buffer_size == 0) { write_buffer_size = WRITE_BUFFER_SIZE; }
+ true_size = min(write_buffer_size,WRITE_BUFFER_SIZE);
+
+ dev->interrupt_out_buffer = kmalloc(true_size*dev->interrupt_out_endpoint_size, GFP_KERNEL);
+
+ if (!dev->interrupt_out_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n");
+ goto error;
+ }
+
+ dev->write_buffer = kmalloc(sizeof(struct alphatrack_ocmd)*true_size, GFP_KERNEL);
+
+ if (!dev->write_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate write_buffer \n");
+ goto error;
+ }
+
+ dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->interrupt_out_urb) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
+ goto error;
+ }
+ dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
+ if (dev->interrupt_out_endpoint)
+ dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
+
+ /* we can register the device now, as it is ready */
+ usb_set_intfdata(intf, dev);
+
+ atomic_set(&dev->writes_pending,0);
+ retval = usb_register_dev(intf, &usb_alphatrack_class);
+ if (retval) {
+ /* something prevented us from registering this driver */
+ dev_err(&intf->dev, "Not able to get a minor for this device.\n");
+ usb_set_intfdata(intf, NULL);
+ goto error;
+ }
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&intf->dev, "Alphatrack Device #%d now attached to major %d minor %d\n",
+ (intf->minor - USB_ALPHATRACK_MINOR_BASE), USB_MAJOR, intf->minor);
+
+exit:
+ return retval;
+
+error:
+ usb_alphatrack_delete(dev);
+
+ return retval;
+}
+
+/**
+ * usb_alphatrack_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ */
+static void usb_alphatrack_disconnect(struct usb_interface *intf)
+{
+ struct usb_alphatrack *dev;
+ int minor;
+
+ mutex_lock(&disconnect_mutex);
+
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
+
+ down(&dev->sem);
+
+ minor = intf->minor;
+
+ /* give back our minor */
+ usb_deregister_dev(intf, &usb_alphatrack_class);
+
+ /* if the device is not opened, then we clean up right now */
+ if (!dev->open_count) {
+ up(&dev->sem);
+ usb_alphatrack_delete(dev);
+ } else {
+ dev->intf = NULL;
+ up(&dev->sem);
+ }
+
+ atomic_set(&dev->writes_pending,0);
+ mutex_unlock(&disconnect_mutex);
+
+ dev_info(&intf->dev, "Alphatrack Surface #%d now disconnected\n",
+ (minor - USB_ALPHATRACK_MINOR_BASE));
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver usb_alphatrack_driver = {
+ .name = "alphatrack",
+ .probe = usb_alphatrack_probe,
+ .disconnect = usb_alphatrack_disconnect,
+ .id_table = usb_alphatrack_table,
+};
+
+/**
+ * usb_alphatrack_init
+ */
+static int __init usb_alphatrack_init(void)
+{
+ int retval;
+
+ /* register this driver with the USB subsystem */
+ retval = usb_register(&usb_alphatrack_driver);
+ if (retval)
+ err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval);
+
+ return retval;
+}
+
+/**
+ * usb_alphatrack_exit
+ */
+static void __exit usb_alphatrack_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&usb_alphatrack_driver);
+}
+
+module_init(usb_alphatrack_init);
+module_exit(usb_alphatrack_exit);
+
diff --git a/drivers/staging/frontier/alphatrack.h b/drivers/staging/frontier/alphatrack.h
new file mode 100644
index 000000000000..35c90a90eb08
--- /dev/null
+++ b/drivers/staging/frontier/alphatrack.h
@@ -0,0 +1,92 @@
+#define show_set_bit(a) show_set_mbit(alphatrack,a)
+#define show_set_cmd(a) show_set_mcmd(alphatrack,a)
+#define show_set_int(a) show_set_mint(alphatrack,a)
+#define show_set_char(a) show_set_mchar(alphatrack,a)
+#define show_set_light(a) show_set_ebit(alphatrack,LightID,lights,a)
+#define show_set_button(a) show_set_ebit(alphatrack,ButtonID,button,a)
+
+struct alphatrack_icmd {
+ unsigned char cmd[12];
+};
+
+struct alphatrack_ocmd {
+ unsigned char cmd[8];
+};
+
+enum LightID {
+ LIGHT_EQ = 0,
+ LIGHT_OUT,
+ LIGHT_F2,
+ LIGHT_SEND,
+ LIGHT_IN,
+ LIGHT_F1,
+ LIGHT_PAN,
+ LIGHT_UNDEF1,
+ LIGHT_UNDEF2,
+ LIGHT_SHIFT,
+ LIGHT_TRACKMUTE,
+ LIGHT_TRACKSOLO,
+ LIGHT_TRACKREC,
+ LIGHT_READ,
+ LIGHT_WRITE,
+ LIGHT_ANYSOLO,
+ LIGHT_AUTO,
+ LIGHT_F4,
+ LIGHT_RECORD,
+ LIGHT_WINDOW,
+ LIGHT_PLUGIN,
+ LIGHT_F3,
+ LIGHT_LOOP
+};
+
+#define BUTTONMASK_BATTERY 0x00004000
+#define BUTTONMASK_BACKLIGHT 0x00008000
+#define BUTTONMASK_FASTFORWARD 0x04000000
+#define BUTTONMASK_TRACKMUTE 0x00040000
+#define BUTTONMASK_TRACKSOLO 0x00800000
+#define BUTTONMASK_TRACKLEFT 0x80000000
+#define BUTTONMASK_RECORD 0x02000000
+#define BUTTONMASK_SHIFT 0x20000000
+#define BUTTONMASK_PUNCH 0x00800000
+#define BUTTONMASK_TRACKRIGHT 0x00020000
+#define BUTTONMASK_REWIND 0x01000000
+#define BUTTONMASK_STOP 0x10000000
+#define BUTTONMASK_LOOP 0x00010000
+#define BUTTONMASK_TRACKREC 0x00001000
+#define BUTTONMASK_PLAY 0x08000000
+#define BUTTONMASK_TOUCH1 0x00000008
+#define BUTTONMASK_TOUCH2 0x00000010
+#define BUTTONMASK_TOUCH3 0x00000020
+
+#define BUTTONMASK_PRESS1 0x00000009
+#define BUTTONMASK_PRESS2 0x00008010
+#define BUTTONMASK_PRESS3 0x00002020
+
+// last 3 bytes are the slider position
+// 40 is the actual slider moving, the most sig bits, and 3 lsb
+
+#define BUTTONMASK_FLIP 0x40000000
+#define BUTTONMASK_F1 0x00100000
+#define BUTTONMASK_F2 0x00400000
+#define BUTTONMASK_F3 0x00200000
+#define BUTTONMASK_F4 0x00080000
+#define BUTTONMASK_PAN 0x00000200
+#define BUTTONMASK_SEND 0x00000800
+#define BUTTONMASK_EQ 0x00004000
+#define BUTTONMASK_PLUGIN 0x00000400
+#define BUTTONMASK_AUTO 0x00000100
+
+
+// #define BUTTONMASK_FOOTSWITCH FIXME
+
+// Lookup. name. midi out. midi in.
+
+struct buttonmap_t {
+ u32 mask;
+ short midi_in;
+ short midi_out;
+ char *name;
+// void (*function) (buttonmap_t *);
+ void (*function) (void);
+};
+
diff --git a/drivers/staging/frontier/frontier_compat.h b/drivers/staging/frontier/frontier_compat.h
new file mode 100644
index 000000000000..00450e637ac8
--- /dev/null
+++ b/drivers/staging/frontier/frontier_compat.h
@@ -0,0 +1,63 @@
+/* USB defines for older kernels */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+
+static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_INT);
+}
+
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+
+static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+
+static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
+}
+
+#endif /* older kernel versions */
diff --git a/drivers/staging/frontier/surface_sysfs.h b/drivers/staging/frontier/surface_sysfs.h
new file mode 100644
index 000000000000..d50a562d658a
--- /dev/null
+++ b/drivers/staging/frontier/surface_sysfs.h
@@ -0,0 +1,100 @@
+/* If you are going to abuse the preprocessor, why not ABUSE the preprocessor?
+ I stuck this header in a separate file so I don't have to look at it */
+
+// FIXME Need locking or atomic ops
+
+#define show_set_mbit(dname,value,bit) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ int temp = (1 && (t->value & (1 << bit))); \
+ return sprintf(buf, "%d\n", temp); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ if(temp > 0) { long b = 1 << bit; t->value |= b; } \
+ else { long b = ~(1 << bit); t->value &= b ; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+#define show_set_ebit(dname,enumname,value,bit) \
+static ssize_t show_##bit(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ enum enumname l = bit; \
+ int temp = t->value & (1 << l); \
+ return sprintf(buf, "%d\n", temp); \
+} \
+static ssize_t set_##bit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ enum enumname l = bit;\
+ long b = 1 << l; \
+ if(temp > 0) { t->value |= b; } \
+ else { t->value &= ~b ; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+// FIXME FOR CORRECTLY SETTING HEX from a string
+#define show_set_mcmd(dname,value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ int count = 0;\
+ int i; \
+ for (i = 0,i<sizeof(dname); i++) count += snprintf(buf, "%02x",t->dname[i]); \
+ return(count);\
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+#define show_set_mint(dname,value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ return sprintf(buf, "%d\n", t->value); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+#define show_set_mchar(dname,value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ return sprintf(buf, "%c\n", t->value); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_##dname *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c
new file mode 100644
index 000000000000..79abb6b16f74
--- /dev/null
+++ b/drivers/staging/frontier/tranzport.c
@@ -0,0 +1,1006 @@
+/*
+ * Frontier Designs Tranzport driver
+ *
+ * Copyright (C) 2007 Michael Taht (m@taht.net)
+ *
+ * Based on the usbled driver and ldusb drivers by
+ *
+ * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
+ *
+ * The ldusb driver was, in turn, derived from Lego USB Tower driver
+ * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
+ * 2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+/**
+ * This driver uses a ring buffer for time critical reading of
+ * interrupt in reports and provides read and write methods for
+ * raw interrupt reports.
+ */
+
+/* Note: this currently uses a dumb ringbuffer for reads and writes.
+ * A more optimal driver would cache and kill off outstanding urbs that are
+ * now invalid, and ignore ones that already were in the queue but valid
+ * as we only have 17 commands for the tranzport. In particular this is
+ * key for getting lights to flash in time as otherwise many commands
+ * can be buffered up before the light change makes it to the interface.
+*/
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/version.h>
+
+#include <asm/uaccess.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+#include frontier_compat.h
+#endif
+
+/* Define these values to match your devices */
+#define VENDOR_ID 0x165b
+#define PRODUCT_ID 0x8101
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define USB_TRANZPORT_MINOR_BASE 0
+#else
+// FIXME 176 - is the ldusb driver's minor - apply for a minor soon
+#define USB_TRANZPORT_MINOR_BASE 177
+#endif
+
+/* table of devices that work with this driver */
+static struct usb_device_id usb_tranzport_table [] = {
+ { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, usb_tranzport_table);
+MODULE_VERSION("0.33");
+MODULE_AUTHOR("Mike Taht <m@taht.net>");
+MODULE_DESCRIPTION("Tranzport USB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Frontier Designs Tranzport Control Surface");
+
+/* These two aren't done yet */
+
+#define SUPPRESS_EXTRA_ONLINE_EVENTS 0
+#define BUFFERED_WRITES 0
+
+#define SUPPRESS_EXTRA_OFFLINE_EVENTS 1
+#define COMPRESS_WHEEL_EVENTS 1
+#define BUFFERED_READS 1
+#define RING_BUFFER_SIZE 1000
+#define WRITE_BUFFER_SIZE 34
+#define TRANZPORT_USB_TIMEOUT 10
+
+
+static int debug = 0;
+
+/* Use our own dbg macro */
+#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
+
+/* Module parameters */
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+/* All interrupt in transfers are collected in a ring buffer to
+ * avoid racing conditions and get better performance of the driver.
+ */
+
+static int ring_buffer_size = RING_BUFFER_SIZE;
+
+module_param(ring_buffer_size, int, S_IRUGO);
+MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports");
+
+/* The write_buffer can one day contain more than one interrupt out transfer.
+ */
+static int write_buffer_size = WRITE_BUFFER_SIZE;
+module_param(write_buffer_size, int, S_IRUGO);
+MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
+
+/*
+ * Increase the interval for debugging purposes.
+ * or set to 1 to use the standard interval from the endpoint descriptors.
+ */
+
+static int min_interrupt_in_interval = TRANZPORT_USB_TIMEOUT;
+module_param(min_interrupt_in_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms");
+
+static int min_interrupt_out_interval = TRANZPORT_USB_TIMEOUT;
+module_param(min_interrupt_out_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms");
+
+struct tranzport_cmd {
+ unsigned char cmd[8];
+};
+
+enum LightID {
+ LightRecord = 0,
+ LightTrackrec,
+ LightTrackmute,
+ LightTracksolo,
+ LightAnysolo,
+ LightLoop,
+ LightPunch
+ };
+
+/* Structure to hold all of our device specific stuff */
+
+struct usb_tranzport {
+ struct semaphore sem; /* locks this structure */
+ struct usb_interface* intf; /* save off the usb interface pointer */
+
+ int open_count; /* number of times this port has been opened */
+
+ struct tranzport_cmd (*ring_buffer)[RING_BUFFER_SIZE]; /* just make c happy */
+ unsigned int ring_head;
+ unsigned int ring_tail;
+
+ wait_queue_head_t read_wait;
+ wait_queue_head_t write_wait;
+
+ unsigned char* interrupt_in_buffer;
+ struct usb_endpoint_descriptor* interrupt_in_endpoint;
+ struct urb* interrupt_in_urb;
+ int interrupt_in_interval;
+ size_t interrupt_in_endpoint_size;
+ int interrupt_in_running;
+ int interrupt_in_done;
+
+ char* interrupt_out_buffer;
+ struct usb_endpoint_descriptor* interrupt_out_endpoint;
+ struct urb* interrupt_out_urb;
+ int interrupt_out_interval;
+ size_t interrupt_out_endpoint_size;
+ int interrupt_out_busy;
+
+ /* Sysfs and translation support */
+
+ int event; /* alternate interface to events */
+ int wheel; /* - for negative, 0 for none, + for positive */
+ unsigned char dump_state; /* 0 if disabled 1 if enabled */
+ unsigned char enable; /* 0 if disabled 1 if enabled */
+ unsigned char offline; /* if the device is out of range or asleep */
+ unsigned char compress_wheel; /* flag to compress wheel events */
+ unsigned char light; /* 7 bits used */
+ unsigned char last_cmd[8];
+ unsigned char last_input[8];
+ unsigned char screen[40]; // We'll also have cells
+
+};
+
+/* prevent races between open() and disconnect() */
+static DEFINE_MUTEX(disconnect_mutex);
+
+static struct usb_driver usb_tranzport_driver;
+
+/**
+ * usb_tranzport_abort_transfers
+ * aborts transfers and frees associated data structures
+ */
+static void usb_tranzport_abort_transfers(struct usb_tranzport *dev)
+{
+ /* shutdown transfer */
+ if (dev->interrupt_in_running) {
+ dev->interrupt_in_running = 0;
+ if (dev->intf)
+ usb_kill_urb(dev->interrupt_in_urb);
+ }
+ if (dev->interrupt_out_busy)
+ if (dev->intf)
+ usb_kill_urb(dev->interrupt_out_urb);
+}
+
+// FIXME ~light not good enough or correct - need atomic set_bit
+
+#define show_set_light(value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ enum LightID light = value; \
+ int temp = (1 && (t->light & (1 << light))); \
+ return sprintf(buf, "%d\n", temp ); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ enum LightID light = (temp << value) & (t->light << value); \
+ t->light = (t->light & ~light) ; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+show_set_light(LightRecord);
+show_set_light(LightTrackrec);
+show_set_light(LightTrackmute);
+show_set_light(LightTracksolo);
+show_set_light(LightAnysolo);
+show_set_light(LightLoop);
+show_set_light(LightPunch);
+
+
+#define show_set_int(value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%d\n", t->value); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+show_set_int(enable);
+show_set_int(offline);
+show_set_int(compress_wheel);
+show_set_int(dump_state);
+show_set_int(wheel);
+show_set_int(event);
+
+#define show_set_cmd(value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%d\n", t->value); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+
+
+
+/**
+ * usb_tranzport_delete
+ */
+static void usb_tranzport_delete(struct usb_tranzport *dev)
+{
+ usb_tranzport_abort_transfers(dev);
+ /* This is just too twisted to be correct */
+ if(dev->intf != NULL) {
+ device_remove_file(&dev->intf->dev, &dev_attr_LightRecord);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTrackrec);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTracksolo);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightAnysolo);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightLoop);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightPunch);
+ device_remove_file(&dev->intf->dev, &dev_attr_wheel);
+ device_remove_file(&dev->intf->dev, &dev_attr_enable);
+ device_remove_file(&dev->intf->dev, &dev_attr_event);
+ device_remove_file(&dev->intf->dev, &dev_attr_offline);
+ device_remove_file(&dev->intf->dev, &dev_attr_compress_wheel);
+
+ device_remove_file(&dev->intf->dev, &dev_attr_dump_state);
+ }
+
+ /* free data structures */
+ usb_free_urb(dev->interrupt_in_urb);
+ usb_free_urb(dev->interrupt_out_urb);
+ kfree(dev->ring_buffer);
+ kfree(dev->interrupt_in_buffer);
+ kfree(dev->interrupt_out_buffer);
+ kfree(dev);
+}
+
+/**
+ * usb_tranzport_interrupt_in_callback
+ */
+
+static void usb_tranzport_interrupt_in_callback(struct urb *urb)
+{
+ struct usb_tranzport *dev = urb->context;
+ unsigned int next_ring_head;
+ int retval = -1;
+
+ if (urb->status) {
+ if (urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN) {
+ goto exit;
+ } else {
+ dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
+ __func__, urb->status);
+ goto resubmit; /* maybe we can recover */
+ }
+ }
+
+ if (urb->actual_length != 8) {
+ dev_warn(&dev->intf->dev,
+ "Urb length was %d bytes!! Do something intelligent \n", urb->actual_length);
+ } else {
+ dbg_info(&dev->intf->dev, "%s: received: %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ __func__, dev->interrupt_in_buffer[0],dev->interrupt_in_buffer[1],dev->interrupt_in_buffer[2],dev->interrupt_in_buffer[3],dev->interrupt_in_buffer[4],dev->interrupt_in_buffer[5],dev->interrupt_in_buffer[6],dev->interrupt_in_buffer[7]);
+#if SUPPRESS_EXTRA_OFFLINE_EVENTS
+ if(dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) { goto resubmit; }
+ if(dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 2; goto resubmit; }
+
+/* Always pass one offline event up the stack */
+ if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; }
+ if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; }
+
+#endif
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail);
+
+ next_ring_head = (dev->ring_head+1) % ring_buffer_size;
+
+ if (next_ring_head != dev->ring_tail) {
+ memcpy(&((*dev->ring_buffer)[dev->ring_head]), dev->interrupt_in_buffer, urb->actual_length);
+ dev->ring_head = next_ring_head;
+ retval = 0;
+ memset(dev->interrupt_in_buffer, 0, urb->actual_length);
+ } else {
+ dev_warn(&dev->intf->dev,
+ "Ring buffer overflow, %d bytes dropped\n",
+ urb->actual_length);
+ memset(dev->interrupt_in_buffer, 0, urb->actual_length);
+ }
+ }
+
+resubmit:
+ /* resubmit if we're still running */
+ if (dev->interrupt_in_running && dev->intf) {
+ retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&dev->intf->dev,
+ "usb_submit_urb failed (%d)\n", retval);
+ }
+
+exit:
+ dev->interrupt_in_done = 1;
+ wake_up_interruptible(&dev->read_wait);
+}
+
+/**
+ * usb_tranzport_interrupt_out_callback
+ */
+static void usb_tranzport_interrupt_out_callback(struct urb *urb)
+{
+ struct usb_tranzport *dev = urb->context;
+
+ /* sync/async unlink faults aren't errors */
+ if (urb->status && !(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ dbg_info(&dev->intf->dev,
+ "%s - nonzero write interrupt status received: %d\n",
+ __func__, urb->status);
+
+ dev->interrupt_out_busy = 0;
+ wake_up_interruptible(&dev->write_wait);
+}
+
+/**
+ * usb_tranzport_open
+ */
+static int usb_tranzport_open(struct inode *inode, struct file *file)
+{
+ struct usb_tranzport *dev;
+ int subminor;
+ int retval = 0;
+ struct usb_interface *interface;
+
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
+
+ mutex_lock(&disconnect_mutex);
+
+ interface = usb_find_interface(&usb_tranzport_driver, subminor);
+
+ if (!interface) {
+ err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto unlock_disconnect_exit;
+ }
+
+ dev = usb_get_intfdata(interface);
+
+ if (!dev) {
+ retval = -ENODEV;
+ goto unlock_disconnect_exit;
+ }
+
+ /* lock this device */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto unlock_disconnect_exit;
+ }
+
+ /* allow opening only once */
+ if (dev->open_count) {
+ retval = -EBUSY;
+ goto unlock_exit;
+ }
+ dev->open_count = 1;
+
+ /* initialize in direction */
+ dev->ring_head = 0;
+ dev->ring_tail = 0;
+ usb_fill_int_urb(dev->interrupt_in_urb,
+ interface_to_usbdev(interface),
+ usb_rcvintpipe(interface_to_usbdev(interface),
+ dev->interrupt_in_endpoint->bEndpointAddress),
+ dev->interrupt_in_buffer,
+ dev->interrupt_in_endpoint_size,
+ usb_tranzport_interrupt_in_callback,
+ dev,
+ dev->interrupt_in_interval);
+
+ dev->interrupt_in_running = 1;
+ dev->interrupt_in_done = 0;
+ dev->enable = 1;
+ dev->offline = 0;
+ dev->compress_wheel = 1;
+
+ retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval);
+ dev->interrupt_in_running = 0;
+ dev->open_count = 0;
+ goto unlock_exit;
+ }
+
+ /* save device in the file's private structure */
+ file->private_data = dev;
+
+
+unlock_exit:
+ up(&dev->sem);
+
+unlock_disconnect_exit:
+ mutex_unlock(&disconnect_mutex);
+
+ return retval;
+}
+
+/**
+ * usb_tranzport_release
+ */
+static int usb_tranzport_release(struct inode *inode, struct file *file)
+{
+ struct usb_tranzport *dev;
+ int retval = 0;
+
+ dev = file->private_data;
+
+ if (dev == NULL) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ if (dev->open_count != 1) {
+ retval = -ENODEV;
+ goto unlock_exit;
+ }
+
+ if (dev->intf == NULL) {
+ /* the device was unplugged before the file was released */
+ up(&dev->sem);
+ /* unlock here as usb_tranzport_delete frees dev */
+ usb_tranzport_delete(dev);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ /* wait until write transfer is finished */
+ if (dev->interrupt_out_busy)
+ wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ);
+ usb_tranzport_abort_transfers(dev);
+ dev->open_count = 0;
+
+unlock_exit:
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/**
+ * usb_tranzport_poll
+ */
+static unsigned int usb_tranzport_poll(struct file *file, poll_table *wait)
+{
+ struct usb_tranzport *dev;
+ unsigned int mask = 0;
+
+ dev = file->private_data;
+
+ poll_wait(file, &dev->read_wait, wait);
+ poll_wait(file, &dev->write_wait, wait);
+
+ if (dev->ring_head != dev->ring_tail)
+ mask |= POLLIN | POLLRDNORM;
+ if (!dev->interrupt_out_busy)
+ mask |= POLLOUT | POLLWRNORM;
+
+ return mask;
+}
+
+/**
+ * usb_tranzport_read
+ */
+static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct usb_tranzport *dev;
+ int retval = 0;
+
+#if BUFFERED_READS
+ int c = 0;
+#endif
+
+#if COMPRESS_WHEEL_EVENTS
+ signed char oldwheel;
+ signed char newwheel;
+ int cancompress = 1;
+ int next_tail;
+#endif
+
+/* do I have such a thing as a null event? */
+
+ dev = file->private_data;
+
+ /* verify that we actually have some data to read */
+ if (count == 0)
+ goto exit;
+
+ /* lock this object */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* verify that the device wasn't unplugged */
+ if (dev->intf == NULL) {
+ retval = -ENODEV;
+ err("No device or device unplugged %d\n", retval);
+ goto unlock_exit;
+ }
+
+ while (dev->ring_head == dev->ring_tail) {
+
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto unlock_exit;
+ }
+ // atomic_cmp_exchange(&dev->interrupt_in_done,0,0);
+ dev->interrupt_in_done = 0 ; /* tiny race - FIXME: make atomic? */
+ retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
+ if (retval < 0) {
+ goto unlock_exit;
+ }
+ }
+
+ dbg_info(&dev->intf->dev, "%s: copying to userspace: %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ __func__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
+
+#if BUFFERED_READS
+ c = 0;
+ while((c < count) && (dev->ring_tail != dev->ring_head)) {
+
+/* This started off in the lower level service routine, and I moved it here. Then my brain died. Not done yet. */
+#if COMPRESS_WHEEL_EVENTS
+ next_tail = (dev->ring_tail+1) % ring_buffer_size;
+ if(dev->compress_wheel) cancompress = 1;
+ while(dev->ring_head != next_tail && cancompress == 1 ) {
+ newwheel = (*dev->ring_buffer)[next_tail].cmd[6];
+ oldwheel = (*dev->ring_buffer)[dev->ring_tail].cmd[6];
+ // if both are wheel events, and no buttons have changes (FIXME, do I have to check?),
+ // and we are the same sign, we can compress +- 7F
+ // FIXME: saner check for overflow! - max of +- 7F
+ // FIXME the math is wrong for going in reverse, actually, as the midi spec doesn't allow signed chars
+
+ dbg_info(&dev->intf->dev, "%s: trying to compress: %02x%02x%02x%02x%02x %02x %02x %02x\n",
+ __func__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
+
+
+ if(((*dev->ring_buffer)[dev->ring_tail].cmd[6] != 0 &&
+ (*dev->ring_buffer)[next_tail].cmd[6] != 0 ) &&
+ ((newwheel > 0 && oldwheel > 0) ||
+ (newwheel < 0 && oldwheel < 0)) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[2] == (*dev->ring_buffer)[next_tail].cmd[2]) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[3] == (*dev->ring_buffer)[next_tail].cmd[3]) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[4] == (*dev->ring_buffer)[next_tail].cmd[4]) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[5] == (*dev->ring_buffer)[next_tail].cmd[5]))
+ {
+ dbg_info(&dev->intf->dev, "%s: should compress: %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ __func__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
+
+ newwheel += oldwheel;
+ if(oldwheel > 0 && !(newwheel > 0)) {
+ newwheel = 0x7f;
+ cancompress = 0;
+ }
+ if(oldwheel < 0 && !(newwheel < 0)) {
+ newwheel = 0x80;
+ cancompress = 0;
+ }
+
+ (*dev->ring_buffer)[next_tail].cmd[6] = newwheel;
+ dev->ring_tail = next_tail;
+ next_tail = (dev->ring_tail+1) % ring_buffer_size;
+ } else {
+ cancompress = 0;
+ }
+ }
+#endif /* COMPRESS_WHEEL_EVENTS */
+
+ if (copy_to_user(&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], 8)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+
+ dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
+ c+=8;
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail);
+ }
+ retval = c;
+
+#else
+ if (copy_to_user(buffer, &(*dev->ring_buffer)[dev->ring_tail], 8)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+
+ dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __func__,dev->ring_head,dev->ring_tail);
+
+ retval = 8;
+#endif /* BUFFERED_READS */
+
+unlock_exit:
+ /* unlock the device */
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/**
+ * usb_tranzport_write
+ */
+static ssize_t usb_tranzport_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct usb_tranzport *dev;
+ size_t bytes_to_write;
+ int retval = 0;
+
+ dev = file->private_data;
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ goto exit;
+
+ /* lock this object */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* verify that the device wasn't unplugged */
+ if (dev->intf == NULL) {
+ retval = -ENODEV;
+ err("No device or device unplugged %d\n", retval);
+ goto unlock_exit;
+ }
+
+ /* wait until previous transfer is finished */
+ if (dev->interrupt_out_busy) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto unlock_exit;
+ }
+ retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy);
+ if (retval < 0) {
+ goto unlock_exit;
+ }
+ }
+
+ /* write the data into interrupt_out_buffer from userspace */
+ bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
+ if (bytes_to_write < count)
+ dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
+
+ dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write);
+
+ if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+
+ if (dev->interrupt_out_endpoint == NULL) {
+ err("Endpoint should not be be null! \n");
+ goto unlock_exit;
+ }
+
+ /* send off the urb */
+ usb_fill_int_urb(dev->interrupt_out_urb,
+ interface_to_usbdev(dev->intf),
+ usb_sndintpipe(interface_to_usbdev(dev->intf),
+ dev->interrupt_out_endpoint->bEndpointAddress),
+ dev->interrupt_out_buffer,
+ bytes_to_write,
+ usb_tranzport_interrupt_out_callback,
+ dev,
+ dev->interrupt_out_interval);
+
+ dev->interrupt_out_busy = 1;
+ wmb();
+
+ retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
+ if (retval) {
+ dev->interrupt_out_busy = 0;
+ err("Couldn't submit interrupt_out_urb %d\n", retval);
+ goto unlock_exit;
+ }
+ retval = bytes_to_write;
+
+unlock_exit:
+ /* unlock the device */
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/* file operations needed when we register this driver */
+static const struct file_operations usb_tranzport_fops = {
+ .owner = THIS_MODULE,
+ .read = usb_tranzport_read,
+ .write = usb_tranzport_write,
+ .open = usb_tranzport_open,
+ .release = usb_tranzport_release,
+ .poll = usb_tranzport_poll,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+static struct usb_class_driver usb_tranzport_class = {
+ .name = "tranzport%d",
+ .fops = &usb_tranzport_fops,
+ .minor_base = USB_TRANZPORT_MINOR_BASE,
+};
+
+
+/**
+ * usb_tranzport_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_tranzport *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+ int true_size;
+ int retval = -ENOMEM;
+
+ /* allocate memory for our device state and intialize it */
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ dev_err(&intf->dev, "Out of memory\n");
+ goto exit;
+ }
+ init_MUTEX(&dev->sem);
+ dev->intf = intf;
+ init_waitqueue_head(&dev->read_wait);
+ init_waitqueue_head(&dev->write_wait);
+
+ iface_desc = intf->cur_altsetting;
+
+ /* set up the endpoint information */
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (usb_endpoint_is_int_in(endpoint))
+ dev->interrupt_in_endpoint = endpoint;
+
+ if (usb_endpoint_is_int_out(endpoint))
+ dev->interrupt_out_endpoint = endpoint;
+ }
+ if (dev->interrupt_in_endpoint == NULL) {
+ dev_err(&intf->dev, "Interrupt in endpoint not found\n");
+ goto error;
+ }
+ if (dev->interrupt_out_endpoint == NULL)
+ dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
+
+
+ dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
+
+ if (dev->interrupt_in_endpoint_size != 8)
+ dev_warn(&intf->dev, "Interrupt in endpoint size is not 8!\n");
+
+ if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; }
+ true_size = min(ring_buffer_size,RING_BUFFER_SIZE);
+ /* FIXME - there are more usb_alloc routines for dma correctness. Needed? */
+
+ dev->ring_buffer = kmalloc((true_size*sizeof(struct tranzport_cmd))+8, GFP_KERNEL);
+
+ if (!dev->ring_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate ring_buffer of size %d\n",true_size);
+ goto error;
+ }
+ dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
+ if (!dev->interrupt_in_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n");
+ goto error;
+ }
+ dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->interrupt_in_urb) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
+ goto error;
+ }
+ dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) :
+ udev->descriptor.bMaxPacketSize0;
+
+ if (dev->interrupt_out_endpoint_size !=8)
+ dev_warn(&intf->dev, "Interrupt out endpoint size is not 8!)\n");
+
+ dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL);
+ if (!dev->interrupt_out_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n");
+ goto error;
+ }
+ dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->interrupt_out_urb) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
+ goto error;
+ }
+ dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
+ if (dev->interrupt_out_endpoint)
+ dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
+
+ /* we can register the device now, as it is ready */
+ usb_set_intfdata(intf, dev);
+
+ retval = usb_register_dev(intf, &usb_tranzport_class);
+ if (retval) {
+ /* something prevented us from registering this driver */
+ dev_err(&intf->dev, "Not able to get a minor for this device.\n");
+ usb_set_intfdata(intf, NULL);
+ goto error;
+ }
+
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightRecord))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackrec))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackmute))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightTracksolo))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightAnysolo))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightLoop))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightPunch))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_wheel))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_event))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_dump_state))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_compress_wheel))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_enable))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_offline))) goto error;
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&intf->dev, "Tranzport Device #%d now attached to major %d minor %d\n",
+ (intf->minor - USB_TRANZPORT_MINOR_BASE), USB_MAJOR, intf->minor);
+
+exit:
+ return retval;
+
+error:
+ usb_tranzport_delete(dev);
+
+ return retval;
+}
+
+/**
+ * usb_tranzport_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ */
+static void usb_tranzport_disconnect(struct usb_interface *intf)
+{
+ struct usb_tranzport *dev;
+ int minor;
+ mutex_lock(&disconnect_mutex);
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
+ down(&dev->sem);
+ minor = intf->minor;
+ /* give back our minor */
+ usb_deregister_dev(intf, &usb_tranzport_class);
+
+ /* if the device is not opened, then we clean up right now */
+ if (!dev->open_count) {
+ up(&dev->sem);
+ usb_tranzport_delete(dev);
+ } else {
+ dev->intf = NULL;
+ up(&dev->sem);
+ }
+
+ mutex_unlock(&disconnect_mutex);
+
+ dev_info(&intf->dev, "Tranzport Surface #%d now disconnected\n",
+ (minor - USB_TRANZPORT_MINOR_BASE));
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver usb_tranzport_driver = {
+ .name = "tranzport",
+ .probe = usb_tranzport_probe,
+ .disconnect = usb_tranzport_disconnect,
+ .id_table = usb_tranzport_table,
+};
+
+/**
+ * usb_tranzport_init
+ */
+static int __init usb_tranzport_init(void)
+{
+ int retval;
+
+ /* register this driver with the USB subsystem */
+ retval = usb_register(&usb_tranzport_driver);
+ if (retval)
+ err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval);
+
+ return retval;
+}
+
+/**
+ * usb_tranzport_exit
+ */
+static void __exit usb_tranzport_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&usb_tranzport_driver);
+}
+
+module_init(usb_tranzport_init);
+module_exit(usb_tranzport_exit);
+
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index 593fdb767aad..f2cf7f66ae05 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -25,3 +25,13 @@ config VIDEO_GO7007_USB
To compile this driver as a module, choose M here: the
module will be called go7007-usb
+config VIDEO_GO7007_USB_S2250_BOARD
+ tristate "Sensoray 2250/2251 support"
+ depends on VIDEO_GO7007_USB && DVB_USB
+ default N
+ ---help---
+ This is a video4linux driver for the Sensoray 2250/2251 device
+
+ To compile this driver as a module, choose M here: the
+ module will be called s2250-board
+
diff --git a/drivers/staging/go7007/Makefile b/drivers/staging/go7007/Makefile
index 9b9310cae1ce..e514b4af6d06 100644
--- a/drivers/staging/go7007/Makefile
+++ b/drivers/staging/go7007/Makefile
@@ -5,14 +5,23 @@
obj-$(CONFIG_VIDEO_GO7007) += go7007.o
obj-$(CONFIG_VIDEO_GO7007_USB) += go7007-usb.o
+obj-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD) += s2250.o
-go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o snd-go7007.o
+go7007-objs += go7007-v4l2.o go7007-driver.o go7007-i2c.o go7007-fw.o \
+ snd-go7007.o wis-saa7113.o
+s2250-objs += s2250-board.o s2250-loader.o
-#ifneq ($(SAA7134_BUILD),)
-#obj-m += saa7134-go7007.o
+# Uncompile when the saa7134 patches get into upstream
+#ifneq ($(CONFIG_VIDEO_SAA7134),)
+#obj-$(CONFIG_VIDEO_SAA7134) += saa7134-go7007.o
+#EXTRA_CFLAGS += -Idrivers/media/video/saa7134
#endif
+ifneq ($(CONFIG_VIDEO_GO7007_USB_S2250_BOARD),)
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb
+endif
+
EXTRA_CFLAGS += -Idrivers/staging/saa7134
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
index e4ead96679c8..58bfc8d81b3b 100644
--- a/drivers/staging/go7007/go7007-driver.c
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -217,6 +217,9 @@ static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
case I2C_DRIVERID_WIS_OV7640:
modname = "wis-ov7640";
break;
+ case I2C_DRIVERID_S2250:
+ modname = "s2250-board";
+ break;
default:
modname = NULL;
break;
@@ -227,7 +230,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, int id, int addr)
return 0;
if (modname != NULL)
printk(KERN_INFO
- "go7007: probing for module %s failed", modname);
+ "go7007: probing for module %s failed\n", modname);
else
printk(KERN_INFO
"go7007: sensor %u seems to be unsupported!\n", id);
diff --git a/drivers/staging/go7007/go7007-fw.c b/drivers/staging/go7007/go7007-fw.c
index a0e17b0e0ce3..871ed43e4e05 100644
--- a/drivers/staging/go7007/go7007-fw.c
+++ b/drivers/staging/go7007/go7007-fw.c
@@ -284,7 +284,7 @@ static const int zz[64] = {
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
};
-static int copy_packages(u16 *dest, u16 *src, int pkg_cnt, int space)
+static int copy_packages(__le16 *dest, u16 *src, int pkg_cnt, int space)
{
int i, cnt = pkg_cnt * 32;
@@ -292,7 +292,7 @@ static int copy_packages(u16 *dest, u16 *src, int pkg_cnt, int space)
return -1;
for (i = 0; i < cnt; ++i)
- dest[i] = __cpu_to_le16(src[i]);
+ dest[i] = cpu_to_le16p(src + i);
return cnt;
}
@@ -372,7 +372,7 @@ static int mjpeg_frame_header(struct go7007 *go, unsigned char *buf, int q)
return p;
}
-static int gen_mjpeghdr_to_package(struct go7007 *go, u16 *code, int space)
+static int gen_mjpeghdr_to_package(struct go7007 *go, __le16 *code, int space)
{
u8 *buf;
u16 mem = 0x3e00;
@@ -643,7 +643,7 @@ static int mpeg1_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
}
static int gen_mpeg1hdr_to_package(struct go7007 *go,
- u16 *code, int space, int *framelen)
+ __le16 *code, int space, int *framelen)
{
u8 *buf;
u16 mem = 0x3e00;
@@ -831,7 +831,7 @@ static int mpeg4_sequence_header(struct go7007 *go, unsigned char *buf, int ext)
}
static int gen_mpeg4hdr_to_package(struct go7007 *go,
- u16 *code, int space, int *framelen)
+ __le16 *code, int space, int *framelen)
{
u8 *buf;
u16 mem = 0x3e00;
@@ -936,7 +936,7 @@ done:
}
static int brctrl_to_package(struct go7007 *go,
- u16 *code, int space, int *framelen)
+ __le16 *code, int space, int *framelen)
{
int converge_speed = 0;
int lambda = (go->format == GO7007_FORMAT_MJPEG || go->dvd_mode) ?
@@ -1091,7 +1091,7 @@ static int brctrl_to_package(struct go7007 *go,
return copy_packages(code, pack, 6, space);
}
-static int config_package(struct go7007 *go, u16 *code, int space)
+static int config_package(struct go7007 *go, __le16 *code, int space)
{
int fps = go->sensor_framerate / go->fps_scale / 1000;
int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
@@ -1213,7 +1213,7 @@ static int config_package(struct go7007 *go, u16 *code, int space)
return copy_packages(code, pack, 5, space);
}
-static int seqhead_to_package(struct go7007 *go, u16 *code, int space,
+static int seqhead_to_package(struct go7007 *go, __le16 *code, int space,
int (*sequence_header_func)(struct go7007 *go,
unsigned char *buf, int ext))
{
@@ -1292,7 +1292,7 @@ static int relative_prime(int big, int little)
return big;
}
-static int avsync_to_package(struct go7007 *go, u16 *code, int space)
+static int avsync_to_package(struct go7007 *go, __le16 *code, int space)
{
int arate = go->board_info->audio_rate * 1001 * go->fps_scale;
int ratio = arate / go->sensor_framerate;
@@ -1323,7 +1323,7 @@ static int avsync_to_package(struct go7007 *go, u16 *code, int space)
return copy_packages(code, pack, 1, space);
}
-static int final_package(struct go7007 *go, u16 *code, int space)
+static int final_package(struct go7007 *go, __le16 *code, int space)
{
int rows = go->interlace_coding ? go->height / 32 : go->height / 16;
u16 pack[] = {
@@ -1386,7 +1386,7 @@ static int final_package(struct go7007 *go, u16 *code, int space)
return copy_packages(code, pack, 1, space);
}
-static int audio_to_package(struct go7007 *go, u16 *code, int space)
+static int audio_to_package(struct go7007 *go, __le16 *code, int space)
{
int clock_config = ((go->board_info->audio_flags &
GO7007_AUDIO_I2S_MASTER ? 1 : 0) << 11) |
@@ -1436,7 +1436,7 @@ static int audio_to_package(struct go7007 *go, u16 *code, int space)
return copy_packages(code, pack, 2, space);
}
-static int modet_to_package(struct go7007 *go, u16 *code, int space)
+static int modet_to_package(struct go7007 *go, __le16 *code, int space)
{
int ret, mb, i, addr, cnt = 0;
u16 pack[32];
@@ -1505,7 +1505,7 @@ static int modet_to_package(struct go7007 *go, u16 *code, int space)
return cnt;
}
-static int do_special(struct go7007 *go, u16 type, u16 *code, int space,
+static int do_special(struct go7007 *go, u16 type, __le16 *code, int space,
int *framelen)
{
switch (type) {
@@ -1555,7 +1555,7 @@ static int do_special(struct go7007 *go, u16 type, u16 *code, int space,
int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
{
const struct firmware *fw_entry;
- u16 *code, *src;
+ __le16 *code, *src;
int framelen[8] = { }; /* holds the lengths of empty frame templates */
int codespace = 64 * 1024, i = 0, srclen, chunk_len, chunk_flags;
int mode_flag;
@@ -1590,7 +1590,7 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
goto fw_failed;
}
memset(code, 0, codespace * 2);
- src = (u16 *)fw_entry->data;
+ src = (__le16 *)fw_entry->data;
srclen = fw_entry->size / 2;
while (srclen >= 2) {
chunk_flags = __le16_to_cpu(src[0]);
diff --git a/drivers/staging/go7007/go7007-priv.h b/drivers/staging/go7007/go7007-priv.h
index 005542d16a56..372f1f1c09b2 100644
--- a/drivers/staging/go7007/go7007-priv.h
+++ b/drivers/staging/go7007/go7007-priv.h
@@ -40,6 +40,7 @@ struct go7007;
#define GO7007_BOARDID_LIFEVIEW_LR192 21 /* TV Walker Ultra */
#define GO7007_BOARDID_ENDURA 22
#define GO7007_BOARDID_ADLINK_MPG24 23
+#define GO7007_BOARDID_SENSORAY_2250 24 /* Sensoray 2250/2251 */
/* Various characteristics of each board */
#define GO7007_BOARD_HAS_AUDIO (1<<0)
@@ -104,6 +105,7 @@ struct go7007_hpi_ops {
int (*stream_start)(struct go7007 *go);
int (*stream_stop)(struct go7007 *go);
int (*send_firmware)(struct go7007 *go, u8 *data, int len);
+ int (*send_command)(struct go7007 *go, unsigned int cmd, void *arg);
};
/* The video buffer size must be a multiple of PAGE_SIZE */
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index 3f5ee3424e72..83eec920c7d3 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -225,7 +225,7 @@ static struct go7007_usb_board board_px_tv402u = {
.inputs = {
{
.video_input = 1,
- .audio_input = TVAUDIO_INPUT_EXTERN,
+ .audio_input = TVAUDIO_INPUT_EXTERN,
.name = "Composite",
},
{
@@ -398,6 +398,41 @@ static struct go7007_usb_board board_adlink_mpg24 = {
},
};
+static struct go7007_usb_board board_sensoray_2250 = {
+ .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C,
+ .main_info = {
+ .firmware = "go7007tv.bin",
+ .audio_flags = GO7007_AUDIO_I2S_MODE_1 |
+ GO7007_AUDIO_I2S_MASTER |
+ GO7007_AUDIO_WORD_16,
+ .flags = GO7007_BOARD_HAS_AUDIO,
+ .audio_rate = 48000,
+ .audio_bclk_div = 8,
+ .audio_main_div = 2,
+ .hpi_buffer_cap = 7,
+ .sensor_flags = GO7007_SENSOR_656 |
+ GO7007_SENSOR_TV,
+ .num_i2c_devs = 1,
+ .i2c_devs = {
+ {
+ .id = I2C_DRIVERID_S2250,
+ .addr = 0x34,
+ },
+ },
+ .num_inputs = 2,
+ .inputs = {
+ {
+ .video_input = 0,
+ .name = "Composite",
+ },
+ {
+ .video_input = 1,
+ .name = "S-Video",
+ },
+ },
+ },
+};
+
static struct usb_device_id go7007_usb_id_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
@@ -491,6 +526,14 @@ static struct usb_device_id go7007_usb_id_table[] = {
.bcdDevice_hi = 0x1,
.driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192,
},
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,
+ .idVendor = 0x1943, /* Vendor ID Sensoray */
+ .idProduct = 0x2250, /* Product ID of 2250/2251 */
+ .bcdDevice_lo = 0x1,
+ .bcdDevice_hi = 0x1,
+ .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250,
+ },
{ } /* Terminating entry */
};
@@ -637,9 +680,10 @@ static void go7007_usb_readinterrupt_complete(struct urb *urb)
{
struct go7007 *go = (struct go7007 *)urb->context;
u16 *regs = (u16 *)urb->transfer_buffer;
+ int status = urb->status;
- if (urb->status != 0) {
- if (urb->status != -ESHUTDOWN &&
+ if (status) {
+ if (status != -ESHUTDOWN &&
go->status != STATUS_SHUTDOWN) {
printk(KERN_ERR
"go7007-usb: error in read interrupt: %d\n",
@@ -680,15 +724,14 @@ static int go7007_usb_read_interrupt(struct go7007 *go)
static void go7007_usb_read_video_pipe_complete(struct urb *urb)
{
struct go7007 *go = (struct go7007 *)urb->context;
- int r;
+ int r, status = urb-> status;
if (!go->streaming) {
wake_up_interruptible(&go->frame_waitq);
return;
}
- if (urb->status != 0) {
- printk(KERN_ERR "go7007-usb: error in video pipe: %d\n",
- urb->status);
+ if (status) {
+ printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", status);
return;
}
if (urb->actual_length != urb->transfer_buffer_length) {
@@ -704,13 +747,12 @@ static void go7007_usb_read_video_pipe_complete(struct urb *urb)
static void go7007_usb_read_audio_pipe_complete(struct urb *urb)
{
struct go7007 *go = (struct go7007 *)urb->context;
- int r;
+ int r, status = urb->status;
if (!go->streaming)
return;
- if (urb->status != 0) {
- printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n",
- urb->status);
+ if (status) {
+ printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", status);
return;
}
if (urb->actual_length != urb->transfer_buffer_length) {
@@ -751,7 +793,7 @@ static int go7007_usb_stream_start(struct go7007 *go)
return 0;
audio_submit_failed:
- for (i = 0; i < 8; ++i)
+ for (i = 0; i < 7; ++i)
usb_kill_urb(usb->audio_urbs[i]);
video_submit_failed:
for (i = 0; i < 8; ++i)
@@ -965,16 +1007,20 @@ static int go7007_usb_probe(struct usb_interface *intf,
name = "Lifeview TV Walker Ultra";
board = &board_lifeview_lr192;
break;
+ case GO7007_BOARDID_SENSORAY_2250:
+ printk(KERN_INFO "Sensoray 2250 found\n");
+ name = "Sensoray 2250/2251\n";
+ board = &board_sensoray_2250;
+ break;
default:
printk(KERN_ERR "go7007-usb: unknown board ID %d!\n",
(unsigned int)id->driver_info);
return 0;
}
- usb = kmalloc(sizeof(struct go7007_usb), GFP_KERNEL);
+ usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL);
if (usb == NULL)
return -ENOMEM;
- memset(usb, 0, sizeof(struct go7007_usb));
/* Allocate the URB and buffer for receiving incoming interrupts */
usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -1179,6 +1225,7 @@ static void go7007_usb_disconnect(struct usb_interface *intf)
{
struct go7007 *go = usb_get_intfdata(intf);
struct go7007_usb *usb = go->hpi_context;
+ struct urb *vurb, *aurb;
int i;
go->status = STATUS_SHUTDOWN;
@@ -1186,15 +1233,19 @@ static void go7007_usb_disconnect(struct usb_interface *intf)
/* Free USB-related structs */
for (i = 0; i < 8; ++i) {
- if (usb->video_urbs[i] != NULL) {
- if (usb->video_urbs[i]->transfer_buffer != NULL)
- kfree(usb->video_urbs[i]->transfer_buffer);
- usb_free_urb(usb->video_urbs[i]);
+ vurb = usb->video_urbs[i];
+ if (vurb) {
+ usb_kill_urb(vurb);
+ if (vurb->transfer_buffer)
+ kfree(vurb->transfer_buffer);
+ usb_free_urb(vurb);
}
- if (usb->audio_urbs[i] != NULL) {
- if (usb->audio_urbs[i]->transfer_buffer != NULL)
- kfree(usb->audio_urbs[i]->transfer_buffer);
- usb_free_urb(usb->audio_urbs[i]);
+ aurb = usb->audio_urbs[i];
+ if (aurb) {
+ usb_kill_urb(aurb);
+ if (aurb->transfer_buffer)
+ kfree(aurb->transfer_buffer);
+ usb_free_urb(aurb);
}
}
kfree(usb->intr_urb->transfer_buffer);
diff --git a/drivers/staging/go7007/go7007-v4l2.c b/drivers/staging/go7007/go7007-v4l2.c
index 94e1141a1fcd..868edb65e7bf 100644
--- a/drivers/staging/go7007/go7007-v4l2.c
+++ b/drivers/staging/go7007/go7007-v4l2.c
@@ -38,6 +38,14 @@
#include "go7007-priv.h"
#include "wis-i2c.h"
+/* Temporary defines until accepted in v4l-dvb */
+#ifndef V4L2_MPEG_STREAM_TYPE_MPEG_ELEM
+#define V4L2_MPEG_STREAM_TYPE_MPEG_ELEM 6 /* MPEG elementary stream */
+#endif
+#ifndef V4L2_MPEG_VIDEO_ENCODING_MPEG_4
+#define V4L2_MPEG_VIDEO_ENCODING_MPEG_4 3
+#endif
+
static void deactivate_buffer(struct go7007_buffer *gobuf)
{
int i;
@@ -81,7 +89,7 @@ static int go7007_streamoff(struct go7007 *go)
return 0;
}
-static int go7007_open(struct inode *inode, struct file *file)
+static int go7007_open(struct file *file)
{
struct go7007 *go = video_get_drvdata(video_devdata(file));
struct go7007_file *gofh;
@@ -99,7 +107,7 @@ static int go7007_open(struct inode *inode, struct file *file)
return 0;
}
-static int go7007_release(struct inode *inode, struct file *file)
+static int go7007_release(struct file *file)
{
struct go7007_file *gofh = file->private_data;
struct go7007 *go = gofh->go;
@@ -319,6 +327,7 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
return 0;
}
+#if 0
static int clip_to_modet_map(struct go7007 *go, int region,
struct v4l2_clip *clip_list)
{
@@ -375,499 +384,801 @@ static int clip_to_modet_map(struct go7007 *go, int region,
return 0;
}
-static int go7007_do_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg)
+static int mpeg_queryctrl(u32 id, struct v4l2_queryctrl *ctrl)
{
- struct go7007_file *gofh = file->private_data;
- struct go7007 *go = gofh->go;
- unsigned long flags;
- int retval = 0;
-
- switch (cmd) {
- case VIDIOC_QUERYCAP:
- {
- struct v4l2_capability *cap = arg;
-
- memset(cap, 0, sizeof(*cap));
- strcpy(cap->driver, "go7007");
- strncpy(cap->card, go->name, sizeof(cap->card));
- cap->version = KERNEL_VERSION(0, 9, 8);
- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_STREAMING; /* | V4L2_CAP_AUDIO; */
- if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
- cap->capabilities |= V4L2_CAP_TUNER;
+ static const u32 user_ctrls[] = {
+ V4L2_CID_USER_CLASS,
+ 0
+ };
+ static const u32 mpeg_ctrls[] = {
+ V4L2_CID_MPEG_CLASS,
+ V4L2_CID_MPEG_STREAM_TYPE,
+ V4L2_CID_MPEG_VIDEO_ENCODING,
+ V4L2_CID_MPEG_VIDEO_ASPECT,
+ V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+ V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+ V4L2_CID_MPEG_VIDEO_BITRATE,
+ 0
+ };
+ static const u32 *ctrl_classes[] = {
+ user_ctrls,
+ mpeg_ctrls,
+ NULL
+ };
+
+ /* The ctrl may already contain the queried i2c controls,
+ * query the mpeg controls if the existing ctrl id is
+ * greater than the next mpeg ctrl id.
+ */
+ id = v4l2_ctrl_next(ctrl_classes, id);
+ if (id >= ctrl->id && ctrl->name[0])
return 0;
+
+ memset(ctrl, 0, sizeof(*ctrl));
+ ctrl->id = id;
+
+ switch (ctrl->id) {
+ case V4L2_CID_USER_CLASS:
+ case V4L2_CID_MPEG_CLASS:
+ return v4l2_ctrl_query_fill_std(ctrl);
+ case V4L2_CID_MPEG_STREAM_TYPE:
+ return v4l2_ctrl_query_fill(ctrl,
+ V4L2_MPEG_STREAM_TYPE_MPEG2_DVD,
+ V4L2_MPEG_STREAM_TYPE_MPEG_ELEM, 1,
+ V4L2_MPEG_STREAM_TYPE_MPEG_ELEM);
+ case V4L2_CID_MPEG_VIDEO_ENCODING:
+ return v4l2_ctrl_query_fill(ctrl,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_4, 1,
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+ case V4L2_CID_MPEG_VIDEO_ASPECT:
+ return v4l2_ctrl_query_fill(ctrl,
+ V4L2_MPEG_VIDEO_ASPECT_1x1,
+ V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
+ V4L2_MPEG_VIDEO_ASPECT_1x1);
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+ return v4l2_ctrl_query_fill_std(ctrl);
+ case V4L2_CID_MPEG_VIDEO_BITRATE:
+ return v4l2_ctrl_query_fill(ctrl,
+ 64000,
+ 10000000, 1,
+ 9800000);
+ default:
+ break;
}
- case VIDIOC_ENUM_FMT:
- {
- struct v4l2_fmtdesc *fmt = arg;
- unsigned int index;
- char *desc;
- u32 pixelformat;
+ return -EINVAL;
+}
+
+static int mpeg_s_control(struct v4l2_control *ctrl, struct go7007 *go)
+{
+ /* pretty sure we can't change any of these while streaming */
+ if (go->streaming)
+ return -EBUSY;
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_STREAM_TYPE:
+ switch (ctrl->value) {
+ case V4L2_MPEG_STREAM_TYPE_MPEG2_DVD:
+ go->format = GO7007_FORMAT_MPEG2;
+ go->bitrate = 9800000;
+ go->gop_size = 15;
+ go->pali = 0x48;
+ go->closed_gop = 1;
+ go->repeat_seqhead = 0;
+ go->seq_header_enable = 1;
+ go->gop_header_enable = 1;
+ go->dvd_mode = 1;
+ break;
+ case V4L2_MPEG_STREAM_TYPE_MPEG_ELEM:
+ /* todo: */
+ break;
+ default:
return -EINVAL;
- switch (fmt->index) {
- case 0:
- pixelformat = V4L2_PIX_FMT_MJPEG;
- desc = "Motion-JPEG";
+ }
+ break;
+ case V4L2_CID_MPEG_VIDEO_ENCODING:
+ switch (ctrl->value) {
+ case V4L2_MPEG_VIDEO_ENCODING_MPEG_1:
+ go->format = GO7007_FORMAT_MPEG1;
+ go->pali = 0;
break;
- case 1:
- pixelformat = V4L2_PIX_FMT_MPEG;
- desc = "MPEG1/MPEG2/MPEG4";
+ case V4L2_MPEG_VIDEO_ENCODING_MPEG_2:
+ go->format = GO7007_FORMAT_MPEG2;
+ /*if (mpeg->pali >> 24 == 2)
+ go->pali = mpeg->pali & 0xff;
+ else*/
+ go->pali = 0x48;
+ break;
+ case V4L2_MPEG_VIDEO_ENCODING_MPEG_4:
+ go->format = GO7007_FORMAT_MPEG4;
+ /*if (mpeg->pali >> 24 == 4)
+ go->pali = mpeg->pali & 0xff;
+ else*/
+ go->pali = 0xf5;
break;
default:
return -EINVAL;
}
- index = fmt->index;
- memset(fmt, 0, sizeof(*fmt));
- fmt->index = index;
- fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
- strncpy(fmt->description, desc, sizeof(fmt->description));
- fmt->pixelformat = pixelformat;
-
- return 0;
- }
- case VIDIOC_TRY_FMT:
- {
- struct v4l2_format *fmt = arg;
-
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ go->gop_header_enable =
+ /*mpeg->flags & GO7007_MPEG_OMIT_GOP_HEADER
+ ? 0 :*/ 1;
+ /*if (mpeg->flags & GO7007_MPEG_REPEAT_SEQHEADER)
+ go->repeat_seqhead = 1;
+ else*/
+ go->repeat_seqhead = 0;
+ go->dvd_mode = 0;
+ break;
+ case V4L2_CID_MPEG_VIDEO_ASPECT:
+ if (go->format == GO7007_FORMAT_MJPEG)
return -EINVAL;
- return set_capture_size(go, fmt, 1);
- }
- case VIDIOC_G_FMT:
- {
- struct v4l2_format *fmt = arg;
-
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ switch (ctrl->value) {
+ case V4L2_MPEG_VIDEO_ASPECT_1x1:
+ go->aspect_ratio = GO7007_RATIO_1_1;
+ break;
+ case V4L2_MPEG_VIDEO_ASPECT_4x3:
+ go->aspect_ratio = GO7007_RATIO_4_3;
+ break;
+ case V4L2_MPEG_VIDEO_ASPECT_16x9:
+ go->aspect_ratio = GO7007_RATIO_16_9;
+ break;
+ case V4L2_MPEG_VIDEO_ASPECT_221x100:
+ default:
return -EINVAL;
- memset(fmt, 0, sizeof(*fmt));
- fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt->fmt.pix.width = go->width;
- fmt->fmt.pix.height = go->height;
- fmt->fmt.pix.pixelformat = go->format == GO7007_FORMAT_MJPEG ?
- V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_MPEG;
- fmt->fmt.pix.field = V4L2_FIELD_NONE;
- fmt->fmt.pix.bytesperline = 0;
- fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
- fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* ?? */
- return 0;
- }
- case VIDIOC_S_FMT:
- {
- struct v4l2_format *fmt = arg;
-
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ }
+ break;
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ go->gop_size = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+ if (ctrl->value != 0 && ctrl->value != 1)
return -EINVAL;
- if (go->streaming)
- return -EBUSY;
- return set_capture_size(go, fmt, 0);
- }
- case VIDIOC_G_FBUF:
- case VIDIOC_S_FBUF:
- return -EINVAL;
- case VIDIOC_REQBUFS:
- {
- struct v4l2_requestbuffers *req = arg;
- unsigned int count, i;
-
- if (go->streaming)
- return -EBUSY;
- if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- req->memory != V4L2_MEMORY_MMAP)
+ go->closed_gop = ctrl->value;
+ break;
+ case V4L2_CID_MPEG_VIDEO_BITRATE:
+ /* Upper bound is kind of arbitrary here */
+ if (ctrl->value < 64000 || ctrl->value > 10000000)
return -EINVAL;
-
- down(&gofh->lock);
- retval = -EBUSY;
- for (i = 0; i < gofh->buf_count; ++i)
- if (gofh->bufs[i].mapped > 0)
- goto unlock_and_return;
- down(&go->hw_lock);
- if (go->in_use > 0 && gofh->buf_count == 0) {
- up(&go->hw_lock);
- goto unlock_and_return;
- }
- if (gofh->buf_count > 0)
- kfree(gofh->bufs);
- retval = -ENOMEM;
- count = req->count;
- if (count > 0) {
- if (count < 2)
- count = 2;
- if (count > 32)
- count = 32;
- gofh->bufs = kmalloc(count *
- sizeof(struct go7007_buffer),
- GFP_KERNEL);
- if (gofh->bufs == NULL) {
- up(&go->hw_lock);
- goto unlock_and_return;
- }
- memset(gofh->bufs, 0,
- count * sizeof(struct go7007_buffer));
- for (i = 0; i < count; ++i) {
- gofh->bufs[i].go = go;
- gofh->bufs[i].index = i;
- gofh->bufs[i].state = BUF_STATE_IDLE;
- gofh->bufs[i].mapped = 0;
- }
- go->in_use = 1;
- } else {
- go->in_use = 0;
- }
- gofh->buf_count = count;
- up(&go->hw_lock);
- up(&gofh->lock);
- memset(req, 0, sizeof(*req));
- req->count = count;
- req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req->memory = V4L2_MEMORY_MMAP;
- return 0;
+ go->bitrate = ctrl->value;
+ break;
+ default:
+ return -EINVAL;
}
- case VIDIOC_QUERYBUF:
- {
- struct v4l2_buffer *buf = arg;
- unsigned int index;
+ return 0;
+}
- retval = -EINVAL;
- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+static int mpeg_g_control(struct v4l2_control *ctrl, struct go7007 *go)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_MPEG_STREAM_TYPE:
+ if (go->dvd_mode)
+ ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_DVD;
+ else
+ ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG_ELEM;
+ break;
+ case V4L2_CID_MPEG_VIDEO_ENCODING:
+ switch (go->format) {
+ case GO7007_FORMAT_MPEG1:
+ ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+ break;
+ case GO7007_FORMAT_MPEG2:
+ ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+ break;
+ case GO7007_FORMAT_MPEG4:
+ ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4;
+ break;
+ default:
return -EINVAL;
- index = buf->index;
- down(&gofh->lock);
- if (index >= gofh->buf_count)
- goto unlock_and_return;
- memset(buf, 0, sizeof(*buf));
- buf->index = index;
- buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- switch (gofh->bufs[index].state) {
- case BUF_STATE_QUEUED:
- buf->flags = V4L2_BUF_FLAG_QUEUED;
+ }
+ break;
+ case V4L2_CID_MPEG_VIDEO_ASPECT:
+ switch (go->aspect_ratio) {
+ case GO7007_RATIO_1_1:
+ ctrl->value = V4L2_MPEG_VIDEO_ASPECT_1x1;
break;
- case BUF_STATE_DONE:
- buf->flags = V4L2_BUF_FLAG_DONE;
+ case GO7007_RATIO_4_3:
+ ctrl->value = V4L2_MPEG_VIDEO_ASPECT_4x3;
+ break;
+ case GO7007_RATIO_16_9:
+ ctrl->value = V4L2_MPEG_VIDEO_ASPECT_16x9;
break;
default:
- buf->flags = 0;
+ return -EINVAL;
}
- if (gofh->bufs[index].mapped)
- buf->flags |= V4L2_BUF_FLAG_MAPPED;
- buf->memory = V4L2_MEMORY_MMAP;
- buf->m.offset = index * GO7007_BUF_SIZE;
- buf->length = GO7007_BUF_SIZE;
- up(&gofh->lock);
+ break;
+ case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+ ctrl->value = go->gop_size;
+ break;
+ case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+ ctrl->value = go->closed_gop;
+ break;
+ case V4L2_CID_MPEG_VIDEO_BITRATE:
+ ctrl->value = go->bitrate;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+#endif
- return 0;
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ strlcpy(cap->driver, "go7007", sizeof(cap->driver));
+ strlcpy(cap->card, go->name, sizeof(cap->card));
+#if 0
+ strlcpy(cap->bus_info, dev_name(&dev->udev->dev), sizeof(cap->bus_info));
+#endif
+
+ cap->version = KERNEL_VERSION(0, 9, 8);
+
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING; /* | V4L2_CAP_AUDIO; */
+
+ if (go->board_info->flags & GO7007_BOARD_HAS_TUNER)
+ cap->capabilities |= V4L2_CAP_TUNER;
+
+ return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *fmt)
+{
+ char *desc = NULL;
+
+ switch (fmt->index) {
+ case 0:
+ fmt->pixelformat = V4L2_PIX_FMT_MJPEG;
+ desc = "Motion-JPEG";
+ break;
+ case 1:
+ fmt->pixelformat = V4L2_PIX_FMT_MPEG;
+ desc = "MPEG1/MPEG2/MPEG4";
+ break;
+ default:
+ return -EINVAL;
}
- case VIDIOC_QBUF:
- {
- struct v4l2_buffer *buf = arg;
- struct go7007_buffer *gobuf;
- int ret;
+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt->flags = V4L2_FMT_FLAG_COMPRESSED;
- retval = -EINVAL;
- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- buf->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
- down(&gofh->lock);
- if (buf->index < 0 || buf->index >= gofh->buf_count)
- goto unlock_and_return;
- gobuf = &gofh->bufs[buf->index];
- if (gobuf->mapped == 0)
- goto unlock_and_return;
- retval = -EBUSY;
- if (gobuf->state != BUF_STATE_IDLE)
- goto unlock_and_return;
- /* offset will be 0 until we really support USERPTR streaming */
- gobuf->offset = gobuf->user_addr & ~PAGE_MASK;
- gobuf->bytesused = 0;
- gobuf->frame_offset = 0;
- gobuf->modet_active = 0;
- if (gobuf->offset > 0)
- gobuf->page_count = GO7007_BUF_PAGES + 1;
- else
- gobuf->page_count = GO7007_BUF_PAGES;
- retval = -ENOMEM;
- down_read(&current->mm->mmap_sem);
- ret = get_user_pages(current, current->mm,
- gobuf->user_addr & PAGE_MASK, gobuf->page_count,
- 1, 1, gobuf->pages, NULL);
- up_read(&current->mm->mmap_sem);
- if (ret != gobuf->page_count) {
- int i;
- for (i = 0; i < ret; ++i)
- page_cache_release(gobuf->pages[i]);
- gobuf->page_count = 0;
+ strncpy(fmt->description, desc, sizeof(fmt->description));
+
+ return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *fmt)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt->fmt.pix.width = go->width;
+ fmt->fmt.pix.height = go->height;
+ fmt->fmt.pix.pixelformat = (go->format == GO7007_FORMAT_MJPEG) ?
+ V4L2_PIX_FMT_MJPEG : V4L2_PIX_FMT_MPEG;
+ fmt->fmt.pix.field = V4L2_FIELD_NONE;
+ fmt->fmt.pix.bytesperline = 0;
+ fmt->fmt.pix.sizeimage = GO7007_BUF_SIZE;
+ fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *fmt)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ return set_capture_size(go, fmt, 1);
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *fmt)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (go->streaming)
+ return -EBUSY;
+
+ return set_capture_size(go, fmt, 0);
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *req)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ int retval = -EBUSY;
+ unsigned int count, i;
+
+ if (go->streaming)
+ return retval;
+
+ if (req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ req->memory != V4L2_MEMORY_MMAP)
+ return -EINVAL;
+
+ down(&gofh->lock);
+ for (i = 0; i < gofh->buf_count; ++i)
+ if (gofh->bufs[i].mapped > 0)
goto unlock_and_return;
- }
- gobuf->state = BUF_STATE_QUEUED;
- spin_lock_irqsave(&go->spinlock, flags);
- list_add_tail(&gobuf->stream, &go->stream);
- spin_unlock_irqrestore(&go->spinlock, flags);
- up(&gofh->lock);
- return 0;
+
+ down(&go->hw_lock);
+ if (go->in_use > 0 && gofh->buf_count == 0) {
+ up(&go->hw_lock);
+ goto unlock_and_return;
}
- case VIDIOC_DQBUF:
- {
- struct v4l2_buffer *buf = arg;
- struct go7007_buffer *gobuf;
- u32 frame_type_flag;
- DEFINE_WAIT(wait);
- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (buf->memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
- down(&gofh->lock);
- retval = -EINVAL;
- if (list_empty(&go->stream))
+ if (gofh->buf_count > 0)
+ kfree(gofh->bufs);
+
+ retval = -ENOMEM;
+ count = req->count;
+ if (count > 0) {
+ if (count < 2)
+ count = 2;
+ if (count > 32)
+ count = 32;
+
+ gofh->bufs = kmalloc(count * sizeof(struct go7007_buffer),
+ GFP_KERNEL);
+
+ if (!gofh->bufs) {
+ up(&go->hw_lock);
goto unlock_and_return;
- gobuf = list_entry(go->stream.next,
- struct go7007_buffer, stream);
- retval = -EAGAIN;
- if (gobuf->state != BUF_STATE_DONE &&
- !(file->f_flags & O_NONBLOCK)) {
- for (;;) {
- prepare_to_wait(&go->frame_waitq, &wait,
- TASK_INTERRUPTIBLE);
- if (gobuf->state == BUF_STATE_DONE)
- break;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- finish_wait(&go->frame_waitq, &wait);
}
- if (gobuf->state != BUF_STATE_DONE)
- goto unlock_and_return;
- spin_lock_irqsave(&go->spinlock, flags);
- deactivate_buffer(gobuf);
- spin_unlock_irqrestore(&go->spinlock, flags);
- frame_type_flag = get_frame_type_flag(gobuf, go->format);
- gobuf->state = BUF_STATE_IDLE;
- memset(buf, 0, sizeof(*buf));
- buf->index = gobuf->index;
- buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf->bytesused = gobuf->bytesused;
- buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag;
- buf->field = V4L2_FIELD_NONE;
- buf->timestamp = gobuf->timestamp;
- buf->sequence = gobuf->seq;
- buf->memory = V4L2_MEMORY_MMAP;
- buf->m.offset = gobuf->index * GO7007_BUF_SIZE;
- buf->length = GO7007_BUF_SIZE;
- buf->reserved = gobuf->modet_active;
- up(&gofh->lock);
- return 0;
- }
- case VIDIOC_STREAMON:
- {
- unsigned int *type = arg;
- if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- down(&gofh->lock);
- down(&go->hw_lock);
- if (!go->streaming) {
- go->streaming = 1;
- go->next_seq = 0;
- go->active_buf = NULL;
- if (go7007_start_encoder(go) < 0)
- retval = -EIO;
- else
- retval = 0;
+ memset(gofh->bufs, 0, count * sizeof(struct go7007_buffer));
+
+ for (i = 0; i < count; ++i) {
+ gofh->bufs[i].go = go;
+ gofh->bufs[i].index = i;
+ gofh->bufs[i].state = BUF_STATE_IDLE;
+ gofh->bufs[i].mapped = 0;
}
- up(&go->hw_lock);
- up(&gofh->lock);
- return retval;
- }
- case VIDIOC_STREAMOFF:
- {
- unsigned int *type = arg;
- if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- down(&gofh->lock);
- go7007_streamoff(go);
- up(&gofh->lock);
- return 0;
+ go->in_use = 1;
+ } else {
+ go->in_use = 0;
}
- case VIDIOC_QUERYCTRL:
- {
- struct v4l2_queryctrl *ctrl = arg;
- u32 id;
- if (!go->i2c_adapter_online)
- return -EIO;
- id = ctrl->id;
- memset(ctrl, 0, sizeof(*ctrl));
- ctrl->id = id;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, arg);
- return ctrl->name[0] == 0 ? -EINVAL : 0;
- }
- case VIDIOC_G_CTRL:
- {
- struct v4l2_control *ctrl = arg;
- struct v4l2_queryctrl query;
+ gofh->buf_count = count;
+ up(&go->hw_lock);
+ up(&gofh->lock);
- if (!go->i2c_adapter_online)
- return -EIO;
- memset(&query, 0, sizeof(query));
- query.id = ctrl->id;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
- if (query.name[0] == 0)
- return -EINVAL;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, arg);
- return 0;
- }
- case VIDIOC_S_CTRL:
- {
- struct v4l2_control *ctrl = arg;
- struct v4l2_queryctrl query;
+ memset(req, 0, sizeof(*req));
- if (!go->i2c_adapter_online)
- return -EIO;
- memset(&query, 0, sizeof(query));
- query.id = ctrl->id;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
- if (query.name[0] == 0)
- return -EINVAL;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, arg);
- return 0;
- }
- case VIDIOC_G_PARM:
- {
- struct v4l2_streamparm *parm = arg;
- struct v4l2_fract timeperframe = {
- .numerator = 1001 * go->fps_scale,
- .denominator = go->sensor_framerate,
- };
+ req->count = count;
+ req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req->memory = V4L2_MEMORY_MMAP;
- if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- memset(parm, 0, sizeof(*parm));
- parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
- parm->parm.capture.timeperframe = timeperframe;
- return 0;
+ return 0;
+
+unlock_and_return:
+ up(&gofh->lock);
+ return retval;
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct go7007_file *gofh = priv;
+ int retval = -EINVAL;
+ unsigned int index;
+
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return retval;
+
+ index = buf->index;
+
+ down(&gofh->lock);
+ if (index >= gofh->buf_count)
+ goto unlock_and_return;
+
+ memset(buf, 0, sizeof(*buf));
+ buf->index = index;
+ buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ switch (gofh->bufs[index].state) {
+ case BUF_STATE_QUEUED:
+ buf->flags = V4L2_BUF_FLAG_QUEUED;
+ break;
+ case BUF_STATE_DONE:
+ buf->flags = V4L2_BUF_FLAG_DONE;
+ break;
+ default:
+ buf->flags = 0;
}
- case VIDIOC_S_PARM:
- {
- struct v4l2_streamparm *parm = arg;
- unsigned int n, d;
- if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- if (parm->parm.capture.capturemode != 0)
- return -EINVAL;
- n = go->sensor_framerate *
- parm->parm.capture.timeperframe.numerator;
- d = 1001 * parm->parm.capture.timeperframe.denominator;
- if (n != 0 && d != 0 && n > d)
- go->fps_scale = (n + d/2) / d;
- else
- go->fps_scale = 1;
- return 0;
+ if (gofh->bufs[index].mapped)
+ buf->flags |= V4L2_BUF_FLAG_MAPPED;
+ buf->memory = V4L2_MEMORY_MMAP;
+ buf->m.offset = index * GO7007_BUF_SIZE;
+ buf->length = GO7007_BUF_SIZE;
+ up(&gofh->lock);
+
+ return 0;
+
+unlock_and_return:
+ up(&gofh->lock);
+ return retval;
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ struct go7007_buffer *gobuf;
+ unsigned long flags;
+ int retval = -EINVAL;
+ int ret;
+
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ buf->memory != V4L2_MEMORY_MMAP)
+ return retval;
+
+ down(&gofh->lock);
+ if (buf->index < 0 || buf->index >= gofh->buf_count)
+ goto unlock_and_return;
+
+ gobuf = &gofh->bufs[buf->index];
+ if (!gobuf->mapped)
+ goto unlock_and_return;
+
+ retval = -EBUSY;
+ if (gobuf->state != BUF_STATE_IDLE)
+ goto unlock_and_return;
+
+ /* offset will be 0 until we really support USERPTR streaming */
+ gobuf->offset = gobuf->user_addr & ~PAGE_MASK;
+ gobuf->bytesused = 0;
+ gobuf->frame_offset = 0;
+ gobuf->modet_active = 0;
+ if (gobuf->offset > 0)
+ gobuf->page_count = GO7007_BUF_PAGES + 1;
+ else
+ gobuf->page_count = GO7007_BUF_PAGES;
+
+ retval = -ENOMEM;
+ down_read(&current->mm->mmap_sem);
+ ret = get_user_pages(current, current->mm,
+ gobuf->user_addr & PAGE_MASK, gobuf->page_count,
+ 1, 1, gobuf->pages, NULL);
+ up_read(&current->mm->mmap_sem);
+
+ if (ret != gobuf->page_count) {
+ int i;
+ for (i = 0; i < ret; ++i)
+ page_cache_release(gobuf->pages[i]);
+ gobuf->page_count = 0;
+ goto unlock_and_return;
}
- case VIDIOC_ENUMSTD:
- {
- struct v4l2_standard *std = arg;
- if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
- go->input == go->board_info->num_inputs - 1) {
- if (!go->i2c_adapter_online)
- return -EIO;
- i2c_clients_command(&go->i2c_adapter,
- VIDIOC_ENUMSTD, arg);
- if (!std->id) /* hack to indicate EINVAL from tuner */
- return -EINVAL;
- } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
- switch (std->index) {
- case 0:
- v4l2_video_std_construct(std,
- V4L2_STD_NTSC, "NTSC");
+ gobuf->state = BUF_STATE_QUEUED;
+ spin_lock_irqsave(&go->spinlock, flags);
+ list_add_tail(&gobuf->stream, &go->stream);
+ spin_unlock_irqrestore(&go->spinlock, flags);
+ up(&gofh->lock);
+
+ return 0;
+
+unlock_and_return:
+ up(&gofh->lock);
+ return retval;
+}
+
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ struct go7007_buffer *gobuf;
+ int retval = -EINVAL;
+ unsigned long flags;
+ u32 frame_type_flag;
+ DEFINE_WAIT(wait);
+
+ if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return retval;
+ if (buf->memory != V4L2_MEMORY_MMAP)
+ return retval;
+
+ down(&gofh->lock);
+ if (list_empty(&go->stream))
+ goto unlock_and_return;
+ gobuf = list_entry(go->stream.next,
+ struct go7007_buffer, stream);
+
+ retval = -EAGAIN;
+ if (gobuf->state != BUF_STATE_DONE &&
+ !(file->f_flags & O_NONBLOCK)) {
+ for (;;) {
+ prepare_to_wait(&go->frame_waitq, &wait,
+ TASK_INTERRUPTIBLE);
+ if (gobuf->state == BUF_STATE_DONE)
break;
- case 1:
- v4l2_video_std_construct(std,
- V4L2_STD_PAL | V4L2_STD_SECAM,
- "PAL/SECAM");
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
break;
- default:
- return -EINVAL;
}
- } else {
- if (std->index != 0)
- return -EINVAL;
- memset(std, 0, sizeof(*std));
- snprintf(std->name, sizeof(std->name), "%dx%d, %dfps",
- go->board_info->sensor_width,
- go->board_info->sensor_height,
- go->board_info->sensor_framerate / 1000);
- std->frameperiod.numerator = 1001;
- std->frameperiod.denominator =
- go->board_info->sensor_framerate;
+ schedule();
}
- return 0;
+ finish_wait(&go->frame_waitq, &wait);
}
- case VIDIOC_G_STD:
- {
- v4l2_std_id *std = arg;
+ if (gobuf->state != BUF_STATE_DONE)
+ goto unlock_and_return;
+
+ spin_lock_irqsave(&go->spinlock, flags);
+ deactivate_buffer(gobuf);
+ spin_unlock_irqrestore(&go->spinlock, flags);
+ frame_type_flag = get_frame_type_flag(gobuf, go->format);
+ gobuf->state = BUF_STATE_IDLE;
+
+ memset(buf, 0, sizeof(*buf));
+ buf->index = gobuf->index;
+ buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf->bytesused = gobuf->bytesused;
+ buf->flags = V4L2_BUF_FLAG_MAPPED | frame_type_flag;
+ buf->field = V4L2_FIELD_NONE;
+ buf->timestamp = gobuf->timestamp;
+ buf->sequence = gobuf->seq;
+ buf->memory = V4L2_MEMORY_MMAP;
+ buf->m.offset = gobuf->index * GO7007_BUF_SIZE;
+ buf->length = GO7007_BUF_SIZE;
+ buf->reserved = gobuf->modet_active;
- if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
- go->input == go->board_info->num_inputs - 1) {
- if (!go->i2c_adapter_online)
- return -EIO;
- i2c_clients_command(&go->i2c_adapter,
- VIDIOC_G_STD, arg);
- } else if (go->board_info->sensor_flags & GO7007_SENSOR_TV) {
- if (go->standard == GO7007_STD_NTSC)
- *std = V4L2_STD_NTSC;
- else
- *std = V4L2_STD_PAL | V4L2_STD_SECAM;
- } else
- *std = 0;
- return 0;
+ up(&gofh->lock);
+ return 0;
+
+unlock_and_return:
+ up(&gofh->lock);
+ return retval;
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ int retval = 0;
+
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ down(&gofh->lock);
+ down(&go->hw_lock);
+
+ if (!go->streaming) {
+ go->streaming = 1;
+ go->next_seq = 0;
+ go->active_buf = NULL;
+ if (go7007_start_encoder(go) < 0)
+ retval = -EIO;
+ else
+ retval = 0;
}
- case VIDIOC_S_STD:
- {
- v4l2_std_id *std = arg;
+ up(&go->hw_lock);
+ up(&gofh->lock);
- if (go->streaming)
- return -EBUSY;
- if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
- *std != 0)
- return -EINVAL;
- if (*std == 0)
- return -EINVAL;
- if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
- go->input == go->board_info->num_inputs - 1) {
- if (!go->i2c_adapter_online)
- return -EIO;
- i2c_clients_command(&go->i2c_adapter,
- VIDIOC_S_STD, arg);
- if (!*std) /* hack to indicate EINVAL from tuner */
- return -EINVAL;
- }
- if (*std & V4L2_STD_NTSC) {
- go->standard = GO7007_STD_NTSC;
- go->sensor_framerate = 30000;
- } else if (*std & V4L2_STD_PAL) {
- go->standard = GO7007_STD_PAL;
- go->sensor_framerate = 25025;
- } else if (*std & V4L2_STD_SECAM) {
- go->standard = GO7007_STD_PAL;
- go->sensor_framerate = 25025;
- } else
+ return retval;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type type)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ down(&gofh->lock);
+ go7007_streamoff(go);
+ up(&gofh->lock);
+
+ return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+ struct v4l2_queryctrl *query)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (!go->i2c_adapter_online)
+ return -EIO;
+
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, query);
+
+ return (!query->name[0]) ? -EINVAL : 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ struct v4l2_queryctrl query;
+
+ if (!go->i2c_adapter_online)
+ return -EIO;
+
+ memset(&query, 0, sizeof(query));
+ query.id = ctrl->id;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
+ if (query.name[0] == 0)
+ return -EINVAL;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_G_CTRL, ctrl);
+
+ return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+ struct v4l2_control *ctrl)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ struct v4l2_queryctrl query;
+
+ if (!go->i2c_adapter_online)
+ return -EIO;
+
+ memset(&query, 0, sizeof(query));
+ query.id = ctrl->id;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_QUERYCTRL, &query);
+ if (query.name[0] == 0)
+ return -EINVAL;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_CTRL, ctrl);
+
+ return 0;
+}
+
+static int vidioc_g_parm(struct file *filp, void *priv,
+ struct v4l2_streamparm *parm)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ struct v4l2_fract timeperframe = {
+ .numerator = 1001 * go->fps_scale,
+ .denominator = go->sensor_framerate,
+ };
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+ parm->parm.capture.timeperframe = timeperframe;
+
+ return 0;
+}
+
+static int vidioc_s_parm(struct file *filp, void *priv,
+ struct v4l2_streamparm *parm)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+ unsigned int n, d;
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+ if (parm->parm.capture.capturemode != 0)
+ return -EINVAL;
+
+ n = go->sensor_framerate *
+ parm->parm.capture.timeperframe.numerator;
+ d = 1001 * parm->parm.capture.timeperframe.denominator;
+ if (n != 0 && d != 0 && n > d)
+ go->fps_scale = (n + d/2) / d;
+ else
+ go->fps_scale = 1;
+
+ return 0;
+}
+
+/* VIDIOC_ENUMSTD on go7007 were used for enumberating the supported fps and
+ its resolution, when the device is not connected to TV.
+ This were an API abuse, probably used by the lack of specific IOCTL's to
+ enumberate it, by the time the driver were written.
+
+ However, since kernel 2.6.19, two new ioctls (VIDIOC_ENUM_FRAMEINTERVALS
+ and VIDIOC_ENUM_FRAMESIZES) were added for this purpose.
+
+ The two functions bellow implements the newer ioctls
+*/
+static int vidioc_enum_framesizes(struct file *filp, void *priv,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ /* Return -EINVAL, if it is a TV board */
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
+ (go->board_info->sensor_flags & GO7007_SENSOR_TV))
+ return -EINVAL;
+
+ if (fsize->index > 0)
+ return -EINVAL;
+
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = go->board_info->sensor_width;
+ fsize->discrete.height = go->board_info->sensor_height;
+
+ return 0;
+}
+
+static int vidioc_enum_frameintervals(struct file *filp, void *priv,
+ struct v4l2_frmivalenum *fival)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ /* Return -EINVAL, if it is a TV board */
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) ||
+ (go->board_info->sensor_flags & GO7007_SENSOR_TV))
+ return -EINVAL;
+
+ if (fival->index > 0)
+ return -EINVAL;
+
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1001;
+ fival->discrete.denominator = go->board_info->sensor_framerate;
+
+ return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (go->streaming)
+ return -EBUSY;
+
+ if (!(go->board_info->sensor_flags & GO7007_SENSOR_TV) &&
+ *std != 0)
+ return -EINVAL;
+
+ if (*std == 0)
+ return -EINVAL;
+
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ go->input == go->board_info->num_inputs - 1) {
+ if (!go->i2c_adapter_online)
+ return -EIO;
+ i2c_clients_command(&go->i2c_adapter,
+ VIDIOC_S_STD, std);
+ if (!*std) /* hack to indicate EINVAL from tuner */
return -EINVAL;
- if (go->i2c_adapter_online)
- i2c_clients_command(&go->i2c_adapter,
- VIDIOC_S_STD, std);
- set_capture_size(go, NULL, 0);
- return 0;
}
+
+ if (*std & V4L2_STD_NTSC) {
+ go->standard = GO7007_STD_NTSC;
+ go->sensor_framerate = 30000;
+ } else if (*std & V4L2_STD_PAL) {
+ go->standard = GO7007_STD_PAL;
+ go->sensor_framerate = 25025;
+ } else if (*std & V4L2_STD_SECAM) {
+ go->standard = GO7007_STD_PAL;
+ go->sensor_framerate = 25025;
+ } else
+ return -EINVAL;
+
+ if (go->i2c_adapter_online)
+ i2c_clients_command(&go->i2c_adapter,
+ VIDIOC_S_STD, std);
+ set_capture_size(go, NULL, 0);
+
+ return 0;
+}
+
+#if 0
case VIDIOC_QUERYSTD:
{
v4l2_std_id *std = arg;
@@ -884,219 +1195,269 @@ static int go7007_do_ioctl(struct inode *inode, struct file *file,
*std = 0;
return 0;
}
- case VIDIOC_ENUMINPUT:
- {
- struct v4l2_input *inp = arg;
- int index;
+#endif
- if (inp->index >= go->board_info->num_inputs)
- return -EINVAL;
- index = inp->index;
- memset(inp, 0, sizeof(*inp));
- inp->index = index;
- strncpy(inp->name, go->board_info->inputs[index].name,
- sizeof(inp->name));
- /* If this board has a tuner, it will be the last input */
- if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
- index == go->board_info->num_inputs - 1)
- inp->type = V4L2_INPUT_TYPE_TUNER;
- else
- inp->type = V4L2_INPUT_TYPE_CAMERA;
- inp->audioset = 0;
- inp->tuner = 0;
- if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
- inp->std = V4L2_STD_NTSC | V4L2_STD_PAL |
- V4L2_STD_SECAM;
- else
- inp->std = 0;
- return 0;
- }
- case VIDIOC_G_INPUT:
- {
- int *input = arg;
+static int vidioc_enum_input(struct file *file, void *priv,
+ struct v4l2_input *inp)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
- *input = go->input;
- return 0;
- }
- case VIDIOC_S_INPUT:
- {
- int *input = arg;
+ if (inp->index >= go->board_info->num_inputs)
+ return -EINVAL;
- if (*input >= go->board_info->num_inputs)
- return -EINVAL;
- if (go->streaming)
- return -EBUSY;
- go->input = *input;
- if (go->i2c_adapter_online) {
- i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT,
- &go->board_info->inputs[*input].video_input);
- i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO,
- &go->board_info->inputs[*input].audio_input);
- }
- return 0;
- }
- case VIDIOC_G_TUNER:
- {
- struct v4l2_tuner *t = arg;
+ strncpy(inp->name, go->board_info->inputs[inp->index].name,
+ sizeof(inp->name));
- if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
- return -EINVAL;
- if (t->index != 0)
- return -EINVAL;
- if (!go->i2c_adapter_online)
- return -EIO;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, arg);
- t->index = 0;
- return 0;
- }
- case VIDIOC_S_TUNER:
- {
- struct v4l2_tuner *t = arg;
+ /* If this board has a tuner, it will be the last input */
+ if ((go->board_info->flags & GO7007_BOARD_HAS_TUNER) &&
+ inp->index == go->board_info->num_inputs - 1)
+ inp->type = V4L2_INPUT_TYPE_TUNER;
+ else
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
- if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
- return -EINVAL;
- if (t->index != 0)
- return -EINVAL;
- if (!go->i2c_adapter_online)
- return -EIO;
- switch (go->board_id) {
- case GO7007_BOARDID_PX_TV402U_NA:
- case GO7007_BOARDID_PX_TV402U_JP:
- /* No selectable options currently */
- if (t->audmode != V4L2_TUNER_MODE_STEREO)
- return -EINVAL;
- break;
- }
- i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, arg);
- return 0;
- }
- case VIDIOC_G_FREQUENCY:
- {
- struct v4l2_frequency *f = arg;
+ inp->audioset = 0;
+ inp->tuner = 0;
+ if (go->board_info->sensor_flags & GO7007_SENSOR_TV)
+ inp->std = V4L2_STD_NTSC | V4L2_STD_PAL |
+ V4L2_STD_SECAM;
+ else
+ inp->std = 0;
- if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
- return -EINVAL;
- if (!go->i2c_adapter_online)
- return -EIO;
- memset(f, 0, sizeof(*f));
- f->type = V4L2_TUNER_ANALOG_TV;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, arg);
- return 0;
- }
- case VIDIOC_S_FREQUENCY:
- {
- if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
- return -EINVAL;
- if (!go->i2c_adapter_online)
- return -EIO;
- i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, arg);
- return 0;
- }
- case VIDIOC_CROPCAP:
- {
- struct v4l2_cropcap *cropcap = arg;
+ return 0;
+}
- if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- memset(cropcap, 0, sizeof(*cropcap));
- cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- /* These specify the raw input of the sensor */
- switch (go->standard) {
- case GO7007_STD_NTSC:
- cropcap->bounds.top = 0;
- cropcap->bounds.left = 0;
- cropcap->bounds.width = 720;
- cropcap->bounds.height = 480;
- cropcap->defrect.top = 0;
- cropcap->defrect.left = 0;
- cropcap->defrect.width = 720;
- cropcap->defrect.height = 480;
- break;
- case GO7007_STD_PAL:
- cropcap->bounds.top = 0;
- cropcap->bounds.left = 0;
- cropcap->bounds.width = 720;
- cropcap->bounds.height = 576;
- cropcap->defrect.top = 0;
- cropcap->defrect.left = 0;
- cropcap->defrect.width = 720;
- cropcap->defrect.height = 576;
- break;
- case GO7007_STD_OTHER:
- cropcap->bounds.top = 0;
- cropcap->bounds.left = 0;
- cropcap->bounds.width = go->board_info->sensor_width;
- cropcap->bounds.height = go->board_info->sensor_height;
- cropcap->defrect.top = 0;
- cropcap->defrect.left = 0;
- cropcap->defrect.width = go->board_info->sensor_width;
- cropcap->defrect.height = go->board_info->sensor_height;
- break;
- }
- return 0;
- }
- case VIDIOC_G_CROP:
- {
- struct v4l2_crop *crop = arg;
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
- memset(crop, 0, sizeof(*crop));
- crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- /* These specify the raw input of the sensor */
- switch (go->standard) {
- case GO7007_STD_NTSC:
- crop->c.top = 0;
- crop->c.left = 0;
- crop->c.width = 720;
- crop->c.height = 480;
- break;
- case GO7007_STD_PAL:
- crop->c.top = 0;
- crop->c.left = 0;
- crop->c.width = 720;
- crop->c.height = 576;
- break;
- case GO7007_STD_OTHER:
- crop->c.top = 0;
- crop->c.left = 0;
- crop->c.width = go->board_info->sensor_width;
- crop->c.height = go->board_info->sensor_height;
- break;
- }
+ *input = go->input;
- return 0;
+ return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (input >= go->board_info->num_inputs)
+ return -EINVAL;
+ if (go->streaming)
+ return -EBUSY;
+
+ go->input = input;
+ if (go->i2c_adapter_online) {
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_INPUT,
+ &go->board_info->inputs[input].video_input);
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_AUDIO,
+ &go->board_info->inputs[input].audio_input);
}
- case VIDIOC_S_CROP:
- {
- struct v4l2_crop *crop = arg;
- if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *t)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (t->index != 0)
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_G_TUNER, t);
+
+ t->index = 0;
+ return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *t)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (t->index != 0)
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+
+ switch (go->board_id) {
+ case GO7007_BOARDID_PX_TV402U_NA:
+ case GO7007_BOARDID_PX_TV402U_JP:
+ /* No selectable options currently */
+ if (t->audmode != V4L2_TUNER_MODE_STEREO)
return -EINVAL;
- return 0;
+ break;
}
- case VIDIOC_G_JPEGCOMP:
- {
- struct v4l2_jpegcompression *params = arg;
- memset(params, 0, sizeof(*params));
- params->quality = 50; /* ?? */
- params->jpeg_markers = V4L2_JPEG_MARKER_DHT |
- V4L2_JPEG_MARKER_DQT;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_TUNER, t);
- return 0;
+ return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+
+ f->type = V4L2_TUNER_ANALOG_TV;
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_G_FREQUENCY, f);
+ return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (!(go->board_info->flags & GO7007_BOARD_HAS_TUNER))
+ return -EINVAL;
+ if (!go->i2c_adapter_online)
+ return -EIO;
+
+ i2c_clients_command(&go->i2c_adapter, VIDIOC_S_FREQUENCY, f);
+
+ return 0;
+}
+
+static int vidioc_cropcap(struct file *file, void *priv,
+ struct v4l2_cropcap *cropcap)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ /* These specify the raw input of the sensor */
+ switch (go->standard) {
+ case GO7007_STD_NTSC:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 480;
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 480;
+ break;
+ case GO7007_STD_PAL:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 576;
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 576;
+ break;
+ case GO7007_STD_OTHER:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = go->board_info->sensor_width;
+ cropcap->bounds.height = go->board_info->sensor_height;
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = go->board_info->sensor_width;
+ cropcap->defrect.height = go->board_info->sensor_height;
+ break;
}
- case VIDIOC_S_JPEGCOMP:
- {
- struct v4l2_jpegcompression *params = arg;
- if (params->quality != 50 ||
- params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
- V4L2_JPEG_MARKER_DQT))
- return -EINVAL;
- return 0;
+ return 0;
+}
+
+static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+ struct go7007_file *gofh = priv;
+ struct go7007 *go = gofh->go;
+
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ crop->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ /* These specify the raw input of the sensor */
+ switch (go->standard) {
+ case GO7007_STD_NTSC:
+ crop->c.top = 0;
+ crop->c.left = 0;
+ crop->c.width = 720;
+ crop->c.height = 480;
+ break;
+ case GO7007_STD_PAL:
+ crop->c.top = 0;
+ crop->c.left = 0;
+ crop->c.width = 720;
+ crop->c.height = 576;
+ break;
+ case GO7007_STD_OTHER:
+ crop->c.top = 0;
+ crop->c.left = 0;
+ crop->c.width = go->board_info->sensor_width;
+ crop->c.height = go->board_info->sensor_height;
+ break;
}
+
+ return 0;
+}
+
+/* FIXME: vidioc_s_crop is not really implemented!!!
+ */
+static int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+ if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int vidioc_g_jpegcomp(struct file *file, void *priv,
+ struct v4l2_jpegcompression *params)
+{
+ memset(params, 0, sizeof(*params));
+ params->quality = 50; /* ?? */
+ params->jpeg_markers = V4L2_JPEG_MARKER_DHT |
+ V4L2_JPEG_MARKER_DQT;
+
+ return 0;
+}
+
+static int vidioc_s_jpegcomp(struct file *file, void *priv,
+ struct v4l2_jpegcompression *params)
+{
+ if (params->quality != 50 ||
+ params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
+ V4L2_JPEG_MARKER_DQT))
+ return -EINVAL;
+
+ return 0;
+}
+
+/* FIXME:
+ Those ioctls are private, and not needed, since several standard
+ extended controls already provide streaming control.
+ So, those ioctls should be converted into vidioc_g_ext_ctrls()
+ and vidioc_s_ext_ctrls()
+ */
+
+#if 0
/* Temporary ioctls for controlling compression characteristics */
case GO7007IOC_S_BITRATE:
{
@@ -1316,27 +1677,7 @@ static int go7007_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
return clip_to_modet_map(go, region->region, region->clips);
}
- default:
- printk(KERN_DEBUG "go7007: unsupported ioctl %d\n", cmd);
- return -ENOIOCTLCMD;
- }
- return 0;
-
-unlock_and_return:
- up(&gofh->lock);
- return retval;
-}
-
-static int go7007_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct go7007_file *gofh = file->private_data;
-
- if (gofh->go->status != STATUS_ONLINE)
- return -EIO;
-
- return video_usercopy(inode, file, cmd, arg, go7007_do_ioctl);
-}
+#endif
static ssize_t go7007_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
@@ -1371,8 +1712,7 @@ static int go7007_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
page = alloc_page(GFP_USER | __GFP_DMA32);
if (!page)
return VM_FAULT_OOM;
- clear_user_page(page_address(page), (unsigned long)vmf->virtual_address,
- page);
+ clear_user_highpage(page, (unsigned long)vmf->virtual_address);
vmf->page = page;
return 0;
}
@@ -1441,23 +1781,59 @@ static void go7007_vfl_release(struct video_device *vfd)
kfree(go);
}
-static struct file_operations go7007_fops = {
+static struct v4l2_file_operations go7007_fops = {
.owner = THIS_MODULE,
.open = go7007_open,
.release = go7007_release,
- .ioctl = go7007_ioctl,
- .llseek = no_llseek,
+ .ioctl = video_ioctl2,
.read = go7007_read,
.mmap = go7007_mmap,
.poll = go7007_poll,
};
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_queryctrl = vidioc_queryctrl,
+ .vidioc_g_ctrl = vidioc_g_ctrl,
+ .vidioc_s_ctrl = vidioc_s_ctrl,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+ .vidioc_g_parm = vidioc_g_parm,
+ .vidioc_s_parm = vidioc_s_parm,
+ .vidioc_enum_framesizes = vidioc_enum_framesizes,
+ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+ .vidioc_cropcap = vidioc_cropcap,
+ .vidioc_g_crop = vidioc_g_crop,
+ .vidioc_s_crop = vidioc_s_crop,
+ .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
+ .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
+};
+
static struct video_device go7007_template = {
.name = "go7007",
.vfl_type = VID_TYPE_CAPTURE,
.fops = &go7007_fops,
.minor = -1,
.release = go7007_vfl_release,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = V4L2_STD_ALL,
+ .current_norm = V4L2_STD_NTSC,
};
int go7007_v4l2_init(struct go7007 *go)
@@ -1477,6 +1853,8 @@ int go7007_v4l2_init(struct go7007 *go)
}
video_set_drvdata(go->video_dev, go);
++go->ref_count;
+ printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
+ go->video_dev->name, go->video_dev->num);
return 0;
}
diff --git a/drivers/staging/go7007/go7007.txt b/drivers/staging/go7007/go7007.txt
new file mode 100644
index 000000000000..9f6772bc68c2
--- /dev/null
+++ b/drivers/staging/go7007/go7007.txt
@@ -0,0 +1,481 @@
+This is a driver for the WIS GO7007SB multi-format video encoder.
+
+Pete Eberlein <pete@sensoray.com>
+
+The driver was orignally released under the GPL and is currently hosted at:
+http://nikosapi.org/wiki/index.php/WIS_Go7007_Linux_driver
+The go7007 firmware can be acquired from the package on the site above.
+
+I've modified the driver to support the following Video4Linux2 MPEG
+controls, with acceptable values:
+
+V4L2_CID_MPEG_STREAM_TYPE V4L2_MPEG_STREAM_TYPE_MPEG2_DVD
+ V4L2_MPEG_STREAM_TYPE_MPEG_ELEM
+V4L2_CID_MPEG_VIDEO_ENCODING V4L2_MPEG_VIDEO_ENCODING_MPEG_1
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_2
+ V4L2_MPEG_VIDEO_ENCODING_MPEG_4
+V4L2_CID_MPEG_VIDEO_ASPECT V4L2_MPEG_VIDEO_ASPECT_1x1
+ V4L2_MPEG_VIDEO_ASPECT_4x3
+ V4L2_MPEG_VIDEO_ASPECT_16x9
+V4L2_CID_MPEG_VIDEO_GOP_SIZE integer
+V4L2_CID_MPEG_VIDEO_BITRATE 64000 .. 10000000
+
+These should be used instead of the non-standard GO7007 ioctls described
+below.
+
+
+The README files from the orignal package appear below:
+
+---------------------------------------------------------------------------
+ WIS GO7007SB Public Linux Driver
+---------------------------------------------------------------------------
+
+
+*** Please see the file RELEASE-NOTES for important last-minute updates ***
+
+
+ 0. OVERVIEW AND LICENSING/DISCLAIMER
+
+
+This driver kit contains Linux drivers for the WIS GO7007SB multi-format
+video encoder. Only kernel version 2.6.x is supported. The video stream
+is available through the Video4Linux2 API and the audio stream is available
+through the ALSA API (or the OSS emulation layer of the ALSA system).
+
+The files in kernel/ and hotplug/ are licensed under the GNU General Public
+License Version 2 from the Free Software Foundation. A copy of the license
+is included in the file COPYING.
+
+The example applications in apps/ and C header files in include/ are
+licensed under a permissive license included in the source files which
+allows copying, modification and redistribution for any purpose without
+attribution.
+
+The firmware files included in the firmware/ directory may be freely
+redistributed only in conjunction with this document; but modification,
+tampering and reverse engineering are prohibited.
+
+MICRONAS USA, INC., MAKES NO WARRANTIES TO ANY PERSON OR ENTITY WITH
+RESPECT TO THE SOFTWARE OR ANY DERIVATIVES THEREOF OR ANY SERVICES OR
+LICENSES AND DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT LIMITATION
+WARRANTIES OF MERCHANTABILITY, SUPPORT, AND FITNESS FOR A PARTICULAR
+PURPOSE AND NON-INFRINGEMENT.
+
+
+ 1. SYSTEM REQUIREMENTS
+
+
+This driver requires Linux kernel 2.6. Kernel 2.4 is not supported. Using
+kernel 2.6.10 or later is recommended, as earlier kernels are known to have
+unstable USB 2.0 support.
+
+A fully built kernel source tree must be available. Typically this will be
+linked from "/lib/modules/<KERNEL VERSION>/build" for convenience. If this
+link does not exist, an extra parameter will need to be passed to the
+`make` command.
+
+All vendor-built kernels should already be configured properly. However,
+for custom-built kernels, the following options need to be enabled in the
+kernel as built-in or modules:
+
+ CONFIG_HOTPLUG - Support for hot-pluggable devices
+ CONFIG_MODULES - Enable loadable module support
+ CONFIG_KMOD - Automatic kernel module loading
+ CONFIG_FW_LOADER - Hotplug firmware loading support
+ CONFIG_I2C - I2C support
+ CONFIG_VIDEO_DEV - Video For Linux
+ CONFIG_SOUND - Sound card support
+ CONFIG_SND - Advanced Linux Sound Architecture
+ CONFIG_USB - Support for Host-side USB
+ CONFIG_USB_DEVICEFS - USB device filesystem
+ CONFIG_USB_EHCI_HCD - EHCI HCD (USB 2.0) support
+
+Additionally, to use the example application, the following options need to
+be enabled in the ALSA section:
+
+ CONFIG_SND_MIXER_OSS - OSS Mixer API
+ CONFIG_SND_PCM_OSS - OSS PCM (digital audio) API
+
+The hotplug scripts, along with the fxload utility, must also be installed.
+These scripts can be obtained from <http://linux-hotplug.sourceforge.net/>.
+Hotplugging is used for loading firmware into the Cypruss EZ-USB chip using
+fxload and for loading firmware into the driver using the firmware agent.
+
+
+ 2. COMPILING AND INSTALLING THE DRIVER
+
+
+Most users should be able to compile the driver by simply running:
+
+ $ make
+
+in the top-level directory of the driver kit. First the kernel modules
+will be built, followed by the example applications.
+
+If the build system is unable to locate the kernel source tree for the
+currently-running kernel, or if the module should be built for a kernel
+other than the currently-running kernel, an additional parameter will need
+to be passed to make to specify the appropriate kernel source directory:
+
+ $ make KERNELSRC=/usr/src/linux-2.6.10-custom3
+
+Once the compile completes, the driver and firmware files should be
+installed by running:
+
+ $ make install
+
+The kernel modules will be placed in "/lib/modules/<KERNEL VERSION>/extra"
+and the firmware files will be placed in the appropriate hotplug firmware
+directory, usually /lib/firmware. In addition, USB maps and scripts will
+be placed in /etc/hotplug/usb to enable fxload to initialize the EZ-USB
+control chip when the device is connected.
+
+
+ 3. PAL/SECAM TUNER CONFIGURATION (TV402U-EU only)
+
+
+The PAL model of the Plextor ConvertX TV402U may require additional
+configuration to correctly select the appropriate TV frequency band and
+audio subchannel.
+
+Users with a device other than the Plextor ConvertX TV402U-EU should skip
+this section.
+
+The wide variety of PAL TV systems used in Europe requires that additional
+information about the local TV standards be passed to the driver in order
+to properly tune TV channels. The two necessary parameters are (a) the PAL
+TV band, and (b) the audio subchannel format in use.
+
+In many cases, the appropriate TV band selection is passed to the driver
+from applications. However, in some cases, the application only specifies
+that the driver should use PAL but not the specific information about the
+appropriate TV band. To work around this issue, the correct TV band may be
+specified in the "force_band" parameter to the wis-sony-tuner module:
+
+ TV band force_band
+ ------- ----------
+ PAL B/G B
+ PAL I I
+ PAL D/K D
+ SECAM L L
+
+If the "force_band" parameter is specified, the driver will ignore any TV
+band specified by applications and will always use the band provided in the
+module parameter.
+
+The other parameter that can be specified is the audio subchannel format.
+There are several stereo audio carrier systems in use, including NICAM and
+three varieties of A2. To receive audio broadcast on one of these stereo
+carriers, the "force_mpx_mode" parameter must be specified to the
+wis-sony-tuner module.
+
+ TV band Audio subcarrier force_mpx_mode
+ ------- ---------------- --------------
+ PAL B/G Mono (default) 1
+ PAL B/G A2 2
+ PAL B/G NICAM 3
+ PAL I Mono (default) 4
+ PAL I NICAM 5
+ PAL D/K Mono (default) 6
+ PAL D/K A2 (1) 7
+ PAL D/K A2 (2) 8
+ PAL D/K A2 (3) 9
+ PAL D/K NICAM 10
+ SECAM L Mono (default) 11
+ SECAM L NICAM 12
+
+If the "force_mpx_mode" parameter is not specified, the correct mono-only
+mode will be chosen based on the TV band. However, the tuner will not
+receive stereo audio or bilingual broadcasts correctly.
+
+To pass the "force_band" or "force_mpx_mode" parameters to the
+wis-sony-tuner module, the following line must be added to the modprobe
+configuration file, which varies from one Linux distribution to another.
+
+ options wis-sony-tuner force_band=B force_mpx_mode=2
+
+The above example would force the tuner to the PAL B/G TV band and receive
+stereo audio broadcasts on the A2 carrier.
+
+To verify that the configuration has been placed in the correct location,
+execute:
+
+ $ modprobe -c | grep wis-sony-tuner
+
+If the configuration line appears, then modprobe will pass the parameters
+correctly the next time the wis-sony-tuner module is loaded into the
+kernel.
+
+
+ 4. TESTING THE DRIVER
+
+
+Because few Linux applications are able to correctly capture from
+Video4Linux2 devices with only compressed formats supported, the new driver
+should be tested with the "gorecord" application in the apps/ directory.
+
+First connect a video source to the device, such as a DVD player or VCR.
+This will be captured to a file for testing the driver. If an input source
+is unavailable, a test file can still be captured, but the video will be
+black and the audio will be silent.
+
+This application will auto-detect the V4L2 and ALSA/OSS device names of the
+hardware and will record video and audio to an AVI file for a specified
+number of seconds. For example:
+
+ $ apps/gorecord -duration 60 capture.avi
+
+If this application does not successfully record an AVI file, the error
+messages produced by gorecord and recorded in the system log (usually in
+/var/log/messages) should provide information to help resolve the problem.
+
+Supplying no parameters to gorecord will cause it to probe the available
+devices and exit. Use the -help flag for usage information.
+
+
+ 5. USING THE DRIVER
+
+
+The V4L2 device implemented by the driver provides a standard compressed
+format API, within the following criteria:
+
+ * Applications that only support the original Video4Linux1 API will not
+ be able to communicate with this driver at all.
+
+ * No raw video modes are supported, so applications like xawtv that
+ expect only uncompressed video will not function.
+
+ * Supported compression formats are: Motion-JPEG, MPEG1, MPEG2 and MPEG4.
+
+ * MPEG video formats are delivered as Video Elementary Streams only.
+ Program Stream (PS), Transport Stream (TS) and Packetized Elementary
+ Stream (PES) formats are not supported.
+
+ * Video parameters such as format and input port may not be changed while
+ the encoder is active.
+
+ * The audio capture device only functions when the video encoder is
+ actively capturing video. Attempts to read from the audio device when
+ the encoder is inactive will result in an I/O error.
+
+ * The native format of the audio device is 48Khz 2-channel 16-bit
+ little-endian PCM, delivered through the ALSA system. No audio
+ compression is implemented in the hardware. ALSA may convert to other
+ uncompressed formats on the fly.
+
+The include/ directory contains a C header file describing non-standard
+features of the GO7007SB encoder, which are described below:
+
+
+ GO7007IOC_S_COMP_PARAMS, GO7007IOC_G_COMP_PARAMS
+
+ These ioctls are used to negotiate general compression parameters.
+
+ To query the current parameters, call the GO7007IOC_G_COMP_PARAMS ioctl
+ with a pointer to a struct go7007_comp_params. If the driver is not
+ set to MPEG format, the EINVAL error code will be returned.
+
+ To change the current parameters, initialize all fields of a struct
+ go7007_comp_params and call the GO7007_IOC_S_COMP_PARAMS ioctl with a
+ pointer to this structure. The driver will return the current
+ parameters with any necessary changes to conform to the limitations of
+ the hardware or current compression mode. Any or all fields can be set
+ to zero to request a reasonable default value. If the driver is not
+ set to MPEG format, the EINVAL error code will be returned. When I/O
+ is in progress, the EBUSY error code will be returned.
+
+ Fields in struct go7007_comp_params:
+
+ __u32 The maximum number of frames in each
+ gop_size Group Of Pictures; i.e. the maximum
+ number of frames minus one between
+ each key frame.
+
+ __u32 The maximum number of sequential
+ max_b_frames bidirectionally-predicted frames.
+ (B-frames are not yet supported.)
+
+ enum go7007_aspect_ratio The aspect ratio to be encoded in the
+ aspect_ratio meta-data of the compressed format.
+
+ Choices are:
+ GO7007_ASPECT_RATIO_1_1
+ GO7007_ASPECT_RATIO_4_3_NTSC
+ GO7007_ASPECT_RATIO_4_3_PAL
+ GO7007_ASPECT_RATIO_16_9_NTSC
+ GO7007_ASPECT_RATIO_16_9_PAL
+
+ __u32 Bit-wise OR of control flags (below)
+ flags
+
+ Flags in struct go7007_comp_params:
+
+ GO7007_COMP_CLOSED_GOP Only produce self-contained GOPs, used
+ to produce streams appropriate for
+ random seeking.
+
+ GO7007_COMP_OMIT_SEQ_HEADER Omit the stream sequence header.
+
+
+ GO7007IOC_S_MPEG_PARAMS, GO7007IOC_G_MPEG_PARAMS
+
+ These ioctls are used to negotiate MPEG-specific stream parameters when
+ the pixelformat has been set to V4L2_PIX_FMT_MPEG.
+
+ To query the current parameters, call the GO7007IOC_G_MPEG_PARAMS ioctl
+ with a pointer to a struct go7007_mpeg_params. If the driver is not
+ set to MPEG format, the EINVAL error code will be returned.
+
+ To change the current parameters, initialize all fields of a struct
+ go7007_mpeg_params and call the GO7007_IOC_S_MPEG_PARAMS ioctl with a
+ pointer to this structure. The driver will return the current
+ parameters with any necessary changes to conform to the limitations of
+ the hardware or selected MPEG mode. Any or all fields can be set to
+ zero to request a reasonable default value. If the driver is not set
+ to MPEG format, the EINVAL error code will be returned. When I/O is in
+ progress, the EBUSY error code will be returned.
+
+ Fields in struct go7007_mpeg_params:
+
+ enum go7007_mpeg_video_standard
+ mpeg_video_standard The MPEG video standard in which to
+ compress the video.
+
+ Choices are:
+ GO7007_MPEG_VIDEO_MPEG1
+ GO7007_MPEG_VIDEO_MPEG2
+ GO7007_MPEG_VIDEO_MPEG4
+
+ __u32 Bit-wise OR of control flags (below)
+ flags
+
+ __u32 The profile and level indication to be
+ pali stored in the sequence header. This
+ is only used as an indicator to the
+ decoder, and does not affect the MPEG
+ features used in the video stream.
+ Not valid for MPEG1.
+
+ Choices for MPEG2 are:
+ GO7007_MPEG2_PROFILE_MAIN_MAIN
+
+ Choices for MPEG4 are:
+ GO7007_MPEG4_PROFILE_S_L0
+ GO7007_MPEG4_PROFILE_S_L1
+ GO7007_MPEG4_PROFILE_S_L2
+ GO7007_MPEG4_PROFILE_S_L3
+ GO7007_MPEG4_PROFILE_ARTS_L1
+ GO7007_MPEG4_PROFILE_ARTS_L2
+ GO7007_MPEG4_PROFILE_ARTS_L3
+ GO7007_MPEG4_PROFILE_ARTS_L4
+ GO7007_MPEG4_PROFILE_AS_L0
+ GO7007_MPEG4_PROFILE_AS_L1
+ GO7007_MPEG4_PROFILE_AS_L2
+ GO7007_MPEG4_PROFILE_AS_L3
+ GO7007_MPEG4_PROFILE_AS_L4
+ GO7007_MPEG4_PROFILE_AS_L5
+
+ Flags in struct go7007_mpeg_params:
+
+ GO7007_MPEG_FORCE_DVD_MODE Force all compression parameters and
+ bitrate control settings to comply
+ with DVD MPEG2 stream requirements.
+ This overrides most compression and
+ bitrate settings!
+
+ GO7007_MPEG_OMIT_GOP_HEADER Omit the GOP header.
+
+ GO7007_MPEG_REPEAT_SEQHEADER Repeat the MPEG sequence header at
+ the start of each GOP.
+
+
+ GO7007IOC_S_BITRATE, GO7007IOC_G_BITRATE
+
+ These ioctls are used to set and query the target bitrate value for the
+ compressed video stream. The bitrate may be selected by storing the
+ target bits per second in an int and calling GO7007IOC_S_BITRATE with a
+ pointer to the int. The bitrate may be queried by calling
+ GO7007IOC_G_BITRATE with a pointer to an int where the current bitrate
+ will be stored.
+
+ Note that this is the primary means of controlling the video quality
+ for all compression modes, including V4L2_PIX_FMT_MJPEG. The
+ VIDIOC_S_JPEGCOMP ioctl is not supported.
+
+
+----------------------------------------------------------------------------
+ Installing the WIS PCI Voyager Driver
+---------------------------------------------------------------------------
+
+The WIS PCI Voyager driver requires several patches to the Linux 2.6.11.x
+kernel source tree before compiling the driver. These patches update the
+in-kernel SAA7134 driver to the newest development version and patch bugs
+in the TDA8290/TDA8275 tuner driver.
+
+The following patches must be downloaded from Gerd Knorr's website and
+applied in the order listed:
+
+ http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner
+ http://dl.bytesex.org/patches/2.6.11-2/i2c-tuner2
+ http://dl.bytesex.org/patches/2.6.11-2/v4l2-api-mpeg
+ http://dl.bytesex.org/patches/2.6.11-2/saa7134-update
+
+The following patches are included with this SDK and can be applied in any
+order:
+
+ patches/2.6.11/saa7134-voyager.diff
+ patches/2.6.11/tda8275-newaddr.diff
+ patches/2.6.11/tda8290-ntsc.diff
+
+Check to make sure the CONFIG_VIDEO_SAA7134 option is enabled in the kernel
+configuration, and build and install the kernel.
+
+After rebooting into the new kernel, the GO7007 driver can be compiled and
+installed:
+
+ $ make SAA7134_BUILD=y
+ $ make install
+ $ modprobe saa7134-go7007
+
+There will be two V4L video devices associated with the PCI Voyager. The
+first device (most likely /dev/video0) provides access to the raw video
+capture mode of the SAA7133 device and is used to configure the source
+video parameters and tune the TV tuner. This device can be used with xawtv
+or other V4L(2) video software as a standard uncompressed device.
+
+The second device (most likely /dev/video1) provides access to the
+compression functions of the GO7007. It can be tested using the gorecord
+application in the apps/ directory of this SDK:
+
+ $ apps/gorecord -vdevice /dev/video1 -noaudio test.avi
+
+Currently the frame resolution is fixed at 720x480 (NTSC) or 720x576 (PAL),
+and the video standard must be specified to both the raw and the compressed
+video devices (xawtv and gorecord, for example).
+
+
+--------------------------------------------------------------------------
+RELEASE NOTES FOR WIS GO7007SB LINUX DRIVER
+---------------------------------------------------------------------------
+
+Last updated: 5 November 2005
+
+ - Release 0.9.7 includes new support for using udev to run fxload. The
+ install script should automatically detect whether the old hotplug
+ scripts or the new udev rules should be used. To force the use of
+ hotplug, run "make install USE_UDEV=n". To force the use of udev, run
+ "make install USE_UDEV=y".
+
+ - Motion detection is supported but undocumented. Try the `modet` app
+ for a demonstration of how to use the facility.
+
+ - Using USB2.0 devices such as the TV402U with USB1.1 HCDs or hubs can
+ cause buffer overruns and frame drops, even at low framerates, due to
+ inconsistency in the bitrate control mechanism.
+
+ - On devices with an SAA7115, including the Plextor ConvertX, video height
+ values of 96, 128, 160, 192, 256, 320, and 384 do not work in NTSC mode.
+ All valid heights up to 512 work correctly in PAL mode.
+
+ - The WIS Star Trek and PCI Voyager boards have no support yet for audio
+ or the TV tuner.
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c
new file mode 100644
index 000000000000..fb6845e37884
--- /dev/null
+++ b/drivers/staging/go7007/s2250-board.c
@@ -0,0 +1,630 @@
+/*
+ * Copyright (C) 2008 Sensoray Company Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include "go7007-priv.h"
+#include "wis-i2c.h"
+
+extern int s2250loader_init(void);
+extern void s2250loader_cleanup(void);
+
+#define TLV320_ADDRESS 0x34
+#define S2250_VIDDEC 0x86
+#define VPX322_ADDR_ANALOGCONTROL1 0x02
+#define VPX322_ADDR_BRIGHTNESS0 0x0127
+#define VPX322_ADDR_BRIGHTNESS1 0x0131
+#define VPX322_ADDR_CONTRAST0 0x0128
+#define VPX322_ADDR_CONTRAST1 0x0132
+#define VPX322_ADDR_HUE 0x00dc
+#define VPX322_ADDR_SAT 0x0030
+
+struct go7007_usb_board {
+ unsigned int flags;
+ struct go7007_board_info main_info;
+};
+
+struct go7007_usb {
+ struct go7007_usb_board *board;
+ struct semaphore i2c_lock;
+ struct usb_device *usbdev;
+ struct urb *video_urbs[8];
+ struct urb *audio_urbs[8];
+ struct urb *intr_urb;
+};
+
+static unsigned char aud_regs[] = {
+ 0x1e, 0x00,
+ 0x00, 0x17,
+ 0x02, 0x17,
+ 0x04, 0xf9,
+ 0x06, 0xf9,
+ 0x08, 0x02,
+ 0x0a, 0x00,
+ 0x0c, 0x00,
+ 0x0a, 0x00,
+ 0x0c, 0x00,
+ 0x0e, 0x02,
+ 0x10, 0x00,
+ 0x12, 0x01,
+ 0x00, 0x00,
+};
+
+
+static unsigned char vid_regs[] = {
+ 0xF2, 0x0f,
+ 0xAA, 0x00,
+ 0xF8, 0xff,
+ 0x00, 0x00,
+};
+
+static u16 vid_regs_fp[] = {
+ 0x028, 0x067,
+ 0x120, 0x016,
+ 0x121, 0xcF2,
+ 0x122, 0x0F2,
+ 0x123, 0x00c,
+ 0x124, 0x2d0,
+ 0x125, 0x2e0,
+ 0x126, 0x004,
+ 0x128, 0x1E0,
+ 0x12A, 0x016,
+ 0x12B, 0x0F2,
+ 0x12C, 0x0F2,
+ 0x12D, 0x00c,
+ 0x12E, 0x2d0,
+ 0x12F, 0x2e0,
+ 0x130, 0x004,
+ 0x132, 0x1E0,
+ 0x140, 0x060,
+ 0x153, 0x00C,
+ 0x154, 0x200,
+ 0x150, 0x801,
+ 0x000, 0x000
+};
+
+/* PAL specific values */
+static u16 vid_regs_fp_pal[] =
+{
+ 0x120, 0x017,
+ 0x121, 0xd22,
+ 0x122, 0x122,
+ 0x12A, 0x017,
+ 0x12B, 0x122,
+ 0x12C, 0x122,
+ 0x140, 0x060,
+ 0x000, 0x000,
+};
+
+struct s2250 {
+ int std;
+ int input;
+ int brightness;
+ int contrast;
+ int saturation;
+ int hue;
+ int reg12b_val;
+ int audio_input;
+};
+
+/* from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
+static int go7007_usb_vendor_request(struct go7007 *go, u16 request,
+ u16 value, u16 index, void *transfer_buffer, int length, int in)
+{
+ struct go7007_usb *usb = go->hpi_context;
+ int timeout = 5000;
+
+ if (in) {
+ return usb_control_msg(usb->usbdev,
+ usb_rcvctrlpipe(usb->usbdev, 0), request,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+ value, index, transfer_buffer, length, timeout);
+ } else {
+ return usb_control_msg(usb->usbdev,
+ usb_sndctrlpipe(usb->usbdev, 0), request,
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ value, index, transfer_buffer, length, timeout);
+ }
+}
+/* end from go7007-usb.c which is Copyright (C) 2005-2006 Micronas USA Inc.*/
+
+static int write_reg(struct i2c_client *client, u8 reg, u8 value)
+{
+ struct go7007 *go = i2c_get_adapdata(client->adapter);
+ struct go7007_usb *usb = go->hpi_context;
+ int rc;
+ int dev_addr = client->addr;
+ u8 *buf;
+
+ if (go == NULL)
+ return -ENODEV;
+
+ if (go->status == STATUS_SHUTDOWN)
+ return -EBUSY;
+
+ buf = kzalloc(16, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ if (down_interruptible(&usb->i2c_lock) != 0) {
+ printk(KERN_INFO "i2c lock failed\n");
+ return -EINTR;
+ }
+ rc = go7007_usb_vendor_request(go, 0x55, dev_addr,
+ (reg<<8 | value),
+ buf,
+ 16, 1);
+
+ up(&usb->i2c_lock);
+ kfree(buf);
+ return rc;
+}
+
+static int write_reg_fp(struct i2c_client *client, u16 addr, u16 val)
+{
+ struct go7007 *go = i2c_get_adapdata(client->adapter);
+ struct go7007_usb *usb = go->hpi_context;
+ u8 *buf;
+ struct s2250 *dec = i2c_get_clientdata(client);
+
+ if (go == NULL)
+ return -ENODEV;
+
+ if (go->status == STATUS_SHUTDOWN)
+ return -EBUSY;
+
+ buf = kzalloc(16, GFP_KERNEL);
+
+ if (buf == NULL)
+ return -ENOMEM;
+
+
+
+ memset(buf, 0xcd, 6);
+
+ if (down_interruptible(&usb->i2c_lock) != 0) {
+ printk(KERN_INFO "i2c lock failed\n");
+ return -EINTR;
+ }
+ if (go7007_usb_vendor_request(go, 0x57, addr, val, buf, 16, 1) < 0)
+ return -EFAULT;
+
+ up(&usb->i2c_lock);
+ if (buf[0] == 0) {
+ unsigned int subaddr, val_read;
+
+ subaddr = (buf[4] << 8) + buf[5];
+ val_read = (buf[2] << 8) + buf[3];
+ if (val_read != val) {
+ printk(KERN_INFO "invalid fp write %x %x\n",
+ val_read, val);
+ return -EFAULT;
+ }
+ if (subaddr != addr) {
+ printk(KERN_INFO "invalid fp write addr %x %x\n",
+ subaddr, addr);
+ return -EFAULT;
+ }
+ } else
+ return -EFAULT;
+
+ /* save last 12b value */
+ if (addr == 0x12b)
+ dec->reg12b_val = val;
+
+ return 0;
+}
+
+static int write_regs(struct i2c_client *client, u8 *regs)
+{
+ int i;
+
+ for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
+ if (write_reg(client, regs[i], regs[i+1]) < 0) {
+ printk(KERN_INFO "s2250: failed\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int write_regs_fp(struct i2c_client *client, u16 *regs)
+{
+ int i;
+
+ for (i = 0; !((regs[i] == 0x00) && (regs[i+1] == 0x00)); i += 2) {
+ if (write_reg_fp(client, regs[i], regs[i+1]) < 0) {
+ printk(KERN_INFO "s2250: failed fp\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+static int s2250_command(struct i2c_client *client,
+ unsigned int cmd, void *arg)
+{
+ struct s2250 *dec = i2c_get_clientdata(client);
+
+ switch (cmd) {
+ case VIDIOC_S_INPUT:
+ {
+ int vidsys;
+ int *input = arg;
+
+ vidsys = (dec->std == V4L2_STD_NTSC) ? 0x01 : 0x00;
+ if (*input == 0) {
+ /* composite */
+ write_reg_fp(client, 0x20, 0x020 | vidsys);
+ write_reg_fp(client, 0x21, 0x662);
+ write_reg_fp(client, 0x140, 0x060);
+ } else {
+ /* S-Video */
+ write_reg_fp(client, 0x20, 0x040 | vidsys);
+ write_reg_fp(client, 0x21, 0x666);
+ write_reg_fp(client, 0x140, 0x060);
+ }
+ dec->input = *input;
+ break;
+ }
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *std = arg;
+ u16 vidsource;
+
+ vidsource = (dec->input == 1) ? 0x040 : 0x020;
+ dec->std = *std;
+ switch (dec->std) {
+ case V4L2_STD_NTSC:
+ write_regs_fp(client, vid_regs_fp);
+ write_reg_fp(client, 0x20, vidsource | 1);
+ break;
+ case V4L2_STD_PAL:
+ write_regs_fp(client, vid_regs_fp);
+ write_regs_fp(client, vid_regs_fp_pal);
+ write_reg_fp(client, 0x20, vidsource);
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+ static const u32 user_ctrls[] = {
+ V4L2_CID_BRIGHTNESS,
+ V4L2_CID_CONTRAST,
+ V4L2_CID_SATURATION,
+ V4L2_CID_HUE,
+ 0
+ };
+ static const u32 *ctrl_classes[] = {
+ user_ctrls,
+ NULL
+ };
+
+ ctrl->id = v4l2_ctrl_next(ctrl_classes, ctrl->id);
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
+ break;
+ case V4L2_CID_CONTRAST:
+ v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
+ break;
+ case V4L2_CID_SATURATION:
+ v4l2_ctrl_query_fill(ctrl, 0, 100, 1, 50);
+ break;
+ case V4L2_CID_HUE:
+ v4l2_ctrl_query_fill(ctrl, -50, 50, 1, 0);
+ break;
+ default:
+ ctrl->name[0] = '\0';
+ return -EINVAL;
+ }
+ break;
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ int value1;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ printk(KERN_INFO "s2250: future setting\n");
+ return -EINVAL;
+ case V4L2_CID_CONTRAST:
+ printk(KERN_INFO "s2250: future setting\n");
+ return -EINVAL;
+ break;
+ case V4L2_CID_SATURATION:
+ if (ctrl->value > 127)
+ dec->saturation = 127;
+ else if (ctrl->value < 0)
+ dec->saturation = 0;
+ else
+ dec->saturation = ctrl->value;
+
+ value1 = dec->saturation * 4140 / 100;
+ if (value1 > 4094)
+ value1 = 4094;
+ write_reg_fp(client, VPX322_ADDR_SAT, value1);
+ break;
+ case V4L2_CID_HUE:
+ if (ctrl->value > 50)
+ dec->hue = 50;
+ else if (ctrl->value < -50)
+ dec->hue = -50;
+ else
+ dec->hue = ctrl->value;
+ /* clamp the hue range */
+ value1 = dec->hue * 280 / 50;
+ write_reg_fp(client, VPX322_ADDR_HUE, value1);
+ break;
+ }
+ break;
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ ctrl->value = dec->brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ ctrl->value = dec->contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ ctrl->value = dec->saturation;
+ break;
+ case V4L2_CID_HUE:
+ ctrl->value = dec->hue;
+ break;
+ }
+ break;
+ }
+ case VIDIOC_S_FMT:
+ {
+ struct v4l2_format *fmt = arg;
+ if (fmt->fmt.pix.height < 640) {
+ write_reg_fp(client, 0x12b, dec->reg12b_val | 0x400);
+ write_reg_fp(client, 0x140, 0x060);
+ } else {
+ write_reg_fp(client, 0x12b, dec->reg12b_val & ~0x400);
+ write_reg_fp(client, 0x140, 0x060);
+ }
+ return 0;
+ }
+ case VIDIOC_G_AUDIO:
+ {
+ struct v4l2_audio *audio = arg;
+
+ memset(audio, 0, sizeof(*audio));
+ audio->index = dec->audio_input;
+ /* fall through */
+ }
+ case VIDIOC_ENUMAUDIO:
+ {
+ struct v4l2_audio *audio = arg;
+
+ switch (audio->index) {
+ case 0:
+ strcpy(audio->name, "Line In");
+ break;
+ case 1:
+ strcpy(audio->name, "Mic");
+ break;
+ case 2:
+ strcpy(audio->name, "Mic Boost");
+ break;
+ default:
+ audio->name[0] = '\0';
+ return 0;
+ }
+ audio->capability = V4L2_AUDCAP_STEREO;
+ audio->mode = 0;
+ return 0;
+ }
+ case VIDIOC_S_AUDIO:
+ {
+ struct v4l2_audio *audio = arg;
+
+ client->addr = TLV320_ADDRESS;
+ switch (audio->index) {
+ case 0:
+ write_reg(client, 0x08, 0x02); /* Line In */
+ break;
+ case 1:
+ write_reg(client, 0x08, 0x04); /* Mic */
+ break;
+ case 2:
+ write_reg(client, 0x08, 0x05); /* Mic Boost */
+ break;
+ default:
+ return -EINVAL;
+ }
+ dec->audio_input = audio->index;
+ return 0;
+ }
+
+ default:
+ printk(KERN_INFO "s2250: unknown command 0x%x\n", cmd);
+ break;
+ }
+ return 0;
+}
+
+static struct i2c_driver s2250_driver;
+
+static struct i2c_client s2250_client_templ = {
+ .name = "Sensoray 2250",
+ .driver = &s2250_driver,
+};
+
+static int s2250_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *client;
+ struct s2250 *dec;
+ u8 *data;
+ struct go7007 *go = i2c_get_adapdata(adapter);
+ struct go7007_usb *usb = go->hpi_context;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ memcpy(client, &s2250_client_templ,
+ sizeof(s2250_client_templ));
+ client->adapter = adapter;
+
+ dec = kmalloc(sizeof(struct s2250), GFP_KERNEL);
+ if (dec == NULL) {
+ kfree(client);
+ return -ENOMEM;
+ }
+
+ dec->std = V4L2_STD_NTSC;
+ dec->brightness = 50;
+ dec->contrast = 50;
+ dec->saturation = 50;
+ dec->hue = 0;
+ client->addr = TLV320_ADDRESS;
+ i2c_set_clientdata(client, dec);
+
+ printk(KERN_DEBUG
+ "s2250: initializing video decoder on %s\n",
+ adapter->name);
+
+ /* initialize the audio */
+ client->addr = TLV320_ADDRESS;
+ if (write_regs(client, aud_regs) < 0) {
+ printk(KERN_ERR
+ "s2250: error initializing audio\n");
+ kfree(client);
+ kfree(dec);
+ return 0;
+ }
+ client->addr = S2250_VIDDEC;
+ i2c_set_clientdata(client, dec);
+
+ if (write_regs(client, vid_regs) < 0) {
+ printk(KERN_ERR
+ "s2250: error initializing decoder\n");
+ kfree(client);
+ kfree(dec);
+ return 0;
+ }
+ if (write_regs_fp(client, vid_regs_fp) < 0) {
+ printk(KERN_ERR
+ "s2250: error initializing decoder\n");
+ kfree(client);
+ kfree(dec);
+ return 0;
+ }
+ /* set default channel */
+ /* composite */
+ write_reg_fp(client, 0x20, 0x020 | 1);
+ write_reg_fp(client, 0x21, 0x662);
+ write_reg_fp(client, 0x140, 0x060);
+
+ /* set default audio input */
+ dec->audio_input = 0;
+ write_reg(client, 0x08, 0x02); /* Line In */
+
+ if (down_interruptible(&usb->i2c_lock) == 0) {
+ data = kzalloc(16, GFP_KERNEL);
+ if (data != NULL) {
+ int rc;
+ rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
+ data, 16, 1);
+ if (rc > 0) {
+ u8 mask;
+ data[0] = 0;
+ mask = 1<<5;
+ data[0] &= ~mask;
+ data[1] |= mask;
+ go7007_usb_vendor_request(go, 0x40, 0,
+ (data[1]<<8)
+ + data[1],
+ data, 16, 0);
+ }
+ kfree(data);
+ }
+ up(&usb->i2c_lock);
+ }
+
+ i2c_attach_client(client);
+ printk("s2250: initialized successfully\n");
+ return 0;
+}
+
+static int s2250_detach(struct i2c_client *client)
+{
+ struct s2250 *dec = i2c_get_clientdata(client);
+ int r;
+
+ r = i2c_detach_client(client);
+ if (r < 0)
+ return r;
+
+ kfree(client);
+ kfree(dec);
+ return 0;
+}
+
+static struct i2c_driver s2250_driver = {
+ .driver = {
+ .name = "Sensoray 2250 board driver",
+ },
+ .id = I2C_DRIVERID_S2250,
+ .detach_client = s2250_detach,
+ .command = s2250_command,
+};
+
+static int __init s2250_init(void)
+{
+ int r;
+
+ r = s2250loader_init();
+ if (r < 0)
+ return r;
+
+ r = i2c_add_driver(&s2250_driver);
+ if (r < 0)
+ return r;
+ return wis_i2c_add_driver(s2250_driver.id, s2250_detect);
+}
+
+static void __exit s2250_cleanup(void)
+{
+ wis_i2c_del_driver(s2250_detect);
+ i2c_del_driver(&s2250_driver);
+
+ s2250loader_cleanup();
+}
+
+module_init(s2250_init);
+module_exit(s2250_cleanup);
+
+MODULE_AUTHOR("");
+MODULE_DESCRIPTION("Board driver for Sensoryray 2250");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c
new file mode 100644
index 000000000000..a5e4acab089e
--- /dev/null
+++ b/drivers/staging/go7007/s2250-loader.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 Sensoray Company Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <dvb-usb.h>
+
+#define S2250_LOADER_FIRMWARE "s2250_loader.fw"
+#define S2250_FIRMWARE "s2250.fw"
+
+typedef struct device_extension_s {
+ struct kref kref;
+ int minor;
+ struct usb_device *usbdev;
+} device_extension_t, *pdevice_extension_t;
+
+#define USB_s2250loader_MAJOR 240
+#define USB_s2250loader_MINOR_BASE 0
+#define MAX_DEVICES 256
+
+static pdevice_extension_t s2250_dev_table[MAX_DEVICES];
+static DECLARE_MUTEX(s2250_dev_table_mutex);
+
+#define to_s2250loader_dev_common(d) container_of(d, device_extension_t, kref)
+static void s2250loader_delete(struct kref *kref)
+{
+ pdevice_extension_t s = to_s2250loader_dev_common(kref);
+ s2250_dev_table[s->minor] = NULL;
+ kfree(s);
+}
+
+static int s2250loader_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *usbdev;
+ int minor, ret;
+ pdevice_extension_t s = NULL;
+ const struct firmware *fw;
+
+ usbdev = usb_get_dev(interface_to_usbdev(interface));
+ if (!usbdev) {
+ printk(KERN_ERR "Enter s2250loader_probe failed\n");
+ return -1;
+ }
+ printk(KERN_INFO "Enter s2250loader_probe 2.6 kernel\n");
+ printk(KERN_INFO "vendor id 0x%x, device id 0x%x devnum:%d\n",
+ usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
+ usbdev->devnum);
+
+ if (usbdev->descriptor.bNumConfigurations != 1) {
+ printk(KERN_ERR "can't handle multiple config\n");
+ return -1;
+ }
+ down(&s2250_dev_table_mutex);
+
+ for (minor = 0; minor < MAX_DEVICES; minor++) {
+ if (s2250_dev_table[minor] == NULL)
+ break;
+ }
+
+ if (minor < 0 || minor >= MAX_DEVICES) {
+ printk(KERN_ERR "Invalid minor: %d\n", minor);
+ goto failed;
+ }
+
+ /* Allocate dev data structure */
+ s = kmalloc(sizeof(device_extension_t), GFP_KERNEL);
+ if (s == NULL) {
+ printk(KERN_ERR "Out of memory\n");
+ goto failed;
+ }
+ s2250_dev_table[minor] = s;
+
+ printk(KERN_INFO "s2250loader_probe: Device %d on Bus %d Minor %d\n",
+ usbdev->devnum, usbdev->bus->busnum, minor);
+
+ memset(s, 0, sizeof(device_extension_t));
+ s->usbdev = usbdev;
+ printk(KERN_INFO "loading 2250 loader\n");
+
+ kref_init(&(s->kref));
+
+ up(&s2250_dev_table_mutex);
+
+ if (request_firmware(&fw, S2250_LOADER_FIRMWARE, &usbdev->dev)) {
+ printk(KERN_ERR
+ "s2250: unable to load firmware from file \"%s\"\n",
+ S2250_LOADER_FIRMWARE);
+ goto failed2;
+ }
+ ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+ release_firmware(fw);
+ if (0 != ret) {
+ printk(KERN_ERR "loader download failed\n");
+ goto failed2;
+ }
+
+ if (request_firmware(&fw, S2250_FIRMWARE, &usbdev->dev)) {
+ printk(KERN_ERR
+ "s2250: unable to load firmware from file \"%s\"\n",
+ S2250_FIRMWARE);
+ goto failed2;
+ }
+ ret = usb_cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+ release_firmware(fw);
+ if (0 != ret) {
+ printk(KERN_ERR "firmware_s2250 download failed\n");
+ goto failed2;
+ }
+
+ usb_set_intfdata(interface, s);
+ return 0;
+
+failed:
+ up(&s2250_dev_table_mutex);
+failed2:
+ if (s)
+ kref_put(&(s->kref), s2250loader_delete);
+
+ printk(KERN_ERR "probe failed\n");
+ return -1;
+}
+
+static void s2250loader_disconnect(struct usb_interface *interface)
+{
+ pdevice_extension_t s = usb_get_intfdata(interface);
+ printk(KERN_INFO "s2250: disconnect\n");
+ lock_kernel();
+ s = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+ kref_put(&(s->kref), s2250loader_delete);
+ unlock_kernel();
+}
+
+static struct usb_device_id s2250loader_ids[] = {
+ {USB_DEVICE(0x1943, 0xa250)},
+ {} /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, s2250loader_ids);
+
+static struct usb_driver s2250loader_driver = {
+ .name = "s2250-loader",
+ .probe = s2250loader_probe,
+ .disconnect = s2250loader_disconnect,
+ .id_table = s2250loader_ids,
+};
+
+int s2250loader_init(void)
+{
+ int r;
+ unsigned i = 0;
+
+ for (i = 0; i < MAX_DEVICES; i++)
+ s2250_dev_table[i] = NULL;
+
+ r = usb_register(&s2250loader_driver);
+ if (r) {
+ printk(KERN_ERR "usb_register failed. Error number %d\n", r);
+ return -1;
+ }
+
+ printk(KERN_INFO "s2250loader_init: driver registered\n");
+ return 0;
+}
+EXPORT_SYMBOL(s2250loader_init);
+
+void s2250loader_cleanup(void)
+{
+ printk(KERN_INFO "s2250loader_cleanup\n");
+ usb_deregister(&s2250loader_driver);
+}
+EXPORT_SYMBOL(s2250loader_cleanup);
diff --git a/drivers/staging/go7007/saa7134-go7007.c b/drivers/staging/go7007/saa7134-go7007.c
index c4a6d8ef9078..665bbf59d026 100644
--- a/drivers/staging/go7007/saa7134-go7007.c
+++ b/drivers/staging/go7007/saa7134-go7007.c
@@ -27,7 +27,7 @@
#include <linux/usb.h>
#include <linux/i2c.h>
#include <asm/byteorder.h>
-#include <media/audiochip.h>
+#include <media/v4l2-common.h>
#include "saa7134-reg.h"
#include "saa7134.h"
@@ -314,7 +314,13 @@ static int saa7134_go7007_stream_start(struct go7007 *go)
static int saa7134_go7007_stream_stop(struct go7007 *go)
{
struct saa7134_go7007 *saa = go->hpi_context;
- struct saa7134_dev *dev = saa->dev;
+ struct saa7134_dev *dev;
+
+ if (!saa)
+ return -EINVAL;
+ dev = saa->dev;
+ if (!dev)
+ return -EINVAL;
/* Shut down TS FIFO */
saa_clearl(SAA7134_MAIN_CTRL, SAA7134_MAIN_CTRL_TE5);
@@ -373,6 +379,47 @@ static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
return 0;
}
+static int saa7134_go7007_send_command(struct go7007 *go, unsigned int cmd,
+ void *arg)
+{
+ struct saa7134_go7007 *saa = go->hpi_context;
+ struct saa7134_dev *dev = saa->dev;
+
+ switch (cmd) {
+ case VIDIOC_S_STD:
+ {
+ v4l2_std_id *std = arg;
+ return saa7134_s_std_internal(dev, NULL, std);
+ }
+ case VIDIOC_G_STD:
+ {
+ v4l2_std_id *std = arg;
+ *std = dev->tvnorm->id;
+ return 0;
+ }
+ case VIDIOC_QUERYCTRL:
+ {
+ struct v4l2_queryctrl *ctrl = arg;
+ if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
+ return saa7134_queryctrl(NULL, NULL, ctrl);
+ }
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
+ return saa7134_g_ctrl_internal(dev, NULL, ctrl);
+ }
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_USER)
+ return saa7134_s_ctrl_internal(dev, NULL, ctrl);
+ }
+ }
+ return -EINVAL;
+
+}
+
static struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
.interface_reset = saa7134_go7007_interface_reset,
.write_interrupt = saa7134_go7007_write_interrupt,
@@ -380,6 +427,7 @@ static struct go7007_hpi_ops saa7134_go7007_hpi_ops = {
.stream_start = saa7134_go7007_stream_start,
.stream_stop = saa7134_go7007_stream_stop,
.send_firmware = saa7134_go7007_send_firmware,
+ .send_command = saa7134_go7007_send_command,
};
/********************* Add/remove functions *********************/
diff --git a/drivers/staging/go7007/wis-i2c.h b/drivers/staging/go7007/wis-i2c.h
index 993f658ad731..431f41dd3966 100644
--- a/drivers/staging/go7007/wis-i2c.h
+++ b/drivers/staging/go7007/wis-i2c.h
@@ -23,6 +23,7 @@
#define I2C_DRIVERID_WIS_SAA7113 0xf0f4
#define I2C_DRIVERID_WIS_OV7640 0xf0f5
#define I2C_DRIVERID_WIS_TW2804 0xf0f6
+#define I2C_DRIVERID_S2250 0xf0f7
#define I2C_ALGO_GO7007 0xf00000
#define I2C_ALGO_GO7007_USB 0xf10000
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
index 5a91ee409a7c..58fddb122372 100644
--- a/drivers/staging/go7007/wis-sony-tuner.c
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -604,7 +604,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner *tun = arg;
- memset(t, 0, sizeof(*tun));
+ memset(tun, 0, sizeof(*tun));
strcpy(tun->name, "Television");
tun->type = V4L2_TUNER_ANALOG_TV;
tun->rangelow = 0UL; /* does anything use these? */
diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c
index 0394e2709278..e1c4a8078901 100644
--- a/drivers/staging/me4000/me4000.c
+++ b/drivers/staging/me4000/me4000.c
@@ -536,25 +536,19 @@ module_init(me4000_init_module);
static void clear_board_info_list(void)
{
- struct list_head *board_p;
- struct list_head *dac_p;
- struct me4000_info *board_info;
- struct me4000_ao_context *ao_context;
+ struct me4000_info *board_info, *board_info_safe;
+ struct me4000_ao_context *ao_context, *ao_context_safe;
/* Clear context lists */
- for (board_p = me4000_board_info_list.next;
- board_p != &me4000_board_info_list; board_p = board_p->next) {
- board_info = list_entry(board_p, struct me4000_info, list);
+ list_for_each_entry(board_info, &me4000_board_info_list, list) {
/* Clear analog output context list */
- while (!list_empty(&board_info->ao_context_list)) {
- dac_p = board_info->ao_context_list.next;
- ao_context =
- list_entry(dac_p, struct me4000_ao_context, list);
+ list_for_each_entry_safe(ao_context, ao_context_safe,
+ &board_info->ao_context_list, list) {
me4000_ao_reset(ao_context);
free_irq(ao_context->irq, ao_context);
if (ao_context->circ_buf.buf)
kfree(ao_context->circ_buf.buf);
- list_del(dac_p);
+ list_del(&ao_context->list);
kfree(ao_context);
}
@@ -574,11 +568,10 @@ static void clear_board_info_list(void)
}
/* Clear the board info list */
- while (!list_empty(&me4000_board_info_list)) {
- board_p = me4000_board_info_list.next;
- board_info = list_entry(board_p, struct me4000_info, list);
+ list_for_each_entry_safe(board_info, board_info_safe,
+ &me4000_board_info_list, list) {
pci_release_regions(board_info->pci_dev_p);
- list_del(board_p);
+ list_del(&board_info->list);
kfree(board_info);
}
}
@@ -663,16 +656,17 @@ static int init_board_info(struct pci_dev *pci_dev_p,
}
/* Get the index of the board in the global list */
- for (board_p = me4000_board_info_list.next, i = 0;
- board_p != &me4000_board_info_list; board_p = board_p->next, i++) {
+ i = 0;
+ list_for_each(board_p, &me4000_board_info_list) {
if (board_p == &board_info->list) {
board_info->board_count = i;
break;
}
+ i++;
}
if (board_p == &me4000_board_info_list) {
printk(KERN_ERR
- "ME4000:init_board_info():Cannot get index of baord\n");
+ "ME4000:init_board_info():Cannot get index of board\n");
return -ENODEV;
}
@@ -863,16 +857,14 @@ static int alloc_ao_contexts(struct me4000_info *info)
static void release_ao_contexts(struct me4000_info *board_info)
{
- struct list_head *dac_p;
- struct me4000_ao_context *ao_context;
+ struct me4000_ao_context *ao_context, *ao_context_safe;
/* Clear analog output context list */
- while (!list_empty(&board_info->ao_context_list)) {
- dac_p = board_info->ao_context_list.next;
- ao_context = list_entry(dac_p, struct me4000_ao_context, list);
+ list_for_each_entry_safe(ao_context, ao_context_safe,
+ &board_info->ao_context_list, list) {
free_irq(ao_context->irq, ao_context);
kfree(ao_context->circ_buf.buf);
- list_del(dac_p);
+ list_del(&ao_context->list);
kfree(ao_context);
}
}
@@ -1180,7 +1172,7 @@ static int me4000_xilinx_download(struct me4000_info *info)
/* Wait until /INIT pin is set */
udelay(20);
- if (!inl(info->plx_regbase + PLX_INTCSR) & 0x20) {
+ if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
printk(KERN_ERR "%s:Can't init Xilinx\n", __func__);
return -EIO;
}
@@ -1303,12 +1295,13 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
dev, mode);
/* Search for the board context */
- for (ptr = me4000_board_info_list.next, i = 0;
- ptr != &me4000_board_info_list; ptr = ptr->next, i++) {
- board_info = list_entry(ptr, struct me4000_info, list);
+ i = 0;
+ list_for_each(ptr, &me4000_board_info_list) {
if (i == board)
break;
+ i++;
}
+ board_info = list_entry(ptr, struct me4000_info, list);
if (ptr == &me4000_board_info_list) {
printk(KERN_ERR
@@ -1318,14 +1311,13 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
}
/* Search for the dac context */
- for (ptr = board_info->ao_context_list.next, i = 0;
- ptr != &board_info->ao_context_list;
- ptr = ptr->next, i++) {
- ao_context = list_entry(ptr, struct me4000_ao_context,
- list);
+ i = 0;
+ list_for_each(ptr, &board_info->ao_context_list) {
if (i == dev)
break;
+ i++;
}
+ ao_context = list_entry(ptr, struct me4000_ao_context, list);
if (ptr == &board_info->ao_context_list) {
printk(KERN_ERR
@@ -1384,12 +1376,13 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
PDEBUG("me4000_open():ai board = %d mode = %d\n", board, mode);
/* Search for the board context */
- for (ptr = me4000_board_info_list.next, i = 0;
- ptr != &me4000_board_info_list; ptr = ptr->next, i++) {
- board_info = list_entry(ptr, struct me4000_info, list);
+ i = 0;
+ list_for_each(ptr, &me4000_board_info_list) {
if (i == board)
break;
+ i++;
}
+ board_info = list_entry(ptr, struct me4000_info, list);
if (ptr == &me4000_board_info_list) {
printk(KERN_ERR
@@ -1438,14 +1431,12 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
PDEBUG("me4000_open():board = %d\n", board);
/* Search for the board context */
- for (ptr = me4000_board_info_list.next;
- ptr != &me4000_board_info_list; ptr = ptr->next) {
- board_info = list_entry(ptr, struct me4000_info, list);
+ list_for_each_entry(board_info, &me4000_board_info_list, list) {
if (board_info->board_count == board)
break;
}
- if (ptr == &me4000_board_info_list) {
+ if (&board_info->list == &me4000_board_info_list) {
printk(KERN_ERR
"ME4000:me4000_open():Board %d not in device list\n",
board);
@@ -1483,14 +1474,12 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
PDEBUG("me4000_open():board = %d\n", board);
/* Search for the board context */
- for (ptr = me4000_board_info_list.next;
- ptr != &me4000_board_info_list; ptr = ptr->next) {
- board_info = list_entry(ptr, struct me4000_info, list);
+ list_for_each_entry(board_info, &me4000_board_info_list, list) {
if (board_info->board_count == board)
break;
}
- if (ptr == &me4000_board_info_list) {
+ if (&board_info->list == &me4000_board_info_list) {
printk(KERN_ERR
"ME4000:me4000_open():Board %d not in device list\n",
board);
@@ -1526,14 +1515,12 @@ static int me4000_open(struct inode *inode_p, struct file *file_p)
PDEBUG("me4000_open():board = %d\n", board);
/* Search for the board context */
- for (ptr = me4000_board_info_list.next;
- ptr != &me4000_board_info_list; ptr = ptr->next) {
- board_info = list_entry(ptr, struct me4000_info, list);
+ list_for_each_entry(board_info, &me4000_board_info_list, list) {
if (board_info->board_count == board)
break;
}
- if (ptr == &me4000_board_info_list) {
+ if (&board_info->list == &me4000_board_info_list) {
printk(KERN_ERR
"ME4000:me4000_open():Board %d not in device list\n",
board);
@@ -5955,7 +5942,6 @@ static irqreturn_t me4000_ext_int_isr(int irq, void *dev_id)
static void __exit me4000_module_exit(void)
{
- struct list_head *board_p;
struct me4000_info *board_info;
CALL_PDEBUG("cleanup_module() is executed\n");
@@ -5975,9 +5961,7 @@ static void __exit me4000_module_exit(void)
pci_unregister_driver(&me4000_driver);
/* Reset the boards */
- for (board_p = me4000_board_info_list.next;
- board_p != &me4000_board_info_list; board_p = board_p->next) {
- board_info = list_entry(board_p, struct me4000_info, list);
+ list_for_each_entry(board_info, &me4000_board_info_list, list) {
me4000_reset_board(board_info);
}
@@ -5992,7 +5976,6 @@ static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
int len = 0;
int limit = count - 1000;
struct me4000_info *board_info;
- struct list_head *ptr;
len += sprintf(buf + len, "\nME4000 DRIVER VERSION %X.%X.%X\n\n",
(ME4000_DRIVER_VERSION & 0xFF0000) >> 16,
@@ -6000,11 +5983,7 @@ static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
(ME4000_DRIVER_VERSION & 0xFF));
/* Search for the board context */
- for (ptr = me4000_board_info_list.next;
- (ptr != &me4000_board_info_list) && (len < limit);
- ptr = ptr->next) {
- board_info = list_entry(ptr, struct me4000_info, list);
-
+ list_for_each_entry(board_info, &me4000_board_info_list, list) {
len +=
sprintf(buf + len, "Board number %d:\n",
board_info->board_count);
@@ -6110,6 +6089,8 @@ static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
sprintf(buf + len, "AO 3 status register = 0x%08X\n",
inl(board_info->me4000_regbase +
ME4000_AO_03_STATUS_REG));
+ if (len >= limit)
+ break;
}
*eof = 1;
diff --git a/drivers/staging/meilhaus/Kconfig b/drivers/staging/meilhaus/Kconfig
new file mode 100644
index 000000000000..923af22a4686
--- /dev/null
+++ b/drivers/staging/meilhaus/Kconfig
@@ -0,0 +1,128 @@
+#
+# Meilhaus configuration
+#
+
+menuconfig MEILHAUS
+ tristate "Meilhaus support"
+ depends on m
+ ---help---
+ If you have a Meilhaus card, say Y (or M) here.
+
+ You need both this driver, and the driver for the particular
+ data collection card.
+
+ To compile this driver as a module, choose M here. The module will
+ be called memain.
+
+if MEILHAUS
+
+config ME0600
+ tristate "Meilhaus ME-600 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-600 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me0600.
+
+config ME0900
+ tristate "Meilhaus ME-900 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-900 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me0900.
+
+config ME1000
+ tristate "Meilhaus ME-1000 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-1000 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me1000.
+
+config ME1400
+ tristate "Meilhaus ME-1400 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-1400 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me1400.
+
+config ME1600
+ tristate "Meilhaus ME-1600 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-1600 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me1600.
+
+config ME4600
+ tristate "Meilhaus ME-4600 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-4600 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me4600.
+
+config ME6000
+ tristate "Meilhaus ME-6000 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-6000 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me6000.
+
+config ME8100
+ tristate "Meilhaus ME-8100 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-8100 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me8100.
+
+config ME8200
+ tristate "Meilhaus ME-8200 support"
+ default n
+ depends on PCI && m
+ help
+ This driver supports the Meilhaus ME-8200 family of boards
+ that do data collection and multipurpose I/O.
+
+ To compile this driver as a module, choose M here: the module
+ will be called me8200.
+
+config MEDUMMY
+ tristate "Meilhaus dummy driver"
+ default n
+ depends on PCI && m
+ help
+ This provides a dummy driver for the Meilhaus driver package
+
+ To compile this driver as a module, choose M here: the module
+ will be called medummy.
+
+endif # MEILHAUS
diff --git a/drivers/staging/meilhaus/Makefile b/drivers/staging/meilhaus/Makefile
new file mode 100644
index 000000000000..5ab2c1c9c861
--- /dev/null
+++ b/drivers/staging/meilhaus/Makefile
@@ -0,0 +1,43 @@
+#
+# Makefile for Meilhaus linux driver system
+#
+
+obj-$(CONFIG_MEILHAUS) += memain.o
+obj-$(CONFIG_ME1600) += me1600.o
+obj-$(CONFIG_ME1000) += me1000.o
+obj-$(CONFIG_ME1400) += me1400.o
+obj-$(CONFIG_ME4600) += me4600.o
+obj-$(CONFIG_ME6000) += me6000.o
+obj-$(CONFIG_ME0600) += me0600.o
+obj-$(CONFIG_ME8100) += me8100.o
+obj-$(CONFIG_ME8200) += me8200.o
+obj-$(CONFIG_ME0900) += me0900.o
+obj-$(CONFIG_MEDUMMY) += medummy.o
+
+
+me1600-objs := medevice.o medlist.o medlock.o me1600_device.o
+me1600-objs += mesubdevice.o meslist.o meslock.o me1600_ao.o
+
+me1000-objs := medevice.o medlist.o medlock.o me1000_device.o
+me1000-objs += mesubdevice.o meslist.o meslock.o me1000_dio.o
+
+me1400-objs := medevice.o medlist.o medlock.o me1400_device.o
+me1400-objs += mesubdevice.o meslist.o meslock.o me8254.o me8255.o me1400_ext_irq.o
+
+me4600-objs := medevice.o medlist.o medlock.o mefirmware.o me4600_device.o
+me4600-objs += mesubdevice.o meslist.o meslock.o me4600_do.o me4600_di.o me4600_dio.o me8254.o me4600_ai.o me4600_ao.o me4600_ext_irq.o
+
+me6000-objs := medevice.o medlist.o medlock.o mefirmware.o me6000_device.o
+me6000-objs += mesubdevice.o meslist.o meslock.o me6000_dio.o me6000_ao.o
+
+me0600-objs := medevice.o medlist.o medlock.o me0600_device.o
+me0600-objs += mesubdevice.o meslist.o meslock.o me0600_relay.o me0600_ttli.o me0600_optoi.o me0600_dio.o me0600_ext_irq.o
+
+me8100-objs := medevice.o medlist.o medlock.o me8100_device.o
+me8100-objs += mesubdevice.o meslist.o meslock.o me8100_di.o me8100_do.o me8254.o
+
+me8200-objs := medevice.o medlist.o medlock.o me8200_device.o
+me8200-objs += mesubdevice.o meslist.o meslock.o me8200_di.o me8200_do.o me8200_dio.o
+
+me0900-objs := medevice.o medlist.o medlock.o me0900_device.o
+me0900-objs += mesubdevice.o meslist.o meslock.o me0900_do.o me0900_di.o
diff --git a/drivers/staging/meilhaus/TODO b/drivers/staging/meilhaus/TODO
new file mode 100644
index 000000000000..6ec25203089c
--- /dev/null
+++ b/drivers/staging/meilhaus/TODO
@@ -0,0 +1,10 @@
+TODO:
+ - checkpatch.pl cleanups
+ - sparse issues
+ - Lindent
+ - audit userspace interface
+ - handle firmware properly
+ - possible comedi merge
+
+Please send cleanup patches to Greg Kroah-Hartman <greg@kroah.com>
+and CC: David Kiliani <mail@davidkiliani.de>
diff --git a/drivers/staging/meilhaus/me0600_device.c b/drivers/staging/meilhaus/me0600_device.c
new file mode 100644
index 000000000000..8950e47e0e86
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_device.c
@@ -0,0 +1,215 @@
+/**
+ * @file me0600_device.c
+ *
+ * @brief ME-630 device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "medevice.h"
+#include "me0600_device.h"
+#include "mesubdevice.h"
+#include "me0600_relay.h"
+#include "me0600_ttli.h"
+#include "me0600_optoi.h"
+#include "me0600_dio.h"
+#include "me0600_ext_irq.h"
+
+me_device_t *me0600_pci_constructor(struct pci_dev *pci_device)
+{
+ me0600_device_t *me0600_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ int err;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me0600_device = kmalloc(sizeof(me0600_device_t), GFP_KERNEL);
+
+ if (!me0600_device) {
+ PERROR("Cannot get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(me0600_device, 0, sizeof(me0600_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me0600_device, pci_device);
+
+ if (err) {
+ kfree(me0600_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+
+ /* Get the index in the device version information table. */
+ version_idx =
+ me0600_versions_get_device_index(me0600_device->base.info.pci.
+ device_id);
+
+ // Initialize spin lock .
+ spin_lock_init(&me0600_device->dio_ctrl_reg_lock);
+ spin_lock_init(&me0600_device->intcsr_lock);
+
+ // Create subdevice instances.
+
+ for (i = 0; i < me0600_versions[version_idx].optoi_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me0600_optoi_constructor(me0600_device->
+ base.info.pci.
+ reg_bases[2]);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me0600_device);
+ kfree(me0600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me0600_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me0600_versions[version_idx].relay_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me0600_relay_constructor(me0600_device->
+ base.info.pci.
+ reg_bases[2]);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me0600_device);
+ kfree(me0600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me0600_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me0600_versions[version_idx].ttli_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me0600_ttli_constructor(me0600_device->
+ base.info.pci.
+ reg_bases[2]);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me0600_device);
+ kfree(me0600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me0600_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me0600_versions[version_idx].dio_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me0600_dio_constructor(me0600_device->
+ base.info.pci.
+ reg_bases[2], i,
+ &me0600_device->
+ dio_ctrl_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me0600_device);
+ kfree(me0600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me0600_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me0600_versions[version_idx].ext_irq_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *)
+ me0600_ext_irq_constructor(me0600_device->base.info.pci.
+ reg_bases[1],
+ me0600_device->base.info.pci.
+ reg_bases[2],
+ &me0600_device->intcsr_lock, i,
+ me0600_device->base.irq);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me0600_device);
+ kfree(me0600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me0600_device->base.slist,
+ subdevice);
+ }
+
+ return (me_device_t *) me0600_device;
+}
+
+// Init and exit of module.
+
+static int __init me0600_init(void)
+{
+ PDEBUG("executed.\n");
+ return 0;
+}
+
+static void __exit me0600_exit(void)
+{
+ PDEBUG("executed.\n");
+}
+
+module_init(me0600_init);
+
+module_exit(me0600_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for ME-6xx Device");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-6xx Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me0600_pci_constructor);
diff --git a/drivers/staging/meilhaus/me0600_device.h b/drivers/staging/meilhaus/me0600_device.h
new file mode 100644
index 000000000000..d93a8aee581b
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_device.h
@@ -0,0 +1,97 @@
+/**
+ * @file me0600_device.h
+ *
+ * @brief ME-630 device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_DEVICE_H
+#define _ME0600_DEVICE_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure holding ME-630 device capabilities.
+ */
+typedef struct me0600_version {
+ uint16_t device_id;
+ unsigned int relay_subdevices;
+ unsigned int ttli_subdevices;
+ unsigned int optoi_subdevices;
+ unsigned int dio_subdevices;
+ unsigned int ext_irq_subdevices;
+} me0600_version_t;
+
+/**
+ * @brief Device capabilities.
+ */
+static me0600_version_t me0600_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME0630, 1, 1, 1, 2, 2},
+ {0},
+};
+
+#define ME0600_DEVICE_VERSIONS (sizeof(me0600_versions) / sizeof(me0600_version_t) - 1) /**< Returns the number of entries in #me0600_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #me0600_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me0600_versions.
+ */
+static inline unsigned int me0600_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME0600_DEVICE_VERSIONS; i++)
+ if (me0600_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The ME-630 device class structure.
+ */
+typedef struct me0600_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+
+ /* Child class attributes. */
+ spinlock_t dio_ctrl_reg_lock;
+ spinlock_t intcsr_lock;
+} me0600_device_t;
+
+/**
+ * @brief The ME-630 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-630 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me0600_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_dio.c b/drivers/staging/meilhaus/me0600_dio.c
new file mode 100644
index 000000000000..3a2775749a2c
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_dio.c
@@ -0,0 +1,415 @@
+/**
+ * @file me0600_dio.c
+ *
+ * @brief ME-630 digital input/output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me0600_dio_reg.h"
+#include "me0600_dio.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me0600_dio_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me0600_dio_subdevice_t *instance;
+ uint8_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_dio_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inb(instance->ctrl_reg);
+ mode &= ~(0x3 << (instance->dio_idx * 2));
+ outb(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outb(0x00, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0x00);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_dio_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me0600_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+ int size =
+ flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
+ | ME_IO_SINGLE_CONFIG_DIO_WORD |
+ ME_IO_SINGLE_CONFIG_DIO_DWORD);
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inb(instance->ctrl_reg);
+ switch (size) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ mode &=
+ ~((ME0600_DIO_CONFIG_BIT_OUT_0) <<
+ (instance->dio_idx * 2));
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ mode &=
+ ~((ME0600_DIO_CONFIG_BIT_OUT_0) <<
+ (instance->dio_idx * 2));
+ mode |=
+ ME0600_DIO_CONFIG_BIT_OUT_0 << (instance->
+ dio_idx *
+ 2);
+ } else {
+ PERROR
+ ("Invalid port configuration specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!err) {
+ outb(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_dio_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me0600_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
+ (instance->dio_idx * 2));
+
+ if ((mode ==
+ (ME0600_DIO_CONFIG_BIT_OUT_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value =
+ inb(instance->
+ port_reg) & (0x0001 << channel);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
+ (instance->dio_idx * 2));
+
+ if ((mode ==
+ (ME0600_DIO_CONFIG_BIT_OUT_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value = inb(instance->port_reg) & 0x00FF;
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+
+ break;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_dio_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me0600_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+ uint8_t byte;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME0600_DIO_CONFIG_BIT_OUT_0 <<
+ (instance->dio_idx * 2))) {
+ byte = inb(instance->port_reg);
+
+ if (value)
+ byte |= 0x1 << channel;
+ else
+ byte &= ~(0x1 << channel);
+
+ outb(byte, instance->port_reg);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME0600_DIO_CONFIG_BIT_OUT_0 <<
+ (instance->dio_idx * 2))) {
+ outb(value, instance->port_reg);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+
+ break;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_dio_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_dio_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DIO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_dio_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_DIR_BYTE;
+ return ME_ERRNO_SUCCESS;
+}
+
+me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock)
+{
+ me0600_dio_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me0600_dio_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me0600_dio_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save digital i/o index */
+ subdevice->dio_idx = dio_idx;
+
+ /* Save the subdevice index */
+ subdevice->ctrl_reg = reg_base + ME0600_DIO_CONFIG_REG;
+ subdevice->port_reg = reg_base + ME0600_DIO_PORT_REG + dio_idx;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me0600_dio_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me0600_dio_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me0600_dio_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me0600_dio_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me0600_dio_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me0600_dio_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me0600_dio_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me0600_dio.h b/drivers/staging/meilhaus/me0600_dio.h
new file mode 100644
index 000000000000..5d075c7d6882
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_dio.h
@@ -0,0 +1,68 @@
+/**
+ * @file me0600_dio.h
+ *
+ * @brief ME-630 digital input/output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_DIO_H_
+#define _ME0600_DIO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me0600_dio_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+ unsigned int dio_idx; /**< The index of the digital i/o on the device. */
+
+ unsigned long port_reg; /**< Register holding the port status. */
+ unsigned long ctrl_reg; /**< Register to configure the port direction. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me0600_dio_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-630 digital input/ouput subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param dio_idx The index of the digital i/o port on the device.
+ * @param ctrl_reg_lock Spin lock protecting the control register.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_dio_reg.h b/drivers/staging/meilhaus/me0600_dio_reg.h
new file mode 100644
index 000000000000..f116ea3b79d2
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_dio_reg.h
@@ -0,0 +1,41 @@
+/**
+ * @file me0600_dio_reg.h
+ *
+ * @brief ME-630 digital input/output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_DIO_REG_H_
+#define _ME0600_DIO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME0600_DIO_CONFIG_REG 0x0007
+#define ME0600_DIO_PORT_0_REG 0x0008
+#define ME0600_DIO_PORT_1_REG 0x0009
+#define ME0600_DIO_PORT_REG ME0600_DIO_PORT_0_REG
+
+#define ME0600_DIO_CONFIG_BIT_OUT_0 0x0001
+#define ME0600_DIO_CONFIG_BIT_OUT_1 0x0004
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_ext_irq.c b/drivers/staging/meilhaus/me0600_ext_irq.c
new file mode 100644
index 000000000000..eba18adecb72
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_ext_irq.c
@@ -0,0 +1,478 @@
+/**
+ * @file me0600_ext_irq.c
+ *
+ * @brief ME-630 external interrupt subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+#include "meids.h"
+#include "medebug.h"
+
+#include "meplx_reg.h"
+#include "me0600_ext_irq_reg.h"
+#include "me0600_ext_irq.h"
+
+/*
+ * Functions
+ */
+
+static int me0600_ext_irq_io_irq_start(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ me0600_ext_irq_subdevice_t *instance;
+ uint32_t tmp;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags & ~ME_IO_IRQ_START_DIO_BIT) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (instance->lintno > 1) {
+ PERROR("Wrong idx=%d.\n", instance->lintno);
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (irq_source != ME_IRQ_SOURCE_DIO_LINE) {
+ PERROR("Invalid irq source specified.\n");
+ return ME_ERRNO_INVALID_IRQ_SOURCE;
+ }
+
+ if (irq_edge != ME_IRQ_EDGE_RISING) {
+ PERROR("Invalid irq edge specified.\n");
+ return ME_ERRNO_INVALID_IRQ_EDGE;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->intcsr_lock);
+ tmp = inl(instance->intcsr);
+ switch (instance->lintno) {
+ case 0:
+ tmp |=
+ PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL |
+ PLX_INTCSR_PCI_INT_EN;
+ break;
+ case 1:
+ tmp |=
+ PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL |
+ PLX_INTCSR_PCI_INT_EN;
+ break;
+ }
+ outl(tmp, instance->intcsr);
+ PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp);
+ spin_unlock(instance->intcsr_lock);
+ instance->rised = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_ext_irq_io_irq_wait(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ me0600_ext_irq_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->rised <= 0) {
+ instance->rised = 0;
+
+ if (time_out) {
+ t = wait_event_interruptible_timeout(instance->
+ wait_queue,
+ (instance->rised !=
+ 0), t);
+
+ if (t == 0) {
+ PERROR("Wait on interrupt timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ } else {
+ wait_event_interruptible(instance->wait_queue,
+ (instance->rised != 0));
+ }
+
+ if (instance->rised < 0) {
+ PERROR("Wait on interrupt aborted by user.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on interrupt aborted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ instance->rised = 0;
+ *irq_count = instance->n;
+ *value = 1;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_ext_irq_io_irq_stop(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel, int flags)
+{
+ me0600_ext_irq_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t tmp;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (instance->lintno > 1) {
+ PERROR("Wrong idx=%d.\n", instance->lintno);
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->intcsr_lock);
+ tmp = inl(instance->intcsr);
+ switch (instance->lintno) {
+ case 0:
+ tmp &= ~PLX_INTCSR_LOCAL_INT1_EN;
+ break;
+ case 1:
+ tmp &= ~PLX_INTCSR_LOCAL_INT2_EN;
+ break;
+ }
+ outl(tmp, instance->intcsr);
+ PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp);
+ spin_unlock(instance->intcsr_lock);
+ instance->rised = -1;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_ext_irq_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me0600_ext_irq_subdevice_t *instance;
+ uint32_t tmp;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->intcsr_lock);
+ tmp = inl(instance->intcsr);
+ switch (instance->lintno) {
+ case 0:
+ tmp |= PLX_INTCSR_LOCAL_INT1_POL | PLX_INTCSR_PCI_INT_EN;
+ tmp &= ~PLX_INTCSR_LOCAL_INT1_EN;
+ break;
+ case 1:
+ tmp |= PLX_INTCSR_LOCAL_INT2_POL | PLX_INTCSR_PCI_INT_EN;
+ tmp &= ~PLX_INTCSR_LOCAL_INT2_EN;
+ break;
+ }
+ outl(tmp, instance->intcsr);
+ PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp);
+ spin_unlock(instance->intcsr_lock);
+
+ instance->rised = -1;
+ instance->n = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_ext_irq_query_number_channels(struct me_subdevice *subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 1;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_ext_irq_query_subdevice_type(struct me_subdevice *subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_EXT_IRQ;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_ext_irq_query_subdevice_caps(struct me_subdevice *subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_EXT_IRQ_EDGE_RISING;
+ return ME_ERRNO_SUCCESS;
+}
+
+static void me0600_ext_irq_destructor(struct me_subdevice *subdevice)
+{
+ me0600_ext_irq_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_ext_irq_subdevice_t *) subdevice;
+
+ free_irq(instance->irq, (void *)instance);
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me0600_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me0600_isr(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{
+ me0600_ext_irq_subdevice_t *instance;
+ uint32_t status;
+ uint32_t mask = PLX_INTCSR_PCI_INT_EN;
+ irqreturn_t ret = IRQ_HANDLED;
+
+ instance = (me0600_ext_irq_subdevice_t *) dev_id;
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ PDEBUG("executed.\n");
+
+ if (instance->lintno > 1) {
+ PERROR_CRITICAL
+ ("%s():Wrong subdevice index=%d plx:irq_status_reg=0x%04X.\n",
+ __func__, instance->lintno, inl(instance->intcsr));
+ return IRQ_NONE;
+ }
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->intcsr_lock);
+ status = inl(instance->intcsr);
+ switch (instance->lintno) {
+ case 0:
+ mask |= PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_LOCAL_INT1_EN;
+ break;
+ case 1:
+ mask |= PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_LOCAL_INT2_EN;
+ break;
+ }
+
+ if ((status & mask) == mask) {
+ instance->rised = 1;
+ instance->n++;
+ inb(instance->reset_reg);
+ PDEBUG("Interrupt detected.\n");
+ } else {
+ PINFO
+ ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n",
+ jiffies, __func__, status);
+ ret = IRQ_NONE;
+ }
+ spin_unlock(instance->intcsr_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return ret;
+}
+
+me0600_ext_irq_subdevice_t *me0600_ext_irq_constructor(uint32_t plx_reg_base,
+ uint32_t me0600_reg_base,
+ spinlock_t * intcsr_lock,
+ unsigned ext_irq_idx,
+ int irq)
+{
+ me0600_ext_irq_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me0600_ext_irq_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for 630_ext_irq instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me0600_ext_irq_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->intcsr_lock = intcsr_lock;
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ subdevice->lintno = ext_irq_idx;
+
+ /* Request interrupt line */
+ subdevice->irq = irq;
+
+ err = request_irq(subdevice->irq, me0600_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME0600_NAME, (void *)subdevice);
+
+ if (err) {
+ PERROR("Cannot get interrupt line.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", subdevice->irq);
+
+ /* Initialize registers */
+ subdevice->intcsr = plx_reg_base + PLX_INTCSR;
+ subdevice->reset_reg =
+ me0600_reg_base + ME0600_INT_0_RESET_REG + ext_irq_idx;
+
+ /* Initialize the subdevice methods */
+ subdevice->base.me_subdevice_io_irq_start = me0600_ext_irq_io_irq_start;
+ subdevice->base.me_subdevice_io_irq_wait = me0600_ext_irq_io_irq_wait;
+ subdevice->base.me_subdevice_io_irq_stop = me0600_ext_irq_io_irq_stop;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me0600_ext_irq_io_reset_subdevice;
+ subdevice->base.me_subdevice_query_number_channels =
+ me0600_ext_irq_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me0600_ext_irq_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me0600_ext_irq_query_subdevice_caps;
+ subdevice->base.me_subdevice_destructor = me0600_ext_irq_destructor;
+
+ subdevice->rised = 0;
+ subdevice->n = 0;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me0600_ext_irq.h b/drivers/staging/meilhaus/me0600_ext_irq.h
new file mode 100644
index 000000000000..f5f2204b49a0
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_ext_irq.h
@@ -0,0 +1,58 @@
+/**
+ * @file me0600_ext_irq.h
+ *
+ * @brief ME-630 external interrupt implementation.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME0600_EXT_IRQ_H_
+#define _ME0600_EXT_IRQ_H_
+
+#include <linux/sched.h>
+
+#include "mesubdevice.h"
+#include "meslock.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The ME-630 external interrupt subdevice class.
+ */
+typedef struct me0600_ext_irq_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *intcsr_lock; /**< Spin lock to protect #intcsr. */
+
+ wait_queue_head_t wait_queue; /**< Queue to put on threads waiting for an interrupt. */
+
+ int irq; /**< The irq number assigned by PCI BIOS. */
+ int rised; /**< If true an interrupt has occured. */
+ unsigned int n; /**< The number of interrupt since the driver was loaded. */
+ unsigned int lintno; /**< The number of the local PCI interrupt. */
+
+ uint32_t intcsr; /**< The PLX interrupt control and status register. */
+ uint32_t reset_reg; /**< The control register. */
+} me0600_ext_irq_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-630 external interrupt instance.
+ *
+ * @param plx_reg_base The register base address of the PLX chip as returned by the PCI BIOS.
+ * @param me0600_reg_base The register base address of the ME-630 device as returned by the PCI BIOS.
+ * @param irq The irq assigned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me0600_ext_irq_subdevice_t *me0600_ext_irq_constructor(uint32_t plx_reg_base,
+ uint32_t me0600_reg_base,
+ spinlock_t * intcsr_lock,
+ unsigned int ext_irq_idx,
+ int irq);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_ext_irq_reg.h b/drivers/staging/meilhaus/me0600_ext_irq_reg.h
new file mode 100644
index 000000000000..f6198fa6d2b2
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_ext_irq_reg.h
@@ -0,0 +1,18 @@
+/**
+ * @file me0600_ext_irq_reg.h
+ *
+ * @brief ME-630 external interrupt register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME0600_EXT_IRQ_REG_H_
+#define _ME0600_EXT_IRQ_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME0600_INT_0_RESET_REG 0x0005
+#define ME0600_INT_1_RESET_REG 0x0006
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_optoi.c b/drivers/staging/meilhaus/me0600_optoi.c
new file mode 100644
index 000000000000..b6d977f228ca
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_optoi.c
@@ -0,0 +1,243 @@
+/**
+ * @file me0600_optoi.c
+ *
+ * @brief ME-630 Optoisolated input subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me0600_optoi_reg.h"
+#include "me0600_optoi.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me0600_optoi_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ PDEBUG("executed.\n");
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_optoi_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type,
+ int trig_edge, int flags)
+{
+ me0600_optoi_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_optoi_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config != ME_SINGLE_CONFIG_DIO_INPUT) {
+ PERROR("Invalid port direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+
+ break;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_optoi_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me0600_optoi_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_optoi_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = inb(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inb(instance->port_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_optoi_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_optoi_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DI;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_optoi_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+me0600_optoi_subdevice_t *me0600_optoi_constructor(uint32_t reg_base)
+{
+ me0600_optoi_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me0600_optoi_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me0600_optoi_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ /* Save the subdevice index */
+ subdevice->port_reg = reg_base + ME0600_OPTO_INPUT_REG;
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me0600_optoi_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me0600_optoi_io_single_config;
+ subdevice->base.me_subdevice_io_single_read =
+ me0600_optoi_io_single_read;
+ subdevice->base.me_subdevice_query_number_channels =
+ me0600_optoi_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me0600_optoi_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me0600_optoi_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me0600_optoi.h b/drivers/staging/meilhaus/me0600_optoi.h
new file mode 100644
index 000000000000..e7e69bcde9c9
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_optoi.h
@@ -0,0 +1,58 @@
+/**
+ * @file me0600_optoi.h
+ *
+ * @brief ME-630 Optoisolated input subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_OPTOI_H_
+#define _ME0600_OPTOI_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me0600_optoi_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+
+ uint32_t port_reg; /**< Register holding the port status. */
+} me0600_optoi_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-630 Optoisolated input subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me0600_optoi_subdevice_t *me0600_optoi_constructor(uint32_t reg_base);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_optoi_reg.h b/drivers/staging/meilhaus/me0600_optoi_reg.h
new file mode 100644
index 000000000000..e0bc45054000
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_optoi_reg.h
@@ -0,0 +1,35 @@
+/**
+ * @file me0600_optoi_reg.h
+ *
+ * @brief ME-630 Optoisolated input subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_OPTOI_REG_H_
+#define _ME0600_OPTOI_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME0600_OPTO_INPUT_REG 0x0004
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_relay.c b/drivers/staging/meilhaus/me0600_relay.c
new file mode 100644
index 000000000000..2665c69addd2
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_relay.c
@@ -0,0 +1,359 @@
+/**
+ * @file me0600_relay.c
+ *
+ * @brief ME-630 relay subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me0600_relay_reg.h"
+#include "me0600_relay.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me0600_relay_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me0600_relay_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_relay_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ outb(0x0, instance->port_0_reg);
+ PDEBUG_REG("port_0_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_0_reg - instance->reg_base, 0);
+ outb(0x0, instance->port_1_reg);
+ PDEBUG_REG("port_1_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_1_reg - instance->reg_base, 0);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_relay_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type,
+ int trig_edge, int flags)
+{
+ me0600_relay_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_relay_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_WORD:
+ if (channel == 0) {
+ if (single_config != ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ PERROR("Invalid word direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+
+ break;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_relay_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me0600_relay_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_relay_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = inb(instance->port_0_reg) & (0x1 << channel);
+ } else if ((channel >= 8) && (channel < 16)) {
+ *value =
+ inb(instance->port_1_reg) & (0x1 << (channel - 8));
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inb(instance->port_0_reg);
+ } else if (channel == 1) {
+ *value = inb(instance->port_1_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_WORD:
+ if (channel == 0) {
+ *value = (uint32_t) inb(instance->port_1_reg) << 8;
+ *value |= inb(instance->port_0_reg);
+ } else {
+ PERROR("Invalid word number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_relay_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me0600_relay_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t state;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_relay_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ state = inb(instance->port_0_reg);
+ state =
+ value ? (state | (0x1 << channel)) : (state &
+ ~(0x1 <<
+ channel));
+ outb(state, instance->port_0_reg);
+ } else if ((channel >= 8) && (channel < 16)) {
+ state = inb(instance->port_1_reg);
+ state =
+ value ? (state | (0x1 << (channel - 8))) : (state &
+ ~(0x1 <<
+ (channel
+ -
+ 8)));
+ outb(state, instance->port_1_reg);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ outb(value, instance->port_0_reg);
+ } else if (channel == 1) {
+ outb(value, instance->port_1_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_WORD:
+ if (channel == 0) {
+ outb(value, instance->port_0_reg);
+ outb(value >> 8, instance->port_1_reg);
+ } else {
+ PERROR("Invalid word number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ break;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_relay_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 16;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_relay_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_relay_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+me0600_relay_subdevice_t *me0600_relay_constructor(uint32_t reg_base)
+{
+ me0600_relay_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me0600_relay_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me0600_relay_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ /* Save the subdevice index */
+ subdevice->port_0_reg = reg_base + ME0600_RELAIS_0_REG;
+ subdevice->port_1_reg = reg_base + ME0600_RELAIS_1_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me0600_relay_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me0600_relay_io_single_config;
+ subdevice->base.me_subdevice_io_single_read =
+ me0600_relay_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me0600_relay_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me0600_relay_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me0600_relay_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me0600_relay_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me0600_relay.h b/drivers/staging/meilhaus/me0600_relay.h
new file mode 100644
index 000000000000..2ce7dcab8b39
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_relay.h
@@ -0,0 +1,63 @@
+/**
+ * @file me0600_relay.h
+ *
+ * @brief ME-630 relay subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_RELAY_H_
+#define _ME0600_RELAY_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me0600_relay_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+
+ unsigned long port_0_reg; /**< Register holding the port status. */
+ unsigned long port_1_reg; /**< Register holding the port status. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me0600_relay_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-630 relay subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param ctrl_reg_lock Spin lock protecting the control register.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me0600_relay_subdevice_t *me0600_relay_constructor(uint32_t reg_base);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_relay_reg.h b/drivers/staging/meilhaus/me0600_relay_reg.h
new file mode 100644
index 000000000000..ba4db2e223c5
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_relay_reg.h
@@ -0,0 +1,36 @@
+/**
+ * @file me0600_relay_reg.h
+ *
+ * @brief ME-630 relay subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_RELAY_REG_H_
+#define _ME0600_RELAY_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME0600_RELAIS_0_REG 0x0001
+#define ME0600_RELAIS_1_REG 0x0002
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_ttli.c b/drivers/staging/meilhaus/me0600_ttli.c
new file mode 100644
index 000000000000..ab8e13b6f329
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_ttli.c
@@ -0,0 +1,238 @@
+/**
+ * @file me0600_ttli.c
+ *
+ * @brief ME-630 TTL input subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me0600_ttli_reg.h"
+#include "me0600_ttli.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me0600_ttli_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ PDEBUG("executed.\n");
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_ttli_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me0600_ttli_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_ttli_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config != ME_SINGLE_CONFIG_DIO_INPUT) {
+ PERROR("Invalid port direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+
+ break;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_ttli_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me0600_ttli_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0600_ttli_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = inb(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inb(instance->port_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0600_ttli_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_ttli_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DI;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0600_ttli_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+me0600_ttli_subdevice_t *me0600_ttli_constructor(uint32_t reg_base)
+{
+ me0600_ttli_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me0600_ttli_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me0600_ttli_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ /* Save the subdevice index */
+ subdevice->port_reg = reg_base + ME0600_TTL_INPUT_REG;
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me0600_ttli_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me0600_ttli_io_single_config;
+ subdevice->base.me_subdevice_io_single_read =
+ me0600_ttli_io_single_read;
+ subdevice->base.me_subdevice_query_number_channels =
+ me0600_ttli_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me0600_ttli_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me0600_ttli_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me0600_ttli.h b/drivers/staging/meilhaus/me0600_ttli.h
new file mode 100644
index 000000000000..6c9039614867
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_ttli.h
@@ -0,0 +1,58 @@
+/**
+ * @file me0600_ttli.h
+ *
+ * @brief ME-630 TTL input subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_TTLI_H_
+#define _ME0600_TTLI_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me0600_ttli_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+
+ uint32_t port_reg; /**< Register holding the port status. */
+} me0600_ttli_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-630 TTL input subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me0600_ttli_subdevice_t *me0600_ttli_constructor(uint32_t reg_base);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0600_ttli_reg.h b/drivers/staging/meilhaus/me0600_ttli_reg.h
new file mode 100644
index 000000000000..4f986d160934
--- /dev/null
+++ b/drivers/staging/meilhaus/me0600_ttli_reg.h
@@ -0,0 +1,35 @@
+/**
+ * @file me0600_ttli_reg.h
+ *
+ * @brief ME-630 TTL input subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0600_TTLI_REG_H_
+#define _ME0600_TTLI_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME0600_TTL_INPUT_REG 0x0003
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0900_device.c b/drivers/staging/meilhaus/me0900_device.c
new file mode 100644
index 000000000000..764d5d307c44
--- /dev/null
+++ b/drivers/staging/meilhaus/me0900_device.c
@@ -0,0 +1,180 @@
+/**
+ * @file me0900_device.c
+ *
+ * @brief ME-9x device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+*/
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "medevice.h"
+#include "me0900_device.h"
+#include "me0900_reg.h"
+#include "mesubdevice.h"
+#include "me0900_do.h"
+#include "me0900_di.h"
+
+me_device_t *me0900_pci_constructor(struct pci_dev *pci_device)
+{
+ me0900_device_t *me0900_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ int err;
+ int i;
+ int port_shift;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me0900_device = kmalloc(sizeof(me0900_device_t), GFP_KERNEL);
+
+ if (!me0900_device) {
+ PERROR("Cannot get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(me0900_device, 0, sizeof(me0900_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me0900_device, pci_device);
+
+ if (err) {
+ kfree(me0900_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+
+ /* Get the index in the device version information table. */
+ version_idx =
+ me0900_versions_get_device_index(me0900_device->base.info.pci.
+ device_id);
+
+ /* Initialize 8255 chip to desired mode */
+ if (me0900_device->base.info.pci.device_id ==
+ PCI_DEVICE_ID_MEILHAUS_ME0940) {
+ outb(0x9B,
+ me0900_device->base.info.pci.reg_bases[2] +
+ ME0900_CTRL_REG);
+ } else if (me0900_device->base.info.pci.device_id ==
+ PCI_DEVICE_ID_MEILHAUS_ME0950) {
+ outb(0x89,
+ me0900_device->base.info.pci.reg_bases[2] +
+ ME0900_CTRL_REG);
+ outb(0x00,
+ me0900_device->base.info.pci.reg_bases[2] +
+ ME0900_WRITE_ENABLE_REG);
+ } else if (me0900_device->base.info.pci.device_id ==
+ PCI_DEVICE_ID_MEILHAUS_ME0960) {
+ outb(0x8B,
+ me0900_device->base.info.pci.reg_bases[2] +
+ ME0900_CTRL_REG);
+ outb(0x00,
+ me0900_device->base.info.pci.reg_bases[2] +
+ ME0900_WRITE_ENABLE_REG);
+ }
+
+ port_shift =
+ (me0900_device->base.info.pci.device_id ==
+ PCI_DEVICE_ID_MEILHAUS_ME0960) ? 1 : 0;
+ // Create subdevice instances.
+
+ for (i = 0; i < me0900_versions[version_idx].di_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me0900_di_constructor(me0900_device->
+ base.info.pci.
+ reg_bases[2],
+ i + port_shift);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me0900_device);
+ kfree(me0900_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me0900_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me0900_versions[version_idx].do_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me0900_do_constructor(me0900_device->
+ base.info.pci.
+ reg_bases[2], i);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me0900_device);
+ kfree(me0900_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me0900_device->base.slist,
+ subdevice);
+ }
+
+ return (me_device_t *) me0900_device;
+}
+
+// Init and exit of module.
+
+static int __init me0900_init(void)
+{
+ PDEBUG("executed.\n.");
+ return 0;
+}
+
+static void __exit me0900_exit(void)
+{
+ PDEBUG("executed.\n.");
+}
+
+module_init(me0900_init);
+module_exit(me0900_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for ME-9x Device");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-9x Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me0900_pci_constructor);
diff --git a/drivers/staging/meilhaus/me0900_device.h b/drivers/staging/meilhaus/me0900_device.h
new file mode 100644
index 000000000000..bd17f2521511
--- /dev/null
+++ b/drivers/staging/meilhaus/me0900_device.h
@@ -0,0 +1,92 @@
+/**
+ * @file me0900_device.h
+ *
+ * @brief ME-0900 (ME-9x) device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0900_DEVICE_H
+#define _ME0900_DEVICE_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure holding ME-0900 (ME-9x) device capabilities.
+ */
+typedef struct me0900_version {
+ uint16_t device_id;
+ unsigned int di_subdevices;
+ unsigned int do_subdevices;
+} me0900_version_t;
+
+/**
+ * @brief Device capabilities.
+ */
+static me0900_version_t me0900_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME0940, 2, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME0950, 0, 2},
+ {PCI_DEVICE_ID_MEILHAUS_ME0960, 1, 1},
+ {0},
+};
+
+#define ME0900_DEVICE_VERSIONS (sizeof(me0900_versions) / sizeof(me0900_version_t) - 1) /**< Returns the number of entries in #me0900_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #me0900_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me0900_versions.
+ */
+static inline unsigned int me0900_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME0900_DEVICE_VERSIONS; i++)
+ if (me0900_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The ME-0900 (ME-9x) device class structure.
+ */
+typedef struct me0900_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+} me0900_device_t;
+
+/**
+ * @brief The ME-9x device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-0900 (ME-9x) device instance. \n
+ * NULL on error.
+ */
+me_device_t *me0900_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0900_di.c b/drivers/staging/meilhaus/me0900_di.c
new file mode 100644
index 000000000000..d7d7394f800a
--- /dev/null
+++ b/drivers/staging/meilhaus/me0900_di.c
@@ -0,0 +1,246 @@
+/**
+ * @file me0900_di.c
+ *
+ * @brief ME-9x digital input subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "meids.h"
+#include "medebug.h"
+#include "meplx_reg.h"
+#include "me0900_reg.h"
+#include "me0900_di.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me0900_di_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ PDEBUG("executed.\n");
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0900_di_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me0900_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0900_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ } else {
+ PERROR("Invalid byte direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0900_di_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me0900_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0900_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = (~inb(instance->port_reg)) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = ~inb(instance->port_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0900_di_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0900_di_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DI;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0900_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+me0900_di_subdevice_t *me0900_di_constructor(uint32_t reg_base,
+ unsigned int di_idx)
+{
+ me0900_di_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me0900_di_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me0900_di_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ /* Save the subdevice index. */
+ subdevice->di_idx = di_idx;
+
+ /* Initialize registers */
+ if (di_idx == 0) {
+ subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
+ subdevice->port_reg = reg_base + ME0900_PORT_A_REG;
+ } else {
+ subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
+ subdevice->port_reg = reg_base + ME0900_PORT_B_REG;
+ }
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me0900_di_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me0900_di_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me0900_di_io_single_read;
+ subdevice->base.me_subdevice_query_number_channels =
+ me0900_di_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me0900_di_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me0900_di_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me0900_di.h b/drivers/staging/meilhaus/me0900_di.h
new file mode 100644
index 000000000000..014f1348fc9f
--- /dev/null
+++ b/drivers/staging/meilhaus/me0900_di.h
@@ -0,0 +1,65 @@
+/**
+ * @file me0900_di.h
+ *
+ * @brief ME-9x digital input subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0900_DI_H_
+#define _ME0900_DI_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me0900_di_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+
+ unsigned int di_idx;
+
+ unsigned long ctrl_reg;
+ unsigned long port_reg;
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me0900_di_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-9x digital input subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me0900_di_subdevice_t *me0900_di_constructor(uint32_t me0900_reg_base,
+ unsigned int di_idx);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0900_do.c b/drivers/staging/meilhaus/me0900_do.c
new file mode 100644
index 000000000000..b5b9c3a98c94
--- /dev/null
+++ b/drivers/staging/meilhaus/me0900_do.c
@@ -0,0 +1,314 @@
+/**
+ * @file me0900_do.c
+ *
+ * @brief ME-9x digital output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me0900_reg.h"
+#include "me0900_do.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me0900_do_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me0900_do_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0900_do_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ outb(0xFF, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0xff);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0900_do_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me0900_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0900_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ } else {
+ PERROR("Invalid byte direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0900_do_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me0900_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0900_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = (~inb(instance->port_reg)) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = ~inb(instance->port_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0900_do_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me0900_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long state;
+
+ PDEBUG("executed.\n");
+
+ instance = (me0900_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ state = inb(instance->port_reg);
+ state =
+ (!value) ? (state | (0x1 << channel)) : (state &
+ ~(0x1 <<
+ channel));
+ outb(state, instance->port_reg);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ outb(~(value), instance->port_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me0900_do_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0900_do_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me0900_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+me0900_do_subdevice_t *me0900_do_constructor(uint32_t reg_base,
+ unsigned int do_idx)
+{
+ me0900_do_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me0900_do_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me0900_do_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ /* Save the subdevice index */
+ subdevice->do_idx = do_idx;
+
+ /* Initialize registers */
+ if (do_idx == 0) {
+ subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
+ subdevice->port_reg = reg_base + ME0900_PORT_A_REG;
+ subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG;
+ subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG;
+ } else {
+ subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
+ subdevice->port_reg = reg_base + ME0900_PORT_B_REG;
+ subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG;
+ subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG;
+ }
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me0900_do_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me0900_do_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me0900_do_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me0900_do_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me0900_do_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me0900_do_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me0900_do_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me0900_do.h b/drivers/staging/meilhaus/me0900_do.h
new file mode 100644
index 000000000000..13e8a8b94cfa
--- /dev/null
+++ b/drivers/staging/meilhaus/me0900_do.h
@@ -0,0 +1,68 @@
+/**
+ * @file me0900_do.h
+ *
+ * @brief ME-9x digital output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0900_DO_H_
+#define _ME0900_DO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me0900_do_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+
+ unsigned int do_idx;
+
+ unsigned long ctrl_reg;
+ unsigned long port_reg;
+ unsigned long enable_reg;
+ unsigned long disable_reg;
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me0900_do_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-9x digital output subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param do_idx The index of the digital output subdevice on this device.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me0900_do_subdevice_t *me0900_do_constructor(uint32_t reg_base,
+ unsigned int do_idx);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me0900_reg.h b/drivers/staging/meilhaus/me0900_reg.h
new file mode 100644
index 000000000000..3bf163b6ac49
--- /dev/null
+++ b/drivers/staging/meilhaus/me0900_reg.h
@@ -0,0 +1,40 @@
+/**
+ * @file me0900_reg.h
+ *
+ * @brief ME-9x register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME0900_REG_H_
+#define _ME0900_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME0900_PORT_A_REG 0x00
+#define ME0900_PORT_B_REG 0x01
+#define ME0900_PORT_C_REG 0x02
+#define ME0900_CTRL_REG 0x03 // ( ,w)
+#define ME0900_WRITE_ENABLE_REG 0x04 // (r,w)
+#define ME0900_WRITE_DISABLE_REG 0x08 // (r,w)
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me1000_device.c b/drivers/staging/meilhaus/me1000_device.c
new file mode 100644
index 000000000000..c44e214af26c
--- /dev/null
+++ b/drivers/staging/meilhaus/me1000_device.c
@@ -0,0 +1,208 @@
+/**
+ * @file me1000_device.c
+ *
+ * @brief ME-1000 device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "medevice.h"
+#include "me1000_device.h"
+#include "mesubdevice.h"
+#include "me1000_dio.h"
+
+static int me1000_config_load(me_device_t * me_device, struct file *filep,
+ me_cfg_device_entry_t * config)
+{
+ me1000_device_t *me1000_device;
+ me1000_dio_subdevice_t *dio;
+
+ PDEBUG("executed.\n");
+
+ me1000_device = (me1000_device_t *) me_device;
+
+ if (config->count == 2) {
+ if (me_slist_get_number_subdevices(&me1000_device->base.slist)
+ == 2) {
+ // Nothing to do.
+ } else {
+ // Remove 2 extra subdevices
+ dio =
+ (me1000_dio_subdevice_t *)
+ me_slist_del_subdevice_tail(&me1000_device->base.
+ slist);
+ if (dio)
+ dio->base.
+ me_subdevice_destructor((me_subdevice_t *)
+ dio);
+
+ dio =
+ (me1000_dio_subdevice_t *)
+ me_slist_del_subdevice_tail(&me1000_device->base.
+ slist);
+ if (dio)
+ dio->base.
+ me_subdevice_destructor((me_subdevice_t *)
+ dio);
+ }
+ } else if (config->count == 4) {
+ //Add 2 subdevices
+ if (me_slist_get_number_subdevices(&me1000_device->base.slist)
+ == 2) {
+ dio =
+ me1000_dio_constructor(me1000_device->base.info.pci.
+ reg_bases[2], 2,
+ &me1000_device->ctrl_lock);
+ if (!dio) {
+ PERROR("Cannot create dio subdevice.\n");
+ return ME_ERRNO_INTERNAL;
+ }
+ me_slist_add_subdevice_tail(&me1000_device->base.slist,
+ (me_subdevice_t *) dio);
+
+ dio =
+ me1000_dio_constructor(me1000_device->base.info.pci.
+ reg_bases[2], 3,
+ &me1000_device->ctrl_lock);
+ if (!dio) {
+ dio =
+ (me1000_dio_subdevice_t *)
+ me_slist_del_subdevice_tail(&me1000_device->
+ base.slist);
+ if (dio)
+ dio->base.
+ me_subdevice_destructor((me_subdevice_t *) dio);
+
+ PERROR("Cannot create dio subdevice.\n");
+ return ME_ERRNO_INTERNAL;
+ }
+ me_slist_add_subdevice_tail(&me1000_device->base.slist,
+ (me_subdevice_t *) dio);
+ } else {
+ // Nothing to do.
+ }
+ } else {
+ PERROR("Invalid configuration.\n");
+ return ME_ERRNO_INTERNAL;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+me_device_t *me1000_pci_constructor(struct pci_dev * pci_device)
+{
+ me1000_device_t *me1000_device;
+ me_subdevice_t *subdevice;
+ int err;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me1000_device = kmalloc(sizeof(me1000_device_t), GFP_KERNEL);
+
+ if (!me1000_device) {
+ PERROR("Cannot get memory for ME-1000 device instance.\n");
+ return NULL;
+ }
+
+ memset(me1000_device, 0, sizeof(me1000_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me1000_device, pci_device);
+
+ if (err) {
+ kfree(me1000_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+ // Initialize spin lock .
+ spin_lock_init(&me1000_device->ctrl_lock);
+
+ for (i = 0; i < 4; i++) {
+ subdevice =
+ (me_subdevice_t *) me1000_dio_constructor(me1000_device->
+ base.info.pci.
+ reg_bases[2], i,
+ &me1000_device->
+ ctrl_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me1000_device);
+ kfree(me1000_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me1000_device->base.slist,
+ subdevice);
+ }
+
+ // Overwrite base class methods.
+ me1000_device->base.me_device_config_load = me1000_config_load;
+
+ return (me_device_t *) me1000_device;
+}
+
+// Init and exit of module.
+static int __init me1000_init(void)
+{
+ PDEBUG("executed.\n");
+ return 0;
+}
+
+static void __exit me1000_exit(void)
+{
+ PDEBUG("executed.\n");
+}
+
+module_init(me1000_init);
+module_exit(me1000_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-1000 Devices");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-1000 Digital I/O Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me1000_pci_constructor);
diff --git a/drivers/staging/meilhaus/me1000_device.h b/drivers/staging/meilhaus/me1000_device.h
new file mode 100644
index 000000000000..cbbe1263017d
--- /dev/null
+++ b/drivers/staging/meilhaus/me1000_device.h
@@ -0,0 +1,59 @@
+/**
+ * @file me1000_device.h
+ *
+ * @brief ME-1000 device class instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1000_H_
+#define _ME1000_H_
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+#define ME1000_MAGIC_NUMBER 1000
+
+/**
+ * @brief The ME-1000 device class structure.
+ */
+typedef struct me1000_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+ spinlock_t ctrl_lock; /**< Guards the DIO mode register. */
+} me1000_device_t;
+
+/**
+ * @brief The ME-1000 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-1000 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me1000_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me1000_dio.c b/drivers/staging/meilhaus/me1000_dio.c
new file mode 100644
index 000000000000..87605a9108ae
--- /dev/null
+++ b/drivers/staging/meilhaus/me1000_dio.c
@@ -0,0 +1,438 @@
+/**
+ * @file me1000_dio.c
+ *
+ * @brief ME-1000 DIO subdevice instance.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+#include "medebug.h"
+
+#include "me1000_dio_reg.h"
+#include "me1000_dio.h"
+
+/*
+ * Defines
+ */
+#define ME1000_DIO_MAGIC_NUMBER 0x1000 /**< The magic number of the class structure. */
+
+/*
+ * Functions
+ */
+
+static int me1000_dio_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me1000_dio_subdevice_t *instance;
+ uint32_t tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1000_dio_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ tmp &= ~(0x1 << instance->dio_idx);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outl(0x00000000, instance->port_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, 0);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1000_dio_io_single_config(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me1000_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ int ctrl;
+ int size =
+ flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
+ | ME_IO_SINGLE_CONFIG_DIO_WORD |
+ ME_IO_SINGLE_CONFIG_DIO_DWORD);
+
+ PDEBUG("executed.\n");
+
+ instance = (me1000_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ ctrl = inl(instance->ctrl_reg);
+
+ switch (size) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_DWORD:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ ctrl &= ~(0x1 << instance->dio_idx);
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ ctrl |= 0x1 << instance->dio_idx;
+ } else {
+ PERROR("Invalid port direction.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!err) {
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me1000_dio_io_single_read(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me1000_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1000_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 32)) {
+ *value = inl(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if ((channel >= 0) && (channel < 4)) {
+ *value =
+ (inl(instance->port_reg) >> (channel * 8)) & 0xFF;
+ } else {
+ PERROR("Invalid byte number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_WORD:
+ if ((channel >= 0) && (channel < 2)) {
+ *value =
+ (inl(instance->port_reg) >> (channel * 16)) &
+ 0xFFFF;
+ } else {
+ PERROR("Invalid word number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_DWORD:
+ if (channel == 0) {
+ *value = inl(instance->port_reg);
+ } else {
+ PERROR("Invalid dword number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me1000_dio_io_single_write(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me1000_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t config;
+ uint32_t state;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1000_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ config = inl(instance->ctrl_reg) & (0x1 << instance->dio_idx);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 32)) {
+ if (config) {
+ state = inl(instance->port_reg);
+ state =
+ value ? (state | (0x1 << channel)) : (state
+ &
+ ~(0x1
+ <<
+ channel));
+ outl(state, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg -
+ instance->reg_base, state);
+ } else {
+ PERROR("Port is not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if ((channel >= 0) && (channel < 4)) {
+ if (config) {
+ state = inl(instance->port_reg);
+ state &= ~(0xFF << (channel * 8));
+ state |= (value & 0xFF) << (channel * 8);
+ outl(state, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg -
+ instance->reg_base, state);
+ } else {
+ PERROR("Port is not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_WORD:
+ if ((channel >= 0) && (channel < 2)) {
+ if (config) {
+ state = inl(instance->port_reg);
+ state &= ~(0xFFFF << (channel * 16));
+ state |= (value & 0xFFFF) << (channel * 16);
+ outl(state, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg -
+ instance->reg_base, state);
+ } else {
+ PERROR("Port is not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid word number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_DWORD:
+ if (channel == 0) {
+ if (config) {
+ outl(value, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg -
+ instance->reg_base, value);
+ } else {
+ PERROR("Port is not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid dword number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me1000_dio_query_number_channels(struct me_subdevice *subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = ME1000_DIO_NUMBER_CHANNELS;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1000_dio_query_subdevice_type(struct me_subdevice *subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DIO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1000_dio_query_subdevice_caps(struct me_subdevice *subdevice,
+ int *caps)
+{
+ me1000_dio_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1000_dio_subdevice_t *) subdevice;
+
+ *caps = ME_CAPS_DIO_DIR_DWORD;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+me1000_dio_subdevice_t *me1000_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock)
+{
+ me1000_dio_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me1000_dio_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for ME-1000 DIO instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me1000_dio_subdevice_t));
+
+ /* Check if counter index is out of range */
+
+ if (dio_idx >= ME1000_DIO_NUMBER_PORTS) {
+ PERROR("DIO index is out of range.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save the DIO index */
+ subdevice->dio_idx = dio_idx;
+
+ /* Initialize registers. */
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+ subdevice->ctrl_reg = reg_base + ME1000_PORT_MODE;
+ subdevice->port_reg =
+ reg_base + ME1000_PORT + (dio_idx * ME1000_PORT_STEP);
+
+ /* Override base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me1000_dio_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me1000_dio_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me1000_dio_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me1000_dio_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me1000_dio_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me1000_dio_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me1000_dio_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me1000_dio.h b/drivers/staging/meilhaus/me1000_dio.h
new file mode 100644
index 000000000000..d26e93f531af
--- /dev/null
+++ b/drivers/staging/meilhaus/me1000_dio.h
@@ -0,0 +1,71 @@
+/**
+ * @file me1000_dio.h
+ *
+ * @brief Meilhaus ME-1000 digital i/o implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1000_DIO_H_
+#define _ME1000_DIO_H_
+
+#include "mesubdevice.h"
+#include "meslock.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The ME-1000 DIO subdevice class.
+ */
+typedef struct me1000_dio_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+// uint32_t magic; /**< The magic number unique for this structure. */
+
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg and #ctrl_reg_mirror from concurrent access. */
+ int dio_idx; /**< The index of the DIO port on the device. */
+
+ unsigned long port_reg; /**< Register to read or write a value from or to the port respectively. */
+ unsigned long ctrl_reg; /**< Register to configure the DIO modes. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me1000_dio_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-1000 DIO instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param dio_idx The index of the DIO on the device.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the control register and from concurrent access.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me1000_dio_subdevice_t *me1000_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me1000_dio_reg.h b/drivers/staging/meilhaus/me1000_dio_reg.h
new file mode 100644
index 000000000000..4d5b38df437f
--- /dev/null
+++ b/drivers/staging/meilhaus/me1000_dio_reg.h
@@ -0,0 +1,50 @@
+/**
+ * @file me1000_dio_reg.h
+ *
+ * @brief ME-1000 digital i/o register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1000_DIO_REG_H_
+# define _ME1000_DIO_REG_H_
+
+# ifdef __KERNEL__
+
+# define ME1000_DIO_NUMBER_CHANNELS 32 /**< The number of channels per DIO port. */
+# define ME1000_DIO_NUMBER_PORTS 4 /**< The number of ports per ME-1000. */
+
+// # define ME1000_PORT_A 0x0000 /**< Port A base register offset. */
+// # define ME1000_PORT_B 0x0004 /**< Port B base register offset. */
+// # define ME1000_PORT_C 0x0008 /**< Port C base register offset. */
+// # define ME1000_PORT_D 0x000C /**< Port D base register offset. */
+# define ME1000_PORT 0x0000 /**< Base for port's register. */
+# define ME1000_PORT_STEP 4 /**< Distance between port's register. */
+
+# define ME1000_PORT_MODE 0x0010 /**< Configuration register to switch the port direction. */
+// # define ME1000_PORT_MODE_OUTPUT_A (1 << 0) /**< If set, port A is in output, otherwise in input mode. */
+// # define ME1000_PORT_MODE_OUTPUT_B (1 << 1) /**< If set, port B is in output, otherwise in input mode. */
+// # define ME1000_PORT_MODE_OUTPUT_C (1 << 2) /**< If set, port C is in output, otherwise in input mode. */
+// # define ME1000_PORT_MODE_OUTPUT_D (1 << 3) /**< If set, port D is in output, otherwise in input mode. */
+
+# endif //__KERNEL__
+#endif //_ME1000_DIO_REG_H_
diff --git a/drivers/staging/meilhaus/me1400_device.c b/drivers/staging/meilhaus/me1400_device.c
new file mode 100644
index 000000000000..b95bb4fce6ab
--- /dev/null
+++ b/drivers/staging/meilhaus/me1400_device.c
@@ -0,0 +1,256 @@
+/**
+ * @file me1400_device.c
+ *
+ * @brief ME-1400 device instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * User application could also include the kernel header files. But the
+ * real kernel functions are protected by #ifdef __KERNEL__.
+ */
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * This must be defined before module.h is included. Not needed, when
+ * it is a built in driver.
+ */
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+
+#include "me1400_device.h"
+#include "me8254.h"
+#include "me8254_reg.h"
+#include "me8255.h"
+#include "me1400_ext_irq.h"
+
+me_device_t *me1400_pci_constructor(struct pci_dev *pci_device)
+{
+ int err;
+ me1400_device_t *me1400_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ unsigned int me8255_idx;
+ unsigned int dio_idx;
+ unsigned int me8254_idx;
+ unsigned int ctr_idx;
+ unsigned int ext_irq_idx;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me1400_device = kmalloc(sizeof(me1400_device_t), GFP_KERNEL);
+
+ if (!me1400_device) {
+ PERROR("Cannot get memory for 1400ate device instance.\n");
+ return NULL;
+ }
+
+ memset(me1400_device, 0, sizeof(me1400_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me1400_device, pci_device);
+
+ if (err) {
+ kfree(me1400_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+
+ /* Check for ME1400 extension device. If detected we fake a ME-1400 D device id. */
+ if (me1400_device->base.info.pci.device_id ==
+ PCI_DEVICE_ID_MEILHAUS_ME140C) {
+ uint8_t ctrl;
+ ctrl =
+ inb(me1400_device->base.info.pci.reg_bases[2] +
+ ME1400D_CLK_SRC_2_REG);
+ PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n",
+ me1400_device->base.info.pci.reg_bases[2],
+ ME1400D_CLK_SRC_2_REG, ctrl);
+ outb(ctrl | 0xF0,
+ me1400_device->base.info.pci.reg_bases[2] +
+ ME1400D_CLK_SRC_2_REG);
+ PDEBUG_REG("xxx_reg outb(0x%X+0x%X)=0x%x\n",
+ me1400_device->base.info.pci.reg_bases[2],
+ ME1400D_CLK_SRC_2_REG, ctrl | 0xF0);
+ ctrl =
+ inb(me1400_device->base.info.pci.reg_bases[2] +
+ ME1400D_CLK_SRC_2_REG);
+ PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n",
+ me1400_device->base.info.pci.reg_bases[2],
+ ME1400D_CLK_SRC_2_REG, ctrl);
+
+ if ((ctrl & 0xF0) == 0xF0) {
+ PINFO("ME1400 D detected.\n");
+ me1400_device->base.info.pci.device_id =
+ PCI_DEVICE_ID_MEILHAUS_ME140D;
+ }
+ }
+
+ /* Initialize global stuff of digital i/o subdevices. */
+ for (me8255_idx = 0; me8255_idx < ME1400_MAX_8255; me8255_idx++) {
+ me1400_device->dio_current_mode[me8255_idx] = 0;
+ spin_lock_init(&me1400_device->dio_ctrl_reg_lock[me8255_idx]);
+ }
+
+ /* Initialize global stuff of counter subdevices. */
+ spin_lock_init(&me1400_device->clk_src_reg_lock);
+
+ for (me8254_idx = 0; me8254_idx < ME1400_MAX_8254; me8254_idx++)
+ spin_lock_init(&me1400_device->ctr_ctrl_reg_lock[me8254_idx]);
+
+ /* Get the index in the device version information table. */
+ version_idx =
+ me1400_versions_get_device_index(me1400_device->base.info.pci.
+ device_id);
+
+ /* Generate DIO subdevice instances. */
+ for (me8255_idx = 0;
+ me8255_idx < me1400_versions[version_idx].dio_chips;
+ me8255_idx++) {
+ for (dio_idx = 0; dio_idx < 3; dio_idx++) {
+ subdevice =
+ (me_subdevice_t *)
+ me8255_constructor(me1400_versions[version_idx].
+ device_id,
+ me1400_device->base.info.pci.
+ reg_bases[2], me8255_idx,
+ dio_idx,
+ &me1400_device->
+ dio_current_mode[me8255_idx],
+ &me1400_device->
+ dio_ctrl_reg_lock[me8255_idx]);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me1400_device);
+ kfree(me1400_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me1400_device->base.slist,
+ subdevice);
+ }
+ }
+
+ /* Generate counter subdevice instances. */
+ for (me8254_idx = 0;
+ me8254_idx < me1400_versions[version_idx].ctr_chips;
+ me8254_idx++) {
+ for (ctr_idx = 0; ctr_idx < 3; ctr_idx++) {
+ subdevice =
+ (me_subdevice_t *)
+ me8254_constructor(me1400_device->base.info.pci.
+ device_id,
+ me1400_device->base.info.pci.
+ reg_bases[2], me8254_idx,
+ ctr_idx,
+ &me1400_device->
+ ctr_ctrl_reg_lock[me8254_idx],
+ &me1400_device->
+ clk_src_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me1400_device);
+ kfree(me1400_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me1400_device->base.slist,
+ subdevice);
+ }
+ }
+
+ /* Generate external interrupt subdevice instances. */
+ for (ext_irq_idx = 0;
+ ext_irq_idx < me1400_versions[version_idx].ext_irq_subdevices;
+ ext_irq_idx++) {
+ subdevice =
+ (me_subdevice_t *)
+ me1400_ext_irq_constructor(me1400_device->base.info.pci.
+ device_id,
+ me1400_device->base.info.pci.
+ reg_bases[1],
+ me1400_device->base.info.pci.
+ reg_bases[2],
+ &me1400_device->clk_src_reg_lock,
+ me1400_device->base.irq);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me1400_device);
+ kfree(me1400_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me1400_device->base.slist,
+ subdevice);
+ }
+
+ return (me_device_t *) me1400_device;
+}
+
+// Init and exit of module.
+
+static int __init me1400_init(void)
+{
+ PDEBUG("executed.\n");
+ return 0;
+}
+
+static void __exit me1400_exit(void)
+{
+ PDEBUG("executed.\n");
+}
+
+module_init(me1400_init);
+module_exit(me1400_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-14xx devices");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-14xx MIO devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me1400_pci_constructor);
diff --git a/drivers/staging/meilhaus/me1400_device.h b/drivers/staging/meilhaus/me1400_device.h
new file mode 100644
index 000000000000..6215b250047d
--- /dev/null
+++ b/drivers/staging/meilhaus/me1400_device.h
@@ -0,0 +1,108 @@
+/**
+ * @file me1400_device.c
+ *
+ * @brief ME-1400 device family instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1400_DEVICE_H_
+#define _ME1400_DEVICE_H_
+
+#include "metypes.h"
+#include "medefines.h"
+#include "meinternal.h"
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure to store device capabilities.
+ */
+typedef struct me1400_version {
+ uint16_t device_id; /**< The PCI device id of the device. */
+ unsigned int dio_chips; /**< The number of 8255 chips on the device. */
+ unsigned int ctr_chips; /**< The number of 8254 chips on the device. */
+ unsigned int ext_irq_subdevices; /**< The number of external interrupt inputs on the device. */
+} me1400_version_t;
+
+/**
+ * @brief Defines for each ME-1400 device version its capabilities.
+ */
+static me1400_version_t me1400_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME1400, 1, 0, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME140A, 1, 1, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME140B, 2, 2, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME14E0, 1, 0, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME14EA, 1, 1, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME14EB, 2, 2, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME140C, 1, 5, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME140D, 2, 10, 1},
+ {0}
+};
+
+#define ME1400_DEVICE_VERSIONS (sizeof(me1400_versions) / sizeof(me1400_version_t) - 1) /**< Returns the number of entries in #me1400_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #me1400_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me1400_versions.
+ */
+static inline unsigned int me1400_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME1400_DEVICE_VERSIONS; i++)
+ if (me1400_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+#define ME1400_MAX_8254 10 /**< The maximum number of 8254 counter subdevices available on any ME-1400 device. */
+#define ME1400_MAX_8255 2 /**< The maximum number of 8255 digital i/o subdevices available on any ME-1400 device. */
+
+/**
+ * @brief The ME-1400 device class.
+ */
+typedef struct me1400_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+
+ spinlock_t clk_src_reg_lock; /**< Guards the 8254 clock source registers. */
+ spinlock_t ctr_ctrl_reg_lock[ME1400_MAX_8254]; /**< Guards the 8254 ctrl registers. */
+
+ int dio_current_mode[ME1400_MAX_8255]; /**< Saves the current mode setting of a single 8255 DIO chip. */
+ spinlock_t dio_ctrl_reg_lock[ME1400_MAX_8255]; /**< Guards the 8255 ctrl register and #dio_current_mode. */
+} me1400_device_t;
+
+/**
+ * @brief The ME-1400 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-1400 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me1400_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me1400_ext_irq.c b/drivers/staging/meilhaus/me1400_ext_irq.c
new file mode 100644
index 000000000000..b4df7cc58ab7
--- /dev/null
+++ b/drivers/staging/meilhaus/me1400_ext_irq.c
@@ -0,0 +1,517 @@
+/**
+ * @file me1400_ext_irq.c
+ *
+ * @brief ME-1400 external interrupt subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+#include "medebug.h"
+#include "meids.h"
+
+#include "me1400_ext_irq.h"
+#include "me1400_ext_irq_reg.h"
+
+/*
+ * Defines
+ */
+#define ME1400_EXT_IRQ_MAGIC_NUMBER 0x1401 /**< The magic number of the class structure. */
+#define ME1400_EXT_IRQ_NUMBER_CHANNELS 1 /**< One channel per counter. */
+
+/*
+ * Functions
+ */
+
+static int me1400_ext_irq_io_irq_start(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ me1400_ext_irq_subdevice_t *instance;
+ unsigned long cpu_flags;
+ uint8_t tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1400_ext_irq_subdevice_t *) subdevice;
+
+ if (flags & ~ME_IO_IRQ_START_DIO_BIT) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (irq_source != ME_IRQ_SOURCE_DIO_LINE) {
+ PERROR("Invalid irq source.\n");
+ return ME_ERRNO_INVALID_IRQ_SOURCE;
+ }
+
+ if (irq_edge != ME_IRQ_EDGE_RISING) {
+ PERROR("Invalid irq edge.\n");
+ return ME_ERRNO_INVALID_IRQ_EDGE;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ spin_lock(instance->clk_src_reg_lock);
+// // Enable IRQ on PLX
+// tmp = inb(instance->plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN);
+// outb(tmp, instance->plx_intcs_reg);
+// PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp);
+
+ // Enable IRQ
+ switch (instance->device_id) {
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ tmp = inb(instance->ctrl_reg);
+ tmp |= ME1400CD_EXT_IRQ_CLK_EN;
+ outb(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ break;
+
+ default:
+ outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ME1400AB_EXT_IRQ_IRQ_EN);
+ break;
+ }
+ spin_unlock(instance->clk_src_reg_lock);
+ instance->rised = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1400_ext_irq_io_irq_wait(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ me1400_ext_irq_subdevice_t *instance;
+ unsigned long cpu_flags;
+ long t = 0;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1400_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time out.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ /* Convert to ticks */
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->rised <= 0) {
+ instance->rised = 0;
+ if (time_out) {
+ t = wait_event_interruptible_timeout(instance->
+ wait_queue,
+ (instance->rised !=
+ 0), t);
+
+ if (t == 0) {
+ PERROR("Wait on interrupt timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ } else {
+ wait_event_interruptible(instance->wait_queue,
+ (instance->rised != 0));
+ }
+
+ if (instance->rised < 0) {
+ PERROR("Wait on interrupt aborted by user.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on interrupt aborted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ instance->rised = 0;
+ *irq_count = instance->n;
+ *value = 1;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me1400_ext_irq_io_irq_stop(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel, int flags)
+{
+ me1400_ext_irq_subdevice_t *instance;
+ unsigned long cpu_flags;
+ uint8_t tmp;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1400_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->clk_src_reg_lock);
+// // Disable IRQ on PLX
+// tmp = inb(instance->plx_intcs_reg) & ( ~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN));
+// outb(tmp, instance->plx_intcs_reg);
+// PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp);
+
+ switch (instance->device_id) {
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ tmp = inb(instance->ctrl_reg);
+ tmp &= ~ME1400CD_EXT_IRQ_CLK_EN;
+ outb(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ break;
+
+ default:
+ outb(0x00, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, 0x00);
+ break;
+ }
+ spin_unlock(instance->clk_src_reg_lock);
+ instance->rised = -1;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me1400_ext_irq_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me1400_ext_irq_subdevice_t *instance =
+ (me1400_ext_irq_subdevice_t *) subdevice;
+
+ PDEBUG("executed.\n");
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ instance->n = 0;
+ return me1400_ext_irq_io_irq_stop(subdevice, filep, 0, flags);
+}
+
+static int me1400_ext_irq_query_number_channels(struct me_subdevice *subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = ME1400_EXT_IRQ_NUMBER_CHANNELS;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1400_ext_irq_query_subdevice_type(struct me_subdevice *subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_EXT_IRQ;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1400_ext_irq_query_subdevice_caps(struct me_subdevice *subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_EXT_IRQ_EDGE_RISING;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1400_ext_irq_query_subdevice_caps_args(struct me_subdevice
+ *subdevice, int cap,
+ int *args, int count)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id,
+ struct pt_regs *regs)
+#endif
+{
+ me1400_ext_irq_subdevice_t *instance;
+ uint32_t status;
+ uint8_t tmp;
+
+ instance = (me1400_ext_irq_subdevice_t *) dev_id;
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ spin_lock(&instance->subdevice_lock);
+ status = inl(instance->plx_intcs_reg);
+// if (!((status & PLX_LOCAL_INT1_STATE) && (status & PLX_LOCAL_INT1_EN) && (status & PLX_PCI_INT_EN)))
+ if ((status &
+ (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) !=
+ (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) {
+ spin_unlock(&instance->subdevice_lock);
+ PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n",
+ jiffies, __func__, status);
+ return IRQ_NONE;
+ }
+
+ inl(instance->ctrl_reg);
+
+ PDEBUG("executed.\n");
+
+ instance->n++;
+ instance->rised = 1;
+
+ switch (instance->device_id) {
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ spin_lock(instance->clk_src_reg_lock);
+ tmp = inb(instance->ctrl_reg);
+ tmp &= ~ME1400CD_EXT_IRQ_CLK_EN;
+ outb(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ tmp |= ME1400CD_EXT_IRQ_CLK_EN;
+ outb(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->clk_src_reg_lock);
+
+ break;
+
+ default:
+ outb(0, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, 0);
+ outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ME1400AB_EXT_IRQ_IRQ_EN);
+ break;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+static void me1400_ext_irq_destructor(struct me_subdevice *subdevice)
+{
+ me1400_ext_irq_subdevice_t *instance;
+ uint8_t tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1400_ext_irq_subdevice_t *) subdevice;
+
+ // Disable IRQ on PLX
+ tmp =
+ inb(instance->
+ plx_intcs_reg) & (~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL |
+ PLX_PCI_INT_EN));
+ outb(tmp, instance->plx_intcs_reg);
+ PDEBUG_REG("ctrl_reg outb(plx:0x%lX)=0x%x\n", instance->plx_intcs_reg,
+ tmp);
+
+ free_irq(instance->irq, (void *)instance);
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id,
+ uint32_t plx_reg_base,
+ uint32_t me1400_reg_base,
+ spinlock_t *
+ clk_src_reg_lock,
+ int irq)
+{
+ me1400_ext_irq_subdevice_t *subdevice;
+ int err;
+ uint8_t tmp;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me1400_ext_irq_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for 1400_ext_irq instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me1400_ext_irq_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+ subdevice->clk_src_reg_lock = clk_src_reg_lock;
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ subdevice->irq = irq;
+
+ err = request_irq(irq, me1400_ext_irq_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME1400_NAME, (void *)subdevice);
+
+ if (err) {
+ PERROR("Can't get irq.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", subdevice->irq);
+
+ /* Initialize registers */
+ subdevice->plx_intcs_reg = plx_reg_base + PLX_INTCSR_REG;
+ subdevice->ctrl_reg = me1400_reg_base + ME1400AB_EXT_IRQ_CTRL_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = me1400_reg_base;
+#endif
+
+ // Enable IRQ on PLX
+ tmp =
+ inb(subdevice->
+ plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL |
+ PLX_PCI_INT_EN);
+ outb(tmp, subdevice->plx_intcs_reg);
+ PDEBUG_REG("ctrl_reg outb(Pplx:0x%lX)=0x%x\n", subdevice->plx_intcs_reg,
+ tmp);
+
+ /* Initialize the subdevice methods */
+ subdevice->base.me_subdevice_io_irq_start = me1400_ext_irq_io_irq_start;
+ subdevice->base.me_subdevice_io_irq_wait = me1400_ext_irq_io_irq_wait;
+ subdevice->base.me_subdevice_io_irq_stop = me1400_ext_irq_io_irq_stop;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me1400_ext_irq_io_reset_subdevice;
+ subdevice->base.me_subdevice_query_number_channels =
+ me1400_ext_irq_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me1400_ext_irq_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me1400_ext_irq_query_subdevice_caps;
+ subdevice->base.me_subdevice_query_subdevice_caps_args =
+ me1400_ext_irq_query_subdevice_caps_args;
+ subdevice->base.me_subdevice_destructor = me1400_ext_irq_destructor;
+
+ subdevice->rised = 0;
+ subdevice->n = 0;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me1400_ext_irq.h b/drivers/staging/meilhaus/me1400_ext_irq.h
new file mode 100644
index 000000000000..9b72a04701c0
--- /dev/null
+++ b/drivers/staging/meilhaus/me1400_ext_irq.h
@@ -0,0 +1,62 @@
+/**
+ * @file me1400_ext_irq.h
+ *
+ * @brief ME-1400 external interrupt implementation.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME1400_EXT_IRQ_H_
+#define _ME1400_EXT_IRQ_H_
+
+#include <linux/sched.h>
+
+#include "mesubdevice.h"
+#include "meslock.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The ME-1400 external interrupt subdevice class.
+ */
+typedef struct me1400_ext_irq_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *clk_src_reg_lock; /**< Lock protecting the clock control register. */
+
+ wait_queue_head_t wait_queue; /**< Queue to put on threads waiting for an interrupt. */
+
+ uint32_t device_id; /**< The device id of the device holding the subdevice. */
+ int irq; /**< The irq number assigned by PCI BIOS. */
+ int rised; /**< If true an interrupt has occured. */
+ unsigned int n; /**< The number of interrupt since the driver was loaded. */
+
+ unsigned long plx_intcs_reg; /**< The PLX interrupt control and status register. */
+ unsigned long ctrl_reg; /**< The control register. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me1400_ext_irq_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-1400 external interrupt instance.
+ *
+ * @param plx_reg_base The register base address of the PLX chip as returned by the PCI BIOS.
+ * @param me1400_reg_base The register base address of the ME-1400 device as returned by the PCI BIOS.
+ * @param irq The irq assigned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id,
+ uint32_t plx_reg_base,
+ uint32_t me1400_reg_base,
+ spinlock_t *
+ clk_src_reg_lock,
+ int irq);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me1400_ext_irq_reg.h b/drivers/staging/meilhaus/me1400_ext_irq_reg.h
new file mode 100644
index 000000000000..c9740f2dd3a7
--- /dev/null
+++ b/drivers/staging/meilhaus/me1400_ext_irq_reg.h
@@ -0,0 +1,56 @@
+/**
+ * @file me1400_ext_irq_reg.h
+ *
+ * @brief ME-1400 external interrupt register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1400_EXT_IRQ_REG_H_
+# define _ME1400_EXT_IRQ_REG_H_
+
+# ifdef __KERNEL__
+
+# define PLX_INTCSR_REG 0x4C /**< The PLX interrupt control and status register offset. */
+# define PLX_ICR_REG 0x50 /**< The PLX initialization control register offset. */
+
+# define PLX_LOCAL_INT1_EN 0x01 /**< If set the local interrupt 1 is enabled. */
+# define PLX_LOCAL_INT1_POL 0x02 /**< If set the local interrupt 1 polarity is high active. */
+# define PLX_LOCAL_INT1_STATE 0x04 /**< If set the local interrupt 1 is activ. */
+# define PLX_LOCAL_INT2_EN 0x08 /**< If set the local interrupt 2 is enabled. */
+# define PLX_LOCAL_INT2_POL 0x10 /**< If set the local interrupt 2 polarity is high active. */
+# define PLX_LOCAL_INT2_STATE 0x20 /**< If set the local interrupt 2 is activ. */
+# define PLX_PCI_INT_EN 0x40 /**< If set the PCI interrupt is enabled. */
+# define PLX_SOFT_INT 0x80 /**< If set an interrupt is generated. */
+
+# define ME1400AB_EXT_IRQ_CTRL_REG 0x11 /**< The external interrupt control register offset. */
+
+# define ME1400AB_EXT_IRQ_CLK_EN 0x01 /**< If this bit is set, the clock output is enabled. */
+# define ME1400AB_EXT_IRQ_IRQ_EN 0x02 /**< If set the external interrupt is enabled. Clearing this bit clears a pending interrupt. */
+
+# define ME1400CD_EXT_IRQ_CTRL_REG 0x11 /**< The external interrupt control register offset. */
+
+# define ME1400CD_EXT_IRQ_CLK_EN 0x10 /**< If set the external interrupt is enabled. Clearing this bit clears a pending interrupt.*/
+
+# endif //__KERNEL__
+
+#endif //_ME1400_EXT_IRQ_REG_H_
diff --git a/drivers/staging/meilhaus/me1600_ao.c b/drivers/staging/meilhaus/me1600_ao.c
new file mode 100644
index 000000000000..d127c6b00307
--- /dev/null
+++ b/drivers/staging/meilhaus/me1600_ao.c
@@ -0,0 +1,1033 @@
+/**
+ * @file me1600_ao.c
+ *
+ * @brief ME-1600 analog output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/* Includes
+ */
+
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#include <linux/workqueue.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+#include "medebug.h"
+
+#include "me1600_ao_reg.h"
+#include "me1600_ao.h"
+
+/* Defines
+ */
+
+static void me1600_ao_destructor(struct me_subdevice *subdevice);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void me1600_ao_work_control_task(void *subdevice);
+#else
+static void me1600_ao_work_control_task(struct work_struct *work);
+#endif
+
+static int me1600_ao_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags);
+static int me1600_ao_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep, int channel,
+ int single_config, int ref, int trig_chan,
+ int trig_type, int trig_edge, int flags);
+static int me1600_ao_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep, int channel, int *value,
+ int time_out, int flags);
+static int me1600_ao_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep, int channel, int value,
+ int time_out, int flags);
+static int me1600_ao_query_number_channels(me_subdevice_t * subdevice,
+ int *number);
+static int me1600_ao_query_subdevice_type(me_subdevice_t * subdevice, int *type,
+ int *subtype);
+static int me1600_ao_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps);
+static int me1600_ao_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit, int *min, int *max,
+ int *maxdata, int *range);
+static int me1600_ao_query_number_ranges(me_subdevice_t * subdevice, int unit,
+ int *count);
+static int me1600_ao_query_range_info(me_subdevice_t * subdevice, int range,
+ int *unit, int *min, int *max,
+ int *maxdata);
+
+/* Functions
+ */
+
+me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base,
+ unsigned int ao_idx,
+ int curr,
+ spinlock_t * config_regs_lock,
+ spinlock_t * ao_shadows_lock,
+ me1600_ao_shadow_t *
+ ao_regs_shadows,
+ struct workqueue_struct *me1600_wq)
+{
+ me1600_ao_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed. idx=%d\n", ao_idx);
+
+ // Allocate memory for subdevice instance.
+ subdevice = kmalloc(sizeof(me1600_ao_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR
+ ("Cannot get memory for analog output subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me1600_ao_subdevice_t));
+
+ // Initialize subdevice base class.
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+ subdevice->config_regs_lock = config_regs_lock;
+ subdevice->ao_shadows_lock = ao_shadows_lock;
+
+ // Save the subdevice index.
+ subdevice->ao_idx = ao_idx;
+
+ // Initialize range lists.
+ subdevice->u_ranges_count = 2;
+
+ subdevice->u_ranges[0].min = 0; //0V
+ subdevice->u_ranges[0].max = 9997558; //10V
+
+ subdevice->u_ranges[1].min = -10E6; //-10V
+ subdevice->u_ranges[1].max = 9995117; //10V
+
+ if (curr) { // This is version with current outputs.
+ subdevice->i_ranges_count = 2;
+
+ subdevice->i_ranges[0].min = 0; //0mA
+ subdevice->i_ranges[0].max = 19995117; //20mA
+
+ subdevice->i_ranges[1].min = 4E3; //4mA
+ subdevice->i_ranges[1].max = 19995118; //20mA
+ } else { // This is version without current outputs.
+ subdevice->i_ranges_count = 0;
+
+ subdevice->i_ranges[0].min = 0; //0mA
+ subdevice->i_ranges[0].max = 0; //0mA
+
+ subdevice->i_ranges[1].min = 0; //0mA
+ subdevice->i_ranges[1].max = 0; //0mA
+ }
+
+ // Initialize registers.
+ subdevice->uni_bi_reg = reg_base + ME1600_UNI_BI_REG;
+ subdevice->i_range_reg = reg_base + ME1600_020_420_REG;
+ subdevice->sim_output_reg = reg_base + ME1600_SIM_OUTPUT_REG;
+ subdevice->current_on_reg = reg_base + ME1600_CURRENT_ON_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ // Initialize shadow structure.
+ subdevice->ao_regs_shadows = ao_regs_shadows;
+
+ // Override base class methods.
+ subdevice->base.me_subdevice_destructor = me1600_ao_destructor;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me1600_ao_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me1600_ao_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me1600_ao_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me1600_ao_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me1600_ao_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me1600_ao_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me1600_ao_query_subdevice_caps;
+ subdevice->base.me_subdevice_query_range_by_min_max =
+ me1600_ao_query_range_by_min_max;
+ subdevice->base.me_subdevice_query_number_ranges =
+ me1600_ao_query_number_ranges;
+ subdevice->base.me_subdevice_query_range_info =
+ me1600_ao_query_range_info;
+
+ // Initialize wait queue.
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ // Prepare work queue.
+ subdevice->me1600_workqueue = me1600_wq;
+
+/* workqueue API changed in kernel 2.6.20 */
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
+ INIT_WORK(&subdevice->ao_control_task, me1600_ao_work_control_task,
+ (void *)subdevice);
+#else
+ INIT_DELAYED_WORK(&subdevice->ao_control_task,
+ me1600_ao_work_control_task);
+#endif
+ return subdevice;
+}
+
+static void me1600_ao_destructor(struct me_subdevice *subdevice)
+{
+ me1600_ao_subdevice_t *instance;
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ instance->ao_control_task_flag = 0;
+
+ // Reset subdevice to asure clean exit.
+ me1600_ao_io_reset_subdevice(subdevice, NULL,
+ ME_IO_RESET_SUBDEVICE_NO_FLAGS);
+
+ // Remove any tasks from work queue. This is paranoic because it was done allready in reset().
+ if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue.
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(2);
+ }
+}
+
+static int me1600_ao_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags)
+{
+ me1600_ao_subdevice_t *instance;
+ uint16_t tmp;
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger.
+
+ // Reset all settings.
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ao_shadows_lock);
+ (instance->ao_regs_shadows)->shadow[instance->ao_idx] = 0;
+ (instance->ao_regs_shadows)->mirror[instance->ao_idx] = 0;
+ (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Not waiting for triggering.
+ (instance->ao_regs_shadows)->synchronous &= ~(0x1 << instance->ao_idx); //Individual triggering.
+
+ // Set output to default (safe) state.
+ spin_lock(instance->config_regs_lock);
+ tmp = inw(instance->uni_bi_reg); // unipolar
+ tmp |= (0x1 << instance->ao_idx);
+ outw(tmp, instance->uni_bi_reg);
+ PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->uni_bi_reg - instance->reg_base, tmp);
+
+ tmp = inw(instance->current_on_reg); // Volts only!
+ tmp &= ~(0x1 << instance->ao_idx);
+ tmp &= 0x00FF;
+ outw(tmp, instance->current_on_reg);
+ PDEBUG_REG("current_on_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->current_on_reg - instance->reg_base, tmp);
+
+ tmp = inw(instance->i_range_reg); // 0..20mA <= If exists.
+ tmp &= ~(0x1 << instance->ao_idx);
+ outw(tmp, instance->i_range_reg);
+ PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->i_range_reg - instance->reg_base, tmp);
+
+ outw(0, (instance->ao_regs_shadows)->registry[instance->ao_idx]);
+ PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ (instance->ao_regs_shadows)->registry[instance->ao_idx] -
+ instance->reg_base, 0);
+
+ // Trigger output.
+ outw(0x0000, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg - instance->reg_base, 0x0000);
+ outw(0xFFFF, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg - instance->reg_base, 0xFFFF);
+ spin_unlock(instance->config_regs_lock);
+ spin_unlock(instance->ao_shadows_lock);
+
+ // Set status to 'none'
+ instance->status = ao_status_none;
+ spin_unlock(&instance->subdevice_lock);
+
+ //Signal reset if user is on wait.
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1600_ao_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me1600_ao_subdevice_t *instance;
+ uint16_t tmp;
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ // Checking parameters.
+ if (flags) {
+ PERROR
+ ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (trig_edge != ME_TRIG_EDGE_NONE) {
+ PERROR
+ ("Invalid trigger edge. Software trigger has not edge. Must be ME_TRIG_EDGE_NONE\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+
+ if (trig_type != ME_TRIG_TYPE_SW) {
+ PERROR("Invalid trigger edge. Must be ME_TRIG_TYPE_SW.\n");
+ return ME_ERRNO_INVALID_TRIG_TYPE;
+ }
+
+ if ((trig_chan != ME_TRIG_CHAN_DEFAULT)
+ && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) {
+ PERROR("Invalid trigger channel specified.\n");
+ return ME_ERRNO_INVALID_TRIG_CHAN;
+ }
+
+ if (ref != ME_REF_AO_GROUND) {
+ PERROR
+ ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if (((single_config + 1) >
+ (instance->u_ranges_count + instance->i_ranges_count))
+ || (single_config < 0)) {
+ PERROR("Invalid range specified.\n");
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+ // Checking parameters - done. All is fine. Do config.
+
+ ME_SUBDEVICE_ENTER;
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ao_shadows_lock);
+ (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger.
+ (instance->ao_regs_shadows)->shadow[instance->ao_idx] = 0;
+ (instance->ao_regs_shadows)->mirror[instance->ao_idx] = 0;
+
+ spin_lock(instance->config_regs_lock);
+ switch (single_config) {
+ case 0: // 0V 10V
+ tmp = inw(instance->current_on_reg); // Volts
+ tmp &= ~(0x1 << instance->ao_idx);
+ outw(tmp, instance->current_on_reg);
+ PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->current_on_reg - instance->reg_base, tmp);
+
+ // 0V
+ outw(0,
+ (instance->ao_regs_shadows)->registry[instance->ao_idx]);
+ PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ (instance->ao_regs_shadows)->registry[instance->
+ ao_idx] -
+ instance->reg_base, 0);
+
+ tmp = inw(instance->uni_bi_reg); // unipolar
+ tmp |= (0x1 << instance->ao_idx);
+ outw(tmp, instance->uni_bi_reg);
+ PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->uni_bi_reg - instance->reg_base, tmp);
+
+ tmp = inw(instance->i_range_reg); // 0..20mA <= If exists.
+ tmp &= ~(0x1 << instance->ao_idx);
+ outw(tmp, instance->i_range_reg);
+ PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->i_range_reg - instance->reg_base, tmp);
+ break;
+
+ case 1: // -10V 10V
+ tmp = inw(instance->current_on_reg); // Volts
+ tmp &= ~(0x1 << instance->ao_idx);
+ outw(tmp, instance->current_on_reg);
+ PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->current_on_reg - instance->reg_base, tmp);
+
+ // 0V
+ outw(0x0800,
+ (instance->ao_regs_shadows)->registry[instance->ao_idx]);
+ PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ (instance->ao_regs_shadows)->registry[instance->
+ ao_idx] -
+ instance->reg_base, 0x0800);
+
+ tmp = inw(instance->uni_bi_reg); // bipolar
+ tmp &= ~(0x1 << instance->ao_idx);
+ outw(tmp, instance->uni_bi_reg);
+ PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->uni_bi_reg - instance->reg_base, tmp);
+
+ tmp = inw(instance->i_range_reg); // 0..20mA <= If exists.
+ tmp &= ~(0x1 << instance->ao_idx);
+ outw(tmp, instance->i_range_reg);
+ PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->i_range_reg - instance->reg_base, tmp);
+ break;
+
+ case 2: // 0mA 20mA
+ tmp = inw(instance->current_on_reg); // mAmpers
+ tmp |= (0x1 << instance->ao_idx);
+ outw(tmp, instance->current_on_reg);
+ PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->current_on_reg - instance->reg_base, tmp);
+
+ tmp = inw(instance->i_range_reg); // 0..20mA
+ tmp &= ~(0x1 << instance->ao_idx);
+ outw(tmp, instance->i_range_reg);
+ PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->i_range_reg - instance->reg_base, tmp);
+
+ // 0mA
+ outw(0,
+ (instance->ao_regs_shadows)->registry[instance->ao_idx]);
+ PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ (instance->ao_regs_shadows)->registry[instance->
+ ao_idx] -
+ instance->reg_base, 0);
+
+ tmp = inw(instance->uni_bi_reg); // unipolar
+ tmp |= (0x1 << instance->ao_idx);
+ outw(tmp, instance->uni_bi_reg);
+ PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->uni_bi_reg - instance->reg_base, tmp);
+ break;
+
+ case 3: // 4mA 20mA
+ tmp = inw(instance->current_on_reg); // mAmpers
+ tmp |= (0x1 << instance->ao_idx);
+ outw(tmp, instance->current_on_reg);
+ PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->current_on_reg - instance->reg_base, tmp);
+
+ tmp = inw(instance->i_range_reg); // 4..20mA
+ tmp |= (0x1 << instance->ao_idx);
+ outw(tmp, instance->i_range_reg);
+ PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->i_range_reg - instance->reg_base, tmp);
+
+ // 4mA
+ outw(0,
+ (instance->ao_regs_shadows)->registry[instance->ao_idx]);
+ PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ (instance->ao_regs_shadows)->registry[instance->
+ ao_idx] -
+ instance->reg_base, 0);
+
+ tmp = inw(instance->uni_bi_reg); // unipolar
+ tmp |= (0x1 << instance->ao_idx);
+ outw(tmp, instance->uni_bi_reg);
+ PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->uni_bi_reg - instance->reg_base, tmp);
+ break;
+ }
+
+ // Trigger output.
+ outw(0x0000, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg - instance->reg_base, 0x0000);
+ outw(0xFFFF, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg - instance->reg_base, 0xFFFF);
+
+ if (trig_chan == ME_TRIG_CHAN_DEFAULT) { // Individual triggering.
+ (instance->ao_regs_shadows)->synchronous &=
+ ~(0x1 << instance->ao_idx);
+ PDEBUG("Individual triggering.\n");
+ } else if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS) { // Synchronous triggering.
+ (instance->ao_regs_shadows)->synchronous |=
+ (0x1 << instance->ao_idx);
+ PDEBUG("Synchronous triggering.\n");
+ }
+ spin_unlock(instance->config_regs_lock);
+ spin_unlock(instance->ao_shadows_lock);
+
+ instance->status = ao_status_single_configured;
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1600_ao_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me1600_ao_subdevice_t *instance;
+ unsigned long delay = 0;
+ unsigned long j = 0;
+ int err = ME_ERRNO_SUCCESS;
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags & ~ME_IO_SINGLE_NONBLOCKING) {
+ PERROR("Invalid flag specified. %d\n", flags);
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if ((!flags) && ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { //Blocking mode. Wait for software trigger.
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+ if (delay == 0)
+ delay = 1;
+ }
+
+ j = jiffies;
+
+ //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (!((instance->
+ ao_regs_shadows)->
+ trigger & instance->
+ ao_idx)),
+ (delay) ? delay : LONG_MAX);
+
+ if (instance == ao_status_none) { // Reset was called.
+ PDEBUG("Single canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ if ((delay) && ((jiffies - j) >= delay)) {
+ PDEBUG("Timeout reached.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ }
+
+ *value = (instance->ao_regs_shadows)->mirror[instance->ao_idx];
+
+ return err;
+}
+
+static int me1600_ao_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me1600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long delay = 0;
+ int i;
+ unsigned long j = 0;
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags &
+ ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS |
+ ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (value & ~ME1600_AO_MAX_DATA) {
+ PERROR("Invalid value provided.\n");
+ return ME_ERRNO_VALUE_OUT_OF_RANGE;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger.
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+
+ if (delay == 0)
+ delay = 1;
+ }
+ //Write value.
+ spin_lock(instance->ao_shadows_lock);
+ (instance->ao_regs_shadows)->shadow[instance->ao_idx] =
+ (uint16_t) value;
+
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { // Trigger all outputs from synchronous list.
+ for (i = 0; i < (instance->ao_regs_shadows)->count; i++) {
+ if (((instance->ao_regs_shadows)->synchronous & (0x1 << i)) || (i == instance->ao_idx)) { // Set all from synchronous list to correct state.
+ PDEBUG
+ ("Synchronous triggering: output %d. idx=%d\n",
+ i, instance->ao_idx);
+ (instance->ao_regs_shadows)->mirror[i] =
+ (instance->ao_regs_shadows)->shadow[i];
+
+ outw((instance->ao_regs_shadows)->shadow[i],
+ (instance->ao_regs_shadows)->registry[i]);
+ PDEBUG_REG
+ ("channel_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ (instance->ao_regs_shadows)->registry[i] -
+ instance->reg_base,
+ (instance->ao_regs_shadows)->shadow[i]);
+
+ (instance->ao_regs_shadows)->trigger &=
+ ~(0x1 << i);
+ }
+ }
+
+ // Trigger output.
+ outw(0x0000, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg - instance->reg_base, 0);
+ outw(0xFFFF, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg - instance->reg_base,
+ 0xFFFF);
+ instance->status = ao_status_single_end;
+ } else { // Individual mode.
+ if ((instance->ao_regs_shadows)->synchronous & (0x1 << instance->ao_idx)) { // Put on synchronous start list. Set output as waiting for trigger.
+ PDEBUG("Add to synchronous list. idx=%d\n",
+ instance->ao_idx);
+ (instance->ao_regs_shadows)->trigger |=
+ (0x1 << instance->ao_idx);
+ instance->status = ao_status_single_run;
+ PDEBUG("Synchronous list: 0x%x.\n",
+ (instance->ao_regs_shadows)->synchronous);
+ } else { // Fired this one.
+ PDEBUG("Triggering. idx=%d\n", instance->ao_idx);
+ (instance->ao_regs_shadows)->mirror[instance->ao_idx] =
+ (instance->ao_regs_shadows)->shadow[instance->
+ ao_idx];
+
+ outw((instance->ao_regs_shadows)->
+ shadow[instance->ao_idx],
+ (instance->ao_regs_shadows)->registry[instance->
+ ao_idx]);
+ PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ (instance->ao_regs_shadows)->
+ registry[instance->ao_idx] -
+ instance->reg_base,
+ (instance->ao_regs_shadows)->
+ shadow[instance->ao_idx]);
+
+ // Set output as triggered.
+ (instance->ao_regs_shadows)->trigger &=
+ ~(0x1 << instance->ao_idx);
+
+ // Trigger output.
+ outw(0x0000, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg -
+ instance->reg_base, 0);
+ outw(0xFFFF, instance->sim_output_reg);
+ PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sim_output_reg -
+ instance->reg_base, 0xFFFF);
+ instance->status = ao_status_single_end;
+ }
+ }
+ spin_unlock(instance->ao_shadows_lock);
+
+ //Init control task
+ instance->timeout.delay = delay;
+ instance->timeout.start_time = jiffies;
+ instance->ao_control_task_flag = 1;
+ queue_delayed_work(instance->me1600_workqueue,
+ &instance->ao_control_task, 1);
+
+ if ((!flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING) && ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { //Blocking mode. Wait for software trigger.
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+ if (delay == 0)
+ delay = 1;
+ }
+
+ j = jiffies;
+
+ //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (!((instance->
+ ao_regs_shadows)->
+ trigger & instance->
+ ao_idx)),
+ (delay) ? delay : LONG_MAX);
+
+ if (instance == ao_status_none) {
+ PDEBUG("Single canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ if ((delay) && ((jiffies - j) >= delay)) {
+ PDEBUG("Timeout reached.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me1600_ao_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ me1600_ao_subdevice_t *instance;
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *number = 1; //Every subdevice has only 1 channel.
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1600_ao_query_subdevice_type(me_subdevice_t * subdevice, int *type,
+ int *subtype)
+{
+ me1600_ao_subdevice_t *instance;
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *type = ME_TYPE_AO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1600_ao_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_AO_TRIG_SYNCHRONOUS;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1600_ao_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range)
+{
+ me1600_ao_subdevice_t *instance;
+ int i;
+ int r = -1;
+ int diff = 21E6;
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if ((*max - *min) < 0) {
+ PERROR("Invalid minimum and maximum values specified.\n");
+ return ME_ERRNO_INVALID_MIN_MAX;
+ }
+ // Maximum ranges are slightly less then 10V or 20mA. For convenient we accepted this value as valid one.
+ if (unit == ME_UNIT_VOLT) {
+ for (i = 0; i < instance->u_ranges_count; i++) {
+ if ((instance->u_ranges[i].min <= *min)
+ && ((instance->u_ranges[i].max + 5000) >= *max)) {
+ if ((instance->u_ranges[i].max -
+ instance->u_ranges[i].min) - (*max -
+ *min) <
+ diff) {
+ r = i;
+ diff =
+ (instance->u_ranges[i].max -
+ instance->u_ranges[i].min) -
+ (*max - *min);
+ }
+ }
+ }
+
+ if (r < 0) {
+ PERROR("No matching range found.\n");
+ return ME_ERRNO_NO_RANGE;
+ } else {
+ *min = instance->u_ranges[r].min;
+ *max = instance->u_ranges[r].max;
+ *range = r;
+ }
+ } else if (unit == ME_UNIT_AMPERE) {
+ for (i = 0; i < instance->i_ranges_count; i++) {
+ if ((instance->i_ranges[i].min <= *min)
+ && (instance->i_ranges[i].max + 5000 >= *max)) {
+ if ((instance->i_ranges[i].max -
+ instance->i_ranges[i].min) - (*max -
+ *min) <
+ diff) {
+ r = i;
+ diff =
+ (instance->i_ranges[i].max -
+ instance->i_ranges[i].min) -
+ (*max - *min);
+ }
+ }
+ }
+
+ if (r < 0) {
+ PERROR("No matching range found.\n");
+ return ME_ERRNO_NO_RANGE;
+ } else {
+ *min = instance->i_ranges[r].min;
+ *max = instance->i_ranges[r].max;
+ *range = r + instance->u_ranges_count;
+ }
+ } else {
+ PERROR("Invalid physical unit specified.\n");
+ return ME_ERRNO_INVALID_UNIT;
+ }
+ *maxdata = ME1600_AO_MAX_DATA;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1600_ao_query_number_ranges(me_subdevice_t * subdevice,
+ int unit, int *count)
+{
+ me1600_ao_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+ switch (unit) {
+ case ME_UNIT_VOLT:
+ *count = instance->u_ranges_count;
+ break;
+ case ME_UNIT_AMPERE:
+ *count = instance->i_ranges_count;
+ break;
+ case ME_UNIT_ANY:
+ *count = instance->u_ranges_count + instance->i_ranges_count;
+ break;
+ default:
+ *count = 0;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1600_ao_query_range_info(me_subdevice_t * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata)
+{
+ me1600_ao_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me1600_ao_subdevice_t *) subdevice;
+
+ if (((range + 1) >
+ (instance->u_ranges_count + instance->i_ranges_count))
+ || (range < 0)) {
+ PERROR("Invalid range number specified.\n");
+ return ME_ERRNO_INVALID_RANGE;
+ }
+
+ if (range < instance->u_ranges_count) {
+ *unit = ME_UNIT_VOLT;
+ *min = instance->u_ranges[range].min;
+ *max = instance->u_ranges[range].max;
+ } else if (range < instance->u_ranges_count + instance->i_ranges_count) {
+ *unit = ME_UNIT_AMPERE;
+ *min = instance->i_ranges[range - instance->u_ranges_count].min;
+ *max = instance->i_ranges[range - instance->u_ranges_count].max;
+ }
+ *maxdata = ME1600_AO_MAX_DATA;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void me1600_ao_work_control_task(void *subdevice)
+#else
+static void me1600_ao_work_control_task(struct work_struct *work)
+#endif
+{
+ me1600_ao_subdevice_t *instance;
+ int reschedule = 1;
+ int signaling = 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ instance = (me1600_ao_subdevice_t *) subdevice;
+#else
+ instance =
+ container_of((void *)work, me1600_ao_subdevice_t, ao_control_task);
+#endif
+
+ PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies,
+ instance->ao_idx);
+
+ if (!((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { // Output was triggerd.
+ // Signal the end.
+ signaling = 1;
+ reschedule = 0;
+ if (instance->status == ao_status_single_run) {
+ instance->status = ao_status_single_end;
+ }
+
+ } else if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout
+ PDEBUG("Timeout reached.\n");
+ spin_lock(instance->ao_shadows_lock);
+ // Restore old settings.
+ PDEBUG("Write old value back to register.\n");
+ (instance->ao_regs_shadows)->shadow[instance->ao_idx] =
+ (instance->ao_regs_shadows)->mirror[instance->ao_idx];
+
+ outw((instance->ao_regs_shadows)->mirror[instance->ao_idx],
+ (instance->ao_regs_shadows)->registry[instance->ao_idx]);
+ PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ (instance->ao_regs_shadows)->registry[instance->
+ ao_idx] -
+ instance->reg_base,
+ (instance->ao_regs_shadows)->mirror[instance->
+ ao_idx]);
+
+ //Remove from synchronous strt list.
+ (instance->ao_regs_shadows)->trigger &=
+ ~(0x1 << instance->ao_idx);
+ if (instance->status == ao_status_none) {
+ instance->status = ao_status_single_end;
+ }
+ spin_unlock(instance->ao_shadows_lock);
+
+ // Signal the end.
+ signaling = 1;
+ reschedule = 0;
+ }
+
+ if (signaling) { //Signal it.
+ wake_up_interruptible_all(&instance->wait_queue);
+ }
+
+ if (instance->ao_control_task_flag && reschedule) { // Reschedule task
+ queue_delayed_work(instance->me1600_workqueue,
+ &instance->ao_control_task, 1);
+ } else {
+ PINFO("<%s> Ending control task.\n", __func__);
+ }
+
+}
diff --git a/drivers/staging/meilhaus/me1600_ao.h b/drivers/staging/meilhaus/me1600_ao.h
new file mode 100644
index 000000000000..b82bf5a1676e
--- /dev/null
+++ b/drivers/staging/meilhaus/me1600_ao.h
@@ -0,0 +1,132 @@
+/**
+ * @file me1600_ao.h
+ *
+ * @brief Meilhaus ME-1600 analog output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1600_AO_H_
+#define _ME1600_AO_H_
+
+# include <linux/version.h>
+# include "mesubdevice.h"
+
+# ifdef __KERNEL__
+
+# define ME1600_MAX_RANGES 2 /**< Specifies the maximum number of ranges in me1600_ao_subdevice_t::u_ranges und me1600_ao_subdevice_t::i_ranges. */
+
+/**
+ * @brief Defines a entry in the range table.
+ */
+typedef struct me1600_ao_range_entry {
+ int32_t min;
+ int32_t max;
+} me1600_ao_range_entry_t;
+
+typedef struct me1600_ao_timeout {
+ unsigned long start_time;
+ unsigned long delay;
+} me1600_ao_timeout_t;
+
+typedef struct me1600_ao_shadow {
+ int count;
+ unsigned long *registry;
+ uint16_t *shadow;
+ uint16_t *mirror;
+ uint16_t synchronous; /**< Synchronization list. */
+ uint16_t trigger; /**< Synchronization flag. */
+} me1600_ao_shadow_t;
+
+typedef enum ME1600_AO_STATUS {
+ ao_status_none = 0,
+ ao_status_single_configured,
+ ao_status_single_run,
+ ao_status_single_end,
+ ao_status_last
+} ME1600_AO_STATUS;
+
+/**
+ * @brief The ME-1600 analog output subdevice class.
+ */
+typedef struct me1600_ao_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ int ao_idx; /**< The index of the analog output subdevice on the device. */
+
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *config_regs_lock; /**< Spin lock to protect configuration registers from concurrent access. */
+
+ int u_ranges_count; /**< The number of voltage ranges available on this subdevice. */
+ me1600_ao_range_entry_t u_ranges[ME1600_MAX_RANGES]; /**< Array holding the voltage ranges on this subdevice. */
+ int i_ranges_count; /**< The number of current ranges available on this subdevice. */
+ me1600_ao_range_entry_t i_ranges[ME1600_MAX_RANGES]; /**< Array holding the current ranges on this subdevice. */
+
+ /* Registers */
+ unsigned long uni_bi_reg; /**< Register for switching between unipoar and bipolar output mode. */
+ unsigned long i_range_reg; /**< Register for switching between ranges. */
+ unsigned long sim_output_reg; /**< Register used in order to update all channels simultaneously. */
+ unsigned long current_on_reg; /**< Register enabling current output on the fourth subdevice. */
+# ifdef PDEBUG_REG
+ unsigned long reg_base;
+# endif
+
+ ME1600_AO_STATUS status;
+ me1600_ao_shadow_t *ao_regs_shadows; /**< Addresses and shadows of output's registers. */
+ spinlock_t *ao_shadows_lock; /**< Protects the shadow's struct. */
+ int mode; /**< Mode in witch output should works. */
+ wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */
+ me1600_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */
+ struct workqueue_struct *me1600_workqueue;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ struct work_struct ao_control_task;
+#else
+ struct delayed_work ao_control_task;
+#endif
+
+ volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */
+} me1600_ao_subdevice_t;
+
+/**
+ * @brief The constructor to generate a subdevice template instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param ao_idx The index of the analog output subdevice on the device.
+ * @param current Flag indicating that analog output with #ao_idx of 3 is capable of current output.
+ * @param config_regs_lock Pointer to spin lock protecting the configuration registers and from concurrent access.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base,
+ unsigned int ao_idx,
+ int curr,
+ spinlock_t * config_regs_lock,
+ spinlock_t * ao_shadows_lock,
+ me1600_ao_shadow_t *
+ ao_regs_shadows,
+ struct workqueue_struct
+ *me1600_wq);
+
+# endif //__KERNEL__
+#endif //_ME1600_AO_H_
diff --git a/drivers/staging/meilhaus/me1600_ao_reg.h b/drivers/staging/meilhaus/me1600_ao_reg.h
new file mode 100644
index 000000000000..31e7800e8074
--- /dev/null
+++ b/drivers/staging/meilhaus/me1600_ao_reg.h
@@ -0,0 +1,66 @@
+/**
+ * @file me1600_ao_reg.h
+ *
+ * @brief ME-1600 analog output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1600_AO_REG_H_
+#define _ME1600_AO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME1600_CHANNEL_0_REG 0x00 /**< Register to set a digital value on channel 0. */
+#define ME1600_CHANNEL_1_REG 0x02 /**< Register to set a digital value on channel 1. */
+#define ME1600_CHANNEL_2_REG 0x04 /**< Register to set a digital value on channel 2. */
+#define ME1600_CHANNEL_3_REG 0x06 /**< Register to set a digital value on channel 3. */
+#define ME1600_CHANNEL_4_REG 0x08 /**< Register to set a digital value on channel 4. */
+#define ME1600_CHANNEL_5_REG 0x0A /**< Register to set a digital value on channel 5. */
+#define ME1600_CHANNEL_6_REG 0x0C /**< Register to set a digital value on channel 6. */
+#define ME1600_CHANNEL_7_REG 0x0E /**< Register to set a digital value on channel 7. */
+#define ME1600_CHANNEL_8_REG 0x10 /**< Register to set a digital value on channel 8. */
+#define ME1600_CHANNEL_9_REG 0x12 /**< Register to set a digital value on channel 9. */
+#define ME1600_CHANNEL_10_REG 0x14 /**< Register to set a digital value on channel 10. */
+#define ME1600_CHANNEL_11_REG 0x16 /**< Register to set a digital value on channel 11. */
+#define ME1600_CHANNEL_12_REG 0x18 /**< Register to set a digital value on channel 12. */
+#define ME1600_CHANNEL_13_REG 0x1A /**< Register to set a digital value on channel 13. */
+#define ME1600_CHANNEL_14_REG 0x1C /**< Register to set a digital value on channel 14. */
+#define ME1600_CHANNEL_15_REG 0x1E /**< Register to set a digital value on channel 15. */
+
+/* Every channel one bit: bipolar = 0, unipolar = 1 */
+#define ME1600_UNI_BI_REG 0x20 /**< Register to switch between unipolar and bipolar. */
+
+/* Every channel one bit (only lower 8 Bits): 0..20mA = 0, 4..20mA = 1 */
+#define ME1600_020_420_REG 0x22 /**< Register to switch between the two current ranges. */
+
+/* If a bit is set, the corresponding DAC (4 ports each) is
+ not set at the moment you write to an output of it.
+ Clearing the bit updates the port. */
+#define ME1600_SIM_OUTPUT_REG 0x24 /**< Register to update all channels of a subdevice simultaneously. */
+
+/* Current on/off (only lower 8 bits): off = 0, on = 1 */
+#define ME1600_CURRENT_ON_REG 0x26 /**< Register to swicht between voltage and current output. */
+
+#define ME1600_AO_MAX_DATA 0x0FFF /**< The maximum digital data accepted by an analog output channel. */
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me1600_device.c b/drivers/staging/meilhaus/me1600_device.c
new file mode 100644
index 000000000000..3bc2cb1dc869
--- /dev/null
+++ b/drivers/staging/meilhaus/me1600_device.c
@@ -0,0 +1,261 @@
+/**
+ * @file me1600_device.c
+ *
+ * @brief ME-1600 device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "medevice.h"
+#include "mesubdevice.h"
+#include "me1600_device.h"
+
+static void me1600_set_registry(me1600_device_t * subdevice, uint32_t reg_base);
+static void me1600_destructor(struct me_device *device);
+
+/**
+ * @brief Global variable.
+ * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts).
+ */
+static struct workqueue_struct *me1600_workqueue;
+
+me_device_t *me1600_pci_constructor(struct pci_dev *pci_device)
+{
+ int err;
+ me1600_device_t *me1600_device;
+ me_subdevice_t *subdevice;
+ unsigned int chip_idx;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me1600_device = kmalloc(sizeof(me1600_device_t), GFP_KERNEL);
+
+ if (!me1600_device) {
+ PERROR("Cannot get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(me1600_device, 0, sizeof(me1600_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me1600_device, pci_device);
+
+ if (err) {
+ kfree(me1600_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+ // Initialize spin lock .
+ spin_lock_init(&me1600_device->config_regs_lock);
+ spin_lock_init(&me1600_device->ao_shadows_lock);
+
+ // Get the number of analog output subdevices.
+ chip_idx =
+ me1600_versions_get_device_index(me1600_device->base.info.pci.
+ device_id);
+
+ // Create shadow instance.
+ me1600_device->ao_regs_shadows.count =
+ me1600_versions[chip_idx].ao_chips;
+ me1600_device->ao_regs_shadows.registry =
+ kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(unsigned long),
+ GFP_KERNEL);
+ me1600_set_registry(me1600_device,
+ me1600_device->base.info.pci.reg_bases[2]);
+ me1600_device->ao_regs_shadows.shadow =
+ kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(uint16_t),
+ GFP_KERNEL);
+ me1600_device->ao_regs_shadows.mirror =
+ kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(uint16_t),
+ GFP_KERNEL);
+
+ // Create subdevice instances.
+ for (i = 0; i < me1600_versions[chip_idx].ao_chips; i++) {
+ subdevice =
+ (me_subdevice_t *) me1600_ao_constructor(me1600_device->
+ base.info.pci.
+ reg_bases[2], i,
+ ((me1600_versions
+ [chip_idx].curr >
+ i) ? 1 : 0),
+ &me1600_device->
+ config_regs_lock,
+ &me1600_device->
+ ao_shadows_lock,
+ &me1600_device->
+ ao_regs_shadows,
+ me1600_workqueue);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me1600_device);
+ kfree(me1600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me1600_device->base.slist,
+ subdevice);
+ }
+
+ // Overwrite base class methods.
+ me1600_device->base.me_device_destructor = me1600_destructor;
+
+ return (me_device_t *) me1600_device;
+}
+
+static void me1600_destructor(struct me_device *device)
+{
+ me1600_device_t *me1600_device = (me1600_device_t *) device;
+ PDEBUG("executed.\n");
+
+ // Destroy shadow instance.
+ kfree(me1600_device->ao_regs_shadows.registry);
+ kfree(me1600_device->ao_regs_shadows.shadow);
+ kfree(me1600_device->ao_regs_shadows.mirror);
+
+ me_device_deinit((me_device_t *) me1600_device);
+ kfree(me1600_device);
+}
+
+static void me1600_set_registry(me1600_device_t * subdevice, uint32_t reg_base)
+{ // Create shadow structure.
+ if (subdevice->ao_regs_shadows.count >= 1) {
+ subdevice->ao_regs_shadows.registry[0] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_0_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 2) {
+ subdevice->ao_regs_shadows.registry[1] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_1_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 3) {
+ subdevice->ao_regs_shadows.registry[2] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_2_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 4) {
+ subdevice->ao_regs_shadows.registry[3] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_3_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 5) {
+ subdevice->ao_regs_shadows.registry[4] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_4_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 6) {
+ subdevice->ao_regs_shadows.registry[5] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_5_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 7) {
+ subdevice->ao_regs_shadows.registry[6] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_6_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 8) {
+ subdevice->ao_regs_shadows.registry[7] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_7_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 9) {
+ subdevice->ao_regs_shadows.registry[8] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_8_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 10) {
+ subdevice->ao_regs_shadows.registry[9] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_9_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 11) {
+ subdevice->ao_regs_shadows.registry[10] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_10_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 12) {
+ subdevice->ao_regs_shadows.registry[11] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_11_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 13) {
+ subdevice->ao_regs_shadows.registry[12] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_12_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 14) {
+ subdevice->ao_regs_shadows.registry[13] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_13_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 15) {
+ subdevice->ao_regs_shadows.registry[14] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_14_REG);
+ }
+ if (subdevice->ao_regs_shadows.count >= 16) {
+ subdevice->ao_regs_shadows.registry[15] =
+ (unsigned long)(reg_base + ME1600_CHANNEL_15_REG);
+ }
+ if (subdevice->ao_regs_shadows.count > 16) {
+ PERROR("More than 16 outputs! (%d)\n",
+ subdevice->ao_regs_shadows.count);
+ }
+}
+
+// Init and exit of module.
+
+static int __init me1600_init(void)
+{
+ PDEBUG("executed\n.");
+
+ me1600_workqueue = create_singlethread_workqueue("me1600");
+ return 0;
+}
+
+static void __exit me1600_exit(void)
+{
+ PDEBUG("executed\n.");
+
+ flush_workqueue(me1600_workqueue);
+ destroy_workqueue(me1600_workqueue);
+}
+
+module_init(me1600_init);
+module_exit(me1600_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for ME-1600 Device");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-1600 Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me1600_pci_constructor);
diff --git a/drivers/staging/meilhaus/me1600_device.h b/drivers/staging/meilhaus/me1600_device.h
new file mode 100644
index 000000000000..f7b231f73ac8
--- /dev/null
+++ b/drivers/staging/meilhaus/me1600_device.h
@@ -0,0 +1,101 @@
+/**
+ * @file me1600_device.h
+ *
+ * @brief ME-1600 device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME1600_H
+#define _ME1600_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+#include "me1600_ao.h"
+#include "me1600_ao_reg.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure to store device capabilities.
+ */
+typedef struct me1600_version {
+ uint16_t device_id; /**< The PCI device id of the device. */
+ unsigned int ao_chips; /**< The number of analog outputs on the device. */
+ int curr; /**< Flag to identify amounts of current output. */
+} me1600_version_t;
+
+/**
+ * @brief Defines for each ME-1600 device version its capabilities.
+ */
+static me1600_version_t me1600_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME1600_4U, 4, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME1600_8U, 8, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME1600_12U, 12, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME1600_16U, 16, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I, 16, 8},
+ {0}
+};
+
+/**< Returns the number of entries in #me1600_versions. */
+#define ME1600_DEVICE_VERSIONS (sizeof(me1600_versions) / sizeof(me1600_version_t) - 1)
+
+/**
+ * @brief Returns the index of the device entry in #me1600_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me1600_versions.
+ */
+static inline unsigned int me1600_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME1600_DEVICE_VERSIONS; i++)
+ if (me1600_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The ME-1600 device class structure.
+ */
+typedef struct me1600_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+ spinlock_t config_regs_lock; /**< Protects the configuration registers. */
+
+ me1600_ao_shadow_t ao_regs_shadows; /**< Addresses and shadows of output's registers. */
+ spinlock_t ao_shadows_lock; /**< Protects the shadow's struct. */
+} me1600_device_t;
+
+/**
+ * @brief The ME-1600 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-1600 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me1600_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_ai.c b/drivers/staging/meilhaus/me4600_ai.c
new file mode 100644
index 000000000000..0a8c9d737e90
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ai.c
@@ -0,0 +1,3434 @@
+/**
+ * @file me4600_ai.c
+ *
+ * @brief ME-4000 analog input subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+#include "medebug.h"
+#include "meids.h"
+
+#include "me4600_reg.h"
+#include "me4600_ai_reg.h"
+#include "me4600_ai.h"
+
+/*
+ * Declarations (local)
+ */
+
+static void me4600_ai_destructor(struct me_subdevice *subdevice);
+static int me4600_ai_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags);
+
+static int me4600_ai_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags);
+
+static int me4600_ai_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags);
+
+static int me4600_ai_io_stream_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags);
+static int me4600_ai_io_stream_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int read_mode,
+ int *values, int *count, int flags);
+static int me4600_ai_io_stream_new_values(me_subdevice_t * subdevice,
+ struct file *filep,
+ int time_out, int *count, int flags);
+static int inline me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t *
+ instance, int *values,
+ const int count,
+ const int flags);
+
+static int me4600_ai_io_stream_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags);
+static int me4600_ai_io_stream_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int stop_mode, int flags);
+static int me4600_ai_io_stream_status(me_subdevice_t * subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *values, int flags);
+
+static int me4600_ai_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range);
+static int me4600_ai_query_number_ranges(me_subdevice_t * subdevice,
+ int unit, int *count);
+static int me4600_ai_query_range_info(me_subdevice_t * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata);
+static int me4600_ai_query_timer(me_subdevice_t * subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks, long long *max_ticks);
+static int me4600_ai_query_number_channels(me_subdevice_t * subdevice,
+ int *number);
+static int me4600_ai_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype);
+static int me4600_ai_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps);
+static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice,
+ int cap, int *args, int count);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me4600_ai_isr(int irq, void *dev_id);
+#else
+static irqreturn_t me4600_ai_isr(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+
+static int ai_mux_toggler(me4600_ai_subdevice_t * subdevice);
+
+/** Immidiate stop.
+* Reset all IRQ's sources. (block laches)
+* Preserve FIFO
+*/
+static int ai_stop_immediately(me4600_ai_subdevice_t * instance);
+
+/** Immidiate stop.
+* Reset all IRQ's sources. (block laches)
+* Reset data FIFO
+*/
+void inline ai_stop_isr(me4600_ai_subdevice_t * instance);
+
+/** Interrupt logics.
+* Read datas
+* Reset latches
+*/
+void ai_limited_isr(me4600_ai_subdevice_t * instance, const uint32_t irq_status,
+ const uint32_t ctrl_status);
+void ai_infinite_isr(me4600_ai_subdevice_t * instance,
+ const uint32_t irq_status, const uint32_t ctrl_status);
+
+/** Last chunck of datas. We must reschedule sample counter.
+* Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts.
+* When threshold is wrongly set some IRQ are lost.(!!!)
+*/
+void inline ai_reschedule_SC(me4600_ai_subdevice_t * instance);
+
+/** Read datas from FIFO and copy them to buffer */
+static int inline ai_read_data(me4600_ai_subdevice_t * instance,
+ const int count);
+
+/** Copy rest of data from fifo to circular buffer.*/
+static int inline ai_read_data_pooling(me4600_ai_subdevice_t * instance);
+
+/** Set ISM to next state for infinite data aqusation mode*/
+void inline ai_infinite_ISM(me4600_ai_subdevice_t * instance);
+
+/** Set ISM to next state for define amount of data aqusation mode*/
+void inline ai_limited_ISM(me4600_ai_subdevice_t * instance,
+ uint32_t irq_status);
+
+/** Set ISM to next stage for limited mode */
+void inline ai_data_acquisition_logic(me4600_ai_subdevice_t * instance);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void me4600_ai_work_control_task(void *subdevice);
+#else
+static void me4600_ai_work_control_task(struct work_struct *work);
+#endif
+
+/* Definitions
+ */
+
+me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base,
+ unsigned int channels,
+ unsigned int ranges,
+ int isolated,
+ int sh,
+ int irq,
+ spinlock_t * ctrl_reg_lock,
+ struct workqueue_struct *me4600_wq)
+{
+ me4600_ai_subdevice_t *subdevice;
+ int err;
+ unsigned int i;
+
+ PDEBUG("executed. idx=0\n");
+
+ // Allocate memory for subdevice instance.
+ subdevice = kmalloc(sizeof(me4600_ai_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me4600_ai_subdevice_t));
+
+ // Initialize subdevice base class.
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ // Initialize circular buffer.
+ subdevice->circ_buf.mask = ME4600_AI_CIRC_BUF_COUNT - 1;
+
+ subdevice->circ_buf.buf =
+ (void *)__get_free_pages(GFP_KERNEL, ME4600_AI_CIRC_BUF_SIZE_ORDER);
+ PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf,
+ ME4600_AI_CIRC_BUF_SIZE);
+
+ if (!subdevice->circ_buf.buf) {
+ PERROR("Cannot get circular buffer.\n");
+ me_subdevice_deinit((me_subdevice_t *) subdevice);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ memset(subdevice->circ_buf.buf, 0, ME4600_AI_CIRC_BUF_SIZE);
+ subdevice->circ_buf.head = 0;
+ subdevice->circ_buf.tail = 0;
+ subdevice->status = ai_status_none;
+
+ // Initialize wait queue.
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ // Save the number of channels.
+ subdevice->channels = channels;
+
+ /* Initialize the single config entries to reset values */
+ for (i = 0; i < channels; i++) {
+ subdevice->single_config[i].status = ME_SINGLE_CHANNEL_NOT_CONFIGURED; //not configured
+ }
+
+ // Save if isolated device.
+ subdevice->isolated = isolated;
+
+ // Save if sample and hold is available.
+ subdevice->sh = sh;
+
+ // Set stream config to not configured state.
+ subdevice->fifo_irq_threshold = 0;
+ subdevice->data_required = 0;
+ subdevice->chan_list_len = 0;
+
+ // Initialize registers addresses.
+ subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AI_STATUS_REG;
+ subdevice->channel_list_reg = reg_base + ME4600_AI_CHANNEL_LIST_REG;
+ subdevice->data_reg = reg_base + ME4600_AI_DATA_REG;
+ subdevice->chan_timer_reg = reg_base + ME4600_AI_CHAN_TIMER_REG;
+ subdevice->chan_pre_timer_reg = reg_base + ME4600_AI_CHAN_PRE_TIMER_REG;
+ subdevice->scan_timer_low_reg = reg_base + ME4600_AI_SCAN_TIMER_LOW_REG;
+ subdevice->scan_timer_high_reg =
+ reg_base + ME4600_AI_SCAN_TIMER_HIGH_REG;
+ subdevice->scan_pre_timer_low_reg =
+ reg_base + ME4600_AI_SCAN_PRE_TIMER_LOW_REG;
+ subdevice->scan_pre_timer_high_reg =
+ reg_base + ME4600_AI_SCAN_PRE_TIMER_HIGH_REG;
+ subdevice->start_reg = reg_base + ME4600_AI_START_REG;
+ subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG;
+ subdevice->sample_counter_reg = reg_base + ME4600_AI_SAMPLE_COUNTER_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ // Initialize ranges.
+ subdevice->ranges_len = ranges;
+ subdevice->ranges[0].min = -10E6;
+ subdevice->ranges[0].max = 9999694;
+
+ subdevice->ranges[1].min = 0;
+ subdevice->ranges[1].max = 9999847;
+
+ subdevice->ranges[2].min = -25E5;
+ subdevice->ranges[2].max = 2499923;
+
+ subdevice->ranges[3].min = 0;
+ subdevice->ranges[3].max = 2499961;
+
+ // We have to switch the mux in order to get it work correctly.
+ ai_mux_toggler(subdevice);
+
+ // Register interrupt service routine.
+ subdevice->irq = irq;
+ if (request_irq(subdevice->irq, me4600_ai_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME4600_NAME, subdevice)) {
+ PERROR("Cannot register interrupt service routine.\n");
+ me_subdevice_deinit((me_subdevice_t *) subdevice);
+ free_pages((unsigned long)subdevice->circ_buf.buf,
+ ME4600_AI_CIRC_BUF_SIZE_ORDER);
+ subdevice->circ_buf.buf = NULL;
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", subdevice->irq);
+
+ // Override base class methods.
+ subdevice->base.me_subdevice_destructor = me4600_ai_destructor;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me4600_ai_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me4600_ai_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me4600_ai_io_single_read;
+ subdevice->base.me_subdevice_io_stream_config =
+ me4600_ai_io_stream_config;
+ subdevice->base.me_subdevice_io_stream_new_values =
+ me4600_ai_io_stream_new_values;
+ subdevice->base.me_subdevice_io_stream_read = me4600_ai_io_stream_read;
+ subdevice->base.me_subdevice_io_stream_start =
+ me4600_ai_io_stream_start;
+ subdevice->base.me_subdevice_io_stream_status =
+ me4600_ai_io_stream_status;
+ subdevice->base.me_subdevice_io_stream_stop = me4600_ai_io_stream_stop;
+ subdevice->base.me_subdevice_query_number_channels =
+ me4600_ai_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me4600_ai_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me4600_ai_query_subdevice_caps;
+ subdevice->base.me_subdevice_query_subdevice_caps_args =
+ me4600_ai_query_subdevice_caps_args;
+ subdevice->base.me_subdevice_query_range_by_min_max =
+ me4600_ai_query_range_by_min_max;
+ subdevice->base.me_subdevice_query_number_ranges =
+ me4600_ai_query_number_ranges;
+ subdevice->base.me_subdevice_query_range_info =
+ me4600_ai_query_range_info;
+ subdevice->base.me_subdevice_query_timer = me4600_ai_query_timer;
+
+ // Prepare work queue.
+ subdevice->me4600_workqueue = me4600_wq;
+
+/* workqueue API changed in kernel 2.6.20 */
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
+ INIT_WORK(&subdevice->ai_control_task, me4600_ai_work_control_task,
+ (void *)subdevice);
+#else
+ INIT_DELAYED_WORK(&subdevice->ai_control_task,
+ me4600_ai_work_control_task);
+#endif
+
+ return subdevice;
+}
+
+static void me4600_ai_destructor(struct me_subdevice *subdevice)
+{
+ me4600_ai_subdevice_t *instance;
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance->ai_control_task_flag = 0;
+ // Reset subdevice to asure clean exit.
+ me4600_ai_io_reset_subdevice(subdevice, NULL,
+ ME_IO_RESET_SUBDEVICE_NO_FLAGS);
+
+ // Remove any tasks from work queue. This is paranoic because it was done allready in reset().
+ if (!cancel_delayed_work(&instance->ai_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue.
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(2);
+ }
+
+ free_irq(instance->irq, instance);
+ free_pages((unsigned long)instance->circ_buf.buf,
+ ME4600_AI_CIRC_BUF_SIZE_ORDER);
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+static int me4600_ai_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ volatile uint32_t ctrl;
+ unsigned long status;
+ const int timeout = HZ / 10; //100ms
+ int i;
+
+ PDEBUG("executed. idx=0\n");
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ instance->ai_control_task_flag = 0;
+ instance->status = ai_status_none;
+
+ for (i = 0; i <= timeout; i++) {
+ spin_lock_irqsave(instance->ctrl_reg_lock, status);
+ ctrl = inl(instance->ctrl_reg);
+ //Stop DMA
+ ctrl &= ~ME4600_AI_CTRL_RPCI_FIFO;
+ // Stop all actions. No conditions!
+ ctrl &= ~ME4600_AI_CTRL_BIT_STOP;
+ ctrl |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP;
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, status);
+
+ if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM))
+ break;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ if (i > timeout) {
+ PERROR("FSM is still busy.\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+
+ spin_lock_irqsave(instance->ctrl_reg_lock, status);
+ ctrl = inl(instance->ctrl_reg);
+ // Clear all features. Dissable interrupts.
+ ctrl &= ~(ME4600_AI_CTRL_BIT_STOP
+ | ME4600_AI_CTRL_BIT_LE_IRQ
+ | ME4600_AI_CTRL_BIT_HF_IRQ | ME4600_AI_CTRL_BIT_SC_IRQ);
+ ctrl |= (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP
+ | ME4600_AI_CTRL_BIT_LE_IRQ_RESET
+ | ME4600_AI_CTRL_BIT_HF_IRQ_RESET
+ | ME4600_AI_CTRL_BIT_SC_IRQ_RESET);
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, status);
+
+ outl(ME4600_AI_MIN_CHAN_TICKS - 1, instance->chan_timer_reg);
+ PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llx\n",
+ instance->reg_base,
+ instance->chan_timer_reg - instance->reg_base,
+ ME4600_AI_MIN_CHAN_TICKS);
+ outl(ME4600_AI_MIN_ACQ_TICKS - 1, instance->chan_pre_timer_reg);
+ PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llx\n",
+ instance->reg_base,
+ instance->chan_pre_timer_reg - instance->reg_base,
+ ME4600_AI_MIN_ACQ_TICKS);
+ outl(0, instance->scan_timer_low_reg);
+ PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_low_reg - instance->reg_base, 0);
+ outl(0, instance->scan_timer_high_reg);
+ PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_high_reg - instance->reg_base, 0);
+ outl(0, instance->scan_pre_timer_low_reg);
+ PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_pre_timer_low_reg - instance->reg_base, 0);
+ outl(0, instance->scan_pre_timer_high_reg);
+ PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_pre_timer_high_reg - instance->reg_base, 0);
+ outl(0xEFFFFFFF, instance->sample_counter_reg);
+ PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sample_counter_reg - instance->reg_base,
+ 0xEFFFFFFF);
+
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+
+ instance->fifo_irq_threshold = 0;
+ instance->data_required = 0;
+ instance->chan_list_len = 0;
+
+ // Initialize the single config entries to reset values.
+ for (i = 0; i < instance->channels; i++) {
+ instance->single_config[i].status =
+ ME_SINGLE_CHANNEL_NOT_CONFIGURED;
+ }
+ instance->status = ai_status_none;
+
+ //Signal reset if user is on wait.
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ai_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags;
+ int i;
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=0\n");
+
+ if (flags & ~ME_IO_SINGLE_CONFIG_CONTINUE) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ switch (trig_type) {
+ case ME_TRIG_TYPE_SW:
+ if (trig_edge != ME_TRIG_EDGE_NONE) {
+ PERROR
+ ("Invalid trigger edge. Software trigger has not edge.\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ if (instance->channels <= 16) //Only versions with 32 channels have analog trigger (4670 and 4680)
+ {
+ PERROR("Invalid trigger type specified.\n");
+ return ME_ERRNO_INVALID_TRIG_TYPE;
+ }
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ if ((trig_edge != ME_TRIG_EDGE_ANY)
+ && (trig_edge != ME_TRIG_EDGE_RISING)
+ && (trig_edge != ME_TRIG_EDGE_FALLING)) {
+ PERROR("Invalid trigger edge specified.\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+ break;
+
+ default:
+ PERROR("Invalid trigger type specified.\n");
+ return ME_ERRNO_INVALID_TRIG_TYPE;
+ }
+
+ if (trig_chan != ME_TRIG_CHAN_DEFAULT) {
+ PERROR("Invalid trigger channel specified.\n");
+ return ME_ERRNO_INVALID_TRIG_CHAN;
+ }
+
+ if ((single_config < 0) || (single_config >= instance->ranges_len)) {
+ PERROR("Invalid single config specified.\n");
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+
+ if ((ref != ME_REF_AI_GROUND) && (ref != ME_REF_AI_DIFFERENTIAL)) {
+ PERROR("Invalid analog reference specified.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if ((single_config % 2) && (ref != ME_REF_AI_GROUND)) {
+ PERROR("Invalid analog reference specified.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if ((ref == ME_REF_AI_DIFFERENTIAL)
+ && ((instance->channels == 16) || (channel >= 16))) {
+ PERROR("Invalid analog reference specified.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if (channel < 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (channel >= instance->channels) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ //Prepare data entry.
+ // Common for all modes.
+ instance->single_config[channel].entry =
+ channel | ME4600_AI_LIST_LAST_ENTRY;
+
+ if (ref == ME_REF_AI_DIFFERENTIAL) { // ME_REF_AI_DIFFERENTIAL
+ instance->single_config[channel].entry |=
+ ME4600_AI_LIST_INPUT_DIFFERENTIAL;
+ }
+/*
+ // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000
+ // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' <== Do nothing. Removed.
+ else
+ {// ME_REF_AI_GROUND
+ instance->single_config[channel].entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED;
+ }
+*/
+ switch (single_config) {
+ case 0: //-10V..10V
+/*
+ // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000
+ // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed.
+ instance->single_config[channel].entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10;
+*/ break;
+
+ case 1: //0V..10V
+ instance->single_config[channel].entry |=
+ ME4600_AI_LIST_RANGE_UNIPOLAR_10;
+ break;
+
+ case 2: //-2.5V..2.5V
+ instance->single_config[channel].entry |=
+ ME4600_AI_LIST_RANGE_BIPOLAR_2_5;
+ break;
+
+ case 3: //0V..2.5V
+ instance->single_config[channel].entry |=
+ ME4600_AI_LIST_RANGE_UNIPOLAR_2_5;
+ break;
+ }
+
+ // Prepare control register.
+ // Common for all modes.
+ instance->single_config[channel].ctrl =
+ ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO;
+
+ switch (trig_type) {
+ case ME_TRIG_TYPE_SW:
+ // Nothing to set.
+ break;
+
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ instance->single_config[channel].ctrl |=
+ ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ instance->single_config[channel].ctrl |=
+ ME4600_AI_CTRL_BIT_EX_TRIG;
+ break;
+ }
+
+ switch (trig_edge) {
+ case ME_TRIG_EDGE_RISING:
+ // Nothing to set.
+ break;
+
+ case ME_TRIG_EDGE_ANY:
+ instance->single_config[channel].ctrl |=
+ ME4600_AI_CTRL_BIT_EX_TRIG_BOTH;
+
+ case ME_TRIG_EDGE_FALLING:
+ instance->single_config[channel].ctrl |=
+ ME4600_AI_CTRL_BIT_EX_TRIG_FALLING;
+ break;
+ }
+
+ // Enable this channel
+ instance->single_config[channel].status = ME_SINGLE_CHANNEL_CONFIGURED;
+
+ // Copy this settings to other outputs.
+ if (flags == ME_IO_SINGLE_CONFIG_CONTINUE) {
+ for (i = channel + 1; i < instance->channels; i++) {
+ instance->single_config[i].ctrl =
+ instance->single_config[channel].ctrl;
+ instance->single_config[i].entry =
+ instance->single_config[channel].entry;
+ instance->single_config[i].status =
+ ME_SINGLE_CHANNEL_CONFIGURED;
+ }
+ }
+
+ instance->status = ai_status_single_configured;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ai_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ volatile uint32_t tmp;
+ volatile uint32_t val;
+ unsigned long cpu_flags;
+ int err = ME_ERRNO_SUCCESS;
+
+ unsigned long j;
+ unsigned long delay = 0;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (instance->status != ai_status_single_configured) {
+ PERROR("Subdevice not configured to work in single mode!\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ if ((channel > instance->channels) || (channel < 0)) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (instance->single_config[channel].status !=
+ ME_SINGLE_CHANNEL_CONFIGURED) {
+ PERROR("Channel is not configured to work in single mode!\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) {
+ PERROR("Subdevice is busy.\n");
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ // Cancel control task
+ PDEBUG("Cancel control task.\n");
+ instance->ai_control_task_flag = 0;
+ cancel_delayed_work(&instance->ai_control_task);
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+
+ if (delay == 0)
+ delay = 1;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ // Mark that StreamConfig is removed.
+ instance->chan_list_len = 0;
+
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ /// @note Imprtant: Preserve EXT IRQ settings.
+ tmp = inl(instance->ctrl_reg);
+ // Clear FIFOs and dissable interrupts
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO);
+
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ |
+ ME4600_AI_CTRL_BIT_LE_IRQ);
+ tmp |=
+ ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_LE_IRQ_RESET;
+
+ tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ outl(0, instance->scan_pre_timer_low_reg);
+ PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_pre_timer_low_reg - instance->reg_base, 0);
+ outl(0, instance->scan_pre_timer_high_reg);
+ PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_pre_timer_high_reg - instance->reg_base, 0);
+ outl(0, instance->scan_timer_low_reg);
+ PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_low_reg - instance->reg_base, 0);
+ outl(0, instance->scan_timer_high_reg);
+ PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_high_reg - instance->reg_base, 0);
+ outl(65, instance->chan_timer_reg);
+ PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->chan_timer_reg - instance->reg_base, 65);
+ outl(65, instance->chan_pre_timer_reg);
+ PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->chan_pre_timer_reg - instance->reg_base, 65);
+
+ //Reactive FIFOs. Enable work.
+ tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ outl(instance->single_config[channel].entry,
+ instance->channel_list_reg);
+ PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->channel_list_reg - instance->reg_base,
+ instance->single_config[channel].entry);
+
+ // Preserve EXT IRQ settings.
+ tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
+ outl(instance->single_config[channel].ctrl | tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ instance->single_config[channel].ctrl | tmp);
+
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+
+ if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start
+ inl(instance->start_reg);
+ PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base,
+ instance->start_reg - instance->reg_base);
+
+ delay = 2;
+ }
+
+ j = jiffies;
+
+ while (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) {
+ if (delay && ((jiffies - j) >= delay)) {
+ if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start.
+ PERROR("Value not available after wait.\n");
+ err = ME_ERRNO_INTERNAL;
+ } else { // External start.
+ PERROR("Timeout reached.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ break;
+ }
+ // Wait
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on external trigger interrupted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ break;
+ }
+
+ if (instance->status != ai_status_single_configured) {
+ PERROR("Wait interrupted by reset.\n");
+ err = ME_ERRNO_CANCELLED;
+ break;
+ }
+ }
+
+ // Read value.
+ if (!err) {
+ val = inl(instance->data_reg) ^ 0x8000;
+ PDEBUG_REG("data_reg inl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->data_reg - instance->reg_base, val);
+ *value = val & ME4600_AI_MAX_DATA;
+ } else {
+ *value = 0xFFFFFFFF;
+ }
+
+ // Restore settings.
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ tmp = inl(instance->ctrl_reg);
+ // Clear FIFOs and dissable interrupts.
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO);
+ tmp |= ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ;
+ tmp |=
+ ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ai_io_stream_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ int i; // internal multipurpose variable
+ unsigned long long data_required;
+
+ volatile uint32_t entry;
+ volatile uint32_t ctrl = ME4600_AI_CTRL_BIT_IMMEDIATE_STOP;
+ volatile uint32_t tmp; // use when current copy of register's value needed
+ unsigned long cpu_flags;
+
+ uint64_t acq_ticks;
+ uint64_t scan_ticks;
+ uint64_t conv_ticks;
+ unsigned int acq_start_ticks_low = trigger->iAcqStartTicksLow;
+ unsigned int acq_start_ticks_high = trigger->iAcqStartTicksHigh;
+ unsigned int scan_start_ticks_low = trigger->iScanStartTicksLow;
+ unsigned int scan_start_ticks_high = trigger->iScanStartTicksHigh;
+ unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow;
+ unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER
+ // Convert ticks to 64 bit long values
+ acq_ticks =
+ (uint64_t) acq_start_ticks_low +
+ ((uint64_t) acq_start_ticks_high << 32);
+ scan_ticks =
+ (uint64_t) scan_start_ticks_low +
+ ((uint64_t) scan_start_ticks_high << 32);
+ conv_ticks =
+ (uint64_t) conv_start_ticks_low +
+ ((uint64_t) conv_start_ticks_high << 32);
+
+ // Check settings - begin
+ switch (trigger->iAcqStartTrigType) {
+ case ME_TRIG_TYPE_SW:
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ break;
+
+ default:
+ PERROR("Invalid acquisition start trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE;
+ goto ERROR;
+ break;
+ }
+
+ if ((trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW)
+ && (trigger->iAcqStartTrigEdge != ME_TRIG_EDGE_NONE)) {
+ PERROR("Invalid acquisition start trigger edge specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+ goto ERROR;
+ }
+
+ if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_SW) {
+ switch (trigger->iAcqStartTrigEdge) {
+ case ME_TRIG_EDGE_RISING:
+ case ME_TRIG_EDGE_FALLING:
+ case ME_TRIG_EDGE_ANY:
+ break;
+
+ default:
+ PERROR
+ ("Invalid acquisition start trigger edge specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+ goto ERROR;
+ break;
+ }
+ }
+
+ if (trigger->iAcqStartTrigChan != ME_TRIG_CHAN_DEFAULT) {
+ PERROR
+ ("Invalid acquisition start trigger channel specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN;
+ goto ERROR;
+ }
+
+ if ((acq_ticks < ME4600_AI_MIN_ACQ_TICKS)
+ || (acq_ticks > ME4600_AI_MAX_ACQ_TICKS)) {
+ PERROR
+ ("Invalid acquisition start trigger argument specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_START_ARG;
+ goto ERROR;
+ }
+
+ switch (trigger->iScanStartTrigType) {
+
+ case ME_TRIG_TYPE_TIMER:
+ if ((scan_ticks < ME4600_AI_MIN_SCAN_TICKS)
+ || (scan_ticks > ME4600_AI_MAX_SCAN_TICKS)
+ || (scan_ticks < count * conv_ticks)
+ ) {
+ PERROR("Invalid scan start argument specified.\n");
+ err = ME_ERRNO_INVALID_SCAN_START_ARG;
+ goto ERROR;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_DIGITAL) {
+ PERROR
+ ("Invalid scan start trigger type specified (Acq is HW digital)\n");
+ err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE;
+ goto ERROR;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_ANALOG) {
+ PERROR
+ ("Invalid scan start trigger type specified (Acq is HW analog)\n");
+ err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE;
+ goto ERROR;
+ }
+ break;
+
+ case ME_TRIG_TYPE_FOLLOW:
+ break;
+
+ default:
+ PERROR("Invalid scan start trigger type specified.\n");
+ err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE;
+ goto ERROR;
+ break;
+ }
+
+ switch (trigger->iConvStartTrigType) {
+
+ case ME_TRIG_TYPE_TIMER:
+ if ((conv_ticks < ME4600_AI_MIN_CHAN_TICKS)
+ || (conv_ticks > ME4600_AI_MAX_CHAN_TICKS)) {
+ PERROR
+ ("Invalid conv start trigger argument specified.\n");
+ err = ME_ERRNO_INVALID_CONV_START_ARG;
+ goto ERROR;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW)
+ || (trigger->iAcqStartTrigType !=
+ ME_TRIG_TYPE_EXT_DIGITAL)) {
+ PERROR("Invalid conv start trigger type specified.\n");
+ err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE;
+ goto ERROR;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW)
+ || (trigger->iAcqStartTrigType !=
+ ME_TRIG_TYPE_EXT_ANALOG)) {
+ PERROR("Invalid conv start trigger type specified.\n");
+ err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE;
+ goto ERROR;
+ }
+ break;
+
+ default:
+ PERROR("Invalid conv start trigger type specified.\n");
+ err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE;
+ goto ERROR;
+
+ break;
+ }
+/**
+* Aceptable settings:
+* iScanStopTrigType : iAcqStopTrigType
+*
+* ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_NONE -> infinite count with manual stop
+* ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_COUNT -> stop after getting iScanStopCount list of values (iScanStopCount * count)
+* ME_TRIG_TYPE_COUNT : ME_TRIG_TYPE_FOLLOW -> stop after getting iAcqStopCount values (it can stops in midle of the list)
+*/
+ switch (trigger->iScanStopTrigType) {
+
+ case ME_TRIG_TYPE_NONE:
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (trigger->iScanStopCount <= 0) {
+ PERROR("Invalid scan stop argument specified.\n");
+ err = ME_ERRNO_INVALID_SCAN_STOP_ARG;
+ goto ERROR;
+ }
+ break;
+
+ default:
+ PERROR("Invalid scan stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE;
+ goto ERROR;
+ break;
+ }
+
+ switch (trigger->iAcqStopTrigType) {
+
+ case ME_TRIG_TYPE_NONE:
+ if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) {
+ PERROR("Invalid acq stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ }
+ break;
+
+ case ME_TRIG_TYPE_FOLLOW:
+ if (trigger->iScanStopTrigType != ME_TRIG_TYPE_COUNT) {
+ PERROR("Invalid acq stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ }
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) {
+ PERROR("Invalid acq stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ }
+
+ if (trigger->iAcqStopCount <= 0) {
+ PERROR
+ ("Invalid acquisition or scan stop argument specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_ARG;
+ goto ERROR;
+ }
+ break;
+
+ default:
+ PERROR("Invalid acq stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ break;
+ }
+
+ if ((count <= 0) || (count > ME4600_AI_LIST_COUNT)) {
+ PERROR("Invalid channel list count specified.\n");
+ err = ME_ERRNO_INVALID_CONFIG_LIST_COUNT;
+ goto ERROR;
+ }
+///This is general limitation
+// if (fifo_irq_threshold < 0 || fifo_irq_threshold >= ME4600_AI_CIRC_BUF_COUNT)
+///This is limitation from Windows. I use it for compatibility.
+ if (fifo_irq_threshold < 0
+ || fifo_irq_threshold >= ME4600_AI_FIFO_COUNT) {
+ PERROR("Invalid fifo irq threshold specified.\n");
+ err = ME_ERRNO_INVALID_FIFO_IRQ_THRESHOLD;
+ goto ERROR;
+ }
+
+ if ((config_list[0].iRef == ME_REF_AI_DIFFERENTIAL)
+ && (instance->channels == 16)) {
+ PERROR
+ ("Differential reference is not available on this subdevice.\n");
+ err = ME_ERRNO_INVALID_REF;
+ goto ERROR;
+ }
+
+ if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) {
+ if (!instance->sh) {
+ PERROR
+ ("Sample and hold is not available for this board.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ goto ERROR;
+ }
+ if (config_list[0].iRef == ME_REF_AI_DIFFERENTIAL) {
+ PERROR
+ ("Sample and hold is not available in differential mode.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ goto ERROR;
+ }
+ }
+
+ for (i = 0; i < count; i++) {
+ if ((config_list[i].iStreamConfig < 0)
+ || (config_list[i].iStreamConfig >= instance->ranges_len)) {
+ PERROR("Invalid stream config specified.\n");
+ err = ME_ERRNO_INVALID_STREAM_CONFIG;
+ goto ERROR;
+ }
+
+ if ((config_list[i].iRef != ME_REF_AI_GROUND)
+ && (config_list[i].iRef != ME_REF_AI_DIFFERENTIAL)) {
+ PERROR("Invalid references in the list. Ref=0x%x\n",
+ config_list[i].iRef);
+ err = ME_ERRNO_INVALID_REF;
+ goto ERROR;
+ }
+
+ if (config_list[i].iStreamConfig % 2) { // StreamConfig: 1 or 3
+ if (config_list[i].iRef == ME_REF_AI_DIFFERENTIAL) {
+ PERROR
+ ("Only bipolar modes support differential measurement.\n");
+ err = ME_ERRNO_INVALID_REF;
+ goto ERROR;
+ }
+ }
+
+ if (config_list[i].iRef != config_list[0].iRef) {
+ PERROR
+ ("Not all references in the configuration list are equal. Ref[0]=0x%x Ref[%d]=0x%x\n",
+ config_list[0].iRef, i, config_list[i].iRef);
+ err = ME_ERRNO_INVALID_REF;
+ goto ERROR;
+ }
+
+ if ((config_list[i].iRef == ME_REF_AI_DIFFERENTIAL)
+ && (config_list[i].iChannel >= 16)) {
+ PERROR("Channel not available in differential mode.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ goto ERROR;
+ }
+
+ if ((config_list[i].iChannel < 0)
+ || (config_list[i].iChannel >= instance->channels)) {
+ PERROR("Invalid channel number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ goto ERROR;
+ }
+ }
+
+ // Check settings - end
+
+ //Cancel control task
+ PDEBUG("Cancel control task.\n");
+ instance->ai_control_task_flag = 0;
+ cancel_delayed_work(&instance->ai_control_task);
+
+ // Work around from Keith Hartley - begin
+ if (trigger->iScanStartTrigType == ME_TRIG_TYPE_TIMER) {
+ if (count == 1) {
+ // The hardware does not work properly with a non-zero scan time
+ // if there is only ONE channel in the channel list. In this case
+ // we must set the scan time to zero and use the channel time.
+
+ conv_ticks = scan_ticks;
+ trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW;
+ } else if (scan_ticks == count * conv_ticks) {
+ // Another hardware problem. If the number of scan ticks is
+ // exactly equal to the number of channel ticks multiplied by
+ // the number of channels then the sampling rate is reduced
+ // by half.
+ trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW;
+ }
+ }
+ // Work around from Keith Hartley - end
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) {
+ PERROR("Subdevice is busy.\n");
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+
+ instance->status = ai_status_none;
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ // Stop all actions. Block all interrupts. Clear (disable) FIFOs.
+ ctrl =
+ ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_SC_IRQ_RESET;
+
+ tmp = inl(instance->ctrl_reg);
+ // Preserve EXT IRQ and OFFSET settings. Clean other bits.
+ tmp &=
+ (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET);
+
+ // Send it to register.
+ outl(tmp | ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp | ctrl);
+
+ // Enable channel fifo -> data fifo in stream_start().
+ ctrl |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO;
+ outl(tmp | ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp | ctrl);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+
+ // Write the channel list
+ for (i = 0; i < count; i++) {
+ entry = config_list[i].iChannel;
+
+ switch (config_list[i].iStreamConfig) {
+ case 0: //BIPOLAR 10V
+/*
+ // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000
+ // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed.
+ entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10;
+*/
+ break;
+ case 1: //UNIPOLAR 10V
+ entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_10;
+ break;
+ case 2: //BIPOLAR 2.5V
+ entry |= ME4600_AI_LIST_RANGE_BIPOLAR_2_5;
+ break;
+ case 3: //UNIPOLAR 2.5V
+ entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_2_5;
+ break;
+ default:
+ PERROR_CRITICAL("UNCHECK ERROR in config_list!\n");
+ PERROR_CRITICAL
+ ("WRONG range\nPosition:%d Range:0x%04X\n", i,
+ config_list[i].iStreamConfig);
+ goto VERIFY_ERROR;
+ break;
+ }
+
+ switch (config_list[i].iRef) {
+ case ME_REF_AI_GROUND: //SINGLE ENDED
+/*
+ // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000
+ // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' ==> Do nothing. Removed.
+ entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED;
+*/ break;
+ case ME_REF_AI_DIFFERENTIAL: //DIFFERENTIAL
+ entry |= ME4600_AI_LIST_INPUT_DIFFERENTIAL;
+ break;
+ default:
+ PERROR_CRITICAL("UNCHECK ERROR in config_list!\n");
+ PERROR_CRITICAL
+ ("WRONG reference\nPosition:%d Reference:0x%04X\n",
+ i, config_list[i].iRef);
+ goto VERIFY_ERROR;
+ break;
+ }
+
+ //Add last entry flag
+ if (i == (count - 1)) {
+ entry |= ME4600_AI_LIST_LAST_ENTRY;
+ }
+
+ outl(entry, instance->channel_list_reg);
+ PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->channel_list_reg - instance->reg_base,
+ entry);
+ }
+
+ // Set triggering registers
+ --acq_ticks;
+ outl(acq_ticks, instance->chan_pre_timer_reg);
+ PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llX\n",
+ instance->reg_base,
+ instance->chan_pre_timer_reg - instance->reg_base,
+ acq_ticks);
+ outl(acq_ticks, instance->scan_pre_timer_low_reg);
+ PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n",
+ instance->reg_base,
+ instance->scan_pre_timer_low_reg - instance->reg_base,
+ acq_ticks & 0xFFFFFFFF);
+ outl((acq_ticks >> 32), instance->scan_pre_timer_high_reg);
+ PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n",
+ instance->reg_base,
+ instance->scan_pre_timer_high_reg - instance->reg_base,
+ (acq_ticks >> 32) & 0xFFFFFFFF);
+
+ // Set triggers
+ switch (trigger->iAcqStartTrigType) {
+ // Internal
+ case ME_TRIG_TYPE_SW:
+ // Nothing to set.
+ break;
+
+ // External
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG;
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG;
+
+ // External trigger needs edge's definition
+ switch (trigger->iAcqStartTrigEdge) {
+ case ME_TRIG_EDGE_RISING:
+ // Nothing to set.
+ break;
+
+ case ME_TRIG_EDGE_FALLING:
+ ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_FALLING;
+ break;
+
+ case ME_TRIG_EDGE_ANY:
+ ctrl |=
+ ME4600_AI_CTRL_BIT_EX_TRIG_FALLING |
+ ME4600_AI_CTRL_BIT_EX_TRIG_BOTH;
+ break;
+
+ default:
+ PERROR_CRITICAL
+ ("UNCHECK TRIGGER EDGE in triggers structure!\n");
+ PERROR_CRITICAL
+ ("WRONG acquisition start trigger:0x%04X.\n",
+ trigger->iAcqStartTrigEdge);
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+ goto VERIFY_ERROR;
+ break;
+ }
+ break;
+
+ default:
+ PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n");
+ PERROR_CRITICAL("WRONG acquisition start trigger:0x%04X.\n",
+ trigger->iAcqStartTrigType);
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE;
+ goto VERIFY_ERROR;
+ break;
+ }
+
+ switch (trigger->iScanStartTrigType) {
+ case ME_TRIG_TYPE_TIMER:
+ --scan_ticks;
+ outl(scan_ticks, instance->scan_timer_low_reg);
+ PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n",
+ instance->reg_base,
+ instance->scan_timer_low_reg - instance->reg_base,
+ scan_ticks & 0xFFFFFFFF);
+ outl((scan_ticks >> 32), instance->scan_timer_high_reg);
+ PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n",
+ instance->reg_base,
+ instance->scan_timer_high_reg - instance->reg_base,
+ (scan_ticks >> 32) & 0xFFFFFFFF);
+
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) {
+ ctrl |= ME4600_AI_CTRL_BIT_MODE_0;
+ } else {
+ ctrl |= ME4600_AI_CTRL_BIT_MODE_1;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ outl(0, instance->scan_timer_low_reg);
+ PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_low_reg - instance->reg_base,
+ 0);
+ outl(0, instance->scan_timer_high_reg);
+ PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_high_reg - instance->reg_base,
+ 0);
+ ctrl |= ME4600_AI_CTRL_BIT_MODE_2;
+ break;
+
+ case ME_TRIG_TYPE_FOLLOW:
+ outl(0, instance->scan_timer_low_reg);
+ PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_low_reg - instance->reg_base,
+ 0);
+ outl(0, instance->scan_timer_high_reg);
+ PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_high_reg - instance->reg_base,
+ 0);
+
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) {
+ ctrl |= ME4600_AI_CTRL_BIT_MODE_0;
+ } else {
+ ctrl |= ME4600_AI_CTRL_BIT_MODE_1;
+ }
+ break;
+
+ default:
+ PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n");
+ PERROR_CRITICAL("WRONG scan start trigger:0x%04X.\n",
+ trigger->iScanStartTrigType);
+ err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE;
+ goto VERIFY_ERROR;
+ break;
+ }
+
+ switch (trigger->iConvStartTrigType) {
+
+ case ME_TRIG_TYPE_TIMER:
+ --conv_ticks;
+ outl(conv_ticks, instance->chan_timer_reg);
+ PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llX\n",
+ instance->reg_base,
+ instance->chan_timer_reg - instance->reg_base,
+ conv_ticks);
+ break;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ case ME_TRIG_TYPE_EXT_ANALOG:
+ outl(0, instance->chan_timer_reg);
+ PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->chan_timer_reg - instance->reg_base, 0);
+ ctrl |= ME4600_AI_CTRL_BIT_MODE_0 | ME4600_AI_CTRL_BIT_MODE_1;
+ break;
+
+ default:
+ PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n");
+ PERROR_CRITICAL("WRONG conv start trigger:0x%04X.\n",
+ trigger->iConvStartTrigType);
+ err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE;
+ goto VERIFY_ERROR;
+
+ break;
+ }
+
+ //Sample & Hold feature
+ if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) {
+ if (instance->sh) {
+ ctrl |= ME4600_AI_CTRL_BIT_SAMPLE_HOLD;
+ } else {
+ PERROR_CRITICAL("UNCHECK S&H feature!\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ goto VERIFY_ERROR;
+ }
+ }
+ //Enable IRQs sources but leave latches blocked.
+ ctrl |= (ME4600_AI_CTRL_BIT_HF_IRQ | ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_LE_IRQ); //The last IRQ source (ME4600_AI_CTRL_BIT_LE_IRQ) is unused!
+
+ //Everything is good. Finalize
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ tmp = inl(instance->ctrl_reg);
+
+ //Preserve EXT IRQ and OFFSET settings. Clean other bits.
+ tmp &=
+ (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET);
+
+ // write the control word
+ outl(ctrl | tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl | tmp);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+
+ //Set the global parameters end exit.
+ instance->chan_list_len = count;
+ instance->fifo_irq_threshold = fifo_irq_threshold;
+
+ if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) {
+ data_required =
+ (unsigned long long)trigger->iAcqStopCount *
+ (unsigned long long)count;
+ if (data_required > UINT_MAX)
+ data_required = UINT_MAX;
+ instance->data_required = (unsigned int)data_required;
+ } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT)
+ instance->data_required =
+ (unsigned long long)trigger->iScanStopCount;
+ else
+ instance->data_required = 0;
+
+ // Mark subdevice as configured to work in stream mode.
+ instance->status = ai_status_stream_configured;
+
+ // Deinit single config. Set all entries to NOT_CONFIGURED.
+ for (i = 0; i < instance->channels; i++) {
+ instance->single_config[i].status =
+ ME_SINGLE_CHANNEL_NOT_CONFIGURED;
+ }
+
+ VERIFY_ERROR: // Error in code. Wrong setting check. This should never ever happend!
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ ERROR: // Error in settings.
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ai_io_stream_new_values(me_subdevice_t * subdevice,
+ struct file *filep,
+ int time_out, int *count, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long t;
+ unsigned long j;
+ int volatile head;
+
+ PDEBUG("executed. idx=0\n");
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ } else { // Max time.
+ t = LONG_MAX;
+ }
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ j = jiffies;
+
+ while (1) {
+ // Only runing device can generate break.
+ head = instance->circ_buf.head;
+ wait_event_interruptible_timeout(instance->wait_queue,
+ ((head !=
+ instance->circ_buf.head)
+ ||
+ ((instance->status <=
+ ai_status_stream_run_wait)
+ && (instance->status >=
+ ai_status_stream_end_wait))),
+ t);
+
+ if (head != instance->circ_buf.head) { // New data in buffer.
+ break;
+ } else if (instance->status == ai_status_stream_end) { // End of work.
+ break;
+ } else if (instance->status == ai_status_stream_fifo_error) {
+ err = ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ break;
+ } else if (instance->status == ai_status_stream_buffer_error) {
+ err = ME_ERRNO_RING_BUFFER_OVERFLOW;
+ break;
+ } else if (instance->status == ai_status_stream_error) {
+ err = ME_ERRNO_INTERNAL;
+ break;
+ } else if ((jiffies - j) >= t) {
+ PERROR("Wait on values timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ break;
+ } else if (signal_pending(current)) {
+ PERROR("Wait on values interrupted from signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ break;
+ }
+ // Correct timeout.
+ t -= jiffies - j;
+ }
+
+ *count = me_circ_buf_values(&instance->circ_buf);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int inline me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t *
+ instance, int *values,
+ const int count,
+ const int flags)
+{
+ int n;
+ int i;
+ uint32_t value;
+
+ ///Checking how many datas can be copied.
+ n = me_circ_buf_values(&instance->circ_buf);
+ if (n <= 0)
+ return 0;
+
+ if (n > count)
+ n = count;
+
+ if (flags & ME_IO_STREAM_READ_FRAMES) {
+ if (n < instance->chan_list_len) //Not enough data!
+ return 0;
+ n -= n % instance->chan_list_len;
+ }
+
+ for (i = 0; i < n; i++) {
+ value = *(instance->circ_buf.buf + instance->circ_buf.tail);
+ if (put_user(value, values + i)) {
+ PERROR("Cannot copy new values to user.\n");
+ return -ME_ERRNO_INTERNAL;
+ }
+ instance->circ_buf.tail++;
+ instance->circ_buf.tail &= instance->circ_buf.mask;
+ }
+ return n;
+}
+
+static int me4600_ai_io_stream_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int read_mode,
+ int *values, int *count, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ int ret;
+
+ int c = *count;
+ int min = c;
+
+ PDEBUG("executed. idx=0\n");
+
+ if (flags & ~ME_IO_STREAM_READ_FRAMES) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!values || !count) {
+ PERROR("Request has invalid pointer.\n");
+ return ME_ERRNO_INVALID_POINTER;
+ }
+
+ if (c < 0) {
+ PERROR("Request has invalid value's counter.\n");
+ return ME_ERRNO_INVALID_VALUE_COUNT;
+ }
+
+ if ((read_mode != ME_READ_MODE_BLOCKING)
+ && (read_mode != ME_READ_MODE_NONBLOCKING)) {
+ PERROR("Invalid read mode specified.\n");
+ return ME_ERRNO_INVALID_READ_MODE;
+ }
+
+ if (c == 0) { //You get what you want! Nothing more or less.
+ return ME_ERRNO_SUCCESS;
+ }
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+ ME_SUBDEVICE_ENTER;
+
+ //Check if subdevice is configured.
+ if (instance->chan_list_len <= 0) {
+ PERROR("Subdevice wasn't configured.\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ if (flags & ME_IO_STREAM_READ_FRAMES) {
+ if (c < instance->chan_list_len) { //Not enough data requested.
+ PERROR
+ ("When using FRAME_READ mode minimal size is defined by channel list.\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INVALID_VALUE_COUNT;
+ }
+ }
+
+ if (c > (ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len)) { // To return acceptable amount of data when user pass too big value.
+ min = ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len;
+ }
+
+ if (flags & ME_IO_STREAM_READ_FRAMES) {
+ //Wait for whole list.
+ if (read_mode == ME_READ_MODE_BLOCKING) {
+ min = c - (c % instance->chan_list_len);
+ }
+
+ if (read_mode == ME_READ_MODE_NONBLOCKING) {
+ min = instance->chan_list_len;
+ }
+ }
+
+ if ((inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { //Working
+ //If blocking mode -> wait for data.
+ if ((me_circ_buf_values(&instance->circ_buf) < min)
+ && (read_mode == ME_READ_MODE_BLOCKING)) {
+ wait_event_interruptible(instance->wait_queue,
+ ((me_circ_buf_values
+ (&instance->circ_buf) >= min)
+ || !(inl(instance->status_reg)
+ &
+ ME4600_AI_STATUS_BIT_FSM)));
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on values interrupted from signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+ }
+ }
+
+ ret = me4600_ai_io_stream_read_get_value(instance, values, c, flags);
+ if (ret < 0) {
+ err = -ret;
+ *count = 0;
+ } else if (ret == 0) {
+ *count = 0;
+ if (instance->status == ai_status_stream_fifo_error) {
+ err = ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ instance->status = ai_status_stream_end;
+ } else if (instance->status == ai_status_stream_buffer_error) {
+ err = ME_ERRNO_RING_BUFFER_OVERFLOW;
+ instance->status = ai_status_stream_end;
+ } else if (instance->status == ai_status_stream_end) {
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ } else if (instance->status == ai_status_stream_error) {
+ err = ME_ERRNO_INTERNAL;
+ } else if (instance->status == ai_status_none) {
+ PDEBUG("Stream canceled.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+ } else {
+ *count = ret;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+/** @brief Stop aqusation. Preserve FIFOs.
+*
+* @param instance The subdevice instance (pointer).
+*/
+
+static int ai_stop_immediately(me4600_ai_subdevice_t * instance)
+{
+ unsigned long cpu_flags = 0;
+ volatile uint32_t ctrl;
+ const int timeout = HZ / 10; //100ms
+ int i;
+
+ for (i = 0; i <= timeout; i++) {
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME4600_AI_CTRL_BIT_STOP;
+ ctrl |=
+ (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP |
+ ME4600_AI_CTRL_BIT_HF_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_SC_IRQ_RESET);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+
+ if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { // Exit.
+ break;
+ }
+
+ PINFO("Wait for stop: %d\n", i + 1);
+ //Still working!
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ if (i > timeout) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ return ME_ERRNO_INTERNAL;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_io_stream_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags = 0;
+ unsigned long ref;
+ unsigned long delay = 0;
+
+ volatile uint32_t tmp;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((start_mode != ME_START_MODE_BLOCKING)
+ && (start_mode != ME_START_MODE_NONBLOCKING)) {
+ PERROR("Invalid start mode specified.\n");
+ return ME_ERRNO_INVALID_START_MODE;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+
+ if (delay == 0)
+ delay = 1;
+ }
+
+ ME_SUBDEVICE_ENTER
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+
+ tmp = inl(instance->ctrl_reg);
+
+ if ((tmp & ME4600_AI_STATUS_BIT_FSM)) {
+ PERROR("Conversion is already running.\n");
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ if (instance->chan_list_len == 0) { //Not configured!
+ PERROR("Subdevice is not configured to work in stream mode!\n");
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ goto ERROR;
+ }
+
+ if (!(tmp & (ME4600_AI_CTRL_BIT_MODE_0 | ME4600_AI_CTRL_BIT_MODE_1 | ME4600_AI_CTRL_BIT_MODE_2))) { //Mode 0 = single work => no stream config
+ PERROR("Subdevice is configured to work in single mode.\n");
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ goto ERROR;
+ }
+ //Reset stop bits.
+ tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ //Start datas' FIFO.
+ tmp |= ME4600_AI_CTRL_BIT_DATA_FIFO;
+ //Free stop bits.
+ tmp &= ~(ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+
+ //Cancel control task
+ PDEBUG("Cancel control task.\n");
+ instance->ai_control_task_flag = 0;
+ cancel_delayed_work(&instance->ai_control_task);
+
+ //Set the starting values.
+ instance->ISM.global_read = 0;
+ instance->ISM.read = 0;
+ //Clear circular buffer
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+
+ //Set everything.
+ ai_data_acquisition_logic(instance);
+
+ //Set status to 'wait for start'
+ instance->status = ai_status_stream_run_wait;
+
+ // Set control task's timeout
+ instance->timeout.delay = delay;
+ instance->timeout.start_time = jiffies;
+
+ //Lets go! Start work
+ inl(instance->start_reg);
+ PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base,
+ instance->start_reg - instance->reg_base);
+
+ // Schedule control task
+ instance->ai_control_task_flag = 1;
+ queue_delayed_work(instance->me4600_workqueue,
+ &instance->ai_control_task, 1);
+
+ PDEVELOP("Delay:%ld\n", delay);
+
+ if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start.
+ ref = jiffies;
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ai_status_stream_run_wait),
+ (delay) ? delay +
+ 1 : LONG_MAX);
+
+ if ((instance->status != ai_status_stream_run)
+ && (instance->status != ai_status_stream_end)) {
+ PDEBUG("Starting stream canceled. %d\n",
+ instance->status);
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ instance->status = ai_status_none;
+ ai_stop_isr(instance);
+ err = ME_ERRNO_SIGNAL;
+ } else if ((delay) && ((jiffies - ref) > delay)) {
+ if (instance->status != ai_status_stream_run) {
+ if (instance->status == ai_status_stream_end) {
+ PDEBUG("Timeout reached.\n");
+ } else if ((jiffies - ref) > delay + 1) {
+ PERROR
+ ("Timeout reached. Not handled by control task!\n");
+ ai_stop_isr(instance);
+ instance->status =
+ ai_status_stream_error;
+ } else {
+ PERROR
+ ("Timeout reached. Signal come but status is strange: %d\n",
+ instance->status);
+ ai_stop_isr(instance);
+ instance->status =
+ ai_status_stream_error;
+ }
+
+ instance->ai_control_task_flag = 0;
+ cancel_delayed_work(&instance->ai_control_task);
+ err = ME_ERRNO_TIMEOUT;
+ }
+ }
+ }
+#ifdef MEDEBUG_INFO
+ tmp = inl(instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ PINFO("STATUS_BIT_FSM=%s.\n",
+ (tmp & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off");
+ PINFO("CTRL_BIT_HF_IRQ=%s.\n",
+ (tmp & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable");
+ PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n",
+ (tmp & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : "work");
+ PINFO("CTRL_BIT_SC_IRQ=%s.\n",
+ (tmp & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable");
+ PINFO("CTRL_BIT_SC_RELOAD=%s.\n",
+ (tmp & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off");
+ PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n",
+ (tmp & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : "work");
+#endif
+
+ ERROR:
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ai_io_stream_status(me_subdevice_t * subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *values, int flags)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ switch (instance->status) {
+ case ai_status_single_configured:
+ case ai_status_stream_configured:
+ case ai_status_stream_end:
+ case ai_status_stream_fifo_error:
+ case ai_status_stream_buffer_error:
+ case ai_status_stream_error:
+ *status = ME_STATUS_IDLE;
+ break;
+
+ case ai_status_stream_run_wait:
+ case ai_status_stream_run:
+ case ai_status_stream_end_wait:
+ *status = ME_STATUS_BUSY;
+ break;
+
+ case ai_status_none:
+ default:
+ *status =
+ (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) ?
+ ME_STATUS_BUSY : ME_STATUS_IDLE;
+ break;
+ }
+
+ if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) {
+ // Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ ((instance->status !=
+ ai_status_stream_run_wait)
+ && (instance->status !=
+ ai_status_stream_run)
+ && (instance->status !=
+ ai_status_stream_end_wait)),
+ LONG_MAX);
+
+ if (instance->status != ai_status_stream_end) {
+ PDEBUG("Wait for IDLE canceled. %d\n",
+ instance->status);
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait for IDLE interrupted.\n");
+ instance->status = ai_status_none;
+ ai_stop_isr(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ *status = ME_STATUS_IDLE;
+ }
+
+ *values = me_circ_buf_values(&instance->circ_buf);
+ PDEBUG("me_circ_buf_values(&instance->circ_buf)=%d.\n", *values);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ai_io_stream_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int stop_mode, int flags)
+{
+/**
+ @note Stop is implemented only in blocking mode.
+ @note Function return when state machine is stoped.
+*/
+ me4600_ai_subdevice_t *instance;
+ unsigned long cpu_flags;
+ uint32_t ctrl;
+ int ret;
+
+ PDEBUG("executed. idx=0\n");
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((stop_mode != ME_STOP_MODE_IMMEDIATE)
+ && (stop_mode != ME_STOP_MODE_LAST_VALUE)) {
+ PERROR("Invalid stop mode specified.\n");
+ return ME_ERRNO_INVALID_STOP_MODE;
+ }
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ // Mark as stopping. => Software stop.
+ instance->status = ai_status_stream_end_wait;
+
+ if (stop_mode == ME_STOP_MODE_IMMEDIATE) {
+ ret = ai_stop_immediately(instance);
+
+ if (ret) {
+ PERROR("FSM is still busy.\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+ instance->ai_control_task_flag = 0;
+
+ } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) {
+ // Set stop bit in registry.
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME4600_AI_CTRL_BIT_STOP;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+
+ // Only runing process will interrupt this call. Events are signaled when status change.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ai_status_stream_end_wait),
+ LONG_MAX);
+
+ if (instance->status != ai_status_stream_end) {
+ PDEBUG("Stopping stream canceled.\n");
+ ret = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Stopping stream interrupted.\n");
+ instance->status = ai_status_none;
+ ret = ME_ERRNO_SIGNAL;
+ }
+ // End of work.
+ ai_stop_immediately(instance);
+
+ }
+
+ ret = ai_read_data_pooling(instance);
+ if (ret > 0) { // Everything fine. More datas put to software buffer.
+ instance->status = ai_status_stream_end;
+ ret = ME_ERRNO_SUCCESS;
+ // Signal that we put last data to software buffer.
+ wake_up_interruptible_all(&instance->wait_queue);
+ } else if (ret == 0) { // Everything fine. No more datas in FIFO.
+ instance->status = ai_status_stream_end;
+ ret = ME_ERRNO_SUCCESS;
+ } else if (ret == -ME_ERRNO_RING_BUFFER_OVERFLOW) { // Stop is unsuccessful, buffer is overflow.
+ instance->status = ai_status_stream_buffer_error;
+ ret = ME_ERRNO_SUCCESS;
+ } else { // Stop is unsuccessful
+ instance->status = ai_status_stream_end;
+ ret = -ret;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return ret;
+}
+
+static int me4600_ai_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range)
+{
+ me4600_ai_subdevice_t *instance;
+ int i;
+ int r = -1;
+ int diff = 21E6;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ if ((*max - *min) < 0) {
+ PERROR("Invalid minimum and maximum values specified.\n");
+ return ME_ERRNO_INVALID_MIN_MAX;
+ }
+
+ if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) {
+ for (i = 0; i < instance->ranges_len; i++) {
+ if ((instance->ranges[i].min <= *min)
+ && ((instance->ranges[i].max + 1000) >= *max)) {
+ if ((instance->ranges[i].max -
+ instance->ranges[i].min) - (*max - *min) <
+ diff) {
+ r = i;
+ diff =
+ (instance->ranges[i].max -
+ instance->ranges[i].min) - (*max -
+ *min);
+ }
+ }
+ }
+
+ if (r < 0) {
+ PERROR("No matching range found.\n");
+ return ME_ERRNO_NO_RANGE;
+ } else {
+ *min = instance->ranges[r].min;
+ *max = instance->ranges[r].max;
+ *maxdata = ME4600_AI_MAX_DATA;
+ *range = r;
+ }
+ } else {
+ PERROR("Invalid physical unit specified.\n");
+ return ME_ERRNO_INVALID_UNIT;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_query_number_ranges(me_subdevice_t * subdevice,
+ int unit, int *count)
+{
+ me4600_ai_subdevice_t *instance;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) {
+ *count = instance->ranges_len;
+ } else {
+ *count = 0;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_query_range_info(me_subdevice_t * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata)
+{
+ me4600_ai_subdevice_t *instance;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ if ((range < instance->ranges_len) && (range >= 0)) {
+ *unit = ME_UNIT_VOLT;
+ *min = instance->ranges[range].min;
+ *max = instance->ranges[range].max;
+ *maxdata = ME4600_AI_MAX_DATA;
+ } else {
+ PERROR("Invalid range number specified.\n");
+ return ME_ERRNO_INVALID_RANGE;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_query_timer(me_subdevice_t * subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks, long long *max_ticks)
+{
+ me4600_ai_subdevice_t *instance;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ switch (timer) {
+
+ case ME_TIMER_ACQ_START:
+ *base_frequency = ME4600_AI_BASE_FREQUENCY;
+ *min_ticks = ME4600_AI_MIN_ACQ_TICKS;
+ *max_ticks = ME4600_AI_MAX_ACQ_TICKS;
+ break;
+
+ case ME_TIMER_SCAN_START:
+ *base_frequency = ME4600_AI_BASE_FREQUENCY;
+ *min_ticks = ME4600_AI_MIN_SCAN_TICKS;
+ *max_ticks = ME4600_AI_MAX_SCAN_TICKS;
+ break;
+
+ case ME_TIMER_CONV_START:
+ *base_frequency = ME4600_AI_BASE_FREQUENCY;
+ *min_ticks = ME4600_AI_MIN_CHAN_TICKS;
+ *max_ticks = ME4600_AI_MAX_CHAN_TICKS;
+ break;
+
+ default:
+ PERROR("Invalid timer specified.(0x%04x)\n", timer);
+
+ return ME_ERRNO_INVALID_TIMER;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ me4600_ai_subdevice_t *instance;
+
+ PDEBUG("executed. idx=0\n");
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+ *number = instance->channels;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed. idx=0\n");
+
+ *type = ME_TYPE_AI;
+ *subtype = ME_SUBTYPE_STREAMING;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed. idx=0\n");
+
+ *caps =
+ ME_CAPS_AI_TRIG_SYNCHRONOUS | ME_CAPS_AI_FIFO |
+ ME_CAPS_AI_FIFO_THRESHOLD;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice,
+ int cap, int *args, int count)
+{
+ me4600_ai_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ instance = (me4600_ai_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=0\n");
+
+ if (count != 1) {
+ PERROR("Invalid capability argument count.\n");
+ return ME_ERRNO_INVALID_CAP_ARG_COUNT;
+ }
+
+ switch (cap) {
+ case ME_CAP_AI_FIFO_SIZE:
+ args[0] = ME4600_AI_FIFO_COUNT;
+ break;
+
+ case ME_CAP_AI_BUFFER_SIZE:
+ args[0] =
+ (instance->circ_buf.buf) ? ME4600_AI_CIRC_BUF_COUNT : 0;
+ break;
+
+ default:
+ PERROR("Invalid capability.\n");
+ err = ME_ERRNO_INVALID_CAP;
+ args[0] = 0;
+ }
+
+ return err;
+}
+
+void ai_limited_isr(me4600_ai_subdevice_t * instance, const uint32_t irq_status,
+ const uint32_t ctrl_status)
+{
+ int to_read;
+
+ if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work. HF need reseting.
+ if (irq_status & ME4600_IRQ_STATUS_BIT_SC) {
+ if (ai_read_data(instance, instance->ISM.next) != instance->ISM.next) { //ERROR!
+ PERROR
+ ("Limited amounts aqusition with TH=0: Circular buffer full!\n");
+ instance->status =
+ ai_status_stream_buffer_error;
+ } else {
+ instance->status = ai_status_stream_end;
+ }
+ //End of work.
+ ai_stop_isr(instance);
+ } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) {
+ instance->ISM.global_read += ME4600_AI_FIFO_HALF;
+
+ if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR!
+ PERROR
+ ("Limited amounts aqusition with TH = 0: Circular buffer full!\n");
+ //End of work.
+ ai_stop_isr(instance);
+ instance->status =
+ ai_status_stream_buffer_error;
+ } else {
+ //Continue.
+ ai_limited_ISM(instance, irq_status);
+ }
+ }
+ //Signal user.
+ wake_up_interruptible_all(&instance->wait_queue);
+ } else //if(instance->fifo_irq_threshold)
+ {
+ if (irq_status & ME4600_IRQ_STATUS_BIT_SC) {
+ instance->ISM.read = 0;
+ if ((instance->fifo_irq_threshold < ME4600_AI_FIFO_HALF)
+ && (!(ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA)))
+ {
+ to_read =
+ ME4600_AI_FIFO_HALF -
+ (ME4600_AI_FIFO_HALF %
+ instance->fifo_irq_threshold);
+ PDEBUG
+ ("Limited amounts aqusition with TH != 0: Not fast enough data aqusition! correction=%d\n",
+ to_read);
+ } else {
+ to_read = instance->ISM.next;
+ }
+ instance->ISM.global_read += to_read;
+
+ ai_reschedule_SC(instance);
+
+ if (ai_read_data(instance, to_read) != to_read) { //ERROR!
+ PERROR
+ ("Limited amounts aqusition with TH != 0: Circular buffer full!\n");
+ //End of work.
+ ai_stop_isr(instance);
+ instance->status =
+ ai_status_stream_buffer_error;
+ } else {
+ //Continue.
+ ai_limited_ISM(instance, irq_status);
+ }
+
+ //Signal user.
+ wake_up_interruptible_all(&instance->wait_queue);
+ } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) {
+ instance->ISM.read += ME4600_AI_FIFO_HALF;
+ instance->ISM.global_read += ME4600_AI_FIFO_HALF;
+
+ if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR!
+ PERROR
+ ("Limited amounts aqusition with TH != 0: Circular buffer full!\n");
+ ai_stop_isr(instance);
+
+ instance->status =
+ ai_status_stream_buffer_error;
+ //Signal user.
+ wake_up_interruptible_all(&instance->
+ wait_queue);
+ } else {
+ //Countinue.
+ ai_limited_ISM(instance, irq_status);
+ }
+ }
+
+ if (instance->ISM.global_read >= instance->data_required) { //End of work. Next paranoid pice of code: '>=' instead od '==' only to be sure.
+ ai_stop_isr(instance);
+ if (instance->status < ai_status_stream_end) {
+ instance->status = ai_status_stream_end;
+ }
+#ifdef MEDEBUG_ERROR
+ if (instance->ISM.global_read > instance->data_required) { //This is security check case. This should never ever happend!
+ PERROR
+ ("Limited amounts aqusition: Read more data than necessary! data_required=%d < read=%d\n",
+ instance->data_required,
+ instance->ISM.global_read);
+ //Signal error (warning??).
+ instance->status = ai_status_stream_error;
+ }
+#endif
+ }
+ }
+}
+
+void ai_infinite_isr(me4600_ai_subdevice_t * instance,
+ const uint32_t irq_status, const uint32_t ctrl_status)
+{
+ int to_read;
+
+ if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { //next chunck of data -> read fifo
+ //Set new state in ISM.
+ if ((instance->fifo_irq_threshold < ME4600_AI_FIFO_HALF) && (!(ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA))) { //There is more data than we ecpected. Propably we aren't fast enough. Read as many as possible.
+ if (instance->fifo_irq_threshold) {
+ to_read =
+ ME4600_AI_FIFO_HALF -
+ (ME4600_AI_FIFO_HALF %
+ instance->fifo_irq_threshold);
+ if (to_read > instance->fifo_irq_threshold) {
+ PDEBUG
+ ("Infinite aqusition: Not fast enough data aqusition! TH != 0: correction=%d\n",
+ to_read);
+ }
+ } else { //No threshold specified.
+ to_read = ME4600_AI_FIFO_HALF;
+ }
+ } else {
+ to_read = instance->ISM.next;
+ }
+
+ instance->ISM.read += to_read;
+
+ //Get data
+ if (ai_read_data(instance, to_read) != to_read) { //ERROR!
+ PERROR("Infinite aqusition: Circular buffer full!\n");
+ ai_stop_isr(instance);
+ instance->status = ai_status_stream_buffer_error;
+ } else {
+ ai_infinite_ISM(instance);
+ instance->ISM.global_read += instance->ISM.read;
+ instance->ISM.read = 0;
+ }
+
+ //Signal data to user
+ wake_up_interruptible_all(&instance->wait_queue);
+ } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { //fifo is half full -> read fifo Large blocks only!
+ instance->ISM.read += ME4600_AI_FIFO_HALF;
+
+ if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR!
+ PERROR("Infinite aqusition: Circular buffer full!\n");
+ ai_stop_isr(instance);
+ instance->status = ai_status_stream_buffer_error;
+
+ //Signal it.
+ wake_up_interruptible_all(&instance->wait_queue);
+ } else {
+ ai_infinite_ISM(instance);
+ }
+ }
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me4600_ai_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me4600_ai_isr(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{ /// @note This is time critical function!
+ uint32_t irq_status;
+ uint32_t ctrl_status;
+ me4600_ai_subdevice_t *instance = dev_id;
+ //int to_read;
+
+ PDEBUG("executed. idx=0\n");
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ irq_status = inl(instance->irq_status_reg);
+ if (!
+ (irq_status &
+ (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC))) {
+#ifdef MEDEBUG_INFO
+ if ((irq_status & (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC | ME4600_IRQ_STATUS_BIT_LE)) == ME4600_IRQ_STATUS_BIT_LE) { //This is security check case. LE is unused. This should never ever happend.
+ PINFO
+ ("%ld Shared interrupt. %s(): irq_status_reg=LE_IRQ\n",
+ jiffies, __func__);
+ } else {
+ PINFO
+ ("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n",
+ jiffies, __func__, irq_status);
+ }
+#endif
+ return IRQ_NONE;
+ }
+
+ if (!instance->circ_buf.buf) { //Security check.
+ PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n");
+ ai_stop_isr(instance);
+ return IRQ_HANDLED;
+ }
+ //Get the status register.
+ ctrl_status = inl(instance->status_reg);
+
+#ifdef MEDEBUG_INFO
+ if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF)
+ PINFO("HF interrupt active\n");
+ if (irq_status & ME4600_IRQ_STATUS_BIT_SC)
+ PINFO("SC interrupt active\n");
+ if (irq_status & ME4600_IRQ_STATUS_BIT_LE)
+ PINFO("LE interrupt active\n");
+#endif
+
+ //This is safety check!
+ if ((irq_status & ME4600_IRQ_STATUS_BIT_AI_HF)
+ && (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA)) {
+ PDEBUG("HF interrupt active but FIFO under half\n");
+ //Reset HF interrupt latch.
+ spin_lock(instance->ctrl_reg_lock);
+ outl(ctrl_status | ME4600_AI_CTRL_BIT_HF_IRQ_RESET,
+ instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl_status);
+ outl(ctrl_status, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl_status);
+ spin_unlock(instance->ctrl_reg_lock);
+ return IRQ_HANDLED;
+ }
+#ifdef MEDEBUG_INFO
+ PINFO("STATUS_BIT_FSM=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off");
+
+ PINFO("STATUS_BIT_EF_CHANNEL=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" :
+ "empty");
+ PINFO("STATUS_BIT_HF_CHANNEL=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" :
+ " > HF");
+ PINFO("STATUS_BIT_FF_CHANNEL=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" :
+ "full");
+
+ PINFO("STATUS_BIT_EF_DATA=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" :
+ "empty");
+ PINFO("STATUS_BIT_HF_DATA=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF");
+ PINFO("STATUS_BIT_FF_DATA=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" :
+ "full");
+
+ PINFO("CTRL_BIT_HF_IRQ=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable");
+ PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" :
+ "work");
+ PINFO("CTRL_BIT_SC_IRQ=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable");
+ PINFO("CTRL_BIT_SC_RELOAD=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off");
+ PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" :
+ "work");
+#endif
+
+ //Look for overflow error.
+ if (!(ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA)) {
+ //FIFO is full. Read datas and reset all settings.
+ PERROR("FIFO overflow.\n");
+ ai_read_data(instance, ME4600_AI_FIFO_COUNT);
+ ai_stop_isr(instance);
+
+ instance->status = ai_status_stream_fifo_error;
+ //Signal it.
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+ }
+
+ if (!instance->data_required) { //This is infinite aqusition.
+#ifdef MEDEBUG_ERROR
+ if ((irq_status &
+ (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC))
+ ==
+ (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC)) {
+ ///In infinite mode only one interrupt source should be reported!
+ PERROR
+ ("Error in ISM! Infinite aqusition: HF and SC interrupts active! threshold=%d next=%d ctrl=0x%04X irq_status_reg=0x%04X",
+ instance->fifo_irq_threshold, instance->ISM.next,
+ ctrl_status, irq_status);
+ }
+#endif
+
+ ai_infinite_isr(instance, irq_status, ctrl_status);
+
+#ifdef MEDEBUG_INFO
+ ctrl_status = inl(instance->ctrl_reg);
+#endif
+ } else {
+
+ ai_limited_isr(instance, irq_status, ctrl_status);
+ ctrl_status = inl(instance->status_reg);
+ if (!(ctrl_status & (ME4600_AI_STATUS_BIT_HF_DATA | ME4600_AI_CTRL_BIT_HF_IRQ_RESET))) { //HF active, but we have more than half already => HF will never come
+ PDEBUG
+ ("MISSED HF. data_required=%d ISM.read=%d ISM.global=%d ISM.next=%d\n",
+ instance->data_required, instance->ISM.read,
+ instance->ISM.global_read, instance->ISM.next);
+ ai_limited_isr(instance, ME4600_IRQ_STATUS_BIT_AI_HF,
+ ctrl_status);
+ }
+ }
+
+#ifdef MEDEBUG_INFO
+ PINFO("STATUS_BIT_FSM=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off");
+
+ PINFO("STATUS_BIT_EF_CHANNEL=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" :
+ "empty");
+ PINFO("STATUS_BIT_HF_CHANNEL=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" :
+ " > HF");
+ PINFO("STATUS_BIT_FF_CHANNEL=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" :
+ "full");
+
+ PINFO("STATUS_BIT_EF_DATA=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" :
+ "empty");
+ PINFO("STATUS_BIT_HF_DATA=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF");
+ PINFO("STATUS_BIT_FF_DATA=%s.\n",
+ (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" :
+ "full");
+
+ PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" :
+ "work");
+ PINFO("CTRL_BIT_SC_IRQ=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable");
+ PINFO("CTRL_BIT_SC_RELOAD=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off");
+ PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n",
+ (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" :
+ "work");
+ PINFO("%ld END\n", jiffies);
+#endif
+
+ return IRQ_HANDLED;
+}
+
+/** @brief Stop aqusation of data. Reset interrupts' laches. Clear data's FIFO.
+*
+* @param instance The subdevice instance (pointer).
+*/
+void inline ai_stop_isr(me4600_ai_subdevice_t * instance)
+{ /// @note This is soft time critical function!
+ register uint32_t tmp;
+
+ spin_lock(instance->ctrl_reg_lock);
+ //Stop all. Reset interrupt laches. Reset data FIFO.
+ tmp = inl(instance->ctrl_reg);
+ tmp |=
+ (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_HF_IRQ_RESET
+ | ME4600_AI_CTRL_BIT_LE_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_SC_IRQ_RESET);
+ tmp &= ~ME4600_AI_CTRL_BIT_DATA_FIFO;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+}
+
+/** @brief Copy data from fifo to circular buffer.
+*
+* @param instance The subdevice instance (pointer).
+* @param count The number of requested data.
+*
+* @return On success: Number of copied values.
+* @return On error: -ME_ERRNO_RING_BUFFER_OVERFLOW.
+*/
+static int inline ai_read_data(me4600_ai_subdevice_t * instance,
+ const int count)
+{ /// @note This is time critical function!
+ int c = count;
+ int empty_space;
+ int copied = 0;
+ int i, j;
+
+ empty_space = me_circ_buf_space_to_end(&instance->circ_buf);
+ if (empty_space <= 0) {
+ PDEBUG("Circular buffer full.\n");
+ return -ME_ERRNO_RING_BUFFER_OVERFLOW;
+ }
+
+ if (empty_space < c) { //Copy first part. Max to end of buffer.
+ PDEBUG
+ ("Try to copy %d values from FIFO to circular buffer (pass 1).\n",
+ empty_space);
+ for (i = 0; i < empty_space; i++) {
+ *(instance->circ_buf.buf + instance->circ_buf.head) =
+ (inw(instance->data_reg) ^ 0x8000);
+ instance->circ_buf.head++;
+ }
+ instance->circ_buf.head &= instance->circ_buf.mask;
+ c -= empty_space;
+ copied = empty_space;
+
+ empty_space = me_circ_buf_space_to_end(&instance->circ_buf);
+ }
+
+ if (empty_space > 0) {
+ j = (empty_space < c) ? empty_space : c;
+ PDEBUG
+ ("Try to copy %d values from FIFO to circular buffer (pass 2).\n",
+ c);
+ for (i = 0; i < j; i++) {
+ *(instance->circ_buf.buf + instance->circ_buf.head) =
+ (inw(instance->data_reg) ^ 0x8000);
+ instance->circ_buf.head++;
+ }
+ instance->circ_buf.head &= instance->circ_buf.mask;
+ copied += j;
+ }
+ return copied;
+}
+
+void inline ai_infinite_ISM(me4600_ai_subdevice_t * instance)
+{ /// @note This is time critical function!
+ register volatile uint32_t ctrl_set, ctrl_reset, tmp;
+
+ if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { // Only sample counter with reloadnig is working. Reset it.
+ PINFO
+ ("Only sample counter with reloadnig is working. Reset it.\n");
+ ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET;
+ ctrl_reset = ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET;
+ } else if (instance->fifo_irq_threshold == instance->ISM.read) { //This is SC interrupt for large block. The whole section is done. Reset SC_IRQ an HF_IRQ and start everything again from beginning.
+ PINFO
+ ("This is SC interrupt for large block. The whole section is done. Reset SC_IRQ an HF_IRQ and start everything again from beginning.\n");
+ ctrl_set =
+ ME4600_AI_CTRL_BIT_SC_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ ctrl_reset =
+ ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_HF_IRQ_RESET);
+ } else if (instance->fifo_irq_threshold >= (ME4600_AI_FIFO_MAX_SC + instance->ISM.read)) { //This is HF interrupt for large block.The next interrupt should be from HF, also. Reset HF.
+ PINFO
+ ("This is HF interrupt for large block.The next interrupt should be from HF, also. Reset HF.\n");
+ ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ } else { //This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF!
+ PINFO
+ ("This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF!\n");
+ ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ ctrl_reset = 0xFFFFFFFF;
+ }
+
+ //Reset interrupt latch.
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ PINFO("ctrl=0x%x ctrl_set=0x%x ctrl_reset=0x%x\n", tmp, ctrl_set,
+ ctrl_reset);
+ tmp |= ctrl_set;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ if (ctrl_reset != 0xFFFFFFFF) {
+ outl(tmp & ctrl_reset, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reset outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ tmp & ctrl_reset);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+
+}
+
+void inline ai_limited_ISM(me4600_ai_subdevice_t * instance,
+ uint32_t irq_status)
+{ /// @note This is time critical function!
+ register volatile uint32_t ctrl_set, ctrl_reset = 0xFFFFFFFF, tmp;
+
+ if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work.
+ PINFO("No threshold provided. SC ends work.\n");
+ ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ if (instance->data_required > (ME4600_AI_FIFO_COUNT - 1 + instance->ISM.global_read)) { //HF need reseting.
+ ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ }
+ } else //if(instance->fifo_irq_threshold)
+ {
+ if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) {
+ PINFO("Threshold provided. Clear HF latch.\n");
+ ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+
+ if (instance->fifo_irq_threshold >= (ME4600_AI_FIFO_MAX_SC + instance->ISM.read)) { //This is not the last one. HF need reseting.
+ PINFO
+ ("The next interrupt is HF. HF need be activating.\n");
+ ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ }
+ }
+
+ if (irq_status & ME4600_IRQ_STATUS_BIT_SC) {
+ PINFO("Threshold provided. Restart SC.\n");
+ ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET;
+ ctrl_reset &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET;
+
+ if (instance->fifo_irq_threshold >= ME4600_AI_FIFO_MAX_SC) { //This is not the last one. HF need to be activating.
+ PINFO
+ ("The next interrupt is HF. HF need to be activating.\n");
+ ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ }
+ }
+ }
+
+ //Reset interrupt latch.
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ctrl_set;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ if (ctrl_reset != 0xFFFFFFFF) {
+ outl(tmp & ctrl_reset, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ tmp & ctrl_reset);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+
+}
+
+/** @brief Last chunck of datas. We must reschedule sample counter.
+* @note Last chunck.
+* Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts.
+* @warning When threshold is wrongly set some IRQ are lost.(!!!)
+*/
+void inline ai_reschedule_SC(me4600_ai_subdevice_t * instance)
+{
+ register uint32_t rest;
+
+ if (instance->data_required <= instance->ISM.global_read)
+ return;
+
+ rest = instance->data_required - instance->ISM.global_read;
+ if (rest < instance->fifo_irq_threshold) { //End of work soon ....
+ PDEBUG("Rescheduling SC from %d to %d.\n",
+ instance->fifo_irq_threshold, rest);
+ /// @note Write new value to SC <== DANGER! This is not safe solution! We can miss some inputs.
+ outl(rest, instance->sample_counter_reg);
+ PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sample_counter_reg - instance->reg_base,
+ rest);
+ instance->fifo_irq_threshold = rest;
+
+ if (rest < ME4600_AI_FIFO_MAX_SC) {
+ instance->ISM.next = rest;
+ } else {
+ instance->ISM.next = rest % ME4600_AI_FIFO_HALF;
+ if (instance->ISM.next + ME4600_AI_FIFO_HALF <
+ ME4600_AI_FIFO_MAX_SC) {
+ instance->ISM.next += ME4600_AI_FIFO_HALF;
+ }
+ }
+ }
+}
+
+/** Start the ISM. All must be reseted before enter to this function. */
+void inline ai_data_acquisition_logic(me4600_ai_subdevice_t * instance)
+{
+ register uint32_t tmp;
+
+ if (!instance->data_required) { //This is infinite aqusition.
+ if (!instance->fifo_irq_threshold) { //No threshold provided. Set SC to 0.5*FIFO. Clear the SC's latch.
+ //Set the sample counter
+ outl(ME4600_AI_FIFO_HALF, instance->sample_counter_reg);
+ PDEBUG_REG
+ ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sample_counter_reg - instance->reg_base,
+ ME4600_AI_FIFO_HALF);
+ } else { //Threshold provided. Set SC to treshold. Clear the SC's latch.
+ //Set the sample counter
+ outl(instance->fifo_irq_threshold,
+ instance->sample_counter_reg);
+ PDEBUG_REG
+ ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sample_counter_reg - instance->reg_base,
+ instance->fifo_irq_threshold);
+ }
+
+ if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //Enable only sample counter's interrupt. Set reload bit. Clear the SC's latch.
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD;
+ tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+ if (!instance->fifo_irq_threshold) { //No threshold provided. Set ISM.next to 0.5*FIFO.
+ instance->ISM.next = ME4600_AI_FIFO_HALF;
+ } else { //Threshold provided. Set ISM.next to treshold.
+ instance->ISM.next =
+ instance->fifo_irq_threshold;
+ }
+ } else { //Enable sample counter's and HF's interrupts.
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD;
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_HF_IRQ_RESET);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ instance->ISM.next =
+ instance->fifo_irq_threshold % ME4600_AI_FIFO_HALF;
+ if (instance->ISM.next + ME4600_AI_FIFO_HALF <
+ ME4600_AI_FIFO_MAX_SC) {
+ instance->ISM.next += ME4600_AI_FIFO_HALF;
+ }
+ }
+ } else { //This aqusition is limited to set number of data.
+ if (instance->fifo_irq_threshold >= instance->data_required) { //Stupid situation.
+ instance->fifo_irq_threshold = 0;
+ PDEBUG
+ ("Stupid situation: data_required(%d) < threshold(%d).\n",
+ instance->fifo_irq_threshold,
+ instance->data_required);
+ }
+
+ if (!instance->fifo_irq_threshold) { //No threshold provided. Easy case: HF=read and SC=end.
+ //Set the sample counter to data_required.
+ outl(instance->data_required,
+ instance->sample_counter_reg);
+ PDEBUG_REG
+ ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sample_counter_reg - instance->reg_base,
+ instance->data_required);
+
+ //Reset the latches of sample counter and HF (if SC>FIFO).
+ //No SC reload!
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_SC_RELOAD);
+ if (instance->data_required >
+ (ME4600_AI_FIFO_COUNT - 1)) {
+ tmp &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET;
+ instance->ISM.next =
+ instance->data_required %
+ ME4600_AI_FIFO_HALF;
+ instance->ISM.next += ME4600_AI_FIFO_HALF;
+
+ } else {
+ instance->ISM.next = instance->data_required;
+ }
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ } else { //The most general case. We have concret numbe of required data and threshold. SC=TH
+ //Set the sample counter to threshold.
+ outl(instance->fifo_irq_threshold,
+ instance->sample_counter_reg);
+ PDEBUG_REG
+ ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->sample_counter_reg - instance->reg_base,
+ instance->fifo_irq_threshold);
+
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ //In this moment we are sure that SC will come more than once.
+ tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD;
+
+ if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //The threshold is so small that we do need HF.
+ tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET;
+ instance->ISM.next =
+ instance->fifo_irq_threshold;
+ } else { //The threshold is large. The HF must be use.
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_HF_IRQ_RESET);
+ instance->ISM.next =
+ instance->fifo_irq_threshold %
+ ME4600_AI_FIFO_HALF;
+ if (instance->ISM.next + ME4600_AI_FIFO_HALF <
+ ME4600_AI_FIFO_MAX_SC) {
+ instance->ISM.next +=
+ ME4600_AI_FIFO_HALF;
+ }
+ }
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+ }
+ }
+}
+
+static int ai_mux_toggler(me4600_ai_subdevice_t * instance)
+{
+ uint32_t tmp;
+
+ PDEBUG("executed. idx=0\n");
+
+ outl(0, instance->scan_pre_timer_low_reg);
+ PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_pre_timer_low_reg - instance->reg_base, 0);
+ outl(0, instance->scan_pre_timer_high_reg);
+ PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_pre_timer_high_reg - instance->reg_base, 0);
+ outl(0, instance->scan_timer_low_reg);
+ PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_low_reg - instance->reg_base, 0);
+ outl(0, instance->scan_timer_high_reg);
+ PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->scan_timer_high_reg - instance->reg_base, 0);
+ outl(65, instance->chan_timer_reg);
+ PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->chan_timer_reg - instance->reg_base, 65);
+ outl(65, instance->chan_pre_timer_reg);
+ PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->chan_pre_timer_reg - instance->reg_base, 65);
+
+ // Turn on internal reference.
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AI_CTRL_BIT_FULLSCALE;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ // Clear data and channel fifo.
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ // Write channel entry.
+ outl(ME4600_AI_LIST_INPUT_DIFFERENTIAL |
+ ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31,
+ instance->channel_list_reg);
+ PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->channel_list_reg - instance->reg_base,
+ ME4600_AI_LIST_INPUT_DIFFERENTIAL |
+ ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31);
+
+ // Start conversion.
+ inl(instance->start_reg);
+ PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base,
+ instance->start_reg - instance->reg_base);
+ udelay(10);
+
+ // Clear data and channel fifo.
+ tmp &=
+ ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO;
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ // Write channel entry.
+ // ME4600_AI_LIST_INPUT_SINGLE_ENDED | ME4600_AI_LIST_RANGE_BIPOLAR_10 <= 0x0000
+ outl(ME4600_AI_LIST_INPUT_SINGLE_ENDED |
+ ME4600_AI_LIST_RANGE_BIPOLAR_10, instance->channel_list_reg);
+ PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->channel_list_reg - instance->reg_base,
+ ME4600_AI_LIST_INPUT_SINGLE_ENDED |
+ ME4600_AI_LIST_RANGE_BIPOLAR_10);
+
+ // Start conversion.
+ inl(instance->start_reg);
+ PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base,
+ instance->start_reg - instance->reg_base);
+ udelay(10);
+
+ // Clear control register.
+ tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+/** @brief Copy rest of data from fifo to circular buffer.
+* @note Helper for STOP command. After FSM is stopped.
+* @note This is slow function that copy all remainig data from FIFO to buffer.
+*
+* @param instance The subdevice instance (pointer).
+*
+* @return On success: Number of copied values.
+* @return On error: Negative error code -ME_ERRNO_RING_BUFFER_OVERFLOW.
+*/
+static int inline ai_read_data_pooling(me4600_ai_subdevice_t * instance)
+{ /// @note This is time critical function!
+ int empty_space;
+ int copied = 0;
+ int status = ME_ERRNO_SUCCESS;
+
+ PDEBUG("Space left in circular buffer = %d.\n",
+ me_circ_buf_space(&instance->circ_buf));
+
+ while ((empty_space = me_circ_buf_space(&instance->circ_buf))) {
+ if (!(status = inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) { //No more data. status = ME_ERRNO_SUCCESS = 0
+ break;
+ }
+ *(instance->circ_buf.buf + instance->circ_buf.head) =
+ (inw(instance->data_reg) ^ 0x8000);
+ instance->circ_buf.head++;
+ instance->circ_buf.head &= instance->circ_buf.mask;
+ }
+
+#ifdef MEDEBUG_ERROR
+ if (!status)
+ PDEBUG
+ ("Copied all remaining datas (%d) from FIFO to circular buffer.\n",
+ copied);
+ else {
+ PDEBUG("No more empty space in buffer.\n");
+ PDEBUG("Copied %d datas from FIFO to circular buffer.\n",
+ copied);
+ PDEBUG("FIFO still not empty.\n");
+ }
+#endif
+ return (!status) ? copied : -ME_ERRNO_RING_BUFFER_OVERFLOW;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void me4600_ai_work_control_task(void *subdevice)
+#else
+static void me4600_ai_work_control_task(struct work_struct *work)
+#endif
+{
+ me4600_ai_subdevice_t *instance;
+ uint32_t status;
+ uint32_t ctrl;
+ unsigned long cpu_flags = 0;
+ int reschedule = 0;
+ int signaling = 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ instance = (me4600_ai_subdevice_t *) subdevice;
+#else
+ instance =
+ container_of((void *)work, me4600_ai_subdevice_t, ai_control_task);
+#endif
+ PINFO("<%s: %ld> executed.\n", __func__, jiffies);
+
+ status = inl(instance->status_reg);
+ PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->status_reg - instance->reg_base, status);
+
+ switch (instance->status) { // Checking actual mode.
+ // Not configured for work.
+ case ai_status_none:
+ break;
+
+ //This are stable modes. No need to do anything. (?)
+ case ai_status_single_configured:
+ case ai_status_stream_configured:
+ case ai_status_stream_fifo_error:
+ case ai_status_stream_buffer_error:
+ case ai_status_stream_error:
+ PERROR("Shouldn't be running!.\n");
+ break;
+
+ // Stream modes
+ case ai_status_stream_run_wait:
+ if (status & ME4600_AI_STATUS_BIT_FSM) { // ISM started..
+ instance->status = ai_status_stream_run;
+ // Signal the end of wait for start.
+ signaling = 1;
+ // Wait now for stop.
+ reschedule = 1;
+ break;
+
+ // Check timeout.
+ if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout
+ PDEBUG("Timeout reached.\n");
+ // Stop all actions. No conditions! Block interrupts. Reset FIFO => Too late!
+ ai_stop_isr(instance);
+
+ instance->status = ai_status_stream_end;
+
+ // Signal the end.
+ signaling = 1;
+ }
+ }
+ break;
+
+ case ai_status_stream_run:
+ // Wait for stop ISM.
+ reschedule = 1;
+ break;
+
+ case ai_status_stream_end_wait:
+ if (!(status & ME4600_AI_STATUS_BIT_FSM)) { // ISM stoped. Overwrite ISR.
+ instance->status = ai_status_stream_end;
+ // Signal the end of wait for stop.
+ signaling = 1;
+ } else {
+ // Wait for stop ISM.
+ reschedule = 1;
+ }
+ break;
+
+ case ai_status_stream_end:
+ //End work.
+ if (status & ME4600_AI_STATUS_BIT_FSM) { // Still working? Stop it!
+ PERROR
+ ("Status is 'ai_status_stream_end' but hardware is still working!\n");
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP |
+ ME4600_AI_CTRL_BIT_HF_IRQ_RESET |
+ ME4600_AI_CTRL_BIT_SC_IRQ_RESET);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock,
+ cpu_flags);
+ }
+ break;
+
+ default:
+ PERROR_CRITICAL("Status is in wrong state (%d)!\n",
+ instance->status);
+ instance->status = ai_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+
+ }
+
+ if (signaling) { //Signal it.
+ wake_up_interruptible_all(&instance->wait_queue);
+ }
+
+ if (instance->ai_control_task_flag && reschedule) { // Reschedule task
+ queue_delayed_work(instance->me4600_workqueue,
+ &instance->ai_control_task, 1);
+ } else {
+ PINFO("<%s> Ending control task.\n", __func__);
+ }
+
+}
diff --git a/drivers/staging/meilhaus/me4600_ai.h b/drivers/staging/meilhaus/me4600_ai.h
new file mode 100644
index 000000000000..1d5a1b9c6f91
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ai.h
@@ -0,0 +1,180 @@
+/**
+ * @file me4600_ai.h
+ *
+ * @brief Meilhaus ME-4000 analog input subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_AI_H_
+#define _ME4600_AI_H_
+
+#include <linux/version.h>
+#include "mesubdevice.h"
+#include "meioctl.h"
+#include "mecirc_buf.h"
+
+#ifdef __KERNEL__
+
+#define ME4600_AI_MAX_DATA 0xFFFF
+
+#ifdef ME_SYNAPSE
+# define ME4600_AI_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse
+#else
+# define ME4600_AI_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB
+#endif
+#define ME4600_AI_CIRC_BUF_SIZE PAGE_SIZE<<ME4600_AI_CIRC_BUF_SIZE_ORDER // Buffer size in bytes.
+
+#ifdef _CBUFF_32b_t
+# define ME4600_AI_CIRC_BUF_COUNT ((ME4600_AI_CIRC_BUF_SIZE) / sizeof(uint32_t)) // Size in values
+#else
+# define ME4600_AI_CIRC_BUF_COUNT ((ME4600_AI_CIRC_BUF_SIZE) / sizeof(uint16_t)) // Size in values
+#endif
+
+#define ME4600_AI_FIFO_HALF 1024 //ME4600_AI_FIFO_COUNT/2 //1024
+#define ME4600_AI_FIFO_MAX_SC 1352 //0.66*ME4600_AI_FIFO_COUNT //1352
+
+typedef enum ME4600_AI_STATUS {
+ ai_status_none = 0,
+ ai_status_single_configured,
+ ai_status_stream_configured,
+ ai_status_stream_run_wait,
+ ai_status_stream_run,
+ ai_status_stream_end_wait,
+ ai_status_stream_end,
+ ai_status_stream_fifo_error,
+ ai_status_stream_buffer_error,
+ ai_status_stream_error,
+ ai_status_last
+} ME4600_AI_STATUS;
+
+typedef struct me4600_single_config_entry {
+ unsigned short status;
+ uint32_t entry;
+ uint32_t ctrl;
+} me4600_single_config_entry_t;
+
+typedef struct me4600_range_entry {
+ int min;
+ int max;
+} me4600_range_entry_t;
+
+typedef struct me4600_ai_ISM {
+ volatile unsigned int global_read; /**< The number of data read in total. */
+ volatile unsigned int read; /**< The number of data read for this chunck. */
+ volatile unsigned int next; /**< The number of data request by user. */
+} me4600_ai_ISM_t;
+
+typedef struct me4600_ai_timeout {
+ unsigned long start_time;
+ unsigned long delay;
+} me4600_ai_timeout_t;
+
+/**
+ * @brief The ME-4000 analog input subdevice class.
+ */
+typedef struct me4600_ai_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+
+ /* Hardware feautres */
+ unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */
+ int isolated; /**< Marks if this subdevice is on an optoisolated device. */
+ int sh; /**< Marks if this subdevice has sample and hold devices. */
+
+ unsigned int channels; /**< The number of channels available on this subdevice. */
+ me4600_single_config_entry_t single_config[32]; /**< The configuration set for single acquisition. */
+
+ unsigned int data_required; /**< The number of data request by user. */
+ unsigned int fifo_irq_threshold; /**< The user adjusted FIFO high water interrupt level. */
+ unsigned int chan_list_len; /**< The length of the user defined channel list. */
+
+ me4600_ai_ISM_t ISM; /**< The information request by Interrupt-State-Machine. */
+ volatile enum ME4600_AI_STATUS status; /**< The current stream status flag. */
+ me4600_ai_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */
+
+ /* Registers *//**< All registers are 32 bits long. */
+ unsigned long ctrl_reg;
+ unsigned long status_reg;
+ unsigned long channel_list_reg;
+ unsigned long data_reg;
+ unsigned long chan_timer_reg;
+ unsigned long chan_pre_timer_reg;
+ unsigned long scan_timer_low_reg;
+ unsigned long scan_timer_high_reg;
+ unsigned long scan_pre_timer_low_reg;
+ unsigned long scan_pre_timer_high_reg;
+ unsigned long start_reg;
+ unsigned long irq_status_reg;
+ unsigned long sample_counter_reg;
+
+ unsigned int ranges_len;
+ me4600_range_entry_t ranges[4]; /**< The ranges available on this subdevice. */
+
+ /* Software buffer */
+ me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. */
+ wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */
+
+ struct workqueue_struct *me4600_workqueue;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ struct work_struct ai_control_task;
+#else
+ struct delayed_work ai_control_task;
+#endif
+
+ volatile int ai_control_task_flag; /**< Flag controling reexecuting of control task */
+
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me4600_ai_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-4000 analog input subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param channels The number of analog input channels available on this subdevice.
+ * @param channels The number of analog input ranges available on this subdevice.
+ * @param isolated Flag indicating if this device is opto isolated.
+ * @param sh Flag indicating if sample and hold devices are available.
+ * @param irq The irq number assigned by PCI BIOS.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base,
+ unsigned int channels,
+ unsigned int ranges,
+ int isolated,
+ int sh,
+ int irq,
+ spinlock_t * ctrl_reg_lock,
+ struct workqueue_struct
+ *me4600_wq);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_ai_reg.h b/drivers/staging/meilhaus/me4600_ai_reg.h
new file mode 100644
index 000000000000..083fac7685f5
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ai_reg.h
@@ -0,0 +1,107 @@
+/**
+ * @file me4600_ai_reg.h
+ *
+ * @brief ME-4000 analog input subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_AI_REG_H_
+#define _ME4600_AI_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME4600_AI_CTRL_REG 0x74 // _/W
+#define ME4600_AI_STATUS_REG 0x74 // R/_
+#define ME4600_AI_CHANNEL_LIST_REG 0x78 // _/W
+#define ME4600_AI_DATA_REG 0x7C // R/_
+#define ME4600_AI_CHAN_TIMER_REG 0x80 // _/W
+#define ME4600_AI_CHAN_PRE_TIMER_REG 0x84 // _/W
+#define ME4600_AI_SCAN_TIMER_LOW_REG 0x88 // _/W
+#define ME4600_AI_SCAN_TIMER_HIGH_REG 0x8C // _/W
+#define ME4600_AI_SCAN_PRE_TIMER_LOW_REG 0x90 // _/W
+#define ME4600_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 // _/W
+#define ME4600_AI_START_REG 0x98 // R/_
+
+#define ME4600_AI_SAMPLE_COUNTER_REG 0xC0 // _/W
+
+#define ME4600_AI_CTRL_BIT_MODE_0 0x00000001
+#define ME4600_AI_CTRL_BIT_MODE_1 0x00000002
+#define ME4600_AI_CTRL_BIT_MODE_2 0x00000004
+#define ME4600_AI_CTRL_BIT_SAMPLE_HOLD 0x00000008
+#define ME4600_AI_CTRL_BIT_IMMEDIATE_STOP 0x00000010
+#define ME4600_AI_CTRL_BIT_STOP 0x00000020
+#define ME4600_AI_CTRL_BIT_CHANNEL_FIFO 0x00000040
+#define ME4600_AI_CTRL_BIT_DATA_FIFO 0x00000080
+#define ME4600_AI_CTRL_BIT_FULLSCALE 0x00000100
+#define ME4600_AI_CTRL_BIT_OFFSET 0x00000200
+#define ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG 0x00000400
+#define ME4600_AI_CTRL_BIT_EX_TRIG 0x00000800
+#define ME4600_AI_CTRL_BIT_EX_TRIG_FALLING 0x00001000
+#define ME4600_AI_CTRL_BIT_EX_IRQ 0x00002000
+#define ME4600_AI_CTRL_BIT_EX_IRQ_RESET 0x00004000
+#define ME4600_AI_CTRL_BIT_LE_IRQ 0x00008000
+#define ME4600_AI_CTRL_BIT_LE_IRQ_RESET 0x00010000
+#define ME4600_AI_CTRL_BIT_HF_IRQ 0x00020000
+#define ME4600_AI_CTRL_BIT_HF_IRQ_RESET 0x00040000
+#define ME4600_AI_CTRL_BIT_SC_IRQ 0x00080000
+#define ME4600_AI_CTRL_BIT_SC_IRQ_RESET 0x00100000
+#define ME4600_AI_CTRL_BIT_SC_RELOAD 0x00200000
+#define ME4600_AI_CTRL_BIT_EX_TRIG_BOTH 0x80000000
+
+#define ME4600_AI_STATUS_BIT_EF_CHANNEL 0x00400000
+#define ME4600_AI_STATUS_BIT_HF_CHANNEL 0x00800000
+#define ME4600_AI_STATUS_BIT_FF_CHANNEL 0x01000000
+#define ME4600_AI_STATUS_BIT_EF_DATA 0x02000000
+#define ME4600_AI_STATUS_BIT_HF_DATA 0x04000000
+#define ME4600_AI_STATUS_BIT_FF_DATA 0x08000000
+#define ME4600_AI_STATUS_BIT_LE 0x10000000
+#define ME4600_AI_STATUS_BIT_FSM 0x20000000
+
+#define ME4600_AI_CTRL_RPCI_FIFO 0x40000000 //Always set to zero!
+
+#define ME4600_AI_BASE_FREQUENCY 33E6
+
+#define ME4600_AI_MIN_ACQ_TICKS 66LL
+#define ME4600_AI_MAX_ACQ_TICKS 0xFFFFFFFFLL
+
+#define ME4600_AI_MIN_SCAN_TICKS 66LL
+#define ME4600_AI_MAX_SCAN_TICKS 0xFFFFFFFFFLL
+
+#define ME4600_AI_MIN_CHAN_TICKS 66LL
+#define ME4600_AI_MAX_CHAN_TICKS 0xFFFFFFFFLL
+
+#define ME4600_AI_FIFO_COUNT 2048
+
+#define ME4600_AI_LIST_COUNT 1024
+
+#define ME4600_AI_LIST_INPUT_SINGLE_ENDED 0x000
+#define ME4600_AI_LIST_INPUT_DIFFERENTIAL 0x020
+
+#define ME4600_AI_LIST_RANGE_BIPOLAR_10 0x000
+#define ME4600_AI_LIST_RANGE_BIPOLAR_2_5 0x040
+#define ME4600_AI_LIST_RANGE_UNIPOLAR_10 0x080
+#define ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 0x0C0
+
+#define ME4600_AI_LIST_LAST_ENTRY 0x100
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_ao.c b/drivers/staging/meilhaus/me4600_ao.c
new file mode 100644
index 000000000000..e2bec8229abd
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ao.c
@@ -0,0 +1,6011 @@
+/**
+ * @file me4600_ao.c
+ *
+ * @brief ME-4000 analog output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+///Common part. (For normal and Bosch builds.)
+
+/* Includes
+ */
+
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "meids.h"
+#include "me4600_reg.h"
+#include "me4600_ao_reg.h"
+#include "me4600_ao.h"
+
+/* Defines
+ */
+
+static int me4600_ao_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range);
+
+static int me4600_ao_query_number_ranges(me_subdevice_t * subdevice,
+ int unit, int *count);
+
+static int me4600_ao_query_range_info(me_subdevice_t * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata);
+
+static int me4600_ao_query_timer(me_subdevice_t * subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks, long long *max_ticks);
+
+static int me4600_ao_query_number_channels(me_subdevice_t * subdevice,
+ int *number);
+
+static int me4600_ao_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype);
+
+static int me4600_ao_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps);
+
+static int me4600_ao_query_subdevice_caps_args(struct me_subdevice *subdevice,
+ int cap, int *args, int count);
+
+#ifndef BOSCH
+/// @note NORMAL BUILD
+/// @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+/* Includes
+ */
+
+# include <linux/workqueue.h>
+
+/* Defines
+ */
+
+/** Remove subdevice.
+*/
+static void me4600_ao_destructor(struct me_subdevice *subdevice);
+
+/** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'.
+*/
+static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags);
+
+/** Set output as single
+*/
+static int me4600_ao_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags);
+
+/** Pass to user actual value of output.
+*/
+static int me4600_ao_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags);
+
+/** Write to output requed value.
+*/
+static int me4600_ao_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags);
+
+/** Set output as streamed device.
+*/
+static int me4600_ao_io_stream_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags);
+
+/** Wait for / Check empty space in buffer.
+*/
+static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice,
+ struct file *filep,
+ int time_out, int *count, int flags);
+
+/** Start streaming.
+*/
+static int me4600_ao_io_stream_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags);
+
+/** Check actual state. / Wait for end.
+*/
+static int me4600_ao_io_stream_status(me_subdevice_t * subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *values, int flags);
+
+/** Stop streaming.
+*/
+static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int stop_mode, int flags);
+
+/** Write datas to buffor.
+*/
+static int me4600_ao_io_stream_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int write_mode,
+ int *values, int *count, int flags);
+
+/** Interrupt handler. Copy from buffer to FIFO.
+*/
+static irqreturn_t me4600_ao_isr(int irq, void *dev_id
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+ , struct pt_regs *regs
+#endif
+ );
+/** Copy data from circular buffer to fifo (fast) in wraparound mode.
+*/
+int inline ao_write_data_wraparound(me4600_ao_subdevice_t * instance, int count,
+ int start_pos);
+
+/** Copy data from circular buffer to fifo (fast).
+*/
+int inline ao_write_data(me4600_ao_subdevice_t * instance, int count,
+ int start_pos);
+
+/** Copy data from circular buffer to fifo (slow).
+*/
+int inline ao_write_data_pooling(me4600_ao_subdevice_t * instance, int count,
+ int start_pos);
+
+/** Copy data from user space to circular buffer.
+*/
+int inline ao_get_data_from_user(me4600_ao_subdevice_t * instance, int count,
+ int *user_values);
+
+/** Stop presentation. Preserve FIFOs.
+*/
+int inline ao_stop_immediately(me4600_ao_subdevice_t * instance);
+
+/** Task for asynchronical state verifying.
+*/
+static void me4600_ao_work_control_task(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ void *subdevice
+#else
+ struct work_struct *work
+#endif
+ );
+/* Functions
+ */
+
+static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t tmp;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ instance->status = ao_status_none;
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ instance->timeout.delay = 0;
+ instance->timeout.start_time = jiffies;
+
+ //Stop state machine.
+ err = ao_stop_immediately(instance);
+
+ //Remove from synchronous start.
+ spin_lock(instance->preload_reg_lock);
+ tmp = inl(instance->preload_reg);
+ tmp &=
+ ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->
+ ao_idx);
+ outl(tmp, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, tmp);
+ *instance->preload_flags &=
+ ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->
+ ao_idx);
+ spin_unlock(instance->preload_reg_lock);
+
+ //Set single mode, dissable FIFO, dissable external trigger, set output to analog, block interrupt.
+ outl(ME4600_AO_MODE_SINGLE | ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_RESET_IRQ,
+ instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ME4600_AO_MODE_SINGLE | ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP |
+ ME4600_AO_CTRL_BIT_RESET_IRQ);
+
+ //Set output to 0V
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->single_reg - instance->reg_base, 0x8000);
+
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ instance->single_value = 0x8000;
+ instance->single_value_in_fifo = 0x8000;
+
+ //Set status to signal that device is unconfigured.
+ instance->status = ao_status_none;
+
+ //Signal reset if user is on wait.
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t ctrl;
+ uint32_t sync;
+ unsigned long cpu_flags;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ // Checking parameters
+ if (flags) {
+ PERROR
+ ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ switch (trig_type) {
+ case ME_TRIG_TYPE_SW:
+ if (trig_edge != ME_TRIG_EDGE_NONE) {
+ PERROR
+ ("Invalid trigger edge. Software trigger has not edge.\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ switch (trig_edge) {
+ case ME_TRIG_EDGE_ANY:
+ case ME_TRIG_EDGE_RISING:
+ case ME_TRIG_EDGE_FALLING:
+ break;
+
+ default:
+ PERROR("Invalid trigger edge.\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+ break;
+
+ default:
+ PERROR
+ ("Invalid trigger type. Trigger must be software or digital.\n");
+ return ME_ERRNO_INVALID_TRIG_TYPE;
+ }
+
+ if ((trig_chan != ME_TRIG_CHAN_DEFAULT)
+ && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) {
+ PERROR("Invalid trigger channel specified.\n");
+ return ME_ERRNO_INVALID_TRIG_CHAN;
+ }
+
+ if (ref != ME_REF_AO_GROUND) {
+ PERROR
+ ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if (single_config != 0) {
+ PERROR
+ ("Invalid single config specified. Only one range for anlog outputs is available.\n");
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+
+ if (channel != 0) {
+ PERROR
+ ("Invalid channel number specified. Analog output have only one channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ //Subdevice running in stream mode!
+ if ((instance->status >= ao_status_stream_run_wait)
+ && (instance->status < ao_status_stream_end)) {
+ PERROR("Subdevice is busy.\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+/// @note For single all calls (config and write) are erasing previous state!
+
+ instance->status = ao_status_none;
+
+ // Correct single mirrors
+ instance->single_value_in_fifo = instance->single_value;
+
+ //Stop device
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+ // Set control register.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ // Set stop bit. Stop streaming mode.
+ ctrl = inl(instance->ctrl_reg);
+ //Reset all bits.
+ ctrl = ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP;
+
+ if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) {
+ PINFO("External digital trigger.\n");
+
+ if (trig_edge == ME_TRIG_EDGE_ANY) {
+// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ instance->ctrl_trg =
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ } else if (trig_edge == ME_TRIG_EDGE_FALLING) {
+// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE;
+ instance->ctrl_trg = ME4600_AO_CTRL_BIT_EX_TRIG_EDGE;
+ } else if (trig_edge == ME_TRIG_EDGE_RISING) {
+ instance->ctrl_trg = 0x0;
+ }
+ } else if (trig_type == ME_TRIG_TYPE_SW) {
+ PDEBUG("Software trigger\n");
+ instance->ctrl_trg = 0x0;
+ }
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ // Set preload/synchronization register.
+ spin_lock(instance->preload_reg_lock);
+ if (trig_type == ME_TRIG_TYPE_SW) {
+ *instance->preload_flags &=
+ ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx);
+ } else //if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL)
+ {
+ *instance->preload_flags |=
+ ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx;
+ }
+
+ if (trig_chan == ME_TRIG_CHAN_DEFAULT) {
+ *instance->preload_flags &=
+ ~(ME4600_AO_SYNC_HOLD << instance->ao_idx);
+ } else //if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS)
+ {
+ *instance->preload_flags |=
+ ME4600_AO_SYNC_HOLD << instance->ao_idx;
+ }
+
+ //Reset hardware register
+ sync = inl(instance->preload_reg);
+ PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, sync);
+ sync &= ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx);
+ sync |= ME4600_AO_SYNC_HOLD << instance->ao_idx;
+
+ //Output configured in default (safe) mode.
+ outl(sync, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, sync);
+ spin_unlock(instance->preload_reg_lock);
+
+ instance->status = ao_status_single_configured;
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ unsigned long j;
+ unsigned long delay = 0;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags & ~ME_IO_SINGLE_NONBLOCKING) {
+ PERROR("Invalid flag specified. %d\n", flags);
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (channel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if ((instance->status >= ao_status_stream_configured)
+ && (instance->status <= ao_status_stream_end)) {
+ PERROR("Subdevice not configured to work in single mode!\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ ME_SUBDEVICE_ENTER;
+ if ((!flags) && (instance->status == ao_status_single_run_wait)) { //Blocking mode. Wait for trigger.
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+ if (delay == 0)
+ delay = 1;
+ }
+
+ j = jiffies;
+
+ //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_single_run_wait),
+ (delay) ? delay +
+ 1 : LONG_MAX);
+
+ if (instance->status == ao_status_none) {
+ PDEBUG("Single canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ if ((delay) && ((jiffies - j) >= delay)) {
+
+ PDEBUG("Timeout reached.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+
+ *value =
+ (!err) ? instance->single_value_in_fifo : instance->
+ single_value;
+ } else { //Non-blocking mode
+ //Read value
+ *value = instance->single_value;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags;
+ unsigned long j;
+ unsigned long delay = 0x0;
+
+ //Registry handling variables.
+ uint32_t sync_mask;
+ uint32_t mode;
+ uint32_t tmp;
+ uint32_t ctrl;
+ uint32_t status;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags &
+ ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS |
+ ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (value & ~ME4600_AO_MAX_DATA) {
+ PERROR("Invalid value provided.\n");
+ return ME_ERRNO_VALUE_OUT_OF_RANGE;
+ }
+
+ if (channel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if ((instance->status == ao_status_none)
+ || (instance->status > ao_status_single_end)) {
+ PERROR("Subdevice not configured to work in single mode!\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+/// @note For single all calls (config and write) are erasing previous state!
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+
+ // Correct single mirrors
+ instance->single_value_in_fifo = instance->single_value;
+
+ //Stop device
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+
+ if (delay == 0)
+ delay = 1;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ instance->single_value_in_fifo = value;
+
+ ctrl = inl(instance->ctrl_reg);
+
+ if (!instance->fifo) { //No FIFO
+ //Set the single mode.
+ ctrl &= ~ME4600_AO_CTRL_MODE_MASK;
+
+ //Write value
+ PDEBUG("Write value\n");
+ outl(value, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base, value);
+ } else { // mix-mode
+ //Set speed
+ outl(ME4600_AO_MIN_CHAN_TICKS - 1, instance->timer_reg);
+ PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->timer_reg - instance->reg_base,
+ (int)ME4600_AO_MIN_CHAN_TICKS);
+ instance->hardware_stop_delay = HZ / 10; //100ms
+
+ status = inl(instance->status_reg);
+
+ //Set the continous mode.
+ ctrl &= ~ME4600_AO_CTRL_MODE_MASK;
+ ctrl |= ME4600_AO_MODE_CONTINUOUS;
+
+ //Prepare FIFO
+ if (!(ctrl & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it.
+ PINFO("Enableing FIFO.\n");
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |=
+ ME4600_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+ } else { //Check if FIFO is empty
+ if (status & ME4600_AO_STATUS_BIT_EF) { //FIFO not empty
+ PINFO("Reseting FIFO.\n");
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4600_AO_CTRL_BIT_ENABLE_IRQ);
+ ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg -
+ instance->reg_base, ctrl);
+
+ ctrl |=
+ ME4600_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+ } else { //FIFO empty, only interrupt needs to be disabled!
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+ }
+ }
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Write output - 1 value to FIFO
+ if (instance->ao_idx & 0x1) {
+ outl(value <<= 16, instance->fifo_reg);
+ PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->fifo_reg - instance->reg_base,
+ value <<= 16);
+ } else {
+ outl(value, instance->fifo_reg);
+ PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->fifo_reg - instance->reg_base,
+ value);
+ }
+ }
+
+ mode = *instance->preload_flags >> instance->ao_idx;
+ mode &= (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG);
+
+ PINFO("Triggering mode: 0x%x\n", mode);
+
+ spin_lock(instance->preload_reg_lock);
+ sync_mask = inl(instance->preload_reg);
+ PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, sync_mask);
+ switch (mode) {
+ case 0: //Individual software
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+ if (!instance->fifo) { // No FIFO - In this case resetting 'ME4600_AO_SYNC_HOLD' will trigger output.
+ if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME4600_AO_SYNC_HOLD) { //Now we can set correct mode. This is exception. It is set to synchronous and triggered later.
+ sync_mask &=
+ ~(ME4600_AO_SYNC_EXT_TRIG << instance->
+ ao_idx);
+ sync_mask |=
+ ME4600_AO_SYNC_HOLD << instance->ao_idx;
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ } else { // FIFO
+ if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode.
+ sync_mask &=
+ ~((ME4600_AO_SYNC_EXT_TRIG |
+ ME4600_AO_SYNC_HOLD) << instance->
+ ao_idx);
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ }
+ instance->single_value = value;
+ break;
+
+ case ME4600_AO_SYNC_EXT_TRIG: //Individual hardware
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+ if (!instance->fifo) { // No FIFO - In this case resetting 'ME4600_AO_SYNC_HOLD' will trigger output.
+ if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME4600_AO_SYNC_HOLD) { //Now we can set correct mode
+ sync_mask &=
+ ~(ME4600_AO_SYNC_EXT_TRIG << instance->
+ ao_idx);
+ sync_mask |=
+ ME4600_AO_SYNC_HOLD << instance->ao_idx;
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ } else { // FIFO
+ if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode.
+ sync_mask &=
+ ~((ME4600_AO_SYNC_EXT_TRIG |
+ ME4600_AO_SYNC_HOLD) << instance->
+ ao_idx);
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ }
+ break;
+
+ case ME4600_AO_SYNC_HOLD: //Synchronous software
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+// if((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME4600_AO_SYNC_HOLD)
+ if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG)) { //Now we can set correct mode
+ sync_mask |=
+ ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx;
+// sync_mask &= ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx);
+ sync_mask |= ME4600_AO_SYNC_HOLD << instance->ao_idx;
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ break;
+
+ case (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG): //Synchronous hardware
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG)) { //Now we can set correct mode
+ sync_mask |=
+ (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx;
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ break;
+ }
+// spin_unlock(instance->preload_reg_lock); // Moved down.
+
+ //Activate ISM (remove 'stop' bits)
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH);
+ ctrl |= instance->ctrl_trg;
+ ctrl &= ~(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+/// @note When flag 'ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS' is set than output is triggered. ALWAYS!
+
+ if (!instance->fifo) { //No FIFO
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Fired all software synchronous outputs.
+ tmp = ~(*instance->preload_flags | 0xFFFF0000);
+ PINFO
+ ("Fired all software synchronous outputs. mask:0x%08x\n",
+ tmp);
+ tmp |= sync_mask & 0xFFFF0000;
+ // Add this channel to list
+ tmp &= ~(ME4600_AO_SYNC_HOLD << instance->ao_idx);
+
+ //Fire
+ PINFO("Software trigger.\n");
+ outl(tmp, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ tmp);
+
+ //Restore save settings
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ } else if (!mode) { // Add this channel to list
+ outl(sync_mask &
+ ~(ME4600_AO_SYNC_HOLD << instance->ao_idx),
+ instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask & ~(ME4600_AO_SYNC_HOLD <<
+ instance->ao_idx));
+
+ //Fire
+ PINFO("Software trigger.\n");
+
+ //Restore save settings
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+
+ } else { // mix-mode - begin
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs
+ //Add channel to start list
+ outl(sync_mask |
+ (ME4600_AO_SYNC_HOLD << instance->ao_idx),
+ instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask | (ME4600_AO_SYNC_HOLD <<
+ instance->ao_idx));
+
+ //Fire
+ PINFO
+ ("Fired all software synchronous outputs by software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base,
+ 0x8000);
+
+ //Restore save settings
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ } else if (!mode) { //Trigger outputs
+/* //Remove channel from start list //<== Unnecessary. Removed.
+ outl(sync_mask & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, tmp);
+*/
+ //Fire
+ PINFO("Software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base,
+ 0x8000);
+
+/* //Restore save settings //<== Unnecessary. Removed.
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask);
+*/
+ }
+ }
+ spin_unlock(instance->preload_reg_lock);
+
+ j = jiffies;
+ instance->status = ao_status_single_run_wait;
+
+ instance->timeout.delay = delay;
+ instance->timeout.start_time = j;
+ instance->ao_control_task_flag = 1;
+ queue_delayed_work(instance->me4600_workqueue,
+ &instance->ao_control_task, 1);
+
+ if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) {
+
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_single_run_wait),
+ (delay) ? delay +
+ 1 : LONG_MAX);
+
+ if (((!delay) || ((jiffies - j) <= delay))
+ && (instance->status != ao_status_single_end)) {
+ PDEBUG("Single canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ ao_stop_immediately(instance);
+ instance->status = ao_status_none;
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ if ((delay) && ((jiffies - j) >= delay)) {
+ if (instance->status == ao_status_single_end) {
+ PDEBUG("Timeout reached.\n");
+ } else {
+ if ((jiffies - j) > delay) {
+ PERROR
+ ("Timeout reached. Not handled by control task!\n");
+ } else {
+ PERROR
+ ("Timeout reached. Signal come but status is strange: %d\n",
+ instance->status);
+ }
+
+ ao_stop_immediately(instance);
+ }
+
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ instance->status = ao_status_single_end;
+ err = ME_ERRNO_TIMEOUT;
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t ctrl;
+ unsigned long cpu_flags;
+ uint64_t conv_ticks;
+ unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow;
+ unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ conv_ticks =
+ (uint64_t) conv_start_ticks_low +
+ ((uint64_t) conv_start_ticks_high << 32);
+
+ if (flags &
+ ~(ME_IO_STREAM_CONFIG_HARDWARE_ONLY | ME_IO_STREAM_CONFIG_WRAPAROUND
+ | ME_IO_STREAM_CONFIG_BIT_PATTERN)) {
+ PERROR("Invalid flags.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) {
+ if (!flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ PERROR
+ ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((trigger->iAcqStopTrigType != ME_TRIG_TYPE_NONE)
+ || (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE)) {
+ PERROR
+ ("Hardware wraparound mode must be in infinite mode.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+ }
+
+ if (count != 1) {
+ PERROR("Only 1 entry in config list acceptable.\n");
+ return ME_ERRNO_INVALID_CONFIG_LIST_COUNT;
+ }
+
+ if (config_list[0].iChannel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (config_list[0].iStreamConfig != 0) {
+ PERROR("Only one range available.\n");
+ return ME_ERRNO_INVALID_STREAM_CONFIG;
+ }
+
+ if (config_list[0].iRef != ME_REF_AO_GROUND) {
+ PERROR("Output is referenced to ground.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if ((trigger->iAcqStartTicksLow != 0)
+ || (trigger->iAcqStartTicksHigh != 0)) {
+ PERROR
+ ("Invalid acquisition start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_ARG;
+ }
+
+ if (config_list[0].iFlags) {
+ PERROR("Invalid config list flag.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ switch (trigger->iAcqStartTrigType) {
+ case ME_TRIG_TYPE_SW:
+ if (trigger->iAcqStartTrigEdge != ME_TRIG_EDGE_NONE) {
+ PERROR
+ ("Invalid acquisition start trigger edge specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+ }
+ break;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ switch (trigger->iAcqStartTrigEdge) {
+ case ME_TRIG_EDGE_ANY:
+ case ME_TRIG_EDGE_RISING:
+ case ME_TRIG_EDGE_FALLING:
+ break;
+
+ default:
+ PERROR
+ ("Invalid acquisition start trigger edge specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+ }
+ break;
+
+ default:
+ PERROR("Invalid acquisition start trigger type specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE;
+ }
+
+ if (trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) {
+ PERROR("Invalid scan start trigger type specified.\n");
+ return ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE;
+ }
+
+ if (trigger->iConvStartTrigType != ME_TRIG_TYPE_TIMER) {
+ PERROR("Invalid conv start trigger type specified.\n");
+ return ME_ERRNO_INVALID_CONV_START_TRIG_TYPE;
+ }
+
+ if ((conv_ticks < ME4600_AO_MIN_CHAN_TICKS)
+ || (conv_ticks > ME4600_AO_MAX_CHAN_TICKS)) {
+ PERROR("Invalid conv start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_CONV_START_ARG;
+ }
+
+ if (trigger->iAcqStartTicksLow || trigger->iAcqStartTicksHigh) {
+ PERROR("Invalid acq start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_ARG;
+ }
+
+ if (trigger->iScanStartTicksLow || trigger->iScanStartTicksHigh) {
+ PERROR("Invalid scan start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_SCAN_START_ARG;
+ }
+
+ switch (trigger->iScanStopTrigType) {
+ case ME_TRIG_TYPE_NONE:
+ if (trigger->iScanStopCount != 0) {
+ PERROR("Invalid scan stop count specified.\n");
+ return ME_ERRNO_INVALID_SCAN_STOP_ARG;
+ }
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ if (trigger->iScanStopCount <= 0) {
+ PERROR("Invalid scan stop count specified.\n");
+ return ME_ERRNO_INVALID_SCAN_STOP_ARG;
+ }
+ } else {
+ PERROR("The continous mode has not 'scan' contects.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ }
+ break;
+
+ default:
+ PERROR("Invalid scan stop trigger type specified.\n");
+ return ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE;
+ }
+
+ switch (trigger->iAcqStopTrigType) {
+ case ME_TRIG_TYPE_NONE:
+ if (trigger->iAcqStopCount != 0) {
+ PERROR("Invalid acq stop count specified.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_ARG;
+ }
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) {
+ PERROR("Invalid acq stop trigger type specified.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ }
+
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ if (trigger->iAcqStopCount <= 0) {
+ PERROR
+ ("The continous mode has not 'scan' contects.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_ARG;
+ }
+ }
+ break;
+
+ default:
+ PERROR("Invalid acq stop trigger type specified.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ }
+
+ switch (trigger->iAcqStartTrigChan) {
+ case ME_TRIG_CHAN_DEFAULT:
+ case ME_TRIG_CHAN_SYNCHRONOUS:
+ break;
+
+ default:
+ PERROR("Invalid acq start trigger channel specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if ((flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) && !instance->bitpattern) {
+ PERROR("This subdevice not support output redirection.\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+ //Stop device
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+
+ //Check if state machine is stopped.
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ //Reset control register. Block all actions. Disable IRQ. Disable FIFO.
+ ctrl =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //This is paranoic, but to be sure.
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+
+ /* Set mode. */
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { //Wraparound
+ if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { //Hardware wraparound
+ PINFO("Hardware wraparound.\n");
+ ctrl |= ME4600_AO_MODE_WRAPAROUND;
+ instance->mode = ME4600_AO_HW_WRAP_MODE;
+ } else { //Software wraparound
+ PINFO("Software wraparound.\n");
+ ctrl |= ME4600_AO_MODE_CONTINUOUS;
+ instance->mode = ME4600_AO_SW_WRAP_MODE;
+ }
+ } else { //Continous
+ PINFO("Continous.\n");
+ ctrl |= ME4600_AO_MODE_CONTINUOUS;
+ instance->mode = ME4600_AO_CONTINOUS;
+ }
+
+ //Set the trigger edge.
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Set the trigger type and edge for external trigger.
+ PINFO("External digital trigger.\n");
+ instance->start_mode = ME4600_AO_EXT_TRIG;
+/*
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+*/
+ switch (trigger->iAcqStartTrigEdge) {
+ case ME_TRIG_EDGE_RISING:
+ PINFO("Set the trigger edge: rising.\n");
+ instance->ctrl_trg = 0x0;
+ break;
+
+ case ME_TRIG_EDGE_FALLING:
+ PINFO("Set the trigger edge: falling.\n");
+// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE;
+ instance->ctrl_trg = ME4600_AO_CTRL_BIT_EX_TRIG_EDGE;
+ break;
+
+ case ME_TRIG_EDGE_ANY:
+ PINFO("Set the trigger edge: both edges.\n");
+// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ instance->ctrl_trg =
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ break;
+ }
+ } else {
+ PINFO("Internal software trigger.\n");
+ instance->start_mode = 0;
+ }
+
+ //Set the stop mode and value.
+ if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of data
+ instance->stop_mode = ME4600_AO_ACQ_STOP_MODE;
+ instance->stop_count = trigger->iAcqStopCount;
+ } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of 'scans'
+ instance->stop_mode = ME4600_AO_SCAN_STOP_MODE;
+ instance->stop_count = trigger->iScanStopCount;
+ } else { //Infinite
+ instance->stop_mode = ME4600_AO_INF_STOP_MODE;
+ instance->stop_count = 0;
+ }
+
+ PINFO("Stop count: %d.\n", instance->stop_count);
+
+ if (trigger->iAcqStartTrigChan == ME_TRIG_CHAN_SYNCHRONOUS) { //Synchronous start
+ instance->start_mode |= ME4600_AO_SYNC_HOLD;
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Externaly triggered
+ PINFO("Synchronous start. Externaly trigger active.\n");
+ instance->start_mode |= ME4600_AO_SYNC_EXT_TRIG;
+ }
+#ifdef MEDEBUG_INFO
+ else {
+ PINFO
+ ("Synchronous start. Externaly trigger dissabled.\n");
+ }
+#endif
+
+ }
+ //Set speed
+ outl(conv_ticks - 2, instance->timer_reg);
+ PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%llx\n", instance->reg_base,
+ instance->timer_reg - instance->reg_base, conv_ticks - 2);
+ instance->hardware_stop_delay = (int)(conv_ticks * HZ) / ME4600_AO_BASE_FREQUENCY; //<== MUST be with cast!
+
+ //Conect outputs to analog or digital port.
+ if (flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) {
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_DO;
+ }
+ // Write the control word
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Set status.
+ instance->status = ao_status_stream_configured;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice,
+ struct file *filep,
+ int time_out, int *count, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ long j;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!instance->circ_buf.buf) {
+ PERROR("Circular buffer not exists.\n");
+ return ME_ERRNO_INTERNAL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (me_circ_buf_space(&instance->circ_buf)) { //The buffer is NOT full.
+ *count = me_circ_buf_space(&instance->circ_buf);
+ } else { //The buffer is full.
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ } else { //Max time.
+ t = LONG_MAX;
+ }
+
+ *count = 0;
+
+ j = jiffies;
+
+ //Only runing process will interrupt this call. Interrupts are when FIFO HF is signaled.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ ((me_circ_buf_space
+ (&instance->circ_buf))
+ || !(inl(instance->status_reg)
+ &
+ ME4600_AO_STATUS_BIT_FSM)),
+ t);
+
+ if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) {
+ PERROR("AO subdevice is not running.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ } else if (signal_pending(current)) {
+ PERROR("Wait on values interrupted from signal.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ } else if ((jiffies - j) >= t) {
+ PERROR("Wait on values timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ } else { //Uff... all is good. Inform user about empty space.
+ *count = me_circ_buf_space(&instance->circ_buf);
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags = 0;
+ uint32_t status;
+ uint32_t ctrl;
+ uint32_t synch;
+ int count = 0;
+ int circ_buffer_count;
+
+ unsigned long ref;
+ unsigned long delay = 0;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags & ~ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) {
+ PERROR("Invalid flags.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if ((start_mode != ME_START_MODE_BLOCKING)
+ && (start_mode != ME_START_MODE_NONBLOCKING)) {
+ PERROR("Invalid start mode specified.\n");
+ return ME_ERRNO_INVALID_START_MODE;
+ }
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+ if (delay == 0)
+ delay = 1;
+ }
+
+ switch (instance->status) { //Checking actual mode.
+ case ao_status_stream_configured:
+ case ao_status_stream_end:
+ //Correct modes!
+ break;
+
+ //The device is in wrong mode.
+ case ao_status_none:
+ case ao_status_single_configured:
+ case ao_status_single_run_wait:
+ case ao_status_single_run:
+ case ao_status_single_end_wait:
+ PERROR
+ ("Subdevice must be preinitialize correctly for streaming.\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+
+ case ao_status_stream_fifo_error:
+ case ao_status_stream_buffer_error:
+ case ao_status_stream_error:
+ PDEBUG("Before restart broke stream 'STOP' must be caled.\n");
+ return ME_STATUS_ERROR;
+
+ case ao_status_stream_run_wait:
+ case ao_status_stream_run:
+ case ao_status_stream_end_wait:
+ PDEBUG("Stream is already working.\n");
+ return ME_ERRNO_SUBDEVICE_BUSY;
+
+ default:
+ instance->status = ao_status_stream_error;
+ PERROR_CRITICAL("Status is in wrong state!\n");
+ return ME_ERRNO_INTERNAL;
+
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->mode == ME4600_AO_CONTINOUS) { //Continous
+ instance->circ_buf.tail += instance->preloaded_count;
+ instance->circ_buf.tail &= instance->circ_buf.mask;
+ }
+ circ_buffer_count = me_circ_buf_values(&instance->circ_buf);
+
+ if (!circ_buffer_count && !instance->preloaded_count) { //No values in buffer
+ ME_SUBDEVICE_EXIT;
+ PERROR("No values in buffer!\n");
+ return ME_ERRNO_LACK_OF_RESOURCES;
+ }
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+
+ //Stop device
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+ //Set values for single_read()
+ instance->single_value = ME4600_AO_MAX_DATA + 1;
+ instance->single_value_in_fifo = ME4600_AO_MAX_DATA + 1;
+
+ //Setting stop points
+ if (instance->stop_mode == ME4600_AO_SCAN_STOP_MODE) {
+ instance->stop_data_count =
+ instance->stop_count * circ_buffer_count;
+ } else {
+ instance->stop_data_count = instance->stop_count;
+ }
+
+ if ((instance->stop_data_count != 0)
+ && (instance->stop_data_count < circ_buffer_count)) {
+ PERROR("More data in buffer than previously set limit!\n");
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ //Check FIFO
+ if (!(ctrl & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. <= This should be done by user call with ME_WRITE_MODE_PRELOAD
+ PINFO("Enableing FIFO.\n");
+ ctrl |=
+ ME4600_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ } else { //Block IRQ
+ ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl | ME4600_AO_CTRL_BIT_RESET_IRQ);
+
+ //Fill FIFO <= Generaly this should be done by user pre-load call but this is second place to do it.
+ status = inl(instance->status_reg);
+ if (!(status & ME4600_AO_STATUS_BIT_EF)) { //FIFO empty
+ if (instance->stop_data_count == 0) {
+ count = ME4600_AO_FIFO_COUNT;
+ } else {
+ count =
+ (ME4600_AO_FIFO_COUNT <
+ instance->
+ stop_data_count) ? ME4600_AO_FIFO_COUNT :
+ instance->stop_data_count;
+ }
+
+ //Copy data
+ count =
+ ao_write_data(instance, count, instance->preloaded_count);
+
+ if (count < 0) { //This should never happend!
+ PERROR_CRITICAL("COPY FINISH WITH ERROR!\n");
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ }
+ //Set pre-load features.
+ spin_lock(instance->preload_reg_lock);
+ synch = inl(instance->preload_reg);
+ synch &=
+ ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->
+ ao_idx);
+ synch |=
+ (instance->start_mode & ~ME4600_AO_EXT_TRIG) << instance->ao_idx;
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, synch);
+ spin_unlock(instance->preload_reg_lock);
+
+ //Default count is '0'
+ if (instance->mode == ME4600_AO_CONTINOUS) { //Continous
+ instance->preloaded_count = 0;
+ instance->circ_buf.tail += count;
+ instance->circ_buf.tail &= instance->circ_buf.mask;
+ } else { //Wraparound
+ instance->preloaded_count += count;
+ instance->data_count += count;
+
+ //Special case: Infinite wraparound with less than FIFO datas always should runs in hardware mode.
+ if ((instance->stop_mode == ME4600_AO_INF_STOP_MODE)
+ && (circ_buffer_count <= ME4600_AO_FIFO_COUNT)) { //Change to hardware wraparound
+ PDEBUG
+ ("Changeing mode from software wraparound to hardware wraparound.\n");
+ //Copy all data
+ count =
+ ao_write_data(instance, circ_buffer_count,
+ instance->preloaded_count);
+ ctrl &= ~ME4600_AO_CTRL_MODE_MASK;
+ ctrl |= ME4600_AO_MODE_WRAPAROUND;
+ }
+
+ if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator.
+ instance->preloaded_count = 0;
+ } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend!
+ PERROR_CRITICAL
+ ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n");
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ }
+
+ //Set status to 'wait for start'
+ instance->status = ao_status_stream_run_wait;
+
+ status = inl(instance->status_reg);
+ //Start state machine and interrupts
+ ctrl &= ~(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ if (instance->start_mode == ME4600_AO_EXT_TRIG) { // External trigger.
+ PINFO("External trigger.\n");
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ }
+ if (!(status & ME4600_AO_STATUS_BIT_HF)) { //More than half!
+ if ((ctrl & ME4600_AO_CTRL_MODE_MASK) == ME4600_AO_MODE_CONTINUOUS) { //Enable IRQ only when hardware_continous is set and FIFO is more than half
+ ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ }
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ //Trigger output
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs
+ spin_lock(instance->preload_reg_lock);
+ synch = inl(instance->preload_reg);
+ //Add channel to start list
+ outl(synch | (ME4600_AO_SYNC_HOLD << instance->ao_idx),
+ instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ synch | (ME4600_AO_SYNC_HOLD << instance->ao_idx));
+
+ //Fire
+ PINFO
+ ("Fired all software synchronous outputs by software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base, 0x8000);
+
+ //Restore save settings
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base, synch);
+ spin_unlock(instance->preload_reg_lock);
+ } else if (!instance->start_mode) { //Trigger outputs
+/*
+ //Remove channel from start list. // <== Unnecessary. Removed.
+ spin_lock(instance->preload_reg_lock);
+ synch = inl(instance->preload_reg);
+ outl(synch & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx));
+*/
+ //Fire
+ PINFO("Software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base, 0x8000);
+
+/*
+ //Restore save settings. // <== Unnecessary. Removed.
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch);
+ spin_unlock(instance->preload_reg_lock);
+*/
+ }
+ // Set control task's timeout
+ ref = jiffies;
+ instance->timeout.delay = delay;
+ instance->timeout.start_time = ref;
+
+ if (status & ME4600_AO_STATUS_BIT_HF) { //Less than half but not empty!
+ PINFO("Less than half.\n");
+ if (instance->stop_data_count != 0) {
+ count = ME4600_AO_FIFO_COUNT / 2;
+ } else {
+ count =
+ ((ME4600_AO_FIFO_COUNT / 2) <
+ instance->stop_data_count) ? ME4600_AO_FIFO_COUNT /
+ 2 : instance->stop_data_count;
+ }
+
+ //Copy data
+ count =
+ ao_write_data(instance, count, instance->preloaded_count);
+
+ if (count < 0) { //This should never happend!
+ PERROR_CRITICAL("COPY FINISH WITH ERROR!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+
+ if (instance->mode == ME4600_AO_CONTINOUS) { //Continous
+ instance->circ_buf.tail += count;
+ instance->circ_buf.tail &= instance->circ_buf.mask;
+ } else { //Wraparound
+ instance->data_count += count;
+ instance->preloaded_count += count;
+
+ if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator.
+ instance->preloaded_count = 0;
+ } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend!
+ PERROR_CRITICAL
+ ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME4600_AO_STATUS_BIT_HF)) { //More than half!
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ }
+ }
+ //Special case: Limited wraparound with less than HALF FIFO datas need work around to generate first interrupt.
+ if ((instance->stop_mode != ME4600_AO_INF_STOP_MODE)
+ && (instance->mode == ME4600_AO_SW_WRAP_MODE)
+ && (circ_buffer_count <= (ME4600_AO_FIFO_COUNT / 2))) { //Put more data to FIFO
+ PINFO("Limited wraparound with less than HALF FIFO datas.\n");
+ if (instance->preloaded_count) { //This should never happend!
+ PERROR_CRITICAL
+ ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+
+ while (instance->stop_data_count > instance->data_count) { //Maximum data not set jet.
+ //Copy to buffer
+ if (circ_buffer_count != ao_write_data(instance, circ_buffer_count, 0)) { //This should never happend!
+ PERROR_CRITICAL
+ ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ instance->data_count += circ_buffer_count;
+
+ if (!((status = inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_HF)) { //FIFO is more than half. Enable IRQ and end copy.
+ spin_lock_irqsave(&instance->subdevice_lock,
+ cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg -
+ instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ break;
+ }
+ }
+ }
+ // Schedule control task.
+ instance->ao_control_task_flag = 1;
+ queue_delayed_work(instance->me4600_workqueue,
+ &instance->ao_control_task, 1);
+
+ if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start.
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_stream_run_wait),
+ (delay) ? delay +
+ 1 : LONG_MAX);
+
+ if ((instance->status != ao_status_stream_run)
+ && (instance->status != ao_status_stream_end)) {
+ PDEBUG("Starting stream canceled. %d\n",
+ instance->status);
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ } else if ((delay) && ((jiffies - ref) >= delay)) {
+ if (instance->status != ao_status_stream_run) {
+ if (instance->status == ao_status_stream_end) {
+ PDEBUG("Timeout reached.\n");
+ } else {
+ if ((jiffies - ref) > delay) {
+ PERROR
+ ("Timeout reached. Not handled by control task!\n");
+ } else {
+ PERROR
+ ("Timeout reached. Signal come but status is strange: %d\n",
+ instance->status);
+ }
+ ao_stop_immediately(instance);
+ }
+
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ instance->status = ao_status_stream_end;
+ err = ME_ERRNO_TIMEOUT;
+ }
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+ return err;
+}
+
+static int me4600_ao_io_stream_status(me_subdevice_t * subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *values, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((wait != ME_WAIT_NONE) && (wait != ME_WAIT_IDLE)) {
+ PERROR("Invalid wait argument specified.\n");
+ *status = ME_STATUS_INVALID;
+ return ME_ERRNO_INVALID_WAIT;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ switch (instance->status) {
+ case ao_status_single_configured:
+ case ao_status_single_end:
+ case ao_status_stream_configured:
+ case ao_status_stream_end:
+ case ao_status_stream_fifo_error:
+ case ao_status_stream_buffer_error:
+ case ao_status_stream_error:
+ *status = ME_STATUS_IDLE;
+ break;
+
+ case ao_status_single_run_wait:
+ case ao_status_single_run:
+ case ao_status_single_end_wait:
+ case ao_status_stream_run_wait:
+ case ao_status_stream_run:
+ case ao_status_stream_end_wait:
+ *status = ME_STATUS_BUSY;
+ break;
+
+ case ao_status_none:
+ default:
+ *status =
+ (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ?
+ ME_STATUS_BUSY : ME_STATUS_IDLE;
+ break;
+ }
+
+ if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) {
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ ((instance->status !=
+ ao_status_single_run_wait)
+ && (instance->status !=
+ ao_status_single_run)
+ && (instance->status !=
+ ao_status_single_end_wait)
+ && (instance->status !=
+ ao_status_stream_run_wait)
+ && (instance->status !=
+ ao_status_stream_run)
+ && (instance->status !=
+ ao_status_stream_end_wait)),
+ LONG_MAX);
+
+ if (instance->status != ao_status_stream_end) {
+ PDEBUG("Wait for IDLE canceled. %d\n",
+ instance->status);
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait for IDLE interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ *status = ME_STATUS_IDLE;
+ }
+
+ *values = me_circ_buf_space(&instance->circ_buf);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int stop_mode, int flags)
+{ // Stop work and empty buffer and FIFO
+ int err = ME_ERRNO_SUCCESS;
+ me4600_ao_subdevice_t *instance;
+ unsigned long cpu_flags;
+ volatile uint32_t ctrl;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags & ~ME_IO_STREAM_STOP_PRESERVE_BUFFERS) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((stop_mode != ME_STOP_MODE_IMMEDIATE)
+ && (stop_mode != ME_STOP_MODE_LAST_VALUE)) {
+ PERROR("Invalid stop mode specified.\n");
+ return ME_ERRNO_INVALID_STOP_MODE;
+ }
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (instance->status < ao_status_stream_configured) {
+ //There is nothing to stop!
+ PERROR("Subdevice not in streaming mode. %d\n",
+ instance->status);
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ //Mark as stopping. => Software stop.
+ instance->status = ao_status_stream_end_wait;
+
+ if (stop_mode == ME_STOP_MODE_IMMEDIATE) { //Stopped now!
+ err = ao_stop_immediately(instance);
+ } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) {
+ ctrl = inl(instance->ctrl_reg) & ME4600_AO_CTRL_MODE_MASK;
+ if (ctrl == ME4600_AO_MODE_WRAPAROUND) { //Hardware wraparound => Hardware stop.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ }
+ //Only runing process will interrupt this call. Events are signaled when status change.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_stream_end_wait),
+ LONG_MAX);
+
+ if (instance->status != ao_status_stream_end) {
+ PDEBUG("Stopping stream canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Stopping stream interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ if (!flags) { //Reset FIFO
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO;
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ if (!flags) { //Reset software buffer
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int write_mode,
+ int *values, int *count, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me4600_ao_subdevice_t *instance;
+ unsigned long cpu_flags = 0;
+ uint32_t reg_copy;
+
+ int copied_from_user = 0;
+ int left_to_copy_from_user = *count;
+
+ int copied_values;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ //Checking arguments
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (*count <= 0) {
+ PERROR("Invalid count of values specified.\n");
+ return ME_ERRNO_INVALID_VALUE_COUNT;
+ }
+
+ if (values == NULL) {
+ PERROR("Invalid address of values specified.\n");
+ return ME_ERRNO_INVALID_POINTER;
+ }
+
+ if ((instance->status == ao_status_none) || (instance->status == ao_status_single_configured)) { //The device is in single mode.
+ PERROR
+ ("Subdevice must be preinitialize correctly for streaming.\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+/// @note If no 'pre-load' is used. stream_start() will move data to FIFO.
+ switch (write_mode) {
+ case ME_WRITE_MODE_PRELOAD:
+
+ //Device must be stopped.
+ if ((instance->status != ao_status_stream_configured)
+ && (instance->status != ao_status_stream_end)) {
+ PERROR
+ ("Subdevice mustn't be runing when 'pre-load' mode is used.\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ break;
+ case ME_WRITE_MODE_NONBLOCKING:
+ case ME_WRITE_MODE_BLOCKING:
+ /// @note In blocking mode: When device is not runing and there is not enought space call will blocked up!
+ /// @note Some other thread must empty buffer by starting engine.
+ break;
+
+ default:
+ PERROR("Invalid write mode specified.\n");
+ return ME_ERRNO_INVALID_WRITE_MODE;
+ }
+
+ if (instance->mode & ME4600_AO_WRAP_MODE) { //Wraparound mode. Device must be stopped.
+ if ((instance->status != ao_status_stream_configured)
+ && (instance->status != ao_status_stream_end)) {
+ PERROR
+ ("Subdevice mustn't be runing when 'pre-load' mode is used.\n");
+ return ME_ERRNO_INVALID_WRITE_MODE;
+ }
+ }
+
+ if ((instance->mode == ME4600_AO_HW_WRAP_MODE) && (write_mode != ME_WRITE_MODE_PRELOAD)) { // hardware wrap_around mode.
+ //This is transparent for user.
+ PDEBUG("Changing write_mode to ME_WRITE_MODE_PRELOAD.\n");
+ write_mode = ME_WRITE_MODE_PRELOAD;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (write_mode == ME_WRITE_MODE_PRELOAD) { //Init enviroment - preload
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ reg_copy = inl(instance->ctrl_reg);
+ //Check FIFO
+ if (!(reg_copy & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO not active. Enable it.
+ reg_copy |= ME4600_AO_CTRL_BIT_ENABLE_FIFO;
+ outl(reg_copy, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ reg_copy);
+ instance->preloaded_count = 0;
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ }
+
+ while (1) {
+ //Copy to buffer. This step is common for all modes.
+ copied_from_user =
+ ao_get_data_from_user(instance, left_to_copy_from_user,
+ values + (*count -
+ left_to_copy_from_user));
+ left_to_copy_from_user -= copied_from_user;
+
+ reg_copy = inl(instance->status_reg);
+ if ((instance->status == ao_status_stream_run) && !(reg_copy & ME4600_AO_STATUS_BIT_FSM)) { //BROKEN PIPE! The state machine is stoped but logical status show that should be working.
+ PERROR("Broken pipe in write.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ break;
+ }
+
+ if ((instance->status == ao_status_stream_run) && (instance->mode == ME4600_AO_CONTINOUS) && (reg_copy & ME4600_AO_STATUS_BIT_HF)) { //Continous mode runing and data are below half!
+
+ // Block interrupts.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ reg_copy = inl(instance->ctrl_reg);
+ //reg_copy &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ reg_copy |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(reg_copy, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ reg_copy);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ //Fast copy
+ copied_values =
+ ao_write_data(instance, ME4600_AO_FIFO_COUNT / 2,
+ 0);
+ if (copied_values > 0) {
+ instance->circ_buf.tail += copied_values;
+ instance->circ_buf.tail &=
+ instance->circ_buf.mask;
+ continue;
+ }
+ // Activate interrupts.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ reg_copy = inl(instance->ctrl_reg);
+ //reg_copy |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ reg_copy &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(reg_copy, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ reg_copy);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (copied_values == 0) { //This was checked and never should happend!
+ PERROR_CRITICAL("COPING FINISH WITH 0!\n");
+ }
+
+ if (copied_values < 0) { //This was checked and never should happend!
+ PERROR_CRITICAL
+ ("COPING FINISH WITH AN ERROR!\n");
+ instance->status = ao_status_stream_fifo_error;
+ err = ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ break;
+ }
+ }
+
+ if (!left_to_copy_from_user) { //All datas were copied.
+ break;
+ } else { //Not all datas were copied.
+ if (instance->mode & ME4600_AO_WRAP_MODE) { //Error too much datas! Wraparound is limited in size!
+ PERROR
+ ("Too much data for wraparound mode! Exceeded size of %ld.\n",
+ ME4600_AO_CIRC_BUF_COUNT - 1);
+ err = ME_ERRNO_RING_BUFFER_OVERFLOW;
+ break;
+ }
+
+ if (write_mode != ME_WRITE_MODE_BLOCKING) { //Non blocking calls
+ break;
+ }
+
+ wait_event_interruptible(instance->wait_queue,
+ me_circ_buf_space(&instance->
+ circ_buf));
+
+ if (signal_pending(current)) {
+ PERROR("Writing interrupted by signal.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ break;
+ }
+
+ if (instance->status == ao_status_none) { //Reset
+ PERROR("Writing interrupted by reset.\n");
+ err = ME_ERRNO_CANCELLED;
+ break;
+ }
+ }
+ }
+
+ if (write_mode == ME_WRITE_MODE_PRELOAD) { //Copy data to FIFO - preload
+ copied_values =
+ ao_write_data_pooling(instance, ME4600_AO_FIFO_COUNT,
+ instance->preloaded_count);
+ instance->preloaded_count += copied_values;
+ instance->data_count += copied_values;
+
+ if ((instance->mode == ME4600_AO_HW_WRAP_MODE)
+ && (me_circ_buf_values(&instance->circ_buf) >
+ ME4600_AO_FIFO_COUNT)) {
+ PERROR
+ ("Too much data for hardware wraparound mode! Exceeded size of %d.\n",
+ ME4600_AO_FIFO_COUNT);
+ err = ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ }
+ }
+
+ *count = *count - left_to_copy_from_user;
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+static irqreturn_t me4600_ao_isr(int irq, void *dev_id
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+ , struct pt_regs *regs
+#endif
+ )
+{
+ me4600_ao_subdevice_t *instance = dev_id;
+ uint32_t irq_status;
+ uint32_t ctrl;
+ uint32_t status;
+ int count = 0;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ irq_status = inl(instance->irq_status_reg);
+ if (!(irq_status & (ME4600_IRQ_STATUS_BIT_AO_HF << instance->ao_idx))) {
+ PINFO("%ld Shared interrupt. %s(): ID=%d: status_reg=0x%04X\n",
+ jiffies, __func__, instance->ao_idx, irq_status);
+ return IRQ_NONE;
+ }
+
+ if (!instance->circ_buf.buf) {
+ instance->status = ao_status_stream_error;
+ PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n");
+ //Block interrupts. Stop machine.
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |=
+ ME4600_AO_CTRL_BIT_RESET_IRQ |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Inform user
+ wake_up_interruptible_all(&instance->wait_queue);
+ return IRQ_HANDLED;
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME4600_AO_STATUS_BIT_FSM)) { //Too late. Not working! END? BROKEN PIPE?
+ PDEBUG("Interrupt come but ISM is not working!\n");
+ //Block interrupts. Stop machine.
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |=
+ ME4600_AO_CTRL_BIT_RESET_IRQ | ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ return IRQ_HANDLED;
+ }
+ //General procedure. Process more datas.
+
+#ifdef MEDEBUG_DEBUG
+ if (!me_circ_buf_values(&instance->circ_buf)) { //Buffer is empty!
+ PDEBUG("Circular buffer empty!\n");
+ }
+#endif
+
+ //Check FIFO
+ if (status & ME4600_AO_STATUS_BIT_HF) { //OK less than half
+
+ //Block interrupts
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ do {
+ //Calculate how many should be copied.
+ count =
+ (instance->stop_data_count) ? instance->
+ stop_data_count -
+ instance->data_count : ME4600_AO_FIFO_COUNT / 2;
+ if (ME4600_AO_FIFO_COUNT / 2 < count) {
+ count = ME4600_AO_FIFO_COUNT / 2;
+ }
+ //Copy data
+ if (instance->mode == ME4600_AO_CONTINOUS) { //Continous
+ count = ao_write_data(instance, count, 0);
+ if (count > 0) {
+ instance->circ_buf.tail += count;
+ instance->circ_buf.tail &=
+ instance->circ_buf.mask;
+ instance->data_count += count;
+
+ if ((instance->status == ao_status_stream_end_wait) && !me_circ_buf_values(&instance->circ_buf)) { //Stoping. Whole buffer was copied.
+ break;
+ }
+ }
+ } else if ((instance->mode == ME4600_AO_SW_WRAP_MODE) && ((ctrl & ME4600_AO_CTRL_MODE_MASK) == ME4600_AO_MODE_CONTINUOUS)) { //Wraparound (software)
+ if (instance->status == ao_status_stream_end_wait) { //We stoping => Copy to the end of the buffer.
+ count =
+ ao_write_data(instance, count, 0);
+ } else { //Copy in wraparound mode.
+ count =
+ ao_write_data_wraparound(instance,
+ count,
+ instance->
+ preloaded_count);
+ }
+
+ if (count > 0) {
+ instance->data_count += count;
+ instance->preloaded_count += count;
+ instance->preloaded_count %=
+ me_circ_buf_values(&instance->
+ circ_buf);
+
+ if ((instance->status == ao_status_stream_end_wait) && !instance->preloaded_count) { //Stoping. Whole buffer was copied.
+ break;
+ }
+ }
+ }
+
+ if ((count <= 0) || (instance->stop_data_count && (instance->stop_data_count <= instance->data_count))) { //End of work.
+ break;
+ }
+ } //Repeat if still is under half fifo
+ while ((status =
+ inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_HF);
+
+ //Unblock interrupts
+ ctrl = inl(instance->ctrl_reg);
+ if (count >= 0) { //Copy was successful.
+ if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. No more interrupts.
+ PDEBUG("Finishing work. Interrupt disabled.\n");
+ instance->status = ao_status_stream_end_wait;
+ } else if (count > 0) { //Normal work. Enable interrupt.
+ PDEBUG("Normal work. Enable interrupt.\n");
+ ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ } else { //Normal work but there are no more data in buffer. Interrupt active but blocked. stream_write() will unblock it.
+ PDEBUG
+ ("No data in software buffer. Interrupt blocked.\n");
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ }
+ } else { //Error during copy.
+ instance->status = ao_status_stream_fifo_error;
+ }
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ } else { //?? more than half
+ PDEBUG
+ ("Interrupt come but FIFO more than half full! Reset interrupt.\n");
+ //Reset pending interrupt
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ }
+
+ PINFO("ISR: Buffer count: %d.(T:%d H:%d)\n",
+ me_circ_buf_values(&instance->circ_buf), instance->circ_buf.tail,
+ instance->circ_buf.head);
+ PINFO("ISR: Stop count: %d.\n", instance->stop_count);
+ PINFO("ISR: Stop data count: %d.\n", instance->stop_data_count);
+ PINFO("ISR: Data count: %d.\n", instance->data_count);
+
+ //Inform user
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+static void me4600_ao_destructor(struct me_subdevice *subdevice)
+{
+ me4600_ao_subdevice_t *instance;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ instance->ao_control_task_flag = 0;
+
+ // Reset subdevice to asure clean exit.
+ me4600_ao_io_reset_subdevice(subdevice, NULL,
+ ME_IO_RESET_SUBDEVICE_NO_FLAGS);
+
+ // Remove any tasks from work queue. This is paranoic because it was done allready in reset().
+ if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue.
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(2);
+ }
+
+ if (instance->fifo) {
+ if (instance->irq) {
+ free_irq(instance->irq, instance);
+ instance->irq = 0;
+ }
+
+ if (instance->circ_buf.buf) {
+ free_pages((unsigned long)instance->circ_buf.buf,
+ ME4600_AO_CIRC_BUF_SIZE_ORDER);
+ }
+ instance->circ_buf.buf = NULL;
+ }
+
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base,
+ spinlock_t * preload_reg_lock,
+ uint32_t * preload_flags,
+ int ao_idx,
+ int fifo,
+ int irq,
+ struct workqueue_struct *me4600_wq)
+{
+ me4600_ao_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed. idx=%d\n", ao_idx);
+
+ // Allocate memory for subdevice instance.
+ subdevice = kmalloc(sizeof(me4600_ao_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me4600_ao_subdevice_t));
+
+ // Initialize subdevice base class.
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->preload_reg_lock = preload_reg_lock;
+ subdevice->preload_flags = preload_flags;
+
+ // Store analog output index.
+ subdevice->ao_idx = ao_idx;
+
+ // Store if analog output has fifo.
+ subdevice->fifo = (ao_idx < fifo) ? 1 : 0;
+
+ if (subdevice->fifo) { // Allocate and initialize circular buffer.
+ subdevice->circ_buf.mask = ME4600_AO_CIRC_BUF_COUNT - 1;
+
+ subdevice->circ_buf.buf =
+ (void *)__get_free_pages(GFP_KERNEL,
+ ME4600_AO_CIRC_BUF_SIZE_ORDER);
+ PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf,
+ ME4600_AO_CIRC_BUF_SIZE);
+
+ if (!subdevice->circ_buf.buf) {
+ PERROR
+ ("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+
+ memset(subdevice->circ_buf.buf, 0, ME4600_AO_CIRC_BUF_SIZE);
+ } else { // No FIFO.
+ subdevice->circ_buf.mask = 0;
+ subdevice->circ_buf.buf = NULL;
+ }
+
+ subdevice->circ_buf.head = 0;
+ subdevice->circ_buf.tail = 0;
+
+ subdevice->status = ao_status_none;
+ subdevice->ao_control_task_flag = 0;
+ subdevice->timeout.delay = 0;
+ subdevice->timeout.start_time = jiffies;
+
+ // Initialize wait queue.
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ // Initialize single value to 0V.
+ subdevice->single_value = 0x8000;
+ subdevice->single_value_in_fifo = 0x8000;
+
+ // Register interrupt service routine.
+ if (subdevice->fifo) {
+ subdevice->irq = irq;
+ if (request_irq(subdevice->irq, me4600_ao_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME4600_NAME, subdevice)) {
+ PERROR("Cannot get interrupt line.\n");
+ PDEBUG("free circ_buf = %p size=%d",
+ subdevice->circ_buf.buf,
+ PAGE_SHIFT << ME4600_AO_CIRC_BUF_SIZE_ORDER);
+ free_pages((unsigned long)subdevice->circ_buf.buf,
+ ME4600_AO_CIRC_BUF_SIZE_ORDER);
+ me_subdevice_deinit((me_subdevice_t *) subdevice);
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", subdevice->irq);
+ } else {
+ subdevice->irq = 0;
+ }
+
+ // Initialize registers.
+ subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG;
+ subdevice->preload_reg = reg_base + ME4600_AO_SYNC_REG;
+ if (ao_idx == 0) {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_00_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_00_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_00_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_00_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_00_TIMER_REG;
+ subdevice->reg_base = reg_base;
+ subdevice->bitpattern = 0;
+ } else if (ao_idx == 1) {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_01_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_01_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_01_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_01_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_01_TIMER_REG;
+ subdevice->reg_base = reg_base;
+ subdevice->bitpattern = 0;
+ } else if (ao_idx == 2) {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_02_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_02_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_02_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_02_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_02_TIMER_REG;
+ subdevice->reg_base = reg_base;
+ subdevice->bitpattern = 0;
+ } else if (ao_idx == 3) {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_03_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_03_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_03_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_03_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_03_TIMER_REG;
+ subdevice->reg_base = reg_base;
+ subdevice->bitpattern = 1;
+ } else {
+ PERROR_CRITICAL("WRONG SUBDEVICE idx=%d!", ao_idx);
+ me_subdevice_deinit((me_subdevice_t *) subdevice);
+ if (subdevice->fifo) {
+ free_pages((unsigned long)subdevice->circ_buf.buf,
+ ME4600_AO_CIRC_BUF_SIZE_ORDER);
+ }
+ subdevice->circ_buf.buf = NULL;
+ kfree(subdevice);
+ return NULL;
+ }
+
+ // Override base class methods.
+ subdevice->base.me_subdevice_destructor = me4600_ao_destructor;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me4600_ao_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me4600_ao_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me4600_ao_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me4600_ao_io_single_write;
+ subdevice->base.me_subdevice_io_stream_config =
+ me4600_ao_io_stream_config;
+ subdevice->base.me_subdevice_io_stream_new_values =
+ me4600_ao_io_stream_new_values;
+ subdevice->base.me_subdevice_io_stream_write =
+ me4600_ao_io_stream_write;
+ subdevice->base.me_subdevice_io_stream_start =
+ me4600_ao_io_stream_start;
+ subdevice->base.me_subdevice_io_stream_status =
+ me4600_ao_io_stream_status;
+ subdevice->base.me_subdevice_io_stream_stop = me4600_ao_io_stream_stop;
+ subdevice->base.me_subdevice_query_number_channels =
+ me4600_ao_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me4600_ao_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me4600_ao_query_subdevice_caps;
+ subdevice->base.me_subdevice_query_subdevice_caps_args =
+ me4600_ao_query_subdevice_caps_args;
+ subdevice->base.me_subdevice_query_range_by_min_max =
+ me4600_ao_query_range_by_min_max;
+ subdevice->base.me_subdevice_query_number_ranges =
+ me4600_ao_query_number_ranges;
+ subdevice->base.me_subdevice_query_range_info =
+ me4600_ao_query_range_info;
+ subdevice->base.me_subdevice_query_timer = me4600_ao_query_timer;
+
+ // Prepare work queue
+ subdevice->me4600_workqueue = me4600_wq;
+
+/* workqueue API changed in kernel 2.6.20 */
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
+ INIT_WORK(&subdevice->ao_control_task, me4600_ao_work_control_task,
+ (void *)subdevice);
+#else
+ INIT_DELAYED_WORK(&subdevice->ao_control_task,
+ me4600_ao_work_control_task);
+#endif
+
+ if (subdevice->fifo) { // Set speed for single operations.
+ outl(ME4600_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg);
+ subdevice->hardware_stop_delay = HZ / 10; //100ms
+ }
+
+ return subdevice;
+}
+
+/** @brief Stop presentation. Preserve FIFOs.
+*
+* @param instance The subdevice instance (pointer).
+*/
+int inline ao_stop_immediately(me4600_ao_subdevice_t * instance)
+{
+ unsigned long cpu_flags;
+ uint32_t ctrl;
+ int timeout;
+ int i;
+
+ timeout =
+ (instance->hardware_stop_delay >
+ (HZ / 10)) ? instance->hardware_stop_delay : HZ / 10;
+ for (i = 0; i <= timeout; i++) {
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched!
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP
+ | ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { // Exit.
+ break;
+ }
+ //Still working!
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ if (i > timeout) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ return ME_ERRNO_INTERNAL;
+ }
+ return ME_ERRNO_SUCCESS;
+}
+
+/** @brief Copy data from circular buffer to fifo (fast) in wraparound.
+* @note This is time critical function. Checking is done at begining and end only.
+* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly.
+*
+* @param instance The subdevice instance (pointer).
+* @param count Maximum number of copied data.
+* @param start_pos Position of the firs value in buffer.
+*
+* @return On success: Number of copied data.
+* @return On error/success: 0. No datas were copied => no data in buffer.
+* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW.
+*/
+int inline ao_write_data_wraparound(me4600_ao_subdevice_t * instance, int count,
+ int start_pos)
+{ /// @note This is time critical function!
+ uint32_t status;
+ uint32_t value;
+ int pos =
+ (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask;
+ int local_count = count;
+ int i = 1;
+
+ if (count <= 0) { //Wrong count!
+ return 0;
+ }
+
+ while (i < local_count) {
+ //Get value from buffer
+ value = *(instance->circ_buf.buf + pos);
+ //Prepare it
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+
+ pos++;
+ pos &= instance->circ_buf.mask;
+ if (pos == instance->circ_buf.head) {
+ pos = instance->circ_buf.tail;
+ }
+ i++;
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied!
+ PERROR("FIFO was full before all datas were copied! idx=%d\n",
+ instance->ao_idx);
+ return -ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ } else { //Add last value
+ value = *(instance->circ_buf.buf + pos);
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+ }
+
+ PINFO("WRAPAROUND LOADED %d values. idx=%d\n", local_count,
+ instance->ao_idx);
+ return local_count;
+}
+
+/** @brief Copy data from software buffer to fifo (fast).
+* @note This is time critical function. Checking is done at begining and end only.
+* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly.
+*
+* @param instance The subdevice instance (pointer).
+* @param count Maximum number of copied data.
+* @param start_pos Position of the firs value in buffer.
+*
+* @return On success: Number of copied data.
+* @return On error/success: 0. No datas were copied => no data in buffer.
+* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW.
+*/
+int inline ao_write_data(me4600_ao_subdevice_t * instance, int count,
+ int start_pos)
+{ /// @note This is time critical function!
+ uint32_t status;
+ uint32_t value;
+ int pos =
+ (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask;
+ int local_count = count;
+ int max_count;
+ int i = 1;
+
+ if (count <= 0) { //Wrong count!
+ return 0;
+ }
+
+ max_count = me_circ_buf_values(&instance->circ_buf) - start_pos;
+ if (max_count <= 0) { //No data to copy!
+ return 0;
+ }
+
+ if (max_count < count) {
+ local_count = max_count;
+ }
+
+ while (i < local_count) {
+ //Get value from buffer
+ value = *(instance->circ_buf.buf + pos);
+ //Prepare it
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+
+ pos++;
+ pos &= instance->circ_buf.mask;
+ i++;
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied!
+ PERROR("FIFO was full before all datas were copied! idx=%d\n",
+ instance->ao_idx);
+ return -ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ } else { //Add last value
+ value = *(instance->circ_buf.buf + pos);
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+ }
+
+ PINFO("FAST LOADED %d values. idx=%d\n", local_count, instance->ao_idx);
+ return local_count;
+}
+
+/** @brief Copy data from software buffer to fifo (slow).
+* @note This is slow function that copy all data from buffer to FIFO with full control.
+*
+* @param instance The subdevice instance (pointer).
+* @param count Maximum number of copied data.
+* @param start_pos Position of the firs value in buffer.
+*
+* @return On success: Number of copied values.
+* @return On error/success: 0. FIFO was full at begining.
+* @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW.
+*/
+int inline ao_write_data_pooling(me4600_ao_subdevice_t * instance, int count,
+ int start_pos)
+{ /// @note This is slow function!
+ uint32_t status;
+ uint32_t value;
+ int pos =
+ (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask;
+ int local_count = count;
+ int i;
+ int max_count;
+
+ if (count <= 0) { //Wrong count!
+ PERROR("SLOW LOADED: Wrong count! idx=%d\n", instance->ao_idx);
+ return 0;
+ }
+
+ max_count = me_circ_buf_values(&instance->circ_buf) - start_pos;
+ if (max_count <= 0) { //No data to copy!
+ PERROR("SLOW LOADED: No data to copy! idx=%d\n",
+ instance->ao_idx);
+ return 0;
+ }
+
+ if (max_count < count) {
+ local_count = max_count;
+ }
+
+ for (i = 0; i < local_count; i++) {
+ status = inl(instance->status_reg);
+ if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full!
+ return i;
+ }
+ //Get value from buffer
+ value = *(instance->circ_buf.buf + pos);
+ //Prepare it
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+
+ pos++;
+ pos &= instance->circ_buf.mask;
+ }
+
+ PINFO("SLOW LOADED %d values. idx=%d\n", local_count, instance->ao_idx);
+ return local_count;
+}
+
+/** @brief Copy data from user space to circular buffer.
+* @param instance The subdevice instance (pointer).
+* @param count Number of datas in user space.
+* @param user_values Buffer's pointer.
+*
+* @return On success: Number of copied values.
+* @return On error: -ME_ERRNO_INTERNAL.
+*/
+int inline ao_get_data_from_user(me4600_ao_subdevice_t * instance, int count,
+ int *user_values)
+{
+ int i, err;
+ int empty_space;
+ int copied;
+ int value;
+
+ empty_space = me_circ_buf_space(&instance->circ_buf);
+ //We have only this space free.
+ copied = (count < empty_space) ? count : empty_space;
+ for (i = 0; i < copied; i++) { //Copy from user to buffer
+ if ((err = get_user(value, (int *)(user_values + i)))) {
+ PERROR
+ ("BUFFER LOADED: get_user(0x%p) return an error: %d. idx=%d\n",
+ user_values + i, err, instance->ao_idx);
+ return -ME_ERRNO_INTERNAL;
+ }
+ /// @note The analog output in me4600 series has size of 16 bits.
+ *(instance->circ_buf.buf + instance->circ_buf.head) =
+ (uint16_t) value;
+ instance->circ_buf.head++;
+ instance->circ_buf.head &= instance->circ_buf.mask;
+ }
+
+ PINFO("BUFFER LOADED %d values. idx=%d\n", copied, instance->ao_idx);
+ return copied;
+}
+
+/** @brief Checking actual hardware and logical state.
+* @param instance The subdevice instance (pointer).
+*/
+static void me4600_ao_work_control_task(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ void *subdevice
+#else
+ struct work_struct *work
+#endif
+ )
+{
+ me4600_ao_subdevice_t *instance;
+ unsigned long cpu_flags = 0;
+ uint32_t status;
+ uint32_t ctrl;
+ uint32_t synch;
+ int reschedule = 0;
+ int signaling = 0;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ instance = (me4600_ao_subdevice_t *) subdevice;
+#else
+ instance =
+ container_of((void *)work, me4600_ao_subdevice_t, ao_control_task);
+#endif
+ PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies,
+ instance->ao_idx);
+
+ status = inl(instance->status_reg);
+ PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->status_reg - instance->reg_base, status);
+
+ switch (instance->status) { // Checking actual mode.
+
+ // Not configured for work.
+ case ao_status_none:
+ break;
+
+ //This are stable modes. No need to do anything. (?)
+ case ao_status_single_configured:
+ case ao_status_stream_configured:
+ case ao_status_stream_fifo_error:
+ case ao_status_stream_buffer_error:
+ case ao_status_stream_error:
+ PERROR("Shouldn't be running!.\n");
+ break;
+
+ case ao_status_stream_end:
+ if (!instance->fifo) {
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+ case ao_status_single_end:
+ if (status & ME4600_AO_STATUS_BIT_FSM) { // State machine is working but the status is set to end. Force stop.
+
+ // Wait for stop.
+ reschedule = 1;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched!
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP
+ | ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ break;
+
+ // Single modes
+ case ao_status_single_run_wait:
+ case ao_status_single_run:
+ case ao_status_single_end_wait:
+
+ if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working.
+ if (((instance->fifo)
+ && (!(status & ME4600_AO_STATUS_BIT_EF)))
+ || (!(instance->fifo))) { // Single is in end state.
+ PDEBUG("Single call has been complited.\n");
+
+ // Set correct value for single_read();
+ instance->single_value =
+ instance->single_value_in_fifo;
+
+ // Set status as 'ao_status_single_end'
+ instance->status = ao_status_single_end;
+
+ // Signal the end.
+ signaling = 1;
+ // Wait for stop ISM.
+ reschedule = 1;
+
+ break;
+ }
+ }
+ // Check timeout.
+ if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout
+ PDEBUG("Timeout reached.\n");
+ // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched!
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ /// Fix for timeout error.
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH);
+ if (instance->fifo) { //Disabling FIFO
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO;
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ spin_lock(instance->preload_reg_lock);
+ //Remove from synchronous start. Block triggering from this output.
+ synch = inl(instance->preload_reg);
+ synch &=
+ ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx);
+ if (!(instance->fifo)) { // No FIFO - set to single safe mode
+ synch |=
+ ME4600_AO_SYNC_HOLD << instance->ao_idx;
+ }
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ synch);
+ spin_unlock(instance->preload_reg_lock);
+
+ if (!(instance->fifo)) { // No FIFO
+ // Restore old settings.
+ PDEBUG("Write old value back to register.\n");
+ outl(instance->single_value,
+ instance->single_reg);
+ PDEBUG_REG
+ ("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base,
+ instance->single_value);
+ }
+ // Set correct value for single_read();
+ instance->single_value_in_fifo = instance->single_value;
+
+ instance->status = ao_status_single_end;
+
+ // Signal the end.
+ signaling = 1;
+ }
+ // Wait for stop.
+ reschedule = 1;
+ break;
+
+ // Stream modes
+ case ao_status_stream_run_wait:
+ if (!instance->fifo) {
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+
+ if (status & ME4600_AO_STATUS_BIT_FSM) { // State machine is working. Waiting for start finish.
+ instance->status = ao_status_stream_run;
+
+ // Signal end of this step
+ signaling = 1;
+ } else { // State machine is not working.
+ if (!(status & ME4600_AO_STATUS_BIT_EF)) { // FIFO is empty. Procedure has started and finish already!
+ instance->status = ao_status_stream_end;
+
+ // Signal the end.
+ signaling = 1;
+ // Wait for stop.
+ reschedule = 1;
+ break;
+ }
+ }
+
+ // Check timeout.
+ if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout
+ PDEBUG("Timeout reached.\n");
+ // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched!
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP |
+ ME4600_AO_CTRL_BIT_RESET_IRQ;
+ ctrl &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ spin_lock(instance->preload_reg_lock);
+ //Remove from synchronous start. Block triggering from this output.
+ synch = inl(instance->preload_reg);
+ synch &=
+ ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx);
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ synch);
+ spin_unlock(instance->preload_reg_lock);
+
+ instance->status = ao_status_stream_end;
+
+ // Signal the end.
+ signaling = 1;
+ }
+ // Wait for stop.
+ reschedule = 1;
+ break;
+
+ case ao_status_stream_run:
+ if (!instance->fifo) {
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+
+ if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. This is an error.
+ // BROKEN PIPE!
+ if (!(status & ME4600_AO_STATUS_BIT_EF)) { // FIFO is empty.
+ if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty.
+ if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. Requed data shown.
+ PDEBUG
+ ("ISM stoped. No data in FIFO. Buffer is not empty.\n");
+ instance->status =
+ ao_status_stream_end;
+ } else {
+ PERROR
+ ("Output stream has been broken. ISM stoped. No data in FIFO. Buffer is not empty.\n");
+ instance->status =
+ ao_status_stream_buffer_error;
+ }
+ } else { // Software buffer is empty.
+ PDEBUG
+ ("ISM stoped. No data in FIFO. Buffer is empty.\n");
+ instance->status = ao_status_stream_end;
+ }
+ } else { // There are still datas in FIFO.
+ if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty.
+ PERROR
+ ("Output stream has been broken. ISM stoped but some data in FIFO and buffer.\n");
+ } else { // Software buffer is empty.
+ PERROR
+ ("Output stream has been broken. ISM stoped but some data in FIFO. Buffer is empty.\n");
+ }
+ instance->status = ao_status_stream_fifo_error;
+
+ }
+
+ // Signal the failure.
+ signaling = 1;
+ break;
+ }
+ // Wait for stop.
+ reschedule = 1;
+ break;
+
+ case ao_status_stream_end_wait:
+ if (!instance->fifo) {
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+
+ if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. Waiting for stop finish.
+ instance->status = ao_status_stream_end;
+ signaling = 1;
+ }
+ // State machine is working.
+ reschedule = 1;
+ break;
+
+ default:
+ PERROR_CRITICAL("Status is in wrong state (%d)!\n",
+ instance->status);
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+
+ }
+
+ if (signaling) { //Signal it.
+ wake_up_interruptible_all(&instance->wait_queue);
+ }
+
+ if (instance->ao_control_task_flag && reschedule) { // Reschedule task
+ queue_delayed_work(instance->me4600_workqueue,
+ &instance->ao_control_task, 1);
+ } else {
+ PINFO("<%s> Ending control task.\n", __func__);
+ }
+
+}
+#else
+/// @note SPECIAL BUILD FOR BOSCH
+/// @author Guenter Gebhardt
+static int me4600_ao_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t tmp;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status);
+ spin_lock(instance->preload_reg_lock);
+ tmp = inl(instance->preload_reg);
+ tmp &= ~(0x10001 << instance->ao_idx);
+ outl(tmp, instance->preload_reg);
+ *instance->preload_flags &= ~(0x1 << instance->ao_idx);
+ spin_unlock(instance->preload_reg_lock);
+
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+
+ while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ;
+
+ outl(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP,
+ instance->ctrl_reg);
+
+ outl(0x8000, instance->single_reg);
+
+ instance->single_value = 0x8000;
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t tmp;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ if (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) {
+ PERROR("Subdevice is busy.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ if (channel == 0) {
+ if (single_config == 0) {
+ if (ref == ME_REF_AO_GROUND) {
+ if (trig_chan == ME_TRIG_CHAN_DEFAULT) {
+ if (trig_type == ME_TRIG_TYPE_SW) {
+ tmp = inl(instance->ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+
+ spin_lock(instance->
+ preload_reg_lock);
+ tmp =
+ inl(instance->preload_reg);
+ tmp &=
+ ~(0x10001 << instance->
+ ao_idx);
+ outl(tmp,
+ instance->preload_reg);
+ *instance->preload_flags &=
+ ~(0x1 << instance->ao_idx);
+ spin_unlock(instance->
+ preload_reg_lock);
+ } else if (trig_type ==
+ ME_TRIG_TYPE_EXT_DIGITAL) {
+ if (trig_edge ==
+ ME_TRIG_EDGE_RISING) {
+ tmp =
+ inl(instance->
+ ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP
+ |
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ } else if (trig_edge ==
+ ME_TRIG_EDGE_FALLING)
+ {
+ tmp =
+ inl(instance->
+ ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP
+ |
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG
+ |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ } else if (trig_edge ==
+ ME_TRIG_EDGE_ANY) {
+ tmp =
+ inl(instance->
+ ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP
+ |
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG
+ |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE
+ |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ } else {
+ PERROR
+ ("Invalid trigger edge.\n");
+ err =
+ ME_ERRNO_INVALID_TRIG_EDGE;
+ goto ERROR;
+ }
+
+ spin_lock(instance->
+ preload_reg_lock);
+
+ tmp =
+ inl(instance->preload_reg);
+ tmp &=
+ ~(0x10001 << instance->
+ ao_idx);
+ tmp |= 0x1 << instance->ao_idx;
+ outl(tmp,
+ instance->preload_reg);
+ *instance->preload_flags &=
+ ~(0x1 << instance->ao_idx);
+ spin_unlock(instance->
+ preload_reg_lock);
+ } else {
+ PERROR
+ ("Invalid trigger type.\n");
+ err =
+ ME_ERRNO_INVALID_TRIG_TYPE;
+ goto ERROR;
+ }
+ } else if (trig_chan ==
+ ME_TRIG_CHAN_SYNCHRONOUS) {
+ if (trig_type == ME_TRIG_TYPE_SW) {
+ tmp = inl(instance->ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+
+ spin_lock(instance->
+ preload_reg_lock);
+ tmp =
+ inl(instance->preload_reg);
+ tmp &=
+ ~(0x10001 << instance->
+ ao_idx);
+ tmp |= 0x1 << instance->ao_idx;
+ outl(tmp,
+ instance->preload_reg);
+ *instance->preload_flags |=
+ 0x1 << instance->ao_idx;
+ spin_unlock(instance->
+ preload_reg_lock);
+ } else if (trig_type ==
+ ME_TRIG_TYPE_EXT_DIGITAL) {
+ if (trig_edge ==
+ ME_TRIG_EDGE_RISING) {
+ tmp =
+ inl(instance->
+ ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ } else if (trig_edge ==
+ ME_TRIG_EDGE_FALLING)
+ {
+ tmp =
+ inl(instance->
+ ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP
+ |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ } else if (trig_edge ==
+ ME_TRIG_EDGE_ANY) {
+ tmp =
+ inl(instance->
+ ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ tmp =
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP
+ |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE
+ |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ outl(tmp,
+ instance->
+ ctrl_reg);
+ } else {
+ PERROR
+ ("Invalid trigger edge.\n");
+ err =
+ ME_ERRNO_INVALID_TRIG_EDGE;
+ goto ERROR;
+ }
+
+ spin_lock(instance->
+ preload_reg_lock);
+
+ tmp =
+ inl(instance->preload_reg);
+ tmp |=
+ 0x10001 << instance->ao_idx;
+ outl(tmp,
+ instance->preload_reg);
+ *instance->preload_flags &=
+ ~(0x1 << instance->ao_idx);
+ spin_unlock(instance->
+ preload_reg_lock);
+ } else {
+ PERROR
+ ("Invalid trigger type.\n");
+ err =
+ ME_ERRNO_INVALID_TRIG_TYPE;
+ goto ERROR;
+ }
+ } else {
+ PERROR
+ ("Invalid trigger channel specified.\n");
+ err = ME_ERRNO_INVALID_REF;
+ goto ERROR;
+ }
+ } else {
+ PERROR("Invalid analog reference specified.\n");
+ err = ME_ERRNO_INVALID_REF;
+ goto ERROR;
+ }
+ } else {
+ PERROR("Invalid single config specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ goto ERROR;
+ }
+ } else {
+ PERROR("Invalid channel number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ goto ERROR;
+ }
+
+ ERROR:
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long tmp;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ if (channel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ tmp = inl(instance->ctrl_reg);
+
+ if (tmp & 0x3) {
+ PERROR("Not in single mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ } else {
+ *value = instance->single_value;
+ }
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long mask = 0;
+ unsigned long tmp;
+ unsigned long cpu_flags;
+ int i;
+ wait_queue_head_t queue;
+ unsigned long j;
+ unsigned long delay = 0;
+
+ PDEBUG("executed.\n");
+
+ init_waitqueue_head(&queue);
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ if (channel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+
+ if (delay == 0)
+ delay = 1;
+ }
+
+ ME_SUBDEVICE_ENTER
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ tmp = inl(instance->ctrl_reg);
+
+ if (tmp & 0x3) {
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ PERROR("Not in single mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ goto ERROR;
+ }
+
+ if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) {
+ outl(value, instance->single_reg);
+ instance->single_value = value;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) {
+ j = jiffies;
+
+ while (inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on external trigger interrupted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+
+ if (delay && ((jiffies - j) > delay)) {
+ PERROR("Timeout reached.\n");
+ err = ME_ERRNO_TIMEOUT;
+ goto ERROR;
+ }
+ }
+ }
+ } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx))
+ == (0x10001 << instance->ao_idx)) {
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) {
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ outl(tmp, instance->ctrl_reg);
+ outl(value, instance->single_reg);
+ instance->single_value = value;
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) {
+ j = jiffies;
+
+ while (inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue,
+ 1);
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on external trigger interrupted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+
+ if (delay && ((jiffies - j) > delay)) {
+ PERROR("Timeout reached.\n");
+ err = ME_ERRNO_TIMEOUT;
+ goto ERROR;
+ }
+ }
+ }
+ } else {
+ outl(value, instance->single_reg);
+ instance->single_value = value;
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ }
+ } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx))
+ == (0x1 << instance->ao_idx)) {
+ outl(value, instance->single_reg);
+ instance->single_value = value;
+
+ PDEBUG("Synchronous SW, flags = 0x%X.\n", flags);
+
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) {
+ PDEBUG("Trigger synchronous SW.\n");
+ spin_lock(instance->preload_reg_lock);
+ tmp = inl(instance->preload_reg);
+
+ for (i = 0; i < ME4600_AO_MAX_SUBDEVICES; i++) {
+ if ((*instance->preload_flags & (0x1 << i))) {
+ if ((tmp & (0x10001 << i)) ==
+ (0x1 << i)) {
+ mask |= 0x1 << i;
+ }
+ }
+ }
+
+ tmp &= ~(mask);
+
+ outl(tmp, instance->preload_reg);
+ spin_unlock(instance->preload_reg_lock);
+ }
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ } else {
+ outl(value, instance->single_reg);
+ instance->single_value = value;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ }
+
+ ERROR:
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long ctrl;
+ unsigned long tmp;
+ unsigned long cpu_flags;
+ uint64_t conv_ticks;
+ unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow;
+ unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ conv_ticks =
+ (uint64_t) conv_start_ticks_low +
+ ((uint64_t) conv_start_ticks_high << 32);
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ ME_SUBDEVICE_ENTER
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ if ((inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_FSM) {
+ PERROR("Subdevice is busy.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(ctrl, instance->ctrl_reg);
+ ctrl = ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(ctrl, instance->ctrl_reg);
+
+ if (count != 1) {
+ PERROR("Invalid stream configuration list count specified.\n");
+ err = ME_ERRNO_INVALID_CONFIG_LIST_COUNT;
+ goto ERROR;
+ }
+
+ if (config_list[0].iChannel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ goto ERROR;
+ }
+
+ if (config_list[0].iStreamConfig != 0) {
+ PERROR("Invalid stream config specified.\n");
+ err = ME_ERRNO_INVALID_STREAM_CONFIG;
+ goto ERROR;
+ }
+
+ if (config_list[0].iRef != ME_REF_AO_GROUND) {
+ PERROR("Invalid analog reference.\n");
+ err = ME_ERRNO_INVALID_REF;
+ goto ERROR;
+ }
+
+ if ((trigger->iAcqStartTicksLow != 0)
+ || (trigger->iAcqStartTicksHigh != 0)) {
+ PERROR
+ ("Invalid acquisition start trigger argument specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_START_ARG;
+ goto ERROR;
+ }
+
+ switch (trigger->iAcqStartTrigType) {
+
+ case ME_TRIG_TYPE_SW:
+ break;
+
+ case ME_TRIG_TYPE_EXT_DIGITAL:
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+ switch (trigger->iAcqStartTrigEdge) {
+
+ case ME_TRIG_EDGE_RISING:
+ break;
+
+ case ME_TRIG_EDGE_FALLING:
+ ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE;
+
+ break;
+
+ case ME_TRIG_EDGE_ANY:
+ ctrl |=
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+
+ break;
+
+ default:
+ PERROR
+ ("Invalid acquisition start trigger edge specified.\n");
+
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+
+ goto ERROR;
+
+ break;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid acquisition start trigger type specified.\n");
+
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE;
+
+ goto ERROR;
+
+ break;
+ }
+
+ switch (trigger->iScanStartTrigType) {
+
+ case ME_TRIG_TYPE_FOLLOW:
+ break;
+
+ default:
+ PERROR("Invalid scan start trigger type specified.\n");
+
+ err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE;
+
+ goto ERROR;
+
+ break;
+ }
+
+ switch (trigger->iConvStartTrigType) {
+
+ case ME_TRIG_TYPE_TIMER:
+ if ((conv_ticks < ME4600_AO_MIN_CHAN_TICKS)
+ || (conv_ticks > ME4600_AO_MAX_CHAN_TICKS)) {
+ PERROR
+ ("Invalid conv start trigger argument specified.\n");
+ err = ME_ERRNO_INVALID_CONV_START_ARG;
+ goto ERROR;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid conv start trigger type specified.\n");
+
+ err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE;
+
+ goto ERROR;
+
+ break;
+ }
+
+ /* Preset to hardware wraparound mode */
+ instance->flags &= ~(ME4600_AO_FLAGS_SW_WRAP_MODE_MASK);
+
+ switch (trigger->iScanStopTrigType) {
+
+ case ME_TRIG_TYPE_NONE:
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ /* Set flags to indicate usage of software mode. */
+ instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_INF;
+ instance->wrap_count = 0;
+ instance->wrap_remaining = 0;
+ }
+
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ if (trigger->iScanStopCount <= 0) {
+ PERROR("Invalid scan stop count specified.\n");
+ err = ME_ERRNO_INVALID_SCAN_STOP_ARG;
+ goto ERROR;
+ }
+
+ /* Set flags to indicate usage of software mode. */
+ instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_FIN;
+ instance->wrap_count = trigger->iScanStopCount;
+ instance->wrap_remaining = trigger->iScanStopCount;
+ } else {
+ PERROR("Invalid scan stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid scan stop trigger type specified.\n");
+
+ err = ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE;
+
+ goto ERROR;
+
+ break;
+ }
+
+ switch (trigger->iAcqStopTrigType) {
+
+ case ME_TRIG_TYPE_NONE:
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) {
+ PERROR("Invalid acq stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ }
+
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ if (trigger->iAcqStopCount <= 0) {
+ PERROR("Invalid acq stop count specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_ARG;
+ goto ERROR;
+ }
+
+ /* Set flags to indicate usage of software mode. */
+ instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_FIN;
+ instance->wrap_count = trigger->iAcqStopCount;
+ instance->wrap_remaining = trigger->iAcqStopCount;
+ } else {
+ PERROR("Invalid acp stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid acq stop trigger type specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ goto ERROR;
+ break;
+ }
+
+ switch (trigger->iAcqStartTrigChan) {
+
+ case ME_TRIG_CHAN_DEFAULT:
+ spin_lock(instance->preload_reg_lock);
+ tmp = inl(instance->preload_reg);
+ tmp &= ~(0x10001 << instance->ao_idx);
+ outl(tmp, instance->preload_reg);
+ spin_unlock(instance->preload_reg_lock);
+
+ break;
+
+ case ME_TRIG_CHAN_SYNCHRONOUS:
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) {
+ spin_lock(instance->preload_reg_lock);
+ tmp = inl(instance->preload_reg);
+ tmp &= ~(0x10001 << instance->ao_idx);
+ outl(tmp, instance->preload_reg);
+ tmp |= 0x1 << instance->ao_idx;
+ outl(tmp, instance->preload_reg);
+ spin_unlock(instance->preload_reg_lock);
+ } else {
+ ctrl &= ~(ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ spin_lock(instance->preload_reg_lock);
+ tmp = inl(instance->preload_reg);
+ tmp &= ~(0x10001 << instance->ao_idx);
+ outl(tmp, instance->preload_reg);
+ tmp |= 0x10000 << instance->ao_idx;
+ outl(tmp, instance->preload_reg);
+ spin_unlock(instance->preload_reg_lock);
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid acq start trigger channel specified.\n");
+ err = ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN;
+ goto ERROR;
+
+ break;
+ }
+
+ outl(conv_ticks - 2, instance->timer_reg);
+
+ if (flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) {
+ if (instance->ao_idx == 3) {
+ ctrl |= ME4600_AO_CTRL_BIT_ENABLE_DO;
+ } else {
+ err = ME_ERRNO_INVALID_FLAGS;
+ goto ERROR;
+ }
+ } else {
+ if (instance->ao_idx == 3) {
+ ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_DO;
+ }
+ }
+
+ /* Set hardware mode. */
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ ctrl |= ME4600_AO_CTRL_BIT_MODE_0;
+ } else {
+ ctrl |= ME4600_AO_CTRL_BIT_MODE_1;
+ }
+
+ PDEBUG("Preload word = 0x%X.\n", inl(instance->preload_reg));
+
+ PDEBUG("Ctrl word = 0x%lX.\n", ctrl);
+ outl(ctrl, instance->ctrl_reg); // Write the control word
+
+ ERROR:
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_new_values(me_subdevice_t * subdevice,
+ struct file *filep,
+ int time_out, int *count, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ long j;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ }
+
+ *count = 0;
+
+ ME_SUBDEVICE_ENTER;
+
+ if (t) {
+ j = jiffies;
+ wait_event_interruptible_timeout(instance->wait_queue,
+ ((me_circ_buf_space
+ (&instance->circ_buf))
+ || !(inl(instance->status_reg)
+ &
+ ME4600_AO_STATUS_BIT_FSM)),
+ t);
+
+ if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) {
+ PERROR("AO subdevice is not running.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ } else if (signal_pending(current)) {
+ PERROR("Wait on values interrupted from signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ } else if ((jiffies - j) >= t) {
+ PERROR("Wait on values timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ } else {
+ *count = me_circ_buf_space(&instance->circ_buf);
+ }
+ } else {
+ wait_event_interruptible(instance->wait_queue,
+ ((me_circ_buf_space
+ (&instance->circ_buf))
+ || !(inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)));
+
+ if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) {
+ PERROR("AO subdevice is not running.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ } else if (signal_pending(current)) {
+ PERROR("Wait on values interrupted from signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ } else {
+ *count = me_circ_buf_space(&instance->circ_buf);
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static void stop_immediately(me4600_ao_subdevice_t * instance)
+{
+ unsigned long cpu_flags;
+ uint32_t tmp;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+
+ while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ;
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+}
+
+static int me4600_ao_io_stream_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags = 0;
+ unsigned long ref;
+ unsigned long tmp;
+ unsigned long delay = 0;
+ wait_queue_head_t queue;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ init_waitqueue_head(&queue);
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+
+ if (delay == 0)
+ delay = 1;
+ }
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ ME_SUBDEVICE_ENTER
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ tmp = inl(instance->ctrl_reg);
+
+ switch (tmp & (ME4600_AO_CTRL_MASK_MODE)) {
+
+ case 0: // Single mode
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ PERROR("Subdevice is configured in single mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ goto ERROR;
+
+ case 1: // Wraparound mode
+ if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { // Normal wraparound with external trigger
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+
+ outl(tmp, instance->ctrl_reg);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (start_mode == ME_START_MODE_BLOCKING) {
+ init_waitqueue_head(&queue);
+
+ if (delay) {
+ ref = jiffies;
+
+ while (!
+ (inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+
+ if (((jiffies - ref) >= delay)) {
+ PERROR
+ ("Timeout reached.\n");
+ stop_immediately
+ (instance);
+ err = ME_ERRNO_TIMEOUT;
+ goto ERROR;
+ }
+ }
+ } else {
+ while (!
+ (inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+ }
+ }
+ } else if (start_mode == ME_START_MODE_NONBLOCKING) {
+ } else {
+ PERROR("Invalid start mode specified.\n");
+ err = ME_ERRNO_INVALID_START_MODE;
+ goto ERROR;
+ }
+ } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x10000 << instance->ao_idx)) { // Synchronous with external trigger
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) {
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ outl(tmp, instance->ctrl_reg);
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+
+ if (start_mode == ME_START_MODE_BLOCKING) {
+ init_waitqueue_head(&queue);
+
+ if (delay) {
+ ref = jiffies;
+
+ while (!
+ (inl
+ (instance->
+ status_reg) &
+ ME4600_AO_STATUS_BIT_FSM))
+ {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending
+ (current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err =
+ ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+
+ if (((jiffies - ref) >=
+ delay)) {
+ PERROR
+ ("Timeout reached.\n");
+ stop_immediately
+ (instance);
+ err =
+ ME_ERRNO_TIMEOUT;
+ goto ERROR;
+ }
+ }
+ } else {
+ while (!
+ (inl
+ (instance->
+ status_reg) &
+ ME4600_AO_STATUS_BIT_FSM))
+ {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending
+ (current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err =
+ ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+ }
+ }
+ } else if (start_mode ==
+ ME_START_MODE_NONBLOCKING) {
+ } else {
+ PERROR
+ ("Invalid start mode specified.\n");
+ err = ME_ERRNO_INVALID_START_MODE;
+ goto ERROR;
+ }
+ } else {
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ outl(tmp, instance->ctrl_reg);
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ }
+ } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x1 << instance->ao_idx)) { // Synchronous wraparound with sw trigger
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+
+ outl(tmp, instance->ctrl_reg);
+
+ if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) {
+ outl(0x8000, instance->single_reg);
+ instance->single_value = 0x8000;
+ }
+
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ } else { // Software start
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ |
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+
+ outl(tmp, instance->ctrl_reg);
+
+ outl(0x8000, instance->single_reg);
+ instance->single_value = 0x8000;
+
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ }
+
+ break;
+
+ case 2: // Continuous mode
+ if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { // Externally triggered
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ instance->wrap_remaining = instance->wrap_count;
+ instance->circ_buf.tail = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (start_mode == ME_START_MODE_BLOCKING) {
+ init_waitqueue_head(&queue);
+
+ if (delay) {
+ ref = jiffies;
+
+ while (!
+ (inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+
+ if (((jiffies - ref) >= delay)) {
+ PERROR
+ ("Timeout reached.\n");
+ stop_immediately
+ (instance);
+ err = ME_ERRNO_TIMEOUT;
+ goto ERROR;
+ }
+ }
+ } else {
+ while (!
+ (inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+ }
+ }
+ } else if (start_mode == ME_START_MODE_NONBLOCKING) {
+ /* Do nothing */
+ } else {
+ PERROR("Invalid start mode specified.\n");
+ stop_immediately(instance);
+ err = ME_ERRNO_INVALID_START_MODE;
+ goto ERROR;
+ }
+ } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x10000 << instance->ao_idx)) { // Synchronous with external trigger
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) {
+ tmp |=
+ ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG |
+ ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ outl(tmp, instance->ctrl_reg);
+ instance->wrap_remaining = instance->wrap_count;
+ instance->circ_buf.tail = 0;
+
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+
+ if (start_mode == ME_START_MODE_BLOCKING) {
+ init_waitqueue_head(&queue);
+
+ if (delay) {
+ ref = jiffies;
+
+ while (!
+ (inl
+ (instance->
+ status_reg) &
+ ME4600_AO_STATUS_BIT_FSM))
+ {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending
+ (current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err =
+ ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+
+ if (((jiffies - ref) >=
+ delay)) {
+ PERROR
+ ("Timeout reached.\n");
+ stop_immediately
+ (instance);
+ err =
+ ME_ERRNO_TIMEOUT;
+ goto ERROR;
+ }
+ }
+ } else {
+ while (!
+ (inl
+ (instance->
+ status_reg) &
+ ME4600_AO_STATUS_BIT_FSM))
+ {
+ interruptible_sleep_on_timeout
+ (&queue, 1);
+
+ if (signal_pending
+ (current)) {
+ PERROR
+ ("Wait on start of state machine interrupted.\n");
+ stop_immediately
+ (instance);
+ err =
+ ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+ }
+ }
+ } else if (start_mode ==
+ ME_START_MODE_NONBLOCKING) {
+ } else {
+ PERROR
+ ("Invalid start mode specified.\n");
+ stop_immediately(instance);
+ err = ME_ERRNO_INVALID_START_MODE;
+ goto ERROR;
+ }
+ } else {
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ outl(tmp, instance->ctrl_reg);
+ instance->wrap_remaining = instance->wrap_count;
+ instance->circ_buf.tail = 0;
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ }
+ } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x1 << instance->ao_idx)) { // Synchronous wraparound with sw trigger
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ instance->wrap_remaining = instance->wrap_count;
+ instance->circ_buf.tail = 0;
+ PDEBUG("CTRL Reg = 0x%X.\n", inl(instance->ctrl_reg));
+ outl(tmp, instance->ctrl_reg);
+
+ if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) {
+ outl(0x8000, instance->single_reg);
+ instance->single_value = 0x8000;
+ }
+
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ } else { // Software start
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR("Conversion is already running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP);
+
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ outl(0x8000, instance->single_reg);
+ instance->single_value = 0x8000;
+ instance->wrap_remaining = instance->wrap_count;
+ instance->circ_buf.tail = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ }
+
+ break;
+
+ default:
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ PERROR("Invalid mode configured.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ ERROR:
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_status(me_subdevice_t * subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *values, int flags)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ wait_queue_head_t queue;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ init_waitqueue_head(&queue);
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (wait == ME_WAIT_NONE) {
+ *status =
+ (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ?
+ ME_STATUS_BUSY : ME_STATUS_IDLE;
+ *values = me_circ_buf_space(&instance->circ_buf);
+ } else if (wait == ME_WAIT_IDLE) {
+ while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) {
+ interruptible_sleep_on_timeout(&queue, 1);
+
+ if (instance->flags & ME4600_AO_FLAGS_BROKEN_PIPE) {
+ PERROR("Output stream was interrupted.\n");
+ *status = ME_STATUS_ERROR;
+ err = ME_ERRNO_SUCCESS;
+ goto ERROR;
+ }
+
+ if (signal_pending(current)) {
+ PERROR
+ ("Wait on state machine interrupted by signal.\n");
+ *status = ME_STATUS_INVALID;
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+ }
+
+ *status = ME_STATUS_IDLE;
+
+ *values = me_circ_buf_space(&instance->circ_buf);
+ } else {
+ PERROR("Invalid wait argument specified.\n");
+ *status = ME_STATUS_INVALID;
+ err = ME_ERRNO_INVALID_WAIT;
+ goto ERROR;
+ }
+
+ ERROR:
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int stop_mode, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me4600_ao_subdevice_t *instance;
+ unsigned long cpu_flags;
+ unsigned long tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (stop_mode == ME_STOP_MODE_IMMEDIATE) {
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ tmp = inl(instance->ctrl_reg);
+ tmp |=
+ ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+
+ while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ;
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) {
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_STOP;
+ outl(tmp, instance->ctrl_reg);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ } else {
+ PERROR("Invalid stop mode specified.\n");
+ err = ME_ERRNO_INVALID_STOP_MODE;
+ goto ERROR;
+ }
+
+ ERROR:
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ao_io_stream_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int write_mode,
+ int *values, int *count, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me4600_ao_subdevice_t *instance;
+ unsigned long tmp;
+ int i;
+ int value;
+ int cnt = *count;
+ int c;
+ int k;
+ int ret = 0;
+ unsigned long cpu_flags = 0;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ if (!instance->fifo) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (*count <= 0) {
+ PERROR("Invalid count of values specified.\n");
+ err = ME_ERRNO_INVALID_VALUE_COUNT;
+ goto ERROR;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ tmp = inl(instance->ctrl_reg);
+
+ switch (tmp & 0x3) {
+
+ case 1: // Wraparound mode
+ if (instance->bosch_fw) { // Bosch firmware
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (cnt != 7) {
+ PERROR
+ ("Invalid count of values specified. 7 expected.\n");
+ err = ME_ERRNO_INVALID_VALUE_COUNT;
+ goto ERROR;
+ }
+
+ for (i = 0; i < 7; i++) {
+ if (get_user(value, values)) {
+ PERROR
+ ("Can't copy value from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ if (i == 0) {
+ /* Maximum voltage */
+ value <<= 16;
+ value |=
+ inl(instance->reg_base +
+ 0xD4) & 0xFFFF;
+ outl(value, instance->reg_base + 0xD4);
+ } else if (i == 1) {
+ /* Minimum voltage */
+ value &= 0xFFFF;
+ value |=
+ inl(instance->reg_base +
+ 0xD4) & 0xFFFF0000;
+ outl(value, instance->reg_base + 0xD4);
+ } else if (i == 2) {
+ /* Delta up */
+ value <<= 16;
+ value |=
+ inl(instance->reg_base +
+ 0xD8) & 0xFFFF;
+ outl(value, instance->reg_base + 0xD8);
+ } else if (i == 3) {
+ /* Delta down */
+ value &= 0xFFFF;
+ value |=
+ inl(instance->reg_base +
+ 0xD8) & 0xFFFF0000;
+ outl(value, instance->reg_base + 0xD8);
+ } else if (i == 4) {
+ /* Start value */
+ outl(value, instance->reg_base + 0xDC);
+ } else if (i == 5) {
+ /* Invert */
+ if (value) {
+ value = inl(instance->ctrl_reg);
+ value |= 0x100;
+ outl(value, instance->ctrl_reg);
+ } else {
+ value = inl(instance->ctrl_reg);
+ value &= ~0x100;
+ outl(value, instance->ctrl_reg);
+ }
+ } else if (i == 6) {
+ /* Timer for positive ramp */
+ outl(value, instance->reg_base + 0xE0);
+ }
+
+ values++;
+ }
+ } else { // Normal firmware
+ PDEBUG("Write for wraparound mode.\n");
+
+ if (inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR
+ ("There is already a conversion running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp |= ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO;
+ outl(tmp, instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_FIFO;
+
+ if ((*count > ME4600_AO_FIFO_COUNT) ||
+ ((instance->
+ flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) ==
+ ME4600_AO_FLAGS_SW_WRAP_MODE_FIN)) {
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_MODE_0 |
+ ME4600_AO_CTRL_BIT_MODE_1);
+ tmp |= ME4600_AO_CTRL_BIT_MODE_1;
+ }
+
+ outl(tmp, instance->ctrl_reg);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if ((*count <= ME4600_AO_FIFO_COUNT) &&
+ ((instance->
+ flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) ==
+ ME4600_AO_FLAGS_SW_WRAP_MODE_INF)) {
+ for (i = 0; i < *count; i++) {
+ if (get_user(value, values + i)) {
+ PERROR
+ ("Cannot copy value from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ if (instance->ao_idx & 0x1)
+ value <<= 16;
+
+ outl(value, instance->fifo_reg);
+ }
+ } else if ((*count <= ME4600_AO_CIRC_BUF_COUNT) &&
+ ((instance->
+ flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK)
+ == ME4600_AO_FLAGS_SW_WRAP_MODE_INF)) {
+ for (i = 0; i < *count; i++) {
+ if (get_user(value, values + i)) {
+ PERROR
+ ("Cannot copy value from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ instance->circ_buf.buf[i] = value; /* Used to hold the values. */
+ }
+
+ instance->circ_buf.tail = 0; /* Used as the current read position. */
+ instance->circ_buf.head = *count; /* Used as the buffer size. */
+
+ /* Preload the FIFO. */
+
+ for (i = 0; i < ME4600_AO_FIFO_COUNT;
+ i++, instance->circ_buf.tail++) {
+ if (instance->circ_buf.tail >=
+ instance->circ_buf.head)
+ instance->circ_buf.tail = 0;
+
+ if (instance->ao_idx & 0x1)
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.
+ tail] << 16,
+ instance->fifo_reg);
+ else
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.
+ tail],
+ instance->fifo_reg);
+ }
+ } else if ((*count <= ME4600_AO_CIRC_BUF_COUNT) &&
+ ((instance->
+ flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK)
+ == ME4600_AO_FLAGS_SW_WRAP_MODE_FIN)) {
+ unsigned int preload_count;
+
+ for (i = 0; i < *count; i++) {
+ if (get_user(value, values + i)) {
+ PERROR
+ ("Cannot copy value from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ instance->circ_buf.buf[i] = value; /* Used to hold the values. */
+ }
+
+ instance->circ_buf.tail = 0; /* Used as the current read position. */
+ instance->circ_buf.head = *count; /* Used as the buffer size. */
+
+ /* Try to preload the whole FIFO. */
+ preload_count = ME4600_AO_FIFO_COUNT;
+
+ if (preload_count > instance->wrap_count)
+ preload_count = instance->wrap_count;
+
+ /* Preload the FIFO. */
+ for (i = 0; i < preload_count;
+ i++, instance->circ_buf.tail++) {
+ if (instance->circ_buf.tail >=
+ instance->circ_buf.head)
+ instance->circ_buf.tail = 0;
+
+ if (instance->ao_idx & 0x1)
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.
+ tail] << 16,
+ instance->fifo_reg);
+ else
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.
+ tail],
+ instance->fifo_reg);
+ }
+
+ instance->wrap_remaining =
+ instance->wrap_count - preload_count;
+ } else {
+ PERROR("To many values written.\n");
+ err = ME_ERRNO_INVALID_VALUE_COUNT;
+ goto ERROR;
+ }
+ }
+
+ break;
+
+ case 2: // Continuous mode
+ /* Check if in SW wrapround mode */
+ if (instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) {
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ PERROR("Subdevice is configured SW wrapround mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ goto ERROR;
+ }
+
+ switch (write_mode) {
+
+ case ME_WRITE_MODE_BLOCKING:
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ PDEBUG("Write for blocking continuous mode.\n");
+
+ while (cnt > 0) {
+ wait_event_interruptible(instance->wait_queue,
+ (c =
+ me_circ_buf_space_to_end
+ (&instance->
+ circ_buf)));
+
+ if (instance->
+ flags & ME4600_AO_FLAGS_BROKEN_PIPE) {
+ PERROR
+ ("Broken pipe in blocking write.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ goto ERROR;
+ } else if (signal_pending(current)) {
+ PERROR
+ ("Wait for free buffer interrupted from signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ goto ERROR;
+ }
+
+ PDEBUG("Space to end = %d.\n", c);
+
+ /* Only able to write size of free buffer or size of count */
+
+ if (cnt < c)
+ c = cnt;
+ k = sizeof(int) * c;
+ k -= copy_from_user(instance->circ_buf.buf +
+ instance->circ_buf.head,
+ values, k);
+ c = k / sizeof(int);
+
+ PDEBUG("Copy %d values from user space.\n", c);
+
+ if (!c) {
+ PERROR
+ ("Cannot copy values from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ instance->circ_buf.head =
+ (instance->circ_buf.head +
+ c) & (instance->circ_buf.mask);
+
+ values += c;
+ cnt -= c;
+ ret += c;
+
+ /* Values are now available so enable interrupts */
+ spin_lock_irqsave(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (me_circ_buf_space(&instance->circ_buf)) {
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ }
+
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ }
+
+ *count = ret;
+
+ break;
+
+ case ME_WRITE_MODE_NONBLOCKING:
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ PDEBUG("Write for non blocking continuous mode.\n");
+
+ while (cnt > 0) {
+ if (instance->
+ flags & ME4600_AO_FLAGS_BROKEN_PIPE) {
+ PERROR
+ ("ME4600:Broken pipe in nonblocking write.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ goto ERROR;
+ }
+
+ c = me_circ_buf_space_to_end(&instance->
+ circ_buf);
+
+ if (!c) {
+ PDEBUG
+ ("Returning from nonblocking write.\n");
+ break;
+ }
+
+ PDEBUG("Space to end = %d.\n", c);
+
+ /* Only able to write size of free buffer or size of count */
+
+ if (cnt < c)
+ c = cnt;
+ k = sizeof(int) * c;
+ k -= copy_from_user(instance->circ_buf.buf +
+ instance->circ_buf.head,
+ values, k);
+ c = k / sizeof(int);
+
+ PDEBUG("Copy %d values from user space.\n", c);
+
+ if (!c) {
+ PERROR
+ ("Cannot copy values from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ instance->circ_buf.head =
+ (instance->circ_buf.head +
+ c) & (instance->circ_buf.mask);
+
+ values += c;
+ cnt -= c;
+ ret += c;
+
+ /* Values are now available so enable interrupts */
+ spin_lock_irqsave(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (me_circ_buf_space(&instance->circ_buf)) {
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ }
+
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ }
+
+ *count = ret;
+
+ break;
+
+ case ME_WRITE_MODE_PRELOAD:
+ PDEBUG("Write for preload continuous mode.\n");
+
+ if ((inl(instance->status_reg) &
+ ME4600_AO_STATUS_BIT_FSM)) {
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ PERROR
+ ("Can't Preload DAC FIFO while conversion is running.\n");
+ err = ME_ERRNO_SUBDEVICE_BUSY;
+ goto ERROR;
+ }
+
+ tmp = inl(instance->ctrl_reg);
+
+ tmp |=
+ ME4600_AO_CTRL_BIT_STOP |
+ ME4600_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(tmp, instance->ctrl_reg);
+ tmp &=
+ ~(ME4600_AO_CTRL_BIT_ENABLE_FIFO |
+ ME4600_AO_CTRL_BIT_ENABLE_IRQ);
+ outl(tmp, instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_ENABLE_FIFO;
+ outl(tmp, instance->ctrl_reg);
+
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+ instance->flags &= ~ME4600_AO_FLAGS_BROKEN_PIPE;
+
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ c = ME4600_AO_FIFO_COUNT;
+
+ if (cnt < c)
+ c = cnt;
+
+ for (i = 0; i < c; i++) {
+ if (get_user(value, values)) {
+ PERROR
+ ("Can't copy value from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ if (instance->ao_idx & 0x1)
+ value <<= 16;
+
+ outl(value, instance->fifo_reg);
+
+ values++;
+ }
+
+ cnt -= c;
+
+ ret += c;
+
+ PDEBUG("Wrote %d values to fifo.\n", c);
+
+ while (1) {
+ c = me_circ_buf_space_to_end(&instance->
+ circ_buf);
+
+ if (c == 0)
+ break;
+
+ if (cnt < c)
+ c = cnt;
+
+ if (c <= 0)
+ break;
+
+ k = sizeof(int) * c;
+
+ k -= copy_from_user(instance->circ_buf.buf +
+ instance->circ_buf.head,
+ values, k);
+
+ c = k / sizeof(int);
+
+ PDEBUG("Wrote %d values to circular buffer.\n",
+ c);
+
+ if (!c) {
+ PERROR
+ ("Can't copy values from user space.\n");
+ err = ME_ERRNO_INTERNAL;
+ goto ERROR;
+ }
+
+ instance->circ_buf.head =
+ (instance->circ_buf.head +
+ c) & (instance->circ_buf.mask);
+
+ values += c;
+ cnt -= c;
+ ret += c;
+ }
+
+ *count = ret;
+
+ break;
+
+ default:
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ PERROR("Invalid write mode specified.\n");
+
+ err = ME_ERRNO_INVALID_WRITE_MODE;
+
+ goto ERROR;
+ }
+
+ break;
+
+ default: // Single mode of invalid
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ PERROR("Subdevice is configured in single mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ goto ERROR;
+ }
+
+ ERROR:
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me4600_ao_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me4600_ao_isr(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{
+ unsigned long tmp;
+ int value;
+ me4600_ao_subdevice_t *instance = dev_id;
+ int i;
+ int c = 0;
+ int c1 = 0;
+
+ if (irq != instance->irq) {
+ PDEBUG("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ if (!((0x1 << (instance->ao_idx + 3)) & inl(instance->irq_status_reg))) {
+ return IRQ_NONE;
+ }
+
+ PDEBUG("executed.\n");
+
+ tmp = inl(instance->status_reg);
+
+ if (!(tmp & ME4600_AO_STATUS_BIT_EF) &&
+ (tmp & ME4600_AO_STATUS_BIT_HF) &&
+ (tmp & ME4600_AO_STATUS_BIT_HF)) {
+ c = ME4600_AO_FIFO_COUNT;
+ PDEBUG("Fifo empty.\n");
+ } else if ((tmp & ME4600_AO_STATUS_BIT_EF) &&
+ (tmp & ME4600_AO_STATUS_BIT_HF) &&
+ (tmp & ME4600_AO_STATUS_BIT_HF)) {
+ c = ME4600_AO_FIFO_COUNT / 2;
+ PDEBUG("Fifo under half full.\n");
+ } else {
+ c = 0;
+ PDEBUG("Fifo full.\n");
+ }
+
+ PDEBUG("Try to write 0x%04X values.\n", c);
+
+ if ((instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) ==
+ ME4600_AO_FLAGS_SW_WRAP_MODE_INF) {
+ while (c) {
+ c1 = c;
+
+ if (c1 > (instance->circ_buf.head - instance->circ_buf.tail)) /* Only up to the end of the buffer */
+ c1 = (instance->circ_buf.head -
+ instance->circ_buf.tail);
+
+ /* Write the values to the FIFO */
+ for (i = 0; i < c1; i++, instance->circ_buf.tail++, c--) {
+ if (instance->ao_idx & 0x1)
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.tail] << 16,
+ instance->fifo_reg);
+ else
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.tail],
+ instance->fifo_reg);
+ }
+
+ if (instance->circ_buf.tail >= instance->circ_buf.head) /* Start from beginning */
+ instance->circ_buf.tail = 0;
+ }
+
+ spin_lock(&instance->subdevice_lock);
+
+ tmp = inl(instance->ctrl_reg);
+ tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(tmp, instance->ctrl_reg);
+
+ if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) {
+ PERROR("Broken pipe.\n");
+ instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE;
+ tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+ } else if ((instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) ==
+ ME4600_AO_FLAGS_SW_WRAP_MODE_FIN) {
+ while (c && instance->wrap_remaining) {
+ c1 = c;
+
+ if (c1 > (instance->circ_buf.head - instance->circ_buf.tail)) /* Only up to the end of the buffer */
+ c1 = (instance->circ_buf.head -
+ instance->circ_buf.tail);
+
+ if (c1 > instance->wrap_remaining) /* Only up to count of user defined number of values */
+ c1 = instance->wrap_remaining;
+
+ /* Write the values to the FIFO */
+ for (i = 0; i < c1;
+ i++, instance->circ_buf.tail++, c--,
+ instance->wrap_remaining--) {
+ if (instance->ao_idx & 0x1)
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.tail] << 16,
+ instance->fifo_reg);
+ else
+ outl(instance->circ_buf.
+ buf[instance->circ_buf.tail],
+ instance->fifo_reg);
+ }
+
+ if (instance->circ_buf.tail >= instance->circ_buf.head) /* Start from beginning */
+ instance->circ_buf.tail = 0;
+ }
+
+ spin_lock(&instance->subdevice_lock);
+
+ tmp = inl(instance->ctrl_reg);
+
+ if (!instance->wrap_remaining) {
+ PDEBUG("Finite SW wraparound done.\n");
+ tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ }
+
+ tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+
+ outl(tmp, instance->ctrl_reg);
+ tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(tmp, instance->ctrl_reg);
+
+ if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) {
+ PERROR("Broken pipe.\n");
+ instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE;
+ tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ } else { /* Regular continuous mode */
+
+ while (1) {
+ c1 = me_circ_buf_values_to_end(&instance->circ_buf);
+ PDEBUG("Values to end = %d.\n", c1);
+
+ if (c1 > c)
+ c1 = c;
+
+ if (c1 <= 0) {
+ PDEBUG("Work done or buffer empty.\n");
+ break;
+ }
+
+ if (instance->ao_idx & 0x1) {
+ for (i = 0; i < c1; i++) {
+ value =
+ *(instance->circ_buf.buf +
+ instance->circ_buf.tail +
+ i) << 16;
+ outl(value, instance->fifo_reg);
+ }
+ } else
+ outsl(instance->fifo_reg,
+ instance->circ_buf.buf +
+ instance->circ_buf.tail, c1);
+
+ instance->circ_buf.tail =
+ (instance->circ_buf.tail +
+ c1) & (instance->circ_buf.mask);
+
+ PDEBUG("%d values wrote to port 0x%04X.\n", c1,
+ instance->fifo_reg);
+
+ c -= c1;
+ }
+
+ spin_lock(&instance->subdevice_lock);
+
+ tmp = inl(instance->ctrl_reg);
+
+ if (!me_circ_buf_values(&instance->circ_buf)) {
+ PDEBUG
+ ("Disable Interrupt because no values left in buffer.\n");
+ tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ }
+
+ tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ;
+
+ outl(tmp, instance->ctrl_reg);
+ tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ;
+ outl(tmp, instance->ctrl_reg);
+
+ if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) {
+ PDEBUG("Broken pipe in me4600_ao_isr.\n");
+ instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE;
+ tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ wake_up_interruptible(&instance->wait_queue);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void me4600_ao_destructor(struct me_subdevice *subdevice)
+{
+ me4600_ao_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ free_irq(instance->irq, instance);
+ kfree(instance->circ_buf.buf);
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base,
+ spinlock_t * preload_reg_lock,
+ uint32_t * preload_flags,
+ int ao_idx, int fifo, int irq)
+{
+ me4600_ao_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me4600_ao_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me4600_ao_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->preload_reg_lock = preload_reg_lock;
+ subdevice->preload_flags = preload_flags;
+
+ /* Allocate and initialize circular buffer */
+ subdevice->circ_buf.mask = ME4600_AO_CIRC_BUF_COUNT - 1;
+ subdevice->circ_buf.buf = kmalloc(ME4600_AO_CIRC_BUF_SIZE, GFP_KERNEL);
+
+ if (!subdevice->circ_buf.buf) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ me_subdevice_deinit((me_subdevice_t *) subdevice);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ memset(subdevice->circ_buf.buf, 0, ME4600_AO_CIRC_BUF_SIZE);
+
+ subdevice->circ_buf.head = 0;
+ subdevice->circ_buf.tail = 0;
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ /* Initialize single value to 0V */
+ subdevice->single_value = 0x8000;
+
+ /* Store analog output index */
+ subdevice->ao_idx = ao_idx;
+
+ /* Store if analog output has fifo */
+ subdevice->fifo = fifo;
+
+ /* Initialize registers */
+
+ if (ao_idx == 0) {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_00_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_00_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_00_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_00_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_00_TIMER_REG;
+ subdevice->reg_base = reg_base;
+
+ if (inl(subdevice->reg_base + ME4600_AO_BOSCH_REG) == 0x20000) {
+ PINFO("Bosch firmware in use for channel 0.\n");
+ subdevice->bosch_fw = 1;
+ } else {
+ subdevice->bosch_fw = 0;
+ }
+ } else if (ao_idx == 1) {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_01_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_01_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_01_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_01_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_01_TIMER_REG;
+ subdevice->reg_base = reg_base;
+ subdevice->bosch_fw = 0;
+ } else if (ao_idx == 2) {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_02_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_02_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_02_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_02_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_02_TIMER_REG;
+ subdevice->reg_base = reg_base;
+ subdevice->bosch_fw = 0;
+ } else {
+ subdevice->ctrl_reg = reg_base + ME4600_AO_03_CTRL_REG;
+ subdevice->status_reg = reg_base + ME4600_AO_03_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME4600_AO_03_FIFO_REG;
+ subdevice->single_reg = reg_base + ME4600_AO_03_SINGLE_REG;
+ subdevice->timer_reg = reg_base + ME4600_AO_03_TIMER_REG;
+ subdevice->reg_base = reg_base;
+ subdevice->bosch_fw = 0;
+ }
+
+ subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG;
+ subdevice->preload_reg = reg_base + ME4600_AO_LOADSETREG_XX;
+
+ /* Register interrupt service routine */
+ subdevice->irq = irq;
+
+ if (request_irq
+ (subdevice->irq, me4600_ao_isr, SA_INTERRUPT | SA_SHIRQ,
+ ME4600_NAME, subdevice)) {
+ PERROR("Cannot get interrupt line.\n");
+ me_subdevice_deinit((me_subdevice_t *) subdevice);
+ kfree(subdevice->circ_buf.buf);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Override base class methods. */
+ subdevice->base.me_subdevice_destructor = me4600_ao_destructor;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me4600_ao_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me4600_ao_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me4600_ao_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me4600_ao_io_single_write;
+ subdevice->base.me_subdevice_io_stream_config =
+ me4600_ao_io_stream_config;
+ subdevice->base.me_subdevice_io_stream_new_values =
+ me4600_ao_io_stream_new_values;
+ subdevice->base.me_subdevice_io_stream_write =
+ me4600_ao_io_stream_write;
+ subdevice->base.me_subdevice_io_stream_start =
+ me4600_ao_io_stream_start;
+ subdevice->base.me_subdevice_io_stream_status =
+ me4600_ao_io_stream_status;
+ subdevice->base.me_subdevice_io_stream_stop = me4600_ao_io_stream_stop;
+ subdevice->base.me_subdevice_query_number_channels =
+ me4600_ao_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me4600_ao_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me4600_ao_query_subdevice_caps;
+ subdevice->base.me_subdevice_query_subdevice_caps_args =
+ me4600_ao_query_subdevice_caps_args;
+ subdevice->base.me_subdevice_query_range_by_min_max =
+ me4600_ao_query_range_by_min_max;
+ subdevice->base.me_subdevice_query_number_ranges =
+ me4600_ao_query_number_ranges;
+ subdevice->base.me_subdevice_query_range_info =
+ me4600_ao_query_range_info;
+ subdevice->base.me_subdevice_query_timer = me4600_ao_query_timer;
+
+ return subdevice;
+}
+
+#endif // BOSCH
+
+/* Common functions
+*/
+
+static int me4600_ao_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range)
+{
+ me4600_ao_subdevice_t *instance;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if ((*max - *min) < 0) {
+ PERROR("Invalid minimum and maximum values specified.\n");
+ return ME_ERRNO_INVALID_MIN_MAX;
+ }
+
+ if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) {
+ if ((*max <= (ME4600_AO_MAX_RANGE + 1000))
+ && (*min >= ME4600_AO_MIN_RANGE)) {
+ *min = ME4600_AO_MIN_RANGE;
+ *max = ME4600_AO_MAX_RANGE;
+ *maxdata = ME4600_AO_MAX_DATA;
+ *range = 0;
+ } else {
+ PERROR("No matching range available.\n");
+ return ME_ERRNO_NO_RANGE;
+ }
+ } else {
+ PERROR("Invalid physical unit specified.\n");
+ return ME_ERRNO_INVALID_UNIT;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ao_query_number_ranges(me_subdevice_t * subdevice,
+ int unit, int *count)
+{
+ me4600_ao_subdevice_t *instance;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) {
+ *count = 1;
+ } else {
+ *count = 0;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ao_query_range_info(me_subdevice_t * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata)
+{
+ me4600_ao_subdevice_t *instance;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (range == 0) {
+ *unit = ME_UNIT_VOLT;
+ *min = ME4600_AO_MIN_RANGE;
+ *max = ME4600_AO_MAX_RANGE;
+ *maxdata = ME4600_AO_MAX_DATA;
+ } else {
+ PERROR("Invalid range number specified.\n");
+ return ME_ERRNO_INVALID_RANGE;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ao_query_timer(me_subdevice_t * subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks, long long *max_ticks)
+{
+ me4600_ao_subdevice_t *instance;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if ((timer != ME_TIMER_ACQ_START) && (timer != ME_TIMER_CONV_START)) {
+ PERROR("Invalid timer specified.\n");
+ return ME_ERRNO_INVALID_TIMER;
+ }
+
+ if (instance->fifo) { //Streaming device.
+ *base_frequency = ME4600_AO_BASE_FREQUENCY;
+ if (timer == ME_TIMER_ACQ_START) {
+ *min_ticks = ME4600_AO_MIN_ACQ_TICKS;
+ *max_ticks = ME4600_AO_MAX_ACQ_TICKS;
+ } else if (timer == ME_TIMER_CONV_START) {
+ *min_ticks = ME4600_AO_MIN_CHAN_TICKS;
+ *max_ticks = ME4600_AO_MAX_CHAN_TICKS;
+ }
+ } else { //Not streaming device!
+ *base_frequency = 0;
+ *min_ticks = 0;
+ *max_ticks = 0;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ao_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ me4600_ao_subdevice_t *instance;
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *number = 1;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ao_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ me4600_ao_subdevice_t *instance;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *type = ME_TYPE_AO;
+ *subtype = (instance->fifo) ? ME_SUBTYPE_STREAMING : ME_SUBTYPE_SINGLE;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ao_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ me4600_ao_subdevice_t *instance;
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *caps =
+ ME_CAPS_AO_TRIG_SYNCHRONOUS | ((instance->fifo) ? ME_CAPS_AO_FIFO :
+ ME_CAPS_NONE);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ao_query_subdevice_caps_args(struct me_subdevice *subdevice,
+ int cap, int *args, int count)
+{
+ me4600_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ instance = (me4600_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (count != 1) {
+ PERROR("Invalid capability argument count.\n");
+ return ME_ERRNO_INVALID_CAP_ARG_COUNT;
+ }
+
+ switch (cap) {
+ case ME_CAP_AI_FIFO_SIZE:
+ args[0] = (instance->fifo) ? ME4600_AO_FIFO_COUNT : 0;
+ break;
+
+ case ME_CAP_AI_BUFFER_SIZE:
+ args[0] =
+ (instance->circ_buf.buf) ? ME4600_AO_CIRC_BUF_COUNT : 0;
+ break;
+
+ default:
+ PERROR("Invalid capability.\n");
+ err = ME_ERRNO_INVALID_CAP;
+ args[0] = 0;
+ }
+
+ return err;
+}
diff --git a/drivers/staging/meilhaus/me4600_ao.h b/drivers/staging/meilhaus/me4600_ao.h
new file mode 100644
index 000000000000..6fbc4a2dd9dd
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ao.h
@@ -0,0 +1,263 @@
+/**
+ * @file me4600_ao.h
+ *
+ * @brief Meilhaus ME-4000 analog output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_AO_H_
+# define _ME4600_AO_H_
+
+# include <linux/version.h>
+# include "mesubdevice.h"
+# include "mecirc_buf.h"
+# include "meioctl.h"
+
+# ifdef __KERNEL__
+
+# ifdef BOSCH
+# undef ME_SYNAPSE
+# ifndef _CBUFF_32b_t
+# define _CBUFF_32b_t
+# endif //_CBUFF_32b_t
+# endif //BOSCH
+
+# define ME4600_AO_MAX_SUBDEVICES 4
+# define ME4600_AO_FIFO_COUNT 4096
+
+# define ME4600_AO_BASE_FREQUENCY 33000000LL
+
+# define ME4600_AO_MIN_ACQ_TICKS 0LL
+# define ME4600_AO_MAX_ACQ_TICKS 0LL
+
+# define ME4600_AO_MIN_CHAN_TICKS 66LL
+# define ME4600_AO_MAX_CHAN_TICKS 0xFFFFFFFFLL
+
+# define ME4600_AO_MIN_RANGE -10000000
+# define ME4600_AO_MAX_RANGE 9999694
+
+# define ME4600_AO_MAX_DATA 0xFFFF
+
+# ifdef ME_SYNAPSE
+# define ME4600_AO_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse
+# else
+# define ME4600_AO_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB
+# endif
+# define ME4600_AO_CIRC_BUF_SIZE PAGE_SIZE<<ME4600_AO_CIRC_BUF_SIZE_ORDER // Buffer size in bytes.
+
+# ifdef _CBUFF_32b_t
+# define ME4600_AO_CIRC_BUF_COUNT ((ME4600_AO_CIRC_BUF_SIZE) / sizeof(uint32_t)) // Size in values
+# else
+# define ME4600_AO_CIRC_BUF_COUNT ((ME4600_AO_CIRC_BUF_SIZE) / sizeof(uint16_t)) // Size in values
+# endif
+
+# define ME4600_AO_CONTINOUS 0x0
+# define ME4600_AO_WRAP_MODE 0x1
+# define ME4600_AO_HW_MODE 0x2
+
+# define ME4600_AO_HW_WRAP_MODE (ME4600_AO_WRAP_MODE | ME4600_AO_HW_MODE)
+# define ME4600_AO_SW_WRAP_MODE ME4600_AO_WRAP_MODE
+
+# define ME4600_AO_INF_STOP_MODE 0x0
+# define ME4600_AO_ACQ_STOP_MODE 0x1
+# define ME4600_AO_SCAN_STOP_MODE 0x2
+
+# ifdef BOSCH //SPECIAL BUILD FOR BOSCH
+
+/* Bits for flags attribute. */
+# define ME4600_AO_FLAGS_BROKEN_PIPE 0x1
+# define ME4600_AO_FLAGS_SW_WRAP_MODE_0 0x2
+# define ME4600_AO_FLAGS_SW_WRAP_MODE_1 0x4
+# define ME4600_AO_FLAGS_SW_WRAP_MODE_MASK (ME4600_AO_FLAGS_SW_WRAP_MODE_0 | ME4600_AO_FLAGS_SW_WRAP_MODE_1)
+
+# define ME4600_AO_FLAGS_SW_WRAP_MODE_NONE 0x0
+# define ME4600_AO_FLAGS_SW_WRAP_MODE_INF 0x2
+# define ME4600_AO_FLAGS_SW_WRAP_MODE_FIN 0x4
+
+ /**
+ * @brief The ME-4000 analog output subdevice class.
+ */
+typedef struct me4600_ao_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *preload_reg_lock; /**< Spin lock to protect #preload_reg from concurrent access. */
+ uint32_t *preload_flags;
+
+ unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */
+ me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. */
+ wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */
+
+ int single_value; /**< Mirror of the value written in single mode. */
+
+ int volatile flags; /**< Flags used for storing SW wraparound setup and error signalling from ISR. */
+ unsigned int wrap_count; /**< The user defined wraparound cycle count. */
+ unsigned int wrap_remaining; /**< The wraparound cycle down counter used by a running conversion. */
+ unsigned int ao_idx; /**< The index of this analog output on this device. */
+ int fifo; /**< If set this device has a FIFO. */
+
+ int bosch_fw; /**< If set the bosch firmware is in PROM. */
+
+ /* Registers */
+ uint32_t ctrl_reg;
+ uint32_t status_reg;
+ uint32_t fifo_reg;
+ uint32_t single_reg;
+ uint32_t timer_reg;
+ uint32_t irq_status_reg;
+ uint32_t preload_reg;
+ uint32_t reg_base;
+} me4600_ao_subdevice_t;
+
+ /**
+ * @brief The constructor to generate a ME-4000 analog output subdevice instance for BOSCH project.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access.
+ * @param preload_flags Pointer to spin lock protecting the hold&trigger register from concurrent access.
+ * @param ao_idx Subdevice number.
+ * @param fifo Flag set if subdevice has hardware FIFO.
+ * @param irq IRQ number.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base,
+ spinlock_t * preload_reg_lock,
+ uint32_t * preload_flags,
+ int ao_idx, int fifo, int irq);
+
+# else //~BOSCH
+
+//ME4600_AO_FLAGS_BROKEN_PIPE is OBSOLETE => Now problems are reported in status.
+
+typedef enum ME4600_AO_STATUS {
+ ao_status_none = 0,
+ ao_status_single_configured,
+ ao_status_single_run_wait,
+ ao_status_single_run,
+ ao_status_single_end_wait,
+ ao_status_single_end,
+ ao_status_stream_configured,
+ ao_status_stream_run_wait,
+ ao_status_stream_run,
+ ao_status_stream_end_wait,
+ ao_status_stream_end,
+ ao_status_stream_fifo_error,
+ ao_status_stream_buffer_error,
+ ao_status_stream_error,
+ ao_status_last
+} ME4600_AO_STATUS;
+
+typedef struct me4600_ao_timeout {
+ unsigned long start_time;
+ unsigned long delay;
+} me4600_ao_timeout_t;
+
+ /**
+ * @brief The ME-4600 analog output subdevice class.
+ */
+typedef struct me4600_ao_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+ unsigned int ao_idx; /**< The index of this analog output on this device. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *preload_reg_lock; /**< Spin lock to protect preload_reg from concurrent access. */
+
+ uint32_t *preload_flags;
+
+ /* Hardware feautres */
+ unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */
+ int fifo; /**< If set this device has a FIFO. */
+ int bitpattern; /**< If set this device use bitpattern. */
+
+ int single_value; /**< Mirror of the output value in single mode. */
+ int single_value_in_fifo; /**< Mirror of the value written in single mode. */
+ uint32_t ctrl_trg; /**< Mirror of the trigger settings. */
+
+ volatile int mode; /**< Flags used for storing SW wraparound setup*/
+ int stop_mode; /**< The user defined stop condition flag. */
+ unsigned int start_mode;
+ unsigned int stop_count; /**< The user defined dates presentation end count. */
+ unsigned int stop_data_count; /**< The stop presentation count. */
+ unsigned int data_count; /**< The real presentation count. */
+ unsigned int preloaded_count; /**< The next data addres in buffer. <= for wraparound mode. */
+ int hardware_stop_delay; /**< The time that stop can take. This is only to not show hardware bug to user. */
+
+ volatile enum ME4600_AO_STATUS status; /**< The current stream status flag. */
+ me4600_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */
+
+ /* Registers *//**< All registers are 32 bits long. */
+ unsigned long ctrl_reg;
+ unsigned long status_reg;
+ unsigned long fifo_reg;
+ unsigned long single_reg;
+ unsigned long timer_reg;
+ unsigned long irq_status_reg;
+ unsigned long preload_reg;
+ unsigned long reg_base;
+
+ /* Software buffer */
+ me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. 32 bit long */
+ wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */
+
+ struct workqueue_struct *me4600_workqueue;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ struct work_struct ao_control_task;
+#else
+ struct delayed_work ao_control_task;
+#endif
+
+ volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */
+
+} me4600_ao_subdevice_t;
+
+ /**
+ * @brief The constructor to generate a ME-4600 analog output subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access.
+ * @param preload_flags Pointer to spin lock protecting the hold&trigger register from concurrent access.
+ * @param ao_idx Subdevice number.
+ * @param fifo Flag set if subdevice has hardware FIFO.
+ * @param irq IRQ number.
+ * @param me4600_wq Queue for asynchronous task (1 queue for all subdevice on 1 board).
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base,
+ spinlock_t * preload_reg_lock,
+ uint32_t * preload_flags,
+ int ao_idx,
+ int fifo,
+ int irq,
+ struct workqueue_struct
+ *me4600_wq);
+
+# endif //BOSCH
+# endif //__KERNEL__
+#endif // ~_ME4600_AO_H_
diff --git a/drivers/staging/meilhaus/me4600_ao_reg.h b/drivers/staging/meilhaus/me4600_ao_reg.h
new file mode 100644
index 000000000000..f83d82ecd4bf
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ao_reg.h
@@ -0,0 +1,113 @@
+/**
+ * @file me4600_ao_reg.h
+ *
+ * @brief ME-4000 analog output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_AO_REG_H_
+#define _ME4600_AO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME4600_AO_00_CTRL_REG 0x00 // R/W
+#define ME4600_AO_00_STATUS_REG 0x04 // R/_
+#define ME4600_AO_00_FIFO_REG 0x08 // _/W
+#define ME4600_AO_00_SINGLE_REG 0x0C // R/W
+#define ME4600_AO_00_TIMER_REG 0x10 // _/W
+
+#define ME4600_AO_01_CTRL_REG 0x18 // R/W
+#define ME4600_AO_01_STATUS_REG 0x1C // R/_
+#define ME4600_AO_01_FIFO_REG 0x20 // _/W
+#define ME4600_AO_01_SINGLE_REG 0x24 // R/W
+#define ME4600_AO_01_TIMER_REG 0x28 // _/W
+
+#define ME4600_AO_02_CTRL_REG 0x30 // R/W
+#define ME4600_AO_02_STATUS_REG 0x34 // R/_
+#define ME4600_AO_02_FIFO_REG 0x38 // _/W
+#define ME4600_AO_02_SINGLE_REG 0x3C // R/W
+#define ME4600_AO_02_TIMER_REG 0x40 // _/W
+
+#define ME4600_AO_03_CTRL_REG 0x48 // R/W
+#define ME4600_AO_03_STATUS_REG 0x4C // R/_
+#define ME4600_AO_03_FIFO_REG 0x50 // _/W
+#define ME4600_AO_03_SINGLE_REG 0x54 // R/W
+#define ME4600_AO_03_TIMER_REG 0x58 // _/W
+
+#define ME4600_AO_DEMUX_ADJUST_REG 0xBC // -/W
+#define ME4600_AO_DEMUX_ADJUST_VALUE 0x4C
+
+#ifdef BOSCH
+# define ME4600_AO_BOSCH_REG 0xC4
+
+# define ME4600_AO_LOADSETREG_XX 0xB4 // R/W
+
+# define ME4600_AO_CTRL_BIT_MODE_0 0x001
+# define ME4600_AO_CTRL_BIT_MODE_1 0x002
+# define ME4600_AO_CTRL_MASK_MODE 0x003
+
+#else //~BOSCH
+
+#define ME4600_AO_SYNC_REG 0xB4 // R/W ///ME4600_AO_SYNC_REG <==> ME4600_AO_PRELOAD_REG <==> ME4600_AO_LOADSETREG_XX
+
+# define ME4600_AO_MODE_SINGLE 0x00000000
+# define ME4600_AO_MODE_WRAPAROUND 0x00000001
+# define ME4600_AO_MODE_CONTINUOUS 0x00000002
+# define ME4600_AO_CTRL_MODE_MASK (ME4600_AO_MODE_WRAPAROUND | ME4600_AO_MODE_CONTINUOUS)
+#endif //BOSCH
+
+#define ME4600_AO_CTRL_BIT_MODE_WRAPAROUND ME4600_AO_MODE_WRAPAROUND
+#define ME4600_AO_CTRL_BIT_MODE_CONTINOUS ME4600_AO_MODE_CONTINUOUS
+#define ME4600_AO_CTRL_BIT_STOP 0x00000004
+#define ME4600_AO_CTRL_BIT_ENABLE_FIFO 0x00000008
+#define ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG 0x00000010
+#define ME4600_AO_CTRL_BIT_EX_TRIG_EDGE 0x00000020
+#define ME4600_AO_CTRL_BIT_IMMEDIATE_STOP 0x00000080
+#define ME4600_AO_CTRL_BIT_ENABLE_DO 0x00000100
+#define ME4600_AO_CTRL_BIT_ENABLE_IRQ 0x00000200
+#define ME4600_AO_CTRL_BIT_RESET_IRQ 0x00000400
+#define ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH 0x00000800
+/*
+#define ME4600_AO_SYNC_HOLD_0 0x00000001
+#define ME4600_AO_SYNC_HOLD_1 0x00000002
+#define ME4600_AO_SYNC_HOLD_2 0x00000004
+#define ME4600_AO_SYNC_HOLD_3 0x00000008
+*/
+#define ME4600_AO_SYNC_HOLD 0x00000001
+
+/*
+#define ME4600_AO_SYNC_EXT_TRIG_0 0x00010000
+#define ME4600_AO_SYNC_EXT_TRIG_1 0x00020000
+#define ME4600_AO_SYNC_EXT_TRIG_2 0x00040000
+#define ME4600_AO_SYNC_EXT_TRIG_3 0x00080000
+*/
+#define ME4600_AO_SYNC_EXT_TRIG 0x00010000
+
+#define ME4600_AO_EXT_TRIG 0x80000000
+
+#define ME4600_AO_STATUS_BIT_FSM 0x00000001
+#define ME4600_AO_STATUS_BIT_FF 0x00000002
+#define ME4600_AO_STATUS_BIT_HF 0x00000004
+#define ME4600_AO_STATUS_BIT_EF 0x00000008
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_device.c b/drivers/staging/meilhaus/me4600_device.c
new file mode 100644
index 000000000000..fa455844f4e3
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_device.c
@@ -0,0 +1,373 @@
+/**
+ * @file me4600_device.c
+ *
+ * @brief ME-4600 device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "medevice.h"
+#include "me4600_device.h"
+#include "meplx_reg.h"
+
+#include "mefirmware.h"
+
+#include "mesubdevice.h"
+#include "me4600_do.h"
+#include "me4600_di.h"
+#include "me4600_dio.h"
+#include "me8254.h"
+#include "me4600_ai.h"
+#include "me4600_ao.h"
+#include "me4600_ext_irq.h"
+
+/**
+ * @brief Global variable.
+ * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts).
+ */
+static struct workqueue_struct *me4600_workqueue;
+
+#ifdef BOSCH
+me_device_t *me4600_pci_constructor(struct pci_dev *pci_device, int me_bosch_fw)
+#else //~BOSCH
+me_device_t *me4600_pci_constructor(struct pci_dev *pci_device)
+#endif //BOSCH
+{
+ me4600_device_t *me4600_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ int err;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me4600_device = kmalloc(sizeof(me4600_device_t), GFP_KERNEL);
+
+ if (!me4600_device) {
+ PERROR("Cannot get memory for ME-4600 device instance.\n");
+ return NULL;
+ }
+
+ memset(me4600_device, 0, sizeof(me4600_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me4600_device, pci_device);
+
+ if (err) {
+ kfree(me4600_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+ // Download the xilinx firmware.
+ if (me4600_device->base.info.pci.device_id == PCI_DEVICE_ID_MEILHAUS_ME4610) { //Jekyll <=> me4610
+ err =
+ me_xilinx_download(me4600_device->base.info.pci.
+ reg_bases[1],
+ me4600_device->base.info.pci.
+ reg_bases[5], &pci_device->dev,
+ "me4610.bin");
+ } else { // General me4600 firmware
+#ifdef BOSCH
+ err =
+ me_xilinx_download(me4600_device->base.info.pci.
+ reg_bases[1],
+ me4600_device->base.info.pci.
+ reg_bases[5], &pci_device->dev,
+ (me_bosch_fw) ? "me4600_bosch.bin" :
+ "me4600.bin");
+#else //~BOSCH
+ err =
+ me_xilinx_download(me4600_device->base.info.pci.
+ reg_bases[1],
+ me4600_device->base.info.pci.
+ reg_bases[5], &pci_device->dev,
+ "me4600.bin");
+#endif
+ }
+
+ if (err) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot download firmware.\n");
+ return NULL;
+ }
+ // Get the index in the device version information table.
+ version_idx =
+ me4600_versions_get_device_index(me4600_device->base.info.pci.
+ device_id);
+
+ // Initialize spin locks.
+ spin_lock_init(&me4600_device->preload_reg_lock);
+
+ me4600_device->preload_flags = 0;
+
+ spin_lock_init(&me4600_device->dio_lock);
+ spin_lock_init(&me4600_device->ai_ctrl_lock);
+ spin_lock_init(&me4600_device->ctr_ctrl_reg_lock);
+ spin_lock_init(&me4600_device->ctr_clk_src_reg_lock);
+
+ // Create digital input instances.
+ for (i = 0; i < me4600_versions[version_idx].di_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me4600_di_constructor(me4600_device->
+ base.info.pci.
+ reg_bases[2],
+ &me4600_device->
+ dio_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me4600_device->base.slist,
+ subdevice);
+ }
+
+ // Create digital output instances.
+ for (i = 0; i < me4600_versions[version_idx].do_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me4600_do_constructor(me4600_device->
+ base.info.pci.
+ reg_bases[2],
+ &me4600_device->
+ dio_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me4600_device->base.slist,
+ subdevice);
+ }
+
+ // Create digital input/output instances.
+ for (i = 0; i < me4600_versions[version_idx].dio_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me4600_dio_constructor(me4600_device->
+ base.info.pci.
+ reg_bases[2],
+ me4600_versions
+ [version_idx].
+ do_subdevices +
+ me4600_versions
+ [version_idx].
+ di_subdevices + i,
+ &me4600_device->
+ dio_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me4600_device->base.slist,
+ subdevice);
+ }
+
+ // Create analog input instances.
+ for (i = 0; i < me4600_versions[version_idx].ai_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me4600_ai_constructor(me4600_device->
+ base.info.pci.
+ reg_bases[2],
+ me4600_versions
+ [version_idx].
+ ai_channels,
+ me4600_versions
+ [version_idx].
+ ai_ranges,
+ me4600_versions
+ [version_idx].
+ ai_isolated,
+ me4600_versions
+ [version_idx].
+ ai_sh,
+ me4600_device->
+ base.irq,
+ &me4600_device->
+ ai_ctrl_lock,
+ me4600_workqueue);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me4600_device->base.slist,
+ subdevice);
+ }
+
+ // Create analog output instances.
+ for (i = 0; i < me4600_versions[version_idx].ao_subdevices; i++) {
+#ifdef BOSCH
+ subdevice =
+ (me_subdevice_t *) me4600_ao_constructor(me4600_device->
+ base.info.pci.
+ reg_bases[2],
+ &me4600_device->
+ preload_reg_lock,
+ &me4600_device->
+ preload_flags, i,
+ me4600_versions
+ [version_idx].
+ ao_fifo,
+ me4600_device->
+ base.irq);
+#else //~BOSCH
+ subdevice =
+ (me_subdevice_t *) me4600_ao_constructor(me4600_device->
+ base.info.pci.
+ reg_bases[2],
+ &me4600_device->
+ preload_reg_lock,
+ &me4600_device->
+ preload_flags, i,
+ me4600_versions
+ [version_idx].
+ ao_fifo,
+ me4600_device->
+ base.irq,
+ me4600_workqueue);
+#endif
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me4600_device->base.slist,
+ subdevice);
+ }
+
+ // Create counter instances.
+ for (i = 0; i < me4600_versions[version_idx].ctr_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me8254_constructor(me4600_device->base.
+ info.pci.device_id,
+ me4600_device->base.
+ info.pci.reg_bases[3],
+ 0, i,
+ &me4600_device->
+ ctr_ctrl_reg_lock,
+ &me4600_device->
+ ctr_clk_src_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me4600_device->base.slist,
+ subdevice);
+ }
+
+ // Create external interrupt instances.
+ for (i = 0; i < me4600_versions[version_idx].ext_irq_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *)
+ me4600_ext_irq_constructor(me4600_device->base.info.pci.
+ reg_bases[2],
+ me4600_device->base.irq,
+ &me4600_device->ai_ctrl_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me4600_device);
+ kfree(me4600_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me4600_device->base.slist,
+ subdevice);
+ }
+
+ return (me_device_t *) me4600_device;
+}
+
+// Init and exit of module.
+
+static int __init me4600_init(void)
+{
+ PDEBUG("executed.\n");
+
+#ifndef BOSCH
+ me4600_workqueue = create_singlethread_workqueue("me4600");
+#endif
+ return 0;
+}
+
+static void __exit me4600_exit(void)
+{
+ PDEBUG("executed.\n");
+
+#ifndef BOSCH
+ flush_workqueue(me4600_workqueue);
+ destroy_workqueue(me4600_workqueue);
+#endif
+}
+
+module_init(me4600_init);
+module_exit(me4600_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for ME-46xx Devices");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-46xx Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me4600_pci_constructor);
diff --git a/drivers/staging/meilhaus/me4600_device.h b/drivers/staging/meilhaus/me4600_device.h
new file mode 100644
index 000000000000..fa812d4cc6dc
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_device.h
@@ -0,0 +1,151 @@
+/**
+ * @file me4600_device.h
+ *
+ * @brief ME-4600 device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_DEVICE_H
+#define _ME4600_DEVICE_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure holding ME-4600 device capabilities.
+ */
+typedef struct me4600_version {
+ uint16_t device_id;
+ unsigned int do_subdevices;
+ unsigned int di_subdevices;
+ unsigned int dio_subdevices;
+ unsigned int ctr_subdevices;
+ unsigned int ai_subdevices;
+ unsigned int ai_channels;
+ unsigned int ai_ranges;
+ unsigned int ai_isolated;
+ unsigned int ai_sh;
+ unsigned int ao_subdevices;
+ unsigned int ao_fifo; //How many devices have FIFO
+ unsigned int ext_irq_subdevices;
+} me4600_version_t;
+
+/**
+ * @brief ME-4600 device capabilities.
+ */
+static me4600_version_t me4600_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME4610, 0, 0, 4, 3, 1, 16, 1, 0, 0, 0, 0, 1},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME4650, 0, 0, 4, 0, 1, 16, 4, 0, 0, 0, 0, 1},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME4660, 0, 0, 4, 3, 1, 16, 4, 0, 0, 2, 0, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4660I, 1, 1, 2, 3, 1, 16, 4, 1, 0, 2, 0, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4660S, 0, 0, 4, 3, 1, 16, 4, 0, 1, 2, 0, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4660IS, 1, 1, 2, 3, 1, 16, 4, 1, 1, 2, 0, 1},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME4670, 0, 0, 4, 3, 1, 32, 4, 0, 0, 4, 0, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4670I, 1, 1, 2, 3, 1, 32, 4, 1, 0, 4, 0, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4670S, 0, 0, 4, 3, 1, 32, 4, 0, 1, 4, 0, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4670IS, 1, 1, 2, 3, 1, 32, 4, 1, 1, 4, 0, 1},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME4680, 0, 0, 4, 3, 1, 32, 4, 0, 0, 4, 4, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4680I, 1, 1, 2, 3, 1, 32, 4, 1, 0, 4, 4, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4680S, 0, 0, 4, 3, 1, 32, 4, 0, 1, 4, 4, 1},
+ {PCI_DEVICE_ID_MEILHAUS_ME4680IS, 1, 1, 2, 3, 1, 32, 4, 1, 1, 4, 4, 1},
+
+ {0},
+};
+
+#define ME4600_DEVICE_VERSIONS (sizeof(me4600_versions) / sizeof(me4600_version_t) - 1) /**< Returns the number of entries in #me4600_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #me4600_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me4600_versions.
+ */
+static inline unsigned int me4600_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME4600_DEVICE_VERSIONS; i++)
+ if (me4600_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The ME-4600 device class structure.
+ */
+typedef struct me4600_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+
+ /* Child class attributes. */
+ spinlock_t preload_reg_lock; /**< Guards the preload register of the anaolog output devices. */
+ unsigned int preload_flags; /**< Used in conjunction with #preload_reg_lock. */
+ spinlock_t dio_lock; /**< Locks the control register of the digital input/output subdevices. */
+ spinlock_t ai_ctrl_lock; /**< Locks the control register of the analog input subdevice. */
+ spinlock_t ctr_ctrl_reg_lock; /**< Locks the counter control register. */
+ spinlock_t ctr_clk_src_reg_lock; /**< Not used on this device but needed for the me8254 subdevice constructor call. */
+} me4600_device_t;
+
+/**
+ * @brief The ME-4600 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ * @param me_bosch_fw If set the device shall use the bosch firmware. (Only for special BOSCH build)
+ *
+ * @return On succes a new ME-4600 device instance. \n
+ * NULL on error.
+ */
+
+#ifdef BOSCH
+/**
+ * @brief The ME-4600 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ * @param me_bosch_fw If set the device shall use the bosch firmware.
+ *
+ * @return On succes a new ME-4600 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me4600_pci_constructor(struct pci_dev *pci_device, int me_bosch_fw)
+ __attribute__ ((weak));
+#else //~BOSCH
+/**
+ * @brief The ME-4600 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-4600 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me4600_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+#endif
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_di.c b/drivers/staging/meilhaus/me4600_di.c
new file mode 100644
index 000000000000..7e3c9f4d2df2
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_di.c
@@ -0,0 +1,256 @@
+/**
+ * @file me4600_di.c
+ *
+ * @brief ME-4000 digital input subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me4600_dio_reg.h"
+#include "me4600_di.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me4600_di_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me4600_di_subdevice_t *instance;
+ uint32_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_di_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inl(instance->ctrl_reg);
+ mode &= ~(ME4600_DIO_CTRL_BIT_MODE_2 | ME4600_DIO_CTRL_BIT_MODE_3); //0xFFF3
+ outl(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outl(0, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_di_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me4600_di_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ } else {
+ PERROR("Invalid port direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_di_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me4600_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = inl(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inl(instance->port_reg) & 0xFF;
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_di_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_di_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DI;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base,
+ spinlock_t * ctrl_reg_lock)
+{
+ me4600_di_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me4600_di_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me4600_di_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save the subdevice index */
+ subdevice->port_reg = reg_base + ME4600_DIO_PORT_1_REG;
+ subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me4600_di_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me4600_di_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me4600_di_io_single_read;
+ subdevice->base.me_subdevice_query_number_channels =
+ me4600_di_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me4600_di_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me4600_di_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me4600_di.h b/drivers/staging/meilhaus/me4600_di.h
new file mode 100644
index 000000000000..ec8b175755be
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_di.h
@@ -0,0 +1,64 @@
+/**
+ * @file me4600_di.h
+ *
+ * @brief ME-4000 digital input subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_DI_H_
+#define _ME4600_DI_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me4600_di_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+
+ unsigned long port_reg; /**< Register holding the port status. */
+ unsigned long ctrl_reg; /**< Register to configure the port direction. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me4600_di_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-4000 digital input subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_dio.c b/drivers/staging/meilhaus/me4600_dio.c
new file mode 100644
index 000000000000..0af95d1a8f5d
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_dio.c
@@ -0,0 +1,510 @@
+/**
+ * @file me4600_dio.c
+ *
+ * @brief ME-4000 digital input/output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me4600_dio_reg.h"
+#include "me4600_dio.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me4600_dio_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me4600_dio_subdevice_t *instance;
+ uint32_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_dio_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ /* Set port to input mode */
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inl(instance->ctrl_reg);
+ mode &=
+ ~((ME4600_DIO_CTRL_BIT_MODE_0 | ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ outl(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outl(0, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_dio_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me4600_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t mode;
+ uint32_t size =
+ flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
+ | ME_IO_SINGLE_CONFIG_DIO_WORD |
+ ME_IO_SINGLE_CONFIG_DIO_DWORD);
+ uint32_t mask;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inl(instance->ctrl_reg);
+ switch (size) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ mode &=
+ ~((ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ mode &=
+ ~((ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ mode |=
+ ME4600_DIO_CTRL_BIT_MODE_0 << (instance->
+ dio_idx * 2);
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) {
+ mask =
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
+ dio_idx *
+ 2);
+ mask |=
+ ME4600_DIO_CTRL_BIT_FUNCTION_0 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1;
+ mask |=
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
+ instance->dio_idx;
+ mode &= ~mask;
+
+ if (ref == ME_REF_DIO_FIFO_LOW) {
+ mode |=
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2);
+ mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1;
+ } else if (ref == ME_REF_DIO_FIFO_HIGH) {
+ mode |=
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2);
+ mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1;
+ mode |=
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
+ instance->dio_idx;
+ } else {
+ PERROR
+ ("Invalid port reference specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else if (single_config ==
+ ME_SINGLE_CONFIG_DIO_DEMUX32) {
+ mask =
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
+ dio_idx *
+ 2);
+ mask |=
+ ME4600_DIO_CTRL_BIT_FUNCTION_0 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1;
+ mask |=
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
+ instance->dio_idx;
+ mode &= ~mask;
+
+ if (ref == ME_REF_DIO_FIFO_LOW) {
+ mode |=
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2);
+ mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0;
+ } else if (ref == ME_REF_DIO_FIFO_HIGH) {
+ mode |=
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2);
+ mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0;
+ mode |=
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
+ instance->dio_idx;
+ } else {
+ PERROR
+ ("Invalid port reference specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else if (single_config ==
+ ME_SINGLE_CONFIG_DIO_BIT_PATTERN) {
+ mask =
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) << (instance->
+ dio_idx *
+ 2);
+ mask |=
+ ME4600_DIO_CTRL_BIT_FUNCTION_0 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1;
+ mask |=
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
+ instance->dio_idx;
+ mode &= ~mask;
+
+ if (ref == ME_REF_DIO_FIFO_LOW) {
+ mode |=
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2);
+ } else if (ref == ME_REF_DIO_FIFO_HIGH) {
+ mode |=
+ (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2);
+ mode |=
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 <<
+ instance->dio_idx;
+ } else {
+ PERROR
+ ("Invalid port reference specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR
+ ("Invalid port configuration specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!err) {
+ outl(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_dio_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me4600_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inl(instance->
+ ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ if ((mode ==
+ (ME4600_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value =
+ inl(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inl(instance->
+ ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ if ((mode ==
+ (ME4600_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value = inl(instance->port_reg) & 0xFF;
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_dio_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me4600_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t mode;
+ uint32_t byte;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inl(instance->
+ ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME4600_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) {
+ byte = inl(instance->port_reg) & 0xFF;
+
+ if (value)
+ byte |= 0x1 << channel;
+ else
+ byte &= ~(0x1 << channel);
+
+ outl(byte, instance->port_reg);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inl(instance->
+ ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME4600_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) {
+ outl(value, instance->port_reg);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_dio_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_dio_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DIO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_dio_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_DIR_BYTE;
+ return ME_ERRNO_SUCCESS;
+}
+
+me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock)
+{
+ me4600_dio_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me4600_dio_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me4600_dio_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save digital i/o index */
+ subdevice->dio_idx = dio_idx;
+
+ /* Save the subdevice index */
+ subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG;
+ subdevice->port_reg = reg_base + ME4600_DIO_PORT_REG + (dio_idx * 4);
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me4600_dio_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me4600_dio_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me4600_dio_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me4600_dio_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me4600_dio_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me4600_dio_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me4600_dio_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me4600_dio.h b/drivers/staging/meilhaus/me4600_dio.h
new file mode 100644
index 000000000000..4625ba91f609
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_dio.h
@@ -0,0 +1,69 @@
+/**
+ * @file me4600_dio.h
+ *
+ * @brief ME-4000 digital input/output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_DIO_H_
+#define _ME4600_DIO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me4600_dio_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+ unsigned int dio_idx; /**< The index of the digital i/o on the device. */
+
+ /* Registers */
+ unsigned long port_reg; /**< Register holding the port status. */
+ unsigned long ctrl_reg; /**< Register to configure the port direction. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me4600_dio_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-4000 digital input/ouput subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param dio_idx The index of the digital i/o port on the device.
+ * @param ctrl_reg_lock Spin lock protecting the control register.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_dio_reg.h b/drivers/staging/meilhaus/me4600_dio_reg.h
new file mode 100644
index 000000000000..7a4016a80fd2
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_dio_reg.h
@@ -0,0 +1,63 @@
+/**
+ * @file me4600_dio_reg.h
+ *
+ * @brief ME-4000 digital input/output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_DIO_REG_H_
+#define _ME4600_DIO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME4600_DIO_PORT_0_REG 0xA0 /**< Port 0 register. */
+#define ME4600_DIO_PORT_1_REG 0xA4 /**< Port 1 register. */
+#define ME4600_DIO_PORT_2_REG 0xA8 /**< Port 2 register. */
+#define ME4600_DIO_PORT_3_REG 0xAC /**< Port 3 register. */
+
+#define ME4600_DIO_DIR_REG 0xB0 /**< Direction register. */
+#define ME4600_DIO_PORT_REG ME4600_DIO_PORT_0_REG /**< Base for port's register. */
+
+#define ME4600_DIO_CTRL_REG 0xB8 /**< Control register. */
+/** Port A - DO */
+#define ME4600_DIO_CTRL_BIT_MODE_0 0x0001
+#define ME4600_DIO_CTRL_BIT_MODE_1 0x0002
+/** Port B - DI */
+#define ME4600_DIO_CTRL_BIT_MODE_2 0x0004
+#define ME4600_DIO_CTRL_BIT_MODE_3 0x0008
+/** Port C - DIO */
+#define ME4600_DIO_CTRL_BIT_MODE_4 0x0010
+#define ME4600_DIO_CTRL_BIT_MODE_5 0x0020
+/** Port D - DIO */
+#define ME4600_DIO_CTRL_BIT_MODE_6 0x0040
+#define ME4600_DIO_CTRL_BIT_MODE_7 0x0080
+
+#define ME4600_DIO_CTRL_BIT_FUNCTION_0 0x0100
+#define ME4600_DIO_CTRL_BIT_FUNCTION_1 0x0200
+
+#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 0x0400
+#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_1 0x0800
+#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_2 0x1000
+#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_3 0x2000
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_do.c b/drivers/staging/meilhaus/me4600_do.c
new file mode 100644
index 000000000000..ee591bc1185e
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_do.c
@@ -0,0 +1,433 @@
+/**
+ * @file me4600_do.c
+ *
+ * @brief ME-4000 digital output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me4600_dio_reg.h"
+#include "me4600_do.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me4600_do_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me4600_do_subdevice_t *instance;
+ uint32_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_do_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ /* Set port to output mode */
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inl(instance->ctrl_reg);
+ mode &= ~ME4600_DIO_CTRL_BIT_MODE_1; //0xFFFD
+ mode |= ME4600_DIO_CTRL_BIT_MODE_0; //0x1
+ outl(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outl(0, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_do_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me4600_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t mode;
+ int size =
+ flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
+ | ME_IO_SINGLE_CONFIG_DIO_WORD |
+ ME_IO_SINGLE_CONFIG_DIO_DWORD);
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inl(instance->ctrl_reg);
+
+ switch (size) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1);
+ mode |= (ME4600_DIO_CTRL_BIT_MODE_0);
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) {
+ mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_0 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1 |
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
+
+ if (ref == ME_REF_DIO_FIFO_LOW) {
+ mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1);
+ } else if (ref == ME_REF_DIO_FIFO_HIGH) {
+ mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1
+ |
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
+ } else {
+ PERROR
+ ("Invalid port reference specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else if (single_config ==
+ ME_SINGLE_CONFIG_DIO_DEMUX32) {
+ mode &=
+ ~(ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_0 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1 |
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
+
+ if (ref == ME_REF_DIO_FIFO_LOW) {
+ mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_0);
+ } else if (ref == ME_REF_DIO_FIFO_HIGH) {
+ mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_0
+ |
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
+ } else {
+ PERROR
+ ("Invalid port reference specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else if (single_config ==
+ ME_SINGLE_CONFIG_DIO_BIT_PATTERN) {
+ mode &=
+ ~(ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_0 |
+ ME4600_DIO_CTRL_BIT_FUNCTION_1 |
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
+
+ if (ref == ME_REF_DIO_FIFO_LOW) {
+ mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1);
+ } else if (ref == ME_REF_DIO_FIFO_HIGH) {
+ mode |= (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1 |
+ ME4600_DIO_CTRL_BIT_FIFO_HIGH_0);
+ } else {
+ PERROR
+ ("Invalid port reference specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid port direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!err) {
+ outl(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_do_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me4600_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode =
+ inl(instance->
+ ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1);
+
+ if (mode == ME4600_DIO_CTRL_BIT_MODE_0) {
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value =
+ inl(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inl(instance->port_reg) & 0xFF;
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ } else {
+ PERROR("Port not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_do_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me4600_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t byte;
+ uint32_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode =
+ inl(instance->
+ ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 |
+ ME4600_DIO_CTRL_BIT_MODE_1);
+
+ if (mode == ME4600_DIO_CTRL_BIT_MODE_0) {
+ switch (flags) {
+
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ byte = inl(instance->port_reg) & 0xFF;
+
+ if (value)
+ byte |= 0x1 << channel;
+ else
+ byte &= ~(0x1 << channel);
+
+ outl(byte, instance->port_reg);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ outl(value, instance->port_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ } else {
+ PERROR("Port not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_do_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_do_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base,
+ spinlock_t * ctrl_reg_lock)
+{
+ me4600_do_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me4600_do_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me4600_do_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save the subdevice index */
+ subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG;
+ subdevice->port_reg = reg_base + ME4600_DIO_PORT_0_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me4600_do_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me4600_do_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me4600_do_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me4600_do_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me4600_do_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me4600_do_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me4600_do_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me4600_do.h b/drivers/staging/meilhaus/me4600_do.h
new file mode 100644
index 000000000000..e8385648e925
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_do.h
@@ -0,0 +1,65 @@
+/**
+ * @file me4600_do.h
+ *
+ * @brief ME-4000 digital output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_DO_H_
+#define _ME4600_DO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me4600_do_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+
+ unsigned long port_reg; /**< Register holding the port status. */
+ unsigned long ctrl_reg; /**< Register to configure the port direction. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me4600_do_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-4000 digital output subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param ctrl_reg_lock Spin lock protecting the control register.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_ext_irq.c b/drivers/staging/meilhaus/me4600_ext_irq.c
new file mode 100644
index 000000000000..adc1e1babf40
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ext_irq.c
@@ -0,0 +1,467 @@
+/**
+ * @file me4600_ext_irq.c
+ *
+ * @brief ME-4000 external interrupt subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "meids.h"
+#include "me4600_reg.h"
+#include "me4600_ai_reg.h"
+#include "me4600_ext_irq_reg.h"
+#include "me4600_ext_irq.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me4600_ext_irq_io_irq_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ me4600_ext_irq_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags;
+ uint32_t tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags & ~ME_IO_IRQ_START_DIO_BIT) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((irq_edge != ME_IRQ_EDGE_RISING)
+ && (irq_edge != ME_IRQ_EDGE_FALLING)
+ && (irq_edge != ME_IRQ_EDGE_ANY)
+ ) {
+ PERROR("Invalid irq edge specified.\n");
+ return ME_ERRNO_INVALID_IRQ_EDGE;
+ }
+
+ if (irq_source != ME_IRQ_SOURCE_DIO_LINE) {
+ PERROR("Invalid irq source specified.\n");
+ return ME_ERRNO_INVALID_IRQ_SOURCE;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ tmp = 0x0; //inl(instance->ext_irq_config_reg);
+
+ if (irq_edge == ME_IRQ_EDGE_RISING) {
+ //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK;
+ //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_RISING;
+ } else if (irq_edge == ME_IRQ_EDGE_FALLING) {
+ //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK;
+ //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_FALLING;
+ tmp = ME4600_EXT_IRQ_CONFIG_MASK_FALLING;
+ } else if (irq_edge == ME_IRQ_EDGE_ANY) {
+ //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK;
+ //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_ANY;
+ tmp = ME4600_EXT_IRQ_CONFIG_MASK_ANY;
+ }
+
+ outl(tmp, instance->ext_irq_config_reg);
+ PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ext_irq_config_reg - instance->reg_base, tmp);
+
+ spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags);
+ tmp = inl(instance->ctrl_reg);
+ tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
+ tmp |= ME4600_AI_CTRL_BIT_EX_IRQ;
+ outl(tmp, instance->ctrl_reg);
+ spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags);
+ instance->rised = 0;
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ext_irq_io_irq_wait(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ me4600_ext_irq_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->rised <= 0) {
+ instance->rised = 0;
+ if (time_out) {
+ t = wait_event_interruptible_timeout(instance->
+ wait_queue,
+ (instance->rised !=
+ 0), t);
+
+ if (t == 0) {
+ PERROR
+ ("Wait on external interrupt timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ } else {
+ wait_event_interruptible(instance->wait_queue,
+ (instance->rised != 0));
+ }
+
+ if (instance->rised < 0) {
+ PERROR("Wait on interrupt aborted by user.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on external interrupt aborted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ instance->rised = 0;
+ *irq_count = instance->count;
+ *value = instance->value;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ext_irq_io_irq_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel, int flags)
+{
+ me4600_ext_irq_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags;
+ uint32_t tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+ instance->rised = -1;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me4600_ext_irq_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags)
+{
+ me4600_ext_irq_subdevice_t *instance;
+ unsigned long cpu_flags;
+ uint32_t tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me4600_ext_irq_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->ctrl_reg_lock);
+ tmp = inl(instance->ctrl_reg);
+ tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET);
+ outl(tmp, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->ctrl_reg_lock);
+ instance->rised = -1;
+ instance->count = 0;
+ outl(ME4600_EXT_IRQ_CONFIG_MASK_ANY, instance->ext_irq_config_reg);
+ PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ext_irq_config_reg - instance->reg_base,
+ ME4600_EXT_IRQ_CONFIG_MASK_ANY);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static void me4600_ext_irq_destructor(struct me_subdevice *subdevice)
+{
+ me4600_ext_irq_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+ instance = (me4600_ext_irq_subdevice_t *) subdevice;
+ me_subdevice_deinit(&instance->base);
+ free_irq(instance->irq, instance);
+ kfree(instance);
+}
+
+static int me4600_ext_irq_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 1;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ext_irq_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_EXT_IRQ;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ext_irq_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps =
+ ME_CAPS_EXT_IRQ_EDGE_RISING | ME_CAPS_EXT_IRQ_EDGE_FALLING |
+ ME_CAPS_EXT_IRQ_EDGE_ANY;
+ return ME_ERRNO_SUCCESS;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me4600_ext_irq_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me4600_ext_irq_isr(int irq, void *dev_id,
+ struct pt_regs *regs)
+#endif
+{
+ me4600_ext_irq_subdevice_t *instance;
+ uint32_t ctrl;
+ uint32_t irq_status;
+
+ instance = (me4600_ext_irq_subdevice_t *) dev_id;
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ irq_status = inl(instance->irq_status_reg);
+ if (!(irq_status & ME4600_IRQ_STATUS_BIT_EX)) {
+ PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n",
+ jiffies, __func__, irq_status);
+ return IRQ_NONE;
+ }
+
+ PDEBUG("executed.\n");
+
+ spin_lock(&instance->subdevice_lock);
+ instance->rised = 1;
+ instance->value = inl(instance->ext_irq_value_reg);
+ instance->count++;
+
+ spin_lock(instance->ctrl_reg_lock);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME4600_AI_CTRL_BIT_EX_IRQ_RESET;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ ctrl &= ~ME4600_AI_CTRL_BIT_EX_IRQ_RESET;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ spin_unlock(&instance->subdevice_lock);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+me4600_ext_irq_subdevice_t *me4600_ext_irq_constructor(uint32_t reg_base,
+ int irq,
+ spinlock_t *
+ ctrl_reg_lock)
+{
+ me4600_ext_irq_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me4600_ext_irq_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me4600_ext_irq_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ /* Register interrupt */
+ subdevice->irq = irq;
+
+ if (request_irq(subdevice->irq, me4600_ext_irq_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME4600_NAME, subdevice)) {
+ PERROR("Cannot register interrupt.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", subdevice->irq);
+
+ /* Initialize registers */
+ subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG;
+ subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG;
+ subdevice->ext_irq_config_reg = reg_base + ME4600_EXT_IRQ_CONFIG_REG;
+ subdevice->ext_irq_value_reg = reg_base + ME4600_EXT_IRQ_VALUE_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Override base class methods. */
+ subdevice->base.me_subdevice_destructor = me4600_ext_irq_destructor;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me4600_ext_irq_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_irq_start = me4600_ext_irq_io_irq_start;
+ subdevice->base.me_subdevice_io_irq_wait = me4600_ext_irq_io_irq_wait;
+ subdevice->base.me_subdevice_io_irq_stop = me4600_ext_irq_io_irq_stop;
+ subdevice->base.me_subdevice_query_number_channels =
+ me4600_ext_irq_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me4600_ext_irq_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me4600_ext_irq_query_subdevice_caps;
+
+ subdevice->rised = 0;
+ subdevice->count = 0;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me4600_ext_irq.h b/drivers/staging/meilhaus/me4600_ext_irq.h
new file mode 100644
index 000000000000..3c7b27f9e5dc
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ext_irq.h
@@ -0,0 +1,78 @@
+/**
+ * @file me4600_ext_irq.h
+ *
+ * @brief Meilhaus ME-4000 external interrupt subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_EXT_IRQ_H_
+#define _ME4600_EXT_IRQ_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The subdevice class.
+ */
+typedef struct me4600_ext_irq_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+
+ wait_queue_head_t wait_queue;
+
+ int irq;
+
+ int rised;
+ int value;
+ int count;
+
+ unsigned long ctrl_reg;
+ unsigned long irq_status_reg;
+ unsigned long ext_irq_config_reg;
+ unsigned long ext_irq_value_reg;
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me4600_ext_irq_subdevice_t;
+
+/**
+ * @brief The constructor to generate a external interrupt subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param irq The interrupt number assigned by the PCI BIOS.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me4600_ext_irq_subdevice_t *me4600_ext_irq_constructor(uint32_t reg_base,
+ int irq,
+ spinlock_t *
+ ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_ext_irq_reg.h b/drivers/staging/meilhaus/me4600_ext_irq_reg.h
new file mode 100644
index 000000000000..898e1e74d9e7
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_ext_irq_reg.h
@@ -0,0 +1,41 @@
+/**
+ * @file me4600_ext_irq_reg.h
+ *
+ * @brief ME-4000 external interrupt subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_EXT_IRQ_REG_H_
+#define _ME4600_EXT_IRQ_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME4600_EXT_IRQ_CONFIG_REG 0xCC // R/_
+#define ME4600_EXT_IRQ_VALUE_REG 0xD0 // R/_
+
+#define ME4600_EXT_IRQ_CONFIG_MASK_RISING 0x0
+#define ME4600_EXT_IRQ_CONFIG_MASK_FALLING 0x1
+#define ME4600_EXT_IRQ_CONFIG_MASK_ANY 0x3
+#define ME4600_EXT_IRQ_CONFIG_MASK 0x3
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me4600_reg.h b/drivers/staging/meilhaus/me4600_reg.h
new file mode 100644
index 000000000000..ae152bbc6a3d
--- /dev/null
+++ b/drivers/staging/meilhaus/me4600_reg.h
@@ -0,0 +1,46 @@
+/**
+ * @file me4600_reg.h
+ *
+ * @brief ME-4000 register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME4600_REG_H_
+#define _ME4600_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME4600_IRQ_STATUS_REG 0x9C // R/_
+
+#define ME4600_IRQ_STATUS_BIT_EX 0x01
+#define ME4600_IRQ_STATUS_BIT_LE 0x02
+#define ME4600_IRQ_STATUS_BIT_AI_HF 0x04
+#define ME4600_IRQ_STATUS_BIT_AO_0_HF 0x08
+#define ME4600_IRQ_STATUS_BIT_AO_1_HF 0x10
+#define ME4600_IRQ_STATUS_BIT_AO_2_HF 0x20
+#define ME4600_IRQ_STATUS_BIT_AO_3_HF 0x40
+#define ME4600_IRQ_STATUS_BIT_SC 0x80
+
+#define ME4600_IRQ_STATUS_BIT_AO_HF ME4600_IRQ_STATUS_BIT_AO_0_HF
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me6000_ao.c b/drivers/staging/meilhaus/me6000_ao.c
new file mode 100644
index 000000000000..94f01231f79a
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_ao.c
@@ -0,0 +1,3739 @@
+/**
+ * @file me6000_ao.c
+ *
+ * @brief ME-6000 analog output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/* Includes
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/workqueue.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "meids.h"
+#include "me6000_reg.h"
+#include "me6000_ao_reg.h"
+#include "me6000_ao.h"
+
+/* Defines
+ */
+
+static int me6000_ao_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range);
+
+static int me6000_ao_query_number_ranges(me_subdevice_t * subdevice,
+ int unit, int *count);
+
+static int me6000_ao_query_range_info(me_subdevice_t * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata);
+
+static int me6000_ao_query_timer(me_subdevice_t * subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks, long long *max_ticks);
+
+static int me6000_ao_query_number_channels(me_subdevice_t * subdevice,
+ int *number);
+
+static int me6000_ao_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype);
+
+static int me6000_ao_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps);
+
+static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice,
+ int cap, int *args, int count);
+
+/** Remove subdevice. */
+static void me6000_ao_destructor(struct me_subdevice *subdevice);
+
+/** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'. */
+static int me6000_ao_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags);
+
+/** Set output as single */
+static int me6000_ao_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags);
+
+/** Pass to user actual value of output. */
+static int me6000_ao_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags);
+
+/** Write to output requed value. */
+static int me6000_ao_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags);
+
+/** Set output as streamed device. */
+static int me6000_ao_io_stream_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags);
+
+/** Wait for / Check empty space in buffer. */
+static int me6000_ao_io_stream_new_values(me_subdevice_t * subdevice,
+ struct file *filep,
+ int time_out, int *count, int flags);
+
+/** Start streaming. */
+static int me6000_ao_io_stream_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags);
+
+/** Check actual state. / Wait for end. */
+static int me6000_ao_io_stream_status(me_subdevice_t * subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *values, int flags);
+
+/** Stop streaming. */
+static int me6000_ao_io_stream_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int stop_mode, int flags);
+
+/** Write datas to buffor. */
+static int me6000_ao_io_stream_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int write_mode,
+ int *values, int *count, int flags);
+
+/** Interrupt handler. Copy from buffer to FIFO. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me6000_ao_isr(int irq, void *dev_id);
+#else
+static irqreturn_t me6000_ao_isr(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+
+/** Copy data from circular buffer to fifo (fast) in wraparound mode. */
+int inline ao_write_data_wraparound(me6000_ao_subdevice_t * instance, int count,
+ int start_pos);
+
+/** Copy data from circular buffer to fifo (fast).*/
+int inline ao_write_data(me6000_ao_subdevice_t * instance, int count,
+ int start_pos);
+
+/** Copy data from circular buffer to fifo (slow).*/
+int inline ao_write_data_pooling(me6000_ao_subdevice_t * instance, int count,
+ int start_pos);
+
+/** Copy data from user space to circular buffer. */
+int inline ao_get_data_from_user(me6000_ao_subdevice_t * instance, int count,
+ int *user_values);
+
+/** Stop presentation. Preserve FIFOs. */
+int inline ao_stop_immediately(me6000_ao_subdevice_t * instance);
+
+/** Function for checking timeout in non-blocking mode. */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void me6000_ao_work_control_task(void *subdevice);
+#else
+static void me6000_ao_work_control_task(struct work_struct *work);
+#endif
+
+/* Functions
+ */
+
+static int me6000_ao_io_reset_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t tmp;
+ uint32_t ctrl;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ instance->status = ao_status_none;
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ instance->timeout.delay = 0;
+ instance->timeout.start_time = jiffies;
+
+ //Stop state machine.
+ err = ao_stop_immediately(instance);
+
+ //Remove from synchronous start.
+ spin_lock(instance->preload_reg_lock);
+ tmp = inl(instance->preload_reg);
+ tmp &=
+ ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->
+ ao_idx);
+ outl(tmp, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, tmp);
+ *instance->preload_flags &=
+ ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->
+ ao_idx);
+
+ //Reset triggering flag
+ *instance->triggering_flags &= ~(0x1 << instance->ao_idx);
+ spin_unlock(instance->preload_reg_lock);
+
+ if (instance->fifo) {
+ //Set single mode, dissable FIFO, dissable external trigger, block interrupt.
+ ctrl = ME6000_AO_MODE_SINGLE;
+
+ //Block ISM.
+ ctrl |=
+ (ME6000_AO_CTRL_BIT_STOP |
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP);
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ //Set speed
+ outl(ME6000_AO_MIN_CHAN_TICKS - 1, instance->timer_reg);
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+ }
+
+ instance->hardware_stop_delay = HZ / 10; //100ms
+
+ //Set output to 0V
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->single_reg - instance->reg_base, 0x8000);
+
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ instance->single_value = 0x8000;
+ instance->single_value_in_fifo = 0x8000;
+
+ //Set status to signal that device is unconfigured.
+ instance->status = ao_status_none;
+ //Signal reset if user is on wait.
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t ctrl;
+ uint32_t sync;
+ unsigned long cpu_flags;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. ID=%d\n", instance->ao_idx);
+
+ // Checking parameters
+ if (flags) {
+ PERROR
+ ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (instance->fifo) { //Stream hardware (with or without fifo)
+ if ((trig_edge == ME_TRIG_TYPE_SW)
+ && (trig_edge != ME_TRIG_EDGE_NONE)) {
+ PERROR
+ ("Invalid trigger edge. Software trigger has not edge.\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+
+ if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) {
+ switch (trig_edge) {
+ case ME_TRIG_EDGE_ANY:
+ case ME_TRIG_EDGE_RISING:
+ case ME_TRIG_EDGE_FALLING:
+ break;
+
+ default:
+ PERROR("Invalid trigger edge.\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+ }
+
+ if ((trig_type != ME_TRIG_TYPE_SW)
+ && (trig_type != ME_TRIG_TYPE_EXT_DIGITAL)) {
+ PERROR
+ ("Invalid trigger type. Trigger must be software or digital.\n");
+ return ME_ERRNO_INVALID_TRIG_TYPE;
+ }
+ } else { //Single
+ if (trig_edge != ME_TRIG_EDGE_NONE) {
+ PERROR
+ ("Invalid trigger edge. Single output trigger hasn't own edge.\n");
+ return ME_ERRNO_INVALID_TRIG_EDGE;
+ }
+
+ if (trig_type != ME_TRIG_TYPE_SW) {
+ PERROR
+ ("Invalid trigger type. Trigger must be software.\n");
+ return ME_ERRNO_INVALID_TRIG_TYPE;
+ }
+
+ }
+
+ if ((trig_chan != ME_TRIG_CHAN_DEFAULT)
+ && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) {
+ PERROR("Invalid trigger channel specified.\n");
+ return ME_ERRNO_INVALID_TRIG_CHAN;
+ }
+/*
+ if ((trig_type == ME_TRIG_TYPE_EXT_DIGITAL) && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS))
+ {
+ PERROR("Invalid trigger channel specified. Must be synchronous when digital is choose.\n");
+ return ME_ERRNO_INVALID_TRIG_CHAN;
+ }
+*/
+ if (ref != ME_REF_AO_GROUND) {
+ PERROR
+ ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if (single_config != 0) {
+ PERROR
+ ("Invalid single config specified. Only one range for anlog outputs is available.\n");
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+
+ if (channel != 0) {
+ PERROR
+ ("Invalid channel number specified. Analog output have only one channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ //Subdevice running in stream mode!
+ if ((instance->status >= ao_status_stream_run_wait)
+ && (instance->status < ao_status_stream_end)) {
+ PERROR("Subdevice is busy.\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+/// @note For single all calls (config and write) are erasing previous state!
+
+ instance->status = ao_status_none;
+
+ // Correct single mirrors
+ instance->single_value_in_fifo = instance->single_value;
+
+ //Stop device
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+
+ if (instance->fifo) { // Set control register.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ // Set stop bit. Stop streaming mode (If running.).
+ ctrl = inl(instance->ctrl_reg);
+ //Reset all bits.
+ ctrl =
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP;
+ if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) {
+ PINFO("External digital trigger.\n");
+
+ if (trig_edge == ME_TRIG_EDGE_ANY) {
+// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ instance->ctrl_trg =
+ ME6000_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ } else if (trig_edge == ME_TRIG_EDGE_FALLING) {
+// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE;
+ instance->ctrl_trg =
+ ME6000_AO_CTRL_BIT_EX_TRIG_EDGE;
+ } else if (trig_edge == ME_TRIG_EDGE_RISING) {
+ instance->ctrl_trg = 0x0;
+ }
+ } else if (trig_type == ME_TRIG_TYPE_SW) {
+ PDEBUG("SOFTWARE TRIGGER\n");
+ instance->ctrl_trg = 0x0;
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ } else {
+ PDEBUG("SOFTWARE TRIGGER\n");
+ }
+
+ // Set preload/synchronization register.
+ spin_lock(instance->preload_reg_lock);
+
+ if (trig_type == ME_TRIG_TYPE_SW) {
+ *instance->preload_flags &=
+ ~(ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx);
+ } else //if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL)
+ {
+ *instance->preload_flags |=
+ ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx;
+ }
+
+ if (trig_chan == ME_TRIG_CHAN_DEFAULT) {
+ *instance->preload_flags &=
+ ~(ME6000_AO_SYNC_HOLD << instance->ao_idx);
+ } else //if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS)
+ {
+ *instance->preload_flags |=
+ ME6000_AO_SYNC_HOLD << instance->ao_idx;
+ }
+
+ //Reset hardware register
+ sync = inl(instance->preload_reg);
+ PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, sync);
+ sync &= ~(ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx);
+ sync |= ME6000_AO_SYNC_HOLD << instance->ao_idx;
+
+ //Output configured in default mode (safe one)
+ outl(sync, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, sync);
+ spin_unlock(instance->preload_reg_lock);
+
+ instance->status = ao_status_single_configured;
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ unsigned long j;
+ unsigned long delay = 0;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags & ~ME_IO_SINGLE_NONBLOCKING) {
+ PERROR("Invalid flag specified. %d\n", flags);
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((instance->status >= ao_status_stream_configured)
+ && (instance->status <= ao_status_stream_end)) {
+ PERROR("Subdevice not configured to work in single mode!\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ if (channel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ ME_SUBDEVICE_ENTER;
+ if ((!flags) && (instance->status == ao_status_single_run_wait)) { //Blocking mode. Wait for trigger.
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+ if (delay == 0)
+ delay = 1;
+ }
+
+ j = jiffies;
+
+ //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_single_run_wait),
+ (delay) ? delay : LONG_MAX);
+
+ if (instance->status == ao_status_none) {
+ PDEBUG("Single canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ if ((delay) && ((jiffies - j) >= delay)) {
+ PDEBUG("Timeout reached.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+
+ *value =
+ (!err) ? instance->single_value_in_fifo : instance->
+ single_value;
+ } else { //Non-blocking mode
+ //Read value
+ *value = instance->single_value;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags;
+ unsigned long j;
+ unsigned long delay = 0;
+
+ uint32_t sync_mask;
+ uint32_t mode;
+
+ uint32_t tmp;
+
+/// Workaround for mix-mode - begin
+ uint32_t ctrl = 0x0;
+ uint32_t status;
+/// Workaround for mix-mode - end
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags &
+ ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS |
+ ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((instance->status == ao_status_none)
+ || (instance->status > ao_status_single_end)) {
+ PERROR("Subdevice not configured to work in single mode!\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ if (channel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (value & ~ME6000_AO_MAX_DATA) {
+ PERROR("Invalid value provided.\n");
+ return ME_ERRNO_VALUE_OUT_OF_RANGE;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+/// @note For single all calls (config and write) are erasing previous state!
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+
+ // Correct single mirrors
+ instance->single_value_in_fifo = instance->single_value;
+
+ //Stop device
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+
+ if (delay == 0)
+ delay = 1;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+
+ instance->single_value_in_fifo = value;
+
+ if (instance->fifo) {
+ ctrl = inl(instance->ctrl_reg);
+ }
+
+ if (instance->fifo & ME6000_AO_HAS_FIFO) { /// Workaround for mix-mode - begin
+ //Set speed
+ outl(ME6000_AO_MIN_CHAN_TICKS - 1, instance->timer_reg);
+ PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->timer_reg - instance->reg_base,
+ (int)ME6000_AO_MIN_CHAN_TICKS);
+ instance->hardware_stop_delay = HZ / 10; //100ms
+
+ status = inl(instance->status_reg);
+
+ //Set the continous mode.
+ ctrl &= ~ME6000_AO_CTRL_MODE_MASK;
+ ctrl |= ME6000_AO_MODE_CONTINUOUS;
+
+ //Prepare FIFO
+ if (!(ctrl & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it.
+ PINFO("Enableing FIFO.\n");
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO;
+ } else { //Check if FIFO is empty
+ if (status & ME6000_AO_STATUS_BIT_EF) { //FIFO not empty
+ PINFO("Reseting FIFO.\n");
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_ENABLE_FIFO |
+ ME6000_AO_CTRL_BIT_ENABLE_IRQ);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg -
+ instance->reg_base, ctrl);
+
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO;
+ } else { //FIFO empty, only interrupt needs to be disabled!
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ }
+ }
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ //Write output - 1 value to FIFO
+ if (instance->ao_idx & 0x1) {
+ outl(value <<= 16, instance->fifo_reg);
+ PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->fifo_reg - instance->reg_base,
+ value <<= 16);
+ } else {
+ outl(value, instance->fifo_reg);
+ PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->fifo_reg - instance->reg_base,
+ value);
+ }
+ /// Workaround for mix-mode - end
+ } else { //No FIFO - always in single mode
+ //Write value
+ PDEBUG("Write value\n");
+ outl(value, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base, value);
+ }
+
+ mode = *instance->preload_flags >> instance->ao_idx;
+ mode &= (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG);
+
+ PINFO("Triggering mode: 0x%08x\n", mode);
+
+ spin_lock(instance->preload_reg_lock);
+ sync_mask = inl(instance->preload_reg);
+ PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, sync_mask);
+ switch (mode) {
+ case 0: //0x00000000: Individual software
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+ if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode.
+ sync_mask &=
+ ~((ME6000_AO_SYNC_EXT_TRIG |
+ ME6000_AO_SYNC_HOLD) << instance->
+ ao_idx);
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ } else { // No FIFO - Single mode: In this case resetting 'ME6000_AO_SYNC_HOLD' will trigger output.
+ if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME6000_AO_SYNC_HOLD) { //Now we can set correct mode. This is exception. It is set to synchronous and triggered later.
+ sync_mask &=
+ ~(ME6000_AO_SYNC_EXT_TRIG << instance->
+ ao_idx);
+ sync_mask |=
+ ME6000_AO_SYNC_HOLD << instance->ao_idx;
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ }
+ instance->single_value = value;
+ break;
+
+ case ME6000_AO_SYNC_EXT_TRIG: //0x00010000: Individual hardware
+ PDEBUG("DIGITAL TRIGGER\n");
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+ if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode
+ if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode.
+ sync_mask &=
+ ~((ME6000_AO_SYNC_EXT_TRIG |
+ ME6000_AO_SYNC_HOLD) << instance->
+ ao_idx);
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ } else { // No FIFO - Single mode
+ if ((sync_mask &
+ ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx)) != ME6000_AO_SYNC_HOLD) {
+ //Now we can set correct mode
+ sync_mask &=
+ ~(ME6000_AO_SYNC_EXT_TRIG << instance->
+ ao_idx);
+ sync_mask |=
+ ME6000_AO_SYNC_HOLD << instance->ao_idx;
+
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ }
+ break;
+
+ case ME6000_AO_SYNC_HOLD: //0x00000001: Synchronous software
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+ if ((sync_mask &
+ ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx)) !=
+ (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG)) {
+ //Now we can set correct mode
+ sync_mask |=
+ ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx;
+ sync_mask |= ME6000_AO_SYNC_HOLD << instance->ao_idx;
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ //Set triggering flag
+ *instance->triggering_flags |= 0x1 << instance->ao_idx;
+ break;
+
+ case (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG): //0x00010001: Synchronous hardware
+ PDEBUG("DIGITAL TRIGGER\n");
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+
+ if ((sync_mask &
+ ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx)) !=
+ (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG)) {
+ //Now we can set correct mode
+ sync_mask |=
+ (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx;
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+ }
+ //Set triggering flag
+ *instance->triggering_flags |= 0x1 << instance->ao_idx;
+ break;
+ }
+// spin_unlock(instance->preload_reg_lock); // Moved down.
+
+ if (instance->fifo) { //Activate ISM (remove 'stop' bits)
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH);
+ ctrl |= instance->ctrl_trg;
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_STOP |
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP);
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+/// @note When flag 'ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS' is set than output is triggered. ALWAYS!
+
+ PINFO("<%s> start mode= 0x%08x %s\n", __func__, mode,
+ (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) ? "SYNCHRONOUS" :
+ "");
+ if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs
+ //Add channel to start list
+ outl(sync_mask |
+ (ME6000_AO_SYNC_HOLD << instance->ao_idx),
+ instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask | (ME6000_AO_SYNC_HOLD <<
+ instance->ao_idx));
+
+ //Fire
+ PINFO
+ ("Fired all software synchronous outputs by software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base,
+ 0x8000);
+
+ //Restore save settings
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+
+ } else if (!mode) { //Trigger outputs
+/* //Remove channel from start list
+ outl(sync_mask & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx));
+*/
+ //Fire
+ PINFO("Software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base,
+ 0x8000);
+
+/* //Restore save settings
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask);
+*/
+ }
+/// @note This is mix-mode case. For now I do not have possibility to trigger first 4 channels (continous mode) and other (single) ones at once.
+/// @note Because triggering is not working it can not be add to synchronous list. First 4 channels don't need this information, anyway.
+ *instance->triggering_flags &= 0xFFFFFFF0;
+ } else { // No FIFO - Single mode
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Fired all software synchronous outputs.
+ tmp = ~(*instance->preload_flags | 0xFFFF0000);
+ PINFO
+ ("Fired all software synchronous outputs. mask:0x%08x\n",
+ tmp);
+ tmp |= sync_mask & 0xFFFF0000;
+ // Add this channel to list
+ tmp &= ~(ME6000_AO_SYNC_HOLD << instance->ao_idx);
+
+ //Fire
+ PINFO("Software trigger.\n");
+ outl(tmp, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ tmp);
+
+ //Restore save settings
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+
+ //Set all as triggered.
+ *instance->triggering_flags = 0x0;
+ } else if (!mode) { // Add this channel to list
+ outl(sync_mask &
+ ~(ME6000_AO_SYNC_HOLD << instance->ao_idx),
+ instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask & ~(ME6000_AO_SYNC_HOLD <<
+ instance->ao_idx));
+
+ //Fire
+ PINFO("Software trigger.\n");
+
+ //Restore save settings
+ outl(sync_mask, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ sync_mask);
+
+ //Set all as triggered.
+ *instance->triggering_flags = 0x0;
+ }
+
+ }
+ spin_unlock(instance->preload_reg_lock);
+
+ instance->status = ao_status_single_run_wait;
+
+ instance->timeout.delay = delay;
+ instance->timeout.start_time = jiffies;
+ instance->ao_control_task_flag = 1;
+ queue_delayed_work(instance->me6000_workqueue,
+ &instance->ao_control_task, 1);
+
+ if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) {
+ j = jiffies;
+
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_single_run_wait),
+ (delay) ? delay +
+ 1 : LONG_MAX);
+
+ if (instance->status != ao_status_single_end) {
+ PDEBUG("Single canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ ao_stop_immediately(instance);
+ instance->status = ao_status_none;
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ if ((delay) && ((jiffies - j) >= delay)) {
+ if (instance->status == ao_status_single_end) {
+ PDEBUG("Timeout reached.\n");
+ } else if ((jiffies - j) > delay) {
+ PERROR
+ ("Timeout reached. Not handled by control task!\n");
+ ao_stop_immediately(instance);
+ } else {
+ PERROR
+ ("Timeout reached. Signal come but status is strange: %d\n",
+ instance->status);
+ ao_stop_immediately(instance);
+ }
+
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ instance->status = ao_status_single_end;
+ err = ME_ERRNO_TIMEOUT;
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_stream_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t ctrl;
+ unsigned long cpu_flags;
+ uint64_t conv_ticks;
+ unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow;
+ unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ conv_ticks =
+ (uint64_t) conv_start_ticks_low +
+ ((uint64_t) conv_start_ticks_high << 32);
+
+ if (flags &
+ ~(ME_IO_STREAM_CONFIG_HARDWARE_ONLY |
+ ME_IO_STREAM_CONFIG_WRAPAROUND)) {
+ PERROR("Invalid flags.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) {
+ if (!flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ PERROR
+ ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((trigger->iAcqStopTrigType != ME_TRIG_TYPE_NONE)
+ || (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE)) {
+ PERROR
+ ("Hardware wraparound mode must be in infinite mode.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+ }
+
+ if (count != 1) {
+ PERROR("Only 1 entry in config list acceptable.\n");
+ return ME_ERRNO_INVALID_CONFIG_LIST_COUNT;
+ }
+
+ if (config_list[0].iChannel != 0) {
+ PERROR("Invalid channel number specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (config_list[0].iStreamConfig != 0) {
+ PERROR("Only one range available.\n");
+ return ME_ERRNO_INVALID_STREAM_CONFIG;
+ }
+
+ if (config_list[0].iRef != ME_REF_AO_GROUND) {
+ PERROR("Output is referenced to ground.\n");
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ if ((trigger->iAcqStartTicksLow != 0)
+ || (trigger->iAcqStartTicksHigh != 0)) {
+ PERROR
+ ("Invalid acquisition start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_ARG;
+ }
+
+ if (config_list[0].iFlags) {
+ PERROR("Invalid config list flag.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((trigger->iAcqStartTrigType != ME_TRIG_TYPE_SW)
+ && (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_DIGITAL)) {
+ PERROR("Invalid acquisition start trigger type specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE;
+ }
+
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) {
+ switch (trigger->iAcqStartTrigEdge) {
+ case ME_TRIG_EDGE_RISING:
+ case ME_TRIG_EDGE_FALLING:
+ case ME_TRIG_EDGE_ANY:
+ break;
+
+ default:
+ PERROR
+ ("Invalid acquisition start trigger edge specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+ }
+ }
+
+ if ((trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW)
+ && (trigger->iAcqStartTrigEdge != ME_TRIG_TYPE_NONE)) {
+ PERROR("Invalid acquisition start trigger edge specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE;
+ }
+
+ if (trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) {
+ PERROR("Invalid scan start trigger type specified.\n");
+ return ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE;
+ }
+
+ if (trigger->iConvStartTrigType != ME_TRIG_TYPE_TIMER) {
+ PERROR("Invalid conv start trigger type specified.\n");
+ return ME_ERRNO_INVALID_CONV_START_TRIG_TYPE;
+ }
+
+ if ((conv_ticks < ME6000_AO_MIN_CHAN_TICKS)
+ || (conv_ticks > ME6000_AO_MAX_CHAN_TICKS)) {
+ PERROR("Invalid conv start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_CONV_START_ARG;
+ }
+
+ if (trigger->iAcqStartTicksLow || trigger->iAcqStartTicksHigh) {
+ PERROR("Invalid acq start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_ARG;
+ }
+
+ if (trigger->iScanStartTicksLow || trigger->iScanStartTicksHigh) {
+ PERROR("Invalid scan start trigger argument specified.\n");
+ return ME_ERRNO_INVALID_SCAN_START_ARG;
+ }
+
+ switch (trigger->iScanStopTrigType) {
+ case ME_TRIG_TYPE_NONE:
+ if (trigger->iScanStopCount != 0) {
+ PERROR("Invalid scan stop count specified.\n");
+ return ME_ERRNO_INVALID_SCAN_STOP_ARG;
+ }
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ if (trigger->iScanStopCount <= 0) {
+ PERROR("Invalid scan stop count specified.\n");
+ return ME_ERRNO_INVALID_SCAN_STOP_ARG;
+ }
+ } else {
+ PERROR("The continous mode has not 'scan' contects.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ }
+ break;
+
+ default:
+ PERROR("Invalid scan stop trigger type specified.\n");
+ return ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE;
+ }
+
+ switch (trigger->iAcqStopTrigType) {
+ case ME_TRIG_TYPE_NONE:
+ if (trigger->iAcqStopCount != 0) {
+ PERROR("Invalid acq stop count specified.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_ARG;
+ }
+ break;
+
+ case ME_TRIG_TYPE_COUNT:
+ if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) {
+ PERROR("Invalid acq stop trigger type specified.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ }
+
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) {
+ if (trigger->iAcqStopCount <= 0) {
+ PERROR
+ ("The continous mode has not 'scan' contects.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_ARG;
+ }
+ }
+// else
+// {
+// PERROR("Invalid acq stop trigger type specified.\n");
+// return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+// }
+
+ break;
+
+ default:
+ PERROR("Invalid acq stop trigger type specified.\n");
+ return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE;
+ }
+
+ switch (trigger->iAcqStartTrigChan) {
+ case ME_TRIG_CHAN_DEFAULT:
+ case ME_TRIG_CHAN_SYNCHRONOUS:
+ break;
+
+ default:
+ PERROR("Invalid acq start trigger channel specified.\n");
+ return ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ //Stop device
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+
+ //Check if state machine is stopped.
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ //Reset control register. Block all actions. Disable IRQ. Disable FIFO.
+ ctrl = ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ //This is paranoic, but to be sure.
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+
+ /* Set mode. */
+ if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { //Wraparound
+ if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { //Hardware wraparound
+ PINFO("Hardware wraparound.\n");
+ ctrl |= ME6000_AO_MODE_WRAPAROUND;
+ instance->mode = ME6000_AO_HW_WRAP_MODE;
+ } else { //Software wraparound
+ PINFO("Software wraparound.\n");
+ ctrl |= ME6000_AO_MODE_CONTINUOUS;
+ instance->mode = ME6000_AO_SW_WRAP_MODE;
+ }
+ } else { //Continous
+ PINFO("Continous.\n");
+ ctrl |= ME6000_AO_MODE_CONTINUOUS;
+ instance->mode = ME6000_AO_CONTINOUS;
+ }
+
+ //Set the trigger edge.
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Set the trigger type and edge for external trigger.
+ PINFO("External digital trigger.\n");
+ instance->start_mode = ME6000_AO_EXT_TRIG;
+
+ switch (trigger->iAcqStartTrigEdge) {
+ case ME_TRIG_EDGE_RISING:
+ PINFO("Set the trigger edge: rising.\n");
+ instance->ctrl_trg = 0x0;
+ break;
+
+ case ME_TRIG_EDGE_FALLING:
+ PINFO("Set the trigger edge: falling.\n");
+// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE;
+ instance->ctrl_trg = ME6000_AO_CTRL_BIT_EX_TRIG_EDGE;
+ break;
+
+ case ME_TRIG_EDGE_ANY:
+ PINFO("Set the trigger edge: both edges.\n");
+// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ instance->ctrl_trg =
+ ME6000_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH;
+ break;
+ }
+ } else {
+ PINFO("Internal software trigger.\n");
+ instance->start_mode = 0;
+ }
+
+ //Set the stop mode and value.
+ if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of data
+ instance->stop_mode = ME6000_AO_ACQ_STOP_MODE;
+ instance->stop_count = trigger->iAcqStopCount;
+ } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of 'scans'
+ instance->stop_mode = ME6000_AO_SCAN_STOP_MODE;
+ instance->stop_count = trigger->iScanStopCount;
+ } else { //Infinite
+ instance->stop_mode = ME6000_AO_INF_STOP_MODE;
+ instance->stop_count = 0;
+ }
+
+ PINFO("Stop count: %d.\n", instance->stop_count);
+
+ if (trigger->iAcqStartTrigChan == ME_TRIG_CHAN_SYNCHRONOUS) { //Synchronous start
+ instance->start_mode |= ME6000_AO_SYNC_HOLD;
+ if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Externaly triggered
+ PINFO("Synchronous start. Externaly trigger active.\n");
+ instance->start_mode |= ME6000_AO_SYNC_EXT_TRIG;
+ }
+#ifdef MEDEBUG_INFO
+ else {
+ PINFO
+ ("Synchronous start. Externaly trigger dissabled.\n");
+ }
+#endif
+
+ }
+ //Set speed
+ outl(conv_ticks - 2, instance->timer_reg);
+ PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%llx\n", instance->reg_base,
+ instance->timer_reg - instance->reg_base, conv_ticks - 2);
+ instance->hardware_stop_delay = (int)(conv_ticks * HZ) / ME6000_AO_BASE_FREQUENCY; //<== MUST be with cast!
+
+ // Write the control word
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Set status.
+ instance->status = ao_status_stream_configured;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_stream_new_values(me_subdevice_t * subdevice,
+ struct file *filep,
+ int time_out, int *count, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ long j;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!instance->circ_buf.buf) {
+ PERROR("Circular buffer not exists.\n");
+ return ME_ERRNO_INTERNAL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (me_circ_buf_space(&instance->circ_buf)) { //The buffer is NOT full.
+ *count = me_circ_buf_space(&instance->circ_buf);
+ } else { //The buffer is full.
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ } else { //Max time.
+ t = LONG_MAX;
+ }
+
+ *count = 0;
+
+ j = jiffies;
+
+ //Only runing process will interrupt this call. Interrupts are when FIFO HF is signaled.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ ((me_circ_buf_space
+ (&instance->circ_buf))
+ || !(inl(instance->status_reg)
+ &
+ ME6000_AO_STATUS_BIT_FSM)),
+ t);
+
+ if (!(inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM)) {
+ PERROR("AO subdevice is not running.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ } else if (signal_pending(current)) {
+ PERROR("Wait on values interrupted from signal.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ } else if ((jiffies - j) >= t) {
+ PERROR("Wait on values timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ } else { //Uff... all is good. Inform user about empty space.
+ *count = me_circ_buf_space(&instance->circ_buf);
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_stream_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long cpu_flags = 0;
+ uint32_t status;
+ uint32_t ctrl;
+ uint32_t synch;
+ int count = 0;
+ int circ_buffer_count;
+
+ unsigned long ref;
+ unsigned long delay = 0;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags & ~ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) {
+ PERROR("Invalid flags.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid timeout specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if ((start_mode != ME_START_MODE_BLOCKING)
+ && (start_mode != ME_START_MODE_NONBLOCKING)) {
+ PERROR("Invalid start mode specified.\n");
+ return ME_ERRNO_INVALID_START_MODE;
+ }
+
+ if (time_out) {
+ delay = (time_out * HZ) / 1000;
+ if (delay == 0)
+ delay = 1;
+ }
+
+ switch (instance->status) { //Checking actual mode.
+ case ao_status_stream_configured:
+ case ao_status_stream_end:
+ //Correct modes!
+ break;
+
+ //The device is in wrong mode.
+ case ao_status_none:
+ case ao_status_single_configured:
+ case ao_status_single_run_wait:
+ case ao_status_single_run:
+ case ao_status_single_end_wait:
+ PERROR
+ ("Subdevice must be preinitialize correctly for streaming.\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+
+ case ao_status_stream_fifo_error:
+ case ao_status_stream_buffer_error:
+ case ao_status_stream_error:
+ PDEBUG("Before restart broke stream 'STOP' must be caled.\n");
+ return ME_STATUS_ERROR;
+
+ case ao_status_stream_run_wait:
+ case ao_status_stream_run:
+ case ao_status_stream_end_wait:
+ PDEBUG("Stream is already working.\n");
+ return ME_ERRNO_SUBDEVICE_BUSY;
+
+ default:
+ instance->status = ao_status_stream_error;
+ PERROR_CRITICAL("Status is in wrong state!\n");
+ return ME_ERRNO_INTERNAL;
+
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->mode == ME6000_AO_CONTINOUS) { //Continous
+ instance->circ_buf.tail += instance->preloaded_count;
+ instance->circ_buf.tail &= instance->circ_buf.mask;
+ }
+ circ_buffer_count = me_circ_buf_values(&instance->circ_buf);
+
+ if (!circ_buffer_count && !instance->preloaded_count) { //No values in buffer
+ ME_SUBDEVICE_EXIT;
+ PERROR("No values in buffer!\n");
+ return ME_ERRNO_LACK_OF_RESOURCES;
+ }
+
+ //Cancel control task
+ PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx);
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+
+ //Stop device
+ err = ao_stop_immediately(instance);
+ if (err) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUBDEVICE_BUSY;
+ }
+ //Set values for single_read()
+ instance->single_value = ME6000_AO_MAX_DATA + 1;
+ instance->single_value_in_fifo = ME6000_AO_MAX_DATA + 1;
+
+ //Setting stop points
+ if (instance->stop_mode == ME6000_AO_SCAN_STOP_MODE) {
+ instance->stop_data_count =
+ instance->stop_count * circ_buffer_count;
+ } else {
+ instance->stop_data_count = instance->stop_count;
+ }
+
+ if ((instance->stop_data_count != 0)
+ && (instance->stop_data_count < circ_buffer_count)) {
+ PERROR("More data in buffer than previously set limit!\n");
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ //Check FIFO
+ if (!(ctrl & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. <= This should be done by user call with ME_WRITE_MODE_PRELOAD
+ PINFO("Enableing FIFO.\n");
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO;
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ } else { //Block IRQ
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ //Fill FIFO <= Generaly this should be done by user pre-load call but this is second place to do it.
+ status = inl(instance->status_reg);
+ if (!(status & ME6000_AO_STATUS_BIT_EF)) { //FIFO empty
+ if (instance->stop_data_count != 0) {
+ count = ME6000_AO_FIFO_COUNT;
+ } else {
+ count =
+ (ME6000_AO_FIFO_COUNT <
+ instance->
+ stop_data_count) ? ME6000_AO_FIFO_COUNT :
+ instance->stop_data_count;
+ }
+
+ //Copy data
+ count =
+ ao_write_data(instance, count, instance->preloaded_count);
+
+ if (count < 0) { //This should never happend!
+ PERROR_CRITICAL("COPY FINISH WITH ERROR!\n");
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ }
+ //Set pre-load features.
+ spin_lock(instance->preload_reg_lock);
+ synch = inl(instance->preload_reg);
+ synch &=
+ ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->
+ ao_idx);
+ synch |=
+ (instance->start_mode & ~ME6000_AO_EXT_TRIG) << instance->ao_idx;
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->preload_reg - instance->reg_base, synch);
+ spin_unlock(instance->preload_reg_lock);
+
+ //Default count is '0'
+ if (instance->mode == ME6000_AO_CONTINOUS) { //Continous
+ instance->preloaded_count = 0;
+ instance->circ_buf.tail += count;
+ instance->circ_buf.tail &= instance->circ_buf.mask;
+ } else { //Wraparound
+ instance->preloaded_count += count;
+ instance->data_count += count;
+
+ //Special case: Infinite wraparound with less than FIFO datas always should runs in hardware mode.
+ if ((instance->stop_mode == ME6000_AO_INF_STOP_MODE)
+ && (circ_buffer_count <= ME6000_AO_FIFO_COUNT)) { //Change to hardware wraparound
+ PDEBUG
+ ("Changeing mode from software wraparound to hardware wraparound.\n");
+ //Copy all data
+ count =
+ ao_write_data(instance, circ_buffer_count,
+ instance->preloaded_count);
+ ctrl &= ~ME6000_AO_CTRL_MODE_MASK;
+ ctrl |= ME6000_AO_MODE_WRAPAROUND;
+ }
+
+ if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator.
+ instance->preloaded_count = 0;
+ } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend!
+ PERROR_CRITICAL
+ ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n");
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ }
+
+ //Set status to 'wait for start'
+ instance->status = ao_status_stream_run_wait;
+
+ status = inl(instance->status_reg);
+ //Start state machine and interrupts
+ PINFO("<%s:%d> Start state machine.\n", __func__, __LINE__);
+ ctrl &= ~(ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP);
+ if (instance->start_mode == ME6000_AO_EXT_TRIG) {
+ PDEBUG("DIGITAL TRIGGER\n");
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG;
+ }
+ if (!(status & ME6000_AO_STATUS_BIT_HF)) { //More than half!
+ if ((ctrl & ME6000_AO_CTRL_MODE_MASK) == ME6000_AO_MODE_CONTINUOUS) { //Enable IRQ only when hardware_continous is set and FIFO is more than half
+ PINFO("<%s:%d> Start interrupts.\n", __func__,
+ __LINE__);
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ }
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ //Trigger output
+ PINFO("<%s> start mode= 0x%x %s\n", __func__, instance->start_mode,
+ (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) ? "SYNCHRONOUS" :
+ "");
+ if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs
+ spin_lock(instance->preload_reg_lock);
+ synch = inl(instance->preload_reg);
+ //Add channel to start list
+ outl(synch | (ME6000_AO_SYNC_HOLD << instance->ao_idx),
+ instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ synch | (ME6000_AO_SYNC_HOLD << instance->ao_idx));
+
+ //Fire
+ PINFO
+ ("Fired all software synchronous outputs by software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base, 0x8000);
+
+ //Restore save settings
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base, synch);
+ spin_unlock(instance->preload_reg_lock);
+ } else if (!instance->start_mode) { //Trigger outputs
+/*
+ spin_lock(instance->preload_reg_lock);
+ synch = inl(instance->preload_reg);
+ //Remove channel from start list
+ outl(synch & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx));
+*/
+ //Fire
+ PINFO("Software trigger.\n");
+ outl(0x8000, instance->single_reg);
+ PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base, 0x8000);
+
+/*
+ //Restore save settings
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch);
+ spin_unlock(instance->preload_reg_lock);
+*/
+ }
+ // Set control task's timeout
+ instance->timeout.delay = delay;
+ instance->timeout.start_time = jiffies;
+
+ if (status & ME6000_AO_STATUS_BIT_HF) { //Less than half but not empty!
+ PINFO("Less than half.\n");
+ if (instance->stop_data_count == 0) {
+ count = ME6000_AO_FIFO_COUNT / 2;
+ } else {
+ count =
+ ((ME6000_AO_FIFO_COUNT / 2) <
+ instance->stop_data_count) ? ME6000_AO_FIFO_COUNT /
+ 2 : instance->stop_data_count;
+ }
+
+ //Copy data
+ count =
+ ao_write_data(instance, count, instance->preloaded_count);
+
+ if (count < 0) { //This should never happend!
+ PERROR_CRITICAL("COPY FINISH WITH ERROR!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+
+ if (instance->mode == ME6000_AO_CONTINOUS) { //Continous
+ instance->circ_buf.tail += count;
+ instance->circ_buf.tail &= instance->circ_buf.mask;
+ } else { //Wraparound
+ instance->data_count += count;
+ instance->preloaded_count += count;
+
+ if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator.
+ instance->preloaded_count = 0;
+ } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend!
+ PERROR_CRITICAL
+ ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME6000_AO_STATUS_BIT_HF)) { //More than half!
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ PINFO("<%s:%d> Start interrupts.\n", __func__,
+ __LINE__);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+ }
+ }
+ //Special case: Limited wraparound with less than HALF FIFO datas need work around to generate first interrupt.
+ if ((instance->stop_mode != ME6000_AO_INF_STOP_MODE)
+ && (instance->mode == ME6000_AO_SW_WRAP_MODE)
+ && (circ_buffer_count <= (ME6000_AO_FIFO_COUNT / 2))) { //Put more data to FIFO
+ PINFO("Limited wraparound with less than HALF FIFO datas.\n");
+ if (instance->preloaded_count) { //This should never happend!
+ PERROR_CRITICAL
+ ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+
+ while (instance->stop_data_count > instance->data_count) { //Maximum data not set jet.
+ //Copy to buffer
+ if (circ_buffer_count != ao_write_data(instance, circ_buffer_count, 0)) { //This should never happend!
+ PERROR_CRITICAL
+ ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n");
+ ME_SUBDEVICE_EXIT;
+ return ME_ERRNO_INTERNAL;
+ }
+ instance->data_count += circ_buffer_count;
+
+ if (!((status = inl(instance->status_reg)) & ME6000_AO_STATUS_BIT_HF)) { //FIFO is more than half. Enable IRQ and end copy.
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ spin_lock_irqsave(&instance->subdevice_lock,
+ cpu_flags);
+ PINFO("<%s:%d> Start interrupts.\n",
+ __func__, __LINE__);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg -
+ instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+ break;
+ }
+ }
+ }
+ // Schedule control task
+ instance->ao_control_task_flag = 1;
+ queue_delayed_work(instance->me6000_workqueue,
+ &instance->ao_control_task, 1);
+
+ if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start.
+ ref = jiffies;
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_stream_run_wait),
+ (delay) ? delay +
+ 1 : LONG_MAX);
+
+ if ((instance->status != ao_status_stream_run)
+ && (instance->status != ao_status_stream_end)) {
+ PDEBUG("Starting stream canceled. %d\n",
+ instance->status);
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on start of state machine interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ if ((delay) && ((jiffies - ref) >= delay)) {
+ if (instance->status != ao_status_stream_run) {
+ if (instance->status == ao_status_stream_end) {
+ PDEBUG("Timeout reached.\n");
+ } else if ((jiffies - ref) > delay) {
+ PERROR
+ ("Timeout reached. Not handled by control task!\n");
+ ao_stop_immediately(instance);
+ } else {
+ PERROR
+ ("Timeout reached. Signal come but status is strange: %d\n",
+ instance->status);
+ ao_stop_immediately(instance);
+ }
+
+ instance->ao_control_task_flag = 0;
+ cancel_delayed_work(&instance->ao_control_task);
+ instance->status = ao_status_stream_end;
+ err = ME_ERRNO_TIMEOUT;
+ }
+ }
+ }
+
+ ME_SUBDEVICE_EXIT;
+ return err;
+}
+
+static int me6000_ao_io_stream_status(me_subdevice_t * subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *values, int flags)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((wait != ME_WAIT_NONE) && (wait != ME_WAIT_IDLE)) {
+ PERROR("Invalid wait argument specified.\n");
+ *status = ME_STATUS_INVALID;
+ return ME_ERRNO_INVALID_WAIT;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ switch (instance->status) {
+ case ao_status_single_configured:
+ case ao_status_single_end:
+ case ao_status_stream_configured:
+ case ao_status_stream_end:
+ case ao_status_stream_fifo_error:
+ case ao_status_stream_buffer_error:
+ case ao_status_stream_error:
+ *status = ME_STATUS_IDLE;
+ break;
+
+ case ao_status_single_run_wait:
+ case ao_status_single_run:
+ case ao_status_single_end_wait:
+ case ao_status_stream_run_wait:
+ case ao_status_stream_run:
+ case ao_status_stream_end_wait:
+ *status = ME_STATUS_BUSY;
+ break;
+
+ case ao_status_none:
+ default:
+ *status =
+ (inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM) ?
+ ME_STATUS_BUSY : ME_STATUS_IDLE;
+ break;
+ }
+
+ if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) {
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ ((instance->status !=
+ ao_status_single_run_wait)
+ && (instance->status !=
+ ao_status_single_run)
+ && (instance->status !=
+ ao_status_single_end_wait)
+ && (instance->status !=
+ ao_status_stream_run_wait)
+ && (instance->status !=
+ ao_status_stream_run)
+ && (instance->status !=
+ ao_status_stream_end_wait)),
+ LONG_MAX);
+
+ if (instance->status != ao_status_stream_end) {
+ PDEBUG("Wait for IDLE canceled. %d\n",
+ instance->status);
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait for IDLE interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ *status = ME_STATUS_IDLE;
+ }
+
+ *values = me_circ_buf_space(&instance->circ_buf);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_stream_stop(me_subdevice_t * subdevice,
+ struct file *filep,
+ int stop_mode, int flags)
+{ /// @note Stop work and empty buffer and FIFO
+ int err = ME_ERRNO_SUCCESS;
+ me6000_ao_subdevice_t *instance;
+ unsigned long cpu_flags;
+ volatile uint32_t ctrl;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (flags & ~ME_IO_STREAM_STOP_PRESERVE_BUFFERS) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((stop_mode != ME_STOP_MODE_IMMEDIATE)
+ && (stop_mode != ME_STOP_MODE_LAST_VALUE)) {
+ PERROR("Invalid stop mode specified.\n");
+ return ME_ERRNO_INVALID_STOP_MODE;
+ }
+
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (instance->status < ao_status_stream_configured) {
+ //There is nothing to stop!
+ PERROR("Subdevice not in streaming mode. %d\n",
+ instance->status);
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ //Mark as stopping. => Software stop.
+ instance->status = ao_status_stream_end_wait;
+
+ if (stop_mode == ME_STOP_MODE_IMMEDIATE) { //Stopped now!
+ err = ao_stop_immediately(instance);
+ } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) {
+ ctrl = inl(instance->ctrl_reg) & ME6000_AO_CTRL_MODE_MASK;
+ if (ctrl == ME6000_AO_MODE_WRAPAROUND) { //Hardware wraparound => Hardware stop.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME6000_AO_CTRL_BIT_STOP;
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+ }
+ //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason.
+ wait_event_interruptible_timeout(instance->wait_queue,
+ (instance->status !=
+ ao_status_stream_end_wait),
+ LONG_MAX);
+
+ if (instance->status != ao_status_stream_end) {
+ PDEBUG("Stopping stream canceled.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Stopping stream interrupted.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ }
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |= ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ if (!flags) { //Reset FIFO
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_FIFO;
+ }
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ if (!flags) { //Reset software buffer
+ instance->circ_buf.head = 0;
+ instance->circ_buf.tail = 0;
+ instance->preloaded_count = 0;
+ instance->data_count = 0;
+ }
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_ao_io_stream_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int write_mode,
+ int *values, int *count, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me6000_ao_subdevice_t *instance;
+ unsigned long cpu_flags = 0;
+ uint32_t reg_copy;
+
+ int copied_from_user = 0;
+ int left_to_copy_from_user = *count;
+
+ int copied_values;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ //Checking arguments
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) {
+ PERROR("Not a streaming ao.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+ }
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (*count <= 0) {
+ PERROR("Invalid count of values specified.\n");
+ return ME_ERRNO_INVALID_VALUE_COUNT;
+ }
+
+ if (values == NULL) {
+ PERROR("Invalid address of values specified.\n");
+ return ME_ERRNO_INVALID_POINTER;
+ }
+
+ if ((instance->status == ao_status_none) || (instance->status == ao_status_single_configured)) { //The device is in single mode.
+ PERROR
+ ("Subdevice must be preinitialize correctly for streaming.\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+
+ switch (write_mode) {
+ case ME_WRITE_MODE_PRELOAD:
+
+ //Device must be stopped.
+ if ((instance->status != ao_status_stream_configured)
+ && (instance->status != ao_status_stream_end)) {
+ PERROR
+ ("Subdevice mustn't be runing when 'pre-load' mode is used.\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ break;
+ case ME_WRITE_MODE_NONBLOCKING:
+ case ME_WRITE_MODE_BLOCKING:
+ /// @note In blocking mode: When device is not runing and there is not enought space call will blocked up!
+ /// @note Some other thread must empty buffer by strating engine.
+ break;
+
+ default:
+ PERROR("Invalid write mode specified.\n");
+ return ME_ERRNO_INVALID_WRITE_MODE;
+ }
+
+ if (instance->mode & ME6000_AO_WRAP_MODE) { //Wraparound mode. Device must be stopped.
+ if ((instance->status != ao_status_stream_configured)
+ && (instance->status != ao_status_stream_end)) {
+ PERROR
+ ("Subdevice mustn't be runing when 'pre-load' mode is used.\n");
+ return ME_ERRNO_INVALID_WRITE_MODE;
+ }
+ }
+
+ if ((instance->mode == ME6000_AO_HW_WRAP_MODE)
+ && (write_mode != ME_WRITE_MODE_PRELOAD)) {
+/*
+ PERROR("Only 'pre-load' write is acceptable in hardware wraparound mode.\n");
+ return ME_ERRNO_PREVIOUS_CONFIG;
+*/
+ //This is transparent for user.
+ PDEBUG("Changing write_mode to ME_WRITE_MODE_PRELOAD.\n");
+ write_mode = ME_WRITE_MODE_PRELOAD;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (write_mode == ME_WRITE_MODE_PRELOAD) { //Init enviroment - preload
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ reg_copy = inl(instance->ctrl_reg);
+ //Check FIFO
+ if (!(reg_copy & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO not active. Enable it.
+ reg_copy |= ME6000_AO_CTRL_BIT_ENABLE_FIFO;
+ outl(reg_copy, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ reg_copy);
+ instance->preloaded_count = 0;
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ }
+
+ while (1) {
+ //Copy to buffer. This step is common for all modes.
+ copied_from_user =
+ ao_get_data_from_user(instance, left_to_copy_from_user,
+ values + (*count -
+ left_to_copy_from_user));
+ left_to_copy_from_user -= copied_from_user;
+
+ reg_copy = inl(instance->status_reg);
+ if ((instance->status == ao_status_stream_run) && !(reg_copy & ME6000_AO_STATUS_BIT_FSM)) { //BROKEN PIPE! The state machine is stoped but logical status show that should be working.
+ PERROR("Broken pipe in write.\n");
+ err = ME_ERRNO_SUBDEVICE_NOT_RUNNING;
+ break;
+ }
+
+ if ((instance->status == ao_status_stream_run) && (instance->mode == ME6000_AO_CONTINOUS) && (reg_copy & ME6000_AO_STATUS_BIT_HF)) { //Continous mode runing and data are below half!
+
+ // Block interrupts.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ reg_copy = inl(instance->ctrl_reg);
+ reg_copy &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(reg_copy, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ reg_copy);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ //Fast copy
+ copied_values =
+ ao_write_data(instance, ME6000_AO_FIFO_COUNT / 2,
+ 0);
+ if (copied_values > 0) {
+ instance->circ_buf.tail += copied_values;
+ instance->circ_buf.tail &=
+ instance->circ_buf.mask;
+ continue;
+ }
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ // Activate interrupts.
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ reg_copy = inl(instance->ctrl_reg);
+ reg_copy |= ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(reg_copy, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ reg_copy);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (copied_values == 0) { //This was checked and never should happend!
+ PERROR_CRITICAL("COPY FINISH WITH 0!\n");
+ }
+
+ if (copied_values < 0) { //This was checked and never should happend!
+ PERROR_CRITICAL("COPY FINISH WITH ERROR!\n");
+ instance->status = ao_status_stream_fifo_error;
+ err = ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ break;
+ }
+ }
+
+ if (!left_to_copy_from_user) { //All datas were copied.
+ break;
+ } else { //Not all datas were copied.
+ if (instance->mode & ME6000_AO_WRAP_MODE) { //Error too much datas! Wraparound is limited in size!
+ PERROR
+ ("Too much data for wraparound mode! Exceeded size of %ld.\n",
+ ME6000_AO_CIRC_BUF_COUNT - 1);
+ err = ME_ERRNO_RING_BUFFER_OVERFLOW;
+ break;
+ }
+
+ if (write_mode != ME_WRITE_MODE_BLOCKING) { //Non blocking calls
+ break;
+ }
+
+ wait_event_interruptible(instance->wait_queue,
+ me_circ_buf_space(&instance->
+ circ_buf));
+
+ if (signal_pending(current)) {
+ PERROR("Writing interrupted by signal.\n");
+ instance->status = ao_status_none;
+ ao_stop_immediately(instance);
+ err = ME_ERRNO_SIGNAL;
+ break;
+ }
+
+ if (instance->status == ao_status_none) { //Reset
+ PERROR("Writing interrupted by reset.\n");
+ err = ME_ERRNO_CANCELLED;
+ break;
+ }
+ }
+ }
+
+ if (write_mode == ME_WRITE_MODE_PRELOAD) { //Copy data to FIFO - preload
+ copied_values =
+ ao_write_data_pooling(instance, ME6000_AO_FIFO_COUNT,
+ instance->preloaded_count);
+ instance->preloaded_count += copied_values;
+ instance->data_count += copied_values;
+
+ if ((instance->mode == ME6000_AO_HW_WRAP_MODE)
+ && (me_circ_buf_values(&instance->circ_buf) >
+ ME6000_AO_FIFO_COUNT)) {
+ PERROR
+ ("Too much data for hardware wraparound mode! Exceeded size of %d.\n",
+ ME6000_AO_FIFO_COUNT);
+ err = ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ }
+ }
+
+ *count = *count - left_to_copy_from_user;
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me6000_ao_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me6000_ao_isr(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{
+ me6000_ao_subdevice_t *instance = dev_id;
+ uint32_t irq_status;
+ uint32_t ctrl;
+ uint32_t status;
+ int count = 0;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ irq_status = inl(instance->irq_status_reg);
+ if (!(irq_status & (ME6000_IRQ_STATUS_BIT_AO_HF << instance->ao_idx))) {
+ PINFO("%ld Shared interrupt. %s(): ID=%d: status_reg=0x%04X\n",
+ jiffies, __func__, instance->ao_idx, irq_status);
+ return IRQ_NONE;
+ }
+
+ if (!instance->circ_buf.buf) {
+ instance->status = ao_status_stream_error;
+ PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n");
+ //Block interrupts. Stop machine.
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |=
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Inform user
+ wake_up_interruptible_all(&instance->wait_queue);
+ return IRQ_HANDLED;
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME6000_AO_STATUS_BIT_FSM)) { //Too late. Not working! END? BROKEN PIPE?
+ /// @note Error checking was moved to separate task.
+ PDEBUG("Interrupt come but ISM is not working!\n");
+ //Block interrupts. Stop machine.
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ ctrl |=
+ ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ /// @note User notification was also moved to separate task.
+ return IRQ_HANDLED;
+ }
+ //General procedure. Process more datas.
+
+#ifdef MEDEBUG_DEBUG
+ if (!me_circ_buf_values(&instance->circ_buf)) { //Buffer is empty!
+ PDEBUG("Circular buffer empty!\n");
+ }
+#endif
+
+ //Check FIFO
+ if (status & ME6000_AO_STATUS_BIT_HF) { //OK less than half
+
+ //Block interrupts
+ ctrl = inl(instance->ctrl_reg);
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+
+ do {
+ //Calculate how many should be copied.
+ count =
+ (instance->stop_data_count) ? instance->
+ stop_data_count -
+ instance->data_count : ME6000_AO_FIFO_COUNT / 2;
+ if (ME6000_AO_FIFO_COUNT / 2 < count) {
+ count = ME6000_AO_FIFO_COUNT / 2;
+ }
+ //Copy data
+ if (instance->mode == ME6000_AO_CONTINOUS) { //Continous
+ count = ao_write_data(instance, count, 0);
+ if (count > 0) {
+ instance->circ_buf.tail += count;
+ instance->circ_buf.tail &=
+ instance->circ_buf.mask;
+ instance->data_count += count;
+
+ if ((instance->status == ao_status_stream_end_wait) && !me_circ_buf_values(&instance->circ_buf)) { //Stoping. Whole buffer was copied.
+ break;
+ }
+ }
+ } else if ((instance->mode == ME6000_AO_SW_WRAP_MODE) && ((ctrl & ME6000_AO_CTRL_MODE_MASK) == ME6000_AO_MODE_CONTINUOUS)) { //Wraparound (software)
+ if (instance->status == ao_status_stream_end_wait) { //We stoping => Copy to the end of the buffer.
+ count =
+ ao_write_data(instance, count, 0);
+ } else { //Copy in wraparound mode.
+ count =
+ ao_write_data_wraparound(instance,
+ count,
+ instance->
+ preloaded_count);
+ }
+
+ if (count > 0) {
+ instance->data_count += count;
+ instance->preloaded_count += count;
+ instance->preloaded_count %=
+ me_circ_buf_values(&instance->
+ circ_buf);
+
+ if ((instance->status == ao_status_stream_end_wait) && !instance->preloaded_count) { //Stoping. Whole buffer was copied.
+ break;
+ }
+ }
+ }
+
+ if ((count <= 0) || (instance->stop_data_count && (instance->stop_data_count <= instance->data_count))) { //End of work.
+ break;
+ }
+ } //Repeat if still is under half fifo
+ while ((status =
+ inl(instance->status_reg)) & ME6000_AO_STATUS_BIT_HF);
+
+ //Unblock interrupts
+ ctrl = inl(instance->ctrl_reg);
+ if (count >= 0) { //Copy was successful.
+ if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. No more interrupts.
+ PDEBUG("Finishing work. Interrupt disabled.\n");
+ instance->status = ao_status_stream_end_wait;
+ } else if (count > 0) { //Normal work. Enable interrupt.
+ PDEBUG("Normal work. Enable interrupt.\n");
+ ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ;
+ } else { //Normal work but there are no more data in buffer. Interrupt blocked. stream_write() will unblock it.
+ PDEBUG
+ ("No data in software buffer. Interrupt blocked.\n");
+ }
+ } else { //Error during copy.
+ instance->status = ao_status_stream_fifo_error;
+ }
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ } else { //?? more than half
+ PDEBUG
+ ("Interrupt come but FIFO more than half full! Reset interrupt.\n");
+ }
+
+ PINFO("ISR: Buffer count: %d.(T:%d H:%d)\n",
+ me_circ_buf_values(&instance->circ_buf), instance->circ_buf.tail,
+ instance->circ_buf.head);
+ PINFO("ISR: Stop count: %d.\n", instance->stop_count);
+ PINFO("ISR: Stop data count: %d.\n", instance->stop_data_count);
+ PINFO("ISR: Data count: %d.\n", instance->data_count);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ //Inform user
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+static void me6000_ao_destructor(struct me_subdevice *subdevice)
+{
+ me6000_ao_subdevice_t *instance;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ instance->ao_control_task_flag = 0;
+
+ // Reset subdevice to asure clean exit.
+ me6000_ao_io_reset_subdevice(subdevice, NULL,
+ ME_IO_RESET_SUBDEVICE_NO_FLAGS);
+
+ // Remove any tasks from work queue. This is paranoic because it was done allready in reset().
+ if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue.
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(2);
+ }
+
+ if (instance->fifo & ME6000_AO_HAS_FIFO) {
+ if (instance->irq) {
+ free_irq(instance->irq, instance);
+ instance->irq = 0;
+ }
+
+ if (instance->circ_buf.buf) {
+ PDEBUG("free circ_buf = %p size=%d",
+ instance->circ_buf.buf,
+ PAGE_SHIFT << ME6000_AO_CIRC_BUF_SIZE_ORDER);
+ free_pages((unsigned long)instance->circ_buf.buf,
+ ME6000_AO_CIRC_BUF_SIZE_ORDER);
+ }
+ instance->circ_buf.buf = NULL;
+ }
+
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base,
+ spinlock_t * preload_reg_lock,
+ uint32_t * preload_flags,
+ uint32_t * triggering_flags,
+ int ao_idx,
+ int fifo,
+ int irq,
+ int high_range,
+ struct workqueue_struct *me6000_wq)
+{
+ me6000_ao_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed ID=%d.\n", ao_idx);
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me6000_ao_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me6000_ao_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->preload_reg_lock = preload_reg_lock;
+ subdevice->preload_flags = preload_flags;
+ subdevice->triggering_flags = triggering_flags;
+
+ /* Store analog output index */
+ subdevice->ao_idx = ao_idx;
+
+ /* Store if analog output has fifo */
+ subdevice->fifo = fifo;
+
+ if (subdevice->fifo & ME6000_AO_HAS_FIFO) {
+ /* Allocate and initialize circular buffer */
+ subdevice->circ_buf.mask = ME6000_AO_CIRC_BUF_COUNT - 1;
+ subdevice->circ_buf.buf =
+ (void *)__get_free_pages(GFP_KERNEL,
+ ME6000_AO_CIRC_BUF_SIZE_ORDER);
+ PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf,
+ ME6000_AO_CIRC_BUF_SIZE);
+
+ if (!subdevice->circ_buf.buf) {
+ PERROR
+ ("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+
+ memset(subdevice->circ_buf.buf, 0, ME6000_AO_CIRC_BUF_SIZE);
+ } else {
+ subdevice->circ_buf.mask = 0;
+ subdevice->circ_buf.buf = NULL;
+ }
+ subdevice->circ_buf.head = 0;
+ subdevice->circ_buf.tail = 0;
+
+ subdevice->status = ao_status_none;
+ subdevice->ao_control_task_flag = 0;
+ subdevice->timeout.delay = 0;
+ subdevice->timeout.start_time = jiffies;
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ /* Initialize single value to 0V */
+ subdevice->single_value = 0x8000;
+ subdevice->single_value_in_fifo = 0x8000;
+
+ /* Initialize range boarders */
+ if (high_range) {
+ subdevice->min = ME6000_AO_MIN_RANGE_HIGH;
+ subdevice->max = ME6000_AO_MAX_RANGE_HIGH;
+ } else {
+ subdevice->min = ME6000_AO_MIN_RANGE;
+ subdevice->max = ME6000_AO_MAX_RANGE;
+ }
+
+ /* Register interrupt service routine */
+
+ if (subdevice->fifo & ME6000_AO_HAS_FIFO) {
+ subdevice->irq = irq;
+ if (request_irq(subdevice->irq, me6000_ao_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME6000_NAME, subdevice)) {
+ PERROR("Cannot get interrupt line.\n");
+ PDEBUG("free circ_buf = %p size=%d",
+ subdevice->circ_buf.buf,
+ PAGE_SHIFT << ME6000_AO_CIRC_BUF_SIZE_ORDER);
+ free_pages((unsigned long)subdevice->circ_buf.buf,
+ ME6000_AO_CIRC_BUF_SIZE_ORDER);
+ subdevice->circ_buf.buf = NULL;
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", subdevice->irq);
+ } else {
+ subdevice->irq = 0;
+ }
+
+ /* Initialize registers */
+ // Only streamed subdevices support interrupts. For the rest this register has no meaning.
+ subdevice->irq_status_reg = reg_base + ME6000_AO_IRQ_STATUS_REG;
+ subdevice->preload_reg = reg_base + ME6000_AO_PRELOAD_REG;
+
+ if (ao_idx == 0) {
+ subdevice->ctrl_reg = reg_base + ME6000_AO_00_CTRL_REG;
+ subdevice->status_reg = reg_base + ME6000_AO_00_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME6000_AO_00_FIFO_REG;
+ subdevice->timer_reg = reg_base + ME6000_AO_00_TIMER_REG;
+ subdevice->irq_reset_reg =
+ reg_base + ME6000_AO_00_IRQ_RESET_REG;
+ subdevice->single_reg = reg_base + ME6000_AO_00_SINGLE_REG;
+ } else if (ao_idx == 1) {
+ subdevice->ctrl_reg = reg_base + ME6000_AO_01_CTRL_REG;
+ subdevice->status_reg = reg_base + ME6000_AO_01_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME6000_AO_01_FIFO_REG;
+ subdevice->timer_reg = reg_base + ME6000_AO_01_TIMER_REG;
+ subdevice->irq_reset_reg =
+ reg_base + ME6000_AO_01_IRQ_RESET_REG;
+ subdevice->single_reg = reg_base + ME6000_AO_01_SINGLE_REG;
+ } else if (ao_idx == 2) {
+ subdevice->ctrl_reg = reg_base + ME6000_AO_02_CTRL_REG;
+ subdevice->status_reg = reg_base + ME6000_AO_02_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME6000_AO_02_FIFO_REG;
+ subdevice->timer_reg = reg_base + ME6000_AO_02_TIMER_REG;
+ subdevice->irq_reset_reg =
+ reg_base + ME6000_AO_02_IRQ_RESET_REG;
+ subdevice->single_reg = reg_base + ME6000_AO_02_SINGLE_REG;
+ } else if (ao_idx == 3) {
+ subdevice->ctrl_reg = reg_base + ME6000_AO_03_CTRL_REG;
+ subdevice->status_reg = reg_base + ME6000_AO_03_STATUS_REG;
+ subdevice->fifo_reg = reg_base + ME6000_AO_03_FIFO_REG;
+ subdevice->timer_reg = reg_base + ME6000_AO_03_TIMER_REG;
+ subdevice->irq_reset_reg =
+ reg_base + ME6000_AO_03_IRQ_RESET_REG;
+ subdevice->single_reg = reg_base + ME6000_AO_03_SINGLE_REG;
+ } else {
+ subdevice->ctrl_reg = reg_base + ME6000_AO_DUMY;
+ subdevice->fifo_reg = reg_base + ME6000_AO_DUMY;
+ subdevice->timer_reg = reg_base + ME6000_AO_DUMY;
+ subdevice->irq_reset_reg = reg_base + ME6000_AO_DUMY;
+ subdevice->single_reg = reg_base + ME6000_AO_DUMY;
+
+ subdevice->status_reg = reg_base + ME6000_AO_SINGLE_STATUS_REG;
+ if (ao_idx == 4) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_04_SINGLE_REG;
+ } else if (ao_idx == 5) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_05_SINGLE_REG;
+ } else if (ao_idx == 6) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_06_SINGLE_REG;
+ } else if (ao_idx == 7) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_07_SINGLE_REG;
+ } else if (ao_idx == 8) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_08_SINGLE_REG;
+ } else if (ao_idx == 9) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_09_SINGLE_REG;
+ } else if (ao_idx == 10) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_10_SINGLE_REG;
+ } else if (ao_idx == 11) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_11_SINGLE_REG;
+ } else if (ao_idx == 12) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_12_SINGLE_REG;
+ } else if (ao_idx == 13) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_13_SINGLE_REG;
+ } else if (ao_idx == 14) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_14_SINGLE_REG;
+ } else if (ao_idx == 15) {
+ subdevice->single_reg =
+ reg_base + ME6000_AO_15_SINGLE_REG;
+ } else {
+ PERROR_CRITICAL("WRONG SUBDEVICE ID=%d!", ao_idx);
+ me_subdevice_deinit((me_subdevice_t *) subdevice);
+ if (subdevice->fifo) {
+ free_pages((unsigned long)subdevice->circ_buf.
+ buf, ME6000_AO_CIRC_BUF_SIZE_ORDER);
+ }
+ subdevice->circ_buf.buf = NULL;
+ kfree(subdevice);
+ return NULL;
+ }
+ }
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Override base class methods. */
+ subdevice->base.me_subdevice_destructor = me6000_ao_destructor;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me6000_ao_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me6000_ao_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me6000_ao_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me6000_ao_io_single_write;
+ subdevice->base.me_subdevice_io_stream_config =
+ me6000_ao_io_stream_config;
+ subdevice->base.me_subdevice_io_stream_new_values =
+ me6000_ao_io_stream_new_values;
+ subdevice->base.me_subdevice_io_stream_write =
+ me6000_ao_io_stream_write;
+ subdevice->base.me_subdevice_io_stream_start =
+ me6000_ao_io_stream_start;
+ subdevice->base.me_subdevice_io_stream_status =
+ me6000_ao_io_stream_status;
+ subdevice->base.me_subdevice_io_stream_stop = me6000_ao_io_stream_stop;
+ subdevice->base.me_subdevice_query_number_channels =
+ me6000_ao_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me6000_ao_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me6000_ao_query_subdevice_caps;
+ subdevice->base.me_subdevice_query_subdevice_caps_args =
+ me6000_ao_query_subdevice_caps_args;
+ subdevice->base.me_subdevice_query_range_by_min_max =
+ me6000_ao_query_range_by_min_max;
+ subdevice->base.me_subdevice_query_number_ranges =
+ me6000_ao_query_number_ranges;
+ subdevice->base.me_subdevice_query_range_info =
+ me6000_ao_query_range_info;
+ subdevice->base.me_subdevice_query_timer = me6000_ao_query_timer;
+
+ //prepare work queue and work function
+ subdevice->me6000_workqueue = me6000_wq;
+
+/* workqueue API changed in kernel 2.6.20 */
+#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) )
+ INIT_WORK(&subdevice->ao_control_task, me6000_ao_work_control_task,
+ (void *)subdevice);
+#else
+ INIT_DELAYED_WORK(&subdevice->ao_control_task,
+ me6000_ao_work_control_task);
+#endif
+
+ if (subdevice->fifo) { //Set speed
+ outl(ME6000_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg);
+ subdevice->hardware_stop_delay = HZ / 10; //100ms
+ }
+
+ return subdevice;
+}
+
+/** @brief Stop presentation. Preserve FIFOs.
+*
+* @param instance The subdevice instance (pointer).
+*/
+int inline ao_stop_immediately(me6000_ao_subdevice_t * instance)
+{
+ unsigned long cpu_flags;
+ uint32_t ctrl;
+ int timeout;
+ int i;
+ uint32_t single_mask;
+
+ single_mask =
+ (instance->ao_idx - ME6000_AO_SINGLE_STATUS_OFFSET <
+ 0) ? 0x0000 : (0x0001 << (instance->ao_idx -
+ ME6000_AO_SINGLE_STATUS_OFFSET));
+
+ timeout =
+ (instance->hardware_stop_delay >
+ (HZ / 10)) ? instance->hardware_stop_delay : HZ / 10;
+ for (i = 0; i <= timeout; i++) {
+ if (instance->fifo) {
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched!
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME6000_AO_CTRL_BIT_STOP |
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ |
+ ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ if (!(inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM)) { // Exit.
+ break;
+ }
+ } else {
+ if (!(inl(instance->status_reg) & single_mask)) { // Exit.
+ break;
+ }
+ }
+
+ PINFO("<%s> Wait for stop: %d\n", __func__, i);
+
+ //Still working!
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ if (i > timeout) {
+ PERROR_CRITICAL("FSM IS BUSY!\n");
+ return ME_ERRNO_INTERNAL;
+ }
+ return ME_ERRNO_SUCCESS;
+}
+
+/** @brief Copy data from circular buffer to fifo (fast) in wraparound.
+* @note This is time critical function. Checking is done at begining and end only.
+* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly.
+*
+* @param instance The subdevice instance (pointer).
+* @param count Maximum number of copied data.
+* @param start_pos Position of the firs value in buffer.
+*
+* @return On success: Number of copied data.
+* @return On error/success: 0. No datas were copied => no data in buffer.
+* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW.
+*/
+int inline ao_write_data_wraparound(me6000_ao_subdevice_t * instance, int count,
+ int start_pos)
+{ /// @note This is time critical function!
+ uint32_t status;
+ uint32_t value;
+ int pos =
+ (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask;
+ int local_count = count;
+ int i = 1;
+
+ if (count <= 0) { //Wrong count!
+ return 0;
+ }
+
+ while (i < local_count) {
+ //Get value from buffer
+ value = *(instance->circ_buf.buf + pos);
+ //Prepare it
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+
+ pos++;
+ pos &= instance->circ_buf.mask;
+ if (pos == instance->circ_buf.head) {
+ pos = instance->circ_buf.tail;
+ }
+ i++;
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied!
+ PERROR("idx=%d FIFO is full before all datas were copied!\n",
+ instance->ao_idx);
+ return -ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ } else { //Add last value
+ value = *(instance->circ_buf.buf + pos);
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+ }
+
+ PINFO("idx=%d WRAPAROUND LOADED %d values\n", instance->ao_idx,
+ local_count);
+ return local_count;
+}
+
+/** @brief Copy data from software buffer to fifo (fast).
+* @note This is time critical function. Checking is done at begining and end only.
+* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly.
+*
+* @param instance The subdevice instance (pointer).
+* @param count Maximum number of copied data.
+* @param start_pos Position of the firs value in buffer.
+*
+* @return On success: Number of copied data.
+* @return On error/success: 0. No datas were copied => no data in buffer.
+* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW.
+*/
+int inline ao_write_data(me6000_ao_subdevice_t * instance, int count,
+ int start_pos)
+{ /// @note This is time critical function!
+ uint32_t status;
+ uint32_t value;
+ int pos =
+ (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask;
+ int local_count = count;
+ int max_count;
+ int i = 1;
+
+ if (count <= 0) { //Wrong count!
+ return 0;
+ }
+
+ max_count = me_circ_buf_values(&instance->circ_buf) - start_pos;
+ if (max_count <= 0) { //No data to copy!
+ return 0;
+ }
+
+ if (max_count < count) {
+ local_count = max_count;
+ }
+
+ while (i < local_count) {
+ //Get value from buffer
+ value = *(instance->circ_buf.buf + pos);
+ //Prepare it
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+
+ pos++;
+ pos &= instance->circ_buf.mask;
+ i++;
+ }
+
+ status = inl(instance->status_reg);
+ if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied!
+ PERROR("idx=%d FIFO is full before all datas were copied!\n",
+ instance->ao_idx);
+ return -ME_ERRNO_FIFO_BUFFER_OVERFLOW;
+ } else { //Add last value
+ value = *(instance->circ_buf.buf + pos);
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+ }
+
+ PINFO("idx=%d FAST LOADED %d values\n", instance->ao_idx, local_count);
+ return local_count;
+}
+
+/** @brief Copy data from software buffer to fifo (slow).
+* @note This is slow function that copy all data from buffer to FIFO with full control.
+*
+* @param instance The subdevice instance (pointer).
+* @param count Maximum number of copied data.
+* @param start_pos Position of the firs value in buffer.
+*
+* @return On success: Number of copied values.
+* @return On error/success: 0. FIFO was full at begining.
+* @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW.
+*/
+int inline ao_write_data_pooling(me6000_ao_subdevice_t * instance, int count,
+ int start_pos)
+{ /// @note This is slow function!
+ uint32_t status;
+ uint32_t value;
+ int pos =
+ (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask;
+ int local_count = count;
+ int i;
+ int max_count;
+
+ if (count <= 0) { //Wrong count!
+ PERROR("idx=%d SLOW LOADED: Wrong count!\n", instance->ao_idx);
+ return 0;
+ }
+
+ max_count = me_circ_buf_values(&instance->circ_buf) - start_pos;
+ if (max_count <= 0) { //No data to copy!
+ PERROR("idx=%d SLOW LOADED: No data to copy!\n",
+ instance->ao_idx);
+ return 0;
+ }
+
+ if (max_count < count) {
+ local_count = max_count;
+ }
+
+ for (i = 0; i < local_count; i++) {
+ status = inl(instance->status_reg);
+ if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full!
+ return i;
+ }
+ //Get value from buffer
+ value = *(instance->circ_buf.buf + pos);
+ //Prepare it
+ if (instance->ao_idx & 0x1) {
+ value <<= 16;
+ }
+ //Put value to FIFO
+ outl(value, instance->fifo_reg);
+ //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value);
+
+ pos++;
+ pos &= instance->circ_buf.mask;
+ }
+
+ PINFO("idx=%d SLOW LOADED %d values\n", instance->ao_idx, local_count);
+ return local_count;
+}
+
+/** @brief Copy data from user space to circular buffer.
+* @param instance The subdevice instance (pointer).
+* @param count Number of datas in user space.
+* @param user_values Buffer's pointer.
+*
+* @return On success: Number of copied values.
+* @return On error: -ME_ERRNO_INTERNAL.
+*/
+int inline ao_get_data_from_user(me6000_ao_subdevice_t * instance, int count,
+ int *user_values)
+{
+ int i, err;
+ int empty_space;
+ int copied;
+ int value;
+
+ empty_space = me_circ_buf_space(&instance->circ_buf);
+ //We have only this space free.
+ copied = (count < empty_space) ? count : empty_space;
+ for (i = 0; i < copied; i++) { //Copy from user to buffer
+ if ((err = get_user(value, (int *)(user_values + i)))) {
+ PERROR
+ ("idx=%d BUFFER LOADED: get_user(0x%p) return an error: %d\n",
+ instance->ao_idx, user_values + i, err);
+ return -ME_ERRNO_INTERNAL;
+ }
+ /// @note The analog output in me6000 series has size of 16 bits.
+ *(instance->circ_buf.buf + instance->circ_buf.head) =
+ (uint16_t) value;
+ instance->circ_buf.head++;
+ instance->circ_buf.head &= instance->circ_buf.mask;
+ }
+
+ PINFO("idx=%d BUFFER LOADED %d values\n", instance->ao_idx, copied);
+ return copied;
+}
+
+static void me6000_ao_work_control_task(
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ void *subdevice
+#else
+ struct work_struct *work
+#endif
+ )
+{
+ me6000_ao_subdevice_t *instance;
+ unsigned long cpu_flags = 0;
+ uint32_t status;
+ uint32_t ctrl;
+ uint32_t synch;
+ int reschedule = 0;
+ int signaling = 0;
+ uint32_t single_mask;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ instance = (me6000_ao_subdevice_t *) subdevice;
+#else
+ instance =
+ container_of((void *)work, me6000_ao_subdevice_t, ao_control_task);
+#endif
+ PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies,
+ instance->ao_idx);
+
+ status = inl(instance->status_reg);
+ PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->status_reg - instance->reg_base, status);
+
+/// @note AO_STATUS_BIT_FSM doesn't work as should be for pure single channels (idx>=4)
+// single_mask = (instance->ao_idx-ME6000_AO_SINGLE_STATUS_OFFSET < 0) ? 0x0000 : (0x0001 << (instance->ao_idx-ME6000_AO_SINGLE_STATUS_OFFSET));
+ single_mask = *instance->triggering_flags & (0x1 << instance->ao_idx);
+
+ switch (instance->status) { // Checking actual mode.
+
+ // Not configured for work.
+ case ao_status_none:
+ break;
+
+ //This are stable modes. No need to do anything. (?)
+ case ao_status_single_configured:
+ case ao_status_stream_configured:
+ case ao_status_stream_fifo_error:
+ case ao_status_stream_buffer_error:
+ case ao_status_stream_error:
+ PERROR("Shouldn't be running!.\n");
+ break;
+
+ // Single modes
+ case ao_status_single_run_wait:
+ case ao_status_single_run:
+ case ao_status_single_end_wait:
+ if (instance->fifo) { // Extra registers.
+ if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working.
+ if (((instance->fifo & ME6000_AO_HAS_FIFO)
+ && (!(status & ME6000_AO_STATUS_BIT_EF)))
+ || (!(instance->fifo & ME6000_AO_HAS_FIFO))) { // Single is in end state.
+ PDEBUG
+ ("Single call has been complited.\n");
+
+ // Set correct value for single_read();
+ instance->single_value =
+ instance->single_value_in_fifo;
+
+ // Set status as 'ao_status_single_end'
+ instance->status = ao_status_single_end;
+
+ spin_lock(instance->preload_reg_lock);
+ if ((single_mask) && (*instance->preload_flags & (ME6000_AO_SYNC_HOLD << instance->ao_idx))) { // This is one of synchronous start channels. Set all as triggered.
+ *instance->triggering_flags =
+ 0x00000000;
+ } else {
+ //Set this channel as triggered (none active).
+ *instance->triggering_flags &=
+ ~(0x1 << instance->ao_idx);
+ }
+ spin_unlock(instance->preload_reg_lock);
+
+ // Signal the end.
+ signaling = 1;
+ // Wait for stop ISM.
+ reschedule = 1;
+
+ break;
+ }
+ }
+ // Check timeout.
+ if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout
+ PDEBUG("Timeout reached.\n");
+ // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched!
+ spin_lock_irqsave(&instance->subdevice_lock,
+ cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME6000_AO_CTRL_BIT_STOP |
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ |
+ ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_EX_TRIG_EDGE |
+ ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH);
+ //Disabling FIFO
+ ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_FIFO;
+
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg -
+ instance->reg_base, ctrl);
+ spin_unlock_irqrestore(&instance->
+ subdevice_lock,
+ cpu_flags);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ spin_lock(instance->preload_reg_lock);
+ //Remove from synchronous start. Block triggering from this output.
+ synch = inl(instance->preload_reg);
+ synch &=
+ ~((ME6000_AO_SYNC_HOLD |
+ ME6000_AO_SYNC_EXT_TRIG) << instance->
+ ao_idx);
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO - set to single safe mode
+ synch |=
+ ME6000_AO_SYNC_HOLD << instance->
+ ao_idx;
+ }
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ synch);
+ //Set this channel as triggered (none active).
+ *instance->triggering_flags &=
+ ~(0x1 << instance->ao_idx);
+ spin_unlock(instance->preload_reg_lock);
+
+ // Set correct value for single_read();
+ instance->single_value_in_fifo =
+ instance->single_value;
+
+ instance->status = ao_status_single_end;
+
+ // Signal the end.
+ signaling = 1;
+ }
+ } else { // No extra registers.
+/*
+ if (!(status & single_mask))
+ {// State machine is not working.
+ PDEBUG("Single call has been complited.\n");
+
+ // Set correct value for single_read();
+ instance->single_value = instance->single_value_in_fifo;
+
+ // Set status as 'ao_status_single_end'
+ instance->status = ao_status_single_end;
+
+ // Signal the end.
+ signaling = 1;
+ // Wait for stop ISM.
+ reschedule = 1;
+
+ break;
+ }
+*/
+ if (!single_mask) { // Was triggered.
+ PDEBUG("Single call has been complited.\n");
+
+ // Set correct value for single_read();
+ instance->single_value =
+ instance->single_value_in_fifo;
+
+ // Set status as 'ao_status_single_end'
+ instance->status = ao_status_single_end;
+
+ // Signal the end.
+ signaling = 1;
+
+ break;
+ }
+ // Check timeout.
+ if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout
+ PDEBUG("Timeout reached.\n");
+
+ spin_lock(instance->preload_reg_lock);
+ //Remove from synchronous start. Block triggering from this output.
+ synch = inl(instance->preload_reg);
+ synch &=
+ ~(ME6000_AO_SYNC_EXT_TRIG << instance->
+ ao_idx);
+ synch |=
+ ME6000_AO_SYNC_HOLD << instance->ao_idx;
+
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG
+ ("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ synch);
+ //Set this channel as triggered (none active).
+ *instance->triggering_flags &=
+ ~(0x1 << instance->ao_idx);
+ spin_unlock(instance->preload_reg_lock);
+
+ // Restore old settings.
+ PDEBUG("Write old value back to register.\n");
+ outl(instance->single_value,
+ instance->single_reg);
+ PDEBUG_REG
+ ("single_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->single_reg - instance->reg_base,
+ instance->single_value);
+
+ // Set correct value for single_read();
+ instance->single_value_in_fifo =
+ instance->single_value;
+
+ instance->status = ao_status_single_end;
+
+ // Signal the end.
+ signaling = 1;
+ }
+ }
+
+ // Wait for stop.
+ reschedule = 1;
+ break;
+
+ case ao_status_stream_end:
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+ case ao_status_single_end:
+ if (instance->fifo) { // Extra registers.
+ if (status & ME6000_AO_STATUS_BIT_FSM) { // State machine is working but the status is set to end. Force stop.
+
+ // Wait for stop.
+ reschedule = 1;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched!
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP |
+ ME6000_AO_CTRL_BIT_STOP;
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ |
+ ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+ } else { // No extra registers.
+/*
+ if (status & single_mask)
+ {// State machine is working but the status is set to end. Force stop.
+
+ // Wait for stop.
+ reschedule = 1;
+ }
+*/
+ }
+ break;
+
+ // Stream modes
+ case ao_status_stream_run_wait:
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+
+ if (status & ME6000_AO_STATUS_BIT_FSM) { // State machine is working. Waiting for start finish.
+ instance->status = ao_status_stream_run;
+
+ // Signal end of this step
+ signaling = 1;
+ } else { // State machine is not working.
+ if (!(status & ME6000_AO_STATUS_BIT_EF)) { // FIFO is empty. Procedure has started and finish already!
+ instance->status = ao_status_stream_end;
+
+ // Signal the end.
+ signaling = 1;
+ // Wait for stop.
+ reschedule = 1;
+ break;
+ }
+ }
+
+ // Check timeout.
+ if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout
+ PDEBUG("Timeout reached.\n");
+ // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched!
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ ctrl = inl(instance->ctrl_reg);
+ ctrl |=
+ ME6000_AO_CTRL_BIT_STOP |
+ ME6000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ ctrl &=
+ ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ |
+ ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG);
+ outl(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base,
+ ctrl);
+ spin_unlock_irqrestore(&instance->subdevice_lock,
+ cpu_flags);
+
+ //Reset interrupt latch
+ inl(instance->irq_reset_reg);
+
+ spin_lock(instance->preload_reg_lock);
+ //Remove from synchronous start. Block triggering from this output.
+ synch = inl(instance->preload_reg);
+ synch &=
+ ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) <<
+ instance->ao_idx);
+ outl(synch, instance->preload_reg);
+ PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->preload_reg - instance->reg_base,
+ synch);
+ spin_unlock(instance->preload_reg_lock);
+
+ instance->status = ao_status_stream_end;
+
+ // Signal the end.
+ signaling = 1;
+ }
+ // Wait for stop.
+ reschedule = 1;
+ break;
+
+ case ao_status_stream_run:
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+
+ if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. This is an error.
+ // BROKEN PIPE!
+ if (!(status & ME6000_AO_STATUS_BIT_EF)) { // FIFO is empty.
+ if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty.
+ if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. Requed data shown.
+ PDEBUG
+ ("ISM stoped. No data in FIFO. Buffer is not empty.\n");
+ instance->status =
+ ao_status_stream_end;
+ } else {
+ PERROR
+ ("Output stream has been broken. ISM stoped. No data in FIFO. Buffer is not empty.\n");
+ instance->status =
+ ao_status_stream_buffer_error;
+ }
+ } else { // Software buffer is empty.
+ PDEBUG
+ ("ISM stoped. No data in FIFO. Buffer is empty.\n");
+ instance->status = ao_status_stream_end;
+ }
+ } else { // There are still datas in FIFO.
+ if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty.
+ PERROR
+ ("Output stream has been broken. ISM stoped but some data in FIFO and buffer.\n");
+ } else { // Software buffer is empty.
+ PERROR
+ ("Output stream has been broken. ISM stoped but some data in FIFO. Buffer is empty.\n");
+ }
+ instance->status = ao_status_stream_fifo_error;
+
+ }
+
+ // Signal the failure.
+ signaling = 1;
+ break;
+ }
+ // Wait for stop.
+ reschedule = 1;
+ break;
+
+ case ao_status_stream_end_wait:
+ if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO
+ PERROR_CRITICAL
+ ("Streaming on single device! This feature is not implemented in this version!\n");
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+ }
+
+ if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. Waiting for stop finish.
+ instance->status = ao_status_stream_end;
+ signaling = 1;
+ }
+ // State machine is working.
+ reschedule = 1;
+ break;
+
+ default:
+ PERROR_CRITICAL("Status is in wrong state (%d)!\n",
+ instance->status);
+ instance->status = ao_status_stream_error;
+ // Signal the end.
+ signaling = 1;
+ break;
+
+ }
+
+ if (signaling) { //Signal it.
+ wake_up_interruptible_all(&instance->wait_queue);
+ }
+
+ if (instance->ao_control_task_flag && reschedule) { // Reschedule task
+ queue_delayed_work(instance->me6000_workqueue,
+ &instance->ao_control_task, 1);
+ } else {
+ PINFO("<%s> Ending control task.\n", __func__);
+ }
+
+}
+
+static int me6000_ao_query_range_by_min_max(me_subdevice_t * subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range)
+{
+ me6000_ao_subdevice_t *instance;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if ((*max - *min) < 0) {
+ PERROR("Invalid minimum and maximum values specified.\n");
+ return ME_ERRNO_INVALID_MIN_MAX;
+ }
+
+ if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) {
+ if ((*max <= (instance->max + 1000)) && (*min >= instance->min)) {
+ *min = instance->min;
+ *max = instance->max;
+ *maxdata = ME6000_AO_MAX_DATA;
+ *range = 0;
+ } else {
+ PERROR("No matching range available.\n");
+ return ME_ERRNO_NO_RANGE;
+ }
+ } else {
+ PERROR("Invalid physical unit specified.\n");
+ return ME_ERRNO_INVALID_UNIT;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_ao_query_number_ranges(me_subdevice_t * subdevice,
+ int unit, int *count)
+{
+ me6000_ao_subdevice_t *instance;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) {
+ *count = 1;
+ } else {
+ *count = 0;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_ao_query_range_info(me_subdevice_t * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata)
+{
+ me6000_ao_subdevice_t *instance;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (range == 0) {
+ *unit = ME_UNIT_VOLT;
+ *min = instance->min;
+ *max = instance->max;
+ *maxdata = ME6000_AO_MAX_DATA;
+ } else {
+ PERROR("Invalid range number specified.\n");
+ return ME_ERRNO_INVALID_RANGE;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_ao_query_timer(me_subdevice_t * subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks, long long *max_ticks)
+{
+ me6000_ao_subdevice_t *instance;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (instance->fifo) { //Streaming device.
+ *base_frequency = ME6000_AO_BASE_FREQUENCY;
+ if (timer == ME_TIMER_ACQ_START) {
+ *min_ticks = ME6000_AO_MIN_ACQ_TICKS;
+ *max_ticks = ME6000_AO_MAX_ACQ_TICKS;
+ } else if (timer == ME_TIMER_CONV_START) {
+ *min_ticks = ME6000_AO_MIN_CHAN_TICKS;
+ *max_ticks = ME6000_AO_MAX_CHAN_TICKS;
+ }
+ } else { //Not streaming device!
+ *base_frequency = 0;
+ *min_ticks = 0;
+ *max_ticks = 0;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_ao_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ me6000_ao_subdevice_t *instance;
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *number = 1;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_ao_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ me6000_ao_subdevice_t *instance;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *type = ME_TYPE_AO;
+ *subtype =
+ (instance->
+ fifo & ME6000_AO_HAS_FIFO) ? ME_SUBTYPE_STREAMING :
+ ME_SUBTYPE_SINGLE;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_ao_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ me6000_ao_subdevice_t *instance;
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ *caps =
+ ME_CAPS_AO_TRIG_SYNCHRONOUS | ((instance->fifo) ? ME_CAPS_AO_FIFO :
+ ME_CAPS_NONE);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice,
+ int cap, int *args, int count)
+{
+ me6000_ao_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ instance = (me6000_ao_subdevice_t *) subdevice;
+
+ PDEBUG("executed. idx=%d\n", instance->ao_idx);
+
+ if (count != 1) {
+ PERROR("Invalid capability argument count.\n");
+ return ME_ERRNO_INVALID_CAP_ARG_COUNT;
+ }
+
+ switch (cap) {
+ case ME_CAP_AI_FIFO_SIZE:
+ args[0] = (instance->fifo) ? ME6000_AO_FIFO_COUNT : 0;
+ break;
+
+ case ME_CAP_AI_BUFFER_SIZE:
+ args[0] =
+ (instance->circ_buf.buf) ? ME6000_AO_CIRC_BUF_COUNT : 0;
+ break;
+
+ default:
+ PERROR("Invalid capability.\n");
+ err = ME_ERRNO_INVALID_CAP;
+ args[0] = 0;
+ }
+
+ return err;
+}
diff --git a/drivers/staging/meilhaus/me6000_ao.h b/drivers/staging/meilhaus/me6000_ao.h
new file mode 100644
index 000000000000..9629649cd410
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_ao.h
@@ -0,0 +1,200 @@
+/**
+ * @file me6000_ao.h
+ *
+ * @brief Meilhaus ME-6000 analog output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME6000_AO_H_
+#define _ME6000_AO_H_
+
+#include <linux/version.h>
+#include "mesubdevice.h"
+#include "mecirc_buf.h"
+#include "meioctl.h"
+
+#ifdef __KERNEL__
+
+#define ME6000_AO_MAX_SUBDEVICES 16
+#define ME6000_AO_FIFO_COUNT 8192
+
+#define ME6000_AO_BASE_FREQUENCY 33000000L
+
+#define ME6000_AO_MIN_ACQ_TICKS 0LL
+#define ME6000_AO_MAX_ACQ_TICKS 0LL
+
+#define ME6000_AO_MIN_CHAN_TICKS 66LL
+#define ME6000_AO_MAX_CHAN_TICKS 0xFFFFFFFFLL
+
+#define ME6000_AO_MIN_RANGE -10000000
+#define ME6000_AO_MAX_RANGE 9999694
+
+#define ME6000_AO_MIN_RANGE_HIGH 0
+#define ME6000_AO_MAX_RANGE_HIGH 49999237
+
+#define ME6000_AO_MAX_DATA 0xFFFF
+
+#ifdef ME_SYNAPSE
+# define ME6000_AO_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse
+#else
+# define ME6000_AO_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB
+#endif
+#define ME6000_AO_CIRC_BUF_SIZE PAGE_SIZE<<ME6000_AO_CIRC_BUF_SIZE_ORDER // Buffer size in bytes.
+
+# ifdef _CBUFF_32b_t
+# define ME6000_AO_CIRC_BUF_COUNT ((ME6000_AO_CIRC_BUF_SIZE) / sizeof(uint32_t)) // Size in values
+# else
+# define ME6000_AO_CIRC_BUF_COUNT ((ME6000_AO_CIRC_BUF_SIZE) / sizeof(uint16_t)) // Size in values
+# endif
+
+# define ME6000_AO_CONTINOUS 0x0
+# define ME6000_AO_WRAP_MODE 0x1
+# define ME6000_AO_HW_MODE 0x2
+
+# define ME6000_AO_HW_WRAP_MODE (ME6000_AO_WRAP_MODE | ME6000_AO_HW_MODE)
+# define ME6000_AO_SW_WRAP_MODE ME6000_AO_WRAP_MODE
+
+# define ME6000_AO_INF_STOP_MODE 0x0
+# define ME6000_AO_ACQ_STOP_MODE 0x1
+# define ME6000_AO_SCAN_STOP_MODE 0x2
+
+# define ME6000_AO_EXTRA_HARDWARE 0x1
+# define ME6000_AO_HAS_FIFO 0x2
+
+typedef enum ME6000_AO_STATUS {
+ ao_status_none = 0,
+ ao_status_single_configured,
+ ao_status_single_run_wait,
+ ao_status_single_run,
+ ao_status_single_end_wait,
+ ao_status_single_end,
+ ao_status_stream_configured,
+ ao_status_stream_run_wait,
+ ao_status_stream_run,
+ ao_status_stream_end_wait,
+ ao_status_stream_end,
+ ao_status_stream_fifo_error,
+ ao_status_stream_buffer_error,
+ ao_status_stream_error,
+ ao_status_last
+} ME6000_AO_STATUS;
+
+typedef struct me6000_ao_timeout {
+ unsigned long start_time;
+ unsigned long delay;
+} me6000_ao_timeout_t;
+
+/**
+ * @brief The ME-6000 analog output subdevice class.
+ */
+typedef struct me6000_ao_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+ unsigned int ao_idx;
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *preload_reg_lock; /**< Spin lock to protect preload_reg from concurrent access. */
+
+ uint32_t *preload_flags;
+ uint32_t *triggering_flags;
+
+ /* Hardware feautres */
+ unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */
+ int fifo; /**< If set this device has a FIFO. */
+
+ //Range
+ int min;
+ int max;
+
+ int single_value; /**< Mirror of the output value in single mode. */
+ int single_value_in_fifo; /**< Mirror of the value written in single mode. */
+ uint32_t ctrl_trg; /**< Mirror of the trigger settings. */
+
+ volatile int mode; /**< Flags used for storing SW wraparound setup*/
+ int stop_mode; /**< The user defined stop condition flag. */
+ unsigned int start_mode;
+ unsigned int stop_count; /**< The user defined dates presentation end count. */
+ unsigned int stop_data_count; /**< The stop presentation count. */
+ unsigned int data_count; /**< The real presentation count. */
+ unsigned int preloaded_count; /**< The next data addres in buffer. <= for wraparound mode. */
+ int hardware_stop_delay; /**< The time that stop can take. This is only to not show hardware bug to user. */
+
+ volatile enum ME6000_AO_STATUS status; /**< The current stream status flag. */
+ me6000_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */
+
+ /* Registers *//**< All registers are 32 bits long. */
+ unsigned long ctrl_reg;
+ unsigned long status_reg;
+ unsigned long fifo_reg;
+ unsigned long single_reg;
+ unsigned long timer_reg;
+ unsigned long irq_status_reg;
+ unsigned long preload_reg;
+ unsigned long irq_reset_reg;
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+
+ /* Software buffer */
+ me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. */
+ wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */
+
+ struct workqueue_struct *me6000_workqueue;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ struct work_struct ao_control_task;
+#else
+ struct delayed_work ao_control_task;
+#endif
+
+ volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */
+
+} me6000_ao_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-6000 analog output subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access.
+ * @param preload_flags Pointer to spin lock protecting the hold&trigger register from concurrent access.
+ * @param ao_idx Subdevice number.
+ * @param fifo Flag set if subdevice has hardware FIFO.
+ * @param irq IRQ number.
+ * @param high_range Flag set if subdevice has high curren output.
+ * @param me6000_wq Queue for asynchronous task (1 queue for all subdevice on 1 board).
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base,
+ spinlock_t * preload_reg_lock,
+ uint32_t * preload_flags,
+ uint32_t * triggering_flags,
+ int ao_idx,
+ int fifo,
+ int irq,
+ int high_range,
+ struct workqueue_struct
+ *me6000_wq);
+
+#endif //__KERNEL__
+#endif //_ME6000_AO_H_
diff --git a/drivers/staging/meilhaus/me6000_ao_reg.h b/drivers/staging/meilhaus/me6000_ao_reg.h
new file mode 100644
index 000000000000..eb8f46e1b75b
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_ao_reg.h
@@ -0,0 +1,177 @@
+/**
+ * @file me6000_ao_reg.h
+ *
+ * @brief ME-6000 analog output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME6000_AO_REG_H_
+#define _ME6000_AO_REG_H_
+
+#ifdef __KERNEL__
+
+// AO
+#define ME6000_AO_00_CTRL_REG 0x00 // R/W
+#define ME6000_AO_00_STATUS_REG 0x04 // R/_
+#define ME6000_AO_00_FIFO_REG 0x08 // _/W
+#define ME6000_AO_00_SINGLE_REG 0x0C // R/W
+#define ME6000_AO_00_TIMER_REG 0x10 // _/W
+
+#define ME6000_AO_01_CTRL_REG 0x18 // R/W
+#define ME6000_AO_01_STATUS_REG 0x1C // R/_
+#define ME6000_AO_01_FIFO_REG 0x20 // _/W
+#define ME6000_AO_01_SINGLE_REG 0x24 // R/W
+#define ME6000_AO_01_TIMER_REG 0x28 // _/W
+
+#define ME6000_AO_02_CTRL_REG 0x30 // R/W
+#define ME6000_AO_02_STATUS_REG 0x34 // R/_
+#define ME6000_AO_02_FIFO_REG 0x38 // _/W
+#define ME6000_AO_02_SINGLE_REG 0x3C // R/W
+#define ME6000_AO_02_TIMER_REG 0x40 // _/W
+
+#define ME6000_AO_03_CTRL_REG 0x48 // R/W
+#define ME6000_AO_03_STATUS_REG 0x4C // R/_
+#define ME6000_AO_03_FIFO_REG 0x50 // _/W
+#define ME6000_AO_03_SINGLE_REG 0x54 // R/W
+#define ME6000_AO_03_TIMER_REG 0x58 // _/W
+
+#define ME6000_AO_SINGLE_STATUS_REG 0xA4 // R/_
+#define ME6000_AO_SINGLE_STATUS_OFFSET 4 //The first single subdevice => bit 0 in ME6000_AO_SINGLE_STATUS_REG.
+
+#define ME6000_AO_04_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_04_SINGLE_REG 0x74 // _/W
+
+#define ME6000_AO_05_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_05_SINGLE_REG 0x78 // _/W
+
+#define ME6000_AO_06_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_06_SINGLE_REG 0x7C // _/W
+
+#define ME6000_AO_07_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_07_SINGLE_REG 0x80 // _/W
+
+#define ME6000_AO_08_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_08_SINGLE_REG 0x84 // _/W
+
+#define ME6000_AO_09_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_09_SINGLE_REG 0x88 // _/W
+
+#define ME6000_AO_10_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_10_SINGLE_REG 0x8C // _/W
+
+#define ME6000_AO_11_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_11_SINGLE_REG 0x90 // _/W
+
+#define ME6000_AO_12_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_12_SINGLE_REG 0x94 // _/W
+
+#define ME6000_AO_13_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_13_SINGLE_REG 0x98 // _/W
+
+#define ME6000_AO_14_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_14_SINGLE_REG 0x9C // _/W
+
+#define ME6000_AO_15_STATUS_REG ME6000_AO_SINGLE_STATUS_REG
+#define ME6000_AO_15_SINGLE_REG 0xA0 // _/W
+
+//ME6000_AO_CTRL_REG
+#define ME6000_AO_MODE_SINGLE 0x00
+#define ME6000_AO_MODE_WRAPAROUND 0x01
+#define ME6000_AO_MODE_CONTINUOUS 0x02
+#define ME6000_AO_CTRL_MODE_MASK (ME6000_AO_MODE_WRAPAROUND | ME6000_AO_MODE_CONTINUOUS)
+
+#define ME6000_AO_CTRL_BIT_MODE_WRAPAROUND 0x001
+#define ME6000_AO_CTRL_BIT_MODE_CONTINUOUS 0x002
+#define ME6000_AO_CTRL_BIT_STOP 0x004
+#define ME6000_AO_CTRL_BIT_ENABLE_FIFO 0x008
+#define ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG 0x010
+#define ME6000_AO_CTRL_BIT_EX_TRIG_EDGE 0x020
+#define ME6000_AO_CTRL_BIT_ENABLE_IRQ 0x040
+#define ME6000_AO_CTRL_BIT_IMMEDIATE_STOP 0x080
+#define ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH 0x800
+
+//ME6000_AO_STATUS_REG
+#define ME6000_AO_STATUS_BIT_FSM 0x01
+#define ME6000_AO_STATUS_BIT_FF 0x02
+#define ME6000_AO_STATUS_BIT_HF 0x04
+#define ME6000_AO_STATUS_BIT_EF 0x08
+
+#define ME6000_AO_PRELOAD_REG 0xA8 // R/W ///ME6000_AO_SYNC_REG <==> ME6000_AO_PRELOAD_REG
+/*
+#define ME6000_AO_SYNC_HOLD_0 0x00000001
+#define ME6000_AO_SYNC_HOLD_1 0x00000002
+#define ME6000_AO_SYNC_HOLD_2 0x00000004
+#define ME6000_AO_SYNC_HOLD_3 0x00000008
+#define ME6000_AO_SYNC_HOLD_4 0x00000010
+#define ME6000_AO_SYNC_HOLD_5 0x00000020
+#define ME6000_AO_SYNC_HOLD_6 0x00000040
+#define ME6000_AO_SYNC_HOLD_7 0x00000080
+#define ME6000_AO_SYNC_HOLD_8 0x00000100
+#define ME6000_AO_SYNC_HOLD_9 0x00000200
+#define ME6000_AO_SYNC_HOLD_10 0x00000400
+#define ME6000_AO_SYNC_HOLD_11 0x00000800
+#define ME6000_AO_SYNC_HOLD_12 0x00001000
+#define ME6000_AO_SYNC_HOLD_13 0x00002000
+#define ME6000_AO_SYNC_HOLD_14 0x00004000
+#define ME6000_AO_SYNC_HOLD_15 0x00008000
+*/
+#define ME6000_AO_SYNC_HOLD 0x00000001
+/*
+#define ME6000_AO_SYNC_EXT_TRIG_0 0x00010000
+#define ME6000_AO_SYNC_EXT_TRIG_1 0x00020000
+#define ME6000_AO_SYNC_EXT_TRIG_2 0x00040000
+#define ME6000_AO_SYNC_EXT_TRIG_3 0x00080000
+#define ME6000_AO_SYNC_EXT_TRIG_4 0x00100000
+#define ME6000_AO_SYNC_EXT_TRIG_5 0x00200000
+#define ME6000_AO_SYNC_EXT_TRIG_6 0x00400000
+#define ME6000_AO_SYNC_EXT_TRIG_7 0x00800000
+#define ME6000_AO_SYNC_EXT_TRIG_8 0x01000000
+#define ME6000_AO_SYNC_EXT_TRIG_9 0x02000000
+#define ME6000_AO_SYNC_EXT_TRIG_10 0x04000000
+#define ME6000_AO_SYNC_EXT_TRIG_11 0x08000000
+#define ME6000_AO_SYNC_EXT_TRIG_12 0x10000000
+#define ME6000_AO_SYNC_EXT_TRIG_13 0x20000000
+#define ME6000_AO_SYNC_EXT_TRIG_14 0x40000000
+#define ME6000_AO_SYNC_EXT_TRIG_15 0x80000000
+*/
+#define ME6000_AO_SYNC_EXT_TRIG 0x00010000
+
+#define ME6000_AO_EXT_TRIG 0x80000000
+
+// AO-IRQ
+#define ME6000_AO_IRQ_STATUS_REG 0x60 // R/_
+#define ME6000_AO_00_IRQ_RESET_REG 0x64 // R/_
+#define ME6000_AO_01_IRQ_RESET_REG 0x68 // R/_
+#define ME6000_AO_02_IRQ_RESET_REG 0x6C // R/_
+#define ME6000_AO_03_IRQ_RESET_REG 0x70 // R/_
+
+#define ME6000_IRQ_STATUS_BIT_0 0x01
+#define ME6000_IRQ_STATUS_BIT_1 0x02
+#define ME6000_IRQ_STATUS_BIT_2 0x04
+#define ME6000_IRQ_STATUS_BIT_3 0x08
+
+#define ME6000_IRQ_STATUS_BIT_AO_HF ME6000_IRQ_STATUS_BIT_0
+
+//DUMY register
+#define ME6000_AO_DUMY 0xFC
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me6000_device.c b/drivers/staging/meilhaus/me6000_device.c
new file mode 100644
index 000000000000..fee4c58b8464
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_device.c
@@ -0,0 +1,211 @@
+/**
+ * @file me6000_device.c
+ *
+ * @brief Device class template implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "mefirmware.h"
+
+#include "mesubdevice.h"
+#include "medebug.h"
+#include "medevice.h"
+#include "me6000_reg.h"
+#include "me6000_device.h"
+#include "meplx_reg.h"
+#include "me6000_dio.h"
+#include "me6000_ao.h"
+
+/**
+ * @brief Global variable.
+ * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts).
+ */
+static struct workqueue_struct *me6000_workqueue;
+
+me_device_t *me6000_pci_constructor(struct pci_dev *pci_device)
+{
+ me6000_device_t *me6000_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ int err;
+ int i;
+ int high_range = 0;
+ int fifo;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me6000_device = kmalloc(sizeof(me6000_device_t), GFP_KERNEL);
+
+ if (!me6000_device) {
+ PERROR("Cannot get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(me6000_device, 0, sizeof(me6000_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me6000_device, pci_device);
+
+ if (err) {
+ kfree(me6000_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+
+ /* Download the xilinx firmware */
+ err = me_xilinx_download(me6000_device->base.info.pci.reg_bases[1],
+ me6000_device->base.info.pci.reg_bases[2],
+ &pci_device->dev, "me6000.bin");
+
+ if (err) {
+ me_device_deinit((me_device_t *) me6000_device);
+ kfree(me6000_device);
+ PERROR("Can't download firmware.\n");
+ return NULL;
+ }
+
+ /* Get the index in the device version information table. */
+ version_idx =
+ me6000_versions_get_device_index(me6000_device->base.info.pci.
+ device_id);
+
+ // Initialize spin lock .
+ spin_lock_init(&me6000_device->preload_reg_lock);
+ spin_lock_init(&me6000_device->dio_ctrl_reg_lock);
+
+ /* Create digital input/output instances. */
+ for (i = 0; i < me6000_versions[version_idx].dio_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me6000_dio_constructor(me6000_device->
+ base.info.pci.
+ reg_bases[3], i,
+ &me6000_device->
+ dio_ctrl_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me6000_device);
+ kfree(me6000_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me6000_device->base.slist,
+ subdevice);
+ }
+
+ /* Create analog output instances. */
+ for (i = 0; i < me6000_versions[version_idx].ao_subdevices; i++) {
+ high_range = ((i == 8)
+ &&
+ ((me6000_device->base.info.pci.device_id ==
+ PCI_DEVICE_ID_MEILHAUS_ME6359)
+ || (me6000_device->base.info.pci.device_id ==
+ PCI_DEVICE_ID_MEILHAUS_ME6259)
+ )
+ )? 1 : 0;
+
+ fifo =
+ (i <
+ me6000_versions[version_idx].
+ ao_fifo) ? ME6000_AO_HAS_FIFO : 0x0;
+ fifo |= (i < 4) ? ME6000_AO_EXTRA_HARDWARE : 0x0;
+
+ subdevice =
+ (me_subdevice_t *) me6000_ao_constructor(me6000_device->
+ base.info.pci.
+ reg_bases[2],
+ &me6000_device->
+ preload_reg_lock,
+ &me6000_device->
+ preload_flags,
+ &me6000_device->
+ triggering_flags,
+ i, fifo,
+ me6000_device->
+ base.irq,
+ high_range,
+ me6000_workqueue);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me6000_device);
+ kfree(me6000_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me6000_device->base.slist,
+ subdevice);
+ }
+
+ return (me_device_t *) me6000_device;
+}
+
+// Init and exit of module.
+
+static int __init me6000_init(void)
+{
+ PDEBUG("executed.\n");
+
+ me6000_workqueue = create_singlethread_workqueue("me6000");
+ return 0;
+}
+
+static void __exit me6000_exit(void)
+{
+ PDEBUG("executed.\n");
+
+ flush_workqueue(me6000_workqueue);
+ destroy_workqueue(me6000_workqueue);
+}
+
+module_init(me6000_init);
+module_exit(me6000_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for ME-6000 Device");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-6000 Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me6000_pci_constructor);
diff --git a/drivers/staging/meilhaus/me6000_device.h b/drivers/staging/meilhaus/me6000_device.h
new file mode 100644
index 000000000000..18cc7d1e14f1
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_device.h
@@ -0,0 +1,149 @@
+/**
+ * @file me6000_device.h
+ *
+ * @brief ME-6000 device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME6000_DEVICE_H
+#define _ME6000_DEVICE_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure holding ME-6000 device capabilities.
+ */
+typedef struct me6000_version {
+ uint16_t device_id;
+ unsigned int dio_subdevices;
+ unsigned int ao_subdevices;
+ unsigned int ao_fifo; //How many devices have FIFO
+} me6000_version_t;
+
+/**
+ * @brief ME-6000 device capabilities.
+ */
+static me6000_version_t me6000_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME6004, 0, 4, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME6008, 0, 8, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME600F, 0, 16, 0},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6014, 0, 4, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME6018, 0, 8, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME601F, 0, 16, 0},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6034, 0, 4, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME6038, 0, 8, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME603F, 0, 16, 0},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6104, 0, 4, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME6108, 0, 8, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME610F, 0, 16, 4},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6114, 0, 4, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME6118, 0, 8, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME611F, 0, 16, 4},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6134, 0, 4, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME6138, 0, 8, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME613F, 0, 16, 4},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6044, 2, 4, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME6048, 2, 8, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME604F, 2, 16, 0},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6054, 2, 4, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME6058, 2, 8, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME605F, 2, 16, 0},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6074, 2, 4, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME6078, 2, 8, 0},
+ {PCI_DEVICE_ID_MEILHAUS_ME607F, 2, 16, 0},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6144, 2, 4, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME6148, 2, 8, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME614F, 2, 16, 4},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6154, 2, 4, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME6158, 2, 8, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME615F, 2, 16, 4},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6174, 2, 4, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME6178, 2, 8, 4},
+ {PCI_DEVICE_ID_MEILHAUS_ME617F, 2, 16, 4},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6259, 2, 9, 0},
+
+ {PCI_DEVICE_ID_MEILHAUS_ME6359, 2, 9, 4},
+
+ {0},
+};
+
+#define ME6000_DEVICE_VERSIONS (sizeof(me6000_versions) / sizeof(me6000_version_t) - 1) /**< Returns the number of entries in #me6000_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #me6000_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me6000_versions.
+ */
+static inline unsigned int me6000_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME6000_DEVICE_VERSIONS; i++)
+ if (me6000_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The ME-6000 device class structure.
+ */
+typedef struct me6000_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+
+ /* Child class attributes. */
+ spinlock_t preload_reg_lock; /**< Guards the preload register. */
+ uint32_t preload_flags;
+ uint32_t triggering_flags;
+
+ spinlock_t dio_ctrl_reg_lock;
+} me6000_device_t;
+
+/**
+ * @brief The ME-6000 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-6000 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me6000_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me6000_dio.c b/drivers/staging/meilhaus/me6000_dio.c
new file mode 100644
index 000000000000..07f1069f9ac6
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_dio.c
@@ -0,0 +1,415 @@
+/**
+ * @file me6000_dio.c
+ *
+ * @brief ME-6000 digital input/output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me6000_dio_reg.h"
+#include "me6000_dio.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me6000_dio_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me6000_dio_subdevice_t *instance;
+ uint8_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me6000_dio_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inb(instance->ctrl_reg);
+ mode &= ~(0x3 << (instance->dio_idx * 2));
+ outb(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outb(0x00, instance->port_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, 0x00);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_dio_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me6000_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+ int size =
+ flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
+ | ME_IO_SINGLE_CONFIG_DIO_WORD |
+ ME_IO_SINGLE_CONFIG_DIO_DWORD);
+
+ PDEBUG("executed.\n");
+
+ instance = (me6000_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inb(instance->ctrl_reg);
+ switch (size) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ mode &=
+ ~((ME6000_DIO_CTRL_BIT_MODE_0 |
+ ME6000_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ mode &=
+ ~((ME6000_DIO_CTRL_BIT_MODE_0 |
+ ME6000_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ mode |=
+ ME6000_DIO_CTRL_BIT_MODE_0 << (instance->
+ dio_idx * 2);
+ } else {
+ PERROR
+ ("Invalid port configuration specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!err) {
+ outb(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_dio_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me6000_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me6000_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
+ ME6000_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ if ((mode ==
+ (ME6000_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value =
+ inb(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
+ ME6000_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ if ((mode ==
+ (ME6000_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value = inb(instance->port_reg) & 0x00FF;
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_dio_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me6000_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+ uint8_t byte;
+
+ PDEBUG("executed.\n");
+
+ instance = (me6000_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
+ ME6000_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME6000_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) {
+ byte = inb(instance->port_reg) & 0x00FF;
+
+ if (value)
+ byte |= 0x1 << channel;
+ else
+ byte &= ~(0x1 << channel);
+
+ outb(byte, instance->port_reg);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
+ ME6000_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME6000_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) {
+ outb(value, instance->port_reg);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me6000_dio_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_dio_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DIO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me6000_dio_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_DIR_BYTE;
+ return ME_ERRNO_SUCCESS;
+}
+
+me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock)
+{
+ me6000_dio_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me6000_dio_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me6000_dio_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Set the subdevice ports */
+ subdevice->ctrl_reg = reg_base + ME6000_DIO_CTRL_REG;
+ switch (dio_idx) {
+ case 0:
+ subdevice->port_reg = reg_base + ME6000_DIO_PORT_0_REG;
+ break;
+ case 1:
+ subdevice->port_reg = reg_base + ME6000_DIO_PORT_1_REG;
+ break;
+ default:
+ err = ME_ERRNO_INVALID_SUBDEVICE;
+ }
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save digital i/o index */
+ subdevice->dio_idx = dio_idx;
+
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me6000_dio_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me6000_dio_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me6000_dio_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me6000_dio_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me6000_dio_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me6000_dio_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me6000_dio_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me6000_dio.h b/drivers/staging/meilhaus/me6000_dio.h
new file mode 100644
index 000000000000..858bec1c4596
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_dio.h
@@ -0,0 +1,68 @@
+/**
+ * @file me6000_dio.h
+ *
+ * @brief ME-6000 digital input/output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME6000_DIO_H_
+#define _ME6000_DIO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me6000_dio_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+ unsigned int dio_idx; /**< The index of the digital i/o on the device. */
+
+ unsigned long port_reg; /**< Register holding the port status. */
+ unsigned long ctrl_reg; /**< Register to configure the port direction. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me6000_dio_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-6000 digital input/ouput subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param dio_idx The index of the digital i/o port on the device.
+ * @param ctrl_reg_lock Spin lock protecting the control register.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me6000_dio_reg.h b/drivers/staging/meilhaus/me6000_dio_reg.h
new file mode 100644
index 000000000000..e67a791a1e69
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_dio_reg.h
@@ -0,0 +1,43 @@
+/**
+ * @file me6000_dio_reg.h
+ *
+ * @brief ME-6000 digital input/output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME6000_DIO_REG_H_
+#define _ME6000_DIO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME6000_DIO_CTRL_REG 0x00 // R/W
+#define ME6000_DIO_PORT_0_REG 0x01 // R/W
+#define ME6000_DIO_PORT_1_REG 0x02 // R/W
+#define ME6000_DIO_PORT_REG ME6000_DIO_PORT_0_REG // R/W
+
+#define ME6000_DIO_CTRL_BIT_MODE_0 0x01
+#define ME6000_DIO_CTRL_BIT_MODE_1 0x02
+#define ME6000_DIO_CTRL_BIT_MODE_2 0x04
+#define ME6000_DIO_CTRL_BIT_MODE_3 0x08
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me6000_reg.h b/drivers/staging/meilhaus/me6000_reg.h
new file mode 100644
index 000000000000..d35273003415
--- /dev/null
+++ b/drivers/staging/meilhaus/me6000_reg.h
@@ -0,0 +1,35 @@
+/**
+ * @file me6000_reg.h
+ *
+ * @brief ME-6000 device register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME6000_REG_H_
+#define _ME6000_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME6000_INIT_XILINX_REG 0xAC // R/-
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8100_device.c b/drivers/staging/meilhaus/me8100_device.c
new file mode 100644
index 000000000000..1fb79e490261
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_device.c
@@ -0,0 +1,187 @@
+/**
+ * @file me8100_device.c
+ *
+ * @brief ME-8100 device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "medevice.h"
+#include "me8100_device.h"
+#include "mesubdevice.h"
+#include "me8100_di.h"
+#include "me8100_do.h"
+#include "me8254.h"
+
+me_device_t *me8100_pci_constructor(struct pci_dev *pci_device)
+{
+ me8100_device_t *me8100_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ int err;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me8100_device = kmalloc(sizeof(me8100_device_t), GFP_KERNEL);
+
+ if (!me8100_device) {
+ PERROR("Cannot get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(me8100_device, 0, sizeof(me8100_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me8100_device, pci_device);
+
+ if (err) {
+ kfree(me8100_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+
+ /* Get the index in the device version information table. */
+ version_idx =
+ me8100_versions_get_device_index(me8100_device->base.info.pci.
+ device_id);
+
+ // Initialize spin lock .
+ spin_lock_init(&me8100_device->dio_ctrl_reg_lock);
+ spin_lock_init(&me8100_device->ctr_ctrl_reg_lock);
+ spin_lock_init(&me8100_device->clk_src_reg_lock);
+
+ // Create subdevice instances.
+
+ for (i = 0; i < me8100_versions[version_idx].di_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me8100_di_constructor(me8100_device->
+ base.info.pci.
+ reg_bases[2],
+ me8100_device->
+ base.info.pci.
+ reg_bases[1], i,
+ me8100_device->
+ base.irq,
+ &me8100_device->
+ dio_ctrl_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me8100_device);
+ kfree(me8100_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me8100_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me8100_versions[version_idx].do_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me8100_do_constructor(me8100_device->
+ base.info.pci.
+ reg_bases[2], i,
+ &me8100_device->
+ dio_ctrl_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me8100_device);
+ kfree(me8100_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me8100_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me8100_versions[version_idx].ctr_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me8254_constructor(me8100_device->base.
+ info.pci.device_id,
+ me8100_device->base.
+ info.pci.reg_bases[2],
+ 0, i,
+ &me8100_device->
+ ctr_ctrl_reg_lock,
+ &me8100_device->
+ clk_src_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me8100_device);
+ kfree(me8100_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me8100_device->base.slist,
+ subdevice);
+ }
+
+ return (me_device_t *) me8100_device;
+}
+
+// Init and exit of module.
+
+static int __init me8100_init(void)
+{
+ PDEBUG("executed.\n.");
+ return ME_ERRNO_SUCCESS;
+}
+
+static void __exit me8100_exit(void)
+{
+ PDEBUG("executed.\n.");
+}
+
+module_init(me8100_init);
+
+module_exit(me8100_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for Template Device");
+MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me8100_pci_constructor);
diff --git a/drivers/staging/meilhaus/me8100_device.h b/drivers/staging/meilhaus/me8100_device.h
new file mode 100644
index 000000000000..44c42efb04e2
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_device.h
@@ -0,0 +1,97 @@
+/**
+ * @file me8100_device.h
+ *
+ * @brief ME-8100 device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8100_DEVICE_H
+#define _ME8100_DEVICE_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure holding ME-8100 device capabilities.
+ */
+typedef struct me8100_version {
+ uint16_t device_id;
+ unsigned int di_subdevices;
+ unsigned int do_subdevices;
+ unsigned int ctr_subdevices;
+} me8100_version_t;
+
+/**
+ * @brief Device capabilities.
+ */
+static me8100_version_t me8100_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME8100_A, 1, 1, 3},
+ {PCI_DEVICE_ID_MEILHAUS_ME8100_B, 2, 2, 3},
+ {0},
+};
+
+#define ME8100_DEVICE_VERSIONS (sizeof(me8100_versions) / sizeof(me8100_version_t) - 1) /**< Returns the number of entries in #me8100_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #me8100_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me8100_versions.
+ */
+static inline unsigned int me8100_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME8100_DEVICE_VERSIONS; i++)
+ if (me8100_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The ME-8100 device class structure.
+ */
+typedef struct me8100_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+
+ /* Child class attributes. */
+ spinlock_t dio_ctrl_reg_lock;
+ spinlock_t ctr_ctrl_reg_lock;
+ spinlock_t clk_src_reg_lock;
+} me8100_device_t;
+
+/**
+ * @brief The ME-8100 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-8100 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me8100_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8100_di.c b/drivers/staging/meilhaus/me8100_di.c
new file mode 100644
index 000000000000..971727c9e305
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_di.c
@@ -0,0 +1,693 @@
+/**
+ * @file me8100_di.c
+ *
+ * @brief ME-8100 digital input subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+
+#include "medefines.h"
+#include "meerror.h"
+
+#include "meids.h"
+#include "medebug.h"
+#include "meplx_reg.h"
+#include "me8100_reg.h"
+#include "me8100_di_reg.h"
+#include "me8100_di.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me8100_di_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me8100_di_subdevice_t *instance;
+ unsigned short ctrl;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_di_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->ctrl_reg_lock);
+ ctrl = inw(instance->ctrl_reg);
+ ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0);
+ outw(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outw(0, instance->mask_reg);
+ PDEBUG_REG("mask_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->mask_reg - instance->reg_base, 0);
+ outw(0, instance->pattern_reg);
+ PDEBUG_REG("pattern_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->pattern_reg - instance->reg_base, 0);
+ instance->rised = -1;
+ instance->irq_count = 0;
+ instance->filtering_flag = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ outl(PLX_INTCSR_LOCAL_INT1_EN |
+ PLX_INTCSR_LOCAL_INT1_POL |
+ PLX_INTCSR_LOCAL_INT2_EN |
+ PLX_INTCSR_LOCAL_INT2_POL |
+ PLX_INTCSR_PCI_INT_EN, instance->irq_status_reg);
+ PDEBUG_REG("plx:irq_status_reg outl(0x%lX)=0x%x\n",
+ instance->irq_status_reg,
+ PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL |
+ PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL |
+ PLX_INTCSR_PCI_INT_EN);
+
+ wake_up_interruptible_all(&instance->wait_queue);
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_di_io_irq_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ me8100_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint16_t ctrl;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_di_subdevice_t *) subdevice;
+
+ if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
+ if (flags &
+ ~(ME_IO_IRQ_START_PATTERN_FILTERING |
+ ME_IO_IRQ_START_DIO_WORD)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (irq_edge != ME_IRQ_EDGE_NOT_USED) {
+ PERROR("Invalid irq edge specified.\n");
+ return ME_ERRNO_INVALID_IRQ_EDGE;
+ }
+ } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
+ if (flags &
+ ~(ME_IO_IRQ_START_EXTENDED_STATUS |
+ ME_IO_IRQ_START_DIO_WORD)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (irq_edge != ME_IRQ_EDGE_ANY) {
+ PERROR("Invalid irq edge specified.\n");
+ return ME_ERRNO_INVALID_IRQ_EDGE;
+ }
+
+ if (!(irq_arg & 0xFFFF)) {
+ PERROR("No mask specified.\n");
+ return ME_ERRNO_INVALID_IRQ_ARG;
+ }
+ } else {
+ PERROR("Invalid irq source specified.\n");
+ return ME_ERRNO_INVALID_IRQ_SOURCE;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
+ outw(irq_arg, instance->pattern_reg);
+ instance->compare_value = irq_arg;
+ instance->filtering_flag =
+ (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0;
+ }
+ if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
+ outw(irq_arg, instance->mask_reg);
+ }
+
+ spin_lock(instance->ctrl_reg_lock);
+ ctrl = inw(instance->ctrl_reg);
+ ctrl |= ME8100_DIO_CTRL_BIT_INTB_0;
+ if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
+ ctrl &= ~ME8100_DIO_CTRL_BIT_INTB_1;
+ }
+
+ if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
+ ctrl |= ME8100_DIO_CTRL_BIT_INTB_1;
+ }
+ outw(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ instance->rised = 0;
+ instance->status_value = 0;
+ instance->status_value_edges = 0;
+ instance->line_value = inw(instance->port_reg);
+ instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8100_di_io_irq_wait(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ me8100_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ unsigned long cpu_flags;
+ int count;
+
+ PDEBUG("executed.\n");
+ PDEVELOP("PID: %d.\n", current->pid);
+
+ instance = (me8100_di_subdevice_t *) subdevice;
+
+ if (flags &
+ ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->rised <= 0) {
+ instance->rised = 0;
+ count = instance->irq_count;
+
+ if (time_out) {
+ t = wait_event_interruptible_timeout(instance->
+ wait_queue,
+ ((count !=
+ instance->
+ irq_count)
+ || (instance->
+ rised < 0)),
+ t);
+// t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t);
+ if (t == 0) {
+ PERROR("Wait on interrupt timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ } else {
+ wait_event_interruptible(instance->wait_queue,
+ ((count != instance->irq_count)
+ || (instance->rised < 0)));
+// wait_event_interruptible(instance->wait_queue, (instance->rised != 0));
+ }
+
+ if (instance->rised < 0) {
+ PERROR("Wait on interrupt aborted by user.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on interrupt aborted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ *irq_count = instance->irq_count;
+ if (!err) {
+ if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) {
+ *value = instance->status_value;
+ } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) {
+ *value = instance->status_value_edges;
+ } else { // Use default
+ if (!instance->status_flag) {
+ *value = instance->status_value;
+ } else {
+ *value = instance->status_value_edges;
+ }
+ }
+ instance->rised = 0;
+/*
+ instance->status_value = 0;
+ instance->status_value_edges = 0;
+*/
+ } else {
+ *value = 0;
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8100_di_io_irq_stop(me_subdevice_t * subdevice,
+ struct file *filep, int channel, int flags)
+{
+ me8100_di_subdevice_t *instance;
+ uint16_t ctrl;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_di_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->ctrl_reg_lock);
+ ctrl = inw(instance->ctrl_reg);
+ ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0);
+ outw(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock(instance->ctrl_reg_lock);
+ instance->rised = -1;
+ instance->status_value = 0;
+ instance->status_value_edges = 0;
+ instance->filtering_flag = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_di_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me8100_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_WORD:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ } else {
+ PERROR
+ ("Invalid port configuration specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8100_di_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me8100_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+
+ switch (flags) {
+
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 16)) {
+ *value = inw(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inw(instance->port_reg) & 0xFF;
+ } else if (channel == 1) {
+ *value = (inw(instance->port_reg) >> 8) & 0xFF;
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_WORD:
+ if (channel == 0) {
+ *value = inw(instance->port_reg);
+ } else {
+ PERROR("Invalid word number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8100_di_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 16;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_di_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DI;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_BIT_PATTERN_IRQ | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY;
+ return ME_ERRNO_SUCCESS;
+}
+
+static void me8100_di_destructor(struct me_subdevice *subdevice)
+{
+ me8100_di_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_di_subdevice_t *) subdevice;
+
+ free_irq(instance->irq, (void *)instance);
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me8100_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me8100_isr(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{
+ me8100_di_subdevice_t *instance;
+ uint32_t icsr;
+
+ uint16_t irq_status;
+ uint16_t line_value = 0;
+
+ uint32_t status_val = 0;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_di_subdevice_t *) dev_id;
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ icsr = inl(instance->irq_status_reg);
+ if (instance->di_idx == 0) {
+
+ if ((icsr &
+ (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN |
+ PLX_INTCSR_LOCAL_INT1_EN)) !=
+ (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN |
+ PLX_INTCSR_LOCAL_INT1_EN)) {
+ PINFO
+ ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n",
+ jiffies, __func__, icsr);
+ return IRQ_NONE;
+ }
+ } else if (instance->di_idx == 1) {
+ if ((icsr &
+ (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN |
+ PLX_INTCSR_LOCAL_INT2_EN)) !=
+ (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN |
+ PLX_INTCSR_LOCAL_INT2_EN)) {
+ PINFO
+ ("%ld Shared interrupt. %s(): idx=1 plx:irq_status_reg=0x%04X\n",
+ jiffies, __func__, icsr);
+ return IRQ_NONE;
+ }
+ } else {
+ PERROR("%s():Wrong interrupt idx=%d csr=0x%X.\n", __func__,
+ instance->di_idx, icsr);
+ return IRQ_NONE;
+ }
+
+ PDEBUG("me8100_isr():Interrupt from idx=%d occured.\n",
+ instance->di_idx);
+ spin_lock(&instance->subdevice_lock);
+ inw(instance->irq_reset_reg);
+ line_value = inw(instance->port_reg);
+
+ irq_status = instance->line_value ^ line_value;
+
+ // Make extended information.
+ status_val |= (0x00FF & (~(uint16_t) instance->line_value & line_value)) << 16; //Raise
+ status_val |= (0x00FF & ((uint16_t) instance->line_value & ~line_value)); //Fall
+
+ instance->line_value = line_value;
+
+ if (instance->rised == 0) {
+ instance->status_value = irq_status;
+ instance->status_value_edges = status_val;
+ } else {
+ instance->status_value |= irq_status;
+ instance->status_value_edges |= status_val;
+ }
+
+ if (instance->filtering_flag) { // For compare mode only.
+ if (instance->compare_value == instance->line_value) {
+ instance->rised = 1;
+ instance->irq_count++;
+ }
+ } else {
+ instance->rised = 1;
+ instance->irq_count++;
+ }
+
+ spin_unlock(&instance->subdevice_lock);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base,
+ uint32_t plx_reg_base,
+ unsigned int di_idx,
+ int irq,
+ spinlock_t * ctrl_reg_lock)
+{
+ me8100_di_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me8100_di_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me8100_di_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save the subdevice index. */
+ subdevice->di_idx = di_idx;
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ /* Register interrupt service routine. */
+ subdevice->irq = irq;
+ err = request_irq(subdevice->irq, me8100_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME8100_NAME, (void *)subdevice);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", subdevice->irq);
+
+ /* Initialize the registers */
+ subdevice->ctrl_reg =
+ me8100_reg_base + ME8100_CTRL_REG_A + di_idx * ME8100_REG_OFFSET;
+ subdevice->port_reg =
+ me8100_reg_base + ME8100_DI_REG_A + di_idx * ME8100_REG_OFFSET;
+ subdevice->mask_reg =
+ me8100_reg_base + ME8100_MASK_REG_A + di_idx * ME8100_REG_OFFSET;
+ subdevice->pattern_reg =
+ me8100_reg_base + ME8100_PATTERN_REG_A + di_idx * ME8100_REG_OFFSET;
+ subdevice->din_int_reg =
+ me8100_reg_base + ME8100_INT_DI_REG_A + di_idx * ME8100_REG_OFFSET;
+ subdevice->irq_reset_reg =
+ me8100_reg_base + ME8100_RES_INT_REG_A + di_idx * ME8100_REG_OFFSET;
+ subdevice->irq_status_reg = plx_reg_base + PLX_INTCSR;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = me8100_reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_irq_start = me8100_di_io_irq_start;
+ subdevice->base.me_subdevice_io_irq_wait = me8100_di_io_irq_wait;
+ subdevice->base.me_subdevice_io_irq_stop = me8100_di_io_irq_stop;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me8100_di_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me8100_di_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me8100_di_io_single_read;
+ subdevice->base.me_subdevice_query_number_channels =
+ me8100_di_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me8100_di_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me8100_di_query_subdevice_caps;
+ subdevice->base.me_subdevice_destructor = me8100_di_destructor;
+
+ subdevice->rised = 0;
+ subdevice->irq_count = 0;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me8100_di.h b/drivers/staging/meilhaus/me8100_di.h
new file mode 100644
index 000000000000..e1db79129175
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_di.h
@@ -0,0 +1,89 @@
+/**
+ * @file me8100_di.h
+ *
+ * @brief ME-8100 digital input subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8100_DI_H_
+#define _ME8100_DI_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me8100_di_subdevice {
+ // Inheritance
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock;
+
+ unsigned di_idx;
+
+ int irq;
+ volatile int rised;
+ unsigned int irq_count;
+
+ uint status_flag; /**< Default interupt status flag */
+ uint status_value; /**< Interupt status */
+ uint status_value_edges; /**< Extended interupt status */
+ uint line_value;
+
+ uint16_t compare_value;
+ uint8_t filtering_flag;
+
+ wait_queue_head_t wait_queue;
+
+ unsigned long ctrl_reg;
+ unsigned long port_reg;
+ unsigned long mask_reg;
+ unsigned long pattern_reg;
+ unsigned long long din_int_reg;
+ unsigned long irq_reset_reg;
+ unsigned long irq_status_reg;
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+
+} me8100_di_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-8100 digital input subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base,
+ uint32_t plx_reg_base,
+ unsigned int di_idx,
+ int irq,
+ spinlock_t * ctrl_leg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8100_di_reg.h b/drivers/staging/meilhaus/me8100_di_reg.h
new file mode 100644
index 000000000000..063bd193709e
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_di_reg.h
@@ -0,0 +1,47 @@
+/**
+ * @file me8100_di_reg.h
+ *
+ * @brief ME-8100 digital input subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8100_DI_REG_H_
+#define _ME8100_DI_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME8100_RES_INT_REG_A 0x02 //(r, )
+#define ME8100_DI_REG_A 0x04 //(r, )
+#define ME8100_PATTERN_REG_A 0x08 //( ,w)
+#define ME8100_MASK_REG_A 0x0A //( ,w)
+#define ME8100_INT_DI_REG_A 0x0A //(r, )
+
+#define ME8100_RES_INT_REG_B 0x0E //(r, )
+#define ME8100_DI_REG_B 0x10 //(r, )
+#define ME8100_PATTERN_REG_B 0x14 //( ,w)
+#define ME8100_MASK_REG_B 0x16 //( ,w)
+#define ME8100_INT_DI_REG_B 0x16 //(r, )
+
+#define ME8100_REG_OFFSET 0x0C
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8100_do.c b/drivers/staging/meilhaus/me8100_do.c
new file mode 100644
index 000000000000..957b9f92f760
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_do.c
@@ -0,0 +1,391 @@
+/**
+ * @file me8100_do.c
+ *
+ * @brief ME-8100 digital output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me8100_reg.h"
+#include "me8100_do_reg.h"
+#include "me8100_do.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me8100_do_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me8100_do_subdevice_t *instance;
+ uint16_t ctrl;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_do_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ ctrl = inw(instance->ctrl_reg);
+ ctrl &= ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0;
+ outw(ctrl, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock(instance->ctrl_reg_lock);
+ outw(0, instance->port_reg);
+ instance->port_reg_mirror = 0;
+ PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_do_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me8100_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ int config;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ config = inw(instance->ctrl_reg);
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_WORD:
+ if (channel == 0) {
+ if (single_config ==
+ ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE) {
+ config &= ~(ME8100_DIO_CTRL_BIT_ENABLE_DIO);
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_SINK) {
+ config |= ME8100_DIO_CTRL_BIT_ENABLE_DIO;
+ config &= ~ME8100_DIO_CTRL_BIT_SOURCE;
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_SOURCE) {
+ config |=
+ ME8100_DIO_CTRL_BIT_ENABLE_DIO |
+ ME8100_DIO_CTRL_BIT_SOURCE;
+ } else {
+ PERROR
+ ("Invalid port configuration specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid word number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!err) {
+ outw(config, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, config);
+ }
+
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8100_do_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me8100_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 16)) {
+ *value = instance->port_reg_mirror & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = instance->port_reg_mirror & 0xFF;
+ } else if (channel == 1) {
+ *value = (instance->port_reg_mirror >> 8) & 0xFF;
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_WORD:
+ if (channel == 0) {
+ *value = instance->port_reg_mirror;
+ } else {
+ PERROR("Invalid word number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8100_do_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me8100_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8100_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 16)) {
+ instance->port_reg_mirror =
+ value ? (instance->
+ port_reg_mirror | (0x1 << channel))
+ : (instance->port_reg_mirror & ~(0x1 << channel));
+ outw(instance->port_reg_mirror, instance->port_reg);
+ PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg - instance->reg_base,
+ instance->port_reg_mirror);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ instance->port_reg_mirror &= ~0xFF;
+ instance->port_reg_mirror |= value & 0xFF;
+ outw(instance->port_reg_mirror, instance->port_reg);
+ PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg - instance->reg_base,
+ instance->port_reg_mirror);
+ } else if (channel == 1) {
+ instance->port_reg_mirror &= ~0xFF00;
+ instance->port_reg_mirror |= (value << 8) & 0xFF00;
+ outw(instance->port_reg_mirror, instance->port_reg);
+ PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg - instance->reg_base,
+ instance->port_reg_mirror);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_WORD:
+ if (channel == 0) {
+ instance->port_reg_mirror = value;
+ outw(value, instance->port_reg);
+ PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg - instance->reg_base,
+ value);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8100_do_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 16;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_do_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_SINK_SOURCE;
+ return ME_ERRNO_SUCCESS;
+}
+
+me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base,
+ unsigned int do_idx,
+ spinlock_t * ctrl_reg_lock)
+{
+ me8100_do_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me8100_do_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me8100_do_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Initialize registers */
+ if (do_idx == 0) {
+ subdevice->port_reg = reg_base + ME8100_DO_REG_A;
+ subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_A;
+ } else if (do_idx == 1) {
+ subdevice->port_reg = reg_base + ME8100_DO_REG_B;
+ subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_B;
+ } else {
+ PERROR("Wrong subdevice idx=%d.\n", do_idx);
+ kfree(subdevice);
+ return NULL;
+ }
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save the subdevice index */
+ subdevice->do_idx = do_idx;
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me8100_do_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me8100_do_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me8100_do_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me8100_do_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me8100_do_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me8100_do_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me8100_do_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me8100_do.h b/drivers/staging/meilhaus/me8100_do.h
new file mode 100644
index 000000000000..acf880136663
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_do.h
@@ -0,0 +1,70 @@
+/**
+ * @file me8100_do.h
+ *
+ * @brief ME-8100 digital output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8100_DO_H_
+#define _ME8100_DO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me8100_do_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect the #ctrl_reg. */
+
+ unsigned int do_idx;
+
+ uint16_t port_reg_mirror; /**< Mirror used to store current port register setting which is write only. */
+
+ unsigned long port_reg; /**< Register holding the port status. */
+ unsigned long ctrl_reg; /**< Control register. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me8100_do_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-8100 digital output subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param do_idx The index of the digital output subdevice on this device.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base,
+ unsigned int do_idx,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8100_do_reg.h b/drivers/staging/meilhaus/me8100_do_reg.h
new file mode 100644
index 000000000000..13a23802b31a
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_do_reg.h
@@ -0,0 +1,36 @@
+/**
+ * @file me8100_ao_reg.h
+ *
+ * @brief ME-8100 analog output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8100_DO_REG_H_
+#define _ME8100_DO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME8100_DO_REG_A 0x06 //( ,w)
+#define ME8100_DO_REG_B 0x12 //( ,w)
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8100_reg.h b/drivers/staging/meilhaus/me8100_reg.h
new file mode 100644
index 000000000000..d8c4b1c6b153
--- /dev/null
+++ b/drivers/staging/meilhaus/me8100_reg.h
@@ -0,0 +1,41 @@
+/**
+ * @file me8100_reg.h
+ *
+ * @brief ME-8100 register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8100_REG_H_
+#define _ME8100_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME8100_CTRL_REG_A 0x00 //( ,w)
+#define ME8100_CTRL_REG_B 0x0C //( ,w)
+
+#define ME8100_DIO_CTRL_BIT_SOURCE 0x10
+#define ME8100_DIO_CTRL_BIT_INTB_1 0x20
+#define ME8100_DIO_CTRL_BIT_INTB_0 0x40
+#define ME8100_DIO_CTRL_BIT_ENABLE_DIO 0x80
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_device.c b/drivers/staging/meilhaus/me8200_device.c
new file mode 100644
index 000000000000..261c0cbd9d0a
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_device.c
@@ -0,0 +1,194 @@
+/**
+ * @file me8200_device.c
+ *
+ * @brief ME-8200 device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include "meids.h"
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "meplx_reg.h"
+#include "medevice.h"
+#include "me8200_device.h"
+#include "mesubdevice.h"
+#include "me8200_di.h"
+#include "me8200_do.h"
+#include "me8200_dio.h"
+
+me_device_t *me8200_pci_constructor(struct pci_dev *pci_device)
+{
+ me8200_device_t *me8200_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ int err;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ me8200_device = kmalloc(sizeof(me8200_device_t), GFP_KERNEL);
+
+ if (!me8200_device) {
+ PERROR("Cannot get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(me8200_device, 0, sizeof(me8200_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) me8200_device, pci_device);
+
+ if (err) {
+ kfree(me8200_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+
+ /* Get the index in the device version information table. */
+ version_idx =
+ me8200_versions_get_device_index(me8200_device->base.info.pci.
+ device_id);
+
+ // Initialize spin lock .
+ spin_lock_init(&me8200_device->irq_ctrl_lock);
+ spin_lock_init(&me8200_device->irq_mode_lock);
+ spin_lock_init(&me8200_device->dio_ctrl_lock);
+
+ /* Setup the PLX interrupt configuration */
+ outl(PLX_INTCSR_LOCAL_INT1_EN |
+ PLX_INTCSR_LOCAL_INT1_POL |
+ PLX_INTCSR_LOCAL_INT2_EN |
+ PLX_INTCSR_LOCAL_INT2_POL |
+ PLX_INTCSR_PCI_INT_EN,
+ me8200_device->base.info.pci.reg_bases[1] + PLX_INTCSR);
+
+ // Create subdevice instances.
+
+ for (i = 0; i < me8200_versions[version_idx].di_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me8200_di_constructor(me8200_device->
+ base.info.pci.
+ reg_bases[2], i,
+ me8200_device->
+ base.irq,
+ &me8200_device->
+ irq_ctrl_lock,
+ &me8200_device->
+ irq_mode_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me8200_device);
+ kfree(me8200_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me8200_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me8200_versions[version_idx].do_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me8200_do_constructor(me8200_device->
+ base.info.pci.
+ reg_bases[2], i,
+ me8200_device->
+ base.irq,
+ &me8200_device->
+ irq_mode_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me8200_device);
+ kfree(me8200_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me8200_device->base.slist,
+ subdevice);
+ }
+
+ for (i = 0; i < me8200_versions[version_idx].dio_subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) me8200_dio_constructor(me8200_device->
+ base.info.pci.
+ reg_bases[2], i,
+ &me8200_device->
+ dio_ctrl_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) me8200_device);
+ kfree(me8200_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&me8200_device->base.slist,
+ subdevice);
+ }
+
+ return (me_device_t *) me8200_device;
+}
+
+// Init and exit of module.
+
+static int __init me8200_init(void)
+{
+ PDEBUG("executed.\n.");
+ return 0;
+}
+
+static void __exit me8200_exit(void)
+{
+ PDEBUG("executed.\n.");
+}
+
+module_init(me8200_init);
+
+module_exit(me8200_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for Template Device");
+MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(me8200_pci_constructor);
diff --git a/drivers/staging/meilhaus/me8200_device.h b/drivers/staging/meilhaus/me8200_device.h
new file mode 100644
index 000000000000..cbd2a01ddb41
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_device.h
@@ -0,0 +1,97 @@
+/**
+ * @file me8200_device.h
+ *
+ * @brief ME-8200 device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_DEVICE_H
+#define _ME8200_DEVICE_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure holding ME-8200 device capabilities.
+ */
+typedef struct me8200_version {
+ uint16_t device_id;
+ unsigned int di_subdevices;
+ unsigned int do_subdevices;
+ unsigned int dio_subdevices;
+} me8200_version_t;
+
+/**
+ * @brief Device capabilities.
+ */
+static me8200_version_t me8200_versions[] = {
+ {PCI_DEVICE_ID_MEILHAUS_ME8200_A, 1, 1, 2},
+ {PCI_DEVICE_ID_MEILHAUS_ME8200_B, 2, 2, 2},
+ {0},
+};
+
+#define ME8200_DEVICE_VERSIONS (sizeof(me8200_versions) / sizeof(me8200_version_t) - 1) /**< Returns the number of entries in #me8200_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #me8200_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #me8200_versions.
+ */
+static inline unsigned int me8200_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < ME8200_DEVICE_VERSIONS; i++)
+ if (me8200_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The ME-8200 device class structure.
+ */
+typedef struct me8200_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+
+ /* Child class attributes. */
+ spinlock_t irq_ctrl_lock; /**< Lock for the interrupt control register. */
+ spinlock_t irq_mode_lock; /**< Lock for the interrupt mode register. */
+ spinlock_t dio_ctrl_lock; /**< Lock for the digital i/o control register. */
+} me8200_device_t;
+
+/**
+ * @brief The ME-8200 device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new ME-8200 device instance. \n
+ * NULL on error.
+ */
+me_device_t *me8200_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_di.c b/drivers/staging/meilhaus/me8200_di.c
new file mode 100644
index 000000000000..27525bc067b6
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_di.c
@@ -0,0 +1,857 @@
+/**
+ * @file me8200_di.c
+ *
+ * @brief ME-8200 digital input subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+///Includes
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+
+#include "medefines.h"
+#include "meerror.h"
+
+#include "meids.h"
+#include "medebug.h"
+#include "me8200_reg.h"
+#include "me8200_di_reg.h"
+#include "me8200_di.h"
+
+/// Defines
+static void me8200_di_destructor(struct me_subdevice *subdevice);
+static int me8200_di_io_irq_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags);
+static int me8200_di_io_irq_wait(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags);
+static int me8200_di_io_irq_stop(me_subdevice_t * subdevice,
+ struct file *filep, int channel, int flags);
+static int me8200_di_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags);
+static int me8200_di_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags);
+static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags);
+static int me8200_di_query_number_channels(me_subdevice_t * subdevice,
+ int *number);
+static int me8200_di_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype);
+static int me8200_di_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me8200_isr(int irq, void *dev_id);
+#else
+static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me8200_isr_EX(int irq, void *dev_id);
+#else
+static irqreturn_t me8200_isr_EX(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+static void me8200_di_check_version(me8200_di_subdevice_t * instance,
+ unsigned long addr);
+
+///Functions
+static int me8200_di_io_irq_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ me8200_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ volatile uint8_t tmp;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_di_subdevice_t *) subdevice;
+
+ if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
+ if (flags &
+ ~(ME_IO_IRQ_START_PATTERN_FILTERING |
+ ME_IO_IRQ_START_DIO_BYTE)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (irq_edge != ME_IRQ_EDGE_NOT_USED) {
+ PERROR("Invalid irq edge specified.\n");
+ return ME_ERRNO_INVALID_IRQ_EDGE;
+ }
+ } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
+ if (flags &
+ ~(ME_IO_IRQ_START_EXTENDED_STATUS |
+ ME_IO_IRQ_START_DIO_BYTE)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if ((irq_edge != ME_IRQ_EDGE_RISING)
+ && (irq_edge != ME_IRQ_EDGE_FALLING)
+ && (irq_edge != ME_IRQ_EDGE_ANY)) {
+ PERROR("Invalid irq edge specified.\n");
+ return ME_ERRNO_INVALID_IRQ_EDGE;
+ }
+
+ if (!(irq_arg & 0xFF)) {
+ PERROR("No mask specified.\n");
+ return ME_ERRNO_INVALID_IRQ_ARG;
+ }
+ } else {
+ PERROR("Invalid irq source specified.\n");
+ return ME_ERRNO_INVALID_IRQ_SOURCE;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, status);
+ if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
+ outb(irq_arg, instance->compare_reg);
+ PDEBUG_REG("compare_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->compare_reg - instance->reg_base, irq_arg);
+ outb(0xFF, instance->mask_reg);
+ PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->mask_reg - instance->reg_base, 0xff);
+ instance->compare_value = irq_arg;
+ instance->filtering_flag =
+ (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0;
+ }
+ if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
+ outb(irq_arg, instance->mask_reg);
+ PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->mask_reg - instance->reg_base, irq_arg);
+ instance->filtering_flag = 0;
+ }
+
+ spin_lock(instance->irq_mode_lock);
+ tmp = inb(instance->irq_mode_reg);
+ tmp &=
+ ~(ME8200_IRQ_MODE_MASK <<
+ (ME8200_IRQ_MODE_DI_SHIFT * instance->di_idx));
+ if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
+ tmp |=
+ ME8200_IRQ_MODE_MASK_COMPARE << (ME8200_IRQ_MODE_DI_SHIFT *
+ instance->di_idx);
+ }
+
+ if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
+ tmp |=
+ ME8200_IRQ_MODE_MASK_MASK << (ME8200_IRQ_MODE_DI_SHIFT *
+ instance->di_idx);
+ }
+ outb(tmp, instance->irq_mode_reg);
+ PDEBUG_REG("irq_mode_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_mode_reg - instance->reg_base, tmp);
+ spin_unlock(instance->irq_mode_lock);
+
+ spin_lock(instance->irq_ctrl_lock);
+ tmp = inb(instance->irq_ctrl_reg);
+ tmp |=
+ (ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+ tmp |=
+ ME8200_DI_IRQ_CTRL_BIT_ENABLE << (ME8200_DI_IRQ_CTRL_SHIFT *
+ instance->di_idx);
+
+ if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
+ tmp &=
+ ~(ME8200_DI_IRQ_CTRL_MASK_EDGE <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+ if (irq_edge == ME_IRQ_EDGE_RISING) {
+ tmp |=
+ ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
+ } else if (irq_edge == ME_IRQ_EDGE_FALLING) {
+ tmp |=
+ ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
+ } else if (irq_edge == ME_IRQ_EDGE_ANY) {
+ tmp |=
+ ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
+ }
+ }
+ outb(tmp, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, tmp);
+ tmp &=
+ ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+ outb(tmp, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, tmp);
+
+ instance->line_value = inb(instance->port_reg);
+ spin_unlock(instance->irq_ctrl_lock);
+
+ instance->rised = 0;
+ instance->status_value = 0;
+ instance->status_value_edges = 0;
+ instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS;
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_di_io_irq_wait(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ me8200_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ unsigned long cpu_flags;
+ int count;
+
+ PDEBUG("executed.\n");
+ PDEVELOP("PID: %d.\n", current->pid);
+
+ instance = (me8200_di_subdevice_t *) subdevice;
+
+ if (flags &
+ ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->rised <= 0) {
+ instance->rised = 0;
+ count = instance->count;
+
+ if (time_out) {
+ t = wait_event_interruptible_timeout(instance->
+ wait_queue,
+ ((count !=
+ instance->count)
+ || (instance->
+ rised < 0)),
+ t);
+// t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t);
+ if (t == 0) {
+ PERROR("Wait on interrupt timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ } else {
+ wait_event_interruptible(instance->wait_queue,
+ ((count != instance->count)
+ || (instance->rised < 0)));
+// wait_event_interruptible(instance->wait_queue, (instance->rised != 0));
+ }
+
+ if (instance->rised < 0) {
+ PERROR("Wait on interrupt aborted by user.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on interrupt aborted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ *irq_count = instance->count;
+ if (!err) {
+ if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) {
+ *value = instance->status_value;
+ } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) {
+ *value = instance->status_value_edges;
+ } else { // Use default
+ if (!instance->status_flag) {
+ *value = instance->status_value;
+ } else {
+ *value = instance->status_value_edges;
+ }
+ }
+ instance->rised = 0;
+/*
+ instance->status_value = 0;
+ instance->status_value_edges = 0;
+*/
+ } else {
+ *value = 0;
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_di_io_irq_stop(me_subdevice_t * subdevice,
+ struct file *filep, int channel, int flags)
+{
+ me8200_di_subdevice_t *instance;
+ uint8_t tmp;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_di_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status);
+ spin_lock(instance->irq_ctrl_lock);
+ tmp = inb(instance->irq_ctrl_reg);
+ tmp |=
+ (ME8200_DI_IRQ_CTRL_BIT_ENABLE <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+ outb(tmp, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, tmp);
+ tmp &=
+ ~(ME8200_DI_IRQ_CTRL_BIT_ENABLE <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+ tmp |=
+ (ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+// tmp &= ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+ outb(tmp, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->irq_ctrl_lock);
+
+ instance->rised = -1;
+ instance->status_value = 0;
+ instance->status_value_edges = 0;
+ instance->filtering_flag = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_di_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me8200_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, status);
+
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ } else {
+ PERROR("Invalid port direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_di_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me8200_di_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_di_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, status);
+
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = inb(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inb(instance->port_reg);
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me8200_di_subdevice_t *instance = (me8200_di_subdevice_t *) subdevice;
+
+ PDEBUG("executed.\n");
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ instance->count = 0;
+ return me8200_di_io_irq_stop(subdevice, filep, 0, 0);
+}
+
+static int me8200_di_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_di_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DI;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps =
+ ME_CAPS_DIO_BIT_PATTERN_IRQ |
+ ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_RISING |
+ ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_FALLING |
+ ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY;
+ return ME_ERRNO_SUCCESS;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me8200_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{
+ me8200_di_subdevice_t *instance;
+ uint8_t ctrl;
+ uint8_t irq_status;
+ uint8_t line_value = 0;
+ uint8_t line_status = 0;
+ uint32_t status_val = 0;
+
+ instance = (me8200_di_subdevice_t *) dev_id;
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ irq_status = inb(instance->irq_status_reg);
+ if (!irq_status) {
+ PINFO
+ ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
+ jiffies, __func__, instance->di_idx, irq_status);
+ return IRQ_NONE;
+ }
+
+ PDEBUG("executed.\n");
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->irq_ctrl_lock);
+ ctrl = inb(instance->irq_ctrl_reg);
+ ctrl |=
+ ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT *
+ instance->di_idx);
+ outb(ctrl, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, ctrl);
+ ctrl &=
+ ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
+ (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
+ outb(ctrl, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, ctrl);
+
+ line_value = inb(instance->port_reg);
+ spin_unlock(instance->irq_ctrl_lock);
+
+ line_status = ((uint8_t) instance->line_value ^ line_value);
+
+ // Make extended information.
+ status_val |= (0x00FF & (~(uint8_t) instance->line_value & line_value)) << 16; //Raise
+ status_val |= (0x00FF & ((uint8_t) instance->line_value & ~line_value)); //Fall
+
+ instance->line_value = (int)line_value;
+
+ if (instance->rised == 0) {
+ instance->status_value = irq_status | line_status;
+ instance->status_value_edges = status_val;
+ } else {
+ instance->status_value |= irq_status | line_status;
+ instance->status_value_edges |= status_val;
+ }
+
+ if (instance->filtering_flag) { // For compare mode only.
+ if (instance->compare_value == instance->line_value) {
+ instance->rised = 1;
+ instance->count++;
+ }
+ } else {
+ instance->rised = 1;
+ instance->count++;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ spin_unlock(&instance->subdevice_lock);
+
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me8200_isr_EX(int irq, void *dev_id)
+#else
+static irqreturn_t me8200_isr_EX(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{
+ me8200_di_subdevice_t *instance;
+ uint8_t irq_status = 0;
+ uint16_t irq_status_EX = 0;
+ uint32_t status_val = 0;
+ int i, j;
+
+ instance = (me8200_di_subdevice_t *) dev_id;
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ PDEBUG("executed.\n");
+
+ //Reset latches. Copy status to extended registers.
+ irq_status = inb(instance->irq_status_reg);
+ PDEBUG_REG("idx=%d irq_status_reg=0x%02X\n", instance->di_idx,
+ irq_status);
+
+ if (!irq_status) {
+ PINFO
+ ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
+ jiffies, __func__, instance->di_idx, irq_status);
+ return IRQ_NONE;
+ }
+
+ irq_status_EX = inb(instance->irq_status_low_reg);
+ irq_status_EX |= (inb(instance->irq_status_high_reg) << 8);
+
+ PDEVELOP("EXTENDED REG: 0x%04x\n", irq_status_EX);
+ instance->line_value = inb(instance->port_reg);
+
+ // Format extended information.
+ for (i = 0, j = 0; i < 8; i++, j += 2) {
+ status_val |= ((0x01 << j) & irq_status_EX) >> (j - i); //Fall
+ status_val |= ((0x01 << (j + 1)) & irq_status_EX) << (15 - j + i); //Raise
+ }
+
+ spin_lock(&instance->subdevice_lock);
+ if (instance->rised == 0) {
+ instance->status_value = irq_status;
+ instance->status_value_edges = status_val;
+ } else {
+ instance->status_value |= irq_status;
+ instance->status_value_edges |= status_val;
+ }
+
+ if (instance->filtering_flag) { // For compare mode only.
+ if (instance->compare_value == instance->line_value) {
+ instance->rised = 1;
+ instance->count++;
+ }
+ } else {
+ instance->rised = 1;
+ instance->count++;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+static void me8200_di_destructor(struct me_subdevice *subdevice)
+{
+ me8200_di_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_di_subdevice_t *) subdevice;
+
+ free_irq(instance->irq, (void *)instance);
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_regbase,
+ unsigned int di_idx,
+ int irq,
+ spinlock_t * irq_ctrl_lock,
+ spinlock_t * irq_mode_lock)
+{
+ me8200_di_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me8200_di_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me8200_di_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Check firmware version.
+ me8200_di_check_version(subdevice,
+ me8200_regbase + ME8200_FIRMWARE_VERSION_REG);
+
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->irq_ctrl_lock = irq_ctrl_lock;
+ subdevice->irq_mode_lock = irq_mode_lock;
+
+ /* Save the subdevice index. */
+ subdevice->di_idx = di_idx;
+
+ /* Initialize registers */
+ if (di_idx == 0) {
+ subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_0_REG;
+ subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_0_REG;
+ subdevice->compare_reg =
+ me8200_regbase + ME8200_DI_COMPARE_0_REG;
+ subdevice->irq_status_reg =
+ me8200_regbase + ME8200_DI_CHANGE_0_REG;
+
+ subdevice->irq_status_low_reg =
+ me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_LOW_REG;
+ subdevice->irq_status_high_reg =
+ me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_HIGH_REG;
+ } else if (di_idx == 1) {
+ subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_1_REG;
+ subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_1_REG;
+ subdevice->compare_reg =
+ me8200_regbase + ME8200_DI_COMPARE_1_REG;
+ subdevice->irq_status_reg =
+ me8200_regbase + ME8200_DI_CHANGE_1_REG;
+
+ subdevice->irq_status_low_reg =
+ me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_LOW_REG;
+ subdevice->irq_status_high_reg =
+ me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_HIGH_REG;
+ } else {
+ PERROR("Wrong subdevice idx=%d.\n", di_idx);
+ kfree(subdevice);
+ return NULL;
+ }
+ subdevice->irq_ctrl_reg = me8200_regbase + ME8200_DI_IRQ_CTRL_REG;
+ subdevice->irq_mode_reg = me8200_regbase + ME8200_IRQ_MODE_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = me8200_regbase;
+#endif
+
+ /* Initialize wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_irq_start = me8200_di_io_irq_start;
+ subdevice->base.me_subdevice_io_irq_wait = me8200_di_io_irq_wait;
+ subdevice->base.me_subdevice_io_irq_stop = me8200_di_io_irq_stop;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me8200_di_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me8200_di_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me8200_di_io_single_read;
+ subdevice->base.me_subdevice_query_number_channels =
+ me8200_di_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me8200_di_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me8200_di_query_subdevice_caps;
+ subdevice->base.me_subdevice_destructor = me8200_di_destructor;
+
+ subdevice->rised = 0;
+ subdevice->count = 0;
+
+ /* Register interrupt service routine. */
+ subdevice->irq = irq;
+ if (subdevice->version > 0) { // NEW
+ err = request_irq(subdevice->irq, me8200_isr_EX,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME8200_NAME, (void *)subdevice);
+ } else { //OLD
+ err = request_irq(subdevice->irq, me8200_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME8200_NAME, (void *)subdevice);
+ }
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ PDEBUG("Registred irq=%d.\n", subdevice->irq);
+
+ return subdevice;
+}
+
+static void me8200_di_check_version(me8200_di_subdevice_t * instance,
+ unsigned long addr)
+{
+
+ PDEBUG("executed.\n");
+ instance->version = 0x000000FF & inb(addr);
+ PDEVELOP("me8200 firmware version: %d\n", instance->version);
+
+ /// @note Fix for wrong values in this registry.
+ if ((instance->version < 0x7) || (instance->version > 0x1F))
+ instance->version = 0x0;
+}
diff --git a/drivers/staging/meilhaus/me8200_di.h b/drivers/staging/meilhaus/me8200_di.h
new file mode 100644
index 000000000000..2a3b005b67d4
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_di.h
@@ -0,0 +1,92 @@
+/**
+ * @file me8200_di.h
+ *
+ * @brief ME-8200 digital input subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_DI_H_
+#define _ME8200_DI_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me8200_di_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock;
+ spinlock_t *irq_ctrl_lock;
+ spinlock_t *irq_mode_lock;
+
+ unsigned int di_idx;
+ unsigned int version;
+
+ int irq; /**< The number of the interrupt request. */
+ volatile int rised; /**< Flag to indicate if an interrupt occured. */
+ uint status_flag; /**< Default interupt status flag */
+ uint status_value; /**< Interupt status */
+ uint status_value_edges; /**< Extended interupt status */
+ uint line_value;
+ int count; /**< Counts the number of interrupts occured. */
+ uint8_t compare_value;
+ uint8_t filtering_flag;
+
+ wait_queue_head_t wait_queue; /**< To wait on interrupts. */
+
+ unsigned long port_reg; /**< The digital input port. */
+ unsigned long compare_reg; /**< The register to hold the value to compare with. */
+ unsigned long mask_reg; /**< The register to hold the mask. */
+ unsigned long irq_mode_reg; /**< The interrupt mode register. */
+ unsigned long irq_ctrl_reg; /**< The interrupt control register. */
+ unsigned long irq_status_reg; /**< The interrupt status register. Also interrupt reseting register (firmware version 7 and later).*/
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+ unsigned long firmware_version_reg; /**< The interrupt reseting register. */
+
+ unsigned long irq_status_low_reg; /**< The interrupt extended status register (low part). */
+ unsigned long irq_status_high_reg; /**< The interrupt extended status register (high part). */
+} me8200_di_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-8200 digital input subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_reg_base,
+ unsigned int di_idx,
+ int irq,
+ spinlock_t * irq_ctrl_lock,
+ spinlock_t * irq_mode_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_di_reg.h b/drivers/staging/meilhaus/me8200_di_reg.h
new file mode 100644
index 000000000000..b9a619d31c2c
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_di_reg.h
@@ -0,0 +1,75 @@
+/**
+ * @file me8200_di_reg.h
+ *
+ * @brief ME-8200 digital input subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_DI_REG_H_
+#define _ME8200_DI_REG_H_
+
+#ifdef __KERNEL__
+
+// Common registry for whole family.
+#define ME8200_DI_PORT_0_REG 0x3 // R
+#define ME8200_DI_PORT_1_REG 0x4 // R
+
+#define ME8200_DI_MASK_0_REG 0x5 // R/W
+#define ME8200_DI_MASK_1_REG 0x6 // R/W
+
+#define ME8200_DI_COMPARE_0_REG 0xA // R/W
+#define ME8200_DI_COMPARE_1_REG 0xB // R/W
+
+#define ME8200_DI_IRQ_CTRL_REG 0xC // R/W
+
+#ifndef ME8200_IRQ_MODE_REG
+# define ME8200_IRQ_MODE_REG 0xD // R/W
+#endif
+
+// This registry are for all versions
+#define ME8200_DI_CHANGE_0_REG 0xE // R
+#define ME8200_DI_CHANGE_1_REG 0xF // R
+
+#define ME8200_DI_IRQ_CTRL_BIT_CLEAR 0x4
+#define ME8200_DI_IRQ_CTRL_BIT_ENABLE 0x8
+
+// This registry are for firmware versions 7 and later
+#define ME8200_DI_EXTEND_CHANGE_0_LOW_REG 0x10 // R
+#define ME8200_DI_EXTEND_CHANGE_0_HIGH_REG 0x11 // R
+#define ME8200_DI_EXTEND_CHANGE_1_LOW_REG 0x12 // R
+#define ME8200_DI_EXTEND_CHANGE_1_HIGH_REG 0x13 // R
+
+#ifndef ME8200_FIRMWARE_VERSION_REG
+# define ME8200_FIRMWARE_VERSION_REG 0x14 // R
+#endif
+
+// Bit definitions
+#define ME8200_DI_IRQ_CTRL_MASK_EDGE 0x3
+#define ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING 0x0
+#define ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING 0x1
+#define ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY 0x3
+
+// Others
+#define ME8200_DI_IRQ_CTRL_SHIFT 4
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_dio.c b/drivers/staging/meilhaus/me8200_dio.c
new file mode 100644
index 000000000000..ff8ca1b8b7f3
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_dio.c
@@ -0,0 +1,418 @@
+/**
+ * @file me8200_dio.c
+ *
+ * @brief ME-8200 digital input/output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me8200_dio_reg.h"
+#include "me8200_dio.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me8200_dio_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me8200_dio_subdevice_t *instance;
+ uint8_t mode;
+
+ PDEBUG("executed.\n");
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ instance = (me8200_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inb(instance->ctrl_reg);
+ mode &= ~(0x3 << (instance->dio_idx * 2));
+ outb(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ spin_unlock(instance->ctrl_reg_lock);
+ outb(0x00, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0x00);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_dio_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me8200_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint32_t mode;
+ uint32_t size =
+ flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
+ | ME_IO_SINGLE_CONFIG_DIO_WORD |
+ ME_IO_SINGLE_CONFIG_DIO_DWORD);
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ mode = inb(instance->ctrl_reg);
+ switch (size) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ mode &=
+ ~((ME8200_DIO_CTRL_BIT_MODE_0 |
+ ME8200_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ mode &=
+ ~((ME8200_DIO_CTRL_BIT_MODE_0 |
+ ME8200_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+ mode |=
+ ME8200_DIO_CTRL_BIT_MODE_0 << (instance->
+ dio_idx * 2);
+ } else {
+ PERROR
+ ("Invalid port configuration specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid channel number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid flags.\n");
+
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (!err) {
+ outb(mode, instance->ctrl_reg);
+ PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->ctrl_reg - instance->reg_base, mode);
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_dio_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me8200_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 |
+ ME8200_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if ((mode ==
+ (ME8200_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value =
+ inb(instance->
+ port_reg) & (0x0001 << channel);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 |
+ ME8200_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if ((mode ==
+ (ME8200_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) || !mode) {
+ *value = inb(instance->port_reg) & 0x00FF;
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_dio_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me8200_dio_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t mode;
+ uint8_t byte;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_dio_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 |
+ ME8200_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME8200_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) {
+ byte = inb(instance->port_reg);
+
+ if (value)
+ byte |= 0x1 << channel;
+ else
+ byte &= ~(0x1 << channel);
+
+ outb(byte, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg -
+ instance->reg_base, byte);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ mode =
+ inb(instance->
+ ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 |
+ ME8200_DIO_CTRL_BIT_MODE_1) <<
+ (instance->dio_idx * 2));
+
+ if (mode ==
+ (ME8200_DIO_CTRL_BIT_MODE_0 <<
+ (instance->dio_idx * 2))) {
+ outb(value, instance->port_reg);
+ PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg -
+ instance->reg_base, value);
+ } else {
+ PERROR("Port not in output or input mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(instance->ctrl_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_dio_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_dio_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DIO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_dio_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_DIR_BYTE;
+ return ME_ERRNO_SUCCESS;
+}
+
+me8200_dio_subdevice_t *me8200_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock)
+{
+ me8200_dio_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me8200_dio_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me8200_dio_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save digital i/o index */
+ subdevice->dio_idx = dio_idx;
+
+ /* Save the subdevice index */
+ subdevice->ctrl_reg = reg_base + ME8200_DIO_CTRL_REG;
+ subdevice->port_reg = reg_base + ME8200_DIO_PORT_REG + dio_idx;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me8200_dio_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me8200_dio_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me8200_dio_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me8200_dio_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me8200_dio_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me8200_dio_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me8200_dio_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me8200_dio.h b/drivers/staging/meilhaus/me8200_dio.h
new file mode 100644
index 000000000000..9ddd93d26f15
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_dio.h
@@ -0,0 +1,68 @@
+/**
+ * @file me8200_dio.h
+ *
+ * @brief ME-8200 digital input/output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_DIO_H_
+#define _ME8200_DIO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me8200_dio_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+ unsigned int dio_idx; /**< The index of the digital i/o on the device. */
+
+ unsigned long port_reg; /**< Register holding the port status. */
+ unsigned long ctrl_reg; /**< Register to configure the port direction. */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me8200_dio_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-8200 digital input/ouput subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param dio_idx The index of the digital i/o port on the device.
+ * @param ctrl_reg_lock Spin lock protecting the control register.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me8200_dio_subdevice_t *me8200_dio_constructor(uint32_t reg_base,
+ unsigned int dio_idx,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_dio_reg.h b/drivers/staging/meilhaus/me8200_dio_reg.h
new file mode 100644
index 000000000000..ac94a133abaf
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_dio_reg.h
@@ -0,0 +1,43 @@
+/**
+ * @file me8200_dio_reg.h
+ *
+ * @brief ME-8200 digital input/output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_DIO_REG_H_
+#define _ME8200_DIO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME8200_DIO_CTRL_REG 0x7 // R/W
+#define ME8200_DIO_PORT_0_REG 0x8 // R/W
+#define ME8200_DIO_PORT_1_REG 0x9 // R/W
+#define ME8200_DIO_PORT_REG ME8200_DIO_PORT_0_REG // R/W
+
+#define ME8200_DIO_CTRL_BIT_MODE_0 0x01
+#define ME8200_DIO_CTRL_BIT_MODE_1 0x02
+#define ME8200_DIO_CTRL_BIT_MODE_2 0x04
+#define ME8200_DIO_CTRL_BIT_MODE_3 0x08
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_do.c b/drivers/staging/meilhaus/me8200_do.c
new file mode 100644
index 000000000000..d2bebd16ff41
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_do.c
@@ -0,0 +1,600 @@
+/**
+ * @file me8200_do.c
+ *
+ * @brief ME-8200 digital output subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "meids.h"
+#include "medebug.h"
+#include "me8200_reg.h"
+#include "me8200_do_reg.h"
+#include "me8200_do.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static int me8200_do_io_irq_start(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ me8200_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t tmp;
+ unsigned long status;
+
+ if (flags & ~ME_IO_IRQ_START_DIO_BYTE) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel != 0) {
+ PERROR("Invalid channel specified.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ if (irq_source != ME_IRQ_SOURCE_DIO_OVER_TEMP) {
+ PERROR("Invalid interrupt source specified.\n");
+ return ME_ERRNO_INVALID_IRQ_SOURCE;
+ }
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, status);
+ spin_lock(instance->irq_mode_lock);
+ tmp = inb(instance->irq_ctrl_reg);
+ tmp |=
+ ME8200_IRQ_MODE_BIT_ENABLE_POWER << (ME8200_IRQ_MODE_POWER_SHIFT *
+ instance->do_idx);
+ outb(tmp, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->irq_mode_lock);
+ instance->rised = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_do_io_irq_wait(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ me8200_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ long t = 0;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (time_out < 0) {
+ PERROR("Invalid time_out specified.\n");
+ return ME_ERRNO_INVALID_TIMEOUT;
+ }
+
+ if (time_out) {
+ t = (time_out * HZ) / 1000;
+
+ if (t == 0)
+ t = 1;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ if (instance->rised <= 0) {
+ instance->rised = 0;
+
+ if (time_out) {
+ t = wait_event_interruptible_timeout(instance->
+ wait_queue,
+ (instance->rised !=
+ 0), t);
+
+ if (t == 0) {
+ PERROR
+ ("Wait on external interrupt timed out.\n");
+ err = ME_ERRNO_TIMEOUT;
+ }
+ } else {
+ wait_event_interruptible(instance->wait_queue,
+ (instance->rised != 0));
+ }
+
+ if (instance->rised < 0) {
+ PERROR("Wait on interrupt aborted by user.\n");
+ err = ME_ERRNO_CANCELLED;
+ }
+ }
+
+ if (signal_pending(current)) {
+ PERROR("Wait on external interrupt aborted by signal.\n");
+ err = ME_ERRNO_SIGNAL;
+ }
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ instance->rised = 0;
+ *irq_count = instance->count;
+ *value = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_do_io_irq_stop(me_subdevice_t * subdevice,
+ struct file *filep, int channel, int flags)
+{
+ me8200_do_subdevice_t *instance;
+ uint8_t tmp;
+ unsigned long cpu_flags;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ spin_lock(instance->irq_mode_lock);
+ tmp = inb(instance->irq_ctrl_reg);
+ tmp &=
+ ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER <<
+ (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx));
+ outb(tmp, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->irq_mode_lock);
+ instance->rised = -1;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_do_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me8200_do_subdevice_t *instance;
+ unsigned long cpu_flags;
+ uint8_t tmp;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
+ outb(0x00, instance->port_reg);
+ PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->port_reg - instance->reg_base, 0x00);
+ spin_lock(instance->irq_mode_lock);
+ tmp = inb(instance->irq_ctrl_reg);
+ tmp &=
+ ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER <<
+ (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx));
+ outb(tmp, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, tmp);
+ spin_unlock(instance->irq_mode_lock);
+ instance->rised = -1;
+ instance->count = 0;
+ spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_do_io_single_config(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me8200_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, status);
+ switch (flags) {
+ case ME_IO_SINGLE_CONFIG_NO_FLAGS:
+ case ME_IO_SINGLE_CONFIG_DIO_BYTE:
+ if (channel == 0) {
+ if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ } else {
+ PERROR("Invalid byte direction specified.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_do_io_single_read(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me8200_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, status);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = inb(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inb(instance->port_reg);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_do_io_single_write(me_subdevice_t * subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me8200_do_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+ uint8_t state;
+ unsigned long status;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock_irqsave(&instance->subdevice_lock, status);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ state = inb(instance->port_reg);
+ state =
+ value ? (state | (0x1 << channel)) : (state &
+ ~(0x1 <<
+ channel));
+ outb(state, instance->port_reg);
+ PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg - instance->reg_base,
+ state);
+ } else {
+ PERROR("Invalid bit number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ outb(value, instance->port_reg);
+ PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n",
+ instance->reg_base,
+ instance->port_reg - instance->reg_base,
+ value);
+ } else {
+ PERROR("Invalid byte number specified.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock_irqrestore(&instance->subdevice_lock, status);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8200_do_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 8;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_do_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8200_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_OVER_TEMP_IRQ;
+ return ME_ERRNO_SUCCESS;
+}
+
+static void me8200_do_destructor(struct me_subdevice *subdevice)
+{
+ me8200_do_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8200_do_subdevice_t *) subdevice;
+
+ free_irq(instance->irq, (void *)instance);
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+static irqreturn_t me8200_do_isr(int irq, void *dev_id)
+#else
+static irqreturn_t me8200_do_isr(int irq, void *dev_id, struct pt_regs *regs)
+#endif
+{
+ me8200_do_subdevice_t *instance;
+ uint16_t ctrl;
+ uint8_t irq_status;
+
+ instance = (me8200_do_subdevice_t *) dev_id;
+
+ if (irq != instance->irq) {
+ PERROR("Incorrect interrupt num: %d.\n", irq);
+ return IRQ_NONE;
+ }
+
+ irq_status = inb(instance->irq_status_reg);
+ if (!
+ (irq_status &
+ (ME8200_DO_IRQ_STATUS_BIT_ACTIVE << instance->do_idx))) {
+ PINFO
+ ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
+ jiffies, __func__, instance->do_idx, irq_status);
+ return IRQ_NONE;
+ }
+
+ PDEBUG("executed.\n");
+
+ spin_lock(&instance->subdevice_lock);
+ instance->rised = 1;
+ instance->count++;
+
+ spin_lock(instance->irq_mode_lock);
+ ctrl = inw(instance->irq_ctrl_reg);
+ ctrl |= ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx;
+ outw(ctrl, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, ctrl);
+ ctrl &= ~(ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx);
+ outw(ctrl, instance->irq_ctrl_reg);
+ PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
+ instance->irq_ctrl_reg - instance->reg_base, ctrl);
+ spin_unlock(instance->irq_mode_lock);
+ spin_unlock(&instance->subdevice_lock);
+ wake_up_interruptible_all(&instance->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base,
+ unsigned int do_idx,
+ int irq,
+ spinlock_t * irq_mode_lock)
+{
+ me8200_do_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me8200_do_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me8200_do_subdevice_t));
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->irq_mode_lock = irq_mode_lock;
+
+ /* Save the index of the digital output */
+ subdevice->do_idx = do_idx;
+ subdevice->irq = irq;
+
+ /* Initialize the registers */
+ if (do_idx == 0) {
+ subdevice->port_reg = reg_base + ME8200_DO_PORT_0_REG;
+ } else if (do_idx == 1) {
+ subdevice->port_reg = reg_base + ME8200_DO_PORT_1_REG;
+ } else {
+ PERROR("Wrong subdevice idx=%d.\n", do_idx);
+ kfree(subdevice);
+ return NULL;
+ }
+ subdevice->irq_ctrl_reg = reg_base + ME8200_IRQ_MODE_REG;
+ subdevice->irq_status_reg = reg_base + ME8200_DO_IRQ_STATUS_REG;
+#ifdef MEDEBUG_DEBUG_REG
+ subdevice->reg_base = reg_base;
+#endif
+
+ /* Initialize the wait queue */
+ init_waitqueue_head(&subdevice->wait_queue);
+
+ /* Request the interrupt line */
+ err = request_irq(irq, me8200_do_isr,
+#ifdef IRQF_DISABLED
+ IRQF_DISABLED | IRQF_SHARED,
+#else
+ SA_INTERRUPT | SA_SHIRQ,
+#endif
+ ME8200_NAME, (void *)subdevice);
+
+ if (err) {
+ PERROR("Cannot get interrupt line.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ PINFO("Registered irq=%d.\n", irq);
+
+ /* Overload base class methods. */
+ subdevice->base.me_subdevice_io_irq_start = me8200_do_io_irq_start;
+ subdevice->base.me_subdevice_io_irq_wait = me8200_do_io_irq_wait;
+ subdevice->base.me_subdevice_io_irq_stop = me8200_do_io_irq_stop;
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me8200_do_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config =
+ me8200_do_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me8200_do_io_single_read;
+ subdevice->base.me_subdevice_io_single_write =
+ me8200_do_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me8200_do_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me8200_do_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me8200_do_query_subdevice_caps;
+ subdevice->base.me_subdevice_destructor = me8200_do_destructor;
+
+ subdevice->rised = 0;
+ subdevice->count = 0;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me8200_do.h b/drivers/staging/meilhaus/me8200_do.h
new file mode 100644
index 000000000000..27581251c847
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_do.h
@@ -0,0 +1,75 @@
+/**
+ * @file me8200_do.h
+ *
+ * @brief ME-8200 digital output subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_DO_H_
+#define _ME8200_DO_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The template subdevice class.
+ */
+typedef struct me8200_do_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *irq_mode_lock;
+
+ int irq; /**< The number of the interrupt request */
+ int rised; /**< Flag to indicate if an interrupt occured */
+ int count; /**< Counts the number of interrupts occured */
+ wait_queue_head_t wait_queue; /**< To wait on interrupts */
+
+ unsigned int do_idx; /**< The number of the digital output */
+
+ unsigned long port_reg; /**< The digital output port */
+ unsigned long irq_ctrl_reg; /**< The interrupt control register */
+ unsigned long irq_status_reg; /**< The interrupt status register */
+#ifdef MEDEBUG_DEBUG_REG
+ unsigned long reg_base;
+#endif
+} me8200_do_subdevice_t;
+
+/**
+ * @brief The constructor to generate a ME-8200 digital output subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param do_idx The index of the digital output subdevice on this device.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base,
+ unsigned int do_idx,
+ int irq,
+ spinlock_t * irq_mode_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_do_reg.h b/drivers/staging/meilhaus/me8200_do_reg.h
new file mode 100644
index 000000000000..41095046037a
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_do_reg.h
@@ -0,0 +1,40 @@
+/**
+ * @file me8200_ao_reg.h
+ *
+ * @brief ME-8200 analog output subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_DO_REG_H_
+#define _ME8200_DO_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME8200_DO_IRQ_STATUS_REG 0x0 // R
+#define ME8200_DO_PORT_0_REG 0x1 // R/W
+#define ME8200_DO_PORT_1_REG 0x2 // R/W
+
+#define ME8200_DO_IRQ_STATUS_BIT_ACTIVE 0x1
+#define ME8200_DO_IRQ_STATUS_SHIFT 1
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8200_reg.h b/drivers/staging/meilhaus/me8200_reg.h
new file mode 100644
index 000000000000..a73fe4d5b0ff
--- /dev/null
+++ b/drivers/staging/meilhaus/me8200_reg.h
@@ -0,0 +1,46 @@
+/**
+ * @file me8200_reg.h
+ *
+ * @brief ME-8200 register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8200_REG_H_
+#define _ME8200_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME8200_IRQ_MODE_REG 0xD // R/W
+
+#define ME8200_IRQ_MODE_MASK 0x3
+
+#define ME8200_IRQ_MODE_MASK_MASK 0x0
+#define ME8200_IRQ_MODE_MASK_COMPARE 0x1
+
+#define ME8200_IRQ_MODE_BIT_ENABLE_POWER 0x10
+#define ME8200_IRQ_MODE_BIT_CLEAR_POWER 0x40
+
+#define ME8200_IRQ_MODE_DI_SHIFT 2
+#define ME8200_IRQ_MODE_POWER_SHIFT 1
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8254.c b/drivers/staging/meilhaus/me8254.c
new file mode 100644
index 000000000000..6e44c3d7a0c7
--- /dev/null
+++ b/drivers/staging/meilhaus/me8254.c
@@ -0,0 +1,1176 @@
+/**
+ * @file me8254.c
+ *
+ * @brief 8254 subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "me8254_reg.h"
+#include "me8254.h"
+
+/*
+ * Defines
+ */
+#define ME8254_NUMBER_CHANNELS 1 /**< One channel per counter. */
+#define ME8254_CTR_WIDTH 16 /**< One counter has 16 bits. */
+
+/*
+ * Functions
+ */
+
+static int me8254_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me8254_subdevice_t *instance;
+ uint8_t clk_src;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8254_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ if (instance->ctr_idx == 0)
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ else if (instance->ctr_idx == 1)
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ else
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outb(0x00, instance->val_reg);
+ outb(0x00, instance->val_reg);
+
+ spin_lock(instance->clk_src_reg_lock);
+ clk_src = inb(instance->clk_src_reg);
+
+ switch (instance->device_id) {
+ case PCI_DEVICE_ID_MEILHAUS_ME1400:
+ case PCI_DEVICE_ID_MEILHAUS_ME140A:
+ case PCI_DEVICE_ID_MEILHAUS_ME140B:
+ case PCI_DEVICE_ID_MEILHAUS_ME14E0:
+ case PCI_DEVICE_ID_MEILHAUS_ME14EA:
+ case PCI_DEVICE_ID_MEILHAUS_ME14EB:
+ if (instance->me8254_idx == 0) {
+ if (instance->ctr_idx == 0)
+ clk_src &=
+ ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ |
+ ME1400AB_8254_A_0_CLK_SRC_QUARZ);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV);
+ else
+ clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV);
+ } else {
+ if (instance->ctr_idx == 0)
+ clk_src &=
+ ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ |
+ ME1400AB_8254_B_0_CLK_SRC_QUARZ);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV);
+ else
+ clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV);
+ }
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ switch (instance->me8254_idx) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ if (instance->ctr_idx == 0)
+ clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK);
+ else
+ clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK);
+ break;
+
+ default:
+ if (instance->ctr_idx == 0)
+ clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK);
+ else
+ clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK);
+ break;
+ }
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4610:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
+
+ /* No clock source register available */
+ break;
+
+ default:
+ PERROR("Invalid device type.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ if (!err)
+ outb(clk_src, instance->clk_src_reg);
+
+ spin_unlock(instance->clk_src_reg_lock);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me1400_ab_ref_config(me8254_subdevice_t * instance, int ref)
+{
+ uint8_t clk_src;
+
+ spin_lock(instance->clk_src_reg_lock);
+ clk_src = inb(instance->clk_src_reg);
+
+ switch (ref) {
+ case ME_REF_CTR_EXTERNAL:
+ if (instance->me8254_idx == 0) {
+ if (instance->ctr_idx == 0)
+ clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_QUARZ);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV);
+ else
+ clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV);
+ } else {
+ if (instance->ctr_idx == 0)
+ clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_QUARZ);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV);
+ else
+ clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV);
+ }
+
+ break;
+
+ case ME_REF_CTR_PREVIOUS:
+ if (instance->me8254_idx == 0) {
+ if (instance->ctr_idx == 0) {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ } else if (instance->ctr_idx == 1)
+ clk_src |= (ME1400AB_8254_A_1_CLK_SRC_PREV);
+ else
+ clk_src |= (ME1400AB_8254_A_2_CLK_SRC_PREV);
+ } else {
+ if (instance->ctr_idx == 0) {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ } else if (instance->ctr_idx == 1)
+ clk_src |= (ME1400AB_8254_B_1_CLK_SRC_PREV);
+ else
+ clk_src |= (ME1400AB_8254_B_2_CLK_SRC_PREV);
+ }
+
+ break;
+
+ case ME_REF_CTR_INTERNAL_1MHZ:
+ if (instance->me8254_idx == 0) {
+ if (instance->ctr_idx == 0) {
+ clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ);
+ clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ if (instance->ctr_idx == 0) {
+ clk_src |= (ME1400AB_8254_B_0_CLK_SRC_QUARZ);
+ clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ }
+
+ break;
+
+ case ME_REF_CTR_INTERNAL_10MHZ:
+ if (instance->me8254_idx == 0) {
+ if (instance->ctr_idx == 0) {
+ clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ);
+ clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ if (instance->ctr_idx == 0) {
+ clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ);
+ clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ outb(clk_src, instance->clk_src_reg);
+ spin_unlock(instance->clk_src_reg_lock);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me1400_cd_ref_config(me8254_subdevice_t * instance, int ref)
+{
+ uint8_t clk_src;
+
+ spin_lock(instance->clk_src_reg_lock);
+ clk_src = inb(instance->clk_src_reg);
+
+ switch (ref) {
+ case ME_REF_CTR_EXTERNAL:
+ switch (instance->me8254_idx) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ if (instance->ctr_idx == 0)
+ clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK);
+ else
+ clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK);
+ break;
+
+ default:
+ if (instance->ctr_idx == 0)
+ clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
+ else if (instance->ctr_idx == 1)
+ clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK);
+ else
+ clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK);
+ break;
+ }
+ break;
+
+ case ME_REF_CTR_PREVIOUS:
+ switch (instance->me8254_idx) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ if (instance->ctr_idx == 0) {
+ clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_PREV);
+ } else if (instance->ctr_idx == 1) {
+ clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_ACE_1_CLK_SRC_PREV);
+ } else {
+ clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_ACE_2_CLK_SRC_PREV);
+ }
+ break;
+
+ default:
+ if (instance->ctr_idx == 0) {
+ clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_PREV);
+ } else if (instance->ctr_idx == 1) {
+ clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_BD_1_CLK_SRC_PREV);
+ } else {
+ clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_BD_2_CLK_SRC_PREV);
+ }
+ break;
+ }
+
+ break;
+
+ case ME_REF_CTR_INTERNAL_1MHZ:
+ switch (instance->me8254_idx) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ if (instance->ctr_idx == 0) {
+ clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_1MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ break;
+
+ default:
+ if (instance->ctr_idx == 0) {
+ clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_1MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+ break;
+ }
+
+ break;
+
+ case ME_REF_CTR_INTERNAL_10MHZ:
+ switch (instance->me8254_idx) {
+ case 0:
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ if (instance->ctr_idx == 0) {
+ clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_10MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+ break;
+
+ default:
+ if (instance->ctr_idx == 0) {
+ clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK);
+ clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_10MHZ);
+ } else {
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ break;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid reference.\n");
+ spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ outb(clk_src, instance->clk_src_reg);
+ spin_unlock(instance->clk_src_reg_lock);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me4600_ref_config(me8254_subdevice_t * instance, int ref)
+{
+ switch (ref) {
+
+ case ME_REF_CTR_EXTERNAL:
+ // Nothing to do
+ break;
+
+ default:
+ PERROR("Invalid reference.\n");
+// spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8100_ref_config(me8254_subdevice_t * instance, int ref)
+{
+ switch (ref) {
+
+ case ME_REF_CTR_EXTERNAL:
+ // Nothing to do
+ break;
+
+ default:
+ PERROR("Invalid reference.\n");
+// spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_REF;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8254_io_single_config(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me8254_subdevice_t *instance;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ if (channel) {
+ PERROR("Invalid channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ instance = (me8254_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ // Configure the counter modes
+ if (instance->ctr_idx == 0) {
+ if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) {
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) {
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M1 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) {
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M2 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) {
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M3 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) {
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M4 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) {
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M5 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else {
+ PERROR("Invalid single configuration.\n");
+ spin_unlock(&instance->subdevice_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else if (instance->ctr_idx == 1) {
+ if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) {
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) {
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M1 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) {
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M2 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) {
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M3 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) {
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M4 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) {
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M5 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else {
+ PERROR("Invalid single configuration.\n");
+ spin_unlock(&instance->subdevice_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ } else {
+ if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) {
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) {
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M1 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) {
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M2 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) {
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M3 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) {
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M4 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) {
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M5 |
+ ME8254_CTRL_BIN, instance->ctrl_reg);
+ } else {
+ PERROR("Invalid single configuration.\n");
+ spin_unlock(&instance->subdevice_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ }
+
+ switch (instance->device_id) {
+ case PCI_DEVICE_ID_MEILHAUS_ME1400:
+ case PCI_DEVICE_ID_MEILHAUS_ME14E0:
+ case PCI_DEVICE_ID_MEILHAUS_ME140A:
+ case PCI_DEVICE_ID_MEILHAUS_ME14EA:
+ case PCI_DEVICE_ID_MEILHAUS_ME140B:
+ case PCI_DEVICE_ID_MEILHAUS_ME14EB:
+ err = me1400_ab_ref_config(instance, ref);
+
+ if (err) {
+ spin_unlock(&instance->subdevice_lock);
+ return err;
+ }
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ err = me1400_cd_ref_config(instance, ref);
+
+ if (err) {
+ spin_unlock(&instance->subdevice_lock);
+ return err;
+ }
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4610:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
+ err = me4600_ref_config(instance, ref);
+
+ if (err) {
+ spin_unlock(&instance->subdevice_lock);
+ return err;
+ }
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
+ err = me8100_ref_config(instance, ref);
+
+ if (err) {
+ spin_unlock(&instance->subdevice_lock);
+ return err;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid device type.\n");
+
+ spin_unlock(&instance->subdevice_lock);
+// spin_unlock(instance->clk_src_reg_lock);
+ return ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8254_io_single_read(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me8254_subdevice_t *instance;
+ uint16_t lo_byte;
+ uint16_t hi_byte;
+
+ PDEBUG("executed.\n");
+
+ if (channel) {
+ PERROR("Invalid channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ instance = (me8254_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ if (instance->ctr_idx == 0)
+ outb(ME8254_CTRL_SC0 | ME8254_CTRL_TLO, instance->ctrl_reg);
+ else if (instance->ctr_idx == 1)
+ outb(ME8254_CTRL_SC1 | ME8254_CTRL_TLO, instance->ctrl_reg);
+ else
+ outb(ME8254_CTRL_SC2 | ME8254_CTRL_TLO, instance->ctrl_reg);
+
+ lo_byte = inb(instance->val_reg);
+ hi_byte = inb(instance->val_reg);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ *value = lo_byte | (hi_byte << 8);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8254_io_single_write(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me8254_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ if (channel) {
+ PERROR("Invalid channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ instance = (me8254_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ outb(value, instance->val_reg);
+ outb((value >> 8), instance->val_reg);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8254_query_number_channels(struct me_subdevice *subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = ME8254_NUMBER_CHANNELS;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8254_query_subdevice_type(struct me_subdevice *subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_CTR;
+ *subtype = ME_SUBTYPE_CTR_8254;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8254_query_subdevice_caps(struct me_subdevice *subdevice,
+ int *caps)
+{
+ me8254_subdevice_t *instance;
+ PDEBUG("executed.\n");
+ instance = (me8254_subdevice_t *) subdevice;
+ *caps = instance->caps;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8254_query_subdevice_caps_args(struct me_subdevice *subdevice,
+ int cap, int *args, int count)
+{
+ PDEBUG("executed.\n");
+
+ if (count != 1) {
+ PERROR("Invalid capability argument count.\n");
+ return ME_ERRNO_INVALID_CAP_ARG_COUNT;
+ }
+
+ if (cap == ME_CAP_CTR_WIDTH) {
+ args[0] = ME8254_CTR_WIDTH;
+ } else {
+ PERROR("Invalid capability.\n");
+ return ME_ERRNO_INVALID_CAP;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static uint32_t me1400AB_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ switch (me8254_idx) {
+
+ case 0:
+ return (reg_base + ME1400AB_8254_A_0_VAL_REG + ctr_idx);
+
+ default:
+ return (reg_base + ME1400AB_8254_B_0_VAL_REG + ctr_idx);
+ }
+
+ return 0;
+}
+
+static uint32_t me1400AB_get_ctrl_reg(uint32_t reg_base,
+ unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ switch (me8254_idx) {
+ case 0:
+ return (reg_base + ME1400AB_8254_A_CTRL_REG);
+
+ default:
+ return (reg_base + ME1400AB_8254_B_CTRL_REG);
+ }
+
+ return 0;
+}
+
+static uint32_t me1400AB_get_clk_src_reg(uint32_t reg_base,
+ unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ switch (me8254_idx) {
+ case 0:
+ return (reg_base + ME1400AB_CLK_SRC_REG);
+
+ default:
+ return (reg_base + ME1400AB_CLK_SRC_REG);
+ }
+
+ return 0;
+}
+
+static uint32_t me1400CD_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ switch (me8254_idx) {
+ case 0:
+ return (reg_base + ME1400C_8254_A_0_VAL_REG + ctr_idx);
+
+ case 1:
+ return (reg_base + ME1400C_8254_B_0_VAL_REG + ctr_idx);
+
+ case 2:
+ return (reg_base + ME1400C_8254_C_0_VAL_REG + ctr_idx);
+
+ case 3:
+ return (reg_base + ME1400C_8254_D_0_VAL_REG + ctr_idx);
+
+ case 4:
+ return (reg_base + ME1400C_8254_E_0_VAL_REG + ctr_idx);
+
+ case 5:
+ return (reg_base + ME1400D_8254_A_0_VAL_REG + ctr_idx);
+
+ case 6:
+ return (reg_base + ME1400D_8254_B_0_VAL_REG + ctr_idx);
+
+ case 7:
+ return (reg_base + ME1400D_8254_C_0_VAL_REG + ctr_idx);
+
+ case 8:
+ return (reg_base + ME1400D_8254_D_0_VAL_REG + ctr_idx);
+
+ default:
+ return (reg_base + ME1400D_8254_E_0_VAL_REG + ctr_idx);
+ }
+
+ return 0;
+}
+
+static uint32_t me1400CD_get_ctrl_reg(uint32_t reg_base,
+ unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ switch (me8254_idx) {
+ case 0:
+ return (reg_base + ME1400C_8254_A_CTRL_REG);
+
+ case 1:
+ return (reg_base + ME1400C_8254_B_CTRL_REG);
+
+ case 2:
+ return (reg_base + ME1400C_8254_C_CTRL_REG);
+
+ case 3:
+ return (reg_base + ME1400C_8254_D_CTRL_REG);
+
+ case 4:
+ return (reg_base + ME1400C_8254_E_CTRL_REG);
+
+ case 5:
+ return (reg_base + ME1400D_8254_A_CTRL_REG);
+
+ case 6:
+ return (reg_base + ME1400D_8254_B_CTRL_REG);
+
+ case 7:
+ return (reg_base + ME1400D_8254_C_CTRL_REG);
+
+ case 8:
+ return (reg_base + ME1400D_8254_D_CTRL_REG);
+
+ default:
+ return (reg_base + ME1400D_8254_E_CTRL_REG);
+ }
+
+ return 0;
+}
+
+static uint32_t me1400CD_get_clk_src_reg(uint32_t reg_base,
+ unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ switch (me8254_idx) {
+ case 0:
+ return (reg_base + ME1400C_CLK_SRC_0_REG);
+
+ case 1:
+ return (reg_base + ME1400C_CLK_SRC_0_REG);
+
+ case 2:
+ return (reg_base + ME1400C_CLK_SRC_1_REG);
+
+ case 3:
+ return (reg_base + ME1400C_CLK_SRC_1_REG);
+
+ case 4:
+ return (reg_base + ME1400C_CLK_SRC_2_REG);
+
+ case 5:
+ return (reg_base + ME1400D_CLK_SRC_0_REG);
+
+ case 6:
+ return (reg_base + ME1400D_CLK_SRC_0_REG);
+
+ case 7:
+ return (reg_base + ME1400D_CLK_SRC_1_REG);
+
+ case 8:
+ return (reg_base + ME1400D_CLK_SRC_1_REG);
+
+ default:
+ return (reg_base + ME1400D_CLK_SRC_2_REG);
+ }
+
+ return 0;
+}
+
+static uint32_t me4600_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ return (reg_base + ME4600_8254_0_VAL_REG + ctr_idx);
+}
+
+static uint32_t me4600_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ return (reg_base + ME4600_8254_CTRL_REG);
+}
+
+static uint32_t me8100_get_val_reg(uint32_t reg_base, unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ return (reg_base + ME8100_COUNTER_REG_0 + ctr_idx * 2);
+}
+
+static uint32_t me8100_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx,
+ unsigned int ctr_idx)
+{
+ return (reg_base + ME8100_COUNTER_CTRL_REG);
+}
+
+me8254_subdevice_t *me8254_constructor(uint32_t device_id,
+ uint32_t reg_base,
+ unsigned int me8254_idx,
+ unsigned int ctr_idx,
+ spinlock_t * ctrl_reg_lock,
+ spinlock_t * clk_src_reg_lock)
+{
+ me8254_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ // Allocate memory for subdevice instance
+ subdevice = kmalloc(sizeof(me8254_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for 8254 instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me8254_subdevice_t));
+
+ // Check if counter index is out of range
+
+ if (ctr_idx > 2) {
+ PERROR("Counter index is out of range.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize subdevice base class
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+ subdevice->clk_src_reg_lock = clk_src_reg_lock;
+
+ // Save type of Meilhaus device
+ subdevice->device_id = device_id;
+
+ // Save the indices
+ subdevice->me8254_idx = me8254_idx;
+ subdevice->ctr_idx = ctr_idx;
+
+ // Do device specific initialization
+ switch (device_id) {
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140A:
+ case PCI_DEVICE_ID_MEILHAUS_ME14EA:
+ // Check if 8254 index is out of range
+ if (me8254_idx > 0) {
+ PERROR("8254 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140B: // Fall through
+ case PCI_DEVICE_ID_MEILHAUS_ME14EB:
+ // Check if 8254 index is out of range
+ if (me8254_idx > 1) {
+ PERROR("8254 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize the counters capabilities
+ if (ctr_idx == 0)
+ subdevice->caps =
+ ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
+ ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
+ ME_CAPS_CTR_CLK_EXTERNAL;
+ else
+ subdevice->caps =
+ ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL;
+
+ // Get the counters registers
+ subdevice->val_reg =
+ me1400AB_get_val_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->ctrl_reg =
+ me1400AB_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->clk_src_reg =
+ me1400AB_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ // Check if 8254 index is out of range
+ if (me8254_idx > 4) {
+ PERROR("8254 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ // Check if 8254 index is out of range
+ if (me8254_idx > 9) {
+ PERROR("8254 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize the counters capabilities
+ if (ctr_idx == 0) {
+ if (me8254_idx == 0)
+ subdevice->caps =
+ ME_CAPS_CTR_CLK_PREVIOUS |
+ ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
+ ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
+ ME_CAPS_CTR_CLK_EXTERNAL;
+ else
+ subdevice->caps =
+ ME_CAPS_CTR_CLK_INTERNAL_1MHZ |
+ ME_CAPS_CTR_CLK_INTERNAL_10MHZ |
+ ME_CAPS_CTR_CLK_EXTERNAL;
+ } else
+ subdevice->caps =
+ ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL;
+
+ // Get the counters registers
+ subdevice->val_reg =
+ me1400CD_get_val_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->ctrl_reg =
+ me1400CD_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->clk_src_reg =
+ me1400CD_get_clk_src_reg(reg_base, me8254_idx, ctr_idx);
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4610:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680I:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680S:
+ case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
+ // Check if 8254 index is out of range
+ if (me8254_idx > 0) {
+ PERROR("8254 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize the counters capabilities
+ subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;
+
+ // Get the counters registers
+ subdevice->val_reg =
+ me4600_get_val_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->ctrl_reg =
+ me4600_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->clk_src_reg = 0; // Not used
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
+ // Check if 8254 index is out of range
+ if (me8254_idx > 0) {
+ PERROR("8254 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize the counters capabilities
+ subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL;
+
+ // Get the counters registers
+ subdevice->val_reg =
+ me8100_get_val_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->ctrl_reg =
+ me8100_get_ctrl_reg(reg_base, me8254_idx, ctr_idx);
+ subdevice->clk_src_reg = 0; // Not used
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4650:
+ case PCI_DEVICE_ID_MEILHAUS_ME1400:
+ case PCI_DEVICE_ID_MEILHAUS_ME14E0:
+ PERROR("No 8254 subdevices available for subdevice device.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+
+ default:
+ PERROR("Unknown device type.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ // Overload subdevice base class methods.
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me8254_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config = me8254_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me8254_io_single_read;
+ subdevice->base.me_subdevice_io_single_write = me8254_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me8254_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me8254_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me8254_query_subdevice_caps;
+ subdevice->base.me_subdevice_query_subdevice_caps_args =
+ me8254_query_subdevice_caps_args;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me8254.h b/drivers/staging/meilhaus/me8254.h
new file mode 100644
index 000000000000..572b7196d5a8
--- /dev/null
+++ b/drivers/staging/meilhaus/me8254.h
@@ -0,0 +1,80 @@
+/**
+ * @file me8254.h
+ *
+ * @brief 8254 counter implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ME8254_H_
+#define _ME8254_H_
+
+#include "mesubdevice.h"
+#include "meslock.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The 8254 subdevice class.
+ */
+typedef struct me8254_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect the control register from concurrent access. */
+ spinlock_t *clk_src_reg_lock; /**< Spin lock to protect the clock source register from concurrent access. */
+
+ uint32_t device_id; /**< The Meilhaus device type carrying the 8254 chip. */
+ int me8254_idx; /**< The index of the 8254 chip on the device. */
+ int ctr_idx; /**< The index of the counter on the 8254 chip. */
+
+ int caps; /**< Holds the device capabilities. */
+
+ unsigned long val_reg; /**< Holds the actual counter value. */
+ unsigned long ctrl_reg; /**< Register to configure the 8254 modes. */
+ unsigned long clk_src_reg; /**< Register to configure the counter connections. */
+} me8254_subdevice_t;
+
+/**
+ * @brief The constructor to generate a 8254 instance.
+ *
+ * @param device_id The kind of Meilhaus device holding the 8254.
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param me8254_idx The index of the 8254 chip on the Meilhaus device.
+ * @param ctr_idx The index of the counter inside a 8254 chip.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the 8254 control register from concurrent access.
+ * @param clk_src_reg_lock Pointer to spin lock protecting the clock source register from concurrent access.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me8254_subdevice_t *me8254_constructor(uint32_t device_id,
+ uint32_t reg_base,
+ unsigned int me8254_idx,
+ unsigned int ctr_idx,
+ spinlock_t * ctrl_reg_lock,
+ spinlock_t * clk_src_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8254_reg.h b/drivers/staging/meilhaus/me8254_reg.h
new file mode 100644
index 000000000000..7e2c36b46f56
--- /dev/null
+++ b/drivers/staging/meilhaus/me8254_reg.h
@@ -0,0 +1,172 @@
+/**
+ * @file me8254_reg.h
+ *
+ * @brief 8254 counter register definitions.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME8254_REG_H_
+#define _ME8254_REG_H_
+
+#ifdef __KERNEL__
+
+/* ME1400 A/B register offsets */
+#define ME1400AB_8254_A_0_VAL_REG 0x0004 /**< Offset of 8254 A counter 0 value register. */
+#define ME1400AB_8254_A_1_VAL_REG 0x0005 /**< Offset of 8254 A counter 1 value register. */
+#define ME1400AB_8254_A_2_VAL_REG 0x0006 /**< Offset of 8254 A counter 2 value register. */
+#define ME1400AB_8254_A_CTRL_REG 0x0007 /**< Offset of 8254 A control register. */
+
+#define ME1400AB_8254_B_0_VAL_REG 0x000C /**< Offset of 8254 B counter 0 value register. */
+#define ME1400AB_8254_B_1_VAL_REG 0x000D /**< Offset of 8254 B counter 1 value register. */
+#define ME1400AB_8254_B_2_VAL_REG 0x000E /**< Offset of 8254 B counter 2 value register. */
+#define ME1400AB_8254_B_CTRL_REG 0x000F /**< Offset of 8254 B control register. */
+
+#define ME1400AB_CLK_SRC_REG 0x0010 /**< Offset of clock source register. */
+
+/* ME1400 C register offsets */
+#define ME1400C_8254_A_0_VAL_REG 0x0004 /**< Offset of 8254 A counter 0 value register. */
+#define ME1400C_8254_A_1_VAL_REG 0x0005 /**< Offset of 8254 A counter 0 value register. */
+#define ME1400C_8254_A_2_VAL_REG 0x0006 /**< Offset of 8254 A counter 0 value register. */
+#define ME1400C_8254_A_CTRL_REG 0x0007 /**< Offset of 8254 A control register. */
+
+#define ME1400C_8254_B_0_VAL_REG 0x000C /**< Offset of 8254 B counter 0 value register. */
+#define ME1400C_8254_B_1_VAL_REG 0x000D /**< Offset of 8254 B counter 0 value register. */
+#define ME1400C_8254_B_2_VAL_REG 0x000E /**< Offset of 8254 B counter 0 value register. */
+#define ME1400C_8254_B_CTRL_REG 0x000F /**< Offset of 8254 B control register. */
+
+#define ME1400C_8254_C_0_VAL_REG 0x0010 /**< Offset of 8254 C counter 0 value register. */
+#define ME1400C_8254_C_1_VAL_REG 0x0011 /**< Offset of 8254 C counter 0 value register. */
+#define ME1400C_8254_C_2_VAL_REG 0x0012 /**< Offset of 8254 C counter 0 value register. */
+#define ME1400C_8254_C_CTRL_REG 0x0013 /**< Offset of 8254 C control register. */
+
+#define ME1400C_8254_D_0_VAL_REG 0x0014 /**< Offset of 8254 D counter 0 value register. */
+#define ME1400C_8254_D_1_VAL_REG 0x0015 /**< Offset of 8254 D counter 0 value register. */
+#define ME1400C_8254_D_2_VAL_REG 0x0016 /**< Offset of 8254 D counter 0 value register. */
+#define ME1400C_8254_D_CTRL_REG 0x0017 /**< Offset of 8254 D control register. */
+
+#define ME1400C_8254_E_0_VAL_REG 0x0018 /**< Offset of 8254 E counter 0 value register. */
+#define ME1400C_8254_E_1_VAL_REG 0x0019 /**< Offset of 8254 E counter 0 value register. */
+#define ME1400C_8254_E_2_VAL_REG 0x001A /**< Offset of 8254 E counter 0 value register. */
+#define ME1400C_8254_E_CTRL_REG 0x001B /**< Offset of 8254 E control register. */
+
+#define ME1400C_CLK_SRC_0_REG 0x001C /**< Offset of clock source register 0. */
+#define ME1400C_CLK_SRC_1_REG 0x001D /**< Offset of clock source register 1. */
+#define ME1400C_CLK_SRC_2_REG 0x001E /**< Offset of clock source register 2. */
+
+/* ME1400 D register offsets */
+#define ME1400D_8254_A_0_VAL_REG 0x0044 /**< Offset of 8254 A counter 0 value register. */
+#define ME1400D_8254_A_1_VAL_REG 0x0045 /**< Offset of 8254 A counter 0 value register. */
+#define ME1400D_8254_A_2_VAL_REG 0x0046 /**< Offset of 8254 A counter 0 value register. */
+#define ME1400D_8254_A_CTRL_REG 0x0047 /**< Offset of 8254 A control register. */
+
+#define ME1400D_8254_B_0_VAL_REG 0x004C /**< Offset of 8254 B counter 0 value register. */
+#define ME1400D_8254_B_1_VAL_REG 0x004D /**< Offset of 8254 B counter 0 value register. */
+#define ME1400D_8254_B_2_VAL_REG 0x004E /**< Offset of 8254 B counter 0 value register. */
+#define ME1400D_8254_B_CTRL_REG 0x004F /**< Offset of 8254 B control register. */
+
+#define ME1400D_8254_C_0_VAL_REG 0x0050 /**< Offset of 8254 C counter 0 value register. */
+#define ME1400D_8254_C_1_VAL_REG 0x0051 /**< Offset of 8254 C counter 0 value register. */
+#define ME1400D_8254_C_2_VAL_REG 0x0052 /**< Offset of 8254 C counter 0 value register. */
+#define ME1400D_8254_C_CTRL_REG 0x0053 /**< Offset of 8254 C control register. */
+
+#define ME1400D_8254_D_0_VAL_REG 0x0054 /**< Offset of 8254 D counter 0 value register. */
+#define ME1400D_8254_D_1_VAL_REG 0x0055 /**< Offset of 8254 D counter 0 value register. */
+#define ME1400D_8254_D_2_VAL_REG 0x0056 /**< Offset of 8254 D counter 0 value register. */
+#define ME1400D_8254_D_CTRL_REG 0x0057 /**< Offset of 8254 D control register. */
+
+#define ME1400D_8254_E_0_VAL_REG 0x0058 /**< Offset of 8254 E counter 0 value register. */
+#define ME1400D_8254_E_1_VAL_REG 0x0059 /**< Offset of 8254 E counter 0 value register. */
+#define ME1400D_8254_E_2_VAL_REG 0x005A /**< Offset of 8254 E counter 0 value register. */
+#define ME1400D_8254_E_CTRL_REG 0x005B /**< Offset of 8254 E control register. */
+
+#define ME1400D_CLK_SRC_0_REG 0x005C /**< Offset of clock source register 0. */
+#define ME1400D_CLK_SRC_1_REG 0x005D /**< Offset of clock source register 1. */
+#define ME1400D_CLK_SRC_2_REG 0x005E /**< Offset of clock source register 2. */
+
+/* ME4600 register offsets */
+#define ME4600_8254_0_VAL_REG 0x0000 /**< Offset of 8254 A counter 0 value register. */
+#define ME4600_8254_1_VAL_REG 0x0001 /**< Offset of 8254 A counter 0 value register. */
+#define ME4600_8254_2_VAL_REG 0x0002 /**< Offset of 8254 A counter 0 value register. */
+#define ME4600_8254_CTRL_REG 0x0003 /**< Offset of 8254 A control register. */
+
+/* Command words for 8254 control register */
+#define ME8254_CTRL_SC0 0x00 /**< Counter 0 selection. */
+#define ME8254_CTRL_SC1 0x40 /**< Counter 1 selection. */
+#define ME8254_CTRL_SC2 0x80 /**< Counter 2 selection. */
+
+#define ME8254_CTRL_TLO 0x00 /**< Counter latching operation. */
+#define ME8254_CTRL_LSB 0x10 /**< Only read LSB. */
+#define ME8254_CTRL_MSB 0x20 /**< Only read MSB. */
+#define ME8254_CTRL_LM 0x30 /**< First read LSB, then MSB. */
+
+#define ME8254_CTRL_M0 0x00 /**< Mode 0 selection. */
+#define ME8254_CTRL_M1 0x02 /**< Mode 1 selection. */
+#define ME8254_CTRL_M2 0x04 /**< Mode 2 selection. */
+#define ME8254_CTRL_M3 0x06 /**< Mode 3 selection. */
+#define ME8254_CTRL_M4 0x08 /**< Mode 4 selection. */
+#define ME8254_CTRL_M5 0x0A /**< Mode 5 selection. */
+
+#define ME8254_CTRL_BIN 0x00 /**< Binary counter. */
+#define ME8254_CTRL_BCD 0x01 /**< BCD counter. */
+
+/* ME-1400 A/B clock source register bits */
+#define ME1400AB_8254_A_0_CLK_SRC_1MHZ (0 << 7) /**< 1MHz clock. */
+#define ME1400AB_8254_A_0_CLK_SRC_10MHZ (1 << 7) /**< 10MHz clock. */
+#define ME1400AB_8254_A_0_CLK_SRC_PIN (0 << 6) /**< CLK 0 to SUB-D. */
+#define ME1400AB_8254_A_0_CLK_SRC_QUARZ (1 << 6) /**< Connect CLK 0 with quarz. */
+
+#define ME1400AB_8254_A_1_CLK_SRC_PIN (0 << 5) /**< CLK 1 to SUB-D. */
+#define ME1400AB_8254_A_1_CLK_SRC_PREV (1 << 5) /**< Connect OUT 0 with CLK 1. */
+
+#define ME1400AB_8254_A_2_CLK_SRC_PIN (0 << 4) /**< CLK 2 to SUB-D. */
+#define ME1400AB_8254_A_2_CLK_SRC_PREV (1 << 4) /**< Connect OUT 1 with CLK 2. */
+
+#define ME1400AB_8254_B_0_CLK_SRC_1MHZ (0 << 3) /**< 1MHz clock. */
+#define ME1400AB_8254_B_0_CLK_SRC_10MHZ (1 << 3) /**< 10MHz clock. */
+#define ME1400AB_8254_B_0_CLK_SRC_PIN (0 << 2) /**< CLK 0 to SUB-D. */
+#define ME1400AB_8254_B_0_CLK_SRC_QUARZ (1 << 2) /**< Connect CLK 0 with quarz. */
+
+#define ME1400AB_8254_B_1_CLK_SRC_PIN (0 << 1) /**< CLK 1 to SUB-D. */
+#define ME1400AB_8254_B_1_CLK_SRC_PREV (1 << 1) /**< Connect OUT 0 with CLK 1. */
+
+#define ME1400AB_8254_B_2_CLK_SRC_PIN (0 << 0) /**< CLK 2 to SUB-D. */
+#define ME1400AB_8254_B_2_CLK_SRC_PREV (1 << 0) /**< Connect OUT 1 with CLK 2. */
+
+/* ME-1400 C/D clock source registers bits */
+#define ME1400CD_8254_ACE_0_CLK_SRC_MASK 0x03 /**< Masks all CLK source bits. */
+#define ME1400CD_8254_ACE_0_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */
+#define ME1400CD_8254_ACE_0_CLK_SRC_1MHZ 0x01 /**< Connect CLK to 1MHz. */
+#define ME1400CD_8254_ACE_0_CLK_SRC_10MHZ 0x02 /**< Connect CLK to 10MHz. */
+#define ME1400CD_8254_ACE_0_CLK_SRC_PREV 0x03 /**< Connect CLK to previous counter output on ME-1400 D extension. */
+
+#define ME1400CD_8254_ACE_1_CLK_SRC_MASK 0x04 /**< Masks all CLK source bits. */
+#define ME1400CD_8254_ACE_1_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */
+#define ME1400CD_8254_ACE_1_CLK_SRC_PREV 0x04 /**< Connect CLK to previous counter output. */
+
+#define ME1400CD_8254_ACE_2_CLK_SRC_MASK 0x08 /**< Masks all CLK source bits. */
+#define ME1400CD_8254_ACE_2_CLK_SRC_PIN 0x00 /**< Connect to SUB-D. */
+#define ME1400CD_8254_ACE_2_CLK_SRC_PREV 0x08 /**< Connect CLK to previous counter output. */
+
+#define ME1400CD_8254_BD_0_CLK_SRC_MASK 0x30 /**< Masks all CLK source bits. */
+#define ME1400CD_8254_BD_0_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */
+#define ME1400CD_8254_BD_0_CLK_SRC_1MHZ 0x10 /**< Connect CLK to 1MHz. */
+#define ME1400CD_8254_BD_0_CLK_SRC_10MHZ 0x20 /**< Connect CLK to 10MHz. */
+#define ME1400CD_8254_BD_0_CLK_SRC_PREV 0x30 /**< Connect CLK to previous counter output. */
+
+#define ME1400CD_8254_BD_1_CLK_SRC_MASK 0x40 /**< Masks all CLK source bits. */
+#define ME1400CD_8254_BD_1_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */
+#define ME1400CD_8254_BD_1_CLK_SRC_PREV 0x40 /**< Connect CLK to previous counter output. */
+
+#define ME1400CD_8254_BD_2_CLK_SRC_MASK 0x80 /**< Masks all CLK source bits. */
+#define ME1400CD_8254_BD_2_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */
+#define ME1400CD_8254_BD_2_CLK_SRC_PREV 0x80 /**< Connect CLK to previous counter output. */
+
+/* ME-8100 counter registers */
+#define ME8100_COUNTER_REG_0 0x18 //(r,w)
+#define ME8100_COUNTER_REG_1 0x1A //(r,w)
+#define ME8100_COUNTER_REG_2 0x1C //(r,w)
+#define ME8100_COUNTER_CTRL_REG 0x1E //(r,w)
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8255.c b/drivers/staging/meilhaus/me8255.c
new file mode 100644
index 000000000000..180e7f8d2146
--- /dev/null
+++ b/drivers/staging/meilhaus/me8255.c
@@ -0,0 +1,462 @@
+/**
+ * @file me8255.c
+ *
+ * @brief 8255 subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+#include "medebug.h"
+
+#include "me8255_reg.h"
+#include "me8255.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static uint8_t get_mode_from_mirror(uint32_t mirror)
+{
+ PDEBUG("executed.\n");
+
+ if (mirror & ME8255_PORT_0_OUTPUT) {
+ if (mirror & ME8255_PORT_1_OUTPUT) {
+ if (mirror & ME8255_PORT_2_OUTPUT) {
+ return ME8255_MODE_OOO;
+ } else {
+ return ME8255_MODE_IOO;
+ }
+ } else {
+ if (mirror & ME8255_PORT_2_OUTPUT) {
+ return ME8255_MODE_OIO;
+ } else {
+ return ME8255_MODE_IIO;
+ }
+ }
+ } else {
+ if (mirror & ME8255_PORT_1_OUTPUT) {
+ if (mirror & ME8255_PORT_2_OUTPUT) {
+ return ME8255_MODE_OOI;
+ } else {
+ return ME8255_MODE_IOI;
+ }
+ } else {
+ if (mirror & ME8255_PORT_2_OUTPUT) {
+ return ME8255_MODE_OII;
+ } else {
+ return ME8255_MODE_III;
+ }
+ }
+ }
+}
+
+static int me8255_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ me8255_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8255_subdevice_t *) subdevice;
+
+ if (flags) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ spin_lock(instance->ctrl_reg_lock);
+ *instance->ctrl_reg_mirror &=
+ ~(ME8255_PORT_0_OUTPUT << instance->dio_idx);
+ outb(get_mode_from_mirror(*instance->ctrl_reg_mirror),
+ instance->ctrl_reg);
+ spin_unlock(instance->ctrl_reg_lock);
+
+ outb(0, instance->port_reg);
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8255_io_single_config(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ me8255_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8255_subdevice_t *) subdevice;
+
+ if (flags & ~ME_IO_SINGLE_CONFIG_DIO_BYTE) {
+ PERROR("Invalid flag specified.\n");
+ return ME_ERRNO_INVALID_FLAGS;
+ }
+
+ if (channel) {
+ PERROR("Invalid channel.\n");
+ return ME_ERRNO_INVALID_CHANNEL;
+ }
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
+ spin_lock(instance->ctrl_reg_lock);
+ *instance->ctrl_reg_mirror &=
+ ~(ME8255_PORT_0_OUTPUT << instance->dio_idx);
+ outb(get_mode_from_mirror(*instance->ctrl_reg_mirror),
+ instance->ctrl_reg);
+ spin_unlock(instance->ctrl_reg_lock);
+ } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
+ spin_lock(instance->ctrl_reg_lock);
+ *instance->ctrl_reg_mirror |=
+ (ME8255_PORT_0_OUTPUT << instance->dio_idx);
+ outb(get_mode_from_mirror(*instance->ctrl_reg_mirror),
+ instance->ctrl_reg);
+ spin_unlock(instance->ctrl_reg_lock);
+ } else {
+ PERROR("Invalid port direction.\n");
+ err = ME_ERRNO_INVALID_SINGLE_CONFIG;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8255_io_single_read(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ me8255_subdevice_t *instance;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8255_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ *value = inb(instance->port_reg) & (0x1 << channel);
+ } else {
+ PERROR("Invalid bit number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ *value = inb(instance->port_reg);
+ } else {
+ PERROR("Invalid byte number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8255_io_single_write(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ me8255_subdevice_t *instance;
+ uint8_t byte;
+ int err = ME_ERRNO_SUCCESS;
+
+ PDEBUG("executed.\n");
+
+ instance = (me8255_subdevice_t *) subdevice;
+
+ ME_SUBDEVICE_ENTER;
+
+ spin_lock(&instance->subdevice_lock);
+ switch (flags) {
+ case ME_IO_SINGLE_TYPE_DIO_BIT:
+ if ((channel >= 0) && (channel < 8)) {
+ if (*instance->
+ ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT <<
+ instance->dio_idx)) {
+ byte = inb(instance->port_reg);
+
+ if (value)
+ byte |= 0x1 << channel;
+ else
+ byte &= ~(0x1 << channel);
+
+ outb(byte, instance->port_reg);
+ } else {
+ PERROR("Port not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid bit number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ case ME_IO_SINGLE_NO_FLAGS:
+ case ME_IO_SINGLE_TYPE_DIO_BYTE:
+ if (channel == 0) {
+ if (*instance->
+ ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT <<
+ instance->dio_idx)) {
+ outb(value, instance->port_reg);
+ } else {
+ PERROR("Port not in output mode.\n");
+ err = ME_ERRNO_PREVIOUS_CONFIG;
+ }
+ } else {
+ PERROR("Invalid byte number.\n");
+ err = ME_ERRNO_INVALID_CHANNEL;
+ }
+ break;
+
+ default:
+ PERROR("Invalid flags specified.\n");
+ err = ME_ERRNO_INVALID_FLAGS;
+ }
+ spin_unlock(&instance->subdevice_lock);
+
+ ME_SUBDEVICE_EXIT;
+
+ return err;
+}
+
+static int me8255_query_number_channels(struct me_subdevice *subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = ME8255_NUMBER_CHANNELS;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8255_query_subdevice_type(struct me_subdevice *subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = ME_TYPE_DIO;
+ *subtype = ME_SUBTYPE_SINGLE;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me8255_query_subdevice_caps(struct me_subdevice *subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = ME_CAPS_DIO_DIR_BYTE;
+ return ME_ERRNO_SUCCESS;
+}
+
+me8255_subdevice_t *me8255_constructor(uint32_t device_id,
+ uint32_t reg_base,
+ unsigned int me8255_idx,
+ unsigned int dio_idx,
+ int *ctrl_reg_mirror,
+ spinlock_t * ctrl_reg_lock)
+{
+ me8255_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(me8255_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for 8255 instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(me8255_subdevice_t));
+
+ /* Check if counter index is out of range */
+
+ if (dio_idx > 2) {
+ PERROR("DIO index is out of range.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save the pointer to global port settings */
+ subdevice->ctrl_reg_mirror = ctrl_reg_mirror;
+
+ /* Save type of Meilhaus device */
+ subdevice->device_id = device_id;
+
+ /* Save the indices */
+ subdevice->me8255_idx = me8255_idx;
+ subdevice->dio_idx = dio_idx;
+
+ /* Do device specific initialization */
+ switch (device_id) {
+ case PCI_DEVICE_ID_MEILHAUS_ME1400:
+ case PCI_DEVICE_ID_MEILHAUS_ME14E0:
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140A:
+ case PCI_DEVICE_ID_MEILHAUS_ME14EA:
+ /* Check if 8255 index is out of range */
+ if (me8255_idx > 0) {
+ PERROR("8255 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140B: /* Fall through */
+ case PCI_DEVICE_ID_MEILHAUS_ME14EB:
+ /* Check if 8255 index is out of range */
+ if (me8255_idx > 1) {
+ PERROR("8255 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Get the registers */
+ if (me8255_idx == 0) {
+ subdevice->ctrl_reg = reg_base + ME1400AB_PORT_A_CTRL;
+ subdevice->port_reg =
+ reg_base + ME1400AB_PORT_A_0 + dio_idx;
+ } else if (me8255_idx == 1) {
+ subdevice->ctrl_reg = reg_base + ME1400AB_PORT_B_CTRL;
+ subdevice->port_reg =
+ reg_base + ME1400AB_PORT_B_0 + dio_idx;
+ }
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ /* Check if 8255 index is out of range */
+ if (me8255_idx > 0) {
+ PERROR("8255 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140D: /* Fall through */
+ /* Check if 8255 index is out of range */
+ if (me8255_idx > 1) {
+ PERROR("8255 index is out of range.\n");
+ me_subdevice_deinit(&subdevice->base);
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Get the registers */
+ if (me8255_idx == 0) {
+ subdevice->ctrl_reg = reg_base + ME1400CD_PORT_A_CTRL;
+ subdevice->port_reg =
+ reg_base + ME1400CD_PORT_A_0 + dio_idx;
+ } else if (me8255_idx == 1) {
+ subdevice->ctrl_reg = reg_base + ME1400CD_PORT_B_CTRL;
+ subdevice->port_reg =
+ reg_base + ME1400CD_PORT_B_0 + dio_idx;
+ }
+
+ break;
+
+ default:
+ PERROR("Unknown device type. dev ID: 0x%04x\n", device_id);
+
+ me_subdevice_deinit(&subdevice->base);
+
+ kfree(subdevice);
+
+ return NULL;
+ }
+
+ /* Overload subdevice base class methods. */
+ subdevice->base.me_subdevice_io_reset_subdevice =
+ me8255_io_reset_subdevice;
+ subdevice->base.me_subdevice_io_single_config = me8255_io_single_config;
+ subdevice->base.me_subdevice_io_single_read = me8255_io_single_read;
+ subdevice->base.me_subdevice_io_single_write = me8255_io_single_write;
+ subdevice->base.me_subdevice_query_number_channels =
+ me8255_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ me8255_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ me8255_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/me8255.h b/drivers/staging/meilhaus/me8255.h
new file mode 100644
index 000000000000..338230052b3c
--- /dev/null
+++ b/drivers/staging/meilhaus/me8255.h
@@ -0,0 +1,59 @@
+/**
+ * @file me8255.h
+ *
+ * @brief Meilhaus PIO 8255 implementation.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME8255_H_
+#define _ME8255_H_
+
+#include "mesubdevice.h"
+#include "meslock.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The 8255 subdevice class.
+ */
+typedef struct me8255_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+
+ int *ctrl_reg_mirror; /**< Pointer to mirror of the control register. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg and #ctrl_reg_mirror from concurrent access. */
+
+ uint32_t device_id; /**< The PCI device id of the device holding the 8255 chip. */
+ int me8255_idx; /**< The index of the 8255 chip on the device. */
+ int dio_idx; /**< The index of the DIO port on the 8255 chip. */
+
+ unsigned long port_reg; /**< Register to read or write a value from or to the port respectively. */
+ unsigned long ctrl_reg; /**< Register to configure the 8255 modes. */
+} me8255_subdevice_t;
+
+/**
+ * @brief The constructor to generate a 8255 instance.
+ *
+ * @param device_id The kind of Meilhaus device holding the 8255.
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param me8255_idx The index of the 8255 chip on the Meilhaus device.
+ * @param dio_idx The index of the counter inside a 8255 chip.
+ * @param ctr_reg_mirror Pointer to mirror of control register.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the 8255 control register and #ctrl_reg_mirror from concurrent access.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+me8255_subdevice_t *me8255_constructor(uint32_t device_id,
+ uint32_t reg_base,
+ unsigned int me8255_idx,
+ unsigned int dio_idx,
+ int *ctrl_reg_mirror,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/me8255_reg.h b/drivers/staging/meilhaus/me8255_reg.h
new file mode 100644
index 000000000000..d1dea1a447f6
--- /dev/null
+++ b/drivers/staging/meilhaus/me8255_reg.h
@@ -0,0 +1,50 @@
+/**
+ * @file me8255_reg.h
+ *
+ * @brief 8255 counter register definitions.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME8255_REG_H_
+#define _ME8255_REG_H_
+
+#ifdef __KERNEL__
+
+#define ME8255_NUMBER_CHANNELS 8 /**< The number of channels per 8255 port. */
+
+#define ME1400AB_PORT_A_0 0x0000 /**< Port 0 offset. */
+#define ME1400AB_PORT_A_1 0x0001 /**< Port 1 offset. */
+#define ME1400AB_PORT_A_2 0x0002 /**< Port 2 offset. */
+#define ME1400AB_PORT_A_CTRL 0x0003 /**< Control register for 8255 A. */
+
+#define ME1400AB_PORT_B_0 0x0008 /**< Port 0 offset. */
+#define ME1400AB_PORT_B_1 0x0009 /**< Port 1 offset. */
+#define ME1400AB_PORT_B_2 0x000A /**< Port 2 offset. */
+#define ME1400AB_PORT_B_CTRL 0x000B /**< Control register for 8255 B. */
+
+#define ME1400CD_PORT_A_0 0x0000 /**< Port 0 offset. */
+#define ME1400CD_PORT_A_1 0x0001 /**< Port 1 offset. */
+#define ME1400CD_PORT_A_2 0x0002 /**< Port 2 offset. */
+#define ME1400CD_PORT_A_CTRL 0x0003 /**< Control register for 8255 A. */
+
+#define ME1400CD_PORT_B_0 0x0040 /**< Port 0 offset. */
+#define ME1400CD_PORT_B_1 0x0041 /**< Port 1 offset. */
+#define ME1400CD_PORT_B_2 0x0042 /**< Port 2 offset. */
+#define ME1400CD_PORT_B_CTRL 0x0043 /**< Control register for 8255 B. */
+
+#define ME8255_MODE_OOO 0x80 /**< Port 2 = Output, Port 1 = Output, Port 0 = Output */
+#define ME8255_MODE_IOO 0x89 /**< Port 2 = Input, Port 1 = Output, Port 0 = Output */
+#define ME8255_MODE_OIO 0x82 /**< Port 2 = Output, Port 1 = Input, Port 0 = Output */
+#define ME8255_MODE_IIO 0x8B /**< Port 2 = Input, Port 1 = Input, Port 0 = Output */
+#define ME8255_MODE_OOI 0x90 /**< Port 2 = Output, Port 1 = Output, Port 0 = Input */
+#define ME8255_MODE_IOI 0x99 /**< Port 2 = Input, Port 1 = Output, Port 0 = Input */
+#define ME8255_MODE_OII 0x92 /**< Port 2 = Output, Port 1 = Input, Port 0 = Input */
+#define ME8255_MODE_III 0x9B /**< Port 2 = Input, Port 1 = Input, Port 0 = Input */
+
+#define ME8255_PORT_0_OUTPUT 0x1 /**< If set in mirror then port 0 is in output mode. */
+#define ME8255_PORT_1_OUTPUT 0x2 /**< If set in mirror then port 1 is in output mode. */
+#define ME8255_PORT_2_OUTPUT 0x4 /**< If set in mirror then port 2 is in output mode. */
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/mecirc_buf.h b/drivers/staging/meilhaus/mecirc_buf.h
new file mode 100644
index 000000000000..e9b591eaa349
--- /dev/null
+++ b/drivers/staging/meilhaus/mecirc_buf.h
@@ -0,0 +1,131 @@
+/**
+ * @file mecirc_buf.h
+ *
+ * @brief Meilhaus circular buffer implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MECIRC_BUF_H_
+#define _MECIRC_BUF_H_
+
+# ifdef __KERNEL__
+
+# ifdef BOSCH
+
+typedef struct me_circ_buf {
+ unsigned int mask;
+// unsigned int count;
+ uint32_t *buf;
+ int volatile head;
+ int volatile tail;
+} me_circ_buf_t;
+
+static int inline me_circ_buf_values(me_circ_buf_t * buf)
+{
+// return ((buf->head - buf->tail) & (buf->count - 1));
+ return ((buf->head - buf->tail) & (buf->mask));
+}
+
+static int inline me_circ_buf_space(me_circ_buf_t * buf)
+{
+// return ((buf->tail - (buf->head + 1)) & (buf->count - 1));
+ return ((buf->tail - (buf->head + 1)) & (buf->mask));
+}
+
+static int inline me_circ_buf_values_to_end(me_circ_buf_t * buf)
+{
+ int end;
+ int n;
+// end = buf->count - buf->tail;
+// n = (buf->head + end) & (buf->count - 1);
+ end = buf->mask + 1 - buf->tail;
+ n = (buf->head + end) & (buf->mask);
+ return (n < end) ? n : end;
+}
+
+static int inline me_circ_buf_space_to_end(me_circ_buf_t * buf)
+{
+ int end;
+ int n;
+
+// end = buf->count - 1 - buf->head;
+// n = (end + buf->tail) & (buf->count - 1);
+ end = buf->mask - buf->head;
+ n = (end + buf->tail) & (buf->mask);
+ return (n <= end) ? n : (end + 1);
+}
+
+#define _CBUFF_32b_t
+
+# else //~BOSCH
+/// @note buf->mask = buf->count-1 = ME4600_AI_CIRC_BUF_COUNT-1
+
+# ifdef _CBUFF_32b_t
+ //32 bit
+typedef struct me_circ_buf_32b {
+ int volatile head;
+ int volatile tail;
+ unsigned int mask; //buffor size-1 must be 2^n-1 to work
+ uint32_t *buf;
+} me_circ_buf_t;
+# else
+ //16 bit
+typedef struct me_circ_buf_16b {
+ int volatile head;
+ int volatile tail;
+ unsigned int mask; //buffor size-1 must be 2^n-1 to work
+ uint16_t *buf;
+} me_circ_buf_t;
+# endif //_CBUFF_32b_t
+
+/** How many values is in buffer */
+static int inline me_circ_buf_values(me_circ_buf_t * buf)
+{
+ return ((buf->head - buf->tail) & (buf->mask));
+}
+
+/** How many space left */
+static int inline me_circ_buf_space(me_circ_buf_t * buf)
+{
+ return ((buf->tail - (buf->head + 1)) & (buf->mask));
+}
+
+/** How many values can be read from buffor in one chunck. */
+static int inline me_circ_buf_values_to_end(me_circ_buf_t * buf)
+{
+ return (buf->tail <=
+ buf->head) ? (buf->head - buf->tail) : (buf->mask - buf->tail +
+ 1);
+}
+
+/** How many values can be write to buffer in one chunck. */
+static int inline me_circ_buf_space_to_end(me_circ_buf_t * buf)
+{
+ return (buf->tail <=
+ buf->head) ? (buf->mask - buf->head + 1) : (buf->tail -
+ buf->head - 1);
+}
+
+# endif //BOSCH
+# endif //__KERNEL__
+#endif //_MECIRC_BUF_H_
diff --git a/drivers/staging/meilhaus/mecommon.h b/drivers/staging/meilhaus/mecommon.h
new file mode 100644
index 000000000000..ef47c384e018
--- /dev/null
+++ b/drivers/staging/meilhaus/mecommon.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File :mecommon.h
+ * Author :GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ * Author :KG (Krzysztof Gantzke) <k.gantzke@meilhaus.de>
+ */
+
+#ifndef _MECOMMON_H_
+#define _MECOMMON_H_
+
+/*==================================================================
+ The version of this release
+ ================================================================*/
+
+#ifndef ME_VERSION_DRIVER
+/* Unknown version */
+# define ME_VERSION_DRIVER 0xFFFFFFFF
+#endif
+
+#ifndef LIBMEDRIVER_VERSION
+/* Unknown version */
+# define LIBMEDRIVER_VERSION 0xFFFFFFFF
+#endif
+
+#endif
diff --git a/drivers/staging/meilhaus/medebug.h b/drivers/staging/meilhaus/medebug.h
new file mode 100644
index 000000000000..dcfb97c26fd1
--- /dev/null
+++ b/drivers/staging/meilhaus/medebug.h
@@ -0,0 +1,125 @@
+/**
+ * @file medebug.h
+ *
+ * @brief Debugging defines.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+#ifndef _MEDEBUG_H_
+#define _MEDEBUG_H_
+
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+
+//Messages control.
+
+#ifdef MEDEBUG_TEST_ALL /* Switch to enable all info messages. */
+# ifndef MEDEBUG_TEST
+# define MEDEBUG_TEST
+# endif
+# ifndef MEDEBUG_TEST_INFO
+# define MEDEBUG_TEST_INFO
+# endif
+# ifndef MEDEBUG_DEBUG_REG
+# define MEDEBUG_DEBUG_REG /* Switch to enable registry access debuging messages. */
+# endif
+# ifndef MEDEBUG_DEBUG_LOCKS
+# define MEDEBUG_DEBUG_LOCKS /* Switch to enable locking messages. */
+# endif
+#endif
+
+#ifdef MEDEBUG_TEST_INFO /* Switch to enable info and test messages. */
+# ifndef MEDEBUG_INFO
+# define MEDEBUG_INFO /* Switch to enable info messages. */
+# endif
+# ifndef MEDEBUG_TEST
+# define MEDEBUG_TEST
+# endif
+#endif
+
+#ifdef MEDEBUG_TEST /* Switch to enable debug test messages. */
+# ifndef MEDEBUG_DEBUG
+# define MEDEBUG_DEBUG /* Switch to enable debug messages. */
+# endif
+# ifndef MEDEBUG_ERROR
+# define MEDEBUG_ERROR /* Switch to enable error messages. */
+# endif
+#endif
+
+#ifdef MEDEBUG_ERROR /* Switch to enable error messages. */
+# ifndef MEDEBUG_ERROR_CRITICAL /* Also critical error messages. */
+# define MEDEBUG_ERROR_CRITICAL /* Switch to enable high importance error messages. */
+# endif
+#endif
+
+#undef PDEBUG /* Only to be sure. */
+#undef PINFO /* Only to be sure. */
+#undef PERROR /* Only to be sure. */
+#undef PERROR_CRITICAL /* Only to be sure. */
+#undef PDEBUG_REG /* Only to be sure. */
+#undef PDEBUG_LOCKS /* Only to be sure. */
+#undef PSECURITY /* Only to be sure. */
+#undef PLOG /* Only to be sure. */
+
+#ifdef MEDEBUG_DEBUG
+# define PDEBUG(fmt, args...) \
+ printk(KERN_DEBUG"ME_DRV D: <%s> " fmt, __func__, ##args)
+#else
+# define PDEBUG(fmt, args...)
+#endif
+
+#ifdef MEDEBUG_DEBUG_LOCKS
+# define PDEBUG_LOCKS(fmt, args...) \
+ printk(KERN_DEBUG"ME_DRV L: <%s> " fmt, __func__, ##args)
+#else
+# define PDEBUG_LOCKS(fmt, args...)
+#endif
+
+#ifdef MEDEBUG_DEBUG_REG
+# define PDEBUG_REG(fmt, args...) \
+ printk(KERN_DEBUG"ME_DRV R: <%s:%d> REG:" fmt, __func__, __LINE__, ##args)
+#else
+# define PDEBUG_REG(fmt, args...)
+#endif
+
+#ifdef MEDEBUG_INFO
+# define PINFO(fmt, args...) \
+ printk(KERN_INFO"ME_DRV I: " fmt, ##args)
+#else
+# define PINFO(fmt, args...)
+#endif
+
+#ifdef MEDEBUG_ERROR
+# define PERROR(fmt, args...) \
+ printk(KERN_ERR"ME_DRV E: <%s:%i> " fmt, __FILE__, __LINE__, ##args)
+#else
+# define PERROR(fmt, args...)
+#endif
+
+#ifdef MEDEBUG_ERROR_CRITICAL
+# define PERROR_CRITICAL(fmt, args...) \
+ printk(KERN_CRIT"ME_DRV C: <%s:%i> " fmt, __FILE__, __LINE__, ##args)
+#else
+# define PERROR_CRITICAL(fmt, args...)
+#endif
+
+//This debug is only to detect logical errors!
+# define PSECURITY(fmt, args...) \
+ printk(KERN_CRIT"ME_DRV SECURITY: <%s:%s:%i> " fmt, __FILE__, __func__, __LINE__, ##args)
+//This debug is to keep track in customers' system
+# define PLOG(fmt, args...) \
+ printk(KERN_INFO"ME_DRV: " fmt, ##args)
+
+//This debug is to check new parts during development
+#ifdef MEDEBUG_DEVELOP
+# define PDEVELOP(fmt, args...) \
+ printk(KERN_CRIT"ME_DRV: <%s:%s:%i> " fmt, __FILE__, __func__, __LINE__, ##args)
+#else
+# define PDEVELOP(fmt, args...)
+#endif
+
+#endif //__KERNEL__
+#endif //_MEDEBUG_H_
diff --git a/drivers/staging/meilhaus/medefines.h b/drivers/staging/meilhaus/medefines.h
new file mode 100644
index 000000000000..6158ef5b80e6
--- /dev/null
+++ b/drivers/staging/meilhaus/medefines.h
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : medefines.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ * Author : KG (Krzysztof Gantzke) <k.gantzke@meilhaus.de>
+ */
+
+#ifndef _MEDEFINES_H_
+#define _MEDEFINES_H_
+
+/*==================================================================
+ General
+ ================================================================*/
+
+#define ME_VALUE_NOT_USED 0x0
+#define ME_VALUE_INVALID ~0x0
+
+/*==================================================================
+ Defines common to access functions
+ ================================================================*/
+
+#define ME_LOCK_RELEASE 0x00010001
+#define ME_LOCK_SET 0x00010002
+#define ME_LOCK_CHECK 0x00010003
+
+/*==================================================================
+ Defines meOpen function
+ ================================================================*/
+
+#define ME_OPEN_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines meClose function
+ ================================================================*/
+
+#define ME_CLOSE_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines meLockDriver function
+ ================================================================*/
+
+#define ME_LOCK_DRIVER_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines meLockDevice function
+ ================================================================*/
+
+#define ME_LOCK_DEVICE_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines meLockSubdevice function
+ ================================================================*/
+
+#define ME_LOCK_SUBDEVICE_NO_FLAGS 0x0
+
+
+/*==================================================================
+ Defines common to error functions
+ ================================================================*/
+
+#define ME_ERROR_MSG_MAX_COUNT 256
+
+#define ME_SWITCH_DISABLE 0x00020001
+#define ME_SWITCH_ENABLE 0x00020002
+
+/*==================================================================
+ Defines common to io functions
+ ================================================================*/
+
+#define ME_REF_DIO_FIFO_LOW 0x00030001
+#define ME_REF_DIO_FIFO_HIGH 0x00030002
+
+#define ME_REF_CTR_PREVIOUS 0x00040001
+#define ME_REF_CTR_INTERNAL_1MHZ 0x00040002
+#define ME_REF_CTR_INTERNAL_10MHZ 0x00040003
+#define ME_REF_CTR_EXTERNAL 0x00040004
+
+#define ME_REF_AI_GROUND 0x00050001
+#define ME_REF_AI_DIFFERENTIAL 0x00050002
+
+#define ME_REF_AO_GROUND 0x00060001
+
+#define ME_TRIG_CHAN_DEFAULT 0x00070001
+#define ME_TRIG_CHAN_SYNCHRONOUS 0x00070002
+
+#define ME_TRIG_TYPE_NONE 0x00000000
+#define ME_TRIG_TYPE_SW 0x00080001
+#define ME_TRIG_TYPE_THRESHOLD 0x00080002
+#define ME_TRIG_TYPE_WINDOW 0x00080003
+#define ME_TRIG_TYPE_EDGE 0x00080004
+#define ME_TRIG_TYPE_SLOPE 0x00080005
+#define ME_TRIG_TYPE_EXT_DIGITAL 0x00080006
+#define ME_TRIG_TYPE_EXT_ANALOG 0x00080007
+#define ME_TRIG_TYPE_PATTERN 0x00080008
+#define ME_TRIG_TYPE_TIMER 0x00080009
+#define ME_TRIG_TYPE_COUNT 0x0008000A
+#define ME_TRIG_TYPE_FOLLOW 0x0008000B
+
+#define ME_TRIG_EDGE_NONE 0x00000000
+#define ME_TRIG_EDGE_ABOVE 0x00090001
+#define ME_TRIG_EDGE_BELOW 0x00090002
+#define ME_TRIG_EDGE_ENTRY 0x00090003
+#define ME_TRIG_EDGE_EXIT 0x00090004
+#define ME_TRIG_EDGE_RISING 0x00090005
+#define ME_TRIG_EDGE_FALLING 0x00090006
+#define ME_TRIG_EDGE_ANY 0x00090007
+
+#define ME_TIMER_ACQ_START 0x000A0001
+#define ME_TIMER_SCAN_START 0x000A0002
+#define ME_TIMER_CONV_START 0x000A0003
+
+/*==================================================================
+ Defines for meIOFrequencyToTicks function
+ ================================================================*/
+
+#define ME_IO_FREQUENCY_TO_TICKS_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines for meIOIrqStart function
+ ================================================================*/
+
+#define ME_IRQ_SOURCE_DIO_PATTERN 0x000B0001
+#define ME_IRQ_SOURCE_DIO_MASK 0x000B0002
+#define ME_IRQ_SOURCE_DIO_LINE 0x000B0003
+#define ME_IRQ_SOURCE_DIO_OVER_TEMP 0x000B0004
+
+#define ME_IRQ_EDGE_NOT_USED 0x00000000
+#define ME_IRQ_EDGE_RISING 0x000C0001
+#define ME_IRQ_EDGE_FALLING 0x000C0002
+#define ME_IRQ_EDGE_ANY 0x000C0003
+
+/*==================================================================
+ Defines for meIOIrqStart function
+ ================================================================*/
+
+#define ME_IO_IRQ_START_NO_FLAGS 0x000000
+#define ME_IO_IRQ_START_DIO_BIT 0x000001
+#define ME_IO_IRQ_START_DIO_BYTE 0x000002
+#define ME_IO_IRQ_START_DIO_WORD 0x000004
+#define ME_IO_IRQ_START_DIO_DWORD 0x000008
+#define ME_IO_IRQ_START_PATTERN_FILTERING 0x000010
+#define ME_IO_IRQ_START_EXTENDED_STATUS 0x000020
+
+/*==================================================================
+ Defines for meIOIrqWait function
+ ================================================================*/
+
+#define ME_IO_IRQ_WAIT_NO_FLAGS 0x000000
+#define ME_IO_IRQ_WAIT_NORMAL_STATUS 0x000001
+#define ME_IO_IRQ_WAIT_EXTENDED_STATUS 0x000002
+
+/*==================================================================
+ Defines for meIOIrqStop function
+ ================================================================*/
+
+#define ME_IO_IRQ_STOP_NO_FLAGS 0x000000
+
+/*==================================================================
+ Defines for meIOIrqSetCallback function
+ ================================================================*/
+
+#define ME_IO_IRQ_SET_CALLBACK_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines for meIOResetDevice function
+ ================================================================*/
+
+#define ME_IO_RESET_DEVICE_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines for meIOResetSubdevice function
+ ================================================================*/
+
+#define ME_IO_RESET_SUBDEVICE_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines for meIOSingleConfig function
+ ================================================================*/
+
+#define ME_SINGLE_CONFIG_DIO_INPUT 0x000D0001
+#define ME_SINGLE_CONFIG_DIO_OUTPUT 0x000D0002
+#define ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE 0x000D0003
+#define ME_SINGLE_CONFIG_DIO_SINK 0x000D0004
+#define ME_SINGLE_CONFIG_DIO_SOURCE 0x000D0005
+#define ME_SINGLE_CONFIG_DIO_MUX32M 0x000D0006
+#define ME_SINGLE_CONFIG_DIO_DEMUX32 0x000D0007
+#define ME_SINGLE_CONFIG_DIO_BIT_PATTERN 0x000D0008
+
+#define ME_SINGLE_CONFIG_CTR_8254_MODE_0 0x000E0001
+#define ME_SINGLE_CONFIG_CTR_8254_MODE_1 0x000E0002
+#define ME_SINGLE_CONFIG_CTR_8254_MODE_2 0x000E0003
+#define ME_SINGLE_CONFIG_CTR_8254_MODE_3 0x000E0004
+#define ME_SINGLE_CONFIG_CTR_8254_MODE_4 0x000E0005
+#define ME_SINGLE_CONFIG_CTR_8254_MODE_5 0x000E0006
+
+#define ME_IO_SINGLE_CONFIG_NO_FLAGS 0x00
+#define ME_IO_SINGLE_CONFIG_DIO_BIT 0x01
+#define ME_IO_SINGLE_CONFIG_DIO_BYTE 0x02
+#define ME_IO_SINGLE_CONFIG_DIO_WORD 0x04
+#define ME_IO_SINGLE_CONFIG_DIO_DWORD 0x08
+#define ME_IO_SINGLE_CONFIG_MULTISIG_LED_ON 0x10
+#define ME_IO_SINGLE_CONFIG_MULTISIG_LED_OFF 0x20
+#define ME_IO_SINGLE_CONFIG_AI_RMS 0x40
+#define ME_IO_SINGLE_CONFIG_CONTINUE 0x80
+
+/*==================================================================
+ Defines for meIOSingle function
+ ================================================================*/
+
+#define ME_IO_SINGLE_NO_FLAGS 0x0
+#define ME_IO_SINGLE_NONBLOCKING 0x20
+
+#define ME_DIR_INPUT 0x000F0001
+#define ME_DIR_OUTPUT 0x000F0002
+
+#define ME_IO_SINGLE_TYPE_NO_FLAGS 0x00
+#define ME_IO_SINGLE_TYPE_DIO_BIT 0x01
+#define ME_IO_SINGLE_TYPE_DIO_BYTE 0x02
+#define ME_IO_SINGLE_TYPE_DIO_WORD 0x04
+#define ME_IO_SINGLE_TYPE_DIO_DWORD 0x08
+#define ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS 0x10
+#define ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING 0x20
+
+/*==================================================================
+ Defines for meIOStreamConfig function
+ ================================================================*/
+
+#define ME_IO_STREAM_CONFIG_NO_FLAGS 0x0
+#define ME_IO_STREAM_CONFIG_BIT_PATTERN 0x1
+#define ME_IO_STREAM_CONFIG_WRAPAROUND 0x2
+#define ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD 0x4
+#define ME_IO_STREAM_CONFIG_HARDWARE_ONLY 0x8
+
+#define ME_IO_STREAM_CONFIG_TYPE_NO_FLAGS 0x0
+
+#define ME_IO_STREAM_TRIGGER_TYPE_NO_FLAGS 0x0
+
+/*==================================================================
+ Defines for meIOStreamRead function
+ ================================================================*/
+
+#define ME_READ_MODE_BLOCKING 0x00100001
+#define ME_READ_MODE_NONBLOCKING 0x00100002
+
+#define ME_IO_STREAM_READ_NO_FLAGS 0x0
+#define ME_IO_STREAM_READ_FRAMES 0x1
+
+/*==================================================================
+ Defines for meIOStreamWrite function
+ ================================================================*/
+
+#define ME_WRITE_MODE_BLOCKING 0x00110001
+#define ME_WRITE_MODE_NONBLOCKING 0x00110002
+#define ME_WRITE_MODE_PRELOAD 0x00110003
+
+#define ME_IO_STREAM_WRITE_NO_FLAGS 0x00000000
+
+/*==================================================================
+ Defines for meIOStreamStart function
+ ================================================================*/
+
+#define ME_IO_STREAM_START_NO_FLAGS 0x00000000
+
+#define ME_START_MODE_BLOCKING 0x00120001
+#define ME_START_MODE_NONBLOCKING 0x00120002
+
+#define ME_IO_STREAM_START_TYPE_NO_FLAGS 0x0
+#define ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS 0x1
+
+/*==================================================================
+ Defines for meIOStreamStop function
+ ================================================================*/
+
+#define ME_IO_STREAM_STOP_NO_FLAGS 0x00000000
+#define ME_IO_STREAM_STOP_PRESERVE_BUFFERS 0x00000001
+
+#define ME_STOP_MODE_IMMEDIATE 0x00130001
+#define ME_STOP_MODE_LAST_VALUE 0x00130002
+
+#define ME_IO_STREAM_STOP_TYPE_NO_FLAGS 0x00000000
+
+/*==================================================================
+ Defines for meIOStreamStatus function
+ ================================================================*/
+
+#define ME_WAIT_NONE 0x00140001
+#define ME_WAIT_IDLE 0x00140002
+
+#define ME_STATUS_INVALID 0x00000000
+#define ME_STATUS_IDLE 0x00150001
+#define ME_STATUS_BUSY 0x00150002
+#define ME_STATUS_ERROR 0x00150003
+
+#define ME_IO_STREAM_STATUS_NO_FLAGS 0x00000000
+
+/*==================================================================
+ Defines for meIOStreamSetCallbacks function
+ ================================================================*/
+
+#define ME_IO_STREAM_SET_CALLBACKS_NO_FLAGS 0x00000000
+
+/*==================================================================
+ Defines for meIOStreamNewValues function
+ ================================================================*/
+
+#define ME_IO_STREAM_NEW_VALUES_NO_FLAGS 0x00000000
+
+/*==================================================================
+ Defines for meIOTimeToTicks function
+ ================================================================*/
+
+#define ME_IO_STREAM_TIME_TO_TICKS_NO_FLAGS 0x00000000
+
+/*==================================================================
+ Defines for module types
+ ================================================================*/
+
+#define ME_MODULE_TYPE_MULTISIG_NONE 0x00000000
+#define ME_MODULE_TYPE_MULTISIG_DIFF16_10V 0x00160001
+#define ME_MODULE_TYPE_MULTISIG_DIFF16_20V 0x00160002
+#define ME_MODULE_TYPE_MULTISIG_DIFF16_50V 0x00160003
+#define ME_MODULE_TYPE_MULTISIG_CURRENT16_0_20MA 0x00160004
+#define ME_MODULE_TYPE_MULTISIG_RTD8_PT100 0x00160005
+#define ME_MODULE_TYPE_MULTISIG_RTD8_PT500 0x00160006
+#define ME_MODULE_TYPE_MULTISIG_RTD8_PT1000 0x00160007
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_B 0x00160008
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_E 0x00160009
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_J 0x0016000A
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_K 0x0016000B
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_N 0x0016000C
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_R 0x0016000D
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_S 0x0016000E
+#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_T 0x0016000F
+#define ME_MODULE_TYPE_MULTISIG_TE8_TEMP_SENSOR 0x00160010
+
+/*==================================================================
+ Defines for meQuerySubdeviceCaps function
+ ================================================================*/
+
+#define ME_CAPS_NONE 0x00000000
+
+#define ME_CAPS_DIO_DIR_BIT 0x00000001
+#define ME_CAPS_DIO_DIR_BYTE 0x00000002
+#define ME_CAPS_DIO_DIR_WORD 0x00000004
+#define ME_CAPS_DIO_DIR_DWORD 0x00000008
+#define ME_CAPS_DIO_SINK_SOURCE 0x00000010
+#define ME_CAPS_DIO_BIT_PATTERN_IRQ 0x00000020
+#define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_RISING 0x00000040
+#define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_FALLING 0x00000080
+#define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY 0x00000100
+#define ME_CAPS_DIO_OVER_TEMP_IRQ 0x00000200
+
+#define ME_CAPS_CTR_CLK_PREVIOUS 0x00000001
+#define ME_CAPS_CTR_CLK_INTERNAL_1MHZ 0x00000002
+#define ME_CAPS_CTR_CLK_INTERNAL_10MHZ 0x00000004
+#define ME_CAPS_CTR_CLK_EXTERNAL 0x00000008
+
+#define ME_CAPS_AI_TRIG_SYNCHRONOUS 0x00000001
+/// @note Backward compatibility for me1600 in old style.
+#define ME_CAPS_AI_TRIG_SIMULTANEOUS ME_CAPS_AI_TRIG_SYNCHRONOUS
+#define ME_CAPS_AI_FIFO 0x00000002
+#define ME_CAPS_AI_FIFO_THRESHOLD 0x00000004
+
+#define ME_CAPS_AO_TRIG_SYNCHRONOUS 0x00000001
+/// @note Backward compatibility for me1600 in old style.
+#define ME_CAPS_AO_TRIG_SIMULTANEOUS ME_CAPS_AO_TRIG_SYNCHRONOUS
+#define ME_CAPS_AO_FIFO 0x00000002
+#define ME_CAPS_AO_FIFO_THRESHOLD 0x00000004
+
+#define ME_CAPS_EXT_IRQ_EDGE_RISING 0x00000001
+#define ME_CAPS_EXT_IRQ_EDGE_FALLING 0x00000002
+#define ME_CAPS_EXT_IRQ_EDGE_ANY 0x00000004
+
+/*==================================================================
+ Defines for meQuerySubdeviceCapsArgs function
+ ================================================================*/
+
+#define ME_CAP_AI_FIFO_SIZE 0x001D0000
+#define ME_CAP_AI_BUFFER_SIZE 0x001D0001
+
+#define ME_CAP_AO_FIFO_SIZE 0x001F0000
+#define ME_CAP_AO_BUFFER_SIZE 0x001F0001
+
+#define ME_CAP_CTR_WIDTH 0x00200000
+
+/*==================================================================
+ Defines common to query functions
+ ================================================================*/
+
+#define ME_UNIT_INVALID 0x00000000
+#define ME_UNIT_VOLT 0x00170001
+#define ME_UNIT_AMPERE 0x00170002
+#define ME_UNIT_ANY 0x00170003
+
+#define ME_TYPE_INVALID 0x00000000
+#define ME_TYPE_AO 0x00180001
+#define ME_TYPE_AI 0x00180002
+#define ME_TYPE_DIO 0x00180003
+#define ME_TYPE_DO 0x00180004
+#define ME_TYPE_DI 0x00180005
+#define ME_TYPE_CTR 0x00180006
+#define ME_TYPE_EXT_IRQ 0x00180007
+
+#define ME_SUBTYPE_INVALID 0x00000000
+#define ME_SUBTYPE_SINGLE 0x00190001
+#define ME_SUBTYPE_STREAMING 0x00190002
+#define ME_SUBTYPE_CTR_8254 0x00190003
+#define ME_SUBTYPE_ANY 0x00190004
+
+#define ME_DEVICE_DRIVER_NAME_MAX_COUNT 64
+#define ME_DEVICE_NAME_MAX_COUNT 64
+
+#define ME_DEVICE_DESCRIPTION_MAX_COUNT 256
+
+#define ME_BUS_TYPE_INVALID 0x00000000
+#define ME_BUS_TYPE_PCI 0x001A0001
+#define ME_BUS_TYPE_USB 0x001A0002
+
+#define ME_PLUGGED_INVALID 0x00000000
+#define ME_PLUGGED_IN 0x001B0001
+#define ME_PLUGGED_OUT 0x001B0002
+
+#define ME_EXTENSION_TYPE_INVALID 0x00000000
+#define ME_EXTENSION_TYPE_NONE 0x001C0001
+#define ME_EXTENSION_TYPE_MUX32M 0x001C0002
+#define ME_EXTENSION_TYPE_DEMUX32 0x001C0003
+#define ME_EXTENSION_TYPE_MUX32S 0x001C0004
+
+#define ME_ACCESS_TYPE_INVALID 0x00000000
+#define ME_ACCESS_TYPE_LOCAL 0x001D0001
+#define ME_ACCESS_TYPE_REMOTE 0x001D0002
+
+/// @note Add by KG
+
+/*==================================================================
+ Defines for meUtilityPWM
+ ================================================================*/
+#define ME_PWM_START_CONNECT_INTERNAL 0x00200001
+
+/* Flags for SingleConfig channels configure */
+#define ME_SINGLE_CHANNEL_NOT_CONFIGURED 0x00
+#define ME_SINGLE_CHANNEL_CONFIGURED 0x01
+
+/* Define if configuration should be downloaded to driver */
+#define ME_CONFIG_LOAD_NO_FLAGS 0x0
+#define ME_CONFIG_LOAD_TO_DRIVER 0x1
+
+#endif
diff --git a/drivers/staging/meilhaus/medevice.c b/drivers/staging/meilhaus/medevice.c
new file mode 100644
index 000000000000..8f62e16c7a37
--- /dev/null
+++ b/drivers/staging/meilhaus/medevice.c
@@ -0,0 +1,1740 @@
+/**
+ * @file medevice.c
+ *
+ * @brief Meilhaus device base class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "mecommon.h"
+#include "meinternal.h"
+#include "medefines.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "medevice.h"
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+static int me_device_io_irq_start(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_irq_start(s,
+ filep,
+ channel,
+ irq_source,
+ irq_edge, irq_arg, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_irq_wait(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_irq_wait(s,
+ filep,
+ channel,
+ irq_count,
+ value, time_out, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_irq_stop(struct me_device *device,
+ struct file *filep,
+ int subdevice, int channel, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_irq_stop(s, filep, channel, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_reset_device(struct me_device *device,
+ struct file *filep, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+ int i, n;
+
+ PDEBUG("executed.\n");
+
+ /* Get the number of subdevices. */
+ n = me_slist_get_number_subdevices(&device->slist);
+
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+
+ /* Reset every subdevice in list. */
+ for (i = 0; i < n; i++) {
+ s = me_slist_get_subdevice(&device->slist, i);
+ err = s->me_subdevice_io_reset_subdevice(s, filep, flags);
+
+ if (err) {
+ PERROR("Cannot reset subdevice.\n");
+ break;
+ }
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_reset_subdevice(struct me_device *device,
+ struct file *filep,
+ int subdevice, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_reset_subdevice(s, filep, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_single_config(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_single_config(s,
+ filep,
+ channel,
+ single_config,
+ ref,
+ trig_chan,
+ trig_type,
+ trig_edge, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_single_read(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_single_read(s,
+ filep,
+ channel,
+ value, time_out, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_single_write(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int value, int time_out, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_single_write(s,
+ filep,
+ channel,
+ value, time_out, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_stream_config(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_stream_config(s,
+ filep,
+ config_list,
+ count,
+ trigger,
+ fifo_irq_threshold,
+ flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_stream_new_values(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int time_out, int *count, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_stream_new_values(s,
+ filep,
+ time_out,
+ count, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_stream_read(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int read_mode,
+ int *values, int *count, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_stream_read(s,
+ filep,
+ read_mode,
+ values, count, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_stream_start(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int start_mode, int time_out, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_stream_start(s,
+ filep,
+ start_mode,
+ time_out, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_stream_status(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int wait,
+ int *status, int *count, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_stream_status(s,
+ filep,
+ wait,
+ status, count, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_stream_stop(struct me_device *device,
+ struct file *filep,
+ int subdevice, int stop_mode, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_stream_stop(s,
+ filep, stop_mode, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_io_stream_write(struct me_device *device,
+ struct file *filep,
+ int subdevice,
+ int write_mode,
+ int *values, int *count, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_io_stream_write(s,
+ filep,
+ write_mode,
+ values, count, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_lock_device(struct me_device *device,
+ struct file *filep, int lock, int flags)
+{
+ PDEBUG("executed.\n");
+
+ return me_dlock_lock(&device->dlock,
+ filep, lock, flags, &device->slist);
+}
+
+static int me_device_lock_subdevice(struct me_device *device,
+ struct file *filep,
+ int subdevice, int lock, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Enter device.
+ err = me_dlock_enter(&device->dlock, filep);
+
+ if (err) {
+ PERROR("Cannot enter device.\n");
+ return err;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_lock_subdevice(s, filep, lock, flags);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ // Exit device.
+ me_dlock_exit(&device->dlock, filep);
+
+ return err;
+}
+
+static int me_device_query_description_device(struct me_device *device,
+ char **description)
+{
+ PDEBUG("executed.\n");
+ *description = device->device_description;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me_device_query_info_device(struct me_device *device,
+ int *vendor_id,
+ int *device_id,
+ int *serial_no,
+ int *bus_type,
+ int *bus_no,
+ int *dev_no, int *func_no, int *plugged)
+{
+ PDEBUG("executed.\n");
+
+ if (device->bus_type == ME_BUS_TYPE_PCI) {
+ *vendor_id = device->info.pci.vendor_id;
+ *device_id = device->info.pci.device_id;
+ *serial_no = device->info.pci.serial_no;
+ *bus_type = ME_BUS_TYPE_PCI;
+ *bus_no = device->info.pci.pci_bus_no;
+ *dev_no = device->info.pci.pci_dev_no;
+ *func_no = device->info.pci.pci_func_no;
+ *plugged = ME_PLUGGED_IN;
+ } else {
+ *plugged = ME_PLUGGED_OUT;
+ }
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me_device_query_name_device(struct me_device *device, char **name)
+{
+ PDEBUG("executed.\n");
+ *name = device->device_name;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me_device_query_name_device_driver(struct me_device *device,
+ char **name)
+{
+ PDEBUG("executed.\n");
+ *name = device->driver_name;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me_device_query_number_subdevices(struct me_device *device,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ return me_slist_query_number_subdevices(&device->slist, number);
+}
+
+static int me_device_query_number_channels(struct me_device *device,
+ int subdevice, int *number)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_number_channels(s, number);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_number_ranges(struct me_device *device,
+ int subdevice, int unit, int *count)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_number_ranges(s, unit, count);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_range_by_min_max(struct me_device *device,
+ int subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_range_by_min_max(s,
+ unit,
+ min,
+ max,
+ maxdata, range);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_range_info(struct me_device *device,
+ int subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_range_info(s,
+ range,
+ unit, min, max, maxdata);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_subdevice_by_type(struct me_device *device,
+ int start_subdevice,
+ int type,
+ int subtype, int *subdevice)
+{
+ PDEBUG("executed.\n");
+
+ return me_slist_get_subdevice_by_type(&device->slist,
+ start_subdevice,
+ type, subtype, subdevice);
+}
+
+static int me_device_query_subdevice_type(struct me_device *device,
+ int subdevice,
+ int *type, int *subtype)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_subdevice_type(s, type, subtype);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_subdevice_caps(struct me_device *device,
+ int subdevice, int *caps)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_subdevice_caps(s, caps);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_subdevice_caps_args(struct me_device *device,
+ int subdevice,
+ int cap, int *args, int count)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_subdevice_caps_args(s,
+ cap,
+ args, count);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_timer(struct me_device *device,
+ int subdevice,
+ int timer,
+ int *base_frequency,
+ uint64_t * min_ticks, uint64_t * max_ticks)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_subdevice_t *s;
+
+ PDEBUG("executed.\n");
+
+ // Check subdevice index.
+
+ if (subdevice >= me_slist_get_number_subdevices(&device->slist)) {
+ PERROR("Invalid subdevice.\n");
+ return ME_ERRNO_INVALID_SUBDEVICE;
+ }
+ // Get subdevice instance.
+ s = me_slist_get_subdevice(&device->slist, subdevice);
+
+ if (s) {
+ // Call subdevice method.
+ err = s->me_subdevice_query_timer(s,
+ timer,
+ base_frequency,
+ min_ticks, max_ticks);
+ } else {
+ // Something really bad happened.
+ PERROR("Cannot get subdevice instance.\n");
+ err = ME_ERRNO_INTERNAL;
+ }
+
+ return err;
+}
+
+static int me_device_query_version_device_driver(struct me_device *device,
+ int *version)
+/** @todo Versions shold be read from driver. I must overwrite this function in each module. Here should be returned an error!
+*/
+{
+ PDEBUG("executed.\n");
+ *version = ME_VERSION_DRIVER;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me_device_config_load(struct me_device *device, struct file *filep,
+ me_cfg_device_entry_t * config)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_SUCCESS; //If no need for config return success.
+// return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static void me_device_destructor(me_device_t * me_device)
+{
+ PDEBUG("executed.\n");
+ me_device_deinit(me_device);
+ kfree(me_device);
+}
+
+/* //me_device_usb_init
+int me_device_usb_init(me_device_t *me_device, struct usb_interface *interface)
+{
+ PDEBUG("executed.\n");
+ return -1;
+}
+*/
+
+static int get_device_descriptions(uint16_t device_id,
+ char **device_name,
+ char **device_description,
+ char **driver_name)
+/** @todo This is wrong concept! Static table has too strong limitations!
+* 'device_name' and 'driver_name' should be calculated from 'device_id'
+* 'device_description' should be read from device or moved to user space and handled by library!
+*/
+{
+ PDEBUG("executed.\n");
+
+ switch (device_id) {
+ case PCI_DEVICE_ID_MEILHAUS_ME1000:
+ case PCI_DEVICE_ID_MEILHAUS_ME1000_A:
+ case PCI_DEVICE_ID_MEILHAUS_ME1000_B:
+ *device_name = ME1000_NAME_DEVICE_ME1000;
+ *device_description = ME1000_DESCRIPTION_DEVICE_ME1000;
+ *driver_name = ME1000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1400:
+ *device_name = ME1400_NAME_DEVICE_ME1400;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140A:
+ *device_name = ME1400_NAME_DEVICE_ME1400A;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400A;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140B:
+ *device_name = ME1400_NAME_DEVICE_ME1400B;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400B;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14E0:
+ *device_name = ME1400_NAME_DEVICE_ME1400E;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400E;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14EA:
+ *device_name = ME1400_NAME_DEVICE_ME1400EA;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400EA;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14EB:
+ *device_name = ME1400_NAME_DEVICE_ME1400EB;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400EB;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ *device_name = ME1400_NAME_DEVICE_ME1400C;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400C;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ *device_name = ME1400_NAME_DEVICE_ME1400D;
+ *device_description = ME1400_DESCRIPTION_DEVICE_ME1400D;
+ *driver_name = ME1400_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_4U:
+ *device_name = ME1600_NAME_DEVICE_ME16004U;
+ *device_description = ME1600_DESCRIPTION_DEVICE_ME16004U;
+ *driver_name = ME1600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_8U:
+ *device_name = ME1600_NAME_DEVICE_ME16008U;
+ *device_description = ME1600_DESCRIPTION_DEVICE_ME16008U;
+ *driver_name = ME1600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_12U:
+ *device_name = ME1600_NAME_DEVICE_ME160012U;
+ *device_description = ME1600_DESCRIPTION_DEVICE_ME160012U;
+ *driver_name = ME1600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_16U:
+ *device_name = ME1600_NAME_DEVICE_ME160016U;
+ *device_description = ME1600_DESCRIPTION_DEVICE_ME160016U;
+ *driver_name = ME1600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I:
+ *device_name = ME1600_NAME_DEVICE_ME160016U8I;
+ *device_description = ME1600_DESCRIPTION_DEVICE_ME160016U8I;
+ *driver_name = ME1600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4610:
+ *device_name = ME4600_NAME_DEVICE_ME4610;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4610;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4650:
+ *device_name = ME4600_NAME_DEVICE_ME4650;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4650;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660:
+ *device_name = ME4600_NAME_DEVICE_ME4660;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4660;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660I:
+ *device_name = ME4600_NAME_DEVICE_ME4660I;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4660I;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660S:
+ *device_name = ME4600_NAME_DEVICE_ME4660S;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4660S;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
+ *device_name = ME4600_NAME_DEVICE_ME4660IS;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4660IS;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670:
+ *device_name = ME4600_NAME_DEVICE_ME4670;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4670;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670I:
+ *device_name = ME4600_NAME_DEVICE_ME4670I;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4670I;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670S:
+ *device_name = ME4600_NAME_DEVICE_ME4670S;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4670S;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
+ *device_name = ME4600_NAME_DEVICE_ME4670IS;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4670IS;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680:
+ *device_name = ME4600_NAME_DEVICE_ME4680;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4680;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680I:
+ *device_name = ME4600_NAME_DEVICE_ME4680I;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4680I;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680S:
+ *device_name = ME4600_NAME_DEVICE_ME4680S;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4680S;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
+ *device_name = ME4600_NAME_DEVICE_ME4680IS;
+ *device_description = ME4600_DESCRIPTION_DEVICE_ME4680IS;
+ *driver_name = ME4600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6004:
+ *device_name = ME6000_NAME_DEVICE_ME60004;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME60004;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6008:
+ *device_name = ME6000_NAME_DEVICE_ME60008;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME60008;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME600F:
+ *device_name = ME6000_NAME_DEVICE_ME600016;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME600016;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6014:
+ *device_name = ME6000_NAME_DEVICE_ME6000I4;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I4;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6018:
+ *device_name = ME6000_NAME_DEVICE_ME6000I8;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I8;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME601F:
+ *device_name = ME6000_NAME_DEVICE_ME6000I16;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I16;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6034:
+ *device_name = ME6000_NAME_DEVICE_ME6000ISLE4;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6038:
+ *device_name = ME6000_NAME_DEVICE_ME6000ISLE8;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME603F:
+ *device_name = ME6000_NAME_DEVICE_ME6000ISLE16;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6104:
+ *device_name = ME6000_NAME_DEVICE_ME61004;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME61004;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6108:
+ *device_name = ME6000_NAME_DEVICE_ME61008;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME61008;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME610F:
+ *device_name = ME6000_NAME_DEVICE_ME610016;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME610016;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6114:
+ *device_name = ME6000_NAME_DEVICE_ME6100I4;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I4;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6118:
+ *device_name = ME6000_NAME_DEVICE_ME6100I8;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I8;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME611F:
+ *device_name = ME6000_NAME_DEVICE_ME6100I16;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I16;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6134:
+ *device_name = ME6000_NAME_DEVICE_ME6100ISLE4;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6138:
+ *device_name = ME6000_NAME_DEVICE_ME6100ISLE8;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME613F:
+ *device_name = ME6000_NAME_DEVICE_ME6100ISLE16;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6044:
+ *device_name = ME6000_NAME_DEVICE_ME60004DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME60004DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6048:
+ *device_name = ME6000_NAME_DEVICE_ME60008DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME60008DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME604F:
+ *device_name = ME6000_NAME_DEVICE_ME600016DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME600016DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6054:
+ *device_name = ME6000_NAME_DEVICE_ME6000I4DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I4DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6058:
+ *device_name = ME6000_NAME_DEVICE_ME6000I8DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I8DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME605F:
+ *device_name = ME6000_NAME_DEVICE_ME6000I16DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I16DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6074:
+ *device_name = ME6000_NAME_DEVICE_ME6000ISLE4DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6078:
+ *device_name = ME6000_NAME_DEVICE_ME6000ISLE8DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME607F:
+ *device_name = ME6000_NAME_DEVICE_ME6000ISLE16DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6144:
+ *device_name = ME6000_NAME_DEVICE_ME61004DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME61004DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6148:
+ *device_name = ME6000_NAME_DEVICE_ME61008DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME61008DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME614F:
+ *device_name = ME6000_NAME_DEVICE_ME610016DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME610016DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6154:
+ *device_name = ME6000_NAME_DEVICE_ME6100I4DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I4DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6158:
+ *device_name = ME6000_NAME_DEVICE_ME6100I8DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I8DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME615F:
+ *device_name = ME6000_NAME_DEVICE_ME6100I16DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I16DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6174:
+ *device_name = ME6000_NAME_DEVICE_ME6100ISLE4DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6178:
+ *device_name = ME6000_NAME_DEVICE_ME6100ISLE8DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME617F:
+ *device_name = ME6000_NAME_DEVICE_ME6100ISLE16DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6259:
+ *device_name = ME6000_NAME_DEVICE_ME6200I9DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6200I9DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6359:
+ *device_name = ME6000_NAME_DEVICE_ME6300I9DIO;
+ *device_description = ME6000_DESCRIPTION_DEVICE_ME6300I9DIO;
+ *driver_name = ME6000_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0630:
+ *device_name = ME0600_NAME_DEVICE_ME0630;
+ *device_description = ME0600_DESCRIPTION_DEVICE_ME0630;
+ *driver_name = ME0600_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
+ *device_name = ME8100_NAME_DEVICE_ME8100A;
+ *device_description = ME8100_DESCRIPTION_DEVICE_ME8100A;
+ *driver_name = ME8100_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
+ *device_name = ME8100_NAME_DEVICE_ME8100B;
+ *device_description = ME8100_DESCRIPTION_DEVICE_ME8100B;
+ *driver_name = ME8100_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8200_A:
+ *device_name = ME8200_NAME_DEVICE_ME8200A;
+ *device_description = ME8200_DESCRIPTION_DEVICE_ME8200A;
+ *driver_name = ME8200_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8200_B:
+ *device_name = ME8200_NAME_DEVICE_ME8200B;
+ *device_description = ME8200_DESCRIPTION_DEVICE_ME8200B;
+ *driver_name = ME8200_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0940:
+ *device_name = ME0900_NAME_DEVICE_ME0940;
+ *device_description = ME0900_DESCRIPTION_DEVICE_ME0940;
+ *driver_name = ME0900_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0950:
+ *device_name = ME0900_NAME_DEVICE_ME0950;
+ *device_description = ME0900_DESCRIPTION_DEVICE_ME0950;
+ *driver_name = ME0900_NAME_DRIVER;
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0960:
+ *device_name = ME0900_NAME_DEVICE_ME0960;
+ *device_description = ME0900_DESCRIPTION_DEVICE_ME0960;
+ *driver_name = ME0900_NAME_DRIVER;
+ break;
+/*
+ case USB_DEVICE_ID_MEPHISTO_S1:
+ *device_name = MEPHISTO_S1_NAME_DEVICE;
+ *device_description = MEPHISTO_S1_DESCRIPTION_DEVICE;
+ *driver_name = MEPHISTO_S1_NAME_DRIVER;
+ break;
+*/
+ default:
+ *device_name = EMPTY_NAME_DEVICE;
+ *device_description = EMPTY_DESCRIPTION_DEVICE;
+ *driver_name = EMPTY_NAME_DRIVER;
+
+ PERROR("Invalid device id.\n");
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int me_device_pci_init(me_device_t * me_device, struct pci_dev *pci_device)
+{
+ int err;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Initialize device list head.
+ INIT_LIST_HEAD(&me_device->list);
+
+ // Initialize device description strings.
+ err = get_device_descriptions(pci_device->device,
+ &me_device->device_name,
+ &me_device->device_description,
+ &me_device->driver_name);
+
+ if (err) {
+ PERROR("Cannot initialize device description strings.\n");
+ return 1;
+ }
+ // Enable the pci device.
+ err = pci_enable_device(pci_device);
+
+ if (err < 0) {
+ PERROR("Cannot enable PCI device.\n");
+ return 1;
+ }
+ // Request the PCI register regions.
+ err = pci_request_regions(pci_device, me_device->device_name);
+
+ if (err < 0) {
+ PERROR("Cannot request PCI regions.\n");
+ goto ERROR_0;
+ }
+ // The bus carrying the device is a PCI bus.
+ me_device->bus_type = ME_BUS_TYPE_PCI;
+
+ // Store the PCI information for later usage.
+ me_device->info.pci.pci_device = pci_device;
+
+ // Get PCI register bases and sizes.
+ for (i = 0; i < 6; i++) {
+ me_device->info.pci.reg_bases[i] =
+ pci_resource_start(pci_device, i);
+ me_device->info.pci.reg_sizes[i] =
+ pci_resource_len(pci_device, i);
+ }
+
+ // Get the PCI location.
+ me_device->info.pci.pci_bus_no = pci_device->bus->number;
+ me_device->info.pci.pci_dev_no = PCI_SLOT(pci_device->devfn);
+ me_device->info.pci.pci_func_no = PCI_FUNC(pci_device->devfn);
+
+ // Get Meilhaus specific device information.
+ me_device->info.pci.vendor_id = pci_device->vendor;
+ me_device->info.pci.device_id = pci_device->device;
+ pci_read_config_byte(pci_device, 0x08,
+ &me_device->info.pci.hw_revision);
+ pci_read_config_dword(pci_device, 0x2C, &me_device->info.pci.serial_no);
+
+ // Get the interrupt request number.
+ me_device->irq = pci_device->irq;
+
+ // Initialize device lock instance.
+ err = me_dlock_init(&me_device->dlock);
+
+ if (err) {
+ PERROR("Cannot initialize device lock instance.\n");
+ goto ERROR_1;
+ }
+ // Initialize subdevice list instance.
+ me_slist_init(&me_device->slist);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice list instance.\n");
+ goto ERROR_2;
+ }
+ // Initialize method pointers.
+ me_device->me_device_io_irq_start = me_device_io_irq_start;
+ me_device->me_device_io_irq_wait = me_device_io_irq_wait;
+ me_device->me_device_io_irq_stop = me_device_io_irq_stop;
+ me_device->me_device_io_reset_device = me_device_io_reset_device;
+ me_device->me_device_io_reset_subdevice = me_device_io_reset_subdevice;
+ me_device->me_device_io_single_config = me_device_io_single_config;
+ me_device->me_device_io_single_read = me_device_io_single_read;
+ me_device->me_device_io_single_write = me_device_io_single_write;
+ me_device->me_device_io_stream_config = me_device_io_stream_config;
+ me_device->me_device_io_stream_new_values =
+ me_device_io_stream_new_values;
+ me_device->me_device_io_stream_read = me_device_io_stream_read;
+ me_device->me_device_io_stream_start = me_device_io_stream_start;
+ me_device->me_device_io_stream_status = me_device_io_stream_status;
+ me_device->me_device_io_stream_stop = me_device_io_stream_stop;
+ me_device->me_device_io_stream_write = me_device_io_stream_write;
+ me_device->me_device_lock_device = me_device_lock_device;
+ me_device->me_device_lock_subdevice = me_device_lock_subdevice;
+ me_device->me_device_query_description_device =
+ me_device_query_description_device;
+ me_device->me_device_query_info_device = me_device_query_info_device;
+ me_device->me_device_query_name_device = me_device_query_name_device;
+ me_device->me_device_query_name_device_driver =
+ me_device_query_name_device_driver;
+ me_device->me_device_query_number_subdevices =
+ me_device_query_number_subdevices;
+ me_device->me_device_query_number_channels =
+ me_device_query_number_channels;
+ me_device->me_device_query_number_ranges =
+ me_device_query_number_ranges;
+ me_device->me_device_query_range_by_min_max =
+ me_device_query_range_by_min_max;
+ me_device->me_device_query_range_info = me_device_query_range_info;
+ me_device->me_device_query_subdevice_by_type =
+ me_device_query_subdevice_by_type;
+ me_device->me_device_query_subdevice_type =
+ me_device_query_subdevice_type;
+ me_device->me_device_query_subdevice_caps =
+ me_device_query_subdevice_caps;
+ me_device->me_device_query_subdevice_caps_args =
+ me_device_query_subdevice_caps_args;
+ me_device->me_device_query_timer = me_device_query_timer;
+ me_device->me_device_query_version_device_driver =
+ me_device_query_version_device_driver;
+ me_device->me_device_config_load = me_device_config_load;
+ me_device->me_device_destructor = me_device_destructor;
+
+ return 0;
+
+ ERROR_0:
+ me_dlock_deinit(&me_device->dlock);
+
+ ERROR_1:
+ pci_release_regions(pci_device);
+
+ ERROR_2:
+ pci_disable_device(pci_device);
+
+ return 1;
+}
+
+void me_device_deinit(me_device_t * me_device)
+{
+ PDEBUG("executed.\n");
+
+ me_slist_deinit(&me_device->slist);
+ me_dlock_deinit(&me_device->dlock);
+
+ if (me_device->bus_type == ME_BUS_TYPE_PCI) {
+ pci_release_regions(me_device->info.pci.pci_device);
+ pci_disable_device(me_device->info.pci.pci_device);
+ }
+/*
+ else
+ {
+ // Must be an USB device.
+ }
+*/
+}
diff --git a/drivers/staging/meilhaus/medevice.h b/drivers/staging/meilhaus/medevice.h
new file mode 100644
index 000000000000..25da82883e1f
--- /dev/null
+++ b/drivers/staging/meilhaus/medevice.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : medevice.h
+ * Author : GG (Guenter Gebhardt) <support@meilhaus.de>
+ */
+
+#ifndef _MEDEVICE_H_
+#define _MEDEVICE_H_
+
+#ifndef KBUILD_MODNAME
+# define KBUILD_MODNAME KBUILD_STR(memain)
+#endif
+
+#include <linux/pci.h>
+//#include <linux/usb.h>
+#include <linux/fs.h>
+#include <linux/spinlock.h>
+
+#include "metypes.h"
+#include "meslist.h"
+#include "medlock.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Defines a pointer type to a PCI constructor function.
+ */
+typedef struct me_device *(*me_pci_constructor_t) (struct pci_dev *);
+
+/**
+ * @brief Defines a pointer type to a ME-4000 PCI constructor function.
+ */
+#ifdef BOSCH
+typedef struct me_device *(*me_bosch_constructor_t) (struct pci_dev *,
+ int me_bosch_fw);
+#endif
+
+/**
+ * @brief Defines a pointer type to a USB constructor function.
+ */
+//typedef struct me_device *(*me_usb_constructor_t)(struct usb_interface *);
+
+/**
+ * @brief Defines a pointer type to the dummy constructor function.
+ */
+typedef struct me_device *(*me_dummy_constructor_t) (unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned int serial_no,
+ int bus_type,
+ int bus_no,
+ int dev_no, int func_no);
+
+//extern me_usb_constructor_t mephisto_s1_constructor __attribute__ ((weak));
+
+/**
+ * @brief Holds the PCI device information.
+ */
+typedef struct me_pci_info {
+ struct pci_dev *pci_device; /**< Kernel PCI device structure. */
+ uint32_t reg_bases[6]; /**< The base adresses of the PCI bars. */
+ uint32_t reg_sizes[6]; /**< The sizes of the PCI bars. */
+
+ uint32_t pci_bus_no; /**< PCI bus number. */
+ uint32_t pci_dev_no; /**< PCI device number. */
+ uint32_t pci_func_no; /**< PCI function number. */
+
+ uint16_t vendor_id; /**< Meilhaus PCI vendor id. */
+ uint16_t device_id; /**< Meilhaus device id. */
+ uint8_t hw_revision; /**< Hardware revision of the device. */
+ uint32_t serial_no; /**< Serial number of the device. */
+} me_pci_info_t;
+
+/**
+ * @brief Holds the USB device information.
+ */
+//typedef struct me_usb_info {
+//} me_usb_info_t;
+
+/**
+ * @brief The Meilhaus device base class structure.
+ */
+typedef struct me_device {
+ /* Attributes */
+ struct list_head list; /**< Enables the device to be added to a dynamic list. */
+// int magic; /**< The magic number of the structure. */
+
+ int bus_type; /**< The descriminator for the union. */
+ union {
+ me_pci_info_t pci; /**< PCI specific device information. */
+// me_usb_info_t usb; /**< USB specific device information. */
+ } info; /**< Holds the device information. */
+
+ int irq; /**< The irq assigned to this device. */
+
+ me_dlock_t dlock; /**< The device locking structure. */
+ me_slist_t slist; /**< The container holding all subdevices belonging to this device. */
+
+ char *device_name; /**< The name of the Meilhaus device. */
+ char *device_description; /**< The description of the Meilhaus device. */
+ char *driver_name; /**< The name of the device driver module supporting the device family. */
+
+ /* Methods */
+ int (*me_device_io_irq_start) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags);
+
+ int (*me_device_io_irq_wait) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags);
+
+ int (*me_device_io_irq_stop) (struct me_device * device,
+ struct file * filep,
+ int subdevice, int channel, int flags);
+
+ int (*me_device_io_reset_device) (struct me_device * device,
+ struct file * filep, int flags);
+
+ int (*me_device_io_reset_subdevice) (struct me_device * device,
+ struct file * filep,
+ int subdevice, int flags);
+
+ int (*me_device_io_single_config) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type,
+ int trig_edge, int flags);
+
+ int (*me_device_io_single_read) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int channel,
+ int *value, int time_out, int flags);
+
+ int (*me_device_io_single_write) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int channel,
+ int value, int time_out, int flags);
+
+ int (*me_device_io_stream_config) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags);
+
+ int (*me_device_io_stream_new_values) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int time_out,
+ int *count, int flags);
+
+ int (*me_device_io_stream_read) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int read_mode,
+ int *values, int *count, int flags);
+
+ int (*me_device_io_stream_start) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int start_mode,
+ int time_out, int flags);
+
+ int (*me_device_io_stream_status) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int wait,
+ int *status, int *count, int flags);
+
+ int (*me_device_io_stream_stop) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int stop_mode, int flags);
+
+ int (*me_device_io_stream_write) (struct me_device * device,
+ struct file * filep,
+ int subdevice,
+ int write_mode,
+ int *values, int *count, int flags);
+
+ int (*me_device_lock_device) (struct me_device * device,
+ struct file * filep, int lock, int flags);
+
+ int (*me_device_lock_subdevice) (struct me_device * device,
+ struct file * filep,
+ int subdevice, int lock, int flags);
+
+ int (*me_device_query_description_device) (struct me_device * device,
+ char **description);
+
+ int (*me_device_query_info_device) (struct me_device * device,
+ int *vendor_id,
+ int *device_id,
+ int *serial_no,
+ int *bus_type,
+ int *bus_no,
+ int *dev_no,
+ int *func_no, int *plugged);
+
+ int (*me_device_query_name_device) (struct me_device * device,
+ char **name);
+
+ int (*me_device_query_name_device_driver) (struct me_device * device,
+ char **name);
+
+ int (*me_device_query_number_subdevices) (struct me_device * device,
+ int *number);
+
+ int (*me_device_query_number_channels) (struct me_device * device,
+ int subdevice, int *number);
+
+ int (*me_device_query_number_ranges) (struct me_device * device,
+ int subdevice,
+ int unit, int *count);
+
+ int (*me_device_query_range_by_min_max) (struct me_device * device,
+ int subdevice,
+ int unit,
+ int *min,
+ int *max,
+ int *maxdata, int *range);
+
+ int (*me_device_query_range_info) (struct me_device * device,
+ int subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata);
+
+ int (*me_device_query_subdevice_by_type) (struct me_device * device,
+ int start_subdevice,
+ int type,
+ int subtype, int *subdevice);
+
+ int (*me_device_query_subdevice_type) (struct me_device * device,
+ int subdevice,
+ int *type, int *subtype);
+
+ int (*me_device_query_subdevice_caps) (struct me_device * device,
+ int subdevice, int *caps);
+
+ int (*me_device_query_subdevice_caps_args) (struct me_device * device,
+ int subdevice,
+ int cap,
+ int *args, int count);
+
+ int (*me_device_query_timer) (struct me_device * device,
+ int subdevice,
+ int timer,
+ int *base_frequency,
+ uint64_t * min_ticks,
+ uint64_t * max_ticks);
+
+ int (*me_device_query_version_device_driver) (struct me_device * device,
+ int *version);
+
+ int (*me_device_config_load) (struct me_device * device,
+ struct file * filep,
+ me_cfg_device_entry_t * config);
+
+ void (*me_device_destructor) (struct me_device * device);
+} me_device_t;
+
+/**
+ * @brief Initializes a PCI device base class structure.
+ *
+ * @param pci_device The PCI device context as handed over by kernel.
+ *
+ * @return 0 on success.
+ */
+int me_device_pci_init(me_device_t * me_device, struct pci_dev *pci_device);
+
+/**
+ * @brief Initializes a USB device base class structure.
+ *
+ * @param usb_interface The USB device interface as handed over by kernel.
+ *
+ * @return 0 on success.
+ */
+//int me_device_usb_init(me_device_t *me_device, struct usb_interface *interface);
+
+/**
+ * @brief Deinitializes a device base class structure and frees any previously
+ * requested resources related with this structure. It also frees any subdevice
+ * instance hold by the subdevice list.
+ *
+ * @param me_device The device class to deinitialize.
+ */
+void me_device_deinit(me_device_t * me_device);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/medlist.c b/drivers/staging/meilhaus/medlist.c
new file mode 100644
index 000000000000..ef4e36955dc8
--- /dev/null
+++ b/drivers/staging/meilhaus/medlist.c
@@ -0,0 +1,127 @@
+/**
+ * @file me_dlist.c
+ *
+ * @brief Implements the device list class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "meerror.h"
+#include "medefines.h"
+
+#include "medlist.h"
+#include "medebug.h"
+
+int me_dlist_query_number_devices(struct me_dlist *dlist, int *number)
+{
+ PDEBUG_LOCKS("called.\n");
+ *number = dlist->n;
+ return ME_ERRNO_SUCCESS;
+}
+
+unsigned int me_dlist_get_number_devices(struct me_dlist *dlist)
+{
+ PDEBUG_LOCKS("called.\n");
+ return dlist->n;
+}
+
+me_device_t *me_dlist_get_device(struct me_dlist * dlist, unsigned int index)
+{
+
+ struct list_head *pos;
+ me_device_t *device = NULL;
+ unsigned int i = 0;
+
+ PDEBUG_LOCKS("called.\n");
+
+ if (index >= dlist->n) {
+ PERROR("Index out of range.\n");
+ return NULL;
+ }
+
+ list_for_each(pos, &dlist->head) {
+ if (i == index) {
+ device = list_entry(pos, me_device_t, list);
+ break;
+ }
+
+ ++i;
+ }
+
+ return device;
+}
+
+void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t * device)
+{
+ PDEBUG_LOCKS("called.\n");
+
+ list_add_tail(&device->list, &dlist->head);
+ ++dlist->n;
+}
+
+me_device_t *me_dlist_del_device_tail(struct me_dlist *dlist)
+{
+
+ struct list_head *last;
+ me_device_t *device;
+
+ PDEBUG_LOCKS("called.\n");
+
+ if (list_empty(&dlist->head))
+ return NULL;
+
+ last = dlist->head.prev;
+
+ device = list_entry(last, me_device_t, list);
+
+ list_del(last);
+
+ --dlist->n;
+
+ return device;
+}
+
+int me_dlist_init(me_dlist_t * dlist)
+{
+ PDEBUG_LOCKS("called.\n");
+
+ INIT_LIST_HEAD(&dlist->head);
+ dlist->n = 0;
+ return 0;
+}
+
+void me_dlist_deinit(me_dlist_t * dlist)
+{
+
+ struct list_head *s;
+ me_device_t *device;
+
+ PDEBUG_LOCKS("called.\n");
+
+ while (!list_empty(&dlist->head)) {
+ s = dlist->head.next;
+ list_del(s);
+ device = list_entry(s, me_device_t, list);
+ device->me_device_destructor(device);
+ }
+
+ dlist->n = 0;
+}
diff --git a/drivers/staging/meilhaus/medlist.h b/drivers/staging/meilhaus/medlist.h
new file mode 100644
index 000000000000..091c11e48ed2
--- /dev/null
+++ b/drivers/staging/meilhaus/medlist.h
@@ -0,0 +1,91 @@
+/**
+ * @file me_dlist.h
+ *
+ * @brief Provides the device list class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME_DLIST_H_
+#define _ME_DLIST_H_
+
+#include <linux/list.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The device list container.
+ */
+typedef struct me_dlist {
+ struct list_head head; /**< The head of the internal list. */
+ unsigned int n; /**< The number of devices in the list. */
+} me_dlist_t;
+
+/**
+ * @brief Queries the number of devices currently inside the list.
+ *
+ * @param dlist The device list to query.
+ * @param[out] number The number of devices.
+ *
+ * @return ME-iDS error code.
+ */
+int me_dlist_query_number_devices(struct me_dlist *dlist, int *number);
+
+/**
+ * @brief Returns the number of devices currently inside the list.
+ *
+ * @param dlist The device list to query.
+ *
+ * @return The number of devices in the list.
+ */
+unsigned int me_dlist_get_number_devices(struct me_dlist *dlist);
+
+/**
+ * @brief Get a device by index.
+ *
+ * @param dlist The device list to query.
+ * @param index The index of the device to get in the list.
+ *
+ * @return The device at index if available.\n
+ * NULL if the index is out of range.
+ */
+me_device_t *me_dlist_get_device(struct me_dlist *dlist, unsigned int index);
+
+/**
+ * @brief Adds a device to the tail of the list.
+ *
+ * @param dlist The device list to add a device to.
+ * @param device The device to add to the list.
+ */
+void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t * device);
+
+/**
+ * @brief Removes a device from the tail of the list.
+ *
+ * @param dlist The device list.
+ *
+ * @return Pointer to the removed subdeivce.\n
+ * NULL in cases where the list was empty.
+ */
+me_device_t *me_dlist_del_device_tail(struct me_dlist *dlist);
+
+/**
+ * @brief Initializes a device list structure.
+ *
+ * @param lock The device list structure to initialize.
+ * @return 0 on success.
+ */
+int me_dlist_init(me_dlist_t * dlist);
+
+/**
+ * @brief Deinitializes a device list structure and destructs every device in it.
+ *
+ * @param dlist The device list structure to deinitialize.
+ * @return 0 on success.
+ */
+void me_dlist_deinit(me_dlist_t * dlist);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/medlock.c b/drivers/staging/meilhaus/medlock.c
new file mode 100644
index 000000000000..f649e3da4f05
--- /dev/null
+++ b/drivers/staging/meilhaus/medlock.c
@@ -0,0 +1,195 @@
+/**
+ * @file medlock.c
+ *
+ * @brief Implements the device lock class.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/spinlock.h>
+
+#include "medefines.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "meslist.h"
+#include "mesubdevice.h"
+#include "medlock.h"
+
+int me_dlock_enter(struct me_dlock *dlock, struct file *filep)
+{
+ PDEBUG_LOCKS("executed.\n");
+
+ spin_lock(&dlock->spin_lock);
+
+ if ((dlock->filep) != NULL && (dlock->filep != filep)) {
+ PERROR("Device is locked by another process.\n");
+ spin_unlock(&dlock->spin_lock);
+ return ME_ERRNO_LOCKED;
+ }
+
+ dlock->count++;
+
+ spin_unlock(&dlock->spin_lock);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+int me_dlock_exit(struct me_dlock *dlock, struct file *filep)
+{
+ PDEBUG_LOCKS("executed.\n");
+
+ spin_lock(&dlock->spin_lock);
+ dlock->count--;
+ spin_unlock(&dlock->spin_lock);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+int me_dlock_lock(struct me_dlock *dlock,
+ struct file *filep, int lock, int flags, me_slist_t * slist)
+{
+ int err = ME_ERRNO_SUCCESS;
+ int i;
+ me_subdevice_t *subdevice;
+
+ PDEBUG_LOCKS("executed.\n");
+
+ spin_lock(&dlock->spin_lock);
+
+ switch (lock) {
+
+ case ME_LOCK_RELEASE:
+ if ((dlock->filep == filep) || (dlock->filep == NULL)) {
+ dlock->filep = NULL;
+
+ /* Unlock all possibly locked subdevices. */
+
+ for (i = 0; i < me_slist_get_number_subdevices(slist);
+ i++) {
+ subdevice = me_slist_get_subdevice(slist, i);
+
+ if (subdevice)
+ err =
+ subdevice->
+ me_subdevice_lock_subdevice
+ (subdevice, filep, ME_LOCK_RELEASE,
+ flags);
+ else
+ err = ME_ERRNO_INTERNAL;
+ }
+ }
+
+ break;
+
+ case ME_LOCK_SET:
+ if (dlock->count) {
+ PERROR("Device is used by another process.\n");
+ err = ME_ERRNO_USED;
+ } else if ((dlock->filep != NULL) && (dlock->filep != filep)) {
+ PERROR("Device is locked by another process.\n");
+ err = ME_ERRNO_LOCKED;
+ } else if (dlock->filep == NULL) {
+ /* Check any subdevice is locked by another process. */
+
+ for (i = 0; i < me_slist_get_number_subdevices(slist);
+ i++) {
+ subdevice = me_slist_get_subdevice(slist, i);
+
+ if (subdevice) {
+ if ((err =
+ subdevice->
+ me_subdevice_lock_subdevice
+ (subdevice, filep, ME_LOCK_CHECK,
+ flags))) {
+ PERROR
+ ("A subdevice is locked by another process.\n");
+ break;
+ }
+ } else {
+ err = ME_ERRNO_INTERNAL;
+ }
+ }
+
+ /* If no subdevices are locked by other processes,
+ we can take ownership of the device. Otherwise we jump ahead. */
+ if (!err)
+ dlock->filep = filep;
+ }
+
+ break;
+
+ case ME_LOCK_CHECK:
+ if (dlock->count) {
+ err = ME_ERRNO_USED;
+ } else if ((dlock->filep != NULL) && (dlock->filep != filep)) {
+ err = ME_ERRNO_LOCKED;
+ } else if (dlock->filep == NULL) {
+ for (i = 0; i < me_slist_get_number_subdevices(slist);
+ i++) {
+ subdevice = me_slist_get_subdevice(slist, i);
+
+ if (subdevice) {
+ if ((err =
+ subdevice->
+ me_subdevice_lock_subdevice
+ (subdevice, filep, ME_LOCK_CHECK,
+ flags))) {
+ PERROR
+ ("A subdevice is locked by another process.\n");
+ break;
+ }
+ } else {
+ err = ME_ERRNO_INTERNAL;
+ }
+ }
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid lock.\n");
+
+ err = ME_ERRNO_INVALID_LOCK;
+
+ break;
+ }
+
+ spin_unlock(&dlock->spin_lock);
+
+ return err;
+}
+
+void me_dlock_deinit(struct me_dlock *dlock)
+{
+ PDEBUG_LOCKS("executed.\n");
+}
+
+int me_dlock_init(me_dlock_t * dlock)
+{
+ PDEBUG_LOCKS("executed.\n");
+
+ dlock->filep = NULL;
+ dlock->count = 0;
+ spin_lock_init(&dlock->spin_lock);
+
+ return 0;
+}
diff --git a/drivers/staging/meilhaus/medlock.h b/drivers/staging/meilhaus/medlock.h
new file mode 100644
index 000000000000..4d6ddc8e58a1
--- /dev/null
+++ b/drivers/staging/meilhaus/medlock.h
@@ -0,0 +1,76 @@
+/**
+ * @file medlock.h
+ *
+ * @brief Provides the device lock class.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _MEDLOCK_H_
+#define _MEDLOCK_H_
+
+#include <linux/spinlock.h>
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The device lock class.
+ */
+typedef struct me_dlock {
+ struct file *filep; /**< Pointer to file structure holding the device. */
+ int count; /**< Number of tasks which are inside the device. */
+ spinlock_t spin_lock; /**< Spin lock protecting the attributes from concurrent access. */
+} me_dlock_t;
+
+/**
+ * @brief Tries to enter a device.
+ *
+ * @param dlock The device lock instance.
+ * @param filep The file structure identifying the calling process.
+ *
+ * @return 0 on success.
+ */
+int me_dlock_enter(struct me_dlock *dlock, struct file *filep);
+
+/**
+ * @brief Exits a device.
+ *
+ * @param dlock The device lock instance.
+ * @param filep The file structure identifying the calling process.
+ *
+ * @return 0 on success.
+ */
+int me_dlock_exit(struct me_dlock *dlock, struct file *filep);
+
+/**
+ * @brief Tries to perform a locking action on a device.
+ *
+ * @param dlock The device lock instance.
+ * @param filep The file structure identifying the calling process.
+ * @param The action to be done.
+ * @param flags Flags from user space.
+ * @param slist The subdevice list of the device.
+ *
+ * @return 0 on success.
+ */
+int me_dlock_lock(struct me_dlock *dlock,
+ struct file *filep, int lock, int flags, me_slist_t * slist);
+
+/**
+ * @brief Initializes a lock structure.
+ *
+ * @param dlock The lock structure to initialize.
+ * @return 0 on success.
+ */
+int me_dlock_init(me_dlock_t * dlock);
+
+/**
+ * @brief Deinitializes a lock structure.
+ *
+ * @param dlock The lock structure to deinitialize.
+ * @return 0 on success.
+ */
+void me_dlock_deinit(me_dlock_t * dlock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/medriver.h b/drivers/staging/meilhaus/medriver.h
new file mode 100644
index 000000000000..02e2408ce5f3
--- /dev/null
+++ b/drivers/staging/meilhaus/medriver.h
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : medriver.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ * Author: Krzysztof Gantzke <k.gantzke@meilhaus.de>
+ */
+
+#ifndef _MEDRIVER_H_
+#define _MEDRIVER_H_
+
+#include "metypes.h"
+#include "meerror.h"
+#include "medefines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /*===========================================================================
+ Functions to access the driver system
+ =========================================================================*/
+
+ int meOpen(int iFlags);
+ int meClose(int iFlags);
+
+ int meLockDriver(int iLock, int iFlags);
+ int meLockDevice(int iDevice, int iLock, int iFlags);
+ int meLockSubdevice(int iDevice, int iSubdevice, int iLock, int iFlags);
+
+ /*===========================================================================
+ Error handling functions
+ =========================================================================*/
+
+ int meErrorGetLastMessage(char *pcErrorMsg, int iCount);
+ int meErrorGetMessage(int iErrorCode, char *pcErrorMsg, int iCount);
+ int meErrorSetDefaultProc(int iSwitch);
+ int meErrorSetUserProc(meErrorCB_t pErrorProc);
+
+
+ /*===========================================================================
+ Functions to perform I/O on a device
+ =========================================================================*/
+
+ int meIOIrqSetCallback(
+ int iDevice,
+ int iSubdevice,
+ meIOIrqCB_t pCallback,
+ void *pCallbackContext,
+ int iFlags);
+ int meIOIrqStart(
+ int iDevice,
+ int iSubdevice,
+ int iChannel,
+ int iIrqSource,
+ int iIrqEdge,
+ int iIrqArg,
+ int iFlags);
+ int meIOIrqStop(
+ int iDevice,
+ int iSubdevice,
+ int iChannel,
+ int iFlags);
+ int meIOIrqWait(
+ int iDevice,
+ int iSubdevice,
+ int iChannel,
+ int *piIrqCount,
+ int *piValue,
+ int iTimeOut,
+ int iFlags);
+
+ int meIOResetDevice(int iDevice, int iFlags);
+ int meIOResetSubdevice(int iDevice, int iSubdevice, int iFlags);
+
+ int meIOStreamFrequencyToTicks(
+ int iDevice,
+ int iSubdevice,
+ int iTimer,
+ double *pdFrequency,
+ int *piTicksLow,
+ int *piTicksHigh,
+ int iFlags);
+
+ int meIOSingleConfig(
+ int iDevice,
+ int iSubdevice,
+ int iChannel,
+ int iSingleConfig,
+ int iRef,
+ int iTrigChan,
+ int iTrigType,
+ int iTrigEdge,
+ int iFlags);
+ int meIOSingle(meIOSingle_t *pSingleList, int iCount, int iFlags);
+
+ int meIOStreamConfig(
+ int iDevice,
+ int iSubdevice,
+ meIOStreamConfig_t *pConfigList,
+ int iCount,
+ meIOStreamTrigger_t *pTrigger,
+ int iFifoIrqThreshold,
+ int iFlags);
+ int meIOStreamNewValues(
+ int iDevice,
+ int iSubdevice,
+ int iTimeOut,
+ int *piCount,
+ int iFlags);
+ int meIOStreamRead(
+ int iDevice,
+ int iSubdevice,
+ int iReadMode,
+ int *piValues,
+ int *piCount,
+ int iFlags);
+ int meIOStreamWrite(
+ int iDevice,
+ int iSubdevice,
+ int iWriteMode,
+ int *piValues,
+ int *piCount,
+ int iFlags);
+ int meIOStreamStart(meIOStreamStart_t *pStartList, int iCount, int iFlags);
+ int meIOStreamStop(meIOStreamStop_t *pStopList, int iCount, int iFlags);
+ int meIOStreamStatus(
+ int iDevice,
+ int iSubdevice,
+ int iWait,
+ int *piStatus,
+ int *piCount,
+ int iFlags);
+ int meIOStreamSetCallbacks(
+ int iDevice,
+ int iSubdevice,
+ meIOStreamCB_t pStartCB,
+ void *pStartCBContext,
+ meIOStreamCB_t pNewValuesCB,
+ void *pNewValuesCBContext,
+ meIOStreamCB_t pEndCB,
+ void *pEndCBContext,
+ int iFlags);
+ int meIOStreamTimeToTicks(
+ int iDevice,
+ int iSubdevice,
+ int iTimer,
+ double *pdTime,
+ int *piTicksLow,
+ int *piTicksHigh,
+ int iFlags);
+
+
+ /*===========================================================================
+ Functions to query the driver system
+ =========================================================================*/
+
+ int meQueryDescriptionDevice(int iDevice, char *pcDescription, int iCount);
+
+ int meQueryInfoDevice(
+ int iDevice,
+ int *piVendorId,
+ int *piDeviceId,
+ int *piSerialNo,
+ int *piBusType,
+ int *piBusNo,
+ int *piDevNo,
+ int *piFuncNo,
+ int *piPlugged);
+
+ int meQueryNameDevice(int iDevice, char *pcName, int iCount);
+ int meQueryNameDeviceDriver(int iDevice, char *pcName, int iCount);
+
+ int meQueryNumberDevices(int *piNumber);
+ int meQueryNumberSubdevices(int iDevice, int *piNumber);
+ int meQueryNumberChannels(int iDevice, int iSubdevice, int *piNumber);
+ int meQueryNumberRanges(
+ int iDevice,
+ int iSubdevice,
+ int iUnit,
+ int *piNumber);
+
+ int meQueryRangeByMinMax(
+ int iDevice,
+ int iSubdevice,
+ int iUnit,
+ double *pdMin,
+ double *pdMax,
+ int *piMaxData,
+ int *piRange);
+ int meQueryRangeInfo(
+ int iDevice,
+ int iSubdevice,
+ int iRange,
+ int *piUnit,
+ double *pdMin,
+ double *pdMax,
+ int *piMaxData);
+
+ int meQuerySubdeviceByType(
+ int iDevice,
+ int iStartSubdevice,
+ int iType,
+ int iSubtype,
+ int *piSubdevice);
+ int meQuerySubdeviceType(
+ int iDevice,
+ int iSubdevice,
+ int *piType,
+ int *piSubtype);
+ int meQuerySubdeviceCaps(
+ int iDevice,
+ int iSubdevice,
+ int *piCaps);
+ int meQuerySubdeviceCapsArgs(
+ int iDevice,
+ int iSubdevice,
+ int iCap,
+ int *piArgs,
+ int iCount);
+
+ int meQueryVersionLibrary(int *piVersion);
+ int meQueryVersionMainDriver(int *piVersion);
+ int meQueryVersionDeviceDriver(int iDevice, int *piVersion);
+
+
+ /*===========================================================================
+ Common utility functions
+ =========================================================================*/
+
+ int meUtilityExtractValues(
+ int iChannel,
+ int *piAIBuffer,
+ int iAIBufferCount,
+ meIOStreamConfig_t *pConfigList,
+ int iConfigListCount,
+ int *piChanBuffer,
+ int *piChanBufferCount);
+ int meUtilityDigitalToPhysical(
+ double dMin,
+ double dMax,
+ int iMaxData,
+ int iData,
+ int iModuleType,
+ double dRefValue,
+ double *pdPhysical);
+ int meUtilityDigitalToPhysicalV(
+ double dMin,
+ double dMax,
+ int iMaxData,
+ int *piDataBuffer,
+ int iCount,
+ int iModuleType,
+ double dRefValue,
+ double *pdPhysicalBuffer);
+ int meUtilityPhysicalToDigital(
+ double dMin,
+ double dMax,
+ int iMaxData,
+ double dPhysical,
+ int *piData);
+ int meUtilityPWMStart(
+ int iDevice,
+ int iSubdevice1,
+ int iSubdevice2,
+ int iSubdevice3,
+ int iRef,
+ int iPrescaler,
+ int iDutyCycle,
+ int iFlag);
+ int meUtilityPWMStop(int iDevice,
+ int iSubdevice1);
+ int meUtilityPWMRestart(
+ int iDevice,
+ int iSubdevice1,
+ int iRef,
+ int iPrescaler);
+
+
+ /*===========================================================================
+ Load configuration from file into driver system
+ =========================================================================*/
+
+ int meConfigLoad(char *pcConfigFile);
+
+
+ /*===========================================================================
+ Functions to query a remote driver system
+ =========================================================================*/
+
+ int meRQueryDescriptionDevice(
+ char *location,
+ int iDevice,
+ char *pcDescription,
+ int iCount);
+
+ int meRQueryInfoDevice(
+ char *location,
+ int iDevice,
+ int *piVendorId,
+ int *piDeviceId,
+ int *piSerialNo,
+ int *piBusType,
+ int *piBusNo,
+ int *piDevNo,
+ int *piFuncNo,
+ int *piPlugged);
+
+ int meRQueryNameDevice(
+ char *location,
+ int iDevice,
+ char *pcName,
+ int iCount);
+
+ int meRQueryNumberDevices(char *location, int *piNumber);
+ int meRQueryNumberSubdevices(char *location, int iDevice, int *piNumber);
+ int meRQueryNumberChannels(
+ char *location,
+ int iDevice,
+ int iSubdevice,
+ int *piNumber);
+ int meRQueryNumberRanges(
+ char *location,
+ int iDevice,
+ int iSubdevice,
+ int iUnit,
+ int *piNumber);
+
+ int meRQueryRangeInfo(
+ char *location,
+ int iDevice,
+ int iSubdevice,
+ int iRange,
+ int *piUnit,
+ double *pdMin,
+ double *pdMax,
+ int *piMaxData);
+
+ int meRQuerySubdeviceType(
+ char *location,
+ int iDevice,
+ int iSubdevice,
+ int *piType,
+ int *piSubtype);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/drivers/staging/meilhaus/medummy.c b/drivers/staging/meilhaus/medummy.c
new file mode 100644
index 000000000000..6a9f08d50bb1
--- /dev/null
+++ b/drivers/staging/meilhaus/medummy.c
@@ -0,0 +1,1266 @@
+/* Device driver for Meilhaus ME-DUMMY devices.
+ * ===========================================
+ *
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * User application could also include the kernel header files. But the
+ * real kernel functions are protected by #ifdef __KERNEL__.
+ */
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * This must be defined before module.h is included. Not needed, when
+ * it is a built in driver.
+ */
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "meerror.h"
+#include "meinternal.h"
+
+#include "meids.h"
+#include "mecommon.h"
+#include "medevice.h"
+#include "medebug.h"
+
+#include "medummy.h"
+
+static int medummy_io_irq_start(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_irq_wait(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int *irq_count,
+ int *value, int timeout, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_irq_stop(me_device_t * device,
+ struct file *filep,
+ int subdevice, int channel, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_reset_device(me_device_t * device,
+ struct file *filep, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_reset_subdevice(me_device_t * device,
+ struct file *filep,
+ int subdevice, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_single_config(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type, int trig_edge, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_single_read(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_single_write(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int channel,
+ int value, int time_out, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_stream_config(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_stream_new_values(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int timeout, int *count, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_stream_read(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int read_mode,
+ int *values, int *count, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_stream_start(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int start_mode, int time_out, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_stream_status(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int wait,
+ int *status, int *values, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_stream_stop(me_device_t * device,
+ struct file *filep,
+ int subdevice, int stop_mode, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_io_stream_write(me_device_t * device,
+ struct file *filep,
+ int subdevice,
+ int write_mode,
+ int *values, int *count, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_lock_device(me_device_t * device,
+ struct file *filep, int lock, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_lock_subdevice(me_device_t * device,
+ struct file *filep,
+ int subdevice, int lock, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_description_device(me_device_t * device,
+ char **description)
+{
+ medummy_device_t *instance = (medummy_device_t *) device;
+
+ PDEBUG("executed.\n");
+
+// if (instance->magic != MEDUMMY_MAGIC_NUMBER)
+// {
+// PERROR("Wrong magic number.\n");
+// return ME_ERRNO_INTERNAL;
+// }
+
+ switch (instance->device_id) {
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1000:
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1000_A:
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1000_B:
+ *description = ME1000_DESCRIPTION_DEVICE_ME1000;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1400:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140A:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400A;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140B:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400B;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14E0:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400E;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14EA:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400EA;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14EB:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400EB;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400C;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ *description = ME1400_DESCRIPTION_DEVICE_ME1400D;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_4U:
+ *description = ME1600_DESCRIPTION_DEVICE_ME16004U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_8U:
+ *description = ME1600_DESCRIPTION_DEVICE_ME16008U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_12U:
+ *description = ME1600_DESCRIPTION_DEVICE_ME160012U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_16U:
+ *description = ME1600_DESCRIPTION_DEVICE_ME160016U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I:
+ *description = ME1600_DESCRIPTION_DEVICE_ME160016U8I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4610:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4610;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4650:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4650;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4660;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660I:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4660I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660S:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4660S;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660IS:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4660IS;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4670;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670I:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4670I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670S:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4670S;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4670IS;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4680;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680I:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4680I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680S:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4680S;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
+ *description = ME4600_DESCRIPTION_DEVICE_ME4680IS;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6004:
+ *description = ME6000_DESCRIPTION_DEVICE_ME60004;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6008:
+ *description = ME6000_DESCRIPTION_DEVICE_ME60008;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME600F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME600016;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6014:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000I4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6018:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000I8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME601F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000I16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6034:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6038:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME603F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6104:
+ *description = ME6000_DESCRIPTION_DEVICE_ME61004;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6108:
+ *description = ME6000_DESCRIPTION_DEVICE_ME61008;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME610F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME610016;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6114:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100I4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6118:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100I8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME611F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100I16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6134:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6138:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME613F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6044:
+ *description = ME6000_DESCRIPTION_DEVICE_ME60004DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6048:
+ *description = ME6000_DESCRIPTION_DEVICE_ME60008DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME604F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME600016DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6054:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000I4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6058:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000I8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME605F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000I16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6074:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6078:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME607F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6144:
+ *description = ME6000_DESCRIPTION_DEVICE_ME61004DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6148:
+ *description = ME6000_DESCRIPTION_DEVICE_ME61008DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME614F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME610016DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6154:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100I4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6158:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100I8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME615F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100I16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6174:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6178:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME617F:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6259:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6200I9DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6359:
+ *description = ME6000_DESCRIPTION_DEVICE_ME6300I9DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0630:
+ *description = ME0600_DESCRIPTION_DEVICE_ME0630;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
+ *description = ME8100_DESCRIPTION_DEVICE_ME8100A;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
+ *description = ME8100_DESCRIPTION_DEVICE_ME8100B;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0940:
+ *description = ME0900_DESCRIPTION_DEVICE_ME0940;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0950:
+ *description = ME0900_DESCRIPTION_DEVICE_ME0950;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0960:
+ *description = ME0900_DESCRIPTION_DEVICE_ME0960;
+
+ break;
+/*
+ case USB_DEVICE_ID_MEPHISTO_S1:
+ *description = MEPHISTO_S1_DESCRIPTION_DEVICE;
+
+ break;
+*/
+ default:
+ *description = EMPTY_DESCRIPTION_DEVICE;
+ PERROR("Invalid device id in device info.\n");
+
+ return ME_ERRNO_INTERNAL;
+ }
+
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_info_device(me_device_t * device,
+ int *vendor_id,
+ int *device_id,
+ int *serial_no,
+ int *bus_type,
+ int *bus_no,
+ int *dev_no, int *func_no, int *plugged)
+{
+ medummy_device_t *instance = (medummy_device_t *) device;
+
+ PDEBUG("executed.\n");
+
+// if (instance->magic != MEDUMMY_MAGIC_NUMBER)
+// {
+// PERROR("Wrong magic number.\n");
+// return ME_ERRNO_INTERNAL;
+// }
+
+ *vendor_id = instance->vendor_id;
+ *device_id = instance->device_id;
+ *serial_no = instance->serial_no;
+ *bus_type = instance->bus_type;
+ *bus_no = instance->bus_no;
+ *dev_no = instance->dev_no;
+ *func_no = instance->func_no;
+ *plugged = ME_PLUGGED_OUT;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int medummy_query_name_device_driver(me_device_t * device, char **name)
+{
+ PDEBUG("executed.\n");
+ *name = MEDUMMY_NAME_DRIVER;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int medummy_query_name_device(me_device_t * device, char **name)
+{
+ medummy_device_t *instance = (medummy_device_t *) device;
+
+ PDEBUG("executed.\n");
+
+// // // if (instance->magic != MEDUMMY_MAGIC_NUMBER)
+// // // {
+// // // PERROR("Wrong magic number.\n");
+// // // return ME_ERRNO_INTERNAL;
+// // // }
+
+ switch (instance->device_id) {
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1000:
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1000_A:
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1000_B:
+ *name = ME1000_NAME_DEVICE_ME1000;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1400:
+ *name = ME1400_NAME_DEVICE_ME1400;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140A:
+ *name = ME1400_NAME_DEVICE_ME1400A;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140B:
+ *name = ME1400_NAME_DEVICE_ME1400B;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14E0:
+ *name = ME1400_NAME_DEVICE_ME1400E;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14EA:
+ *name = ME1400_NAME_DEVICE_ME1400EA;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME14EB:
+ *name = ME1400_NAME_DEVICE_ME1400EB;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140C:
+ *name = ME1400_NAME_DEVICE_ME1400C;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME140D:
+ *name = ME1400_NAME_DEVICE_ME1400D;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_4U:
+ *name = ME1600_NAME_DEVICE_ME16004U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_8U:
+ *name = ME1600_NAME_DEVICE_ME16008U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_12U:
+ *name = ME1600_NAME_DEVICE_ME160012U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_16U:
+ *name = ME1600_NAME_DEVICE_ME160016U;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I:
+ *name = ME1600_NAME_DEVICE_ME160016U8I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4610:
+ *name = ME4600_NAME_DEVICE_ME4610;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4650:
+ *name = ME4600_NAME_DEVICE_ME4650;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660:
+ *name = ME4600_NAME_DEVICE_ME4660;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4660I:
+ *name = ME4600_NAME_DEVICE_ME4660I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670:
+ *name = ME4600_NAME_DEVICE_ME4670;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670I:
+ *name = ME4600_NAME_DEVICE_ME4670I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670S:
+ *name = ME4600_NAME_DEVICE_ME4670S;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4670IS:
+ *name = ME4600_NAME_DEVICE_ME4670IS;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680:
+ *name = ME4600_NAME_DEVICE_ME4680;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680I:
+ *name = ME4600_NAME_DEVICE_ME4680I;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680S:
+ *name = ME4600_NAME_DEVICE_ME4680S;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME4680IS:
+ *name = ME4600_NAME_DEVICE_ME4680IS;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6004:
+ *name = ME6000_NAME_DEVICE_ME60004;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6008:
+ *name = ME6000_NAME_DEVICE_ME60008;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME600F:
+ *name = ME6000_NAME_DEVICE_ME600016;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6014:
+ *name = ME6000_NAME_DEVICE_ME6000I4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6018:
+ *name = ME6000_NAME_DEVICE_ME6000I8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME601F:
+ *name = ME6000_NAME_DEVICE_ME6000I16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6034:
+ *name = ME6000_NAME_DEVICE_ME6000ISLE4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6038:
+ *name = ME6000_NAME_DEVICE_ME6000ISLE8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME603F:
+ *name = ME6000_NAME_DEVICE_ME6000ISLE16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6104:
+ *name = ME6000_NAME_DEVICE_ME61004;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6108:
+ *name = ME6000_NAME_DEVICE_ME61008;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME610F:
+ *name = ME6000_NAME_DEVICE_ME610016;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6114:
+ *name = ME6000_NAME_DEVICE_ME6100I4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6118:
+ *name = ME6000_NAME_DEVICE_ME6100I8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME611F:
+ *name = ME6000_NAME_DEVICE_ME6100I16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6134:
+ *name = ME6000_NAME_DEVICE_ME6100ISLE4;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6138:
+ *name = ME6000_NAME_DEVICE_ME6100ISLE8;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME613F:
+ *name = ME6000_NAME_DEVICE_ME6100ISLE16;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6044:
+ *name = ME6000_NAME_DEVICE_ME60004DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6048:
+ *name = ME6000_NAME_DEVICE_ME60008DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME604F:
+ *name = ME6000_NAME_DEVICE_ME600016DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6054:
+ *name = ME6000_NAME_DEVICE_ME6000I4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6058:
+ *name = ME6000_NAME_DEVICE_ME6000I8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME605F:
+ *name = ME6000_NAME_DEVICE_ME6000I16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6074:
+ *name = ME6000_NAME_DEVICE_ME6000ISLE4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6078:
+ *name = ME6000_NAME_DEVICE_ME6000ISLE8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME607F:
+ *name = ME6000_NAME_DEVICE_ME6000ISLE16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6144:
+ *name = ME6000_NAME_DEVICE_ME61004DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6148:
+ *name = ME6000_NAME_DEVICE_ME61008DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME614F:
+ *name = ME6000_NAME_DEVICE_ME610016DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6154:
+ *name = ME6000_NAME_DEVICE_ME6100I4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6158:
+ *name = ME6000_NAME_DEVICE_ME6100I8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME615F:
+ *name = ME6000_NAME_DEVICE_ME6100I16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6174:
+ *name = ME6000_NAME_DEVICE_ME6100ISLE4DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME6178:
+ *name = ME6000_NAME_DEVICE_ME6100ISLE8DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME617F:
+ *name = ME6000_NAME_DEVICE_ME6100ISLE16DIO;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0630:
+ *name = ME0600_NAME_DEVICE_ME0630;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_A:
+ *name = ME8100_NAME_DEVICE_ME8100A;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME8100_B:
+ *name = ME8100_NAME_DEVICE_ME8100B;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0940:
+ *name = ME0900_NAME_DEVICE_ME0940;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0950:
+ *name = ME0900_NAME_DEVICE_ME0950;
+
+ break;
+
+ case PCI_DEVICE_ID_MEILHAUS_ME0960:
+ *name = ME0900_NAME_DEVICE_ME0960;
+
+ break;
+/*
+ case USB_DEVICE_ID_MEPHISTO_S1:
+ *name = MEPHISTO_S1_NAME_DEVICE;
+
+ break;
+*/
+ default:
+ *name = EMPTY_NAME_DEVICE;
+ PERROR("Invalid PCI device id.\n");
+
+ return ME_ERRNO_INTERNAL;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int medummy_query_number_subdevices(me_device_t * device, int *number)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_number_channels(me_device_t * device,
+ int subdevice, int *number)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_number_ranges(me_device_t * device,
+ int subdevice, int unit, int *count)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_subdevice_type(me_device_t * device,
+ int subdevice, int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_subdevice_caps(me_device_t * device,
+ int subdevice, int *caps)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_subdevice_caps_args(me_device_t * device,
+ int subdevice,
+ int cap, int *args, int count)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int medummy_query_subdevice_by_type(me_device_t * device,
+ int start_subdevice,
+ int type,
+ int subtype, int *subdevice)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_range_by_min_max(me_device_t * device,
+ int subdevice,
+ int unit,
+ int *min,
+ int *max, int *maxdata, int *range)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_range_info(me_device_t * device,
+ int subdevice,
+ int range,
+ int *unit, int *min, int *max, int *maxdata)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+int medummy_query_timer(me_device_t * device,
+ int subdevice,
+ int timer,
+ int *base_frequency,
+ uint64_t * min_ticks, uint64_t * max_ticks)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_DEVICE_UNPLUGGED;
+}
+
+static int medummy_query_version_device_driver(me_device_t * device,
+ int *version)
+{
+ PDEBUG("executed.\n");
+
+ *version = ME_VERSION_DRIVER;
+ return ME_ERRNO_SUCCESS;
+}
+
+static void medummy_destructor(me_device_t * device)
+{
+ PDEBUG("executed.\n");
+ kfree(device);
+}
+
+static int init_device_info(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned int serial_no,
+ int bus_type,
+ int bus_no,
+ int dev_no,
+ int func_no, medummy_device_t * instance)
+{
+ PDEBUG("executed.\n");
+
+// instance->magic = MEDUMMY_MAGIC_NUMBER;
+ instance->vendor_id = vendor_id;
+ instance->device_id = device_id;
+ instance->serial_no = serial_no;
+ instance->bus_type = bus_type;
+ instance->bus_no = bus_no;
+ instance->dev_no = dev_no;
+ instance->func_no = func_no;
+
+ return 0;
+}
+
+static int medummy_config_load(me_device_t * device, struct file *filep,
+ me_cfg_device_entry_t * config)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_SUCCESS;
+}
+
+static int init_device_instance(me_device_t * device)
+{
+ PDEBUG("executed.\n");
+
+ INIT_LIST_HEAD(&device->list);
+
+ device->me_device_io_irq_start = medummy_io_irq_start;
+ device->me_device_io_irq_wait = medummy_io_irq_wait;
+ device->me_device_io_irq_stop = medummy_io_irq_stop;
+ device->me_device_io_reset_device = medummy_io_reset_device;
+ device->me_device_io_reset_subdevice = medummy_io_reset_subdevice;
+ device->me_device_io_single_config = medummy_io_single_config;
+ device->me_device_io_single_read = medummy_io_single_read;
+ device->me_device_io_single_write = medummy_io_single_write;
+ device->me_device_io_stream_config = medummy_io_stream_config;
+ device->me_device_io_stream_new_values = medummy_io_stream_new_values;
+ device->me_device_io_stream_read = medummy_io_stream_read;
+ device->me_device_io_stream_start = medummy_io_stream_start;
+ device->me_device_io_stream_status = medummy_io_stream_status;
+ device->me_device_io_stream_stop = medummy_io_stream_stop;
+ device->me_device_io_stream_write = medummy_io_stream_write;
+
+ device->me_device_lock_device = medummy_lock_device;
+ device->me_device_lock_subdevice = medummy_lock_subdevice;
+
+ device->me_device_query_description_device =
+ medummy_query_description_device;
+ device->me_device_query_info_device = medummy_query_info_device;
+ device->me_device_query_name_device_driver =
+ medummy_query_name_device_driver;
+ device->me_device_query_name_device = medummy_query_name_device;
+
+ device->me_device_query_number_subdevices =
+ medummy_query_number_subdevices;
+ device->me_device_query_number_channels = medummy_query_number_channels;
+ device->me_device_query_number_ranges = medummy_query_number_ranges;
+
+ device->me_device_query_range_by_min_max =
+ medummy_query_range_by_min_max;
+ device->me_device_query_range_info = medummy_query_range_info;
+
+ device->me_device_query_subdevice_type = medummy_query_subdevice_type;
+ device->me_device_query_subdevice_by_type =
+ medummy_query_subdevice_by_type;
+ device->me_device_query_subdevice_caps = medummy_query_subdevice_caps;
+ device->me_device_query_subdevice_caps_args =
+ medummy_query_subdevice_caps_args;
+
+ device->me_device_query_timer = medummy_query_timer;
+
+ device->me_device_query_version_device_driver =
+ medummy_query_version_device_driver;
+
+ device->me_device_destructor = medummy_destructor;
+ device->me_device_config_load = medummy_config_load;
+ return 0;
+}
+
+me_device_t *medummy_constructor(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned int serial_no,
+ int bus_type,
+ int bus_no, int dev_no, int func_no)
+{
+ int result = 0;
+ medummy_device_t *instance;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate structure for device attributes */
+ instance = kmalloc(sizeof(medummy_device_t), GFP_KERNEL);
+
+ if (!instance) {
+ PERROR("Can't get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(instance, 0, sizeof(medummy_device_t));
+
+ /* Initialize device info */
+ result = init_device_info(vendor_id,
+ device_id,
+ serial_no,
+ bus_type, bus_no, dev_no, func_no, instance);
+
+ if (result) {
+ PERROR("Cannot init baord info.\n");
+ kfree(instance);
+ return NULL;
+ }
+
+ /* Initialize device instance */
+ result = init_device_instance((me_device_t *) instance);
+
+ if (result) {
+ PERROR("Cannot init baord info.\n");
+ kfree(instance);
+ return NULL;
+ }
+
+ return (me_device_t *) instance;
+}
+
+// Init and exit of module.
+
+static int __init dummy_init(void)
+{
+ PDEBUG("executed.\n");
+ return 0;
+}
+
+static void __exit dummy_exit(void)
+{
+ PDEBUG("executed.\n");
+}
+
+module_init(dummy_init);
+
+module_exit(dummy_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-DUMMY Devices");
+MODULE_SUPPORTED_DEVICE("Meilhaus ME-DUMMY Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(medummy_constructor);
diff --git a/drivers/staging/meilhaus/medummy.h b/drivers/staging/meilhaus/medummy.h
new file mode 100644
index 000000000000..717000ff6c1c
--- /dev/null
+++ b/drivers/staging/meilhaus/medummy.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : medummy.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ */
+
+#ifndef _MEDUMMY_H_
+#define _MEDUMMY_H_
+
+#include "metypes.h"
+#include "medefines.h"
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+#define MEDUMMY_MAGIC_NUMBER 0xDDDD
+
+typedef struct medummy_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+// int magic; /**< The magic number of the structure */
+ unsigned short vendor_id; /**< Vendor ID */
+ unsigned short device_id; /**< Device ID */
+ unsigned int serial_no; /**< Serial number of the device */
+ int bus_type; /**< Bus type */
+ int bus_no; /**< Bus number */
+ int dev_no; /**< Device number */
+ int func_no; /**< Function number */
+} medummy_device_t;
+
+me_device_t *medummy_constructor(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned int serial_no,
+ int bus_type,
+ int bus_no,
+ int dev_no,
+ int func_no) __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/meerror.h b/drivers/staging/meilhaus/meerror.h
new file mode 100644
index 000000000000..9eda4bf907ba
--- /dev/null
+++ b/drivers/staging/meilhaus/meerror.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : meerror.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ * Author : KG (Krzysztof Gantzke) <k.gantzke@meilhaus.de>
+ */
+
+#ifndef _MEERROR_H_
+#define _MEERROR_H_
+
+extern char *meErrorMsgTable[];
+
+#define ME_ERRNO_SUCCESS 0
+#define ME_ERRNO_INVALID_DEVICE 1
+#define ME_ERRNO_INVALID_SUBDEVICE 2
+#define ME_ERRNO_INVALID_CHANNEL 3
+#define ME_ERRNO_INVALID_SINGLE_CONFIG 4
+#define ME_ERRNO_INVALID_REF 5
+#define ME_ERRNO_INVALID_TRIG_CHAN 6
+#define ME_ERRNO_INVALID_TRIG_TYPE 7
+#define ME_ERRNO_INVALID_TRIG_EDGE 8
+#define ME_ERRNO_INVALID_TIMEOUT 9
+#define ME_ERRNO_INVALID_FLAGS 10
+#define ME_ERRNO_OPEN 11
+#define ME_ERRNO_CLOSE 12
+#define ME_ERRNO_NOT_OPEN 13
+#define ME_ERRNO_INVALID_DIR 14
+#define ME_ERRNO_PREVIOUS_CONFIG 15
+#define ME_ERRNO_NOT_SUPPORTED 16
+#define ME_ERRNO_SUBDEVICE_TYPE 17
+#define ME_ERRNO_USER_BUFFER_SIZE 18
+#define ME_ERRNO_LOCKED 19
+#define ME_ERRNO_NOMORE_SUBDEVICE_TYPE 20
+#define ME_ERRNO_TIMEOUT 21
+#define ME_ERRNO_SIGNAL 22
+#define ME_ERRNO_INVALID_IRQ_SOURCE 23
+#define ME_ERRNO_THREAD_RUNNING 24
+#define ME_ERRNO_START_THREAD 25
+#define ME_ERRNO_CANCEL_THREAD 26
+#define ME_ERRNO_NO_CALLBACK 27
+#define ME_ERRNO_USED 28
+#define ME_ERRNO_INVALID_UNIT 29
+#define ME_ERRNO_INVALID_MIN_MAX 30
+#define ME_ERRNO_NO_RANGE 31
+#define ME_ERRNO_INVALID_RANGE 32
+#define ME_ERRNO_SUBDEVICE_BUSY 33
+#define ME_ERRNO_INVALID_LOCK 34
+#define ME_ERRNO_INVALID_SWITCH 35
+#define ME_ERRNO_INVALID_ERROR_MSG_COUNT 36
+#define ME_ERRNO_INVALID_STREAM_CONFIG 37
+#define ME_ERRNO_INVALID_CONFIG_LIST_COUNT 38
+#define ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE 39
+#define ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE 40
+#define ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN 41
+#define ME_ERRNO_INVALID_ACQ_START_TIMEOUT 42
+#define ME_ERRNO_INVALID_ACQ_START_ARG 43
+#define ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE 44
+#define ME_ERRNO_INVALID_SCAN_START_ARG 45
+#define ME_ERRNO_INVALID_CONV_START_TRIG_TYPE 46
+#define ME_ERRNO_INVALID_CONV_START_ARG 47
+#define ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE 48
+#define ME_ERRNO_INVALID_SCAN_STOP_ARG 49
+#define ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE 50
+#define ME_ERRNO_INVALID_ACQ_STOP_ARG 51
+#define ME_ERRNO_SUBDEVICE_NOT_RUNNING 52
+#define ME_ERRNO_INVALID_READ_MODE 53
+#define ME_ERRNO_INVALID_VALUE_COUNT 54
+#define ME_ERRNO_INVALID_WRITE_MODE 55
+#define ME_ERRNO_INVALID_TIMER 56
+#define ME_ERRNO_DEVICE_UNPLUGGED 57
+#define ME_ERRNO_USED_INTERNAL 58
+#define ME_ERRNO_INVALID_DUTY_CYCLE 59
+#define ME_ERRNO_INVALID_WAIT 60
+#define ME_ERRNO_CONNECT_REMOTE 61
+#define ME_ERRNO_COMMUNICATION 62
+#define ME_ERRNO_INVALID_SINGLE_LIST 63
+#define ME_ERRNO_INVALID_MODULE_TYPE 64
+#define ME_ERRNO_INVALID_START_MODE 65
+#define ME_ERRNO_INVALID_STOP_MODE 66
+#define ME_ERRNO_INVALID_FIFO_IRQ_THRESHOLD 67
+#define ME_ERRNO_INVALID_POINTER 68
+#define ME_ERRNO_CREATE_EVENT 69
+#define ME_ERRNO_LACK_OF_RESOURCES 70
+#define ME_ERRNO_CANCELLED 71
+#define ME_ERRNO_RING_BUFFER_OVERFLOW 72
+#define ME_ERRNO_RING_BUFFER_UNDEFFLOW 73
+#define ME_ERRNO_INVALID_IRQ_EDGE 74
+#define ME_ERRNO_INVALID_IRQ_ARG 75
+#define ME_ERRNO_INVALID_CAP 76
+#define ME_ERRNO_INVALID_CAP_ARG_COUNT 77
+#define ME_ERRNO_INTERNAL 78
+
+/** New error for range check */
+#define ME_ERRNO_VALUE_OUT_OF_RANGE 79
+#define ME_ERRNO_FIFO_BUFFER_OVERFLOW 80
+#define ME_ERRNO_FIFO_BUFFER_UNDEFFLOW 81
+
+#define ME_ERRNO_INVALID_ERROR_NUMBER 82
+#endif
diff --git a/drivers/staging/meilhaus/mefirmware.c b/drivers/staging/meilhaus/mefirmware.c
new file mode 100644
index 000000000000..c07d202e8cb5
--- /dev/null
+++ b/drivers/staging/meilhaus/mefirmware.c
@@ -0,0 +1,137 @@
+/**
+ * @file mefirmware.c
+ *
+ * @brief Implements the firmware handling.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/***************************************************************************
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) *
+ * Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef KBUILD_MODNAME
+# define KBUILD_MODNAME KBUILD_STR(mefirmware)
+#endif
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include <linux/firmware.h>
+
+#include "meplx_reg.h"
+#include "medebug.h"
+
+#include "mefirmware.h"
+
+int me_xilinx_download(unsigned long register_base_control,
+ unsigned long register_base_data,
+ struct device *dev, const char *firmware_name)
+{
+ int err = ME_ERRNO_FIRMWARE;
+ uint32_t value = 0;
+ int idx = 0;
+
+ const struct firmware *fw;
+
+ PDEBUG("executed.\n");
+
+ if (!firmware_name) {
+ PERROR("Request for firmware failed. No name provided. \n");
+ return err;
+ }
+
+ PINFO("Request '%s' firmware.\n", firmware_name);
+ err = request_firmware(&fw, firmware_name, dev);
+
+ if (err) {
+ PERROR("Request for firmware failed.\n");
+ return err;
+ }
+ // Set PLX local interrupt 2 polarity to high.
+ // Interrupt is thrown by init pin of xilinx.
+ outl(PLX_INTCSR_LOCAL_INT2_POL, register_base_control + PLX_INTCSR);
+
+ // Set /CS and /WRITE of the Xilinx
+ value = inl(register_base_control + PLX_ICR);
+ value |= ME_FIRMWARE_CS_WRITE;
+ outl(value, register_base_control + PLX_ICR);
+
+ // Init Xilinx with CS1
+ inl(register_base_data + ME_XILINX_CS1_REG);
+
+ // Wait for init to complete
+ udelay(20);
+
+ // Checkl /INIT pin
+ if (!
+ (inl(register_base_control + PLX_INTCSR) &
+ PLX_INTCSR_LOCAL_INT2_STATE)) {
+ PERROR("Can't init Xilinx.\n");
+ release_firmware(fw);
+ return -EIO;
+ }
+ // Reset /CS and /WRITE of the Xilinx
+ value = inl(register_base_control + PLX_ICR);
+ value &= ~ME_FIRMWARE_CS_WRITE;
+ outl(value, register_base_control + PLX_ICR);
+
+ // Download Xilinx firmware
+ udelay(10);
+
+ for (idx = 0; idx < fw->size; idx++) {
+ outl(fw->data[idx], register_base_data);
+#ifdef ME6000_v2_4
+/// This checking only for board's version 2.4
+ // Check if BUSY flag is set (low = ready, high = busy)
+ if (inl(register_base_control + PLX_ICR) &
+ ME_FIRMWARE_BUSY_FLAG) {
+ PERROR("Xilinx is still busy (idx = %d)\n", idx);
+ release_firmware(fw);
+ return -EIO;
+ }
+#endif //ME6000_v2_4
+ }
+ PDEBUG("Download finished. %d bytes written to PLX.\n", idx);
+
+ // If done flag is high download was successful
+ if (inl(register_base_control + PLX_ICR) & ME_FIRMWARE_DONE_FLAG) {
+ PDEBUG("SUCCESS. Done flag is set.\n");
+ } else {
+ PERROR("FAILURE. DONE flag is not set.\n");
+ release_firmware(fw);
+ return -EIO;
+ }
+
+ // Set /CS and /WRITE
+ value = inl(register_base_control + PLX_ICR);
+ value |= ME_FIRMWARE_CS_WRITE;
+ outl(value, register_base_control + PLX_ICR);
+
+ PDEBUG("Enable interrupts on the PCI interface.\n");
+ outl(ME_PLX_PCI_ACTIVATE, register_base_control + PLX_INTCSR);
+ release_firmware(fw);
+
+ return 0;
+}
diff --git a/drivers/staging/meilhaus/mefirmware.h b/drivers/staging/meilhaus/mefirmware.h
new file mode 100644
index 000000000000..a2685080c97b
--- /dev/null
+++ b/drivers/staging/meilhaus/mefirmware.h
@@ -0,0 +1,57 @@
+/**
+ * @file mefirmware.h
+ *
+ * @brief Definitions of the firmware handling functions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/***************************************************************************
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) *
+ * Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#ifndef _MEFIRMWARE_H
+# define _MEFIRMWARE_H
+
+# ifdef __KERNEL__
+
+#define ME_ERRNO_FIRMWARE -1
+
+/**
+* Registry
+*/
+#define ME_XILINX_CS1_REG 0x00C8
+
+/**
+* Flags (bits)
+*/
+
+#define ME_FIRMWARE_BUSY_FLAG 0x00000020
+#define ME_FIRMWARE_DONE_FLAG 0x00000004
+#define ME_FIRMWARE_CS_WRITE 0x00000100
+
+#define ME_PLX_PCI_ACTIVATE 0x43
+
+int me_xilinx_download(unsigned long register_base_control,
+ unsigned long register_base_data,
+ struct device *dev, const char *firmware_name);
+
+# endif //__KERNEL__
+
+#endif //_MEFIRMWARE_H
diff --git a/drivers/staging/meilhaus/meids.h b/drivers/staging/meilhaus/meids.h
new file mode 100644
index 000000000000..b3e757cbdda6
--- /dev/null
+++ b/drivers/staging/meilhaus/meids.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : meids.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ */
+
+#ifndef _MEIDS_H_
+#define _MEIDS_H_
+
+#ifdef __KERNEL__
+
+/*=============================================================================
+ Driver names
+ ===========================================================================*/
+
+#define MEMAIN_NAME "memain"
+#define ME1000_NAME "me1000"
+#define ME1400_NAME "me1400"
+#define ME1600_NAME "me1600"
+#define ME4600_NAME "me4600"
+#define ME6000_NAME "me6000"
+#define ME0600_NAME "me0600" //"me630"
+#define ME8100_NAME "me8100"
+#define ME8200_NAME "me8200"
+#define ME0900_NAME "me0900" //"me9x"
+//#define MEPHISTO_S1_NAME "mephisto_s1"
+#define MEDUMMY_NAME "medummy"
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/meinternal.h b/drivers/staging/meilhaus/meinternal.h
new file mode 100644
index 000000000000..8d126b4905a7
--- /dev/null
+++ b/drivers/staging/meilhaus/meinternal.h
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : meinternal.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ */
+
+#ifndef _MEINTERNAL_H_
+#define _MEINTERNAL_H_
+
+/*=============================================================================
+ PCI Vendor IDs
+ ===========================================================================*/
+
+#define PCI_VENDOR_ID_MEILHAUS 0x1402
+
+/*=============================================================================
+ PCI Device IDs
+ ===========================================================================*/
+
+#define PCI_DEVICE_ID_MEILHAUS_ME1000 0x1000
+#define PCI_DEVICE_ID_MEILHAUS_ME1000_A 0x100A
+#define PCI_DEVICE_ID_MEILHAUS_ME1000_B 0x100B
+
+#define PCI_DEVICE_ID_MEILHAUS_ME1400 0x1400
+#define PCI_DEVICE_ID_MEILHAUS_ME140A 0x140A
+#define PCI_DEVICE_ID_MEILHAUS_ME140B 0x140B
+#define PCI_DEVICE_ID_MEILHAUS_ME14E0 0x14E0
+#define PCI_DEVICE_ID_MEILHAUS_ME14EA 0x14EA
+#define PCI_DEVICE_ID_MEILHAUS_ME14EB 0x14EB
+#define PCI_DEVICE_ID_MEILHAUS_ME140C 0X140C
+#define PCI_DEVICE_ID_MEILHAUS_ME140D 0X140D
+
+#define PCI_DEVICE_ID_MEILHAUS_ME1600_4U 0x1604 // 4 voltage outputs
+#define PCI_DEVICE_ID_MEILHAUS_ME1600_8U 0x1608 // 8 voltage outputs
+#define PCI_DEVICE_ID_MEILHAUS_ME1600_12U 0x160C // 12 voltage outputs
+#define PCI_DEVICE_ID_MEILHAUS_ME1600_16U 0x160F // 16 voltage outputs
+#define PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I 0x168F // 16 voltage/8 current o.
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4610 0x4610 // Jekyll
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 // Low Cost version
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 // Isolated version with Sample and Hold
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 // Isolated version with Sample and Hold
+
+#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 // Standard version
+#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 // Isolated version
+#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 // Standard version with Sample and Hold
+#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 // Isolated version with Sample and Hold
+
+/* ME6000 standard version */
+#define PCI_DEVICE_ID_MEILHAUS_ME6004 0x6004
+#define PCI_DEVICE_ID_MEILHAUS_ME6008 0x6008
+#define PCI_DEVICE_ID_MEILHAUS_ME600F 0x600F
+
+/* ME6000 isolated version */
+#define PCI_DEVICE_ID_MEILHAUS_ME6014 0x6014
+#define PCI_DEVICE_ID_MEILHAUS_ME6018 0x6018
+#define PCI_DEVICE_ID_MEILHAUS_ME601F 0x601F
+
+/* ME6000 isle version */
+#define PCI_DEVICE_ID_MEILHAUS_ME6034 0x6034
+#define PCI_DEVICE_ID_MEILHAUS_ME6038 0x6038
+#define PCI_DEVICE_ID_MEILHAUS_ME603F 0x603F
+
+/* ME6000 standard version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6044 0x6044
+#define PCI_DEVICE_ID_MEILHAUS_ME6048 0x6048
+#define PCI_DEVICE_ID_MEILHAUS_ME604F 0x604F
+
+/* ME6000 isolated version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6054 0x6054
+#define PCI_DEVICE_ID_MEILHAUS_ME6058 0x6058
+#define PCI_DEVICE_ID_MEILHAUS_ME605F 0x605F
+
+/* ME6000 isle version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6074 0x6074
+#define PCI_DEVICE_ID_MEILHAUS_ME6078 0x6078
+#define PCI_DEVICE_ID_MEILHAUS_ME607F 0x607F
+
+/* ME6100 standard version */
+#define PCI_DEVICE_ID_MEILHAUS_ME6104 0x6104
+#define PCI_DEVICE_ID_MEILHAUS_ME6108 0x6108
+#define PCI_DEVICE_ID_MEILHAUS_ME610F 0x610F
+
+/* ME6100 isolated version */
+#define PCI_DEVICE_ID_MEILHAUS_ME6114 0x6114
+#define PCI_DEVICE_ID_MEILHAUS_ME6118 0x6118
+#define PCI_DEVICE_ID_MEILHAUS_ME611F 0x611F
+
+/* ME6100 isle version */
+#define PCI_DEVICE_ID_MEILHAUS_ME6134 0x6134
+#define PCI_DEVICE_ID_MEILHAUS_ME6138 0x6138
+#define PCI_DEVICE_ID_MEILHAUS_ME613F 0x613F
+
+/* ME6100 standard version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6144 0x6144
+#define PCI_DEVICE_ID_MEILHAUS_ME6148 0x6148
+#define PCI_DEVICE_ID_MEILHAUS_ME614F 0x614F
+
+/* ME6100 isolated version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6154 0x6154
+#define PCI_DEVICE_ID_MEILHAUS_ME6158 0x6158
+#define PCI_DEVICE_ID_MEILHAUS_ME615F 0x615F
+
+/* ME6100 isle version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6174 0x6174
+#define PCI_DEVICE_ID_MEILHAUS_ME6178 0x6178
+#define PCI_DEVICE_ID_MEILHAUS_ME617F 0x617F
+
+/* ME6200 isolated version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6259 0x6259
+
+/* ME6300 isolated version with DIO */
+#define PCI_DEVICE_ID_MEILHAUS_ME6359 0x6359
+
+/* ME0630 */
+#define PCI_DEVICE_ID_MEILHAUS_ME0630 0x0630
+
+/* ME8100 */
+#define PCI_DEVICE_ID_MEILHAUS_ME8100_A 0x810A
+#define PCI_DEVICE_ID_MEILHAUS_ME8100_B 0x810B
+
+/* ME8200 */
+#define PCI_DEVICE_ID_MEILHAUS_ME8200_A 0x820A
+#define PCI_DEVICE_ID_MEILHAUS_ME8200_B 0x820B
+
+/* ME0900 */
+#define PCI_DEVICE_ID_MEILHAUS_ME0940 0x0940
+#define PCI_DEVICE_ID_MEILHAUS_ME0950 0x0950
+#define PCI_DEVICE_ID_MEILHAUS_ME0960 0x0960
+
+
+/*=============================================================================
+ USB Vendor IDs
+ ===========================================================================*/
+
+//#define USB_VENDOR_ID_MEPHISTO_S1 0x0403
+
+
+/*=============================================================================
+ USB Device IDs
+ ===========================================================================*/
+
+//#define USB_DEVICE_ID_MEPHISTO_S1 0xDCD0
+
+
+/* ME-1000 defines */
+#define ME1000_NAME_DRIVER "ME-1000"
+
+#define ME1000_NAME_DEVICE_ME1000 "ME-1000"
+
+#define ME1000_DESCRIPTION_DEVICE_ME1000 "ME-1000 device, 128 digital i/o lines."
+
+/* ME-1400 defines */
+#define ME1400_NAME_DRIVER "ME-1400"
+
+#define ME1400_NAME_DEVICE_ME1400 "ME-1400"
+#define ME1400_NAME_DEVICE_ME1400E "ME-1400E"
+#define ME1400_NAME_DEVICE_ME1400A "ME-1400A"
+#define ME1400_NAME_DEVICE_ME1400EA "ME-1400EA"
+#define ME1400_NAME_DEVICE_ME1400B "ME-1400B"
+#define ME1400_NAME_DEVICE_ME1400EB "ME-1400EB"
+#define ME1400_NAME_DEVICE_ME1400C "ME-1400C"
+#define ME1400_NAME_DEVICE_ME1400D "ME-1400D"
+
+#define ME1400_DESCRIPTION_DEVICE_ME1400 "ME-1400 device, 24 digital i/o lines."
+#define ME1400_DESCRIPTION_DEVICE_ME1400E "ME-1400E device, 24 digital i/o lines."
+#define ME1400_DESCRIPTION_DEVICE_ME1400A "ME-1400A device, 24 digital i/o lines, 3 counters."
+#define ME1400_DESCRIPTION_DEVICE_ME1400EA "ME-1400EA device, 24 digital i/o lines, 3 counters."
+#define ME1400_DESCRIPTION_DEVICE_ME1400B "ME-1400B device, 48 digital i/o lines, 6 counters."
+#define ME1400_DESCRIPTION_DEVICE_ME1400EB "ME-1400EB device, 48 digital i/o lines, 6 counters."
+#define ME1400_DESCRIPTION_DEVICE_ME1400C "ME-1400C device, 24 digital i/o lines, 15 counters."
+#define ME1400_DESCRIPTION_DEVICE_ME1400D "ME-1400D device, 48 digital i/o lines, 30 counters."
+
+/* ME-1600 defines */
+#define ME1600_NAME_DRIVER "ME-1600"
+
+#define ME1600_NAME_DEVICE_ME16004U "ME-1600/4U"
+#define ME1600_NAME_DEVICE_ME16008U "ME-1600/8U"
+#define ME1600_NAME_DEVICE_ME160012U "ME-1600/12U"
+#define ME1600_NAME_DEVICE_ME160016U "ME-1600/16U"
+#define ME1600_NAME_DEVICE_ME160016U8I "ME-1600/16U8I"
+
+#define ME1600_DESCRIPTION_DEVICE_ME16004U "ME-1600/4U device, 4 voltage outputs."
+#define ME1600_DESCRIPTION_DEVICE_ME16008U "ME-1600/8U device, 8 voltage outputs."
+#define ME1600_DESCRIPTION_DEVICE_ME160012U "ME-1600/12U device, 12 voltage outputs."
+#define ME1600_DESCRIPTION_DEVICE_ME160016U "ME-1600/16U device, 16 voltage outputs."
+#define ME1600_DESCRIPTION_DEVICE_ME160016U8I "ME-1600/16U8I device, 16 voltage, 8 current outputs."
+
+/* ME-4000 defines */
+#define ME4600_NAME_DRIVER "ME-4600"
+
+#define ME4600_NAME_DEVICE_ME4610 "ME-4610"
+#define ME4600_NAME_DEVICE_ME4650 "ME-4650"
+#define ME4600_NAME_DEVICE_ME4660 "ME-4660"
+#define ME4600_NAME_DEVICE_ME4660I "ME-4660I"
+#define ME4600_NAME_DEVICE_ME4660S "ME-4660S"
+#define ME4600_NAME_DEVICE_ME4660IS "ME-4660IS"
+#define ME4600_NAME_DEVICE_ME4670 "ME-4670"
+#define ME4600_NAME_DEVICE_ME4670I "ME-4670I"
+#define ME4600_NAME_DEVICE_ME4670S "ME-4670S"
+#define ME4600_NAME_DEVICE_ME4670IS "ME-4670IS"
+#define ME4600_NAME_DEVICE_ME4680 "ME-4680"
+#define ME4600_NAME_DEVICE_ME4680I "ME-4680I"
+#define ME4600_NAME_DEVICE_ME4680S "ME-4680S"
+#define ME4600_NAME_DEVICE_ME4680IS "ME-4680IS"
+
+#define ME4600_DESCRIPTION_DEVICE_ME4610 "ME-4610 device, 16 streaming analog inputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4650 "ME-4650 device, 16 streaming analog inputs, 32 digital i/o lines, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4660 "ME-4660 device, 16 streaming analog inputs, 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4660I "ME-4660I opto isolated device, 16 streaming analog inputs, 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4660S "ME-4660 device, 16 streaming analog inputs (8 S&H), 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4660IS "ME-4660I opto isolated device, 16 streaming analog inputs (8 S&H), 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4670 "ME-4670 device, 32 streaming analog inputs, 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4670I "ME-4670I opto isolated device, 32 streaming analog inputs, 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4670S "ME-4670S device, 32 streaming analog inputs (8 S&H), 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4670IS "ME-4670IS opto isolated device, 32 streaming analog inputs (8 S&H), 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4680 "ME-4680 device, 32 streaming analog inputs, 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4680I "ME-4680I opto isolated device, 32 streaming analog inputs, 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4680S "ME-4680S device, 32 streaming analog inputs, 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+#define ME4600_DESCRIPTION_DEVICE_ME4680IS "ME-4680IS opto isolated device, 32 streaming analog inputs (8 S&H), 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt."
+
+/* ME-6000 defines */
+#define ME6000_NAME_DRIVER "ME-6000"
+
+#define ME6000_NAME_DEVICE_ME60004 "ME-6000/4"
+#define ME6000_NAME_DEVICE_ME60008 "ME-6000/8"
+#define ME6000_NAME_DEVICE_ME600016 "ME-6000/16"
+#define ME6000_NAME_DEVICE_ME6000I4 "ME-6000I/4"
+#define ME6000_NAME_DEVICE_ME6000I8 "ME-6000I/8"
+#define ME6000_NAME_DEVICE_ME6000I16 "ME-6000I/16"
+#define ME6000_NAME_DEVICE_ME6000ISLE4 "ME-6000ISLE/4"
+#define ME6000_NAME_DEVICE_ME6000ISLE8 "ME-6000ISLE/8"
+#define ME6000_NAME_DEVICE_ME6000ISLE16 "ME-6000ISLE/16"
+#define ME6000_NAME_DEVICE_ME61004 "ME-6100/4"
+#define ME6000_NAME_DEVICE_ME61008 "ME-6100/8"
+#define ME6000_NAME_DEVICE_ME610016 "ME-6100/16"
+#define ME6000_NAME_DEVICE_ME6100I4 "ME-6100I/4"
+#define ME6000_NAME_DEVICE_ME6100I8 "ME-6100I/8"
+#define ME6000_NAME_DEVICE_ME6100I16 "ME-6100I/16"
+#define ME6000_NAME_DEVICE_ME6100ISLE4 "ME-6100ISLE/4"
+#define ME6000_NAME_DEVICE_ME6100ISLE8 "ME-6100ISLE/8"
+#define ME6000_NAME_DEVICE_ME6100ISLE16 "ME-6100ISLE/16"
+#define ME6000_NAME_DEVICE_ME60004DIO "ME-6000/4/DIO"
+#define ME6000_NAME_DEVICE_ME60008DIO "ME-6000/8/DIO"
+#define ME6000_NAME_DEVICE_ME600016DIO "ME-6000/16/DIO"
+#define ME6000_NAME_DEVICE_ME6000I4DIO "ME-6000I/4/DIO"
+#define ME6000_NAME_DEVICE_ME6000I8DIO "ME-6000I/8/DIO"
+#define ME6000_NAME_DEVICE_ME6000I16DIO "ME-6000I/16/DIO"
+#define ME6000_NAME_DEVICE_ME6000ISLE4DIO "ME-6000ISLE/4/DIO"
+#define ME6000_NAME_DEVICE_ME6000ISLE8DIO "ME-6000ISLE/8/DIO"
+#define ME6000_NAME_DEVICE_ME6000ISLE16DIO "ME-6000ISLE/16/DIO"
+#define ME6000_NAME_DEVICE_ME61004DIO "ME-6100/4/DIO"
+#define ME6000_NAME_DEVICE_ME61008DIO "ME-6100/8/DIO"
+#define ME6000_NAME_DEVICE_ME610016DIO "ME-6100/16/DIO"
+#define ME6000_NAME_DEVICE_ME6100I4DIO "ME-6100I/4/DIO"
+#define ME6000_NAME_DEVICE_ME6100I8DIO "ME-6100I/8/DIO"
+#define ME6000_NAME_DEVICE_ME6100I16DIO "ME-6100I/16/DIO"
+#define ME6000_NAME_DEVICE_ME6100ISLE4DIO "ME-6100ISLE/4/DIO"
+#define ME6000_NAME_DEVICE_ME6100ISLE8DIO "ME-6100ISLE/8/DIO"
+#define ME6000_NAME_DEVICE_ME6100ISLE16DIO "ME-6100ISLE/16/DIO"
+#define ME6000_NAME_DEVICE_ME6200I9DIO "ME-6200I/9/DIO"
+#define ME6000_NAME_DEVICE_ME6300I9DIO "ME-6300I/9/DIO"
+
+#define ME6000_DESCRIPTION_DEVICE_ME60004 "ME-6000/4 device, 4 single analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME60008 "ME-6000/8 device, 8 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME600016 "ME-6000/16 device, 16 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME6000I4 "ME-6000I/4 isolated device, 4 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME6000I8 "ME-6000I/8 isolated device, 8 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME6000I16 "ME-6000I/16 isolated device, 16 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE4 "ME-6000ISLE/4 isle device, 4 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE8 "ME-6000ISLE/8 isle device, 8 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE16 "ME-6000ISLE/16 isle device, 16 single analog outputs"
+#define ME6000_DESCRIPTION_DEVICE_ME61004 "ME-6100/4 device, 4 streaming analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME61008 "ME-6100/8 device, 4 streaming, 4 single analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME610016 "ME-6100/16 device, 4 streaming, 12 single analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME6100I4 "ME-6100I/4 isolated device, 4 streaming analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME6100I8 "ME-6100I/8 isolated device, 4 streaming, 4 single analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME6100I16 "ME-6100I/16 isolated device, 4 streaming, 12 single analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE4 "ME-6100ISLE/4 isle device, 4 streaming analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE8 "ME-6100ISLE/8 isle device, 4 streaming, 4 single analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE16 "ME-6100ISLE/16 isle device, 4 streaming, 12 single analog outputs."
+#define ME6000_DESCRIPTION_DEVICE_ME60004DIO "ME-6000/4/DIO device, 4 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME60008DIO "ME-6000/8/DIO device, 8 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME600016DIO "ME-6000/16/DIO device, 8 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6000I4DIO "ME-6000I/4/DIO isolated device, 4 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6000I8DIO "ME-6000I/8/DIO isolated device, 8 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6000I16DIO "ME-6000I/16/DIO isolated device, 16 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO "ME-6000ISLE/4/DIO isle device, 4 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO "ME-6000ISLE/8/DIO isle device, 8 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO "ME-6000ISLE/16/DIO isle device, 16 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME61004DIO "ME-6100/4/DIO device, 4 streaming analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME61008DIO "ME-6100/8/DIO device, 4 streaming, 4 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME610016DIO "ME-6100/16/DIO device, 4 streaming, 12 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6100I4DIO "ME-6100I/4/DIO isolated device, 4 streaming analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6100I8DIO "ME-6100I/8/DIO isolated device, 4 streaming, 4 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6100I16DIO "ME-6100I/16/DIO isolated device, 4 streaming, 12 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO "ME-6100ISLE/4/DIO isle device, 4 streaming analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO "ME-6100ISLE/8/DIO isle device, 4 streaming, 4 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO "ME-6100ISLE/16/DIO isle device, 4 streaming, 12 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6200I9DIO "ME-6200I/9/DIO isolated device, 9 single analog outputs, 16 digital i/o lines."
+#define ME6000_DESCRIPTION_DEVICE_ME6300I9DIO "ME-6300I/9/DIO isolated device, 4 streaming, 5 single analog outputs, 16 digital i/o lines."
+
+/* ME-630 defines */
+#define ME0600_NAME_DRIVER "ME-0600"
+
+#define ME0600_NAME_DEVICE_ME0630 "ME-630"
+
+#define ME0600_DESCRIPTION_DEVICE_ME0630 "ME-630 device, up to 16 relay, 8 digital ttl input lines, 8 isolated digital input lines, 16 digital i/o lines, 2 external interrupts."
+
+/* ME-8100 defines */
+#define ME8100_NAME_DRIVER "ME-8100"
+
+#define ME8100_NAME_DEVICE_ME8100A "ME-8100A"
+#define ME8100_NAME_DEVICE_ME8100B "ME-8100B"
+
+#define ME8100_DESCRIPTION_DEVICE_ME8100A "ME-8100A opto isolated device, 16 digital input lines, 16 digital output lines."
+#define ME8100_DESCRIPTION_DEVICE_ME8100B "ME-8100B opto isolated device, 32 digital input lines, 32 digital output lines, 3 counters."
+
+/* ME-8200 defines */
+#define ME8200_NAME_DRIVER "ME-8200"
+
+#define ME8200_NAME_DEVICE_ME8200A "ME-8200A"
+#define ME8200_NAME_DEVICE_ME8200B "ME-8200B"
+
+#define ME8200_DESCRIPTION_DEVICE_ME8200A "ME-8200A opto isolated device, 8 digital output lines, 8 digital input lines, 16 digital i/o lines."
+#define ME8200_DESCRIPTION_DEVICE_ME8200B "ME-8200B opto isolated device, 16 digital output lines, 16 digital input lines, 16 digital i/o lines."
+
+/* ME-0900 defines */
+#define ME0900_NAME_DRIVER "ME-0900"
+
+#define ME0900_NAME_DEVICE_ME0940 "ME-94"
+#define ME0900_NAME_DEVICE_ME0950 "ME-95"
+#define ME0900_NAME_DEVICE_ME0960 "ME-96"
+
+#define ME0900_DESCRIPTION_DEVICE_ME0940 "ME-94 device, 16 digital input lines, 2 external interrupt lines."
+#define ME0900_DESCRIPTION_DEVICE_ME0950 "ME-95 device, 16 digital output lines."
+#define ME0900_DESCRIPTION_DEVICE_ME0960 "ME-96 device, 8 digital input lines, 8 digital output lines, 2 external interrupt lines."
+
+/* ME-DUMMY defines */
+#define MEDUMMY_NAME_DRIVER "ME-Dummy"
+
+/* MEPHISTO_S1 defines */
+/*
+#define MEPHISTO_S1_NAME_DRIVER "MEphisto Scope 1"
+#define MEPHISTO_S1_NAME_DEVICE "MEphisto Scope 1"
+#define MEPHISTO_S1_DESCRIPTION_DEVICE "MEphisto Scope 1 device, 2 analog inputs, 24 digital i/o."
+*/
+/* Error defines */
+#define EMPTY_NAME_DRIVER "ME-???"
+#define EMPTY_NAME_DEVICE "ME-???"
+#define EMPTY_DESCRIPTION_DEVICE "ME-??? unknown device"
+
+#endif
diff --git a/drivers/staging/meilhaus/meioctl.h b/drivers/staging/meilhaus/meioctl.h
new file mode 100644
index 000000000000..6dc719fba57c
--- /dev/null
+++ b/drivers/staging/meilhaus/meioctl.h
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : meioctl.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ */
+
+#ifndef _MEIOCTL_H_
+#define _MEIOCTL_H_
+
+
+/*=============================================================================
+ Types for the input/output ioctls
+ ===========================================================================*/
+
+typedef struct me_io_irq_start {
+ int device;
+ int subdevice;
+ int channel;
+ int irq_source;
+ int irq_edge;
+ int irq_arg;
+ int flags;
+ int errno;
+} me_io_irq_start_t;
+
+
+typedef struct me_io_irq_wait {
+ int device;
+ int subdevice;
+ int channel;
+ int irq_count;
+ int value;
+ int time_out;
+ int flags;
+ int errno;
+} me_io_irq_wait_t;
+
+
+typedef struct me_io_irq_stop {
+ int device;
+ int subdevice;
+ int channel;
+ int flags;
+ int errno;
+} me_io_irq_stop_t;
+
+
+typedef struct me_io_reset_device {
+ int device;
+ int flags;
+ int errno;
+} me_io_reset_device_t;
+
+
+typedef struct me_io_reset_subdevice {
+ int device;
+ int subdevice;
+ int flags;
+ int errno;
+} me_io_reset_subdevice_t;
+
+
+typedef struct me_io_single_config {
+ int device;
+ int subdevice;
+ int channel;
+ int single_config;
+ int ref;
+ int trig_chan;
+ int trig_type;
+ int trig_edge;
+ int flags;
+ int errno;
+} me_io_single_config_t;
+
+
+typedef struct me_io_single {
+ meIOSingle_t *single_list;
+ int count;
+ int flags;
+ int errno;
+} me_io_single_t;
+
+
+typedef struct me_io_stream_config {
+ int device;
+ int subdevice;
+ meIOStreamConfig_t *config_list;
+ int count;
+ meIOStreamTrigger_t trigger;
+ int fifo_irq_threshold;
+ int flags;
+ int errno;
+} me_io_stream_config_t;
+
+
+typedef struct me_io_stream_new_values {
+ int device;
+ int subdevice;
+ int time_out;
+ int count;
+ int flags;
+ int errno;
+} me_io_stream_new_values_t;
+
+
+typedef struct me_io_stream_read {
+ int device;
+ int subdevice;
+ int read_mode;
+ int *values;
+ int count;
+ int flags;
+ int errno;
+} me_io_stream_read_t;
+
+
+typedef struct me_io_stream_start {
+ meIOStreamStart_t *start_list;
+ int count;
+ int flags;
+ int errno;
+} me_io_stream_start_t;
+
+
+typedef struct me_io_stream_status {
+ int device;
+ int subdevice;
+ int wait;
+ int status;
+ int count;
+ int flags;
+ int errno;
+} me_io_stream_status_t;
+
+
+typedef struct me_io_stream_stop {
+ meIOStreamStop_t *stop_list;
+ int count;
+ int flags;
+ int errno;
+} me_io_stream_stop_t;
+
+
+typedef struct me_io_stream_write {
+ int device;
+ int subdevice;
+ int write_mode;
+ int *values;
+ int count;
+ int flags;
+ int errno;
+} me_io_stream_write_t;
+
+
+/*=============================================================================
+ Types for the lock ioctls
+ ===========================================================================*/
+
+typedef struct me_lock_device {
+ int device;
+ int lock;
+ int flags;
+ int errno;
+} me_lock_device_t;
+
+
+typedef struct me_lock_driver {
+ int flags;
+ int lock;
+ int errno;
+} me_lock_driver_t;
+
+
+typedef struct me_lock_subdevice {
+ int device;
+ int subdevice;
+ int lock;
+ int flags;
+ int errno;
+} me_lock_subdevice_t;
+
+
+/*=============================================================================
+ Types for the query ioctls
+ ===========================================================================*/
+
+typedef struct me_query_info_device {
+ int device;
+ int vendor_id;
+ int device_id;
+ int serial_no;
+ int bus_type;
+ int bus_no;
+ int dev_no;
+ int func_no;
+ int plugged;
+ int errno;
+} me_query_info_device_t;
+
+
+typedef struct me_query_description_device {
+ int device;
+ char *name;
+ int count;
+ int errno;
+} me_query_description_device_t;
+
+
+typedef struct me_query_name_device {
+ int device;
+ char *name;
+ int count;
+ int errno;
+} me_query_name_device_t;
+
+
+typedef struct me_query_name_device_driver {
+ int device;
+ char *name;
+ int count;
+ int errno;
+} me_query_name_device_driver_t;
+
+
+typedef struct me_query_version_main_driver {
+ int version;
+ int errno;
+} me_query_version_main_driver_t;
+
+
+typedef struct me_query_version_device_driver {
+ int device;
+ int version;
+ int errno;
+} me_query_version_device_driver_t;
+
+
+typedef struct me_query_number_devices {
+ int number;
+ int errno;
+} me_query_number_devices_t;
+
+
+typedef struct me_query_number_subdevices {
+ int device;
+ int number;
+ int errno;
+} me_query_number_subdevices_t;
+
+
+typedef struct me_query_number_channels {
+ int device;
+ int subdevice;
+ int number;
+ int errno;
+} me_query_number_channels_t;
+
+
+typedef struct me_query_number_ranges {
+ int device;
+ int subdevice;
+ int channel;
+ int unit;
+ int number;
+ int errno;
+} me_query_number_ranges_t;
+
+
+typedef struct me_query_subdevice_by_type {
+ int device;
+ int start_subdevice;
+ int type;
+ int subtype;
+ int subdevice;
+ int errno;
+} me_query_subdevice_by_type_t;
+
+
+typedef struct me_query_subdevice_type {
+ int device;
+ int subdevice;
+ int type;
+ int subtype;
+ int errno;
+} me_query_subdevice_type_t;
+
+
+typedef struct me_query_subdevice_caps {
+ int device;
+ int subdevice;
+ int caps;
+ int errno;
+} me_query_subdevice_caps_t;
+
+
+typedef struct me_query_subdevice_caps_args {
+ int device;
+ int subdevice;
+ int cap;
+ int args[8];
+ int count;
+ int errno;
+} me_query_subdevice_caps_args_t;
+
+
+typedef struct me_query_timer {
+ int device;
+ int subdevice;
+ int timer;
+ int base_frequency;
+ long long min_ticks;
+ long long max_ticks;
+ int errno;
+} me_query_timer_t;
+
+
+typedef struct me_query_range_by_min_max {
+ int device;
+ int subdevice;
+ int channel;
+ int unit;
+ int min;
+ int max;
+ int max_data;
+ int range;
+ int errno;
+} me_query_range_by_min_max_t;
+
+
+typedef struct me_query_range_info {
+ int device;
+ int subdevice;
+ int channel;
+ int unit;
+ int range;
+ int min;
+ int max;
+ int max_data;
+ int errno;
+} me_query_range_info_t;
+
+
+/*=============================================================================
+ Types for the configuration ioctls
+ ===========================================================================*/
+
+typedef struct me_cfg_tcpip_location {
+ int access_type;
+ char *remote_host;
+ int remote_device_number;
+} me_cfg_tcpip_location_t;
+
+
+typedef union me_cfg_tcpip {
+ int access_type;
+ me_cfg_tcpip_location_t location;
+} me_cfg_tcpip_t;
+
+
+typedef struct me_cfg_pci_hw_location {
+ unsigned int bus_type;
+ unsigned int bus_no;
+ unsigned int device_no;
+ unsigned int function_no;
+} me_cfg_pci_hw_location_t;
+
+/*
+typedef struct me_cfg_usb_hw_location {
+ unsigned int bus_type;
+ unsigned int root_hub_no;
+} me_cfg_usb_hw_location_t;
+*/
+
+typedef union me_cfg_hw_location {
+ unsigned int bus_type;
+ me_cfg_pci_hw_location_t pci;
+// me_cfg_usb_hw_location_t usb;
+} me_cfg_hw_location_t;
+
+
+typedef struct me_cfg_device_info {
+ unsigned int vendor_id;
+ unsigned int device_id;
+ unsigned int serial_no;
+ me_cfg_hw_location_t hw_location;
+} me_cfg_device_info_t;
+
+
+typedef struct me_cfg_subdevice_info {
+ int type;
+ int sub_type;
+ unsigned int number_channels;
+} me_cfg_subdevice_info_t;
+
+
+typedef struct me_cfg_range_entry {
+ int unit;
+ double min;
+ double max;
+ unsigned int max_data;
+} me_cfg_range_entry_t;
+
+
+typedef struct me_cfg_mux32m_device {
+ int type;
+ int timed;
+ unsigned int ai_channel;
+ unsigned int dio_device;
+ unsigned int dio_subdevice;
+ unsigned int timer_device;
+ unsigned int timer_subdevice;
+ unsigned int mux32s_count;
+} me_cfg_mux32m_device_t;
+
+
+typedef struct me_cfg_demux32_device {
+ int type;
+ int timed;
+ unsigned int ao_channel;
+ unsigned int dio_device;
+ unsigned int dio_subdevice;
+ unsigned int timer_device;
+ unsigned int timer_subdevice;
+} me_cfg_demux32_device_t;
+
+
+typedef union me_cfg_external_device {
+ int type;
+ me_cfg_mux32m_device_t mux32m;
+ me_cfg_demux32_device_t demux32;
+} me_cfg_external_device_t;
+
+
+typedef struct me_cfg_subdevice_entry {
+ me_cfg_subdevice_info_t info;
+ me_cfg_range_entry_t *range_list;
+ unsigned int count;
+ int locked;
+ me_cfg_external_device_t external_device;
+} me_cfg_subdevice_entry_t;
+
+
+typedef struct me_cfg_device_entry {
+ me_cfg_tcpip_t tcpip;
+ me_cfg_device_info_t info;
+ me_cfg_subdevice_entry_t *subdevice_list;
+ unsigned int count;
+} me_cfg_device_entry_t;
+
+
+typedef struct me_config_load {
+ me_cfg_device_entry_t *device_list;
+ unsigned int count;
+ int errno;
+} me_config_load_t;
+
+
+/*=============================================================================
+ The ioctls of the board
+ ===========================================================================*/
+
+#define MEMAIN_MAGIC 'y'
+
+#define ME_IO_IRQ_ENABLE _IOR (MEMAIN_MAGIC, 1, me_io_irq_start_t)
+#define ME_IO_IRQ_WAIT _IOR (MEMAIN_MAGIC, 2, me_io_irq_wait_t)
+#define ME_IO_IRQ_DISABLE _IOR (MEMAIN_MAGIC, 3, me_io_irq_stop_t)
+
+#define ME_IO_RESET_DEVICE _IOW (MEMAIN_MAGIC, 4, me_io_reset_device_t)
+#define ME_IO_RESET_SUBDEVICE _IOW (MEMAIN_MAGIC, 5, me_io_reset_subdevice_t)
+
+#define ME_IO_SINGLE _IOWR(MEMAIN_MAGIC, 6, me_io_single_t)
+#define ME_IO_SINGLE_CONFIG _IOW (MEMAIN_MAGIC, 7, me_io_single_config_t)
+
+#define ME_IO_STREAM_CONFIG _IOW (MEMAIN_MAGIC, 8, me_io_stream_config_t)
+#define ME_IO_STREAM_NEW_VALUES _IOR (MEMAIN_MAGIC, 9, me_io_stream_new_values_t)
+#define ME_IO_STREAM_READ _IOR (MEMAIN_MAGIC, 10, me_io_stream_read_t)
+#define ME_IO_STREAM_START _IOW (MEMAIN_MAGIC, 11, me_io_stream_start_t)
+#define ME_IO_STREAM_STATUS _IOR (MEMAIN_MAGIC, 12, me_io_stream_status_t)
+#define ME_IO_STREAM_STOP _IOW (MEMAIN_MAGIC, 13, me_io_stream_stop_t)
+#define ME_IO_STREAM_WRITE _IOW (MEMAIN_MAGIC, 14, me_io_stream_write_t)
+
+#define ME_LOCK_DRIVER _IOW (MEMAIN_MAGIC, 15, me_lock_driver_t)
+#define ME_LOCK_DEVICE _IOW (MEMAIN_MAGIC, 16, me_lock_device_t)
+#define ME_LOCK_SUBDEVICE _IOW (MEMAIN_MAGIC, 17, me_lock_subdevice_t)
+
+#define ME_QUERY_DESCRIPTION_DEVICE _IOR (MEMAIN_MAGIC, 18, me_query_description_device_t)
+
+#define ME_QUERY_INFO_DEVICE _IOR (MEMAIN_MAGIC, 19, me_query_info_device_t)
+
+#define ME_QUERY_NAME_DEVICE _IOR (MEMAIN_MAGIC, 20, me_query_name_device_t)
+#define ME_QUERY_NAME_DEVICE_DRIVER _IOR (MEMAIN_MAGIC, 21, me_query_name_device_driver_t)
+
+#define ME_QUERY_NUMBER_DEVICES _IOR (MEMAIN_MAGIC, 22, me_query_number_devices_t)
+#define ME_QUERY_NUMBER_SUBDEVICES _IOR (MEMAIN_MAGIC, 23, me_query_number_subdevices_t)
+#define ME_QUERY_NUMBER_CHANNELS _IOR (MEMAIN_MAGIC, 24, me_query_number_channels_t)
+#define ME_QUERY_NUMBER_RANGES _IOR (MEMAIN_MAGIC, 25, me_query_number_ranges_t)
+
+#define ME_QUERY_RANGE_BY_MIN_MAX _IOR (MEMAIN_MAGIC, 26, me_query_range_by_min_max_t)
+#define ME_QUERY_RANGE_INFO _IOR (MEMAIN_MAGIC, 27, me_query_range_info_t)
+
+#define ME_QUERY_SUBDEVICE_BY_TYPE _IOR (MEMAIN_MAGIC, 28, me_query_subdevice_by_type_t)
+#define ME_QUERY_SUBDEVICE_TYPE _IOR (MEMAIN_MAGIC, 29, me_query_subdevice_type_t)
+#define ME_QUERY_SUBDEVICE_CAPS _IOR (MEMAIN_MAGIC, 29, me_query_subdevice_caps_t)
+#define ME_QUERY_SUBDEVICE_CAPS_ARGS _IOR (MEMAIN_MAGIC, 30, me_query_subdevice_caps_args_t)
+
+#define ME_QUERY_TIMER _IOR (MEMAIN_MAGIC, 31, me_query_timer_t)
+
+#define ME_QUERY_VERSION_DEVICE_DRIVER _IOR (MEMAIN_MAGIC, 32, me_query_version_device_driver_t)
+#define ME_QUERY_VERSION_MAIN_DRIVER _IOR (MEMAIN_MAGIC, 33, me_query_version_main_driver_t)
+
+#define ME_CONFIG_LOAD _IOWR(MEMAIN_MAGIC, 34, me_config_load_t)
+
+#endif
diff --git a/drivers/staging/meilhaus/memain.c b/drivers/staging/meilhaus/memain.c
new file mode 100644
index 000000000000..b09d1a6c766c
--- /dev/null
+++ b/drivers/staging/meilhaus/memain.c
@@ -0,0 +1,2022 @@
+/**
+ * @file memain.c
+ *
+ * @brief Main Meilhaus device driver.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ * @author Krzysztof Gantzke (k.gantzke@meilhaus.de)
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+#include <linux/pci.h>
+//#include <linux/usb.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/cdev.h>
+#include <linux/rwsem.h>
+
+#include "medefines.h"
+#include "metypes.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "memain.h"
+#include "medevice.h"
+#include "meioctl.h"
+#include "mecommon.h"
+
+/* Module parameters
+*/
+
+#ifdef BOSCH
+static unsigned int me_bosch_fw = 0;
+
+# ifdef module_param
+module_param(me_bosch_fw, int, S_IRUGO);
+# else
+MODULE_PARM(me_bosch_fw, "i");
+# endif
+
+MODULE_PARM_DESC(me_bosch_fw,
+ "Flags which signals the ME-4600 driver to load the bosch firmware (default = 0).");
+#endif //BOSCH
+
+static unsigned int major = 0;
+#ifdef module_param
+module_param(major, int, S_IRUGO);
+#else
+MODULE_PARM(major, "i");
+#endif
+
+/* Global Driver Lock
+*/
+
+static struct file *me_filep = NULL;
+static int me_count = 0;
+static spinlock_t me_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_RWSEM(me_rwsem);
+
+/* Board instances are kept in a global list */
+LIST_HEAD(me_device_list);
+
+/* Prototypes
+*/
+
+static int me_probe_pci(struct pci_dev *dev, const struct pci_device_id *id);
+static void me_remove_pci(struct pci_dev *dev);
+static int insert_to_device_list(me_device_t * n_device);
+static int replace_with_dummy(int vendor_id, int device_id, int serial_no);
+static void clear_device_list(void);
+static int me_open(struct inode *inode_ptr, struct file *filep);
+static int me_release(struct inode *, struct file *);
+static int me_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+//static int me_probe_usb(struct usb_interface *interface, const struct usb_device_id *id);
+//static void me_disconnect_usb(struct usb_interface *interface);
+
+/* Character device structure
+*/
+
+static struct cdev *cdevp;
+
+/* File operations provided by the module
+*/
+
+static struct file_operations me_file_operations = {
+ .owner = THIS_MODULE,
+ .ioctl = me_ioctl,
+ .open = me_open,
+ .release = me_release,
+};
+
+struct pci_driver me_pci_driver = {
+ .name = MEMAIN_NAME,
+ .id_table = me_pci_table,
+ .probe = me_probe_pci,
+ .remove = me_remove_pci
+};
+
+/* //me_usb_driver
+static struct usb_driver me_usb_driver =
+{
+ .name = MEMAIN_NAME,
+ .id_table = me_usb_table,
+ .probe = me_probe_usb,
+ .disconnect = me_disconnect_usb
+};
+*/
+
+#ifdef ME_LOCK_MULTIPLEX_TEMPLATE
+ME_LOCK_MULTIPLEX_TEMPLATE("me_lock_device",
+ me_lock_device_t,
+ me_lock_device,
+ me_device_lock_device,
+ (device, filep, karg.lock, karg.flags))
+
+ ME_LOCK_MULTIPLEX_TEMPLATE("me_lock_subdevice",
+ me_lock_subdevice_t,
+ me_lock_subdevice,
+ me_device_lock_subdevice,
+ (device, filep, karg.subdevice, karg.lock,
+ karg.flags))
+#else
+#error macro ME_LOCK_MULTIPLEX_TEMPLATE not defined
+#endif
+
+#ifdef ME_IO_MULTIPLEX_TEMPLATE
+ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_start",
+ me_io_irq_start_t,
+ me_io_irq_start,
+ me_device_io_irq_start,
+ (device,
+ filep,
+ karg.subdevice,
+ karg.channel,
+ karg.irq_source,
+ karg.irq_edge, karg.irq_arg, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_wait",
+ me_io_irq_wait_t,
+ me_io_irq_wait,
+ me_device_io_irq_wait,
+ (device,
+ filep,
+ karg.subdevice,
+ karg.channel,
+ &karg.irq_count, &karg.value, karg.time_out, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_stop",
+ me_io_irq_stop_t,
+ me_io_irq_stop,
+ me_device_io_irq_stop,
+ (device,
+ filep, karg.subdevice, karg.channel, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_reset_device",
+ me_io_reset_device_t,
+ me_io_reset_device,
+ me_device_io_reset_device, (device, filep, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_reset_subdevice",
+ me_io_reset_subdevice_t,
+ me_io_reset_subdevice,
+ me_device_io_reset_subdevice,
+ (device, filep, karg.subdevice, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_single_config",
+ me_io_single_config_t,
+ me_io_single_config,
+ me_device_io_single_config,
+ (device,
+ filep,
+ karg.subdevice,
+ karg.channel,
+ karg.single_config,
+ karg.ref,
+ karg.trig_chan,
+ karg.trig_type, karg.trig_edge, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_new_values",
+ me_io_stream_new_values_t,
+ me_io_stream_new_values,
+ me_device_io_stream_new_values,
+ (device,
+ filep,
+ karg.subdevice, karg.time_out, &karg.count, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_read",
+ me_io_stream_read_t,
+ me_io_stream_read,
+ me_device_io_stream_read,
+ (device,
+ filep,
+ karg.subdevice,
+ karg.read_mode, karg.values, &karg.count, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_status",
+ me_io_stream_status_t,
+ me_io_stream_status,
+ me_device_io_stream_status,
+ (device,
+ filep,
+ karg.subdevice,
+ karg.wait, &karg.status, &karg.count, karg.flags))
+
+ ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_write",
+ me_io_stream_write_t,
+ me_io_stream_write,
+ me_device_io_stream_write,
+ (device,
+ filep,
+ karg.subdevice,
+ karg.write_mode, karg.values, &karg.count, karg.flags))
+#else
+#error macro ME_IO_MULTIPLEX_TEMPLATE not defined
+#endif
+
+#ifdef ME_QUERY_MULTIPLEX_STR_TEMPLATE
+ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_name_device",
+ me_query_name_device_t,
+ me_query_name_device,
+ me_device_query_name_device, (device, &msg))
+
+ ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_name_device_driver",
+ me_query_name_device_driver_t,
+ me_query_name_device_driver,
+ me_device_query_name_device_driver,
+ (device, &msg))
+
+ ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_description_device",
+ me_query_description_device_t,
+ me_query_description_device,
+ me_device_query_description_device,
+ (device, &msg))
+#else
+#error macro ME_QUERY_MULTIPLEX_STR_TEMPLATE not defined
+#endif
+
+#ifdef ME_QUERY_MULTIPLEX_TEMPLATE
+ME_QUERY_MULTIPLEX_TEMPLATE("me_query_info_device",
+ me_query_info_device_t,
+ me_query_info_device,
+ me_device_query_info_device,
+ (device,
+ &karg.vendor_id,
+ &karg.device_id,
+ &karg.serial_no,
+ &karg.bus_type,
+ &karg.bus_no,
+ &karg.dev_no, &karg.func_no, &karg.plugged))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_subdevices",
+ me_query_number_subdevices_t,
+ me_query_number_subdevices,
+ me_device_query_number_subdevices,
+ (device, &karg.number))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_channels",
+ me_query_number_channels_t,
+ me_query_number_channels,
+ me_device_query_number_channels,
+ (device, karg.subdevice, &karg.number))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_by_type",
+ me_query_subdevice_by_type_t,
+ me_query_subdevice_by_type,
+ me_device_query_subdevice_by_type,
+ (device,
+ karg.start_subdevice,
+ karg.type, karg.subtype, &karg.subdevice))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_type",
+ me_query_subdevice_type_t,
+ me_query_subdevice_type,
+ me_device_query_subdevice_type,
+ (device, karg.subdevice, &karg.type, &karg.subtype))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_caps",
+ me_query_subdevice_caps_t,
+ me_query_subdevice_caps,
+ me_device_query_subdevice_caps,
+ (device, karg.subdevice, &karg.caps))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_caps_args",
+ me_query_subdevice_caps_args_t,
+ me_query_subdevice_caps_args,
+ me_device_query_subdevice_caps_args,
+ (device, karg.subdevice, karg.cap, karg.args,
+ karg.count))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_ranges",
+ me_query_number_ranges_t,
+ me_query_number_ranges,
+ me_device_query_number_ranges,
+ (device, karg.subdevice, karg.unit, &karg.number))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_range_by_min_max",
+ me_query_range_by_min_max_t,
+ me_query_range_by_min_max,
+ me_device_query_range_by_min_max,
+ (device,
+ karg.subdevice,
+ karg.unit,
+ &karg.min, &karg.max, &karg.max_data, &karg.range))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_range_info",
+ me_query_range_info_t,
+ me_query_range_info,
+ me_device_query_range_info,
+ (device,
+ karg.subdevice,
+ karg.range,
+ &karg.unit, &karg.min, &karg.max, &karg.max_data))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_timer",
+ me_query_timer_t,
+ me_query_timer,
+ me_device_query_timer,
+ (device,
+ karg.subdevice,
+ karg.timer,
+ &karg.base_frequency,
+ &karg.min_ticks, &karg.max_ticks))
+
+ ME_QUERY_MULTIPLEX_TEMPLATE("me_query_version_device_driver",
+ me_query_version_device_driver_t,
+ me_query_version_device_driver,
+ me_device_query_version_device_driver,
+ (device, &karg.version))
+#else
+#error macro ME_QUERY_MULTIPLEX_TEMPLATE not defined
+#endif
+
+/** ******************************************************************************** **/
+
+static me_device_t *get_dummy_instance(unsigned short vendor_id,
+ unsigned short device_id,
+ unsigned int serial_no,
+ int bus_type,
+ int bus_no, int dev_no, int func_no)
+{
+ int err;
+ me_dummy_constructor_t constructor = NULL;
+ me_device_t *instance;
+
+ PDEBUG("executed.\n");
+
+ if ((constructor = symbol_get(medummy_constructor)) == NULL) {
+ err = request_module(MEDUMMY_NAME);
+
+ if (err) {
+ PERROR("Error while request for module %s.\n",
+ MEDUMMY_NAME);
+ return NULL;
+ }
+
+ if ((constructor = symbol_get(medummy_constructor)) == NULL) {
+ PERROR("Can't get %s driver module constructor.\n",
+ MEDUMMY_NAME);
+ return NULL;
+ }
+ }
+
+ if ((instance = (*constructor) (vendor_id,
+ device_id,
+ serial_no,
+ bus_type,
+ bus_no, dev_no, func_no)) == NULL)
+ symbol_put(medummy_constructor);
+
+ return instance;
+}
+
+static int me_probe_pci(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int err;
+ me_pci_constructor_t constructor = NULL;
+#ifdef BOSCH
+ me_bosch_constructor_t constructor_bosch = NULL;
+#endif
+ me_device_t *n_device = NULL;
+ uint32_t device;
+
+ char constructor_name[24] = "me0000_pci_constructor";
+ char module_name[7] = "me0000";
+
+ PDEBUG("executed.\n");
+ device = dev->device;
+ if ((device & 0xF000) == 0x6000) { // Exceptions: me61xx, me62xx, me63xx are handled by one driver.
+ device &= 0xF0FF;
+ }
+
+ constructor_name[2] += (char)((device >> 12) & 0x000F);
+ constructor_name[3] += (char)((device >> 8) & 0x000F);
+ PDEBUG("constructor_name: %s\n", constructor_name);
+ module_name[2] += (char)((device >> 12) & 0x000F);
+ module_name[3] += (char)((device >> 8) & 0x000F);
+ PDEBUG("module_name: %s\n", module_name);
+
+ if ((constructor =
+ (me_pci_constructor_t) symbol_get(constructor_name)) == NULL) {
+ if (request_module(module_name)) {
+ PERROR("Error while request for module %s.\n",
+ module_name);
+ return -ENODEV;
+ }
+
+ if ((constructor =
+ (me_pci_constructor_t) symbol_get(constructor_name)) ==
+ NULL) {
+ PERROR("Can't get %s driver module constructor.\n",
+ module_name);
+ return -ENODEV;
+ }
+ }
+#ifdef BOSCH
+ if ((device & 0xF000) == 0x4000) { // Bosch build has differnt constructor for me4600.
+ if ((n_device =
+ (*constructor_bosch) (dev, me_bosch_fw)) == NULL) {
+ symbol_put(constructor_name);
+ PERROR
+ ("Can't get device instance of %s driver module.\n",
+ module_name);
+ return -ENODEV;
+ }
+ } else {
+#endif
+ if ((n_device = (*constructor) (dev)) == NULL) {
+ symbol_put(constructor_name);
+ PERROR
+ ("Can't get device instance of %s driver module.\n",
+ module_name);
+ return -ENODEV;
+ }
+#ifdef BOSCH
+ }
+#endif
+
+ insert_to_device_list(n_device);
+ err =
+ n_device->me_device_io_reset_device(n_device, NULL,
+ ME_IO_RESET_DEVICE_NO_FLAGS);
+ if (err) {
+ PERROR("Error while reseting device.\n");
+ } else {
+ PDEBUG("Reseting device was sucessful.\n");
+ }
+ return ME_ERRNO_SUCCESS;
+}
+
+static void release_instance(me_device_t * device)
+{
+ int vendor_id;
+ int device_id;
+ int serial_no;
+ int bus_type;
+ int bus_no;
+ int dev_no;
+ int func_no;
+ int plugged;
+
+ uint32_t dev_id;
+
+ char constructor_name[24] = "me0000_pci_constructor";
+
+ PDEBUG("executed.\n");
+
+ device->me_device_query_info_device(device,
+ &vendor_id,
+ &device_id,
+ &serial_no,
+ &bus_type,
+ &bus_no,
+ &dev_no, &func_no, &plugged);
+
+ dev_id = device_id;
+ device->me_device_destructor(device);
+
+ if (plugged != ME_PLUGGED_IN) {
+ PDEBUG("release: medummy_constructor\n");
+
+ symbol_put("medummy_constructor");
+ } else {
+ if ((dev_id & 0xF000) == 0x6000) { // Exceptions: me61xx, me62xx, me63xx are handled by one driver.
+ dev_id &= 0xF0FF;
+ }
+
+ constructor_name[2] += (char)((dev_id >> 12) & 0x000F);
+ constructor_name[3] += (char)((dev_id >> 8) & 0x000F);
+ PDEBUG("release: %s\n", constructor_name);
+
+ symbol_put(constructor_name);
+ }
+}
+
+static int insert_to_device_list(me_device_t * n_device)
+{
+ me_device_t *o_device = NULL;
+
+ struct list_head *pos;
+ int n_vendor_id;
+ int n_device_id;
+ int n_serial_no;
+ int n_bus_type;
+ int n_bus_no;
+ int n_dev_no;
+ int n_func_no;
+ int n_plugged;
+ int o_vendor_id;
+ int o_device_id;
+ int o_serial_no;
+ int o_bus_type;
+ int o_bus_no;
+ int o_dev_no;
+ int o_func_no;
+ int o_plugged;
+
+ PDEBUG("executed.\n");
+
+ n_device->me_device_query_info_device(n_device,
+ &n_vendor_id,
+ &n_device_id,
+ &n_serial_no,
+ &n_bus_type,
+ &n_bus_no,
+ &n_dev_no,
+ &n_func_no, &n_plugged);
+
+ down_write(&me_rwsem);
+
+ list_for_each(pos, &me_device_list) {
+ o_device = list_entry(pos, me_device_t, list);
+ o_device->me_device_query_info_device(o_device,
+ &o_vendor_id,
+ &o_device_id,
+ &o_serial_no,
+ &o_bus_type,
+ &o_bus_no,
+ &o_dev_no,
+ &o_func_no, &o_plugged);
+
+ if (o_plugged == ME_PLUGGED_OUT) {
+ if (((o_vendor_id == n_vendor_id) &&
+ (o_device_id == n_device_id) &&
+ (o_serial_no == n_serial_no) &&
+ (o_bus_type == n_bus_type)) ||
+ ((o_vendor_id == n_vendor_id) &&
+ (o_device_id == n_device_id) &&
+ (o_bus_type == n_bus_type) &&
+ (o_bus_no == n_bus_no) &&
+ (o_dev_no == n_dev_no) &&
+ (o_func_no == n_func_no))) {
+ n_device->list.prev = pos->prev;
+ n_device->list.next = pos->next;
+ pos->prev->next = &n_device->list;
+ pos->next->prev = &n_device->list;
+ release_instance(o_device);
+ break;
+ }
+ }
+ }
+
+ if (pos == &me_device_list) {
+ list_add_tail(&n_device->list, &me_device_list);
+ }
+
+ up_write(&me_rwsem);
+
+ return 0;
+}
+
+static void me_remove_pci(struct pci_dev *dev)
+{
+ int vendor_id = dev->vendor;
+ int device_id = dev->device;
+ int subsystem_vendor = dev->subsystem_vendor;
+ int subsystem_device = dev->subsystem_device;
+ int serial_no = (subsystem_device << 16) | subsystem_vendor;
+
+ PDEBUG("executed.\n");
+
+ PINFO("Vendor id = 0x%08X\n", vendor_id);
+ PINFO("Device id = 0x%08X\n", device_id);
+ PINFO("Serial Number = 0x%08X\n", serial_no);
+
+ replace_with_dummy(vendor_id, device_id, serial_no);
+}
+
+static int replace_with_dummy(int vendor_id, int device_id, int serial_no)
+{
+
+ struct list_head *pos;
+ me_device_t *n_device = NULL;
+ me_device_t *o_device = NULL;
+ int o_vendor_id;
+ int o_device_id;
+ int o_serial_no;
+ int o_bus_type;
+ int o_bus_no;
+ int o_dev_no;
+ int o_func_no;
+ int o_plugged;
+
+ PDEBUG("executed.\n");
+
+ down_write(&me_rwsem);
+
+ list_for_each(pos, &me_device_list) {
+ o_device = list_entry(pos, me_device_t, list);
+ o_device->me_device_query_info_device(o_device,
+ &o_vendor_id,
+ &o_device_id,
+ &o_serial_no,
+ &o_bus_type,
+ &o_bus_no,
+ &o_dev_no,
+ &o_func_no, &o_plugged);
+
+ if (o_plugged == ME_PLUGGED_IN) {
+ if (((o_vendor_id == vendor_id) &&
+ (o_device_id == device_id) &&
+ (o_serial_no == serial_no))) {
+ n_device = get_dummy_instance(o_vendor_id,
+ o_device_id,
+ o_serial_no,
+ o_bus_type,
+ o_bus_no,
+ o_dev_no,
+ o_func_no);
+
+ if (!n_device) {
+ up_write(&me_rwsem);
+ PERROR("Cannot get dummy instance.\n");
+ return 1;
+ }
+
+ n_device->list.prev = pos->prev;
+
+ n_device->list.next = pos->next;
+ pos->prev->next = &n_device->list;
+ pos->next->prev = &n_device->list;
+ release_instance(o_device);
+ break;
+ }
+ }
+ }
+
+ up_write(&me_rwsem);
+
+ return 0;
+}
+
+static void clear_device_list(void)
+{
+
+ struct list_head *entry;
+ me_device_t *device;
+
+ // Clear the device info list .
+ down_write(&me_rwsem);
+
+ while (!list_empty(&me_device_list)) {
+ entry = me_device_list.next;
+ device = list_entry(entry, me_device_t, list);
+ list_del(entry);
+ release_instance(device);
+ }
+
+ up_write(&me_rwsem);
+}
+
+static int lock_driver(struct file *filep, int lock, int flags)
+{
+ int err = ME_ERRNO_SUCCESS;
+ me_device_t *device;
+
+ PDEBUG("executed.\n");
+
+ down_read(&me_rwsem);
+
+ spin_lock(&me_lock);
+
+ switch (lock) {
+
+ case ME_LOCK_SET:
+ if (me_count) {
+ PERROR
+ ("Driver System is currently used by another process.\n");
+ err = ME_ERRNO_USED;
+ } else if ((me_filep != NULL) && (me_filep != filep)) {
+ PERROR
+ ("Driver System is already logged by another process.\n");
+ err = ME_ERRNO_LOCKED;
+ } else {
+ list_for_each_entry(device, &me_device_list, list) {
+ err =
+ device->me_device_lock_device(device, filep,
+ ME_LOCK_CHECK,
+ flags);
+
+ if (err)
+ break;
+ }
+
+ if (!err)
+ me_filep = filep;
+ }
+
+ break;
+
+ case ME_LOCK_RELEASE:
+ if ((me_filep != NULL) && (me_filep != filep)) {
+ err = ME_ERRNO_SUCCESS;
+ } else {
+ list_for_each_entry(device, &me_device_list, list) {
+ device->me_device_lock_device(device, filep,
+ ME_LOCK_RELEASE,
+ flags);
+ }
+
+ me_filep = NULL;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid lock specified.\n");
+
+ err = ME_ERRNO_INVALID_LOCK;
+
+ break;
+ }
+
+ spin_unlock(&me_lock);
+
+ up_read(&me_rwsem);
+
+ return err;
+}
+
+static int me_lock_driver(struct file *filep, me_lock_driver_t * arg)
+{
+ int err = 0;
+
+ me_lock_driver_t lock;
+
+ PDEBUG("executed.\n");
+
+ err = copy_from_user(&lock, arg, sizeof(me_lock_driver_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to kernel space.\n");
+ return -EFAULT;
+ }
+
+ lock.errno = lock_driver(filep, lock.lock, lock.flags);
+
+ err = copy_to_user(arg, &lock, sizeof(me_lock_driver_t));
+
+ if (err) {
+ PERROR("Can't copy query back to user space.\n");
+ return -EFAULT;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me_open(struct inode *inode_ptr, struct file *filep)
+{
+
+ PDEBUG("executed.\n");
+ // Nothing to do here.
+ return 0;
+}
+
+static int me_release(struct inode *inode_ptr, struct file *filep)
+{
+
+ PDEBUG("executed.\n");
+ lock_driver(filep, ME_LOCK_RELEASE, ME_LOCK_DRIVER_NO_FLAGS);
+
+ return 0;
+}
+
+static int me_query_version_main_driver(struct file *filep,
+ me_query_version_main_driver_t * arg)
+{
+ int err;
+ me_query_version_main_driver_t karg;
+
+ PDEBUG("executed.\n");
+
+ karg.version = ME_VERSION_DRIVER;
+ karg.errno = ME_ERRNO_SUCCESS;
+
+ err = copy_to_user(arg, &karg, sizeof(me_query_version_main_driver_t));
+
+ if (err) {
+ PERROR("Can't copy query back to user space.\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int me_config_load_device(struct file *filep,
+ me_cfg_device_entry_t * karg, int device_no)
+{
+
+ int err = ME_ERRNO_SUCCESS;
+ int k = 0;
+
+ struct list_head *pos = NULL;
+ me_device_t *device = NULL;
+
+ PDEBUG("executed.\n");
+
+ list_for_each(pos, &me_device_list) {
+ if (k == device_no) {
+ device = list_entry(pos, me_device_t, list);
+ break;
+ }
+
+ k++;
+ }
+
+ if (pos == &me_device_list) {
+ PERROR("Invalid device number specified.\n");
+ return ME_ERRNO_INVALID_DEVICE;
+ } else {
+ spin_lock(&me_lock);
+
+ if ((me_filep != NULL) && (me_filep != filep)) {
+ spin_unlock(&me_lock);
+ PERROR("Resource is locked by another process.\n");
+ return ME_ERRNO_LOCKED;
+ } else {
+ me_count++;
+ spin_unlock(&me_lock);
+
+ err =
+ device->me_device_config_load(device, filep, karg);
+
+ spin_lock(&me_lock);
+ me_count--;
+ spin_unlock(&me_lock);
+ }
+ }
+
+ return err;
+}
+
+static int me_config_load(struct file *filep, me_config_load_t * arg)
+{
+ int err;
+ int i;
+ me_config_load_t cfg_setup;
+ me_config_load_t karg_cfg_setup;
+
+ struct list_head *pos = NULL;
+
+ struct list_head new_list;
+ me_device_t *o_device;
+ me_device_t *n_device;
+ int o_vendor_id;
+ int o_device_id;
+ int o_serial_no;
+ int o_bus_type;
+ int o_bus_no;
+ int o_dev_no;
+ int o_func_no;
+ int o_plugged;
+
+ PDEBUG("executed.\n");
+
+ // Copy argument to kernel space.
+ err = copy_from_user(&karg_cfg_setup, arg, sizeof(me_config_load_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to kernel space.\n");
+ return -EFAULT;
+ }
+ // Allocate kernel buffer for device list.
+ cfg_setup.device_list =
+ kmalloc(sizeof(me_cfg_device_entry_t) * karg_cfg_setup.count,
+ GFP_KERNEL);
+
+ if (!cfg_setup.device_list) {
+ PERROR("Can't get buffer %li for device list.\n",
+ sizeof(me_cfg_device_entry_t) * karg_cfg_setup.count);
+ return -ENOMEM;
+ }
+ // Copy device list to kernel space.
+ err =
+ copy_from_user(cfg_setup.device_list, karg_cfg_setup.device_list,
+ sizeof(me_cfg_device_entry_t) *
+ karg_cfg_setup.count);
+
+ if (err) {
+ PERROR("Can't copy device list to kernel space.\n");
+ kfree(cfg_setup.device_list);
+ return -EFAULT;
+ }
+
+ cfg_setup.count = karg_cfg_setup.count;
+
+ INIT_LIST_HEAD(&new_list);
+
+ down_write(&me_rwsem);
+
+ spin_lock(&me_lock);
+
+ if ((me_filep != NULL) && (me_filep != filep)) {
+ spin_unlock(&me_lock);
+ PERROR("Driver System is logged by another process.\n");
+ karg_cfg_setup.errno = ME_ERRNO_LOCKED;
+ } else {
+ me_count++;
+ spin_unlock(&me_lock);
+
+ for (i = 0; i < karg_cfg_setup.count; i++) {
+ PDEBUG("me_config_load() device=%d.\n", i);
+ if (cfg_setup.device_list[i].tcpip.access_type ==
+ ME_ACCESS_TYPE_LOCAL) {
+ list_for_each(pos, &me_device_list) {
+ o_device =
+ list_entry(pos, me_device_t, list);
+ o_device->
+ me_device_query_info_device
+ (o_device, &o_vendor_id,
+ &o_device_id, &o_serial_no,
+ &o_bus_type, &o_bus_no, &o_dev_no,
+ &o_func_no, &o_plugged);
+
+ if (cfg_setup.device_list[i].info.
+ hw_location.bus_type ==
+ ME_BUS_TYPE_PCI) {
+ if (((o_vendor_id ==
+ cfg_setup.device_list[i].
+ info.vendor_id)
+ && (o_device_id ==
+ cfg_setup.
+ device_list[i].info.
+ device_id)
+ && (o_serial_no ==
+ cfg_setup.
+ device_list[i].info.
+ serial_no)
+ && (o_bus_type ==
+ cfg_setup.
+ device_list[i].info.
+ hw_location.bus_type))
+ ||
+ ((o_vendor_id ==
+ cfg_setup.device_list[i].
+ info.vendor_id)
+ && (o_device_id ==
+ cfg_setup.
+ device_list[i].info.
+ device_id)
+ && (o_bus_type ==
+ cfg_setup.
+ device_list[i].info.
+ hw_location.bus_type)
+ && (o_bus_no ==
+ cfg_setup.
+ device_list[i].info.
+ hw_location.pci.bus_no)
+ && (o_dev_no ==
+ cfg_setup.
+ device_list[i].info.
+ hw_location.pci.
+ device_no)
+ && (o_func_no ==
+ cfg_setup.
+ device_list[i].info.
+ hw_location.pci.
+ function_no))) {
+ list_move_tail(pos,
+ &new_list);
+ break;
+ }
+ }
+/*
+ else if (cfg_setup.device_list[i].info.hw_location.bus_type == ME_BUS_TYPE_USB)
+ {
+ if (((o_vendor_id == cfg_setup.device_list[i].info.vendor_id) &&
+ (o_device_id == cfg_setup.device_list[i].info.device_id) &&
+ (o_serial_no == cfg_setup.device_list[i].info.serial_no) &&
+ (o_bus_type == cfg_setup.device_list[i].info.hw_location.bus_type)) ||
+ ((o_vendor_id == cfg_setup.device_list[i].info.vendor_id) &&
+ (o_device_id == cfg_setup.device_list[i].info.device_id) &&
+ (o_bus_type == cfg_setup.device_list[i].info.hw_location.bus_type) &&
+ (o_bus_no == cfg_setup.device_list[i].info.hw_location.usb.root_hub_no)))
+ {
+ list_move_tail(pos, &new_list);
+ break;
+ }
+ }
+*/
+ else {
+ PERROR("Wrong bus type: %d.\n",
+ cfg_setup.device_list[i].
+ info.hw_location.
+ bus_type);
+ }
+ }
+
+ if (pos == &me_device_list) { // Device is not already in the list
+ if (cfg_setup.device_list[i].info.
+ hw_location.bus_type ==
+ ME_BUS_TYPE_PCI) {
+ n_device =
+ get_dummy_instance
+ (cfg_setup.device_list[i].
+ info.vendor_id,
+ cfg_setup.device_list[i].
+ info.device_id,
+ cfg_setup.device_list[i].
+ info.serial_no,
+ cfg_setup.device_list[i].
+ info.hw_location.bus_type,
+ cfg_setup.device_list[i].
+ info.hw_location.pci.
+ bus_no,
+ cfg_setup.device_list[i].
+ info.hw_location.pci.
+ device_no,
+ cfg_setup.device_list[i].
+ info.hw_location.pci.
+ function_no);
+
+ if (!n_device) {
+ PERROR
+ ("Can't get dummy instance.\n");
+ kfree(cfg_setup.
+ device_list);
+ spin_lock(&me_lock);
+ me_count--;
+ spin_unlock(&me_lock);
+ up_write(&me_rwsem);
+ return -EFAULT;
+ }
+
+ list_add_tail(&n_device->list,
+ &new_list);
+ }
+/*
+ else if (cfg_setup.device_list[i].info.hw_location.bus_type == ME_BUS_TYPE_USB)
+ {
+ n_device = get_dummy_instance(
+ cfg_setup.device_list[i].info.vendor_id,
+ cfg_setup.device_list[i].info.device_id,
+ cfg_setup.device_list[i].info.serial_no,
+ cfg_setup.device_list[i].info.hw_location.bus_type,
+ cfg_setup.device_list[i].info.hw_location.usb.root_hub_no,
+ 0,
+ 0);
+
+ if (!n_device)
+ {
+ PERROR("Can't get dummy instance.\n");
+ kfree(cfg_setup.device_list);
+ spin_lock(&me_lock);
+ me_count--;
+ spin_unlock(&me_lock);
+ up_write(&me_rwsem);
+ return -EFAULT;
+ }
+
+ list_add_tail(&n_device->list, &new_list);
+ }
+*/
+ }
+ } else {
+ n_device = get_dummy_instance(0,
+ 0, 0, 0, 0, 0, 0);
+
+ if (!n_device) {
+ PERROR("Can't get dummy instance.\n");
+ kfree(cfg_setup.device_list);
+ spin_lock(&me_lock);
+ me_count--;
+ spin_unlock(&me_lock);
+ up_write(&me_rwsem);
+ return -EFAULT;
+ }
+
+ list_add_tail(&n_device->list, &new_list);
+ }
+ }
+
+ while (!list_empty(&me_device_list)) {
+ o_device =
+ list_entry(me_device_list.next, me_device_t, list);
+ o_device->me_device_query_info_device(o_device,
+ &o_vendor_id,
+ &o_device_id,
+ &o_serial_no,
+ &o_bus_type,
+ &o_bus_no,
+ &o_dev_no,
+ &o_func_no,
+ &o_plugged);
+
+ if (o_plugged == ME_PLUGGED_IN) {
+ list_move_tail(me_device_list.next, &new_list);
+ } else {
+ list_del(me_device_list.next);
+ release_instance(o_device);
+ }
+ }
+
+ // Move temporary new list to global driver list.
+ list_splice(&new_list, &me_device_list);
+
+ karg_cfg_setup.errno = ME_ERRNO_SUCCESS;
+ }
+
+ for (i = 0; i < cfg_setup.count; i++) {
+
+ karg_cfg_setup.errno =
+ me_config_load_device(filep, &cfg_setup.device_list[i], i);
+ if (karg_cfg_setup.errno) {
+ PERROR("me_config_load_device(%d)=%d\n", i,
+ karg_cfg_setup.errno);
+ break;
+ }
+ }
+
+ spin_lock(&me_lock);
+
+ me_count--;
+ spin_unlock(&me_lock);
+ up_write(&me_rwsem);
+
+ err = copy_to_user(arg, &karg_cfg_setup, sizeof(me_config_load_t));
+
+ if (err) {
+ PERROR("Can't copy config list to user space.\n");
+ kfree(cfg_setup.device_list);
+ return -EFAULT;
+ }
+
+ kfree(cfg_setup.device_list);
+ return 0;
+}
+
+static int me_io_stream_start(struct file *filep, me_io_stream_start_t * arg)
+{
+ int err;
+ int i, k;
+
+ struct list_head *pos;
+ me_device_t *device;
+ me_io_stream_start_t karg;
+ meIOStreamStart_t *list;
+
+ PDEBUG("executed.\n");
+
+ err = copy_from_user(&karg, arg, sizeof(me_io_stream_start_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to kernel space.\n");
+ return -EFAULT;
+ }
+
+ karg.errno = ME_ERRNO_SUCCESS;
+
+ list = kmalloc(sizeof(meIOStreamStart_t) * karg.count, GFP_KERNEL);
+
+ if (!list) {
+ PERROR("Can't get buffer for start list.\n");
+ return -ENOMEM;
+ }
+
+ err =
+ copy_from_user(list, karg.start_list,
+ sizeof(meIOStreamStart_t) * karg.count);
+
+ if (err) {
+ PERROR("Can't copy start list to kernel space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ spin_lock(&me_lock);
+
+ if ((me_filep != NULL) && (me_filep != filep)) {
+ spin_unlock(&me_lock);
+ PERROR("Driver System is logged by another process.\n");
+
+ for (i = 0; i < karg.count; i++) {
+ list[i].iErrno = ME_ERRNO_LOCKED;
+ }
+ } else {
+ me_count++;
+ spin_unlock(&me_lock);
+
+ for (i = 0; i < karg.count; i++) {
+ down_read(&me_rwsem);
+ k = 0;
+ list_for_each(pos, &me_device_list) {
+ if (k == list[i].iDevice) {
+ device =
+ list_entry(pos, me_device_t, list);
+ break;
+ }
+
+ k++;
+ }
+
+ if (pos == &me_device_list) {
+ up_read(&me_rwsem);
+ PERROR("Invalid device number specified.\n");
+ list[i].iErrno = ME_ERRNO_INVALID_DEVICE;
+ karg.errno = ME_ERRNO_INVALID_DEVICE;
+ break;
+ } else {
+ list[i].iErrno =
+ device->me_device_io_stream_start(device,
+ filep,
+ list[i].
+ iSubdevice,
+ list[i].
+ iStartMode,
+ list[i].
+ iTimeOut,
+ list[i].
+ iFlags);
+
+ if (list[i].iErrno) {
+ up_read(&me_rwsem);
+ karg.errno = list[i].iErrno;
+ break;
+ }
+ }
+
+ up_read(&me_rwsem);
+ }
+
+ spin_lock(&me_lock);
+
+ me_count--;
+ spin_unlock(&me_lock);
+ }
+
+ err = copy_to_user(arg, &karg, sizeof(me_io_stream_start_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to user space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ err =
+ copy_to_user(karg.start_list, list,
+ sizeof(meIOStreamStart_t) * karg.count);
+
+ if (err) {
+ PERROR("Can't copy start list to user space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ kfree(list);
+
+ return err;
+}
+
+static int me_io_single(struct file *filep, me_io_single_t * arg)
+{
+ int err;
+ int i, k;
+
+ struct list_head *pos;
+ me_device_t *device;
+ me_io_single_t karg;
+ meIOSingle_t *list;
+
+ PDEBUG("executed.\n");
+
+ err = copy_from_user(&karg, arg, sizeof(me_io_single_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to kernel space.\n");
+ return -EFAULT;
+ }
+
+ karg.errno = ME_ERRNO_SUCCESS;
+
+ list = kmalloc(sizeof(meIOSingle_t) * karg.count, GFP_KERNEL);
+
+ if (!list) {
+ PERROR("Can't get buffer for single list.\n");
+ return -ENOMEM;
+ }
+
+ err =
+ copy_from_user(list, karg.single_list,
+ sizeof(meIOSingle_t) * karg.count);
+
+ if (err) {
+ PERROR("Can't copy single list to kernel space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ spin_lock(&me_lock);
+
+ if ((me_filep != NULL) && (me_filep != filep)) {
+ spin_unlock(&me_lock);
+ PERROR("Driver System is logged by another process.\n");
+
+ for (i = 0; i < karg.count; i++) {
+ list[i].iErrno = ME_ERRNO_LOCKED;
+ }
+ } else {
+ me_count++;
+ spin_unlock(&me_lock);
+
+ for (i = 0; i < karg.count; i++) {
+ k = 0;
+
+ down_read(&me_rwsem);
+
+ list_for_each(pos, &me_device_list) {
+ if (k == list[i].iDevice) {
+ device =
+ list_entry(pos, me_device_t, list);
+ break;
+ }
+
+ k++;
+ }
+
+ if (pos == &me_device_list) {
+ up_read(&me_rwsem);
+ PERROR("Invalid device number specified.\n");
+ list[i].iErrno = ME_ERRNO_INVALID_DEVICE;
+ karg.errno = ME_ERRNO_INVALID_DEVICE;
+ break;
+ } else {
+ if (list[i].iDir == ME_DIR_OUTPUT) {
+ list[i].iErrno =
+ device->
+ me_device_io_single_write(device,
+ filep,
+ list[i].
+ iSubdevice,
+ list[i].
+ iChannel,
+ list[i].
+ iValue,
+ list[i].
+ iTimeOut,
+ list[i].
+ iFlags);
+
+ if (list[i].iErrno) {
+ up_read(&me_rwsem);
+ karg.errno = list[i].iErrno;
+ break;
+ }
+ } else if (list[i].iDir == ME_DIR_INPUT) {
+ list[i].iErrno =
+ device->
+ me_device_io_single_read(device,
+ filep,
+ list[i].
+ iSubdevice,
+ list[i].
+ iChannel,
+ &list[i].
+ iValue,
+ list[i].
+ iTimeOut,
+ list[i].
+ iFlags);
+
+ if (list[i].iErrno) {
+ up_read(&me_rwsem);
+ karg.errno = list[i].iErrno;
+ break;
+ }
+ } else {
+ up_read(&me_rwsem);
+ PERROR
+ ("Invalid single direction specified.\n");
+ list[i].iErrno = ME_ERRNO_INVALID_DIR;
+ karg.errno = ME_ERRNO_INVALID_DIR;
+ break;
+ }
+ }
+
+ up_read(&me_rwsem);
+ }
+
+ spin_lock(&me_lock);
+
+ me_count--;
+ spin_unlock(&me_lock);
+ }
+
+ err = copy_to_user(arg, &karg, sizeof(me_io_single_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to user space.\n");
+ return -EFAULT;
+ }
+
+ err =
+ copy_to_user(karg.single_list, list,
+ sizeof(meIOSingle_t) * karg.count);
+
+ if (err) {
+ PERROR("Can't copy single list to user space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ kfree(list);
+
+ return err;
+}
+
+static int me_io_stream_config(struct file *filep, me_io_stream_config_t * arg)
+{
+ int err;
+ int k = 0;
+
+ struct list_head *pos;
+ me_device_t *device;
+ me_io_stream_config_t karg;
+ meIOStreamConfig_t *list;
+
+ PDEBUG("executed.\n");
+
+ err = copy_from_user(&karg, arg, sizeof(me_io_stream_config_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to kernel space.\n");
+ return -EFAULT;
+ }
+
+ list = kmalloc(sizeof(meIOStreamConfig_t) * karg.count, GFP_KERNEL);
+
+ if (!list) {
+ PERROR("Can't get buffer for config list.\n");
+ return -ENOMEM;
+ }
+
+ err =
+ copy_from_user(list, karg.config_list,
+ sizeof(meIOStreamConfig_t) * karg.count);
+
+ if (err) {
+ PERROR("Can't copy config list to kernel space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ spin_lock(&me_lock);
+
+ if ((me_filep != NULL) && (me_filep != filep)) {
+ spin_unlock(&me_lock);
+ PERROR("Driver System is logged by another process.\n");
+ karg.errno = ME_ERRNO_LOCKED;
+ } else {
+ me_count++;
+ spin_unlock(&me_lock);
+
+ down_read(&me_rwsem);
+
+ list_for_each(pos, &me_device_list) {
+ if (k == karg.device) {
+ device = list_entry(pos, me_device_t, list);
+ break;
+ }
+
+ k++;
+ }
+
+ if (pos == &me_device_list) {
+ PERROR("Invalid device number specified.\n");
+ karg.errno = ME_ERRNO_INVALID_DEVICE;
+ } else {
+ karg.errno =
+ device->me_device_io_stream_config(device, filep,
+ karg.subdevice,
+ list, karg.count,
+ &karg.trigger,
+ karg.
+ fifo_irq_threshold,
+ karg.flags);
+ }
+
+ up_read(&me_rwsem);
+
+ spin_lock(&me_lock);
+ me_count--;
+ spin_unlock(&me_lock);
+ }
+
+ err = copy_to_user(arg, &karg, sizeof(me_io_stream_config_t));
+
+ if (err) {
+ PERROR("Can't copy back to user space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ kfree(list);
+
+ return err;
+}
+
+static int me_query_number_devices(struct file *filep,
+ me_query_number_devices_t * arg)
+{
+ int err;
+ me_query_number_devices_t karg;
+
+ struct list_head *pos;
+
+ PDEBUG("executed.\n");
+
+ karg.number = 0;
+ down_read(&me_rwsem);
+ list_for_each(pos, &me_device_list) {
+ karg.number++;
+ }
+
+ up_read(&me_rwsem);
+
+ karg.errno = ME_ERRNO_SUCCESS;
+
+ err = copy_to_user(arg, &karg, sizeof(me_query_number_devices_t));
+
+ if (err) {
+ PERROR("Can't copy query back to user space.\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int me_io_stream_stop(struct file *filep, me_io_stream_stop_t * arg)
+{
+ int err;
+ int i, k;
+
+ struct list_head *pos;
+ me_device_t *device;
+ me_io_stream_stop_t karg;
+ meIOStreamStop_t *list;
+
+ PDEBUG("executed.\n");
+
+ err = copy_from_user(&karg, arg, sizeof(me_io_stream_stop_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to kernel space.\n");
+ return -EFAULT;
+ }
+
+ karg.errno = ME_ERRNO_SUCCESS;
+
+ list = kmalloc(sizeof(meIOStreamStop_t) * karg.count, GFP_KERNEL);
+
+ if (!list) {
+ PERROR("Can't get buffer for stop list.\n");
+ return -ENOMEM;
+ }
+
+ err =
+ copy_from_user(list, karg.stop_list,
+ sizeof(meIOStreamStop_t) * karg.count);
+
+ if (err) {
+ PERROR("Can't copy stop list to kernel space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ spin_lock(&me_lock);
+
+ if ((me_filep != NULL) && (me_filep != filep)) {
+ spin_unlock(&me_lock);
+ PERROR("Driver System is logged by another process.\n");
+
+ for (i = 0; i < karg.count; i++) {
+ list[i].iErrno = ME_ERRNO_LOCKED;
+ }
+ } else {
+ me_count++;
+ spin_unlock(&me_lock);
+
+ for (i = 0; i < karg.count; i++) {
+ k = 0;
+ down_read(&me_rwsem);
+ list_for_each(pos, &me_device_list) {
+ if (k == list[i].iDevice) {
+ device =
+ list_entry(pos, me_device_t, list);
+ break;
+ }
+
+ k++;
+ }
+
+ if (pos == &me_device_list) {
+ up_read(&me_rwsem);
+ PERROR("Invalid device number specified.\n");
+ list[i].iErrno = ME_ERRNO_INVALID_DEVICE;
+ karg.errno = ME_ERRNO_INVALID_DEVICE;
+ break;
+ } else {
+ list[i].iErrno =
+ device->me_device_io_stream_stop(device,
+ filep,
+ list[i].
+ iSubdevice,
+ list[i].
+ iStopMode,
+ list[i].
+ iFlags);
+
+ if (list[i].iErrno) {
+ up_read(&me_rwsem);
+ karg.errno = list[i].iErrno;
+ break;
+ }
+ }
+
+ up_read(&me_rwsem);
+ }
+
+ spin_lock(&me_lock);
+
+ me_count--;
+ spin_unlock(&me_lock);
+ }
+
+ err = copy_to_user(arg, &karg, sizeof(me_io_stream_stop_t));
+
+ if (err) {
+ PERROR("Can't copy arguments to user space.\n");
+ return -EFAULT;
+ }
+
+ err =
+ copy_to_user(karg.stop_list, list,
+ sizeof(meIOStreamStop_t) * karg.count);
+
+ if (err) {
+ PERROR("Can't copy stop list to user space.\n");
+ kfree(list);
+ return -EFAULT;
+ }
+
+ kfree(list);
+
+ return err;
+}
+
+/* //me_probe_usb
+static int me_probe_usb(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ //int err;
+ //me_usb_constructor_t *constructor = NULL;
+ me_device_t *n_device = NULL;
+
+ PDEBUG("executed.\n");
+
+ switch (id->idProduct)
+ {
+ case USB_DEVICE_ID_MEPHISTO_S1:
+ if((constructor = symbol_get(mephisto_s1_constructor)) == NULL){
+ err = request_module(MEPHISTO_S1_NAME);
+ if(err){
+ PERROR("Error while request for module %s.\n", MEPHISTO_S1_NAME);
+ return -ENODEV;
+ }
+ if((constructor = symbol_get(mephisto_s1_constructor)) == NULL){
+ PERROR("Can't get %s driver module constructor.\n", MEPHISTO_S1_NAME);
+ return -ENODEV;
+ }
+ }
+
+ if((n_device = (*constructor)(interface)) == NULL){
+ symbol_put(mephisto_s1_constructor);
+ PERROR("Can't get device instance of %s driver module.\n", MEPHISTO_S1_NAME);
+ return -ENODEV;
+ }
+
+ break;
+
+ default:
+ PERROR("Invalid product id.\n");
+
+ return -EINVAL;
+ }
+
+ return insert_to_device_list(n_device);
+}
+*/
+
+/* //me_disconnect_usb
+static void me_disconnect_usb(struct usb_interface *interface)
+{
+
+ struct usb_device *device = interface_to_usbdev(interface);
+ int vendor_id = device->descriptor.idVendor;
+ int device_id = device->descriptor.idProduct;
+ int serial_no;
+
+ sscanf(&device->serial[2], "%x", &serial_no);
+
+ PDEBUG("executed.\n");
+
+ PINFO("Vendor id = 0x%08X\n", vendor_id);
+ PINFO("Device id = 0x%08X\n", device_id);
+ PINFO("Serial Number = 0x%08X\n", serial_no);
+
+ replace_with_dummy(vendor_id, device_id, serial_no);
+}
+*/
+
+static int me_ioctl(struct inode *inodep,
+ struct file *filep, unsigned int service, unsigned long arg)
+{
+
+ PDEBUG("executed.\n");
+
+ if (_IOC_TYPE(service) != MEMAIN_MAGIC) {
+ PERROR("Invalid magic number.\n");
+ return -ENOTTY;
+ }
+
+ PDEBUG("service number: 0x%x.\n", service);
+
+ switch (service) {
+ case ME_IO_IRQ_ENABLE:
+ return me_io_irq_start(filep, (me_io_irq_start_t *) arg);
+
+ case ME_IO_IRQ_WAIT:
+ return me_io_irq_wait(filep, (me_io_irq_wait_t *) arg);
+
+ case ME_IO_IRQ_DISABLE:
+ return me_io_irq_stop(filep, (me_io_irq_stop_t *) arg);
+
+ case ME_IO_RESET_DEVICE:
+ return me_io_reset_device(filep, (me_io_reset_device_t *) arg);
+
+ case ME_IO_RESET_SUBDEVICE:
+ return me_io_reset_subdevice(filep,
+ (me_io_reset_subdevice_t *) arg);
+
+ case ME_IO_SINGLE_CONFIG:
+ return me_io_single_config(filep,
+ (me_io_single_config_t *) arg);
+
+ case ME_IO_SINGLE:
+ return me_io_single(filep, (me_io_single_t *) arg);
+
+ case ME_IO_STREAM_CONFIG:
+ return me_io_stream_config(filep,
+ (me_io_stream_config_t *) arg);
+
+ case ME_IO_STREAM_NEW_VALUES:
+ return me_io_stream_new_values(filep,
+ (me_io_stream_new_values_t *)
+ arg);
+
+ case ME_IO_STREAM_READ:
+ return me_io_stream_read(filep, (me_io_stream_read_t *) arg);
+
+ case ME_IO_STREAM_START:
+ return me_io_stream_start(filep, (me_io_stream_start_t *) arg);
+
+ case ME_IO_STREAM_STATUS:
+ return me_io_stream_status(filep,
+ (me_io_stream_status_t *) arg);
+
+ case ME_IO_STREAM_STOP:
+ return me_io_stream_stop(filep, (me_io_stream_stop_t *) arg);
+
+ case ME_IO_STREAM_WRITE:
+ return me_io_stream_write(filep, (me_io_stream_write_t *) arg);
+
+ case ME_LOCK_DRIVER:
+ return me_lock_driver(filep, (me_lock_driver_t *) arg);
+
+ case ME_LOCK_DEVICE:
+ return me_lock_device(filep, (me_lock_device_t *) arg);
+
+ case ME_LOCK_SUBDEVICE:
+ return me_lock_subdevice(filep, (me_lock_subdevice_t *) arg);
+
+ case ME_QUERY_INFO_DEVICE:
+ return me_query_info_device(filep,
+ (me_query_info_device_t *) arg);
+
+ case ME_QUERY_DESCRIPTION_DEVICE:
+ return me_query_description_device(filep,
+ (me_query_description_device_t
+ *) arg);
+
+ case ME_QUERY_NAME_DEVICE:
+ return me_query_name_device(filep,
+ (me_query_name_device_t *) arg);
+
+ case ME_QUERY_NAME_DEVICE_DRIVER:
+ return me_query_name_device_driver(filep,
+ (me_query_name_device_driver_t
+ *) arg);
+
+ case ME_QUERY_NUMBER_DEVICES:
+ return me_query_number_devices(filep,
+ (me_query_number_devices_t *)
+ arg);
+
+ case ME_QUERY_NUMBER_SUBDEVICES:
+ return me_query_number_subdevices(filep,
+ (me_query_number_subdevices_t
+ *) arg);
+
+ case ME_QUERY_NUMBER_CHANNELS:
+ return me_query_number_channels(filep,
+ (me_query_number_channels_t *)
+ arg);
+
+ case ME_QUERY_NUMBER_RANGES:
+ return me_query_number_ranges(filep,
+ (me_query_number_ranges_t *) arg);
+
+ case ME_QUERY_RANGE_BY_MIN_MAX:
+ return me_query_range_by_min_max(filep,
+ (me_query_range_by_min_max_t *)
+ arg);
+
+ case ME_QUERY_RANGE_INFO:
+ return me_query_range_info(filep,
+ (me_query_range_info_t *) arg);
+
+ case ME_QUERY_SUBDEVICE_BY_TYPE:
+ return me_query_subdevice_by_type(filep,
+ (me_query_subdevice_by_type_t
+ *) arg);
+
+ case ME_QUERY_SUBDEVICE_TYPE:
+ return me_query_subdevice_type(filep,
+ (me_query_subdevice_type_t *)
+ arg);
+
+ case ME_QUERY_SUBDEVICE_CAPS:
+ return me_query_subdevice_caps(filep,
+ (me_query_subdevice_caps_t *)
+ arg);
+
+ case ME_QUERY_SUBDEVICE_CAPS_ARGS:
+ return me_query_subdevice_caps_args(filep,
+ (me_query_subdevice_caps_args_t
+ *) arg);
+
+ case ME_QUERY_TIMER:
+ return me_query_timer(filep, (me_query_timer_t *) arg);
+
+ case ME_QUERY_VERSION_MAIN_DRIVER:
+ return me_query_version_main_driver(filep,
+ (me_query_version_main_driver_t
+ *) arg);
+
+ case ME_QUERY_VERSION_DEVICE_DRIVER:
+ return me_query_version_device_driver(filep,
+ (me_query_version_device_driver_t
+ *) arg);
+
+ case ME_CONFIG_LOAD:
+ return me_config_load(filep, (me_config_load_t *) arg);
+ }
+
+ PERROR("Invalid ioctl number.\n");
+ return -ENOTTY;
+}
+
+// Init and exit of module.
+static int memain_init(void)
+{
+ int result = 0;
+ dev_t dev = MKDEV(major, 0);
+
+ PDEBUG("executed.\n");
+
+ // Register pci driver. This will return 0 if the PCI subsystem is not available.
+ result = pci_register_driver(&me_pci_driver);
+
+ if (result < 0) {
+ PERROR("Can't register pci driver.\n");
+ goto INIT_ERROR_1;
+ }
+
+/*
+ // Register usb driver. This will return -ENODEV if no USB subsystem is available.
+ result = usb_register(&me_usb_driver);
+
+ if (result)
+ {
+ if (result == -ENODEV)
+ {
+ PERROR("No USB subsystem available.\n");
+ }
+ else
+ {
+ PERROR("Can't register usb driver.\n");
+ goto INIT_ERROR_2;
+ }
+ }
+*/
+ // Register the character device.
+ if (major) {
+ result = register_chrdev_region(dev, 1, MEMAIN_NAME);
+ } else {
+ result = alloc_chrdev_region(&dev, 0, 1, MEMAIN_NAME);
+ major = MAJOR(dev);
+ }
+
+ if (result < 0) {
+ PERROR("Can't get major driver no.\n");
+ goto INIT_ERROR_3;
+ }
+
+ cdevp = cdev_alloc();
+
+ if (!cdevp) {
+ PERROR("Can't get character device structure.\n");
+ result = -ENOMEM;
+ goto INIT_ERROR_4;
+ }
+
+ cdevp->ops = &me_file_operations;
+
+ cdevp->owner = THIS_MODULE;
+
+ result = cdev_add(cdevp, dev, 1);
+
+ if (result < 0) {
+ PERROR("Cannot add character device structure.\n");
+ goto INIT_ERROR_5;
+ }
+
+ return 0;
+
+ INIT_ERROR_5:
+ cdev_del(cdevp);
+
+ INIT_ERROR_4:
+ unregister_chrdev_region(dev, 1);
+
+ INIT_ERROR_3:
+// usb_deregister(&me_usb_driver);
+
+//INIT_ERROR_2:
+ pci_unregister_driver(&me_pci_driver);
+ clear_device_list();
+
+ INIT_ERROR_1:
+ return result;
+}
+
+static void __exit memain_exit(void)
+{
+ dev_t dev = MKDEV(major, 0);
+
+ PDEBUG("executed.\n");
+
+ cdev_del(cdevp);
+ unregister_chrdev_region(dev, 1);
+ pci_unregister_driver(&me_pci_driver);
+// usb_deregister(&me_usb_driver);
+ clear_device_list();
+}
+
+module_init(memain_init);
+module_exit(memain_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR
+ ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
+MODULE_DESCRIPTION("Central module for Meilhaus Driver System.");
+MODULE_SUPPORTED_DEVICE("Meilhaus PCI/cPCI boards.");
+MODULE_LICENSE("GPL");
+
+#ifdef BOSCH
+// Export the flag for the BOSCH firmware.
+EXPORT_SYMBOL(me_bosch_fw);
+#endif // BOSCH
diff --git a/drivers/staging/meilhaus/memain.h b/drivers/staging/meilhaus/memain.h
new file mode 100644
index 000000000000..7616ff7f65cb
--- /dev/null
+++ b/drivers/staging/meilhaus/memain.h
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : memain.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ */
+
+#ifndef _MEMAIN_H_
+#define _MEMAIN_H_
+
+#include "meinternal.h"
+
+#include "meids.h"
+#include "medebug.h"
+
+#include "medevice.h"
+/*#include "me1000_device.h"
+#include "me1400_device.h"
+#include "me1600_device.h"*/
+#include "me4600_device.h"
+/*#include "me6000_device.h"
+#include "me0600_device.h"
+#include "me8100_device.h"
+#include "me8200_device.h"
+#include "me0900_device.h"*/
+#include "medummy.h"
+
+#ifdef __KERNEL__
+
+/*=============================================================================
+ PCI device table.
+ This is used by modprobe to translate PCI IDs to drivers.
+ ===========================================================================*/
+
+static struct pci_device_id me_pci_table[] __devinitdata = {
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_A, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_B, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1400, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140A, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140B, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14E0, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EA, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EB, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140C, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140D, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_4U, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_8U, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_12U, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4610, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6004, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6008, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME600F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6014, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6018, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME601F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6034, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6038, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME603F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6104, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6108, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME610F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6114, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6118, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME611F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6134, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6138, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME613F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6044, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6048, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME604F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6054, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6058, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME605F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6074, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6078, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME607F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6144, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6148, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME614F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6154, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6158, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME615F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6174, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6178, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME617F, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6259, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6359, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0630, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_A, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_B, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_A, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_B, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0940, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0950, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+ {PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0960, PCI_ANY_ID,
+ PCI_ANY_ID, 0, 0, 0},
+
+ {0}
+};
+
+MODULE_DEVICE_TABLE(pci, me_pci_table);
+
+/*=============================================================================
+ USB device table.
+ This is used by modprobe to translate USB IDs to drivers.
+ ===========================================================================*/
+/*
+static struct usb_device_id me_usb_table[] __devinitdata = {
+ { USB_DEVICE(USB_VENDOR_ID_MEPHISTO_S1, USB_DEVICE_ID_MEPHISTO_S1) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE (usb, me_usb_table);
+*/
+
+/*=============================================================================
+ Templates
+ ===========================================================================*/
+
+#define ME_LOCK_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \
+static int CALL(struct file *filep, TYPE *arg){ \
+ int err = 0; \
+ int k = 0; \
+ struct list_head *pos; \
+ me_device_t *device; \
+ TYPE karg; \
+ \
+ PDEBUG("executed.\n"); \
+ \
+ err = copy_from_user(&karg, arg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy arguments to kernel space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ down_read(&me_rwsem); \
+ \
+ list_for_each(pos, &me_device_list){ \
+ if(k == karg.device){ \
+ device = list_entry(pos, me_device_t, list); \
+ break; \
+ } \
+ k++; \
+ } \
+ \
+ if(pos == &me_device_list){ \
+ PERROR("Invalid device number specified\n"); \
+ karg.errno = ME_ERRNO_INVALID_DEVICE; \
+ } \
+ else{ \
+ spin_lock(&me_lock); \
+ if((me_filep != NULL) && (me_filep != filep)){ \
+ spin_unlock(&me_lock); \
+ PERROR("Resource is locked by another process\n"); \
+ if(karg.lock == ME_LOCK_SET) \
+ karg.errno = ME_ERRNO_LOCKED; \
+ else if(karg.lock == ME_LOCK_RELEASE) \
+ karg.errno = ME_ERRNO_SUCCESS; \
+ else{ \
+ PERROR("Invalid lock specified\n"); \
+ karg.errno = ME_ERRNO_INVALID_LOCK; \
+ }\
+ } \
+ else { \
+ me_count++; \
+ spin_unlock(&me_lock); \
+ \
+ karg.errno = device->DEV_CALL ARGS; \
+ \
+ spin_lock(&me_lock); \
+ me_count--; \
+ spin_unlock(&me_lock); \
+ } \
+ } \
+ \
+ up_read(&me_rwsem); \
+ \
+ err = copy_to_user(arg, &karg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy arguments back to user space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ return ME_ERRNO_SUCCESS; \
+}
+
+#define ME_IO_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \
+static int CALL(struct file *filep, TYPE *arg){ \
+ int err = 0; \
+ int k = 0; \
+ struct list_head *pos; \
+ me_device_t *device; \
+ TYPE karg; \
+ \
+ PDEBUG("executed.\n"); \
+ \
+ err = copy_from_user(&karg, arg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy arguments to kernel space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ down_read(&me_rwsem); \
+ \
+ list_for_each(pos, &me_device_list){ \
+ if(k == karg.device){ \
+ device = list_entry(pos, me_device_t, list); \
+ break; \
+ } \
+ k++; \
+ } \
+ \
+ if(pos == &me_device_list){ \
+ PERROR("Invalid device number specified\n"); \
+ karg.errno = ME_ERRNO_INVALID_DEVICE; \
+ } \
+ else{ \
+ spin_lock(&me_lock); \
+ if((me_filep != NULL) && (me_filep != filep)){ \
+ spin_unlock(&me_lock); \
+ PERROR("Resource is locked by another process\n"); \
+ karg.errno = ME_ERRNO_LOCKED; \
+ } \
+ else { \
+ me_count++; \
+ spin_unlock(&me_lock); \
+ \
+ karg.errno = device->DEV_CALL ARGS; \
+ \
+ spin_lock(&me_lock); \
+ me_count--; \
+ spin_unlock(&me_lock); \
+ } \
+ } \
+ \
+ up_read(&me_rwsem); \
+ \
+ err = copy_to_user(arg, &karg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy arguments back to user space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ return ME_ERRNO_SUCCESS; \
+}
+
+#define ME_QUERY_MULTIPLEX_STR_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \
+static int CALL(struct file *filep, TYPE *arg){ \
+ int err = 0; \
+ int k = 0; \
+ struct list_head *pos; \
+ me_device_t *device; \
+ char *msg = NULL; \
+ TYPE karg; \
+ \
+ PDEBUG("executed.\n"); \
+ \
+ err = copy_from_user(&karg, arg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy arguments to kernel space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ down_read(&me_rwsem); \
+ \
+ list_for_each(pos, &me_device_list){ \
+ if(k == karg.device){ \
+ device = list_entry(pos, me_device_t, list); \
+ break; \
+ } \
+ k++; \
+ } \
+ \
+ if(pos == &me_device_list){ \
+ PERROR("Invalid device number specified\n"); \
+ karg.errno = ME_ERRNO_INVALID_DEVICE; \
+ } \
+ else{ \
+ karg.errno = device->DEV_CALL ARGS; \
+ if(!karg.errno){ \
+ if((strlen(msg) + 1) > karg.count){ \
+ PERROR("User buffer for device name is to little\n"); \
+ karg.errno = ME_ERRNO_USER_BUFFER_SIZE; \
+ } \
+ else{ \
+ err = copy_to_user(karg.name, msg, strlen(msg) + 1); \
+ if(err){ \
+ PERROR("Can't copy device name to user space\n"); \
+ return -EFAULT; \
+ } \
+ } \
+ } \
+ } \
+ \
+ up_read(&me_rwsem); \
+ \
+ err = copy_to_user(arg, &karg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy query back to user space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ return ME_ERRNO_SUCCESS; \
+}
+
+#define ME_QUERY_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \
+static int CALL(struct file *filep, TYPE *arg){ \
+ int err = 0; \
+ int k = 0; \
+ struct list_head *pos; \
+ me_device_t *device; \
+ TYPE karg; \
+ \
+ PDEBUG("executed.\n"); \
+ \
+ err = copy_from_user(&karg, arg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy arguments from user space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ down_read(&me_rwsem); \
+ \
+ list_for_each(pos, &me_device_list){ \
+ if(k == karg.device){ \
+ device = list_entry(pos, me_device_t, list); \
+ break; \
+ } \
+ k++; \
+ } \
+ \
+ if(pos == &me_device_list){ \
+ PERROR("Invalid device number specified\n"); \
+ karg.errno = ME_ERRNO_INVALID_DEVICE; \
+ } \
+ else{ \
+ karg.errno = device->DEV_CALL ARGS; \
+ } \
+ \
+ up_read(&me_rwsem); \
+ \
+ err = copy_to_user(arg, &karg, sizeof(TYPE)); \
+ if(err){ \
+ PERROR("Can't copy arguments to user space\n"); \
+ return -EFAULT; \
+ } \
+ \
+ return ME_ERRNO_SUCCESS; \
+}
+
+#endif //__KERNEL__
+#endif
diff --git a/drivers/staging/meilhaus/meplx_reg.h b/drivers/staging/meilhaus/meplx_reg.h
new file mode 100644
index 000000000000..1868614dc232
--- /dev/null
+++ b/drivers/staging/meilhaus/meplx_reg.h
@@ -0,0 +1,53 @@
+/**
+ * @file meplx_reg.h
+ *
+ * @brief PLX 9052 PCI bridge register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MEPLX_REG_H_
+#define _MEPLX_REG_H_
+
+#ifdef __KERNEL__
+
+#define PLX_INTCSR 0x4C /**< Interrupt control and status register. */
+#define PLX_INTCSR_LOCAL_INT1_EN 0x01 /**< If set, local interrupt 1 is enabled (r/w). */
+#define PLX_INTCSR_LOCAL_INT1_POL 0x02 /**< If set, local interrupt 1 polarity is active high (r/w). */
+#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 /**< If set, local interrupt 1 is active (r/_). */
+#define PLX_INTCSR_LOCAL_INT2_EN 0x08 /**< If set, local interrupt 2 is enabled (r/w). */
+#define PLX_INTCSR_LOCAL_INT2_POL 0x10 /**< If set, local interrupt 2 polarity is active high (r/w). */
+#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 /**< If set, local interrupt 2 is active (r/_). */
+#define PLX_INTCSR_PCI_INT_EN 0x40 /**< If set, PCI interrupt is enabled (r/w). */
+#define PLX_INTCSR_SOFT_INT 0x80 /**< If set, a software interrupt is generated (r/w). */
+
+#define PLX_ICR 0x50 /**< Initialization control register. */
+#define PLX_ICR_BIT_EEPROM_CLOCK_SET 0x01000000
+#define PLX_ICR_BIT_EEPROM_CHIP_SELECT 0x02000000
+#define PLX_ICR_BIT_EEPROM_WRITE 0x04000000
+#define PLX_ICR_BIT_EEPROM_READ 0x08000000
+#define PLX_ICR_BIT_EEPROM_VALID 0x10000000
+
+#define PLX_ICR_MASK_EEPROM 0x1F000000
+#define EEPROM_DELAY 1
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/meslist.c b/drivers/staging/meilhaus/meslist.c
new file mode 100644
index 000000000000..7e8b66c05f7e
--- /dev/null
+++ b/drivers/staging/meilhaus/meslist.c
@@ -0,0 +1,173 @@
+/**
+ * @file me_slist.c
+ *
+ * @brief Implements the subdevice list class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "meerror.h"
+#include "medefines.h"
+
+#include "meslist.h"
+#include "medebug.h"
+
+int me_slist_query_number_subdevices(struct me_slist *slist, int *number)
+{
+ PDEBUG_LOCKS("called.\n");
+ *number = slist->n;
+ return ME_ERRNO_SUCCESS;
+}
+
+unsigned int me_slist_get_number_subdevices(struct me_slist *slist)
+{
+ PDEBUG_LOCKS("called.\n");
+ return slist->n;
+}
+
+me_subdevice_t *me_slist_get_subdevice(struct me_slist * slist,
+ unsigned int index)
+{
+
+ struct list_head *pos;
+ me_subdevice_t *subdevice = NULL;
+ unsigned int i = 0;
+
+ PDEBUG_LOCKS("called.\n");
+
+ if (index >= slist->n) {
+ PERROR("Index out of range.\n");
+ return NULL;
+ }
+
+ list_for_each(pos, &slist->head) {
+ if (i == index) {
+ subdevice = list_entry(pos, me_subdevice_t, list);
+ break;
+ }
+
+ ++i;
+ }
+
+ return subdevice;
+}
+
+int me_slist_get_subdevice_by_type(struct me_slist *slist,
+ unsigned int start_subdevice,
+ int type, int subtype, int *subdevice)
+{
+ me_subdevice_t *pos;
+ int s_type, s_subtype;
+ unsigned int index = 0;
+
+ PDEBUG_LOCKS("called.\n");
+
+ if (start_subdevice >= slist->n) {
+ PERROR("Start index out of range.\n");
+ return ME_ERRNO_NOMORE_SUBDEVICE_TYPE;
+ }
+
+ list_for_each_entry(pos, &slist->head, list) {
+ if (index < start_subdevice) { // Go forward to start subdevice.
+ ++index;
+ continue;
+ }
+
+ pos->me_subdevice_query_subdevice_type(pos,
+ &s_type, &s_subtype);
+
+ if (subtype == ME_SUBTYPE_ANY) {
+ if (s_type == type)
+ break;
+ } else {
+ if ((s_type == type) && (s_subtype == subtype))
+ break;
+ }
+
+ ++index;
+ }
+
+ if (index >= slist->n) {
+ return ME_ERRNO_NOMORE_SUBDEVICE_TYPE;
+ }
+
+ *subdevice = index;
+
+ return ME_ERRNO_SUCCESS;
+}
+
+void me_slist_add_subdevice_tail(struct me_slist *slist,
+ me_subdevice_t * subdevice)
+{
+ PDEBUG_LOCKS("called.\n");
+
+ list_add_tail(&subdevice->list, &slist->head);
+ ++slist->n;
+}
+
+me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist)
+{
+
+ struct list_head *last;
+ me_subdevice_t *subdevice;
+
+ PDEBUG_LOCKS("called.\n");
+
+ if (list_empty(&slist->head))
+ return NULL;
+
+ last = slist->head.prev;
+
+ subdevice = list_entry(last, me_subdevice_t, list);
+
+ list_del(last);
+
+ --slist->n;
+
+ return subdevice;
+}
+
+int me_slist_init(me_slist_t * slist)
+{
+ PDEBUG_LOCKS("called.\n");
+
+ INIT_LIST_HEAD(&slist->head);
+ slist->n = 0;
+ return 0;
+}
+
+void me_slist_deinit(me_slist_t * slist)
+{
+
+ struct list_head *s;
+ me_subdevice_t *subdevice;
+
+ PDEBUG_LOCKS("called.\n");
+
+ while (!list_empty(&slist->head)) {
+ s = slist->head.next;
+ list_del(s);
+ subdevice = list_entry(s, me_subdevice_t, list);
+ subdevice->me_subdevice_destructor(subdevice);
+ }
+
+ slist->n = 0;
+}
diff --git a/drivers/staging/meilhaus/meslist.h b/drivers/staging/meilhaus/meslist.h
new file mode 100644
index 000000000000..d26c89693d2c
--- /dev/null
+++ b/drivers/staging/meilhaus/meslist.h
@@ -0,0 +1,108 @@
+/**
+ * @file me_slist.h
+ *
+ * @brief Provides the subdevice list class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _ME_SLIST_H_
+#define _ME_SLIST_H_
+
+#include <linux/list.h>
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The subdevice list container.
+ */
+typedef struct me_slist {
+ struct list_head head; /**< The head of the internal list. */
+ unsigned int n; /**< The number of subdevices in the list. */
+} me_slist_t;
+
+/**
+ * @brief Queries the number of subdevices currently inside the list.
+ *
+ * @param slist The subdevice list to query.
+ * @param[out] number The number of subdevices of the device.
+ *
+ * @return ME-iDS error code.
+ */
+int me_slist_query_number_subdevices(struct me_slist *slist, int *number);
+
+/**
+ * @brief Returns the number of subdevices currently inside the list.
+ *
+ * @param slist The subdevice list to query.
+ *
+ * @return The number of subdevices in the list.
+ */
+unsigned int me_slist_get_number_subdevices(struct me_slist *slist);
+
+/**
+ * @brief Get a subdevice by index.
+ *
+ * @param slist The subdevice list to query.
+ * @param index The index of the subdevice to get in the list.
+ *
+ * @return The subdevice at index if available.\n
+ * NULL if the index is out of range.
+ */
+me_subdevice_t *me_slist_get_subdevice(struct me_slist *slist,
+ unsigned int index);
+
+/**
+ * @brief Get a subdevice index by type and subtype.
+ *
+ * @param slist The subdevice list to query.
+ * @param start_subdevice The subdevice index at which the start shall begin.
+ * @param type The type of the subdevice to query.
+ * @param subtype The subtype of the subdevice to query.
+ * @param[out] subdevice On success this parameter returns the index of the subdevice matching the requested type.
+ *
+ * @return ME_ERRNO_SUCCESS on success.
+ */
+int me_slist_get_subdevice_by_type(struct me_slist *slist,
+ unsigned int start_subdevice,
+ int type, int subtype, int *subdevice);
+
+/**
+ * @brief Adds a subdevice to the tail of the list.
+ *
+ * @param slist The subdevice list to add a subdevice to.
+ * @param subdevice The subdevice to add to the list.
+ */
+void me_slist_add_subdevice_tail(struct me_slist *slist,
+ me_subdevice_t * subdevice);
+
+/**
+ * @brief Removes a subdevice from the tail of the list.
+ *
+ * @param slist The subdevice list.
+ *
+ * @return Pointer to the removed subdeivce.\n
+ * NULL in cases where the list was empty.
+ */
+me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist);
+
+/**
+ * @brief Initializes a subdevice list structure.
+ *
+ * @param lock The subdevice list structure to initialize.
+ * @return 0 on success.
+ */
+int me_slist_init(me_slist_t * slist);
+
+/**
+ * @brief Deinitializes a subdevice list structure and destructs every subdevice in it.
+ *
+ * @param slist The subdevice list structure to deinitialize.
+ * @return 0 on success.
+ */
+void me_slist_deinit(me_slist_t * slist);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/meslock.c b/drivers/staging/meilhaus/meslock.c
new file mode 100644
index 000000000000..5230b89b45b5
--- /dev/null
+++ b/drivers/staging/meilhaus/meslock.c
@@ -0,0 +1,136 @@
+/**
+ * @file meslock.c
+ *
+ * @brief Implements the subdevice lock class.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/spinlock.h>
+
+#include "medefines.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "meslock.h"
+
+int me_slock_enter(struct me_slock *slock, struct file *filep)
+{
+ PDEBUG_LOCKS("executed.\n");
+
+ spin_lock(&slock->spin_lock);
+
+ if ((slock->filep) != NULL && (slock->filep != filep)) {
+ PERROR("Subdevice is locked by another process.\n");
+ spin_unlock(&slock->spin_lock);
+ return ME_ERRNO_LOCKED;
+ }
+
+ slock->count++;
+
+ spin_unlock(&slock->spin_lock);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+int me_slock_exit(struct me_slock *slock, struct file *filep)
+{
+ PDEBUG_LOCKS("executed.\n");
+
+ spin_lock(&slock->spin_lock);
+ slock->count--;
+ spin_unlock(&slock->spin_lock);
+
+ return ME_ERRNO_SUCCESS;
+}
+
+int me_slock_lock(struct me_slock *slock, struct file *filep, int lock)
+{
+ PDEBUG_LOCKS("executed.\n");
+
+ switch (lock) {
+
+ case ME_LOCK_RELEASE:
+ spin_lock(&slock->spin_lock);
+
+ if (slock->filep == filep)
+ slock->filep = NULL;
+
+ spin_unlock(&slock->spin_lock);
+
+ break;
+
+ case ME_LOCK_SET:
+ spin_lock(&slock->spin_lock);
+
+ if (slock->count) {
+ spin_unlock(&slock->spin_lock);
+ PERROR("Subdevice is used by another process.\n");
+ return ME_ERRNO_USED;
+ } else if (slock->filep == NULL)
+ slock->filep = filep;
+ else if (slock->filep != filep) {
+ spin_unlock(&slock->spin_lock);
+ PERROR("Subdevice is locked by another process.\n");
+ return ME_ERRNO_LOCKED;
+ }
+
+ spin_unlock(&slock->spin_lock);
+
+ break;
+
+ case ME_LOCK_CHECK:
+ spin_lock(&slock->spin_lock);
+
+ if (slock->count) {
+ spin_unlock(&slock->spin_lock);
+ return ME_ERRNO_USED;
+ } else if ((slock->filep != NULL) && (slock->filep != filep)) {
+ spin_unlock(&slock->spin_lock);
+ return ME_ERRNO_LOCKED;
+ }
+
+ spin_unlock(&slock->spin_lock);
+
+ break;
+
+ default:
+ break;
+ }
+
+ return ME_ERRNO_SUCCESS;
+}
+
+void me_slock_deinit(struct me_slock *slock)
+{
+ PDEBUG_LOCKS("executed.\n");
+}
+
+int me_slock_init(me_slock_t * slock)
+{
+ PDEBUG_LOCKS("executed.\n");
+
+ slock->filep = NULL;
+ slock->count = 0;
+ spin_lock_init(&slock->spin_lock);
+
+ return 0;
+}
diff --git a/drivers/staging/meilhaus/meslock.h b/drivers/staging/meilhaus/meslock.h
new file mode 100644
index 000000000000..f42b25c3f622
--- /dev/null
+++ b/drivers/staging/meilhaus/meslock.h
@@ -0,0 +1,73 @@
+/**
+ * @file meslock.h
+ *
+ * @brief Provides the subdevice lock class.
+ * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _MESLOCK_H_
+#define _MESLOCK_H_
+
+#include <linux/spinlock.h>
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The subdevice lock class.
+ */
+typedef struct me_slock {
+ struct file *filep; /**< Pointer to file structure holding the subdevice. */
+ int count; /**< Number of tasks which are inside the subdevice. */
+ spinlock_t spin_lock; /**< Spin lock protecting the attributes from concurrent access. */
+} me_slock_t;
+
+/**
+ * @brief Tries to enter a subdevice.
+ *
+ * @param slock The subdevice lock instance.
+ * @param filep The file structure identifying the calling process.
+ *
+ * @return 0 on success.
+ */
+int me_slock_enter(struct me_slock *slock, struct file *filep);
+
+/**
+ * @brief Exits a subdevice.
+ *
+ * @param slock The subdevice lock instance.
+ * @param filep The file structure identifying the calling process.
+ *
+ * @return 0 on success.
+ */
+int me_slock_exit(struct me_slock *slock, struct file *filep);
+
+/**
+ * @brief Tries to perform a locking action on a subdevice.
+ *
+ * @param slock The subdevice lock instance.
+ * @param filep The file structure identifying the calling process.
+ * @param The action to be done.
+ *
+ * @return 0 on success.
+ */
+int me_slock_lock(struct me_slock *slock, struct file *filep, int lock);
+
+/**
+ * @brief Initializes a lock structure.
+ *
+ * @param slock The lock structure to initialize.
+ * @return 0 on success.
+ */
+int me_slock_init(me_slock_t * slock);
+
+/**
+ * @brief Deinitializes a lock structure.
+ *
+ * @param slock The lock structure to deinitialize.
+ * @return 0 on success.
+ */
+void me_slock_deinit(me_slock_t * slock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/mesubdevice.c b/drivers/staging/meilhaus/mesubdevice.c
new file mode 100644
index 000000000000..98d4f1f7a824
--- /dev/null
+++ b/drivers/staging/meilhaus/mesubdevice.c
@@ -0,0 +1,317 @@
+/**
+ * @file mesubdevice.c
+ *
+ * @brief Subdevice base class implemention.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#include <linux/slab.h>
+
+#include "medefines.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "mesubdevice.h"
+
+static int me_subdevice_io_irq_start(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_irq_wait(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_irq_stop(struct me_subdevice *subdevice,
+ struct file *filep, int channel, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_reset_subdevice(struct me_subdevice *subdevice,
+ struct file *filep, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_single_config(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type,
+ int trig_edge, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_single_read(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int *value, int time_out, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_single_write(struct me_subdevice *subdevice,
+ struct file *filep,
+ int channel,
+ int value, int time_out, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_stream_config(struct me_subdevice *subdevice,
+ struct file *filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_stream_new_values(struct me_subdevice *subdevice,
+ struct file *filep,
+ int time_out,
+ int *count, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_stream_read(struct me_subdevice *subdevice,
+ struct file *filep,
+ int read_mode,
+ int *values, int *count, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_stream_start(struct me_subdevice *subdevice,
+ struct file *filep,
+ int start_mode, int time_out, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_stream_status(struct me_subdevice *subdevice,
+ struct file *filep,
+ int wait,
+ int *status, int *count, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_stream_stop(struct me_subdevice *subdevice,
+ struct file *filep,
+ int stop_mode, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_io_stream_write(struct me_subdevice *subdevice,
+ struct file *filep,
+ int write_mode,
+ int *values, int *count, int flags)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_lock_subdevice(me_subdevice_t * subdevice,
+ struct file *filep, int lock, int flags)
+{
+ PDEBUG("executed.\n");
+ return me_slock_lock(&subdevice->lock, filep, lock);
+}
+
+static int me_subdevice_query_number_channels(struct me_subdevice *subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_query_number_ranges(struct me_subdevice *subdevice,
+ int unit, int *count)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_query_range_by_min_max(struct me_subdevice *subdevice,
+ int unit,
+ int *min,
+ int *max,
+ int *maxdata, int *range)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_query_range_info(struct me_subdevice *subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_query_subdevice_type(struct me_subdevice *subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_query_subdevice_caps(struct me_subdevice *subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int me_subdevice_query_subdevice_caps_args(struct me_subdevice
+ *subdevice, int cap,
+ int *args, int count)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_query_timer(struct me_subdevice *subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks, long long *max_ticks)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_NOT_SUPPORTED;
+}
+
+static int me_subdevice_config_load(struct me_subdevice *subdevice,
+ me_cfg_device_entry_t * config)
+{
+ PDEBUG("executed.\n");
+ return ME_ERRNO_SUCCESS;
+}
+
+static void me_subdevice_destructor(struct me_subdevice *subdevice)
+{
+ PDEBUG("executed.\n");
+ me_subdevice_deinit(subdevice);
+ kfree(subdevice);
+}
+
+int me_subdevice_init(me_subdevice_t * subdevice)
+{
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Init list head */
+ INIT_LIST_HEAD(&subdevice->list);
+
+ /* Initialize the subdevice lock instance */
+
+ err = me_slock_init(&subdevice->lock);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice lock instance.\n");
+ return 1;
+ }
+
+ /* Subdevice base class methods */
+ subdevice->me_subdevice_io_irq_start = me_subdevice_io_irq_start;
+ subdevice->me_subdevice_io_irq_wait = me_subdevice_io_irq_wait;
+ subdevice->me_subdevice_io_irq_stop = me_subdevice_io_irq_stop;
+ subdevice->me_subdevice_io_reset_subdevice =
+ me_subdevice_io_reset_subdevice;
+ subdevice->me_subdevice_io_single_config =
+ me_subdevice_io_single_config;
+ subdevice->me_subdevice_io_single_read = me_subdevice_io_single_read;
+ subdevice->me_subdevice_io_single_write = me_subdevice_io_single_write;
+ subdevice->me_subdevice_io_stream_config =
+ me_subdevice_io_stream_config;
+ subdevice->me_subdevice_io_stream_new_values =
+ me_subdevice_io_stream_new_values;
+ subdevice->me_subdevice_io_stream_read = me_subdevice_io_stream_read;
+ subdevice->me_subdevice_io_stream_start = me_subdevice_io_stream_start;
+ subdevice->me_subdevice_io_stream_status =
+ me_subdevice_io_stream_status;
+ subdevice->me_subdevice_io_stream_stop = me_subdevice_io_stream_stop;
+ subdevice->me_subdevice_io_stream_write = me_subdevice_io_stream_write;
+ subdevice->me_subdevice_lock_subdevice = me_subdevice_lock_subdevice;
+ subdevice->me_subdevice_query_number_channels =
+ me_subdevice_query_number_channels;
+ subdevice->me_subdevice_query_number_ranges =
+ me_subdevice_query_number_ranges;
+ subdevice->me_subdevice_query_range_by_min_max =
+ me_subdevice_query_range_by_min_max;
+ subdevice->me_subdevice_query_range_info =
+ me_subdevice_query_range_info;
+ subdevice->me_subdevice_query_subdevice_type =
+ me_subdevice_query_subdevice_type;
+ subdevice->me_subdevice_query_subdevice_caps =
+ me_subdevice_query_subdevice_caps;
+ subdevice->me_subdevice_query_subdevice_caps_args =
+ me_subdevice_query_subdevice_caps_args;
+ subdevice->me_subdevice_query_timer = me_subdevice_query_timer;
+ subdevice->me_subdevice_config_load = me_subdevice_config_load;
+ subdevice->me_subdevice_destructor = me_subdevice_destructor;
+
+ return 0;
+}
+
+void me_subdevice_deinit(me_subdevice_t * subdevice)
+{
+ PDEBUG("executed.\n");
+ me_subdevice_io_reset_subdevice(subdevice, NULL,
+ ME_IO_RESET_SUBDEVICE_NO_FLAGS);
+ me_slock_deinit(&subdevice->lock);
+}
diff --git a/drivers/staging/meilhaus/mesubdevice.h b/drivers/staging/meilhaus/mesubdevice.h
new file mode 100644
index 000000000000..19ec2b5d96f0
--- /dev/null
+++ b/drivers/staging/meilhaus/mesubdevice.h
@@ -0,0 +1,197 @@
+/**
+ * @file mesubdevice.h
+ *
+ * @brief Provides the subdevice base class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+#ifndef _MESUBDEVICE_H_
+#define _MESUBDEVICE_H_
+
+#include <linux/list.h>
+
+#include "metypes.h"
+#include "meioctl.h"
+#include "meslock.h"
+
+# include <linux/workqueue.h>
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Macro used to enter a subdevice.
+ */
+#define ME_SUBDEVICE_ENTER \
+{ \
+ int err; \
+ err = me_slock_enter(&instance->base.lock, filep); \
+ if(err){ \
+ PERROR("Cannot enter subdevice.\n"); \
+ return err; \
+ } \
+}
+
+/**
+ * @brief Macro used to exit a subdevice.
+ */
+#define ME_SUBDEVICE_EXIT \
+{\
+ int err; \
+ err = me_slock_exit(&instance->base.lock, filep); \
+ if(err){ \
+ PERROR("Cannot exit subdevice.\n"); \
+ return err; \
+ } \
+}
+
+/**
+ * @brief The subdevice base class.
+ */
+typedef struct me_subdevice {
+ /* Attributes */
+ struct list_head list; /**< Enables the subdevice to be added to a dynamic list. */
+ me_slock_t lock; /**< Used by user application in order to lock the subdevice for exclusive usage. */
+
+ /* Methods */
+ int (*me_subdevice_io_irq_start) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int channel,
+ int irq_source,
+ int irq_edge, int irq_arg, int flags);
+
+ int (*me_subdevice_io_irq_wait) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int channel,
+ int *irq_count,
+ int *value, int time_out, int flags);
+
+ int (*me_subdevice_io_irq_stop) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int channel, int flags);
+
+ int (*me_subdevice_io_reset_subdevice) (struct me_subdevice * subdevice,
+ struct file * filep, int flags);
+
+ int (*me_subdevice_io_single_config) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int channel,
+ int single_config,
+ int ref,
+ int trig_chan,
+ int trig_type,
+ int trig_edge, int flags);
+
+ int (*me_subdevice_io_single_read) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int channel,
+ int *value,
+ int time_out, int flags);
+
+ int (*me_subdevice_io_single_write) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int channel,
+ int value,
+ int time_out, int flags);
+
+ int (*me_subdevice_io_stream_config) (struct me_subdevice * subdevice,
+ struct file * filep,
+ meIOStreamConfig_t * config_list,
+ int count,
+ meIOStreamTrigger_t * trigger,
+ int fifo_irq_threshold,
+ int flags);
+
+ int (*me_subdevice_io_stream_new_values) (struct me_subdevice *
+ subdevice,
+ struct file * filep,
+ int time_out, int *count,
+ int flags);
+
+ int (*me_subdevice_io_stream_read) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int read_mode,
+ int *values, int *count, int flags);
+
+ int (*me_subdevice_io_stream_start) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int start_mode,
+ int time_out, int flags);
+
+ int (*me_subdevice_io_stream_status) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int wait,
+ int *status,
+ int *count, int flags);
+
+ int (*me_subdevice_io_stream_stop) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int stop_mode, int flags);
+
+ int (*me_subdevice_io_stream_write) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int write_mode,
+ int *values,
+ int *count, int flags);
+
+ int (*me_subdevice_lock_subdevice) (struct me_subdevice * subdevice,
+ struct file * filep,
+ int lock, int flags);
+
+ int (*me_subdevice_query_number_channels) (struct me_subdevice *
+ subdevice, int *number);
+
+ int (*me_subdevice_query_number_ranges) (struct me_subdevice *
+ subdevice, int unit,
+ int *count);
+
+ int (*me_subdevice_query_range_by_min_max) (struct me_subdevice *
+ subdevice, int unit,
+ int *min, int *max,
+ int *maxdata, int *range);
+
+ int (*me_subdevice_query_range_info) (struct me_subdevice * subdevice,
+ int range,
+ int *unit,
+ int *min, int *max, int *maxdata);
+
+ int (*me_subdevice_query_subdevice_type) (struct me_subdevice *
+ subdevice, int *type,
+ int *subtype);
+
+ int (*me_subdevice_query_subdevice_caps) (struct me_subdevice *
+ subdevice, int *caps);
+
+ int (*me_subdevice_query_subdevice_caps_args) (struct me_subdevice *
+ subdevice, int cap,
+ int *args, int count);
+
+ int (*me_subdevice_query_timer) (struct me_subdevice * subdevice,
+ int timer,
+ int *base_frequency,
+ long long *min_ticks,
+ long long *max_ticks);
+
+ int (*me_subdevice_config_load) (struct me_subdevice * subdevice,
+ me_cfg_device_entry_t * config);
+
+ void (*me_subdevice_destructor) (struct me_subdevice * subdevice);
+} me_subdevice_t;
+
+/**
+ * @brief Initializes a subdevice structure.
+ *
+ * @param subdevice The subdevice structure to initialize.
+ * @return 0 on success.
+ */
+int me_subdevice_init(me_subdevice_t * subdevice);
+
+/**
+ * @brief Deinitializes a subdevice structure.
+ *
+ * @param subdevice The subdevice structure to initialize.
+ */
+void me_subdevice_deinit(me_subdevice_t * subdevice);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/metempl_device.c b/drivers/staging/meilhaus/metempl_device.c
new file mode 100644
index 000000000000..e48632ddc1aa
--- /dev/null
+++ b/drivers/staging/meilhaus/metempl_device.c
@@ -0,0 +1,137 @@
+/**
+ * @file metempl_device.c
+ *
+ * @brief template device class implementation.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <meids.h>
+#include "meerror.h"
+#include "mecommon.h"
+#include "meinternal.h"
+
+#include "medebug.h"
+#include "medevice.h"
+#include "metempl_device.h"
+#include "mesubdevice.h"
+#include "metempl_sub.h"
+
+me_device_t *metempl_pci_constructor(struct pci_dev *pci_device)
+{
+ metempl_device_t *metempl_device;
+ me_subdevice_t *subdevice;
+ unsigned int version_idx;
+ int err;
+ int i;
+
+ PDEBUG("executed.\n");
+
+ // Allocate structure for device instance.
+ metempl_device = kmalloc(sizeof(metempl_device_t), GFP_KERNEL);
+
+ if (!metempl_device) {
+ PERROR("Cannot get memory for device instance.\n");
+ return NULL;
+ }
+
+ memset(metempl_device, 0, sizeof(metempl_device_t));
+
+ // Initialize base class structure.
+ err = me_device_pci_init((me_device_t *) metempl_device, pci_device);
+
+ if (err) {
+ kfree(metempl_device);
+ PERROR("Cannot initialize device base class.\n");
+ return NULL;
+ }
+
+ /* Get the index in the device version information table. */
+ version_idx =
+ metempl_versions_get_device_index(metempl_device->base.info.pci.
+ device_id);
+
+ // Initialize spin lock .
+ spin_lock_init(&metempl_device->ctrl_reg_lock);
+
+ // Create subdevice instances.
+ for (i = 0; i < metempl_versions[version_idx].subdevices; i++) {
+ subdevice =
+ (me_subdevice_t *) metempl_sub_constructor(metempl_device->
+ base.info.pci.
+ reg_bases[2], i,
+ &metempl_device->
+ ctrl_reg_lock);
+
+ if (!subdevice) {
+ me_device_deinit((me_device_t *) metempl_device);
+ kfree(metempl_device);
+ PERROR("Cannot get memory for subdevice.\n");
+ return NULL;
+ }
+
+ me_slist_add_subdevice_tail(&metempl_device->base.slist,
+ subdevice);
+ }
+
+ /* Overwrite base class methods if applicable. */
+
+ return (me_device_t *) metempl_device;
+}
+
+// Init and exit of module.
+
+static int __init metempl_init(void)
+{
+ PDEBUG("executed.\n.");
+ return 0;
+}
+
+static void __exit metempl_exit(void)
+{
+ PDEBUG("executed.\n.");
+}
+
+module_init(metempl_init);
+
+module_exit(metempl_exit);
+
+// Administrative stuff for modinfo.
+MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>");
+MODULE_DESCRIPTION("Device Driver Module for Template Device");
+MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices");
+MODULE_LICENSE("GPL");
+
+// Export the constructor.
+EXPORT_SYMBOL(metempl_pci_constructor);
diff --git a/drivers/staging/meilhaus/metempl_device.h b/drivers/staging/meilhaus/metempl_device.h
new file mode 100644
index 000000000000..3c3702cc72eb
--- /dev/null
+++ b/drivers/staging/meilhaus/metempl_device.h
@@ -0,0 +1,92 @@
+/**
+ * @file metempl_device.h
+ *
+ * @brief template device class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _METEMPL_DEVICE_H
+#define _METEMPL_DEVICE_H
+
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "medevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief Structure holding template device capabilities.
+ */
+typedef struct metempl_version {
+ uint16_t device_id;
+ unsigned int subdevices;
+} metempl_version_t;
+
+/**
+ * @brief Device capabilities.
+ */
+static metempl_version_t metempl_versions[] = {
+ {0xDEAD, 1},
+ {0},
+};
+
+#define METEMPL_DEVICE_VERSIONS (sizeof(metempl_versions) / sizeof(metempl_version_t) - 1) /**< Returns the number of entries in #metempl_versions. */
+
+/**
+ * @brief Returns the index of the device entry in #metempl_versions.
+ *
+ * @param device_id The PCI device id of the device to query.
+ * @return The index of the device in #metempl_versions.
+ */
+static inline unsigned int metempl_versions_get_device_index(uint16_t device_id)
+{
+ unsigned int i;
+ for (i = 0; i < METEMPL_DEVICE_VERSIONS; i++)
+ if (metempl_versions[i].device_id == device_id)
+ break;
+ return i;
+}
+
+/**
+ * @brief The template device class structure.
+ */
+typedef struct metempl_device {
+ me_device_t base; /**< The Meilhaus device base class. */
+
+ /* Child class attributes. */
+ spinlock_t ctrl_reg_lock;
+} metempl_device_t;
+
+/**
+ * @brief The template device class constructor.
+ *
+ * @param pci_device The pci device structure given by the PCI subsystem.
+ *
+ * @return On succes a new template device instance. \n
+ * NULL on error.
+ */
+me_device_t *metempl_pci_constructor(struct pci_dev *pci_device)
+ __attribute__ ((weak));
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/metempl_sub.c b/drivers/staging/meilhaus/metempl_sub.c
new file mode 100644
index 000000000000..f1d65d889e23
--- /dev/null
+++ b/drivers/staging/meilhaus/metempl_sub.c
@@ -0,0 +1,149 @@
+/**
+ * @file metempl_sub.c
+ *
+ * @brief Subdevice instance.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+
+/*
+ * Includes
+ */
+#include <linux/module.h>
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <linux/types.h>
+
+#include "medefines.h"
+#include "meinternal.h"
+#include "meerror.h"
+
+#include "medebug.h"
+#include "metempl_sub_reg.h"
+#include "metempl_sub.h"
+
+/*
+ * Defines
+ */
+
+/*
+ * Functions
+ */
+
+static void metempl_sub_destructor(struct me_subdevice *subdevice)
+{
+ metempl_sub_subdevice_t *instance;
+
+ PDEBUG("executed.\n");
+ instance = (metempl_sub_subdevice_t *) subdevice;
+
+ /* Until there this was the things the default constructor does.
+ If you do not have any additional things to do you can wipe it out. */
+
+ me_subdevice_deinit(&instance->base);
+ kfree(instance);
+}
+
+static int metempl_sub_query_number_channels(me_subdevice_t * subdevice,
+ int *number)
+{
+ PDEBUG("executed.\n");
+ *number = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int metempl_sub_query_subdevice_type(me_subdevice_t * subdevice,
+ int *type, int *subtype)
+{
+ PDEBUG("executed.\n");
+ *type = 0;
+ *subtype = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+static int metempl_sub_query_subdevice_caps(me_subdevice_t * subdevice,
+ int *caps)
+{
+ PDEBUG("executed.\n");
+ *caps = 0;
+ return ME_ERRNO_SUCCESS;
+}
+
+metempl_sub_subdevice_t *metempl_sub_constructor(uint32_t reg_base,
+ unsigned int sub_idx,
+ spinlock_t * ctrl_reg_lock)
+{
+ metempl_sub_subdevice_t *subdevice;
+ int err;
+
+ PDEBUG("executed.\n");
+
+ /* Allocate memory for subdevice instance */
+ subdevice = kmalloc(sizeof(metempl_sub_subdevice_t), GFP_KERNEL);
+
+ if (!subdevice) {
+ PERROR("Cannot get memory for subdevice instance.\n");
+ return NULL;
+ }
+
+ memset(subdevice, 0, sizeof(metempl_sub_subdevice_t));
+
+ /* Check if subdevice index is out of range */
+
+ if (sub_idx >= 2) {
+ PERROR("Template subdevice index is out of range.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+
+ /* Initialize subdevice base class */
+ err = me_subdevice_init(&subdevice->base);
+
+ if (err) {
+ PERROR("Cannot initialize subdevice base class instance.\n");
+ kfree(subdevice);
+ return NULL;
+ }
+ // Initialize spin locks.
+ spin_lock_init(&subdevice->subdevice_lock);
+
+ subdevice->ctrl_reg_lock = ctrl_reg_lock;
+
+ /* Save the subdevice index */
+ subdevice->sub_idx = sub_idx;
+
+ /* Override base class methods. */
+ subdevice->base.me_subdevice_destructor = metempl_sub_destructor;
+ subdevice->base.me_subdevice_query_number_channels =
+ metempl_sub_query_number_channels;
+ subdevice->base.me_subdevice_query_subdevice_type =
+ metempl_sub_query_subdevice_type;
+ subdevice->base.me_subdevice_query_subdevice_caps =
+ metempl_sub_query_subdevice_caps;
+
+ return subdevice;
+}
diff --git a/drivers/staging/meilhaus/metempl_sub.h b/drivers/staging/meilhaus/metempl_sub.h
new file mode 100644
index 000000000000..80c8af9a8c5a
--- /dev/null
+++ b/drivers/staging/meilhaus/metempl_sub.h
@@ -0,0 +1,64 @@
+/**
+ * @file metempl_sub.h
+ *
+ * @brief Meilhaus subdevice class.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _METEMPL_SUB_H_
+#define _METEMPL_SUB_H_
+
+#include "mesubdevice.h"
+
+#ifdef __KERNEL__
+
+/**
+ * @brief The subdevice class.
+ */
+typedef struct metempl_sub_subdevice {
+ /* Inheritance */
+ me_subdevice_t base; /**< The subdevice base class. */
+
+ /* Attributes */
+ spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */
+ spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */
+ int sub_idx; /**< The index of the subdevice on the device. */
+
+ unsigned long ctrl_reg; /**< Register to configure the modes. */
+} metempl_sub_subdevice_t;
+
+/**
+ * @brief The constructor to generate a subdevice instance.
+ *
+ * @param reg_base The register base address of the device as returned by the PCI BIOS.
+ * @param sub_idx The index of the subdevice on the device.
+ * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access.
+ *
+ * @return Pointer to new instance on success.\n
+ * NULL on error.
+ */
+metempl_sub_subdevice_t *metempl_sub_constructor(uint32_t reg_base,
+ unsigned int sub_idx,
+ spinlock_t * ctrl_reg_lock);
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/metempl_sub_reg.h b/drivers/staging/meilhaus/metempl_sub_reg.h
new file mode 100644
index 000000000000..1a2cab778a12
--- /dev/null
+++ b/drivers/staging/meilhaus/metempl_sub_reg.h
@@ -0,0 +1,35 @@
+/**
+ * @file metempl_sub_reg.h
+ *
+ * @brief Subdevice register definitions.
+ * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ * @author Guenter Gebhardt
+ */
+
+/*
+ * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _METEMPL_SUB_REG_H_
+#define _METEMPL_SUB_REG_H_
+
+#ifdef __KERNEL__
+
+#define METEMPL_PORT_MODE 0x0010 /**< Configuration register. */
+
+#endif
+#endif
diff --git a/drivers/staging/meilhaus/metypes.h b/drivers/staging/meilhaus/metypes.h
new file mode 100644
index 000000000000..228ea15753ea
--- /dev/null
+++ b/drivers/staging/meilhaus/metypes.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de)
+ *
+ * Source File : metypes.h
+ * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de>
+ */
+
+#ifndef _METYPES_H_
+#define _METYPES_H_
+
+
+typedef int (*meErrorCB_t)(char *pcFunctionName, int iErrorCode);
+
+typedef int (*meIOStreamCB_t)(
+ int iDevice,
+ int iSubdevice,
+ int iCount,
+ void *pvContext,
+ int iErrorCode);
+
+typedef int (*meIOIrqCB_t)(
+ int iDevice,
+ int iSubdevice,
+ int iChannel,
+ int iIrqCount,
+ int iValue,
+ void *pvContext,
+ int iErrorCode);
+
+
+typedef struct meIOSingle {
+ int iDevice;
+ int iSubdevice;
+ int iChannel;
+ int iDir;
+ int iValue;
+ int iTimeOut;
+ int iFlags;
+ int iErrno;
+} meIOSingle_t;
+
+
+typedef struct meIOStreamConfig {
+ int iChannel;
+ int iStreamConfig;
+ int iRef;
+ int iFlags;
+} meIOStreamConfig_t;
+
+
+typedef struct meIOStreamTrigger {
+ int iAcqStartTrigType;
+ int iAcqStartTrigEdge;
+ int iAcqStartTrigChan;
+ int iAcqStartTicksLow;
+ int iAcqStartTicksHigh;
+ int iAcqStartArgs[10];
+ int iScanStartTrigType;
+ int iScanStartTicksLow;
+ int iScanStartTicksHigh;
+ int iScanStartArgs[10];
+ int iConvStartTrigType;
+ int iConvStartTicksLow;
+ int iConvStartTicksHigh;
+ int iConvStartArgs[10];
+ int iScanStopTrigType;
+ int iScanStopCount;
+ int iScanStopArgs[10];
+ int iAcqStopTrigType;
+ int iAcqStopCount;
+ int iAcqStopArgs[10];
+ int iFlags;
+} meIOStreamTrigger_t;
+
+
+typedef struct meIOStreamStart {
+ int iDevice;
+ int iSubdevice;
+ int iStartMode;
+ int iTimeOut;
+ int iFlags;
+ int iErrno;
+} meIOStreamStart_t;
+
+
+typedef struct meIOStreamStop {
+ int iDevice;
+ int iSubdevice;
+ int iStopMode;
+ int iFlags;
+ int iErrno;
+} meIOStreamStop_t;
+
+
+#endif
diff --git a/drivers/staging/mimio/Kconfig b/drivers/staging/mimio/Kconfig
new file mode 100644
index 000000000000..c0ba4c800dff
--- /dev/null
+++ b/drivers/staging/mimio/Kconfig
@@ -0,0 +1,10 @@
+config INPUT_MIMIO
+ tristate "Mimio Xi interactive whiteboard support"
+ depends on USB
+ default N
+ help
+ Say Y here if you want to use a Mimio Xi interactive
+ whiteboard device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mimio.
diff --git a/drivers/staging/mimio/Makefile b/drivers/staging/mimio/Makefile
new file mode 100644
index 000000000000..77807ee0450e
--- /dev/null
+++ b/drivers/staging/mimio/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_INPUT_MIMIO) += mimio.o
diff --git a/drivers/staging/mimio/mimio.c b/drivers/staging/mimio/mimio.c
new file mode 100644
index 000000000000..1ba8103f5003
--- /dev/null
+++ b/drivers/staging/mimio/mimio.c
@@ -0,0 +1,914 @@
+/*
+ * Hardware event => input event mapping:
+ *
+ *
+ *
+ input.h:#define BTN_TOOL_PEN 0x140 black
+ input.h:#define BTN_TOOL_RUBBER 0x141 blue
+ input.h:#define BTN_TOOL_BRUSH 0x142 green
+ input.h:#define BTN_TOOL_PENCIL 0x143 red
+ input.h:#define BTN_TOOL_AIRBRUSH 0x144 eraser
+ input.h:#define BTN_TOOL_FINGER 0x145 small eraser
+ input.h:#define BTN_TOOL_MOUSE 0x146 mimio interactive
+ input.h:#define BTN_TOOL_LENS 0x147 mimio interactive but1
+ input.h:#define LOCALBTN_TOOL_EXTRA1 0x14a mimio interactive but2 == BTN_TOUCH
+ input.h:#define LOCALBTN_TOOL_EXTRA2 0x14b mimio extra pens (orange, brown, yellow, purple) == BTN_STYLUS
+ input.h:#define LOCALBTN_TOOL_EXTRA3 0x14c unused == BTN_STYLUS2
+ input.h:#define BTN_TOOL_DOUBLETAP 0x14d unused
+ input.h:#define BTN_TOOL_TRIPLETAP 0x14e unused
+ *
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_K) => EV_KEY BIT(BTN_TOOL_PEN)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_B) => EV_KEY BIT(BTN_TOOL_RUBBER)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_G) => EV_KEY BIT(BTN_TOOL_BRUSH)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_R) => EV_KEY BIT(BTN_TOOL_PENCIL)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_E) => EV_KEY BIT(BTN_TOOL_AIRBRUSH)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_ES) => EV_KEY BIT(BTN_TOOL_FINGER)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_I) => EV_KEY BIT(BTN_TOOL_MOUSE)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_IL) => EV_KEY BIT(BTN_TOOL_LENS)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_IR) => EV_KEY BIT(BTN_TOOL_DOUBLETAP)
+ * MIMIO_EV_PENDOWN(MIMIO_PEN_EX) => EV_KEY BIT(BTN_TOOL_TRIPLETAP)
+ * MIMIO_EV_PENDATA => EV_ABS BIT(ABS_X), BIT(ABS_Y)
+ * MIMIO_EV_MEMRESET => EV_KEY BIT(BTN_0)
+ * MIMIO_EV_ACC(ACC_NEWPAGE) => EV_KEY BIT(BTN_1)
+ * MIMIO_EV_ACC(ACC_TAGPAGE) => EV_KEY BIT(BTN_2)
+ * MIMIO_EV_ACC(ACC_PRINTPAGE) => EV_KEY BIT(BTN_3)
+ * MIMIO_EV_ACC(ACC_MAXIMIZE) => EV_KEY BIT(BTN_4)
+ * MIMIO_EV_ACC(ACC_FINDCTLPNL) => EV_KEY BIT(BTN_5)
+ *
+ *
+ * open issues:
+ * - cold-load of data captured when mimio in standalone mode not yet
+ * supported; need to snoop Win32 box to see datastream for this.
+ * - mimio mouse not yet supported; need to snoop Win32 box to see the
+ * datastream for this.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#define DRIVER_VERSION "v0.031"
+#define DRIVER_AUTHOR "mwilder@cs.nmsu.edu"
+#define DRIVER_DESC "USB mimio-xi driver"
+
+enum {UPVALUE, DOWNVALUE, MOVEVALUE};
+
+#define MIMIO_XRANGE_MAX 9600
+#define MIMIO_YRANGE_MAX 4800
+
+#define LOCALBTN_TOOL_EXTRA1 BTN_TOUCH
+#define LOCALBTN_TOOL_EXTRA2 BTN_STYLUS
+#define LOCALBTN_TOOL_EXTRA3 BTN_STYLUS2
+
+#define MIMIO_VENDOR_ID 0x08d3
+#define MIMIO_PRODUCT_ID 0x0001
+#define MIMIO_MAXPAYLOAD (8)
+#define MIMIO_MAXNAMELEN (64)
+#define MIMIO_TXWAIT (1)
+#define MIMIO_TXDONE (2)
+
+#define MIMIO_EV_PENDOWN (0x22)
+#define MIMIO_EV_PENDATA (0x24)
+#define MIMIO_EV_PENUP (0x51)
+#define MIMIO_EV_MEMRESET (0x45)
+#define MIMIO_EV_ACC (0xb2)
+
+#define MIMIO_PEN_K (1) /* black pen */
+#define MIMIO_PEN_B (2) /* blue pen */
+#define MIMIO_PEN_G (3) /* green pen */
+#define MIMIO_PEN_R (4) /* red pen */
+/* 5, 6, 7, 8 are extra pens */
+#define MIMIO_PEN_E (9) /* big eraser */
+#define MIMIO_PEN_ES (10) /* lil eraser */
+#define MIMIO_PENJUMP_START (10)
+#define MIMIO_PENJUMP (6)
+#define MIMIO_PEN_I (17) /* mimio interactive */
+#define MIMIO_PEN_IL (18) /* mimio interactive button 1 */
+#define MIMIO_PEN_IR (19) /* mimio interactive button 2 */
+
+#define MIMIO_PEN_MAX (MIMIO_PEN_IR)
+
+#define ACC_DONE (0)
+#define ACC_NEWPAGE (1)
+#define ACC_TAGPAGE (2)
+#define ACC_PRINTPAGE (4)
+#define ACC_MAXIMIZE (8)
+#define ACC_FINDCTLPNL (16)
+
+#define isvalidtxsize(n) ((n) > 0 && (n) <= MIMIO_MAXPAYLOAD)
+
+
+struct pktbuf {
+ unsigned char instr;
+ unsigned char buf[16];
+ unsigned char *p;
+ unsigned char *q;
+};
+
+struct usbintendpt {
+ dma_addr_t dma;
+ struct urb *urb;
+ unsigned char *buf;
+ struct usb_endpoint_descriptor *desc;
+};
+
+struct mimio {
+ struct input_dev *idev;
+ struct usb_device *udev;
+ struct usb_interface *uifc;
+ int open;
+ int present;
+ int greeted;
+ int txflags;
+ char phys[MIMIO_MAXNAMELEN];
+ struct usbintendpt in;
+ struct usbintendpt out;
+ struct pktbuf pktbuf;
+ unsigned char minor;
+ wait_queue_head_t waitq;
+ spinlock_t txlock;
+ void (*rxhandler)(struct mimio *, unsigned char *, unsigned int);
+ int last_pen_down;
+};
+
+static void mimio_close(struct input_dev *);
+static void mimio_dealloc(struct mimio *);
+static void mimio_disconnect(struct usb_interface *);
+static int mimio_greet(struct mimio *);
+static void mimio_irq_in(struct urb *);
+static void mimio_irq_out(struct urb *);
+static int mimio_open(struct input_dev *);
+static int mimio_probe(struct usb_interface *, const struct usb_device_id *);
+static void mimio_rx_handler(struct mimio *, unsigned char *, unsigned int);
+static int mimio_tx(struct mimio *, const char *, int);
+
+static char mimio_name[] = "VirtualInk mimio-Xi";
+static struct usb_device_id mimio_table [] = {
+ { USB_DEVICE(MIMIO_VENDOR_ID, MIMIO_PRODUCT_ID) },
+ { USB_DEVICE(0x0525, 0xa4a0) }, /* gadget zero firmware */
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, mimio_table);
+
+static struct usb_driver mimio_driver = {
+ .name = "mimio",
+ .probe = mimio_probe,
+ .disconnect = mimio_disconnect,
+ .id_table = mimio_table,
+};
+
+static DECLARE_MUTEX(disconnect_sem);
+
+static void mimio_close(struct input_dev *idev)
+{
+ struct mimio *mimio;
+
+ mimio = input_get_drvdata(idev);
+ if (!mimio) {
+ dev_err(&idev->dev, "null mimio attached to input device\n");
+ return;
+ }
+
+ if (mimio->open <= 0)
+ dev_err(&idev->dev, "mimio not open.\n");
+ else
+ mimio->open--;
+
+ if (mimio->present == 0 && mimio->open == 0)
+ mimio_dealloc(mimio);
+}
+
+static void mimio_dealloc(struct mimio *mimio)
+{
+ if (mimio == NULL)
+ return;
+
+ usb_kill_urb(mimio->in.urb);
+
+ usb_kill_urb(mimio->out.urb);
+
+ if (mimio->idev) {
+ input_unregister_device(mimio->idev);
+ if (mimio->idev->grab)
+ input_close_device(mimio->idev->grab);
+ else
+ dev_dbg(&mimio->idev->dev, "mimio->idev->grab == NULL"
+ " -- didn't call input_close_device\n");
+ }
+
+ usb_free_urb(mimio->in.urb);
+
+ usb_free_urb(mimio->out.urb);
+
+ if (mimio->in.buf) {
+ usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->in.buf,
+ mimio->in.dma);
+ }
+
+ if (mimio->out.buf)
+ usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->out.buf,
+ mimio->out.dma);
+
+ if (mimio->idev)
+ input_free_device(mimio->idev);
+
+ kfree(mimio);
+}
+
+static void mimio_disconnect(struct usb_interface *ifc)
+{
+ struct mimio *mimio;
+
+ down(&disconnect_sem);
+
+ mimio = usb_get_intfdata(ifc);
+ usb_set_intfdata(ifc, NULL);
+ dev_dbg(&mimio->idev->dev, "disconnect\n");
+
+ if (mimio) {
+ mimio->present = 0;
+
+ if (mimio->open <= 0)
+ mimio_dealloc(mimio);
+ }
+
+ up(&disconnect_sem);
+}
+
+static int mimio_greet(struct mimio *mimio)
+{
+ const struct grtpkt {
+ int nbytes;
+ unsigned delay;
+ char data[8];
+ } grtpkts[] = {
+ { 3, 0, { 0x11, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 5, 0, { 0x53, 0x55, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 } },
+ { 5, 0, { 0x43, 0x55, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00 } },
+ { 5, 0, { 0x33, 0x55, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00 } },
+ { 5, 0, { 0x13, 0x00, 0x5e, 0x02, 0x4f, 0x00, 0x00, 0x00 } },
+ { 5, 0, { 0x13, 0x00, 0x04, 0x03, 0x14, 0x00, 0x00, 0x00 } },
+ { 5, 2, { 0x13, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00, 0x00 } },
+ { 5, 0, { 0x13, 0x00, 0x0d, 0x08, 0x16, 0x00, 0x00, 0x00 } },
+ { 5, 0, { 0x13, 0x00, 0x4d, 0x01, 0x5f, 0x00, 0x00, 0x00 } },
+ { 3, 0, { 0xf1, 0x55, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ { 7, 2, { 0x52, 0x55, 0x00, 0x07, 0x31, 0x55, 0x64, 0x00 } },
+ { 0, 0, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
+ };
+ int rslt;
+ const struct grtpkt *pkt;
+
+ for (pkt = grtpkts; pkt->nbytes; pkt++) {
+ rslt = mimio_tx(mimio, pkt->data, pkt->nbytes);
+ if (rslt)
+ return rslt;
+ if (pkt->delay)
+ msleep(pkt->delay);
+ }
+
+ return 0;
+}
+
+static void mimio_irq_in(struct urb *urb)
+{
+ int rslt;
+ char *data;
+ const char *reason = "going down";
+ struct mimio *mimio;
+
+ mimio = urb->context;
+
+ if (mimio == NULL)
+ /* paranoia */
+ return;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ETIMEDOUT:
+ reason = "timeout -- unplugged?";
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ dev_dbg(&mimio->idev->dev, "%s.\n", reason);
+ return;
+ default:
+ dev_dbg(&mimio->idev->dev, "unknown urb-status: %d.\n",
+ urb->status);
+ goto exit;
+ }
+ data = mimio->in.buf;
+
+ if (mimio->rxhandler)
+ mimio->rxhandler(mimio, data, urb->actual_length);
+exit:
+ /*
+ * Keep listening to device on same urb.
+ */
+ rslt = usb_submit_urb(urb, GFP_ATOMIC);
+ if (rslt)
+ dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
+ rslt);
+}
+
+static void mimio_irq_out(struct urb *urb)
+{
+ unsigned long flags;
+ struct mimio *mimio;
+
+ mimio = urb->context;
+
+ if (urb->status)
+ dev_dbg(&mimio->idev->dev, "urb-status: %d.\n", urb->status);
+
+ spin_lock_irqsave(&mimio->txlock, flags);
+ mimio->txflags |= MIMIO_TXDONE;
+ spin_unlock_irqrestore(&mimio->txlock, flags);
+ wmb();
+ wake_up(&mimio->waitq);
+}
+
+static int mimio_open(struct input_dev *idev)
+{
+ int rslt;
+ struct mimio *mimio;
+
+ rslt = 0;
+ down(&disconnect_sem);
+ mimio = input_get_drvdata(idev);
+ dev_dbg(&idev->dev, "mimio_open\n");
+
+ if (mimio == NULL) {
+ dev_err(&idev->dev, "null mimio.\n");
+ rslt = -ENODEV;
+ goto exit;
+ }
+
+ if (mimio->open++)
+ goto exit;
+
+ if (mimio->present && !mimio->greeted) {
+ struct urb *urb = mimio->in.urb;
+ mimio->in.urb->dev = mimio->udev;
+ rslt = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
+ if (rslt) {
+ dev_err(&idev->dev, "usb_submit_urb failure "
+ "(res = %d: %s). Not greeting.\n",
+ rslt,
+ (!urb ? "urb is NULL" :
+ (urb->hcpriv ? "urb->hcpriv is non-NULL" :
+ (!urb->complete ? "urb is not complete" :
+ (urb->number_of_packets <= 0 ? "urb has no packets" :
+ (urb->interval <= 0 ? "urb interval too small" :
+ "urb interval too large or some other error"))))));
+ rslt = -EIO;
+ goto exit;
+ }
+ rslt = mimio_greet(mimio);
+ if (rslt == 0) {
+ dev_dbg(&idev->dev, "Mimio greeted OK.\n");
+ mimio->greeted = 1;
+ } else {
+ dev_dbg(&idev->dev, "Mimio greet Failure (%d)\n",
+ rslt);
+ }
+ }
+
+exit:
+ up(&disconnect_sem);
+ return rslt;
+}
+
+static int mimio_probe(struct usb_interface *ifc,
+ const struct usb_device_id *id)
+{
+ char path[64];
+ int pipe, maxp;
+ struct mimio *mimio;
+ struct usb_device *udev;
+ struct usb_host_interface *hostifc;
+ struct input_dev *input_dev;
+ int res = 0;
+ int i;
+
+ udev = interface_to_usbdev(ifc);
+
+ mimio = kzalloc(sizeof(struct mimio), GFP_KERNEL);
+ if (!mimio)
+ return -ENOMEM;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ mimio_dealloc(mimio);
+ return -ENOMEM;
+ }
+
+ mimio->uifc = ifc;
+ mimio->udev = udev;
+ mimio->pktbuf.p = mimio->pktbuf.buf;
+ mimio->pktbuf.q = mimio->pktbuf.buf;
+ /* init_input_dev(mimio->idev); */
+ mimio->idev = input_dev;
+ init_waitqueue_head(&mimio->waitq);
+ spin_lock_init(&mimio->txlock);
+ hostifc = ifc->cur_altsetting;
+
+ if (hostifc->desc.bNumEndpoints != 2) {
+ dev_err(&udev->dev, "Unexpected endpoint count: %d.\n",
+ hostifc->desc.bNumEndpoints);
+ mimio_dealloc(mimio);
+ return -ENODEV;
+ }
+
+ mimio->in.desc = &(hostifc->endpoint[0].desc);
+ mimio->out.desc = &(hostifc->endpoint[1].desc);
+
+ mimio->in.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
+ &mimio->in.dma);
+ mimio->out.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
+ &mimio->out.dma);
+
+ if (mimio->in.buf == NULL || mimio->out.buf == NULL) {
+ dev_err(&udev->dev, "usb_buffer_alloc failure.\n");
+ mimio_dealloc(mimio);
+ return -ENOMEM;
+ }
+
+ mimio->in.urb = usb_alloc_urb(0, GFP_KERNEL);
+ mimio->out.urb = usb_alloc_urb(0, GFP_KERNEL);
+
+ if (mimio->in.urb == NULL || mimio->out.urb == NULL) {
+ dev_err(&udev->dev, "usb_alloc_urb failure.\n");
+ mimio_dealloc(mimio);
+ return -ENOMEM;
+ }
+
+ /*
+ * Build the input urb.
+ */
+ pipe = usb_rcvintpipe(udev, mimio->in.desc->bEndpointAddress);
+ maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+ if (maxp > MIMIO_MAXPAYLOAD)
+ maxp = MIMIO_MAXPAYLOAD;
+ usb_fill_int_urb(mimio->in.urb, udev, pipe, mimio->in.buf, maxp,
+ mimio_irq_in, mimio, mimio->in.desc->bInterval);
+ mimio->in.urb->transfer_dma = mimio->in.dma;
+ mimio->in.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /*
+ * Build the output urb.
+ */
+ pipe = usb_sndintpipe(udev, mimio->out.desc->bEndpointAddress);
+ maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+ if (maxp > MIMIO_MAXPAYLOAD)
+ maxp = MIMIO_MAXPAYLOAD;
+ usb_fill_int_urb(mimio->out.urb, udev, pipe, mimio->out.buf, maxp,
+ mimio_irq_out, mimio, mimio->out.desc->bInterval);
+ mimio->out.urb->transfer_dma = mimio->out.dma;
+ mimio->out.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /*
+ * Build input device info
+ */
+ usb_make_path(udev, path, 64);
+ snprintf(mimio->phys, MIMIO_MAXNAMELEN, "%s/input0", path);
+ input_set_drvdata(input_dev, mimio);
+ /* input_dev->dev = &ifc->dev; */
+ input_dev->open = mimio_open;
+ input_dev->close = mimio_close;
+ input_dev->name = mimio_name;
+ input_dev->phys = mimio->phys;
+ input_dev->dev.parent = &ifc->dev;
+
+ input_dev->id.bustype = BUS_USB;
+ input_dev->id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+ input_dev->id.product = le16_to_cpu(udev->descriptor.idProduct);
+ input_dev->id.version = le16_to_cpu(udev->descriptor.bcdDevice);
+
+ input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+ for (i = BTN_TOOL_PEN; i <= LOCALBTN_TOOL_EXTRA2; ++i)
+ set_bit(i, input_dev->keybit);
+
+ input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
+ BIT_MASK(BTN_1) |
+ BIT_MASK(BTN_2) |
+ BIT_MASK(BTN_3) |
+ BIT_MASK(BTN_4) |
+ BIT_MASK(BTN_5);
+ /* input_dev->keybit[BTN_MOUSE] |= BIT(BTN_LEFT); */
+ input_dev->absbit[0] |= BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
+ input_set_abs_params(input_dev, ABS_X, 0, MIMIO_XRANGE_MAX, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, MIMIO_YRANGE_MAX, 0, 0);
+ input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
+
+#if 0
+ input_dev->absmin[ABS_X] = 0;
+ input_dev->absmin[ABS_Y] = 0;
+ input_dev->absmax[ABS_X] = 9600;
+ input_dev->absmax[ABS_Y] = 4800;
+ input_dev->absfuzz[ABS_X] = 0;
+ input_dev->absfuzz[ABS_Y] = 0;
+ input_dev->absflat[ABS_X] = 0;
+ input_dev->absflat[ABS_Y] = 0;
+#endif
+
+#if 0
+ /* this will just reduce the precision */
+ input_dev->absfuzz[ABS_X] = 8; /* experimental; may need to change */
+ input_dev->absfuzz[ABS_Y] = 8; /* experimental; may need to change */
+#endif
+
+ /*
+ * Register the input device.
+ */
+ res = input_register_device(mimio->idev);
+ if (res) {
+ dev_err(&udev->dev, "input_register_device failure (%d)\n",
+ res);
+ mimio_dealloc(mimio);
+ return -EIO;
+ }
+ dev_dbg(&mimio->idev->dev, "input: %s on %s (res = %d).\n",
+ input_dev->name, input_dev->phys, res);
+
+ usb_set_intfdata(ifc, mimio);
+ mimio->present = 1;
+
+ /*
+ * Submit the input urb to the usb subsystem.
+ */
+ mimio->in.urb->dev = mimio->udev;
+ res = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
+ if (res) {
+ dev_err(&mimio->idev->dev, "usb_submit_urb failure (%d)\n",
+ res);
+ mimio_dealloc(mimio);
+ return -EIO;
+ }
+
+ /*
+ * Attempt to greet the mimio after giving
+ * it some post-init settling time.
+ *
+ * note: sometimes this sleep interval isn't
+ * long enough to permit the device to re-init
+ * after a hot-swap; maybe need to bump it up.
+ *
+ * As it is, this probably breaks module unloading support!
+ */
+ msleep(1024);
+
+ res = mimio_greet(mimio);
+ if (res == 0) {
+ dev_dbg(&mimio->idev->dev, "Mimio greeted OK.\n");
+ mimio->greeted = 1;
+ mimio->rxhandler = mimio_rx_handler;
+ } else {
+ dev_dbg(&mimio->idev->dev, "Mimio greet Failure (%d)\n", res);
+ }
+
+ return 0;
+}
+
+static int handle_mimio_rx_penupdown(struct mimio *mimio,
+ int down,
+ const char *const instr[],
+ const int instr_ofst[])
+{
+ int penid, x;
+ if (mimio->pktbuf.q - mimio->pktbuf.p < (down ? 4 : 3))
+ return 1; /* partial pkt */
+
+ if (down) {
+ x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
+ *(mimio->pktbuf.p + 2);
+ if (x != *(mimio->pktbuf.p + 3)) {
+ dev_dbg(&mimio->idev->dev, "EV_PEN%s: bad xsum.\n",
+ down ? "DOWN":"UP");
+ /* skip this event data */
+ mimio->pktbuf.p += 4;
+ /* decode any remaining events */
+ return 0;
+ }
+ penid = mimio->pktbuf.instr = *(mimio->pktbuf.p + 2);
+ if (penid > MIMIO_PEN_MAX) {
+ dev_dbg(&mimio->idev->dev,
+ "Unmapped penID (not in [0, %d]): %d\n",
+ MIMIO_PEN_MAX, (int)mimio->pktbuf.instr);
+ penid = mimio->pktbuf.instr = 0;
+ }
+ mimio->last_pen_down = penid;
+ } else {
+ penid = mimio->last_pen_down;
+ }
+ dev_dbg(&mimio->idev->dev, "%s (id %d, code %d) %s.\n", instr[penid],
+ instr_ofst[penid], penid, down ? "down" : "up");
+
+ if (instr_ofst[penid] >= 0) {
+ int code = BTN_TOOL_PEN + instr_ofst[penid];
+ int value = down ? DOWNVALUE : UPVALUE;
+ if (code > KEY_MAX)
+ dev_dbg(&mimio->idev->dev, "input_event will ignore "
+ "-- code (%d) > KEY_MAX\n", code);
+ if (!test_bit(code, mimio->idev->keybit))
+ dev_dbg(&mimio->idev->dev, "input_event will ignore "
+ "-- bit for code (%d) not enabled\n", code);
+ if (!!test_bit(code, mimio->idev->key) == value)
+ dev_dbg(&mimio->idev->dev, "input_event will ignore "
+ "-- bit for code (%d) already set to %d\n",
+ code, value);
+ if (value != DOWNVALUE) {
+ /* input_regs(mimio->idev, regs); */
+ input_report_key(mimio->idev, code, value);
+ input_sync(mimio->idev);
+ } else {
+ /* wait until we get some coordinates */
+ }
+ } else {
+ dev_dbg(&mimio->idev->dev, "penID offset[%d] == %d is < 0 "
+ "- not sending\n", penid, instr_ofst[penid]);
+ }
+ mimio->pktbuf.p += down ? 4 : 3; /* 3 for up, 4 for down */
+ return 0;
+}
+
+/*
+ * Stay tuned for partial-packet excitement.
+ *
+ * This routine buffers data packets received from the mimio device
+ * in the mimio's data space. This buffering is necessary because
+ * the mimio's in endpoint can serve us partial packets of data, and
+ * we want the driver to support the servicing of multiple mimios.
+ * Empirical evidence gathered so far suggests that the method of
+ * buffering packet data in the mimio's data space works. Previous
+ * versions of this driver did not buffer packet data in each mimio's
+ * data-space, and were therefore not able to service multiple mimios.
+ * Note that since the caller of this routine is running in interrupt
+ * context, care needs to be taken to ensure that this routine does not
+ * become bloated, and it may be that another spinlock is needed in each
+ * mimio to guard the buffered packet data properly.
+ */
+static void mimio_rx_handler(struct mimio *mimio,
+ unsigned char *data,
+ unsigned int nbytes)
+{
+ struct device *dev = &mimio->idev->dev;
+ unsigned int x;
+ unsigned int y;
+ static const char * const instr[] = {
+ "?0",
+ "black pen", "blue pen", "green pen", "red pen",
+ "brown pen", "orange pen", "purple pen", "yellow pen",
+ "big eraser", "lil eraser",
+ "?11", "?12", "?13", "?14", "?15", "?16",
+ "mimio interactive", "interactive button1",
+ "interactive button2"
+ };
+
+ /* Mimio Interactive gives:
+ * down: [0x22 0x01 0x11 0x32 0x24]
+ * b1 : [0x22 0x01 0x12 0x31 0x24]
+ * b2 : [0x22 0x01 0x13 0x30 0x24]
+ */
+ static const int instr_ofst[] = {
+ -1,
+ 0, 1, 2, 3,
+ 9, 9, 9, 9,
+ 4, 5,
+ -1, -1, -1, -1, -1, -1,
+ 6, 7, 8,
+ };
+
+ memcpy(mimio->pktbuf.q, data, nbytes);
+ mimio->pktbuf.q += nbytes;
+
+ while (mimio->pktbuf.p < mimio->pktbuf.q) {
+ int t = *mimio->pktbuf.p;
+ switch (t) {
+ case MIMIO_EV_PENUP:
+ case MIMIO_EV_PENDOWN:
+ if (handle_mimio_rx_penupdown(mimio,
+ t == MIMIO_EV_PENDOWN,
+ instr, instr_ofst))
+ return; /* partial packet */
+ break;
+
+ case MIMIO_EV_PENDATA:
+ if (mimio->pktbuf.q - mimio->pktbuf.p < 6)
+ /* partial pkt */
+ return;
+ x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
+ *(mimio->pktbuf.p + 2) ^
+ *(mimio->pktbuf.p + 3) ^
+ *(mimio->pktbuf.p + 4);
+ if (x != *(mimio->pktbuf.p + 5)) {
+ dev_dbg(dev, "EV_PENDATA: bad xsum.\n");
+ mimio->pktbuf.p += 6; /* skip this event data */
+ break; /* decode any remaining events */
+ }
+ x = *(mimio->pktbuf.p + 1);
+ x <<= 8;
+ x |= *(mimio->pktbuf.p + 2);
+ y = *(mimio->pktbuf.p + 3);
+ y <<= 8;
+ y |= *(mimio->pktbuf.p + 4);
+ dev_dbg(dev, "coord: (%d, %d)\n", x, y);
+ if (instr_ofst[mimio->pktbuf.instr] >= 0) {
+ int code = BTN_TOOL_PEN +
+ instr_ofst[mimio->last_pen_down];
+#if 0
+ /* Utter hack to ensure we get forwarded _AND_
+ * so we can identify when a complete signal is
+ * received */
+ mimio->idev->abs[ABS_Y] = -1;
+ mimio->idev->abs[ABS_X] = -1;
+#endif
+ /* input_regs(mimio->idev, regs); */
+ input_report_abs(mimio->idev, ABS_X, x);
+ input_report_abs(mimio->idev, ABS_Y, y);
+ /* fake a penup */
+ change_bit(code, mimio->idev->key);
+ input_report_key(mimio->idev,
+ code,
+ DOWNVALUE);
+ /* always sync here */
+ mimio->idev->sync = 0;
+ input_sync(mimio->idev);
+ }
+ mimio->pktbuf.p += 6;
+ break;
+ case MIMIO_EV_MEMRESET:
+ if (mimio->pktbuf.q - mimio->pktbuf.p < 7)
+ /* partial pkt */
+ return;
+ dev_dbg(dev, "mem-reset.\n");
+ /* input_regs(mimio->idev, regs); */
+ input_event(mimio->idev, EV_KEY, BTN_0, 1);
+ input_event(mimio->idev, EV_KEY, BTN_0, 0);
+ input_sync(mimio->idev);
+ mimio->pktbuf.p += 7;
+ break;
+ case MIMIO_EV_ACC:
+ if (mimio->pktbuf.q - mimio->pktbuf.p < 4)
+ /* partial pkt */
+ return;
+ x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
+ *(mimio->pktbuf.p + 2);
+ if (x != *(mimio->pktbuf.p + 3)) {
+ dev_dbg(dev, "EV_ACC: bad xsum.\n");
+ mimio->pktbuf.p += 4; /* skip this event data */
+ break; /* decode any remaining events */
+ }
+ switch (*(mimio->pktbuf.p + 2)) {
+ case ACC_NEWPAGE:
+ dev_dbg(&mimio->idev->dev, "new-page.\n");
+ /* input_regs(mimio->idev, regs); */
+ input_event(mimio->idev, EV_KEY, BTN_1, 1);
+ input_event(mimio->idev, EV_KEY, BTN_1, 0);
+ input_sync(mimio->idev);
+ break;
+ case ACC_TAGPAGE:
+ dev_dbg(&mimio->idev->dev, "tag-page.\n");
+ /* input_regs(mimio->idev, regs); */
+ input_event(mimio->idev, EV_KEY, BTN_2, 1);
+ input_event(mimio->idev, EV_KEY, BTN_2, 0);
+ input_sync(mimio->idev);
+ break;
+ case ACC_PRINTPAGE:
+ dev_dbg(&mimio->idev->dev, "print-page.\n");
+ /* input_regs(mimio->idev, regs);*/
+ input_event(mimio->idev, EV_KEY, BTN_3, 1);
+ input_event(mimio->idev, EV_KEY, BTN_3, 0);
+ input_sync(mimio->idev);
+ break;
+ case ACC_MAXIMIZE:
+ dev_dbg(&mimio->idev->dev,
+ "maximize-window.\n");
+ /* input_regs(mimio->idev, regs); */
+ input_event(mimio->idev, EV_KEY, BTN_4, 1);
+ input_event(mimio->idev, EV_KEY, BTN_4, 0);
+ input_sync(mimio->idev);
+ break;
+ case ACC_FINDCTLPNL:
+ dev_dbg(&mimio->idev->dev, "find-ctl-panel.\n");
+ /* input_regs(mimio->idev, regs); */
+ input_event(mimio->idev, EV_KEY, BTN_5, 1);
+ input_event(mimio->idev, EV_KEY, BTN_5, 0);
+ input_sync(mimio->idev);
+ break;
+ case ACC_DONE:
+ dev_dbg(&mimio->idev->dev, "acc-done.\n");
+ /* no event is dispatched to the input
+ * subsystem for this device event.
+ */
+ break;
+ default:
+ dev_dbg(dev, "unknown acc event.\n");
+ break;
+ }
+ mimio->pktbuf.p += 4;
+ break;
+ default:
+ mimio->pktbuf.p++;
+ break;
+ }
+ }
+
+ /*
+ * No partial event was received, so reset mimio's pktbuf ptrs.
+ */
+ mimio->pktbuf.p = mimio->pktbuf.q = mimio->pktbuf.buf;
+}
+
+static int mimio_tx(struct mimio *mimio, const char *buf, int nbytes)
+{
+ int rslt;
+ int timeout;
+ unsigned long flags;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (!(isvalidtxsize(nbytes))) {
+ dev_err(&mimio->idev->dev, "invalid arg: nbytes: %d.\n",
+ nbytes);
+ return -EINVAL;
+ }
+
+ /*
+ * Init the out urb and copy the data to send.
+ */
+ mimio->out.urb->dev = mimio->udev;
+ mimio->out.urb->transfer_buffer_length = nbytes;
+ memcpy(mimio->out.urb->transfer_buffer, buf, nbytes);
+
+ /*
+ * Send the data.
+ */
+ spin_lock_irqsave(&mimio->txlock, flags);
+ mimio->txflags = MIMIO_TXWAIT;
+ rslt = usb_submit_urb(mimio->out.urb, GFP_ATOMIC);
+ spin_unlock_irqrestore(&mimio->txlock, flags);
+ dev_dbg(&mimio->idev->dev, "rslt: %d.\n", rslt);
+
+ if (rslt) {
+ dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
+ rslt);
+ return rslt;
+ }
+
+ /*
+ * Wait for completion to be signalled (the mimio_irq_out
+ * completion routine will or MIMIO_TXDONE in with txflags).
+ */
+ timeout = HZ;
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&mimio->waitq, &wait);
+
+ while (timeout && ((mimio->txflags & MIMIO_TXDONE) == 0)) {
+ timeout = schedule_timeout(timeout);
+ rmb();
+ }
+
+ if ((mimio->txflags & MIMIO_TXDONE) == 0)
+ dev_dbg(&mimio->idev->dev, "tx timed out.\n");
+
+ /*
+ * Now that completion has been signalled,
+ * unlink the urb so that it can be recycled.
+ */
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&mimio->waitq, &wait);
+ usb_unlink_urb(mimio->out.urb);
+
+ return rslt;
+}
+
+static int __init mimio_init(void)
+{
+ int rslt;
+
+ rslt = usb_register(&mimio_driver);
+ if (rslt != 0) {
+ err("%s: usb_register failure: %d", __func__, rslt);
+ return rslt;
+ }
+
+ printk(KERN_INFO KBUILD_MODNAME ":"
+ DRIVER_DESC " " DRIVER_VERSION "\n");
+ return rslt;
+}
+
+static void __exit mimio_exit(void)
+{
+ usb_deregister(&mimio_driver);
+}
+
+module_init(mimio_init);
+module_exit(mimio_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/otus/80211core/amsdu.c b/drivers/staging/otus/80211core/amsdu.c
new file mode 100644
index 000000000000..c9123d58b82f
--- /dev/null
+++ b/drivers/staging/otus/80211core/amsdu.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfGetAmsduSubFrame */
+/* Get a subframe from a-MSDU. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : A-MSDU frame buffer */
+/* offset : offset of subframe in the A-MSDU */
+/* */
+/* OUTPUTS */
+/* NULL or subframe */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+zbuf_t* zfGetAmsduSubFrame(zdev_t* dev, zbuf_t* buf, u16_t* offset)
+{
+ u16_t subframeLen;
+ u16_t amsduLen = zfwBufGetSize(dev, buf);
+ zbuf_t* newBuf;
+
+ ZM_PERFORMANCE_RX_AMSDU(dev, buf, amsduLen);
+
+ /* Verify A-MSDU length */
+ if (amsduLen < (*offset + 14))
+ {
+ return NULL;
+ }
+
+ /* Locate A-MSDU subframe by offset and verify subframe length */
+ subframeLen = (zmw_buf_readb(dev, buf, *offset + 12) << 8) +
+ zmw_buf_readb(dev, buf, *offset + 13);
+ if (subframeLen == 0)
+ {
+ return NULL;
+ }
+
+ /* Verify A-MSDU subframe length */
+ if ((*offset+14+subframeLen) <= amsduLen)
+ {
+ /* Allocate a new buffer */
+ if ((newBuf = zfwBufAllocate(dev, 24+2+subframeLen)) != NULL)
+ {
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ /* Copy and convert subframe to wlan frame format */
+ /* SHALL NOT INCLUDE QOS and AMSDU header. Ray 20070807 For Vista */
+ zfRxBufferCopy(dev, newBuf, buf, 0, 0, 24);
+ zfRxBufferCopy(dev, newBuf, buf, 24, *offset+14, subframeLen);
+ zfwBufSetSize(dev, newBuf, 24+subframeLen);
+#else
+ /* Copy subframe to new buffer */
+ zfRxBufferCopy(dev, newBuf, buf, 0, *offset, 14+subframeLen);
+ zfwBufSetSize(dev, newBuf, 14+subframeLen);
+#endif
+ /* Update offset */
+ *offset += (((14+subframeLen)+3) & 0xfffc);
+
+ /* Return buffer pointer */
+ return newBuf;
+ }
+ }
+ return NULL;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfDeAmsdu */
+/* De-AMSDU. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : A-MSDU frame buffer */
+/* vap : VAP port */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+void zfDeAmsdu(zdev_t* dev, zbuf_t* buf, u16_t vap, u8_t encryMode)
+{
+ u16_t offset = ZM_SIZE_OF_WLAN_DATA_HEADER+ZM_SIZE_OF_QOS_CTRL;
+ zbuf_t* subframeBuf;
+ zmw_get_wlan_dev(dev);
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ if (encryMode == ZM_AES || encryMode == ZM_TKIP)
+ {
+ offset += (ZM_SIZE_OF_IV + ZM_SIZE_OF_EXT_IV);
+ }
+ else if (encryMode == ZM_WEP64 || encryMode == ZM_WEP128)
+ {
+ offset += ZM_SIZE_OF_IV;
+ }
+
+ /* Repeatly calling zfGetAmsduSubFrame() until NULL returned */
+ while ((subframeBuf = zfGetAmsduSubFrame(dev, buf, &offset)) != NULL)
+ {
+ wd->commTally.NotifyNDISRxFrmCnt++;
+ if (wd->zfcbRecvEth != NULL)
+ {
+ wd->zfcbRecvEth(dev, subframeBuf, (u8_t)vap);
+ ZM_PERFORMANCE_RX_MSDU(dev, wd->tick);
+ }
+ }
+ zfwBufFree(dev, buf, 0);
+
+ return;
+}
diff --git a/drivers/staging/otus/80211core/cagg.c b/drivers/staging/otus/80211core/cagg.c
new file mode 100644
index 000000000000..4942190747a1
--- /dev/null
+++ b/drivers/staging/otus/80211core/cagg.c
@@ -0,0 +1,3611 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : cagg.c */
+/* */
+/* Abstract */
+/* This module contains A-MPDU aggregation related functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+
+#include "cprecomp.h"
+
+extern u8_t zcUpToAc[8];
+const u8_t pri[] = {3,3,2,3,2,1,3,2,1,0};
+
+
+u16_t aggr_count;
+u32_t success_mpdu;
+u32_t total_mpdu;
+
+void zfAggInit(zdev_t* dev)
+{
+ u16_t i,j;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+ /*
+ * reset sta information
+ */
+
+ zmw_enter_critical_section(dev);
+ wd->aggInitiated = 0;
+ wd->addbaComplete = 0;
+ wd->addbaCount = 0;
+ wd->reorder = 1;
+ for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
+ {
+ for (j=0; j<ZM_AC; j++)
+ {
+ //wd->aggSta[i].aggQNumber[j] = ZM_AGG_POOL_SIZE;
+ wd->aggSta[i].aggFlag[j] = wd->aggSta[i].count[j] = 0;
+ wd->aggSta[i].tid_tx[j] = NULL;
+ wd->aggSta[i].tid_tx[j+1] = NULL;
+
+ }
+ }
+
+ /*
+ * reset Tx/Rx aggregation queue information
+ */
+ wd->aggState = 0;
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ /*
+ * reset tx aggregation queue
+ */
+ wd->aggQPool[i] = zfwMemAllocate(dev, sizeof(struct aggQueue));
+ if(!wd->aggQPool[i])
+ {
+ zmw_leave_critical_section(dev);
+ return;
+ }
+ wd->aggQPool[i]->aggHead = wd->aggQPool[i]->aggTail =
+ wd->aggQPool[i]->aggQEnabled = wd->aggQPool[i]->aggReady =
+ wd->aggQPool[i]->clearFlag = wd->aggQPool[i]->deleteFlag = 0;
+ //wd->aggQPool[i]->aggSize = 16;
+
+ /*
+ * reset rx aggregation queue
+ */
+ wd->tid_rx[i] = zfwMemAllocate(dev, sizeof(struct agg_tid_rx));
+ if (!wd->tid_rx[i])
+ {
+ zmw_leave_critical_section(dev);
+ return;
+ }
+ wd->tid_rx[i]->aid = ZM_MAX_STA_SUPPORT;
+ wd->tid_rx[i]->seq_start = wd->tid_rx[i]->baw_head = \
+ wd->tid_rx[i]->baw_tail = 0;
+ wd->tid_rx[i]->sq_exceed_count = wd->tid_rx[i]->sq_behind_count = 0;
+ for (j=0; j<=ZM_AGG_BAW_SIZE; j++)
+ wd->tid_rx[i]->frame[j].buf = 0;
+ /*
+ * reset ADDBA exchange status code
+ * 0: NULL
+ * 1: ADDBA Request sent/received
+ * 2: ACK for ADDBA Request sent/received
+ * 3: ADDBA Response sent/received
+ * 4: ACK for ADDBA Response sent/received
+ */
+ wd->tid_rx[i]->addBaExchangeStatusCode = 0;
+
+ }
+ zmw_leave_critical_section(dev);
+ zfAggTallyReset(dev);
+ DESTQ.init = zfAggDestInit;
+ DESTQ.init(dev);
+ wd->aggInitiated = 1;
+ aggr_count = 0;
+ success_mpdu = 0;
+ total_mpdu = 0;
+#ifdef ZM_ENABLE_AGGREGATION
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+ BAW = zfwMemAllocate(dev, sizeof(struct baw_enabler));
+ if(!BAW)
+ {
+ return;
+ }
+ BAW->init = zfBawInit;
+ BAW->init(dev);
+#endif //disable BAW
+#endif
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggGetSta */
+/* return STA AID. */
+/* take buf as input, use the dest address of buf as index to */
+/* search STA AID. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer for one particular packet */
+/* */
+/* OUTPUTS */
+/* AID */
+/* */
+/* AUTHOR */
+/* Honda ZyDAS Technology Corporation 2006.11 */
+/* */
+/************************************************************************/
+
+
+
+u16_t zfAggGetSta(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t id;
+ u16_t dst[3];
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ dst[0] = zmw_rx_buf_readh(dev, buf, 0);
+ dst[1] = zmw_rx_buf_readh(dev, buf, 2);
+ dst[2] = zmw_rx_buf_readh(dev, buf, 4);
+
+ zmw_enter_critical_section(dev);
+
+ if(wd->wlanMode == ZM_MODE_AP) {
+ id = zfApFindSta(dev, dst);
+ }
+ else {
+ id = 0;
+ }
+ zmw_leave_critical_section(dev);
+
+#if ZM_AGG_FPGA_DEBUG
+ id = 0;
+#endif
+
+ return id;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxGetQueue */
+/* return Queue Pool index. */
+/* take aid as input, look for the queue index associated */
+/* with this aid. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* aid : associated id */
+/* */
+/* OUTPUTS */
+/* Queue number */
+/* */
+/* AUTHOR */
+/* Honda ZyDAS Technology Corporation 2006.11 */
+/* */
+/************************************************************************/
+TID_TX zfAggTxGetQueue(zdev_t* dev, u16_t aid, u16_t tid)
+{
+ //u16_t i;
+ TID_TX tid_tx;
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ /*
+ * not a STA aid
+ */
+ if (0xffff == aid)
+ return NULL;
+
+ //zmw_enter_critical_section(dev);
+
+ tid_tx = wd->aggSta[aid].tid_tx[tid];
+ if (!tid_tx) return NULL;
+ if (0 == tid_tx->aggQEnabled)
+ return NULL;
+
+ //zmw_leave_critical_section(dev);
+
+ return tid_tx;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxNewQueue */
+/* return Queue Pool index. */
+/* take aid as input, find a new queue for this aid. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* aid : associated id */
+/* */
+/* OUTPUTS */
+/* Queue number */
+/* */
+/* AUTHOR */
+/* Honda ZyDAS Technology Corporation 2006.12 */
+/* */
+/************************************************************************/
+TID_TX zfAggTxNewQueue(zdev_t* dev, u16_t aid, u16_t tid, zbuf_t* buf)
+{
+ u16_t i;
+ TID_TX tid_tx=NULL;
+ u16_t ac = zcUpToAc[tid&0x7] & 0x3;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ /*
+ * not a STA aid
+ */
+ if (0xffff == aid)
+ return NULL;
+
+ zmw_enter_critical_section(dev);
+
+ /*
+ * find one new queue for sta
+ */
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ if (wd->aggQPool[i]->aggQEnabled)
+ {
+ /*
+ * this q is enabled
+ */
+ }
+ else
+ {
+ tid_tx = wd->aggQPool[i];
+ tid_tx->aggQEnabled = 1;
+ tid_tx->aggQSTA = aid;
+ tid_tx->ac = ac;
+ tid_tx->tid = tid;
+ tid_tx->aggHead = tid_tx->aggTail = tid_tx->size = 0;
+ tid_tx->aggReady = 0;
+ wd->aggSta[aid].tid_tx[tid] = tid_tx;
+ tid_tx->dst[0] = zmw_rx_buf_readh(dev, buf, 0);
+ tid_tx->dst[1] = zmw_rx_buf_readh(dev, buf, 2);
+ tid_tx->dst[2] = zmw_rx_buf_readh(dev, buf, 4);
+ break;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return tid_tx;
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxEnqueue */
+/* return Status code ZM_SUCCESS or error code */
+/* take (aid,ac,qnum,buf) as input */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* aid : associated id */
+/* ac : access category */
+/* qnum: the queue number to which will be enqueued */
+/* buf : the packet to be queued */
+/* */
+/* OUTPUTS */
+/* status code */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggTxEnqueue(zdev_t* dev, zbuf_t* buf, u16_t aid, TID_TX tid_tx)
+{
+ //u16_t qlen, frameLen;
+ u32_t time;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+
+ if (tid_tx->size < (ZM_AGGQ_SIZE - 2))
+ {
+ /* Queue not full */
+
+
+ /*
+ * buffer copy
+ * in zfwBufFree will return a ndismsendcomplete
+ * to resolve the synchronize problem in aggregate
+ */
+
+ u8_t sendComplete = 0;
+
+ tid_tx->aggvtxq[tid_tx->aggHead].buf = buf;
+ time = zm_agg_GetTime();
+ tid_tx->aggvtxq[tid_tx->aggHead].arrivalTime = time;
+ tid_tx->aggvtxq[tid_tx->aggHead].baw_retransmit = 0;
+
+ tid_tx->aggHead = ((tid_tx->aggHead + 1) & ZM_AGGQ_SIZE_MASK);
+ tid_tx->lastArrival = time;
+ tid_tx->size++;
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ if (buf && (tid_tx->size < (ZM_AGGQ_SIZE - 10))) {
+ tid_tx->complete = tid_tx->aggHead;
+ sendComplete = 1;
+ }
+ zmw_leave_critical_section(dev);
+
+ if (!DESTQ.exist(dev, 0, tid_tx->ac, tid_tx, NULL)) {
+ DESTQ.insert(dev, 0, tid_tx->ac, tid_tx, NULL);
+ }
+
+ zm_msg1_agg(ZM_LV_0, "tid_tx->size=", tid_tx->size);
+ //zm_debug_msg1("tid_tx->size=", tid_tx->size);
+
+ if (buf && sendComplete && wd->zfcbSendCompleteIndication) {
+ //zmw_leave_critical_section(dev);
+ wd->zfcbSendCompleteIndication(dev, buf);
+ }
+
+ /*if (tid_tx->size >= 16 && zfHpGetFreeTxdCount(dev) > 20)
+ zfAggTxSend(dev, zfHpGetFreeTxdCount(dev), tid_tx);
+ */
+ return ZM_SUCCESS;
+ }
+ else
+ {
+ zm_msg1_agg(ZM_LV_0, "can't enqueue, tid_tx->size=", tid_tx->size);
+ /*
+ * Queue Full
+ */
+
+ /*
+ * zm_msg1_agg(ZM_LV_0, "Queue full, qnum = ", qnum);
+ * wd->commTally.txQosDropCount[ac]++;
+ * zfwBufFree(dev, buf, ZM_SUCCESS);
+ * zm_msg1_agg(ZM_LV_1, "Packet discarded, VTXQ full, ac=", ac);
+ *
+ * return ZM_ERR_EXCEED_PRIORITY_THRESHOLD;
+ */
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (!DESTQ.exist(dev, 0, tid_tx->ac, tid_tx, NULL)) {
+ DESTQ.insert(dev, 0, tid_tx->ac, tid_tx, NULL);
+ }
+
+ return ZM_ERR_EXCEED_PRIORITY_THRESHOLD;
+}
+
+u16_t zfAggDestExist(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq) {
+ struct dest* dest;
+ u16_t exist = 0;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if (!DESTQ.Head[ac]) {
+ exist = 0;
+ }
+ else {
+ dest = DESTQ.Head[ac];
+ if (dest->tid_tx == tid_tx) {
+ exist = 1;
+ }
+ else {
+ while (dest->next != DESTQ.Head[ac]) {
+ dest = dest->next;
+ if (dest->tid_tx == tid_tx){
+ exist = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return exist;
+}
+
+void zfAggDestInsert(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq)
+{
+ struct dest* new_dest;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ new_dest = zfwMemAllocate(dev, sizeof(struct dest));
+ if(!new_dest)
+ {
+ return;
+ }
+ new_dest->Qtype = Qtype;
+ new_dest->tid_tx = tid_tx;
+ if (0 == Qtype)
+ new_dest->tid_tx = tid_tx;
+ else
+ new_dest->vtxq = vtxq;
+ if (!DESTQ.Head[ac]) {
+
+ zmw_enter_critical_section(dev);
+ new_dest->next = new_dest;
+ DESTQ.Head[ac] = DESTQ.dest[ac] = new_dest;
+ zmw_leave_critical_section(dev);
+ }
+ else {
+
+ zmw_enter_critical_section(dev);
+ new_dest->next = DESTQ.dest[ac]->next;
+ DESTQ.dest[ac]->next = new_dest;
+ zmw_leave_critical_section(dev);
+ }
+
+
+ //DESTQ.size[ac]++;
+ return;
+}
+
+void zfAggDestDelete(zdev_t* dev, u16_t Qtype, TID_TX tid_tx, void* vtxq)
+{
+ struct dest* dest, *temp;
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if (wd->destLock) {
+ zmw_leave_critical_section(dev);
+ return;
+ }
+
+
+ //zmw_declare_for_critical_section();
+ for (i=0; i<4; i++) {
+ if (!DESTQ.Head[i]) continue;
+ dest = DESTQ.Head[i];
+ if (!dest) continue;
+
+
+ while (dest && (dest->next != DESTQ.Head[i])) {
+ if (Qtype == 0 && dest->next->tid_tx == tid_tx){
+ break;
+ }
+ if (Qtype == 1 && dest->next->vtxq == vtxq) {
+ break;
+ }
+ dest = dest->next;
+ }
+
+ if ((Qtype == 0 && dest->next->tid_tx == tid_tx) || (Qtype == 1 && dest->next->vtxq == vtxq)) {
+
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ if (tid_tx->size) {
+ zmw_leave_critical_section(dev);
+ return;
+ }
+ if (!DESTQ.Head[i]) {
+ temp = NULL;
+ }
+ else {
+ temp = dest->next;
+ if (temp == dest) {
+ DESTQ.Head[i] = DESTQ.dest[i] = NULL;
+ //DESTQ.size[i] = 0;
+ }
+ else {
+ dest->next = dest->next->next;
+ }
+ }
+
+ if (temp == NULL)
+ {/* do nothing */} //zfwMemFree(dev, temp, sizeof(struct dest));
+ else
+ zfwMemFree(dev, temp, sizeof(struct dest));
+
+ /*zmw_enter_critical_section(dev);
+ if (DESTQ.size[i] > 0)
+ DESTQ.size[i]--;
+ zmw_leave_critical_section(dev);
+ */
+ }
+
+ }
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+void zfAggDestInit(zdev_t* dev)
+{
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ for (i=0; i<4; i++) {
+ //wd->destQ.Head[i].next = wd->destQ.Head[i];
+ //wd->destQ.dest[i] = wd->destQ.Head[i];
+ //DESTQ.size[i] = 0;
+ DESTQ.Head[i] = NULL;
+ }
+ DESTQ.insert = zfAggDestInsert;
+ DESTQ.delete = zfAggDestDelete;
+ DESTQ.init = zfAggDestInit;
+ DESTQ.getNext = zfAggDestGetNext;
+ DESTQ.exist = zfAggDestExist;
+ DESTQ.ppri = 0;
+ return;
+}
+
+struct dest* zfAggDestGetNext(zdev_t* dev, u16_t ac)
+{
+ struct dest *dest = NULL;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if (DESTQ.dest[ac]) {
+ dest = DESTQ.dest[ac];
+ DESTQ.dest[ac] = DESTQ.dest[ac]->next;
+ }
+ else {
+ dest = NULL;
+ }
+ zmw_leave_critical_section(dev);
+
+ return dest;
+}
+
+#ifdef ZM_ENABLE_AGGREGATION
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+u16_t zfAggTidTxInsertHead(zdev_t* dev, struct bufInfo *buf_info,TID_TX tid_tx)
+{
+ zbuf_t* buf;
+ u32_t time;
+ struct baw_header *baw_header;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+
+ buf = buf_info->buf;
+
+ zmw_enter_critical_section(dev);
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ zmw_leave_critical_section(dev);
+
+ if (tid_tx->size >= (ZM_AGGQ_SIZE - 2)) {
+ zfwBufFree(dev, buf, ZM_SUCCESS);
+ return 0;
+ }
+
+ zmw_enter_critical_section(dev);
+ tid_tx->aggTail = (tid_tx->aggTail == 0)? ZM_AGGQ_SIZE_MASK: tid_tx->aggTail - 1;
+ tid_tx->aggvtxq[tid_tx->aggTail].buf = buf;
+ //time = zm_agg_GetTime();
+ tid_tx->aggvtxq[tid_tx->aggTail].arrivalTime = buf_info->timestamp;
+ tid_tx->aggvtxq[tid_tx->aggTail].baw_retransmit = buf_info->baw_retransmit;
+
+ baw_header = &tid_tx->aggvtxq[tid_tx->aggTail].baw_header;
+ baw_header->headerLen = buf_info->baw_header->headerLen;
+ baw_header->micLen = buf_info->baw_header->micLen;
+ baw_header->snapLen = buf_info->baw_header->snapLen;
+ baw_header->removeLen = buf_info->baw_header->removeLen;
+ baw_header->keyIdx = buf_info->baw_header->keyIdx;
+ zfwMemoryCopy((u8_t *)baw_header->header, (u8_t *)buf_info->baw_header->header, 58);
+ zfwMemoryCopy((u8_t *)baw_header->mic , (u8_t *)buf_info->baw_header->mic , 8);
+ zfwMemoryCopy((u8_t *)baw_header->snap , (u8_t *)buf_info->baw_header->snap , 8);
+
+ tid_tx->size++;
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ zmw_leave_critical_section(dev);
+
+ //tid_tx->lastArrival = time;
+ if (1 == tid_tx->size) {
+ DESTQ.insert(dev, 0, tid_tx->ac, tid_tx, NULL);
+ }
+
+
+ zm_msg1_agg(ZM_LV_0, "0xC2:insertHead, tid_tx->size=", tid_tx->size);
+
+ return TRUE;
+}
+#endif //disable BAW
+#endif
+
+void zfiTxComplete(zdev_t* dev)
+{
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ if( (wd->wlanMode == ZM_MODE_AP) ||
+ (wd->wlanMode == ZM_MODE_INFRASTRUCTURE && wd->sta.EnableHT) ||
+ (wd->wlanMode == ZM_MODE_PSEUDO) ) {
+ zfAggTxScheduler(dev, 0);
+ }
+
+ return;
+}
+
+TID_TX zfAggTxReady(zdev_t* dev) {
+ //struct dest* dest;
+ u16_t i;
+ TID_TX tid_tx = NULL;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ if (wd->aggQPool[i]->aggQEnabled)
+ {
+ if (wd->aggQPool[i]->size >= 16) {
+ tid_tx = wd->aggQPool[i];
+ break;
+ }
+ }
+ else {
+ }
+ }
+ zmw_leave_critical_section(dev);
+ return tid_tx;
+}
+
+u16_t zfAggValidTidTx(zdev_t* dev, TID_TX tid_tx) {
+ u16_t i, valid = 0;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ if (wd->aggQPool[i] == tid_tx)
+ {
+ valid = 1;
+ break;
+ }
+ else {
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+ return valid;
+}
+
+void zfAggTxScheduler(zdev_t* dev, u8_t ScanAndClear)
+{
+ TID_TX tid_tx = NULL;
+ void* vtxq;
+ struct dest* dest;
+ zbuf_t* buf;
+ u32_t txql, min_txql;
+ //u16_t aggr_size = 1;
+ u16_t txq_threshold;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if (!wd->aggInitiated)
+ {
+ return;
+ }
+
+ /* debug */
+ txql = TXQL;
+ min_txql = AGG_MIN_TXQL;
+
+ if(wd->txq_threshold)
+ txq_threshold = wd->txq_threshold;
+ else
+ txq_threshold = AGG_MIN_TXQL;
+
+ tid_tx = zfAggTxReady(dev);
+ if (tid_tx) ScanAndClear = 0;
+ while (zfHpGetFreeTxdCount(dev) > 20 && (TXQL < txq_threshold || tid_tx)) {
+ //while (zfHpGetFreeTxdCount(dev) > 20 && (ScanAndClear || tid_tx)) {
+ //while (TXQL < txq_threshold) {
+ u16_t i;
+ u8_t ac;
+ s8_t destQ_count = 0;
+ //while ((zfHpGetFreeTxdCount(dev)) > 32) {
+
+ //DbgPrint("zfAggTxScheduler: in while loop");
+ for (i=0; i<4; i++) {
+ if (DESTQ.Head[i]) destQ_count++;
+ }
+ if (0 >= destQ_count) break;
+
+ zmw_enter_critical_section(dev);
+ ac = pri[DESTQ.ppri]; DESTQ.ppri = (DESTQ.ppri + 1) % 10;
+ zmw_leave_critical_section(dev);
+
+ for (i=0; i<10; i++){
+ if(DESTQ.Head[ac]) break;
+
+ zmw_enter_critical_section(dev);
+ ac = pri[DESTQ.ppri]; DESTQ.ppri = (DESTQ.ppri + 1) % 10;
+ zmw_leave_critical_section(dev);
+ }
+ if (i == 10) break;
+ //DbgPrint("zfAggTxScheduler: have dest Q");
+ zmw_enter_critical_section(dev);
+ wd->destLock = 1;
+ zmw_leave_critical_section(dev);
+
+ dest = DESTQ.getNext(dev, ac);
+ if (!dest) {
+ zmw_enter_critical_section(dev);
+ wd->destLock = 0;
+ zmw_leave_critical_section(dev);
+
+ DbgPrint("bug report! DESTQ.getNext got nothing!");
+ break;
+ }
+ if (dest->Qtype == 0) {
+ tid_tx = dest->tid_tx;
+
+ //DbgPrint("zfAggTxScheduler: have tid_tx Q");
+
+ if(tid_tx && zfAggValidTidTx(dev, tid_tx))
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ else {
+ zmw_enter_critical_section(dev);
+ wd->destLock = 0;
+ zmw_leave_critical_section(dev);
+
+ tid_tx = zfAggTxReady(dev);
+ continue;
+ }
+
+ zmw_enter_critical_section(dev);
+ wd->destLock = 0;
+ zmw_leave_critical_section(dev);
+ //zmw_enter_critical_section(dev);
+ if (tid_tx && !tid_tx->size) {
+
+ //zmw_leave_critical_section(dev);
+ //DESTQ.delete(dev, 0, tid_tx, NULL);
+ }
+ else if(wd->aggState == 0){
+ //wd->aggState = 1;
+ //zmw_leave_critical_section(dev);
+ zfAggTxSend(dev, zfHpGetFreeTxdCount(dev), tid_tx);
+ //wd->aggState = 0;
+ }
+ else {
+ //zmw_leave_critical_section(dev);
+ break;
+ }
+ }
+ else {
+ vtxq = dest->vtxq;
+ buf = zfGetVtxq(dev, ac);
+ zm_assert( buf != 0 );
+
+ zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+
+ }
+ /*flush all but < 16 frames in tid_tx to TXQ*/
+ tid_tx = zfAggTxReady(dev);
+ }
+
+ /*while ((zfHpGetFreeTxdCount(dev)) > 32) {
+ //while ((zfHpGetFreeTxdCount(dev)) > 32) {
+
+ destQ_count = 0;
+ for (i=0; i<4; i++) destQ_count += wd->destQ.size[i];
+ if (0 >= destQ_count) break;
+
+ ac = pri[wd->destQ.ppri]; wd->destQ.ppri = (wd->destQ.ppri + 1) % 10;
+ for (i=0; i<10; i++){
+ if(wd->destQ.size[ac]!=0) break;
+ ac = pri[wd->destQ.ppri]; wd->destQ.ppri = (wd->destQ.ppri + 1) % 10;
+ }
+ if (i == 10) break;
+ dest = wd->destQ.getNext(dev, ac);
+ if (dest->Qtype == 0) {
+ tid_tx = dest->tid_tx;
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ if (!tid_tx->size) {
+ wd->destQ.delete(dev, 0, tid_tx, NULL);
+ break;
+ }
+ else if((wd->aggState == 0) && (tid_tx->size >= 16)){
+ zfAggTxSend(dev, zfHpGetFreeTxdCount(dev), tid_tx);
+ }
+ else {
+ break;
+ }
+ }
+
+ }
+ */
+ return;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTx */
+/* return Status code ZM_SUCCESS or error code */
+/* management A-MPDU aggregation function, */
+/* management aggregation queue, calculate arrivalrate, */
+/* add/delete an aggregation queue of a stream, */
+/* enqueue packets into responsible aggregate queue. */
+/* take (dev, buf, ac) as input */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : packet buff */
+/* ac : access category */
+/* */
+/* OUTPUTS */
+/* status code */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggTx(zdev_t* dev, zbuf_t* buf, u16_t tid)
+{
+ u16_t aid;
+ //u16_t qnum;
+ //u16_t aggflag = 0;
+ //u16_t arrivalrate = 0;
+ TID_TX tid_tx;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if(!wd->aggInitiated)
+ {
+ return ZM_ERR_TX_BUFFER_UNAVAILABLE;
+ }
+
+ aid = zfAggGetSta(dev, buf);
+
+ //arrivalrate = zfAggTxArrivalRate(dev, aid, tid);
+
+ if (0xffff == aid)
+ {
+ /*
+ * STA not associated, this is a BC/MC or STA->AP packet
+ */
+
+ return ZM_ERR_TX_BUFFER_UNAVAILABLE;
+ }
+
+ /*
+ * STA associated, a unicast packet
+ */
+
+ tid_tx = zfAggTxGetQueue(dev, aid, tid);
+
+ /*tid_q.tid_tx = tid_tx;
+ wd->destQ.insert = zfAggDestInsert;
+ wd->destQ.insert(dev, 0, tid_q);
+ */
+ if (tid_tx != NULL)
+ {
+ /*
+ * this (aid, ac) is aggregated
+ */
+
+ //if (arrivalrate < ZM_AGG_LOW_THRESHOLD)
+ if (0)
+ {
+ /*
+ * arrival rate too low
+ * delete this aggregate queue
+ */
+
+ zmw_enter_critical_section(dev);
+
+ //wd->aggQPool[qnum]->clearFlag = wd->aggQPool[qnum]->deleteFlag =1;
+
+ zmw_leave_critical_section(dev);
+
+ }
+
+ return zfAggTxEnqueue(dev, buf, aid, tid_tx);
+
+ }
+ else
+ {
+ /*
+ * this (aid, ac) not yet aggregated
+ * queue not found
+ */
+
+ //if (arrivalrate > ZM_AGG_HIGH_THRESHOLD)
+ if (1)
+ {
+ /*
+ * arrivalrate high enough to get a new agg queue
+ */
+
+ tid_tx = zfAggTxNewQueue(dev, aid, tid, buf);
+
+ //zm_msg1_agg(ZM_LV_0, "get new AggQueue qnum = ", tid_tx->);
+
+ if (tid_tx)
+ {
+ /*
+ * got a new aggregate queue
+ */
+
+ //zmw_enter_critical_section(dev);
+
+ //wd->aggSta[aid].aggFlag[ac] = 1;
+
+ //zmw_leave_critical_section(dev);
+
+ /*
+ * add ADDBA functions here
+ * return ZM_ERR_TX_BUFFER_UNAVAILABLE;
+ */
+
+
+ //zfAggSendAddbaRequest(dev, tid_tx->dst, tid_tx->ac, tid_tx->tid);
+ //zmw_enter_critical_section(dev);
+
+ //wd->aggSta[aid].aggFlag[ac] = 0;
+
+ //zmw_leave_critical_section(dev);
+
+ return zfAggTxEnqueue(dev, buf, aid, tid_tx);
+
+ }
+ else
+ {
+ /*
+ * just can't get a new aggregate queue
+ */
+
+ return ZM_ERR_TX_BUFFER_UNAVAILABLE;
+ }
+ }
+ else
+ {
+ /*
+ * arrival rate is not high enough to get a new agg queue
+ */
+
+ return ZM_ERR_TX_BUFFER_UNAVAILABLE;
+ }
+ }
+
+
+
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxReadyCount */
+/* return counter of ready to aggregate queues. */
+/* take (dev, ac) as input, only calculate the ready to aggregate */
+/* queues of one particular ac. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* ac : access category */
+/* */
+/* OUTPUTS */
+/* counter of ready to aggregate queues */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggTxReadyCount(zdev_t* dev, u16_t ac)
+{
+ u16_t i;
+ u16_t readycount = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ for (i=0 ; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ if (wd->aggQPool[i]->aggQEnabled && (wd->aggQPool[i]->aggReady || \
+ wd->aggQPool[i]->clearFlag) && ac == wd->aggQPool[i]->ac)
+ readycount++;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return readycount;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxPartial */
+/* return the number that Vtxq has to send. */
+/* take (dev, ac, readycount) as input, calculate the ratio of */
+/* Vtxq length to (Vtxq length + readycount) of a particular ac, */
+/* and returns the Vtxq length * the ratio */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* ac : access category */
+/* readycount: the number of ready to aggregate queues of this ac */
+/* */
+/* OUTPUTS */
+/* Vtxq length * ratio */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggTxPartial(zdev_t* dev, u16_t ac, u16_t readycount)
+{
+ u16_t qlen;
+ u16_t partial;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ qlen = zm_agg_qlen(dev, wd->vtxqHead[ac], wd->vtxqTail[ac]);
+
+ if ((qlen + readycount) > 0)
+ {
+ partial = (u16_t)( zm_agg_weight(ac) * ((u16_t)qlen/(qlen + \
+ readycount)) );
+ }
+ else
+ {
+ partial = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (partial > qlen)
+ partial = qlen;
+
+ return partial;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxSend */
+/* return sentcount */
+/* take (dev, ac, n) as input, n is the number of scheduled agg */
+/* queues to be sent of the particular ac. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* ac : access category */
+/* n : the number of scheduled aggregation queues to be sent */
+/* */
+/* OUTPUTS */
+/* sentcount */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggTxSend(zdev_t* dev, u32_t freeTxd, TID_TX tid_tx)
+{
+ //u16_t qnum;
+ //u16_t qlen;
+ u16_t j;
+ //u16_t sentcount = 0;
+ zbuf_t* buf;
+ struct aggControl aggControl;
+ u16_t aggLen;
+ //zbuf_t* newBuf;
+ //u16_t bufLen;
+ //TID_BAW tid_baw = NULL;
+ //struct bufInfo *buf_info;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ //while (tid_tx->size > 0)
+
+ zmw_enter_critical_section(dev);
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ aggLen = zm_agg_min(16, zm_agg_min(tid_tx->size, (u16_t)(freeTxd - 2)));
+ zmw_leave_critical_section(dev);
+
+ /*
+ * why there have to be 2 free Txd?
+ */
+ if (aggLen <=0 )
+ return 0;
+
+
+ if (aggLen == 1) {
+ buf = zfAggTxGetVtxq(dev, tid_tx);
+ if (buf)
+ zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ if (tid_tx->size == 0) {
+ //DESTQ.delete(dev, 0, tid_tx, NULL);
+ }
+
+ return 1;
+ }
+ /*
+ * Free Txd queue is big enough to put aggregation
+ */
+ zmw_enter_critical_section(dev);
+ if (wd->aggState == 1) {
+ zmw_leave_critical_section(dev);
+ return 0;
+ }
+ wd->aggState = 1;
+ zmw_leave_critical_section(dev);
+
+
+ zm_msg1_agg(ZM_LV_0, "aggLen=", aggLen);
+ tid_tx->aggFrameSize = 0;
+ for (j=0; j < aggLen; j++) {
+ buf = zfAggTxGetVtxq(dev, tid_tx);
+
+ zmw_enter_critical_section(dev);
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ zmw_leave_critical_section(dev);
+
+ if ( buf ) {
+ //struct aggTally *agg_tal;
+ u16_t completeIndex;
+
+ if (0 == j) {
+ aggControl.ampduIndication = ZM_AGG_FIRST_MPDU;
+
+ }
+ else if ((j == (aggLen - 1)) || tid_tx->size == 0)
+ {
+ aggControl.ampduIndication = ZM_AGG_LAST_MPDU;
+ //wd->aggState = 0;
+
+ }
+ else
+ {
+ aggControl.ampduIndication = ZM_AGG_MIDDLE_MPDU;
+ /* the packet is delayed more than 500 ms, drop it */
+
+ }
+ tid_tx->aggFrameSize += zfwBufGetSize(dev, buf);
+ aggControl.addbaIndication = 0;
+ aggControl.aggEnabled = 1;
+
+#ifdef ZM_AGG_TALLY
+ agg_tal = &wd->agg_tal;
+ agg_tal->sent_packets_sum++;
+
+#endif
+
+ zfAggTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0, &aggControl, tid_tx);
+
+ zmw_enter_critical_section(dev);
+ completeIndex = tid_tx->complete;
+ if(zm_agg_inQ(tid_tx, tid_tx->complete))
+ zm_agg_plus(tid_tx->complete);
+ zmw_leave_critical_section(dev);
+
+ if(zm_agg_inQ(tid_tx, completeIndex) && wd->zfcbSendCompleteIndication
+ && tid_tx->aggvtxq[completeIndex].buf) {
+ wd->zfcbSendCompleteIndication(dev, tid_tx->aggvtxq[completeIndex].buf);
+ zm_debug_msg0("in queue complete worked!");
+ }
+
+ }
+ else {
+ /*
+ * this aggregation queue is empty
+ */
+ zm_msg1_agg(ZM_LV_0, "aggLen not reached, but no more frame, j=", j);
+
+ break;
+ }
+ }
+ zmw_enter_critical_section(dev);
+ wd->aggState = 0;
+ zmw_leave_critical_section(dev);
+
+ //zm_acquire_agg_spin_lock(Adapter);
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ //zm_release_agg_spin_lock(Adapter);
+
+ if (tid_tx->size == 0) {
+ //DESTQ.delete(dev, 0, tid_tx, NULL);
+ }
+
+
+
+ //zfAggInvokeBar(dev, tid_tx);
+ if(j>0) {
+ aggr_count++;
+ zm_msg1_agg(ZM_LV_0, "0xC2:sent 1 aggr, aggr_count=", aggr_count);
+ zm_msg1_agg(ZM_LV_0, "0xC2:sent 1 aggr, aggr_size=", j);
+ }
+ return j;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxGetReadyQueue */
+/* return the number of the aggregation queue */
+/* take (dev, ac) as input, find the agg queue with smallest */
+/* arrival time (waited longest) among those ready or clearFlag */
+/* set queues. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* ac : access category */
+/* */
+/* OUTPUTS */
+/* aggregation queue number */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+TID_TX zfAggTxGetReadyQueue(zdev_t* dev, u16_t ac)
+{
+ //u16_t qnum = ZM_AGG_POOL_SIZE;
+ u16_t i;
+ u32_t time = 0;
+ TID_TX tid_tx = NULL;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ for (i=0 ;i<ZM_AGG_POOL_SIZE; i++)
+ {
+ if (1 == wd->aggQPool[i]->aggQEnabled && ac == wd->aggQPool[i]->ac &&
+ (wd->aggQPool[i]->size > 0))
+ {
+ if (0 == time || time > wd->aggQPool[i]->aggvtxq[ \
+ wd->aggQPool[i]->aggHead ].arrivalTime)
+ {
+ tid_tx = wd->aggQPool[i];
+ time = tid_tx->aggvtxq[ tid_tx->aggHead ].arrivalTime;
+ }
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return tid_tx;
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxGetVtxq */
+/* return an MSDU */
+/* take (dev, qnum) as input, return an MSDU out of the agg queue. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* qnum: queue number */
+/* */
+/* OUTPUTS */
+/* a MSDU */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+zbuf_t* zfAggTxGetVtxq(zdev_t* dev, TID_TX tid_tx)
+{
+ zbuf_t* buf = NULL;
+
+ zmw_declare_for_critical_section();
+
+ if (tid_tx->aggHead != tid_tx->aggTail)
+ {
+ buf = tid_tx->aggvtxq[ tid_tx->aggTail ].buf;
+
+ tid_tx->aggvtxq[tid_tx->aggTail].buf = NULL;
+
+ zmw_enter_critical_section(dev);
+ tid_tx->aggTail = ((tid_tx->aggTail + 1) & ZM_AGGQ_SIZE_MASK);
+ if(tid_tx->size > 0) tid_tx->size--;
+ tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail);
+ if (NULL == buf) {
+ //tid_tx->aggTail = tid_tx->aggHead = tid_tx->size = 0;
+ //zm_msg1_agg(ZM_LV_0, "GetVtxq buf == NULL, tid_tx->size=", tid_tx->size);
+ }
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ /*
+ * queue is empty
+ */
+ zm_msg1_agg(ZM_LV_0, "tid_tx->aggHead == tid_tx->aggTail, tid_tx->size=", tid_tx->size);
+
+ }
+
+ if (zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail) != tid_tx->size)
+ zm_msg1_agg(ZM_LV_0, "qlen!=tid_tx->size! tid_tx->size=", tid_tx->size);
+ return buf;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxDeleteQueue */
+/* return ZM_SUCCESS (can't fail) */
+/* take (dev, qnum) as input, reset (delete) this aggregate queue, */
+/* this queue is virtually returned to the aggregate queue pool. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* qnum: queue number */
+/* */
+/* OUTPUTS */
+/* ZM_SUCCESS */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggTxDeleteQueue(zdev_t* dev, u16_t qnum)
+{
+ u16_t ac, tid;
+ struct aggQueue *tx_tid;
+ struct aggSta *agg_sta;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ tx_tid = wd->aggQPool[qnum];
+ agg_sta = &wd->aggSta[tx_tid->aggQSTA];
+ ac = tx_tid->ac;
+ tid = tx_tid->tid;
+
+ zmw_enter_critical_section(dev);
+
+ tx_tid->aggQEnabled = 0;
+ tx_tid->aggHead = tx_tid->aggTail = 0;
+ tx_tid->aggReady = 0;
+ tx_tid->clearFlag = tx_tid->deleteFlag = 0;
+ tx_tid->size = 0;
+ agg_sta->count[ac] = 0;
+
+ agg_sta->tid_tx[tid] = NULL;
+ agg_sta->aggFlag[ac] = 0;
+
+ zmw_leave_critical_section(dev);
+
+ zm_msg1_agg(ZM_LV_0, "queue deleted! qnum=", qnum);
+
+ return ZM_SUCCESS;
+}
+
+#ifdef ZM_ENABLE_AGGREGATION
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+void zfBawCore(zdev_t* dev, u16_t baw_seq, u32_t bitmap, u16_t aggLen) {
+ TID_BAW tid_baw;
+ s16_t i;
+ zbuf_t* buf;
+ struct bufInfo *buf_info;
+
+ zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+ tid_baw = BAW->getQ(dev, baw_seq);
+ //tid_baw = NULL;
+ if (NULL == tid_baw)
+ return;
+
+ total_mpdu += aggLen;
+ for (i = aggLen - 1; i>=0; i--) {
+ if (((bitmap >> i) & 0x1) == 0) {
+ buf_info = BAW->pop(dev, i, tid_baw);
+ buf = buf_info->buf;
+ if (buf) {
+ //wd->zfcbSetBawQ(dev, buf, 0);
+ zfAggTidTxInsertHead(dev, buf_info, tid_baw->tid_tx);
+ }
+ }
+ else {
+ success_mpdu++;
+ }
+ }
+ BAW->disable(dev, tid_baw);
+ zfAggTxScheduler(dev);
+ zm_debug_msg1("success_mpdu = ", success_mpdu);
+ zm_debug_msg1(" total_mpdu = ", total_mpdu);
+}
+
+void zfBawInit(zdev_t* dev) {
+ TID_BAW tid_baw;
+ u16_t i,j;
+ zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+
+ for (i=0; i<ZM_BAW_POOL_SIZE; i++){
+ tid_baw = &BAW->tid_baw[i];
+ for (j=0; j<ZM_VTXQ_SIZE; j++) {
+ tid_baw->frame[j].buf = NULL;
+ }
+ tid_baw->enabled = tid_baw->head = tid_baw->tail = tid_baw->size = 0;
+ tid_baw->start_seq = 0;
+ }
+ BAW->delPoint = 0;
+ BAW->core = zfBawCore;
+ BAW->getNewQ = zfBawGetNewQ;
+ BAW->insert = zfBawInsert;
+ BAW->pop = zfBawPop;
+ BAW->enable = zfBawEnable;
+ BAW->disable = zfBawDisable;
+ BAW->getQ = zfBawGetQ;
+}
+
+
+
+TID_BAW zfBawGetNewQ(zdev_t* dev, u16_t start_seq, TID_TX tid_tx) {
+ TID_BAW tid_baw=NULL;
+ TID_BAW next_baw=NULL;
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+
+ /*
+ for (i=0; i<ZM_BAW_POOL_SIZE; i++){
+ tid_baw = &BAW->tid_baw[i];
+ if (FALSE == tid_baw->enabled)
+ break;
+ }
+ */
+
+ tid_baw = &BAW->tid_baw[BAW->delPoint];
+ i = BAW->delPoint;
+ //if (ZM_BAW_POOL_SIZE == i) {
+ //return NULL;
+ // u8_t temp = BAW->delPoint;
+ // tid_baw = &BAW->tid_baw[BAW->delPoint];
+ // BAW->disable(dev, tid_baw);
+ // BAW->delPoint = (BAW->delPoint < (ZM_BAW_POOL_SIZE - 1))? (BAW->delPoint + 1): 0;
+ // temp = BAW->delPoint;
+ //}
+
+ zm_msg1_agg(ZM_LV_0, "get new tid_baw, index=", i);
+ BAW->delPoint = (i < (ZM_BAW_POOL_SIZE -1))? (i + 1): 0;
+ next_baw = &BAW->tid_baw[BAW->delPoint];
+ if (1 == next_baw->enabled) BAW->disable(dev, next_baw);
+
+ BAW->enable(dev, tid_baw, start_seq);
+ tid_baw->tid_tx = tid_tx;
+
+ return tid_baw;
+}
+
+u16_t zfBawInsert(zdev_t* dev, zbuf_t* buf, u16_t baw_seq, TID_BAW tid_baw, u8_t baw_retransmit, struct baw_header_r *header_r) {
+ //TID_BAW tid_baw;
+ //u16_t bufLen;
+
+ //zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+
+ if(tid_baw->size < (ZM_VTXQ_SIZE - 1)) {
+ struct baw_header *baw_header = &tid_baw->frame[tid_baw->head].baw_header;
+
+ baw_header->headerLen = header_r->headerLen;
+ baw_header->micLen = header_r->micLen;
+ baw_header->snapLen = header_r->snapLen;
+ baw_header->removeLen = header_r->removeLen;
+ baw_header->keyIdx = header_r->keyIdx;
+ zfwMemoryCopy((u8_t *)baw_header->header, (u8_t *)header_r->header, 58);
+ zfwMemoryCopy((u8_t *)baw_header->mic , (u8_t *)header_r->mic , 8);
+ zfwMemoryCopy((u8_t *)baw_header->snap , (u8_t *)header_r->snap , 8);
+ //wd->zfcbSetBawQ(dev, buf, 1);
+ tid_baw->frame[tid_baw->head].buf = buf;
+ tid_baw->frame[tid_baw->head].baw_seq = baw_seq;
+ tid_baw->frame[tid_baw->head].baw_retransmit = baw_retransmit + 1;
+
+ //tid_baw->frame[tid_baw->head].data = pBuf->data;
+ tid_baw->head++;
+ tid_baw->size++;
+ }
+ else {
+ //wd->zfcbSetBawQ(dev, buf, 0);
+ zfwBufFree(dev, buf, ZM_SUCCESS);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+struct bufInfo* zfBawPop(zdev_t* dev, u16_t index, TID_BAW tid_baw) {
+ //TID_BAW tid_baw;
+ //zbuf_t* buf;
+ struct bufInfo *buf_info;
+ zmw_get_wlan_dev(dev);
+
+ buf_info = &wd->buf_info;
+ buf_info->baw_header = NULL;
+
+ if (NULL == (buf_info->buf = tid_baw->frame[index].buf))
+ return buf_info;
+
+ buf_info->baw_retransmit = tid_baw->frame[index].baw_retransmit;
+ buf_info->baw_header = &tid_baw->frame[index].baw_header;
+ buf_info->timestamp = tid_baw->frame[index].timestamp;
+ //pBuf->data = pBuf->buffer;
+ //wd->zfcbRestoreBufData(dev, buf);
+ tid_baw->frame[index].buf = NULL;
+
+ return buf_info;
+}
+
+void zfBawEnable(zdev_t* dev, TID_BAW tid_baw, u16_t start_seq) {
+ //TID_BAW tid_baw;
+
+ //zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+
+ tid_baw->enabled = TRUE;
+ tid_baw->head = tid_baw->tail = tid_baw->size = 0;
+ tid_baw->start_seq = start_seq;
+}
+
+void zfBawDisable(zdev_t* dev, TID_BAW tid_baw) {
+ //TID_BAW tid_baw;
+ u16_t i;
+
+ //zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+ for (i=0; i<ZM_VTXQ_SIZE; i++) {
+ if (tid_baw->frame[i].buf) {
+
+ //wd->zfcbSetBawQ(dev, tid_baw->frame[i].buf, 0);
+ zfwBufFree(dev, tid_baw->frame[i].buf, ZM_SUCCESS);
+ tid_baw->frame[i].buf = NULL;
+ }
+ }
+
+ tid_baw->enabled = FALSE;
+}
+
+TID_BAW zfBawGetQ(zdev_t* dev, u16_t baw_seq) {
+ TID_BAW tid_baw=NULL;
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+ for (i=0; i<ZM_BAW_POOL_SIZE; i++){
+ tid_baw = &BAW->tid_baw[i];
+ if (TRUE == tid_baw->enabled)
+ {
+ zm_msg1_agg(ZM_LV_0, "get an old tid_baw, baw_seq=", baw_seq);
+ zm_msg1_agg(ZM_LV_0, "check a tid_baw->start_seq=", tid_baw->start_seq);
+ if(baw_seq == tid_baw->start_seq)
+ break;
+ }
+
+ }
+ if (ZM_BAW_POOL_SIZE == i)
+ return NULL;
+ return tid_baw;
+}
+#endif //disable BAW
+#endif
+
+u16_t zfAggTallyReset(zdev_t* dev)
+{
+ struct aggTally* agg_tal;
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ agg_tal = &wd->agg_tal;
+ agg_tal->got_packets_sum = 0;
+ agg_tal->got_bytes_sum = 0;
+ agg_tal->sent_bytes_sum = 0;
+ agg_tal->sent_packets_sum = 0;
+ agg_tal->avg_got_packets = 0;
+ agg_tal->avg_got_bytes = 0;
+ agg_tal->avg_sent_packets = 0;
+ agg_tal->avg_sent_bytes = 0;
+ agg_tal->time = 0;
+ return 0;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggScanAndClear */
+/* If the packets in a queue have waited for too long, clear and */
+/* delete this aggregation queue. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* time : current time */
+/* */
+/* OUTPUTS */
+/* ZM_SUCCESS */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggScanAndClear(zdev_t* dev, u32_t time)
+{
+ u16_t i;
+ u16_t head;
+ u16_t tail;
+ u32_t tick;
+ u32_t arrivalTime;
+ //u16_t aid, ac;
+ TID_TX tid_tx;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if(!(wd->state == ZM_WLAN_STATE_ENABLED)) return 0;
+ zfAggTxScheduler(dev, 1);
+ tick = zm_agg_GetTime();
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ if (!wd->aggQPool[i]) return 0;
+ if (1 == wd->aggQPool[i]->aggQEnabled)
+ {
+ tid_tx = wd->aggQPool[i];
+ zmw_enter_critical_section(dev);
+
+ head = tid_tx->aggHead;
+ tail = tid_tx->aggTail;
+
+ arrivalTime = (u32_t)tid_tx->aggvtxq[tid_tx->aggTail].arrivalTime;
+
+
+ if((tick - arrivalTime) <= ZM_AGG_CLEAR_TIME)
+ {
+
+ }
+ else if((tid_tx->size = zm_agg_qlen(dev, tid_tx->aggHead, tid_tx->aggTail)) > 0)
+ {
+
+ tid_tx->clearFlag = 1;
+
+ //zm_msg1_agg(ZM_LV_0, "clear queue tick =", tick);
+ //zm_msg1_agg(ZM_LV_0, "clear queue arrival =", arrivalTime);
+
+
+ //zmw_leave_critical_section(dev);
+ //zfAggTxScheduler(dev);
+ //zmw_enter_critical_section(dev);
+
+ }
+
+ if (tid_tx->size == 0)
+ {
+ /*
+ * queue empty
+ */
+ if (tick - tid_tx->lastArrival > ZM_AGG_DELETE_TIME)
+ {
+ zm_msg1_agg(ZM_LV_0, "delete queue, idle for n sec. n = ", \
+ ZM_AGG_DELETE_TIME/10);
+
+ zmw_leave_critical_section(dev);
+ zfAggTxDeleteQueue(dev, i);
+ zmw_enter_critical_section(dev);
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+ }
+ }
+
+ zfAggRxClear(dev, time);
+
+#ifdef ZM_AGG_TALLY
+ if((wd->tick % 100) == 0) {
+ zfAggPrintTally(dev);
+ }
+#endif
+
+ return ZM_SUCCESS;
+}
+
+u16_t zfAggPrintTally(zdev_t* dev)
+{
+ struct aggTally* agg_tal;
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ agg_tal = &wd->agg_tal;
+
+ if(agg_tal->got_packets_sum < 10)
+ {
+ zfAggTallyReset(dev);
+ return 0;
+ }
+
+ agg_tal->time++;
+ agg_tal->avg_got_packets = (agg_tal->avg_got_packets * (agg_tal->time - 1) +
+ agg_tal->got_packets_sum) / agg_tal->time;
+ agg_tal->avg_got_bytes = (agg_tal->avg_got_bytes * (agg_tal->time - 1) +
+ agg_tal->got_bytes_sum) / agg_tal->time;
+ agg_tal->avg_sent_packets = (agg_tal->avg_sent_packets * (agg_tal->time - 1)
+ + agg_tal->sent_packets_sum) / agg_tal->time;
+ agg_tal->avg_sent_bytes = (agg_tal->avg_sent_bytes * (agg_tal->time - 1) +
+ agg_tal->sent_bytes_sum) / agg_tal->time;
+ zm_msg1_agg(ZM_LV_0, "got_packets_sum =", agg_tal->got_packets_sum);
+ zm_msg1_agg(ZM_LV_0, " got_bytes_sum =", agg_tal->got_bytes_sum);
+ zm_msg1_agg(ZM_LV_0, "sent_packets_sum=", agg_tal->sent_packets_sum);
+ zm_msg1_agg(ZM_LV_0, " sent_bytes_sum =", agg_tal->sent_bytes_sum);
+ agg_tal->got_packets_sum = agg_tal->got_bytes_sum =agg_tal->sent_packets_sum
+ = agg_tal->sent_bytes_sum = 0;
+ zm_msg1_agg(ZM_LV_0, "avg_got_packets =", agg_tal->avg_got_packets);
+ zm_msg1_agg(ZM_LV_0, " avg_got_bytes =", agg_tal->avg_got_bytes);
+ zm_msg1_agg(ZM_LV_0, "avg_sent_packets=", agg_tal->avg_sent_packets);
+ zm_msg1_agg(ZM_LV_0, " avg_sent_bytes =", agg_tal->avg_sent_bytes);
+ if ((wd->commTally.BA_Fail == 0) || (wd->commTally.Hw_Tx_MPDU == 0))
+ {
+ zm_msg1_agg(ZM_LV_0, "Hardware Tx MPDU=", wd->commTally.Hw_Tx_MPDU);
+ zm_msg1_agg(ZM_LV_0, " BA Fail number=", wd->commTally.BA_Fail);
+ }
+ else
+ zm_msg1_agg(ZM_LV_0, "1/(BA fail rate)=", wd->commTally.Hw_Tx_MPDU/wd->commTally.BA_Fail);
+
+ return 0;
+}
+
+u16_t zfAggRxClear(zdev_t* dev, u32_t time)
+{
+ u16_t i;
+ struct agg_tid_rx *tid_rx;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ zmw_enter_critical_section(dev);
+ tid_rx = wd->tid_rx[i];
+ if (tid_rx->baw_head != tid_rx->baw_tail)
+ {
+ u16_t j = tid_rx->baw_tail;
+ while ((j != tid_rx->baw_head) && !tid_rx->frame[j].buf) {
+ j = (j + 1) & ZM_AGG_BAW_MASK;
+ }
+ if ((j != tid_rx->baw_head) && (time - tid_rx->frame[j].arrivalTime) >
+ (ZM_AGG_CLEAR_TIME - 5))
+ {
+ zmw_leave_critical_section(dev);
+ zm_msg0_agg(ZM_LV_1, "queue RxFlush by RxClear");
+ zfAggRxFlush(dev, 0, tid_rx);
+ zmw_enter_critical_section(dev);
+ }
+ }
+ zmw_leave_critical_section(dev);
+ }
+
+ return ZM_SUCCESS;
+}
+
+struct agg_tid_rx* zfAggRxEnabled(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t dst0, src[3], ac, aid, fragOff;
+ u8_t up;
+ u16_t offset = 0;
+ u16_t seq_no;
+ u16_t frameType;
+ u16_t frameCtrl;
+ u16_t frameSubtype;
+ u32_t tcp_seq;
+ //struct aggSta *agg_sta;
+#if ZM_AGG_FPGA_REORDERING
+ struct agg_tid_rx *tid_rx;
+#endif
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+ seq_no = zmw_rx_buf_readh(dev, buf, 22) >> 4;
+ //DbgPrint("Rx seq=%d\n", seq_no);
+ if (wd->sta.EnableHT == 0)
+ {
+ return NULL;
+ }
+
+ frameCtrl = zmw_rx_buf_readb(dev, buf, 0);
+ frameType = frameCtrl & 0xf;
+ frameSubtype = frameCtrl & 0xf0;
+
+
+ if (frameType != ZM_WLAN_DATA_FRAME) //non-Qos Data? (frameSubtype&0x80)
+ {
+ return NULL;
+ }
+#ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
+ tcp_seq = zmw_rx_buf_readb(dev, buf, 22+36) << 24;
+ tcp_seq += zmw_rx_buf_readb(dev, buf, 22+37) << 16;
+ tcp_seq += zmw_rx_buf_readb(dev, buf, 22+38) << 8;
+ tcp_seq += zmw_rx_buf_readb(dev, buf, 22+39);
+#endif
+
+ ZM_SEQ_DEBUG("In %5d, %12u\n", seq_no, tcp_seq);
+ dst0 = zmw_rx_buf_readh(dev, buf, offset+4);
+
+ src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
+ src[1] = zmw_rx_buf_readh(dev, buf, offset+12);
+ src[2] = zmw_rx_buf_readh(dev, buf, offset+14);
+
+#if ZM_AGG_FPGA_DEBUG
+ aid = 0;
+#else
+ aid = zfApFindSta(dev, src);
+#endif
+
+ //agg_sta = &wd->aggSta[aid];
+ //zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
+ //ac = zcUpToAc[up&0x7] & 0x3;
+
+ /*
+ * Filter unicast frame only, aid == 0 is for debug only
+ */
+ if ((dst0 & 0x1) == 0 && aid == 0)
+ {
+#if ZM_AGG_FPGA_REORDERING
+ tid_rx = zfAggRxGetQueue(dev, buf) ;
+ if(!tid_rx)
+ return NULL;
+ else
+ {
+ //if (tid_rx->addBaExchangeStatusCode == ZM_AGG_ADDBA_RESPONSE)
+ return tid_rx;
+ }
+#else
+ return NULL;
+#endif
+ }
+
+ return NULL;
+}
+
+u16_t zfAggRx(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo *addInfo, struct agg_tid_rx *tid_rx)
+{
+ u16_t seq_no;
+ s16_t index;
+ u16_t offset = 0;
+ zbuf_t* pbuf;
+ u8_t frameSubType;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ ZM_PERFORMANCE_RX_REORDER(dev);
+
+ seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
+
+ index = seq_no - tid_rx->seq_start;
+ /*
+ * for debug
+ */
+
+ /* zm_msg2_agg(ZM_LV_0, "queue seq = ", seq_no);
+ * DbgPrint("%s:%s%lxh %s%lxh\n", __func__, "queue seq=", seq_no,
+ * "; seq_start=", tid_rx->seq_start);
+ */
+
+ //DbgPrint("seq_no=%d, seq_start=%d\n", seq_no, tid_rx->seq_start);
+
+ /* In some APs, we found that it might transmit NULL data whose sequence number
+ is out or order. In order to avoid this problem, we ignore these NULL data.
+ */
+
+ frameSubType = (zmw_rx_buf_readh(dev, buf, 0) & 0xF0) >> 4;
+
+ /* If this is a NULL data instead of Qos NULL data */
+ if ((frameSubType & 0x0C) == 0x04)
+ {
+ s16_t seq_diff;
+
+ seq_diff = (seq_no > tid_rx->seq_start) ?
+ seq_no - tid_rx->seq_start : tid_rx->seq_start - seq_no;
+
+ if (seq_diff > ZM_AGG_BAW_SIZE)
+ {
+ zm_debug_msg0("Free Rx NULL data in zfAggRx");
+
+ /* Free Rx buffer */
+ zfwBufFree(dev, buf, 0);
+ return ZM_ERR_OUT_OF_ORDER_NULL_DATA;
+ }
+ }
+
+ /*
+ * sequence number wrap at 4k
+ */
+ if (tid_rx->seq_start > seq_no)
+ {
+ //index += 4096;
+
+ zmw_enter_critical_section(dev);
+ if (tid_rx->seq_start >= 4096) {
+ tid_rx->seq_start = 0;
+ }
+ zmw_leave_critical_section(dev);
+
+ }
+
+ if (tid_rx->seq_start == seq_no) {
+ zmw_enter_critical_section(dev);
+ if (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) > 0) {
+ //DbgPrint("head=%d, tail=%d", tid_rx->baw_head, tid_rx->baw_tail);
+ tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
+ }
+ tid_rx->seq_start = (tid_rx->seq_start + 1) & (4096 - 1);
+ zmw_leave_critical_section(dev);
+
+ ZM_PERFORMANCE_RX_SEQ(dev, buf);
+
+ if (wd->zfcbRecv80211 != NULL) {
+ //seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
+ //DbgPrint("Recv indicate seq=%d\n", seq_no);
+ //DbgPrint("1. seq=%d\n", seq_no);
+
+ wd->zfcbRecv80211(dev, buf, addInfo);
+ }
+ else {
+ zfiRecv80211(dev, buf, addInfo);
+ }
+ }
+ else if (!zfAggRxEnqueue(dev, buf, tid_rx, addInfo))
+ {
+ /*
+ * duplicated packet
+ */
+ return 1;
+ }
+
+ while (tid_rx->baw_head != tid_rx->baw_tail) {// && tid_rx->frame[tid_rx->baw_tail].buf)
+ u16_t tailIndex;
+
+ zmw_enter_critical_section(dev);
+
+ tailIndex = tid_rx->baw_tail;
+ pbuf = tid_rx->frame[tailIndex].buf;
+ tid_rx->frame[tailIndex].buf = 0;
+ if (!pbuf)
+ {
+ zmw_leave_critical_section(dev);
+ break;
+ }
+
+ tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
+ tid_rx->seq_start = (tid_rx->seq_start + 1) & (4096 - 1);
+
+
+ //if(pbuf && tid_rx->baw_size > 0)
+ // tid_rx->baw_size--;
+
+ zmw_leave_critical_section(dev);
+
+ ZM_PERFORMANCE_RX_SEQ(dev, pbuf);
+
+ if (wd->zfcbRecv80211 != NULL)
+ {
+ //seq_no = zmw_rx_buf_readh(dev, pbuf, offset+22) >> 4;
+ //DbgPrint("Recv indicate seq=%d\n", seq_no);
+ //DbgPrint("1. seq=%d\n", seq_no);
+ wd->zfcbRecv80211(dev, pbuf, addInfo);
+ }
+ else
+ {
+ //seq_no = zmw_rx_buf_readh(dev, pbuf, offset+22) >> 4;
+ //DbgPrint("Recv indicate seq=%d\n", seq_no);
+ zfiRecv80211(dev, pbuf, addInfo);
+ }
+ }
+
+ return 1;
+}
+
+struct agg_tid_rx *zfAggRxGetQueue(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t src[3];
+ u16_t aid, ac, i;
+ u16_t offset = 0;
+ struct agg_tid_rx *tid_rx = NULL;
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
+ src[1] = zmw_rx_buf_readh(dev, buf, offset+12);
+ src[2] = zmw_rx_buf_readh(dev, buf, offset+14);
+ aid = zfApFindSta(dev, src);
+
+ ac = (zmw_rx_buf_readh(dev, buf, 24) & 0xF);
+
+ // mark by spin lock debug
+ //zmw_enter_critical_section(dev);
+
+ for (i=0; i<ZM_AGG_POOL_SIZE ; i++)
+ {
+ if((wd->tid_rx[i]->aid == aid) && (wd->tid_rx[i]->ac == ac))
+ {
+ tid_rx = wd->tid_rx[i];
+ break;
+ }
+ }
+
+ // mark by spin lock debug
+ //zmw_leave_critical_section(dev);
+ return tid_rx;
+}
+
+
+u16_t zfAggRxEnqueue(zdev_t* dev, zbuf_t* buf, struct agg_tid_rx *tid_rx, struct zsAdditionInfo *addInfo)
+{
+ u16_t seq_no, offset = 0;
+ u16_t q_index;
+ s16_t index;
+ u8_t bdropframe = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
+ index = seq_no - tid_rx->seq_start;
+
+ /*
+ * sequence number wrap at 4k
+ * -1000: check for duplicate past packet
+ */
+ bdropframe = 0;
+ if (tid_rx->seq_start > seq_no) {
+ if ((tid_rx->seq_start > 3967) && (seq_no < 128)) {
+ index += 4096;
+ } else if (tid_rx->seq_start - seq_no > 70) {
+ zmw_enter_critical_section(dev);
+ tid_rx->sq_behind_count++;
+ if (tid_rx->sq_behind_count > 3) {
+ tid_rx->sq_behind_count = 0;
+ } else {
+ bdropframe = 1;
+ }
+ zmw_leave_critical_section(dev);
+ } else {
+ bdropframe = 1;
+ }
+ } else {
+ if (seq_no - tid_rx->seq_start > 70) {
+ zmw_enter_critical_section(dev);
+ tid_rx->sq_exceed_count++;
+ if (tid_rx->sq_exceed_count > 3) {
+ tid_rx->sq_exceed_count = 0;
+ } else {
+ bdropframe = 1;
+ }
+ zmw_leave_critical_section(dev);
+ }
+ }
+
+ if (bdropframe == 1) {
+ /*if (wd->zfcbRecv80211 != NULL) {
+ wd->zfcbRecv80211(dev, buf, addInfo);
+ }
+ else {
+ zfiRecv80211(dev, buf, addInfo);
+ }*/
+
+ ZM_PERFORMANCE_FREE(dev, buf);
+
+ zfwBufFree(dev, buf, 0);
+ /*zfAggRxFlush(dev, seq_no, tid_rx);
+ tid_rx->seq_start = seq_no;
+ index = seq_no - tid_rx->seq_start;
+ */
+
+ //DbgPrint("Free an old packet, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
+
+ /*
+ * duplicate past packet
+ * happens only in simulated aggregation environment
+ */
+ return 0;
+ } else {
+ zmw_enter_critical_section(dev);
+ if (tid_rx->sq_exceed_count > 0){
+ tid_rx->sq_exceed_count--;
+ }
+
+ if (tid_rx->sq_behind_count > 0) {
+ tid_rx->sq_behind_count--;
+ }
+ zmw_leave_critical_section(dev);
+ }
+
+ if (index < 0) {
+ zfAggRxFlush(dev, seq_no, tid_rx);
+ tid_rx->seq_start = seq_no;
+ index = 0;
+ }
+
+ //if (index >= (ZM_AGG_BAW_SIZE - 1))
+ if (index >= (ZM_AGG_BAW_MASK))
+ {
+ /*
+ * queue full
+ */
+ //DbgPrint("index >= 64, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
+ zfAggRxFlush(dev, seq_no, tid_rx);
+ //tid_rx->seq_start = seq_no;
+ index = seq_no - tid_rx->seq_start;
+ if ((tid_rx->seq_start > seq_no) && (tid_rx->seq_start > 1000) && (tid_rx->seq_start - 1000) > seq_no)
+ {
+ //index = seq_no - tid_rx->seq_start;
+ index += 4096;
+ }
+ //index = seq_no - tid_rx->seq_start;
+ while (index >= (ZM_AGG_BAW_MASK)) {
+ //DbgPrint("index >= 64, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
+ tid_rx->seq_start = (tid_rx->seq_start + ZM_AGG_BAW_MASK) & (4096 - 1);
+ index = seq_no - tid_rx->seq_start;
+ if ((tid_rx->seq_start > seq_no) && (tid_rx->seq_start > 1000) && (tid_rx->seq_start - 1000) > seq_no)
+ {
+ index += 4096;
+ }
+ }
+ }
+
+
+ q_index = (tid_rx->baw_tail + index) & ZM_AGG_BAW_MASK;
+ if (tid_rx->frame[q_index].buf && (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) >
+ (((q_index) - tid_rx->baw_tail) & ZM_AGG_BAW_MASK)))
+ {
+
+ ZM_PERFORMANCE_DUP(dev, tid_rx->frame[q_index].buf, buf);
+ zfwBufFree(dev, buf, 0);
+ //DbgPrint("Free a duplicate packet, seq_start=%d, seq_no=%d\n", tid_rx->seq_start, seq_no);
+ //DbgPrint("head=%d, tail=%d", tid_rx->baw_head, tid_rx->baw_tail);
+ /*
+ * duplicate packet
+ */
+ return 0;
+ }
+
+ zmw_enter_critical_section(dev);
+ if(tid_rx->frame[q_index].buf) {
+ zfwBufFree(dev, tid_rx->frame[q_index].buf, 0);
+ tid_rx->frame[q_index].buf = 0;
+ }
+
+ tid_rx->frame[q_index].buf = buf;
+ tid_rx->frame[q_index].arrivalTime = zm_agg_GetTime();
+ zfwMemoryCopy((void*)&tid_rx->frame[q_index].addInfo, (void*)addInfo, sizeof(struct zsAdditionInfo));
+
+ /*
+ * for debug simulated aggregation only,
+ * should be done in rx of ADDBA Request
+ */
+ //tid_rx->addInfo = addInfo;
+
+
+ if (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) <= index)
+ {
+ //tid_rx->baw_size = index + 1;
+ if (((tid_rx->baw_head - tid_rx->baw_tail) & ZM_AGG_BAW_MASK) <=
+ //((q_index + 1) & ZM_AGG_BAW_MASK))
+ (((q_index) - tid_rx->baw_tail) & ZM_AGG_BAW_MASK))//tid_rx->baw_size )
+ tid_rx->baw_head = (q_index + 1) & ZM_AGG_BAW_MASK;
+ }
+ zmw_leave_critical_section(dev);
+
+ /*
+ * success
+ */
+ //DbgPrint("head=%d, tail=%d, start=%d", tid_rx->baw_head, tid_rx->baw_tail, tid_rx->seq_start);
+ return 1;
+}
+
+u16_t zfAggRxFlush(zdev_t* dev, u16_t seq_no, struct agg_tid_rx *tid_rx)
+{
+ zbuf_t* pbuf;
+ u16_t seq;
+ struct zsAdditionInfo addInfo;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ ZM_PERFORMANCE_RX_FLUSH(dev);
+
+ while (1)
+ {
+ zmw_enter_critical_section(dev);
+ if (tid_rx->baw_tail == tid_rx->baw_head) {
+ zmw_leave_critical_section(dev);
+ break;
+ }
+
+ pbuf = tid_rx->frame[tid_rx->baw_tail].buf;
+ zfwMemoryCopy((void*)&addInfo, (void*)&tid_rx->frame[tid_rx->baw_tail].addInfo, sizeof(struct zsAdditionInfo));
+ tid_rx->frame[tid_rx->baw_tail].buf = 0;
+ //if(pbuf && tid_rx->baw_size > 0) tid_rx->baw_size--;
+ tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
+ tid_rx->seq_start = (tid_rx->seq_start + 1) & (4096 - 1);
+ zmw_leave_critical_section(dev);
+
+ if (pbuf)
+ {
+
+ ZM_PERFORMANCE_RX_SEQ(dev, pbuf);
+
+ if (wd->zfcbRecv80211 != NULL)
+ {
+ seq = zmw_rx_buf_readh(dev, pbuf, 22) >> 4;
+ //DbgPrint("Recv indicate seq=%d\n", seq);
+ //DbgPrint("2. seq=%d\n", seq);
+ wd->zfcbRecv80211(dev, pbuf, &addInfo);
+ }
+ else
+ {
+ seq = zmw_rx_buf_readh(dev, pbuf, 22) >> 4;
+ //DbgPrint("Recv indicate seq=%d\n", seq);
+ zfiRecv80211(dev, pbuf, &addInfo);
+ }
+ }
+ }
+
+ zmw_enter_critical_section(dev);
+ tid_rx->baw_head = tid_rx->baw_tail = 0;
+ zmw_leave_critical_section(dev);
+ return 1;
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggRxFreeBuf */
+/* Frees all queued packets in buffer when the driver is down. */
+/* The zfFreeResource() will check if the buffer is all freed. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* ZM_SUCCESS */
+/* */
+/* AUTHOR */
+/* Honda Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggRxFreeBuf(zdev_t* dev, u16_t destroy)
+{
+ u16_t i;
+ zbuf_t* buf;
+ struct agg_tid_rx *tid_rx;
+
+ TID_TX tid_tx;
+ //struct bufInfo *buf_info;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ u16_t j;
+
+ tid_rx = wd->tid_rx[i];
+
+ for(j=0; j <= ZM_AGG_BAW_SIZE; j++)
+ {
+ zmw_enter_critical_section(dev);
+ buf = tid_rx->frame[j].buf;
+ tid_rx->frame[j].buf = 0;
+ zmw_leave_critical_section(dev);
+
+ if (buf)
+ {
+ zfwBufFree(dev, buf, 0);
+ }
+ }
+
+ #if 0
+ if ( tid_rx->baw_head != tid_rx->baw_tail )
+ {
+ while (tid_rx->baw_head != tid_rx->baw_tail)
+ {
+ buf = tid_rx->frame[tid_rx->baw_tail].buf;
+ tid_rx->frame[tid_rx->baw_tail].buf = 0;
+ if (buf)
+ {
+ zfwBufFree(dev, buf, 0);
+
+ zmw_enter_critical_section(dev);
+ tid_rx->frame[tid_rx->baw_tail].buf = 0;
+ zmw_leave_critical_section(dev);
+ }
+ zmw_enter_critical_section(dev);
+ //if (tid_rx->baw_size > 0)tid_rx->baw_size--;
+ tid_rx->baw_tail = (tid_rx->baw_tail + 1) & ZM_AGG_BAW_MASK;
+ tid_rx->seq_start++;
+ zmw_leave_critical_section(dev);
+ }
+ }
+ #endif
+
+ zmw_enter_critical_section(dev);
+ tid_rx->seq_start = 0;
+ tid_rx->baw_head = tid_rx->baw_tail = 0;
+ tid_rx->aid = ZM_MAX_STA_SUPPORT;
+ zmw_leave_critical_section(dev);
+
+ #ifdef ZM_ENABLE_AGGREGATION
+ #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+ if (tid_baw->enabled) {
+ zm_msg1_agg(ZM_LV_0, "Device down, clear BAW queue:", i);
+ BAW->disable(dev, tid_baw);
+ }
+ #endif
+ #endif
+ if (1 == wd->aggQPool[i]->aggQEnabled) {
+ tid_tx = wd->aggQPool[i];
+ buf = zfAggTxGetVtxq(dev, tid_tx);
+ while (buf) {
+ zfwBufFree(dev, buf, 0);
+ buf = zfAggTxGetVtxq(dev, tid_tx);
+ }
+ }
+
+ if(destroy) {
+ zfwMemFree(dev, wd->aggQPool[i], sizeof(struct aggQueue));
+ zfwMemFree(dev, wd->tid_rx[i], sizeof(struct agg_tid_rx));
+ }
+ }
+ #ifdef ZM_ENABLE_AGGREGATION
+ #ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+ if(destroy) zfwMemFree(dev, BAW, sizeof(struct baw_enabler));
+ #endif
+ #endif
+ return ZM_SUCCESS;
+}
+
+
+void zfAggRecvBAR(zdev_t* dev, zbuf_t *buf) {
+ u16_t start_seq, len;
+ u8_t i, bitmap[8];
+ len = zfwBufGetSize(dev, buf);
+ start_seq = zmw_rx_buf_readh(dev, buf, len-2);
+ DbgPrint("Received a BAR Control frame, start_seq=%d", start_seq>>4);
+ /* todo: set the bitmap by reordering buffer! */
+ for (i=0; i<8; i++) bitmap[i]=0;
+ zfSendBA(dev, start_seq, bitmap);
+}
+
+#ifdef ZM_ENABLE_AGGREGATION
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+void zfAggTxRetransmit(zdev_t* dev, struct bufInfo *buf_info, struct aggControl *aggControl, TID_TX tid_tx) {
+ u16_t removeLen;
+ u16_t err;
+
+ zmw_get_wlan_dev(dev);
+ if (aggControl && (ZM_AGG_FIRST_MPDU == aggControl->ampduIndication) ) {
+ tid_tx->bar_ssn = buf_info->baw_header->header[15];
+ aggControl->tid_baw->start_seq = tid_tx->bar_ssn >> 4;
+ zm_msg1_agg(ZM_LV_0, "start seq=", tid_tx->bar_ssn >> 4);
+ }
+ buf_info->baw_header->header[4] |= (1 << 11);
+ if (aggControl && aggControl->aggEnabled) {
+ //if (wd->enableAggregation==0 && !(buf_info->baw_header->header[6]&0x1))
+ //{
+ //if (((buf_info->baw_header->header[2] & 0x3) == 2))
+ //{
+ /* Enable aggregation */
+ buf_info->baw_header->header[1] |= 0x20;
+ if (ZM_AGG_LAST_MPDU == aggControl->ampduIndication) {
+ buf_info->baw_header->header[1] |= 0x4000;
+ }
+ else {
+ buf_info->baw_header->header[1] &= ~0x4000;
+ //zm_debug_msg0("ZM_AGG_LAST_MPDU");
+ }
+ //}
+ //else {
+ // zm_debug_msg1("no aggr, header[2]&0x3 = ",buf_info->baw_header->header[2] & 0x3)
+ // aggControl->aggEnabled = 0;
+ //}
+ //}
+ //else {
+ // zm_debug_msg1("no aggr, wd->enableAggregation = ", wd->enableAggregation);
+ // zm_debug_msg1("no aggr, !header[6]&0x1 = ",!(buf_info->baw_header->header[6]&0x1));
+ // aggControl->aggEnabled = 0;
+ //}
+ }
+
+ /*if (aggControl->tid_baw) {
+ struct baw_header_r header_r;
+
+ header_r.header = buf_info->baw_header->header;
+ header_r.mic = buf_info->baw_header->mic;
+ header_r.snap = buf_info->baw_header->snap;
+ header_r.headerLen = buf_info->baw_header->headerLen;
+ header_r.micLen = buf_info->baw_header->micLen;
+ header_r.snapLen = buf_info->baw_header->snapLen;
+ header_r.removeLen = buf_info->baw_header->removeLen;
+ header_r.keyIdx = buf_info->baw_header->keyIdx;
+
+ BAW->insert(dev, buf_info->buf, tid_tx->bar_ssn >> 4, aggControl->tid_baw, buf_info->baw_retransmit, &header_r);
+ }*/
+
+ if ((err = zfHpSend(dev,
+ buf_info->baw_header->header,
+ buf_info->baw_header->headerLen,
+ buf_info->baw_header->snap,
+ buf_info->baw_header->snapLen,
+ buf_info->baw_header->mic,
+ buf_info->baw_header->micLen,
+ buf_info->buf,
+ buf_info->baw_header->removeLen,
+ ZM_EXTERNAL_ALLOC_BUF,
+ (u8_t)tid_tx->ac,
+ buf_info->baw_header->keyIdx)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+
+ return;
+
+zlError:
+ zfwBufFree(dev, buf_info->buf, 0);
+ return;
+
+}
+#endif //disable BAW
+#endif
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAggTxSendEth */
+/* Called to transmit Ethernet frame from upper elayer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer pointer */
+/* port : WLAN port, 0=>standard, 0x10-0x17=>VAP, 0x20-0x25=>WDS */
+/* */
+/* OUTPUTS */
+/* error code */
+/* */
+/* AUTHOR */
+/* Stephen, Honda Atheros Communications, Inc. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfAggTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u8_t flag, struct aggControl *aggControl, TID_TX tid_tx)
+{
+ u16_t err;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ u16_t removeLen;
+ u16_t header[(8+30+2+18)/2]; /* ctr+(4+a1+a2+a3+2+a4)+qos+iv */
+ u16_t headerLen;
+ u16_t mic[8/2];
+ u16_t micLen;
+ u16_t snap[8/2];
+ u16_t snapLen;
+ u16_t fragLen;
+ u16_t frameLen;
+ u16_t fragNum;
+ struct zsFrag frag;
+ u16_t i, id;
+ u16_t da[3];
+ u16_t sa[3];
+ u8_t up;
+ u8_t qosType, keyIdx = 0;
+ u16_t fragOff;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zm_msg1_tx(ZM_LV_2, "zfTxSendEth(), port=", port);
+
+ /* Get IP TOS for QoS AC and IP frag offset */
+ zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
+
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 16);
+ da[1] = zmw_tx_buf_readh(dev, buf, 18);
+ da[2] = zmw_tx_buf_readh(dev, buf, 20);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 10);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 12);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 14);
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 4);
+ da[1] = zmw_tx_buf_readh(dev, buf, 6);
+ da[2] = zmw_tx_buf_readh(dev, buf, 8);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 10);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 12);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 14);
+ }
+ else if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 4);
+ da[1] = zmw_tx_buf_readh(dev, buf, 6);
+ da[2] = zmw_tx_buf_readh(dev, buf, 8);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 16);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 18);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 20);
+ }
+ else
+ {
+ //
+ }
+#else
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 0);
+ da[1] = zmw_tx_buf_readh(dev, buf, 2);
+ da[2] = zmw_tx_buf_readh(dev, buf, 4);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 6);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 8);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 10);
+#endif
+ //Decide Key Index in ATOM, No meaning in OTUS--CWYang(m)
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ keyIdx = wd->ap.bcHalKeyIdx[port];
+ id = zfApFindSta(dev, da);
+ if (id != 0xffff)
+ {
+ switch (wd->ap.staTable[id].encryMode)
+ {
+ case ZM_AES:
+ case ZM_TKIP:
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+#endif //ZM_ENABLE_CENC
+ keyIdx = wd->ap.staTable[id].keyIdx;
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (wd->sta.encryMode)
+ {
+ case ZM_WEP64:
+ case ZM_WEP128:
+ case ZM_WEP256:
+ keyIdx = wd->sta.keyId;
+ break;
+ case ZM_AES:
+ case ZM_TKIP:
+ if ((da[0]& 0x1))
+ keyIdx = 5;
+ else
+ keyIdx = 4;
+ break;
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+ keyIdx = wd->sta.cencKeyId;
+ break;
+#endif //ZM_ENABLE_CENC
+ }
+ }
+
+ /* Create SNAP */
+ removeLen = zfTxGenWlanSnap(dev, buf, snap, &snapLen);
+ //zm_msg1_tx(ZM_LV_0, "fragOff=", fragOff);
+
+ fragLen = wd->fragThreshold;
+ frameLen = zfwBufGetSize(dev, buf);
+ frameLen -= removeLen;
+
+#if 0
+ /* Create MIC */
+ if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)&&
+ (wd->sta.encryMode == ZM_TKIP) )
+ {
+ if ( frameLen > fragLen )
+ {
+ micLen = zfTxGenWlanTail(dev, buf, snap, snapLen, mic);
+ }
+ else
+ {
+ /* append MIC by HMAC */
+ micLen = 8;
+ }
+ }
+ else
+ {
+ micLen = 0;
+ }
+#else
+ if ( frameLen > fragLen )
+ {
+ micLen = zfTxGenWlanTail(dev, buf, snap, snapLen, mic);
+ }
+ else
+ {
+ /* append MIC by HMAC */
+ micLen = 0;
+ }
+#endif
+
+ /* Access Category */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zfApGetStaQosType(dev, da, &qosType);
+ if (qosType == 0)
+ {
+ up = 0;
+ }
+ }
+ else if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ if (wd->sta.wmeConnected == 0)
+ {
+ up = 0;
+ }
+ }
+ else
+ {
+ /* TODO : STA QoS control field */
+ up = 0;
+ }
+
+ /* Assign sequence number */
+ zmw_enter_critical_section(dev);
+ frag.seq[0] = ((wd->seq[zcUpToAc[up&0x7]]++) << 4);
+ if (aggControl && (ZM_AGG_FIRST_MPDU == aggControl->ampduIndication) ) {
+ tid_tx->bar_ssn = frag.seq[0];
+
+ zm_msg1_agg(ZM_LV_0, "start seq=", tid_tx->bar_ssn >> 4);
+ }
+ //tid_tx->baw_buf[tid_tx->baw_head-1].baw_seq=frag.seq[0];
+ zmw_leave_critical_section(dev);
+
+
+ frag.buf[0] = buf;
+ frag.bufType[0] = bufType;
+ frag.flag[0] = flag;
+ fragNum = 1;
+
+ for (i=0; i<fragNum; i++)
+ {
+ /* Create WLAN header(Control Setting + 802.11 header + IV) */
+ if (up !=0 ) zm_debug_msg1("up not 0, up=",up);
+ headerLen = zfTxGenWlanHeader(dev, frag.buf[i], header, frag.seq[i],
+ frag.flag[i], snapLen+micLen, removeLen,
+ port, da, sa, up, &micLen, snap, snapLen,
+ aggControl);
+
+ /* Get buffer DMA address */
+ //if ((addrTblSize = zfwBufMapDma(dev, frag.buf[i], &addrTbl)) == 0)
+ //if ((addrTblSize = zfwMapTxDma(dev, frag.buf[i], &addrTbl)) == 0)
+ //{
+ // err = ZM_ERR_BUFFER_DMA_ADDR;
+ // goto zlError;
+ //}
+
+ /* Flush buffer on cache */
+ //zfwBufFlush(dev, frag.buf[i]);
+
+#if 0
+ zm_msg1_tx(ZM_LV_0, "headerLen=", headerLen);
+ zm_msg1_tx(ZM_LV_0, "snapLen=", snapLen);
+ zm_msg1_tx(ZM_LV_0, "micLen=", micLen);
+ zm_msg1_tx(ZM_LV_0, "removeLen=", removeLen);
+ zm_msg1_tx(ZM_LV_0, "addrTblSize=", addrTblSize);
+ zm_msg1_tx(ZM_LV_0, "frag.bufType[0]=", frag.bufType[0]);
+#endif
+
+ fragLen = zfwBufGetSize(dev, frag.buf[i]);
+ if ((da[0]&0x1) == 0)
+ {
+ wd->commTally.txUnicastFrm++;
+ wd->commTally.txUnicastOctets += (fragLen+snapLen);
+ }
+ else if ((da[0]& 0x1))
+ {
+ wd->commTally.txBroadcastFrm++;
+ wd->commTally.txBroadcastOctets += (fragLen+snapLen);
+ }
+ else
+ {
+ wd->commTally.txMulticastFrm++;
+ wd->commTally.txMulticastOctets += (fragLen+snapLen);
+ }
+ wd->ledStruct.txTraffic++;
+
+#if 0 //Who care this?
+ if ( (i)&&(i == (fragNum-1)) )
+ {
+ wd->trafTally.txDataByteCount -= micLen;
+ }
+#endif
+
+ /*if (aggControl->tid_baw && aggControl->aggEnabled) {
+ struct baw_header_r header_r;
+
+ header_r.header = header;
+ header_r.mic = mic;
+ header_r.snap = snap;
+ header_r.headerLen = headerLen;
+ header_r.micLen = micLen;
+ header_r.snapLen = snapLen;
+ header_r.removeLen = removeLen;
+ header_r.keyIdx = keyIdx;
+
+ BAW->insert(dev, buf, tid_tx->bar_ssn >> 4, aggControl->tid_baw, 0, &header_r);
+ }*/
+
+ if ((err = zfHpSend(dev, header, headerLen, snap, snapLen,
+ mic, micLen, frag.buf[i], removeLen,
+ frag.bufType[i], zcUpToAc[up&0x7], keyIdx)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+
+
+ continue;
+
+zlError:
+ if (frag.bufType[i] == ZM_EXTERNAL_ALLOC_BUF)
+ {
+ zfwBufFree(dev, frag.buf[i], err);
+ }
+ else if (frag.bufType[i] == ZM_INTERNAL_ALLOC_BUF)
+ {
+ zfwBufFree(dev, frag.buf[i], 0);
+ }
+ else
+ {
+ zm_assert(0);
+ }
+ } /* for (i=0; i<fragNum; i++) */
+
+ return ZM_SUCCESS;
+}
+
+/*
+ * zfAggSendADDBA() refers zfSendMmFrame() in cmm.c
+ */
+u16_t zfAggSendAddbaRequest(zdev_t* dev, u16_t *dst, u16_t ac, u16_t up)
+{
+ zbuf_t* buf;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ //u16_t err;
+ u16_t offset = 0;
+ u16_t hlen = 32;
+ u16_t header[(24+25+1)/2];
+ u16_t vap = 0;
+ u16_t i;
+ u8_t encrypt = 0;
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+
+ /*
+ * TBD : Maximum size of managment frame
+ */
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
+ return ZM_SUCCESS;
+ }
+
+ /*
+ * Reserve room for wlan header
+ */
+ offset = hlen;
+
+ /*
+ * add addba frame body
+ */
+ offset = zfAggSetAddbaFrameBody(dev, buf, offset, ac, up);
+
+
+ zfwBufSetSize(dev, buf, offset);
+
+ /*
+ * Copy wlan header
+ */
+ zfAggGenAddbaHeader(dev, dst, header, offset-hlen, buf, vap, encrypt);
+ for (i=0; i<(hlen>>1); i++)
+ {
+ zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
+ }
+
+ /* Get buffer DMA address */
+ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
+ //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
+ //{
+ // goto zlError;
+ //}
+
+ //zm_msg2_mm(ZM_LV_2, "offset=", offset);
+ //zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
+ //zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
+ //zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
+
+ #if 0
+ if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+ #else
+ zfPutVmmq(dev, buf);
+ zfPushVtxq(dev);
+ #endif
+
+ return ZM_SUCCESS;
+
+}
+
+u16_t zfAggSetAddbaFrameBody(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t ac, u16_t up)
+{
+ u16_t ba_parameter, start_seq;
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+ /*
+ * ADDBA Request frame body
+ */
+
+ /*
+ * Category
+ */
+ zmw_tx_buf_writeb(dev, buf, offset++, 3);
+ /*
+ * Action details = 0
+ */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_ADDBA_REQUEST_FRAME);
+ /*
+ * Dialog Token = nonzero
+ * TBD: define how to get dialog token?
+ */
+ zmw_tx_buf_writeb(dev, buf, offset++, 2);
+ /*
+ * Block Ack parameter set
+ * BA policy = 1 for immediate BA, 0 for delayed BA
+ * TID(4bits) & buffer size(4bits) (TID=up & buffer size=0x80)
+ * TBD: how to get buffer size?
+ * zwwwwwwwwwwswwwwwwwwwwwswwwwwwwwswwwwwwwwwwwww{
+ * x B0 x B1 x B2 B5 x B6 B15 x
+ * uwwwwwwwwwwqwwwwwwwwwwwqwwwwwwwwqwwwwwwwwwwwwwt
+ * x Reserved x BA policy x TID x Buffer size x
+ * |wwwwwwwwwwrwwwwwwwwwwwrwwwwwwwwrwwwwwwwwwwwww}
+ */
+ ba_parameter = 1 << 12; // buffer size = 0x40(64)
+ ba_parameter |= up << 2; // tid = up
+ ba_parameter |= 2; // ba policy = 1
+ zmw_tx_buf_writeh(dev, buf, offset, ba_parameter);
+ offset+=2;
+ /*
+ * BA timeout value
+ */
+ zmw_tx_buf_writeh(dev, buf, offset, 0);
+ offset+=2;
+ /*
+ * BA starting sequence number
+ * zwwwwwwwwwwwwwswwwwwwwwwwwwwwwwwwwww{
+ * x B0 B3 x B4 B15 x
+ * uwwwwwwwwwwwwwqwwwwwwwwwwwwwwwwwwwwwt
+ * x Frag num(0) x BA starting seq num x
+ * |wwwwwwwwwwwwwrwwwwwwwwwwwwwwwwwwwww}
+ */
+ start_seq = ((wd->seq[ac]) << 4) & 0xFFF0;
+ zmw_tx_buf_writeh(dev, buf, offset, start_seq);
+ offset+=2;
+
+ return offset;
+}
+
+u16_t zfAggGenAddbaHeader(zdev_t* dev, u16_t* dst,
+ u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt)
+{
+ u8_t hlen = 32; // MAC ctrl + PHY ctrl + 802.11 MM header
+ //u8_t frameType = ZM_WLAN_FRAME_TYPE_ACTION;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ /*
+ * Generate control setting
+ */
+ //bodyLen = zfwBufGetSize(dev, buf);
+ header[0] = 24+len+4; //Length
+ header[1] = 0x8; //MAC control, backoff + (ack)
+
+#if 0
+ /* CCK 1M */
+ header[2] = 0x0f00; //PHY control L
+ header[3] = 0x0000; //PHY control H
+#else
+ /* OFDM 6M */
+ header[2] = 0x0f01; //PHY control L
+ header[3] = 0x000B; //PHY control H
+#endif
+
+ /*
+ * Generate WLAN header
+ * Frame control frame type and subtype
+ */
+ header[4+0] = ZM_WLAN_FRAME_TYPE_ACTION;
+ /*
+ * Duration
+ */
+ header[4+1] = 0;
+
+ if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ header[4+8] = wd->sta.bssid[0];
+ header[4+9] = wd->sta.bssid[1];
+ header[4+10] = wd->sta.bssid[2];
+ }
+ else if (wd->wlanMode == ZM_MODE_PSEUDO)
+ {
+ /* Address 3 = 00:00:00:00:00:00 */
+ header[4+8] = 0;
+ header[4+9] = 0;
+ header[4+10] = 0;
+ }
+ else if (wd->wlanMode == ZM_MODE_IBSS)
+ {
+ header[4+8] = wd->sta.bssid[0];
+ header[4+9] = wd->sta.bssid[1];
+ header[4+10] = wd->sta.bssid[2];
+ }
+ else if (wd->wlanMode == ZM_MODE_AP)
+ {
+ /* Address 3 = BSSID */
+ header[4+8] = wd->macAddr[0];
+ header[4+9] = wd->macAddr[1];
+ header[4+10] = wd->macAddr[2] + (vap<<8);
+ }
+
+ /* Address 1 = DA */
+ header[4+2] = dst[0];
+ header[4+3] = dst[1];
+ header[4+4] = dst[2];
+
+ /* Address 2 = SA */
+ header[4+5] = wd->macAddr[0];
+ header[4+6] = wd->macAddr[1];
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ header[4+7] = wd->macAddr[2] + (vap<<8);
+ }
+ else
+ {
+ header[4+7] = wd->macAddr[2];
+ }
+
+ /* Sequence Control */
+ zmw_enter_critical_section(dev);
+ header[4+11] = ((wd->mmseq++)<<4);
+ zmw_leave_critical_section(dev);
+
+
+ return hlen;
+}
+
+
+u16_t zfAggProcessAction(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t category;
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ category = zmw_rx_buf_readb(dev, buf, 24);
+
+ switch (category)
+ {
+ case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
+ zfAggBlockAckActionFrame(dev, buf);
+ break;
+
+ }
+
+ return ZM_SUCCESS;
+}
+
+
+u16_t zfAggBlockAckActionFrame(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t action;
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ action = zmw_rx_buf_readb(dev, buf, 25);
+#ifdef ZM_ENABLE_AGGREGATION
+ switch (action)
+ {
+ case ZM_WLAN_ADDBA_REQUEST_FRAME:
+ zm_msg0_agg(ZM_LV_0, "Received BA Action frame is ADDBA request");
+ zfAggRecvAddbaRequest(dev, buf);
+ break;
+ case ZM_WLAN_ADDBA_RESPONSE_FRAME:
+ zm_msg0_agg(ZM_LV_0, "Received BA Action frame is ADDBA response");
+ zfAggRecvAddbaResponse(dev, buf);
+ break;
+ case ZM_WLAN_DELBA_FRAME:
+ zfAggRecvDelba(dev, buf);
+ break;
+ }
+#endif
+ return ZM_SUCCESS;
+}
+
+u16_t zfAggRecvAddbaRequest(zdev_t* dev, zbuf_t* buf)
+{
+ //u16_t dialog;
+ struct aggBaFrameParameter bf;
+ u16_t i;
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ bf.buf = buf;
+ bf.dialog = zmw_rx_buf_readb(dev, buf, 26);
+ /*
+ * ba parameter set
+ */
+ bf.ba_parameter = zmw_rx_buf_readh(dev, buf, 27);
+ bf.ba_policy = (bf.ba_parameter >> 1) & 1;
+ bf.tid = (bf.ba_parameter >> 2) & 0xF;
+ bf.buffer_size = (bf.ba_parameter >> 6);
+ /*
+ * BA timeout value
+ */
+ bf.ba_timeout = zmw_rx_buf_readh(dev, buf, 29);
+ /*
+ * BA starting sequence number
+ */
+ bf.ba_start_seq = zmw_rx_buf_readh(dev, buf, 31) >> 4;
+
+ i=26;
+ while(i < 32) {
+ zm_debug_msg2("Recv ADDBA Req:", zmw_rx_buf_readb(dev,buf,i));
+ i++;
+ }
+
+ zfAggSendAddbaResponse(dev, &bf);
+
+ zfAggAddbaSetTidRx(dev, buf, &bf);
+
+ return ZM_SUCCESS;
+}
+
+u16_t zfAggAddbaSetTidRx(zdev_t* dev, zbuf_t* buf, struct aggBaFrameParameter *bf)
+{
+ u16_t i, ac, aid, fragOff;
+ u16_t src[3];
+ u16_t offset = 0;
+ u8_t up;
+ struct agg_tid_rx *tid_rx = NULL;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
+ src[1] = zmw_rx_buf_readh(dev, buf, offset+12);
+ src[2] = zmw_rx_buf_readh(dev, buf, offset+14);
+ aid = zfApFindSta(dev, src);
+
+ zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
+ ac = zcUpToAc[up&0x7] & 0x3;
+
+ ac = bf->tid;
+
+ for (i=0; i<ZM_AGG_POOL_SIZE ; i++)
+ {
+ if((wd->tid_rx[i]->aid == aid) && (wd->tid_rx[i]->ac == ac))
+ {
+ tid_rx = wd->tid_rx[i];
+ break;
+ }
+ }
+
+ if (!tid_rx)
+ {
+ for (i=0; i<ZM_AGG_POOL_SIZE; i++)
+ {
+ if (wd->tid_rx[i]->aid == ZM_MAX_STA_SUPPORT)
+ {
+ tid_rx = wd->tid_rx[i];
+ break;
+ }
+ }
+ if (!tid_rx)
+ return 0;
+ }
+
+ zmw_enter_critical_section(dev);
+
+ tid_rx->aid = aid;
+ tid_rx->ac = ac;
+ tid_rx->addBaExchangeStatusCode = ZM_AGG_ADDBA_RESPONSE;
+ tid_rx->seq_start = bf->ba_start_seq;
+ tid_rx->baw_head = tid_rx->baw_tail = 0;
+ tid_rx->sq_exceed_count = tid_rx->sq_behind_count = 0;
+ zmw_leave_critical_section(dev);
+
+ return 0;
+}
+
+u16_t zfAggRecvAddbaResponse(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t i,ac, aid=0;
+ u16_t src[3];
+ struct aggBaFrameParameter bf;
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ src[0] = zmw_rx_buf_readh(dev, buf, 10);
+ src[1] = zmw_rx_buf_readh(dev, buf, 12);
+ src[2] = zmw_rx_buf_readh(dev, buf, 14);
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ aid = zfApFindSta(dev, src);
+
+
+ bf.buf = buf;
+ bf.dialog = zmw_rx_buf_readb(dev, buf, 26);
+ bf.status_code = zmw_rx_buf_readh(dev, buf, 27);
+ if (!bf.status_code)
+ {
+ wd->addbaComplete=1;
+ }
+
+ /*
+ * ba parameter set
+ */
+ bf.ba_parameter = zmw_rx_buf_readh(dev, buf, 29);
+ bf.ba_policy = (bf.ba_parameter >> 1) & 1;
+ bf.tid = (bf.ba_parameter >> 2) & 0xF;
+ bf.buffer_size = (bf.ba_parameter >> 6);
+ /*
+ * BA timeout value
+ */
+ bf.ba_timeout = zmw_rx_buf_readh(dev, buf, 31);
+
+ i=26;
+ while(i < 32) {
+ zm_debug_msg2("Recv ADDBA Rsp:", zmw_rx_buf_readb(dev,buf,i));
+ i++;
+ }
+
+ ac = zcUpToAc[bf.tid&0x7] & 0x3;
+
+ //zmw_enter_critical_section(dev);
+
+ //wd->aggSta[aid].aggFlag[ac] = 0;
+
+ //zmw_leave_critical_section(dev);
+
+ return ZM_SUCCESS;
+}
+
+u16_t zfAggRecvDelba(zdev_t* dev, zbuf_t* buf)
+{
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+ return ZM_SUCCESS;
+}
+
+u16_t zfAggSendAddbaResponse(zdev_t* dev, struct aggBaFrameParameter *bf)
+{
+ zbuf_t* buf;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ //u16_t err;
+ u16_t offset = 0;
+ u16_t hlen = 32;
+ u16_t header[(24+25+1)/2];
+ u16_t vap = 0;
+ u16_t i;
+ u8_t encrypt = 0;
+ u16_t dst[3];
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+
+ /*
+ * TBD : Maximum size of managment frame
+ */
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
+ return ZM_SUCCESS;
+ }
+
+ /*
+ * Reserve room for wlan header
+ */
+ offset = hlen;
+
+ /*
+ * add addba frame body
+ */
+ offset = zfAggSetAddbaResponseFrameBody(dev, buf, bf, offset);
+
+
+ zfwBufSetSize(dev, buf, offset);
+
+ /*
+ * Copy wlan header
+ */
+
+ dst[0] = zmw_rx_buf_readh(dev, bf->buf, 10);
+ dst[1] = zmw_rx_buf_readh(dev, bf->buf, 12);
+ dst[2] = zmw_rx_buf_readh(dev, bf->buf, 14);
+ zfAggGenAddbaHeader(dev, dst, header, offset-hlen, buf, vap, encrypt);
+ for (i=0; i<(hlen>>1); i++)
+ {
+ zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
+ }
+
+ /* Get buffer DMA address */
+ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
+ //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
+ //{
+ // goto zlError;
+ //}
+
+ //zm_msg2_mm(ZM_LV_2, "offset=", offset);
+ //zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
+ //zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
+ //zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
+
+ #if 0
+ if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+ #else
+ zfPutVmmq(dev, buf);
+ zfPushVtxq(dev);
+ #endif
+
+ //zfAggSendAddbaRequest(dev, dst, zcUpToAc[bf->tid&0x7] & 0x3, bf->tid);
+ return ZM_SUCCESS;
+
+}
+
+u16_t zfAggSetAddbaResponseFrameBody(zdev_t* dev, zbuf_t* buf,
+ struct aggBaFrameParameter *bf, u16_t offset)
+{
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+ /*
+ * ADDBA Request frame body
+ */
+
+ /*
+ * Category
+ */
+ zmw_tx_buf_writeb(dev, buf, offset++, 3);
+ /*
+ * Action details = 0
+ */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_ADDBA_RESPONSE_FRAME);
+ /*
+ * Dialog Token = nonzero
+ */
+ zmw_tx_buf_writeb(dev, buf, offset++, bf->dialog);
+ /*
+ * Status code
+ */
+ zmw_tx_buf_writeh(dev, buf, offset, 0);
+ offset+=2;
+ /*
+ * Block Ack parameter set
+ * BA policy = 1 for immediate BA, 0 for delayed BA
+ * TID(4bits) & buffer size(4bits) (TID=0x1 & buffer size=0x80)
+ * TBD: how to get TID number and buffer size?
+ * zwwwwwwwwwwswwwwwwwwwwwswwwwwwwwswwwwwwwwwwwww{
+ * x B0 x B1 x B2 B5 x B6 B15 x
+ * uwwwwwwwwwwqwwwwwwwwwwwqwwwwwwwwqwwwwwwwwwwwwwt
+ * x Reserved x BA policy x TID x Buffer size x
+ * |wwwwwwwwwwrwwwwwwwwwwwrwwwwwwwwrwwwwwwwwwwwww}
+ */
+ zmw_tx_buf_writeh(dev, buf, offset, bf->ba_parameter);
+ offset+=2;
+ /*
+ * BA timeout value
+ */
+ zmw_tx_buf_writeh(dev, buf, offset, bf->ba_timeout);
+ offset+=2;
+
+ return offset;
+}
+
+void zfAggInvokeBar(zdev_t* dev, TID_TX tid_tx)
+{
+ struct aggBarControl aggBarControl;
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+ //bar_control = aggBarControl->tid_info << 12 | aggBarControl->compressed_bitmap << 2
+ // | aggBarControl->multi_tid << 1 | aggBarControl->bar_ack_policy;
+ aggBarControl.bar_ack_policy = 0;
+ aggBarControl.multi_tid = 0;
+ aggBarControl.compressed_bitmap = 0;
+ aggBarControl.tid_info = tid_tx->tid;
+ zfAggSendBar(dev, tid_tx, &aggBarControl);
+
+ return;
+
+}
+/*
+ * zfAggSendBar() refers zfAggSendAddbaRequest()
+ */
+u16_t zfAggSendBar(zdev_t* dev, TID_TX tid_tx, struct aggBarControl *aggBarControl)
+{
+ zbuf_t* buf;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ //u16_t err;
+ u16_t offset = 0;
+ u16_t hlen = 16+8; /* mac header + control headers*/
+ u16_t header[(8+24+1)/2];
+ u16_t vap = 0;
+ u16_t i;
+ u8_t encrypt = 0;
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+
+ /*
+ * TBD : Maximum size of managment frame
+ */
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
+ return ZM_SUCCESS;
+ }
+
+ /*
+ * Reserve room for wlan header
+ */
+ offset = hlen;
+
+ /*
+ * add addba frame body
+ */
+ offset = zfAggSetBarBody(dev, buf, offset, tid_tx, aggBarControl);
+
+
+ zfwBufSetSize(dev, buf, offset);
+
+ /*
+ * Copy wlan header
+ */
+ zfAggGenBarHeader(dev, tid_tx->dst, header, offset-hlen, buf, vap, encrypt);
+ for (i=0; i<(hlen>>1); i++)
+ {
+ zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
+ }
+
+ /* Get buffer DMA address */
+ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
+ //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
+ //{
+ // goto zlError;
+ //}
+
+ //zm_msg2_mm(ZM_LV_2, "offset=", offset);
+ //zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
+ //zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
+ //zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
+
+ #if 0
+ if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+ #else
+ zfPutVmmq(dev, buf);
+ zfPushVtxq(dev);
+ #endif
+
+ return ZM_SUCCESS;
+
+}
+
+u16_t zfAggSetBarBody(zdev_t* dev, zbuf_t* buf, u16_t offset, TID_TX tid_tx, struct aggBarControl *aggBarControl)
+{
+ u16_t bar_control, start_seq;
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+ /*
+ * BAR Control frame body
+ */
+
+ /*
+ * BAR Control Field
+ * zwwwwwwwwwswwwwwwwwwwwswwwwwwwwwwwwswwwwwwwwwwswwwwwwwwww{
+ * x B0 x B1 x B2 x B3 B11 x B12 B15 x
+ * uwwwwwwwwwqwwwwwwwwwwwqwwwwwwwwwwwwqwwwwwwwwwwqwwwwwwwwwwt
+ * x BAR Ack x Multi-TID x Compressed x Reserved x TID_INFO x
+ * x Policy x x Bitmap x x x
+ * |wwwwwwwwwrwwwwwwwwwwwrwwwwwwwwwwwwrwwwwwwwwwwrwwwwwwwwww}
+ */
+ bar_control = aggBarControl->tid_info << 12 | aggBarControl->compressed_bitmap << 2
+ | aggBarControl->multi_tid << 1 | aggBarControl->bar_ack_policy;
+
+ zmw_tx_buf_writeh(dev, buf, offset, bar_control);
+ offset+=2;
+ if (0 == aggBarControl->multi_tid) {
+ /*
+ * BA starting sequence number
+ * zwwwwwwwwwwwwwswwwwwwwwwwwwwwwwwwwww{
+ * x B0 B3 x B4 B15 x
+ * uwwwwwwwwwwwwwqwwwwwwwwwwwwwwwwwwwwwt
+ * x Frag num(0) x BA starting seq num x
+ * |wwwwwwwwwwwwwrwwwwwwwwwwwwwwwwwwwww}
+ */
+ start_seq = (tid_tx->bar_ssn << 4) & 0xFFF0;
+ zmw_tx_buf_writeh(dev, buf, offset, start_seq);
+ offset+=2;
+ }
+ if (1 == aggBarControl->multi_tid && 1 == aggBarControl->compressed_bitmap) {
+ /* multi-tid BlockAckReq variant, not implemented*/
+ }
+
+ return offset;
+}
+
+u16_t zfAggGenBarHeader(zdev_t* dev, u16_t* dst,
+ u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt)
+{
+ u8_t hlen = 16+8; // MAC ctrl + PHY ctrl + 802.11 MM header
+ //u8_t frameType = ZM_WLAN_FRAME_TYPE_ACTION;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ /*
+ * Generate control setting
+ */
+ //bodyLen = zfwBufGetSize(dev, buf);
+ header[0] = 16+len+4; //Length
+ header[1] = 0x8; //MAC control, backoff + (ack)
+
+#if 1
+ /* CCK 1M */
+ header[2] = 0x0f00; //PHY control L
+ header[3] = 0x0000; //PHY control H
+#else
+ /* CCK 6M */
+ header[2] = 0x0f01; //PHY control L
+ header[3] = 0x000B; //PHY control H
+
+#endif
+ /*
+ * Generate WLAN header
+ * Frame control frame type and subtype
+ */
+ header[4+0] = ZM_WLAN_FRAME_TYPE_BAR;
+ /*
+ * Duration
+ */
+ header[4+1] = 0;
+
+ /* Address 1 = DA */
+ header[4+2] = dst[0];
+ header[4+3] = dst[1];
+ header[4+4] = dst[2];
+
+ /* Address 2 = SA */
+ header[4+5] = wd->macAddr[0];
+ header[4+6] = wd->macAddr[1];
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ header[4+7] = wd->macAddr[2]; //Multiple SSID
+#else
+ header[4+7] = wd->macAddr[2] + (vap<<8); //VAP
+#endif
+ }
+ else
+ {
+ header[4+7] = wd->macAddr[2];
+ }
+
+ /* Sequence Control */
+ zmw_enter_critical_section(dev);
+ header[4+11] = ((wd->mmseq++)<<4);
+ zmw_leave_critical_section(dev);
+
+
+ return hlen;
+}
diff --git a/drivers/staging/otus/80211core/cagg.h b/drivers/staging/otus/80211core/cagg.h
new file mode 100644
index 000000000000..1d87a564162b
--- /dev/null
+++ b/drivers/staging/otus/80211core/cagg.h
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : cagg.h */
+/* */
+/* Abstract */
+/* This module contains A-MPDU aggregation relatived functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/****************************************************************************/
+/*Revision History: */
+/* Who When What */
+/* -------- -------- ----------------------------------------------*/
+/* */
+/* Honda 12-4-06 created */
+/* */
+/****************************************************************************/
+
+#ifndef _CAGG_H
+#define _CAGG_H
+
+
+/*
+ * the aggregation functions flag, 0 if don't do aggregate
+ */
+
+#define ZM_AGG_FPGA_DEBUG 1
+#define ZM_AGG_FPGA_REORDERING 1
+
+#ifndef ZM_AGG_TALLY
+//#define ZM_AGG_TALLY
+#endif
+/*
+ * Aggregate control
+ */
+
+
+#define ZM_AGG_POOL_SIZE 20
+#define ZM_BAW_POOL_SIZE 32
+#define ZM_AGGQ_SIZE 64
+#define ZM_AGGQ_SIZE_MASK (ZM_AGGQ_SIZE-1)
+#define ZM_AGG_LOW_THRESHOLD 1
+#define ZM_AGG_HIGH_THRESHOLD 5
+
+/*
+ * number of access categories (ac)
+ */
+#define ZM_AC 4
+/*
+ * the timer to clear aggregation queue, unit: 1 tick
+ * if the packet is too old (current time - arrival time)
+ * the packet and the aggregate queue will be cleared
+ */
+#define ZM_AGG_CLEAR_TIME 10
+/*
+ * delete the queue if idle for ZM_DELETE_TIME
+ * unit: 10ms
+ */
+#define ZM_AGG_DELETE_TIME 10000
+
+/*
+ * block ack window size
+ */
+#define ZM_AGG_BAW_SIZE 64
+#define ZM_AGG_BAW_MASK (ZM_AGG_BAW_SIZE-1)
+/*
+ * originator ADDBA Resquest receiver
+ * |----------------------------->|
+ * 1| ACK |1
+ * |<-----------------------------|
+ * 2| ADDBA Response |2
+ * |<-----------------------------|
+ * 3| ACK |3
+ * |----------------------------->|
+ * 4 4
+ */
+#define ZM_AGG_ADDBA_REQUEST 1
+#define ZM_AGG_ADDBA_REQUEST_ACK 2
+#define ZM_AGG_ADDBA_RESPONSE 3
+#define ZM_AGG_ADDBA_RESPONSE_ACK 4
+
+#define ZM_AGG_SINGLE_MPDU 00
+#define ZM_AGG_FIRST_MPDU 01
+#define ZM_AGG_MIDDLE_MPDU 11
+#define ZM_AGG_LAST_MPDU 10
+/*
+ * end of Aggregate control
+ */
+
+#define TID_TX struct aggQueue*
+#define TID_BAW struct baw_q*
+#define BAW wd->baw_enabler
+#define DESTQ wd->destQ
+
+/*
+ * Queue access
+ */
+#define zm_agg_qlen(dev, head, tail) ((head - tail) & ZM_AGGQ_SIZE_MASK)
+#define zm_agg_inQ(tid_tx, pt) ((((pt - tid_tx->aggTail) & ZM_AGGQ_SIZE_MASK) < \
+ ((tid_tx->aggHead - tid_tx->aggTail) & ZM_AGGQ_SIZE_MASK))? TRUE:FALSE)
+#define zm_agg_plus(pt) pt = (pt + 1) & ZM_AGGQ_SIZE_MASK
+#define zm_agg_min(A, B) ((A>B)? B:A)
+#define zm_agg_GetTime() wd->tick
+#define TXQL (zfHpGetMaxTxdCount(dev) - zfHpGetFreeTxdCount(dev))
+
+/* don't change AGG_MIN_TXQL easily, this might cause BAW BSOD */
+#define AGG_MIN_TXQL 2
+/*
+ * consider tcp,udp,ac(1234)
+ */
+#define zm_agg_dynamic_threshold(dev, ar) ((ar > 16)? 11: \
+ (ar > 12)? 8: \
+ (ar > 8)? 5: \
+ (ar > 4)? 2:1)
+#define zm_agg_weight(ac) ((3 == ac)? 4: \
+ (2 == ac)? 3: \
+ (0 == ac)? 2:1)
+/*
+ * the required free queue ratio per ac
+ */
+
+#define zm_agg_ratio(ac) ((3 == ac)? 3: \
+ (2 == ac)? (zfHpGetMaxTxdCount(dev)*1/4): \
+ (0 == ac)? (zfHpGetMaxTxdCount(dev)*2/4): \
+ (zfHpGetMaxTxdCount(dev)*3/4))
+
+//#define zm_agg_ratio(ac) 3
+/*
+ * end of Queue access
+ */
+
+#define ZM_AGGMSG_LEV ZM_LV_3
+#define zm_msg0_agg(lv, msg) if (ZM_AGGMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_agg(lv, msg, val) if (ZM_AGGMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_agg(lv, msg, val) if (ZM_AGGMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+struct baw_header_r {
+ u16_t *header;
+ u16_t *mic;
+ u16_t *snap;
+ u16_t headerLen;
+ u16_t micLen;
+ u16_t snapLen;
+ u16_t removeLen;
+ u8_t keyIdx;
+};
+
+struct baw_header {
+ u16_t header[29];//[(8+30+2+18)/2]; 58 bytes /* ctr+(4+a1+a2+a3+2+a4)+qos+iv */
+ u16_t headerLen;
+ u16_t mic[4]; //[8/2]; 8 bytes
+ u16_t micLen;
+ u16_t snap[4]; //[8/2]; 8 bytes
+ u16_t snapLen;
+ u16_t removeLen;
+ u8_t keyIdx;
+};
+
+struct bufInfo {
+ zbuf_t* buf;
+ u8_t baw_retransmit;
+ u32_t timestamp;
+ struct baw_header *baw_header;
+};
+#endif
+struct aggElement
+{
+ zbuf_t* buf;
+ u32_t arrivalTime;
+ u8_t baw_retransmit;
+ struct zsAdditionInfo addInfo;
+ //struct baw_header baw_header;
+};
+
+
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+struct baw_buf
+{
+ zbuf_t* buf;
+ u16_t baw_seq;
+ u32_t timestamp;
+ u8_t baw_retransmit;
+ struct baw_header baw_header;
+};
+
+struct baw_q {
+ struct baw_buf frame[ZM_VTXQ_SIZE];
+ u16_t enabled;
+ u16_t start_seq;
+ u16_t head;
+ u16_t tail;
+ u16_t size;
+ TID_TX tid_tx;
+
+ //struct baw_header *baw_header;
+};
+
+struct baw_enabler
+{
+ struct baw_q tid_baw[ZM_BAW_POOL_SIZE];
+ u8_t delPoint;
+ void (*core)(zdev_t* dev, u16_t baw_seq, u32_t bitmap, u16_t aggLen);
+ //void (*core);
+ void (*init)(zdev_t* dev);
+ TID_BAW (*getNewQ)(zdev_t* dev, u16_t start_seq, TID_TX tid_tx);
+ TID_BAW (*getQ)(zdev_t* dev, u16_t baw_seq);
+ u16_t (*insert)(zdev_t* dev, zbuf_t* buf, u16_t baw_seq, TID_BAW tid_baw, u8_t baw_retransmit, struct baw_header_r *header_r);
+ struct bufInfo* (*pop)(zdev_t* dev, u16_t index, TID_BAW tid_baw);
+ void (*enable)(zdev_t* dev, TID_BAW tid_baw, u16_t start_seq);
+ void (*disable)(zdev_t* dev, TID_BAW tid_baw);
+
+};
+#endif
+struct aggQueue
+{
+ struct aggElement aggvtxq[ZM_AGGQ_SIZE];
+ u16_t aggHead;
+ u16_t aggTail;
+ s16_t size;
+ u16_t aggQSTA;
+ u16_t aggQEnabled;
+ u16_t ac;
+ u16_t tid;
+ u16_t aggReady;
+ u16_t clearFlag;
+ u16_t deleteFlag;
+ u32_t lastArrival;
+ u16_t aggFrameSize;
+ u16_t bar_ssn; /* starting sequence number in BAR */
+ u16_t dst[3];
+ u16_t complete; /* complete indication pointer */
+};
+
+struct aggSta
+{
+ u16_t count[ZM_AC];
+ TID_TX tid_tx[8];
+ u16_t aggFlag[ZM_AC];
+};
+
+struct agg_tid_rx
+{
+ u16_t aid;
+ u16_t ac;
+ u16_t addBaExchangeStatusCode;
+ //struct zsAdditionInfo *addInfo;
+ u16_t seq_start; /* first seq expected next */
+ u16_t baw_head; /* head of valid block ack window */
+ u16_t baw_tail; /* tail of valid block ack window */
+ //u16_t free_count; /* block ack window size */
+ u8_t sq_exceed_count;
+ u8_t sq_behind_count;
+ struct aggElement frame[ZM_AGG_BAW_SIZE + 1]; /* out-of-order rx frames */
+};
+
+struct aggControl
+{
+ u16_t aggEnabled;
+ u16_t ampduIndication;
+ u16_t addbaIndication;
+ //TID_BAW tid_baw;
+ u32_t timestamp;
+};
+
+struct aggBaFrameParameter
+{
+ zbuf_t* buf;
+ u16_t ba_parameter;
+ u8_t dialog;
+ u16_t ba_policy;
+ u16_t tid;
+ u16_t buffer_size;
+ u16_t ba_timeout;
+ u16_t ba_start_seq;
+ u16_t status_code;
+};
+
+struct aggBarControl
+{
+ u16_t bar_ack_policy ;
+ u16_t multi_tid ;
+ u16_t compressed_bitmap ;
+ u16_t tid_info ;
+};
+
+struct aggTally
+{
+ u32_t got_packets_sum;
+ u32_t got_bytes_sum;
+ u32_t sent_packets_sum;
+ u32_t sent_bytes_sum;
+ u32_t avg_got_packets;
+ u32_t avg_got_bytes;
+ u32_t avg_sent_packets;
+ u32_t avg_sent_bytes;
+ u16_t time;
+};
+
+
+struct destQ {
+ struct dest{
+ u16_t Qtype : 1; /* 0 aggr, 1 vtxq */
+ TID_TX tid_tx;
+ void* vtxq;
+
+ struct dest* next;
+ } *dest[4];
+ struct dest* Head[4];
+ //s16_t size[4];
+ u16_t ppri;
+ void (*insert)(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq);
+ void (*delete)(zdev_t* dev, u16_t Qtype, TID_TX tid_tx, void* vtxq);
+ void (*init)(zdev_t* dev);
+ struct dest* (*getNext)(zdev_t* dev, u16_t ac);
+ u16_t (*exist)(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq);
+ //void (*scan)(zdev_t* dev);
+};
+/*
+ * aggregation tx
+ */
+void zfAggInit(zdev_t* dev);
+u16_t zfApFindSta(zdev_t* dev, u16_t* addr);
+u16_t zfAggGetSta(zdev_t* dev, zbuf_t* buf);
+TID_TX zfAggTxGetQueue(zdev_t* dev, u16_t aid, u16_t tid);
+TID_TX zfAggTxNewQueue(zdev_t* dev, u16_t aid, u16_t tid, zbuf_t* buf);
+u16_t zfAggTxEnqueue(zdev_t* dev, zbuf_t* buf, u16_t aid, TID_TX tid_tx);
+u16_t zfAggTx(zdev_t* dev, zbuf_t* buf, u16_t tid);
+u16_t zfAggTxReadyCount(zdev_t* dev, u16_t ac);
+u16_t zfAggTxPartial(zdev_t* dev, u16_t ac, u16_t readycount);
+u16_t zfAggTxSend(zdev_t* dev, u32_t freeTxd, TID_TX tid_tx);
+TID_TX zfAggTxGetReadyQueue(zdev_t* dev, u16_t ac);
+zbuf_t* zfAggTxGetVtxq(zdev_t* dev, TID_TX tid_tx);
+u16_t zfAggTxDeleteQueue(zdev_t* dev, u16_t qnum);
+u16_t zfAggScanAndClear(zdev_t* dev, u32_t time);
+u16_t zfAggClearQueue(zdev_t* dev);
+void zfAggTxScheduler(zdev_t* dev, u8_t ScanAndClear);
+
+/* tid_tx manipulation */
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+u16_t zfAggTidTxInsertHead(zdev_t* dev, struct bufInfo* buf_info, TID_TX tid_tx);
+#endif
+void zfAggDestInsert(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq);
+void zfAggDestDelete(zdev_t* dev, u16_t Qtype, TID_TX tid_tx, void* vtxq);
+void zfAggDestInit(zdev_t* dev);
+struct dest* zfAggDestGetNext(zdev_t* dev, u16_t ac);
+u16_t zfAggDestExist(zdev_t* dev, u16_t Qtype, u16_t ac, TID_TX tid_tx, void* vtxq);
+/*
+ * aggregation rx
+ */
+struct agg_tid_rx *zfAggRxEnabled(zdev_t* dev, zbuf_t* buf);
+u16_t zfAggRx(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo *addInfo, struct agg_tid_rx *tid_rx);
+struct agg_tid_rx *zfAggRxGetQueue(zdev_t* dev, zbuf_t* buf);
+u16_t zfAggRxEnqueue(zdev_t* dev, zbuf_t* buf, struct agg_tid_rx *tid_rx, struct zsAdditionInfo *addInfo);
+u16_t zfAggRxFlush(zdev_t* dev, u16_t seq_no, struct agg_tid_rx *tid_rx);
+u16_t zfAggRxFreeBuf(zdev_t* dev, u16_t destroy);
+u16_t zfAggRxClear(zdev_t* dev, u32_t time);
+void zfAggRecvBAR(zdev_t* dev, zbuf_t* buf);
+/*
+ * end of aggregation rx
+ */
+
+/*
+ * ADDBA
+ */
+u16_t zfAggSendAddbaRequest(zdev_t* dev, u16_t *dst, u16_t ac, u16_t up);
+u16_t zfAggSetAddbaFrameBody(zdev_t* dev,zbuf_t* buf, u16_t offset, u16_t ac, u16_t up);
+u16_t zfAggGenAddbaHeader(zdev_t* dev, u16_t* dst,
+ u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt);
+u16_t zfAggProcessAction(zdev_t* dev, zbuf_t* buf);
+u16_t zfAggBlockAckActionFrame(zdev_t* dev, zbuf_t* buf);
+u16_t zfAggRecvAddbaRequest(zdev_t* dev, zbuf_t* buf);
+u16_t zfAggRecvAddbaResponse(zdev_t* dev, zbuf_t* buf);
+u16_t zfAggRecvDelba(zdev_t* dev, zbuf_t* buf);
+u16_t zfAggSendAddbaResponse(zdev_t* dev, struct aggBaFrameParameter *bf);
+u16_t zfAggSetAddbaResponseFrameBody(zdev_t* dev, zbuf_t* buf,
+ struct aggBaFrameParameter *bf, u16_t offset);
+u16_t zfAggAddbaSetTidRx(zdev_t* dev, zbuf_t* buf,
+ struct aggBaFrameParameter *bf);
+/*
+ * zfAggTxSendEth
+ */
+u16_t zfAggTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u8_t flag, struct aggControl *aggControl, TID_TX tid_tx);
+
+/*
+ * statistics functions
+ */
+u16_t zfAggTallyReset(zdev_t* dev);
+
+u16_t zfAggPrintTally(zdev_t* dev);
+
+/*
+ * BAR
+ */
+void zfAggInvokeBar(zdev_t* dev, TID_TX tid_tx);
+u16_t zfAggSendBar(zdev_t* dev, TID_TX tid_tx, struct aggBarControl *aggBarControl);
+u16_t zfAggSetBarBody(zdev_t* dev, zbuf_t* buf, u16_t offset, TID_TX tid_tx, struct aggBarControl *aggBarControl);
+u16_t zfAggGenBarHeader(zdev_t* dev, u16_t* dst,
+ u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt);
+
+#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION //disable BAW
+/* BAW BA retransmission */
+void zfBawCore(zdev_t* dev, u16_t baw_seq, u32_t bitmap, u16_t aggLen);
+void zfBawInit(zdev_t* dev);
+TID_BAW zfBawGetNewQ(zdev_t* dev, u16_t start_seq, TID_TX tid_tx);
+u16_t zfBawInsert(zdev_t* dev, zbuf_t* buf, u16_t baw_seq, TID_BAW tid_baw, u8_t baw_retransmit, struct baw_header_r *header_r);
+struct bufInfo* zfBawPop(zdev_t* dev, u16_t index, TID_BAW tid_baw);
+void zfBawEnable(zdev_t* dev, TID_BAW tid_baw, u16_t start_seq);
+void zfBawDisable(zdev_t* dev, TID_BAW tid_baw);
+TID_BAW zfBawGetQ(zdev_t* dev, u16_t baw_seq);
+void zfAggTxRetransmit(zdev_t* dev, struct bufInfo *buf_info, struct aggControl *aggControl, TID_TX tid_tx);
+#endif
+/* extern functions */
+extern zbuf_t* zfGetVtxq(zdev_t* dev, u8_t ac);
+
+#endif /* #ifndef _CAGG_H */
+
diff --git a/drivers/staging/otus/80211core/ccmd.c b/drivers/staging/otus/80211core/ccmd.c
new file mode 100644
index 000000000000..479977973671
--- /dev/null
+++ b/drivers/staging/otus/80211core/ccmd.c
@@ -0,0 +1,1861 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : cmd.c */
+/* */
+/* Abstract */
+/* This module contains command interface functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#include "../hal/hpreg.h"
+
+
+u16_t zfWlanReset(zdev_t* dev);
+u32_t zfUpdateRxRate(zdev_t* dev);
+
+
+extern void zfiUsbRecv(zdev_t *dev, zbuf_t *buf);
+extern void zfiUsbRegIn(zdev_t* dev, u32_t* rsp, u16_t rspLen);
+extern void zfiUsbOutComplete(zdev_t* dev, zbuf_t *buf, u8_t status, u8_t *hdr);
+extern void zfiUsbRegOutComplete(zdev_t* dev);
+extern u16_t zfHpReinit(zdev_t* dev, u32_t frequency);
+
+/* Get size (byte) of driver core global data structure. */
+/* This size will be used by driver wrapper to allocate */
+/* a memory space for driver core to store global variables */
+u16_t zfiGlobalDataSize(zdev_t* dev)
+{
+ u32_t ret;
+ ret = (sizeof(struct zsWlanDev));
+ zm_assert((ret>>16) == 0);
+ return (u16_t)ret;
+}
+
+
+/* Initialize WLAN hardware and software, resource will be allocated */
+/* for WLAN operation, must be called first before other function. */
+extern u16_t zfiWlanOpen(zdev_t* dev, struct zsCbFuncTbl* cbFuncTbl)
+{
+ //u16_t ret;
+ //u32_t i;
+ //u8_t* ch;
+ //u8_t bPassive;
+ u32_t devSize;
+ struct zfCbUsbFuncTbl cbUsbFuncTbl;
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg0("start");
+
+ devSize = sizeof(struct zsWlanDev);
+ /* Zeroize zsWlanDev struct */
+ zfZeroMemory((u8_t*)wd, (u16_t)devSize);
+
+#ifdef ZM_ENABLE_AGGREGATION
+ zfAggInit(dev);
+#endif
+
+ zfCwmInit(dev);
+
+ wd->commTally.RateCtrlTxMPDU = 0;
+ wd->commTally.RateCtrlBAFail = 0;
+ wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT;
+
+ if (cbFuncTbl == NULL)
+ {
+ /* zfcbRecvEth() is mandatory */
+ zm_assert(0);
+ }
+ else
+ {
+ if (cbFuncTbl->zfcbRecvEth == NULL)
+ {
+ /* zfcbRecvEth() is mandatory */
+ zm_assert(0);
+ }
+ wd->zfcbAuthNotify = cbFuncTbl->zfcbAuthNotify;
+ wd->zfcbAuthNotify = cbFuncTbl->zfcbAuthNotify;
+ wd->zfcbAsocNotify = cbFuncTbl->zfcbAsocNotify;
+ wd->zfcbDisAsocNotify = cbFuncTbl->zfcbDisAsocNotify;
+ wd->zfcbApConnectNotify = cbFuncTbl->zfcbApConnectNotify;
+ wd->zfcbConnectNotify = cbFuncTbl->zfcbConnectNotify;
+ wd->zfcbScanNotify = cbFuncTbl->zfcbScanNotify;
+ wd->zfcbMicFailureNotify = cbFuncTbl->zfcbMicFailureNotify;
+ wd->zfcbApMicFailureNotify = cbFuncTbl->zfcbApMicFailureNotify;
+ wd->zfcbIbssPartnerNotify = cbFuncTbl->zfcbIbssPartnerNotify;
+ wd->zfcbMacAddressNotify = cbFuncTbl->zfcbMacAddressNotify;
+ wd->zfcbSendCompleteIndication = cbFuncTbl->zfcbSendCompleteIndication;
+ wd->zfcbRecvEth = cbFuncTbl->zfcbRecvEth;
+ wd->zfcbRestoreBufData = cbFuncTbl->zfcbRestoreBufData;
+ wd->zfcbRecv80211 = cbFuncTbl->zfcbRecv80211;
+#ifdef ZM_ENABLE_CENC
+ wd->zfcbCencAsocNotify = cbFuncTbl->zfcbCencAsocNotify;
+#endif //ZM_ENABLE_CENC
+ wd->zfcbClassifyTxPacket = cbFuncTbl->zfcbClassifyTxPacket;
+ wd->zfcbHwWatchDogNotify = cbFuncTbl->zfcbHwWatchDogNotify;
+ }
+
+ //add by honda 0330
+ cbUsbFuncTbl.zfcbUsbRecv = zfiUsbRecv;
+ cbUsbFuncTbl.zfcbUsbRegIn = zfiUsbRegIn;
+ cbUsbFuncTbl.zfcbUsbOutComplete = zfiUsbOutComplete;
+ cbUsbFuncTbl.zfcbUsbRegOutComplete = zfiUsbRegOutComplete;
+ zfwUsbRegisterCallBack(dev, &cbUsbFuncTbl);
+ /* Init OWN MAC address */
+ wd->macAddr[0] = 0x8000;
+ wd->macAddr[1] = 0x0000;
+ wd->macAddr[2] = 0x0000;
+
+ wd->regulationTable.regionCode = 0xffff;
+
+ zfHpInit(dev, wd->frequency);
+
+ /* init region code */
+ //wd->regulationTable.regionCode = NULL1_WORLD; //Only 2.4g RegCode
+ //zfHpGetRegulationTablefromRegionCode(dev, NULL1_WORLD);
+ //zfiWlanSetDot11DMode(dev , 1); // Enable 802.11d
+ /* Get the first channel */
+ //wd->frequency = zfChGetFirstChannel(dev, &bPassive);
+#ifdef ZM_AP_DEBUG
+ //wd->frequency = 2437;
+#endif
+
+ //STA mode
+ wd->sta.mTxRate = 0x0;
+ wd->sta.uTxRate = 0x3;
+ wd->sta.mmTxRate = 0x0;
+ wd->sta.adapterState = ZM_STA_STATE_DISCONNECT;
+ wd->sta.capability[0] = 0x01;
+ wd->sta.capability[1] = 0x00;
+
+ wd->sta.preambleTypeHT = 0;
+ wd->sta.htCtrlBandwidth = 0;
+ wd->sta.htCtrlSTBC = 0;
+ wd->sta.htCtrlSG = 0;
+ wd->sta.defaultTA = 0;
+ //wd->sta.activescanTickPerChannel = ZM_TIME_ACTIVE_SCAN/ZM_MS_PER_TICK;
+ {
+ u8_t Dur = ZM_TIME_ACTIVE_SCAN;
+ zfwGetActiveScanDur(dev, &Dur);
+ wd->sta.activescanTickPerChannel = Dur/ZM_MS_PER_TICK;
+
+ }
+ wd->sta.passiveScanTickPerChannel = ZM_TIME_PASSIVE_SCAN/ZM_MS_PER_TICK;
+ wd->sta.bAutoReconnect = TRUE;
+ wd->sta.dropUnencryptedPkts = FALSE;
+
+ /* set default to bypass all multicast packet for linux, window XP would set 0 by wrapper initialization */
+ wd->sta.bAllMulticast = 1;
+
+ /* Initial the RIFS Status / RIFS-like frame count / RIFS count */
+ wd->sta.rifsState = ZM_RIFS_STATE_DETECTING;
+ wd->sta.rifsLikeFrameCnt = 0;
+ wd->sta.rifsCount = 0;
+
+ wd->sta.osRxFilter = 0;
+ wd->sta.bSafeMode = 0;
+
+ //Common
+ zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_DISCONNECT);
+ wd->beaconInterval = 100;
+ wd->rtsThreshold = 2346;
+ wd->fragThreshold = 32767;
+ wd->wlanMode = ZM_MODE_INFRASTRUCTURE;
+ wd->txMCS = 0xff; //AUTO
+ wd->dtim = 1;
+ //wd->txMT = 1; //OFDM
+ wd->tick = 1;
+ wd->maxTxPower2 = 0xff;
+ wd->maxTxPower5 = 0xff;
+ wd->supportMode = 0xffffffff;
+ wd->ws.adhocMode = ZM_ADHOCBAND_G;
+ wd->ws.autoSetFrequency = 0xff;
+
+ //AP mode
+ //wd->bgMode = wd->ws.bgMode;
+ wd->ap.ssidLen[0] = 6;
+ wd->ap.ssid[0][0] = 'Z';
+ wd->ap.ssid[0][1] = 'D';
+ wd->ap.ssid[0][2] = '1';
+ wd->ap.ssid[0][3] = '2';
+ wd->ap.ssid[0][4] = '2';
+ wd->ap.ssid[0][5] = '1';
+
+ // Init the country iso name as NA
+ wd->ws.countryIsoName[0] = 0;
+ wd->ws.countryIsoName[1] = 0;
+ wd->ws.countryIsoName[2] = '\0';
+
+ /* init fragmentation is disabled */
+ //zfiWlanSetFragThreshold(dev, 0);
+
+ /* airopeek : swSniffer 1=>on 0=>off */
+ wd->swSniffer = 0;
+ wd->XLinkMode = 0;
+
+// jhlee HT 0
+#if 1
+ /* AP Mode*/
+ /* Init HT Capability Info */
+ wd->ap.HTCap.Data.ElementID = ZM_WLAN_EID_HT_CAPABILITY;
+ wd->ap.HTCap.Data.Length = 26;
+ //wd->ap.HTCap.Data.SupChannelWidthSet = 0;
+ //wd->ap.HTCap.Data.MIMOPowerSave = 3;
+ //wd->ap.HTCap.Data.ShortGIfor40MHz = 0;
+ //wd->ap.HTCap.Data.ShortGIfor20MHz = 0;
+ //wd->ap.HTCap.Data.DSSSandCCKin40MHz = 0;
+ wd->ap.HTCap.Data.AMPDUParam |= HTCAP_MaxRxAMPDU3;
+ wd->ap.HTCap.Data.MCSSet[0] = 0xFF; // MCS 0 ~ 7
+ wd->ap.HTCap.Data.MCSSet[1] = 0xFF; // MCS 8 ~ 15
+
+ /* Init Extended HT Capability Info */
+ wd->ap.ExtHTCap.Data.ElementID = ZM_WLAN_EID_EXTENDED_HT_CAPABILITY;
+ wd->ap.ExtHTCap.Data.Length = 22;
+ wd->ap.ExtHTCap.Data.ControlChannel = 6;
+ //wd->ap.ExtHTCap.Data.ExtChannelOffset = 3;
+ wd->ap.ExtHTCap.Data.ChannelInfo |= ExtHtCap_RecomTxWidthSet;
+ //wd->ap.ExtHTCap.Data.RIFSMode = 1;
+ wd->ap.ExtHTCap.Data.OperatingInfo |= 1;
+
+ /* STA Mode*/
+ /* Init HT Capability Info */
+ wd->sta.HTCap.Data.ElementID = ZM_WLAN_EID_HT_CAPABILITY;
+ wd->sta.HTCap.Data.Length = 26;
+
+ /* Test with 5G-AP : 7603 */
+ //wd->sta.HTCap.Data.SupChannelWidthSet = 1;
+ wd->sta.HTCap.Data.HtCapInfo |= HTCAP_SMEnabled;
+ wd->sta.HTCap.Data.HtCapInfo |= HTCAP_SupChannelWidthSet;
+ wd->sta.HTCap.Data.HtCapInfo |= HTCAP_ShortGIfor40MHz;
+ wd->sta.HTCap.Data.HtCapInfo |= HTCAP_DSSSandCCKin40MHz;
+#ifndef ZM_DISABLE_AMSDU8K_SUPPORT
+ wd->sta.HTCap.Data.HtCapInfo |= HTCAP_MaxAMSDULength;
+#endif
+ //wd->sta.HTCap.Data.MIMOPowerSave = 0;
+ //wd->sta.HTCap.Data.ShortGIfor40MHz = 0;
+ //wd->sta.HTCap.Data.ShortGIfor20MHz = 0;
+ //wd->sta.HTCap.Data.DSSSandCCKin40MHz = 0;
+ wd->sta.HTCap.Data.AMPDUParam |= HTCAP_MaxRxAMPDU3;
+ wd->sta.HTCap.Data.MCSSet[0] = 0xFF; // MCS 0 ~ 7
+ wd->sta.HTCap.Data.MCSSet[1] = 0xFF; // MCS 8 ~ 15
+ wd->sta.HTCap.Data.PCO |= HTCAP_TransmissionTime3;
+ //wd->sta.HTCap.Data.TransmissionTime = 0;
+ /* Init Extended HT Capability Info */
+ wd->sta.ExtHTCap.Data.ElementID = ZM_WLAN_EID_EXTENDED_HT_CAPABILITY;
+ wd->sta.ExtHTCap.Data.Length = 22;
+ wd->sta.ExtHTCap.Data.ControlChannel = 6;
+
+ //wd->sta.ExtHTCap.Data.ExtChannelOffset |= 3;
+ wd->sta.ExtHTCap.Data.ChannelInfo |= ExtHtCap_ExtChannelOffsetBelow;
+
+ //wd->sta.ExtHTCap.Data.RecomTxWidthSet = 1;
+ //wd->sta.ExtHTCap.Data.RIFSMode = 1;
+ wd->sta.ExtHTCap.Data.OperatingInfo |= 1;
+#endif
+
+#if 0
+ /* WME test code */
+ wd->ap.qosMode[0] = 1;
+#endif
+
+ wd->ledStruct.ledMode[0] = 0x2221;
+ wd->ledStruct.ledMode[1] = 0x2221;
+
+ zfTimerInit(dev);
+
+ ZM_PERFORMANCE_INIT(dev);
+
+ zfBssInfoCreate(dev);
+ zfScanMgrInit(dev);
+ zfPowerSavingMgrInit(dev);
+
+#if 0
+ /* Test code */
+ {
+ u32_t key[4] = {0xffffffff, 0xff, 0, 0};
+ u16_t addr[3] = {0x8000, 0x01ab, 0x0000};
+ //zfSetKey(dev, 0, 0, ZM_WEP64, addr, key);
+ //zfSetKey(dev, 0, 0, ZM_AES, addr, key);
+ //zfSetKey(dev, 64, 0, 1, wd->macAddr, key);
+ }
+#endif
+
+ // WME settings
+ wd->ws.staWmeEnabled = 1; // Enable WME by default
+ #define ZM_UAPSD_Q_SIZE 32 //2^N
+ wd->ap.uapsdQ = zfQueueCreate(dev, ZM_UAPSD_Q_SIZE);
+ zm_assert(wd->ap.uapsdQ != NULL);
+ wd->sta.uapsdQ = zfQueueCreate(dev, ZM_UAPSD_Q_SIZE);
+ zm_assert(wd->sta.uapsdQ != NULL);
+
+ //zfHpInit(dev, wd->frequency);
+
+ /* MAC address */
+ //zfHpSetMacAddress(dev, wd->macAddr, 0);
+ zfHpGetMacAddress(dev);
+
+ zfCoreSetFrequency(dev, wd->frequency);
+
+#if ZM_PCI_LOOP_BACK == 1
+ zfwWriteReg(dev, ZM_REG_PCI_CONTROL, 6);
+#endif /* #if ZM_PCI_LOOP_BACK == 1 */
+
+ //zfiWlanSetDot11DMode(dev , 1); // Enable 802.11d
+ //zfiWlanSetDot11HDFSMode(dev , 1); // Enable 802.11h DFS
+ wd->sta.DFSEnable = 1;
+ wd->sta.capability[1] |= ZM_BIT_0;
+
+ //zfiWlanSetFrequency(dev, 5260000, TRUE);
+ //zfiWlanSetAniMode(dev , 1); // Enable ANI
+
+ /* Trgger Rx DMA */
+ zfHpStartRecv(dev);
+
+ zm_debug_msg0("end");
+
+ return 0;
+}
+
+/* WLAN hardware will be shutdown and all resource will be release */
+u16_t zfiWlanClose(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zm_msg0_init(ZM_LV_0, "enter");
+
+ wd->state = ZM_WLAN_STATE_CLOSEDED;
+
+ //zfiWlanDisable(dev, 1);
+ zfWlanReset(dev);
+
+ zfHpStopRecv(dev);
+
+ /* Disable MAC */
+ /* Disable PHY */
+ /* Disable RF */
+
+ zfHpRelease(dev);
+
+ zfQueueDestroy(dev, wd->ap.uapsdQ);
+ zfQueueDestroy(dev, wd->sta.uapsdQ);
+
+ zfBssInfoDestroy(dev);
+
+#ifdef ZM_ENABLE_AGGREGATION
+ /* add by honda */
+ zfAggRxFreeBuf(dev, 1); //1 for release structure memory
+ /* end of add by honda */
+#endif
+
+ zm_msg0_init(ZM_LV_0, "exit");
+
+ return 0;
+}
+
+void zfGetWrapperSetting(zdev_t* dev)
+{
+ u8_t bPassive;
+ u16_t vapId = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+#if 0
+ if ( (wd->ws.countryIsoName[0] != 0)
+ || (wd->ws.countryIsoName[1] != 0)
+ || (wd->ws.countryIsoName[2] != '\0') )
+ {
+ zfHpGetRegulationTablefromRegionCode(
+ dev,
+ zfHpGetRegionCodeFromIsoName(dev, wd->ws.countryIsoName) );
+ }
+#endif
+ zmw_enter_critical_section(dev);
+
+ wd->wlanMode = wd->ws.wlanMode;
+
+ /* set channel */
+ if ( wd->ws.frequency )
+ {
+ wd->frequency = wd->ws.frequency;
+ wd->ws.frequency = 0;
+ }
+ else
+ {
+ wd->frequency = zfChGetFirstChannel(dev, &bPassive);
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ if (wd->ws.adhocMode == ZM_ADHOCBAND_A)
+ {
+ wd->frequency = ZM_CH_A_36;
+ }
+ else
+ {
+ wd->frequency = ZM_CH_G_6;
+ }
+ }
+ }
+#ifdef ZM_AP_DEBUG
+ /* honda add for debug, 2437 channel 6, 2452 channel 9 */
+ wd->frequency = 2437;
+ /* end of add by honda */
+#endif
+
+ /* set preamble type */
+ switch (wd->ws.preambleType)
+ {
+ case ZM_PREAMBLE_TYPE_AUTO:
+ case ZM_PREAMBLE_TYPE_SHORT:
+ case ZM_PREAMBLE_TYPE_LONG:
+ wd->preambleType = wd->ws.preambleType;
+ break;
+ default:
+ wd->preambleType = ZM_PREAMBLE_TYPE_SHORT;
+ break;
+ }
+ wd->ws.preambleType = 0;
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ vapId = zfwGetVapId(dev);
+
+ if (vapId == 0xffff)
+ {
+ wd->ap.authAlgo[0] = wd->ws.authMode;
+ wd->ap.encryMode[0] = wd->ws.encryMode;
+ }
+ else
+ {
+ wd->ap.authAlgo[vapId + 1] = wd->ws.authMode;
+ wd->ap.encryMode[vapId + 1] = wd->ws.encryMode;
+ }
+ wd->ws.authMode = 0;
+ wd->ws.encryMode = ZM_NO_WEP;
+
+ /* Get beaconInterval from WrapperSetting */
+ if ((wd->ws.beaconInterval >= 20) && (wd->ws.beaconInterval <= 1000))
+ {
+ wd->beaconInterval = wd->ws.beaconInterval;
+ }
+ else
+ {
+ wd->beaconInterval = 100; //100ms
+ }
+
+ if (wd->ws.dtim > 0)
+ {
+ wd->dtim = wd->ws.dtim;
+ }
+ else
+ {
+ wd->dtim = 1;
+ }
+
+ wd->ap.qosMode = wd->ws.apWmeEnabled & 0x1;
+ wd->ap.uapsdEnabled = (wd->ws.apWmeEnabled & 0x2) >> 1;
+ }
+ else
+ {
+ wd->sta.authMode = wd->ws.authMode;
+ wd->sta.currentAuthMode = wd->ws.authMode;
+ wd->sta.wepStatus = wd->ws.wepStatus;
+
+ if ( wd->ws.beaconInterval )
+ {
+ wd->beaconInterval = wd->ws.beaconInterval;
+ }
+ else
+ {
+ wd->beaconInterval = 0x64;
+ }
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ /* 1. Set default channel 6 (2437MHz) */
+// wd->frequency = 2437;
+
+ /* 2. Otus support 802.11g Mode */
+ if ((wd->ws.adhocMode == ZM_ADHOCBAND_G) ||
+ (wd->ws.adhocMode == ZM_ADHOCBAND_BG) ||
+ (wd->ws.adhocMode == ZM_ADHOCBAND_ABG) ) {
+ wd->wfc.bIbssGMode = 1;
+ } else {
+ wd->wfc.bIbssGMode = 0;
+ }
+
+ /* 3. set short preamble */
+ //wd->sta.preambleType = ZM_PREAMBLE_TYPE_SHORT ;
+ }
+
+ /* set ATIM window */
+ if ( wd->ws.atimWindow )
+ {
+ wd->sta.atimWindow = wd->ws.atimWindow;
+ }
+ else
+ {
+ //wd->sta.atimWindow = 0x0a;
+ wd->sta.atimWindow = 0;
+ }
+
+ //wd->sta.connectingHiddenAP = 1;//wd->ws.connectingHiddenAP;
+ wd->sta.dropUnencryptedPkts = wd->ws.dropUnencryptedPkts;
+ wd->sta.ibssJoinOnly = wd->ws.ibssJoinOnly;
+
+ if ( wd->ws.bDesiredBssid )
+ {
+ zfMemoryCopy(wd->sta.desiredBssid, wd->ws.desiredBssid, 6);
+ wd->sta.bDesiredBssid = TRUE;
+ wd->ws.bDesiredBssid = FALSE;
+ }
+ else
+ {
+ wd->sta.bDesiredBssid = FALSE;
+ }
+
+ /* check ssid */
+ if ( wd->ws.ssidLen != 0 )
+ {
+ if ( (!zfMemoryIsEqual(wd->ws.ssid, wd->sta.ssid,
+ wd->sta.ssidLen))||
+ (wd->ws.ssidLen != wd->sta.ssidLen)||
+ (wd->sta.authMode == ZM_AUTH_MODE_WPA)||
+ (wd->sta.authMode == ZM_AUTH_MODE_WPAPSK) ||
+ (wd->ws.staWmeQosInfo!= 0) )
+ {
+ /*if u-APSD test(set QosInfo), clear connectByReasso to do association (not reassociation)*/
+ wd->sta.connectByReasso = FALSE;
+ wd->sta.failCntOfReasso = 0;
+ wd->sta.pmkidInfo.bssidCount = 0;
+
+ wd->sta.ssidLen = wd->ws.ssidLen;
+ zfMemoryCopy(wd->sta.ssid, wd->ws.ssid, wd->sta.ssidLen);
+
+ if ( wd->sta.ssidLen < 32 )
+ {
+ wd->sta.ssid[wd->sta.ssidLen] = 0;
+ }
+ }
+ }
+ else
+ { /* ANY BSS */
+ wd->sta.ssid[0] = 0;
+ wd->sta.ssidLen = 0;
+ }
+
+ wd->sta.wmeEnabled = wd->ws.staWmeEnabled;
+ wd->sta.wmeQosInfo = wd->ws.staWmeQosInfo;
+
+ }
+
+ zmw_leave_critical_section(dev);
+}
+
+u16_t zfWlanEnable(zdev_t* dev)
+{
+ u8_t bssid[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( wd->wlanMode == ZM_MODE_UNKNOWN )
+ {
+ zm_debug_msg0("Unknown Mode...Skip...");
+ return 0;
+ }
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ u16_t vapId;
+
+ vapId = zfwGetVapId(dev);
+
+ if (vapId == 0xffff)
+ {
+ /* AP mode */
+ zfApInitStaTbl(dev);
+
+ /* AP default parameters */
+ wd->bRate = 0xf;
+ wd->gRate = 0xff;
+ wd->bRateBasic = 0xf;
+ wd->gRateBasic = 0x0;
+ //wd->beaconInterval = 100;
+ wd->ap.apBitmap = 1;
+ wd->ap.beaconCounter = 0;
+ //wd->ap.vapNumber = 1; //mark by ygwei for Vap
+
+ wd->ap.hideSsid[0] = 0;
+ wd->ap.staAgingTimeSec = 10*60;
+ wd->ap.staProbingTimeSec = 60;
+
+ for (i=0; i<ZM_MAX_AP_SUPPORT; i++)
+ {
+ wd->ap.bcmcHead[i] = wd->ap.bcmcTail[i] = 0;
+ }
+
+ //wd->ap.uniHead = wd->ap.uniTail = 0;
+
+ /* load AP parameters */
+ wd->bRateBasic = wd->ws.bRateBasic;
+ wd->gRateBasic = wd->ws.gRateBasic;
+ wd->bgMode = wd->ws.bgMode;
+ if ((wd->ws.ssidLen <= 32) && (wd->ws.ssidLen != 0))
+ {
+ wd->ap.ssidLen[0] = wd->ws.ssidLen;
+ for(i=0; i<wd->ws.ssidLen; i++)
+ {
+ wd->ap.ssid[0][i] = wd->ws.ssid[i];
+ }
+ wd->ws.ssidLen = 0; // Reset Wrapper Variable
+ }
+
+ if (wd->ap.encryMode[0] == 0)
+ {
+ wd->ap.capab[0] = 0x001;
+ }
+ else
+ {
+ wd->ap.capab[0] = 0x011;
+ }
+ /* set Short Slot Time bit if not 11b */
+ if (wd->ap.wlanType[0] != ZM_WLAN_TYPE_PURE_B)
+ {
+ wd->ap.capab[0] |= 0x400;
+ }
+
+ // wd->ap.vapNumber = 1; // mark by ygwei for Vap Test
+ }
+ else
+ {
+#if 0
+ /* VAP Test Code */
+ wd->ap.apBitmap = 0x3;
+ wd->ap.capab[1] = 0x401;
+ wd->ap.ssidLen[1] = 4;
+ wd->ap.ssid[1][0] = 'v';
+ wd->ap.ssid[1][1] = 'a';
+ wd->ap.ssid[1][2] = 'p';
+ wd->ap.ssid[1][3] = '1';
+ wd->ap.authAlgo[1] = wd->ws.authMode;
+ wd->ap.encryMode[1] = wd->ws.encryMode;
+ wd->ap.vapNumber = 2;
+#else
+ /* VAP Test Code */
+ wd->ap.apBitmap = 0x1 | (0x01 << (vapId+1));
+
+ if ((wd->ws.ssidLen <= 32) && (wd->ws.ssidLen != 0))
+ {
+ wd->ap.ssidLen[vapId+1] = wd->ws.ssidLen;
+ for(i=0; i<wd->ws.ssidLen; i++)
+ {
+ wd->ap.ssid[vapId+1][i] = wd->ws.ssid[i];
+ }
+ wd->ws.ssidLen = 0; // Reset Wrapper Variable
+ }
+
+ if (wd->ap.encryMode[vapId+1] == 0)
+ {
+ wd->ap.capab[vapId+1] = 0x401;
+ }
+ else
+ {
+ wd->ap.capab[vapId+1] = 0x411;
+ }
+
+ wd->ap.authAlgo[vapId+1] = wd->ws.authMode;
+ wd->ap.encryMode[vapId+1] = wd->ws.encryMode;
+
+ /* Need to be modified when VAP is used */
+ //wd->ap.vapNumber = 2;
+#endif
+ }
+
+ wd->ap.vapNumber++;
+
+ zfCoreSetFrequency(dev, wd->frequency);
+
+ zfInitMacApMode(dev);
+
+ /* Disable protection mode */
+ zfApSetProtectionMode(dev, 0);
+
+ zfApSendBeacon(dev);
+ } /*if (wd->wlanMode == ZM_MODE_AP) */
+ else
+ {
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_EXTERNAL);
+
+ zmw_enter_critical_section(dev);
+ wd->sta.oppositeCount = 0; /* reset opposite count */
+ //wd->sta.bAutoReconnect = wd->sta.bAutoReconnectEnabled;
+ //wd->sta.scanWithSSID = 0;
+ zfStaInitOppositeInfo(dev);
+ zmw_leave_critical_section(dev);
+
+ zfStaResetStatus(dev, 0);
+
+ if ( (wd->sta.cmDisallowSsidLength != 0)&&
+ (wd->sta.ssidLen == wd->sta.cmDisallowSsidLength)&&
+ (zfMemoryIsEqual(wd->sta.ssid, wd->sta.cmDisallowSsid,
+ wd->sta.ssidLen)) &&
+ (wd->sta.wepStatus == ZM_ENCRYPTION_TKIP))
+ { /* countermeasures */
+ zm_debug_msg0("countermeasures disallow association");
+
+ }
+ else
+ {
+ switch( wd->wlanMode )
+ {
+ case ZM_MODE_IBSS:
+ /* some registers may be set here */
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
+ {
+ zfHpSetApStaMode(dev, ZM_HAL_80211_MODE_IBSS_WPA2PSK);
+ }
+ else
+ {
+ zfHpSetApStaMode(dev, ZM_HAL_80211_MODE_IBSS_GENERAL);
+ }
+
+ zm_msg0_mm(ZM_LV_0, "ZM_MODE_IBSS");
+ zfIbssConnectNetwork(dev);
+ break;
+
+ case ZM_MODE_INFRASTRUCTURE:
+ /* some registers may be set here */
+ zfHpSetApStaMode(dev, ZM_HAL_80211_MODE_STA);
+
+ zfInfraConnectNetwork(dev);
+ break;
+
+ case ZM_MODE_PSEUDO:
+ /* some registers may be set here */
+ zfHpSetApStaMode(dev, ZM_HAL_80211_MODE_STA);
+
+ zfUpdateBssid(dev, bssid);
+ zfCoreSetFrequency(dev, wd->frequency);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ }
+
+
+ //if ( (wd->wlanMode != ZM_MODE_INFRASTRUCTURE)&&
+ // (wd->wlanMode != ZM_MODE_AP) )
+ if ( wd->wlanMode == ZM_MODE_PSEUDO )
+ {
+ /* Reset Wlan status */
+ zfWlanReset(dev);
+
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid);
+ }
+ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED);
+ }
+
+
+ if(wd->wlanMode == ZM_MODE_AP)
+ {
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid);
+ }
+ //zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED);
+ }
+
+ // Assign default Tx Rate
+ if ( wd->sta.EnableHT )
+ {
+ u32_t oneTxStreamCap;
+ oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM);
+ if(oneTxStreamCap)
+ wd->CurrentTxRateKbps = 135000;
+ else
+ wd->CurrentTxRateKbps = 270000;
+ wd->CurrentRxRateKbps = 270000;
+ }
+ else
+ {
+ wd->CurrentTxRateKbps = 54000;
+ wd->CurrentRxRateKbps = 54000;
+ }
+
+ wd->state = ZM_WLAN_STATE_ENABLED;
+
+ return 0;
+}
+
+/* Enable/disable Wlan operation */
+u16_t zfiWlanEnable(zdev_t* dev)
+{
+ u16_t ret;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_msg0_mm(ZM_LV_1, "Enable Wlan");
+
+ zfGetWrapperSetting(dev);
+
+ zfZeroMemory((u8_t*) &wd->trafTally, sizeof(struct zsTrafTally));
+
+ // Reset cmMicFailureCount to 0 for new association request
+ if ( wd->sta.cmMicFailureCount == 1 )
+ {
+ zfTimerCancel(dev, ZM_EVENT_CM_TIMER);
+ wd->sta.cmMicFailureCount = 0;
+ }
+
+ zfFlushVtxq(dev);
+ if ((wd->queueFlushed & 0x10) != 0)
+ {
+ zfHpUsbReset(dev);
+ }
+ ret = zfWlanEnable(dev);
+
+ return ret;
+}
+/* Add a flag named ResetKeyCache to show if KeyCache should be cleared.
+ for hostapd in AP mode, if driver receives iwconfig ioctl
+ after setting group key, it shouldn't clear KeyCache. */
+u16_t zfiWlanDisable(zdev_t* dev, u8_t ResetKeyCache)
+{
+ u16_t i;
+ u8_t isConnected;
+
+ zmw_get_wlan_dev(dev);
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ zmw_declare_for_critical_section();
+#endif
+ wd->state = ZM_WLAN_STATE_DISABLED;
+
+ zm_msg0_mm(ZM_LV_1, "Disable Wlan");
+
+ if ( wd->wlanMode != ZM_MODE_AP )
+ {
+ isConnected = zfStaIsConnected(dev);
+
+ if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)&&
+ (wd->sta.currentAuthMode != ZM_AUTH_MODE_WPA2) )
+ {
+ /* send deauthentication frame */
+ if (isConnected)
+ {
+ //zfiWlanDeauth(dev, NULL, 0);
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, wd->sta.bssid, 3, 0, 0);
+ //zmw_debug_msg0("send a Deauth frame!");
+ }
+ }
+
+ // Remove all the connected peer stations
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ wd->sta.ibssBssIsCreator = 0;
+ zfTimerCancel(dev, ZM_EVENT_IBSS_MONITOR);
+ zfStaIbssMonitoring(dev, 1);
+ }
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssWpa2Psk = 0;
+ zmw_leave_critical_section(dev);
+#endif
+
+ wd->sta.wpaState = ZM_STA_WPA_STATE_INIT;
+
+ /* reset connect timeout counter */
+ wd->sta.connectTimeoutCount = 0;
+
+ /* reset connectState to None */
+ wd->sta.connectState = ZM_STA_CONN_STATE_NONE;
+
+ /* reset leap enable variable */
+ wd->sta.leapEnabled = 0;
+
+ /* Disable the RIFS Status / RIFS-like frame count / RIFS count */
+ if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTED )
+ zfHpDisableRifs(dev);
+ wd->sta.rifsState = ZM_RIFS_STATE_DETECTING;
+ wd->sta.rifsLikeFrameCnt = 0;
+ wd->sta.rifsCount = 0;
+
+ wd->sta.osRxFilter = 0;
+ wd->sta.bSafeMode = 0;
+
+ zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT);
+ if (ResetKeyCache)
+ zfHpResetKeyCache(dev);
+
+ if (isConnected)
+ {
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECTION_DISABLED, wd->sta.bssid);
+ }
+ }
+ else
+ {
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_DISABLED, wd->sta.bssid);
+ }
+ }
+ }
+ else //if (wd->wlanMode == ZM_MODE_AP)
+ {
+ for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
+ {
+ /* send deauthentication frame */
+ if (wd->ap.staTable[i].valid == 1)
+ {
+ /* Reason : Sending station is leaving */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH,
+ wd->ap.staTable[i].addr, 3, 0, 0);
+ }
+ }
+
+ if (ResetKeyCache)
+ zfHpResetKeyCache(dev);
+
+ wd->ap.vapNumber--;
+ }
+
+ /* stop beacon */
+ zfHpDisableBeacon(dev);
+
+ /* Flush VTxQ and MmQ */
+ zfFlushVtxq(dev);
+ /* Flush AP PS queues */
+ zfApFlushBufferedPsFrame(dev);
+ /* Free buffer in defragment list*/
+ zfAgingDefragList(dev, 1);
+
+ #ifdef ZM_ENABLE_AGGREGATION
+ /* add by honda */
+ zfAggRxFreeBuf(dev, 0); //1 for release structure memory
+ /* end of add by honda */
+ #endif
+
+ // Clear the information for the peer stations of IBSS or AP of Station mode
+ zfZeroMemory((u8_t*)wd->sta.oppositeInfo, sizeof(struct zsOppositeInfo) * ZM_MAX_OPPOSITE_COUNT);
+
+ /* Turn off Software WEP/TKIP */
+ if (wd->sta.SWEncryptEnable != 0)
+ {
+ zm_debug_msg0("Disable software encryption");
+ zfStaDisableSWEncryption(dev);
+ }
+
+ /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */
+ //zfHpSetTTSIFSTime(dev, 0x8);
+
+ return 0;
+}
+
+u16_t zfiWlanSuspend(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ // Change the HAL state to init so that any packet can't be transmitted between
+ // resume & HAL reinit. This would cause the chip hang issue in OTUS.
+ zmw_enter_critical_section(dev);
+ wd->halState = ZM_HAL_STATE_INIT;
+ zmw_leave_critical_section(dev);
+
+ return 0;
+}
+
+u16_t zfiWlanResume(zdev_t* dev, u8_t doReconn)
+{
+ u16_t ret;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ /* Redownload firmware, Reinit MAC,PHY,RF */
+ zfHpReinit(dev, wd->frequency);
+
+ //Set channel according to AP's configuration
+ zfCoreSetFrequencyExV2(dev, wd->frequency, wd->BandWidth40,
+ wd->ExtOffset, NULL, 1);
+
+ zfHpSetMacAddress(dev, wd->macAddr, 0);
+
+ /* Start Rx */
+ zfHpStartRecv(dev);
+
+ zfFlushVtxq(dev);
+
+ if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE &&
+ wd->wlanMode != ZM_MODE_IBSS )
+ {
+ return 1;
+ }
+
+ zm_msg0_mm(ZM_LV_1, "Resume Wlan");
+ if ( (zfStaIsConnected(dev)) || (zfStaIsConnecting(dev)) )
+ {
+ if (doReconn == 1)
+ {
+ zm_msg0_mm(ZM_LV_1, "Re-connect...");
+ zmw_enter_critical_section(dev);
+ wd->sta.connectByReasso = FALSE;
+ zmw_leave_critical_section(dev);
+
+ zfWlanEnable(dev);
+ }
+ else if (doReconn == 0)
+ {
+ zfHpSetRollCallTable(dev);
+ }
+ }
+
+ ret = 0;
+
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiWlanFlushAllQueuedBuffers */
+/* Flush Virtual TxQ, MmQ, PS frames and defragment list */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+void zfiWlanFlushAllQueuedBuffers(zdev_t* dev)
+{
+ /* Flush VTxQ and MmQ */
+ zfFlushVtxq(dev);
+ /* Flush AP PS queues */
+ zfApFlushBufferedPsFrame(dev);
+ /* Free buffer in defragment list*/
+ zfAgingDefragList(dev, 1);
+}
+
+/* Do WLAN site survey */
+u16_t zfiWlanScan(zdev_t* dev)
+{
+ u16_t ret = 1;
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg0("");
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ wd->heartBeatNotification |= ZM_BSSID_LIST_SCAN;
+ wd->sta.scanFrequency = 0;
+ //wd->sta.pUpdateBssList->bssCount = 0;
+ ret = 0;
+ }
+ else
+ {
+ #if 0
+ if ( !zfStaBlockWlanScan(dev) )
+ {
+ zm_debug_msg0("scan request");
+ //zfTimerSchedule(dev, ZM_EVENT_SCAN, ZM_TICK_ZERO);
+ ret = 0;
+ goto start_scan;
+ }
+ #else
+ goto start_scan;
+ #endif
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return ret;
+
+start_scan:
+ zmw_leave_critical_section(dev);
+
+ if(wd->ledStruct.LEDCtrlFlagFromReg & ZM_LED_CTRL_FLAG_ALPHA) // flag for Alpha
+ wd->ledStruct.LEDCtrlFlag |= ZM_LED_CTRL_FLAG_ALPHA;
+
+ ret = zfScanMgrScanStart(dev, ZM_SCAN_MGR_SCAN_EXTERNAL);
+
+ zm_debug_msg1("ret = ", ret);
+
+ return ret;
+}
+
+
+/* rate */
+/* 0 : AUTO */
+/* 1 : CCK 1M */
+/* 2 : CCK 2M */
+/* 3 : CCK 5.5M */
+/* 4 : CCK 11M */
+/* 5 : OFDM 6M */
+/* 6 : OFDM 9M */
+/* 7 : OFDM 12M */
+/* 8 : OFDM 18M */
+/* 9 : OFDM 24M */
+/* 10 : OFDM 36M */
+/* 11 : OFDM 48M */
+/* 12 : OFDM 54M */
+/* 13 : MCS 0 */
+/* 28 : MCS 15 */
+u16_t zcRateToMCS[] =
+ {0xff, 0, 1, 2, 3, 0xb, 0xf, 0xa, 0xe, 0x9, 0xd, 0x8, 0xc};
+u16_t zcRateToMT[] = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1};
+
+u16_t zfiWlanSetTxRate(zdev_t* dev, u16_t rate)
+{ // jhlee HT 0
+ zmw_get_wlan_dev(dev);
+
+ if (rate <=12)
+ {
+ wd->txMCS = zcRateToMCS[rate];
+ wd->txMT = zcRateToMT[rate];
+ return ZM_SUCCESS;
+ }
+ else if ((rate<=28)||(rate==13+32))
+ {
+ wd->txMCS = rate - 12 - 1;
+ wd->txMT = 2;
+ return ZM_SUCCESS;
+ }
+
+ return ZM_ERR_INVALID_TX_RATE;
+}
+
+const u32_t zcRateIdToKbps40M[] =
+ {
+ 1000, 2000, 5500, 11000, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
+ 6000, 9000, 12000, 18000, /* 6M 9M 12M 18M , 4 5 6 7*/
+ 24000, 36000, 48000, 54000, /* 24M 36M 48M 54M , 8 9 10 11*/
+ 13500, 27000, 40500, 54000, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
+ 81000, 108000, 121500, 135000, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
+ 27000, 54000, 81000, 108000, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
+ 162000, 216000, 243000, 270000, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
+ 270000, 300000, 150000 /* MCS14SG, MCS15SG, MCS7SG , 28 29 30*/
+ };
+
+const u32_t zcRateIdToKbps20M[] =
+ {
+ 1000, 2000, 5500, 11000, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
+ 6000, 9000, 12000, 18000, /* 6M 9M 12M 18M , 4 5 6 7*/
+ 24000, 36000, 48000, 54000, /* 24M 36M 48M 54M , 8 9 10 11*/
+ 6500, 13000, 19500, 26000, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
+ 39000, 52000, 58500, 65000, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
+ 13000, 26000, 39000, 52000, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
+ 78000, 104000, 117000, 130000, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
+ 130000, 144400, 72200 /* MCS14SG, MCS15SG, MSG7SG , 28 29 30*/
+ };
+
+u32_t zfiWlanQueryTxRate(zdev_t* dev)
+{
+ u8_t rateId = 0xff;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ /* If Tx rate had not been trained, return maximum Tx rate instead */
+ if ((wd->wlanMode == ZM_MODE_INFRASTRUCTURE) && (zfStaIsConnected(dev)))
+ {
+ zmw_enter_critical_section(dev);
+ //Not in fixed rate mode
+ if (wd->txMCS == 0xff)
+ {
+ if ((wd->sta.oppositeInfo[0].rcCell.flag & ZM_RC_TRAINED_BIT) == 0)
+ {
+ rateId = wd->sta.oppositeInfo[0].rcCell.operationRateSet[wd->sta.oppositeInfo[0].rcCell.operationRateCount-1];
+ }
+ else
+ {
+ rateId = wd->sta.oppositeInfo[0].rcCell.operationRateSet[wd->sta.oppositeInfo[0].rcCell.currentRateIndex];
+ }
+ }
+ zmw_leave_critical_section(dev);
+ }
+ if (rateId != 0xff)
+ {
+ if (wd->sta.htCtrlBandwidth)
+ {
+ return zcRateIdToKbps40M[rateId];
+ }
+ else
+ {
+ return zcRateIdToKbps20M[rateId];
+ }
+ }
+ else
+ {
+ return wd->CurrentTxRateKbps;
+ }
+}
+
+void zfWlanUpdateRxRate(zdev_t* dev, struct zsAdditionInfo* addInfo)
+{
+ u32_t rxRateKbps;
+ zmw_get_wlan_dev(dev);
+ //zm_msg1_mm(ZM_LV_0, "addInfo->Tail.Data.RxMacStatus =", addInfo->Tail.Data.RxMacStatus & 0x03);
+
+ /* b5~b4: MPDU indication. */
+ /* 00: Single MPDU. */
+ /* 10: First MPDU of A-MPDU. */
+ /* 11: Middle MPDU of A-MPDU. */
+ /* 01: Last MPDU of A-MPDU. */
+ /* Only First MPDU and Single MPDU have PLCP header */
+ /* First MPDU : (mpduInd & 0x30) == 0x00 */
+ /* Single MPDU : (mpduInd & 0x30) == 0x20 */
+ if ((addInfo->Tail.Data.RxMacStatus & 0x10) == 0)
+ {
+ /* Modulation type */
+ wd->modulationType = addInfo->Tail.Data.RxMacStatus & 0x03;
+ switch(wd->modulationType)
+ {
+ case 0x0: wd->rateField = addInfo->PlcpHeader[0] & 0xff; //CCK mode
+ wd->rxInfo = 0;
+ break;
+ case 0x1: wd->rateField = addInfo->PlcpHeader[0] & 0x0f; //Legacy-OFDM mode
+ wd->rxInfo = 0;
+ break;
+ case 0x2: wd->rateField = addInfo->PlcpHeader[3]; //HT-OFDM mode
+ wd->rxInfo = addInfo->PlcpHeader[6];
+ break;
+ default: break;
+ }
+
+ rxRateKbps = zfUpdateRxRate(dev);
+ if (wd->CurrentRxRateUpdated == 1)
+ {
+ if (rxRateKbps > wd->CurrentRxRateKbps)
+ {
+ wd->CurrentRxRateKbps = rxRateKbps;
+ }
+ }
+ else
+ {
+ wd->CurrentRxRateKbps = rxRateKbps;
+ wd->CurrentRxRateUpdated = 1;
+ }
+ }
+}
+#if 0
+u16_t zcIndextoRateBG[16] = {1000, 2000, 5500, 11000, 0, 0, 0, 0, 48000,
+ 24000, 12000, 6000, 54000, 36000, 18000, 9000};
+u32_t zcIndextoRateN20L[16] = {6500, 13000, 19500, 26000, 39000, 52000, 58500,
+ 65000, 13000, 26000, 39000, 52000, 78000, 104000,
+ 117000, 130000};
+u32_t zcIndextoRateN20S[16] = {7200, 14400, 21700, 28900, 43300, 57800, 65000,
+ 72200, 14400, 28900, 43300, 57800, 86700, 115600,
+ 130000, 144400};
+u32_t zcIndextoRateN40L[16] = {13500, 27000, 40500, 54000, 81000, 108000, 121500,
+ 135000, 27000, 54000, 81000, 108000, 162000, 216000,
+ 243000, 270000};
+u32_t zcIndextoRateN40S[16] = {15000, 30000, 45000, 60000, 90000, 120000, 135000,
+ 150000, 30000, 60000, 90000, 120000, 180000, 240000,
+ 270000, 300000};
+#endif
+
+extern u16_t zcIndextoRateBG[16];
+extern u32_t zcIndextoRateN20L[16];
+extern u32_t zcIndextoRateN20S[16];
+extern u32_t zcIndextoRateN40L[16];
+extern u32_t zcIndextoRateN40S[16];
+
+u32_t zfiWlanQueryRxRate(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->CurrentRxRateUpdated = 0;
+ return wd->CurrentRxRateKbps;
+}
+
+u32_t zfUpdateRxRate(zdev_t* dev)
+{
+ u8_t mcs, bandwidth;
+ u32_t rxRateKbps = 130000;
+ zmw_get_wlan_dev(dev);
+
+ switch (wd->modulationType)
+ {
+ case 0x0: //CCK mode
+ switch (wd->rateField)
+ {
+ case 0x0a: rxRateKbps = 1000;
+ break;
+ case 0x14: rxRateKbps = 2000;
+
+ case 0x37: rxRateKbps = 5500;
+ break;
+ case 0x6e: rxRateKbps = 11000;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x1: //Legacy-OFDM mode
+ if (wd->rateField <= 15)
+ {
+ rxRateKbps = zcIndextoRateBG[wd->rateField];
+ }
+ break;
+ case 0x2: //HT-OFDM mode
+ mcs = wd->rateField & 0x7F;
+ bandwidth = wd->rateField & 0x80;
+ if (mcs <= 15)
+ {
+ if (bandwidth != 0)
+ {
+ if((wd->rxInfo & 0x80) != 0)
+ {
+ /* Short GI 40 MHz MIMO Rate */
+ rxRateKbps = zcIndextoRateN40S[mcs];
+ }
+ else
+ {
+ /* Long GI 40 MHz MIMO Rate */
+ rxRateKbps = zcIndextoRateN40L[mcs];
+ }
+ }
+ else
+ {
+ if((wd->rxInfo & 0x80) != 0)
+ {
+ /* Short GI 20 MHz MIMO Rate */
+ rxRateKbps = zcIndextoRateN20S[mcs];
+ }
+ else
+ {
+ /* Long GI 20 MHz MIMO Rate */
+ rxRateKbps = zcIndextoRateN20L[mcs];
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ //zm_msg1_mm(ZM_LV_0, "wd->CurrentRxRateKbps=", wd->CurrentRxRateKbps);
+
+ // ToDo: use bandwith field to define 40MB
+ return rxRateKbps;
+}
+
+/* Get WLAN stastics */
+u16_t zfiWlanGetStatistics(zdev_t* dev)
+{
+ /* Return link statistics */
+ return 0;
+}
+
+u16_t zfiWlanReset(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->state = ZM_WLAN_STATE_DISABLED;
+
+ return zfWlanReset(dev);
+}
+
+/* Reset WLAN */
+u16_t zfWlanReset(zdev_t* dev)
+{
+ u8_t isConnected;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zm_debug_msg0("zfWlanReset");
+
+ isConnected = zfStaIsConnected(dev);
+
+ //if ( wd->wlanMode != ZM_MODE_AP )
+ {
+ if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)&&
+ (wd->sta.currentAuthMode != ZM_AUTH_MODE_WPA2) )
+ {
+ /* send deauthentication frame */
+ if (isConnected)
+ {
+ //zfiWlanDeauth(dev, NULL, 0);
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, wd->sta.bssid, 3, 0, 0);
+ //zmw_debug_msg0("send a Deauth frame!");
+ }
+ }
+ }
+
+ zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT);
+ zfHpResetKeyCache(dev);
+
+ if (isConnected)
+ {
+ //zfiWlanDisable(dev);
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECTION_RESET, wd->sta.bssid);
+ }
+ }
+ else
+ {
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_RESET, wd->sta.bssid);
+ }
+ }
+
+ /* stop beacon */
+ zfHpDisableBeacon(dev);
+
+ /* Free buffer in defragment list*/
+ zfAgingDefragList(dev, 1);
+
+ /* Flush VTxQ and MmQ */
+ zfFlushVtxq(dev);
+
+ #ifdef ZM_ENABLE_AGGREGATION
+ /* add by honda */
+ zfAggRxFreeBuf(dev, 0); //1 for release structure memory
+ /* end of add by honda */
+ #endif
+
+ zfStaRefreshBlockList(dev, 1);
+
+ zmw_enter_critical_section(dev);
+
+ zfTimerCancel(dev, ZM_EVENT_IBSS_MONITOR);
+ zfTimerCancel(dev, ZM_EVENT_CM_BLOCK_TIMER);
+ zfTimerCancel(dev, ZM_EVENT_CM_DISCONNECT);
+
+ wd->sta.connectState = ZM_STA_CONN_STATE_NONE;
+ wd->sta.connectByReasso = FALSE;
+ wd->sta.cmDisallowSsidLength = 0;
+ wd->sta.bAutoReconnect = 0;
+ wd->sta.InternalScanReq = 0;
+ wd->sta.encryMode = ZM_NO_WEP;
+ wd->sta.wepStatus = ZM_ENCRYPTION_WEP_DISABLED;
+ wd->sta.wpaState = ZM_STA_WPA_STATE_INIT;
+ wd->sta.cmMicFailureCount = 0;
+ wd->sta.ibssBssIsCreator = 0;
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ wd->sta.ibssWpa2Psk = 0;
+#endif
+ /* reset connect timeout counter */
+ wd->sta.connectTimeoutCount = 0;
+
+ /* reset leap enable variable */
+ wd->sta.leapEnabled = 0;
+
+ /* Reset the RIFS Status / RIFS-like frame count / RIFS count */
+ if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTED )
+ zfHpDisableRifs(dev);
+ wd->sta.rifsState = ZM_RIFS_STATE_DETECTING;
+ wd->sta.rifsLikeFrameCnt = 0;
+ wd->sta.rifsCount = 0;
+
+ wd->sta.osRxFilter = 0;
+ wd->sta.bSafeMode = 0;
+
+ // Clear the information for the peer stations of IBSS or AP of Station mode
+ zfZeroMemory((u8_t*)wd->sta.oppositeInfo, sizeof(struct zsOppositeInfo) * ZM_MAX_OPPOSITE_COUNT);
+
+ zmw_leave_critical_section(dev);
+
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_EXTERNAL);
+
+ /* Turn off Software WEP/TKIP */
+ if (wd->sta.SWEncryptEnable != 0)
+ {
+ zm_debug_msg0("Disable software encryption");
+ zfStaDisableSWEncryption(dev);
+ }
+
+ /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */
+ //zfHpSetTTSIFSTime(dev, 0x8);
+
+ /* Keep Pseudo mode */
+ if ( wd->wlanMode != ZM_MODE_PSEUDO )
+ {
+ wd->wlanMode = ZM_MODE_INFRASTRUCTURE;
+ }
+ return 0;
+}
+
+/* Deauthenticate a STA */
+u16_t zfiWlanDeauth(zdev_t* dev, u16_t* macAddr, u16_t reason)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ //u16_t id;
+
+ /*
+ * we will reset all key in zfHpResetKeyCache() when call
+ * zfiWlanDisable(), if we want to reset PairwiseKey for each sta,
+ * need to use a nullAddr to let keyindex not match.
+ * otherwise hardware will still find PairwiseKey when AP change
+ * encryption mode from WPA to WEP
+ */
+
+ /*
+ if ((id = zfApFindSta(dev, macAddr)) != 0xffff)
+ {
+ u32_t key[8];
+ u16_t nullAddr[3] = { 0x0, 0x0, 0x0 };
+
+ if (wd->ap.staTable[i].encryMode != ZM_NO_WEP)
+ {
+ zfHpSetApPairwiseKey(dev, nullAddr,
+ ZM_NO_WEP, &key[0], &key[4], i+1);
+ }
+ //zfHpSetApPairwiseKey(dev, (u16_t *)macAddr,
+ // ZM_NO_WEP, &key[0], &key[4], id+1);
+ wd->ap.staTable[id].encryMode = ZM_NO_WEP;
+ wd->ap.staTable[id].keyIdx = 0xff;
+ }
+ */
+
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, macAddr, reason, 0, 0);
+ }
+ else
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, wd->sta.bssid, 3, 0, 0);
+ }
+
+ /* Issue DEAUTH command to FW */
+ return 0;
+}
+
+
+/* XP packet filter feature : */
+/* 1=>enable: All multicast address packets, not just the ones enumerated in the multicast address list. */
+/* 0=>disable */
+void zfiWlanSetAllMulticast(zdev_t* dev, u32_t setting)
+{
+ zmw_get_wlan_dev(dev);
+ zm_msg1_mm(ZM_LV_0, "sta.bAllMulticast = ", setting);
+ wd->sta.bAllMulticast = (u8_t)setting;
+}
+
+
+/* HT configure API */
+void zfiWlanSetHTCtrl(zdev_t* dev, u32_t *setting, u32_t forceTxTPC)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->preambleType = (u8_t)setting[0];
+ wd->sta.preambleTypeHT = (u8_t)setting[1];
+ wd->sta.htCtrlBandwidth = (u8_t)setting[2];
+ wd->sta.htCtrlSTBC = (u8_t)setting[3];
+ wd->sta.htCtrlSG = (u8_t)setting[4];
+ wd->sta.defaultTA = (u8_t)setting[5];
+ wd->enableAggregation = (u8_t)setting[6];
+ wd->enableWDS = (u8_t)setting[7];
+
+ wd->forceTxTPC = forceTxTPC;
+}
+
+/* FB50 in OS XP, RD private test code */
+void zfiWlanQueryHTCtrl(zdev_t* dev, u32_t *setting, u32_t *forceTxTPC)
+{
+ zmw_get_wlan_dev(dev);
+
+ setting[0] = wd->preambleType;
+ setting[1] = wd->sta.preambleTypeHT;
+ setting[2] = wd->sta.htCtrlBandwidth;
+ setting[3] = wd->sta.htCtrlSTBC;
+ setting[4] = wd->sta.htCtrlSG;
+ setting[5] = wd->sta.defaultTA;
+ setting[6] = wd->enableAggregation;
+ setting[7] = wd->enableWDS;
+
+ *forceTxTPC = wd->forceTxTPC;
+}
+
+void zfiWlanDbg(zdev_t* dev, u8_t setting)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->enableHALDbgInfo = setting;
+}
+
+/* FB50 in OS XP, RD private test code */
+void zfiWlanSetRxPacketDump(zdev_t* dev, u32_t setting)
+{
+ zmw_get_wlan_dev(dev);
+ if (setting)
+ {
+ wd->rxPacketDump = 1; /* enable */
+ }
+ else
+ {
+ wd->rxPacketDump = 0; /* disable */
+ }
+}
+
+
+/* FB50 in OS XP, RD private test code */
+/* Tally */
+void zfiWlanResetTally(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ wd->commTally.txUnicastFrm = 0; //txUnicastFrames
+ wd->commTally.txMulticastFrm = 0; //txMulticastFrames
+ wd->commTally.txUnicastOctets = 0; //txUniOctets byte size
+ wd->commTally.txMulticastOctets = 0; //txMultiOctets byte size
+ wd->commTally.txFrmUpperNDIS = 0;
+ wd->commTally.txFrmDrvMgt = 0;
+ wd->commTally.RetryFailCnt = 0;
+ wd->commTally.Hw_TotalTxFrm = 0; //Hardware total Tx Frame
+ wd->commTally.Hw_RetryCnt = 0; //txMultipleRetriesFrames
+ wd->commTally.Hw_UnderrunCnt = 0;//
+ wd->commTally.DriverRxFrmCnt = 0;//
+ wd->commTally.rxUnicastFrm = 0; //rxUnicastFrames
+ wd->commTally.rxMulticastFrm = 0; //rxMulticastFrames
+ wd->commTally.NotifyNDISRxFrmCnt = 0;//
+ wd->commTally.rxUnicastOctets = 0; //rxUniOctets byte size
+ wd->commTally.rxMulticastOctets = 0; //rxMultiOctets byte size
+ wd->commTally.DriverDiscardedFrm = 0;// Discard by ValidateFrame
+ wd->commTally.LessThanDataMinLen = 0;//
+ wd->commTally.GreaterThanMaxLen = 0;//
+ wd->commTally.DriverDiscardedFrmCauseByMulticastList = 0;
+ wd->commTally.DriverDiscardedFrmCauseByFrmCtrl = 0;
+ wd->commTally.rxNeedFrgFrm = 0; // need more frg frm
+ wd->commTally.DriverRxMgtFrmCnt = 0;
+ wd->commTally.rxBroadcastFrm = 0; //Receive broadcast frame count
+ wd->commTally.rxBroadcastOctets = 0; //Receive broadcast frame byte size
+ wd->commTally.Hw_TotalRxFrm = 0;//
+ wd->commTally.Hw_CRC16Cnt = 0; //rxPLCPCRCErrCnt
+ wd->commTally.Hw_CRC32Cnt = 0; //rxCRC32ErrCnt
+ wd->commTally.Hw_DecrypErr_UNI = 0;//
+ wd->commTally.Hw_DecrypErr_Mul = 0;//
+ wd->commTally.Hw_RxFIFOOverrun = 0;//
+ wd->commTally.Hw_RxTimeOut = 0;
+ wd->commTally.LossAP = 0;//
+
+ wd->commTally.Tx_MPDU = 0;
+ wd->commTally.BA_Fail = 0;
+ wd->commTally.Hw_Tx_AMPDU = 0;
+ wd->commTally.Hw_Tx_MPDU = 0;
+
+ wd->commTally.txQosDropCount[0] = 0;
+ wd->commTally.txQosDropCount[1] = 0;
+ wd->commTally.txQosDropCount[2] = 0;
+ wd->commTally.txQosDropCount[3] = 0;
+ wd->commTally.txQosDropCount[4] = 0;
+
+ wd->commTally.Hw_RxMPDU = 0;
+ wd->commTally.Hw_RxDropMPDU = 0;
+ wd->commTally.Hw_RxDelMPDU = 0;
+
+ wd->commTally.Hw_RxPhyMiscError = 0;
+ wd->commTally.Hw_RxPhyXRError = 0;
+ wd->commTally.Hw_RxPhyOFDMError = 0;
+ wd->commTally.Hw_RxPhyCCKError = 0;
+ wd->commTally.Hw_RxPhyHTError = 0;
+ wd->commTally.Hw_RxPhyTotalCount = 0;
+
+#if (defined(GCCK) && defined(OFDM))
+ wd->commTally.rx11bDataFrame = 0;
+ wd->commTally.rxOFDMDataFrame = 0;
+#endif
+
+ zmw_leave_critical_section(dev);
+}
+
+/* FB50 in OS XP, RD private test code */
+void zfiWlanQueryTally(zdev_t* dev, struct zsCommTally *tally)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ zfMemoryCopy((u8_t*)tally, (u8_t*)&wd->commTally, sizeof(struct zsCommTally));
+ zmw_leave_critical_section(dev);
+}
+void zfiWlanQueryTrafTally(zdev_t* dev, struct zsTrafTally *tally)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ zfMemoryCopy((u8_t*)tally, (u8_t*)&wd->trafTally, sizeof(struct zsTrafTally));
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanQueryMonHalRxInfo(zdev_t* dev, struct zsMonHalRxInfo *monHalRxInfo)
+{
+ zfHpQueryMonHalRxInfo(dev, (u8_t *)monHalRxInfo);
+}
+
+/* parse the modeMDKEnable to DrvCore */
+void zfiDKEnable(zdev_t* dev, u32_t enable)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->modeMDKEnable = enable;
+ zm_debug_msg1("modeMDKEnable = ", wd->modeMDKEnable);
+}
+
+/* airoPeek */
+u32_t zfiWlanQueryPacketTypePromiscuous(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->swSniffer;
+}
+
+/* airoPeek */
+void zfiWlanSetPacketTypePromiscuous(zdev_t* dev, u32_t setValue)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->swSniffer = setValue;
+ zm_msg1_mm(ZM_LV_0, "wd->swSniffer ", wd->swSniffer);
+ if (setValue)
+ {
+ /* write register for sniffer mode */
+ zfHpSetSnifferMode(dev, 1);
+ zm_msg0_mm(ZM_LV_1, "enalbe sniffer mode");
+ }
+ else
+ {
+ zfHpSetSnifferMode(dev, 0);
+ zm_msg0_mm(ZM_LV_0, "disalbe sniffer mode");
+ }
+}
+
+void zfiWlanSetXLinkMode(zdev_t* dev, u32_t setValue)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->XLinkMode = setValue;
+ if (setValue)
+ {
+ /* write register for sniffer mode */
+ zfHpSetSnifferMode(dev, 1);
+ }
+ else
+ {
+ zfHpSetSnifferMode(dev, 0);
+ }
+}
+
+extern void zfStaChannelManagement(zdev_t* dev, u8_t scan);
+void zfiSetChannelManagement(zdev_t* dev, u32_t setting)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch (setting)
+ {
+ case 1:
+ wd->sta.EnableHT = 1;
+ wd->BandWidth40 = 1;
+ wd->ExtOffset = 1;
+ break;
+ case 3:
+ wd->sta.EnableHT = 1;
+ wd->BandWidth40 = 1;
+ wd->ExtOffset = 3;
+ break;
+ case 0:
+ wd->sta.EnableHT = 1;
+ wd->BandWidth40 = 0;
+ wd->ExtOffset = 0;
+ break;
+ default:
+ wd->BandWidth40 = 0;
+ wd->ExtOffset = 0;
+ break;
+
+ }
+ zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
+ wd->ExtOffset, NULL);
+}
+
+void zfiSetRifs(zdev_t* dev, u16_t setting)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.ie.HtInfo.ChannelInfo |= ExtHtCap_RIFSMode;
+ wd->sta.EnableHT = 1;
+ switch (setting)
+ {
+ case 0:
+ wd->sta.HT2040 = 0;
+// zfHpSetRifs(dev, 1, 0, (wd->sta.currentFrequency < 3000)? 1:0);
+ break;
+ case 1:
+ wd->sta.HT2040 = 1;
+// zfHpSetRifs(dev, 1, 1, (wd->sta.currentFrequency < 3000)? 1:0);
+ break;
+ default:
+ wd->sta.HT2040 = 0;
+// zfHpSetRifs(dev, 1, 0, (wd->sta.currentFrequency < 3000)? 1:0);
+ break;
+ }
+}
+
+void zfiCheckRifs(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if(wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_RIFSMode)
+ {
+// zfHpSetRifs(dev, wd->sta.EnableHT, wd->sta.HT2040, (wd->sta.currentFrequency < 3000)? 1:0);
+ }
+}
+
+void zfiSetReorder(zdev_t* dev, u16_t value)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->reorder = value;
+}
+
+void zfiSetSeqDebug(zdev_t* dev, u16_t value)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->seq_debug = value;
+}
diff --git a/drivers/staging/otus/80211core/cfunc.c b/drivers/staging/otus/80211core/cfunc.c
new file mode 100644
index 000000000000..d7c49d7523df
--- /dev/null
+++ b/drivers/staging/otus/80211core/cfunc.c
@@ -0,0 +1,1227 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+
+u8_t zfQueryOppositeRate(zdev_t* dev, u8_t dst_mac[6], u8_t frameType)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* For AP's rate adaption */
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ return 0;
+ }
+
+ /* For STA's rate adaption */
+ if ( (frameType & 0x0c) == ZM_WLAN_DATA_FRAME )
+ {
+ if ( ZM_IS_MULTICAST(dst_mac) )
+ {
+ return wd->sta.mTxRate;
+ }
+ else
+ {
+ return wd->sta.uTxRate;
+ }
+ }
+
+ return wd->sta.mmTxRate;
+}
+
+void zfCopyToIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src,
+ u16_t offset, u16_t length)
+{
+ u16_t i;
+
+ for(i=0; i<length;i++)
+ {
+ zmw_tx_buf_writeb(dev, buf, offset+i, src[i]);
+ }
+}
+
+void zfCopyToRxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src,
+ u16_t offset, u16_t length)
+{
+ u16_t i;
+
+ for(i=0; i<length;i++)
+ {
+ zmw_rx_buf_writeb(dev, buf, offset+i, src[i]);
+ }
+}
+
+void zfCopyFromIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* dst,
+ u16_t offset, u16_t length)
+{
+ u16_t i;
+
+ for(i=0; i<length; i++)
+ {
+ dst[i] = zmw_tx_buf_readb(dev, buf, offset+i);
+ }
+}
+
+void zfCopyFromRxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* dst,
+ u16_t offset, u16_t length)
+{
+ u16_t i;
+
+ for(i=0; i<length; i++)
+ {
+ dst[i] = zmw_rx_buf_readb(dev, buf, offset+i);
+ }
+}
+
+#if 1
+void zfMemoryCopy(u8_t* dst, u8_t* src, u16_t length)
+{
+ zfwMemoryCopy(dst, src, length);
+}
+
+void zfMemoryMove(u8_t* dst, u8_t* src, u16_t length)
+{
+ zfwMemoryMove(dst, src, length);
+}
+
+void zfZeroMemory(u8_t* va, u16_t length)
+{
+ zfwZeroMemory(va, length);
+}
+
+u8_t zfMemoryIsEqual(u8_t* m1, u8_t* m2, u16_t length)
+{
+ return zfwMemoryIsEqual(m1, m2, length);
+}
+#endif
+
+u8_t zfRxBufferEqualToStr(zdev_t* dev, zbuf_t* buf,
+ const u8_t* str, u16_t offset, u16_t length)
+{
+ u16_t i;
+ u8_t ch;
+
+ for(i=0; i<length; i++)
+ {
+ ch = zmw_rx_buf_readb(dev, buf, offset+i);
+ if ( ch != str[i] )
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void zfTxBufferCopy(zdev_t*dev, zbuf_t* dst, zbuf_t* src,
+ u16_t dstOffset, u16_t srcOffset, u16_t length)
+{
+ u16_t i;
+
+ for(i=0; i<length; i++)
+ {
+ zmw_tx_buf_writeb(dev, dst, dstOffset+i,
+ zmw_tx_buf_readb(dev, src, srcOffset+i));
+ }
+}
+
+void zfRxBufferCopy(zdev_t*dev, zbuf_t* dst, zbuf_t* src,
+ u16_t dstOffset, u16_t srcOffset, u16_t length)
+{
+ u16_t i;
+
+ for(i=0; i<length; i++)
+ {
+ zmw_rx_buf_writeb(dev, dst, dstOffset+i,
+ zmw_rx_buf_readb(dev, src, srcOffset+i));
+ }
+}
+
+
+void zfCollectHWTally(zdev_t*dev, u32_t* rsp, u8_t id)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (id == 0)
+ {
+ wd->commTally.Hw_UnderrunCnt += (0xFFFF & rsp[1]);
+ wd->commTally.Hw_TotalRxFrm += rsp[2];
+ wd->commTally.Hw_CRC32Cnt += rsp[3];
+ wd->commTally.Hw_CRC16Cnt += rsp[4];
+ #ifdef ZM_ENABLE_NATIVE_WIFI
+ /* These code are here to satisfy Vista DTM */
+ wd->commTally.Hw_DecrypErr_UNI += ((rsp[5]>50) && (rsp[5]<60))?50:rsp[5];
+ #else
+ wd->commTally.Hw_DecrypErr_UNI += rsp[5];
+ #endif
+ wd->commTally.Hw_RxFIFOOverrun += rsp[6];
+ wd->commTally.Hw_DecrypErr_Mul += rsp[7];
+ wd->commTally.Hw_RetryCnt += rsp[8];
+ wd->commTally.Hw_TotalTxFrm += rsp[9];
+ wd->commTally.Hw_RxTimeOut +=rsp[10];
+
+ wd->commTally.Tx_MPDU += rsp[11];
+ wd->commTally.BA_Fail += rsp[12];
+ wd->commTally.Hw_Tx_AMPDU += rsp[13];
+ wd->commTally.Hw_Tx_MPDU += rsp[14];
+ wd->commTally.RateCtrlTxMPDU += rsp[11];
+ wd->commTally.RateCtrlBAFail += rsp[12];
+ }
+ else
+ {
+ wd->commTally.Hw_RxMPDU += rsp[1];
+ wd->commTally.Hw_RxDropMPDU += rsp[2];
+ wd->commTally.Hw_RxDelMPDU += rsp[3];
+
+ wd->commTally.Hw_RxPhyMiscError += rsp[4];
+ wd->commTally.Hw_RxPhyXRError += rsp[5];
+ wd->commTally.Hw_RxPhyOFDMError += rsp[6];
+ wd->commTally.Hw_RxPhyCCKError += rsp[7];
+ wd->commTally.Hw_RxPhyHTError += rsp[8];
+ wd->commTally.Hw_RxPhyTotalCount += rsp[9];
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (id == 0)
+ {
+ zm_msg1_mm(ZM_LV_1, "rsplen =", rsp[0]);
+ zm_msg1_mm(ZM_LV_1, "Hw_UnderrunCnt = ", (0xFFFF & rsp[1]));
+ zm_msg1_mm(ZM_LV_1, "Hw_TotalRxFrm = ", rsp[2]);
+ zm_msg1_mm(ZM_LV_1, "Hw_CRC32Cnt = ", rsp[3]);
+ zm_msg1_mm(ZM_LV_1, "Hw_CRC16Cnt = ", rsp[4]);
+ zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_UNI = ", rsp[5]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxFIFOOverrun = ", rsp[6]);
+ zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_Mul = ", rsp[7]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RetryCnt = ", rsp[8]);
+ zm_msg1_mm(ZM_LV_1, "Hw_TotalTxFrm = ", rsp[9]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxTimeOut = ", rsp[10]);
+ zm_msg1_mm(ZM_LV_1, "Tx_MPDU = ", rsp[11]);
+ zm_msg1_mm(ZM_LV_1, "BA_Fail = ", rsp[12]);
+ zm_msg1_mm(ZM_LV_1, "Hw_Tx_AMPDU = ", rsp[13]);
+ zm_msg1_mm(ZM_LV_1, "Hw_Tx_MPDU = ", rsp[14]);
+ }
+ else
+ {
+ zm_msg1_mm(ZM_LV_1, "rsplen = ", rsp[0]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxMPDU = ", (0xFFFF & rsp[1]));
+ zm_msg1_mm(ZM_LV_1, "Hw_RxDropMPDU = ", rsp[2]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxDelMPDU = ", rsp[3]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyMiscError = ", rsp[4]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyXRError = ", rsp[5]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyOFDMError = ", rsp[6]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyCCKError = ", rsp[7]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyHTError = ", rsp[8]);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyTotalCount = ", rsp[9]);
+ }
+
+}
+
+/* Timer related functions */
+void zfTimerInit(zdev_t* dev)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg0("");
+
+ wd->timerList.freeCount = ZM_MAX_TIMER_COUNT;
+ wd->timerList.head = &(wd->timerList.list[0]);
+ wd->timerList.tail = &(wd->timerList.list[ZM_MAX_TIMER_COUNT-1]);
+ wd->timerList.head->pre = NULL;
+ wd->timerList.head->next = &(wd->timerList.list[1]);
+ wd->timerList.tail->pre = &(wd->timerList.list[ZM_MAX_TIMER_COUNT-2]);
+ wd->timerList.tail->next = NULL;
+
+ for( i=1; i<(ZM_MAX_TIMER_COUNT-1); i++ )
+ {
+ wd->timerList.list[i].pre = &(wd->timerList.list[i-1]);
+ wd->timerList.list[i].next = &(wd->timerList.list[i+1]);
+ }
+
+ wd->bTimerReady = TRUE;
+}
+
+
+u16_t zfTimerSchedule(zdev_t* dev, u16_t event, u32_t tick)
+{
+ struct zsTimerEntry *pFreeEntry;
+ struct zsTimerEntry *pEntry;
+ u8_t i, count;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->timerList.freeCount == 0 )
+ {
+ zm_debug_msg0("no more timer");
+ return 1;
+ }
+
+ //zm_debug_msg2("event = ", event);
+ //zm_debug_msg1("target tick = ", wd->tick + tick);
+
+ count = ZM_MAX_TIMER_COUNT - wd->timerList.freeCount;
+
+ if ( count == 0 )
+ {
+ wd->timerList.freeCount--;
+ wd->timerList.head->event = event;
+ wd->timerList.head->timer = wd->tick + tick;
+ //zm_debug_msg1("free timer count = ", wd->timerList.freeCount);
+
+ return 0;
+ }
+
+ pFreeEntry = wd->timerList.tail;
+ pFreeEntry->timer = wd->tick + tick;
+ pFreeEntry->event = event;
+ wd->timerList.tail = pFreeEntry->pre;
+ pEntry = wd->timerList.head;
+
+ for( i=0; i<count; i++ )
+ {
+ // prevent from the case of tick overflow
+ if ( ( pEntry->timer > pFreeEntry->timer )&&
+ ((pEntry->timer - pFreeEntry->timer) < 1000000000) )
+ {
+ if ( i != 0 )
+ {
+ pFreeEntry->pre = pEntry->pre;
+ pFreeEntry->pre->next = pFreeEntry;
+ }
+ else
+ {
+ pFreeEntry->pre = NULL;
+ }
+
+ pEntry->pre = pFreeEntry;
+ pFreeEntry->next = pEntry;
+ break;
+ }
+
+ pEntry = pEntry->next;
+ }
+
+ if ( i == 0 )
+ {
+ wd->timerList.head = pFreeEntry;
+ }
+
+ if ( i == count )
+ {
+ pFreeEntry->pre = pEntry->pre;
+ pFreeEntry->pre->next = pFreeEntry;
+ pEntry->pre = pFreeEntry;
+ pFreeEntry->next = pEntry;
+ }
+
+ wd->timerList.freeCount--;
+ //zm_debug_msg1("free timer count = ", wd->timerList.freeCount);
+
+ return 0;
+}
+
+u16_t zfTimerCancel(zdev_t* dev, u16_t event)
+{
+ struct zsTimerEntry *pEntry;
+ u8_t i, count;
+
+ zmw_get_wlan_dev(dev);
+
+ //zm_debug_msg2("event = ", event);
+ //zm_debug_msg1("free timer count(b) = ", wd->timerList.freeCount);
+
+ pEntry = wd->timerList.head;
+ count = ZM_MAX_TIMER_COUNT - wd->timerList.freeCount;
+
+ for( i=0; i<count; i++ )
+ {
+ if ( pEntry->event == event )
+ {
+ if ( pEntry == wd->timerList.head )
+ { /* remove head entry */
+ wd->timerList.head = pEntry->next;
+ wd->timerList.tail->next = pEntry;
+ pEntry->pre = wd->timerList.tail;
+ wd->timerList.tail = pEntry;
+ pEntry = wd->timerList.head;
+ }
+ else
+ { /* remove non-head entry */
+ pEntry->pre->next = pEntry->next;
+ pEntry->next->pre = pEntry->pre;
+ wd->timerList.tail->next = pEntry;
+ pEntry->pre = wd->timerList.tail;
+ wd->timerList.tail = pEntry;
+ pEntry = pEntry->next;
+ }
+
+ wd->timerList.freeCount++;
+ }
+ else
+ {
+ pEntry = pEntry->next;
+ }
+ }
+
+ //zm_debug_msg1("free timer count(a) = ", wd->timerList.freeCount);
+
+ return 0;
+}
+
+void zfTimerClear(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->timerList.freeCount = ZM_MAX_TIMER_COUNT;
+}
+
+u16_t zfTimerCheckAndHandle(zdev_t* dev)
+{
+ struct zsTimerEntry *pEntry;
+ struct zsTimerEntry *pTheLastEntry = NULL;
+ u16_t event[ZM_MAX_TIMER_COUNT];
+ u8_t i, j=0, count;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( !wd->bTimerReady )
+ {
+ return 0;
+ }
+
+ zmw_enter_critical_section(dev);
+
+ pEntry = wd->timerList.head;
+ count = ZM_MAX_TIMER_COUNT - wd->timerList.freeCount;
+
+ for( i=0; i<count; i++ )
+ {
+ // prevent from the case of tick overflow
+ if ( ( pEntry->timer > wd->tick )&&
+ ((pEntry->timer - wd->tick) < 1000000000) )
+ {
+ break;
+ }
+
+ event[j++] = pEntry->event;
+ pTheLastEntry = pEntry;
+ pEntry = pEntry->next;
+ }
+
+ if ( j > 0 )
+ {
+ wd->timerList.tail->next = wd->timerList.head;
+ wd->timerList.head->pre = wd->timerList.tail;
+ wd->timerList.head = pEntry;
+ wd->timerList.tail = pTheLastEntry;
+ wd->timerList.freeCount += j;
+ //zm_debug_msg1("free timer count = ", wd->timerList.freeCount);
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zfProcessEvent(dev, event, j);
+
+ return 0;
+}
+
+u32_t zfCoreSetKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t type,
+ u16_t* mac, u32_t* key)
+{
+ u32_t ret;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->sta.flagKeyChanging++;
+ zm_debug_msg1(" zfCoreSetKey++++ ", wd->sta.flagKeyChanging);
+ zmw_leave_critical_section(dev);
+
+ ret = zfHpSetKey(dev, user, keyId, type, mac, key);
+ return ret;
+}
+
+void zfCoreSetKeyComplete(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+#if 0
+ wd->sta.flagKeyChanging = 0;
+#else
+ if(wd->sta.flagKeyChanging)
+ {
+ zmw_enter_critical_section(dev);
+ wd->sta.flagKeyChanging--;
+ zmw_leave_critical_section(dev);
+ }
+#endif
+ zm_debug_msg1(" zfCoreSetKeyComplete--- ", wd->sta.flagKeyChanging);
+
+ zfPushVtxq(dev);
+}
+
+void zfCoreHalInitComplete(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->halState = ZM_HAL_STATE_RUNNING;
+ zmw_leave_critical_section(dev);
+
+ zfPushVtxq(dev);
+}
+
+void zfCoreMacAddressNotify(zdev_t* dev, u8_t* addr)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->macAddr[0] = addr[0] | ((u16_t)addr[1]<<8);
+ wd->macAddr[1] = addr[2] | ((u16_t)addr[3]<<8);
+ wd->macAddr[2] = addr[4] | ((u16_t)addr[5]<<8);
+
+
+ //zfHpSetMacAddress(dev, wd->macAddr, 0);
+ if (wd->zfcbMacAddressNotify != NULL)
+ {
+ wd->zfcbMacAddressNotify(dev, addr);
+ }
+}
+
+void zfCoreSetIsoName(zdev_t* dev, u8_t* isoName)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.countryIsoName[0] = isoName[0];
+ wd->ws.countryIsoName[1] = isoName[1];
+ wd->ws.countryIsoName[2] = '\0';
+ }
+
+
+extern void zfScanMgrScanEventStart(zdev_t* dev);
+extern u8_t zfScanMgrScanEventTimeout(zdev_t* dev);
+extern void zfScanMgrScanEventRetry(zdev_t* dev);
+
+void zfProcessEvent(zdev_t* dev, u16_t* eventArray, u8_t eventCount)
+{
+ u8_t i, j, bypass = FALSE;
+ u16_t eventBypass[32];
+ u8_t eventBypassCount = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zfZeroMemory((u8_t*) eventBypass, 64);
+
+ for( i=0; i<eventCount; i++ )
+ {
+ for( j=0; j<eventBypassCount; j++ )
+ {
+ if ( eventBypass[j] == eventArray[i] )
+ {
+ bypass = TRUE;
+ break;
+ }
+ }
+
+ if ( bypass )
+ {
+ continue;
+ }
+
+ switch( eventArray[i] )
+ {
+ case ZM_EVENT_SCAN:
+ {
+ zfScanMgrScanEventStart(dev);
+ eventBypass[eventBypassCount++] = ZM_EVENT_IN_SCAN;
+ eventBypass[eventBypassCount++] = ZM_EVENT_TIMEOUT_SCAN;
+ }
+ break;
+
+ case ZM_EVENT_TIMEOUT_SCAN:
+ {
+ u8_t res;
+
+ res = zfScanMgrScanEventTimeout(dev);
+ if ( res == 0 )
+ {
+ eventBypass[eventBypassCount++] = ZM_EVENT_TIMEOUT_SCAN;
+ }
+ else if ( res == 1 )
+ {
+ eventBypass[eventBypassCount++] = ZM_EVENT_IN_SCAN;
+ }
+ }
+ break;
+
+ case ZM_EVENT_IBSS_MONITOR:
+ {
+ zfStaIbssMonitoring(dev, 0);
+ }
+ break;
+
+ case ZM_EVENT_IN_SCAN:
+ {
+ zfScanMgrScanEventRetry(dev);
+ }
+ break;
+
+ case ZM_EVENT_CM_TIMER:
+ {
+ zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_TIMER");
+
+ wd->sta.cmMicFailureCount = 0;
+ }
+ break;
+
+ case ZM_EVENT_CM_DISCONNECT:
+ {
+ zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_DISCONNECT");
+
+ zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT);
+
+ zmw_enter_critical_section(dev);
+ //zfTimerSchedule(dev, ZM_EVENT_CM_BLOCK_TIMER,
+ // ZM_TICK_CM_BLOCK_TIMEOUT);
+
+ /* Timer Resolution on WinXP is 15/16 ms */
+ /* Decrease Time offset for <XP> Counter Measure */
+ zfTimerSchedule(dev, ZM_EVENT_CM_BLOCK_TIMER,
+ ZM_TICK_CM_BLOCK_TIMEOUT - ZM_TICK_CM_BLOCK_TIMEOUT_OFFSET);
+
+ zmw_leave_critical_section(dev);
+ wd->sta.cmMicFailureCount = 0;
+ //zfiWlanDisable(dev);
+ zfHpResetKeyCache(dev);
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_DISCONNECT_MIC_FAIL,
+ wd->sta.bssid);
+ }
+ }
+ break;
+
+ case ZM_EVENT_CM_BLOCK_TIMER:
+ {
+ zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_BLOCK_TIMER");
+
+ //zmw_enter_critical_section(dev);
+ wd->sta.cmDisallowSsidLength = 0;
+ if ( wd->sta.bAutoReconnect )
+ {
+ zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_BLOCK_TIMER:bAutoReconnect!=0");
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ zfScanMgrScanStart(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ }
+ //zmw_leave_critical_section(dev);
+ }
+ break;
+
+ case ZM_EVENT_TIMEOUT_ADDBA:
+ {
+ if (!wd->addbaComplete && (wd->addbaCount < 5))
+ {
+ zfAggSendAddbaRequest(dev, wd->sta.bssid, 0, 0);
+ wd->addbaCount++;
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_ADDBA, 100);
+ }
+ else
+ {
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_ADDBA);
+ }
+ }
+ break;
+
+ #ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
+ case ZM_EVENT_TIMEOUT_PERFORMANCE:
+ {
+ zfiPerformanceRefresh(dev);
+ }
+ break;
+ #endif
+ case ZM_EVENT_SKIP_COUNTERMEASURE:
+ //enable the Countermeasure
+ {
+ zm_debug_msg0("Countermeasure : Enable MIC Check ");
+ wd->TKIP_Group_KeyChanging = 0x0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void zfBssInfoCreate(zdev_t* dev)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ wd->sta.bssList.bssCount = 0;
+ wd->sta.bssList.head = NULL;
+ wd->sta.bssList.tail = NULL;
+ wd->sta.bssInfoArrayHead = 0;
+ wd->sta.bssInfoArrayTail = 0;
+ wd->sta.bssInfoFreeCount = ZM_MAX_BSS;
+
+ for( i=0; i< ZM_MAX_BSS; i++ )
+ {
+ //wd->sta.bssInfoArray[i] = &(wd->sta.bssInfoPool[i]);
+ wd->sta.bssInfoArray[i] = zfwMemAllocate(dev, sizeof(struct zsBssInfo));
+
+ }
+
+ zmw_leave_critical_section(dev);
+}
+
+void zfBssInfoDestroy(zdev_t* dev)
+{
+ u8_t i;
+ zmw_get_wlan_dev(dev);
+
+ zfBssInfoRefresh(dev, 1);
+
+ for( i=0; i< ZM_MAX_BSS; i++ )
+ {
+ if (wd->sta.bssInfoArray[i] != NULL)
+ {
+ zfwMemFree(dev, wd->sta.bssInfoArray[i], sizeof(struct zsBssInfo));
+ }
+ else
+ {
+ zm_assert(0);
+ }
+ }
+ return;
+}
+
+struct zsBssInfo* zfBssInfoAllocate(zdev_t* dev)
+{
+ struct zsBssInfo* pBssInfo;
+
+ zmw_get_wlan_dev(dev);
+
+ if (wd->sta.bssInfoFreeCount == 0)
+ return NULL;
+
+ pBssInfo = wd->sta.bssInfoArray[wd->sta.bssInfoArrayHead];
+ wd->sta.bssInfoArray[wd->sta.bssInfoArrayHead] = NULL;
+ wd->sta.bssInfoArrayHead = (wd->sta.bssInfoArrayHead + 1) & (ZM_MAX_BSS - 1);
+ wd->sta.bssInfoFreeCount--;
+
+ zfZeroMemory((u8_t*)pBssInfo, sizeof(struct zsBssInfo));
+
+ return pBssInfo;
+}
+
+void zfBssInfoFree(zdev_t* dev, struct zsBssInfo* pBssInfo)
+{
+ zmw_get_wlan_dev(dev);
+
+ zm_assert(wd->sta.bssInfoArray[wd->sta.bssInfoArrayTail] == NULL);
+
+ pBssInfo->signalStrength = pBssInfo->signalQuality = 0;
+ pBssInfo->sortValue = 0;
+
+ wd->sta.bssInfoArray[wd->sta.bssInfoArrayTail] = pBssInfo;
+ wd->sta.bssInfoArrayTail = (wd->sta.bssInfoArrayTail + 1) & (ZM_MAX_BSS - 1);
+ wd->sta.bssInfoFreeCount++;
+}
+
+void zfBssInfoReorderList(zdev_t* dev)
+{
+ struct zsBssInfo* pBssInfo = NULL;
+ struct zsBssInfo* pInsBssInfo = NULL;
+ struct zsBssInfo* pNextBssInfo = NULL;
+ struct zsBssInfo* pPreBssInfo = NULL;
+ u8_t i = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (wd->sta.bssList.bssCount > 1)
+ {
+ pInsBssInfo = wd->sta.bssList.head;
+ wd->sta.bssList.tail = pInsBssInfo;
+ pBssInfo = pInsBssInfo->next;
+ pInsBssInfo->next = NULL;
+ while (pBssInfo != NULL)
+ {
+ i = 0;
+ while (1)
+ {
+// if (pBssInfo->signalStrength >= pInsBssInfo->signalStrength)
+ if( pBssInfo->sortValue >= pInsBssInfo->sortValue)
+ {
+ if (i==0)
+ {
+ //Insert BssInfo to head
+ wd->sta.bssList.head = pBssInfo;
+ pNextBssInfo = pBssInfo->next;
+ pBssInfo->next = pInsBssInfo;
+ break;
+ }
+ else
+ {
+ //Insert BssInfo to neither head nor tail
+ pPreBssInfo->next = pBssInfo;
+ pNextBssInfo = pBssInfo->next;
+ pBssInfo->next = pInsBssInfo;
+ break;
+ }
+ }
+ else
+ {
+ if (pInsBssInfo->next != NULL)
+ {
+ //Signal strength smaller than current BssInfo, check next
+ pPreBssInfo = pInsBssInfo;
+ pInsBssInfo = pInsBssInfo->next;
+ }
+ else
+ {
+ //Insert BssInfo to tail
+ pInsBssInfo->next = pBssInfo;
+ pNextBssInfo = pBssInfo->next;
+ wd->sta.bssList.tail = pBssInfo;
+ pBssInfo->next = NULL;
+ break;
+ }
+ }
+ i++;
+ }
+ pBssInfo = pNextBssInfo;
+ pInsBssInfo = wd->sta.bssList.head;
+ }
+ } //if (wd->sta.bssList.bssCount > 1)
+
+ zmw_leave_critical_section(dev);
+}
+
+void zfBssInfoInsertToList(zdev_t* dev, struct zsBssInfo* pBssInfo)
+{
+ zmw_get_wlan_dev(dev);
+
+ zm_assert(pBssInfo);
+
+ //zm_debug_msg2("pBssInfo = ", pBssInfo);
+
+ if ( wd->sta.bssList.bssCount == 0 )
+ {
+ wd->sta.bssList.head = pBssInfo;
+ wd->sta.bssList.tail = pBssInfo;
+ }
+ else
+ {
+ wd->sta.bssList.tail->next = pBssInfo;
+ wd->sta.bssList.tail = pBssInfo;
+ }
+
+ pBssInfo->next = NULL;
+ wd->sta.bssList.bssCount++;
+
+ //zm_debug_msg2("bss count = ", wd->sta.bssList.bssCount);
+}
+
+void zfBssInfoRemoveFromList(zdev_t* dev, struct zsBssInfo* pBssInfo)
+{
+ struct zsBssInfo* pNowBssInfo;
+ struct zsBssInfo* pPreBssInfo = NULL;
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_assert(pBssInfo);
+ zm_assert(wd->sta.bssList.bssCount);
+
+ //zm_debug_msg2("pBssInfo = ", pBssInfo);
+
+ pNowBssInfo = wd->sta.bssList.head;
+
+ for( i=0; i<wd->sta.bssList.bssCount; i++ )
+ {
+ if ( pNowBssInfo == pBssInfo )
+ {
+ if ( i == 0 )
+ { /* remove head */
+ wd->sta.bssList.head = pBssInfo->next;
+ }
+ else
+ {
+ pPreBssInfo->next = pBssInfo->next;
+ }
+
+ if ( i == (wd->sta.bssList.bssCount - 1) )
+ { /* remove tail */
+ wd->sta.bssList.tail = pPreBssInfo;
+ }
+
+ break;
+ }
+
+ pPreBssInfo = pNowBssInfo;
+ pNowBssInfo = pNowBssInfo->next;
+ }
+
+ zm_assert(i != wd->sta.bssList.bssCount);
+ wd->sta.bssList.bssCount--;
+
+ //zm_debug_msg2("bss count = ", wd->sta.bssList.bssCount);
+}
+
+void zfBssInfoRefresh(zdev_t* dev, u16_t mode)
+{
+ struct zsBssInfo* pBssInfo;
+ struct zsBssInfo* pNextBssInfo;
+ u8_t i, bssCount;
+
+ zmw_get_wlan_dev(dev);
+
+ pBssInfo = wd->sta.bssList.head;
+ bssCount = wd->sta.bssList.bssCount;
+
+ for( i=0; i<bssCount; i++ )
+ {
+ if (mode == 1)
+ {
+ pNextBssInfo = pBssInfo->next;
+ zfBssInfoRemoveFromList(dev, pBssInfo);
+ zfBssInfoFree(dev, pBssInfo);
+ pBssInfo = pNextBssInfo;
+ }
+ else
+ {
+ if ( pBssInfo->flag & ZM_BSS_INFO_VALID_BIT )
+ { /* this one must be kept */
+ pBssInfo->flag &= ~ZM_BSS_INFO_VALID_BIT;
+ pBssInfo = pBssInfo->next;
+ }
+ else
+ {
+ #define ZM_BSS_CACHE_TIME_IN_MS 20000
+ if ((wd->tick - pBssInfo->tick) > (ZM_BSS_CACHE_TIME_IN_MS/ZM_MS_PER_TICK))
+ {
+ pNextBssInfo = pBssInfo->next;
+ zfBssInfoRemoveFromList(dev, pBssInfo);
+ zfBssInfoFree(dev, pBssInfo);
+ pBssInfo = pNextBssInfo;
+ }
+ else
+ {
+ pBssInfo = pBssInfo->next;
+ }
+ }
+ }
+ } //for( i=0; i<bssCount; i++ )
+ return;
+}
+
+void zfDumpSSID(u8_t length, u8_t *value)
+{
+ u8_t buf[50];
+ u8_t tmpLength = length;
+
+ if ( tmpLength > 49 )
+ {
+ tmpLength = 49;
+ }
+
+ zfMemoryCopy(buf, value, tmpLength);
+ buf[tmpLength] = '\0';
+ //printk("SSID: %s\n", buf);
+ //zm_debug_msg_s("ssid = ", value);
+}
+
+void zfCoreReinit(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.flagKeyChanging = 0;
+ wd->sta.flagFreqChanging = 0;
+}
+
+void zfGenerateRandomBSSID(zdev_t* dev, u8_t *MACAddr, u8_t *BSSID)
+{
+ //ULONGLONG time;
+ u32_t time;
+
+ zmw_get_wlan_dev(dev);
+
+ time = wd->tick;
+
+ //
+ // Initialize the random BSSID to be the same as MAC address.
+ //
+
+ // RtlCopyMemory(BSSID, MACAddr, sizeof(DOT11_MAC_ADDRESS));
+ zfMemoryCopy(BSSID, MACAddr, 6);
+
+ //
+ // Get the system time in 10 millisecond.
+ //
+
+ // NdisGetCurrentSystemTime((PLARGE_INTEGER)&time);
+ // time /= 100000;
+
+ //
+ // Randomize the first 4 bytes of BSSID.
+ //
+
+ BSSID[0] ^= (u8_t)(time & 0xff);
+ BSSID[0] &= ~0x01; // Turn off multicast bit
+ BSSID[0] |= 0x02; // Turn on local bit
+
+ time >>= 8;
+ BSSID[1] ^= (u8_t)(time & 0xff);
+
+ time >>= 8;
+ BSSID[2] ^= (u8_t)(time & 0xff);
+
+ time >>= 8;
+ BSSID[3] ^= (u8_t)(time & 0xff);
+}
+
+u8_t zfiWlanGetDestAddrFromBuf(zdev_t *dev, zbuf_t *buf, u16_t *macAddr)
+{
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ /* DA */
+ macAddr[0] = zmw_tx_buf_readh(dev, buf, 16);
+ macAddr[1] = zmw_tx_buf_readh(dev, buf, 18);
+ macAddr[2] = zmw_tx_buf_readh(dev, buf, 20);
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ /* DA */
+ macAddr[0] = zmw_tx_buf_readh(dev, buf, 4);
+ macAddr[1] = zmw_tx_buf_readh(dev, buf, 6);
+ macAddr[2] = zmw_tx_buf_readh(dev, buf, 8);
+ }
+ else if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ /* DA */
+ macAddr[0] = zmw_tx_buf_readh(dev, buf, 4);
+ macAddr[1] = zmw_tx_buf_readh(dev, buf, 6);
+ macAddr[2] = zmw_tx_buf_readh(dev, buf, 8);
+ }
+ else
+ {
+ return 1;
+ }
+#else
+ /* DA */
+ macAddr[0] = zmw_tx_buf_readh(dev, buf, 0);
+ macAddr[1] = zmw_tx_buf_readh(dev, buf, 2);
+ macAddr[2] = zmw_tx_buf_readh(dev, buf, 4);
+#endif
+
+ return 0;
+}
+
+/* Leave an empty line below to remove warning message on some compiler */
+
+u16_t zfFindCleanFrequency(zdev_t* dev, u32_t adhocMode)
+{
+ u8_t i, j;
+ u16_t returnChannel;
+ u16_t count_24G = 0, min24GIndex = 0;
+ u16_t count_5G = 0, min5GIndex = 0;
+ u16_t CombinationBssNumberIn24G[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ u16_t BssNumberIn24G[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ u16_t Array_24G[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ u16_t BssNumberIn5G[31] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ u16_t Array_5G[31] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ struct zsBssInfo* pBssInfo;
+
+ zmw_get_wlan_dev(dev);
+
+ if ((pBssInfo = wd->sta.bssList.head) == NULL)
+ {
+ if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G ||
+ adhocMode == ZM_ADHOCBAND_BG || adhocMode == ZM_ADHOCBAND_ABG )
+ {
+ returnChannel = zfChGetFirst2GhzChannel(dev);
+ }
+ else
+ {
+ returnChannel = zfChGetFirst5GhzChannel(dev);
+ }
+
+ return returnChannel;
+ }
+
+ /* #1 Get Allowed Channel following Country Code ! */
+ zmw_declare_for_critical_section();
+ zmw_enter_critical_section(dev);
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel < 3000)
+ { // 2.4GHz
+ Array_24G[count_24G] = wd->regulationTable.allowChannel[i].channel;
+ count_24G++;
+ }
+ else
+ { // 5GHz
+ count_5G++;
+ Array_5G[i] = wd->regulationTable.allowChannel[i].channel;
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+ while( pBssInfo != NULL )
+ {
+ /* #2_1 Count BSS number in some specificed frequency in 2.4GHz band ! */
+ if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G ||
+ adhocMode == ZM_ADHOCBAND_BG || adhocMode == ZM_ADHOCBAND_ABG )
+ {
+ for( i=0; i<=(count_24G+3); i++ )
+ {
+ if( pBssInfo->frequency == Array_24G[i] )
+ { // Array_24G[0] correspond to BssNumberIn24G[2]
+ BssNumberIn24G[pBssInfo->channel+1]++;
+ }
+ }
+ }
+
+ /* #2_2 Count BSS number in some specificed frequency in 5GHz band ! */
+ if( adhocMode == ZM_ADHOCBAND_A || adhocMode == ZM_ADHOCBAND_ABG )
+ {
+ for( i=0; i<count_5G; i++ )
+ { // 5GHz channel is not equal to array index
+ if( pBssInfo->frequency == Array_5G[i] )
+ { // Array_5G[0] correspond to BssNumberIn5G[0]
+ BssNumberIn5G[i]++;
+ }
+ }
+ }
+
+ pBssInfo = pBssInfo->next;
+ }
+
+#if 0
+ for(i=0; i<=(count_24G+3); i++)
+ {
+ printk("2.4GHz Before combin, %d BSS network : %d", i, BssNumberIn24G[i]);
+ }
+
+ for(i=0; i<count_5G; i++)
+ {
+ printk("5GHz Before combin, %d BSS network : %d", i, BssNumberIn5G[i]);
+ }
+#endif
+
+ if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G ||
+ adhocMode == ZM_ADHOCBAND_BG || adhocMode == ZM_ADHOCBAND_ABG )
+ {
+ /* #3_1 Count BSS number that influence the specificed frequency in 2.4GHz ! */
+ for( j=0; j<count_24G; j++ )
+ {
+ CombinationBssNumberIn24G[j] = BssNumberIn24G[j] + BssNumberIn24G[j+1] +
+ BssNumberIn24G[j+2] + BssNumberIn24G[j+3] +
+ BssNumberIn24G[j+4];
+ //printk("After combine, the number of BSS network channel %d is %d",
+ // j , CombinationBssNumberIn24G[j]);
+ }
+
+ /* #4_1 Find the less utilized frequency in 2.4GHz band ! */
+ min24GIndex = zfFindMinimumUtilizationChannelIndex(dev, CombinationBssNumberIn24G, count_24G);
+ }
+
+ /* #4_2 Find the less utilized frequency in 5GHz band ! */
+ if( adhocMode == ZM_ADHOCBAND_A || adhocMode == ZM_ADHOCBAND_ABG )
+ {
+ min5GIndex = zfFindMinimumUtilizationChannelIndex(dev, BssNumberIn5G, count_5G);
+ }
+
+ if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G || adhocMode == ZM_ADHOCBAND_BG )
+ {
+ return Array_24G[min24GIndex];
+ }
+ else if( adhocMode == ZM_ADHOCBAND_A )
+ {
+ return Array_5G[min5GIndex];
+ }
+ else if( adhocMode == ZM_ADHOCBAND_ABG )
+ {
+ if ( CombinationBssNumberIn24G[min24GIndex] <= BssNumberIn5G[min5GIndex] )
+ return Array_24G[min24GIndex];
+ else
+ return Array_5G[min5GIndex];
+ }
+ else
+ return 2412;
+}
+
+u16_t zfFindMinimumUtilizationChannelIndex(zdev_t* dev, u16_t* array, u16_t count)
+{
+ u8_t i;
+ u16_t tempMinIndex, tempMinValue;
+
+ zmw_get_wlan_dev(dev);
+
+ i = 1;
+ tempMinIndex = 0;
+ tempMinValue = array[tempMinIndex];
+ while( i< count )
+ {
+ if( array[i] < tempMinValue )
+ {
+ tempMinValue = array[i];
+ tempMinIndex = i;
+ }
+ i++;
+ }
+
+ return tempMinIndex;
+}
+
+u8_t zfCompareWithBssid(zdev_t* dev, u16_t* bssid)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( zfMemoryIsEqual((u8_t*)bssid, (u8_t*)wd->sta.bssid, 6) )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
diff --git a/drivers/staging/otus/80211core/cfunc.h b/drivers/staging/otus/80211core/cfunc.h
new file mode 100644
index 000000000000..fc7548c39d1b
--- /dev/null
+++ b/drivers/staging/otus/80211core/cfunc.h
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : func_extr.c */
+/* */
+/* Abstract */
+/* This module contains function prototype. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+
+#ifndef _CFUNC_H
+#define _CFUNC_H
+
+#include "queue.h"
+
+/* amsdu.c */
+void zfDeAmsdu(zdev_t* dev, zbuf_t* buf, u16_t vap, u8_t encryMode);
+
+/* cscanmgr.c */
+void zfScanMgrInit(zdev_t* dev);
+u8_t zfScanMgrScanStart(zdev_t* dev, u8_t scanType);
+void zfScanMgrScanStop(zdev_t* dev, u8_t scanType);
+void zfScanMgrScanAck(zdev_t* dev);
+
+/* cpsmgr.c */
+void zfPowerSavingMgrInit(zdev_t* dev);
+void zfPowerSavingMgrSetMode(zdev_t* dev, u8_t mode);
+void zfPowerSavingMgrMain(zdev_t* dev);
+void zfPowerSavingMgrWakeup(zdev_t* dev);
+u8_t zfPowerSavingMgrIsSleeping(zdev_t *dev);
+void zfPowerSavingMgrProcessBeacon(zdev_t* dev, zbuf_t* buf);
+void zfPowerSavingMgrAtimWinExpired(zdev_t* dev);
+void zfPowerSavingMgrConnectNotify(zdev_t *dev);
+void zfPowerSavingMgrPreTBTTInterrupt(zdev_t *dev);
+
+/* ccmd.c */
+u16_t zfWlanEnable(zdev_t* dev);
+
+/* cfunc.c */
+u8_t zfQueryOppositeRate(zdev_t* dev, u8_t dst_mac[6], u8_t frameType);
+void zfCopyToIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src,
+ u16_t offset, u16_t length);
+void zfCopyToRxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src,
+ u16_t offset, u16_t length);
+void zfCopyFromIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* dst,
+ u16_t offset, u16_t length);
+void zfCopyFromRxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* dst,
+ u16_t offset, u16_t length);
+void zfMemoryCopy(u8_t* dst, u8_t* src, u16_t length);
+void zfMemoryMove(u8_t* dst, u8_t* src, u16_t length);
+void zfZeroMemory(u8_t* va, u16_t length);
+u8_t zfMemoryIsEqual(u8_t* m1, u8_t* m2, u16_t length);
+u8_t zfRxBufferEqualToStr(zdev_t* dev, zbuf_t* buf, const u8_t* str,
+ u16_t offset, u16_t length);
+void zfTxBufferCopy(zdev_t*dev, zbuf_t* dst, zbuf_t* src,
+ u16_t dstOffset, u16_t srcOffset, u16_t length);
+void zfRxBufferCopy(zdev_t*dev, zbuf_t* dst, zbuf_t* src,
+ u16_t dstOffset, u16_t srcOffset, u16_t length);
+
+void zfCollectHWTally(zdev_t*dev, u32_t* rsp, u8_t id);
+void zfTimerInit(zdev_t* dev);
+u16_t zfTimerSchedule(zdev_t* dev, u16_t event, u32_t tick);
+u16_t zfTimerCancel(zdev_t* dev, u16_t event);
+void zfTimerClear(zdev_t* dev);
+u16_t zfTimerCheckAndHandle(zdev_t* dev);
+void zfProcessEvent(zdev_t* dev, u16_t* eventArray, u8_t eventCount);
+
+void zfBssInfoCreate(zdev_t* dev);
+void zfBssInfoDestroy(zdev_t* dev);
+
+struct zsBssInfo* zfBssInfoAllocate(zdev_t* dev);
+void zfBssInfoFree(zdev_t* dev, struct zsBssInfo* pBssInfo);
+void zfBssInfoReorderList(zdev_t* dev);
+void zfBssInfoInsertToList(zdev_t* dev, struct zsBssInfo* pBssInfo);
+void zfBssInfoRemoveFromList(zdev_t* dev, struct zsBssInfo* pBssInfo);
+void zfBssInfoRefresh(zdev_t* dev, u16_t mode);
+void zfCoreSetFrequencyComplete(zdev_t* dev);
+void zfCoreSetFrequency(zdev_t* dev, u16_t frequency);
+void zfCoreSetFrequencyV2(zdev_t* dev, u16_t frequency,
+ zfpFreqChangeCompleteCb cb);
+void zfCoreSetFrequencyEx(zdev_t* dev, u16_t frequency, u8_t bw40,
+ u8_t extOffset, zfpFreqChangeCompleteCb cb);
+void zfCoreSetFrequencyExV2(zdev_t* dev, u16_t frequency, u8_t bw40,
+ u8_t extOffset, zfpFreqChangeCompleteCb cb, u8_t forceSetFreq);
+void zfReSetCurrentFrequency(zdev_t* dev);
+u32_t zfCoreSetKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t type,
+ u16_t* mac, u32_t* key);
+void zfCoreSetKeyComplete(zdev_t* dev);
+void zfCoreReinit(zdev_t* dev);
+void zfCoreMacAddressNotify(zdev_t* dev, u8_t *addr);
+void zfCoreSetIsoName(zdev_t* dev, u8_t* isoName);
+void zfGenerateRandomBSSID(zdev_t* dev, u8_t *MACAddr, u8_t *BSSID);
+void zfCoreHalInitComplete(zdev_t* dev);
+
+u16_t zfFindCleanFrequency(zdev_t* dev, u32_t adhocMode);
+u16_t zfFindMinimumUtilizationChannelIndex(zdev_t* dev, u16_t* array, u16_t count);
+u8_t zfCompareWithBssid(zdev_t* dev, u16_t* bssid);
+
+/* chb.c */
+void zfDumpBssList(zdev_t* dev);
+
+
+u16_t zfIssueCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen, u16_t src, u8_t* buf);
+
+
+/* cic.c */
+void zfUpdateBssid(zdev_t* dev, u8_t* bssid);
+void zfResetSupportRate(zdev_t* dev, u8_t type);
+void zfUpdateSupportRate(zdev_t* dev, u8_t* rateArray);
+u8_t zfIsGOnlyMode(zdev_t* dev, u16_t frequency, u8_t* rateArray);
+void zfGatherBMode(zdev_t* dev, u8_t* rateArray, u8_t* extrateArray);
+u8_t zfPSDeviceSleep(zdev_t* dev);
+u16_t zfGetRandomNumber(zdev_t* dev, u16_t initValue);
+void zfCoreEvent(zdev_t* dev, u16_t event, u8_t* rsp);
+void zfBeaconCfgInterrupt(zdev_t* dev, u8_t* rsp);
+void zfEndOfAtimWindowInterrupt(zdev_t* dev);
+
+/* cinit.c */
+u16_t zfTxGenWlanHeader(zdev_t* dev, zbuf_t* buf, u16_t* header, u16_t seq,
+ u8_t flag, u16_t plusLen, u16_t minusLen, u16_t port,
+ u16_t* da, u16_t* sa, u8_t up, u16_t *micLen,
+ u16_t* snap, u16_t snapLen, struct aggControl *aggControl);
+u16_t zfTxGenMmHeader(zdev_t* dev, u8_t frameType, u16_t* dst,
+ u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt);
+void zfInitMacApMode(zdev_t* dev);
+u16_t zfChGetNextChannel(zdev_t* dev, u16_t frequency, u8_t* pbPassive);
+u16_t zfChGetFirstChannel(zdev_t* dev, u8_t* pbPassive);
+u16_t zfChGetFirst2GhzChannel(zdev_t* dev);
+u16_t zfChGetFirst5GhzChannel(zdev_t* dev);
+u16_t zfChGetLastChannel(zdev_t* dev, u8_t* pbPassive);
+u16_t zfChGetLast5GhzChannel(zdev_t* dev);
+u16_t zfChNumToFreq(zdev_t* dev, u8_t ch, u8_t freqBand);
+u8_t zfChFreqToNum(u16_t freq, u8_t* bIs5GBand);
+
+/* cmm.c */
+void zfProcessManagement(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo); //CWYang(m)
+void zfSendMmFrame(zdev_t* dev, u8_t frameType, u16_t* dst,
+ u32_t p1, u32_t p2, u32_t p3);
+u16_t zfFindElement(zdev_t* dev, zbuf_t* buf, u8_t eid);
+u16_t zfFindWifiElement(zdev_t* dev, zbuf_t* buf, u8_t type, u8_t subtype);
+u16_t zfFindSuperGElement(zdev_t* dev, zbuf_t* buf, u8_t type);
+u16_t zfFindXRElement(zdev_t* dev, zbuf_t* buf, u8_t type);
+u16_t zfRemoveElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t eid);
+u16_t zfUpdateElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t* updateeid);
+void zfProcessProbeReq(zdev_t* dev, zbuf_t* buf, u16_t* src);
+void zfProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo);
+u16_t zfSendProbeReq(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t bWithSSID);
+u16_t zfMmAddIeSupportRate(zdev_t* dev, zbuf_t* buf,
+ u16_t offset, u8_t eid, u8_t rateSet);
+u16_t zfMmAddIeDs(zdev_t* dev, zbuf_t* buf, u16_t offset);
+u16_t zfMmAddIeErp(zdev_t* dev, zbuf_t* buf, u16_t offset);
+void zfUpdateDefaultQosParameter(zdev_t* dev, u8_t mode);
+u16_t zfMmAddIeWpa(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t apId);
+u16_t zfMmAddHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset); //CWYang(+)
+u16_t zfMmAddPreNHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset);
+u16_t zfMmAddExtendedHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset); //CWYang(+)
+u16_t zfFindATHExtCap(zdev_t* dev, zbuf_t* buf, u8_t type, u8_t subtype);
+u16_t zfFindBrdcmMrvlRlnkExtCap(zdev_t* dev, zbuf_t* buf);
+u16_t zfFindMarvelExtCap(zdev_t* dev, zbuf_t* buf);
+u16_t zfFindBroadcomExtCap(zdev_t* dev, zbuf_t* buf);
+u16_t zfFindRlnkExtCap(zdev_t* dev, zbuf_t* buf);
+
+/* cmmap.c */
+void zfMmApTimeTick(zdev_t* dev);
+void zfApAgingSta(zdev_t* dev);
+u16_t zfApAddSta(zdev_t* dev, u16_t* addr, u16_t state, u16_t apId, u8_t type,
+ u8_t qosType, u8_t qosInfo);
+void zfApProtctionMonitor(zdev_t* dev);
+void zfApProcessBeacon(zdev_t* dev, zbuf_t* buf);
+void zfApProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId);
+void zfApProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId);
+void zfApProcessAsocRsp(zdev_t* dev, zbuf_t* buf);
+void zfApProcessDeauth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId);
+void zfApProcessDisasoc(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId);
+void zfApProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo);
+void zfApStoreAsocReqIe(zdev_t* dev, zbuf_t* buf, u16_t aid);
+u16_t zfApAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap);
+void zfApSendBeacon(zdev_t* dev);
+u16_t zfApGetSTAInfo(zdev_t* dev, u16_t* addr, u16_t* state, u8_t* vap);
+u16_t zfIntrabssForward(zdev_t* dev, zbuf_t* buf, u8_t srcVap);
+u16_t zfApBufferPsFrame(zdev_t* dev, zbuf_t* buf, u16_t port);
+void zfApInitStaTbl(zdev_t* dev);
+void zfApGetStaTxRateAndQosType(zdev_t* dev, u16_t* addr, u32_t* phyCtrl,
+ u8_t* qosType, u16_t* rcProbingFlag);
+void zfApGetStaQosType(zdev_t* dev, u16_t* addr, u8_t* qosType);
+void zfApSetStaTxRate(zdev_t* dev, u16_t* addr, u32_t phyCtrl);
+struct zsMicVar* zfApGetRxMicKey(zdev_t* dev, zbuf_t* buf);
+struct zsMicVar* zfApGetTxMicKey(zdev_t* dev, zbuf_t* buf, u8_t* qosType);
+u16_t zfApAddIeWmePara(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap);
+u16_t zfApUpdatePsBit(zdev_t* dev, zbuf_t* buf, u8_t* vap, u8_t* uapsdTrig);
+void zfApProcessPsPoll(zdev_t* dev, zbuf_t* buf);
+u16_t zfApFindSta(zdev_t* dev, u16_t* addr);
+void zfApGetStaEncryType(zdev_t* dev, u16_t* addr, u8_t* encryType);
+void zfApGetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t* iv16, u32_t* iv32);
+void zfApSetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t iv16, u32_t iv32);
+void zfApClearStaKey(zdev_t* dev, u16_t* addr);
+#ifdef ZM_ENABLE_CENC
+void zfApGetStaCencIvAndKeyIdx(zdev_t* dev, u16_t* addr, u32_t *iv,
+ u8_t *keyIdx);
+void zfApSetStaCencIv(zdev_t* dev, u16_t* addr, u32_t *iv);
+#endif //ZM_ENABLE_CENC
+void zfApSetProtectionMode(zdev_t* dev, u16_t mode);
+void zfApFlushBufferedPsFrame(zdev_t* dev);
+void zfApSendFailure(zdev_t* dev, u8_t* addr);
+u8_t zfApRemoveFromPsQueue(zdev_t* dev, u16_t id, u16_t* src);
+void zfApProcessAction(zdev_t* dev, zbuf_t* buf);
+/* cmmsta.c */
+void zfMmStaTimeTick(zdev_t* dev);
+void zfReWriteBeaconStartAddress(zdev_t* dev); // Mxzeng
+void zfStaProcessBeacon(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo); //CWYang(m)
+void zfStaProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId);
+void zfStaProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId);
+void zfStaProcessAsocRsp(zdev_t* dev, zbuf_t* buf);
+void zfStaProcessDeauth(zdev_t* dev, zbuf_t* buf);
+void zfStaProcessDisasoc(zdev_t* dev, zbuf_t* buf);
+void zfStaProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo);
+void zfStaProcessAtim(zdev_t* dev, zbuf_t* buf);
+void zfStaStoreAsocRspIe(zdev_t* dev, zbuf_t* buf);
+void zfStaChannelManagement(zdev_t* dev, u8_t scan);
+void zfIbssConnectNetwork(zdev_t* dev);
+void zfInfraConnectNetwork(zdev_t* dev);
+u8_t zfCheckAuthentication(zdev_t* dev, struct zsBssInfo* pBssInfo);
+u8_t zfChangeAdapterState(zdev_t* dev, u8_t newState);
+u16_t zfStaAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset);
+u16_t zfStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType);
+u16_t zfStaAddIeIbss(zdev_t* dev, zbuf_t* buf, u16_t offset);
+void zfStaStartConnect(zdev_t* dev, u8_t bIsSharedKey);
+u8_t zfStaIsConnected(zdev_t* dev);
+u8_t zfStaIsConnecting(zdev_t* dev);
+u8_t zfStaIsDisconnect(zdev_t* dev);
+void zfStaSendBeacon(zdev_t* dev);
+void zfSendNullData(zdev_t* dev, u8_t type);
+void zfSendPSPoll(zdev_t* dev);
+void zfSendBA(zdev_t* dev, u16_t start_seq, u8_t *bitmap);
+void zdRateInfoCountTx(zdev_t* dev, u16_t* macAddr);
+struct zsMicVar* zfStaGetRxMicKey(zdev_t* dev, zbuf_t* buf);
+struct zsMicVar* zfStaGetTxMicKey(zdev_t* dev, zbuf_t* buf);
+u16_t zfStaRxValidateFrame(zdev_t* dev, zbuf_t* buf);
+void zfStaMicFailureHandling(zdev_t* dev, zbuf_t* buf);
+u8_t zfStaBlockWlanScan(zdev_t* dev);
+void zfStaIbssPSCheckState(zdev_t* dev, zbuf_t* buf);
+u8_t zfStaIbssPSQueueData(zdev_t* dev, zbuf_t* buf);
+void zfStaIbssPSSend(zdev_t* dev);
+void zfStaResetStatus(zdev_t* dev, u8_t bInit);
+u16_t zfStaAddIeWmeInfo(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t qosInfo);
+void zfInitPartnerNotifyEvent(zdev_t* dev, zbuf_t* buf, struct zsPartnerNotifyEvent *event);
+void zfStaInitOppositeInfo(zdev_t* dev);
+void zfStaIbssMonitoring(zdev_t* dev, u8_t reset);
+struct zsBssInfo* zfStaFindBssInfo(zdev_t* dev, zbuf_t* buf, struct zsWlanProbeRspFrameHeader *pProbeRspHeader);
+u8_t zfStaInitBssInfo(zdev_t* dev, zbuf_t* buf,
+ struct zsWlanProbeRspFrameHeader *pProbeRspHeader,
+ struct zsBssInfo* pBssInfo, struct zsAdditionInfo* AddInfo, u8_t type);
+s8_t zfStaFindFreeOpposite(zdev_t* dev, u16_t *sa, int *pFoundIdx);
+s8_t zfStaFindOppositeByMACAddr(zdev_t* dev, u16_t *sa, u8_t *pFoundIdx);
+void zfStaRefreshBlockList(zdev_t* dev, u16_t flushFlag);
+void zfStaConnectFail(zdev_t* dev, u16_t reason, u16_t* bssid, u8_t weight);
+void zfStaGetTxRate(zdev_t* dev, u16_t* macAddr, u32_t* phyCtrl,
+ u16_t* rcProbingFlag);
+u16_t zfStaProcessAction(zdev_t* dev, zbuf_t* buf);
+struct zsTkipSeed* zfStaGetRxSeed(zdev_t* dev, zbuf_t* buf);
+#ifdef ZM_ENABLE_CENC
+/* CENC */
+u16_t zfStaAddIeCenc(zdev_t* dev, zbuf_t* buf, u16_t offset);
+#endif //ZM_ENABLE_CENC
+void zfStaEnableSWEncryption(zdev_t *dev, u8_t value);
+void zfStaDisableSWEncryption(zdev_t *dev);
+u16_t zfComputeBssInfoWeightValue(zdev_t *dev, u8_t isBMode, u8_t isHT, u8_t isHT40, u8_t signalStrength);
+u16_t zfStaAddIbssAdditionalIE(zdev_t* dev, zbuf_t* buf, u16_t offset);
+
+/* ctkip.c */
+void zfTkipInit(u8_t* key, u8_t* ta, struct zsTkipSeed* pSeed, u8_t* initIv);
+void zfMicSetKey(u8_t* key, struct zsMicVar* pMic);
+void zfMicAppendByte(u8_t b, struct zsMicVar* pMic);
+void zfMicClear(struct zsMicVar* pMic);
+void zfMicAppendTxBuf(zdev_t* dev, zbuf_t* buf, u8_t* da, u8_t* sa,
+ u16_t removeLen, u8_t* mic);
+u8_t zfMicRxVerify(zdev_t* dev, zbuf_t* buf);
+void zfMicGetMic(u8_t* dst, struct zsMicVar* pMic);
+void zfCalTxMic(zdev_t *dev, zbuf_t *buf, u8_t *snap, u16_t snapLen, u16_t offset, u16_t *da, u16_t *sa, u8_t up, u8_t *mic);
+void zfTKIPEncrypt(zdev_t *dev, zbuf_t *buf, u8_t *snap, u16_t snapLen, u16_t offset, u8_t keyLen, u8_t* key, u32_t* icv);
+u16_t zfTKIPDecrypt(zdev_t *dev, zbuf_t *buf, u16_t offset, u8_t keyLen, u8_t* key);
+void zfTkipGetseeds(u16_t iv16, u8_t *RC4Key, struct zsTkipSeed *Seed);
+u8_t zfTkipPhase1KeyMix(u32_t iv32, struct zsTkipSeed* pSeed);
+u8_t zfTkipPhase2KeyMix(u16_t iv16, struct zsTkipSeed* pSeed);
+void zfWEPEncrypt(zdev_t *dev, zbuf_t *buf, u8_t *snap, u16_t snapLen, u16_t offset, u8_t keyLen, u8_t* WepKey, u8_t *iv);
+u16_t zfWEPDecrypt(zdev_t *dev, zbuf_t *buf, u16_t offset, u8_t keyLen, u8_t* WepKey, u8_t *iv);
+
+/* ctxrx.c */
+u16_t zfSend80211Frame(zdev_t* dev, zbuf_t* buf);
+void zfIsrPciTxComp(zdev_t* dev);
+void zfTxPciDmaStart(zdev_t* dev);
+u16_t zfTxPortControl(zdev_t* dev, zbuf_t* buf, u16_t port);
+u16_t zfTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port,
+ u16_t bufType, u16_t flag);
+u16_t zfTxGenWlanTail(zdev_t* dev, zbuf_t* buf, u16_t* snap, u16_t snaplen,
+ u16_t* mic);
+u16_t zfTxGenWlanSnap(zdev_t* dev, zbuf_t* buf, u16_t* snap, u16_t* snaplen);
+void zfTxGetIpTosAndFrag(zdev_t* dev, zbuf_t* buf, u8_t* up, u16_t* fragOff);
+u16_t zfPutVtxq(zdev_t* dev, zbuf_t* buf);
+void zfPushVtxq(zdev_t* dev);
+u8_t zfIsVtxqEmpty(zdev_t* dev);
+u16_t zfGetSeqCtrl(zdev_t* dev, zbuf_t* buf, u16_t offset);
+u8_t zfGetFragNo(zdev_t* dev, zbuf_t* buf);
+void zfShowRxEAPOL(zdev_t* dev, zbuf_t* buf, u16_t offset);
+void zfShowTxEAPOL(zdev_t* dev, zbuf_t* buf, u16_t offset);
+void zfCoreRecv(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo);
+u16_t zfPutVmmq(zdev_t* dev, zbuf_t* buf);
+void zfFlushVtxq(zdev_t* dev);
+void zfAgingDefragList(zdev_t* dev, u16_t flushFlag);
+
+void zfLed100msCtrl(zdev_t* dev);
+void zf80211FrameSend(zdev_t* dev, zbuf_t* buf, u16_t* header, u16_t snapLen,
+ u16_t* da, u16_t* sa, u8_t up, u16_t headerLen, u16_t* snap,
+ u16_t* tail, u16_t tailLen, u16_t offset, u16_t bufType,
+ u8_t ac, u8_t keyIdx);
+void zfCheckIsRIFSFrame(zdev_t* dev, zbuf_t* buf, u16_t frameSubType);
+
+/* queue.c */
+struct zsQueue* zfQueueCreate(zdev_t* dev, u16_t size);
+void zfQueueDestroy(zdev_t* dev, struct zsQueue* q);
+u16_t zfQueuePutNcs(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick);
+u16_t zfQueuePut(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick);
+zbuf_t* zfQueueGet(zdev_t* dev, struct zsQueue* q);
+zbuf_t* zfQueueGetWithMac(zdev_t* dev, struct zsQueue* q, u8_t* addr, u8_t* mb);
+void zfQueueFlush(zdev_t* dev, struct zsQueue* q);
+void zfQueueAge(zdev_t* dev, struct zsQueue* q, u32_t tick, u32_t msAge);
+void zfQueueGenerateUapsdTim(zdev_t* dev, struct zsQueue* q,
+ u8_t* uniBitMap, u16_t* highestByte);
+
+/* hpmain.c */
+u16_t zfHpInit(zdev_t* dev, u32_t frequency);
+u16_t zfHpRelease(zdev_t* dev);
+void zfHpSetFrequencyEx(zdev_t* dev, u32_t frequency, u8_t bw40,
+ u8_t extOffset, u8_t initRF);
+u16_t zfHpStartRecv(zdev_t* dev);
+u16_t zfHpStopRecv(zdev_t* dev);
+u16_t zfHpResetKeyCache(zdev_t* dev);
+u16_t zfHpSetApStaMode(zdev_t* dev, u8_t mode);
+u16_t zfHpSetBssid(zdev_t* dev, u8_t* bssid);
+u16_t zfHpSetSnifferMode(zdev_t* dev, u16_t on);
+u8_t zfHpUpdateQosParameter(zdev_t* dev, u16_t* cwminTbl, u16_t* cwmaxTbl,
+ u16_t* aifsTbl, u16_t* txopTbl);
+void zfHpSetAtimWindow(zdev_t* dev, u16_t atimWin);
+void zfHpEnableBeacon(zdev_t* dev, u16_t mode, u16_t bcnInterval, u16_t dtim, u8_t enableAtim);
+void zfHpDisableBeacon(zdev_t* dev);
+void zfHpSetBasicRateSet(zdev_t* dev, u16_t bRateBasic, u16_t gRateBasic);
+void zfHpSetRTSCTSRate(zdev_t* dev, u32_t rate);
+void zfHpSetMacAddress(zdev_t* dev, u16_t* macAddr, u16_t macAddrId);
+u32_t zfHpGetMacAddress(zdev_t* dev);
+u32_t zfHpGetTransmitPower(zdev_t* dev);
+void zfHpSetMulticastList(zdev_t* dev, u8_t size, u8_t* pList, u8_t bAllMulticast);
+
+u16_t zfHpRemoveKey(zdev_t* dev, u16_t user);
+u32_t zfHpSetKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t type,
+ u16_t* mac, u32_t* key);
+//u32_t zfHpSetStaPairwiseKey(zdev_t* dev, u16_t* apMacAddr, u8_t type,
+// u32_t* key, u32_t* micKey);
+//u32_t zfHpSetStaGroupKey(zdev_t* dev, u16_t* apMacAddr, u8_t type,
+// u32_t* key, u32_t* micKey);
+u32_t zfHpSetApPairwiseKey(zdev_t* dev, u16_t* staMacAddr, u8_t type,
+ u32_t* key, u32_t* micKey, u16_t staAid);
+u32_t zfHpSetApGroupKey(zdev_t* dev, u16_t* apMacAddr, u8_t type,
+ u32_t* key, u32_t* micKey, u16_t vapId);
+u32_t zfHpSetDefaultKey(zdev_t* dev, u8_t keyId, u8_t type, u32_t* key, u32_t* micKey);
+u32_t zfHpSetPerUserKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t* mac, u8_t type, u32_t* key, u32_t* micKey);
+
+void zfHpSendBeacon(zdev_t* dev, zbuf_t* buf, u16_t len);
+u16_t zfHpGetPayloadLen(zdev_t* dev,
+ zbuf_t* buf,
+ u16_t len,
+ u16_t plcpHdrLen,
+ u32_t *rxMT,
+ u32_t *rxMCS,
+ u32_t *rxBW,
+ u32_t *rxSG
+ );
+u32_t zfHpGetFreeTxdCount(zdev_t* dev);
+u32_t zfHpGetMaxTxdCount(zdev_t* dev);
+u16_t zfHpSend(zdev_t* dev, u16_t* header, u16_t headerLen,
+ u16_t* snap, u16_t snapLen, u16_t* tail, u16_t tailLen, zbuf_t* buf,
+ u16_t offset, u16_t bufType, u8_t ac, u8_t keyIdx);
+void zfHpGetRegulationTablefromRegionCode(zdev_t* dev, u16_t regionCode);
+void zfHpGetRegulationTablefromCountry(zdev_t* dev, u16_t CountryCode);
+u8_t zfHpGetRegulationTablefromISO(zdev_t* dev, u8_t *countryInfo, u8_t length);
+const char* zfHpGetisoNamefromregionCode(zdev_t* dev, u16_t regionCode);
+u16_t zfHpGetRegionCodeFromIsoName(zdev_t* dev, u8_t *countryIsoName);
+u8_t zfHpGetRegulatoryDomain(zdev_t* dev);
+void zfHpLedCtrl(zdev_t* dev, u16_t ledId, u8_t mode);
+u16_t zfHpResetTxRx(zdev_t* dev);
+u16_t zfHpDeleteAllowChannel(zdev_t* dev, u16_t freq);
+u16_t zfHpAddAllowChannel(zdev_t* dev, u16_t freq);
+u32_t zfHpCwmUpdate(zdev_t* dev);
+u32_t zfHpAniUpdate(zdev_t* dev);
+u32_t zfHpAniUpdateRssi(zdev_t* dev, u8_t rssi);
+void zfHpAniAttach(zdev_t* dev);
+void zfHpAniArPoll(zdev_t* dev, u32_t listenTime, u32_t phyCnt1, u32_t phyCnt2);
+void zfHpHeartBeat(zdev_t* dev);
+void zfHpPowerSaveSetState(zdev_t* dev, u8_t psState);
+void zfHpPowerSaveSetMode(zdev_t* dev, u8_t staMode, u8_t psMode, u16_t bcnInterval);
+u16_t zfHpIsDfsChannel(zdev_t* dev, u16_t freq);
+u16_t zfHpIsDfsChannelNCS(zdev_t* dev, u16_t freq);
+u16_t zfHpFindFirstNonDfsChannel(zdev_t* dev, u16_t aBand);
+u16_t zfHpIsAllowedChannel(zdev_t* dev, u16_t freq);
+void zfHpDisableDfsChannel(zdev_t* dev, u8_t disableFlag);
+void zfHpSetTTSIFSTime(zdev_t* dev, u8_t sifs_time);
+
+void zfHpQueryMonHalRxInfo(zdev_t* dev, u8_t *monHalRxInfo);
+
+void zfDumpSSID(u8_t length, u8_t *value);
+void zfHpSetAggPktNum(zdev_t* dev, u32_t num);
+void zfHpSetMPDUDensity(zdev_t* dev, u8_t density);
+void zfHpSetSlotTime(zdev_t* dev, u8_t type);
+void zfHpSetSlotTimeRegister(zdev_t* dev, u8_t type);
+void zfHpSetRifs(zdev_t* dev, u8_t ht_enable, u8_t ht2040, u8_t g_mode);
+void zfHpBeginSiteSurvey(zdev_t* dev, u8_t status);
+void zfHpFinishSiteSurvey(zdev_t* dev, u8_t status);
+u16_t zfHpEnableHwRetry(zdev_t* dev);
+u16_t zfHpDisableHwRetry(zdev_t* dev);
+void zfHpSWDecrypt(zdev_t* dev, u8_t enable);
+void zfHpSWEncrypt(zdev_t* dev, u8_t enable);
+u32_t zfHpCapability(zdev_t* dev);
+void zfHpSetRollCallTable(zdev_t* dev);
+u8_t zfHpregulatoryDomain(zdev_t* dev);
+u16_t zfStaAddIePowerCap(zdev_t* dev, zbuf_t* buf, u16_t offset);
+u8_t zfHpGetMaxTxPower(zdev_t* dev);
+u8_t zfHpGetMinTxPower(zdev_t* dev);
+u16_t zfStaAddIeSupportCh(zdev_t* dev, zbuf_t* buf, u16_t offset);
+void zfHpEnableRifs(zdev_t* dev, u8_t mode24g, u8_t modeHt, u8_t modeHt2040);
+void zfHpDisableRifs(zdev_t* dev);
+u16_t zfHpUsbReset(zdev_t* dev);
+
+
+#endif /* #ifndef _CFUNC_H */
diff --git a/drivers/staging/otus/80211core/chb.c b/drivers/staging/otus/80211core/chb.c
new file mode 100644
index 000000000000..7fac15011256
--- /dev/null
+++ b/drivers/staging/otus/80211core/chb.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : hb.c */
+/* */
+/* Abstract */
+/* This module contains house keeping and timer functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+
+/* Called by wrapper every 10 msec */
+void zfiHeartBeat(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->tick++;
+
+#if 0
+ /* => every 1.28 seconds */
+ if (wd->cwm.cw_enable && ((wd->tick & 0x7f) == 0x3f))
+ {
+ zfHpCwmUpdate(dev);
+ }
+#endif
+ /* => every 2.56 seconds */
+ if ((wd->tick & 0xff) == 0)
+ {
+ zfAgingDefragList(dev, 1);
+ }
+
+ /* Watch Dog */
+ //zfWatchDog();
+
+ /* LED Control (per 100ms) */
+ if ((wd->tick % 10) == 9)
+ {
+ zfLed100msCtrl(dev);
+#ifdef ZM_ENABLE_BA_RATECTRL
+ if (!wd->modeMDKEnable)
+ {
+ zfiDbgReadTally(dev);
+ }
+#endif
+ }
+
+#ifdef ZM_ENABLE_REWRITE_BEACON_START_ADDRESS
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ if ( zfStaIsConnected(dev) )
+ {
+ zfReWriteBeaconStartAddress(dev);
+ }
+ }
+#endif
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ if ( zfStaIsConnected(dev) )
+ {
+ wd->tickIbssReceiveBeacon++; // add 10ms
+
+ if ( (wd->sta.ibssSiteSurveyStatus == 2) &&
+ (wd->tickIbssReceiveBeacon == 300) &&
+ (wd->sta.ibssReceiveBeaconCount < 3) )
+ {
+ zm_debug_msg0("It is happen!!! No error message");
+ zfReSetCurrentFrequency(dev);
+ }
+ }
+ }
+
+ if(wd->sta.ReceivedPacketRateCounter <= 0)
+ {
+ wd->sta.ReceivedPktRatePerSecond = wd->sta.TotalNumberOfReceivePackets;
+ //zm_debug_msg1("Receive Packet Per Second = ", wd->sta.ReceivedPktRatePerSecond);
+ if (wd->sta.TotalNumberOfReceivePackets != 0)
+ {
+ wd->sta.avgSizeOfReceivePackets = wd->sta.TotalNumberOfReceiveBytes/wd->sta.TotalNumberOfReceivePackets;
+ }
+ else
+ {
+ wd->sta.avgSizeOfReceivePackets = 640;
+ }
+ wd->sta.TotalNumberOfReceivePackets = 0;
+ wd->sta.TotalNumberOfReceiveBytes = 0;
+ wd->sta.ReceivedPacketRateCounter = 100; /*for another 1s*/
+ }
+ else
+ {
+ wd->sta.ReceivedPacketRateCounter--;
+ }
+
+ /* => every 1.28 seconds */
+ if((wd->tick & 0x7f) == 0x3f)
+ {
+ if( wd->sta.NonNAPcount > 0)
+ {
+ wd->sta.RTSInAGGMode = TRUE;
+ wd->sta.NonNAPcount = 0;
+ }
+ else
+ {
+ wd->sta.RTSInAGGMode = FALSE;
+ }
+ }
+
+
+
+ /* Maintain management time tick */
+ zfMmApTimeTick(dev);
+ zfMmStaTimeTick(dev);
+
+ //zfPhyCrTuning(dev);
+
+ //zfTxPowerControl(dev);
+ zfHpHeartBeat(dev);
+
+}
+
+
+void zfDumpBssList(zdev_t* dev)
+{
+ struct zsBssInfo* pBssInfo;
+ u8_t str[33];
+ u8_t i, j;
+ u32_t addr1, addr2;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zm_debug_msg0("***** Bss scan result *****");
+ zmw_enter_critical_section(dev);
+
+ pBssInfo = wd->sta.bssList.head;
+
+ for( i=0; i<wd->sta.bssList.bssCount; i++ )
+ {
+ if ( i )
+ {
+ zm_debug_msg0("---------------------------");
+ }
+
+ zm_debug_msg1("BSS #", i);
+ for(j=0; j<pBssInfo->ssid[1]; j++)
+ {
+ str[j] = pBssInfo->ssid[2+j];
+ }
+ str[pBssInfo->ssid[1]] = 0;
+ zm_debug_msg0("SSID = ");
+ zm_debug_msg0(str);
+
+ addr1 = (pBssInfo->bssid[0] << 16) + (pBssInfo->bssid[1] << 8 )
+ + pBssInfo->bssid[2];
+ addr2 = (pBssInfo->bssid[3] << 16) + (pBssInfo->bssid[4] << 8 )
+ + pBssInfo->bssid[5];
+ zm_debug_msg2("Bssid = ", addr1);
+ zm_debug_msg2(" ", addr2);
+ zm_debug_msg1("frequency = ", pBssInfo->frequency);
+ zm_debug_msg1("security type = ", pBssInfo->securityType);
+ zm_debug_msg1("WME = ", pBssInfo->wmeSupport);
+ zm_debug_msg1("beacon interval = ", pBssInfo->beaconInterval[0]
+ + (pBssInfo->beaconInterval[1] << 8));
+ zm_debug_msg1("capability = ", pBssInfo->capability[0]
+ + (pBssInfo->capability[1] << 8));
+ if ( pBssInfo->supportedRates[1] > 0 )
+ {
+ for( j=0; j<pBssInfo->supportedRates[1]; j++ )
+ {
+ zm_debug_msg2("supported rates = ", pBssInfo->supportedRates[2+j]);
+ }
+ }
+
+ for( j=0; j<pBssInfo->extSupportedRates[1]; j++ )
+ {
+ zm_debug_msg2("ext supported rates = ", pBssInfo->extSupportedRates[2+j]);
+ }
+
+ pBssInfo = pBssInfo->next;
+ }
+ zmw_leave_critical_section(dev);
+
+ zm_debug_msg0("***************************");
+}
+
diff --git a/drivers/staging/otus/80211core/cic.c b/drivers/staging/otus/80211core/cic.c
new file mode 100644
index 000000000000..c84f079e3d84
--- /dev/null
+++ b/drivers/staging/otus/80211core/cic.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+#include "ratectrl.h"
+
+
+void zfUpdateBssid(zdev_t* dev, u8_t* bssid)
+{
+
+ zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ //zmw_enter_critical_section(dev);
+ wd->sta.bssid[0] = bssid[0] + (((u16_t) bssid[1]) << 8);
+ wd->sta.bssid[1] = bssid[2] + (((u16_t) bssid[3]) << 8);
+ wd->sta.bssid[2] = bssid[4] + (((u16_t) bssid[5]) << 8);
+ //zmw_leave_critical_section(dev);
+
+ zfHpSetBssid(dev, bssid);
+
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfResetSupportRate */
+/* Reset support rate to default value. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* type: ZM_DEFAULT_SUPPORT_RATE_ZERO => reset to zero */
+/* ZM_DEFAULT_SUPPORT_RATE_DISCONNECT => reset to disconnect status */
+/* ZM_DEFAULT_SUPPORT_RATE_IBSS_B => reset to IBSS creator(b mode) */
+/* ZM_DEFAULT_SUPPORT_RATE_IBSS_AG => reset to IBSS creator(a/g mode) */
+/* */
+/************************************************************************************/
+void zfResetSupportRate(zdev_t* dev, u8_t type)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch(type)
+ {
+ case ZM_DEFAULT_SUPPORT_RATE_ZERO:
+ wd->bRate = 0;
+ wd->bRateBasic = 0;
+ wd->gRate = 0;
+ wd->gRateBasic = 0;
+ break;
+ case ZM_DEFAULT_SUPPORT_RATE_DISCONNECT:
+ wd->bRate = 0xf;
+ wd->bRateBasic = 0xf;
+ wd->gRate = 0xff;
+ wd->gRateBasic = 0x15;
+ break;
+ case ZM_DEFAULT_SUPPORT_RATE_IBSS_B:
+ wd->bRate = 0xf;
+ wd->bRateBasic = 0xf;
+ wd->gRate = 0;
+ wd->gRateBasic = 0;
+ break;
+ case ZM_DEFAULT_SUPPORT_RATE_IBSS_AG:
+ wd->bRate = 0xf;
+ wd->bRateBasic = 0xf;
+ wd->gRate = 0xff;
+ wd->gRateBasic = 0;
+ break;
+ }
+}
+
+void zfUpdateSupportRate(zdev_t* dev, u8_t* rateArray)
+{
+ u8_t bRate=0, bRateBasic=0, gRate=0, gRateBasic=0;
+ u8_t length = rateArray[1];
+ u8_t i, j;
+
+ zmw_get_wlan_dev(dev);
+
+ for(i=2; i<length+2; i++)
+ {
+ for(j=0; j<4; j++)
+ {
+ if ( (rateArray[i] & 0x7f) == zg11bRateTbl[j] )
+ {
+ bRate |= (1 << j);
+ if ( rateArray[i] & 0x80 )
+ {
+ bRateBasic |= (1 << j);
+ }
+ }
+ }
+
+ if ( j == 4 )
+ {
+ for(j=0; j<8; j++)
+ {
+ if ( (rateArray[i] & 0x7f) == zg11gRateTbl[j] )
+ {
+ gRate |= (1 << j);
+ if ( rateArray[i] & 0x80 )
+ {
+ gRateBasic |= (1 << j);
+ }
+ }
+ }
+ }
+ }
+
+
+ wd->bRate |= bRate;
+ wd->bRateBasic |= bRateBasic;
+ wd->gRate |= gRate;
+ wd->gRateBasic |= gRateBasic;
+}
+
+u8_t zfIsGOnlyMode(zdev_t* dev, u16_t frequency, u8_t* rateArray)
+{
+ u8_t length = rateArray[1];
+ u8_t i, j;
+
+ if (frequency < 3000) {
+ for (i = 2; i < length+2; i++) {
+ for (j = 0; j < 8; j++) {
+ if ( ((rateArray[i] & 0x7f) == zg11gRateTbl[j])
+ && (rateArray[i] & 0x80) ) {
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+void zfGatherBMode(zdev_t* dev, u8_t* rateArray, u8_t* extrateArray)
+{
+ u8_t gatherBMode[ZM_MAX_SUPP_RATES_IE_SIZE + 2];
+ u8_t i, j, k = 0;
+ u8_t length;
+
+ gatherBMode[0] = ZM_WLAN_EID_SUPPORT_RATE;
+ gatherBMode[1] = 0;
+
+ length = rateArray[1];
+ for (i = 2; i < length+2; i++) {
+ for (j = 0; j < 4; j++) {
+ if ( (rateArray[i] & 0x7f) == zg11bRateTbl[j] ) {
+ gatherBMode[2+k] = rateArray[i];
+
+ gatherBMode[1]++;
+ k++;
+ }
+ }
+ }
+
+ length = extrateArray[1];
+ for (i = 2; i < length+2; i++) {
+ for (j = 0; j < 4; j++) {
+ if ( (extrateArray[i] & 0x7f) == zg11bRateTbl[j] ) {
+ gatherBMode[2+k] = extrateArray[i];
+
+ gatherBMode[1]++;
+ k++;
+ }
+ }
+ }
+
+ extrateArray[0] = extrateArray[1] = 0;
+ zfMemoryCopy(rateArray, gatherBMode, gatherBMode[1]+2);
+}
+
+u16_t zfGetRandomNumber(zdev_t* dev, u16_t initValue)
+{
+#if 0
+ /* Compiler/Linker error on Linux */
+ if ( initValue )
+ {
+ srand(initValue);
+ }
+
+ return ((u16_t)rand());
+#endif
+ return 0;
+}
+
+u8_t zfPSDeviceSleep(zdev_t* dev)
+{
+ //zmw_get_wlan_dev(dev);
+
+ /* enter PS mode */
+
+ return 0;
+}
+
+u8_t zcOfdmPhyCrtlToRate[] =
+{
+ /* 0x8=48M, 0x9=24M, 0xa=12M, 0xb=6M, 0xc=54M, 0xd=36M, 0xe=18M, 0xf=9M */
+ 10, 8, 6, 4, 11, 9, 7, 5
+};
+
+u8_t zfPhyCtrlToRate(u32_t phyCtrl)
+{
+ u32_t mt, mcs, sg;
+ u8_t rate = 0;
+
+ mt = phyCtrl & 0x3;
+ mcs = (phyCtrl>>18) & 0x3f;
+ sg = (phyCtrl>>31) & 0x1;
+
+ if ((mt == 0) && (mcs <=3))
+ {
+ rate = (u8_t)mcs;
+ }
+ else if ((mt == 1) && (mcs >= 0x8) && (mcs <= 0xf))
+ {
+ rate = zcOfdmPhyCrtlToRate[mcs-8];
+ }
+ else if ((mt == 2) && (mcs <= 15))
+ {
+ rate = (u8_t)mcs + 12;
+ if(sg) {
+ if (mcs != 7)
+ {
+ rate = (u8_t)mcs + 12 + 2;
+ }
+ else //MCS7-SG
+ {
+ rate = (u8_t)30;
+ }
+ }
+ }
+
+ return rate;
+}
+
+
+void zfCoreEvent(zdev_t* dev, u16_t event, u8_t* rsp)
+{
+ u16_t i;
+ zbuf_t* psBuf;
+ u8_t moreData;
+ u8_t vap = 0;
+ u8_t peerIdx;
+ s8_t res;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+ if (event == 0) //Beacon Event
+ {
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ zfApSendBeacon(dev);
+
+ if (wd->CurrentDtimCount == 0)
+ {
+ /* TODO : Send queued broadcast frames at BC/MC event */
+ do
+ {
+ psBuf = NULL;
+ moreData = 0;
+ zmw_enter_critical_section(dev);
+ if (wd->ap.bcmcTail[vap] != wd->ap.bcmcHead[vap])
+ {
+ //zm_msg0_mm(ZM_LV_0, "Send BCMC frames");
+ psBuf = wd->ap.bcmcArray[vap][wd->ap.bcmcHead[vap]];
+ wd->ap.bcmcHead[vap] = (wd->ap.bcmcHead[vap] + 1)
+ & (ZM_BCMC_ARRAY_SIZE - 1);
+ if (wd->ap.bcmcTail[vap] != wd->ap.bcmcHead[vap])
+ {
+ moreData = 0x20;
+ }
+ }
+ zmw_leave_critical_section(dev);
+ if (psBuf != NULL)
+ {
+ /* TODO : config moreData bit */
+ zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF,
+ moreData);
+ }
+ } while(psBuf != NULL);
+
+ }
+ }
+ else
+ {
+ /* STA mode */
+ if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
+ {
+ /* send queued packets */
+ for(i=0; i<wd->sta.staPSDataCount; i++)
+ {
+ zfTxSendEth(dev, wd->sta.staPSDataQueue[i], 0,
+ ZM_EXTERNAL_ALLOC_BUF, 0);
+ }
+
+ wd->sta.staPSDataCount = 0;
+ }
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ zfStaSendBeacon(dev);
+ wd->sta.ibssAtimTimer = ZM_BIT_15 | wd->sta.atimWindow;
+ }
+
+ zfPowerSavingMgrPreTBTTInterrupt(dev);
+ }
+ } //if (event == 0) //Beacon Event
+ else if (event == 1) //Retry completed event
+ {
+ u32_t retryRate;
+
+ retryRate = (u32_t)(rsp[6]) + (((u32_t)(rsp[7]))<<8)
+ + (((u32_t)(rsp[8]))<<16) + (((u32_t)(rsp[9]))<<24);
+ /* Degrade Tx Rate */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zmw_enter_critical_section(dev);
+ if ((i=zfApFindSta(dev, (u16_t*)rsp)) != 0xffff)
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->ap.staTable[i].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t*)rsp, &peerIdx);
+ if ( res == 0 )
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ } //else if (event == 1) //Retry completed event
+ else if (event == 2) //Tx Fail event
+ {
+ u32_t retryRate;
+
+ retryRate = (u32_t)(rsp[6]) + (((u32_t)(rsp[7]))<<8)
+ + (((u32_t)(rsp[8]))<<16) + (((u32_t)(rsp[9]))<<24);
+
+ /* Degrade Tx Rate */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zmw_enter_critical_section(dev);
+ if ((i=zfApFindSta(dev, (u16_t*)rsp)) != 0xffff)
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->ap.staTable[i].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+
+ zfApSendFailure(dev, rsp);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t*)rsp, &peerIdx);
+ if ( res == 0 )
+ {
+ zfRateCtrlTxFailEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, 0,(u32_t)zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ } //else if (event == 2) //Tx Fail event
+ else if (event == 3) //Tx Comp event
+ {
+ u32_t retryRate;
+
+ retryRate = (u32_t)(rsp[6]) + (((u32_t)(rsp[7]))<<8)
+ + (((u32_t)(rsp[8]))<<16) + (((u32_t)(rsp[9]))<<24);
+
+ /* TODO : Tx completed, used for rate control probing */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zmw_enter_critical_section(dev);
+ if ((i=zfApFindSta(dev, (u16_t*)rsp)) != 0xffff)
+ {
+ zfRateCtrlTxSuccessEvent(dev, &wd->ap.staTable[i].rcCell, zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t*)rsp, &peerIdx);
+ if ( res == 0 )
+ {
+ zfRateCtrlTxSuccessEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, zfPhyCtrlToRate(retryRate));
+ }
+ zmw_leave_critical_section(dev);
+ }
+ } //else if (event == 3) //Tx Comp event
+ else if (event == 4) //BA failed count
+ {
+ u32_t fail;
+ u32_t rate;
+ peerIdx = 0;
+
+ fail=((u32_t*)rsp)[0] & 0xFFFF;
+ rate=((u32_t*)rsp)[0] >> 16;
+
+ if (rate > 15) {
+ rate = (rate & 0xF) + 12 + 2;
+ }
+ else {
+ rate = rate + 12;
+ }
+
+ zmw_enter_critical_section(dev);
+ zfRateCtrlTxFailEvent(dev, &wd->sta.oppositeInfo[peerIdx].rcCell, (u8_t)rate, fail);
+ zmw_leave_critical_section(dev);
+ }
+}
+
+void zfBeaconCfgInterrupt(zdev_t* dev, u8_t* rsp)
+{
+ u32_t txBeaconCounter;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ txBeaconCounter = *((u32_t *)rsp);
+ if ( wd->sta.beaconTxCnt != txBeaconCounter )
+ {
+ wd->sta.txBeaconInd = 1;
+
+ zmw_enter_critical_section(dev);
+ wd->tickIbssSendBeacon = 0;
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ wd->sta.txBeaconInd = 0;
+ }
+
+#ifdef ZM_ENABLE_IBSS_DELAYED_JOIN_INDICATION
+ if ( wd->sta.txBeaconInd && wd->sta.ibssDelayedInd )
+ {
+ if (wd->zfcbIbssPartnerNotify != NULL)
+ {
+ wd->zfcbIbssPartnerNotify(dev, 1, &wd->sta.ibssDelayedIndEvent);
+ }
+
+ wd->sta.ibssDelayedInd = 0;
+ }
+#endif
+
+ wd->sta.beaconTxCnt = txBeaconCounter;
+
+ // Need to check if the time is expired after ATIM window??
+
+ // Check if we have buffered any data for those stations that are sleeping
+ // If it's true, then transmitting ATIM pkt to notify them
+
+#ifdef ZM_ENABLE_IBSS_PS
+ // TODO: Need to check if the station receive our ATIM pkt???
+ zfStaIbssPSSend(dev);
+
+ if ( wd->sta.atimWindow == 0 )
+ {
+ // We won't receive the end of ATIM isr so we fake it
+ zfPowerSavingMgrAtimWinExpired(dev);
+ }
+#endif
+ }
+}
+
+void zfEndOfAtimWindowInterrupt(zdev_t* dev)
+{
+#ifdef ZM_ENABLE_IBSS_PS
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ // Transmit any queued pkt for the stations!!
+ zfPowerSavingMgrAtimWinExpired(dev);
+ }
+#endif
+}
diff --git a/drivers/staging/otus/80211core/cinit.c b/drivers/staging/otus/80211core/cinit.c
new file mode 100644
index 000000000000..5f853ce79309
--- /dev/null
+++ b/drivers/staging/otus/80211core/cinit.c
@@ -0,0 +1,1911 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : init.c */
+/* */
+/* Abstract */
+/* This module contains init functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#include "../hal/hpreg.h"
+
+extern const u8_t zcUpToAc[8];
+
+u16_t zcIndextoRateBG[16] = {1000, 2000, 5500, 11000, 0, 0, 0, 0, 48000,
+ 24000, 12000, 6000, 54000, 36000, 18000, 9000};
+u32_t zcIndextoRateN20L[16] = {6500, 13000, 19500, 26000, 39000, 52000, 58500,
+ 65000, 13000, 26000, 39000, 52000, 78000, 104000,
+ 117000, 130000};
+u32_t zcIndextoRateN20S[16] = {7200, 14400, 21700, 28900, 43300, 57800, 65000,
+ 72200, 14400, 28900, 43300, 57800, 86700, 115600,
+ 130000, 144400};
+u32_t zcIndextoRateN40L[16] = {13500, 27000, 40500, 54000, 81000, 108000, 121500,
+ 135000, 27000, 54000, 81000, 108000, 162000, 216000,
+ 243000, 270000};
+u32_t zcIndextoRateN40S[16] = {15000, 30000, 45000, 60000, 90000, 120000, 135000,
+ 150000, 30000, 60000, 90000, 120000, 180000, 240000,
+ 270000, 300000};
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfTxGenWlanHeader */
+/* Generate WLAN MAC header and LLC header. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer pointer */
+/* id : Index of TxD */
+/* port : WLAN port */
+/* */
+/* OUTPUTS */
+/* length of removed Ethernet header */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.5 */
+/* */
+/************************************************************************/
+u16_t zfTxGenWlanHeader(zdev_t* dev, zbuf_t* buf, u16_t* header, u16_t seq,
+ u8_t flag, u16_t plusLen, u16_t minusLen, u16_t port,
+ u16_t* da, u16_t* sa, u8_t up, u16_t *micLen,
+ u16_t* snap, u16_t snapLen, struct aggControl *aggControl)
+{
+
+ u16_t len;
+ u16_t macCtrl;
+ u32_t phyCtrl;
+ u16_t hlen = 16;
+ u16_t icvLen = 0;
+ u16_t wdsPortId;
+ u16_t vap = 0;
+ u16_t mcs = 0;
+ u16_t mt = 0;
+ u8_t qosType;
+ u8_t b1, b2;
+ u16_t wdsPort;
+ u8_t encExemptionActionType;
+ u16_t rateProbingFlag = 0;
+ u8_t tkipFrameOffset = 0;
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ u8_t res, peerIdx;
+ u8_t userIdx=0;
+ u16_t *iv16;
+ u32_t *iv32;
+#endif
+
+ zmw_get_wlan_dev(dev);
+
+ /* Generate WLAN header */
+ /* Frame control */
+ header[4] = 0x0008 | (flag<<8);
+ /* Duration */
+ header[5] = 0x0000;
+
+ if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ /* ToDS bit */
+ header[4] |= 0x0100;
+
+ /*Sometimes we wake up to tx/rx but AP still think we are sleeping, so still need to set this bit*/
+ if ( zfPowerSavingMgrIsSleeping(dev) || wd->sta.psMgr.tempWakeUp == 1 )
+ {
+ header[4] |= 0x1000;
+ }
+
+ /* Address 1 = BSSID */
+ header[6] = wd->sta.bssid[0];
+ header[7] = wd->sta.bssid[1];
+ header[8] = wd->sta.bssid[2];
+ /* Address 3 = DA */
+ header[12] = da[0];
+ header[13] = da[1];
+ header[14] = da[2];
+ }
+ else if (wd->wlanMode == ZM_MODE_PSEUDO)
+ {
+ /* Address 1 = DA */
+ header[6] = da[0];
+ header[7] = da[1];
+ header[8] = da[2];
+ /* Address 3 = 00:00:00:00:00:00 */
+ header[12] = 0;
+ header[13] = 0;
+ header[14] = 0;
+
+ /* PSEUDO test : WDS */
+ if (wd->enableWDS)
+ {
+ /* ToDS and FromDS bit */
+ header[4] |= 0x0300;
+
+ /* Address 4 = SA */
+ header[16] = 0;
+ header[17] = 0;
+ header[18] = 0;
+
+ hlen = 19;
+ }
+ }
+ else if (wd->wlanMode == ZM_MODE_IBSS)
+ {
+ /* Address 1 = DA */
+ header[6] = da[0];
+ header[7] = da[1];
+ header[8] = da[2];
+ /* Address 3 = BSSID */
+ header[12] = wd->sta.bssid[0];
+ header[13] = wd->sta.bssid[1];
+ header[14] = wd->sta.bssid[2];
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, da, &peerIdx);
+ if(res == 0) // Find opposite in our OppositeInfo Structure !
+ {
+ userIdx = peerIdx;
+ }
+ zmw_leave_critical_section(dev);
+#endif
+ }
+ else if (wd->wlanMode == ZM_MODE_AP)
+ {
+ if (port < 0x20)
+ /* AP mode */
+ {
+ /* FromDS bit */
+ header[4] |= 0x0200;
+
+ /* Address 1 = DA */
+ header[6] = da[0];
+ header[7] = da[1];
+ header[8] = da[2];
+ /* Address 3 = SA */
+ header[12] = sa[0];
+ header[13] = sa[1];
+ header[14] = sa[2];
+
+ if (port < ZM_MAX_AP_SUPPORT)
+ {
+ vap = port;
+ header[14] += (vap<<8);
+ }
+ }
+ else
+ /* WDS port */
+ {
+ /* ToDS and FromDS bit */
+ header[4] |= 0x0300;
+
+ wdsPortId = port - 0x20;
+
+ /* Address 1 = RA */
+ header[6] = wd->ap.wds.macAddr[wdsPortId][0];
+ header[7] = wd->ap.wds.macAddr[wdsPortId][1];
+ header[8] = wd->ap.wds.macAddr[wdsPortId][2];
+ /* Address 3 = DA */
+ header[12] = da[0];
+ header[13] = da[1];
+ header[14] = da[2];
+ /* Address 4 = SA */
+ header[16] = sa[0];
+ header[17] = sa[1];
+ header[18] = sa[2];
+
+ hlen = 19;
+ }
+ } /* else if (wd->wlanMode == ZM_MODE_AP) */
+
+ /* Address 2 = TA */
+ header[9] = wd->macAddr[0];
+ header[10] = wd->macAddr[1];
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ header[11] = wd->macAddr[2]; //Multiple SSID
+#else
+ header[11] = wd->macAddr[2] + (vap<<8); //VAP
+#endif
+
+ if ( (wd->wlanMode == ZM_MODE_IBSS) && (wd->XLinkMode) )
+ {
+ header[9] = sa[0];
+ header[10] = sa[1];
+ header[11] = sa[2];
+ }
+
+ /* Sequence Control */
+ header[15] = seq;
+
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zfApGetStaTxRateAndQosType(dev, da, &phyCtrl, &qosType, &rateProbingFlag);
+ mt = (u16_t)(phyCtrl & 0x3);
+ mcs = (u16_t)((phyCtrl >> 16) & 0x3f);
+#if 1
+ //zfApGetStaQosType(dev, da, &qosType);
+
+ /* if DA == WME STA */
+ if (qosType == 1)
+ {
+ /* QoS data */
+ header[4] |= 0x0080;
+
+ /* QoS Control */
+ header[hlen] = up;
+ hlen += 1;
+ }
+#endif
+ }
+
+#if 0
+ //AGG Test Code
+ if (header[6] == 0x8000)
+ {
+ /* QoS data */
+ header[4] |= 0x0080;
+
+ /* QoS Control */
+ header[hlen] = 0;
+ hlen += 1;
+ }
+#endif
+
+ if (wd->wlanMode == ZM_MODE_AP) {
+ /* Todo: rate control here for qos field */
+ }
+ else {
+ /* Rate control */
+ zfStaGetTxRate(dev, da, &phyCtrl, &rateProbingFlag);
+ mt = (u16_t)(phyCtrl & 0x3);
+ mcs = (u16_t)((phyCtrl >> 16) & 0x3f);
+ }
+
+ if (wd->txMCS != 0xff)
+ {
+ /* fixed rate */
+ phyCtrl = ((u32_t)wd->txMCS<<16) + wd->txMT;
+ mcs = wd->txMCS;
+ mt = wd->txMT;
+ }
+
+ if (wd->enableAggregation)
+ {
+ /* force enable aggregation */
+ if (wd->enableAggregation==2 && !(header[6]&0x1))
+ {
+ /* QoS data */
+ header[4] |= 0x0080;
+
+ /* QoS Control */
+ header[hlen] = 0;
+ hlen += 1;
+ }
+ /* if wd->enableAggregation=1 => force disable */
+ /* if wd->enableAggregation=0 => auto */
+ }
+
+#ifdef ZM_ENABLE_AGGREGATION
+ /*
+ * aggregation control
+ */
+
+ /*
+ * QoS data
+ */
+ if (wd->wlanMode == ZM_MODE_AP) {
+ if (aggControl && mt == 2) {
+ if (wd->enableAggregation==0 && !(header[6]&0x1))
+ {
+ header[4] |= 0x0080;
+
+ /*
+ * QoS Control
+ */
+ header[hlen] = 0;
+ hlen += 1;
+ }
+ }
+ }
+#endif
+
+ // MSDU Length
+ len = zfwBufGetSize(dev, buf);
+
+ /* Generate control setting */
+ /* Backoff, Non-Burst and hardware duration */
+ macCtrl = 0x208;
+
+ /* ACK */
+ if ((header[6] & 0x1) == 0x1)
+ {
+ /* multicast frame : Set NO-ACK bit */
+ macCtrl |= 0x4;
+ }
+ else
+ {
+ /* unicast frame */
+ #if 0
+ // Enable RTS according to MPDU Lengths ( not MSDU Lengths )
+ if (len >= wd->rtsThreshold)
+ {
+ /* Enable RTS */
+ macCtrl |= 1;
+ }
+ #endif
+ }
+ /* VAP test code */
+ //macCtrl |= 0x4;
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ u8_t encryType;
+ u16_t iv16;
+ u32_t iv32;
+
+ /* Check whether this is a multicast frame */
+ if ((header[6] & 0x1) == 0x1)
+ {
+ /* multicast frame */
+ if (wd->ap.encryMode[vap] == ZM_TKIP)
+ {
+ wd->ap.iv16[vap]++;
+
+ if(wd->ap.iv16[vap] == 0)
+ {
+ wd->ap.iv32[vap]++;
+ }
+
+ b1 = (u8_t) (wd->ap.iv16[vap] >> 8);
+ b2 = (b1 | 0x20) & 0x7f;
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ b1 = (u8_t) wd->ap.iv16[vap];
+ b2 = 0x20 | (wd->ap.bcKeyIndex[vap] << 6);
+ header[hlen+1] = ((u16_t)b2 << 8) + b1;
+ header[hlen+2] = (u16_t) wd->ap.iv32[vap];
+ header[hlen+3] = (u16_t) (wd->ap.iv32[vap] >> 16);
+
+ //macCtrl |= 0x80;
+ macCtrl |= 0x40;
+ icvLen = 4;
+
+ /* set hardware MIC */
+ if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
+ {
+ macCtrl |= 0x100;
+ plusLen += 8;
+ *micLen = 8;
+ }
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ }
+ else if (wd->ap.encryMode[vap] == ZM_AES)
+ {
+ wd->ap.iv16[vap]++;
+
+ if(wd->ap.iv16[vap] == 0)
+ {
+ wd->ap.iv32[vap]++;
+ }
+
+ b1 = (u8_t) wd->ap.iv16[vap];
+ b2 = (u8_t) (wd->ap.iv16[vap] >> 8);
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ header[hlen+1] = 0x2000 | (wd->ap.bcKeyIndex[vap] << 14);
+ header[hlen+2] = (u16_t) (wd->ap.iv32[vap]);
+ header[hlen+3] = (u16_t) (wd->ap.iv32[vap] >> 16);
+
+ macCtrl |= 0xc0;
+ icvLen = 8; /* MIC */
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ }
+ #ifdef ZM_ENABLE_CENC
+ else if (wd->ap.encryMode[vap] == ZM_CENC)
+ {
+ //u32_t txiv[4];
+
+ wd->ap.txiv[vap][0]++;
+
+ if (wd->ap.txiv[vap][0] == 0)
+ {
+ wd->ap.txiv[vap][1]++;
+ }
+
+ if (wd->ap.txiv[vap][1] == 0)
+ {
+ wd->ap.txiv[vap][2]++;
+ }
+
+ if (wd->ap.txiv[vap][2] == 0)
+ {
+ wd->ap.txiv[vap][3]++;
+ }
+
+ if (wd->ap.txiv[vap][3] == 0)
+ {
+ wd->ap.txiv[vap][0] = 0;
+ wd->ap.txiv[vap][1] = 0;
+ wd->ap.txiv[vap][2] = 0;
+ }
+
+ header[hlen] = (wd->ap.bcKeyIndex[vap] & 0x0001); /* For Key Id and reserved field */
+ header[hlen+1] = (u16_t)wd->ap.txiv[vap][0];
+ header[hlen+2] = (u16_t)(wd->ap.txiv[vap][0] >> 16);
+ header[hlen+3] = (u16_t)wd->ap.txiv[vap][1];
+ header[hlen+4] = (u16_t)(wd->ap.txiv[vap][1] >> 16);
+ header[hlen+5] = (u16_t)wd->ap.txiv[vap][2];
+ header[hlen+6] = (u16_t)(wd->ap.txiv[vap][2] >> 16);
+ header[hlen+7] = (u16_t)wd->ap.txiv[vap][3];
+ header[hlen+8] = (u16_t)(wd->ap.txiv[vap][3] >> 16);
+
+ macCtrl |= 0x80;
+ icvLen = 16; /* MIC */
+
+ header[4] |= 0x4000;
+ hlen += 9;
+ }
+ #endif //ZM_ENABLE_CENC
+ }
+ else
+ {
+ /* Get STA's encryption type */
+ zfApGetStaEncryType(dev, da, &encryType);
+
+ if (encryType == ZM_TKIP)
+ {
+ /* Get iv16 and iv32 */
+ zfApGetStaWpaIv(dev, da, &iv16, &iv32);
+
+ iv16++;
+ if (iv16 == 0)
+ {
+ iv32++;
+ }
+
+ b1 = (u8_t) (iv16 >> 8);
+ b2 = (b1 | 0x20) & 0x7f;
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ b1 = (u8_t) iv16;
+ b2 = 0x20;
+ header[hlen+1] = ((u16_t)b2 << 8) + b1;
+ header[hlen+2] = (u16_t) iv32;
+ header[hlen+3] = (u16_t) (iv32 >> 16);
+
+ //macCtrl |= 0x80;
+ macCtrl |= 0x40;
+ icvLen = 4;
+
+ /* set hardware MIC */
+ if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
+ {
+ macCtrl |= 0x100;
+ plusLen += 8;
+ *micLen = 8;
+ }
+
+ header[4] |= 0x4000;
+ hlen += 4;
+
+ /* Set iv16 and iv32 */
+ zfApSetStaWpaIv(dev, da, iv16, iv32);
+ }
+ else if (encryType == ZM_AES)
+ {
+ /* Get iv16 and iv32 */
+ zfApGetStaWpaIv(dev, da, &iv16, &iv32);
+
+ iv16++;
+ if (iv16 == 0)
+ {
+ iv32++;
+ }
+
+ b1 = (u8_t) iv16;
+ b2 = (u8_t) (iv16 >> 8);
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ header[hlen+1] = 0x2000;
+ header[hlen+2] = (u16_t) (iv32);
+ header[hlen+3] = (u16_t) (iv32 >> 16);
+
+ macCtrl |= 0xc0;
+ icvLen = 8; /* MIC */
+
+ header[4] |= 0x4000;
+ hlen += 4;
+
+ /* Set iv16 and iv32 */
+ zfApSetStaWpaIv(dev, da, iv16, iv32);
+ }
+ #ifdef ZM_ENABLE_CENC
+ else if (encryType == ZM_CENC)
+ {
+ u32_t txiv[4];
+ u8_t keyIdx;
+
+ /* Get CENC TxIV */
+ zfApGetStaCencIvAndKeyIdx(dev, da, txiv, &keyIdx);
+
+ txiv[0] += 2;
+
+ if (txiv[0] == 0 || txiv[0] == 1)
+ {
+ txiv[1]++;
+ }
+
+ if (txiv[1] == 0)
+ {
+ txiv[2]++;
+ }
+
+ if (txiv[2] == 0)
+ {
+ txiv[3]++;
+ }
+
+ if (txiv[3] == 0)
+ {
+ txiv[0] = 0;
+ txiv[1] = 0;
+ txiv[2] = 0;
+ }
+
+ header[hlen] = (keyIdx & 0x0001); /* For Key Id and reserved field */
+ header[hlen+1] = (u16_t)txiv[0];
+ header[hlen+2] = (u16_t)(txiv[0] >> 16);
+ header[hlen+3] = (u16_t)txiv[1];
+ header[hlen+4] = (u16_t)(txiv[1] >> 16);
+ header[hlen+5] = (u16_t)txiv[2];
+ header[hlen+6] = (u16_t)(txiv[2] >> 16);
+ header[hlen+7] = (u16_t)txiv[3];
+ header[hlen+8] = (u16_t)(txiv[3] >> 16);
+
+ macCtrl |= 0x80;
+ icvLen = 16; /* MIC */
+
+ header[4] |= 0x4000;
+ hlen += 9;
+
+ /* Set CENC IV */
+ zfApSetStaCencIv(dev, da, txiv);
+ }
+ #endif //ZM_ENABLE_CENC
+ }
+
+ /* protection mode */
+ if (wd->ap.protectionMode == 1)
+ {
+ /* Enable Self-CTS */
+ macCtrl &= 0xFFFC;
+ macCtrl |= 2;
+ }
+
+ /* Rate Control */
+ if (port < 0x20)
+ {
+ /* AP */
+ /* IV */
+ if ((wd->ap.encryMode[vap] == ZM_WEP64) ||
+ (wd->ap.encryMode[vap] == ZM_WEP128) ||
+ (wd->ap.encryMode[vap] == ZM_WEP256))
+ {
+ header[4] |= 0x4000;
+ header[hlen] = 0x0; //IV
+ header[hlen+1] = wd->ap.bcKeyIndex[vap] << 14; //IV with Keyid--CWYang(m)
+ hlen += 2;
+ icvLen = 4;
+ macCtrl |= 0x40;
+ }
+ }
+ else
+ {
+ /* WDS */
+
+ /* TODO : Fixed rate to 54M */
+ phyCtrl = 0xc0001; //PHY control L
+
+ /* WDS port checking */
+ if ((wdsPort = (port - 0x20)) >= ZM_MAX_WDS_SUPPORT)
+ {
+ wdsPort = 0;
+ }
+
+ #if 1
+ /* IV */
+ switch (wd->ap.wds.encryMode[wdsPort])
+ {
+ case ZM_WEP64:
+ case ZM_WEP128:
+ case ZM_WEP256:
+ header[4] |= 0x4000;
+ header[hlen] = 0x0; //IV
+ header[hlen+1] = wd->ap.bcKeyIndex[vap] << 14; //IV with Keyid
+ hlen += 2;
+ icvLen = 4;
+ macCtrl |= 0x40;
+ break;
+
+ case ZM_TKIP:
+ wd->sta.iv16++;
+
+ if ( wd->sta.iv16 == 0 )
+ {
+ wd->sta.iv32++;
+ }
+
+ b1 = (u8_t) (wd->sta.iv16 >> 8);
+ b2 = (b1 | 0x20) & 0x7f;
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ b1 = (u8_t) wd->sta.iv16;
+ b2 = 0x20;
+ header[hlen+1] = ((u16_t)b2 << 8) + b1;
+ header[hlen+2] = (u16_t) wd->sta.iv32;
+ header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
+
+ //macCtrl |= 0x80;
+ macCtrl |= 0x40;
+ icvLen = 4;
+
+ /* set hardware MIC */
+ if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
+ {
+ macCtrl |= 0x100;
+ plusLen += 8;
+ *micLen = 8;
+ }
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ break;
+
+ case ZM_AES:
+ wd->sta.iv16++;
+ if ( wd->sta.iv16 == 0 )
+ {
+ wd->sta.iv32++;
+ }
+
+ b1 = (u8_t) wd->sta.iv16;
+ b2 = (u8_t) (wd->sta.iv16 >> 8);
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ header[hlen+1] = 0x2000;
+ header[hlen+2] = (u16_t) (wd->sta.iv32);
+ header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
+
+ macCtrl |= 0xc0; /* Set to AES in control setting */
+ icvLen = 8; /* MIC */
+
+ header[4] |= 0x4000; /* Set WEP bit in wlan header */
+ hlen += 4; /* plus IV length */
+ break;
+ }/* end of switch */
+ #endif
+ }
+ }
+ else /* wd->wlanMode != ZM_MODE_AP */
+ {
+ encExemptionActionType = zfwGetPktEncExemptionActionType(dev, buf);
+
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ #if 1
+ /* if WME AP */
+ if (wd->sta.wmeConnected != 0)
+ {
+ /* QoS data */
+ header[4] |= 0x0080;
+
+ /* QoS Control */
+ header[hlen] = up;
+ hlen += 1;
+ }
+ #endif
+
+ if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
+ {
+ if ( wd->sta.authMode < ZM_AUTH_MODE_WPA )
+ { /* non-WPA */
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED )
+ {
+ if ( (wd->sta.encryMode == ZM_WEP64)||
+ (wd->sta.encryMode == ZM_WEP128)||
+ (wd->sta.encryMode == ZM_WEP256) )
+ {
+ header[4] |= 0x4000;
+ header[hlen] = 0x0; //IV
+ header[hlen+1] = 0x0; //IV
+ header[hlen+1] |= (((u16_t) wd->sta.keyId) << 14);
+ hlen += 2;
+ icvLen = 4;
+
+ /* For Software WEP */
+ if ((wd->sta.SWEncryptEnable & ZM_SW_WEP_ENCRY_EN) != 0)
+ {
+ u8_t keyLen = 5;
+ u8_t iv[3];
+
+ iv[0] = 0x0;
+ iv[1] = 0x0;
+ iv[2] = 0x0;
+
+ if (wd->sta.SWEncryMode[wd->sta.keyId] == ZM_WEP64)
+ {
+ keyLen = 5;
+ }
+ else if (wd->sta.SWEncryMode[wd->sta.keyId] == ZM_WEP128)
+ {
+ keyLen = 13;
+ }
+ else if (wd->sta.SWEncryMode[wd->sta.keyId] == ZM_WEP256)
+ {
+ keyLen = 29;
+ }
+
+ zfWEPEncrypt(dev, buf, (u8_t*) snap, snapLen, minusLen, keyLen,
+ wd->sta.wepKey[wd->sta.keyId], iv);
+ }
+ else
+ {
+ macCtrl |= 0x40;
+ }
+ }
+ }
+ }
+ else
+ { /* WPA */
+ if ( wd->sta.wpaState >= ZM_STA_WPA_STATE_PK_OK )
+ {
+ wd->sta.iv16++;
+ if ( wd->sta.iv16 == 0 )
+ {
+ wd->sta.iv32++;
+ }
+
+ /* set encryption mode */
+ if ( wd->sta.encryMode == ZM_TKIP )
+ {
+ b1 = (u8_t) (wd->sta.iv16 >> 8);
+ b2 = (b1 | 0x20) & 0x7f;
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ b1 = (u8_t) wd->sta.iv16;
+ b2 = 0x20;
+
+ // header[hlen+1] = (((u16_t) wd->sta.keyId) << 14) | (((u16_t)b2 << 8) + b1);
+ // STA in infrastructure mode should use keyId = 0 to transmit unicast !
+ header[hlen+1] = (((u16_t)b2 << 8) + b1);
+ header[hlen+2] = (u16_t) wd->sta.iv32;
+ header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
+
+ /* If software encryption enable */
+ if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_ENCRY_EN) == 0)
+ {
+ //macCtrl |= 0x80;
+ /* TKIP same to WEP */
+ macCtrl |= 0x40;
+ icvLen = 4;
+
+ /* set hardware MIC */
+ if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
+ {
+ macCtrl |= 0x100;
+ plusLen += 8;
+ *micLen = 8;
+ }
+ }
+ else
+ {
+ u8_t mic[8];
+ u16_t offset;
+ u32_t icv;
+ u8_t RC4Key[16];
+
+ /* TODO: Remove the criticial section here. */
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ /* Calculate MIC */
+ zfCalTxMic(dev, buf, (u8_t *)snap, snapLen, minusLen, da, sa, up, mic);
+
+ offset = zfwBufGetSize(dev, buf);
+
+ /* Append MIC to the buffer */
+ zfCopyToIntTxBuffer(dev, buf, mic, offset, 8);
+ zfwBufSetSize(dev, buf, offset+8);
+ zmw_leave_critical_section(dev);
+
+ /* TKIP Key Mixing */
+ zfTkipPhase1KeyMix(wd->sta.iv32, &wd->sta.txSeed);
+ zfTkipPhase2KeyMix(wd->sta.iv16, &wd->sta.txSeed);
+ zfTkipGetseeds(wd->sta.iv16, RC4Key, &wd->sta.txSeed);
+
+ /* Encrypt Data */
+ zfTKIPEncrypt(dev, buf, (u8_t *)snap, snapLen, minusLen, 16, RC4Key, &icv);
+
+ icvLen = 4;
+ len += 8;
+ }
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ }
+ else if ( wd->sta.encryMode == ZM_AES )
+ {
+ b1 = (u8_t) wd->sta.iv16;
+ b2 = (u8_t) (wd->sta.iv16 >> 8);
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ // header[hlen+1] = (((u16_t) wd->sta.keyId) << 14) | (0x2000);
+ // STA in infrastructure mode should use keyId = 0 to transmit unicast !
+ header[hlen+1] = 0x2000;
+ header[hlen+2] = (u16_t) (wd->sta.iv32);
+ header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
+
+ macCtrl |= 0xc0;
+ icvLen = 8; /* MIC */
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ }
+ #ifdef ZM_ENABLE_CENC
+ else if ( wd->sta.encryMode == ZM_CENC )
+ {
+ /* Accumlate the PN sequence */
+ wd->sta.txiv[0] += 2;
+
+ if (wd->sta.txiv[0] == 0 || wd->sta.txiv[0] == 1)
+ {
+ wd->sta.txiv[1]++;
+ }
+
+ if (wd->sta.txiv[1] == 0)
+ {
+ wd->sta.txiv[2]++;
+ }
+
+ if (wd->sta.txiv[2] == 0)
+ {
+ wd->sta.txiv[3]++;
+ }
+
+ if (wd->sta.txiv[3] == 0)
+ {
+ wd->sta.txiv[0] = 0;
+ wd->sta.txiv[1] = 0;
+ wd->sta.txiv[2] = 0;
+ }
+
+ header[hlen] = (wd->sta.cencKeyId & 0x0001); /* For Key Id and reserved field */
+ header[hlen+1] = (u16_t) wd->sta.txiv[0];
+ header[hlen+2] = (u16_t) (wd->sta.txiv[0] >> 16);
+ header[hlen+3] = (u16_t) wd->sta.txiv[1];
+ header[hlen+4] = (u16_t) (wd->sta.txiv[1] >> 16);
+ header[hlen+5] = (u16_t) wd->sta.txiv[2];
+ header[hlen+6] = (u16_t) (wd->sta.txiv[2] >> 16);
+ header[hlen+7] = (u16_t) wd->sta.txiv[3];
+ header[hlen+8] = (u16_t) (wd->sta.txiv[3] >> 16);
+
+ macCtrl |= 0x80;
+ icvLen = 16; /* MIC */
+
+ header[4] |= 0x4000;
+ hlen += 9;
+ }
+ #endif //ZM_ENABLE_CENC
+ }
+ }
+ } // if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
+ } /* if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE ) */
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
+ {
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ if( wd->sta.oppositeInfo[userIdx].wpaState >= ZM_STA_WPA_STATE_PK_OK || wd->sta.wpaState >= ZM_STA_WPA_STATE_PK_OK)
+ {
+ int isUnicast = 1 ;
+
+ if((da[0]& 0x1))
+ {
+ isUnicast = 0 ; // Not unicast , is broadcast
+ }
+
+ if( wd->sta.ibssWpa2Psk == 1 )
+ { /* The IV order is not the same between unicast and broadcast ! */
+ if ( isUnicast )
+ {
+ iv16 = &wd->sta.oppositeInfo[userIdx].iv16;
+ iv32 = &wd->sta.oppositeInfo[userIdx].iv32;
+ }
+ else
+ {
+ iv16 = &wd->sta.iv16;
+ iv32 = &wd->sta.iv32;
+ }
+ }
+ else
+ {
+ iv16 = &wd->sta.iv16;
+ iv32 = &wd->sta.iv32;
+ }
+
+ (*iv16)++;
+ if ( *iv16 == 0 )
+ {
+ *iv32++;
+ }
+
+ if ( wd->sta.oppositeInfo[userIdx].encryMode == ZM_AES || wd->sta.encryMode == ZM_AES)
+ {
+ //printk("Station encryption mode is AES-CCMP\n") ;
+ b1 = (u8_t) (*iv16);
+ b2 = (u8_t) ((*iv16) >> 8);
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+
+ if ( isUnicast )
+ {
+ header[hlen+1] = 0x2000;
+ }
+ else
+ {
+ header[hlen+1] = 0x2000 | (((u16_t) wd->sta.keyId) << 14);
+ }
+
+ header[hlen+2] = (u16_t) (*iv32);
+ header[hlen+3] = (u16_t) ((*iv32) >> 16);
+ macCtrl |= 0xc0;
+ icvLen = 8; /* MIC */
+ }
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ }
+ else if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED)
+ {
+ if ( (wd->sta.encryMode == ZM_WEP64)||
+ (wd->sta.encryMode == ZM_WEP128)||
+ (wd->sta.encryMode == ZM_WEP256) )
+ {
+ header[4] |= 0x4000;
+ header[hlen] = 0x0; //IV
+ header[hlen+1] = 0x0; //IV
+ header[hlen+1] |= (((u16_t) wd->sta.keyId) << 14);
+ hlen += 2;
+ icvLen = 4;
+ macCtrl |= 0x40;
+ }
+ }
+#else
+ /* ----- 20070405 add by Mxzeng ----- */
+ if( wd->sta.wpaState >= ZM_STA_WPA_STATE_PK_OK )
+ {
+ int isUnicast = 1 ;
+
+ if((da[0]& 0x1))
+ {
+ isUnicast = 0 ; // Not unicast , is broadcast
+ }
+
+ wd->sta.iv16++;
+ if ( wd->sta.iv16 == 0 )
+ {
+ wd->sta.iv32++;
+ }
+
+ if ( wd->sta.encryMode == ZM_AES )
+ {
+ //printk("Station encryption mode is AES-CCMP\n") ;
+ b1 = (u8_t) wd->sta.iv16;
+ b2 = (u8_t) (wd->sta.iv16 >> 8);
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+
+ if ( isUnicast )
+ {
+ header[hlen+1] = 0x2000;
+ }
+ else
+ {
+ header[hlen+1] = 0x2000 | (((u16_t) wd->sta.keyId) << 14);
+ }
+
+ header[hlen+2] = (u16_t) (wd->sta.iv32);
+ header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
+ macCtrl |= 0xc0;
+ icvLen = 8; /* MIC */
+ }
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ }
+ else if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED)
+ {
+ if ( (wd->sta.encryMode == ZM_WEP64)||
+ (wd->sta.encryMode == ZM_WEP128)||
+ (wd->sta.encryMode == ZM_WEP256) )
+ {
+ header[4] |= 0x4000;
+ header[hlen] = 0x0; //IV
+ header[hlen+1] = 0x0; //IV
+ header[hlen+1] |= (((u16_t) wd->sta.keyId) << 14);
+ hlen += 2;
+ icvLen = 4;
+ macCtrl |= 0x40;
+ }
+ }
+#endif
+ } // End if ( encExemptionActionType == ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION )
+ } // End if ( wd->wlanMode == ZM_MODE_IBSS )
+ else if ( wd->wlanMode == ZM_MODE_PSEUDO )
+ {
+ switch (wd->sta.encryMode)
+ {
+ case ZM_WEP64:
+ case ZM_WEP128:
+ case ZM_WEP256:
+ header[4] |= 0x4000;
+ header[hlen] = 0x0; //IV
+ header[hlen+1] = 0x0; //IV
+ hlen += 2;
+ icvLen = 4;
+ macCtrl |= 0x40;
+ break;
+
+ case ZM_TKIP:
+ {
+ wd->sta.iv16++;
+ if ( wd->sta.iv16 == 0 )
+ {
+ wd->sta.iv32++;
+ }
+
+ b1 = (u8_t) (wd->sta.iv16 >> 8);
+ b2 = (b1 | 0x20) & 0x7f;
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ b1 = (u8_t) wd->sta.iv16;
+ b2 = 0x20;
+ header[hlen+1] = ((u16_t)b2 << 8) + b1;
+ header[hlen+2] = (u16_t) wd->sta.iv32;
+ header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
+
+ //macCtrl |= 0x80;
+ macCtrl |= 0x40;
+ icvLen = 4;
+
+ /* set hardware MIC */
+ if ( (!(seq & 0xf))&&(!(flag & 0x4)) )
+ {
+ macCtrl |= 0x100;
+ plusLen += 8;
+ *micLen = 8;
+ }
+
+ header[4] |= 0x4000;
+ hlen += 4;
+ }/* end of PSEUDO TKIP */
+ break;
+
+ case ZM_AES:
+ {
+ wd->sta.iv16++;
+ if ( wd->sta.iv16 == 0 )
+ {
+ wd->sta.iv32++;
+ }
+
+ b1 = (u8_t) wd->sta.iv16;
+ b2 = (u8_t) (wd->sta.iv16 >> 8);
+ header[hlen] = ((u16_t)b2 << 8) + b1;
+ header[hlen+1] = 0x2000;
+ header[hlen+2] = (u16_t) (wd->sta.iv32);
+ header[hlen+3] = (u16_t) (wd->sta.iv32 >> 16);
+ macCtrl |= 0xc0;
+ icvLen = 8; /* MIC */
+ header[4] |= 0x4000;
+ hlen += 4;
+ }/* end of PSEUDO AES */
+ break;
+
+ #ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+ /* Accumlate the PN sequence */
+ wd->sta.txiv[0] += 2;
+
+ if (wd->sta.txiv[0] == 0 || wd->sta.txiv[0] == 1)
+ {
+ wd->sta.txiv[1]++;
+ }
+
+ if (wd->sta.txiv[1] == 0)
+ {
+ wd->sta.txiv[2]++;
+ }
+
+ if (wd->sta.txiv[2] == 0)
+ {
+ wd->sta.txiv[3]++;
+ }
+
+ if (wd->sta.txiv[3] == 0)
+ {
+ wd->sta.txiv[0] = 0;
+ wd->sta.txiv[1] = 0;
+ wd->sta.txiv[2] = 0;
+ }
+
+ header[hlen] = 0;
+ header[hlen+1] = (u16_t) wd->sta.txiv[0];
+ header[hlen+2] = (u16_t) (wd->sta.txiv[0] >> 16);
+ header[hlen+3] = (u16_t) wd->sta.txiv[1];
+ header[hlen+4] = (u16_t) (wd->sta.txiv[1] >> 16);
+ header[hlen+5] = (u16_t) wd->sta.txiv[2];
+ header[hlen+6] = (u16_t) (wd->sta.txiv[2] >> 16);
+ header[hlen+7] = (u16_t) wd->sta.txiv[3];
+ header[hlen+8] = (u16_t) (wd->sta.txiv[3] >> 16);
+
+ macCtrl |= 0x80;
+ icvLen = 16; /* MIC */
+
+ header[4] |= 0x4000;
+ hlen += 9;
+ break;
+ #endif //ZM_ENABLE_CENC
+ }/* end of switch */
+ }
+
+ /* Generate control setting */
+
+ /* protection mode */
+ if (wd->enableProtectionMode)
+ {
+ if (wd->enableProtectionMode==2)
+ {
+ /* Force enable protection: self cts */
+ macCtrl &= 0xFFFC;
+ macCtrl |= 2;
+ }
+ /* if wd->enableProtectionMode=1 => force disable */
+ /* if wd->enableProtectionMode=0 => auto */
+ }
+ else
+ {
+
+ /* protection mode */
+ if (wd->sta.bProtectionMode == TRUE)
+ {
+ /* Enable Self-CTS */
+ macCtrl &= 0xFFFC;
+ macCtrl |= 2;
+ }
+ }
+
+ }
+
+ if (wd->txMCS != 0xff)
+ {
+ /* fixed rate */
+ phyCtrl = ((u32_t)wd->txMCS<<16) + wd->txMT;
+ mcs = wd->txMCS;
+ mt = wd->txMT;
+ }
+
+ if (mt == 2)
+ {
+#if 0
+ /* HT PT: 0 Mixed mode 1 Green field */
+ if (wd->sta.preambleTypeHT == ZM_PREAMBLE_TYPE_GREEN_FIELD)
+ {
+ phyCtrl |= 0x4; /* Bit 2 */
+ }
+#endif
+ /* Bandwidth */
+ if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
+ {
+ phyCtrl |= (0x80<<16); /* BIT 23 */
+ }
+#if 0
+ /* STBC */
+ if (wd->sta.htCtrlSTBC<=0x3)
+ {
+ phyCtrl |= (wd->sta.htCtrlSTBC<<28); /* BIT 23 */
+ }
+#endif
+ /* Short GI */
+ if(wd->sta.htCtrlSG)
+ {
+ phyCtrl |= (0x8000<<16); /* BIT 31 */
+ }
+
+ /* TA */
+ if ( ((mcs >=0x8) && (mcs<=0xf)) || (wd->sta.htCtrlSTBC) )
+ {
+ phyCtrl |= 0x1800; /* BIT 11 12 */
+ }
+ }
+ else if(mt == 1)
+ {
+ #if 0
+ //bug that cause OFDM rate become duplicate legacy rate
+ /* Bandwidth */
+ if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
+ {
+ phyCtrl |= (0x80<<16); /* BIT 23 */
+ mt = 3; /* duplicate legacy */
+ phyCtrl |= mt;
+ }
+ #endif
+ }
+ else if(mt == 0)
+ {
+ /* CCK PT: Legcy Preamble: 1 long preamble 2 short preamble */
+ if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_SHORT)
+ {
+ //phyCtrl |= 0x4; /* BIT 2 */
+ }
+ }
+
+ /* TA */
+ if (wd->sta.defaultTA)
+ {
+ phyCtrl |= 0x1000;
+ }
+ else
+ {
+ phyCtrl |= 0x0800;
+ }
+
+ //Get CurrentTxRate -- CWYang(+)
+ if ((mt == 0) || (mt == 1)) //B,G Rate
+ {
+ if (mcs < 16)
+ {
+ wd->CurrentTxRateKbps = zcIndextoRateBG[mcs];
+ }
+ }
+ else if (mt == 2)
+ {
+ if (mcs < 16)
+ {
+ if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ)
+ {
+ if((phyCtrl & 0x80000000) != 0)
+ {
+ /* Short GI 40 MHz MIMO Rate */
+ wd->CurrentTxRateKbps = zcIndextoRateN40S[mcs];
+ }
+ else
+ {
+ /* Long GI 40 MHz MIMO Rate */
+ wd->CurrentTxRateKbps = zcIndextoRateN40L[mcs];
+ }
+ }
+ else
+ {
+ if((phyCtrl & 0x80000000) != 0)
+ {
+ /* Short GI 20 MHz MIMO Rate */
+ wd->CurrentTxRateKbps = zcIndextoRateN20S[mcs];
+ }
+ else
+ {
+ /* Long GI 20 MHz MIMO Rate */
+ wd->CurrentTxRateKbps = zcIndextoRateN20L[mcs];
+ }
+ }
+ }
+ }
+
+ //802.11 header(include IV) = (hlen<<1)-8
+ //ethernet frame = len
+ //snap + mic = plusLen
+ //ethernet header = minusLen
+ //icv = icvLen
+ //crc32 = 4
+ //length=802.11 header+snap+(ethernet frame-ethernet header)+mic+icv+crc32
+ header[0] = ((hlen<<1)-8)+plusLen+(len-minusLen)+icvLen+4; //Length
+
+ // header[0] : MPDU Lengths
+ if ((header[6] & 0x1) != 0x1) // Unicast Frame
+ {
+ if (header[0] >= wd->rtsThreshold)
+ {
+ /* Enable RTS */
+ macCtrl |= 1;
+ }
+ }
+
+ if ( wd->sta.encryMode == ZM_TKIP )
+ tkipFrameOffset = 8;
+
+ if( wd->sta.EnableHT != 1 )
+ { // Aggregation should not be fragmented !
+ if ( header[0] > ( wd->fragThreshold + tkipFrameOffset ) )
+ {
+ return 0; // Need to be fragmented ! !
+ }
+ }
+
+ //if ( wd->sta.encryMode == ZM_TKIP )
+ //{
+ // zm_debug_msg1("ctrl length = ", header[0]);
+ //}
+
+ //MAC control
+ if (rateProbingFlag != 0)
+ {
+ macCtrl |= 0x8000;
+ }
+ header[1] = macCtrl;
+ //PHY control L
+ header[2] = (u16_t) ((phyCtrl&0xffff) | 0x700 | (zcUpToAc[up&0x7]<<13));
+ //PHY control H
+ header[3] = (u16_t) ((phyCtrl>>16) | 0x700);
+
+ if (wd->enableAggregation)
+ {
+ /* force enable aggregation */
+ if (wd->enableAggregation==2 && !(header[6]&0x1))
+ {
+ if (((header[2] & 0x3) == 2))
+ {
+ /* Enable aggregation */
+ header[1] |= 0x20;
+ }
+ }
+ /* if wd->enableAggregation=1 => force disable */
+ /* if wd->enableAggregation=0 => auto */
+ }
+
+#ifdef ZM_ENABLE_AGGREGATION
+ if (wd->addbaComplete) {
+ #ifdef ZM_BYPASS_AGGR_SCHEDULING
+ if (!(header[6]&0x1) && !rateProbingFlag && (wd->enableAggregation != 1))
+ {
+ if (((header[2] & 0x3) == 2))
+ {
+ /* Unicast frame with HT rate => Enable aggregation */
+ /* We only support software encryption in single packet mode */
+ if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_ENCRY_EN) == 0 &&
+ (wd->sta.SWEncryptEnable & ZM_SW_WEP_ENCRY_EN) == 0)
+ {
+ /* Set aggregation group bits per AC */
+ header[1] |= (0x20 | (zcUpToAc[up&0x7]<<10));
+
+ //if (wd->sta.currentFrequency < 3000)
+ {
+ /* issue: -PB42 Enable RTS/CTS to prevent OWL Tx hang up */
+ /* If this is Owl Ap, enable RTS/CTS protect */
+ if ( (wd->sta.athOwlAp == 1) || (wd->sta.RTSInAGGMode == TRUE) )
+ {
+ header[1] &= 0xfffc;
+ header[1] |= 0x1;
+ }
+
+ /* Enable RIFS : workaround 854T RTS/CTS */
+ /* Bit13 : TI enable RIFS */
+ //header[1] |= 0x2000;
+ }
+ }
+ }
+ }
+ #else
+ /*
+ * aggregation ampduIndication control
+ */
+ if (aggControl && aggControl->aggEnabled) {
+ if (wd->enableAggregation==0 && !(header[6]&0x1))
+ {
+ if (((header[2] & 0x3) == 2))
+ {
+ /* Enable aggregation */
+ header[1] |= 0x20;
+ if (ZM_AGG_LAST_MPDU == aggControl->ampduIndication)
+ header[1] |= 0x4000;
+ }
+ else {
+ zm_debug_msg1("no aggr, header[2]&0x3 = ",header[2] & 0x3)
+ aggControl->aggEnabled = 0;
+ }
+ }
+ else {
+ zm_debug_msg1("no aggr, wd->enableAggregation = ", wd->enableAggregation);
+ zm_debug_msg1("no aggr, !header[6]&0x1 = ",!(header[6]&0x1));
+ aggControl->aggEnabled = 0;
+ }
+ }
+ #endif
+
+ #ifdef ZM_AGGR_BIT_ON
+ if (!(header[6]&0x1) && !rateProbingFlag)
+ {
+ if (((header[2] & 0x3) == 2))
+ {
+ /* Unicast frame with HT rate => Enable aggregation */
+ /* Set aggregation group bits per AC */
+ header[1] |= (0x20 | (zcUpToAc[up&0x7]<<10));
+
+ //if (wd->sta.currentFrequency < 3000)
+ {
+ /* Enable RTS/CTS to prevent OWL Tx hang up */
+ header[1] &= 0xfffc;
+ header[1] |= 0x1;
+ }
+ }
+ }
+ #endif
+ }
+#endif
+
+ return (hlen<<1);
+}
+
+
+u16_t zfTxGenMmHeader(zdev_t* dev, u8_t frameType, u16_t* dst,
+ u16_t* header, u16_t len, zbuf_t* buf, u16_t vap, u8_t encrypt)
+{
+ //u16_t bodyLen;
+ u8_t hlen = 32; // MAC ctrl + PHY ctrl + 802.11 MM header
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ /* Generate control setting */
+ //bodyLen = zfwBufGetSize(dev, buf);
+ header[0] = 24+len+4; //Length
+ if ((dst[0] & 0x1) != 0) //Broadcast, multicast frames
+ {
+ header[1] = 0xc; //MAC control, backoff + noack
+ }
+ else
+ {
+ header[1] = 0x8; //MAC control, backoff + (ack)
+ }
+ /* Dualband Management frame tx Rate */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ if (wd->frequency < 3000)
+ {
+ /* CCK 1M */
+ header[2] = 0x0f00; //PHY control L
+ header[3] = 0x0000; //PHY control H
+ }
+ else
+ {
+ /* CCK 6M */
+ header[2] = 0x0f01; //PHY control L
+ header[3] = 0x000B; //PHY control H
+ }
+ }
+ else
+ {
+ if (wd->sta.currentFrequency < 3000)
+ {
+ /* CCK 2M */
+ header[2] = 0x0f00; //PHY control L
+ header[3] = 0x0001; //PHY control H
+ }
+ else
+ {
+ /* CCK 6M */
+ header[2] = 0x0f01; //PHY control L
+ header[3] = 0x000B; //PHY control H
+ }
+ }
+ /* Generate WLAN header */
+ /* Frame control */
+ header[4+0] = frameType;
+ /* Duration */
+ header[4+1] = 0;
+
+ if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ if ( frameType == ZM_WLAN_FRAME_TYPE_PROBEREQ )
+ {
+ header[4+8] = 0xFFFF;
+ header[4+9] = 0xFFFF;
+ header[4+10] = 0xFFFF;
+ }
+ else if ( frameType == ZM_WLAN_FRAME_TYPE_BA ) {
+ /* do nothing */
+ }
+ else
+ {
+ header[4+8] = wd->sta.bssid[0];
+ header[4+9] = wd->sta.bssid[1];
+ header[4+10] = wd->sta.bssid[2];
+ }
+ }
+ else if (wd->wlanMode == ZM_MODE_PSEUDO)
+ {
+ /* Address 3 = 00:00:00:00:00:00 */
+ header[4+8] = 0;
+ header[4+9] = 0;
+ header[4+10] = 0;
+ }
+ else if (wd->wlanMode == ZM_MODE_IBSS)
+ {
+ header[4+8] = wd->sta.bssid[0];
+ header[4+9] = wd->sta.bssid[1];
+ header[4+10] = wd->sta.bssid[2];
+
+ if ( frameType == ZM_WLAN_FRAME_TYPE_ATIM )
+ {
+ /* put ATIM to queue 5th */
+ //header[2] |= (ZM_BIT_13|ZM_BIT_14);
+ header[2] |= ZM_BIT_15;
+ }
+ }
+ else if (wd->wlanMode == ZM_MODE_AP)
+ {
+ /* Address 3 = BSSID */
+ header[4+8] = wd->macAddr[0];
+ header[4+9] = wd->macAddr[1];
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ header[4+10] = wd->macAddr[2]; //Multiple SSID
+#else
+ header[4+10] = wd->macAddr[2] + (vap<<8); //VAP
+#endif
+ //if in scan, must set address 3 to broadcast because of some ap would care this
+ //if ((wd->heartBeatNotification & ZM_BSSID_LIST_SCAN)
+ // == ZM_BSSID_LIST_SCAN)
+ //if FrameType is Probe Request, Address3 should be boradcast
+ if (frameType == ZM_WLAN_FRAME_TYPE_PROBEREQ)
+ {
+ header[4+8] = 0xFFFF;
+ header[4+9] = 0xFFFF;
+ header[4+10] = 0xFFFF;
+ }
+ }
+
+ /* Address 1 = DA */
+ header[4+2] = dst[0];
+ header[4+3] = dst[1];
+ header[4+4] = dst[2];
+
+ /* Address 2 = SA */
+ header[4+5] = wd->macAddr[0];
+ header[4+6] = wd->macAddr[1];
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ header[4+7] = wd->macAddr[2]; //Multiple SSID
+#else
+ header[4+7] = wd->macAddr[2] + (vap<<8); //VAP
+#endif
+ }
+ else
+ {
+ header[4+7] = wd->macAddr[2];
+ }
+
+ /* Sequence Control */
+ zmw_enter_critical_section(dev);
+ header[4+11] = ((wd->mmseq++)<<4);
+ zmw_leave_critical_section(dev);
+
+ if( frameType == ZM_WLAN_FRAME_TYPE_QOS_NULL )
+ {
+ /*Qos Control*/
+ header[4+12] = 0x0;
+ hlen+=2;
+ header[0]+=2;
+ }
+
+ if ( encrypt )
+ {
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED )
+ {
+ if ( (wd->sta.encryMode == ZM_WEP64)||
+ (wd->sta.encryMode == ZM_WEP128)||
+ (wd->sta.encryMode == ZM_WEP256) )
+ {
+ header[4] |= 0x4000;
+ header[16] = 0x0; //IV
+ header[17] = 0x0; //IV
+ header[17] |= (((u16_t) wd->sta.keyId) << 14);
+ hlen += 4;
+
+ header[0] += 8; // icvLen = 4;
+ header[1] |= 0x40; // enable encryption on macCtrl
+ }
+ }
+ }
+
+ // Enable HW duration
+ if ( frameType != ZM_WLAN_FRAME_TYPE_PSPOLL )
+ {
+ header[1] |= 0x200;
+ }
+
+ return hlen;
+}
+
+void zfInitMacApMode(zdev_t* dev)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zfHpEnableBeacon(dev, ZM_MODE_AP, (wd->beaconInterval/wd->ap.vapNumber), 1, 0);
+
+ /* AP mode */
+ zfHpSetApStaMode(dev, ZM_HAL_80211_MODE_AP);
+
+ /* VAP test code */
+ /* AP + VAP mode */
+ if (wd->ap.vapNumber >= 2)
+ {
+ for (i=1; i<ZM_MAX_AP_SUPPORT; i++)
+ {
+ if (((wd->ap.apBitmap >> i) & 0x1) != 0)
+ {
+ u16_t mac[3];
+ mac[0] = wd->macAddr[0];
+ mac[1] = wd->macAddr[1];
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ mac[2] = wd->macAddr[2]; //Multiple SSID
+#else
+ mac[2] = wd->macAddr[2] + (i<<8); //VAP
+#endif
+ zfHpSetMacAddress(dev, mac, i);
+
+ }
+ }
+ }
+
+ /* basic rate setting */
+ zfHpSetBasicRateSet(dev, wd->bRateBasic, wd->gRateBasic);
+
+ /* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME AP default. */
+ zfUpdateDefaultQosParameter(dev, 1);
+
+ return;
+}
+
+u16_t zfChGetNextChannel(zdev_t* dev, u16_t frequency, u8_t* pbPassive)
+{
+ u8_t i;
+ u8_t bPassive;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Avoid NULL value */
+ if ( pbPassive == NULL )
+ {
+ pbPassive = &bPassive;
+ }
+
+ for( i=0; i<wd->regulationTable.allowChannelCnt; i++ )
+ {
+ if ( wd->regulationTable.allowChannel[i].channel == frequency )
+ {
+ if ( i == (wd->regulationTable.allowChannelCnt-1) )
+ {
+ i = 0;
+ }
+ else
+ {
+ i++;
+ }
+
+ if ( wd->regulationTable.allowChannel[i].channelFlags
+ & ZM_REG_FLAG_CHANNEL_PASSIVE )
+ {
+ *pbPassive = TRUE;
+ }
+ else
+ {
+ *pbPassive = FALSE;
+ }
+
+ return wd->regulationTable.allowChannel[i].channel;
+ }
+ }
+
+ return 0xffff;
+}
+
+u16_t zfChGetFirstChannel(zdev_t* dev, u8_t* pbPassive)
+{
+ u8_t bPassive;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Avoid NULL value */
+ if ( pbPassive == NULL )
+ {
+ pbPassive = &bPassive;
+ }
+
+ if ( wd->regulationTable.allowChannel[0].channelFlags & ZM_REG_FLAG_CHANNEL_PASSIVE )
+ {
+ *pbPassive = TRUE;
+ }
+ else
+ {
+ *pbPassive = FALSE;
+ }
+
+ return wd->regulationTable.allowChannel[0].channel;
+}
+
+u16_t zfChGetFirst2GhzChannel(zdev_t* dev)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for( i=0; i<wd->regulationTable.allowChannelCnt; i++ )
+ {
+ if ( wd->regulationTable.allowChannel[i].channel < 3000 )
+ {
+ /* find the first 2Ghz channel */
+ return wd->regulationTable.allowChannel[i].channel;
+ }
+ }
+
+ /* Can not find any 2Ghz channel */
+ return 0;
+}
+
+u16_t zfChGetFirst5GhzChannel(zdev_t* dev)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for( i=0; i<wd->regulationTable.allowChannelCnt; i++ )
+ {
+ if ( wd->regulationTable.allowChannel[i].channel > 3000 )
+ {
+ /* find the first 5Ghz channel */
+ return wd->regulationTable.allowChannel[i].channel;
+ }
+ }
+
+ /* Can not find any 5Ghz channel */
+ return 0;
+}
+
+u16_t zfChGetLastChannel(zdev_t* dev, u8_t* pbPassive)
+{
+ u8_t bPassive;
+ u8_t ChannelIndex;
+
+ zmw_get_wlan_dev(dev);
+
+ ChannelIndex = wd->regulationTable.allowChannelCnt-1;
+
+ /* Avoid NULL value */
+ if ( pbPassive == NULL )
+ {
+ pbPassive = &bPassive;
+ }
+
+ if ( wd->regulationTable.allowChannel[ChannelIndex].channelFlags
+ & ZM_REG_FLAG_CHANNEL_PASSIVE )
+ {
+ *pbPassive = TRUE;
+ }
+ else
+ {
+ *pbPassive = FALSE;
+ }
+
+ return wd->regulationTable.allowChannel[ChannelIndex].channel;
+}
+
+u16_t zfChGetLast5GhzChannel(zdev_t* dev)
+{
+ u8_t i;
+ u16_t last5Ghzfrequency;
+
+ zmw_get_wlan_dev(dev);
+
+ last5Ghzfrequency = 0;
+ for( i=0; i<wd->regulationTable.allowChannelCnt; i++ )
+ {
+ if ( wd->regulationTable.allowChannel[i].channel > 3000 )
+ {
+ last5Ghzfrequency = wd->regulationTable.allowChannel[i].channel;
+ }
+ }
+
+ return last5Ghzfrequency;
+}
+
+/* freqBand = 0 => auto check */
+/* = 1 => 2.4 GHz band */
+/* = 2 => 5 GHz band */
+u16_t zfChNumToFreq(zdev_t* dev, u8_t ch, u8_t freqBand)
+{
+ u16_t freq = 0xffff;
+
+ if ( freqBand == 0 )
+ {
+ if (ch > 14)
+ { /* adapter is at 5 GHz band */
+ freqBand = 2;
+ }
+ else
+ {
+ freqBand = 1;
+ }
+ }
+
+ if ( freqBand == 2 )
+ { /* the channel belongs to 5 GHz band */
+ if ( (ch >= 184)&&(ch <= 196) )
+ {
+ freq = 4000 + ch*5;
+ }
+ else
+ {
+ freq = 5000 + ch*5;
+ }
+ }
+ else
+ { /* the channel belongs to 2.4 GHz band */
+ if ( ch == 14 )
+ {
+ freq = ZM_CH_G_14;
+ }
+ else
+ {
+ freq = ZM_CH_G_1 + (ch-1)*5;
+ }
+ }
+
+ return freq;
+}
+
+u8_t zfChFreqToNum(u16_t freq, u8_t* pbIs5GBand)
+{
+ u8_t ch;
+ u8_t Is5GBand;
+
+ /* to avoid NULL value */
+ if ( pbIs5GBand == NULL )
+ {
+ pbIs5GBand = &Is5GBand;
+ }
+
+ *pbIs5GBand = FALSE;
+
+ if ( freq == ZM_CH_G_14 )
+ {
+ ch = 14;
+ }
+ else if ( freq < 4000 )
+ {
+ ch = (freq - ZM_CH_G_1) / 5 + 1;
+ }
+ else if ( freq < 5000 )
+ {
+ ch = (freq - 4000) / 5;
+ *pbIs5GBand = TRUE;
+ }
+ else
+ {
+ ch = (freq - 5000) / 5;
+ *pbIs5GBand = TRUE;
+ }
+
+ return ch;
+}
diff --git a/drivers/staging/otus/80211core/cmm.c b/drivers/staging/otus/80211core/cmm.c
new file mode 100644
index 000000000000..b74379d928f6
--- /dev/null
+++ b/drivers/staging/otus/80211core/cmm.c
@@ -0,0 +1,2141 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : mm.c */
+/* */
+/* Abstract */
+/* This module contains common functions for handle management */
+/* frame. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#include "../hal/hpreg.h"
+
+/* TODO : put all constant tables to a file */
+const u8_t zg11bRateTbl[4] = {2, 4, 11, 22};
+const u8_t zg11gRateTbl[8] = {12, 18, 24, 36, 48, 72, 96, 108};
+
+/* 0xff => element does not exist */
+const u8_t zgElementOffsetTable[] =
+{
+ 4, /* 0 : asoc req */
+ 6, /* 1 : asoc rsp */
+ 10, /* 2 : reasoc req*/
+ 6, /* 3 : reasoc rsp */
+ 0, /* 4 : probe req */
+ 12, /* 5 : probe rsp */
+ 0xff, /* 6 : reserved */
+ 0xff, /* 7 : reserved */
+ 12, /* 8 : beacon */
+ 4, /* 9 : ATIM */
+ 0xff, /* 10 : disasoc */
+ 6, /* 11 : auth */
+ 0xff, /* 12 : deauth */
+ 4, /* 13 : action */
+ 0xff, /* 14 : reserved */
+ 0xff, /* 15 : reserved */
+};
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfFindElement */
+/* Find a specific element in management frame */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : management frame buffer */
+/* eid : target element id */
+/* */
+/* OUTPUTS */
+/* byte offset of target element */
+/* or 0xffff if not found */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfFindElement(zdev_t* dev, zbuf_t* buf, u8_t eid)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id, HTEid=0;
+ u8_t oui[4] = {0x00, 0x50, 0xf2, 0x01};
+ u8_t oui11n[3] = {0x00,0x90,0x4C};
+ u8_t HTType = 0;
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ // jhlee HT 0
+
+ if ((eid == ZM_WLAN_EID_HT_CAPABILITY) ||
+ (eid == ZM_WLAN_EID_EXTENDED_HT_CAPABILITY))
+ {
+ HTEid = eid;
+ eid = ZM_WLAN_EID_WPA_IE;
+ HTType = 1;
+ }
+
+
+ bufLen = zfwBufGetSize(dev, buf);
+ /* Search loop */
+ while ((offset+2)<bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == eid)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 && eid != ZM_WLAN_EID_SSID)
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( eid == ZM_WLAN_EID_WPA_IE )
+ {
+ /* avoid sta to be thought use 11n when find a WPA_IE */
+ if ( (HTType == 0) && zfRxBufferEqualToStr(dev, buf, oui, offset+2, 4) )
+ {
+ return offset;
+ }
+
+ // jhlee HT 0
+ // CWYang(+)
+
+ if ((HTType == 1) && ( zfRxBufferEqualToStr(dev, buf, oui11n, offset+2, 3) ))
+ {
+ if ( zmw_rx_buf_readb(dev, buf, offset+5) == HTEid )
+ {
+ return offset + 5;
+ }
+ }
+
+ }
+ else
+ {
+ return offset;
+ }
+ }
+ /* Advance to next element */
+ #if 1
+ elen = zmw_rx_buf_readb(dev, buf, offset+1);
+ #else
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+ #endif
+
+ offset += (elen+2);
+ }
+ return 0xffff;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfFindWifiElement */
+/* Find a specific Wifi element in management frame */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : management frame buffer */
+/* type : OUI type */
+/* subType : OUI subtype */
+/* */
+/* OUTPUTS */
+/* byte offset of target element */
+/* or 0xffff if not found */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.1 */
+/* */
+/************************************************************************/
+u16_t zfFindWifiElement(zdev_t* dev, zbuf_t* buf, u8_t type, u8_t subtype)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t tmp;
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+ /* Search loop */
+ while ((offset+2)<bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x50)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0xF2)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+5)) == type))
+
+ {
+ if ( subtype != 0xff )
+ {
+ if ( (tmp = zmw_rx_buf_readb(dev, buf, offset+6)) == subtype )
+ {
+ return offset;
+ }
+ }
+ else
+ {
+ return offset;
+ }
+ }
+ }
+ /* Advance to next element */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+ offset += (elen+2);
+ }
+ return 0xffff;
+}
+
+u16_t zfRemoveElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t eid)
+{
+ u16_t offset = 0;
+ u16_t elen;
+ u8_t HTEid = 0;
+ u8_t oui[4] = {0x00, 0x50, 0xf2, 0x01};
+ u8_t oui11n[3] = {0x00,0x90,0x4C};
+ u8_t HTType = 0;
+
+ if ((eid == ZM_WLAN_EID_HT_CAPABILITY) ||
+ (eid == ZM_WLAN_EID_EXTENDED_HT_CAPABILITY))
+ {
+ HTEid = eid;
+ eid = ZM_WLAN_EID_WPA_IE;
+ HTType = 1;
+ }
+
+ while (offset < size)
+ {
+ elen = *(buf+offset+1);
+
+ if (*(buf+offset) == eid)
+ {
+ if ( eid == ZM_WLAN_EID_WPA_IE )
+ {
+ if ( (HTType == 0)
+ && (*(buf+offset+2) == oui[0])
+ && (*(buf+offset+3) == oui[1])
+ && (*(buf+offset+4) == oui[2])
+ && (*(buf+offset+5) == oui[3]) )
+ {
+ zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2);
+ return (size-elen-2);
+ }
+
+ if ( (HTType == 1)
+ && (*(buf+offset+2) == oui11n[0])
+ && (*(buf+offset+3) == oui11n[1])
+ && (*(buf+offset+4) == oui11n[2])
+ && (*(buf+offset+5) == HTEid) )
+ {
+ zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2);
+ return (size-elen-2);
+ }
+ }
+ else
+ {
+ zfMemoryMove(buf+offset, buf+offset+elen+2, size-offset-elen-2);
+ return (size-elen-2);
+ }
+ }
+
+ offset += (elen+2);
+ }
+
+ return size;
+}
+
+u16_t zfUpdateElement(zdev_t* dev, u8_t* buf, u16_t size, u8_t* updateeid)
+{
+ u16_t offset = 0;
+ u16_t elen;
+
+ while (offset < size) {
+ elen = *(buf+offset+1);
+
+ if (*(buf+offset) == updateeid[0]) {
+ if (updateeid[1] <= elen) {
+ zfMemoryMove(buf+offset, updateeid, updateeid[1]+2);
+ zfMemoryMove(buf+offset+updateeid[1]+2, buf+offset+elen+2, size-offset-elen-2);
+
+ return size-(elen-updateeid[1]);
+ } else {
+ zfMemoryMove(buf+offset+updateeid[1]+2, buf+offset+elen+2, size-offset-elen-2);
+ zfMemoryMove(buf+offset, updateeid, updateeid[1]+2);
+
+ return size+(updateeid[1]-elen);
+ }
+ }
+
+ offset += (elen+2);
+ }
+
+ return size;
+}
+
+u16_t zfFindSuperGElement(zdev_t* dev, zbuf_t* buf, u8_t type)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t super_feature;
+ u8_t ouiSuperG[6] = {0x00,0x03,0x7f,0x01, 0x01, 0x00};
+
+ zmw_get_wlan_dev(dev);
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+ /* Search loop */
+ while ((offset+2)<bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_VENDOR_PRIVATE)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if (zfRxBufferEqualToStr(dev, buf, ouiSuperG, offset+2, 6) && ( zmw_rx_buf_readb(dev, buf, offset+1) >= 6))
+ {
+ /* super_feature 0:useFastFrame, 1:useCompression, 2:useTurboPrime */
+ super_feature= zmw_rx_buf_readb(dev, buf, offset+8);
+ if ((super_feature & 0x01) || (super_feature & 0x02) || (super_feature & 0x04))
+ {
+ return offset;
+ }
+ }
+ }
+ /* Advance to next element */
+ #if 1
+ elen = zmw_rx_buf_readb(dev, buf, offset+1);
+ #else
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+ #endif
+
+ offset += (elen+2);
+ }
+ return 0xffff;
+}
+
+u16_t zfFindXRElement(zdev_t* dev, zbuf_t* buf, u8_t type)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t ouixr[6] = {0x00,0x03,0x7f,0x03, 0x01, 0x00};
+
+ zmw_get_wlan_dev(dev);
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+ /* Search loop */
+ while ((offset+2)<bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_VENDOR_PRIVATE)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if (zfRxBufferEqualToStr(dev, buf, ouixr, offset+2, 6) && ( zmw_rx_buf_readb(dev, buf, offset+1) >= 6))
+ {
+ return offset;
+ }
+ }
+ /* Advance to next element */
+ #if 1
+ elen = zmw_rx_buf_readb(dev, buf, offset+1);
+ #else
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+ #endif
+
+ offset += (elen+2);
+ }
+ return 0xffff;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfMmAddIeSupportRate */
+/* Add information element Support Rate to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* eid : element ID */
+/* rateSet : CCK or OFDM */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfMmAddIeSupportRate(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t eid, u8_t rateSet)
+{
+ u8_t len = 0;
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ //if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) )
+ //{
+ // return offset;
+ //}
+
+ /* Information : Support Rate */
+ if ( rateSet == ZM_RATE_SET_CCK )
+ {
+ for (i=0; i<4; i++)
+ {
+ if ((wd->bRate & (0x1<<i)) == (0x1<<i))
+ //if ((0xf & (0x1<<i)) == (0x1<<i))
+ {
+ zmw_tx_buf_writeb(dev, buf, offset+len+2,
+ zg11bRateTbl[i]+((wd->bRateBasic & (0x1<<i))<<(7-i)));
+ len++;
+ }
+ }
+ }
+ else if ( rateSet == ZM_RATE_SET_OFDM )
+ {
+ for (i=0; i<8; i++)
+ {
+ if ((wd->gRate & (0x1<<i)) == (0x1<<i))
+ //if ((0xff & (0x1<<i)) == (0x1<<i))
+ {
+ zmw_tx_buf_writeb(dev, buf, offset+len+2,
+ zg11gRateTbl[i]+((wd->gRateBasic & (0x1<<i))<<(7-i)));
+ len++;
+ }
+ }
+ }
+
+ if (len > 0)
+ {
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset, eid);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset+1, len);
+
+ /* Return value */
+ offset += (2+len);
+ }
+
+ return offset;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfMmAddIeDs */
+/* Add information element DS to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfMmAddIeDs(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_DS);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, 1);
+
+ /* Information : DS */
+ zmw_tx_buf_writeb(dev, buf, offset++,
+ zfChFreqToNum(wd->frequency, NULL));
+
+ return offset;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfMmAddIeErp */
+/* Add information element ERP to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfMmAddIeErp(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_ERP);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, 1);
+
+ /* Information : ERP */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->erpElement);
+
+ return offset;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfMmAddIeWpa */
+/* Add information element WPA to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Yuan-Gu Wei ZyDAS Technology Corporation 2006.2 */
+/* */
+/************************************************************************/
+u16_t zfMmAddIeWpa(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t apId)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ int i;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ //zmw_inttx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE);
+
+ /* Element Length */
+ //zmw_inttx_buf_writeb(dev, buf, offset++, wd->ap.wpaLen);
+ for(i = 0; i < wd->ap.wpaLen[apId]; i++)
+ {
+ /* Information : WPA */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.wpaIe[apId][i]);
+ }
+
+ return offset;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfMmAddHTCapability */
+/* Add HT Capability Infomation to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Chao-Wen Yang ZyDAS Technology Corporation 2006.06 */
+/* */
+/************************************************************************/
+u16_t zfMmAddHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ u8_t OUI[3] = {0x0,0x90,0x4C};
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Prob ID */
+ zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE);
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ /* Element Length */
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.Length + 4);
+
+ /* OUI Data */
+ for (i = 0; i < 3; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, OUI[i]);
+ }
+
+ /* Element Type ID */
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.ElementID);
+
+ /* HT Capability Data */
+ for (i = 0; i < 26; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Byte[i+2]);
+ }
+ }
+ else
+ {
+ /* Element Length */
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.Length + 4);
+
+ /* OUI Data */
+ for (i = 0; i < 3; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, OUI[i]);
+ }
+
+ /* Element Type ID */
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.ElementID);
+
+ /* HT Capability Data */
+ for (i = 0; i < 26; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Byte[i+2]);
+ }
+ }
+
+ return offset;
+}
+
+
+u16_t zfMmAddPreNHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ //u8_t OUI[3] = {0x0,0x90,0x4C};
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Prob ID */
+ zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_PREN2_EID_HTCAPABILITY);
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ /* Element Length */
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Data.Length);
+
+ /* HT Capability Data */
+ for (i = 0; i < 26; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.HTCap.Byte[i+2]);
+ }
+ }
+ else
+ {
+ /* Element Length */
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Data.Length);
+
+ /* HT Capability Data */
+ for (i = 0; i < 26; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.HTCap.Byte[i+2]);
+ }
+ }
+
+ return offset;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfMmAddExtendedHTCapability */
+/* Add Extended HT Capability Infomation to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Chao-Wen Yang ZyDAS Technology Corporation 2006.06 */
+/* */
+/************************************************************************/
+u16_t zfMmAddExtendedHTCapability(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ u8_t OUI[3] = {0x0,0x90,0x4C};
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Prob ID */
+ zmw_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WPA_IE);
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ /* Element Length */
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Data.Length + 4);
+
+ /* OUI Data */
+ for (i = 0; i < 3; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, OUI[i]);
+ }
+
+ /* Element Type ID */
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Data.ElementID);
+
+ /* HT Capability Data */
+ for (i = 0; i < 22; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, wd->ap.ExtHTCap.Byte[i+2]);
+ }
+ }
+ else
+ {
+ /* Element Length */
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Data.Length + 4);
+
+ /* OUI Data */
+ for (i = 0; i < 3; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, OUI[i]);
+ }
+
+ /* Element Type ID */
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Data.ElementID);
+
+ /* HT Capability Data */
+ for (i = 0; i < 22; i++)
+ {
+ zmw_buf_writeb(dev, buf, offset++, wd->sta.ExtHTCap.Byte[i+2]);
+ }
+ }
+
+ return offset;
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfSendMmFrame */
+/* Send management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* frameType : management frame type */
+/* dst : destination MAC address */
+/* p1 : parameter 1 */
+/* p2 : parameter 2 */
+/* p3 : parameter 3 */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+/* probe req : p1=> bWithSSID, p2=>R, p3=>R */
+/* probe rsp : p1=>R, p2=>R, p3=>VAP ID(AP) */
+/* deauth : p1=>Reason Code, p2=>R, p3=>VAP ID(AP) */
+/* Disasoc : p1=>Reason Code, p2=>R, p3=>VAP ID(AP) */
+/* ATIM : p1=>R, p2=>R, p3=>R */
+/* (re)asoc rsp : p1=>Status Code, p2=>AID, p3=>VAP ID(AP) */
+/* asoc req : p1=>R, p2=>R, p3=>R */
+/* reasoc req : p1=>AP MAC[0], p2=>AP MAC[1], p3=>AP MAC[2] */
+/* auth : p1=>low=Algorithm, high=Transaction, p2=>Status, p3=>VAP ID */
+void zfSendMmFrame(zdev_t* dev, u8_t frameType, u16_t* dst,
+ u32_t p1, u32_t p2, u32_t p3)
+{
+ zbuf_t* buf;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ u16_t offset = 0;
+ u16_t hlen = 32;
+ u16_t header[(24+25+1)/2];
+ u16_t vap = 0;
+ u16_t i;
+ u8_t encrypt = 0;
+ u16_t aid;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zm_msg2_mm(ZM_LV_2, "Send mm frame, type=", frameType);
+ /* TBD : Maximum size of managment frame */
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
+ return;
+ }
+
+ //Reserve room for wlan header
+ offset = hlen;
+
+ switch (frameType)
+ {
+ case ZM_WLAN_FRAME_TYPE_PROBEREQ :
+ offset = zfSendProbeReq(dev, buf, offset, (u8_t) p1);
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_PROBERSP :
+ zm_msg0_mm(ZM_LV_3, "probe rsp");
+ /* 24-31 Time Stamp : hardware WON'T fill this field */
+ zmw_tx_buf_writeh(dev, buf, offset, 0);
+ zmw_tx_buf_writeh(dev, buf, offset+2, 0);
+ zmw_tx_buf_writeh(dev, buf, offset+4, 0);
+ zmw_tx_buf_writeh(dev, buf, offset+6, 0);
+ offset+=8;
+
+ /* Beacon Interval */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
+ offset+=2;
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ vap = (u16_t) p3;
+ /* Capability */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
+ offset+=2;
+ /* SSID */
+ offset = zfApAddIeSsid(dev, buf, offset, vap);
+ }
+ else
+ {
+ /* Capability */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[0]);
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[1]);
+ /* SSID */
+ offset = zfStaAddIeSsid(dev, buf, offset);
+ }
+
+ /* Support Rate */
+ if ( wd->frequency < 3000 )
+ {
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
+ }
+ else
+ {
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
+ }
+
+ /* DS parameter set */
+ offset = zfMmAddIeDs(dev, buf, offset);
+
+ /* TODO G IBSS */
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ offset = zfStaAddIeIbss(dev, buf, offset);
+
+ if (wd->frequency < 3000)
+ {
+ if( wd->wfc.bIbssGMode
+ && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) // Only accompany with enabling a mode .
+ {
+ /* ERP Information */
+ wd->erpElement = 0;
+ offset = zfMmAddIeErp(dev, buf, offset);
+
+ /* Enable G Mode */
+ /* Extended Supported Rates */
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ }
+ }
+
+
+ if ((wd->wlanMode == ZM_MODE_AP)
+ && (wd->ap.wlanType[vap] != ZM_WLAN_TYPE_PURE_B))
+ {
+ /* ERP Information */
+ offset = zfMmAddIeErp(dev, buf, offset);
+
+ /* Extended Supported Rates */
+ if ( wd->frequency < 3000 )
+ {
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ }
+
+ /* ERP Information */
+ //offset = zfMmAddIeErp(dev, buf, offset);
+
+ /* Extended Supported Rates */
+ //offset = zfMmAddIeSupportRate(dev, buf, offset,
+ // ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+
+ /* TODO : RSN */
+ if (wd->wlanMode == ZM_MODE_AP && wd->ap.wpaSupport[vap] == 1)
+ {
+ offset = zfMmAddIeWpa(dev, buf, offset, vap);
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS && wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK)
+ {
+ offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH);
+ }
+
+ /* WME Parameters */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ if (wd->ap.qosMode == 1)
+ {
+ offset = zfApAddIeWmePara(dev, buf, offset, vap);
+ }
+ }
+
+ if ( wd->wlanMode != ZM_MODE_IBSS )
+ {
+ // jhlee HT 0
+ //CWYang(+)
+ /* TODO : Need to check if it is ok */
+ /* HT Capabilities Info */
+ offset = zfMmAddHTCapability(dev, buf, offset);
+ //CWYang(+)
+ /* Extended HT Capabilities Info */
+ offset = zfMmAddExtendedHTCapability(dev, buf, offset);
+ }
+
+ if ( wd->sta.ibssAdditionalIESize )
+ offset = zfStaAddIbssAdditionalIE(dev, buf, offset);
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_AUTH :
+ if (p1 == 0x30001)
+ {
+ hlen += 4;
+ offset += 4; // for reserving wep header
+ encrypt = 1;
+ }
+
+ /* Algotrithm Number */
+ zmw_tx_buf_writeh(dev, buf, offset, (u16_t)(p1&0xffff));
+ offset+=2;
+
+ /* Transaction Number */
+ zmw_tx_buf_writeh(dev, buf, offset, (u16_t)(p1>>16));
+ offset+=2;
+
+ /* Status Code */
+ zmw_tx_buf_writeh(dev, buf, offset, (u16_t)p2);
+ offset+=2;
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ vap = (u16_t) p3;
+ }
+
+ /* Challenge Text => share-2 or share-3 */
+ if (p1 == 0x20001)
+ {
+ if (p2 == 0) //Status == success
+ {
+ zmw_buf_writeh(dev, buf, offset, 0x8010);
+ offset+=2;
+ /* share-2 : AP generate challenge text */
+ for (i=0; i<128; i++)
+ {
+ wd->ap.challengeText[i] = (u8_t)zfGetRandomNumber(dev, 0);
+ }
+ zfCopyToIntTxBuffer(dev, buf, wd->ap.challengeText, offset, 128);
+ offset += 128;
+ }
+ }
+ else if (p1 == 0x30001)
+ {
+ /* share-3 : STA return challenge Text */
+ zfCopyToIntTxBuffer(dev, buf, wd->sta.challengeText, offset, wd->sta.challengeText[1]+2);
+ offset += (wd->sta.challengeText[1]+2);
+ }
+
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_ASOCREQ :
+ case ZM_WLAN_FRAME_TYPE_REASOCREQ :
+ /* Capability */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[0]);
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[1]);
+
+ /* Listen Interval */
+ zmw_tx_buf_writeh(dev, buf, offset, 0x0005);
+ offset+=2;
+
+ /* Reassocaited Request : Current AP address */
+ if (frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ)
+ {
+ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[0]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[1]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[2]);
+ offset+=2;
+ }
+
+ /* SSID */
+ offset = zfStaAddIeSsid(dev, buf, offset);
+
+
+ if ( wd->sta.currentFrequency < 3000 )
+ {
+ /* Support Rate */
+ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
+ }
+ else
+ {
+ /* Support Rate */
+ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
+ }
+
+ if ((wd->sta.capability[1] & ZM_BIT_0) == 1)
+ { //spectrum managment flag enable
+ offset = zfStaAddIePowerCap(dev, buf, offset);
+ offset = zfStaAddIeSupportCh(dev, buf, offset);
+ }
+
+ if (wd->sta.currentFrequency < 3000)
+ {
+ /* Extended Supported Rates */
+ if (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N))
+ {
+ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ }
+
+
+ //offset = zfStaAddIeWpaRsn(dev, buf, offset, frameType);
+ //Move to wrapper function, for OS difference--CWYang(m)
+ //for windows wrapper, zfwStaAddIeWpaRsn() should be below:
+ //u16_t zfwStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType)
+ //{
+ // return zfStaAddIeWpaRsn(dev, buf, offset, frameType);
+ //}
+ offset = zfwStaAddIeWpaRsn(dev, buf, offset, frameType);
+
+#ifdef ZM_ENABLE_CENC
+ /* CENC */
+ //if (wd->sta.encryMode == ZM_CENC)
+ offset = zfStaAddIeCenc(dev, buf, offset);
+#endif //ZM_ENABLE_CENC
+ if (((wd->sta.wmeEnabled & ZM_STA_WME_ENABLE_BIT) != 0) //WME enabled
+ && ((wd->sta.apWmeCapability & 0x1) != 0)) //WME AP
+ {
+ if (((wd->sta.apWmeCapability & 0x80) != 0) //UAPSD AP
+ && ((wd->sta.wmeEnabled & ZM_STA_UAPSD_ENABLE_BIT) != 0)) //UAPSD enabled
+ {
+ offset = zfStaAddIeWmeInfo(dev, buf, offset, wd->sta.wmeQosInfo);
+ }
+ else
+ {
+ offset = zfStaAddIeWmeInfo(dev, buf, offset, 0);
+ }
+ }
+ // jhlee HT 0
+ //CWYang(+)
+ if (wd->sta.EnableHT != 0)
+ {
+ #ifndef ZM_DISABLE_AMSDU8K_SUPPORT
+ //Support 8K A-MSDU
+ if (wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED)
+ {
+ wd->sta.HTCap.Data.HtCapInfo |= HTCAP_MaxAMSDULength;
+ }
+ else
+ {
+ wd->sta.HTCap.Data.HtCapInfo &= (~HTCAP_MaxAMSDULength);
+ }
+ #else
+ //Support 4K A-MSDU
+ wd->sta.HTCap.Data.HtCapInfo &= (~HTCAP_MaxAMSDULength);
+ #endif
+
+ /* HT Capabilities Info */
+ if (wd->BandWidth40 == 1) {
+ wd->sta.HTCap.Data.HtCapInfo |= HTCAP_SupChannelWidthSet;
+ }
+ else {
+ wd->sta.HTCap.Data.HtCapInfo &= ~HTCAP_SupChannelWidthSet;
+ //wd->sta.HTCap.Data.HtCapInfo |= HTCAP_SupChannelWidthSet;
+ }
+
+ wd->sta.HTCap.Data.AMPDUParam &= ~HTCAP_MaxRxAMPDU3;
+ wd->sta.HTCap.Data.AMPDUParam |= HTCAP_MaxRxAMPDU3;
+ wd->sta.HTCap.Data.MCSSet[1] = 0xFF; // MCS 8 ~ 15
+ offset = zfMmAddHTCapability(dev, buf, offset);
+ offset = zfMmAddPreNHTCapability(dev, buf, offset);
+ //CWYang(+)
+ /* Extended HT Capabilities Info */
+ //offset = zfMmAddExtendedHTCapability(dev, buf, offset);
+ }
+
+
+ //Store asoc request frame body, for VISTA only
+ wd->sta.asocReqFrameBodySize = ((offset - hlen) >
+ ZM_CACHED_FRAMEBODY_SIZE)?
+ ZM_CACHED_FRAMEBODY_SIZE:(offset - hlen);
+ for (i=0; i<wd->sta.asocReqFrameBodySize; i++)
+ {
+ wd->sta.asocReqFrameBody[i] = zmw_tx_buf_readb(dev, buf, i + hlen);
+ }
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_ASOCRSP :
+ case ZM_WLAN_FRAME_TYPE_REASOCRSP :
+ vap = (u16_t) p3;
+
+ /* Capability */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
+ offset+=2;
+
+ /* Status Code */
+ zmw_tx_buf_writeh(dev, buf, offset, (u16_t)p1);
+ offset+=2;
+
+ /* AID */
+ zmw_tx_buf_writeh(dev, buf, offset, (u16_t)(p2|0xc000));
+ offset+=2;
+
+
+ if ( wd->frequency < 3000 )
+ {
+ /* Support Rate */
+ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
+
+ /* Extended Supported Rates */
+ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ else
+ {
+ /* Support Rate */
+ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
+ }
+
+
+
+ /* WME Parameters */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ /* TODO : if WME STA then send WME parameter element */
+ if (wd->ap.qosMode == 1)
+ {
+ offset = zfApAddIeWmePara(dev, buf, offset, vap);
+ }
+ }
+ // jhlee HT 0
+ //CWYang(+)
+ /* HT Capabilities Info */
+ offset = zfMmAddHTCapability(dev, buf, offset);
+ //CWYang(+)
+ /* Extended HT Capabilities Info */
+ offset = zfMmAddExtendedHTCapability(dev, buf, offset);
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_ATIM :
+ /* NULL frame */
+ /* TODO : add two dumb bytes temporarily */
+ offset += 2;
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_QOS_NULL :
+ zmw_buf_writeh(dev, buf, offset, 0x0010);
+ offset += 2;
+ break;
+
+ case ZM_WLAN_DATA_FRAME :
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_DISASOC :
+ case ZM_WLAN_FRAME_TYPE_DEAUTH :
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ vap = (u16_t) p3;
+
+ if ((aid = zfApFindSta(dev, dst)) != 0xffff)
+ {
+ zmw_enter_critical_section(dev);
+ /* Clear STA table */
+ wd->ap.staTable[aid].valid = 0;
+
+ zmw_leave_critical_section(dev);
+
+ if (wd->zfcbDisAsocNotify != NULL)
+ {
+ wd->zfcbDisAsocNotify(dev, (u8_t*)dst, vap);
+ }
+ }
+ }
+ /* Reason Code */
+ zmw_tx_buf_writeh(dev, buf, offset, (u16_t)p1);
+ offset+=2;
+ break;
+ }
+
+ zfwBufSetSize(dev, buf, offset);
+
+ zm_msg2_mm(ZM_LV_2, "management frame body size=", offset-hlen);
+
+ //Copy wlan header
+ zfTxGenMmHeader(dev, frameType, dst, header, offset-hlen, buf, vap, encrypt);
+ for (i=0; i<(hlen>>1); i++)
+ {
+ zmw_tx_buf_writeh(dev, buf, i*2, header[i]);
+ }
+
+ /* Get buffer DMA address */
+ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
+ //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
+ //{
+ // goto zlError;
+ //}
+
+ zm_msg2_mm(ZM_LV_2, "offset=", offset);
+ zm_msg2_mm(ZM_LV_2, "hlen=", hlen);
+ //zm_msg2_mm(ZM_LV_2, "addrTblSize=", addrTblSize);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.len[0]=", addrTbl.len[0]);
+ //zm_msg2_mm(ZM_LV_2, "addrTbl.physAddrl[0]=", addrTbl.physAddrl[0]);
+ //zm_msg2_mm(ZM_LV_2, "buf->data=", buf->data);
+
+ #if 0
+ if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+ #else
+ zfPutVmmq(dev, buf);
+ zfPushVtxq(dev);
+ #endif
+
+ return;
+#if 0
+zlError:
+
+ zfwBufFree(dev, buf, 0);
+ return;
+#endif
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfProcessManagement */
+/* Process received management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : received management frame buffer */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+void zfProcessManagement(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo) //CWYang(m)
+{
+ u8_t frameType;
+ u16_t ta[3];
+ u16_t ra[3];
+ u16_t vap = 0, index = 0;
+ //u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ ra[0] = zmw_rx_buf_readh(dev, buf, 4);
+ ra[1] = zmw_rx_buf_readh(dev, buf, 6);
+ ra[2] = zmw_rx_buf_readh(dev, buf, 8);
+
+ ta[0] = zmw_rx_buf_readh(dev, buf, 10);
+ ta[1] = zmw_rx_buf_readh(dev, buf, 12);
+ ta[2] = zmw_rx_buf_readh(dev, buf, 14);
+
+ frameType = zmw_rx_buf_readb(dev, buf, 0);
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+#if 1
+ vap = 0;
+ if ((ra[0] & 0x1) != 1)
+ {
+ /* AP : Find virtual AP */
+ if ((index = zfApFindSta(dev, ta)) != 0xffff)
+ {
+ vap = wd->ap.staTable[index].vap;
+ }
+ }
+ zm_msg2_mm(ZM_LV_2, "vap=", vap);
+#endif
+
+ /* Dispatch by frame type */
+ switch (frameType)
+ {
+ /* Beacon */
+ case ZM_WLAN_FRAME_TYPE_BEACON :
+ zfApProcessBeacon(dev, buf);
+ break;
+ /* Authentication */
+ case ZM_WLAN_FRAME_TYPE_AUTH :
+ zfApProcessAuth(dev, buf, ta, vap);
+ break;
+ /* Association request */
+ case ZM_WLAN_FRAME_TYPE_ASOCREQ :
+ /* Reassociation request */
+ case ZM_WLAN_FRAME_TYPE_REASOCREQ :
+ zfApProcessAsocReq(dev, buf, ta, vap);
+ break;
+ /* Association response */
+ case ZM_WLAN_FRAME_TYPE_ASOCRSP :
+ //zfApProcessAsocRsp(dev, buf);
+ break;
+ /* Deauthentication */
+ case ZM_WLAN_FRAME_TYPE_DEAUTH :
+ zfApProcessDeauth(dev, buf, ta, vap);
+ break;
+ /* Disassociation */
+ case ZM_WLAN_FRAME_TYPE_DISASOC :
+ zfApProcessDisasoc(dev, buf, ta, vap);
+ break;
+ /* Probe request */
+ case ZM_WLAN_FRAME_TYPE_PROBEREQ :
+ zfProcessProbeReq(dev, buf, ta);
+ break;
+ /* Probe response */
+ case ZM_WLAN_FRAME_TYPE_PROBERSP :
+ zfApProcessProbeRsp(dev, buf, AddInfo);
+ break;
+ /* Action */
+ case ZM_WLAN_FRAME_TYPE_ACTION :
+ zfApProcessAction(dev, buf);
+ break;
+ }
+ }
+ else //if ((wd->wlanMode == ZM_MODE_INFRASTRUCTURE) || (wd->wlanMode == ZM_MODE_IBSS))
+ {
+ /* Dispatch by frame type */
+ switch (frameType)
+ {
+ /* Beacon */
+ case ZM_WLAN_FRAME_TYPE_BEACON :
+ /* if enable 802.11h and current chanel is silent but receive beacon from other AP */
+ if (((wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
+ & ZM_REG_FLAG_CHANNEL_CSA) != 0) && wd->sta.DFSEnable)
+ {
+ wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
+ &= ~(ZM_REG_FLAG_CHANNEL_CSA & ZM_REG_FLAG_CHANNEL_PASSIVE);
+ }
+ zfStaProcessBeacon(dev, buf, AddInfo); //CWYang(m)
+ break;
+ /* Authentication */
+ case ZM_WLAN_FRAME_TYPE_AUTH :
+ /* TODO : vap parameter is useless in STA mode, get rid of it */
+ zfStaProcessAuth(dev, buf, ta, 0);
+ break;
+ /* Association request */
+ case ZM_WLAN_FRAME_TYPE_ASOCREQ :
+ /* TODO : vap parameter is useless in STA mode, get rid of it */
+ zfStaProcessAsocReq(dev, buf, ta, 0);
+ break;
+ /* Association response */
+ case ZM_WLAN_FRAME_TYPE_ASOCRSP :
+ /* Reassociation request */
+ case ZM_WLAN_FRAME_TYPE_REASOCRSP :
+ zfStaProcessAsocRsp(dev, buf);
+ break;
+ /* Deauthentication */
+ case ZM_WLAN_FRAME_TYPE_DEAUTH :
+ zm_debug_msg0("Deauthentication received");
+ zfStaProcessDeauth(dev, buf);
+ break;
+ /* Disassociation */
+ case ZM_WLAN_FRAME_TYPE_DISASOC :
+ zm_debug_msg0("Disassociation received");
+ zfStaProcessDisasoc(dev, buf);
+ break;
+ /* Probe request */
+ case ZM_WLAN_FRAME_TYPE_PROBEREQ :
+ zfProcessProbeReq(dev, buf, ta);
+ break;
+ /* Probe response */
+ case ZM_WLAN_FRAME_TYPE_PROBERSP :
+ /* if enable 802.11h and current chanel is silent but receive probe response from other AP */
+ if (((wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
+ & ZM_REG_FLAG_CHANNEL_CSA) != 0) && wd->sta.DFSEnable)
+ {
+ wd->regulationTable.allowChannel[wd->regulationTable.CurChIndex].channelFlags
+ &= ~(ZM_REG_FLAG_CHANNEL_CSA & ZM_REG_FLAG_CHANNEL_PASSIVE);
+ }
+ zfStaProcessProbeRsp(dev, buf, AddInfo);
+ break;
+
+ case ZM_WLAN_FRAME_TYPE_ATIM:
+ zfStaProcessAtim(dev, buf);
+ break;
+ /* Action */
+ case ZM_WLAN_FRAME_TYPE_ACTION :
+ zm_msg0_mm(ZM_LV_2, "ProcessActionMgtFrame");
+ zfStaProcessAction(dev, buf);
+ break;
+ }
+ }
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfProcessProbeReq */
+/* Process probe request management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : auth frame buffer */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+void zfProcessProbeReq(zdev_t* dev, zbuf_t* buf, u16_t* src)
+{
+ u16_t offset;
+ u8_t len;
+ u16_t i, j;
+ u8_t ch;
+ u16_t sendFlag;
+
+ zmw_get_wlan_dev(dev);
+
+ /* check mode : AP/IBSS */
+ if ((wd->wlanMode != ZM_MODE_AP) && (wd->wlanMode != ZM_MODE_IBSS))
+ {
+ zm_msg0_mm(ZM_LV_3, "Ignore probe req");
+ return;
+ }
+
+ if ((wd->wlanMode != ZM_MODE_AP) && (wd->sta.adapterState == ZM_STA_STATE_DISCONNECT))
+ {
+ zm_msg0_mm(ZM_LV_3, "Packets dropped due to disconnect state");
+ return;
+ }
+
+ if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBERSP, src, 0, 0, 0);
+
+ return;
+ }
+
+ /* check SSID */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) == 0xffff)
+ {
+ zm_msg0_mm(ZM_LV_3, "probe req SSID not found");
+ return;
+ }
+
+ len = zmw_rx_buf_readb(dev, buf, offset+1);
+
+ for (i=0; i<ZM_MAX_AP_SUPPORT; i++)
+ {
+ if ((wd->ap.apBitmap & (1<<i)) != 0)
+ {
+ zm_msg1_mm(ZM_LV_3, "len=", len);
+ sendFlag = 0;
+ /* boardcast SSID */
+ if (len == 0)
+ {
+ if (wd->ap.hideSsid[i] == 0)
+ {
+ sendFlag = 1;
+ }
+ }
+ /* Not broadcast SSID */
+ else if (wd->ap.ssidLen[i] == len)
+ {
+ for (j=0; j<len; j++)
+ {
+ if ((ch = zmw_rx_buf_readb(dev, buf, offset+2+j))
+ != wd->ap.ssid[i][j])
+ {
+ break;
+ }
+ }
+ if (j == len)
+ {
+ sendFlag = 1;
+ }
+ }
+ if (sendFlag == 1)
+ {
+ /* Send probe response */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBERSP, src, i, 0, i);
+ }
+ }
+ }
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfProcessProbeRsp */
+/* Process probe response management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : auth frame buffer */
+/* AddInfo : Rx Header and Rx Mac Status */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Aress Yang ZyDAS Technology Corporation 2006.11 */
+/* */
+/************************************************************************/
+void zfProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo)
+{
+ /* Gather scan result */
+ /* Parse TIM and send PS-POLL in power saving mode */
+ struct zsWlanProbeRspFrameHeader* pProbeRspHeader;
+ struct zsBssInfo* pBssInfo;
+ u8_t pBuf[sizeof(struct zsWlanProbeRspFrameHeader)];
+ int res;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zfCopyFromRxBuffer(dev, buf, pBuf, 0,
+ sizeof(struct zsWlanProbeRspFrameHeader));
+ pProbeRspHeader = (struct zsWlanProbeRspFrameHeader*) pBuf;
+
+ zmw_enter_critical_section(dev);
+
+ //zm_debug_msg1("bss count = ", wd->sta.bssList.bssCount);
+
+ pBssInfo = zfStaFindBssInfo(dev, buf, pProbeRspHeader);
+
+ //if ( i == wd->sta.bssList.bssCount )
+ if ( pBssInfo == NULL )
+ {
+ /* Allocate a new entry if BSS not in the scan list */
+ pBssInfo = zfBssInfoAllocate(dev);
+ if (pBssInfo != NULL)
+ {
+ res = zfStaInitBssInfo(dev, buf, pProbeRspHeader, pBssInfo, AddInfo, 0);
+ //zfDumpSSID(pBssInfo->ssid[1], &(pBssInfo->ssid[2]));
+ if ( res != 0 )
+ {
+ zfBssInfoFree(dev, pBssInfo);
+ }
+ else
+ {
+ zfBssInfoInsertToList(dev, pBssInfo);
+ }
+ }
+ }
+ else
+ {
+ res = zfStaInitBssInfo(dev, buf, pProbeRspHeader, pBssInfo, AddInfo, 1);
+ if (res == 2)
+ {
+ zfBssInfoRemoveFromList(dev, pBssInfo);
+ zfBssInfoFree(dev, pBssInfo);
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ int idx;
+
+ // It would reset the alive counter if the peer station is found!
+ zfStaFindFreeOpposite(dev, (u16_t *)pBssInfo->macaddr, &idx);
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfSendProbeReq */
+/* Send probe request management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Ji-Huang Lee ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+
+u16_t zfSendProbeReq(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t bWithSSID)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+ /* SSID */
+ if (bWithSSID == 0) /* broadcast ssid */
+ {
+ //zmw_leave_critical_section(dev);
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0); /* length = 0 */
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ if (wd->ws.probingSsidList[bWithSSID-1].ssidLen == 0)
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0); /* length = 0 */
+ }
+ else
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
+ zmw_tx_buf_writeb(dev, buf, offset++,
+ wd->ws.probingSsidList[bWithSSID-1].ssidLen);
+ zfCopyToIntTxBuffer(dev, buf,
+ wd->ws.probingSsidList[bWithSSID-1].ssid,
+ offset,
+ wd->ws.probingSsidList[bWithSSID-1].ssidLen); /* ssid */
+ offset += wd->ws.probingSsidList[bWithSSID-1].ssidLen;
+ }
+ zmw_leave_critical_section(dev);
+ }
+
+ /* Supported rates */
+ if ( wd->sta.currentFrequency < 3000 )
+ { /* 802.11b+g */
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
+
+ if (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) {
+ if (wd->wlanMode == ZM_MODE_IBSS) {
+ if (wd->wfc.bIbssGMode) {
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ } else {
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ }
+ }
+ else
+ { /* 802.11a */
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
+ }
+
+ return offset;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfUpdateDefaultQosParameter */
+/* Update TxQs CWMIN, CWMAX, AIFS and TXO to WME default value. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* mode : 0=>STA, 1=>AP */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+void zfUpdateDefaultQosParameter(zdev_t* dev, u8_t mode)
+{
+ u16_t cwmin[5];
+ u16_t cwmax[5];
+ u16_t aifs[5];
+ u16_t txop[5];
+
+ /* WMM parameter for STA */
+ /* Best Effor */
+ cwmin[0] = 15;
+ cwmax[0] = 1023;
+ aifs[0] = 3 * 9 + 10;
+ txop[0] = 0;
+ /* Back Ground */
+ cwmin[1] = 15;
+ cwmax[1] = 1023;
+ aifs[1] = 7 * 9 + 10;
+ txop[1] = 0;
+ /* VIDEO */
+ cwmin[2] = 7;
+ cwmax[2] = 15;
+ aifs[2] = 2 * 9 + 10;
+ txop[2] = 94;
+ /* VOICE */
+ cwmin[3] = 3;
+ cwmax[3] = 7;
+ aifs[3] = 2 * 9 + 10;
+ txop[3] = 47;
+ /* Special TxQ */
+ cwmin[4] = 3;
+ cwmax[4] = 7;
+ aifs[4] = 2 * 9 + 10;
+ txop[4] = 0;
+
+ /* WMM parameter for AP */
+ if (mode == 1)
+ {
+ cwmax[0] = 63;
+ aifs[3] = 1 * 9 + 10;
+ aifs[4] = 1 * 9 + 10;
+ }
+ zfHpUpdateQosParameter(dev, cwmin, cwmax, aifs, txop);
+}
+
+u16_t zfFindATHExtCap(zdev_t* dev, zbuf_t* buf, u8_t type, u8_t subtype)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t tmp;
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+
+ /* Search loop */
+ while ((offset+2)<bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x03)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x7f)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+5)) == type))
+
+ {
+ if ( subtype != 0xff )
+ {
+ if ( (tmp = zmw_rx_buf_readb(dev, buf, offset+6)) == subtype )
+ {
+ return offset;
+ }
+ }
+ else
+ {
+ return offset;
+ }
+ }
+ }
+
+ /* Advance to next element */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+ offset += (elen+2);
+ }
+ return 0xffff;
+}
+
+u16_t zfFindBrdcmMrvlRlnkExtCap(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t tmp;
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+
+ /* Search loop */
+ while ((offset+2)<bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x10)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x18))
+
+ {
+ return offset;
+ }
+ else if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x50)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x43))
+
+ {
+ return offset;
+ }
+ }
+ else if ((id = zmw_rx_buf_readb(dev, buf, offset)) == 0x7F)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if ((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x01)
+
+ {
+ return offset;
+ }
+ }
+
+ /* Advance to next element */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+ offset += (elen+2);
+ }
+ return 0xffff;
+}
+
+u16_t zfFindMarvelExtCap(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t tmp;
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+
+ /* Search loop */
+ while ((offset+2)<bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1))>(bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if (((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x50)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x43))
+
+ {
+ return offset;
+ }
+ }
+
+ /* Advance to next element */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+ offset += (elen+2);
+ }
+ return 0xffff;
+}
+
+u16_t zfFindBroadcomExtCap(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t tmp;
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+
+ /* Search loop */
+ while((offset+2) < bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == ZM_WLAN_EID_WIFI_IE)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) > (bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if (elen == 0)
+ {
+ return 0xffff;
+ }
+
+ if ( ((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x00)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+3)) == 0x10)
+ && ((tmp = zmw_rx_buf_readb(dev, buf, offset+4)) == 0x18) )
+ {
+ return offset;
+ }
+ }
+
+ /* Advance to next element */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+
+ offset += (elen+2);
+ }
+
+ return 0xffff;
+}
+
+u16_t zfFindRlnkExtCap(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t subType;
+ u16_t offset;
+ u16_t bufLen;
+ u16_t elen;
+ u8_t id;
+ u8_t tmp;
+
+ /* Get offset of first element */
+ subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
+
+ if ((offset = zgElementOffsetTable[subType]) == 0xff)
+ {
+ zm_assert(0);
+ }
+
+ /* Plus wlan header */
+ offset += 24;
+
+ bufLen = zfwBufGetSize(dev, buf);
+
+ /* Search loop */
+ while((offset+2) < bufLen) // including element ID and length (2bytes)
+ {
+ /* Search target element */
+ if ((id = zmw_rx_buf_readb(dev, buf, offset)) == 0x7F)
+ {
+ /* Bingo */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) > (bufLen - offset))
+ {
+ /* Element length error */
+ return 0xffff;
+ }
+
+ if ( elen == 0 )
+ {
+ return 0xffff;
+ }
+
+ if ((tmp = zmw_rx_buf_readb(dev, buf, offset+2)) == 0x01)
+
+ {
+ return offset;
+ }
+ }
+
+ /* Advance to next element */
+ if ((elen = zmw_rx_buf_readb(dev, buf, offset+1)) == 0)
+ {
+ return 0xffff;
+ }
+
+ offset += (elen+2);
+ }
+
+ return 0xffff;
+}
diff --git a/drivers/staging/otus/80211core/cmmap.c b/drivers/staging/otus/80211core/cmmap.c
new file mode 100644
index 000000000000..7f09fded459e
--- /dev/null
+++ b/drivers/staging/otus/80211core/cmmap.c
@@ -0,0 +1,2402 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : mm.c */
+/* */
+/* Abstract */
+/* This module contains common functions for handle AP */
+/* management frame. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#include "ratectrl.h"
+
+extern const u8_t zcUpToAc[];
+
+void zfMmApTimeTick(zdev_t* dev)
+{
+ u32_t now;
+ zmw_get_wlan_dev(dev);
+
+ //zm_debug_msg1("wd->wlanMode : ", wd->wlanMode);
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ /* => every 1.28 seconds */
+ /* AP : aging STA that does not active for wd->ap.staAgingTime */
+ now = wd->tick & 0x7f;
+ if (now == 0x0)
+ {
+ zfApAgingSta(dev);
+ }
+ else if (now == 0x1f)
+ {
+ zfQueueAge(dev, wd->ap.uapsdQ, wd->tick, 10000);
+ }
+ /* AP : check (wd->ap.protectedObss) and (wd->ap.bStaAssociated) */
+ /* to enable NonErp and Protection mode */
+ else if (now == 0x3f)
+ {
+ //zfApProtctionMonitor(dev);
+ }
+ }
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApInitStaTbl */
+/* Init AP's station table. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+void zfApInitStaTbl(zdev_t* dev)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
+ {
+ wd->ap.staTable[i].valid = 0;
+ wd->ap.staTable[i].state = 0;
+ wd->ap.staTable[i].addr[0] = 0;
+ wd->ap.staTable[i].addr[1] = 0;
+ wd->ap.staTable[i].addr[2] = 0;
+ wd->ap.staTable[i].time = 0;
+ wd->ap.staTable[i].vap = 0;
+ wd->ap.staTable[i].encryMode = ZM_NO_WEP;
+ }
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApFindSta */
+/* Find a STA in station table. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : Target STA address */
+/* */
+/* OUTPUTS */
+/* 0xffff : fail */
+/* other : STA table index */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfApFindSta(zdev_t* dev, u16_t* addr)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
+ {
+ if (wd->ap.staTable[i].valid == 1)
+ {
+ if ((wd->ap.staTable[i].addr[0] == addr[0])
+ && (wd->ap.staTable[i].addr[1] == addr[1])
+ && (wd->ap.staTable[i].addr[2] == addr[2]))
+ {
+ return i;
+ }
+ }
+ }
+ return 0xffff;
+}
+
+u16_t zfApGetSTAInfo(zdev_t* dev, u16_t* addr, u16_t* state, u8_t* vap)
+{
+ u16_t id;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ *vap = wd->ap.staTable[id].vap;
+ *state = wd->ap.staTable[id++].state;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return id;
+}
+
+
+void zfApGetStaQosType(zdev_t* dev, u16_t* addr, u8_t* qosType)
+{
+ u16_t id;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ *qosType = wd->ap.staTable[id].qosType;
+ }
+ else
+ {
+ *qosType = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return;
+}
+
+void zfApGetStaTxRateAndQosType(zdev_t* dev, u16_t* addr, u32_t* phyCtrl,
+ u8_t* qosType, u16_t* rcProbingFlag)
+{
+ u16_t id;
+ u8_t rate;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->ap.staTable[id].rcCell, rcProbingFlag);
+#ifdef ZM_AP_DEBUG
+ //rate = 15;
+#endif
+ *phyCtrl = zcRateToPhyCtrl[rate];
+ *qosType = wd->ap.staTable[id].qosType;
+ }
+ else
+ {
+ if (wd->frequency < 3000)
+ {
+ /* CCK 1M */
+ //header[2] = 0x0f00; //PHY control L
+ //header[3] = 0x0000; //PHY control H
+ *phyCtrl = 0x00000F00;
+ }
+ else
+ {
+ /* CCK 6M */
+ //header[2] = 0x0f01; //PHY control L
+ //header[3] = 0x000B; //PHY control H
+ *phyCtrl = 0x000B0F01;
+ }
+ *qosType = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zm_msg2_mm(ZM_LV_3, "PhyCtrl=", *phyCtrl);
+ return;
+}
+
+void zfApGetStaEncryType(zdev_t* dev, u16_t* addr, u8_t* encryType)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ u16_t id;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ *encryType = wd->ap.staTable[id].encryMode;
+ }
+ else
+ {
+ *encryType = ZM_NO_WEP;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zm_msg2_mm(ZM_LV_3, "encyrType=", *encryType);
+ return;
+}
+
+void zfApGetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t* iv16, u32_t* iv32)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ u16_t id;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ *iv16 = wd->ap.staTable[id].iv16;
+ *iv32 = wd->ap.staTable[id].iv32;
+ }
+ else
+ {
+ *iv16 = 0;
+ *iv32 = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zm_msg2_mm(ZM_LV_3, "iv16=", *iv16);
+ zm_msg2_mm(ZM_LV_3, "iv32=", *iv32);
+ return;
+}
+
+void zfApSetStaWpaIv(zdev_t* dev, u16_t* addr, u16_t iv16, u32_t iv32)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ u16_t id;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ wd->ap.staTable[id].iv16 = iv16;
+ wd->ap.staTable[id].iv32 = iv32;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zm_msg2_mm(ZM_LV_3, "iv16=", iv16);
+ zm_msg2_mm(ZM_LV_3, "iv32=", iv32);
+ return;
+}
+
+void zfApClearStaKey(zdev_t* dev, u16_t* addr)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ u16_t bcAddr[3] = { 0xffff, 0xffff, 0xffff };
+ u16_t id;
+
+ zmw_get_wlan_dev(dev);
+
+ if (zfMemoryIsEqual((u8_t*)bcAddr, (u8_t*)addr, sizeof(bcAddr)) == TRUE)
+ {
+ /* Turn off group key information */
+ // zfClearKey(dev, 0);
+ }
+ else
+ {
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ /* Turn off STA's key information */
+ zfHpRemoveKey(dev, id+1);
+
+ /* Update STA's Encryption Type */
+ wd->ap.staTable[id].encryMode = ZM_NO_WEP;
+ }
+ else
+ {
+ zm_msg0_mm(ZM_LV_3, "Can't find STA address\n");
+ }
+ zmw_leave_critical_section(dev);
+ }
+}
+
+#ifdef ZM_ENABLE_CENC
+void zfApGetStaCencIvAndKeyIdx(zdev_t* dev, u16_t* addr, u32_t *iv, u8_t *keyIdx)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ u16_t id;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ *iv++ = wd->ap.staTable[id].txiv[0];
+ *iv++ = wd->ap.staTable[id].txiv[1];
+ *iv++ = wd->ap.staTable[id].txiv[2];
+ *iv = wd->ap.staTable[id].txiv[3];
+ *keyIdx = wd->ap.staTable[id].cencKeyIdx;
+ }
+ else
+ {
+ *iv++ = 0x5c365c37;
+ *iv++ = 0x5c365c36;
+ *iv++ = 0x5c365c36;
+ *iv = 0x5c365c36;
+ *keyIdx = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+void zfApSetStaCencIv(zdev_t* dev, u16_t* addr, u32_t *iv)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ u16_t id;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ wd->ap.staTable[id].txiv[0] = *iv++;
+ wd->ap.staTable[id].txiv[1] = *iv++;
+ wd->ap.staTable[id].txiv[2] = *iv++;
+ wd->ap.staTable[id].txiv[3] = *iv;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return;
+}
+#endif //ZM_ENABLE_CENC
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApFlushBufferedPsFrame */
+/* Free buffered PS frames. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+void zfApFlushBufferedPsFrame(zdev_t* dev)
+{
+ u16_t emptyFlag;
+ u16_t freeCount;
+ u16_t vap;
+ zbuf_t* psBuf = NULL;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ freeCount = 0;
+ emptyFlag = 0;
+ while (1)
+ {
+ psBuf = NULL;
+ zmw_enter_critical_section(dev);
+ if (wd->ap.uniHead != wd->ap.uniTail)
+ {
+ psBuf = wd->ap.uniArray[wd->ap.uniHead];
+ wd->ap.uniHead = (wd->ap.uniHead + 1) & (ZM_UNI_ARRAY_SIZE - 1);
+ }
+ else
+ {
+ emptyFlag = 1;
+ }
+ zmw_leave_critical_section(dev);
+
+ if (psBuf != NULL)
+ {
+ zfwBufFree(dev, psBuf, ZM_ERR_FLUSH_PS_QUEUE);
+ }
+ zm_assert(freeCount++ < (ZM_UNI_ARRAY_SIZE*2));
+
+ if (emptyFlag != 0)
+ {
+ break;
+ }
+ }
+
+ for (vap=0; vap<ZM_MAX_AP_SUPPORT; vap++)
+ {
+ freeCount = 0;
+ emptyFlag = 0;
+ while (1)
+ {
+ psBuf = NULL;
+ zmw_enter_critical_section(dev);
+ if (wd->ap.bcmcHead[vap] != wd->ap.bcmcTail[vap])
+ {
+ psBuf = wd->ap.bcmcArray[vap][wd->ap.bcmcHead[vap]];
+ wd->ap.bcmcHead[vap] = (wd->ap.bcmcHead[vap] + 1)
+ & (ZM_BCMC_ARRAY_SIZE - 1);
+ }
+ else
+ {
+ emptyFlag = 1;
+ }
+ zmw_leave_critical_section(dev);
+
+ if (psBuf != NULL)
+ {
+ zfwBufFree(dev, psBuf, ZM_ERR_FLUSH_PS_QUEUE);
+ }
+ zm_assert(freeCount++ < (ZM_BCMC_ARRAY_SIZE*2));
+
+ if (emptyFlag != 0)
+ {
+ break;
+ }
+ }
+ }
+ return;
+}
+
+
+u16_t zfApBufferPsFrame(zdev_t* dev, zbuf_t* buf, u16_t port)
+{
+ u16_t id;
+ u16_t addr[3];
+ u16_t vap = 0;
+ u8_t up;
+ u16_t fragOff;
+ u8_t ac;
+ u16_t ret;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if (port < ZM_MAX_AP_SUPPORT)
+ {
+ vap = port;
+ }
+
+ addr[0] = zmw_rx_buf_readh(dev, buf, 0);
+ addr[1] = zmw_rx_buf_readh(dev, buf, 2);
+ addr[2] = zmw_rx_buf_readh(dev, buf, 4);
+
+ if ((addr[0] & 0x1) == 0x1)
+ {
+ if (wd->ap.staPowerSaving > 0)
+ {
+ zmw_enter_critical_section(dev);
+
+ /* Buffer this BC or MC frame */
+ if (((wd->ap.bcmcTail[vap]+1)&(ZM_BCMC_ARRAY_SIZE-1))
+ != wd->ap.bcmcHead[vap])
+ {
+ wd->ap.bcmcArray[vap][wd->ap.bcmcTail[vap]++] = buf;
+ wd->ap.bcmcTail[vap] &= (ZM_BCMC_ARRAY_SIZE-1);
+ zmw_leave_critical_section(dev);
+
+ zm_msg0_tx(ZM_LV_0, "Buffer BCMC");
+ }
+ else
+ {
+ /* bcmcArray full */
+ zmw_leave_critical_section(dev);
+
+ zm_msg0_tx(ZM_LV_0, "BCMC buffer full");
+
+ /* free buffer according to buffer type */
+ zfwBufFree(dev, buf, ZM_ERR_BCMC_PS_BUFFER_UNAVAILABLE);
+ }
+ return 1;
+ }
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ if (wd->ap.staTable[id].psMode == 1)
+ {
+
+ zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
+ ac = zcUpToAc[up&0x7] & 0x3;
+
+ if ((wd->ap.staTable[id].qosType == 1) &&
+ ((wd->ap.staTable[id].qosInfo & (0x8>>ac)) != 0))
+ {
+ ret = zfQueuePutNcs(dev, wd->ap.uapsdQ, buf, wd->tick);
+ zmw_leave_critical_section(dev);
+ if (ret != ZM_SUCCESS)
+ {
+ zfwBufFree(dev, buf, ZM_ERR_AP_UAPSD_QUEUE_FULL);
+ }
+ }
+ else
+ {
+ /* Buffer this unicast frame */
+ if (((wd->ap.uniTail+1)&(ZM_UNI_ARRAY_SIZE-1))
+ != wd->ap.uniHead)
+ {
+ wd->ap.uniArray[wd->ap.uniTail++] = buf;
+ wd->ap.uniTail &= (ZM_UNI_ARRAY_SIZE-1);
+ zmw_leave_critical_section(dev);
+ zm_msg0_tx(ZM_LV_0, "Buffer UNI");
+
+ }
+ else
+ {
+ /* uniArray full */
+ zmw_leave_critical_section(dev);
+ zm_msg0_tx(ZM_LV_0, "UNI buffer full");
+ /* free buffer according to buffer type */
+ zfwBufFree(dev, buf, ZM_ERR_UNI_PS_BUFFER_UNAVAILABLE);
+ }
+ }
+ return 1;
+ } /* if (wd->ap.staTable[id++].psMode == 1) */
+ } /* if ((id = zfApFindSta(dev, addr)) != 0xffff) */
+ zmw_leave_critical_section(dev);
+ }
+
+ return 0;
+}
+
+u16_t zfApGetSTAInfoAndUpdatePs(zdev_t* dev, u16_t* addr, u16_t* state,
+ u8_t* vap, u16_t psMode, u8_t* uapsdTrig)
+{
+ u16_t id;
+ u8_t uapsdStaAwake = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+#ifdef ZM_AP_DEBUG
+ //psMode=0;
+#endif
+
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ if (psMode != 0)
+ {
+ zm_msg0_mm(ZM_LV_0, "psMode = 1");
+ if (wd->ap.staTable[id].psMode == 0)
+ {
+ wd->ap.staPowerSaving++;
+ }
+ else
+ {
+ if (wd->ap.staTable[id].qosType == 1)
+ {
+ zm_msg0_mm(ZM_LV_0, "UAPSD trigger");
+ *uapsdTrig = wd->ap.staTable[id].qosInfo;
+ }
+ }
+ }
+ else
+ {
+ if (wd->ap.staTable[id].psMode != 0)
+ {
+ wd->ap.staPowerSaving--;
+ if ((wd->ap.staTable[id].qosType == 1) && ((wd->ap.staTable[id].qosInfo&0xf)!=0))
+ {
+ uapsdStaAwake = 1;
+ }
+ }
+ }
+
+ wd->ap.staTable[id].psMode = (u8_t) psMode;
+ wd->ap.staTable[id].time = wd->tick;
+ *vap = wd->ap.staTable[id].vap;
+ *state = wd->ap.staTable[id++].state;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (uapsdStaAwake == 1)
+ {
+ zbuf_t* psBuf;
+ u8_t mb;
+
+ while (1)
+ {
+ if ((psBuf = zfQueueGetWithMac(dev, wd->ap.uapsdQ, (u8_t*)addr, &mb)) != NULL)
+ {
+ zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return id;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApGetNewSta */
+/* Get a new STA from station table. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0xffff : fail */
+/* other : STA table index */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfApGetNewSta(zdev_t* dev)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
+ {
+ if (wd->ap.staTable[i].valid == 0)
+ {
+ zm_msg2_mm(ZM_LV_0, "zfApGetNewSta=", i);
+ return i;
+ }
+ }
+ return 0xffff;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApAddSta */
+/* Add a STA to station table. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : STA MAC address */
+/* state : STA state */
+/* apId : Virtual AP ID */
+/* type : 0=>11b, 1=>11g */
+/* */
+/* OUTPUTS */
+/* 0xffff : fail */
+/* Other : index */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfApAddSta(zdev_t* dev, u16_t* addr, u16_t state, u16_t apId, u8_t type,
+ u8_t qosType, u8_t qosInfo)
+{
+ u16_t index;
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zm_msg1_mm(ZM_LV_0, "STA type=", type);
+
+ zmw_enter_critical_section(dev);
+
+ if ((index = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ zm_msg0_mm(ZM_LV_2, "found");
+ /* Update STA state */
+ if ((state == ZM_STATE_AUTH) || (state == ZM_STATE_PREAUTH))
+ {
+ wd->ap.staTable[index].state = state;
+ wd->ap.staTable[index].time = wd->tick;
+ wd->ap.staTable[index].vap = (u8_t)apId;
+ }
+ else if (state == ZM_STATE_ASOC)
+ {
+ if ((wd->ap.staTable[index].state == ZM_STATE_AUTH))
+ //&& (wd->ap.staTable[index].vap == apId))
+ {
+ wd->ap.staTable[index].state = state;
+ wd->ap.staTable[index].time = wd->tick;
+ wd->ap.staTable[index].qosType = qosType;
+ wd->ap.staTable[index].vap = (u8_t)apId;
+ wd->ap.staTable[index].staType = type;
+ wd->ap.staTable[index].qosInfo = qosInfo;
+
+ if (wd->frequency < 3000)
+ {
+ /* Init 11b/g */
+ zfRateCtrlInitCell(dev, &wd->ap.staTable[index].rcCell, type, 1, 1);
+ }
+ else
+ {
+ /* Init 11a */
+ zfRateCtrlInitCell(dev, &wd->ap.staTable[index].rcCell, type, 0, 1);
+ }
+
+ if (wd->zfcbApConnectNotify != NULL)
+ {
+ wd->zfcbApConnectNotify(dev, (u8_t*)addr, apId);
+ }
+ }
+ else
+ {
+ index = 0xffff;
+ }
+ }
+ }
+ else
+ {
+ zm_msg0_mm(ZM_LV_2, "Not found");
+ if ((state == ZM_STATE_AUTH) || (state == ZM_STATE_PREAUTH))
+ {
+ /* Get a new STA and update state */
+ index = zfApGetNewSta(dev);
+ zm_msg2_mm(ZM_LV_1, "new STA index=", index);
+
+ if (index != 0xffff)
+ {
+ for (i=0; i<3; i++)
+ {
+ wd->ap.staTable[index].addr[i] = addr[i];
+ }
+ wd->ap.staTable[index].state = state;
+ wd->ap.staTable[index].valid = 1;
+ wd->ap.staTable[index].time = wd->tick;
+ wd->ap.staTable[index].vap = (u8_t)apId;
+ wd->ap.staTable[index].encryMode = ZM_NO_WEP;
+ }
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return index;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApAgingSta */
+/* Aging STA in station table. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* number of 11b STA in STA table */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+void zfApAgingSta(zdev_t* dev)
+{
+ u16_t i;
+ u32_t deltaMs;
+ u16_t addr[3];
+ u16_t txFlag;
+ u16_t psStaCount = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ wd->ap.gStaAssociated = wd->ap.bStaAssociated = 0;
+
+ for (i=0; i<ZM_MAX_STA_SUPPORT; i++)
+ {
+ txFlag = 0;
+ zmw_enter_critical_section(dev);
+ if (wd->ap.staTable[i].valid == 1)
+ {
+ addr[0] = wd->ap.staTable[i].addr[0];
+ addr[1] = wd->ap.staTable[i].addr[1];
+ addr[2] = wd->ap.staTable[i].addr[2];
+ /* millisecond */
+ deltaMs = (u32_t)((u32_t)wd->tick-(u32_t)wd->ap.staTable[i].time)
+ * ZM_MS_PER_TICK;
+
+ /* preauth */
+ if ((wd->ap.staTable[i].state == ZM_STATE_PREAUTH)
+ && (deltaMs > ZM_PREAUTH_TIMEOUT_MS))
+ {
+ /* Aging STA */
+ wd->ap.staTable[i].valid = 0;
+ wd->ap.authSharing = 0;
+ txFlag = 1;
+ }
+
+ /* auth */
+ if ((wd->ap.staTable[i].state == ZM_STATE_AUTH)
+ && (deltaMs > ZM_AUTH_TIMEOUT_MS))
+ {
+ /* Aging STA */
+ wd->ap.staTable[i].valid = 0;
+ txFlag = 1;
+ }
+
+ /* asoc */
+ if (wd->ap.staTable[i].state == ZM_STATE_ASOC)
+ {
+ if (wd->ap.staTable[i].psMode != 0)
+ {
+ psStaCount++;
+ }
+
+ if (deltaMs > ((u32_t)wd->ap.staAgingTimeSec<<10))
+ {
+ /* Aging STA */
+ zm_msg1_mm(ZM_LV_0, "Age STA index=", i);
+ wd->ap.staTable[i].valid = 0;
+ txFlag = 1;
+ }
+ else if (deltaMs > ((u32_t)wd->ap.staProbingTimeSec<<10))
+ {
+ if (wd->ap.staTable[i].psMode == 0)
+ {
+ /* Probing non-PS STA */
+ zm_msg1_mm(ZM_LV_0, "Probing STA index=", i);
+ wd->ap.staTable[i].time +=
+ (wd->ap.staProbingTimeSec * ZM_TICK_PER_SECOND);
+ txFlag = 2;
+ }
+ }
+ }
+
+
+ }
+ zmw_leave_critical_section(dev);
+
+ if (txFlag == 1)
+ {
+ /* Send deauthentication management frame */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, addr, 4, 0, 0);
+ }
+ else if (txFlag == 2)
+ {
+ zfSendMmFrame(dev, ZM_WLAN_DATA_FRAME, addr, 0, 0, 0);
+ }
+
+ }
+
+ wd->ap.staPowerSaving = psStaCount;
+
+ return;
+}
+
+void zfApProtctionMonitor(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* 11b STA associated => nonErp, Protect */
+ if (wd->ap.bStaAssociated > 0)
+ {
+ /* Enable NonErp bit in information element */
+ wd->erpElement = ZM_WLAN_NON_ERP_PRESENT_BIT
+ | ZM_WLAN_USE_PROTECTION_BIT;
+
+ /* Enable protection mode */
+ zfApSetProtectionMode(dev, 1);
+
+ }
+ /* 11b STA not associated, protection OBSS present => Protect */
+ else if (wd->ap.protectedObss > 2) //Threshold
+ {
+ if (wd->disableSelfCts == 0)
+ {
+ /* Disable NonErp bit in information element */
+ wd->erpElement = ZM_WLAN_USE_PROTECTION_BIT;
+
+ /* Enable protection mode */
+ zfApSetProtectionMode(dev, 1);
+ }
+ }
+ else
+ {
+ /* Disable NonErp bit in information element */
+ wd->erpElement = 0;
+
+ /* Disable protection mode */
+ zfApSetProtectionMode(dev, 0);
+ }
+ wd->ap.protectedObss = 0;
+}
+
+
+void zfApProcessBeacon(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t offset;
+ u8_t ch;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_msg0_mm(ZM_LV_3, "Rx beacon");
+
+ /* update Non-ERP flag(wd->ap.nonErpObss) */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) == 0xffff)
+ {
+ /* 11b OBSS */
+ wd->ap.protectedObss++;
+ return;
+ }
+
+ ch = zmw_rx_buf_readb(dev, buf, offset+2);
+ if ((ch & ZM_WLAN_USE_PROTECTION_BIT) == ZM_WLAN_USE_PROTECTION_BIT)
+ {
+ /* Protected OBSS */
+ wd->ap.protectedObss = 1;
+ }
+
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfProcessAuth */
+/* Process authenticate management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : auth frame buffer */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+/* Note : AP allows one authenticating STA at a time, does not */
+/* support multiple authentication process. Make sure */
+/* authentication state machine will not be blocked due */
+/* to incompleted authentication handshake. */
+void zfApProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
+{
+ u16_t algo, seq, status;
+ u8_t authSharing;
+ u16_t ret;
+ u16_t i;
+ u8_t challengePassed = 0;
+ u8_t frameCtrl;
+ u32_t retAlgoSeq;
+ u32_t retStatus;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+ frameCtrl = zmw_rx_buf_readb(dev, buf, 1);
+ /* AP : Auth share 3 */
+ /* shift for WEP IV */
+ if ((frameCtrl & 0x40) != 0)
+ {
+ algo = zmw_rx_buf_readh(dev, buf, 28);
+ seq = zmw_rx_buf_readh(dev, buf, 30);
+ status = zmw_rx_buf_readh(dev, buf, 32);
+ }
+ else
+ {
+ algo = zmw_rx_buf_readh(dev, buf, 24);
+ seq = zmw_rx_buf_readh(dev, buf, 26);
+ status = zmw_rx_buf_readh(dev, buf, 28);
+ }
+
+ zm_msg2_mm(ZM_LV_0, "Rx Auth, seq=", seq);
+
+ /* Set default to authentication algorithm not support */
+ retAlgoSeq = 0x20000 | algo;
+ retStatus = 13; /* authentication algorithm not support */
+
+ /* AP : Auth open 1 */
+ if (algo == 0)
+ {
+ if (wd->ap.authAlgo[apId] == 0)
+ {
+ retAlgoSeq = 0x20000;
+ if (seq == 1)
+ {
+ /* AP : update STA to auth */
+ if ((ret = zfApAddSta(dev, src, ZM_STATE_AUTH, apId, 0, 0, 0)) != 0xffff)
+ {
+ /* AP : call zfwAuthNotify() for host to judge */
+ //zfwAuthNotify(dev, src);
+
+ /* AP : response Auth seq=2, success */
+ retStatus = 0;
+
+ }
+ else
+ {
+ /* AP : response Auth seq=2, unspecific error */
+ retStatus = 1;
+ }
+ }
+ else
+ {
+ /* AP : response Auth seq=2, sequence number out of expected */
+ retStatus = 14;
+ }
+ }
+ }
+ /* AP : Auth share 1 */
+ else if (algo == 1)
+ {
+ if (wd->ap.authAlgo[apId] == 1)
+ {
+ if (seq == 1)
+ {
+ retAlgoSeq = 0x20001;
+
+ /* critical section */
+ zmw_enter_critical_section(dev);
+ if (wd->ap.authSharing == 1)
+ {
+ authSharing = 1;
+ }
+ else
+ {
+ authSharing = 0;
+ wd->ap.authSharing = 1;
+ }
+ /* end of critical section */
+ zmw_leave_critical_section(dev);
+
+ if (authSharing == 1)
+ {
+ /* AP : response Auth seq=2, status = fail */
+ retStatus = 1;
+ }
+ else
+ {
+ /* AP : update STA to preauth */
+ zfApAddSta(dev, src, ZM_STATE_PREAUTH, apId, 0, 0, 0);
+
+ /* AP : call zfwAuthNotify() for host to judge */
+ //zfwAuthNotify(dev, src);
+
+ /* AP : response Auth seq=2 */
+ retStatus = 0;
+ }
+ }
+ else if (seq == 3)
+ {
+ retAlgoSeq = 0x40001;
+
+ if (wd->ap.authSharing == 1)
+ {
+ /* check challenge text */
+ if (zmw_buf_readh(dev, buf, 30+4) == 0x8010)
+ {
+ for (i=0; i<128; i++)
+ {
+ if (wd->ap.challengeText[i]
+ != zmw_buf_readb(dev, buf, 32+i+4))
+ {
+ break;
+ }
+ }
+ if (i == 128)
+ {
+ challengePassed = 1;
+ }
+ }
+
+ if (challengePassed == 1)
+ {
+ /* AP : update STA to auth */
+ zfApAddSta(dev, src, ZM_STATE_AUTH, apId, 0, 0, 0);
+
+ /* AP : response Auth seq=2 */
+ retStatus = 0;
+ }
+ else
+ {
+ /* AP : response Auth seq=2, challenge failure */
+ retStatus = 15;
+
+ /* TODO : delete STA */
+ }
+
+ wd->ap.authSharing = 0;
+ }
+ }
+ else
+ {
+ retAlgoSeq = 0x40001;
+ retStatus = 14;
+ }
+ }
+ }
+
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH, src, retAlgoSeq,
+ retStatus, apId);
+ return;
+}
+
+void zfApProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
+{
+ u16_t aid = 0xffff;
+ u8_t frameType;
+ u16_t offset;
+ u8_t staType = 0;
+ u8_t qosType = 0;
+ u8_t qosInfo = 0;
+ u8_t tmp;
+ u16_t i, j, k;
+ u16_t encMode = 0;
+
+ zmw_get_wlan_dev(dev);
+ /* AP : check SSID */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) != 0xffff)
+ {
+ k = 0;
+ for (j = 0; j < wd->ap.vapNumber; j++)
+ {
+ if ((tmp = zmw_buf_readb(dev, buf, offset+1))
+ != wd->ap.ssidLen[j])
+ {
+ k++;
+ }
+ }
+ if (k == wd->ap.vapNumber)
+ {
+ goto zlDeauth;
+ }
+
+ k = 0;
+ for (j = 0; j < wd->ap.vapNumber; j++)
+ {
+ for (i=0; i<wd->ap.ssidLen[j]; i++)
+ {
+ if ((tmp = zmw_buf_readb(dev, buf, offset+2+i))
+ != wd->ap.ssid[j][i])
+ {
+ break;
+ }
+ }
+ if (i == wd->ap.ssidLen[j])
+ {
+ apId = j;
+ }
+ else
+ {
+ k++;
+ }
+ }
+ if (k == wd->ap.vapNumber)
+ {
+ goto zlDeauth;
+ }
+ }
+
+ /* TODO : check capability */
+
+ /* AP : check support rate */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) != 0xffff)
+ {
+ /* 11g STA */
+ staType = 1;
+ }
+ //CWYang(+)
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff)
+ {
+ /* 11n STA */
+ staType = 2;
+ }
+
+ /* TODO : do not allow 11b STA to associated in Pure G mode */
+ if (wd->ap.wlanType[apId] == ZM_WLAN_TYPE_PURE_G && staType == 0)
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 3, 0, 0);
+ return;
+ }
+
+ /* In pure B mode, we set G STA into B mode */
+ if (wd->ap.wlanType[apId] == ZM_WLAN_TYPE_PURE_B && staType == 1)
+ {
+ staType = 0;
+ }
+
+ /* AP : check 11i and WPA */
+ /* AP : check 11h */
+
+ /* AP : check WME */
+ if ((offset = zfFindWifiElement(dev, buf, 2, 0)) != 0xffff)
+ {
+ /* WME STA */
+ qosType = 1;
+ zm_msg0_mm(ZM_LV_0, "WME STA");
+
+ if (wd->ap.uapsdEnabled != 0)
+ {
+ qosInfo = zmw_rx_buf_readb(dev, buf, offset+8);
+ }
+ }
+
+ if (wd->ap.wpaSupport[apId] == 1)
+ {
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_WPA_IE)) != 0xffff )
+ {
+ /* get WPA IE */
+ u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length+2 < ZM_MAX_WPAIE_SIZE)
+ {
+ zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
+ wd->ap.stawpaLen[apId] = length+2;
+ encMode = 1;
+
+
+ zm_msg1_mm(ZM_LV_0, "WPA Mode zfwAsocNotify, apId=", apId);
+
+ /* AP : Call zfwAsocNotify() */
+ if (wd->zfcbAsocNotify != NULL)
+ {
+ wd->zfcbAsocNotify(dev, src, wd->ap.stawpaIe[apId], wd->ap.stawpaLen[apId], apId);
+ }
+ }
+ else
+ {
+ goto zlDeauth;
+ }
+ }
+ else if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_RSN_IE)) != 0xffff )
+ {
+ /* get RSN IE */
+ u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length+2 < ZM_MAX_WPAIE_SIZE)
+ {
+ zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
+ wd->ap.stawpaLen[apId] = length+2;
+ encMode = 1;
+
+ zm_msg1_mm(ZM_LV_0, "RSN Mode zfwAsocNotify, apId=", apId);
+
+ /* AP : Call zfwAsocNotify() */
+ if (wd->zfcbAsocNotify != NULL)
+ {
+ wd->zfcbAsocNotify(dev, src, wd->ap.stawpaIe[apId], wd->ap.stawpaLen[apId], apId);
+ }
+ }
+ else
+ {
+ goto zlDeauth;
+ }
+ }
+#ifdef ZM_ENABLE_CENC
+ else if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CENC_IE)) != 0xffff )
+ {
+ /* get CENC IE */
+ u8_t length = zmw_rx_buf_readb(dev, buf, offset+1);
+
+ if (length+2 < ZM_MAX_WPAIE_SIZE)
+ {
+ zfCopyFromRxBuffer(dev, buf, wd->ap.stawpaIe[apId], offset, length+2);
+ wd->ap.stawpaLen[apId] = length+2;
+ encMode = 1;
+
+ zm_msg1_mm(ZM_LV_0, "CENC Mode zfwAsocNotify, apId=", apId);
+
+ /* AP : Call zfwAsocNotify() */
+ if (wd->zfcbCencAsocNotify != NULL)
+ {
+ wd->zfcbCencAsocNotify(dev, src, wd->ap.stawpaIe[apId],
+ wd->ap.stawpaLen[apId], apId);
+ }
+ }
+ else
+ {
+ goto zlDeauth;
+ }
+ }
+#endif //ZM_ENABLE_CENC
+ else
+ { /* ap is encryption but sta has no wpa/rsn ie */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
+ return;
+ }
+ }
+ /* sta has wpa/rsn ie but ap is no encryption */
+ if ((wd->ap.wpaSupport[apId] == 0) && (encMode == 1))
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
+ return;
+ }
+
+ /* AP : update STA to asoc */
+ aid = zfApAddSta(dev, src, ZM_STATE_ASOC, apId, staType, qosType, qosInfo);
+
+ zfApStoreAsocReqIe(dev, buf, aid);
+
+zlDeauth:
+ /* AP : send asoc rsp2 */
+ if (aid != 0xffff)
+ {
+ frameType = zmw_rx_buf_readb(dev, buf, 0);
+
+ if (frameType == ZM_WLAN_FRAME_TYPE_ASOCREQ)
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCRSP, src, 0, aid+1, apId);
+ }
+ else
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_REASOCRSP, src, 0, aid+1, apId);
+ }
+ }
+ else
+ {
+ /* TODO : send deauthentication */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 6, 0, 0);
+ }
+
+ return;
+}
+
+void zfApStoreAsocReqIe(zdev_t* dev, zbuf_t* buf, u16_t aid)
+{
+ //struct zsWlanAssoFrameHeader* pAssoFrame;
+ //u8_t pBuf[sizeof(struct zsWlanAssoFrameHeader)];
+ u16_t offset;
+ u32_t i;
+ u16_t length;
+ u8_t *htcap;
+
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<wd->sta.asocRspFrameBodySize; i++)
+ {
+ wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24);
+ }
+ /* capability: 2 octets */
+ offset = 24;
+
+ /* Listen interval: 2 octets */
+ offset = 26;
+
+ /* SSID */
+ offset = 28;
+
+ /* supported rates */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_SUPPORT_RATE)) == 0xffff)
+ return;
+ length = zmw_rx_buf_readb(dev, buf, offset + 1);
+
+ /* extended supported rates */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) == 0xffff)
+ return;
+ length = zmw_rx_buf_readb(dev, buf, offset + 1);
+
+ /* power capability:4 octets */
+ offset = offset + 2 + length;
+
+ /* supported channels: 4 octets */
+ offset = offset + 2 + 4;
+
+ /* RSN */
+
+ /* QoS */
+
+ /* HT capabilities: 28 octets */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff) {
+ /* atheros pre n */
+ htcap = (u8_t *)&wd->ap.ie[aid].HtCap;
+ htcap[0] = zmw_rx_buf_readb(dev, buf, offset);
+ htcap[1] = 26;
+ for (i=1; i<=26; i++)
+ {
+ htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i);
+ zm_debug_msg2("ASOC: HT Capabilities, htcap=", htcap[i+1]);
+ }
+ return;
+ }
+ else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff) {
+ /* pre n 2.0 standard */
+ htcap = (u8_t *)&wd->ap.ie[aid].HtCap;
+ for (i=0; i<28; i++)
+ {
+ htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i);
+ zm_debug_msg2("ASOC: HT Capabilities, htcap=", htcap[i]);
+ }
+ }
+ else {
+ /* not 11n AP */
+ return;
+ }
+
+
+ /* supported regulatory classes */
+ offset = offset + length;
+ //length = zmw_rx_buf_readb(dev, buf, offset + 1);
+ {
+ u8_t *htcap;
+ htcap = (u8_t *)&wd->sta.ie.HtInfo;
+ //zm_debug_msg2("ASOC: HT Capabilities info=", ((u16_t *)htcap)[1]);
+ //zm_debug_msg2("ASOC: A-MPDU parameters=", htcap[4]);
+ //zm_debug_msg2("ASOC: Supported MCS set=", ((u32_t *)htcap)[1]>>8);
+ }
+
+}
+
+void zfApProcessAsocRsp(zdev_t* dev, zbuf_t* buf)
+{
+
+}
+
+void zfApProcessDeauth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
+{
+ u16_t aid;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ /* AP : if SA=associated STA then deauthenticate STA */
+ if ((aid = zfApFindSta(dev, src)) != 0xffff)
+ {
+ /* Clear STA table */
+ wd->ap.staTable[aid].valid = 0;
+ if (wd->zfcbDisAsocNotify != NULL)
+ {
+ wd->zfcbDisAsocNotify(dev, (u8_t*)src, apId);
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+}
+
+void zfApProcessDisasoc(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
+{
+ u16_t aid;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ /* AP : if SA=associated STA then deauthenticate STA */
+ if ((aid = zfApFindSta(dev, src)) != 0xffff)
+ {
+ /* Clear STA table */
+ wd->ap.staTable[aid].valid = 0;
+ zmw_leave_critical_section(dev);
+ if (wd->zfcbDisAsocNotify != NULL)
+ {
+ wd->zfcbDisAsocNotify(dev, (u8_t*)src, apId);
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+}
+
+
+void zfApProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo)
+{
+#if 0
+ zmw_get_wlan_dev(dev);
+
+ zm_msg0_mm(ZM_LV_0, "Rx probersp");
+
+ /* Gather scan result */
+
+ //zm_debug_msg1("bssList Count = ", wd->sta.bssList.bssCount);
+ /* return if not in scanning */
+ if ((wd->heartBeatNotification & ZM_BSSID_LIST_SCAN)
+ != ZM_BSSID_LIST_SCAN)
+ {
+ return;
+ }
+
+ //if ( wd->sta.pUpdateBssList->bssCount == ZM_MAX_BSS )
+ if ( wd->sta.bssList.bssCount == ZM_MAX_BSS )
+ {
+ return;
+ }
+
+ zfProcessProbeRsp(dev, buf, AddInfo);
+
+#endif
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApAddIeSsid */
+/* Add AP information element SSID to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* vap : virtual AP ID */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+u16_t zfApAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssidLen[vap]);
+
+ /* Information : SSID */
+ for (i=0; i<wd->ap.ssidLen[vap]; i++)
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->ap.ssid[vap][i]);
+ }
+
+ return offset;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApAddIeTim */
+/* Add AP information element TIM to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* vap : virtual AP ID */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+u16_t zfApAddIeTim(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
+{
+ u8_t uniBitMap[9];
+ u16_t highestByte;
+ u16_t i;
+ u16_t lenOffset;
+ u16_t id;
+ u16_t dst[3];
+ u16_t aid;
+ u16_t bitPosition;
+ u16_t bytePosition;
+ zbuf_t* psBuf;
+ zbuf_t* tmpBufArray[ZM_UNI_ARRAY_SIZE];
+ u16_t tmpBufArraySize = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_TIM);
+
+ /* offset of Element Length */
+ lenOffset = offset++;
+
+ /* Information : TIM */
+ /* DTIM count */
+ /* TODO : Doesn't work for Virtual AP's case */
+ wd->CurrentDtimCount++;
+ if (wd->CurrentDtimCount >= wd->dtim)
+ {
+ wd->CurrentDtimCount = 0;
+ }
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->CurrentDtimCount);
+ /* DTIM period */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->dtim);
+ /* bitmap offset */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0);
+
+ /* Update BCMC bit */
+ if (wd->CurrentDtimCount == 0)
+ {
+ zmw_enter_critical_section(dev);
+ wd->ap.timBcmcBit[vap] = (wd->ap.bcmcTail[vap]!=wd->ap.bcmcHead[vap])?1:0;
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ wd->ap.timBcmcBit[vap] = 0;
+ }
+
+ /* Update Unicast bitmap */
+ /* reset bit map */
+ for (i=0; i<9; i++)
+ {
+ uniBitMap[i] = 0;
+ }
+ highestByte = 0;
+#if 1
+
+ zmw_enter_critical_section(dev);
+
+ id = wd->ap.uniHead;
+ while (id != wd->ap.uniTail)
+ {
+ psBuf = wd->ap.uniArray[id];
+
+ /* TODO : Aging PS frame after queuing for more than 10 seconds */
+
+ /* get destination STA's aid */
+ dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
+ dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
+ dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
+ if ((aid = zfApFindSta(dev, dst)) != 0xffff)
+ {
+ if (wd->ap.staTable[aid].psMode != 0)
+ {
+ zm_msg1_mm(ZM_LV_0, "aid=",aid);
+ aid++;
+ zm_assert(aid<=64);
+ bitPosition = (1 << (aid & 0x7));
+ bytePosition = (aid >> 3);
+ uniBitMap[bytePosition] |= bitPosition;
+
+ if (bytePosition>highestByte)
+ {
+ highestByte = bytePosition;
+ }
+ id = (id+1) & (ZM_UNI_ARRAY_SIZE-1);
+ }
+ else
+ {
+ zm_msg0_mm(ZM_LV_0, "Send PS frame which STA no longer in PS mode");
+ /* Send PS frame which STA no longer in PS mode */
+ zfApRemoveFromPsQueue(dev, id, dst);
+ tmpBufArray[tmpBufArraySize++] = psBuf;
+ }
+ }
+ else
+ {
+ zm_msg0_mm(ZM_LV_0, "Free garbage PS frame");
+ /* Free garbage PS frame */
+ zfApRemoveFromPsQueue(dev, id, dst);
+ zfwBufFree(dev, psBuf, 0);
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+#endif
+
+ zfQueueGenerateUapsdTim(dev, wd->ap.uapsdQ, uniBitMap, &highestByte);
+
+ zm_msg1_mm(ZM_LV_3, "bm=",uniBitMap[0]);
+ zm_msg1_mm(ZM_LV_3, "highestByte=",highestByte);
+ zm_msg1_mm(ZM_LV_3, "timBcmcBit[]=",wd->ap.timBcmcBit[vap]);
+
+ /* bitmap */
+ zmw_tx_buf_writeb(dev, buf, offset++,
+ uniBitMap[0] | wd->ap.timBcmcBit[vap]);
+ for (i=0; i<highestByte; i++)
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, uniBitMap[i+1]);
+ }
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, lenOffset, highestByte+4);
+
+ for (i=0; i<tmpBufArraySize; i++)
+ {
+ /* Put to VTXQ[ac] */
+ zfPutVtxq(dev, tmpBufArray[i]);
+ }
+ /* Push VTXQ[ac] */
+ zfPushVtxq(dev);
+
+ return offset;
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApRemoveFromPsQueue */
+/* Remove zbuf from PS queue. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* id : index in ps queue */
+/* */
+/* OUTPUTS */
+/* more data bit */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+u8_t zfApRemoveFromPsQueue(zdev_t* dev, u16_t id, u16_t* addr)
+{
+ u16_t dst[3];
+ u16_t nid;
+ u8_t moreData = 0;
+ zmw_get_wlan_dev(dev);
+
+ wd->ap.uniTail = (wd->ap.uniTail-1) & (ZM_UNI_ARRAY_SIZE-1);
+ while (id != wd->ap.uniTail)
+ {
+ nid = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
+ wd->ap.uniArray[id] = wd->ap.uniArray[nid];
+
+ /* Search until tail to config more data bit */
+ dst[0] = zmw_buf_readh(dev, wd->ap.uniArray[id], 0);
+ dst[1] = zmw_buf_readh(dev, wd->ap.uniArray[id], 2);
+ dst[2] = zmw_buf_readh(dev, wd->ap.uniArray[id], 4);
+ if ((addr[0] == dst[0]) && (addr[1] == dst[1])
+ && (addr[2] == dst[2]))
+ {
+ moreData = 0x20;
+ }
+
+ id = nid;
+ }
+ return moreData;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApAddIeWmePara */
+/* Add WME Parameter Element to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* vap : virtual AP ID */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.1 */
+/* */
+/************************************************************************/
+u16_t zfApAddIeWmePara(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t vap)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WIFI_IE);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, 24);
+
+ /* OUI */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x50);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0xF2);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x02);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
+
+ /* QoS Info */
+ if (wd->ap.uapsdEnabled)
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x81);
+ }
+ else
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
+ }
+
+ /* Reserved */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+
+ /* Best Effort AC parameters */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x03);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ /* Backfround AC parameters */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x27);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0xA4);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ /* Video AC parameters */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x42);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x43);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x5E);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ /* Voice AC parameters */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x62);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x32);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x2F);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+
+ return offset;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApSendBeacon */
+/* Sned AP mode beacon. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+void zfApSendBeacon(zdev_t* dev)
+{
+ zbuf_t* buf;
+ u16_t offset;
+ u16_t vap;
+ u16_t seq;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ wd->ap.beaconCounter++;
+ if (wd->ap.beaconCounter >= wd->ap.vapNumber)
+ {
+ wd->ap.beaconCounter = 0;
+ }
+ vap = wd->ap.beaconCounter;
+
+
+ zm_msg1_mm(ZM_LV_2, "Send beacon, vap=", vap);
+
+ /* TBD : Maximum size of beacon */
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc beacon buf Fail!");
+ return;
+ }
+
+ offset = 0;
+
+ /* wlan header */
+ /* Frame control */
+ zmw_tx_buf_writeh(dev, buf, offset, 0x0080);
+ offset+=2;
+ /* Duration */
+ zmw_tx_buf_writeh(dev, buf, offset, 0x0000);
+ offset+=2;
+ /* Address 1 */
+ zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
+ offset+=2;
+ /* Address 2 */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
+ offset+=2;
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
+#else
+ zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
+#endif
+ offset+=2;
+ /* Address 3 */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
+ offset+=2;
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); //Multiple SSID
+#else
+ zmw_tx_buf_writeh(dev, buf, offset, (wd->macAddr[2]+(vap<<8))); //VAP
+#endif
+ offset+=2;
+
+ /* Sequence number */
+ zmw_enter_critical_section(dev);
+ seq = ((wd->mmseq++)<<4);
+ zmw_leave_critical_section(dev);
+ zmw_tx_buf_writeh(dev, buf, offset, seq);
+ offset+=2;
+
+ /* 24-31 Time Stamp : hardware will fill this field */
+ zmw_tx_buf_writeh(dev, buf, offset, 0);
+ zmw_tx_buf_writeh(dev, buf, offset+2, 0);
+ zmw_tx_buf_writeh(dev, buf, offset+4, 0);
+ zmw_tx_buf_writeh(dev, buf, offset+6, 0);
+ offset+=8;
+
+ /* Beacon Interval */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
+ offset+=2;
+
+ /* Capability */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->ap.capab[vap]);
+ offset+=2;
+
+ /* SSID */
+ if (wd->ap.hideSsid[vap] == 0)
+ {
+ offset = zfApAddIeSsid(dev, buf, offset, vap);
+ }
+ else
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0);
+
+ }
+
+ /* Support Rate */
+ if ( wd->frequency < 3000 )
+ {
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
+ }
+ else
+ {
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
+ }
+
+ /* DS parameter set */
+ offset = zfMmAddIeDs(dev, buf, offset);
+
+ /* TIM */
+ offset = zfApAddIeTim(dev, buf, offset, vap);
+
+ /* If WLAN Type is not PURE B */
+ if (wd->ap.wlanType[vap] != ZM_WLAN_TYPE_PURE_B)
+ {
+ if ( wd->frequency < 3000 )
+ {
+ /* ERP Information */
+ offset = zfMmAddIeErp(dev, buf, offset);
+
+ /* Extended Supported Rates */
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ }
+
+ /* TODO : country information */
+ /* TODO : RSN */
+ if (wd->ap.wpaSupport[vap] == 1)
+ {
+ offset = zfMmAddIeWpa(dev, buf, offset, vap);
+ }
+
+ /* WME Parameters */
+ if (wd->ap.qosMode == 1)
+ {
+ offset = zfApAddIeWmePara(dev, buf, offset, vap);
+ }
+
+ /* HT Capabilities Info */
+ offset = zfMmAddHTCapability(dev, buf, offset);
+
+ /* Extended HT Capabilities Info */
+ offset = zfMmAddExtendedHTCapability(dev, buf, offset);
+
+ /* 1212 : write to beacon fifo */
+ /* 1221 : write to share memory */
+ zfHpSendBeacon(dev, buf, offset);
+
+ /* Free beacon buffer */
+ /* TODO: In order to fit the madwifi beacon architecture, we need to
+ free beacon buffer in the HAL layer.
+ */
+
+ //zfwBufFree(dev, buf, 0);
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfIntrabssForward */
+/* Called to transmit intra-BSS frame from upper layer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer pointer */
+/* vap : virtual AP */
+/* */
+/* OUTPUTS */
+/* 1 : unicast intras-BSS frame */
+/* 0 : other frames */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+u16_t zfIntrabssForward(zdev_t* dev, zbuf_t* buf, u8_t srcVap)
+{
+ u16_t err;
+ u16_t asocFlag = 0;
+ u16_t dst[3];
+ u16_t aid;
+ u16_t staState;
+ zbuf_t* txBuf;
+ u16_t len;
+ u16_t i;
+ u16_t temp;
+ u16_t ret;
+ u8_t vap = 0;
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ dst[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
+ dst[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
+ dst[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
+#else
+ dst[0] = zmw_rx_buf_readh(dev, buf, 0);
+ dst[1] = zmw_rx_buf_readh(dev, buf, 2);
+ dst[2] = zmw_rx_buf_readh(dev, buf, 4);
+#endif // ZM_ENABLE_NATIVE_WIFI
+
+ /* Do Intra-BSS forward(data copy) if necessary*/
+ if ((dst[0]&0x1) != 0x1)
+ {
+ aid = zfApGetSTAInfo(dev, dst, &staState, &vap);
+ if ((aid != 0xffff) && (staState == ZM_STATE_ASOC) && (srcVap == vap))
+ {
+ asocFlag = 1;
+ zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : asoc STA");
+ }
+
+ }
+ else
+ {
+ vap = srcVap;
+ zm_msg0_rx(ZM_LV_2, "Intra-BSS forward : BCorMC");
+ }
+
+ /* destination address = associated STA or BC/MC */
+ if ((asocFlag == 1) || ((dst[0]&0x1) == 0x1))
+ {
+ /* Allocate frame */
+ if ((txBuf = zfwBufAllocate(dev, ZM_RX_FRAME_SIZE))
+ == NULL)
+ {
+ zm_msg0_rx(ZM_LV_1, "Alloc intra-bss buf Fail!");
+ goto zlAllocError;
+ }
+
+ /* Copy frame */
+ len = zfwBufGetSize(dev, buf);
+ for (i=0; i<len; i+=2)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, i);
+ zmw_tx_buf_writeh(dev, txBuf, i, temp);
+ }
+ zfwBufSetSize(dev, txBuf, len);
+
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ /* Tx-A2 = Rx-A1, Tx-A3 = Rx-A2, Tx-A1 = Rx-A3 */
+ for (i=0; i<6; i+=2)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+i);
+ zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A2_OFFSET+i, temp);
+ temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+i);
+ zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A3_OFFSET+i, temp);
+ temp = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+i);
+ zmw_tx_buf_writeh(dev, txBuf, ZM_WLAN_HEADER_A1_OFFSET+i, temp);
+ }
+
+ #endif
+
+ /* Transmit frame */
+ /* Return error if port is disabled */
+ if ((err = zfTxPortControl(dev, txBuf, vap)) == ZM_PORT_DISABLED)
+ {
+ err = ZM_ERR_TX_PORT_DISABLED;
+ goto zlTxError;
+ }
+
+#if 1
+ /* AP : Buffer frame for power saving STA */
+ if ((ret = zfApBufferPsFrame(dev, txBuf, vap)) == 0)
+ {
+ /* forward frame if not been buffered */
+ #if 1
+ /* Put to VTXQ[ac] */
+ ret = zfPutVtxq(dev, txBuf);
+ /* Push VTXQ[ac] */
+ zfPushVtxq(dev);
+ #else
+ zfTxSendEth(dev, txBuf, vap, ZM_INTERNAL_ALLOC_BUF, 0);
+ #endif
+
+ }
+#endif
+ }
+ return asocFlag;
+
+zlTxError:
+ zfwBufFree(dev, txBuf, 0);
+zlAllocError:
+ return asocFlag;
+}
+
+struct zsMicVar* zfApGetRxMicKey(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t sa[6];
+ u16_t id = 0, macAddr[3];
+
+ zmw_get_wlan_dev(dev);
+
+ zfCopyFromRxBuffer(dev, buf, sa, ZM_WLAN_HEADER_A2_OFFSET, 6);
+
+ macAddr[0] = sa[0] + (sa[1] << 8);
+ macAddr[1] = sa[2] + (sa[3] << 8);
+ macAddr[2] = sa[4] + (sa[5] << 8);
+
+ if ((id = zfApFindSta(dev, macAddr)) != 0xffff)
+ return (&wd->ap.staTable[id].rxMicKey);
+
+ return NULL;
+}
+
+struct zsMicVar* zfApGetTxMicKey(zdev_t* dev, zbuf_t* buf, u8_t* qosType)
+{
+ u8_t da[6];
+ u16_t id = 0, macAddr[3];
+
+ zmw_get_wlan_dev(dev);
+
+ zfCopyFromIntTxBuffer(dev, buf, da, 0, 6);
+
+ macAddr[0] = da[0] + (da[1] << 8);
+ macAddr[1] = da[2] + (da[3] << 8);
+ macAddr[2] = da[4] + (da[5] << 8);
+
+ if ((macAddr[0] & 0x1))
+ {
+ return (&wd->ap.bcMicKey[0]);
+ }
+ else if ((id = zfApFindSta(dev, macAddr)) != 0xffff)
+ {
+ *qosType = wd->ap.staTable[id].qosType;
+ return (&wd->ap.staTable[id].txMicKey);
+ }
+
+ return NULL;
+}
+
+u16_t zfApUpdatePsBit(zdev_t* dev, zbuf_t* buf, u8_t* vap, u8_t* uapsdTrig)
+{
+ u16_t staState;
+ u16_t aid;
+ u16_t psBit;
+ u16_t src[3];
+ u16_t dst[1];
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ src[0] = zmw_rx_buf_readh(dev, buf, 10);
+ src[1] = zmw_rx_buf_readh(dev, buf, 12);
+ src[2] = zmw_rx_buf_readh(dev, buf, 14);
+
+ if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3)
+ {
+ /* AP */
+ dst[0] = zmw_rx_buf_readh(dev, buf, 4);
+
+ psBit = (zmw_rx_buf_readb(dev, buf, 1) & 0x10) >> 4;
+ /* Get AID and update STA PS mode */
+ aid = zfApGetSTAInfoAndUpdatePs(dev, src, &staState, vap, psBit, uapsdTrig);
+
+ /* if STA not associated, send deauth */
+ if ((aid == 0xffff) || (staState != ZM_STATE_ASOC))
+ {
+ if ((dst[0]&0x1)==0)
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, src, 0x7,
+ 0, 0);
+ }
+
+ return ZM_ERR_STA_NOT_ASSOCIATED;
+ }
+ } /* if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3) */
+ else
+ {
+ /* WDS */
+ for (i=0; i<ZM_MAX_WDS_SUPPORT; i++)
+ {
+ if ((wd->ap.wds.wdsBitmap & (1<<i)) != 0)
+ {
+ if ((src[0] == wd->ap.wds.macAddr[i][0])
+ && (src[1] == wd->ap.wds.macAddr[i][1])
+ && (src[2] == wd->ap.wds.macAddr[i][2]))
+ {
+ *vap = 0x20 + i;
+ break;
+ }
+ }
+ }
+ }
+ return ZM_SUCCESS;
+}
+
+void zfApProcessPsPoll(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t src[3];
+ u16_t dst[3];
+ zbuf_t* psBuf = NULL;
+ u16_t id;
+ u8_t moreData = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ src[0] = zmw_tx_buf_readh(dev, buf, 10);
+ src[1] = zmw_tx_buf_readh(dev, buf, 12);
+ src[2] = zmw_tx_buf_readh(dev, buf, 14);
+
+ /* Find ps buffer for PsPoll */
+ zmw_enter_critical_section(dev);
+ id = wd->ap.uniHead;
+ while (id != wd->ap.uniTail)
+ {
+ psBuf = wd->ap.uniArray[id];
+
+ dst[0] = zmw_tx_buf_readh(dev, psBuf, 0);
+ dst[1] = zmw_tx_buf_readh(dev, psBuf, 2);
+ dst[2] = zmw_tx_buf_readh(dev, psBuf, 4);
+
+ if ((src[0] == dst[0]) && (src[1] == dst[1]) && (src[2] == dst[2]))
+ {
+ moreData = zfApRemoveFromPsQueue(dev, id, src);
+ break;
+ }
+ else
+ {
+ psBuf = NULL;
+ }
+ id = (id + 1) & (ZM_UNI_ARRAY_SIZE - 1);
+ }
+ zmw_leave_critical_section(dev);
+
+ /* Send ps buffer */
+ if (psBuf != NULL)
+ {
+ /* Send with more data bit */
+ zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, moreData);
+ }
+
+ return;
+}
+
+void zfApSetProtectionMode(zdev_t* dev, u16_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ if (mode == 0)
+ {
+ if (wd->ap.protectionMode != mode)
+ {
+ /* Write MAC&PHY registers to disable protection */
+
+ wd->ap.protectionMode = mode;
+ }
+
+ }
+ else
+ {
+ if (wd->ap.protectionMode != mode)
+ {
+ /* Write MAC&PHY registers to enable protection */
+
+ wd->ap.protectionMode = mode;
+ }
+ }
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfApSendFailure */
+/* Send failure. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : receiver address */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+void zfApSendFailure(zdev_t* dev, u8_t* addr)
+{
+ u16_t id;
+ u16_t staAddr[3];
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ staAddr[0] = addr[0] + (((u16_t)addr[1])<<8);
+ staAddr[1] = addr[2] + (((u16_t)addr[3])<<8);
+ staAddr[2] = addr[4] + (((u16_t)addr[5])<<8);
+ zmw_enter_critical_section(dev);
+ if ((id = zfApFindSta(dev, staAddr)) != 0xffff)
+ {
+ /* Send failture : Add 3 minutes to inactive time that will */
+ /* will make STA been kicked out soon */
+ wd->ap.staTable[id].time -= (3*ZM_TICK_PER_MINUTE);
+ }
+ zmw_leave_critical_section(dev);
+}
+
+
+void zfApProcessAction(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t category;
+
+ //zmw_get_wlan_dev(dev);
+
+ //zmw_declare_for_critical_section();
+
+ category = zmw_rx_buf_readb(dev, buf, 24);
+
+ switch (category)
+ {
+ case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
+ zfAggBlockAckActionFrame(dev, buf);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
diff --git a/drivers/staging/otus/80211core/cmmsta.c b/drivers/staging/otus/80211core/cmmsta.c
new file mode 100644
index 000000000000..c75ba11ee43d
--- /dev/null
+++ b/drivers/staging/otus/80211core/cmmsta.c
@@ -0,0 +1,5782 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+#include "ratectrl.h"
+#include "../hal/hpreg.h"
+
+/* TODO : change global variable to constant */
+u8_t zgWpaRadiusOui[] = { 0x00, 0x50, 0xf2, 0x01 };
+u8_t zgWpaAesOui[] = { 0x00, 0x50, 0xf2, 0x04 };
+u8_t zgWpa2RadiusOui[] = { 0x00, 0x0f, 0xac, 0x01 };
+u8_t zgWpa2AesOui[] = { 0x00, 0x0f, 0xac, 0x04 };
+
+const u16_t zcCwTlb[16] = { 0, 1, 3, 7, 15, 31, 63, 127,
+ 255, 511, 1023, 2047, 4095, 4095, 4095, 4095};
+
+void zfStaStartConnectCb(zdev_t* dev);
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaPutApIntoBlockingList */
+/* Put AP into blocking AP list. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* bssid : AP's BSSID */
+/* weight : weight of AP */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+void zfStaPutApIntoBlockingList(zdev_t* dev, u8_t* bssid, u8_t weight)
+{
+ u16_t i, j;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ if (weight > 0)
+ {
+ zmw_enter_critical_section(dev);
+ /*Find same bssid entry first*/
+ for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
+ {
+ for (j=0; j<6; j++)
+ {
+ if(wd->sta.blockingApList[i].addr[j]!= bssid[j])
+ {
+ break;
+ }
+ }
+
+ if(j==6)
+ {
+ break;
+ }
+ }
+ /*This bssid doesn't have old record.Find an empty entry*/
+ if (i == ZM_MAX_BLOCKING_AP_LIST_SIZE)
+ {
+ for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
+ {
+ if (wd->sta.blockingApList[i].weight == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ /* If the list is full, pick one entry for replacement */
+ if (i == ZM_MAX_BLOCKING_AP_LIST_SIZE)
+ {
+ i = bssid[5] & (ZM_MAX_BLOCKING_AP_LIST_SIZE-1);
+ }
+
+ /* Update AP address and weight */
+ for (j=0; j<6; j++)
+ {
+ wd->sta.blockingApList[i].addr[j] = bssid[j];
+ }
+
+ wd->sta.blockingApList[i].weight = weight;
+ zmw_leave_critical_section(dev);
+ }
+
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaIsApInBlockingList */
+/* Is AP in blocking list. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* bssid : AP's BSSID */
+/* */
+/* OUTPUTS */
+/* TRUE : AP in blocking list */
+/* FALSE : AP not in blocking list */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfStaIsApInBlockingList(zdev_t* dev, u8_t* bssid)
+{
+ u16_t i, j;
+ zmw_get_wlan_dev(dev);
+ //zmw_declare_for_critical_section();
+
+ //zmw_enter_critical_section(dev);
+ for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
+ {
+ if (wd->sta.blockingApList[i].weight != 0)
+ {
+ for (j=0; j<6; j++)
+ {
+ if (wd->sta.blockingApList[i].addr[j] != bssid[j])
+ {
+ break;
+ }
+ }
+ if (j == 6)
+ {
+ //zmw_leave_critical_section(dev);
+ return TRUE;
+ }
+ }
+ }
+ //zmw_leave_critical_section(dev);
+ return FALSE;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaRefreshBlockList */
+/* Is AP in blocking list. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* flushFlag : flush whole blocking list */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+void zfStaRefreshBlockList(zdev_t* dev, u16_t flushFlag)
+{
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ for (i=0; i<ZM_MAX_BLOCKING_AP_LIST_SIZE; i++)
+ {
+ if (wd->sta.blockingApList[i].weight != 0)
+ {
+ if (flushFlag != 0)
+ {
+ wd->sta.blockingApList[i].weight = 0;
+ }
+ else
+ {
+ wd->sta.blockingApList[i].weight--;
+ }
+ }
+ }
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaConnectFail */
+/* Handle Connect failure. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* bssid : BSSID */
+/* reason : reason of failure */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+void zfStaConnectFail(zdev_t* dev, u16_t reason, u16_t* bssid, u8_t weight)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* Change internal state */
+ zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT);
+
+ /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */
+ //zfHpSetTTSIFSTime(dev, 0x8);
+
+ /* Notify wrapper of connection status changes */
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, reason, bssid);
+ }
+
+ /* Put AP into internal blocking list */
+ zfStaPutApIntoBlockingList(dev, (u8_t *)bssid, weight);
+
+ /* Issue another SCAN */
+ if ( wd->sta.bAutoReconnect )
+ {
+ zm_debug_msg0("Start internal scan...");
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ zfScanMgrScanStart(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ }
+}
+
+u8_t zfiWlanIBSSGetPeerStationsCount(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->sta.oppositeCount;
+}
+
+u8_t zfiWlanIBSSIteratePeerStations(zdev_t* dev, u8_t numToIterate, zfpIBSSIteratePeerStationCb callback, void *ctx)
+{
+ u8_t oppositeCount;
+ u8_t i;
+ u8_t index = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ oppositeCount = wd->sta.oppositeCount;
+ if ( oppositeCount > numToIterate )
+ {
+ oppositeCount = numToIterate;
+ }
+
+ for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
+ {
+ if ( oppositeCount == 0 )
+ {
+ break;
+ }
+
+ if ( wd->sta.oppositeInfo[i].valid == 0 )
+ {
+ continue;
+ }
+
+ callback(dev, &wd->sta.oppositeInfo[i], ctx, index++);
+ oppositeCount--;
+
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return index;
+}
+
+
+s8_t zfStaFindFreeOpposite(zdev_t* dev, u16_t *sa, int *pFoundIdx)
+{
+ int oppositeCount;
+ int i;
+
+ zmw_get_wlan_dev(dev);
+
+ oppositeCount = wd->sta.oppositeCount;
+
+ for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
+ {
+ if ( oppositeCount == 0 )
+ {
+ break;
+ }
+
+ if ( wd->sta.oppositeInfo[i].valid == 0 )
+ {
+ continue;
+ }
+
+ oppositeCount--;
+ if ( zfMemoryIsEqual((u8_t*) sa, wd->sta.oppositeInfo[i].macAddr, 6) )
+ {
+ //wd->sta.oppositeInfo[i].aliveCounter++;
+ wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER;
+
+ /* it is already stored */
+ return 1;
+ }
+ }
+
+ // Check if there's still space for new comer
+ if ( wd->sta.oppositeCount == ZM_MAX_OPPOSITE_COUNT )
+ {
+ return -1;
+ }
+
+ // Find an unused slot for new peer station
+ for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
+ {
+ if ( wd->sta.oppositeInfo[i].valid == 0 )
+ {
+ break;
+ }
+ }
+
+ *pFoundIdx = i;
+ return 0;
+}
+
+s8_t zfStaFindOppositeByMACAddr(zdev_t* dev, u16_t *sa, u8_t *pFoundIdx)
+{
+ u32_t oppositeCount;
+ u32_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ oppositeCount = wd->sta.oppositeCount;
+
+ for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
+ {
+ if ( oppositeCount == 0 )
+ {
+ break;
+ }
+
+ if ( wd->sta.oppositeInfo[i].valid == 0 )
+ {
+ continue;
+ }
+
+ oppositeCount--;
+ if ( zfMemoryIsEqual((u8_t*) sa, wd->sta.oppositeInfo[i].macAddr, 6) )
+ {
+ *pFoundIdx = (u8_t)i;
+
+ return 0;
+ }
+ }
+
+ *pFoundIdx = 0;
+ return 1;
+}
+
+static void zfStaInitCommonOppositeInfo(zdev_t* dev, int i)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* set the default rate to the highest rate */
+ wd->sta.oppositeInfo[i].valid = 1;
+ wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER;
+ wd->sta.oppositeCount++;
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ /* Set parameters for new opposite peer station !!! */
+ wd->sta.oppositeInfo[i].camIdx = 0xff; // Not set key in this location
+ wd->sta.oppositeInfo[i].pkInstalled = 0;
+ wd->sta.oppositeInfo[i].wpaState = ZM_STA_WPA_STATE_INIT ; // No encryption
+#endif
+}
+
+int zfStaSetOppositeInfoFromBSSInfo(zdev_t* dev, struct zsBssInfo* pBssInfo)
+{
+ int i;
+ u8_t* dst;
+ u16_t sa[3];
+ int res;
+ u32_t oneTxStreamCap;
+
+ zmw_get_wlan_dev(dev);
+
+ zfMemoryCopy((u8_t*) sa, pBssInfo->macaddr, 6);
+
+ res = zfStaFindFreeOpposite(dev, sa, &i);
+ if ( res != 0 )
+ {
+ goto zlReturn;
+ }
+
+ dst = wd->sta.oppositeInfo[i].macAddr;
+ zfMemoryCopy(dst, (u8_t *)sa, 6);
+
+ oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM);
+
+ if (pBssInfo->extSupportedRates[1] != 0)
+ {
+ /* TODO : Handle 11n */
+ if (pBssInfo->frequency < 3000)
+ {
+ /* 2.4GHz */
+ if (pBssInfo->EnableHT == 1)
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, pBssInfo->SG40);
+ else
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 1, pBssInfo->SG40);
+ }
+ else
+ {
+ /* 5GHz */
+ if (pBssInfo->EnableHT == 1)
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, pBssInfo->SG40);
+ else
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, pBssInfo->SG40);
+ }
+ }
+ else
+ {
+ /* TODO : Handle 11n */
+ if (pBssInfo->frequency < 3000)
+ {
+ /* 2.4GHz */
+ if (pBssInfo->EnableHT == 1)
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, pBssInfo->SG40);
+ else
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 0, 1, pBssInfo->SG40);
+ }
+ else
+ {
+ /* 5GHz */
+ if (pBssInfo->EnableHT == 1)
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, pBssInfo->SG40);
+ else
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, pBssInfo->SG40);
+ }
+ }
+
+
+ zfStaInitCommonOppositeInfo(dev, i);
+zlReturn:
+ return 0;
+}
+
+int zfStaSetOppositeInfoFromRxBuf(zdev_t* dev, zbuf_t* buf)
+{
+ int i;
+ u8_t* dst;
+ u16_t sa[3];
+ int res = 0;
+ u16_t offset;
+ u8_t bSupportExtRate;
+ u32_t rtsctsRate = 0xffffffff; /* CTS:OFDM 6M, RTS:OFDM 6M */
+ u32_t oneTxStreamCap;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ sa[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
+ sa[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2);
+ sa[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4);
+
+ zmw_enter_critical_section(dev);
+
+ res = zfStaFindFreeOpposite(dev, sa, &i);
+ if ( res != 0 )
+ {
+ goto zlReturn;
+ }
+
+ dst = wd->sta.oppositeInfo[i].macAddr;
+ zfCopyFromRxBuffer(dev, buf, dst, ZM_WLAN_HEADER_A2_OFFSET, 6);
+
+ if ( (wd->sta.currentFrequency < 3000) && !(wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) )
+ {
+ bSupportExtRate = 0;
+ } else {
+ bSupportExtRate = 1;
+ }
+
+ if ( (bSupportExtRate == 1)
+ && (wd->sta.currentFrequency < 3000)
+ && (wd->wlanMode == ZM_MODE_IBSS)
+ && (wd->wfc.bIbssGMode == 0) )
+ {
+ bSupportExtRate = 0;
+ }
+
+ wd->sta.connection_11b = 0;
+ oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM);
+
+ if ( ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) != 0xffff)
+ && (bSupportExtRate == 1) )
+ {
+ /* TODO : Handle 11n */
+ if (wd->sta.currentFrequency < 3000)
+ {
+ /* 2.4GHz */
+ if (wd->sta.EnableHT == 1)
+ {
+ //11ng
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, wd->sta.SG40);
+ }
+ else
+ {
+ //11g
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 1, wd->sta.SG40);
+ }
+ rtsctsRate = 0x00001bb; /* CTS:CCK 1M, RTS:OFDM 6M */
+ }
+ else
+ {
+ /* 5GHz */
+ if (wd->sta.EnableHT == 1)
+ {
+ //11na
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, wd->sta.SG40);
+ }
+ else
+ {
+ //11a
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, wd->sta.SG40);
+ }
+ rtsctsRate = 0x10b01bb; /* CTS:OFDM 6M, RTS:OFDM 6M */
+ }
+ }
+ else
+ {
+ /* TODO : Handle 11n */
+ if (wd->sta.currentFrequency < 3000)
+ {
+ /* 2.4GHz */
+ if (wd->sta.EnableHT == 1)
+ {
+ //11ng
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, wd->sta.SG40);
+ rtsctsRate = 0x00001bb; /* CTS:CCK 1M, RTS:OFDM 6M */
+ }
+ else
+ {
+ //11b
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 0, 1, wd->sta.SG40);
+ rtsctsRate = 0x0; /* CTS:CCK 1M, RTS:CCK 1M */
+ wd->sta.connection_11b = 1;
+ }
+ }
+ else
+ {
+ /* 5GHz */
+ if (wd->sta.EnableHT == 1)
+ {
+ //11na
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, wd->sta.SG40);
+ }
+ else
+ {
+ //11a
+ zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, wd->sta.SG40);
+ }
+ rtsctsRate = 0x10b01bb; /* CTS:OFDM 6M, RTS:OFDM 6M */
+ }
+ }
+
+ zfStaInitCommonOppositeInfo(dev, i);
+
+zlReturn:
+ zmw_leave_critical_section(dev);
+
+ if (rtsctsRate != 0xffffffff)
+ {
+ zfHpSetRTSCTSRate(dev, rtsctsRate);
+ }
+ return res;
+}
+
+void zfStaProtErpMonitor(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t offset;
+ u8_t erp;
+ u8_t bssid[6];
+
+ zmw_get_wlan_dev(dev);
+
+ if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)&&(zfStaIsConnected(dev)) )
+ {
+ ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);
+
+ if (zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6))
+ {
+ if ( (offset=zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff )
+ {
+ erp = zmw_rx_buf_readb(dev, buf, offset+2);
+
+ if ( erp & ZM_BIT_1 )
+ {
+ //zm_debug_msg0("protection mode on");
+ if (wd->sta.bProtectionMode == FALSE)
+ {
+ wd->sta.bProtectionMode = TRUE;
+ zfHpSetSlotTime(dev, 0);
+ }
+ }
+ else
+ {
+ //zm_debug_msg0("protection mode off");
+ if (wd->sta.bProtectionMode == TRUE)
+ {
+ wd->sta.bProtectionMode = FALSE;
+ zfHpSetSlotTime(dev, 1);
+ }
+ }
+ }
+ }
+ //Check the existence of Non-N AP
+ //Follow the check the "pBssInfo->EnableHT"
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff)
+ {}
+ else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff)
+ {}
+ else
+ {wd->sta.NonNAPcount++;}
+ }
+}
+
+void zfStaUpdateWmeParameter(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t tmp;
+ u16_t aifs[5];
+ u16_t cwmin[5];
+ u16_t cwmax[5];
+ u16_t txop[5];
+ u8_t acm;
+ u8_t ac;
+ u16_t len;
+ u16_t i;
+ u16_t offset;
+ u8_t rxWmeParameterSetCount;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Update if WME parameter set count is changed */
+ /* If connect to WME AP */
+ if (wd->sta.wmeConnected != 0)
+ {
+ /* Find WME parameter element */
+ if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff)
+ {
+ if ((len = zmw_rx_buf_readb(dev, buf, offset+1)) >= 7)
+ {
+ rxWmeParameterSetCount=zmw_rx_buf_readb(dev, buf, offset+8);
+ if (rxWmeParameterSetCount != wd->sta.wmeParameterSetCount)
+ {
+ zm_msg0_mm(ZM_LV_0, "wmeParameterSetCount changed!");
+ wd->sta.wmeParameterSetCount = rxWmeParameterSetCount;
+ /* retrieve WME parameter and update TxQ parameters */
+ acm = 0xf;
+ for (i=0; i<4; i++)
+ {
+ if (len >= (8+(i*4)+4))
+ {
+ tmp=zmw_rx_buf_readb(dev, buf, offset+10+i*4);
+ ac = (tmp >> 5) & 0x3;
+ if ((tmp & 0x10) == 0)
+ {
+ acm &= (~(1<<ac));
+ }
+ aifs[ac] = ((tmp & 0xf) * 9) + 10;
+ tmp=zmw_rx_buf_readb(dev, buf, offset+11+i*4);
+ /* Convert to 2^n */
+ cwmin[ac] = zcCwTlb[(tmp & 0xf)];
+ cwmax[ac] = zcCwTlb[(tmp >> 4)];
+ txop[ac]=zmw_rx_buf_readh(dev, buf,
+ offset+12+i*4);
+ }
+ }
+
+ if ((acm & 0x4) != 0)
+ {
+ cwmin[2] = cwmin[0];
+ cwmax[2] = cwmax[0];
+ aifs[2] = aifs[0];
+ txop[2] = txop[0];
+ }
+ if ((acm & 0x8) != 0)
+ {
+ cwmin[3] = cwmin[2];
+ cwmax[3] = cwmax[2];
+ aifs[3] = aifs[2];
+ txop[3] = txop[2];
+ }
+ cwmin[4] = 3;
+ cwmax[4] = 7;
+ aifs[4] = 28;
+
+ if ((cwmin[2]+aifs[2]) > ((cwmin[0]+aifs[0])+1))
+ {
+ wd->sta.ac0PriorityHigherThanAc2 = 1;
+ }
+ else
+ {
+ wd->sta.ac0PriorityHigherThanAc2 = 0;
+ }
+ zfHpUpdateQosParameter(dev, cwmin, cwmax, aifs, txop);
+ }
+ }
+ }
+ } //if (wd->sta.wmeConnected != 0)
+}
+/* process 802.11h Dynamic Frequency Selection */
+void zfStaUpdateDot11HDFS(zdev_t* dev, zbuf_t* buf)
+{
+ zmw_get_wlan_dev(dev);
+
+ /*
+ Channel Switch Announcement Element Format
+ +------+----------+------+-------------------+------------------+--------------------+
+ |Format|Element ID|Length|Channel Switch Mode|New Channel Number|Channel Switch Count|
+ +------+----------+------+-------------------+------------------+--------------------+
+ |Bytes | 1 | 1 | 1 | 1 | 1 |
+ +------+----------+------+-------------------+------------------+--------------------+
+ |Value | 37 | 3 | 0 or 1 |unsigned integer |unsigned integer |
+ +------+----------+------+-------------------+------------------+--------------------+
+ */
+ //u8_t length, channel, is5G;
+ u16_t offset;
+
+ /* get EID(Channel Switch Announcement) */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CHANNEL_SWITCH_ANNOUNCE)) == 0xffff )
+ {
+ //zm_debug_msg0("EID(Channel Switch Announcement) not found");
+ return;
+ }
+ else if ( zmw_rx_buf_readb(dev, buf, offset+1) == 0x3 )
+ {
+ zm_debug_msg0("EID(Channel Switch Announcement) found");
+
+ //length = zmw_rx_buf_readb(dev, buf, offset+1);
+ //zfCopyFromRxBuffer(dev, buf, pBssInfo->supportedRates, offset, length+2);
+
+ //Chanell Switch Mode set to 1, driver should disable transmit immediate
+ //we do this by poll CCA high
+ if (zmw_rx_buf_readb(dev, buf, offset+2) == 0x1 )
+ {
+ //use ZM_OID_INTERNAL_WRITE,ZM_CMD_RESET to notice firmware flush quene and stop dma,
+ //then restart rx dma but not tx dma
+ if (wd->sta.DFSDisableTx != TRUE)
+ {
+ /* TODO : zfHpResetTxRx would cause Rx hang */
+ //zfHpResetTxRx(dev);
+ wd->sta.DFSDisableTx = TRUE;
+ /* Trgger Rx DMA */
+ zfHpStartRecv(dev);
+ }
+ //Adapter->ZD80211HSetting.DisableTxBy80211H=TRUE;
+ //AcquireCtrOfPhyReg(Adapter);
+ //ZD1205_WRITE_REGISTER(Adapter,CR24, 0x0);
+ //ReleaseDoNotSleep(Adapter);
+ }
+
+ if (zmw_rx_buf_readb(dev, buf, offset+4) <= 0x2 )
+ {
+ //Channel Switch
+ //if Channel Switch Count = 0 , STA should change channel immediately.
+ //if Channel Switch Count > 0 , STA should change channel after TBTT*count
+ //But it won't be accurate to let driver calculate TBTT*count, and the value of
+ //Channel Switch Count will decrease by one each when continue receving beacon
+ //So we change channel here when we receive count <=2.
+
+ zfHpDeleteAllowChannel(dev, wd->sta.currentFrequency);
+ wd->frequency = zfChNumToFreq(dev, zmw_rx_buf_readb(dev, buf, offset+3), 0);
+ //zfHpAddAllowChannel(dev, wd->frequency);
+ zm_debug_msg1("CWY - jump to frequency = ", wd->frequency);
+ zfCoreSetFrequency(dev, wd->frequency);
+ wd->sta.DFSDisableTx = FALSE;
+ /* Increase rxBeaconCount to prevent beacon lost */
+ if (zfStaIsConnected(dev))
+ {
+ wd->sta.rxBeaconCount = 1 << 6; // 2 times of check would pass
+ }
+ //start tx dma to transmit packet
+
+ //if (zmw_rx_buf_readb(dev, buf, offset+3) != wd->frequency)
+ //{
+ // //ZDDbgPrint(("Radar Detect by AP\n"));
+ // zfCoreSetFrequency();
+ // ProcessRadarDetectEvent(Adapter);
+ // Set_RF_Channel(Adapter, SwRfd->Rfd->RxBuffer[index+3], (UCHAR)Adapter->RF_Mode, 1);
+ // Adapter->CardSetting.Channel = SwRfd->Rfd->RxBuffer[index+3];
+ // Adapter->SaveChannel = Adapter->CardSetting.Channel;
+ // Adapter->UtilityChannel = Adapter->CardSetting.Channel;
+ //}
+ }
+ }
+
+}
+/* TODO : process 802.11h Transmission Power Control */
+void zfStaUpdateDot11HTPC(zdev_t* dev, zbuf_t* buf)
+{
+}
+
+/* IBSS power-saving mode */
+void zfStaIbssPSCheckState(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t i, frameCtrl;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( !zfStaIsConnected(dev) )
+ {
+ return;
+ }
+
+ if ( wd->wlanMode != ZM_MODE_IBSS )
+ {
+ return ;
+ }
+
+ /* check BSSID */
+ if ( !zfRxBufferEqualToStr(dev, buf, (u8_t*) wd->sta.bssid,
+ ZM_WLAN_HEADER_A3_OFFSET, 6) )
+ {
+ return;
+ }
+
+ frameCtrl = zmw_rx_buf_readb(dev, buf, 1);
+
+ /* check power management bit */
+ if ( frameCtrl & ZM_BIT_4 )
+ {
+ for(i=1; i<ZM_MAX_PS_STA; i++)
+ {
+ if ( !wd->sta.staPSList.entity[i].bUsed )
+ {
+ continue;
+ }
+
+ /* check source address */
+ if ( zfRxBufferEqualToStr(dev, buf,
+ wd->sta.staPSList.entity[i].macAddr,
+ ZM_WLAN_HEADER_A2_OFFSET, 6) )
+ {
+ return;
+ }
+ }
+
+ for(i=1; i<ZM_MAX_PS_STA; i++)
+ {
+ if ( !wd->sta.staPSList.entity[i].bUsed )
+ {
+ wd->sta.staPSList.entity[i].bUsed = TRUE;
+ wd->sta.staPSList.entity[i].bDataQueued = FALSE;
+ break;
+ }
+ }
+
+ if ( i == ZM_MAX_PS_STA )
+ {
+ /* STA list is full */
+ return;
+ }
+
+ zfCopyFromRxBuffer(dev, buf, wd->sta.staPSList.entity[i].macAddr,
+ ZM_WLAN_HEADER_A2_OFFSET, 6);
+
+ if ( wd->sta.staPSList.count == 0 )
+ {
+ // enable ATIM window
+ //zfEnableAtimWindow(dev);
+ }
+
+ wd->sta.staPSList.count++;
+ }
+ else if ( wd->sta.staPSList.count )
+ {
+ for(i=1; i<ZM_MAX_PS_STA; i++)
+ {
+ if ( wd->sta.staPSList.entity[i].bUsed )
+ {
+ if ( zfRxBufferEqualToStr(dev, buf,
+ wd->sta.staPSList.entity[i].macAddr,
+ ZM_WLAN_HEADER_A2_OFFSET, 6) )
+ {
+ wd->sta.staPSList.entity[i].bUsed = FALSE;
+ wd->sta.staPSList.count--;
+
+ if ( wd->sta.staPSList.entity[i].bDataQueued )
+ {
+ /* send queued data */
+ }
+ }
+ }
+ }
+
+ if ( wd->sta.staPSList.count == 0 )
+ {
+ /* disable ATIM window */
+ //zfDisableAtimWindow(dev);
+ }
+
+ }
+}
+
+/* IBSS power-saving mode */
+u8_t zfStaIbssPSQueueData(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t i;
+ u16_t da[3];
+
+ zmw_get_wlan_dev(dev);
+
+ if ( !zfStaIsConnected(dev) )
+ {
+ return 0;
+ }
+
+ if ( wd->wlanMode != ZM_MODE_IBSS )
+ {
+ return 0;
+ }
+
+ if ( wd->sta.staPSList.count == 0 && wd->sta.powerSaveMode <= ZM_STA_PS_NONE )
+ {
+ return 0;
+ }
+
+ /* DA */
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ da[0] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
+ da[1] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET + 2);
+ da[2] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET + 4);
+#else
+ da[0] = zmw_tx_buf_readh(dev, buf, 0);
+ da[1] = zmw_tx_buf_readh(dev, buf, 2);
+ da[2] = zmw_tx_buf_readh(dev, buf, 4);
+#endif
+
+ if ( ZM_IS_MULTICAST_OR_BROADCAST(da) )
+ {
+ wd->sta.staPSList.entity[0].bDataQueued = TRUE;
+ wd->sta.ibssPSDataQueue[wd->sta.ibssPSDataCount++] = buf;
+ return 1;
+ }
+
+ // Unicast packet...
+
+ for(i=1; i<ZM_MAX_PS_STA; i++)
+ {
+ if ( zfMemoryIsEqual(wd->sta.staPSList.entity[i].macAddr,
+ (u8_t*) da, 6) )
+ {
+ wd->sta.staPSList.entity[i].bDataQueued = TRUE;
+ wd->sta.ibssPSDataQueue[wd->sta.ibssPSDataCount++] = buf;
+
+ return 1;
+ }
+ }
+
+#if 0
+ if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
+ {
+ wd->sta.staPSDataQueue[wd->sta.staPSDataCount++] = buf;
+
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+/* IBSS power-saving mode */
+void zfStaIbssPSSend(zdev_t* dev)
+{
+ u8_t i;
+ u16_t bcastAddr[3] = {0xffff, 0xffff, 0xffff};
+
+ zmw_get_wlan_dev(dev);
+
+ if ( !zfStaIsConnected(dev) )
+ {
+ return ;
+ }
+
+ if ( wd->wlanMode != ZM_MODE_IBSS )
+ {
+ return ;
+ }
+
+ for(i=0; i<ZM_MAX_PS_STA; i++)
+ {
+ if ( wd->sta.staPSList.entity[i].bDataQueued )
+ {
+ if ( i == 0 )
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ATIM,
+ bcastAddr,
+ 0, 0, 0);
+ }
+ else if ( wd->sta.staPSList.entity[i].bUsed )
+ {
+ // Send ATIM to prevent the peer to go to sleep
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ATIM,
+ (u16_t*) wd->sta.staPSList.entity[i].macAddr,
+ 0, 0, 0);
+ }
+
+ wd->sta.staPSList.entity[i].bDataQueued = FALSE;
+ }
+ }
+
+ for(i=0; i<wd->sta.ibssPSDataCount; i++)
+ {
+ zfTxSendEth(dev, wd->sta.ibssPSDataQueue[i], 0,
+ ZM_EXTERNAL_ALLOC_BUF, 0);
+ }
+
+ wd->sta.ibssPrevPSDataCount = wd->sta.ibssPSDataCount;
+ wd->sta.ibssPSDataCount = 0;
+}
+
+
+void zfStaReconnect(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE &&
+ wd->wlanMode != ZM_MODE_IBSS )
+ {
+ return;
+ }
+
+ if ( (zfStaIsConnected(dev))||(zfStaIsConnecting(dev)) )
+ {
+ return;
+ }
+
+ if ( wd->sta.bChannelScan )
+ {
+ return;
+ }
+
+ /* Recover zero SSID length */
+ if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) && (wd->ws.ssidLen == 0))
+ {
+ zm_debug_msg0("zfStaReconnect: NOT Support!! Set SSID to any BSS");
+ /* ANY BSS */
+ zmw_enter_critical_section(dev);
+ wd->sta.ssid[0] = 0;
+ wd->sta.ssidLen = 0;
+ zmw_leave_critical_section(dev);
+ }
+
+ // RAY: To ensure no TX pending before re-connecting
+ zfFlushVtxq(dev);
+ zfWlanEnable(dev);
+ zfScanMgrScanAck(dev);
+}
+
+void zfStaTimer100ms(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( (wd->tick % 10) == 0 )
+ {
+ zfPushVtxq(dev);
+// zfPowerSavingMgrMain(dev);
+ }
+}
+
+
+void zfStaCheckRxBeacon(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) && (zfStaIsConnected(dev)))
+ {
+ if (wd->beaconInterval == 0)
+ {
+ wd->beaconInterval = 100;
+ }
+ if ( (wd->tick % ((wd->beaconInterval * 10) / ZM_MS_PER_TICK)) == 0 )
+ {
+ /* Check rxBeaconCount */
+ if (wd->sta.rxBeaconCount == 0)
+ {
+ if (wd->sta.beaconMissState == 1)
+ {
+ /*notify AP that we left*/
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, wd->sta.bssid, 3, 0, 0);
+ /* Beacon Lost */
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_BEACON_MISS,
+ wd->sta.bssid, 0);
+ }
+ else
+ {
+ wd->sta.beaconMissState = 1;
+ /* Reset channel */
+ zfCoreSetFrequencyExV2(dev, wd->frequency, wd->BandWidth40,
+ wd->ExtOffset, NULL, 1);
+ }
+ }
+ else
+ {
+ wd->sta.beaconMissState = 0;
+ }
+ wd->sta.rxBeaconCount = 0;
+ }
+ }
+}
+
+
+
+void zfStaCheckConnectTimeout(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE )
+ {
+ return;
+ }
+
+ if ( !zfStaIsConnecting(dev) )
+ {
+ return;
+ }
+
+ zmw_enter_critical_section(dev);
+ if ( (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_OPEN)||
+ (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_1)||
+ (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_2)||
+ (wd->sta.connectState == ZM_STA_CONN_STATE_ASSOCIATE) )
+ {
+ if ( (wd->tick - wd->sta.connectTimer) > ZM_INTERVAL_CONNECT_TIMEOUT )
+ {
+ if ( wd->sta.connectByReasso )
+ {
+ wd->sta.failCntOfReasso++;
+ if ( wd->sta.failCntOfReasso > 2 )
+ {
+ wd->sta.connectByReasso = FALSE;
+ }
+ }
+
+ wd->sta.connectState = ZM_STA_CONN_STATE_NONE;
+ zm_debug_msg1("connect timeout, state = ", wd->sta.connectState);
+ //zfiWlanDisable(dev);
+ goto failed;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+ return;
+
+failed:
+ zmw_leave_critical_section(dev);
+ if(wd->sta.authMode == ZM_AUTH_MODE_AUTO)
+ { // Fix some AP not send authentication failed message to sta and lead to connect timeout !
+ wd->sta.connectTimeoutCount++;
+ }
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_TIMEOUT, wd->sta.bssid, 2);
+ return;
+}
+
+void zfMmStaTimeTick(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* airopeek */
+ if (wd->wlanMode != ZM_MODE_AP && !wd->swSniffer)
+ {
+ if ( wd->tick & 1 )
+ {
+ zfTimerCheckAndHandle(dev);
+ }
+
+ zfStaCheckRxBeacon(dev);
+ zfStaTimer100ms(dev);
+ zfStaCheckConnectTimeout(dev);
+ zfPowerSavingMgrMain(dev);
+ }
+
+#ifdef ZM_ENABLE_AGGREGATION
+ /*
+ * add by honda
+ */
+ zfAggScanAndClear(dev, wd->tick);
+#endif
+}
+
+void zfStaSendBeacon(zdev_t* dev)
+{
+ zbuf_t* buf;
+ u16_t offset, seq;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ //zm_debug_msg0("\n");
+
+ /* TBD : Maximum size of beacon */
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_debug_msg0("Allocate beacon buffer failed");
+ return;
+ }
+
+ offset = 0;
+ /* wlan header */
+ /* Frame control */
+ zmw_tx_buf_writeh(dev, buf, offset, 0x0080);
+ offset+=2;
+ /* Duration */
+ zmw_tx_buf_writeh(dev, buf, offset, 0x0000);
+ offset+=2;
+ /* Address 1 */
+ zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, 0xffff);
+ offset+=2;
+ /* Address 2 */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]);
+ offset+=2;
+ /* Address 3 */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[0]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[1]);
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[2]);
+ offset+=2;
+
+ /* Sequence number */
+ zmw_enter_critical_section(dev);
+ seq = ((wd->mmseq++)<<4);
+ zmw_leave_critical_section(dev);
+ zmw_tx_buf_writeh(dev, buf, offset, seq);
+ offset+=2;
+
+ /* 24-31 Time Stamp : hardware will fill this field */
+ offset+=8;
+
+ /* Beacon Interval */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval);
+ offset+=2;
+
+ /* Capability */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[0]);
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[1]);
+
+ /* SSID */
+ offset = zfStaAddIeSsid(dev, buf, offset);
+
+ if(wd->frequency <= ZM_CH_G_14) // 2.4 GHz b+g
+ {
+
+ /* Support Rate */
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK);
+
+ /* DS parameter set */
+ offset = zfMmAddIeDs(dev, buf, offset);
+
+ offset = zfStaAddIeIbss(dev, buf, offset);
+
+ if( wd->wfc.bIbssGMode
+ && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) // Only accompany with enabling a mode .
+ {
+ /* ERP Information */
+ wd->erpElement = 0;
+ offset = zfMmAddIeErp(dev, buf, offset);
+ }
+
+ /* TODO : country information */
+ /* RSN */
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
+ {
+ offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH);
+ }
+
+ if( wd->wfc.bIbssGMode
+ && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) // Only accompany with enabling a mode .
+ {
+ /* Enable G Mode */
+ /* Extended Supported Rates */
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM);
+ }
+ }
+ else // 5GHz a
+ {
+ /* Support Rate a Mode */
+ offset = zfMmAddIeSupportRate(dev, buf, offset,
+ ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM);
+
+ /* DS parameter set */
+ offset = zfMmAddIeDs(dev, buf, offset);
+
+ offset = zfStaAddIeIbss(dev, buf, offset);
+
+ /* TODO : country information */
+ /* RSN */
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
+ {
+ offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH);
+ }
+ }
+
+ if ( wd->wlanMode != ZM_MODE_IBSS )
+ {
+ /* TODO : Need to check if it is ok */
+ /* HT Capabilities Info */
+ offset = zfMmAddHTCapability(dev, buf, offset);
+
+ /* Extended HT Capabilities Info */
+ offset = zfMmAddExtendedHTCapability(dev, buf, offset);
+ }
+
+ if ( wd->sta.ibssAdditionalIESize )
+ offset = zfStaAddIbssAdditionalIE(dev, buf, offset);
+
+ /* 1212 : write to beacon fifo */
+ /* 1221 : write to share memory */
+ zfHpSendBeacon(dev, buf, offset);
+
+ /* Free beacon buffer */
+ //zfwBufFree(dev, buf, 0);
+}
+
+void zfStaSignalStatistic(zdev_t* dev, u8_t SignalStrength, u8_t SignalQuality) //CWYang(+)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* Add Your Code to Do Works Like Moving Average Here */
+ wd->SignalStrength = (wd->SignalStrength * 7 + SignalStrength * 3)/10;
+ wd->SignalQuality = (wd->SignalQuality * 7 + SignalQuality * 3)/10;
+
+}
+
+struct zsBssInfo* zfStaFindBssInfo(zdev_t* dev, zbuf_t* buf, struct zsWlanProbeRspFrameHeader *pProbeRspHeader)
+{
+ u8_t i;
+ u8_t j;
+ u8_t k;
+ u8_t isMatched, length, channel;
+ u16_t offset, frequency;
+ struct zsBssInfo* pBssInfo;
+
+ zmw_get_wlan_dev(dev);
+
+ if ((pBssInfo = wd->sta.bssList.head) == NULL)
+ {
+ return NULL;
+ }
+
+ for( i=0; i<wd->sta.bssList.bssCount; i++ )
+ {
+ //zm_debug_msg2("check pBssInfo = ", pBssInfo);
+
+ /* Check BSSID */
+ for( j=0; j<6; j++ )
+ {
+ if ( pBssInfo->bssid[j] != pProbeRspHeader->bssid[j] )
+ {
+ break;
+ }
+ }
+
+ /* Check SSID */
+ if (j == 6)
+ {
+ if (pProbeRspHeader->ssid[1] <= 32)
+ {
+ /* compare length and ssid */
+ isMatched = 1;
+ if((pProbeRspHeader->ssid[1] != 0) && (pBssInfo->ssid[1] != 0))
+ {
+ for( k=1; k<pProbeRspHeader->ssid[1] + 1; k++ )
+ {
+ if ( pBssInfo->ssid[k] != pProbeRspHeader->ssid[k] )
+ {
+ isMatched = 0;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ isMatched = 0;
+ }
+ }
+ else
+ {
+ isMatched = 0;
+ }
+
+ /* Check channel */
+ /* Add check channel to solve the bug #31222 */
+ if (isMatched) {
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_DS)) != 0xffff) {
+ if ((length = zmw_rx_buf_readb(dev, buf, offset+1)) == 1) {
+ channel = zmw_rx_buf_readb(dev, buf, offset+2);
+ if (zfHpIsAllowedChannel(dev, zfChNumToFreq(dev, channel, 0)) == 0) {
+ frequency = 0;
+ } else {
+ frequency = zfChNumToFreq(dev, channel, 0);;
+ }
+ } else {
+ frequency = 0;
+ }
+ } else {
+ frequency = wd->sta.currentFrequency;
+ }
+
+ if (frequency != 0) {
+ if ( ((frequency > 3000) && (pBssInfo->frequency > 3000))
+ || ((frequency < 3000) && (pBssInfo->frequency < 3000)) ) {
+ /* redundant */
+ break;
+ }
+ }
+ }
+
+ pBssInfo = pBssInfo->next;
+ }
+
+ if ( i == wd->sta.bssList.bssCount )
+ {
+ pBssInfo = NULL;
+ }
+
+ return pBssInfo;
+}
+
+u8_t zfStaInitBssInfo(zdev_t* dev, zbuf_t* buf,
+ struct zsWlanProbeRspFrameHeader *pProbeRspHeader,
+ struct zsBssInfo* pBssInfo, struct zsAdditionInfo* AddInfo, u8_t type)
+{
+ u8_t length, channel, is5G;
+ u16_t i, offset;
+ u8_t apQosInfo;
+ u16_t eachIElength = 0;
+ u16_t accumulateLen = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ if ((type == 1) && ((pBssInfo->flag & ZM_BSS_INFO_VALID_BIT) != 0))
+ {
+ goto zlUpdateRssi;
+ }
+
+ /* get SSID */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) == 0xffff )
+ {
+ zm_debug_msg0("EID(SSID) not found");
+ goto zlError;
+ }
+
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+
+ {
+ u8_t Show_Flag = 0;
+ zfwGetShowZeroLengthSSID(dev, &Show_Flag);
+
+ if(Show_Flag)
+ {
+ if (length > ZM_MAX_SSID_LENGTH )
+ {
+ zm_debug_msg0("EID(SSID) is invalid");
+ goto zlError;
+ }
+ }
+ else
+ {
+ if ( length == 0 || length > ZM_MAX_SSID_LENGTH )
+ {
+ zm_debug_msg0("EID(SSID) is invalid");
+ goto zlError;
+ }
+
+ }
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->ssid, offset, length+2);
+
+ /* get DS parameter */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_DS)) != 0xffff )
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if ( length != 1 )
+ {
+ zm_msg0_mm(ZM_LV_0, "Abnormal DS Param Set IE");
+ goto zlError;
+ }
+ channel = zmw_rx_buf_readb(dev, buf, offset+2);
+
+ if (zfHpIsAllowedChannel(dev, zfChNumToFreq(dev, channel, 0)) == 0)
+ {
+ goto zlError2;
+ }
+
+ pBssInfo->frequency = zfChNumToFreq(dev, channel, 0); // auto check
+ pBssInfo->channel = channel;
+
+
+ }
+ else
+ {
+ /* DS parameter not found */
+ pBssInfo->frequency = wd->sta.currentFrequency;
+ pBssInfo->channel = zfChFreqToNum(wd->sta.currentFrequency, &is5G);
+ }
+
+ /* initialize security type */
+ pBssInfo->securityType = ZM_SECURITY_TYPE_NONE;
+
+ /* get macaddr */
+ for( i=0; i<6; i++ )
+ {
+ pBssInfo->macaddr[i] = pProbeRspHeader->sa[i];
+ }
+
+ /* get bssid */
+ for( i=0; i<6; i++ )
+ {
+ pBssInfo->bssid[i] = pProbeRspHeader->bssid[i];
+ }
+
+ /* get timestamp */
+ for( i=0; i<8; i++ )
+ {
+ pBssInfo->timeStamp[i] = pProbeRspHeader->timeStamp[i];
+ }
+
+ /* get beacon interval */
+ pBssInfo->beaconInterval[0] = pProbeRspHeader->beaconInterval[0];
+ pBssInfo->beaconInterval[1] = pProbeRspHeader->beaconInterval[1];
+
+ /* get capability */
+ pBssInfo->capability[0] = pProbeRspHeader->capability[0];
+ pBssInfo->capability[1] = pProbeRspHeader->capability[1];
+
+ /* Copy frame body */
+ offset = 36; // Copy from the start of variable IE
+ pBssInfo->frameBodysize = zfwBufGetSize(dev, buf)-offset;
+ if (pBssInfo->frameBodysize > (ZM_MAX_PROBE_FRAME_BODY_SIZE-1))
+ {
+ pBssInfo->frameBodysize = ZM_MAX_PROBE_FRAME_BODY_SIZE-1;
+ }
+ accumulateLen = 0;
+ do
+ {
+ eachIElength = zmw_rx_buf_readb(dev, buf, offset + accumulateLen+1) + 2; //Len+(EID+Data)
+
+ if ( (eachIElength >= 2)
+ && ((accumulateLen + eachIElength) <= pBssInfo->frameBodysize) )
+ {
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->frameBody+accumulateLen, offset+accumulateLen, eachIElength);
+ accumulateLen+=(u16_t)eachIElength;
+ }
+ else
+ {
+ zm_msg0_mm(ZM_LV_1, "probersp frameBodysize abnormal");
+ break;
+ }
+ }
+ while(accumulateLen < pBssInfo->frameBodysize);
+ pBssInfo->frameBodysize = accumulateLen;
+
+ /* get supported rates */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SUPPORT_RATE)) == 0xffff )
+ {
+ zm_debug_msg0("EID(supported rates) not found");
+ goto zlError;
+ }
+
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if ( length == 0 || length > ZM_MAX_SUPP_RATES_IE_SIZE)
+ {
+ zm_msg0_mm(ZM_LV_0, "Supported rates IE length abnormal");
+ goto zlError;
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->supportedRates, offset, length+2);
+
+
+
+ /* get Country information */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_COUNTRY)) != 0xffff )
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length > ZM_MAX_COUNTRY_INFO_SIZE)
+ {
+ length = ZM_MAX_COUNTRY_INFO_SIZE;
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->countryInfo, offset, length+2);
+ /* check 802.11d support data */
+ if (wd->sta.b802_11D)
+ {
+ zfHpGetRegulationTablefromISO(dev, (u8_t *)&pBssInfo->countryInfo, 3);
+ /* only set regulatory one time */
+ wd->sta.b802_11D = 0;
+ }
+ }
+
+ /* get ERP information */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff )
+ {
+ pBssInfo->erp = zmw_rx_buf_readb(dev, buf, offset+2);
+ }
+
+ /* get extended supported rates */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) != 0xffff )
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length > ZM_MAX_SUPP_RATES_IE_SIZE)
+ {
+ zm_msg0_mm(ZM_LV_0, "Extended rates IE length abnormal");
+ goto zlError;
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->extSupportedRates, offset, length+2);
+ }
+ else
+ {
+ pBssInfo->extSupportedRates[0] = 0;
+ pBssInfo->extSupportedRates[1] = 0;
+ }
+
+ /* get WPA IE */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_WPA_IE)) != 0xffff )
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length > ZM_MAX_IE_SIZE)
+ {
+ length = ZM_MAX_IE_SIZE;
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->wpaIe, offset, length+2);
+ pBssInfo->securityType = ZM_SECURITY_TYPE_WPA;
+ }
+ else
+ {
+ pBssInfo->wpaIe[1] = 0;
+ }
+
+ /* get WPS IE */
+ if ((offset = zfFindWifiElement(dev, buf, 4, 0xff)) != 0xffff)
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length > ZM_MAX_WPS_IE_SIZE )
+ {
+ length = ZM_MAX_WPS_IE_SIZE;
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->wscIe, offset, length+2);
+ }
+ else
+ {
+ pBssInfo->wscIe[1] = 0;
+ }
+
+ /* get SuperG IE */
+ if ((offset = zfFindSuperGElement(dev, buf, ZM_WLAN_EID_VENDOR_PRIVATE)) != 0xffff)
+ {
+ pBssInfo->apCap |= ZM_SuperG_AP;
+ }
+
+ /* get XR IE */
+ if ((offset = zfFindXRElement(dev, buf, ZM_WLAN_EID_VENDOR_PRIVATE)) != 0xffff)
+ {
+ pBssInfo->apCap |= ZM_XR_AP;
+ }
+
+ /* get RSN IE */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_RSN_IE)) != 0xffff )
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length > ZM_MAX_IE_SIZE)
+ {
+ length = ZM_MAX_IE_SIZE;
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->rsnIe, offset, length+2);
+ pBssInfo->securityType = ZM_SECURITY_TYPE_WPA;
+ }
+ else
+ {
+ pBssInfo->rsnIe[1] = 0;
+ }
+#ifdef ZM_ENABLE_CENC
+ /* get CENC IE */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CENC_IE)) != 0xffff )
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+ if (length > ZM_MAX_IE_SIZE )
+ {
+ length = ZM_MAX_IE_SIZE;
+ }
+ zfCopyFromRxBuffer(dev, buf, pBssInfo->cencIe, offset, length+2);
+ pBssInfo->securityType = ZM_SECURITY_TYPE_CENC;
+ pBssInfo->capability[0] &= 0xffef;
+ }
+ else
+ {
+ pBssInfo->cencIe[1] = 0;
+ }
+#endif //ZM_ENABLE_CENC
+ /* get WME Parameter IE, probe rsp may contain WME parameter element */
+ //if ( wd->bQoSEnable )
+ {
+ if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff)
+ {
+ apQosInfo = zmw_rx_buf_readb(dev, buf, offset+8) & 0x80;
+ pBssInfo->wmeSupport = 1 | apQosInfo;
+ }
+ else if ((offset = zfFindWifiElement(dev, buf, 2, 0)) != 0xffff)
+ {
+ apQosInfo = zmw_rx_buf_readb(dev, buf, offset+8) & 0x80;
+ pBssInfo->wmeSupport = 1 | apQosInfo;
+ }
+ else
+ {
+ pBssInfo->wmeSupport = 0;
+ }
+ }
+ //CWYang(+)
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff)
+ {
+ /* 11n AP */
+ pBssInfo->EnableHT = 1;
+ if (zmw_rx_buf_readb(dev, buf, offset+1) & 0x02)
+ {
+ pBssInfo->enableHT40 = 1;
+ }
+ else
+ {
+ pBssInfo->enableHT40 = 0;
+ }
+
+ if (zmw_rx_buf_readb(dev, buf, offset+1) & 0x40)
+ {
+ pBssInfo->SG40 = 1;
+ }
+ else
+ {
+ pBssInfo->SG40 = 0;
+ }
+ }
+ else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff)
+ {
+ /* 11n AP */
+ pBssInfo->EnableHT = 1;
+ pBssInfo->apCap |= ZM_All11N_AP;
+ if (zmw_rx_buf_readb(dev, buf, offset+2) & 0x02)
+ {
+ pBssInfo->enableHT40 = 1;
+ }
+ else
+ {
+ pBssInfo->enableHT40 = 0;
+ }
+
+ if (zmw_rx_buf_readb(dev, buf, offset+2) & 0x40)
+ {
+ pBssInfo->SG40 = 1;
+ }
+ else
+ {
+ pBssInfo->SG40 = 0;
+ }
+ }
+ else
+ {
+ pBssInfo->EnableHT = 0;
+ }
+ /* HT information */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)
+ {
+ /* atheros pre n */
+ pBssInfo->extChOffset = zmw_rx_buf_readb(dev, buf, offset+2) & 0x03;
+ }
+ else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTINFORMATION)) != 0xffff)
+ {
+ /* pre n 2.0 standard */
+ pBssInfo->extChOffset = zmw_rx_buf_readb(dev, buf, offset+3) & 0x03;
+ }
+ else
+ {
+ pBssInfo->extChOffset = 0;
+ }
+
+ if ( (pBssInfo->enableHT40 == 1)
+ && ((pBssInfo->extChOffset != 1) && (pBssInfo->extChOffset != 3)) )
+ {
+ pBssInfo->enableHT40 = 0;
+ }
+
+ if (pBssInfo->enableHT40 == 1)
+ {
+ if (zfHpIsAllowedChannel(dev, pBssInfo->frequency+((pBssInfo->extChOffset==1)?20:-20)) == 0)
+ {
+ /* if extension channel is not an allowed channel, treat AP as non-HT mode */
+ pBssInfo->EnableHT = 0;
+ pBssInfo->enableHT40 = 0;
+ pBssInfo->extChOffset = 0;
+ }
+ }
+
+ /* get ATH Extended Capability */
+ if ( ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)&&
+ ((offset = zfFindBrdcmMrvlRlnkExtCap(dev, buf)) == 0xffff))
+
+ {
+ pBssInfo->athOwlAp = 1;
+ }
+ else
+ {
+ pBssInfo->athOwlAp = 0;
+ }
+
+ /* get Broadcom Extended Capability */
+ if ( (pBssInfo->EnableHT == 1) //((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)
+ && ((offset = zfFindBroadcomExtCap(dev, buf)) != 0xffff) )
+ {
+ pBssInfo->broadcomHTAp = 1;
+ }
+ else
+ {
+ pBssInfo->broadcomHTAp = 0;
+ }
+
+ /* get Marvel Extended Capability */
+ if ((offset = zfFindMarvelExtCap(dev, buf)) != 0xffff)
+ {
+ pBssInfo->marvelAp = 1;
+ }
+ else
+ {
+ pBssInfo->marvelAp = 0;
+ }
+
+ /* get ATIM window */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_IBSS)) != 0xffff )
+ {
+ pBssInfo->atimWindow = zmw_rx_buf_readh(dev, buf,offset+2);
+ }
+
+ /* Fit for support mode */
+ if (pBssInfo->frequency > 3000) {
+ if (wd->supportMode & ZM_WIRELESS_MODE_5_N) {
+#if 0
+ if (wd->supportMode & ZM_WIRELESS_MODE_5_54) {
+ /* support mode: a, n */
+ /* do nothing */
+ } else {
+ /* support mode: n */
+ /* reject non-n bss info */
+ if (!pBssInfo->EnableHT) {
+ goto zlError2;
+ }
+ }
+#endif
+ } else {
+ if (wd->supportMode & ZM_WIRELESS_MODE_5_54) {
+ /* support mode: a */
+ /* delete n mode information */
+ pBssInfo->EnableHT = 0;
+ pBssInfo->enableHT40 = 0;
+ pBssInfo->apCap &= (~ZM_All11N_AP);
+ pBssInfo->extChOffset = 0;
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_EID_HT_CAPABILITY);
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTCAPABILITY);
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY);
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTINFORMATION);
+ } else {
+ /* support mode: none */
+ goto zlError2;
+ }
+ }
+ } else {
+ if (wd->supportMode & ZM_WIRELESS_MODE_24_N) {
+#if 0
+ if (wd->supportMode & ZM_WIRELESS_MODE_24_54) {
+ if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
+ /* support mode: b, g, n */
+ /* do nothing */
+ } else {
+ /* support mode: g, n */
+ /* reject b-only bss info */
+ if ( (!pBssInfo->EnableHT)
+ && (pBssInfo->extSupportedRates[1] == 0) ) {
+ goto zlError2;
+ }
+ }
+ } else {
+ if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
+ /* support mode: b, n */
+ /* 1. reject g-only bss info
+ * 2. if non g-only, delete g mode information
+ */
+ if ( !pBssInfo->EnableHT ) {
+ if ( zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->supportedRates)
+ || zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->extSupportedRates) ) {
+ goto zlError2;
+ } else {
+ zfGatherBMode(dev, pBssInfo->supportedRates,
+ pBssInfo->extSupportedRates);
+ pBssInfo->erp = 0;
+
+ pBssInfo->frameBodysize = zfRemoveElement(dev,
+ pBssInfo->frameBody, pBssInfo->frameBodysize,
+ ZM_WLAN_EID_ERP);
+ pBssInfo->frameBodysize = zfRemoveElement(dev,
+ pBssInfo->frameBody, pBssInfo->frameBodysize,
+ ZM_WLAN_EID_EXTENDED_RATE);
+
+ pBssInfo->frameBodysize = zfUpdateElement(dev,
+ pBssInfo->frameBody, pBssInfo->frameBodysize,
+ pBssInfo->supportedRates);
+ }
+ }
+ } else {
+ /* support mode: n */
+ /* reject non-n bss info */
+ if (!pBssInfo->EnableHT) {
+ goto zlError2;
+ }
+ }
+ }
+#endif
+ } else {
+ /* delete n mode information */
+ pBssInfo->EnableHT = 0;
+ pBssInfo->enableHT40 = 0;
+ pBssInfo->apCap &= (~ZM_All11N_AP);
+ pBssInfo->extChOffset = 0;
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_EID_HT_CAPABILITY);
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTCAPABILITY);
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY);
+ pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody,
+ pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTINFORMATION);
+
+ if (wd->supportMode & ZM_WIRELESS_MODE_24_54) {
+#if 0
+ if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
+ /* support mode: b, g */
+ /* delete n mode information */
+ } else {
+ /* support mode: g */
+ /* delete n mode information */
+ /* reject b-only bss info */
+ if (pBssInfo->extSupportedRates[1] == 0) {
+ goto zlError2;
+ }
+ }
+#endif
+ } else {
+ if (wd->supportMode & ZM_WIRELESS_MODE_24_11) {
+ /* support mode: b */
+ /* delete n mode information */
+ if ( zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->supportedRates)
+ || zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->extSupportedRates) ) {
+ goto zlError2;
+ } else {
+ zfGatherBMode(dev, pBssInfo->supportedRates,
+ pBssInfo->extSupportedRates);
+ pBssInfo->erp = 0;
+
+ pBssInfo->frameBodysize = zfRemoveElement(dev,
+ pBssInfo->frameBody, pBssInfo->frameBodysize,
+ ZM_WLAN_EID_ERP);
+ pBssInfo->frameBodysize = zfRemoveElement(dev,
+ pBssInfo->frameBody, pBssInfo->frameBodysize,
+ ZM_WLAN_EID_EXTENDED_RATE);
+
+ pBssInfo->frameBodysize = zfUpdateElement(dev,
+ pBssInfo->frameBody, pBssInfo->frameBodysize,
+ pBssInfo->supportedRates);
+ }
+ } else {
+ /* support mode: none */
+ goto zlError2;
+ }
+ }
+ }
+ }
+
+ pBssInfo->flag |= ZM_BSS_INFO_VALID_BIT;
+
+zlUpdateRssi:
+ /* Update Timer information */
+ pBssInfo->tick = wd->tick;
+
+ /* Update ERP information */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff )
+ {
+ pBssInfo->erp = zmw_rx_buf_readb(dev, buf, offset+2);
+ }
+
+ if( (s8_t)pBssInfo->signalStrength < (s8_t)AddInfo->Tail.Data.SignalStrength1 )
+ {
+ /* Update signal strength */
+ pBssInfo->signalStrength = (u8_t)AddInfo->Tail.Data.SignalStrength1;
+ /* Update signal quality */
+ pBssInfo->signalQuality = (u8_t)(AddInfo->Tail.Data.SignalStrength1 * 2);
+
+ /* Update the sorting value */
+ pBssInfo->sortValue = zfComputeBssInfoWeightValue(dev,
+ (pBssInfo->supportedRates[6] + pBssInfo->extSupportedRates[0]),
+ pBssInfo->EnableHT,
+ pBssInfo->enableHT40,
+ pBssInfo->signalStrength);
+ }
+
+ return 0;
+
+zlError:
+
+ return 1;
+
+zlError2:
+
+ return 2;
+}
+
+void zfStaProcessBeacon(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo) //CWYang(m)
+{
+ /* Parse TIM and send PS-POLL in power saving mode */
+ struct zsWlanBeaconFrameHeader* pBeaconHeader;
+ struct zsBssInfo* pBssInfo;
+ u8_t pBuf[sizeof(struct zsWlanBeaconFrameHeader)];
+ u8_t bssid[6];
+ int res;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ /* sta routine jobs */
+ zfStaProtErpMonitor(dev, buf); /* check protection mode */
+
+ if (zfStaIsConnected(dev))
+ {
+ ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);
+
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ if ( zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6) )
+ {
+ zfPowerSavingMgrProcessBeacon(dev, buf);
+ zfStaUpdateWmeParameter(dev, buf);
+ if (wd->sta.DFSEnable)
+ zfStaUpdateDot11HDFS(dev, buf);
+ if (wd->sta.TPCEnable)
+ zfStaUpdateDot11HTPC(dev, buf);
+ /* update signal strength and signal quality */
+ zfStaSignalStatistic(dev, AddInfo->Tail.Data.SignalStrength1,
+ AddInfo->Tail.Data.SignalQuality); //CWYang(+)
+ wd->sta.rxBeaconCount++;
+ }
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ if ( zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A3_OFFSET, 6) )
+ {
+ int res;
+ struct zsPartnerNotifyEvent event;
+
+ zm_debug_msg0("20070916 Receive opposite Beacon!");
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssReceiveBeaconCount++;
+ zmw_leave_critical_section(dev);
+
+ res = zfStaSetOppositeInfoFromRxBuf(dev, buf);
+ if ( res == 0 )
+ {
+ // New peer station found. Notify the wrapper now
+ zfInitPartnerNotifyEvent(dev, buf, &event);
+ if (wd->zfcbIbssPartnerNotify != NULL)
+ {
+ wd->zfcbIbssPartnerNotify(dev, 1, &event);
+ }
+ }
+ /* update signal strength and signal quality */
+ zfStaSignalStatistic(dev, AddInfo->Tail.Data.SignalStrength1,
+ AddInfo->Tail.Data.SignalQuality); //CWYang(+)
+ }
+ //else if ( wd->sta.ibssPartnerStatus == ZM_IBSS_PARTNER_LOST )
+ // Why does this happen in IBSS?? The impact of Vista since
+ // we need to tell it the BSSID
+#if 0
+ else if ( wd->sta.oppositeCount == 0 )
+ { /* IBSS merge if SSID matched */
+ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) != 0xffff )
+ {
+ if ( (wd->sta.ssidLen == zmw_buf_readb(dev, buf, offset+1))&&
+ (zfRxBufferEqualToStr(dev, buf, wd->sta.ssid,
+ offset+2, wd->sta.ssidLen)) )
+ {
+ capabilityInfo = zmw_buf_readh(dev, buf, 34);
+
+ if ( capabilityInfo & ZM_BIT_1 )
+ {
+ if ( (wd->sta.capability[0] & ZM_BIT_4) ==
+ (capabilityInfo & ZM_BIT_4) )
+ {
+ zm_debug_msg0("IBSS merge");
+ zfCopyFromRxBuffer(dev, buf, bssid,
+ ZM_WLAN_HEADER_A3_OFFSET, 6);
+ zfUpdateBssid(dev, bssid);
+ }
+ }
+ }
+ }
+ }
+#endif
+ }
+ }
+
+ /* return if not channel scan */
+ if ( !wd->sta.bChannelScan )
+ {
+ goto zlReturn;
+ }
+
+ zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanBeaconFrameHeader));
+ pBeaconHeader = (struct zsWlanBeaconFrameHeader*) pBuf;
+
+ zmw_enter_critical_section(dev);
+
+ //zm_debug_msg1("bss count = ", wd->sta.bssList.bssCount);
+
+ pBssInfo = zfStaFindBssInfo(dev, buf, pBeaconHeader);
+
+ if ( pBssInfo == NULL )
+ {
+ /* Allocate a new entry if BSS not in the scan list */
+ pBssInfo = zfBssInfoAllocate(dev);
+ if (pBssInfo != NULL)
+ {
+ res = zfStaInitBssInfo(dev, buf, pBeaconHeader, pBssInfo, AddInfo, 0);
+ //zfDumpSSID(pBssInfo->ssid[1], &(pBssInfo->ssid[2]));
+ if ( res != 0 )
+ {
+ zfBssInfoFree(dev, pBssInfo);
+ }
+ else
+ {
+ zfBssInfoInsertToList(dev, pBssInfo);
+ }
+ }
+ }
+ else
+ {
+ res = zfStaInitBssInfo(dev, buf, pBeaconHeader, pBssInfo, AddInfo, 1);
+ if (res == 2)
+ {
+ zfBssInfoRemoveFromList(dev, pBssInfo);
+ zfBssInfoFree(dev, pBssInfo);
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ int idx;
+
+ // It would reset the alive counter if the peer station is found!
+ zfStaFindFreeOpposite(dev, (u16_t *)pBssInfo->macaddr, &idx);
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+zlReturn:
+
+ return;
+}
+
+
+void zfAuthFreqCompleteCb(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_COMPLETED)
+ {
+ zm_debug_msg0("ZM_STA_CONN_STATE_ASSOCIATE");
+ wd->sta.connectTimer = wd->tick;
+ wd->sta.connectState = ZM_STA_CONN_STATE_ASSOCIATE;
+ }
+
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfProcessAuth */
+/* Process authenticate management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : auth frame buffer */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+/* Note : AP allows one authenticating STA at a time, does not */
+/* support multiple authentication process. Make sure */
+/* authentication state machine will not be blocked due */
+/* to incompleted authentication handshake. */
+void zfStaProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
+{
+ struct zsWlanAuthFrameHeader* pAuthFrame;
+ u8_t pBuf[sizeof(struct zsWlanAuthFrameHeader)];
+ u32_t p1, p2;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ if ( !zfStaIsConnecting(dev) )
+ {
+ return;
+ }
+
+ pAuthFrame = (struct zsWlanAuthFrameHeader*) pBuf;
+ zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanAuthFrameHeader));
+
+ if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_OPEN )
+ {
+ if ( (zmw_le16_to_cpu(pAuthFrame->seq) == 2)&&
+ (zmw_le16_to_cpu(pAuthFrame->algo) == 0)&&
+ (zmw_le16_to_cpu(pAuthFrame->status) == 0) )
+ {
+
+ zmw_enter_critical_section(dev);
+ wd->sta.connectTimer = wd->tick;
+ zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_COMPLETED");
+ wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_COMPLETED;
+ zmw_leave_critical_section(dev);
+
+ //Set channel according to AP's configuration
+ //Move to here because of Cisco 11n AP feature
+ zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
+ wd->ExtOffset, zfAuthFreqCompleteCb);
+
+ /* send association frame */
+ if ( wd->sta.connectByReasso )
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_REASOCREQ,
+ wd->sta.bssid, 0, 0, 0);
+ }
+ else
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCREQ,
+ wd->sta.bssid, 0, 0, 0);
+ }
+
+
+ }
+ else
+ {
+ zm_debug_msg1("authentication failed, status = ",
+ pAuthFrame->status);
+
+ if (wd->sta.authMode == ZM_AUTH_MODE_AUTO)
+ {
+ wd->sta.bIsSharedKey = 1;
+ zfStaStartConnect(dev, wd->sta.bIsSharedKey);
+ }
+ else
+ {
+ zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
+ }
+ }
+ }
+ else if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_1 )
+ {
+ if ( (zmw_le16_to_cpu(pAuthFrame->algo) == 1) &&
+ (zmw_le16_to_cpu(pAuthFrame->seq) == 2) &&
+ (zmw_le16_to_cpu(pAuthFrame->status) == 0))
+ //&& (pAuthFrame->challengeText[1] <= 255) )
+ {
+ zfMemoryCopy(wd->sta.challengeText, pAuthFrame->challengeText,
+ pAuthFrame->challengeText[1]+2);
+
+ /* send the 3rd authentication frame */
+ p1 = 0x30001;
+ p2 = 0;
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH,
+ wd->sta.bssid, p1, p2, 0);
+
+ zmw_enter_critical_section(dev);
+ wd->sta.connectTimer = wd->tick;
+
+ zm_debug_msg0("ZM_STA_SUB_STATE_AUTH_SHARE_2");
+ wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_SHARE_2;
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zm_debug_msg1("authentication failed, status = ",
+ pAuthFrame->status);
+
+ zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
+ }
+ }
+ else if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_2 )
+ {
+ if ( (zmw_le16_to_cpu(pAuthFrame->algo) == 1)&&
+ (zmw_le16_to_cpu(pAuthFrame->seq) == 4)&&
+ (zmw_le16_to_cpu(pAuthFrame->status) == 0) )
+ {
+ //Set channel according to AP's configuration
+ //Move to here because of Cisco 11n AP feature
+ zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
+ wd->ExtOffset, NULL);
+
+ /* send association frame */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCREQ,
+ wd->sta.bssid, 0, 0, 0);
+
+ zmw_enter_critical_section(dev);
+ wd->sta.connectTimer = wd->tick;
+
+ zm_debug_msg0("ZM_STA_SUB_STATE_ASSOCIATE");
+ wd->sta.connectState = ZM_STA_CONN_STATE_ASSOCIATE;
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zm_debug_msg1("authentication failed, status = ",
+ pAuthFrame->status);
+
+ zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
+ }
+ }
+ else
+ {
+ zm_debug_msg0("unknown case");
+ }
+}
+
+void zfStaProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId)
+{
+
+ return;
+}
+
+void zfStaProcessAsocRsp(zdev_t* dev, zbuf_t* buf)
+{
+ struct zsWlanAssoFrameHeader* pAssoFrame;
+ u8_t pBuf[sizeof(struct zsWlanAssoFrameHeader)];
+ u16_t offset;
+ u32_t i;
+ u32_t oneTxStreamCap;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( !zfStaIsConnecting(dev) )
+ {
+ return;
+ }
+
+ pAssoFrame = (struct zsWlanAssoFrameHeader*) pBuf;
+ zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanAssoFrameHeader));
+
+ if ( wd->sta.connectState == ZM_STA_CONN_STATE_ASSOCIATE )
+ {
+ if ( pAssoFrame->status == 0 )
+ {
+ zm_debug_msg0("ZM_STA_STATE_CONNECTED");
+
+ if (wd->sta.EnableHT == 1)
+ {
+ wd->sta.wmeConnected = 1;
+ }
+ if ((wd->sta.wmeEnabled & ZM_STA_WME_ENABLE_BIT) != 0) //WME enabled
+ {
+ /* Asoc rsp may contain WME parameter element */
+ if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff)
+ {
+ zm_debug_msg0("WME enable");
+ wd->sta.wmeConnected = 1;
+ if ((wd->sta.wmeEnabled & ZM_STA_UAPSD_ENABLE_BIT) != 0)
+ {
+ if ((zmw_rx_buf_readb(dev, buf, offset+8) & 0x80) != 0)
+ {
+ zm_debug_msg0("UAPSD enable");
+ wd->sta.qosInfo = wd->sta.wmeQosInfo;
+ }
+ }
+
+ zfStaUpdateWmeParameter(dev, buf);
+ }
+ }
+
+
+ //Store asoc response frame body, for VISTA only
+ wd->sta.asocRspFrameBodySize = zfwBufGetSize(dev, buf)-24;
+ if (wd->sta.asocRspFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
+ {
+ wd->sta.asocRspFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
+ }
+ for (i=0; i<wd->sta.asocRspFrameBodySize; i++)
+ {
+ wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24);
+ }
+
+ zfStaStoreAsocRspIe(dev, buf);
+ if (wd->sta.EnableHT &&
+ ((wd->sta.ie.HtCap.HtCapInfo & HTCAP_SupChannelWidthSet) != 0) &&
+ (wd->ExtOffset != 0))
+ {
+ wd->sta.htCtrlBandwidth = 1;
+ }
+ else
+ {
+ wd->sta.htCtrlBandwidth = 0;
+ }
+
+ //Set channel according to AP's configuration
+ //zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
+ // wd->ExtOffset, NULL);
+
+ if (wd->sta.EnableHT == 1)
+ {
+ wd->addbaComplete = 0;
+
+ if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_ENCRY_EN) == 0 &&
+ (wd->sta.SWEncryptEnable & ZM_SW_WEP_ENCRY_EN) == 0)
+ {
+ wd->addbaCount = 1;
+ zfAggSendAddbaRequest(dev, wd->sta.bssid, 0, 0);
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_ADDBA, 100);
+ }
+ }
+
+ /* set RIFS support */
+ if(wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_RIFSMode)
+ {
+ wd->sta.HT2040 = 1;
+// zfHpSetRifs(dev, wd->sta.EnableHT, 1, (wd->sta.currentFrequency < 3000)? 1:0);
+ }
+
+ wd->sta.aid = pAssoFrame->aid & 0x3fff;
+ wd->sta.oppositeCount = 0; /* reset opposite count */
+ zfStaSetOppositeInfoFromRxBuf(dev, buf);
+
+ wd->sta.rxBeaconCount = 16;
+
+ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED);
+ wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ if (wd->sta.EnableHT != 0) /* 11n */
+ {
+ oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM);
+ if (wd->sta.htCtrlBandwidth == 1) /* HT40*/
+ {
+ if(oneTxStreamCap) /* one Tx stream */
+ {
+ if (wd->sta.SG40)
+ {
+ wd->CurrentTxRateKbps = 150000;
+ wd->CurrentRxRateKbps = 300000;
+ }
+ else
+ {
+ wd->CurrentTxRateKbps = 135000;
+ wd->CurrentRxRateKbps = 270000;
+ }
+ }
+ else /* Two Tx streams */
+ {
+ if (wd->sta.SG40)
+ {
+ wd->CurrentTxRateKbps = 300000;
+ wd->CurrentRxRateKbps = 300000;
+ }
+ else
+ {
+ wd->CurrentTxRateKbps = 270000;
+ wd->CurrentRxRateKbps = 270000;
+ }
+ }
+ }
+ else /* HT20 */
+ {
+ if(oneTxStreamCap) /* one Tx stream */
+ {
+ wd->CurrentTxRateKbps = 650000;
+ wd->CurrentRxRateKbps = 130000;
+ }
+ else /* Two Tx streams */
+ {
+ wd->CurrentTxRateKbps = 130000;
+ wd->CurrentRxRateKbps = 130000;
+ }
+ }
+ }
+ else /* 11abg */
+ {
+ if (wd->sta.connection_11b != 0)
+ {
+ wd->CurrentTxRateKbps = 11000;
+ wd->CurrentRxRateKbps = 11000;
+ }
+ else
+ {
+ wd->CurrentTxRateKbps = 54000;
+ wd->CurrentRxRateKbps = 54000;
+ }
+ }
+
+
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid);
+ }
+ wd->sta.connectByReasso = TRUE;
+ wd->sta.failCntOfReasso = 0;
+
+ zfPowerSavingMgrConnectNotify(dev);
+
+ /* Disable here because fixed rate is only for test, TBD. */
+ //if (wd->sta.EnableHT)
+ //{
+ // wd->txMCS = 7; //Rate = 65Mbps
+ // wd->txMT = 2; // Ht rate
+ // wd->enableAggregation = 2; // Enable Aggregation
+ //}
+ }
+ else
+ {
+ zm_debug_msg1("association failed, status = ",
+ pAssoFrame->status);
+
+ zm_debug_msg0("ZM_STA_STATE_DISCONNECT");
+ wd->sta.connectByReasso = FALSE;
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_ASOC_FAILED, wd->sta.bssid, 3);
+ }
+ }
+
+}
+
+void zfStaStoreAsocRspIe(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t offset;
+ u32_t i;
+ u16_t length;
+ u8_t *htcap;
+ u8_t asocBw40 = 0;
+ u8_t asocExtOffset = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<wd->sta.asocRspFrameBodySize; i++)
+ {
+ wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24);
+ }
+
+ /* HT capabilities: 28 octets */
+ if ( ((wd->sta.currentFrequency > 3000) && !(wd->supportMode & ZM_WIRELESS_MODE_5_N))
+ || ((wd->sta.currentFrequency < 3000) && !(wd->supportMode & ZM_WIRELESS_MODE_24_N)) )
+ {
+ /* not 11n AP */
+ htcap = (u8_t *)&wd->sta.ie.HtCap;
+ for (i=0; i<28; i++)
+ {
+ htcap[i] = 0;
+ }
+ wd->BandWidth40 = 0;
+ wd->ExtOffset = 0;
+ return;
+ }
+
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff)
+ {
+ /* atheros pre n */
+ zm_debug_msg0("atheros pre n");
+ htcap = (u8_t *)&wd->sta.ie.HtCap;
+ htcap[0] = zmw_rx_buf_readb(dev, buf, offset);
+ htcap[1] = 26;
+ for (i=1; i<=26; i++)
+ {
+ htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i);
+ zm_msg2_mm(ZM_LV_1, "ASOC: HT Capabilities, htcap=", htcap[i+1]);
+ }
+ }
+ else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff)
+ {
+ /* pre n 2.0 standard */
+ zm_debug_msg0("pre n 2.0 standard");
+ htcap = (u8_t *)&wd->sta.ie.HtCap;
+ for (i=0; i<28; i++)
+ {
+ htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i);
+ zm_msg2_mm(ZM_LV_1, "ASOC: HT Capabilities, htcap=", htcap[i]);
+ }
+ }
+ else
+ {
+ /* not 11n AP */
+ htcap = (u8_t *)&wd->sta.ie.HtCap;
+ for (i=0; i<28; i++)
+ {
+ htcap[i] = 0;
+ }
+ wd->BandWidth40 = 0;
+ wd->ExtOffset = 0;
+ return;
+ }
+
+ asocBw40 = (u8_t)((wd->sta.ie.HtCap.HtCapInfo & HTCAP_SupChannelWidthSet) >> 1);
+
+ /* HT information */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)
+ {
+ /* atheros pre n */
+ zm_debug_msg0("atheros pre n HTINFO");
+ length = 22;
+ htcap = (u8_t *)&wd->sta.ie.HtInfo;
+ htcap[0] = zmw_rx_buf_readb(dev, buf, offset);
+ htcap[1] = 22;
+ for (i=1; i<=22; i++)
+ {
+ htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i);
+ zm_msg2_mm(ZM_LV_1, "ASOC: HT Info, htinfo=", htcap[i+1]);
+ }
+ }
+ else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTINFORMATION)) != 0xffff)
+ {
+ /* pre n 2.0 standard */
+ zm_debug_msg0("pre n 2.0 standard HTINFO");
+ length = zmw_rx_buf_readb(dev, buf, offset + 1);
+ htcap = (u8_t *)&wd->sta.ie.HtInfo;
+ for (i=0; i<24; i++)
+ {
+ htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i);
+ zm_msg2_mm(ZM_LV_1, "ASOC: HT Info, htinfo=", htcap[i]);
+ }
+ }
+ else
+ {
+ zm_debug_msg0("no HTINFO");
+ htcap = (u8_t *)&wd->sta.ie.HtInfo;
+ for (i=0; i<24; i++)
+ {
+ htcap[i] = 0;
+ }
+ }
+ asocExtOffset = wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_ExtChannelOffsetBelow;
+
+ if ((wd->sta.EnableHT == 1) && (asocBw40 == 1) && ((asocExtOffset == 1) || (asocExtOffset == 3)))
+ {
+ wd->BandWidth40 = asocBw40;
+ wd->ExtOffset = asocExtOffset;
+ }
+ else
+ {
+ wd->BandWidth40 = 0;
+ wd->ExtOffset = 0;
+ }
+
+ return;
+}
+
+void zfStaProcessDeauth(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t apMacAddr[3];
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ /* STA : if SA=connected AP then disconnect with AP */
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ apMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
+ apMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
+ apMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
+ if ((apMacAddr[0] == wd->sta.bssid[0]) && (apMacAddr[1] == wd->sta.bssid[1]) && (apMacAddr[2] == wd->sta.bssid[2]))
+ {
+ if (zfwBufGetSize(dev, buf) >= 24+2) //not a malformed frame
+ {
+ if ( zfStaIsConnected(dev) )
+ {
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_DEAUTH, wd->sta.bssid, 2);
+ }
+ else if (zfStaIsConnecting(dev))
+ {
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3);
+ }
+ else
+ {
+ }
+ }
+ }
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ u16_t peerMacAddr[3];
+ u8_t peerIdx;
+ s8_t res;
+
+ if ( zfStaIsConnected(dev) )
+ {
+ peerMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
+ peerMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2);
+ peerMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4);
+
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, peerMacAddr, &peerIdx);
+ if ( res == 0 )
+ {
+ wd->sta.oppositeInfo[peerIdx].aliveCounter = 0;
+ }
+ zmw_leave_critical_section(dev);
+ }
+ }
+}
+
+void zfStaProcessDisasoc(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t apMacAddr[3];
+
+ zmw_get_wlan_dev(dev);
+
+ /* STA : if SA=connected AP then disconnect with AP */
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ apMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
+ apMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
+ apMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
+
+ if ((apMacAddr[0] == wd->sta.bssid[0]) && (apMacAddr[1] == wd->sta.bssid[1]) && (apMacAddr[2] == wd->sta.bssid[2]))
+ {
+ if (zfwBufGetSize(dev, buf) >= 24+2) //not a malformed frame
+ {
+ if ( zfStaIsConnected(dev) )
+ {
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_DISASOC, wd->sta.bssid, 2);
+ }
+ else
+ {
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_ASOC_FAILED, wd->sta.bssid, 3);
+ }
+ }
+ }
+ }
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfProcessProbeReq */
+/* Process probe request management frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : auth frame buffer */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+void zfStaProcessProbeReq(zdev_t* dev, zbuf_t* buf, u16_t* src)
+{
+ u16_t offset;
+ u8_t len;
+ u16_t i, j;
+ u16_t sendFlag;
+
+ zmw_get_wlan_dev(dev);
+
+ /* check mode : AP/IBSS */
+ if ((wd->wlanMode != ZM_MODE_AP) || (wd->wlanMode != ZM_MODE_IBSS))
+ {
+ zm_msg0_mm(ZM_LV_3, "Ignore probe req");
+ return;
+ }
+
+ /* check SSID */
+ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) == 0xffff)
+ {
+ zm_msg0_mm(ZM_LV_3, "probe req SSID not found");
+ return;
+ }
+
+ len = zmw_rx_buf_readb(dev, buf, offset+1);
+
+ for (i=0; i<ZM_MAX_AP_SUPPORT; i++)
+ {
+ if ((wd->ap.apBitmap & (i<<i)) != 0)
+ {
+ sendFlag = 0;
+ /* boardcast SSID */
+ if ((len == 0) && (wd->ap.hideSsid[i] == 0))
+ {
+ sendFlag = 1;
+ }
+ /* Not broadcast SSID */
+ else if (wd->ap.ssidLen[i] == len)
+ {
+ for (j=0; j<len; j++)
+ {
+ if (zmw_rx_buf_readb(dev, buf, offset+1+j)
+ != wd->ap.ssid[i][j])
+ {
+ break;
+ }
+ }
+ if (j == len)
+ {
+ sendFlag = 1;
+ }
+ }
+ if (sendFlag == 1)
+ {
+ /* Send probe response */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBERSP, src, i, 0, 0);
+ }
+ }
+ }
+}
+
+void zfStaProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo)
+{
+ /* return if not channel scan */
+ // Probe response is sent with unicast. Is this required?
+ // IBSS would send probe request and the code below would prevent
+ // the probe response from handling.
+ #if 0
+ zmw_get_wlan_dev(dev);
+
+ if ( !wd->sta.bChannelScan )
+ {
+ return;
+ }
+ #endif
+
+ zfProcessProbeRsp(dev, buf, AddInfo);
+}
+
+void zfIBSSSetupBssDesc(zdev_t *dev)
+{
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ u8_t i;
+#endif
+ struct zsBssInfo *pBssInfo;
+ u16_t offset = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ pBssInfo = &wd->sta.ibssBssDesc;
+ zfZeroMemory((u8_t *)pBssInfo, sizeof(struct zsBssInfo));
+
+ pBssInfo->signalStrength = 100;
+
+ zfMemoryCopy((u8_t *)pBssInfo->macaddr, (u8_t *)wd->macAddr,6);
+ zfMemoryCopy((u8_t *)pBssInfo->bssid, (u8_t *)wd->sta.bssid, 6);
+
+ pBssInfo->beaconInterval[0] = (u8_t)(wd->beaconInterval) ;
+ pBssInfo->beaconInterval[1] = (u8_t)((wd->beaconInterval) >> 8) ;
+
+ pBssInfo->capability[0] = wd->sta.capability[0];
+ pBssInfo->capability[1] = wd->sta.capability[1];
+
+ pBssInfo->ssid[0] = ZM_WLAN_EID_SSID;
+ pBssInfo->ssid[1] = wd->sta.ssidLen;
+ zfMemoryCopy((u8_t *)&pBssInfo->ssid[2], (u8_t *)wd->sta.ssid, wd->sta.ssidLen);
+ zfMemoryCopy((u8_t *)&pBssInfo->frameBody[offset], (u8_t *)pBssInfo->ssid,
+ wd->sta.ssidLen + 2);
+ offset += wd->sta.ssidLen + 2;
+
+ /* support rate */
+
+ /* DS parameter set */
+ pBssInfo->channel = zfChFreqToNum(wd->frequency, NULL);
+ pBssInfo->frequency = wd->frequency;
+ pBssInfo->atimWindow = wd->sta.atimWindow;
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
+ {
+ u8_t rsn[64]=
+ {
+ /* Element ID */
+ 0x30,
+ /* Length */
+ 0x14,
+ /* Version */
+ 0x01, 0x00,
+ /* Group Cipher Suite, default=TKIP */
+ 0x00, 0x0f, 0xac, 0x04,
+ /* Pairwise Cipher Suite Count */
+ 0x01, 0x00,
+ /* Pairwise Cipher Suite, default=TKIP */
+ 0x00, 0x0f, 0xac, 0x02,
+ /* Authentication and Key Management Suite Count */
+ 0x01, 0x00,
+ /* Authentication type, default=PSK */
+ 0x00, 0x0f, 0xac, 0x02,
+ /* RSN capability */
+ 0x00, 0x00
+ };
+
+ /* Overwrite Group Cipher Suite by AP's setting */
+ zfMemoryCopy(rsn+4, zgWpa2AesOui, 4);
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ /* Overwrite Pairwise Cipher Suite by AES */
+ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
+ }
+
+ // RSN element id
+ pBssInfo->frameBody[offset++] = ZM_WLAN_EID_RSN_IE ;
+
+ // RSN length
+ pBssInfo->frameBody[offset++] = rsn[1] ;
+
+ // RSN information
+ for(i=0; i<rsn[1]; i++)
+ {
+ pBssInfo->frameBody[offset++] = rsn[i+2] ;
+ }
+
+ zfMemoryCopy(pBssInfo->rsnIe, rsn, rsn[1]+2);
+ }
+#endif
+}
+
+void zfIbssConnectNetwork(zdev_t* dev)
+{
+ struct zsBssInfo* pBssInfo;
+ struct zsBssInfo tmpBssInfo;
+ u8_t macAddr[6], bssid[6], bssNotFound = TRUE;
+ u16_t i, j=100;
+ u16_t k;
+ struct zsPartnerNotifyEvent event;
+ u32_t channelFlags;
+ u16_t oppositeWepStatus;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ /* change state to CONNECTING and stop the channel scanning */
+ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING);
+ zfPowerSavingMgrWakeup(dev);
+
+ /* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME STA default. */
+ zfUpdateDefaultQosParameter(dev, 0);
+
+ wd->sta.bProtectionMode = FALSE;
+ zfHpSetSlotTime(dev, 1);
+
+ /* ESS bit off */
+ wd->sta.capability[0] &= ~ZM_BIT_0;
+ /* IBSS bit on */
+ wd->sta.capability[0] |= ZM_BIT_1;
+ /* not not use short slot time */
+ wd->sta.capability[1] &= ~ZM_BIT_2;
+
+ wd->sta.wmeConnected = 0;
+ wd->sta.psMgr.tempWakeUp = 0;
+ wd->sta.qosInfo = 0;
+ wd->sta.EnableHT = 0;
+ wd->BandWidth40 = 0;
+ wd->ExtOffset = 0;
+
+ if ( wd->sta.bssList.bssCount )
+ {
+ //Reorder BssList by RSSI--CWYang(+)
+ zfBssInfoReorderList(dev);
+
+ zmw_enter_critical_section(dev);
+
+ pBssInfo = wd->sta.bssList.head;
+
+ for(i=0; i<wd->sta.bssList.bssCount; i++)
+ {
+ // 20070806 #1 Privacy bit
+ if ( pBssInfo->capability[0] & ZM_BIT_4 )
+ { // Privacy Ibss network
+// zm_debug_msg0("Privacy bit on");
+ oppositeWepStatus = ZM_ENCRYPTION_WEP_ENABLED;
+
+ if ( pBssInfo->rsnIe[1] != 0 )
+ {
+ if ( (pBssInfo->rsnIe[7] == 0x01) || (pBssInfo->rsnIe[7] == 0x05) )
+ { // WEP-40 & WEP-104
+// zm_debug_msg0("WEP40 or WEP104");
+ oppositeWepStatus = ZM_ENCRYPTION_WEP_ENABLED;
+ }
+ else if ( pBssInfo->rsnIe[7] == 0x02 )
+ { // TKIP
+// zm_debug_msg0("TKIP");
+ oppositeWepStatus = ZM_ENCRYPTION_TKIP;
+ }
+ else if ( pBssInfo->rsnIe[7] == 0x04 )
+ { // AES
+// zm_debug_msg0("CCMP-AES");
+ oppositeWepStatus = ZM_ENCRYPTION_AES;
+ }
+ }
+ }
+ else
+ {
+// zm_debug_msg0("Privacy bit off");
+ oppositeWepStatus = ZM_ENCRYPTION_WEP_DISABLED;
+ }
+
+ if ( (zfMemoryIsEqual(&(pBssInfo->ssid[2]), wd->sta.ssid,
+ wd->sta.ssidLen))&&
+ (wd->sta.ssidLen == pBssInfo->ssid[1])&&
+ (oppositeWepStatus == wd->sta.wepStatus) )
+ {
+ /* Check support mode */
+ if (pBssInfo->frequency > 3000) {
+ if ( (pBssInfo->EnableHT == 1)
+ || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
+ {
+ channelFlags = CHANNEL_A_HT;
+ if (pBssInfo->enableHT40 == 1) {
+ channelFlags |= CHANNEL_HT40;
+ }
+ } else {
+ channelFlags = CHANNEL_A;
+ }
+ } else {
+ if ( (pBssInfo->EnableHT == 1)
+ || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
+ {
+ channelFlags = CHANNEL_G_HT;
+ if(pBssInfo->enableHT40 == 1) {
+ channelFlags |= CHANNEL_HT40;
+ }
+ } else {
+ if (pBssInfo->extSupportedRates[1] == 0) {
+ channelFlags = CHANNEL_B;
+ } else {
+ channelFlags = CHANNEL_G;
+ }
+ }
+ }
+
+ if ( ((channelFlags == CHANNEL_B) && (wd->connectMode & ZM_BIT_0))
+ || ((channelFlags == CHANNEL_G) && (wd->connectMode & ZM_BIT_1))
+ || ((channelFlags == CHANNEL_A) && (wd->connectMode & ZM_BIT_2))
+ || ((channelFlags & CHANNEL_HT20) && (wd->connectMode & ZM_BIT_3)) )
+ {
+ pBssInfo = pBssInfo->next;
+ continue;
+ }
+
+ /* Bypass DFS channel */
+ if (zfHpIsDfsChannelNCS(dev, pBssInfo->frequency))
+ {
+ zm_debug_msg0("Bypass DFS channel");
+ continue;
+ }
+
+ /* check IBSS bit */
+ if ( pBssInfo->capability[0] & ZM_BIT_1 )
+ {
+ /* may check timestamp here */
+ j = i;
+ break;
+ }
+ }
+
+ pBssInfo = pBssInfo->next;
+ }
+
+ if ((j < wd->sta.bssList.bssCount) && (pBssInfo != NULL))
+ {
+ zfwMemoryCopy((u8_t*)&tmpBssInfo, (u8_t*)(pBssInfo), sizeof(struct zsBssInfo));
+ pBssInfo = &tmpBssInfo;
+ }
+ else
+ {
+ pBssInfo = NULL;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ //if ( j < wd->sta.bssList.bssCount )
+ if (pBssInfo != NULL)
+ {
+ int res;
+
+ zm_debug_msg0("IBSS found");
+
+ /* Found IBSS, reset bssNotFoundCount */
+ zmw_enter_critical_section(dev);
+ wd->sta.bssNotFoundCount = 0;
+ zmw_leave_critical_section(dev);
+
+ bssNotFound = FALSE;
+ wd->sta.atimWindow = pBssInfo->atimWindow;
+ wd->frequency = pBssInfo->frequency;
+ //wd->sta.flagFreqChanging = 1;
+ zfCoreSetFrequency(dev, wd->frequency);
+ zfUpdateBssid(dev, pBssInfo->bssid);
+ zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_ZERO);
+ zfUpdateSupportRate(dev, pBssInfo->supportedRates);
+ zfUpdateSupportRate(dev, pBssInfo->extSupportedRates);
+ wd->beaconInterval = pBssInfo->beaconInterval[0] +
+ (((u16_t) pBssInfo->beaconInterval[1]) << 8);
+
+ if (wd->beaconInterval == 0)
+ {
+ wd->beaconInterval = 100;
+ }
+
+ /* rsn information element */
+ if ( pBssInfo->rsnIe[1] != 0 )
+ {
+ zfMemoryCopy(wd->sta.rsnIe, pBssInfo->rsnIe,
+ pBssInfo->rsnIe[1]+2);
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ /* If not use RSNA , run traditional */
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssWpa2Psk = 1;
+ zmw_leave_critical_section(dev);
+#endif
+ }
+ else
+ {
+ wd->sta.rsnIe[1] = 0;
+ }
+
+ /* privacy bit */
+ if ( pBssInfo->capability[0] & ZM_BIT_4 )
+ {
+ wd->sta.capability[0] |= ZM_BIT_4;
+ }
+ else
+ {
+ wd->sta.capability[0] &= ~ZM_BIT_4;
+ }
+
+ /* preamble type */
+ wd->preambleTypeInUsed = wd->preambleType;
+ if ( wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_AUTO )
+ {
+ if (pBssInfo->capability[0] & ZM_BIT_5)
+ {
+ wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT;
+ }
+ else
+ {
+ wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_LONG;
+ }
+ }
+
+ if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG)
+ {
+ wd->sta.capability[0] &= ~ZM_BIT_5;
+ }
+ else
+ {
+ wd->sta.capability[0] |= ZM_BIT_5;
+ }
+
+ wd->sta.beaconFrameBodySize = pBssInfo->frameBodysize + 12;
+
+ if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
+ {
+ wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
+ }
+
+ for (k=0; k<8; k++)
+ {
+ wd->sta.beaconFrameBody[k] = pBssInfo->timeStamp[k];
+ }
+ wd->sta.beaconFrameBody[8] = pBssInfo->beaconInterval[0];
+ wd->sta.beaconFrameBody[9] = pBssInfo->beaconInterval[1];
+ wd->sta.beaconFrameBody[10] = pBssInfo->capability[0];
+ wd->sta.beaconFrameBody[11] = pBssInfo->capability[1];
+ //for (k=12; k<wd->sta.beaconFrameBodySize; k++)
+ for (k=0; k<pBssInfo->frameBodysize; k++)
+ {
+ wd->sta.beaconFrameBody[k+12] = pBssInfo->frameBody[k];
+ }
+
+ zmw_enter_critical_section(dev);
+ res = zfStaSetOppositeInfoFromBSSInfo(dev, pBssInfo);
+ if ( res == 0 )
+ {
+ zfMemoryCopy(event.bssid, (u8_t *)(pBssInfo->bssid), 6);
+ zfMemoryCopy(event.peerMacAddr, (u8_t *)(pBssInfo->macaddr), 6);
+ }
+ zmw_leave_critical_section(dev);
+
+ //zfwIbssPartnerNotify(dev, 1, &event);
+ goto connect_done;
+ }
+ }
+
+ /* IBSS not found */
+ if ( bssNotFound )
+ {
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ u16_t offset ;
+#endif
+ if ( wd->sta.ibssJoinOnly )
+ {
+ zm_debug_msg0("IBSS join only...retry...");
+ goto retry_ibss;
+ }
+
+ if(wd->sta.bssNotFoundCount<2)
+ {
+ zmw_enter_critical_section(dev);
+ zm_debug_msg1("IBSS not found, do sitesurvey!! bssNotFoundCount=", wd->sta.bssNotFoundCount);
+ wd->sta.bssNotFoundCount++;
+ zmw_leave_critical_section(dev);
+ goto retry_ibss;
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ /* Fail IBSS found, TODO create IBSS */
+ wd->sta.bssNotFoundCount = 0;
+ zmw_leave_critical_section(dev);
+ }
+
+
+ if (zfHpIsDfsChannel(dev, wd->frequency))
+ {
+ wd->frequency = zfHpFindFirstNonDfsChannel(dev, wd->frequency > 3000);
+ }
+
+ if( wd->ws.autoSetFrequency == 0 )
+ { /* Auto set frequency */
+ zm_debug_msg1("Create Ad Hoc Network Band ", wd->ws.adhocMode);
+ wd->frequency = zfFindCleanFrequency(dev, wd->ws.adhocMode);
+ wd->ws.autoSetFrequency = 0xff;
+ }
+ zm_debug_msg1("IBSS not found, created one in channel ", wd->frequency);
+
+ wd->sta.ibssBssIsCreator = 1;
+
+ //wd->sta.flagFreqChanging = 1;
+ zfCoreSetFrequency(dev, wd->frequency);
+ if (wd->sta.bDesiredBssid == TRUE)
+ {
+ for (k=0; k<6; k++)
+ {
+ bssid[k] = wd->sta.desiredBssid[k];
+ }
+ }
+ else
+ {
+ #if 1
+ macAddr[0] = (wd->macAddr[0] & 0xff);
+ macAddr[1] = (wd->macAddr[0] >> 8);
+ macAddr[2] = (wd->macAddr[1] & 0xff);
+ macAddr[3] = (wd->macAddr[1] >> 8);
+ macAddr[4] = (wd->macAddr[2] & 0xff);
+ macAddr[5] = (wd->macAddr[2] >> 8);
+ zfGenerateRandomBSSID(dev, (u8_t *)wd->macAddr, (u8_t *)bssid);
+ #else
+ for (k=0; k<6; k++)
+ {
+ bssid[k] = (u8_t) zfGetRandomNumber(dev, 0);
+ }
+ bssid[0] &= ~ZM_BIT_0;
+ bssid[0] |= ZM_BIT_1;
+ #endif
+ }
+
+ zfUpdateBssid(dev, bssid);
+ //wd->sta.atimWindow = 0x0a;
+
+ /* rate information */
+ if(wd->frequency <= ZM_CH_G_14) // 2.4 GHz b+g
+ {
+ if ( wd->wfc.bIbssGMode
+ && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) )
+ {
+ zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_AG);
+ }
+ else
+ {
+ zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_B);
+ }
+ } else {
+ zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_AG);
+ }
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED )
+ {
+ wd->sta.capability[0] &= ~ZM_BIT_4;
+ }
+ else
+ {
+ wd->sta.capability[0] |= ZM_BIT_4;
+ }
+
+ wd->preambleTypeInUsed = wd->preambleType;
+ if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG)
+ {
+ wd->sta.capability[0] &= ~ZM_BIT_5;
+ }
+ else
+ {
+ wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT;
+ wd->sta.capability[0] |= ZM_BIT_5;
+ }
+
+ zfIBSSSetupBssDesc(dev);
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+
+ // 20070411 Add WPA2PSK information to its IBSS network !!!
+ offset = 0 ;
+
+ /* timestamp */
+ offset += 8 ;
+
+ /* beacon interval */
+ wd->sta.beaconFrameBody[offset++] = (u8_t)(wd->beaconInterval) ;
+ wd->sta.beaconFrameBody[offset++] = (u8_t)((wd->beaconInterval) >> 8) ;
+
+ /* capability information */
+ wd->sta.beaconFrameBody[offset++] = wd->sta.capability[0] ;
+ wd->sta.beaconFrameBody[offset++] = wd->sta.capability[1] ;
+ #if 0
+ /* ssid */
+ // ssid element id
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_SSID ;
+ // ssid length
+ wd->sta.beaconFrameBody[offset++] = wd->sta.ssidLen ;
+ // ssid information
+ for(i=0; i<wd->sta.ssidLen; i++)
+ {
+ wd->sta.beaconFrameBody[offset++] = wd->sta.ssid[i] ;
+ }
+
+ /* support rate */
+ rateSet = ZM_RATE_SET_CCK ;
+ if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) )
+ {
+ offset += 0 ;
+ }
+ else
+ {
+ // support rate element id
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_SUPPORT_RATE ;
+
+ // support rate length
+ lenOffset = offset++;
+
+ // support rate information
+ for (i=0; i<4; i++)
+ {
+ if ((wd->bRate & (0x1<<i)) == (0x1<<i))
+ {
+ wd->sta.beaconFrameBody[offset++] =
+ zg11bRateTbl[i]+((wd->bRateBasic & (0x1<<i))<<(7-i)) ;
+ len++;
+ }
+ }
+
+ // support rate length
+ wd->sta.beaconFrameBody[lenOffset] = len ;
+ }
+
+ /* DS parameter set */
+ // DS parameter set elemet id
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_DS ;
+
+ // DS parameter set length
+ wd->sta.beaconFrameBody[offset++] = 1 ;
+
+ // DS parameter set information
+ wd->sta.beaconFrameBody[offset++] =
+ zfChFreqToNum(wd->frequency, NULL) ;
+
+ /* IBSS parameter set */
+ // IBSS parameter set element id
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_IBSS ;
+
+ // IBSS parameter set length
+ wd->sta.beaconFrameBody[offset++] = 2 ;
+
+ // IBSS parameter set information
+ wd->sta.beaconFrameBody[offset] = wd->sta.atimWindow ;
+ offset += 2 ;
+
+ /* ERP Information and Extended Supported Rates */
+ if ( wd->wfc.bIbssGMode
+ && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) )
+ {
+ /* ERP Information */
+ wd->erpElement = 0;
+ // ERP element id
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_ERP ;
+
+ // ERP length
+ wd->sta.beaconFrameBody[offset++] = 1 ;
+
+ // ERP information
+ wd->sta.beaconFrameBody[offset++] = wd->erpElement ;
+
+ /* Extended Supported Rates */
+ if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) )
+ {
+ offset += 0 ;
+ }
+ else
+ {
+ len = 0 ;
+
+ // Extended Supported Rates element id
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_EXTENDED_RATE ;
+
+ // Extended Supported Rates length
+ lenOffset = offset++ ;
+
+ // Extended Supported Rates information
+ for (i=0; i<8; i++)
+ {
+ if ((wd->gRate & (0x1<<i)) == (0x1<<i))
+ {
+ wd->sta.beaconFrameBody[offset++] =
+ zg11gRateTbl[i]+((wd->gRateBasic & (0x1<<i))<<(7-i));
+ len++;
+ }
+ }
+
+ // extended support rate length
+ wd->sta.beaconFrameBody[lenOffset] = len ;
+ }
+ }
+ #endif
+
+ /* RSN : important information influence the result of creating an IBSS network */
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK )
+ {
+ u8_t frameType = ZM_WLAN_FRAME_TYPE_AUTH ;
+ u8_t rsn[64]=
+ {
+ /* Element ID */
+ 0x30,
+ /* Length */
+ 0x14,
+ /* Version */
+ 0x01, 0x00,
+ /* Group Cipher Suite, default=TKIP */
+ 0x00, 0x0f, 0xac, 0x04,
+ /* Pairwise Cipher Suite Count */
+ 0x01, 0x00,
+ /* Pairwise Cipher Suite, default=TKIP */
+ 0x00, 0x0f, 0xac, 0x02,
+ /* Authentication and Key Management Suite Count */
+ 0x01, 0x00,
+ /* Authentication type, default=PSK */
+ 0x00, 0x0f, 0xac, 0x02,
+ /* RSN capability */
+ 0x00, 0x00
+ };
+
+ /* Overwrite Group Cipher Suite by AP's setting */
+ zfMemoryCopy(rsn+4, zgWpa2AesOui, 4);
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ /* Overwrite Pairwise Cipher Suite by AES */
+ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
+ }
+
+ // RSN element id
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_RSN_IE ;
+
+ // RSN length
+ wd->sta.beaconFrameBody[offset++] = rsn[1] ;
+
+ // RSN information
+ for(i=0; i<rsn[1]; i++)
+ wd->sta.beaconFrameBody[offset++] = rsn[i+2] ;
+
+ zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2);
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ /* If not use RSNA , run traditional */
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssWpa2Psk = 1;
+ zmw_leave_critical_section(dev);
+#endif
+ }
+
+ #if 0
+ /* HT Capabilities Info */
+ {
+ u8_t OUI[3] = { 0x0 , 0x90 , 0x4C } ;
+
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_WPA_IE ;
+
+ wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Data.Length + 4 ;
+
+ for (i = 0; i < 3; i++)
+ {
+ wd->sta.beaconFrameBody[offset++] = OUI[i] ;
+ }
+
+ wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Data.ElementID ;
+
+ for (i = 0; i < 26; i++)
+ {
+ wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Byte[i+2] ;
+ }
+ }
+
+ /* Extended HT Capabilities Info */
+ {
+ u8_t OUI[3] = { 0x0 , 0x90 , 0x4C } ;
+
+ wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_WPA_IE ;
+
+ wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Data.Length + 4 ;
+
+ for (i = 0; i < 3; i++)
+ {
+ wd->sta.beaconFrameBody[offset++] = OUI[i] ;
+ }
+
+ wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Data.ElementID ;
+
+ for (i = 0; i < 22; i++)
+ {
+ wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Byte[i+2] ;
+ }
+ }
+ #endif
+
+ wd->sta.beaconFrameBodySize = offset ;
+
+ if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
+ {
+ wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
+ }
+
+ // 20070416 Let Create IBSS network could enter the zfwIbssPartnerNotify function
+ // bssNotFound = FALSE ;
+
+ printk("The capability info 1 = %02x\n", wd->sta.capability[0]) ;
+ printk("The capability info 2 = %02x\n", wd->sta.capability[1]) ;
+ for(k=0; k<wd->sta.beaconFrameBodySize; k++)
+ {
+ printk("%02x ", wd->sta.beaconFrameBody[k]) ;
+ }
+ #if 0
+ zmw_enter_critical_section(dev);
+ zfMemoryCopy(event.bssid, (u8_t *)bssid, 6);
+ zfMemoryCopy(event.peerMacAddr, (u8_t *)wd->macAddr, 6);
+ zmw_leave_critical_section(dev);
+ #endif
+#endif
+
+ //zmw_enter_critical_section(dev);
+ //wd->sta.ibssPartnerStatus = ZM_IBSS_PARTNER_LOST;
+ //zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ wd->sta.ibssBssIsCreator = 0;
+ }
+
+connect_done:
+ zfHpEnableBeacon(dev, ZM_MODE_IBSS, wd->beaconInterval, wd->dtim, (u8_t)wd->sta.atimWindow);
+ zfStaSendBeacon(dev); // Refresh Beacon content for ZD1211B HalPlus
+ zfHpSetAtimWindow(dev, wd->sta.atimWindow);
+
+ // Start the IBSS timer to monitor for new stations
+ zmw_enter_critical_section(dev);
+ zfTimerSchedule(dev, ZM_EVENT_IBSS_MONITOR, ZM_TICK_IBSS_MONITOR);
+ zmw_leave_critical_section(dev);
+
+
+ if (wd->zfcbConnectNotify != NULL)
+ {
+ wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid);
+ }
+ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED);
+ wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
+
+#ifdef ZM_ENABLE_IBSS_DELAYED_JOIN_INDICATION
+ if ( !bssNotFound )
+ {
+ wd->sta.ibssDelayedInd = 1;
+ zfMemoryCopy((u8_t *)&wd->sta.ibssDelayedIndEvent, (u8_t *)&event, sizeof(struct zsPartnerNotifyEvent));
+ }
+#else
+ if ( !bssNotFound )
+ {
+ if (wd->zfcbIbssPartnerNotify != NULL)
+ {
+ wd->zfcbIbssPartnerNotify(dev, 1, &event);
+ }
+ }
+#endif
+
+ return;
+
+retry_ibss:
+ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING);
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND, wd->sta.bssid, 0);
+ return;
+}
+
+void zfStaProcessAtim(zdev_t* dev, zbuf_t* buf)
+{
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg0("Receiving Atim window notification");
+
+ wd->sta.recvAtim = 1;
+}
+
+static struct zsBssInfo* zfInfraFindAPToConnect(zdev_t* dev,
+ struct zsBssInfo* candidateBss)
+{
+ struct zsBssInfo* pBssInfo;
+ struct zsBssInfo* pNowBssInfo=NULL;
+ u16_t i;
+ u16_t ret, apWepStatus;
+ u32_t k;
+ u32_t channelFlags;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ pBssInfo = wd->sta.bssList.head;
+
+ for(i=0; i<wd->sta.bssList.bssCount; i++)
+ {
+ if ( pBssInfo->capability[0] & ZM_BIT_4 )
+ {
+ apWepStatus = ZM_ENCRYPTION_WEP_ENABLED;
+ }
+ else
+ {
+ apWepStatus = ZM_ENCRYPTION_WEP_DISABLED;
+ }
+
+ if ( ((zfMemoryIsEqual(&(pBssInfo->ssid[2]), wd->sta.ssid,
+ wd->sta.ssidLen))&&
+ (wd->sta.ssidLen == pBssInfo->ssid[1]))||
+ ((wd->sta.ssidLen == 0)&&
+ /* connect to any BSS: AP's ans STA's WEP status must match */
+ (wd->sta.wepStatus == apWepStatus )&&
+ (pBssInfo->securityType != ZM_SECURITY_TYPE_WPA) ))
+ {
+ if ( wd->sta.ssidLen == 0 )
+ {
+ zm_debug_msg0("ANY BSS found");
+ }
+
+ if ( ((wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED && apWepStatus == ZM_ENCRYPTION_WEP_ENABLED) ||
+ (wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED &&
+ (apWepStatus == ZM_ENCRYPTION_WEP_DISABLED && wd->sta.dropUnencryptedPkts == 1))) &&
+ (wd->sta.authMode >= ZM_AUTH_MODE_OPEN && wd->sta.authMode <= ZM_AUTH_MODE_AUTO) )
+ {
+ zm_debug_msg0("Privacy policy is inconsistent");
+ pBssInfo = pBssInfo->next;
+ continue;
+ }
+
+ /* for WPA negative test */
+ if ( !zfCheckAuthentication(dev, pBssInfo) )
+ {
+ pBssInfo = pBssInfo->next;
+ continue;
+ }
+
+ /* Check bssid */
+ if (wd->sta.bDesiredBssid == TRUE)
+ {
+ for (k=0; k<6; k++)
+ {
+ if (wd->sta.desiredBssid[k] != pBssInfo->bssid[k])
+ {
+ zm_msg0_mm(ZM_LV_1, "desired bssid not matched 1");
+ break;
+ }
+ }
+
+ if (k != 6)
+ {
+ zm_msg0_mm(ZM_LV_1, "desired bssid not matched 2");
+ pBssInfo = pBssInfo->next;
+ continue;
+ }
+ }
+
+ /* Check support mode */
+ if (pBssInfo->frequency > 3000) {
+ if ( (pBssInfo->EnableHT == 1)
+ || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
+ {
+ channelFlags = CHANNEL_A_HT;
+ if (pBssInfo->enableHT40 == 1) {
+ channelFlags |= CHANNEL_HT40;
+ }
+ } else {
+ channelFlags = CHANNEL_A;
+ }
+ } else {
+ if ( (pBssInfo->EnableHT == 1)
+ || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP
+ {
+ channelFlags = CHANNEL_G_HT;
+ if(pBssInfo->enableHT40 == 1) {
+ channelFlags |= CHANNEL_HT40;
+ }
+ } else {
+ if (pBssInfo->extSupportedRates[1] == 0) {
+ channelFlags = CHANNEL_B;
+ } else {
+ channelFlags = CHANNEL_G;
+ }
+ }
+ }
+
+ if ( ((channelFlags == CHANNEL_B) && (wd->connectMode & ZM_BIT_0))
+ || ((channelFlags == CHANNEL_G) && (wd->connectMode & ZM_BIT_1))
+ || ((channelFlags == CHANNEL_A) && (wd->connectMode & ZM_BIT_2))
+ || ((channelFlags & CHANNEL_HT20) && (wd->connectMode & ZM_BIT_3)) )
+ {
+ pBssInfo = pBssInfo->next;
+ continue;
+ }
+
+ /* Skip if AP in blocking list */
+ if ((ret = zfStaIsApInBlockingList(dev, pBssInfo->bssid)) == TRUE)
+ {
+ zm_msg0_mm(ZM_LV_0, "Candidate AP in blocking List, skip if there's stilla choice!");
+ pNowBssInfo = pBssInfo;
+ pBssInfo = pBssInfo->next;
+ continue;
+ }
+
+ if ( pBssInfo->capability[0] & ZM_BIT_0 ) // check if infra-BSS
+ {
+ pNowBssInfo = pBssInfo;
+ wd->sta.apWmeCapability = pBssInfo->wmeSupport;
+
+
+ goto done;
+ }
+ }
+
+ pBssInfo = pBssInfo->next;
+ }
+
+done:
+ if (pNowBssInfo != NULL)
+ {
+ zfwMemoryCopy((void*)candidateBss, (void*)pNowBssInfo, sizeof(struct zsBssInfo));
+ pNowBssInfo = candidateBss;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return pNowBssInfo;
+}
+
+
+void zfInfraConnectNetwork(zdev_t* dev)
+{
+ struct zsBssInfo* pBssInfo;
+ struct zsBssInfo* pNowBssInfo=NULL;
+ struct zsBssInfo candidateBss;
+ //u16_t i, j=100, quality=10000;
+ //u8_t ret=FALSE, apWepStatus;
+ u8_t ret=FALSE;
+ u16_t k;
+ u8_t density = ZM_MPDU_DENSITY_NONE;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ /* Reset bssNotFoundCount for Ad-Hoc:IBSS */
+ /* Need review : IbssConn -> InfraConn -> IbssConn etc, flag/counter reset? */
+ zmw_enter_critical_section(dev);
+ wd->sta.bssNotFoundCount = 0;
+ zmw_leave_critical_section(dev);
+
+ /* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME STA default. */
+ zfUpdateDefaultQosParameter(dev, 0);
+
+ zfStaRefreshBlockList(dev, 0);
+
+ /* change state to CONNECTING and stop the channel scanning */
+ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING);
+ zfPowerSavingMgrWakeup(dev);
+
+ wd->sta.wmeConnected = 0;
+ wd->sta.psMgr.tempWakeUp = 0;
+ wd->sta.qosInfo = 0;
+ zfQueueFlush(dev, wd->sta.uapsdQ);
+
+ wd->sta.connectState = ZM_STA_CONN_STATE_NONE;
+
+ //Reorder BssList by RSSI--CWYang(+)
+ zfBssInfoReorderList(dev);
+
+ pNowBssInfo = zfInfraFindAPToConnect(dev, &candidateBss);
+
+ if (wd->sta.SWEncryptEnable != 0)
+ {
+ if (wd->sta.bSafeMode == 0)
+ {
+ zfStaDisableSWEncryption(dev);//Quickly reboot
+ }
+ }
+ if ( pNowBssInfo != NULL )
+ {
+ //zm_assert(pNowBssInfo != NULL);
+
+ pBssInfo = pNowBssInfo;
+ wd->sta.ssidLen = pBssInfo->ssid[1];
+ zfMemoryCopy(wd->sta.ssid, &(pBssInfo->ssid[2]), pBssInfo->ssid[1]);
+ wd->frequency = pBssInfo->frequency;
+ //wd->sta.flagFreqChanging = 1;
+
+ //zfCoreSetFrequency(dev, wd->frequency);
+ zfUpdateBssid(dev, pBssInfo->bssid);
+ zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_ZERO);
+ zfUpdateSupportRate(dev, pBssInfo->supportedRates);
+ zfUpdateSupportRate(dev, pBssInfo->extSupportedRates);
+
+ wd->beaconInterval = pBssInfo->beaconInterval[0] +
+ (((u16_t) pBssInfo->beaconInterval[1]) << 8);
+ if (wd->beaconInterval == 0)
+ {
+ wd->beaconInterval = 100;
+ }
+
+ /* ESS bit on */
+ wd->sta.capability[0] |= ZM_BIT_0;
+ /* IBSS bit off */
+ wd->sta.capability[0] &= ~ZM_BIT_1;
+
+ /* 11n AP flag */
+ wd->sta.EnableHT = pBssInfo->EnableHT;
+ wd->sta.SG40 = pBssInfo->SG40;
+#ifdef ZM_ENABLE_CENC
+ if ( pBssInfo->securityType == ZM_SECURITY_TYPE_CENC )
+ {
+ wd->sta.wmeEnabled = 0; //Disable WMM in CENC
+ cencInit(dev);
+ cencSetCENCMode(dev, NdisCENC_PSK);
+ wd->sta.wpaState = ZM_STA_WPA_STATE_INIT;
+ /* CENC */
+ if ( pBssInfo->cencIe[1] != 0 )
+ {
+ //wd->sta.wepStatus = ZM_ENCRYPTION_CENC;
+ //wd->sta.encryMode = ZM_CENC;
+ zfwCencHandleBeaconProbrespon(dev, (u8_t *)&pBssInfo->cencIe,
+ (u8_t *)&pBssInfo->ssid, (u8_t *)&pBssInfo->macaddr);
+ zfMemoryCopy(wd->sta.cencIe, pBssInfo->cencIe,
+ pBssInfo->cencIe[1]+2);
+ }
+ else
+ {
+ wd->sta.cencIe[1] = 0;
+ }
+ }
+#endif //ZM_ENABLE_CENC
+ if ( pBssInfo->securityType == ZM_SECURITY_TYPE_WPA )
+ {
+ wd->sta.wpaState = ZM_STA_WPA_STATE_INIT;
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_TKIP )
+ {
+ wd->sta.encryMode = ZM_TKIP;
+
+ /* Turn on software encryption/decryption for TKIP */
+ if (wd->sta.EnableHT == 1)
+ {
+ zfStaEnableSWEncryption(dev, (ZM_SW_TKIP_ENCRY_EN|ZM_SW_TKIP_DECRY_EN));
+ }
+
+ /* Do not support TKIP in 11n mode */
+ //wd->sta.EnableHT = 0;
+ //pBssInfo->enableHT40 = 0;
+ }
+ else if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ wd->sta.encryMode = ZM_AES;
+
+ /* If AP supports HT mode */
+ if (wd->sta.EnableHT)
+ {
+ /* Set MPDU density to 8 us*/
+ density = ZM_MPDU_DENSITY_8US;
+ }
+ }
+
+ if ( pBssInfo->wpaIe[1] != 0 )
+ {
+ zfMemoryCopy(wd->sta.wpaIe, pBssInfo->wpaIe,
+ pBssInfo->wpaIe[1]+2);
+ }
+ else
+ {
+ wd->sta.wpaIe[1] = 0;
+ }
+
+ if ( pBssInfo->rsnIe[1] != 0 )
+ {
+ zfMemoryCopy(wd->sta.rsnIe, pBssInfo->rsnIe,
+ pBssInfo->rsnIe[1]+2);
+ }
+ else
+ {
+ wd->sta.rsnIe[1] = 0;
+ }
+ }
+
+
+
+ /* check preamble bit */
+ wd->preambleTypeInUsed = wd->preambleType;
+ if ( wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_AUTO )
+ {
+ if (pBssInfo->capability[0] & ZM_BIT_5)
+ {
+ wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT;
+ }
+ else
+ {
+ wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_LONG;
+ }
+ }
+
+ if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG)
+ {
+ wd->sta.capability[0] &= ~ZM_BIT_5;
+ }
+ else
+ {
+ wd->sta.capability[0] |= ZM_BIT_5;
+ }
+
+ /* check 802.11n 40MHz Setting */
+ if ((pBssInfo->enableHT40 == 1) &&
+ ((pBssInfo->extChOffset == 1) || (pBssInfo->extChOffset == 3)))
+ {
+ wd->BandWidth40 = pBssInfo->enableHT40;
+ wd->ExtOffset = pBssInfo->extChOffset;
+ }
+ else
+ {
+ wd->BandWidth40 = 0;
+ wd->ExtOffset = 0;
+ }
+
+ /* check 802.11H support bit */
+
+ /* check Owl Ap */
+ if ( pBssInfo->athOwlAp & ZM_BIT_0 )
+ {
+ /* In this function, FW retry will be enable, ZM_MAC_REG_RETRY_MAX
+ will be set to 0.
+ */
+ zfHpDisableHwRetry(dev);
+ wd->sta.athOwlAp = 1;
+ /* Set MPDU density to 8 us*/
+ density = ZM_MPDU_DENSITY_8US;
+ }
+ else
+ {
+ /* In this function, FW retry will be disable, ZM_MAC_REG_RETRY_MAX
+ will be set to 3.
+ */
+ zfHpEnableHwRetry(dev);
+ wd->sta.athOwlAp = 0;
+ }
+ wd->reorder = 1;
+
+ /* Set MPDU density */
+ zfHpSetMPDUDensity(dev, density);
+
+ /* check short slot time bit */
+ if ( pBssInfo->capability[1] & ZM_BIT_2 )
+ {
+ wd->sta.capability[1] |= ZM_BIT_2;
+ }
+
+ if ( pBssInfo->erp & ZM_BIT_1 )
+ {
+ //zm_debug_msg0("protection mode on");
+ wd->sta.bProtectionMode = TRUE;
+ zfHpSetSlotTime(dev, 0);
+ }
+ else
+ {
+ //zm_debug_msg0("protection mode off");
+ wd->sta.bProtectionMode = FALSE;
+ zfHpSetSlotTime(dev, 1);
+ }
+
+ if (pBssInfo->marvelAp == 1)
+ {
+ wd->sta.enableDrvBA = 0;
+ /*
+ * 8701 : NetGear 3500 (MARVELL)
+ * Downlink issue : set slottime to 20.
+ */
+ zfHpSetSlotTimeRegister(dev, 0);
+ }
+ else
+ {
+ wd->sta.enableDrvBA = 1;
+
+ /*
+ * This is not good for here do reset slot time.
+ * I think it should reset when leave MARVELL ap
+ * or enter disconnect state etc.
+ */
+ zfHpSetSlotTimeRegister(dev, 1);
+ }
+
+ //Store probe response frame body, for VISTA only
+ wd->sta.beaconFrameBodySize = pBssInfo->frameBodysize + 12;
+ if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE)
+ {
+ wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE;
+ }
+ for (k=0; k<8; k++)
+ {
+ wd->sta.beaconFrameBody[k] = pBssInfo->timeStamp[k];
+ }
+ wd->sta.beaconFrameBody[8] = pBssInfo->beaconInterval[0];
+ wd->sta.beaconFrameBody[9] = pBssInfo->beaconInterval[1];
+ wd->sta.beaconFrameBody[10] = pBssInfo->capability[0];
+ wd->sta.beaconFrameBody[11] = pBssInfo->capability[1];
+ for (k=0; k<(wd->sta.beaconFrameBodySize - 12); k++)
+ {
+ wd->sta.beaconFrameBody[k+12] = pBssInfo->frameBody[k];
+ }
+
+ if ( ( pBssInfo->capability[0] & ZM_BIT_4 )&&
+ (( wd->sta.authMode == ZM_AUTH_MODE_OPEN )||
+ ( wd->sta.authMode == ZM_AUTH_MODE_SHARED_KEY)||
+ (wd->sta.authMode == ZM_AUTH_MODE_AUTO)) )
+ { /* privacy enabled */
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED )
+ {
+ zm_debug_msg0("Adapter is no WEP, try to connect to WEP AP");
+ ret = FALSE;
+ }
+
+ /* Do not support WEP in 11n mode */
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED )
+ {
+ /* Turn on software encryption/decryption for WEP */
+ if (wd->sta.EnableHT == 1)
+ {
+ zfStaEnableSWEncryption(dev, (ZM_SW_WEP_ENCRY_EN|ZM_SW_WEP_DECRY_EN));
+ }
+
+ //wd->sta.EnableHT = 0;
+ //wd->BandWidth40 = 0;
+ //wd->ExtOffset = 0;
+ }
+
+ wd->sta.capability[0] |= ZM_BIT_4;
+
+ if ( wd->sta.authMode == ZM_AUTH_MODE_AUTO )
+ { /* Try to use open and shared-key authehtication alternatively */
+ if ( (wd->sta.connectTimeoutCount % 2) == 0 )
+ wd->sta.bIsSharedKey = 0;
+ else
+ wd->sta.bIsSharedKey = 1;
+ }
+ else if ( wd->sta.authMode != ZM_AUTH_MODE_SHARED_KEY )
+ { /* open or auto */
+ //zfStaStartConnect(dev, 0);
+ wd->sta.bIsSharedKey = 0;
+ }
+ else if ( wd->sta.authMode != ZM_AUTH_MODE_OPEN )
+ { /* shared key */
+ //zfStaStartConnect(dev, 1) ;
+ wd->sta.bIsSharedKey = 1;
+ }
+ }
+ else
+ {
+ if ( (pBssInfo->securityType == ZM_SECURITY_TYPE_WPA)||
+ (pBssInfo->capability[0] & ZM_BIT_4) )
+ {
+ wd->sta.capability[0] |= ZM_BIT_4;
+ /* initialize WPA related parameters */
+ }
+ else
+ {
+ wd->sta.capability[0] &= (~ZM_BIT_4);
+ }
+
+ /* authentication with open system */
+ //zfStaStartConnect(dev, 0);
+ wd->sta.bIsSharedKey = 0;
+ }
+
+ /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */
+ /*
+ if ( (pBssInfo->broadcomHTAp == 1)
+ && (wd->sta.SWEncryptEnable != 0) )
+ {
+ zfHpSetTTSIFSTime(dev, 0xa);
+ }
+ else
+ {
+ zfHpSetTTSIFSTime(dev, 0x8);
+ }
+ */
+ }
+ else
+ {
+ zm_debug_msg0("Desired SSID not found");
+ goto zlConnectFailed;
+ }
+
+
+ zfCoreSetFrequencyV2(dev, wd->frequency, zfStaStartConnectCb);
+ return;
+
+zlConnectFailed:
+ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND, wd->sta.bssid, 0);
+ return;
+}
+
+u8_t zfCheckWPAAuth(zdev_t* dev, struct zsBssInfo* pBssInfo)
+{
+ u8_t ret=TRUE;
+ u8_t pmkCount;
+ u8_t i;
+ u16_t encAlgoType = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_TKIP )
+ {
+ encAlgoType = ZM_TKIP;
+ }
+ else if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ encAlgoType = ZM_AES;
+ }
+
+ switch(wd->sta.authMode)
+ {
+ case ZM_AUTH_MODE_WPA:
+ case ZM_AUTH_MODE_WPAPSK:
+ if ( pBssInfo->wpaIe[1] == 0 )
+ {
+ ret = FALSE;
+ break;
+ }
+
+ pmkCount = pBssInfo->wpaIe[12];
+ for(i=0; i < pmkCount; i++)
+ {
+ if ( pBssInfo->wpaIe[17 + 4*i] == encAlgoType )
+ {
+ ret = TRUE;
+ goto done;
+ }
+ }
+
+ ret = FALSE;
+ break;
+
+ case ZM_AUTH_MODE_WPA2:
+ case ZM_AUTH_MODE_WPA2PSK:
+ if ( pBssInfo->rsnIe[1] == 0 )
+ {
+ ret = FALSE;
+ break;
+ }
+
+ pmkCount = pBssInfo->rsnIe[8];
+ for(i=0; i < pmkCount; i++)
+ {
+ if ( pBssInfo->rsnIe[13 + 4*i] == encAlgoType )
+ {
+ ret = TRUE;
+ goto done;
+ }
+ }
+
+ ret = FALSE;
+ break;
+ }
+
+done:
+ return ret;
+}
+
+u8_t zfCheckAuthentication(zdev_t* dev, struct zsBssInfo* pBssInfo)
+{
+ u8_t ret=TRUE;
+ u16_t encAlgoType;
+ u16_t UnicastCipherNum;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Connecting to ANY has been checked */
+ if ( wd->sta.ssidLen == 0 )
+ {
+ return ret;
+ }
+
+
+ switch(wd->sta.authMode)
+ //switch(wd->ws.authMode)//Quickly reboot
+ {
+ case ZM_AUTH_MODE_WPA_AUTO:
+ case ZM_AUTH_MODE_WPAPSK_AUTO:
+ encAlgoType = 0;
+ if(pBssInfo->rsnIe[1] != 0)
+ {
+ UnicastCipherNum = (pBssInfo->rsnIe[8]) +
+ (pBssInfo->rsnIe[9] << 8);
+
+ /* If there is only one unicast cipher */
+ if (UnicastCipherNum == 1)
+ {
+ encAlgoType = pBssInfo->rsnIe[13];
+ //encAlgoType = pBssInfo->rsnIe[7];
+ }
+ else
+ {
+ u16_t ii;
+ u16_t desiredCipher = 0;
+ u16_t IEOffSet = 13;
+
+ /* Enumerate all the supported unicast cipher */
+ for (ii = 0; ii < UnicastCipherNum; ii++)
+ {
+ if (pBssInfo->rsnIe[IEOffSet+ii*4] > desiredCipher)
+ {
+ desiredCipher = pBssInfo->rsnIe[IEOffSet+ii*4];
+ }
+ }
+
+ encAlgoType = desiredCipher;
+ }
+
+ if ( encAlgoType == 0x02 )
+ {
+ wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
+
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2;
+ }
+ else //ZM_AUTH_MODE_WPAPSK_AUTO
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2PSK;
+ }
+ }
+ else if ( encAlgoType == 0x04 )
+ {
+ wd->sta.wepStatus = ZM_ENCRYPTION_AES;
+
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2;
+ }
+ else //ZM_AUTH_MODE_WPAPSK_AUTO
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2PSK;
+ }
+ }
+ else
+ {
+ ret = FALSE;
+ }
+ }
+ else if(pBssInfo->wpaIe[1] != 0)
+ {
+ UnicastCipherNum = (pBssInfo->wpaIe[12]) +
+ (pBssInfo->wpaIe[13] << 8);
+
+ /* If there is only one unicast cipher */
+ if (UnicastCipherNum == 1)
+ {
+ encAlgoType = pBssInfo->wpaIe[17];
+ //encAlgoType = pBssInfo->wpaIe[11];
+ }
+ else
+ {
+ u16_t ii;
+ u16_t desiredCipher = 0;
+ u16_t IEOffSet = 17;
+
+ /* Enumerate all the supported unicast cipher */
+ for (ii = 0; ii < UnicastCipherNum; ii++)
+ {
+ if (pBssInfo->wpaIe[IEOffSet+ii*4] > desiredCipher)
+ {
+ desiredCipher = pBssInfo->wpaIe[IEOffSet+ii*4];
+ }
+ }
+
+ encAlgoType = desiredCipher;
+ }
+
+ if ( encAlgoType == 0x02 )
+ {
+ wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
+
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA;
+ }
+ else //ZM_AUTH_MODE_WPAPSK_AUTO
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPAPSK;
+ }
+ }
+ else if ( encAlgoType == 0x04 )
+ {
+ wd->sta.wepStatus = ZM_ENCRYPTION_AES;
+
+ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO )
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA;
+ }
+ else //ZM_AUTH_MODE_WPAPSK_AUTO
+ {
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_WPAPSK;
+ }
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ break;
+
+ case ZM_AUTH_MODE_WPA:
+ case ZM_AUTH_MODE_WPAPSK:
+ case ZM_AUTH_MODE_WPA_NONE:
+ case ZM_AUTH_MODE_WPA2:
+ case ZM_AUTH_MODE_WPA2PSK:
+ {
+ if ( pBssInfo->securityType != ZM_SECURITY_TYPE_WPA )
+ {
+ ret = FALSE;
+ }
+
+ ret = zfCheckWPAAuth(dev, pBssInfo);
+ }
+ break;
+
+ case ZM_AUTH_MODE_OPEN:
+ case ZM_AUTH_MODE_SHARED_KEY:
+ case ZM_AUTH_MODE_AUTO:
+ {
+ if ( pBssInfo->wscIe[1] )
+ {
+ // If the AP is a Jumpstart AP, it's ok!! Ray
+ break;
+ }
+ else if ( pBssInfo->securityType == ZM_SECURITY_TYPE_WPA )
+ {
+ ret = FALSE;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+u8_t zfStaIsConnected(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->sta.adapterState == ZM_STA_STATE_CONNECTED )
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+u8_t zfStaIsConnecting(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->sta.adapterState == ZM_STA_STATE_CONNECTING )
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+u8_t zfStaIsDisconnect(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->sta.adapterState == ZM_STA_STATE_DISCONNECT )
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+u8_t zfChangeAdapterState(zdev_t* dev, u8_t newState)
+{
+ u8_t ret = TRUE;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ //if ( newState == wd->sta.adapterState )
+ //{
+ // return FALSE;
+ //}
+
+ switch(newState)
+ {
+ case ZM_STA_STATE_DISCONNECT:
+ zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_DISCONNECT);
+
+ #if 1
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ #else
+ if ( wd->sta.bChannelScan )
+ {
+ /* stop the action of channel scanning */
+ wd->sta.bChannelScan = FALSE;
+ ret = TRUE;
+ break;
+ }
+ #endif
+
+ break;
+ case ZM_STA_STATE_CONNECTING:
+ #if 1
+ zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL);
+ #else
+ if ( wd->sta.bChannelScan )
+ {
+ /* stop the action of channel scanning */
+ wd->sta.bChannelScan = FALSE;
+ ret = TRUE;
+ break;
+ }
+ #endif
+
+ break;
+ case ZM_STA_STATE_CONNECTED:
+ break;
+ default:
+ break;
+ }
+
+ //if ( ret )
+ //{
+ zmw_enter_critical_section(dev);
+ wd->sta.adapterState = newState;
+ zmw_leave_critical_section(dev);
+
+ zm_debug_msg1("change adapter state = ", newState);
+ //}
+
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaMmAddIeSsid */
+/* Add information element SSID to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Ji-Huang Lee ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+u16_t zfStaAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ssidLen);
+
+ /* Information : SSID */
+ for (i=0; i<wd->sta.ssidLen; i++)
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ssid[i]);
+ }
+
+ return offset;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaMmAddIeWpa */
+/* Add information element SSID to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Ji-Huang Lee ZyDAS Technology Corporation 2006.01 */
+/* */
+/************************************************************************/
+u16_t zfStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType)
+{
+ u32_t i;
+ u8_t ssn[64]={
+ /* Element ID */
+ 0xdd,
+ /* Length */
+ 0x18,
+ /* OUI type */
+ 0x00, 0x50, 0xf2, 0x01,
+ /* Version */
+ 0x01, 0x00,
+ /* Group Cipher Suite, default=TKIP */
+ 0x00, 0x50, 0xf2, 0x02,
+ /* Pairwise Cipher Suite Count */
+ 0x01, 0x00,
+ /* Pairwise Cipher Suite, default=TKIP */
+ 0x00, 0x50, 0xf2, 0x02,
+ /* Authentication and Key Management Suite Count */
+ 0x01, 0x00,
+ /* Authentication type, default=PSK */
+ 0x00, 0x50, 0xf2, 0x02,
+ /* WPA capability */
+ 0x00, 0x00
+ };
+
+ u8_t rsn[64]={
+ /* Element ID */
+ 0x30,
+ /* Length */
+ 0x14,
+ /* Version */
+ 0x01, 0x00,
+ /* Group Cipher Suite, default=TKIP */
+ 0x00, 0x0f, 0xac, 0x02,
+ /* Pairwise Cipher Suite Count */
+ 0x01, 0x00,
+ /* Pairwise Cipher Suite, default=TKIP */
+ 0x00, 0x0f, 0xac, 0x02,
+ /* Authentication and Key Management Suite Count */
+ 0x01, 0x00,
+ /* Authentication type, default=PSK */
+ 0x00, 0x0f, 0xac, 0x02,
+ /* RSN capability */
+ 0x00, 0x00
+ };
+
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPAPSK )
+ {
+ /* Overwrite Group Cipher Suite by AP's setting */
+ zfMemoryCopy(ssn+8, wd->sta.wpaIe+8, 4);
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ /* Overwrite Pairwise Cipher Suite by AES */
+ zfMemoryCopy(ssn+14, zgWpaAesOui, 4);
+ }
+
+ zfCopyToIntTxBuffer(dev, buf, ssn, offset, ssn[1]+2);
+ zfMemoryCopy(wd->sta.wpaIe, ssn, ssn[1]+2);
+ offset += (ssn[1]+2);
+ }
+ else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA )
+ {
+ /* Overwrite Group Cipher Suite by AP's setting */
+ zfMemoryCopy(ssn+8, wd->sta.wpaIe+8, 4);
+ /* Overwrite Key Management Suite by WPA-Radius */
+ zfMemoryCopy(ssn+20, zgWpaRadiusOui, 4);
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ /* Overwrite Pairwise Cipher Suite by AES */
+ zfMemoryCopy(ssn+14, zgWpaAesOui, 4);
+ }
+
+ zfCopyToIntTxBuffer(dev, buf, ssn, offset, ssn[1]+2);
+ zfMemoryCopy(wd->sta.wpaIe, ssn, ssn[1]+2);
+ offset += (ssn[1]+2);
+ }
+ else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA2PSK )
+ {
+ /* Overwrite Group Cipher Suite by AP's setting */
+ zfMemoryCopy(rsn+4, wd->sta.rsnIe+4, 4);
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ /* Overwrite Pairwise Cipher Suite by AES */
+ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
+ }
+
+ if ( frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ )
+ {
+ for(i=0; i<wd->sta.pmkidInfo.bssidCount; i++)
+ {
+ if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid,
+ (u8_t*) wd->sta.bssid, 6) )
+ {
+ /* matched */
+ break;
+ }
+
+ if ( i < wd->sta.pmkidInfo.bssidCount )
+ {
+ // Fill PMKID Count in RSN information element
+ rsn[22] = 0x01;
+ rsn[23] = 0x00;
+
+ // Fill PMKID in RSN information element
+ zfMemoryCopy(rsn+24,
+ wd->sta.pmkidInfo.bssidInfo[i].pmkid, 16);
+ rsn[1] += 18;
+ }
+ }
+ }
+
+ zfCopyToIntTxBuffer(dev, buf, rsn, offset, rsn[1]+2);
+ zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2);
+ offset += (rsn[1]+2);
+ }
+ else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA2 )
+ {
+ /* Overwrite Group Cipher Suite by AP's setting */
+ zfMemoryCopy(rsn+4, wd->sta.rsnIe+4, 4);
+ /* Overwrite Key Management Suite by WPA2-Radius */
+ zfMemoryCopy(rsn+16, zgWpa2RadiusOui, 4);
+
+ if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES )
+ {
+ /* Overwrite Pairwise Cipher Suite by AES */
+ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4);
+ }
+
+ if (( frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ || ( frameType == ZM_WLAN_FRAME_TYPE_ASOCREQ )))
+ {
+
+ if (wd->sta.pmkidInfo.bssidCount != 0) {
+ // Fill PMKID Count in RSN information element
+ rsn[22] = 1;
+ rsn[23] = 0;
+ /*
+ * The caller is respnsible to give us the relevant PMKID.
+ * We'll only accept 1 PMKID for now.
+ */
+ for(i=0; i<wd->sta.pmkidInfo.bssidCount; i++)
+ {
+ if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid, (u8_t*) wd->sta.bssid, 6) )
+ {
+ zfMemoryCopy(rsn+24, wd->sta.pmkidInfo.bssidInfo[i].pmkid, 16);
+ break;
+ }
+ }
+ rsn[1] += 18;
+ }
+
+ }
+
+ zfCopyToIntTxBuffer(dev, buf, rsn, offset, rsn[1]+2);
+ zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2);
+ offset += (rsn[1]+2);
+ }
+
+ return offset;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaAddIeIbss */
+/* Add information element IBSS parameter to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Ji-Huang Lee ZyDAS Technology Corporation 2005.12 */
+/* */
+/************************************************************************/
+u16_t zfStaAddIeIbss(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_IBSS);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, 2);
+
+ /* ATIM window */
+ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.atimWindow);
+ offset += 2;
+
+ return offset;
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaAddIeWmeInfo */
+/* Add WME Information Element to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+u16_t zfStaAddIeWmeInfo(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t qosInfo)
+{
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WIFI_IE);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, 7);
+
+ /* OUI */
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x50);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0xF2);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x02);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x00);
+ zmw_tx_buf_writeb(dev, buf, offset++, 0x01);
+
+ /* QoS Info */
+ zmw_tx_buf_writeb(dev, buf, offset++, qosInfo);
+
+ return offset;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaAddIePowerCap */
+/* Add information element Power capability to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Sharon 2007.12 */
+/* */
+/************************************************************************/
+u16_t zfStaAddIePowerCap(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ u8_t MaxTxPower;
+ u8_t MinTxPower;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_POWER_CAPABILITY);
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, 2);
+
+ MinTxPower = (u8_t)(zfHpGetMinTxPower(dev)/2);
+ MaxTxPower = (u8_t)(zfHpGetMaxTxPower(dev)/2);
+
+ /* Min Transmit Power Cap */
+ zmw_tx_buf_writeh(dev, buf, offset++, MinTxPower);
+
+ /* Max Transmit Power Cap */
+ zmw_tx_buf_writeh(dev, buf, offset++, MaxTxPower);
+
+ return offset;
+}
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfStaAddIeSupportCh */
+/* Add information element supported channels to buffer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer to add information element */
+/* offset : add information element from this offset */
+/* */
+/* OUTPUTS */
+/* buffer offset after adding information element */
+/* */
+/* AUTHOR */
+/* Sharon 2007.12 */
+/* */
+/************************************************************************/
+u16_t zfStaAddIeSupportCh(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+
+ u8_t i;
+ u16_t count_24G = 0;
+ u16_t count_5G = 0;
+ u16_t channelNum;
+ u8_t length;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+ zmw_enter_critical_section(dev);
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel < 3000)
+ { // 2.4Hz
+ count_24G++;
+ }
+ else
+ { // 5GHz
+ count_5G++;
+ }
+ }
+
+ length = (u8_t)(count_5G * 2 + 2); //5G fill by pair, 2,4G (continuous channels) fill 2 bytes
+
+ /* Element ID */
+ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SUPPORTED_CHANNELS );
+
+ /* Element Length */
+ zmw_tx_buf_writeb(dev, buf, offset++, length);
+
+ // 2.4GHz (continuous channels)
+ /* First channel number */
+ zmw_tx_buf_writeh(dev, buf, offset++, 1); //Start from channle 1
+ /* Number of channels */
+ zmw_tx_buf_writeh(dev, buf, offset++, count_24G);
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt ; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel > 4000 && wd->regulationTable.allowChannel[i].channel < 5000)
+ { // 5GHz 4000 -5000Mhz
+ channelNum = (wd->regulationTable.allowChannel[i].channel-4000)/5;
+ /* First channel number */
+ zmw_tx_buf_writeh(dev, buf, offset++, channelNum);
+ /* Number of channels */
+ zmw_tx_buf_writeh(dev, buf, offset++, 1);
+ }
+ else if (wd->regulationTable.allowChannel[i].channel >= 5000)
+ { // 5GHz >5000Mhz
+ channelNum = (wd->regulationTable.allowChannel[i].channel-5000)/5;
+ /* First channel number */
+ zmw_tx_buf_writeh(dev, buf, offset++, channelNum);
+ /* Number of channels */
+ zmw_tx_buf_writeh(dev, buf, offset++, 1);
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+ return offset;
+}
+
+void zfStaStartConnectCb(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zfStaStartConnect(dev, wd->sta.bIsSharedKey);
+}
+
+void zfStaStartConnect(zdev_t* dev, u8_t bIsSharedKey)
+{
+ u32_t p1, p2;
+ u8_t newConnState;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ /* p1_low = algorithm number, p1_high = transaction sequence number */
+ if ( bIsSharedKey )
+ {
+ //wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_SHARE_1;
+ newConnState = ZM_STA_CONN_STATE_AUTH_SHARE_1;
+ zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_SHARE_1");
+ p1 = ZM_AUTH_ALGO_SHARED_KEY;
+ }
+ else
+ {
+ //wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_OPEN;
+ newConnState = ZM_STA_CONN_STATE_AUTH_OPEN;
+ zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_OPEN");
+ if( wd->sta.leapEnabled )
+ p1 = ZM_AUTH_ALGO_LEAP;
+ else
+ p1 = ZM_AUTH_ALGO_OPEN_SYSTEM;
+ }
+
+ /* status code */
+ p2 = 0x0;
+
+ zmw_enter_critical_section(dev);
+ wd->sta.connectTimer = wd->tick;
+ wd->sta.connectState = newConnState;
+ zmw_leave_critical_section(dev);
+
+ /* send the 1st authentication frame */
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH, wd->sta.bssid, p1, p2, 0);
+
+ return;
+}
+
+void zfSendNullData(zdev_t* dev, u8_t type)
+{
+ zbuf_t* buf;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ u16_t err;
+ u16_t hlen;
+ u16_t header[(34+8+1)/2];
+ u16_t bcastAddr[3] = {0xffff,0xffff,0xffff};
+ u16_t *dstAddr;
+
+ zmw_get_wlan_dev(dev);
+
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
+ return;
+ }
+
+ zfwBufSetSize(dev, buf, 0);
+
+ //zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len);
+
+ if ( wd->wlanMode == ZM_MODE_IBSS)
+ {
+ dstAddr = bcastAddr;
+ }
+ else
+ {
+ dstAddr = wd->sta.bssid;
+ }
+
+ if (wd->sta.wmeConnected != 0)
+ {
+ /* If connect to a WMM AP, Send QoS Null data */
+ hlen = zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_QOS_NULL, dstAddr, header, 0, buf, 0, 0);
+ }
+ else
+ {
+ hlen = zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_NULL, dstAddr, header, 0, buf, 0, 0);
+ }
+
+ if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ header[4] |= 0x0100; //TODS bit
+ }
+
+ if ( type == 1 )
+ {
+ header[4] |= 0x1000;
+ }
+
+ /* Get buffer DMA address */
+ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
+ //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
+ //{
+ // goto zlError;
+ //}
+
+ /*increase unicast frame counter*/
+ wd->commTally.txUnicastFrm++;
+
+ if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+
+
+ return;
+
+zlError:
+
+ zfwBufFree(dev, buf, 0);
+ return;
+
+}
+
+void zfSendPSPoll(zdev_t* dev)
+{
+ zbuf_t* buf;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ u16_t err;
+ u16_t hlen;
+ u16_t header[(8+24+1)/2];
+
+ zmw_get_wlan_dev(dev);
+
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
+ return;
+ }
+
+ zfwBufSetSize(dev, buf, 0);
+
+ //zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len);
+
+ zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_PSPOLL, wd->sta.bssid, header, 0, buf, 0, 0);
+
+ header[0] = 20;
+ header[4] |= 0x1000;
+ header[5] = wd->sta.aid | 0xc000; //Both bit-14 and bit-15 are 1
+ hlen = 16 + 8;
+
+ /* Get buffer DMA address */
+ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0)
+ //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0)
+ //{
+ // goto zlError;
+ //}
+
+ if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+
+ return;
+
+zlError:
+
+ zfwBufFree(dev, buf, 0);
+ return;
+
+}
+
+void zfSendBA(zdev_t* dev, u16_t start_seq, u8_t *bitmap)
+{
+ zbuf_t* buf;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ u16_t err;
+ u16_t hlen;
+ u16_t header[(8+24+1)/2];
+ u16_t i, offset = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ if ((buf = zfwBufAllocate(dev, 1024)) == NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!");
+ return;
+ }
+
+ zfwBufSetSize(dev, buf, 12); // 28 = FC 2 + DU 2 + RA 6 + TA 6 + BAC 2 + SEQ 2 + BitMap 8
+ // 12 = BAC 2 + SEQ 2 + BitMap 8
+
+ //zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len);
+
+ zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_BA, wd->sta.bssid, header, 0, buf, 0, 0);
+
+ header[0] = 32; /* MAC header 16 + BA control 2 + BA info 10 + FCS 4*/
+ header[1] = 0x4; /* No ACK */
+
+ /* send by OFDM 6M */
+ header[2] = (u16_t)(zcRateToPhyCtrl[4] & 0xffff);
+ header[3] = (u16_t)(zcRateToPhyCtrl[4]>>16) & 0xffff;
+
+ hlen = 16 + 8; /* MAC header 16 + control 8*/
+ offset = 0;
+ zmw_tx_buf_writeh(dev, buf, offset, 0x05); /*compressed bitmap on*/
+ offset+=2;
+ zmw_tx_buf_writeh(dev, buf, offset, start_seq);
+ offset+=2;
+
+ for (i=0; i<8; i++) {
+ zmw_tx_buf_writeb(dev, buf, offset, bitmap[i]);
+ offset++;
+ }
+
+ if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+
+ return;
+
+zlError:
+
+ zfwBufFree(dev, buf, 0);
+ return;
+
+}
+
+void zfStaGetTxRate(zdev_t* dev, u16_t* macAddr, u32_t* phyCtrl,
+ u16_t* rcProbingFlag)
+{
+ u8_t addr[6], i;
+ u8_t rate;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ ZM_MAC_WORD_TO_BYTE(macAddr, addr);
+ *phyCtrl = 0;
+
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ zmw_enter_critical_section(dev);
+ rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[0].rcCell, rcProbingFlag);
+//#ifdef ZM_FB50
+ //rate = 27;
+//#endif
+ *phyCtrl = zcRateToPhyCtrl[rate];
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ for(i=0; i<wd->sta.oppositeCount; i++)
+ {
+ if ( addr[0] && 0x01 == 1 ) // The default beacon transmitted rate is CCK and 1 Mbps , but the a mode should use
+ // OFDM modulation and 6Mbps to transmit beacon.
+ {
+ //rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[i].rcCell, rcProbingFlag);
+ rate = wd->sta.oppositeInfo[i].rcCell.operationRateSet[0];
+ *phyCtrl = zcRateToPhyCtrl[rate];
+ break;
+ }
+ else if ( zfMemoryIsEqual(addr, wd->sta.oppositeInfo[i].macAddr, 6) )
+ {
+ rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[i].rcCell, rcProbingFlag);
+ *phyCtrl = zcRateToPhyCtrl[rate];
+ break;
+ }
+ }
+ zmw_leave_critical_section(dev);
+ }
+
+ return;
+}
+
+struct zsMicVar* zfStaGetRxMicKey(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t keyIndex;
+ u8_t da0;
+
+ zmw_get_wlan_dev(dev);
+
+ /* if need not check MIC, return NULL */
+ if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))||
+ (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
+ {
+ return NULL;
+ }
+
+ da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
+
+ if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) == 0x80)
+ keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+5); /* Qos Packet*/
+ else
+ keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+3); /* normal Packet*/
+ keyIndex = (keyIndex & 0xc0) >> 6;
+
+ return (&wd->sta.rxMicKey[keyIndex]);
+}
+
+struct zsMicVar* zfStaGetTxMicKey(zdev_t* dev, zbuf_t* buf)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* if need not check MIC, return NULL */
+ //if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))||
+ // (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
+ if ( (wd->sta.encryMode != ZM_TKIP) || (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
+ {
+ return NULL;
+ }
+
+ return (&wd->sta.txMicKey);
+}
+
+u16_t zfStaRxValidateFrame(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t frameType, frameCtrl;
+ u8_t da0;
+ //u16_t sa[3];
+ u16_t ret;
+ u16_t i;
+ //u8_t sa0;
+
+ zmw_get_wlan_dev(dev);
+
+ frameType = zmw_rx_buf_readb(dev, buf, 0);
+ da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
+ //sa0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
+
+ if ( (!zfStaIsConnected(dev))&&((frameType & 0xf) == ZM_WLAN_DATA_FRAME) )
+ {
+ return ZM_ERR_DATA_BEFORE_CONNECTED;
+ }
+
+
+ if ( (zfStaIsConnected(dev))&&((frameType & 0xf) == ZM_WLAN_DATA_FRAME) )
+ {
+ /* check BSSID */
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ /* Big Endian and Little Endian Compatibility */
+ u16_t mac[3];
+ mac[0] = zmw_cpu_to_le16(wd->sta.bssid[0]);
+ mac[1] = zmw_cpu_to_le16(wd->sta.bssid[1]);
+ mac[2] = zmw_cpu_to_le16(wd->sta.bssid[2]);
+ if ( !zfRxBufferEqualToStr(dev, buf, (u8_t *)mac,
+ ZM_WLAN_HEADER_A2_OFFSET, 6) )
+ {
+/*We will get lots of garbage data, especially in AES mode.*/
+/*To avoid sending too many deauthentication frames in STA mode, mark it.*/
+#if 0
+ /* If unicast frame, send deauth to the transmitter */
+ if (( da0 & 0x01 ) == 0)
+ {
+ for (i=0; i<3; i++)
+ {
+ sa[i] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+(i*2));
+ }
+ /* If mutilcast address, don't send deauthentication*/
+ if (( sa0 & 0x01 ) == 0)
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, sa, 7, 0, 0);
+ }
+#endif
+ return ZM_ERR_DATA_BSSID_NOT_MATCHED;
+ }
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ /* Big Endian and Little Endian Compatibility */
+ u16_t mac[3];
+ mac[0] = zmw_cpu_to_le16(wd->sta.bssid[0]);
+ mac[1] = zmw_cpu_to_le16(wd->sta.bssid[1]);
+ mac[2] = zmw_cpu_to_le16(wd->sta.bssid[2]);
+ if ( !zfRxBufferEqualToStr(dev, buf, (u8_t *)mac,
+ ZM_WLAN_HEADER_A3_OFFSET, 6) )
+ {
+ return ZM_ERR_DATA_BSSID_NOT_MATCHED;
+ }
+ }
+
+ frameCtrl = zmw_rx_buf_readb(dev, buf, 1);
+
+ /* check security bit */
+ if ( wd->sta.dropUnencryptedPkts &&
+ (wd->sta.wepStatus != ZM_ENCRYPTION_WEP_DISABLED )&&
+ ( !(frameCtrl & ZM_BIT_6) ) )
+ { /* security on, but got data without encryption */
+
+ #if 1
+ ret = ZM_ERR_DATA_NOT_ENCRYPTED;
+ if ( wd->sta.pStaRxSecurityCheckCb != NULL )
+ {
+ ret = wd->sta.pStaRxSecurityCheckCb(dev, buf);
+ }
+ else
+ {
+ ret = ZM_ERR_DATA_NOT_ENCRYPTED;
+ }
+ if (ret == ZM_ERR_DATA_NOT_ENCRYPTED)
+ {
+ wd->commTally.swRxDropUnencryptedCount++;
+ }
+ return ret;
+ #else
+ if ( (wd->sta.wepStatus != ZM_ENCRYPTION_TKIP)&&
+ (wd->sta.wepStatus != ZM_ENCRYPTION_AES) )
+ {
+ return ZM_ERR_DATA_NOT_ENCRYPTED;
+ }
+ #endif
+ }
+ }
+
+ return ZM_SUCCESS;
+}
+
+void zfStaMicFailureHandling(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t da0;
+ u8_t micNotify = 1;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK )
+ {
+ return;
+ }
+
+ zmw_enter_critical_section(dev);
+
+ wd->sta.cmMicFailureCount++;
+
+ if ( wd->sta.cmMicFailureCount == 1 )
+ {
+ zm_debug_msg0("get the first MIC failure");
+ //zfTimerSchedule(dev, ZM_EVENT_CM_TIMER, ZM_TICK_CM_TIMEOUT);
+
+ /* Timer Resolution on WinXP is 15/16 ms */
+ /* Decrease Time offset for <XP> Counter Measure */
+ zfTimerSchedule(dev, ZM_EVENT_CM_TIMER, ZM_TICK_CM_TIMEOUT - ZM_TICK_CM_TIMEOUT_OFFSET);
+ }
+ else if ( wd->sta.cmMicFailureCount == 2 )
+ {
+ zm_debug_msg0("get the second MIC failure");
+ /* reserve 2 second for OS to send MIC failure report to AP */
+ wd->sta.cmDisallowSsidLength = wd->sta.ssidLen;
+ zfMemoryCopy(wd->sta.cmDisallowSsid, wd->sta.ssid, wd->sta.ssidLen);
+ //wd->sta.cmMicFailureCount = 0;
+ zfTimerCancel(dev, ZM_EVENT_CM_TIMER);
+ //zfTimerSchedule(dev, ZM_EVENT_CM_DISCONNECT, ZM_TICK_CM_DISCONNECT);
+
+ /* Timer Resolution on WinXP is 15/16 ms */
+ /* Decrease Time offset for <XP> Counter Measure */
+ zfTimerSchedule(dev, ZM_EVENT_CM_DISCONNECT, ZM_TICK_CM_DISCONNECT - ZM_TICK_CM_DISCONNECT_OFFSET);
+ }
+ else
+ {
+ micNotify = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (micNotify == 1)
+ {
+ da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
+ if ( da0 & 0x01 )
+ {
+ if (wd->zfcbMicFailureNotify != NULL)
+ {
+ wd->zfcbMicFailureNotify(dev, wd->sta.bssid, ZM_MIC_GROUP_ERROR);
+ }
+ }
+ else
+ {
+ if (wd->zfcbMicFailureNotify != NULL)
+ {
+ wd->zfcbMicFailureNotify(dev, wd->sta.bssid, ZM_MIC_PAIRWISE_ERROR);
+ }
+ }
+ }
+}
+
+
+u8_t zfStaBlockWlanScan(zdev_t* dev)
+{
+ u8_t ret=FALSE;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->sta.bChannelScan )
+ {
+ return TRUE;
+ }
+
+ return ret;
+}
+
+void zfStaResetStatus(zdev_t* dev, u8_t bInit)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zfHpDisableBeacon(dev);
+
+ wd->dtim = 1;
+ wd->sta.capability[0] = 0x01;
+ wd->sta.capability[1] = 0x00;
+ /* 802.11h */
+ if (wd->sta.DFSEnable || wd->sta.TPCEnable)
+ wd->sta.capability[1] |= ZM_BIT_0;
+
+ /* release queued packets */
+ for(i=0; i<wd->sta.ibssPSDataCount; i++)
+ {
+ zfwBufFree(dev, wd->sta.ibssPSDataQueue[i], 0);
+ }
+
+ for(i=0; i<wd->sta.staPSDataCount; i++)
+ {
+ zfwBufFree(dev, wd->sta.staPSDataQueue[i], 0);
+ }
+
+ wd->sta.ibssPSDataCount = 0;
+ wd->sta.staPSDataCount = 0;
+ zfZeroMemory((u8_t*) &wd->sta.staPSList, sizeof(struct zsStaPSList));
+
+ wd->sta.wmeConnected = 0;
+ wd->sta.psMgr.tempWakeUp = 0;
+ wd->sta.qosInfo = 0;
+ zfQueueFlush(dev, wd->sta.uapsdQ);
+
+ return;
+
+}
+
+void zfStaIbssMonitoring(zdev_t* dev, u8_t reset)
+{
+ u16_t i;
+ u16_t oppositeCount;
+ struct zsPartnerNotifyEvent event;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ //zm_debug_msg1("zfStaIbssMonitoring %d", wd->sta.oppositeCount);
+
+ zmw_enter_critical_section(dev);
+
+ if ( wd->sta.oppositeCount == 0 )
+ {
+ goto done;
+ }
+
+ if ( wd->sta.bChannelScan )
+ {
+ goto done;
+ }
+
+ oppositeCount = wd->sta.oppositeCount;
+
+ for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++)
+ {
+ if ( oppositeCount == 0 )
+ {
+ break;
+ }
+
+ if ( reset )
+ {
+ wd->sta.oppositeInfo[i].valid = 0;
+ }
+
+ if ( wd->sta.oppositeInfo[i].valid == 0 )
+ {
+ continue;
+ }
+
+ oppositeCount--;
+
+ if ( wd->sta.oppositeInfo[i].aliveCounter )
+ {
+ zm_debug_msg1("Setting alive to ", wd->sta.oppositeInfo[i].aliveCounter);
+
+ zmw_leave_critical_section(dev);
+
+ if ( wd->sta.oppositeInfo[i].aliveCounter != ZM_IBSS_PEER_ALIVE_COUNTER )
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ,
+ (u16_t*)wd->sta.oppositeInfo[i].macAddr, 1, 0, 0);
+ }
+
+ zmw_enter_critical_section(dev);
+ wd->sta.oppositeInfo[i].aliveCounter--;
+ }
+ else
+ {
+ zm_debug_msg0("zfStaIbssMonitoring remove the peer station");
+ zfMemoryCopy(event.bssid, (u8_t *)(wd->sta.bssid), 6);
+ zfMemoryCopy(event.peerMacAddr, wd->sta.oppositeInfo[i].macAddr, 6);
+
+ wd->sta.oppositeInfo[i].valid = 0;
+ wd->sta.oppositeCount--;
+ if (wd->zfcbIbssPartnerNotify != NULL)
+ {
+ zmw_leave_critical_section(dev);
+ wd->zfcbIbssPartnerNotify(dev, 0, &event);
+ zmw_enter_critical_section(dev);
+ }
+ }
+ }
+
+done:
+ if ( reset == 0 )
+ {
+ zfTimerSchedule(dev, ZM_EVENT_IBSS_MONITOR, ZM_TICK_IBSS_MONITOR);
+ }
+
+ zmw_leave_critical_section(dev);
+}
+
+void zfInitPartnerNotifyEvent(zdev_t* dev, zbuf_t* buf, struct zsPartnerNotifyEvent *event)
+{
+ u16_t *peerMacAddr;
+
+ zmw_get_wlan_dev(dev);
+
+ peerMacAddr = (u16_t *)event->peerMacAddr;
+
+ zfMemoryCopy(event->bssid, (u8_t *)(wd->sta.bssid), 6);
+ peerMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
+ peerMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET + 2);
+ peerMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET + 4);
+}
+
+void zfStaInitOppositeInfo(zdev_t* dev)
+{
+ int i;
+
+ zmw_get_wlan_dev(dev);
+
+ for(i=0; i<ZM_MAX_OPPOSITE_COUNT; i++)
+ {
+ wd->sta.oppositeInfo[i].valid = 0;
+ wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER;
+ }
+}
+#ifdef ZM_ENABLE_CENC
+u16_t zfStaAddIeCenc(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ zmw_get_wlan_dev(dev);
+
+ if (wd->sta.cencIe[1] != 0)
+ {
+ zfCopyToIntTxBuffer(dev, buf, wd->sta.cencIe, offset, wd->sta.cencIe[1]+2);
+ offset += (wd->sta.cencIe[1]+2);
+ }
+ return offset;
+}
+#endif //ZM_ENABLE_CENC
+u16_t zfStaProcessAction(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t category, actionDetails;
+ zmw_get_wlan_dev(dev);
+
+ category = zmw_rx_buf_readb(dev, buf, 24);
+ actionDetails = zmw_rx_buf_readb(dev, buf, 25);
+ switch (category)
+ {
+ case 0: //Spectrum Management
+ switch(actionDetails)
+ {
+ case 0: //Measurement Request
+ break;
+ case 1: //Measurement Report
+ //ProcessActionSpectrumFrame_MeasurementReport(Adapter,pActionBody+3);
+ break;
+ case 2: //TPC request
+ //if (wd->sta.TPCEnable)
+ // zfStaUpdateDot11HTPC(dev, buf);
+ break;
+ case 3: //TPC report
+ //if (wd->sta.TPCEnable)
+ // zfStaUpdateDot11HTPC(dev, buf);
+ break;
+ case 4: //Channel Switch Announcement
+ if (wd->sta.DFSEnable)
+ zfStaUpdateDot11HDFS(dev, buf);
+ break;
+ default:
+ zm_debug_msg1("Action Frame contain not support action field ", actionDetails);
+ break;
+ }
+ break;
+ case ZM_WLAN_BLOCK_ACK_ACTION_FRAME:
+ zfAggBlockAckActionFrame(dev, buf);
+ break;
+ case 17: //Qos Management
+ break;
+ }
+
+ return 0;
+}
+
+/* Determine the time not send beacon , if more than some value ,
+ re-write the beacon start address */
+void zfReWriteBeaconStartAddress(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->tickIbssSendBeacon++; // Increase 1 per 10ms .
+ zmw_leave_critical_section(dev);
+
+ if ( wd->tickIbssSendBeacon == 40 )
+ {
+// DbgPrint("20070727");
+ zfHpEnableBeacon(dev, ZM_MODE_IBSS, wd->beaconInterval, wd->dtim, (u8_t)wd->sta.atimWindow);
+ zmw_enter_critical_section(dev);
+ wd->tickIbssSendBeacon = 0;
+ zmw_leave_critical_section(dev);
+ }
+}
+
+struct zsTkipSeed* zfStaGetRxSeed(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t keyIndex;
+ u8_t da0;
+
+ zmw_get_wlan_dev(dev);
+
+ /* if need not check MIC, return NULL */
+ if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))||
+ (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) )
+ {
+ return NULL;
+ }
+
+ da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
+
+ if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) == 0x80)
+ keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+5); /* Qos Packet*/
+ else
+ keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+3); /* normal Packet*/
+ keyIndex = (keyIndex & 0xc0) >> 6;
+
+ return (&wd->sta.rxSeed[keyIndex]);
+}
+
+void zfStaEnableSWEncryption(zdev_t *dev, u8_t value)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.SWEncryptEnable = value;
+ zfHpSWDecrypt(dev, 1);
+ zfHpSWEncrypt(dev, 1);
+}
+
+void zfStaDisableSWEncryption(zdev_t *dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.SWEncryptEnable = 0;
+ zfHpSWDecrypt(dev, 0);
+ zfHpSWEncrypt(dev, 0);
+}
+
+u16_t zfComputeBssInfoWeightValue(zdev_t *dev, u8_t isBMode, u8_t isHT, u8_t isHT40, u8_t signalStrength)
+{
+ u8_t weightOfB = 0;
+ u8_t weightOfAGBelowThr = 0;
+ u8_t weightOfAGUpThr = 15;
+ u8_t weightOfN20BelowThr = 15;
+ u8_t weightOfN20UpThr = 30;
+ u8_t weightOfN40BelowThr = 16;
+ u8_t weightOfN40UpThr = 32;
+
+ zmw_get_wlan_dev(dev);
+
+ if( isBMode == 0 )
+ return (signalStrength + weightOfB); // pure b mode , do not add the weight value for this AP !
+ else
+ {
+ if( isHT == 0 && isHT40 == 0 )
+ { // a , g , b/g mode ! add the weight value 15 for this AP if it's signal strength is more than some value !
+ if( signalStrength < 18 ) // -77 dBm
+ return signalStrength + weightOfAGBelowThr;
+ else
+ return (signalStrength + weightOfAGUpThr);
+ }
+ else if( isHT == 1 && isHT40 == 0 )
+ { // 80211n mode use 20MHz
+ if( signalStrength < 23 ) // -72 dBm
+ return (signalStrength + weightOfN20BelowThr);
+ else
+ return (signalStrength + weightOfN20UpThr);
+ }
+ else // isHT == 1 && isHT40 == 1
+ { // 80211n mode use 40MHz
+ if( signalStrength < 16 ) // -79 dBm
+ return (signalStrength + weightOfN40BelowThr);
+ else
+ return (signalStrength + weightOfN40UpThr);
+ }
+ }
+}
+
+u16_t zfStaAddIbssAdditionalIE(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<wd->sta.ibssAdditionalIESize; i++)
+ {
+ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ibssAdditionalIE[i]);
+ }
+
+ return offset;
+}
diff --git a/drivers/staging/otus/80211core/coid.c b/drivers/staging/otus/80211core/coid.c
new file mode 100644
index 000000000000..6007f3131f8f
--- /dev/null
+++ b/drivers/staging/otus/80211core/coid.c
@@ -0,0 +1,2695 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : iod.c */
+/* */
+/* Abstract */
+/* This module contains OID functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#include "../hal/hpreg.h"
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiWlanQueryMacAddress */
+/* Query OWN MAC address. */
+/* */
+/* INPUTS */
+/* addr : for return MAC address */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+void zfiWlanQueryMacAddress(zdev_t* dev, u8_t* addr)
+{
+ u16_t vapId = 0;
+ zmw_get_wlan_dev(dev);
+
+ vapId = zfwGetVapId(dev);
+
+ addr[0] = (u8_t)(wd->macAddr[0] & 0xff);
+ addr[1] = (u8_t)(wd->macAddr[0] >> 8);
+ addr[2] = (u8_t)(wd->macAddr[1] & 0xff);
+ addr[3] = (u8_t)(wd->macAddr[1] >> 8);
+ addr[4] = (u8_t)(wd->macAddr[2] & 0xff);
+ if (vapId == 0xffff)
+ addr[5] = (u8_t)(wd->macAddr[2] >> 8);
+ else
+ {
+#ifdef ZM_VAPMODE_MULTILE_SSID
+ addr[5] = (u8_t)(wd->macAddr[2] >> 8); // Multiple SSID
+#else
+ addr[5] = vapId + 1 + (u8_t)(wd->macAddr[2] >> 8); //VAP
+#endif
+ }
+
+ return;
+}
+
+void zfiWlanQueryBssList(zdev_t* dev, struct zsBssList* pBssList)
+{
+ struct zsBssInfo* pBssInfo;
+ struct zsBssInfo* pDstBssInfo;
+ u8_t i;
+ u8_t* pMemList;
+ u8_t* pMemInfo;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ pMemList = (u8_t*) pBssList;
+ pMemInfo = pMemList + sizeof(struct zsBssList);
+ pBssList->head = (struct zsBssInfo*) pMemInfo;
+
+ zmw_enter_critical_section(dev);
+
+ pBssInfo = wd->sta.bssList.head;
+ pDstBssInfo = (struct zsBssInfo*) pMemInfo;
+ pBssList->bssCount = wd->sta.bssList.bssCount;
+
+ for( i=0; i<wd->sta.bssList.bssCount; i++ )
+ {
+ zfMemoryCopy((u8_t*)pDstBssInfo, (u8_t*)pBssInfo,
+ sizeof(struct zsBssInfo));
+
+ if ( pBssInfo->next != NULL )
+ {
+ pBssInfo = pBssInfo->next;
+ pDstBssInfo->next = pDstBssInfo + 1;
+ pDstBssInfo++;
+ }
+ else
+ {
+ zm_assert(i==(wd->sta.bssList.bssCount-1));
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zfScanMgrScanAck(dev);
+}
+
+void zfiWlanQueryBssListV1(zdev_t* dev, struct zsBssListV1* bssListV1)
+{
+ struct zsBssInfo* pBssInfo;
+ //struct zsBssInfo* pDstBssInfo;
+ u8_t i, j, bdrop = 0, k = 0, Same_Count = 0;
+ u8_t bssid[6];
+ //u8_t* pMemList;
+ //u8_t* pMemInfo;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ bssListV1->bssCount = wd->sta.bssList.bssCount;
+
+ pBssInfo = wd->sta.bssList.head;
+ ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);
+
+ for( i=0; i<wd->sta.bssList.bssCount; i++ )
+ {
+ bdrop = 0;
+ if ( zfStaIsConnected(dev)
+ && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) )
+ {
+ for (j = 0; j < 6; j++)
+ {
+ if ( pBssInfo->bssid[j] != bssid[j] )
+ {
+ break;
+ }
+ }
+
+ if ( (j == 6)
+ &&((pBssInfo->ssid[1] == wd->sta.ssidLen) || (pBssInfo->ssid[1] == 0) )&& (pBssInfo->frequency == wd->frequency) )
+ {
+ if(pBssInfo->ssid[1] == 0)
+ pBssInfo->ssid[1] = wd->sta.ssidLen;
+
+ if(Same_Count == 0)
+ {//First meet
+ Same_Count++;
+ }
+ else
+ {//same one
+ bdrop = 1;
+ bssListV1->bssCount--;
+ }
+
+ }
+ }
+
+ if (bdrop == 0)
+ {
+ zfMemoryCopy((u8_t*)(&bssListV1->bssInfo[k]), (u8_t*)pBssInfo,
+ sizeof(struct zsBssInfo));
+
+ if(Same_Count == 1)
+ {
+ zfMemoryCopy(&(bssListV1->bssInfo[k].ssid[2]), wd->sta.ssid, wd->sta.ssidLen);
+ Same_Count++;
+ }
+
+ k++;
+ }
+
+ if ( pBssInfo->next != NULL )
+ {
+ pBssInfo = pBssInfo->next;
+ }
+ else
+ {
+ zm_assert(i==(wd->sta.bssList.bssCount-1));
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zfScanMgrScanAck(dev);
+}
+
+void zfiWlanQueryAdHocCreatedBssDesc(zdev_t* dev, struct zsBssInfo *pBssInfo)
+{
+ zmw_get_wlan_dev(dev);
+
+ zfMemoryCopy((u8_t *)pBssInfo, (u8_t *)&wd->sta.ibssBssDesc, sizeof(struct zsBssInfo));
+}
+
+u8_t zfiWlanQueryAdHocIsCreator(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->sta.ibssBssIsCreator;
+}
+
+u32_t zfiWlanQuerySupportMode(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->supportMode;
+}
+
+u32_t zfiWlanQueryTransmitPower(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ u32_t ret = 0;
+
+ if (zfStaIsConnected(dev)) {
+ ret = wd->sta.connPowerInHalfDbm;
+ } else {
+ ret = zfHpGetTransmitPower(dev);
+ }
+
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiWlanFlushBssList */
+/* Flush BSSID List. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2006.12 */
+/* */
+/************************************************************************/
+void zfiWlanFlushBssList(zdev_t* dev)
+{
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ /* Call zfBssInfoRefresh() twice to remove all entry */
+ zfBssInfoRefresh(dev, 1);
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetWlanMode(zdev_t* dev, u8_t wlanMode)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->ws.wlanMode = wlanMode;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetAuthenticationMode(zdev_t* dev, u8_t authMode)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->ws.authMode = authMode;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetWepStatus(zdev_t* dev, u8_t wepStatus)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->ws.wepStatus = wepStatus;
+ zmw_leave_critical_section(dev);
+
+}
+
+void zfiWlanSetSSID(zdev_t* dev, u8_t* ssid, u8_t ssidLength)
+{
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( ssidLength <= 32 )
+ {
+ zmw_enter_critical_section(dev);
+
+ wd->ws.ssidLen = ssidLength;
+ zfMemoryCopy(wd->ws.ssid, ssid, ssidLength);
+
+ if ( ssidLength < 32 )
+ {
+ wd->ws.ssid[ssidLength] = 0;
+ }
+
+ wd->ws.probingSsidList[0].ssidLen = ssidLength;
+ zfMemoryCopy(wd->ws.probingSsidList[0].ssid, ssid, ssidLength);
+ for (i=1; i<ZM_MAX_PROBE_HIDDEN_SSID_SIZE; i++)
+ {
+ wd->ws.probingSsidList[i].ssidLen = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+ }
+}
+
+void zfiWlanSetFragThreshold(zdev_t* dev, u16_t fragThreshold)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (fragThreshold == 0)
+ { /* fragmentation is disabled */
+ wd->fragThreshold = 32767;
+ }
+ else if (fragThreshold < 256)
+ {
+ /* Minimum fragment threshold */
+ wd->fragThreshold = 256;
+ }
+ else if (fragThreshold > 2346)
+ {
+ wd->fragThreshold = 2346;
+ }
+ else
+ {
+ wd->fragThreshold = fragThreshold & 0xfffe;
+ }
+
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetRtsThreshold(zdev_t* dev, u16_t rtsThreshold)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->rtsThreshold = rtsThreshold;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetFrequency(zdev_t* dev, u32_t frequency, u8_t bImmediate)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( bImmediate )
+ {
+ zmw_enter_critical_section(dev);
+ wd->frequency = (u16_t) (frequency/1000);
+ zmw_leave_critical_section(dev);
+ zfCoreSetFrequency(dev, wd->frequency);
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ if( frequency == 0 )
+ { // Auto select clean channel depend on wireless environment !
+ wd->ws.autoSetFrequency = 0;
+ }
+ wd->ws.frequency = (u16_t) (frequency/1000);
+ zmw_leave_critical_section(dev);
+ }
+}
+
+void zfiWlanSetBssid(zdev_t* dev, u8_t* bssid)
+{
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ for (i=0; i<6; i++)
+ {
+ wd->ws.desiredBssid[i] = bssid[i];
+ }
+ wd->ws.bDesiredBssid = TRUE;
+ zmw_leave_critical_section(dev);
+
+}
+
+void zfiWlanSetBeaconInterval(zdev_t* dev,
+ u16_t beaconInterval,
+ u8_t bImmediate)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( bImmediate )
+ {
+ zmw_enter_critical_section(dev);
+ wd->beaconInterval = beaconInterval;
+ zmw_leave_critical_section(dev);
+
+ /* update beacon interval here */
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ wd->ws.beaconInterval = beaconInterval;
+ zmw_leave_critical_section(dev);
+ }
+}
+
+
+void zfiWlanSetDtimCount(zdev_t* dev, u8_t dtim)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if (dtim > 0)
+ {
+ wd->ws.dtim = dtim;
+ }
+ zmw_leave_critical_section(dev);
+}
+
+
+void zfiWlanSetAtimWindow(zdev_t* dev, u16_t atimWindow, u8_t bImmediate)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( bImmediate )
+ {
+ zmw_enter_critical_section(dev);
+ wd->sta.atimWindow = atimWindow;
+ zmw_leave_critical_section(dev);
+
+ /* atim window here */
+ }
+ else
+ {
+ zmw_enter_critical_section(dev);
+ wd->ws.atimWindow = atimWindow;
+ zmw_leave_critical_section(dev);
+ }
+}
+
+
+void zfiWlanSetEncryMode(zdev_t* dev, u8_t encryMode)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ /* Hostapd Issue */
+ if ((wd->ws.encryMode != ZM_AES) && (wd->ws.encryMode != ZM_TKIP))
+ wd->ws.encryMode = encryMode;
+ }
+ else
+ wd->ws.encryMode = encryMode;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetDefaultKeyId(zdev_t* dev, u8_t keyId)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.keyId = keyId;
+}
+
+u8_t zfiWlanQueryIsPKInstalled(zdev_t *dev, u8_t *staMacAddr)
+{
+ u8_t isInstalled = 0;
+
+#if 1
+//#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ u8_t res, peerIdx;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t *)staMacAddr, &peerIdx);
+ if( res == 0 )
+ {
+ isInstalled = wd->sta.oppositeInfo[peerIdx].pkInstalled;
+ }
+ zmw_leave_critical_section(dev);
+//#endif
+#endif
+
+ return isInstalled;
+}
+
+u8_t zfiWlanSetKey(zdev_t* dev, struct zsKeyInfo keyInfo)
+{
+ u16_t broadcast[3] = {0xffff, 0xffff, 0xffff};
+ u32_t* key;
+ u8_t encryMode = ZM_NO_WEP;
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ u8_t encryType = ZM_NO_WEP;
+#endif
+ u8_t micKey[16];
+ u16_t id = 0;
+ u8_t vapId, i, addr[6];
+ u8_t userIdx=0;
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ /* Determine opposite exist or not */
+ u8_t res, peerIdx;
+// u8_t userIdx=0;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->sta.ibssWpa2Psk == 1 )
+ {
+ zmw_enter_critical_section(dev);
+ res = zfStaFindOppositeByMACAddr(dev, (u16_t*)keyInfo.macAddr, &peerIdx);
+ if( res == 0 )
+ {
+ userIdx = peerIdx;
+ if ( wd->sta.oppositeInfo[userIdx].camIdx == 0xff )
+ wd->sta.oppositeInfo[userIdx].camIdx = userIdx;
+ }
+ zmw_leave_critical_section(dev);
+ }
+#else
+ zmw_get_wlan_dev(dev);
+#endif
+
+ if ( keyInfo.flag & ZM_KEY_FLAG_AUTHENTICATOR )
+ { /* set key by authenticator */
+ /* set pairwise key */
+ if (keyInfo.flag & ZM_KEY_FLAG_PK)
+ {
+ /* Find STA's information */
+ if ((id = zfApFindSta(dev, keyInfo.macAddr)) == 0xffff)
+ {
+ /* Can't STA in the staTable */
+ return ZM_STATUS_FAILURE;
+ }
+
+ wd->ap.staTable[id].iv16 = 0;
+ wd->ap.staTable[id].iv32 = 0;
+
+ if (keyInfo.keyLength == 32)
+ { /* TKIP */
+ //u8_t KeyRsc[6] = {0, 0, 0, 0, 0, 0};
+
+ /* In the current AP mode, we set KeyRsc to zero */
+ //zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
+ // &(wd->ap.staTable[id].txSeed), KeyRsc);
+ //zfTkipInit(keyInfo.key, (u8_t*) keyInfo.macAddr,
+ // &(wd->ap.staTable[id].rxSeed), KeyRsc);
+#ifdef ZM_ENABLE_CENC
+ if (keyInfo.flag & ZM_KEY_FLAG_CENC)
+ {
+ zm_debug_msg0("Set CENC pairwise Key");
+
+ wd->ap.staTable[id].encryMode = ZM_CENC;
+
+ /* Reset txiv and rxiv */
+ wd->ap.staTable[id].txiv[0] = 0x5c365c37;
+ wd->ap.staTable[id].txiv[1] = 0x5c365c36;
+ wd->ap.staTable[id].txiv[2] = 0x5c365c36;
+ wd->ap.staTable[id].txiv[3] = 0x5c365c36;
+
+ wd->ap.staTable[id].rxiv[0] = 0x5c365c36;
+ wd->ap.staTable[id].rxiv[1] = 0x5c365c36;
+ wd->ap.staTable[id].rxiv[2] = 0x5c365c36;
+ wd->ap.staTable[id].rxiv[3] = 0x5c365c36;
+
+ /* Set Key Index */
+ wd->ap.staTable[id].cencKeyIdx = keyInfo.keyIndex;
+
+ //zfCoreSetKey(dev, id+1, 1, ZM_CENC, (u16_t *)keyInfo.macAddr,
+ // (u32_t*) &keyInfo.key[16]);
+ }
+ else
+#endif //ZM_ENABLE_CENC
+ {
+ wd->ap.staTable[id].encryMode = ZM_TKIP;
+
+ zfMemoryCopy(micKey, &keyInfo.key[16], 8);
+ zfMemoryCopy(&micKey[8], &keyInfo.key[24], 8);
+
+ //zfCoreSetKey(dev, id+1, 1, ZM_TKIP, (u16_t *)keyInfo.macAddr,
+ // (u32_t*) micKey);
+
+ /* For fragmentation, we use software MIC */
+ zfMemoryCopy((u8_t *)&(wd->ap.staTable[id].txMicKey), &(keyInfo.key[16]), 8);
+ zfMemoryCopy((u8_t *)&(wd->ap.staTable[id].rxMicKey), &(keyInfo.key[24]), 8);
+
+ }
+ }
+ else if (keyInfo.keyLength == 16)
+ { /* AES */
+ wd->ap.staTable[id].encryMode = ZM_AES;
+ }
+ else if (keyInfo.keyLength == 0)
+ {
+ /* Clear Key Info */
+ zfApClearStaKey(dev, (u16_t *)keyInfo.macAddr);
+
+ return ZM_STATUS_SUCCESS;
+ }
+ else
+ {
+ return ZM_STATUS_FAILURE;
+ }
+
+ //zfCoreSetKey(dev, id+1, 0, wd->ap.staTable[id].encryMode,
+ // (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
+ zfHpSetApPairwiseKey(dev, (u16_t *)keyInfo.macAddr,
+ wd->ap.staTable[id].encryMode, (u32_t*) keyInfo.key,
+ (u32_t*) &keyInfo.key[16], id+1);
+ wd->ap.staTable[id].keyIdx = id + 1 + 4;
+ }
+ else if (keyInfo.flag & ZM_KEY_FLAG_GK)
+ {
+ vapId = keyInfo.vapId;
+
+ wd->ap.iv16[vapId] = 0;
+ wd->ap.iv32[vapId] = 0;
+
+ if (keyInfo.keyLength == 32)
+ { /* TKIP */
+ //u8_t KeyRsc[6] = {0, 0, 0, 0, 0, 0};
+
+ //zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
+ // &(wd->ap.bcSeed), KeyRsc);
+#ifdef ZM_ENABLE_CENC
+ if (keyInfo.flag & ZM_KEY_FLAG_CENC)
+ {
+ encryMode = ZM_CENC;
+ zm_debug_msg0("Set CENC group Key");
+
+ /* Reset txiv and rxiv */
+ wd->ap.txiv[vapId][0] = 0x5c365c36;
+ wd->ap.txiv[vapId][1] = 0x5c365c36;
+ wd->ap.txiv[vapId][2] = 0x5c365c36;
+ wd->ap.txiv[vapId][3] = 0x5c365c36;
+
+ //zfCoreSetKey(dev, 0, 1, ZM_CENC, keyInfo.vapAddr,
+ // (u32_t*) &keyInfo.key[16]);
+ key = (u32_t*) keyInfo.key;
+ }
+ else
+#endif //ZM_ENABLE_CENC
+ {
+ encryMode = ZM_TKIP;
+ key = (u32_t *)keyInfo.key;
+
+ /* set MIC key to HMAC */
+ //zfCoreSetKey(dev, 0, 1, ZM_TKIP, broadcast,
+ // (u32_t*) (&keyInfo.key[16]));
+ //zfCoreSetKey(dev, 0, 1, ZM_TKIP, keyInfo.vapAddr,
+ // (u32_t*) (&keyInfo.key[16]));
+
+ zfMicSetKey(&(keyInfo.key[16]), &(wd->ap.bcMicKey[0]));
+ key = (u32_t*) keyInfo.key;
+ }
+ }
+ else if (keyInfo.keyLength == 16)
+ { /* AES */
+ encryMode = ZM_AES;
+ key = (u32_t *)keyInfo.key;
+ zm_debug_msg0("CWY - Set AES Group Key");
+ }
+ else if (keyInfo.keyLength == 0)
+ {
+ /* Clear Key Info */
+ zfApClearStaKey(dev, broadcast);
+
+ /* Turn off WEP bit in the capability field */
+ wd->ap.capab[vapId] &= 0xffef;
+
+ return ZM_STATUS_SUCCESS;
+ }
+ else
+ { /* WEP */
+ if (keyInfo.keyLength == 5)
+ {
+ encryMode = ZM_WEP64;
+ }
+ else if (keyInfo.keyLength == 13)
+ {
+ encryMode = ZM_WEP128;
+ }
+ else if (keyInfo.keyLength == 29)
+ {
+ encryMode = ZM_WEP256;
+ }
+
+ key = (u32_t*) keyInfo.key;
+ }
+
+ // Modification for CAM not support VAP search
+ //zfCoreSetKey(dev, 0, 0, encryMode, broadcast, key);
+ //zfCoreSetKey(dev, 0, 0, encryMode, wd->macAddr, key);
+ //zfCoreSetKey(dev, 0, 0, encryMode, keyInfo.vapAddr, key);
+ zfHpSetApGroupKey(dev, wd->macAddr, encryMode,
+ key, (u32_t*) &keyInfo.key[16], vapId);
+
+ //zfiWlanSetEncryMode(dev, encryMode);
+ wd->ws.encryMode = encryMode;
+
+ /* set the multicast address encryption type */
+ wd->ap.encryMode[vapId] = encryMode;
+
+ /* set the multicast key index */
+ wd->ap.bcKeyIndex[vapId] = keyInfo.keyIndex;
+ wd->ap.bcHalKeyIdx[vapId] = vapId + 60;
+
+ /* Turn on WEP bit in the capability field */
+ wd->ap.capab[vapId] |= 0x10;
+ }
+ }
+ else
+ { /* set by supplicant */
+
+ if ( keyInfo.flag & ZM_KEY_FLAG_PK )
+ { /* set pairwise key */
+
+ //zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
+ // &wd->sta.txSeed, keyInfo.initIv);
+ //zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
+ // &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ if ( wd->sta.ibssWpa2Psk == 1 )
+ {
+ /* unicast -- > pairwise key */
+ wd->sta.oppositeInfo[userIdx].iv16 = 0;
+ wd->sta.oppositeInfo[userIdx].iv32 = 0;
+ }
+ else
+ {
+ wd->sta.iv16 = 0;
+ wd->sta.iv32 = 0;
+ }
+
+ wd->sta.oppositeInfo[userIdx].pkInstalled = 1;
+#else
+ wd->sta.iv16 = 0;
+ wd->sta.iv32 = 0;
+
+ wd->sta.oppositeInfo[userIdx].pkInstalled = 1;
+#endif
+
+ if ( keyInfo.keyLength == 32 )
+ { /* TKIP */
+ zfTkipInit(keyInfo.key, (u8_t*) wd->macAddr,
+ &wd->sta.txSeed, keyInfo.initIv);
+ zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
+ &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);
+
+#ifdef ZM_ENABLE_CENC
+ if (keyInfo.flag & ZM_KEY_FLAG_CENC)
+ {
+ zm_debug_msg0("Set CENC pairwise Key");
+
+ wd->sta.encryMode = ZM_CENC;
+
+ /* Reset txiv and rxiv */
+ wd->sta.txiv[0] = 0x5c365c36;
+ wd->sta.txiv[1] = 0x5c365c36;
+ wd->sta.txiv[2] = 0x5c365c36;
+ wd->sta.txiv[3] = 0x5c365c36;
+
+ wd->sta.rxiv[0] = 0x5c365c37;
+ wd->sta.rxiv[1] = 0x5c365c36;
+ wd->sta.rxiv[2] = 0x5c365c36;
+ wd->sta.rxiv[3] = 0x5c365c36;
+
+ /* Set Key Index */
+ wd->sta.cencKeyId = keyInfo.keyIndex;
+
+ //zfCoreSetKey(dev, id+1, 1, ZM_CENC, (u16_t *)keyInfo.macAddr,
+ // (u32_t*) &keyInfo.key[16]);
+ }
+ else
+#endif //ZM_ENABLE_CENC
+ {
+ wd->sta.encryMode = ZM_TKIP;
+
+ //zfCoreSetKey(dev, 0, 1, ZM_TKIP, wd->sta.bssid,
+ // (u32_t*) &keyInfo.key[16]);
+
+ zfMicSetKey(&keyInfo.key[16], &wd->sta.txMicKey);
+ zfMicSetKey(&keyInfo.key[24],
+ &wd->sta.rxMicKey[keyInfo.keyIndex]);
+ }
+ }
+ else if ( keyInfo.keyLength == 16 )
+ { /* AES */
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ if ( wd->sta.ibssWpa2Psk == 1 )
+ {
+ wd->sta.oppositeInfo[userIdx].encryMode = ZM_AES;
+ encryType = wd->sta.oppositeInfo[userIdx].encryMode;
+ }
+ else
+ {
+ wd->sta.encryMode = ZM_AES;
+ encryType = wd->sta.encryMode;
+ }
+#else
+ wd->sta.encryMode = ZM_AES;
+#endif
+ }
+ else
+ {
+ return ZM_STATUS_FAILURE;
+ }
+
+ /* user 0 */
+ //zfCoreSetKey(dev, 0, 0, wd->sta.encryMode,
+ // wd->sta.bssid, (u32_t*) keyInfo.key);
+ //zfHpSetStaPairwiseKey(dev, wd->sta.bssid, wd->sta.encryMode,
+ // (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ if ( (keyInfo.keyLength==16) && (wd->sta.ibssWpa2Psk==1) )
+ { /* If not AES-CCMP and ibss network , use traditional */
+ zfHpSetPerUserKey(dev,
+ userIdx,
+ keyInfo.keyIndex, // key id == 0 ( Pairwise key = 0 )
+ (u8_t*)keyInfo.macAddr, // RX need Source Address ( Address 2 )
+ encryType,
+// wd->sta.encryMode,
+ (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+
+ wd->sta.oppositeInfo[userIdx].wpaState = ZM_STA_WPA_STATE_PK_OK ;
+ }
+ else
+ {/* Big Endian and Little Endian Compatibility */
+ for (i = 0; i < 3; i++)
+ {
+ addr[2 * i] = wd->sta.bssid[i] & 0xff;
+ addr[2 * i + 1] = wd->sta.bssid[i] >> 8;
+ }
+ zfHpSetPerUserKey(dev,
+ ZM_USER_KEY_PK, // user id
+ 0, // key id
+ addr,//(u8_t *)wd->sta.bssid,
+ wd->sta.encryMode,
+ (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+
+ wd->sta.keyId = 4;
+ }
+#else
+ /* Big Endian and Little Endian Compatibility */
+ for (i = 0; i < 3; i++)
+ {
+ addr[2 * i] = wd->sta.bssid[i] & 0xff;
+ addr[2 * i + 1] = wd->sta.bssid[i] >> 8;
+ }
+ zfHpSetPerUserKey(dev,
+ ZM_USER_KEY_PK, // user id
+ 0, // key id
+ addr,//(u8_t *)wd->sta.bssid,
+ wd->sta.encryMode,
+ (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+
+ wd->sta.keyId = 4;
+#endif
+
+ wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
+ }
+ else if ( keyInfo.flag & ZM_KEY_FLAG_GK )
+ { /* set group key */
+
+ zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
+ &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);
+
+ if ( keyInfo.keyLength == 32 )
+ { /* TKIP */
+#ifdef ZM_ENABLE_CENC
+ if (keyInfo.flag & ZM_KEY_FLAG_CENC)
+ {
+ encryMode = ZM_CENC;
+ zm_debug_msg0("Set CENC group Key");
+
+ /* Reset txiv and rxiv */
+ wd->sta.rxivGK[0] = 0x5c365c36;
+ wd->sta.rxivGK[1] = 0x5c365c36;
+ wd->sta.rxivGK[2] = 0x5c365c36;
+ wd->sta.rxivGK[3] = 0x5c365c36;
+
+ //zfCoreSetKey(dev, 0, 1, ZM_CENC, keyInfo.vapAddr,
+ // (u32_t*) &keyInfo.key[16]);
+ key = (u32_t*) keyInfo.key;
+ }
+ else
+#endif //ZM_ENABLE_CENC
+ {
+ encryMode = ZM_TKIP;
+ key = (u32_t*) wd->sta.rxSeed[keyInfo.keyIndex].tk;
+
+ if ( !(keyInfo.flag & ZM_KEY_FLAG_INIT_IV) )
+ {
+ wd->sta.rxSeed[keyInfo.keyIndex].iv16 = 0;
+ wd->sta.rxSeed[keyInfo.keyIndex].iv32 = 0;
+ }
+
+ /* set MIC key to HMAC */
+ //zfCoreSetKey(dev, 8, 1, ZM_TKIP, broadcast,
+ // (u32_t*) (&keyInfo.key[16]));
+
+ zfMicSetKey(&keyInfo.key[24],
+ &wd->sta.rxMicKey[keyInfo.keyIndex]);
+ }
+ }
+ else if ( keyInfo.keyLength == 16 )
+ { /* AES */
+ encryMode = ZM_AES;
+ //key = (u32_t*) wd->sta.rxSeed[keyInfo.keyIndex].tk;
+ }
+ else
+ { /* WEP */
+ if ( keyInfo.keyLength == 5 )
+ {
+ encryMode = ZM_WEP64;
+ }
+ else if ( keyInfo.keyLength == 13 )
+ {
+ encryMode = ZM_WEP128;
+ }
+ else if ( keyInfo.keyLength == 29 )
+ {
+ encryMode = ZM_WEP256;
+ }
+
+ key = (u32_t*) keyInfo.key;
+ }
+
+ /* user 8 */
+ //zfCoreSetKey(dev, 8, 0, encryMode, broadcast, key);
+ //zfHpSetStaGroupKey(dev, broadcast, encryMode,
+ // (u32_t*) keyInfo.key, (u32_t*) (&keyInfo.key[16]));
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ if ( (keyInfo.keyLength==16) && (wd->sta.ibssWpa2Psk==1) )
+ {/* If not AES-CCMP and ibss network , use traditional */
+ zfHpSetPerUserKey(dev,
+ userIdx,
+ keyInfo.keyIndex, // key id
+ // (u8_t *)broadcast, // for only 2 stations IBSS netwrl ( A2 )
+ (u8_t*)keyInfo.macAddr, // for multiple ( > 2 ) stations IBSS network ( A2 )
+ encryMode,
+ (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+ }
+ else
+ {
+ zfHpSetPerUserKey(dev,
+ ZM_USER_KEY_GK, // user id
+ 0, // key id
+ (u8_t *)broadcast,
+ encryMode,
+ (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+
+ wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
+ }
+#else
+ zfHpSetPerUserKey(dev,
+ ZM_USER_KEY_GK, // user id
+ 0, // key id
+ (u8_t *)broadcast,
+ encryMode,
+ (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+
+ wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
+#endif
+ }
+ else
+ { /* legacy WEP */
+ zm_debug_msg0("legacy WEP");
+
+ if ( keyInfo.keyIndex >= 4 )
+ {
+ return ZM_STATUS_FAILURE;
+ }
+
+ if ( keyInfo.keyLength == 5 )
+ {
+ zm_debug_msg0("WEP 64");
+
+ encryMode = ZM_WEP64;
+ }
+ else if ( keyInfo.keyLength == 13 )
+ {
+ zm_debug_msg0("WEP 128");
+
+ encryMode = ZM_WEP128;
+ }
+ else if ( keyInfo.keyLength == 32 )
+ {
+ /* TKIP */
+ #if 0
+ // Don't reset the IV since some AP would fail in IV check and drop our connection
+ if ( wd->sta.wpaState != ZM_STA_WPA_STATE_PK_OK )
+ {
+ wd->sta.iv16 = 0;
+ wd->sta.iv32 = 0;
+ }
+ #endif
+
+ encryMode = ZM_TKIP;
+
+ zfTkipInit(keyInfo.key, (u8_t*) wd->sta.bssid,
+ &wd->sta.rxSeed[keyInfo.keyIndex], keyInfo.initIv);
+ zfMicSetKey(&keyInfo.key[24],
+ &wd->sta.rxMicKey[keyInfo.keyIndex]);
+ }
+ else if ( keyInfo.keyLength == 16 )
+ {
+ /* AES */
+ #if 0
+ // Don't reset the IV since some AP would fail in IV check and drop our connection
+ if ( wd->sta.wpaState != ZM_STA_WPA_STATE_PK_OK )
+ {
+ /* broadcast -- > group key */
+ /* Only initialize when set our default key ! */
+ wd->sta.iv16 = 0;
+ wd->sta.iv32 = 0;
+ }
+ #endif
+
+ encryMode = ZM_AES;
+ }
+ else if ( keyInfo.keyLength == 29 )
+ {
+ zm_debug_msg0("WEP 256");
+
+ encryMode = ZM_WEP256;
+ //zfCoreSetKey(dev, 64, 1, wd->sta.encryMode,
+ // wd->sta.bssid, (u32_t*) (&keyInfo.key[16]));
+ }
+ else
+ {
+ return ZM_STATUS_FAILURE;
+ }
+
+ {
+ u8_t i;
+
+ zm_debug_msg0("key = ");
+ for(i = 0; i < keyInfo.keyLength; i++)
+ {
+ zm_debug_msg2("", keyInfo.key[i]);
+ }
+ }
+
+ if ( keyInfo.flag & ZM_KEY_FLAG_DEFAULT_KEY )
+ {
+ //for WEP default key 1~3 and ATOM platform--CWYang(+)
+ vapId = 0;
+ wd->ap.bcHalKeyIdx[vapId] = keyInfo.keyIndex;
+ wd->ap.bcKeyIndex[vapId] = keyInfo.keyIndex;
+ wd->sta.keyId = keyInfo.keyIndex;
+ }
+
+ if(encryMode == ZM_TKIP)
+ {
+ if(wd->TKIP_Group_KeyChanging == 0x1)
+ {
+ zm_debug_msg0("Countermeasure : Cancel Old Timer ");
+ zfTimerCancel(dev, ZM_EVENT_SKIP_COUNTERMEASURE);
+ }
+ else
+ {
+ zm_debug_msg0("Countermeasure : Create New Timer ");
+ }
+
+ wd->TKIP_Group_KeyChanging = 0x1;
+ zfTimerSchedule(dev, ZM_EVENT_SKIP_COUNTERMEASURE, 150);
+ }
+
+
+
+ //------------------------------------------------------------------------
+
+ /* use default key */
+ //zfCoreSetKey(dev, ZM_USER_KEY_DEFAULT+keyInfo.keyIndex, 0,
+ // wd->sta.encryMode, wd->sta.bssid, (u32_t*) keyInfo.key);
+
+ if ( encryMode == ZM_TKIP ||
+ encryMode == ZM_AES )
+ {
+ zfHpSetDefaultKey(dev, keyInfo.keyIndex, encryMode,
+ (u32_t*) keyInfo.key, (u32_t*) &keyInfo.key[16]);
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ if ( (keyInfo.keyLength==16) && (wd->sta.ibssWpa2Psk==1) )
+ {/* If not AES-CCMP and ibss network , use traditional */
+ wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
+ }
+ else
+ {
+ if (wd->sta.wpaState == ZM_STA_WPA_STATE_PK_OK)
+ wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
+ else
+ {
+ wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
+ wd->sta.encryMode = encryMode;
+ wd->ws.encryMode = encryMode;
+ }
+ }
+#else
+ if (wd->sta.wpaState == ZM_STA_WPA_STATE_PK_OK)
+ wd->sta.wpaState = ZM_STA_WPA_STATE_GK_OK;
+ else if ( wd->sta.wpaState == ZM_STA_WPA_STATE_INIT )
+ {
+ wd->sta.wpaState = ZM_STA_WPA_STATE_PK_OK;
+ wd->sta.encryMode = encryMode;
+ wd->ws.encryMode = encryMode;
+ }
+#endif
+ }
+ else
+ {
+ zfHpSetDefaultKey(dev, keyInfo.keyIndex, encryMode,
+ (u32_t*) keyInfo.key, NULL);
+
+ /* Save key for software WEP */
+ zfMemoryCopy(wd->sta.wepKey[keyInfo.keyIndex], keyInfo.key,
+ keyInfo.keyLength);
+
+ /* TODO: Check whether we need to save the SWEncryMode */
+ wd->sta.SWEncryMode[keyInfo.keyIndex] = encryMode;
+
+ wd->sta.encryMode = encryMode;
+ wd->ws.encryMode = encryMode;
+ }
+ }
+ }
+
+// wd->sta.flagKeyChanging = 1;
+ return ZM_STATUS_SUCCESS;
+}
+
+/* PSEUDO test */
+u8_t zfiWlanPSEUDOSetKey(zdev_t* dev, struct zsKeyInfo keyInfo)
+{
+ //u16_t broadcast[3] = {0xffff, 0xffff, 0xffff};
+ //u32_t* key;
+ u8_t micKey[16];
+
+ zmw_get_wlan_dev(dev);
+
+ switch (keyInfo.keyLength)
+ {
+ case 5:
+ wd->sta.encryMode = ZM_WEP64;
+ /* use default key */
+ zfCoreSetKey(dev, 64, 0, ZM_WEP64, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
+ break;
+
+ case 13:
+ wd->sta.encryMode = ZM_WEP128;
+ /* use default key */
+ zfCoreSetKey(dev, 64, 0, ZM_WEP128, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
+ break;
+
+ case 29:
+ wd->sta.encryMode = ZM_WEP256;
+ /* use default key */
+ zfCoreSetKey(dev, 64, 1, ZM_WEP256, (u16_t *)keyInfo.macAddr, (u32_t*) (&keyInfo.key[16]));
+ zfCoreSetKey(dev, 64, 0, ZM_WEP256, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
+ break;
+
+ case 16:
+ wd->sta.encryMode = ZM_AES;
+ //zfCoreSetKey(dev, 0, 0, ZM_AES, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
+ zfCoreSetKey(dev, 64, 0, ZM_AES, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
+ break;
+
+ case 32:
+#ifdef ZM_ENABLE_CENC
+ if (keyInfo.flag & ZM_KEY_FLAG_CENC)
+ {
+ u16_t boardcastAddr[3] = {0xffff, 0xffff, 0xffff};
+ u16_t Addr_a[] = { 0x0000, 0x0080, 0x0901};
+ u16_t Addr_b[] = { 0x0000, 0x0080, 0x0902};
+ /* CENC test: user0,1 and user2 for boardcast */
+ wd->sta.encryMode = ZM_CENC;
+ zfCoreSetKey(dev, 0, 1, ZM_CENC, (u16_t *)Addr_a, (u32_t*) (&keyInfo.key[16]));
+ zfCoreSetKey(dev, 0, 0, ZM_CENC, (u16_t *)Addr_a, (u32_t*) keyInfo.key);
+
+ zfCoreSetKey(dev, 1, 1, ZM_CENC, (u16_t *)Addr_b, (u32_t*) (&keyInfo.key[16]));
+ zfCoreSetKey(dev, 1, 0, ZM_CENC, (u16_t *)Addr_b, (u32_t*) keyInfo.key);
+
+ zfCoreSetKey(dev, 2, 1, ZM_CENC, (u16_t *)boardcastAddr, (u32_t*) (&keyInfo.key[16]));
+ zfCoreSetKey(dev, 2, 0, ZM_CENC, (u16_t *)boardcastAddr, (u32_t*) keyInfo.key);
+
+ /* Initialize PN sequence */
+ wd->sta.txiv[0] = 0x5c365c36;
+ wd->sta.txiv[1] = 0x5c365c36;
+ wd->sta.txiv[2] = 0x5c365c36;
+ wd->sta.txiv[3] = 0x5c365c36;
+ }
+ else
+#endif //ZM_ENABLE_CENC
+ {
+ wd->sta.encryMode = ZM_TKIP;
+ zfCoreSetKey(dev, 64, 1, ZM_TKIP, (u16_t *)keyInfo.macAddr, (u32_t*) micKey);
+ zfCoreSetKey(dev, 64, 0, ZM_TKIP, (u16_t *)keyInfo.macAddr, (u32_t*) keyInfo.key);
+ }
+ break;
+ default:
+ wd->sta.encryMode = ZM_NO_WEP;
+ }
+
+ return ZM_STATUS_SUCCESS;
+}
+
+void zfiWlanSetPowerSaveMode(zdev_t* dev, u8_t mode)
+{
+#if 0
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.powerSaveMode = mode;
+
+ /* send null data with PwrBit to inform AP */
+ if ( mode > ZM_STA_PS_NONE )
+ {
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ zfSendNullData(dev, 1);
+ }
+
+ /* device into PS mode */
+ zfPSDeviceSleep(dev);
+ }
+#endif
+
+ zfPowerSavingMgrSetMode(dev, mode);
+}
+
+void zfiWlanSetMacAddress(zdev_t* dev, u16_t* mac)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->macAddr[0] = mac[0];
+ wd->macAddr[1] = mac[1];
+ wd->macAddr[2] = mac[2];
+
+ zfHpSetMacAddress(dev, mac, 0);
+}
+
+u8_t zfiWlanQueryWlanMode(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->wlanMode;
+}
+
+u8_t zfiWlanQueryAdapterState(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->state;
+}
+
+u8_t zfiWlanQueryAuthenticationMode(zdev_t* dev, u8_t bWrapper)
+{
+ u8_t authMode;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( bWrapper )
+ {
+ authMode = wd->ws.authMode;
+ }
+ else
+ {
+ //authMode = wd->sta.authMode;
+ authMode = wd->sta.currentAuthMode;
+ }
+
+ return authMode;
+}
+
+u8_t zfiWlanQueryWepStatus(zdev_t* dev, u8_t bWrapper)
+{
+ u8_t wepStatus;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( bWrapper )
+ {
+ wepStatus = wd->ws.wepStatus;
+ }
+ else
+ {
+ wepStatus = wd->sta.wepStatus;
+ }
+
+ return wepStatus;
+}
+
+void zfiWlanQuerySSID(zdev_t* dev, u8_t* ssid, u8_t* pSsidLength)
+{
+ u16_t vapId = 0;
+ zmw_get_wlan_dev(dev);
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ vapId = zfwGetVapId(dev);
+
+ if (vapId == 0xffff)
+ {
+ *pSsidLength = wd->ap.ssidLen[0];
+ zfMemoryCopy(ssid, wd->ap.ssid[0], wd->ap.ssidLen[0]);
+ }
+ else
+ {
+ *pSsidLength = wd->ap.ssidLen[vapId + 1];
+ zfMemoryCopy(ssid, wd->ap.ssid[vapId + 1], wd->ap.ssidLen[vapId + 1]);
+ }
+ }
+ else
+ {
+ *pSsidLength = wd->sta.ssidLen;
+ zfMemoryCopy(ssid, wd->sta.ssid, wd->sta.ssidLen);
+ }
+}
+
+u16_t zfiWlanQueryFragThreshold(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->fragThreshold;
+}
+
+u16_t zfiWlanQueryRtsThreshold(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->rtsThreshold;
+}
+
+u32_t zfiWlanQueryFrequency(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return (wd->frequency*1000);
+}
+
+/***********************************************************
+ * Function: zfiWlanQueryCurrentFrequency
+ * Return value:
+ * - 0 : no validate current frequency
+ * - (>0): current frequency depend on "qmode"
+ * Input:
+ * - qmode:
+ * 0: return value depend on the support mode, this
+ qmode is use to solve the bug #31223
+ * 1: return the actually current frequency
+ ***********************************************************/
+u32_t zfiWlanQueryCurrentFrequency(zdev_t* dev, u8_t qmode)
+{
+ u32_t frequency;
+
+ zmw_get_wlan_dev(dev);
+
+ switch (qmode)
+ {
+ case 0:
+ if (wd->sta.currentFrequency > 3000)
+ {
+ if (wd->supportMode & ZM_WIRELESS_MODE_5)
+ {
+ frequency = wd->sta.currentFrequency;
+ }
+ else if (wd->supportMode & ZM_WIRELESS_MODE_24)
+ {
+ frequency = zfChGetFirst2GhzChannel(dev);
+ }
+ else
+ {
+ frequency = 0;
+ }
+ }
+ else
+ {
+ if (wd->supportMode & ZM_WIRELESS_MODE_24)
+ {
+ frequency = wd->sta.currentFrequency;
+ }
+ else if (wd->supportMode & ZM_WIRELESS_MODE_5)
+ {
+ frequency = zfChGetLast5GhzChannel(dev);
+ }
+ else
+ {
+ frequency = 0;
+ }
+ }
+ break;
+
+ case 1:
+ frequency = wd->sta.currentFrequency;
+ break;
+
+ default:
+ frequency = 0;
+ }
+
+ return (frequency*1000);
+}
+
+u32_t zfiWlanQueryFrequencyAttribute(zdev_t* dev, u32_t freq)
+{
+ zmw_get_wlan_dev(dev);
+
+ u8_t i;
+ u16_t frequency = (u16_t) (freq/1000);
+ u32_t ret = 0;
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if ( wd->regulationTable.allowChannel[i].channel == frequency )
+ {
+ ret = wd->regulationTable.allowChannel[i].channelFlags;
+ }
+ }
+
+ return ret;
+}
+
+/* BandWidth 0=>20 1=>40 */
+/* ExtOffset 0=>20 1=>high control 40 3=>low control 40 */
+void zfiWlanQueryFrequencyHT(zdev_t* dev, u32_t *bandWidth, u32_t *extOffset)
+{
+ zmw_get_wlan_dev(dev);
+
+ *bandWidth = wd->BandWidth40;
+ *extOffset = wd->ExtOffset;
+}
+
+u8_t zfiWlanQueryCWMode(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->cwm.cw_mode;
+}
+
+u32_t zfiWlanQueryCWEnable(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->cwm.cw_enable;
+}
+
+void zfiWlanQueryBssid(zdev_t* dev, u8_t* bssid)
+{
+ u8_t addr[6];
+
+ zmw_get_wlan_dev(dev);
+
+ ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, addr);
+ zfMemoryCopy(bssid, addr, 6);
+}
+
+u16_t zfiWlanQueryBeaconInterval(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->beaconInterval;
+}
+
+u32_t zfiWlanQueryRxBeaconTotal(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ wd->sta.rxBeaconTotal += wd->sta.rxBeaconCount;
+
+ return wd->sta.rxBeaconTotal;
+}
+
+u16_t zfiWlanQueryAtimWindow(zdev_t* dev)
+{
+ u16_t atimWindow;
+
+ zmw_get_wlan_dev(dev);
+
+ atimWindow = wd->sta.atimWindow;
+
+ return atimWindow;
+}
+
+u8_t zfiWlanQueryEncryMode(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if (wd->wlanMode == ZM_MODE_AP)
+ return wd->ap.encryMode[0];
+ else
+ return wd->sta.encryMode;
+}
+
+u16_t zfiWlanQueryCapability(zdev_t* dev)
+{
+ u16_t capability;
+
+ zmw_get_wlan_dev(dev);
+
+ capability = wd->sta.capability[0] +
+ (((u16_t) wd->sta.capability[1]) << 8);
+
+ return capability;
+
+}
+
+u16_t zfiWlanQueryAid(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->sta.aid;
+}
+
+void zfiWlanQuerySupportRate(zdev_t* dev, u8_t* rateArray, u8_t* pLength)
+{
+ u8_t i, j=0;
+
+ zmw_get_wlan_dev(dev);
+
+ for( i=0; i<4; i++ )
+ {
+ if ( wd->bRate & (0x1 << i) )
+ {
+ rateArray[j] = zg11bRateTbl[i] +
+ ((wd->bRateBasic & (0x1<<i))<<(7-i));
+ j++;
+ }
+ }
+
+ *pLength = j;
+}
+
+void zfiWlanQueryExtSupportRate(zdev_t* dev, u8_t* rateArray, u8_t* pLength)
+{
+ u8_t i, j=0;
+
+ zmw_get_wlan_dev(dev);
+
+ for( i=0; i<8; i++ )
+ {
+ if ( wd->gRate & (0x1 << i) )
+ {
+ rateArray[j] = zg11gRateTbl[i] +
+ ((wd->gRateBasic & (0x1<<i))<<(7-i));
+ j++;
+ }
+ }
+
+ *pLength = j;
+}
+
+void zfiWlanQueryRsnIe(zdev_t* dev, u8_t* ie, u8_t* pLength)
+{
+ u8_t len;
+
+ zmw_get_wlan_dev(dev);
+
+ len = wd->sta.rsnIe[1] + 2;
+ zfMemoryCopy(ie, wd->sta.rsnIe, len);
+ *pLength = len;
+}
+
+void zfiWlanQueryWpaIe(zdev_t* dev, u8_t* ie, u8_t* pLength)
+{
+ u8_t len;
+
+ zmw_get_wlan_dev(dev);
+
+ len = wd->sta.wpaIe[1] + 2;
+ zfMemoryCopy(ie, wd->sta.wpaIe, len);
+ *pLength = len;
+
+}
+
+u8_t zfiWlanQueryMulticastCipherAlgo(zdev_t *dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch( wd->sta.currentAuthMode )
+ {
+ case ZM_AUTH_MODE_WPA2PSK:
+ case ZM_AUTH_MODE_WPA2:
+ if ( wd->sta.rsnIe[7] == 2 )
+ {
+ return ZM_TKIP;
+ }
+ else
+ {
+ return ZM_AES;
+ }
+ break;
+
+ case ZM_AUTH_MODE_WPAPSK:
+ case ZM_AUTH_MODE_WPA:
+ if ( wd->sta.rsnIe[11] == 2 )
+ {
+ return ZM_TKIP;
+ }
+ else
+ {
+ return ZM_AES;
+ }
+ break;
+
+ default:
+ return wd->sta.encryMode;
+ }
+}
+
+u8_t zfiWlanQueryHTMode(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ // 0:Legancy, 1:N
+ return wd->sta.EnableHT;
+}
+
+u8_t zfiWlanQueryBandWidth40(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ // 0:20M, 1:40M
+ return wd->BandWidth40;
+}
+
+u16_t zfiWlanQueryRegionCode(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->regulationTable.regionCode;
+}
+void zfiWlanSetWpaIe(zdev_t* dev, u8_t* ie, u8_t Length)
+{
+ u16_t vapId = 0;
+ zmw_get_wlan_dev(dev);
+
+ if (wd->wlanMode == ZM_MODE_AP) // AP Mode
+ {
+ vapId = zfwGetVapId(dev);
+
+ if (vapId == 0xffff)
+ vapId = 0;
+ else
+ vapId++;
+
+ zm_assert(Length < ZM_MAX_WPAIE_SIZE);
+ if (Length < ZM_MAX_WPAIE_SIZE)
+ {
+ wd->ap.wpaLen[vapId] = Length;
+ zfMemoryCopy(wd->ap.wpaIe[vapId], ie, wd->ap.wpaLen[vapId]);
+ }
+
+ }
+ else
+ {
+ wd->sta.wpaLen = Length;
+ zfMemoryCopy(wd->sta.wpaIe, ie, wd->sta.wpaLen);
+ }
+ //zfiWlanSetWpaSupport(dev, 1);
+ if (wd->wlanMode == ZM_MODE_AP) // AP Mode
+ {
+ wd->ap.wpaSupport[vapId] = 1;
+ }
+ else
+ {
+ wd->sta.wpaSupport = 1;
+ }
+
+}
+
+void zfiWlanSetWpaSupport(zdev_t* dev, u8_t WpaSupport)
+{
+ u16_t vapId = 0;
+ zmw_get_wlan_dev(dev);
+
+ if (wd->wlanMode == ZM_MODE_AP) // AP Mode
+ {
+ vapId = zfwGetVapId(dev);
+
+ if (vapId == 0xffff)
+ vapId = 0;
+ else
+ vapId++;
+
+ wd->ap.wpaSupport[vapId] = WpaSupport;
+ }
+ else
+ {
+ wd->sta.wpaSupport = WpaSupport;
+ }
+
+}
+
+void zfiWlanSetProtectionMode(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.bProtectionMode = mode;
+ if (wd->sta.bProtectionMode == TRUE)
+ {
+ zfHpSetSlotTime(dev, 0);
+ }
+ else
+ {
+ zfHpSetSlotTime(dev, 1);
+ }
+
+ zm_msg1_mm(ZM_LV_1, "wd->protectionMode=", wd->sta.bProtectionMode);
+}
+
+void zfiWlanSetBasicRate(zdev_t* dev, u8_t bRateSet, u8_t gRateSet,
+ u32_t nRateSet)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.bRateBasic = bRateSet;
+ wd->ws.gRateBasic = gRateSet;
+ wd->ws.nRateBasic = nRateSet;
+}
+
+void zfiWlanSetBGMode(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.bgMode = mode;
+}
+
+void zfiWlanSetpreambleType(zdev_t* dev, u8_t type)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.preambleType = type;
+}
+
+u8_t zfiWlanQuerypreambleType(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->ws.preambleType;
+}
+
+u8_t zfiWlanQueryPowerSaveMode(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->sta.powerSaveMode;
+}
+
+u8_t zfiWlanSetPmkidInfo(zdev_t* dev, u16_t* bssid, u8_t* pmkid)
+{
+ u32_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for(i=0; i<wd->sta.pmkidInfo.bssidCount; i++)
+ {
+ if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid,
+ (u8_t*) bssid, 6) )
+ {
+ /* matched */
+ break;
+ }
+ }
+
+ if ( i < wd->sta.pmkidInfo.bssidCount )
+ {
+ /* overwrite the original one */
+ zfMemoryCopy(wd->sta.pmkidInfo.bssidInfo[i].pmkid, pmkid, 16);
+ }
+ else
+ {
+ if ( i < ZM_PMKID_MAX_BSS_CNT )
+ {
+ wd->sta.pmkidInfo.bssidInfo[i].bssid[0] = bssid[0];
+ wd->sta.pmkidInfo.bssidInfo[i].bssid[1] = bssid[1];
+ wd->sta.pmkidInfo.bssidInfo[i].bssid[2] = bssid[2];
+
+ zfMemoryCopy(wd->sta.pmkidInfo.bssidInfo[i].pmkid, pmkid, 16);
+ wd->sta.pmkidInfo.bssidCount++;
+ }
+ }
+
+ return 0;
+}
+
+u32_t zfiWlanQueryPmkidInfo(zdev_t* dev, u8_t* buf, u32_t len)
+{
+ //struct zsPmkidInfo* pPmkidInfo = ( struct zsPmkidInfo* ) buf;
+ u32_t size;
+
+ zmw_get_wlan_dev(dev);
+
+ size = sizeof(u32_t) +
+ wd->sta.pmkidInfo.bssidCount * sizeof(struct zsPmkidBssidInfo);
+
+ if ( len < size )
+ {
+ return wd->sta.pmkidInfo.bssidCount;
+ }
+
+ zfMemoryCopy(buf, (u8_t*) &wd->sta.pmkidInfo, (u16_t) size);
+
+ return 0;
+}
+
+void zfiWlanSetMulticastList(zdev_t* dev, u8_t size, u8_t* pList)
+{
+ struct zsMulticastAddr* pMacList = (struct zsMulticastAddr*) pList;
+ u8_t i;
+ u8_t bAllMulticast = 0;
+ //u32_t value;
+
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.multicastList.size = size;
+ for(i=0; i<size; i++)
+ {
+ zfMemoryCopy(wd->sta.multicastList.macAddr[i].addr,
+ pMacList[i].addr, 6);
+ }
+
+ if ( wd->sta.osRxFilter & ZM_PACKET_TYPE_ALL_MULTICAST )
+ bAllMulticast = 1;
+ zfHpSetMulticastList(dev, size, pList, bAllMulticast);
+
+}
+
+void zfiWlanRemoveKey(zdev_t* dev, u8_t keyType, u8_t keyId)
+{
+ u16_t fakeMacAddr[3] = {0, 0, 0};
+ u32_t fakeKey[4] = {0, 0, 0, 0};
+
+ zmw_get_wlan_dev(dev);
+
+ if ( keyType == 0 )
+ {
+ /* remove WEP key */
+ zm_debug_msg0("remove WEP key");
+ zfCoreSetKey(dev, ZM_USER_KEY_DEFAULT+keyId, 0,
+ ZM_NO_WEP, fakeMacAddr, fakeKey);
+ wd->sta.encryMode = ZM_NO_WEP;
+ }
+ else if ( keyType == 1 )
+ {
+ /* remove pairwise key */
+ zm_debug_msg0("remove pairwise key");
+ zfHpRemoveKey(dev, ZM_USER_KEY_PK);
+ wd->sta.encryMode = ZM_NO_WEP;
+ }
+ else
+ {
+ /* remove group key */
+ zm_debug_msg0("remove group key");
+ zfHpRemoveKey(dev, ZM_USER_KEY_GK);
+ }
+}
+
+
+void zfiWlanQueryRegulationTable(zdev_t* dev, struct zsRegulationTable* pEntry)
+{
+ zmw_get_wlan_dev(dev);
+
+ zfMemoryCopy((u8_t*) pEntry, (u8_t*) &wd->regulationTable,
+ sizeof(struct zsRegulationTable));
+}
+
+/* parameter "time" is specified in ms */
+void zfiWlanSetScanTimerPerChannel(zdev_t* dev, u16_t time)
+{
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg1("scan time (ms) = ", time);
+
+ wd->sta.activescanTickPerChannel = time / ZM_MS_PER_TICK;
+}
+
+void zfiWlanSetAutoReconnect(zdev_t* dev, u8_t enable)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.bAutoReconnect = enable;
+ //wd->sta.bAutoReconnectEnabled = enable;
+}
+
+void zfiWlanSetStaWme(zdev_t* dev, u8_t enable, u8_t uapsdInfo)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.staWmeEnabled = enable & 0x3;
+ if ((enable & 0x2) != 0)
+ {
+ wd->ws.staWmeQosInfo = uapsdInfo & 0x6f;
+ }
+ else
+ {
+ wd->ws.staWmeQosInfo = 0;
+ }
+}
+
+void zfiWlanSetApWme(zdev_t* dev, u8_t enable)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.apWmeEnabled = enable;
+}
+
+u8_t zfiWlanQuerywmeEnable(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->ws.staWmeEnabled;
+}
+
+void zfiWlanSetProbingHiddenSsid(zdev_t* dev, u8_t* ssid, u8_t ssidLen,
+ u16_t entry)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+ if ((ssidLen <= 32) && (entry < ZM_MAX_PROBE_HIDDEN_SSID_SIZE))
+ {
+ zmw_enter_critical_section(dev);
+ wd->ws.probingSsidList[entry].ssidLen = ssidLen;
+ zfMemoryCopy(wd->ws.probingSsidList[entry].ssid, ssid, ssidLen);
+ zmw_leave_critical_section(dev);
+ }
+
+ return;
+}
+
+void zfiWlanSetDisableProbingWithSsid(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.disableProbingWithSsid = mode;
+
+ return;
+}
+
+void zfiWlanSetDropUnencryptedPackets(zdev_t* dev, u8_t enable)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.dropUnencryptedPkts = enable;
+}
+
+void zfiWlanSetStaRxSecurityCheckCb(zdev_t* dev, zfpStaRxSecurityCheckCb pStaRxSecurityCheckCb)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.pStaRxSecurityCheckCb = pStaRxSecurityCheckCb;
+}
+
+void zfiWlanSetIBSSJoinOnly(zdev_t* dev, u8_t joinOnly)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.ibssJoinOnly = joinOnly;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiConfigWdsPort */
+/* Configure WDS port. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* wdsPortId : WDS port ID, start from 0 */
+/* flag : 0=>disable WDS port, 1=>enable WDS port */
+/* wdsAddr : WDS neighbor MAC address */
+/* encType : encryption type for WDS port */
+/* wdsKey : encryption key for WDS port */
+/* */
+/* OUTPUTS */
+/* Error code */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+u16_t zfiConfigWdsPort(zdev_t* dev, u8_t wdsPortId, u16_t flag, u16_t* wdsAddr,
+ u16_t encType, u32_t* wdsKey)
+{
+ u16_t addr[3];
+ u32_t key[4];
+
+ zmw_get_wlan_dev(dev);
+
+ if (wdsPortId > ZM_MAX_WDS_SUPPORT)
+ {
+ return ZM_ERR_WDS_PORT_ID;
+ }
+
+ if (flag == 1)
+ {
+ /* Enable WDS port */
+ wd->ap.wds.macAddr[wdsPortId][0] = wdsAddr[0];
+ wd->ap.wds.macAddr[wdsPortId][1] = wdsAddr[1];
+ wd->ap.wds.macAddr[wdsPortId][2] = wdsAddr[2];
+
+ wd->ap.wds.wdsBitmap |= (1 << wdsPortId);
+ wd->ap.wds.encryMode[wdsPortId] = (u8_t) encType;
+
+ zfCoreSetKey(dev, 10+ZM_MAX_WDS_SUPPORT, 0, (u8_t) encType, wdsAddr, wdsKey);
+ }
+ else
+ {
+ /* Disable WDS port */
+ addr[0] = addr[1] = addr[2] = 0;
+ key[0] = key[1] = key[2] = key[3] = 0;
+ wd->ap.wds.wdsBitmap &= (~(1 << wdsPortId));
+ zfCoreSetKey(dev, 10+ZM_MAX_WDS_SUPPORT, 0, ZM_NO_WEP, addr, key);
+ }
+
+ return ZM_SUCCESS;
+}
+#ifdef ZM_ENABLE_CENC
+/* CENC */
+void zfiWlanQueryGSN(zdev_t* dev, u8_t *gsn, u16_t vapId)
+{
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ u32_t txiv[4];
+ zmw_get_wlan_dev(dev);
+
+ /* convert little endian to big endian for 32 bits */
+ txiv[3] = wd->ap.txiv[vapId][0];
+ txiv[2] = wd->ap.txiv[vapId][1];
+ txiv[1] = wd->ap.txiv[vapId][2];
+ txiv[0] = wd->ap.txiv[vapId][3];
+
+ zfMemoryCopy(gsn, (u8_t*)txiv, 16);
+}
+#endif //ZM_ENABLE_CENC
+//CWYang(+)
+void zfiWlanQuerySignalInfo(zdev_t* dev, u8_t *buffer)
+{
+ zmw_get_wlan_dev(dev);
+
+ /*Change Signal Strength/Quality Value to Human Sense Here*/
+
+ buffer[0] = wd->SignalStrength;
+ buffer[1] = wd->SignalQuality;
+}
+
+/* OS-XP */
+u16_t zfiStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType)
+{
+ return zfStaAddIeWpaRsn(dev, buf, offset, frameType);
+}
+
+/* zfiDebugCmd */
+/* cmd value-description */
+/* 0 schedule timer */
+/* 1 cancel timer */
+/* 2 clear timer */
+/* 3 test timer */
+/* 4 */
+/* 5 */
+/* 6 checksum test 0/1 */
+/* 7 enableProtectionMode */
+/* 8 rx packet content dump 0/1 */
+
+u32_t zfiDebugCmd(zdev_t* dev, u32_t cmd, u32_t value)
+{
+ u16_t event;
+ u32_t tick;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+
+ zmw_enter_critical_section(dev);
+
+ if ( cmd == 0 )
+ { /* schedule timer */
+ event = (u16_t) ((value >> 16) & 0xffff);
+ tick = value & 0xffff;
+ zfTimerSchedule(dev, event, tick);
+ }
+ else if ( cmd == 1 )
+ { /* cancel timer */
+ event = (u16_t) (value & 0xffff);
+ zfTimerCancel(dev, event);
+ }
+ else if ( cmd == 2 )
+ { /* clear timer */
+ zfTimerClear(dev);
+ }
+ else if ( cmd == 3 )
+ { /* test timer */
+ zfTimerSchedule(dev, 1, 500);
+ zfTimerSchedule(dev, 2, 1000);
+ zfTimerSchedule(dev, 3, 1000);
+ zfTimerSchedule(dev, 4, 1000);
+ zfTimerSchedule(dev, 5, 1500);
+ zfTimerSchedule(dev, 6, 2000);
+ zfTimerSchedule(dev, 7, 2200);
+ zfTimerSchedule(dev, 6, 2500);
+ zfTimerSchedule(dev, 8, 2800);
+ }
+ else if ( cmd == 4)
+ {
+ zfTimerSchedule(dev, 1, 500);
+ zfTimerSchedule(dev, 2, 1000);
+ zfTimerSchedule(dev, 3, 1000);
+ zfTimerSchedule(dev, 4, 1000);
+ zfTimerSchedule(dev, 5, 1500);
+ zfTimerSchedule(dev, 6, 2000);
+ zfTimerSchedule(dev, 7, 2200);
+ zfTimerSchedule(dev, 6, 2500);
+ zfTimerSchedule(dev, 8, 2800);
+ zfTimerCancel(dev, 1);
+ zfTimerCancel(dev, 3);
+ zfTimerCancel(dev, 6);
+ }
+ else if ( cmd == 5 )
+ {
+ wd->sta.keyId = (u8_t) value;
+ }
+ else if ( cmd == 6 )
+ {
+ /* 0: normal 1: always set TCP/UDP checksum zero */
+ wd->checksumTest = value;
+ }
+ else if ( cmd == 7 )
+ {
+ wd->enableProtectionMode = value;
+ zm_msg1_mm(ZM_LV_1, "wd->enableProtectionMode=", wd->enableProtectionMode);
+ }
+ else if ( cmd == 8 )
+ {
+ /* rx packet content dump */
+ if (value)
+ {
+ wd->rxPacketDump = 1;
+ }
+ else
+ {
+ wd->rxPacketDump = 0;
+ }
+ }
+
+
+ zmw_leave_critical_section(dev);
+
+ return 0;
+}
+
+#ifdef ZM_ENABLE_CENC
+u8_t zfiWlanSetCencPairwiseKey(zdev_t* dev, u8_t keyid, u32_t *txiv, u32_t *rxiv,
+ u8_t *key, u8_t *mic)
+{
+ struct zsKeyInfo keyInfo;
+ u8_t cencKey[32];
+ u8_t i;
+ u16_t macAddr[3];
+
+ zmw_get_wlan_dev(dev);
+
+ for (i = 0; i < 16; i++)
+ cencKey[i] = key[i];
+ for (i = 0; i < 16; i++)
+ cencKey[i + 16] = mic[i];
+ keyInfo.key = cencKey;
+ keyInfo.keyLength = 32;
+ keyInfo.keyIndex = keyid;
+ keyInfo.flag = ZM_KEY_FLAG_CENC | ZM_KEY_FLAG_PK;
+ for (i = 0; i < 3; i++)
+ macAddr[i] = wd->sta.bssid[i];
+ keyInfo.macAddr = macAddr;
+
+ zfiWlanSetKey(dev, keyInfo);
+
+ /* Reset txiv and rxiv */
+ //wd->sta.txiv[0] = txiv[0];
+ //wd->sta.txiv[1] = txiv[1];
+ //wd->sta.txiv[2] = txiv[2];
+ //wd->sta.txiv[3] = txiv[3];
+ //
+ //wd->sta.rxiv[0] = rxiv[0];
+ //wd->sta.rxiv[1] = rxiv[1];
+ //wd->sta.rxiv[2] = rxiv[2];
+ //wd->sta.rxiv[3] = rxiv[3];
+
+ return 0;
+}
+
+u8_t zfiWlanSetCencGroupKey(zdev_t* dev, u8_t keyid, u32_t *rxiv,
+ u8_t *key, u8_t *mic)
+{
+ struct zsKeyInfo keyInfo;
+ u8_t cencKey[32];
+ u8_t i;
+ u16_t macAddr[6] = {0xffff, 0xffff, 0xffff};
+
+ zmw_get_wlan_dev(dev);
+
+ for (i = 0; i < 16; i++)
+ cencKey[i] = key[i];
+ for (i = 0; i < 16; i++)
+ cencKey[i + 16] = mic[i];
+ keyInfo.key = cencKey;
+ keyInfo.keyLength = 32;
+ keyInfo.keyIndex = keyid;
+ keyInfo.flag = ZM_KEY_FLAG_CENC | ZM_KEY_FLAG_GK;
+ keyInfo.vapId = 0;
+ for (i = 0; i < 3; i++)
+ keyInfo.vapAddr[i] = wd->macAddr[i];
+ keyInfo.macAddr = macAddr;
+
+ zfiWlanSetKey(dev, keyInfo);
+
+ /* Reset txiv and rxiv */
+ wd->sta.rxivGK[0] = ((rxiv[3] >> 24) & 0xFF)
+ + (((rxiv[3] >> 16) & 0xFF) << 8)
+ + (((rxiv[3] >> 8) & 0xFF) << 16)
+ + ((rxiv[3] & 0xFF) << 24);
+ wd->sta.rxivGK[1] = ((rxiv[2] >> 24) & 0xFF)
+ + (((rxiv[2] >> 16) & 0xFF) << 8)
+ + (((rxiv[2] >> 8) & 0xFF) << 16)
+ + ((rxiv[2] & 0xFF) << 24);
+ wd->sta.rxivGK[2] = ((rxiv[1] >> 24) & 0xFF)
+ + (((rxiv[1] >> 16) & 0xFF) << 8)
+ + (((rxiv[1] >> 8) & 0xFF) << 16)
+ + ((rxiv[1] & 0xFF) << 24);
+ wd->sta.rxivGK[3] = ((rxiv[0] >> 24) & 0xFF)
+ + (((rxiv[0] >> 16) & 0xFF) << 8)
+ + (((rxiv[0] >> 8) & 0xFF) << 16)
+ + ((rxiv[0] & 0xFF) << 24);
+
+ wd->sta.authMode = ZM_AUTH_MODE_CENC;
+ wd->sta.currentAuthMode = ZM_AUTH_MODE_CENC;
+
+ return 0;
+}
+#endif //ZM_ENABLE_CENC
+
+u8_t zfiWlanSetDot11DMode(zdev_t* dev, u8_t mode)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.b802_11D = mode;
+ if (mode) //Enable 802.11d
+ {
+ wd->regulationTable.regionCode = NO_ENUMRD;
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ wd->regulationTable.allowChannel[i].channelFlags |= ZM_REG_FLAG_CHANNEL_PASSIVE;
+ }
+ else //Disable
+ {
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ wd->regulationTable.allowChannel[i].channelFlags &= ~ZM_REG_FLAG_CHANNEL_PASSIVE;
+ }
+
+ return 0;
+}
+
+u8_t zfiWlanSetDot11HDFSMode(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ //zm_debug_msg0("CWY - Enable 802.11h DFS");
+
+ // TODO : DFS Enable in 5250 to 5350 MHz and 5470 to 5725 MHz .
+ //if ( Adapter->ZD80211HSupport &&
+ // Adapter->CardSetting.NetworkTypeInUse == Ndis802_11OFDM5 &&
+ // ((ChannelNo >=52 && ChannelNo <= 64) || //5250~5350 MHZ
+ // (ChannelNo >=100 && ChannelNo <= 140))) //5470~5725 MHZ
+ //{
+ // Adapter->ZD80211HSetting.DFSEnable=TRUE;
+ //}
+ //else
+ //{
+ // Adapter->ZD80211HSetting.DFSEnable=FALSE;
+ //}
+
+ wd->sta.DFSEnable = mode;
+ if (mode)
+ wd->sta.capability[1] |= ZM_BIT_0;
+ else
+ wd->sta.capability[1] &= (~ZM_BIT_0);
+
+ return 0;
+}
+
+u8_t zfiWlanSetDot11HTPCMode(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ // TODO : TPC Enable in 5150~5350 MHz and 5470~5725MHz.
+ //if ( Adapter->ZD80211HSupport &&
+ // Adapter->CardSetting.NetworkTypeInUse == Ndis802_11OFDM5 &&
+ // ((ChannelNo == 36 || ChannelNo == 40 || ChannelNo == 44 || ChannelNo == 48) || //5150~5250 MHZ , Not Japan
+ // (ChannelNo >=52 && ChannelNo <= 64) || //5250~5350 MHZ
+ // (ChannelNo >=100 && ChannelNo <= 140))) //5470~5725 MHZ
+ //{
+ // Adapter->ZD80211HSetting.TPCEnable=TRUE;
+ //}
+ //else
+ //{
+ // Adapter->ZD80211HSetting.TPCEnable=FALSE;
+ //}
+
+ wd->sta.TPCEnable = mode;
+ if (mode)
+ wd->sta.capability[1] |= ZM_BIT_0;
+ else
+ wd->sta.capability[1] &= (~ZM_BIT_0);
+
+ return 0;
+}
+
+u8_t zfiWlanSetAniMode(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->aniEnable = mode;
+ if (mode)
+ zfHpAniAttach(dev);
+
+ return 0;
+}
+
+#ifdef ZM_OS_LINUX_FUNC
+void zfiWlanShowTally(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zm_msg1_mm(ZM_LV_0, "Hw_UnderrunCnt = ", wd->commTally.Hw_UnderrunCnt);
+ zm_msg1_mm(ZM_LV_0, "Hw_TotalRxFrm = ", wd->commTally.Hw_TotalRxFrm);
+ zm_msg1_mm(ZM_LV_0, "Hw_CRC32Cnt = ", wd->commTally.Hw_CRC32Cnt);
+ zm_msg1_mm(ZM_LV_0, "Hw_CRC16Cnt = ", wd->commTally.Hw_CRC16Cnt);
+ zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_UNI = ", wd->commTally.Hw_DecrypErr_UNI);
+ zm_msg1_mm(ZM_LV_0, "Hw_RxFIFOOverrun = ", wd->commTally.Hw_RxFIFOOverrun);
+ zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_Mul = ", wd->commTally.Hw_DecrypErr_Mul);
+ zm_msg1_mm(ZM_LV_1, "Hw_RetryCnt = ", wd->commTally.Hw_RetryCnt);
+ zm_msg1_mm(ZM_LV_0, "Hw_TotalTxFrm = ", wd->commTally.Hw_TotalTxFrm);
+ zm_msg1_mm(ZM_LV_0, "Hw_RxTimeOut = ", wd->commTally.Hw_RxTimeOut);
+ zm_msg1_mm(ZM_LV_0, "Tx_MPDU = ", wd->commTally.Tx_MPDU);
+ zm_msg1_mm(ZM_LV_0, "BA_Fail = ", wd->commTally.BA_Fail);
+ zm_msg1_mm(ZM_LV_0, "Hw_Tx_AMPDU = ", wd->commTally.Hw_Tx_AMPDU);
+ zm_msg1_mm(ZM_LV_0, "Hw_Tx_MPDU = ", wd->commTally.Hw_Tx_MPDU);
+
+ zm_msg1_mm(ZM_LV_1, "Hw_RxMPDU = ", wd->commTally.Hw_RxMPDU);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxDropMPDU = ", wd->commTally.Hw_RxDropMPDU);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxDelMPDU = ", wd->commTally.Hw_RxDelMPDU);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyMiscError = ", wd->commTally.Hw_RxPhyMiscError);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyXRError = ", wd->commTally.Hw_RxPhyXRError);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyOFDMError = ", wd->commTally.Hw_RxPhyOFDMError);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyCCKError = ", wd->commTally.Hw_RxPhyCCKError);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyHTError = ", wd->commTally.Hw_RxPhyHTError);
+ zm_msg1_mm(ZM_LV_1, "Hw_RxPhyTotalCount = ", wd->commTally.Hw_RxPhyTotalCount);
+
+ if (!((wd->commTally.Tx_MPDU == 0) && (wd->commTally.BA_Fail == 0)))
+ {
+ zm_debug_msg_p("BA Fail Ratio(%) = ", wd->commTally.BA_Fail * 100,
+ (wd->commTally.BA_Fail + wd->commTally.Tx_MPDU));
+ }
+
+ if (!((wd->commTally.Hw_Tx_MPDU == 0) && (wd->commTally.Hw_Tx_AMPDU == 0)))
+ {
+ zm_debug_msg_p("Avg Agg Number = ",
+ wd->commTally.Hw_Tx_MPDU, wd->commTally.Hw_Tx_AMPDU);
+ }
+}
+#endif
+
+void zfiWlanSetMaxTxPower(zdev_t* dev, u8_t power2, u8_t power5)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->maxTxPower2 = power2;
+ wd->maxTxPower5 = power5;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanQueryMaxTxPower(zdev_t* dev, u8_t *power2, u8_t *power5)
+{
+ zmw_get_wlan_dev(dev);
+
+ *power2 = wd->maxTxPower2;
+ *power5 = wd->maxTxPower5;
+}
+
+void zfiWlanSetConnectMode(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->connectMode = mode;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetSupportMode(zdev_t* dev, u32_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->supportMode = mode;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanSetAdhocMode(zdev_t* dev, u32_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ws.adhocMode = mode;
+}
+
+u32_t zfiWlanQueryAdhocMode(zdev_t* dev, u8_t bWrapper)
+{
+ u32_t adhocMode;
+
+ zmw_get_wlan_dev(dev);
+
+ if ( bWrapper )
+ {
+ adhocMode = wd->ws.adhocMode;
+ }
+ else
+ {
+ adhocMode = wd->wfc.bIbssGMode;
+ }
+
+ return adhocMode;
+}
+
+
+u8_t zfiWlanSetCountryIsoName(zdev_t* dev, u8_t *countryIsoName, u8_t length)
+{
+ u8_t buf[5];
+ zmw_get_wlan_dev(dev);
+
+ if (length == 4)
+ {
+ buf[2] = wd->ws.countryIsoName[0] = countryIsoName[2];
+ buf[3] = wd->ws.countryIsoName[1] = countryIsoName[1];
+ buf[4] = wd->ws.countryIsoName[2] = countryIsoName[0];
+ }
+ else if (length == 3)
+ {
+ buf[2] = wd->ws.countryIsoName[0] = countryIsoName[1];
+ buf[3] = wd->ws.countryIsoName[1] = countryIsoName[0];
+ buf[4] = wd->ws.countryIsoName[2] = '\0';
+ }
+ else
+ {
+ return 1;
+ }
+
+ return zfHpGetRegulationTablefromISO(dev, buf, length);
+}
+
+
+const char* zfiWlanQueryCountryIsoName(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->ws.countryIsoName;
+}
+
+
+
+void zfiWlanSetRegulatory(zdev_t* dev, u8_t CCS, u16_t Code, u8_t bfirstChannel)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if (CCS)
+ {
+ /* Reset Regulation Table by Country Code */
+ zfHpGetRegulationTablefromCountry(dev, Code);
+ }
+ else
+ {
+ /* Reset Regulation Table by Region Code */
+ zfHpGetRegulationTablefromRegionCode(dev, Code);
+ }
+
+ if (bfirstChannel) {
+ zmw_enter_critical_section(dev);
+ wd->frequency = zfChGetFirstChannel(dev, NULL);
+ zmw_leave_critical_section(dev);
+ zfCoreSetFrequency(dev, wd->frequency);
+ }
+}
+
+
+const char* zfiHpGetisoNamefromregionCode(zdev_t* dev, u16_t regionCode)
+{
+ return zfHpGetisoNamefromregionCode(dev, regionCode);
+}
+
+u16_t zfiWlanChannelToFrequency(zdev_t* dev, u8_t channel)
+{
+ return zfChNumToFreq(dev, channel, 0);
+}
+
+u8_t zfiWlanFrequencyToChannel(zdev_t* dev, u16_t freq)
+{
+ u8_t is5GBand = 0;
+
+ return zfChFreqToNum(freq, &is5GBand);
+}
+
+void zfiWlanDisableDfsChannel(zdev_t* dev, u8_t disableFlag)
+{
+ zfHpDisableDfsChannel(dev, disableFlag);
+ return;
+}
+
+void zfiWlanSetLEDCtrlParam(zdev_t* dev, u8_t type, u8_t flag)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->ledStruct.LEDCtrlType = type;
+ wd->ledStruct.LEDCtrlFlagFromReg = flag;
+ zmw_leave_critical_section(dev);
+}
+
+void zfiWlanEnableLeapConfig(zdev_t* dev, u8_t leapEnabled)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.leapEnabled = leapEnabled;
+}
+
+u32_t zfiWlanQueryHwCapability(zdev_t* dev)
+{
+ return zfHpCapability(dev);
+}
+
+u32_t zfiWlanQueryReceivedPacket(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->sta.ReceivedPktRatePerSecond;
+}
+
+void zfiWlanCheckSWEncryption(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if (wd->sta.SWEncryptEnable != 0)
+ {
+ zfHpSWDecrypt(dev, 1);
+ }
+}
+
+u16_t zfiWlanQueryAllowChannels(zdev_t* dev, u16_t *channels)
+{
+ u16_t ii;
+ zmw_get_wlan_dev(dev);
+
+ for (ii = 0; ii < wd->regulationTable.allowChannelCnt; ii++)
+ {
+ channels[ii] = wd->regulationTable.allowChannel[ii].channel;
+ }
+
+ return wd->regulationTable.allowChannelCnt;
+}
+
+void zfiWlanSetDynamicSIFSParam(zdev_t* dev, u8_t val)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->dynamicSIFSEnable = val;
+
+ zm_debug_msg1("wd->dynamicSIFSEnable = ", wd->dynamicSIFSEnable)
+}
+
+u16_t zfiWlanGetMulticastAddressCount(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ return wd->sta.multicastList.size;
+}
+
+void zfiWlanGetMulticastList(zdev_t* dev, u8_t* pMCList)
+{
+ struct zsMulticastAddr* pMacList = (struct zsMulticastAddr*) pMCList;
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ for ( i=0; i<wd->sta.multicastList.size; i++ )
+ {
+ zfMemoryCopy(pMacList[i].addr, wd->sta.multicastList.macAddr[i].addr, 6);
+ }
+}
+
+void zfiWlanSetPacketFilter(zdev_t* dev, u32_t PacketFilter)
+{
+ u8_t bAllMulticast = 0;
+ u32_t oldFilter;
+
+ zmw_get_wlan_dev(dev);
+
+ oldFilter = wd->sta.osRxFilter;
+
+ wd->sta.osRxFilter = PacketFilter;
+
+ if ((oldFilter & ZM_PACKET_TYPE_ALL_MULTICAST) !=
+ (wd->sta.osRxFilter & ZM_PACKET_TYPE_ALL_MULTICAST))
+ {
+ if ( wd->sta.osRxFilter & ZM_PACKET_TYPE_ALL_MULTICAST )
+ bAllMulticast = 1;
+ zfHpSetMulticastList(dev, wd->sta.multicastList.size,
+ (u8_t*)wd->sta.multicastList.macAddr, bAllMulticast);
+ }
+}
+
+u8_t zfiCompareWithMulticastListAddress(zdev_t* dev, u16_t* dstMacAddr)
+{
+ u8_t i;
+ u8_t bIsInMCListAddr = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ for ( i=0; i<wd->sta.multicastList.size; i++ )
+ {
+ if ( zfwMemoryIsEqual((u8_t*)dstMacAddr, (u8_t*)wd->sta.multicastList.macAddr[i].addr, 6) )
+ {
+ bIsInMCListAddr = 1;
+ break;
+ }
+ }
+
+ return bIsInMCListAddr;
+}
+
+void zfiWlanSetSafeModeEnabled(zdev_t* dev, u8_t safeMode)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.bSafeMode = safeMode;
+
+ if ( safeMode )
+ zfStaEnableSWEncryption(dev, 1);
+ else
+ zfStaDisableSWEncryption(dev);
+}
+
+void zfiWlanSetIBSSAdditionalIELength(zdev_t* dev, u32_t ibssAdditionalIESize, u8_t* ibssAdditionalIE)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( ibssAdditionalIESize )
+ {
+ wd->sta.ibssAdditionalIESize = ibssAdditionalIESize;
+ zfMemoryCopy(wd->sta.ibssAdditionalIE, ibssAdditionalIE, (u16_t)ibssAdditionalIESize);
+ }
+ else
+ wd->sta.ibssAdditionalIESize = 0;
+}
diff --git a/drivers/staging/otus/80211core/cprecomp.h b/drivers/staging/otus/80211core/cprecomp.h
new file mode 100644
index 000000000000..1670bfc22587
--- /dev/null
+++ b/drivers/staging/otus/80211core/cprecomp.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _CPRECOMP_H
+#define _CPRECOMP_H
+
+#include "../oal_dt.h"
+#include "../oal_marc.h"
+#include "pub_zfi.h"
+#include "pub_zfw.h"
+#include "pub_usb.h"
+#include "wlan.h"
+#include "struct.h"
+#include "cfunc.h"
+#include "cagg.h"
+#include "cwm.h"
+#include "performance.h"
+#endif
+
diff --git a/drivers/staging/otus/80211core/cpsmgr.c b/drivers/staging/otus/80211core/cpsmgr.c
new file mode 100644
index 000000000000..cf73caca8e52
--- /dev/null
+++ b/drivers/staging/otus/80211core/cpsmgr.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * The power saving manager is to save the power as much as possible.
+ * Generally speaking, it controls:
+ *
+ * - when to sleep
+ * -
+ *
+ */
+#include "cprecomp.h"
+
+void zfPowerSavingMgrInit(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.powerSaveMode = ZM_STA_PS_NONE;
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
+ wd->sta.psMgr.isSleepAllowed = 0;
+ wd->sta.psMgr.maxSleepPeriods = 1;
+ wd->sta.psMgr.ticks = 0;
+ wd->sta.psMgr.sleepAllowedtick = 0;
+}
+
+static u16_t zfPowerSavingMgrHandlePsNone(zdev_t* dev, u8_t *isWakeUpRequired)
+{
+ u16_t ret = 0;
+ zmw_get_wlan_dev(dev);
+
+ switch(wd->sta.psMgr.state)
+ {
+ case ZM_PS_MSG_STATE_ACTIVE:
+ *isWakeUpRequired = 0;
+ break;
+
+ case ZM_PS_MSG_STATE_T1:
+ case ZM_PS_MSG_STATE_T2:
+ case ZM_PS_MSG_STATE_SLEEP:
+ default:
+ *isWakeUpRequired = 1;
+zm_debug_msg0("zfPowerSavingMgrHandlePsNone: Wake up now\n");
+ if ( zfStaIsConnected(dev) )
+ {
+ zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
+ //zfSendNullData(dev, 0);
+ ret = 1;
+ }
+
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
+ break;
+ }
+ return ret;
+}
+
+static void zfPowerSavingMgrHandlePs(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch(wd->sta.psMgr.state)
+ {
+ case ZM_PS_MSG_STATE_ACTIVE:
+ //zm_debug_msg0("zfPowerSavingMgrHandlePs: Prepare to sleep...\n");
+ //wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
+ break;
+
+ case ZM_PS_MSG_STATE_T1:
+ case ZM_PS_MSG_STATE_T2:
+ case ZM_PS_MSG_STATE_SLEEP:
+ default:
+ break;
+ }
+}
+
+void zfPowerSavingMgrSetMode(zdev_t* dev, u8_t mode)
+{
+ u16_t sendNull = 0;
+ u8_t isWakeUpRequired = 0;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zm_debug_msg1("mode = ", mode);
+
+ if (mode > ZM_STA_PS_LIGHT)
+ {
+ zm_debug_msg0("return - wrong power save mode");
+ return;
+ }
+
+ zmw_enter_critical_section(dev);
+
+ #if 1
+ switch(mode)
+ {
+ case ZM_STA_PS_NONE:
+ sendNull = zfPowerSavingMgrHandlePsNone(dev, &isWakeUpRequired);
+ break;
+
+ case ZM_STA_PS_FAST:
+ case ZM_STA_PS_LIGHT:
+ wd->sta.psMgr.maxSleepPeriods = 1;
+ zfPowerSavingMgrHandlePs(dev);
+ break;
+
+ case ZM_STA_PS_MAX:
+ wd->sta.psMgr.maxSleepPeriods = ZM_PS_MAX_SLEEP_PERIODS;
+ zfPowerSavingMgrHandlePs(dev);
+ break;
+ }
+ #else
+ switch(wd->sta.psMgr.state)
+ {
+ case ZM_PS_MSG_STATE_ACTIVE:
+ if ( mode != ZM_STA_PS_NONE )
+ {
+zm_debug_msg0("zfPowerSavingMgrSetMode: switch from ZM_PS_MSG_STATE_ACTIVE to ZM_PS_MSG_STATE_T1\n");
+ // Stall the TX & start to wait the pending TX to be completed
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
+ }
+ break;
+
+ case ZM_PS_MSG_STATE_SLEEP:
+ break;
+ }
+ #endif
+
+ wd->sta.powerSaveMode = mode;
+ zmw_leave_critical_section(dev);
+
+ if ( isWakeUpRequired )
+ {
+ zfHpPowerSaveSetState(dev, 0);
+ wd->sta.psMgr.tempWakeUp = 0;
+ }
+
+ if ( zfStaIsConnected(dev)
+ && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
+ {
+ switch(mode)
+ {
+ case ZM_STA_PS_NONE:
+ zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
+ break;
+
+ case ZM_STA_PS_FAST:
+ case ZM_STA_PS_MAX:
+ case ZM_STA_PS_LIGHT:
+ zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
+ break;
+
+ default:
+ zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
+ break;
+ }
+ }
+
+ if (sendNull == 1)
+ {
+ zfSendNullData(dev, 0);
+ }
+
+ return;
+}
+
+static void zfPowerSavingMgrNotifyPSToAP(zdev_t *dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ if ( (wd->sta.psMgr.tempWakeUp != 1)&&
+ (wd->sta.psMgr.lastTxUnicastFrm != wd->commTally.txUnicastFrm ||
+ wd->sta.psMgr.lastTxBroadcastFrm != wd->commTally.txBroadcastFrm ||
+ wd->sta.psMgr.lastTxMulticastFrm != wd->commTally.txMulticastFrm) )
+ {
+ zmw_enter_critical_section(dev);
+ wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm;
+ wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm;
+ wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm;
+ zmw_leave_critical_section(dev);
+
+ zfSendNullData(dev, 1);
+ }
+}
+
+static void zfPowerSavingMgrOnHandleT1(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ // If the tx Q is not empty...return
+ if ( zfIsVtxqEmpty(dev) == FALSE )
+ {
+ return;
+ }
+
+zm_debug_msg0("VtxQ is empty now...Check if HAL TXQ is empty\n");
+
+ // The the HAL TX Q is not empty...return
+ if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
+ {
+ return;
+ }
+
+zm_debug_msg0("HAL TXQ is empty now...Could go to sleep...\n");
+
+ zmw_enter_critical_section(dev);
+
+ if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
+ {
+ if (wd->sta.ReceivedPktRatePerSecond > 200)
+ {
+ zmw_leave_critical_section(dev);
+ return;
+ }
+
+ if ( zfStaIsConnected(dev)
+ && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
+ {
+ if (wd->sta.psMgr.sleepAllowedtick) {
+ wd->sta.psMgr.sleepAllowedtick--;
+ zmw_leave_critical_section(dev);
+ return;
+ }
+ }
+ }
+
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_T2;
+
+ zmw_leave_critical_section(dev);
+
+ // Send the Null pkt to AP to notify that I'm going to sleep
+ if ( zfStaIsConnected(dev) )
+ {
+zm_debug_msg0("zfPowerSavingMgrOnHandleT1 send Null data\n");
+ zfPowerSavingMgrNotifyPSToAP(dev);
+ }
+
+ // Stall the TX now
+ // zfTxEngineStop(dev);
+}
+
+static void zfPowerSavingMgrOnHandleT2(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ // Wait until the Null pkt is transmitted
+ if ( zfHpGetFreeTxdCount(dev) != zfHpGetMaxTxdCount(dev) )
+ {
+ return;
+ }
+
+ zmw_enter_critical_section(dev);
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_SLEEP;
+ wd->sta.psMgr.lastTxUnicastFrm = wd->commTally.txUnicastFrm;
+ wd->sta.psMgr.lastTxBroadcastFrm = wd->commTally.txBroadcastFrm;
+ wd->sta.psMgr.lastTxMulticastFrm = wd->commTally.txMulticastFrm;
+ zmw_leave_critical_section(dev);
+
+ // Let CHIP sleep now
+zm_debug_msg0("zfPowerSavingMgrOnHandleT2 zzzz....\n");
+ zfHpPowerSaveSetState(dev, 1);
+ wd->sta.psMgr.tempWakeUp = 0;
+}
+
+u8_t zfPowerSavingMgrIsSleeping(zdev_t *dev)
+{
+ u8_t isSleeping = FALSE;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if ( wd->sta.psMgr.state == ZM_PS_MSG_STATE_SLEEP ||
+ wd->sta.psMgr.state == ZM_PS_MSG_STATE_T2)
+ {
+ isSleeping = TRUE;
+ }
+ zmw_leave_critical_section(dev);
+ return isSleeping;
+}
+
+static u8_t zfPowerSavingMgrIsIdle(zdev_t *dev)
+{
+ u8_t isIdle = 0;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ( zfStaIsConnected(dev) && wd->sta.psMgr.isSleepAllowed == 0 )
+ {
+ goto done;
+ }
+
+ if ( wd->sta.bChannelScan )
+ {
+ goto done;
+ }
+
+ if ( zfStaIsConnecting(dev) )
+ {
+ goto done;
+ }
+
+ if (wd->sta.powerSaveMode == ZM_STA_PS_LIGHT)
+ {
+ if (wd->sta.ReceivedPktRatePerSecond > 200)
+ {
+ goto done;
+ }
+
+ if ( zfStaIsConnected(dev)
+ && (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) )
+ {
+ if (wd->sta.psMgr.sleepAllowedtick) {
+ wd->sta.psMgr.sleepAllowedtick--;
+ goto done;
+ }
+ }
+ }
+
+ isIdle = 1;
+
+done:
+ zmw_leave_critical_section(dev);
+
+ if ( zfIsVtxqEmpty(dev) == FALSE )
+ {
+ isIdle = 0;
+ }
+
+ return isIdle;
+}
+
+static void zfPowerSavingMgrSleepIfIdle(zdev_t *dev)
+{
+ u8_t isIdle;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ isIdle = zfPowerSavingMgrIsIdle(dev);
+
+ if ( isIdle == 0 )
+ {
+ return;
+ }
+
+ zmw_enter_critical_section(dev);
+
+ switch(wd->sta.powerSaveMode)
+ {
+ case ZM_STA_PS_NONE:
+ break;
+
+ case ZM_STA_PS_MAX:
+ case ZM_STA_PS_FAST:
+ case ZM_STA_PS_LIGHT:
+ zm_debug_msg0("zfPowerSavingMgrSleepIfIdle: IDLE so slep now...\n");
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_T1;
+ break;
+ }
+
+ zmw_leave_critical_section(dev);
+}
+
+static void zfPowerSavingMgrDisconnectMain(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+#ifdef ZM_ENABLE_DISCONNECT_PS
+ switch(wd->sta.psMgr.state)
+ {
+ case ZM_PS_MSG_STATE_ACTIVE:
+ zfPowerSavingMgrSleepIfIdle(dev);
+ break;
+
+ case ZM_PS_MSG_STATE_SLEEP:
+ break;
+
+ case ZM_PS_MSG_STATE_T1:
+ zfPowerSavingMgrOnHandleT1(dev);
+ break;
+
+ case ZM_PS_MSG_STATE_T2:
+ zfPowerSavingMgrOnHandleT2(dev);
+ break;
+ }
+#else
+ zfPowerSavingMgrWakeup(dev);
+#endif
+}
+
+static void zfPowerSavingMgrInfraMain(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch(wd->sta.psMgr.state)
+ {
+ case ZM_PS_MSG_STATE_ACTIVE:
+ zfPowerSavingMgrSleepIfIdle(dev);
+ break;
+
+ case ZM_PS_MSG_STATE_SLEEP:
+ break;
+
+ case ZM_PS_MSG_STATE_T1:
+ zfPowerSavingMgrOnHandleT1(dev);
+ break;
+
+ case ZM_PS_MSG_STATE_T2:
+ zfPowerSavingMgrOnHandleT2(dev);
+ break;
+ }
+}
+
+void zfPowerSavingMgrAtimWinExpired(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+//printk("zfPowerSavingMgrAtimWinExpired #1\n");
+ if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE )
+ {
+ return;
+ }
+
+//printk("zfPowerSavingMgrAtimWinExpired #2\n");
+ // if we received any ATIM window from the others to indicate we have buffered data
+ // at the other station, we can't go to sleep
+ if ( wd->sta.recvAtim )
+ {
+ wd->sta.recvAtim = 0;
+ zm_debug_msg0("Can't sleep due to receving ATIM window!");
+ return;
+ }
+
+ // if we are the one to tx beacon during last beacon interval. we can't go to sleep
+ // since we need to be alive to respond the probe request!
+ if ( wd->sta.txBeaconInd )
+ {
+ zm_debug_msg0("Can't sleep due to just transmit a beacon!");
+ return;
+ }
+
+ // If we buffer any data for the other stations. we could not go to sleep
+ if ( wd->sta.ibssPrevPSDataCount != 0 )
+ {
+ zm_debug_msg0("Can't sleep due to buffering data for the others!");
+ return;
+ }
+
+ // before sleeping, we still need to notify the others by transmitting null
+ // pkt with power mgmt bit turned on.
+ zfPowerSavingMgrOnHandleT1(dev);
+}
+
+static void zfPowerSavingMgrIBSSMain(zdev_t* dev)
+{
+ // wait for the end of
+ // if need to wait to know if we are the one to transmit the beacon
+ // during the beacon interval. If it's me, we can't go to sleep.
+
+ zmw_get_wlan_dev(dev);
+
+ switch(wd->sta.psMgr.state)
+ {
+ case ZM_PS_MSG_STATE_ACTIVE:
+ case ZM_PS_MSG_STATE_SLEEP:
+ case ZM_PS_MSG_STATE_T1:
+ break;
+
+ case ZM_PS_MSG_STATE_T2:
+ zfPowerSavingMgrOnHandleT2(dev);
+ break;
+ }
+
+ return;
+}
+
+#if 1
+void zfPowerSavingMgrMain(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch (wd->sta.adapterState)
+ {
+ case ZM_STA_STATE_DISCONNECT:
+ zfPowerSavingMgrDisconnectMain(dev);
+ break;
+ case ZM_STA_STATE_CONNECTED:
+ {
+ if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) {
+ zfPowerSavingMgrInfraMain(dev);
+ } else if (wd->wlanMode == ZM_MODE_IBSS) {
+ zfPowerSavingMgrIBSSMain(dev);
+ }
+ }
+ break;
+ case ZM_STA_STATE_CONNECTING:
+ default:
+ break;
+ }
+}
+#else
+void zfPowerSavingMgrMain(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE )
+ {
+ return;
+ }
+
+ switch(wd->sta.psMgr.state)
+ {
+ case ZM_PS_MSG_STATE_ACTIVE:
+ goto check_sleep;
+ break;
+
+ case ZM_PS_MSG_STATE_SLEEP:
+ goto sleeping;
+ break;
+
+ case ZM_PS_MSG_STATE_T1:
+ zfPowerSavingMgrOnHandleT1(dev);
+ break;
+
+ case ZM_PS_MSG_STATE_T2:
+ zfPowerSavingMgrOnHandleT2(dev);
+ break;
+ }
+
+ return;
+
+sleeping:
+ return;
+
+check_sleep:
+ zfPowerSavingMgrSleepIfIdle(dev);
+ return;
+}
+#endif
+
+#ifdef ZM_ENABLE_POWER_SAVE
+void zfPowerSavingMgrWakeup(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+//zm_debug_msg0("zfPowerSavingMgrWakeup");
+
+ //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE && ( zfPowerSavingMgrIsIdle(dev) == 0 ))
+ if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_ACTIVE )
+ {
+ zmw_enter_critical_section(dev);
+
+ wd->sta.psMgr.isSleepAllowed = 0;
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_ACTIVE;
+
+ if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE )
+ wd->sta.psMgr.tempWakeUp = 1;
+
+ zmw_leave_critical_section(dev);
+
+ // Wake up the CHIP now!!
+ zfHpPowerSaveSetState(dev, 0);
+ }
+}
+#else
+void zfPowerSavingMgrWakeup(zdev_t* dev)
+{
+}
+#endif
+
+void zfPowerSavingMgrProcessBeacon(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t length, bitmap;
+ u16_t offset, n1, n2, q, r;
+ zbuf_t* psBuf;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ if ( wd->sta.powerSaveMode == ZM_STA_PS_NONE )
+ //if ( wd->sta.psMgr.state != ZM_PS_MSG_STATE_SLEEP )
+ {
+ return;
+ }
+
+ wd->sta.psMgr.isSleepAllowed = 1;
+
+ if ( (offset=zfFindElement(dev, buf, ZM_WLAN_EID_TIM)) != 0xffff )
+ {
+ length = zmw_rx_buf_readb(dev, buf, offset+1);
+
+ if ( length > 3 )
+ {
+ n1 = zmw_rx_buf_readb(dev, buf, offset+4) & (~ZM_BIT_0);
+ n2 = length + n1 - 4;
+ q = wd->sta.aid >> 3;
+ r = wd->sta.aid & 7;
+
+ if ((q >= n1) && (q <= n2))
+ {
+ bitmap = zmw_rx_buf_readb(dev, buf, offset+5+q-n1);
+
+ if ( (bitmap >> r) & ZM_BIT_0 )
+ {
+ //if ( wd->sta.powerSaveMode == ZM_STA_PS_FAST )
+ if ( 0 )
+ {
+ wd->sta.psMgr.state = ZM_PS_MSG_STATE_S1;
+ //zfSendPSPoll(dev);
+ zfSendNullData(dev, 0);
+ }
+ else
+ {
+ if ((wd->sta.qosInfo&0xf) != 0xf)
+ {
+ /* send ps-poll */
+ //printk("zfSendPSPoll #1\n");
+
+ wd->sta.psMgr.isSleepAllowed = 0;
+
+ switch (wd->sta.powerSaveMode)
+ {
+ case ZM_STA_PS_MAX:
+ case ZM_STA_PS_FAST:
+ //zm_debug_msg0("wake up and send PS-Poll\n");
+ zfSendPSPoll(dev);
+ break;
+ case ZM_STA_PS_LIGHT:
+ zm_debug_msg0("wake up and send null data\n");
+
+ zmw_enter_critical_section(dev);
+ wd->sta.psMgr.sleepAllowedtick = 400;
+ zmw_leave_critical_section(dev);
+
+ zfSendNullData(dev, 0);
+ break;
+ }
+
+ wd->sta.psMgr.tempWakeUp = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ while ((psBuf = zfQueueGet(dev, wd->sta.uapsdQ)) != NULL)
+ {
+ zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ }
+
+ //printk("zfPowerSavingMgrProcessBeacon #1\n");
+ zfPowerSavingMgrMain(dev);
+}
+
+void zfPowerSavingMgrConnectNotify(zdev_t *dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ switch(wd->sta.powerSaveMode)
+ {
+ case ZM_STA_PS_NONE:
+ zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
+ break;
+
+ case ZM_STA_PS_FAST:
+ case ZM_STA_PS_MAX:
+ case ZM_STA_PS_LIGHT:
+ zfHpPowerSaveSetMode(dev, 0, 1, wd->beaconInterval);
+ break;
+
+ default:
+ zfHpPowerSaveSetMode(dev, 0, 0, wd->beaconInterval);
+ break;
+ }
+ }
+}
+
+void zfPowerSavingMgrPreTBTTInterrupt(zdev_t *dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ /* disable TBTT interrupt when change from connection to disconnect */
+ if (zfStaIsDisconnect(dev)) {
+ zfHpPowerSaveSetMode(dev, 0, 0, 0);
+ zfPowerSavingMgrWakeup(dev);
+ return;
+ }
+
+ zmw_enter_critical_section(dev);
+ wd->sta.psMgr.ticks++;
+
+ if ( wd->sta.psMgr.ticks < wd->sta.psMgr.maxSleepPeriods )
+ {
+ zmw_leave_critical_section(dev);
+ return;
+ }
+ else
+ {
+ wd->sta.psMgr.ticks = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zfPowerSavingMgrWakeup(dev);
+}
+
+/* Leave an empty line below to remove warning message on some compiler */
+
diff --git a/drivers/staging/otus/80211core/cscanmgr.c b/drivers/staging/otus/80211core/cscanmgr.c
new file mode 100644
index 000000000000..b32835c87590
--- /dev/null
+++ b/drivers/staging/otus/80211core/cscanmgr.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+
+void zfScanMgrInit(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.scanMgr.scanReqs[0] = 0;
+ wd->sta.scanMgr.scanReqs[1] = 0;
+
+ wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE;
+ wd->sta.scanMgr.scanStartDelay = 3;
+ //wd->sta.scanMgr.scanStartDelay = 0;
+}
+
+u8_t zfScanMgrScanStart(zdev_t* dev, u8_t scanType)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg1("scanType = ", scanType);
+
+ zmw_declare_for_critical_section();
+
+ if ( scanType != ZM_SCAN_MGR_SCAN_INTERNAL &&
+ scanType != ZM_SCAN_MGR_SCAN_EXTERNAL )
+ {
+ zm_debug_msg0("unknown scanType");
+ return 1;
+ }
+ else if (zfStaIsConnecting(dev))
+ {
+ zm_debug_msg0("reject scan request due to connecting");
+ return 1;
+ }
+
+ i = scanType - 1;
+
+ zmw_enter_critical_section(dev);
+
+ if ( wd->sta.scanMgr.scanReqs[i] == 1 )
+ {
+ zm_debug_msg1("scan rescheduled", scanType);
+ goto scan_done;
+ }
+
+ wd->sta.scanMgr.scanReqs[i] = 1;
+ zm_debug_msg1("scan scheduled: ", scanType);
+
+ // If there's no scan pending, we do the scan right away.
+ // If there's an internal scan and the new scan request is external one,
+ // we will restart the scan.
+ if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE )
+ {
+ goto schedule_scan;
+ }
+ else if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_INTERNAL &&
+ scanType == ZM_SCAN_MGR_SCAN_EXTERNAL )
+ {
+ // Stop the internal scan & schedule external scan first
+ zfTimerCancel(dev, ZM_EVENT_SCAN);
+
+ /* Fix for WHQL sendrecv => we do not apply delay time in which the device
+ stop transmitting packet when we already connect to some AP */
+ wd->sta.bScheduleScan = FALSE;
+
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+
+ wd->sta.bChannelScan = FALSE;
+ goto schedule_scan;
+ }
+ else
+ {
+ zm_debug_msg0("Scan is busy...waiting later to start\n");
+ }
+
+ zmw_leave_critical_section(dev);
+ return 0;
+
+scan_done:
+ zmw_leave_critical_section(dev);
+ return 1;
+
+schedule_scan:
+
+ wd->sta.bScheduleScan = TRUE;
+
+ zfTimerSchedule(dev, ZM_EVENT_SCAN, wd->sta.scanMgr.scanStartDelay);
+ wd->sta.scanMgr.scanStartDelay = 3;
+ //wd->sta.scanMgr.scanStartDelay = 0;
+ wd->sta.scanMgr.currScanType = scanType;
+ zmw_leave_critical_section(dev);
+
+ if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ {
+ zfSendNullData(dev, 1);
+ }
+ return 0;
+}
+
+void zfScanMgrScanStop(zdev_t* dev, u8_t scanType)
+{
+ u8_t scanNotifyRequired = 0;
+ u8_t theOtherScan = ZM_SCAN_MGR_SCAN_NONE;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE )
+ {
+ zm_assert(wd->sta.scanMgr.scanReqs[0] == 0);
+ zm_assert(wd->sta.scanMgr.scanReqs[1] == 0);
+ goto done;
+ }
+
+ switch(scanType)
+ {
+ case ZM_SCAN_MGR_SCAN_EXTERNAL:
+ scanNotifyRequired = 1;
+ theOtherScan = ZM_SCAN_MGR_SCAN_INTERNAL;
+ break;
+
+ case ZM_SCAN_MGR_SCAN_INTERNAL:
+ theOtherScan = ZM_SCAN_MGR_SCAN_EXTERNAL;
+ break;
+
+ default:
+ goto done;
+ }
+
+ if ( wd->sta.scanMgr.currScanType != scanType )
+ {
+ goto stop_done;
+ }
+
+ zfTimerCancel(dev, ZM_EVENT_SCAN);
+
+ /* Fix for WHQL sendrecv => we do not apply delay time in which the device
+ stop transmitting packet when we already connect to some AP */
+ wd->sta.bScheduleScan = FALSE;
+
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+
+ wd->sta.bChannelScan = FALSE;
+ wd->sta.scanFrequency = 0;
+
+ if ( wd->sta.scanMgr.scanReqs[theOtherScan - 1] )
+ {
+ wd->sta.scanMgr.currScanType = theOtherScan;
+
+ // Schedule the other scan after 1 second later
+ zfTimerSchedule(dev, ZM_EVENT_SCAN, 100);
+ }
+ else
+ {
+ wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE;
+ }
+
+stop_done:
+ wd->sta.scanMgr.scanReqs[scanType - 1] = 0;
+
+ zmw_leave_critical_section(dev);
+
+ /* avoid lose receive packet when site survey */
+ if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ {
+ zfSendNullData(dev, 0);
+ }
+
+ if ( scanNotifyRequired )
+ {
+ zm_debug_msg0("Scan notify after reset");
+ if (wd->zfcbScanNotify != NULL)
+ {
+ wd->zfcbScanNotify(dev, NULL);
+ }
+ }
+
+ return;
+
+done:
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+void zfScanMgrScanAck(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ wd->sta.scanMgr.scanStartDelay = 3;
+ //wd->sta.scanMgr.scanStartDelay = 0;
+
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+extern void zfStaReconnect(zdev_t* dev);
+
+static void zfScanSendProbeRequest(zdev_t* dev)
+{
+ u8_t k;
+ u16_t dst[3] = { 0xffff, 0xffff, 0xffff };
+
+ zmw_get_wlan_dev(dev);
+
+ /* Increase rxBeaconCount to prevent beacon lost */
+ if (zfStaIsConnected(dev))
+ {
+ wd->sta.rxBeaconCount++;
+ }
+
+ if ( wd->sta.bPassiveScan )
+ {
+ return;
+ }
+ /* enable 802.l11h and in DFS Band , disable sending probe request */
+ if (wd->sta.DFSEnable)
+ {
+ if (zfHpIsDfsChannel(dev, wd->sta.scanFrequency))
+ {
+ return;
+ }
+ }
+
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, 0, 0, 0);
+
+ if ( wd->sta.disableProbingWithSsid )
+ {
+ return;
+ }
+
+ for (k=1; k<=ZM_MAX_PROBE_HIDDEN_SSID_SIZE; k++)
+ {
+ if ( wd->ws.probingSsidList[k-1].ssidLen != 0 )
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, k, 0, 0);
+ }
+ }
+}
+
+static void zfScanMgrEventSetFreqCompleteCb(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+//printk("zfScanMgrEventSetFreqCompleteCb #1\n");
+
+ zmw_enter_critical_section(dev);
+ zfTimerSchedule(dev, ZM_EVENT_IN_SCAN, ZM_TICK_IN_SCAN);
+ if (wd->sta.bPassiveScan)
+ {
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.passiveScanTickPerChannel);
+ }
+ else
+ {
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.activescanTickPerChannel);
+ }
+ zmw_leave_critical_section(dev);
+
+ zfScanSendProbeRequest(dev);
+}
+
+
+static void zfScanMgrEventScanCompleteCb(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ {
+ zfSendNullData(dev, 0);
+ }
+ return;
+}
+
+
+void zfScanMgrScanEventRetry(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( !wd->sta.bChannelScan )
+ {
+ return;
+ }
+
+ if ( !wd->sta.bPassiveScan )
+ {
+ zfScanSendProbeRequest(dev);
+ #if 0
+ zmw_enter_critical_section(dev);
+ zfTimerSchedule(dev, ZM_EVENT_IN_SCAN, ZM_TICK_IN_SCAN);
+ zmw_leave_critical_section(dev);
+ #endif
+ }
+}
+
+u8_t zfScanMgrScanEventTimeout(zdev_t* dev)
+{
+ u16_t nextScanFrequency = 0;
+ u8_t temp;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if ( wd->sta.scanFrequency == 0 )
+ {
+ zmw_leave_critical_section(dev);
+ return -1;
+ }
+
+ nextScanFrequency = zfChGetNextChannel(dev, wd->sta.scanFrequency,
+ &wd->sta.bPassiveScan);
+
+ if ( (nextScanFrequency == 0xffff)
+ || (wd->sta.scanFrequency == zfChGetLastChannel(dev, &temp)) )
+ {
+ u8_t currScanType;
+ u8_t isExternalScan = 0;
+ u8_t isInternalScan = 0;
+
+ //zm_debug_msg1("end scan = ", KeQueryInterruptTime());
+ wd->sta.scanFrequency = 0;
+
+ zm_debug_msg1("scan 1 type: ", wd->sta.scanMgr.currScanType);
+ zm_debug_msg1("scan channel count = ", wd->regulationTable.allowChannelCnt);
+
+ //zfBssInfoRefresh(dev);
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+
+ if ( wd->sta.bChannelScan == FALSE )
+ {
+ zm_debug_msg0("WOW!! scan is cancelled\n");
+ zmw_leave_critical_section(dev);
+ goto report_scan_result;
+ }
+
+
+ currScanType = wd->sta.scanMgr.currScanType;
+ switch(currScanType)
+ {
+ case ZM_SCAN_MGR_SCAN_EXTERNAL:
+ isExternalScan = 1;
+
+ if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] )
+ {
+ wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] = 0;
+ isInternalScan = 1;
+ }
+
+ break;
+
+ case ZM_SCAN_MGR_SCAN_INTERNAL:
+ isInternalScan = 1;
+
+ if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_EXTERNAL - 1] )
+ {
+ // Because the external scan should pre-empts internal scan.
+ // So this shall not be happened!!
+ zm_assert(0);
+ }
+
+ break;
+
+ default:
+ zm_assert(0);
+ break;
+ }
+
+ wd->sta.scanMgr.scanReqs[currScanType - 1] = 0;
+ wd->sta.scanMgr.scanStartDelay = 100;
+ wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE;
+ zmw_leave_critical_section(dev);
+
+ //Set channel according to AP's configuration
+ zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
+ wd->ExtOffset, zfScanMgrEventScanCompleteCb);
+
+ wd->sta.bChannelScan = FALSE;
+
+ #if 1
+ if (zfStaIsConnected(dev))
+ { // Finish site survey, reset the variable to detect using wrong frequency !
+ zfHpFinishSiteSurvey(dev, 1);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 2;
+ wd->tickIbssReceiveBeacon = 0;
+ wd->sta.ibssReceiveBeaconCount = 0;
+ zmw_leave_critical_section(dev);
+
+ /* #5 Re-enable RIFS function after the site survey ! */
+ /* This is because switch band will reset the BB register to initial value */
+ if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTED )
+ {
+ zfHpEnableRifs(dev, ((wd->sta.currentFrequency<3000)?1:0), wd->sta.EnableHT, wd->sta.HT2040);
+ }
+ }
+ else
+ {
+ zfHpFinishSiteSurvey(dev, 0);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 0;
+ zmw_leave_critical_section(dev);
+ }
+ #endif
+
+report_scan_result:
+ /* avoid lose receive packet when site survey */
+ //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ //{
+ // zfSendNullData(dev, 0);
+ //}
+
+ if ( isExternalScan )//Quickly reboot
+ {
+ if (wd->zfcbScanNotify != NULL)
+ {
+ wd->zfcbScanNotify(dev, NULL);
+ }
+ }
+
+ if ( isInternalScan )
+ {
+ //wd->sta.InternalScanReq = 0;
+ zfStaReconnect(dev);
+ }
+
+ return 0;
+ }
+ else
+ {
+ wd->sta.scanFrequency = nextScanFrequency;
+
+ //zmw_enter_critical_section(dev);
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+ zmw_leave_critical_section(dev);
+
+ zm_debug_msg0("scan 2");
+ zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb);
+
+ return 1;
+ }
+}
+
+void zfScanMgrScanEventStart(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( wd->sta.bChannelScan )
+ {
+ return;
+ }
+
+ zfPowerSavingMgrWakeup(dev);
+
+ zmw_enter_critical_section(dev);
+
+ if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE )
+ {
+ goto no_scan;
+ }
+
+ //zfBssInfoRefresh(dev);
+ zfBssInfoRefresh(dev, 0);
+ wd->sta.bChannelScan = TRUE;
+ wd->sta.bScheduleScan = FALSE;
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+
+ //zm_debug_msg1("start scan = ", KeQueryInterruptTime());
+ wd->sta.scanFrequency = zfChGetFirstChannel(dev, &wd->sta.bPassiveScan);
+ zmw_leave_critical_section(dev);
+
+ /* avoid lose receive packet when site survey */
+ //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ //{
+ // zfSendNullData(dev, 1);
+ //}
+// zm_debug_msg0("scan 0");
+// zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb);
+
+ #if 1
+ if (zfStaIsConnected(dev))
+ {// If doing site survey !
+ zfHpBeginSiteSurvey(dev, 1);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 1;
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zfHpBeginSiteSurvey(dev, 0);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 0;
+ zmw_leave_critical_section(dev);
+ }
+ #endif
+
+ zm_debug_msg0("scan 0");
+ zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb);
+
+ return;
+
+no_scan:
+ zmw_leave_critical_section(dev);
+ return;
+}
diff --git a/drivers/staging/otus/80211core/ctkip.c b/drivers/staging/otus/80211core/ctkip.c
new file mode 100644
index 000000000000..be42f7aaa37d
--- /dev/null
+++ b/drivers/staging/otus/80211core/ctkip.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : ctkip.c */
+/* */
+/* Abstract */
+/* This module contains Tx and Rx functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+
+u16_t zgTkipSboxLower[256] =
+ {
+ 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54,
+ 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A,
+ 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B,
+ 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B,
+ 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F,
+ 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F,
+ 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5,
+ 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F,
+ 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB,
+ 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97,
+ 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED,
+ 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A,
+ 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94,
+ 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3,
+ 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04,
+ 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D,
+ 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39,
+ 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95,
+ 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83,
+ 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76,
+ 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4,
+ 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B,
+ 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0,
+ 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18,
+ 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51,
+ 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85,
+ 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12,
+ 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9,
+ 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7,
+ 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A,
+ 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8,
+ 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A
+ };
+
+
+u16_t zgTkipSboxUpper[256] =
+ {
+ 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91,
+ 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC,
+ 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB,
+ 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B,
+ 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83,
+ 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A,
+ 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F,
+ 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA,
+ 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B,
+ 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13,
+ 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6,
+ 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85,
+ 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11,
+ 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B,
+ 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1,
+ 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF,
+ 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E,
+ 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6,
+ 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B,
+ 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD,
+ 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8,
+ 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2,
+ 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49,
+ 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10,
+ 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97,
+ 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F,
+ 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C,
+ 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27,
+ 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33,
+ 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5,
+ 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0,
+ 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C
+ };
+
+u16_t zfrotr1(u16_t a)
+// rotate right by 1 bit.
+{
+ u16_t b;
+
+ if (a & 0x01)
+ {
+ b = (a >> 1) | 0x8000;
+ }
+ else
+ {
+ b = (a >> 1) & 0x7fff;
+ }
+ return b;
+}
+
+/*************************************************************/
+/* zfTkipSbox() */
+/* Returns a 16 bit value from a 64K entry table. The Table */
+/* is synthesized from two 256 entry byte wide tables. */
+/*************************************************************/
+u16_t zfTkipSbox(u16_t index)
+{
+ u16_t low;
+ u16_t high;
+ u16_t left, right;
+
+ low = (index & 0xFF);
+ high = ((index >> 8) & 0xFF);
+
+ left = zgTkipSboxLower[low] + (zgTkipSboxUpper[low] << 8 );
+ right = zgTkipSboxUpper[high] + (zgTkipSboxLower[high] << 8 );
+
+ return (left ^ right);
+}
+
+u8_t zfTkipPhase1KeyMix(u32_t iv32, struct zsTkipSeed* pSeed)
+{
+ u16_t tsc0;
+ u16_t tsc1;
+ u16_t i, j;
+#if 0
+ /* Need not proceed this function with the same iv32 */
+ if ( iv32 == pSeed->iv32 )
+ {
+ return 1;
+ }
+#endif
+ tsc0 = (u16_t) ((iv32 >> 16) & 0xffff); /* msb */
+ tsc1 = (u16_t) (iv32 & 0xffff);
+
+ /* Phase 1, step 1 */
+ pSeed->ttak[0] = tsc1;
+ pSeed->ttak[1] = tsc0;
+ pSeed->ttak[2] = (u16_t) (pSeed->ta[0] + (pSeed->ta[1] <<8));
+ pSeed->ttak[3] = (u16_t) (pSeed->ta[2] + (pSeed->ta[3] <<8));
+ pSeed->ttak[4] = (u16_t) (pSeed->ta[4] + (pSeed->ta[5] <<8));
+
+ /* Phase 1, step 2 */
+ for (i=0; i<8; i++)
+ {
+ j = 2*(i & 1);
+ pSeed->ttak[0] =(pSeed->ttak[0] + zfTkipSbox(pSeed->ttak[4]
+ ^ ZM_BYTE_TO_WORD(pSeed->tk[1+j], pSeed->tk[j])))
+ & 0xffff;
+ pSeed->ttak[1] =(pSeed->ttak[1] + zfTkipSbox(pSeed->ttak[0]
+ ^ ZM_BYTE_TO_WORD(pSeed->tk[5+j], pSeed->tk[4+j] )))
+ & 0xffff;
+ pSeed->ttak[2] =(pSeed->ttak[2] + zfTkipSbox(pSeed->ttak[1]
+ ^ ZM_BYTE_TO_WORD(pSeed->tk[9+j], pSeed->tk[8+j] )))
+ & 0xffff;
+ pSeed->ttak[3] =(pSeed->ttak[3] + zfTkipSbox(pSeed->ttak[2]
+ ^ ZM_BYTE_TO_WORD(pSeed->tk[13+j], pSeed->tk[12+j])))
+ & 0xffff;
+ pSeed->ttak[4] =(pSeed->ttak[4] + zfTkipSbox(pSeed->ttak[3]
+ ^ ZM_BYTE_TO_WORD(pSeed->tk[1+j], pSeed->tk[j] )))
+ & 0xffff;
+ pSeed->ttak[4] =(pSeed->ttak[4] + i) & 0xffff;
+ }
+
+ if ( iv32 == (pSeed->iv32+1) )
+ {
+ pSeed->iv32tmp = iv32;
+ return 1;
+ }
+
+ return 0;
+}
+
+u8_t zfTkipPhase2KeyMix(u16_t iv16, struct zsTkipSeed* pSeed)
+{
+ u16_t tsc2;
+
+ tsc2 = iv16;
+
+ /* Phase 2, Step 1 */
+ pSeed->ppk[0] = pSeed->ttak[0];
+ pSeed->ppk[1] = pSeed->ttak[1];
+ pSeed->ppk[2] = pSeed->ttak[2];
+ pSeed->ppk[3] = pSeed->ttak[3];
+ pSeed->ppk[4] = pSeed->ttak[4];
+ pSeed->ppk[5] = (pSeed->ttak[4] + tsc2) & 0xffff;
+
+ /* Phase2, Step 2 */
+ pSeed->ppk[0] = pSeed->ppk[0]
+ + zfTkipSbox(pSeed->ppk[5] ^ ZM_BYTE_TO_WORD(pSeed->tk[1],pSeed->tk[0]));
+ pSeed->ppk[1] = pSeed->ppk[1]
+ + zfTkipSbox(pSeed->ppk[0] ^ ZM_BYTE_TO_WORD(pSeed->tk[3],pSeed->tk[2]));
+ pSeed->ppk[2] = pSeed->ppk[2]
+ + zfTkipSbox(pSeed->ppk[1] ^ ZM_BYTE_TO_WORD(pSeed->tk[5],pSeed->tk[4]));
+ pSeed->ppk[3] = pSeed->ppk[3]
+ + zfTkipSbox(pSeed->ppk[2] ^ ZM_BYTE_TO_WORD(pSeed->tk[7],pSeed->tk[6]));
+ pSeed->ppk[4] = pSeed->ppk[4]
+ + zfTkipSbox(pSeed->ppk[3] ^ ZM_BYTE_TO_WORD(pSeed->tk[9],pSeed->tk[8]));
+ pSeed->ppk[5] = pSeed->ppk[5]
+ + zfTkipSbox(pSeed->ppk[4] ^ ZM_BYTE_TO_WORD(pSeed->tk[11],pSeed->tk[10]));
+
+ pSeed->ppk[0] = pSeed->ppk[0]
+ + zfrotr1(pSeed->ppk[5] ^ ZM_BYTE_TO_WORD(pSeed->tk[13],pSeed->tk[12]));
+ pSeed->ppk[1] = pSeed->ppk[1]
+ + zfrotr1(pSeed->ppk[0] ^ ZM_BYTE_TO_WORD(pSeed->tk[15],pSeed->tk[14]));
+ pSeed->ppk[2] = pSeed->ppk[2] + zfrotr1(pSeed->ppk[1]);
+ pSeed->ppk[3] = pSeed->ppk[3] + zfrotr1(pSeed->ppk[2]);
+ pSeed->ppk[4] = pSeed->ppk[4] + zfrotr1(pSeed->ppk[3]);
+ pSeed->ppk[5] = pSeed->ppk[5] + zfrotr1(pSeed->ppk[4]);
+
+ if (iv16 == 0)
+ {
+ if (pSeed->iv16 == 0xffff)
+ {
+ pSeed->iv16tmp=0;
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if (iv16 == (pSeed->iv16+1))
+ {
+ pSeed->iv16tmp = iv16;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void zfTkipInit(u8_t* key, u8_t* ta, struct zsTkipSeed* pSeed, u8_t* initIv)
+{
+ u16_t iv16;
+ u32_t iv32;
+ u16_t i;
+
+ /* clear memory */
+ zfZeroMemory((u8_t*) pSeed, sizeof(struct zsTkipSeed));
+ /* set key to seed */
+ zfMemoryCopy(pSeed->ta, ta, 6);
+ zfMemoryCopy(pSeed->tk, key, 16);
+
+ iv16 = *initIv++;
+ iv16 += *initIv<<8;
+ initIv++;
+
+ iv32=0;
+
+ for(i=0; i<4; i++) // initiv is little endian
+ {
+ iv32 += *initIv<<(i*8);
+ *initIv++;
+ }
+
+ pSeed->iv32 = iv32+1; // Force Recalculating on Tkip Phase1
+ zfTkipPhase1KeyMix(iv32, pSeed);
+
+ pSeed->iv16 = iv16;
+ pSeed->iv32 = iv32;
+}
+
+u32_t zfGetU32t(u8_t* p)
+{
+ u32_t res=0;
+ u16_t i;
+
+ for( i=0; i<4; i++ )
+ {
+ res |= (*p++) << (8*i);
+ }
+
+ return res;
+
+}
+
+void zfPutU32t(u8_t* p, u32_t value)
+{
+ u16_t i;
+
+ for(i=0; i<4; i++)
+ {
+ *p++ = (u8_t) (value & 0xff);
+ value >>= 8;
+ }
+}
+
+void zfMicClear(struct zsMicVar* pMic)
+{
+ pMic->left = pMic->k0;
+ pMic->right = pMic->k1;
+ pMic->nBytes = 0;
+ pMic->m = 0;
+}
+
+void zfMicSetKey(u8_t* key, struct zsMicVar* pMic)
+{
+ pMic->k0 = zfGetU32t(key);
+ pMic->k1 = zfGetU32t(key+4);
+ zfMicClear(pMic);
+}
+
+void zfMicAppendByte(u8_t b, struct zsMicVar* pMic)
+{
+ // Append the byte to our word-sized buffer
+ pMic->m |= b << (8* pMic->nBytes);
+ pMic->nBytes++;
+
+ // Process the word if it is full.
+ if ( pMic->nBytes >= 4 )
+ {
+ pMic->left ^= pMic->m;
+ pMic->right ^= ZM_ROL32(pMic->left, 17 );
+ pMic->left += pMic->right;
+ pMic->right ^= ((pMic->left & 0xff00ff00) >> 8) |
+ ((pMic->left & 0x00ff00ff) << 8);
+ pMic->left += pMic->right;
+ pMic->right ^= ZM_ROL32( pMic->left, 3 );
+ pMic->left += pMic->right;
+ pMic->right ^= ZM_ROR32( pMic->left, 2 );
+ pMic->left += pMic->right;
+ // Clear the buffer
+ pMic->m = 0;
+ pMic->nBytes = 0;
+ }
+}
+
+void zfMicGetMic(u8_t* dst, struct zsMicVar* pMic)
+{
+ // Append the minimum padding
+ zfMicAppendByte(0x5a, pMic);
+ zfMicAppendByte(0, pMic);
+ zfMicAppendByte(0, pMic);
+ zfMicAppendByte(0, pMic);
+ zfMicAppendByte(0, pMic);
+
+ // and then zeroes until the length is a multiple of 4
+ while( pMic->nBytes != 0 )
+ {
+ zfMicAppendByte(0, pMic);
+ }
+
+ // The appendByte function has already computed the result.
+ zfPutU32t(dst, pMic->left);
+ zfPutU32t(dst+4, pMic->right);
+
+ // Reset to the empty message.
+ zfMicClear(pMic);
+
+}
+
+u8_t zfMicRxVerify(zdev_t* dev, zbuf_t* buf)
+{
+ struct zsMicVar* pMicKey;
+ struct zsMicVar MyMicKey;
+ u8_t mic[8];
+ u8_t da[6];
+ u8_t sa[6];
+ u8_t bValue;
+ u16_t i, payloadOffset, tailOffset;
+
+ zmw_get_wlan_dev(dev);
+
+ /* need not check MIC if pMicKEy is equal to NULL */
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ pMicKey = zfApGetRxMicKey(dev, buf);
+
+ if ( pMicKey != NULL )
+ {
+ zfCopyFromRxBuffer(dev, buf, sa, ZM_WLAN_HEADER_A2_OFFSET, 6);
+ zfCopyFromRxBuffer(dev, buf, da, ZM_WLAN_HEADER_A3_OFFSET, 6);
+ }
+ else
+ {
+ return ZM_MIC_SUCCESS;
+ }
+ }
+ else if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ pMicKey = zfStaGetRxMicKey(dev, buf);
+
+ if ( pMicKey != NULL )
+ {
+ zfCopyFromRxBuffer(dev, buf, sa, ZM_WLAN_HEADER_A3_OFFSET, 6);
+ zfCopyFromRxBuffer(dev, buf, da, ZM_WLAN_HEADER_A1_OFFSET, 6);
+ }
+ else
+ {
+ return ZM_MIC_SUCCESS;
+ }
+ }
+ else
+ {
+ return ZM_MIC_SUCCESS;
+ }
+
+ MyMicKey.k0=pMicKey->k0;
+ MyMicKey.k1=pMicKey->k1;
+ pMicKey = &MyMicKey;
+
+ zfMicClear(pMicKey);
+ tailOffset = zfwBufGetSize(dev, buf);
+ tailOffset -= 8;
+
+ /* append DA */
+ for(i=0; i<6; i++)
+ {
+ zfMicAppendByte(da[i], pMicKey);
+ }
+ /* append SA */
+ for(i=0; i<6; i++)
+ {
+ zfMicAppendByte(sa[i], pMicKey);
+ }
+
+ /* append for alignment */
+ if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) != 0)
+ zfMicAppendByte(zmw_rx_buf_readb(dev, buf,24)&0x7, pMicKey);
+ else
+ zfMicAppendByte(0, pMicKey);
+ zfMicAppendByte(0, pMicKey);
+ zfMicAppendByte(0, pMicKey);
+ zfMicAppendByte(0, pMicKey);
+
+ /* append payload */
+ payloadOffset = ZM_SIZE_OF_WLAN_DATA_HEADER +
+ ZM_SIZE_OF_IV +
+ ZM_SIZE_OF_EXT_IV;
+
+ if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) != 0)
+ {
+ /* Qos Packet, Plcpheader + 2 */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ /* TODO : Rx Qos element offset in software MIC check */
+ }
+ else if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ if (wd->sta.wmeConnected != 0)
+ {
+ payloadOffset += 2;
+ }
+ }
+ }
+
+ for(i=payloadOffset; i<tailOffset; i++)
+ {
+ bValue = zmw_rx_buf_readb(dev, buf, i);
+ zfMicAppendByte(bValue, pMicKey);
+ }
+
+ zfMicGetMic(mic, pMicKey);
+
+ if ( !zfRxBufferEqualToStr(dev, buf, mic, tailOffset, 8) )
+ {
+ return ZM_MIC_FAILURE;
+ }
+
+ return ZM_MIC_SUCCESS;
+}
+
+void zfTkipGetseeds(u16_t iv16, u8_t *RC4Key, struct zsTkipSeed *Seed)
+{
+ RC4Key[0] = ZM_HI8(iv16);
+ RC4Key[1] = (ZM_HI8(iv16) | 0x20) & 0x7f;
+ RC4Key[2] = ZM_LO8(iv16);
+ RC4Key[3] = ((Seed->ppk[5] ^ ZM_BYTE_TO_WORD(Seed->tk[1],Seed->tk[0]))>>1) & 0xff;
+ RC4Key[4] = Seed->ppk[0] & 0xff;
+ RC4Key[5] = Seed->ppk[0] >> 8;
+ RC4Key[6] = Seed->ppk[1] & 0xff;
+ RC4Key[7] = Seed->ppk[1] >> 8;
+ RC4Key[8] = Seed->ppk[2] & 0xff;
+ RC4Key[9] = Seed->ppk[2] >> 8;
+ RC4Key[10] = Seed->ppk[3] & 0xff;
+ RC4Key[11] = Seed->ppk[3] >> 8;
+ RC4Key[12] = Seed->ppk[4] & 0xff;
+ RC4Key[13] = Seed->ppk[4] >> 8;
+ RC4Key[14] = Seed->ppk[5] & 0xff;
+ RC4Key[15] = Seed->ppk[5] >> 8;
+}
+
+void zfCalTxMic(zdev_t *dev, zbuf_t *buf, u8_t *snap, u16_t snapLen, u16_t offset, u16_t *da, u16_t *sa, u8_t up, u8_t *mic)
+{
+ struct zsMicVar* pMicKey;
+ u16_t i;
+ u16_t len;
+ u8_t bValue;
+ u8_t qosType;
+ u8_t *pDa = (u8_t *)da;
+ u8_t *pSa = (u8_t *)sa;
+
+ zmw_get_wlan_dev(dev);
+
+ /* need not check MIC if pMicKEy is equal to NULL */
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ pMicKey = zfApGetTxMicKey(dev, buf, &qosType);
+
+ if ( pMicKey == NULL )
+ return;
+ }
+ else if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ pMicKey = zfStaGetTxMicKey(dev, buf);
+
+ if ( pMicKey == NULL )
+ {
+ zm_debug_msg0("pMicKey is NULL");
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ zfMicClear(pMicKey);
+ len = zfwBufGetSize(dev, buf);
+
+ /* append DA */
+ for(i = 0; i < 6; i++)
+ {
+ zfMicAppendByte(pDa[i], pMicKey);
+ }
+
+ /* append SA */
+ for(i = 0; i < 6; i++)
+ {
+ zfMicAppendByte(pSa[i], pMicKey);
+ }
+
+ if (up != 0)
+ zfMicAppendByte((up&0x7), pMicKey);
+ else
+ zfMicAppendByte(0, pMicKey);
+
+ zfMicAppendByte(0, pMicKey);
+ zfMicAppendByte(0, pMicKey);
+ zfMicAppendByte(0, pMicKey);
+
+ /* For Snap header */
+ for(i = 0; i < snapLen; i++)
+ {
+ zfMicAppendByte(snap[i], pMicKey);
+ }
+
+ for(i = offset; i < len; i++)
+ {
+ bValue = zmw_tx_buf_readb(dev, buf, i);
+ zfMicAppendByte(bValue, pMicKey);
+ }
+
+ zfMicGetMic(mic, pMicKey);
+}
+
+void zfTKIPEncrypt(zdev_t *dev, zbuf_t *buf, u8_t *snap, u16_t snapLen, u16_t offset, u8_t keyLen, u8_t* key, u32_t* icv)
+{
+ u8_t iv[3];
+
+ iv[0] = key[0];
+ iv[1] = key[1];
+ iv[2] = key[2];
+
+ keyLen -= 3;
+
+ zfWEPEncrypt(dev, buf, snap, snapLen, offset, keyLen, &key[3], iv);
+}
+
+u16_t zfTKIPDecrypt(zdev_t *dev, zbuf_t *buf, u16_t offset, u8_t keyLen, u8_t* key)
+{
+ u16_t ret = ZM_ICV_SUCCESS;
+ u8_t iv[3];
+
+ iv[0] = key[0];
+ iv[1] = key[1];
+ iv[2] = key[2];
+
+ keyLen -= 3;
+
+ ret = zfWEPDecrypt(dev, buf, offset, keyLen, &key[3], iv);
+
+ return ret;
+}
diff --git a/drivers/staging/otus/80211core/ctxrx.c b/drivers/staging/otus/80211core/ctxrx.c
new file mode 100644
index 000000000000..e258a7df5363
--- /dev/null
+++ b/drivers/staging/otus/80211core/ctxrx.c
@@ -0,0 +1,4096 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : htr.c */
+/* */
+/* Abstract */
+/* This module contains Tx and Rx functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+
+u16_t zfWlanRxValidate(zdev_t* dev, zbuf_t* buf);
+u16_t zfWlanRxFilter(zdev_t* dev, zbuf_t* buf);
+
+
+
+const u8_t zgSnapBridgeTunnel[6] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0xF8 };
+const u8_t zgSnap8021h[6] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 };
+/* Table for converting IP DSCP P2-P0 bits to 802.11e Access Category */
+const u8_t zcUpToAc[8] = {0, 1, 1, 0, 2, 2, 3, 3}; //WMM default
+//const u8_t zcUpToAc[8] = {0, 1, 1, 0, 0, 0, 0, 0}; //For 2 TxQ
+//const u8_t zcUpToAc[8] = {0, 0, 0, 0, 0, 0, 0, 0}; //For single TxQ
+const u8_t zcMaxspToPktNum[4] = {8, 2, 4, 6};
+
+u8_t zfGetEncryModeFromRxStatus(struct zsAdditionInfo* addInfo)
+{
+ u8_t securityByte;
+ u8_t encryMode;
+
+ securityByte = (addInfo->Tail.Data.SAIndex & 0xc0) >> 4; /* byte4 */
+ securityByte |= (addInfo->Tail.Data.DAIndex & 0xc0) >> 6; /* byte5 */
+
+ switch( securityByte )
+ {
+ case ZM_NO_WEP:
+ case ZM_WEP64:
+ case ZM_WEP128:
+ case ZM_WEP256:
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+#endif //ZM_ENABLE_CENC
+ case ZM_TKIP:
+ case ZM_AES:
+
+ encryMode = securityByte;
+ break;
+
+ default:
+
+ if ( (securityByte & 0xf8) == 0x08 )
+ {
+ // decrypted by software
+ }
+
+ encryMode = ZM_NO_WEP;
+ break;
+ }
+
+ return encryMode;
+}
+
+void zfGetRxIvIcvLength(zdev_t* dev, zbuf_t* buf, u8_t vap, u16_t* pIvLen,
+ u16_t* pIcvLen, struct zsAdditionInfo* addInfo)
+{
+ u16_t wdsPort;
+ u8_t encryMode;
+
+ zmw_get_wlan_dev(dev);
+
+ *pIvLen = 0;
+ *pIcvLen = 0;
+
+ encryMode = zfGetEncryModeFromRxStatus(addInfo);
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ if (vap < ZM_MAX_AP_SUPPORT)
+ {
+ if (( wd->ap.encryMode[vap] == ZM_WEP64 ) ||
+ ( wd->ap.encryMode[vap] == ZM_WEP128 ) ||
+ ( wd->ap.encryMode[vap] == ZM_WEP256 ))
+ {
+ *pIvLen = 4;
+ *pIcvLen = 4;
+ }
+ else
+ {
+ u16_t id;
+ u16_t addr[3];
+
+ addr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
+ addr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2);
+ addr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4);
+
+ /* Find STA's information */
+ if ((id = zfApFindSta(dev, addr)) != 0xffff)
+ {
+ if (wd->ap.staTable[id].encryMode == ZM_TKIP)
+ {
+ *pIvLen = 8;
+ *pIcvLen = 4;
+ }
+ else if (wd->ap.staTable[id].encryMode == ZM_AES)
+ {
+ *pIvLen = 8;
+ *pIcvLen = 8; // AES MIC
+ //*pIcvLen = 0;
+ }
+#ifdef ZM_ENABLE_CENC
+ else if (wd->ap.staTable[id].encryMode == ZM_CENC)
+ {
+ *pIvLen = 18;
+ *pIcvLen= 16;
+ }
+#endif //ZM_ENABLE_CENC
+ }
+ }
+ /* WDS port checking */
+ if ((wdsPort = vap - 0x20) >= ZM_MAX_WDS_SUPPORT)
+ {
+ wdsPort = 0;
+ }
+
+ switch (wd->ap.wds.encryMode[wdsPort])
+ {
+ case ZM_WEP64:
+ case ZM_WEP128:
+ case ZM_WEP256:
+ *pIvLen = 4;
+ *pIcvLen = 4;
+ break;
+ case ZM_TKIP:
+ *pIvLen = 8;
+ *pIcvLen = 4;
+ break;
+ case ZM_AES:
+ *pIvLen = 8;
+ *pIcvLen = 0;
+ break;
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+ *pIvLen = 18;
+ *pIcvLen = 16;
+ break;
+#endif //ZM_ENABLE_CENC
+ }/* end of switch */
+ }
+ }
+ else if ( wd->wlanMode == ZM_MODE_PSEUDO)
+ {
+ /* test: 6518 for QA auto test */
+ switch (encryMode)
+ {
+ case ZM_WEP64:
+ case ZM_WEP128:
+ case ZM_WEP256:
+ *pIvLen = 4;
+ *pIcvLen = 4;
+ break;
+ case ZM_TKIP:
+ *pIvLen = 8;
+ *pIcvLen = 4;
+ break;
+ case ZM_AES:
+ *pIvLen = 8;
+ *pIcvLen = 0;
+ break;
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+ *pIvLen = 18;
+ *pIcvLen = 16;
+#endif //ZM_ENABLE_CENC
+ }/* end of switch */
+ }
+ else
+ {
+ if ( (encryMode == ZM_WEP64)||
+ (encryMode == ZM_WEP128)||
+ (encryMode == ZM_WEP256) )
+ {
+ *pIvLen = 4;
+ *pIcvLen = 4;
+ }
+ else if ( encryMode == ZM_TKIP )
+ {
+ *pIvLen = 8;
+ *pIcvLen = 4;
+ }
+ else if ( encryMode == ZM_AES )
+ {
+ *pIvLen = 8;
+ *pIcvLen = 8; // AES MIC
+ }
+#ifdef ZM_ENABLE_CENC
+ else if ( encryMode == ZM_CENC)
+ {
+ *pIvLen = 18;
+ *pIcvLen= 16;
+ }
+#endif //ZM_ENABLE_CENC
+ }
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAgingDefragList */
+/* Force flushing whole defrag list or aging the buffer */
+/* in the defrag list. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* flushFlag : 1=>flushing, 0=>Aging */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+void zfAgingDefragList(zdev_t* dev, u16_t flushFlag)
+{
+ u16_t i, j;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ for(i=0; i<ZM_MAX_DEFRAG_ENTRIES; i++)
+ {
+ if (wd->defragTable.defragEntry[i].fragCount != 0 )
+ {
+ if (((wd->tick - wd->defragTable.defragEntry[i].tick) >
+ (ZM_DEFRAG_AGING_TIME_SEC * ZM_TICK_PER_SECOND))
+ || (flushFlag != 0))
+ {
+ zm_msg1_rx(ZM_LV_2, "Aging defrag list :", i);
+ /* Free the buffers in the defrag list */
+ for (j=0; j<wd->defragTable.defragEntry[i].fragCount; j++)
+ {
+ zfwBufFree(dev, wd->defragTable.defragEntry[i].fragment[j], 0);
+ }
+ }
+ }
+ wd->defragTable.defragEntry[i].fragCount = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAddFirstFragToDefragList */
+/* Add first fragment to defragment list, the first empty entry */
+/* will be selected. If the list is full, sequentially select */
+/* one entry for replacement. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : first fragment buffer */
+/* addr : address of first fragment buffer */
+/* seqNum : sequence of first fragment buffer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+void zfAddFirstFragToDefragList(zdev_t* dev, zbuf_t* buf, u8_t* addr, u16_t seqNum)
+{
+ u16_t i, j;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ /* Find an empty one in defrag list */
+ for(i=0; i<ZM_MAX_DEFRAG_ENTRIES; i++)
+ {
+ if ( wd->defragTable.defragEntry[i].fragCount == 0 )
+ {
+ break;
+ }
+ }
+
+ /* If full, sequentially replace existing one */
+ if (i == ZM_MAX_DEFRAG_ENTRIES)
+ {
+ i = wd->defragTable.replaceNum++ & (ZM_MAX_DEFRAG_ENTRIES-1);
+ /* Free the buffers in the defrag list to be replaced */
+ for (j=0; j<wd->defragTable.defragEntry[i].fragCount; j++)
+ {
+ zfwBufFree(dev, wd->defragTable.defragEntry[i].fragment[j], 0);
+ }
+ }
+
+ wd->defragTable.defragEntry[i].fragCount = 1;
+ wd->defragTable.defragEntry[i].fragment[0] = buf;
+ wd->defragTable.defragEntry[i].seqNum = seqNum;
+ wd->defragTable.defragEntry[i].tick = wd->tick;
+
+ for (j=0; j<6; j++)
+ {
+ wd->defragTable.defragEntry[i].addr[j] = addr[j];
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfAddFragToDefragList */
+/* Add middle or last fragment to defragment list. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : first fragment buffer */
+/* addr : address of fragment buffer */
+/* seqNum : sequence fragment buffer */
+/* fragNum : fragment number of fragment buffer */
+/* moreFrag : more frag bit of fragment buffer */
+/* addInfo : addition info of fragment buffer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+zbuf_t* zfAddFragToDefragList(zdev_t* dev, zbuf_t* buf, u8_t* addr,
+ u16_t seqNum, u8_t fragNum, u8_t moreFrag,
+ struct zsAdditionInfo* addInfo)
+{
+ u16_t i, j, k;
+ zbuf_t* returnBuf = NULL;
+ u16_t defragDone = 0;
+ u16_t lenErr = 0;
+ u16_t startAddr, fragHead, frameLen, ivLen, icvLen;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ /* Find frag in the defrag list */
+ for(i=0; i<ZM_MAX_DEFRAG_ENTRIES; i++)
+ {
+ if ( wd->defragTable.defragEntry[i].fragCount != 0 )
+ {
+ /* Compare address */
+ for (j=0; j<6; j++)
+ {
+ if (addr[j] != wd->defragTable.defragEntry[i].addr[j])
+ {
+ break;
+ }
+ }
+ if (j == 6)
+ {
+ /* Compare sequence and fragment number */
+ if (seqNum == wd->defragTable.defragEntry[i].seqNum)
+ {
+ if ((fragNum == wd->defragTable.defragEntry[i].fragCount)
+ && (fragNum < 8))
+ {
+ /* Add frag frame to defrag list */
+ wd->defragTable.defragEntry[i].fragment[fragNum] = buf;
+ wd->defragTable.defragEntry[i].fragCount++;
+ defragDone = 1;
+
+ if (moreFrag == 0)
+ {
+ /* merge all fragment if more data bit is cleared */
+ returnBuf = wd->defragTable.defragEntry[i].fragment[0];
+ startAddr = zfwBufGetSize(dev, returnBuf);
+ /* skip WLAN header 24(Data) or 26(QoS Data) */
+ fragHead = 24 + ((zmw_rx_buf_readh(dev, returnBuf, 0) & 0x80) >> 6);
+ zfGetRxIvIcvLength(dev, returnBuf, 0, &ivLen, &icvLen, addInfo);
+ fragHead += ivLen; /* skip IV */
+ for(k=1; k<wd->defragTable.defragEntry[i].fragCount; k++)
+ {
+ frameLen = zfwBufGetSize(dev,
+ wd->defragTable.defragEntry[i].fragment[k]);
+ if ((startAddr+frameLen-fragHead) < 1560)
+ {
+ zfRxBufferCopy(dev, returnBuf, wd->defragTable.defragEntry[i].fragment[k],
+ startAddr, fragHead, frameLen-fragHead);
+ startAddr += (frameLen-fragHead);
+ }
+ else
+ {
+ lenErr = 1;
+ }
+ zfwBufFree(dev, wd->defragTable.defragEntry[i].fragment[k], 0);
+ }
+
+ wd->defragTable.defragEntry[i].fragCount = 0;
+ zfwBufSetSize(dev, returnBuf, startAddr);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (lenErr == 1)
+ {
+ zfwBufFree(dev, returnBuf, 0);
+ return NULL;
+ }
+ if (defragDone == 0)
+ {
+ zfwBufFree(dev, buf, 0);
+ return NULL;
+ }
+
+ return returnBuf;
+}
+
+
+/* return value = NULL => save or free this frame */
+zbuf_t* zfDefragment(zdev_t* dev, zbuf_t* buf, u8_t* pbIsDefrag,
+ struct zsAdditionInfo* addInfo)
+{
+ u8_t fragNum;
+ u16_t seqNum;
+ u8_t moreFragBit;
+ u8_t addr[6];
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ *pbIsDefrag = FALSE;
+ seqNum = zmw_buf_readh(dev, buf, 22);
+ fragNum = (u8_t)(seqNum & 0xf);
+ moreFragBit = (zmw_buf_readb(dev, buf, 1) & ZM_BIT_2) >> 2;
+
+ if ((fragNum == 0) && (moreFragBit == 0))
+ {
+ /* Not part of a fragmentation */
+
+ return buf;
+ }
+ else
+ {
+ wd->commTally.swRxFragmentCount++;
+ seqNum = seqNum >> 4;
+ for (i=0; i<6; i++)
+ {
+ addr[i] = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+i);
+ }
+
+ if (fragNum == 0)
+ {
+ /* more frag = 1 */
+ /* First part of a fragmentation */
+ zm_msg1_rx(ZM_LV_2, "First Frag, seq=", seqNum);
+ zfAddFirstFragToDefragList(dev, buf, addr, seqNum);
+ buf = NULL;
+ }
+ else
+ {
+ /* Middle or last part of a fragmentation */
+ zm_msg1_rx(ZM_LV_2, "Frag seq=", seqNum);
+ zm_msg1_rx(ZM_LV_2, "Frag moreFragBit=", moreFragBit);
+ buf = zfAddFragToDefragList(dev, buf, addr, seqNum, fragNum, moreFragBit, addInfo);
+ if (buf != NULL)
+ {
+ *pbIsDefrag = TRUE;
+ }
+ }
+ }
+
+ return buf;
+}
+
+
+#if ZM_PROTOCOL_RESPONSE_SIMULATION
+u16_t zfSwap(u16_t num)
+{
+ return ((num >> 8) + ((num & 0xff) << 8));
+}
+
+
+void zfProtRspSim(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t ethType;
+ u16_t arpOp;
+ u16_t prot;
+ u16_t temp;
+ u16_t i;
+ u16_t dip[2];
+ u16_t dstPort;
+ u16_t srcPort;
+
+ ethType = zmw_rx_buf_readh(dev, buf, 12);
+ zm_msg2_rx(ZM_LV_2, "ethType=", ethType);
+
+ /* ARP */
+ if (ethType == 0x0608)
+ {
+ arpOp = zmw_rx_buf_readh(dev, buf, 20);
+ dip[0] = zmw_rx_buf_readh(dev, buf, 38);
+ dip[1] = zmw_rx_buf_readh(dev, buf, 40);
+ zm_msg2_rx(ZM_LV_2, "arpOp=", arpOp);
+ zm_msg2_rx(ZM_LV_2, "ip0=", dip[0]);
+ zm_msg2_rx(ZM_LV_2, "ip1=", dip[1]);
+
+ //ARP request to 192.168.1.15
+ if ((arpOp == 0x0100) && (dip[0] == 0xa8c0) && (dip[1] == 0x0f01));
+ {
+ zm_msg0_rx(ZM_LV_2, "ARP");
+ /* ARP response */
+ zmw_rx_buf_writeh(dev, buf, 20, 0x0200);
+
+ /* dst hardware address */
+
+ /* src hardware address */
+ //zmw_rx_buf_writeh(dev, buf, 6, 0xa000);
+ //zmw_rx_buf_writeh(dev, buf, 8, 0x0000);
+ //zmw_rx_buf_writeh(dev, buf, 10, 0x0000);
+
+ /* dst ip address */
+ for (i=0; i<5; i++)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, 22+(i*2));
+ zmw_rx_buf_writeh(dev, buf, 32+(i*2), temp);
+ }
+
+ /* src hardware address */
+ zmw_rx_buf_writeh(dev, buf, 22, 0xa000);
+ zmw_rx_buf_writeh(dev, buf, 24, 0x0000);
+ zmw_rx_buf_writeh(dev, buf, 26, 0x0000);
+
+ /* src ip address */
+ zmw_rx_buf_writeh(dev, buf, 28, 0xa8c0);
+ zmw_rx_buf_writeh(dev, buf, 30, 0x0f01);
+ }
+ }
+ /* ICMP */
+ else if (ethType == 0x0008)
+ {
+ zm_msg0_rx(ZM_LV_2, "IP");
+ prot = zmw_rx_buf_readb(dev, buf, 23);
+ dip[0] = zmw_rx_buf_readh(dev, buf, 30);
+ dip[1] = zmw_rx_buf_readh(dev, buf, 32);
+ zm_msg2_rx(ZM_LV_2, "prot=", prot);
+ zm_msg2_rx(ZM_LV_2, "ip0=", dip[0]);
+ zm_msg2_rx(ZM_LV_2, "ip1=", dip[1]);
+
+ /* PING request to 192.168.1.15 */
+ if ((prot == 0x1) && (dip[0] == 0xa8c0) && (dip[1] == 0x0f01))
+ {
+ zm_msg0_rx(ZM_LV_2, "ICMP");
+ /* change dst */
+ for (i=0; i<3; i++)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, 6+(i*2));
+ zmw_rx_buf_writeh(dev, buf, i*2, temp);
+ }
+ /* change src */
+ zmw_rx_buf_writeh(dev, buf, 6, 0xa000);
+ zmw_rx_buf_writeh(dev, buf, 8, 0x0000);
+ zmw_rx_buf_writeh(dev, buf, 10, 0x0000);
+
+ /* exchange src ip and dst ip */
+ for (i=0; i<2; i++)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, 26+(i*2));
+ zmw_rx_buf_writeh(dev, buf, 30+(i*2), temp);
+ }
+ zmw_rx_buf_writeh(dev, buf, 26, 0xa8c0);
+ zmw_rx_buf_writeh(dev, buf, 28, 0x0f01);
+
+ /* change icmp type to echo reply */
+ zmw_rx_buf_writeb(dev, buf, 34, 0x0);
+
+ /* update icmp checksum */
+ temp = zmw_rx_buf_readh(dev, buf, 36);
+ temp += 8;
+ zmw_rx_buf_writeh(dev, buf, 36, temp);
+ }
+ else if (prot == 0x6)
+ {
+ zm_msg0_rx(ZM_LV_2, "TCP");
+ srcPort = zmw_rx_buf_readh(dev, buf, 34);
+ dstPort = zmw_rx_buf_readh(dev, buf, 36);
+ zm_msg2_rx(ZM_LV_2, "Src Port=", srcPort);
+ zm_msg2_rx(ZM_LV_2, "Dst Port=", dstPort);
+ if ((dstPort == 0x1500) || (srcPort == 0x1500))
+ {
+ zm_msg0_rx(ZM_LV_2, "FTP");
+
+ /* change dst */
+ for (i=0; i<3; i++)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, 6+(i*2));
+ zmw_rx_buf_writeh(dev, buf, i*2, temp);
+ }
+ /* change src */
+ zmw_rx_buf_writeh(dev, buf, 6, 0xa000);
+ zmw_rx_buf_writeh(dev, buf, 8, 0x0000);
+ zmw_rx_buf_writeh(dev, buf, 10, 0x0000);
+
+ /* exchange src ip and dst ip */
+ for (i=0; i<2; i++)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, 26+(i*2));
+ zmw_rx_buf_writeh(dev, buf, 30+(i*2), temp);
+ }
+ zmw_rx_buf_writeh(dev, buf, 26, 0xa8c0);
+ zmw_rx_buf_writeh(dev, buf, 28, 0x0f01);
+#if 0
+ /* Patch src port */
+ temp = zmw_rx_buf_readh(dev, buf, 34);
+ temp = zfSwap(zfSwap(temp) + 1);
+ zmw_rx_buf_writeh(dev, buf, 34, temp);
+ temp = zmw_rx_buf_readh(dev, buf, 38);
+ temp = zfSwap(zfSwap(temp) + 1);
+ zmw_rx_buf_writeh(dev, buf, 38, temp);
+
+ /* Patch checksum */
+ temp = zmw_rx_buf_readh(dev, buf, 50);
+ temp = zfSwap(temp);
+ temp = ~temp;
+ temp += 2;
+ temp = ~temp;
+ temp = zfSwap(temp);
+ zmw_rx_buf_writeh(dev, buf, 50, temp);
+#endif
+ }
+
+ }
+ else if (prot == 0x11)
+ {
+ /* change dst */
+ for (i=0; i<3; i++)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, 6+(i*2));
+ zmw_rx_buf_writeh(dev, buf, i*2, temp);
+ }
+ /* change src */
+ zmw_rx_buf_writeh(dev, buf, 6, 0xa000);
+ zmw_rx_buf_writeh(dev, buf, 8, 0x0000);
+ zmw_rx_buf_writeh(dev, buf, 10, 0x0000);
+
+ zm_msg0_rx(ZM_LV_2, "UDP");
+ srcPort = zmw_rx_buf_readh(dev, buf, 34);
+ dstPort = zmw_rx_buf_readh(dev, buf, 36);
+ zm_msg2_rx(ZM_LV_2, "Src Port=", srcPort);
+ zm_msg2_rx(ZM_LV_2, "Dst Port=", dstPort);
+
+ /* exchange src ip and dst ip */
+ for (i=0; i<2; i++)
+ {
+ temp = zmw_rx_buf_readh(dev, buf, 26+(i*2));
+ zmw_rx_buf_writeh(dev, buf, 30+(i*2), temp);
+ }
+ zmw_rx_buf_writeh(dev, buf, 26, 0xa8c0);
+ zmw_rx_buf_writeh(dev, buf, 28, 0x0f01);
+
+ /* exchange port */
+ zmw_rx_buf_writeh(dev, buf, 34, srcPort+1);
+ zmw_rx_buf_writeh(dev, buf, 36, dstPort);
+
+ /* checksum = 0 */
+ zmw_rx_buf_writeh(dev, buf, 40, 0);
+ }
+
+ }
+ else if (ethType == 0x0060) /* =>0x0060 is port */
+ {
+ /* change src for Evl tool loop back receive */
+ zmw_rx_buf_writeh(dev, buf, 6, 0xa000);
+ zmw_rx_buf_writeh(dev, buf, 8, 0x0000);
+ zmw_rx_buf_writeh(dev, buf, 10, 0x0000);
+ }
+
+}
+#endif
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiTxSendEth */
+/* Called to native 802.11 management frames */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer pointer */
+/* port : WLAN port, 0=>standard, 0x1-0x7=>VAP, 0x20-0x25=>WDS */
+/* */
+/* OUTPUTS */
+/* error code */
+/* */
+/* AUTHOR */
+/* Ray ZyDAS Technology Corporation 2005.5 */
+/* */
+/************************************************************************/
+u16_t zfiTxSend80211Mgmt(zdev_t* dev, zbuf_t* buf, u16_t port)
+{
+ u16_t err;
+ //u16_t addrTblSize = 0;
+ //struct zsAddrTbl addrTbl;
+ u16_t hlen;
+ u16_t header[(24+25+1)/2];
+ int i;
+
+ for(i=0;i<12;i++)
+ {
+ header[i] = zmw_buf_readh(dev, buf, i);
+ }
+ hlen = 24;
+
+ zfwBufRemoveHead(dev, buf, 24);
+
+ if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0,
+ ZM_EXTERNAL_ALLOC_BUF, 0, 0)) != ZM_SUCCESS)
+ {
+ goto zlError;
+ }
+
+ return 0;
+
+zlError:
+
+ zfwBufFree(dev, buf, 0);
+ return 0;
+}
+
+u8_t zfiIsTxQueueFull(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if ((((wd->vtxqHead[0] + 1) & ZM_VTXQ_SIZE_MASK) != wd->vtxqTail[0]) )
+ {
+ zmw_leave_critical_section(dev);
+ return 0;
+ }
+ else
+ {
+ zmw_leave_critical_section(dev);
+ return 1;
+ }
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiTxSendEth */
+/* Called to transmit Ethernet frame from upper layer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer pointer */
+/* port : WLAN port, 0=>standard, 0x1-0x7=>VAP, 0x20-0x25=>WDS */
+/* */
+/* OUTPUTS */
+/* error code */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.5 */
+/* */
+/************************************************************************/
+u16_t zfiTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port)
+{
+ u16_t err, ret;
+
+ zmw_get_wlan_dev(dev);
+
+ ZM_PERFORMANCE_TX_MSDU(dev, wd->tick);
+ zm_msg1_tx(ZM_LV_2, "zfiTxSendEth(), port=", port);
+ /* Return error if port is disabled */
+ if ((err = zfTxPortControl(dev, buf, port)) == ZM_PORT_DISABLED)
+ {
+ err = ZM_ERR_TX_PORT_DISABLED;
+ goto zlError;
+ }
+
+#if 1
+ if ((wd->wlanMode == ZM_MODE_AP) && (port < 0x20))
+ {
+ /* AP : Buffer frame for power saving STA */
+ if ((ret = zfApBufferPsFrame(dev, buf, port)) == 1)
+ {
+ return ZM_SUCCESS;
+ }
+ }
+ else
+#endif
+ if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ if ( zfPowerSavingMgrIsSleeping(dev) )
+ {
+ /*check ZM_ENABLE_POWER_SAVE flag*/
+ zfPowerSavingMgrWakeup(dev);
+ }
+ }
+#ifdef ZM_ENABLE_IBSS_PS
+ /* IBSS power-saving mode */
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ if ( zfStaIbssPSQueueData(dev, buf) )
+ {
+ return ZM_SUCCESS;
+ }
+ }
+#endif
+
+#if 1
+ //if ( wd->bQoSEnable )
+ if (1)
+ {
+ /* Put to VTXQ[ac] */
+ ret = zfPutVtxq(dev, buf);
+
+ /* Push VTXQ[ac] */
+ zfPushVtxq(dev);
+ }
+ else
+ {
+ ret = zfTxSendEth(dev, buf, port, ZM_EXTERNAL_ALLOC_BUF, 0);
+ }
+
+ return ret;
+#else
+ return zfTxSendEth(dev, buf, port, ZM_EXTERNAL_ALLOC_BUF, 0);
+#endif
+
+zlError:
+ zm_msg2_tx(ZM_LV_1, "Tx Comp err=", err);
+
+ zfwBufFree(dev, buf, err);
+ return err;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfTxSendEth */
+/* Called to transmit Ethernet frame from upper layer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : buffer pointer */
+/* port : WLAN port, 0=>standard, 0x10-0x17=>VAP, 0x20-0x25=>WDS */
+/* */
+/* OUTPUTS */
+/* error code */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.5 */
+/* */
+/************************************************************************/
+u16_t zfTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u16_t flag)
+{
+ u16_t err;
+ //u16_t addrTblSize;
+ //struct zsAddrTbl addrTbl;
+ u16_t removeLen;
+ u16_t header[(8+30+2+18)/2]; /* ctr+(4+a1+a2+a3+2+a4)+qos+iv */
+ u16_t headerLen;
+ u16_t mic[8/2];
+ u16_t micLen;
+ u16_t snap[8/2];
+ u16_t snapLen;
+ u16_t fragLen;
+ u16_t frameLen;
+ u16_t fragNum;
+ struct zsFrag frag;
+ u16_t i, j, id;
+ u16_t offset;
+ u16_t da[3];
+ u16_t sa[3];
+ u8_t up;
+ u8_t qosType, keyIdx = 0;
+ u16_t fragOff;
+ u16_t newFlag;
+ struct zsMicVar* pMicKey;
+ u8_t tkipFrameOffset = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ newFlag = flag & 0xff00;
+ flag = flag & 0xff;
+
+ zm_msg1_tx(ZM_LV_2, "zfTxSendEth(), port=", port);
+
+ /* Get IP TOS for QoS AC and IP frag offset */
+ zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
+
+ //EOSP bit
+ if (newFlag & 0x100)
+ {
+ up |= 0x10;
+ }
+
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 16);
+ da[1] = zmw_tx_buf_readh(dev, buf, 18);
+ da[2] = zmw_tx_buf_readh(dev, buf, 20);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 10);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 12);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 14);
+ }
+ else if ( wd->wlanMode == ZM_MODE_IBSS )
+ {
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 4);
+ da[1] = zmw_tx_buf_readh(dev, buf, 6);
+ da[2] = zmw_tx_buf_readh(dev, buf, 8);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 10);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 12);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 14);
+ }
+ else if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 4);
+ da[1] = zmw_tx_buf_readh(dev, buf, 6);
+ da[2] = zmw_tx_buf_readh(dev, buf, 8);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 16);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 18);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 20);
+ }
+ else
+ {
+ //
+ }
+#else
+ /* DA */
+ da[0] = zmw_tx_buf_readh(dev, buf, 0);
+ da[1] = zmw_tx_buf_readh(dev, buf, 2);
+ da[2] = zmw_tx_buf_readh(dev, buf, 4);
+ /* SA */
+ sa[0] = zmw_tx_buf_readh(dev, buf, 6);
+ sa[1] = zmw_tx_buf_readh(dev, buf, 8);
+ sa[2] = zmw_tx_buf_readh(dev, buf, 10);
+#endif
+ //Decide Key Index in ATOM, No meaning in OTUS--CWYang(m)
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ keyIdx = wd->ap.bcHalKeyIdx[port];
+ id = zfApFindSta(dev, da);
+ if (id != 0xffff)
+ {
+ switch (wd->ap.staTable[id].encryMode)
+ {
+ case ZM_AES:
+ case ZM_TKIP:
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+#endif //ZM_ENABLE_CENC
+ keyIdx = wd->ap.staTable[id].keyIdx;
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (wd->sta.encryMode)
+ {
+ case ZM_WEP64:
+ case ZM_WEP128:
+ case ZM_WEP256:
+ keyIdx = wd->sta.keyId;
+ break;
+ case ZM_AES:
+ case ZM_TKIP:
+ if ((da[0] & 0x1))
+ keyIdx = 5;
+ else
+ keyIdx = 4;
+ break;
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+ keyIdx = wd->sta.cencKeyId;
+ break;
+#endif //ZM_ENABLE_CENC
+ }
+ }
+
+ /* Create SNAP */
+ removeLen = zfTxGenWlanSnap(dev, buf, snap, &snapLen);
+ //zm_msg1_tx(ZM_LV_0, "fragOff=", fragOff);
+
+
+/* ********************************************************************************************** */
+/* Add 20071025 Mxzeng */
+/* ********************************************************************************************** */
+/* ---------------------------------------------------------------------------------------------- */
+/* Ethernet : frameLen = zfwBufGetSize(dev, buf); */
+/* ---+--6--+--6--+--2--+-----20-----+-------------------------+------ Variable -------+--------- */
+/* | DA | SA | Type| IP Header | TCP(20) UDP(12) ICMP(8) | Application Payload L | */
+/* ---+-----+-----+-----+------------+-------------------------+-----------------------+--------- */
+/* MSDU = 6 + 6 + 2 + ( Network Layer header ) + ( Transport Layer header ) + L */
+/* */
+/* MSDU - DA - SA : frameLen -= removeLen; */
+/* ---+--2--+-----20-----+-------------------------+------ Variable -------+--------------------- */
+/* | Type| IP Header | TCP(20) UDP(12) ICMP(8) | Application Payload L | */
+/* ---+-----+------------+-------------------------+-----------------------+--------------------- */
+/* */
+/* MPDU : frameLen + mpduLengthOffset ; */
+/* -+---2---+----2---+-6-+-6-+--6--+---2----+--1--+--1-+---1---+-------3------+-frameLen-+---4--+- */
+/* | frame |duration| DA|SA |BSSID|sequence|SNAP |SNAP|Control| RFC 1042 | | FCS | */
+/* |Control| | | | | number |DSAP |SSAP| | encapsulation| | | */
+/* -+-------+--------+---+---+-----+--------+-----+----+-------+--------------+----------+------+- */
+/* ----------------------------------------------------------------------------------------------- */
+
+ if ( wd->sta.encryMode == ZM_TKIP )
+ tkipFrameOffset = 8;
+
+ fragLen = wd->fragThreshold + tkipFrameOffset; // Fragmentation threshold for MPDU Lengths
+ frameLen = zfwBufGetSize(dev, buf); // MSDU Lengths
+ frameLen -= removeLen; // MSDU Lengths - DA - SA
+
+ /* #1st create MIC Length manually */
+ micLen = 0;
+
+ /* Access Category */
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ zfApGetStaQosType(dev, da, &qosType);
+ if (qosType == 0)
+ {
+ up = 0;
+ }
+ }
+ else if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)
+ {
+ if (wd->sta.wmeConnected == 0)
+ {
+ up = 0;
+ }
+ }
+ else
+ {
+ /* TODO : STA QoS control field */
+ up = 0;
+ }
+
+ /* #2nd Assign sequence number */
+ zmw_enter_critical_section(dev);
+ frag.seq[0] = ((wd->seq[zcUpToAc[up&0x7]]++) << 4);
+ zmw_leave_critical_section(dev);
+
+ /* #3rd Pass the total payload to generate MPDU length ! */
+ frag.buf[0] = buf;
+ frag.bufType[0] = bufType;
+ frag.flag[0] = (u8_t)flag;
+ fragNum = 1;
+
+ headerLen = zfTxGenWlanHeader(dev, frag.buf[0], header, frag.seq[0],
+ frag.flag[0], snapLen+micLen, removeLen, port, da, sa,
+ up, &micLen, snap, snapLen, NULL);
+
+ //zm_debug_msg1("#1 headerLen = ", headerLen);
+
+ /* #4th Check the HeaderLen and determine whether the MPDU Lengths bigger than Fragmentation threshold */
+ /* If MPDU Lengths large than fragmentation threshold --> headerLen = 0 */
+ if( headerLen != 0 )
+ {
+ zf80211FrameSend(dev, frag.buf[0], header, snapLen, da, sa, up,
+ headerLen, snap, mic, micLen, removeLen, frag.bufType[0],
+ zcUpToAc[up&0x7], keyIdx);
+ }
+ else //if( headerLen == 0 ) // Need to be fragmented
+ {
+ u16_t mpduLengthOffset;
+ u16_t pseudSnapLen = 0;
+
+ mpduLengthOffset = header[0] - frameLen; // For fragmentation threshold !
+
+ micLen = zfTxGenWlanTail(dev, buf, snap, snapLen, mic); // Get snap and mic information
+
+ fragLen = fragLen - mpduLengthOffset;
+
+ //zm_debug_msg1("#2 frameLen = ", frameLen);
+ //zm_debug_msg1("#3 fragThreshold = ", fragLen);
+
+ /* fragmentation */
+ if (frameLen >= fragLen)
+ {
+ //copy fragLen to frag
+ i = 0;
+ while( frameLen > 0 )
+ {
+ if ((frag.buf[i] = zfwBufAllocate(dev, fragLen+32)) != NULL)
+ {
+ frag.bufType[i] = ZM_INTERNAL_ALLOC_BUF;
+ frag.seq[i] = frag.seq[0] + i;
+ offset = removeLen + i*fragLen;
+
+ /* Consider the offset if we consider snap length to the other fragmented frame */
+ if ( i >= 1 )
+ offset = offset + pseudSnapLen*(i-1);
+
+ if (frameLen > fragLen + pseudSnapLen)
+ {
+ frag.flag[i] = flag | 0x4; /* More data */
+ /* First fragment */
+ if (i == 0)
+ {
+ /* Add SNAP */
+ for (j=0; j<snapLen; j+=2)
+ {
+ zmw_tx_buf_writeh(dev, frag.buf[i], j, snap[(j>>1)]);
+ }
+ zfTxBufferCopy(dev, frag.buf[i], buf, snapLen, offset, fragLen);
+ zfwBufSetSize(dev, frag.buf[i], snapLen+fragLen);
+
+ /* Add pseud snap length to the other fragmented frame */
+ pseudSnapLen = snapLen;
+
+ frameLen -= fragLen;
+ }
+ /* Intermediate Fragment */
+ else
+ {
+ //zfTxBufferCopy(dev, frag.buf[i], buf, 0, offset, fragLen);
+ //zfwBufSetSize(dev, frag.buf[i], fragLen);
+
+ zfTxBufferCopy(dev, frag.buf[i], buf, 0, offset, fragLen+pseudSnapLen );
+ zfwBufSetSize(dev, frag.buf[i], fragLen+pseudSnapLen);
+
+ frameLen -= (fragLen+pseudSnapLen);
+ }
+ //frameLen -= fragLen;
+ }
+ else
+ {
+ /* Last fragment */
+ zfTxBufferCopy(dev, frag.buf[i], buf, 0, offset, frameLen);
+ /* Add MIC if need */
+ if ( micLen )
+ {
+ zfCopyToRxBuffer(dev, frag.buf[i], (u8_t*) mic, frameLen, micLen);
+ }
+ zfwBufSetSize(dev, frag.buf[i], frameLen+micLen);
+ frameLen = 0;
+ frag.flag[i] = (u8_t)flag; /* No more data */
+ }
+ i++;
+ }
+ else
+ {
+ break;
+ }
+
+ // Please pay attention to the index of the buf !!!
+ // If write to null buf , the OS will crash !!!
+ zfwCopyBufContext(dev, buf, frag.buf[i-1]);
+ }
+ fragNum = i;
+ snapLen = micLen = removeLen = 0;
+
+ zfwBufFree(dev, buf, 0);
+ }
+
+ for (i=0; i<fragNum; i++)
+ {
+ /* Create WLAN header(Control Setting + 802.11 header + IV) */
+ headerLen = zfTxGenWlanHeader(dev, frag.buf[i], header, frag.seq[i],
+ frag.flag[i], snapLen+micLen, removeLen, port, da, sa, up, &micLen,
+ snap, snapLen, NULL);
+
+ zf80211FrameSend(dev, frag.buf[i], header, snapLen, da, sa, up,
+ headerLen, snap, mic, micLen, removeLen, frag.bufType[i],
+ zcUpToAc[up&0x7], keyIdx);
+
+ } /* for (i=0; i<fragNum; i++) */
+ }
+
+ return ZM_SUCCESS;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfTxPortControl */
+/* Check port status. */
+/* */
+/* INPUTS */
+/* buf : buffer pointer */
+/* port : port number, 0=>standard, 10-17=>Virtual AP, 20-25=>WDS */
+/* */
+/* OUTPUTS */
+/* ZM_PORT_ENABLED or ZM_PORT_DISABLE */
+/* */
+/* AUTHOR */
+/* Signature ZyDAS Technology Corporation 2005.4 */
+/* */
+/************************************************************************/
+u16_t zfTxPortControl(zdev_t* dev, zbuf_t* buf, u16_t port)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ if ( wd->sta.adapterState == ZM_STA_STATE_DISCONNECT )
+ {
+ zm_msg0_tx(ZM_LV_3, "Packets dropped due to disconnect state");
+ return ZM_PORT_DISABLED;
+ }
+ }
+
+ return ZM_PORT_ENABLED;
+}
+
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfIdlRecv */
+/* Do frame validation and filtering then pass to zfwRecv80211(). */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : received 802.11 frame buffer. */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+void zfCoreRecv(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo)
+{
+ u16_t ret = 0;
+ u16_t bssid[3];
+ struct agg_tid_rx *tid_rx;
+ zmw_get_wlan_dev(dev);
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ /* tally */
+ wd->commTally.DriverRxFrmCnt++;
+
+ bssid[0] = zmw_buf_readh(dev, buf, 16);
+ bssid[1] = zmw_buf_readh(dev, buf, 18);
+ bssid[2] = zmw_buf_readh(dev, buf, 20);
+
+ /* Validate Rx frame */
+ if ((ret = zfWlanRxValidate(dev, buf)) != ZM_SUCCESS)
+ {
+ zm_msg1_rx(ZM_LV_1, "Rx invalid:", ret);
+ goto zlError;
+ }
+
+#ifdef ZM_ENABLE_AGGREGATION
+ //#ifndef ZM_ENABLE_FW_BA_RETRANSMISSION
+ /*
+ * add by honda
+ */
+ tid_rx = zfAggRxEnabled(dev, buf);
+ if (tid_rx && wd->reorder)
+ {
+ zfAggRx(dev, buf, addInfo, tid_rx);
+
+ return;
+ }
+ /*
+ * end of add by honda
+ */
+ //#endif
+#endif
+
+ /* Filter Rx frame */
+ if ((ret = zfWlanRxFilter(dev, buf)) != ZM_SUCCESS)
+ {
+ zm_msg1_rx(ZM_LV_1, "Rx duplicated:", ret);
+ goto zlError;
+ }
+
+ /* Discard error frame except mic failure */
+ if ((addInfo->Tail.Data.ErrorIndication & 0x3f) != 0)
+ {
+ if ( wd->XLinkMode && ((addInfo->Tail.Data.ErrorIndication & 0x3f)==0x10) &&
+ zfCompareWithBssid(dev, bssid) )
+ {
+ // Bypass frames !!!
+ }
+ else
+ {
+ goto zlError;
+ }
+ }
+
+
+ /* OTUS command-8212 dump rx packet */
+ if (wd->rxPacketDump)
+ {
+ zfwDumpBuf(dev, buf);
+ }
+
+ /* Call zfwRecv80211() wrapper function to deliver Rx packet */
+ /* to driver framework. */
+
+ if (wd->zfcbRecv80211 != NULL)
+ {
+ wd->zfcbRecv80211(dev, buf, addInfo); //CWYang(m)
+ }
+ else
+ {
+ zfiRecv80211(dev, buf, addInfo);
+ }
+ return;
+
+zlError:
+ zm_msg1_rx(ZM_LV_1, "Free packet, error code:", ret);
+
+ wd->commTally.DriverDiscardedFrm++;
+
+ /* Free Rx buffer */
+ zfwBufFree(dev, buf, 0);
+
+ return;
+}
+
+
+void zfShowRxEAPOL(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ u8_t packetType, keyType, code, identifier, type, flags;
+ u16_t packetLen, keyInfo, keyLen, keyDataLen, length, Op_Code;
+ u32_t replayCounterH, replayCounterL, vendorId, VendorType;
+
+ /* EAPOL packet type */
+ packetType = zmw_rx_buf_readb(dev, buf, offset+1); // 0: EAP-Packet
+ // 1: EAPOL-Start
+ // 2: EAPOL-Logoff
+ // 3: EAPOL-Key
+ // 4: EAPOL-Encapsulated-ASF-Alert
+
+ /* EAPOL frame format */
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
+ /* ----------------------------------------------- */
+ /* PAE Ethernet Type (0x888e) */
+ /* ----------------------------------------------- 2 */
+ /* Protocol Version | Type */
+ /* ----------------------------------------------- 4 */
+ /* Length */
+ /* ----------------------------------------------- 6 */
+ /* Packet Body */
+ /* ----------------------------------------------- N */
+
+ /* EAPOL body length */
+ packetLen = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+2)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+3);
+
+ if( packetType == 0 )
+ { // EAP-Packet
+
+ /* EAP-Packet Code */
+ code = zmw_rx_buf_readb(dev, buf, offset+4); // 1 : Request
+ // 2 : Response
+ // 3 : Success
+ // 4 : Failure
+ // An EAP packet of the type of Success and Failure has no Data field, and has a length of 4.
+
+ /* EAP Packet format */
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
+ /* ----------------------------------------------- */
+ /* Code | Identifier */
+ /* ----------------------------------------------- 2 */
+ /* Length */
+ /* ----------------------------------------------- 4 */
+ /* Data */
+ /* ----------------------------------------------- N */
+
+ zm_debug_msg0("EAP-Packet");
+ zm_debug_msg1("Packet Length = ", packetLen);
+ zm_debug_msg1("EAP-Packet Code = ", code);
+
+ if( code == 1 )
+ {
+ zm_debug_msg0("EAP-Packet Request");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_rx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+7);
+ /* EAP-Packet Type */
+ type = zmw_rx_buf_readb(dev, buf, offset+8); // 1 : Identity
+ // 2 : Notification
+ // 3 : Nak (Response Only)
+ // 4 : MD5-Challenge
+ // 5 : One Time Password (OTP)
+ // 6 : Generic Token Card (GTC)
+ // 254 : (Expanded Types)Wi-Fi Protected Setup
+ // 255 : Experimental Use
+
+ /* The data field in an EAP packet of the type of Request or Response is in the format shown bellowing */
+ /* 0 1 2 3 4 5 6 7 N */
+ /* ----------------------------------------------- */
+ /* Type | Type Data */
+ /* ----------------------------------------------- */
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ zm_debug_msg1("EAP-Packet Type = ", type);
+
+ if( type == 1 )
+ {
+ zm_debug_msg0("EAP-Packet Request Identity");
+ }
+ else if( type == 2 )
+ {
+ zm_debug_msg0("EAP-Packet Request Notification");
+ }
+ else if( type == 4 )
+ {
+ zm_debug_msg0("EAP-Packet Request MD5-Challenge");
+ }
+ else if( type == 5 )
+ {
+ zm_debug_msg0("EAP-Packet Request One Time Password");
+ }
+ else if( type == 6 )
+ {
+ zm_debug_msg0("EAP-Packet Request Generic Token Card");
+ }
+ else if( type == 254 )
+ {
+ zm_debug_msg0("EAP-Packet Request Wi-Fi Protected Setup");
+
+ /* 0 1 2 3 */
+ /* 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 6 7 8 9 0 1 */
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
+ /*| Type | Vendor-Id |*/
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
+ /*| Vendor-Type |*/
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
+ /*| Vendor data... */
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
+
+ /* EAP-Packet Vendor ID */
+ vendorId = (((u32_t) zmw_rx_buf_readb(dev, buf, offset+9)) << 16) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+10)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+11);
+ /* EAP-Packet Vendor Type */
+ VendorType = (((u32_t) zmw_rx_buf_readb(dev, buf, offset+12)) << 24) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+13)) << 16) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+14)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+15);
+ /* EAP-Packet Op Code */
+ Op_Code = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+16)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+17);
+ /* EAP-Packet Flags */
+ flags = zmw_rx_buf_readb(dev, buf, offset+18);
+
+ zm_debug_msg1("EAP-Packet Vendor ID = ", vendorId);
+ zm_debug_msg1("EAP-Packet Venodr Type = ", VendorType);
+ zm_debug_msg1("EAP-Packet Op Code = ", Op_Code);
+ zm_debug_msg1("EAP-Packet Flags = ", flags);
+ }
+ }
+ else if( code == 2 )
+ {
+ zm_debug_msg0("EAP-Packet Response");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_rx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+7);
+ /* EAP-Packet Type */
+ type = zmw_rx_buf_readb(dev, buf, offset+8);
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ zm_debug_msg1("EAP-Packet Type = ", type);
+
+ if( type == 1 )
+ {
+ zm_debug_msg0("EAP-Packet Response Identity");
+ }
+ else if( type == 2 )
+ {
+ zm_debug_msg0("EAP-Packet Request Notification");
+ }
+ else if( type == 3 )
+ {
+ zm_debug_msg0("EAP-Packet Request Nak");
+ }
+ else if( type == 4 )
+ {
+ zm_debug_msg0("EAP-Packet Request MD5-Challenge");
+ }
+ else if( type == 5 )
+ {
+ zm_debug_msg0("EAP-Packet Request One Time Password");
+ }
+ else if( type == 6 )
+ {
+ zm_debug_msg0("EAP-Packet Request Generic Token Card");
+ }
+ else if( type == 254 )
+ {
+ zm_debug_msg0("EAP-Packet Response Wi-Fi Protected Setup");
+
+ /* EAP-Packet Vendor ID */
+ vendorId = (((u32_t) zmw_rx_buf_readb(dev, buf, offset+9)) << 16) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+10)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+11);
+ /* EAP-Packet Vendor Type */
+ VendorType = (((u32_t) zmw_rx_buf_readb(dev, buf, offset+12)) << 24) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+13)) << 16) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+14)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+15);
+ /* EAP-Packet Op Code */
+ Op_Code = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+16)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+17);
+ /* EAP-Packet Flags */
+ flags = zmw_rx_buf_readb(dev, buf, offset+18);
+
+ zm_debug_msg1("EAP-Packet Vendor ID = ", vendorId);
+ zm_debug_msg1("EAP-Packet Venodr Type = ", VendorType);
+ zm_debug_msg1("EAP-Packet Op Code = ", Op_Code);
+ zm_debug_msg1("EAP-Packet Flags = ", flags);
+ }
+ }
+ else if( code == 3 )
+ {
+ zm_debug_msg0("EAP-Packet Success");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_rx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+7);
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ }
+ else if( code == 4 )
+ {
+ zm_debug_msg0("EAP-Packet Failure");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_rx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+7);
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ }
+ }
+ else if( packetType == 1 )
+ { // EAPOL-Start
+ zm_debug_msg0("EAPOL-Start");
+ }
+ else if( packetType == 2 )
+ { // EAPOL-Logoff
+ zm_debug_msg0("EAPOL-Logoff");
+ }
+ else if( packetType == 3 )
+ { // EAPOL-Key
+ /* EAPOL-Key type */
+ keyType = zmw_rx_buf_readb(dev, buf, offset+4);
+ /* EAPOL-Key information */
+ keyInfo = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+5)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+6);
+ /* EAPOL-Key length */
+ keyLen = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+7)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+8);
+ /* EAPOL-Key replay counter (high double word) */
+ replayCounterH = (((u32_t) zmw_rx_buf_readb(dev, buf, offset+9)) << 24) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+10)) << 16) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+11)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+12);
+ /* EAPOL-Key replay counter (low double word) */
+ replayCounterL = (((u32_t) zmw_rx_buf_readb(dev, buf, offset+13)) << 24) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+14)) << 16) +
+ (((u32_t) zmw_rx_buf_readb(dev, buf, offset+15)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+16);
+ /* EAPOL-Key data length */
+ keyDataLen = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+97)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+98);
+
+ zm_debug_msg0("EAPOL-Key");
+ zm_debug_msg1("packet length = ", packetLen);
+
+ if ( keyType == 254 )
+ {
+ zm_debug_msg0("key type = 254 (SSN key descriptor)");
+ }
+ else
+ {
+ zm_debug_msg2("key type = 0x", keyType);
+ }
+
+ zm_debug_msg2("replay counter(L) = ", replayCounterL);
+
+ zm_debug_msg2("key information = ", keyInfo);
+
+ if ( keyInfo & ZM_BIT_3 )
+ {
+ zm_debug_msg0(" - pairwise key");
+ }
+ else
+ {
+ zm_debug_msg0(" - group key");
+ }
+
+ if ( keyInfo & ZM_BIT_6 )
+ {
+ zm_debug_msg0(" - Tx key installed");
+ }
+ else
+ {
+ zm_debug_msg0(" - Tx key not set");
+ }
+
+ if ( keyInfo & ZM_BIT_7 )
+ {
+ zm_debug_msg0(" - Ack needed");
+ }
+ else
+ {
+ zm_debug_msg0(" - Ack not needed");
+ }
+
+ if ( keyInfo & ZM_BIT_8 )
+ {
+ zm_debug_msg0(" - MIC set");
+ }
+ else
+ {
+ zm_debug_msg0(" - MIC not set");
+ }
+
+ if ( keyInfo & ZM_BIT_9 )
+ {
+ zm_debug_msg0(" - packet encrypted");
+ }
+ else
+ {
+ zm_debug_msg0(" - packet not encrypted");
+ }
+
+ zm_debug_msg1("keyLen = ", keyLen);
+ zm_debug_msg1("keyDataLen = ", keyDataLen);
+ }
+ else if( packetType == 4 )
+ {
+ zm_debug_msg0("EAPOL-Encapsulated-ASF-Alert");
+ }
+}
+
+void zfShowTxEAPOL(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ u8_t packetType, keyType, code, identifier, type, flags;
+ u16_t packetLen, keyInfo, keyLen, keyDataLen, length, Op_Code;
+ u32_t replayCounterH, replayCounterL, vendorId, VendorType;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg1("EAPOL Packet size = ", zfwBufGetSize(dev, buf));
+
+ /* EAPOL packet type */
+ // 0: EAP-Packet
+ // 1: EAPOL-Start
+ // 2: EAPOL-Logoff
+ // 3: EAPOL-Key
+ // 4: EAPOL-Encapsulated-ASF-Alert
+
+ /* EAPOL frame format */
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
+ /* ----------------------------------------------- */
+ /* PAE Ethernet Type (0x888e) */
+ /* ----------------------------------------------- 2 */
+ /* Protocol Version | Type */
+ /* ----------------------------------------------- 4 */
+ /* Length */
+ /* ----------------------------------------------- 6 */
+ /* Packet Body */
+ /* ----------------------------------------------- N */
+
+ packetType = zmw_tx_buf_readb(dev, buf, offset+1);
+ /* EAPOL body length */
+ packetLen = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+2)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+3);
+
+ if( packetType == 0 )
+ { // EAP-Packet
+ /* EAP-Packet Code */
+ code = zmw_tx_buf_readb(dev, buf, offset+4); // 1 : Request
+ // 2 : Response
+ // 3 : Success
+ // 4 : Failure
+
+ // An EAP packet of the type of Success and Failure has no Data field, and has a length of 4.
+
+ /* EAP Packet format */
+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
+ /* ----------------------------------------------- */
+ /* Code | Identifier */
+ /* ----------------------------------------------- 2 */
+ /* Length */
+ /* ----------------------------------------------- 4 */
+ /* Data */
+ /* ----------------------------------------------- N */
+
+ zm_debug_msg0("EAP-Packet");
+ zm_debug_msg1("Packet Length = ", packetLen);
+ zm_debug_msg1("EAP-Packet Code = ", code);
+
+ if( code == 1 )
+ {
+ zm_debug_msg0("EAP-Packet Request");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_tx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+7);
+ /* EAP-Packet Type */
+ type = zmw_tx_buf_readb(dev, buf, offset+8); // 1 : Identity
+ // 2 : Notification
+ // 3 : Nak (Response Only)
+ // 4 : MD5-Challenge
+ // 5 : One Time Password (OTP)
+ // 6 : Generic Token Card (GTC)
+ // 254 : (Expanded Types)Wi-Fi Protected Setup
+ // 255 : Experimental Use
+
+ /* The data field in an EAP packet of the type of Request or Response is in the format shown bellowing */
+ /* 0 1 2 3 4 5 6 7 N */
+ /* ----------------------------------------------- */
+ /* Type | Type Data */
+ /* ----------------------------------------------- */
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ zm_debug_msg1("EAP-Packet Type = ", type);
+
+ if( type == 1 )
+ {
+ zm_debug_msg0("EAP-Packet Request Identity");
+ }
+ else if( type == 2 )
+ {
+ zm_debug_msg0("EAP-Packet Request Notification");
+ }
+ else if( type == 4 )
+ {
+ zm_debug_msg0("EAP-Packet Request MD5-Challenge");
+ }
+ else if( type == 5 )
+ {
+ zm_debug_msg0("EAP-Packet Request One Time Password");
+ }
+ else if( type == 6 )
+ {
+ zm_debug_msg0("EAP-Packet Request Generic Token Card");
+ }
+ else if( type == 254 )
+ {
+ zm_debug_msg0("EAP-Packet Request Wi-Fi Protected Setup");
+
+ /* 0 1 2 3 */
+ /* 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 6 7 8 9 0 1 */
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
+ /*| Type | Vendor-Id |*/
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
+ /*| Vendor-Type |*/
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
+ /*| Vendor data... */
+ /*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
+
+ /* EAP-Packet Vendor ID */
+ vendorId = (((u32_t) zmw_tx_buf_readb(dev, buf, offset+9)) << 16) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+10)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+11);
+ /* EAP-Packet Vendor Type */
+ VendorType = (((u32_t) zmw_tx_buf_readb(dev, buf, offset+12)) << 24) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+13)) << 16) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+14)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+15);
+ /* EAP-Packet Op Code */
+ Op_Code = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+16)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+17);
+ /* EAP-Packet Flags */
+ flags = zmw_tx_buf_readb(dev, buf, offset+18);
+
+ zm_debug_msg1("EAP-Packet Vendor ID = ", vendorId);
+ zm_debug_msg1("EAP-Packet Venodr Type = ", VendorType);
+ zm_debug_msg1("EAP-Packet Op Code = ", Op_Code);
+ zm_debug_msg1("EAP-Packet Flags = ", flags);
+ }
+ }
+ else if( code == 2 )
+ {
+ zm_debug_msg0("EAP-Packet Response");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_tx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+7);
+ /* EAP-Packet Type */
+ type = zmw_tx_buf_readb(dev, buf, offset+8);
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ zm_debug_msg1("EAP-Packet Type = ", type);
+
+ if( type == 1 )
+ {
+ zm_debug_msg0("EAP-Packet Response Identity");
+ }
+ else if( type == 2 )
+ {
+ zm_debug_msg0("EAP-Packet Request Notification");
+ }
+ else if( type == 3 )
+ {
+ zm_debug_msg0("EAP-Packet Request Nak");
+ }
+ else if( type == 4 )
+ {
+ zm_debug_msg0("EAP-Packet Request MD5-Challenge");
+ }
+ else if( type == 5 )
+ {
+ zm_debug_msg0("EAP-Packet Request One Time Password");
+ }
+ else if( type == 6 )
+ {
+ zm_debug_msg0("EAP-Packet Request Generic Token Card");
+ }
+ else if( type == 254 )
+ {
+ zm_debug_msg0("EAP-Packet Response Wi-Fi Protected Setup");
+
+ /* EAP-Packet Vendor ID */
+ vendorId = (((u32_t) zmw_tx_buf_readb(dev, buf, offset+9)) << 16) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+10)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+11);
+ /* EAP-Packet Vendor Type */
+ VendorType = (((u32_t) zmw_tx_buf_readb(dev, buf, offset+12)) << 24) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+13)) << 16) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+14)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+15);
+ /* EAP-Packet Op Code */
+ Op_Code = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+16)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+17);
+ /* EAP-Packet Flags */
+ flags = zmw_tx_buf_readb(dev, buf, offset+18);
+
+ zm_debug_msg1("EAP-Packet Vendor ID = ", vendorId);
+ zm_debug_msg1("EAP-Packet Venodr Type = ", VendorType);
+ zm_debug_msg1("EAP-Packet Op Code = ", Op_Code);
+ zm_debug_msg1("EAP-Packet Flags = ", flags);
+ }
+ }
+ else if( code == 3 )
+ {
+ zm_debug_msg0("EAP-Packet Success");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_rx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_rx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_rx_buf_readb(dev, buf, offset+7);
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ }
+ else if( code == 4 )
+ {
+ zm_debug_msg0("EAP-Packet Failure");
+
+ /* EAP-Packet Identifier */
+ identifier = zmw_tx_buf_readb(dev, buf, offset+5);
+ /* EAP-Packet Length */
+ length = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+6)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+7);
+
+ zm_debug_msg1("EAP-Packet Identifier = ", identifier);
+ zm_debug_msg1("EAP-Packet Length = ", length);
+ }
+ }
+ else if( packetType == 1 )
+ { // EAPOL-Start
+ zm_debug_msg0("EAPOL-Start");
+ }
+ else if( packetType == 2 )
+ { // EAPOL-Logoff
+ zm_debug_msg0("EAPOL-Logoff");
+ }
+ else if( packetType == 3 )
+ { // EAPOL-Key
+ /* EAPOL-Key type */
+ keyType = zmw_tx_buf_readb(dev, buf, offset+4);
+ /* EAPOL-Key information */
+ keyInfo = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+5)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+6);
+ /* EAPOL-Key length */
+ keyLen = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+7)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+8);
+ /* EAPOL-Key replay counter (high double word) */
+ replayCounterH = (((u32_t) zmw_tx_buf_readb(dev, buf, offset+9)) << 24) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+10)) << 16) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+11)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+12);
+ /* EAPOL-Key replay counter (low double word) */
+ replayCounterL = (((u32_t) zmw_tx_buf_readb(dev, buf, offset+13)) << 24) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+14)) << 16) +
+ (((u32_t) zmw_tx_buf_readb(dev, buf, offset+15)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+16);
+ /* EAPOL-Key data length */
+ keyDataLen = (((u16_t) zmw_tx_buf_readb(dev, buf, offset+97)) << 8) +
+ zmw_tx_buf_readb(dev, buf, offset+98);
+
+ zm_debug_msg0("EAPOL-Key");
+ zm_debug_msg1("packet length = ", packetLen);
+
+ if ( keyType == 254 )
+ {
+ zm_debug_msg0("key type = 254 (SSN key descriptor)");
+ }
+ else
+ {
+ zm_debug_msg2("key type = 0x", keyType);
+ }
+
+ zm_debug_msg2("replay counter(L) = ", replayCounterL);
+
+ zm_debug_msg2("key information = ", keyInfo);
+
+ if ( keyInfo & ZM_BIT_3 )
+ {
+ zm_debug_msg0(" - pairwise key");
+ }
+ else
+ {
+ zm_debug_msg0(" - group key");
+ }
+
+ if ( keyInfo & ZM_BIT_6 )
+ {
+ zm_debug_msg0(" - Tx key installed");
+ }
+ else
+ {
+ zm_debug_msg0(" - Tx key not set");
+ }
+
+ if ( keyInfo & ZM_BIT_7 )
+ {
+ zm_debug_msg0(" - Ack needed");
+ }
+ else
+ {
+ zm_debug_msg0(" - Ack not needed");
+ }
+
+ if ( keyInfo & ZM_BIT_8 )
+ {
+ zm_debug_msg0(" - MIC set");
+ }
+ else
+ {
+ zm_debug_msg0(" - MIC not set");
+ }
+
+ if ( keyInfo & ZM_BIT_9 )
+ {
+ zm_debug_msg0(" - packet encrypted");
+ }
+ else
+ {
+ zm_debug_msg0(" - packet not encrypted");
+ }
+
+ zm_debug_msg1("keyLen = ", keyLen);
+ zm_debug_msg1("keyDataLen = ", keyDataLen);
+ }
+ else if( packetType == 4 )
+ {
+ zm_debug_msg0("EAPOL-Encapsulated-ASF-Alert");
+ }
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiRecv80211 */
+/* Called to receive 802.11 frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : received 802.11 frame buffer. */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.5 */
+/* */
+/************************************************************************/
+void zfiRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo)
+{
+ u8_t snapCase=0, encryMode;
+ u16_t frameType, typeLengthField;
+ u16_t frameCtrl;
+ u16_t frameSubtype;
+ u16_t ret;
+ u16_t len;
+ u8_t bIsDefrag = 0;
+ u16_t offset, tailLen;
+ u8_t vap = 0;
+ u16_t da[3], sa[3];
+ u16_t ii;
+ u8_t uapsdTrig = 0;
+ zbuf_t* psBuf;
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ u8_t i;
+#endif
+
+ zmw_get_wlan_dev(dev);
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ //zm_msg2_rx(ZM_LV_2, "zfiRecv80211(), buf=", buf);
+
+ //zm_msg2_rx(ZM_LV_0, "h[0]=", zmw_rx_buf_readh(dev, buf, 0));
+ //zm_msg2_rx(ZM_LV_0, "h[2]=", zmw_rx_buf_readh(dev, buf, 2));
+ //zm_msg2_rx(ZM_LV_0, "h[4]=", zmw_rx_buf_readh(dev, buf, 4));
+
+ frameCtrl = zmw_rx_buf_readb(dev, buf, 0);
+ frameType = frameCtrl & 0xf;
+ frameSubtype = frameCtrl & 0xf0;
+
+#if 0 // Move to ProcessBeacon to judge if there's a new peer station
+ if ( (wd->wlanMode == ZM_MODE_IBSS)&&
+ (wd->sta.ibssPartnerStatus != ZM_IBSS_PARTNER_ALIVE) )
+ {
+ zfStaIbssMonitoring(dev, buf);
+ }
+#endif
+
+ /* If data frame */
+ if (frameType == ZM_WLAN_DATA_FRAME)
+ {
+ wd->sta.TotalNumberOfReceivePackets++;
+ wd->sta.TotalNumberOfReceiveBytes += zfwBufGetSize(dev, buf);
+ //zm_debug_msg1("Receive packets = ", wd->sta.TotalNumberOfReceivePackets);
+
+ //zm_msg0_rx(ZM_LV_0, "Rx data");
+ if (wd->wlanMode == ZM_MODE_AP)
+ {
+ if ((ret = zfApUpdatePsBit(dev, buf, &vap, &uapsdTrig)) != ZM_SUCCESS)
+ {
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ if (((uapsdTrig&0xf) != 0) && ((frameSubtype & 0x80) != 0))
+ {
+ u8_t ac = zcUpToAc[zmw_buf_readb(dev, buf, 24)&0x7];
+ u8_t pktNum;
+ u8_t mb;
+ u16_t flag;
+ u8_t src[6];
+
+ //printk("QoS ctrl=%d\n", zmw_buf_readb(dev, buf, 24));
+ //printk("UAPSD trigger, ac=%d\n", ac);
+
+ if (((0x8>>ac) & uapsdTrig) != 0)
+ {
+ pktNum = zcMaxspToPktNum[(uapsdTrig>>4) & 0x3];
+
+ for (ii=0; ii<6; ii++)
+ {
+ src[ii] = zmw_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+ii);
+ }
+
+ for (ii=0; ii<pktNum; ii++)
+ {
+ //if ((psBuf = zfQueueGet(dev, wd->ap.uapsdQ)) != NULL)
+ if ((psBuf = zfQueueGetWithMac(dev, wd->ap.uapsdQ, src, &mb)) != NULL)
+ {
+ if ((ii+1) == pktNum)
+ {
+ //EOSP anyway
+ flag = 0x100 | (mb<<5);
+ }
+ else
+ {
+ if (mb != 0)
+ {
+ //more data, not EOSP
+ flag = 0x20;
+ }
+ else
+ {
+ //no more data, EOSP
+ flag = 0x100;
+ }
+ }
+ zfTxSendEth(dev, psBuf, 0, ZM_EXTERNAL_ALLOC_BUF, flag);
+ }
+
+ if ((psBuf == NULL) || (mb == 0))
+ {
+ if ((ii == 0) && (psBuf == NULL))
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_QOS_NULL, (u16_t*)src, 0, 0, 0);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ }
+ else if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ u16_t frameCtrlMSB;
+ u8_t bssid[6];
+
+ /* Check Is RIFS frame and decide to enable RIFS or not */
+ if( wd->sta.EnableHT )
+ zfCheckIsRIFSFrame(dev, buf, frameSubtype);
+
+ if ( zfPowerSavingMgrIsSleeping(dev) || wd->sta.psMgr.tempWakeUp == 1)
+ {
+ frameCtrlMSB = zmw_rx_buf_readb(dev, buf, 1);
+
+ /* check more data */
+ if ( frameCtrlMSB & ZM_BIT_5 )
+ {
+ //if rx frame's AC is not delivery-enabled
+ if ((wd->sta.qosInfo&0xf) != 0xf)
+ {
+ u8_t rxAc = 0;
+ if ((frameSubtype & 0x80) != 0)
+ {
+ rxAc = zcUpToAc[zmw_buf_readb(dev, buf, 24)&0x7];
+ }
+
+ if (((0x8>>rxAc) & wd->sta.qosInfo) == 0)
+ {
+ zfSendPSPoll(dev);
+ wd->sta.psMgr.tempWakeUp = 0;
+ }
+ }
+ }
+ }
+ /*increase beacon count when receive vaild data frame from AP*/
+ ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid);
+
+ if (zfStaIsConnected(dev)&&
+ zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6))
+ {
+ wd->sta.rxBeaconCount++;
+ }
+ }
+
+ zm_msg1_rx(ZM_LV_2, "Rx VAP=", vap);
+
+ /* handle IV, EXT-IV, ICV, and EXT-ICV */
+ zfGetRxIvIcvLength(dev, buf, vap, &offset, &tailLen, addInfo);
+
+ zfStaIbssPSCheckState(dev, buf);
+ //QoS data frame
+ if ((frameSubtype & 0x80) == 0x80)
+ {
+ offset += 2;
+ }
+
+ len = zfwBufGetSize(dev, buf);
+ /* remove ICV */
+ if (tailLen > 0)
+ {
+ if (len > tailLen)
+ {
+ len -= tailLen;
+ zfwBufSetSize(dev, buf, len);
+ }
+ }
+
+ /* Filter NULL data */
+ if (((frameSubtype&0x40) != 0) || ((len = zfwBufGetSize(dev, buf))<=24))
+ {
+ zm_msg1_rx(ZM_LV_1, "Free Rx NULL data, len=", len);
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ /* check and handle defragmentation */
+ if ( wd->sta.bSafeMode && (wd->sta.wepStatus == ZM_ENCRYPTION_AES) && wd->sta.SWEncryptEnable )
+ {
+ zm_msg0_rx(ZM_LV_1, "Bypass defragmentation packets in safe mode");
+ }
+ else
+ {
+ if ( (buf = zfDefragment(dev, buf, &bIsDefrag, addInfo)) == NULL )
+ {
+ /* In this case, the buffer has been freed in zfDefragment */
+ return;
+ }
+ }
+
+ ret = ZM_MIC_SUCCESS;
+
+ /* If SW WEP/TKIP are not turned on */
+ if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_DECRY_EN) == 0 &&
+ (wd->sta.SWEncryptEnable & ZM_SW_WEP_DECRY_EN) == 0)
+ {
+ encryMode = zfGetEncryModeFromRxStatus(addInfo);
+
+ /* check if TKIP */
+ if ( encryMode == ZM_TKIP )
+ {
+ if ( bIsDefrag )
+ {
+ ret = zfMicRxVerify(dev, buf);
+ }
+ else
+ {
+ /* check MIC failure bit */
+ if ( ZM_RX_STATUS_IS_MIC_FAIL(addInfo) )
+ {
+ ret = ZM_MIC_FAILURE;
+ }
+ }
+
+ if ( ret == ZM_MIC_FAILURE )
+ {
+ u8_t Unicast_Pkt = 0x0;
+
+ if ((zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) & 0x1) == 0)
+ {
+ wd->commTally.swRxUnicastMicFailCount++;
+ Unicast_Pkt = 0x1;
+ }/*
+ else if (zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) == 0xffff)
+ {
+ wd->commTally.swRxMulticastMicFailCount++;
+ }*/
+ else
+ {
+ wd->commTally.swRxMulticastMicFailCount++;
+ }
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ u16_t idx;
+ u8_t addr[6];
+
+ for (idx=0; idx<6; idx++)
+ {
+ addr[idx] = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+idx);
+ }
+
+ if (wd->zfcbApMicFailureNotify != NULL)
+ {
+ wd->zfcbApMicFailureNotify(dev, addr, buf);
+ }
+ }
+ else
+ {
+ if(Unicast_Pkt)
+ {
+ zm_debug_msg0("Countermeasure : Unicast_Pkt ");
+ }
+ else
+ {
+ zm_debug_msg0("Countermeasure : Non-Unicast_Pkt ");
+ }
+
+ if((wd->TKIP_Group_KeyChanging == 0x0) || (Unicast_Pkt == 0x1))
+ {
+ zm_debug_msg0("Countermeasure : Do MIC Check ");
+ zfStaMicFailureHandling(dev, buf);
+ }
+ else
+ {
+ zm_debug_msg0("Countermeasure : SKIP MIC Check due to Group Keychanging ");
+ }
+ }
+ /* Discard MIC failed frame */
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+ }
+ }
+ else
+ {
+ u8_t IsEncryFrame;
+
+ /* TODO: Check whether WEP bit is turned on in MAC header */
+ encryMode = ZM_NO_WEP;
+
+ IsEncryFrame = (zmw_rx_buf_readb(dev, buf, 1) & 0x40);
+
+ if (IsEncryFrame)
+ {
+ /* Software decryption for TKIP */
+ if (wd->sta.SWEncryptEnable & ZM_SW_TKIP_DECRY_EN)
+ {
+ u16_t iv16;
+ u16_t iv32;
+ u8_t RC4Key[16];
+ u16_t IvOffset;
+ struct zsTkipSeed *rxSeed;
+
+ IvOffset = offset + ZM_SIZE_OF_WLAN_DATA_HEADER;
+
+ rxSeed = zfStaGetRxSeed(dev, buf);
+
+ if (rxSeed == NULL)
+ {
+ zm_debug_msg0("rxSeed is NULL");
+
+ /* Discard this frame */
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ iv16 = (zmw_rx_buf_readb(dev, buf, IvOffset) << 8) + zmw_rx_buf_readb(dev, buf, IvOffset+2);
+ iv32 = zmw_rx_buf_readb(dev, buf, IvOffset+4) +
+ (zmw_rx_buf_readb(dev, buf, IvOffset+5) << 8) +
+ (zmw_rx_buf_readb(dev, buf, IvOffset+6) << 16) +
+ (zmw_rx_buf_readb(dev, buf, IvOffset+7) << 24);
+
+ /* TKIP Key Mixing */
+ zfTkipPhase1KeyMix(iv32, rxSeed);
+ zfTkipPhase2KeyMix(iv16, rxSeed);
+ zfTkipGetseeds(iv16, RC4Key, rxSeed);
+
+ /* Decrypt Data */
+ ret = zfTKIPDecrypt(dev, buf, IvOffset+ZM_SIZE_OF_IV+ZM_SIZE_OF_EXT_IV, 16, RC4Key);
+
+ if (ret == ZM_ICV_FAILURE)
+ {
+ zm_debug_msg0("TKIP ICV fail");
+
+ /* Discard ICV failed frame */
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ /* Remove ICV from buffer */
+ zfwBufSetSize(dev, buf, len-4);
+
+ /* Check MIC */
+ ret = zfMicRxVerify(dev, buf);
+
+ if (ret == ZM_MIC_FAILURE)
+ {
+ if ((zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) & 0x1) == 0)
+ {
+ wd->commTally.swRxUnicastMicFailCount++;
+ }
+ else if (zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) == 0xffff)
+ {
+ wd->commTally.swRxMulticastMicFailCount++;
+ }
+ else
+ {
+ wd->commTally.swRxMulticastMicFailCount++;
+ }
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ u16_t idx;
+ u8_t addr[6];
+
+ for (idx=0; idx<6; idx++)
+ {
+ addr[idx] = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+idx);
+ }
+
+ if (wd->zfcbApMicFailureNotify != NULL)
+ {
+ wd->zfcbApMicFailureNotify(dev, addr, buf);
+ }
+ }
+ else
+ {
+ zfStaMicFailureHandling(dev, buf);
+ }
+
+ zm_debug_msg0("MIC fail");
+ /* Discard MIC failed frame */
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ encryMode = ZM_TKIP;
+ offset += ZM_SIZE_OF_IV + ZM_SIZE_OF_EXT_IV;
+ }
+ else if(wd->sta.SWEncryptEnable & ZM_SW_WEP_DECRY_EN)
+ {
+ u16_t IvOffset;
+ u8_t keyLen = 5;
+ u8_t iv[3];
+ u8_t *wepKey;
+ u8_t keyIdx;
+
+ IvOffset = offset + ZM_SIZE_OF_WLAN_DATA_HEADER;
+
+ /* Retrieve IV */
+ iv[0] = zmw_rx_buf_readb(dev, buf, IvOffset);
+ iv[1] = zmw_rx_buf_readb(dev, buf, IvOffset+1);
+ iv[2] = zmw_rx_buf_readb(dev, buf, IvOffset+2);
+
+ keyIdx = ((zmw_rx_buf_readb(dev, buf, IvOffset+3) >> 6) & 0x03);
+
+ IvOffset += ZM_SIZE_OF_IV;
+
+ if (wd->sta.SWEncryMode[keyIdx] == ZM_WEP64)
+ {
+ keyLen = 5;
+ }
+ else if (wd->sta.SWEncryMode[keyIdx] == ZM_WEP128)
+ {
+ keyLen = 13;
+ }
+ else if (wd->sta.SWEncryMode[keyIdx] == ZM_WEP256)
+ {
+ keyLen = 29;
+ }
+
+ zfWEPDecrypt(dev, buf, IvOffset, keyLen, wd->sta.wepKey[keyIdx], iv);
+
+ if (ret == ZM_ICV_FAILURE)
+ {
+ zm_debug_msg0("WEP ICV fail");
+
+ /* Discard ICV failed frame */
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ encryMode = wd->sta.SWEncryMode[keyIdx];
+
+ /* Remove ICV from buffer */
+ zfwBufSetSize(dev, buf, len-4);
+
+ offset += ZM_SIZE_OF_IV;
+ }
+ }
+ }
+
+#ifdef ZM_ENABLE_CENC
+ //else if ( encryMode == ZM_CENC ) /* check if CENC */
+ if ( encryMode == ZM_CENC )
+ {
+ u32_t rxIV[4];
+
+ rxIV[0] = (zmw_rx_buf_readh(dev, buf, 28) << 16)
+ + zmw_rx_buf_readh(dev, buf, 26);
+ rxIV[1] = (zmw_rx_buf_readh(dev, buf, 32) << 16)
+ + zmw_rx_buf_readh(dev, buf, 30);
+ rxIV[2] = (zmw_rx_buf_readh(dev, buf, 36) << 16)
+ + zmw_rx_buf_readh(dev, buf, 34);
+ rxIV[3] = (zmw_rx_buf_readh(dev, buf, 40) << 16)
+ + zmw_rx_buf_readh(dev, buf, 38);
+
+ //zm_debug_msg2("rxIV[0] = 0x", rxIV[0]);
+ //zm_debug_msg2("rxIV[1] = 0x", rxIV[1]);
+ //zm_debug_msg2("rxIV[2] = 0x", rxIV[2]);
+ //zm_debug_msg2("rxIV[3] = 0x", rxIV[3]);
+
+ /* destination address*/
+ da[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
+ da[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+2);
+ da[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+4);
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ }
+ else
+ {
+ if ((da[0] & 0x1))
+ { //multicast frame
+ /* Accumlate the PN sequence */
+ wd->sta.rxivGK[0] ++;
+
+ if (wd->sta.rxivGK[0] == 0)
+ {
+ wd->sta.rxivGK[1]++;
+ }
+
+ if (wd->sta.rxivGK[1] == 0)
+ {
+ wd->sta.rxivGK[2]++;
+ }
+
+ if (wd->sta.rxivGK[2] == 0)
+ {
+ wd->sta.rxivGK[3]++;
+ }
+
+ if (wd->sta.rxivGK[3] == 0)
+ {
+ wd->sta.rxivGK[0] = 0;
+ wd->sta.rxivGK[1] = 0;
+ wd->sta.rxivGK[2] = 0;
+ }
+
+ //zm_debug_msg2("wd->sta.rxivGK[0] = 0x", wd->sta.rxivGK[0]);
+ //zm_debug_msg2("wd->sta.rxivGK[1] = 0x", wd->sta.rxivGK[1]);
+ //zm_debug_msg2("wd->sta.rxivGK[2] = 0x", wd->sta.rxivGK[2]);
+ //zm_debug_msg2("wd->sta.rxivGK[3] = 0x", wd->sta.rxivGK[3]);
+
+ if ( !((wd->sta.rxivGK[0] == rxIV[0])
+ && (wd->sta.rxivGK[1] == rxIV[1])
+ && (wd->sta.rxivGK[2] == rxIV[2])
+ && (wd->sta.rxivGK[3] == rxIV[3])))
+ {
+ u8_t PacketDiscard = 0;
+ /* Discard PN Code Error frame */
+ if (rxIV[0] < wd->sta.rxivGK[0])
+ {
+ PacketDiscard = 1;
+ }
+ if (wd->sta.rxivGK[0] > 0xfffffff0)
+ { //boundary case
+ if ((rxIV[0] < 0xfffffff0)
+ && (((0xffffffff - wd->sta.rxivGK[0]) + rxIV[0]) > 16))
+ {
+ PacketDiscard = 1;
+ }
+ }
+ else
+ { //normal case
+ if ((rxIV[0] - wd->sta.rxivGK[0]) > 16)
+ {
+ PacketDiscard = 1;
+ }
+ }
+ // sync sta pn code with ap because of losting some packets
+ wd->sta.rxivGK[0] = rxIV[0];
+ wd->sta.rxivGK[1] = rxIV[1];
+ wd->sta.rxivGK[2] = rxIV[2];
+ wd->sta.rxivGK[3] = rxIV[3];
+ if (PacketDiscard)
+ {
+ zm_debug_msg0("Discard PN Code lost too much multicast frame");
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+ }
+ }
+ else
+ { //unicast frame
+ /* Accumlate the PN sequence */
+ wd->sta.rxiv[0] += 2;
+
+ if (wd->sta.rxiv[0] == 0 || wd->sta.rxiv[0] == 1)
+ {
+ wd->sta.rxiv[1]++;
+ }
+
+ if (wd->sta.rxiv[1] == 0)
+ {
+ wd->sta.rxiv[2]++;
+ }
+
+ if (wd->sta.rxiv[2] == 0)
+ {
+ wd->sta.rxiv[3]++;
+ }
+
+ if (wd->sta.rxiv[3] == 0)
+ {
+ wd->sta.rxiv[0] = 0;
+ wd->sta.rxiv[1] = 0;
+ wd->sta.rxiv[2] = 0;
+ }
+
+ //zm_debug_msg2("wd->sta.rxiv[0] = 0x", wd->sta.rxiv[0]);
+ //zm_debug_msg2("wd->sta.rxiv[1] = 0x", wd->sta.rxiv[1]);
+ //zm_debug_msg2("wd->sta.rxiv[2] = 0x", wd->sta.rxiv[2]);
+ //zm_debug_msg2("wd->sta.rxiv[3] = 0x", wd->sta.rxiv[3]);
+
+ if ( !((wd->sta.rxiv[0] == rxIV[0])
+ && (wd->sta.rxiv[1] == rxIV[1])
+ && (wd->sta.rxiv[2] == rxIV[2])
+ && (wd->sta.rxiv[3] == rxIV[3])))
+ {
+ zm_debug_msg0("PN Code mismatch, lost unicast frame, sync pn code to recv packet");
+ // sync sta pn code with ap because of losting some packets
+ wd->sta.rxiv[0] = rxIV[0];
+ wd->sta.rxiv[1] = rxIV[1];
+ wd->sta.rxiv[2] = rxIV[2];
+ wd->sta.rxiv[3] = rxIV[3];
+ /* Discard PN Code Error frame */
+ //zm_debug_msg0("Discard PN Code mismatch unicast frame");
+ //zfwBufFree(dev, buf, 0);
+ //return;
+ }
+ }
+ }
+ }
+#endif //ZM_ENABLE_CENC
+
+ /* for tally */
+ if ((zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) & 0x1) == 0)
+ {
+ /* for ACU to display RxRate */
+ zfWlanUpdateRxRate(dev, addInfo);
+
+ wd->commTally.rxUnicastFrm++;
+ wd->commTally.rxUnicastOctets += (len-24);
+ }
+ else if (zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET) == 0xffff)
+ {
+ wd->commTally.rxBroadcastFrm++;
+ wd->commTally.rxBroadcastOctets += (len-24);
+ }
+ else
+ {
+ wd->commTally.rxMulticastFrm++;
+ wd->commTally.rxMulticastOctets += (len-24);
+ }
+ wd->ledStruct.rxTraffic++;
+
+ if ((frameSubtype & 0x80) == 0x80)
+ {
+ /* if QoS control bit-7 is 1 => A-MSDU frame */
+ if ((zmw_rx_buf_readh(dev, buf, 24) & 0x80) != 0)
+ {
+ zfDeAmsdu(dev, buf, vap, encryMode);
+ return;
+ }
+ }
+
+ // Remove MIC of TKIP
+ if ( encryMode == ZM_TKIP )
+ {
+ zfwBufSetSize(dev, buf, zfwBufGetSize(dev, buf) - 8);
+ }
+
+ /* Convert 802.11 and SNAP header to ethernet header */
+ if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)||
+ (wd->wlanMode == ZM_MODE_IBSS) )
+ {
+ /* destination address*/
+ da[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET);
+ da[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+2);
+ da[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET+4);
+
+ /* check broadcast frame */
+ if ( (da[0] == 0xffff) && (da[1] == 0xffff) && (da[2] == 0xffff) )
+ {
+ // Ap send broadcast frame to the DUT !
+ }
+ /* check multicast frame */
+ /* TODO : Remove these code, hardware should be able to block */
+ /* multicast frame on the multicast address list */
+ /* or bypass all multicast packet by flag bAllMulticast */
+ else if ((da[0] & 0x01) && (wd->sta.bAllMulticast == 0))
+ {
+ for(ii=0; ii<wd->sta.multicastList.size; ii++)
+ {
+ if ( zfMemoryIsEqual(wd->sta.multicastList.macAddr[ii].addr,
+ (u8_t*) da, 6))
+ {
+ break;
+ }
+ }
+
+ if ( ii == wd->sta.multicastList.size )
+ { /* not found */
+ zm_debug_msg0("discard unknown multicast frame");
+
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+ }
+
+#ifdef ZM_ENABLE_NATIVE_WIFI //Native Wifi : 1, Ethernet format : 0
+ //To remove IV
+ if (offset > 0)
+ {
+ for (i=12; i>0; i--)
+ {
+ zmw_rx_buf_writeh(dev, buf, ((i-1)*2)+offset,
+ zmw_rx_buf_readh(dev, buf, (i-1)*2));
+ }
+ zfwBufRemoveHead(dev, buf, offset);
+ }
+#else
+
+ if (zfRxBufferEqualToStr(dev, buf, zgSnapBridgeTunnel,
+ 24+offset, 6))
+ {
+ snapCase = 1;
+ }
+ else if ( zfRxBufferEqualToStr(dev, buf, zgSnap8021h,
+ 24+offset, 6) )
+ {
+ typeLengthField =
+ (((u16_t) zmw_rx_buf_readb(dev, buf, 30+offset)) << 8) +
+ zmw_rx_buf_readb(dev, buf, 31+offset);
+
+ //zm_debug_msg2("tpyeLengthField = ", typeLengthField);
+
+ //8137 : IPX, 80F3 : Appletalk
+ if ( (typeLengthField != 0x8137)&&
+ (typeLengthField != 0x80F3) )
+ {
+ snapCase = 2;
+ }
+
+ if ( typeLengthField == 0x888E )
+ {
+ zfShowRxEAPOL(dev, buf, 32);
+ }
+ }
+ else
+ {
+ //zfwDumpBuf(dev, buf);
+ }
+
+ /* source address */
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ /* SA = Address 3 */
+ sa[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET);
+ sa[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2);
+ sa[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4);
+ }
+ else
+ {
+ /* SA = Address 2 */
+ sa[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET);
+ sa[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2);
+ sa[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4);
+ }
+
+ if ( snapCase )
+ {
+ /* SA */
+ zmw_rx_buf_writeh(dev, buf, 24+offset, sa[0]);
+ zmw_rx_buf_writeh(dev, buf, 26+offset, sa[1]);
+ zmw_rx_buf_writeh(dev, buf, 28+offset, sa[2]);
+
+ /* DA = Address 1 */
+ zmw_rx_buf_writeh(dev, buf, 18+offset, da[0]);
+ zmw_rx_buf_writeh(dev, buf, 20+offset, da[1]);
+ zmw_rx_buf_writeh(dev, buf, 22+offset, da[2]);
+ zfwBufRemoveHead(dev, buf, 18+offset);
+ }
+ else
+ {
+ /* SA */
+ zmw_rx_buf_writeh(dev, buf, 16+offset, sa[0]);
+ zmw_rx_buf_writeh(dev, buf, 18+offset, sa[1]);
+ zmw_rx_buf_writeh(dev, buf, 20+offset, sa[2]);
+
+ /* DA = Address 1 */
+ zmw_rx_buf_writeh(dev, buf, 10+offset, da[0]);
+ zmw_rx_buf_writeh(dev, buf, 12+offset, da[1]);
+ zmw_rx_buf_writeh(dev, buf, 14+offset, da[2]);
+ zfwBufRemoveHead(dev, buf, 10+offset);
+ /* Ethernet payload length */
+ typeLengthField = zfwBufGetSize(dev, buf) - 14;
+ zmw_rx_buf_writeh(dev, buf, 12, (typeLengthField<<8)+(typeLengthField>>8));
+ }
+#endif // ZM_ENABLE_NATIVE_WIFI
+ }
+ else if (wd->wlanMode == ZM_MODE_AP)
+ {
+ //if ((zmw_rx_buf_readb(dev, buf, 1) & 0x3) != 3)
+ if (vap < ZM_MAX_AP_SUPPORT)
+ /* AP mode */
+ {
+#ifdef ZM_ENABLE_NATIVE_WIFI //Native Wifi : 1, Ethernet format : 0
+ //To remove IV
+ if (offset > 0)
+ {
+ for (i=12; i>0; i--)
+ {
+ zmw_rx_buf_writeh(dev, buf, ((i-1)*2)+offset,
+ zmw_rx_buf_readh(dev, buf, (i-1)*2));
+ }
+ zfwBufRemoveHead(dev, buf, offset);
+ }
+#else
+ /* SA = Address 2 */
+ zmw_rx_buf_writeh(dev, buf, 24+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A2_OFFSET));
+ zmw_rx_buf_writeh(dev, buf, 26+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A2_OFFSET+2));
+ zmw_rx_buf_writeh(dev, buf, 28+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A2_OFFSET+4));
+ /* DA = Address 3 */
+ /* Seq : Read 20 write 22, read 18 write 20, read 16 write 18 */
+ /* sequence must not be inverted */
+ zmw_rx_buf_writeh(dev, buf, 22+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A3_OFFSET+4));
+ zmw_rx_buf_writeh(dev, buf, 20+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A3_OFFSET+2));
+ zmw_rx_buf_writeh(dev, buf, 18+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A3_OFFSET));
+ zfwBufRemoveHead(dev, buf, 18+offset);
+#endif // ZM_ENABLE_NATIVE_WIFI
+ #if 1
+ if ((ret = zfIntrabssForward(dev, buf, vap)) == 1)
+ {
+ /* Free Rx buffer if intra-BSS unicast frame */
+ zm_msg0_rx(ZM_LV_2, "Free intra-BSS unicast frame");
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+ #endif
+ }
+ else
+ /* WDS mode */
+ {
+ zm_msg0_rx(ZM_LV_2, "Rx WDS data");
+
+ /* SA = Address 4 */
+ zmw_rx_buf_writeh(dev, buf, 30+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A4_OFFSET));
+ zmw_rx_buf_writeh(dev, buf, 32+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A4_OFFSET+2));
+ zmw_rx_buf_writeh(dev, buf, 34+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A4_OFFSET+4));
+ /* DA = Address 3 */
+ /* Seq : Read 20 write 22, read 18 write 20, read 16 write 18 */
+ /* sequence must not be inverted */
+ zmw_rx_buf_writeh(dev, buf, 28+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A3_OFFSET+4));
+ zmw_rx_buf_writeh(dev, buf, 26+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A3_OFFSET+2));
+ zmw_rx_buf_writeh(dev, buf, 24+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A3_OFFSET));
+ zfwBufRemoveHead(dev, buf, 24+offset);
+ }
+ }
+ else if (wd->wlanMode == ZM_MODE_PSEUDO)
+ {
+ /* WDS test: remove add4 */
+ if (wd->enableWDS)
+ {
+ offset += 6;
+ }
+
+ /* SA = Address 2 */
+ zmw_rx_buf_writeh(dev, buf, 24+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A2_OFFSET));
+ zmw_rx_buf_writeh(dev, buf, 26+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A2_OFFSET+2));
+ zmw_rx_buf_writeh(dev, buf, 28+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A2_OFFSET+4));
+ /* DA = Address 1 */
+ zmw_rx_buf_writeh(dev, buf, 18+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A1_OFFSET));
+ zmw_rx_buf_writeh(dev, buf, 20+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A1_OFFSET+2));
+ zmw_rx_buf_writeh(dev, buf, 22+offset, zmw_rx_buf_readh(dev, buf,
+ ZM_WLAN_HEADER_A1_OFFSET+4));
+ zfwBufRemoveHead(dev, buf, 18+offset);
+ }
+ else
+ {
+ zm_assert(0);
+ }
+
+ /* Call zfwRecvEth() to notify upper layer */
+ //zm_msg2_rx(ZM_LV_2, "Call zfwRecvEth(), buf=", buf);
+ //zfwDumpBuf(dev, buf);
+
+ #if ZM_PROTOCOL_RESPONSE_SIMULATION == 1
+ zfProtRspSim(dev, buf);
+ #endif
+ //zfwDumpBuf(dev, buf);
+
+ /* tally */
+ wd->commTally.NotifyNDISRxFrmCnt++;
+
+ if (wd->zfcbRecvEth != NULL)
+ {
+ wd->zfcbRecvEth(dev, buf, vap);
+ ZM_PERFORMANCE_RX_MSDU(dev, wd->tick)
+ }
+ }
+ /* if management frame */
+ else if (frameType == ZM_WLAN_MANAGEMENT_FRAME)
+ {
+ zm_msg2_rx(ZM_LV_2, "Rx management,FC=", frameCtrl);
+ /* Call zfProcessManagement() to handle management frame */
+ zfProcessManagement(dev, buf, addInfo); //CWYang(m)
+ zfwBufFree(dev, buf, 0);
+ }
+ /* PsPoll */
+ else if ((wd->wlanMode == ZM_MODE_AP) && (frameCtrl == 0xa4))
+ {
+ zm_msg0_rx(ZM_LV_0, "Rx PsPoll");
+ zfApProcessPsPoll(dev, buf);
+ zfwBufFree(dev, buf, 0);
+ }
+ else
+ {
+ zm_msg0_rx(ZM_LV_1, "Rx discard!!");
+ wd->commTally.DriverDiscardedFrm++;
+
+ zfwBufFree(dev, buf, 0);
+ }
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfWlanRxValidate */
+/* Validate Rx frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : received 802.11 frame buffer. */
+/* */
+/* OUTPUTS */
+/* Error code */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfWlanRxValidate(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t frameType;
+ u16_t frameCtrl;
+ u16_t frameLen;
+ u16_t ret;
+ u8_t frameSubType;
+
+ zmw_get_wlan_dev(dev);
+
+ frameCtrl = zmw_rx_buf_readh(dev, buf, 0);
+ frameType = frameCtrl & 0xC;
+ frameSubType = (frameCtrl & 0xF0) >> 4;
+
+ frameLen = zfwBufGetSize(dev, buf);
+
+ /* Accept Data/Management frame with protocol version = 0 */
+ if ((frameType == 0x8) || (frameType == 0x0))
+ {
+
+ /* TODO : check rx status => erro bit */
+
+ /* Check Minimum Length with Wep */
+ if ((frameCtrl & 0x4000) != 0)
+ {
+ /* Minimum Length = */
+ /* PLCP(5)+Header(24)+IV(4)+ICV(4)+CRC(4)+RxStatus(8) */
+ if (frameLen < 32)
+ {
+ return ZM_ERR_MIN_RX_ENCRYPT_FRAME_LENGTH;
+ }
+ }
+ else if ( frameSubType == 0x5 || frameSubType == 0x8 )
+ {
+ /* Minimum Length = PLCP(5)+MACHeader(24)+Timestamp(8)+BeaconInterval(2)+Cap(2)+CRC(4)+RxStatus(8) */
+ if (frameLen < 36)
+ {
+ return ZM_ERR_MIN_RX_FRAME_LENGTH;
+ }
+ }
+ else
+ {
+ /* Minimum Length = PLCP(5)+MACHeader(24)+CRC(4)+RxStatus(8) */
+ if (frameLen < 24)
+ {
+ return ZM_ERR_MIN_RX_FRAME_LENGTH;
+ }
+ }
+
+ /* Check if frame Length > ZM_WLAN_MAX_RX_SIZE. */
+ if (frameLen > ZM_WLAN_MAX_RX_SIZE)
+ {
+ return ZM_ERR_MAX_RX_FRAME_LENGTH;
+ }
+ }
+ else if ((frameCtrl&0xff) == 0xa4)
+ {
+ /* PsPoll */
+ //zm_msg0_rx(ZM_LV_0, "rx pspoll");
+ }
+ else if ((frameCtrl&0xff) == ZM_WLAN_FRAME_TYPE_BAR)
+ {
+ if (wd->sta.enableDrvBA == 1)
+ {
+ zfAggRecvBAR(dev, buf);
+ }
+
+ return ZM_ERR_RX_BAR_FRAME;
+ }
+ else
+ {
+ return ZM_ERR_RX_FRAME_TYPE;
+ }
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ }
+ else if ( wd->wlanMode != ZM_MODE_PSEUDO )
+ {
+ if ( (ret=zfStaRxValidateFrame(dev, buf))!=ZM_SUCCESS )
+ {
+ //zm_debug_msg1("discard frame, code = ", ret);
+ return ret;
+ }
+ }
+
+ return ZM_SUCCESS;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfWlanRxFilter */
+/* Filter duplicated frame. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : received 802.11 frame buffer. */
+/* */
+/* OUTPUTS */
+/* Error code */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u16_t zfWlanRxFilter(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t src[3];
+ u16_t dst0;
+ u16_t frameType;
+ u16_t seq;
+ u16_t offset;
+ u16_t index;
+ u16_t col;
+ u16_t i;
+ u8_t up = 0; /* User priority */
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ /* RX PREFIX */
+ offset = 0;
+
+ frameType = zmw_rx_buf_readh(dev, buf, offset);
+
+ // Don't divide 2^4 because we don't want the fragementation pkt to be treated as
+ // duplicated frames
+ seq = zmw_rx_buf_readh(dev, buf, offset+22);
+ dst0 = zmw_rx_buf_readh(dev, buf, offset+4);
+ src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
+ src[1] = zmw_rx_buf_readh(dev, buf, offset+12);
+ src[2] = zmw_rx_buf_readh(dev, buf, offset+14);
+
+ /* QoS data frame */
+ if ((frameType & 0x88) == 0x88)
+ {
+ up = zmw_rx_buf_readb(dev, buf, offset+24);
+ up &= 0x7;
+ }
+
+ index = (src[2]+up) & (ZM_FILTER_TABLE_ROW-1);
+
+ /* TBD : filter frame with source address == own MAC adress */
+ if ((wd->macAddr[0] == src[0]) && (wd->macAddr[1] == src[1])
+ && (wd->macAddr[2] == src[2]))
+ {
+ //zm_msg0_rx(ZM_LV_0, "Rx filter=>src is own MAC");
+ wd->trafTally.rxSrcIsOwnMac++;
+#if 0
+ return ZM_ERR_RX_SRC_ADDR_IS_OWN_MAC;
+#endif
+ }
+
+ zm_msg2_rx(ZM_LV_2, "Rx seq=", seq);
+
+ /* Filter unicast frame only */
+ if ((dst0 & 0x1) == 0)
+ {
+ zmw_enter_critical_section(dev);
+
+ for(i=0; i<ZM_FILTER_TABLE_COL; i++)
+ {
+ if ((wd->rxFilterTbl[i][index].addr[0] == src[0])
+ && (wd->rxFilterTbl[i][index].addr[1] == src[1])
+ && (wd->rxFilterTbl[i][index].addr[2] == src[2])
+ && (wd->rxFilterTbl[i][index].up == up))
+ {
+ if (((frameType&0x800)==0x800)
+ &&(wd->rxFilterTbl[i][index].seq==seq))
+ {
+ zmw_leave_critical_section(dev);
+ /* hit : duplicated frame */
+ zm_msg0_rx(ZM_LV_1, "Rx filter hit=>duplicated");
+ wd->trafTally.rxDuplicate++;
+ return ZM_ERR_RX_DUPLICATE;
+ }
+ else
+ {
+ /* hit : not duplicated frame, update sequence number */
+ wd->rxFilterTbl[i][index].seq = seq;
+ zmw_leave_critical_section(dev);
+ zm_msg0_rx(ZM_LV_2, "Rx filter hit");
+ return ZM_SUCCESS;
+ }
+ }
+ } /* for(i=0; i<ZM_FILTER_TABLE_COL; i++) */
+
+ /* miss : add to table */
+ zm_msg0_rx(ZM_LV_1, "Rx filter miss");
+ /* TODO : Random select a column */
+ col = (u16_t)(wd->tick & (ZM_FILTER_TABLE_COL-1));
+ wd->rxFilterTbl[col][index].addr[0] = src[0];
+ wd->rxFilterTbl[col][index].addr[1] = src[1];
+ wd->rxFilterTbl[col][index].addr[2] = src[2];
+ wd->rxFilterTbl[col][index].seq = seq;
+ wd->rxFilterTbl[col][index].up = up;
+
+ zmw_leave_critical_section(dev);
+ } /* if ((dst0 & 0x1) == 0) */
+
+ return ZM_SUCCESS;
+}
+
+
+
+u16_t zfTxGenWlanTail(zdev_t* dev, zbuf_t* buf, u16_t* snap, u16_t snaplen,
+ u16_t* mic)
+{
+ struct zsMicVar* pMicKey;
+ u16_t i, length, payloadOffset;
+ u8_t bValue, qosType = 0;
+ u8_t snapByte[12];
+
+ zmw_get_wlan_dev(dev);
+
+ if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ pMicKey = zfApGetTxMicKey(dev, buf, &qosType);
+
+ if ( pMicKey == NULL )
+ {
+ return 0;
+ }
+ }
+ else if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ pMicKey = zfStaGetTxMicKey(dev, buf);
+
+ if ( pMicKey == NULL )
+ {
+ return 0;
+ }
+ }
+ else
+ {
+ return 0;
+ }
+
+ length = zfwBufGetSize(dev, buf);
+
+ zfMicClear(pMicKey);
+
+ /* append DA and SA */
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ for(i=16; i<22; i++)
+ { // VISTA DA
+ bValue = zmw_tx_buf_readb(dev, buf, i);
+ zfMicAppendByte(bValue, pMicKey);
+ }
+ for(i=10; i<16; i++)
+ { // VISTA SA
+ bValue = zmw_tx_buf_readb(dev, buf, i);
+ zfMicAppendByte(bValue, pMicKey);
+ }
+#else
+ for(i=0; i<12; i++)
+ {
+ bValue = zmw_tx_buf_readb(dev, buf, i);
+ zfMicAppendByte(bValue, pMicKey);
+ }
+#endif
+
+ /* append for alignment */
+ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ {
+ if (wd->sta.wmeConnected != 0)
+ zfMicAppendByte(zmw_tx_buf_readb(dev, buf, ZM_80211_FRAME_IP_OFFSET + 1) >> 5, pMicKey);
+ else
+ zfMicAppendByte(0, pMicKey);
+ }
+ else if ( wd->wlanMode == ZM_MODE_AP )
+ {
+ if (qosType == 1)
+ zfMicAppendByte(zmw_tx_buf_readb(dev, buf, ZM_80211_FRAME_IP_OFFSET + 1) >> 5, pMicKey);
+ else
+ zfMicAppendByte(0, pMicKey);
+ }
+ else
+ {
+ /* TODO : Qos Software MIC in IBSS Mode */
+ zfMicAppendByte(0, pMicKey);
+ }
+ zfMicAppendByte(0, pMicKey);
+ zfMicAppendByte(0, pMicKey);
+ zfMicAppendByte(0, pMicKey);
+
+ if ( snaplen == 0 )
+ {
+ payloadOffset = ZM_80211_FRAME_IP_OFFSET;
+ }
+ else
+ {
+ payloadOffset = ZM_80211_FRAME_TYPE_OFFSET;
+
+ for(i=0; i<(snaplen>>1); i++)
+ {
+ snapByte[i*2] = (u8_t) (snap[i] & 0xff);
+ snapByte[i*2+1] = (u8_t) ((snap[i] >> 8) & 0xff);
+ }
+
+ for(i=0; i<snaplen; i++)
+ {
+ zfMicAppendByte(snapByte[i], pMicKey);
+ }
+ }
+
+ for(i=payloadOffset; i<length; i++)
+ {
+ bValue = zmw_tx_buf_readb(dev, buf, i);
+ zfMicAppendByte(bValue, pMicKey);
+ }
+
+ zfMicGetMic( (u8_t*) mic, pMicKey);
+
+ return ZM_SIZE_OF_MIC;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfTxGetIpTosAndFrag */
+/* Get IP TOS and frag offset from Tx buffer */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : Tx buffer pointer */
+/* up : pointer for returning user priority */
+/* fragOff : pointer for returning ip frag offset */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+void zfTxGetIpTosAndFrag(zdev_t* dev, zbuf_t* buf, u8_t* up, u16_t* fragOff)
+{
+ u8_t ipv;
+ u16_t len;
+ u16_t etherType;
+ u8_t tos;
+
+ *up = 0;
+ *fragOff = 0;
+
+ len = zfwBufGetSize(dev, buf);
+
+ if (len >= 34) //Minimum IPv4 packet size, 14(Ether header)+20(IPv4 header)
+ {
+ etherType = (((u16_t)zmw_tx_buf_readb(dev, buf, ZM_80211_FRAME_TYPE_OFFSET))<<8)
+ + zmw_tx_buf_readb(dev, buf, ZM_80211_FRAME_TYPE_OFFSET + 1);
+
+ /* protocol type = IP */
+ if (etherType == 0x0800)
+ {
+ ipv = zmw_tx_buf_readb(dev, buf, ZM_80211_FRAME_IP_OFFSET) >> 4;
+ if (ipv == 0x4) //IPv4
+ {
+ tos = zmw_tx_buf_readb(dev, buf, ZM_80211_FRAME_IP_OFFSET + 1);
+ *up = (tos >> 5);
+ *fragOff = zmw_tx_buf_readh(dev, buf, ZM_80211_FRAME_IP_OFFSET + 6);
+ }
+ /* TODO : handle VLAN tag and IPv6 packet */
+ }
+ }
+ return;
+}
+
+#ifdef ZM_ENABLE_NATIVE_WIFI
+u16_t zfTxGenWlanSnap(zdev_t* dev, zbuf_t* buf, u16_t* snap, u16_t* snaplen)
+{
+ snap[0] = zmw_buf_readh(dev, buf, ZM_80211_FRAME_HEADER_LEN + 0);
+ snap[1] = zmw_buf_readh(dev, buf, ZM_80211_FRAME_HEADER_LEN + 2);
+ snap[2] = zmw_buf_readh(dev, buf, ZM_80211_FRAME_HEADER_LEN + 4);
+ *snaplen = 6;
+
+ return ZM_80211_FRAME_HEADER_LEN + *snaplen;
+}
+#else
+u16_t zfTxGenWlanSnap(zdev_t* dev, zbuf_t* buf, u16_t* snap, u16_t* snaplen)
+{
+ u16_t removed;
+ u16_t etherType;
+ u16_t len;
+
+ len = zfwBufGetSize(dev, buf);
+ if (len < 14) //Minimum Ethernet packet size, 14(Ether header)
+ {
+ /* TODO : Assert? */
+ *snaplen = 0;
+ return 0;
+ }
+
+ /* Generate RFC1042 header */
+ etherType = (((u16_t)zmw_tx_buf_readb(dev, buf, 12))<<8)
+ + zmw_tx_buf_readb(dev, buf, 13);
+
+ //zm_debug_msg2("ethernet type or length = ", etherType);
+
+ if (etherType > 1500)
+ {
+ /* ETHERNET format */
+ removed = 12;
+ snap[0] = 0xaaaa;
+ snap[1] = 0x0003;
+ if ((etherType ==0x8137) || (etherType == 0x80f3))
+ {
+ /* Bridge Tunnel */
+ snap[2] = 0xF800;
+ }
+ else
+ {
+ /* RFC 1042 */
+ snap[2] = 0x0000;
+ }
+ *snaplen = 6;
+
+ if ( etherType == 0x888E )
+ {
+ zfShowTxEAPOL(dev, buf, 14);
+ }
+ }
+ else
+ {
+ /* 802.3 format */
+ removed = 14;
+ *snaplen = 0;
+ }
+
+ return removed;
+}
+#endif
+
+u8_t zfIsVtxqEmpty(zdev_t* dev)
+{
+ u8_t isEmpty = TRUE;
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (wd->vmmqHead != wd->vmmqTail)
+ {
+ isEmpty = FALSE;
+ goto check_done;
+ }
+
+ for(i=0; i < 4; i++)
+ {
+ if (wd->vtxqHead[i] != wd->vtxqTail[i])
+ {
+ isEmpty = FALSE;
+ goto check_done;
+ }
+ }
+
+check_done:
+ zmw_leave_critical_section(dev);
+ return isEmpty;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfPutVtxq */
+/* Put Tx buffer to virtual TxQ */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : Tx buffer pointer */
+/* */
+/* OUTPUTS */
+/* ZM_SUCCESS or error code */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+u16_t zfPutVtxq(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t ac;
+ u8_t up;
+ u16_t fragOff;
+#ifdef ZM_AGG_TALLY
+ struct aggTally *agg_tal;
+#endif
+#ifdef ZM_ENABLE_AGGREGATION
+ #ifndef ZM_BYPASS_AGGR_SCHEDULING
+ u16_t ret;
+ u16_t tid;
+ #endif
+#endif
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zfTxGetIpTosAndFrag(dev, buf, &up, &fragOff);
+
+ if ( wd->zfcbClassifyTxPacket != NULL )
+ {
+ ac = wd->zfcbClassifyTxPacket(dev, buf);
+ }
+ else
+ {
+ ac = zcUpToAc[up&0x7] & 0x3;
+ }
+
+ /*
+ * add by honda
+ * main A-MPDU aggregation function
+ */
+#ifdef ZM_AGG_TALLY
+ agg_tal = &wd->agg_tal;
+ agg_tal->got_packets_sum++;
+
+#endif
+
+#ifdef ZM_ENABLE_AGGREGATION
+ #ifndef ZM_BYPASS_AGGR_SCHEDULING
+ tid = up&0x7;
+ if(wd->enableAggregation==0)
+ {
+ if( (wd->wlanMode == ZM_MODE_AP) ||
+ (wd->wlanMode == ZM_MODE_INFRASTRUCTURE && wd->sta.EnableHT) ||
+ (wd->wlanMode == ZM_MODE_PSEUDO) ) {
+ // (infrastructure_mode && connect_to_11n_ap) || (ap_mode && is_11n_ap)
+ //ret = zfAggPutVtxq(dev, buf);
+
+
+ ret = zfAggTx(dev, buf, tid);
+ if (ZM_SUCCESS == ret)
+ {
+ //zfwBufFree(dev, buf, ZM_SUCCESS);
+
+ return ZM_SUCCESS;
+ }
+ if (ZM_ERR_EXCEED_PRIORITY_THRESHOLD == ret)
+ {
+ wd->commTally.txQosDropCount[ac]++;
+ zfwBufFree(dev, buf, ZM_SUCCESS);
+
+ zm_msg1_tx(ZM_LV_1, "Packet discarded, VTXQ full, ac=", ac);
+
+ return ZM_ERR_EXCEED_PRIORITY_THRESHOLD;
+ }
+ if (ZM_ERR_TX_BUFFER_UNAVAILABLE == ret)
+ {
+ /*
+ * do nothing
+ * continue following procession, put into VTXQ
+ * return ZM_SUCCESS;
+ */
+ }
+ }
+ }
+ #endif
+#endif
+ /*
+ * end of add by honda
+ */
+
+ /* First Ip frag */
+ if ((fragOff & 0xff3f) == 0x0020)
+ {
+ /* Don't let ip frag in if VTXQ unable to hold */
+ /* whole ip frag burst(assume 20 frag) */
+ zmw_enter_critical_section(dev);
+ if (((wd->vtxqHead[ac] - wd->vtxqTail[ac])& ZM_VTXQ_SIZE_MASK)
+ > (ZM_VTXQ_SIZE-20))
+ {
+ wd->qosDropIpFrag[ac] = 1;
+ }
+ else
+ {
+ wd->qosDropIpFrag[ac] = 0;
+ }
+ zmw_leave_critical_section(dev);
+
+ if (wd->qosDropIpFrag[ac] == 1)
+ {
+ //zm_debug_msg2("vtQ full, drop buf = ", buf);
+ wd->commTally.txQosDropCount[ac]++;
+ zfwBufFree(dev, buf, ZM_SUCCESS);
+ zm_msg1_tx(ZM_LV_1, "Packet discarded, first ip frag, ac=", ac);
+ //VTXQ[] can not hold whold ip frag burst(assume 20 frags)
+ return ZM_ERR_EXCEED_PRIORITY_THRESHOLD;
+ }
+ }
+ else if ((fragOff & 0xff3f) == 0)
+ {
+ wd->qosDropIpFrag[ac] = 0;
+ }
+
+ if (((fragOff &= 0xff1f) != 0) && (wd->qosDropIpFrag[ac] == 1))
+ {
+ wd->commTally.txQosDropCount[ac]++;
+ zfwBufFree(dev, buf, ZM_SUCCESS);
+ zm_msg1_tx(ZM_LV_1, "Packet discarded, ip frag, ac=", ac);
+ //Discard following ip frags
+ return ZM_ERR_EXCEED_PRIORITY_THRESHOLD;
+ }
+
+ zmw_enter_critical_section(dev);
+ if (((wd->vtxqHead[ac] + 1) & ZM_VTXQ_SIZE_MASK) != wd->vtxqTail[ac])
+ {
+ wd->vtxq[ac][wd->vtxqHead[ac]] = buf;
+ wd->vtxqHead[ac] = ((wd->vtxqHead[ac] + 1) & ZM_VTXQ_SIZE_MASK);
+ zmw_leave_critical_section(dev);
+ return ZM_SUCCESS;
+ }
+ else
+ {
+ zmw_leave_critical_section(dev);
+
+ wd->commTally.txQosDropCount[ac]++;
+ zfwBufFree(dev, buf, ZM_SUCCESS);
+ zm_msg1_tx(ZM_LV_1, "Packet discarded, VTXQ full, ac=", ac);
+ return ZM_ERR_EXCEED_PRIORITY_THRESHOLD; //VTXQ[] Full
+ }
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfGetVtxq */
+/* Get Tx buffer from virtual TxQ */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* Tx buffer pointer */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+zbuf_t* zfGetVtxq(zdev_t* dev, u8_t ac)
+{
+ zbuf_t* buf;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ ac &= 0x3;
+ zmw_enter_critical_section(dev);
+ if (wd->vtxqHead[ac] != wd->vtxqTail[ac])
+ {
+ buf = wd->vtxq[ac][wd->vtxqTail[ac]];
+ wd->vtxqTail[ac] = ((wd->vtxqTail[ac] + 1) & ZM_VTXQ_SIZE_MASK);
+ zmw_leave_critical_section(dev);
+ return buf;
+ }
+ else
+ {
+ zmw_leave_critical_section(dev);
+ return 0; //VTXQ[] empty
+ }
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfPutVmmq */
+/* Put Tx buffer to virtual MmQ */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : Tx buffer pointer */
+/* */
+/* OUTPUTS */
+/* ZM_SUCCESS or error code */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.12 */
+/* */
+/************************************************************************/
+u16_t zfPutVmmq(zdev_t* dev, zbuf_t* buf)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if (((wd->vmmqHead + 1) & ZM_VMMQ_SIZE_MASK) != wd->vmmqTail)
+ {
+ wd->vmmq[wd->vmmqHead] = buf;
+ wd->vmmqHead = ((wd->vmmqHead + 1) & ZM_VMMQ_SIZE_MASK);
+ zmw_leave_critical_section(dev);
+ return ZM_SUCCESS;
+ }
+ else
+ {
+ zmw_leave_critical_section(dev);
+
+ zfwBufFree(dev, buf, ZM_SUCCESS);
+ zm_msg0_mm(ZM_LV_0, "Packet discarded, VMmQ full");
+ return ZM_ERR_VMMQ_FULL; //VTXQ[] Full
+ }
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfGetVmmq */
+/* Get Tx buffer from virtual MmQ */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* Tx buffer pointer */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.12 */
+/* */
+/************************************************************************/
+zbuf_t* zfGetVmmq(zdev_t* dev)
+{
+ zbuf_t* buf;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if (wd->vmmqHead != wd->vmmqTail)
+ {
+ buf = wd->vmmq[wd->vmmqTail];
+ wd->vmmqTail = ((wd->vmmqTail + 1) & ZM_VMMQ_SIZE_MASK);
+ zmw_leave_critical_section(dev);
+ return buf;
+ }
+ else
+ {
+ zmw_leave_critical_section(dev);
+ return 0; //VTXQ[] empty
+ }
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfPushVtxq */
+/* Service Virtual TxQ (weighted round robin) */
+/* Get Tx buffer form virtual TxQ and put to hardware TxD queue */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+void zfPushVtxq(zdev_t* dev)
+{
+ zbuf_t* buf;
+ u16_t i;
+ u16_t txed;
+ u32_t freeTxd;
+ u16_t err;
+ u16_t skipFlag = 0;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+
+
+ //zm_debug_msg1("zfHpGetFreeTxdCount = ", zfHpGetFreeTxdCount(dev));
+
+ if (wd->halState == ZM_HAL_STATE_INIT)
+ {
+ if (!wd->modeMDKEnable)
+ {
+ zm_debug_msg0("HAL is not ready for Tx");
+ }
+ return;
+ }
+ else if (wd->sta.DFSDisableTx)
+ {
+ zm_debug_msg0("return because 802.11h DFS Disable Tx");
+ return;
+ }
+ else if (wd->sta.flagFreqChanging != 0)
+ {
+ //Hold until RF frequency changed
+ return;
+ }
+ else if (( wd->sta.flagKeyChanging ) && ( wd->wlanMode != ZM_MODE_AP ))
+ {
+ return;
+ }
+#ifdef ZM_ENABLE_POWER_SAVE
+ else if ( zfPowerSavingMgrIsSleeping(dev) )
+ {
+ //zm_debug_msg0("Packets queued since the MAC is in power-saving mode\n");
+ return;
+ }
+#endif
+
+ zmw_enter_critical_section(dev);
+ if (wd->vtxqPushing != 0)
+ {
+ skipFlag = 1;
+ }
+ else
+ {
+ wd->vtxqPushing = 1;
+ }
+ zmw_leave_critical_section(dev);
+
+ if (skipFlag == 1)
+ {
+ return;
+ }
+
+ while (1)
+ {
+ txed = 0;
+
+ /* 2006.12.20, Serve Management queue */
+ while( zfHpGetFreeTxdCount(dev) > 0 )
+ {
+ if ((buf = zfGetVmmq(dev)) != 0)
+ {
+ txed = 1;
+ //zm_debug_msg2("send buf = ", buf);
+ if ((err = zfHpSend(dev, NULL, 0, NULL, 0, NULL, 0, buf, 0,
+ ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS)
+ {
+ zfwBufFree(dev, buf, 0);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ if ((wd->sta.bScheduleScan) || ((wd->sta.bChannelScan == TRUE) && (zfStaIsConnected(dev))))
+ {
+ //Hold until Scan Stop
+ wd->vtxqPushing = 0;
+ return;
+ }
+
+#ifdef ZM_ENABLE_AGGREGATION
+ #ifndef ZM_BYPASS_AGGR_SCHEDULING
+ if( (wd->wlanMode == ZM_MODE_AP) ||
+ (wd->wlanMode == ZM_MODE_INFRASTRUCTURE && wd->sta.EnableHT) ||
+ (wd->wlanMode == ZM_MODE_PSEUDO) ) {
+
+ zfAggTxScheduler(dev, 0);
+
+ if (txed == 0) {
+ wd->vtxqPushing = 0;
+ return;
+ }
+ else {
+ continue;
+ }
+ }
+ #endif
+#endif
+
+ /* Service VTxQ[3] */
+ for (i=0; i<4; i++)
+ {
+ if ((freeTxd = zfHpGetFreeTxdCount(dev)) >= 3)
+ {
+ if ((buf = zfGetVtxq(dev, 3)) != 0)
+ {
+ txed = 1;
+ //zm_debug_msg2("send buf = ", buf);
+ zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ ZM_PERFORMANCE_TX_MPDU(dev, wd->tick);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* Service VTxQ[2] */
+ for (i=0; i<3; i++)
+ {
+ if ((freeTxd = zfHpGetFreeTxdCount(dev)) >= (zfHpGetMaxTxdCount(dev)*1/4))
+ {
+ if ((buf = zfGetVtxq(dev, 2)) != 0)
+ {
+ txed = 1;
+ zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ ZM_PERFORMANCE_TX_MPDU(dev, wd->tick);
+ }
+ if (wd->sta.ac0PriorityHigherThanAc2 == 1)
+ {
+ if ((buf = zfGetVtxq(dev, 0)) != 0)
+ {
+ txed = 1;
+ zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ ZM_PERFORMANCE_TX_MPDU(dev, wd->tick);
+ }
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* Service VTxQ[0] */
+ for (i=0; i<2; i++)
+ {
+ if ((freeTxd = zfHpGetFreeTxdCount(dev)) >= (zfHpGetMaxTxdCount(dev)*2/4))
+ {
+ if ((buf = zfGetVtxq(dev, 0)) != 0)
+ {
+ txed = 1;
+ zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ ZM_PERFORMANCE_TX_MPDU(dev, wd->tick);
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ }
+
+ /* Service VTxQ[1] */
+ if ((freeTxd = zfHpGetFreeTxdCount(dev)) >= (zfHpGetMaxTxdCount(dev)*3/4))
+ {
+ if ((buf = zfGetVtxq(dev, 1)) != 0)
+ {
+ txed = 1;
+ zfTxSendEth(dev, buf, 0, ZM_EXTERNAL_ALLOC_BUF, 0);
+ ZM_PERFORMANCE_TX_MPDU(dev, wd->tick);
+ }
+ }
+
+ /* All VTxQs are either empty or exceed their threshold */
+ if (txed == 0)
+ {
+ wd->vtxqPushing = 0;
+ return;
+ }
+ } //while (1)
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfFlushVtxq */
+/* Flush Virtual TxQ and MmQ */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.1 */
+/* */
+/************************************************************************/
+void zfFlushVtxq(zdev_t* dev)
+{
+ zbuf_t* buf;
+ u8_t i;
+ zmw_get_wlan_dev(dev);
+
+ /* Flush MmQ */
+ while ((buf = zfGetVmmq(dev)) != 0)
+ {
+ zfwBufFree(dev, buf, 0);
+ zm_debug_msg0("zfFlushVtxq: [Vmmq]");
+ wd->queueFlushed |= 0x10;
+ }
+
+ /* Flush VTxQ */
+ for (i=0; i<4; i++)
+ {
+ while ((buf = zfGetVtxq(dev, i)) != 0)
+ {
+ zfwBufFree(dev, buf, 0);
+ zm_debug_msg1("zfFlushVtxq: [zfGetVtxq]- ", i);
+ wd->queueFlushed |= (1<<i);
+ }
+ }
+}
+
+void zf80211FrameSend(zdev_t* dev, zbuf_t* buf, u16_t* header, u16_t snapLen,
+ u16_t* da, u16_t* sa, u8_t up, u16_t headerLen, u16_t* snap,
+ u16_t* tail, u16_t tailLen, u16_t offset, u16_t bufType,
+ u8_t ac, u8_t keyIdx)
+{
+ u16_t err;
+ u16_t fragLen;
+
+ zmw_get_wlan_dev(dev);
+
+ fragLen = zfwBufGetSize(dev, buf);
+ if ((da[0]&0x1) == 0)
+ {
+ wd->commTally.txUnicastFrm++;
+ wd->commTally.txUnicastOctets += (fragLen+snapLen);
+ }
+ else if (da[0] == 0xffff)
+ {
+ wd->commTally.txBroadcastFrm++;
+ wd->commTally.txBroadcastOctets += (fragLen+snapLen);
+ }
+ else
+ {
+ wd->commTally.txMulticastFrm++;
+ wd->commTally.txMulticastOctets += (fragLen+snapLen);
+ }
+ wd->ledStruct.txTraffic++;
+
+ if ((err = zfHpSend(dev, header, headerLen, snap, snapLen,
+ tail, tailLen, buf, offset,
+ bufType, ac, keyIdx)) != ZM_SUCCESS)
+ {
+ if (bufType == ZM_EXTERNAL_ALLOC_BUF)
+ {
+ zfwBufFree(dev, buf, err);
+ }
+ else if (bufType == ZM_INTERNAL_ALLOC_BUF)
+ {
+ zfwBufFree(dev, buf, 0);
+ }
+ else
+ {
+ zm_assert(0);
+ }
+ }
+}
+
+void zfCheckIsRIFSFrame(zdev_t* dev, zbuf_t* buf, u16_t frameSubtype)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* #2 Record the sequence number to determine whether the unicast frame is separated by RIFS or not */
+ if (frameSubtype & 0x80)
+ { //QoS data frame
+ u16_t sequenceNum;
+ u16_t qosControlField;
+
+ sequenceNum = ( zmw_buf_readh(dev, buf, 22) >> 4 ); // Discard fragment number !
+ qosControlField = zmw_buf_readh(dev, buf, 24); // Don't consider WDS (Wireless Distribution System)
+ //DbgPrint("The QoS Control Field : %d", qosControlField);
+ //DbgPrint("The RIFS Count : %d", wd->sta.rifsCount);
+
+ if( qosControlField & ZM_BIT_5 )
+ {// ACK policy is "No ACK"
+ /* RIFS-Like frame */
+ wd->sta.rifsLikeFrameSequence[wd->sta.rifsLikeFrameCnt] = sequenceNum;
+
+ if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTING )
+ {
+ if( wd->sta.rifsLikeFrameSequence[2] != 0 )
+ {// RIFS-like Pattern collected
+ if( ( wd->sta.rifsLikeFrameSequence[2] - wd->sta.rifsLikeFrameSequence[1] == 2 ) &&
+ ( wd->sta.rifsLikeFrameSequence[1] - wd->sta.rifsLikeFrameSequence[0] == 2 ) )
+ {
+ /* RIFS pattern matched */
+
+ /* #3 Enable RIFS function if the RIFS pattern matched */
+ zfHpEnableRifs(dev, ((wd->sta.currentFrequency<3000)?1:0), wd->sta.EnableHT, wd->sta.HT2040);
+
+ // Set RIFS timer
+ wd->sta.rifsTimer = wd->tick;
+
+ wd->sta.rifsCount++;
+
+ // Set state to be Detected
+ wd->sta.rifsState = ZM_RIFS_STATE_DETECTED;
+ }
+ }
+ }
+ else
+ {// state = Detected
+ // Reset RIFS timer
+ if( (wd->tick - wd->sta.rifsTimer) < ZM_RIFS_TIMER_TIMEOUT )
+ wd->sta.rifsTimer = wd->tick;
+ }
+
+ //DbgPrint("SN1 = %d, SN2 = %d, SN3 = %d\n", wd->sta.rifsLikeFrameSequence[0],
+ // wd->sta.rifsLikeFrameSequence[1],
+ // wd->sta.rifsLikeFrameSequence[2]);
+
+ // Update RIFS-like sequence number
+ if( wd->sta.rifsLikeFrameSequence[2] != 0 )
+ {
+ wd->sta.rifsLikeFrameSequence[0] = wd->sta.rifsLikeFrameSequence[1];
+ wd->sta.rifsLikeFrameSequence[1] = wd->sta.rifsLikeFrameSequence[2];
+ wd->sta.rifsLikeFrameSequence[2] = 0;
+ }
+
+ // Only record three adjacent frame
+ if( wd->sta.rifsLikeFrameCnt < 2 )
+ wd->sta.rifsLikeFrameCnt++;
+ }
+ }
+
+ /* #4 Disable RIFS function if the timer TIMEOUT */
+ if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTED )
+ {
+ if( ( wd->tick - wd->sta.rifsTimer ) > ZM_RIFS_TIMER_TIMEOUT )
+ {// TIMEOUT
+ // Disable RIFS
+ zfHpDisableRifs(dev);
+
+ // Reset RIFS-like sequence number FIFO
+ wd->sta.rifsLikeFrameSequence[0] = 0;
+ wd->sta.rifsLikeFrameSequence[1] = 0;
+ wd->sta.rifsLikeFrameSequence[2] = 0;
+ wd->sta.rifsLikeFrameCnt = 0;
+
+ // Set state to be Detecting
+ wd->sta.rifsState = ZM_RIFS_STATE_DETECTING;
+ }
+ }
+}
diff --git a/drivers/staging/otus/80211core/cwep.c b/drivers/staging/otus/80211core/cwep.c
new file mode 100644
index 000000000000..ec31bb1ac283
--- /dev/null
+++ b/drivers/staging/otus/80211core/cwep.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : cwep.c */
+/* */
+/* Abstract */
+/* This module contains Tx and Rx functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+
+u32_t crc32_tab[] =
+{
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+void zfWEPEncrypt(zdev_t *dev, zbuf_t *buf, u8_t *snap, u16_t snapLen, u16_t offset, u8_t keyLen, u8_t* WepKey, u8_t *iv)
+{
+ u8_t S[256],S2[256];
+ u16_t ui;
+ u16_t i;
+ u16_t j;
+ u8_t temp;
+ u8_t K;
+ u32_t ltemp;
+ u16_t len;
+ u32_t icv;
+ u8_t key[32];
+
+ key[0] = iv[0];
+ key[1] = iv[1];
+ key[2] = iv[2];
+
+ /* Append Wep Key after IV */
+ zfMemoryCopy(&key[3], WepKey, keyLen);
+
+ keyLen += 3;
+
+ for(i = 0; i < 256; i++)
+ {
+ S[i] = (u8_t)i;
+ S2[i] = key[i&(keyLen-1)];
+ }
+
+ j = 0;
+ for(i = 0; i < 256; i++)
+ {
+ j = (j + S[i] + S2[i]) ;
+ j&=255 ;
+
+ // Swap S[i] and S[j]
+ temp = S[i];
+ S[i] = S[j];
+ S[j] = temp;
+ }
+
+ i = j = 0;
+ icv = -1;
+
+ /* For Snap Header */
+ for (ui = 0; ui < snapLen; ui++)
+ {
+ u8_t In;
+
+ i++;
+ i &= 255;
+ j += S[i];
+ j &= 255;
+
+ // Swap S[i] and S[j]
+ temp = S[i];
+ S[i] = S[j];
+ S[j] = temp;
+// temp = (S[i] + temp) & 255;
+ temp += S[i];
+ temp &=255;
+ K = S[temp]; // Key used to Xor with input data
+
+ In = snap[ui];
+ icv = (icv>>8) ^ crc32_tab[(icv^In)&0xff];
+
+ snap[ui] = In ^ K;
+ //zmw_tx_buf_writeb(dev, buf, ui, In ^ K);
+ }
+
+ len = zfwBufGetSize(dev, buf);
+
+ for (ui = offset; ui < len; ui++)
+ {
+ u8_t In;
+
+ i++;
+ i &= 255;
+ j += S[i];
+ j &= 255;
+
+ // Swap S[i] and S[j]
+ temp = S[i];
+ S[i] = S[j];
+ S[j] = temp;
+// temp = (S[i] + temp) & 255;
+ temp += S[i];
+ temp &=255;
+ K = S[temp]; // Key used to Xor with input data
+
+ In = zmw_tx_buf_readb(dev, buf, ui);
+ icv = (icv>>8) ^ crc32_tab[(icv^In)&0xff];
+
+ zmw_tx_buf_writeb(dev, buf, ui, In ^ K);
+ } //End of for (ui = 0; ui < Num_Bytes; ui++)
+
+ icv = ~(icv);
+ ltemp = (u32_t) icv;
+
+ for (ui = 0; ui < 4; ui++)
+ {
+ i ++;
+ i &= 255;
+ j += S[i];
+ j &= 255;
+
+ // Swap S[i] and S[j]
+ temp = S[i];
+ S[i] = S[j];
+ S[j] = temp;
+ temp += S[i];
+ temp &= 255;
+ K = S[temp]; // Key used to Xor with input data
+
+ //*Out++ = (u8_t)(ltemp ^ K)&0xff;
+ zmw_tx_buf_writeb(dev, buf, len+ui, (u8_t)(ltemp ^ K)&0xff);
+ ltemp >>= 8;
+ }
+
+ zfwBufSetSize(dev, buf, len+4);
+}
+
+u16_t zfWEPDecrypt(zdev_t *dev, zbuf_t *buf, u16_t offset, u8_t keyLen, u8_t* WepKey, u8_t *iv)
+{
+ u8_t S[256];
+ u8_t S2[256];
+ u16_t ui;
+ u16_t i;
+ u16_t j;
+ u32_t icv_tmp;
+ u32_t *icv;
+ u32_t rxbuf_icv;
+ u8_t temp;
+ u8_t K;
+ u16_t len;
+ u8_t key[32];
+
+ /* Retrieve IV */
+ key[0] = iv[0];
+ key[1] = iv[1];
+ key[2] = iv[2];
+
+ /* Append Wep Key after IV */
+ zfMemoryCopy(&key[3], WepKey, keyLen);
+
+ keyLen += 3;
+
+ for(i = 0; i < 256; i++)
+ {
+ S[i] = (u8_t)i;
+ S2[i] = key[i&(keyLen-1)];
+ }
+
+ j = 0;
+ for(i = 0; i < 256; i++)
+ {
+ j = (j + S[i] + S2[i]);
+ j&=255 ;
+
+ // Swap S[i] and S[j]
+ temp = S[i];
+ S[i] = S[j];
+ S[j] = temp;
+ }
+
+ i = j = 0;
+
+ len = zfwBufGetSize(dev, buf);
+
+ for (ui = offset; ui < len; ui++)
+ {
+ u8_t In;
+
+ i++;
+ i &= 255;
+ j += S[i];
+ j &= 255;
+
+ // Swap S[i] and S[j]
+ temp = S[i];
+ S[i] = S[j];
+ S[j] = temp;
+// temp = (S[i] + temp) & 255;
+ temp += S[i];
+ temp &=255;
+ K = S[temp]; // Key used to Xor with input data
+
+ In = zmw_rx_buf_readb(dev, buf, ui);
+
+ zmw_rx_buf_writeb(dev, buf, ui, In ^ K);
+ } //End of for (ui = 0; ui < Num_Bytes; ui++)
+
+ icv = &icv_tmp;
+ *icv = -1;
+
+ for (ui = offset; ui < len - 4; ui++)
+ {
+ u8_t In;
+
+ In = zmw_rx_buf_readb(dev, buf, ui);
+ *icv = (*icv>>8) ^ crc32_tab[(*icv^In)&0xff];
+ }
+
+ *icv = ~*icv;
+
+ rxbuf_icv = (zmw_rx_buf_readb(dev, buf, len-4) |
+ zmw_rx_buf_readb(dev, buf, len-3) << 8 |
+ zmw_rx_buf_readb(dev, buf, len-2) << 16 |
+ zmw_rx_buf_readb(dev, buf, len-1) << 24);
+
+ if (*icv != rxbuf_icv)
+ {
+ return ZM_ICV_FAILURE;
+ }
+
+ return ZM_ICV_SUCCESS;
+}
diff --git a/drivers/staging/otus/80211core/cwm.c b/drivers/staging/otus/80211core/cwm.c
new file mode 100644
index 000000000000..80f1141bf910
--- /dev/null
+++ b/drivers/staging/otus/80211core/cwm.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : cwm.c */
+/* */
+/* Abstract */
+/* This module contains channel width related functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+
+#include "cprecomp.h"
+
+
+
+void zfCwmInit(zdev_t* dev) {
+ //u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ switch (wd->wlanMode) {
+ case ZM_MODE_AP:
+ wd->cwm.cw_mode = CWM_MODE2040;
+ wd->cwm.cw_width = CWM_WIDTH40;
+ wd->cwm.cw_enable = 1;
+ break;
+ case ZM_MODE_INFRASTRUCTURE:
+ case ZM_MODE_PSEUDO:
+ case ZM_MODE_IBSS:
+ default:
+ wd->cwm.cw_mode = CWM_MODE2040;
+ wd->cwm.cw_width = CWM_WIDTH20;
+ wd->cwm.cw_enable = 1;
+ break;
+ }
+}
+
+
+void zfCoreCwmBusy(zdev_t* dev, u16_t busy)
+{
+
+ zmw_get_wlan_dev(dev);
+
+ zm_msg1_mm(ZM_LV_0, "CwmBusy=", busy);
+
+ if(wd->cwm.cw_mode == CWM_MODE20) {
+ wd->cwm.cw_width = CWM_WIDTH20;
+ return;
+ }
+
+ if(wd->cwm.cw_mode == CWM_MODE40) {
+ wd->cwm.cw_width = CWM_WIDTH40;
+ return;
+ }
+
+ if (busy) {
+ wd->cwm.cw_width = CWM_WIDTH20;
+ return;
+ }
+
+
+ if((wd->wlanMode == ZM_MODE_INFRASTRUCTURE || wd->wlanMode == ZM_MODE_PSEUDO ||
+ wd->wlanMode == ZM_MODE_IBSS)) {
+ if (wd->sta.ie.HtCap.HtCapInfo && HTCAP_SupChannelWidthSet != 0 &&
+ wd->sta.ie.HtInfo.ChannelInfo && ExtHtCap_RecomTxWidthSet != 0 &&
+ (wd->sta.ie.HtInfo.ChannelInfo && ExtHtCap_ExtChannelOffsetAbove) == 1) {
+
+ wd->cwm.cw_width = CWM_WIDTH40;
+ }
+ else {
+ wd->cwm.cw_width = CWM_WIDTH20;
+ }
+
+ return;
+ }
+
+ if(wd->wlanMode == ZM_MODE_AP) {
+ wd->cwm.cw_width = CWM_WIDTH40;
+ }
+
+}
+
+
+
+
+u16_t zfCwmIsExtChanBusy(u32_t ctlBusy, u32_t extBusy)
+{
+ u32_t busy; /* percentage */
+ u32_t cycleTime, ctlClear;
+
+ cycleTime = 1280000; //1.28 seconds
+
+ if (cycleTime > ctlBusy) {
+ ctlClear = cycleTime - ctlBusy;
+ }
+ else
+ {
+ ctlClear = 0;
+ }
+
+ /* Compute ratio of extension channel busy to control channel clear
+ * as an approximation to extension channel cleanliness.
+ *
+ * According to the hardware folks, ext rxclear is undefined
+ * if the ctrl rxclear is de-asserted (i.e. busy)
+ */
+ if (ctlClear) {
+ busy = (extBusy * 100) / ctlClear;
+ } else {
+ busy = 0;
+ }
+ if (busy > ATH_CWM_EXTCH_BUSY_THRESHOLD) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/drivers/staging/otus/80211core/cwm.h b/drivers/staging/otus/80211core/cwm.h
new file mode 100644
index 000000000000..40c39fad5f44
--- /dev/null
+++ b/drivers/staging/otus/80211core/cwm.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : cwm.h */
+/* */
+/* Abstract */
+/* This module contains channel width relatived functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/****************************************************************************/
+/*Revision History: */
+/* Who When What */
+/* -------- -------- ----------------------------------------------*/
+/* */
+/* Honda 3-19-07 created */
+/* */
+/****************************************************************************/
+
+#ifndef _CWM_H
+#define _CWM_H
+
+#define ATH_CWM_EXTCH_BUSY_THRESHOLD 30 /* Extension Channel Busy Threshold (0-100%) */
+
+void zfCwmInit(zdev_t* dev);
+void zfCoreCwmBusy(zdev_t* dev, u16_t busy);
+u16_t zfCwmIsExtChanBusy(u32_t ctlBusy, u32_t extBusy);
+
+
+
+#endif /* #ifndef _CWM_H */
diff --git a/drivers/staging/otus/80211core/freqctrl.c b/drivers/staging/otus/80211core/freqctrl.c
new file mode 100644
index 000000000000..bab0df08d826
--- /dev/null
+++ b/drivers/staging/otus/80211core/freqctrl.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+
+/* zfAddFreqChangeReq should be called inside the critical section */
+static void zfAddFreqChangeReq(zdev_t* dev, u16_t frequency, u8_t bw40,
+ u8_t extOffset, zfpFreqChangeCompleteCb cb)
+{
+ zmw_get_wlan_dev(dev);
+
+//printk("zfAddFreqChangeReq freqReqQueueTail%d\n", wd->freqCtrl.freqReqQueueTail);
+ wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueTail] = frequency;
+ wd->freqCtrl.freqReqBw40[wd->freqCtrl.freqReqQueueTail] = bw40;
+ wd->freqCtrl.freqReqExtOffset[wd->freqCtrl.freqReqQueueTail] = extOffset;
+ wd->freqCtrl.freqChangeCompCb[wd->freqCtrl.freqReqQueueTail] = cb;
+ wd->freqCtrl.freqReqQueueTail++;
+ if ( wd->freqCtrl.freqReqQueueTail >= ZM_MAX_FREQ_REQ_QUEUE )
+ {
+ wd->freqCtrl.freqReqQueueTail = 0;
+ }
+}
+
+void zfCoreSetFrequencyV2(zdev_t* dev, u16_t frequency, zfpFreqChangeCompleteCb cb)
+{
+ zfCoreSetFrequencyEx(dev, frequency, 0, 0, cb);
+}
+
+void zfCoreSetFrequencyExV2(zdev_t* dev, u16_t frequency, u8_t bw40,
+ u8_t extOffset, zfpFreqChangeCompleteCb cb, u8_t forceSetFreq)
+{
+ u8_t setFreqImmed = 0;
+ u8_t initRF = 0;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zm_msg1_scan(ZM_LV_1, "Freq=", frequency);
+
+ zmw_enter_critical_section(dev);
+ if ((wd->sta.currentFrequency == frequency)
+ && (wd->sta.currentBw40 == bw40)
+ && (wd->sta.currentExtOffset == extOffset))
+ {
+ if ( forceSetFreq == 0 && wd->sta.flagFreqChanging == 0 )
+ {
+ goto done;
+ }
+ }
+#ifdef ZM_FB50
+ /*if(frequency!=2437) {
+ zmw_leave_critical_section(dev);
+ return;
+ }*/
+#endif
+
+ zfAddFreqChangeReq(dev, frequency, bw40, extOffset, cb);
+
+// zm_assert( wd->sta.flagFreqChanging == 0 );
+ //wd->sta.flagFreqChanging = 1;
+ if ( wd->sta.flagFreqChanging == 0 )
+ {
+ if ((wd->sta.currentBw40 != bw40) || (wd->sta.currentExtOffset != extOffset))
+ {
+ initRF = 1;
+ }
+ wd->sta.currentFrequency = frequency;
+ wd->sta.currentBw40 = bw40;
+ wd->sta.currentExtOffset = extOffset;
+ setFreqImmed = 1;
+ }
+ wd->sta.flagFreqChanging++;
+
+ zmw_leave_critical_section(dev);
+
+ if ( setFreqImmed )
+ {
+ //zfHpSetFrequency(dev, frequency, 0);
+ if ( forceSetFreq )
+ { // Cold reset to reset the frequency after scanning !
+ zm_debug_msg0("#6_1 20070917");
+ zm_debug_msg0("It is happen!!! No error message");
+ zfHpSetFrequencyEx(dev, frequency, bw40, extOffset, 2);
+ }
+ else
+ {
+ zfHpSetFrequencyEx(dev, frequency, bw40, extOffset, initRF);
+ }
+
+ if ( zfStaIsConnected(dev)
+ && (frequency == wd->frequency)) {
+ wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
+ }
+ }
+ return;
+
+done:
+ zmw_leave_critical_section(dev);
+
+ if ( cb != NULL )
+ {
+ cb(dev);
+ }
+ zfPushVtxq(dev);
+ return;
+}
+
+void zfCoreSetFrequencyEx(zdev_t* dev, u16_t frequency, u8_t bw40,
+ u8_t extOffset, zfpFreqChangeCompleteCb cb)
+{
+ zfCoreSetFrequencyExV2(dev, frequency, bw40, extOffset, cb, 0);
+}
+
+void zfCoreSetFrequency(zdev_t* dev, u16_t frequency)
+{
+ zfCoreSetFrequencyV2(dev, frequency, NULL);
+}
+
+/* zfRemoveFreqChangeReq SHOULD NOT be called inside the critical section */
+static void zfRemoveFreqChangeReq(zdev_t* dev)
+{
+ zfpFreqChangeCompleteCb cb = NULL;
+ u16_t frequency;
+ u8_t bw40;
+ u8_t extOffset;
+ u16_t compFreq = 0;
+ u8_t compBw40 = 0;
+ u8_t compExtOffset = 0;
+
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (wd->freqCtrl.freqReqQueueHead != wd->freqCtrl.freqReqQueueTail)
+ {
+ zm_msg1_scan(ZM_LV_1, "Freq=",
+ wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead]);
+ compFreq = wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead];
+ compBw40 = wd->freqCtrl.freqReqBw40[wd->freqCtrl.freqReqQueueHead];
+ compExtOffset = wd->freqCtrl.freqReqExtOffset[wd->freqCtrl.freqReqQueueHead];
+
+ wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead] = 0;
+ cb = wd->freqCtrl.freqChangeCompCb[wd->freqCtrl.freqReqQueueHead];
+ wd->freqCtrl.freqReqQueueHead++;
+ if ( wd->freqCtrl.freqReqQueueHead >= ZM_MAX_FREQ_REQ_QUEUE )
+ {
+ wd->freqCtrl.freqReqQueueHead = 0;
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+ if ( cb != NULL )
+ {
+ cb(dev);
+ }
+
+ zmw_enter_critical_section(dev);
+ while (wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead] != 0)
+ {
+ frequency = wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead];
+ bw40 = wd->freqCtrl.freqReqBw40[wd->freqCtrl.freqReqQueueHead];
+ extOffset=wd->freqCtrl.freqReqExtOffset[wd->freqCtrl.freqReqQueueHead];
+ if ((compFreq == frequency)
+ && (compBw40 == bw40)
+ && (compExtOffset == extOffset))
+ {
+ /* Duplicated frequency command */
+ zm_msg1_scan(ZM_LV_1, "Duplicated Freq=", frequency);
+
+ cb = wd->freqCtrl.freqChangeCompCb[wd->freqCtrl.freqReqQueueHead];
+ wd->freqCtrl.freqReqQueue[wd->freqCtrl.freqReqQueueHead] = 0;
+ wd->freqCtrl.freqReqQueueHead++;
+
+ if ( wd->freqCtrl.freqReqQueueHead >= ZM_MAX_FREQ_REQ_QUEUE )
+ {
+ wd->freqCtrl.freqReqQueueHead = 0;
+ }
+
+ if ( wd->sta.flagFreqChanging != 0 )
+ {
+ wd->sta.flagFreqChanging--;
+ }
+
+ zmw_leave_critical_section(dev);
+ if ( cb != NULL )
+ {
+ cb(dev);
+ }
+ zmw_enter_critical_section(dev);
+ }
+ else
+ {
+ u8_t initRF = 0;
+ if ((wd->sta.currentBw40 != bw40) || (wd->sta.currentExtOffset != extOffset))
+ {
+ initRF = 1;
+ }
+ wd->sta.currentFrequency = frequency;
+ wd->sta.currentBw40 = bw40;
+ wd->sta.currentExtOffset = extOffset;
+ zmw_leave_critical_section(dev);
+
+ zfHpSetFrequencyEx(dev, frequency, bw40, extOffset, initRF);
+ if ( zfStaIsConnected(dev)
+ && (frequency == wd->frequency)) {
+ wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev);
+ }
+
+ return;
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+ return;
+}
+
+void zfCoreSetFrequencyComplete(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zm_msg1_scan(ZM_LV_1, "flagFreqChanging=", wd->sta.flagFreqChanging);
+
+ zmw_enter_critical_section(dev);
+ //wd->sta.flagFreqChanging = 0;
+ if ( wd->sta.flagFreqChanging != 0 )
+ {
+ wd->sta.flagFreqChanging--;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ zfRemoveFreqChangeReq(dev);
+
+ zfPushVtxq(dev);
+ return;
+}
+
+void zfReSetCurrentFrequency(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg0("It is happen!!! No error message");
+
+ zfCoreSetFrequencyExV2(dev, wd->frequency, 0, 0, NULL, 1);
+}
diff --git a/drivers/staging/otus/80211core/ledmgr.c b/drivers/staging/otus/80211core/ledmgr.c
new file mode 100644
index 000000000000..1e104a928ca4
--- /dev/null
+++ b/drivers/staging/otus/80211core/ledmgr.c
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfLedCtrlType1 */
+/* Traditional single-LED state */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.6 */
+/* */
+/************************************************************************/
+// bit 15-12 : Toff for Scan state
+// 11-8 : Ton for Scan state
+// 7 : Reserved
+// 6 : mode
+//--------------------------------------
+// bit 6 = 0
+// 5-4 : Connect state
+// 00 => always off
+// 01 => always on
+// 10 => Idle off, acitve on
+// 11 => Idle on, active off
+//--------------------------------------
+// bit 6 = 1
+// 5-4 : freq
+// 00 => 1Hz
+// 01 => 0.5Hz
+// 10 => 0.25Hz
+// 11 => 0.125Hz
+//--------------------------------------
+// 3 : Power save state
+// 0 => always off in power save state
+// 1 => works as connect state
+// 2 : Disable state
+// 1 : Reserved
+// 0 : Power-on state
+void zfLedCtrlType1(zdev_t* dev)
+{
+ u16_t i;
+ u32_t ton, toff, tmp, period;
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<ZM_MAX_LED_NUMBER; i++)
+ {
+ if (zfStaIsConnected(dev) != TRUE)
+ {
+ //Scan state
+ ton = ((wd->ledStruct.ledMode[i] & 0xf00) >> 8) * 5;
+ toff = ((wd->ledStruct.ledMode[i] & 0xf000) >> 12) * 5;
+
+ if ((ton + toff) != 0)
+ {
+ tmp = wd->ledStruct.counter / (ton+toff);
+ tmp = wd->ledStruct.counter - (tmp * (ton+toff));
+ if (tmp < ton)
+ {
+ zfHpLedCtrl(dev, i, 1);
+ }
+ else
+ {
+ zfHpLedCtrl(dev, i, 0);
+ }
+ }
+ }
+ else
+ {
+ if ((zfPowerSavingMgrIsSleeping(dev)) && ((wd->ledStruct.ledMode[i] & 0x8) == 0))
+ {
+ zfHpLedCtrl(dev, i, 0);
+ }
+ else
+ {
+ //Connect state
+ if ((wd->ledStruct.ledMode[i] & 0x40) == 0)
+ {
+ if ((wd->ledStruct.counter & 1) == 0)
+ {
+ zfHpLedCtrl(dev, i, (wd->ledStruct.ledMode[i] & 0x10) >> 4);
+ }
+ else
+ {
+ if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
+ {
+ wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
+ if ((wd->ledStruct.ledMode[i] & 0x20) != 0)
+ {
+ zfHpLedCtrl(dev, i, ((wd->ledStruct.ledMode[i] & 0x10) >> 4)^1);
+ }
+ }
+ }
+ }// if ((wd->ledStruct.ledMode[i] & 0x40) == 0)
+ else
+ {
+ period = 5 * (1 << ((wd->ledStruct.ledMode[i] & 0x30) >> 4));
+ tmp = wd->ledStruct.counter / (period*2);
+ tmp = wd->ledStruct.counter - (tmp * (period*2));
+ if (tmp < period)
+ {
+ if ((wd->ledStruct.counter & 1) == 0)
+ {
+ zfHpLedCtrl(dev, i, 0);
+ }
+ else
+ {
+ if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
+ {
+ wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
+ zfHpLedCtrl(dev, i, 1);
+ }
+ }
+ }
+ else
+ {
+ if ((wd->ledStruct.counter & 1) == 0)
+ {
+ zfHpLedCtrl(dev, i, 1);
+ }
+ else
+ {
+ if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
+ {
+ wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
+ zfHpLedCtrl(dev, i, 0);
+ }
+ }
+ }
+ } //else, if ((wd->ledStruct.ledMode[i] & 0x40) == 0)
+ } //else, if (zfPowerSavingMgrIsSleeping(dev))
+ } //else : if (zfStaIsConnected(dev) != TRUE)
+ } //for (i=0; i<ZM_MAX_LED_NUMBER; i++)
+}
+
+/******************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfLedCtrlType2 */
+/* Customize for Netgear Dual-LED state ((bug#31292)) */
+/* */
+/* 1. Status: When dongle does not connect to 2.4G or 5G but in site */
+/* survey/association */
+/* LED status: Slow blinking, Amber then Blue per 500ms */
+/* 2. Status: Connection at 2.4G in site survey/association */
+/* LED status: Slow blinking, Amber/off per 500ms */
+/* 3. Status: Connection at 5G in site survey/association */
+/* LED status: Slow blinking, Blue/off per 500ms */
+/* 4. Status: When transfer the packet */
+/* LED status: Blink per packet, including TX and RX */
+/* 5. Status: When linking is established but no traffic */
+/* LED status: Always on */
+/* 6. Status: When linking is dropped but no re-connection */
+/* LED status: Always off */
+/* 7. Status: From one connection(2.4G or 5G) to change to another band */
+/* LED status: Amber/Blue =>Slow blinking, Amber then Blue per 500ms */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Shang-Chun Liu Atheros Communications, INC. 2007.11 */
+/* */
+/******************************************************************************/
+void zfLedCtrlType2_scan(zdev_t* dev);
+
+void zfLedCtrlType2(zdev_t* dev)
+{
+ u32_t ton, toff, tmp, period;
+ u16_t OperateLED;
+ zmw_get_wlan_dev(dev);
+
+ if (zfStaIsConnected(dev) != TRUE)
+ {
+ // Disconnect state
+ if(wd->ledStruct.counter % 4 != 0)
+ {
+ // Update LED each 400ms(4*100)
+ // Prevent this situation
+ // _______ ___
+ // LED[0] ON | | | x |
+ // ------ OFF->+-+-+-+-+-+-+-+-+-+-+-+->>>...
+ // LED[1] ON
+ //
+ return;
+ }
+
+ if (((wd->state == ZM_WLAN_STATE_DISABLED) && (wd->sta.bChannelScan))
+ || ((wd->state != ZM_WLAN_STATE_DISABLED) && (wd->sta.bAutoReconnect)))
+ {
+ // Scan/AutoReconnect state
+ zfLedCtrlType2_scan(dev);
+ }
+ else
+ {
+ // Neither Connected nor Scan
+ zfHpLedCtrl(dev, 0, 0);
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ }
+ else
+ {
+ if( wd->sta.bChannelScan )
+ {
+ // Scan state
+ if(wd->ledStruct.counter % 4 != 0)
+ return;
+ zfLedCtrlType2_scan(dev);
+ return;
+ }
+
+ if(wd->frequency < 3000)
+ {
+ OperateLED = 0; // LED[0]: work on 2.4G (b/g band)
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ else
+ {
+ OperateLED = 1; // LED[1]: work on 5G (a band)
+ zfHpLedCtrl(dev, 0, 0);
+ }
+
+ if ((zfPowerSavingMgrIsSleeping(dev)) && ((wd->ledStruct.ledMode[OperateLED] & 0x8) == 0))
+ {
+ // If Sleeping, turn OFF
+ zfHpLedCtrl(dev, OperateLED, 0);
+ }
+ else
+ {
+ //Connect state
+ if ((wd->ledStruct.counter & 1) == 0) // even
+ {
+ // No traffic, always ON
+ zfHpLedCtrl(dev, OperateLED, 1);
+ }
+ else // odd
+ {
+ if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
+ {
+ // If have traffic, turn OFF
+ // _____ _ _ _ _____
+ // LED[Operate] ON | | | | | | | |
+ // ------------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
+ //
+ wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
+ zfHpLedCtrl(dev, OperateLED, 0);
+ }
+ }
+ }
+ }
+}
+
+void zfLedCtrlType2_scan(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ // When doing scan, blink(Amber/Blue) and off per 500ms (about 400ms in our driver)
+ // _______ _______
+ // LED[0] ON | | 8 12 | |
+ // ------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
+ // LED[1] ON 0 4 |_______| 0 3
+ //
+
+ switch(wd->ledStruct.counter % 16)
+ {
+ case 0: // case 0~3, LED[0] on
+ if(wd->supportMode & ZM_WIRELESS_MODE_24)
+ {
+ zfHpLedCtrl(dev, 0, 1);
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ else
+ {
+ zfHpLedCtrl(dev, 1, 1);
+ zfHpLedCtrl(dev, 0, 0);
+ }
+ break;
+
+ case 8: // case 8~11, LED[1] on
+ if(wd->supportMode & ZM_WIRELESS_MODE_5)
+ {
+ zfHpLedCtrl(dev, 1, 1);
+ zfHpLedCtrl(dev, 0, 0);
+ }
+ else
+ {
+ zfHpLedCtrl(dev, 0, 1);
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ break;
+
+ default: // others, all off
+ zfHpLedCtrl(dev, 0, 0);
+ zfHpLedCtrl(dev, 1, 0);
+ break;
+ }
+}
+
+/**********************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfLedCtrlType3 */
+/* Customize for Netgear Single-LED state ((bug#32243)) */
+/* */
+/* EOff: when the adapter is disabled or hasn't started to associate with AP */
+/* yet. */
+/* EOn: Once adpater associate with AP successfully */
+/* ESlow blinking: whenever adapters do site-survey or try to associate with AP */
+/* - If there is a connection already, and adapters do site-survey or */
+/* re-associate action, the LED should keep LED backgraoud as ON, thus */
+/* the blinking behavior SHOULD be OFF (200ms) - ON (800ms) and continue this*/
+/* cycle. */
+/* - If there is no connection yet, and adapters start to do site-survey or */
+/* associate action, the LED should keep LED background as OFF, thus the */
+/* blinking behavior SHOULD be ON (200ms) - OFF (800ms) and continue this */
+/* cycle. */
+/* - For the case that associate fail, adpater should keep associating, and the*/
+/* LED should also keep slow blinking. */
+/* EQuick blinking: to blink OFF-ON cycle for each time that traffic packet is */
+/* received or is transmitted. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Shang-Chun Liu Atheros Communications, INC. 2008.01 */
+/* */
+/**********************************************************************************/
+void zfLedCtrlType3_scan(zdev_t* dev, u16_t isConnect);
+
+void zfLedCtrlType3(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if (zfStaIsConnected(dev) != TRUE)
+ {
+ // Disconnect state
+ if(wd->ledStruct.counter % 2 != 0)
+ {
+ // Update LED each 200ms(2*100)
+ // Prevent this situation
+ // ___ _
+ // LED[0] ON | | |x|
+ // ------ OFF->+-+-+-+-+-+-+->>>...
+ //
+ return;
+ }
+
+ if (((wd->state == ZM_WLAN_STATE_DISABLED) && (wd->sta.bChannelScan))
+ || ((wd->state != ZM_WLAN_STATE_DISABLED) && (wd->sta.bAutoReconnect)))
+ {
+ // Scan/AutoReconnect state
+ zfLedCtrlType3_scan(dev, 0);
+ }
+ else
+ {
+ // Neither Connected nor Scan
+ zfHpLedCtrl(dev, 0, 0);
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ }
+ else
+ {
+ if( wd->sta.bChannelScan )
+ {
+ // Scan state
+ if(wd->ledStruct.counter % 2 != 0)
+ return;
+ zfLedCtrlType3_scan(dev, 1);
+ return;
+ }
+
+ if ((zfPowerSavingMgrIsSleeping(dev)) && ((wd->ledStruct.ledMode[0] & 0x8) == 0))
+ {
+ // If Sleeping, turn OFF
+ zfHpLedCtrl(dev, 0, 0);
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ else
+ {
+ //Connect state
+ if ((wd->ledStruct.counter & 1) == 0) // even
+ {
+ // No traffic, always ON
+ zfHpLedCtrl(dev, 0, 1);
+ zfHpLedCtrl(dev, 1, 1);
+ }
+ else // odd
+ {
+ if ((wd->ledStruct.txTraffic > 0) || (wd->ledStruct.rxTraffic > 0))
+ {
+ // If have traffic, turn OFF
+ // _____ _ _ _ _____
+ // LED[Operate] ON | | | | | | | |
+ // ------------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
+ //
+ wd->ledStruct.txTraffic = wd->ledStruct.rxTraffic = 0;
+ zfHpLedCtrl(dev, 0, 0);
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ }
+ }
+ }
+}
+
+void zfLedCtrlType3_scan(zdev_t* dev, u16_t isConnect)
+{
+ u32_t ton, toff, tmp;
+ zmw_get_wlan_dev(dev);
+
+ // Doing scan when :
+ // 1. Disconnected: ON (200ms) - OFF (800ms) (200ms-600ms in our driver)
+ // ___ ___ ___
+ // LED[0] ON | | | | | |
+ // ------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
+ // 0 2 4 6 8 10 12 14 16
+ // 2. Connected: ON (800ms) - OFF (200ms) (600ms-200ms in our driver)
+ // ___________ ___________ ______
+ // LED[0] ON | | | | |
+ // ------ OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+->>>...
+ // 0 2 4 6 8 10 12 14 16
+
+ //Scan state
+ if(!isConnect)
+ ton = 2, toff = 6;
+ else
+ ton = 6, toff = 2;
+
+ if ((ton + toff) != 0)
+ {
+ tmp = wd->ledStruct.counter % (ton+toff);
+ if (tmp < ton)
+ {
+ zfHpLedCtrl(dev, 0, 1);
+ zfHpLedCtrl(dev, 1, 1);
+ }
+ else
+ {
+ zfHpLedCtrl(dev, 0, 0);
+ zfHpLedCtrl(dev, 1, 0);
+ }
+ }
+}
+
+/******************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfLedCtrl_BlinkWhenScan_Alpha */
+/* Customize for Alpha/DLink LED */
+/* - Blink LED 12 times within 3 seconds when doing Active Scan */
+/* ___ ___ ___ ___ */
+/* LED[0] ON | | | | | | | | */
+/* -------OFF->-+-+-+-+-+-+-+-+-+-+-+-+-+--+-->>>... */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Shang-Chun Liu Atheros Communications, INC. 2007.11 */
+/* */
+/******************************************************************************/
+void zfLedCtrl_BlinkWhenScan_Alpha(zdev_t* dev)
+{
+ static u32_t counter = 0;
+ zmw_get_wlan_dev(dev);
+
+ if(counter > 34) // counter for 3 sec
+ {
+ wd->ledStruct.LEDCtrlFlag &= ~(u8_t)ZM_LED_CTRL_FLAG_ALPHA;
+ counter = 0;
+ }
+
+ if( (counter % 3) < 2)
+ zfHpLedCtrl(dev, 0, 1);
+ else
+ zfHpLedCtrl(dev, 0, 0);
+
+ counter++;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfLed100msCtrl */
+/* LED 100 milliseconds timer. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.6 */
+/* */
+/************************************************************************/
+void zfLed100msCtrl(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->ledStruct.counter++;
+
+ if(wd->ledStruct.LEDCtrlFlag)
+ {
+ switch(wd->ledStruct.LEDCtrlFlag) {
+ case ZM_LED_CTRL_FLAG_ALPHA:
+ zfLedCtrl_BlinkWhenScan_Alpha(dev);
+ break;
+ }
+ }
+ else
+ {
+ switch(wd->ledStruct.LEDCtrlType) {
+ case 1: // Traditional 1 LED
+ zfLedCtrlType1(dev);
+ break;
+
+ case 2: // Dual-LEDs for Netgear
+ zfLedCtrlType2(dev);
+ break;
+
+ case 3: // Single-LED for Netgear (WN111v2)
+ zfLedCtrlType3(dev);
+ break;
+
+ default:
+ zfLedCtrlType1(dev);
+ break;
+ }
+ }
+}
+
diff --git a/drivers/staging/otus/80211core/performance.c b/drivers/staging/otus/80211core/performance.c
new file mode 100644
index 000000000000..51b42d54f653
--- /dev/null
+++ b/drivers/staging/otus/80211core/performance.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : performance.c */
+/* */
+/* Abstract */
+/* This module performance evaluation functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
+
+#define ZM_TP_SIZE 50
+struct zsSummary zm_summary;
+struct zsVariation zm_var;
+struct zsThroughput zm_tp;
+
+void zfiPerformanceInit(zdev_t* dev)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_summary.tick_base = wd->tick;
+ zm_summary.tx_msdu_count = 0;
+ zm_summary.tx_mpdu_count = 0;
+ zm_summary.rx_msdu_count = 0;
+ zm_summary.rx_mpdu_count = 0;
+ zm_summary.rx_broken_seq = 0;
+ zm_summary.rx_broken_sum = 0;
+ zm_summary.rx_seq_base = 0;
+ zm_summary.rx_broken_seq_dis = 0;
+ zm_summary.rx_duplicate_seq = 0;
+ zm_summary.rx_old_seq = 0;
+ zm_summary.reset_count = 0;
+ zm_summary.reset_sum = 0;
+ zm_summary.rx_lost_sum = 0;
+ zm_summary.rx_duplicate_error = 0;
+ zm_summary.rx_free = 0;
+ zm_summary.rx_amsdu_len = 0;
+ zm_summary.rx_flush = 0;
+ zm_summary.rx_clear = 0;
+ zm_summary.rx_reorder = 0;
+
+ for (i=0; i<100; i++)
+ {
+ zm_var.tx_msdu_tick[i] = zm_var.tx_mpdu_tick[i] = 0;
+ zm_var.rx_msdu_tick[i] = zm_var.rx_mpdu_tick[i] = 0;
+ }
+
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_PERFORMANCE, 100);
+
+ zm_tp.size = ZM_TP_SIZE;
+ zm_tp.head = zm_tp.size - 1;
+ zm_tp.tail = 0;
+ for (i=0; i<zm_tp.size; i++)
+ {
+ zm_tp.tx[i]=0;
+ zm_tp.rx[i]=0;
+ }
+}
+
+void zfiPerformanceGraph(zdev_t* dev)
+{
+ s16_t i,j;
+ u8_t s[ZM_TP_SIZE+5];
+ zmw_get_wlan_dev(dev);
+
+ for (i=0; i<(zm_tp.size-1); i++)
+ {
+ zm_tp.tx[i] = zm_tp.tx[i+1];
+ zm_tp.rx[i] = zm_tp.rx[i+1];
+ }
+ zm_tp.tx[zm_tp.size-1] = zm_summary.tx_mpdu_count*1500*8/1000000;
+ zm_tp.rx[zm_tp.size-1] = zm_summary.rx_msdu_count*1500*8/1000000;
+
+ for (i=15; i>0; i--)
+ {
+ s[0] = (i/10) + '0';
+ s[1] = (i%10) + '0';
+ s[2] = '0';
+ s[3] = '|';
+ for (j=0; j<zm_tp.size; j++)
+ {
+ if ((zm_tp.tx[j]/10 == i) && (zm_tp.rx[j]/10 == i))
+ {
+ s[4+j] = 'X';
+ }
+ else if (zm_tp.tx[j]/10 == i)
+ {
+ s[4+j] = 'T';
+ }
+ else if (zm_tp.rx[j]/10 == i)
+ {
+ s[4+j] = 'R';
+ }
+ else
+ {
+ s[4+j] = ' ';
+ }
+ }
+ s[zm_tp.size+4] = '\0';
+ DbgPrint("%s",s);
+ }
+ DbgPrint("000|__________________________________________________");
+
+}
+
+
+void zfiPerformanceRefresh(zdev_t* dev)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zfiDbgReadReg(dev, 0x11772c);
+
+ zm_var.tx_msdu_mean = zm_summary.tx_msdu_count / 100;
+ zm_var.tx_mpdu_mean = zm_summary.tx_mpdu_count / 100;
+ zm_var.rx_msdu_mean = zm_summary.rx_msdu_count / 100;
+ zm_var.rx_mpdu_mean = zm_summary.rx_mpdu_count / 100;
+
+ zm_var.tx_msdu_sum = zm_var.tx_mpdu_sum = 0;
+ zm_var.rx_msdu_sum = zm_var.rx_mpdu_sum = 0;
+ zm_summary.tx_idle_count = zm_summary.rx_idle_count = 0;
+ for (i=0; i<100; i++)
+ {
+ zm_var.tx_msdu_sum += (zm_var.tx_msdu_tick[i] * zm_var.tx_msdu_tick[i]);
+ zm_var.tx_mpdu_sum += (zm_var.tx_mpdu_tick[i] * zm_var.tx_mpdu_tick[i]);
+ zm_var.rx_msdu_sum += (zm_var.rx_msdu_tick[i] * zm_var.rx_msdu_tick[i]);
+ zm_var.rx_mpdu_sum += (zm_var.rx_mpdu_tick[i] * zm_var.rx_mpdu_tick[i]);
+
+ if (!zm_var.tx_mpdu_tick[i]) zm_summary.tx_idle_count++;
+ if (!zm_var.rx_mpdu_tick[i]) zm_summary.rx_idle_count++;
+ }
+ zm_var.tx_msdu_var = (zm_var.tx_msdu_sum / 100) - (zm_var.tx_msdu_mean * zm_var.tx_msdu_mean);
+ zm_var.tx_mpdu_var = (zm_var.tx_mpdu_sum / 100) - (zm_var.tx_mpdu_mean * zm_var.tx_mpdu_mean);
+ zm_var.rx_msdu_var = (zm_var.rx_msdu_sum / 100) - (zm_var.rx_msdu_mean * zm_var.rx_msdu_mean);
+ zm_var.rx_mpdu_var = (zm_var.rx_mpdu_sum / 100) - (zm_var.rx_mpdu_mean * zm_var.rx_mpdu_mean);
+
+ zm_summary.tick_base = wd->tick;
+ zm_summary.rx_broken_sum += zm_summary.rx_broken_seq;
+ zm_summary.rx_lost_sum += (zm_summary.rx_broken_seq - zm_summary.rx_duplicate_seq - zm_summary.rx_old_seq);
+
+ zfiPerformanceGraph(dev);
+
+ DbgPrint("******************************************************\n");
+ DbgPrint("* TX: MSDU=%5d, VAR=%5d; MPDU=%5d, VAR=%5d\n", zm_summary.tx_msdu_count,
+ zm_var.tx_msdu_var, zm_summary.tx_mpdu_count, zm_var.tx_mpdu_var);
+ DbgPrint("* TX: idle=%5d,TxRate=%3d, PER=%5d\n", zm_summary.tx_idle_count,
+ wd->CurrentTxRateKbps/1000,
+ (u16_t)wd->PER[wd->sta.oppositeInfo[0].rcCell.currentRate]);
+ DbgPrint("* RX: MSDU=%5d, VAR=%5d; MPDU=%5d, VAR=%5d\n", zm_summary.rx_msdu_count,
+ zm_var.rx_msdu_var, zm_summary.rx_mpdu_count, zm_var.rx_mpdu_var);
+ DbgPrint("* RX: idle=%5d,RxRate=%3d,AMSDU=%5d\n", zm_summary.rx_idle_count,
+ wd->CurrentRxRateKbps/1000, zm_summary.rx_amsdu_len);
+ DbgPrint("* RX broken seq=%4d, distances=%4d, duplicates=%4d\n", zm_summary.rx_broken_seq,
+ zm_summary.rx_broken_seq_dis, zm_summary.rx_duplicate_seq);
+ DbgPrint("* RX old seq=%4d, lost=%4d, broken sum=%4d\n", zm_summary.rx_old_seq,
+ (zm_summary.rx_broken_seq - zm_summary.rx_duplicate_seq - zm_summary.rx_old_seq),
+ zm_summary.rx_broken_sum);
+ DbgPrint("* Rx lost sum=%4d,dup. error=%4d, free count=%4d\n", zm_summary.rx_lost_sum,
+ zm_summary.rx_duplicate_error, zm_summary.rx_free);
+ DbgPrint("* Rx flush sum=%4d, clear sum=%4d, reorder=%7d\n", zm_summary.rx_flush,
+ zm_summary.rx_clear, zm_summary.rx_reorder);
+ DbgPrint("* Firmware reset=%3d, reset sum=%4d\n", zm_summary.reset_count,
+ zm_summary.reset_sum);
+ DbgPrint("******************************************************\n\n");
+ //reset count 11772c
+ zm_summary.tx_msdu_count = 0;
+ zm_summary.tx_mpdu_count = 0;
+ zm_summary.rx_msdu_count = 0;
+ zm_summary.rx_mpdu_count = 0;
+ zm_summary.rx_broken_seq = 0;
+ zm_summary.rx_broken_seq_dis = 0;
+ zm_summary.rx_duplicate_seq = 0;
+ zm_summary.rx_old_seq = 0;
+ zm_summary.reset_count = 0;
+ zm_summary.rx_amsdu_len = 0;
+
+ for (i=0; i<100; i++)
+ {
+ zm_var.tx_msdu_tick[i] = zm_var.tx_mpdu_tick[i] = 0;
+ zm_var.rx_msdu_tick[i] = zm_var.rx_mpdu_tick[i] = 0;
+ }
+
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_PERFORMANCE, 100);
+}
+
+void zfiTxPerformanceMSDU(zdev_t* dev, u32_t tick)
+{
+ u32_t index;
+ zm_summary.tx_msdu_count++;
+
+ index = tick - zm_summary.tick_base;
+
+ if (index < 100)
+ {
+ zm_var.tx_msdu_tick[index]++;
+ }
+ else
+ {
+ //DbgPrint("wd->tick exceeded tick_base+100!\n");
+ }
+}
+
+void zfiRxPerformanceMSDU(zdev_t* dev, u32_t tick)
+{
+ u32_t index;
+ zm_summary.rx_msdu_count++;
+
+ index = tick - zm_summary.tick_base;
+
+ if (index < 100)
+ {
+ zm_var.rx_msdu_tick[index]++;
+ }
+ else
+ {
+ //DbgPrint("wd->tick exceeded tick_base+100!\n");
+ }
+}
+
+void zfiTxPerformanceMPDU(zdev_t* dev, u32_t tick)
+{
+ u32_t index;
+ zm_summary.tx_mpdu_count++;
+
+ index = tick - zm_summary.tick_base;
+
+ if (index < 100)
+ {
+ zm_var.tx_mpdu_tick[index]++;
+ }
+ else
+ {
+ //DbgPrint("wd->tick exceeded tick_base+100!\n");
+ }
+}
+
+#ifndef ZM_INT_USE_EP2_HEADER_SIZE
+#define ZM_INT_USE_EP2_HEADER_SIZE 12
+#endif
+void zfiRxPerformanceMPDU(zdev_t* dev, zbuf_t* buf)
+{
+ u32_t index;
+ u16_t frameType;
+ u16_t frameCtrl;
+ u8_t mpduInd;
+ u16_t plcpHdrLen;
+ u16_t len;
+
+ zmw_get_wlan_dev(dev);
+
+ len = zfwBufGetSize(dev, buf);
+ mpduInd = zmw_rx_buf_readb(dev, buf, len-1);
+ /* First MPDU or Single MPDU */
+ if(((mpduInd & 0x30) == 0x00) || ((mpduInd & 0x30) == 0x20))
+ //if ((mpduInd & 0x10) == 0x00)
+ {
+ plcpHdrLen = 12; // PLCP header length
+ }
+ else
+ {
+ if (zmw_rx_buf_readh(dev, buf, 4) == wd->macAddr[0] &&
+ zmw_rx_buf_readh(dev, buf, 6) == wd->macAddr[1] &&
+ zmw_rx_buf_readh(dev, buf, 8) == wd->macAddr[2]) {
+ plcpHdrLen = 0;
+ }
+ else if (zmw_rx_buf_readh(dev, buf, 16) == wd->macAddr[0] &&
+ zmw_rx_buf_readh(dev, buf, 18) == wd->macAddr[1] &&
+ zmw_rx_buf_readh(dev, buf, 20) == wd->macAddr[2]){
+ plcpHdrLen = 12;
+ }
+ else {
+ plcpHdrLen = 0;
+ }
+ }
+
+ frameCtrl = zmw_rx_buf_readb(dev, buf, plcpHdrLen + 0);
+ frameType = frameCtrl & 0xf;
+
+ if (frameType != ZM_WLAN_DATA_FRAME)
+ {
+ return;
+ }
+
+ zm_summary.rx_mpdu_count++;
+
+ index = wd->tick - zm_summary.tick_base;
+
+ if (index < 100)
+ {
+ zm_var.rx_mpdu_tick[index]++;
+ }
+ else
+ {
+ //DbgPrint("wd->tick exceeded tick_base+100!\n");
+ }
+}
+
+void zfiRxPerformanceSeq(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t seq_no;
+ u16_t offset = 0;
+ u16_t old_dis = zm_summary.rx_broken_seq_dis;
+ //sys_time = KeQueryPerformanceCounter(&freq);
+
+ seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
+
+ ZM_SEQ_DEBUG("Out %5d\n", seq_no);
+
+ if (seq_no < zm_summary.rx_seq_base)
+ {
+ if (seq_no == 0)
+ {
+ if (zm_summary.rx_seq_base != 4095)
+ {
+ zm_summary.rx_broken_seq++;
+ ZM_SEQ_DEBUG("Broken seq");
+ zm_summary.rx_broken_seq_dis+=(4096 - zm_summary.rx_seq_base);
+ }
+ }
+ else if ((seq_no < 300) && (zm_summary.rx_seq_base > 3800))
+ {
+ zm_summary.rx_broken_seq++;
+ ZM_SEQ_DEBUG("Broken seq");
+ zm_summary.rx_broken_seq_dis+=(4096 - zm_summary.rx_seq_base + seq_no);
+ }
+ else
+ {
+ zm_summary.rx_broken_seq++;
+ ZM_SEQ_DEBUG("Broken seq");
+ zm_summary.rx_broken_seq_dis+=(zm_summary.rx_seq_base - seq_no);
+ zm_summary.rx_old_seq++;
+ }
+ }
+ else
+ {
+ if (seq_no != (zm_summary.rx_seq_base + 1))
+ {
+ if ((seq_no > 3800) && (zm_summary.rx_seq_base < 300))
+ {
+ zm_summary.rx_broken_seq++;
+ ZM_SEQ_DEBUG("Broken seq");
+ zm_summary.rx_broken_seq_dis+=(4096 - seq_no + zm_summary.rx_seq_base);
+ zm_summary.rx_old_seq++;
+ }
+ else
+ {
+ zm_summary.rx_broken_seq++;
+ ZM_SEQ_DEBUG("Broken seq");
+ zm_summary.rx_broken_seq_dis+=(seq_no - zm_summary.rx_seq_base);
+ }
+ }
+ }
+ if (seq_no == zm_summary.rx_seq_base)
+ {
+ zm_summary.rx_duplicate_seq++;
+ }
+
+ if ((zm_summary.rx_broken_seq_dis - old_dis) > 100)
+ {
+ DbgPrint("* seq_no=%4d, base_seq=%4d, dis_diff=%4d", seq_no,
+ zm_summary.rx_seq_base, zm_summary.rx_broken_seq_dis - old_dis);
+ }
+ zm_summary.rx_seq_base = seq_no;
+}
+
+void zfiRxPerformanceReg(zdev_t* dev, u32_t reg, u32_t rsp)
+{
+ zm_summary.reset_count = (u16_t)rsp - zm_summary.reset_sum;
+ zm_summary.reset_sum = (u16_t)rsp;
+}
+
+void zfiRxPerformanceDup(zdev_t* dev, zbuf_t* buf1, zbuf_t* buf2)
+{
+ u16_t seq_no1, seq_no2;
+
+ seq_no1 = zmw_rx_buf_readh(dev, buf1, 22) >> 4;
+ seq_no2 = zmw_rx_buf_readh(dev, buf2, 22) >> 4;
+ if (seq_no1 != seq_no2)
+ {
+ zm_summary.rx_duplicate_error++;
+ }
+}
+
+void zfiRxPerformanceFree(zdev_t* dev, zbuf_t* buf)
+{
+ zm_summary.rx_free++;
+}
+
+void zfiRxPerformanceAMSDU(zdev_t* dev, zbuf_t* buf, u16_t len)
+{
+ if (zm_summary.rx_amsdu_len < len)
+ {
+ zm_summary.rx_amsdu_len = len;
+ }
+}
+void zfiRxPerformanceFlush(zdev_t* dev)
+{
+ zm_summary.rx_flush++;
+}
+
+void zfiRxPerformanceClear(zdev_t* dev)
+{
+ zm_summary.rx_clear++;
+ ZM_SEQ_DEBUG("RxClear");
+}
+
+void zfiRxPerformanceReorder(zdev_t* dev)
+{
+ zm_summary.rx_reorder++;
+}
+#endif /* end of ZM_ENABLE_PERFORMANCE_EVALUATION */
diff --git a/drivers/staging/otus/80211core/performance.h b/drivers/staging/otus/80211core/performance.h
new file mode 100644
index 000000000000..29f658ae477c
--- /dev/null
+++ b/drivers/staging/otus/80211core/performance.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _PERFORMANCE_H
+#define _PERFORMANCE_H
+
+#ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
+
+struct zsSummary
+{
+ u32_t tx_msdu_count;
+ u32_t tx_mpdu_count;
+ u32_t rx_msdu_count;
+ u32_t rx_mpdu_count;
+ u32_t tick_base;
+ u16_t rx_seq_base;
+ u16_t rx_broken_seq;
+ u16_t rx_broken_sum;
+ u16_t rx_broken_seq_dis;
+ u16_t rx_duplicate_seq;
+ u16_t rx_duplicate_error;
+ u16_t rx_old_seq;
+ u16_t rx_lost_sum;
+ u16_t tx_idle_count;
+ u16_t rx_idle_count;
+ u16_t reset_count;
+ u16_t reset_sum;
+ u16_t rx_free;
+ u16_t rx_amsdu_len;
+ u16_t rx_flush;
+ u16_t rx_clear;
+ u32_t rx_reorder;
+};
+
+struct zsVariation
+{
+ u32_t tx_msdu_tick[100];
+ u32_t tx_mpdu_tick[100];
+ u32_t rx_msdu_tick[100];
+ u32_t rx_mpdu_tick[100];
+
+ u32_t tx_msdu_mean;
+ u32_t tx_mpdu_mean;
+ u32_t rx_msdu_mean;
+ u32_t rx_mpdu_mean;
+
+ u32_t tx_msdu_sum;
+ u32_t tx_mpdu_sum;
+ u32_t rx_msdu_sum;
+ u32_t rx_mpdu_sum;
+
+ u32_t tx_msdu_var;
+ u32_t tx_mpdu_var;
+ u32_t rx_msdu_var;
+ u32_t rx_mpdu_var;
+};
+
+struct zsThroughput
+{
+ u32_t tx[50];
+ u32_t rx[50];
+ u16_t head;
+ u16_t tail;
+ u16_t size;
+ LARGE_INTEGER sys_time;
+ LARGE_INTEGER freq;
+};
+
+void zfiPerformanceInit(zdev_t* dev);
+void zfiPerformanceRefresh(zdev_t* dev);
+
+void zfiTxPerformanceMSDU(zdev_t* dev, u32_t tick);
+void zfiRxPerformanceMSDU(zdev_t* dev, u32_t tick);
+void zfiTxPerformanceMPDU(zdev_t* dev, u32_t tick);
+void zfiRxPerformanceMPDU(zdev_t* dev, zbuf_t* buf);
+void zfiRxPerformanceSeq(zdev_t* dev, zbuf_t* buf);
+void zfiRxPerformanceReg(zdev_t* dev, u32_t reg, u32_t rsp);
+void zfiRxPerformanceDup(zdev_t* dev, zbuf_t* buf1, zbuf_t* buf2);
+void zfiRxPerformanceFree(zdev_t* dev, zbuf_t* buf);
+void zfiRxPerformanceAMSDU(zdev_t* dev, zbuf_t* buf, u16_t len);
+void zfiRxPerformanceFlush(zdev_t* dev);
+void zfiRxPerformanceClear(zdev_t* dev);
+void zfiRxPerformanceReorder(zdev_t* dev);
+#endif /* end of ZM_ENABLE_PERFORMANCE_EVALUATION */
+#endif /* end of _PERFORMANCE_H */
diff --git a/drivers/staging/otus/80211core/pub_usb.h b/drivers/staging/otus/80211core/pub_usb.h
new file mode 100644
index 000000000000..c4b4bd25e828
--- /dev/null
+++ b/drivers/staging/otus/80211core/pub_usb.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _PUB_USB_H
+#define _PUB_USB_H
+
+#include "../oal_dt.h"
+
+#define ZM_HAL_80211_MODE_AP 0
+#define ZM_HAL_80211_MODE_STA 1
+#define ZM_HAL_80211_MODE_IBSS_GENERAL 2
+#define ZM_HAL_80211_MODE_IBSS_WPA2PSK 3
+
+/* USB module description */
+/* Queue Management */
+/* 80211core requires OAL to implement a transmission queue in OAL's */
+/* USB module. Because there is only limited on-chip memory, so USB */
+/* data transfer may be pending until on-chip memory is available. */
+/* 80211core also requires OAL's USB module to provide two functions */
+/* zfwUsbGetFreeTxQSize() and zfwUsbGetMaxTxQSize() for 80211core to */
+/* query the status of this transmission queue. The main purpose of */
+/* this queue is for QoS/WMM. Though there are hardware priority */
+/* queues on the chip, and also software priority queues in the */
+/* 80211core. There is still one and only one USB channel. So */
+/* 80211core will use the information that zfwUsbGetFreeTxQSize() */
+/* returned to schedule the traffic from the software priority */
+/* queues to the hardware priority queues. For example, if 80211core */
+/* found that USB transmission queue is going to be full, it will */
+/* not allow packets with lower priority to enter the USB channel. */
+
+
+/* Structure for USB call back functions */
+struct zfCbUsbFuncTbl {
+ void (*zfcbUsbRecv)(zdev_t *dev, zbuf_t *buf);
+ void (*zfcbUsbRegIn)(zdev_t* dev, u32_t* rsp, u16_t rspLen);
+ void (*zfcbUsbOutComplete)(zdev_t* dev, zbuf_t *buf, u8_t status, u8_t *hdr);
+ void (*zfcbUsbRegOutComplete)(zdev_t* dev);
+};
+
+/* Call back functions */
+/* Below are the functions that should be called by the OAL */
+
+/* When data is available in endpoint 3, OAL shall embed the data in */
+/* zbuf_t and supply to 80211core by calling this function */
+/* void (*zfcbUsbRecv)(zdev_t *dev, zbuf_t *buf); */
+
+/* When data is available in endpoint 2, OAL shall call this function */
+/* void (*zfcbUsbRegIn)(zdev_t* dev, u32_t* rsp, u16_t rspLen); */
+
+/* When USB data transfer completed in endpoint 1, OAL shall call this function */
+/* void (*zfcbUsbOutComplete)(zdev_t* dev, zbuf_t *buf, u8_t status, u8_t *hdr); */
+
+
+/* Call out functions */
+/* Below are the functions that supply by the OAL for 80211core to */
+/* manipulate the USB */
+
+/* Return OAL's USB TxQ size */
+extern u32_t zfwUsbGetMaxTxQSize(zdev_t* dev);
+
+/* Return OAL's TxQ available size */
+extern u32_t zfwUsbGetFreeTxQSize(zdev_t* dev);
+
+/* Register call back function */
+extern void zfwUsbRegisterCallBack(zdev_t* dev, struct zfCbUsbFuncTbl *zfUsbFunc);
+
+/* Enable USB interrupt endpoint */
+extern u32_t zfwUsbEnableIntEpt(zdev_t *dev, u8_t endpt);
+
+/* Enable USB Rx endpoint */
+extern int zfwUsbEnableRxEpt(zdev_t* dev, u8_t endpt);
+
+/* 80211core call this function to send a USB request over endpoint 0 */
+extern u32_t zfwUsbSubmitControl(zdev_t* dev, u8_t req, u16_t value,
+ u16_t index, void *data, u32_t size);
+extern u32_t zfwUsbSubmitControlIo(zdev_t* dev, u8_t req, u8_t reqtype,
+ u16_t value, u16_t index, void *data, u32_t size);
+
+/* 80211core call this function to transfer data out over endpoint 1 */
+extern void zfwUsbCmd(zdev_t* dev, u8_t endpt, u32_t* cmd, u16_t cmdLen);
+
+/* 80211core call this function to transfer data out over endpoint 4 */
+extern u32_t zfwUsbSend(zdev_t* dev, u8_t endpt, u8_t *hdr, u16_t hdrlen, u8_t *snap, u16_t snapLen,
+ u8_t *tail, u16_t tailLen, zbuf_t *buf, u16_t offset);
+
+/* 80211core call this function to set USB configuration */
+extern u32_t zfwUsbSetConfiguration(zdev_t *dev, u16_t value);
+
+#endif
diff --git a/drivers/staging/otus/80211core/pub_zfi.h b/drivers/staging/otus/80211core/pub_zfi.h
new file mode 100644
index 000000000000..a35bd5d41d2c
--- /dev/null
+++ b/drivers/staging/otus/80211core/pub_zfi.h
@@ -0,0 +1,821 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _PUB_DEFS_H
+#define _PUB_DEFS_H
+
+#include "../oal_dt.h"
+
+/***** Section 1 : Tunable Parameters *****/
+/* The defintions in this section are tunabel parameters */
+
+/* Maximum number of BSS that could be scaned */
+#define ZM_MAX_BSS 128
+
+/* Maximum number of WPA2 PMKID that supported */
+#define ZM_PMKID_MAX_BSS_CNT 8
+
+/* Enable aggregation and deaggregation */
+#define ZM_ENABLE_AGGREGATION
+
+#ifdef ZM_ENABLE_AGGREGATION
+ /* Enable BA failed retransmission in firmware */
+ #define ZM_ENABLE_FW_BA_RETRANSMISSION
+ #define ZM_BYPASS_AGGR_SCHEDULING
+ //#define ZM_AGGR_BIT_ON
+#endif
+
+
+#ifndef ZM_FB50
+//#define ZM_FB50
+#endif
+
+#ifndef ZM_AP_DEBUG
+//#define ZM_AP_DEBUG
+#endif
+
+//#define ZM_ENABLE_BA_RATECTRL
+
+/***** End of section 1 *****/
+
+
+/***** Section 2 : Public Definitions, data structures and prototypes *****/
+/* function return status */
+#define ZM_STATUS_SUCCESS 0
+#define ZM_STATUS_FAILURE 1
+
+// media connect status
+#define ZM_STATUS_MEDIA_CONNECT 0x00
+#define ZM_STATUS_MEDIA_DISCONNECT 0x01
+#define ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND 0x02
+#define ZM_STATUS_MEDIA_DISABLED 0x03
+#define ZM_STATUS_MEDIA_CONNECTION_DISABLED 0x04
+#define ZM_STATUS_MEDIA_CONNECTION_RESET 0x05
+#define ZM_STATUS_MEDIA_RESET 0x06
+#define ZM_STATUS_MEDIA_DISCONNECT_DEAUTH 0x07
+#define ZM_STATUS_MEDIA_DISCONNECT_DISASOC 0x08
+#define ZM_STATUS_MEDIA_DISCONNECT_TIMEOUT 0x09
+#define ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED 0x0a
+#define ZM_STATUS_MEDIA_DISCONNECT_ASOC_FAILED 0x0b
+#define ZM_STATUS_MEDIA_DISCONNECT_MIC_FAIL 0x0c
+#define ZM_STATUS_MEDIA_DISCONNECT_UNREACHABLE 0x0d
+#define ZM_STATUS_MEDIA_DISCONNECT_BEACON_MISS 0x0e
+
+// Packet Filter
+#define ZM_PACKET_TYPE_DIRECTED 0x00000001
+#define ZM_PACKET_TYPE_MULTICAST 0x00000002
+#define ZM_PACKET_TYPE_ALL_MULTICAST 0x00000004
+#define ZM_PACKET_TYPE_BROADCAST 0x00000008
+#define ZM_PACKET_TYPE_PROMISCUOUS 0x00000020
+
+/* BSS mode definition */
+/* TODO : The definitions here are coupled with XP's NDIS OID. */
+/* We can't be changed them freely, need to disarm this mine */
+#define ZM_MODE_IBSS 0
+#define ZM_MODE_INFRASTRUCTURE 1
+#define ZM_MODE_UNKNOWN 2
+#define ZM_MODE_INFRASTRUCTURE_MAX 3
+#define ZM_MODE_AP 4
+#define ZM_MODE_PSEUDO 5
+
+
+/* Authentication mode */
+#define ZM_AUTH_MODE_OPEN 0
+#define ZM_AUTH_MODE_SHARED_KEY 1
+#define ZM_AUTH_MODE_AUTO 2
+#define ZM_AUTH_MODE_WPA 3
+#define ZM_AUTH_MODE_WPAPSK 4
+#define ZM_AUTH_MODE_WPA_NONE 5
+#define ZM_AUTH_MODE_WPA2 6
+#define ZM_AUTH_MODE_WPA2PSK 7
+#ifdef ZM_ENABLE_CENC
+#define ZM_AUTH_MODE_CENC 8
+#endif //ZM_ENABLE_CENC
+#define ZM_AUTH_MODE_WPA_AUTO 9
+#define ZM_AUTH_MODE_WPAPSK_AUTO 10
+
+// Encryption mode
+#define ZM_NO_WEP 0x0
+#define ZM_AES 0x4
+#define ZM_TKIP 0x2
+#define ZM_WEP64 0x1
+#define ZM_WEP128 0x5
+#define ZM_WEP256 0x6
+#ifdef ZM_ENABLE_CENC
+#define ZM_CENC 0x7
+#endif //ZM_ENABLE_CENC
+
+/* Encryption type for wep status */
+#define ZM_ENCRYPTION_WEP_DISABLED 0
+#define ZM_ENCRYPTION_WEP_ENABLED 1
+#define ZM_ENCRYPTION_WEP_KEY_ABSENT 2
+#define ZM_ENCRYPTION_NOT_SUPPORTED 3
+#define ZM_ENCRYPTION_TKIP 4
+#define ZM_ENCRYPTION_TKIP_KEY_ABSENT 5
+#define ZM_ENCRYPTION_AES 6
+#define ZM_ENCRYPTION_AES_KEY_ABSENT 7
+
+#ifdef ZM_ENABLE_CENC
+#define ZM_ENCRYPTION_CENC 8
+#endif //ZM_ENABLE_CENC
+
+/* security type */
+#define ZM_SECURITY_TYPE_NONE 0
+#define ZM_SECURITY_TYPE_WEP 1
+#define ZM_SECURITY_TYPE_WPA 2
+
+#ifdef ZM_ENABLE_CENC
+#define ZM_SECURITY_TYPE_CENC 3
+#endif //ZM_ENABLE_CENC
+
+/* Encryption Exemption Action Type */
+#define ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION 0
+#define ZM_ENCRYPTION_EXEMPT_ALWAYS 1
+
+/* MIC failure */
+#define ZM_MIC_PAIRWISE_ERROR 0x06
+#define ZM_MIC_GROUP_ERROR 0x0E
+
+
+/* power save mode */
+#define ZM_STA_PS_NONE 0
+#define ZM_STA_PS_MAX 1
+#define ZM_STA_PS_FAST 2
+#define ZM_STA_PS_LIGHT 3
+
+/* WME AC Type */
+#define ZM_WME_AC_BK 0 /* Background AC */
+#define ZM_WME_AC_BE 1 /* Best-effort AC */
+#define ZM_WME_AC_VIDEO 2 /* Video AC */
+#define ZM_WME_AC_VOICE 3 /* Voice AC */
+
+/* Preamble type */
+#define ZM_PREAMBLE_TYPE_AUTO 0
+#define ZM_PREAMBLE_TYPE_LONG 1
+#define ZM_PREAMBLE_TYPE_SHORT 2
+
+/* wireless modes constants */
+#define ZM_WIRELESS_MODE_5_54 0x01 ///< 5 GHz 54 Mbps
+#define ZM_WIRELESS_MODE_5_108 0x02 ///< 5 GHz 108 Mbps
+#define ZM_WIRELESS_MODE_24_11 0x04 ///< 2.4 GHz 11 Mbps
+#define ZM_WIRELESS_MODE_24_54 0x08 ///< 2.4 GHz 54 Mbps
+#define ZM_WIRELESS_MODE_24_108 0x10 ///< 2.4 GHz 108 Mbps
+#define ZM_WIRELESS_MODE_49_13 0x100 ///< 4.9 GHz 13.5 Mbps, quarter rate chn-bandwidth = 5
+#define ZM_WIRELESS_MODE_49_27 0x200 ///< 4.9 GHz 27 Mbps, half rate chn-bandwidth = 10
+#define ZM_WIRELESS_MODE_49_54 0x400 ///< 4.9 GHz 54 Mbps, full rate chn-bandwidth = 20
+#define ZM_WIRELESS_MODE_5_300 0x1000 ///< 5 GHz 300 Mbps
+#define ZM_WIRELESS_MODE_24_300 0x2000 ///< 2.4 GHz 300 Mbps
+#define ZM_WIRELESS_MODE_5_130 0x4000 ///< 5 GHz 130 Mbps
+#define ZM_WIRELESS_MODE_24_130 0x8000 ///< 2.4 GHz 130 Mbps
+
+#define ZM_WIRELESS_MODE_24_N (ZM_WIRELESS_MODE_24_130|ZM_WIRELESS_MODE_24_300)
+#define ZM_WIRELESS_MODE_5_N (ZM_WIRELESS_MODE_5_130|ZM_WIRELESS_MODE_5_300)
+#define ZM_WIRELESS_MODE_24 (ZM_WIRELESS_MODE_24_11|ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)
+#define ZM_WIRELESS_MODE_5 (ZM_WIRELESS_MODE_5_54|ZM_WIRELESS_MODE_5_N)
+
+/* AdHoc Mode with different band */
+#define ZM_ADHOCBAND_A 1
+#define ZM_ADHOCBAND_B 2
+#define ZM_ADHOCBAND_G 3
+#define ZM_ADHOCBAND_BG 4
+#define ZM_ADHOCBAND_ABG 5
+
+/* Authentication algorithm in the field algNo of authentication frames */
+#define ZM_AUTH_ALGO_OPEN_SYSTEM 0x10000 /* Open system */
+#define ZM_AUTH_ALGO_SHARED_KEY 0x10001 /* Shared Key */
+#define ZM_AUTH_ALGO_LEAP 0x10080 /* Leap */
+
+struct zsScanResult
+{
+ u32_t reserved;
+};
+
+
+struct zsStastics
+{
+ u32_t reserved;
+};
+
+#define ZM_MAX_SUPP_RATES_IE_SIZE 12
+#define ZM_MAX_IE_SIZE 50 //100
+#define ZM_MAX_WPS_IE_SIZE 150
+#define ZM_MAX_PROBE_FRAME_BODY_SIZE 512//300
+#define ZM_MAX_COUNTRY_INFO_SIZE 20
+
+#define ZM_MAX_SSID_LENGTH 32
+struct zsBssInfo
+{
+ u8_t macaddr[6];
+ u8_t bssid[6];
+ u8_t beaconInterval[2];
+ u8_t capability[2];
+ u8_t timeStamp[8];
+ u8_t ssid[ZM_MAX_SSID_LENGTH + 2]; // EID(1) + Length(1) + SSID(32)
+ u8_t supportedRates[ZM_MAX_SUPP_RATES_IE_SIZE + 2]; // EID(1) + Length(1) + supported rates [12]
+ u8_t channel;
+ u16_t frequency;
+ u16_t atimWindow;
+ u8_t erp;
+ u8_t extSupportedRates[ZM_MAX_SUPP_RATES_IE_SIZE + 2]; // EID(1) + Length(1) + extended supported rates [12]
+ u8_t wpaIe[ZM_MAX_IE_SIZE + 2];
+ u8_t wscIe[ZM_MAX_WPS_IE_SIZE + 2];
+ u8_t rsnIe[ZM_MAX_IE_SIZE + 2];
+#ifdef ZM_ENABLE_CENC
+ u8_t cencIe[ZM_MAX_IE_SIZE + 2]; /* CENC */ /* half size because of memory exceed 64k boundary */
+#endif //ZM_ENABLE_CENC
+ u8_t securityType;
+ u8_t signalStrength;
+ u8_t signalQuality;
+ u16_t sortValue;
+ u8_t wmeSupport;
+ u8_t flag;
+ u8_t EnableHT;
+ u8_t enableHT40;
+ u8_t SG40;
+ u8_t extChOffset;
+ u8_t apCap; // bit0:11N AP
+ u16_t frameBodysize;
+ u8_t frameBody[ZM_MAX_PROBE_FRAME_BODY_SIZE];
+ u8_t countryInfo[ZM_MAX_COUNTRY_INFO_SIZE + 2];
+ u16_t athOwlAp;
+ u16_t marvelAp;
+ u16_t broadcomHTAp;
+ u32_t tick;
+ struct zsBssInfo* next;
+};
+
+struct zsBssList
+{
+ u8_t bssCount;
+ struct zsBssInfo* head;
+ struct zsBssInfo* tail;
+};
+
+struct zsBssListV1
+{
+ u8_t bssCount;
+ struct zsBssInfo bssInfo[ZM_MAX_BSS];
+};
+
+#define ZM_KEY_FLAG_GK 0x0001
+#define ZM_KEY_FLAG_PK 0X0002
+#define ZM_KEY_FLAG_AUTHENTICATOR 0x0004
+#define ZM_KEY_FLAG_INIT_IV 0x0008
+#define ZM_KEY_FLAG_DEFAULT_KEY 0x0010
+
+#ifdef ZM_ENABLE_CENC
+#define ZM_KEY_FLAG_CENC 0x0020
+#endif //ZM_ENABLE_CENC
+
+// Comment: For TKIP, key[0]~key[15] => TKIP key
+// key[16]~key[23] => Tx MIC key
+// key[24]~key[31] => Rx MIC key
+struct zsKeyInfo
+{
+ u8_t* key;
+ u8_t keyLength;
+ u8_t keyIndex;
+ u8_t* initIv;
+ u16_t flag;
+ u8_t vapId;
+ u16_t vapAddr[3];
+ u16_t* macAddr;
+};
+
+
+
+/*
+ * Channels are specified by frequency.
+ */
+typedef struct {
+ u16_t channel; /* setting in Mhz */
+ u32_t channelFlags; /* see below */
+ u8_t privFlags;
+ s8_t maxRegTxPower; /* max regulatory tx power in dBm */
+ s8_t maxTxPower; /* max true tx power in 0.25 dBm */
+ s8_t minTxPower; /* min true tx power in 0.25 dBm */
+} ZM_HAL_CHANNEL;
+
+struct zsRegulationTable
+{
+ u16_t regionCode;
+ u16_t CurChIndex;
+ u16_t allowChannelCnt;
+ ZM_HAL_CHANNEL allowChannel[60]; /* 2.4GHz: 14 channels, 5 GHz: 31 channels */
+};
+
+struct zsPartnerNotifyEvent
+{
+ u8_t bssid[6]; // The BSSID of IBSS
+ u8_t peerMacAddr[6]; // The MAC address of peer station
+};
+
+#define ZM_RC_TRAINED_BIT 0x1
+struct zsRcCell
+{
+ u32_t txCount;
+ u32_t failCount;
+ u8_t currentRate;
+ u8_t currentRateIndex;
+ u32_t probingTime;
+ u8_t operationRateSet[24];
+ u8_t operationRateCount;
+ u16_t rxRssi;
+ u8_t flag;
+ u32_t lasttxCount;
+ u32_t lastTime;
+};
+
+struct zsOppositeInfo
+{
+ u8_t macAddr[6];
+ struct zsRcCell rcCell;
+ u8_t valid; // This indicate if this opposite is still valid
+ u8_t aliveCounter;
+ u8_t pkInstalled;
+
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ /* For WPA2PSK ! */
+ u8_t wpaState;
+ u8_t camIdx;
+ u8_t encryMode;
+ u16_t iv16;
+ u32_t iv32;
+#endif
+};
+
+typedef void (*zfpIBSSIteratePeerStationCb)(
+ zdev_t* dev, struct zsOppositeInfo *peerInfo, void *ctx, u8_t index);
+
+typedef u16_t (*zfpStaRxSecurityCheckCb)(zdev_t* dev, zbuf_t* buf);
+
+
+/* Communication Tally data structure */
+struct zsCommTally
+{
+ u32_t txUnicastFrm; // 0 txUnicastFrames
+ u32_t txMulticastFrm; // 1 txMulticastFrames
+ u32_t txUnicastOctets; // 2 txUniOctets byte size
+ u32_t txMulticastOctets; // 3 txMultiOctets byte size
+ u32_t txFrmUpperNDIS; // 4
+ u32_t txFrmDrvMgt; // 5
+ u32_t RetryFailCnt; // 6
+ u32_t Hw_TotalTxFrm; // 7 Hardware total Tx Frame
+ u32_t Hw_RetryCnt; // 8 txMultipleRetriesFrames
+ u32_t Hw_UnderrunCnt; // 9
+
+ u32_t DriverRxFrmCnt; // 10
+ u32_t rxUnicastFrm; // 11 rxUnicastFrames
+ u32_t rxMulticastFrm; // 12rxMulticastFrames
+
+ u32_t NotifyNDISRxFrmCnt; // 14
+ u32_t rxUnicastOctets; // 15 rxUniOctets byte size
+ u32_t rxMulticastOctets; // 16 rxMultiOctets byte size
+ u32_t DriverDiscardedFrm; // 17 Discard by ValidateFrame
+ u32_t LessThanDataMinLen; // 18
+ u32_t GreaterThanMaxLen; // 19
+ u32_t DriverDiscardedFrmCauseByMulticastList;
+ u32_t DriverDiscardedFrmCauseByFrmCtrl;
+ u32_t rxNeedFrgFrm; // 22 need more frg frm
+ u32_t DriverRxMgtFrmCnt;
+ u32_t rxBroadcastFrm; // 24 Receive broadcast frame count
+ u32_t rxBroadcastOctets; // 25 Receive broadcast frame byte size
+ u32_t rx11bDataFrame; // 26 Measured quality 11b data frame count
+ u32_t rxOFDMDataFrame; // 27 Measured quality 11g data frame count
+
+
+ u32_t Hw_TotalRxFrm; // 28
+ u32_t Hw_CRC16Cnt; // 29 rxPLCPCRCErrCnt
+ u32_t Hw_CRC32Cnt; // 30 rxCRC32ErrCnt
+ u32_t Hw_DecrypErr_UNI; // 31
+ u32_t Hw_DecrypErr_Mul; // 32
+
+ u32_t Hw_RxFIFOOverrun; // 34
+ u32_t Hw_RxTimeOut; // 35
+ u32_t LossAP; // 36
+
+ u32_t Tx_MPDU; // 37
+ u32_t BA_Fail; // 38
+ u32_t Hw_Tx_AMPDU; // 39
+ u32_t Hw_Tx_MPDU; // 40
+
+ u32_t RateCtrlTxMPDU;
+ u32_t RateCtrlBAFail;
+
+ u32_t txQosDropCount[5]; //41 42 43 44 45
+
+ u32_t Hw_RxMPDU; // 46
+ u32_t Hw_RxDropMPDU; // 47
+ u32_t Hw_RxDelMPDU; // 48
+
+ u32_t Hw_RxPhyMiscError; // 49
+ u32_t Hw_RxPhyXRError; // 50
+ u32_t Hw_RxPhyOFDMError; // 51
+ u32_t Hw_RxPhyCCKError; // 52
+ u32_t Hw_RxPhyHTError; // 53
+ u32_t Hw_RxPhyTotalCount; // 54
+
+ u32_t swRxFragmentCount; // 55
+ u32_t swRxUnicastMicFailCount; // 56
+ u32_t swRxMulticastMicFailCount; // 57
+ u32_t swRxDropUnencryptedCount; // 58
+
+ u32_t txBroadcastFrm;
+ u32_t txBroadcastOctets;
+};
+
+/* Traffic Monitor Tally data structure */
+struct zsTrafTally
+{
+ u32_t rxDuplicate;
+ u32_t rxSrcIsOwnMac;
+ //u32_t rxDataFrameCount;
+ //u32_t rxDataByteCount;
+ //u32_t rxDataBytesIn1000ms;
+ //u32_t rxDataTmpFor1000ms;
+ //u32_t rxDataBytesIn2000ms;
+ //u32_t rxDataTmpFor2000ms;
+
+ //u32_t txDataFrameCount;
+ //u32_t txDataByteCount;
+ //u32_t txDataBytesIn1000ms;
+ //u32_t txDataTmpFor1000ms;
+ u32_t txDataBytesIn2000ms;
+ u32_t txDataTmpFor2000ms;
+};
+
+/* Hal rx packet moniter information */
+struct zsMonHalRxInfo
+{
+ u32_t currentRSSI[7];
+ u32_t currentRxEVM[14];
+ u32_t currentRxDataMT;
+ u32_t currentRxDataMCS;
+ u32_t currentRxDataBW;
+ u32_t currentRxDataSG;
+};
+
+struct zsTail
+{
+ u8_t SignalStrength1;
+ u8_t SignalStrength2;
+ u8_t SignalStrength3;
+ u8_t SignalQuality;
+ u8_t SAIndex;
+ u8_t DAIndex;
+ u8_t ErrorIndication;
+ u8_t RxMacStatus;
+};
+
+union zuTail
+{
+ struct zsTail Data;
+ u8_t Byte[8];
+};
+
+struct zsAdditionInfo
+{
+ u8_t PlcpHeader[12];
+ union zuTail Tail;
+};
+
+
+struct zsPmkidBssidInfo
+{
+ u16_t bssid[3];
+ u8_t pmkid[16];
+};
+
+struct zsPmkidInfo
+{
+ u32_t bssidCount;
+ struct zsPmkidBssidInfo bssidInfo[ZM_PMKID_MAX_BSS_CNT];
+};
+
+
+struct zsCbFuncTbl
+{
+ u16_t (*zfcbAuthNotify)(zdev_t* dev, u16_t* macAddr);
+ u16_t (*zfcbAsocNotify)(zdev_t* dev, u16_t* macAddr, u8_t* body,
+ u16_t bodySize, u16_t port);
+ u16_t (*zfcbDisAsocNotify)(zdev_t* dev, u8_t* macAddr, u16_t port);
+ u16_t (*zfcbApConnectNotify)(zdev_t* dev, u8_t* macAddr, u16_t port);
+ void (*zfcbConnectNotify)(zdev_t* dev, u16_t status, u16_t* bssid);
+ void (*zfcbScanNotify)(zdev_t* dev, struct zsScanResult* result);
+ void (*zfcbMicFailureNotify)(zdev_t* dev, u16_t* addr, u16_t status);
+ void (*zfcbApMicFailureNotify)(zdev_t* dev, u8_t* addr, zbuf_t* buf);
+ void (*zfcbIbssPartnerNotify)(zdev_t* dev, u16_t status,
+ struct zsPartnerNotifyEvent *event);
+ void (*zfcbMacAddressNotify)(zdev_t* dev, u8_t* addr);
+ void (*zfcbSendCompleteIndication)(zdev_t* dev, zbuf_t* buf);
+ void (*zfcbRecvEth)(zdev_t* dev, zbuf_t* buf, u16_t port);
+ void (*zfcbRecv80211)(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo);
+ void (*zfcbRestoreBufData)(zdev_t* dev, zbuf_t* buf);
+#ifdef ZM_ENABLE_CENC
+ u16_t (*zfcbCencAsocNotify)(zdev_t* dev, u16_t* macAddr, u8_t* body,
+ u16_t bodySize, u16_t port);
+#endif //ZM_ENABLE_CENC
+ u8_t (*zfcbClassifyTxPacket)(zdev_t* dev, zbuf_t* buf);
+
+ void (*zfcbHwWatchDogNotify)(zdev_t* dev);
+};
+
+extern void zfZeroMemory(u8_t* va, u16_t length);
+#define ZM_INIT_CB_FUNC_TABLE(p) zfZeroMemory((u8_t *)p, sizeof(struct zsCbFuncTbl));
+
+//extern struct zsWlanDev zgWlanDev;
+
+/* Initialize WLAN hardware and software, resource will be allocated */
+/* for WLAN operation, must be called first before other function. */
+extern u16_t zfiWlanOpen(zdev_t* dev, struct zsCbFuncTbl* cbFuncTbl);
+
+/* WLAN hardware will be shutdown and all resource will be release */
+extern u16_t zfiWlanClose(zdev_t* dev);
+
+/* Enable/disable Wlan operation */
+extern u16_t zfiWlanEnable(zdev_t* dev);
+extern u16_t zfiWlanDisable(zdev_t* dev, u8_t ResetKeyCache);
+extern u16_t zfiWlanResume(zdev_t* dev, u8_t doReconn);
+extern u16_t zfiWlanSuspend(zdev_t* dev);
+
+/* Enable/disable ISR interrupt */
+extern u16_t zfiWlanInterruptEnable(zdev_t* dev);
+extern u16_t zfiWlanInterruptDisable(zdev_t* dev);
+
+/* Do WLAN site survey */
+extern u16_t zfiWlanScan(zdev_t* dev);
+
+/* Get WLAN stastics */
+extern u16_t zfiWlanGetStatistics(zdev_t* dev);
+
+/* Reset WLAN */
+extern u16_t zfiWlanReset(zdev_t* dev);
+
+/* Deauthenticate a STA */
+extern u16_t zfiWlanDeauth(zdev_t* dev, u16_t* macAddr, u16_t reason);
+
+extern u16_t zfiTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port);
+extern u8_t zfiIsTxQueueFull(zdev_t* dev);
+extern u16_t zfiTxSend80211Mgmt(zdev_t* dev, zbuf_t* buf, u16_t port);
+
+extern void zfiIsrPci(zdev_t* dev);
+
+extern u8_t zfiWlanIBSSGetPeerStationsCount(zdev_t* dev);
+extern u8_t zfiWlanIBSSIteratePeerStations(zdev_t* dev, u8_t numToIterate, zfpIBSSIteratePeerStationCb callback, void *ctx);
+extern void zfiWlanFlushAllQueuedBuffers(zdev_t* dev);
+
+/* coid.c */
+extern void zfiWlanQueryMacAddress(zdev_t* dev, u8_t* addr);
+
+extern u16_t zfiGlobalDataSize(zdev_t* dev);
+
+extern void zfiHeartBeat(zdev_t* dev);
+
+extern void zfiWlanSetWlanMode(zdev_t* dev, u8_t wlanMode);
+extern void zfiWlanSetAuthenticationMode(zdev_t* dev, u8_t authMode);
+extern void zfiWlanSetWepStatus(zdev_t* dev, u8_t wepStatus);
+extern void zfiWlanSetSSID(zdev_t* dev, u8_t* ssid, u8_t ssidLength);
+extern void zfiWlanSetFragThreshold(zdev_t* dev, u16_t fragThreshold);
+extern void zfiWlanSetRtsThreshold(zdev_t* dev, u16_t rtsThreshold);
+extern void zfiWlanSetFrequency(zdev_t* dev, u32_t frequency, u8_t bImmediate);
+extern void zfiWlanSetBssid(zdev_t* dev, u8_t* bssid);
+extern void zfiWlanSetBeaconInterval(zdev_t* dev, u16_t beaconInterval,
+ u8_t bImmediate);
+extern void zfiWlanSetDtimCount(zdev_t* dev, u8_t dtim);
+extern void zfiWlanSetAtimWindow(zdev_t* dev, u16_t atimWindow, u8_t bImmediate);
+extern void zfiWlanSetEncryMode(zdev_t* dev, u8_t encryMode);
+extern u8_t zfiWlanSetKey(zdev_t* dev, struct zsKeyInfo keyInfo);
+extern u8_t zfiWlanPSEUDOSetKey(zdev_t* dev, struct zsKeyInfo keyInfo);
+extern void zfiWlanSetPowerSaveMode(zdev_t* dev, u8_t mode);
+extern void zfiWlanQueryBssListV1(zdev_t* dev, struct zsBssListV1* bssListV1);
+extern void zfiWlanQueryBssList(zdev_t* dev, struct zsBssList* pBssList);
+extern void zfiWlanSetProtectionMode(zdev_t* dev, u8_t mode);
+extern void zfiWlanFlushBssList(zdev_t* dev);
+
+void zfiWlanDisableDfsChannel(zdev_t* dev, u8_t disableFlag);
+
+extern u8_t zfiWlanQueryWlanMode(zdev_t* dev);
+extern u16_t zfiWlanChannelToFrequency(zdev_t* dev, u8_t channel);
+extern u8_t zfiWlanFrequencyToChannel(zdev_t* dev, u16_t freq);
+
+#define ZM_WLAN_STATE_OPENED 0
+#define ZM_WLAN_STATE_ENABLED 1
+#define ZM_WLAN_STATE_DISABLED 2
+#define ZM_WLAN_STATE_CLOSEDED 3
+extern u8_t zfiWlanQueryAdapterState(zdev_t* dev);
+extern u8_t zfiWlanQueryAuthenticationMode(zdev_t* dev, u8_t bWrapper);
+extern u8_t zfiWlanQueryWepStatus(zdev_t* dev, u8_t bWrapper);
+extern void zfiWlanQuerySSID(zdev_t* dev, u8_t* ssid, u8_t* pSsidLength);
+extern u16_t zfiWlanQueryFragThreshold(zdev_t* dev);
+extern u16_t zfiWlanQueryRtsThreshold(zdev_t* dev);
+extern u32_t zfiWlanQueryFrequency(zdev_t* dev);
+extern u32_t zfiWlanQueryCurrentFrequency(zdev_t* dev, u8_t qmode);
+extern u32_t zfiWlanQueryFrequencyAttribute(zdev_t* dev, u32_t frequency);
+extern void zfiWlanQueryFrequencyHT(zdev_t* dev, u32_t *bandWidth, u32_t *extOffset);
+extern u8_t zfiWlanQueryCWMode(zdev_t* dev);
+extern u32_t zfiWlanQueryCWEnable(zdev_t* dev);
+extern void zfiWlanQueryBssid(zdev_t* dev, u8_t* bssid);
+extern u16_t zfiWlanQueryBeaconInterval(zdev_t* dev);
+extern u32_t zfiWlanQueryRxBeaconTotal(zdev_t* dev);
+extern u16_t zfiWlanQueryAtimWindow(zdev_t* dev);
+extern u8_t zfiWlanQueryEncryMode(zdev_t* dev);
+extern u16_t zfiWlanQueryCapability(zdev_t* dev);
+extern u16_t zfiWlanQueryAid(zdev_t* dev);
+extern void zfiWlanQuerySupportRate(zdev_t* dev, u8_t* rateArray, u8_t* pLength);
+extern void zfiWlanQueryExtSupportRate(zdev_t* dev, u8_t* rateArray, u8_t* pLength);
+extern void zfiWlanQueryRsnIe(zdev_t* dev, u8_t* ie, u8_t* pLength);
+extern void zfiWlanQueryWpaIe(zdev_t* dev, u8_t* ie, u8_t* pLength);
+extern u8_t zfiWlanQueryHTMode(zdev_t* dev);
+extern u8_t zfiWlanQueryBandWidth40(zdev_t* dev);
+extern u8_t zfiWlanQueryMulticastCipherAlgo(zdev_t *dev);
+extern u16_t zfiWlanQueryRegionCode(zdev_t* dev);
+extern void zfiWlanSetWpaIe(zdev_t* dev, u8_t* ie, u8_t Length);
+extern void zfiWlanSetWpaSupport(zdev_t* dev, u8_t WpaSupport);
+extern void zfiWlanCheckStaWpaIe(zdev_t* dev);
+extern void zfiWlanSetBasicRate(zdev_t* dev, u8_t bRateSet, u8_t gRateSet,
+ u32_t nRateSet);
+extern void zfiWlanSetBGMode(zdev_t* dev, u8_t mode);
+extern void zfiWlanSetpreambleType(zdev_t* dev, u8_t type);
+extern u8_t zfiWlanQuerypreambleType(zdev_t* dev);
+extern u8_t zfiWlanQueryPowerSaveMode(zdev_t* dev);
+extern void zfiWlanSetMacAddress(zdev_t* dev, u16_t* mac);
+extern u16_t zfiWlanSetTxRate(zdev_t* dev, u16_t rate);
+extern u32_t zfiWlanQueryTxRate(zdev_t* dev);
+extern void zfWlanUpdateRxRate(zdev_t* dev, struct zsAdditionInfo* addInfo);
+extern u32_t zfiWlanQueryRxRate(zdev_t* dev);
+extern u8_t zfiWlanSetPmkidInfo(zdev_t* dev, u16_t* bssid, u8_t* pmkid);
+extern u32_t zfiWlanQueryPmkidInfo(zdev_t* dev, u8_t* buf, u32_t len);
+extern void zfiWlanSetAllMulticast(zdev_t* dev, u32_t setting);
+extern void zfiWlanSetHTCtrl(zdev_t* dev, u32_t *setting, u32_t forceTxTPC);
+extern void zfiWlanQueryHTCtrl(zdev_t* dev, u32_t *setting, u32_t *forceTxTPC);
+extern void zfiWlanDbg(zdev_t* dev, u8_t setting);
+
+extern void zfiWlanResetTally(zdev_t* dev);
+extern void zfiWlanQueryTally(zdev_t* dev, struct zsCommTally *tally);
+extern void zfiWlanQueryTrafTally(zdev_t* dev, struct zsTrafTally *tally);
+extern void zfiWlanQueryMonHalRxInfo(zdev_t* dev, struct zsMonHalRxInfo *halRxInfo);
+
+extern u32_t zfiFWConfig(zdev_t* dev, u32_t size);
+
+extern void zfiDKEnable(zdev_t* dev, u32_t enable);
+
+extern void zfiWlanSetMulticastList(zdev_t* dev, u8_t size, u8_t* pList);
+extern void zfiWlanRemoveKey(zdev_t* dev, u8_t keyType, u8_t keyId);
+extern u8_t zfiWlanQueryIsPKInstalled(zdev_t *dev, u8_t *staMacAddr);
+extern u32_t zfiWlanQueryPacketTypePromiscuous(zdev_t* dev);
+extern void zfiWlanSetPacketTypePromiscuous(zdev_t* dev, u32_t setValue);
+extern void zfiSetChannelManagement(zdev_t* dev, u32_t setting);
+extern void zfiSetRifs(zdev_t* dev, u16_t setting);
+extern void zfiCheckRifs(zdev_t* dev);
+extern void zfiSetReorder(zdev_t* dev, u16_t value);
+extern void zfiSetSeqDebug(zdev_t* dev, u16_t value);
+
+extern u16_t zfiConfigWdsPort(zdev_t* dev, u8_t wdsPortId, u16_t flag, u16_t* wdsAddr,
+ u16_t encType, u32_t* wdsKey);
+extern void zfiWlanQueryRegulationTable(zdev_t* dev, struct zsRegulationTable* pEntry);
+extern void zfiWlanSetScanTimerPerChannel(zdev_t* dev, u16_t time);
+extern void zfiWlanSetAutoReconnect(zdev_t* dev, u8_t enable);
+extern u32_t zfiDebugCmd(zdev_t* dev, u32_t cmd, u32_t value);
+extern void zfiWlanSetProbingHiddenSsid(zdev_t* dev, u8_t* ssid, u8_t ssidLen,
+ u16_t entry);
+extern void zfiWlanSetDropUnencryptedPackets(zdev_t* dev, u8_t enable);
+extern void zfiWlanSetIBSSJoinOnly(zdev_t* dev, u8_t joinOnly);
+extern void zfiWlanSetDefaultKeyId(zdev_t* dev, u8_t keyId);
+extern void zfiWlanSetDisableProbingWithSsid(zdev_t* dev, u8_t mode);
+extern void zfiWlanQueryGSN(zdev_t* dev, u8_t *gsn, u16_t vapId);
+extern u16_t zfiStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType);
+extern u8_t zfiWlanSetDot11DMode(zdev_t* dev, u8_t mode);
+extern u8_t zfiWlanSetDot11HDFSMode(zdev_t* dev, u8_t mode);
+extern u8_t zfiWlanSetDot11HTPCMode(zdev_t* dev, u8_t mode);
+extern u8_t zfiWlanSetAniMode(zdev_t* dev, u8_t mode);
+extern void zfiWlanSetStaWme(zdev_t* dev, u8_t enable, u8_t uapsdInfo);
+extern void zfiWlanSetApWme(zdev_t* dev, u8_t enable);
+extern u8_t zfiWlanQuerywmeEnable(zdev_t* dev);
+#ifdef ZM_OS_LINUX_FUNC
+extern void zfiWlanShowTally(zdev_t* dev);
+#endif
+#ifdef ZM_ENABLE_CENC
+/* CENC */
+extern u8_t zfiWlanSetCencPairwiseKey(zdev_t* dev, u8_t keyid, u32_t *txiv, u32_t *rxiv,
+ u8_t *key, u8_t *mic);
+extern u8_t zfiWlanSetCencGroupKey(zdev_t* dev, u8_t keyid, u32_t *rxiv,
+ u8_t *key, u8_t *mic);
+#endif //ZM_ENABLE_CENC
+extern void zfiWlanQuerySignalInfo(zdev_t* dev, u8_t *buffer);
+extern void zfiWlanQueryAdHocCreatedBssDesc(zdev_t* dev, struct zsBssInfo *pBssInfo);
+extern u8_t zfiWlanQueryAdHocIsCreator(zdev_t* dev);
+extern u32_t zfiWlanQuerySupportMode(zdev_t* dev);
+extern u32_t zfiWlanQueryTransmitPower(zdev_t* dev);
+extern void zfiWlanEnableLeapConfig(zdev_t* dev, u8_t leapEnabled);
+
+/* returned buffer allocated by driver core */
+extern void zfiRecvEthComplete(zdev_t* dev, zbuf_t* buf);
+
+extern void zfiRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo);
+
+extern void zfiWlanSetMaxTxPower(zdev_t* dev, u8_t power2, u8_t power5);
+extern void zfiWlanQueryMaxTxPower(zdev_t* dev, u8_t *power2, u8_t *power5);
+extern void zfiWlanSetConnectMode(zdev_t* dev, u8_t mode);
+extern void zfiWlanSetSupportMode(zdev_t* dev, u32_t mode);
+extern void zfiWlanSetAdhocMode(zdev_t* dev, u32_t mode);
+extern u32_t zfiWlanQueryAdhocMode(zdev_t* dev, u8_t bWrapper);
+extern u8_t zfiWlanSetCountryIsoName(zdev_t* dev, u8_t *countryIsoName, u8_t length);
+extern const char* zfiWlanQueryCountryIsoName(zdev_t* dev);
+extern u8_t zfiWlanQueryregulatoryDomain(zdev_t* dev);
+extern u8_t zfiWlanQueryCCS(zdev_t* dev);
+extern void zfiWlanSetCCS(zdev_t* dev, u8_t mode);
+extern void zfiWlanSetRegulatory(zdev_t* dev, u8_t CCS, u16_t Code, u8_t bfirstChannel);
+extern const char* zfiHpGetisoNamefromregionCode(zdev_t* dev, u16_t regionCode);
+extern void zfiWlanSetLEDCtrlParam(zdev_t* dev, u8_t type, u8_t flag);
+extern u32_t zfiWlanQueryReceivedPacket(zdev_t* dev);
+extern void zfiWlanCheckSWEncryption(zdev_t* dev);
+extern u16_t zfiWlanQueryAllowChannels(zdev_t *dev, u16_t *channels);
+extern u16_t zfiWlanGetMulticastAddressCount(zdev_t* dev);
+extern void zfiWlanGetMulticastList(zdev_t* dev, u8_t* pMCList);
+extern void zfiWlanSetPacketFilter(zdev_t* dev, u32_t PacketFilter);
+extern u8_t zfiCompareWithMulticastListAddress(zdev_t* dev, u16_t* dstMacAddr);
+extern void zfiWlanSetSafeModeEnabled(zdev_t* dev, u8_t safeMode);
+extern void zfiWlanSetIBSSAdditionalIELength(zdev_t* dev, u32_t ibssAdditionalIESize, u8_t* ibssAdditionalIE);
+extern void zfiWlanSetXLinkMode(zdev_t* dev, u32_t setValue);
+
+/* hprw.c */
+extern u32_t zfiDbgWriteFlash(zdev_t* dev, u32_t addr, u32_t val);
+extern u32_t zfiDbgWriteReg(zdev_t* dev, u32_t addr, u32_t val);
+extern u32_t zfiDbgReadReg(zdev_t* dev, u32_t addr);
+
+extern u32_t zfiDbgWriteEeprom(zdev_t* dev, u32_t addr, u32_t val);
+extern u32_t zfiDbgBlockWriteEeprom(zdev_t* dev, u32_t addr, u32_t* buf);
+extern u32_t zfiDbgBlockWriteEeprom_v2(zdev_t* dev, u32_t addr, u32_t* buf, u32_t wrlen);
+
+extern u16_t zfiDbgChipEraseFlash(zdev_t *dev);
+extern u16_t zfiDbgProgramFlash(zdev_t *dev, u32_t offset, u32_t len, u32_t *data);
+extern u32_t zfiDbgGetFlashCheckSum(zdev_t *dev, u32_t addr, u32_t len);
+extern u32_t zfiDbgReadFlash(zdev_t *dev, u32_t addr, u32_t len);
+extern u32_t zfiDownloadFwSet(zdev_t *dev);
+
+extern u32_t zfiDbgDelayWriteReg(zdev_t* dev, u32_t addr, u32_t val);
+extern u32_t zfiDbgFlushDelayWrite(zdev_t* dev);
+
+extern u32_t zfiDbgSetIFSynthesizer(zdev_t* dev, u32_t value);
+extern u32_t zfiDbgReadTally(zdev_t* dev);
+
+extern u32_t zfiDbgQueryHwTxBusy(zdev_t* dev);
+
+extern u8_t zfiWlanGetDestAddrFromBuf(zdev_t *dev, zbuf_t *buf, u16_t *macAddr);
+
+extern u32_t zfiWlanQueryHwCapability(zdev_t* dev);
+
+extern void zfiWlanSetDynamicSIFSParam(zdev_t* dev, u8_t val);
+
+/***** End of section 2 *****/
+
+/***** section 3 performace evaluation *****/
+#ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
+extern void zfiTxPerformanceMSDU(zdev_t* dev, u32_t tick);
+extern void zfiRxPerformanceMPDU(zdev_t* dev, zbuf_t* buf);
+extern void zfiRxPerformanceReg(zdev_t* dev, u32_t reg, u32_t rsp);
+#define ZM_PERFORMANCE_INIT(dev) zfiPerformanceInit(dev);
+#define ZM_PERFORMANCE_TX_MSDU(dev, tick) zfiTxPerformanceMSDU(dev, tick);
+#define ZM_PERFORMANCE_RX_MSDU(dev, tick) zfiRxPerformanceMSDU(dev, tick);
+#define ZM_PERFORMANCE_TX_MPDU(dev, tick) zfiTxPerformanceMPDU(dev, tick);
+#define ZM_PERFORMANCE_RX_MPDU(dev, buf) zfiRxPerformanceMPDU(dev, buf);
+#define ZM_PERFORMANCE_RX_SEQ(dev, buf) zfiRxPerformanceSeq(dev, buf);
+#define ZM_PERFORMANCE_REG(dev, reg, rsp) {if(cmd[1] == reg) zfiRxPerformanceReg(dev, reg, rsp);}
+#define ZM_PERFORMANCE_DUP(dev, buf1, buf2) zfiRxPerformanceDup(dev, buf1, buf2);
+#define ZM_PERFORMANCE_FREE(dev, buf) zfiRxPerformanceFree(dev, buf);
+#define ZM_PERFORMANCE_RX_AMSDU(dev, buf, len) zfiRxPerformanceAMSDU(dev, buf, len);
+#define ZM_PERFORMANCE_RX_FLUSH(dev) zfiRxPerformanceFlush(dev);
+#define ZM_PERFORMANCE_RX_CLEAR(dev) zfiRxPerformanceClear(dev);
+#define ZM_SEQ_DEBUG if (wd->seq_debug) DbgPrint
+#define ZM_PERFORMANCE_RX_REORDER(dev) zfiRxPerformanceReorder(dev);
+#else
+#define ZM_PERFORMANCE_INIT(dev)
+#define ZM_PERFORMANCE_TX_MSDU(dev, tick)
+#define ZM_PERFORMANCE_RX_MSDU(dev, tick)
+#define ZM_PERFORMANCE_TX_MPDU(dev, tick)
+#define ZM_PERFORMANCE_RX_MPDU(dev, buf)
+#define ZM_PERFORMANCE_RX_SEQ(dev, buf)
+#define ZM_PERFORMANCE_REG(dev, reg, rsp)
+#define ZM_PERFORMANCE_DUP(dev, buf1, buf2)
+#define ZM_PERFORMANCE_FREE(dev, buf)
+#define ZM_PERFORMANCE_RX_AMSDU(dev, buf, len)
+#define ZM_PERFORMANCE_RX_FLUSH(dev)
+#define ZM_PERFORMANCE_RX_CLEAR(dev)
+#define ZM_SEQ_DEBUG
+#define ZM_PERFORMANCE_RX_REORDER(dev)
+#endif
+/***** End of section 3 *****/
+#endif
diff --git a/drivers/staging/otus/80211core/pub_zfw.h b/drivers/staging/otus/80211core/pub_zfw.h
new file mode 100644
index 000000000000..2474bb7536e8
--- /dev/null
+++ b/drivers/staging/otus/80211core/pub_zfw.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _PUB_ZFW_H
+#define _PUB_ZFW_H
+
+#include "../oal_dt.h"
+
+
+/* Buffer management */
+#ifdef ZM_ENABLE_BUFFER_DEBUG
+extern zbuf_t* zfwBufAllocateWithContext(zdev_t* dev, u16_t len, u8_t *functionName, ULONG line);
+#define zfwBufAllocate(dev, len) zfwBufAllocateWithContext(dev, len, (u8_t *)__func__, __LINE__)
+#else
+extern zbuf_t* zfwBufAllocate(zdev_t* dev, u16_t len);
+#endif
+extern void zfwBufFree(zdev_t* dev, zbuf_t* buf, u16_t errCode);
+extern u16_t zfwBufChain(zdev_t* dev, zbuf_t** head, zbuf_t* tail);
+extern u16_t zfwBufCopy(zdev_t* dev, zbuf_t* dst, zbuf_t* src);
+extern u16_t zfwBufSetSize(zdev_t* dev, zbuf_t* buf, u16_t size);
+extern u16_t zfwBufRemoveHead(zdev_t* dev, zbuf_t* buf, u16_t size);
+extern u16_t zfwBufGetSize(zdev_t* dev, zbuf_t* buf);
+extern void zfwCopyBufContext(zdev_t* dev, zbuf_t* source, zbuf_t* dest);
+
+/* Memory management */
+extern void* zfwMemAllocate(zdev_t* dev, u32_t size);
+extern void zfwMemFree(zdev_t* dev, void* mem, u32_t size);
+extern void zfwMemoryCopy(u8_t* dst, u8_t* src, u16_t length);
+extern void zfwMemoryMove(u8_t* dst, u8_t* src, u16_t length);
+extern void zfwZeroMemory(u8_t* va, u16_t length);
+extern u8_t zfwMemoryIsEqual(u8_t* m1, u8_t* m2, u16_t length);
+
+/* Others */
+extern void zfwSleep(zdev_t* dev, u32_t ms);
+extern u16_t zfwGetVapId(zdev_t* dev);
+extern u16_t zfwStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType);
+extern u32_t zfwWaitForEvent(zdev_t *dev, u32_t event, u32_t timeout);
+extern void zfwSendEvent(zdev_t* dev);
+extern void zfwGetActiveScanDur(zdev_t* dev, u8_t* Dur );
+extern void zfwGetShowZeroLengthSSID(zdev_t* dev, u8_t* Dur );
+/* For debugging */
+extern void zfwDumpBuf(zdev_t* dev, zbuf_t* buf);
+extern void zfwDbgReadRegDone(zdev_t* dev, u32_t addr, u32_t val);
+/* For Evl */
+extern void zfwDbgDownloadFwInitDone(zdev_t* dev);
+extern void zfwDbgReadFlashDone(zdev_t* dev, u32_t addr, u32_t* rspdata, u32_t datalen);
+extern void zfwDbgGetFlashChkSumDone(zdev_t* dev, u32_t* rspdata);
+extern void zfwDbgProgrameFlashDone(zdev_t* dev);
+extern void zfwDbgProgrameFlashChkDone(zdev_t* dev);
+extern void zfwDbgWriteRegDone(zdev_t* dev, u32_t addr, u32_t val);
+extern void zfwDbgWriteEepromDone(zdev_t* dev, u32_t addr, u32_t val);
+extern void zfwDbgReadTallyDone(zdev_t* dev);
+extern void zfwWlanReadRegDone(zdev_t* dev, u32_t addr, u32_t val);
+extern void zfwWlanWriteRegDone(zdev_t* dev, u32_t addr, u32_t val);
+extern void zfwWlanReadTallyDone(zdev_t* dev);
+extern void zfwDbgQueryHwTxBusyDone(zdev_t* dev, u32_t val);
+extern u32_t zfwReadReg(zdev_t* dev, u32_t offset);
+extern u32_t zfwReadEeprom(zdev_t* dev, u32_t addr);
+
+/* Reserved for Vista, please return 0 */
+extern u8_t zfwGetPktEncExemptionActionType(zdev_t* dev, zbuf_t* buf);
+
+#ifdef ZM_ENABLE_CENC
+/* Reserved for CENC, please return 0 */
+extern u8_t zfwCencHandleBeaconProbrespon(zdev_t* dev, u8_t *pWIEc,
+ u8_t *pPeerSSIDc, u8_t *pPeerAddrc);
+#endif //ZM_ENABLE_CENC
+
+#ifdef ZM_HALPLUS_LOCK
+extern asmlinkage struct zsWlanDev *zfwGetWlanDev(zdev_t* dev);
+extern asmlinkage void zfwEnterCriticalSection(zdev_t* dev);
+extern asmlinkage void zfwLeaveCriticalSection(zdev_t* dev);
+extern asmlinkage u8_t zfwBufReadByte(zdev_t* dev, zbuf_t* buf, u16_t offset);
+extern asmlinkage u16_t zfwBufReadHalfWord(zdev_t* dev, zbuf_t* buf, u16_t offset);
+extern asmlinkage void zfwBufWriteByte(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t value);
+extern asmlinkage void zfwBufWriteHalfWord(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t value);
+extern asmlinkage u8_t *zfwGetBuffer(zdev_t* dev, zbuf_t* buf);
+#endif
+
+#endif //_PUB_ZFW_H
diff --git a/drivers/staging/otus/80211core/queue.c b/drivers/staging/otus/80211core/queue.c
new file mode 100644
index 000000000000..d294831b5c36
--- /dev/null
+++ b/drivers/staging/otus/80211core/queue.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : queue.c */
+/* */
+/* Abstract */
+/* This module contains queue management functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "cprecomp.h"
+#include "queue.h"
+
+
+struct zsQueue* zfQueueCreate(zdev_t* dev, u16_t size)
+{
+ struct zsQueue* q;
+
+ if ((q = (struct zsQueue*)zfwMemAllocate(dev, sizeof(struct zsQueue)
+ + (sizeof(struct zsQueueCell)*(size-1)))) != NULL)
+ {
+ q->size = size;
+ q->sizeMask = size-1;
+ q->head = 0;
+ q->tail = 0;
+ }
+ return q;
+}
+
+void zfQueueDestroy(zdev_t* dev, struct zsQueue* q)
+{
+ u16_t size = sizeof(struct zsQueue) + (sizeof(struct zsQueueCell)*(q->size-1));
+
+ zfQueueFlush(dev, q);
+ zfwMemFree(dev, q, size);
+
+ return;
+}
+
+u16_t zfQueuePutNcs(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick)
+{
+ u16_t ret = ZM_ERR_QUEUE_FULL;
+
+ zm_msg0_mm(ZM_LV_1, "zfQueuePutNcs()");
+
+ if (((q->tail+1)&q->sizeMask) != q->head)
+ {
+ q->cell[q->tail].buf = buf;
+ q->cell[q->tail].tick = tick;
+ q->tail = (q->tail+1) & q->sizeMask;
+ ret = ZM_SUCCESS;
+ }
+
+ return ret;
+}
+
+u16_t zfQueuePut(zdev_t* dev, struct zsQueue* q, zbuf_t* buf, u32_t tick)
+{
+ u16_t ret;
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ ret = zfQueuePutNcs(dev, q, buf, tick);
+
+ zmw_leave_critical_section(dev);
+
+ return ret;
+}
+
+zbuf_t* zfQueueGet(zdev_t* dev, struct zsQueue* q)
+{
+ zbuf_t* buf = NULL;
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (q->head != q->tail)
+ {
+ buf = q->cell[q->head].buf;
+ q->head = (q->head+1) & q->sizeMask;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return buf;
+}
+
+u16_t zfCompareDstwithBuf(zdev_t* dev, zbuf_t* buf, u8_t* addr)
+{
+ u16_t i;
+ u8_t dst[6];
+
+ for (i=0; i<6; i++)
+ {
+ dst[i] = zmw_buf_readb(dev, buf, i);
+ if (dst[i] != addr[i])
+ {
+ return 1+i;
+ }
+ }
+
+ return 0;
+}
+
+
+zbuf_t* zfQueueGetWithMac(zdev_t* dev, struct zsQueue* q, u8_t* addr, u8_t* mb)
+{
+ zbuf_t* buf;
+ zbuf_t* retBuf = NULL;
+ u16_t index, next;
+ zmw_declare_for_critical_section();
+
+ *mb = 0;
+
+ zmw_enter_critical_section(dev);
+
+ index = q->head;
+
+ while (1)
+ {
+ if (index != q->tail)
+ {
+ buf = q->cell[index].buf;
+
+ //if buf's detination address == input addr
+ if (zfCompareDstwithBuf(dev, buf, addr) == 0)
+ {
+ retBuf = buf;
+ //Get it, and trace the whole queue to calculate more bit
+ while ((next =((index+1)&q->sizeMask)) != q->tail)
+ {
+ q->cell[index].buf = q->cell[next].buf;
+ q->cell[index].tick = q->cell[next].tick;
+
+ if ((*mb == 0) && (zfCompareDstwithBuf(dev,
+ q->cell[next].buf, addr) == 0))
+ {
+ *mb = 1;
+ }
+
+ index = next;
+ }
+ q->tail = (q->tail-1) & q->sizeMask;
+
+ zmw_leave_critical_section(dev);
+ return retBuf;
+ }
+ index = (index + 1) & q->sizeMask;
+ } //if (index != q->tail)
+ else
+ {
+ break;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return retBuf;
+
+}
+
+void zfQueueFlush(zdev_t* dev, struct zsQueue* q)
+{
+ zbuf_t* buf;
+
+ while ((buf = zfQueueGet(dev, q)) != NULL)
+ {
+ zfwBufFree(dev, buf, 0);
+ }
+
+ return;
+}
+
+void zfQueueAge(zdev_t* dev, struct zsQueue* q, u32_t tick, u32_t msAge)
+{
+ zbuf_t* buf;
+ u32_t buftick;
+ zmw_declare_for_critical_section();
+
+ while (1)
+ {
+ buf = NULL;
+ zmw_enter_critical_section(dev);
+
+ if (q->head != q->tail)
+ {
+ buftick = q->cell[q->head].tick;
+ if (((tick - buftick)*ZM_MS_PER_TICK) > msAge)
+ {
+ buf = q->cell[q->head].buf;
+ q->head = (q->head+1) & q->sizeMask;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (buf != NULL)
+ {
+ zm_msg0_mm(ZM_LV_0, "Age frame in queue!");
+ zfwBufFree(dev, buf, 0);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return;
+}
+
+
+u8_t zfQueueRemovewithIndex(zdev_t* dev, struct zsQueue* q, u16_t index, u8_t* addr)
+{
+ u16_t next;
+ u8_t mb = 0;
+
+ //trace the whole queue to calculate more bit
+ while ((next =((index+1)&q->sizeMask)) != q->tail)
+ {
+ q->cell[index].buf = q->cell[next].buf;
+ q->cell[index].tick = q->cell[next].tick;
+
+ if ((mb == 0) && (zfCompareDstwithBuf(dev,
+ q->cell[next].buf, addr) == 0))
+ {
+ mb = 1;
+ }
+
+ index = next;
+ }
+ q->tail = (q->tail-1) & q->sizeMask;
+
+ return mb;
+
+}
+
+void zfQueueGenerateUapsdTim(zdev_t* dev, struct zsQueue* q,
+ u8_t* uniBitMap, u16_t* highestByte)
+{
+ zbuf_t* psBuf;
+ u8_t dst[6];
+ u16_t id, aid, index, i;
+ u16_t bitPosition;
+ u16_t bytePosition;
+ zmw_get_wlan_dev(dev);
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ index = q->head;
+
+ while (index != q->tail)
+ {
+ psBuf = q->cell[index].buf;
+ for (i=0; i<6; i++)
+ {
+ dst[i] = zmw_buf_readb(dev, psBuf, i);
+ }
+ /* TODO : use u8_t* fot MAC address */
+ if (((id = zfApFindSta(dev, (u16_t*)dst)) != 0xffff)
+ && (wd->ap.staTable[id].psMode != 0))
+ {
+ /* Calculate PVB only when all AC are delivery-enabled */
+ if ((wd->ap.staTable[id].qosInfo & 0xf) == 0xf)
+ {
+ aid = id + 1;
+ bitPosition = (1 << (aid & 0x7));
+ bytePosition = (aid >> 3);
+ uniBitMap[bytePosition] |= bitPosition;
+
+ if (bytePosition>*highestByte)
+ {
+ *highestByte = bytePosition;
+ }
+ }
+ index = (index+1) & q->sizeMask;
+ }
+ else
+ {
+ /* Free garbage UAPSD frame */
+ zfQueueRemovewithIndex(dev, q, index, dst);
+ zfwBufFree(dev, psBuf, 0);
+ }
+ }
+ zmw_leave_critical_section(dev);
+
+ return;
+}
diff --git a/drivers/staging/otus/80211core/queue.h b/drivers/staging/otus/80211core/queue.h
new file mode 100644
index 000000000000..4526b882bd03
--- /dev/null
+++ b/drivers/staging/otus/80211core/queue.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _QUEUE_H
+#define _QUEUE_H
+
+#include "../oal_dt.h"
+
+struct zsQueueCell
+{
+ u32_t tick;
+ zbuf_t* buf;
+};
+
+struct zsQueue
+{
+ u16_t size;
+ u16_t sizeMask;
+ u16_t head;
+ u16_t tail;
+ struct zsQueueCell cell[1];
+};
+
+#endif //#ifndef _QUEUE_H
diff --git a/drivers/staging/otus/80211core/ratectrl.c b/drivers/staging/otus/80211core/ratectrl.c
new file mode 100644
index 000000000000..a43104cd7f51
--- /dev/null
+++ b/drivers/staging/otus/80211core/ratectrl.c
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+#include "ratectrl.h"
+
+const u32_t zcRateToPhyCtrl[] =
+ {
+ /* 1M, 2M, 5M, 11M , 0 1 2 3*/
+ 0x00000, 0x10000, 0x20000, 0x30000,
+ /* 6M 9M 12M 18M , 4 5 6 7*/
+ 0xb0001, 0xf0001, 0xa0001, 0xe0001,
+ /* 24M 36M 48M 54M , 8 9 10 11*/
+ 0x90001, 0xd0001, 0x80001, 0xc0001,
+ /* MCS0 MCS1 MCS2 MCS3, 12 13 14 15*/
+ 0x00002, 0x10002, 0x20002, 0x30002,
+ /* MCS4 MCS5 MCS6 MCS7, 16 17 18 19*/
+ 0x40002, 0x50002, 0x60002, 0x70002,
+ /* MCS8 MCS9 MCS10 MCS11, 20 21 22 23*/
+ 0x80002, 0x90002, 0xa0002, 0xb0002,
+ /* MCS12 MCS13 MCS14 MCS15, 24 25 26 27*/
+ 0xc0002, 0xd0002, 0xe0002, 0xf0002,
+ /* MCS14SG, MCS15SG MCS7SG , 28 29, 30*/
+ 0x800e0002, 0x800f0002, 0x80070002
+ };
+
+
+const u8_t zcHtRateTable[15][4] =
+ { /*[5G 20MHz] [5G 40MHz] [2.4G 20MHz] [2.4G 40MHz]*/
+ { 4, 4, 0, 0}, /*OFDM6M OFDM6M CCK1M CCK1M */
+ { 5, 5, 1, 1}, /*OFDM9M OFDM9M CCK2M CCK2M */
+ { 13, 12, 2, 2}, /*MCS1 MCS0 CCK5M CCK5M */
+ { 14, 13, 3, 3}, /*MCS2 MCS1 CCK11M CCK11M */
+ { 15, 14, 13, 12}, /*MCS3 MCS2 MCS1 MCS0 */
+ { 16, 15, 14, 13}, /*MCS4 MCS3 MCS2 MCS1 */
+ { 23, 16, 15, 14}, /*MCS11 MCS4 MCS3 MCS2 */
+ { 24, 23, 16, 15}, /*MCS12 MCS11 MCS4 MCS3 */
+ { 25, 24, 23, 16}, /*MCS13 MCS12 MCS11 MCS4 */
+ { 26, 25, 24, 23}, /*MCS14 MCS13 MCS12 MCS11 */
+ { 27, 26, 25, 24}, /*MCS15 MCS14 MCS13 MCS12 */
+ { 0, 27, 26, 25}, /*0 MCS15 MCS14 MCS13 */
+ { 0, 29, 27, 26}, /*0 MCS15SG MCS15 MCS14 */
+ { 0, 0, 0, 28}, /*0 0 0 MCS14SG*/
+ { 0, 0, 0, 29} /*0 0 0 MCS15SG*/
+ };
+
+const u8_t zcHtOneTxStreamRateTable[15][4] =
+ { /*[5G 20MHz] [5G 40MHz] [2.4G 20MHz] [2.4G 40MHz]*/
+ { 4, 4, 0, 0}, /*OFDM6M OFDM6M CCK1M CCK1M */
+ { 5, 5, 1, 1}, /*OFDM9M OFDM9M CCK2M CCK2M */
+ { 13, 12, 2, 2}, /*MCS1 MCS0 CCK5M CCK5M */
+ { 14, 13, 3, 3}, /*MCS2 MCS1 CCK11M CCK11M */
+ { 15, 14, 13, 12}, /*MCS3 MCS2 MCS1 MCS0 */
+ { 16, 15, 14, 13}, /*MCS4 MCS3 MCS2 MCS1 */
+ { 17, 16, 15, 14}, /*MCS5 MCS4 MCS3 MCS2 */
+ { 18, 17, 16, 15}, /*MCS6 MCS5 MCS4 MCS3 */
+ { 19, 18, 17, 16}, /*MCS7 MCS6 MCS5 MCS4 */
+ { 0, 19, 18, 17}, /*0 MCS7 MCS6 MCS5 */
+ { 0, 30, 19, 18}, /*0 MCS7SG MCS7 MCS6 */
+ { 0, 0, 0, 19}, /*0 0 0 MCS7 */
+ { 0, 0, 0, 30}, /*0 0 0 MCS7SG */
+ { 0, 0, 0, 0 }, /*0 0 0 0 */
+ { 0, 0, 0, 0 } /*0 0 0 0 */
+ };
+
+const u16_t zcRate[] =
+ {
+ 1, 2, 5, 11, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
+ 6, 9, 12, 18, /* 6M 9M 12M 18M , 4 5 6 7*/
+ 24, 36, 48, 54, /* 24M 36M 48M 54M , 8 9 10 11*/
+ 13, 27, 40, 54, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
+ 81, 108, 121, 135, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
+ 27, 54, 81, 108, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
+ 162, 216, 243, 270, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
+ 270, 300, 150 /* MCS14SG, MCS15SG, MCS7SG , 28 29 30*/
+ };
+
+const u16_t PERThreshold[] =
+ {
+ 100, 50, 50, 50, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
+ 50, 50, 30, 30, /* 6M 9M 12M 18M , 4 5 6 7*/
+ 25, 25, 25, 20, /* 24M 36M 48M 54M , 8 9 10 11*/
+ 50, 50, 50, 40, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
+ 30, 30, 30, 30, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
+ 30, 30, 25, 25, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
+ 25, 25, 15, 15, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
+ 15, 15, 10 /* MCS14SG, MCS15SG , 28 29*/
+ };
+
+const u16_t FailDiff[] =
+ {
+ 40, 46, 40, 0, /* 1M, 2M, 5M, 11M , 0 1 2 3*/
+ 24, 17, 22, 16, /* 6M 9M 12M 18M , 4 5 6 7*/
+ 19, 13, 5, 0, /* 24M 36M 48M 54M , 8 9 10 11*/
+ 36, 22, 15, 19, /* MCS0 MCS1 MCS2 MCS3 , 12 13 14 15*/
+ 12, 5, 4, 7, /* MCS4 MCS5 MCS6 MCS7 , 16 17 18 19*/
+ 0, 0, 0, 0, /* MCS8 MCS9 MCS10 MCS11 , 20 21 22 23*/
+ 9, 4, 3, 3, /* MCS12 MCS13 MCS14 MCS15 , 24 25 26 27*/
+ 3, 0, 0 /* MCS14SG, MCS15SG , 28 29*/
+ };
+
+
+#ifdef ZM_ENABLE_BA_RATECTRL
+u32_t TxMPDU[29];
+u32_t BAFail[29];
+u32_t BAPER[29];
+const u16_t BADiff[] =
+ {
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 361, 220, 151, 187,
+ 122, 48, 41, 65,
+ 0, 0, 0, 0,
+ 88, 33, 27, 25,
+ 0
+ };
+#endif
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlInitCell */
+/* Initialize rate control cell. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* type : 0=>11b, 1=>11a/g, 2=>11n, 3=>11n one Tx stream */
+/* gBand : 1=>2.4G, 0=>5G */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+void zfRateCtrlInitCell(zdev_t* dev, struct zsRcCell* rcCell, u8_t type,
+ u8_t gBand, u8_t SG40)
+{
+ u8_t i;
+ u8_t maxrate;
+ zmw_get_wlan_dev(dev);
+
+ if (SG40) SG40 = 1;
+
+ if (gBand != 0)
+ {
+ if (type == 1) //11g
+ {
+ for (i=0; i<4; i++) //1M 2M 5M 11M
+ {
+ rcCell->operationRateSet[i] = (u8_t)i;
+ }
+ for (i=4; i<10; i++) //12M 18M 24M 36M 48M 54M
+ {
+ rcCell->operationRateSet[i] = 2+i;
+ }
+ rcCell->operationRateCount = 10;
+ rcCell->currentRateIndex = 5; //18M
+ }
+ else if (type == 2) //11ng
+ {
+ if (wd->wlanMode == ZM_MODE_AP) //AP 11ng 40M
+ {
+ for (i=0; i<15; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtRateTable[i][3];
+ }
+ if(!SG40) rcCell->operationRateSet[13] = 27;
+ rcCell->operationRateCount = 14+SG40;
+ rcCell->currentRateIndex = 10;
+ }
+ else //STA
+ {
+ if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M
+ {
+ for (i=0; i<15; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtRateTable[i][3];
+ }
+ if(!SG40) rcCell->operationRateSet[13] = 27;
+ rcCell->operationRateCount = 14+SG40;
+ rcCell->currentRateIndex = 10;
+ }
+ else //11ng 20M
+ {
+ for (i=0; i<13; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtRateTable[i][2];
+ }
+ rcCell->operationRateCount = 13;
+ rcCell->currentRateIndex = 9;
+ }
+ }
+ }
+ else if (type == 3) //11ng one Tx stream
+ {
+ if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11ng 40M one Tx stream
+ {
+ if(SG40 != 0)
+ {
+ maxrate = 13;
+ }
+ else
+ {
+ maxrate = 12;
+ }
+ for (i=0; i<maxrate; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][3];
+ }
+ rcCell->operationRateCount = i;
+ rcCell->currentRateIndex = ((i+1)*3)/4;
+ }
+ else //11ng 20M
+ {
+ for (i=0; i<11; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][2];
+ }
+ rcCell->operationRateCount = i;
+ rcCell->currentRateIndex = ((i+1)*3)/4;
+ }
+ }
+ else //if (type == 0) //11b
+ {
+ for (i=0; i<4; i++)
+ {
+ rcCell->operationRateSet[i] = (u8_t)i;
+ }
+ rcCell->operationRateCount = 4;
+ rcCell->currentRateIndex = rcCell->operationRateCount-1;
+ }
+ }
+ else
+ {
+ if (type == 2) //11na
+ {
+ if (wd->wlanMode == ZM_MODE_AP) //AP 11na 40M
+ {
+ for (i=0; i<(12+SG40); i++)
+ {
+ rcCell->operationRateSet[i] = zcHtRateTable[i][1];
+ }
+ rcCell->operationRateCount = 12+SG40;
+ rcCell->currentRateIndex = 8;
+ }
+ else //STA
+ {
+ if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M
+ {
+ for (i=0; i<(12+SG40); i++)
+ {
+ rcCell->operationRateSet[i] = zcHtRateTable[i][1];
+ }
+ rcCell->operationRateCount = 12+SG40;
+ rcCell->currentRateIndex = 8;
+ }
+ else //11na 20M
+ {
+ for (i=0; i<11; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtRateTable[i][0];
+ }
+ rcCell->operationRateCount = 11;
+ rcCell->currentRateIndex = 7;
+ }
+ }
+ }
+ else if (type == 3) //11na one Tx stream
+ {
+ if (wd->sta.htCtrlBandwidth == ZM_BANDWIDTH_40MHZ) //11na 40M one Tx stream
+ {
+ if(SG40 != 0)
+ {
+ maxrate = 11;
+ }
+ else
+ {
+ maxrate = 10;
+ }
+ for (i=0; i<maxrate; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][1];
+ }
+ rcCell->operationRateCount = i;
+ rcCell->currentRateIndex = ((i+1)*3)/4;
+ }
+ else //11ng 20M
+ {
+ for (i=0; i<9; i++)
+ {
+ rcCell->operationRateSet[i] = zcHtOneTxStreamRateTable[i][0];
+ }
+ rcCell->operationRateCount = i;
+ rcCell->currentRateIndex = ((i+1)*3)/4;
+ }
+ }
+ else //if (type == 1) //11a
+ {
+ for (i=0; i<8; i++) //6M 9M 12M 18M 24M 36M 48M 54M
+ {
+ rcCell->operationRateSet[i] = i+4;
+ }
+ rcCell->operationRateCount = 8;
+ rcCell->currentRateIndex = 4; //24M
+ }
+ }
+
+ rcCell->flag = 0;
+ rcCell->txCount = 0;
+ rcCell->failCount = 0;
+ rcCell->currentRate = rcCell->operationRateSet[rcCell->currentRateIndex];
+ rcCell->lasttxCount = 0;
+ rcCell->lastTime = wd->tick;
+ rcCell->probingTime = wd->tick;
+ for (i=0; i<ZM_RATE_TABLE_SIZE; i++) {
+ wd->PER[i] = 0;
+ wd->txMPDU[i] = wd->txFail[i] = 0;
+ }
+ wd->probeCount = 0;
+ wd->probeInterval = 0;
+#ifdef ZM_ENABLE_BA_RATECTRL
+ for (i=0; i<29; i++) {
+ TxMPDU[i]=0;
+ BAFail[i]=0;
+ BAPER[i]=0;
+ }
+#endif
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlGetHigherRate */
+/* Get a higher rate. */
+/* */
+/* INPUTS */
+/* rcCell : rate control cell */
+/* */
+/* OUTPUTS */
+/* rate */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+u8_t zfRateCtrlGetHigherRate(struct zsRcCell* rcCell)
+{
+ u8_t rateIndex;
+
+ rateIndex = rcCell->currentRateIndex
+ + (((rcCell->currentRateIndex+1) < rcCell->operationRateCount)?1:0);
+ return rcCell->operationRateSet[rateIndex];
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlNextLowerRate */
+/* Get a lower rate. */
+/* */
+/* INPUTS */
+/* rcCell : rate control cell */
+/* */
+/* OUTPUTS */
+/* rate */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+u8_t zfRateCtrlNextLowerRate(zdev_t* dev, struct zsRcCell* rcCell)
+{
+ zmw_get_wlan_dev(dev);
+ if (rcCell->currentRateIndex > 0)
+ {
+ rcCell->currentRateIndex--;
+ rcCell->currentRate = rcCell->operationRateSet[rcCell->currentRateIndex];
+ }
+ zm_msg1_tx(ZM_LV_0, "Lower Tx Rate=", rcCell->currentRate);
+ //DbgPrint("Lower Tx Rate=%d", rcCell->currentRate);
+ rcCell->failCount = rcCell->txCount = 0;
+ rcCell->lasttxCount = 0;
+ rcCell->lastTime = wd->tick;
+ return rcCell->currentRate;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlRateDiff */
+/* Rate difference. */
+/* */
+/* INPUTS */
+/* rcCell : rate control cell */
+/* retryRate : retry rate */
+/* */
+/* OUTPUTS */
+/* rate difference */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+u8_t zfRateCtrlRateDiff(struct zsRcCell* rcCell, u8_t retryRate)
+{
+ u16_t i;
+
+ /* Find retryRate in operationRateSet[] */
+ for (i=0; i<rcCell->operationRateCount; i++)
+ {
+ if (retryRate == rcCell->operationRateSet[i])
+ {
+ if (i < rcCell->currentRateIndex)
+ {
+ return ((rcCell->currentRateIndex - i)+1)>>1;
+ }
+ else if (i == rcCell->currentRateIndex == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ /* TODO : retry rate not in operation rate set */
+ zm_msg1_tx(ZM_LV_0, "Not in operation rate set:", retryRate);
+ return 1;
+
+}
+
+u32_t zfRateCtrlUDPTP(zdev_t* dev, u16_t Rate, u32_t PER) {
+ if ((PER < 100) && (Rate > 0) && PER)
+ return 1168000/(((12304/Rate)+197)*(100+100*PER/(100-PER)));
+ else
+ return 0;
+}
+
+u8_t zfRateCtrlFindMaxUDPTP(zdev_t* dev, struct zsRcCell* rcCell) {
+ u8_t i, maxIndex=0, rateIndex;
+ u32_t max=0, UDPThroughput;
+
+ zmw_get_wlan_dev(dev);
+
+ rateIndex = zm_agg_min(rcCell->currentRateIndex+3, rcCell->operationRateCount-1);
+ for (i=rcCell->currentRateIndex; i < rateIndex; i++) {
+ UDPThroughput = zfRateCtrlUDPTP(dev, zcRate[rcCell->operationRateSet[i]],
+ wd->PER[rcCell->operationRateSet[i]]);
+ if (max < UDPThroughput) {
+ max = UDPThroughput;
+ maxIndex = i;
+ }
+ }
+
+ return rcCell->operationRateSet[maxIndex];
+}
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlGetTxRate */
+/* Get transmission rate. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* rcCell : rate control cell */
+/* probing : rate probing flag */
+/* */
+/* OUTPUTS */
+/* Tx rate */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+u16_t zfRateCtrlGetTxRate(zdev_t* dev, struct zsRcCell* rcCell, u16_t* probing)
+{
+ u8_t newRate, highRate;
+ zmw_get_wlan_dev(dev);
+
+ zm_msg1_tx(ZM_LV_3, "txCount=", rcCell->txCount);
+ zm_msg1_tx(ZM_LV_3, "probingTime=", rcCell->probingTime);
+ zm_msg1_tx(ZM_LV_3, "tick=", wd->tick);
+ *probing = 0;
+ newRate = rcCell->currentRate;
+
+ if (wd->probeCount && (wd->probeCount < wd->success_probing))
+ {
+ if (wd->probeInterval < 50)
+ {
+ wd->probeInterval++;
+ }
+ else
+ {
+ wd->probeInterval++;
+ if (wd->probeInterval > 52) //probe 51, 52, 53 three packets every 50 packets
+ {
+ wd->probeInterval = 0;
+ }
+ newRate=zfRateCtrlGetHigherRate(rcCell);
+ *probing = 1;
+ wd->probeCount++;
+ rcCell->probingTime = wd->tick;
+ }
+ }
+ /* Accumulate at least 1000ms and 8 packets or Accumulate over 1K packets */
+ else if ((((wd->tick - rcCell->probingTime) > (ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK))
+ && (rcCell->txCount >= ZM_RATE_CTRL_MIN_PROBING_PACKET))
+ || (rcCell->txCount >= 1000))
+ {
+#ifndef ZM_DISABLE_RATE_CTRL
+ /* PER = fail/total */
+ wd->probeCount = 0;
+ wd->probeSuccessCount = 0;
+ if (wd->txMPDU[rcCell->currentRate] != 0) {
+ wd->PER[rcCell->currentRate] = zm_agg_min(100,
+ (wd->txFail[rcCell->currentRate]*100)/wd->txMPDU[rcCell->currentRate]);
+ if (!wd->PER[rcCell->currentRate]) wd->PER[rcCell->currentRate] ++;
+ }
+
+ /* if PER < threshold, do rate probing, return probing rate */
+ if ((wd->PER[rcCell->currentRate] <= (ZM_RATE_PROBING_THRESHOLD+15)) ||
+ ((rcCell->currentRate <= 16) &&
+ ((wd->PER[rcCell->currentRate]/2) <= ZM_RATE_PROBING_THRESHOLD)))
+ {
+ if ((newRate=zfRateCtrlGetHigherRate(rcCell)) != rcCell->currentRate)
+ {
+ *probing = 1;
+ wd->probeCount++;
+ wd->probeInterval = 0;
+ wd->success_probing =
+ (rcCell->currentRate <= 16)? (ZM_RATE_SUCCESS_PROBING/2) : ZM_RATE_SUCCESS_PROBING;
+ //DbgPrint("Start Probing");
+ zm_msg1_tx(ZM_LV_0, "Probing Rate=", newRate);
+ }
+ }
+#endif
+
+ zm_msg0_tx(ZM_LV_1, "Diminish counter");
+ rcCell->failCount = rcCell->failCount>>1;
+ rcCell->txCount = rcCell->txCount>>1;
+ wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
+ wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
+
+
+ if (rcCell->currentRate > 15) {
+ highRate = zfRateCtrlGetHigherRate(rcCell);
+ if ((highRate != rcCell->currentRate) && wd->PER[highRate] &&
+ ((wd->PER[rcCell->currentRate] + FailDiff[rcCell->currentRate]) >
+ wd->PER[highRate])) {
+ //DbgPrint("PER compare force raise rate to %d", highRate);
+ wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
+ zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
+ }
+ }
+ else {
+ highRate = zfRateCtrlFindMaxUDPTP(dev, rcCell);
+ if (rcCell->currentRate < highRate) {
+ //DbgPrint("UDP Throughput compare force raise rate to %d", highRate);
+ wd->probeSuccessCount = wd->probeCount = ZM_RATE_SUCCESS_PROBING;
+ zfRateCtrlTxSuccessEvent(dev, rcCell, highRate);
+ }
+ }
+ rcCell->probingTime = wd->tick;
+ }
+
+ if( (wd->tick > 1000)
+ && ((wd->tick - rcCell->lastTime) > 3840) )
+ {
+ if (rcCell->lasttxCount < 70)
+ {
+ rcCell->failCount = rcCell->failCount>>1;
+ rcCell->txCount = rcCell->txCount>>1;
+ wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
+ wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
+
+ rcCell->failCount = (rcCell->failCount < rcCell->txCount)?
+ rcCell->failCount : rcCell->txCount;
+ wd->txFail[rcCell->currentRate] = (wd->txFail[rcCell->currentRate] < wd->txMPDU[rcCell->currentRate])?
+ wd->txFail[rcCell->currentRate] : wd->txMPDU[rcCell->currentRate];
+ }
+
+ rcCell->lastTime = wd->tick;
+ rcCell->lasttxCount = 0;
+ }
+
+ rcCell->txCount++;
+ rcCell->lasttxCount++;
+ wd->txMPDU[rcCell->currentRate]++;
+ zm_msg1_tx(ZM_LV_1, "Get Tx Rate=", newRate);
+ return newRate;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlTxFailEvent */
+/* Tx fail event. Calculate PER and lower Tx rate if under */
+/* PER under threshold. */
+/* */
+/* INPUTS */
+/* rcCell : rate control cell */
+/* retryRate : retry rate */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+void zfRateCtrlTxFailEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t aggRate, u32_t retryRate)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+#ifndef ZM_DISABLE_RATE_CTRL
+ //DbgPrint("aggRate=%d, retryRate=%d", aggRate, retryRate);
+ if (aggRate && (aggRate != rcCell->currentRate)) {
+ wd->txFail[aggRate] += retryRate;
+ return;
+ }
+
+ if (!aggRate) {
+ retryRate = (zfRateCtrlRateDiff(rcCell, (u8_t)retryRate)+1)>>1;
+ if (rcCell->currentRate <12) //legacy rate
+ {
+ retryRate*=2;
+ }
+ }
+ rcCell->failCount += retryRate;
+ wd->txFail[rcCell->currentRate] += retryRate;
+
+ //DbgPrint("failCount=%d", rcCell->failCount);
+ if (rcCell->failCount > ZM_MIN_RATE_FAIL_COUNT)
+ {
+ if (wd->txMPDU[rcCell->currentRate] != 0) {
+ wd->PER[rcCell->currentRate] = zm_agg_min(100,
+ (wd->txFail[rcCell->currentRate]*100)/wd->txMPDU[rcCell->currentRate]);
+ if (!wd->PER[rcCell->currentRate]) wd->PER[rcCell->currentRate] ++;
+ }
+ //zm_msg1_tx(ZM_LV_1, "PER=", per);
+ //DbgPrint("PER=%d, txFail=%d, txMPDU=%d", wd->PER[rcCell->currentRate], wd->txFail[rcCell->currentRate], wd->txMPDU[rcCell->currentRate]);
+ if (wd->PER[rcCell->currentRate] > PERThreshold[rcCell->currentRate])
+ {
+ /* Lower Tx Rate if PER < THRESHOLD */
+ zfRateCtrlNextLowerRate(dev, rcCell);
+ rcCell->flag |= ZM_RC_TRAINED_BIT;
+
+ // Resolve compatibility problem with Marvell
+ if(rcCell->currentRate == 15)
+ {
+ zmw_leave_critical_section(dev);
+ zfHpSetAggPktNum(dev, 8);
+ zmw_enter_critical_section(dev);
+ }
+
+ wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
+ wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
+
+ wd->probeCount = wd->probeSuccessCount = 0;
+ }
+ }
+
+#endif
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlTxSuccessEvent */
+/* Tx success event. Raise Tx rate because rate probing success. */
+/* */
+/* INPUTS */
+/* rcCell : rate control cell */
+/* successRate : success rate */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+void zfRateCtrlTxSuccessEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t successRate)
+{
+ /* Raise Tx Rate */
+ u16_t i, PERProbe;
+ u16_t pcount;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ //DbgPrint("Probing successRate=%d", successRate);
+ /* Find successRate in operationRateSet[] */
+ wd->probeSuccessCount++;
+ if (wd->probeCount < wd->success_probing)
+ {
+ return;
+ }
+
+ pcount = wd->probeCount;
+ if (pcount != 0)
+ {
+ PERProbe = wd->probeSuccessCount * 100 / pcount;
+ }
+ else
+ {
+ PERProbe = 1;
+ }
+
+ if (PERProbe < ((rcCell->currentRate < 16)? 80:100))
+ {
+ return;
+ }
+ //DbgPrint("wd->probeCount=%d, wd->probeSuccessCount=%d", wd->probeCount, wd->probeSuccessCount);
+ wd->probeCount = wd->probeSuccessCount = 0;
+ for (i=0; i<rcCell->operationRateCount; i++)
+ {
+ if (successRate == rcCell->operationRateSet[i])
+ {
+ if (i > rcCell->currentRateIndex)
+ {
+ /* Raise current Tx rate */
+ zm_msg1_tx(ZM_LV_0, "Raise Tx Rate=", successRate);
+ //DbgPrint("Raise Tx Rate=%d", successRate);
+
+ // Resolve compatibility problem with Marvell
+ if((rcCell->currentRate <= 15) && (successRate > 15))
+ {
+ zmw_leave_critical_section(dev);
+ zfHpSetAggPktNum(dev, 16);
+ zmw_enter_critical_section(dev);
+ }
+
+ rcCell->currentRate = successRate;
+ rcCell->currentRateIndex = (u8_t)i;
+ rcCell->failCount = rcCell->txCount = 0;
+ rcCell->lasttxCount = 0;
+ rcCell->lastTime = wd->tick;
+ wd->txFail[rcCell->currentRate] = wd->txFail[rcCell->currentRate] >> 1;
+ wd->txMPDU[rcCell->currentRate] = wd->txMPDU[rcCell->currentRate] >> 1;
+ }
+ }
+ }
+
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfRateCtrlRxRssiEvent */
+/* Rx RSSI event. Calculate RSSI moving average, accelarate */
+/* rate probing if RSSI variation over threshold. */
+/* */
+/* INPUTS */
+/* rcCell : rate control cell */
+/* successRate : success rate */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+void zfRateCtrlRxRssiEvent(struct zsRcCell* rcCell, u16_t rxRssi)
+{
+ /* if delta(rcCell->rxRssi, rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION */
+ if ((rcCell->rxRssi - rxRssi) > ZM_RATE_CTRL_RSSI_VARIATION)
+ {
+ /* Accelerate rate probing via decreaing rcCell->probingTime */
+ rcCell->probingTime -= ZM_RATE_CTRL_PROBING_INTERVAL_MS/ZM_MS_PER_TICK;
+ }
+
+ /* Update RSSI moving average */
+ rcCell->rxRssi = (((rcCell->rxRssi*7) + rxRssi)+4) >> 3;
+ return;
+}
+
+
+#ifdef ZM_ENABLE_BA_RATECTRL
+u8_t HigherRate(u8_t Rate) {
+ if (Rate < 28) Rate++; //28=MCS15SG, 27=MCS15, 26=MCS14, 25=MCS13
+ if (Rate > 28) Rate = 28;
+ while ((Rate >= 20) && (Rate <= 23)) {
+ Rate ++;
+ }
+ return Rate;
+}
+
+u8_t LowerRate(u8_t Rate) {
+ if (Rate > 1) Rate--;
+ while ((Rate >= 20) && (Rate <= 23)) {
+ Rate --;
+ }
+ return Rate;
+}
+
+u8_t RateMapToRateIndex(u8_t Rate, struct zsRcCell* rcCell) {
+ u8_t i;
+ for (i=0; i<rcCell->operationRateCount; i++) {
+ if (Rate == rcCell->operationRateSet[i]) {
+ return i;
+ }
+ }
+ return 0;
+}
+
+void zfRateCtrlAggrSta(zdev_t* dev) {
+ u8_t RateIndex, Rate;
+ u8_t HRate;
+ u8_t LRate;
+ u32_t RateCtrlTxMPDU, RateCtrlBAFail;
+ zmw_get_wlan_dev(dev);
+
+ RateIndex = wd->sta.oppositeInfo[0].rcCell.currentRateIndex;
+ Rate = wd->sta.oppositeInfo[0].rcCell.operationRateSet[RateIndex];
+
+ TxMPDU[Rate] = (TxMPDU[Rate] / 5) + (wd->commTally.RateCtrlTxMPDU * 4 / 5);
+ BAFail[Rate] = (BAFail[Rate] / 5) + (wd->commTally.RateCtrlBAFail * 4 / 5);
+ RateCtrlTxMPDU = wd->commTally.RateCtrlTxMPDU;
+ RateCtrlBAFail = wd->commTally.RateCtrlBAFail;
+ wd->commTally.RateCtrlTxMPDU = 0;
+ wd->commTally.RateCtrlBAFail = 0;
+ if (TxMPDU[Rate] > 0) {
+ BAPER[Rate] = BAFail[Rate] * 1000 / TxMPDU[Rate]; //PER*1000
+ BAPER[Rate] = (BAPER[Rate]>0)? BAPER[Rate]:1;
+ }
+ else {
+ return;
+ }
+
+ HRate = HigherRate(Rate);
+ LRate = LowerRate(Rate);
+ if (BAPER[Rate]>200) {
+ if ((RateCtrlTxMPDU > 100) && (BAPER[Rate]<300) && (HRate != Rate) && BAPER[HRate] &&
+ (BAPER[HRate] < BAPER[Rate] + BADiff[Rate])) {
+ Rate = HRate;
+ //DbgPrint("Rate improved to %d", Rate);
+ }
+ else {
+ Rate = LRate;
+ //DbgPrint("Rate decreased to %d", Rate);
+ }
+ }
+ else if (BAPER[Rate] && BAPER[Rate]<100) {
+ if (RateCtrlTxMPDU > 100) {
+ Rate = HRate;
+ //DbgPrint("Rate improved to %d", Rate);
+ }
+ }
+ wd->sta.oppositeInfo[0].rcCell.currentRate = Rate;
+ wd->sta.oppositeInfo[0].rcCell.currentRateIndex = RateMapToRateIndex(Rate, &wd->sta.oppositeInfo[0].rcCell);
+}
+#endif
diff --git a/drivers/staging/otus/80211core/ratectrl.h b/drivers/staging/otus/80211core/ratectrl.h
new file mode 100644
index 000000000000..92411d725cd8
--- /dev/null
+++ b/drivers/staging/otus/80211core/ratectrl.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _RATECTRL_H
+#define _RATECTRL_H
+
+#define ZM_RATE_CTRL_PROBING_INTERVAL_MS 1000 //1000ms
+#define ZM_RATE_CTRL_MIN_PROBING_PACKET 8
+
+#define ZM_MIN_RATE_FAIL_COUNT 20
+
+#define ZM_RATE_PROBING_THRESHOLD 15 //6%
+#define ZM_RATE_SUCCESS_PROBING 10
+
+#define ZM_RATE_CTRL_RSSI_VARIATION 5 //TBD
+
+extern const u32_t zcRateToPhyCtrl[];
+
+extern void zfRateCtrlInitCell(zdev_t* dev, struct zsRcCell* rcCell, u8_t type, u8_t gBand, u8_t SG40);
+extern u16_t zfRateCtrlGetTxRate(zdev_t* dev, struct zsRcCell* rcCell, u16_t* probing);
+extern void zfRateCtrlTxFailEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t aggRate, u32_t retryRate);
+extern void zfRateCtrlTxSuccessEvent(zdev_t* dev, struct zsRcCell* rcCell, u8_t successRate);
+extern void zfRateCtrlAggrSta(zdev_t* dev);
+#endif
diff --git a/drivers/staging/otus/80211core/struct.h b/drivers/staging/otus/80211core/struct.h
new file mode 100644
index 000000000000..17b5ce37ebb5
--- /dev/null
+++ b/drivers/staging/otus/80211core/struct.h
@@ -0,0 +1,1315 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _STRUCT_H
+#define _STRUCT_H
+
+#include "../oal_marc.h"
+
+#define ZM_SW_LOOP_BACK 0 /* 1=>enable, 0=>disable */
+#define ZM_PCI_LOOP_BACK 0 /* 1=>enable, 0=>disable */
+#define ZM_PROTOCOL_RESPONSE_SIMULATION 0
+
+#define ZM_RX_FRAME_SIZE 1600
+
+extern const u8_t zg11bRateTbl[4];
+extern const u8_t zg11gRateTbl[8];
+
+#define ZM_DRIVER_CORE_MAJOR_VERSION 1
+#define ZM_DRIVER_CORE_MINOR_VERSION 1
+#define ZM_DRIVER_CORE_BRANCH_MAJOR_VERSION 3
+#define ZM_DRIVER_CORE_BRANCH_MINOR_VERSION 39
+
+#ifndef ZM_VTXQ_SIZE
+#define ZM_VTXQ_SIZE 1024 //2^N
+#endif
+
+#define ZM_VTXQ_SIZE_MASK (ZM_VTXQ_SIZE-1)
+#define ZM_VMMQ_SIZE 8 //2^N
+#define ZM_VMMQ_SIZE_MASK (ZM_VMMQ_SIZE-1)
+
+#include "cagg.h"
+
+#define ZM_AGG_POOL_SIZE 20
+#define ZM_RATE_TABLE_SIZE 32
+
+#define ZM_MAX_BUF_DISCRETE_NUMBER 5
+
+
+
+
+
+
+
+
+
+/**********************************************************************************/
+/* IBSS macros */
+/**********************************************************************************/
+#define ZM_IBSS_PEER_ALIVE_COUNTER 4
+
+/**********************************************************************************/
+/* BIT mapping related macros */
+/**********************************************************************************/
+
+#define ZM_BIT_0 0x1
+#define ZM_BIT_1 0x2
+#define ZM_BIT_2 0x4
+#define ZM_BIT_3 0x8
+#define ZM_BIT_4 0x10
+#define ZM_BIT_5 0x20
+#define ZM_BIT_6 0x40
+#define ZM_BIT_7 0x80
+#define ZM_BIT_8 0x100
+#define ZM_BIT_9 0x200
+#define ZM_BIT_10 0x400
+#define ZM_BIT_11 0x800
+#define ZM_BIT_12 0x1000
+#define ZM_BIT_13 0x2000
+#define ZM_BIT_14 0x4000
+#define ZM_BIT_15 0x8000
+#define ZM_BIT_16 0x10000
+#define ZM_BIT_17 0x20000
+#define ZM_BIT_18 0x40000
+#define ZM_BIT_19 0x80000
+#define ZM_BIT_20 0x100000
+#define ZM_BIT_21 0x200000
+#define ZM_BIT_22 0x400000
+#define ZM_BIT_23 0x800000
+#define ZM_BIT_24 0x1000000
+#define ZM_BIT_25 0x2000000
+#define ZM_BIT_26 0x4000000
+#define ZM_BIT_27 0x8000000
+#define ZM_BIT_28 0x10000000
+#define ZM_BIT_29 0x20000000 //WPA support
+#define ZM_BIT_30 0x40000000
+#define ZM_BIT_31 0x80000000
+
+
+/**********************************************************************************/
+/* MAC address related macros */
+/**********************************************************************************/
+#define ZM_MAC_BYTE_TO_WORD(macb, macw) macw[0] = macb[0] + (macb[1] << 8); \
+ macw[1] = macb[2] + (macb[3] << 8); \
+ macw[2] = macb[4] + (macb[5] << 8);
+
+#define ZM_MAC_WORD_TO_BYTE(macw, macb) macb[0] = (u8_t) (macw[0] & 0xff); \
+ macb[1] = (u8_t) (macw[0] >> 8); \
+ macb[2] = (u8_t) (macw[1] & 0xff); \
+ macb[3] = (u8_t) (macw[1] >> 8); \
+ macb[4] = (u8_t) (macw[2] & 0xff); \
+ macb[5] = (u8_t) (macw[2] >> 8);
+
+#define ZM_MAC_0(macw) ((u8_t)(macw[0] & 0xff))
+#define ZM_MAC_1(macw) ((u8_t)(macw[0] >> 8))
+#define ZM_MAC_2(macw) ((u8_t)(macw[1] & 0xff))
+#define ZM_MAC_3(macw) ((u8_t)(macw[1] >> 8))
+#define ZM_MAC_4(macw) ((u8_t)(macw[2] & 0xff))
+#define ZM_MAC_5(macw) ((u8_t)(macw[2] >> 8))
+
+#define ZM_IS_MULTICAST_OR_BROADCAST(mac) (mac[0] & 0x01)
+#define ZM_IS_MULTICAST(mac) ((mac[0] & 0x01) && (((u8_t)mac[0]) != 0xFF))
+
+#define ZM_MAC_EQUAL(mac1, mac2) ((mac1[0]==mac2[0])&&(mac1[1]==mac2[1])&&(mac1[2]==mac2[2]))
+#define ZM_MAC_NOT_EQUAL(mac1, mac2) ((mac1[0]!=mac2[0])||(mac1[1]!=mac2[1])||(mac1[2]!=mac2[2]))
+/**********************************************************************************/
+/* MAC address related mac'ros (end) */
+/**********************************************************************************/
+#define ZM_BYTE_TO_WORD(A, B) ((A<<8)+B)
+#define ZM_ROL32( A, n ) \
+ ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
+#define ZM_ROR32( A, n ) ZM_ROL32( (A), 32-(n) )
+#define ZM_LO8(v16) ((u8_t)((v16) & 0xFF))
+#define ZM_HI8(v16) ((u8_t)(((v16)>>8)&0xFF))
+
+#ifdef ZM_ENABLE_BUFFER_TRACE
+extern void zfwBufTrace(zdev_t* dev, zbuf_t *buf, u8_t *functionName);
+#define ZM_BUFFER_TRACE(dev, buf) zfwBufTrace(dev, buf, __func__);
+#else
+#define ZM_BUFFER_TRACE(dev, buf)
+#endif
+
+/* notification events to heart beat function */
+#define ZM_BSSID_LIST_SCAN 0x01
+
+/* CAM mode */
+#define ZM_CAM_AP 0x1
+#define ZM_CAM_STA 0x2
+#define ZM_CAM_HOST 0x4
+
+/* finite state machine for adapter */
+#define ZM_STA_STATE_DISCONNECT 1
+#define ZM_STA_STATE_CONNECTING 2
+#define ZM_STA_STATE_CONNECTED 3
+
+/* Event definitions for finite state machine */
+#define ZM_EVENT_TIMEOUT_SCAN 0x0000
+#define ZM_EVENT_TIMEOUT_BG_SCAN 0x0001
+#define ZN_EVENT_TIMEOUT_RECONNECT 0x0002
+#define ZM_EVENT_TIMEOUT_INIT_SCAN 0x0003
+#define ZM_EVENT_TIMEOUT_AUTH 0x0004
+#define ZM_EVENT_TIMEOUT_ASSO 0x0005
+#define ZM_EVENT_TIMEOUT_AUTO_SCAN 0x0006
+#define ZM_EVENT_TIMEOUT_MIC_FAIL 0x0007
+#define ZM_EVENT_TIMEOUT_CHECK_AP 0x0008
+#define ZM_EVENT_CONNECT 0x0009
+#define ZM_EVENT_INIT_SCAN 0x000a
+#define ZM_EVENT_SCAN 0x000b
+#define ZM_EVENT_BG_SCAN 0x000c
+#define ZM_EVENT_DISCONNECT 0x000d
+#define ZM_EVENT_WPA_MIC_FAIL 0x000e
+#define ZM_EVENT_AP_ALIVE 0x000f
+#define ZM_EVENT_CHANGE_TO_AP 0x0010
+#define ZM_EVENT_CHANGE_TO_STA 0x0011
+#define ZM_EVENT_IDLE 0x0012
+#define ZM_EVENT_AUTH 0x0013
+#define ZM_EVENT_ASSO_RSP 0x0014
+#define ZM_EVENT_WPA_PK_OK 0x0015
+#define ZM_EVENT_WPA_GK_OK 0x0016
+#define ZM_EVENT_RCV_BEACON 0x0017
+#define ZM_EVENT_RCV_PROBE_RSP 0x0018
+#define ZM_EVENT_SEND_DATA 0x0019
+#define ZM_EVENT_AUTO_SCAN 0x001a
+#define ZM_EVENT_MIC_FAIL1 0x001d
+#define ZM_EVENT_MIC_FAIL2 0x001e
+#define ZM_EVENT_IBSS_MONITOR 0x001f
+#define ZM_EVENT_IN_SCAN 0x0020
+#define ZM_EVENT_CM_TIMER 0x0021
+#define ZM_EVENT_CM_DISCONNECT 0x0022
+#define ZM_EVENT_CM_BLOCK_TIMER 0x0023
+#define ZM_EVENT_TIMEOUT_ADDBA 0x0024
+#define ZM_EVENT_TIMEOUT_PERFORMANCE 0x0025
+#define ZM_EVENT_SKIP_COUNTERMEASURE 0x0026
+#define ZM_EVENT_NONE 0xffff
+
+/* Actions after call finite state machine */
+#define ZM_ACTION_NONE 0x0000
+#define ZM_ACTION_QUEUE_DATA 0x0001
+#define ZM_ACTION_DROP_DATA 0x0002
+
+/* Timers for finite state machine */
+#define ZM_TICK_ZERO 0
+#define ZM_TICK_INIT_SCAN_END 8
+#define ZM_TICK_NEXT_BG_SCAN 50
+#define ZM_TICK_BG_SCAN_END 8
+#define ZM_TICK_AUTH_TIMEOUT 4
+#define ZM_TICK_ASSO_TIMEOUT 4
+#define ZM_TICK_AUTO_SCAN 300
+#define ZM_TICK_MIC_FAIL_TIMEOUT 6000
+#define ZM_TICK_CHECK_AP1 150
+#define ZM_TICK_CHECK_AP2 350
+#define ZM_TICK_CHECK_AP3 250
+#define ZM_TICK_IBSS_MONITOR 160
+#define ZM_TICK_IN_SCAN 4
+#define ZM_TICK_CM_TIMEOUT 6000
+#define ZM_TICK_CM_DISCONNECT 200
+#define ZM_TICK_CM_BLOCK_TIMEOUT 6000
+
+/* Fix bug#33338 Counter Measure Issur */
+#ifdef NDIS_CM_FOR_XP
+#define ZM_TICK_CM_TIMEOUT_OFFSET 2160
+#define ZM_TICK_CM_DISCONNECT_OFFSET 72
+#define ZM_TICK_CM_BLOCK_TIMEOUT_OFFSET 2160
+#else
+#define ZM_TICK_CM_TIMEOUT_OFFSET 0
+#define ZM_TICK_CM_DISCONNECT_OFFSET 0
+#define ZM_TICK_CM_BLOCK_TIMEOUT_OFFSET 0
+#endif
+
+#define ZM_TIME_ACTIVE_SCAN 30 //ms
+#define ZM_TIME_PASSIVE_SCAN 110 //ms
+
+/* finite state machine for BSS connect */
+#define ZM_STA_CONN_STATE_NONE 0
+#define ZM_STA_CONN_STATE_AUTH_OPEN 1
+#define ZM_STA_CONN_STATE_AUTH_SHARE_1 2
+#define ZM_STA_CONN_STATE_AUTH_SHARE_2 3
+#define ZM_STA_CONN_STATE_ASSOCIATE 4
+#define ZM_STA_CONN_STATE_SSID_NOT_FOUND 5
+#define ZM_STA_CONN_STATE_AUTH_COMPLETED 6
+
+/* finite state machine for WPA handshaking */
+#define ZM_STA_WPA_STATE_INIT 0
+#define ZM_STA_WPA_STATE_PK_OK 1
+#define ZM_STA_WPA_STATE_GK_OK 2
+
+/* various timers */
+#define ZM_INTERVAL_CONNECT_TIMEOUT 20 /* 200 milisecond */
+
+/* IBSS definitions */
+#define ZM_IBSS_PARTNER_LOST 0
+#define ZM_IBSS_PARTNER_ALIVE 1
+#define ZM_IBSS_PARTNER_CHECK 2
+
+#define ZM_BCMC_ARRAY_SIZE 16 /* Must be 2^N */
+#define ZM_UNI_ARRAY_SIZE 16 /* Must be 2^N */
+
+#define ZM_MAX_DEFRAG_ENTRIES 4 /* 2^N */
+#define ZM_DEFRAG_AGING_TIME_SEC 5 /* 5 seconds */
+
+#define ZM_MAX_WPAIE_SIZE 128
+/* WEP related definitions */
+#define ZM_USER_KEY_DEFAULT 64
+#define ZM_USER_KEY_PK 0 /* Pairwise Key */
+#define ZM_USER_KEY_GK 1 /* Group Key */
+/* AP WLAN Type */
+#define ZM_WLAN_TYPE_PURE_B 2
+#define ZM_WLAN_TYPE_PURE_G 1
+#define ZM_WLAN_TYPE_MIXED 0
+
+/* HAL State */
+#define ZM_HAL_STATE_INIT 0
+#define ZM_HAL_STATE_RUNNING 1
+
+/* AP Capability */
+#define ZM_All11N_AP 0x01
+#define ZM_XR_AP 0x02
+#define ZM_SuperG_AP 0x04
+
+/* MPDU Density */
+#define ZM_MPDU_DENSITY_NONE 0
+#define ZM_MPDU_DENSITY_1_8US 1
+#define ZM_MPDU_DENSITY_1_4US 2
+#define ZM_MPDU_DENSITY_1_2US 3
+#define ZM_MPDU_DENSITY_1US 4
+#define ZM_MPDU_DENSITY_2US 5
+#define ZM_MPDU_DENSITY_4US 6
+#define ZM_MPDU_DENSITY_8US 7
+
+/* Software Encryption */
+#define ZM_SW_TKIP_ENCRY_EN 0x01
+#define ZM_SW_TKIP_DECRY_EN 0x02
+#define ZM_SW_WEP_ENCRY_EN 0x04
+#define ZM_SW_WEP_DECRY_EN 0x08
+
+/* Default Support Rate */
+#define ZM_DEFAULT_SUPPORT_RATE_ZERO 0x0
+#define ZM_DEFAULT_SUPPORT_RATE_DISCONNECT 0x1
+#define ZM_DEFAULT_SUPPORT_RATE_IBSS_B 0x2
+#define ZM_DEFAULT_SUPPORT_RATE_IBSS_AG 0x3
+
+/* security related definitions */
+struct zsTkipSeed
+{
+ u8_t tk[32]; /* key */
+ u8_t ta[6];
+ u16_t ttak[5];
+ u16_t ppk[6];
+ u16_t iv16,iv16tmp;
+ u32_t iv32,iv32tmp;
+};
+
+struct zsMicVar
+{
+ u32_t k0, k1; // Key
+ u32_t left, right; // Current state
+ u32_t m; // Message accumulator (single word)
+ u16_t nBytes; // # bytes in M
+};
+
+struct zsDefragEntry
+{
+ u8_t fragCount;
+ u8_t addr[6];
+ u16_t seqNum;
+ zbuf_t* fragment[8];
+ u32_t tick;
+};
+
+struct zsDefragList
+{
+ struct zsDefragEntry defragEntry[ZM_MAX_DEFRAG_ENTRIES];
+ u8_t replaceNum;
+};
+
+#define ZM_MAX_OPPOSITE_COUNT 16
+#define ZM_MAX_TX_SAMPLES 15
+#define ZM_TX_RATE_DOWN_CRITERIA 80
+#define ZM_TX_RATE_UP_CRITERIA 200
+
+
+#define ZM_MAX_PROBE_HIDDEN_SSID_SIZE 2
+struct zsSsidList
+{
+ u8_t ssid[32];
+ u8_t ssidLen;
+};
+
+struct zsWrapperSetting
+{
+ u8_t bDesiredBssid;
+ u8_t desiredBssid[6];
+ u16_t bssid[3];
+ u8_t ssid[32];
+ u8_t ssidLen;
+ u8_t authMode;
+ u8_t wepStatus;
+ u8_t encryMode;
+ u8_t wlanMode;
+ u16_t frequency;
+ u16_t beaconInterval;
+ u8_t dtim;
+ u8_t preambleType;
+ u16_t atimWindow;
+
+ struct zsSsidList probingSsidList[ZM_MAX_PROBE_HIDDEN_SSID_SIZE];
+
+ u8_t dropUnencryptedPkts;
+ u8_t ibssJoinOnly;
+ u32_t adhocMode;
+ u8_t countryIsoName[4];
+ u16_t autoSetFrequency;
+
+ /* AP */
+ u8_t bRateBasic;
+ u8_t gRateBasic;
+ u32_t nRateBasic;
+ u8_t bgMode;
+
+ /* Common */
+ u8_t staWmeEnabled;
+ u8_t staWmeQosInfo;
+ u8_t apWmeEnabled;
+
+
+ /* rate information: added in the future */
+};
+
+struct zsWrapperFeatureCtrl
+{
+ u8_t bIbssGMode;
+};
+
+#define ZM_MAX_PS_STA 16
+#define ZM_PS_QUEUE_SIZE 32
+
+struct zsStaPSEntity
+{
+ u8_t bUsed;
+ u8_t macAddr[6];
+ u8_t bDataQueued;
+};
+
+struct zsStaPSList
+{
+ u8_t count;
+ struct zsStaPSEntity entity[ZM_MAX_PS_STA];
+};
+
+#define ZM_MAX_TIMER_COUNT 32
+
+/* double linked list */
+struct zsTimerEntry
+{
+ u16_t event;
+ u32_t timer;
+ struct zsTimerEntry *pre;
+ struct zsTimerEntry *next;
+};
+
+struct zsTimerList
+{
+ u8_t freeCount;
+ struct zsTimerEntry list[ZM_MAX_TIMER_COUNT];
+ struct zsTimerEntry *head;
+ struct zsTimerEntry *tail;
+};
+
+/* Multicast list */
+#define ZM_MAX_MULTICAST_LIST_SIZE 64
+
+struct zsMulticastAddr
+{
+ u8_t addr[6];
+};
+
+struct zsMulticastList
+{
+ u8_t size;
+ struct zsMulticastAddr macAddr[ZM_MAX_MULTICAST_LIST_SIZE];
+};
+
+enum ieee80211_cwm_mode {
+ CWM_MODE20,
+ CWM_MODE2040,
+ CWM_MODE40,
+ CWM_MODEMAX
+
+};
+
+enum ieee80211_cwm_extprotspacing {
+ CWM_EXTPROTSPACING20,
+ CWM_EXTPROTSPACING25,
+ CWM_EXTPROTSPACINGMAX
+};
+
+enum ieee80211_cwm_width {
+ CWM_WIDTH20,
+ CWM_WIDTH40
+};
+
+enum ieee80211_cwm_extprotmode {
+ CWM_EXTPROTNONE, /* no protection */
+ CWM_EXTPROTCTSONLY, /* CTS to self */
+ CWM_EXTPROTRTSCTS, /* RTS-CTS */
+ CWM_EXTPROTMAX
+};
+
+struct ieee80211_cwm {
+
+ /* Configuration */
+ enum ieee80211_cwm_mode cw_mode; /* CWM mode */
+ u8_t cw_extoffset; /* CWM Extension Channel Offset */
+ enum ieee80211_cwm_extprotmode cw_extprotmode; /* CWM Extension Channel Protection Mode */
+ enum ieee80211_cwm_extprotspacing cw_extprotspacing;/* CWM Extension Channel Protection Spacing */
+ u32_t cw_enable; /* CWM State Machine Enabled */
+ u32_t cw_extbusythreshold;/* CWM Extension Channel Busy Threshold */
+
+ /* State */
+ enum ieee80211_cwm_width cw_width; /* CWM channel width */
+};
+
+
+/* AP : STA database structure */
+struct zsStaTable
+{
+ u32_t time; /* tick time */
+ //u32_t phyCtrl; /* Tx PHY CTRL */
+ u16_t addr[3]; /* STA MAC address */
+ u16_t state; /* aut/asoc */
+ //u16_t retry; /* Retry count */
+ struct zsRcCell rcCell;
+
+ u8_t valid; /* Valid flag : 1=>valid */
+ u8_t psMode; /* STA power saving mode */
+ u8_t staType; /* 0=>11b, 1=>11g, 2=>11n */
+ u8_t qosType; /* 0=>Legacy, 1=>WME */
+ u8_t qosInfo; /* WME QoS info */
+ u8_t vap; /* Virtual AP ID */
+ u8_t encryMode; /* Encryption type for this STA */
+ u8_t keyIdx;
+ struct zsMicVar txMicKey;
+ struct zsMicVar rxMicKey;
+ u16_t iv16;
+ u32_t iv32;
+#ifdef ZM_ENABLE_CENC
+ /* CENC */
+ u8_t cencKeyIdx;
+ u32_t txiv[4];
+ u32_t rxiv[4];
+#endif //ZM_ENABLE_CENC
+};
+
+struct zdStructWds
+{
+ u8_t wdsBitmap; /* Set bit-N to 1 to enable WDS */
+ u8_t encryMode[ZM_MAX_WDS_SUPPORT]; /* WDS encryption mode */
+ u16_t macAddr[ZM_MAX_WDS_SUPPORT][3]; /* WDS neighbor MAC address */
+};
+
+ // htcapinfo 16bits
+#define HTCAP_AdvCodingCap 0x0001
+#define HTCAP_SupChannelWidthSet 0x0002
+#define HTCAP_DynamicSMPS 0x0004
+#define HTCAP_SMEnabled 0x000C
+#define HTCAP_GreenField 0x0010
+#define HTCAP_ShortGIfor20MHz 0x0020
+#define HTCAP_ShortGIfor40MHz 0x0040
+#define HTCAP_TxSTBC 0x0080
+#define HTCAP_RxOneStream 0x0100
+#define HTCAP_RxTwoStream 0x0200
+#define HTCAP_RxThreeStream 0x0300
+#define HTCAP_DelayedBlockACK 0x0400
+#define HTCAP_MaxAMSDULength 0x0800
+#define HTCAP_DSSSandCCKin40MHz 0x1000
+#define HTCAP_PSMPSup 0x2000
+#define HTCAP_STBCControlFrameSup 0x4000
+#define HTCAP_LSIGTXOPProtectionSUP 0x8000
+ // Ampdu HT Parameter Info 8bits
+#define HTCAP_MaxRxAMPDU0 0x00
+#define HTCAP_MaxRxAMPDU1 0x01
+#define HTCAP_MaxRxAMPDU2 0x02
+#define HTCAP_MaxRxAMPDU3 0x03
+ // PCO 8bits
+#define HTCAP_PCO 0x01
+#define HTCAP_TransmissionTime1 0x02
+#define HTCAP_TransmissionTime2 0x04
+#define HTCAP_TransmissionTime3 0x06
+ // MCS FeedBack 8bits
+#define HTCAP_PlusHTCSupport 0x04
+#define HTCAP_RDResponder 0x08
+ // TX Beamforming 0 8bits
+#define HTCAP_TxBFCapable 0x01
+#define HTCAP_RxStaggeredSoundCap 0x02
+#define HTCAP_TxStaggeredSoundCap 0x04
+#define HTCAP_RxZLFCapable 0x08
+#define HTCAP_TxZLFCapable 0x10
+#define HTCAP_ImplicitTxBFCapable 0x20
+ // Tx Beamforming 1 8bits
+#define HTCAP_ExplicitCSITxBFCap 0x01
+#define HTCAP_ExpUncompSteerMatrCap 0x02
+ // Antenna Selection Capabilities 8bits
+#define HTCAP_AntennaSelectionCap 0x01
+#define HTCAP_ExplicitCSITxASCap 0x02
+#define HTCAP_AntennaIndFeeTxASCap 0x04
+#define HTCAP_ExplicitCSIFeedbackCap 0x08
+#define HTCAP_AntennaIndFeedbackCap 0x10
+#define HTCAP_RxASCap 0x20
+#define HTCAP_TxSoundPPDUsCap 0x40
+
+
+
+struct zsHTCapability
+{
+ u8_t ElementID;
+ u8_t Length;
+ // HT Capability Info
+ u16_t HtCapInfo;
+ u8_t AMPDUParam;
+ u8_t MCSSet[16]; //16 bytes
+ // Extended HT Capability Info
+ u8_t PCO;
+ u8_t MCSFeedBack;
+
+ u8_t TxBFCap[4];
+ u8_t AselCap;
+};
+
+union zuHTCapability
+{
+ struct zsHTCapability Data;
+ u8_t Byte[28];
+};
+
+ //channelinfo 8bits
+#define ExtHtCap_ExtChannelOffsetAbove 0x01
+#define ExtHtCap_ExtChannelOffsetBelow 0x03
+#define ExtHtCap_RecomTxWidthSet 0x04
+#define ExtHtCap_RIFSMode 0x08
+#define ExtHtCap_ControlAccessOnly 0x10
+ //operatinginfo 16bits
+#define ExtHtCap_NonGFDevicePresent 0x0004
+ //beaconinfo 16bits
+#define ExtHtCap_DualBeacon 0x0040
+#define ExtHtCap_DualSTBCProtection 0x0080
+#define ExtHtCap_SecondaryBeacon 0x0100
+#define ExtHtCap_LSIGTXOPProtectFullSup 0x0200
+#define ExtHtCap_PCOActive 0x0400
+#define ExtHtCap_PCOPhase 0x0800
+
+
+struct zsExtHTCapability
+{
+ u8_t ElementID;
+ u8_t Length;
+ u8_t ControlChannel;
+ u8_t ChannelInfo;
+ u16_t OperatingInfo;
+ u16_t BeaconInfo;
+ // Supported MCS Set
+ u8_t MCSSet[16];
+};
+
+union zuExtHTCapability
+{
+ struct zsExtHTCapability Data;
+ u8_t Byte[24];
+};
+
+struct InformationElementSta {
+ struct zsHTCapability HtCap;
+ struct zsExtHTCapability HtInfo;
+};
+
+struct InformationElementAp {
+ struct zsHTCapability HtCap;
+};
+
+#define ZM_MAX_FREQ_REQ_QUEUE 32
+typedef void (*zfpFreqChangeCompleteCb)(zdev_t* dev);
+
+struct zsWlanDevFreqControl
+{
+ u16_t freqReqQueue[ZM_MAX_FREQ_REQ_QUEUE];
+ u8_t freqReqBw40[ZM_MAX_FREQ_REQ_QUEUE];
+ u8_t freqReqExtOffset[ZM_MAX_FREQ_REQ_QUEUE];
+ zfpFreqChangeCompleteCb freqChangeCompCb[ZM_MAX_FREQ_REQ_QUEUE];
+ u8_t freqReqQueueHead;
+ u8_t freqReqQueueTail;
+};
+
+struct zsWlanDevAp
+{
+ u16_t protectedObss; /* protected overlap BSS */
+ u16_t staAgingTimeSec; /* in second, STA will be deathed if it does not */
+ /* active for this long time */
+ u16_t staProbingTimeSec;/* in second, STA will be probed if it does not */
+ /* active for this long time */
+ u8_t authSharing; /* authentication on going*/
+ u8_t bStaAssociated; /* 11b STA associated */
+ u8_t gStaAssociated; /* 11g STA associated */
+ u8_t nStaAssociated; /* 11n STA associated */
+ u16_t protectionMode; /* AP protection mode flag */
+ u16_t staPowerSaving; /* Set associated power saving STA count */
+
+
+
+ zbuf_t* uniArray[ZM_UNI_ARRAY_SIZE]; /* array to store unicast frames */
+ u16_t uniHead;
+ u16_t uniTail;
+
+ /* HT Capability Info */
+ union zuHTCapability HTCap; //CWYang(+)
+
+ /* Extended HT Capability Info */
+ union zuExtHTCapability ExtHTCap; //CWYang(+)
+
+ /* STA table */
+ struct zsStaTable staTable[ZM_MAX_STA_SUPPORT];
+
+ /* WDS */
+ struct zdStructWds wds;
+ /* WPA */
+ u8_t wpaIe[ZM_MAX_AP_SUPPORT][ZM_MAX_WPAIE_SIZE];
+ u8_t wpaLen[ZM_MAX_AP_SUPPORT];
+ u8_t stawpaIe[ZM_MAX_AP_SUPPORT][ZM_MAX_WPAIE_SIZE];
+ u8_t stawpaLen[ZM_MAX_AP_SUPPORT];
+ u8_t wpaSupport[ZM_MAX_AP_SUPPORT];
+
+ //struct zsTkipSeed bcSeed;
+ u8_t bcKeyIndex[ZM_MAX_AP_SUPPORT];
+ u8_t bcHalKeyIdx[ZM_MAX_AP_SUPPORT];
+ struct zsMicVar bcMicKey[ZM_MAX_AP_SUPPORT];
+ u16_t iv16[ZM_MAX_AP_SUPPORT];
+ u32_t iv32[ZM_MAX_AP_SUPPORT];
+
+#ifdef ZM_ENABLE_CENC
+ /* CENC */
+ u32_t txiv[ZM_MAX_AP_SUPPORT][4];
+#endif //ZM_ENABLE_CENC
+
+ /* Virtual AP */
+ u8_t beaconCounter;
+ u8_t vapNumber;
+ u8_t apBitmap; /* Set bit-N to 1 to enable VAP */
+ u8_t hideSsid[ZM_MAX_AP_SUPPORT];
+ u8_t authAlgo[ZM_MAX_AP_SUPPORT];
+ u8_t ssid[ZM_MAX_AP_SUPPORT][32]; /* SSID */
+ u8_t ssidLen[ZM_MAX_AP_SUPPORT]; /* SSID length */
+ u8_t encryMode[ZM_MAX_AP_SUPPORT];
+ u8_t wepStatus[ZM_MAX_AP_SUPPORT];
+ u16_t capab[ZM_MAX_AP_SUPPORT]; /* Capability */
+ u8_t timBcmcBit[ZM_MAX_AP_SUPPORT]; /* BMCM bit of TIM */
+ u8_t wlanType[ZM_MAX_AP_SUPPORT];
+
+ /* Array to store BC or MC frames */
+ zbuf_t* bcmcArray[ZM_MAX_AP_SUPPORT][ZM_BCMC_ARRAY_SIZE];
+ u16_t bcmcHead[ZM_MAX_AP_SUPPORT];
+ u16_t bcmcTail[ZM_MAX_AP_SUPPORT];
+
+ u8_t qosMode; /* 1=>WME */
+ u8_t uapsdEnabled;
+ struct zsQueue* uapsdQ;
+
+ u8_t challengeText[128];
+
+ struct InformationElementAp ie[ZM_MAX_STA_SUPPORT];
+
+
+};
+
+#define ZM_MAX_BLOCKING_AP_LIST_SIZE 4 /* 2^N */
+struct zsBlockingAp
+{
+ u8_t addr[6];
+ u8_t weight;
+};
+
+#define ZM_SCAN_MGR_SCAN_NONE 0
+#define ZM_SCAN_MGR_SCAN_INTERNAL 1
+#define ZM_SCAN_MGR_SCAN_EXTERNAL 2
+
+struct zsWlanDevStaScanMgr
+{
+ u8_t scanReqs[2];
+ u8_t currScanType;
+ u8_t scanStartDelay;
+};
+
+#define ZM_PS_MSG_STATE_ACTIVE 0
+#define ZM_PS_MSG_STATE_SLEEP 1
+#define ZM_PS_MSG_STATE_T1 2
+#define ZM_PS_MSG_STATE_T2 3
+#define ZM_PS_MSG_STATE_S1 4
+
+#define ZM_PS_MAX_SLEEP_PERIODS 3 // The number of beacon periods
+
+struct zsWlanDevStaPSMgr
+{
+ u8_t state;
+ u8_t isSleepAllowed;
+ u8_t maxSleepPeriods;
+ u8_t ticks;
+ u32_t lastTxUnicastFrm;
+ u32_t lastTxMulticastFrm;
+ u32_t lastTxBroadcastFrm;
+ u8_t tempWakeUp; /*enable when wake up but still in ps mode */
+ u16_t sleepAllowedtick;
+};
+
+struct zsWlanDevSta
+{
+ u32_t beaconTxCnt; /* Transmitted beacon counter (in IBSS) */
+ u8_t txBeaconInd; /* In IBSS mode, true means that we just transmit a beacon during
+ last beacon period.
+ */
+ u16_t beaconCnt; /* receive beacon count, will be perodically reset */
+ u16_t bssid[3]; /* BSSID of connected AP */
+ u8_t ssid[32]; /* SSID */
+ u8_t ssidLen; /* SSID length */
+ u8_t mTxRate; /* Tx rate for multicast */
+ u8_t uTxRate; /* Tx rate for unicast */
+ u8_t mmTxRate; /* Tx rate for management frame */
+ u8_t bChannelScan;
+ u8_t bScheduleScan;
+
+ u8_t InternalScanReq;
+ u16_t activescanTickPerChannel;
+ u16_t passiveScanTickPerChannel;
+ u16_t scanFrequency;
+ u32_t connPowerInHalfDbm;
+
+ u16_t currentFrequency;
+ u16_t currentBw40;
+ u16_t currentExtOffset;
+
+ u8_t bPassiveScan;
+
+ struct zsBlockingAp blockingApList[ZM_MAX_BLOCKING_AP_LIST_SIZE];
+
+ //struct zsBssInfo bssInfoPool[ZM_MAX_BSS];
+ struct zsBssInfo* bssInfoArray[ZM_MAX_BSS];
+ struct zsBssList bssList;
+ u8_t bssInfoArrayHead;
+ u8_t bssInfoArrayTail;
+ u8_t bssInfoFreeCount;
+
+ u8_t authMode;
+ u8_t currentAuthMode;
+ u8_t wepStatus;
+ u8_t encryMode;
+ u8_t keyId;
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ u8_t ibssWpa2Psk;
+#endif
+#ifdef ZM_ENABLE_CENC
+ u8_t cencKeyId; //CENC
+#endif //ZM_ENABLE_CENC
+ u8_t dropUnencryptedPkts;
+ u8_t ibssJoinOnly;
+ u8_t adapterState;
+ u8_t oldAdapterState;
+ u8_t connectState;
+ u8_t connectRetry;
+ u8_t wpaState;
+ u8_t wpaIe[ZM_MAX_IE_SIZE + 2];
+ u8_t rsnIe[ZM_MAX_IE_SIZE + 2];
+ u8_t challengeText[255+2];
+ u8_t capability[2];
+ //u8_t connectingHiddenAP;
+ //u8_t scanWithSSID;
+ u16_t aid;
+ u32_t mgtFrameCount;
+ u8_t bProtectionMode;
+ u32_t NonNAPcount;
+ u8_t RTSInAGGMode;
+ u32_t connectTimer;
+ u16_t atimWindow;
+ u8_t desiredBssid[6];
+ u8_t bDesiredBssid;
+ struct zsTkipSeed txSeed;
+ struct zsTkipSeed rxSeed[4];
+ struct zsMicVar txMicKey;
+ struct zsMicVar rxMicKey[4];
+ u16_t iv16;
+ u32_t iv32;
+ struct zsOppositeInfo oppositeInfo[ZM_MAX_OPPOSITE_COUNT];
+ u8_t oppositeCount;
+ u8_t bssNotFoundCount; /* sitesurvey for search desired ISBB threshold */
+ u16_t rxBeaconCount;
+ u8_t beaconMissState;
+ u32_t rxBeaconTotal;
+ u8_t bIsSharedKey;
+ u8_t connectTimeoutCount;
+
+ u8_t recvAtim;
+
+ /* ScanMgr Control block */
+ struct zsWlanDevStaScanMgr scanMgr;
+ struct zsWlanDevStaPSMgr psMgr;
+
+ // The callback would be called if receiving an unencrypted packets but
+ // the station is in encrypted mode. The wrapper could decide whether
+ // to drop the packet by its OS setting.
+ zfpStaRxSecurityCheckCb pStaRxSecurityCheckCb;
+
+ /* WME */
+ u8_t apWmeCapability; //bit-0 => a WME AP
+ //bit-7 => a UAPSD AP
+ u8_t wmeParameterSetCount;
+
+ u8_t wmeEnabled;
+ #define ZM_STA_WME_ENABLE_BIT 0x1
+ #define ZM_STA_UAPSD_ENABLE_BIT 0x2
+ u8_t wmeQosInfo;
+
+ u8_t wmeConnected;
+ u8_t qosInfo;
+ struct zsQueue* uapsdQ;
+
+ /* countermeasures */
+ u8_t cmMicFailureCount;
+ u8_t cmDisallowSsidLength;
+ u8_t cmDisallowSsid[32];
+
+ /* power-saving mode */
+ u8_t powerSaveMode;
+ zbuf_t* staPSDataQueue[ZM_PS_QUEUE_SIZE];
+ u8_t staPSDataCount;
+
+ /* IBSS power-saving mode */
+ /* record the STA which has entered the PS mode */
+ struct zsStaPSList staPSList;
+ /* queue the data of the PS STAs */
+ zbuf_t* ibssPSDataQueue[ZM_PS_QUEUE_SIZE];
+ u8_t ibssPSDataCount;
+ u8_t ibssPrevPSDataCount;
+ u8_t bIbssPSEnable;
+ /* BIT_15: ON/OFF, BIT_0~14: Atim Timer */
+ u16_t ibssAtimTimer;
+
+ /* WPA2 */
+ struct zsPmkidInfo pmkidInfo;
+
+ /* Multicast list related objects */
+ struct zsMulticastList multicastList;
+
+ /* XP packet filter feature : */
+ /* 1=>enable: All multicast address packets, not just the ones enumerated in the multicast address list. */
+ /* 0=>disable */
+ u8_t bAllMulticast;
+
+ /* reassociation flag */
+ u8_t connectByReasso;
+ u8_t failCntOfReasso;
+
+ /* for HT configure control setting */
+ u8_t preambleTypeHT; /* HT: 0 Mixed mode 1 Green field */
+ u8_t htCtrlBandwidth;
+ u8_t htCtrlSTBC;
+ u8_t htCtrlSG;
+ u8_t defaultTA;
+
+ u8_t connection_11b;
+
+ u8_t EnableHT;
+ u8_t SG40;
+ u8_t HT2040;
+ /* for WPA setting */
+ u8_t wpaSupport;
+ u8_t wpaLen;
+
+ /* IBSS related objects */
+ u8_t ibssDelayedInd;
+ struct zsPartnerNotifyEvent ibssDelayedIndEvent;
+ u8_t ibssPartnerStatus;
+
+ u8_t bAutoReconnect;
+
+ u8_t flagFreqChanging;
+ u8_t flagKeyChanging;
+ struct zsBssInfo ibssBssDesc;
+ u8_t ibssBssIsCreator;
+ u16_t ibssReceiveBeaconCount;
+ u8_t ibssSiteSurveyStatus;
+
+ u8_t disableProbingWithSsid;
+#ifdef ZM_ENABLE_CENC
+ /* CENC */
+ u8_t cencIe[ZM_MAX_IE_SIZE + 2];
+#endif //ZM_ENABLE_CENC
+ u32_t txiv[4]; //Tx PN Sequence
+ u32_t rxiv[4]; //Rx PN Sequence
+ u32_t rxivGK[4];//Broadcast Rx PN Sequence
+ u8_t wepKey[4][32]; // For Software WEP
+ u8_t SWEncryMode[4];
+
+ /* 802.11d */
+ u8_t b802_11D;
+
+ /* 802.11h */
+ u8_t TPCEnable;
+ u8_t DFSEnable;
+ u8_t DFSDisableTx;
+
+ /* Owl AP */
+ u8_t athOwlAp;
+
+ /* Enable BA response in driver */
+ u8_t enableDrvBA;
+
+ /* HT Capability Info */
+ union zuHTCapability HTCap; //CWYang(+)
+
+ /* Extended HT Capability Info */
+ union zuExtHTCapability ExtHTCap; //CWYang(+)
+
+ struct InformationElementSta ie;
+
+#define ZM_CACHED_FRAMEBODY_SIZE 200
+ u8_t asocReqFrameBody[ZM_CACHED_FRAMEBODY_SIZE];
+ u16_t asocReqFrameBodySize;
+ u8_t asocRspFrameBody[ZM_CACHED_FRAMEBODY_SIZE];
+ u16_t asocRspFrameBodySize;
+ u8_t beaconFrameBody[ZM_CACHED_FRAMEBODY_SIZE];
+ u16_t beaconFrameBodySize;
+
+ u8_t ac0PriorityHigherThanAc2;
+ u8_t SWEncryptEnable;
+
+ u8_t leapEnabled;
+
+ u32_t TotalNumberOfReceivePackets;
+ u32_t TotalNumberOfReceiveBytes;
+ u32_t avgSizeOfReceivePackets;
+
+ u32_t ReceivedPacketRateCounter;
+ u32_t ReceivedPktRatePerSecond;
+
+ /* #2 Record the sequence number to determine whether the unicast frame is separated by RIFS or not */
+#define ZM_RIFS_STATE_DETECTING 0
+#define ZM_RIFS_STATE_DETECTED 1
+#define ZM_RIFS_TIMER_TIMEOUT 4480 // <Driver time>4480ms <Real time>7s
+ u8_t rifsState;
+ u8_t rifsLikeFrameCnt;
+ u16_t rifsLikeFrameSequence[3];
+ u32_t rifsTimer;
+ u32_t rifsCount;
+
+ /* RX filter desired by upper layers. Note this contains some bits which must be filtered
+ by sw since the hw supports only a subset of possible filter actions.= */
+ u32_t osRxFilter;
+
+ u8_t bSafeMode;
+
+ u32_t ibssAdditionalIESize;
+ u8_t ibssAdditionalIE[256];
+}; //struct zsWlanDevSta
+
+#define ZM_CMD_QUEUE_SIZE 256 //Roger Check, test 64 when ready
+
+#define ZM_OID_READ 1
+#define ZM_OID_WRITE 2
+#define ZM_OID_INTERNAL_WRITE 3
+#define ZM_CMD_SET_FREQUENCY 4
+#define ZM_CMD_SET_KEY 5
+#define ZM_CWM_READ 6
+#define ZM_MAC_READ 7
+#define ZM_ANI_READ 8
+#define ZM_EEPROM_READ 9
+#define ZM_EEPROM_WRITE 0x0A
+#define ZM_OID_CHAN 0x30
+#define ZM_OID_SYNTH 0x32
+#define ZM_OID_TALLY 0x81
+#define ZM_OID_TALLY_APD 0x82
+
+#define ZM_OID_DKTX_STATUS 0x92
+#define ZM_OID_FLASH_CHKSUM 0xD0
+#define ZM_OID_FLASH_READ 0xD1
+#define ZM_OID_FLASH_PROGRAM 0xD2
+#define ZM_OID_FW_DL_INIT 0xD3
+
+/* Driver to Firmware OID */
+#define ZM_CMD_ECHO 0x80
+#define ZM_CMD_TALLY 0x81
+#define ZM_CMD_TALLY_APD 0x82
+#define ZM_CMD_CONFIG 0x83
+#define ZM_CMD_RREG 0x00
+#define ZM_CMD_WREG 0x01
+#define ZM_CMD_RMEM 0x02
+#define ZM_CMD_WMEM 0x03
+#define ZM_CMD_BITAND 0x04
+#define ZM_CMD_BITOR 0x05
+#define ZM_CMD_EKEY 0x28
+#define ZM_CMD_DKEY 0x29
+#define ZM_CMD_FREQUENCY 0x30
+#define ZM_CMD_RF_INIT 0x31
+#define ZM_CMD_SYNTH 0x32
+#define ZM_CMD_FREQ_STRAT 0x33
+#define ZM_CMD_RESET 0x90
+#define ZM_CMD_DKRESET 0x91
+#define ZM_CMD_DKTX_STATUS 0x92
+#define ZM_CMD_FDC 0xA0
+#define ZM_CMD_WREEPROM 0xB0
+#define ZM_CMD_WFLASH 0xB0
+#define ZM_CMD_FLASH_ERASE 0xB1
+#define ZM_CMD_FLASH_PROG 0xB2
+#define ZM_CMD_FLASH_CHKSUM 0xB3
+#define ZM_CMD_FLASH_READ 0xB4
+#define ZM_CMD_FW_DL_INIT 0xB5
+#define ZM_CMD_MEM_WREEPROM 0xBB
+
+
+/* duplicate filter table column */
+#define ZM_FILTER_TABLE_COL 2 /* 2^n */
+/* duplicate filter table Row */
+#define ZM_FILTER_TABLE_ROW 8 /* 2^n */
+
+/* duplicate filter table structure */
+struct zsRxFilter
+{
+ u16_t addr[3];
+ u16_t seq;
+ u8_t up;
+};
+
+struct zsWlanDev
+{
+ /* AP global variables */
+ struct zsWlanDevAp ap;
+ /* STA global variables */
+ struct zsWlanDevSta sta;
+ /* save wrapper setting */
+ struct zsWrapperSetting ws;
+ /* features determined by wrapper (vendor) */
+ struct zsWrapperFeatureCtrl wfc;
+ /* Traffic Monitor tally */
+ struct zsTrafTally trafTally;
+ /* Communication tally */
+ struct zsCommTally commTally;
+ /* Duplicate frame filter table */
+ struct zsRxFilter rxFilterTbl[ZM_FILTER_TABLE_COL][ZM_FILTER_TABLE_ROW];
+ /* Regulatory table */
+ struct zsRegulationTable regulationTable;
+
+ /* */
+ struct zsWlanDevFreqControl freqCtrl;
+
+ enum devState state;
+
+ u8_t halState;
+ u8_t wlanMode; /* AP/INFRASTRUCTURE/IBSS/PSEUDO */
+ u16_t macAddr[3]; /* MAC address */
+ u16_t beaconInterval; /* beacon Interval */
+ u8_t dtim; /* DTIM period */
+ u8_t CurrentDtimCount;
+ u8_t preambleType;
+ u8_t preambleTypeInUsed;
+ u8_t maxTxPower2; /* 2.4 GHz Max Tx power (Unit: 0.5 dBm) */
+ u8_t maxTxPower5; /* 5 GHz Max Tx power (Unit: 0.5 dBm) */
+ u8_t connectMode;
+ u32_t supportMode;
+
+ u8_t bRate; /* 11b Support Rate bit map */
+ u8_t bRateBasic; /* 11b Basic Rate bit map */
+ u8_t gRate; /* 11g Support Rate bit map */
+ u8_t gRateBasic; /* 11g Basic Rate bit map */
+ /* channel index point to the item in regulation table */
+ u8_t channelIndex;
+
+ /* channel management */
+ u8_t BandWidth40;
+ u8_t ExtOffset; //1 above, 3 below, 0 not present
+ u16_t frequency; /* operation frequency */
+
+ u8_t erpElement; /* ERP information element data */
+
+ u8_t disableSelfCts; /* set to 1 to disable Self-CTS */
+ u8_t bgMode;
+
+ /* private test flag */
+ u32_t enableProtectionMode; /* force enable/disable self cts */
+ u32_t checksumTest; /* OTUS checksum test 1=>zero checksum 0=>normal */
+ u32_t rxPacketDump; /* rx packet dump */
+
+ u8_t enableAggregation; /* force enable/disable A-MSPU */
+ u8_t enableWDS; /* force enable/disable WDS testing */
+ u8_t enableTxPathMode; /* OTUS special testing mode 1=>diable, 0=>enable: ZM_SYSTEM_TEST_MODE */
+ u8_t enableHALDbgInfo; /* */
+
+ u32_t forceTxTPC; /* force tx packet send TPC */
+
+ u16_t seq[4];
+ u16_t mmseq;
+
+ /* driver core time tick */
+ u32_t tick;
+ u16_t tickIbssSendBeacon;
+ u16_t tickIbssReceiveBeacon;
+
+ /* RTS threshold */
+ u16_t rtsThreshold;
+
+ /* fragmentation threshold, 256 <= value <= 2346, 0=disabled */
+ u16_t fragThreshold;
+
+ /* Tx Rate */
+ u16_t txMCS;
+ u16_t txMT;
+ u32_t CurrentTxRateKbps; //CWYang(+)
+ /* Rx Rate */
+ u32_t CurrentRxRateKbps; //Janet(+)
+ u8_t CurrentRxRateUpdated;
+ u8_t modulationType;
+ u8_t rxInfo;
+ u16_t rateField;
+
+ /* timer related objects */
+ struct zsTimerList timerList;
+ u8_t bTimerReady;
+
+ /* for defragmentation */
+ struct zsDefragList defragTable;
+
+ /* Data struct for Interface Dependent Layer */
+ //struct zsIdlStruct idlStruct;
+
+ /* Signal Strength/Quality Related Parameters */
+ u8_t SignalStrength; //CWYang(+)
+ u8_t SignalQuality; //CWYang(+)
+
+
+
+ /* QoS */
+ zbuf_t* vtxq[4][ZM_VTXQ_SIZE];
+ u16_t vtxqHead[4];
+ u16_t vtxqTail[4];
+ u16_t qosDropIpFrag[4];
+
+ /* Management Tx queue */
+ zbuf_t* vmmq[ZM_VMMQ_SIZE];
+ u16_t vmmqHead;
+ u16_t vmmqTail;
+
+ u8_t vtxqPushing;
+
+ /*
+ * add by honda
+ * 1. Aggregate queues
+ * 2. STA's associated information and queue number
+ * 3. rx aggregation re-ordering queue
+ */
+ struct aggQueue *aggQPool[ZM_AGG_POOL_SIZE];
+ u8_t aggInitiated;
+ u8_t addbaComplete;
+ u8_t addbaCount;
+ u8_t aggState;
+ u8_t destLock;
+ struct aggSta aggSta[ZM_MAX_STA_SUPPORT];
+ struct agg_tid_rx *tid_rx[ZM_AGG_POOL_SIZE];
+ struct aggTally agg_tal;
+ struct destQ destQ;
+ struct baw_enabler *baw_enabler;
+ struct ieee80211_cwm cwm;
+ u16_t reorder;
+ u16_t seq_debug;
+ /* rate control */
+ u32_t txMPDU[ZM_RATE_TABLE_SIZE];
+ u32_t txFail[ZM_RATE_TABLE_SIZE];
+ u32_t PER[ZM_RATE_TABLE_SIZE];
+ u16_t probeCount;
+ u16_t probeSuccessCount;
+ u16_t probeInterval;
+ u16_t success_probing;
+ /*
+ * end of add by honda
+ */
+
+ /* airopeek sniffer mode for upper sw */
+ u32_t swSniffer; /* window: airoPeek */
+ u32_t XLinkMode;
+
+ /* MDK mode */
+ /* init by 0=>normal driver 1=>MDK driver */
+ u32_t modeMDKEnable;
+
+ u32_t heartBeatNotification;
+
+ /* pointer for HAL Plus private memory */
+ void* hpPrivate;
+
+ /* for WPA setting */
+ //u8_t wpaSupport[ZM_MAX_AP_SUPPORT];
+ //u8_t wpaLen[ZM_MAX_AP_SUPPORT];
+ //u8_t wpaIe[ZM_MAX_AP_SUPPORT][ZM_MAX_IE_SIZE];
+
+ struct zsLedStruct ledStruct;
+
+ /* ani flag */
+ u8_t aniEnable;
+ u16_t txq_threshold;
+
+ //Skip Mic Error Check
+ u8_t TKIP_Group_KeyChanging;
+
+ u8_t dynamicSIFSEnable;
+
+ u8_t queueFlushed;
+
+ u16_t (*zfcbAuthNotify)(zdev_t* dev, u16_t* macAddr);
+ u16_t (*zfcbAsocNotify)(zdev_t* dev, u16_t* macAddr, u8_t* body, u16_t bodySize, u16_t port);
+ u16_t (*zfcbDisAsocNotify)(zdev_t* dev, u8_t* macAddr, u16_t port);
+ u16_t (*zfcbApConnectNotify)(zdev_t* dev, u8_t* macAddr, u16_t port);
+ void (*zfcbConnectNotify)(zdev_t* dev, u16_t status, u16_t* bssid);
+ void (*zfcbScanNotify)(zdev_t* dev, struct zsScanResult* result);
+ void (*zfcbMicFailureNotify)(zdev_t* dev, u16_t* addr, u16_t status);
+ void (*zfcbApMicFailureNotify)(zdev_t* dev, u8_t* addr, zbuf_t* buf);
+ void (*zfcbIbssPartnerNotify)(zdev_t* dev, u16_t status, struct zsPartnerNotifyEvent *event);
+ void (*zfcbMacAddressNotify)(zdev_t* dev, u8_t* addr);
+ void (*zfcbSendCompleteIndication)(zdev_t* dev, zbuf_t* buf);
+ void (*zfcbRecvEth)(zdev_t* dev, zbuf_t* buf, u16_t port);
+ void (*zfcbRecv80211)(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo);
+ void (*zfcbRestoreBufData)(zdev_t* dev, zbuf_t* buf);
+#ifdef ZM_ENABLE_CENC
+ u16_t (*zfcbCencAsocNotify)(zdev_t* dev, u16_t* macAddr, u8_t* body,
+ u16_t bodySize, u16_t port);
+#endif //ZM_ENABLE_CENC
+ u8_t (*zfcbClassifyTxPacket)(zdev_t* dev, zbuf_t* buf);
+ void (*zfcbHwWatchDogNotify)(zdev_t* dev);
+};
+
+
+struct zsWlanKey
+{
+ u8_t key;
+};
+
+
+/* These macros are defined here for backward compatibility */
+/* Please leave them alone */
+/* For Tx packet allocated in upper layer layer */
+#define zmw_tx_buf_readb(dev, buf, offset) zmw_buf_readb(dev, buf, offset)
+#define zmw_tx_buf_readh(dev, buf, offset) zmw_buf_readh(dev, buf, offset)
+#define zmw_tx_buf_writeb(dev, buf, offset, value) zmw_buf_writeb(dev, buf, offset, value)
+#define zmw_tx_buf_writeh(dev, buf, offset, value) zmw_buf_writeh(dev, buf, offset, value)
+
+/* For Rx packet allocated in driver */
+#define zmw_rx_buf_readb(dev, buf, offset) zmw_buf_readb(dev, buf, offset)
+#define zmw_rx_buf_readh(dev, buf, offset) zmw_buf_readh(dev, buf, offset)
+#define zmw_rx_buf_writeb(dev, buf, offset, value) zmw_buf_writeb(dev, buf, offset, value)
+#define zmw_rx_buf_writeh(dev, buf, offset, value) zmw_buf_writeh(dev, buf, offset, value)
+
+#endif /* #ifndef _STRUCT_H */
diff --git a/drivers/staging/otus/80211core/wlan.h b/drivers/staging/otus/80211core/wlan.h
new file mode 100644
index 000000000000..26c18b837cfc
--- /dev/null
+++ b/drivers/staging/otus/80211core/wlan.h
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : wlan_defs.h */
+/* */
+/* Abstract */
+/* This module contains WLAN definitions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+
+#ifndef _WLAN_H
+#define _WLAN_H
+
+
+#define ZM_EXTERNAL_ALLOC_BUF 0
+#define ZM_INTERNAL_ALLOC_BUF 1
+
+#define ZM_SIZE_OF_CTRL_SET 8
+#define ZM_SIZE_OF_IV 4
+#define ZM_SIZE_OF_EXT_IV 4
+#define ZM_SIZE_OF_MIC 8
+#define ZM_SIZE_OF_CCX_MIC 8
+#define ZM_SIZE_OF_WLAN_DATA_HEADER 24
+#define ZM_SIZE_OF_QOS_CTRL 2
+
+/* Header definition */
+#define ZM_SIZE_OF_WLAN_WDS_HEADER 32
+#define ZM_SIZE_OF_SNAP_HEADER 8
+
+#define ZM_WLAN_HEADER_A1_OFFSET 4
+#define ZM_WLAN_HEADER_A2_OFFSET 10
+#define ZM_WLAN_HEADER_A3_OFFSET 16
+#define ZM_WLAN_HEADER_A4_OFFSET 24
+#define ZM_WLAN_HEADER_IV_OFFSET 24
+#define ZM_SIZE_OF_WLAN_DATA_HEADER 24
+
+/* Port definition */
+#define ZM_PORT_DISABLED 0
+#define ZM_PORT_ENABLED 1
+
+/* Frame Type */
+#define ZM_WLAN_MANAGEMENT_FRAME 0x0
+#define ZM_WLAN_CONTROL_FRAME 0x4
+#define ZM_WLAN_DATA_FRAME 0x8
+
+/* Frame Subtype */
+#define ZM_WLAN_FRAME_TYPE_ASOCREQ 0x00
+#define ZM_WLAN_FRAME_TYPE_ASOCRSP 0x10
+#define ZM_WLAN_FRAME_TYPE_REASOCREQ 0x20
+#define ZM_WLAN_FRAME_TYPE_REASOCRSP 0x30
+#define ZM_WLAN_FRAME_TYPE_PROBEREQ 0x40
+#define ZM_WLAN_FRAME_TYPE_PROBERSP 0x50
+/* 0x60, 0x70 => Reserved */
+#define ZM_WLAN_FRAME_TYPE_BEACON 0x80
+#define ZM_WLAN_FRAME_TYPE_ATIM 0x90
+#define ZM_WLAN_FRAME_TYPE_DISASOC 0xA0
+#define ZM_WLAN_FRAME_TYPE_AUTH 0xB0
+#define ZM_WLAN_FRAME_TYPE_DEAUTH 0xC0
+#define ZM_WLAN_FRAME_TYPE_ACTION 0xD0
+
+/* Frame type and subtype */
+#define ZM_WLAN_FRAME_TYPE_NULL 0x48
+#define ZM_WLAN_FRAME_TYPE_BAR 0x84
+#define ZM_WLAN_FRAME_TYPE_BA 0x94
+#define ZM_WLAN_FRAME_TYPE_PSPOLL 0xA4
+#define ZM_WLAN_FRAME_TYPE_RTS 0xB4
+#define ZM_WLAN_FRAME_TYPE_CTS 0xC4
+#define ZM_WLAN_FRAME_TYPE_QOS_NULL 0xC8
+
+/* action frame */
+#define ZM_WLAN_SPECTRUM_MANAGEMENT_ACTION_FRAME 0
+#define ZM_WLAN_QOS_ACTION_FRAME 1
+#define ZM_WLAN_DLS_ACTION_FRAME 2
+#define ZM_WLAN_BLOCK_ACK_ACTION_FRAME 3
+/* block ack action frame*/
+#define ZM_WLAN_ADDBA_REQUEST_FRAME 0
+#define ZM_WLAN_ADDBA_RESPONSE_FRAME 1
+#define ZM_WLAN_DELBA_FRAME 2
+
+/* Element ID */
+#define ZM_WLAN_EID_SSID 0
+#define ZM_WLAN_EID_SUPPORT_RATE 1
+#define ZM_WLAN_EID_FH 2
+#define ZM_WLAN_EID_DS 3
+#define ZM_WLAN_EID_CFS 4
+#define ZM_WLAN_EID_TIM 5
+#define ZM_WLAN_EID_IBSS 6
+#define ZM_WLAN_EID_COUNTRY 7
+/* reserved 8-15 */
+#define ZM_WLAN_EID_CHALLENGE 16
+/* reserved 17-31 */
+#define ZM_WLAN_EID_POWER_CONSTRAINT 32
+#define ZM_WLAN_EID_POWER_CAPABILITY 33
+#define ZM_WLAN_EID_TPC_REQUEST 34
+#define ZM_WLAN_EID_TPC_REPORT 35
+#define ZM_WLAN_EID_SUPPORTED_CHANNELS 36
+#define ZM_WLAN_EID_CHANNEL_SWITCH_ANNOUNCE 37
+#define ZM_WLAN_EID_MEASUREMENT_REQUEST 38
+#define ZM_WLAN_EID_MEASUREMENT_REPORT 39
+#define ZM_WLAN_EID_QUIET 40
+#define ZM_WLAN_EID_IBSS_DFS 41
+#define ZM_WLAN_EID_ERP 42
+#define ZM_WLAN_PREN2_EID_HTCAPABILITY 45
+#define ZM_WLAN_EID_RSN_IE 48
+#define ZM_WLAN_EID_EXTENDED_RATE 50
+#define ZM_WLAN_EID_HT_CAPABILITY 51
+#define ZM_WLAN_EID_EXTENDED_HT_CAPABILITY 52
+#define ZM_WLAN_EID_NEW_EXT_CHANNEL_OFFSET 53
+#define ZM_WLAN_PREN2_EID_HTINFORMATION 61
+#define ZM_WLAN_PREN2_EID_SECONDCHOFFSET 62
+#ifdef ZM_ENABLE_CENC
+#define ZM_WLAN_EID_CENC_IE 68
+#endif //ZM_ENABLE_CENC
+#define ZM_WLAN_EID_VENDOR_PRIVATE 221 /* Vendor private space; must demux OUI */
+#define ZM_WLAN_EID_WPA_IE 221
+#define ZM_WLAN_EID_WPS_IE 221
+#define ZM_WLAN_EID_WIFI_IE 221
+
+/* ERP information element */
+#define ZM_WLAN_NON_ERP_PRESENT_BIT 0x1
+#define ZM_WLAN_USE_PROTECTION_BIT 0x2
+#define ZM_WLAN_BARKER_PREAMBLE_MODE_BIT 0x4
+
+/* Channel frequency, in MHz */
+#define ZM_CH_G_1 2412
+#define ZM_CH_G_2 2417
+#define ZM_CH_G_3 2422
+#define ZM_CH_G_4 2427
+#define ZM_CH_G_5 2432
+#define ZM_CH_G_6 2437
+#define ZM_CH_G_7 2442
+#define ZM_CH_G_8 2447
+#define ZM_CH_G_9 2452
+#define ZM_CH_G_10 2457
+#define ZM_CH_G_11 2462
+#define ZM_CH_G_12 2467
+#define ZM_CH_G_13 2472
+#define ZM_CH_G_14 2484
+#define ZM_CH_A_184 4920
+#define ZM_CH_A_188 4940
+#define ZM_CH_A_192 4960
+#define ZM_CH_A_196 4980
+#define ZM_CH_A_8 5040
+#define ZM_CH_A_12 5060
+#define ZM_CH_A_16 5080
+#define ZM_CH_A_36 5180
+#define ZM_CH_A_40 5200
+#define ZM_CH_A_44 5220
+#define ZM_CH_A_48 5240
+#define ZM_CH_A_52 5260
+#define ZM_CH_A_56 5280
+#define ZM_CH_A_60 5300
+#define ZM_CH_A_64 5320
+#define ZM_CH_A_100 5500
+#define ZM_CH_A_104 5520
+#define ZM_CH_A_108 5540
+#define ZM_CH_A_112 5560
+#define ZM_CH_A_116 5580
+#define ZM_CH_A_120 5600
+#define ZM_CH_A_124 5620
+#define ZM_CH_A_128 5640
+#define ZM_CH_A_132 5660
+#define ZM_CH_A_136 5680
+#define ZM_CH_A_140 5700
+#define ZM_CH_A_149 5745
+#define ZM_CH_A_153 5765
+#define ZM_CH_A_157 5785
+#define ZM_CH_A_161 5805
+#define ZM_CH_A_165 5825
+
+
+/* AP : STA table => STA Type */
+#define ZM_11B_STA 0x0
+#define ZM_11G_STA 0x2
+#define ZM_11N_STA 0x4
+
+/* AP : timeout */
+#define ZM_MS_PER_TICK 10
+#define ZM_TICK_PER_SECOND (1000/ZM_MS_PER_TICK)
+#define ZM_TICK_PER_MINUTE (60*1000/ZM_MS_PER_TICK)
+#define ZM_PREAUTH_TIMEOUT_MS 1000 /* 1 sec */
+#define ZM_AUTH_TIMEOUT_MS 1000 /* 1 sec */
+
+/* Error code */
+#define ZM_SUCCESS 0
+#define ZM_ERR_TX_PORT_DISABLED 1
+#define ZM_ERR_BUFFER_DMA_ADDR 2
+#define ZM_ERR_FREE_TXD_EXHAUSTED 3
+#define ZM_ERR_TX_BUFFER_UNAVAILABLE 4
+#define ZM_ERR_BCMC_PS_BUFFER_UNAVAILABLE 5
+#define ZM_ERR_UNI_PS_BUFFER_UNAVAILABLE 6
+#define ZM_ERR_EXCEED_PRIORITY_THRESHOLD 7
+#define ZM_ERR_VMMQ_FULL 8
+#define ZM_ERR_FLUSH_PS_QUEUE 9
+#define ZM_ERR_CMD_INT_MISSED 15 /* Polling cmd int timeout*/
+/* Rx */
+#define ZM_ERR_RX_FRAME_TYPE 20
+#define ZM_ERR_MIN_RX_ENCRYPT_FRAME_LENGTH 21
+#define ZM_ERR_MIN_RX_FRAME_LENGTH 22
+#define ZM_ERR_MAX_RX_FRAME_LENGTH 23
+#define ZM_ERR_RX_DUPLICATE 24
+#define ZM_ERR_RX_SRC_ADDR_IS_OWN_MAC 25
+#define ZM_ERR_MIN_RX_PROTOCOL_VERSION 26
+#define ZM_ERR_WPA_GK_NOT_INSTALLED 27
+#define ZM_ERR_STA_NOT_ASSOCIATED 28
+#define ZM_ERR_DATA_BEFORE_CONNECTED 29
+#define ZM_ERR_DATA_NOT_ENCRYPTED 30
+#define ZM_ERR_DATA_BSSID_NOT_MATCHED 31
+#define ZM_ERR_RX_BAR_FRAME 32
+#define ZM_ERR_OUT_OF_ORDER_NULL_DATA 33
+
+/* ZFI */
+#define ZM_ERR_INVALID_TX_RATE 40
+#define ZM_ERR_WDS_PORT_ID 41
+
+/* QUEUE */
+#define ZM_ERR_QUEUE_FULL 50
+#define ZM_ERR_STA_UAPSD_QUEUE_FULL 51
+#define ZM_ERR_AP_UAPSD_QUEUE_FULL 52
+
+/* Maximum Rx frame length */
+#if ZM_LARGEPAYLOAD_TEST == 1
+#define ZM_WLAN_MAX_RX_SIZE 16384
+#else
+#define ZM_WLAN_MAX_RX_SIZE 8192
+#endif
+
+/* PCI DMA test error code */
+#define ZM_ERR_INTERRUPT_MISSED 100
+#define ZM_ERR_OWN_BIT_NOT_CLEARED 101
+#define ZM_ERR_RX_SEQ_NUMBER 102
+#define ZM_ERR_RX_LENGTH 103
+#define ZM_ERR_RX_DATA 104
+#define ZM_ERR_RX_DESCRIPTOR_NUM 105
+/* Common register test error code */
+#define ZM_ERR_REGISTER_ACCESS 110 /* Register R/W test fail*/
+#define ZM_ERR_CLEAR_INTERRUPT_FLAG 111
+#define ZM_ERR_COMMAND_RESPONSE 112
+#define ZM_ERR_INTERRUPT_GENERATE 113
+#define ZM_ERR_INTERRUPT_ACK 114
+#define ZM_ERR_SCRATCH_ACCESS 115
+#define ZM_ERR_INTERRUPT_MASK_ACCESS 116
+#define ZM_ERR_SHARE_MEMORY_PCI_ACCESS 117
+#define ZM_ERR_SHARE_MEMORY_FW_ACCESS 118
+#define ZM_ERR_SHARE_MEMORY_DISABLE 119
+#define ZM_ERR_SHARE_MEMORY_TEST_RESPONSE 120
+
+/* Firmware Download error code */
+#define ZM_ERR_FIRMWARE_DOWNLOAD_TIMEOUT 150
+#define ZM_ERR_FIRMWARE_DOWNLOAD_INT_FLAG 151
+#define ZM_ERR_FIRMWARE_READY_TIMEOUT 152
+#define ZM_ERR_FIRMWARE_WRONG_TYPE 153
+
+/* Debug */
+#define ZM_LV_0 0//Debug level 0, Disable debug message
+#define ZM_LV_1 1//Debug level 1, Show minimum information
+#define ZM_LV_2 2//Debug level 2, Show medium message
+#define ZM_LV_3 3//Debug level 3, Show all
+
+#define ZM_SCANMSG_LEV ZM_LV_1
+#define ZM_TXMSG_LEV ZM_LV_0//ZM_LV_0
+#define ZM_RXMSG_LEV ZM_LV_0
+#define ZM_MMMSG_LEV ZM_LV_0
+#define ZM_DESMSG_LEV ZM_LV_0//ZM_LV_0
+#define ZM_BUFMSG_LEV ZM_LV_0//ZM_LV_1
+#define ZM_INITMSG_LEV ZM_LV_0
+
+#define zm_msg0_scan(lv, msg) if (ZM_SCANMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_scan(lv, msg, val) if (ZM_SCANMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_scan(lv, msg, val) if (ZM_SCANMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#define zm_msg0_tx(lv, msg) if (ZM_TXMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_tx(lv, msg, val) if (ZM_TXMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_tx(lv, msg, val) if (ZM_TXMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#define zm_msg0_rx(lv, msg) if (ZM_RXMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_rx(lv, msg, val) if (ZM_RXMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_rx(lv, msg, val) if (ZM_RXMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#define zm_msg0_mm(lv, msg) if (ZM_MMMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_mm(lv, msg, val) if (ZM_MMMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_mm(lv, msg, val) if (ZM_MMMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#define zm_msg0_des(lv, msg) if (ZM_DESMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_des(lv, msg, val) if (ZM_DESMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_des(lv, msg, val) if (ZM_DESMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#define zm_msg0_buf(lv, msg) if (ZM_BUFMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_buf(lv, msg, val) if (ZM_BUFMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_buf(lv, msg, val) if (ZM_BUFMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#define zm_msg0_init(lv, msg) if (ZM_INITMSG_LEV >= lv) \
+ {zm_debug_msg0(msg);}
+#define zm_msg1_init(lv, msg, val) if (ZM_INITMSG_LEV >= lv) \
+ {zm_debug_msg1(msg, val);}
+#define zm_msg2_init(lv, msg, val) if (ZM_INITMSG_LEV >= lv) \
+ {zm_debug_msg2(msg, val);}
+
+#define ZM_MAX_AP_SUPPORT 2 /* Must <= 8 */
+#define ZM_MAX_WDS_SUPPORT 6 /* Must <= 6 */
+#define ZM_MAX_STA_SUPPORT 16 /* Must <= 64 */
+
+/* STA table state */
+#define ZM_STATE_AUTH 1
+#define ZM_STATE_PREAUTH 2
+#define ZM_STATE_ASOC 3
+
+/* Rate set */
+#define ZM_RATE_SET_CCK 0
+#define ZM_RATE_SET_OFDM 1
+
+/* HT PT */
+#define ZM_PREAMBLE_TYPE_MIXED_MODE 0
+#define ZM_PREAMBLE_TYPE_GREEN_FIELD 1
+
+/* HT bandwidth */
+#define ZM_BANDWIDTH_20MHZ 0
+#define ZM_BANDWIDTH_40MHZ 1
+
+/* MIC status */
+#define ZM_MIC_SUCCESS 0
+#define ZM_MIC_FAILURE 1
+
+/* ICV status */
+#define ZM_ICV_SUCCESS 0
+#define ZM_ICV_FAILURE 1
+
+/* definition check */
+#if (ZM_MAX_AP_SUPPORT > 8)
+definition error, ZM_MAX_AP_SUPPORT > 8
+#endif
+#if (ZM_MAX_AP_SUPPORT > 64)
+definition error, ZM_MAX_STA_SUPPORT > 64
+#endif
+
+/* Transmission Rate information */
+
+/* WLAN frame format */
+#define ZM_PLCP_HEADER_SIZE 5
+#define ZM_ETHERNET_ADDRESS_LENGTH 6
+#define ZM_TIMESTAMP_OFFSET 0
+#define ZM_BEACON_INTERVAL_OFFSET 8
+#define ZM_CAPABILITY_OFFSET 10
+
+/* Reason Code */
+/* An unsolicited notification management frame of */
+/* type Disassocation or Deauthentication was generated. */
+#ifdef ZM_REASON_CODE
+#define ZM_WLAN_REASON_CODE_UNSPECIFIED 1
+#define ZM_WLAN_FRAME_DISASOC_DEAUTH_REASON_CODE 24
+#endif
+
+struct zsWlanManagementFrameHeader
+{
+ //u8_t plcpHdr[ZM_PLCP_HEADER_SIZE];
+ u8_t frameCtrl[2];
+ u8_t duration[2];
+ u8_t da[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t sa[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t bssid[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t seqCtrl[2];
+ u8_t body[1];
+};
+
+struct zsWlanProbeRspFrameHeader
+{
+ //u8_t plcpHdr[ZM_PLCP_HEADER_SIZE];
+ u8_t frameCtrl[2];
+ u8_t duration[2];
+ u8_t da[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t sa[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t bssid[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t seqCtrl[2];
+ u8_t timeStamp[8];
+ u8_t beaconInterval[2];
+ u8_t capability[2];
+ u8_t ssid[ZM_MAX_SSID_LENGTH + 2]; // EID(1) + Length(1) + SSID(32)
+} ;
+
+#define zsWlanBeaconFrameHeader zsWlanProbeRspFrameHeader
+
+struct zsWlanAuthFrameHeader
+{
+ //u8_t plcpHdr[ZM_PLCP_HEADER_SIZE];
+ u8_t frameCtrl[2];
+ u8_t duration[2];
+ u8_t address1[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t address2[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t address3[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t seqCtrl[2];
+ u16_t algo;
+ u16_t seq;
+ u16_t status;
+ u8_t challengeText[255]; // the first 2 bytes are information ID, length
+};
+
+struct zsWlanAssoFrameHeader
+{
+ //u8_t plcpHdr[PLCP_HEADER_SIZE];
+ u8_t frameCtrl[2];
+ u8_t duration[2];
+ u8_t address1[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t address2[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t address3[ZM_ETHERNET_ADDRESS_LENGTH];
+ u8_t seqCtrl[2];
+ u8_t capability[2];
+ u16_t status;
+ u16_t aid;
+ //u8_t supportedRates[10];
+};
+
+struct zsFrag
+{
+ zbuf_t* buf[16];
+ u16_t bufType[16];
+ u16_t seq[16];
+ u8_t flag[16];
+
+};
+
+//================================
+// Hardware related definitions
+//================================
+#define ZM_MAC_REG_BASE 0x1c3000
+
+#define ZM_MAC_REG_ATIM_WINDOW (ZM_MAC_REG_BASE + 0x51C)
+#define ZM_MAC_REG_BCN_PERIOD (ZM_MAC_REG_BASE + 0x520)
+#define ZM_MAC_REG_PRETBTT (ZM_MAC_REG_BASE + 0x524)
+
+#define ZM_MAC_REG_MAC_ADDR_L (ZM_MAC_REG_BASE + 0x610)
+#define ZM_MAC_REG_MAC_ADDR_H (ZM_MAC_REG_BASE + 0x614)
+
+#define ZM_MAC_REG_GROUP_HASH_TBL_L (ZM_MAC_REG_BASE + 0x624)
+#define ZM_MAC_REG_GROUP_HASH_TBL_H (ZM_MAC_REG_BASE + 0x628)
+
+#define ZM_MAC_REG_BASIC_RATE (ZM_MAC_REG_BASE + 0x630)
+#define ZM_MAC_REG_MANDATORY_RATE (ZM_MAC_REG_BASE + 0x634)
+#define ZM_MAC_REG_RTS_CTS_RATE (ZM_MAC_REG_BASE + 0x638)
+#define ZM_MAC_REG_BACKOFF_PROTECT (ZM_MAC_REG_BASE + 0x63c)
+#define ZM_MAC_REG_RX_THRESHOLD (ZM_MAC_REG_BASE + 0x640)
+#define ZM_MAC_REG_RX_PE_DELAY (ZM_MAC_REG_BASE + 0x64C)
+
+#define ZM_MAC_REG_DYNAMIC_SIFS_ACK (ZM_MAC_REG_BASE + 0x658)
+#define ZM_MAC_REG_SNIFFER (ZM_MAC_REG_BASE + 0x674)
+#define ZM_MAC_REG_TX_UNDERRUN (ZM_MAC_REG_BASE + 0x688)
+#define ZM_MAC_REG_RX_TOTAL (ZM_MAC_REG_BASE + 0x6A0)
+#define ZM_MAC_REG_RX_CRC32 (ZM_MAC_REG_BASE + 0x6A4)
+#define ZM_MAC_REG_RX_CRC16 (ZM_MAC_REG_BASE + 0x6A8)
+#define ZM_MAC_REG_RX_ERR_UNI (ZM_MAC_REG_BASE + 0x6AC)
+#define ZM_MAC_REG_RX_OVERRUN (ZM_MAC_REG_BASE + 0x6B0)
+#define ZM_MAC_REG_RX_ERR_MUL (ZM_MAC_REG_BASE + 0x6BC)
+#define ZM_MAC_REG_TX_RETRY (ZM_MAC_REG_BASE + 0x6CC)
+#define ZM_MAC_REG_TX_TOTAL (ZM_MAC_REG_BASE + 0x6F4)
+
+
+#define ZM_MAC_REG_ACK_EXTENSION (ZM_MAC_REG_BASE + 0x690)
+#define ZM_MAC_REG_EIFS_AND_SIFS (ZM_MAC_REG_BASE + 0x698)
+
+#define ZM_MAC_REG_SLOT_TIME (ZM_MAC_REG_BASE + 0x6F0)
+
+#define ZM_MAC_REG_ROLL_CALL_TBL_L (ZM_MAC_REG_BASE + 0x704)
+#define ZM_MAC_REG_ROLL_CALL_TBL_H (ZM_MAC_REG_BASE + 0x708)
+
+#define ZM_MAC_REG_AC0_CW (ZM_MAC_REG_BASE + 0xB00)
+#define ZM_MAC_REG_AC1_CW (ZM_MAC_REG_BASE + 0xB04)
+#define ZM_MAC_REG_AC2_CW (ZM_MAC_REG_BASE + 0xB08)
+#define ZM_MAC_REG_AC3_CW (ZM_MAC_REG_BASE + 0xB0C)
+#define ZM_MAC_REG_AC4_CW (ZM_MAC_REG_BASE + 0xB10)
+#define ZM_MAC_REG_AC1_AC0_AIFS (ZM_MAC_REG_BASE + 0xB14)
+#define ZM_MAC_REG_AC3_AC2_AIFS (ZM_MAC_REG_BASE + 0xB18)
+
+#define ZM_MAC_REG_RETRY_MAX (ZM_MAC_REG_BASE + 0xB28)
+
+#define ZM_MAC_REG_TXOP_NOT_ENOUGH_INDICATION (ZM_MAC_REG_BASE + 0xB30)
+
+#define ZM_MAC_REG_AC1_AC0_TXOP (ZM_MAC_REG_BASE + 0xB44)
+#define ZM_MAC_REG_AC3_AC2_TXOP (ZM_MAC_REG_BASE + 0xB48)
+
+#define ZM_MAC_REG_ACK_TABLE (ZM_MAC_REG_BASE + 0xC00)
+
+#define ZM_MAC_REG_BCN_ADDR (ZM_MAC_REG_BASE + 0xD84)
+#define ZM_MAC_REG_BCN_LENGTH (ZM_MAC_REG_BASE + 0xD88)
+
+#define ZM_MAC_REG_BCN_PLCP (ZM_MAC_REG_BASE + 0xD90)
+#define ZM_MAC_REG_BCN_CTRL (ZM_MAC_REG_BASE + 0xD94)
+
+#define ZM_MAC_REG_BCN_HT1 (ZM_MAC_REG_BASE + 0xDA0)
+#define ZM_MAC_REG_BCN_HT2 (ZM_MAC_REG_BASE + 0xDA4)
+
+
+#define ZM_RX_STATUS_IS_MIC_FAIL(rxStatus) rxStatus->Tail.Data.ErrorIndication & ZM_BIT_6
+
+//================================
+//================================
+
+#ifdef ZM_ENABLE_NATIVE_WIFI
+#define ZM_80211_FRAME_HEADER_LEN 24
+#define ZM_80211_FRAME_TYPE_OFFSET 30 // ZM_80211_FRAME_HEADER_LEN + SNAP
+#define ZM_80211_FRAME_IP_OFFSET 32 // ZM_80211_FRAME_HEADER_LEN + SNAP + TYPE
+#else
+#define ZM_80211_FRAME_HEADER_LEN 14
+#define ZM_80211_FRAME_TYPE_OFFSET 12 // ZM_80211_FRAME_HEADER_LEN + SNAP
+#define ZM_80211_FRAME_IP_OFFSET 14 // ZM_80211_FRAME_HEADER_LEN + SNAP + TYPE
+#endif
+
+#define ZM_BSS_INFO_VALID_BIT 0x01
+#define ZM_BSS_INFO_UPDATED_BIT 0x02
+
+
+
+
+
+#define ZM_ERROR_INDICATION_RX_TIMEOUT 0x01
+#define ZM_ERROR_INDICATION_OVERRUN 0x02
+#define ZM_ERROR_INDICATION_DECRYPT_ERROR 0x04
+#define ZM_ERROR_INDICATION_CRC32_ERROR 0x08
+#define ZM_ERROR_INDICATION_ADDR_NOT_MATCH 0x10
+#define ZM_ERROR_INDICATION_CRC16_ERROR 0x20
+#define ZM_ERROR_INDICATION_MIC_ERROR 0x40
+
+#define ZM_RXMAC_STATUS_MOD_TYPE_CCK 0x00
+#define ZM_RXMAC_STATUS_MOD_TYPE_OFDM 0x01
+#define ZM_RXMAC_STATUS_MOD_TYPE_HT_OFDM 0x02
+#define ZM_RXMAC_STATUS_MOD_TYPE_DL_OFDM 0x03
+#define ZM_RXMAC_STATUS_TOTAL_ERROR 0x80
+
+
+
+
+
+#define ZM_MAX_LED_NUMBER 2
+
+#define ZM_LED_DISABLE_MODE 0x0
+#define ZM_LED_LINK_MODE 0x1
+#define ZM_LED_LINK_TR_MODE 0x2
+#define ZM_LED_TR_ON_MODE 0x3
+#define ZM_LED_TR_OFF_MODE 0x4
+
+#define ZM_LED_CTRL_FLAG_ALPHA 0x1
+
+struct zsLedStruct
+{
+ u32_t counter;
+ u32_t counter100ms;
+ u16_t ledLinkState;
+ u16_t ledMode[ZM_MAX_LED_NUMBER];
+ u32_t txTraffic;
+ u32_t rxTraffic;
+ u8_t LEDCtrlType;
+ u8_t LEDCtrlFlag; // Control Flag for vendors
+ u8_t LEDCtrlFlagFromReg; // Control Flag for vendors in registry
+};
+
+
+//HAL+ capability bits definition
+#define ZM_HP_CAP_11N 0x1
+#define ZM_HP_CAP_11N_ONE_TX_STREAM 0x2
+#define ZM_HP_CAP_2G 0x4
+#define ZM_HP_CAP_5G 0x8
+
+#endif /* #ifndef _WLAN_H */
diff --git a/drivers/staging/otus/Kconfig b/drivers/staging/otus/Kconfig
new file mode 100644
index 000000000000..d549d08fd495
--- /dev/null
+++ b/drivers/staging/otus/Kconfig
@@ -0,0 +1,32 @@
+config OTUS
+ tristate "Atheros OTUS 802.11n USB wireless support"
+ depends on USB && WLAN_80211 && MAC80211
+ default N
+ ---help---
+ Enable support for Atheros 802.11n USB hardware:
+ * UB81 - 2x2 2.4 GHz
+ * UB82 - 2x2 2.4 GHz and 5 GHz
+ * UB83 - 1x2 2.4 GHz
+
+ This includes the following devices currently on the market:
+ Dlink DWA-160A1, Netgear WNDA3100 and WN111v2, TP-Link
+ TL-WN821N, and AVM FRITZ!WLAN N USB Stick.
+
+ This driver requires its own supplicant driver for
+ wpa_supplicant 0.4.8. For your convenience you can find the
+ tarball here:
+
+ http://www.kernel.org/pub/linux/kernel/people/mcgrof/otus/wpa_supplicant-0.4.8_otus.tar.bz2
+
+ Before compiling wpa_supplicant, ensure your .config has at
+ least the following:
+ CONFIG_WIRELESS_EXTENSION=y
+ CONFIG_EAP_WSC=y
+ CONFIG_WSC_IE=y
+ CONFIG_DRIVER_WEXT=y
+ CONFIG_DRIVER_OTUS=y
+
+ After a successful compile, you can use the Atheros device as
+ shown in the example:
+ $ wpa_supplicant -Dotus -i <atheros device from ifconfig> -c /path/to/wpa_supplicant.conf -d
+
diff --git a/drivers/staging/otus/Makefile b/drivers/staging/otus/Makefile
new file mode 100644
index 000000000000..debcc5cbf876
--- /dev/null
+++ b/drivers/staging/otus/Makefile
@@ -0,0 +1,67 @@
+obj-$(CONFIG_OTUS) += arusb_lnx.o
+
+EXTRA_CFLAGS += -DAMAC
+EXTRA_CFLAGS += -DGCCK
+EXTRA_CFLAGS += -DOFDM
+EXTRA_CFLAGS += -DTXQ_IN_ISR
+EXTRA_CFLAGS += -DWLAN_HOSTIF=0 #0:USB, 1:PCI
+
+#Test Mode
+EXTRA_CFLAGS += -DZM_USB_STREAM_MODE=1
+EXTRA_CFLAGS += -DZM_USB_TX_STREAM_MODE=0
+EXTRA_CFLAGS += -DZM_PCI_DMA_TEST=0
+EXTRA_CFLAGS += -DZM_LARGEPAYLOAD_TEST=0
+EXTRA_CFLAGS += -DZM_FW_LOOP_BACK=0
+EXTRA_CFLAGS += -DZM_LINUX_TPC=1
+#EXTRA_CFLAGS += -DZM_DONT_COPY_RX_BUFFER
+
+EXTRA_CFLAGS += -DZM_HOSTAPD_SUPPORT
+#EXTRA_CFLAGS += -DfTX_GAIN_OFDM=0
+#EXTRA_CFLAGS += -DZM_CONFIG_BIG_ENDIAN -DBIG_ENDIAN
+EXTRA_CFLAGS += -DZM_HALPLUS_LOCK
+EXTRA_CFLAGS += -DZM_OTUS_LINUX_PHASE_2
+
+arusb_lnx-objs := \
+ usbdrv.o \
+ zdusb.o \
+ ioctl.o \
+ wrap_buf.o \
+ wrap_mem.o \
+ wrap_ev.o \
+ wrap_usb.o \
+ wrap_pkt.o \
+ wrap_dbg.o \
+ wrap_mis.o \
+ wrap_sec.o \
+ wwrap.o \
+ 80211core/ccmd.o \
+ 80211core/chb.o \
+ 80211core/cinit.o \
+ 80211core/cmm.o \
+ 80211core/cmmap.o \
+ 80211core/cmmsta.o \
+ 80211core/cfunc.o \
+ 80211core/coid.o \
+ 80211core/ctkip.o \
+ 80211core/ctxrx.o \
+ 80211core/cic.o \
+ 80211core/cpsmgr.o \
+ 80211core/cscanmgr.o \
+ 80211core/ratectrl.o \
+ 80211core/ledmgr.o \
+ 80211core/amsdu.o \
+ 80211core/cwm.o \
+ 80211core/cagg.o \
+ 80211core/queue.o \
+ 80211core/freqctrl.o \
+ 80211core/cwep.o \
+ hal/hprw.o \
+ hal/hpmain.o \
+ hal/hpusb.o \
+ hal/hpreg.o \
+ hal/hpfwuinit.o \
+ hal/hpfwbu.o \
+ hal/hpfw2.o \
+ hal/hpDKfwu.o \
+ hal/hpfwspiu.o \
+ hal/hpani.o
diff --git a/drivers/staging/otus/TODO b/drivers/staging/otus/TODO
new file mode 100644
index 000000000000..e912293ed1ed
--- /dev/null
+++ b/drivers/staging/otus/TODO
@@ -0,0 +1,9 @@
+TODO:
+ - checkpatch.pl cleanups
+ - sparse cleanups
+ - port to in-kernel 80211 stack
+ - proper network developer maintainer
+
+Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
+Luis Rodriguez <Luis.Rodriguez@Atheros.com> and the
+otus-devel@lists.madwifi-project.org mailing list.
diff --git a/drivers/staging/otus/apdbg.c b/drivers/staging/otus/apdbg.c
new file mode 100644
index 000000000000..d3e2f6224196
--- /dev/null
+++ b/drivers/staging/otus/apdbg.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : apdbg.c */
+/* */
+/* Abstract */
+/* Debug tools */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <linux/sockios.h>
+
+#define ZM_IOCTL_REG_READ 0x01
+#define ZM_IOCTL_REG_WRITE 0x02
+#define ZM_IOCTL_MEM_DUMP 0x03
+#define ZM_IOCTL_REG_DUMP 0x05
+#define ZM_IOCTL_TXD_DUMP 0x06
+#define ZM_IOCTL_RXD_DUMP 0x07
+#define ZM_IOCTL_MEM_READ 0x0B
+#define ZM_IOCTL_MEM_WRITE 0x0C
+#define ZM_IOCTL_DMA_TEST 0x10
+#define ZM_IOCTL_REG_TEST 0x11
+#define ZM_IOCTL_TEST 0x80
+#define ZM_IOCTL_TALLY 0x81 //CWYang(+)
+#define ZM_IOCTL_RTS 0xA0
+#define ZM_IOCTL_MIX_MODE 0xA1
+#define ZM_IOCTL_FRAG 0xA2
+#define ZM_IOCTL_SCAN 0xA3
+#define ZM_IOCTL_KEY 0xA4
+#define ZM_IOCTL_RATE 0xA5
+#define ZM_IOCTL_ENCRYPTION_MODE 0xA6
+#define ZM_IOCTL_GET_TXCNT 0xA7
+#define ZM_IOCTL_GET_DEAGG_CNT 0xA8
+#define ZM_IOCTL_DURATION_MODE 0xA9
+#define ZM_IOCTL_SET_AES_KEY 0xAA
+#define ZM_IOCTL_SET_AES_MODE 0xAB
+#define ZM_IOCTL_SIGNAL_STRENGTH 0xAC //CWYang(+)
+#define ZM_IOCTL_SIGNAL_QUALITY 0xAD //CWYang(+)
+#define ZM_IOCTL_SET_PIBSS_MODE 0xAE
+#define ZDAPIOCTL SIOCDEVPRIVATE
+
+struct zdap_ioctl {
+ unsigned short cmd; /* Command to run */
+ unsigned int addr; /* Length of the data buffer */
+ unsigned int value; /* Pointer to the data buffer */
+ unsigned char data[0x100];
+};
+
+/* Declaration of macro and function for handling WEP Keys */
+
+#if 0
+
+#define SKIP_ELEM { \
+ while(isxdigit(*p)) \
+ p++; \
+}
+
+#define SKIP_DELIMETER { \
+ if(*p == ':' || *p == ' ') \
+ p++; \
+}
+
+#endif
+
+char hex(char);
+unsigned char asctohex(char *str);
+
+char *prgname;
+
+int set_ioctl(int sock, struct ifreq *req)
+{
+ if (ioctl(sock, ZDAPIOCTL, req) < 0) {
+ fprintf(stderr, "%s: ioctl(SIOCGIFMAP): %s\n",
+ prgname, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int read_reg(int sock, struct ifreq *req)
+{
+ struct zdap_ioctl *zdreq = 0;
+
+ if (!set_ioctl(sock, req))
+ return -1;
+
+ //zdreq = (struct zdap_ioctl *)req->ifr_data;
+ //printf( "reg = %4x, value = %4x\n", zdreq->addr, zdreq->value);
+
+ return 0;
+}
+
+
+int read_mem(int sock, struct ifreq *req)
+{
+ struct zdap_ioctl *zdreq = 0;
+ int i;
+
+ if (!set_ioctl(sock, req))
+ return -1;
+
+ /*zdreq = (struct zdap_ioctl *)req->ifr_data;
+ printf( "dump mem from %x, length = %x\n", zdreq->addr, zdreq->value);
+
+ for (i=0; i<zdreq->value; i++) {
+ printf("%02x", zdreq->data[i]);
+ printf(" ");
+
+ if ((i>0) && ((i+1)%16 == 0))
+ printf("\n");
+ }*/
+
+ return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+ int sock;
+ int addr, value;
+ struct ifreq req;
+ char *action = NULL;
+ struct zdap_ioctl zdreq;
+
+ prgname = argv[0];
+
+ if (argc < 3) {
+ fprintf(stderr,"%s: usage is \"%s <ifname> <operation> [<address>] [<value>]\"\n",
+ prgname, prgname);
+ fprintf(stderr,"valid operation: read, write, mem, reg,\n");
+ fprintf(stderr," : txd, rxd, rmem, wmem\n");
+ fprintf(stderr," : dmat, regt, test\n");
+
+ fprintf(stderr," scan, Channel Scan\n");
+ fprintf(stderr," rts <decimal>, Set RTS Threshold\n");
+ fprintf(stderr," frag <decimal>, Set Fragment Threshold\n");
+ fprintf(stderr," rate <0-28>, 0:AUTO, 1-4:CCK, 5-12:OFDM, 13-28:HT\n");
+ fprintf(stderr," TBD mix <0 or 1>, Set 1 to enable mixed mode\n");
+ fprintf(stderr," enc, <0-3>, 0=>OPEN, 1=>WEP64, 2=>WEP128, 3=>WEP256\n");
+ fprintf(stderr," skey <key>, Set WEP key\n");
+ fprintf(stderr," txcnt, Get TxQ Cnt\n");
+ fprintf(stderr," dagcnt, Get Deaggregate Cnt\n");
+ fprintf(stderr," durmode <mode>, Set Duration Mode 0=>HW, 1=>SW\n");
+ fprintf(stderr," aeskey <user> <key>\n");
+ fprintf(stderr," aesmode <mode>\n");
+ fprintf(stderr," wlanmode <0,1> 0:Station mode, 1:PIBSS mode\n");
+ fprintf(stderr," tal <0,1>, Get Current Tally Info, 0=>read, 1=>read and reset\n");
+
+ exit(1);
+ }
+
+ strcpy(req.ifr_name, argv[1]);
+ zdreq.addr = 0;
+ zdreq.value = 0;
+
+ /* a silly raw socket just for ioctl()ling it */
+ sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ if (sock < 0) {
+ fprintf(stderr, "%s: socket(): %s\n", argv[0], strerror(errno));
+ exit(1);
+ }
+
+ if (argc >= 4)
+ {
+ sscanf(argv[3], "%x", &addr);
+ }
+
+ if (argc >= 5)
+ {
+ sscanf(argv[4], "%x", &value);
+ }
+
+ zdreq.addr = addr;
+ zdreq.value = value;
+
+ if (!strcmp(argv[2], "read"))
+ {
+ zdreq.cmd = ZM_IOCTL_REG_READ;
+ }
+ else if (!strcmp(argv[2], "mem"))
+ {
+ zdreq.cmd = ZM_IOCTL_MEM_DUMP;
+ }
+ else if (!strcmp(argv[2], "write"))
+ {
+ zdreq.cmd = ZM_IOCTL_REG_WRITE;
+ }
+ else if (!strcmp(argv[2], "reg"))
+ {
+ zdreq.cmd = ZM_IOCTL_REG_DUMP;
+ }
+ else if (!strcmp(argv[2], "txd"))
+ {
+ zdreq.cmd = ZM_IOCTL_TXD_DUMP;
+ }
+ else if (!strcmp(argv[2], "rxd"))
+ {
+ zdreq.cmd = ZM_IOCTL_RXD_DUMP;
+ }
+ else if (!strcmp(argv[2], "rmem"))
+ {
+ zdreq.cmd = ZM_IOCTL_MEM_READ;
+ }
+ else if (!strcmp(argv[2], "wmem"))
+ {
+ zdreq.cmd = ZM_IOCTL_MEM_WRITE;
+ }
+ else if (!strcmp(argv[2], "dmat"))
+ {
+ zdreq.cmd = ZM_IOCTL_DMA_TEST;
+ }
+ else if (!strcmp(argv[2], "regt"))
+ {
+ zdreq.cmd = ZM_IOCTL_REG_TEST;
+ }
+ else if (!strcmp(argv[2], "test"))
+ {
+ zdreq.cmd = ZM_IOCTL_TEST;
+ }
+ else if (!strcmp(argv[2], "tal"))
+ {
+ sscanf(argv[3], "%d", &addr);
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_TALLY;
+ }
+ else if (!strcmp(argv[2], "rts"))
+ {
+ sscanf(argv[3], "%d", &addr);
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_RTS;
+ }
+ else if (!strcmp(argv[2], "mix"))
+ {
+ zdreq.cmd = ZM_IOCTL_MIX_MODE;
+ }
+ else if (!strcmp(argv[2], "frag"))
+ {
+ sscanf(argv[3], "%d", &addr);
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_FRAG;
+ }
+ else if (!strcmp(argv[2], "scan"))
+ {
+ zdreq.cmd = ZM_IOCTL_SCAN;
+ }
+ else if (!strcmp(argv[2], "skey"))
+ {
+ zdreq.cmd = ZM_IOCTL_KEY;
+
+ if (argc >= 4)
+ {
+ unsigned char temp[29];
+ int i;
+ int keyLen;
+ int encType;
+
+ keyLen = strlen(argv[3]);
+
+ if (keyLen == 10)
+ {
+ sscanf(argv[3], "%02x%02x%02x%02x%02x", &temp[0], &temp[1],
+ &temp[2], &temp[3], &temp[4]);
+ }
+ else if (keyLen == 26)
+ {
+ sscanf(argv[3], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ &temp[0], &temp[1], &temp[2], &temp[3], &temp[4],
+ &temp[5], &temp[6], &temp[7], &temp[8], &temp[9],
+ &temp[10], &temp[11], &temp[12]);
+ }
+ else if (keyLen == 58)
+ {
+ sscanf(argv[3], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ &temp[0], &temp[1], &temp[2], &temp[3], &temp[4],
+ &temp[5], &temp[6], &temp[7], &temp[8], &temp[9],
+ &temp[10], &temp[11], &temp[12], &temp[13], &temp[14],
+ &temp[15], &temp[16], &temp[17], &temp[18], &temp[19],
+ &temp[20], &temp[21], &temp[22], &temp[23], &temp[24],
+ &temp[25], &temp[26], &temp[27], &temp[28]);
+ }
+ else
+ {
+ fprintf(stderr, "Invalid key length\n");
+ exit(1);
+ }
+ zdreq.addr = keyLen/2;
+
+ for(i=0; i<zdreq.addr; i++)
+ {
+ zdreq.data[i] = temp[i];
+ }
+ }
+ else
+ {
+ printf("Error : Key required!\n");
+ }
+ }
+ else if (!strcmp(argv[2], "rate"))
+ {
+ sscanf(argv[3], "%d", &addr);
+
+ if (addr > 28)
+ {
+ fprintf(stderr, "Invalid rate, range:0~28\n");
+ exit(1);
+ }
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_RATE;
+ }
+ else if (!strcmp(argv[2], "enc"))
+ {
+ sscanf(argv[3], "%d", &addr);
+
+ if (addr > 3)
+ {
+ fprintf(stderr, "Invalid encryption mode, range:0~3\n");
+ exit(1);
+ }
+
+ if (addr == 2)
+ {
+ addr = 5;
+ }
+ else if (addr == 3)
+ {
+ addr = 6;
+ }
+
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_ENCRYPTION_MODE;
+ }
+ else if (!strcmp(argv[2], "txcnt"))
+ {
+ zdreq.cmd = ZM_IOCTL_GET_TXCNT;
+ }
+ else if (!strcmp(argv[2], "dagcnt"))
+ {
+ sscanf(argv[3], "%d", &addr);
+
+ if (addr != 0 && addr != 1)
+ {
+ fprintf(stderr, "The value should be 0 or 1\n");
+ exit(0);
+ }
+
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_GET_DEAGG_CNT;
+ }
+ else if (!strcmp(argv[2], "durmode"))
+ {
+ sscanf(argv[3], "%d", &addr);
+
+ if (addr != 0 && addr != 1)
+ {
+ fprintf(stderr, "The Duration mode should be 0 or 1\n");
+ exit(0);
+ }
+
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_DURATION_MODE;
+ }
+ else if (!strcmp(argv[2], "aeskey"))
+ {
+ unsigned char temp[16];
+ int i;
+
+ sscanf(argv[3], "%d", &addr);
+
+ sscanf(argv[4], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5], &temp[6], &temp[7], &temp[8], &temp[9], &temp[10], &temp[11], &temp[12], &temp[13], &temp[14], &temp[15]);
+
+ for(i = 0; i < 16; i++)
+ {
+ zdreq.data[i] = temp[i];
+ }
+
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_SET_AES_KEY;
+ }
+ else if (!strcmp(argv[2], "aesmode"))
+ {
+ sscanf(argv[3], "%d", &addr);
+
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_SET_AES_MODE;
+ }
+ else if (!strcmp(argv[2], "wlanmode"))
+ {
+ sscanf(argv[3], "%d", &addr);
+
+ zdreq.addr = addr;
+ zdreq.cmd = ZM_IOCTL_SET_PIBSS_MODE;
+ }
+ else
+ {
+ fprintf(stderr, "error action\n");
+ exit(1);
+ }
+
+ req.ifr_data = (char *)&zdreq;
+ set_ioctl(sock, &req);
+
+fail:
+ exit(0);
+}
+
+unsigned char asctohex(char *str)
+{
+ unsigned char value;
+
+ value = hex(*str) & 0x0f;
+ value = value << 4;
+ str++;
+ value |= hex(*str) & 0x0f;
+
+ return value;
+}
+
+char hex(char v)
+{
+ if(isdigit(v))
+ return v - '0';
+ else if(isxdigit(v))
+ return (tolower(v) - 'a' + 10);
+ else
+ return 0;
+}
+
diff --git a/drivers/staging/otus/athr_common.h b/drivers/staging/otus/athr_common.h
new file mode 100644
index 000000000000..620f78a41d5f
--- /dev/null
+++ b/drivers/staging/otus/athr_common.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : athr_common.h */
+/* */
+/* Abstract */
+/* WPA related function and data structure definitions. */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#ifndef _ATHR_COMMON_H
+#define _ATHR_COMMON_H
+
+#define ZD_IOCTL_WPA (SIOCDEVPRIVATE + 1)
+#define ZD_IOCTL_PARAM (SIOCDEVPRIVATE + 2)
+#define ZD_IOCTL_GETWPAIE (SIOCDEVPRIVATE + 3)
+#define ZD_PARAM_ROAMING 0x0001
+#define ZD_PARAM_PRIVACY 0x0002
+#define ZD_PARAM_WPA 0x0003
+#define ZD_PARAM_COUNTERMEASURES 0x0004
+#define ZD_PARAM_DROPUNENCRYPTED 0x0005
+#define ZD_PARAM_AUTH_ALGS 0x0006
+
+#define ZD_CMD_SET_ENCRYPT_KEY 0x0001
+#define ZD_CMD_SET_MLME 0x0002
+#define ZD_CMD_SCAN_REQ 0x0003
+#define ZD_CMD_SET_GENERIC_ELEMENT 0x0004
+#define ZD_CMD_GET_TSC 0x0005
+
+#define ZD_FLAG_SET_TX_KEY 0x0001
+
+#define ZD_GENERIC_ELEMENT_HDR_LEN \
+((int) (&((struct athr_wlan_param *) 0)->u.generic_elem.data))
+
+#define ZD_CRYPT_ALG_NAME_LEN 16
+#define ZD_MAX_KEY_SIZE 32
+#define ZD_MAX_GENERIC_SIZE 64
+
+#define IEEE80211_ADDR_LEN 6
+#define IEEE80211_MAX_IE_SIZE 256
+
+#ifdef ZM_ENALBE_WAPI
+#define ZM_CMD_WAPI_SETWAPI 0x0001
+#define ZM_CMD_WAPI_GETWAPI 0x0002
+#define ZM_CMD_WAPI_SETKEY 0x0003
+#define ZM_CMD_WAPI_GETKEY 0x0004
+#define ZM_CMD_WAPI_REKEY 0x0005
+
+#define ZM_WAPI_WAI_REQUEST 0x00f1
+#define ZM_WAPI_UNICAST_REKEY 0x00f2
+#define ZM_WAPI_STA_AGING 0x00f3
+#define ZM_WAPI_MULTI_REKEY 0x00f4
+
+#define ZM_WAPI_KEY_SIZE 32
+#define ZM_WAPI_IV_LEN 16
+#endif //ZM_ENALBE_WAPI
+/* structure definition */
+
+struct athr_wlan_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u8 alg[ZD_CRYPT_ALG_NAME_LEN];
+ u32 flags;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[ZD_MAX_KEY_SIZE];
+ } crypt;
+ struct {
+ u32 flags_and;
+ u32 flags_or;
+ } set_flags_sta;
+ struct {
+ u8 len;
+ u8 data[ZD_MAX_GENERIC_SIZE];
+ } generic_elem;
+ struct {
+#define MLME_STA_DEAUTH 0
+#define MLME_STA_DISASSOC 1
+ u16 cmd;
+ u16 reason_code;
+ } mlme;
+ struct {
+ u8 ssid_len;
+ u8 ssid[32];
+ } scan_req;
+ } u;
+};
+
+struct ieee80211req_wpaie {
+ u8 wpa_macaddr[IEEE80211_ADDR_LEN];
+ u8 wpa_ie[IEEE80211_MAX_IE_SIZE];
+};
+
+#ifdef ZM_ENALBE_WAPI
+struct athr_wapi_param {
+ u16 cmd;
+ u16 len;
+
+ union {
+ struct {
+ u8 sta_addr[ETH_ALEN];
+ u8 reserved;
+ u8 keyid;
+ u8 key[ZM_WAPI_KEY_SIZE];
+ } crypt;
+ struct {
+ u8 wapi_policy;
+ } info;
+ } u;
+};
+
+struct athr_wapi_sta_info
+{
+ u16 msg_type;
+ u16 datalen;
+ u8 sta_mac[ETH_ALEN];
+ u8 reserve_data[2];
+ u8 gsn[ZM_WAPI_IV_LEN];
+ u8 wie[256];
+};
+#endif //ZM_ENALBE_WAPI
+#endif
diff --git a/drivers/staging/otus/hal/hpDKfwu.c b/drivers/staging/otus/hal/hpDKfwu.c
new file mode 100644
index 000000000000..144c62dc8da2
--- /dev/null
+++ b/drivers/staging/otus/hal/hpDKfwu.c
@@ -0,0 +1,832 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+
+const u32_t zcDKFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE3E7FFC, 0xE114D73E,
+0x1E13D43E, 0x1E4C470B, 0x0009B017, 0x956EE600,
+0xC84060E2, 0x2F028F03, 0x8FF93652, 0xD4387601,
+0x4E0BDE38, 0xD4380009, 0x00094E0B, 0x4E0BD437,
+0x7F040009, 0xA0364F26, 0x4F226EF6, 0x410BD134,
+0xD4340009, 0x0009440B, 0x450BD533, 0xD7330009,
+0xD233E1FF, 0x2712611D, 0xD4325029, 0xE1FFCB01,
+0x1209E501, 0x12112212, 0xD52F2452, 0xD22F9740,
+0xE7002572, 0xD42FD12E, 0x2270D62F, 0x2172E201,
+0x26202420, 0xE4FFD62D, 0xE6002641, 0xE104D52C,
+0x6063666D, 0x626D7601, 0x32124000, 0x05458FF8,
+0x000B4F26, 0xEAC80009, 0xDB266AAC, 0xDD27DC26,
+0xD828DE27, 0x4C0BE901, 0x4D0B0009, 0x4E0B0009,
+0x60B20009, 0x89078801, 0x6242D423, 0x890332A6,
+0x6050D522, 0x8BEE8801, 0x2B92D41F, 0x26686642,
+0x480B89E9, 0xD51D0009, 0xAFE4E200, 0x27102520,
+0x00000FA0, 0x001C001C, 0x00200ED4, 0x0000B38E,
+0x00202F90, 0x00201356, 0x00202F9C, 0x00202FB4,
+0x00201314, 0x00201412, 0x00200EF8, 0x001C3510,
+0x001C3624, 0x001E212C, 0x00202F00, 0x00202A9C,
+0x00202F08, 0x00202F14, 0x00202F20, 0x00202F22,
+0x00202F26, 0x001C1028, 0x00201220, 0x0020294C,
+0x00201D10, 0x00201EC8, 0x00203220, 0x00202F24,
+0x2FB62F96, 0x2FD62FC6, 0x4F222FE6, 0xDE947F80,
+0x61E0E024, 0x0F14D493, 0x710161E3, 0xD7926210,
+0x470BE028, 0xD5910F24, 0x0009450B, 0x6D032008,
+0x1F0B8F11, 0xD48FDC8E, 0xDD8F67C0, 0x657C4D0B,
+0xDD8FD18E, 0x6B9C6910, 0x420862B3, 0x32B84208,
+0x3D2C4208, 0xE0281FDB, 0xE58004FC, 0x604C66E2,
+0x3050655C, 0x2D628F13, 0x01FCE024, 0x641CE500,
+0x625DDE84, 0x8B013243, 0x0009A39E, 0x6753655D,
+0x607037EC, 0x39DC6953, 0xAFF27501, 0x20088094,
+0xE0248B13, 0xE50001FC, 0xA009DE7A, 0x655D641C,
+0x32EC6253, 0x6C536B22, 0x3CDC67B2, 0x75041C71,
+0x3243625D, 0xA37F8BF3, 0x88012D10, 0xE0248B16,
+0xE40001FC, 0x671C2D40, 0x624DDE6E, 0x8B013273,
+0x0009A372, 0x6CE3644D, 0x7C046943, 0x39EC6B43,
+0x65923BCC, 0x74086DB2, 0x25D2AFEF, 0x8B198804,
+0x01FCE024, 0x2D70E700, 0x1FD86D1C, 0x627DDE61,
+0x8B0132D3, 0x0009A358, 0x6B73677D, 0x3BEC61E3,
+0x710464B2, 0x3C1C6C73, 0x694265C2, 0x29597708,
+0x2492AFED, 0x8B188805, 0x01FCE024, 0x2D40E400,
+0xDE54671C, 0x3273624D, 0xA33D8B01, 0x644D0009,
+0x6BE36D43, 0x65D23DEC, 0x61437B04, 0x6C1231BC,
+0x74086952, 0xAFED29CB, 0x88312592, 0xDE4A8B20,
+0x65E6DB4A, 0x61E6DC4A, 0x67E2D94A, 0x62E27E04,
+0x1FEC7EE8, 0x7E0464E2, 0x6EE21FED, 0x5BFD2BE0,
+0x60B27B04, 0xC9011FBE, 0x6BB22C00, 0x29B04B09,
+0xDC412F26, 0x66134C0B, 0xE2007F04, 0x2D20A30C,
+0x8B218830, 0xD939DE38, 0xE06465E6, 0x720462E3,
+0x672666E2, 0x6E23DC36, 0x62227EE8, 0x6BE261E6,
+0x29B01FEF, 0x7E040F16, 0xC90160E2, 0x6EE22C00,
+0x4E09DC30, 0x2F262CE0, 0xD130E068, 0x04FE410B,
+0xE2007F04, 0x2D20A2E8, 0x8B058833, 0x4E0BDE2C,
+0xE1000009, 0x2D10A2E0, 0x89018828, 0x0009A106,
+0xE143DE20, 0xE04062E1, 0x3217622D, 0x0FE68F04,
+0x6023E240, 0x262106FE, 0x8B013217, 0x0009A0EF,
+0x02FEE040, 0x8521E401, 0x8B013046, 0x0009A0E7,
+0xE501E040, 0x2D5007FE, 0x6471B2C7, 0x09FEE040,
+0x6291E143, 0x652DE068, 0x8D6B3517, 0xE6400F56,
+0x8B273563, 0xE048E600, 0xE11A0F65, 0x72C0A031,
+0x00117800, 0x00202FB8, 0x00201356, 0x00202480,
+0x00202F1A, 0x00202FBC, 0x002013A2, 0x00202F19,
+0x00202B40, 0x00117804, 0x00117810, 0x00202F15,
+0x00202F16, 0x00202F17, 0x00200B84, 0x00200BD8,
+0x00200BD4, 0x41216153, 0x41214121, 0x41214121,
+0x45214521, 0x60534521, 0x6603C903, 0x0F65E048,
+0xE0077118, 0xE0442209, 0x641D0F25, 0x65F3E04C,
+0x0F46B314, 0x04FDE048, 0x0BFDE044, 0x61BD674D,
+0x41084708, 0x0F16E050, 0xD2936073, 0x420B09FE,
+0x6C07E00F, 0x607329C9, 0xE0400F96, 0x65F30EFE,
+0x6D0D85E2, 0x01FEE050, 0x60D3420B, 0x6073290B,
+0xE04C0F96, 0x04FEB2D9, 0x06FEE040, 0x6261E068,
+0x0F56652D, 0x3563E640, 0xE000894E, 0x602381F8,
+0x4008C903, 0x6B034000, 0xE0546103, 0xE0580FB6,
+0xECFFDD7D, 0x6CCC0FF6, 0x0FD6E06C, 0x4D0B60C3,
+0x42216253, 0x42214221, 0x64234221, 0x324C4200,
+0xE05C6E07, 0x45214200, 0xE0400FE6, 0x0BFE4521,
+0xC9036053, 0x30FC4008, 0x6D037B06, 0x85F81F05,
+0x6C2D1FB7, 0x1FC66E03, 0x0FC6E060, 0x05FEE058,
+0x64C3B2B4, 0x33FCE354, 0x563262D2, 0x22696132,
+0x67B42D22, 0x490B5936, 0x220B607C, 0x05FEE058,
+0x64C32D22, 0x7E01B289, 0xE70662ED, 0x8FE33273,
+0xE0407C01, 0x626106FE, 0x06FEE040, 0x85614200,
+0x302C760C, 0x6103701B, 0x64F3E500, 0x7501E704,
+0x6B5D6966, 0x24923B73, 0x74048FF9, 0xB26C65F3,
+0xE040641D, 0xB20506FE, 0xA1DD6461, 0xD44F0009,
+0xE201D74F, 0x2D20470B, 0x0009A1D6, 0x8B078829,
+0xEC00DE4C, 0x61E22DC0, 0x641DB1D7, 0x0009A1CC,
+0x622CE281, 0x8B013020, 0x0009A118, 0x06FCE028,
+0xE682626C, 0x3260666C, 0xA0EE8B01, 0xE6830009,
+0x3260666C, 0xA0DC8B01, 0xE6900009, 0x3260666C,
+0xA0D08B01, 0xE6910009, 0x3260666C, 0xA0B98B01,
+0xE6B00009, 0x3260666C, 0xA07F8B01, 0xE6BB0009,
+0x3260666C, 0xE6928920, 0x3260666C, 0xE4008B14,
+0xEB04D531, 0x52516652, 0x8B073620, 0x624D7401,
+0x8FF732B7, 0xE6007508, 0x52FBA002, 0xE60152FB,
+0xE6041261, 0x2260A188, 0xD229D428, 0xD4296542,
+0x0009420B, 0x0009A180, 0xE100E670, 0x601336FC,
+0xE0248162, 0x0BFCD21F, 0x6BBC6722, 0x26727BFC,
+0xEB0416B2, 0x06FEE078, 0x3263621D, 0xA16B8B01,
+0xDE1D0009, 0x31EC611D, 0xD41C6E12, 0x410BD114,
+0xE0700009, 0x450BD51A, 0xD41A04FE, 0x420BD210,
+0xD2170009, 0x64E3420B, 0xD60DD417, 0x0009460B,
+0x05FEE070, 0x01FDE074, 0x611DE600, 0x6253351C,
+0x326C666D, 0x22E07601, 0x32B3626D, 0x4E198FF7,
+0xE0747104, 0x0F15AFCE, 0x002029F8, 0x00202FDC,
+0x00201356, 0x00117804, 0x00202B10, 0x00117800,
+0x002013A2, 0x00203014, 0x00117808, 0x00202FF4,
+0x0020139A, 0x00203008, 0x00203010, 0x02FCE024,
+0x672CE07C, 0xEC000F76, 0xE07CEB04, 0x62CD07FE,
+0x8B013273, 0x0009A118, 0x6CCDD7B9, 0x357C65C3,
+0x62C37704, 0xD4B7327C, 0x6D52D7B7, 0x6E22470B,
+0x470BD7B6, 0xD4B664D3, 0x420BD2B3, 0xD2B30009,
+0x64E3420B, 0xD6B0D4B3, 0x0009460B, 0x67D3E600,
+0x376C666D, 0x626D7601, 0x27E032B3, 0x4E198FF7,
+0x7C08AFD3, 0x6212D1A6, 0x2228622C, 0xD2AA8B04,
+0x0009420B, 0x0009A003, 0x420BD2A8, 0x56FB0009,
+0xA0E1E200, 0xB1A62620, 0x56FB0009, 0xA0DBE200,
+0x52FB2620, 0xE500D69A, 0x65622250, 0x7604D2A0,
+0x62622252, 0xA0CFD69F, 0x56FB2620, 0x2610E124,
+0x5217D19D, 0x52181621, 0x52191622, 0x521A1623,
+0x551B1624, 0x1655E200, 0x1656551C, 0x1657551D,
+0x1658551E, 0x1659551F, 0x11281127, 0x112A1129,
+0x112C112B, 0x112E112D, 0x112FA0AE, 0xD68FD18E,
+0x6262E040, 0x76046512, 0x2152352C, 0x55116266,
+0x1151352C, 0x62626563, 0x75085612, 0x1162362C,
+0x56136252, 0x362C75EC, 0x62521163, 0x75105614,
+0x1164362C, 0x62526653, 0x76105515, 0x1155352C,
+0x56166262, 0x362CD57E, 0x62561166, 0x362C5617,
+0x66531167, 0x55186252, 0x352C7604, 0x62661158,
+0x352C5519, 0x65631159, 0x561A6262, 0x362C7504,
+0x6252116A, 0x7504561B, 0x116B362C, 0x561C6256,
+0x116C362C, 0x561D6256, 0x116D362C, 0x62526653,
+0x7604551E, 0x115E352C, 0x561F6262, 0x362CD569,
+0x6252116F, 0x7594061E, 0x0166362C, 0x6653E044,
+0x051E6252, 0x352C7644, 0xE0480156, 0x061E6262,
+0x0166362C, 0xE054D660, 0x051E6262, 0x352C4229,
+0x76040156, 0xE0586262, 0x4229061E, 0x0166362C,
+0xE23856FB, 0xE0442620, 0xE048021E, 0x62121621,
+0x55111622, 0x1653E200, 0x16545512, 0x16555515,
+0x16565513, 0x16575516, 0xE040051E, 0x051E1658,
+0x1659E050, 0x165A5514, 0xE04C051E, 0x051E165B,
+0x165CE054, 0xE058051E, 0x051E165D, 0x165EE044,
+0xE0480126, 0x11212122, 0x11251122, 0x11261123,
+0xE0400126, 0xE0500126, 0x01261124, 0x0126E04C,
+0x0126E054, 0x0126E058, 0x3F3C9358, 0x6EF64F26,
+0x6CF66DF6, 0x000B6BF6, 0x4F2269F6, 0xE240614D,
+0x89143123, 0x3127E21F, 0x8B09D734, 0xD434614D,
+0xE00171E0, 0x5671440B, 0x26596507, 0x1761A007,
+0xE001D42F, 0x6672440B, 0x26596507, 0x4F262762,
+0x0009000B, 0x614D4F22, 0x3123E240, 0xE21F8912,
+0xD7263127, 0x614D8B08, 0x5671D225, 0x420B71E0,
+0x260BE001, 0x1761A006, 0x6672D221, 0xE001420B,
+0x2762260B, 0x000B4F26, 0xE6400009, 0x46284618,
+0x6252D51C, 0x89FC2268, 0x0009000B, 0x4618E680,
+0xD5184628, 0x22686252, 0x000B89FC, 0xA0010009,
+0x7201E200, 0x8BFC3242, 0x0009000B, 0x00000080,
+0x00117804, 0x00202FF4, 0x00201356, 0x0020139A,
+0x00203008, 0x00203010, 0x00200C38, 0x00200C12,
+0x00202F00, 0x00202F14, 0x00202AA4, 0x001C36A0,
+0x001C3CA0, 0x001C36F4, 0x001C3B88, 0x001C3704,
+0x002029F8, 0x001C373C, 0x4618E680, 0xD52F4628,
+0x22686252, 0x000B8BFC, 0x2FE60009, 0x7FFC4F22,
+0xBFF16E53, 0x61E22F42, 0xE280D629, 0x54E11615,
+0x16464218, 0x422855E2, 0x57E31657, 0x16786EF2,
+0x26E22E2B, 0x4F267F04, 0x6EF6AFA8, 0x2FD62FC6,
+0x4F222FE6, 0x6C53DD1E, 0x6E43BFD6, 0x2DE2BF95,
+0x0009BFD2, 0x2C1251D5, 0x1C4154D6, 0x1C5255D7,
+0x1C6356D8, 0x6EF64F26, 0x000B6DF6, 0x61636CF6,
+0xA004E600, 0x62564109, 0x24227601, 0x36127404,
+0x000B8BF9, 0x4F220009, 0xD10FD40E, 0x0009410B,
+0xD40FD20E, 0xE5056022, 0x2202CB20, 0xD50D2452,
+0x450BE700, 0xD70C2472, 0x0009470B, 0xE601D10B,
+0x2162D20B, 0x4F264618, 0x2262000B, 0x001C3700,
+0x001C370C, 0x00203028, 0x00201356, 0x001C3500,
+0x001D4004, 0x002013CC, 0x00200EF8, 0x001E212C,
+0x001C3D30, 0x0009A1A9, 0x2FE62FD6, 0xDD8F4F22,
+0xA0049EA7, 0xD48E0009, 0x420BD28E, 0x62D265D2,
+0x8BF822E8, 0x0009A004, 0xD28AD48B, 0x55D1420B,
+0x22E852D1, 0xA0048BF8, 0xD4880009, 0x420BD285,
+0x52D255D2, 0x8BF822E8, 0x0009A004, 0xD281D484,
+0x55D3420B, 0x22E852D3, 0xA0048BF8, 0xD4810009,
+0x420BD27C, 0x52D455D4, 0x8BF822E8, 0x6EF64F26,
+0x6DF6000B, 0x2FD62FC6, 0x4F222FE6, 0x6E636D73,
+0x6C53B018, 0x64C357F4, 0xB05465E3, 0xB06A66D3,
+0xB09A0009, 0xB09E0009, 0xB0A20009, 0xB0BE0009,
+0xB0C10009, 0xB1240009, 0x4F260009, 0x6DF66EF6,
+0x6CF6A023, 0x3412D16C, 0xD66C0529, 0x2650D76C,
+0x2742000B, 0x0009A014, 0x2FD62FC6, 0x4F222FE6,
+0x6E636D73, 0x6C53BFEE, 0x64C357F4, 0xB02A65E3,
+0xB10666D3, 0x4F260009, 0x6DF66EF6, 0x6CF6A005,
+0xE603D260, 0x000B4618, 0xD25E2262, 0x000BE600,
+0x4F222262, 0xE40ABF7E, 0x0009BF7E, 0xE104D25A,
+0xE5004118, 0x2212E40A, 0x2252BF74, 0x6072D757,
+0x4F26CB20, 0x2702000B, 0xD1554F22, 0xE400410B,
+0x452BD554, 0x2FE64F26, 0x6E63D153, 0x44186612,
+0x45289210, 0x26294408, 0x44084500, 0x4400265B,
+0x4708264B, 0x47082162, 0x27EBD14C, 0x000B2172,
+0x03F06EF6, 0x2FE61FFF, 0xDE494F22, 0xE40AE101,
+0x2E12BF48, 0x726C62E3, 0xE401E100, 0x22122212,
+0x22122212, 0x22122212, 0xE7302242, 0xE40AE503,
+0x22122212, 0x22122212, 0x22122212, 0x22122212,
+0x22122212, 0x22122212, 0x22522272, 0x22122212,
+0x22122212, 0x22122212, 0x22122212, 0x121ABF22,
+0x2E62E600, 0x000B4F26, 0xD2326EF6, 0xE441E101,
+0x000B2212, 0xD1302242, 0xE605D430, 0x000B2162,
+0xD52F2462, 0x6050D22F, 0x8B0E8801, 0x6040D42E,
+0x8B078801, 0x9626D52D, 0x88016050, 0x96238B0C,
+0x0009A00A, 0xA0079621, 0xE6000009, 0x2262D426,
+0x88016040, 0xE6048B00, 0xAEF3E40A, 0xD2242262,
+0xE40AE601, 0x2262AEEE, 0x2FC62FB6, 0x2FE62FD6,
+0xDC204F22, 0x60C2ED00, 0xCB01EB64, 0x60C22C02,
+0xA041C901, 0x03C46E03, 0x034003D4, 0x001C3B88,
+0x0020302C, 0x002013A2, 0x00203034, 0x0020303C,
+0x00203044, 0x0020304C, 0x0025E720, 0x0020321C,
+0x00202F04, 0x001C5968, 0x001D4004, 0x001C3500,
+0x00201154, 0x00201180, 0x001C5814, 0x001C59D0,
+0x001C5830, 0x001C6268, 0x001C59A4, 0x001C639C,
+0x00202F16, 0x001C5804, 0x00202F15, 0x00202F17,
+0x001C581C, 0x001C5860, 0x89073DB2, 0xE40A60C2,
+0xBE9FC901, 0x7D016E03, 0x8BF52EE8, 0x8B033DB2,
+0xD23ED43D, 0x0009420B, 0x4F26E40A, 0x6DF66EF6,
+0xAE8F6CF6, 0x44116BF6, 0x604B8F01, 0x000B6043,
+0x2FB60009, 0x2FD62FC6, 0x4F222FE6, 0xDC347FFC,
+0x60C2ED00, 0xCB02EB64, 0x60C22C02, 0xC9022F02,
+0x6E03A009, 0x89083DB3, 0xE40A60C2, 0xC9022F02,
+0x6E03BE70, 0x2EE87D01, 0x3DB38BF4, 0xD4298B08,
+0x7F04D226, 0x6EF64F26, 0x6CF66DF6, 0x6BF6422B,
+0x4F267F04, 0x6DF66EF6, 0x000B6CF6, 0xD5226BF6,
+0x60525651, 0x000B4628, 0x2FB6306C, 0x2FD62FC6,
+0x4F222FE6, 0x4F024F12, 0x6E43BFF1, 0xDC1B6B03,
+0xBFECDD1B, 0x30B80009, 0x060A3C05, 0x46094609,
+0x3D654601, 0x4209020A, 0x42094209, 0x8BF032E2,
+0x4F164F06, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x4F222FE6, 0xE102DE0F, 0xE403E500, 0xBFD42E12,
+0xE6062E52, 0xE7004618, 0x2E62E403, 0x4F262E72,
+0x6EF6AFCB, 0x0009000B, 0x00203054, 0x00201356,
+0x001C5860, 0x0020306C, 0x001C1040, 0xCCCCCCCD,
+0x10624DD3, 0x001D4004, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE5007FDC, 0x6453E110,
+0x6C534128, 0xED096E53, 0x6653655D, 0x365C4608,
+0x75014608, 0x6043361C, 0x0F66675D, 0xEB0060C3,
+0x26C137D3, 0x81628161, 0x16B28163, 0x16B416E3,
+0x74048FEA, 0xD9A668F2, 0x1981DAA6, 0x59F12982,
+0x1A91D1A5, 0x5AF22A92, 0x5DF45BF3, 0x54F65EF5,
+0x21A211A1, 0x11B211B3, 0x11D411D5, 0x11E611E7,
+0x11481149, 0x55F7EE00, 0x57F8DD9C, 0x64E3D29C,
+0xDB9DD99C, 0xE845EAB8, 0x2D521D51, 0x6AAC2272,
+0x6EED4808, 0x4D086DE3, 0x3DEC65E3, 0x4D084508,
+0x3D9C35EC, 0x450860C3, 0x81D12DC1, 0x4508E050,
+0x45084008, 0x60C381D2, 0xE60035BC, 0x81D334A2,
+0x1D531DD2, 0x8D01D489, 0xD4861D64, 0xB05C65D3,
+0x64ED7E01, 0x8BDC3482, 0xDB88D182, 0xD2806812,
+0x1B814829, 0x2FD26412, 0x2B92694D, 0xD97F6722,
+0x1B734729, 0xD77C6822, 0x1BA26A8D, 0xD2806B72,
+0x22B2D57B, 0xE0035D72, 0x5E7412D2, 0x12E44018,
+0xD67C5176, 0x54781216, 0x1248E103, 0xD4796792,
+0x6852127A, 0x28C1E7FF, 0x81916952, 0x6A52E050,
+0x81A24008, 0x60C36B52, 0x6C5281B3, 0x6E521CC2,
+0x62521E63, 0x1264E600, 0x46086563, 0x7501364C,
+0x665D2672, 0x8BF83613, 0x4F267F24, 0x6DF66EF6,
+0x6BF66CF6, 0x69F66AF6, 0x68F6000B, 0x60616642,
+0x8D04C803, 0x6061E500, 0x8802C903, 0x52628B03,
+0x51246563, 0x000B2412, 0x2FD66053, 0x4F222FE6,
+0x6E537FEC, 0xE5506253, 0xE4006D43, 0xA0014508,
+0x5224E101, 0x22116043, 0x81238121, 0x81226053,
+0x362056E2, 0xD2548BF5, 0x64F316E4, 0x420BE614,
+0x65E165E3, 0x2549E4FC, 0x61F12E51, 0x214965F3,
+0x54D12F11, 0x410BD14C, 0x57D1E614, 0xCB016071,
+0x1DE12701, 0x4F267F14, 0x000B6EF6, 0x2FD66DF6,
+0x4F222FE6, 0x6E537FEC, 0xE5FC6653, 0x60616D43,
+0xCB012059, 0x52E22601, 0x8B063260, 0x51E212E4,
+0x8B0431E0, 0xA00252D1, 0xAFF01E22, 0xD23A5664,
+0xE61464F3, 0x65E3420B, 0xE1FC67E1, 0x2E712719,
+0x54D167F1, 0xD1342719, 0xE61465F3, 0x2F71410B,
+0x602152D1, 0x2201CB01, 0x7F141DE1, 0x6EF64F26,
+0x6DF6000B, 0x4F222FE6, 0xDE23624C, 0x42004208,
+0x3E2CA005, 0xD41F5252, 0xBF8E5624, 0x65E22E62,
+0x352052E1, 0xD6228BF6, 0x4F262622, 0x6EF6000B,
+0x2FC62FB6, 0x2FE62FD6, 0xDC184F22, 0x52C1DB1F,
+0x362066C2, 0x6061891C, 0x8801C903, 0xDE138918,
+0xBF63DD1B, 0x650364E3, 0x66B28503, 0x3262620D,
+0xD40B8907, 0x0009BF9B, 0x4D0BD416, 0xAFE60009,
+0xBF620009, 0xD41464E3, 0x00094D0B, 0x0009AFDF,
+0x2262D212, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x00202B00, 0x00202B08, 0x00202B10, 0x00202B38,
+0x00202F1C, 0x001000B4, 0x00101680, 0x001E2108,
+0x001C3D00, 0x00117880, 0x00200A9E, 0x00202F00,
+0x00201356, 0x00203088, 0x0020308C, 0x001C3D28,
+0x2FC62FB6, 0x2FE62FD6, 0x7FFC4F22, 0x6022D22B,
+0x8D41C803, 0xDE2A2F01, 0xDB2BDC2A, 0xED01A017,
+0xC9036051, 0x89168801, 0xD128D426, 0x0009410B,
+0x61035503, 0xC8208551, 0xE0508903, 0x720102BE,
+0xD2230B26, 0x420B64E3, 0xD6226513, 0x52C126D2,
+0x352065C2, 0xDE208BE4, 0xDB21DD20, 0x52D1DC21,
+0x352065D2, 0x60518918, 0x8801C903, 0xD41B8914,
+0x460BD616, 0x57030009, 0x8F0437E0, 0xE2016503,
+0xAFEC2B20, 0xD4182C52, 0x420BD218, 0xD6110009,
+0x4118E101, 0x2612AFE3, 0xC80460F1, 0xD2148907,
+0x4F267F04, 0x6DF66EF6, 0x422B6CF6, 0x7F046BF6,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x001E2100,
+0x00202B10, 0x00202B08, 0x00202AA4, 0x0020106C,
+0x002010EE, 0x001C3D30, 0x00117880, 0x00202B00,
+0x00202F20, 0x00202F1C, 0x00202B38, 0x0020108A,
+0x00200170, 0xE601D203, 0x1265D503, 0x000B2252,
+0x00001266, 0x001C1010, 0x0000C34F, 0x0009000B,
+0x2FD62FC6, 0x4F222FE6, 0x6D436C53, 0xEE00A004,
+0x7E0164D4, 0x644CBFF2, 0x8BF93EC2, 0x6EF64F26,
+0x000B6DF6, 0xE5006CF6, 0x6643A002, 0x76017501,
+0x22286260, 0xAFE38BFA, 0x2FE60009, 0x75076253,
+0xE1086753, 0x6043EE0A, 0x4409C90F, 0x650330E2,
+0x8D014409, 0xE630E637, 0x4110365C, 0x8FF22760,
+0xE00077FF, 0x000B8028, 0x000B6EF6, 0x000BE000,
+0x2FE6E000, 0x7FEC4F22, 0x6E436253, 0xBFDC65F3,
+0xBFD06423, 0xBFCE64E3, 0xD40364F3, 0x0009BFCB,
+0x4F267F14, 0x6EF6000B, 0x00203090, 0xE4FDD59A,
+0xD69A6152, 0x25122149, 0x74016052, 0x2502CB01,
+0xD1976752, 0x25722749, 0xC8406010, 0x60628902,
+0x2602CB04, 0xE5016062, 0x2602CB08, 0xE4026062,
+0x2602C9CF, 0x45186062, 0x2602CB03, 0x000B1642,
+0xD58C1653, 0xD28DD78C, 0xE100D48D, 0x2511E600,
+0x22102711, 0x2461AFD2, 0xD28A664C, 0x362C4600,
+0xCB106060, 0x2600000B, 0xD286654C, 0x352C4500,
+0xE1EF6650, 0x000B2619, 0x664C2560, 0x4600D282,
+0x6060362C, 0x000BCB10, 0x654C2600, 0x4500D27E,
+0x6650352C, 0x2619E1EF, 0x2560000B, 0xD279664C,
+0x362C4600, 0xCB086060, 0x2600000B, 0xD275654C,
+0x352C4500, 0xE1F76650, 0x000B2619, 0x664C2560,
+0x4600D271, 0x6060362C, 0x000BCB08, 0x654C2600,
+0x4500D26D, 0x6650352C, 0x2619E1F7, 0x2560000B,
+0xD668624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0x624C600C, 0x4200D663, 0x6020326C,
+0x4021C908, 0x40214021, 0x600C000B, 0x644CD15F,
+0x6240341C, 0x602C000B, 0x644CD15D, 0x6240341C,
+0x602C000B, 0x4F222FE6, 0x645C6E43, 0x3467E60A,
+0xBFEB8914, 0x640C0009, 0x880160EC, 0xE00F8B02,
+0x2409A002, 0x44094409, 0xE60A624C, 0x89053263,
+0x644CBFE2, 0x6023620C, 0x8B00C880, 0x6023E200,
+0x000B4F26, 0x4F226EF6, 0x6062D64A, 0x8B038801,
+0x0009B246, 0x0009A003, 0xE640D247, 0xD6472260,
+0x4F26E200, 0x2622000B, 0xD6424F22, 0x88026062,
+0xB28F8B01, 0xD6410009, 0x4F26E200, 0x2622000B,
+0xD43DD53C, 0xE701E100, 0x000B2512, 0xD23A2470,
+0x000BE604, 0x4F222260, 0xD13AD439, 0x0009410B,
+0xE1FDD539, 0xD2396650, 0xE7002619, 0x4F262560,
+0x2270000B, 0xD4364F22, 0x410BD132, 0xD5320009,
+0x6650E7FB, 0x4F262679, 0x2560000B, 0xD4314F22,
+0x410BD12C, 0xD52C0009, 0x6650E7F7, 0x4F262679,
+0x2560000B, 0x942DD528, 0x22496250, 0x2520000B,
+0xE4BFD525, 0x22496250, 0x2520000B, 0xD2264F22,
+0x600D8522, 0x89112008, 0x89138801, 0x89158803,
+0x89438805, 0x89498806, 0x894F8808, 0x89558809,
+0x895B880A, 0x8961880B, 0x0009A068, 0x0009B06A,
+0x600CA065, 0x0009B078, 0x600CA061, 0x0009B081,
+0x600CA05D, 0x0000FF7F, 0x001E2148, 0x001E1108,
+0x001E1000, 0x00202F60, 0x00202F62, 0x00202F81,
+0x00202F44, 0x001E103F, 0x001E105F, 0x001E102F,
+0x001E1090, 0x00202F68, 0x001E100B, 0x00202F64,
+0x00203094, 0x00201356, 0x001E1028, 0x00202F80,
+0x002030A0, 0x002030B0, 0x00202F38, 0x6260D684,
+0x8B2B2228, 0x0009B061, 0x600CA029, 0x6260D680,
+0x8B232228, 0x0009B069, 0x600CA021, 0x6260D67C,
+0x8B1B2228, 0x0009B0C7, 0x600CA019, 0x6260D678,
+0x8B132228, 0x0009B0CD, 0x600CA011, 0x6260D674,
+0x8B0B2228, 0x0009B125, 0x600CA009, 0x6260D670,
+0x8B032228, 0x0009B13D, 0x600CA001, 0x4F26E000,
+0x0009000B, 0xD26CD16B, 0xD56C8412, 0x4000C90F,
+0xD76B012D, 0xE403D66B, 0xE20F611C, 0x2540E001,
+0x25202712, 0x2602000B, 0xE601D262, 0x30668523,
+0xE0008D05, 0xD663D260, 0xE0018122, 0x000B2602,
+0xD25C0009, 0x600D8523, 0x89052008, 0x8B0A8801,
+0x6060D65D, 0x2600CB01, 0xD457D65A, 0xE001E101,
+0x000B2612, 0x000B8142, 0xD152E000, 0x8513E501,
+0x640D4518, 0x66033453, 0xE0008D05, 0xD551D253,
+0x2260E001, 0x000B2502, 0x4F220009, 0x8513D149,
+0x6453650D, 0x62494419, 0x227D672E, 0x8801602C,
+0x88028909, 0x88038910, 0x8806891A, 0x88078935,
+0xA04C893B, 0xD5460009, 0x6652D746, 0x2762D446,
+0x622C6261, 0x2421A038, 0x2228625C, 0xD4438B3F,
+0x6642D540, 0x2562D440, 0x24018561, 0x6203A02C,
+0x2008605C, 0x88108907, 0x88208908, 0x88308909,
+0xA02C890A, 0xD23A0009, 0x6222A008, 0xA005D239,
+0xD2396222, 0x6222A002, 0x6262D638, 0xD432D531,
+0x66212522, 0xA00F626C, 0xD6352421, 0x6261D52D,
+0x622CD42D, 0xA0072562, 0xD6322421, 0x8561D529,
+0x2562D429, 0x62032401, 0x662D8515, 0x3617610D,
+0x65038F01, 0xB0CB2451, 0xA0010009, 0xE000E001,
+0x000B4F26, 0xD6190009, 0xD427E101, 0x65412610,
+0xD118D717, 0xE20F655D, 0x2752E001, 0x000B2620,
+0x2FE62102, 0xD20F4F22, 0x640C8523, 0x8B082448,
+0xD511D61D, 0x2621E200, 0x940F8451, 0xA0482049,
+0xDE0D8051, 0xC84060E0, 0xE2018D32, 0x89443427,
+0xD216D615, 0x2641420B, 0x0009A030, 0x0000FF7F,
+0x00202F81, 0x00202F38, 0x00202F44, 0x001E1100,
+0x001E100C, 0x00202F64, 0x001E1000, 0x001E1001,
+0x00202F6C, 0x00202F4C, 0x00202F50, 0x00202F54,
+0x00202F70, 0x00202F74, 0x00202F78, 0x00202F7C,
+0x00203280, 0x0020328A, 0x00202F5E, 0x0020225A,
+0x89123427, 0xD294D693, 0x2641420B, 0xCB8084E1,
+0x80E1B0F5, 0xD69160E0, 0x2E00CB04, 0xC93F6060,
+0xD68F2600, 0xA001E001, 0xE0002602, 0x000B4F26,
+0xD68C6EF6, 0xC8806060, 0xD2868919, 0x88016021,
+0xD2898B15, 0x8524E501, 0x89103056, 0xE203D187,
+0x2120D487, 0xE00B6541, 0x0656655D, 0xE40FD585,
+0x2140E702, 0xD77E2571, 0x000BE001, 0x000B2702,
+0x2FE6E000, 0xDE804F22, 0xC88084E1, 0xD57A892C,
+0x20088554, 0x61038F28, 0x8553D77C, 0x64036672,
+0x8566650C, 0x3520620C, 0xD6798B1E, 0x651CD774,
+0x2651644C, 0x60E02741, 0x8904C840, 0x420BD275,
+0xA0030009, 0xD2680009, 0x0009420B, 0x0009B09F,
+0xE201D167, 0x60E02122, 0xCB04D464, 0x60402E00,
+0x2400C93F, 0x6023A001, 0x4F26E000, 0x6EF6000B,
+0x2FB62FA6, 0x2FD62FC6, 0xDA622FE6, 0x66A1E240,
+0x3622DC5E, 0x62638900, 0x6ED36D2C, 0x4E2136D8,
+0x4E212A61, 0xDB61D460, 0xE700A00F, 0x770162B2,
+0x71026123, 0x66212B12, 0x71026213, 0x61212B12,
+0x651D666D, 0x356C4528, 0x627C2452, 0x8BED32E3,
+0xC90360D3, 0x8B108803, 0x617367B2, 0x2B127102,
+0x71026E13, 0x2B126571, 0x655D6DE1, 0x422862DD,
+0x325CE107, 0xA00C2C10, 0x88022422, 0xA0038B01,
+0x8801E203, 0xE2018B05, 0x66B22C20, 0x655D6561,
+0xE60F2452, 0x67A12C60, 0x8B052778, 0xDD38DC44,
+0xEB01EA00, 0x2DB22CA2, 0x6DF66EF6, 0x6BF66CF6,
+0x6AF6000B, 0x2FE62FD6, 0xE240DD36, 0x362266D1,
+0x62638900, 0x3678672C, 0x7703DE38, 0x47212D61,
+0x64E2D635, 0xA00E4721, 0x6562E100, 0x62537101,
+0x74012450, 0x24204219, 0x45297401, 0x74012450,
+0x24504519, 0x621C7401, 0x8BEE3273, 0x66E24200,
+0x420061D1, 0x2118362C, 0x2E628F06, 0xDD1CD728,
+0xE501E400, 0x2D522742, 0x000B6EF6, 0x2FD66DF6,
+0x4F222FE6, 0xED0AEE01, 0x64E3BC96, 0xBC9B64E3,
+0x62EC7E01, 0x8BF732D7, 0xBC9EEE01, 0x64E364E3,
+0x7E01BCA3, 0x32D762EC, 0x4F268BF7, 0x000B6EF6,
+0xD1186DF6, 0xD418920D, 0x72122122, 0x2422D617,
+0xD7177204, 0x72202622, 0x2722D116, 0x000B7230,
+0x137A2122, 0x00202F5E, 0x00202366, 0x001E1015,
+0x00202F64, 0x001E1001, 0x00202F38, 0x001E1100,
+0x00202F62, 0x00202F50, 0x001E1000, 0x00202F54,
+0x00202F60, 0x0020225A, 0x001E100C, 0x00202F4C,
+0x00202F68, 0x00202F6C, 0x00202F70, 0x00202F74,
+0x00202F78, 0x00202F7C, 0x4F222FE6, 0xD6507FFC,
+0x88016060, 0xE2018951, 0x2620BFBB, 0xD54ED14D,
+0xDE4E6010, 0x64E36552, 0x7402C840, 0x8D22D14C,
+0xD24C7502, 0xE601D74C, 0xE7042722, 0x76016255,
+0x626C2421, 0x8FF93273, 0xD4437402, 0x6242E601,
+0x640D8528, 0x67494419, 0x275D657E, 0x81E4607C,
+0xE417D542, 0x67557601, 0x3243626C, 0x8FF92171,
+0xA0207102, 0xD23E0009, 0xE601D73B, 0xE7042722,
+0x76016255, 0x626C2421, 0x8FF93273, 0xD4327402,
+0x6242E601, 0x640D8528, 0x67494419, 0x275D657E,
+0x81E4607C, 0xE417D533, 0x67557601, 0x3243626C,
+0x8FF92171, 0x924A7102, 0xD2262E21, 0x5E23D72E,
+0x64F22FE2, 0x604365F2, 0x2700C980, 0xC9606043,
+0x80716103, 0xC9036043, 0x80724519, 0x65F2605C,
+0x817266F2, 0x46194629, 0x606C4529, 0x4018645C,
+0x8173304C, 0x21185E23, 0x64F22FE2, 0x6E4C62F2,
+0x602C4219, 0x66F262F2, 0x46294018, 0x461930EC,
+0x42298174, 0x652C606C, 0x305C4018, 0x81758F07,
+0x0009BC9C, 0x2228620C, 0xA00A8908, 0x60130009,
+0x8B038840, 0x0009B009, 0x0009A003, 0xE202D60F,
+0x7F042622, 0x000B4F26, 0x000B6EF6, 0x060A0009,
+0x00202F80, 0x001E1000, 0x00202F6C, 0x00203280,
+0x0020328C, 0x00203224, 0x00202F54, 0x00203254,
+0x00203252, 0x00203226, 0x00202F38, 0x00202F64,
+0x4F222FE6, 0xDE937FFC, 0x200884E9, 0x2F008D06,
+0xD692D491, 0x0009460B, 0x64F0B194, 0x6620D290,
+0x89022668, 0xC9BF60E0, 0x7F042E00, 0x000B4F26,
+0x000B6EF6, 0x2FE60009, 0xDE8A4F22, 0x60E0D68A,
+0xCBC0D48A, 0x62602E00, 0xC803602C, 0x40218904,
+0x70014021, 0x6603A002, 0x66034009, 0xD684616D,
+0xE500A004, 0x75016262, 0x74042422, 0x3213625D,
+0xD2808BF8, 0x0009420B, 0xC9BF84E2, 0x4F2680E2,
+0x6EF6000B, 0x2FE62FD6, 0x7FFC4F22, 0x6260D67A,
+0x89442228, 0xD56FE100, 0x60502610, 0xCB40D477,
+0x2500440B, 0x8D052008, 0x62E06E03, 0x7104612C,
+0x2F11A006, 0xD472D66A, 0xDD726760, 0x657C4D0B,
+0xE23C6D1D, 0x8B033D27, 0xD264D46F, 0x0009420B,
+0x4D214D21, 0xA005D76D, 0x66E6E400, 0x357C4508,
+0x74012562, 0x35D3654D, 0xD7698BF7, 0x6172E003,
+0x81114018, 0x6E7260F1, 0x81E2700C, 0xD4656172,
+0xDD658113, 0x4D0BDE65, 0xE2016572, 0xD4642E22,
+0x420BD252, 0xD6530009, 0xC93F6060, 0x7F042600,
+0x6EF64F26, 0x6DF6000B, 0x2FC62FB6, 0x2FE62FD6,
+0xD25C4F22, 0x6B436E73, 0x420B6C53, 0x20086D63,
+0x61038F08, 0xD245D458, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6422B, 0x21B060C3, 0x60D38011, 0xE5008111,
+0x64BCA007, 0x6053655D, 0x665300EC, 0x7501361C,
+0x625D8064, 0x8BF53243, 0x6060D636, 0x2600C9BF,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x7FC44F22,
+0x720262F3, 0x22512F41, 0x45297202, 0x60632251,
+0xE5C4E682, 0x67F38121, 0x655C666C, 0xE408BFBC,
+0x4F267F3C, 0x0009000B, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE1007FC4, 0x6513ECFF,
+0x6B136CCD, 0xDE36D735, 0xEDFF64F3, 0xD835EA04,
+0x6053655C, 0x027D4000, 0x32C0622D, 0x66038D0D,
+0x09ED6063, 0x2491027D, 0x24217402, 0x698202ED,
+0x3928622D, 0x74022892, 0x75017104, 0x6063625C,
+0x07D532A2, 0x0EB58FE4, 0x2448641C, 0xE6808905,
+0x67F3E5C5, 0xBF7F666C, 0x7F3C655C, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0xD11E68F6,
+0x6012D21E, 0xCB20E405, 0x2102E500, 0x000B2242,
+0x00002252, 0x001E1017, 0x002030BC, 0x00201356,
+0x00202F1A, 0x001E1015, 0x001E10BF, 0x00117800,
+0x001E10FC, 0x00200170, 0x00202F20, 0x002024BE,
+0x002030C0, 0x002013A2, 0x002030DC, 0x0011788C,
+0x00202F1C, 0x00202B00, 0x002010EE, 0x001E2130,
+0x002030E4, 0x00202480, 0x002030E8, 0x00202F26,
+0x00202F2E, 0x00203220, 0x001C3500, 0x001D4004,
+0xD565D164, 0xE400D765, 0x2142E20F, 0x17411154,
+0xD5632722, 0x9669D763, 0x15412572, 0x96661562,
+0xE6011565, 0xD5601165, 0x666CE6F8, 0x25422542,
+0x25422542, 0x25422542, 0x25622542, 0x7601E727,
+0x67632572, 0x25627797, 0xE7042572, 0x2572E248,
+0xE2192522, 0xE2702522, 0x25422542, 0x25422542,
+0x25222542, 0x2522E20C, 0x25422542, 0x25422542,
+0x25422542, 0x25422542, 0x000B154A, 0xE2081145,
+0x0009422B, 0x2FE62FD6, 0x7FFC4F22, 0xC8206043,
+0x6E438D02, 0x0009BE6D, 0xC81060E3, 0xBE6A8901,
+0x60E30009, 0x8901C840, 0x0009BE8C, 0xC80160E3,
+0xDD3E8938, 0xC80260D0, 0x2F008D03, 0x460BD63C,
+0x60F00009, 0x8902C804, 0x460BD63A, 0x62F00009,
+0xC8806023, 0x60D08902, 0x2D00C97F, 0xC8016023,
+0xD6358906, 0x0009460B, 0x0009A007, 0x51630601,
+0x8902C808, 0x460BD631, 0x60F00009, 0x8902C810,
+0x420BD22F, 0xD52F0009, 0x88026052, 0xD22E8B03,
+0xA005E604, 0x88012260, 0xD22B8B02, 0x2260E601,
+0x2522E200, 0xC88060E3, 0xD628892E, 0x60E36E60,
+0x8902C880, 0x420BD226, 0x60E30009, 0x8902C840,
+0x420BD224, 0x60E30009, 0x8902C802, 0x420BD222,
+0x60E30009, 0x890EC804, 0x410BD120, 0xBF0E0009,
+0xBF4D0009, 0xD51E0009, 0x6050D41E, 0xC908D71E,
+0xBF842500, 0x60E32472, 0x8905C808, 0x7F04D21B,
+0x6EF64F26, 0x6DF6422B, 0x4F267F04, 0x000B6EF6,
+0x00006DF6, 0x001C581C, 0xA000A000, 0x001D0100,
+0x001D4000, 0x00040021, 0x001C589C, 0x001E1021,
+0x00201536, 0x00201558, 0x00201B98, 0x00201570,
+0x0020157E, 0x00202F64, 0x001E100B, 0x001E1028,
+0x002015D4, 0x002015E0, 0x00201586, 0x002015A4,
+0x001E1000, 0x0010F100, 0x12345678, 0x002015BC,
+0x644CD6A7, 0x000B346C, 0xD6A62450, 0x346C644C,
+0x2450000B, 0x644CD6A4, 0x000B346C, 0x625C2450,
+0x4208616D, 0x42084119, 0x42006019, 0x670E614C,
+0xD49E321C, 0x4200207D, 0x324CC90F, 0x2200000B,
+0x4208625C, 0x42004208, 0x324C644C, 0x4200D498,
+0x000B324C, 0x2FE62260, 0x614C4F12, 0x4100D493,
+0x6710314C, 0xE29F666D, 0x27294619, 0x6E536269,
+0x672E6573, 0x4221227D, 0x42214221, 0x7601662C,
+0xE4014608, 0x34E84608, 0x644C4600, 0x071A0467,
+0x2150257B, 0x000B4F16, 0x4F226EF6, 0xD2857FE8,
+0x88016021, 0xD2848B7B, 0x26686621, 0xD2838B77,
+0x26686621, 0xE50F8B73, 0xE401BFA2, 0xBFA4E501,
+0xE586E400, 0xE400655C, 0x2F50BFA4, 0xBFA1E401,
+0xE602E506, 0x60634618, 0x81F2E401, 0x6543BF9F,
+0xE40185F2, 0xBFAB6543, 0x85F26603, 0x6543E401,
+0x6603BFB1, 0xE40265F0, 0x6053756C, 0x80F8BF80,
+0xBF82E402, 0x84F8E512, 0x7090E402, 0x6503BF82,
+0x4618E602, 0x81F66063, 0xBF80E402, 0x85F6E500,
+0x6603E402, 0xE500BF8C, 0xE40285F6, 0xBF926603,
+0xE5FEE500, 0xE010655C, 0xBF61E403, 0xE5130F54,
+0xE40EBF63, 0x05FCE010, 0xBF63E40E, 0xE5007585,
+0xBF64E403, 0xE500E640, 0xBF71E403, 0xE500E640,
+0xBF78E403, 0xE5FFE640, 0xE014655C, 0xBF47E404,
+0xE40F0F54, 0xE504BF49, 0x05FCE014, 0xBF49E40F,
+0xE5017584, 0xBF4AE640, 0xE501E404, 0xBF57E640,
+0xE501E404, 0xE404E640, 0xAF5C7F18, 0x7F184F26,
+0x000B4F26, 0x4F220009, 0xD2427FF0, 0x88016021,
+0xD2418B71, 0x26686621, 0xD2408B6D, 0x26686621,
+0xE50F8B69, 0xE401BF1C, 0xBF1EE501, 0xE586E400,
+0xE400655C, 0x2F50BF1E, 0xBF1BE401, 0xE401E506,
+0xBF1C6543, 0xE401E640, 0xBF296543, 0xE401E640,
+0xBF306543, 0x65F0E640, 0x756CE402, 0xBEFF6053,
+0xE40280F4, 0xE512BF01, 0xE40284F4, 0xBF017090,
+0xE6406503, 0xBF02E402, 0xE640E500, 0xBF0FE402,
+0xE640E500, 0xBF16E402, 0xE5FEE500, 0x6053655C,
+0xBEE5E403, 0xE51380F8, 0xE40EBEE7, 0xE40E84F8,
+0xBEE77085, 0xE5006503, 0xBEE8E640, 0xE500E403,
+0xBEF5E640, 0xE500E403, 0xBEFCE640, 0xE5FFE403,
+0x6053655C, 0xBECBE404, 0xE40F80FC, 0xE504BECD,
+0xE40F84FC, 0xBECD7083, 0xE5016503, 0xBECEE640,
+0xE501E404, 0xBEDBE640, 0xE501E404, 0xE404E640,
+0xAEE07F10, 0x7F104F26, 0x000B4F26, 0x00000009,
+0x001E102F, 0x001E1080, 0x001E1090, 0x001E103F,
+0x001E103E, 0x00202F5E, 0x00202F60, 0x00202F62,
+0xD21DD11C, 0x66206010, 0x676C7001, 0x3700C90F,
+0xE5008D13, 0x67106210, 0x7701622C, 0x64232170,
+0xD6166010, 0x44084408, 0x3428C90F, 0x62602100,
+0x7201D513, 0x44082620, 0x000B354C, 0xD10F6053,
+0x25586510, 0xE6008D13, 0xD60DD40B, 0x655C6540,
+0x47086753, 0x37584708, 0x47086540, 0x24507501,
+0x367C6040, 0x2400C90F, 0x72FF6210, 0x000B2120,
+0x00006063, 0x00202F19, 0x00202F18, 0x00202F1A,
+0x00202B40, 0x7FFC4F22, 0xE680D1A8, 0x666C6212,
+0xD2A72F22, 0x67F36563, 0x420B7542, 0x7F04E404,
+0x000B4F26, 0xE6800009, 0xD2A1666C, 0xE7006563,
+0x422B7540, 0xE6806473, 0xD29D666C, 0xE7006563,
+0x422B7543, 0x2FB66473, 0x2FD62FC6, 0x4F222FE6,
+0x4D18ED01, 0xDB98DC97, 0x65C252C1, 0x89203520,
+0xC9036051, 0x891C8801, 0xD194DE92, 0x64E3410B,
+0x85036503, 0x670D66B2, 0x89073762, 0xD291D490,
+0x0009420B, 0xE701D190, 0x2172AFE6, 0xDE8F64E3,
+0x00094E0B, 0xD48FD68E, 0x410BD18F, 0xAFDB26D2,
+0x4F260009, 0x6DF66EF6, 0x000B6CF6, 0x4F226BF6,
+0x85467FF4, 0x2F01E681, 0x666C8547, 0x854881F1,
+0x81F2D27B, 0x67F38542, 0x854381F3, 0x81F4E40C,
+0x65636053, 0x420B81F5, 0x7F0C7540, 0x000B4F26,
+0x2F860009, 0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6,
+0x7FEC4F22, 0xE000D176, 0xD4782F12, 0x81F26103,
+0xDC771F42, 0xD6776B13, 0xE0014B08, 0x460BDE76,
+0x3BEC4B00, 0x66C21F03, 0x362052C1, 0xA1818B01,
+0x60610009, 0x8801C903, 0xA17B8B01, 0x85610009,
+0x8B01C801, 0x0009A080, 0x85D25D63, 0xC9036603,
+0x85D36403, 0x6053650D, 0x40214021, 0x4500C93F,
+0x322A6103, 0x6053252D, 0xC901E510, 0xD95E3153,
+0x6E038D21, 0x4408D761, 0x44086870, 0x44006213,
+0x28884200, 0x342C8F0E, 0x6043D25D, 0x60E3072D,
+0x4A196A7D, 0x658E68A9, 0x285D8801, 0x6A7C8F0B,
+0x6A13A009, 0x6043D257, 0x61ED0E2D, 0x68194119,
+0x287D678E, 0xD1546AEC, 0x22286210, 0xEAFF8901,
+0xEEFF6AAC, 0x6EEC65AD, 0x8B0F35E0, 0x4D0BDD3F,
+0x540364C3, 0xBF72E502, 0xD44C6D03, 0x410BD13F,
+0xD74B65D3, 0xD44BEE01, 0x27E2A025, 0x2679E7FC,
+0x81D26063, 0x946085D3, 0x61032049, 0x4508268B,
+0x251B6063, 0x605381D2, 0x85D481D3, 0x4118E108,
+0x81D4201B, 0xEE0262C2, 0x20798521, 0x64C28121,
+0x6041678D, 0xCB0137E3, 0x24018D04, 0xEEE785D2,
+0x81D220E9, 0x490BD438, 0x60C20009, 0x52F366F2,
+0x2B02CB01, 0x2622AF6F, 0xD2208561, 0x8F02C802,
+0xA0D264C3, 0x420B0009, 0xD9300009, 0x5E036503,
+0x079EE04C, 0x7701DD2E, 0x69D20976, 0x7901D626,
+0x6D602D92, 0x89062DD8, 0xD218D424, 0xED01420B,
+0xA0B3D723, 0x625127D2, 0x4118E10F, 0x2219E402,
+0x32404418, 0x85518B46, 0x20D9EDFC, 0x60518151,
+0xCB017DE3, 0x85E12501, 0x20D9D60A, 0x460B81E1,
+0x69F264C3, 0xA09957F3, 0x7E032972, 0x001C3D9C,
+0x00201E38, 0x00202B38, 0x00202F00, 0x0020106C,
+0x00202B00, 0x002010EE, 0x001E2130, 0x0020108A,
+0x001C3D30, 0x00203200, 0x00201356, 0x0020320C,
+0x00202B10, 0x002029F8, 0x001C3D00, 0x0020321C,
+0x00203100, 0x00203180, 0x00202F14, 0x00202B08,
+0x001E212C, 0x00203204, 0x00203208, 0x00202AA4,
+0x00203220, 0x6DDD6D51, 0x6DD94D19, 0x2D6D66DE,
+0x60DC7D01, 0x41186103, 0x8F458801, 0xD65B2511,
+0x74016462, 0x85E32642, 0x6063660D, 0x40214021,
+0x4600C93F, 0x322A6D03, 0x6063262D, 0xD154C801,
+0x8901D954, 0x2D6B96A1, 0xE010E600, 0x64DD0F64,
+0x07FCE010, 0x4000607C, 0x622D021D, 0x8D123240,
+0x60636603, 0xE7FF021D, 0x8B013270, 0x01D5A00B,
+0x02FCE010, 0x7201E604, 0x622C0F24, 0x8BE73262,
+0x666C06FC, 0x60634600, 0x7101019D, 0xD1420915,
+0x697D6711, 0x89073940, 0x602D6211, 0x890388FF,
+0xDD3E21D1, 0x2D20E201, 0xEDFC8551, 0x815120D9,
+0xD23B6051, 0x64C3CB01, 0x2501420B, 0x02FCE010,
+0x612CD438, 0x440BE001, 0x270267F2, 0xD23685EF,
+0x420B54F2, 0xAE96650D, 0x420B0009, 0x54030009,
+0x85446E03, 0x4D18ED08, 0x30D020D9, 0xBE568B03,
+0xA007E501, 0x85410009, 0x620DDD2C, 0x890122D8,
+0xE500BE4D, 0xD22BD42A, 0x65E3420B, 0xED01D72A,
+0x27D2AE79, 0xEE0485F2, 0x610D7001, 0x81F231E7,
+0x7C088D02, 0x0009AE66, 0x4F267F14, 0x6DF66EF6,
+0x6BF66CF6, 0x69F66AF6, 0x68F6000B, 0x4F222FE6,
+0x6E22D21E, 0xC84060E3, 0x22E28D02, 0x0009BDD2,
+0x4218E240, 0x89012E28, 0x0009BDDD, 0xC81060E3,
+0xD4178905, 0x420BD217, 0xBDDC0009, 0x60E30009,
+0x8901C805, 0x0009BE2D, 0xC80260E3, 0x4F268902,
+0x6EF6ADD9, 0x000B4F26, 0x80006EF6, 0x00203220,
+0x00202F26, 0x00202F2E, 0x00202F22, 0x00202F24,
+0x002010EE, 0x002029F8, 0x002013A2, 0x00008000,
+0x00202B08, 0x0020108A, 0x001E212C, 0x001C3510,
+0x00203214, 0x00201356, 0x080A0C0E, 0x00020406,
+0x1A1C1E20, 0x12141618, 0x2E303234, 0x26282A2C,
+0x3A3C3E40, 0x6C625648, 0x41112F26, 0xE2208F18,
+0x890B3123, 0x321CD204, 0xD1026220, 0x412B312C,
+0x00090009, 0x00202A22, 0x002029D8, 0x000BE000,
+0x400062F6, 0x40004000, 0x40004000, 0x40004000,
+0x62F6000B, 0x40004000, 0x40004000, 0x40004000,
+0x40184000, 0x62F6000B, 0x40004000, 0x40004000,
+0x40004000, 0x40284000, 0x62F6000B, 0x40004000,
+0x40184000, 0x000B4028, 0xC90F62F6, 0x40054005,
+0x40054005, 0x62F6000B, 0x4005C907, 0x40054005,
+0x62F6000B, 0x4005C903, 0x000B4005, 0xC90162F6,
+0x000B4005, 0x000062F6, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x544F0D0A, 0x46205355, 0x00003A57, 0x20636544,
+0x32203231, 0x20373030, 0x333A3132, 0x34323A36,
+0x00000000, 0x00000D0A, 0x00000043, 0x42707372,
+0x3D206675, 0x554E203D, 0x202C4C4C, 0x6E49677A,
+0x4E497274, 0x6D754E51, 0x0000003D, 0x61766E49,
+0x2064696C, 0x72657375, 0x20726F20, 0x2079656B,
+0x00214449, 0x52504545, 0x57204D4F, 0x65746972,
+0x6461202C, 0x003D7264, 0x6C617620, 0x0000003D,
+0x00000A0D, 0x6E6B6E55, 0x206E776F, 0x6D6D6F63,
+0x3D646E61, 0x00000000, 0x000A0D52, 0x203A3051,
+0x00000020, 0x203A3151, 0x00000020, 0x203A3251,
+0x00000020, 0x203A3351, 0x00000020, 0x203A3451,
+0x00000020, 0x61437748, 0x7262696C, 0x6F697461,
+0x6620206E, 0x0A6C6961, 0x0000000D, 0x73696F4E,
+0x61432065, 0x7262696C, 0x6F697461, 0x6166206E,
+0x21216C69, 0x00000D0A, 0x00000072, 0x00205220,
+0x00000D0A, 0x62735576, 0x7473725F, 0x00000A0D,
+0x62735576, 0x7375735F, 0x646E6570, 0x00000A0D,
+0x62735576, 0x7365725F, 0x000A0D6D, 0x00000042,
+0x72746E49, 0x6D652051, 0x2C797470, 0x49677A20,
+0x4972746E, 0x754E514E, 0x00003D6D, 0x654C7245,
+0x0000006E, 0x00000049, 0x20746F4E, 0x756F6E65,
+0x49206867, 0x4220514E, 0x0A0D6675, 0x00000000,
+0x000000FF, 0x00020001, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00020003, 0x01090108, 0x0002010A,
+0x02000003, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C0207, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00FF010F, 0x01090108, 0x010B010A,
+0x020000FF, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00205220, 0x00000046, 0x00000059, 0x73204142,
+0x003D7165, 0x49544120, 0x0000204D, 0x00000000,
+0x00000000, 0x002E0209, 0x80000101, 0x000409FA,
+0x00FF0400, 0x05070000, 0x02000201, 0x82050700,
+0x00020002, 0x03830507, 0x07010040, 0x40020405,
+0x02090000, 0x0101002E, 0x09FA8000, 0x04000004,
+0x000000FF, 0x02010507, 0x07000040, 0x40028205,
+0x05070000, 0x00400383, 0x04050701, 0x00004002,
+0x00000000, 0x00000000, 0x07090000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, };
+
+const u32_t zcDKFwImageSize=12988;
diff --git a/drivers/staging/otus/hal/hpani.c b/drivers/staging/otus/hal/hpani.c
new file mode 100644
index 000000000000..ba95b5d012a4
--- /dev/null
+++ b/drivers/staging/otus/hal/hpani.c
@@ -0,0 +1,732 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+#include "hpani.h"
+#include "hpusb.h"
+
+
+extern u16_t zfDelayWriteInternalReg(zdev_t* dev, u32_t addr, u32_t val);
+extern u16_t zfFlushDelayWrite(zdev_t* dev);
+
+/*
+ * Anti noise immunity support. We track phy errors and react
+ * to excessive errors by adjusting the noise immunity parameters.
+ */
+
+/******************************************************************************
+ *
+ * New Ani Algorithm for Station side only
+ *
+ *****************************************************************************/
+
+#define ZM_HAL_NOISE_IMMUNE_MAX 4 /* Max noise immunity level */
+#define ZM_HAL_SPUR_IMMUNE_MAX 7 /* Max spur immunity level */
+#define ZM_HAL_FIRST_STEP_MAX 2 /* Max first step level */
+
+#define ZM_HAL_ANI_OFDM_TRIG_HIGH 500
+#define ZM_HAL_ANI_OFDM_TRIG_LOW 200
+#define ZM_HAL_ANI_CCK_TRIG_HIGH 200
+#define ZM_HAL_ANI_CCK_TRIG_LOW 100
+#define ZM_HAL_ANI_NOISE_IMMUNE_LVL 4
+#define ZM_HAL_ANI_USE_OFDM_WEAK_SIG TRUE
+#define ZM_HAL_ANI_CCK_WEAK_SIG_THR FALSE
+#define ZM_HAL_ANI_SPUR_IMMUNE_LVL 7
+#define ZM_HAL_ANI_FIRSTEP_LVL 0
+#define ZM_HAL_ANI_RSSI_THR_HIGH 40
+#define ZM_HAL_ANI_RSSI_THR_LOW 7
+#define ZM_HAL_ANI_PERIOD 100
+
+#define ZM_HAL_EP_RND(x, mul) \
+ ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+
+s32_t BEACON_RSSI(zdev_t* dev)
+{
+ s32_t rssi;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ rssi = ZM_HAL_EP_RND(HpPriv->stats.ast_nodestats.ns_avgbrssi, ZM_HAL_RSSI_EP_MULTIPLIER);
+
+ return rssi;
+}
+
+/*
+ * Setup ANI handling. Sets all thresholds and levels to default level AND
+ * resets the channel statistics
+ */
+
+void zfHpAniAttach(zdev_t* dev)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ u32_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+ const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+ const int coarseLow[] = { -64, -64, -64, -64, -70 };
+ const int firpwr[] = { -78, -78, -78, -78, -80 };
+
+ for (i = 0; i < 5; i++)
+ {
+ HpPriv->totalSizeDesired[i] = totalSizeDesired[i];
+ HpPriv->coarseHigh[i] = coarseHigh[i];
+ HpPriv->coarseLow[i] = coarseLow[i];
+ HpPriv->firpwr[i] = firpwr[i];
+ }
+
+ /* owl has phy counters */
+ HpPriv->hasHwPhyCounters = 1;
+
+ memset((char *)&HpPriv->ani, 0, sizeof(HpPriv->ani));
+ for (i = 0; i < N(wd->regulationTable.allowChannel); i++)
+ {
+ /* New ANI stuff */
+ HpPriv->ani[i].ofdmTrigHigh = ZM_HAL_ANI_OFDM_TRIG_HIGH;
+ HpPriv->ani[i].ofdmTrigLow = ZM_HAL_ANI_OFDM_TRIG_LOW;
+ HpPriv->ani[i].cckTrigHigh = ZM_HAL_ANI_CCK_TRIG_HIGH;
+ HpPriv->ani[i].cckTrigLow = ZM_HAL_ANI_CCK_TRIG_LOW;
+ HpPriv->ani[i].rssiThrHigh = ZM_HAL_ANI_RSSI_THR_HIGH;
+ HpPriv->ani[i].rssiThrLow = ZM_HAL_ANI_RSSI_THR_LOW;
+ HpPriv->ani[i].ofdmWeakSigDetectOff = !ZM_HAL_ANI_USE_OFDM_WEAK_SIG;
+ HpPriv->ani[i].cckWeakSigThreshold = ZM_HAL_ANI_CCK_WEAK_SIG_THR;
+ HpPriv->ani[i].spurImmunityLevel = ZM_HAL_ANI_SPUR_IMMUNE_LVL;
+ HpPriv->ani[i].firstepLevel = ZM_HAL_ANI_FIRSTEP_LVL;
+ if (HpPriv->hasHwPhyCounters)
+ {
+ HpPriv->ani[i].ofdmPhyErrBase = 0;//AR_PHY_COUNTMAX - ZM_HAL_ANI_OFDM_TRIG_HIGH;
+ HpPriv->ani[i].cckPhyErrBase = 0;//AR_PHY_COUNTMAX - ZM_HAL_ANI_CCK_TRIG_HIGH;
+ }
+ }
+ if (HpPriv->hasHwPhyCounters)
+ {
+ //zm_debug_msg2("Setting OfdmErrBase = 0x", HpPriv->ani[0].ofdmPhyErrBase);
+ //zm_debug_msg2("Setting cckErrBase = 0x", HpPriv->ani[0].cckPhyErrBase);
+ //OS_REG_WRITE(ah, AR_PHY_ERR_1, HpPriv->ani[0].ofdmPhyErrBase);
+ //OS_REG_WRITE(ah, AR_PHY_ERR_2, HpPriv->ani[0].cckPhyErrBase);
+ }
+ HpPriv->aniPeriod = ZM_HAL_ANI_PERIOD;
+ //if (ath_hal_enableANI)
+ HpPriv->procPhyErr |= ZM_HAL_PROCESS_ANI;
+
+ HpPriv->stats.ast_nodestats.ns_avgbrssi = ZM_RSSI_DUMMY_MARKER;
+ HpPriv->stats.ast_nodestats.ns_avgrssi = ZM_RSSI_DUMMY_MARKER;
+ HpPriv->stats.ast_nodestats.ns_avgtxrssi = ZM_RSSI_DUMMY_MARKER;
+#undef N
+}
+
+/*
+ * Control Adaptive Noise Immunity Parameters
+ */
+u8_t zfHpAniControl(zdev_t* dev, ZM_HAL_ANI_CMD cmd, int param)
+{
+#define N(a) (sizeof(a)/sizeof(a[0]))
+ typedef s32_t TABLE[];
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ struct zsAniState *aniState = HpPriv->curani;
+
+ switch (cmd)
+ {
+ case ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL:
+ {
+ u32_t level = param;
+
+ if (level >= N(HpPriv->totalSizeDesired))
+ {
+ zm_debug_msg1("level out of range, desired level : ", level);
+ zm_debug_msg1("max level : ", N(HpPriv->totalSizeDesired));
+ return FALSE;
+ }
+
+ zfDelayWriteInternalReg(dev, AR_PHY_DESIRED_SZ,
+ (HpPriv->regPHYDesiredSZ & ~AR_PHY_DESIRED_SZ_TOT_DES)
+ | ((HpPriv->totalSizeDesired[level] << AR_PHY_DESIRED_SZ_TOT_DES_S)
+ & AR_PHY_DESIRED_SZ_TOT_DES));
+ zfDelayWriteInternalReg(dev, AR_PHY_AGC_CTL1,
+ (HpPriv->regPHYAgcCtl1 & ~AR_PHY_AGC_CTL1_COARSE_LOW)
+ | ((HpPriv->coarseLow[level] << AR_PHY_AGC_CTL1_COARSE_LOW_S)
+ & AR_PHY_AGC_CTL1_COARSE_LOW));
+ zfDelayWriteInternalReg(dev, AR_PHY_AGC_CTL1,
+ (HpPriv->regPHYAgcCtl1 & ~AR_PHY_AGC_CTL1_COARSE_HIGH)
+ | ((HpPriv->coarseHigh[level] << AR_PHY_AGC_CTL1_COARSE_HIGH_S)
+ & AR_PHY_AGC_CTL1_COARSE_HIGH));
+ zfDelayWriteInternalReg(dev, AR_PHY_FIND_SIG,
+ (HpPriv->regPHYFindSig & ~AR_PHY_FIND_SIG_FIRPWR)
+ | ((HpPriv->firpwr[level] << AR_PHY_FIND_SIG_FIRPWR_S)
+ & AR_PHY_FIND_SIG_FIRPWR));
+ zfFlushDelayWrite(dev);
+
+ if (level > aniState->noiseImmunityLevel)
+ HpPriv->stats.ast_ani_niup++;
+ else if (level < aniState->noiseImmunityLevel)
+ HpPriv->stats.ast_ani_nidown++;
+ aniState->noiseImmunityLevel = (u8_t)level;
+ break;
+ }
+ case ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION:
+ {
+ const TABLE m1ThreshLow = { 127, 50 };
+ const TABLE m2ThreshLow = { 127, 40 };
+ const TABLE m1Thresh = { 127, 0x4d };
+ const TABLE m2Thresh = { 127, 0x40 };
+ const TABLE m2CountThr = { 31, 16 };
+ const TABLE m2CountThrLow = { 63, 48 };
+ u32_t on = param ? 1 : 0;
+
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
+ (HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_M1_THRESH_LOW)
+ | ((m1ThreshLow[on] << AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S)
+ & AR_PHY_SFCORR_LOW_M1_THRESH_LOW));
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
+ (HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_M2_THRESH_LOW)
+ | ((m2ThreshLow[on] << AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S)
+ & AR_PHY_SFCORR_LOW_M2_THRESH_LOW));
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR,
+ (HpPriv->regPHYSfcorr & ~AR_PHY_SFCORR_M1_THRESH)
+ | ((m1Thresh[on] << AR_PHY_SFCORR_M1_THRESH_S)
+ & AR_PHY_SFCORR_M1_THRESH));
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR,
+ (HpPriv->regPHYSfcorr & ~AR_PHY_SFCORR_M2_THRESH)
+ | ((m2Thresh[on] << AR_PHY_SFCORR_M2_THRESH_S)
+ & AR_PHY_SFCORR_M2_THRESH));
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR,
+ (HpPriv->regPHYSfcorr & ~AR_PHY_SFCORR_M2COUNT_THR)
+ | ((m2CountThr[on] << AR_PHY_SFCORR_M2COUNT_THR_S)
+ & AR_PHY_SFCORR_M2COUNT_THR));
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
+ (HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW)
+ | ((m2CountThrLow[on] << AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S)
+ & AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW));
+
+ if (on)
+ {
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
+ HpPriv->regPHYSfcorrLow | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, AR_PHY_SFCORR_LOW,
+ HpPriv->regPHYSfcorrLow & ~AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ }
+ zfFlushDelayWrite(dev);
+ if (!on != aniState->ofdmWeakSigDetectOff)
+ {
+ if (on)
+ HpPriv->stats.ast_ani_ofdmon++;
+ else
+ HpPriv->stats.ast_ani_ofdmoff++;
+ aniState->ofdmWeakSigDetectOff = !on;
+ }
+ break;
+ }
+ case ZM_HAL_ANI_CCK_WEAK_SIGNAL_THR:
+ {
+ const TABLE weakSigThrCck = { 8, 6 };
+ u32_t high = param ? 1 : 0;
+
+ zfDelayWriteInternalReg(dev, AR_PHY_CCK_DETECT,
+ (HpPriv->regPHYCckDetect & ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK)
+ | ((weakSigThrCck[high] << AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S)
+ & AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK));
+ zfFlushDelayWrite(dev);
+ if (high != aniState->cckWeakSigThreshold)
+ {
+ if (high)
+ HpPriv->stats.ast_ani_cckhigh++;
+ else
+ HpPriv->stats.ast_ani_ccklow++;
+ aniState->cckWeakSigThreshold = (u8_t)high;
+ }
+ break;
+ }
+ case ZM_HAL_ANI_FIRSTEP_LEVEL:
+ {
+ const TABLE firstep = { 0, 4, 8 };
+ u32_t level = param;
+
+ if (level >= N(firstep))
+ {
+ zm_debug_msg1("level out of range, desired level : ", level);
+ zm_debug_msg1("max level : ", N(firstep));
+ return FALSE;
+ }
+ zfDelayWriteInternalReg(dev, AR_PHY_FIND_SIG,
+ (HpPriv->regPHYFindSig & ~AR_PHY_FIND_SIG_FIRSTEP)
+ | ((firstep[level] << AR_PHY_FIND_SIG_FIRSTEP_S)
+ & AR_PHY_FIND_SIG_FIRSTEP));
+ zfFlushDelayWrite(dev);
+ if (level > aniState->firstepLevel)
+ HpPriv->stats.ast_ani_stepup++;
+ else if (level < aniState->firstepLevel)
+ HpPriv->stats.ast_ani_stepdown++;
+ aniState->firstepLevel = (u8_t)level;
+ break;
+ }
+ case ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL:
+ {
+ const TABLE cycpwrThr1 = { 2, 4, 6, 8, 10, 12, 14, 16 };
+ u32_t level = param;
+
+ if (level >= N(cycpwrThr1))
+ {
+ zm_debug_msg1("level out of range, desired level : ", level);
+ zm_debug_msg1("max level : ", N(cycpwrThr1));
+ return FALSE;
+ }
+ zfDelayWriteInternalReg(dev, AR_PHY_TIMING5,
+ (HpPriv->regPHYTiming5 & ~AR_PHY_TIMING5_CYCPWR_THR1)
+ | ((cycpwrThr1[level] << AR_PHY_TIMING5_CYCPWR_THR1_S)
+ & AR_PHY_TIMING5_CYCPWR_THR1));
+ zfFlushDelayWrite(dev);
+ if (level > aniState->spurImmunityLevel)
+ HpPriv->stats.ast_ani_spurup++;
+ else if (level < aniState->spurImmunityLevel)
+ HpPriv->stats.ast_ani_spurdown++;
+ aniState->spurImmunityLevel = (u8_t)level;
+ break;
+ }
+ case ZM_HAL_ANI_PRESENT:
+ break;
+#ifdef AH_PRIVATE_DIAG
+ case ZM_HAL_ANI_MODE:
+ if (param == 0)
+ {
+ HpPriv->procPhyErr &= ~ZM_HAL_PROCESS_ANI;
+ /* Turn off HW counters if we have them */
+ zfHpAniDetach(dev);
+ //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) &~ HAL_RX_FILTER_PHYERR);
+ }
+ else
+ { /* normal/auto mode */
+ HpPriv->procPhyErr |= ZM_HAL_PROCESS_ANI;
+ if (HpPriv->hasHwPhyCounters)
+ {
+ //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) &~ HAL_RX_FILTER_PHYERR);
+ }
+ else
+ {
+ //zfHpSetRxFilter(dev, zfHpGetRxFilter(dev) | HAL_RX_FILTER_PHYERR);
+ }
+ }
+ break;
+ case ZM_HAL_ANI_PHYERR_RESET:
+ HpPriv->stats.ast_ani_ofdmerrs = 0;
+ HpPriv->stats.ast_ani_cckerrs = 0;
+ break;
+#endif /* AH_PRIVATE_DIAG */
+ default:
+ zm_debug_msg1("invalid cmd ", cmd);
+ return FALSE;
+ }
+ return TRUE;
+#undef N
+}
+
+void zfHpAniRestart(zdev_t* dev)
+{
+ struct zsAniState *aniState;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ aniState = HpPriv->curani;
+
+ aniState->listenTime = 0;
+ if (HpPriv->hasHwPhyCounters)
+ {
+ //if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX)
+ //{
+ // aniState->ofdmPhyErrBase = 0;
+ // zm_debug_msg0("OFDM Trigger is too high for hw counters");
+ //}
+ //else
+ // aniState->ofdmPhyErrBase = AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+ //if (aniState->cckTrigHigh > AR_PHY_COUNTMAX)
+ //{
+ // aniState->cckPhyErrBase = 0;
+ // zm_debug_msg0("CCK Trigger is too high for hw counters");
+ //}
+ //else
+ // aniState->cckPhyErrBase = AR_PHY_COUNTMAX - aniState->cckTrigHigh;
+ //zm_debug_msg2("Writing ofdmbase = 0x", aniState->ofdmPhyErrBase);
+ //zm_debug_msg2("Writing cckbase = 0x", aniState->cckPhyErrBase);
+ //OS_REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+ //OS_REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+ aniState->ofdmPhyErrBase = 0;
+ aniState->cckPhyErrBase = 0;
+ }
+ aniState->ofdmPhyErrCount = 0;
+ aniState->cckPhyErrCount = 0;
+}
+
+void zfHpAniOfdmErrTrigger(zdev_t* dev)
+{
+ struct zsAniState *aniState;
+ s32_t rssi;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ //HALASSERT(chan != NULL);
+
+ if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
+ return;
+
+ aniState = HpPriv->curani;
+ /* First, raise noise immunity level, up to max */
+ if (aniState->noiseImmunityLevel < ZM_HAL_NOISE_IMMUNE_MAX)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel + 1);
+ return;
+ }
+ /* then, raise spur immunity level, up to max */
+ if (aniState->spurImmunityLevel < ZM_HAL_SPUR_IMMUNE_MAX)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel + 1);
+ return;
+ }
+ rssi = BEACON_RSSI(dev);
+ if (rssi > aniState->rssiThrHigh)
+ {
+ /*
+ * Beacon rssi is high, can turn off ofdm weak sig detect.
+ */
+ if (!aniState->ofdmWeakSigDetectOff)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, FALSE);
+ zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, 0);
+ return;
+ }
+ /*
+ * If weak sig detect is already off, as last resort, raise
+ * first step level
+ */
+ if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
+ return;
+ }
+ }
+ else if (rssi > aniState->rssiThrLow)
+ {
+ /*
+ * Beacon rssi in mid range, need ofdm weak signal detect,
+ * but we can raise firststepLevel
+ */
+ if (aniState->ofdmWeakSigDetectOff)
+ zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, TRUE);
+ if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
+ zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
+ return;
+ }
+ else
+ {
+ /*
+ * Beacon rssi is low, if in 11b/g mode, turn off ofdm
+ * weak sign detction and zero firstepLevel to maximize
+ * CCK sensitivity
+ */
+ if (wd->frequency < 3000)
+ {
+ if (!aniState->ofdmWeakSigDetectOff)
+ zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, FALSE);
+ if (aniState->firstepLevel > 0)
+ zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, 0);
+ return;
+ }
+ }
+}
+
+void zfHpAniCckErrTrigger(zdev_t* dev)
+{
+ struct zsAniState *aniState;
+ s32_t rssi;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ //HALASSERT(chan != NULL);
+
+ if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
+ return;
+
+ /* first, raise noise immunity level, up to max */
+ aniState = HpPriv->curani;
+ if (aniState->noiseImmunityLevel < ZM_HAL_NOISE_IMMUNE_MAX)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel + 1);
+ return;
+ }
+ rssi = BEACON_RSSI(dev);
+ if (rssi > aniState->rssiThrLow)
+ {
+ /*
+ * Beacon signal in mid and high range, raise firsteplevel.
+ */
+ if (aniState->firstepLevel < ZM_HAL_FIRST_STEP_MAX)
+ zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel + 1);
+ }
+ else
+ {
+ /*
+ * Beacon rssi is low, zero firstepLevel to maximize
+ * CCK sensitivity.
+ */
+ if (wd->frequency < 3000)
+ {
+ if (aniState->firstepLevel > 0)
+ zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, 0);
+ }
+ }
+}
+
+void zfHpAniLowerImmunity(zdev_t* dev)
+{
+ struct zsAniState *aniState;
+ s32_t rssi;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ aniState = HpPriv->curani;
+
+ rssi = BEACON_RSSI(dev);
+ if (rssi > aniState->rssiThrHigh)
+ {
+ /*
+ * Beacon signal is high, leave ofdm weak signal detection off
+ * or it may oscillate. Let it fall through.
+ */
+ }
+ else if (rssi > aniState->rssiThrLow)
+ {
+ /*
+ * Beacon rssi in mid range, turn on ofdm weak signal
+ * detection or lower first step level.
+ */
+ if (aniState->ofdmWeakSigDetectOff)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, TRUE);
+ return;
+ }
+ if (aniState->firstepLevel > 0)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1);
+ return;
+ }
+ }
+ else
+ {
+ /*
+ * Beacon rssi is low, reduce first step level.
+ */
+ if (aniState->firstepLevel > 0)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_FIRSTEP_LEVEL, aniState->firstepLevel - 1);
+ return;
+ }
+ }
+ /* then lower spur immunity level, down to zero */
+ if (aniState->spurImmunityLevel > 0)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, aniState->spurImmunityLevel - 1);
+ return;
+ }
+ /*
+ * if all else fails, lower noise immunity level down to a min value
+ * zero for now
+ */
+ if (aniState->noiseImmunityLevel > 0)
+ {
+ zfHpAniControl(dev, ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL, aniState->noiseImmunityLevel - 1);
+ return;
+ }
+}
+
+#define CLOCK_RATE 44000 /* XXX use mac_usec or similar */
+/* convert HW counter values to ms using 11g clock rate, goo9d enough
+ for 11a and Turbo */
+
+/*
+ * Return an approximation of the time spent ``listening'' by
+ * deducting the cycles spent tx'ing and rx'ing from the total
+ * cycle count since our last call. A return value <0 indicates
+ * an invalid/inconsistent time.
+ */
+s32_t zfHpAniGetListenTime(zdev_t* dev)
+{
+ struct zsAniState *aniState;
+ u32_t txFrameCount, rxFrameCount, cycleCount;
+ s32_t listenTime;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ txFrameCount = 0;//OS_REG_READ(ah, AR_TFCNT);
+ rxFrameCount = 0;//OS_REG_READ(ah, AR_RFCNT);
+ cycleCount = 0;//OS_REG_READ(ah, AR_CCCNT);
+
+ aniState = HpPriv->curani;
+ if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount)
+ {
+ /*
+ * Cycle counter wrap (or initial call); it's not possible
+ * to accurately calculate a value because the registers
+ * right shift rather than wrap--so punt and return 0.
+ */
+ listenTime = 0;
+ HpPriv->stats.ast_ani_lzero++;
+ }
+ else
+ {
+ s32_t ccdelta = cycleCount - aniState->cycleCount;
+ s32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
+ s32_t tfdelta = txFrameCount - aniState->txFrameCount;
+ listenTime = (ccdelta - rfdelta - tfdelta) / CLOCK_RATE;
+ }
+ aniState->cycleCount = cycleCount;
+ aniState->txFrameCount = txFrameCount;
+ aniState->rxFrameCount = rxFrameCount;
+ return listenTime;
+}
+
+/*
+ * Do periodic processing. This routine is called from the
+ * driver's rx interrupt handler after processing frames.
+ */
+void zfHpAniArPoll(zdev_t* dev, u32_t listenTime, u32_t phyCnt1, u32_t phyCnt2)
+{
+ struct zsAniState *aniState;
+ //s32_t listenTime;
+
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv *HpPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+ /*
+ * Since we're called from end of rx tasklet, we also check for
+ * AR processing now
+ */
+
+ aniState = HpPriv->curani;
+ //HpPriv->stats.ast_nodestats = *stats; /* XXX optimize? */
+
+ //listenTime = zfHpAniGetListenTime(dev);
+ //if (listenTime < 0)
+ //{
+ // HpPriv->stats.ast_ani_lneg++;
+ // /* restart ANI period if listenTime is invalid */
+ // zfHpAniRestart(dev);
+ // return;
+ //}
+ /* XXX beware of overflow? */
+ aniState->listenTime += listenTime;
+
+ if (HpPriv->hasHwPhyCounters)
+ {
+ //u32_t phyCnt1, phyCnt2;
+ u32_t ofdmPhyErrCnt, cckPhyErrCnt;
+
+ /* NB: these are not reset-on-read */
+ //phyCnt1 = 0;//OS_REG_READ(ah, AR_PHY_ERR_1);
+ //phyCnt2 = 0;//OS_REG_READ(ah, AR_PHY_ERR_2);
+ /* XXX sometimes zero, why? */
+ //if (phyCnt1 < aniState->ofdmPhyErrBase ||
+ // phyCnt2 < aniState->cckPhyErrBase)
+ //{
+ // if (phyCnt1 < aniState->ofdmPhyErrBase)
+ // {
+ // zm_debug_msg2("phyCnt1 = 0x", phyCnt1);
+ // zm_debug_msg2("resetting counter value to 0x", aniState->ofdmPhyErrBase);
+ // //OS_REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+ // //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ // }
+ // if (phyCnt2 < aniState->cckPhyErrBase)
+ // {
+ // zm_debug_msg2("phyCnt2 = 0x", phyCnt2);
+ // zm_debug_msg2("resetting counter value to 0x", aniState->cckPhyErrBase);
+ // //OS_REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ // //OS_REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+ // }
+ // return; /* XXX */
+ //}
+ /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
+ //ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ //HpPriv->stats.ast_ani_ofdmerrs += ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ //aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+ ofdmPhyErrCnt = phyCnt1;
+ HpPriv->stats.ast_ani_ofdmerrs += ofdmPhyErrCnt;
+ aniState->ofdmPhyErrCount += ofdmPhyErrCnt;
+
+ //cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ //HpPriv->stats.ast_ani_cckerrs += cckPhyErrCnt - aniState->cckPhyErrCount;
+ //aniState->cckPhyErrCount = cckPhyErrCnt;
+ cckPhyErrCnt = phyCnt2;
+ HpPriv->stats.ast_ani_cckerrs += cckPhyErrCnt;
+ aniState->cckPhyErrCount += cckPhyErrCnt;
+ }
+ /*
+ * If ani is not enabled, return after we've collected
+ * statistics
+ */
+ if ((HpPriv->procPhyErr & ZM_HAL_PROCESS_ANI) == 0)
+ return;
+ if (aniState->listenTime > 5 * HpPriv->aniPeriod)
+ {
+ /*
+ * Check to see if need to lower immunity if
+ * 5 aniPeriods have passed
+ */
+ if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+ aniState->ofdmTrigLow/1000 &&
+ aniState->cckPhyErrCount <= aniState->listenTime *
+ aniState->cckTrigLow/1000)
+ zfHpAniLowerImmunity(dev);
+ zfHpAniRestart(dev);
+ }
+ else if (aniState->listenTime > HpPriv->aniPeriod)
+ {
+ /* check to see if need to raise immunity */
+ if (aniState->ofdmPhyErrCount > aniState->listenTime *
+ aniState->ofdmTrigHigh / 1000)
+ {
+ zfHpAniOfdmErrTrigger(dev);
+ zfHpAniRestart(dev);
+ }
+ else if (aniState->cckPhyErrCount > aniState->listenTime *
+ aniState->cckTrigHigh / 1000)
+ {
+ zfHpAniCckErrTrigger(dev);
+ zfHpAniRestart(dev);
+ }
+ }
+}
diff --git a/drivers/staging/otus/hal/hpani.h b/drivers/staging/otus/hal/hpani.h
new file mode 100644
index 000000000000..96e69af3c685
--- /dev/null
+++ b/drivers/staging/otus/hal/hpani.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+
+typedef struct {
+ u32_t ackrcv_bad;
+ u32_t rts_bad;
+ u32_t rts_good;
+ u32_t fcs_bad;
+ u32_t beacons;
+} ZM_HAL_MIB_STATS;
+
+/*
+ * Per-node statistics maintained by the driver for use in
+ * optimizing signal quality and other operational aspects.
+ */
+typedef struct {
+ u32_t ns_avgbrssi; /* average beacon rssi */
+ u32_t ns_avgrssi; /* average data rssi */
+ u32_t ns_avgtxrssi; /* average tx rssi */
+} ZM_HAL_NODE_STATS;
+
+#define ZM_HAL_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */
+
+struct zsAniStats {
+ u32_t ast_ani_niup; /* ANI increased noise immunity */
+ u32_t ast_ani_nidown; /* ANI decreased noise immunity */
+ u32_t ast_ani_spurup; /* ANI increased spur immunity */
+ u32_t ast_ani_spurdown;/* ANI descreased spur immunity */
+ u32_t ast_ani_ofdmon; /* ANI OFDM weak signal detect on */
+ u32_t ast_ani_ofdmoff;/* ANI OFDM weak signal detect off */
+ u32_t ast_ani_cckhigh;/* ANI CCK weak signal threshold high */
+ u32_t ast_ani_ccklow; /* ANI CCK weak signal threshold low */
+ u32_t ast_ani_stepup; /* ANI increased first step level */
+ u32_t ast_ani_stepdown;/* ANI decreased first step level */
+ u32_t ast_ani_ofdmerrs;/* ANI cumulative ofdm phy err count */
+ u32_t ast_ani_cckerrs;/* ANI cumulative cck phy err count */
+ u32_t ast_ani_reset; /* ANI parameters zero'd for non-STA */
+ u32_t ast_ani_lzero; /* ANI listen time forced to zero */
+ u32_t ast_ani_lneg; /* ANI listen time calculated < 0 */
+ ZM_HAL_MIB_STATS ast_mibstats; /* MIB counter stats */
+ ZM_HAL_NODE_STATS ast_nodestats; /* Latest rssi stats from driver */
+};
+
+/*
+ * Per-channel ANI state private to the driver.
+ */
+struct zsAniState {
+ ZM_HAL_CHANNEL c;
+ u8_t noiseImmunityLevel;
+ u8_t spurImmunityLevel;
+ u8_t firstepLevel;
+ u8_t ofdmWeakSigDetectOff;
+ u8_t cckWeakSigThreshold;
+
+ /* Thresholds */
+ u32_t listenTime;
+ u32_t ofdmTrigHigh;
+ u32_t ofdmTrigLow;
+ s32_t cckTrigHigh;
+ s32_t cckTrigLow;
+ s32_t rssiThrLow;
+ s32_t rssiThrHigh;
+
+ u32_t noiseFloor; /* The current noise floor */
+ u32_t txFrameCount; /* Last txFrameCount */
+ u32_t rxFrameCount; /* Last rx Frame count */
+ u32_t cycleCount; /* Last cycleCount (can detect wrap-around) */
+ u32_t ofdmPhyErrCount;/* OFDM err count since last reset */
+ u32_t cckPhyErrCount; /* CCK err count since last reset */
+ u32_t ofdmPhyErrBase; /* Base value for ofdm err counter */
+ u32_t cckPhyErrBase; /* Base value for cck err counters */
+ s16_t pktRssi[2]; /* Average rssi of pkts for 2 antennas */
+ s16_t ofdmErrRssi[2]; /* Average rssi of ofdm phy errs for 2 ant */
+ s16_t cckErrRssi[2]; /* Average rssi of cck phy errs for 2 ant */
+};
+
+typedef enum {
+ ZM_HAL_ANI_PRESENT, /* is ANI support present */
+ ZM_HAL_ANI_NOISE_IMMUNITY_LEVEL, /* set level */
+ ZM_HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION, /* enable/disable */
+ ZM_HAL_ANI_CCK_WEAK_SIGNAL_THR, /* enable/disable */
+ ZM_HAL_ANI_FIRSTEP_LEVEL, /* set level */
+ ZM_HAL_ANI_SPUR_IMMUNITY_LEVEL, /* set level */
+ ZM_HAL_ANI_MODE, /* 0 => manual, 1 => auto */
+ ZM_HAL_ANI_PHYERR_RESET, /* reset phy error stats */
+} ZM_HAL_ANI_CMD;
+
+#define AR_PHY_COUNTMAX (3 << 22) // Max counted before intr
+#define ZM_HAL_PROCESS_ANI 0x00000001 /* ANI state setup */
+#define ZM_RSSI_DUMMY_MARKER 0x127
+
+/* PHY registers in ar5416, related base and register offsets
+ may need to be changed in otus BB */
+#define AR_PHY_BASE 0x1C5800 /* base address of phy regs */
+#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
+
+#define AR_PHY_TEST 0x1C5800 /* PHY test control */
+#define PHY_AGC_CLR 0x10000000 /* disable AGC to A2 */
+#define RFSILENT_BB 0x00002000 /* shush bb */
+
+#define AR_PHY_TURBO 0x1C5804 /* frame control register */
+#define AR_PHY_FC_TURBO_MODE 0x00000001 /* Set turbo mode bits */
+#define AR_PHY_FC_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode setting */
+#define AR_PHY_FC_DYN2040_EN 0x00000004 /* Enable dyn 20/40 mode */
+#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 /* dyn 20/40 - primary only */
+#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/
+#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */
+#define AR_PHY_FC_HT_EN 0x00000040 /* ht enable */
+#define AR_PHY_FC_SHORT_GI_40 0x00000080 /* allow short GI for HT 40 */
+#define AR_PHY_FC_WALSH 0x00000100 /* walsh spatial spreading for 2 chains,2 streams TX */
+#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 /* single length (4us) 1st HT long training symbol */
+
+#define AR_PHY_TIMING2 0x1C5810 /* Timing Control 2 */
+#define AR_PHY_TIMING2_USE_FORCE 0x00001000
+#define AR_PHY_TIMING2_FORCE_VAL 0x00000fff
+
+#define AR_PHY_TIMING3 0x1C5814 /* Timing control 3 */
+#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
+#define AR_PHY_TIMING3_DSC_MAN_S 17
+#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
+#define AR_PHY_TIMING3_DSC_EXP_S 13
+
+#define AR_PHY_CHIP_ID 0x1C5818 /* PHY chip revision ID */
+#define AR_PHY_CHIP_ID_REV_0 0x80 /* 5416 Rev 0 (owl 1.0) BB */
+#define AR_PHY_CHIP_ID_REV_1 0x81 /* 5416 Rev 1 (owl 2.0) BB */
+
+#define AR_PHY_ACTIVE 0x1C581C /* activation register */
+#define AR_PHY_ACTIVE_EN 0x00000001 /* Activate PHY chips */
+#define AR_PHY_ACTIVE_DIS 0x00000000 /* Deactivate PHY chips */
+
+#define AR_PHY_RF_CTL2 0x1C5824
+#define AR_PHY_TX_END_DATA_START 0x000000FF
+#define AR_PHY_TX_END_DATA_START_S 0
+#define AR_PHY_TX_END_PA_ON 0x0000FF00
+#define AR_PHY_TX_END_PA_ON_S 8
+
+
+#define AR_PHY_RF_CTL3 0x1C5828
+#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
+#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
+
+#define AR_PHY_ADC_CTL 0x1C582C
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
+#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
+#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
+#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 /* BB Rev 4.2+ only */
+#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 /* BB Rev 4.2+ only */
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
+#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
+
+#define AR_PHY_ADC_SERIAL_CTL 0x1C5830
+#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
+#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
+
+#define AR_PHY_RF_CTL4 0x1C5834
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000
+#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000
+#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00
+#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
+#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
+
+#define AR_PHY_SETTLING 0x1C5844
+#define AR_PHY_SETTLING_SWITCH 0x00003F80
+#define AR_PHY_SETTLING_SWITCH_S 7
+
+#define AR_PHY_RXGAIN 0x1C5848
+#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
+#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
+#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
+#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
+
+#define AR_PHY_DESIRED_SZ 0x1C5850
+#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
+#define AR_PHY_DESIRED_SZ_ADC_S 0
+#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
+#define AR_PHY_DESIRED_SZ_PGA_S 8
+#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
+#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
+
+#define AR_PHY_FIND_SIG 0x1C5858
+#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
+#define AR_PHY_FIND_SIG_FIRSTEP_S 12
+#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
+#define AR_PHY_FIND_SIG_FIRPWR_S 18
+
+#define AR_PHY_AGC_CTL1 0x1C585C
+#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80
+#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
+#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000
+#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
+
+#define AR_PHY_AGC_CONTROL 0x1C5860 /* chip calibration and noise floor setting */
+#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */
+#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calculation */
+
+#define AR_PHY_CCA 0x1C5864
+#define AR_PHY_MINCCA_PWR 0x1FF00000
+#define AR_PHY_MINCCA_PWR_S 19
+#define AR_PHY_CCA_THRESH62 0x0007F000
+#define AR_PHY_CCA_THRESH62_S 12
+
+#define AR_PHY_SFCORR_LOW 0x1C586C
+#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
+#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
+#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
+#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
+
+#define AR_PHY_SFCORR 0x1C5868
+#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
+#define AR_PHY_SFCORR_M2COUNT_THR_S 0
+#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
+#define AR_PHY_SFCORR_M1_THRESH_S 17
+#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
+#define AR_PHY_SFCORR_M2_THRESH_S 24
+
+#define AR_PHY_SLEEP_CTR_CONTROL 0x1C5870
+#define AR_PHY_SLEEP_CTR_LIMIT 0x1C5874
+#define AR_PHY_SLEEP_SCAL 0x1C5878
+
+#define AR_PHY_PLL_CTL 0x1C587c /* PLL control register */
+#define AR_PHY_PLL_CTL_40 0xaa /* 40 MHz */
+#define AR_PHY_PLL_CTL_40_5413 0x04
+#define AR_PHY_PLL_CTL_44 0xab /* 44 MHz for 11b, 11g */
+#define AR_PHY_PLL_CTL_44_2133 0xeb /* 44 MHz for 11b, 11g */
+#define AR_PHY_PLL_CTL_40_2133 0xea /* 40 MHz for 11a, turbos */
+
+#define AR_PHY_RX_DELAY 0x1C5914 /* analog pow-on time (100ns) */
+#define AR_PHY_RX_DELAY_DELAY 0x00003FFF /* delay from wakeup to rx ena */
+
+#define AR_PHY_TIMING_CTRL4 0x1C5920 /* timing control */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F /* Mask for kcos_theta-1 for q correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 /* shift for Q_COFF */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 /* Mask for sin_theta for i correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 /* Shift for sin_theta for i correction */
+#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 /* enable IQ correction */
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 /* Mask for max number of samples (logarithmic) */
+#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 /* Shift for max number of samples */
+#define AR_PHY_TIMING_CTRL4_DO_IQCAL 0x10000 /* perform IQ calibration */
+
+#define AR_PHY_TIMING5 0x1C5924
+#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
+#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
+
+#define AR_PHY_POWER_TX_RATE1 0x1C5934
+#define AR_PHY_POWER_TX_RATE2 0x1C5938
+#define AR_PHY_POWER_TX_RATE_MAX 0x1C593c
+#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
+
+#define AR_PHY_FRAME_CTL 0x1C5944
+#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038
+#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
+
+#define AR_PHY_TXPWRADJ 0x1C594C /* BB Rev 4.2+ only */
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0
+#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
+#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
+
+#define AR_PHY_RADAR_0 0x1C5954 /* radar detection settings */
+#define AR_PHY_RADAR_0_ENA 0x00000001 /* Enable radar detection */
+#define AR_PHY_RADAR_0_INBAND 0x0000003e /* Inband pulse threshold */
+#define AR_PHY_RADAR_0_INBAND_S 1
+#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 /* Pulse rssi threshold */
+#define AR_PHY_RADAR_0_PRSSI_S 6
+#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 /* Pulse height threshold */
+#define AR_PHY_RADAR_0_HEIGHT_S 12
+#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 /* Radar rssi threshold */
+#define AR_PHY_RADAR_0_RRSSI_S 18
+#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 /* Radar firpwr threshold */
+#define AR_PHY_RADAR_0_FIRPWR_S 24
+
+#define AR_PHY_SWITCH_CHAIN_0 0x1C5960
+#define AR_PHY_SWITCH_COM 0x1C5964
+
+#define AR_PHY_SIGMA_DELTA 0x1C596C /* AR5312 only */
+#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
+#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
+#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8
+#define AR_PHY_SIGMA_DELTA_FILT2_S 3
+#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00
+#define AR_PHY_SIGMA_DELTA_FILT1_S 8
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
+#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
+
+#define AR_PHY_RESTART 0x1C5970 /* restart */
+#define AR_PHY_RESTART_DIV_GC 0x001C0000 /* bb_ant_fast_div_gc_limit */
+#define AR_PHY_RESTART_DIV_GC_S 18
+
+#define AR_PHY_RFBUS_REQ 0x1C597C
+#define AR_PHY_RFBUS_REQ_EN 0x00000001
+
+#define AR_PHY_RX_CHAINMASK 0x1C59a4
+
+#define AR_PHY_EXT_CCA 0x1C59bc
+#define AR_PHY_EXT_MINCCA_PWR 0xFF800000
+#define AR_PHY_EXT_MINCCA_PWR_S 23
+
+#define AR_PHY_HALFGI 0x1C59D0 /* Timing control 3 */
+#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0
+#define AR_PHY_HALFGI_DSC_MAN_S 4
+#define AR_PHY_HALFGI_DSC_EXP 0x0000000F
+#define AR_PHY_HALFGI_DSC_EXP_S 0
+
+#define AR_PHY_HEAVY_CLIP_ENABLE 0x1C59E0
+
+#define AR_PHY_M_SLEEP 0x1C59f0 /* sleep control registers */
+#define AR_PHY_REFCLKDLY 0x1C59f4
+#define AR_PHY_REFCLKPD 0x1C59f8
+
+/* PHY IQ calibration results */
+#define AR_PHY_IQCAL_RES_PWR_MEAS_I 0x1C5C10 /* power measurement for I */
+#define AR_PHY_IQCAL_RES_PWR_MEAS_Q 0x1C5C14 /* power measurement for Q */
+#define AR_PHY_IQCAL_RES_IQ_CORR_MEAS 0x1C5C18 /* IQ correlation measurement */
+
+#define AR_PHY_CURRENT_RSSI 0x1C5C1c /* rssi of current frame rx'd */
+
+#define AR_PHY_RFBUS_GRANT 0x1C5C20
+#define AR_PHY_RFBUS_GRANT_EN 0x00000001
+
+#define AR_PHY_MODE 0x1C6200 /* Mode register */
+#define AR_PHY_MODE_AR2133 0x08 /* AR2133 */
+#define AR_PHY_MODE_AR5111 0x00 /* AR5111/AR2111 */
+#define AR_PHY_MODE_AR5112 0x08 /* AR5112*/
+#define AR_PHY_MODE_DYNAMIC 0x04 /* dynamic CCK/OFDM mode */
+#define AR_PHY_MODE_RF2GHZ 0x02 /* 2.4 GHz */
+#define AR_PHY_MODE_RF5GHZ 0x00 /* 5 GHz */
+#define AR_PHY_MODE_CCK 0x01 /* CCK */
+#define AR_PHY_MODE_OFDM 0x00 /* OFDM */
+
+#define AR_PHY_CCK_TX_CTRL 0x1C6204
+#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
+
+#define AR_PHY_CCK_DETECT 0x1C6208
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
+#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 // [12:6] settling time for antenna switch
+#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
+#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
+
+#define AR_PHY_GAIN_2GHZ 0x1C620C
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
+#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00
+#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F
+#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
+
+#define AR_PHY_CCK_RXCTRL4 0x1C621C
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000
+#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
+
+#define AR_PHY_DAG_CTRLCCK 0x1C6228
+#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 /* BB Rev 4.2+ only */
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 /* BB Rev 4.2+ only */
+#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 /* BB Rev 4.2+ only */
+
+#define AR_PHY_POWER_TX_RATE3 0x1C6234
+#define AR_PHY_POWER_TX_RATE4 0x1C6238
+
+#define AR_PHY_SCRM_SEQ_XR 0x1C623C
+#define AR_PHY_HEADER_DETECT_XR 0x1C6240
+#define AR_PHY_CHIRP_DETECTED_XR 0x1C6244
+#define AR_PHY_BLUETOOTH 0x1C6254
+
+#define AR_PHY_TPCRG1 0x1C6258 /* ar2413 power control */
+#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
+#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
+
+#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
+#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
+#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
+#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
+#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
+#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
+//
+
+#define AR_PHY_ANALOG_SWAP 0xa268
+#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
+
+#define AR_PHY_TPCRG5 0x1C626C /* ar2413 power control */
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
+#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
+#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
+
+#define AR_PHY_POWER_TX_RATE5 0x1C638C
+#define AR_PHY_POWER_TX_RATE6 0x1C6390
+
+#define AR_PHY_CAL_CHAINMASK 0x1C639C
+
+#define AR_PHY_POWER_TX_SUB 0x1C63C8
+#define AR_PHY_POWER_TX_RATE7 0x1C63CC
+#define AR_PHY_POWER_TX_RATE8 0x1C63D0
+#define AR_PHY_POWER_TX_RATE9 0x1C63D4
diff --git a/drivers/staging/otus/hal/hpfw2.c b/drivers/staging/otus/hal/hpfw2.c
new file mode 100644
index 000000000000..baceb0299765
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfw2.c
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+
+const u32_t zcP2FwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE947FFC, 0xE114D594,
+0x1E13D494, 0x67521E4C, 0xD494D693, 0x37402769,
+0x62528F06, 0x7201D692, 0x60602522, 0x2600C93F,
+0xD7906152, 0x2512611D, 0x264B6652, 0x2562470B,
+0x0009B00D, 0xE60095AC, 0xC84060E2, 0x2F028F03,
+0x8FF93652, 0x7F047601, 0xA05A4F26, 0x4F226EF6,
+0x410BD185, 0xD4850009, 0x0009440B, 0x450BD584,
+0xD7840009, 0xD284E1FF, 0x2712611D, 0xD4835029,
+0xE1FFCB01, 0x1209E501, 0x12112212, 0xE7202452,
+0x4718D57F, 0x2572D27F, 0xD17FE700, 0xD680D47F,
+0xE2012270, 0x24702172, 0xD67E2620, 0x2641E4FF,
+0xD57DE600, 0x666DE104, 0x76016063, 0x4000626D,
+0x8FF83212, 0xD5790545, 0x2520E201, 0xD279D778,
+0x2710E100, 0xE5802212, 0x655C6613, 0x666DD476,
+0x76046763, 0x374C626D, 0x8FF83253, 0xD4732712,
+0xD573E101, 0xD6732410, 0x2542E400, 0xE03AE501,
+0xD272D771, 0xE0390654, 0x27110654, 0x000B4F26,
+0x7FC82211, 0xD76FD16E, 0xDC70DB6F, 0xD271DE70,
+0xD572D471, 0x1F12D672, 0x1F76710C, 0x1FB877FC,
+0x1FEA1FC9, 0x72041F2B, 0xDE6FDC6E, 0x1F13EB10,
+0x1F511F44, 0x1F771F65, 0xD86C1F2C, 0xDD6DD96C,
+0xD26DEA00, 0x89003A22, 0xD1587A01, 0x88016010,
+0x56F98B03, 0x4218E201, 0xD1682622, 0x0009410B,
+0x440BD467, 0xD5670009, 0x0009450B, 0x6010D14C,
+0x8B108801, 0xE650D14B, 0x46186212, 0x8B083266,
+0x56FAD147, 0x2120E200, 0xCB016062, 0x2602A003,
+0x72012710, 0x60822122, 0x89098801, 0xE2C8D15A,
+0x622C6612, 0x89033626, 0x6010D158, 0x8BC88801,
+0x51F76792, 0x217252F6, 0xD6555191, 0x55FB2212,
+0x52FC6462, 0x55612542, 0x2252E400, 0x61436643,
+0x05DE6013, 0x36CC4608, 0x02DE2652, 0xC9036021,
+0x8B028801, 0x720162E2, 0x74012E22, 0x36B3664C,
+0x71048FEE, 0x66C2D147, 0x45286512, 0x265B4518,
+0x60822C62, 0x89018801, 0x0009A168, 0x6272D742,
+0x8B132228, 0xD726D541, 0x6552D441, 0x51436672,
+0x316C365C, 0x27622668, 0x14138D05, 0x6262D63D,
+0xB1A57201, 0xD61E2622, 0x2622E200, 0x52916692,
+0x8B013620, 0x0009A144, 0x6061A06E, 0x001C001C,
+0x001D4020, 0x0000B38E, 0xFFFF0000, 0x12340000,
+0x001E1015, 0x00201278, 0x002018A0, 0x00201922,
+0x0020128C, 0x001C3510, 0x001C3624, 0x001E212C,
+0x0020397C, 0x00203514, 0x00203984, 0x00203990,
+0x0020399C, 0x002039F8, 0x002039FC, 0x002039A4,
+0x002039A5, 0x002039A8, 0x00117700, 0x00203A12,
+0x00203578, 0x001142D8, 0x00203A14, 0x00203A16,
+0x001C3D30, 0x00117718, 0x001C3D00, 0x001C1000,
+0x001C36F8, 0x00117734, 0x001C3684, 0x00117710,
+0x001C3520, 0x00117600, 0x00117740, 0x001C1028,
+0x0020358C, 0x002039AC, 0x7FFFFFFF, 0x00201734,
+0x002032BE, 0x002022E8, 0x00203DC0, 0x002039FA,
+0x00203584, 0x002039EC, 0x001C3D2C, 0x001C36B0,
+0x0020351C, 0x0011775C, 0x8801C90F, 0xA0CF8901,
+0xD17C0009, 0x36206212, 0xD47B8904, 0x2421E200,
+0x2162A0CC, 0x6211D179, 0x89012228, 0x0009A0C3,
+0xE202D775, 0x75016571, 0x3123615D, 0x27518D02,
+0x0009A0BC, 0xD27255F2, 0x62226052, 0x40094019,
+0xC90F4009, 0x8F19880A, 0x52F31F2D, 0x40196022,
+0x40094009, 0x8808C90F, 0xA0A78901, 0x60630009,
+0x51F255F8, 0xE701CB01, 0x2502D263, 0xE1002172,
+0x2211D564, 0x74016452, 0x2542A098, 0x8B3F8805,
+0x602252F3, 0x40094019, 0xC90F4009, 0x8B168802,
+0xE5FFD45D, 0x655D6742, 0x8B102758, 0x6272D75B,
+0x8B0C3260, 0x55F257F8, 0x2762E101, 0xD5522512,
+0xD757E400, 0x62722541, 0xA0777201, 0x52F32722,
+0x40196022, 0x40094009, 0x8805C90F, 0x31B38B6E,
+0xD5508B6C, 0x615257F4, 0x7101E240, 0x64722512,
+0x1F4DD14D, 0x42182419, 0x8B033420, 0x6262D64B,
+0x26227201, 0xE200D640, 0x2621B0AA, 0x0009A056,
+0x3123E220, 0x88038B52, 0x52F38B1E, 0x40196022,
+0x40094009, 0x8803C90F, 0xD7418B16, 0x647251F4,
+0x7401D23D, 0x65122742, 0x1F5DE640, 0x46182529,
+0x8B033560, 0x6262D63B, 0x26227201, 0xE200D62E,
+0x2621B086, 0x0009A010, 0xD738D137, 0xD22A6412,
+0xE5007401, 0x21423A76, 0x22518F06, 0xEA00D634,
+0x72016262, 0x2622B074, 0x2FB2D532, 0x95406652,
+0xD4305BF1, 0x36205241, 0x60618910, 0x8B01C803,
+0x2B22E201, 0x8FF54510, 0x57F15664, 0x6272E1F0,
+0x41284118, 0x2722221B, 0x6BF2A008, 0x6BF2A006,
+0xE200D615, 0xD1152621, 0x2121E200, 0xE20256F5,
+0x42186662, 0x26284228, 0x1F6D8D0C, 0xD61FD11E,
+0x460B6511, 0x2008645D, 0x57F58904, 0x6272D11C,
+0x27222219, 0xD11BE201, 0x66122822, 0x8B012668,
+0x0009AE17, 0x450BD518, 0xD1180009, 0xAE10E600,
+0x07D12160, 0x00203A0C, 0x00203A10, 0x00203A18,
+0x001C3DC0, 0x0011772C, 0x001C3B88, 0x002039F4,
+0x0011773C, 0x00117744, 0x0000F000, 0x00117764,
+0x00117748, 0x00117768, 0x0011776C, 0x01FFFFFF,
+0x0011774C, 0x00203584, 0x001142D8, 0x00114774,
+0xFDFFFFFF, 0x00203DC0, 0x0020246C, 0x002039FA,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xD11F7FF4, 0x6212DE1F, 0x67E25411, 0xD41E1F41,
+0x1F722F22, 0x6743D51D, 0x7794D21D, 0x5A425841,
+0x6C726942, 0x6D225B16, 0xE6006052, 0x2502CB20,
+0x7601E540, 0x3253626D, 0x62F28BFB, 0x212255F1,
+0x55F21151, 0x2E52D613, 0x14A21481, 0xD4122492,
+0x11B627C2, 0x674226D2, 0xD911DA10, 0x2A72E801,
+0x1A8C490B, 0x4218E201, 0x7F0C1A2C, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0x000068F6,
+0x001C3B9C, 0x001C3D98, 0x001C3700, 0x001C3500,
+0x001C5960, 0x001C8960, 0x0020358C, 0x001C3D00,
+0x00201610, 0x2F962F86, 0x2FC62FA6, 0x2FE62FD6,
+0x4F124F22, 0x7F884F02, 0xE018DEB2, 0xD4B261E0,
+0x61E30F14, 0x62107101, 0x440BE01C, 0x20080F24,
+0x8F126D03, 0xD4AD1F08, 0x6740DDAD, 0x657CD4AD,
+0x470BD7AD, 0xD2AD0009, 0x621C6120, 0x46086623,
+0x36284608, 0x3D6C4608, 0xE01C1FD8, 0xE58004FC,
+0x604C66E2, 0x3050655C, 0x2D628F17, 0x01FCE018,
+0xDEA3E500, 0x641CA008, 0x6753655D, 0x607037EC,
+0x31DC6153, 0x80147501, 0x3243625D, 0xD49D8BF4,
+0xE200D59D, 0xA27F2421, 0x20082521, 0xE0188B13,
+0xE50001FC, 0xA009DE96, 0x655D641C, 0x32EC6253,
+0x62536722, 0x32DC6672, 0x75041261, 0x3243625D,
+0xA2698BF3, 0x88012D10, 0xE0188B16, 0xE40001FC,
+0x671C2D40, 0x624DDE8A, 0x8B013273, 0x0009A25C,
+0x6DE3644D, 0x7D046243, 0x32EC6643, 0x652236DC,
+0x74086162, 0x2512AFEF, 0x8B198804, 0x01FCE018,
+0x2D70E700, 0x1FD56D1C, 0x627DDE7D, 0x8B0132D3,
+0x0009A242, 0x6173677D, 0x31EC65E3, 0x75046412,
+0x365C6673, 0x61426262, 0x21297708, 0x2412AFED,
+0x8B198805, 0x01FCE018, 0x2D70E700, 0x1FD46D1C,
+0x627DDE6F, 0x8B0132D3, 0x0009A226, 0x6173677D,
+0x31EC65E3, 0x75046412, 0x365C6673, 0x61426262,
+0x212B7708, 0x2412AFED, 0x8B598831, 0x61E6DE67,
+0x61E31F19, 0x64E27104, 0x1F4A6216, 0x1F2B6416,
+0x75E46513, 0x66536712, 0x1F4C7604, 0x64521F7D,
+0xD75F6E66, 0x27E0D25F, 0xDE5F6062, 0xC9013245,
+0x65622E00, 0x4609060A, 0x4609D15C, 0x46094509,
+0x21501F4E, 0xB2B0646D, 0x620D1F6F, 0x8B012228,
+0x0009A1EA, 0xD756DE55, 0x661C61E0, 0x6410D150,
+0x470B654C, 0x7FFC54FF, 0x2FE25EFE, 0x51FE7FFC,
+0x2F12E040, 0x55FBD14F, 0x57FD56FC, 0x04FE410B,
+0xD24D7F08, 0xE11C640D, 0x1D412D10, 0xD44B6522,
+0x67421D52, 0x1D73DE4A, 0xD24A65E2, 0x67221D54,
+0x1D75D249, 0xD2496E22, 0x66221DE6, 0x1D67A1BC,
+0x89018830, 0x0009A08E, 0xE340D538, 0x33FC6156,
+0x23126456, 0x71046153, 0x67521341, 0x13726416,
+0x7EE46E13, 0x65E66212, 0x66E3D731, 0x13246EE2,
+0x760427E0, 0x6062D22F, 0x3255DE2F, 0x2E00C901,
+0x060A6E62, 0xD12D4609, 0x4E094609, 0x13434609,
+0x646D21E0, 0xB2501F5E, 0x620D1F6F, 0x8B012228,
+0x0009A18A, 0xDE25D522, 0x61E06450, 0xD724654C,
+0x470B54FF, 0x7FFC661C, 0x06FEE054, 0x7FFC2F62,
+0xEE4001FE, 0x2F123EFC, 0x55E2D125, 0x57E456E3,
+0x64E2410B, 0xD21C7F08, 0xE11C640D, 0x1D412D10,
+0xD61A6522, 0x67621D52, 0x1D73DE19, 0xD2196EE2,
+0x62221DE4, 0xD2181D25, 0x1D266222, 0x6222D217,
+0x1D27A15A, 0x00117800, 0x00202A18, 0x00203996,
+0x002035BC, 0x00203A7C, 0x002018D0, 0x00203995,
+0x00117804, 0x00203A14, 0x00203A16, 0x00117810,
+0x00203991, 0x10624DD3, 0x00203992, 0x00203993,
+0x00114AA4, 0x00200F68, 0x001C5864, 0x001C6864,
+0x001C7864, 0x001C59BC, 0x001C69BC, 0x001C79BC,
+0x00200FC0, 0x8B048833, 0x470BD7A2, 0xA123EE00,
+0x88282DE0, 0xA0D38901, 0xDE9F0009, 0x62E1E143,
+0x3216E054, 0x0FE68F02, 0x2E21E240, 0x622D62E1,
+0x8B013217, 0x0009A0BC, 0xE50185E1, 0x8B013056,
+0x0009A0B6, 0x2D10E101, 0x64E1B111, 0x06FEE054,
+0x6261E143, 0x3517652D, 0xE6408945, 0x8B0C3563,
+0xE058E41A, 0xE5000F45, 0x72C0E05C, 0x60230F55,
+0x6703C907, 0xA014E060, 0x66530F75, 0x46214621,
+0x46214621, 0x45214621, 0xE0587618, 0x0F654521,
+0xE0034521, 0xE05C2509, 0xE0070F55, 0xE0602209,
+0xE8540F25, 0x858238FC, 0x640D65F3, 0x1844B170,
+0xDD7A8584, 0x85866C0D, 0x610D4C08, 0x410860C3,
+0xE00F0EFE, 0x18154D0B, 0x2E296207, 0x668260C3,
+0x85620FE6, 0x4D0B5185, 0x2E0B600D, 0x548460C3,
+0xB13C0FE6, 0xE05465F3, 0xE5400EFE, 0xE06C62E1,
+0x3653662D, 0x0F668D41, 0xC9036023, 0x40004008,
+0x61036403, 0xD965E070, 0x0F46E5FF, 0xE074655C,
+0x60530F96, 0x6263490B, 0x42214221, 0x42214221,
+0x42006723, 0x4200327C, 0x6C074621, 0x4621E054,
+0x606309FE, 0x4008C903, 0x790630FC, 0x6A036D2D,
+0x65F3E800, 0x64D3B124, 0xE0706EA2, 0x2AE22EC9,
+0x01FE6694, 0x666CE074, 0x470B07FE, 0x2E0B6063,
+0x65F32AE2, 0xB0FA64D3, 0x628D7801, 0x32E3EE06,
+0x7D018FE7, 0x0EFEE054, 0xE05462E1, 0x420006FE,
+0x760C8561, 0x701B302C, 0xE4006103, 0xE70465F3,
+0x68667401, 0x3973694D, 0x8FF92582, 0x65F37504,
+0x641DB0DD, 0x0EFEE054, 0x64E1B09C, 0x0009A054,
+0xD43B56F8, 0xEA01D23B, 0x26A0420B, 0x0009A04C,
+0x06FCE01C, 0x8829606C, 0x5CF88B08, 0xE200D636,
+0x52612C20, 0x642DB04B, 0x0009A03E, 0x666CE681,
+0x8B043060, 0x420BD231, 0xA03554F8, 0xE6820009,
+0x3060666C, 0xD22E8B04, 0x54F8420B, 0x0009A02C,
+0x666CE683, 0x8B0A3060, 0xDA2755F8, 0x2590E900,
+0xD82855A1, 0x2852D628, 0xA01D52A2, 0xE6922620,
+0x3060666C, 0xD2208B08, 0x5C21D824, 0x6CCC52F8,
+0x28C1E600, 0x2260A010, 0x666CE693, 0x8B063060,
+0xD61F59F8, 0xE201EA00, 0xA00529A0, 0xD6162621,
+0xD21DD41C, 0x6562420B, 0x4F067F78, 0x4F264F16,
+0x6DF66EF6, 0x6AF66CF6, 0x000B69F6, 0x4F2268F6,
+0xE240614D, 0x89323123, 0x3127E21F, 0x8B27D713,
+0xD406614D, 0xE00171E0, 0x5671440B, 0x26596507,
+0x1761A025, 0x00200FBC, 0x00117804, 0x00203470,
+0x00203A9C, 0x002018C0, 0x00117800, 0x00115F00,
+0x00116058, 0x0020397C, 0x00203990, 0x00203A1A,
+0x00203A16, 0x00203AB4, 0x002018D0, 0x001C3704,
+0xE001D490, 0x6672440B, 0x26596507, 0x4F262762,
+0x0009000B, 0x614D4F22, 0x3123E240, 0xE21F8912,
+0xD7893127, 0x614D8B08, 0x5671D286, 0x420B71E0,
+0x260BE001, 0x1761A006, 0x6672D282, 0xE001420B,
+0x2762260B, 0x000B4F26, 0xE6400009, 0x46284618,
+0x6252D57E, 0x89FC2268, 0x0009000B, 0x4618E680,
+0xD57A4628, 0x22686252, 0x000B89FC, 0xA0010009,
+0x7201E200, 0x8BFC3242, 0x0009000B, 0x4618E680,
+0xD5734628, 0x22686252, 0x000B8BFC, 0x2FE60009,
+0x7FFC4F22, 0xBFF16E53, 0x61E22F42, 0xE280D66D,
+0x54E11615, 0x16464218, 0x422855E2, 0x57E31657,
+0x16786EF2, 0x26E22E2B, 0x4F267F04, 0x6EF6AFCE,
+0x2FD62FC6, 0x4F222FE6, 0x6C53DD62, 0x6E43BFD6,
+0x2DE2BFBB, 0x0009BFD2, 0x2C1251D5, 0x1C4154D6,
+0x1C5255D7, 0x1C6356D8, 0x6EF64F26, 0x000B6DF6,
+0x61636CF6, 0xA004E600, 0x62564109, 0x24227601,
+0x36127404, 0x000B8BF9, 0xD6530009, 0x8562E500,
+0xA00B674D, 0x655D610D, 0x40006053, 0x305CD44F,
+0x024D4008, 0x3270622D, 0x75018905, 0x3213625D,
+0x000B8BF1, 0x000BE000, 0x2FE6E001, 0x54416743,
+0x4E08EE7F, 0x4E28D246, 0x25E96543, 0x60436E21,
+0x9E7562ED, 0x4529C903, 0xE60032E3, 0x8D456103,
+0x21184509, 0xD23F8B05, 0x002C6053, 0xA08AC93F,
+0x60136603, 0x8B268801, 0x880C6053, 0xD53A8B04,
+0xC93F8453, 0x6603A07F, 0x8B048808, 0x84E2DE36,
+0xA078C93F, 0x880D6603, 0x8B03D633, 0xC93F8461,
+0x6603A071, 0x88096260, 0x622C8F09, 0xE014DE2C,
+0x655C05EC, 0x60233258, 0xA064C93F, 0x60236603,
+0xA060C93F, 0x88026603, 0xE0078B5D, 0x60432509,
+0x8905C810, 0x6053D225, 0xC93F002C, 0x6603A053,
+0x6053DE23, 0xC93F00EC, 0x6603A04D, 0x88016013,
+0x60538B19, 0x8B04880C, 0x8423D21E, 0xA042C93F,
+0x88086603, 0xD51B8B04, 0xC93F8452, 0x6603A03B,
+0xD618880D, 0x84618B03, 0xA034C93F, 0x60606603,
+0xA030C93F, 0x88026603, 0xE0078B2D, 0x60432509,
+0x8923C810, 0x6053DE10, 0xC93F00EC, 0x6603A023,
+0x00000BB8, 0x00203470, 0x001C3704, 0x001C373C,
+0x001C3700, 0x001C370C, 0x00114000, 0x00114008,
+0x001142D8, 0x001142E4, 0x001142E8, 0x001142F5,
+0x001142ED, 0x001142FD, 0x00114309, 0x6053D209,
+0xC93F002C, 0x60136603, 0x8B038802, 0xC8106043,
+0x76028900, 0xC93F6063, 0x40004018, 0x1741240B,
+0x6EF6000B, 0x00114301, 0x0009A16E, 0x2FE62FD6,
+0xDD944F22, 0xA0049EB2, 0xD4930009, 0x420BD293,
+0x62D265D2, 0x8BF822E8, 0x0009A004, 0xD28FD490,
+0x55D1420B, 0x22E852D1, 0xA0048BF8, 0xD48D0009,
+0x420BD28A, 0x52D255D2, 0x8BF822E8, 0x0009A004,
+0xD286D489, 0x55D3420B, 0x22E852D3, 0xA0048BF8,
+0xD4860009, 0x420BD281, 0x52D455D4, 0x8BF822E8,
+0x6EF64F26, 0x6DF6000B, 0x2FD62FC6, 0x4F222FE6,
+0x6E636C73, 0x6D53B01A, 0x64D357F4, 0xB05F65E3,
+0xB07566C3, 0xB0A40009, 0xB0A80009, 0xB0AC0009,
+0xB0AC0009, 0xB0AF0009, 0xB03154F5, 0x6CCD6C03,
+0x4F2660C3, 0x6DF66EF6, 0x6CF6000B, 0x3412D170,
+0xD6700529, 0x2650D770, 0x2742000B, 0x0009A018,
+0x2FD62FC6, 0x4F222FE6, 0x6E636C73, 0x6D53BFEE,
+0x64D357F4, 0xB03365E3, 0xB08D66C3, 0xB00F54F5,
+0x6CCD6C03, 0x4F2660C3, 0x6DF66EF6, 0x6CF6000B,
+0xE503D162, 0xD763D462, 0x21524518, 0x2472000B,
+0xD45FD15E, 0x2162E600, 0x2462000B, 0xBF734F22,
+0xBF73E40A, 0xD25C0009, 0x4118E104, 0xE40AE500,
+0xBF692212, 0xD7592252, 0xCB206072, 0x000B4F26,
+0x4F222702, 0x410BD156, 0xD556E400, 0x4F26452B,
+0xD1552FE6, 0x66126E63, 0x92104418, 0x44084528,
+0x45002629, 0x265B4408, 0x264B4400, 0x21624708,
+0xD14E4708, 0x217227EB, 0x6EF6000B, 0x1FFF03F0,
+0x4F222FE6, 0xE101DE4A, 0xBF3DE40A, 0x67E32E12,
+0xE500776C, 0xE204E130, 0x2752E40A, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x27222712, 0x27522752, 0x27522752, 0x27522752,
+0x27522752, 0x175ABF18, 0x2E62E600, 0x000B4F26,
+0xD2346EF6, 0xE441E101, 0x000B2212, 0xD1322242,
+0xE605D432, 0x000B2162, 0x000B2462, 0xD2300009,
+0xE40AE601, 0x2262AF00, 0x2FC62FB6, 0x2FE62FD6,
+0x7FFC4F22, 0x6C43DB2B, 0xED0060B2, 0x2B02CB03,
+0xC90360B2, 0x6E03A008, 0x89073DC2, 0xE46460B2,
+0xB07CC903, 0x7D016E03, 0x8BF52EE8, 0x8F043DC2,
+0xD4212FE1, 0x460BD621, 0x62F10009, 0x6023622D,
+0x89FFC801, 0x7F046023, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6000B, 0x001C3B88, 0x00203AC8, 0x002018D0,
+0x00203AD0, 0x00203AD8, 0x00203AE0, 0x00203AE8,
+0x0025E720, 0x00203DBC, 0x00203980, 0x001C5968,
+0x001C3B40, 0x000F8000, 0x001D4004, 0x001C3500,
+0x002015E4, 0x00201610, 0x001C5814, 0x001C59D0,
+0x001C5830, 0x001C6268, 0x001C59A4, 0x001C639C,
+0x001C581C, 0x001C5860, 0x00203AF0, 0x002018C0,
+0x8F014411, 0x6043604B, 0x0009000B, 0x5651D52B,
+0x46286052, 0x306C000B, 0x2FC62FB6, 0x2FE62FD6,
+0x4F124F22, 0xBFF14F02, 0x6B036E43, 0xDD25DC24,
+0x0009BFEC, 0x3C0530B8, 0x4609060A, 0x46014609,
+0x020A3D65, 0x42094209, 0x32E24209, 0x4F068BF0,
+0x4F264F16, 0x6DF66EF6, 0x000B6CF6, 0x2FC66BF6,
+0x2FE62FD6, 0x4F124F22, 0xBFCF4F02, 0x6C036E43,
+0xBFCBDD13, 0x30C80009, 0x060A3D05, 0x46094609,
+0x36E24601, 0x4F068BF5, 0x4F264F16, 0x6DF66EF6,
+0x6CF6000B, 0x4F222FE6, 0xE102DE0B, 0xE403E500,
+0xBFB92E12, 0xE6062E52, 0xE7004618, 0x2E62E403,
+0x4F262E72, 0x6EF6AFB0, 0x0009000B, 0x001C1040,
+0xCCCCCCCD, 0x10624DD3, 0x001D4004, 0x2F962F86,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0xE5007F98,
+0x6453E710, 0x6B534728, 0xEE1ADCBC, 0x6153655D,
+0x315C4108, 0x75014108, 0x6043317C, 0x0F16665D,
+0xED0060B3, 0x21B136E3, 0x81128111, 0x11D28113,
+0x11D411D3, 0x74048FEA, 0xD8B167F2, 0x1871D9B1,
+0x58F12872, 0x1981D1B0, 0x59F22982, 0x5DF45AF3,
+0x54F65EF5, 0x21921191, 0x11A211A3, 0x11D411D5,
+0x11E611E7, 0x11481149, 0xDAA855F7, 0x57F8EE00,
+0x52F9DDA7, 0x64E3D6A7, 0x2A521A51, 0xD8A7D9A6,
+0x2D72EAEF, 0x6AAC2622, 0x6DE36EED, 0x61E34D08,
+0x41083DEC, 0x31EC4D08, 0x60B33D9C, 0x2DB14108,
+0xE05081D1, 0xE79F4108, 0x41084008, 0x81D2677C,
+0x318C60B3, 0x3472E200, 0x1DD281D3, 0xD4931D13,
+0x1D248D01, 0x65D3D48F, 0x7E01B0B2, 0x34A264ED,
+0xDA8C8BDA, 0x68A22FD2, 0x4829DD91, 0x64A22D82,
+0x694D7DFC, 0x2D92D286, 0x4E296E22, 0x2DE27D0C,
+0x6AD36822, 0xD784618D, 0x6D722A16, 0xD583D489,
+0x5E7224D2, 0x14E2D688, 0xEE005174, 0x58761414,
+0x1486D186, 0xE7105978, 0x62521498, 0x142A65E3,
+0x64E326E2, 0x644DE600, 0x48086843, 0x4808384C,
+0x6053381C, 0x28B10C86, 0x60B309CE, 0x60538191,
+0x60430ACE, 0x605381A2, 0x60B30DCE, 0x605381D3,
+0x740108CE, 0x09CE1882, 0x19E3624D, 0x32730ACE,
+0x8FE01A64, 0xD96A7504, 0x6C92E003, 0x2CB14018,
+0xDA6F6D92, 0xE05081D1, 0x40086E92, 0x619281E2,
+0x811360B3, 0xE6006492, 0x67921442, 0x17A3D468,
+0xE1FF6892, 0xE7031864, 0x46086563, 0x7501364C,
+0x665D2612, 0x8BF83673, 0xE003DC5A, 0x40186DC2,
+0x6EC22DB1, 0x81E1D25F, 0xEE0061C2, 0x64C21112,
+0x1423E024, 0xD45B65C2, 0x67C215E4, 0x8172E580,
+0x66E368C2, 0x655C8183, 0x6963666D, 0x6A6D7604,
+0x3A53394C, 0x29E28FF8, 0xDC54DB53, 0x740424B2,
+0x7F6824C2, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0x614268F6, 0xC8036011, 0xE5008F03,
+0x3420D23C, 0x60118B06, 0x8802C903, 0xD2398B06,
+0x8B033420, 0x65135612, 0x24225264, 0x6053000B,
+0x2FE62FD6, 0x7FEC4F22, 0x62536E53, 0x6D43E550,
+0x4508E400, 0xE101A001, 0x60435224, 0x81212211,
+0x60538123, 0x56E28122, 0x8BF53620, 0x16E4D238,
+0xE61464F3, 0x65E3420B, 0xE4FC65E1, 0x2E512549,
+0x65F361F1, 0x2F112149, 0xD13154D1, 0xE614410B,
+0x607157D1, 0x2701CB01, 0x7F141DE1, 0x6EF64F26,
+0x6DF6000B, 0x2FE62FD6, 0x7FEC4F22, 0x66536E53,
+0x6D43E5FC, 0x20596061, 0x2601CB01, 0x326052E2,
+0x12E48B06, 0x31E051E2, 0x52D18B04, 0x1E22A002,
+0x5664AFF0, 0x64F3D21E, 0x420BE614, 0x67E165E3,
+0x2719E1FC, 0x67F12E71, 0x271954D1, 0x65F3D118,
+0x410BE614, 0x52D12F71, 0xCB016021, 0x1DE12201,
+0x4F267F14, 0x000B6EF6, 0x00006DF6, 0x002039AC,
+0x0020357C, 0x00203584, 0x0020358C, 0x002035B4,
+0x00203998, 0x002039A0, 0x00100208, 0x001014C0,
+0x001E210C, 0x001C3D00, 0x002039EC, 0x001000C8,
+0x00117880, 0x00117780, 0x00040020, 0x0026C401,
+0x00200D42, 0x4F222FE6, 0xDE42624C, 0x42004208,
+0x3E2CA005, 0xD4405252, 0xBF695624, 0x65E22E62,
+0x352052E1, 0xD63D8BF6, 0x4F262622, 0x6EF6000B,
+0x2FC62FB6, 0x2FE62FD6, 0xDC394F22, 0x52C1DB39,
+0x362066C2, 0x6061891C, 0x8801C903, 0xDE348918,
+0xBF38DD35, 0x650364E3, 0x66B28503, 0x3262620D,
+0xD4328907, 0x0009BF76, 0x4D0BD431, 0xAFE60009,
+0xBF3D0009, 0xD42F64E3, 0x00094D0B, 0x0009AFDF,
+0x2262D22D, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x2FD62FC6, 0x4F222FE6, 0xDD29DC28, 0x6E4360C2,
+0x04DE4008, 0xE614D127, 0x65E3410B, 0xD127D726,
+0x55E227E2, 0x35E05254, 0x21228F04, 0x400860C2,
+0x122202DE, 0x605365C2, 0x75014008, 0x0DE606DE,
+0xC90F6053, 0x60632C02, 0x6EF64F26, 0x000B6DF6,
+0x85436CF6, 0x650D5643, 0x622D6262, 0x35277204,
+0xE1008F0C, 0x2268960C, 0xD6158B03, 0x72015261,
+0xD6131621, 0x6262E101, 0x26227201, 0x6013000B,
+0x000001FF, 0x0020358C, 0x00203584, 0x001C3D00,
+0x002035B4, 0x0020397C, 0x002018C0, 0x0020357C,
+0x00203B18, 0x00203B1C, 0x001C3D28, 0x002039EC,
+0x002039AC, 0x00200D42, 0x002039F0, 0x002039F4,
+0x00117754, 0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6,
+0x7FF84F22, 0x6C22D241, 0xC80360C3, 0xDE40896E,
+0xDA41DB40, 0x52B1D941, 0x362066B2, 0x60618945,
+0x8801C903, 0xDD3B8941, 0x420BD23D, 0x650364D3,
+0x60A12F02, 0x89328801, 0x85145153, 0x8840600C,
+0x1F118F0C, 0xD5376191, 0x641D450B, 0x8B262008,
+0xD7356691, 0x646D470B, 0x8B202008, 0x420BD233,
+0x51F154F1, 0xC8208511, 0xD1318904, 0x021EE050,
+0x01267201, 0x420BD22F, 0x200864F2, 0x64D38907,
+0x4D0BDD2D, 0xD12D65F2, 0xAFC4E601, 0xD22C2162,
+0x420B65F2, 0xD72B64E3, 0xAFBCE601, 0xD2262762,
+0x420B65F2, 0xAFB664D3, 0xDE270009, 0xDA28DD27,
+0x52D1DB28, 0x362066D2, 0x60618918, 0x8801C903,
+0xD4228914, 0x450BD516, 0x56030009, 0x8F0436E0,
+0xE2016503, 0xAFEC2A20, 0xD41F2B52, 0x420BD216,
+0xD7180009, 0x4118E101, 0x2712AFE3, 0xC80460C3,
+0xD21A8902, 0x0009420B, 0x4F267F08, 0x6DF66EF6,
+0x6BF66CF6, 0x000B6AF6, 0x000069F6, 0x001E2100,
+0x0020358C, 0x00203584, 0x00203A14, 0x001142D8,
+0x002014A6, 0x00115EA2, 0x00114774, 0x00200D8A,
+0x0020351C, 0x002016C2, 0x002014D0, 0x001E212C,
+0x00201534, 0x001C3D30, 0x00117880, 0x0020357C,
+0x0020399C, 0x00203998, 0x002035B4, 0x00200644,
+0xE601D203, 0x1265D503, 0x000B2252, 0x00001266,
+0x001C1010, 0x0000C34F, 0x0009000B, 0x0009000B,
+0x0009000B, 0x0009000B, 0xE000000B, 0xE000000B,
+0x0009000B, 0xE4FDD59D, 0xD69D6152, 0x25122149,
+0x74016052, 0x2502CB01, 0xD19A6752, 0x25722749,
+0xC8406010, 0x60628902, 0x2602CB04, 0xE1F76462,
+0x26422419, 0xE7016062, 0x2602C9CF, 0xE5026062,
+0x2602CB10, 0x47186062, 0x2602CB03, 0x000B1652,
+0xD58D1673, 0xD28ED78D, 0xE100D48E, 0x2511E600,
+0x22102711, 0x2461AFCE, 0xD28B664C, 0x362C4600,
+0xCB106060, 0x2600000B, 0xD287654C, 0x352C4500,
+0xE1EF6650, 0x000B2619, 0x664C2560, 0x4600D283,
+0x6060362C, 0x000BCB10, 0x654C2600, 0x4500D27F,
+0x6650352C, 0x2619E1EF, 0x2560000B, 0xD27A664C,
+0x362C4600, 0xCB086060, 0x2600000B, 0xD276654C,
+0x352C4500, 0xE1F76650, 0x000B2619, 0x664C2560,
+0x4600D272, 0x6060362C, 0x000BCB08, 0x654C2600,
+0x4500D26E, 0x6650352C, 0x2619E1F7, 0x2560000B,
+0xD669624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0x624C600C, 0x4200D664, 0x6020326C,
+0x4021C908, 0x40214021, 0x600C000B, 0x644CD160,
+0x6240341C, 0x602C000B, 0x644CD15E, 0x6240341C,
+0x602C000B, 0x4F222FE6, 0x645C6E43, 0x3467E60A,
+0xBFEB8914, 0x640C0009, 0x880160EC, 0xE00F8B02,
+0x2409A002, 0x44094409, 0xE60A624C, 0x89053263,
+0x644CBFE2, 0x6023620C, 0x8B00C880, 0x6023E200,
+0x000B4F26, 0x4F226EF6, 0x6062D64B, 0x8B038801,
+0x0009B256, 0x0009A003, 0xE640D248, 0xD6482260,
+0x4F26E200, 0x2622000B, 0xD6434F22, 0x88026062,
+0xB29F8B01, 0xD6420009, 0x4F26E200, 0x2622000B,
+0xD43ED53D, 0xE701E100, 0x000B2512, 0xD23B2470,
+0x000BE604, 0x4F222260, 0xD13BD43A, 0x0009410B,
+0xE1FDD53A, 0xD23A6650, 0xE7002619, 0x4F262560,
+0x2270000B, 0xD5374F22, 0x6152D237, 0x611DD737,
+0x64522512, 0x242BE6FF, 0xD4352542, 0x666DD22E,
+0x2762420B, 0xE1FBD52D, 0x27196750, 0x000B4F26,
+0x4F222570, 0xD128D42F, 0x0009410B, 0xE7F7D527,
+0x26796650, 0x000B4F26, 0xD5242560, 0x62509425,
+0x000B2249, 0xD5212520, 0x6250E4BF, 0x000B2249,
+0x4F222520, 0x8522D224, 0x2008600D, 0x88018911,
+0x88038944, 0x88058946, 0x88068948, 0x8808894E,
+0x88098954, 0x880A895A, 0x880B8960, 0xA06D8966,
+0xB06F0009, 0xA06A0009, 0xFF7F600C, 0x001E2148,
+0x001E1108, 0x001E1000, 0x00203A4C, 0x00203A4E,
+0x00203A6D, 0x00203A30, 0x001E103F, 0x001E105F,
+0x001E102F, 0x001E1090, 0x00203A54, 0x001E100B,
+0x00203A50, 0x00203B20, 0x002018C0, 0x001E1028,
+0x00203A6C, 0x001D4020, 0x98760000, 0x001C1000,
+0x00203B2C, 0x00203B3C, 0x00203A24, 0x0009B04C,
+0x600CA035, 0x0009B055, 0x600CA031, 0x6260D684,
+0x8B2B2228, 0x0009B061, 0x600CA029, 0x6260D680,
+0x8B232228, 0x0009B069, 0x600CA021, 0x6260D67C,
+0x8B1B2228, 0x0009B0C7, 0x600CA019, 0x6260D678,
+0x8B132228, 0x0009B0CD, 0x600CA011, 0x6260D674,
+0x8B0B2228, 0x0009B125, 0x600CA009, 0x6260D670,
+0x8B032228, 0x0009B13D, 0x600CA001, 0x4F26E000,
+0x0009000B, 0xD26CD16B, 0xD56C8412, 0x4000C90F,
+0xD76B012D, 0xE403D66B, 0xE20F611C, 0x2540E001,
+0x25202712, 0x2602000B, 0xE601D262, 0x30668523,
+0xE0008D05, 0xD663D260, 0xE0018122, 0x000B2602,
+0xD25C0009, 0x600D8523, 0x89052008, 0x8B0A8801,
+0x6060D65D, 0x2600CB01, 0xD457D65A, 0xE001E101,
+0x000B2612, 0x000B8142, 0xD152E000, 0x8513E501,
+0x640D4518, 0x66033453, 0xE0008D05, 0xD551D253,
+0x2260E001, 0x000B2502, 0x4F220009, 0x8513D149,
+0x6453650D, 0x62494419, 0x227D672E, 0x8801602C,
+0x88028909, 0x88038910, 0x8806891A, 0x88078935,
+0xA04C893B, 0xD5460009, 0x6652D746, 0x2762D446,
+0x622C6261, 0x2421A038, 0x2228625C, 0xD4438B3F,
+0x6642D540, 0x2562D440, 0x24018561, 0x6203A02C,
+0x2008605C, 0x88108907, 0x88208908, 0x88308909,
+0xA02C890A, 0xD23A0009, 0x6222A008, 0xA005D239,
+0xD2396222, 0x6222A002, 0x6262D638, 0xD432D531,
+0x66212522, 0xA00F626C, 0xD6352421, 0x6261D52D,
+0x622CD42D, 0xA0072562, 0xD6322421, 0x8561D529,
+0x2562D429, 0x62032401, 0x662D8515, 0x3617610D,
+0x65038F01, 0xB0CB2451, 0xA0010009, 0xE000E001,
+0x000B4F26, 0xD6190009, 0xD427E101, 0x65412610,
+0xD118D717, 0xE20F655D, 0x2752E001, 0x000B2620,
+0x2FE62102, 0xD20F4F22, 0x640C8523, 0x8B082448,
+0xD511D61D, 0x2621E200, 0x940F8451, 0xA0482049,
+0xDE0D8051, 0xC84060E0, 0xE2018D32, 0x89443427,
+0xD216D615, 0x2641420B, 0x0009A030, 0x0000FF7F,
+0x00203A6D, 0x00203A24, 0x00203A30, 0x001E1100,
+0x001E100C, 0x00203A50, 0x001E1000, 0x001E1001,
+0x00203A58, 0x00203A38, 0x00203A3C, 0x00203A40,
+0x00203A5C, 0x00203A60, 0x00203A64, 0x00203A68,
+0x00203E20, 0x00203E2A, 0x00203A4A, 0x002027F2,
+0x89123427, 0xD294D693, 0x2641420B, 0xCB8084E1,
+0x80E1B0F5, 0xD69160E0, 0x2E00CB04, 0xC93F6060,
+0xD68F2600, 0xA001E001, 0xE0002602, 0x000B4F26,
+0xD68C6EF6, 0xC8806060, 0xD2868919, 0x88016021,
+0xD2898B15, 0x8524E501, 0x89103056, 0xE203D187,
+0x2120D487, 0xE00B6541, 0x0656655D, 0xE40FD585,
+0x2140E702, 0xD77E2571, 0x000BE001, 0x000B2702,
+0x2FE6E000, 0xDE804F22, 0xC88084E1, 0xD57A892C,
+0x20088554, 0x61038F28, 0x8553D77C, 0x64036672,
+0x8566650C, 0x3520620C, 0xD6798B1E, 0x651CD774,
+0x2651644C, 0x60E02741, 0x8904C840, 0x420BD275,
+0xA0030009, 0xD2680009, 0x0009420B, 0x0009B09F,
+0xE201D167, 0x60E02122, 0xCB04D464, 0x60402E00,
+0x2400C93F, 0x6023A001, 0x4F26E000, 0x6EF6000B,
+0x2FB62FA6, 0x2FD62FC6, 0xDA622FE6, 0x66A1E240,
+0x3622DC5E, 0x62638900, 0x6ED36D2C, 0x4E2136D8,
+0x4E212A61, 0xDB61D460, 0xE700A00F, 0x770162B2,
+0x71026123, 0x66212B12, 0x71026213, 0x61212B12,
+0x651D666D, 0x356C4528, 0x627C2452, 0x8BED32E3,
+0xC90360D3, 0x8B108803, 0x617367B2, 0x2B127102,
+0x71026E13, 0x2B126571, 0x655D6DE1, 0x422862DD,
+0x325CE107, 0xA00C2C10, 0x88022422, 0xA0038B01,
+0x8801E203, 0xE2018B05, 0x66B22C20, 0x655D6561,
+0xE60F2452, 0x67A12C60, 0x8B052778, 0xDD38DC44,
+0xEB01EA00, 0x2DB22CA2, 0x6DF66EF6, 0x6BF66CF6,
+0x6AF6000B, 0x2FE62FD6, 0xE240DD36, 0x362266D1,
+0x62638900, 0x3678672C, 0x7703DE38, 0x47212D61,
+0x64E2D635, 0xA00E4721, 0x6562E100, 0x62537101,
+0x74012450, 0x24204219, 0x45297401, 0x74012450,
+0x24504519, 0x621C7401, 0x8BEE3273, 0x66E24200,
+0x420061D1, 0x2118362C, 0x2E628F06, 0xDD1CD728,
+0xE501E400, 0x2D522742, 0x000B6EF6, 0x2FD66DF6,
+0x4F222FE6, 0xED0AEE01, 0x64E3BC86, 0xBC8B64E3,
+0x62EC7E01, 0x8BF732D7, 0xBC8EEE01, 0x64E364E3,
+0x7E01BC93, 0x32D762EC, 0x4F268BF7, 0x000B6EF6,
+0xD1186DF6, 0xD418920D, 0x72122122, 0x2422D617,
+0xD7177204, 0x72202622, 0x2722D116, 0x000B7230,
+0x137A2122, 0x00203A4A, 0x002028FE, 0x001E1015,
+0x00203A50, 0x001E1001, 0x00203A24, 0x001E1100,
+0x00203A4E, 0x00203A3C, 0x001E1000, 0x00203A40,
+0x00203A4C, 0x002027F2, 0x001E100C, 0x00203A38,
+0x00203A54, 0x00203A58, 0x00203A5C, 0x00203A60,
+0x00203A64, 0x00203A68, 0x4F222FE6, 0xD6707FFC,
+0x88016060, 0xE2018951, 0x2620BFBB, 0xD56ED16D,
+0xDE6E6010, 0x64E36552, 0x7402C840, 0x8D22D16C,
+0xD26C7502, 0xE601D76C, 0xE7042722, 0x76016255,
+0x626C2421, 0x8FF93273, 0xD4637402, 0x6242E601,
+0x640D8528, 0x67494419, 0x275D657E, 0x81E4607C,
+0xE417D562, 0x67557601, 0x3243626C, 0x8FF92171,
+0xA0207102, 0xD25E0009, 0xE601D75B, 0xE7042722,
+0x76016255, 0x626C2421, 0x8FF93273, 0xD4527402,
+0x6242E601, 0x640D8528, 0x67494419, 0x275D657E,
+0x81E4607C, 0xE417D553, 0x67557601, 0x3243626C,
+0x8FF92171, 0x92897102, 0xD2462E21, 0x5E23D74E,
+0x64F22FE2, 0x604365F2, 0x2700C980, 0xC9606043,
+0x80716103, 0xC9036043, 0x80724519, 0x65F2605C,
+0x817266F2, 0x46194629, 0x606C4529, 0x4018645C,
+0x8173304C, 0x21185E23, 0x64F22FE2, 0x6E4C62F2,
+0x602C4219, 0x66F262F2, 0x46294018, 0x461930EC,
+0x42298174, 0x652C606C, 0x305C4018, 0x81758F07,
+0x0009BC97, 0x2228620C, 0xA00A8908, 0x60130009,
+0x8B038840, 0x0009B009, 0x0009A003, 0xE202D62F,
+0x7F042622, 0x000B4F26, 0x4F226EF6, 0x8552D52A,
+0x8830600D, 0x88318903, 0xA0348923, 0x85550009,
+0xD428D727, 0x85532701, 0x610DD627, 0x24124118,
+0x460BD426, 0xD7230009, 0xD226D425, 0x6572420B,
+0xE230D120, 0x42286712, 0x2729E620, 0x37604628,
+0xD6218B03, 0xA016E200, 0xD61F2622, 0xA012E202,
+0xD1182622, 0x6212E530, 0xE6204528, 0x46282259,
+0x89083260, 0xD41AD119, 0xE601D513, 0x2160450B,
+0x472BD718, 0x4F264F26, 0x0009000B, 0x0000060A,
+0x00203A6C, 0x001E1000, 0x00203A58, 0x00203E20,
+0x00203E2C, 0x00203DC4, 0x00203A40, 0x00203DF4,
+0x00203DF2, 0x00203DC6, 0x00203A24, 0x00203A50,
+0x00203A3C, 0x00203A38, 0x002018C0, 0x00203B48,
+0x00203B4C, 0x002018D0, 0x00203A54, 0x001E100B,
+0x00203B60, 0x00114004, 0x4F222FE6, 0x84E9DE86,
+0x2448640C, 0xB17B8901, 0xD2840009, 0x26686620,
+0x60E08902, 0x2E00C9BF, 0x000B4F26, 0x000B6EF6,
+0x2FE60009, 0xDE7E4F22, 0x60E0D67E, 0xCBC0D47E,
+0x62602E00, 0xC803602C, 0x40218904, 0x70014021,
+0x6603A002, 0x66034009, 0xD678616D, 0xE500A004,
+0x75016262, 0x74042422, 0x3213625D, 0xD2748BF8,
+0x0009420B, 0xC9BF84E2, 0x4F2680E2, 0x6EF6000B,
+0x2FE62FD6, 0x7FFC4F22, 0x6260D66E, 0x89402228,
+0xD565E100, 0x60502610, 0xCB40D46B, 0x2500440B,
+0x8D052008, 0x62E06E03, 0x7104612C, 0x2F11A006,
+0xD466D65E, 0xDD666760, 0x657C4D0B, 0xE23C6D1D,
+0x8B033D27, 0xD264D463, 0x0009420B, 0x4D214D21,
+0xA005D762, 0x66E6E400, 0x357C4508, 0x74012562,
+0x35D3654D, 0xD75E8BF7, 0x6E72E003, 0x81E14018,
+0x6E7260F1, 0x81E2700C, 0xD45A6172, 0xDD5A8113,
+0x65724D0B, 0xD64AD259, 0x2212E101, 0xC93F6060,
+0x7F042600, 0x6EF64F26, 0x6DF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xD2524F22, 0x6B436E73, 0x420B6C53,
+0x20086D63, 0x64038D1C, 0xE50ED13C, 0x32526210,
+0x60C38916, 0x804124B0, 0x814160D3, 0xA007E500,
+0x655D61BC, 0x00EC6053, 0x364C6653, 0x80647501,
+0x3213625D, 0xD6308BF5, 0xC9BF6060, 0x2600A008,
+0xD239D440, 0x6EF64F26, 0x6CF66DF6, 0x6BF6422B,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x2F962F86,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0xE1007FC4,
+0x6513ECFF, 0x6B136CCD, 0xDE34D733, 0xEDFF64F3,
+0xD833EA04, 0x6053655C, 0x027D4000, 0x32C0622D,
+0x66038D0D, 0x09ED6063, 0x2491027D, 0x24217402,
+0x698202ED, 0x3928622D, 0x74022892, 0x75017104,
+0x6063625C, 0x07D532A2, 0x0EB58FE4, 0x2448641C,
+0xE6808905, 0x67F3E5C5, 0xBF8F666C, 0x7F3C655C,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0xD11C68F6, 0x6012D21C, 0xCB20E405, 0x2102E500,
+0x000B2242, 0x00002252, 0x001E1017, 0x00203996,
+0x001E1015, 0x001E10BF, 0x00117800, 0x001E10FC,
+0x00200644, 0x0020399C, 0x00202A56, 0x00203B64,
+0x002018D0, 0x00203B80, 0x002018C0, 0x0011788C,
+0x00203998, 0x0020357C, 0x00201534, 0x001E2130,
+0x00202A18, 0x00203B88, 0x002039FC, 0x00203A04,
+0x00203DC0, 0x001C3500, 0x001D4004, 0xD564D163,
+0xE400D764, 0x2142E20F, 0x17411154, 0xD5622722,
+0x9669D762, 0x15412572, 0x96661562, 0xE6011565,
+0xD55F1165, 0x666CE6F8, 0x25422542, 0x25422542,
+0x25422542, 0x25622542, 0x7601E727, 0x67632572,
+0x25627797, 0xE7042572, 0x2572E248, 0xE2192522,
+0xE2702522, 0x25422542, 0x25422542, 0x25222542,
+0x2522E20C, 0x25422542, 0x25422542, 0x25422542,
+0x25422542, 0x000B154A, 0xE2081145, 0x0009422B,
+0x2FE62FD6, 0x7FFC4F22, 0xC8206043, 0x6E438D02,
+0x0009BE85, 0xC81060E3, 0xBE828901, 0x60E30009,
+0x8901C840, 0x0009BEA4, 0xC80160E3, 0xDD3D8938,
+0xC80260D0, 0x2F008D03, 0x460BD63B, 0x60F00009,
+0x8902C804, 0x460BD639, 0x62F00009, 0xC8806023,
+0x60D08902, 0x2D00C97F, 0xC8016023, 0xD6348906,
+0x0009460B, 0x0009A007, 0x51630601, 0x8902C808,
+0x460BD630, 0x60F00009, 0x8902C810, 0x420BD22E,
+0xD52E0009, 0x88026052, 0xD22D8B03, 0xA005E604,
+0x88012260, 0xD22A8B02, 0x2260E601, 0x2522E200,
+0xC88060E3, 0xD227892D, 0x60E36E20, 0x8902C880,
+0x420BD225, 0x60E30009, 0x8902C840, 0x420BD223,
+0x60E30009, 0x8902C802, 0x420BD221, 0x60E30009,
+0x890DC804, 0xDD20D11F, 0x0009410B, 0x0009BF11,
+0x0009BF4C, 0xD51ED41D, 0x2470E708, 0x25D2BF85,
+0xC80860E3, 0xD21B8905, 0x4F267F04, 0x422B6EF6,
+0x7F046DF6, 0x6EF64F26, 0x6DF6000B, 0x001C581C,
+0xA000A000, 0x001D0100, 0x001D4000, 0x00040021,
+0x001C589C, 0x001E1021, 0x00201A46, 0x00201A68,
+0x002020C8, 0x00201A80, 0x00201A8E, 0x00203A50,
+0x001E100B, 0x001E1028, 0x00201AFA, 0x00201B06,
+0x00201A96, 0x00201AB4, 0x12345678, 0x001E1000,
+0x0010F100, 0x00201AE2, 0x644CD6A7, 0x000B346C,
+0xD6A62450, 0x346C644C, 0x2450000B, 0x644CD6A4,
+0x000B346C, 0x625C2450, 0x4208616D, 0x42084119,
+0x42006019, 0x670E614C, 0xD49E321C, 0x4200207D,
+0x324CC90F, 0x2200000B, 0x4208625C, 0x42004208,
+0x324C644C, 0x4200D498, 0x000B324C, 0x2FE62260,
+0x614C4F12, 0x4100D493, 0x6710314C, 0xE29F666D,
+0x27294619, 0x6E536269, 0x672E6573, 0x4221227D,
+0x42214221, 0x7601662C, 0xE4014608, 0x34E84608,
+0x644C4600, 0x071A0467, 0x2150257B, 0x000B4F16,
+0x4F226EF6, 0xD2857FE8, 0x88016021, 0xD2848B7B,
+0x26686621, 0xD2838B77, 0x26686621, 0xE50F8B73,
+0xE401BFA2, 0xBFA4E501, 0xE586E400, 0xE400655C,
+0x2F50BFA4, 0xBFA1E401, 0xE602E506, 0x60634618,
+0x81F2E401, 0x6543BF9F, 0xE40185F2, 0xBFAB6543,
+0x85F26603, 0x6543E401, 0x6603BFB1, 0xE40265F0,
+0x6053756C, 0x80F8BF80, 0xBF82E402, 0x84F8E512,
+0x7090E402, 0x6503BF82, 0x4618E602, 0x81F66063,
+0xBF80E402, 0x85F6E500, 0x6603E402, 0xE500BF8C,
+0xE40285F6, 0xBF926603, 0xE5FEE500, 0xE010655C,
+0xBF61E403, 0xE5130F54, 0xE40EBF63, 0x05FCE010,
+0xBF63E40E, 0xE5007585, 0xBF64E403, 0xE500E640,
+0xBF71E403, 0xE500E640, 0xBF78E403, 0xE5FFE640,
+0xE014655C, 0xBF47E404, 0xE40F0F54, 0xE504BF49,
+0x05FCE014, 0xBF49E40F, 0xE5017584, 0xBF4AE640,
+0xE501E404, 0xBF57E640, 0xE501E404, 0xE404E640,
+0xAF5C7F18, 0x7F184F26, 0x000B4F26, 0x4F220009,
+0xD2427FF0, 0x88016021, 0xD2418B71, 0x26686621,
+0xD2408B6D, 0x26686621, 0xE50F8B69, 0xE401BF1C,
+0xBF1EE501, 0xE586E400, 0xE400655C, 0x2F50BF1E,
+0xBF1BE401, 0xE401E506, 0xBF1C6543, 0xE401E640,
+0xBF296543, 0xE401E640, 0xBF306543, 0x65F0E640,
+0x756CE402, 0xBEFF6053, 0xE40280F4, 0xE512BF01,
+0xE40284F4, 0xBF017090, 0xE6406503, 0xBF02E402,
+0xE640E500, 0xBF0FE402, 0xE640E500, 0xBF16E402,
+0xE5FEE500, 0x6053655C, 0xBEE5E403, 0xE51380F8,
+0xE40EBEE7, 0xE40E84F8, 0xBEE77085, 0xE5006503,
+0xBEE8E640, 0xE500E403, 0xBEF5E640, 0xE500E403,
+0xBEFCE640, 0xE5FFE403, 0x6053655C, 0xBECBE404,
+0xE40F80FC, 0xE504BECD, 0xE40F84FC, 0xBECD7083,
+0xE5016503, 0xBECEE640, 0xE501E404, 0xBEDBE640,
+0xE501E404, 0xE404E640, 0xAEE07F10, 0x7F104F26,
+0x000B4F26, 0x00000009, 0x001E102F, 0x001E1080,
+0x001E1090, 0x001E103F, 0x001E103E, 0x00203A4A,
+0x00203A4C, 0x00203A4E, 0xD21DD11C, 0x66206010,
+0x676C7001, 0x3700C90F, 0xE5008D13, 0x67106210,
+0x7701622C, 0x64232170, 0xD6166010, 0x44084408,
+0x3428C90F, 0x62602100, 0x7201D513, 0x44082620,
+0x000B354C, 0xD10F6053, 0x25586510, 0xE6008D13,
+0xD60DD40B, 0x655C6540, 0x47086753, 0x37584708,
+0x47086540, 0x24507501, 0x367C6040, 0x2400C90F,
+0x72FF6210, 0x000B2120, 0x00006063, 0x00203995,
+0x00203994, 0x00203996, 0x002035BC, 0x7FFC4F22,
+0xE680D1A8, 0x666C6212, 0xD2A72F22, 0x67F36563,
+0x420B7542, 0x7F04E404, 0x000B4F26, 0xE6800009,
+0xD2A1666C, 0xE7006563, 0x422B7540, 0xE6806473,
+0xD29D666C, 0xE7006563, 0x422B7543, 0x2F866473,
+0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6, 0x7FC04F22,
+0xDB97D296, 0x72012F22, 0xD1961F21, 0x66125211,
+0x8B013620, 0x0009A0F9, 0xC9036061, 0x8B018801,
+0x0009A0F3, 0xD290DC8F, 0x64C3420B, 0x6503D18F,
+0x60111F02, 0x8B048801, 0x420BD28D, 0xAFE464C3,
+0x54530009, 0x844CEE84, 0x890130E0, 0x0009A0C3,
+0x6610D188, 0x6023626C, 0x8B718801, 0x6210D186,
+0x89662228, 0xDA86D285, 0xE0036122, 0x64221112,
+0x4018D881, 0xDD83E500, 0x814167A3, 0x77042850,
+0x647266A2, 0x6ED3D580, 0x1F457E04, 0x65521F56,
+0x64E368D2, 0x1F8874F8, 0x684369E2, 0x1F637894,
+0x1F991F74, 0x62826142, 0xD779D978, 0x1F2BD679,
+0x67726292, 0x1F1A6062, 0x2602CB20, 0xD176E600,
+0xE5401F57, 0x1F7D1F2C, 0x76011F1E, 0x3253626D,
+0x51F38BFB, 0x52F555F4, 0x25222A12, 0x55F757F6,
+0x27525AF8, 0x5DF92DA2, 0x2ED251FB, 0xD56B5EFA,
+0x54FC24E2, 0x281257FD, 0xD160D869, 0x25722942,
+0x69126782, 0x1974D866, 0xDD666A12, 0x56FE60A1,
+0x2A01CB01, 0xDA646412, 0xE9012842, 0x4A0B2D42,
+0x52FE2692, 0xD661EE01, 0x22E24E18, 0x72016262,
+0x60B22622, 0xCB01D14F, 0x2B02E202, 0x2120A03F,
+0x8B3C2228, 0xE601D55A, 0x2160E700, 0xE01C2572,
+0xC801004C, 0xD8578B0C, 0x1F8FD257, 0xE6002822,
+0x7601E57D, 0x3253626C, 0x56FF8BFB, 0x2622D253,
+0xE2FE69B2, 0x2B922929, 0x0A4CE01E, 0xE01F65F2,
+0x014C25A0, 0x741057F1, 0xEA062710, 0xDD4CE600,
+0x8446DE4C, 0x2D007601, 0x696C6844, 0x2E8039A3,
+0x8FF67E01, 0xDE487D01, 0x2EA0EA94, 0xE1007E01,
+0x7E0F2E10, 0xD12FE205, 0x64102E20, 0x6023624C,
+0x89088801, 0x55F2D22A, 0x64C3420B, 0xEE01D132,
+0xAF1A4E18, 0x55F221E2, 0x8553D13C, 0x620D6612,
+0x89063262, 0xD63BD43A, 0xE801460B, 0xAF0CD73A,
+0xD91F2782, 0x64C3490B, 0xEE01D127, 0xDA38D437,
+0x4A0B4E18, 0xAF0021E2, 0x7F400009, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0x4F2268F6,
+0x85467FF4, 0x2F01E681, 0x666C8547, 0x854881F1,
+0x81F2D209, 0x67F38542, 0x854381F3, 0x81F4E40C,
+0x65636053, 0x420B81F5, 0x7F0C7540, 0x000B4F26,
+0x00000009, 0x001C3D9C, 0x002023FC, 0x0011779A,
+0x001C36F8, 0x002035B4, 0x002014A6, 0x00203A16,
+0x002014D0, 0x002039A5, 0x002039A4, 0x002039A0,
+0x001C3B9C, 0x001C3704, 0x001C3D98, 0x001C3BB4,
+0x001C5960, 0x001C3500, 0x001C3D30, 0x001C8960,
+0x0020358C, 0x001C3D00, 0x00201610, 0x00117730,
+0x002039A8, 0x001C582C, 0x2000A000, 0x0000A000,
+0x0011778C, 0x00117792, 0x00117788, 0x0020397C,
+0x0020357C, 0x00201534, 0x001E2130, 0x00203DA0,
+0x002018C0, 0x2F962F86, 0x2FB62FA6, 0x2FD62FC6,
+0x4F222FE6, 0xD19B7FEC, 0x2F12E000, 0x6103D49A,
+0x1F4281F2, 0xDD9ADA99, 0xD69A6813, 0xE0014808,
+0x460BDE99, 0x38EC4800, 0x65A21F03, 0x352052A1,
+0xA23E8B01, 0x60510009, 0x8801C903, 0xA2388B01,
+0x52530009, 0x32E0DE91, 0xD9918B10, 0x64A3490B,
+0x4B0BDB90, 0xDE906403, 0xD791D690, 0xEC01D591,
+0x2E02E100, 0x271026C0, 0x2502AFDF, 0xC8018551,
+0xA1578B01, 0x62510009, 0x4200622D, 0x5E53366A,
+0x85E2226D, 0xC903642C, 0x85E36603, 0x6053650D,
+0x40214021, 0x4500C93F, 0x322A6703, 0x6053252D,
+0xC901D17F, 0x60106C03, 0x8801D97F, 0xDB7F8B05,
+0x2120E200, 0xCB0160B2, 0xD17D2B02, 0x88016011,
+0x65A28B0A, 0x8D042448, 0x9B9E6251, 0xA00322B9,
+0x919B2521, 0x2521221B, 0x37B3EB10, 0x2448895E,
+0xD4738B07, 0x22286241, 0x60638903, 0xA05781F8,
+0xD5706473, 0x46084608, 0x85E26273, 0x46006B50,
+0x362C4200, 0x2BB8C910, 0x8F1F6463, 0x26686603,
+0xD2698911, 0x062D6043, 0x4119616D, 0x6B0E6019,
+0x81F820BD, 0x880160C3, 0x646C8F2C, 0x880F6073,
+0xA0278B1B, 0xD2610009, 0x052D6043, 0x4119615D,
+0x670E6019, 0x645C207D, 0x81F8A01C, 0x890F2668,
+0x6043D25B, 0x6B5D052D, 0x60B94B19, 0x201D610E,
+0x60C381F8, 0x8F0D8801, 0x6473645C, 0xEC00A00A,
+0x6043D254, 0x625D052D, 0x60294219, 0x207D670E,
+0x81F8645C, 0x880285F8, 0x85E1890A, 0x8D07C820,
+0xE6DC6203, 0x60232269, 0x81E1A002, 0x644CE4FF,
+0x6210D149, 0x89012228, 0x644CE4FF, 0x654DEBFF,
+0x35B06BBC, 0xDB368B2B, 0x64A34B0B, 0x410BD135,
+0x54036403, 0x85446E03, 0xC948DB40, 0xDC408808,
+0xBEAC8B01, 0x64B3E502, 0x65E34C0B, 0xDB3DEC01,
+0xD13D2DC2, 0x621260B2, 0x72017001, 0x21228805,
+0x2B028F08, 0x666CE680, 0x6563D238, 0x7549E700,
+0x6473420B, 0xA030D436, 0x7FFF0009, 0x85E28000,
+0x20B9EBFC, 0x610381E2, 0x942A85E3, 0x62032049,
+0x450885F8, 0x81E2201B, 0xC90160C3, 0x40084018,
+0x40084008, 0x4000225B, 0x6023220B, 0x85E481E3,
+0x4118E108, 0x81E4201B, 0xE40262A2, 0x20B98521,
+0x67A28121, 0xCB016071, 0x85F82701, 0x89033042,
+0xECE785E2, 0x81E220C9, 0x490BD41E, 0xA03B0009,
+0x7E030009, 0x001C3D30, 0x00203DAC, 0x0020358C,
+0x001E212C, 0x00203470, 0x001C3D00, 0x00117780,
+0x002014A6, 0x00201670, 0x0011770C, 0x002039A4,
+0x002039A5, 0x002039A0, 0x002018C0, 0x001C36F8,
+0x00203A1A, 0x00203DBC, 0x00203BA0, 0x00203C20,
+0x00203CA0, 0x00203D20, 0x00203990, 0x00203584,
+0x002014D0, 0x00203A1C, 0x00203A20, 0x002023FC,
+0x00203DA4, 0x00203DA8, 0x602262F2, 0x40094019,
+0xC90F4009, 0x8B0B880A, 0x60E2DE8C, 0x40094019,
+0xC90F4009, 0x8B038808, 0xCB0160A2, 0x2802A006,
+0x65E2DE87, 0x2E527501, 0x286266A2, 0x52F366F2,
+0x2622AE83, 0xD2838551, 0xDE83C802, 0xA0958B01,
+0x420B0009, 0x4E0B64A3, 0x5E036403, 0x85E46503,
+0x4918E908, 0xD77D209B, 0xE04C81E4, 0xDC7C0B7E,
+0x7B01D97C, 0x61C207B6, 0x71016690, 0x8D062668,
+0xD4792C12, 0x420BD279, 0xA070EB01, 0x62512DB2,
+0x4B18EB0F, 0x22B9E102, 0x32104118, 0x85518B0F,
+0x2029E2FC, 0x60518151, 0xCB0172E0, 0x85E12501,
+0x202994A3, 0x85E481E1, 0xA0522049, 0x675181E4,
+0x4719677D, 0x667E6779, 0x7701276D, 0x6903607C,
+0x88014918, 0x25918F3E, 0x6B12D161, 0x21B27B01,
+0x660D85E3, 0x40216063, 0xC93F4021, 0x6C034600,
+0x262D322A, 0xC8016063, 0xDB5ED15D, 0x967D8901,
+0xE6002C6B, 0x666C67CD, 0x40006063, 0x622D021D,
+0x8D0E3270, 0x60436403, 0xE9FF021D, 0x8B013290,
+0x01C5A007, 0x626C7601, 0x3292E904, 0x646C8BEB,
+0x60434400, 0xD15004BD, 0x0B457401, 0x669D6911,
+0x89073670, 0x602D6211, 0x890388FF, 0xE201DB4B,
+0x2B2021C1, 0xECFC8551, 0x815120C9, 0xCB016051,
+0xDC472501, 0x64A34C0B, 0x51F366F2, 0x85EF2612,
+0x54F2D244, 0x650D420B, 0x0009ADE7, 0xE500DC42,
+0x420B2C52, 0x4E0B64A3, 0x54036403, 0x85446E03,
+0x6703E908, 0x65034918, 0x27998541, 0xDB323790,
+0x8F0BD932, 0x6013610D, 0x8B07C820, 0xC9486053,
+0x8B038808, 0xE501BD4B, 0x0009A005, 0x2128D233,
+0xBD448901, 0x64B3E500, 0x490B65E3, 0xADBCEC01,
+0x85F22DC2, 0x7001EE04, 0x31E7610D, 0x8D0281F2,
+0xADA97A08, 0x7F140009, 0x6EF64F26, 0x6CF66DF6,
+0x6AF66BF6, 0x000B69F6, 0xF7FF68F6, 0x2FE68000,
+0xD2234F22, 0x60E36E22, 0x8D02C840, 0xBBE522E2,
+0xE2400009, 0x2E284218, 0xBBF08901, 0x60E30009,
+0x8905C810, 0xD21CD41B, 0x0009420B, 0x0009BBEF,
+0xC80560E3, 0xBD6D8901, 0x60E30009, 0x8902C802,
+0xABEC4F26, 0x4F266EF6, 0x6EF6000B, 0x001C3D3C,
+0x00117760, 0x002014A6, 0x00201670, 0x0020351C,
+0x00203DC0, 0x00203990, 0x00203584, 0x002014D0,
+0x002039FC, 0x00203A04, 0x002039F8, 0x002039FA,
+0x00201534, 0x002018D0, 0x00203A1C, 0x00008000,
+0x001C3510, 0x00203DB4, 0x002018C0, 0x89014F22,
+0x611B600B, 0x611BB00A, 0x000B4F26, 0x600B600B,
+0x611BA004, 0x8DF12107, 0x8BF84011, 0x620D2F26,
+0x8F3E3020, 0x40180019, 0x8B0B3016, 0x31043104,
+0x31043104, 0x31043104, 0x31043104, 0x412462F6,
+0x601C000B, 0x41296219, 0x20084018, 0x31048926,
+0x31043104, 0x31043104, 0x31043104, 0x31043104,
+0x31043104, 0x31043104, 0x31043104, 0x61193104,
+0x3204221D, 0x32043204, 0x32043204, 0x32043204,
+0x32043204, 0x32043204, 0x32043204, 0x32043204,
+0x212D3204, 0x601962F6, 0x4024000B, 0x000BE000,
+0x621362F6, 0x41294228, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x602D4224, 0x62F6000B,
+0x080A0C0E, 0x00020406, 0x1A1C1E20, 0x12141618,
+0x2E303234, 0x26282A2C, 0x3A3C3E40, 0x6C625648,
+0x41112F26, 0xE2208F18, 0x890B3123, 0x321CD204,
+0xD1026220, 0x412B312C, 0x00090009, 0x0020349A,
+0x00203450, 0x000BE000, 0x400062F6, 0x40004000,
+0x40004000, 0x40004000, 0x62F6000B, 0x40004000,
+0x40004000, 0x40004000, 0x40184000, 0x62F6000B,
+0x40004000, 0x40004000, 0x40004000, 0x40284000,
+0x62F6000B, 0x40004000, 0x40184000, 0x000B4028,
+0xC90F62F6, 0x40054005, 0x40054005, 0x62F6000B,
+0x4005C907, 0x40054005, 0x62F6000B, 0x4005C903,
+0x000B4005, 0xC90162F6, 0x000B4005, 0x000062F6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x42707372,
+0x3D206675, 0x554E203D, 0x202C4C4C, 0x6E49677A,
+0x4E497274, 0x6D754E51, 0x0000003D, 0x61766E49,
+0x2064696C, 0x72657375, 0x20726F20, 0x2079656B,
+0x00214449, 0x6E6B6E55, 0x206E776F, 0x6D6D6F63,
+0x3D646E61, 0x00000000, 0x203A3051, 0x00000020,
+0x203A3151, 0x00000020, 0x203A3251, 0x00000020,
+0x203A3351, 0x00000020, 0x203A3451, 0x00000020,
+0x2B434741, 0x73696F4E, 0x61432065, 0x7262696C,
+0x6F697461, 0x6166206E, 0x6F206C69, 0x6974206E,
+0x0D0A656D, 0x00000000, 0x00000072, 0x00205220,
+0x62735576, 0x7473725F, 0x00000A0D, 0x62735576,
+0x7375735F, 0x646E6570, 0x00000A0D, 0x62735576,
+0x7365725F, 0x000A0D6D, 0x00000044, 0x44387570,
+0x72637365, 0x6F747069, 0x3D584572, 0x00000000,
+0x00000047, 0x72746E49, 0x6D652051, 0x2C797470,
+0x49677A20, 0x4972746E, 0x754E514E, 0x00003D6D,
+0x654C7245, 0x0000006E, 0x20746F4E, 0x756F6E65,
+0x49206867, 0x4220514E, 0x0A0D6675, 0x00000000,
+0x000000FF, 0x00020001, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00020003, 0x01090108, 0x0002010A,
+0x02000003, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x000000FF, 0x00020001, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00020003, 0x01090108, 0x0002010A,
+0x00030003, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00FF010F, 0x01090108, 0x010B010A,
+0x0200010F, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00FF010F, 0x01090108, 0x010B010A,
+0x010F010F, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00205220, 0x00000046, 0x00000059, 0x73204142,
+0x003D7165, 0x49544120, 0x0000204D, 0x00000000,
+0x00000000, 0x002E0209, 0x80000101, 0x000409FA,
+0x00FF0400, 0x05070000, 0x02000201, 0x82050700,
+0x00020002, 0x03830507, 0x07010040, 0x40030405,
+0x02090100, 0x0101002E, 0x09FA8000, 0x04000004,
+0x000000FF, 0x02010507, 0x07000040, 0x40028205,
+0x05070000, 0x00400383, 0x04050701, 0x00004002,
+0x00000000, 0x00000000, 0x07090000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, };
+
+const u32_t zcP2FwImageSize=15964;
diff --git a/drivers/staging/otus/hal/hpfwbu.c b/drivers/staging/otus/hal/hpfwbu.c
new file mode 100644
index 000000000000..f60f57ed887a
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwbu.c
@@ -0,0 +1,5269 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+
+const u32_t zcFwBufImage[] = {
+0x3A4BCF18, 0xF44C076E, 0xF59452EA, 0x451BA755,
+0x140AC87A, 0xC07EE942, 0x3EF978AB, 0xF5B03DC6,
+0xB70080F0, 0xA89064EA, 0x54E2C1D6, 0xEB047DF4,
+0x1798390C, 0x00350624, 0x35B3ECF0, 0x59F2FABF,
+0xAF9D248E, 0xF9BDB9F0, 0xD05C8B47, 0xC08B5A16,
+0x990093C7, 0xD335A160, 0x1C04942C, 0xBF6E7A88,
+0xFD232B0F, 0x5C224387, 0xBF1E156C, 0xF24F2A27,
+0xFF56421D, 0xB213037C, 0x2BA67BA0, 0x4950CF8A,
+0x05F00F25, 0xA5E82085, 0x74168A0C, 0x2F2AB30B,
+0xC80C57EE, 0xB6BDF570, 0x89BC5A99, 0x7F3B5A67,
+0xF6C943B8, 0x0C9C9201, 0xE8383747, 0x0C9A72D6,
+0xE0520704, 0xA66D7F30, 0xE444A434, 0xE0C94AB7,
+0x8DD7751C, 0x1A659464, 0x6C9ABA4F, 0x792F2D2D,
+0x5936F66B, 0x061E580E, 0x59903F6C, 0x1FBFB8A0,
+0xCC822EFE, 0x4B030CAF, 0xB62457C9, 0x27E9BF15,
+0xB113A487, 0xFA0FC915, 0x447B184A, 0x5330CD51,
+0x00BCC622, 0xF30DE149, 0xFF718E1C, 0x7B5D2861,
+0xDBCA573E, 0xFB0D7BF9, 0xE1CFBAAC, 0xF99D4583,
+0x4BA7498A, 0x7CAEA7EB, 0xBA958E32, 0x36C530FF,
+0x8F88CA99, 0xF93CABC2, 0x8E47EF11, 0xFB0EED6F,
+0x5B3668A1, 0x9D63ADDE, 0xA0EEAB8C, 0x084915F1,
+0xFACAAA27, 0x209638FE, 0x1CED9EFF, 0xEEBD2335,
+0x38C6F424, 0x2D1F3D7E, 0x976E8106, 0xBE087AD2,
+0x32194845, 0x756066DB, 0xC70E3165, 0xC568DCB1,
+0x3212E4E1, 0xB5D991AD, 0x07C3CEF8, 0xDB4ABB38,
+0x1574C232, 0xF8C792BC, 0x14E62DBE, 0x5A48E7DC,
+0xEFDC5407, 0xC45B4017, 0x3B814E89, 0xF0936466,
+0x89491B2B, 0x9A359A41, 0x82287675, 0xA0F338D3,
+0x523FDD3C, 0x4E40B795, 0x458ADAA4, 0xED812957,
+0x7ADC73BC, 0x6FD7DB78, 0x2740FC04, 0x6392AEA3,
+0x185ABCEA, 0x6B50ABC3, 0x3681F07F, 0xC840F8CE,
+0x5733E7EC, 0x0805FA71, 0x0B34530A, 0x8CB3D033,
+0x81451551, 0x53B0B4EC, 0x908646D0, 0x10A3E642,
+0xF358DC34, 0xC1FA570C, 0x2B1284B0, 0x592322BB,
+0x9D587783, 0xE7D77988, 0xE1BE5D7B, 0x44B93E23,
+0xF8BE94A2, 0x506DC723, 0x6E0A7D09, 0x3FB1046F,
+0xDB3A166F, 0x9CB7D6A0, 0xE278DE6D, 0x88459334,
+0xB52BA3C9, 0x284740A2, 0x04D30792, 0x944D79CA,
+0x1D050EA9, 0xA404DB1B, 0x99526023, 0xBACE24E7,
+0xB9F20704, 0x284E6432, 0x47A593D1, 0x95F8DFCB,
+0x220C9167, 0x8FAABBBC, 0x93D34E8C, 0xCE077138,
+0x4FC18081, 0xE76DD7E5, 0x67465F6C, 0x7A479D77,
+0x74D61F82, 0x00559214, 0x2F66E42E, 0x8742A96B,
+0x62063950, 0xA2DBFAE5, 0x368B966F, 0xAB5FCCE1,
+0xCB4023B1, 0x1E7AF542, 0x05953E30, 0x8CA51CFC,
+0x2216547D, 0x29D562D4, 0xE9C9F8EE, 0xA90505C9,
+0x088D0EEB, 0xD7A290FA, 0x95E5B567, 0x53FAD3C0,
+0xB89FC625, 0x69A7519B, 0x3687C7EF, 0x7188CB55,
+0xCE5DB97E, 0xA260574A, 0xD453D173, 0x145D970B,
+0x12112CC6, 0x399839E0, 0x29C55BEB, 0xE467C71F,
+0x10B3C9D4, 0x8F1C9662, 0xF207A826, 0xE0245600,
+0x688B1812, 0x5A483031, 0x7048380A, 0x78E3D5BB,
+0x1951533D, 0x8FA5D8E3, 0xC5BE500D, 0x71DB5B2B,
+0xA17AA000, 0x408C9BE8, 0x161E12F5, 0xB1C38C45,
+0x22A88F05, 0xDE3F4405, 0x5078ADBB, 0xCE1BF1A6,
+0xB7A75B04, 0x6B8364E8, 0x0CE32E3E, 0x9BF65504,
+0x28C18157, 0x78359AC6, 0x617BF202, 0x1E76FA09,
+0x0F8E61A8, 0x6D02F0D5, 0x80356459, 0x79CEFAE7,
+0x7D00F155, 0x5C1C0128, 0xC75CA073, 0x32816090,
+0x9FF78DFC, 0x848D269C, 0xF811B314, 0xA86920FC,
+0x6F885D01, 0xACFE6525, 0xC726074D, 0xFED68599,
+0xF1D5C76A, 0x8799E5F5, 0xF85F5171, 0xD8DE2D3B,
+0xE7DD8E75, 0x43F8614A, 0x0684FC8D, 0x9683B8C8,
+0x74BE786B, 0x2514762D, 0x7D866682, 0xE711FE1F,
+0x0DE9E273, 0x12F53167, 0x4FA3A7FE, 0x2A00EB61,
+0xB3984A28, 0x4319F2B0, 0x42BA0CA2, 0x848771B6,
+0x995E945E, 0xD41115F5, 0x43D9834B, 0x54EEDC36,
+0x5C3C5407, 0x671B540E, 0xDCF18948, 0x150ED973,
+0x2D4922DE, 0xF93CA17D, 0xB24A76E5, 0xD1C01C22,
+0xF2963DD6, 0x3B860066, 0x08EF0EA4, 0x609B60CC,
+0xE2E901FA, 0x25BE9B93, 0xDF96D9BC, 0x86D415DF,
+0x75CCF6BB, 0x882D54B2, 0x7976E9AF, 0x88A0B178,
+0x5ADE5A55, 0x8A8C0112, 0xD896755A, 0xCB6789B3,
+0x8B63AE2F, 0x2545036C, 0xE4655B94, 0x20959977,
+0x29DFB4D1, 0xCDAAEBF4, 0x1C07EC05, 0x5A6F607D,
+0x88A9B31D, 0x118C74D2, 0x000BB065, 0x75C46712,
+0xEF1A58BD, 0x50ECA262, 0xCCE393B9, 0x6EDB92E8,
+0x700EF517, 0xBF6CF4AD, 0x57456DC0, 0xF629517C,
+0x40331F8B, 0xC10A454D, 0x6CCB02CF, 0x9BF11B1C,
+0xE0871437, 0x23623585, 0xF519F09C, 0x4DB2AFC8,
+0x88FCBD7B, 0xB512FE8D, 0xDE445894, 0x078AD03C,
+0x44375FB0, 0x0BABEDB1, 0x40D5E8E1, 0x13F20A86,
+0xF1406303, 0x7205C322, 0x3FC43779, 0x7A60D510,
+0x14469E04, 0xF4E77873, 0x2EAD7ECE, 0xA135D6EA,
+0x3F4C4B30, 0x21488077, 0x69F64F1C, 0xEEF4876E,
+0x63610C0B, 0xB7B24C5C, 0x324A76FE, 0x0CF651D3,
+0x9460F0B1, 0x81A83230, 0x0839CFF9, 0x70722F04,
+0xC278FB3B, 0x5DD1BDA4, 0x1E4B3DBA, 0xAE161A93,
+0x9E1033C3, 0xD938FCEC, 0xDA2B2F93, 0x28CD82EA,
+0x14AD1FAF, 0xE4EC9CB8, 0xE770AFDF, 0xEFB12898,
+0x500BE181, 0x602625C5, 0xF160631B, 0x78D3643F,
+0x4E13ED37, 0x647BB223, 0xCF18D75C, 0xF477F94C,
+0x786ECB89, 0xB3ED21F8, 0x1BEF3916, 0x240FB35A,
+0x5C69B7D9, 0x8E96290A, 0xD40DC98C, 0xD1370291,
+0x5870021E, 0x3F7CF23F, 0xFD4A6ADA, 0x36482457,
+0x926600AF, 0xDC8618BC, 0x67D3779F, 0x3422830C,
+0x87A41FBA, 0xCA0AFF53, 0x63BC45F3, 0x520BBBAE,
+0xEDE2E031, 0xB6FA9450, 0x258CA712, 0xD709C4E4,
+0x617709B2, 0xAACE0B41, 0x363DBF55, 0x701D6583,
+0x39F3C885, 0x7CD6297B, 0x078FE13B, 0xA398DABF,
+0xDB97C514, 0x039102E3, 0x5CA545AF, 0x9298BA18,
+0xD18DAF86, 0x3D70EEA2, 0x5266AD68, 0xB04945B5,
+0x402DDA5B, 0x01DC6CD1, 0x93AC5053, 0x08DF9EA9,
+0x485EBE97, 0xA5D05853, 0x6CBEE910, 0xD485F4E2,
+0x8F201D07, 0xEFC384A3, 0x7272AFBE, 0xC0B41FD7,
+0x8E54A971, 0xA7F9E0F7, 0xC21700B4, 0xC24A4ED0,
+0x5419EACF, 0xBC2D8FB1, 0x2C5B5AFF, 0x0345274C,
+0xC41DF47A, 0x37658AFF, 0x24CF3BE7, 0xA3086248,
+0xF82B5928, 0xB49A9B04, 0xD4105AEF, 0x444EBE8D,
+0x348368DF, 0xDC77A7A0, 0x68D37E0D, 0xD2EB54EE,
+0xDDAC8C33, 0xE5C93C79, 0xE4706ABF, 0x17536EFD,
+0x6C2B2B16, 0x038AA806, 0xDAD42458, 0xAE1D76A1,
+0xCC8DE95C, 0x1BA20647, 0x0521068C, 0x306FBE44,
+0x4E29D881, 0xD2A14D53, 0xA155853E, 0x44500CC4,
+0xFC4466B7, 0x5AACD51D, 0x506D3A73, 0x3F61E0FE,
+0x58F11F9D, 0xC92A2CAD, 0xD9A4F86B, 0x1FA747B1,
+0x77DEC5D2, 0xDFAB369A, 0xD471EA01, 0x724502DA,
+0x618CE21A, 0x52388BEB, 0x2E8A4CC5, 0x58332211,
+0x3FCC46E1, 0x501210E2, 0xE9D51D1A, 0x37237B55,
+0x8CE3E2F1, 0x6B2E98CC, 0xB56A11E5, 0x8819036B,
+0xA6AA2F27, 0xB0124A0E, 0x92F17364, 0xD4A89238,
+0x0507E337, 0x8ED95DEC, 0x9C014BA8, 0xBA5B11C6,
+0x9C15D38C, 0x52596C98, 0x9330DD3D, 0xD6147570,
+0x21701F1B, 0x5A2385F1, 0xE2F38C6C, 0xB3E94698,
+0x2F9C63FA, 0x7E0234D8, 0x4CDD3288, 0xE1969B5F,
+0x853B3C1D, 0xF61465A7, 0xF281C419, 0x46C5F072,
+0x9F1722DD, 0x64F2A994, 0x86AEE8A8, 0x55895E17,
+0x6047D1AC, 0x3375A934, 0x336BEACA, 0x90791174,
+0x4DACC4D2, 0x24253860, 0x2A7876FB, 0x9DBDF98D,
+0xD5BCE182, 0x67EB5F70, 0xCC06BA38, 0xE8F78715,
+0xFEB0EB44, 0xE9776E03, 0x892A0898, 0x7A070650,
+0x6D04DDC4, 0x99A5B7EA, 0x3B416BB6, 0xDADCE834,
+0xB3B03278, 0xDB73B70E, 0xB0F0224E, 0x538A4AF9,
+0xD25D6A37, 0x8F627FB0, 0x11ED9387, 0xB8C88457,
+0x0CF320CA, 0xA20E62A2, 0x1DACDD4A, 0xAB84575D,
+0x740DAF75, 0xAB9DB955, 0xFF787314, 0xA680B8E3,
+0xC976D38E, 0x1FD38F4D, 0x0AEB6633, 0xB69A03DF,
+0xB6CA8610, 0x106354C2, 0xC37D48C8, 0x3E5EED54,
+0x534CC9BA, 0xE37DFFAD, 0x9F69EB05, 0xF67217EE,
+0x50180B3D, 0xCC61C127, 0xC3598D73, 0xE5C00F01,
+0xFFE9B111, 0x5E23EA2F, 0xF6C45DCE, 0x44585E39,
+0xB02C6004, 0x37233902, 0x4F374C0D, 0x34288898,
+0xE274937D, 0xC81D472C, 0x17A43151, 0x2638F7D3,
+0x5304E5B5, 0xD5CE5EDE, 0x357FA7B3, 0xFBE27986,
+0x64E65D1F, 0xC28D1237, 0xA73D9AB3, 0x124CA6C8,
+0x770D7415, 0x5788C32C, 0x18DEFC00, 0xB3B2B06A,
+0x55CC86A0, 0x8D929309, 0x84AB381A, 0x9DEFE8DD,
+0x26C742C8, 0x952BAC34, 0x0A3B140F, 0x82A9304B,
+0x52CEC9F4, 0x47DF4D08, 0x15A116D8, 0x7B890B18,
+0xC87BEF1A, 0xB59601B6, 0xD37BFB28, 0x5D9F564D,
+0xFB002F8D, 0xE7602E57, 0xE429C852, 0x9C0A8C75,
+0xE02611DC, 0x8A1C9861, 0x7495D6DE, 0xCA059710,
+0xAE5969B8, 0xE5B2CBDC, 0xA49F6EC1, 0x85D2A553,
+0xE4719B0F, 0x40F68BBC, 0x092E24B5, 0x7B132678,
+0xD70C17E1, 0x309E6AA1, 0xE009657F, 0xA7238C7A,
+0xE0575D78, 0x1D6980E7, 0xEFCDD368, 0x19F08D93,
+0xFAC03B85, 0x51BADA8F, 0x037DF839, 0x8F4D29F4,
+0x1DC8A913, 0x50C55402, 0xDEE578F0, 0x2BA1C091,
+0x9ACA567E, 0xA8FFECFA, 0xA3C05D12, 0xF18C6283,
+0xEAAE6662, 0xB4DC6A79, 0xCEC5E782, 0x93A2E384,
+0x8F8A5E6F, 0xCA8379D5, 0x81BCD49E, 0x5FCE174B,
+0xD1543A5B, 0x845D635F, 0xD53125B9, 0x3B2121AE,
+0xF8ECDD01, 0xF84D2D11, 0x6579BC21, 0x5C2DC220,
+0x9EC1A688, 0x1148D831, 0x6C087799, 0x58944357,
+0x56F79FC6, 0x6B689B55, 0x740B5FD1, 0x9F7BFB5F,
+0x6B2F3E2D, 0x10E09273, 0x2E9E3213, 0xF3436AA0,
+0x14A9F681, 0x9087D3CE, 0x68D0430B, 0x9FAFE3EF,
+0xD45B8C61, 0xB982724A, 0x04448D7F, 0x8712E47A,
+0x2C188D15, 0x9C3F06CC, 0x6343B130, 0x56C6765C,
+0xF657BC9A, 0x15F1E973, 0x47E71181, 0x8639F5D7,
+0xC1F3FDD5, 0xDC522441, 0x56BB2908, 0xAA48AEC6,
+0xEC04087A, 0x8D375875, 0xE2941F88, 0xED31CC72,
+0x09BD8794, 0x4C81D5C1, 0x1CC96D9C, 0x98A89022,
+0xAA362C57, 0x924D583D, 0x270430E6, 0x0FD4040A,
+0xAF561155, 0x38DCD1CF, 0xE861D2AC, 0x24A2EF3C,
+0x2B7E3868, 0x13DA6C12, 0x69202EB6, 0x4A5FEC66,
+0x185417A9, 0x3C92EFF4, 0x949842E6, 0x02115D93,
+0xAD1726FF, 0x4E093D7D, 0xC3E41B9C, 0x27BBC1C1,
+0x4FFA49C7, 0x6C63D24C, 0x84255444, 0x282C3BA2,
+0x3D679D86, 0x03B410B1, 0x64DB454C, 0x535499D4,
+0x25B421A1, 0x7E68C8FE, 0x0477E3B9, 0xCEFB087D,
+0x9E59B89C, 0xBB787559, 0x1A550EE4, 0x078B48AB,
+0x73A865FE, 0xD7227471, 0x3A864049, 0xE5EE3A1D,
+0x201BC19D, 0xEB8DAE2C, 0x0E2AB31D, 0xCDAC2D79,
+0xDAAB08B1, 0x63ECD4F2, 0xC00F9716, 0xD415C6BB,
+0x8C20C39F, 0xDED8F5A2, 0x1D6A4190, 0x3D319167,
+0x56B3A26B, 0x0547BF52, 0xA056924F, 0x4DAA539A,
+0x557241D1, 0x42C9124E, 0x18723323, 0x6AD6E7EC,
+0x8E039337, 0xF6FDDD65, 0x5F3525F9, 0xC0AD9704,
+0x810EF049, 0xCE022EE0, 0x41CE7E52, 0x8E172A44,
+0x648808E2, 0xC7FF6896, 0x2AD0985C, 0x304B9631,
+0xD21EA39B, 0x279F5089, 0xCDB5C390, 0x21716A40,
+0x5E34B278, 0x39475D72, 0xBA4F4DB1, 0x8B25818F,
+0xE6E466F4, 0xC4A09DF8, 0x59F18AC7, 0x887AB5FE,
+0xEEA4BA42, 0x17371DA8, 0xA82193D1, 0x6DC30EF7,
+0xDEB9D349, 0x2B3271D4, 0x1FE83836, 0xEC755A29,
+0x05F07FCD, 0xC331D3AE, 0xC6208B76, 0x497FF280,
+0x4C579C5A, 0x22B71F94, 0x30FD620B, 0x31B71AE3,
+0xDF7D1A41, 0xF041ACA5, 0x9533261B, 0x3262D291,
+0x060E9672, 0x7D191A55, 0x6D0F0945, 0xF8C7777C,
+0x1C173808, 0x78308E77, 0xC1EEAD3B, 0x059CCD9D,
+0xA8FDBE19, 0xE47630FA, 0x88A49DE5, 0x03347DAB,
+0x4F31F969, 0xF9C62B12, 0x93AB126F, 0x8A7A3BFB,
+0x82591545, 0x2A1A2131, 0x1DEBB134, 0x449E28DD,
+0xFA7E0248, 0xC1E3A5BC, 0x1747E097, 0x4C69AA5C,
+0x1FD71B4B, 0xAC64CA6C, 0x5545F9F9, 0x5E5886F2,
+0x243DBA6C, 0x495BE163, 0x4ECF5A6C, 0x430C9019,
+0x89A980FA, 0x528945AE, 0x00CE6936, 0x9F9A73B2,
+0x9E59DC6B, 0xD57740CD, 0x0E0CB735, 0xB1202BE3,
+0xAA26C2A9, 0x267A77A6, 0x3FA12CF0, 0x4587C0AF,
+0x354ED831, 0xFFD8BD8E, 0x56CC0F26, 0x75717AE3,
+0x51B10674, 0x3E33EC26, 0x26CE80DB, 0x5C4A9140,
+0x017F6C2F, 0xF9038D9A, 0x0A22C29F, 0xBA1F7C8D,
+0x125CC934, 0x6CF66BFF, 0x48C13DCD, 0x63FC3D81,
+0x258C181D, 0x1A4C3DDD, 0x2E24BECC, 0x7C86A9ED,
+0x5BD1989C, 0x57CE595C, 0xDF291AFE, 0xEAF00887,
+0xD8DD4259, 0xDF67331E, 0x50D0CE88, 0x1FD090AE,
+0x632DA5F0, 0x95272A5B, 0x31172F25, 0x547FD7DF,
+0xAFBE11D9, 0x97189DFC, 0xC4881191, 0x1C92365D,
+0x843DEFDE, 0xCF0A399B, 0xCF327CAF, 0xDDAF0BCE,
+0x03AA7A2E, 0x411A8664, 0x6CCF7CD9, 0x61097EF5,
+0x07F3941E, 0x5BC3EB75, 0x2791945F, 0xBEBB526E,
+0x18631A34, 0x25FEBF10, 0x419834CF, 0xF642D176,
+0x372FFF10, 0x2A1BEA1B, 0x400FF345, 0x257A234A,
+0x9F15E99D, 0xE06AA1DB, 0x3A0DB315, 0x2BA30D99,
+0x0E9E831E, 0x1B25EE41, 0x8DB30E70, 0x9FBA6D64,
+0xAB8AA5E3, 0x5A96177A, 0x6BE03535, 0x97E37DCE,
+0xACA24F26, 0x5F0096F7, 0x5D02722F, 0xAF8F3EC7,
+0xA6824151, 0x70FAD406, 0xDEBA8513, 0x99C63E34,
+0x1CC4A3DF, 0x7F756508, 0xB7386527, 0x647C7FB8,
+0x43F1F4DF, 0xC7E4EC18, 0x302BA109, 0xD5E9175B,
+0x82856F77, 0x0F6D45D9, 0x95AE28B9, 0xE63385C3,
+0x8FB26619, 0xBD99F298, 0xC884B948, 0x0B596FF1,
+0xE061C3F9, 0xBC2F9A81, 0xC488CD91, 0x372EF590,
+0x3DA1BFE5, 0x10DE037B, 0x7210B4DC, 0x74E4EFF8,
+0x6365AFD2, 0x8CEABC85, 0x1D8FFD43, 0x4DE243F8,
+0xEC976FD9, 0xAD827765, 0xC679F15D, 0xC125EC31,
+0x95D3481C, 0xC4EA6EAC, 0xC8FC014F, 0x1352EB66,
+0x9C400EB5, 0x227BFAB9, 0xB12BF958, 0x85B6D782,
+0x78B6E44D, 0xE2232EEE, 0x4F101711, 0x9ABEBF69,
+0x66ACC682, 0x04AD5F55, 0xE4FC6238, 0xBA3D2266,
+0xA2BA3170, 0x083F39AB, 0xFF2075C4, 0x945C4B05,
+0x41E8C113, 0xEC7CAD67, 0x3653733E, 0x03510C3B,
+0x1E973158, 0xFBE507F3, 0x2CCD8D9A, 0x6EA9442F,
+0x0D48DE95, 0xC517BFAE, 0x04EBB5C9, 0xEFAB1823,
+0xD5FBFC0A, 0x6890F212, 0xA1C00CCD, 0x6DD561E6,
+0x20D39B1C, 0x56113FBA, 0xCF3A7FD7, 0x3AB5A0DB,
+0x3656572E, 0x7BC48CD3, 0x8902AE36, 0xD3E94AFF,
+0xC06EB447, 0xCC513C0C, 0x2544B7DD, 0x6F168877,
+0x53162607, 0x461DCEF0, 0xF47AF2BB, 0x8AF9F3CC,
+0x1EEFF9E6, 0x57CFB6B6, 0x7F712439, 0xAB20C93D,
+0x043F9003, 0x60C808BC, 0x86C2137C, 0x46ADB474,
+0x848B65F2, 0x5544789B, 0x18E9AEC7, 0xC889913E,
+0xFEB79B2F, 0xA3FBE518, 0x67922463, 0x93746398,
+0x968E160F, 0x8CA856A4, 0xA040202E, 0x660C00C6,
+0x8F0A8E62, 0xE2BA54DE, 0x4BD0C117, 0x1A1A3092,
+0x086CAA3A, 0x2BBA5676, 0x89610176, 0x00ED2F97,
+0xC72130C7, 0x5A053880, 0x7298E553, 0xD67971EA,
+0x0D41E477, 0x2FA8285F, 0xB856A190, 0x132DB916,
+0xCDFFDD11, 0xB5519A81, 0x1BC7001B, 0x97C824DC,
+0xBB4C707F, 0x90166DC2, 0x42DFAB7A, 0x90E33184,
+0x6C6B940C, 0xDC553814, 0xC4F5E7AA, 0x99434AE9,
+0x82BB09D4, 0xCB0A7DA3, 0x3A8033AE, 0x054D3481,
+0xE20AF761, 0x25F5F254, 0x7AD3AF3A, 0x23A34C29,
+0xA19C57BC, 0x39B57AD9, 0x55E1EC59, 0x5ECA4198,
+0xDB908BCD, 0x4871C3F4, 0xE7091328, 0x64A9B6EC,
+0x1CCAB2F3, 0xEDB22423, 0xFFB6A717, 0x6FA13548,
+0x361FF711, 0x24664017, 0xCBBF9970, 0x83A7B7DE,
+0x9B704690, 0x01A0B877, 0x95041B60, 0xC048F3E1,
+0xA31625F2, 0xE3DFBE27, 0xF657295B, 0x1F5C3AF5,
+0x60EE1637, 0x575EDFAC, 0x725844FB, 0x242723D0,
+0x04FA46FC, 0x1A8C3F44, 0x0E03A5FE, 0x8778079F,
+0x606E4E1A, 0x7C0AF3D5, 0x9578B266, 0x63BCE765,
+0xA8ED66D9, 0x9242377A, 0x817A5D5E, 0xD0981A98,
+0xC07F2E7F, 0x0E66F84A, 0x3635F854, 0xD7AD8359,
+0xDCF23230, 0xC1B9084C, 0xA7987FE5, 0xC3B27EB4,
+0x1F747061, 0xFD278601, 0xB6ED3B5A, 0x9CEF8AA0,
+0xA5023C46, 0xB49832AF, 0xB12055FD, 0xD85310E1,
+0x2C19ADE6, 0xEFBB17A8, 0xC246A4C7, 0xBE4B2666,
+0x13C2D7F9, 0x50063BA1, 0x9B00E02D, 0x335B9DF8,
+0xD424AF25, 0xBAE40C92, 0xE87BD6B7, 0x384D1EB1,
+0x8B91E8F4, 0x9E3FC6D5, 0x6BB1A51E, 0x21AE5533,
+0xFCB8E713, 0x188B66B1, 0x6572E9ED, 0x98829178,
+0x7BAE8CBF, 0xE00C32B4, 0xDAFC14D5, 0xEA8FC746,
+0x2C8D712E, 0x89A05FC9, 0x9A274641, 0xAC2450AD,
+0x2437784F, 0x3B1B80F0, 0x0B4A31FD, 0x277C0232,
+0xFDDC6829, 0x3F3C606C, 0x0EF62352, 0x3D07D04A,
+0x4E0939E8, 0xD59BF115, 0xA02752E7, 0x42BF7133,
+0x9FA0939E, 0x64764109, 0xD5D03EBA, 0x3D4433A3,
+0x1749B437, 0x137298B1, 0x677BE344, 0xA83CEF7E,
+0x17813A39, 0xBC71823F, 0x2070E9A7, 0x3873AEF8,
+0x5AF1E21B, 0x1F0CC692, 0xB8EFB04D, 0x1A1CC514,
+0xADED6C3D, 0xDF35A8D7, 0x6D93275E, 0x9C362545,
+0x62BF7583, 0xFC56D990, 0x0CD6A324, 0xF12A7939,
+0x52587029, 0xD00D5F16, 0x51622555, 0x1178E887,
+0x81E7BCC8, 0x92BB1C11, 0x097330E4, 0xCF8C5CAF,
+0xD076D6BC, 0xBA292918, 0xF835A829, 0x4280A51E,
+0x09CD7827, 0x11583487, 0xB8BA2CEF, 0xD598AE93,
+0x99F4FD77, 0xEB151110, 0x1571B076, 0x63F2103A,
+0x56C6BF44, 0x9E63B556, 0xFB981238, 0x5D8C978B,
+0x9501D936, 0x82A1E971, 0xE5A4F7E2, 0xC6E3727A,
+0x03329F07, 0x248ACDD6, 0x437E917B, 0x23B02B20,
+0x73F76AA0, 0x75EA06C5, 0xD7C662B3, 0x267777F8,
+0xDC96BF06, 0x54020346, 0xCBDF069B, 0x030133EC,
+0xA7EF1C2E, 0x568959AB, 0x4FC31DE0, 0x3A22890E,
+0x280F8652, 0x1BD8CB24, 0x9A8D92C9, 0x52718DE1,
+0x12033FC7, 0xD48490CC, 0x681ADEE2, 0xF91BF7B8,
+0xB8609B38, 0x34CF4BCA, 0x8F123290, 0x0D0F4FCD,
+0xC4F43323, 0x2FC04F1C, 0x4669B890, 0x1E8D2A7F,
+0x0658CAE6, 0x5489F3A3, 0x9CD362FE, 0xBA5190B1,
+0x06A58820, 0x7A9AF759, 0xDC94E672, 0xEB284B85,
+0xF8EFA022, 0x3837C379, 0x7C9E9A2A, 0xD2ED96BC,
+0x5D1E4C7E, 0x97F2169F, 0xFC3C37C2, 0xE039EDF1,
+0xDBE93909, 0x81FEAC6B, 0xFCD383FC, 0x170B91FB,
+0x05BA3243, 0x8FB2ADE1, 0x52AFB984, 0xE8262E9A,
+0x1E704638, 0x89B8DFD8, 0x18C0C641, 0x2760C7E6,
+0xD3AFF3C9, 0xC4E3543B, 0x0C0B7910, 0x1DEF7792,
+0x483D7194, 0x9AAF5864, 0x08607947, 0x626F0CF3,
+0xC0F6A486, 0xEB4525CE, 0xA8BBA8F8, 0xE450DA14,
+0x2DC4D114, 0xBCA527C9, 0x6682AA4D, 0xCBB48A5F,
+0x1B474C99, 0x7F5B526C, 0xEC435C0C, 0x9E8D3E1A,
+0x67D2EA29, 0xA3B7ADCD, 0x8328590E, 0x7345607B,
+0xB6057588, 0x1A8B034C, 0x5C8CA534, 0x8115DC5F,
+0x189C2ABE, 0xF1B92927, 0x78A3B62F, 0x4B621D49,
+0xDC176A68, 0xCBD3C1DC, 0xD82348BB, 0xEEF05FA7,
+0xC0DD3D83, 0xC1F2A7BF, 0xB2079D00, 0x14B5730E,
+0x73203CD7, 0xA8672433, 0xA171FFED, 0x9F181200,
+0x4E16A5C8, 0x56D8AC31, 0x73803D86, 0xD4685CA4,
+0xE8DE9FE2, 0xA35D2CE8, 0x808CF3E2, 0x198700AE,
+0x0034163F, 0x57BC76FE, 0x271ACF93, 0xAA3AF6D0,
+0x37003A7E, 0x450B74F4, 0x157401CB, 0xB79DDDA8,
+0xD60AB7A4, 0x3A4C8779, 0xB6990FC8, 0xA1668D5A,
+0x05B7965F, 0x7814376D, 0xFA0D2D8A, 0xD97A1142,
+0xE804DE3D, 0x4939089E, 0x78D40CAC, 0x01DEF5EA,
+0x3DD1CADA, 0x96465956, 0x6358CFB6, 0xACE02DE5,
+0xB4C9F6CE, 0xE9C95AFF, 0x70EAD28E, 0x58803693,
+0x89EF9972, 0x58F0273F, 0xDB17A277, 0x0B082B98,
+0xAAB13ABD, 0xE86381EC, 0xC18924D4, 0xE28D4348,
+0xC21895AB, 0xE17073AD, 0x9417539B, 0xA043E5F5,
+0x88FFD026, 0xD972F017, 0xD0C8B8D3, 0xB34F3D67,
+0xC525E4B5, 0x0189A5A1, 0x59224A35, 0xAA18F2D5,
+0xFC9E170C, 0x16D3795A, 0x35DB09FA, 0x1624DB1D,
+0x4A6E059F, 0xC5C88A93, 0x9051D373, 0x4B12B09C,
+0x4088AF39, 0x705394F6, 0x360F2BAC, 0x8A1F2420,
+0x641D4FA5, 0xA78B78F9, 0xA5A5302E, 0x691D2108,
+0x7CFB57FD, 0x1812FE68, 0x8A2BB5E0, 0xF181CA14,
+0x1846848E, 0xDC044F67, 0x17FCCA28, 0x21D7C5AC,
+0x4C43432F, 0xC457E26E, 0xB0C9ADD2, 0x791EE2B4,
+0x620F27BE, 0x229E0B1E, 0x746B4FFC, 0x02038738,
+0x1C7B971B, 0x05193430, 0x8645DBD7, 0x58678F98,
+0x141E912D, 0xD89C587E, 0x9FD7B43F, 0x21851D56,
+0x725311A7, 0x0605B1B2, 0xC18BF2B7, 0xC6F79EA9,
+0xBD84A01B, 0xC9B7F2DA, 0x04E47EE8, 0x1C1A14F5,
+0xBD5B4FF1, 0xE15FBC2E, 0xC4D43F01, 0x5D39AD4A,
+0xBD3BD983, 0xB2314A4B, 0x8DABA67E, 0xB5263B5A,
+0x9912F262, 0x82659C80, 0xC3610181, 0x3F229014,
+0x2685532F, 0xCE4EC210, 0xF46AB09A, 0xFAFA69C8,
+0xD1292944, 0x2EF880D9, 0xD03AAEAB, 0x0E83C435,
+0x842C482C, 0xA70951A1, 0x0E4EA07D, 0xE0332D0C,
+0x3EA27E55, 0x04721425, 0x7C8B56DC, 0x96391312,
+0xF600D78C, 0xC850517C, 0xB3F9F2AE, 0x59A99351,
+0x8D6AA838, 0xF586672E, 0xD81FE525, 0x3CEF31DF,
+0xABDC7079, 0x6E1BB8F6, 0x6B45B87B, 0x9FD2CAC4,
+0x648E357A, 0x6C57D30B, 0x23766B64, 0x8C8BD9C1,
+0x9A29001A, 0x206F47E3, 0x5F423D75, 0x293A32C4,
+0xDCC6432B, 0xA4280954, 0x457790B8, 0x11E84CEF,
+0xAB11D0BF, 0xD04258E3, 0xFB44C0CE, 0xED8231B2,
+0x0277A6B2, 0xD8E5C517, 0xCEDF4C8B, 0x19D90170,
+0x20555532, 0xFCB610B9, 0x88D5F5A9, 0xD35DC77E,
+0xEF5EA686, 0xD866959C, 0xF0886B56, 0x005CFB90,
+0x582AD255, 0x7381289F, 0xC18CED4D, 0x444F0A6B,
+0x9917AE56, 0x505A7BCD, 0xCBDC903B, 0x51EF0F3C,
+0xC4E6AF5A, 0xB148AD2F, 0x609A124A, 0xB5DA89E4,
+0x3A68C7D4, 0x98694F02, 0xE85B1766, 0x754BA5FF,
+0x1296A58E, 0x27736843, 0x9B6280BD, 0x2686032D,
+0xB428AC04, 0xB06DBA5C, 0x625FE034, 0xD4BCB25E,
+0xC91C5B3C, 0x73BB70E5, 0xA26A479A, 0x73173229,
+0x3AA1235C, 0xE16171D1, 0x42D0D42F, 0xFC624752,
+0xF1F5DCC2, 0x1B6F20A9, 0xFF9D626D, 0xDBF052C0,
+0x90E38D23, 0xFB72CC5E, 0x9186519C, 0xF2330093,
+0xE5251385, 0xA0094977, 0xE83FA066, 0x2E389CE2,
+0xD3A62E72, 0xA9422A8B, 0xC61CFD5B, 0x1B3A516A,
+0x58087800, 0x3A47462C, 0x557DDD8B, 0x94FD21D4,
+0xE1AEA942, 0x4B2CC532, 0xB2185B36, 0xDCA15259,
+0x1D044D7D, 0x781317B8, 0x49CB13E7, 0xDAAFFBC6,
+0x30A05644, 0x77B05F37, 0x065A567C, 0x94721C79,
+0x47316C60, 0x58AAC7C9, 0x410081AB, 0x7D4A36FA,
+0xCDF23455, 0x1873EF87, 0x186982B5, 0x7C78D9DA,
+0x3567D966, 0x10FF5E8E, 0xDB88E5B3, 0xFF1D39A1,
+0xB8A345A3, 0x7A7258F3, 0x9706B3CE, 0xB5ADCC26,
+0x4561EF5B, 0xB002FBF6, 0xF3F4C6FA, 0x57EC75AD,
+0xBCF37924, 0xBC05B0AD, 0x2AB19DAA, 0x0EBD25EA,
+0xF335D08C, 0xDFF79E19, 0xDD86D418, 0xECE11951,
+0xC06F4D50, 0xFD698DF8, 0xBA6192EF, 0x365A28CE,
+0x74DEC0B7, 0xE971F67B, 0xBF89DD42, 0x1E683399,
+0x164A7158, 0xA1E48475, 0xBE139E8E, 0xBDEBA7FE,
+0x74E03AEC, 0x88EA9618, 0x9B0048C2, 0x68C1DD20,
+0x8DC9FC85, 0x24B55E3B, 0x51C38BDA, 0x2ECD7B13,
+0x54D66C89, 0x69A3EBC1, 0x4B4E4F13, 0xAD37B7DF,
+0x030A1D8B, 0x85A114D9, 0x403BE495, 0xB5E40331,
+0x316E7310, 0xB36AA494, 0xDBFFCB9A, 0x5C0E5DA5,
+0x099BA9E8, 0x66826E9D, 0x0BC5849B, 0x1A20CBAB,
+0x0744FBE6, 0x2CB52040, 0x8B88533F, 0xA8A44BF1,
+0x62FEB4A8, 0xDB2ABC4D, 0x46F0B676, 0xCBD06470,
+0xDB6D71EF, 0x5DC3551A, 0x71B31A5B, 0x046D4C7F,
+0xC051A998, 0x1EC19FF9, 0xA9E21F9F, 0x7951E081,
+0x78BCBA62, 0x91B623F2, 0x8EF6A81D, 0x1023755E,
+0xCE47F5AA, 0x0EF27527, 0xE9E488D5, 0xD53E4A29,
+0x78A276E1, 0xB2100585, 0x01208E3C, 0xA38BCAFF,
+0x36221FB7, 0xB3C9194E, 0x51BD75D4, 0x9C8C73AC,
+0x7ACA9964, 0x17890C94, 0x9FDA51F4, 0xC4FDF688,
+0x2C8244B2, 0x0D834C74, 0x290973D3, 0x7F134553,
+0x296D2FC2, 0x4E08ED27, 0x1C51E53D, 0x3D892F49,
+0x945F76CC, 0x2E531E63, 0x71EE37E0, 0x9C47F346,
+0x2D8D920C, 0xC3E465BA, 0x3A72D142, 0x5B6AB80D,
+0x364C2AE7, 0x3B18389B, 0xB9442484, 0x5D687BB5,
+0x97C65A4F, 0xC7DBE8BE, 0x0F840061, 0x5A73EA89,
+0xCBBDD954, 0xAFE9CABD, 0x06ABDF95, 0xF139302D,
+0x3804FEA8, 0x7CE6542F, 0xDE47B8ED, 0xD34BE509,
+0x5EB9C9E1, 0xDC582534, 0xE77D7FC8, 0x2BEFED7E,
+0x4EA26DFD, 0x54670B81, 0x665C4531, 0x5B7A7023,
+0xA05D9A2E, 0x71BDDB2E, 0x9D51D8C2, 0xD8A665CC,
+0xA9B87A22, 0x581D28BF, 0xF9D40373, 0xE04D8F63,
+0x117B9842, 0x8868B9BE, 0x8397FAB9, 0xEF5CED75,
+0xF70F90D8, 0xD3DFD3A6, 0x1779F576, 0x3059520D,
+0xC38F4AA9, 0x6B7A6D0A, 0x4E73112A, 0x4FF9DCED,
+0xAEA1383A, 0xBAB0AA93, 0x41DBCBED, 0x266775A6,
+0x8EE0D5D5, 0xB522CB9E, 0xC6E5D0D3, 0x86E4C8FD,
+0xA894642F, 0xF69821A9, 0x88B41798, 0x4585A188,
+0x9D2130FC, 0xC5B18E0D, 0x6B92C9EE, 0x3C9289FB,
+0x1F02CBB6, 0x31FA86DE, 0x1B2295CD, 0x5B4DA19C,
+0x3134D8FC, 0xE5EABC44, 0xDF8C5095, 0xF6571881,
+0x1F2FBD62, 0xE585FE61, 0x020CEDF6, 0xD70ABC83,
+0x5F37746A, 0x6FDA3BF7, 0x5434E503, 0x44CF6915,
+0x561B2393, 0xEA4A2251, 0xA988C080, 0xE47B1791,
+0xD335CFBE, 0xEDA9DEE2, 0x4F70FB22, 0x83A2C29F,
+0xF44FA002, 0x069D25EC, 0x4D5043F5, 0x887464CA,
+0x661D1E9F, 0x98B856AD, 0x81A23FB0, 0x3693BD42,
+0xCE0AEB0B, 0x1F6E8322, 0xCBDF571B, 0x93688909,
+0xFA16A774, 0x25834437, 0xEE77FA98, 0x8DC68C60,
+0x155A8760, 0x22B8FCA3, 0x1B1BB054, 0xCA3AFFCA,
+0xC8EACEA4, 0xC86BADD9, 0x473770AB, 0x41D6E398,
+0x568B397D, 0x065C0BE5, 0x51D38A0D, 0x3BB3A0E1,
+0xBC386DCB, 0x7DCBA6B0, 0x19007254, 0x3F4FC726,
+0xF27DAE85, 0xF7FDA72A, 0x6D0B5C07, 0x64A0ED12,
+0xE26D8878, 0x210E4F6B, 0x65F92C0D, 0x4E4E2CA6,
+0x5E479D49, 0x7B287050, 0xE9A4836C, 0xC3A111A2,
+0x9B90D6FD, 0xA5F362E0, 0xADC9526B, 0x79B736E9,
+0x72A9A57B, 0x181B4E70, 0x5236F32A, 0x5567E3C9,
+0x23EFD063, 0x87113163, 0xCDF6D4F4, 0xF53A8722,
+0xB70CF941, 0x757F40C8, 0x6A652BE7, 0xD71DA5AA,
+0xF87D51C2, 0xB4A68E16, 0x763D8FEB, 0xB6DE5436,
+0x12184DCD, 0x38D1DE90, 0xB39E5209, 0x1600492A,
+0x073AE8F5, 0x0366AC0E, 0x1AD5014F, 0x398E0873,
+0xD653928E, 0x30B5B4DE, 0xAC68A06E, 0x8DAEF4D3,
+0x76A880D8, 0xF3B3BCC5, 0x2B631F58, 0x340914DB,
+0xB4771DCC, 0x7C9D4A43, 0xAFDB1138, 0x014B5A83,
+0x0D44185D, 0x20C89576, 0x994B4367, 0xA84BD792,
+0xB2E17CB1, 0x00CE5214, 0xFB93E54F, 0x03CCA7F1,
+0x956A82E6, 0x22329A71, 0x2A634374, 0xF18B7AD9,
+0x1F168BC4, 0xC2CB1EDC, 0x8E0AF6CD, 0x211AF22A,
+0xAB5DA374, 0x63F1F25E, 0xEC58D4CC, 0x48C65C46,
+0x5A7F7574, 0x7BA60047, 0x279EF299, 0xE0B77F48,
+0x647A03C3, 0xAE7C4D8F, 0xF65149D0, 0xAC9EF228,
+0xCD90B1CD, 0xCEEDA54C, 0xD8FD0A6A, 0x8D7C2291,
+0xB38EF6C1, 0x7F38E676, 0xDADD0A8F, 0x1125713C,
+0xAA78A299, 0x54033F20, 0x199C76C5, 0xCAF82A17,
+0x16F2EE8B, 0x20071D0F, 0x2CA000F8, 0x0178A24B,
+0x0029EE46, 0xA9D8C738, 0x123D2BBD, 0xEF7CAC52,
+0xBD241869, 0x435F8FF7, 0xB573A190, 0x402BFB2F,
+0xFDA3097C, 0xF3765889, 0x68E2C7D5, 0x4C26F858,
+0xD6814D1F, 0x6B043C7B, 0x173DB091, 0x95126C7C,
+0x0FE8E1BE, 0xFDEB233C, 0xB979B0CB, 0x00E00659,
+0x19952E52, 0xA0976F7E, 0x02FB462C, 0x798815C8,
+0xA2504EFE, 0x0F4811AD, 0xBA8F122E, 0x5EE5864F,
+0xD39B6799, 0x5319F6A3, 0xF6A66685, 0x988D106F,
+0x7ABA5220, 0x0320384B, 0x4DE48C79, 0xF5CB36E6,
+0x2B33270F, 0xFF4E6965, 0xD4D843D5, 0x7EEE861C,
+0xA96AE5EE, 0x310E5215, 0x6D20068E, 0xB149AE8B,
+0x0997D9EF, 0x5043FFFA, 0x0516E2B6, 0x3FCCDA32,
+0x8E604A04, 0x23012778, 0x9444A474, 0xB7F5DC24,
+0x3A58E6FB, 0x17B759FB, 0xF29C1EE7, 0x8893D2D1,
+0xC6CD235B, 0xAAB0CBCE, 0x2D84474C, 0x8A0BE027,
+0xFDB87FB5, 0xE6B507BD, 0x19B41927, 0x783FF4DA,
+0x485A1D5D, 0x8ED285C2, 0x25AFC4C5, 0xBF0D662B,
+0xC4238532, 0x4339FCCF, 0x14A784B6, 0x71665819,
+0xED76E473, 0x5F1BAE9E, 0xD0AEC17B, 0x4CE78814,
+0xD3609F61, 0xD4E49EB0, 0xE4E3EFDA, 0x9B7CAD1D,
+0xEF01ABB7, 0xD137BEE9, 0xEE87A81D, 0xD4B204FF,
+0x00B25737, 0x2770FBD1, 0x174AFF7F, 0x0A77A21C,
+0xF1B370E7, 0x9C093CB0, 0x080C1FFA, 0x83CE92D9,
+0x1707470C, 0x3303479F, 0x25F1B6AF, 0xF40EEB7F,
+0xB98A1677, 0xA54A1BA2, 0x43B4144A, 0x2F092A35,
+0x33286A77, 0xA0AB9C93, 0x4F8D70DC, 0x3A47BF6F,
+0xB6209AB5, 0xA4C94557, 0x5E757055, 0x706EAD9F,
+0x467BC02A, 0x6472A857, 0x42055C57, 0x66F2BA60,
+0x33C0536F, 0x3240BFBD, 0x3DD74E6B, 0x1F58A552,
+0x822E9577, 0xF49BFE77, 0x5490DC6D, 0x1D32BBA0,
+0x1C30B072, 0x78A4A5C0, 0x1EE88A57, 0x97CAC3C8,
+0x9912861F, 0xC916BBAF, 0xFC3A7F0E, 0xCA5E1F3A,
+0x630F09CD, 0xF6C8C210, 0xF0A12A72, 0xF3148619,
+0xDF1672E1, 0xFCE5C390, 0x29CAE554, 0xE984A45C,
+0x8A1F0A3A, 0x6A02C707, 0x8CFB3ED6, 0xC0A741BD,
+0x7A871FE5, 0x91021A69, 0x505FB05A, 0x8F85227B,
+0xC300ACF1, 0x0A1B201B, 0x224614B2, 0x54A23576,
+0x5360A5BA, 0xDCD23A31, 0xF98DF638, 0x79FF79D7,
+0xEAC8EAC3, 0x4D22C65D, 0xDFFBF1D9, 0x55FD8848,
+0x4BFD2347, 0xE2A08287, 0xE6A48824, 0x80625EA9,
+0x71AB3F7E, 0x99B84DE5, 0x6512ADBE, 0xFBF24C47,
+0x3EEF2564, 0x23DF9F1B, 0x24BE5199, 0xDEDD72D5,
+0xA2FE063B, 0x4FE520B1, 0x9E4E7BBE, 0xD615BDBE,
+0xC14E8184, 0x40F86FB1, 0xD403A65A, 0xC5AF6386,
+0x412F8434, 0x6D6012B0, 0x4EC57107, 0x3F76AF19,
+0x54A305BD, 0xEA9C4EB2, 0x584E0176, 0x20759805,
+0x1A16C84A, 0x50BB10DB, 0xE610AF45, 0x98CF1EA0,
+0x3F8C7756, 0xF9056BE0, 0xBAA66B7D, 0xF7076DCF,
+0x67F1994D, 0x92BFEB62, 0x86FBDE17, 0x389DB311,
+0x2A171F5A, 0xE14898B1, 0x4D11723F, 0x29889062,
+0xCBF3DD79, 0x2B7468FC, 0x4FB93770, 0xC5FCEFE8,
+0x8FEE6678, 0x9F4ABA9C, 0x6A6B23E1, 0xFEA7077F,
+0xC835F734, 0xCA67807C, 0x1BFBEB49, 0xB8B1E842,
+0x6A850623, 0x001C1E8D, 0x782AC01E, 0xA28A72D8,
+0x6CD66FC1, 0x77EF6F13, 0xFF40D7CF, 0x4A163DFB,
+0xDB21AA89, 0x29D03A9E, 0x3A4D1D57, 0x7A89CDC9,
+0xC5623E10, 0x8A444799, 0x1F620DF4, 0xFF876758,
+0xC9DEEF2E, 0x7F86911E, 0xE3196093, 0xA00EB422,
+0xCDB1743F, 0x4AAD1988, 0x70167700, 0x70595C5F,
+0x8E648013, 0x401D8770, 0xC762F0E7, 0xDB776926,
+0x2BDC55B3, 0x8F4AD2C1, 0x1A2EEB50, 0xBD4BF2A4,
+0xA43FFE90, 0x752935E7, 0xB02C7801, 0xDD4CD3DB,
+0x3815C394, 0xAF427695, 0x7455A8F9, 0xC444C7EC,
+0x9BC9B2C5, 0x08423BA7, 0x5D91ADD8, 0x59D866DB,
+0x0AD32258, 0x7BC397F6, 0x0EF7DB59, 0xC1034320,
+0x79073406, 0x991A12B9, 0x9D6776A0, 0x6348A5EB,
+0xBD98CDC4, 0x81A6C5C5, 0x76A3ABA6, 0xFA9CDF77,
+0x97772B59, 0xD987E42B, 0xA4B893D4, 0x61F78E38,
+0x82567691, 0xCB91CD58, 0xEEFA69AE, 0xF7D51178,
+0xA436C578, 0x99E86E08, 0xA8C3B16B, 0xD609054F,
+0x1E0ADCE8, 0x5DF6EF20, 0xEB3CC45B, 0x9FAEA24F,
+0x97F57F19, 0x66E2713F, 0x42A423C3, 0x2A21B17C,
+0x6A4C6B40, 0xFA0F4F2B, 0xD1F3F64A, 0xD0AAFA50,
+0x767D3AC2, 0x837E626D, 0x3B21279C, 0xCAE18855,
+0xFA8CA385, 0xA91BDE45, 0x1A953327, 0x733948CC,
+0x158B8CD2, 0x904AC43D, 0xA6BC8F82, 0x55F027DA,
+0x95B6BB32, 0x9265FF80, 0x8EEF0D24, 0x28F6796E,
+0x1D736700, 0xB621D4D6, 0xAB2F1A4A, 0xECD7DB83,
+0x35CAD419, 0x60604917, 0x5DE51335, 0xA3D7E122,
+0x685D04D4, 0x494739D4, 0x0060722C, 0x59149718,
+0x03C9F144, 0x43328818, 0xBB1AE189, 0xCA7B9250,
+0xC835666D, 0x83950220, 0xD774405F, 0xF6F4FCCE,
+0x0E38794D, 0xAF184A7E, 0xEF66E15B, 0xA0C2A74F,
+0x876112D5, 0x7D68C9CF, 0x8902011C, 0x6AB0E128,
+0x2A515520, 0xA99D1DA0, 0x9EACEB4D, 0xB669AA8F,
+0x6F96DCE2, 0xCFEB5CDF, 0x46EB36BD, 0xEDDF8317,
+0x4FA30C3E, 0x9541A8A1, 0xA5F75533, 0xEFE1FEF6,
+0x7F21B481, 0xDA11D5EA, 0x64642069, 0x083D2137,
+0xDF508726, 0x8F6CCC4B, 0xC5412D0A, 0x6A9F6BEA,
+0x3E3CC54F, 0x078BBB1E, 0xA6047468, 0xF1FA39C2,
+0x26143435, 0x90132EB3, 0x4216580C, 0xF6773B8C,
+0xA6B188BF, 0xE3B49523, 0x89E4563F, 0xD0B16538,
+0x2D9079FD, 0x69ABDE36, 0x669AC5EB, 0xD0618DD9,
+0x5080BFEF, 0xADC056D6, 0x72402C9C, 0x0AE79E07,
+0x8D6DF48E, 0x0502837E, 0x79BA17AD, 0xE4871C89,
+0xC4554CD5, 0x23FCB2A4, 0x646FA999, 0x212A9DB8,
+0xBD23DF0A, 0x890B5FE6, 0xB5D03292, 0x9FA3FD59,
+0xD612F8B1, 0x611365FB, 0x7E7C9FAB, 0x024194D2,
+0x46C2C617, 0xAEB0FAD9, 0xAE5D3A7E, 0xEA8B0ABB,
+0x760730A4, 0x50443E76, 0xECA64341, 0x538E5256,
+0x8A8505F5, 0xE0E4DC29, 0x105DC564, 0xC73D93D9,
+0xE3F27C90, 0x8CC01FC8, 0x400D0F76, 0xDCD01130,
+0x1E3416D4, 0x4C612E03, 0x0BFE7A5C, 0xFDB15334,
+0x5326A77F, 0x99549BDA, 0xDDE90BAB, 0x920BD872,
+0xC4B4F5DF, 0x7B39BAC2, 0x777C6694, 0xB4971103,
+0x9E7806A1, 0xD3141F2D, 0x2B40BAD0, 0x74AF248F,
+0xD1AEED43, 0x2F453736, 0x1880104E, 0xF9CD502F,
+0x7691FE59, 0x39C3FEC7, 0x72EA7BF2, 0x0C94BAB5,
+0x35D6F509, 0xAE86AC96, 0x0624C181, 0xA69DF699,
+0x5991FCE3, 0xAB20D4F1, 0xF30F1BC9, 0xB094CF62,
+0xA3B5A732, 0x3BC8C32F, 0xE7710370, 0x429A8D96,
+0xD8913A42, 0xCFBD0E4F, 0x710B7078, 0xC6501E93,
+0x241224AF, 0x978D2320, 0x8EF1064B, 0x273FAE07,
+0x316EC02C, 0xB3C16C0B, 0x8249C245, 0x21AD11CB,
+0x6265FE57, 0xA9F1D5FC, 0x0B52F1CD, 0x0381D983,
+0x2931D6B1, 0xD126CD94, 0x69D95197, 0x7CFB6AD0,
+0x46E6D50D, 0xE60BCBD2, 0x72FBB436, 0xC971A4CA,
+0xA580B9B9, 0xBC823514, 0x5D15A840, 0x87A91622,
+0x63490D13, 0x277189A8, 0x22CA2EDC, 0x1C56456D,
+0x1B5EB836, 0xD8BBF2EB, 0x20F56DFB, 0x99321E4B,
+0x9238B783, 0xE5E5D085, 0xC81DAA11, 0xEF8DD032,
+0xCEC28645, 0xFC40AAA5, 0xBFA5FC68, 0x1C2CF7C7,
+0xC0DFD194, 0x5AB730DA, 0xE3FB56A9, 0xA0AD00E9,
+0xB7BA2E2E, 0x579C8722, 0x04AA07FD, 0xF55C6C5C,
+0xE56CD6DD, 0xA7DA5100, 0x2A6BA1E5, 0x9B7E5104,
+0x81410420, 0xDC6130A8, 0x3EC8935B, 0xCC2EC782,
+0x142344EF, 0xF016E0CA, 0xA3ACFA8E, 0x019A7009,
+0xA0DAEC5D, 0xFA503565, 0xC907794E, 0x77AA4E69,
+0xB45B7E54, 0x929A056A, 0x46AA4AE1, 0x55E56EDF,
+0xFDD9D726, 0x35744D5C, 0xD6854700, 0x9A6E1EEE,
+0x0B00F6FB, 0x6BE65BFB, 0x9CF98DE0, 0xD80ACE66,
+0x1E5300E4, 0x745338DD, 0x4CB925DE, 0xB369B0D4,
+0x7A53A606, 0xD2B96E54, 0x88F96B30, 0xB72C3E19,
+0xC2A41177, 0x6206F879, 0xC1F6CD78, 0x879DA74F,
+0x763F9417, 0xD109B779, 0x6A58B34C, 0xDCD7C21A,
+0x1B0A0154, 0x45EE3A9C, 0x62C60161, 0x79E47020,
+0x42250A39, 0x9E2C2C59, 0xCE4F6206, 0xC2970386,
+0x983CC2C3, 0x0DAF0A85, 0x388626DA, 0x06A56D27,
+0x9223203A, 0x96E0148C, 0x22F0D052, 0xD5F1AA88,
+0x394BC8B9, 0x03CF58FA, 0xC0B1073C, 0xC16B35C7,
+0x7B7CF9F8, 0x2E3A24A5, 0xA19089C9, 0x4223FAE9,
+0x7751D977, 0x802E7062, 0x6D3651EF, 0x39E9B52E,
+0x946D07F8, 0x8E2EAEB7, 0xF9279A65, 0x14DEE911,
+0x8B92A149, 0x9611756E, 0x067DD22D, 0x59907967,
+0xB3417E3C, 0x3B72AB7A, 0x825D87C7, 0xCE5FA852,
+0x5D88C5F8, 0xE792BF66, 0x28DB3A4A, 0x118CA3A2,
+0xCC86284E, 0xA0AC4AE8, 0x33394B70, 0x974F96C2,
+0x86ADD3B5, 0xC87295B9, 0x1447D26F, 0xC9ECAE80,
+0x10CA01D7, 0xE04ECC68, 0xAE56597E, 0xAAA1248C,
+0x81C35460, 0x0087CA93, 0x943AABA2, 0x0AFCBFAA,
+0xEA77D5AB, 0x020D36D6, 0xF1CCBBB6, 0x8DF1426F,
+0xAE726D96, 0xA6E4C915, 0x58F15F91, 0x5B696D6F,
+0x00042B30, 0xC6AC90C3, 0xBD8E0187, 0xE73ED2E2,
+0xCEE64CF6, 0x48B56436, 0xA33994CA, 0xB3E3B7AB,
+0x060D5E14, 0xC1B176C6, 0x4A76C391, 0xD7C8DB1D,
+0x333E4998, 0xC20BAC4F, 0x523BE3E0, 0x237E87BC,
+0xE6CDBEC0, 0xC506F19C, 0x262C0039, 0x7F85A4AC,
+0x46160693, 0x2EA1BC36, 0x4CAC0DF2, 0x0066B83F,
+0xBCBC778D, 0x7F4AB507, 0x99CADB2F, 0xC95520D0,
+0xC5CBF067, 0x903ECD68, 0xF5D7B0FC, 0x08198C8F,
+0xA17879EC, 0x18C2723D, 0x5A4D6D37, 0x080198B6,
+0x3525186C, 0xEF8BE144, 0x44B05851, 0x28B5025A,
+0x0FDF085D, 0xDEB1F249, 0xA7C00F42, 0x7614A735,
+0x3BEBF467, 0x7871D305, 0xD4F63809, 0x9D044079,
+0xE585D3D6, 0xA89952F3, 0xF42C2B8E, 0x04179DA4,
+0x00A6CE87, 0x96CA92B8, 0x9DF2B156, 0x3ECF18BC,
+0xDE2509CF, 0x5CD85FCA, 0xF8A7CEEF, 0xCB7DC25E,
+0xF2847474, 0x35B501D1, 0x137BBB3E, 0x451E1BB9,
+0xD360D811, 0x792B3464, 0x4BF89A81, 0xA7E9C450,
+0x628BCB0C, 0x2AF7037D, 0xA45F628E, 0xF0EC875D,
+0x9CE3677D, 0x2CD0EA59, 0xA50A0217, 0x8BA45DD7,
+0x1735ACF1, 0x5804C4D9, 0xE619B352, 0x948F44A8,
+0xA9BF5C7F, 0x614D4F6C, 0x6D9FCA79, 0x29717B0C,
+0x50BF2D5C, 0xD5847B52, 0x0D4FAAA5, 0x1AABCA5D,
+0x779399E0, 0x58A90CD6, 0x37EC2615, 0x61B68C07,
+0xC49F4AEE, 0xFAC4D897, 0x9C68CC6D, 0xBB3352F6,
+0xF933436D, 0xD310078E, 0x2FBFA17A, 0x3D839C4C,
+0x186E69EF, 0xCBE7CC6A, 0x7434231A, 0x80F8130B,
+0x58CD7EA2, 0x2E46D714, 0x367286E2, 0xA6E2044D,
+0xC2ABC50A, 0x6FEDC9C4, 0xE2F26F03, 0x3B030D52,
+0x3674D8E7, 0x9096DF78, 0x90902892, 0x44A32190,
+0xD08D2649, 0xEFE0ED0A, 0xCE1BF4E9, 0x62C19753,
+0xFBF3D1A8, 0xD4AA5390, 0x4B32E77F, 0x9894F05E,
+0x41B9DBBE, 0xE9B09561, 0x46C883A0, 0xADD5D60F,
+0x69CE5BBE, 0xFD29CCF1, 0x2F209371, 0x4C6716E9,
+0x31E9A09F, 0x04089795, 0xB9EF9025, 0x97C6267D,
+0x63823150, 0x3AB346BA, 0xED3E0579, 0x85FC7062,
+0x37B35761, 0x4A32B6CD, 0xC38EB479, 0x203642CC,
+0x568FCAD7, 0x67D92B5D, 0xE51B8C3E, 0x02104078,
+0x026BC607, 0x5A06CDA7, 0xE27435D0, 0xC7C20CE7,
+0xFEA74022, 0x77310076, 0x35C6F953, 0xE1B199C5,
+0x262F139B, 0xFD2FE2C7, 0x3EEE02EB, 0x915A873F,
+0x2DE4AB8E, 0x2421DC15, 0xD1DD0D9E, 0xDE02B5AD,
+0x151C76CF, 0x798B90B7, 0x82EDDF4C, 0x795E18CF,
+0xF09CEC5A, 0x070ADF8F, 0xCDCF5232, 0xD498D43C,
+0xB4FC2662, 0x25678E54, 0x5D200482, 0xC31F21C9,
+0x35E5AF29, 0x8CC0E603, 0x995351AD, 0xD8EB54F6,
+0x564E35D9, 0x0C13E321, 0x34CFA33D, 0x33D1E5F9,
+0x2EAC9748, 0xFFB950D6, 0x2032206F, 0x4F871AE3,
+0xBD464C61, 0x06356EA0, 0xA15A290D, 0xA78456D0,
+0xD2F4EE88, 0x4D835908, 0x15DC87B3, 0x79EDB6C3,
+0xAEAF0F9E, 0x5C3E7EF9, 0x639A099E, 0xD375D8DA,
+0xB718510B, 0x090DF965, 0x9C8A362E, 0x25AD10BB,
+0xF9A42BE9, 0x8ADE3DF0, 0x5527424E, 0x301F0D0F,
+0x2F691C9A, 0x534FE1FC, 0x7D406016, 0xF98820A2,
+0x4D204871, 0xED145173, 0xD67ECE9A, 0x35F9F990,
+0x8ED4D787, 0x1F3F46E1, 0x5A68F171, 0x9A9D28B0,
+0xE726BD5C, 0x8119228D, 0x0ADBA4D2, 0xEA243204,
+0xE523C0D6, 0x261E3664, 0xB2D1211C, 0xB4D9293A,
+0x9C89D924, 0x15A6A3A9, 0x0D8C6C66, 0xEC04AD36,
+0x0CDF0F98, 0x9262C7DF, 0x8EE0E09B, 0x6B929EE9,
+0xDCC713BC, 0x75FD34FF, 0x2784E694, 0x23C23044,
+0xB7B04F09, 0xF10B753E, 0x2EC774DA, 0x470BE72E,
+0x054510E9, 0x9C7DDF10, 0x1466C277, 0x9F52F493,
+0x7F298608, 0xF1BA10D3, 0x8847A319, 0xEE8A63CA,
+0x8E64B34E, 0xEBB66933, 0x575ADB24, 0x041BFD76,
+0x727ED364, 0x00F4A008, 0x8F5EDA92, 0x21477637,
+0x0B360617, 0x56DC8978, 0x27F88944, 0x69B799EF,
+0xEA1E943B, 0x6FDD60B0, 0xCE2AD89F, 0xB98CCF43,
+0x2A3796BF, 0x4DD02535, 0xC6B524EA, 0x6B173341,
+0xDCE0A457, 0x91770646, 0x57A8D138, 0xFC218331,
+0xDC6B712D, 0x14C0B3B9, 0x30CA09AD, 0x759EB942,
+0xBC9634AB, 0x8F92A7E5, 0xF7F85B53, 0x6C831B3B,
+0x56A75B18, 0x43DB9F1C, 0xF81FC212, 0xB8EB9026,
+0x78A74B51, 0x870655E3, 0xA17B536D, 0xBDE866CF,
+0xFC609F11, 0xF34A7016, 0x7C4FD4DD, 0x236312F6,
+0xB50520A8, 0x4BEEA2C3, 0x2B690BA3, 0x18701667,
+0xBD791FA9, 0x236D36CF, 0x49E576CC, 0x316A77E1,
+0x93E9B0BF, 0x52715603, 0x83B9AAF2, 0x0F8F2A80,
+0xA87F764A, 0xD2079BEB, 0x48A24AB6, 0xAC370950,
+0x3077FB2F, 0x4BAFF3F5, 0x1A79926D, 0x8B369956,
+0xAD78F739, 0xED88CE42, 0xB96A7C15, 0xA7BBA2EE,
+0x47CC3233, 0x804DE962, 0xE0B431A3, 0x4A8257B8,
+0xA4B0E8E2, 0x2FFC49B8, 0xF0CDF5E5, 0xF089C32A,
+0x46328288, 0xEACBC054, 0xA48CB5CC, 0x77996530,
+0x83A4E184, 0x3C2F47D9, 0x5106177C, 0x33F1A787,
+0xA2266E7A, 0xEBC426C8, 0xD7E8ADD3, 0x2DF40477,
+0xF9E8D7BD, 0x80BD8EAB, 0xE61CE55F, 0xF6A7EF6F,
+0x5C67E1C0, 0xFBD0088A, 0x7ED37B24, 0xF5BFD58E,
+0xC29CFB0F, 0x61ECE08B, 0xA776CFD8, 0x9E0F3A05,
+0x8FC8B02F, 0xFDF82702, 0x028C2F2C, 0x169D3094,
+0xE4AA3228, 0xF2CD142D, 0x9C70574E, 0x057BFE78,
+0x782B9039, 0x0D01311F, 0x97552050, 0x6A097F2F,
+0x1B3242B8, 0xF43F32FB, 0x96004287, 0xC3DC0939,
+0x4215A0E1, 0xACD1A28A, 0x189932EC, 0x9BBA0475,
+0xFA154E5B, 0x4B4E8D01, 0x4D6B18B1, 0x31545B3C,
+0xC849C52D, 0x60958B9B, 0xE92CF090, 0xAC3E1B58,
+0x251D02A3, 0xFAEE4F8B, 0xB1CF6CCC, 0xC2A0D8B0,
+0x0501DF46, 0xD0369D94, 0xF3E11479, 0x397599F8,
+0xB90064D2, 0x341F6D57, 0x31F0141A, 0x2F899029,
+0xBC9EF6E8, 0x13B47347, 0xB93D59BB, 0x556E990F,
+0x5727BDFC, 0xBA9F5121, 0xD67BE7CA, 0xB167E84D,
+0x2C0ED0FF, 0x251FFD4A, 0xC98719F2, 0xD379D976,
+0x8B3A0A9B, 0x40BA5F66, 0xE40A93E8, 0x2F89FC04,
+0xFCBAFDD4, 0xF2424270, 0x1BDBDD15, 0x7F1459B0,
+0x5ACB6C6A, 0xFA20719F, 0x2F16FFB4, 0x820DDE50,
+0x468AAC15, 0x7816134C, 0x978D9570, 0x6745CD6D,
+0xC1E768C1, 0x15E243B5, 0xBA30AD61, 0x483FB6FE,
+0xCAA17D0F, 0x2F8F0974, 0x34AB68B4, 0xB3E864B0,
+0xC1DA3828, 0x5DAD43B0, 0x72D13B81, 0x01F274AB,
+0x9C0651AD, 0x0FC30C10, 0x0E7AA3CB, 0xDBE6B9D9,
+0xF423B9A7, 0x457B4E32, 0x40E8E269, 0x91DA042A,
+0x9DBF41E9, 0x308C0F2E, 0xCABFAC0D, 0x0E2C86B2,
+0x117BC3C6, 0xEEA538F8, 0xF31585DF, 0x0DF50281,
+0xEAA9601E, 0x8F408AFA, 0xF1144F9A, 0xA2AB2ECD,
+0xACB88685, 0x6F4EFFBD, 0x81EEF886, 0x46B02240,
+0x3C09D916, 0x4F0DAF68, 0x8337B3E3, 0x9A011BA6,
+0x4C63AC66, 0x2FCC669E, 0x0C7D15BB, 0x51279D9F,
+0xC1354779, 0xEFF940AF, 0xA956CB37, 0x0DB797E2,
+0xE665EE55, 0x79AF879D, 0x21BBC902, 0x30B264BF,
+0x411CDC98, 0xE453389F, 0x47C2C197, 0x3E6015F8,
+0xF9E7AA2B, 0xA9302474, 0x04C6888F, 0x4D118BF9,
+0x0DB7AAC0, 0x52A38EDB, 0x4DAB22F2, 0x7DBB6EAB,
+0xD4D17851, 0xFD944314, 0x40C5838C, 0xBA6EB0EF,
+0x9AA287A5, 0xF6D236F0, 0x41D9E2BA, 0x6968D776,
+0x31B1D129, 0x42C3F963, 0x27CCAD30, 0xCD61BF4E,
+0x2C7DABAB, 0xA78A9CC3, 0x7F856B6F, 0xB6D444A5,
+0x90CBB312, 0x95611781, 0x4916D531, 0xC496C30E,
+0x706D0CB7, 0x35D0064B, 0xFE26C36A, 0x6211F14B,
+0x2C2340BA, 0x58633567, 0x06B6BA8E, 0xA7EC3D8D,
+0x1071B0CD, 0x388EEFA8, 0x60D8FB1C, 0x5F99D147,
+0x52CA6EBF, 0xFA73602E, 0x0376C15C, 0x3C91B57D,
+0x9386AF17, 0x14A35A1A, 0xBDB42A39, 0x0E83C257,
+0xD4C5C775, 0xA607FA46, 0x91B9AD40, 0x7623C5D6,
+0xE3D53E6A, 0xA3C663E7, 0x5AD39BCE, 0x03B58394,
+0x38862C7A, 0x01D50B9F, 0xEAAB38EC, 0xAB3DFB8B,
+0x06795385, 0xB17F485E, 0xE2F57914, 0xB79A3BAA,
+0x13DA7886, 0x7136C7EB, 0x5E748AF7, 0xD34F16FC,
+0x968F6701, 0x99C5D7BE, 0x530F7FAC, 0xCDF5D567,
+0xE31DE0D3, 0xCF93BC68, 0x34C578AA, 0xA201F761,
+0x5CB8DC00, 0xCA24DB98, 0xF8AD7E4F, 0x808EC476,
+0x603BA751, 0x489555C6, 0xF2A03FF0, 0xD2461E9A,
+0x102C33BE, 0x7673933C, 0xC11A2424, 0x6A23C8C6,
+0x69499812, 0x19AA8510, 0xC8CDA75F, 0x34B5216A,
+0xD87F7420, 0xC8CEDB53, 0x8DF11BA2, 0xB10911C6,
+0x3F1E5955, 0xF075F4EB, 0x17874FC5, 0x0D55685B,
+0x5EE521E5, 0x46C72924, 0xF8540210, 0x5D5E4C5C,
+0xE87A133C, 0x91633DC9, 0x36B54D5D, 0xA8B5D440,
+0x7DB7D6C4, 0x5FA82C17, 0xAD679039, 0x86B3B839,
+0xDF5121B7, 0xC08B768A, 0x338A512F, 0xCF9A4F9A,
+0x5DEFBB5B, 0x4C9301B2, 0x08023702, 0x5B1D7E28,
+0xEC800505, 0x3A869E80, 0x4C50C8AE, 0xB1AE9064,
+0xAFFA34EB, 0xF2F006B9, 0xD8A9A3D1, 0x2C6C2134,
+0x677EE648, 0xBB6B6D5C, 0xA285136C, 0x6C47BF4C,
+0xAF158DC1, 0x0EF75E2B, 0x5B9C74D5, 0x9B8D4BE3,
+0xE495BE19, 0x5940B228, 0x55E62656, 0x3247E060,
+0xBF7094CD, 0x1C1AB380, 0xECEA2275, 0xB6DD8251,
+0xCCA39DD2, 0xAB85D992, 0x278197D2, 0xFB6C9FD0,
+0xBD53B458, 0x89EFE0EC, 0x52A3DFFD, 0xA6B7FF7B,
+0xFB043649, 0x93C93F79, 0xAEB4CD6D, 0x71DB5C90,
+0x9E8DFE92, 0x0F1A5B91, 0x55C5CF5D, 0x1A1847AC,
+0x8D25CF6C, 0x914FD316, 0x39FCFE20, 0xD8F66A07,
+0x2CDD3DC6, 0xE415AC72, 0x3D1BD09B, 0xA8322C59,
+0xBD3A826A, 0x2A988A40, 0xEBD8B1DD, 0x9F53EEEF,
+0xDF571816, 0xD4FCCDAE, 0xB85A1E50, 0xBE1A571F,
+0x0ED07534, 0x4C1E471A, 0x8B4D36F6, 0x0E388FC6,
+0x9ED2BC4D, 0x3E2D7F72, 0x752ACA15, 0x8960B48E,
+0x5892B3D7, 0x70F6F3CD, 0x26C485EF, 0xC83839B9,
+0xFE6C224B, 0x3547203F, 0xF73ACA84, 0x065DCDBC,
+0x8986EBDC, 0xCD59EA14, 0xC0EF58A8, 0xC5587229,
+0x484FBCEF, 0x9B8BF24D, 0x351CF946, 0xE10AA973,
+0x17919640, 0x95FF7B1C, 0x82AB65E5, 0x070BCC98,
+0x0E7CDB8D, 0x38DB27DE, 0xCA543C2B, 0x0131EB41,
+0x8300996B, 0x88B63D66, 0x03ADAC1D, 0xB205A87B,
+0xD8BDC0C6, 0x443F6071, 0x2CE69D2A, 0x6E1E5A53,
+0x4EFF93AC, 0x70322657, 0x5CCDD146, 0x04C435B6,
+0x5BF3CD69, 0x51E09115, 0x2545DFB2, 0xA52EF448,
+0x8D387046, 0x7C4F1F25, 0x2EFFD8AA, 0xFD6422B0,
+0xB82E26A7, 0xCF01CC45, 0x88899EBE, 0xDB621966,
+0xBBA1822F, 0xB264AAEB, 0x1076EAA5, 0xC24B0CD5,
+0x54D554B0, 0x4ECA7C05, 0xC8C9B053, 0x70A86D97,
+0x4E3265CA, 0xEA24F810, 0x873B172D, 0x79A74D18,
+0xEC3F49D5, 0xD1799602, 0xA21A28B6, 0x3FB99AD1,
+0xC2DB35B3, 0x63EC2E51, 0x17E4489F, 0xE8E19164,
+0x79ADD819, 0x10D66157, 0x5F621A73, 0x1CD063BA,
+0x6665815F, 0xFA0B7081, 0x6E0FA473, 0x0CE3571E,
+0xB5EAEF46, 0xAA04CF54, 0x336680CA, 0xDABBFF11,
+0x2259E797, 0xB57B4470, 0x111EB4BF, 0xC171D42B,
+0x5889A7A4, 0x419CCB3E, 0xBEA1F366, 0x41FE414B,
+0xA65CB898, 0x6C28363A, 0x8F82FC84, 0xDBED5A9C,
+0x4DBF3526, 0xF2F34E66, 0x9D2C9B11, 0x0C0D4DFB,
+0x4DBF79D4, 0xA256E86D, 0x6407376C, 0x3F3E8AFF,
+0x474B3593, 0xE55965C8, 0xCB20D358, 0x0C671A9B,
+0x169F8342, 0xD2E1C9E7, 0xBDDBAAEB, 0x93DF0C75,
+0xF27707F7, 0x5108305B, 0x4FF2C060, 0xEB9C08DE,
+0xDF11020E, 0xD2271046, 0x6D1BFD27, 0xED020CDC,
+0x2C22659B, 0x692050D9, 0xD14BE291, 0x3EBF8E86,
+0x8344B625, 0x7840B91C, 0xB702BD5F, 0x4935D318,
+0x01A22013, 0xF2A20B08, 0x651A1C38, 0x004FE633,
+0xE51DCC06, 0xF5B86138, 0x9FBFF118, 0x6F7B3CD4,
+0x028938B4, 0x071E96AE, 0xDF33DC9E, 0x79001AC7,
+0x7B5D20FC, 0x3F137794, 0x81165B04, 0x973F8FD4,
+0x0AE4CBF5, 0x7C48180B, 0x4A96BC89, 0x58066E74,
+0x86669DC6, 0xDC55A218, 0x858C3130, 0x99AEAC91,
+0x26983FC4, 0xEE4D4F06, 0xD8D6D657, 0x18EF262B,
+0x374A620F, 0x85995F9C, 0xCC814AC1, 0x39F487E0,
+0xC628177B, 0x2FAE2C39, 0x642525A2, 0xC1474F2D,
+0xBC7CD49E, 0xE81E13F7, 0x83F42BDB, 0x8AB7D99A,
+0xA8040B11, 0xD8AA68EC, 0x983B3739, 0xEE42ECDB,
+0xC9513498, 0xCAA06A14, 0xE4784094, 0xE6BEBB9E,
+0x13BE8018, 0x59E3D5D4, 0x0CF1728F, 0x963413BE,
+0x319533B7, 0x14662ABE, 0x3363B45D, 0x59A99687,
+0xBBB0FDA4, 0xCDBB8B21, 0x0240F3B1, 0x226DAC3B,
+0x30E1C49E, 0x76E076D7, 0x4B91C598, 0xB3C46E2F,
+0x4A657CC7, 0x66C3875A, 0xCBC6FC54, 0xF832EBE8,
+0xDD1EAD3D, 0xFEFDAF85, 0x8DE51B88, 0xAEAFD5D3,
+0x3E4CEA82, 0x55F47934, 0x9F8314CA, 0xD0220BC0,
+0x5ACEF81F, 0x71FDD8E9, 0x13A14ED8, 0x6F1FC1E4,
+0x75046A04, 0xC6C4FDAF, 0x4FFFF724, 0xF44FEDD6,
+0x7E1C5CBC, 0x784C6B4C, 0x8D85F220, 0x38B65C3E,
+0x8C992050, 0x2DE34C13, 0x9F2A4547, 0x48E58F65,
+0xA280B689, 0x6F540D8A, 0x10B61B39, 0x1C8A2849,
+0xA7316358, 0xDBFB7862, 0x182C553D, 0x92F04389,
+0x1FE7BADD, 0x6A724CBA, 0x970BE020, 0x93760058,
+0x2DF9E0AD, 0xCFF1F8B1, 0x170D810A, 0x45F4E6A2,
+0x37A0E8FD, 0x86D11C6D, 0x4F3C6A3A, 0x4B144452,
+0xCE9B87A1, 0x7C08C30D, 0x9CB9B0AB, 0xD55F2CC5,
+0xFF95180F, 0xF35505BD, 0xED5BDB96, 0x85CA2E41,
+0x8708B264, 0xD6079734, 0xCA76AB3D, 0xFD6CDF4F,
+0x9AAB840B, 0x92D3A5F7, 0x93A92C38, 0x0419AA7A,
+0x1D50006E, 0x126F48FF, 0xACDA412C, 0x01139454,
+0x8E23C486, 0x01D44F51, 0x7A5F6F10, 0x377D4D5E,
+0xB784E72F, 0xA9AC925F, 0xB9C66C79, 0x057331E6,
+0xCFF040E4, 0x77E8A960, 0x35E31EEC, 0xEB807A44,
+0x8594FFFC, 0xD27629B7, 0x5DDF526E, 0xBCF2F484,
+0x88805013, 0x41047850, 0xB8574ECD, 0x3E15082F,
+0x309C16DC, 0x297B6904, 0x30C39ECB, 0xD20B61AF,
+0x51A578AF, 0x4E0D24A9, 0xC61FBE5F, 0x7A89F4C6,
+0x9432299D, 0xFE261B95, 0xDD1FC4CA, 0x044BFB92,
+0x41BE56CA, 0x0A2B6831, 0xE135D75D, 0xAB2D00A0,
+0xB4374080, 0xFAA6DBD0, 0xA704C4A9, 0xD81385A4,
+0x51533312, 0xED5EDAF7, 0xE4EDFAEB, 0x74B7DAFE,
+0x9D810AA7, 0x40B91827, 0x65219BCB, 0x75431C16,
+0x94D923D3, 0x00B7AA4E, 0xB8A88FDA, 0x927278D7,
+0x7A237697, 0x45B14097, 0x2E3A562F, 0x93003322,
+0x0B88A5FF, 0xD13D4ADD, 0x6D7B7579, 0x72D834C4,
+0x0BCAA361, 0xC02E00B8, 0x15023551, 0x481C5E93,
+0x02E81A16, 0x8A846A33, 0x1239A971, 0x994818B4,
+0xFC3DBB6D, 0x43C8D2F2, 0xE3AE548C, 0x408032F1,
+0x02B05636, 0xE361A60C, 0xFE2CA292, 0x061D2374,
+0xDB285556, 0x70627EA4, 0x7FC64AF0, 0xFE100B6D,
+0x71AEB3F2, 0xA565A412, 0xA698731F, 0x49DD9767,
+0xC3627EBC, 0x75FB2DBF, 0xFDC0E971, 0xF6ED12A6,
+0xA23DC00F, 0x897E917B, 0x7F2031E0, 0x17DCE568,
+0xDF69CAD3, 0xC6FB5B6D, 0x097268B0, 0xE1102444,
+0x86DF9383, 0xBD7B9CC2, 0xBAAF7DCF, 0x985B45D1,
+0x4218E95A, 0xB2455EF4, 0xDB015F9B, 0x54CCCE76,
+0x56EDF561, 0x6F66F95E, 0xF8B1EBD0, 0xF7A39AE0,
+0xF66D8346, 0xA4677007, 0x02C4B3EB, 0x829987B0,
+0x7C0E1919, 0x51F7060B, 0x4B30F1D6, 0x85A4E0CA,
+0xEC049FA0, 0x17CBF1E4, 0x7A1AAD95, 0xEBA4C513,
+0xE8462E78, 0x54CDDA0C, 0xEE7B8378, 0x9858C8C1,
+0xBA33587C, 0x4D6F1B14, 0x7A2C0525, 0x7E6EE4D2,
+0xACA18692, 0xDD186820, 0x41198B03, 0x8AC85AB7,
+0xBD86900B, 0x36E2C354, 0xE65F9115, 0xB10645DA,
+0x7971D230, 0xC83D3583, 0x8C60C81D, 0x94DB5741,
+0x4FCB8934, 0x9A520FE2, 0xCE49446D, 0x8864E641,
+0xF5EF25A5, 0xC1DEED0A, 0xC8057F37, 0xFB305C73,
+0x392E670D, 0xA4D00D2A, 0x356A46F0, 0x2F675567,
+0xB7997CF0, 0x88AF3A4E, 0x56C9D51E, 0xDD746ECD,
+0x40CFA453, 0x5EA740CD, 0xE4DD6BB1, 0xCCB31429,
+0xA2227F3F, 0x18A1EAF0, 0xC155417B, 0x41FE735F,
+0x16D40B00, 0xC9F72AFC, 0x86B1D62D, 0x6A99A82A,
+0x09D33248, 0xEC44639C, 0x9B0AB2B2, 0x6969164C,
+0xEF602BB1, 0x0208FC6F, 0xC1109578, 0x2997AB87,
+0xE5626B14, 0xCDAF48E1, 0x20781633, 0x2EBE0A41,
+0x7379261E, 0xF216F7A1, 0x714D8258, 0x936FE68F,
+0x160856F9, 0x2A4D1416, 0xB558E412, 0x7DB196DF,
+0xDC88CCB2, 0xF37AB612, 0x7423F214, 0xD3B06A43,
+0x25A8012D, 0xC1C69FFA, 0x936F2C18, 0x56D77C19,
+0x774BFC69, 0xF5E85E24, 0xD79158C9, 0xA67C3E15,
+0xB958819E, 0x69F81278, 0xF2B35107, 0xBF2F4085,
+0x1C997A06, 0x6C238C3B, 0xC756D56E, 0xD15C1149,
+0x351E6EC4, 0x2311303F, 0x0621602C, 0xB11B6DD1,
+0xBE8E50B5, 0x34A5F589, 0xE4D308AE, 0x4344B297,
+0xA33AE98D, 0x0A303CDB, 0x388EA17B, 0x0107B5A5,
+0x38B39042, 0xFE678995, 0xB426FE69, 0x221FCF06,
+0xC45926AB, 0x21A430F9, 0x6D192D2E, 0x4168C10B,
+0x5BA6B132, 0x0519ECA7, 0x21127582, 0xF6C447E0,
+0x0C72FC31, 0x0941B3F0, 0x76F23877, 0x86CF0677,
+0xE7785105, 0xA4637864, 0x94C82B45, 0xF60FD6A0,
+0x46941C27, 0x7A33A698, 0xE1DF8BFB, 0x5249970B,
+0xDFE65E1C, 0xF4A4FB22, 0x599639F4, 0xFE0E9722,
+0x7BB48F58, 0x533465E3, 0x9E884B35, 0x2620429C,
+0x2875FFC1, 0xF11EC0CA, 0x663AF5F0, 0xB2C59C38,
+0x03556ED9, 0x271E9E39, 0x8556E062, 0x08207682,
+0xE5797F00, 0x66A362B5, 0x7ED8394D, 0x2922C374,
+0x271657BE, 0xAC15071B, 0xE296691E, 0x0FE2C740,
+0x19120FB5, 0x9ABD888A, 0xA200762C, 0x7837F41C,
+0xC6F4EA19, 0xF286ABF4, 0xFCA8998F, 0x97B0E7D5,
+0x1339C79F, 0xFED05D43, 0xB3392E71, 0xFC2A01EB,
+0xB720CBED, 0x4FA71358, 0x04A57F62, 0x3D558B0A,
+0x1DEB4D40, 0xC9C823F1, 0x470F630A, 0x08F22975,
+0x2BD85107, 0x3288A628, 0xB0C89675, 0x32D957C1,
+0x80B78426, 0x98A46953, 0xA493AF60, 0xC2B84AC4,
+0x486D658F, 0xFE119FF9, 0xB2FE565F, 0xEADB58CD,
+0x1F45F9B4, 0xCEAE62B6, 0x68EC702D, 0xF52ADDF7,
+0x0FFC0715, 0x4129E42C, 0x956AC4D9, 0x0035CD9C,
+0xF8FEBAA1, 0x29C58397, 0x7C2E2E41, 0x7BE74DAF,
+0x2791D34D, 0xB6D67B0D, 0x8F557528, 0x9DDEED5B,
+0xB3AA4BB7, 0x05E22E43, 0x4CDA600D, 0x432E2D32,
+0x405DA5BD, 0xAF23818C, 0x2F73FE09, 0xD4624626,
+0x653EFCB3, 0x77D65D3F, 0x51A3DCB3, 0x767F407C,
+0xC66452E3, 0x10B6842E, 0x93A0840E, 0xE453AD10,
+0xDE58FC3D, 0x6C227215, 0x1EE130EA, 0xB0BF64BE,
+0xA11E5D38, 0x0131B755, 0x191F70D0, 0xDB483959,
+0xAA8D2F9E, 0x5A002AA0, 0xF5A2996D, 0xFD0F95F9,
+0xD6A12864, 0x3AA48B74, 0x50F6679F, 0x0ADF5C49,
+0xE2F8CE68, 0xBF213E67, 0x5E9ACEEA, 0xCACD0EBE,
+0x6DF766A5, 0x33C0A156, 0x720868EA, 0x3112A0DC,
+0xB382350A, 0x369D9C50, 0xE8F890D0, 0x0A121399,
+0x2AB458EA, 0x51C8233D, 0xBF46403C, 0x0728CD55,
+0x23F6774B, 0x2FB59DB0, 0xFA2CF724, 0xB49FA848,
+0x5FFFA125, 0xDE2C0D15, 0x76B78C41, 0x192BA62C,
+0x4C9563E2, 0x8F742507, 0x882104E0, 0x357AD078,
+0x799E25A2, 0xEF3ED021, 0x69D54B46, 0x5EC57870,
+0x0FF418E0, 0x07C5AC7F, 0xC1ACBF9A, 0x80A830D9,
+0x837C7C5A, 0x04C11D86, 0xC14C8BC7, 0x92BA650B,
+0x94D34FA8, 0xDBDD5EDC, 0x9ED2A08F, 0xA1FAE485,
+0x5FD66C3D, 0x4CCB6F9F, 0xB7AA56B0, 0x0FB3C73A,
+0x03AF96E6, 0xDB2D38F9, 0x7AF20D60, 0xB57CBE90,
+0x20EB2D6E, 0xCF934452, 0x82EC26F6, 0x84B3737A,
+0x0972F1B7, 0x39B6DB4D, 0x13E53CC0, 0x67C41D72,
+0x94BAAC78, 0x663A9C6C, 0x36927448, 0xCFBC2610,
+0x980F53BA, 0x7E56C96A, 0x04C62DFB, 0xA471D579,
+0xDF9B2EE1, 0xE12DEBB7, 0x2DB9B042, 0xF0C74B96,
+0x6A3762E9, 0xF4DC39D9, 0x761A5884, 0xFA363D3B,
+0x92766759, 0xF3EAD441, 0x878269ED, 0x1AFFAFE5,
+0xCB432764, 0xFE19475C, 0xCF8776DA, 0x1F0AD906,
+0x7D99AC20, 0xC27317FB, 0x439944A4, 0x65D14C2D,
+0x43E45262, 0xCDE6B3BD, 0xE25C67CD, 0x321AA2E6,
+0x352A2764, 0x5569EF42, 0x005C370D, 0x290801E0,
+0x61883035, 0x2A2DBC48, 0xE2D559FF, 0x01F5DF13,
+0x69B61558, 0xE94BF364, 0x3CA76FCA, 0x2E016483,
+0xDB675F9C, 0x4FA5B6DC, 0x59A6C3EC, 0x56C6E6CF,
+0x24CD59F5, 0x46911834, 0x683B9E39, 0xB5AF6174,
+0x5C31E269, 0x679C9A12, 0x3787D3E6, 0xF1727EE6,
+0xB070882F, 0xFC37EACA, 0xBEE0783F, 0xF6218369,
+0x19372940, 0x3FF7D890, 0x69736919, 0xDD961CB9,
+0x883010F1, 0x6E472D5B, 0x2447E00D, 0xF39E1F0E,
+0x1DBD442F, 0xBE1977E0, 0xC8655F42, 0x37C84253,
+0x3480DAC4, 0x4CFE1DC8, 0xF1521AD5, 0xA45C4F8C,
+0x87FBAEE0, 0x3E41E9E2, 0xF47771E5, 0x16C74CDF,
+0xA33D4035, 0x38513A10, 0xABF3264D, 0xB8D80DF6,
+0xD9AD7256, 0xF78375B8, 0xD7661CF7, 0x1C363AF9,
+0xD425FA32, 0x001D7B98, 0xDB96A1CC, 0xA092E683,
+0x65CF5316, 0x5F282689, 0x9F52F912, 0x8958A1B7,
+0x6457A3F7, 0xAB43FADD, 0x061328C7, 0x9D31B5E3,
+0x75A77F6D, 0x4A764D4A, 0x488CE83E, 0x29887218,
+0x9A04BDD0, 0xEF331070, 0xBCD2F884, 0x6BF66A6F,
+0xB85143CB, 0xFA529278, 0x9EA3A354, 0x4A73BDAF,
+0x0CBB7563, 0xD01AE35F, 0xD2AC3DAA, 0xFC8243B7,
+0xD805D97B, 0xC162A75F, 0x1D49AC67, 0x9E1BC38C,
+0x1D06AAE8, 0xEAF80CD8, 0xCE825DD4, 0xACA3F06A,
+0x83D092EE, 0x3F2BAABC, 0x2482D120, 0xF301680C,
+0x7DAC373F, 0xF5D6178D, 0xB7E9217F, 0xCCFE8C13,
+0x976024E0, 0xA2F39F8C, 0xB6C65734, 0x10AE514A,
+0x696584CF, 0x2542113C, 0x479CB20F, 0x8D3A22E3,
+0xF7C4B88C, 0xF4F7FBE2, 0x2F553308, 0x9EA71E3A,
+0x7B958F48, 0x0927DAAB, 0xF08949B7, 0x7CD46C0E,
+0x7A892BBC, 0x882F32CE, 0x34C490C8, 0x8483ED04,
+0x07EB4EFC, 0x4BEBCD82, 0x83B15EE8, 0x8F3B78AC,
+0xF95EFDA9, 0x816BEBF9, 0x269BDA58, 0xEE373342,
+0xE09FDA9F, 0xC7651AAB, 0xB8D398B2, 0xC7F449B2,
+0x031310F5, 0xC869706F, 0xDA22F127, 0x8C68DF91,
+0xE676068A, 0xB85AAAC7, 0xD32F35BC, 0xE22DF031,
+0xFE142BD9, 0xD4FB2700, 0x2D197707, 0xA3A43A64,
+0x0C02B050, 0xE945AD56, 0x7DEE0A5D, 0x1075DE3E,
+0xD99AD91C, 0x6A7BB71D, 0x1774B3B8, 0x2228B112,
+0x0DEEE844, 0x38074EBE, 0x6DACF57B, 0x7E0094B7,
+0xCE46F8EC, 0x4DAF34F4, 0x5B961907, 0xC8236FF7,
+0xFD380AA7, 0x61EBA84A, 0xAE4892EB, 0x0F1B6365,
+0xB0C4C9A0, 0x04E6012D, 0xA5F90D01, 0xD6C8882E,
+0xBCB9C1EB, 0x0E5E0FEC, 0x53A46889, 0xA2C0FA51,
+0x520DA459, 0x3FD95FA2, 0x6E1D6FE8, 0xBC093220,
+0xAB16390A, 0x163E3D6D, 0x0A63517C, 0x3BF38F3D,
+0x88A1F66D, 0x96263536, 0x412DF008, 0x12FB126D,
+0x44441D7A, 0x31C9F726, 0xF66F60CF, 0xAE1453D4,
+0xDAEAD71B, 0x54EAEE0F, 0x948B73BB, 0x31EA3E74,
+0x355D4FDC, 0x2A1F3A9E, 0x586D08DF, 0x123AC2E8,
+0xF5AC0065, 0x8874ACAB, 0x05B03D63, 0x01BD6A4C,
+0x7A6A9880, 0x2BC16F93, 0xC4112F0C, 0x8287B40D,
+0x48EABF08, 0x29E56860, 0x0F505C84, 0x447DC08B,
+0x1665119C, 0x00347E37, 0x482EF03E, 0x01B15D44,
+0xE6C1B9FF, 0xB165E436, 0x0CF690F7, 0x7FC5BD01,
+0xB784C7F4, 0x9BE04EBB, 0x9F614431, 0x6C37A5A9,
+0x2D0DB87D, 0xF6511369, 0xE115073A, 0xF96C6AB6,
+0x04A13C3C, 0xBF30B2DA, 0x93D18FC6, 0xF67D2E47,
+0xCA089151, 0x51A6BC39, 0x8C1FCA93, 0xFBF2F2BB,
+0xAD0A3F33, 0x82AA2767, 0x81BF2313, 0x758A82B8,
+0xE103788E, 0xC00C4B5C, 0x5F52FF58, 0xABAD38F7,
+0xDA68EE9A, 0x9B6D405D, 0x803449D9, 0x6178B345,
+0x3C785FB4, 0xFEBABE55, 0x0E2458AB, 0x021F0D71,
+0x39201ED1, 0x741B1A7D, 0xE0B0AFF4, 0x45652CFF,
+0x907DA678, 0x313A93B4, 0x0B0D6B0D, 0x42C96E43,
+0xEEE3E7E1, 0xE83C83E9, 0x9052B867, 0xF9514243,
+0x61F20CB2, 0x57E1AC64, 0xC2443123, 0x432C96D4,
+0x616A824F, 0x3C8D1E06, 0x8E64222A, 0x65C1A21D,
+0x8686308A, 0x2A576A2F, 0x1CA0FF20, 0x2C8F9D3A,
+0xC98C9C69, 0x35322A29, 0xDFD33C93, 0x9634F411,
+0x0B4F8FFC, 0x3AED4B01, 0xEBBC7012, 0xED2387EA,
+0x48BF42AF, 0xD60399D6, 0x7A9B8CA9, 0x53886337,
+0x2DBB9429, 0x0A6AF764, 0xDE4D8F78, 0x1EDECEE4,
+0x4F8EE99E, 0xAF23EAFD, 0x929550B1, 0x2CBD8621,
+0x22A8FAA2, 0xBE2A0A8D, 0x06F7E794, 0x16E1F3EC,
+0x093AAEAA, 0x92D429F8, 0xBB79A7E7, 0x43EF89BB,
+0x0E097511, 0x748E68B0, 0x322C00AC, 0xA62EF42A,
+0xD03BB8BC, 0x9FF67810, 0xDE24BF03, 0x140CA6FD,
+0x68F16B41, 0x1B7C68C7, 0x32646342, 0xC5E714F8,
+0xEFFFD2B8, 0x27843628, 0xF8445F51, 0xB9E8519B,
+0x8EB01D04, 0x356FBF2F, 0x32E96BAD, 0x6A629BDE,
+0x52063313, 0x200069B0, 0xE161CF71, 0x84FB7A12,
+0x1805ADC0, 0x80F75012, 0xFE9E629E, 0x93395C33,
+0xFF075A91, 0xB61E46B8, 0xCA9FE7C8, 0x97DCCBCA,
+0xCEFFB6F8, 0x30EE7985, 0x1FABC829, 0x20B3F57B,
+0x27042B07, 0xE12C5151, 0x23482B8A, 0x7B9B8EB2,
+0xC997FEB3, 0x76AB2497, 0xD5CDA590, 0x9EBE90FD,
+0xE3732B18, 0xFF28CEC9, 0xC6582320, 0x6EF106FA,
+0x8ED74023, 0x1A0B69E5, 0x4A95DD91, 0xB41AF82C,
+0x83DF69D3, 0xC548861C, 0x2F60BA93, 0xFC815984,
+0x1A848B67, 0x1EAE87C4, 0xF7479103, 0x8E16DB51,
+0x040B95B9, 0x2A9DB812, 0x987AFCD1, 0x866DF413,
+0xBF9558ED, 0xACF1AF2F, 0xA65305CC, 0x168336F3,
+0x1E59B97F, 0x3F9F447C, 0x3D54B30D, 0xE939D598,
+0x36A40885, 0x02396794, 0xEB0F0A67, 0xCEAEA12F,
+0xC58B4AC8, 0xE6D49760, 0x0F8F2776, 0x66A8F436,
+0x31BACD7D, 0x376993DE, 0x32BD0431, 0x68BDC728,
+0x63EA6748, 0xE6B00E29, 0x7448CABC, 0x42A6517D,
+0xBB1313C4, 0xA04DC8FF, 0x3D402237, 0xA382645F,
+0x52ED55D6, 0x92D7D7B7, 0x541230FF, 0x7AFC0420,
+0x3DC4624F, 0xD9B2193D, 0xA73B9704, 0xBBDE0FF1,
+0x9EB56615, 0x8AB080B6, 0x3C4D8E14, 0x5001B43D,
+0x1EBFAA23, 0xD4AACD27, 0xCFAAB4BB, 0x6FFEE61F,
+0xAE5A7426, 0xDB942949, 0x452C0B16, 0x738E0637,
+0x36A5122D, 0xFF1F7A4E, 0x743D35CF, 0x847D54A9,
+0x42C3EABA, 0xD46728C5, 0x30B2708D, 0x4F6BE0BC,
+0x3C26790D, 0xB0B67C8A, 0xEE07EFDC, 0x9E380611,
+0xEAD6804C, 0x4EF66024, 0x8459AE38, 0x1DEAAFFB,
+0xF76573AE, 0x6CB1C8F0, 0xFFCC267E, 0x26A215F7,
+0x0B1A057C, 0x7DAB9CB7, 0xD40BCBA9, 0xE561F9FE,
+0xA44013A6, 0x7B22C0B9, 0x998A921F, 0xBD25244B,
+0x15E07FED, 0xF15B2E31, 0x54E80016, 0xA12BCE7F,
+0x658A2093, 0xB642C47B, 0xD731FC00, 0xC00E302D,
+0x55B251DC, 0x342939EB, 0x6EADB2F7, 0x0CF93318,
+0x61EBD85A, 0x99B715EF, 0x679C8D3A, 0x9CC1B803,
+0xABEF955E, 0xB8CFF9D4, 0x707A839F, 0xF5D02A7E,
+0x59E0D903, 0x5A425E3B, 0xBB61163C, 0x96ECE9AA,
+0x797B82AA, 0xA9FA6BB6, 0x797C00DC, 0xC1C1FC4C,
+0x8F7FDA66, 0x77902514, 0x6D1B843D, 0x4F881FA4,
+0xC24AD625, 0xBC237A45, 0x9A2E0F44, 0x82FAA3F3,
+0xD70E3489, 0x4F2B3417, 0x65CF65E4, 0xEAAE6A93,
+0x4BEAEC2C, 0x4918723D, 0x7D8F30B4, 0x7706F59A,
+0xCB2A7452, 0x5083D2D6, 0x4724B426, 0x84EB15DC,
+0xBAA2C6CF, 0x71FA984A, 0xDDF7A3DF, 0xB115BF1A,
+0x258AF0E3, 0xA1637D87, 0x03585DF8, 0x5EA4B80D,
+0x8641F318, 0x66EE2F24, 0xC81E505E, 0x5E640639,
+0xDB7739B8, 0x1A3B861F, 0x0F5ECC51, 0xB21C00DD,
+0x680FF30B, 0xDE697468, 0x57A43B33, 0xD7EF6B3B,
+0x4BFC7D25, 0x710F0752, 0xABAA9752, 0xCFCFD84D,
+0x3BCC1CDC, 0x2381C524, 0xB60CAD92, 0xE05BC1AA,
+0x2B887D88, 0xCD4566C5, 0x0D2976E7, 0xCB000A2C,
+0x667BECF6, 0xEFC7F221, 0x7A7584D1, 0xC41D8B2E,
+0xD9BB7D3F, 0x7CEB5626, 0x7D8165A0, 0xEE178F99,
+0x3E8A8CB7, 0x693D4501, 0xB0E228A5, 0xD55B73C1,
+0xAF9043BF, 0x6C627A2C, 0x7B9F490C, 0x7EA61899,
+0x92B980AF, 0x6D13C758, 0x2C007C73, 0x74336E0D,
+0xA39F13AC, 0x533F05D7, 0x75536CFB, 0x9708DE27,
+0xE2A14E87, 0x36673FEF, 0x71BA654F, 0xB98CD2FC,
+0x27F29A6E, 0x82478171, 0x1C2815F0, 0x8A8F4549,
+0x048A8D9B, 0x7CEE51F2, 0xA1648AC3, 0x004F8B8F,
+0xB6FE8EF0, 0x6D10A0A1, 0xAD7A24D8, 0x75039717,
+0x97847786, 0x2791CC05, 0x6937FD6F, 0x60F98115,
+0x5FAB6D35, 0xC0550A70, 0xC0F4D817, 0x7B5BFDDB,
+0xEF63B4D2, 0x6C87C6C5, 0x956D6B87, 0x69179257,
+0x10973C90, 0x8CDBE860, 0xC7C761EE, 0xF823E34E,
+0x6FA2CF3B, 0xA903ABCB, 0xC82C9B01, 0x60FE96E6,
+0xE5EC33C0, 0x73A3011C, 0x2A1B9054, 0xCF16F92D,
+0x4FAF6CC8, 0xD9DD74FE, 0xB3C639ED, 0x3F47AF63,
+0xC8E99D12, 0x92D95986, 0x835ACA6F, 0xD52930A2,
+0xC7DD54A5, 0x617FDD15, 0xE9A6D295, 0xF56C6087,
+0x7813B662, 0x1F8EA244, 0x1CDE3BAD, 0x58FC0F7B,
+0x02E31A5A, 0xA78EAC74, 0x10C06107, 0x22BA3C63,
+0xF84AD224, 0x6A8BF66C, 0x2A5CAAC5, 0x8ADC3FB5,
+0x9683451A, 0x1B52FCB4, 0x95491BA5, 0xFE6C3713,
+0xE9098CEF, 0x73C01EF9, 0x6E85EF1A, 0xEE189743,
+0x2E9E5286, 0xC1FAA665, 0xD861E384, 0x701C834D,
+0xDC5CA5CC, 0x52A3A6C4, 0xF2AF2C43, 0xC37C6465,
+0x6E94AD69, 0x98808AF4, 0xED8A99F2, 0x377257D3,
+0xE60F2096, 0x615EFCB8, 0x67A2BB3A, 0xB4DDD40F,
+0x1D47F918, 0x86F77D6E, 0xFD05D2B8, 0xE18C330C,
+0xA48260A4, 0x5615B83B, 0xBCD7D855, 0xF8073219,
+0x8622BB89, 0xD35CE05B, 0x17162483, 0x137BDB69,
+0xECD0F226, 0x61F8982A, 0x3C10ABD4, 0x2F33ABF4,
+0x9358B547, 0x58B277A7, 0x92456A7C, 0x4384B49A,
+0x5F1FF0EC, 0xA153EA4D, 0xA8E49100, 0xD3A75723,
+0xD1ADC606, 0x76C314B7, 0xBC6AB227, 0x257312AF,
+0x8B6AA1E3, 0xD87FF5E8, 0x2BAED373, 0xC848AB63,
+0xB72B1E5E, 0x730A73D8, 0x4915E5B6, 0xDF7D77AD,
+0xEAE247D7, 0x9556DDA8, 0xDE0C9C47, 0xA4E3296E,
+0x31F5BC94, 0x05258B24, 0x2837374F, 0xC7E4C81B,
+0x5A1AC819, 0x068074AE, 0xDF876732, 0xC0192EF9,
+0x7FFD84D8, 0xFF1CE148, 0x821B4AA3, 0x56674838,
+0xF9A147F4, 0x182EF58B, 0x16E17174, 0xDE27029E,
+0x8BEC55AD, 0x40646F89, 0xDBFF92FC, 0x9F24C017,
+0x711EAD18, 0xA663E1EF, 0xEF92F684, 0x4BD05E67,
+0x7E089B13, 0xCBF619BE, 0xCEBEF231, 0xC947586C,
+0x0F526C47, 0x6672600F, 0xDAAB63DD, 0x950D4FD0,
+0x199C3EC2, 0x0F201C9D, 0x06BCC8D3, 0xA7672C6D,
+0xB39C7D0C, 0xC74B0805, 0xC9BBD249, 0xACDD5396,
+0xAB7BDF8E, 0x12012B8E, 0x67236047, 0x0AE0741B,
+0x1D747E56, 0x7EC6C00C, 0xD08E8341, 0xB0ABDAD6,
+0x4FA4BDF6, 0x90CE8D0E, 0x6E734117, 0x3EF9192E,
+0xACA32DA2, 0xFDB9C58E, 0x256626B5, 0x5EA961B3,
+0xFBC15776, 0x36602B5F, 0xF8D08644, 0x5B693C23,
+0xC62EA3B1, 0xC664C7C3, 0x73BE8859, 0x17F44E8F,
+0xF9B8D923, 0xD168A3A5, 0x6CCD110C, 0xD353181F,
+0xC0E774EC, 0x5F9E127C, 0x6C824511, 0xFDA13494,
+0xCB588BA6, 0x47148694, 0xAB877E87, 0xE97F757B,
+0xF54D0A2A, 0x0FE11891, 0x5D8747FB, 0xE7800C7E,
+0xEF96298F, 0x400F458A, 0xE2D04518, 0x4B4E6EFC,
+0x9B15002C, 0x3CE1B537, 0xF5ACB9B8, 0x67030647,
+0x475FD148, 0x1E03A40A, 0x896C7C05, 0x85F70B68,
+0xC590CA84, 0x53B5440E, 0x1400F78F, 0x3ABE7F8A,
+0x19CA67FF, 0x68B54A34, 0x555988AC, 0x4AB16B4A,
+0x7511FA63, 0x248EC9EC, 0xC25AFE4F, 0x19F578E1,
+0xE92AF03D, 0xAF9DE18F, 0x2798C7A7, 0x6B46990F,
+0x41D45894, 0x74696A0A, 0xC6AAF5F8, 0x72CC10E0,
+0xDB9CA283, 0xD6BBD0F3, 0x58EA4C06, 0xDEA5E8B9,
+0x1908EBDB, 0x95D33DD5, 0x20D7013C, 0xE725C282,
+0xFD48C92F, 0xDBBA7D19, 0xC7BEBEA9, 0xB186B799,
+0xDD0DD17B, 0xD8090A41, 0xF98BC20B, 0xDD7E4B9D,
+0xEBAE4247, 0x4376FDC4, 0x7F3EFAC6, 0xA9B9A951,
+0x4AE390C4, 0x651863AF, 0x2CD42DBC, 0xC2A13962,
+0xEF0FC443, 0xAEE63246, 0x09B83E19, 0xC3C940AB,
+0x00B12826, 0xC0A30412, 0xFCF6ABCC, 0x3CFE721A,
+0x62C1F4C6, 0xE963A359, 0xAE11F3D6, 0xE490D12A,
+0xC45C928B, 0x05CCA78A, 0x1982E93F, 0x577F81CA,
+0x66D50D6E, 0xB4C7030F, 0x93092C3E, 0x118B08FF,
+0x178545B7, 0xEED74838, 0xF7D2CE48, 0x238969BC,
+0xB8EFAEAE, 0x75726A3B, 0xB1E0220F, 0xC4D60EB6,
+0x0EBC0243, 0x5FE0D6CA, 0x35456B45, 0x1F64AC2A,
+0x58484A1F, 0x2A11455D, 0x33BC4403, 0x56E4E62D,
+0x60B41E2B, 0xDB65D3F8, 0x7EC18D34, 0xF575DC85,
+0x6E0B9995, 0x1C14C91E, 0xB2A94718, 0xAEC4A823,
+0x993D374E, 0xF1E4210B, 0x8CFCC03A, 0x99BD1C28,
+0xA928E3F9, 0xBB957D0E, 0x77C865EF, 0x7FF50A45,
+0x4279A638, 0xE628FFA1, 0xBCCA171E, 0x284C9CEC,
+0xA476E346, 0x7E2F9C08, 0xBF65044F, 0x5B7C3D5B,
+0x6E60EE5D, 0xF5C99509, 0xFA352B7E, 0x6FDE8E8A,
+0xF2340FE1, 0xDF542B6C, 0x510CB30B, 0x367E7016,
+0x198A0A95, 0xA4DF508E, 0x593C2338, 0xB12BCDE1,
+0x554AD3C0, 0x4DDAB1C1, 0xD2BD1850, 0xF6E126CA,
+0xF87289C7, 0x86EC92A5, 0x4E033906, 0x52DC5F3F,
+0xCC6E2E59, 0xFF751753, 0xDF8B8BA2, 0xDBF5954A,
+0xBD367488, 0x6A0CDF1F, 0x4103139C, 0xDE49DBB0,
+0x5A8428F4, 0xA26872B1, 0x96BF7203, 0x99D5E78E,
+0x243850A6, 0x389DAD80, 0x6335D33F, 0xEC67B0A5,
+0x029C0CA9, 0xF5F6F6C9, 0xDF574C15, 0xE6D3EC29,
+0x1AA349BA, 0x453E7258, 0x7DB79BE3, 0x51FCA7F6,
+0x2B42FCA5, 0xBF0E4871, 0x58063C40, 0x193580E2,
+0x25605322, 0xBC49C479, 0x0ED70FC4, 0xA78B59A0,
+0xE6CE3E8C, 0x92EE657A, 0x63D12529, 0xF95DAF45,
+0xF92C3BF3, 0x7D514200, 0x694DF84A, 0xEF177E2D,
+0x4E119CCF, 0xA025C55D, 0xF96974D6, 0x26D13E7F,
+0x799ADC27, 0xD7925EC1, 0x8AE60BF7, 0xF9EF1A2E,
+0x89EADD3A, 0x9C28CACF, 0x63377EB7, 0x6D1EF7E5,
+0x6585B16C, 0x9972D115, 0x65F8F5E6, 0xF93DECB4,
+0x6D71605D, 0xC6FDBCB8, 0xD937BA31, 0xCED727EE,
+0xC34C5605, 0x25FA70B6, 0x5C0B7FB0, 0x8F9340F5,
+0xA3376693, 0x4498B66A, 0x2D21F377, 0xC0A4C6EA,
+0x0780736B, 0xF42D7F07, 0xE56D47E5, 0xB48C25D6,
+0xA48DA0DA, 0xFE69693F, 0xF01E19CA, 0x8A0C5C8F,
+0xDF702C23, 0xE18A93F0, 0xD4D5C91E, 0xD2A706F7,
+0x674F9E28, 0xAF0F80C7, 0x648D49E8, 0x6BE8640F,
+0xF5FCFFD5, 0x8EDC391E, 0xE583D8BC, 0x8426C090,
+0xF456A27D, 0x07249BF4, 0x054A2F45, 0xAC46B73B,
+0xB89EEDFB, 0x48EAF867, 0x69B2D7CC, 0xCA0CA0F1,
+0x38CD0428, 0x029808CF, 0x86EE75DC, 0xF4FEE9F0,
+0x6987D5E9, 0x56AB5537, 0x3DDD0940, 0x4742FF89,
+0x2C3B179E, 0xD05B5CB1, 0x3C4E9033, 0x6BCF0141,
+0xF2F6D3E2, 0xAD297B1F, 0xB1CC23D4, 0x5452038B,
+0x1751FCBE, 0x24AA465F, 0x94C62D18, 0xF49B2EC8,
+0x97AC47DF, 0xD66C19B5, 0x09AAB297, 0x89936144,
+0xD15C026B, 0x4CEC8778, 0x94050D61, 0xD812E96F,
+0xB6BD7B12, 0xA5F9BE77, 0x531A5C7A, 0x3605BA71,
+0xD500CE54, 0xE325964C, 0x323432FE, 0x580A9DC8,
+0xD25A3135, 0x089D6C9C, 0x58856F73, 0x7DFCEE30,
+0x7DE2580F, 0xF4E4488B, 0x71821DDF, 0xD194F5DC,
+0x7D070394, 0xBA28BF76, 0xAAF0A38E, 0xD4F6275E,
+0x1B742E66, 0xD9E68EA9, 0x68B0F939, 0x52AF9D7B,
+0x54A39705, 0x20F844C1, 0xE6981DDC, 0x80322E62,
+0x536235B9, 0x7A57F4FC, 0x14EBF376, 0x64BE2E5A,
+0x70A18910, 0x0FE09587, 0x10E9CA78, 0x8F90D3D2,
+0xAE74717D, 0xA544EAED, 0x6746AF3E, 0x430CB3FC,
+0xBC185576, 0xEAA35DC3, 0xDA6309D2, 0x40643F87,
+0x68859117, 0xA17AC84D, 0xD7922CA8, 0xEF7C0BEF,
+0x83337348, 0x9B4B1790, 0x8876A77E, 0xF293C9C7,
+0x20D399CD, 0xA78224BA, 0xFD1279C8, 0x8B7837C1,
+0x0F1DD415, 0xAE3FBD2E, 0xC4F77B52, 0x51E79FB3,
+0x7A856D9D, 0x14BFDAD7, 0x993FB625, 0x667C65EF,
+0x32F83338, 0xAA06EDCE, 0xACE7A099, 0xD26DAE89,
+0xDC6891CE, 0xCD2F6F04, 0x27425FB8, 0x7C301D8D,
+0x1EDEBE1A, 0xBE540AF8, 0x1D356C6A, 0x963E8639,
+0x9920CA55, 0xDEFE5F44, 0x107D5545, 0x3D079BE4,
+0xEF673F66, 0xDB3C2954, 0xDD76D666, 0x1DFBEF59,
+0x8F384B34, 0xBE6F773C, 0x079DD187, 0x2314AC8B,
+0x5FEB0114, 0x59E85CF3, 0x9BFE9190, 0xB360A31B,
+0x4F7EF967, 0xFEB0D561, 0xBFE779F2, 0xF33702B3,
+0xBB263417, 0x09607C65, 0xA877F109, 0xBB43CFF1,
+0x4A190DB2, 0x9B7BD38F, 0xAEB7C449, 0x3DB3A460,
+0x7D928522, 0xD18AC966, 0x187FE766, 0x97629792,
+0xF59D506E, 0x6FBA202C, 0x77035FF3, 0xDA068CDE,
+0xE195779A, 0xAEB92298, 0xD2A44EDD, 0x12577D85,
+0xA3B47B9E, 0x5BD07CB7, 0x4B6AE3FC, 0xBE35B6E2,
+0x9D7F7AF2, 0x9A38EA75, 0xD87FB055, 0x3339F2A3,
+0xD7CB82B4, 0x357721E4, 0xBEF46553, 0x9DE28CA3,
+0x1B1EC2DF, 0xE29B9CC0, 0xEFAE347E, 0xE5864917,
+0xA097B712, 0x6B67041E, 0x5B29542F, 0x01D96EED,
+0xF9A6DC07, 0xC0B5E3F0, 0x21E1899C, 0xE9373A86,
+0xF3176509, 0x950844A2, 0x7D24FFEB, 0x5DC0BCA0,
+0xC442B7C1, 0x37DC6EC1, 0xC65C8BA5, 0x18F0FA85,
+0x2AD80D2D, 0xC68CDCBB, 0x6AE5EC93, 0xE3955DBD,
+0x3E80C4B3, 0x50FED127, 0x743CABC0, 0xD0E91707,
+0x9BF7EB4B, 0x7A632755, 0x9A192482, 0x8F923E9E,
+0xE2E70FE5, 0x5F50AA16, 0x0EC496D1, 0xC6EC4862,
+0x040A0274, 0x2FC951C2, 0xF65D3A80, 0x8D585163,
+0xC6B529D1, 0xD2CAEE6E, 0xE3E112B7, 0x3244312F,
+0x1B393E58, 0x2444D538, 0xBE69AC21, 0xC92A0506,
+0xD1A74434, 0x49C3EA05, 0x0E53B319, 0x3843CE03,
+0x8DB8415E, 0x766B6FC7, 0x515B9E7A, 0x3BA05B32,
+0xBFAFC449, 0x31302A57, 0x1960A211, 0x66A097E0,
+0xBC65A9B4, 0x89E83065, 0x36FDBF2C, 0xDCD4664A,
+0x0ED6CFBF, 0xDD4DC6DC, 0xD76D2F00, 0xB6DA6540,
+0x9A396444, 0x28F185DE, 0xA0FEFA1D, 0xF476E0ED,
+0xEF15505A, 0x183365BF, 0x481FFD90, 0x29ABEE75,
+0x1EC90B07, 0xC10B2657, 0x0DBF6DDB, 0x52AD02B7,
+0xE87DDB54, 0xD3704106, 0xD4E2C592, 0x0CB2DD05,
+0x4BAA2FFB, 0x02611368, 0xD50F8F1C, 0x416FF25C,
+0x9A69782D, 0x268C6474, 0x2ECD4D64, 0x196DE2F5,
+0x47A8561C, 0x8C7CE6C9, 0xD2B1E2D2, 0xA038C165,
+0x3AB8844B, 0x4A699830, 0x0FFC0B17, 0x89B685AA,
+0xDA276D85, 0xE934C4CD, 0xF511226F, 0x9CDD2B1F,
+0x94F75492, 0x55ECEB42, 0x42F0A3D3, 0xD7EB482C,
+0xA78D0373, 0x62F088A6, 0x7ECF4602, 0x7A3404B6,
+0x40B36495, 0x60441DF4, 0x6722F539, 0xCFE76C48,
+0xB6B94C9F, 0x9ADB4B6A, 0x1EBBA65F, 0x5B5081AF,
+0xB764423C, 0xB6F910E3, 0x14AC4B6F, 0x5C811E82,
+0xAA36E5F1, 0x24EC82AF, 0xA2F1C050, 0x0504324C,
+0x304CED0F, 0x01E31DD9, 0xC82EC7E6, 0xD55AFFF9,
+0xFFB3047B, 0x3006F2E9, 0xC725BCD1, 0x7DCC1082,
+0xA9A22CF8, 0x64D5AF9D, 0x389C34AD, 0x7DFF37C6,
+0x41F1509D, 0x1845B3FE, 0x055C23F0, 0xC6291F5F,
+0xCDD3C7DD, 0x5F0356B4, 0x7FD2C387, 0x494A091E,
+0x50C69D3E, 0xFE769A5A, 0x63904701, 0x8960ABF2,
+0xE68EDF3A, 0x0AB57C8E, 0x0B9D0A6C, 0x51888148,
+0x50C5D533, 0xC69038FA, 0x3ACBE661, 0x0CAEB601,
+0x8C14AB6C, 0xBA86D94F, 0x0724056B, 0x0FEFFCBA,
+0x12449DDB, 0xABFFECCE, 0xB12A2BD7, 0x7260A0E8,
+0xBE184A48, 0xCFD3CA3F, 0xDF088660, 0x78EE9B67,
+0xA9EDB113, 0x4FD5D353, 0x8E348CC6, 0xD578C337,
+0xF0493BE9, 0xCCFB54EC, 0x9CEEF85C, 0x0CAAE15E,
+0x371AD12F, 0x9C5B9270, 0x2495F0DE, 0x06DE2DBB,
+0x911AE7EC, 0xEEDE3363, 0x6DD38D6C, 0x2AF7F3D9,
+0x51C8D118, 0xF23818A7, 0x95438AEA, 0x3A8A798F,
+0x230D2BEF, 0x3D16273C, 0x9C36FF83, 0x785C9537,
+0x3E42AF2F, 0x12A16741, 0xE58D0DC4, 0x33EBEFF9,
+0x6F1972DA, 0x128C9BAA, 0x858D6032, 0xDAF185E1,
+0xAE355065, 0xDE0086F3, 0x0F661A65, 0xF4334169,
+0xB1559BA6, 0x3892109A, 0xE903BA00, 0xAE0CBD58,
+0x073C21A0, 0xFCADB299, 0xB4E39AF1, 0x78475459,
+0xB46DC847, 0xDBA97661, 0x15D118F5, 0x01ED48D0,
+0x99F658BC, 0x399FDC8E, 0x44D4A919, 0x7C2CE4B9,
+0xCA0367CC, 0xCC2B9828, 0x16AACAA6, 0x7AA5B6BA,
+0xFEC77C66, 0x231B22F9, 0xC8BE0D04, 0x6FF2788C,
+0x5F9CEBB5, 0x901EAA5D, 0xDE682BBF, 0x998E70D4,
+0xBD9CCCDA, 0x6995441E, 0x5702F360, 0xBC035EED,
+0x20F60B51, 0xD57361D8, 0xC071113B, 0x73CE6CE4,
+0xC6569DC9, 0xD24B89ED, 0xA6052276, 0x8CEE2026,
+0xFBF5B58E, 0xF692DF81, 0x6B7CDD7C, 0xF5B6C04C,
+0xEC1BBA29, 0xD6AC8CDD, 0x320491F8, 0x1D812AC7,
+0x631B0051, 0xD08A4D2A, 0x569746DD, 0xAA653FCF,
+0xA92E8E70, 0xC59A6705, 0x278EA1FF, 0x63E5FA17,
+0x1C20E82D, 0x550F7CE3, 0x55CED415, 0x5F9C4C4A,
+0x7D746311, 0x5B07976A, 0x12477E31, 0xAB8113AA,
+0x796EDCEA, 0x4A90E4B4, 0xB36E6188, 0xEE7D5E0F,
+0x15CEA060, 0xB81AB2CA, 0x296D22B0, 0xFA0753E2,
+0x0D0D15BB, 0xD4AF8BD7, 0x951FA575, 0xCBEBD58A,
+0x0AF5C362, 0x9EF43FB0, 0xD97E5184, 0xA14469BC,
+0xCAE5D55E, 0x93D4CDF9, 0x95B013A8, 0x6998F35C,
+0xF1DDC0B1, 0x476F9FC7, 0xB6472B70, 0x1D55AC5C,
+0xF0E0C0C8, 0x95372BF5, 0x75CCCDBE, 0x9F9D2003,
+0xCAAD0D51, 0xEE54CC2E, 0xE5EBDBF0, 0x9B248BB3,
+0x4BF07D19, 0x542997E9, 0x17447C4B, 0xCF2B2768,
+0x86118A5B, 0x57579F12, 0xC5CD9E74, 0x97ED5724,
+0x01BD2EE4, 0x2A0403A6, 0x01833741, 0xA1E8D364,
+0x4D1A2EEA, 0x62760377, 0xA10D6861, 0x09C68E2F,
+0xAB482850, 0xACD24B74, 0x5038C8CA, 0x71DE3A93,
+0x671D25E4, 0x9EA7AC1A, 0x3E7287F5, 0x9FC963CF,
+0x73F90AB6, 0xC775D840, 0x00B868D9, 0xF6A9BE3D,
+0x17FFB472, 0x5D2389E3, 0x0D42A149, 0x2FAB1235,
+0x90A7998E, 0xD895F6EE, 0x19921013, 0xEE42EA48,
+0xC5D19A17, 0x5507890A, 0x9F893B29, 0x4FF39F19,
+0xD6EF85AD, 0x3FFB1599, 0xF1761017, 0xFC51B90D,
+0x8F6C566B, 0x44BAC7A4, 0x2B2E3755, 0xABECB8DB,
+0x5C4A1629, 0x837CC4F7, 0x3E732B0A, 0x803CE303,
+0x71865D8D, 0x346665AB, 0x58BF809B, 0x100626AA,
+0x9446AB13, 0xD53ADCDA, 0x75C0BFCD, 0x95853304,
+0xF4758E87, 0xD6B64517, 0x13293D0D, 0xEC9368FB,
+0xD449A2CC, 0xAA17B0BE, 0x9D0B85C0, 0x77BEED16,
+0x7699CAE7, 0xC776D10D, 0x962D48CE, 0x838D00BE,
+0x279AEBF9, 0x22EF837B, 0x58E46DAD, 0xB56B6305,
+0x3232D58B, 0x167969DB, 0x5B63F5B5, 0x7E82B175,
+0x05DDB402, 0x5AB29BBA, 0xF3B627D5, 0x97168C85,
+0xAD9EE022, 0x48F0CEEA, 0x84104C22, 0x690FCC19,
+0xCA2F2474, 0x76F95539, 0x9FD2B987, 0x79EFC557,
+0xCEE5DA4D, 0x27EB98F6, 0xA0628916, 0x8E05614F,
+0x8AC89026, 0x7705135E, 0x3F7E42B8, 0x7BCD773B,
+0xF98B9741, 0xCB8A514E, 0x9298220D, 0x5665FA3A,
+0xE66A1FF7, 0xAC4ECB71, 0xA7E56FEF, 0x9D1EF7F8,
+0x23566B64, 0xB4FE822E, 0x1AA53208, 0xF4545E5D,
+0xEA86C879, 0x18F6B7C2, 0xE10A17AC, 0xBD37011F,
+0xFBDF81B8, 0xA978A4EB, 0xD42437A7, 0x474E6A41,
+0xF8885248, 0xF750BAA9, 0xD238EA62, 0xD69BA74D,
+0x266EC6BF, 0xE7EDE077, 0xE8F0A303, 0x8B56A96D,
+0x41380980, 0xDDF0B16C, 0x00E83594, 0xA503EBF5,
+0x960A258E, 0x499827BD, 0x6C8E6F7B, 0x166C845D,
+0xC842C934, 0xBAEFC699, 0xD9846213, 0x832EC19B,
+0x1EAD7599, 0x221E7EE9, 0x8176A313, 0xB28D8E39,
+0xBAC29A96, 0xB964F91F, 0x3F268150, 0xD4BB7011,
+0x347EC445, 0x7FDC9E82, 0xEB70F4C9, 0xA6F38EBF,
+0x398CF137, 0xD7F88CF5, 0xCBDDCB3F, 0xA0DAFA74,
+0xD29D30AD, 0x822B6919, 0xCE059949, 0x3A946183,
+0xDE4C572D, 0xD1E6D844, 0xC43C7DAC, 0xDBBEEDD0,
+0xA656DF6D, 0x454C22A9, 0x9FA48790, 0x69B04531,
+0x99BB305F, 0x80500F71, 0xFE2363C2, 0xB67F538F,
+0x302EC0C3, 0x4A6E3458, 0x57E4CFD4, 0xE65CDAEB,
+0xF31ABB31, 0x62DF98AC, 0x894AE781, 0xB1588AB1,
+0x45D5CC3E, 0x3520F5B0, 0xC72D0CB7, 0xA1D6CBF9,
+0x742FFA63, 0xA0A5224F, 0x5EA1C85A, 0xB81E9F77,
+0x31D76C4F, 0x525257F5, 0xBFF85009, 0x2125B270,
+0x16E47E6E, 0x9128B981, 0x0D5FBE39, 0xF67A418C,
+0xCF3C71CB, 0xAC04ABE1, 0x9B550AAF, 0xB5077F18,
+0xFB7C5EC0, 0x64784DB4, 0x1E668B48, 0x84659836,
+0x604457BF, 0xF6F69C8D, 0x394301DC, 0xED0211BD,
+0x8BAC1A3A, 0xBB752FD2, 0x78B8C036, 0xBCB98E8A,
+0x33C595DE, 0xB3F3C5F8, 0x698666AC, 0xA1F42D7A,
+0x5751ACC8, 0xC069575B, 0x35D50F99, 0xB294BF38,
+0x82A4A331, 0x05147751, 0xCAE18C12, 0x9E89AAF1,
+0x3531C372, 0xB2114A88, 0x41797201, 0xDDDDEC10,
+0x01185F2A, 0xDED50CDC, 0x72156BAD, 0x88F3DB94,
+0x50450DDF, 0x6B1E7ABF, 0x3D317708, 0xFDFF5A15,
+0xDC8B1697, 0xCC2248FD, 0xD9196272, 0x4445195D,
+0x54D90281, 0x7A891C9D, 0x69FF98D5, 0xADE6D74B,
+0x26D27973, 0x0F14734F, 0x3F957FC8, 0x812AC874,
+0xEDC0F9B4, 0xD31D6D75, 0x7A2608C3, 0xD89984B1,
+0xF581081A, 0xEDB9DF6F, 0x16ECC191, 0x6B945724,
+0x1BCE8269, 0x02E6DB68, 0x56362541, 0x9D247CF4,
+0xA5265E72, 0x2C8B9413, 0x1157DB4B, 0x3145CFB2,
+0xFBDEBCF5, 0x1042B117, 0x284DAE18, 0x10575C21,
+0x1DDE578E, 0x80F59EDE, 0xCAB51C04, 0xB594BDA8,
+0x08ACEF85, 0x08C8D4C7, 0x7304D433, 0xE87D3A88,
+0x31CCFED8, 0x1D8E71E5, 0xC5A2F02C, 0xACBF3B5E,
+0xAA161BCA, 0xA10BE577, 0xF9CE41D2, 0x2B86F031,
+0x3D4A8D23, 0xED926DE4, 0x3844E21F, 0xFE57BCD0,
+0x36DC309D, 0x17137409, 0x9F6A8507, 0x14CF12EB,
+0xA770AFB5, 0x7C6DA2E4, 0x856B48B8, 0x2EA235DF,
+0x55BD1164, 0x5BD9FF0C, 0x5228C552, 0x9E719AFA,
+0x3EC3703B, 0xE06A94F3, 0x296FF0D9, 0xE468D9C9,
+0xD2A15CDC, 0x6C4EAAA2, 0x2AF3B8BF, 0x6B6EDC78,
+0x42B78972, 0x4C97A66C, 0x161C30BF, 0xCD2816DC,
+0x431BDA17, 0xD9653022, 0x67D95E39, 0xBCB18342,
+0x227982E7, 0x23C5B11B, 0x514420AB, 0x089F3A5C,
+0x2B2F8244, 0x2F2A80C8, 0xB0A90558, 0x75BAA243,
+0xE2FC4F62, 0xEB0A6104, 0xB7F221B2, 0x4ECD79DF,
+0xB3E08B8B, 0xBA25E1CB, 0xD39F3431, 0xB50202FE,
+0x78F15ECE, 0xEFF61ECF, 0xB3CDDD50, 0x3FD064A8,
+0x96B028BC, 0xB29DD4E1, 0x7E9EC629, 0xC407F4D1,
+0x8C21785B, 0xE11767BA, 0xCFE6DE26, 0x0DA98E22,
+0x33AC5670, 0x0FDBC175, 0xF11F8EF5, 0x60638843,
+0x8B67E55A, 0x3F27F75B, 0x6691FB98, 0x635A35A9,
+0xB317459C, 0xE7419C01, 0x8BAB28D7, 0xE347D791,
+0xEFC019A0, 0x45009041, 0xA6DEB3E8, 0x6F7379FF,
+0x0FF50390, 0x810BEE78, 0xAD13716B, 0xA7DBD7AB,
+0xEF439D4B, 0xDDA744A5, 0x31EDDE8D, 0xA85B71F2,
+0xDF439C70, 0xA7E3DA94, 0x525ED453, 0x3D913C32,
+0xD104CE61, 0x42F5FFED, 0x14C7625A, 0x4E5B314B,
+0xA7EAD1ED, 0xFA01D595, 0xE67BCF06, 0xE63685E2,
+0x3A32E9D3, 0x374C25F0, 0xA8E8A41D, 0xA403AEF5,
+0x901A194C, 0x17605BC9, 0x8522DD12, 0x27096BAA,
+0x017434B7, 0x99C8D2DA, 0x7F96B068, 0x8521CD09,
+0x529B46D6, 0x47852810, 0x021BC8BF, 0x93C98329,
+0x6FE73A78, 0x44DB69A9, 0xC839D490, 0xCAC42AFE,
+0xCF1ECCF4, 0x6F2E5F44, 0x795C8219, 0xA06C667B,
+0x80411F31, 0xB09926E1, 0xC62B6C18, 0x77C6E6DD,
+0x7622FC07, 0x02162DB2, 0x3EA31334, 0x6CC02B4A,
+0xAA6B81C3, 0x4424A9A5, 0x26BD2EF3, 0x334896D6,
+0xADDD2711, 0x76035757, 0x80AA328E, 0x2F39C06E,
+0x357520CB, 0xF62BDF46, 0xC59343C4, 0x7CA4CAE2,
+0x89B03EF3, 0x251A785B, 0xA4755BB9, 0x262D478D,
+0x462E6252, 0x6B5F6BED, 0xCA46E77B, 0xA2CF08AD,
+0x561E19EA, 0xBF31AA15, 0xD376F44C, 0xCC332150,
+0x8C0AEE42, 0xC06D5F91, 0xDADF8613, 0xBE0FA22C,
+0xF50AE482, 0xE3615501, 0xECC8D5AA, 0x58A7FD3E,
+0xD59B8CC9, 0x09DB0987, 0xF1D9753D, 0x9C79E20E,
+0x9A222AEA, 0xC4E58914, 0x6712E0A2, 0x8CD5C80E,
+0xEAB8AA56, 0xDBFA8D9C, 0x3515BD21, 0xB65B9E0C,
+0xF0D27FEE, 0xE33871C1, 0xEE8FE52F, 0x02ACCB3F,
+0xE9197277, 0xB7B70770, 0xA26E3581, 0x82481E7F,
+0x005AF99F, 0x8B970B4B, 0xEC74B662, 0x2F21C5A3,
+0x049DBA83, 0x495B3E1B, 0x112234B8, 0x95B42A5F,
+0x2C8FA833, 0x6D706E30, 0x2AAAEC09, 0xDE7C3377,
+0x06CE9D46, 0x7574EAAB, 0xFCB1A08D, 0x462AFB6C,
+0x192847B2, 0xCC149AC3, 0x427834CE, 0xE90180A0,
+0x946E526E, 0x6018BE4E, 0x20442F52, 0x1D39FA05,
+0x35F690AD, 0x29DB3A53, 0x6360158C, 0x3EC815F8,
+0xDED650AF, 0xFA168B37, 0x233F8A3D, 0x245009CF,
+0x71BB2237, 0x4989A01C, 0xD58AE4F1, 0x62C99EA0,
+0x48E9056E, 0x7E1A786D, 0xBF6CBAAB, 0x22669A6B,
+0x57857590, 0xE4558CE3, 0xBC6C63EC, 0x6AE02A61,
+0xA2ABFBBB, 0xD2B2FE90, 0xDF8BDB43, 0xEC2D59AC,
+0x7B6AFDC3, 0x6B001D5F, 0x3DFEE08F, 0xB9A597D6,
+0x09DEAC68, 0xE42D9E73, 0x2E33507C, 0x6525F051,
+0x0D7143C6, 0x01DD115B, 0x94180279, 0x28FC60D7,
+0xC0900603, 0xED4FBE53, 0xFC0677BD, 0x7DA2A878,
+0xA8D0EC73, 0xF6A09B2A, 0x24A129EE, 0x169BCA2F,
+0xE0BAE526, 0x5C8E2FCB, 0xA218EFFA, 0x842B61FB,
+0x87B860CD, 0x106E9B86, 0x930685F0, 0xC5A72109,
+0xFB977BD5, 0x9D3B4AC6, 0xDA378FE0, 0x0AAF747B,
+0x0408D50D, 0x488785B9, 0x81AE971D, 0x12ADFEF3,
+0xF0B64128, 0x3D4C90BB, 0xC994AAA1, 0xB854400E,
+0x901AE3DD, 0x7A4A0DE7, 0x18E07456, 0x20C38BCD,
+0x94441976, 0xE2E419C2, 0xDBD3C92F, 0x4DD63841,
+0xE2994959, 0xF41F196D, 0x0835431A, 0x93A2E9CF,
+0xB01FABED, 0xD0135535, 0xEBCEA18D, 0xC4F83A1B,
+0x5D72845C, 0x04335E3A, 0x68C4C987, 0x77178710,
+0xC5293A9A, 0x44E40AE1, 0xCE454FDE, 0x71DE89B7,
+0xA373D9D3, 0x6D19E483, 0x812896D6, 0xC3231C14,
+0xE960ABA4, 0xB7FB6F83, 0x1F7C4EB8, 0xD10DBE69,
+0x8575CF6E, 0xC03B15D5, 0x4D7F4EF3, 0xF0615F31,
+0x34E21762, 0x22D5A7A1, 0x729FA3F8, 0x2E1050FB,
+0x8A9F46DC, 0x535EB5A7, 0xD143560E, 0xF8EC3A4B,
+0x2249FD06, 0xE8E2AB08, 0x1E734127, 0xBA5B635A,
+0xD8F419DB, 0x0B5200D0, 0x8110304F, 0x3497DA80,
+0x35CA71CD, 0x0FD8227E, 0x086C74E2, 0xAB68A1AF,
+0xE3BD57EC, 0x83B42D29, 0x3C2D672D, 0x05D85CED,
+0x64F04926, 0x91364A12, 0x7FC73349, 0xEBA1FC77,
+0xECE0D20D, 0xB1DDDB9B, 0xEB6B492B, 0x0FC02BB6,
+0x56201D76, 0xED20F79E, 0xFC6034FB, 0x6A539F1D,
+0x520FECBF, 0x4E3AECF6, 0x76B01C74, 0xEFC421D4,
+0x82AC989A, 0x407A77CD, 0x6D287BFE, 0x26617425,
+0xEA2316C3, 0x8616554E, 0x9F4C4535, 0x88C0C6C1,
+0xEAC4F0F7, 0x32C7DD93, 0x41D9C37E, 0x2A9CBB2E,
+0x0591BAEF, 0x2BE43F21, 0x5E06EE4D, 0xDDDF5525,
+0xEC137DBE, 0xF0AA295C, 0xF2C9FDE2, 0x5DF9D693,
+0x10A6CAC0, 0xC6846D09, 0xF1DDABF3, 0xD56F8BBC,
+0xAA5DCE9D, 0x6F59004F, 0xB8A035BC, 0x61F47282,
+0xC89DAC9E, 0xFC7E5B3D, 0x4C5406DD, 0x54CFD147,
+0xBB44AB2A, 0x791269C0, 0x8CF66B4D, 0xD01A3190,
+0x636F45CA, 0xB32FC209, 0xCB8B9F49, 0xF46D74B9,
+0x5AFC9BD0, 0xC4C716C1, 0xF98C54F3, 0x36AFF013,
+0xB4D6D90B, 0x5F1299B6, 0xA3BFCFA4, 0xEA336AAD,
+0xCCD443DA, 0x74CA40B4, 0x31EF1614, 0x36D3FFEE,
+0x876AE252, 0xC8D62E9F, 0x6424F397, 0x1F730F2D,
+0xB20FDA53, 0xFCFEE60F, 0x676A61C3, 0x26C5E143,
+0xC201573E, 0x4A8C46BE, 0xEF87D0A9, 0xE07E80B4,
+0x34F20109, 0x8B936A70, 0x9F8E0305, 0xF3297CA0,
+0x4E7BF0E9, 0x0F374BB9, 0xCE78A01E, 0x5FE26DD8,
+0xA3826ACF, 0x321F69AB, 0x441AF14E, 0x8AC19CF7,
+0x4BFD1AD6, 0x5951ABD1, 0x098C17F0, 0xA9B75F76,
+0xA462551B, 0x6B703A12, 0xEDCB57B2, 0x8CD4C933,
+0xD338D3D8, 0xE343FC24, 0x9CDD52EB, 0x17A41942,
+0x63A8EF50, 0x215BB11A, 0xE1E25CB6, 0xB62C0A88,
+0xE58CDEC3, 0xC0E6389A, 0x2B7BEE55, 0xA3FCBD07,
+0x7CD451FE, 0xB06F6724, 0x5675A7EA, 0x141D52FC,
+0x05E86E9B, 0x53D75C3A, 0xE799AA2A, 0xE474384C,
+0x8C85E6E6, 0xA477A8D7, 0xA1E6AB0C, 0x9033E7CD,
+0x2F55D504, 0x4DAE81FB, 0xBD229A64, 0x862765C9,
+0x5B6A85F0, 0x95A39328, 0x38826CFB, 0xBF7DEBA4,
+0x42EFAB62, 0x2D0BBA60, 0xB06731AF, 0x16D4C4B0,
+0xCA4B9264, 0x3DF24AE2, 0xFED93848, 0x7CB33B08,
+0xAC9CAE9F, 0xA0F80B61, 0xA66CF713, 0x9364865F,
+0xDFA1E0B3, 0xFE6DF33F, 0x8039A612, 0x119F60BF,
+0xCEEDE309, 0xD28316A8, 0xCD61D2F5, 0x3CBEB015,
+0x85C0BF51, 0x6EDBBC15, 0x79F3D207, 0x485EE4FA,
+0xCEC302EA, 0x59D8B92D, 0x51C1FB36, 0xF4FE8B71,
+0x2DBD5718, 0x84024040, 0xFDD6590F, 0xA1CE9CC9,
+0xC4AEAB72, 0x0A2FE8BF, 0x28C33618, 0xBA4E15FB,
+0xA9C72819, 0xA3EE45D7, 0xD2DC52F1, 0x3FC84A2E,
+0x1C9DF73E, 0x632F9BDE, 0x7E9FBD20, 0x0D689B79,
+0x91E8D5C0, 0x6EE7952C, 0x905F192E, 0x2D79E712,
+0x8670A7A2, 0x1DBFC4D9, 0x64634429, 0xE636043B,
+0x643C6B0F, 0x50AF327B, 0x0E734D61, 0x2D7D6E46,
+0xB877DCD6, 0x7CCF4F1A, 0xDF4D8CF8, 0x0E7FA78E,
+0x0CBC4EC2, 0xAE9B4A22, 0x4F02D49C, 0x48F09C43,
+0x5031B1A0, 0xDCB8A1FC, 0x91C73599, 0xCF00A64D,
+0xDFCE561E, 0x8B18157D, 0xE1ED6A81, 0xCF94EF36,
+0xB412CE1A, 0x602E2076, 0x716B0F3F, 0xADEB32C0,
+0xD4E16094, 0xEC95D41F, 0x75858767, 0x438AD1A1,
+0xE61C5527, 0x0D71FBB2, 0x2A99D070, 0x5C018826,
+0xCCCC27FD, 0x053883D9, 0xF1D30EF5, 0x676AD38A,
+0xDF81AB28, 0x2257FB9D, 0x373313AE, 0x67E1FE8A,
+0xF4F66B02, 0xAFF8C7FA, 0x3B60D94D, 0xD44D0FE2,
+0x5FCDFE4B, 0xC63010B6, 0x06CFCCF4, 0x09D8DD85,
+0xAB79F2BE, 0xD5C0C498, 0x7364E4FD, 0xB295CEDF,
+0xDB89A068, 0x59A6A0C7, 0x0C823207, 0x7380FCFE,
+0x6E33C4B9, 0x0744E4F2, 0xF663BB33, 0x9EE512CE,
+0x870ED35B, 0xB4502654, 0x367CD4FD, 0x5D4238D9,
+0xEAB2B86E, 0x6E8ADDAA, 0xF080EDD6, 0x1DC90F46,
+0xB1FC9127, 0x63771392, 0x96729BF6, 0xD18E1413,
+0x5D85938D, 0xB8CED349, 0xF9B886C1, 0xCA486562,
+0xBAA9ED7A, 0x049718D8, 0x7CF8E67A, 0x1702843C,
+0x6DCDC34E, 0x93C51F83, 0x2415A4F3, 0xA8D77B3A,
+0x0FB823E8, 0x424F03C3, 0x9CAA503C, 0x7AA5433F,
+0x3BDD74FE, 0x99D3332E, 0x1E62231B, 0x90A4E595,
+0x7EDA974D, 0x43E2CD14, 0x27DB9D9F, 0x561F5CC6,
+0xA77EABA6, 0x97867B48, 0xAD6533CE, 0xEB726CF4,
+0x5857B217, 0x2D7DA10B, 0xD939C20E, 0x81F1F073,
+0xF42DEAF2, 0x3AD7780E, 0x88C77661, 0xD2E819B2,
+0xF872F581, 0x999F0C5A, 0x3887ABA4, 0x27F95B6D,
+0x991D9458, 0x9D1BB131, 0x6ECC5298, 0x9E9A7B26,
+0x6E65F271, 0xE90FA04C, 0x7B692AA0, 0x878943D5,
+0x924895E5, 0x041BC73A, 0x448E28B2, 0x61D22D1F,
+0xE7969773, 0xBC8E5980, 0x9A198852, 0xB94415C9,
+0xA02374BA, 0x340BD5F3, 0x27F2A0FF, 0x39BDB33F,
+0xCC042BCF, 0x83D6C135, 0x9C7A8D8E, 0x05823C23,
+0x2D7A3F91, 0xE792BCCA, 0xA2D82177, 0x73C82E7E,
+0xBEBC9613, 0x9F596CB0, 0x6E784AA7, 0x1B7BDA9F,
+0x846391F7, 0x852AD070, 0xF831E8CA, 0x16A78223,
+0xF68F5250, 0xE2554493, 0xD38F2AFB, 0x764BA7A8,
+0x3CAEFC55, 0x6E9B9037, 0xD87D486E, 0x7352AEA9,
+0x11987EE0, 0xDF7E84DA, 0x2838E736, 0xA8C7BAC2,
+0xF49E21EE, 0xFAD106E9, 0x7363AC6F, 0x5E9974CB,
+0xBA008BB0, 0xAF5DB3FC, 0x7AC3CFD7, 0x2D55EDC6,
+0x2C1C9AD7, 0x6A3AA494, 0x5F0E0A3A, 0x37422BFA,
+0x83B4D594, 0xB7ECCF66, 0x82FCCDD0, 0x8ECBFD79,
+0x664B9341, 0x02F178A2, 0x2095C8E0, 0xFC5F17B7,
+0x1810BA9B, 0x964E4CD1, 0xFBAED808, 0xDEE87796,
+0x63DE4F69, 0xC99275DD, 0x65242304, 0x7AB5C28B,
+0x01BB7A3B, 0xC85D7716, 0x32AFB9A3, 0x2ED2CBB1,
+0xB194218F, 0x21FE560D, 0xCB4503A5, 0x5CE0464D,
+0xC4AE9A3C, 0x061530CB, 0xEDA38E6B, 0x4029D3E6,
+0xB0C20336, 0xA37825C0, 0xC68F8B37, 0x9405AD3B,
+0x8B1A8F99, 0xA761DE8B, 0x683B3259, 0xA154C554,
+0x6BD835C9, 0x6DEAE35A, 0xBEAE6D49, 0x21D8B074,
+0x46C01B31, 0xBE9B3A16, 0x1D611EAA, 0x423AB74C,
+0x931F5AF5, 0xBB9E289A, 0xA4101132, 0x4A8BE0D7,
+0x3307E4B2, 0xDE78DB5E, 0x347EB5CE, 0x13EEE999,
+0x2C2D7955, 0xBA893EBA, 0x5DFC2EC1, 0xE7DD7A5F,
+0x5E1C64D8, 0x4552E447, 0x1837D8E4, 0x9711836B,
+0x3219F893, 0x04392C84, 0x3E94848C, 0x15E5F481,
+0x0EC58819, 0x7341D458, 0x4AE63711, 0x85C1FD1F,
+0x97B58BD7, 0xB0550EBE, 0xB9108743, 0x6F53B386,
+0x7A73F31B, 0xE07CF8B9, 0x61FF27C8, 0x06A9A8B4,
+0xEB0F2BB9, 0x46D275FB, 0xCF39B474, 0xC34F3B6D,
+0x52F2F119, 0xD87963BF, 0xC60BF16C, 0x7797D0AD,
+0x7EA4DBF0, 0xD21409C7, 0xF678A927, 0x638E67CD,
+0x93261AED, 0xEA9B25FE, 0x1EBCAFDC, 0x580CC829,
+0x58D1DA1A, 0x658881F8, 0xC48DB682, 0xD42E8CB4,
+0x1DF33D74, 0x31C04F68, 0x7D871E29, 0xAE11FD72,
+0xD7E8F8F6, 0x530D9D9C, 0x580A0715, 0x0F17B1A3,
+0xB863F42F, 0xA6A4DC08, 0x82773E76, 0x9354B309,
+0xE17D0770, 0x04E4DE5B, 0x712EA396, 0x49D37B55,
+0xAE4109BA, 0x03862DC9, 0x7BCF61D2, 0x43CA2017,
+0x23BDD50F, 0x74577459, 0x4E8F4E23, 0xBF924C1A,
+0xE4EC70CE, 0x37FBEC66, 0xA6DA8935, 0xE11F4090,
+0x5C8F9EE3, 0x19D167EC, 0x9EE4F2C5, 0x64A81E6C,
+0xB35642BB, 0x82083A01, 0x001CA1F6, 0xAA69C7E8,
+0x685F24D9, 0xE6868E31, 0x38ADD8F0, 0xA2FDD44E,
+0xEE0C491D, 0xC60B1E9A, 0xF7A89268, 0xFD784F35,
+0xC6B7335C, 0x75EFCEC1, 0xE2D9F7CF, 0xE1C364F8,
+0x7CC63B2C, 0xC179E2AD, 0x56C193A5, 0x5134FB69,
+0x35058BB5, 0x36F4BCD5, 0xDF4A08C2, 0x14AA2330,
+0x760C8CD8, 0x2C562394, 0x0BEB669B, 0x2301973A,
+0xAF5C4FF2, 0x1C770AAB, 0x25DD2087, 0x732AADC4,
+0x59054958, 0x59DDCBE4, 0x74CFC8A8, 0x7C015016,
+0x32A0276E, 0x8F1C2E93, 0x0CE91F71, 0x055C307A,
+0x435D967E, 0xF4C33704, 0x5BDF2AD7, 0x8855099C,
+0x307B2736, 0xBB6B19CB, 0x626349D3, 0x8F52ABFA,
+0x251A1ED6, 0xE0587BC0, 0x12831408, 0xDA83CABF,
+0xAB2C7DFD, 0x6BCF0271, 0x72058DF0, 0x17AFC1DD,
+0xFFC52C30, 0x551401E0, 0x9EED54DF, 0x14E951E4,
+0x14624B3F, 0x4C24650B, 0x5A65F86B, 0xE94F6143,
+0xDC7CE9CF, 0x94D5D8F3, 0x093B0A04, 0x22098D01,
+0xEDF09E7C, 0x165EDB0F, 0xD09CA774, 0xB96AA141,
+0xB5745978, 0x9D820434, 0x42B0E026, 0x96938A25,
+0x72E8634B, 0xBE36EC02, 0x42F3F74B, 0x358FA621,
+0xBD451484, 0xB43A75D1, 0xB0A57F91, 0x701A7C82,
+0x484B3F46, 0x047F78AD, 0x65F7371C, 0xEAC8A954,
+0xE59F6354, 0x3EEEFB4E, 0xF131954B, 0x1C00BAC2,
+0xE3897637, 0x5FEC83AB, 0x58CFA2C4, 0x1F4C0A6A,
+0x97956BC6, 0x63D11D7D, 0xB46179D0, 0x11039A75,
+0x1B50E088, 0x68E9476B, 0xAA68DB55, 0x8A4A051E,
+0xEFA0DDF5, 0x05A2A674, 0xFFE03E72, 0xC5A0295C,
+0x6FD4D834, 0x8E42BB94, 0xF3DFD88E, 0xBA691AD2,
+0x3458473E, 0x6269A348, 0x72962FB6, 0x86D5064B,
+0x8A153740, 0x54AC97D8, 0xED2CE057, 0x68200474,
+0xBBA8E19D, 0xBFDD08F3, 0xB0DF76D1, 0x62F29649,
+0x5AB77030, 0x1EE9A00E, 0x7DAB1C90, 0xAB608FFD,
+0x8506A853, 0x75B9339B, 0x1AE0CCBA, 0xFB60BB79,
+0x8650F92F, 0x4819E1F7, 0x0A7045A8, 0xB5BCE5F1,
+0x77A98B27, 0x03DE21E4, 0x3FE3F132, 0x106827EC,
+0xD4DC1469, 0xAAC82F9B, 0x1D5953A1, 0x8034B369,
+0xD4412B6F, 0x90FB9F25, 0x14279070, 0x6D98AF1C,
+0x3D286F37, 0x8324A732, 0x58123E4E, 0xEB051032,
+0xC15CD557, 0xEB82DE99, 0x6213434E, 0x39F0FC9C,
+0x5EBFE1C5, 0x8CEBF470, 0xFF7D8D8A, 0x740A6A3E,
+0x720D080C, 0xB73B74FA, 0x5173F96E, 0x9FC01794,
+0xDABF1C81, 0xCA813295, 0xBEA2DB8D, 0x4C7E0CE4,
+0x8051BA67, 0xE63399E2, 0x83A15EE4, 0x47F4A718,
+0xD8246E6A, 0x0B4F87BE, 0x031648B8, 0x99E3E3E6,
+0x4ABCC64F, 0x52768181, 0xE708372B, 0x2D0B1D2C,
+0x4DF52402, 0x389BE9F6, 0xDE2F3232, 0x5D43D74E,
+0xD37BB898, 0xE7272645, 0x9B5432DA, 0x9D7A9473,
+0xA69628A5, 0x583555A7, 0x255B08BD, 0xAD68EAE3,
+0x1A79982D, 0xACE09726, 0x15E576AD, 0x260EB406,
+0xA7440B46, 0x66B6D317, 0xBE6ECA3B, 0x3ADEA1C1,
+0xD80399C3, 0x0EF198D0, 0xFAEE2010, 0xEF2E8E56,
+0x5B6CC402, 0x3FD27BE2, 0x970AAB5F, 0x618C17C6,
+0x7F5022FB, 0x552FC1FA, 0x5DD82984, 0x09769539,
+0x98812D1F, 0xBD8B2539, 0xD78AD9A6, 0x1CE41D07,
+0x272A0AB7, 0x5CB7E101, 0x6F42D56A, 0x001D930E,
+0x3C17C305, 0x30AAE354, 0x2A4AABE0, 0x922BCB94,
+0x73F34C1C, 0xE07E1501, 0xCB55A3E1, 0x0CDC3669,
+0xD9C07DE7, 0x2DAB82BF, 0x963EACAA, 0x9B05E0F1,
+0xE2DA0EFA, 0x0613BFE5, 0xDFB605E9, 0x5DCCA8FD,
+0x6D433873, 0x81A9B4C5, 0xD1D1CB14, 0x9B6A9906,
+0xC104767C, 0x30101D37, 0x186FBB79, 0x8F95D488,
+0xA3094F43, 0x7F17C981, 0xFD92B3FE, 0xADAB3AB5,
+0x20D1406C, 0x9462C8E7, 0x5D64819D, 0xB3E85196,
+0x67B854FE, 0x7D039FC6, 0xAD98A85E, 0xF672E041,
+0x30FA19A9, 0x4A276EB8, 0xB7041D2E, 0x57BB21E2,
+0x4E251667, 0x15C5401E, 0xDAB59431, 0xD6C6FD1F,
+0x1726EB70, 0x900F4E84, 0xD327DE33, 0x7A0AE04B,
+0x76B1174E, 0xFD547B94, 0x370832DC, 0xDDE65CDD,
+0x74672C02, 0x164703FE, 0x34CAD31F, 0x3E692DED,
+0x4BC38FA5, 0x143F99E5, 0x61BB640E, 0xB957BC8D,
+0xC9DD9E35, 0x2B5CB310, 0xADD6EAD0, 0x91981D46,
+0xED803D57, 0x61D7737C, 0x92D3AC3E, 0x36A034CB,
+0xE1395DC5, 0x5F2070F8, 0xC5EE9F8A, 0x70546B88,
+0xC9EA230C, 0x58DC3073, 0x57CBBEB7, 0xA0B78CFE,
+0x0B3FE75B, 0x07ADACCD, 0xC292C338, 0xD70CD7E5,
+0x729D8F4E, 0x218FA041, 0x10EC1199, 0xAC1EC51D,
+0x5DECC8D1, 0xBA36230A, 0xBC41F5A5, 0x75864896,
+0xB4403D4A, 0xFEEE8F44, 0x8D94A256, 0x62BA0115,
+0x3A570C61, 0x9221C583, 0xD2981A6B, 0xFD8AAF5A,
+0x2A102D59, 0x64083BDD, 0xBD1AADE6, 0x7E6D1E99,
+0x20568A6D, 0x8DFA704B, 0x87D27122, 0x2EFDAB7D,
+0xF3AF9D39, 0xD8DED0B2, 0x2D4B34B9, 0x12F3E32C,
+0xA6BCBE65, 0x680029A1, 0x094B07B3, 0xDA5918ED,
+0xF7D0A86D, 0x1A7E18C8, 0x9285A97F, 0x2040282C,
+0x5B133531, 0xA48237AC, 0x3557BC1B, 0x7E6ED77B,
+0x436234C7, 0x9B2094DE, 0x5D967593, 0x8867D1C4,
+0x88EC3948, 0xE7F84AD4, 0x1871B3E6, 0xE8E992C6,
+0xA16DC2F8, 0x0DFDF590, 0x9B56238D, 0x329017F5,
+0xBF9BD409, 0x68BD9B1C, 0x4036C4FF, 0x3BF6D93C,
+0xAE100602, 0x90B43508, 0xA85B4013, 0x2C66EA54,
+0x227D32D7, 0x0BA526D1, 0x075213B8, 0x1A3DED07,
+0xD458DFFD, 0xDC8ACD43, 0xAC7809AB, 0x2D25408A,
+0xD8F0C887, 0xAD8CD30D, 0x4054F61E, 0xA9F0CCA3,
+0xBFEBD31D, 0x6D2BAB1E, 0xF8E42D8B, 0x6C94A4E4,
+0x1158D2A3, 0x93F44EFE, 0x8AD05A25, 0x8C229D32,
+0xB213D76E, 0xDFE63822, 0x561986EC, 0x806CA082,
+0x6DB3BF8D, 0x1E850D30, 0x8F7A44C0, 0x75BB3328,
+0x86C7BE12, 0xDE5C44BD, 0xDF4D048E, 0x968712C3,
+0xB1B41CF8, 0xCC194FE9, 0xDA2E1A8D, 0x72A08662,
+0x5ABA2536, 0x223E2013, 0xA5A923A5, 0x7565B5DD,
+0xBCA0A2B0, 0x0C29864B, 0xAAD8CB87, 0xE4C7E559,
+0x77E19E51, 0x194E54ED, 0x54DD1B54, 0x0FAD37A7,
+0x0EF6B0E3, 0x0E3A2FC8, 0xA0063995, 0xE17AE20E,
+0xDC11B7F8, 0x85F1A76D, 0xD97858D4, 0xB763E49C,
+0xB5BE7EC4, 0x3CE924C4, 0x4246019D, 0xD33DBB27,
+0x737863A7, 0x32C26BDD, 0x714897A3, 0x36091018,
+0xF26BC990, 0xDDB640B0, 0x448F5B12, 0xD7A5EB4B,
+0x5614EEA4, 0xCA4912FB, 0x011F9D6C, 0xA4FC90AB,
+0x9FB4982D, 0x20AD146F, 0x4B7AB74E, 0x107A9411,
+0x71DBA90A, 0xD510E3D2, 0x248D0D35, 0xB666229E,
+0x61EE1EEA, 0x702031B5, 0x36992A7B, 0xC90C08CB,
+0x6478995A, 0xE6C2BA7A, 0x8A9179AC, 0xC8EE2956,
+0x27B042C8, 0x48DB81D9, 0xAA39F2CB, 0x5E4D5F3C,
+0x24FFD6B9, 0x5B562C2F, 0x00FD33B6, 0x435F5F52,
+0xF392FFC1, 0x0E927C40, 0x5508CBAB, 0x976AA567,
+0xA13E7C52, 0x532109E9, 0x16B9021F, 0x60C615A1,
+0x1D23C258, 0xFD783147, 0x63600FB1, 0xAAA245F0,
+0x9B3DC1E1, 0x7B270D0D, 0x5B1632CE, 0x8B871F7F,
+0xC535EFF8, 0x73109C6A, 0xEB83D02D, 0xF7AE76FB,
+0x2E39E502, 0xA4128216, 0xF90D57E5, 0xFF0C465E,
+0x02008029, 0xE5CBBA1F, 0x4280FA3C, 0xCDBD75C8,
+0xCB4AF342, 0x17695A4E, 0xAA6162B5, 0x8660A679,
+0xD1A8701C, 0x47694CA7, 0xDA8D43FD, 0x44A4BC1B,
+0xAB34B9AA, 0xE55563DD, 0x08D4142B, 0x81197AC8,
+0x997B1DC2, 0x2E7CC50A, 0x7A326A21, 0xA76419DB,
+0xEA8B5428, 0x65729140, 0x051DAF66, 0x8871BCA9,
+0xA175E5BF, 0x60310C98, 0xB7DE8929, 0x35E2459E,
+0x08EB4547, 0x904D7B2B, 0x29382CC4, 0xCEC8664E,
+0x1E8C9C2C, 0x3B942134, 0x9CEC5D55, 0xDA548376,
+0x2E4EFD61, 0x26F65F09, 0x5A3DD7CA, 0x2FD4E58D,
+0x6B71B8C2, 0x13189115, 0x2B5542BA, 0x1CE85C2C,
+0x5B9FE09D, 0x68704BFE, 0xB15313B9, 0x3EF2729E,
+0x583ECC31, 0xA3DED8CA, 0xFCD27C3D, 0x904DAB39,
+0xFE1069A4, 0xE99A57BA, 0x112EB80C, 0xE1483C74,
+0x8A27B0D7, 0xA58F7325, 0x7CD050A1, 0x626D4F3E,
+0x51643657, 0xA967FC59, 0x5BACBC0B, 0x2CF3E459,
+0x7D8988D9, 0x53913DF8, 0x2381A6FC, 0x64D6D441,
+0x48AE9101, 0x185D9539, 0x1B044AEC, 0xB5ABCEDD,
+0xFA8ECA52, 0x8CCDD142, 0x96FD4442, 0xD865FEDF,
+0xCE4EE2FA, 0xA5160AE9, 0xC91B2B3A, 0xF993F45F,
+0x1509132C, 0x920ECC5F, 0xD813DDC1, 0x834B68E4,
+0xD5E876A0, 0x61DE0E41, 0x4C143913, 0xC7293985,
+0x17E226E7, 0x38830927, 0xDC604DF2, 0x799D1430,
+0x846585AB, 0xE5D21E38, 0x6381D136, 0x1B60633B,
+0x23B7AE14, 0x554E53CC, 0x5807A210, 0x30560866,
+0x12F79E62, 0xE27B5D45, 0x3889C1E5, 0x47F845FF,
+0xFFD9DE98, 0xB10E09D2, 0x4A184A72, 0x083D2971,
+0x8AB7478D, 0x92380377, 0x57A724EC, 0xBBBD5CA6,
+0xE2FB9D32, 0xAB6ADFC6, 0x3916DED4, 0x4E19438F,
+0xE21E15CF, 0x6AF4BCC9, 0x8D08924A, 0x1662BAA9,
+0x3064AD27, 0xB86D7EE4, 0x88624C62, 0x1A0BF3E7,
+0xF3E4A287, 0x6787F006, 0x01375D4B, 0x998BB38F,
+0x6D669A29, 0xD760B093, 0xC4768853, 0xF041100F,
+0x35DE10DD, 0xE06C8BB8, 0x2C79A902, 0x60600DAD,
+0x6E11CF5C, 0x18778777, 0x7CCE406C, 0xE54AF2EA,
+0x7472C475, 0x73DBEE7E, 0xE533DC40, 0xB07407DD,
+0xF6ACA8D3, 0xE71BD7D1, 0x4BD3514D, 0xC5C362CA,
+0x0690E5A1, 0x0FFDC8D8, 0x58188645, 0x8636413C,
+0x3412A033, 0xAF4FC340, 0xA5DFEAB8, 0xB87272E3,
+0xA4A9219F, 0x29696E90, 0x35D2F627, 0x8794DBD7,
+0x5D2D87F8, 0xFA73559D, 0x7D22F440, 0xF50197E9,
+0xEB74B829, 0x8F9649CF, 0x16F47D30, 0x5C7D9870,
+0x36FF6C0B, 0x313A92ED, 0x303B3654, 0xE3E33CCA,
+0x02C26ECC, 0x26949920, 0x4445DF20, 0x01FDBC98,
+0x49138C6F, 0x1B5555E2, 0x122B45D2, 0x4B2E0202,
+0x7B6014D4, 0xFAE0CD09, 0x77E165A0, 0xFBE76980,
+0xF5808BD3, 0xFD110E5E, 0x97450E11, 0x297F9B1F,
+0x607A2C41, 0xE384DFC9, 0x25D9A8DC, 0xF919D955,
+0x5E025993, 0xCC318847, 0x9717D2D5, 0x48F0DD1F,
+0x6CC4A8EB, 0x9BD0F4E1, 0x506F2A93, 0x18B8748E,
+0x16FFBA48, 0x552E4955, 0xB963F64F, 0xA1A34AC8,
+0x62E95CC7, 0x4D87EA89, 0x21E8C031, 0xC1F0ED07,
+0x28B7BB22, 0x0B838D04, 0x6361B440, 0xA653521C,
+0x92DA3F78, 0x4241CFED, 0xFAFCBD41, 0x3EFAB6BC,
+0x25F30607, 0x41BB70DA, 0x9FF3440A, 0x2502039E,
+0x3813EC82, 0xC6A4FD6B, 0xF8537C8C, 0x098ED49F,
+0xE0A0BD6E, 0x6BA2F2B3, 0xC35C9D9D, 0x1256E66A,
+0x790B2490, 0xD5C69889, 0x39E712FE, 0xCF73DE0B,
+0x41B3B614, 0x745ABD73, 0x654C79D8, 0x5B15923D,
+0x8C15F218, 0x585CCCF0, 0x624F7B44, 0x76BDDFDB,
+0x96F26B52, 0xE13058A1, 0x086C950E, 0x29519DEA,
+0xA42CFE04, 0x0D7A190B, 0xD0678C6A, 0xABB78679,
+0xBA48A2E4, 0x5F3DA10A, 0x11F04183, 0xAC720A3F,
+0x6A807781, 0x6F146BFB, 0xE8A67934, 0x54578834,
+0xAA60C8F0, 0x2061A1E6, 0x9E87799B, 0x68D91F86,
+0x8974F540, 0xB1C3F101, 0x99C21E56, 0xB57BA73F,
+0x8B2DAA3E, 0xF1E2D24E, 0x48F7D4EE, 0x7039FDB3,
+0xC666EEDC, 0x251F972E, 0x4D53F6BF, 0x6CC73EE7,
+0xCB07F7B9, 0x69ECB8CA, 0x363FD80C, 0x3B587AB3,
+0x738C1E5C, 0x5C9C1D92, 0xE7B52396, 0xEDE6324B,
+0xFE5B5045, 0xC90D8B3E, 0x371A0128, 0xF2C8DCF8,
+0x5B648CB5, 0x12F8E8FF, 0x5FE4BA71, 0xB925CFBE,
+0x7416E14F, 0x76489FFE, 0x1F4DE367, 0xA400F039,
+0x66390E83, 0x1AE79CEC, 0xDB573E98, 0xB6021F29,
+0xD01615E5, 0x02A2281F, 0xE85019C1, 0x027BB41F,
+0x8D9177C3, 0x79026E78, 0xF158B623, 0xBEFF5858,
+0x7B63518E, 0x8F42C08C, 0xB388227D, 0x940D607A,
+0xA4C79541, 0x9800CC91, 0xA356B535, 0x285BABB9,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xE411E520, 0xA0024528, 0x442B4428, 0x96070009,
+0x46106246, 0x8FFB2522, 0xD4027504, 0x0009AFF5,
+0x00000FB3, 0x00200004, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x16D49357,
+0x0009000B, 0x4F222FE6, 0xDE947FFC, 0xE114D594,
+0x1E13D494, 0x67521E4C, 0xD494D693, 0x37402769,
+0x62528F06, 0x7201D692, 0x60602522, 0x2600C93F,
+0xD7906152, 0x2512611D, 0x264B6652, 0x2562470B,
+0x0009B00D, 0xE60095AC, 0xC84060E2, 0x2F028F03,
+0x8FF93652, 0x7F047601, 0xA05A4F26, 0x4F226EF6,
+0x410BD185, 0xD4850009, 0x0009440B, 0x450BD584,
+0xD7840009, 0xD284E1FF, 0x2712611D, 0xD4835029,
+0xE1FFCB01, 0x1209E501, 0x12112212, 0xE7202452,
+0x4718D57F, 0x2572D27F, 0xD17FE700, 0xD680D47F,
+0xE2012270, 0x24702172, 0xD67E2620, 0x2641E4FF,
+0xD57DE600, 0x666DE104, 0x76016063, 0x4000626D,
+0x8FF83212, 0xD5790545, 0x2520E201, 0xD279D778,
+0x2710E100, 0xE5802212, 0x655C6613, 0x666DD476,
+0x76046763, 0x374C626D, 0x8FF83253, 0xD4732712,
+0xD573E101, 0xD6732410, 0x2542E400, 0xE03AE501,
+0xD272D771, 0xE0390654, 0x27110654, 0x000B4F26,
+0x7FC82211, 0xD76FD16E, 0xDC70DB6F, 0xD271DE70,
+0xD572D471, 0x1F12D672, 0x1F76710C, 0x1FB877FC,
+0x1FEA1FC9, 0x72041F2B, 0xDE6FDC6E, 0x1F13EB10,
+0x1F511F44, 0x1F771F65, 0xD86C1F2C, 0xDD6DD96C,
+0xD26DEA00, 0x89003A22, 0xD1587A01, 0x88016010,
+0x56F98B03, 0x4218E201, 0xD1682622, 0x0009410B,
+0x440BD467, 0xD5670009, 0x0009450B, 0x6010D14C,
+0x8B108801, 0xE650D14B, 0x46186212, 0x8B083266,
+0x56FAD147, 0x2120E200, 0xCB016062, 0x2602A003,
+0x72012710, 0x60822122, 0x89098801, 0xE2C8D15A,
+0x622C6612, 0x89033626, 0x6010D158, 0x8BC88801,
+0x51F76792, 0x217252F6, 0xD6555191, 0x55FB2212,
+0x52FC6462, 0x55612542, 0x2252E400, 0x61436643,
+0x05DE6013, 0x36CC4608, 0x02DE2652, 0xC9036021,
+0x8B028801, 0x720162E2, 0x74012E22, 0x36B3664C,
+0x71048FEE, 0x66C2D147, 0x45286512, 0x265B4518,
+0x60822C62, 0x89018801, 0x0009A168, 0x6272D742,
+0x8B132228, 0xD726D541, 0x6552D441, 0x51436672,
+0x316C365C, 0x27622668, 0x14138D05, 0x6262D63D,
+0xB1A57201, 0xD61E2622, 0x2622E200, 0x52916692,
+0x8B013620, 0x0009A144, 0x6061A06E, 0x001C001C,
+0x001D4020, 0x0000B38E, 0xFFFF0000, 0x12340000,
+0x001E1015, 0x00201278, 0x002018A0, 0x00201922,
+0x0020128C, 0x001C3510, 0x001C3624, 0x001E212C,
+0x0020397C, 0x00203514, 0x00203984, 0x00203990,
+0x0020399C, 0x002039F8, 0x002039FC, 0x002039A4,
+0x002039A5, 0x002039A8, 0x00117700, 0x00203A12,
+0x00203578, 0x001142D8, 0x00203A14, 0x00203A16,
+0x001C3D30, 0x00117718, 0x001C3D00, 0x001C1000,
+0x001C36F8, 0x00117734, 0x001C3684, 0x00117710,
+0x001C3520, 0x00117600, 0x00117740, 0x001C1028,
+0x0020358C, 0x002039AC, 0x7FFFFFFF, 0x00201734,
+0x002032BE, 0x002022E8, 0x00203DC0, 0x002039FA,
+0x00203584, 0x002039EC, 0x001C3D2C, 0x001C36B0,
+0x0020351C, 0x0011775C, 0x8801C90F, 0xA0CF8901,
+0xD17C0009, 0x36206212, 0xD47B8904, 0x2421E200,
+0x2162A0CC, 0x6211D179, 0x89012228, 0x0009A0C3,
+0xE202D775, 0x75016571, 0x3123615D, 0x27518D02,
+0x0009A0BC, 0xD27255F2, 0x62226052, 0x40094019,
+0xC90F4009, 0x8F19880A, 0x52F31F2D, 0x40196022,
+0x40094009, 0x8808C90F, 0xA0A78901, 0x60630009,
+0x51F255F8, 0xE701CB01, 0x2502D263, 0xE1002172,
+0x2211D564, 0x74016452, 0x2542A098, 0x8B3F8805,
+0x602252F3, 0x40094019, 0xC90F4009, 0x8B168802,
+0xE5FFD45D, 0x655D6742, 0x8B102758, 0x6272D75B,
+0x8B0C3260, 0x55F257F8, 0x2762E101, 0xD5522512,
+0xD757E400, 0x62722541, 0xA0777201, 0x52F32722,
+0x40196022, 0x40094009, 0x8805C90F, 0x31B38B6E,
+0xD5508B6C, 0x615257F4, 0x7101E240, 0x64722512,
+0x1F4DD14D, 0x42182419, 0x8B033420, 0x6262D64B,
+0x26227201, 0xE200D640, 0x2621B0AA, 0x0009A056,
+0x3123E220, 0x88038B52, 0x52F38B1E, 0x40196022,
+0x40094009, 0x8803C90F, 0xD7418B16, 0x647251F4,
+0x7401D23D, 0x65122742, 0x1F5DE640, 0x46182529,
+0x8B033560, 0x6262D63B, 0x26227201, 0xE200D62E,
+0x2621B086, 0x0009A010, 0xD738D137, 0xD22A6412,
+0xE5007401, 0x21423A76, 0x22518F06, 0xEA00D634,
+0x72016262, 0x2622B074, 0x2FB2D532, 0x95406652,
+0xD4305BF1, 0x36205241, 0x60618910, 0x8B01C803,
+0x2B22E201, 0x8FF54510, 0x57F15664, 0x6272E1F0,
+0x41284118, 0x2722221B, 0x6BF2A008, 0x6BF2A006,
+0xE200D615, 0xD1152621, 0x2121E200, 0xE20256F5,
+0x42186662, 0x26284228, 0x1F6D8D0C, 0xD61FD11E,
+0x460B6511, 0x2008645D, 0x57F58904, 0x6272D11C,
+0x27222219, 0xD11BE201, 0x66122822, 0x8B012668,
+0x0009AE17, 0x450BD518, 0xD1180009, 0xAE10E600,
+0x07D12160, 0x00203A0C, 0x00203A10, 0x00203A18,
+0x001C3DC0, 0x0011772C, 0x001C3B88, 0x002039F4,
+0x0011773C, 0x00117744, 0x0000F000, 0x00117764,
+0x00117748, 0x00117768, 0x0011776C, 0x01FFFFFF,
+0x0011774C, 0x00203584, 0x001142D8, 0x00114774,
+0xFDFFFFFF, 0x00203DC0, 0x0020246C, 0x002039FA,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xD11F7FF4, 0x6212DE1F, 0x67E25411, 0xD41E1F41,
+0x1F722F22, 0x6743D51D, 0x7794D21D, 0x5A425841,
+0x6C726942, 0x6D225B16, 0xE6006052, 0x2502CB20,
+0x7601E540, 0x3253626D, 0x62F28BFB, 0x212255F1,
+0x55F21151, 0x2E52D613, 0x14A21481, 0xD4122492,
+0x11B627C2, 0x674226D2, 0xD911DA10, 0x2A72E801,
+0x1A8C490B, 0x4218E201, 0x7F0C1A2C, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0x000068F6,
+0x001C3B9C, 0x001C3D98, 0x001C3700, 0x001C3500,
+0x001C5960, 0x001C8960, 0x0020358C, 0x001C3D00,
+0x00201610, 0x2F962F86, 0x2FC62FA6, 0x2FE62FD6,
+0x4F124F22, 0x7F884F02, 0xE018DEB2, 0xD4B261E0,
+0x61E30F14, 0x62107101, 0x440BE01C, 0x20080F24,
+0x8F126D03, 0xD4AD1F08, 0x6740DDAD, 0x657CD4AD,
+0x470BD7AD, 0xD2AD0009, 0x621C6120, 0x46086623,
+0x36284608, 0x3D6C4608, 0xE01C1FD8, 0xE58004FC,
+0x604C66E2, 0x3050655C, 0x2D628F17, 0x01FCE018,
+0xDEA3E500, 0x641CA008, 0x6753655D, 0x607037EC,
+0x31DC6153, 0x80147501, 0x3243625D, 0xD49D8BF4,
+0xE200D59D, 0xA27F2421, 0x20082521, 0xE0188B13,
+0xE50001FC, 0xA009DE96, 0x655D641C, 0x32EC6253,
+0x62536722, 0x32DC6672, 0x75041261, 0x3243625D,
+0xA2698BF3, 0x88012D10, 0xE0188B16, 0xE40001FC,
+0x671C2D40, 0x624DDE8A, 0x8B013273, 0x0009A25C,
+0x6DE3644D, 0x7D046243, 0x32EC6643, 0x652236DC,
+0x74086162, 0x2512AFEF, 0x8B198804, 0x01FCE018,
+0x2D70E700, 0x1FD56D1C, 0x627DDE7D, 0x8B0132D3,
+0x0009A242, 0x6173677D, 0x31EC65E3, 0x75046412,
+0x365C6673, 0x61426262, 0x21297708, 0x2412AFED,
+0x8B198805, 0x01FCE018, 0x2D70E700, 0x1FD46D1C,
+0x627DDE6F, 0x8B0132D3, 0x0009A226, 0x6173677D,
+0x31EC65E3, 0x75046412, 0x365C6673, 0x61426262,
+0x212B7708, 0x2412AFED, 0x8B598831, 0x61E6DE67,
+0x61E31F19, 0x64E27104, 0x1F4A6216, 0x1F2B6416,
+0x75E46513, 0x66536712, 0x1F4C7604, 0x64521F7D,
+0xD75F6E66, 0x27E0D25F, 0xDE5F6062, 0xC9013245,
+0x65622E00, 0x4609060A, 0x4609D15C, 0x46094509,
+0x21501F4E, 0xB2B0646D, 0x620D1F6F, 0x8B012228,
+0x0009A1EA, 0xD756DE55, 0x661C61E0, 0x6410D150,
+0x470B654C, 0x7FFC54FF, 0x2FE25EFE, 0x51FE7FFC,
+0x2F12E040, 0x55FBD14F, 0x57FD56FC, 0x04FE410B,
+0xD24D7F08, 0xE11C640D, 0x1D412D10, 0xD44B6522,
+0x67421D52, 0x1D73DE4A, 0xD24A65E2, 0x67221D54,
+0x1D75D249, 0xD2496E22, 0x66221DE6, 0x1D67A1BC,
+0x89018830, 0x0009A08E, 0xE340D538, 0x33FC6156,
+0x23126456, 0x71046153, 0x67521341, 0x13726416,
+0x7EE46E13, 0x65E66212, 0x66E3D731, 0x13246EE2,
+0x760427E0, 0x6062D22F, 0x3255DE2F, 0x2E00C901,
+0x060A6E62, 0xD12D4609, 0x4E094609, 0x13434609,
+0x646D21E0, 0xB2501F5E, 0x620D1F6F, 0x8B012228,
+0x0009A18A, 0xDE25D522, 0x61E06450, 0xD724654C,
+0x470B54FF, 0x7FFC661C, 0x06FEE054, 0x7FFC2F62,
+0xEE4001FE, 0x2F123EFC, 0x55E2D125, 0x57E456E3,
+0x64E2410B, 0xD21C7F08, 0xE11C640D, 0x1D412D10,
+0xD61A6522, 0x67621D52, 0x1D73DE19, 0xD2196EE2,
+0x62221DE4, 0xD2181D25, 0x1D266222, 0x6222D217,
+0x1D27A15A, 0x00117800, 0x00202A18, 0x00203996,
+0x002035BC, 0x00203A7C, 0x002018D0, 0x00203995,
+0x00117804, 0x00203A14, 0x00203A16, 0x00117810,
+0x00203991, 0x10624DD3, 0x00203992, 0x00203993,
+0x00114AA4, 0x00200F68, 0x001C5864, 0x001C6864,
+0x001C7864, 0x001C59BC, 0x001C69BC, 0x001C79BC,
+0x00200FC0, 0x8B048833, 0x470BD7A2, 0xA123EE00,
+0x88282DE0, 0xA0D38901, 0xDE9F0009, 0x62E1E143,
+0x3216E054, 0x0FE68F02, 0x2E21E240, 0x622D62E1,
+0x8B013217, 0x0009A0BC, 0xE50185E1, 0x8B013056,
+0x0009A0B6, 0x2D10E101, 0x64E1B111, 0x06FEE054,
+0x6261E143, 0x3517652D, 0xE6408945, 0x8B0C3563,
+0xE058E41A, 0xE5000F45, 0x72C0E05C, 0x60230F55,
+0x6703C907, 0xA014E060, 0x66530F75, 0x46214621,
+0x46214621, 0x45214621, 0xE0587618, 0x0F654521,
+0xE0034521, 0xE05C2509, 0xE0070F55, 0xE0602209,
+0xE8540F25, 0x858238FC, 0x640D65F3, 0x1844B170,
+0xDD7A8584, 0x85866C0D, 0x610D4C08, 0x410860C3,
+0xE00F0EFE, 0x18154D0B, 0x2E296207, 0x668260C3,
+0x85620FE6, 0x4D0B5185, 0x2E0B600D, 0x548460C3,
+0xB13C0FE6, 0xE05465F3, 0xE5400EFE, 0xE06C62E1,
+0x3653662D, 0x0F668D41, 0xC9036023, 0x40004008,
+0x61036403, 0xD965E070, 0x0F46E5FF, 0xE074655C,
+0x60530F96, 0x6263490B, 0x42214221, 0x42214221,
+0x42006723, 0x4200327C, 0x6C074621, 0x4621E054,
+0x606309FE, 0x4008C903, 0x790630FC, 0x6A036D2D,
+0x65F3E800, 0x64D3B124, 0xE0706EA2, 0x2AE22EC9,
+0x01FE6694, 0x666CE074, 0x470B07FE, 0x2E0B6063,
+0x65F32AE2, 0xB0FA64D3, 0x628D7801, 0x32E3EE06,
+0x7D018FE7, 0x0EFEE054, 0xE05462E1, 0x420006FE,
+0x760C8561, 0x701B302C, 0xE4006103, 0xE70465F3,
+0x68667401, 0x3973694D, 0x8FF92582, 0x65F37504,
+0x641DB0DD, 0x0EFEE054, 0x64E1B09C, 0x0009A054,
+0xD43B56F8, 0xEA01D23B, 0x26A0420B, 0x0009A04C,
+0x06FCE01C, 0x8829606C, 0x5CF88B08, 0xE200D636,
+0x52612C20, 0x642DB04B, 0x0009A03E, 0x666CE681,
+0x8B043060, 0x420BD231, 0xA03554F8, 0xE6820009,
+0x3060666C, 0xD22E8B04, 0x54F8420B, 0x0009A02C,
+0x666CE683, 0x8B0A3060, 0xDA2755F8, 0x2590E900,
+0xD82855A1, 0x2852D628, 0xA01D52A2, 0xE6922620,
+0x3060666C, 0xD2208B08, 0x5C21D824, 0x6CCC52F8,
+0x28C1E600, 0x2260A010, 0x666CE693, 0x8B063060,
+0xD61F59F8, 0xE201EA00, 0xA00529A0, 0xD6162621,
+0xD21DD41C, 0x6562420B, 0x4F067F78, 0x4F264F16,
+0x6DF66EF6, 0x6AF66CF6, 0x000B69F6, 0x4F2268F6,
+0xE240614D, 0x89323123, 0x3127E21F, 0x8B27D713,
+0xD406614D, 0xE00171E0, 0x5671440B, 0x26596507,
+0x1761A025, 0x00200FBC, 0x00117804, 0x00203470,
+0x00203A9C, 0x002018C0, 0x00117800, 0x00115F00,
+0x00116058, 0x0020397C, 0x00203990, 0x00203A1A,
+0x00203A16, 0x00203AB4, 0x002018D0, 0x001C3704,
+0xE001D490, 0x6672440B, 0x26596507, 0x4F262762,
+0x0009000B, 0x614D4F22, 0x3123E240, 0xE21F8912,
+0xD7893127, 0x614D8B08, 0x5671D286, 0x420B71E0,
+0x260BE001, 0x1761A006, 0x6672D282, 0xE001420B,
+0x2762260B, 0x000B4F26, 0xE6400009, 0x46284618,
+0x6252D57E, 0x89FC2268, 0x0009000B, 0x4618E680,
+0xD57A4628, 0x22686252, 0x000B89FC, 0xA0010009,
+0x7201E200, 0x8BFC3242, 0x0009000B, 0x4618E680,
+0xD5734628, 0x22686252, 0x000B8BFC, 0x2FE60009,
+0x7FFC4F22, 0xBFF16E53, 0x61E22F42, 0xE280D66D,
+0x54E11615, 0x16464218, 0x422855E2, 0x57E31657,
+0x16786EF2, 0x26E22E2B, 0x4F267F04, 0x6EF6AFCE,
+0x2FD62FC6, 0x4F222FE6, 0x6C53DD62, 0x6E43BFD6,
+0x2DE2BFBB, 0x0009BFD2, 0x2C1251D5, 0x1C4154D6,
+0x1C5255D7, 0x1C6356D8, 0x6EF64F26, 0x000B6DF6,
+0x61636CF6, 0xA004E600, 0x62564109, 0x24227601,
+0x36127404, 0x000B8BF9, 0xD6530009, 0x8562E500,
+0xA00B674D, 0x655D610D, 0x40006053, 0x305CD44F,
+0x024D4008, 0x3270622D, 0x75018905, 0x3213625D,
+0x000B8BF1, 0x000BE000, 0x2FE6E001, 0x54416743,
+0x4E08EE7F, 0x4E28D246, 0x25E96543, 0x60436E21,
+0x9E7562ED, 0x4529C903, 0xE60032E3, 0x8D456103,
+0x21184509, 0xD23F8B05, 0x002C6053, 0xA08AC93F,
+0x60136603, 0x8B268801, 0x880C6053, 0xD53A8B04,
+0xC93F8453, 0x6603A07F, 0x8B048808, 0x84E2DE36,
+0xA078C93F, 0x880D6603, 0x8B03D633, 0xC93F8461,
+0x6603A071, 0x88096260, 0x622C8F09, 0xE014DE2C,
+0x655C05EC, 0x60233258, 0xA064C93F, 0x60236603,
+0xA060C93F, 0x88026603, 0xE0078B5D, 0x60432509,
+0x8905C810, 0x6053D225, 0xC93F002C, 0x6603A053,
+0x6053DE23, 0xC93F00EC, 0x6603A04D, 0x88016013,
+0x60538B19, 0x8B04880C, 0x8423D21E, 0xA042C93F,
+0x88086603, 0xD51B8B04, 0xC93F8452, 0x6603A03B,
+0xD618880D, 0x84618B03, 0xA034C93F, 0x60606603,
+0xA030C93F, 0x88026603, 0xE0078B2D, 0x60432509,
+0x8923C810, 0x6053DE10, 0xC93F00EC, 0x6603A023,
+0x00000BB8, 0x00203470, 0x001C3704, 0x001C373C,
+0x001C3700, 0x001C370C, 0x00114000, 0x00114008,
+0x001142D8, 0x001142E4, 0x001142E8, 0x001142F5,
+0x001142ED, 0x001142FD, 0x00114309, 0x6053D209,
+0xC93F002C, 0x60136603, 0x8B038802, 0xC8106043,
+0x76028900, 0xC93F6063, 0x40004018, 0x1741240B,
+0x6EF6000B, 0x00114301, 0x0009A16E, 0x2FE62FD6,
+0xDD944F22, 0xA0049EB2, 0xD4930009, 0x420BD293,
+0x62D265D2, 0x8BF822E8, 0x0009A004, 0xD28FD490,
+0x55D1420B, 0x22E852D1, 0xA0048BF8, 0xD48D0009,
+0x420BD28A, 0x52D255D2, 0x8BF822E8, 0x0009A004,
+0xD286D489, 0x55D3420B, 0x22E852D3, 0xA0048BF8,
+0xD4860009, 0x420BD281, 0x52D455D4, 0x8BF822E8,
+0x6EF64F26, 0x6DF6000B, 0x2FD62FC6, 0x4F222FE6,
+0x6E636C73, 0x6D53B01A, 0x64D357F4, 0xB05F65E3,
+0xB07566C3, 0xB0A40009, 0xB0A80009, 0xB0AC0009,
+0xB0AC0009, 0xB0AF0009, 0xB03154F5, 0x6CCD6C03,
+0x4F2660C3, 0x6DF66EF6, 0x6CF6000B, 0x3412D170,
+0xD6700529, 0x2650D770, 0x2742000B, 0x0009A018,
+0x2FD62FC6, 0x4F222FE6, 0x6E636C73, 0x6D53BFEE,
+0x64D357F4, 0xB03365E3, 0xB08D66C3, 0xB00F54F5,
+0x6CCD6C03, 0x4F2660C3, 0x6DF66EF6, 0x6CF6000B,
+0xE503D162, 0xD763D462, 0x21524518, 0x2472000B,
+0xD45FD15E, 0x2162E600, 0x2462000B, 0xBF734F22,
+0xBF73E40A, 0xD25C0009, 0x4118E104, 0xE40AE500,
+0xBF692212, 0xD7592252, 0xCB206072, 0x000B4F26,
+0x4F222702, 0x410BD156, 0xD556E400, 0x4F26452B,
+0xD1552FE6, 0x66126E63, 0x92104418, 0x44084528,
+0x45002629, 0x265B4408, 0x264B4400, 0x21624708,
+0xD14E4708, 0x217227EB, 0x6EF6000B, 0x1FFF03F0,
+0x4F222FE6, 0xE101DE4A, 0xBF3DE40A, 0x67E32E12,
+0xE500776C, 0xE204E130, 0x2752E40A, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x27222712, 0x27522752, 0x27522752, 0x27522752,
+0x27522752, 0x175ABF18, 0x2E62E600, 0x000B4F26,
+0xD2346EF6, 0xE441E101, 0x000B2212, 0xD1322242,
+0xE605D432, 0x000B2162, 0x000B2462, 0xD2300009,
+0xE40AE601, 0x2262AF00, 0x2FC62FB6, 0x2FE62FD6,
+0x7FFC4F22, 0x6C43DB2B, 0xED0060B2, 0x2B02CB03,
+0xC90360B2, 0x6E03A008, 0x89073DC2, 0xE46460B2,
+0xB07CC903, 0x7D016E03, 0x8BF52EE8, 0x8F043DC2,
+0xD4212FE1, 0x460BD621, 0x62F10009, 0x6023622D,
+0x89FFC801, 0x7F046023, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6000B, 0x001C3B88, 0x00203AC8, 0x002018D0,
+0x00203AD0, 0x00203AD8, 0x00203AE0, 0x00203AE8,
+0x0025E720, 0x00203DBC, 0x00203980, 0x001C5968,
+0x001C3B40, 0x000F8000, 0x001D4004, 0x001C3500,
+0x002015E4, 0x00201610, 0x001C5814, 0x001C59D0,
+0x001C5830, 0x001C6268, 0x001C59A4, 0x001C639C,
+0x001C581C, 0x001C5860, 0x00203AF0, 0x002018C0,
+0x8F014411, 0x6043604B, 0x0009000B, 0x5651D52B,
+0x46286052, 0x306C000B, 0x2FC62FB6, 0x2FE62FD6,
+0x4F124F22, 0xBFF14F02, 0x6B036E43, 0xDD25DC24,
+0x0009BFEC, 0x3C0530B8, 0x4609060A, 0x46014609,
+0x020A3D65, 0x42094209, 0x32E24209, 0x4F068BF0,
+0x4F264F16, 0x6DF66EF6, 0x000B6CF6, 0x2FC66BF6,
+0x2FE62FD6, 0x4F124F22, 0xBFCF4F02, 0x6C036E43,
+0xBFCBDD13, 0x30C80009, 0x060A3D05, 0x46094609,
+0x36E24601, 0x4F068BF5, 0x4F264F16, 0x6DF66EF6,
+0x6CF6000B, 0x4F222FE6, 0xE102DE0B, 0xE403E500,
+0xBFB92E12, 0xE6062E52, 0xE7004618, 0x2E62E403,
+0x4F262E72, 0x6EF6AFB0, 0x0009000B, 0x001C1040,
+0xCCCCCCCD, 0x10624DD3, 0x001D4004, 0x2F962F86,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0xE5007F98,
+0x6453E710, 0x6B534728, 0xEE1ADCBC, 0x6153655D,
+0x315C4108, 0x75014108, 0x6043317C, 0x0F16665D,
+0xED0060B3, 0x21B136E3, 0x81128111, 0x11D28113,
+0x11D411D3, 0x74048FEA, 0xD8B167F2, 0x1871D9B1,
+0x58F12872, 0x1981D1B0, 0x59F22982, 0x5DF45AF3,
+0x54F65EF5, 0x21921191, 0x11A211A3, 0x11D411D5,
+0x11E611E7, 0x11481149, 0xDAA855F7, 0x57F8EE00,
+0x52F9DDA7, 0x64E3D6A7, 0x2A521A51, 0xD8A7D9A6,
+0x2D72EAEF, 0x6AAC2622, 0x6DE36EED, 0x61E34D08,
+0x41083DEC, 0x31EC4D08, 0x60B33D9C, 0x2DB14108,
+0xE05081D1, 0xE79F4108, 0x41084008, 0x81D2677C,
+0x318C60B3, 0x3472E200, 0x1DD281D3, 0xD4931D13,
+0x1D248D01, 0x65D3D48F, 0x7E01B0B2, 0x34A264ED,
+0xDA8C8BDA, 0x68A22FD2, 0x4829DD91, 0x64A22D82,
+0x694D7DFC, 0x2D92D286, 0x4E296E22, 0x2DE27D0C,
+0x6AD36822, 0xD784618D, 0x6D722A16, 0xD583D489,
+0x5E7224D2, 0x14E2D688, 0xEE005174, 0x58761414,
+0x1486D186, 0xE7105978, 0x62521498, 0x142A65E3,
+0x64E326E2, 0x644DE600, 0x48086843, 0x4808384C,
+0x6053381C, 0x28B10C86, 0x60B309CE, 0x60538191,
+0x60430ACE, 0x605381A2, 0x60B30DCE, 0x605381D3,
+0x740108CE, 0x09CE1882, 0x19E3624D, 0x32730ACE,
+0x8FE01A64, 0xD96A7504, 0x6C92E003, 0x2CB14018,
+0xDA6F6D92, 0xE05081D1, 0x40086E92, 0x619281E2,
+0x811360B3, 0xE6006492, 0x67921442, 0x17A3D468,
+0xE1FF6892, 0xE7031864, 0x46086563, 0x7501364C,
+0x665D2612, 0x8BF83673, 0xE003DC5A, 0x40186DC2,
+0x6EC22DB1, 0x81E1D25F, 0xEE0061C2, 0x64C21112,
+0x1423E024, 0xD45B65C2, 0x67C215E4, 0x8172E580,
+0x66E368C2, 0x655C8183, 0x6963666D, 0x6A6D7604,
+0x3A53394C, 0x29E28FF8, 0xDC54DB53, 0x740424B2,
+0x7F6824C2, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0x614268F6, 0xC8036011, 0xE5008F03,
+0x3420D23C, 0x60118B06, 0x8802C903, 0xD2398B06,
+0x8B033420, 0x65135612, 0x24225264, 0x6053000B,
+0x2FE62FD6, 0x7FEC4F22, 0x62536E53, 0x6D43E550,
+0x4508E400, 0xE101A001, 0x60435224, 0x81212211,
+0x60538123, 0x56E28122, 0x8BF53620, 0x16E4D238,
+0xE61464F3, 0x65E3420B, 0xE4FC65E1, 0x2E512549,
+0x65F361F1, 0x2F112149, 0xD13154D1, 0xE614410B,
+0x607157D1, 0x2701CB01, 0x7F141DE1, 0x6EF64F26,
+0x6DF6000B, 0x2FE62FD6, 0x7FEC4F22, 0x66536E53,
+0x6D43E5FC, 0x20596061, 0x2601CB01, 0x326052E2,
+0x12E48B06, 0x31E051E2, 0x52D18B04, 0x1E22A002,
+0x5664AFF0, 0x64F3D21E, 0x420BE614, 0x67E165E3,
+0x2719E1FC, 0x67F12E71, 0x271954D1, 0x65F3D118,
+0x410BE614, 0x52D12F71, 0xCB016021, 0x1DE12201,
+0x4F267F14, 0x000B6EF6, 0x00006DF6, 0x002039AC,
+0x0020357C, 0x00203584, 0x0020358C, 0x002035B4,
+0x00203998, 0x002039A0, 0x00100208, 0x001014C0,
+0x001E210C, 0x001C3D00, 0x002039EC, 0x001000C8,
+0x00117880, 0x00117780, 0x00040020, 0x0026C401,
+0x00200D42, 0x4F222FE6, 0xDE42624C, 0x42004208,
+0x3E2CA005, 0xD4405252, 0xBF695624, 0x65E22E62,
+0x352052E1, 0xD63D8BF6, 0x4F262622, 0x6EF6000B,
+0x2FC62FB6, 0x2FE62FD6, 0xDC394F22, 0x52C1DB39,
+0x362066C2, 0x6061891C, 0x8801C903, 0xDE348918,
+0xBF38DD35, 0x650364E3, 0x66B28503, 0x3262620D,
+0xD4328907, 0x0009BF76, 0x4D0BD431, 0xAFE60009,
+0xBF3D0009, 0xD42F64E3, 0x00094D0B, 0x0009AFDF,
+0x2262D22D, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x2FD62FC6, 0x4F222FE6, 0xDD29DC28, 0x6E4360C2,
+0x04DE4008, 0xE614D127, 0x65E3410B, 0xD127D726,
+0x55E227E2, 0x35E05254, 0x21228F04, 0x400860C2,
+0x122202DE, 0x605365C2, 0x75014008, 0x0DE606DE,
+0xC90F6053, 0x60632C02, 0x6EF64F26, 0x000B6DF6,
+0x85436CF6, 0x650D5643, 0x622D6262, 0x35277204,
+0xE1008F0C, 0x2268960C, 0xD6158B03, 0x72015261,
+0xD6131621, 0x6262E101, 0x26227201, 0x6013000B,
+0x000001FF, 0x0020358C, 0x00203584, 0x001C3D00,
+0x002035B4, 0x0020397C, 0x002018C0, 0x0020357C,
+0x00203B18, 0x00203B1C, 0x001C3D28, 0x002039EC,
+0x002039AC, 0x00200D42, 0x002039F0, 0x002039F4,
+0x00117754, 0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6,
+0x7FF84F22, 0x6C22D241, 0xC80360C3, 0xDE40896E,
+0xDA41DB40, 0x52B1D941, 0x362066B2, 0x60618945,
+0x8801C903, 0xDD3B8941, 0x420BD23D, 0x650364D3,
+0x60A12F02, 0x89328801, 0x85145153, 0x8840600C,
+0x1F118F0C, 0xD5376191, 0x641D450B, 0x8B262008,
+0xD7356691, 0x646D470B, 0x8B202008, 0x420BD233,
+0x51F154F1, 0xC8208511, 0xD1318904, 0x021EE050,
+0x01267201, 0x420BD22F, 0x200864F2, 0x64D38907,
+0x4D0BDD2D, 0xD12D65F2, 0xAFC4E601, 0xD22C2162,
+0x420B65F2, 0xD72B64E3, 0xAFBCE601, 0xD2262762,
+0x420B65F2, 0xAFB664D3, 0xDE270009, 0xDA28DD27,
+0x52D1DB28, 0x362066D2, 0x60618918, 0x8801C903,
+0xD4228914, 0x450BD516, 0x56030009, 0x8F0436E0,
+0xE2016503, 0xAFEC2A20, 0xD41F2B52, 0x420BD216,
+0xD7180009, 0x4118E101, 0x2712AFE3, 0xC80460C3,
+0xD21A8902, 0x0009420B, 0x4F267F08, 0x6DF66EF6,
+0x6BF66CF6, 0x000B6AF6, 0x000069F6, 0x001E2100,
+0x0020358C, 0x00203584, 0x00203A14, 0x001142D8,
+0x002014A6, 0x00115EA2, 0x00114774, 0x00200D8A,
+0x0020351C, 0x002016C2, 0x002014D0, 0x001E212C,
+0x00201534, 0x001C3D30, 0x00117880, 0x0020357C,
+0x0020399C, 0x00203998, 0x002035B4, 0x00200644,
+0xE601D203, 0x1265D503, 0x000B2252, 0x00001266,
+0x001C1010, 0x0000C34F, 0x0009000B, 0x0009000B,
+0x0009000B, 0x0009000B, 0xE000000B, 0xE000000B,
+0x0009000B, 0xE4FDD59D, 0xD69D6152, 0x25122149,
+0x74016052, 0x2502CB01, 0xD19A6752, 0x25722749,
+0xC8406010, 0x60628902, 0x2602CB04, 0xE1F76462,
+0x26422419, 0xE7016062, 0x2602C9CF, 0xE5026062,
+0x2602CB10, 0x47186062, 0x2602CB03, 0x000B1652,
+0xD58D1673, 0xD28ED78D, 0xE100D48E, 0x2511E600,
+0x22102711, 0x2461AFCE, 0xD28B664C, 0x362C4600,
+0xCB106060, 0x2600000B, 0xD287654C, 0x352C4500,
+0xE1EF6650, 0x000B2619, 0x664C2560, 0x4600D283,
+0x6060362C, 0x000BCB10, 0x654C2600, 0x4500D27F,
+0x6650352C, 0x2619E1EF, 0x2560000B, 0xD27A664C,
+0x362C4600, 0xCB086060, 0x2600000B, 0xD276654C,
+0x352C4500, 0xE1F76650, 0x000B2619, 0x664C2560,
+0x4600D272, 0x6060362C, 0x000BCB08, 0x654C2600,
+0x4500D26E, 0x6650352C, 0x2619E1F7, 0x2560000B,
+0xD669624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0x624C600C, 0x4200D664, 0x6020326C,
+0x4021C908, 0x40214021, 0x600C000B, 0x644CD160,
+0x6240341C, 0x602C000B, 0x644CD15E, 0x6240341C,
+0x602C000B, 0x4F222FE6, 0x645C6E43, 0x3467E60A,
+0xBFEB8914, 0x640C0009, 0x880160EC, 0xE00F8B02,
+0x2409A002, 0x44094409, 0xE60A624C, 0x89053263,
+0x644CBFE2, 0x6023620C, 0x8B00C880, 0x6023E200,
+0x000B4F26, 0x4F226EF6, 0x6062D64B, 0x8B038801,
+0x0009B256, 0x0009A003, 0xE640D248, 0xD6482260,
+0x4F26E200, 0x2622000B, 0xD6434F22, 0x88026062,
+0xB29F8B01, 0xD6420009, 0x4F26E200, 0x2622000B,
+0xD43ED53D, 0xE701E100, 0x000B2512, 0xD23B2470,
+0x000BE604, 0x4F222260, 0xD13BD43A, 0x0009410B,
+0xE1FDD53A, 0xD23A6650, 0xE7002619, 0x4F262560,
+0x2270000B, 0xD5374F22, 0x6152D237, 0x611DD737,
+0x64522512, 0x242BE6FF, 0xD4352542, 0x666DD22E,
+0x2762420B, 0xE1FBD52D, 0x27196750, 0x000B4F26,
+0x4F222570, 0xD128D42F, 0x0009410B, 0xE7F7D527,
+0x26796650, 0x000B4F26, 0xD5242560, 0x62509425,
+0x000B2249, 0xD5212520, 0x6250E4BF, 0x000B2249,
+0x4F222520, 0x8522D224, 0x2008600D, 0x88018911,
+0x88038944, 0x88058946, 0x88068948, 0x8808894E,
+0x88098954, 0x880A895A, 0x880B8960, 0xA06D8966,
+0xB06F0009, 0xA06A0009, 0xFF7F600C, 0x001E2148,
+0x001E1108, 0x001E1000, 0x00203A4C, 0x00203A4E,
+0x00203A6D, 0x00203A30, 0x001E103F, 0x001E105F,
+0x001E102F, 0x001E1090, 0x00203A54, 0x001E100B,
+0x00203A50, 0x00203B20, 0x002018C0, 0x001E1028,
+0x00203A6C, 0x001D4020, 0x98760000, 0x001C1000,
+0x00203B2C, 0x00203B3C, 0x00203A24, 0x0009B04C,
+0x600CA035, 0x0009B055, 0x600CA031, 0x6260D684,
+0x8B2B2228, 0x0009B061, 0x600CA029, 0x6260D680,
+0x8B232228, 0x0009B069, 0x600CA021, 0x6260D67C,
+0x8B1B2228, 0x0009B0C7, 0x600CA019, 0x6260D678,
+0x8B132228, 0x0009B0CD, 0x600CA011, 0x6260D674,
+0x8B0B2228, 0x0009B125, 0x600CA009, 0x6260D670,
+0x8B032228, 0x0009B13D, 0x600CA001, 0x4F26E000,
+0x0009000B, 0xD26CD16B, 0xD56C8412, 0x4000C90F,
+0xD76B012D, 0xE403D66B, 0xE20F611C, 0x2540E001,
+0x25202712, 0x2602000B, 0xE601D262, 0x30668523,
+0xE0008D05, 0xD663D260, 0xE0018122, 0x000B2602,
+0xD25C0009, 0x600D8523, 0x89052008, 0x8B0A8801,
+0x6060D65D, 0x2600CB01, 0xD457D65A, 0xE001E101,
+0x000B2612, 0x000B8142, 0xD152E000, 0x8513E501,
+0x640D4518, 0x66033453, 0xE0008D05, 0xD551D253,
+0x2260E001, 0x000B2502, 0x4F220009, 0x8513D149,
+0x6453650D, 0x62494419, 0x227D672E, 0x8801602C,
+0x88028909, 0x88038910, 0x8806891A, 0x88078935,
+0xA04C893B, 0xD5460009, 0x6652D746, 0x2762D446,
+0x622C6261, 0x2421A038, 0x2228625C, 0xD4438B3F,
+0x6642D540, 0x2562D440, 0x24018561, 0x6203A02C,
+0x2008605C, 0x88108907, 0x88208908, 0x88308909,
+0xA02C890A, 0xD23A0009, 0x6222A008, 0xA005D239,
+0xD2396222, 0x6222A002, 0x6262D638, 0xD432D531,
+0x66212522, 0xA00F626C, 0xD6352421, 0x6261D52D,
+0x622CD42D, 0xA0072562, 0xD6322421, 0x8561D529,
+0x2562D429, 0x62032401, 0x662D8515, 0x3617610D,
+0x65038F01, 0xB0CB2451, 0xA0010009, 0xE000E001,
+0x000B4F26, 0xD6190009, 0xD427E101, 0x65412610,
+0xD118D717, 0xE20F655D, 0x2752E001, 0x000B2620,
+0x2FE62102, 0xD20F4F22, 0x640C8523, 0x8B082448,
+0xD511D61D, 0x2621E200, 0x940F8451, 0xA0482049,
+0xDE0D8051, 0xC84060E0, 0xE2018D32, 0x89443427,
+0xD216D615, 0x2641420B, 0x0009A030, 0x0000FF7F,
+0x00203A6D, 0x00203A24, 0x00203A30, 0x001E1100,
+0x001E100C, 0x00203A50, 0x001E1000, 0x001E1001,
+0x00203A58, 0x00203A38, 0x00203A3C, 0x00203A40,
+0x00203A5C, 0x00203A60, 0x00203A64, 0x00203A68,
+0x00203E20, 0x00203E2A, 0x00203A4A, 0x002027F2,
+0x89123427, 0xD294D693, 0x2641420B, 0xCB8084E1,
+0x80E1B0F5, 0xD69160E0, 0x2E00CB04, 0xC93F6060,
+0xD68F2600, 0xA001E001, 0xE0002602, 0x000B4F26,
+0xD68C6EF6, 0xC8806060, 0xD2868919, 0x88016021,
+0xD2898B15, 0x8524E501, 0x89103056, 0xE203D187,
+0x2120D487, 0xE00B6541, 0x0656655D, 0xE40FD585,
+0x2140E702, 0xD77E2571, 0x000BE001, 0x000B2702,
+0x2FE6E000, 0xDE804F22, 0xC88084E1, 0xD57A892C,
+0x20088554, 0x61038F28, 0x8553D77C, 0x64036672,
+0x8566650C, 0x3520620C, 0xD6798B1E, 0x651CD774,
+0x2651644C, 0x60E02741, 0x8904C840, 0x420BD275,
+0xA0030009, 0xD2680009, 0x0009420B, 0x0009B09F,
+0xE201D167, 0x60E02122, 0xCB04D464, 0x60402E00,
+0x2400C93F, 0x6023A001, 0x4F26E000, 0x6EF6000B,
+0x2FB62FA6, 0x2FD62FC6, 0xDA622FE6, 0x66A1E240,
+0x3622DC5E, 0x62638900, 0x6ED36D2C, 0x4E2136D8,
+0x4E212A61, 0xDB61D460, 0xE700A00F, 0x770162B2,
+0x71026123, 0x66212B12, 0x71026213, 0x61212B12,
+0x651D666D, 0x356C4528, 0x627C2452, 0x8BED32E3,
+0xC90360D3, 0x8B108803, 0x617367B2, 0x2B127102,
+0x71026E13, 0x2B126571, 0x655D6DE1, 0x422862DD,
+0x325CE107, 0xA00C2C10, 0x88022422, 0xA0038B01,
+0x8801E203, 0xE2018B05, 0x66B22C20, 0x655D6561,
+0xE60F2452, 0x67A12C60, 0x8B052778, 0xDD38DC44,
+0xEB01EA00, 0x2DB22CA2, 0x6DF66EF6, 0x6BF66CF6,
+0x6AF6000B, 0x2FE62FD6, 0xE240DD36, 0x362266D1,
+0x62638900, 0x3678672C, 0x7703DE38, 0x47212D61,
+0x64E2D635, 0xA00E4721, 0x6562E100, 0x62537101,
+0x74012450, 0x24204219, 0x45297401, 0x74012450,
+0x24504519, 0x621C7401, 0x8BEE3273, 0x66E24200,
+0x420061D1, 0x2118362C, 0x2E628F06, 0xDD1CD728,
+0xE501E400, 0x2D522742, 0x000B6EF6, 0x2FD66DF6,
+0x4F222FE6, 0xED0AEE01, 0x64E3BC86, 0xBC8B64E3,
+0x62EC7E01, 0x8BF732D7, 0xBC8EEE01, 0x64E364E3,
+0x7E01BC93, 0x32D762EC, 0x4F268BF7, 0x000B6EF6,
+0xD1186DF6, 0xD418920D, 0x72122122, 0x2422D617,
+0xD7177204, 0x72202622, 0x2722D116, 0x000B7230,
+0x137A2122, 0x00203A4A, 0x002028FE, 0x001E1015,
+0x00203A50, 0x001E1001, 0x00203A24, 0x001E1100,
+0x00203A4E, 0x00203A3C, 0x001E1000, 0x00203A40,
+0x00203A4C, 0x002027F2, 0x001E100C, 0x00203A38,
+0x00203A54, 0x00203A58, 0x00203A5C, 0x00203A60,
+0x00203A64, 0x00203A68, 0x4F222FE6, 0xD6707FFC,
+0x88016060, 0xE2018951, 0x2620BFBB, 0xD56ED16D,
+0xDE6E6010, 0x64E36552, 0x7402C840, 0x8D22D16C,
+0xD26C7502, 0xE601D76C, 0xE7042722, 0x76016255,
+0x626C2421, 0x8FF93273, 0xD4637402, 0x6242E601,
+0x640D8528, 0x67494419, 0x275D657E, 0x81E4607C,
+0xE417D562, 0x67557601, 0x3243626C, 0x8FF92171,
+0xA0207102, 0xD25E0009, 0xE601D75B, 0xE7042722,
+0x76016255, 0x626C2421, 0x8FF93273, 0xD4527402,
+0x6242E601, 0x640D8528, 0x67494419, 0x275D657E,
+0x81E4607C, 0xE417D553, 0x67557601, 0x3243626C,
+0x8FF92171, 0x92897102, 0xD2462E21, 0x5E23D74E,
+0x64F22FE2, 0x604365F2, 0x2700C980, 0xC9606043,
+0x80716103, 0xC9036043, 0x80724519, 0x65F2605C,
+0x817266F2, 0x46194629, 0x606C4529, 0x4018645C,
+0x8173304C, 0x21185E23, 0x64F22FE2, 0x6E4C62F2,
+0x602C4219, 0x66F262F2, 0x46294018, 0x461930EC,
+0x42298174, 0x652C606C, 0x305C4018, 0x81758F07,
+0x0009BC97, 0x2228620C, 0xA00A8908, 0x60130009,
+0x8B038840, 0x0009B009, 0x0009A003, 0xE202D62F,
+0x7F042622, 0x000B4F26, 0x4F226EF6, 0x8552D52A,
+0x8830600D, 0x88318903, 0xA0348923, 0x85550009,
+0xD428D727, 0x85532701, 0x610DD627, 0x24124118,
+0x460BD426, 0xD7230009, 0xD226D425, 0x6572420B,
+0xE230D120, 0x42286712, 0x2729E620, 0x37604628,
+0xD6218B03, 0xA016E200, 0xD61F2622, 0xA012E202,
+0xD1182622, 0x6212E530, 0xE6204528, 0x46282259,
+0x89083260, 0xD41AD119, 0xE601D513, 0x2160450B,
+0x472BD718, 0x4F264F26, 0x0009000B, 0x0000060A,
+0x00203A6C, 0x001E1000, 0x00203A58, 0x00203E20,
+0x00203E2C, 0x00203DC4, 0x00203A40, 0x00203DF4,
+0x00203DF2, 0x00203DC6, 0x00203A24, 0x00203A50,
+0x00203A3C, 0x00203A38, 0x002018C0, 0x00203B48,
+0x00203B4C, 0x002018D0, 0x00203A54, 0x001E100B,
+0x00203B60, 0x00114004, 0x4F222FE6, 0x84E9DE86,
+0x2448640C, 0xB17B8901, 0xD2840009, 0x26686620,
+0x60E08902, 0x2E00C9BF, 0x000B4F26, 0x000B6EF6,
+0x2FE60009, 0xDE7E4F22, 0x60E0D67E, 0xCBC0D47E,
+0x62602E00, 0xC803602C, 0x40218904, 0x70014021,
+0x6603A002, 0x66034009, 0xD678616D, 0xE500A004,
+0x75016262, 0x74042422, 0x3213625D, 0xD2748BF8,
+0x0009420B, 0xC9BF84E2, 0x4F2680E2, 0x6EF6000B,
+0x2FE62FD6, 0x7FFC4F22, 0x6260D66E, 0x89402228,
+0xD565E100, 0x60502610, 0xCB40D46B, 0x2500440B,
+0x8D052008, 0x62E06E03, 0x7104612C, 0x2F11A006,
+0xD466D65E, 0xDD666760, 0x657C4D0B, 0xE23C6D1D,
+0x8B033D27, 0xD264D463, 0x0009420B, 0x4D214D21,
+0xA005D762, 0x66E6E400, 0x357C4508, 0x74012562,
+0x35D3654D, 0xD75E8BF7, 0x6E72E003, 0x81E14018,
+0x6E7260F1, 0x81E2700C, 0xD45A6172, 0xDD5A8113,
+0x65724D0B, 0xD64AD259, 0x2212E101, 0xC93F6060,
+0x7F042600, 0x6EF64F26, 0x6DF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xD2524F22, 0x6B436E73, 0x420B6C53,
+0x20086D63, 0x64038D1C, 0xE50ED13C, 0x32526210,
+0x60C38916, 0x804124B0, 0x814160D3, 0xA007E500,
+0x655D61BC, 0x00EC6053, 0x364C6653, 0x80647501,
+0x3213625D, 0xD6308BF5, 0xC9BF6060, 0x2600A008,
+0xD239D440, 0x6EF64F26, 0x6CF66DF6, 0x6BF6422B,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x2F962F86,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0xE1007FC4,
+0x6513ECFF, 0x6B136CCD, 0xDE34D733, 0xEDFF64F3,
+0xD833EA04, 0x6053655C, 0x027D4000, 0x32C0622D,
+0x66038D0D, 0x09ED6063, 0x2491027D, 0x24217402,
+0x698202ED, 0x3928622D, 0x74022892, 0x75017104,
+0x6063625C, 0x07D532A2, 0x0EB58FE4, 0x2448641C,
+0xE6808905, 0x67F3E5C5, 0xBF8F666C, 0x7F3C655C,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0xD11C68F6, 0x6012D21C, 0xCB20E405, 0x2102E500,
+0x000B2242, 0x00002252, 0x001E1017, 0x00203996,
+0x001E1015, 0x001E10BF, 0x00117800, 0x001E10FC,
+0x00200644, 0x0020399C, 0x00202A56, 0x00203B64,
+0x002018D0, 0x00203B80, 0x002018C0, 0x0011788C,
+0x00203998, 0x0020357C, 0x00201534, 0x001E2130,
+0x00202A18, 0x00203B88, 0x002039FC, 0x00203A04,
+0x00203DC0, 0x001C3500, 0x001D4004, 0xD564D163,
+0xE400D764, 0x2142E20F, 0x17411154, 0xD5622722,
+0x9669D762, 0x15412572, 0x96661562, 0xE6011565,
+0xD55F1165, 0x666CE6F8, 0x25422542, 0x25422542,
+0x25422542, 0x25622542, 0x7601E727, 0x67632572,
+0x25627797, 0xE7042572, 0x2572E248, 0xE2192522,
+0xE2702522, 0x25422542, 0x25422542, 0x25222542,
+0x2522E20C, 0x25422542, 0x25422542, 0x25422542,
+0x25422542, 0x000B154A, 0xE2081145, 0x0009422B,
+0x2FE62FD6, 0x7FFC4F22, 0xC8206043, 0x6E438D02,
+0x0009BE85, 0xC81060E3, 0xBE828901, 0x60E30009,
+0x8901C840, 0x0009BEA4, 0xC80160E3, 0xDD3D8938,
+0xC80260D0, 0x2F008D03, 0x460BD63B, 0x60F00009,
+0x8902C804, 0x460BD639, 0x62F00009, 0xC8806023,
+0x60D08902, 0x2D00C97F, 0xC8016023, 0xD6348906,
+0x0009460B, 0x0009A007, 0x51630601, 0x8902C808,
+0x460BD630, 0x60F00009, 0x8902C810, 0x420BD22E,
+0xD52E0009, 0x88026052, 0xD22D8B03, 0xA005E604,
+0x88012260, 0xD22A8B02, 0x2260E601, 0x2522E200,
+0xC88060E3, 0xD227892D, 0x60E36E20, 0x8902C880,
+0x420BD225, 0x60E30009, 0x8902C840, 0x420BD223,
+0x60E30009, 0x8902C802, 0x420BD221, 0x60E30009,
+0x890DC804, 0xDD20D11F, 0x0009410B, 0x0009BF11,
+0x0009BF4C, 0xD51ED41D, 0x2470E708, 0x25D2BF85,
+0xC80860E3, 0xD21B8905, 0x4F267F04, 0x422B6EF6,
+0x7F046DF6, 0x6EF64F26, 0x6DF6000B, 0x001C581C,
+0xA000A000, 0x001D0100, 0x001D4000, 0x00040021,
+0x001C589C, 0x001E1021, 0x00201A46, 0x00201A68,
+0x002020C8, 0x00201A80, 0x00201A8E, 0x00203A50,
+0x001E100B, 0x001E1028, 0x00201AFA, 0x00201B06,
+0x00201A96, 0x00201AB4, 0x12345678, 0x001E1000,
+0x0010F100, 0x00201AE2, 0x644CD6A7, 0x000B346C,
+0xD6A62450, 0x346C644C, 0x2450000B, 0x644CD6A4,
+0x000B346C, 0x625C2450, 0x4208616D, 0x42084119,
+0x42006019, 0x670E614C, 0xD49E321C, 0x4200207D,
+0x324CC90F, 0x2200000B, 0x4208625C, 0x42004208,
+0x324C644C, 0x4200D498, 0x000B324C, 0x2FE62260,
+0x614C4F12, 0x4100D493, 0x6710314C, 0xE29F666D,
+0x27294619, 0x6E536269, 0x672E6573, 0x4221227D,
+0x42214221, 0x7601662C, 0xE4014608, 0x34E84608,
+0x644C4600, 0x071A0467, 0x2150257B, 0x000B4F16,
+0x4F226EF6, 0xD2857FE8, 0x88016021, 0xD2848B7B,
+0x26686621, 0xD2838B77, 0x26686621, 0xE50F8B73,
+0xE401BFA2, 0xBFA4E501, 0xE586E400, 0xE400655C,
+0x2F50BFA4, 0xBFA1E401, 0xE602E506, 0x60634618,
+0x81F2E401, 0x6543BF9F, 0xE40185F2, 0xBFAB6543,
+0x85F26603, 0x6543E401, 0x6603BFB1, 0xE40265F0,
+0x6053756C, 0x80F8BF80, 0xBF82E402, 0x84F8E512,
+0x7090E402, 0x6503BF82, 0x4618E602, 0x81F66063,
+0xBF80E402, 0x85F6E500, 0x6603E402, 0xE500BF8C,
+0xE40285F6, 0xBF926603, 0xE5FEE500, 0xE010655C,
+0xBF61E403, 0xE5130F54, 0xE40EBF63, 0x05FCE010,
+0xBF63E40E, 0xE5007585, 0xBF64E403, 0xE500E640,
+0xBF71E403, 0xE500E640, 0xBF78E403, 0xE5FFE640,
+0xE014655C, 0xBF47E404, 0xE40F0F54, 0xE504BF49,
+0x05FCE014, 0xBF49E40F, 0xE5017584, 0xBF4AE640,
+0xE501E404, 0xBF57E640, 0xE501E404, 0xE404E640,
+0xAF5C7F18, 0x7F184F26, 0x000B4F26, 0x4F220009,
+0xD2427FF0, 0x88016021, 0xD2418B71, 0x26686621,
+0xD2408B6D, 0x26686621, 0xE50F8B69, 0xE401BF1C,
+0xBF1EE501, 0xE586E400, 0xE400655C, 0x2F50BF1E,
+0xBF1BE401, 0xE401E506, 0xBF1C6543, 0xE401E640,
+0xBF296543, 0xE401E640, 0xBF306543, 0x65F0E640,
+0x756CE402, 0xBEFF6053, 0xE40280F4, 0xE512BF01,
+0xE40284F4, 0xBF017090, 0xE6406503, 0xBF02E402,
+0xE640E500, 0xBF0FE402, 0xE640E500, 0xBF16E402,
+0xE5FEE500, 0x6053655C, 0xBEE5E403, 0xE51380F8,
+0xE40EBEE7, 0xE40E84F8, 0xBEE77085, 0xE5006503,
+0xBEE8E640, 0xE500E403, 0xBEF5E640, 0xE500E403,
+0xBEFCE640, 0xE5FFE403, 0x6053655C, 0xBECBE404,
+0xE40F80FC, 0xE504BECD, 0xE40F84FC, 0xBECD7083,
+0xE5016503, 0xBECEE640, 0xE501E404, 0xBEDBE640,
+0xE501E404, 0xE404E640, 0xAEE07F10, 0x7F104F26,
+0x000B4F26, 0x00000009, 0x001E102F, 0x001E1080,
+0x001E1090, 0x001E103F, 0x001E103E, 0x00203A4A,
+0x00203A4C, 0x00203A4E, 0xD21DD11C, 0x66206010,
+0x676C7001, 0x3700C90F, 0xE5008D13, 0x67106210,
+0x7701622C, 0x64232170, 0xD6166010, 0x44084408,
+0x3428C90F, 0x62602100, 0x7201D513, 0x44082620,
+0x000B354C, 0xD10F6053, 0x25586510, 0xE6008D13,
+0xD60DD40B, 0x655C6540, 0x47086753, 0x37584708,
+0x47086540, 0x24507501, 0x367C6040, 0x2400C90F,
+0x72FF6210, 0x000B2120, 0x00006063, 0x00203995,
+0x00203994, 0x00203996, 0x002035BC, 0x7FFC4F22,
+0xE680D1A8, 0x666C6212, 0xD2A72F22, 0x67F36563,
+0x420B7542, 0x7F04E404, 0x000B4F26, 0xE6800009,
+0xD2A1666C, 0xE7006563, 0x422B7540, 0xE6806473,
+0xD29D666C, 0xE7006563, 0x422B7543, 0x2F866473,
+0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6, 0x7FC04F22,
+0xDB97D296, 0x72012F22, 0xD1961F21, 0x66125211,
+0x8B013620, 0x0009A0F9, 0xC9036061, 0x8B018801,
+0x0009A0F3, 0xD290DC8F, 0x64C3420B, 0x6503D18F,
+0x60111F02, 0x8B048801, 0x420BD28D, 0xAFE464C3,
+0x54530009, 0x844CEE84, 0x890130E0, 0x0009A0C3,
+0x6610D188, 0x6023626C, 0x8B718801, 0x6210D186,
+0x89662228, 0xDA86D285, 0xE0036122, 0x64221112,
+0x4018D881, 0xDD83E500, 0x814167A3, 0x77042850,
+0x647266A2, 0x6ED3D580, 0x1F457E04, 0x65521F56,
+0x64E368D2, 0x1F8874F8, 0x684369E2, 0x1F637894,
+0x1F991F74, 0x62826142, 0xD779D978, 0x1F2BD679,
+0x67726292, 0x1F1A6062, 0x2602CB20, 0xD176E600,
+0xE5401F57, 0x1F7D1F2C, 0x76011F1E, 0x3253626D,
+0x51F38BFB, 0x52F555F4, 0x25222A12, 0x55F757F6,
+0x27525AF8, 0x5DF92DA2, 0x2ED251FB, 0xD56B5EFA,
+0x54FC24E2, 0x281257FD, 0xD160D869, 0x25722942,
+0x69126782, 0x1974D866, 0xDD666A12, 0x56FE60A1,
+0x2A01CB01, 0xDA646412, 0xE9012842, 0x4A0B2D42,
+0x52FE2692, 0xD661EE01, 0x22E24E18, 0x72016262,
+0x60B22622, 0xCB01D14F, 0x2B02E202, 0x2120A03F,
+0x8B3C2228, 0xE601D55A, 0x2160E700, 0xE01C2572,
+0xC801004C, 0xD8578B0C, 0x1F8FD257, 0xE6002822,
+0x7601E57D, 0x3253626C, 0x56FF8BFB, 0x2622D253,
+0xE2FE69B2, 0x2B922929, 0x0A4CE01E, 0xE01F65F2,
+0x014C25A0, 0x741057F1, 0xEA062710, 0xDD4CE600,
+0x8446DE4C, 0x2D007601, 0x696C6844, 0x2E8039A3,
+0x8FF67E01, 0xDE487D01, 0x2EA0EA94, 0xE1007E01,
+0x7E0F2E10, 0xD12FE205, 0x64102E20, 0x6023624C,
+0x89088801, 0x55F2D22A, 0x64C3420B, 0xEE01D132,
+0xAF1A4E18, 0x55F221E2, 0x8553D13C, 0x620D6612,
+0x89063262, 0xD63BD43A, 0xE801460B, 0xAF0CD73A,
+0xD91F2782, 0x64C3490B, 0xEE01D127, 0xDA38D437,
+0x4A0B4E18, 0xAF0021E2, 0x7F400009, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0x4F2268F6,
+0x85467FF4, 0x2F01E681, 0x666C8547, 0x854881F1,
+0x81F2D209, 0x67F38542, 0x854381F3, 0x81F4E40C,
+0x65636053, 0x420B81F5, 0x7F0C7540, 0x000B4F26,
+0x00000009, 0x001C3D9C, 0x002023FC, 0x0011779A,
+0x001C36F8, 0x002035B4, 0x002014A6, 0x00203A16,
+0x002014D0, 0x002039A5, 0x002039A4, 0x002039A0,
+0x001C3B9C, 0x001C3704, 0x001C3D98, 0x001C3BB4,
+0x001C5960, 0x001C3500, 0x001C3D30, 0x001C8960,
+0x0020358C, 0x001C3D00, 0x00201610, 0x00117730,
+0x002039A8, 0x001C582C, 0x2000A000, 0x0000A000,
+0x0011778C, 0x00117792, 0x00117788, 0x0020397C,
+0x0020357C, 0x00201534, 0x001E2130, 0x00203DA0,
+0x002018C0, 0x2F962F86, 0x2FB62FA6, 0x2FD62FC6,
+0x4F222FE6, 0xD19B7FEC, 0x2F12E000, 0x6103D49A,
+0x1F4281F2, 0xDD9ADA99, 0xD69A6813, 0xE0014808,
+0x460BDE99, 0x38EC4800, 0x65A21F03, 0x352052A1,
+0xA23E8B01, 0x60510009, 0x8801C903, 0xA2388B01,
+0x52530009, 0x32E0DE91, 0xD9918B10, 0x64A3490B,
+0x4B0BDB90, 0xDE906403, 0xD791D690, 0xEC01D591,
+0x2E02E100, 0x271026C0, 0x2502AFDF, 0xC8018551,
+0xA1578B01, 0x62510009, 0x4200622D, 0x5E53366A,
+0x85E2226D, 0xC903642C, 0x85E36603, 0x6053650D,
+0x40214021, 0x4500C93F, 0x322A6703, 0x6053252D,
+0xC901D17F, 0x60106C03, 0x8801D97F, 0xDB7F8B05,
+0x2120E200, 0xCB0160B2, 0xD17D2B02, 0x88016011,
+0x65A28B0A, 0x8D042448, 0x9B9E6251, 0xA00322B9,
+0x919B2521, 0x2521221B, 0x37B3EB10, 0x2448895E,
+0xD4738B07, 0x22286241, 0x60638903, 0xA05781F8,
+0xD5706473, 0x46084608, 0x85E26273, 0x46006B50,
+0x362C4200, 0x2BB8C910, 0x8F1F6463, 0x26686603,
+0xD2698911, 0x062D6043, 0x4119616D, 0x6B0E6019,
+0x81F820BD, 0x880160C3, 0x646C8F2C, 0x880F6073,
+0xA0278B1B, 0xD2610009, 0x052D6043, 0x4119615D,
+0x670E6019, 0x645C207D, 0x81F8A01C, 0x890F2668,
+0x6043D25B, 0x6B5D052D, 0x60B94B19, 0x201D610E,
+0x60C381F8, 0x8F0D8801, 0x6473645C, 0xEC00A00A,
+0x6043D254, 0x625D052D, 0x60294219, 0x207D670E,
+0x81F8645C, 0x880285F8, 0x85E1890A, 0x8D07C820,
+0xE6DC6203, 0x60232269, 0x81E1A002, 0x644CE4FF,
+0x6210D149, 0x89012228, 0x644CE4FF, 0x654DEBFF,
+0x35B06BBC, 0xDB368B2B, 0x64A34B0B, 0x410BD135,
+0x54036403, 0x85446E03, 0xC948DB40, 0xDC408808,
+0xBEAC8B01, 0x64B3E502, 0x65E34C0B, 0xDB3DEC01,
+0xD13D2DC2, 0x621260B2, 0x72017001, 0x21228805,
+0x2B028F08, 0x666CE680, 0x6563D238, 0x7549E700,
+0x6473420B, 0xA030D436, 0x7FFF0009, 0x85E28000,
+0x20B9EBFC, 0x610381E2, 0x942A85E3, 0x62032049,
+0x450885F8, 0x81E2201B, 0xC90160C3, 0x40084018,
+0x40084008, 0x4000225B, 0x6023220B, 0x85E481E3,
+0x4118E108, 0x81E4201B, 0xE40262A2, 0x20B98521,
+0x67A28121, 0xCB016071, 0x85F82701, 0x89033042,
+0xECE785E2, 0x81E220C9, 0x490BD41E, 0xA03B0009,
+0x7E030009, 0x001C3D30, 0x00203DAC, 0x0020358C,
+0x001E212C, 0x00203470, 0x001C3D00, 0x00117780,
+0x002014A6, 0x00201670, 0x0011770C, 0x002039A4,
+0x002039A5, 0x002039A0, 0x002018C0, 0x001C36F8,
+0x00203A1A, 0x00203DBC, 0x00203BA0, 0x00203C20,
+0x00203CA0, 0x00203D20, 0x00203990, 0x00203584,
+0x002014D0, 0x00203A1C, 0x00203A20, 0x002023FC,
+0x00203DA4, 0x00203DA8, 0x602262F2, 0x40094019,
+0xC90F4009, 0x8B0B880A, 0x60E2DE8C, 0x40094019,
+0xC90F4009, 0x8B038808, 0xCB0160A2, 0x2802A006,
+0x65E2DE87, 0x2E527501, 0x286266A2, 0x52F366F2,
+0x2622AE83, 0xD2838551, 0xDE83C802, 0xA0958B01,
+0x420B0009, 0x4E0B64A3, 0x5E036403, 0x85E46503,
+0x4918E908, 0xD77D209B, 0xE04C81E4, 0xDC7C0B7E,
+0x7B01D97C, 0x61C207B6, 0x71016690, 0x8D062668,
+0xD4792C12, 0x420BD279, 0xA070EB01, 0x62512DB2,
+0x4B18EB0F, 0x22B9E102, 0x32104118, 0x85518B0F,
+0x2029E2FC, 0x60518151, 0xCB0172E0, 0x85E12501,
+0x202994A3, 0x85E481E1, 0xA0522049, 0x675181E4,
+0x4719677D, 0x667E6779, 0x7701276D, 0x6903607C,
+0x88014918, 0x25918F3E, 0x6B12D161, 0x21B27B01,
+0x660D85E3, 0x40216063, 0xC93F4021, 0x6C034600,
+0x262D322A, 0xC8016063, 0xDB5ED15D, 0x967D8901,
+0xE6002C6B, 0x666C67CD, 0x40006063, 0x622D021D,
+0x8D0E3270, 0x60436403, 0xE9FF021D, 0x8B013290,
+0x01C5A007, 0x626C7601, 0x3292E904, 0x646C8BEB,
+0x60434400, 0xD15004BD, 0x0B457401, 0x669D6911,
+0x89073670, 0x602D6211, 0x890388FF, 0xE201DB4B,
+0x2B2021C1, 0xECFC8551, 0x815120C9, 0xCB016051,
+0xDC472501, 0x64A34C0B, 0x51F366F2, 0x85EF2612,
+0x54F2D244, 0x650D420B, 0x0009ADE7, 0xE500DC42,
+0x420B2C52, 0x4E0B64A3, 0x54036403, 0x85446E03,
+0x6703E908, 0x65034918, 0x27998541, 0xDB323790,
+0x8F0BD932, 0x6013610D, 0x8B07C820, 0xC9486053,
+0x8B038808, 0xE501BD4B, 0x0009A005, 0x2128D233,
+0xBD448901, 0x64B3E500, 0x490B65E3, 0xADBCEC01,
+0x85F22DC2, 0x7001EE04, 0x31E7610D, 0x8D0281F2,
+0xADA97A08, 0x7F140009, 0x6EF64F26, 0x6CF66DF6,
+0x6AF66BF6, 0x000B69F6, 0xF7FF68F6, 0x2FE68000,
+0xD2234F22, 0x60E36E22, 0x8D02C840, 0xBBE522E2,
+0xE2400009, 0x2E284218, 0xBBF08901, 0x60E30009,
+0x8905C810, 0xD21CD41B, 0x0009420B, 0x0009BBEF,
+0xC80560E3, 0xBD6D8901, 0x60E30009, 0x8902C802,
+0xABEC4F26, 0x4F266EF6, 0x6EF6000B, 0x001C3D3C,
+0x00117760, 0x002014A6, 0x00201670, 0x0020351C,
+0x00203DC0, 0x00203990, 0x00203584, 0x002014D0,
+0x002039FC, 0x00203A04, 0x002039F8, 0x002039FA,
+0x00201534, 0x002018D0, 0x00203A1C, 0x00008000,
+0x001C3510, 0x00203DB4, 0x002018C0, 0x89014F22,
+0x611B600B, 0x611BB00A, 0x000B4F26, 0x600B600B,
+0x611BA004, 0x8DF12107, 0x8BF84011, 0x620D2F26,
+0x8F3E3020, 0x40180019, 0x8B0B3016, 0x31043104,
+0x31043104, 0x31043104, 0x31043104, 0x412462F6,
+0x601C000B, 0x41296219, 0x20084018, 0x31048926,
+0x31043104, 0x31043104, 0x31043104, 0x31043104,
+0x31043104, 0x31043104, 0x31043104, 0x61193104,
+0x3204221D, 0x32043204, 0x32043204, 0x32043204,
+0x32043204, 0x32043204, 0x32043204, 0x32043204,
+0x212D3204, 0x601962F6, 0x4024000B, 0x000BE000,
+0x621362F6, 0x41294228, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x31044224, 0x31044224,
+0x31044224, 0x31044224, 0x602D4224, 0x62F6000B,
+0x080A0C0E, 0x00020406, 0x1A1C1E20, 0x12141618,
+0x2E303234, 0x26282A2C, 0x3A3C3E40, 0x6C625648,
+0x41112F26, 0xE2208F18, 0x890B3123, 0x321CD204,
+0xD1026220, 0x412B312C, 0x00090009, 0x0020349A,
+0x00203450, 0x000BE000, 0x400062F6, 0x40004000,
+0x40004000, 0x40004000, 0x62F6000B, 0x40004000,
+0x40004000, 0x40004000, 0x40184000, 0x62F6000B,
+0x40004000, 0x40004000, 0x40004000, 0x40284000,
+0x62F6000B, 0x40004000, 0x40184000, 0x000B4028,
+0xC90F62F6, 0x40054005, 0x40054005, 0x62F6000B,
+0x4005C907, 0x40054005, 0x62F6000B, 0x4005C903,
+0x000B4005, 0xC90162F6, 0x000B4005, 0x000062F6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x42707372,
+0x3D206675, 0x554E203D, 0x202C4C4C, 0x6E49677A,
+0x4E497274, 0x6D754E51, 0x0000003D, 0x61766E49,
+0x2064696C, 0x72657375, 0x20726F20, 0x2079656B,
+0x00214449, 0x6E6B6E55, 0x206E776F, 0x6D6D6F63,
+0x3D646E61, 0x00000000, 0x203A3051, 0x00000020,
+0x203A3151, 0x00000020, 0x203A3251, 0x00000020,
+0x203A3351, 0x00000020, 0x203A3451, 0x00000020,
+0x2B434741, 0x73696F4E, 0x61432065, 0x7262696C,
+0x6F697461, 0x6166206E, 0x6F206C69, 0x6974206E,
+0x0D0A656D, 0x00000000, 0x00000072, 0x00205220,
+0x62735576, 0x7473725F, 0x00000A0D, 0x62735576,
+0x7375735F, 0x646E6570, 0x00000A0D, 0x62735576,
+0x7365725F, 0x000A0D6D, 0x00000044, 0x44387570,
+0x72637365, 0x6F747069, 0x3D584572, 0x00000000,
+0x00000047, 0x72746E49, 0x6D652051, 0x2C797470,
+0x49677A20, 0x4972746E, 0x754E514E, 0x00003D6D,
+0x654C7245, 0x0000006E, 0x20746F4E, 0x756F6E65,
+0x49206867, 0x4220514E, 0x0A0D6675, 0x00000000,
+0x000000FF, 0x00020001, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00020003, 0x01090108, 0x0002010A,
+0x02000003, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x000000FF, 0x00020001, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00020003, 0x01090108, 0x0002010A,
+0x00030003, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00FF010F, 0x01090108, 0x010B010A,
+0x0200010F, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00FF010F, 0x01090108, 0x010B010A,
+0x010F010F, 0x02020201, 0x02040203, 0x02060205,
+0x02020200, 0x02040203, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00205220, 0x00000046, 0x00000059, 0x73204142,
+0x003D7165, 0x49544120, 0x0000204D, 0x00000000,
+0x00000000, 0x002E0209, 0x80000101, 0x000409FA,
+0x00FF0400, 0x05070000, 0x02000201, 0x82050700,
+0x00020002, 0x03830507, 0x07010040, 0x40030405,
+0x02090100, 0x0101002E, 0x09FA8000, 0x04000004,
+0x000000FF, 0x02010507, 0x07000040, 0x40028205,
+0x05070000, 0x00400383, 0x04050701, 0x00004002,
+0x00000000, 0x00000000, 0x07090000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x6621D2A8, 0x2008606D, 0xA1B18B01, 0x88100009,
+0x88118922, 0x88128920, 0x8813891E, 0x8821891C,
+0x8822891A, 0x883A8918, 0x883B8916, 0xE6448914,
+0x30604608, 0xE6488910, 0x30604608, 0xE658890C,
+0x30604608, 0x963D8908, 0x89053060, 0x3060963B,
+0x96398902, 0x8B013060, 0xE010000B, 0x8B018820,
+0xE020000B, 0x892B8837, 0x89298832, 0x89278835,
+0x89258836, 0x89238830, 0x89218838, 0x891F8839,
+0x891D8834, 0x891B8833, 0x4608E64C, 0x89173060,
+0x3060961B, 0x96198914, 0x89113060, 0x30609617,
+0x9615890E, 0x890B3060, 0x30609613, 0x96118908,
+0x89053060, 0x3060960F, 0x960D8902, 0x8B0C3060,
+0xE030000B, 0x05100165, 0x02300A10, 0x04300330,
+0x06300530, 0x0B300A30, 0x88400C30, 0xA1428B01,
+0x88410009, 0xA13E8B01, 0x88430009, 0xA13A8B01,
+0x88480009, 0xA1368B01, 0x884A0009, 0xA1328B01,
+0x884B0009, 0xA12E8B01, 0x884C0009, 0xA12A8B01,
+0xE6800009, 0x3060666C, 0xA1248B01, 0xE6810009,
+0x3060666C, 0xA11E8B01, 0xE6820009, 0x3060666C,
+0xA1188B01, 0xE6830009, 0x3060666C, 0xA1128B01,
+0xE6840009, 0x3060666C, 0xA10C8B01, 0xE6850009,
+0x3060666C, 0xA1068B01, 0xE6860009, 0x3060666C,
+0xA1008B01, 0xE6870009, 0x3060666C, 0xA0FA8B01,
+0xE6880009, 0x3060666C, 0xA0F48B01, 0xE6890009,
+0x3060666C, 0xA0EE8B01, 0xE68A0009, 0x3060666C,
+0xA0E88B01, 0xE68B0009, 0x3060666C, 0xA0E28B01,
+0xE68C0009, 0x3060666C, 0xA0DC8B01, 0xE68D0009,
+0x3060666C, 0xA0D68B01, 0xE68E0009, 0x3060666C,
+0xA0D08B01, 0xE68F0009, 0x3060666C, 0xA0CA8B01,
+0xE6900009, 0x3060666C, 0xA0C48B01, 0xE6910009,
+0x3060666C, 0xA0BE8B01, 0xE6F80009, 0x3060666C,
+0xA0B88B01, 0xE6F90009, 0x3060666C, 0xA0B28B01,
+0xE6FA0009, 0x3060666C, 0xA0AC8B01, 0xE6FB0009,
+0x3060666C, 0xA0A68B01, 0xE6FC0009, 0x3060666C,
+0xA0A08B01, 0xE6FD0009, 0x3060666C, 0xA09A8B01,
+0xE6FE0009, 0x3060666C, 0xA0948B01, 0xE6FF0009,
+0x3060666C, 0xA08E8B01, 0xE6D00009, 0x3060666C,
+0xA0888B01, 0xE6D10009, 0x3060666C, 0xA0828B01,
+0xE6D20009, 0x3060666C, 0xA07C8B01, 0xE6D30009,
+0x3060666C, 0xE6D48977, 0x3060666C, 0xE6D58973,
+0x3060666C, 0xE6D6896F, 0x3060666C, 0xE6D7896B,
+0x3060666C, 0xE6D88967, 0x3060666C, 0xA0038963,
+0x00000009, 0x00114000, 0x666CE6D9, 0x895A3060,
+0x666CE6DA, 0x89563060, 0x666CE6DB, 0x89523060,
+0x666CE6DC, 0x894E3060, 0x666CE6DD, 0x894A3060,
+0x666CE6F0, 0x89463060, 0x666CE6F1, 0x89423060,
+0x666CE6F2, 0x893E3060, 0x666CE6F3, 0x893A3060,
+0x666CE6F4, 0x89363060, 0x666CE6F5, 0x89323060,
+0x666CE6F6, 0x892E3060, 0x666CE6F7, 0x892A3060,
+0x4608E650, 0x89263060, 0x3060969A, 0x96988923,
+0x89203060, 0x30609696, 0x9694891D, 0x891A3060,
+0x30609692, 0x96908917, 0x89143060, 0x3060968E,
+0x968C8911, 0x890E3060, 0x3060968A, 0x9688890B,
+0x89083060, 0x30609686, 0x96848905, 0x89023060,
+0x30609682, 0x000B8B01, 0xE0FFE040, 0x600C000B,
+0xE000000B, 0x6243D157, 0xE4028512, 0x662D670D,
+0xE500A00E, 0x6053655D, 0x305C4000, 0x4008D152,
+0x622D021D, 0x8B023260, 0xA0047108, 0x7501041C,
+0x3273625D, 0x60438BEE, 0xC90A000B, 0x674C76FE,
+0x025C606C, 0x3723622C, 0x20088906, 0x70FF8902,
+0x6603AFF6, 0xE000000B, 0x0009000B, 0x4F124F22,
+0x326052F2, 0x34508910, 0x3470890E, 0x3750890D,
+0x3268890A, 0x04273458, 0x60733758, 0x440BD43B,
+0x306C011A, 0x6203A001, 0x4F166263, 0x000B4F26,
+0x2FE66023, 0x4F124F22, 0x6E434F02, 0x614C54F4,
+0x2F164118, 0x666C677C, 0x64EC655C, 0x46184718,
+0xBFD34518, 0x65034418, 0x60537F04, 0xC980E702,
+0x6E034718, 0x37ED4728, 0x62594519, 0x010A652E,
+0x312C225D, 0x4F06601C, 0x4F264F16, 0x6EF6000B,
+0x03400240, 0x05400440, 0x07400640, 0x09400840,
+0x11400B40, 0x0A401240, 0x4F220A50, 0x614C8451,
+0x3127620C, 0xA00C8901, 0x8452E400, 0x3127620C,
+0xA0068901, 0x8453E401, 0x3127620C, 0xE4038D01,
+0x6263E402, 0x60437201, 0x677C072C, 0x62532F76,
+0x072C7201, 0x055C066C, 0x666C677C, 0xBFA8655C,
+0x7F046413, 0x000B4F26, 0x605C600C, 0x8F068801,
+0x606C6243, 0x8B018801, 0x720AA001, 0x000B72F6,
+0x00006023, 0x00114000, 0x00114008, 0x00203374,
+0xE040D690, 0x056E614C, 0x9274D78F, 0x352C357C,
+0xE400E718, 0x626C6650, 0x89043120, 0x624C7401,
+0x8FF73273, 0x000B7501, 0xE2FF6043, 0x622C644C,
+0x890D3420, 0x8801605C, 0x965D8B03, 0xA005346C,
+0x62436243, 0x324C4208, 0x326C9657, 0x6023000B,
+0x6043000B, 0x2F962F86, 0x2FB62FA6, 0x2FD62FC6,
+0x4F222FE6, 0x92497FF4, 0x6B533526, 0x00296943,
+0xE13FCA01, 0x6E03EAFF, 0x6AAC2F10, 0x6D43EC00,
+0x62D0E808, 0x34A0642C, 0xBFCE8939, 0x3B0065E3,
+0x6CCC8F0A, 0x420062C3, 0x362C6693, 0x1FC18461,
+0x4109610C, 0x2F10A02D, 0x891C2CC8, 0x65E364D0,
+0x644CBFBB, 0x89163B02, 0x70FF60C3, 0x049C4000,
+0x644C65E3, 0x1F02BFB1, 0x8D1A30B2, 0x56F21FC1,
+0x356C6593, 0xC9038451, 0x89122008, 0x660C8451,
+0xA00E4609, 0x7C012F60, 0x328362CC, 0x8FC87D02,
+0xA0061F21, 0x06250009, 0x12C008FC, 0x62CC09B4,
+0x50F11F21, 0x8B128808, 0x7CFF6CCC, 0x60C34C00,
+0x65E3049C, 0x644CBF89, 0x8B083B06, 0x849139CC,
+0x2008C903, 0x84918903, 0x4209620C, 0x60F02F20,
+0x4F267F0C, 0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6,
+0x68F6000B, 0x2F962F86, 0x2FB62FA6, 0x2FD62FC6,
+0x4F222FE6, 0x92727FFC, 0x3426E100, 0x6B436953,
+0x2F12666C, 0xCA010029, 0x8D032668, 0xE2F06E03,
+0x2F22622C, 0x6AACEAFF, 0x6C93ED00, 0x66C0E808,
+0x34A0646C, 0xBF508913, 0x3B0065E3, 0x6DDC8B0A,
+0x39DC4D00, 0xC9038491, 0x8B082008, 0xCB0F60F2,
+0x2F02A005, 0x62DC7D01, 0x8FE83283, 0x60F27C02,
+0x4F267F04, 0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6,
+0x68F6000B, 0x2F962F86, 0x2FB62FA6, 0x2FD62FC6,
+0x4F222FE6, 0x4F024F12, 0x3F3C9332, 0x4308E35B,
+0x605333FC, 0x80341351, 0xE7606063, 0x80381362,
+0x4708E012, 0xE03F8136, 0xD11237FC, 0x27008138,
+0x80788074, 0xE9166053, 0x60638012, 0x21414918,
+0x6B938013, 0xEDFF6AB4, 0x6AAC61B0, 0x6C1C4A18,
+0x68C82CAB, 0x6DDD688D, 0x234238D0, 0x8B131398,
+0xD207D406, 0x0009420B, 0x432BD306, 0x09B40009,
+0x0000FE10, 0x001142D8, 0x000DDD00, 0x001160B0,
+0x002018C0, 0x00115E88, 0x342292E3, 0x8F02E100,
+0xA1616593, 0x92DD0009, 0x352CE7FF, 0xEE04677C,
+0x622C6250, 0x89043270, 0x621C7101, 0x8FF732E3,
+0xE8FC7501, 0x3488688C, 0x9ACBE064, 0x40086893,
+0x0F4438AC, 0x661C6583, 0x644CBE18, 0x64E36E0C,
+0x65E37401, 0x45086643, 0x35EC4608, 0x4508364C,
+0x45004608, 0x369C4600, 0x61A39AB5, 0xE0656763,
+0x400837AC, 0x62637114, 0x321C0F76, 0x94AB7004,
+0x61430F26, 0x359C6263, 0x7004324C, 0x0F267114,
+0x7004361C, 0x0F666753, 0x700437AC, 0x7A140F76,
+0x37AC6753, 0x66537004, 0x364C0F76, 0x74147004,
+0x354C0F66, 0x0F567004, 0x395C958F, 0xED006A93,
+0x6BD3E956, 0xEC054908, 0x4008E065, 0x60B302FE,
+0x644C042C, 0x60E32F46, 0xE06A07AC, 0x01FE4008,
+0x061C60B3, 0x058C60E3, 0x4008E065, 0x677C01FC,
+0x655C666C, 0x641CBDED, 0x7F046403, 0x60D36DDC,
+0xE0660F44, 0x04FE4008, 0x054C60B3, 0x2F56655C,
+0x07AC60E3, 0x4008E06B, 0x60B301FE, 0x60E3061C,
+0xE065058C, 0x01FC4008, 0x666C677C, 0xBDD0655C,
+0x6403641C, 0x65F37F04, 0x60D37510, 0xE0650544,
+0x07FE4008, 0x057C60C3, 0x2F56655C, 0x07AC60E3,
+0x4008E06A, 0x60C301FE, 0x60E3061C, 0xE065058C,
+0x01FC4008, 0x666C677C, 0xBDB2655C, 0x6403641C,
+0x61F37F04, 0x60D37120, 0xE0660144, 0x02FE4008,
+0x052C60C3, 0x2F56655C, 0x07AC60E3, 0x4008E06B,
+0x60C301FE, 0x60E3061C, 0xE065058C, 0x01FC4008,
+0x666C677C, 0xBD94655C, 0x6503641C, 0x64F37F04,
+0x60D3349C, 0xE0670454, 0x07FE4008, 0x057C60B3,
+0x2F56655C, 0x07AC60E3, 0x4008E06C, 0xA00501FE,
+0x0BB860B3, 0x03C2013E, 0x013F0462, 0x60E3061C,
+0xE065058C, 0x01FC4008, 0x666C677C, 0xBD70655C,
+0x6203641C, 0xE1B87F04, 0x64F3611C, 0x60D3341C,
+0xE0680424, 0x05FE4008, 0x075C60B3, 0x2F76677C,
+0x07AC60E3, 0x4008E06D, 0x60B301FE, 0x60E3061C,
+0xE065058C, 0x02FC4008, 0x666C677C, 0xBD50655C,
+0x6703642C, 0xE2C07F04, 0x66F3622C, 0x60D3362C,
+0xE0670674, 0x07FE4008, 0x027C60C3, 0x2F26622C,
+0x07AC60E3, 0x4008E06C, 0x60C302FE, 0x60E3062C,
+0xE065058C, 0x02FC4008, 0x666C677C, 0xBD30655C,
+0x6203642C, 0xE7C87F04, 0x66F3677C, 0x60D3367C,
+0xE0680624, 0x06FE4008, 0x026C60C3, 0x2F26622C,
+0x07AC60E3, 0x4008E06D, 0x60C302FE, 0x60E3062C,
+0xE065058C, 0x02FC4008, 0x666C677C, 0xBD10655C,
+0x6103642C, 0x66937F04, 0x62F37608, 0x60D3326C,
+0x02147D01, 0xE60562DC, 0x7C013263, 0x7B018D02,
+0x0009AEFA, 0x0009A17B, 0xE7FF9BD5, 0x677C35BC,
+0x6250EE08, 0x3270622C, 0x71018904, 0x32E3621C,
+0x75018FF7, 0xDDD89CC8, 0x3D4534C8, 0x4008E064,
+0x4E090E0A, 0x0FE46593, 0x702435BC, 0x64EC661C,
+0x0F56BCB4, 0x64E36E0C, 0x65E37401, 0x45086243,
+0x35EC4208, 0x4508324C, 0x45004208, 0x329C4200,
+0x61B37B0C, 0x38BC6823, 0x7114E06E, 0x40086B23,
+0x91A23B1C, 0x70040F86, 0x68236413, 0x0FB6359C,
+0x7004381C, 0x0F867414, 0x7004342C, 0x67539896,
+0x0F466253, 0x7004378C, 0x6B537814, 0x7114321C,
+0x3B8C0F76, 0x351C7004, 0x0FB69789, 0x397C7004,
+0x70040F26, 0xED006893, 0x0F56EC05, 0x6AD3E956,
+0xE06E4908, 0x02FE4008, 0x012C60A3, 0x2F16611C,
+0x078C60E3, 0x4008E073, 0x60A304FE, 0xE06E064C,
+0x0BFE4008, 0x05BC60E3, 0x4008E065, 0x677C01FC,
+0x655C666C, 0x641CBC85, 0x7F046403, 0x60D36DDC,
+0xE06F0F44, 0x04FE4008, 0x054C60A3, 0x2F56655C,
+0x078C60E3, 0x4008E074, 0x60A30BFE, 0xE06E06BC,
+0x0BFE4008, 0x05BC60E3, 0x4008E065, 0x677C01FC,
+0x655C666C, 0x641CBC65, 0x7F046403, 0x751065F3,
+0x054460D3, 0x4008E06E, 0x60C307FE, 0x655C057C,
+0x60E32F56, 0xE073078C, 0x0BFE4008, 0x06BC60C3,
+0x4008E06E, 0x60E301FE, 0xE065051C, 0x0BFC4008,
+0x666C677C, 0xBC44655C, 0x610364BC, 0x6BF37F04,
+0x60D37B20, 0xE06F0B14, 0x01FE4008, 0x041C60C3,
+0x2F46644C, 0x078C60E3, 0x4008E074, 0x60C301FE,
+0xE06E061C, 0x0BFE4008, 0x05BC60E3, 0x4008E065,
+0xA00501FC, 0x0136677C, 0x028212C0, 0x01370142,
+0x655C666C, 0x641CBC1D, 0x7F046203, 0x349C64F3,
+0x042460D3, 0x4008E070, 0x60A304FE, 0x655C054C,
+0x60E32F56, 0xE075078C, 0x0BFE4008, 0x06BC60A3,
+0x4008E06E, 0x60E301FE, 0xE065051C, 0x0BFC4008,
+0x666C677C, 0xBBFC655C, 0x610364BC, 0xEBB87F04,
+0x65F36BBC, 0x60D335BC, 0xE0710514, 0x07FE4008,
+0x047C60A3, 0x2F46644C, 0x078C60E3, 0x4008E076,
+0x60A30BFE, 0xE06E06BC, 0x01FE4008, 0x051C60E3,
+0x4008E065, 0x677C0BFC, 0x655C666C, 0x64BCBBD9,
+0x7F046103, 0x622CE2C0, 0x3B2C6BF3, 0x0B1460D3,
+0x4008E070, 0x60C302FE, 0x677C072C, 0x60E32F76,
+0xE075078C, 0x02FE4008, 0x062C60C3, 0x4008E06E,
+0x60E302FE, 0xE065052C, 0x02FC4008, 0x666C677C,
+0xBBB6655C, 0x6703642C, 0xEBC87F04, 0x66F36BBC,
+0x60D336BC, 0xE0710674, 0x06FE4008, 0x026C60C3,
+0x2F26622C, 0x078C60E3, 0x4008E076, 0x60C302FE,
+0xE06E062C, 0x02FE4008, 0x052C60E3, 0x4008E065,
+0x677C02FC, 0x655C666C, 0x642CBB93, 0x7F046103,
+0x72086293, 0x362C66F3, 0x7D0160D3, 0x62DC0614,
+0x3263E605, 0x8D027C01, 0xAEE27A01, 0x6EF30009,
+0xE2B068F3, 0x6AF3E05A, 0x389C7E18, 0x69F3622C,
+0x7A084008, 0x67F36DF3, 0x392C61F3, 0x6CA30FE6,
+0x77207D10, 0xE4007128, 0xEB0565F3, 0x604C6654,
+0x66D4626C, 0x2E604221, 0x048C6674, 0x626C2C20,
+0x09444221, 0x21207001, 0x32B3620C, 0x71016403,
+0x8FEB7E01, 0xE05A7C01, 0x6EF34008, 0x7E300BFE,
+0xEC19ED00, 0x66B365A3, 0xBB7E64DC, 0x62DC7D01,
+0x2E0032C3, 0x7E018FF6, 0x666CE6B0, 0x6BF36EF3,
+0x7B283E6C, 0xEC4CA010, 0xCCCCCCCD, 0x64D36DDC,
+0x644C74F4, 0xBB6865B3, 0x67F366E3, 0x77306503,
+0x075460D3, 0x62DC7D01, 0x8BEF32C3, 0x7B306BF3,
+0x61B367B3, 0xED8064B3, 0x71027701, 0x6DDC7403,
+0xDC37E500, 0x605CDE37, 0x091C084C, 0x0A7C668C,
+0x699C4628, 0x49284618, 0x05BC6AAC, 0x4A18269B,
+0x70046803, 0x655C26AB, 0x620C38CC, 0x38EC265B,
+0x286232D3, 0x65038FE7, 0x644CE4B8, 0x3C4C6CF3,
+0x6EF37408, 0xE2B0E658, 0x3E4C6AF3, 0x74086BF3,
+0x460861F3, 0x622C68F3, 0x7A0869F3, 0x314C7B18,
+0x386C64F3, 0x6DA3392C, 0x742867B3, 0x66C4E500,
+0x626C605C, 0x422166E4, 0x66142760, 0x2D20058C,
+0x4221626C, 0x70010954, 0x620C2420, 0x3263E605,
+0x74016503, 0x8FEA7701, 0xE05E7D01, 0x02FD4008,
+0x6D2DE9D0, 0x699C7D07, 0xEE00A00B, 0x66B365A3,
+0x64ECBAFB, 0x620367F3, 0x60EC379C, 0x70010724,
+0x62EC6E03, 0x8BF132D3, 0x4008E05F, 0xEAB008FD,
+0x6DF36AAC, 0x6BF36C8D, 0x7C0D3DAC, 0x7B28A012,
+0x0000A280, 0x001BC000, 0x64E36EEC, 0x644C74F4,
+0xBADA65B3, 0x62F366D3, 0x329C6103, 0x7E0160E3,
+0x62EC0214, 0x8BEF32C3, 0x3D9C6DF3, 0x67D36ED3,
+0xEC8061D3, 0x77027E01, 0x6CCC7103, 0xDBB9E400,
+0x604CDAB9, 0x067C041C, 0x08EC654C, 0x666C4528,
+0x46284518, 0x09DC688C, 0x4818256B, 0x70046603,
+0x699C258B, 0x620C36BC, 0x36AC259B, 0x265232C3,
+0x64038FE7, 0x4008E064, 0x70E007FC, 0x706C0CFC,
+0x0F8668CC, 0x0DFC7098, 0x6ADC706C, 0x708C0FA6,
+0x9BBF0EFE, 0xE2543EB2, 0x697CE100, 0x42088F02,
+0x0009A163, 0x4008E063, 0x6EF305FE, 0x3E2C96B3,
+0x64E3356C, 0xEDFFE703, 0x32D06250, 0x622C8D07,
+0x681C7101, 0x24203873, 0x8FF57505, 0xE0647401,
+0x0AFC4008, 0x64AC65E3, 0x661CBA18, 0xE063670C,
+0x62734008, 0x42080BFE, 0x7701327C, 0x3A2C6AB3,
+0x48086873, 0x948F6EA3, 0x3E4C387C, 0x3B8C74FF,
+0x38283A4C, 0xEC003B4C, 0x6083DD88, 0x655C05EC,
+0xE0652F56, 0x67B04008, 0x65A066E4, 0x677C01FC,
+0x655C666C, 0x641CBA1D, 0x7C017F04, 0xE40462CC,
+0x2D003243, 0x7D018FE9, 0xE063E554, 0x67F34508,
+0x375C4008, 0x966805FE, 0x356CEDFF, 0x6DDC6473,
+0xEE04E100, 0x666C6650, 0x890636D0, 0x621C7101,
+0x246032E3, 0x8FF57505, 0xE0647401, 0x02FC4008,
+0x642C6573, 0x661CB9CA, 0x6E23620C, 0xE0634E08,
+0x72013E2C, 0x0BFE4008, 0x47086723, 0x6AB3372C,
+0x68733AEC, 0x6EA338E8, 0x3E1C9140, 0x3B7C71FF,
+0x3B1C3A1C, 0x0F96704C, 0xEC00E904, 0x6083DD60,
+0x644C04EC, 0xE0652F46, 0x67B04008, 0x65A066E4,
+0x677C01FC, 0x655C666C, 0x641CB9CB, 0x7C017F04,
+0x329362CC, 0x8FEA2D00, 0xE0767D01, 0x09FE4008,
+0x70B4E454, 0x67F34408, 0x374C05FE, 0xEDFF9617,
+0x356C6473, 0xE1006DDC, 0x6650EE04, 0x36D0666C,
+0x71018906, 0x32E3621C, 0x75092460, 0x74018FF5,
+0xE064A006, 0x05BA0BB8, 0x05C905BB, 0x05DD05CA,
+0x65734008, 0x661C07FC, 0x647CB970, 0x6623620C,
+0x4608E063, 0x46004008, 0x362C0BFE, 0x68237201,
+0x3A6C6AB3, 0x48004808, 0x91676EA3, 0x3E1C382C,
+0x3B8C71FF, 0x38683A1C, 0xEC003B1C, 0x6083DD35,
+0x644C04EC, 0xE0652F46, 0x67B04008, 0x65A066E4,
+0x677C01FC, 0x655C666C, 0x641CB973, 0x7C017F04,
+0xE50862CC, 0x2D003253, 0x7D018FE9, 0x4008E063,
+0x05FEE654, 0x64F34608, 0xECFF9741, 0x357C346C,
+0xEE006CCC, 0x6250ED04, 0x32C0622C, 0x7E018906,
+0x38D368EC, 0x75092420, 0x74018FF5, 0x4008E077,
+0x700405FE, 0x649306FE, 0xEA54B9A7, 0x65F34A08,
+0x640C35AC, 0x66ECB91A, 0x6613610C, 0x4608E063,
+0x46004008, 0x361C0BFE, 0x68137101, 0x3A6C6AB3,
+0x48004808, 0x92136EA3, 0x3E2C381C, 0x3B8C72FF,
+0x38683A2C, 0xEC003B2C, 0xE077DD0B, 0x05FE4008,
+0x06FE7004, 0x6493B981, 0x0009A010, 0x060105DE,
+0x00000602, 0x0000B280, 0x001BC000, 0x001142E4,
+0x001142E8, 0x001142ED, 0x001142F5, 0x60836403,
+0x677C07EC, 0x67B02F76, 0x65A066E4, 0x666C677C,
+0xB906655C, 0x7F04644C, 0x61CC7C01, 0x3123E208,
+0x8FD22D00, 0xA0FC7D01, 0xE0630009, 0x05FE4008,
+0x96D067F3, 0x356C372C, 0xEEFF6473, 0x32E06250,
+0x622C8D08, 0x681C7101, 0x3863E608, 0x75052420,
+0x74018FF4, 0x4008E064, 0x657302FC, 0xB8B5642C,
+0x650C661C, 0x4008E063, 0x0BFE6253, 0x325C4208,
+0x6AB37501, 0x68533A2C, 0x6EA34808, 0x385C94AC,
+0x74FF3E4C, 0x3A4C3B8C, 0x3B4C3828, 0xDD96EC00,
+0x06EC6083, 0x2F66666C, 0x4008E065, 0x66E467B0,
+0x01FC65A0, 0x666C677C, 0xB8BA655C, 0x7F04641C,
+0x62CC7C01, 0x3243E404, 0x8FE92D00, 0xE5547D01,
+0x4508E063, 0x400867F3, 0x05FE375C, 0xEEFF9685,
+0x6473356C, 0xE1006EEC, 0x666C6650, 0x890736E0,
+0x621C7101, 0x3283E808, 0x75092460, 0x74018FF4,
+0x4008E064, 0x65730AFC, 0xB86764AC, 0x620C661C,
+0xE0636623, 0x40084608, 0x0BFE4600, 0x7201362C,
+0x6AB36823, 0x48083A6C, 0x6EA34800, 0x382C915E,
+0x71FF3E1C, 0x3A1C3B8C, 0x3B1C3868, 0xDD6FEC00,
+0x04EC6083, 0x2F46644C, 0x4008E065, 0x66E467B0,
+0x01FC65A0, 0x666C677C, 0xB86A655C, 0x7F04641C,
+0x62CC7C01, 0x3253E508, 0x8FE92D00, 0xE0637D01,
+0xE6544008, 0x460805FE, 0x973864F3, 0x346CECFF,
+0x6CCC357C, 0xED08EE00, 0x666C6650, 0x890636C0,
+0x62EC7E01, 0x246032D3, 0x8FF57509, 0xE0777401,
+0x05FE4008, 0x06FE7004, 0xB89E6493, 0x4808E854,
+0x358C65F3, 0xB811640C, 0x610C66EC, 0xE0636613,
+0x40084608, 0x0BFE4600, 0x7101361C, 0x6AB36813,
+0x48083A6C, 0x6EA34800, 0x381C920A, 0x72FF3E2C,
+0xA0063B8C, 0x05023A2C, 0x052A0503, 0x0572052B,
+0x38680573, 0xEC003B2C, 0xE077DD41, 0x05FE4008,
+0x06FE7004, 0x6493B871, 0x60836403, 0x677C07EC,
+0x67B02F76, 0x65A066E4, 0x666C677C, 0xB808655C,
+0x7F04644C, 0x61CC7C01, 0x3123E208, 0x8FE42D00,
+0xD3347D01, 0x0009430B, 0xE079620C, 0x0F244008,
+0x88306023, 0xA24D8B01, 0x88400009, 0xA2498B01,
+0x22280009, 0xA2458B01, 0xE5FF0009, 0x655CD42A,
+0xE03AE601, 0x8F043250, 0xE0790464, 0x4008E210,
+0xE05B0F24, 0x05FE4008, 0x3566963B, 0xA1498B01,
+0x60230009, 0x640CCB01, 0x6E23B842, 0xE118660C,
+0x890F3613, 0x4008E063, 0x04FE4608, 0x97294608,
+0x460070E0, 0x05FE347C, 0x346CB85C, 0xE0606203,
+0x0F244008, 0xCB0260E3, 0x640CB82A, 0xE118660C,
+0x890F3613, 0x4008E063, 0x04FE4608, 0x91114608,
+0x460070E0, 0x05FE341C, 0x346CB844, 0xE0616203,
+0x0F244008, 0xCB0560E3, 0x640CB812, 0xA00D660C,
+0x09B4E07A, 0x0000064D, 0x001142FD, 0x00114301,
+0x00114309, 0x00114400, 0x001142D8, 0x4008E118,
+0x8F043613, 0xE0610F64, 0xA0104008, 0xE07A0DFC,
+0x06FC4008, 0x626C70A4, 0x04FE4208, 0x97B44208,
+0x420070E0, 0x05FE347C, 0x342CB814, 0xE0796D03,
+0x00FC4008, 0xCB07DB8E, 0x430BD38E, 0x610C640C,
+0x4008E07A, 0x709C0F14, 0xE61802FC, 0x8D1C3163,
+0xE05D682C, 0x01FC4008, 0x09FC70FC, 0x04FE70FC,
+0xD385661C, 0x659C430B, 0xE07A6503, 0x01FC4008,
+0x611C70A4, 0x04FE4108, 0x97864108, 0x347C4100,
+0x430BD37E, 0xA003341C, 0xE0616C03, 0x0CFC4008,
+0xE500D67B, 0x640D8562, 0x4008E05B, 0x0AFEA036,
+0x6053655C, 0x305C4000, 0x4008D676, 0x622D026D,
+0x8F2A32A0, 0xD3746E03, 0x64AD430B, 0x2228620D,
+0xD6728927, 0x066C60E3, 0x4008E060, 0x460002FC,
+0x3E676E2C, 0x62638B00, 0x4008E060, 0x0F243867,
+0x62638D03, 0x4008E061, 0xE06102FC, 0x400861DC,
+0x0F243167, 0x8F01682C, 0x626362D3, 0x346764CC,
+0x6D238D01, 0xA00466C3, 0x75016C63, 0x3243625C,
+0xE0608BC6, 0x07FC4008, 0x617CE400, 0xE904D55C,
+0x666C6650, 0x8B013617, 0x6673677C, 0x624C7401,
+0x25603293, 0x75018FF4, 0xE03AD656, 0xE400056C,
+0x8D012558, 0xE2026243, 0x4008E061, 0x67830EFC,
+0x3E283828, 0x9119E500, 0x6053655C, 0x3A1002BC,
+0x622C8D0B, 0x3A609613, 0x32778907, 0xE0618B02,
+0x02FC4008, 0xA01D6053, 0x25580B24, 0x32878908,
+0x62838B00, 0xA0156053, 0x064D0B24, 0x099E096C,
+0x8F083277, 0xE07B6623, 0x0F164008, 0x02FC7098,
+0x01FE7068, 0x626C662C, 0x32876053, 0x0B648F02,
+0x646336E8, 0x625C7501, 0x8BCD3293, 0xE014D635,
+0xE4000644, 0xD53461DC, 0x6250E708, 0x3217622C,
+0x6DDC8B01, 0x740162D3, 0x3673664C, 0x8FF42520,
+0xE4007501, 0xD52D61CC, 0x622C6250, 0x8B013217,
+0x62C36CCC, 0x664C7401, 0x25203673, 0x75018FF4,
+0x0009A0EC, 0x4008E079, 0x642C02FC, 0x430BD319,
+0x660C6E43, 0x3653E518, 0xE0638910, 0x46084008,
+0x460804FE, 0x70E09722, 0x347C4600, 0xD31305FE,
+0x346C430B, 0xE0626203, 0x0F244008, 0xCB0660E3,
+0x430BD30C, 0x660C6403, 0x3653E518, 0xE0638928,
+0x46084008, 0x460804FE, 0x70E09708, 0x347C4600,
+0xD30605FE, 0x346C430B, 0x6C03A01D, 0x0000064D,
+0x001142E8, 0x001148E0, 0x001148BA, 0x00114934,
+0x00114000, 0x00114008, 0x00114774, 0x00114011,
+0x001142E4, 0x001142D8, 0x001142ED, 0x001142F5,
+0x4008E062, 0x60E30CFC, 0xD39CCB08, 0x6403430B,
+0xE07A610C, 0x4008E618, 0x8D1C3163, 0xE05D0F14,
+0x07FC4008, 0x09FC70FC, 0x04FE70FC, 0xD394667C,
+0x659C430B, 0xE07A6503, 0x01FC4008, 0x611C70A4,
+0x04FE4108, 0x9D744108, 0x34DC4100, 0x430BD38D,
+0xA003341C, 0xE0626D03, 0x0DFC4008, 0xE500D68A,
+0x640D8562, 0x4008E05B, 0x01FEA02C, 0x6053655C,
+0x305C4000, 0x4008D685, 0x622D026D, 0x8F203210,
+0xD3836E03, 0x641D430B, 0x2228620D, 0xD681891D,
+0x066C60E3, 0x4008E062, 0x460002FC, 0x3167612C,
+0x62638B00, 0x64CCE062, 0x34674008, 0x8F010F24,
+0x626362C3, 0x356765DC, 0x6C238D01, 0xA00466D3,
+0x75016D63, 0x3243625C, 0xE0628BD0, 0x07FC4008,
+0x617CE400, 0xE904D570, 0x622C6250, 0x8B013217,
+0x6273677C, 0x664C7401, 0x25203693, 0x75018FF4,
+0x61CCE400, 0xE708D569, 0x666C6650, 0x8B013617,
+0x66C36CCC, 0x624C7401, 0x25603273, 0x75018FF4,
+0x61DCE400, 0x6650D562, 0x3617666C, 0x6DDC8B01,
+0x740166D3, 0x3273624C, 0x8FF42560, 0xA0057501,
+0x064D0009, 0xE200D65B, 0x0624E03A, 0xE03AD659,
+0x2228026C, 0xE039894B, 0x2228026C, 0xE05B8947,
+0x0EFE4008, 0x3E669690, 0xE0798941, 0x00FC4008,
+0x8D023E66, 0xCB02640C, 0xD344640C, 0x0009430B,
+0xE05C660C, 0x07FC4008, 0x4608701C, 0x617C05FE,
+0x977A4608, 0x357C4600, 0x6613356C, 0x430BD346,
+0xD54464E3, 0x62032008, 0x0029150F, 0x6603CA01,
+0x2668E03B, 0x05648D20, 0xC8F06023, 0xD53F8909,
+0x76FF6650, 0x84512560, 0x805170FF, 0x70FF8452,
+0x60238052, 0x890FC80F, 0x6260D639, 0x26207201,
+0x70018461, 0x84628061, 0xA0057001, 0xD6318062,
+0xE03BE200, 0x162F0624, 0x4008E05B, 0x964302FE,
+0x8B653266, 0xD72BD428, 0xD52E6040, 0x4028C93F,
+0x40084008, 0x50726203, 0xC802D12B, 0xE604891A,
+0x46284618, 0x2522226B, 0xE2086040, 0x6503C93F,
+0x66034508, 0x45004508, 0x46284218, 0x6263252B,
+0x42084208, 0x252B4200, 0x4218E208, 0x252B4228,
+0x2152A062, 0x4618E614, 0x226B4628, 0x60402522,
+0xC93FE428, 0x45086503, 0x45084028, 0x45004008,
+0x40084418, 0x254BE728, 0x47184000, 0x4728250B,
+0xD412257B, 0x2152A044, 0x064D09B4, 0x001148E0,
+0x001148BA, 0x00114934, 0x00114000, 0x00114008,
+0x00114774, 0x00114011, 0x001142FD, 0x00114301,
+0x00114309, 0x001142D8, 0x00114A24, 0x001142F5,
+0x001142ED, 0x001C3694, 0x001C3BB4, 0x001142E8,
+0xE214D429, 0x42186040, 0x4028C93F, 0x40084008,
+0xD6264228, 0x2602202B, 0xE7286040, 0x6503C93F,
+0x45084508, 0x45004028, 0x40084718, 0x4008257B,
+0x4000E728, 0x250B4718, 0xD21D4728, 0x2252257B,
+0xD71C6240, 0x0724E044, 0x3F3C932C, 0x4F164F06,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0x2FE668F6, 0x6243D114, 0xE4028512, 0x6E2D670D,
+0xE500A00F, 0x6053655D, 0x305C4000, 0x4008D10F,
+0x622D021D, 0x8B0332E0, 0x041C7108, 0x644CA004,
+0x625D7501, 0x8BED3273, 0x4618E602, 0x604D2469,
+0x6EF6000B, 0x000001F0, 0x001142E8, 0x001C3694,
+0x001C3BB4, 0x001142D8, 0x00114000, 0x00114008,
+0xD766D565, 0x62725151, 0x321CE340, 0x51522722,
+0x337C5271, 0x1721321C, 0x52725153, 0x321C644C,
+0x1722D15F, 0x66125255, 0x2162362C, 0x316C5173,
+0x61521713, 0xD65B5274, 0x1724321C, 0x52755154,
+0x1725321C, 0x52765158, 0x1726321C, 0x51776262,
+0x1717312C, 0x51785261, 0x1718312C, 0x51795262,
+0x1719312C, 0x517A5263, 0x171A312C, 0x517B5264,
+0x171B312C, 0x517C5265, 0x171C312C, 0x517D5266,
+0x171D312C, 0x517E5267, 0x171E312C, 0x527F5168,
+0x321CD645, 0x6262172F, 0x76946132, 0x2312312C,
+0x52316162, 0x321CD641, 0x515C1321, 0x351C5532,
+0x61621352, 0x41295235, 0x1325321C, 0x56365561,
+0x365C4529, 0x1366E538, 0x55312450, 0x71046143,
+0x66722152, 0x75086543, 0x56712562, 0x750C6543,
+0x56722562, 0x75106543, 0x56752562, 0x75146543,
+0x56732562, 0x75186543, 0x56762562, 0x751C6543,
+0x56322562, 0x75206543, 0x66322562, 0x75246543,
+0x56742562, 0x75286543, 0x56342562, 0x752C6543,
+0x55332562, 0x72306243, 0x55352252, 0x72346243,
+0x56362252, 0x24627438, 0x1341E400, 0x17412742,
+0x17451742, 0x17461743, 0x23421342, 0x13441744,
+0x13451343, 0x1346000B, 0xD510E124, 0x51572410,
+0x52581411, 0x57591422, 0x515A1473, 0x525B1414,
+0x575C1425, 0x525D1476, 0x1427E700, 0x1468565E,
+0x1469565F, 0x15781577, 0x157A1579, 0x157C157B,
+0x157E157D, 0x157F000B, 0x001C369C, 0x0020351C,
+0x00203578, 0x001C3CA0, 0x001C36F4, 0x001C3B88,
+0x6E726157, 0x21676E69, 0x69685420, 0x6F642073,
+0x656C676E, 0x746F6E20, 0x65656220, 0x6163206E,
+0x7262696C, 0x64657461, 0x0000000A, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+const u32_t zcFwBufImageSize=83968;
diff --git a/drivers/staging/otus/hal/hpfwspiu.c b/drivers/staging/otus/hal/hpfwspiu.c
new file mode 100644
index 000000000000..eda7ff5e573c
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwspiu.c
@@ -0,0 +1,655 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+
+const u32_t zcFwImageSPI[]={
+0x0009000B, 0x4F222FE6, 0xB0187FFC, 0xE6000009,
+0x943DD520, 0xC8406052, 0x2F028F03, 0x8FF93642,
+0xD41D7601, 0x4E0BDE1D, 0xD41D0009, 0x00094E0B,
+0x4E0BD41C, 0x7F040009, 0xA0214F26, 0x4F226EF6,
+0xE205D119, 0x2122E400, 0x92222142, 0x8BFD4210,
+0x450BD516, 0xD6160009, 0x0009460B, 0xE5FFD715,
+0x2752655D, 0xE1FFD714, 0xD4145079, 0x1709CB01,
+0x17112712, 0x2412E101, 0x4F26D411, 0x2410000B,
+0xDE11DD10, 0x00094D0B, 0x00094E0B, 0x0009AFFA,
+0x03E82710, 0x001C001C, 0x00116594, 0x00114EBE,
+0x001165A4, 0x001165BC, 0x001D4004, 0x00114FA0,
+0x00114378, 0x001C3510, 0x001C3624, 0x001E212C,
+0x001164FC, 0x00114700, 0x0011589C, 0x2FA62F96,
+0x2FC62FB6, 0x2FE62FD6, 0x7FC84F22, 0xD28DDD8C,
+0x61D360D0, 0x80F47101, 0x420B6010, 0x200880F8,
+0x6E038F10, 0xDB89D488, 0xD4896A40, 0x4B0BDC89,
+0x67C065AC, 0x697CDE88, 0x41086193, 0x31984108,
+0x3E1C4108, 0x66D284F8, 0x2008600C, 0x2E628F13,
+0xE40084F4, 0xDA81670C, 0x3273624D, 0xA0D38B01,
+0x644D0009, 0x35AC6543, 0x69436652, 0x39EC6B62,
+0xAFF119B1, 0x88017404, 0x84F48B15, 0x2E70E700,
+0xDA766E0C, 0x32E3627D, 0xA0C48B01, 0x677D0009,
+0x6C7366A3, 0x65737604, 0x356C3CAC, 0x6D5264C2,
+0xAFEF7708, 0xE2B024D2, 0x3020622C, 0x84F48B30,
+0x650CEC00, 0xDA691F53, 0x55F3E904, 0x325362CD,
+0xA0A88B01, 0x6CCD0009, 0x67C36EA3, 0x6BC37E04,
+0x3BEC37AC, 0x6EB26D72, 0xDB62D461, 0x00094B0B,
+0x410BD161, 0xD46164D3, 0x00094B0B, 0x450BD55E,
+0xD45F64E3, 0x00094B0B, 0x61D3E600, 0x316C666D,
+0x646D7601, 0x21E03493, 0x4E198FF7, 0x7C08AFD5,
+0x622CE2B1, 0x8B113020, 0xD552D456, 0xDA56DC4F,
+0x0009450B, 0x4A0BE400, 0xD75467C2, 0x470BDB52,
+0x4B0B0009, 0xE900E403, 0x2E90A06D, 0x622CE2B2,
+0x89683020, 0x622CE2B3, 0x8B1D3020, 0xDA45D44C,
+0x4A0BD942, 0x65960009, 0x6792D44A, 0x1F74DD3B,
+0x1F5D4D0B, 0xD639D448, 0x460BDB48, 0x55F455F4,
+0x4B0BD936, 0xD44654FD, 0x490B6503, 0x5DF51F05,
+0x1ED1EC04, 0x2EC0A047, 0x622CE2B4, 0x8B3E3020,
+0xDA34D440, 0x4A0BDD31, 0x84F40009, 0x600C6CD2,
+0x1F072F02, 0x1FC6C903, 0xE6001F08, 0xD73AE030,
+0x6CF2DB3A, 0x1F790F65, 0xA0211FBA, 0x51F6E904,
+0x6D63666D, 0x4C1536EC, 0xD2353D1C, 0x1F6B8F05,
+0x89023C93, 0xA00264D3, 0xE50455F8, 0x420B64D3,
+0x5BFB0009, 0xD61954FA, 0x460B65D3, 0x54F91B01,
+0xDA1655B1, 0x7CFC4A0B, 0x06FDE030, 0x0F657604,
+0x626D55F7, 0x8BDA3253, 0xA00484F4, 0xD4252E00,
+0x420BD20E, 0x7F3865D2, 0x6EF64F26, 0x6CF66DF6,
+0x6AF66BF6, 0x69F6000B, 0xE6006163, 0x4109A004,
+0x76016256, 0x74042422, 0x8BF93612, 0x0009000B,
+0x00117800, 0x00115FF0, 0x001164F6, 0x00114F2C,
+0x001165C0, 0x001164F5, 0x0011611C, 0x00117804,
+0x001165E0, 0x00114EBE, 0x00114F02, 0x001165F4,
+0x001165FC, 0x00116600, 0x00114BF0, 0x001148FC,
+0x00116618, 0x00116634, 0x00116640, 0x00114E56,
+0x0011664C, 0x00116658, 0x0011667C, 0x00116670,
+0x00114BC4, 0x00116688, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE5007FD8, 0x6453E110,
+0x6C534128, 0x655DEE0A, 0x46086653, 0x4608365C,
+0x361C7501, 0x675D6043, 0x60C30F66, 0x37E3ED00,
+0x816126C1, 0x81638162, 0x16D316D2, 0x8FEA16D4,
+0x68F27404, 0xDAB3D9B2, 0x29821981, 0xD1B259F1,
+0x2A921A91, 0x5BF35AF2, 0x5EF55DF4, 0x11A154F6,
+0x11B321A2, 0x11D511B2, 0x11E711D4, 0x114911E6,
+0x55F71148, 0xEE00DBA9, 0xDDA957F8, 0xD6A952F9,
+0x1B5164E3, 0xDBA82B52, 0xEAB8D8A8, 0x2D72E945,
+0x6AAC2622, 0x6EED4908, 0x4D086DE3, 0x3DEC61E3,
+0x4D084108, 0x3DBC31EC, 0x410860C3, 0x81D12DC1,
+0x4108E050, 0x41084008, 0x60C381D2, 0xE500318C,
+0x81D334A2, 0x1D131DD2, 0x8D01D494, 0xD4911D54,
+0xB08165D3, 0x64ED7E01, 0x8BDC3492, 0xDB94D18D,
+0xD28B6812, 0x1B814829, 0x2FD26412, 0x2B92694D,
+0xD98A6722, 0x1B734729, 0xD7876822, 0x1BA26A8D,
+0xD28C6B72, 0x22B2D586, 0xE0035D72, 0x5E7412D2,
+0x12E44018, 0xD6885176, 0x54781216, 0x1248E1FF,
+0xD4856792, 0x6852127A, 0x28C1E703, 0x81916952,
+0x6A52E050, 0x81A24008, 0x60C36B52, 0x6D5281B3,
+0x6E521DD2, 0x62521E63, 0x1264E600, 0x46086563,
+0x7501364C, 0x665D2612, 0x8BF83673, 0xE003D471,
+0x40186542, 0x674225C1, 0x8171D274, 0xEE006842,
+0x69421882, 0x1923E024, 0xE5806A42, 0x6B421AE4,
+0x81B266E3, 0xD46D6C42, 0x655C81C3, 0x6D63666D,
+0x616D7604, 0x31533D4C, 0x2DE28FF8, 0xD569D268,
+0x74042422, 0x7F282452, 0x6EF64F26, 0x6CF66DF6,
+0x6AF66BF6, 0x000B69F6, 0x664268F6, 0xC8036061,
+0xE5008D04, 0xC9036061, 0x8B038802, 0x65635262,
+0x24125124, 0x6053000B, 0x2FE62FD6, 0x7FEC4F22,
+0x62536E53, 0x6D43E550, 0x4508E400, 0xE101A001,
+0x60435224, 0x81212211, 0x60538123, 0x56E28122,
+0x8BF53620, 0x16E4D250, 0xE61464F3, 0x65E3420B,
+0xE4FC65E1, 0x2E512549, 0x65F361F1, 0x2F112149,
+0xD14954D1, 0xE614410B, 0x607157D1, 0x2701CB01,
+0x7F141DE1, 0x6EF64F26, 0x6DF6000B, 0x2FE62FD6,
+0x7FEC4F22, 0x66536E53, 0x6D43E5FC, 0x20596061,
+0x2601CB01, 0x326052E2, 0x12E48B06, 0x31E051E2,
+0x52D18B04, 0x1E22A002, 0x5664AFF0, 0x64F3D236,
+0x420BE614, 0x67E165E3, 0x2719E1FC, 0x67F12E71,
+0x271954D1, 0x65F3D130, 0x410BE614, 0x52D12F71,
+0xCB016021, 0x1DE12201, 0x4F267F14, 0x000B6EF6,
+0x2FE66DF6, 0x624C4F22, 0x4208DE1B, 0xA0054200,
+0x52523E2C, 0x5624D417, 0x2E62BF8E, 0x52E165E2,
+0x8BF63520, 0x2622D61B, 0x000B4F26, 0x2FB66EF6,
+0x2FD62FC6, 0x4F222FE6, 0xDB1CDC10, 0x66C252C1,
+0x89403620, 0xC9036061, 0x893C8801, 0xDD18DE0B,
+0x64E3BF63, 0x85036503, 0x620D66B2, 0x892B3262,
+0xBF9BD403, 0xD4130009, 0x00094D0B, 0x0009AFE6,
+0x001160DC, 0x001160E4, 0x001160EC, 0x00116114,
+0x001164F8, 0x00116500, 0x001000C8, 0x00101680,
+0x001E2108, 0x001C3D00, 0x00117880, 0x00117780,
+0x00040020, 0x0026C401, 0x001142F8, 0x001164DC,
+0x00114EBE, 0x0011669C, 0x64E3BF3E, 0x4D0BD406,
+0xAFBB0009, 0xD2050009, 0x4F262262, 0x6DF66EF6,
+0x000B6CF6, 0x00006BF6, 0x001166A0, 0x001C3D28,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xD23C7FFC, 0xC8036022, 0x2F018F3D, 0x0009A061,
+0xC9036061, 0x893B8801, 0xD238D837, 0x420BD938,
+0xE4006483, 0x6A036D03, 0x5C02490B, 0xD236DB35,
+0x56D385D2, 0x650D6422, 0x4B0BE740, 0xD1326E03,
+0x64126EED, 0x214234EC, 0x3DC05DD4, 0x85D28BEF,
+0x70FF56D3, 0xE740650D, 0x6C034B0B, 0x490BDB2A,
+0x66B2E403, 0x36CC6CCD, 0xE700D928, 0x2B62E5C8,
+0x6473E650, 0x490BDC26, 0x6483655C, 0x65A34C0B,
+0xEE01D124, 0xD11C21E2, 0x66125211, 0x8BBF3620,
+0xDD22DE21, 0xDC23DB22, 0x65D252D1, 0x89183520,
+0xC9036051, 0x89148801, 0xD114D41C, 0x0009410B,
+0x36E05603, 0x65038F04, 0x2B20E201, 0x2C52AFEC,
+0xD213D419, 0x0009420B, 0xE101D618, 0xAFE34118,
+0x60F12612, 0x8902C804, 0x420BD215, 0x7F040009,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0x000068F6, 0x001E2100, 0x001160E4, 0x0011453A,
+0x00114BF0, 0x00114E0C, 0x00116714, 0x001159B0,
+0x00114558, 0x001E212C, 0x00117880, 0x001160DC,
+0x001164FC, 0x001164F8, 0x00116114, 0x001C3D30,
+0x001140CC, 0xD6C2D5C1, 0x26226252, 0xC8016060,
+0x000B8BFA, 0x2FE60009, 0xBFF34F22, 0xD2BD0009,
+0xE405E100, 0x22402212, 0x6422DEB8, 0xE700D5B8,
+0x25721E42, 0xC98F8451, 0xC9F0CB10, 0x8051CB02,
+0xCB026050, 0x62522500, 0x2E22BFDC, 0xD6B250E4,
+0x4F262602, 0x6EF6000B, 0x4F222FD6, 0x0009BFDB,
+0x620CDDAE, 0x60D02D22, 0x8906C801, 0x0009BFD3,
+0x2D22620C, 0xC80160D0, 0x4F268BF8, 0x6DF6000B,
+0x4F222FE6, 0x6E43BFE8, 0xE100D2A2, 0x22E02212,
+0x6422D59E, 0xE600DE9E, 0x2E621542, 0xC9F084E1,
+0x80E1CB01, 0xCB0260E0, 0x67E22E00, 0x4F262572,
+0x6EF6AFA8, 0xE406AFE4, 0xE404AFE2, 0xBFF94F22,
+0xE4C70009, 0x644CBFDC, 0x4F26AFF6, 0xE406AFD8,
+0xE404AFD6, 0x4F222FE6, 0x6E43BFF8, 0xD58DD28D,
+0xE401E100, 0x221260E3, 0x80512240, 0x6622D187,
+0xE700DE87, 0x2E721162, 0xC9F084E1, 0x80E1CB02,
+0xCB0260E0, 0x62E22E00, 0x2122BF7C, 0xAFDF4F26,
+0x2FD66EF6, 0x4F222FE6, 0xBFCB6D53, 0xBF9B6E43,
+0xD27C0009, 0x22E061D3, 0x6022DE7D, 0x411821E9,
+0x201BC9FF, 0x2202D577, 0xD6768453, 0x60D38051,
+0xD4728053, 0xD1726762, 0x1472ED00, 0x841121D2,
+0xCB04C9F0, 0x60108011, 0x2100CB02, 0xBF516212,
+0x4F262422, 0xAFA76EF6, 0x65436DF6, 0xAFD0E4D8,
+0x6543644C, 0xAFCCE4D8, 0x2FC6644C, 0x2FE62FD6,
+0x6E534F22, 0xBF676D43, 0xD7626C63, 0x27D0D264,
+0x61E36072, 0x41182129, 0x201BC9FF, 0x2702D45D,
+0xD15B8443, 0x60E38041, 0xDE588043, 0xE6006472,
+0x21621E42, 0x65DC8411, 0x60C36203, 0x4008C907,
+0x67034008, 0xE29F6023, 0x622CC98F, 0x3520207B,
+0x80118D18, 0x7C048411, 0x60C36603, 0x6203C90F,
+0xC9F06063, 0x8011202B, 0x880B6053, 0x84118B14,
+0xC90F6603, 0xC90F7001, 0x60636203, 0x202BC9F0,
+0x8011A00A, 0x7C018411, 0x60C36603, 0x6203C90F,
+0xC9F06063, 0x8011202B, 0xCB026010, 0x62122100,
+0x2E22BEF0, 0xD63C50E4, 0x4F262602, 0x6DF66EF6,
+0x6CF6000B, 0x2FC62FB6, 0x2FE62FD6, 0x6C634F22,
+0x6E436D53, 0x6B73BF36, 0x0009BF06, 0x61D3D231,
+0xDE3322E0, 0x21E96022, 0xC9FF4118, 0xD42D201B,
+0x84432202, 0x8041D72F, 0x804360D3, 0x6622D427,
+0x1462D127, 0x14C327C2, 0x21C2EC00, 0x7B048411,
+0x60B36D03, 0x6503C90F, 0xC9F060D3, 0x8011205B,
+0xCB026010, 0x62122100, 0x4F262422, 0x6DF66EF6,
+0xAEAF6CF6, 0x2FB66BF6, 0x2FD62FC6, 0x4F222FE6,
+0x6C536D63, 0xBEFD6E43, 0xBECD6B73, 0xD2150009,
+0x22E061C3, 0x6022DE16, 0x411821E9, 0x201BC9FF,
+0x2202D110, 0xD60F8413, 0x60C38011, 0xDE0B8013,
+0xD40B6762, 0xEC006BBD, 0x1EB51E72, 0x844124C2,
+0xC9F04B21, 0x8041CB04, 0xE1406040, 0x2400CB06,
+0xE5006242, 0x4B212E22, 0x4128A014, 0x001D1200,
+0x00116528, 0x00116530, 0x00116538, 0x00116544,
+0x00FFFFFF, 0x00116534, 0x6053655D, 0x06DE4008,
+0x21627501, 0x32B3625D, 0x4F268BF6, 0x6DF66EF6,
+0xAE5F6CF6, 0x4F226BF6, 0xBF73677C, 0xAEB3644C,
+0x4F224F26, 0xBFA6677D, 0xAEAD644C, 0x4F224F26,
+0xE500E49F, 0xBF08E603, 0x4F26644C, 0x600C000B,
+0xE49F4F22, 0xE603E500, 0x644CBEFF, 0x4F264019,
+0x600D000B, 0x6543665C, 0xE403AEF7, 0x6543665C,
+0xE40BAEF3, 0xD175D674, 0x60436262, 0xC8012122,
+0x8F016010, 0xC9EFCB10, 0x62122100, 0x2622000B,
+0x4F222FE6, 0xE0004F13, 0xBE2C401E, 0xD56C6E43,
+0x2522620C, 0xE401BFE6, 0x6063D669, 0x60ECCF80,
+0x89072008, 0x89098801, 0x890D8802, 0x89118803,
+0x0009A013, 0xC9E36060, 0x2600A00F, 0xCB106060,
+0xCB04C9F7, 0x2600A009, 0xCB106060, 0xCB08C9FB,
+0x2600A003, 0xCB1C6060, 0xD5592600, 0xBE616252,
+0xE400642C, 0x4F264F17, 0x6EF6AFBC, 0x2F962F86,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0x60C36C7C,
+0x6A638802, 0x69538F09, 0x65436290, 0x662CE4AF,
+0xBEF7E701, 0xA00A644C, 0x2CC80009, 0x88018901,
+0x65438B05, 0xE600E4AF, 0xBEEBE701, 0xBDD1644C,
+0xED010009, 0xDE43EBAF, 0xE800A02C, 0x0009BDF4,
+0x60C3D141, 0x8802E200, 0xD5402122, 0x21B08D06,
+0x89082CC8, 0x890A8801, 0x0009A00C, 0x009C60D3,
+0xA007D639, 0xD2388061, 0xA0036083, 0xD2368021,
+0x802160D3, 0xD1356412, 0x1E42E600, 0x84512162,
+0xC9F07D01, 0x8051CB02, 0xCB026050, 0x67122500,
+0x2E72BDA0, 0x8BD13DA2, 0x0009BDF6, 0x0009BDA3,
+0x620CD627, 0x4F262622, 0x6DF66EF6, 0x6BF66CF6,
+0x69F66AF6, 0x68F6000B, 0xE702AF98, 0x2F962F86,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0x3F3C9331,
+0x0F569030, 0xE8FF70FC, 0x688C0F46, 0xE900A049,
+0x4018E010, 0xE50404FE, 0xBF33349C, 0x88FF6A43,
+0x901F893E, 0xE1100CFE, 0x41183C98, 0x8B033C16,
+0x64A3BE1B, 0x0009A031, 0x4018E010, 0xED000BFE,
+0xA0073BCC, 0x64D36EF3, 0xBF1F34BC, 0x2E00E501,
+0x7E017D01, 0x8BF63DC2, 0x64A3BE07, 0xA01AED00,
+0xEFF86EF3, 0x00001004, 0x001D1204, 0x0011652C,
+0x00116544, 0x001D1200, 0x00116530, 0x00116528,
+0x666C66E0, 0x89043680, 0x35BC65D3, 0xBE51E701,
+0x7D01E402, 0x3DC27E01, 0xE1108BF2, 0x391C4118,
+0x90547904, 0x391201FE, 0x93518BB2, 0x4F263F3C,
+0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6, 0x68F6000B,
+0x676D6253, 0x66236543, 0xE402AEC3, 0x2FA62F96,
+0x2FC62FB6, 0x2FE62FD6, 0x697D4F22, 0x4A216A93,
+0x4A084A21, 0x6C436D63, 0xA0086B73, 0x64C36E53,
+0x669365D3, 0x6BBDBFE4, 0x3DAC3CBC, 0x6EEF3EB8,
+0x8BF42EE8, 0x4F26E000, 0x6DF66EF6, 0x6BF66CF6,
+0x000B6AF6, 0x2FA669F6, 0x2FC62FB6, 0x2FE62FD6,
+0xEC004F22, 0x6B536EC3, 0xA0066D43, 0x64D3EA01,
+0x65A3BEA8, 0x7D013C0C, 0x3EB27E01, 0x60C38BF7,
+0x6EF64F26, 0x6CF66DF6, 0x000B6BF6, 0x10046AF6,
+0x00001008, 0x0009000B, 0x2FD62FC6, 0x4F222FE6,
+0x6D436C53, 0xEE00A004, 0x7E0164D4, 0x644CBFF2,
+0x8BF93EC2, 0x6EF64F26, 0x000B6DF6, 0xE5006CF6,
+0x6643A002, 0x76017501, 0x22286260, 0xAFE38BFA,
+0x2FE60009, 0x75076253, 0xE1086753, 0x6043EE0A,
+0x4409C90F, 0x650330E2, 0x8D014409, 0xE630E637,
+0x4110365C, 0x8FF22760, 0xE00077FF, 0x000B8028,
+0x4F226EF6, 0xBFE47FEC, 0xBFD865F3, 0x7F1464F3,
+0x000B4F26, 0x4F22E000, 0xBFDA7FEC, 0x64F365F3,
+0x7406BFCD, 0x4F267F14, 0xE000000B, 0x4F222FE6,
+0x62537FEC, 0x65F36E43, 0x6423BFCB, 0x64E3BFBF,
+0x64F3BFBD, 0xBFBAD403, 0x7F140009, 0x000B4F26,
+0x00006EF6, 0x001166A4, 0xE4FDD29A, 0xD79A6122,
+0x22122149, 0x74016022, 0x2202CB01, 0xD5976622,
+0x22622649, 0xC8406070, 0x60528902, 0x2502CB04,
+0xE1F76452, 0x25422419, 0xE7016052, 0x2502C9CF,
+0xE6026052, 0x2502CB03, 0x15624718, 0x1573000B,
+0xD78CD58B, 0xD48DD28C, 0xE600E100, 0x27112511,
+0xAFD12210, 0x664C2461, 0x4600D289, 0x6060362C,
+0x000BCB10, 0x654C2600, 0x4500D285, 0x6650352C,
+0x2619E1EF, 0x2560000B, 0xD282664C, 0x362C4600,
+0xCB106060, 0x2600000B, 0xD27E654C, 0x352C4500,
+0xE1EF6650, 0x000B2619, 0x664C2560, 0x4600D278,
+0x6060362C, 0x000BCB08, 0x654C2600, 0x4500D274,
+0x6650352C, 0x2619E1F7, 0x2560000B, 0xD271664C,
+0x362C4600, 0xCB086060, 0x2600000B, 0xD26D654C,
+0x352C4500, 0xE1F76650, 0x000B2619, 0x624C2560,
+0x4200D667, 0x6020326C, 0x4021C908, 0x40214021,
+0x600C000B, 0xD663624C, 0x326C4200, 0xC9086020,
+0x40214021, 0x000B4021, 0xD15F600C, 0x341C644C,
+0x000B6240, 0xD15D602C, 0x341C644C, 0x000B6240,
+0x2FE6602C, 0x6E434F22, 0xE60A645C, 0x89143467,
+0x0009BFEB, 0x60EC640C, 0x8B028801, 0xA002E00F,
+0x44092409, 0x624C4409, 0x3263E60A, 0xBFE28905,
+0x620C644C, 0xC8806023, 0xE2008B00, 0x4F266023,
+0x6EF6000B, 0xD64A4F22, 0x88016062, 0xB2458B03,
+0xA0030009, 0xD2470009, 0x2260E640, 0xE200D646,
+0x000B4F26, 0x4F222622, 0x6062D641, 0x8B018802,
+0x0009B28E, 0xE200D640, 0x000B4F26, 0xD53C2622,
+0xE100D43C, 0x2512E701, 0x2470000B, 0xE604D239,
+0x2260000B, 0xD4394F22, 0x410BD139, 0xD5390009,
+0x6650E1FD, 0x2619D238, 0x2560E700, 0x000B4F26,
+0x4F222270, 0xD132D435, 0x0009410B, 0xE7FBD531,
+0x26796650, 0x000B4F26, 0x4F222560, 0xD12CD430,
+0x0009410B, 0xE7F7D52B, 0x26796650, 0x000B4F26,
+0xD5282560, 0x6250942D, 0x000B2249, 0xD5252520,
+0x6250E4BF, 0x000B2249, 0x4F222520, 0x8522D225,
+0x2008600D, 0x88018911, 0x88038913, 0x88058915,
+0x88068942, 0x88088948, 0x8809894E, 0x880A8954,
+0x880B895A, 0xA0678960, 0xB0690009, 0xA0640009,
+0xB077600C, 0xA0600009, 0xB080600C, 0xA05C0009,
+0xFF7F600C, 0x001E2148, 0x001E1000, 0x001E1108,
+0x00116570, 0x00116572, 0x00116591, 0x00116554,
+0x001E103F, 0x001E105F, 0x001E102F, 0x001E1090,
+0x00116578, 0x001E100B, 0x00116574, 0x001166A8,
+0x00114EBE, 0x001E1028, 0x00116590, 0x001166B4,
+0x001166C4, 0x00116548, 0x6260D684, 0x8B2B2228,
+0x0009B061, 0x600CA029, 0x6260D680, 0x8B232228,
+0x0009B069, 0x600CA021, 0x6260D67C, 0x8B1B2228,
+0x0009B0C7, 0x600CA019, 0x6260D678, 0x8B132228,
+0x0009B0CD, 0x600CA011, 0x6260D674, 0x8B0B2228,
+0x0009B125, 0x600CA009, 0x6260D670, 0x8B032228,
+0x0009B13D, 0x600CA001, 0x4F26E000, 0x0009000B,
+0xD26CD16B, 0xD56C8412, 0x4000C90F, 0xD76B012D,
+0xE403D66B, 0xE20F611C, 0x2540E001, 0x25202712,
+0x2602000B, 0xE601D262, 0x30668523, 0xE0008D05,
+0xD663D260, 0xE0018122, 0x000B2602, 0xD25C0009,
+0x600D8523, 0x89052008, 0x8B0A8801, 0x6060D65D,
+0x2600CB01, 0xD457D65A, 0xE001E101, 0x000B2612,
+0x000B8142, 0xD152E000, 0x8513E501, 0x640D4518,
+0x66033453, 0xE0008D05, 0xD551D253, 0x2260E001,
+0x000B2502, 0x4F220009, 0x8513D149, 0x6453650D,
+0x62494419, 0x227D672E, 0x8801602C, 0x88028909,
+0x88038910, 0x8806891A, 0x88078935, 0xA04C893B,
+0xD5460009, 0x6652D746, 0x2762D446, 0x622C6261,
+0x2421A038, 0x2228625C, 0xD4438B3F, 0x6642D540,
+0x2562D440, 0x24018561, 0x6203A02C, 0x2008605C,
+0x88108907, 0x88208908, 0x88308909, 0xA02C890A,
+0xD23A0009, 0x6222A008, 0xA005D239, 0xD2396222,
+0x6222A002, 0x6262D638, 0xD432D531, 0x66212522,
+0xA00F626C, 0xD6352421, 0x6261D52D, 0x622CD42D,
+0xA0072562, 0xD6322421, 0x8561D529, 0x2562D429,
+0x62032401, 0x662D8515, 0x3617610D, 0x65038F01,
+0xB0CB2451, 0xA0010009, 0xE000E001, 0x000B4F26,
+0xD6190009, 0xD427E101, 0x65412610, 0xD118D717,
+0xE20F655D, 0x2752E001, 0x000B2620, 0x2FE62102,
+0xD20F4F22, 0x640C8523, 0x8B082448, 0xD511D61D,
+0x2621E200, 0x940F8451, 0xA0482049, 0xDE0D8051,
+0xC84060E0, 0xE2018D32, 0x89443427, 0xD216D615,
+0x2641420B, 0x0009A030, 0x0000FF7F, 0x00116591,
+0x00116548, 0x00116554, 0x001E1100, 0x001E100C,
+0x00116574, 0x001E1000, 0x001E1001, 0x0011657C,
+0x0011655C, 0x00116560, 0x00116564, 0x00116580,
+0x00116584, 0x00116588, 0x0011658C, 0x00116774,
+0x0011677E, 0x0011656E, 0x00115DCA, 0x89123427,
+0xD294D693, 0x2641420B, 0xCB8084E1, 0x80E1B0F5,
+0xD69160E0, 0x2E00CB04, 0xC93F6060, 0xD68F2600,
+0xA001E001, 0xE0002602, 0x000B4F26, 0xD68C6EF6,
+0xC8806060, 0xD2868919, 0x88016021, 0xD2898B15,
+0x8524E501, 0x89103056, 0xE203D187, 0x2120D487,
+0xE00B6541, 0x0656655D, 0xE40FD585, 0x2140E702,
+0xD77E2571, 0x000BE001, 0x000B2702, 0x2FE6E000,
+0xDE804F22, 0xC88084E1, 0xD57A892C, 0x20088554,
+0x61038F28, 0x8553D77C, 0x64036672, 0x8566650C,
+0x3520620C, 0xD6798B1E, 0x651CD774, 0x2651644C,
+0x60E02741, 0x8904C840, 0x420BD275, 0xA0030009,
+0xD2680009, 0x0009420B, 0x0009B09F, 0xE201D167,
+0x60E02122, 0xCB04D464, 0x60402E00, 0x2400C93F,
+0x6023A001, 0x4F26E000, 0x6EF6000B, 0x2FB62FA6,
+0x2FD62FC6, 0xDA622FE6, 0x66A1E240, 0x3622DC5E,
+0x62638900, 0x6ED36D2C, 0x4E2136D8, 0x4E212A61,
+0xDB61D460, 0xE700A00F, 0x770162B2, 0x71026123,
+0x66212B12, 0x71026213, 0x61212B12, 0x651D666D,
+0x356C4528, 0x627C2452, 0x8BED32E3, 0xC90360D3,
+0x8B108803, 0x617367B2, 0x2B127102, 0x71026E13,
+0x2B126571, 0x655D6DE1, 0x422862DD, 0x325CE107,
+0xA00C2C10, 0x88022422, 0xA0038B01, 0x8801E203,
+0xE2018B05, 0x66B22C20, 0x655D6561, 0xE60F2452,
+0x67A12C60, 0x8B052778, 0xDD38DC44, 0xEB01EA00,
+0x2DB22CA2, 0x6DF66EF6, 0x6BF66CF6, 0x6AF6000B,
+0x2FE62FD6, 0xE240DD36, 0x362266D1, 0x62638900,
+0x3678672C, 0x7703DE38, 0x47212D61, 0x64E2D635,
+0xA00E4721, 0x6562E100, 0x62537101, 0x74012450,
+0x24204219, 0x45297401, 0x74012450, 0x24504519,
+0x621C7401, 0x8BEE3273, 0x66E24200, 0x420061D1,
+0x2118362C, 0x2E628F06, 0xDD1CD728, 0xE501E400,
+0x2D522742, 0x000B6EF6, 0x2FD66DF6, 0x4F222FE6,
+0xED0AEE01, 0x64E3BC97, 0xBC9C64E3, 0x62EC7E01,
+0x8BF732D7, 0xBC9FEE01, 0x64E364E3, 0x7E01BCA4,
+0x32D762EC, 0x4F268BF7, 0x000B6EF6, 0xD1186DF6,
+0xD418920D, 0x72122122, 0x2422D617, 0xD7177204,
+0x72202622, 0x2722D116, 0x000B7230, 0x137A2122,
+0x0011656E, 0x00115ED6, 0x001E1015, 0x00116574,
+0x001E1001, 0x00116548, 0x001E1100, 0x00116572,
+0x00116560, 0x001E1000, 0x00116564, 0x00116570,
+0x00115DCA, 0x001E100C, 0x0011655C, 0x00116578,
+0x0011657C, 0x00116580, 0x00116584, 0x00116588,
+0x0011658C, 0x4F222FE6, 0xD6507FFC, 0x88016060,
+0xE2018951, 0x2620BFBB, 0xD54ED14D, 0xDE4E6010,
+0x64E36552, 0x7402C840, 0x8D22D14C, 0xD24C7502,
+0xE601D74C, 0xE7042722, 0x76016255, 0x626C2421,
+0x8FF93273, 0xD4437402, 0x6242E601, 0x640D8528,
+0x67494419, 0x275D657E, 0x81E4607C, 0xE417D542,
+0x67557601, 0x3243626C, 0x8FF92171, 0xA0207102,
+0xD23E0009, 0xE601D73B, 0xE7042722, 0x76016255,
+0x626C2421, 0x8FF93273, 0xD4327402, 0x6242E601,
+0x640D8528, 0x67494419, 0x275D657E, 0x81E4607C,
+0xE417D533, 0x67557601, 0x3243626C, 0x8FF92171,
+0x924A7102, 0xD2262E21, 0x5E23D72E, 0x64F22FE2,
+0x604365F2, 0x2700C980, 0xC9606043, 0x80716103,
+0xC9036043, 0x80724519, 0x65F2605C, 0x817266F2,
+0x46194629, 0x606C4529, 0x4018645C, 0x8173304C,
+0x21185E23, 0x64F22FE2, 0x6E4C62F2, 0x602C4219,
+0x66F262F2, 0x46294018, 0x461930EC, 0x42298174,
+0x652C606C, 0x305C4018, 0x81758F07, 0x0009BC9D,
+0x2228620C, 0xA00A8908, 0x60130009, 0x8B038840,
+0x0009B009, 0x0009A003, 0xE202D60F, 0x7F042622,
+0x000B4F26, 0x000B6EF6, 0x060A0009, 0x00116590,
+0x001E1000, 0x0011657C, 0x00116774, 0x00116780,
+0x00116718, 0x00116564, 0x00116748, 0x00116746,
+0x0011671A, 0x00116548, 0x00116574, 0x4F222FE6,
+0x84E9DE8E, 0x2448640C, 0xB18B8901, 0xD28C0009,
+0x26686620, 0x60E08902, 0x2E00C9BF, 0x000B4F26,
+0x000B6EF6, 0x2FE60009, 0xDE864F22, 0x60E0D686,
+0xCBC0D486, 0x62602E00, 0xC803602C, 0x40218904,
+0x70014021, 0x6603A002, 0x66034009, 0xD680616D,
+0xE500A004, 0x75016262, 0x74042422, 0x3213625D,
+0xD27C8BF8, 0x0009420B, 0xC9BF84E2, 0x4F2680E2,
+0x6EF6000B, 0x2FE62FD6, 0x7FFC4F22, 0x6260D676,
+0x89402228, 0xD56DE100, 0x60502610, 0xCB40D473,
+0x2500440B, 0x8D052008, 0x62E06E03, 0x7104612C,
+0x2F11A006, 0xD46ED666, 0xDD6E6760, 0x657C4D0B,
+0xE23C6D1D, 0x8B033D27, 0xD26CD46B, 0x0009420B,
+0x4D214D21, 0xA005D76A, 0x66E6E400, 0x357C4508,
+0x74012562, 0x35D3654D, 0xD7668BF7, 0x6E72E003,
+0x81E14018, 0x6E7260F1, 0x81E2700C, 0xD4626172,
+0xDD628113, 0x65724D0B, 0xD652D261, 0x2212E101,
+0xC93F6060, 0x7F042600, 0x6EF64F26, 0x6DF6000B,
+0x2FC62FB6, 0x2FE62FD6, 0xD25A4F22, 0x6B436E73,
+0x420B6C53, 0x20086D63, 0x61038F08, 0xD24FD456,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6422B, 0x21B060C3,
+0x60D38011, 0xE5008111, 0x64BCA007, 0x6053655D,
+0x665300EC, 0x7501361C, 0x625D8064, 0x8BF53243,
+0x6060D636, 0x2600C9BF, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6000B, 0x7FC44F22, 0x720262F3, 0x22512F41,
+0x45297202, 0x60632251, 0xE5C4E682, 0x67F38121,
+0x655C666C, 0xE408BFBC, 0x4F267F3C, 0x0009000B,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xE1007FC4, 0x6513ECFF, 0x6B136CCD, 0xDE34D733,
+0xEDFF64F3, 0xD833EA04, 0x6053655C, 0x027D4000,
+0x32C0622D, 0x66038D0D, 0x09ED6063, 0x2491027D,
+0x24217402, 0x698202ED, 0x3928622D, 0x74022892,
+0x75017104, 0x6063625C, 0x07D532A2, 0x0EB58FE4,
+0x2448641C, 0xE6808905, 0x67F3E5C5, 0xBF7F666C,
+0x7F3C655C, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0xD11C68F6, 0x6012D21C, 0xCB20E405,
+0x2102E500, 0x000B2242, 0x00002252, 0x001E1017,
+0x001164F6, 0x001E1015, 0x001E10BF, 0x00117800,
+0x001E10FC, 0x001140CC, 0x001164FC, 0x0011602E,
+0x001166D0, 0x00114F2C, 0x001166EC, 0x00114EBE,
+0x0011788C, 0x001164F8, 0x001160DC, 0x001145BC,
+0x001E2130, 0x00115FF0, 0x001166F4, 0x00116510,
+0x00116518, 0x00116710, 0x001C3500, 0x001D4004,
+0xD565D164, 0xE400D765, 0x2142E20F, 0x17411154,
+0xD5632722, 0x9669D763, 0x15412572, 0x96661562,
+0xE6011565, 0xD5601165, 0x666CE6F8, 0x25422542,
+0x25422542, 0x25422542, 0x25622542, 0x7601E727,
+0x67632572, 0x25627797, 0xE7042572, 0x2572E248,
+0xE2192522, 0xE2702522, 0x25422542, 0x25422542,
+0x25222542, 0x2522E20C, 0x25422542, 0x25422542,
+0x25422542, 0x25422542, 0x000B154A, 0xE2081145,
+0x0009422B, 0x2FE62FD6, 0x7FFC4F22, 0xC8206043,
+0x6E438D02, 0x0009BE75, 0xC81060E3, 0xBE728901,
+0x60E30009, 0x8901C840, 0x0009BE94, 0xC80160E3,
+0xDD3E8938, 0xC80260D0, 0x2F008D03, 0x460BD63C,
+0x60F00009, 0x8902C804, 0x460BD63A, 0x62F00009,
+0xC8806023, 0x60D08902, 0x2D00C97F, 0xC8016023,
+0xD6358906, 0x0009460B, 0x0009A007, 0x51630601,
+0x8902C808, 0x460BD631, 0x60F00009, 0x8902C810,
+0x420BD22F, 0xD52F0009, 0x88026052, 0xD22E8B03,
+0xA005E604, 0x88012260, 0xD22B8B02, 0x2260E601,
+0x2522E200, 0xC88060E3, 0xD628892E, 0x60E36E60,
+0x8902C880, 0x420BD226, 0x60E30009, 0x8902C840,
+0x420BD224, 0x60E30009, 0x8902C802, 0x420BD222,
+0x60E30009, 0x890EC804, 0x410BD120, 0xBF120009,
+0xBF4D0009, 0xD51E0009, 0x6050D41E, 0xC908D71E,
+0xBF842500, 0x60E32472, 0x8905C808, 0x7F04D21B,
+0x6EF64F26, 0x6DF6422B, 0x4F267F04, 0x000B6EF6,
+0x00006DF6, 0x001C581C, 0xA000A000, 0x001D0100,
+0x001D4000, 0x00040021, 0x001C589C, 0x001E1021,
+0x001150C4, 0x001150E6, 0x00115724, 0x001150FE,
+0x0011510C, 0x00116574, 0x001E100B, 0x001E1028,
+0x00115162, 0x0011516E, 0x00115114, 0x00115132,
+0x001E1000, 0x0010F100, 0x12345678, 0x0011514A,
+0x644CD6A7, 0x000B346C, 0xD6A62450, 0x346C644C,
+0x2450000B, 0x644CD6A4, 0x000B346C, 0x625C2450,
+0x4208616D, 0x42084119, 0x42006019, 0x670E614C,
+0xD49E321C, 0x4200207D, 0x324CC90F, 0x2200000B,
+0x4208625C, 0x42004208, 0x324C644C, 0x4200D498,
+0x000B324C, 0x2FE62260, 0x614C4F12, 0x4100D493,
+0x6710314C, 0xE29F666D, 0x27294619, 0x6E536269,
+0x672E6573, 0x4221227D, 0x42214221, 0x7601662C,
+0xE4014608, 0x34E84608, 0x644C4600, 0x071A0467,
+0x2150257B, 0x000B4F16, 0x4F226EF6, 0xD2857FE8,
+0x88016021, 0xD2848B7B, 0x26686621, 0xD2838B77,
+0x26686621, 0xE50F8B73, 0xE401BFA2, 0xBFA4E501,
+0xE586E400, 0xE400655C, 0x2F50BFA4, 0xBFA1E401,
+0xE602E506, 0x60634618, 0x81F2E401, 0x6543BF9F,
+0xE40185F2, 0xBFAB6543, 0x85F26603, 0x6543E401,
+0x6603BFB1, 0xE40265F0, 0x6053756C, 0x80F8BF80,
+0xBF82E402, 0x84F8E512, 0x7090E402, 0x6503BF82,
+0x4618E602, 0x81F66063, 0xBF80E402, 0x85F6E500,
+0x6603E402, 0xE500BF8C, 0xE40285F6, 0xBF926603,
+0xE5FEE500, 0xE010655C, 0xBF61E403, 0xE5130F54,
+0xE40EBF63, 0x05FCE010, 0xBF63E40E, 0xE5007585,
+0xBF64E403, 0xE500E640, 0xBF71E403, 0xE500E640,
+0xBF78E403, 0xE5FFE640, 0xE014655C, 0xBF47E404,
+0xE40F0F54, 0xE504BF49, 0x05FCE014, 0xBF49E40F,
+0xE5017584, 0xBF4AE640, 0xE501E404, 0xBF57E640,
+0xE501E404, 0xE404E640, 0xAF5C7F18, 0x7F184F26,
+0x000B4F26, 0x4F220009, 0xD2427FF0, 0x88016021,
+0xD2418B71, 0x26686621, 0xD2408B6D, 0x26686621,
+0xE50F8B69, 0xE401BF1C, 0xBF1EE501, 0xE586E400,
+0xE400655C, 0x2F50BF1E, 0xBF1BE401, 0xE401E506,
+0xBF1C6543, 0xE401E640, 0xBF296543, 0xE401E640,
+0xBF306543, 0x65F0E640, 0x756CE402, 0xBEFF6053,
+0xE40280F4, 0xE512BF01, 0xE40284F4, 0xBF017090,
+0xE6406503, 0xBF02E402, 0xE640E500, 0xBF0FE402,
+0xE640E500, 0xBF16E402, 0xE5FEE500, 0x6053655C,
+0xBEE5E403, 0xE51380F8, 0xE40EBEE7, 0xE40E84F8,
+0xBEE77085, 0xE5006503, 0xBEE8E640, 0xE500E403,
+0xBEF5E640, 0xE500E403, 0xBEFCE640, 0xE5FFE403,
+0x6053655C, 0xBECBE404, 0xE40F80FC, 0xE504BECD,
+0xE40F84FC, 0xBECD7083, 0xE5016503, 0xBECEE640,
+0xE501E404, 0xBEDBE640, 0xE501E404, 0xE404E640,
+0xAEE07F10, 0x7F104F26, 0x000B4F26, 0x00000009,
+0x001E102F, 0x001E1080, 0x001E1090, 0x001E103F,
+0x001E103E, 0x0011656E, 0x00116570, 0x00116572,
+0xD21DD11C, 0x66206010, 0x676C7001, 0x3700C90F,
+0xE5008D13, 0x67106210, 0x7701622C, 0x64232170,
+0xD6166010, 0x44084408, 0x3428C90F, 0x62602100,
+0x7201D513, 0x44082620, 0x000B354C, 0xD10F6053,
+0x25586510, 0xE6008D13, 0xD60DD40B, 0x655C6540,
+0x47086753, 0x37584708, 0x47086540, 0x24507501,
+0x367C6040, 0x2400C90F, 0x72FF6210, 0x000B2120,
+0x00006063, 0x001164F5, 0x001164F4, 0x001164F6,
+0x0011611C, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x544F0D0A, 0x53205355, 0x46204950,
+0x00003A57, 0x2074634F, 0x32203220, 0x20373030,
+0x333A3831, 0x36343A32, 0x00000000, 0x00000D0A,
+0x42707372, 0x3D206675, 0x554E203D, 0x202C4C4C,
+0x6E49677A, 0x4E497274, 0x6D754E51, 0x0000003D,
+0x52504545, 0x57204D4F, 0x65746972, 0x6461202C,
+0x003D7264, 0x6C617620, 0x0000003D, 0x00000A0D,
+0x5A205746, 0x4D435F4D, 0x4C465F44, 0x5F485341,
+0x53415245, 0x000A0D45, 0x5A205746, 0x4D435F4D,
+0x4C465F44, 0x5F485341, 0x534B4843, 0x0A0D4D55,
+0x00000000, 0x2D495053, 0x72646461, 0x0000003D,
+0x2D495053, 0x676E656C, 0x003D6874, 0x2D495053,
+0x736B6863, 0x003D6D75, 0x5A205746, 0x4D435F4D,
+0x4C465F44, 0x5F485341, 0x44414552, 0x00000A0D,
+0x61202072, 0x3D726464, 0x00000000, 0x72202020,
+0x75427073, 0x00003D66, 0x6E6B6E55, 0x206E776F,
+0x6D6D6F63, 0x3D646E61, 0x00000000, 0x00000072,
+0x00205220, 0x00000D0A, 0x62735576, 0x7473725F,
+0x00000A0D, 0x62735576, 0x7375735F, 0x646E6570,
+0x00000A0D, 0x62735576, 0x7365725F, 0x000A0D6D,
+0x72746E49, 0x6D652051, 0x2C797470, 0x49677A20,
+0x4972746E, 0x754E514E, 0x00003D6D, 0x654C7245,
+0x0000006E, 0x20746F4E, 0x756F6E65, 0x49206867,
+0x4220514E, 0x0A0D6675, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x002E0209, 0x80000101,
+0x000409FA, 0x00FF0400, 0x05070000, 0x02000201,
+0x82050700, 0x00020002, 0x03830507, 0x07010040,
+0x40020405, 0x02090000, 0x0101002E, 0x09FA8000,
+0x04000004, 0x000000FF, 0x02010507, 0x07000040,
+0x40028205, 0x05070000, 0x00400383, 0x04050701,
+0x00004002, 0x00000000, 0x00000000, 0x07090000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, };
+
+const u32_t zcFwImageSPISize=10156;
diff --git a/drivers/staging/otus/hal/hpfwu.c b/drivers/staging/otus/hal/hpfwu.c
new file mode 100644
index 000000000000..2b77cbacc6d6
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwu.c
@@ -0,0 +1,1017 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE947FFC, 0xE114D594,
+0x1E13D494, 0x67521E4C, 0xD494D693, 0x37402769,
+0x62528F06, 0x7201D692, 0x60602522, 0x2600C93F,
+0xD7906152, 0x2512611D, 0x264B6652, 0x2562470B,
+0x0009B017, 0xE60095AC, 0xC84060E2, 0x2F028F03,
+0x8FF93652, 0xD4887601, 0x4E0BDE88, 0xD4880009,
+0x00094E0B, 0x4E0BD487, 0x7F040009, 0xA0524F26,
+0x4F226EF6, 0x410BD184, 0xD4840009, 0x0009440B,
+0x450BD583, 0xD7830009, 0xD283E1FF, 0x2712611D,
+0xD4825029, 0xE1FFCB01, 0x1209E501, 0x12112212,
+0xE7202452, 0x4718D57E, 0x2572D27E, 0xD17EE700,
+0xD67FD47E, 0xE2012270, 0x24702172, 0xD67D2620,
+0x2641E4FF, 0xD57CE600, 0x666DE104, 0x76016063,
+0x4000626D, 0x8FF83212, 0xD5780545, 0x2520E201,
+0xD278D777, 0xE480E100, 0x22122710, 0x6613D576,
+0x666D644C, 0x76046763, 0x375C626D, 0x8FF83243,
+0xD5722712, 0xD273D772, 0xE400E101, 0x27102511,
+0x000B4F26, 0x7FCC2242, 0xD170D56F, 0xD271DB70,
+0x1F51D471, 0xD6717508, 0x1F12D771, 0x1F55710C,
+0x1FB975FC, 0x72041F2A, 0x1F13EB10, 0x1F561F44,
+0x1F781F67, 0xD86B1F2B, 0xDD6CD96B, 0xDC6CEA00,
+0xD26DDE6C, 0x89003A22, 0xD15D7A01, 0x88016010,
+0x56F88B03, 0x4218E201, 0xD1682622, 0x0009410B,
+0x440BD467, 0xD5670009, 0x0009450B, 0x6010D150,
+0x8B108801, 0xE650D14F, 0x46186212, 0x8B083266,
+0x56F9D14B, 0x2120E200, 0xCB016062, 0x2602A003,
+0x72012710, 0x60822122, 0x89098801, 0xE2C8D15A,
+0x622C6612, 0x89033626, 0x6010D158, 0x8BC88801,
+0x51F66792, 0x217252F5, 0xD6555191, 0x55FA2212,
+0x52FB6462, 0x55612542, 0x2252E400, 0x61436643,
+0x05DE6013, 0x36CC4608, 0x07DE2652, 0xC9036071,
+0x8B028801, 0x720162E2, 0x74012E22, 0x36B3664C,
+0x71048FEE, 0x66C2D147, 0x45286512, 0x265B4518,
+0x60822C62, 0x89018801, 0x0009A168, 0x6272D742,
+0x8B132228, 0xD42BD741, 0x6772D541, 0x51536242,
+0x312C327C, 0x24222228, 0x15138D05, 0x6262D63D,
+0xB1627201, 0xD6232622, 0x2622E200, 0x52916692,
+0x8B013620, 0x0009A144, 0x6061A06E, 0x001C001C,
+0x001D4020, 0x0000B38E, 0xFFFF0000, 0x12340000,
+0x001E1015, 0x00201274, 0x002039F4, 0x002018A2,
+0x00203A00, 0x00203A18, 0x00201860, 0x0020196C,
+0x00201288, 0x001C3510, 0x001C3624, 0x001E212C,
+0x002038F4, 0x0020348C, 0x002038FC, 0x00203908,
+0x00203914, 0x00203970, 0x00203974, 0x0020391C,
+0x0020391D, 0x00203920, 0x00117700, 0x0020398C,
+0x0020398A, 0x002034F0, 0x00117710, 0x001C3D30,
+0x001C36F8, 0x00117734, 0x001C3684, 0x001C3D00,
+0x001C1000, 0x001C1028, 0x00203504, 0x00203924,
+0x00117600, 0x00117740, 0x7FFFFFFF, 0x00201730,
+0x0020332A, 0x00202334, 0x00203DA4, 0x00203972,
+0x002034FC, 0x00203964, 0x001C3D2C, 0x001C36B0,
+0x00203494, 0x0011775C, 0x8801C90F, 0xA0CF8901,
+0xD1960009, 0x36206212, 0xD4958904, 0x2421E200,
+0x2162A0CC, 0x6211D193, 0x89012228, 0x0009A0C3,
+0xE202D78F, 0x75016571, 0x3123615D, 0x27518D02,
+0x0009A0BC, 0xD28C57F2, 0x62226072, 0x40094019,
+0xC90F4009, 0x8F19880A, 0x52F31F2C, 0x40196022,
+0x40094009, 0x8808C90F, 0xA0A78901, 0x60630009,
+0xCB0154F7, 0xD27E55F2, 0xE7012402, 0xD47FE100,
+0x22112572, 0x72016242, 0x2422A098, 0x8B3F8805,
+0x602252F3, 0x40094019, 0xC90F4009, 0x8B168802,
+0xE4FFD577, 0x644D6752, 0x8B102748, 0x6272D775,
+0x8B0C3260, 0x51F255F7, 0xD26DE701, 0x21722562,
+0xD571E100, 0x64522211, 0xA0777401, 0x52F32542,
+0x40196022, 0x40094009, 0x8805C90F, 0x31B38B6E,
+0xD26A8B6C, 0x672254F4, 0x7701D569, 0x61422272,
+0x1F1CE640, 0x46182159, 0x8B033160, 0x6262D665,
+0x26227201, 0xE200D65A, 0x2621B067, 0x0009A056,
+0x3123E220, 0x88038B52, 0x52F38B1E, 0x40196022,
+0x40094009, 0x8803C90F, 0xD25B8B16, 0x672254F4,
+0x7701D557, 0x61422272, 0x1F1CE640, 0x46182159,
+0x8B033160, 0x6262D655, 0x26227201, 0xE200D648,
+0x2621B043, 0x0009A010, 0xD452D551, 0xD2446752,
+0xE1007701, 0x25723A46, 0x22118F06, 0xEA00D64E,
+0x72016262, 0x2622B031, 0x2FB2D54C, 0x95736652,
+0xD44A5BF1, 0x36205241, 0x60618910, 0x8B01C803,
+0x2B22E201, 0x8FF54510, 0x57F15664, 0x6272E1F0,
+0x41284118, 0x2722221B, 0x6BF2A008, 0x6BF2A006,
+0xE200D62F, 0xD12F2621, 0x2121E200, 0xD13CE201,
+0x66122822, 0x8B012668, 0x0009AE2B, 0x450BD539,
+0xD1390009, 0xAE24E600, 0x2F862160, 0x2FA62F96,
+0x2FC62FB6, 0x2FE62FD6, 0x7FF44F22, 0xDE34D133,
+0x54116212, 0x1F4167E2, 0x2F22D432, 0xD5321F72,
+0xD2326743, 0x58417794, 0x69425A42, 0x5B166C72,
+0x60526D22, 0xCB20E600, 0xE5402502, 0x626D7601,
+0x8BFB3253, 0x55F162F2, 0x11512122, 0xD62855F2,
+0x14812E52, 0x249214A2, 0x27C2D426, 0x26D211B6,
+0xDA256742, 0xE801D925, 0x490B2A72, 0xE2011A8C,
+0x1A2C4218, 0x4F267F0C, 0x6DF66EF6, 0x6BF66CF6,
+0x69F66AF6, 0x68F6000B, 0x000007D1, 0x00203984,
+0x00203988, 0x0020398E, 0x001C3DC0, 0x0011772C,
+0x001C3B88, 0x0020396C, 0x0011773C, 0x00117744,
+0x0000F000, 0x00117764, 0x00117748, 0x00117768,
+0x0011776C, 0x01FFFFFF, 0x0011774C, 0x002034FC,
+0x00203DA4, 0x002024F8, 0x00203972, 0x001C3B9C,
+0x001C3D98, 0x001C3700, 0x001C3500, 0x001C5960,
+0x001C8960, 0x00203504, 0x001C3D00, 0x0020160C,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xDE957FAC, 0x61E0E014, 0x0F14D494, 0x710161E3,
+0xE0186210, 0xD2920F24, 0x0009420B, 0x450BD591,
+0x20080009, 0x8F126D03, 0xD28F1F07, 0x6720D48F,
+0x657CDD8F, 0x470BD78F, 0xD18F0009, 0x619C6910,
+0x46086613, 0x36184608, 0x3D6C4608, 0xE0181FD7,
+0xE58004FC, 0x604C66E2, 0x3050655C, 0x2D628F15,
+0x01FCE014, 0xDE85E500, 0x641CA008, 0x6753655D,
+0x607037EC, 0x39DC6953, 0x80947501, 0x3243625D,
+0xD67F8BF4, 0xA34EE200, 0x20082621, 0xE0148B13,
+0xE40001FC, 0xA009DE79, 0x644D671C, 0x35EC6543,
+0x69436652, 0x39DC6262, 0x74041921, 0x3273624D,
+0xA3388BF3, 0x88012D10, 0xE0148B17, 0xE70001FC,
+0x6D1C2D70, 0xDE6D1FD4, 0x32D3627D, 0xA32A8B01,
+0x677D0009, 0x667365E3, 0x61737504, 0x315C36EC,
+0x69126462, 0xAFEF7708, 0x88042492, 0xE0148B18,
+0xE40001FC, 0x671C2D40, 0x624DDE60, 0x8B013273,
+0x0009A311, 0x6943644D, 0x39EC62E3, 0x72046592,
+0x3D2C6D43, 0x615266D2, 0x21697408, 0x2512AFED,
+0x8B188805, 0x01FCE014, 0x2D40E400, 0xDE53671C,
+0x3273624D, 0xA2F68B01, 0x644D0009, 0x62E36943,
+0x659239EC, 0x6D437204, 0x66D23D2C, 0x74086152,
+0xAFED216B, 0x88312512, 0xD44A8B3A, 0x6146D94A,
+0x75046543, 0x67566442, 0x6E531F48, 0x65527E04,
+0x7EE462E2, 0x7E0464E2, 0x6EE21FE9, 0x5EF929E0,
+0x7E04D942, 0x1FEA60E2, 0x2900C901, 0xD9406EE2,
+0x29E04E09, 0x2F562F26, 0x56FAD93E, 0x6513490B,
+0xD13D7F08, 0xE71C6E0D, 0x1DE12D70, 0xDE3B6912,
+0x64E21D92, 0x1D43D13A, 0xD23A6512, 0x67221D54,
+0x1D75D239, 0x1D666622, 0x6262D638, 0x1D27A2AB,
+0x8B398830, 0x6596D92B, 0x67926696, 0x61967904,
+0x74E46493, 0x6E436992, 0x1F9B7E04, 0x1FEC6442,
+0xD9256EE2, 0x5EFC29E0, 0x7E04D924, 0x1FED60E2,
+0x2900C901, 0xD9226EE2, 0x29E04E09, 0x59FC7FFC,
+0xDE272F92, 0x2F164E0B, 0xD41F7F08, 0xE21C610D,
+0x1D112D20, 0xD2206442, 0xD41C1D42, 0x1D536542,
+0x6752D51B, 0xD71B1D74, 0x1D156172, 0x1D666622,
+0x6262D61A, 0x1D27A26F, 0x8B358833, 0x490BD919,
+0xA268EE00, 0x00002DE0, 0x00117800, 0x00203A1C,
+0x002018A2, 0x00202AAC, 0x0020390E, 0x00203A20,
+0x00203534, 0x002018EE, 0x0020390D, 0x00117804,
+0x0020398C, 0x00117810, 0x00203909, 0x0020390A,
+0x0020390B, 0x00200F64, 0x001C5864, 0x001C6864,
+0x001C7864, 0x001C59BC, 0x001C69BC, 0x001C79BC,
+0x00200FBC, 0x00200FB8, 0x89018828, 0x0009A0C0,
+0xE643DEB5, 0x326662E1, 0x1FEE8F02, 0x2E21E240,
+0x622D62E1, 0x8B013267, 0x0009A0AA, 0xE50185E1,
+0x8B013056, 0x0009A0A4, 0x2D10E101, 0x64E1B225,
+0xE64357FE, 0x652D6271, 0x89443567, 0x3563E640,
+0xE6008B05, 0x0F65E040, 0xA00FE11A, 0x615372C0,
+0x41214121, 0x41214121, 0x45214121, 0x45214521,
+0xC9036053, 0xE0406603, 0x71180F65, 0x2209E007,
+0x0F25E03C, 0xE044641D, 0xB2A365F3, 0xE33C0F46,
+0x853233FC, 0x620DDE95, 0x42086031, 0x6023610D,
+0x1323E944, 0x06FE4108, 0xE00F39FC, 0x13144E0B,
+0x67075D91, 0x60D32679, 0x0F6654FE, 0x51928542,
+0x600D4E0B, 0x60D3260B, 0x0F666492, 0x65F3B237,
+0x696156FE, 0xE640659D, 0x89383563, 0xD78359FE,
+0x79066591, 0xC9036053, 0x40004008, 0x61036203,
+0x0F26E050, 0x470BE0FF, 0x6C07600C, 0x6603605D,
+0x46214621, 0x46214621, 0x42006263, 0x4200326C,
+0x40214021, 0x4008C903, 0x6D2D30FC, 0xE8006A03,
+0xB25765F3, 0x6EA264D3, 0x2EC9E050, 0x66942AE2,
+0xD76E01FE, 0x606C470B, 0x2AE22E0B, 0x64D365F3,
+0x7801B1FD, 0xEE06628D, 0x8FE932E3, 0x5EFE7D01,
+0x61E1E400, 0x410085E1, 0x66E3310C, 0x760C711B,
+0xE70465F3, 0x68667401, 0x3A736A4D, 0x8FF92582,
+0x65F37504, 0x641DB1E3, 0x64E1B1A4, 0x0009A17B,
+0xD45B56F7, 0xEC01D25B, 0x26C0420B, 0x0009A173,
+0x06FCE018, 0x8829606C, 0x58F78B08, 0xE400D252,
+0x66222840, 0x646DB171, 0x0009A165, 0x666CE681,
+0x89013060, 0x0009A0AC, 0xD550D14F, 0x62126A56,
+0x212232AC, 0x54116C56, 0x34CC6253, 0x64521141,
+0x72085812, 0xD44A384C, 0x68221182, 0x5A136C42,
+0x3ACC3C8C, 0x11A324C2, 0x6C2272EC, 0x72105814,
+0x118438CC, 0x5A156822, 0x11A53A8C, 0x6A227210,
+0xD6405816, 0x118638AC, 0x52176C62, 0x112732CC,
+0x5A185861, 0x11A83A8C, 0x5C195A62, 0x11C93CAC,
+0x521A5C63, 0x112A32CC, 0x5A1B5864, 0x11AB3A8C,
+0x5C1C5A65, 0x11CC3CAC, 0x521D5C66, 0x112D32CC,
+0x5A1E5867, 0x11AE3A8C, 0x561F5A68, 0x36ACE840,
+0x116FDA2D, 0x6CA2381C, 0x7A946682, 0x286236CC,
+0x5C8162A2, 0x18C13C2C, 0x62A27A44, 0x362C5682,
+0xD6261862, 0x5A856262, 0x3A2C4229, 0x760418A5,
+0x56866262, 0x362C4229, 0x56F71866, 0x2620E238,
+0x16C15C81, 0x16226212, 0xE2005C11, 0x551216C3,
+0x55151654, 0x55131655, 0x55161656, 0x55821657,
+0x65821658, 0x55141659, 0x5584165A, 0x5583165B,
+0x5585165C, 0x5586165D, 0x1821165E, 0x11212122,
+0x11251122, 0x11261123, 0x28221822, 0x18241124,
+0x18251823, 0x1826A0C7, 0x00117804, 0x002033E8,
+0x00203A40, 0x002018A2, 0x00203494, 0x001C36A0,
+0x002034F0, 0x001C3CA0, 0x001C36F4, 0x001C3B88,
+0x666CE682, 0x8B203060, 0xEA2456F7, 0x26A0D194,
+0x16C15C17, 0x16225218, 0x16835819, 0x16A45A1A,
+0x16C55C1B, 0x1626521C, 0xE200581D, 0x551E1687,
+0x551F1658, 0x11271659, 0x11291128, 0x112B112A,
+0x112D112C, 0xA08E112E, 0xE683112F, 0x3060666C,
+0x52F78B0B, 0xEA00D883, 0x658222A0, 0x7804DC82,
+0x62822C52, 0xA07ED681, 0xE6902620, 0x3060666C,
+0xDA7F8B06, 0x00094A0B, 0xE20056F7, 0x2620A073,
+0x666CE691, 0x8B103060, 0x6222D276, 0x2228622C,
+0xD2788904, 0x0009420B, 0x0009A003, 0x420BD276,
+0x56F70009, 0xA05EE200, 0xE6922620, 0x3060666C,
+0xE0188951, 0xE6B00BFC, 0x666C62BC, 0x8B2A3260,
+0x02FCE014, 0x682CEA00, 0x62ADE904, 0x894A3283,
+0x6AADDD64, 0x3CDC6CA3, 0x7D046EC2, 0xDB68D467,
+0x32DC62A3, 0x4B0BDC67, 0x4C0B6D22, 0xD46664E3,
+0x00094B0B, 0x64D34C0B, 0x4B0BD464, 0xE6000009,
+0x666D6BE3, 0x76013B6C, 0x3293626D, 0x8FF72BD0,
+0xAFDA4D19, 0xE6B57A08, 0x3260666C, 0xD45C8B13,
+0x4B0BDB57, 0xD25B0009, 0x6022DB5B, 0xCB20E6FF,
+0x2202666D, 0xDB592B62, 0xE014E200, 0x56F72B20,
+0xA01002FC, 0xD4562620, 0x6542D256, 0x420BD456,
+0xA0080009, 0xDB520009, 0x52B1E600, 0x622CDB53,
+0x52F72B21, 0x7F542260, 0x6EF64F26, 0x6CF66DF6,
+0x6AF66BF6, 0x000B69F6, 0x4F2268F6, 0xE240614D,
+0x89143123, 0x3127E21F, 0x8B09D749, 0xD449614D,
+0xE00171E0, 0x5671440B, 0x26596507, 0x1761A007,
+0xE001D444, 0x6672440B, 0x26596507, 0x4F262762,
+0x0009000B, 0x614D4F22, 0x3123E240, 0xE21F8912,
+0xD73B3127, 0x614D8B08, 0x5671D23A, 0x420B71E0,
+0x260BE001, 0x1761A006, 0x6672D236, 0xE001420B,
+0x2762260B, 0x000B4F26, 0xE6400009, 0x46284618,
+0x6252D531, 0x89FC2268, 0x0009000B, 0x4618E680,
+0xD52D4628, 0x22686252, 0x000B89FC, 0xA0010009,
+0x7201E200, 0x8BFC3242, 0x0009000B, 0x4618E680,
+0xD5264628, 0x22686252, 0x000B8BFC, 0x2FE60009,
+0x7FFC4F22, 0xBFF16E53, 0x61E22F42, 0xE280D620,
+0x54E11615, 0x16464218, 0x422855E2, 0x57E31657,
+0x16786EF2, 0x26E22E2B, 0x4F267F04, 0x6EF6AFCE,
+0x00203494, 0x00117804, 0x002038F4, 0x00203908,
+0x0020050A, 0x00201008, 0x0020102E, 0x00203A58,
+0x002018A2, 0x002018E6, 0x00203A6C, 0x00203A74,
+0x00203A78, 0x001C3500, 0x001C1000, 0x0020398A,
+0x00117800, 0x002018EE, 0x00203A8C, 0x00203990,
+0x001C3704, 0x002033E8, 0x001C373C, 0x001C3700,
+0x001C370C, 0x2FD62FC6, 0x4F222FE6, 0x6C53DD10,
+0x6E43BFA4, 0x2DE2BF89, 0x0009BFA0, 0x2C1251D5,
+0x1C4154D6, 0x1C5255D7, 0x1C6356D8, 0x6EF64F26,
+0x000B6DF6, 0x61636CF6, 0xA004E600, 0x62564109,
+0x24227601, 0x36127404, 0x000B8BF9, 0x00000009,
+0x001C370C, 0x0009A16E, 0x2FE62FD6, 0xDD944F22,
+0xA0049EB2, 0xD4930009, 0x420BD293, 0x62D265D2,
+0x8BF822E8, 0x0009A004, 0xD28FD490, 0x55D1420B,
+0x22E852D1, 0xA0048BF8, 0xD48D0009, 0x420BD28A,
+0x52D255D2, 0x8BF822E8, 0x0009A004, 0xD286D489,
+0x55D3420B, 0x22E852D3, 0xA0048BF8, 0xD4860009,
+0x420BD281, 0x52D455D4, 0x8BF822E8, 0x6EF64F26,
+0x6DF6000B, 0x2FD62FC6, 0x4F222FE6, 0x6E636C73,
+0x6D53B01A, 0x64D357F4, 0xB05F65E3, 0xB07566C3,
+0xB0A40009, 0xB0A80009, 0xB0AC0009, 0xB0AC0009,
+0xB0AF0009, 0xB03154F5, 0x6CCD6C03, 0x4F2660C3,
+0x6DF66EF6, 0x6CF6000B, 0x3412D170, 0xD6700529,
+0x2650D770, 0x2742000B, 0x0009A018, 0x2FD62FC6,
+0x4F222FE6, 0x6E636C73, 0x6D53BFEE, 0x64D357F4,
+0xB03365E3, 0xB08D66C3, 0xB00F54F5, 0x6CCD6C03,
+0x4F2660C3, 0x6DF66EF6, 0x6CF6000B, 0xE503D162,
+0xD763D462, 0x21524518, 0x2472000B, 0xD45FD15E,
+0x2162E600, 0x2462000B, 0xBF734F22, 0xBF73E40A,
+0xD25C0009, 0x4118E104, 0xE40AE500, 0xBF692212,
+0xD7592252, 0xCB206072, 0x000B4F26, 0x4F222702,
+0x410BD156, 0xD556E400, 0x4F26452B, 0xD1552FE6,
+0x66126E63, 0x92104418, 0x44084528, 0x45002629,
+0x265B4408, 0x264B4400, 0x21624708, 0xD14E4708,
+0x217227EB, 0x6EF6000B, 0x1FFF03F0, 0x4F222FE6,
+0xE101DE4A, 0xBF3DE40A, 0x67E32E12, 0xE500776C,
+0xE204E130, 0x2752E40A, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27222712,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x175ABF18, 0x2E62E600, 0x000B4F26, 0xD2346EF6,
+0xE441E101, 0x000B2212, 0xD1322242, 0xE605D432,
+0x000B2162, 0x000B2462, 0xD2300009, 0xE40AE601,
+0x2262AF00, 0x2FC62FB6, 0x2FE62FD6, 0x7FFC4F22,
+0x6C43DB2B, 0xED0060B2, 0x2B02CB03, 0xC90360B2,
+0x6E03A008, 0x89073DC2, 0xE46460B2, 0xB07CC903,
+0x7D016E03, 0x8BF52EE8, 0x8F043DC2, 0xD4212FE1,
+0x460BD621, 0x62F10009, 0x6023622D, 0x89FFC801,
+0x7F046023, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x001C3B88, 0x00203AA0, 0x002018EE, 0x00203AA8,
+0x00203AB0, 0x00203AB8, 0x00203AC0, 0x0025E720,
+0x00203DA0, 0x002038F8, 0x001C5968, 0x001C3B40,
+0x000F8000, 0x001D4004, 0x001C3500, 0x002015E0,
+0x0020160C, 0x001C5814, 0x001C59D0, 0x001C5830,
+0x001C6268, 0x001C59A4, 0x001C639C, 0x001C581C,
+0x001C5860, 0x00203AC8, 0x002018A2, 0x8F014411,
+0x6043604B, 0x0009000B, 0x5651D52B, 0x46286052,
+0x306C000B, 0x2FC62FB6, 0x2FE62FD6, 0x4F124F22,
+0xBFF14F02, 0x6B036E43, 0xDD25DC24, 0x0009BFEC,
+0x3C0530B8, 0x4609060A, 0x46014609, 0x020A3D65,
+0x42094209, 0x32E24209, 0x4F068BF0, 0x4F264F16,
+0x6DF66EF6, 0x000B6CF6, 0x2FC66BF6, 0x2FE62FD6,
+0x4F124F22, 0xBFCF4F02, 0x6C036E43, 0xBFCBDD13,
+0x30C80009, 0x060A3D05, 0x46094609, 0x36E24601,
+0x4F068BF5, 0x4F264F16, 0x6DF66EF6, 0x6CF6000B,
+0x4F222FE6, 0xE102DE0B, 0xE403E500, 0xBFB92E12,
+0xE6062E52, 0xE7004618, 0x2E62E403, 0x4F262E72,
+0x6EF6AFB0, 0x0009000B, 0x001C1040, 0xCCCCCCCD,
+0x10624DD3, 0x001D4004, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE5007F98, 0x6453E710,
+0x6B534728, 0xEE1ADCBC, 0x6153655D, 0x315C4108,
+0x75014108, 0x6043317C, 0x0F16665D, 0xED0060B3,
+0x21B136E3, 0x81128111, 0x11D28113, 0x11D411D3,
+0x74048FEA, 0xD8B167F2, 0x1871D9B1, 0x58F12872,
+0x1981D1B0, 0x59F22982, 0x5DF45AF3, 0x54F65EF5,
+0x21921191, 0x11A211A3, 0x11D411D5, 0x11E611E7,
+0x11481149, 0xDAA855F7, 0x57F8EE00, 0x52F9DDA7,
+0x64E3D6A7, 0x2A521A51, 0xD8A7D9A6, 0x2D729AD5,
+0x6EED2622, 0x4D086DE3, 0x3DEC61E3, 0x4D084108,
+0x3D9C31EC, 0x410860B3, 0x81D12DB1, 0x4108E050,
+0x4008E7B7, 0x677C4108, 0x60B381D2, 0xE200318C,
+0x81D33472, 0x1D131DD2, 0x8D01D493, 0xD4901D24,
+0xB0B365D3, 0x64ED7E01, 0x8BDA34A2, 0x2FD2DA8C,
+0xDD9268A2, 0x2D824829, 0x7DFC64A2, 0xD287694D,
+0x6E222D92, 0x7D0C4E29, 0x68222DE2, 0x618D6AD3,
+0x2A16D784, 0xD48A6D72, 0x24D2D583, 0xD6895E72,
+0x517414E2, 0x1414EE00, 0xD1875876, 0x59781486,
+0x1498E710, 0x65E36252, 0x26E2142A, 0xE60064E3,
+0x6843644D, 0x384C4808, 0x381C4808, 0x0C866053,
+0x09CE28B1, 0x819160B3, 0x0ACE6053, 0x81A26043,
+0x0DCE6053, 0x81D360B3, 0x08CE6053, 0x18827401,
+0x624D09CE, 0x0ACE19E3, 0x1A643273, 0x75048FE0,
+0xE003D96A, 0x40186C92, 0x6D922CB1, 0x81D1DA6F,
+0x6E92E050, 0x81E24008, 0x60B36192, 0x64928113,
+0x1442E600, 0xD4696792, 0x689217A3, 0x1864E1FF,
+0x6563E703, 0x364C4608, 0x26127501, 0x3673665D,
+0xDC5B8BF8, 0x6DC2E003, 0x2DB14018, 0xD2606EC2,
+0x61C281E1, 0x1112EE00, 0xE02464C2, 0x65C21423,
+0x15E4D45B, 0xE58067C2, 0x68C28172, 0x818366E3,
+0x666D655C, 0x76046963, 0x394C6A6D, 0x8FF83A53,
+0xDB5429E2, 0x24B2DC54, 0x24C27404, 0x4F267F68,
+0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6, 0x68F6000B,
+0x60116142, 0x8F03C803, 0xD23DE500, 0x8B063420,
+0xC9036011, 0x8B068802, 0x3420D239, 0x56128B03,
+0x52646513, 0x000B2422, 0x01136053, 0x2FE62FD6,
+0x7FEC4F22, 0x62536E53, 0x6D43E550, 0x4508E400,
+0xE101A001, 0x60435224, 0x81212211, 0x60538123,
+0x56E28122, 0x8BF53620, 0x16E4D238, 0xE61464F3,
+0x65E3420B, 0xE4FC65E1, 0x2E512549, 0x65F361F1,
+0x2F112149, 0xD13154D1, 0xE614410B, 0x607157D1,
+0x2701CB01, 0x7F141DE1, 0x6EF64F26, 0x6DF6000B,
+0x2FE62FD6, 0x7FEC4F22, 0x66536E53, 0x6D43E5FC,
+0x20596061, 0x2601CB01, 0x326052E2, 0x12E48B06,
+0x31E051E2, 0x52D18B04, 0x1E22A002, 0x5664AFF0,
+0x64F3D21E, 0x420BE614, 0x67E165E3, 0x2719E1FC,
+0x67F12E71, 0x271954D1, 0x65F3D118, 0x410BE614,
+0x52D12F71, 0xCB016021, 0x1DE12201, 0x4F267F14,
+0x000B6EF6, 0x00006DF6, 0x00203924, 0x002034F4,
+0x002034FC, 0x00203504, 0x0020352C, 0x00203910,
+0x00203918, 0x00100208, 0x001017C0, 0x001E210C,
+0x001C3D00, 0x00203964, 0x001000C8, 0x00117880,
+0x00117780, 0x00040020, 0x0026C401, 0x00200ED6,
+0x4F222FE6, 0xDE42624C, 0x42004208, 0x3E2CA005,
+0xD4405252, 0xBF695624, 0x65E22E62, 0x352052E1,
+0xD63D8BF6, 0x4F262622, 0x6EF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xDC394F22, 0x52C1DB39, 0x362066C2,
+0x6061891C, 0x8801C903, 0xDE348918, 0xBF37DD35,
+0x650364E3, 0x66B28503, 0x3262620D, 0xD4328907,
+0x0009BF76, 0x4D0BD431, 0xAFE60009, 0xBF3D0009,
+0xD42F64E3, 0x00094D0B, 0x0009AFDF, 0x2262D22D,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x2FD62FC6,
+0x4F222FE6, 0xDD29DC28, 0x6E4360C2, 0x04DE4008,
+0xE614D127, 0x65E3410B, 0xD127D726, 0x55E227E2,
+0x35E05254, 0x21228F04, 0x400860C2, 0x122202DE,
+0x605365C2, 0x75014008, 0x0DE606DE, 0xC90F6053,
+0x60632C02, 0x6EF64F26, 0x000B6DF6, 0x85436CF6,
+0x650D5643, 0x622D6262, 0x35277204, 0xE1008F0C,
+0x2268960C, 0xD6158B03, 0x72015261, 0xD6131621,
+0x6262E101, 0x26227201, 0x6013000B, 0x000001FF,
+0x00203504, 0x002034FC, 0x001C3D00, 0x0020352C,
+0x002038F4, 0x002018A2, 0x002034F4, 0x00203AF0,
+0x00203AF4, 0x001C3D28, 0x00203964, 0x00203924,
+0x00200ED6, 0x00203968, 0x0020396C, 0x00117754,
+0x2FC62FB6, 0x2FE62FD6, 0x7FF84F22, 0x6022D237,
+0x8D58C803, 0xDE362F01, 0xDB37DC36, 0x66C252C1,
+0x892F3620, 0xC9036061, 0x892B8801, 0xD233DD31,
+0x64D3420B, 0x1F016503, 0x880160B1, 0xD2308B04,
+0x64D3420B, 0x0009AFEA, 0x85615653, 0x8904C820,
+0xE050D72C, 0x7201027E, 0xD22B0726, 0x6453420B,
+0x89072008, 0x55F1D126, 0x64D3410B, 0xE601D727,
+0x2762AFD4, 0x55F1D226, 0x64E3420B, 0xE601D125,
+0x2162AFCC, 0xDD25DE24, 0xDC26DB25, 0x66D252D1,
+0x89183620, 0xC9036061, 0x89148801, 0xD117D41F,
+0x0009410B, 0x36E05603, 0x65038F04, 0x2B20E201,
+0x2C52AFEC, 0xD712D41C, 0x0009470B, 0xE601D115,
+0xAFE34618, 0x60F12162, 0x8907C804, 0x7F08D217,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6422B, 0x4F267F08,
+0x6DF66EF6, 0x000B6CF6, 0x00006BF6, 0x001E2100,
+0x00203504, 0x002034FC, 0x0020398C, 0x002014A0,
+0x002014CC, 0x00203494, 0x002016BE, 0x001E212C,
+0x00201530, 0x001C3D30, 0x00117880, 0x002034F4,
+0x00203914, 0x00203910, 0x0020352C, 0x00200610,
+0xE601D203, 0x1265D503, 0x000B2252, 0x00001266,
+0x001C1010, 0x0000C34F, 0x0009000B, 0x2FD62FC6,
+0x4F222FE6, 0x6D436C53, 0xEE00A004, 0x7E0164D4,
+0x644CBFF2, 0x8BF93EC2, 0x6EF64F26, 0x000B6DF6,
+0xE5006CF6, 0x6643A002, 0x76017501, 0x22286260,
+0xAFE38BFA, 0x2FE60009, 0x75076253, 0xE1086753,
+0x6043EE0A, 0x4409C90F, 0x650330E2, 0x8D014409,
+0xE630E637, 0x4110365C, 0x8FF22760, 0xE00077FF,
+0x000B8028, 0x000B6EF6, 0x000BE000, 0x2FE6E000,
+0x7FEC4F22, 0x6E436253, 0xBFDC65F3, 0xBFD06423,
+0xBFCE64E3, 0xD40364F3, 0x0009BFCB, 0x4F267F14,
+0x6EF6000B, 0x00203AF8, 0xE4FDD29F, 0xD79F6122,
+0x22122149, 0x74016022, 0x2202CB01, 0xD59C6622,
+0x22622649, 0xC8406070, 0x60528902, 0x2502CB04,
+0xE1F76452, 0x25422419, 0xE7016052, 0x2502CB40,
+0xE6026052, 0x2502C9CF, 0x47186052, 0x2502CB10,
+0xCB036052, 0x15622502, 0x1573000B, 0xD78ED58D,
+0xD48FD28E, 0xE600E100, 0x27112511, 0xAFCB2210,
+0x664C2461, 0x4600D28B, 0x6060362C, 0x000BCB10,
+0x654C2600, 0x4500D287, 0x6650352C, 0x2619E1EF,
+0x2560000B, 0xD284664C, 0x362C4600, 0xCB106060,
+0x2600000B, 0xD280654C, 0x352C4500, 0xE1EF6650,
+0x000B2619, 0x664C2560, 0x4600D27A, 0x6060362C,
+0x000BCB08, 0x654C2600, 0x4500D276, 0x6650352C,
+0x2619E1F7, 0x2560000B, 0xD273664C, 0x362C4600,
+0xCB086060, 0x2600000B, 0xD26F654C, 0x352C4500,
+0xE1F76650, 0x000B2619, 0x624C2560, 0x4200D669,
+0x6020326C, 0x4021C908, 0x40214021, 0x600C000B,
+0xD665624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0xD161600C, 0x341C644C, 0x000B6240,
+0xD15F602C, 0x341C644C, 0x000B6240, 0x2FE6602C,
+0x6E434F22, 0xE60A645C, 0x89143467, 0x0009BFEB,
+0x60EC640C, 0x8B028801, 0xA002E00F, 0x44092409,
+0x624C4409, 0x3263E60A, 0xBFE28905, 0x620C644C,
+0xC8806023, 0xE2008B00, 0x4F266023, 0x6EF6000B,
+0xD64C4F22, 0x88016062, 0xB2578B03, 0xA0030009,
+0xD2490009, 0x2260E640, 0xE200D648, 0x000B4F26,
+0x4F222622, 0x6062D643, 0x8B018802, 0x0009B2A0,
+0xE200D642, 0x000B4F26, 0xD53E2622, 0xE100D43E,
+0x2512E701, 0x2470000B, 0xE604D23B, 0x2260000B,
+0xD43B4F22, 0x410BD13B, 0xD53B0009, 0x6650E1FD,
+0x2619D23A, 0x2560E700, 0x000B4F26, 0x4F222270,
+0xD238D537, 0xD7386152, 0x2512611D, 0xE6FF6452,
+0x2542242B, 0xD22FD435, 0x420B666D, 0xD52E2762,
+0x6750E1FB, 0x4F262719, 0x2570000B, 0xD4304F22,
+0x410BD128, 0xD5280009, 0x6650E7F7, 0x4F262679,
+0x2560000B, 0x9425D524, 0x22496250, 0x2520000B,
+0xE4BFD521, 0x22496250, 0x2520000B, 0xD2254F22,
+0x600D8522, 0x89112008, 0x89458801, 0x89478803,
+0x89498805, 0x894F8806, 0x89558808, 0x895B8809,
+0x8961880A, 0x8967880B, 0x0009A06E, 0x0009B070,
+0x600CA06B, 0x0000FF7F, 0x001E2148, 0x001E1000,
+0x001E1108, 0x002039C4, 0x002039C6, 0x002039E5,
+0x002039A8, 0x001E103F, 0x001E105F, 0x001E102F,
+0x001E1090, 0x002039CC, 0x001E100B, 0x002039C8,
+0x00203AFC, 0x002018A2, 0x001E1028, 0x002039E4,
+0x001D4020, 0x98760000, 0x001C1000, 0x00203B08,
+0x00203B18, 0x0020399C, 0x0009B04C, 0x600CA035,
+0x0009B055, 0x600CA031, 0x6260D684, 0x8B2B2228,
+0x0009B061, 0x600CA029, 0x6260D680, 0x8B232228,
+0x0009B069, 0x600CA021, 0x6260D67C, 0x8B1B2228,
+0x0009B0C7, 0x600CA019, 0x6260D678, 0x8B132228,
+0x0009B0CD, 0x600CA011, 0x6260D674, 0x8B0B2228,
+0x0009B125, 0x600CA009, 0x6260D670, 0x8B032228,
+0x0009B13D, 0x600CA001, 0x4F26E000, 0x0009000B,
+0xD26CD16B, 0xD56C8412, 0x4000C90F, 0xD76B012D,
+0xE403D66B, 0xE20F611C, 0x2540E001, 0x25202712,
+0x2602000B, 0xE601D262, 0x30668523, 0xE0008D05,
+0xD663D260, 0xE0018122, 0x000B2602, 0xD25C0009,
+0x600D8523, 0x89052008, 0x8B0A8801, 0x6060D65D,
+0x2600CB01, 0xD457D65A, 0xE001E101, 0x000B2612,
+0x000B8142, 0xD152E000, 0x8513E501, 0x640D4518,
+0x66033453, 0xE0008D05, 0xD551D253, 0x2260E001,
+0x000B2502, 0x4F220009, 0x8513D149, 0x6453650D,
+0x62494419, 0x227D672E, 0x8801602C, 0x88028909,
+0x88038910, 0x8806891A, 0x88078935, 0xA04C893B,
+0xD5460009, 0x6652D746, 0x2762D446, 0x622C6261,
+0x2421A038, 0x2228625C, 0xD4438B3F, 0x6642D540,
+0x2562D440, 0x24018561, 0x6203A02C, 0x2008605C,
+0x88108907, 0x88208908, 0x88308909, 0xA02C890A,
+0xD23A0009, 0x6222A008, 0xA005D239, 0xD2396222,
+0x6222A002, 0x6262D638, 0xD432D531, 0x66212522,
+0xA00F626C, 0xD6352421, 0x6261D52D, 0x622CD42D,
+0xA0072562, 0xD6322421, 0x8561D529, 0x2562D429,
+0x62032401, 0x662D8515, 0x3617610D, 0x65038F01,
+0xB0CB2451, 0xA0010009, 0xE000E001, 0x000B4F26,
+0xD6190009, 0xD427E101, 0x65412610, 0xD118D717,
+0xE20F655D, 0x2752E001, 0x000B2620, 0x2FE62102,
+0xD20F4F22, 0x640C8523, 0x8B082448, 0xD511D61D,
+0x2621E200, 0x940F8451, 0xA0482049, 0xDE0D8051,
+0xC84060E0, 0xE2018D32, 0x89443427, 0xD216D615,
+0x2641420B, 0x0009A030, 0x0000FF7F, 0x002039E5,
+0x0020399C, 0x002039A8, 0x001E1100, 0x001E100C,
+0x002039C8, 0x001E1000, 0x001E1001, 0x002039D0,
+0x002039B0, 0x002039B4, 0x002039B8, 0x002039D4,
+0x002039D8, 0x002039DC, 0x002039E0, 0x00203E04,
+0x00203E0E, 0x002039C2, 0x00202886, 0x89123427,
+0xD294D693, 0x2641420B, 0xCB8084E1, 0x80E1B0F5,
+0xD69160E0, 0x2E00CB04, 0xC93F6060, 0xD68F2600,
+0xA001E001, 0xE0002602, 0x000B4F26, 0xD68C6EF6,
+0xC8806060, 0xD2868919, 0x88016021, 0xD2898B15,
+0x8524E501, 0x89103056, 0xE203D187, 0x2120D487,
+0xE00B6541, 0x0656655D, 0xE40FD585, 0x2140E702,
+0xD77E2571, 0x000BE001, 0x000B2702, 0x2FE6E000,
+0xDE804F22, 0xC88084E1, 0xD57A892C, 0x20088554,
+0x61038F28, 0x8553D77C, 0x64036672, 0x8566650C,
+0x3520620C, 0xD6798B1E, 0x651CD774, 0x2651644C,
+0x60E02741, 0x8904C840, 0x420BD275, 0xA0030009,
+0xD2680009, 0x0009420B, 0x0009B09F, 0xE201D167,
+0x60E02122, 0xCB04D464, 0x60402E00, 0x2400C93F,
+0x6023A001, 0x4F26E000, 0x6EF6000B, 0x2FB62FA6,
+0x2FD62FC6, 0xDA622FE6, 0x66A1E240, 0x3622DC5E,
+0x62638900, 0x6ED36D2C, 0x4E2136D8, 0x4E212A61,
+0xDB61D460, 0xE700A00F, 0x770162B2, 0x71026123,
+0x66212B12, 0x71026213, 0x61212B12, 0x651D666D,
+0x356C4528, 0x627C2452, 0x8BED32E3, 0xC90360D3,
+0x8B108803, 0x617367B2, 0x2B127102, 0x71026E13,
+0x2B126571, 0x655D6DE1, 0x422862DD, 0x325CE107,
+0xA00C2C10, 0x88022422, 0xA0038B01, 0x8801E203,
+0xE2018B05, 0x66B22C20, 0x655D6561, 0xE60F2452,
+0x67A12C60, 0x8B052778, 0xDD38DC44, 0xEB01EA00,
+0x2DB22CA2, 0x6DF66EF6, 0x6BF66CF6, 0x6AF6000B,
+0x2FE62FD6, 0xE240DD36, 0x362266D1, 0x62638900,
+0x3678672C, 0x7703DE38, 0x47212D61, 0x64E2D635,
+0xA00E4721, 0x6562E100, 0x62537101, 0x74012450,
+0x24204219, 0x45297401, 0x74012450, 0x24504519,
+0x621C7401, 0x8BEE3273, 0x66E24200, 0x420061D1,
+0x2118362C, 0x2E628F06, 0xDD1CD728, 0xE501E400,
+0x2D522742, 0x000B6EF6, 0x2FD66DF6, 0x4F222FE6,
+0xED0AEE01, 0x64E3BC85, 0xBC8A64E3, 0x62EC7E01,
+0x8BF732D7, 0xBC8DEE01, 0x64E364E3, 0x7E01BC92,
+0x32D762EC, 0x4F268BF7, 0x000B6EF6, 0xD1186DF6,
+0xD418920D, 0x72122122, 0x2422D617, 0xD7177204,
+0x72202622, 0x2722D116, 0x000B7230, 0x137A2122,
+0x002039C2, 0x00202992, 0x001E1015, 0x002039C8,
+0x001E1001, 0x0020399C, 0x001E1100, 0x002039C6,
+0x002039B4, 0x001E1000, 0x002039B8, 0x002039C4,
+0x00202886, 0x001E100C, 0x002039B0, 0x002039CC,
+0x002039D0, 0x002039D4, 0x002039D8, 0x002039DC,
+0x002039E0, 0x4F222FE6, 0xD6707FFC, 0x88016060,
+0xE2018951, 0x2620BFBB, 0xD56ED16D, 0xDE6E6010,
+0x64E36552, 0x7402C840, 0x8D22D16C, 0xD26C7502,
+0xE601D76C, 0xE7042722, 0x76016255, 0x626C2421,
+0x8FF93273, 0xD4637402, 0x6242E601, 0x640D8528,
+0x67494419, 0x275D657E, 0x81E4607C, 0xE417D562,
+0x67557601, 0x3243626C, 0x8FF92171, 0xA0207102,
+0xD25E0009, 0xE601D75B, 0xE7042722, 0x76016255,
+0x626C2421, 0x8FF93273, 0xD4527402, 0x6242E601,
+0x640D8528, 0x67494419, 0x275D657E, 0x81E4607C,
+0xE417D553, 0x67557601, 0x3243626C, 0x8FF92171,
+0x92897102, 0xD2462E21, 0x5E23D74E, 0x64F22FE2,
+0x604365F2, 0x2700C980, 0xC9606043, 0x80716103,
+0xC9036043, 0x80724519, 0x65F2605C, 0x817266F2,
+0x46194629, 0x606C4529, 0x4018645C, 0x8173304C,
+0x21185E23, 0x64F22FE2, 0x6E4C62F2, 0x602C4219,
+0x66F262F2, 0x46294018, 0x461930EC, 0x42298174,
+0x652C606C, 0x305C4018, 0x81758F07, 0x0009BC96,
+0x2228620C, 0xA00A8908, 0x60130009, 0x8B038840,
+0x0009B009, 0x0009A003, 0xE202D62F, 0x7F042622,
+0x000B4F26, 0x4F226EF6, 0x8552D52A, 0x8830600D,
+0x88318903, 0xA0348923, 0x85550009, 0xD428D727,
+0x85532701, 0x610DD627, 0x24124118, 0x460BD426,
+0xD7230009, 0xD226D425, 0x6572420B, 0xE230D120,
+0x42286712, 0x2729E620, 0x37604628, 0xD6218B03,
+0xA016E200, 0xD61F2622, 0xA012E202, 0xD1182622,
+0x6212E530, 0xE6204528, 0x46282259, 0x89083260,
+0xD41AD119, 0xE601D513, 0x2160450B, 0x472BD718,
+0x4F264F26, 0x0009000B, 0x0000060A, 0x002039E4,
+0x001E1000, 0x002039D0, 0x00203E04, 0x00203E10,
+0x00203DA8, 0x002039B8, 0x00203DD8, 0x00203DD6,
+0x00203DAA, 0x0020399C, 0x002039C8, 0x002039B4,
+0x002039B0, 0x002018A2, 0x00203B24, 0x00203B28,
+0x002018EE, 0x002039CC, 0x001E100B, 0x00203B3C,
+0x00114004, 0x4F222FE6, 0xDE967FFC, 0x200884E9,
+0x2F008D06, 0xD695D494, 0x0009460B, 0x64F0B19A,
+0x6620D293, 0x89022668, 0xC9BF60E0, 0x7F042E00,
+0x000B4F26, 0x000B6EF6, 0x2FE60009, 0xDE8D4F22,
+0x60E0D68D, 0xCBC0D48D, 0x62602E00, 0xC803602C,
+0x40218904, 0x70014021, 0x6603A002, 0x66034009,
+0xD687616D, 0xE500A004, 0x75016262, 0x74042422,
+0x3213625D, 0xD2838BF8, 0x0009420B, 0xC9BF84E2,
+0x4F2680E2, 0x6EF6000B, 0x2FE62FD6, 0x7FFC4F22,
+0x6260D67D, 0x89442228, 0xD572E100, 0x60502610,
+0xCB40D47A, 0x2500440B, 0x8D052008, 0x62E06E03,
+0x7104612C, 0x2F11A006, 0xD475D66D, 0xDD756760,
+0x657C4D0B, 0xE23C6D1D, 0x8B033D27, 0xD267D472,
+0x0009420B, 0x4D214D21, 0xA005D770, 0x66E6E400,
+0x357C4508, 0x74012562, 0x35D3654D, 0xD76C8BF7,
+0x6172E003, 0x81114018, 0x6E7260F1, 0x81E2700C,
+0xD4686172, 0xDD688113, 0x4D0BDE68, 0xE2016572,
+0xD4672E22, 0x420BD255, 0xD6560009, 0xC93F6060,
+0x7F042600, 0x6EF64F26, 0x6DF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xD25F4F22, 0x6B436E73, 0x420B6C53,
+0x20086D63, 0x64038D1C, 0xE50ED149, 0x32526210,
+0x60C38916, 0x804124B0, 0x814160D3, 0xA007E500,
+0x655D61BC, 0x00EC6053, 0x364C6653, 0x80647501,
+0x3213625D, 0xD63B8BF5, 0xC9BF6060, 0x2600A008,
+0xD23AD44D, 0x6EF64F26, 0x6CF66DF6, 0x6BF6422B,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x7FC44F22,
+0x720262F3, 0x22512F41, 0x45297202, 0x60632251,
+0xE5C4E682, 0x67F38121, 0x655C666C, 0xE408BFB6,
+0x4F267F3C, 0x0009000B, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE1007FC4, 0x6513ECFF,
+0x6B136CCD, 0xDE36D735, 0xEDFF64F3, 0xD835EA04,
+0x6053655C, 0x027D4000, 0x32C0622D, 0x66038D0D,
+0x09ED6063, 0x2491027D, 0x24217402, 0x698202ED,
+0x3928622D, 0x74022892, 0x75017104, 0x6063625C,
+0x07D532A2, 0x0EB58FE4, 0x2448641C, 0xE6808905,
+0x67F3E5C5, 0xBF79666C, 0x7F3C655C, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0xD11E68F6,
+0x6012D21E, 0xCB20E405, 0x2102E500, 0x000B2242,
+0x00002252, 0x001E1017, 0x00203B40, 0x002018A2,
+0x0020390E, 0x001E1015, 0x001E10BF, 0x00117800,
+0x001E10FC, 0x00200610, 0x00203914, 0x00202AEA,
+0x00203B44, 0x002018EE, 0x00203B60, 0x0011788C,
+0x00203910, 0x002034F4, 0x00201530, 0x001E2130,
+0x00203B68, 0x00202AAC, 0x00203B6C, 0x00203974,
+0x0020397C, 0x00203DA4, 0x001C3500, 0x001D4004,
+0xD564D163, 0xE400D764, 0x2142E20F, 0x17411154,
+0xD5622722, 0x9669D762, 0x15412572, 0x96661562,
+0xE6011565, 0xD55F1165, 0x666CE6F8, 0x25422542,
+0x25422542, 0x25422542, 0x25622542, 0x7601E727,
+0x67632572, 0x25627797, 0xE7042572, 0x2572E248,
+0xE2192522, 0xE2702522, 0x25422542, 0x25422542,
+0x25222542, 0x2522E20C, 0x25422542, 0x25422542,
+0x25422542, 0x25422542, 0x000B154A, 0xE2081145,
+0x0009422B, 0x2FE62FD6, 0x7FFC4F22, 0xC8206043,
+0x6E438D02, 0x0009BE67, 0xC81060E3, 0xBE648901,
+0x60E30009, 0x8901C840, 0x0009BE86, 0xC80160E3,
+0xDD3D8938, 0xC80260D0, 0x2F008D03, 0x460BD63B,
+0x60F00009, 0x8902C804, 0x460BD639, 0x62F00009,
+0xC8806023, 0x60D08902, 0x2D00C97F, 0xC8016023,
+0xD6348906, 0x0009460B, 0x0009A007, 0x51630601,
+0x8902C808, 0x460BD630, 0x60F00009, 0x8902C810,
+0x420BD22E, 0xD52E0009, 0x88026052, 0xD22D8B03,
+0xA005E604, 0x88012260, 0xD22A8B02, 0x2260E601,
+0x2522E200, 0xC88060E3, 0xD227892D, 0x60E36E20,
+0x8902C880, 0x420BD225, 0x60E30009, 0x8902C840,
+0x420BD223, 0x60E30009, 0x8902C802, 0x420BD221,
+0x60E30009, 0x890DC804, 0xDD20D11F, 0x0009410B,
+0x0009BF0D, 0x0009BF4C, 0xD51ED41D, 0x2470E708,
+0x25D2BF85, 0xC80860E3, 0xD21B8905, 0x4F267F04,
+0x422B6EF6, 0x7F046DF6, 0x6EF64F26, 0x6DF6000B,
+0x001C581C, 0xA000A000, 0x001D0100, 0x001D4000,
+0x00040021, 0x001C589C, 0x001E1021, 0x00201A90,
+0x00201AB2, 0x00202114, 0x00201ACA, 0x00201AD8,
+0x002039C8, 0x001E100B, 0x001E1028, 0x00201B44,
+0x00201B50, 0x00201AE0, 0x00201AFE, 0x12345678,
+0x001E1000, 0x0010F100, 0x00201B2C, 0x644CD6A7,
+0x000B346C, 0xD6A62450, 0x346C644C, 0x2450000B,
+0x644CD6A4, 0x000B346C, 0x625C2450, 0x4208616D,
+0x42084119, 0x42006019, 0x670E614C, 0xD49E321C,
+0x4200207D, 0x324CC90F, 0x2200000B, 0x4208625C,
+0x42004208, 0x324C644C, 0x4200D498, 0x000B324C,
+0x2FE62260, 0x614C4F12, 0x4100D493, 0x6710314C,
+0xE29F666D, 0x27294619, 0x6E536269, 0x672E6573,
+0x4221227D, 0x42214221, 0x7601662C, 0xE4014608,
+0x34E84608, 0x644C4600, 0x071A0467, 0x2150257B,
+0x000B4F16, 0x4F226EF6, 0xD2857FE8, 0x88016021,
+0xD2848B7B, 0x26686621, 0xD2838B77, 0x26686621,
+0xE50F8B73, 0xE401BFA2, 0xBFA4E501, 0xE586E400,
+0xE400655C, 0x2F50BFA4, 0xBFA1E401, 0xE602E506,
+0x60634618, 0x81F2E401, 0x6543BF9F, 0xE40185F2,
+0xBFAB6543, 0x85F26603, 0x6543E401, 0x6603BFB1,
+0xE40265F0, 0x6053756C, 0x80F8BF80, 0xBF82E402,
+0x84F8E512, 0x7090E402, 0x6503BF82, 0x4618E602,
+0x81F66063, 0xBF80E402, 0x85F6E500, 0x6603E402,
+0xE500BF8C, 0xE40285F6, 0xBF926603, 0xE5FEE500,
+0xE010655C, 0xBF61E403, 0xE5130F54, 0xE40EBF63,
+0x05FCE010, 0xBF63E40E, 0xE5007585, 0xBF64E403,
+0xE500E640, 0xBF71E403, 0xE500E640, 0xBF78E403,
+0xE5FFE640, 0xE014655C, 0xBF47E404, 0xE40F0F54,
+0xE504BF49, 0x05FCE014, 0xBF49E40F, 0xE5017584,
+0xBF4AE640, 0xE501E404, 0xBF57E640, 0xE501E404,
+0xE404E640, 0xAF5C7F18, 0x7F184F26, 0x000B4F26,
+0x4F220009, 0xD2427FF0, 0x88016021, 0xD2418B71,
+0x26686621, 0xD2408B6D, 0x26686621, 0xE50F8B69,
+0xE401BF1C, 0xBF1EE501, 0xE586E400, 0xE400655C,
+0x2F50BF1E, 0xBF1BE401, 0xE401E506, 0xBF1C6543,
+0xE401E640, 0xBF296543, 0xE401E640, 0xBF306543,
+0x65F0E640, 0x756CE402, 0xBEFF6053, 0xE40280F4,
+0xE512BF01, 0xE40284F4, 0xBF017090, 0xE6406503,
+0xBF02E402, 0xE640E500, 0xBF0FE402, 0xE640E500,
+0xBF16E402, 0xE5FEE500, 0x6053655C, 0xBEE5E403,
+0xE51380F8, 0xE40EBEE7, 0xE40E84F8, 0xBEE77085,
+0xE5006503, 0xBEE8E640, 0xE500E403, 0xBEF5E640,
+0xE500E403, 0xBEFCE640, 0xE5FFE403, 0x6053655C,
+0xBECBE404, 0xE40F80FC, 0xE504BECD, 0xE40F84FC,
+0xBECD7083, 0xE5016503, 0xBECEE640, 0xE501E404,
+0xBEDBE640, 0xE501E404, 0xE404E640, 0xAEE07F10,
+0x7F104F26, 0x000B4F26, 0x00000009, 0x001E102F,
+0x001E1080, 0x001E1090, 0x001E103F, 0x001E103E,
+0x002039C2, 0x002039C4, 0x002039C6, 0xD21DD11C,
+0x66206010, 0x676C7001, 0x3700C90F, 0xE5008D13,
+0x67106210, 0x7701622C, 0x64232170, 0xD6166010,
+0x44084408, 0x3428C90F, 0x62602100, 0x7201D513,
+0x44082620, 0x000B354C, 0xD10F6053, 0x25586510,
+0xE6008D13, 0xD60DD40B, 0x655C6540, 0x47086753,
+0x37584708, 0x47086540, 0x24507501, 0x367C6040,
+0x2400C90F, 0x72FF6210, 0x000B2120, 0x00006063,
+0x0020390D, 0x0020390C, 0x0020390E, 0x00203534,
+0x7FFC4F22, 0xE680D19F, 0x666C6212, 0xD29E2F22,
+0x67F36563, 0x420B7542, 0x7F04E404, 0x000B4F26,
+0xE6800009, 0xD298666C, 0xE7006563, 0x422B7540,
+0xE6806473, 0xD294666C, 0xE7006563, 0x422B7543,
+0x2F866473, 0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6,
+0x7FCC4F22, 0xDC8ED28D, 0x72011F21, 0xDB8D1F22,
+0xD18EDE8D, 0x66125211, 0x8B013620, 0x0009A0E5,
+0xC9036061, 0x8B018801, 0x0009A0DF, 0xD288D487,
+0xED84420B, 0x2F025503, 0x30D0845C, 0xA0B88901,
+0xD1840009, 0x626C6610, 0x88016023, 0xD1828B68,
+0x62101FC3, 0x895B2228, 0xE003D480, 0x40186742,
+0x68421772, 0xD57EE900, 0x81816DB3, 0x7D042190,
+0x67D26AB2, 0x64E26852, 0x1F491F57, 0x740464E3,
+0x1FA46542, 0x65431F5A, 0x625275F8, 0x1F761FD5,
+0x6D531F2B, 0xDA74D773, 0x7D94D274, 0x68D21F88,
+0x6AA26972, 0xD1726022, 0x2202CB20, 0xE1401F1C,
+0x7601E600, 0x3213626D, 0x56F48BFB, 0x52F651F5,
+0x21222B62, 0x52F851F7, 0x212256F9, 0x2E6251FA,
+0x51FB2412, 0x2D822512, 0xD9662792, 0x29A2DD5F,
+0x6AD2D965, 0xD9646892, 0x68D21A84, 0x6081DA63,
+0x2801CB01, 0xD86266D2, 0x2A622962, 0xED015AFC,
+0x2AD2480B, 0x2AD24D18, 0x62D2DD5E, 0x2D227201,
+0xD15056F3, 0xE2026062, 0x2602CB01, 0x2120A03D,
+0x8B3A2228, 0xE401DD58, 0x2140E600, 0xE01C2D62,
+0xC801005C, 0xD4558B0A, 0xE600D755, 0xED7D2472,
+0x626C7601, 0x8BFB32D3, 0x24D2DD52, 0xE2FE68C2,
+0x2C822829, 0x095CE01E, 0xE01F5DF1, 0x0A5C2D90,
+0x751051F2, 0xED0621A0, 0xD74BE600, 0x8456D44B,
+0x27007601, 0x696C6854, 0x248039D3, 0x8FF67401,
+0xDA477701, 0x2A10E194, 0xE2007A01, 0x7A0F2A20,
+0xD130E805, 0x66102A80, 0x6023626C, 0x89088801,
+0xD240D42A, 0x420B65F2, 0xD131ED01, 0xAF304D18,
+0x65F221D2, 0x8553D43C, 0x620D6642, 0x89073262,
+0xD13BD43A, 0x0009410B, 0xE601D73A, 0x2762AF1A,
+0xD134D41E, 0x410B65F2, 0xD125ED01, 0xD637D436,
+0x460B4D18, 0xAF0D21D2, 0x7F340009, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0x4F2268F6,
+0x85467FF4, 0x2F01E681, 0x666C8547, 0x854881F1,
+0x81F2D209, 0x67F38542, 0x854381F3, 0x81F4E40C,
+0x65636053, 0x420B81F5, 0x7F0C7540, 0x000B4F26,
+0x00000009, 0x001C3D9C, 0x0020245C, 0x0011779A,
+0x001C36F8, 0x001C3B9C, 0x001C3704, 0x0020352C,
+0x002014A0, 0x0020391D, 0x0020391C, 0x00203918,
+0x001C3D98, 0x001C3BB4, 0x001C5960, 0x001C3500,
+0x001C3D30, 0x001C8960, 0x00203504, 0x001C3D00,
+0x0020160C, 0x00117730, 0x00203920, 0x001C582C,
+0x2000A000, 0x0000A000, 0x0011778C, 0x00117792,
+0x00117788, 0x002014CC, 0x002038F4, 0x002034F4,
+0x00201530, 0x001E2130, 0x00203D84, 0x002018A2,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xD19B7FEC, 0x2F12E000, 0x6103D49A, 0x1F4281F2,
+0xDD9ADA99, 0xD69A6813, 0xE0014808, 0x460BDE99,
+0x38EC4800, 0x65A21F03, 0x352052A1, 0xA23E8B01,
+0x60510009, 0x8801C903, 0xA2388B01, 0x52530009,
+0x32E0DE91, 0xD9918B10, 0x64A3490B, 0x4B0BDB90,
+0xDE906403, 0xD791D690, 0xEC01D591, 0x2E02E100,
+0x271026C0, 0x2502AFDF, 0xC8018551, 0xA1578B01,
+0x62510009, 0x4200622D, 0x5E53366A, 0x85E2226D,
+0xC903642C, 0x85E36603, 0x6053650D, 0x40214021,
+0x4500C93F, 0x322A6703, 0x6053252D, 0xC901D17F,
+0x60106C03, 0x8801D97F, 0xDB7F8B05, 0x2120E200,
+0xCB0160B2, 0xD17D2B02, 0x88016011, 0x65A28B0A,
+0x8D042448, 0x9B9E6251, 0xA00322B9, 0x919B2521,
+0x2521221B, 0x37B3EB10, 0x2448895E, 0xD4738B07,
+0x22286241, 0x60638903, 0xA05781F8, 0xD5706473,
+0x46084608, 0x85E26273, 0x46006B50, 0x362C4200,
+0x2BB8C910, 0x8F1F6463, 0x26686603, 0xD2698911,
+0x062D6043, 0x4119616D, 0x6B0E6019, 0x81F820BD,
+0x880160C3, 0x646C8F2C, 0x880F6073, 0xA0278B1B,
+0xD2610009, 0x052D6043, 0x4119615D, 0x670E6019,
+0x645C207D, 0x81F8A01C, 0x890F2668, 0x6043D25B,
+0x6B5D052D, 0x60B94B19, 0x201D610E, 0x60C381F8,
+0x8F0D8801, 0x6473645C, 0xEC00A00A, 0x6043D254,
+0x625D052D, 0x60294219, 0x207D670E, 0x81F8645C,
+0x880285F8, 0x85E1890A, 0x8D07C820, 0xE6DC6203,
+0x60232269, 0x81E1A002, 0x644CE4FF, 0x6210D149,
+0x89012228, 0x644CE4FF, 0x654DEBFF, 0x35B06BBC,
+0xDB368B2B, 0x64A34B0B, 0x410BD135, 0x54036403,
+0x85446E03, 0xC948DB40, 0xDC408808, 0xBEAE8B01,
+0x64B3E502, 0x65E34C0B, 0xDB3DEC01, 0xD13D2DC2,
+0x621260B2, 0x72017001, 0x21228805, 0x2B028F08,
+0x666CE680, 0x6563D238, 0x7549E700, 0x6473420B,
+0xA030D436, 0x7FFF0009, 0x85E28000, 0x20B9EBFC,
+0x610381E2, 0x942A85E3, 0x62032049, 0x450885F8,
+0x81E2201B, 0xC90160C3, 0x40084018, 0x40084008,
+0x4000225B, 0x6023220B, 0x85E481E3, 0x4118E108,
+0x81E4201B, 0xE40262A2, 0x20B98521, 0x67A28121,
+0xCB016071, 0x85F82701, 0x89033042, 0xECE785E2,
+0x81E220C9, 0x490BD41E, 0xA03B0009, 0x7E030009,
+0x001C3D30, 0x00203D90, 0x00203504, 0x001E212C,
+0x002033E8, 0x001C3D00, 0x00117780, 0x002014A0,
+0x0020166C, 0x0011770C, 0x0020391C, 0x0020391D,
+0x00203918, 0x002018A2, 0x001C36F8, 0x00203990,
+0x00203DA0, 0x00203B84, 0x00203C04, 0x00203C84,
+0x00203D04, 0x00203908, 0x002034FC, 0x002014CC,
+0x00203994, 0x00203998, 0x0020245C, 0x00203D88,
+0x00203D8C, 0x602262F2, 0x40094019, 0xC90F4009,
+0x8B0B880A, 0x60E2DE8C, 0x40094019, 0xC90F4009,
+0x8B038808, 0xCB0160A2, 0x2802A006, 0x65E2DE87,
+0x2E527501, 0x286266A2, 0x52F366F2, 0x2622AE83,
+0xD2838551, 0xDE83C802, 0xA0958B01, 0x420B0009,
+0x4E0B64A3, 0x5E036403, 0x85E46503, 0x4918E908,
+0xD77D209B, 0xE04C81E4, 0xDC7C0B7E, 0x7B01D97C,
+0x61C207B6, 0x71016690, 0x8D062668, 0xD4792C12,
+0x420BD279, 0xA070EB01, 0x62512DB2, 0x4B18EB0F,
+0x22B9E102, 0x32104118, 0x85518B0F, 0x2029E2FC,
+0x60518151, 0xCB0172E0, 0x85E12501, 0x202994A3,
+0x85E481E1, 0xA0522049, 0x675181E4, 0x4719677D,
+0x667E6779, 0x7701276D, 0x6903607C, 0x88014918,
+0x25918F3E, 0x6B12D161, 0x21B27B01, 0x660D85E3,
+0x40216063, 0xC93F4021, 0x6C034600, 0x262D322A,
+0xC8016063, 0xDB5ED15D, 0x967D8901, 0xE6002C6B,
+0x666C67CD, 0x40006063, 0x622D021D, 0x8D0E3270,
+0x60436403, 0xE9FF021D, 0x8B013290, 0x01C5A007,
+0x626C7601, 0x3292E904, 0x646C8BEB, 0x60434400,
+0xD15004BD, 0x0B457401, 0x669D6911, 0x89073670,
+0x602D6211, 0x890388FF, 0xE201DB4B, 0x2B2021C1,
+0xECFC8551, 0x815120C9, 0xCB016051, 0xDC472501,
+0x64A34C0B, 0x51F366F2, 0x85EF2612, 0x54F2D244,
+0x650D420B, 0x0009ADE7, 0xE500DC42, 0x420B2C52,
+0x4E0B64A3, 0x54036403, 0x85446E03, 0x6703E908,
+0x65034918, 0x27998541, 0xDB323790, 0x8F0BD932,
+0x6013610D, 0x8B07C820, 0xC9486053, 0x8B038808,
+0xE501BD4D, 0x0009A005, 0x2128D233, 0xBD468901,
+0x64B3E500, 0x490B65E3, 0xADBCEC01, 0x85F22DC2,
+0x7001EE04, 0x31E7610D, 0x8D0281F2, 0xADA97A08,
+0x7F140009, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0xF7FF68F6, 0x2FE68000, 0xD2234F22,
+0x60E36E22, 0x8D02C840, 0xBBF922E2, 0xE2400009,
+0x2E284218, 0xBC048901, 0x60E30009, 0x8905C810,
+0xD21CD41B, 0x0009420B, 0x0009BC03, 0xC80560E3,
+0xBD6D8901, 0x60E30009, 0x8902C802, 0xAC004F26,
+0x4F266EF6, 0x6EF6000B, 0x001C3D3C, 0x00117760,
+0x002014A0, 0x0020166C, 0x00203494, 0x00203DA4,
+0x00203908, 0x002034FC, 0x002014CC, 0x00203974,
+0x0020397C, 0x00203970, 0x00203972, 0x00201530,
+0x002018EE, 0x00203994, 0x00008000, 0x001C3510,
+0x00203D98, 0x002018A2, 0x080A0C0E, 0x00020406,
+0x1A1C1E20, 0x12141618, 0x2E303234, 0x26282A2C,
+0x3A3C3E40, 0x6C625648, 0x41112F26, 0xE2208F18,
+0x890B3123, 0x321CD204, 0xD1026220, 0x412B312C,
+0x00090009, 0x00203412, 0x002033C8, 0x000BE000,
+0x400062F6, 0x40004000, 0x40004000, 0x40004000,
+0x62F6000B, 0x40004000, 0x40004000, 0x40004000,
+0x40184000, 0x62F6000B, 0x40004000, 0x40004000,
+0x40004000, 0x40284000, 0x62F6000B, 0x40004000,
+0x40184000, 0x000B4028, 0xC90F62F6, 0x40054005,
+0x40054005, 0x62F6000B, 0x4005C907, 0x40054005,
+0x62F6000B, 0x4005C903, 0x000B4005, 0xC90162F6,
+0x000B4005, 0x000062F6, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x544F0D0A, 0x46205355, 0x00003A57,
+0x206C754A, 0x32203120, 0x20383030, 0x323A3132,
+0x34333A38, 0x00000000, 0x00000D0A, 0x00000043,
+0x42707372, 0x3D206675, 0x554E203D, 0x202C4C4C,
+0x6E49677A, 0x4E497274, 0x6D754E51, 0x0000003D,
+0x61766E49, 0x2064696C, 0x72657375, 0x20726F20,
+0x2079656B, 0x00214449, 0x52504545, 0x57204D4F,
+0x65746972, 0x6461202C, 0x003D7264, 0x6C617620,
+0x0000003D, 0x00000A0D, 0x435F4D5A, 0x465F444D,
+0x4C445F57, 0x494E495F, 0x00000054, 0x6E6B6E55,
+0x206E776F, 0x6D6D6F63, 0x3D646E61, 0x00000000,
+0x203A3051, 0x00000020, 0x203A3151, 0x00000020,
+0x203A3251, 0x00000020, 0x203A3351, 0x00000020,
+0x203A3451, 0x00000020, 0x2B434741, 0x73696F4E,
+0x61432065, 0x7262696C, 0x6F697461, 0x6166206E,
+0x6F206C69, 0x6974206E, 0x0D0A656D, 0x00000000,
+0x00000072, 0x00205220, 0x00000D0A, 0x62735576,
+0x7473725F, 0x00000A0D, 0x62735576, 0x7375735F,
+0x646E6570, 0x00000A0D, 0x62735576, 0x7365725F,
+0x000A0D6D, 0x00000044, 0x44387570, 0x72637365,
+0x6F747069, 0x3D584572, 0x00000000, 0x00000047,
+0x00000042, 0x72746E49, 0x6D652051, 0x2C797470,
+0x49677A20, 0x4972746E, 0x754E514E, 0x00003D6D,
+0x654C7245, 0x0000006E, 0x00000049, 0x20746F4E,
+0x756F6E65, 0x49206867, 0x4220514E, 0x0A0D6675,
+0x00000000, 0x000000FF, 0x00020001, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00020003, 0x01090108,
+0x0002010A, 0x02000003, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x000000FF, 0x00020001, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00020003, 0x01090108,
+0x0002010A, 0x00030003, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00FF010F, 0x01090108,
+0x010B010A, 0x0200010F, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00FF010F, 0x01090108,
+0x010B010A, 0x010F010F, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00205220, 0x00000046, 0x00000059,
+0x73204142, 0x003D7165, 0x49544120, 0x0000204D,
+0x00000000, 0x00000000, 0x002E0209, 0x80000101,
+0x000409FA, 0x00FF0400, 0x05070000, 0x02000201,
+0x82050700, 0x00020002, 0x03830507, 0x07010040,
+0x40030405, 0x02090100, 0x0101002E, 0x09FA8000,
+0x04000004, 0x000000FF, 0x02010507, 0x07000040,
+0x40028205, 0x05070000, 0x00400383, 0x04050701,
+0x00004002, 0x00000000, 0x00000000, 0x07090000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+const u32_t zcFwImageSize=15936;
diff --git a/drivers/staging/otus/hal/hpfwu.c.drv_ba_resend b/drivers/staging/otus/hal/hpfwu.c.drv_ba_resend
new file mode 100644
index 000000000000..7f5bcff57b59
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwu.c.drv_ba_resend
@@ -0,0 +1,742 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE297FFC, 0xE114D729,
+0x1E13D429, 0x1E4C470B, 0x0009B018, 0xA0039545,
+0x3652E600, 0x76018D04, 0xC84060E2, 0x2F028DF9,
+0xDE23D422, 0x00094E0B, 0x4E0BD422, 0xD4220009,
+0x00094E0B, 0x4F267F04, 0x6EF6A024, 0xD11F4F22,
+0x0009410B, 0x440BD41E, 0xD51E0009, 0x0009450B,
+0xE1FFD71D, 0xD21D611D, 0x50292712, 0xCB01D41C,
+0xE501E1FF, 0x22121209, 0x24521211, 0xD61AD519,
+0xE2009714, 0xD4192572, 0xD6192620, 0x4F262422,
+0x2622000B, 0xDD18DC17, 0x4C0BDE18, 0x4D0B0009,
+0x4E0B0009, 0xAFF80009, 0x27100009, 0x00000640,
+0x001C001C, 0x00200BC4, 0x0000B38E, 0x002029F8,
+0x00200F72, 0x00202A04, 0x00202A1C, 0x00200F20,
+0x00201056, 0x00200C1C, 0x001C3510, 0x001C3624,
+0x001E212C, 0x00202994, 0x00202530, 0x0020299C,
+0x002029A8, 0x00200E50, 0x002023E6, 0x00201920,
+0x2FC62F96, 0x2FE62FD6, 0x7F904F22, 0xE020DE8D,
+0xD48D61E0, 0x61E30F14, 0x62107101, 0xE024D78B,
+0x0F24470B, 0x450BD58A, 0x20080009, 0x8F116D03,
+0xDD881F0A, 0x67D0D488, 0x410BD188, 0xD288657C,
+0x6920DD88, 0x66C36C9C, 0x46084608, 0x460836C8,
+0x1FDA3D6C, 0x04FCE024, 0x66E2E580, 0x655C604C,
+0x8F163050, 0xE0202D62, 0xE50001FC, 0xDE7E641C,
+0x3243625D, 0xA32C8B01, 0x655D0009, 0x36EC6653,
+0xE02C6760, 0x69530F74, 0x39DC607E, 0xAFEF8094,
+0x20087501, 0xE0208B14, 0xE50001FC, 0xA00ADE72,
+0x655D641C, 0x39EC6953, 0x67536C92, 0x37DC62C2,
+0x75041721, 0x625D1F2C, 0x8BF23243, 0x2D10A309,
+0x8B178801, 0x01FCE020, 0x2D70E700, 0x1FD76D1C,
+0x627DDE65, 0x8B0132D3, 0x0009A2FB, 0x65E3677D,
+0x75046673, 0x36EC6C73, 0x64623C5C, 0x770869C2,
+0x2492AFEF, 0x8B188804, 0x01FCE020, 0x2D40E400,
+0xDE59671C, 0x3273624D, 0xA2E28B01, 0x644D0009,
+0x6CE36D43, 0x65D23DEC, 0x61437C04, 0x621231CC,
+0x74086952, 0xAFED2929, 0x88052592, 0xE0208B18,
+0xE40001FC, 0x671C2D40, 0x624DDE4B, 0x8B013273,
+0x0009A2C7, 0x6943644D, 0x39EC61E3, 0x71046592,
+0x3C1C6C43, 0x6D5262C2, 0x2D2B7408, 0x25D2AFED,
+0x8B1B8831, 0xD942D241, 0x72046422, 0x72046622,
+0x72046722, 0x72E86C22, 0x1F2E1F4D, 0x72046422,
+0x72046E22, 0x652229E0, 0x2950D93A, 0xDE3A2FC6,
+0x55FE4E0B, 0xE2007F04, 0x2D20A29B, 0x8B1D8830,
+0xDE33D232, 0x72046522, 0x72046122, 0x72046722,
+0x72E86922, 0x72046422, 0x72046C22, 0x6E222EC0,
+0x1F9FD62C, 0x7FFC26E0, 0x09FEE040, 0x2F92DC2B,
+0x66134C0B, 0xE2007F04, 0x2D20A27B, 0x89018828,
+0x0009A109, 0xE143DE20, 0xE04062E1, 0x3617662D,
+0x0FE68F03, 0x660302FE, 0x36172201, 0xA0F38B01,
+0xE0400009, 0xE50104FE, 0x30568541, 0xA0EB8B01,
+0xE0400009, 0x09FEE701, 0xB2612D70, 0xE0406491,
+0xE1430CFE, 0xE06862C1, 0x3517652D, 0x0F568D68,
+0x3563E640, 0xE6008B24, 0x0F65E048, 0xA02EE11A,
+0x000072C0, 0x00117800, 0x00202A20, 0x00200F72,
+0x00201FDC, 0x002029B0, 0x00202A24, 0x00200FBC,
+0x002029AF, 0x002025D4, 0x00117804, 0x00117810,
+0x002029AC, 0x002029AD, 0x00200948, 0x00200994,
+0x41216153, 0x41214121, 0x41214121, 0x45214521,
+0x60534521, 0x6603C903, 0x0F65E048, 0xE0077118,
+0xE0442209, 0x641D0F25, 0x65F3E04C, 0x0F46B291,
+0x0EFDE048, 0x0DFDE044, 0x61DD67ED, 0x41084708,
+0x0F16E050, 0xDD946073, 0x4D0B06FE, 0x6E07E00F,
+0x607326E9, 0xE0400F66, 0x65F30CFE, 0x690D85C2,
+0x01FEE050, 0x60934D0B, 0x6073260B, 0xE04C0F66,
+0x04FEB256, 0x07FEE040, 0x6271E068, 0x0F56652D,
+0x3563E640, 0xED008954, 0x0FD5E064, 0xC9036023,
+0x40004008, 0x61036903, 0x0F96E054, 0xDE7EE058,
+0x0FF6ECFF, 0xE06C6CCC, 0x60C30FE6, 0x62534E0B,
+0x42214221, 0x42214221, 0x42006723, 0x6107327C,
+0x4200E05C, 0x0F164521, 0x4521E040, 0x60530CFE,
+0x4008C903, 0x7C0630FC, 0x6E031FC6, 0x1FD56D2D,
+0x1F04A01E, 0x0FD6E060, 0x05FEE058, 0x64D3B231,
+0x62E2E05C, 0xE05409FE, 0x2E222299, 0x64D361C4,
+0x01FE661C, 0x07FEE06C, 0x6063470B, 0xE058220B,
+0xB20505FE, 0xE0642E22, 0x7D0102FD, 0x0F257201,
+0x02FDE064, 0x3262E606, 0xE0408BDC, 0x626106FE,
+0x05FEE040, 0x85514200, 0x302C750C, 0x6103701B,
+0x64F3E600, 0xE704A004, 0x76016256, 0x74042422,
+0x3273626D, 0x65F38BF8, 0x641DB1E2, 0x06FEE040,
+0x6461B19E, 0x0009A175, 0xD74DD44C, 0x470BE201,
+0xA16E2D20, 0x88290009, 0xDE4A8B07, 0x2D20E200,
+0xB16D66E2, 0xA164646D, 0xE2810009, 0x3020622C,
+0xA0A78B01, 0xE0240009, 0x626C06FC, 0x666CE682,
+0x8B213260, 0xE42452FA, 0xD43F2240, 0x12615647,
+0x12625648, 0x12635649, 0x1264564A, 0x1265564B,
+0x1266564C, 0x1267564D, 0x1268564E, 0x1269564F,
+0x1427E200, 0x14291428, 0x142B142A, 0x142D142C,
+0x142F142E, 0x1F6CA135, 0x666CE683, 0x8B073260,
+0xE60052FA, 0xD22B2260, 0x6222D62C, 0x2622A129,
+0x666CE690, 0x8B183260, 0xE60052FA, 0xD2282260,
+0x6022E605, 0x2202CB20, 0x2262D226, 0x2262E600,
+0x460BD625, 0xD2250009, 0x0009420B, 0xE601D224,
+0xD2242262, 0xA10C4618, 0xE6B02262, 0x3260666C,
+0xD5188B22, 0xD216D420, 0x75046D52, 0x6E52420B,
+0x420BD21E, 0xD41E64D3, 0x450BD511, 0xD21B0009,
+0x64E3420B, 0xD60ED41B, 0x0009460B, 0xE600E504,
+0x3253626D, 0xA0EC8B01, 0x666D0009, 0x326C62D3,
+0x22E07601, 0x4E19AFF4, 0xD214D413, 0xD4146542,
+0x0009420B, 0x0009A0DD, 0x0020248C, 0x00202A44,
+0x00200F72, 0x00117804, 0x00202538, 0x00202994,
+0x001C3500, 0x001D4004, 0x00201056, 0x00200C1C,
+0x001E212C, 0x001C3D30, 0x00202A5C, 0x00200FB4,
+0x00202A70, 0x00202A78, 0x00117800, 0x00200FBC,
+0x00202A7C, 0xD6AED4AD, 0x6262E040, 0x76046542,
+0x2452352C, 0x62626563, 0x75045641, 0x1461362C,
+0x62526653, 0x76085542, 0x1452352C, 0x55436262,
+0x352C76EC, 0x65631453, 0x56446262, 0x362C7510,
+0x66531464, 0x55456252, 0x352C7610, 0x65621455,
+0xD69C5246, 0x1426325C, 0x55476262, 0x352C7604,
+0x62621457, 0x76045548, 0x1458352C, 0x62626563,
+0x75045649, 0x1469362C, 0x564A6252, 0x362C7504,
+0x6653146A, 0x554B6252, 0x352C7604, 0x6262145B,
+0x7604554C, 0x145C352C, 0x62626563, 0x7504564D,
+0x146D362C, 0x62526653, 0x7604554E, 0x145E352C,
+0x524F6562, 0x325CD684, 0x6262142F, 0x7694054E,
+0x0456352C, 0x6263E044, 0x054E6662, 0x356C7244,
+0xE0480456, 0x054E6622, 0xD67C356C, 0x62620456,
+0x054EE054, 0x352C4229, 0x76040456, 0xE0586262,
+0x4229064E, 0x52FA362C, 0xE6380466, 0xE0442260,
+0xE048064E, 0x66421261, 0x56411262, 0x56421263,
+0x56451264, 0x56431265, 0x56461266, 0x064E1267,
+0x1268E040, 0xE050064E, 0x56441269, 0x064E126A,
+0x126BE04C, 0xE054064E, 0x064E126C, 0x126DE058,
+0xE044064E, 0xE200126E, 0xE0480426, 0x14212422,
+0x14251422, 0x14261423, 0xE0400426, 0xE0500426,
+0x04261424, 0x0426E04C, 0x0426E054, 0x0426E058,
+0x7F701F6C, 0x6EF64F26, 0x6CF66DF6, 0x69F6000B,
+0x614D4F22, 0x3123E240, 0xE21F8917, 0x89083127,
+0xD550D44F, 0x450BE001, 0x67076642, 0xA00C2679,
+0xE23F2462, 0x89083127, 0xD64AD749, 0xE00171E0,
+0x5571460B, 0x25296207, 0x4F261751, 0x0009000B,
+0x614D4F22, 0x3123E240, 0xE21F8915, 0x89073127,
+0xD240D43F, 0x420B6642, 0x260BE001, 0x2462A00B,
+0x3127E23F, 0xD73A8907, 0x5571D63A, 0x460B71E0,
+0x250BE001, 0x4F261751, 0x0009000B, 0x4618E640,
+0xD5354628, 0x22686252, 0x000B89FC, 0xE6800009,
+0x46284618, 0x6252D530, 0x89FC2268, 0x0009000B,
+0xE200A001, 0x32427201, 0x000B8BFC, 0xE6800009,
+0x46284618, 0x6252D529, 0x8BFC2268, 0x0009000B,
+0x4F222FE6, 0x6E537FFC, 0x2F42BFF1, 0xD62461E2,
+0x1615E280, 0x421854E1, 0x55E21646, 0x16574228,
+0x6EF257E3, 0x2E2B1678, 0x7F0426E2, 0xAFCE4F26,
+0x2FC66EF6, 0x2FE62FD6, 0xDD194F22, 0xBFD66C53,
+0xBFBB6E43, 0xBFD22DE2, 0x51D50009, 0x54D62C12,
+0x55D71C41, 0x56D81C52, 0x4F261C63, 0x6DF66EF6,
+0x6CF6000B, 0xE6006163, 0x4109A004, 0x76016256,
+0x74042422, 0x8BF93612, 0x0009000B, 0x00202538,
+0x001C36A0, 0x001C3CA0, 0x001C36F4, 0x001C3B88,
+0x001C3704, 0x0020248C, 0x001C373C, 0x001C3700,
+0x001C370C, 0x0009A109, 0x2FD62FC6, 0x4F222FE6,
+0x6E636D73, 0x6C53B016, 0x64C357F4, 0xB02965E3,
+0xB03D66D3, 0xB06D0009, 0xB0710009, 0xB0750009,
+0xB08A0009, 0xB08D0009, 0x4F260009, 0x6DF66EF6,
+0x6CF6A0B4, 0x3412D190, 0xD6900529, 0x2650D790,
+0x2742000B, 0x2FD62FC6, 0x4F222FE6, 0x6E636D73,
+0x6C53BFF0, 0x64C357F4, 0x66D365E3, 0x6EF64F26,
+0x6CF66DF6, 0xD1872FE6, 0x66126E63, 0x92BC4418,
+0x44084528, 0x45002629, 0x265B4408, 0x264B4400,
+0x21624708, 0xD1804708, 0x217227EB, 0x6EF6000B,
+0x4F222FE6, 0xE101DE7D, 0xBFABE40A, 0x62E32E12,
+0xE100726C, 0x2212E401, 0x22122212, 0x22122212,
+0x22422212, 0xE503E730, 0x2212E40A, 0x22122212,
+0x22122212, 0x22122212, 0x22122212, 0x22122212,
+0x22722212, 0x22122252, 0x22122212, 0x22122212,
+0x22122212, 0xBF852212, 0xE600121A, 0x4F262E62,
+0x6EF6000B, 0xE101D266, 0x2212E441, 0x2242000B,
+0xD465D164, 0x2162E605, 0x2462000B, 0xD264D563,
+0x88016050, 0xD4638B07, 0x60409668, 0x8B098801,
+0xA0079665, 0xE6000009, 0x2262D45E, 0x88016040,
+0xE6048B00, 0xAF5DE40A, 0xD25B2262, 0xE40AE601,
+0x2262AF58, 0x2FC62FB6, 0x2FE62FD6, 0xDC574F22,
+0x60C2ED00, 0xCB01EB64, 0x60C22C02, 0xA008C901,
+0x3DB26E03, 0x60C28907, 0xC901E40A, 0x6E03BF42,
+0x2EE87D01, 0x3DB28BF5, 0xD44D8B03, 0x420BD24D,
+0xE40A0009, 0x6EF64F26, 0x6CF66DF6, 0x6BF6AF32,
+0x8F014411, 0x6043604B, 0x0009000B, 0x2FC62FB6,
+0x2FE62FD6, 0x7FFC4F22, 0xED00DC40, 0xEB6460C2,
+0x2C02CB02, 0x2F0260C2, 0xA009C902, 0x3DB36E03,
+0x60C28908, 0x2F02E40A, 0xBF13C902, 0x7D016E03,
+0x8BF42EE8, 0x8B0B3DB3, 0xD236D437, 0x4F267F04,
+0x6DF66EF6, 0x422B6CF6, 0x1FFF6BF6, 0x03C40340,
+0x4F267F04, 0x6DF66EF6, 0x000B6CF6, 0xD52F6BF6,
+0x60525651, 0x000B4628, 0x2FB6306C, 0x2FD62FC6,
+0x4F222FE6, 0x4F024F12, 0x6E43BFF1, 0xDC286B03,
+0xBFECDD28, 0x30B80009, 0x060A3C05, 0x46094609,
+0x3D654601, 0x4209020A, 0x42094209, 0x8BF032E2,
+0x4F164F06, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x4F222FE6, 0xE102DE1C, 0xE403E500, 0xBFD42E12,
+0xE6062E52, 0xE7004618, 0x2E62E403, 0x4F262E72,
+0x6EF6AFCB, 0x0009000B, 0x0025E720, 0x00202C3C,
+0x00202998, 0x001C5814, 0x001C59D0, 0x001C5830,
+0x001C6268, 0x001C59A4, 0x001C639C, 0x002029AD,
+0x001C5804, 0x002029AC, 0x001C581C, 0x001C5860,
+0x00202A90, 0x00200F72, 0x00202AA8, 0x001C1040,
+0xCCCCCCCD, 0x10624DD3, 0x001D4004, 0x2F962F86,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0xE4007FE0,
+0x4528E510, 0x67436C43, 0xE108A00F, 0x6043644D,
+0x0F564008, 0xEE0060C3, 0x815125C1, 0x81538152,
+0x157315E2, 0x751415E4, 0x624D7401, 0x8BED3213,
+0xDA7251F1, 0x1A1154F2, 0xD1712A12, 0x56F455F3,
+0x58F657F5, 0x21421141, 0x11521153, 0x11641165,
+0x11761177, 0x11881189, 0xD96A6DF2, 0xDB6A52F7,
+0x29D219D1, 0x2B221B21, 0xD868EB45, 0xE9B8EA50,
+0x4A084B08, 0xA020699C, 0x6EEDEE00, 0x61E36DE3,
+0x41084D08, 0x31EC3DEC, 0x41084D08, 0x60C33D8C,
+0xD75F4108, 0x81D12DC1, 0x410860A3, 0x60C381D2,
+0xE200317C, 0x81D33492, 0x1D131DD2, 0x8D01D456,
+0xD4521D24, 0x65D3B03C, 0x64ED7E01, 0x8BDC34B2,
+0xDB54D14E, 0xD24F6512, 0x1B514529, 0xD14C6412,
+0x2B72674D, 0xD6506722, 0x1B734729, 0x2FD26922,
+0x1B82689D, 0x26926912, 0x16A25A12, 0xDA465B14,
+0x5C1616B4, 0x5D1816C6, 0x6EA216D8, 0x7F2016EA,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0x664268F6, 0xC8036061, 0xE5008D04, 0xC9036061,
+0x8B038802, 0x65635262, 0x24125124, 0x6053000B,
+0x2FE62FD6, 0x7FEC4F22, 0x62536E53, 0x6D43E550,
+0x4508E400, 0xE101A001, 0x60435224, 0x81212211,
+0x60538123, 0x56E28122, 0x8BF53620, 0x16E4D22F,
+0xE61464F3, 0x65E3420B, 0xE4FC65E1, 0x2E512549,
+0x65F361F1, 0x2F112149, 0xD12854D1, 0xE614410B,
+0x607157D1, 0x2701CB01, 0x7F141DE1, 0x6EF64F26,
+0x6DF6000B, 0x2FE62FD6, 0x7FEC4F22, 0x66536E53,
+0x6D43E5FC, 0x20596061, 0x2601CB01, 0x326052E2,
+0x12E48B06, 0x31E051E2, 0x52D18B04, 0x1E22A002,
+0x5664AFF0, 0x64F3D215, 0x420BE614, 0x67E165E3,
+0x2719E1FC, 0x67F12E71, 0x271954D1, 0x65F3D10F,
+0x410BE614, 0x52D12F71, 0xCB016021, 0x1DE12201,
+0x4F267F14, 0x000B6EF6, 0x00006DF6, 0x0020259C,
+0x002025A4, 0x00202594, 0x002025CC, 0x001000A0,
+0x00101640, 0x001E2108, 0x001C3D00, 0x00200904,
+0x2FC62FB6, 0x2FE62FD6, 0x7FFC4F22, 0x6022D225,
+0x8D35C803, 0xDE242F01, 0xDB25DC24, 0xED01A016,
+0xC9036061, 0x89158801, 0xD122D420, 0x0009410B,
+0x65035603, 0xC8208561, 0xE0508903, 0x720102BE,
+0xD21D0B26, 0x64E3420B, 0x21D2D11C, 0x66C252C1,
+0x8BE53620, 0xDD1AEE01, 0x4E18A00E, 0xC9036061,
+0x890D8801, 0xD713D416, 0x470BDB16, 0xD4160009,
+0x65034B0B, 0x21E2D111, 0x66D252D1, 0x8BED3620,
+0xC80460F1, 0xD2118907, 0x4F267F04, 0x6DF66EF6,
+0x422B6CF6, 0x7F046BF6, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6000B, 0x001E2100, 0x002025A4, 0x0020259C,
+0x00202538, 0x00200D42, 0x00200DC4, 0x001C3D30,
+0x00202594, 0x00200D60, 0x002025CC, 0x00200100,
+0xE601D203, 0x1265D503, 0x000B2252, 0x00001266,
+0x001C1010, 0x0000C34F, 0xD62A7FFC, 0x2642644C,
+0xC8205066, 0x2F028DFC, 0x7F04000B, 0x2FD62FC6,
+0x4F222FE6, 0x6D436C53, 0xEE00A004, 0x7E0164D4,
+0x644CBFEA, 0x8BF93EC2, 0x6EF64F26, 0x000B6DF6,
+0xA0016CF6, 0x76016643, 0x22286260, 0x36488BFB,
+0x6563AFE4, 0x62532FE6, 0x67537507, 0xEE0AE108,
+0xC90F6043, 0x30E24409, 0x44096503, 0xE6378D01,
+0x365CE630, 0x27604110, 0x77FF8FF2, 0x8028E000,
+0x6EF6000B, 0xE000000B, 0xE000000B, 0x4F222FE6,
+0x62537FEC, 0x65F36E43, 0x6423BFDC, 0x64E3BFD1,
+0x64F3BFCF, 0xBFCCD404, 0x7F140009, 0x000B4F26,
+0x00006EF6, 0x001C0004, 0x00202AC4, 0xE110D5A1,
+0xE6406050, 0x2500C9FD, 0xE0FF75E9, 0x80516453,
+0x80538052, 0x80568055, 0x251075EF, 0xE1EF6250,
+0x2219E001, 0xE7202520, 0x24608052, 0x2570000B,
+0xE4FDD595, 0xE7026152, 0x25122149, 0x74016052,
+0x2502CB01, 0xD1916652, 0x25622649, 0x92C46012,
+0x2102CB08, 0xC9CF6012, 0x60122102, 0x2102CB03,
+0x000B1172, 0x4F221123, 0xD78AD589, 0xD48BD28A,
+0xE600E100, 0x27112511, 0xBFBF2210, 0xAFD72461,
+0x664C4F26, 0x4600D286, 0x6060362C, 0x000BCB10,
+0x654C2600, 0x4500D282, 0x6650352C, 0x2619E1EF,
+0x2560000B, 0xD27F664C, 0x362C4600, 0xCB106060,
+0x2600000B, 0xD27B654C, 0x352C4500, 0xE1EF6650,
+0x000B2619, 0x664C2560, 0x4600D275, 0x6060362C,
+0x000BCB08, 0x654C2600, 0x4500D271, 0x6650352C,
+0x2619E1F7, 0x2560000B, 0xD26E664C, 0x362C4600,
+0xCB086060, 0x2600000B, 0xD26A654C, 0x352C4500,
+0xE1F76650, 0x000B2619, 0x624C2560, 0x4200D664,
+0x6020326C, 0x4021C908, 0x40214021, 0x600C000B,
+0xD660624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0x644C600C, 0x74FFD15B, 0x6240341C,
+0x602C000B, 0x644CD159, 0x6240341C, 0x602C000B,
+0x4F222FE6, 0xE60A655C, 0x8D153567, 0xBFEA6E43,
+0x640C6453, 0x880160EC, 0xE00F8B02, 0x2409A002,
+0x44094409, 0xE60A624C, 0x89053263, 0x644CBFE2,
+0x6023620C, 0x8B00C880, 0x6023E200, 0x000B4F26,
+0x4F226EF6, 0x6062D646, 0x8B038801, 0x0009B241,
+0x0009A003, 0xE640D243, 0xD6432260, 0x4F26E200,
+0x2622000B, 0xD63E4F22, 0x88026062, 0xB28B8B01,
+0xD63D0009, 0x4F26E200, 0x2622000B, 0xD439D538,
+0xE701E100, 0x000B2512, 0x0FFF2470, 0xE604D235,
+0x2260000B, 0xD4354F22, 0x410BD135, 0xD5250009,
+0x6650E1FD, 0x2619D233, 0x2560E700, 0x000B4F26,
+0x4F222270, 0xD12ED430, 0x0009410B, 0xE7FBD51D,
+0x26796650, 0x000B4F26, 0x4F222560, 0xD128D42B,
+0x0009410B, 0xE7F7D517, 0x26796650, 0x000B4F26,
+0xD5142560, 0x62509425, 0x000B2249, 0xD5112520,
+0x6250E4BF, 0x000B2249, 0x4F222520, 0x8522D220,
+0x2008600D, 0x88018911, 0x8803893C, 0x8805893E,
+0x88068940, 0x88088946, 0x8809894C, 0x880A8952,
+0x880B8958, 0xA065895E, 0xB0670009, 0xA0620009,
+0xFF7F600C, 0x001E1028, 0x001E2148, 0x001E1108,
+0x002029DC, 0x002029DE, 0x002029E9, 0x002029C0,
+0x001E103F, 0x001E105F, 0x001E1030, 0x001E1090,
+0x002029E4, 0x001E100B, 0x002029E0, 0x00202AC8,
+0x00200F72, 0x002029E8, 0x00202AD4, 0x00202AE4,
+0x002029B4, 0x0009B04C, 0x600CA035, 0x0009B056,
+0x600CA031, 0x6260D67C, 0x8B2B2228, 0x0009B062,
+0x600CA029, 0x6260D678, 0x8B232228, 0x0009B06A,
+0x600CA021, 0x6260D674, 0x8B1B2228, 0x0009B0B4,
+0x600CA019, 0x6260D670, 0x8B132228, 0x0009B0BA,
+0x600CA011, 0x6260D66C, 0x8B0B2228, 0x0009B11A,
+0x600CA009, 0x6260D668, 0x8B032228, 0x0009B132,
+0x600CA001, 0x4F26E000, 0x0009000B, 0xD264D163,
+0xD5648412, 0x4000C90F, 0xD763012D, 0x611CE403,
+0xD662E20F, 0x27122540, 0xE0012520, 0x2602000B,
+0xE601D25A, 0x30668523, 0xE0008D06, 0xE000D258,
+0x8122D65A, 0x2602E001, 0x0009000B, 0x8523D253,
+0x2008600D, 0x88018905, 0xD6558B0A, 0xCB016060,
+0xD6522600, 0xE101D44E, 0x2612E001, 0x8142000B,
+0xE000000B, 0xE501D149, 0x45188513, 0x3453640D,
+0x8D056603, 0xD24BE000, 0xE001D548, 0x25022260,
+0x0009000B, 0xD1414F22, 0x650D8513, 0x44196453,
+0x672E6249, 0x602C227D, 0x89098801, 0x890C8802,
+0x89108803, 0x89268806, 0x89298807, 0x0009A038,
+0xD63ED53D, 0xA027E212, 0x625C2652, 0x8B2F2228,
+0xA01ED63B, 0x605C6262, 0x89052008, 0x89088810,
+0x890B8820, 0x0009A024, 0xD634D436, 0xA013E204,
+0xD7352642, 0xE20CD631, 0x2672A00E, 0xD62FD533,
+0xA009E218, 0xD4322652, 0xE20AD62C, 0x2642A004,
+0xD62AD230, 0xE22E2622, 0xD42F8515, 0x3277670D,
+0x8F012421, 0x24516503, 0x0009B0DB, 0xE001A001,
+0x4F26E000, 0x0009000B, 0xE101D61A, 0x2610D427,
+0xD7196541, 0x655DD119, 0xE001E20F, 0x26202752,
+0x2102000B, 0x4F222FE6, 0x8523D210, 0x2448640C,
+0xD61E8B08, 0xE200D512, 0x84512621, 0x20499412,
+0x8051A050, 0x60E0DE0E, 0x8D35C840, 0x3427E201,
+0xD116894C, 0x420BD216, 0xD5162141, 0xCB046052,
+0x2502A035, 0x0000FF7F, 0x002029E9, 0x002029B4,
+0x002029C0, 0x001E1100, 0x001E100C, 0x002029E0,
+0x001E1000, 0x001E1001, 0x00202C40, 0x002029C8,
+0x002029D0, 0x00202CAE, 0x00202CB2, 0x00202CBE,
+0x00202CD6, 0x00202CE0, 0x002029CC, 0x002029DA,
+0x00201DB6, 0x001E1108, 0x89173427, 0xD794D293,
+0x2241470B, 0xE5FBD693, 0x21596162, 0x84E12612,
+0xB0FFCB80, 0x60E080E1, 0xCB04D68F, 0x60602E00,
+0x2600C93F, 0xE001D68D, 0x2602A001, 0x4F26E000,
+0x6EF6000B, 0x6060D68A, 0x8919C880, 0x6021D283,
+0x8B158801, 0xE501D287, 0x30568524, 0xD1868910,
+0xD486E203, 0x65412120, 0x655DE00B, 0xD5840656,
+0xE702E40F, 0x25712140, 0xE001D77C, 0x2702000B,
+0xE000000B, 0x4F222FE6, 0x84E1DE7E, 0x8934C880,
+0x8554D578, 0x8F302008, 0xD77B6103, 0x66728553,
+0x650C6403, 0x620C8566, 0x8B263520, 0xD773D677,
+0x644C651C, 0x27412651, 0xC84060E0, 0xD2748907,
+0x0009420B, 0x6062D667, 0xA008CB04, 0xD1642602,
+0x0009410B, 0xE5FBD663, 0x24596462, 0xB0A12642,
+0xD5620009, 0x2522E201, 0xD75F60E0, 0x2E00CB04,
+0xC93F6070, 0xA0012700, 0xE0006023, 0x000B4F26,
+0x2FA66EF6, 0x2FC62FB6, 0x2FE62FD6, 0xE240DA5C,
+0xDC5966A1, 0x3123616D, 0x62638900, 0x6ED36D2C,
+0x4E2136D8, 0x4E212A61, 0xDB5BD45A, 0xE700A00F,
+0x770166B2, 0x71026163, 0x65612B12, 0x71026613,
+0x62612B12, 0x622D655D, 0x325C4228, 0x627C2422,
+0x8BED32E3, 0xC90360D3, 0x8B108803, 0xED076EB2,
+0x710261E3, 0x67132B12, 0x62E17102, 0x65712B12,
+0x655D622D, 0x352C4528, 0xA00C2CD0, 0x88022452,
+0xA0038B01, 0x8801E203, 0xE2018B05, 0x66B22C20,
+0x677D6761, 0xEB0F2472, 0x6DA12CB0, 0x8B052DD8,
+0xD432D23E, 0xE101EE00, 0x241222E2, 0x6DF66EF6,
+0x6BF66CF6, 0x6AF6000B, 0x2FE62FD6, 0xE240DD30,
+0x616D66D1, 0x89003123, 0x672C6263, 0xDE323678,
+0x2D617703, 0xD62F4721, 0x472164E2, 0xE100A00E,
+0x71016562, 0x24506253, 0x42197401, 0x74012420,
+0x24504529, 0x45197401, 0x74012450, 0x3273621C,
+0x42008BEE, 0x64D166E2, 0x362C4200, 0x8F062448,
+0xDD222E62, 0xE500DE15, 0x2D52E701, 0x6EF62E72,
+0x6DF6000B, 0x2FE62FD6, 0xEE014F22, 0xED0AA005,
+0x64E3BC97, 0x64E3BC9D, 0x62EC7E01, 0x8BF732D7,
+0xEE01A005, 0x64E3BC9E, 0x64E3BCA4, 0x62EC7E01,
+0x8BF732D7, 0x6EF64F26, 0x6DF6000B, 0x002029DA,
+0x00201EC2, 0x001E1108, 0x001E1015, 0x002029E0,
+0x001E1001, 0x002029B4, 0x001E1100, 0x002029DE,
+0x002029CC, 0x001E1000, 0x002029D0, 0x002029DC,
+0x00201DB6, 0x001E100C, 0x002029C8, 0x002029E4,
+0x2FE62FD6, 0x7FFC4F22, 0x6060D64C, 0x89488801,
+0xE101D44B, 0xD74B8548, 0x650D2610, 0x45196070,
+0x6659DD49, 0x61D3626E, 0xC840262D, 0x74027102,
+0x8D1AD746, 0xD246666C, 0xE501DE46, 0xA0042E22,
+0x6245EE04, 0x21217501, 0x625C7102, 0x8BF832E3,
+0x81D46063, 0xD540E601, 0x626CE417, 0x891E3243,
+0x76016255, 0xAFF82721, 0xD23C7702, 0xE501DE39,
+0xA0042E22, 0x6245EE04, 0x21217501, 0x625C7102,
+0x8BF832E3, 0x81D46063, 0xD535E601, 0xE417A004,
+0x76016255, 0x77022721, 0x3243626C, 0x924B8BF8,
+0xD4302D21, 0x6142D730, 0x65F22F12, 0x60536DF2,
+0x2700C980, 0xC9606053, 0x80716103, 0x6EF26053,
+0xC90365F2, 0x45294D19, 0x60DC8072, 0x81724519,
+0x605C4E29, 0x401862EC, 0x8173302C, 0x21186D42,
+0x6EF22FD2, 0x66F262F2, 0x46294219, 0x66F2656C,
+0x64EC602C, 0x46294018, 0x4619304C, 0x606C8174,
+0x305C4018, 0x81758F07, 0x0009BCBF, 0x2228620C,
+0xA00A8908, 0x60130009, 0x8B038840, 0x0009B00A,
+0x0009A003, 0xE202D611, 0x7F042622, 0x6EF64F26,
+0x6DF6000B, 0x0009000B, 0x0000060A, 0x002029E8,
+0x00202C40, 0x001E1000, 0x00202CD6, 0x00202CE2,
+0x00202C52, 0x002029D0, 0x00202C82, 0x00202C80,
+0x00202C54, 0x001E100C, 0x002029B4, 0x002029E0,
+0x4F222FE6, 0xDE907FFC, 0x200884E9, 0x2F008D06,
+0xD68FD48E, 0x0009460B, 0x64F0B146, 0x6620D28D,
+0x89022668, 0xC9BF60E0, 0x7F042E00, 0x000B4F26,
+0x000B6EF6, 0x2FE60009, 0xDE874F22, 0x60E0D687,
+0xCBC0D487, 0x62602E00, 0xC803602C, 0x40218904,
+0x70014021, 0x6603A002, 0x66034009, 0xD681616D,
+0xE500A004, 0x75016262, 0x74042422, 0x3213625D,
+0xD27D8BF8, 0x0009420B, 0xC9BF84E2, 0x4F2680E2,
+0x6EF6000B, 0x2FD62FC6, 0x4F222FE6, 0xDC727FFC,
+0x84C2D276, 0xCB40DD76, 0x80C2420B, 0x8D042008,
+0x62E06E03, 0xA006642C, 0xD66A7404, 0x6160D471,
+0x470BD771, 0x644D651C, 0x45216543, 0xA0044521,
+0x62E6E600, 0x2F227601, 0x626D2D22, 0x8BF83253,
+0xC9036043, 0x89122008, 0x89058803, 0x89068802,
+0x89078801, 0x0009A008, 0xA005E007, 0xE00380D8,
+0x80D8A002, 0x80D8E001, 0x2F2262E2, 0xE00F2D22,
+0x80D8D65E, 0xCB086060, 0x60C02600, 0x2C00C93F,
+0x4F267F04, 0x6DF66EF6, 0x6CF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xD2564F22, 0x6E436D73, 0x420B6B53,
+0x20086C63, 0x64038F08, 0xD245D452, 0x6EF64F26,
+0x6CF66DF6, 0x6BF6422B, 0x24E060B3, 0x60C38041,
+0xA0078141, 0x655DE500, 0x00DC6053, 0x324C6253,
+0x80247501, 0x6EEC625D, 0x8BF432E3, 0x6060D636,
+0x2600C9BF, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x7FC44F22, 0x720262F3, 0x22512F41, 0x45297202,
+0x60632251, 0xE5C4E682, 0x67F38121, 0x655C666C,
+0xE408BFBC, 0x4F267F3C, 0x0009000B, 0xD237D136,
+0xE4056012, 0xE500CB20, 0x22422102, 0x2252000B,
+0xD534D133, 0xE400D734, 0x2142E20F, 0x17411154,
+0xD5322722, 0x9635D732, 0x15412572, 0x96321562,
+0xE6011565, 0xD52F1165, 0x666CE6F8, 0x25422542,
+0x25422542, 0x25422542, 0x25622542, 0x7601E727,
+0x67632572, 0x25627797, 0xE7042572, 0x2572E248,
+0xE2192522, 0xE2702522, 0x25422542, 0x25422542,
+0x25222542, 0x2522E20C, 0x25422542, 0x25422542,
+0x25422542, 0x25422542, 0x000B154A, 0xE2081145,
+0x0009422B, 0x51630601, 0x001E1017, 0x00202AF0,
+0x00200F72, 0x002029B0, 0x001E1015, 0x001E10BF,
+0x00117800, 0x001E10FC, 0x00200100, 0x0020201A,
+0x001E10F8, 0x00202AF4, 0x00200FBC, 0x001E10AE,
+0x00201FDC, 0x00202B10, 0x001C3500, 0x001D4004,
+0x001C581C, 0xA000A000, 0x001D0100, 0x001D4000,
+0x00040021, 0x001C589C, 0x2FE62FD6, 0x7FFC4F22,
+0xC8206043, 0x6E438D02, 0x0009BEBB, 0xC81060E3,
+0xBEB88901, 0x60E30009, 0x8901C840, 0x0009BEDA,
+0xC80160E3, 0xDD378936, 0xC80260D0, 0x2F008D03,
+0x460BD635, 0x60F00009, 0x8902C804, 0x460BD633,
+0x62F00009, 0xC8806023, 0x60D08902, 0x2D00C97F,
+0xC8016023, 0xD62E8904, 0x0009460B, 0x0009A005,
+0x8902C808, 0x460BD62B, 0x60F00009, 0x8902C810,
+0x420BD229, 0xD5290009, 0x88026052, 0xD2288B03,
+0xA005E604, 0x88012260, 0xD2258B02, 0x2260E601,
+0x2522E200, 0xC88060E3, 0xD622892E, 0x60E36E60,
+0x8902C880, 0x420BD220, 0x60E30009, 0x8902C840,
+0x420BD21E, 0x60E30009, 0x8902C802, 0x420BD21C,
+0x60E30009, 0x890EC804, 0x410BD11A, 0xBF150009,
+0xBF1D0009, 0xD5180009, 0x6050D418, 0xC908D718,
+0xBF542500, 0x60E32472, 0x8905C808, 0x7F04D215,
+0x6EF64F26, 0x6DF6422B, 0x4F267F04, 0x000B6EF6,
+0x00006DF6, 0x001E1021, 0x00201182, 0x002011A4,
+0x002017B0, 0x002011BC, 0x002011CC, 0x002029E0,
+0x001E100B, 0x001E1028, 0x00201222, 0x0020122E,
+0x002011D4, 0x002011F2, 0x001E1000, 0x0010F100,
+0x12345678, 0x0020120A, 0xD6A8644C, 0x346C74FF,
+0x2450000B, 0x644CD6A6, 0x000B346C, 0xD6A52450,
+0x346C644C, 0x2450000B, 0x616D625C, 0x41194208,
+0x60194208, 0x644C4200, 0x324C670E, 0x207DD19E,
+0xC90F4200, 0x000B321C, 0x67632200, 0x4208625C,
+0x42004208, 0x324C644C, 0x4200D198, 0x000B321C,
+0x2FE62270, 0x614C4F12, 0x4100D493, 0x6710314C,
+0x2729E29F, 0x65736E53, 0x4719676D, 0x672E6279,
+0x4221227D, 0x42214221, 0x7601662C, 0xE4014608,
+0x34E84608, 0x644C4600, 0x0E1A0467, 0x215025EB,
+0x000B4F16, 0x4F226EF6, 0xD2857FE8, 0x88016021,
+0xD2848B7B, 0x26686621, 0xD2838B77, 0x26686621,
+0xE50F8B73, 0xE401BFA0, 0xBFA3E501, 0xE586E400,
+0xE400655C, 0x2F50BFA3, 0xBFA0E401, 0xE602E506,
+0x60634618, 0x81F2E401, 0x6543BF9E, 0xE40185F2,
+0xBFAA6543, 0x85F26603, 0x6543E401, 0x6603BFB1,
+0xE40265F0, 0x6053756C, 0x80F8BF7E, 0xBF81E402,
+0x84F8E512, 0x7090E402, 0x6503BF81, 0x4618E602,
+0x81F66063, 0xBF7FE402, 0x85F6E500, 0x6603E402,
+0xE500BF8B, 0xE40285F6, 0xBF926603, 0xE5FEE500,
+0xE010655C, 0xBF5FE403, 0xE5130F54, 0xE40EBF62,
+0x05FCE010, 0xBF62E40E, 0xE5007585, 0xBF63E403,
+0xE500E640, 0xBF70E403, 0xE500E640, 0xBF78E403,
+0xE5FFE640, 0xE014655C, 0xBF45E404, 0xE40F0F54,
+0xE504BF48, 0x05FCE014, 0xBF48E40F, 0xE5017584,
+0xBF49E640, 0xE501E404, 0xBF56E640, 0xE501E404,
+0xE404E640, 0xAF5C7F18, 0x7F184F26, 0x000B4F26,
+0x4F220009, 0xD2427FF0, 0x88016021, 0xD2418B71,
+0x26686621, 0xD2408B6D, 0x26686621, 0xE50F8B69,
+0xE401BF1A, 0xBF1DE501, 0xE586E400, 0xE400655C,
+0x2F50BF1D, 0xBF1AE401, 0xE401E506, 0xBF1B6543,
+0xE401E640, 0xBF286543, 0xE401E640, 0xBF306543,
+0x65F0E640, 0x756CE402, 0xBEFD6053, 0xE40280F4,
+0xE512BF00, 0xE40284F4, 0xBF007090, 0xE6406503,
+0xBF01E402, 0xE640E500, 0xBF0EE402, 0xE640E500,
+0xBF16E402, 0xE5FEE500, 0x6053655C, 0xBEE3E403,
+0xE51380F8, 0xE40EBEE6, 0xE40E84F8, 0xBEE67085,
+0xE5006503, 0xBEE7E640, 0xE500E403, 0xBEF4E640,
+0xE500E403, 0xBEFCE640, 0xE5FFE403, 0x6053655C,
+0xBEC9E404, 0xE40F80FC, 0xE504BECC, 0xE40F84FC,
+0xBECC7083, 0xE5016503, 0xBECDE640, 0xE501E404,
+0xBEDAE640, 0xE501E404, 0xE404E640, 0xAEE07F10,
+0x7F104F26, 0x000B4F26, 0x00000009, 0x001E1030,
+0x001E1080, 0x001E1090, 0x001E103F, 0x001E103E,
+0x002029DA, 0x002029DC, 0x002029DE, 0xD21DD11C,
+0x66206010, 0x676C7001, 0x3700C90F, 0xE5008D13,
+0x67106210, 0x7701622C, 0x64232170, 0xD6166010,
+0x44084408, 0x3428C90F, 0x62602100, 0x7201D513,
+0x44082620, 0x000B354C, 0xD10F6053, 0x25586510,
+0xE6008D13, 0xD60DD40B, 0x655C6540, 0x47086753,
+0x37584708, 0x47086540, 0x24507501, 0x367C6040,
+0x2400C90F, 0x72FF6210, 0x000B2120, 0x00006063,
+0x002029AF, 0x002029AE, 0x002029B0, 0x002025D4,
+0x7FFC4F22, 0xE680D19D, 0x666C6212, 0xD29C2F22,
+0x67F36563, 0x420B7542, 0x7F04E404, 0x000B4F26,
+0xE6800009, 0xD296666C, 0xE7006563, 0x422B7540,
+0xE6806473, 0xD292666C, 0xE7006563, 0x422B7543,
+0x2FB66473, 0x2FD62FC6, 0x4F222FE6, 0x4D18ED01,
+0xDB8DDC8C, 0x65C252C1, 0x89203520, 0xC9036051,
+0x891C8801, 0xD189DE87, 0x64E3410B, 0x85036503,
+0x670D66B2, 0x89073762, 0xD286D485, 0x0009420B,
+0xE701D185, 0x2172AFE6, 0xDE8464E3, 0x00094E0B,
+0xD484D683, 0x410BD184, 0xAFDB26D2, 0x4F260009,
+0x6DF66EF6, 0x000B6CF6, 0x4F226BF6, 0x85467FF4,
+0x2F01E681, 0x666C8547, 0x854881F1, 0x81F2D270,
+0x67F38542, 0x854381F3, 0x81F4E40C, 0x65636053,
+0x420B81F5, 0x7F0C7540, 0x000B4F26, 0x2F860009,
+0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6, 0x7FF44F22,
+0xDC6EE200, 0x2F21A136, 0xDD6D6A13, 0xE0014A08,
+0x4D0BD96C, 0x3A9C4A00, 0x1F917930, 0x66C21F02,
+0x362052C1, 0xA1218B01, 0x60610009, 0x8801C903,
+0xA11B8B01, 0x85610009, 0x8977C801, 0x85D25D63,
+0xC9036603, 0x85D36403, 0x6053650D, 0x40214021,
+0x4500C93F, 0x322A6103, 0x6053252D, 0xC901E210,
+0xD9553123, 0x6E038D21, 0x4408D757, 0x44086570,
+0x44006213, 0x25584200, 0x342C8F0E, 0x6043D253,
+0x60E3072D, 0x4B196B7D, 0x658E68B9, 0x285D8801,
+0x6B7C8F0B, 0x6B13A009, 0x6043D24D, 0x61ED0E2D,
+0x68194119, 0x287D678E, 0xD14A6BEC, 0x22286212,
+0xEBFF8901, 0xEEFF6BBC, 0x6EEC65BD, 0x8B0F35E0,
+0x4D0BDD36, 0x540364C3, 0xBF76E502, 0xD4426D03,
+0x410BD136, 0xD74165D3, 0xD441EE01, 0x27E2A01D,
+0x26E9EEFC, 0x81D26063, 0x914E85D3, 0x81D32019,
+0x450885D2, 0x81D2208B, 0xE20885D3, 0x81D3205B,
+0x421885D4, 0x81D4202B, 0x854164C2, 0x814120E9,
+0xD43465C2, 0xCB016051, 0x490B2501, 0x60C20009,
+0x52F256F1, 0x2A02CB01, 0x2622AF79, 0x420BD21B,
+0x5E0364C3, 0x85E16D03, 0x6053650D, 0x897BC820,
+0x6210D129, 0x8B112228, 0xD72785EF, 0x4221620D,
+0x42214221, 0xE501D625, 0x27504221, 0xD725D924,
+0x2621D425, 0x2960E600, 0x24612762, 0x852162C2,
+0x8B43C802, 0xD912D71E, 0xE0016270, 0x612C490B,
+0x6692D91C, 0xA03E260B, 0x7E032962, 0x001C3D9C,
+0x00201A3C, 0x002025CC, 0x00202994, 0x00200D42,
+0x00202594, 0x00200DC4, 0x001E2130, 0x00200D60,
+0x001C3D30, 0x00202C28, 0x00200F72, 0x002025A4,
+0x0020248C, 0x001C3D00, 0x00202C3C, 0x00202B28,
+0x00202BA8, 0x002029A8, 0x0020259C, 0x001E212C,
+0x00202C2C, 0x00202C30, 0x00202D10, 0x002029EE,
+0x002029EC, 0x002029F0, 0x002029F4, 0xE04CD139,
+0x7201021E, 0xD9380126, 0x6290D438, 0x72016541,
+0x29207501, 0x85E12451, 0x4618E640, 0x891D2068,
+0xD934D733, 0x665D6171, 0x6592D733, 0x641D470B,
+0xE200DE32, 0x2E20A012, 0xE90885E4, 0x49186203,
+0x32902299, 0xE5018B04, 0x64E3BEB7, 0x0009A006,
+0x2598D92B, 0xE5008902, 0x64E3BEAF, 0xD22AD429,
+0x65D3420B, 0xEE01D729, 0x27E2AED9, 0x7C0862F1,
+0x2F217201, 0xEE0462F1, 0x31E7612D, 0xAEC38901,
+0x7F0C0009, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0x2FE668F6, 0xD21D4F22, 0x60E36E22,
+0x8D02C840, 0xBE3322E2, 0xE2400009, 0x2E284218,
+0xBE3E8901, 0x60E30009, 0x8905C810, 0xD216D415,
+0x0009420B, 0x0009BE3D, 0xC80560E3, 0xBE8E8901,
+0x60E30009, 0x8902C802, 0xAE3A4F26, 0x4F266EF6,
+0x6EF6000B, 0x00202538, 0x002029EC, 0x002029F4,
+0x002029EE, 0x002029F0, 0x00201AA0, 0x00202D10,
+0x00008000, 0x0020259C, 0x00200D60, 0x001E212C,
+0x001C3510, 0x00202C34, 0x00200F72, 0x080A0C0E,
+0x00020406, 0x1A1C1E20, 0x12141618, 0x2E303234,
+0x26282A2C, 0x3A3C3E40, 0x6C625648, 0x41112F26,
+0xE2208F18, 0x890B3123, 0x321CD204, 0xD1026220,
+0x412B312C, 0x00090009, 0x002024B6, 0x0020246C,
+0x000BE000, 0x400062F6, 0x40004000, 0x40004000,
+0x40004000, 0x62F6000B, 0x40004000, 0x40004000,
+0x40004000, 0x40184000, 0x62F6000B, 0x40004000,
+0x40004000, 0x40004000, 0x40284000, 0x62F6000B,
+0x40004000, 0x40184000, 0x000B4028, 0xC90F62F6,
+0x40054005, 0x40054005, 0x62F6000B, 0x4005C907,
+0x40054005, 0x62F6000B, 0x4005C903, 0x000B4005,
+0xC90162F6, 0x000B4005, 0x000062F6, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x544F0D0A, 0x46205355,
+0x00003A57, 0x2079614D, 0x32203033, 0x20373030,
+0x333A3231, 0x38313A37, 0x00000000, 0x00000D0A,
+0x00000043, 0x42707372, 0x3D206675, 0x554E203D,
+0x202C4C4C, 0x6E49677A, 0x4E497274, 0x6D754E51,
+0x0000003D, 0x61766E49, 0x2064696C, 0x72657375,
+0x20726F20, 0x2079656B, 0x00214449, 0x52504545,
+0x57204D4F, 0x65746972, 0x6461202C, 0x003D7264,
+0x6C617620, 0x0000003D, 0x00000A0D, 0x6E6B6E55,
+0x206E776F, 0x6D6D6F63, 0x3D646E61, 0x00000000,
+0x61437748, 0x7262696C, 0x6F697461, 0x6620206E,
+0x0A6C6961, 0x0000000D, 0x73696F4E, 0x61432065,
+0x7262696C, 0x6F697461, 0x6166206E, 0x21216C69,
+0x00000D0A, 0x00000D0A, 0x62735576, 0x7473725F,
+0x00000A0D, 0x62735576, 0x7375735F, 0x646E6570,
+0x00000A0D, 0x62735576, 0x7365725F, 0x000A0D6D,
+0x00000042, 0x72746E49, 0x6D652051, 0x2C797470,
+0x49677A20, 0x4972746E, 0x754E514E, 0x00003D6D,
+0x20746F4E, 0x756F6E65, 0x49206867, 0x4220514E,
+0x0A0D6675, 0x00000000, 0x000000FF, 0x00020001,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x010E010D, 0x00020003,
+0x01090108, 0x0002010A, 0x00030002, 0x02020201,
+0x02040203, 0x02060205, 0x02080207, 0x020A0209,
+0x020C020B, 0x020E020D, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x010E010D, 0x00FF010F,
+0x01090108, 0x010B010A, 0x00030002, 0x02020201,
+0x02040203, 0x02060205, 0x02080207, 0x020A0209,
+0x020C020B, 0x020E020D, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00205220, 0x00000046,
+0x00000059, 0x49544120, 0x0000204D, 0x00000000,
+0x02000112, 0x40FFFFFF, 0x91700CF3, 0x20104890,
+0x02090100, 0x0101002E, 0x09FA8000, 0x04000004,
+0x000000FF, 0x02010507, 0x07000200, 0x00028205,
+0x05070002, 0x00400383, 0x04050701, 0x01004003,
+0x002E0209, 0x80000101, 0x000409FA, 0x00FF0400,
+0x05070000, 0x00400201, 0x82050700, 0x00004002,
+0x03830507, 0x07010040, 0x40030405, 0x03040100,
+0x030C0409, 0x0079005A, 0x00410044, 0x03180053,
+0x00530055, 0x00320042, 0x0030002E, 0x00570020,
+0x0041004C, 0x0000004E, 0x00000000, 0x00000000,
+0x00000709, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, };
+
+const u32_t zcFwImageSize=11540;
diff --git a/drivers/staging/otus/hal/hpfwu_2k.c b/drivers/staging/otus/hal/hpfwu_2k.c
new file mode 100644
index 000000000000..94e2caca5369
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwu_2k.c
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE947FFC, 0xE114D594,
+0x1E13D494, 0x67521E4C, 0xD494D693, 0x37402769,
+0x62528F06, 0x7201D692, 0x60602522, 0x2600C93F,
+0xD7906152, 0x2512611D, 0x264B6652, 0x2562470B,
+0x0009B017, 0xE60095AC, 0xC84060E2, 0x2F028F03,
+0x8FF93652, 0xD4887601, 0x4E0BDE88, 0xD4880009,
+0x00094E0B, 0x4E0BD487, 0x7F040009, 0xA0524F26,
+0x4F226EF6, 0x410BD184, 0xD4840009, 0x0009440B,
+0x450BD583, 0xD7830009, 0xD283E1FF, 0x2712611D,
+0xD4825029, 0xE1FFCB01, 0x1209E501, 0x12112212,
+0xE7202452, 0x4718D57E, 0x2572D27E, 0xD17EE700,
+0xD67FD47E, 0xE2012270, 0x24702172, 0xD67D2620,
+0x2641E4FF, 0xD57CE600, 0x666DE104, 0x76016063,
+0x4000626D, 0x8FF83212, 0xD5780545, 0x2520E201,
+0xD278D777, 0xE480E100, 0x22122710, 0x6613D576,
+0x666D644C, 0x76046763, 0x375C626D, 0x8FF83243,
+0xD5722712, 0xD273D772, 0xE400E101, 0x27102511,
+0x000B4F26, 0x7FCC2242, 0xD170D56F, 0xD271DB70,
+0x1F51D471, 0xD6717508, 0x1F12D771, 0x1F55710C,
+0x1FB975FC, 0x72041F2A, 0x1F13EB10, 0x1F561F44,
+0x1F781F67, 0xD86B1F2B, 0xDD6CD96B, 0xDC6CEA00,
+0xD26DDE6C, 0x89003A22, 0xD15D7A01, 0x88016010,
+0x56F88B03, 0x4218E201, 0xD1682622, 0x0009410B,
+0x440BD467, 0xD5670009, 0x0009450B, 0x6010D150,
+0x8B108801, 0xE650D14F, 0x46186212, 0x8B083266,
+0x56F9D14B, 0x2120E200, 0xCB016062, 0x2602A003,
+0x72012710, 0x60822122, 0x89098801, 0xE2C8D15A,
+0x622C6612, 0x89033626, 0x6010D158, 0x8BC88801,
+0x51F66792, 0x217252F5, 0xD6555191, 0x55FA2212,
+0x52FB6462, 0x55612542, 0x2252E400, 0x61436643,
+0x05DE6013, 0x36CC4608, 0x07DE2652, 0xC9036071,
+0x8B028801, 0x720162E2, 0x74012E22, 0x36B3664C,
+0x71048FEE, 0x66C2D147, 0x45286512, 0x265B4518,
+0x60822C62, 0x89018801, 0x0009A168, 0x6272D742,
+0x8B132228, 0xD42BD741, 0x6772D541, 0x51536242,
+0x312C327C, 0x24222228, 0x15138D05, 0x6262D63D,
+0xB1627201, 0xD6232622, 0x2622E200, 0x52916692,
+0x8B013620, 0x0009A144, 0x6061A06E, 0x001C001C,
+0x001D4020, 0x0000B38E, 0xFFFF0000, 0x12340000,
+0x001E1015, 0x00201274, 0x002039EC, 0x002018A2,
+0x002039F8, 0x00203A10, 0x00201860, 0x00201964,
+0x00201288, 0x001C3510, 0x001C3624, 0x001E212C,
+0x002038EC, 0x00203484, 0x002038F4, 0x00203900,
+0x0020390C, 0x00203968, 0x0020396C, 0x00203914,
+0x00203915, 0x00203918, 0x00117700, 0x00203984,
+0x00203982, 0x002034E8, 0x00117710, 0x001C3D30,
+0x001C36F8, 0x00117734, 0x001C3684, 0x001C3D00,
+0x001C1000, 0x001C1028, 0x002034FC, 0x0020391C,
+0x00117600, 0x00117740, 0x7FFFFFFF, 0x00201730,
+0x00203322, 0x0020232C, 0x00203D9C, 0x0020396A,
+0x002034F4, 0x0020395C, 0x001C3D2C, 0x001C36B0,
+0x0020348C, 0x0011775C, 0x8801C90F, 0xA0CF8901,
+0xD1960009, 0x36206212, 0xD4958904, 0x2421E200,
+0x2162A0CC, 0x6211D193, 0x89012228, 0x0009A0C3,
+0xE202D78F, 0x75016571, 0x3123615D, 0x27518D02,
+0x0009A0BC, 0xD28C57F2, 0x62226072, 0x40094019,
+0xC90F4009, 0x8F19880A, 0x52F31F2C, 0x40196022,
+0x40094009, 0x8808C90F, 0xA0A78901, 0x60630009,
+0xCB0154F7, 0xD27E55F2, 0xE7012402, 0xD47FE100,
+0x22112572, 0x72016242, 0x2422A098, 0x8B3F8805,
+0x602252F3, 0x40094019, 0xC90F4009, 0x8B168802,
+0xE4FFD577, 0x644D6752, 0x8B102748, 0x6272D775,
+0x8B0C3260, 0x51F255F7, 0xD26DE701, 0x21722562,
+0xD571E100, 0x64522211, 0xA0777401, 0x52F32542,
+0x40196022, 0x40094009, 0x8805C90F, 0x31B38B6E,
+0xD26A8B6C, 0x672254F4, 0x7701D569, 0x61422272,
+0x1F1CE640, 0x46182159, 0x8B033160, 0x6262D665,
+0x26227201, 0xE200D65A, 0x2621B067, 0x0009A056,
+0x3123E220, 0x88038B52, 0x52F38B1E, 0x40196022,
+0x40094009, 0x8803C90F, 0xD25B8B16, 0x672254F4,
+0x7701D557, 0x61422272, 0x1F1CE640, 0x46182159,
+0x8B033160, 0x6262D655, 0x26227201, 0xE200D648,
+0x2621B043, 0x0009A010, 0xD452D551, 0xD2446752,
+0xE1007701, 0x25723A46, 0x22118F06, 0xEA00D64E,
+0x72016262, 0x2622B031, 0x2FB2D54C, 0x95736652,
+0xD44A5BF1, 0x36205241, 0x60618910, 0x8B01C803,
+0x2B22E201, 0x8FF54510, 0x57F15664, 0x6272E1F0,
+0x41284118, 0x2722221B, 0x6BF2A008, 0x6BF2A006,
+0xE200D62F, 0xD12F2621, 0x2121E200, 0xD13CE201,
+0x66122822, 0x8B012668, 0x0009AE2B, 0x450BD539,
+0xD1390009, 0xAE24E600, 0x2F862160, 0x2FA62F96,
+0x2FC62FB6, 0x2FE62FD6, 0x7FF44F22, 0xDE34D133,
+0x54116212, 0x1F4167E2, 0x2F22D432, 0xD5321F72,
+0xD2326743, 0x58417794, 0x69425A42, 0x5B166C72,
+0x60526D22, 0xCB20E600, 0xE5402502, 0x626D7601,
+0x8BFB3253, 0x55F162F2, 0x11512122, 0xD62855F2,
+0x14812E52, 0x249214A2, 0x27C2D426, 0x26D211B6,
+0xDA256742, 0xE801D925, 0x490B2A72, 0xE2011A8C,
+0x1A2C4218, 0x4F267F0C, 0x6DF66EF6, 0x6BF66CF6,
+0x69F66AF6, 0x68F6000B, 0x000007D1, 0x0020397C,
+0x00203980, 0x00203986, 0x001C3DC0, 0x0011772C,
+0x001C3B88, 0x00203964, 0x0011773C, 0x00117744,
+0x0000F000, 0x00117764, 0x00117748, 0x00117768,
+0x0011776C, 0x01FFFFFF, 0x0011774C, 0x002034F4,
+0x00203D9C, 0x002024F0, 0x0020396A, 0x001C3B9C,
+0x001C3D98, 0x001C3700, 0x001C3500, 0x001C5960,
+0x001C8960, 0x002034FC, 0x001C3D00, 0x0020160C,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xDE957FAC, 0x61E0E014, 0x0F14D494, 0x710161E3,
+0xE0186210, 0xD2920F24, 0x0009420B, 0x450BD591,
+0x20080009, 0x8F126D03, 0xD28F1F07, 0x6720D48F,
+0x657CDD8F, 0x470BD78F, 0xD18F0009, 0x619C6910,
+0x46086613, 0x36184608, 0x3D6C4608, 0xE0181FD7,
+0xE58004FC, 0x604C66E2, 0x3050655C, 0x2D628F15,
+0x01FCE014, 0xDE85E500, 0x641CA008, 0x6753655D,
+0x607037EC, 0x39DC6953, 0x80947501, 0x3243625D,
+0xD67F8BF4, 0xA34EE200, 0x20082621, 0xE0148B13,
+0xE40001FC, 0xA009DE79, 0x644D671C, 0x35EC6543,
+0x69436652, 0x39DC6262, 0x74041921, 0x3273624D,
+0xA3388BF3, 0x88012D10, 0xE0148B17, 0xE70001FC,
+0x6D1C2D70, 0xDE6D1FD4, 0x32D3627D, 0xA32A8B01,
+0x677D0009, 0x667365E3, 0x61737504, 0x315C36EC,
+0x69126462, 0xAFEF7708, 0x88042492, 0xE0148B18,
+0xE40001FC, 0x671C2D40, 0x624DDE60, 0x8B013273,
+0x0009A311, 0x6943644D, 0x39EC62E3, 0x72046592,
+0x3D2C6D43, 0x615266D2, 0x21697408, 0x2512AFED,
+0x8B188805, 0x01FCE014, 0x2D40E400, 0xDE53671C,
+0x3273624D, 0xA2F68B01, 0x644D0009, 0x62E36943,
+0x659239EC, 0x6D437204, 0x66D23D2C, 0x74086152,
+0xAFED216B, 0x88312512, 0xD44A8B3A, 0x6146D94A,
+0x75046543, 0x67566442, 0x6E531F48, 0x65527E04,
+0x7EE462E2, 0x7E0464E2, 0x6EE21FE9, 0x5EF929E0,
+0x7E04D942, 0x1FEA60E2, 0x2900C901, 0xD9406EE2,
+0x29E04E09, 0x2F562F26, 0x56FAD93E, 0x6513490B,
+0xD13D7F08, 0xE71C6E0D, 0x1DE12D70, 0xDE3B6912,
+0x64E21D92, 0x1D43D13A, 0xD23A6512, 0x67221D54,
+0x1D75D239, 0x1D666622, 0x6262D638, 0x1D27A2AB,
+0x8B398830, 0x6596D92B, 0x67926696, 0x61967904,
+0x74E46493, 0x6E436992, 0x1F9B7E04, 0x1FEC6442,
+0xD9256EE2, 0x5EFC29E0, 0x7E04D924, 0x1FED60E2,
+0x2900C901, 0xD9226EE2, 0x29E04E09, 0x59FC7FFC,
+0xDE272F92, 0x2F164E0B, 0xD41F7F08, 0xE21C610D,
+0x1D112D20, 0xD2206442, 0xD41C1D42, 0x1D536542,
+0x6752D51B, 0xD71B1D74, 0x1D156172, 0x1D666622,
+0x6262D61A, 0x1D27A26F, 0x8B358833, 0x490BD919,
+0xA268EE00, 0x00002DE0, 0x00117800, 0x00203A14,
+0x002018A2, 0x00202AA4, 0x00203906, 0x00203A18,
+0x0020352C, 0x002018EE, 0x00203905, 0x00117804,
+0x00203984, 0x00117810, 0x00203901, 0x00203902,
+0x00203903, 0x00200F64, 0x001C5864, 0x001C6864,
+0x001C7864, 0x001C59BC, 0x001C69BC, 0x001C79BC,
+0x00200FBC, 0x00200FB8, 0x89018828, 0x0009A0C0,
+0xE643DEB5, 0x326662E1, 0x1FEE8F02, 0x2E21E240,
+0x622D62E1, 0x8B013267, 0x0009A0AA, 0xE50185E1,
+0x8B013056, 0x0009A0A4, 0x2D10E101, 0x64E1B225,
+0xE64357FE, 0x652D6271, 0x89443567, 0x3563E640,
+0xE6008B05, 0x0F65E040, 0xA00FE11A, 0x615372C0,
+0x41214121, 0x41214121, 0x45214121, 0x45214521,
+0xC9036053, 0xE0406603, 0x71180F65, 0x2209E007,
+0x0F25E03C, 0xE044641D, 0xB2A365F3, 0xE33C0F46,
+0x853233FC, 0x620DDE95, 0x42086031, 0x6023610D,
+0x1323E944, 0x06FE4108, 0xE00F39FC, 0x13144E0B,
+0x67075D91, 0x60D32679, 0x0F6654FE, 0x51928542,
+0x600D4E0B, 0x60D3260B, 0x0F666492, 0x65F3B237,
+0x696156FE, 0xE640659D, 0x89383563, 0xD78359FE,
+0x79066591, 0xC9036053, 0x40004008, 0x61036203,
+0x0F26E050, 0x470BE0FF, 0x6C07600C, 0x6603605D,
+0x46214621, 0x46214621, 0x42006263, 0x4200326C,
+0x40214021, 0x4008C903, 0x6D2D30FC, 0xE8006A03,
+0xB25765F3, 0x6EA264D3, 0x2EC9E050, 0x66942AE2,
+0xD76E01FE, 0x606C470B, 0x2AE22E0B, 0x64D365F3,
+0x7801B1FD, 0xEE06628D, 0x8FE932E3, 0x5EFE7D01,
+0x61E1E400, 0x410085E1, 0x66E3310C, 0x760C711B,
+0xE70465F3, 0x68667401, 0x3A736A4D, 0x8FF92582,
+0x65F37504, 0x641DB1E3, 0x64E1B1A4, 0x0009A17B,
+0xD45B56F7, 0xEC01D25B, 0x26C0420B, 0x0009A173,
+0x06FCE018, 0x8829606C, 0x58F78B08, 0xE400D252,
+0x66222840, 0x646DB171, 0x0009A165, 0x666CE681,
+0x89013060, 0x0009A0AC, 0xD550D14F, 0x62126A56,
+0x212232AC, 0x54116C56, 0x34CC6253, 0x64521141,
+0x72085812, 0xD44A384C, 0x68221182, 0x5A136C42,
+0x3ACC3C8C, 0x11A324C2, 0x6C2272EC, 0x72105814,
+0x118438CC, 0x5A156822, 0x11A53A8C, 0x6A227210,
+0xD6405816, 0x118638AC, 0x52176C62, 0x112732CC,
+0x5A185861, 0x11A83A8C, 0x5C195A62, 0x11C93CAC,
+0x521A5C63, 0x112A32CC, 0x5A1B5864, 0x11AB3A8C,
+0x5C1C5A65, 0x11CC3CAC, 0x521D5C66, 0x112D32CC,
+0x5A1E5867, 0x11AE3A8C, 0x561F5A68, 0x36ACE840,
+0x116FDA2D, 0x6CA2381C, 0x7A946682, 0x286236CC,
+0x5C8162A2, 0x18C13C2C, 0x62A27A44, 0x362C5682,
+0xD6261862, 0x5A856262, 0x3A2C4229, 0x760418A5,
+0x56866262, 0x362C4229, 0x56F71866, 0x2620E238,
+0x16C15C81, 0x16226212, 0xE2005C11, 0x551216C3,
+0x55151654, 0x55131655, 0x55161656, 0x55821657,
+0x65821658, 0x55141659, 0x5584165A, 0x5583165B,
+0x5585165C, 0x5586165D, 0x1821165E, 0x11212122,
+0x11251122, 0x11261123, 0x28221822, 0x18241124,
+0x18251823, 0x1826A0C7, 0x00117804, 0x002033E0,
+0x00203A38, 0x002018A2, 0x0020348C, 0x001C36A0,
+0x002034E8, 0x001C3CA0, 0x001C36F4, 0x001C3B88,
+0x666CE682, 0x8B203060, 0xEA2456F7, 0x26A0D194,
+0x16C15C17, 0x16225218, 0x16835819, 0x16A45A1A,
+0x16C55C1B, 0x1626521C, 0xE200581D, 0x551E1687,
+0x551F1658, 0x11271659, 0x11291128, 0x112B112A,
+0x112D112C, 0xA08E112E, 0xE683112F, 0x3060666C,
+0x52F78B0B, 0xEA00D883, 0x658222A0, 0x7804DC82,
+0x62822C52, 0xA07ED681, 0xE6902620, 0x3060666C,
+0xDA7F8B06, 0x00094A0B, 0xE20056F7, 0x2620A073,
+0x666CE691, 0x8B103060, 0x6222D276, 0x2228622C,
+0xD2788904, 0x0009420B, 0x0009A003, 0x420BD276,
+0x56F70009, 0xA05EE200, 0xE6922620, 0x3060666C,
+0xE0188951, 0xE6B00BFC, 0x666C62BC, 0x8B2A3260,
+0x02FCE014, 0x682CEA00, 0x62ADE904, 0x894A3283,
+0x6AADDD64, 0x3CDC6CA3, 0x7D046EC2, 0xDB68D467,
+0x32DC62A3, 0x4B0BDC67, 0x4C0B6D22, 0xD46664E3,
+0x00094B0B, 0x64D34C0B, 0x4B0BD464, 0xE6000009,
+0x666D6BE3, 0x76013B6C, 0x3293626D, 0x8FF72BD0,
+0xAFDA4D19, 0xE6B57A08, 0x3260666C, 0xD45C8B13,
+0x4B0BDB57, 0xD25B0009, 0x6022DB5B, 0xCB20E6FF,
+0x2202666D, 0xDB592B62, 0xE014E200, 0x56F72B20,
+0xA01002FC, 0xD4562620, 0x6542D256, 0x420BD456,
+0xA0080009, 0xDB520009, 0x52B1E600, 0x622CDB53,
+0x52F72B21, 0x7F542260, 0x6EF64F26, 0x6CF66DF6,
+0x6AF66BF6, 0x000B69F6, 0x4F2268F6, 0xE240614D,
+0x89143123, 0x3127E21F, 0x8B09D749, 0xD449614D,
+0xE00171E0, 0x5671440B, 0x26596507, 0x1761A007,
+0xE001D444, 0x6672440B, 0x26596507, 0x4F262762,
+0x0009000B, 0x614D4F22, 0x3123E240, 0xE21F8912,
+0xD73B3127, 0x614D8B08, 0x5671D23A, 0x420B71E0,
+0x260BE001, 0x1761A006, 0x6672D236, 0xE001420B,
+0x2762260B, 0x000B4F26, 0xE6400009, 0x46284618,
+0x6252D531, 0x89FC2268, 0x0009000B, 0x4618E680,
+0xD52D4628, 0x22686252, 0x000B89FC, 0xA0010009,
+0x7201E200, 0x8BFC3242, 0x0009000B, 0x4618E680,
+0xD5264628, 0x22686252, 0x000B8BFC, 0x2FE60009,
+0x7FFC4F22, 0xBFF16E53, 0x61E22F42, 0xE280D620,
+0x54E11615, 0x16464218, 0x422855E2, 0x57E31657,
+0x16786EF2, 0x26E22E2B, 0x4F267F04, 0x6EF6AFCE,
+0x0020348C, 0x00117804, 0x002038EC, 0x00203900,
+0x0020050A, 0x00201008, 0x0020102E, 0x00203A50,
+0x002018A2, 0x002018E6, 0x00203A64, 0x00203A6C,
+0x00203A70, 0x001C3500, 0x001C1000, 0x00203982,
+0x00117800, 0x002018EE, 0x00203A84, 0x00203988,
+0x001C3704, 0x002033E0, 0x001C373C, 0x001C3700,
+0x001C370C, 0x2FD62FC6, 0x4F222FE6, 0x6C53DD10,
+0x6E43BFA4, 0x2DE2BF89, 0x0009BFA0, 0x2C1251D5,
+0x1C4154D6, 0x1C5255D7, 0x1C6356D8, 0x6EF64F26,
+0x000B6DF6, 0x61636CF6, 0xA004E600, 0x62564109,
+0x24227601, 0x36127404, 0x000B8BF9, 0x00000009,
+0x001C370C, 0x0009A16E, 0x2FE62FD6, 0xDD944F22,
+0xA0049EB2, 0xD4930009, 0x420BD293, 0x62D265D2,
+0x8BF822E8, 0x0009A004, 0xD28FD490, 0x55D1420B,
+0x22E852D1, 0xA0048BF8, 0xD48D0009, 0x420BD28A,
+0x52D255D2, 0x8BF822E8, 0x0009A004, 0xD286D489,
+0x55D3420B, 0x22E852D3, 0xA0048BF8, 0xD4860009,
+0x420BD281, 0x52D455D4, 0x8BF822E8, 0x6EF64F26,
+0x6DF6000B, 0x2FD62FC6, 0x4F222FE6, 0x6E636C73,
+0x6D53B01A, 0x64D357F4, 0xB05F65E3, 0xB07566C3,
+0xB0A40009, 0xB0A80009, 0xB0AC0009, 0xB0AC0009,
+0xB0AF0009, 0xB03154F5, 0x6CCD6C03, 0x4F2660C3,
+0x6DF66EF6, 0x6CF6000B, 0x3412D170, 0xD6700529,
+0x2650D770, 0x2742000B, 0x0009A018, 0x2FD62FC6,
+0x4F222FE6, 0x6E636C73, 0x6D53BFEE, 0x64D357F4,
+0xB03365E3, 0xB08D66C3, 0xB00F54F5, 0x6CCD6C03,
+0x4F2660C3, 0x6DF66EF6, 0x6CF6000B, 0xE503D162,
+0xD763D462, 0x21524518, 0x2472000B, 0xD45FD15E,
+0x2162E600, 0x2462000B, 0xBF734F22, 0xBF73E40A,
+0xD25C0009, 0x4118E104, 0xE40AE500, 0xBF692212,
+0xD7592252, 0xCB206072, 0x000B4F26, 0x4F222702,
+0x410BD156, 0xD556E400, 0x4F26452B, 0xD1552FE6,
+0x66126E63, 0x92104418, 0x44084528, 0x45002629,
+0x265B4408, 0x264B4400, 0x21624708, 0xD14E4708,
+0x217227EB, 0x6EF6000B, 0x1FFF03F0, 0x4F222FE6,
+0xE101DE4A, 0xBF3DE40A, 0x67E32E12, 0xE500776C,
+0xE204E130, 0x2752E40A, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27222712,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x175ABF18, 0x2E62E600, 0x000B4F26, 0xD2346EF6,
+0xE441E101, 0x000B2212, 0xD1322242, 0xE605D432,
+0x000B2162, 0x000B2462, 0xD2300009, 0xE40AE601,
+0x2262AF00, 0x2FC62FB6, 0x2FE62FD6, 0x7FFC4F22,
+0x6C43DB2B, 0xED0060B2, 0x2B02CB03, 0xC90360B2,
+0x6E03A008, 0x89073DC2, 0xE46460B2, 0xB07CC903,
+0x7D016E03, 0x8BF52EE8, 0x8F043DC2, 0xD4212FE1,
+0x460BD621, 0x62F10009, 0x6023622D, 0x89FFC801,
+0x7F046023, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x001C3B88, 0x00203A98, 0x002018EE, 0x00203AA0,
+0x00203AA8, 0x00203AB0, 0x00203AB8, 0x0025E720,
+0x00203D98, 0x002038F0, 0x001C5968, 0x001C3B40,
+0x000F8000, 0x001D4004, 0x001C3500, 0x002015E0,
+0x0020160C, 0x001C5814, 0x001C59D0, 0x001C5830,
+0x001C6268, 0x001C59A4, 0x001C639C, 0x001C581C,
+0x001C5860, 0x00203AC0, 0x002018A2, 0x8F014411,
+0x6043604B, 0x0009000B, 0x5651D52B, 0x46286052,
+0x306C000B, 0x2FC62FB6, 0x2FE62FD6, 0x4F124F22,
+0xBFF14F02, 0x6B036E43, 0xDD25DC24, 0x0009BFEC,
+0x3C0530B8, 0x4609060A, 0x46014609, 0x020A3D65,
+0x42094209, 0x32E24209, 0x4F068BF0, 0x4F264F16,
+0x6DF66EF6, 0x000B6CF6, 0x2FC66BF6, 0x2FE62FD6,
+0x4F124F22, 0xBFCF4F02, 0x6C036E43, 0xBFCBDD13,
+0x30C80009, 0x060A3D05, 0x46094609, 0x36E24601,
+0x4F068BF5, 0x4F264F16, 0x6DF66EF6, 0x6CF6000B,
+0x4F222FE6, 0xE102DE0B, 0xE403E500, 0xBFB92E12,
+0xE6062E52, 0xE7004618, 0x2E62E403, 0x4F262E72,
+0x6EF6AFB0, 0x0009000B, 0x001C1040, 0xCCCCCCCD,
+0x10624DD3, 0x001D4004, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE5007F98, 0x6453E710,
+0x6B534728, 0xEE1ADCBC, 0x6153655D, 0x315C4108,
+0x75014108, 0x6043317C, 0x0F16665D, 0xED0060B3,
+0x21B136E3, 0x81128111, 0x11D28113, 0x11D411D3,
+0x74048FEA, 0xD8B167F2, 0x1871D9B1, 0x58F12872,
+0x1981D1B0, 0x59F22982, 0x5DF45AF3, 0x54F65EF5,
+0x21921191, 0x11A211A3, 0x11D411D5, 0x11E611E7,
+0x11481149, 0xDAA855F7, 0x57F8EE00, 0x52F9DDA7,
+0x64E3D6A7, 0x2A521A51, 0xD8A7D9A6, 0x2D729AD5,
+0x6EED2622, 0x4D086DE3, 0x3DEC61E3, 0x4D084108,
+0x3D9C31EC, 0x410860B3, 0x81D12DB1, 0x4108E050,
+0x4008E7B7, 0x677C4108, 0x60B381D2, 0xE200318C,
+0x81D33472, 0x1D131DD2, 0x8D01D493, 0xD4901D24,
+0xB0B365D3, 0x64ED7E01, 0x8BDA34A2, 0x2FD2DA8C,
+0xDD9268A2, 0x2D824829, 0x7DFC64A2, 0xD287694D,
+0x6E222D92, 0x7D0C4E29, 0x68222DE2, 0x618D6AD3,
+0x2A16D784, 0xD48A6D72, 0x24D2D583, 0xD6895E72,
+0x517414E2, 0x1414EE00, 0xD1875876, 0x59781486,
+0x1498E710, 0x65E36252, 0x26E2142A, 0xE60064E3,
+0x6843644D, 0x384C4808, 0x381C4808, 0x0C866053,
+0x09CE28B1, 0x819160B3, 0x0ACE6053, 0x81A26043,
+0x0DCE6053, 0x81D360B3, 0x08CE6053, 0x18827401,
+0x624D09CE, 0x0ACE19E3, 0x1A643273, 0x75048FE0,
+0xE003D96A, 0x40186C92, 0x6D922CB1, 0x81D1DA6F,
+0x6E92E050, 0x81E24008, 0x60B36192, 0x64928113,
+0x1442E600, 0xD4696792, 0x689217A3, 0x1864E1FF,
+0x6563E703, 0x364C4608, 0x26127501, 0x3673665D,
+0xDC5B8BF8, 0x6DC2E003, 0x2DB14018, 0xD2606EC2,
+0x61C281E1, 0x1112EE00, 0xE02464C2, 0x65C21423,
+0x15E4D45B, 0xE58067C2, 0x68C28172, 0x818366E3,
+0x666D655C, 0x76046963, 0x394C6A6D, 0x8FF83A53,
+0xDB5429E2, 0x24B2DC54, 0x24C27404, 0x4F267F68,
+0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6, 0x68F6000B,
+0x60116142, 0x8F03C803, 0xD23DE500, 0x8B063420,
+0xC9036011, 0x8B068802, 0x3420D239, 0x56128B03,
+0x52646513, 0x000B2422, 0x01136053, 0x2FE62FD6,
+0x7FEC4F22, 0x62536E53, 0x6D43E550, 0x4508E400,
+0xE101A001, 0x60435224, 0x81212211, 0x60538123,
+0x56E28122, 0x8BF53620, 0x16E4D238, 0xE61464F3,
+0x65E3420B, 0xE4FC65E1, 0x2E512549, 0x65F361F1,
+0x2F112149, 0xD13154D1, 0xE614410B, 0x607157D1,
+0x2701CB01, 0x7F141DE1, 0x6EF64F26, 0x6DF6000B,
+0x2FE62FD6, 0x7FEC4F22, 0x66536E53, 0x6D43E5FC,
+0x20596061, 0x2601CB01, 0x326052E2, 0x12E48B06,
+0x31E051E2, 0x52D18B04, 0x1E22A002, 0x5664AFF0,
+0x64F3D21E, 0x420BE614, 0x67E165E3, 0x2719E1FC,
+0x67F12E71, 0x271954D1, 0x65F3D118, 0x410BE614,
+0x52D12F71, 0xCB016021, 0x1DE12201, 0x4F267F14,
+0x000B6EF6, 0x00006DF6, 0x0020391C, 0x002034EC,
+0x002034F4, 0x002034FC, 0x00203524, 0x00203908,
+0x00203910, 0x00100208, 0x001017C0, 0x001E210C,
+0x001C3D00, 0x0020395C, 0x001000C8, 0x00117880,
+0x00117780, 0x00040020, 0x0026C401, 0x00200ED6,
+0x4F222FE6, 0xDE42624C, 0x42004208, 0x3E2CA005,
+0xD4405252, 0xBF695624, 0x65E22E62, 0x352052E1,
+0xD63D8BF6, 0x4F262622, 0x6EF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xDC394F22, 0x52C1DB39, 0x362066C2,
+0x6061891C, 0x8801C903, 0xDE348918, 0xBF37DD35,
+0x650364E3, 0x66B28503, 0x3262620D, 0xD4328907,
+0x0009BF76, 0x4D0BD431, 0xAFE60009, 0xBF3D0009,
+0xD42F64E3, 0x00094D0B, 0x0009AFDF, 0x2262D22D,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x2FD62FC6,
+0x4F222FE6, 0xDD29DC28, 0x6E4360C2, 0x04DE4008,
+0xE614D127, 0x65E3410B, 0xD127D726, 0x55E227E2,
+0x35E05254, 0x21228F04, 0x400860C2, 0x122202DE,
+0x605365C2, 0x75014008, 0x0DE606DE, 0xC90F6053,
+0x60632C02, 0x6EF64F26, 0x000B6DF6, 0x85436CF6,
+0x650D5643, 0x622D6262, 0x35277204, 0xE1008F0C,
+0x2268960C, 0xD6158B03, 0x72015261, 0xD6131621,
+0x6262E101, 0x26227201, 0x6013000B, 0x000001FF,
+0x002034FC, 0x002034F4, 0x001C3D00, 0x00203524,
+0x002038EC, 0x002018A2, 0x002034EC, 0x00203AE8,
+0x00203AEC, 0x001C3D28, 0x0020395C, 0x0020391C,
+0x00200ED6, 0x00203960, 0x00203964, 0x00117754,
+0x2FC62FB6, 0x2FE62FD6, 0x7FF84F22, 0x6022D237,
+0x8D58C803, 0xDE362F01, 0xDB37DC36, 0x66C252C1,
+0x892F3620, 0xC9036061, 0x892B8801, 0xD233DD31,
+0x64D3420B, 0x1F016503, 0x880160B1, 0xD2308B04,
+0x64D3420B, 0x0009AFEA, 0x85615653, 0x8904C820,
+0xE050D72C, 0x7201027E, 0xD22B0726, 0x6453420B,
+0x89072008, 0x55F1D126, 0x64D3410B, 0xE601D727,
+0x2762AFD4, 0x55F1D226, 0x64E3420B, 0xE601D125,
+0x2162AFCC, 0xDD25DE24, 0xDC26DB25, 0x66D252D1,
+0x89183620, 0xC9036061, 0x89148801, 0xD117D41F,
+0x0009410B, 0x36E05603, 0x65038F04, 0x2B20E201,
+0x2C52AFEC, 0xD712D41C, 0x0009470B, 0xE601D115,
+0xAFE34618, 0x60F12162, 0x8907C804, 0x7F08D217,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6422B, 0x4F267F08,
+0x6DF66EF6, 0x000B6CF6, 0x00006BF6, 0x001E2100,
+0x002034FC, 0x002034F4, 0x00203984, 0x002014A0,
+0x002014CC, 0x0020348C, 0x002016BE, 0x001E212C,
+0x00201530, 0x001C3D30, 0x00117880, 0x002034EC,
+0x0020390C, 0x00203908, 0x00203524, 0x00200610,
+0xE601D203, 0x1265D503, 0x000B2252, 0x00001266,
+0x001C1010, 0x0000C34F, 0x0009000B, 0x2FD62FC6,
+0x4F222FE6, 0x6D436C53, 0xEE00A004, 0x7E0164D4,
+0x644CBFF2, 0x8BF93EC2, 0x6EF64F26, 0x000B6DF6,
+0xE5006CF6, 0x6643A002, 0x76017501, 0x22286260,
+0xAFE38BFA, 0x2FE60009, 0x75076253, 0xE1086753,
+0x6043EE0A, 0x4409C90F, 0x650330E2, 0x8D014409,
+0xE630E637, 0x4110365C, 0x8FF22760, 0xE00077FF,
+0x000B8028, 0x000B6EF6, 0x000BE000, 0x2FE6E000,
+0x7FEC4F22, 0x6E436253, 0xBFDC65F3, 0xBFD06423,
+0xBFCE64E3, 0xD40364F3, 0x0009BFCB, 0x4F267F14,
+0x6EF6000B, 0x00203AF0, 0xE4FDD29D, 0xD79D6122,
+0x22122149, 0x74016022, 0x2202CB01, 0xD59A6622,
+0x22622649, 0xC8406070, 0x60528902, 0x2502CB04,
+0xE6016052, 0x2502CB08, 0xE4026052, 0x2502C9CF,
+0x46186052, 0x2502CB10, 0xCB036052, 0x15422502,
+0x1563000B, 0xD78ED58D, 0xD48FD28E, 0xE600E100,
+0x27112511, 0xAFCF2210, 0x664C2461, 0x4600D28B,
+0x6060362C, 0x000BCB10, 0x654C2600, 0x4500D287,
+0x6650352C, 0x2619E1EF, 0x2560000B, 0xD284664C,
+0x362C4600, 0xCB106060, 0x2600000B, 0xD280654C,
+0x352C4500, 0xE1EF6650, 0x000B2619, 0x664C2560,
+0x4600D27A, 0x6060362C, 0x000BCB08, 0x654C2600,
+0x4500D276, 0x6650352C, 0x2619E1F7, 0x2560000B,
+0xD273664C, 0x362C4600, 0xCB086060, 0x2600000B,
+0xD26F654C, 0x352C4500, 0xE1F76650, 0x000B2619,
+0x624C2560, 0x4200D669, 0x6020326C, 0x4021C908,
+0x40214021, 0x600C000B, 0xD665624C, 0x326C4200,
+0xC9086020, 0x40214021, 0x000B4021, 0xD161600C,
+0x341C644C, 0x000B6240, 0xD15F602C, 0x341C644C,
+0x000B6240, 0x2FE6602C, 0x6E434F22, 0xE60A645C,
+0x89143467, 0x0009BFEB, 0x60EC640C, 0x8B028801,
+0xA002E00F, 0x44092409, 0x624C4409, 0x3263E60A,
+0xBFE28905, 0x620C644C, 0xC8806023, 0xE2008B00,
+0x4F266023, 0x6EF6000B, 0xD64C4F22, 0x88016062,
+0xB2578B03, 0xA0030009, 0xD2490009, 0x2260E640,
+0xE200D648, 0x000B4F26, 0x4F222622, 0x6062D643,
+0x8B018802, 0x0009B2A0, 0xE200D642, 0x000B4F26,
+0xD53E2622, 0xE100D43E, 0x2512E701, 0x2470000B,
+0xE604D23B, 0x2260000B, 0xD43B4F22, 0x410BD13B,
+0xD53B0009, 0x6650E1FD, 0x2619D23A, 0x2560E700,
+0x000B4F26, 0x4F222270, 0xD238D537, 0xD7386152,
+0x2512611D, 0xE6FF6452, 0x2542242B, 0xD22FD435,
+0x420B666D, 0xD52E2762, 0x6750E1FB, 0x4F262719,
+0x2570000B, 0xD4304F22, 0x410BD128, 0xD5280009,
+0x6650E7F7, 0x4F262679, 0x2560000B, 0x9425D524,
+0x22496250, 0x2520000B, 0xE4BFD521, 0x22496250,
+0x2520000B, 0xD2254F22, 0x600D8522, 0x89112008,
+0x89458801, 0x89478803, 0x89498805, 0x894F8806,
+0x89558808, 0x895B8809, 0x8961880A, 0x8967880B,
+0x0009A06E, 0x0009B070, 0x600CA06B, 0x0000FF7F,
+0x001E2148, 0x001E1000, 0x001E1108, 0x002039BC,
+0x002039BE, 0x002039DD, 0x002039A0, 0x001E103F,
+0x001E105F, 0x001E102F, 0x001E1090, 0x002039C4,
+0x001E100B, 0x002039C0, 0x00203AF4, 0x002018A2,
+0x001E1028, 0x002039DC, 0x001D4020, 0x98760000,
+0x001C1000, 0x00203B00, 0x00203B10, 0x00203994,
+0x0009B04C, 0x600CA035, 0x0009B055, 0x600CA031,
+0x6260D684, 0x8B2B2228, 0x0009B061, 0x600CA029,
+0x6260D680, 0x8B232228, 0x0009B069, 0x600CA021,
+0x6260D67C, 0x8B1B2228, 0x0009B0C7, 0x600CA019,
+0x6260D678, 0x8B132228, 0x0009B0CD, 0x600CA011,
+0x6260D674, 0x8B0B2228, 0x0009B125, 0x600CA009,
+0x6260D670, 0x8B032228, 0x0009B13D, 0x600CA001,
+0x4F26E000, 0x0009000B, 0xD26CD16B, 0xD56C8412,
+0x4000C90F, 0xD76B012D, 0xE403D66B, 0xE20F611C,
+0x2540E001, 0x25202712, 0x2602000B, 0xE601D262,
+0x30668523, 0xE0008D05, 0xD663D260, 0xE0018122,
+0x000B2602, 0xD25C0009, 0x600D8523, 0x89052008,
+0x8B0A8801, 0x6060D65D, 0x2600CB01, 0xD457D65A,
+0xE001E101, 0x000B2612, 0x000B8142, 0xD152E000,
+0x8513E501, 0x640D4518, 0x66033453, 0xE0008D05,
+0xD551D253, 0x2260E001, 0x000B2502, 0x4F220009,
+0x8513D149, 0x6453650D, 0x62494419, 0x227D672E,
+0x8801602C, 0x88028909, 0x88038910, 0x8806891A,
+0x88078935, 0xA04C893B, 0xD5460009, 0x6652D746,
+0x2762D446, 0x622C6261, 0x2421A038, 0x2228625C,
+0xD4438B3F, 0x6642D540, 0x2562D440, 0x24018561,
+0x6203A02C, 0x2008605C, 0x88108907, 0x88208908,
+0x88308909, 0xA02C890A, 0xD23A0009, 0x6222A008,
+0xA005D239, 0xD2396222, 0x6222A002, 0x6262D638,
+0xD432D531, 0x66212522, 0xA00F626C, 0xD6352421,
+0x6261D52D, 0x622CD42D, 0xA0072562, 0xD6322421,
+0x8561D529, 0x2562D429, 0x62032401, 0x662D8515,
+0x3617610D, 0x65038F01, 0xB0CB2451, 0xA0010009,
+0xE000E001, 0x000B4F26, 0xD6190009, 0xD427E101,
+0x65412610, 0xD118D717, 0xE20F655D, 0x2752E001,
+0x000B2620, 0x2FE62102, 0xD20F4F22, 0x640C8523,
+0x8B082448, 0xD511D61D, 0x2621E200, 0x940F8451,
+0xA0482049, 0xDE0D8051, 0xC84060E0, 0xE2018D32,
+0x89443427, 0xD216D615, 0x2641420B, 0x0009A030,
+0x0000FF7F, 0x002039DD, 0x00203994, 0x002039A0,
+0x001E1100, 0x001E100C, 0x002039C0, 0x001E1000,
+0x001E1001, 0x002039C8, 0x002039A8, 0x002039AC,
+0x002039B0, 0x002039CC, 0x002039D0, 0x002039D4,
+0x002039D8, 0x00203DFC, 0x00203E06, 0x002039BA,
+0x0020287E, 0x89123427, 0xD294D693, 0x2641420B,
+0xCB8084E1, 0x80E1B0F5, 0xD69160E0, 0x2E00CB04,
+0xC93F6060, 0xD68F2600, 0xA001E001, 0xE0002602,
+0x000B4F26, 0xD68C6EF6, 0xC8806060, 0xD2868919,
+0x88016021, 0xD2898B15, 0x8524E501, 0x89103056,
+0xE203D187, 0x2120D487, 0xE00B6541, 0x0656655D,
+0xE40FD585, 0x2140E702, 0xD77E2571, 0x000BE001,
+0x000B2702, 0x2FE6E000, 0xDE804F22, 0xC88084E1,
+0xD57A892C, 0x20088554, 0x61038F28, 0x8553D77C,
+0x64036672, 0x8566650C, 0x3520620C, 0xD6798B1E,
+0x651CD774, 0x2651644C, 0x60E02741, 0x8904C840,
+0x420BD275, 0xA0030009, 0xD2680009, 0x0009420B,
+0x0009B09F, 0xE201D167, 0x60E02122, 0xCB04D464,
+0x60402E00, 0x2400C93F, 0x6023A001, 0x4F26E000,
+0x6EF6000B, 0x2FB62FA6, 0x2FD62FC6, 0xDA622FE6,
+0x66A1E240, 0x3622DC5E, 0x62638900, 0x6ED36D2C,
+0x4E2136D8, 0x4E212A61, 0xDB61D460, 0xE700A00F,
+0x770162B2, 0x71026123, 0x66212B12, 0x71026213,
+0x61212B12, 0x651D666D, 0x356C4528, 0x627C2452,
+0x8BED32E3, 0xC90360D3, 0x8B108803, 0x617367B2,
+0x2B127102, 0x71026E13, 0x2B126571, 0x655D6DE1,
+0x422862DD, 0x325CE107, 0xA00C2C10, 0x88022422,
+0xA0038B01, 0x8801E203, 0xE2018B05, 0x66B22C20,
+0x655D6561, 0xE60F2452, 0x67A12C60, 0x8B052778,
+0xDD38DC44, 0xEB01EA00, 0x2DB22CA2, 0x6DF66EF6,
+0x6BF66CF6, 0x6AF6000B, 0x2FE62FD6, 0xE240DD36,
+0x362266D1, 0x62638900, 0x3678672C, 0x7703DE38,
+0x47212D61, 0x64E2D635, 0xA00E4721, 0x6562E100,
+0x62537101, 0x74012450, 0x24204219, 0x45297401,
+0x74012450, 0x24504519, 0x621C7401, 0x8BEE3273,
+0x66E24200, 0x420061D1, 0x2118362C, 0x2E628F06,
+0xDD1CD728, 0xE501E400, 0x2D522742, 0x000B6EF6,
+0x2FD66DF6, 0x4F222FE6, 0xED0AEE01, 0x64E3BC85,
+0xBC8A64E3, 0x62EC7E01, 0x8BF732D7, 0xBC8DEE01,
+0x64E364E3, 0x7E01BC92, 0x32D762EC, 0x4F268BF7,
+0x000B6EF6, 0xD1186DF6, 0xD418920D, 0x72122122,
+0x2422D617, 0xD7177204, 0x72202622, 0x2722D116,
+0x000B7230, 0x137A2122, 0x002039BA, 0x0020298A,
+0x001E1015, 0x002039C0, 0x001E1001, 0x00203994,
+0x001E1100, 0x002039BE, 0x002039AC, 0x001E1000,
+0x002039B0, 0x002039BC, 0x0020287E, 0x001E100C,
+0x002039A8, 0x002039C4, 0x002039C8, 0x002039CC,
+0x002039D0, 0x002039D4, 0x002039D8, 0x4F222FE6,
+0xD6707FFC, 0x88016060, 0xE2018951, 0x2620BFBB,
+0xD56ED16D, 0xDE6E6010, 0x64E36552, 0x7402C840,
+0x8D22D16C, 0xD26C7502, 0xE601D76C, 0xE7042722,
+0x76016255, 0x626C2421, 0x8FF93273, 0xD4637402,
+0x6242E601, 0x640D8528, 0x67494419, 0x275D657E,
+0x81E4607C, 0xE417D562, 0x67557601, 0x3243626C,
+0x8FF92171, 0xA0207102, 0xD25E0009, 0xE601D75B,
+0xE7042722, 0x76016255, 0x626C2421, 0x8FF93273,
+0xD4527402, 0x6242E601, 0x640D8528, 0x67494419,
+0x275D657E, 0x81E4607C, 0xE417D553, 0x67557601,
+0x3243626C, 0x8FF92171, 0x92897102, 0xD2462E21,
+0x5E23D74E, 0x64F22FE2, 0x604365F2, 0x2700C980,
+0xC9606043, 0x80716103, 0xC9036043, 0x80724519,
+0x65F2605C, 0x817266F2, 0x46194629, 0x606C4529,
+0x4018645C, 0x8173304C, 0x21185E23, 0x64F22FE2,
+0x6E4C62F2, 0x602C4219, 0x66F262F2, 0x46294018,
+0x461930EC, 0x42298174, 0x652C606C, 0x305C4018,
+0x81758F07, 0x0009BC96, 0x2228620C, 0xA00A8908,
+0x60130009, 0x8B038840, 0x0009B009, 0x0009A003,
+0xE202D62F, 0x7F042622, 0x000B4F26, 0x4F226EF6,
+0x8552D52A, 0x8830600D, 0x88318903, 0xA0348923,
+0x85550009, 0xD428D727, 0x85532701, 0x610DD627,
+0x24124118, 0x460BD426, 0xD7230009, 0xD226D425,
+0x6572420B, 0xE230D120, 0x42286712, 0x2729E620,
+0x37604628, 0xD6218B03, 0xA016E200, 0xD61F2622,
+0xA012E202, 0xD1182622, 0x6212E530, 0xE6204528,
+0x46282259, 0x89083260, 0xD41AD119, 0xE601D513,
+0x2160450B, 0x472BD718, 0x4F264F26, 0x0009000B,
+0x0000060A, 0x002039DC, 0x001E1000, 0x002039C8,
+0x00203DFC, 0x00203E08, 0x00203DA0, 0x002039B0,
+0x00203DD0, 0x00203DCE, 0x00203DA2, 0x00203994,
+0x002039C0, 0x002039AC, 0x002039A8, 0x002018A2,
+0x00203B1C, 0x00203B20, 0x002018EE, 0x002039C4,
+0x001E100B, 0x00203B34, 0x00114004, 0x4F222FE6,
+0xDE967FFC, 0x200884E9, 0x2F008D06, 0xD695D494,
+0x0009460B, 0x64F0B19A, 0x6620D293, 0x89022668,
+0xC9BF60E0, 0x7F042E00, 0x000B4F26, 0x000B6EF6,
+0x2FE60009, 0xDE8D4F22, 0x60E0D68D, 0xCBC0D48D,
+0x62602E00, 0xC803602C, 0x40218904, 0x70014021,
+0x6603A002, 0x66034009, 0xD687616D, 0xE500A004,
+0x75016262, 0x74042422, 0x3213625D, 0xD2838BF8,
+0x0009420B, 0xC9BF84E2, 0x4F2680E2, 0x6EF6000B,
+0x2FE62FD6, 0x7FFC4F22, 0x6260D67D, 0x89442228,
+0xD572E100, 0x60502610, 0xCB40D47A, 0x2500440B,
+0x8D052008, 0x62E06E03, 0x7104612C, 0x2F11A006,
+0xD475D66D, 0xDD756760, 0x657C4D0B, 0xE23C6D1D,
+0x8B033D27, 0xD267D472, 0x0009420B, 0x4D214D21,
+0xA005D770, 0x66E6E400, 0x357C4508, 0x74012562,
+0x35D3654D, 0xD76C8BF7, 0x6172E003, 0x81114018,
+0x6E7260F1, 0x81E2700C, 0xD4686172, 0xDD688113,
+0x4D0BDE68, 0xE2016572, 0xD4672E22, 0x420BD255,
+0xD6560009, 0xC93F6060, 0x7F042600, 0x6EF64F26,
+0x6DF6000B, 0x2FC62FB6, 0x2FE62FD6, 0xD25F4F22,
+0x6B436E73, 0x420B6C53, 0x20086D63, 0x64038D1C,
+0xE50ED149, 0x32526210, 0x60C38916, 0x804124B0,
+0x814160D3, 0xA007E500, 0x655D61BC, 0x00EC6053,
+0x364C6653, 0x80647501, 0x3213625D, 0xD63B8BF5,
+0xC9BF6060, 0x2600A008, 0xD23AD44D, 0x6EF64F26,
+0x6CF66DF6, 0x6BF6422B, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6000B, 0x7FC44F22, 0x720262F3, 0x22512F41,
+0x45297202, 0x60632251, 0xE5C4E682, 0x67F38121,
+0x655C666C, 0xE408BFB6, 0x4F267F3C, 0x0009000B,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xE1007FC4, 0x6513ECFF, 0x6B136CCD, 0xDE36D735,
+0xEDFF64F3, 0xD835EA04, 0x6053655C, 0x027D4000,
+0x32C0622D, 0x66038D0D, 0x09ED6063, 0x2491027D,
+0x24217402, 0x698202ED, 0x3928622D, 0x74022892,
+0x75017104, 0x6063625C, 0x07D532A2, 0x0EB58FE4,
+0x2448641C, 0xE6808905, 0x67F3E5C5, 0xBF79666C,
+0x7F3C655C, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0xD11E68F6, 0x6012D21E, 0xCB20E405,
+0x2102E500, 0x000B2242, 0x00002252, 0x001E1017,
+0x00203B38, 0x002018A2, 0x00203906, 0x001E1015,
+0x001E10BF, 0x00117800, 0x001E10FC, 0x00200610,
+0x0020390C, 0x00202AE2, 0x00203B3C, 0x002018EE,
+0x00203B58, 0x0011788C, 0x00203908, 0x002034EC,
+0x00201530, 0x001E2130, 0x00203B60, 0x00202AA4,
+0x00203B64, 0x0020396C, 0x00203974, 0x00203D9C,
+0x001C3500, 0x001D4004, 0xD564D163, 0xE400D764,
+0x2142E20F, 0x17411154, 0xD5622722, 0x9669D762,
+0x15412572, 0x96661562, 0xE6011565, 0xD55F1165,
+0x666CE6F8, 0x25422542, 0x25422542, 0x25422542,
+0x25622542, 0x7601E727, 0x67632572, 0x25627797,
+0xE7042572, 0x2572E248, 0xE2192522, 0xE2702522,
+0x25422542, 0x25422542, 0x25222542, 0x2522E20C,
+0x25422542, 0x25422542, 0x25422542, 0x25422542,
+0x000B154A, 0xE2081145, 0x0009422B, 0x2FE62FD6,
+0x7FFC4F22, 0xC8206043, 0x6E438D02, 0x0009BE67,
+0xC81060E3, 0xBE648901, 0x60E30009, 0x8901C840,
+0x0009BE86, 0xC80160E3, 0xDD3D8938, 0xC80260D0,
+0x2F008D03, 0x460BD63B, 0x60F00009, 0x8902C804,
+0x460BD639, 0x62F00009, 0xC8806023, 0x60D08902,
+0x2D00C97F, 0xC8016023, 0xD6348906, 0x0009460B,
+0x0009A007, 0x51630601, 0x8902C808, 0x460BD630,
+0x60F00009, 0x8902C810, 0x420BD22E, 0xD52E0009,
+0x88026052, 0xD22D8B03, 0xA005E604, 0x88012260,
+0xD22A8B02, 0x2260E601, 0x2522E200, 0xC88060E3,
+0xD227892D, 0x60E36E20, 0x8902C880, 0x420BD225,
+0x60E30009, 0x8902C840, 0x420BD223, 0x60E30009,
+0x8902C802, 0x420BD221, 0x60E30009, 0x890DC804,
+0xDD20D11F, 0x0009410B, 0x0009BF0D, 0x0009BF4C,
+0xD51ED41D, 0x2470E708, 0x25D2BF85, 0xC80860E3,
+0xD21B8905, 0x4F267F04, 0x422B6EF6, 0x7F046DF6,
+0x6EF64F26, 0x6DF6000B, 0x001C581C, 0xA000A000,
+0x001D0100, 0x001D4000, 0x00040021, 0x001C589C,
+0x001E1021, 0x00201A88, 0x00201AAA, 0x0020210C,
+0x00201AC2, 0x00201AD0, 0x002039C0, 0x001E100B,
+0x001E1028, 0x00201B3C, 0x00201B48, 0x00201AD8,
+0x00201AF6, 0x12345678, 0x001E1000, 0x0010F100,
+0x00201B24, 0x644CD6A7, 0x000B346C, 0xD6A62450,
+0x346C644C, 0x2450000B, 0x644CD6A4, 0x000B346C,
+0x625C2450, 0x4208616D, 0x42084119, 0x42006019,
+0x670E614C, 0xD49E321C, 0x4200207D, 0x324CC90F,
+0x2200000B, 0x4208625C, 0x42004208, 0x324C644C,
+0x4200D498, 0x000B324C, 0x2FE62260, 0x614C4F12,
+0x4100D493, 0x6710314C, 0xE29F666D, 0x27294619,
+0x6E536269, 0x672E6573, 0x4221227D, 0x42214221,
+0x7601662C, 0xE4014608, 0x34E84608, 0x644C4600,
+0x071A0467, 0x2150257B, 0x000B4F16, 0x4F226EF6,
+0xD2857FE8, 0x88016021, 0xD2848B7B, 0x26686621,
+0xD2838B77, 0x26686621, 0xE50F8B73, 0xE401BFA2,
+0xBFA4E501, 0xE586E400, 0xE400655C, 0x2F50BFA4,
+0xBFA1E401, 0xE602E506, 0x60634618, 0x81F2E401,
+0x6543BF9F, 0xE40185F2, 0xBFAB6543, 0x85F26603,
+0x6543E401, 0x6603BFB1, 0xE40265F0, 0x6053756C,
+0x80F8BF80, 0xBF82E402, 0x84F8E512, 0x7090E402,
+0x6503BF82, 0x4618E602, 0x81F66063, 0xBF80E402,
+0x85F6E500, 0x6603E402, 0xE500BF8C, 0xE40285F6,
+0xBF926603, 0xE5FEE500, 0xE010655C, 0xBF61E403,
+0xE5130F54, 0xE40EBF63, 0x05FCE010, 0xBF63E40E,
+0xE5007585, 0xBF64E403, 0xE500E640, 0xBF71E403,
+0xE500E640, 0xBF78E403, 0xE5FFE640, 0xE014655C,
+0xBF47E404, 0xE40F0F54, 0xE504BF49, 0x05FCE014,
+0xBF49E40F, 0xE5017584, 0xBF4AE640, 0xE501E404,
+0xBF57E640, 0xE501E404, 0xE404E640, 0xAF5C7F18,
+0x7F184F26, 0x000B4F26, 0x4F220009, 0xD2427FF0,
+0x88016021, 0xD2418B71, 0x26686621, 0xD2408B6D,
+0x26686621, 0xE50F8B69, 0xE401BF1C, 0xBF1EE501,
+0xE586E400, 0xE400655C, 0x2F50BF1E, 0xBF1BE401,
+0xE401E506, 0xBF1C6543, 0xE401E640, 0xBF296543,
+0xE401E640, 0xBF306543, 0x65F0E640, 0x756CE402,
+0xBEFF6053, 0xE40280F4, 0xE512BF01, 0xE40284F4,
+0xBF017090, 0xE6406503, 0xBF02E402, 0xE640E500,
+0xBF0FE402, 0xE640E500, 0xBF16E402, 0xE5FEE500,
+0x6053655C, 0xBEE5E403, 0xE51380F8, 0xE40EBEE7,
+0xE40E84F8, 0xBEE77085, 0xE5006503, 0xBEE8E640,
+0xE500E403, 0xBEF5E640, 0xE500E403, 0xBEFCE640,
+0xE5FFE403, 0x6053655C, 0xBECBE404, 0xE40F80FC,
+0xE504BECD, 0xE40F84FC, 0xBECD7083, 0xE5016503,
+0xBECEE640, 0xE501E404, 0xBEDBE640, 0xE501E404,
+0xE404E640, 0xAEE07F10, 0x7F104F26, 0x000B4F26,
+0x00000009, 0x001E102F, 0x001E1080, 0x001E1090,
+0x001E103F, 0x001E103E, 0x002039BA, 0x002039BC,
+0x002039BE, 0xD21DD11C, 0x66206010, 0x676C7001,
+0x3700C90F, 0xE5008D13, 0x67106210, 0x7701622C,
+0x64232170, 0xD6166010, 0x44084408, 0x3428C90F,
+0x62602100, 0x7201D513, 0x44082620, 0x000B354C,
+0xD10F6053, 0x25586510, 0xE6008D13, 0xD60DD40B,
+0x655C6540, 0x47086753, 0x37584708, 0x47086540,
+0x24507501, 0x367C6040, 0x2400C90F, 0x72FF6210,
+0x000B2120, 0x00006063, 0x00203905, 0x00203904,
+0x00203906, 0x0020352C, 0x7FFC4F22, 0xE680D19F,
+0x666C6212, 0xD29E2F22, 0x67F36563, 0x420B7542,
+0x7F04E404, 0x000B4F26, 0xE6800009, 0xD298666C,
+0xE7006563, 0x422B7540, 0xE6806473, 0xD294666C,
+0xE7006563, 0x422B7543, 0x2F866473, 0x2FA62F96,
+0x2FC62FB6, 0x2FE62FD6, 0x7FCC4F22, 0xDC8ED28D,
+0x72011F21, 0xDB8D1F22, 0xD18EDE8D, 0x66125211,
+0x8B013620, 0x0009A0E5, 0xC9036061, 0x8B018801,
+0x0009A0DF, 0xD288D487, 0xED84420B, 0x2F025503,
+0x30D0845C, 0xA0B88901, 0xD1840009, 0x626C6610,
+0x88016023, 0xD1828B68, 0x62101FC3, 0x895B2228,
+0xE003D480, 0x40186742, 0x68421772, 0xD57EE900,
+0x81816DB3, 0x7D042190, 0x67D26AB2, 0x64E26852,
+0x1F491F57, 0x740464E3, 0x1FA46542, 0x65431F5A,
+0x625275F8, 0x1F761FD5, 0x6D531F2B, 0xDA74D773,
+0x7D94D274, 0x68D21F88, 0x6AA26972, 0xD1726022,
+0x2202CB20, 0xE1401F1C, 0x7601E600, 0x3213626D,
+0x56F48BFB, 0x52F651F5, 0x21222B62, 0x52F851F7,
+0x212256F9, 0x2E6251FA, 0x51FB2412, 0x2D822512,
+0xD9662792, 0x29A2DD5F, 0x6AD2D965, 0xD9646892,
+0x68D21A84, 0x6081DA63, 0x2801CB01, 0xD86266D2,
+0x2A622962, 0xED015AFC, 0x2AD2480B, 0x2AD24D18,
+0x62D2DD5E, 0x2D227201, 0xD15056F3, 0xE2026062,
+0x2602CB01, 0x2120A03D, 0x8B3A2228, 0xE401DD58,
+0x2140E600, 0xE01C2D62, 0xC801005C, 0xD4558B0A,
+0xE600D755, 0xED7D2472, 0x626C7601, 0x8BFB32D3,
+0x24D2DD52, 0xE2FE68C2, 0x2C822829, 0x095CE01E,
+0xE01F5DF1, 0x0A5C2D90, 0x751051F2, 0xED0621A0,
+0xD74BE600, 0x8456D44B, 0x27007601, 0x696C6854,
+0x248039D3, 0x8FF67401, 0xDA477701, 0x2A10E194,
+0xE2007A01, 0x7A0F2A20, 0xD130E805, 0x66102A80,
+0x6023626C, 0x89088801, 0xD240D42A, 0x420B65F2,
+0xD131ED01, 0xAF304D18, 0x65F221D2, 0x8553D43C,
+0x620D6642, 0x89073262, 0xD13BD43A, 0x0009410B,
+0xE601D73A, 0x2762AF1A, 0xD134D41E, 0x410B65F2,
+0xD125ED01, 0xD637D436, 0x460B4D18, 0xAF0D21D2,
+0x7F340009, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0x4F2268F6, 0x85467FF4, 0x2F01E681,
+0x666C8547, 0x854881F1, 0x81F2D209, 0x67F38542,
+0x854381F3, 0x81F4E40C, 0x65636053, 0x420B81F5,
+0x7F0C7540, 0x000B4F26, 0x00000009, 0x001C3D9C,
+0x00202454, 0x0011779A, 0x001C36F8, 0x001C3B9C,
+0x001C3704, 0x00203524, 0x002014A0, 0x00203915,
+0x00203914, 0x00203910, 0x001C3D98, 0x001C3BB4,
+0x001C5960, 0x001C3500, 0x001C3D30, 0x001C8960,
+0x002034FC, 0x001C3D00, 0x0020160C, 0x00117730,
+0x00203918, 0x001C582C, 0x2000A000, 0x0000A000,
+0x0011778C, 0x00117792, 0x00117788, 0x002014CC,
+0x002038EC, 0x002034EC, 0x00201530, 0x001E2130,
+0x00203D7C, 0x002018A2, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xD19B7FEC, 0x2F12E000,
+0x6103D49A, 0x1F4281F2, 0xDD9ADA99, 0xD69A6813,
+0xE0014808, 0x460BDE99, 0x38EC4800, 0x65A21F03,
+0x352052A1, 0xA23E8B01, 0x60510009, 0x8801C903,
+0xA2388B01, 0x52530009, 0x32E0DE91, 0xD9918B10,
+0x64A3490B, 0x4B0BDB90, 0xDE906403, 0xD791D690,
+0xEC01D591, 0x2E02E100, 0x271026C0, 0x2502AFDF,
+0xC8018551, 0xA1578B01, 0x62510009, 0x4200622D,
+0x5E53366A, 0x85E2226D, 0xC903642C, 0x85E36603,
+0x6053650D, 0x40214021, 0x4500C93F, 0x322A6703,
+0x6053252D, 0xC901D17F, 0x60106C03, 0x8801D97F,
+0xDB7F8B05, 0x2120E200, 0xCB0160B2, 0xD17D2B02,
+0x88016011, 0x65A28B0A, 0x8D042448, 0x9B9E6251,
+0xA00322B9, 0x919B2521, 0x2521221B, 0x37B3EB10,
+0x2448895E, 0xD4738B07, 0x22286241, 0x60638903,
+0xA05781F8, 0xD5706473, 0x46084608, 0x85E26273,
+0x46006B50, 0x362C4200, 0x2BB8C910, 0x8F1F6463,
+0x26686603, 0xD2698911, 0x062D6043, 0x4119616D,
+0x6B0E6019, 0x81F820BD, 0x880160C3, 0x646C8F2C,
+0x880F6073, 0xA0278B1B, 0xD2610009, 0x052D6043,
+0x4119615D, 0x670E6019, 0x645C207D, 0x81F8A01C,
+0x890F2668, 0x6043D25B, 0x6B5D052D, 0x60B94B19,
+0x201D610E, 0x60C381F8, 0x8F0D8801, 0x6473645C,
+0xEC00A00A, 0x6043D254, 0x625D052D, 0x60294219,
+0x207D670E, 0x81F8645C, 0x880285F8, 0x85E1890A,
+0x8D07C820, 0xE6DC6203, 0x60232269, 0x81E1A002,
+0x644CE4FF, 0x6210D149, 0x89012228, 0x644CE4FF,
+0x654DEBFF, 0x35B06BBC, 0xDB368B2B, 0x64A34B0B,
+0x410BD135, 0x54036403, 0x85446E03, 0xC948DB40,
+0xDC408808, 0xBEAE8B01, 0x64B3E502, 0x65E34C0B,
+0xDB3DEC01, 0xD13D2DC2, 0x621260B2, 0x72017001,
+0x21228805, 0x2B028F08, 0x666CE680, 0x6563D238,
+0x7549E700, 0x6473420B, 0xA030D436, 0x7FFF0009,
+0x85E28000, 0x20B9EBFC, 0x610381E2, 0x942A85E3,
+0x62032049, 0x450885F8, 0x81E2201B, 0xC90160C3,
+0x40084018, 0x40084008, 0x4000225B, 0x6023220B,
+0x85E481E3, 0x4118E108, 0x81E4201B, 0xE40262A2,
+0x20B98521, 0x67A28121, 0xCB016071, 0x85F82701,
+0x89033042, 0xECE785E2, 0x81E220C9, 0x490BD41E,
+0xA03B0009, 0x7E030009, 0x001C3D30, 0x00203D88,
+0x002034FC, 0x001E212C, 0x002033E0, 0x001C3D00,
+0x00117780, 0x002014A0, 0x0020166C, 0x0011770C,
+0x00203914, 0x00203915, 0x00203910, 0x002018A2,
+0x001C36F8, 0x00203988, 0x00203D98, 0x00203B7C,
+0x00203BFC, 0x00203C7C, 0x00203CFC, 0x00203900,
+0x002034F4, 0x002014CC, 0x0020398C, 0x00203990,
+0x00202454, 0x00203D80, 0x00203D84, 0x602262F2,
+0x40094019, 0xC90F4009, 0x8B0B880A, 0x60E2DE8C,
+0x40094019, 0xC90F4009, 0x8B038808, 0xCB0160A2,
+0x2802A006, 0x65E2DE87, 0x2E527501, 0x286266A2,
+0x52F366F2, 0x2622AE83, 0xD2838551, 0xDE83C802,
+0xA0958B01, 0x420B0009, 0x4E0B64A3, 0x5E036403,
+0x85E46503, 0x4918E908, 0xD77D209B, 0xE04C81E4,
+0xDC7C0B7E, 0x7B01D97C, 0x61C207B6, 0x71016690,
+0x8D062668, 0xD4792C12, 0x420BD279, 0xA070EB01,
+0x62512DB2, 0x4B18EB0F, 0x22B9E102, 0x32104118,
+0x85518B0F, 0x2029E2FC, 0x60518151, 0xCB0172E0,
+0x85E12501, 0x202994A3, 0x85E481E1, 0xA0522049,
+0x675181E4, 0x4719677D, 0x667E6779, 0x7701276D,
+0x6903607C, 0x88014918, 0x25918F3E, 0x6B12D161,
+0x21B27B01, 0x660D85E3, 0x40216063, 0xC93F4021,
+0x6C034600, 0x262D322A, 0xC8016063, 0xDB5ED15D,
+0x967D8901, 0xE6002C6B, 0x666C67CD, 0x40006063,
+0x622D021D, 0x8D0E3270, 0x60436403, 0xE9FF021D,
+0x8B013290, 0x01C5A007, 0x626C7601, 0x3292E904,
+0x646C8BEB, 0x60434400, 0xD15004BD, 0x0B457401,
+0x669D6911, 0x89073670, 0x602D6211, 0x890388FF,
+0xE201DB4B, 0x2B2021C1, 0xECFC8551, 0x815120C9,
+0xCB016051, 0xDC472501, 0x64A34C0B, 0x51F366F2,
+0x85EF2612, 0x54F2D244, 0x650D420B, 0x0009ADE7,
+0xE500DC42, 0x420B2C52, 0x4E0B64A3, 0x54036403,
+0x85446E03, 0x6703E908, 0x65034918, 0x27998541,
+0xDB323790, 0x8F0BD932, 0x6013610D, 0x8B07C820,
+0xC9486053, 0x8B038808, 0xE501BD4D, 0x0009A005,
+0x2128D233, 0xBD468901, 0x64B3E500, 0x490B65E3,
+0xADBCEC01, 0x85F22DC2, 0x7001EE04, 0x31E7610D,
+0x8D0281F2, 0xADA97A08, 0x7F140009, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0xF7FF68F6,
+0x2FE68000, 0xD2234F22, 0x60E36E22, 0x8D02C840,
+0xBBF922E2, 0xE2400009, 0x2E284218, 0xBC048901,
+0x60E30009, 0x8905C810, 0xD21CD41B, 0x0009420B,
+0x0009BC03, 0xC80560E3, 0xBD6D8901, 0x60E30009,
+0x8902C802, 0xAC004F26, 0x4F266EF6, 0x6EF6000B,
+0x001C3D3C, 0x00117760, 0x002014A0, 0x0020166C,
+0x0020348C, 0x00203D9C, 0x00203900, 0x002034F4,
+0x002014CC, 0x0020396C, 0x00203974, 0x00203968,
+0x0020396A, 0x00201530, 0x002018EE, 0x0020398C,
+0x00008000, 0x001C3510, 0x00203D90, 0x002018A2,
+0x080A0C0E, 0x00020406, 0x1A1C1E20, 0x12141618,
+0x2E303234, 0x26282A2C, 0x3A3C3E40, 0x6C625648,
+0x41112F26, 0xE2208F18, 0x890B3123, 0x321CD204,
+0xD1026220, 0x412B312C, 0x00090009, 0x0020340A,
+0x002033C0, 0x000BE000, 0x400062F6, 0x40004000,
+0x40004000, 0x40004000, 0x62F6000B, 0x40004000,
+0x40004000, 0x40004000, 0x40184000, 0x62F6000B,
+0x40004000, 0x40004000, 0x40004000, 0x40284000,
+0x62F6000B, 0x40004000, 0x40184000, 0x000B4028,
+0xC90F62F6, 0x40054005, 0x40054005, 0x62F6000B,
+0x4005C907, 0x40054005, 0x62F6000B, 0x4005C903,
+0x000B4005, 0xC90162F6, 0x000B4005, 0x000062F6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x544F0D0A,
+0x46205355, 0x00003A57, 0x206C754A, 0x32203120,
+0x20383030, 0x323A3132, 0x32313A37, 0x00000000,
+0x00000D0A, 0x00000043, 0x42707372, 0x3D206675,
+0x554E203D, 0x202C4C4C, 0x6E49677A, 0x4E497274,
+0x6D754E51, 0x0000003D, 0x61766E49, 0x2064696C,
+0x72657375, 0x20726F20, 0x2079656B, 0x00214449,
+0x52504545, 0x57204D4F, 0x65746972, 0x6461202C,
+0x003D7264, 0x6C617620, 0x0000003D, 0x00000A0D,
+0x435F4D5A, 0x465F444D, 0x4C445F57, 0x494E495F,
+0x00000054, 0x6E6B6E55, 0x206E776F, 0x6D6D6F63,
+0x3D646E61, 0x00000000, 0x203A3051, 0x00000020,
+0x203A3151, 0x00000020, 0x203A3251, 0x00000020,
+0x203A3351, 0x00000020, 0x203A3451, 0x00000020,
+0x2B434741, 0x73696F4E, 0x61432065, 0x7262696C,
+0x6F697461, 0x6166206E, 0x6F206C69, 0x6974206E,
+0x0D0A656D, 0x00000000, 0x00000072, 0x00205220,
+0x00000D0A, 0x62735576, 0x7473725F, 0x00000A0D,
+0x62735576, 0x7375735F, 0x646E6570, 0x00000A0D,
+0x62735576, 0x7365725F, 0x000A0D6D, 0x00000044,
+0x44387570, 0x72637365, 0x6F747069, 0x3D584572,
+0x00000000, 0x00000047, 0x00000042, 0x72746E49,
+0x6D652051, 0x2C797470, 0x49677A20, 0x4972746E,
+0x754E514E, 0x00003D6D, 0x654C7245, 0x0000006E,
+0x00000049, 0x20746F4E, 0x756F6E65, 0x49206867,
+0x4220514E, 0x0A0D6675, 0x00000000, 0x000000FF,
+0x00020001, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x010E010D,
+0x00020003, 0x01090108, 0x0002010A, 0x02000003,
+0x02020201, 0x02040203, 0x02060205, 0x02020200,
+0x02040203, 0x020C020B, 0x020E020D, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x000000FF,
+0x00020001, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x010E010D,
+0x00020003, 0x01090108, 0x0002010A, 0x00030003,
+0x02020201, 0x02040203, 0x02060205, 0x02020200,
+0x02040203, 0x020C020B, 0x020E020D, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x010E010D,
+0x00FF010F, 0x01090108, 0x010B010A, 0x0200010F,
+0x02020201, 0x02040203, 0x02060205, 0x02020200,
+0x02040203, 0x020C020B, 0x020E020D, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x010E010D,
+0x00FF010F, 0x01090108, 0x010B010A, 0x010F010F,
+0x02020201, 0x02040203, 0x02060205, 0x02020200,
+0x02040203, 0x020C020B, 0x020E020D, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00205220,
+0x00000046, 0x00000059, 0x73204142, 0x003D7165,
+0x49544120, 0x0000204D, 0x00000000, 0x00000000,
+0x002E0209, 0x80000101, 0x000409FA, 0x00FF0400,
+0x05070000, 0x02000201, 0x82050700, 0x00020002,
+0x03830507, 0x07010040, 0x40030405, 0x02090100,
+0x0101002E, 0x09FA8000, 0x04000004, 0x000000FF,
+0x02010507, 0x07000040, 0x40028205, 0x05070000,
+0x00400383, 0x04050701, 0x00004002, 0x00000000,
+0x00000000, 0x07090000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, };
+
+const u32_t zcFwImageSize=15928;
diff --git a/drivers/staging/otus/hal/hpfwu_BA.c b/drivers/staging/otus/hal/hpfwu_BA.c
new file mode 100644
index 000000000000..0c741571f2b5
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwu_BA.c
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE917FFC, 0xE114D791,
+0x1E13D491, 0x1E4C470B, 0x0009B017, 0x95C2E600,
+0xC84060E2, 0x2F028F03, 0x8FF93652, 0xD48B7601,
+0x4E0BDE8B, 0xD48B0009, 0x00094E0B, 0x4E0BD48A,
+0x7F040009, 0xA0474F26, 0x4F226EF6, 0x410BD187,
+0xD4870009, 0x0009440B, 0x450BD586, 0xD7860009,
+0x611DE1FF, 0xD1852712, 0x6012E2FF, 0xCB01D484,
+0x71DC2102, 0x71042122, 0x2122E501, 0xD5812452,
+0xD2819792, 0xE7002572, 0xD481D180, 0x2270D681,
+0x2172E201, 0x26202470, 0xE4FFD67F, 0xE6002641,
+0xE104D57E, 0x6063666D, 0x626D7601, 0x32124000,
+0x05458FF8, 0xE501D27A, 0xD17A2250, 0xD57BD47A,
+0xE700E600, 0x25722470, 0x11622162, 0x11691166,
+0x4F26116A, 0x116E000B, 0xD1757FC4, 0x2F12D875,
+0xD476D175, 0xD577D676, 0x1F87D777, 0xD97778FC,
+0x1F1BD277, 0x1F417104, 0x1F647404, 0x1F887604,
+0x71F41F1C, 0x1F42E8C8, 0x1F651F53, 0x1F991F76,
+0x1F1D1F2A, 0xDD6F688C, 0xDA70DE6F, 0xDC71DB70,
+0x00094A0B, 0x00094B0B, 0x00094C0B, 0x6010D15E,
+0x8B0F8801, 0xE950D15D, 0x49186212, 0x8B073296,
+0x56FAD159, 0x2120E200, 0xCB016062, 0x2602A002,
+0x21227201, 0x880160D2, 0xD1638907, 0x32866212,
+0xD1628903, 0x88016010, 0x64E28BDA, 0x52F751F8,
+0x55E12142, 0x2252D15E, 0x661254FB, 0x246259FC,
+0x29725711, 0x880160D2, 0x66E28B53, 0x362052E1,
+0x6061894C, 0x8801C90F, 0xD1568B48, 0x36206212,
+0xA0438903, 0x27102162, 0xD5530FA0, 0x6651E710,
+0x626D7601, 0x8F3C3273, 0x65F22561, 0x695251F2,
+0x54F359F1, 0x679252F4, 0x61426512, 0x56F66922,
+0x642252F5, 0xCB206062, 0xE6002602, 0x76011F1E,
+0x626DE110, 0x32134118, 0x51FE8FF8, 0x267256F1,
+0x56F457F2, 0x55F32752, 0x251257F5, 0x27422692,
+0x51F969E2, 0x2192D43D, 0xE90161F2, 0x2192440B,
+0x491865F2, 0xD9382592, 0xE200D539, 0x62512921,
+0x720154FD, 0x622D2521, 0x2422A003, 0xE200D932,
+0xE9012921, 0x2D92D12C, 0x26686612, 0xAF6F8B01,
+0xD6300009, 0x0009460B, 0xE700D128, 0x2170AF68,
+0x001C001C, 0x00200F7C, 0x0000B38E, 0x0020322C,
+0x0020145E, 0x00203238, 0x00203250, 0x0020141C,
+0x0020151C, 0x00200FA0, 0x001C3510, 0x001C3648,
+0x001E212C, 0x00203188, 0x00202D24, 0x00203190,
+0x0020319C, 0x002031A8, 0x002031B8, 0x002031BC,
+0x002031B0, 0x00117708, 0x002031B1, 0x002031B4,
+0x001C3D30, 0x00117718, 0x00117734, 0x001C3B9C,
+0x001C3704, 0x001C3D98, 0x001C3500, 0x001C3D00,
+0x001C36F8, 0x001C1028, 0x00202D98, 0x00201328,
+0x00202C04, 0x00201E18, 0x002034BC, 0x002031BA,
+0x00202D90, 0x002031CC, 0x002031D0, 0x00201276,
+0x002031D2, 0x00201FD0, 0x2FB62F96, 0x2FD62FC6,
+0x4F222FE6, 0xDE947F8C, 0x61E0E024, 0x0F14D493,
+0x710161E3, 0xD7926210, 0x470BE028, 0xD5910F24,
+0x0009450B, 0x6D032008, 0x1F0B8F11, 0xD48FDC8E,
+0xDD8F67C0, 0x657C4D0B, 0xDD8FD18E, 0x6B9C6910,
+0x420862B3, 0x32B84208, 0x3D2C4208, 0xE0281FDB,
+0xE58004FC, 0x604C66E2, 0x3050655C, 0x2D628F13,
+0x01FCE024, 0x641CE500, 0x625DDE84, 0x8B013243,
+0x0009A33D, 0x6753655D, 0x607037EC, 0x39DC6953,
+0xAFF27501, 0x20088094, 0xE0248B13, 0xE50001FC,
+0xA009DE7A, 0x655D641C, 0x32EC6253, 0x6C536B22,
+0x3CDC67B2, 0x75041C71, 0x3243625D, 0xA31E8BF3,
+0x88012D10, 0xE0248B16, 0xE40001FC, 0x671C2D40,
+0x624DDE6E, 0x8B013273, 0x0009A311, 0x6CE3644D,
+0x7C046943, 0x39EC6B43, 0x65923BCC, 0x74086DB2,
+0x25D2AFEF, 0x8B198804, 0x01FCE024, 0x2D70E700,
+0x1FD86D1C, 0x627DDE61, 0x8B0132D3, 0x0009A2F7,
+0x6B73677D, 0x3BEC61E3, 0x710464B2, 0x3C1C6C73,
+0x694265C2, 0x29597708, 0x2492AFED, 0x8B188805,
+0x01FCE024, 0x2D40E400, 0xDE54671C, 0x3273624D,
+0xA2DC8B01, 0x644D0009, 0x6BE36D43, 0x65D23DEC,
+0x61437B04, 0x6C1231BC, 0x74086952, 0xAFED29CB,
+0x88312592, 0xDE4A8B20, 0x65E6DB4A, 0x61E6DC4A,
+0x67E2D94A, 0x62E27E04, 0x1FEC7EE8, 0x7E0464E2,
+0x6EE21FED, 0x5BFD2BE0, 0x60B27B04, 0xC9011FBE,
+0x6BB22C00, 0x29B04B09, 0xDC412F26, 0x66134C0B,
+0xE2007F04, 0x2D20A2AB, 0x8B218830, 0xD939DE38,
+0xE06465E6, 0x720462E3, 0x672666E2, 0x6E23DC36,
+0x62227EE8, 0x6BE261E6, 0x29B01FEF, 0x7E040F16,
+0xC90160E2, 0x6EE22C00, 0x4E09DC30, 0x2F262CE0,
+0xD130E068, 0x04FE410B, 0xE2007F04, 0x2D20A287,
+0x8B058833, 0x4E0BDE2C, 0xE1000009, 0x2D10A27F,
+0x89018828, 0x0009A106, 0xE143DE20, 0xE04062E1,
+0x3217622D, 0x0FE68F04, 0x6023E240, 0x262106FE,
+0x8B013217, 0x0009A0EF, 0x02FEE040, 0x8521E401,
+0x8B013046, 0x0009A0E7, 0xE501E040, 0x2D5007FE,
+0x6471B265, 0x09FEE040, 0x6291E143, 0x652DE068,
+0x8D6B3517, 0xE6400F56, 0x8B273563, 0xE048E600,
+0xE11A0F65, 0x72C0A031, 0x00117800, 0x00203254,
+0x0020145E, 0x00202588, 0x002031A2, 0x00203258,
+0x002014AA, 0x002031A1, 0x00202DC8, 0x00117804,
+0x00117810, 0x0020319D, 0x0020319E, 0x0020319F,
+0x00200C2C, 0x00200C80, 0x00200C7C, 0x41216153,
+0x41214121, 0x41214121, 0x45214521, 0x60534521,
+0x6603C903, 0x0F65E048, 0xE0077118, 0xE0442209,
+0x641D0F25, 0x65F3E04C, 0x0F46B28C, 0x04FDE048,
+0x0BFDE044, 0x61BD674D, 0x41084708, 0x0F16E050,
+0xD29B6073, 0x420B09FE, 0x6C07E00F, 0x607329C9,
+0xE0400F96, 0x65F30EFE, 0x6D0D85E2, 0x01FEE050,
+0x60D3420B, 0x6073290B, 0xE04C0F96, 0x04FEB251,
+0x06FEE040, 0x6261E068, 0x0F56652D, 0x3563E640,
+0xE000894E, 0x602381F8, 0x4008C903, 0x6B034000,
+0xE0546103, 0xE0580FB6, 0xECFFDD85, 0x6CCC0FF6,
+0x0FD6E06C, 0x4D0B60C3, 0x42216253, 0x42214221,
+0x64234221, 0x324C4200, 0xE05C6E07, 0x45214200,
+0xE0400FE6, 0x0BFE4521, 0xC9036053, 0x30FC4008,
+0x6D037B06, 0x85F81F05, 0x6C2D1FB7, 0x1FC66E03,
+0x0FC6E060, 0x05FEE058, 0x64C3B22C, 0x33FCE354,
+0x563262D2, 0x22696132, 0x67B42D22, 0x490B5936,
+0x220B607C, 0x05FEE058, 0x64C32D22, 0x7E01B201,
+0xE70662ED, 0x8FE33273, 0xE0407C01, 0x626106FE,
+0x06FEE040, 0x85614200, 0x302C760C, 0x6103701B,
+0x64F3E500, 0x7501E704, 0x6B5D6966, 0x24923B73,
+0x74048FF9, 0xB1E465F3, 0xE040641D, 0xB1A306FE,
+0xA17C6461, 0xD4570009, 0xE201D757, 0x2D20470B,
+0x0009A175, 0x8B078829, 0xEC00DE54, 0x61E22DC0,
+0x641DB175, 0x0009A16B, 0x622CE281, 0x8B013020,
+0x0009A0B6, 0x06FCE028, 0xE682626C, 0x3260666C,
+0x56FB8B20, 0x2610E124, 0x5217D149, 0x52181621,
+0x52191622, 0x521A1623, 0x551B1624, 0x1655E200,
+0x1656551C, 0x1657551D, 0x1658551E, 0x1659551F,
+0x11281127, 0x112A1129, 0x112C112B, 0x112E112D,
+0x112FA13D, 0x666CE683, 0x8B0B3260, 0xD63752FB,
+0x2250E500, 0xD2376562, 0x22527604, 0xD6366262,
+0x2620A12D, 0x666CE690, 0x8B033260, 0x0009B1C7,
+0x0009A011, 0x666CE691, 0x8B103260, 0x6252D52B,
+0x2228622C, 0xD22D8904, 0x0009420B, 0x0009A003,
+0x420BD22B, 0x56FB0009, 0xA110E200, 0xE6B02620,
+0x3260666C, 0xE0248B34, 0xE07002FC, 0x0F16612C,
+0xEB04EC00, 0x01FEE070, 0x321362CD, 0xA0FE8B01,
+0xD21A0009, 0x6DC36CCD, 0x72043D2C, 0x312C61C3,
+0x6D126ED2, 0xD114D41B, 0x0009410B, 0x410BD11A,
+0xD41A64E3, 0x420BD210, 0xD2170009, 0x64D3420B,
+0xD60DD417, 0x0009460B, 0x61E3E600, 0x316C666D,
+0x626D7601, 0x21D032B3, 0x4D198FF7, 0x7C08AFD2,
+0xD211D410, 0xD4116542, 0x0009420B, 0x0009A0CF,
+0x00202C80, 0x00203278, 0x0020145E, 0x00117804,
+0x00202D2C, 0x00203188, 0x0020319C, 0x00200CBA,
+0x00200CE0, 0x00203290, 0x002014A2, 0x002032A4,
+0x002032AC, 0x00117800, 0x002014AA, 0x002032B0,
+0xD5B5D1B4, 0x6252E040, 0x75046612, 0x2162362C,
+0x56116256, 0x1161362C, 0x62526653, 0x76085512,
+0x1152352C, 0x55136262, 0x352C76EC, 0x65631153,
+0x56146262, 0x362C7510, 0x66531164, 0x55156252,
+0x352C7610, 0x62621155, 0x362C5616, 0xD6A31166,
+0x55176262, 0x352C7604, 0x62661157, 0x352C5518,
+0x65631158, 0x56196262, 0x362C7504, 0x62561169,
+0x362C561A, 0x6256116A, 0x362C561B, 0x6653116B,
+0x551C6252, 0x352C7604, 0x6266115C, 0x352C551D,
+0x6263115D, 0x551E6662, 0x356C7204, 0x6622115E,
+0xD58F521F, 0x112F326C, 0x061E6252, 0x362C7594,
+0xE0440166, 0x62526653, 0x7644051E, 0x0156352C,
+0x6262E048, 0x362C061E, 0xD6860166, 0x6262E054,
+0x4229051E, 0x0156352C, 0x62627604, 0x061EE058,
+0x362C4229, 0x56FB0166, 0x2620E238, 0x021EE044,
+0x1621E048, 0x16226212, 0x16235211, 0xE2005512,
+0x55151654, 0x55131655, 0x55161656, 0x051E1657,
+0x1658E040, 0xE050051E, 0x55141659, 0x051E165A,
+0x165BE04C, 0xE054051E, 0x051E165C, 0x165DE058,
+0xE044051E, 0x0126165E, 0x2122E048, 0x11221121,
+0x11231125, 0x01261126, 0x0126E040, 0x1124E050,
+0xE04C0126, 0xE0540126, 0xE0580126, 0x7F740126,
+0x6EF64F26, 0x6CF66DF6, 0x000B6BF6, 0x4F2269F6,
+0xE240614D, 0x89143123, 0x3127E21F, 0x8B09D75A,
+0xD45A614D, 0xE00171E0, 0x5671440B, 0x26596507,
+0x1761A007, 0xE001D455, 0x6672440B, 0x26596507,
+0x4F262762, 0x0009000B, 0x614D4F22, 0x3123E240,
+0xE21F8912, 0xD74C3127, 0x614D8B08, 0x5671D24B,
+0x420B71E0, 0x260BE001, 0x1761A006, 0x6672D247,
+0xE001420B, 0x2762260B, 0x000B4F26, 0xE6400009,
+0x46284618, 0x6252D542, 0x89FC2268, 0x0009000B,
+0x4618E680, 0xD53E4628, 0x22686252, 0x000B89FC,
+0xA0010009, 0x7201E200, 0x8BFC3242, 0x0009000B,
+0x4618E680, 0xD5374628, 0x22686252, 0x000B8BFC,
+0x2FE60009, 0x7FFC4F22, 0xBFF16E53, 0x61E22F42,
+0xE280D631, 0x54E11615, 0x16464218, 0x422855E2,
+0x57E31657, 0x16786EF2, 0x26E22E2B, 0x4F267F04,
+0x6EF6AFCE, 0x2FD62FC6, 0x4F222FE6, 0x6C53DD26,
+0x6E43BFD6, 0x2DE2BFBB, 0x0009BFD2, 0x2C1251D5,
+0x1C4154D6, 0x1C5255D7, 0x1C6356D8, 0x6EF64F26,
+0x000B6DF6, 0x61636CF6, 0xA004E600, 0x62564109,
+0x24227601, 0x36127404, 0x000B8BF9, 0x4F220009,
+0xD117D416, 0x0009410B, 0xD417D216, 0xE5056022,
+0x2202CB20, 0xD5152452, 0x450BE700, 0xD7142472,
+0x0009470B, 0xE601D113, 0x2162D213, 0x4F264618,
+0x2262000B, 0x00202D2C, 0x001C36A0, 0x001C3CA0,
+0x001C36F4, 0x001C3B88, 0x001C3704, 0x00202C80,
+0x001C373C, 0x001C3700, 0x001C370C, 0x002032C4,
+0x0020145E, 0x001C3500, 0x001D4004, 0x002014D4,
+0x00200FA0, 0x001E212C, 0x001C3D30, 0x0009A1A9,
+0x2FE62FD6, 0xDD8F4F22, 0xA0049EA7, 0xD48E0009,
+0x420BD28E, 0x62D265D2, 0x8BF822E8, 0x0009A004,
+0xD28AD48B, 0x55D1420B, 0x22E852D1, 0xA0048BF8,
+0xD4880009, 0x420BD285, 0x52D255D2, 0x8BF822E8,
+0x0009A004, 0xD281D484, 0x55D3420B, 0x22E852D3,
+0xA0048BF8, 0xD4810009, 0x420BD27C, 0x52D455D4,
+0x8BF822E8, 0x6EF64F26, 0x6DF6000B, 0x2FD62FC6,
+0x4F222FE6, 0x6E636D73, 0x6C53B018, 0x64C357F4,
+0xB05465E3, 0xB06A66D3, 0xB09A0009, 0xB09E0009,
+0xB0A20009, 0xB0BE0009, 0xB0C10009, 0xB1240009,
+0x4F260009, 0x6DF66EF6, 0x6CF6A023, 0x3412D16C,
+0xD66C0529, 0x2650D76C, 0x2742000B, 0x0009A014,
+0x2FD62FC6, 0x4F222FE6, 0x6E636D73, 0x6C53BFEE,
+0x64C357F4, 0xB02A65E3, 0xB10666D3, 0x4F260009,
+0x6DF66EF6, 0x6CF6A005, 0xE603D260, 0x000B4618,
+0xD25E2262, 0x000BE600, 0x4F222262, 0xE40ABF7E,
+0x0009BF7E, 0xE104D25A, 0xE5004118, 0x2212E40A,
+0x2252BF74, 0x6072D757, 0x4F26CB20, 0x2702000B,
+0xD1554F22, 0xE400410B, 0x452BD554, 0x2FE64F26,
+0x6E63D153, 0x44186612, 0x45289210, 0x26294408,
+0x44084500, 0x4400265B, 0x4708264B, 0x47082162,
+0x27EBD14C, 0x000B2172, 0x03F06EF6, 0x2FE61FFF,
+0xDE494F22, 0xE40AE101, 0x2E12BF48, 0x726C62E3,
+0xE401E100, 0x22122212, 0x22122212, 0x22122212,
+0xE7302242, 0xE40AE503, 0x22122212, 0x22122212,
+0x22122212, 0x22122212, 0x22122212, 0x22122212,
+0x22522272, 0x22122212, 0x22122212, 0x22122212,
+0x22122212, 0x121ABF22, 0x2E62E600, 0x000B4F26,
+0xD2326EF6, 0xE441E101, 0x000B2212, 0xD1302242,
+0xE605D430, 0x000B2162, 0xD52F2462, 0x6050D22F,
+0x8B0E8801, 0x6040D42E, 0x8B078801, 0x9626D52D,
+0x88016050, 0x96238B0C, 0x0009A00A, 0xA0079621,
+0xE6000009, 0x2262D426, 0x88016040, 0xE6048B00,
+0xAEF3E40A, 0xD2242262, 0xE40AE601, 0x2262AEEE,
+0x2FC62FB6, 0x2FE62FD6, 0xDC204F22, 0x60C2ED00,
+0xCB01EB64, 0x60C22C02, 0xA041C901, 0x03C46E03,
+0x034003D4, 0x001C3B88, 0x002032C8, 0x002014AA,
+0x002032D0, 0x002032D8, 0x002032E0, 0x002032E8,
+0x0025E720, 0x002034B8, 0x0020318C, 0x001C5968,
+0x001D4004, 0x001C3500, 0x0020124A, 0x00201276,
+0x001C5814, 0x001C59D0, 0x001C5830, 0x001C6268,
+0x001C59A4, 0x001C639C, 0x0020319E, 0x001C5804,
+0x0020319D, 0x0020319F, 0x001C581C, 0x001C5860,
+0x89073DB2, 0xE40A60C2, 0xBE9FC901, 0x7D016E03,
+0x8BF52EE8, 0x8B033DB2, 0xD23ED43D, 0x0009420B,
+0x4F26E40A, 0x6DF66EF6, 0xAE8F6CF6, 0x44116BF6,
+0x604B8F01, 0x000B6043, 0x2FB60009, 0x2FD62FC6,
+0x4F222FE6, 0xDC347FFC, 0x60C2ED00, 0xCB02EB64,
+0x60C22C02, 0xC9022F02, 0x6E03A009, 0x89083DB3,
+0xE40A60C2, 0xC9022F02, 0x6E03BE70, 0x2EE87D01,
+0x3DB38BF4, 0xD4298B08, 0x7F04D226, 0x6EF64F26,
+0x6CF66DF6, 0x6BF6422B, 0x4F267F04, 0x6DF66EF6,
+0x000B6CF6, 0xD5226BF6, 0x60525651, 0x000B4628,
+0x2FB6306C, 0x2FD62FC6, 0x4F222FE6, 0x4F024F12,
+0x6E43BFF1, 0xDC1B6B03, 0xBFECDD1B, 0x30B80009,
+0x060A3C05, 0x46094609, 0x3D654601, 0x4209020A,
+0x42094209, 0x8BF032E2, 0x4F164F06, 0x6EF64F26,
+0x6CF66DF6, 0x6BF6000B, 0x4F222FE6, 0xE102DE0F,
+0xE403E500, 0xBFD42E12, 0xE6062E52, 0xE7004618,
+0x2E62E403, 0x4F262E72, 0x6EF6AFCB, 0x0009000B,
+0x002032F0, 0x0020145E, 0x001C5860, 0x00203308,
+0x001C1040, 0xCCCCCCCD, 0x10624DD3, 0x001D4004,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xE5007FD8, 0x6453E110, 0x6C534128, 0x655DEE0A,
+0x46086653, 0x4608365C, 0x361C7501, 0x675D6043,
+0x60C30F66, 0x37E3ED00, 0x816126C1, 0x81638162,
+0x16D316D2, 0x8FEA16D4, 0x68F27404, 0xDAB3D9B2,
+0x29821981, 0xD1B259F1, 0x2A921A91, 0x5BF35AF2,
+0x5EF55DF4, 0x11A154F6, 0x11B321A2, 0x11D511B2,
+0x11E711D4, 0x114911E6, 0x55F71148, 0xEE00DBA9,
+0xDDA957F8, 0xD6A952F9, 0x1B5164E3, 0xDBA82B52,
+0xEAB8D8A8, 0x2D72E945, 0x6AAC2622, 0x6EED4908,
+0x4D086DE3, 0x3DEC61E3, 0x4D084108, 0x3DBC31EC,
+0x410860C3, 0x81D12DC1, 0x4108E050, 0x41084008,
+0x60C381D2, 0xE500318C, 0x81D334A2, 0x1D131DD2,
+0x8D01D494, 0xD4911D54, 0xB08165D3, 0x64ED7E01,
+0x8BDC3492, 0xDB94D18D, 0xD28B6812, 0x1B814829,
+0x2FD26412, 0x2B92694D, 0xD98A6722, 0x1B734729,
+0xD7876822, 0x1BA26A8D, 0xD28C6B72, 0x22B2D586,
+0xE0035D72, 0x5E7412D2, 0x12E44018, 0xD6885176,
+0x54781216, 0x1248E1FF, 0xD4856792, 0x6852127A,
+0x28C1E703, 0x81916952, 0x6A52E050, 0x81A24008,
+0x60C36B52, 0x6D5281B3, 0x6E521DD2, 0x62521E63,
+0x1264E600, 0x46086563, 0x7501364C, 0x665D2612,
+0x8BF83673, 0xE003D471, 0x40186542, 0x674225C1,
+0x8171D274, 0xEE006842, 0x69421882, 0x1923E024,
+0xE5806A42, 0x6B421AE4, 0x81B266E3, 0xD46D6C42,
+0x655C81C3, 0x6D63666D, 0x616D7604, 0x31533D4C,
+0x2DE28FF8, 0xD569D268, 0x74042422, 0x7F282452,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0x664268F6, 0xC8036061, 0xE5008D04, 0xC9036061,
+0x8B038802, 0x65635262, 0x24125124, 0x6053000B,
+0x2FE62FD6, 0x7FEC4F22, 0x62536E53, 0x6D43E550,
+0x4508E400, 0xE101A001, 0x60435224, 0x81212211,
+0x60538123, 0x56E28122, 0x8BF53620, 0x16E4D250,
+0xE61464F3, 0x65E3420B, 0xE4FC65E1, 0x2E512549,
+0x65F361F1, 0x2F112149, 0xD14954D1, 0xE614410B,
+0x607157D1, 0x2701CB01, 0x7F141DE1, 0x6EF64F26,
+0x6DF6000B, 0x2FE62FD6, 0x7FEC4F22, 0x66536E53,
+0x6D43E5FC, 0x20596061, 0x2601CB01, 0x326052E2,
+0x12E48B06, 0x31E051E2, 0x52D18B04, 0x1E22A002,
+0x5664AFF0, 0x64F3D236, 0x420BE614, 0x67E165E3,
+0x2719E1FC, 0x67F12E71, 0x271954D1, 0x65F3D130,
+0x410BE614, 0x52D12F71, 0xCB016021, 0x1DE12201,
+0x4F267F14, 0x000B6EF6, 0x2FE66DF6, 0x624C4F22,
+0x4208DE1B, 0xA0054200, 0x52523E2C, 0x5624D417,
+0x2E62BF8E, 0x52E165E2, 0x8BF63520, 0x2622D61B,
+0x000B4F26, 0x2FB66EF6, 0x2FD62FC6, 0x4F222FE6,
+0xDB1CDC10, 0x66C252C1, 0x89403620, 0xC9036061,
+0x893C8801, 0xDD18DE0B, 0x64E3BF63, 0x85036503,
+0x620D66B2, 0x892B3262, 0xBF9BD403, 0xD4130009,
+0x00094D0B, 0x0009AFE6, 0x00202D88, 0x00202D90,
+0x00202D98, 0x00202DC0, 0x002031A4, 0x002031AC,
+0x001000C8, 0x00101680, 0x001E2108, 0x001C3D00,
+0x00117880, 0x00117780, 0x00040020, 0x0026C401,
+0x00200B26, 0x00203188, 0x0020145E, 0x00203324,
+0x64E3BF3E, 0x4D0BD406, 0xAFBB0009, 0xD2050009,
+0x4F262262, 0x6DF66EF6, 0x000B6CF6, 0x00006BF6,
+0x00203328, 0x001C3D28, 0x2FC62FB6, 0x2FE62FD6,
+0x7FFC4F22, 0x6022D22B, 0x8D41C803, 0xDE2A2F01,
+0xDB2BDC2A, 0xED01A017, 0xC9036051, 0x89168801,
+0xD128D426, 0x0009410B, 0x61035503, 0xC8208551,
+0xE0508903, 0x720102BE, 0xD2230B26, 0x420B64E3,
+0xD6226513, 0x52C126D2, 0x352065C2, 0xDE208BE4,
+0xDB21DD20, 0x52D1DC21, 0x352065D2, 0x60518918,
+0x8801C903, 0xD41B8914, 0x460BD616, 0x57030009,
+0x8F0437E0, 0xE2016503, 0xAFEC2B20, 0xD4182C52,
+0x420BD218, 0xD6110009, 0x4118E101, 0x2612AFE3,
+0xC80460F1, 0xD2148907, 0x4F267F04, 0x6DF66EF6,
+0x422B6CF6, 0x7F046BF6, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6000B, 0x001E2100, 0x00202D98, 0x00202D90,
+0x00202D2C, 0x00201162, 0x002011E4, 0x001C3D30,
+0x00117880, 0x00202D88, 0x002031A8, 0x002031A4,
+0x00202DC0, 0x00201180, 0x00200308, 0xE601D203,
+0x1265D503, 0x000B2252, 0x00001266, 0x001C1010,
+0x0000C34F, 0x0009000B, 0x2FD62FC6, 0x4F222FE6,
+0x6D436C53, 0xEE00A004, 0x7E0164D4, 0x644CBFF2,
+0x8BF93EC2, 0x6EF64F26, 0x000B6DF6, 0xE5006CF6,
+0x6643A002, 0x76017501, 0x22286260, 0xAFE38BFA,
+0x2FE60009, 0x75076253, 0xE1086753, 0x6043EE0A,
+0x4409C90F, 0x650330E2, 0x8D014409, 0xE630E637,
+0x4110365C, 0x8FF22760, 0xE00077FF, 0x000B8028,
+0x000B6EF6, 0x000BE000, 0x2FE6E000, 0x7FEC4F22,
+0x6E436253, 0xBFDC65F3, 0xBFD06423, 0xBFCE64E3,
+0xD40364F3, 0x0009BFCB, 0x4F267F14, 0x6EF6000B,
+0x0020332C, 0xE4FDD29A, 0xD79A6122, 0x22122149,
+0x74016022, 0x2202CB01, 0xD5976622, 0x22622649,
+0xC8406070, 0x60528902, 0x2502CB04, 0xE1F76452,
+0x25422419, 0xE7016052, 0x2502C9CF, 0xE6026052,
+0x2502CB03, 0x15624718, 0x1573000B, 0xD78CD58B,
+0xD48DD28C, 0xE600E100, 0x27112511, 0xAFD12210,
+0x664C2461, 0x4600D289, 0x6060362C, 0x000BCB10,
+0x654C2600, 0x4500D285, 0x6650352C, 0x2619E1EF,
+0x2560000B, 0xD282664C, 0x362C4600, 0xCB106060,
+0x2600000B, 0xD27E654C, 0x352C4500, 0xE1EF6650,
+0x000B2619, 0x664C2560, 0x4600D278, 0x6060362C,
+0x000BCB08, 0x654C2600, 0x4500D274, 0x6650352C,
+0x2619E1F7, 0x2560000B, 0xD271664C, 0x362C4600,
+0xCB086060, 0x2600000B, 0xD26D654C, 0x352C4500,
+0xE1F76650, 0x000B2619, 0x624C2560, 0x4200D667,
+0x6020326C, 0x4021C908, 0x40214021, 0x600C000B,
+0xD663624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0xD15F600C, 0x341C644C, 0x000B6240,
+0xD15D602C, 0x341C644C, 0x000B6240, 0x2FE6602C,
+0x6E434F22, 0xE60A645C, 0x89143467, 0x0009BFEB,
+0x60EC640C, 0x8B028801, 0xA002E00F, 0x44092409,
+0x624C4409, 0x3263E60A, 0xBFE28905, 0x620C644C,
+0xC8806023, 0xE2008B00, 0x4F266023, 0x6EF6000B,
+0xD64A4F22, 0x88016062, 0xB2458B03, 0xA0030009,
+0xD2470009, 0x2260E640, 0xE200D646, 0x000B4F26,
+0x4F222622, 0x6062D641, 0x8B018802, 0x0009B28E,
+0xE200D640, 0x000B4F26, 0xD53C2622, 0xE100D43C,
+0x2512E701, 0x2470000B, 0xE604D239, 0x2260000B,
+0xD4394F22, 0x410BD139, 0xD5390009, 0x6650E1FD,
+0x2619D238, 0x2560E700, 0x000B4F26, 0x4F222270,
+0xD132D435, 0x0009410B, 0xE7FBD531, 0x26796650,
+0x000B4F26, 0x4F222560, 0xD12CD430, 0x0009410B,
+0xE7F7D52B, 0x26796650, 0x000B4F26, 0xD5282560,
+0x6250942D, 0x000B2249, 0xD5252520, 0x6250E4BF,
+0x000B2249, 0x4F222520, 0x8522D225, 0x2008600D,
+0x88018911, 0x88038913, 0x88058915, 0x88068942,
+0x88088948, 0x8809894E, 0x880A8954, 0x880B895A,
+0xA0678960, 0xB0690009, 0xA0640009, 0xB077600C,
+0xA0600009, 0xB080600C, 0xA05C0009, 0xFF7F600C,
+0x001E2148, 0x001E1000, 0x001E1108, 0x002031FC,
+0x002031FE, 0x0020321D, 0x002031E0, 0x001E103F,
+0x001E105F, 0x001E102F, 0x001E1090, 0x00203204,
+0x001E100B, 0x00203200, 0x00203330, 0x0020145E,
+0x001E1028, 0x0020321C, 0x0020333C, 0x0020334C,
+0x002031D4, 0x6260D684, 0x8B2B2228, 0x0009B061,
+0x600CA029, 0x6260D680, 0x8B232228, 0x0009B069,
+0x600CA021, 0x6260D67C, 0x8B1B2228, 0x0009B0C7,
+0x600CA019, 0x6260D678, 0x8B132228, 0x0009B0CD,
+0x600CA011, 0x6260D674, 0x8B0B2228, 0x0009B125,
+0x600CA009, 0x6260D670, 0x8B032228, 0x0009B13D,
+0x600CA001, 0x4F26E000, 0x0009000B, 0xD26CD16B,
+0xD56C8412, 0x4000C90F, 0xD76B012D, 0xE403D66B,
+0xE20F611C, 0x2540E001, 0x25202712, 0x2602000B,
+0xE601D262, 0x30668523, 0xE0008D05, 0xD663D260,
+0xE0018122, 0x000B2602, 0xD25C0009, 0x600D8523,
+0x89052008, 0x8B0A8801, 0x6060D65D, 0x2600CB01,
+0xD457D65A, 0xE001E101, 0x000B2612, 0x000B8142,
+0xD152E000, 0x8513E501, 0x640D4518, 0x66033453,
+0xE0008D05, 0xD551D253, 0x2260E001, 0x000B2502,
+0x4F220009, 0x8513D149, 0x6453650D, 0x62494419,
+0x227D672E, 0x8801602C, 0x88028909, 0x88038910,
+0x8806891A, 0x88078935, 0xA04C893B, 0xD5460009,
+0x6652D746, 0x2762D446, 0x622C6261, 0x2421A038,
+0x2228625C, 0xD4438B3F, 0x6642D540, 0x2562D440,
+0x24018561, 0x6203A02C, 0x2008605C, 0x88108907,
+0x88208908, 0x88308909, 0xA02C890A, 0xD23A0009,
+0x6222A008, 0xA005D239, 0xD2396222, 0x6222A002,
+0x6262D638, 0xD432D531, 0x66212522, 0xA00F626C,
+0xD6352421, 0x6261D52D, 0x622CD42D, 0xA0072562,
+0xD6322421, 0x8561D529, 0x2562D429, 0x62032401,
+0x662D8515, 0x3617610D, 0x65038F01, 0xB0CB2451,
+0xA0010009, 0xE000E001, 0x000B4F26, 0xD6190009,
+0xD427E101, 0x65412610, 0xD118D717, 0xE20F655D,
+0x2752E001, 0x000B2620, 0x2FE62102, 0xD20F4F22,
+0x640C8523, 0x8B082448, 0xD511D61D, 0x2621E200,
+0x940F8451, 0xA0482049, 0xDE0D8051, 0xC84060E0,
+0xE2018D32, 0x89443427, 0xD216D615, 0x2641420B,
+0x0009A030, 0x0000FF7F, 0x0020321D, 0x002031D4,
+0x002031E0, 0x001E1100, 0x001E100C, 0x00203200,
+0x001E1000, 0x001E1001, 0x00203208, 0x002031E8,
+0x002031EC, 0x002031F0, 0x0020320C, 0x00203210,
+0x00203214, 0x00203218, 0x0020351C, 0x00203526,
+0x002031FA, 0x00202362, 0x89123427, 0xD294D693,
+0x2641420B, 0xCB8084E1, 0x80E1B0F5, 0xD69160E0,
+0x2E00CB04, 0xC93F6060, 0xD68F2600, 0xA001E001,
+0xE0002602, 0x000B4F26, 0xD68C6EF6, 0xC8806060,
+0xD2868919, 0x88016021, 0xD2898B15, 0x8524E501,
+0x89103056, 0xE203D187, 0x2120D487, 0xE00B6541,
+0x0656655D, 0xE40FD585, 0x2140E702, 0xD77E2571,
+0x000BE001, 0x000B2702, 0x2FE6E000, 0xDE804F22,
+0xC88084E1, 0xD57A892C, 0x20088554, 0x61038F28,
+0x8553D77C, 0x64036672, 0x8566650C, 0x3520620C,
+0xD6798B1E, 0x651CD774, 0x2651644C, 0x60E02741,
+0x8904C840, 0x420BD275, 0xA0030009, 0xD2680009,
+0x0009420B, 0x0009B09F, 0xE201D167, 0x60E02122,
+0xCB04D464, 0x60402E00, 0x2400C93F, 0x6023A001,
+0x4F26E000, 0x6EF6000B, 0x2FB62FA6, 0x2FD62FC6,
+0xDA622FE6, 0x66A1E240, 0x3622DC5E, 0x62638900,
+0x6ED36D2C, 0x4E2136D8, 0x4E212A61, 0xDB61D460,
+0xE700A00F, 0x770162B2, 0x71026123, 0x66212B12,
+0x71026213, 0x61212B12, 0x651D666D, 0x356C4528,
+0x627C2452, 0x8BED32E3, 0xC90360D3, 0x8B108803,
+0x617367B2, 0x2B127102, 0x71026E13, 0x2B126571,
+0x655D6DE1, 0x422862DD, 0x325CE107, 0xA00C2C10,
+0x88022422, 0xA0038B01, 0x8801E203, 0xE2018B05,
+0x66B22C20, 0x655D6561, 0xE60F2452, 0x67A12C60,
+0x8B052778, 0xDD38DC44, 0xEB01EA00, 0x2DB22CA2,
+0x6DF66EF6, 0x6BF66CF6, 0x6AF6000B, 0x2FE62FD6,
+0xE240DD36, 0x362266D1, 0x62638900, 0x3678672C,
+0x7703DE38, 0x47212D61, 0x64E2D635, 0xA00E4721,
+0x6562E100, 0x62537101, 0x74012450, 0x24204219,
+0x45297401, 0x74012450, 0x24504519, 0x621C7401,
+0x8BEE3273, 0x66E24200, 0x420061D1, 0x2118362C,
+0x2E628F06, 0xDD1CD728, 0xE501E400, 0x2D522742,
+0x000B6EF6, 0x2FD66DF6, 0x4F222FE6, 0xED0AEE01,
+0x64E3BC97, 0xBC9C64E3, 0x62EC7E01, 0x8BF732D7,
+0xBC9FEE01, 0x64E364E3, 0x7E01BCA4, 0x32D762EC,
+0x4F268BF7, 0x000B6EF6, 0xD1186DF6, 0xD418920D,
+0x72122122, 0x2422D617, 0xD7177204, 0x72202622,
+0x2722D116, 0x000B7230, 0x137A2122, 0x002031FA,
+0x0020246E, 0x001E1015, 0x00203200, 0x001E1001,
+0x002031D4, 0x001E1100, 0x002031FE, 0x002031EC,
+0x001E1000, 0x002031F0, 0x002031FC, 0x00202362,
+0x001E100C, 0x002031E8, 0x00203204, 0x00203208,
+0x0020320C, 0x00203210, 0x00203214, 0x00203218,
+0x4F222FE6, 0xD6507FFC, 0x88016060, 0xE2018951,
+0x2620BFBB, 0xD54ED14D, 0xDE4E6010, 0x64E36552,
+0x7402C840, 0x8D22D14C, 0xD24C7502, 0xE601D74C,
+0xE7042722, 0x76016255, 0x626C2421, 0x8FF93273,
+0xD4437402, 0x6242E601, 0x640D8528, 0x67494419,
+0x275D657E, 0x81E4607C, 0xE417D542, 0x67557601,
+0x3243626C, 0x8FF92171, 0xA0207102, 0xD23E0009,
+0xE601D73B, 0xE7042722, 0x76016255, 0x626C2421,
+0x8FF93273, 0xD4327402, 0x6242E601, 0x640D8528,
+0x67494419, 0x275D657E, 0x81E4607C, 0xE417D533,
+0x67557601, 0x3243626C, 0x8FF92171, 0x924A7102,
+0xD2262E21, 0x5E23D72E, 0x64F22FE2, 0x604365F2,
+0x2700C980, 0xC9606043, 0x80716103, 0xC9036043,
+0x80724519, 0x65F2605C, 0x817266F2, 0x46194629,
+0x606C4529, 0x4018645C, 0x8173304C, 0x21185E23,
+0x64F22FE2, 0x6E4C62F2, 0x602C4219, 0x66F262F2,
+0x46294018, 0x461930EC, 0x42298174, 0x652C606C,
+0x305C4018, 0x81758F07, 0x0009BC9D, 0x2228620C,
+0xA00A8908, 0x60130009, 0x8B038840, 0x0009B009,
+0x0009A003, 0xE202D60F, 0x7F042622, 0x000B4F26,
+0x000B6EF6, 0x060A0009, 0x0020321C, 0x001E1000,
+0x00203208, 0x0020351C, 0x00203528, 0x002034C0,
+0x002031F0, 0x002034F0, 0x002034EE, 0x002034C2,
+0x002031D4, 0x00203200, 0x4F222FE6, 0xDE937FFC,
+0x200884E9, 0x2F008D06, 0xD692D491, 0x0009460B,
+0x64F0B194, 0x6620D290, 0x89022668, 0xC9BF60E0,
+0x7F042E00, 0x000B4F26, 0x000B6EF6, 0x2FE60009,
+0xDE8A4F22, 0x60E0D68A, 0xCBC0D48A, 0x62602E00,
+0xC803602C, 0x40218904, 0x70014021, 0x6603A002,
+0x66034009, 0xD684616D, 0xE500A004, 0x75016262,
+0x74042422, 0x3213625D, 0xD2808BF8, 0x0009420B,
+0xC9BF84E2, 0x4F2680E2, 0x6EF6000B, 0x2FE62FD6,
+0x7FFC4F22, 0x6260D67A, 0x89442228, 0xD56FE100,
+0x60502610, 0xCB40D477, 0x2500440B, 0x8D052008,
+0x62E06E03, 0x7104612C, 0x2F11A006, 0xD472D66A,
+0xDD726760, 0x657C4D0B, 0xE23C6D1D, 0x8B033D27,
+0xD264D46F, 0x0009420B, 0x4D214D21, 0xA005D76D,
+0x66E6E400, 0x357C4508, 0x74012562, 0x35D3654D,
+0xD7698BF7, 0x6172E003, 0x81114018, 0x6E7260F1,
+0x81E2700C, 0xD4656172, 0xDD658113, 0x4D0BDE65,
+0xE2016572, 0xD4642E22, 0x420BD252, 0xD6530009,
+0xC93F6060, 0x7F042600, 0x6EF64F26, 0x6DF6000B,
+0x2FC62FB6, 0x2FE62FD6, 0xD25C4F22, 0x6B436E73,
+0x420B6C53, 0x20086D63, 0x61038F08, 0xD245D458,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6422B, 0x21B060C3,
+0x60D38011, 0xE5008111, 0x64BCA007, 0x6053655D,
+0x665300EC, 0x7501361C, 0x625D8064, 0x8BF53243,
+0x6060D636, 0x2600C9BF, 0x6EF64F26, 0x6CF66DF6,
+0x6BF6000B, 0x7FC44F22, 0x720262F3, 0x22512F41,
+0x45297202, 0x60632251, 0xE5C4E682, 0x67F38121,
+0x655C666C, 0xE408BFBC, 0x4F267F3C, 0x0009000B,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xE1007FC4, 0x6513ECFF, 0x6B136CCD, 0xDE36D735,
+0xEDFF64F3, 0xD835EA04, 0x6053655C, 0x027D4000,
+0x32C0622D, 0x66038D0D, 0x09ED6063, 0x2491027D,
+0x24217402, 0x698202ED, 0x3928622D, 0x74022892,
+0x75017104, 0x6063625C, 0x07D532A2, 0x0EB58FE4,
+0x2448641C, 0xE6808905, 0x67F3E5C5, 0xBF7F666C,
+0x7F3C655C, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0xD11E68F6, 0x6012D21E, 0xCB20E405,
+0x2102E500, 0x000B2242, 0x00002252, 0x001E1017,
+0x00203358, 0x0020145E, 0x002031A2, 0x001E1015,
+0x001E10BF, 0x00117800, 0x001E10FC, 0x00200308,
+0x002031A8, 0x002025C6, 0x0020335C, 0x002014AA,
+0x00203378, 0x0011788C, 0x002031A4, 0x00202D88,
+0x002011E4, 0x001E2130, 0x00203380, 0x00202588,
+0x00203384, 0x002031BC, 0x002031C4, 0x002034BC,
+0x001C3500, 0x001D4004, 0xD565D164, 0xE400D765,
+0x2142E20F, 0x17411154, 0xD5632722, 0x9669D763,
+0x15412572, 0x96661562, 0xE6011565, 0xD5601165,
+0x666CE6F8, 0x25422542, 0x25422542, 0x25422542,
+0x25622542, 0x7601E727, 0x67632572, 0x25627797,
+0xE7042572, 0x2572E248, 0xE2192522, 0xE2702522,
+0x25422542, 0x25422542, 0x25222542, 0x2522E20C,
+0x25422542, 0x25422542, 0x25422542, 0x25422542,
+0x000B154A, 0xE2081145, 0x0009422B, 0x2FE62FD6,
+0x7FFC4F22, 0xC8206043, 0x6E438D02, 0x0009BE6D,
+0xC81060E3, 0xBE6A8901, 0x60E30009, 0x8901C840,
+0x0009BE8C, 0xC80160E3, 0xDD3E8938, 0xC80260D0,
+0x2F008D03, 0x460BD63C, 0x60F00009, 0x8902C804,
+0x460BD63A, 0x62F00009, 0xC8806023, 0x60D08902,
+0x2D00C97F, 0xC8016023, 0xD6358906, 0x0009460B,
+0x0009A007, 0x51630601, 0x8902C808, 0x460BD631,
+0x60F00009, 0x8902C810, 0x420BD22F, 0xD52F0009,
+0x88026052, 0xD22E8B03, 0xA005E604, 0x88012260,
+0xD22B8B02, 0x2260E601, 0x2522E200, 0xC88060E3,
+0xD628892E, 0x60E36E60, 0x8902C880, 0x420BD226,
+0x60E30009, 0x8902C840, 0x420BD224, 0x60E30009,
+0x8902C802, 0x420BD222, 0x60E30009, 0x890EC804,
+0x410BD120, 0xBF0E0009, 0xBF4D0009, 0xD51E0009,
+0x6050D41E, 0xC908D71E, 0xBF842500, 0x60E32472,
+0x8905C808, 0x7F04D21B, 0x6EF64F26, 0x6DF6422B,
+0x4F267F04, 0x000B6EF6, 0x00006DF6, 0x001C581C,
+0xA000A000, 0x001D0100, 0x001D4000, 0x00040021,
+0x001C589C, 0x001E1021, 0x00201640, 0x00201662,
+0x00201CA0, 0x0020167A, 0x00201688, 0x00203200,
+0x001E100B, 0x001E1028, 0x002016DE, 0x002016EA,
+0x00201690, 0x002016AE, 0x001E1000, 0x0010F100,
+0x12345678, 0x002016C6, 0x644CD6A7, 0x000B346C,
+0xD6A62450, 0x346C644C, 0x2450000B, 0x644CD6A4,
+0x000B346C, 0x625C2450, 0x4208616D, 0x42084119,
+0x42006019, 0x670E614C, 0xD49E321C, 0x4200207D,
+0x324CC90F, 0x2200000B, 0x4208625C, 0x42004208,
+0x324C644C, 0x4200D498, 0x000B324C, 0x2FE62260,
+0x614C4F12, 0x4100D493, 0x6710314C, 0xE29F666D,
+0x27294619, 0x6E536269, 0x672E6573, 0x4221227D,
+0x42214221, 0x7601662C, 0xE4014608, 0x34E84608,
+0x644C4600, 0x071A0467, 0x2150257B, 0x000B4F16,
+0x4F226EF6, 0xD2857FE8, 0x88016021, 0xD2848B7B,
+0x26686621, 0xD2838B77, 0x26686621, 0xE50F8B73,
+0xE401BFA2, 0xBFA4E501, 0xE586E400, 0xE400655C,
+0x2F50BFA4, 0xBFA1E401, 0xE602E506, 0x60634618,
+0x81F2E401, 0x6543BF9F, 0xE40185F2, 0xBFAB6543,
+0x85F26603, 0x6543E401, 0x6603BFB1, 0xE40265F0,
+0x6053756C, 0x80F8BF80, 0xBF82E402, 0x84F8E512,
+0x7090E402, 0x6503BF82, 0x4618E602, 0x81F66063,
+0xBF80E402, 0x85F6E500, 0x6603E402, 0xE500BF8C,
+0xE40285F6, 0xBF926603, 0xE5FEE500, 0xE010655C,
+0xBF61E403, 0xE5130F54, 0xE40EBF63, 0x05FCE010,
+0xBF63E40E, 0xE5007585, 0xBF64E403, 0xE500E640,
+0xBF71E403, 0xE500E640, 0xBF78E403, 0xE5FFE640,
+0xE014655C, 0xBF47E404, 0xE40F0F54, 0xE504BF49,
+0x05FCE014, 0xBF49E40F, 0xE5017584, 0xBF4AE640,
+0xE501E404, 0xBF57E640, 0xE501E404, 0xE404E640,
+0xAF5C7F18, 0x7F184F26, 0x000B4F26, 0x4F220009,
+0xD2427FF0, 0x88016021, 0xD2418B71, 0x26686621,
+0xD2408B6D, 0x26686621, 0xE50F8B69, 0xE401BF1C,
+0xBF1EE501, 0xE586E400, 0xE400655C, 0x2F50BF1E,
+0xBF1BE401, 0xE401E506, 0xBF1C6543, 0xE401E640,
+0xBF296543, 0xE401E640, 0xBF306543, 0x65F0E640,
+0x756CE402, 0xBEFF6053, 0xE40280F4, 0xE512BF01,
+0xE40284F4, 0xBF017090, 0xE6406503, 0xBF02E402,
+0xE640E500, 0xBF0FE402, 0xE640E500, 0xBF16E402,
+0xE5FEE500, 0x6053655C, 0xBEE5E403, 0xE51380F8,
+0xE40EBEE7, 0xE40E84F8, 0xBEE77085, 0xE5006503,
+0xBEE8E640, 0xE500E403, 0xBEF5E640, 0xE500E403,
+0xBEFCE640, 0xE5FFE403, 0x6053655C, 0xBECBE404,
+0xE40F80FC, 0xE504BECD, 0xE40F84FC, 0xBECD7083,
+0xE5016503, 0xBECEE640, 0xE501E404, 0xBEDBE640,
+0xE501E404, 0xE404E640, 0xAEE07F10, 0x7F104F26,
+0x000B4F26, 0x00000009, 0x001E102F, 0x001E1080,
+0x001E1090, 0x001E103F, 0x001E103E, 0x002031FA,
+0x002031FC, 0x002031FE, 0xD21DD11C, 0x66206010,
+0x676C7001, 0x3700C90F, 0xE5008D13, 0x67106210,
+0x7701622C, 0x64232170, 0xD6166010, 0x44084408,
+0x3428C90F, 0x62602100, 0x7201D513, 0x44082620,
+0x000B354C, 0xD10F6053, 0x25586510, 0xE6008D13,
+0xD60DD40B, 0x655C6540, 0x47086753, 0x37584708,
+0x47086540, 0x24507501, 0x367C6040, 0x2400C90F,
+0x72FF6210, 0x000B2120, 0x00006063, 0x002031A1,
+0x002031A0, 0x002031A2, 0x00202DC8, 0x7FFC4F22,
+0xE680D19D, 0x666C6212, 0xD29C2F22, 0x67F36563,
+0x420B7542, 0x7F04E404, 0x000B4F26, 0xE6800009,
+0xD296666C, 0xE7006563, 0x422B7540, 0xE6806473,
+0xD292666C, 0xE7006563, 0x422B7543, 0x2F866473,
+0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6, 0x7FF44F22,
+0xDD8CD28B, 0x72011F21, 0xDB8B1F22, 0x6AF2E840,
+0x5211D18A, 0x36206612, 0xA0A78B01, 0x60610009,
+0x8801C903, 0xA0A18B01, 0xD9840009, 0x420BD284,
+0x55036493, 0x845C6A03, 0x30E0EE84, 0xD1818B79,
+0x606C6610, 0x8B3D8801, 0x6210D17F, 0x892F2228,
+0xD57EE701, 0x64522B72, 0x1442E003, 0xD57C6252,
+0xE6004018, 0x21608121, 0xD17A6453, 0x6E527404,
+0x60126742, 0xCB20DC78, 0x76012102, 0x3283626D,
+0x25E28BFB, 0x2472DE71, 0x62E267C2, 0x1274D173,
+0x604164E2, 0x2401CB01, 0xEE0066E2, 0xDC702C62,
+0xEC012C62, 0x2DC2410B, 0x4C18EC01, 0x2BE22DC2,
+0xD764DE6C, 0xD16C60E2, 0xCB01E202, 0x27202E02,
+0x2122A02F, 0x8B2C2008, 0xE701DE68, 0xD466EC00,
+0x2170D264, 0xEE012EC2, 0x612224E2, 0x2169E6FE,
+0xE01E2212, 0x54F10C5C, 0x24C0E01F, 0x56F2025C,
+0x26207510, 0xD75EE600, 0xEE06D45E, 0x76018456,
+0x6C542700, 0x31E3616C, 0x740124C0, 0x77018FF6,
+0xE494D259, 0x72012240, 0x2250E500, 0xE605720F,
+0xD2562260, 0x65A36493, 0xEE01420B, 0xAF6F4E18,
+0x2FA22DE2, 0xD45265F2, 0x66428553, 0x3262620D,
+0xD4508907, 0x410BD150, 0xD7500009, 0xAF57E601,
+0xD43A2762, 0xDD37D149, 0x65F2410B, 0xD44CEE01,
+0x4E18D64C, 0x2DE2460B, 0x0009AF4A, 0x7F0C2FA2,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0x4F2268F6, 0x85467FF4, 0x2F01E681, 0x666C8547,
+0x854881F1, 0x81F2D225, 0x67F38542, 0x854381F3,
+0x81F4E40C, 0x65636053, 0x420B81F5, 0x7F0C7540,
+0x000B4F26, 0x2F860009, 0x2FA62F96, 0x2FC62FB6,
+0x2FE62FD6, 0x7FEC4F22, 0xE800D11A, 0xD4322F12,
+0x1F416183, 0x6A13DB20, 0x4A08D630, 0xDE20E001,
+0x4A00460B, 0x1F023AEC, 0x52B166B2, 0x8B013620,
+0x0009A19B, 0xC9036061, 0x8B018801, 0x0009A195,
+0xDE275263, 0x8B4F32E0, 0x420BD20D, 0xDE2564B3,
+0xD70DD50E, 0xED01DC0B, 0x2E02E100, 0x27D02502,
+0xAFE12C10, 0x00002E16, 0x001C3D9C, 0x00201F40,
+0x0011779A, 0x001C3D30, 0x001D0104, 0x00202DC0,
+0x00201162, 0x002031B1, 0x002031B0, 0x002031AC,
+0x001C3B9C, 0x001C3500, 0x00202D98, 0x00201276,
+0x001C3D00, 0x001C36F8, 0x00117708, 0x002031B4,
+0x0011778C, 0x00117792, 0x00117788, 0x00201180,
+0x00203188, 0x00202D88, 0x002011E4, 0x001E2130,
+0x0020349C, 0x0020145E, 0x002034A8, 0x00202C80,
+0x00117780, 0x0011770C, 0xC8018561, 0x5C63897A,
+0x660385C2, 0x6403C903, 0x650D85C3, 0x40216053,
+0xC93F4021, 0x6E034500, 0x252D322A, 0xE2106053,
+0x3E23C901, 0x6D038D23, 0x4408D79D, 0x44086570,
+0x440062E3, 0x25584200, 0x342C8F0F, 0x6043D299,
+0x697D072D, 0x60994919, 0x201D610E, 0x60D381F6,
+0x8F0C8801, 0xA00A697C, 0xD29369E3, 0x052D6043,
+0x4219625D, 0x670E6029, 0x81F6207D, 0xD18F695C,
+0x22286210, 0xE9FF8901, 0xEEFF699C, 0x6EEC659D,
+0x8B0F35E0, 0x4C0BDC8A, 0x540364B3, 0xBF20E502,
+0xD4886E03, 0x410BD188, 0xD78865E3, 0xD488ED01,
+0x27D2A01E, 0x26E9EEFC, 0x81C26063, 0x97C585C3,
+0x62032079, 0x450885F6, 0x6063260B, 0x81C2252B,
+0x81C36053, 0xE10885C4, 0x201B4118, 0x62B281C4,
+0x20E98521, 0x64B28121, 0xCB016041, 0xD4792401,
+0x450BD579, 0x60B20009, 0x57F266F2, 0x2A02CB01,
+0x2672AF22, 0xD26E8561, 0x8F02C802, 0xA09F64B3,
+0x420B0009, 0xDC710009, 0x5E036503, 0x07CEE04C,
+0x7701DD6F, 0x6CD20C76, 0x7C01D664, 0x6D602DC2,
+0x89062DD8, 0xD264D463, 0xED01420B, 0xA07ED763,
+0x625127D2, 0x4118E10F, 0x2219E402, 0x32404418,
+0x85518B11, 0x20D9EDFC, 0x60518151, 0xCB017DE3,
+0x85E12501, 0x20D9D65F, 0x460B81E1, 0x6CF264B3,
+0xA06457F2, 0x6D512C72, 0x4D196DDD, 0x66DE6DD9,
+0x7D012D6D, 0x610360DC, 0x88014118, 0x25118F45,
+0x6462D653, 0x26427401, 0x660D85E3, 0x40216063,
+0xC93F4021, 0x6D034600, 0x262D322A, 0xC8016063,
+0xDC4ED14D, 0x964A8901, 0xE6002D6B, 0x0F64E010,
+0xE01064DD, 0x607C07FC, 0x021D4000, 0x3240622D,
+0x66038D12, 0x021D6063, 0x3270E7FF, 0xA00B8B01,
+0xE01001D5, 0xE60402FC, 0x0F247201, 0x3262622C,
+0x06FC8BE7, 0x4600666C, 0x01CD6063, 0x0C157101,
+0x6711D13B, 0x3C406C7D, 0x62118907, 0x88FF602D,
+0x21D18903, 0xE201DD37, 0x85512D20, 0x20D9EDFC,
+0x60518151, 0xCB01D22F, 0x420B64B3, 0xE0102501,
+0xD43102FC, 0xE001612C, 0x67F2440B, 0x85EF2702,
+0x54F1D22E, 0x650D420B, 0x0009AE7E, 0x80007E03,
+0x0009420B, 0x6E035403, 0xED088544, 0x20D94D18,
+0x8B0330D0, 0xE501BE3D, 0x0009A007, 0xDD248541,
+0x22D8620D, 0xBE348901, 0xD412E500, 0x420BD212,
+0xD71265E3, 0xAE5FED01, 0x780127D2, 0xEE04618D,
+0x8D0231E7, 0xAE4E7B08, 0x7F140009, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0x000068F6,
+0x002034B8, 0x0020339C, 0x0020341C, 0x0020319C,
+0x00201162, 0x00202D90, 0x00201180, 0x001E212C,
+0x002034A0, 0x002034A4, 0x0020145E, 0x00202D2C,
+0x002034BC, 0x002011E4, 0x002031BC, 0x002031C4,
+0x002031B8, 0x002031BA, 0x00202C80, 0x002014AA,
+0x00008000, 0x4F222FE6, 0x6E22D212, 0xC84060E3,
+0x22E28D02, 0x0009BCFA, 0x4218E240, 0x89012E28,
+0x0009BD05, 0xC81060E3, 0xD40B8905, 0x420BD20B,
+0xBD040009, 0x60E30009, 0x8901C805, 0x0009BDEB,
+0xC80260E3, 0x4F268902, 0x6EF6AD01, 0x000B4F26,
+0x00006EF6, 0x001C3510, 0x002034B0, 0x0020145E,
+0x080A0C0E, 0x00020406, 0x1A1C1E20, 0x12141618,
+0x2E303234, 0x26282A2C, 0x3A3C3E40, 0x6C625648,
+0x41112F26, 0xE2208F18, 0x890B3123, 0x321CD204,
+0xD1026220, 0x412B312C, 0x00090009, 0x00202CAA,
+0x00202C60, 0x000BE000, 0x400062F6, 0x40004000,
+0x40004000, 0x40004000, 0x62F6000B, 0x40004000,
+0x40004000, 0x40004000, 0x40184000, 0x62F6000B,
+0x40004000, 0x40004000, 0x40004000, 0x40284000,
+0x62F6000B, 0x40004000, 0x40184000, 0x000B4028,
+0xC90F62F6, 0x40054005, 0x40054005, 0x62F6000B,
+0x4005C907, 0x40054005, 0x62F6000B, 0x4005C903,
+0x000B4005, 0xC90162F6, 0x000B4005, 0x000062F6,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x544F0D0A,
+0x46205355, 0x00003A57, 0x206C754A, 0x32203532,
+0x20373030, 0x313A3132, 0x37323A32, 0x00000000,
+0x00000D0A, 0x00000043, 0x42707372, 0x3D206675,
+0x554E203D, 0x202C4C4C, 0x6E49677A, 0x4E497274,
+0x6D754E51, 0x0000003D, 0x61766E49, 0x2064696C,
+0x72657375, 0x20726F20, 0x2079656B, 0x00214449,
+0x52504545, 0x57204D4F, 0x65746972, 0x6461202C,
+0x003D7264, 0x6C617620, 0x0000003D, 0x00000A0D,
+0x6E6B6E55, 0x206E776F, 0x6D6D6F63, 0x3D646E61,
+0x00000000, 0x000A0D52, 0x203A3051, 0x00000020,
+0x203A3151, 0x00000020, 0x203A3251, 0x00000020,
+0x203A3351, 0x00000020, 0x203A3451, 0x00000020,
+0x61437748, 0x7262696C, 0x6F697461, 0x6620206E,
+0x0A6C6961, 0x0000000D, 0x73696F4E, 0x61432065,
+0x7262696C, 0x6F697461, 0x6166206E, 0x21216C69,
+0x00000D0A, 0x00000072, 0x00205220, 0x00000D0A,
+0x62735576, 0x7473725F, 0x00000A0D, 0x62735576,
+0x7375735F, 0x646E6570, 0x00000A0D, 0x62735576,
+0x7365725F, 0x000A0D6D, 0x00000042, 0x72746E49,
+0x6D652051, 0x2C797470, 0x49677A20, 0x4972746E,
+0x754E514E, 0x00003D6D, 0x654C7245, 0x0000006E,
+0x00000049, 0x20746F4E, 0x756F6E65, 0x49206867,
+0x4220514E, 0x0A0D6675, 0x00000000, 0x000000FF,
+0x00020001, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x010E010D,
+0x00020003, 0x01090108, 0x0002010A, 0x02000003,
+0x02020201, 0x02040203, 0x02060205, 0x02020200,
+0x02040203, 0x020C0207, 0x020E020D, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x010E010D,
+0x00FF010F, 0x01090108, 0x010B010A, 0x020000FF,
+0x02020201, 0x02040203, 0x02060205, 0x02020200,
+0x02040203, 0x020C020B, 0x020E020D, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00205220,
+0x00000046, 0x00000059, 0x73204142, 0x003D7165,
+0x49544120, 0x0000204D, 0x00000000, 0x00000000,
+0x002E0209, 0x80000101, 0x000409FA, 0x00FF0400,
+0x05070000, 0x02000201, 0x82050700, 0x00020002,
+0x03830507, 0x07010040, 0x40020405, 0x02090000,
+0x0101002E, 0x09FA8000, 0x04000004, 0x000000FF,
+0x02010507, 0x07000040, 0x40028205, 0x05070000,
+0x00400383, 0x04050701, 0x00004002, 0x00000000,
+0x00000000, 0x07090000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, };
+
+const u32_t zcFwImageSize=13656;
diff --git a/drivers/staging/otus/hal/hpfwu_FB50_mdk.c b/drivers/staging/otus/hal/hpfwu_FB50_mdk.c
new file mode 100644
index 000000000000..ed1736f945ab
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwu_FB50_mdk.c
@@ -0,0 +1,721 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xD2287FFC, 0x0009420B,
+0x0009B019, 0x9446D526, 0xE600A003, 0x8D043642,
+0x60527601, 0x8DF9C840, 0xD4222F02, 0x4E0BDE22,
+0xD4220009, 0x00094E0B, 0x4E0BD421, 0x7F040009,
+0xA0254F26, 0x4F226EF6, 0x410BD11E, 0xD41E0009,
+0x0009440B, 0x450BD51D, 0xD71D0009, 0x611DE1FF,
+0x2712D21C, 0xD41C5029, 0xE1FFCB01, 0x1209E501,
+0x12112212, 0xD5192452, 0xD6199716, 0xE7002572,
+0x2670D218, 0x2272D618, 0x4F26E201, 0x2622000B,
+0xDD17DC16, 0x4C0BDE17, 0x4D0B0009, 0x4E0B0009,
+0xAFF80009, 0x27100009, 0x00000640, 0x0020095A,
+0x001C001C, 0x00202940, 0x00200E2A, 0x0020294C,
+0x00202964, 0x00200CF0, 0x00200F26, 0x002009C4,
+0x001C3510, 0x001C3624, 0x001E212C, 0x002028EC,
+0x00202850, 0x002028F4, 0x00202900, 0x00200BEC,
+0x00201FD4, 0x002017B8, 0x2FD62FC6, 0x4F222FE6,
+0xDEA17FA4, 0x61E0E01C, 0x7D016DE3, 0x61D00F14,
+0xD59FD49E, 0x450BE020, 0xE0200F14, 0xE78004FC,
+0x604C66E2, 0x7D7F677C, 0x1F693070, 0x2D628F17,
+0x01FCE01C, 0x641CE500, 0xD797DE96, 0x3243625D,
+0xA21A8B01, 0x655D0009, 0x31EC6153, 0xE0286C10,
+0x6D530FC4, 0x3D7C62CE, 0xAFEF2D20, 0x20087501,
+0xE01C8B15, 0xE50001FC, 0xD78BDE8A, 0x641CA00A,
+0x6C53655D, 0x66C23CEC, 0x66626253, 0x2262327C,
+0x1F697504, 0x3243625D, 0xA1F68BF2, 0x88012D10,
+0xE01C8B16, 0xE40001FC, 0x671C2D40, 0x624DDE7D,
+0x8B013273, 0x0009A1E9, 0x62E3644D, 0x72046D43,
+0x3DEC6143, 0x65D2312C, 0x74086C12, 0x25C2AFEF,
+0x8B188804, 0x01FCE01C, 0x2D40E400, 0xDE71671C,
+0x3273624D, 0xA1D08B01, 0x644D0009, 0x62E36D43,
+0x65D23DEC, 0x61437204, 0x6612312C, 0x74086C52,
+0xAFED2C69, 0x880525C2, 0xE01C8B18, 0xE40001FC,
+0x671C2D40, 0x624DDE63, 0x8B013273, 0x0009A1B5,
+0x6C43644D, 0x3CEC62E3, 0x720465C2, 0x3D2C6D43,
+0x615266D2, 0x216B7408, 0x2512AFED, 0x8B138830,
+0xE200DE58, 0x64E22D20, 0x8B042448, 0x420BD257,
+0xA19A0009, 0x55E10009, 0x57E356E2, 0xDD545CE4,
+0x2FC64D0B, 0x7F04A191, 0x89018828, 0x0009A0EA,
+0xE143DE4C, 0x622D62E1, 0x8F033217, 0x56FB1FEB,
+0x2621E240, 0x8B013217, 0x0009A0D5, 0xE1015EFB,
+0x301685E1, 0xA0CE8B01, 0xE4010009, 0x2D4055FB,
+0x6451B179, 0xE14357FB, 0xE0546271, 0x3517652D,
+0x0F568D41, 0x3563E640, 0xE6008B05, 0x0F65E034,
+0xA00FE11A, 0x615372C0, 0x41214121, 0x41214121,
+0x45214121, 0x45214521, 0xC9036053, 0xE0346603,
+0x71180F65, 0x2209E007, 0x641DE030, 0x0F2565F3,
+0x1F4EB1F1, 0x04FDE034, 0x674DE030, 0x47080CFD,
+0x607361CD, 0x4108D22B, 0xE00F0CFE, 0x1F1F420B,
+0x2CD96D07, 0x5EFB6073, 0x85E20FC6, 0x420B51FF,
+0x2C0B600D, 0x54FE6073, 0xB1BB0FC6, 0xE05465F3,
+0x652D62E1, 0xE6400F56, 0x89623563, 0xE050E100,
+0x60230F15, 0x4008C903, 0x6D034000, 0xE0406103,
+0xE0440FD6, 0xD217EEFF, 0x6EEC0FF6, 0x0F26E058,
+0x60E3420B, 0x42216253, 0x42214221, 0x66234221,
+0x326C4200, 0x45214200, 0xE0486707, 0x0F764521,
+0xC9036053, 0x40085CFB, 0x7C0630FC, 0x6E036D2D,
+0x1FD51FC6, 0x1F04A02E, 0x00117D00, 0x00202968,
+0x00200E2A, 0x00117D04, 0x00117D84, 0x00200700,
+0x0020074C, 0x00202034, 0x0FD6E04C, 0x05FEE044,
+0x64D3B189, 0x64E2E048, 0xE04006FE, 0x2E422469,
+0x01FE67C4, 0x667CE058, 0x420B02FE, 0x240B6063,
+0x05FEE044, 0xB15D2E42, 0xE05064D3, 0x7D0101FD,
+0x0F157101, 0x02FDE050, 0x3262E606, 0x56FB8BDC,
+0x55FB6261, 0x85514200, 0x302C750C, 0x6103701B,
+0x64F3E600, 0xE704A004, 0x76016256, 0x74042422,
+0x3273626D, 0x65F38BF8, 0x641DB13C, 0xB0D256FB,
+0xA0AA6461, 0xD4880009, 0xE201D588, 0x2D20450B,
+0x0009A0A3, 0x8B078829, 0xE200DE85, 0x66E22D20,
+0x646DB0A1, 0x0009A099, 0x622CE281, 0x8B3D3020,
+0xD680E738, 0xE0442D70, 0xE0480C6E, 0x6E621DC1,
+0x51611DE2, 0x54621D13, 0x55651D44, 0x57631D55,
+0x5C661D76, 0x0E6E1DC7, 0x1DE8E040, 0xE050016E,
+0x54641D19, 0x056E1D4A, 0x1D5BE04C, 0xE054076E,
+0x0C6E1D7C, 0x1DCDE058, 0xE044026E, 0xED001D2E,
+0xE04806D6, 0x16D126D2, 0x16D516D2, 0x16D616D3,
+0xE04006D6, 0xE05006D6, 0x06D616D4, 0x06D6E04C,
+0x06D6E054, 0x06D6E058, 0x1F29A057, 0x622CE282,
+0x89313020, 0x05FCE020, 0x625CE683, 0x3260666C,
+0xD65D8B07, 0x2650E500, 0x52617680, 0xA044D65B,
+0xE6902622, 0x3260666C, 0xD2578B16, 0xE500D658,
+0x60622250, 0xCB20D257, 0xE6052602, 0xD6562262,
+0x2252460B, 0x420BD255, 0xD2550009, 0x2262E601,
+0x4618D254, 0x2262A029, 0xD254D453, 0xD4546542,
+0x0009420B, 0x0009A021, 0xE524D647, 0xD5452650,
+0x16215257, 0x16225258, 0x16235259, 0x1624525A,
+0x1625525B, 0x1626525C, 0x1627525D, 0x1628525E,
+0x1F29525F, 0xE2001629, 0x15281527, 0x152A1529,
+0x152C152B, 0x152E152D, 0x7F5C152F, 0x6EF64F26,
+0x000B6DF6, 0x4F226CF6, 0xE240614D, 0x89173123,
+0x3127E21F, 0xD43B8908, 0xE001D53B, 0x6642450B,
+0x26796707, 0x2462A00C, 0x3127E23F, 0xD7358908,
+0x71E0D635, 0x460BE001, 0x62075571, 0x17512529,
+0x000B4F26, 0x4F220009, 0xE240614D, 0x89153123,
+0x3127E21F, 0xD42B8907, 0x6642D22B, 0xE001420B,
+0xA00B260B, 0xE23F2462, 0x89073127, 0xD626D725,
+0x71E05571, 0xE001460B, 0x1751250B, 0x000B4F26,
+0xE6400009, 0x46284618, 0x6252D520, 0x89FC2268,
+0x0009000B, 0x4618E680, 0xD51C4628, 0x22686252,
+0x000B89FC, 0xA0010009, 0x7201E200, 0x8BFC3242,
+0x0009000B, 0x4618E680, 0xD5154628, 0x22686252,
+0x000B8BFC, 0x00000009, 0x0020296C, 0x00200E2A,
+0x00117D04, 0x00202858, 0x00117D80, 0x002028EC,
+0x001C3500, 0x001D4004, 0x00200F26, 0x002009C4,
+0x001E212C, 0x001C3D28, 0x00117D00, 0x00200E8A,
+0x00202984, 0x001C3704, 0x00202034, 0x001C373C,
+0x001C3700, 0x4F222FE6, 0x6E537FFC, 0x2F42BFCA,
+0xD61561E2, 0x1615E280, 0x421854E1, 0x55E21646,
+0x16574228, 0x6EF257E3, 0x2E2B1678, 0x7F0426E2,
+0xAFA74F26, 0x2FC66EF6, 0x2FE62FD6, 0xDD0A4F22,
+0xBFAF6C53, 0xBF946E43, 0xBFAB2DE2, 0x51D50009,
+0x54D62C12, 0x55D71C41, 0x56D81C52, 0x4F261C63,
+0x6DF66EF6, 0x6CF6000B, 0x001C370C, 0x0009A0F8,
+0xD19B4F22, 0xD49B9299, 0x2122B00D, 0x9795E605,
+0xB0229595, 0xB0366463, 0xB03A0009, 0xB03D0009,
+0xA06C0009, 0x4F124F26, 0xD1934F02, 0x94873145,
+0x4609060A, 0x46094609, 0x00293646, 0xD78CD58F,
+0x2500CA01, 0x4F062762, 0x4F16000B, 0xBFEA4F22,
+0xB0230009, 0xA0520009, 0x2FE64F26, 0x6E63D188,
+0x44186612, 0x4528926D, 0x26294408, 0x44084500,
+0x4400265B, 0x4708264B, 0x47082162, 0x27EBD181,
+0x000B2172, 0xD1806EF6, 0xE603D480, 0x000B2162,
+0xD27F2462, 0xE40A9656, 0x2262AFB0, 0x2FC62FB6,
+0x2FE62FD6, 0xDC7B4F22, 0x2C22E201, 0xBFA5E40A,
+0x60C27C44, 0xCB01ED00, 0x60C22C02, 0xC901EB64,
+0x6E03A008, 0x89073DB2, 0xE40160C2, 0xBF95C901,
+0x7D016E03, 0x8BF52EE8, 0x8B033DB2, 0xD26FD46E,
+0x0009420B, 0x4F26E40A, 0x6DF66EF6, 0xAF856CF6,
+0x44116BF6, 0x604B8F01, 0x000B6043, 0x2F860009,
+0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6, 0x7FFC4F22,
+0x6DA3EA00, 0xDC626BA3, 0x9914E864, 0x8B4E2BB8,
+0x3AE3EE0A, 0x60C2894B, 0xCB02ED00, 0x62C22C02,
+0x2F0260C2, 0xA010C902, 0x096C6E03, 0x5BB45288,
+0x1FFF09B4, 0x01FF03C4, 0x89083D83, 0xE46460C2,
+0xC9022F02, 0x6E03BF52, 0x2EE87D01, 0xD1518BF4,
+0x54C1D551, 0x66526412, 0x6269EE01, 0x4220622F,
+0x622F4219, 0x4E182299, 0x8D0322E8, 0xE4FF6423,
+0x3428229A, 0x6572D749, 0x622F6259, 0x42194220,
+0x2299622F, 0x8D0322E8, 0xE6FF6623, 0x3628229A,
+0x3468BFA7, 0x30E2EE02, 0xAFB78901, 0xD240EB01,
+0x6EECEEE6, 0xBF21E40A, 0xAFAF22E2, 0xEE0A7A01,
+0x89013AE3, 0x8B033D83, 0xD234D43A, 0x0009420B,
+0x4F267F04, 0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6,
+0x68F6000B, 0x5651D534, 0x46286052, 0x306C000B,
+0x2FC62FB6, 0x2FE62FD6, 0x4F124F22, 0xBFF14F02,
+0x6B036E43, 0xDD1CDC2D, 0x0009BFEC, 0x3C0530B8,
+0x4609060A, 0x46014609, 0x020A3D65, 0x42094209,
+0x32E24209, 0x4F068BF0, 0x4F264F16, 0x6DF66EF6,
+0x000B6CF6, 0x2FE66BF6, 0xDE214F22, 0xE500E102,
+0x2E12E403, 0x2E52BFD4, 0x4618E606, 0xE403E700,
+0x2E722E62, 0xAFCB4F26, 0x4F226EF6, 0x0009BFEB,
+0xE6E6D213, 0xE40A666C, 0x2262BFC2, 0x4F26AFE3,
+0x002028F0, 0x0024CDE0, 0x10624DD3, 0x00202AF0,
+0x001C5814, 0x001C59D0, 0x001C59A4, 0x001C639C,
+0x001C5804, 0x001C581C, 0x00202998, 0x00200E2A,
+0x001C5860, 0x001C6864, 0x001C59BC, 0x001C69BC,
+0x001C947C, 0x002029B0, 0x001C1040, 0xCCCCCCCD,
+0x001D4004, 0x2F962F86, 0x2FB62FA6, 0x2FD62FC6,
+0x4F222FE6, 0xE4007FE4, 0x4528E510, 0x67436C43,
+0xE107A00F, 0x6043644D, 0x0F564008, 0xEE0060C3,
+0x815125C1, 0x81538152, 0x157315E2, 0x751415E4,
+0x624D7401, 0x8BED3213, 0xDA6F51F1, 0x1A1154F2,
+0xD16E2A12, 0x57F455F3, 0x6DF258F5, 0x1141D96C,
+0x11532142, 0x11751152, 0x11871174, 0x52F61186,
+0x19D1D668, 0xD86829D2, 0xDA68E950, 0x1621EBB4,
+0x6BBC2622, 0xA0214908, 0x6EEDEE00, 0x61E36DE3,
+0x41084D08, 0x31EC3DEC, 0x41084D08, 0x60C33D8C,
+0xE7904108, 0x81D12DC1, 0x41086093, 0x81D2677C,
+0x31AC60C3, 0x3472E200, 0x1DD281D3, 0xD4551D13,
+0x1D248D01, 0xB03AD450, 0x7E0165D3, 0x34B264ED,
+0xD14D8BDB, 0x6512DB52, 0x4529D24D, 0x64121B51,
+0x674DD14A, 0x67222B72, 0x4729D64E, 0x69221B73,
+0x689D2FD2, 0x69121B82, 0x5A122692, 0x5B1416A2,
+0x16B4DA44, 0x16C65C16, 0x16EA6EA2, 0x4F267F1C,
+0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6, 0x68F6000B,
+0x60616642, 0x8D04C803, 0x6061E500, 0x8802C903,
+0x52628B03, 0x51246563, 0x000B2412, 0x2FD66053,
+0x4F222FE6, 0x6E537FEC, 0xE5506253, 0xE4006D43,
+0xA0014508, 0x5224E101, 0x22116043, 0x81238121,
+0x81226053, 0x362056E2, 0xD22F8BF5, 0x64F316E4,
+0x420BE614, 0x65E165E3, 0x2549E4FC, 0x61F12E51,
+0x214965F3, 0x54D12F11, 0x410BD127, 0x57D1E614,
+0xCB016071, 0x1DE12701, 0x4F267F14, 0x000B6EF6,
+0x2FD66DF6, 0x4F222FE6, 0x6E537FEC, 0xE5FC6653,
+0x60616D43, 0xCB012059, 0x52E22601, 0x8B063260,
+0x51E212E4, 0x8B0431E0, 0xA00252D1, 0xAFF01E22,
+0xD2155664, 0xE61464F3, 0x65E3420B, 0xE1FC67E1,
+0x2E712719, 0x54D167F1, 0xD10F2719, 0xE61465F3,
+0x2F71410B, 0x602152D1, 0x2201CB01, 0x7F141DE1,
+0x6EF64F26, 0x6DF6000B, 0x002028BC, 0x002028C4,
+0x002028B4, 0x002028E4, 0x0010008C, 0x00100EC0,
+0x001E2108, 0x001C3D00, 0x00202194, 0x2FC62FB6,
+0x2FE62FD6, 0xD6314F22, 0x60D36D62, 0x894DC803,
+0xDB30DC2F, 0x0009A02C, 0xC9036061, 0x892B8801,
+0xD22DD42B, 0x0009420B, 0x65035603, 0xC8208561,
+0xE0508903, 0x720102BE, 0x85620B26, 0x4000600D,
+0x4000366A, 0x40004624, 0x206D4624, 0xD423C903,
+0x40086E03, 0xD1224000, 0x340C410B, 0x61E3D521,
+0xD721E001, 0x450BD221, 0x64E37E30, 0x2702420B,
+0x66C252C1, 0x8BCF3620, 0x4E18EE01, 0xA011DB1C,
+0x6061EC75, 0x8801C903, 0xD4198910, 0x460BD612,
+0xD4180009, 0x470BD718, 0xD2136503, 0x64C3D113,
+0x22E2410B, 0x66B252B1, 0x8BEA3620, 0xC80460D3,
+0xD2128906, 0x6EF64F26, 0x6CF66DF6, 0x6BF6422B,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x001E2100,
+0x002028BC, 0x00202858, 0x00200AE0, 0x002028C4,
+0x00200B62, 0x00202034, 0x001C3D30, 0x00200DF0,
+0x002028B4, 0x002028E4, 0x00200AFE, 0x002000F8,
+0xE601D237, 0x1265D537, 0x000B2252, 0xD6361266,
+0x88016062, 0xE1018B62, 0xD5342612, 0x5451D134,
+0xE0406212, 0x2122324C, 0x54115752, 0x1141347C,
+0x57125453, 0x1172374C, 0x52135755, 0x1123327C,
+0x56146452, 0x1164364C, 0x54155754, 0x1145347C,
+0x56165458, 0x1166364C, 0x6762D626, 0x327C5217,
+0x57611127, 0x327C5218, 0x57621128, 0x327C5219,
+0x57631129, 0x347C541A, 0x5764114A, 0x347C541B,
+0x5765114B, 0x347C541C, 0x5266114C, 0x372C571D,
+0x5267117D, 0x342C541E, 0x5268114E, 0x362C561F,
+0xD615116F, 0x041E6262, 0x342C7694, 0xE0440146,
+0x061E6262, 0x0166362C, 0x525CE048, 0xD60F051E,
+0x0156352C, 0xE0546262, 0x4229051E, 0x0156352C,
+0xE0585561, 0x4529061E, 0x0166365C, 0x0009000B,
+0x001C1010, 0x0000C34F, 0x001C1028, 0x001C369C,
+0x00202858, 0x001C3CA0, 0x001C36F4, 0x001C3B88,
+0xD62F7FFC, 0x2642644C, 0xC8205066, 0x2F028DFC,
+0x7F04000B, 0x2FD62FC6, 0x4F222FE6, 0x6D436C53,
+0xEE00A004, 0x7E0164D4, 0x644CBFEA, 0x8BF93EC2,
+0x6EF64F26, 0x000B6DF6, 0xA0016CF6, 0x76016643,
+0x22286260, 0x36488BFB, 0x6563AFE4, 0x2FB62F96,
+0x2FD62FC6, 0x4F222FE6, 0xEC1CED08, 0xDB196E53,
+0x61C3E90A, 0x60434B0B, 0x3092C90F, 0x66038D02,
+0x7630A001, 0x4D107637, 0x7E012E60, 0x7CFC8FF1,
+0x8058E000, 0x6EF64F26, 0x6CF66DF6, 0x000B6BF6,
+0x000B69F6, 0x000BE000, 0x2FE6E000, 0x7FEC4F22,
+0x6E436253, 0xBFD165F3, 0xBFC66423, 0xBFC464E3,
+0xD40564F3, 0x0009BFC1, 0x4F267F14, 0x6EF6000B,
+0x001C0004, 0x002020F4, 0x002029CC, 0xE110D59C,
+0xE6406050, 0x2500C9FD, 0xE0FF75E9, 0x80516453,
+0x80538052, 0x80568055, 0x251075EF, 0xE1EF6250,
+0x2219E001, 0xE7202520, 0x24608052, 0x2570000B,
+0xE4FDD590, 0xE7026152, 0x25122149, 0x74016052,
+0x2502CB01, 0xD18C6652, 0x25622649, 0x92C26012,
+0x2102CB08, 0xC9CF6012, 0x60122102, 0x2102CB03,
+0x000B1172, 0x4F221123, 0xE100D484, 0xD285D784,
+0xD5852410, 0x2711D485, 0x2211E700, 0xBFBD2511,
+0xD5832471, 0x2560E600, 0x4F26AFD2, 0xD281664C,
+0x362C4600, 0xCB106060, 0x2600000B, 0xD27D654C,
+0x352C4500, 0xE1EF6650, 0x000B2619, 0x664C2560,
+0x4600D279, 0x6060362C, 0x000BCB10, 0x654C2600,
+0x4500D275, 0x6650352C, 0x2619E1EF, 0x2560000B,
+0xD270664C, 0x362C4600, 0xCB086060, 0x2600000B,
+0xD26C654C, 0x352C4500, 0xE1F76650, 0x000B2619,
+0x664C2560, 0x4600D268, 0x6060362C, 0x000BCB08,
+0x654C2600, 0x4500D264, 0x6650352C, 0x2619E1F7,
+0x2560000B, 0xD65F624C, 0x326C4200, 0xC9086020,
+0x40214021, 0x000B4021, 0x624C600C, 0x4200D65A,
+0x6020326C, 0x4021C908, 0x40214021, 0x600C000B,
+0xD156644C, 0x341C74FF, 0x000B6240, 0xD154602C,
+0x341C644C, 0x000B6240, 0x2FE6602C, 0x655C4F22,
+0x3567E60A, 0x6E438D15, 0x6453BFEA, 0x60EC640C,
+0x8B028801, 0xA002E00F, 0x44092409, 0x624C4409,
+0x3263E60A, 0xBFE28905, 0x620C644C, 0xC8806023,
+0xE2008B00, 0x4F266023, 0x6EF6000B, 0xD6414F22,
+0x88016062, 0xB2228B03, 0xA0030009, 0xD23E0009,
+0x2260E640, 0xE200D63D, 0x000B4F26, 0x4F222622,
+0x6062D638, 0x8B018802, 0x0009B26C, 0xE200D637,
+0x000B4F26, 0x0FFF2622, 0xD433D532, 0xE701E100,
+0x000B2512, 0xD2302470, 0x000BE604, 0xD5202260,
+0x6150E4FD, 0x2149D62E, 0x2510E700, 0x2670000B,
+0xE4FBD51B, 0x22496250, 0x2520000B, 0xE4F7D518,
+0x22496250, 0x2520000B, 0xD2264F22, 0x600D8522,
+0x89112008, 0x89138801, 0x89158803, 0x89178805,
+0x89418806, 0x89478808, 0x894D8809, 0x8953880A,
+0x8959880B, 0x0009A060, 0x0009B062, 0x600CA05D,
+0x0009B070, 0x600CA059, 0x0009B07A, 0x600CA055,
+0x6260D606, 0x8B4F2228, 0x0009B086, 0x600CA04D,
+0x001E1028, 0x001E2148, 0x001E1108, 0x0020293D,
+0x0020292C, 0x0020292E, 0x00202930, 0x00202910,
+0x001E1008, 0x001E103F, 0x001E105F, 0x001E1030,
+0x001E1090, 0x00202938, 0x001E100B, 0x00202934,
+0x0020293C, 0x00202904, 0x6260D687, 0x8B232228,
+0x0009B06A, 0x600CA021, 0x6260D683, 0x8B1B2228,
+0x0009B0B4, 0x600CA019, 0x6260D67F, 0x8B132228,
+0x0009B0BA, 0x600CA011, 0x6260D67B, 0x8B0B2228,
+0x0009B11E, 0x600CA009, 0x6260D677, 0x8B032228,
+0x0009B136, 0x600CA001, 0x4F26E000, 0x0009000B,
+0xD273D172, 0xD5738412, 0x4000C90F, 0xD772012D,
+0x611CE403, 0xD671E20F, 0x27122540, 0xE0012520,
+0x2602000B, 0xE601D269, 0x30668523, 0xE0008D06,
+0xE000D267, 0x8122D669, 0x2602E001, 0x0009000B,
+0x8523D262, 0x2008600D, 0x88018905, 0xD6648B0A,
+0xCB016060, 0xD6612600, 0xE101D45D, 0x2612E001,
+0x8142000B, 0xE000000B, 0xE501D158, 0x45188513,
+0x3453640D, 0x8D056603, 0xD25AE000, 0xE001D557,
+0x25022260, 0x0009000B, 0xD1504F22, 0x650D8513,
+0x44196453, 0x672E6249, 0x602C227D, 0x89098801,
+0x890C8802, 0x89108803, 0x89268806, 0x89298807,
+0x0009A038, 0xD64DD54C, 0xA027E212, 0x625C2652,
+0x8B2F2228, 0xA01ED64A, 0x605C6262, 0x89052008,
+0x89088810, 0x890B8820, 0x0009A024, 0xD643D445,
+0xA013E204, 0xD7442642, 0xE20CD640, 0x2672A00E,
+0xD63ED542, 0xA009E218, 0xD4412652, 0xE20AD63B,
+0x2642A004, 0xD639D23F, 0xE22E2622, 0xD43E8515,
+0x3277670D, 0x8F012421, 0x24516503, 0x0009B0DF,
+0xE001A001, 0x4F26E000, 0x0009000B, 0xE101D629,
+0x2610D436, 0xD7286541, 0x655DD128, 0xE001E20F,
+0x26202752, 0x2102000B, 0x4F222FE6, 0x8523D21F,
+0x2448640C, 0xD62D8B08, 0xE200D521, 0x84512621,
+0x20499430, 0x8051A026, 0x60E0DE1D, 0x8D0BC840,
+0x3427E201, 0xD1258922, 0x420BD225, 0xD5252141,
+0xCB046052, 0x2502A00B, 0x89173427, 0xD722D21F,
+0x2241470B, 0xE5FBD61F, 0x21596162, 0x84E12612,
+0xB12DCB80, 0x60E080E1, 0xCB04D61C, 0x60602E00,
+0x2600C93F, 0xE001D609, 0x2602A001, 0x4F26E000,
+0x6EF6000B, 0x0000FF7F, 0x0020293D, 0x00202904,
+0x00202910, 0x001E1100, 0x001E100C, 0x00202934,
+0x001E1000, 0x001E1001, 0x00202AF4, 0x00202918,
+0x00202920, 0x00202B62, 0x00202B66, 0x00202B72,
+0x00202B8A, 0x00202B94, 0x0020291C, 0x0020292A,
+0x00201AB6, 0x001E1108, 0x00201BC2, 0x001E1015,
+0x6060D696, 0x8919C880, 0x6021D295, 0x8B158801,
+0xE501D294, 0x30568524, 0xD1938910, 0xD493E203,
+0x65412120, 0x655DE00B, 0xD5910656, 0xE702E40F,
+0x25712140, 0xE001D78F, 0x2702000B, 0xE000000B,
+0x4F222FE6, 0x84E1DE8C, 0x8934C880, 0x8554D585,
+0x8F302008, 0xD7896103, 0x66728553, 0x650C6403,
+0x620C8566, 0x8B263520, 0xD780D685, 0x644C651C,
+0x27412651, 0xC84060E0, 0xD2828907, 0x0009420B,
+0x6062D681, 0xA008CB04, 0xD1802602, 0x0009410B,
+0xE5FBD67D, 0x24596462, 0xB0A12642, 0xD5750009,
+0x2522E201, 0xD77A60E0, 0x2E00CB04, 0xC93F6070,
+0xA0012700, 0xE0006023, 0x000B4F26, 0x2FA66EF6,
+0x2FC62FB6, 0x2FE62FD6, 0xE240DA69, 0xDC6666A1,
+0x3123616D, 0x62638900, 0x6ED36D2C, 0x4E2136D8,
+0x4E212A61, 0xDB6CD46B, 0xE700A00F, 0x770166B2,
+0x71026163, 0x65612B12, 0x71026613, 0x62612B12,
+0x622D655D, 0x325C4228, 0x627C2422, 0x8BED32E3,
+0xC90360D3, 0x8B108803, 0xED076EB2, 0x710261E3,
+0x67132B12, 0x62E17102, 0x65712B12, 0x655D622D,
+0x352C4528, 0xA00C2CD0, 0x88022452, 0xA0038B01,
+0x8801E203, 0xE2018B05, 0x66B22C20, 0x677D6761,
+0xEB0F2472, 0x6DA12CB0, 0x8B052DD8, 0xD445D24F,
+0xE101EE00, 0x241222E2, 0x6DF66EF6, 0x6BF66CF6,
+0x6AF6000B, 0x2FE62FD6, 0xE240DD3D, 0x616D66D1,
+0x89003123, 0x672C6263, 0xDE433678, 0x2D617703,
+0xD6404721, 0x472164E2, 0xE100A00E, 0x71016562,
+0x24506253, 0x42197401, 0x74012420, 0x24504529,
+0x45197401, 0x74012450, 0x3273621C, 0x42008BEE,
+0x64D166E2, 0x362C4200, 0x8F062448, 0xDD332E62,
+0xE500DE28, 0x2D52E701, 0x6EF62E72, 0x6DF6000B,
+0x2FE62FD6, 0xEE014F22, 0xED0AA005, 0x64E3BCB6,
+0x64E3BCBC, 0x62EC7E01, 0x8BF732D7, 0xEE01A005,
+0x64E3BCBD, 0x64E3BCC3, 0x62EC7E01, 0x8BF732D7,
+0x6EF64F26, 0x6DF6000B, 0x2FE62FD6, 0x7FFC4F22,
+0x6060D61F, 0x89758801, 0xE101D41E, 0xD7128548,
+0x650D2610, 0x45196070, 0x6659DD1B, 0x61D3626E,
+0xC840262D, 0x74027102, 0x8D47D718, 0xD218666C,
+0xE501DE0A, 0xA0312E22, 0x0000EE04, 0x001E1001,
+0x0020292A, 0x00202904, 0x001E1100, 0x0020292E,
+0x0020291C, 0x00202934, 0x001E1000, 0x00202920,
+0x0020292C, 0x00201AB6, 0x001E1108, 0x00201BC2,
+0x001E1015, 0x001E100C, 0x00202918, 0x00202938,
+0x0020293C, 0x00202AF4, 0x00202B8A, 0x00202B96,
+0x00202B06, 0x75016245, 0x71022121, 0x32E3625C,
+0x60638BF8, 0xE60181D4, 0xE417D538, 0x3243626C,
+0x6255891E, 0x27217601, 0x7702AFF8, 0xDE35D234,
+0x2E22E501, 0xEE04A004, 0x75016245, 0x71022121,
+0x32E3625C, 0x60638BF8, 0xE60181D4, 0xA004D52E,
+0x6255E417, 0x27217601, 0x626C7702, 0x8BF83243,
+0x2D21924B, 0xD72AD429, 0x2F126142, 0x6DF265F2,
+0xC9806053, 0x60532700, 0x6103C960, 0x60538071,
+0x65F26EF2, 0x4D19C903, 0x80724529, 0x451960DC,
+0x4E298172, 0x62EC605C, 0x302C4018, 0x6D428173,
+0x2FD22118, 0x62F26EF2, 0x421966F2, 0x656C4629,
+0x602C66F2, 0x401864EC, 0x304C4629, 0x81744619,
+0x4018606C, 0x8F07305C, 0xBCB58175, 0x620C0009,
+0x89082228, 0x0009A00A, 0x88406013, 0xB00A8B03,
+0xA0030009, 0xD60B0009, 0x2622E202, 0x4F267F04,
+0x000B6EF6, 0x000B6DF6, 0x060A0009, 0x00202B36,
+0x00202B34, 0x00202920, 0x00202B08, 0x001E100C,
+0x00202904, 0x00202934, 0x7FFC4F22, 0x6620D27E,
+0x8D082668, 0xD47D2F60, 0x420BD27D, 0x64F00009,
+0xA0907F04, 0x7F044F26, 0x000B4F26, 0x000B0009,
+0x2FE60009, 0xDE774F22, 0x60E0D677, 0xCBC0D477,
+0x62602E00, 0xC803602C, 0x40218904, 0x70014021,
+0x6603A002, 0x66034009, 0xD671616D, 0xE500A004,
+0x75016262, 0x74042422, 0x3213625D, 0xD16D8BF8,
+0x0009410B, 0xE401D66C, 0x84E22641, 0x80E2C9BF,
+0x000B4F26, 0x2FE66EF6, 0xD5687FFC, 0x6250DE61,
+0x642C84E2, 0xCB407404, 0x80E2614D, 0x44216413,
+0xD7634421, 0xE600A004, 0x76016256, 0x27222F22,
+0x3243626D, 0x60138BF8, 0x2008C903, 0x88038912,
+0x88028905, 0x88018906, 0xA0088907, 0xE0070009,
+0x8078A005, 0xA002E003, 0xE0018078, 0x62528078,
+0x27222F22, 0xD650E00F, 0x60618078, 0x8B018801,
+0x2621E200, 0x6060D64F, 0x2600CB08, 0xC93F60E0,
+0x7F042E00, 0x6EF6000B, 0x6021D247, 0x8D188801,
+0xD2466143, 0x22106053, 0x60638021, 0xD4468121,
+0xE500A007, 0x027C605D, 0x364C6603, 0x26207001,
+0x625D6503, 0x3213611C, 0xD6408BF4, 0xC9BF6060,
+0x000B2600, 0x2FD60009, 0x4F222FE6, 0x60437FFC,
+0x8D02C820, 0xBF6A6E43, 0x60E30009, 0x8901C810,
+0x0009BF67, 0xC84060E3, 0xBF8C8901, 0x60E30009,
+0x8929C801, 0x60D0DD32, 0x8D03C802, 0xD6312F00,
+0x0009460B, 0xC80460F0, 0xD62F8902, 0x0009460B,
+0x602362F0, 0x8902C880, 0xC97F60D0, 0x60232D00,
+0x8902C801, 0x420BD229, 0xD5290009, 0x88026052,
+0xD2288B03, 0xA005E604, 0x88012260, 0xD2258B02,
+0x2260E601, 0x2522E200, 0xC88060E3, 0xD2228916,
+0x60E36E20, 0x8902C802, 0x420BD220, 0x60E30009,
+0x8902C804, 0x420BD21E, 0x60E30009, 0x8905C808,
+0x7F04D21C, 0x6EF64F26, 0x6DF6422B, 0x4F267F04,
+0x000B6EF6, 0x00006DF6, 0x001E1020, 0x002029D0,
+0x00200E2A, 0x001E1015, 0x001E10BF, 0x00117D00,
+0x001E10FC, 0x002000F8, 0x00202930, 0x00117D80,
+0x001E10F8, 0x001E10AE, 0x00117D84, 0x001E1017,
+0x001E1021, 0x0020105C, 0x0020107E, 0x00201608,
+0x00202934, 0x001E100B, 0x001E1028, 0x002010AE,
+0x002010C0, 0x002010CC, 0xD6A8644C, 0x346C74FF,
+0x2450000B, 0x644CD6A6, 0x000B346C, 0xD6A52450,
+0x346C644C, 0x2450000B, 0x616D625C, 0x41194208,
+0x60194208, 0x644C4200, 0x324C670E, 0x207DD19E,
+0xC90F4200, 0x000B321C, 0x67632200, 0x4208625C,
+0x42004208, 0x324C644C, 0x4200D198, 0x000B321C,
+0x2FE62270, 0x614C4F12, 0x4100D493, 0x6710314C,
+0x2729E29F, 0x65736E53, 0x4719676D, 0x672E6279,
+0x4221227D, 0x42214221, 0x7601662C, 0xE4014608,
+0x34E84608, 0x644C4600, 0x0E1A0467, 0x215025EB,
+0x000B4F16, 0x4F226EF6, 0xD2857FE8, 0x88016021,
+0xD2848B7B, 0x26686621, 0xD2838B77, 0x26686621,
+0xE50F8B73, 0xE401BFA0, 0xBFA3E501, 0xE586E400,
+0xE400655C, 0x2F50BFA3, 0xBFA0E401, 0xE602E506,
+0x60634618, 0x81F2E401, 0x6543BF9E, 0xE40185F2,
+0xBFAA6543, 0x85F26603, 0x6543E401, 0x6603BFB1,
+0xE40265F0, 0x6053756C, 0x80F8BF7E, 0xBF81E402,
+0x84F8E512, 0x7090E402, 0x6503BF81, 0x4618E602,
+0x81F66063, 0xBF7FE402, 0x85F6E500, 0x6603E402,
+0xE500BF8B, 0xE40285F6, 0xBF926603, 0xE5FEE500,
+0xE010655C, 0xBF5FE403, 0xE5130F54, 0xE40EBF62,
+0x05FCE010, 0xBF62E40E, 0xE5007585, 0xBF63E403,
+0xE500E640, 0xBF70E403, 0xE500E640, 0xBF78E403,
+0xE5FFE640, 0xE014655C, 0xBF45E404, 0xE40F0F54,
+0xE504BF48, 0x05FCE014, 0xBF48E40F, 0xE5017584,
+0xBF49E640, 0xE501E404, 0xBF56E640, 0xE501E404,
+0xE404E640, 0xAF5C7F18, 0x7F184F26, 0x000B4F26,
+0x4F220009, 0xD2427FF0, 0x88016021, 0xD2418B71,
+0x26686621, 0xD2408B6D, 0x26686621, 0xE50F8B69,
+0xE401BF1A, 0xBF1DE501, 0xE586E400, 0xE400655C,
+0x2F50BF1D, 0xBF1AE401, 0xE401E506, 0xBF1B6543,
+0xE401E640, 0xBF286543, 0xE401E640, 0xBF306543,
+0x65F0E640, 0x756CE402, 0xBEFD6053, 0xE40280F4,
+0xE512BF00, 0xE40284F4, 0xBF007090, 0xE6406503,
+0xBF01E402, 0xE640E500, 0xBF0EE402, 0xE640E500,
+0xBF16E402, 0xE5FEE500, 0x6053655C, 0xBEE3E403,
+0xE51380F8, 0xE40EBEE6, 0xE40E84F8, 0xBEE67085,
+0xE5006503, 0xBEE7E640, 0xE500E403, 0xBEF4E640,
+0xE500E403, 0xBEFCE640, 0xE5FFE403, 0x6053655C,
+0xBEC9E404, 0xE40F80FC, 0xE504BECC, 0xE40F84FC,
+0xBECC7083, 0xE5016503, 0xBECDE640, 0xE501E404,
+0xBEDAE640, 0xE501E404, 0xE404E640, 0xAEE07F10,
+0x7F104F26, 0x000B4F26, 0x00000009, 0x001E1030,
+0x001E1080, 0x001E1090, 0x001E103F, 0x001E103E,
+0x0020292A, 0x0020292C, 0x0020292E, 0x0009000B,
+0x666CE680, 0x6563D2A0, 0x7540E700, 0x6473422B,
+0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6, 0x4C18EC01,
+0xDA9BDB9A, 0x65B252B1, 0x89223520, 0xC9036051,
+0x891E8801, 0xD197DE95, 0x64E3410B, 0x85036503,
+0x670D66A2, 0xDD943762, 0xD494890A, 0x420BD294,
+0xD1940009, 0xE701D494, 0x21724D0B, 0x0009AFE2,
+0x420BD292, 0xD69264E3, 0x4D0BD492, 0xAFD926C2,
+0x4F260009, 0x6DF66EF6, 0x6BF66CF6, 0x6AF6000B,
+0x7FF44F22, 0xE6818546, 0x85472F01, 0x81F1666C,
+0xD27D8548, 0x854281F2, 0x81F367F3, 0xE40C8543,
+0x605381F4, 0x81F56563, 0x7540420B, 0x4F267F0C,
+0x0009000B, 0x2F962F86, 0x2FB62FA6, 0x2FD62FC6,
+0x4F222FE6, 0xE2007FEC, 0xA0CBDB7B, 0x6A132F21,
+0x4A08D27A, 0xDE7AE001, 0x4A00420B, 0x7E303AEC,
+0x1F021FE1, 0x66B2DD77, 0x362052B1, 0xA0B58B01,
+0x60610009, 0x8801C903, 0xA0AF8B01, 0x85610009,
+0x8974C801, 0xEE105163, 0xDC638512, 0xC9036603,
+0x85136403, 0x4021600D, 0xC93F4021, 0x8D2030E3,
+0xD7696503, 0x62704408, 0x44004408, 0x22284500,
+0x345C8F0C, 0x6043D265, 0x625D052D, 0x60294219,
+0x207D670E, 0x605C81F6, 0x81F8A00B, 0x6043D260,
+0x685D052D, 0x60894819, 0x209D690E, 0x605C81F6,
+0xD75C81F8, 0x22286272, 0xE0FF8902, 0x81F8600C,
+0xEEFF85F8, 0x6EEC650D, 0x8B0F35E0, 0x4E0BDE45,
+0x540364B3, 0xBF7BE502, 0xD4536803, 0x410BD147,
+0xD7526583, 0xD452E901, 0x2792A020, 0x26E9EEFC,
+0x81126063, 0x946E8513, 0x81132049, 0x45088512,
+0x62036953, 0xE50885F6, 0x8112202B, 0x45188513,
+0x8113209B, 0xD4478514, 0x8114205B, 0x851161B2,
+0x811120E9, 0x602162B2, 0x2201CB01, 0x00094C0B,
+0x56F160B2, 0xCB0152F2, 0xAF7C2A02, 0x85612622,
+0xC802DC3A, 0xD938D227, 0x8D0FD82C, 0x420B64B3,
+0x65030009, 0x480B6493, 0xE8015E03, 0x85EF2C82,
+0x650DD635, 0x64D3460B, 0x0009AF65, 0x0009420B,
+0x6E035403, 0xE5088544, 0x45186103, 0x31502159,
+0xBF258B03, 0xA007E501, 0x85410009, 0x620DD52B,
+0x89012258, 0xE500BF1C, 0x480B6493, 0xD42865E3,
+0xE801D611, 0x2C82460B, 0x0009AF45, 0x7B0862F1,
+0x2F217201, 0xEE0362F1, 0x31E7612D, 0xAF2E8901,
+0x7F140009, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0xFE0368F6, 0x002018B8, 0x002028E4,
+0x002028EC, 0x00200AE0, 0x00200E2A, 0x002028B4,
+0x00200B62, 0x001E2130, 0x00202AD4, 0x00200AFE,
+0x001C3D30, 0x00202AD8, 0x002028C4, 0x00202034,
+0x001C3D00, 0x00202AE4, 0x00202AF0, 0x002029D4,
+0x00202A54, 0x00202900, 0x002028BC, 0x001E212C,
+0x00202ADC, 0x00202AE0, 0x00200E8A, 0x00008000,
+0x00202AEC, 0x4F222FE6, 0x6E22D20D, 0xC84060E3,
+0x22E28D02, 0x0009BE7A, 0x4218E240, 0x89012E28,
+0x0009BE76, 0xC80560E3, 0xBECB8901, 0x60E30009,
+0x8902C802, 0xAE734F26, 0x4F266EF6, 0x6EF6000B,
+0x001C3510, 0x080A0C0E, 0x00020406, 0x1A1C1E20,
+0x12141618, 0x2E303234, 0x26282A2C, 0x3A3C3E40,
+0x6C625648, 0x41112F26, 0xE2208F18, 0x890B3123,
+0x321CD204, 0xD1026220, 0x412B312C, 0x00090009,
+0x0020205E, 0x00202014, 0x000BE000, 0x400062F6,
+0x40004000, 0x40004000, 0x40004000, 0x62F6000B,
+0x40004000, 0x40004000, 0x40004000, 0x40184000,
+0x62F6000B, 0x40004000, 0x40004000, 0x40004000,
+0x40284000, 0x62F6000B, 0x40004000, 0x40184000,
+0x000B4028, 0xC90F62F6, 0x40054005, 0x40054005,
+0x62F6000B, 0x4005C907, 0x40054005, 0x62F6000B,
+0x4005C903, 0x000B4005, 0xC90162F6, 0x000B4005,
+0x000062F6, 0x080A0C0E, 0x00020406, 0x1A1C1E20,
+0x12141618, 0x2E303234, 0x26282A2C, 0x3A3C3E40,
+0x6C625648, 0x41112F26, 0xE2208F18, 0x890B3123,
+0x321CD204, 0xD1026220, 0x412B312C, 0x00090009,
+0x0020211E, 0x002020D4, 0x000BE000, 0x400162F6,
+0x40014001, 0x40014001, 0x40014001, 0x62F6000B,
+0x40014001, 0x40014001, 0x40014001, 0x40194001,
+0x62F6000B, 0x40014001, 0x40014001, 0x40014001,
+0x40294001, 0x62F6000B, 0x40014001, 0x40194001,
+0x000B4029, 0x400462F6, 0x40044004, 0xC90F4004,
+0x62F6000B, 0x40044004, 0xC9074004, 0x62F6000B,
+0x40044004, 0x000BC903, 0x400462F6, 0x000BC901,
+0x000062F6, 0x3622E218, 0x67438F12, 0x0009A004,
+0x76FF6254, 0x74012420, 0xC8036053, 0x60438BF8,
+0x8902C803, 0x422BD22B, 0xD22B0009, 0x0009422B,
+0x2FE66473, 0x8D4A3450, 0x27786763, 0x62438947,
+0x227B225B, 0xC9016023, 0x8D203452, 0x2EE86E03,
+0x60238B15, 0x8B08C803, 0x47096643, 0x47106256,
+0x8FFB2622, 0xA0327604, 0x47010009, 0x61436673,
+0x46106255, 0x8FFB2121, 0xA0287102, 0x66430009,
+0x47106254, 0x8FFB2620, 0xA0207601, 0x61430009,
+0x2EE8357C, 0x8F15317C, 0x60236653, 0x8B07C803,
+0x76FC4709, 0x47106262, 0x21268FFB, 0x0009A00F,
+0x65634701, 0x75FE6673, 0x46106251, 0x21258FFB,
+0x0009A005, 0x626076FF, 0x8FFB4710, 0x60432124,
+0x6EF6000B, 0x00202306, 0x002027B2, 0xE21E2FE6,
+0x67633626, 0x8D1B6153, 0x3E106E43, 0x3E128916,
+0x65E38908, 0x3672E600, 0x62148910, 0x25207601,
+0x7501AFF9, 0x317C64E3, 0x6513347C, 0xE600A004,
+0x625075FF, 0x24247601, 0x8BF93672, 0x60E3A011,
+0x890831E2, 0x327C6213, 0x8B0432E6, 0x651364E3,
+0xA0086673, 0xD28F6EF6, 0x651364E3, 0x422B6673,
+0x000B6EF6, 0xE2046EF6, 0x67433622, 0x8F10356C,
+0xA004346C, 0x75FF0009, 0x76FF6250, 0x60532424,
+0x8BF8C803, 0xC8036043, 0xA1058901, 0xA2770009,
+0xA2990009, 0x2FB60009, 0x2FD62FC6, 0x7FE42FE6,
+0x6C636043, 0x66521F62, 0xC9037504, 0x1F516E53,
+0x45086503, 0xE1FC6D43, 0x2D194500, 0x1F732558,
+0x1F651F44, 0x2FD28D0B, 0x88086053, 0x88108923,
+0x8818895B, 0xA0898B01, 0xA0BD0009, 0x62630009,
+0x2D22E600, 0x7CFC7D04, 0xEB10A00D, 0xE60064E6,
+0x7CF065E6, 0x62E261E6, 0x1D512D42, 0x1D231D12,
+0x7E047D10, 0x3CB21FE1, 0x1F6589F0, 0x2FD21FC2,
+0xA0A11FE6, 0x64D21FD4, 0x44286263, 0x44294418,
+0x42184419, 0x4629242B, 0x2D424619, 0x65637D04,
+0xA0217CFD, 0x67E6EB10, 0x62E67CF0, 0x64E66673,
+0x256B4618, 0x2D5261E2, 0x65234729, 0x45184719,
+0x4229275B, 0x42191D71, 0x47186743, 0x4429227B,
+0x44196713, 0x247B4718, 0x1D431D22, 0x41194129,
+0x65137D10, 0x1FE17E04, 0x89DC3CB2, 0x1FE67EFF,
+0x1FC21F55, 0xA0672FD2, 0x6CF21FD4, 0x66C257F5,
+0x46286273, 0x42284629, 0x2C62262B, 0x7C045DF2,
+0x7DFE4729, 0xA01CEB10, 0x65E65EF1, 0x66E66273,
+0x47286753, 0x6763227B, 0x452961E6, 0x257B4728,
+0x2C2264E6, 0x65131C51, 0x45284629, 0x1C62265B,
+0x41296643, 0x216B4628, 0x44291C13, 0x67437C10,
+0x3DB27DF0, 0x1FD289E1, 0x7EFEA034, 0x51F56CF2,
+0x621366C2, 0x42284618, 0x42184619, 0x2C62262B,
+0x7C045DF2, 0x7DFF4119, 0xA01FEB10, 0x65E65EF1,
+0x64E67DF0, 0x42286253, 0x421867E6, 0x66E6212B,
+0x61432C12, 0x45194128, 0x251B4118, 0x65731C51,
+0x44194528, 0x245B4518, 0x64631C42, 0x47194428,
+0x274B4418, 0x46191C73, 0x61637C10, 0x89DE3DB2,
+0x7EFD1FD2, 0x1FC41FE6, 0x5DF2E704, 0xA00D5EF6,
+0x62E451F4, 0x66E47DFC, 0x65E464E4, 0x71012120,
+0x71012160, 0x71012140, 0x71012150, 0x89F03D72,
+0x66D357F3, 0x641365E3, 0x6EF67F1C, 0x6CF66DF6,
+0x6BF6A190, 0x00202194, 0x2FC62FB6, 0x2FE62FD6,
+0x60437FE4, 0x6C63C903, 0x66031F62, 0x460875FC,
+0x61526E43, 0x4600E2FC, 0x26682E29, 0x1F441F73,
+0x1F516D53, 0x8D0B1F15, 0x60632FE2, 0x891F8808,
+0x89538810, 0x8B018818, 0x0009A081, 0x0009A0B9,
+0xEB10A00D, 0x52D37DF0, 0x54D156D2, 0x2E1665D2,
+0x2E662E26, 0x2E427EFC, 0x1FD16153, 0x3CB27CF0,
+0x7D0489F0, 0x1F151FD6, 0x2FE21FC2, 0x1FE4A0A1,
+0x621366E2, 0x42294619, 0x42194618, 0x2E62262B,
+0x7CFF4118, 0xEB10A021, 0x54D37DF0, 0x624357D2,
+0x42194229, 0x55D1212B, 0x2E1666D2, 0x41296173,
+0x41194418, 0x2E46241B, 0x44296453, 0x44194718,
+0x2E76274B, 0x47296763, 0x47194518, 0x257B7EFC,
+0x46182E52, 0x1FD16163, 0x3CB27CF0, 0x7D0389DC,
+0x1F151FD6, 0x2FE21FC2, 0x1FE4A06B, 0x57F56EF2,
+0x627366E2, 0x46284629, 0x262B4229, 0x2E625CF2,
+0x7CFE4728, 0xA01BEB10, 0x7DF05DF1, 0x55D251D3,
+0x46296613, 0x54D1276B, 0x2E7662D2, 0x41286753,
+0x217B4729, 0x61432E16, 0x41294528, 0x2E56251B,
+0x44286523, 0x245B4529, 0x42282E46, 0x7CF06723,
+0x89E23CB2, 0x1FD67D02, 0xA03A1FC2, 0x67F21FE4,
+0x657251F5, 0x45296213, 0x45284519, 0x42194518,
+0x5CF2252B, 0x41282752, 0x7CFD4118, 0xA022EB10,
+0x7DF05DF1, 0x54D256D3, 0x45196563, 0x52D14628,
+0x4618215B, 0x6ED26543, 0x45192716, 0x265B4428,
+0x65436163, 0x45186423, 0x42284419, 0x4218254B,
+0x271664E3, 0x44196623, 0x264B2756, 0x4E282766,
+0x61E34E18, 0x3CB27CF0, 0x7D0189DB, 0x1FC21FD6,
+0xE7041F74, 0x51F45DF2, 0x5EF6A00D, 0x84E27EFC,
+0x620364E0, 0x7DFC84E1, 0x84E36503, 0x21646603,
+0x21542124, 0x3D722144, 0x57F389F0, 0x641366D3,
+0x7F1C65E3, 0x6DF66EF6, 0xA09D6CF6, 0x2F866BF6,
+0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6, 0x614374E0,
+0x6A636873, 0x6B56E920, 0x6C567AE0, 0x6D567120,
+0x6E563A92, 0x64566756, 0x62566656, 0x11C121B2,
+0x11E311D2, 0x11451174, 0x8DEC1166, 0x71201127,
+0x6613A004, 0x7AFF6254, 0x76012620, 0x8BF92AA8,
+0x6EF66083, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0x2F8668F6, 0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6,
+0x6A636873, 0x75E0E920, 0x56565257, 0x57545155,
+0x5D525E53, 0x6B525C51, 0x24662426, 0x24762416,
+0x7AE024E6, 0x24C624D6, 0x8DEC3A92, 0x66A324B6,
+0x6EF66783, 0x6CF66DF6, 0x6AF66BF6, 0xA04369F6,
+0x2FE668F6, 0xC8046063, 0x8D046E63, 0x62166153,
+0x24227EFC, 0x60E37404, 0x8908C818, 0x71046513,
+0x62526616, 0x24227EF8, 0xAFF41461, 0xE2047408,
+0x65133E22, 0x66E38D02, 0x6EF6A01C, 0x6EF6AF87,
+0xC8046063, 0x61638D04, 0x625275FC, 0x242671FC,
+0xC8186013, 0x75F88906, 0x66525251, 0x24662426,
+0x71F8AFF6, 0x3122E204, 0x66138F02, 0x0009AFA1,
+0x0009A00A, 0x0009A004, 0x76FF6254, 0x74012420,
+0x8BF92668, 0x6073000B, 0x0009A004, 0x625075FF,
+0x242476FF, 0x8BF92668, 0x6073000B, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x544F0D0A, 0x46205355, 0x00003A57, 0x2072614D,
+0x32203232, 0x20373030, 0x353A3731, 0x37333A32,
+0x00000000, 0x00000D0A, 0x00000043, 0x61766E49,
+0x2064696C, 0x72657375, 0x20726F20, 0x2079656B,
+0x00214449, 0x6E6B6E55, 0x206E776F, 0x6D6D6F63,
+0x3D646E61, 0x00000000, 0x61437748, 0x7262696C,
+0x6F697461, 0x6620206E, 0x0A6C6961, 0x0000000D,
+0x73696F4E, 0x61432065, 0x7262696C, 0x6F697461,
+0x6166206E, 0x21216C69, 0x00000D0A, 0x00000D0A,
+0x00000042, 0x000000FF, 0x00020001, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00020003, 0x01090108,
+0x0002010A, 0x00030002, 0x02020201, 0x02040203,
+0x02060205, 0x02080207, 0x020A0209, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00FF010F, 0x01090108,
+0x010B010A, 0x00030002, 0x02020201, 0x02040203,
+0x02060205, 0x02080207, 0x020A0209, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00000072, 0x00205220, 0x00000046,
+0x00000059, 0x73204142, 0x003D7165, 0x00000074,
+0x00000000, 0x02000112, 0x40FFFFFF, 0x12210ACE,
+0x20104890, 0x02090100, 0x0101002E, 0x09FA8000,
+0x04000004, 0x000000FF, 0x02010507, 0x07000200,
+0x00028205, 0x05070002, 0x00400383, 0x04050701,
+0x01004003, 0x002E0209, 0x80000101, 0x000409FA,
+0x00FF0400, 0x05070000, 0x00400201, 0x82050700,
+0x00004002, 0x03830507, 0x07010040, 0x40030405,
+0x03040100, 0x030C0409, 0x0079005A, 0x00410044,
+0x03180053, 0x00530055, 0x00320042, 0x0030002E,
+0x00570020, 0x0041004C, 0x0000004E, 0x00000000,
+0x00000000, 0x00000709, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, };
+
+const u32_t zcFwImageSize=11204;
diff --git a/drivers/staging/otus/hal/hpfwu_OTUS_RC.c b/drivers/staging/otus/hal/hpfwu_OTUS_RC.c
new file mode 100644
index 000000000000..089d3e0ad853
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwu_OTUS_RC.c
@@ -0,0 +1,715 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE287FFC, 0xE114D728,
+0x1E13D428, 0x1E4C470B, 0x0009B018, 0xA0039543,
+0x3652E600, 0x76018D04, 0xC84060E2, 0x2F028DF9,
+0xDE22D421, 0x00094E0B, 0x4E0BD421, 0xD4210009,
+0x00094E0B, 0x4F267F04, 0x6EF6A022, 0xD11E4F22,
+0x0009410B, 0x440BD41D, 0xD51D0009, 0x0009450B,
+0xE1FFD71C, 0xD21C611D, 0x50292712, 0xCB01E1FF,
+0xD61BD41A, 0x22121209, 0xE5011211, 0x2452E200,
+0xD5182622, 0x970FD618, 0x4F262572, 0x2620000B,
+0xDD17DC16, 0x4C0BDE17, 0x4D0B0009, 0x4E0B0009,
+0xAFF80009, 0x27100009, 0x00000640, 0x001C001C,
+0x002008EA, 0x0000B38E, 0x002028DC, 0x00200DA6,
+0x002028E8, 0x00202900, 0x00200C6C, 0x00200EA2,
+0x00200940, 0x001C3510, 0x001C3624, 0x001E212C,
+0x00202894, 0x0020288C, 0x002027F0, 0x00200B68,
+0x00201F74, 0x00201734, 0x2FD62FC6, 0x4F222FE6,
+0xDEA17FA4, 0x61E0E01C, 0x7D016DE3, 0x61D00F14,
+0xD59FD49E, 0x450BE020, 0xE0200F14, 0xE78004FC,
+0x604C66E2, 0x7D7F677C, 0x1F693070, 0x2D628F17,
+0x01FCE01C, 0x641CE500, 0xD797DE96, 0x3243625D,
+0xA21A8B01, 0x655D0009, 0x31EC6153, 0xE0286C10,
+0x6D530FC4, 0x3D7C62CE, 0xAFEF2D20, 0x20087501,
+0xE01C8B15, 0xE50001FC, 0xD78BDE8A, 0x641CA00A,
+0x6C53655D, 0x66C23CEC, 0x66626253, 0x2262327C,
+0x1F697504, 0x3243625D, 0xA1F68BF2, 0x88012D10,
+0xE01C8B16, 0xE40001FC, 0x671C2D40, 0x624DDE7D,
+0x8B013273, 0x0009A1E9, 0x62E3644D, 0x72046D43,
+0x3DEC6143, 0x65D2312C, 0x74086C12, 0x25C2AFEF,
+0x8B188804, 0x01FCE01C, 0x2D40E400, 0xDE71671C,
+0x3273624D, 0xA1D08B01, 0x644D0009, 0x62E36D43,
+0x65D23DEC, 0x61437204, 0x6612312C, 0x74086C52,
+0xAFED2C69, 0x880525C2, 0xE01C8B18, 0xE40001FC,
+0x671C2D40, 0x624DDE63, 0x8B013273, 0x0009A1B5,
+0x6C43644D, 0x3CEC62E3, 0x720465C2, 0x3D2C6D43,
+0x615266D2, 0x216B7408, 0x2512AFED, 0x8B138830,
+0xE200DE58, 0x64E22D20, 0x8B042448, 0x420BD257,
+0xA19A0009, 0x55E10009, 0x57E356E2, 0xDD545CE4,
+0x2FC64D0B, 0x7F04A191, 0x89018828, 0x0009A0EA,
+0xE143DE4C, 0x622D62E1, 0x8F033217, 0x56FB1FEB,
+0x2621E240, 0x8B013217, 0x0009A0D5, 0xE1015EFB,
+0x301685E1, 0xA0CE8B01, 0xE4010009, 0x2D4055FB,
+0x6451B179, 0xE14357FB, 0xE0546271, 0x3517652D,
+0x0F568D41, 0x3563E640, 0xE6008B05, 0x0F65E034,
+0xA00FE11A, 0x615372C0, 0x41214121, 0x41214121,
+0x45214121, 0x45214521, 0xC9036053, 0xE0346603,
+0x71180F65, 0x2209E007, 0x641DE030, 0x0F2565F3,
+0x1F4EB1F1, 0x04FDE034, 0x674DE030, 0x47080CFD,
+0x607361CD, 0x4108D22B, 0xE00F0CFE, 0x1F1F420B,
+0x2CD96D07, 0x5EFB6073, 0x85E20FC6, 0x420B51FF,
+0x2C0B600D, 0x54FE6073, 0xB1BB0FC6, 0xE05465F3,
+0x652D62E1, 0xE6400F56, 0x89623563, 0xE050E100,
+0x60230F15, 0x4008C903, 0x6D034000, 0xE0406103,
+0xE0440FD6, 0xD217EEFF, 0x6EEC0FF6, 0x0F26E058,
+0x60E3420B, 0x42216253, 0x42214221, 0x66234221,
+0x326C4200, 0x45214200, 0xE0486707, 0x0F764521,
+0xC9036053, 0x40085CFB, 0x7C0630FC, 0x6E036D2D,
+0x1FD51FC6, 0x1F04A02E, 0x00117D00, 0x00202904,
+0x00200DA6, 0x00117D04, 0x00117D84, 0x00200700,
+0x0020074C, 0x00201FD4, 0x0FD6E04C, 0x05FEE044,
+0x64D3B189, 0x64E2E048, 0xE04006FE, 0x2E422469,
+0x01FE67C4, 0x667CE058, 0x420B02FE, 0x240B6063,
+0x05FEE044, 0xB15D2E42, 0xE05064D3, 0x7D0101FD,
+0x0F157101, 0x02FDE050, 0x3262E606, 0x56FB8BDC,
+0x55FB6261, 0x85514200, 0x302C750C, 0x6103701B,
+0x64F3E600, 0xE704A004, 0x76016256, 0x74042422,
+0x3273626D, 0x65F38BF8, 0x641DB13C, 0xB0D256FB,
+0xA0AA6461, 0xD4880009, 0xE201D588, 0x2D20450B,
+0x0009A0A3, 0x8B078829, 0xE200DE85, 0x66E22D20,
+0x646DB0A1, 0x0009A099, 0x622CE281, 0x8B3D3020,
+0xD680E738, 0xE0442D70, 0xE0480C6E, 0x6E621DC1,
+0x51611DE2, 0x54621D13, 0x55651D44, 0x57631D55,
+0x5C661D76, 0x0E6E1DC7, 0x1DE8E040, 0xE050016E,
+0x54641D19, 0x056E1D4A, 0x1D5BE04C, 0xE054076E,
+0x0C6E1D7C, 0x1DCDE058, 0xE044026E, 0xED001D2E,
+0xE04806D6, 0x16D126D2, 0x16D516D2, 0x16D616D3,
+0xE04006D6, 0xE05006D6, 0x06D616D4, 0x06D6E04C,
+0x06D6E054, 0x06D6E058, 0x1F29A057, 0x622CE282,
+0x89313020, 0x05FCE020, 0x625CE683, 0x3260666C,
+0xD65D8B07, 0x2650E500, 0x52617680, 0xA044D65B,
+0xE6902622, 0x3260666C, 0xD2578B16, 0xE500D658,
+0x60622250, 0xCB20D257, 0xE6052602, 0xD6562262,
+0x2252460B, 0x420BD255, 0xD2550009, 0x2262E601,
+0x4618D254, 0x2262A029, 0xD254D453, 0xD4546542,
+0x0009420B, 0x0009A021, 0xE524D647, 0xD5452650,
+0x16215257, 0x16225258, 0x16235259, 0x1624525A,
+0x1625525B, 0x1626525C, 0x1627525D, 0x1628525E,
+0x1F29525F, 0xE2001629, 0x15281527, 0x152A1529,
+0x152C152B, 0x152E152D, 0x7F5C152F, 0x6EF64F26,
+0x000B6DF6, 0x4F226CF6, 0xE240614D, 0x89173123,
+0x3127E21F, 0xD43B8908, 0xE001D53B, 0x6642450B,
+0x26796707, 0x2462A00C, 0x3127E23F, 0xD7358908,
+0x71E0D635, 0x460BE001, 0x62075571, 0x17512529,
+0x000B4F26, 0x4F220009, 0xE240614D, 0x89153123,
+0x3127E21F, 0xD42B8907, 0x6642D22B, 0xE001420B,
+0xA00B260B, 0xE23F2462, 0x89073127, 0xD626D725,
+0x71E05571, 0xE001460B, 0x1751250B, 0x000B4F26,
+0xE6400009, 0x46284618, 0x6252D520, 0x89FC2268,
+0x0009000B, 0x4618E680, 0xD51C4628, 0x22686252,
+0x000B89FC, 0xA0010009, 0x7201E200, 0x8BFC3242,
+0x0009000B, 0x4618E680, 0xD5154628, 0x22686252,
+0x000B8BFC, 0x00000009, 0x00202908, 0x00200DA6,
+0x00117D04, 0x002027F8, 0x00117D80, 0x0020288C,
+0x001C3500, 0x001D4004, 0x00200EA2, 0x00200940,
+0x001E212C, 0x001C3D28, 0x00117D00, 0x00200E06,
+0x00202920, 0x001C3704, 0x00201FD4, 0x001C373C,
+0x001C3700, 0x4F222FE6, 0x6E537FFC, 0x2F42BFCA,
+0xD61561E2, 0x1615E280, 0x421854E1, 0x55E21646,
+0x16574228, 0x6EF257E3, 0x2E2B1678, 0x7F0426E2,
+0xAFA74F26, 0x2FC66EF6, 0x2FE62FD6, 0xDD0A4F22,
+0xBFAF6C53, 0xBF946E43, 0xBFAB2DE2, 0x51D50009,
+0x54D62C12, 0x55D71C41, 0x56D81C52, 0x4F261C63,
+0x6DF66EF6, 0x6CF6000B, 0x001C370C, 0x0009A0C0,
+0xD17B4F22, 0xD47B92B6, 0x2122B00D, 0x97B2E605,
+0xB02295B2, 0xB0366463, 0xB0360009, 0xB0390009,
+0xA0680009, 0x4F124F26, 0xD1734F02, 0x94A43145,
+0x4609060A, 0x46094609, 0x00293646, 0xD76CD56F,
+0x2500CA01, 0x4F062762, 0x4F16000B, 0xBFEA4F22,
+0xB01F0009, 0xA04E0009, 0x2FE64F26, 0x6E63D168,
+0x44186612, 0x4528928A, 0x26294408, 0x44084500,
+0x4400265B, 0x4708264B, 0x47082162, 0x27EBD161,
+0x000B2172, 0x000B6EF6, 0xD25F0009, 0xE40A9677,
+0x2262AFB4, 0x2FC62FB6, 0x2FE62FD6, 0xDC5B4F22,
+0x2C22E201, 0xBFA9E40A, 0x60C27C44, 0xCB01ED00,
+0x60C22C02, 0xC901EB64, 0x6E03A008, 0x89073DB2,
+0xE40160C2, 0xBF99C901, 0x7D016E03, 0x8BF52EE8,
+0x8B033DB2, 0xD24FD44E, 0x0009420B, 0x4F26E40A,
+0x6DF66EF6, 0xAF896CF6, 0x44116BF6, 0x604B8F01,
+0x000B6043, 0x2FB60009, 0x2FD62FC6, 0x4F222FE6,
+0xDC457FFC, 0x60C2ED00, 0xCB02EB64, 0x60C22C02,
+0xC9022F02, 0x6E03A009, 0x89083DB3, 0xE46460C2,
+0xC9022F02, 0x6E03BF6A, 0x2EE87D01, 0xD73B8BF4,
+0x617251C1, 0xDE3BDC3A, 0xD23CD13B, 0x64C23DB3,
+0x651264E2, 0x65228F09, 0xD232D439, 0x4F267F04,
+0x6DF66EF6, 0x422B6CF6, 0x7F046BF6, 0x6EF64F26,
+0x6CF66DF6, 0x6BF6000B, 0x5651D532, 0x46286052,
+0x306C000B, 0x5288096C, 0x09B45BB4, 0x03C41FFF,
+0x2FC62FB6, 0x2FE62FD6, 0x4F124F22, 0xBFEB4F02,
+0x6B036E43, 0xDD18DC28, 0x0009BFE6, 0x3C0530B8,
+0x4609060A, 0x46014609, 0x020A3D65, 0x42094209,
+0x32E24209, 0x4F068BF0, 0x4F264F16, 0x6DF66EF6,
+0x000B6CF6, 0x2FE66BF6, 0xDE1C4F22, 0xE500E102,
+0x2E12E403, 0x2E52BFD4, 0x4618E606, 0xE403E700,
+0x2E722E62, 0xAFCB4F26, 0x000B6EF6, 0x00000009,
+0x00202890, 0x0024CDE0, 0x10624DD3, 0x00202A8C,
+0x001C5814, 0x001C59D0, 0x001C5804, 0x001C581C,
+0x00202934, 0x00200DA6, 0x001C5860, 0x001C6864,
+0x001C7864, 0x001C59BC, 0x001C69BC, 0x001C79BC,
+0x0020294C, 0x001C1040, 0xCCCCCCCD, 0x001D4004,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xE4007FE4, 0x4528E510, 0x67436C43, 0xE107A00F,
+0x6043644D, 0x0F564008, 0xEE0060C3, 0x815125C1,
+0x81538152, 0x157315E2, 0x751415E4, 0x624D7401,
+0x8BED3213, 0xDA6F51F1, 0x1A1154F2, 0xD16E2A12,
+0x57F455F3, 0x6DF258F5, 0x1141D96C, 0x11532142,
+0x11751152, 0x11871174, 0x52F61186, 0x19D1D668,
+0xD86829D2, 0xDA68E950, 0x1621EBB4, 0x6BBC2622,
+0xA0214908, 0x6EEDEE00, 0x61E36DE3, 0x41084D08,
+0x31EC3DEC, 0x41084D08, 0x60C33D8C, 0xE7904108,
+0x81D12DC1, 0x41086093, 0x81D2677C, 0x31AC60C3,
+0x3472E200, 0x1DD281D3, 0xD4551D13, 0x1D248D01,
+0xB03AD450, 0x7E0165D3, 0x34B264ED, 0xD14D8BDB,
+0x6512DB52, 0x4529D24D, 0x64121B51, 0x674DD14A,
+0x67222B72, 0x4729D64E, 0x69221B73, 0x689D2FD2,
+0x69121B82, 0x5A122692, 0x5B1416A2, 0x16B4DA44,
+0x16C65C16, 0x16EA6EA2, 0x4F267F1C, 0x6DF66EF6,
+0x6BF66CF6, 0x69F66AF6, 0x68F6000B, 0x60616642,
+0x8D04C803, 0x6061E500, 0x8802C903, 0x52628B03,
+0x51246563, 0x000B2412, 0x2FD66053, 0x4F222FE6,
+0x6E537FEC, 0xE5506253, 0xE4006D43, 0xA0014508,
+0x5224E101, 0x22116043, 0x81238121, 0x81226053,
+0x362056E2, 0xD22F8BF5, 0x64F316E4, 0x420BE614,
+0x65E165E3, 0x2549E4FC, 0x61F12E51, 0x214965F3,
+0x54D12F11, 0x410BD127, 0x57D1E614, 0xCB016071,
+0x1DE12701, 0x4F267F14, 0x000B6EF6, 0x2FD66DF6,
+0x4F222FE6, 0x6E537FEC, 0xE5FC6653, 0x60616D43,
+0xCB012059, 0x52E22601, 0x8B063260, 0x51E212E4,
+0x8B0431E0, 0xA00252D1, 0xAFF01E22, 0xD2155664,
+0xE61464F3, 0x65E3420B, 0xE1FC67E1, 0x2E712719,
+0x54D167F1, 0xD10F2719, 0xE61465F3, 0x2F71410B,
+0x602152D1, 0x2201CB01, 0x7F141DE1, 0x6EF64F26,
+0x6DF6000B, 0x0020285C, 0x00202864, 0x00202854,
+0x00202884, 0x0010008C, 0x00100EC0, 0x001E2108,
+0x001C3D00, 0x00202134, 0x2FC62FB6, 0x2FE62FD6,
+0xD6314F22, 0x60D36D62, 0x894DC803, 0xDB30DC2F,
+0x0009A02C, 0xC9036061, 0x892B8801, 0xD22DD42B,
+0x0009420B, 0x65035603, 0xC8208561, 0xE0508903,
+0x720102BE, 0x85620B26, 0x4000600D, 0x4000366A,
+0x40004624, 0x206D4624, 0xD423C903, 0x40086E03,
+0xD1224000, 0x340C410B, 0x61E3D521, 0xD721E001,
+0x450BD221, 0x64E37E30, 0x2702420B, 0x66C252C1,
+0x8BCF3620, 0x4E18EE01, 0xA011DB1C, 0x6061EC75,
+0x8801C903, 0xD4198910, 0x460BD612, 0xD4180009,
+0x470BD718, 0xD2136503, 0x64C3D113, 0x22E2410B,
+0x66B252B1, 0x8BEA3620, 0xC80460D3, 0xD2128906,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6422B, 0x6EF64F26,
+0x6CF66DF6, 0x6BF6000B, 0x001E2100, 0x0020285C,
+0x002027F8, 0x00200A5C, 0x00202864, 0x00200ADE,
+0x00201FD4, 0x001C3D30, 0x00200D6C, 0x00202854,
+0x00202884, 0x00200A7A, 0x002000F8, 0xE601D237,
+0x1265D537, 0x000B2252, 0xD6361266, 0x88016062,
+0xE1018B62, 0xD5342612, 0x5451D134, 0xE0406212,
+0x2122324C, 0x54115752, 0x1141347C, 0x57125453,
+0x1172374C, 0x52135755, 0x1123327C, 0x56146452,
+0x1164364C, 0x54155754, 0x1145347C, 0x56165458,
+0x1166364C, 0x6762D626, 0x327C5217, 0x57611127,
+0x327C5218, 0x57621128, 0x327C5219, 0x57631129,
+0x347C541A, 0x5764114A, 0x347C541B, 0x5765114B,
+0x347C541C, 0x5266114C, 0x372C571D, 0x5267117D,
+0x342C541E, 0x5268114E, 0x362C561F, 0xD615116F,
+0x041E6262, 0x342C7694, 0xE0440146, 0x061E6262,
+0x0166362C, 0x525CE048, 0xD60F051E, 0x0156352C,
+0xE0546262, 0x4229051E, 0x0156352C, 0xE0585561,
+0x4529061E, 0x0166365C, 0x0009000B, 0x001C1010,
+0x0000C34F, 0x001C1028, 0x001C369C, 0x002027F8,
+0x001C3CA0, 0x001C36F4, 0x001C3B88, 0xD62F7FFC,
+0x2642644C, 0xC8205066, 0x2F028DFC, 0x7F04000B,
+0x2FD62FC6, 0x4F222FE6, 0x6D436C53, 0xEE00A004,
+0x7E0164D4, 0x644CBFEA, 0x8BF93EC2, 0x6EF64F26,
+0x000B6DF6, 0xA0016CF6, 0x76016643, 0x22286260,
+0x36488BFB, 0x6563AFE4, 0x2FB62F96, 0x2FD62FC6,
+0x4F222FE6, 0xEC1CED08, 0xDB196E53, 0x61C3E90A,
+0x60434B0B, 0x3092C90F, 0x66038D02, 0x7630A001,
+0x4D107637, 0x7E012E60, 0x7CFC8FF1, 0x8058E000,
+0x6EF64F26, 0x6CF66DF6, 0x000B6BF6, 0x000B69F6,
+0x000BE000, 0x2FE6E000, 0x7FEC4F22, 0x6E436253,
+0xBFD165F3, 0xBFC66423, 0xBFC464E3, 0xD40564F3,
+0x0009BFC1, 0x4F267F14, 0x6EF6000B, 0x001C0004,
+0x00202094, 0x00202968, 0xE110D59C, 0xE6406050,
+0x2500C9FD, 0xE0FF75E9, 0x80516453, 0x80538052,
+0x80568055, 0x251075EF, 0xE1EF6250, 0x2219E001,
+0xE7202520, 0x24608052, 0x2570000B, 0xE4FDD590,
+0xE7026152, 0x25122149, 0x74016052, 0x2502CB01,
+0xD18C6652, 0x25622649, 0x92C26012, 0x2102CB08,
+0xC9CF6012, 0x60122102, 0x2102CB03, 0x000B1172,
+0x4F221123, 0xE100D484, 0xD285D784, 0xD5852410,
+0x2711D485, 0x2211E700, 0xBFBD2511, 0xD5832471,
+0x2560E600, 0x4F26AFD2, 0xD281664C, 0x362C4600,
+0xCB106060, 0x2600000B, 0xD27D654C, 0x352C4500,
+0xE1EF6650, 0x000B2619, 0x664C2560, 0x4600D279,
+0x6060362C, 0x000BCB10, 0x654C2600, 0x4500D275,
+0x6650352C, 0x2619E1EF, 0x2560000B, 0xD270664C,
+0x362C4600, 0xCB086060, 0x2600000B, 0xD26C654C,
+0x352C4500, 0xE1F76650, 0x000B2619, 0x664C2560,
+0x4600D268, 0x6060362C, 0x000BCB08, 0x654C2600,
+0x4500D264, 0x6650352C, 0x2619E1F7, 0x2560000B,
+0xD65F624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0x624C600C, 0x4200D65A, 0x6020326C,
+0x4021C908, 0x40214021, 0x600C000B, 0xD156644C,
+0x341C74FF, 0x000B6240, 0xD154602C, 0x341C644C,
+0x000B6240, 0x2FE6602C, 0x655C4F22, 0x3567E60A,
+0x6E438D15, 0x6453BFEA, 0x60EC640C, 0x8B028801,
+0xA002E00F, 0x44092409, 0x624C4409, 0x3263E60A,
+0xBFE28905, 0x620C644C, 0xC8806023, 0xE2008B00,
+0x4F266023, 0x6EF6000B, 0xD6414F22, 0x88016062,
+0xB2228B03, 0xA0030009, 0xD23E0009, 0x2260E640,
+0xE200D63D, 0x000B4F26, 0x4F222622, 0x6062D638,
+0x8B018802, 0x0009B26C, 0xE200D637, 0x000B4F26,
+0x0FFF2622, 0xD433D532, 0xE701E100, 0x000B2512,
+0xD2302470, 0x000BE604, 0xD5202260, 0x6150E4FD,
+0x2149D62E, 0x2510E700, 0x2670000B, 0xE4FBD51B,
+0x22496250, 0x2520000B, 0xE4F7D518, 0x22496250,
+0x2520000B, 0xD2264F22, 0x600D8522, 0x89112008,
+0x89138801, 0x89158803, 0x89178805, 0x89418806,
+0x89478808, 0x894D8809, 0x8953880A, 0x8959880B,
+0x0009A060, 0x0009B062, 0x600CA05D, 0x0009B070,
+0x600CA059, 0x0009B07A, 0x600CA055, 0x6260D606,
+0x8B4F2228, 0x0009B086, 0x600CA04D, 0x001E1028,
+0x001E2148, 0x001E1108, 0x002028D9, 0x002028C8,
+0x002028CA, 0x002028CC, 0x002028AC, 0x001E1008,
+0x001E103F, 0x001E105F, 0x001E1030, 0x001E1090,
+0x002028D4, 0x001E100B, 0x002028D0, 0x002028D8,
+0x002028A0, 0x6260D687, 0x8B232228, 0x0009B06A,
+0x600CA021, 0x6260D683, 0x8B1B2228, 0x0009B0B4,
+0x600CA019, 0x6260D67F, 0x8B132228, 0x0009B0BA,
+0x600CA011, 0x6260D67B, 0x8B0B2228, 0x0009B11E,
+0x600CA009, 0x6260D677, 0x8B032228, 0x0009B136,
+0x600CA001, 0x4F26E000, 0x0009000B, 0xD273D172,
+0xD5738412, 0x4000C90F, 0xD772012D, 0x611CE403,
+0xD671E20F, 0x27122540, 0xE0012520, 0x2602000B,
+0xE601D269, 0x30668523, 0xE0008D06, 0xE000D267,
+0x8122D669, 0x2602E001, 0x0009000B, 0x8523D262,
+0x2008600D, 0x88018905, 0xD6648B0A, 0xCB016060,
+0xD6612600, 0xE101D45D, 0x2612E001, 0x8142000B,
+0xE000000B, 0xE501D158, 0x45188513, 0x3453640D,
+0x8D056603, 0xD25AE000, 0xE001D557, 0x25022260,
+0x0009000B, 0xD1504F22, 0x650D8513, 0x44196453,
+0x672E6249, 0x602C227D, 0x89098801, 0x890C8802,
+0x89108803, 0x89268806, 0x89298807, 0x0009A038,
+0xD64DD54C, 0xA027E212, 0x625C2652, 0x8B2F2228,
+0xA01ED64A, 0x605C6262, 0x89052008, 0x89088810,
+0x890B8820, 0x0009A024, 0xD643D445, 0xA013E204,
+0xD7442642, 0xE20CD640, 0x2672A00E, 0xD63ED542,
+0xA009E218, 0xD4412652, 0xE20AD63B, 0x2642A004,
+0xD639D23F, 0xE22E2622, 0xD43E8515, 0x3277670D,
+0x8F012421, 0x24516503, 0x0009B0DF, 0xE001A001,
+0x4F26E000, 0x0009000B, 0xE101D629, 0x2610D436,
+0xD7286541, 0x655DD128, 0xE001E20F, 0x26202752,
+0x2102000B, 0x4F222FE6, 0x8523D21F, 0x2448640C,
+0xD62D8B08, 0xE200D521, 0x84512621, 0x20499430,
+0x8051A026, 0x60E0DE1D, 0x8D0BC840, 0x3427E201,
+0xD1258922, 0x420BD225, 0xD5252141, 0xCB046052,
+0x2502A00B, 0x89173427, 0xD722D21F, 0x2241470B,
+0xE5FBD61F, 0x21596162, 0x84E12612, 0xB12DCB80,
+0x60E080E1, 0xCB04D61C, 0x60602E00, 0x2600C93F,
+0xE001D609, 0x2602A001, 0x4F26E000, 0x6EF6000B,
+0x0000FF7F, 0x002028D9, 0x002028A0, 0x002028AC,
+0x001E1100, 0x001E100C, 0x002028D0, 0x001E1000,
+0x001E1001, 0x00202A90, 0x002028B4, 0x002028BC,
+0x00202AFE, 0x00202B02, 0x00202B0E, 0x00202B26,
+0x00202B30, 0x002028B8, 0x002028C6, 0x00201A32,
+0x001E1108, 0x00201B3E, 0x001E1015, 0x6060D696,
+0x8919C880, 0x6021D295, 0x8B158801, 0xE501D294,
+0x30568524, 0xD1938910, 0xD493E203, 0x65412120,
+0x655DE00B, 0xD5910656, 0xE702E40F, 0x25712140,
+0xE001D78F, 0x2702000B, 0xE000000B, 0x4F222FE6,
+0x84E1DE8C, 0x8934C880, 0x8554D585, 0x8F302008,
+0xD7896103, 0x66728553, 0x650C6403, 0x620C8566,
+0x8B263520, 0xD780D685, 0x644C651C, 0x27412651,
+0xC84060E0, 0xD2828907, 0x0009420B, 0x6062D681,
+0xA008CB04, 0xD1802602, 0x0009410B, 0xE5FBD67D,
+0x24596462, 0xB0A12642, 0xD5750009, 0x2522E201,
+0xD77A60E0, 0x2E00CB04, 0xC93F6070, 0xA0012700,
+0xE0006023, 0x000B4F26, 0x2FA66EF6, 0x2FC62FB6,
+0x2FE62FD6, 0xE240DA69, 0xDC6666A1, 0x3123616D,
+0x62638900, 0x6ED36D2C, 0x4E2136D8, 0x4E212A61,
+0xDB6CD46B, 0xE700A00F, 0x770166B2, 0x71026163,
+0x65612B12, 0x71026613, 0x62612B12, 0x622D655D,
+0x325C4228, 0x627C2422, 0x8BED32E3, 0xC90360D3,
+0x8B108803, 0xED076EB2, 0x710261E3, 0x67132B12,
+0x62E17102, 0x65712B12, 0x655D622D, 0x352C4528,
+0xA00C2CD0, 0x88022452, 0xA0038B01, 0x8801E203,
+0xE2018B05, 0x66B22C20, 0x677D6761, 0xEB0F2472,
+0x6DA12CB0, 0x8B052DD8, 0xD445D24F, 0xE101EE00,
+0x241222E2, 0x6DF66EF6, 0x6BF66CF6, 0x6AF6000B,
+0x2FE62FD6, 0xE240DD3D, 0x616D66D1, 0x89003123,
+0x672C6263, 0xDE433678, 0x2D617703, 0xD6404721,
+0x472164E2, 0xE100A00E, 0x71016562, 0x24506253,
+0x42197401, 0x74012420, 0x24504529, 0x45197401,
+0x74012450, 0x3273621C, 0x42008BEE, 0x64D166E2,
+0x362C4200, 0x8F062448, 0xDD332E62, 0xE500DE28,
+0x2D52E701, 0x6EF62E72, 0x6DF6000B, 0x2FE62FD6,
+0xEE014F22, 0xED0AA005, 0x64E3BCB6, 0x64E3BCBC,
+0x62EC7E01, 0x8BF732D7, 0xEE01A005, 0x64E3BCBD,
+0x64E3BCC3, 0x62EC7E01, 0x8BF732D7, 0x6EF64F26,
+0x6DF6000B, 0x2FE62FD6, 0x7FFC4F22, 0x6060D61F,
+0x89758801, 0xE101D41E, 0xD7128548, 0x650D2610,
+0x45196070, 0x6659DD1B, 0x61D3626E, 0xC840262D,
+0x74027102, 0x8D47D718, 0xD218666C, 0xE501DE0A,
+0xA0312E22, 0x0000EE04, 0x001E1001, 0x002028C6,
+0x002028A0, 0x001E1100, 0x002028CA, 0x002028B8,
+0x002028D0, 0x001E1000, 0x002028BC, 0x002028C8,
+0x00201A32, 0x001E1108, 0x00201B3E, 0x001E1015,
+0x001E100C, 0x002028B4, 0x002028D4, 0x002028D8,
+0x00202A90, 0x00202B26, 0x00202B32, 0x00202AA2,
+0x75016245, 0x71022121, 0x32E3625C, 0x60638BF8,
+0xE60181D4, 0xE417D538, 0x3243626C, 0x6255891E,
+0x27217601, 0x7702AFF8, 0xDE35D234, 0x2E22E501,
+0xEE04A004, 0x75016245, 0x71022121, 0x32E3625C,
+0x60638BF8, 0xE60181D4, 0xA004D52E, 0x6255E417,
+0x27217601, 0x626C7702, 0x8BF83243, 0x2D21924B,
+0xD72AD429, 0x2F126142, 0x6DF265F2, 0xC9806053,
+0x60532700, 0x6103C960, 0x60538071, 0x65F26EF2,
+0x4D19C903, 0x80724529, 0x451960DC, 0x4E298172,
+0x62EC605C, 0x302C4018, 0x6D428173, 0x2FD22118,
+0x62F26EF2, 0x421966F2, 0x656C4629, 0x602C66F2,
+0x401864EC, 0x304C4629, 0x81744619, 0x4018606C,
+0x8F07305C, 0xBCB58175, 0x620C0009, 0x89082228,
+0x0009A00A, 0x88406013, 0xB00A8B03, 0xA0030009,
+0xD60B0009, 0x2622E202, 0x4F267F04, 0x000B6EF6,
+0x000B6DF6, 0x060A0009, 0x00202AD2, 0x00202AD0,
+0x002028BC, 0x00202AA4, 0x001E100C, 0x002028A0,
+0x002028D0, 0x7FFC4F22, 0x6620D27E, 0x8D082668,
+0xD47D2F60, 0x420BD27D, 0x64F00009, 0xA0907F04,
+0x7F044F26, 0x000B4F26, 0x000B0009, 0x2FE60009,
+0xDE774F22, 0x60E0D677, 0xCBC0D477, 0x62602E00,
+0xC803602C, 0x40218904, 0x70014021, 0x6603A002,
+0x66034009, 0xD671616D, 0xE500A004, 0x75016262,
+0x74042422, 0x3213625D, 0xD16D8BF8, 0x0009410B,
+0xE401D66C, 0x84E22641, 0x80E2C9BF, 0x000B4F26,
+0x2FE66EF6, 0xD5687FFC, 0x6250DE61, 0x642C84E2,
+0xCB407404, 0x80E2614D, 0x44216413, 0xD7634421,
+0xE600A004, 0x76016256, 0x27222F22, 0x3243626D,
+0x60138BF8, 0x2008C903, 0x88038912, 0x88028905,
+0x88018906, 0xA0088907, 0xE0070009, 0x8078A005,
+0xA002E003, 0xE0018078, 0x62528078, 0x27222F22,
+0xD650E00F, 0x60618078, 0x8B018801, 0x2621E200,
+0x6060D64F, 0x2600CB08, 0xC93F60E0, 0x7F042E00,
+0x6EF6000B, 0x6021D247, 0x8D188801, 0xD2466143,
+0x22106053, 0x60638021, 0xD4468121, 0xE500A007,
+0x027C605D, 0x364C6603, 0x26207001, 0x625D6503,
+0x3213611C, 0xD6408BF4, 0xC9BF6060, 0x000B2600,
+0x2FD60009, 0x4F222FE6, 0x60437FFC, 0x8D02C820,
+0xBF6A6E43, 0x60E30009, 0x8901C810, 0x0009BF67,
+0xC84060E3, 0xBF8C8901, 0x60E30009, 0x8929C801,
+0x60D0DD32, 0x8D03C802, 0xD6312F00, 0x0009460B,
+0xC80460F0, 0xD62F8902, 0x0009460B, 0x602362F0,
+0x8902C880, 0xC97F60D0, 0x60232D00, 0x8902C801,
+0x420BD229, 0xD5290009, 0x88026052, 0xD2288B03,
+0xA005E604, 0x88012260, 0xD2258B02, 0x2260E601,
+0x2522E200, 0xC88060E3, 0xD2228916, 0x60E36E20,
+0x8902C802, 0x420BD220, 0x60E30009, 0x8902C804,
+0x420BD21E, 0x60E30009, 0x8905C808, 0x7F04D21C,
+0x6EF64F26, 0x6DF6422B, 0x4F267F04, 0x000B6EF6,
+0x00006DF6, 0x001E1020, 0x0020296C, 0x00200DA6,
+0x001E1015, 0x001E10BF, 0x00117D00, 0x001E10FC,
+0x002000F8, 0x002028CC, 0x00117D80, 0x001E10F8,
+0x001E10AE, 0x00117D84, 0x001E1017, 0x001E1021,
+0x00200FD8, 0x00200FFA, 0x00201584, 0x002028D0,
+0x001E100B, 0x001E1028, 0x0020102A, 0x0020103C,
+0x00201048, 0xD6A8644C, 0x346C74FF, 0x2450000B,
+0x644CD6A6, 0x000B346C, 0xD6A52450, 0x346C644C,
+0x2450000B, 0x616D625C, 0x41194208, 0x60194208,
+0x644C4200, 0x324C670E, 0x207DD19E, 0xC90F4200,
+0x000B321C, 0x67632200, 0x4208625C, 0x42004208,
+0x324C644C, 0x4200D198, 0x000B321C, 0x2FE62270,
+0x614C4F12, 0x4100D493, 0x6710314C, 0x2729E29F,
+0x65736E53, 0x4719676D, 0x672E6279, 0x4221227D,
+0x42214221, 0x7601662C, 0xE4014608, 0x34E84608,
+0x644C4600, 0x0E1A0467, 0x215025EB, 0x000B4F16,
+0x4F226EF6, 0xD2857FE8, 0x88016021, 0xD2848B7B,
+0x26686621, 0xD2838B77, 0x26686621, 0xE50F8B73,
+0xE401BFA0, 0xBFA3E501, 0xE586E400, 0xE400655C,
+0x2F50BFA3, 0xBFA0E401, 0xE602E506, 0x60634618,
+0x81F2E401, 0x6543BF9E, 0xE40185F2, 0xBFAA6543,
+0x85F26603, 0x6543E401, 0x6603BFB1, 0xE40265F0,
+0x6053756C, 0x80F8BF7E, 0xBF81E402, 0x84F8E512,
+0x7090E402, 0x6503BF81, 0x4618E602, 0x81F66063,
+0xBF7FE402, 0x85F6E500, 0x6603E402, 0xE500BF8B,
+0xE40285F6, 0xBF926603, 0xE5FEE500, 0xE010655C,
+0xBF5FE403, 0xE5130F54, 0xE40EBF62, 0x05FCE010,
+0xBF62E40E, 0xE5007585, 0xBF63E403, 0xE500E640,
+0xBF70E403, 0xE500E640, 0xBF78E403, 0xE5FFE640,
+0xE014655C, 0xBF45E404, 0xE40F0F54, 0xE504BF48,
+0x05FCE014, 0xBF48E40F, 0xE5017584, 0xBF49E640,
+0xE501E404, 0xBF56E640, 0xE501E404, 0xE404E640,
+0xAF5C7F18, 0x7F184F26, 0x000B4F26, 0x4F220009,
+0xD2427FF0, 0x88016021, 0xD2418B71, 0x26686621,
+0xD2408B6D, 0x26686621, 0xE50F8B69, 0xE401BF1A,
+0xBF1DE501, 0xE586E400, 0xE400655C, 0x2F50BF1D,
+0xBF1AE401, 0xE401E506, 0xBF1B6543, 0xE401E640,
+0xBF286543, 0xE401E640, 0xBF306543, 0x65F0E640,
+0x756CE402, 0xBEFD6053, 0xE40280F4, 0xE512BF00,
+0xE40284F4, 0xBF007090, 0xE6406503, 0xBF01E402,
+0xE640E500, 0xBF0EE402, 0xE640E500, 0xBF16E402,
+0xE5FEE500, 0x6053655C, 0xBEE3E403, 0xE51380F8,
+0xE40EBEE6, 0xE40E84F8, 0xBEE67085, 0xE5006503,
+0xBEE7E640, 0xE500E403, 0xBEF4E640, 0xE500E403,
+0xBEFCE640, 0xE5FFE403, 0x6053655C, 0xBEC9E404,
+0xE40F80FC, 0xE504BECC, 0xE40F84FC, 0xBECC7083,
+0xE5016503, 0xBECDE640, 0xE501E404, 0xBEDAE640,
+0xE501E404, 0xE404E640, 0xAEE07F10, 0x7F104F26,
+0x000B4F26, 0x00000009, 0x001E1030, 0x001E1080,
+0x001E1090, 0x001E103F, 0x001E103E, 0x002028C6,
+0x002028C8, 0x002028CA, 0x0009000B, 0x666CE680,
+0x6563D2A8, 0x7540E700, 0x6473422B, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0x4C18EC01, 0xDAA3DBA2,
+0x65B252B1, 0x89223520, 0xC9036051, 0x891E8801,
+0xD19FDE9D, 0x64E3410B, 0x85036503, 0x670D66A2,
+0xDD9C3762, 0xD49C890A, 0x420BD29C, 0xD19C0009,
+0xE701D49C, 0x21724D0B, 0x0009AFE2, 0x420BD29A,
+0xD69A64E3, 0x4D0BD49A, 0xAFD926C2, 0x4F260009,
+0x6DF66EF6, 0x6BF66CF6, 0x6AF6000B, 0x7FF44F22,
+0xE6818546, 0x85472F01, 0x81F1666C, 0xD2858548,
+0x854281F2, 0x81F367F3, 0xE40C8543, 0x605381F4,
+0x81F56563, 0x7540420B, 0x4F267F0C, 0x0009000B,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xDC847FF0, 0xE800A0DD, 0xD2836B13, 0xE0014B08,
+0x4B00420B, 0x1F03DE81, 0x3BEC85F2, 0x2F827E30,
+0x1FE26803, 0x66C2DD7E, 0x362052C1, 0xA0C38B01,
+0x60610009, 0x8801C903, 0xA0BD8B01, 0x85610009,
+0x8965C801, 0xEE105163, 0xDA6A8512, 0xC9036603,
+0x85136403, 0x4021600D, 0xC93F4021, 0x8D1C30E3,
+0xD7706503, 0x62704408, 0x44004408, 0x22284500,
+0x345C8F0A, 0x6043D26C, 0x697D072D, 0x68994919,
+0x697C6E8E, 0x28EDA009, 0x6043D268, 0x697D072D,
+0x68994919, 0x697C6E8E, 0xEEFF28ED, 0x6EEC629D,
+0x8B0F32E0, 0x410BD152, 0x540364C3, 0xBF85E502,
+0xD45F6E03, 0x460BD654, 0xD75E65E3, 0xD45EEE01,
+0x27E2A01D, 0x26E9EEFC, 0x81126063, 0x97888513,
+0x20794208, 0x85128113, 0x8112208B, 0x202B8513,
+0x85148113, 0x4218E208, 0x8114202B, 0x854164C2,
+0x814120E9, 0xD45165C2, 0xCB016051, 0x4A0B2501,
+0x60C20009, 0x52F356F2, 0x2B02CB01, 0x2622AF8B,
+0xD2378561, 0x8D2EC802, 0x420B64C3, 0xD6480009,
+0x5E036503, 0x076EE04C, 0x7701D146, 0x60120676,
+0x8B058801, 0xEA0C85E1, 0x20AB4A18, 0x81E1A007,
+0x88026012, 0x85E18B03, 0x20A9EADF, 0x855181E1,
+0x20A9EAFC, 0x60518151, 0xCB01DA28, 0x4A0B64C3,
+0x56F22501, 0xD73851F3, 0x85EF2612, 0x470B64D3,
+0xAF58650D, 0x420B0009, 0x54030009, 0x85446E03,
+0x4A18EA08, 0x30A020A9, 0x8B03DA1A, 0xE501BF16,
+0x0009A007, 0xD62D8541, 0x2268620D, 0xBF0D8901,
+0xD423E500, 0x420BD218, 0xD72265E3, 0xEE01D428,
+0x27E24A0B, 0x0009AF37, 0x68F26083, 0x780181F2,
+0x618D7C08, 0x31E7EE03, 0xAF1D8901, 0x7F100009,
+0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0xFE0368F6, 0x00201834, 0x00202884, 0x0020288C,
+0x00200A5C, 0x00200DA6, 0x00202854, 0x00200ADE,
+0x001E2130, 0x00202A70, 0x00200A7A, 0x001C3D30,
+0x00202A74, 0x00202864, 0x00201FD4, 0x001C3D00,
+0x00202A80, 0x00202A8C, 0x00202970, 0x002029F0,
+0x0020285C, 0x001E212C, 0x00202A78, 0x00202A7C,
+0x002027F8, 0x002027F4, 0x00200E06, 0x00008000,
+0x00202A88, 0x4F222FE6, 0x6E22D20D, 0xC84060E3,
+0x22E28D02, 0x0009BE68, 0x4218E240, 0x89012E28,
+0x0009BE64, 0xC80560E3, 0xBEB98901, 0x60E30009,
+0x8902C802, 0xAE614F26, 0x4F266EF6, 0x6EF6000B,
+0x001C3510, 0x080A0C0E, 0x00020406, 0x1A1C1E20,
+0x12141618, 0x2E303234, 0x26282A2C, 0x3A3C3E40,
+0x6C625648, 0x41112F26, 0xE2208F18, 0x890B3123,
+0x321CD204, 0xD1026220, 0x412B312C, 0x00090009,
+0x00201FFE, 0x00201FB4, 0x000BE000, 0x400062F6,
+0x40004000, 0x40004000, 0x40004000, 0x62F6000B,
+0x40004000, 0x40004000, 0x40004000, 0x40184000,
+0x62F6000B, 0x40004000, 0x40004000, 0x40004000,
+0x40284000, 0x62F6000B, 0x40004000, 0x40184000,
+0x000B4028, 0xC90F62F6, 0x40054005, 0x40054005,
+0x62F6000B, 0x4005C907, 0x40054005, 0x62F6000B,
+0x4005C903, 0x000B4005, 0xC90162F6, 0x000B4005,
+0x000062F6, 0x080A0C0E, 0x00020406, 0x1A1C1E20,
+0x12141618, 0x2E303234, 0x26282A2C, 0x3A3C3E40,
+0x6C625648, 0x41112F26, 0xE2208F18, 0x890B3123,
+0x321CD204, 0xD1026220, 0x412B312C, 0x00090009,
+0x002020BE, 0x00202074, 0x000BE000, 0x400162F6,
+0x40014001, 0x40014001, 0x40014001, 0x62F6000B,
+0x40014001, 0x40014001, 0x40014001, 0x40194001,
+0x62F6000B, 0x40014001, 0x40014001, 0x40014001,
+0x40294001, 0x62F6000B, 0x40014001, 0x40194001,
+0x000B4029, 0x400462F6, 0x40044004, 0xC90F4004,
+0x62F6000B, 0x40044004, 0xC9074004, 0x62F6000B,
+0x40044004, 0x000BC903, 0x400462F6, 0x000BC901,
+0x000062F6, 0x3622E218, 0x67438F12, 0x0009A004,
+0x76FF6254, 0x74012420, 0xC8036053, 0x60438BF8,
+0x8902C803, 0x422BD22B, 0xD22B0009, 0x0009422B,
+0x2FE66473, 0x8D4A3450, 0x27786763, 0x62438947,
+0x227B225B, 0xC9016023, 0x8D203452, 0x2EE86E03,
+0x60238B15, 0x8B08C803, 0x47096643, 0x47106256,
+0x8FFB2622, 0xA0327604, 0x47010009, 0x61436673,
+0x46106255, 0x8FFB2121, 0xA0287102, 0x66430009,
+0x47106254, 0x8FFB2620, 0xA0207601, 0x61430009,
+0x2EE8357C, 0x8F15317C, 0x60236653, 0x8B07C803,
+0x76FC4709, 0x47106262, 0x21268FFB, 0x0009A00F,
+0x65634701, 0x75FE6673, 0x46106251, 0x21258FFB,
+0x0009A005, 0x626076FF, 0x8FFB4710, 0x60432124,
+0x6EF6000B, 0x002022A6, 0x00202752, 0xE21E2FE6,
+0x67633626, 0x8D1B6153, 0x3E106E43, 0x3E128916,
+0x65E38908, 0x3672E600, 0x62148910, 0x25207601,
+0x7501AFF9, 0x317C64E3, 0x6513347C, 0xE600A004,
+0x625075FF, 0x24247601, 0x8BF93672, 0x60E3A011,
+0x890831E2, 0x327C6213, 0x8B0432E6, 0x651364E3,
+0xA0086673, 0xD28F6EF6, 0x651364E3, 0x422B6673,
+0x000B6EF6, 0xE2046EF6, 0x67433622, 0x8F10356C,
+0xA004346C, 0x75FF0009, 0x76FF6250, 0x60532424,
+0x8BF8C803, 0xC8036043, 0xA1058901, 0xA2770009,
+0xA2990009, 0x2FB60009, 0x2FD62FC6, 0x7FE42FE6,
+0x6C636043, 0x66521F62, 0xC9037504, 0x1F516E53,
+0x45086503, 0xE1FC6D43, 0x2D194500, 0x1F732558,
+0x1F651F44, 0x2FD28D0B, 0x88086053, 0x88108923,
+0x8818895B, 0xA0898B01, 0xA0BD0009, 0x62630009,
+0x2D22E600, 0x7CFC7D04, 0xEB10A00D, 0xE60064E6,
+0x7CF065E6, 0x62E261E6, 0x1D512D42, 0x1D231D12,
+0x7E047D10, 0x3CB21FE1, 0x1F6589F0, 0x2FD21FC2,
+0xA0A11FE6, 0x64D21FD4, 0x44286263, 0x44294418,
+0x42184419, 0x4629242B, 0x2D424619, 0x65637D04,
+0xA0217CFD, 0x67E6EB10, 0x62E67CF0, 0x64E66673,
+0x256B4618, 0x2D5261E2, 0x65234729, 0x45184719,
+0x4229275B, 0x42191D71, 0x47186743, 0x4429227B,
+0x44196713, 0x247B4718, 0x1D431D22, 0x41194129,
+0x65137D10, 0x1FE17E04, 0x89DC3CB2, 0x1FE67EFF,
+0x1FC21F55, 0xA0672FD2, 0x6CF21FD4, 0x66C257F5,
+0x46286273, 0x42284629, 0x2C62262B, 0x7C045DF2,
+0x7DFE4729, 0xA01CEB10, 0x65E65EF1, 0x66E66273,
+0x47286753, 0x6763227B, 0x452961E6, 0x257B4728,
+0x2C2264E6, 0x65131C51, 0x45284629, 0x1C62265B,
+0x41296643, 0x216B4628, 0x44291C13, 0x67437C10,
+0x3DB27DF0, 0x1FD289E1, 0x7EFEA034, 0x51F56CF2,
+0x621366C2, 0x42284618, 0x42184619, 0x2C62262B,
+0x7C045DF2, 0x7DFF4119, 0xA01FEB10, 0x65E65EF1,
+0x64E67DF0, 0x42286253, 0x421867E6, 0x66E6212B,
+0x61432C12, 0x45194128, 0x251B4118, 0x65731C51,
+0x44194528, 0x245B4518, 0x64631C42, 0x47194428,
+0x274B4418, 0x46191C73, 0x61637C10, 0x89DE3DB2,
+0x7EFD1FD2, 0x1FC41FE6, 0x5DF2E704, 0xA00D5EF6,
+0x62E451F4, 0x66E47DFC, 0x65E464E4, 0x71012120,
+0x71012160, 0x71012140, 0x71012150, 0x89F03D72,
+0x66D357F3, 0x641365E3, 0x6EF67F1C, 0x6CF66DF6,
+0x6BF6A190, 0x00202134, 0x2FC62FB6, 0x2FE62FD6,
+0x60437FE4, 0x6C63C903, 0x66031F62, 0x460875FC,
+0x61526E43, 0x4600E2FC, 0x26682E29, 0x1F441F73,
+0x1F516D53, 0x8D0B1F15, 0x60632FE2, 0x891F8808,
+0x89538810, 0x8B018818, 0x0009A081, 0x0009A0B9,
+0xEB10A00D, 0x52D37DF0, 0x54D156D2, 0x2E1665D2,
+0x2E662E26, 0x2E427EFC, 0x1FD16153, 0x3CB27CF0,
+0x7D0489F0, 0x1F151FD6, 0x2FE21FC2, 0x1FE4A0A1,
+0x621366E2, 0x42294619, 0x42194618, 0x2E62262B,
+0x7CFF4118, 0xEB10A021, 0x54D37DF0, 0x624357D2,
+0x42194229, 0x55D1212B, 0x2E1666D2, 0x41296173,
+0x41194418, 0x2E46241B, 0x44296453, 0x44194718,
+0x2E76274B, 0x47296763, 0x47194518, 0x257B7EFC,
+0x46182E52, 0x1FD16163, 0x3CB27CF0, 0x7D0389DC,
+0x1F151FD6, 0x2FE21FC2, 0x1FE4A06B, 0x57F56EF2,
+0x627366E2, 0x46284629, 0x262B4229, 0x2E625CF2,
+0x7CFE4728, 0xA01BEB10, 0x7DF05DF1, 0x55D251D3,
+0x46296613, 0x54D1276B, 0x2E7662D2, 0x41286753,
+0x217B4729, 0x61432E16, 0x41294528, 0x2E56251B,
+0x44286523, 0x245B4529, 0x42282E46, 0x7CF06723,
+0x89E23CB2, 0x1FD67D02, 0xA03A1FC2, 0x67F21FE4,
+0x657251F5, 0x45296213, 0x45284519, 0x42194518,
+0x5CF2252B, 0x41282752, 0x7CFD4118, 0xA022EB10,
+0x7DF05DF1, 0x54D256D3, 0x45196563, 0x52D14628,
+0x4618215B, 0x6ED26543, 0x45192716, 0x265B4428,
+0x65436163, 0x45186423, 0x42284419, 0x4218254B,
+0x271664E3, 0x44196623, 0x264B2756, 0x4E282766,
+0x61E34E18, 0x3CB27CF0, 0x7D0189DB, 0x1FC21FD6,
+0xE7041F74, 0x51F45DF2, 0x5EF6A00D, 0x84E27EFC,
+0x620364E0, 0x7DFC84E1, 0x84E36503, 0x21646603,
+0x21542124, 0x3D722144, 0x57F389F0, 0x641366D3,
+0x7F1C65E3, 0x6DF66EF6, 0xA09D6CF6, 0x2F866BF6,
+0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6, 0x614374E0,
+0x6A636873, 0x6B56E920, 0x6C567AE0, 0x6D567120,
+0x6E563A92, 0x64566756, 0x62566656, 0x11C121B2,
+0x11E311D2, 0x11451174, 0x8DEC1166, 0x71201127,
+0x6613A004, 0x7AFF6254, 0x76012620, 0x8BF92AA8,
+0x6EF66083, 0x6CF66DF6, 0x6AF66BF6, 0x000B69F6,
+0x2F8668F6, 0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6,
+0x6A636873, 0x75E0E920, 0x56565257, 0x57545155,
+0x5D525E53, 0x6B525C51, 0x24662426, 0x24762416,
+0x7AE024E6, 0x24C624D6, 0x8DEC3A92, 0x66A324B6,
+0x6EF66783, 0x6CF66DF6, 0x6AF66BF6, 0xA04369F6,
+0x2FE668F6, 0xC8046063, 0x8D046E63, 0x62166153,
+0x24227EFC, 0x60E37404, 0x8908C818, 0x71046513,
+0x62526616, 0x24227EF8, 0xAFF41461, 0xE2047408,
+0x65133E22, 0x66E38D02, 0x6EF6A01C, 0x6EF6AF87,
+0xC8046063, 0x61638D04, 0x625275FC, 0x242671FC,
+0xC8186013, 0x75F88906, 0x66525251, 0x24662426,
+0x71F8AFF6, 0x3122E204, 0x66138F02, 0x0009AFA1,
+0x0009A00A, 0x0009A004, 0x76FF6254, 0x74012420,
+0x8BF92668, 0x6073000B, 0x0009A004, 0x625075FF,
+0x242476FF, 0x8BF92668, 0x6073000B, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x544F0D0A,
+0x46205355, 0x00003A57, 0x2072614D, 0x32203232,
+0x20373030, 0x353A3431, 0x33353A34, 0x00000000,
+0x00000D0A, 0x00000043, 0x61766E49, 0x2064696C,
+0x72657375, 0x20726F20, 0x2079656B, 0x00214449,
+0x6E6B6E55, 0x206E776F, 0x6D6D6F63, 0x3D646E61,
+0x00000000, 0x61437748, 0x7262696C, 0x6F697461,
+0x6620206E, 0x0A6C6961, 0x0000000D, 0x73696F4E,
+0x61432065, 0x7262696C, 0x6F697461, 0x6166206E,
+0x21216C69, 0x00000D0A, 0x00000D0A, 0x00000042,
+0x000000FF, 0x00020001, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00020003, 0x01090108, 0x0002010A,
+0x00030002, 0x02020201, 0x02040203, 0x02060205,
+0x02080207, 0x020A0209, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x010E010D, 0x00FF010F, 0x01090108, 0x010B010A,
+0x00030002, 0x02020201, 0x02040203, 0x02060205,
+0x02080207, 0x020A0209, 0x020C020B, 0x020E020D,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00000072, 0x00205220, 0x00000046, 0x00000059,
+0x73204142, 0x003D7165, 0x00000074, 0x00000000,
+0x02000112, 0x40FFFFFF, 0x12210ACE, 0x20104890,
+0x02090100, 0x0101002E, 0x09FA8000, 0x04000004,
+0x000000FF, 0x02010507, 0x07000200, 0x00028205,
+0x05070002, 0x00400383, 0x04050701, 0x01004003,
+0x002E0209, 0x80000101, 0x000409FA, 0x00FF0400,
+0x05070000, 0x00400201, 0x82050700, 0x00004002,
+0x03830507, 0x07010040, 0x40030405, 0x03040100,
+0x030C0409, 0x0079005A, 0x00410044, 0x03180053,
+0x00530055, 0x00320042, 0x0030002E, 0x00570020,
+0x0041004C, 0x0000004E, 0x00000000, 0x00000000,
+0x00000709, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+const u32_t zcFwImageSize=11104;
diff --git a/drivers/staging/otus/hal/hpfwu_txstream.c b/drivers/staging/otus/hal/hpfwu_txstream.c
new file mode 100644
index 000000000000..2b77cbacc6d6
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwu_txstream.c
@@ -0,0 +1,1017 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x4F222FE6, 0xDE947FFC, 0xE114D594,
+0x1E13D494, 0x67521E4C, 0xD494D693, 0x37402769,
+0x62528F06, 0x7201D692, 0x60602522, 0x2600C93F,
+0xD7906152, 0x2512611D, 0x264B6652, 0x2562470B,
+0x0009B017, 0xE60095AC, 0xC84060E2, 0x2F028F03,
+0x8FF93652, 0xD4887601, 0x4E0BDE88, 0xD4880009,
+0x00094E0B, 0x4E0BD487, 0x7F040009, 0xA0524F26,
+0x4F226EF6, 0x410BD184, 0xD4840009, 0x0009440B,
+0x450BD583, 0xD7830009, 0xD283E1FF, 0x2712611D,
+0xD4825029, 0xE1FFCB01, 0x1209E501, 0x12112212,
+0xE7202452, 0x4718D57E, 0x2572D27E, 0xD17EE700,
+0xD67FD47E, 0xE2012270, 0x24702172, 0xD67D2620,
+0x2641E4FF, 0xD57CE600, 0x666DE104, 0x76016063,
+0x4000626D, 0x8FF83212, 0xD5780545, 0x2520E201,
+0xD278D777, 0xE480E100, 0x22122710, 0x6613D576,
+0x666D644C, 0x76046763, 0x375C626D, 0x8FF83243,
+0xD5722712, 0xD273D772, 0xE400E101, 0x27102511,
+0x000B4F26, 0x7FCC2242, 0xD170D56F, 0xD271DB70,
+0x1F51D471, 0xD6717508, 0x1F12D771, 0x1F55710C,
+0x1FB975FC, 0x72041F2A, 0x1F13EB10, 0x1F561F44,
+0x1F781F67, 0xD86B1F2B, 0xDD6CD96B, 0xDC6CEA00,
+0xD26DDE6C, 0x89003A22, 0xD15D7A01, 0x88016010,
+0x56F88B03, 0x4218E201, 0xD1682622, 0x0009410B,
+0x440BD467, 0xD5670009, 0x0009450B, 0x6010D150,
+0x8B108801, 0xE650D14F, 0x46186212, 0x8B083266,
+0x56F9D14B, 0x2120E200, 0xCB016062, 0x2602A003,
+0x72012710, 0x60822122, 0x89098801, 0xE2C8D15A,
+0x622C6612, 0x89033626, 0x6010D158, 0x8BC88801,
+0x51F66792, 0x217252F5, 0xD6555191, 0x55FA2212,
+0x52FB6462, 0x55612542, 0x2252E400, 0x61436643,
+0x05DE6013, 0x36CC4608, 0x07DE2652, 0xC9036071,
+0x8B028801, 0x720162E2, 0x74012E22, 0x36B3664C,
+0x71048FEE, 0x66C2D147, 0x45286512, 0x265B4518,
+0x60822C62, 0x89018801, 0x0009A168, 0x6272D742,
+0x8B132228, 0xD42BD741, 0x6772D541, 0x51536242,
+0x312C327C, 0x24222228, 0x15138D05, 0x6262D63D,
+0xB1627201, 0xD6232622, 0x2622E200, 0x52916692,
+0x8B013620, 0x0009A144, 0x6061A06E, 0x001C001C,
+0x001D4020, 0x0000B38E, 0xFFFF0000, 0x12340000,
+0x001E1015, 0x00201274, 0x002039F4, 0x002018A2,
+0x00203A00, 0x00203A18, 0x00201860, 0x0020196C,
+0x00201288, 0x001C3510, 0x001C3624, 0x001E212C,
+0x002038F4, 0x0020348C, 0x002038FC, 0x00203908,
+0x00203914, 0x00203970, 0x00203974, 0x0020391C,
+0x0020391D, 0x00203920, 0x00117700, 0x0020398C,
+0x0020398A, 0x002034F0, 0x00117710, 0x001C3D30,
+0x001C36F8, 0x00117734, 0x001C3684, 0x001C3D00,
+0x001C1000, 0x001C1028, 0x00203504, 0x00203924,
+0x00117600, 0x00117740, 0x7FFFFFFF, 0x00201730,
+0x0020332A, 0x00202334, 0x00203DA4, 0x00203972,
+0x002034FC, 0x00203964, 0x001C3D2C, 0x001C36B0,
+0x00203494, 0x0011775C, 0x8801C90F, 0xA0CF8901,
+0xD1960009, 0x36206212, 0xD4958904, 0x2421E200,
+0x2162A0CC, 0x6211D193, 0x89012228, 0x0009A0C3,
+0xE202D78F, 0x75016571, 0x3123615D, 0x27518D02,
+0x0009A0BC, 0xD28C57F2, 0x62226072, 0x40094019,
+0xC90F4009, 0x8F19880A, 0x52F31F2C, 0x40196022,
+0x40094009, 0x8808C90F, 0xA0A78901, 0x60630009,
+0xCB0154F7, 0xD27E55F2, 0xE7012402, 0xD47FE100,
+0x22112572, 0x72016242, 0x2422A098, 0x8B3F8805,
+0x602252F3, 0x40094019, 0xC90F4009, 0x8B168802,
+0xE4FFD577, 0x644D6752, 0x8B102748, 0x6272D775,
+0x8B0C3260, 0x51F255F7, 0xD26DE701, 0x21722562,
+0xD571E100, 0x64522211, 0xA0777401, 0x52F32542,
+0x40196022, 0x40094009, 0x8805C90F, 0x31B38B6E,
+0xD26A8B6C, 0x672254F4, 0x7701D569, 0x61422272,
+0x1F1CE640, 0x46182159, 0x8B033160, 0x6262D665,
+0x26227201, 0xE200D65A, 0x2621B067, 0x0009A056,
+0x3123E220, 0x88038B52, 0x52F38B1E, 0x40196022,
+0x40094009, 0x8803C90F, 0xD25B8B16, 0x672254F4,
+0x7701D557, 0x61422272, 0x1F1CE640, 0x46182159,
+0x8B033160, 0x6262D655, 0x26227201, 0xE200D648,
+0x2621B043, 0x0009A010, 0xD452D551, 0xD2446752,
+0xE1007701, 0x25723A46, 0x22118F06, 0xEA00D64E,
+0x72016262, 0x2622B031, 0x2FB2D54C, 0x95736652,
+0xD44A5BF1, 0x36205241, 0x60618910, 0x8B01C803,
+0x2B22E201, 0x8FF54510, 0x57F15664, 0x6272E1F0,
+0x41284118, 0x2722221B, 0x6BF2A008, 0x6BF2A006,
+0xE200D62F, 0xD12F2621, 0x2121E200, 0xD13CE201,
+0x66122822, 0x8B012668, 0x0009AE2B, 0x450BD539,
+0xD1390009, 0xAE24E600, 0x2F862160, 0x2FA62F96,
+0x2FC62FB6, 0x2FE62FD6, 0x7FF44F22, 0xDE34D133,
+0x54116212, 0x1F4167E2, 0x2F22D432, 0xD5321F72,
+0xD2326743, 0x58417794, 0x69425A42, 0x5B166C72,
+0x60526D22, 0xCB20E600, 0xE5402502, 0x626D7601,
+0x8BFB3253, 0x55F162F2, 0x11512122, 0xD62855F2,
+0x14812E52, 0x249214A2, 0x27C2D426, 0x26D211B6,
+0xDA256742, 0xE801D925, 0x490B2A72, 0xE2011A8C,
+0x1A2C4218, 0x4F267F0C, 0x6DF66EF6, 0x6BF66CF6,
+0x69F66AF6, 0x68F6000B, 0x000007D1, 0x00203984,
+0x00203988, 0x0020398E, 0x001C3DC0, 0x0011772C,
+0x001C3B88, 0x0020396C, 0x0011773C, 0x00117744,
+0x0000F000, 0x00117764, 0x00117748, 0x00117768,
+0x0011776C, 0x01FFFFFF, 0x0011774C, 0x002034FC,
+0x00203DA4, 0x002024F8, 0x00203972, 0x001C3B9C,
+0x001C3D98, 0x001C3700, 0x001C3500, 0x001C5960,
+0x001C8960, 0x00203504, 0x001C3D00, 0x0020160C,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xDE957FAC, 0x61E0E014, 0x0F14D494, 0x710161E3,
+0xE0186210, 0xD2920F24, 0x0009420B, 0x450BD591,
+0x20080009, 0x8F126D03, 0xD28F1F07, 0x6720D48F,
+0x657CDD8F, 0x470BD78F, 0xD18F0009, 0x619C6910,
+0x46086613, 0x36184608, 0x3D6C4608, 0xE0181FD7,
+0xE58004FC, 0x604C66E2, 0x3050655C, 0x2D628F15,
+0x01FCE014, 0xDE85E500, 0x641CA008, 0x6753655D,
+0x607037EC, 0x39DC6953, 0x80947501, 0x3243625D,
+0xD67F8BF4, 0xA34EE200, 0x20082621, 0xE0148B13,
+0xE40001FC, 0xA009DE79, 0x644D671C, 0x35EC6543,
+0x69436652, 0x39DC6262, 0x74041921, 0x3273624D,
+0xA3388BF3, 0x88012D10, 0xE0148B17, 0xE70001FC,
+0x6D1C2D70, 0xDE6D1FD4, 0x32D3627D, 0xA32A8B01,
+0x677D0009, 0x667365E3, 0x61737504, 0x315C36EC,
+0x69126462, 0xAFEF7708, 0x88042492, 0xE0148B18,
+0xE40001FC, 0x671C2D40, 0x624DDE60, 0x8B013273,
+0x0009A311, 0x6943644D, 0x39EC62E3, 0x72046592,
+0x3D2C6D43, 0x615266D2, 0x21697408, 0x2512AFED,
+0x8B188805, 0x01FCE014, 0x2D40E400, 0xDE53671C,
+0x3273624D, 0xA2F68B01, 0x644D0009, 0x62E36943,
+0x659239EC, 0x6D437204, 0x66D23D2C, 0x74086152,
+0xAFED216B, 0x88312512, 0xD44A8B3A, 0x6146D94A,
+0x75046543, 0x67566442, 0x6E531F48, 0x65527E04,
+0x7EE462E2, 0x7E0464E2, 0x6EE21FE9, 0x5EF929E0,
+0x7E04D942, 0x1FEA60E2, 0x2900C901, 0xD9406EE2,
+0x29E04E09, 0x2F562F26, 0x56FAD93E, 0x6513490B,
+0xD13D7F08, 0xE71C6E0D, 0x1DE12D70, 0xDE3B6912,
+0x64E21D92, 0x1D43D13A, 0xD23A6512, 0x67221D54,
+0x1D75D239, 0x1D666622, 0x6262D638, 0x1D27A2AB,
+0x8B398830, 0x6596D92B, 0x67926696, 0x61967904,
+0x74E46493, 0x6E436992, 0x1F9B7E04, 0x1FEC6442,
+0xD9256EE2, 0x5EFC29E0, 0x7E04D924, 0x1FED60E2,
+0x2900C901, 0xD9226EE2, 0x29E04E09, 0x59FC7FFC,
+0xDE272F92, 0x2F164E0B, 0xD41F7F08, 0xE21C610D,
+0x1D112D20, 0xD2206442, 0xD41C1D42, 0x1D536542,
+0x6752D51B, 0xD71B1D74, 0x1D156172, 0x1D666622,
+0x6262D61A, 0x1D27A26F, 0x8B358833, 0x490BD919,
+0xA268EE00, 0x00002DE0, 0x00117800, 0x00203A1C,
+0x002018A2, 0x00202AAC, 0x0020390E, 0x00203A20,
+0x00203534, 0x002018EE, 0x0020390D, 0x00117804,
+0x0020398C, 0x00117810, 0x00203909, 0x0020390A,
+0x0020390B, 0x00200F64, 0x001C5864, 0x001C6864,
+0x001C7864, 0x001C59BC, 0x001C69BC, 0x001C79BC,
+0x00200FBC, 0x00200FB8, 0x89018828, 0x0009A0C0,
+0xE643DEB5, 0x326662E1, 0x1FEE8F02, 0x2E21E240,
+0x622D62E1, 0x8B013267, 0x0009A0AA, 0xE50185E1,
+0x8B013056, 0x0009A0A4, 0x2D10E101, 0x64E1B225,
+0xE64357FE, 0x652D6271, 0x89443567, 0x3563E640,
+0xE6008B05, 0x0F65E040, 0xA00FE11A, 0x615372C0,
+0x41214121, 0x41214121, 0x45214121, 0x45214521,
+0xC9036053, 0xE0406603, 0x71180F65, 0x2209E007,
+0x0F25E03C, 0xE044641D, 0xB2A365F3, 0xE33C0F46,
+0x853233FC, 0x620DDE95, 0x42086031, 0x6023610D,
+0x1323E944, 0x06FE4108, 0xE00F39FC, 0x13144E0B,
+0x67075D91, 0x60D32679, 0x0F6654FE, 0x51928542,
+0x600D4E0B, 0x60D3260B, 0x0F666492, 0x65F3B237,
+0x696156FE, 0xE640659D, 0x89383563, 0xD78359FE,
+0x79066591, 0xC9036053, 0x40004008, 0x61036203,
+0x0F26E050, 0x470BE0FF, 0x6C07600C, 0x6603605D,
+0x46214621, 0x46214621, 0x42006263, 0x4200326C,
+0x40214021, 0x4008C903, 0x6D2D30FC, 0xE8006A03,
+0xB25765F3, 0x6EA264D3, 0x2EC9E050, 0x66942AE2,
+0xD76E01FE, 0x606C470B, 0x2AE22E0B, 0x64D365F3,
+0x7801B1FD, 0xEE06628D, 0x8FE932E3, 0x5EFE7D01,
+0x61E1E400, 0x410085E1, 0x66E3310C, 0x760C711B,
+0xE70465F3, 0x68667401, 0x3A736A4D, 0x8FF92582,
+0x65F37504, 0x641DB1E3, 0x64E1B1A4, 0x0009A17B,
+0xD45B56F7, 0xEC01D25B, 0x26C0420B, 0x0009A173,
+0x06FCE018, 0x8829606C, 0x58F78B08, 0xE400D252,
+0x66222840, 0x646DB171, 0x0009A165, 0x666CE681,
+0x89013060, 0x0009A0AC, 0xD550D14F, 0x62126A56,
+0x212232AC, 0x54116C56, 0x34CC6253, 0x64521141,
+0x72085812, 0xD44A384C, 0x68221182, 0x5A136C42,
+0x3ACC3C8C, 0x11A324C2, 0x6C2272EC, 0x72105814,
+0x118438CC, 0x5A156822, 0x11A53A8C, 0x6A227210,
+0xD6405816, 0x118638AC, 0x52176C62, 0x112732CC,
+0x5A185861, 0x11A83A8C, 0x5C195A62, 0x11C93CAC,
+0x521A5C63, 0x112A32CC, 0x5A1B5864, 0x11AB3A8C,
+0x5C1C5A65, 0x11CC3CAC, 0x521D5C66, 0x112D32CC,
+0x5A1E5867, 0x11AE3A8C, 0x561F5A68, 0x36ACE840,
+0x116FDA2D, 0x6CA2381C, 0x7A946682, 0x286236CC,
+0x5C8162A2, 0x18C13C2C, 0x62A27A44, 0x362C5682,
+0xD6261862, 0x5A856262, 0x3A2C4229, 0x760418A5,
+0x56866262, 0x362C4229, 0x56F71866, 0x2620E238,
+0x16C15C81, 0x16226212, 0xE2005C11, 0x551216C3,
+0x55151654, 0x55131655, 0x55161656, 0x55821657,
+0x65821658, 0x55141659, 0x5584165A, 0x5583165B,
+0x5585165C, 0x5586165D, 0x1821165E, 0x11212122,
+0x11251122, 0x11261123, 0x28221822, 0x18241124,
+0x18251823, 0x1826A0C7, 0x00117804, 0x002033E8,
+0x00203A40, 0x002018A2, 0x00203494, 0x001C36A0,
+0x002034F0, 0x001C3CA0, 0x001C36F4, 0x001C3B88,
+0x666CE682, 0x8B203060, 0xEA2456F7, 0x26A0D194,
+0x16C15C17, 0x16225218, 0x16835819, 0x16A45A1A,
+0x16C55C1B, 0x1626521C, 0xE200581D, 0x551E1687,
+0x551F1658, 0x11271659, 0x11291128, 0x112B112A,
+0x112D112C, 0xA08E112E, 0xE683112F, 0x3060666C,
+0x52F78B0B, 0xEA00D883, 0x658222A0, 0x7804DC82,
+0x62822C52, 0xA07ED681, 0xE6902620, 0x3060666C,
+0xDA7F8B06, 0x00094A0B, 0xE20056F7, 0x2620A073,
+0x666CE691, 0x8B103060, 0x6222D276, 0x2228622C,
+0xD2788904, 0x0009420B, 0x0009A003, 0x420BD276,
+0x56F70009, 0xA05EE200, 0xE6922620, 0x3060666C,
+0xE0188951, 0xE6B00BFC, 0x666C62BC, 0x8B2A3260,
+0x02FCE014, 0x682CEA00, 0x62ADE904, 0x894A3283,
+0x6AADDD64, 0x3CDC6CA3, 0x7D046EC2, 0xDB68D467,
+0x32DC62A3, 0x4B0BDC67, 0x4C0B6D22, 0xD46664E3,
+0x00094B0B, 0x64D34C0B, 0x4B0BD464, 0xE6000009,
+0x666D6BE3, 0x76013B6C, 0x3293626D, 0x8FF72BD0,
+0xAFDA4D19, 0xE6B57A08, 0x3260666C, 0xD45C8B13,
+0x4B0BDB57, 0xD25B0009, 0x6022DB5B, 0xCB20E6FF,
+0x2202666D, 0xDB592B62, 0xE014E200, 0x56F72B20,
+0xA01002FC, 0xD4562620, 0x6542D256, 0x420BD456,
+0xA0080009, 0xDB520009, 0x52B1E600, 0x622CDB53,
+0x52F72B21, 0x7F542260, 0x6EF64F26, 0x6CF66DF6,
+0x6AF66BF6, 0x000B69F6, 0x4F2268F6, 0xE240614D,
+0x89143123, 0x3127E21F, 0x8B09D749, 0xD449614D,
+0xE00171E0, 0x5671440B, 0x26596507, 0x1761A007,
+0xE001D444, 0x6672440B, 0x26596507, 0x4F262762,
+0x0009000B, 0x614D4F22, 0x3123E240, 0xE21F8912,
+0xD73B3127, 0x614D8B08, 0x5671D23A, 0x420B71E0,
+0x260BE001, 0x1761A006, 0x6672D236, 0xE001420B,
+0x2762260B, 0x000B4F26, 0xE6400009, 0x46284618,
+0x6252D531, 0x89FC2268, 0x0009000B, 0x4618E680,
+0xD52D4628, 0x22686252, 0x000B89FC, 0xA0010009,
+0x7201E200, 0x8BFC3242, 0x0009000B, 0x4618E680,
+0xD5264628, 0x22686252, 0x000B8BFC, 0x2FE60009,
+0x7FFC4F22, 0xBFF16E53, 0x61E22F42, 0xE280D620,
+0x54E11615, 0x16464218, 0x422855E2, 0x57E31657,
+0x16786EF2, 0x26E22E2B, 0x4F267F04, 0x6EF6AFCE,
+0x00203494, 0x00117804, 0x002038F4, 0x00203908,
+0x0020050A, 0x00201008, 0x0020102E, 0x00203A58,
+0x002018A2, 0x002018E6, 0x00203A6C, 0x00203A74,
+0x00203A78, 0x001C3500, 0x001C1000, 0x0020398A,
+0x00117800, 0x002018EE, 0x00203A8C, 0x00203990,
+0x001C3704, 0x002033E8, 0x001C373C, 0x001C3700,
+0x001C370C, 0x2FD62FC6, 0x4F222FE6, 0x6C53DD10,
+0x6E43BFA4, 0x2DE2BF89, 0x0009BFA0, 0x2C1251D5,
+0x1C4154D6, 0x1C5255D7, 0x1C6356D8, 0x6EF64F26,
+0x000B6DF6, 0x61636CF6, 0xA004E600, 0x62564109,
+0x24227601, 0x36127404, 0x000B8BF9, 0x00000009,
+0x001C370C, 0x0009A16E, 0x2FE62FD6, 0xDD944F22,
+0xA0049EB2, 0xD4930009, 0x420BD293, 0x62D265D2,
+0x8BF822E8, 0x0009A004, 0xD28FD490, 0x55D1420B,
+0x22E852D1, 0xA0048BF8, 0xD48D0009, 0x420BD28A,
+0x52D255D2, 0x8BF822E8, 0x0009A004, 0xD286D489,
+0x55D3420B, 0x22E852D3, 0xA0048BF8, 0xD4860009,
+0x420BD281, 0x52D455D4, 0x8BF822E8, 0x6EF64F26,
+0x6DF6000B, 0x2FD62FC6, 0x4F222FE6, 0x6E636C73,
+0x6D53B01A, 0x64D357F4, 0xB05F65E3, 0xB07566C3,
+0xB0A40009, 0xB0A80009, 0xB0AC0009, 0xB0AC0009,
+0xB0AF0009, 0xB03154F5, 0x6CCD6C03, 0x4F2660C3,
+0x6DF66EF6, 0x6CF6000B, 0x3412D170, 0xD6700529,
+0x2650D770, 0x2742000B, 0x0009A018, 0x2FD62FC6,
+0x4F222FE6, 0x6E636C73, 0x6D53BFEE, 0x64D357F4,
+0xB03365E3, 0xB08D66C3, 0xB00F54F5, 0x6CCD6C03,
+0x4F2660C3, 0x6DF66EF6, 0x6CF6000B, 0xE503D162,
+0xD763D462, 0x21524518, 0x2472000B, 0xD45FD15E,
+0x2162E600, 0x2462000B, 0xBF734F22, 0xBF73E40A,
+0xD25C0009, 0x4118E104, 0xE40AE500, 0xBF692212,
+0xD7592252, 0xCB206072, 0x000B4F26, 0x4F222702,
+0x410BD156, 0xD556E400, 0x4F26452B, 0xD1552FE6,
+0x66126E63, 0x92104418, 0x44084528, 0x45002629,
+0x265B4408, 0x264B4400, 0x21624708, 0xD14E4708,
+0x217227EB, 0x6EF6000B, 0x1FFF03F0, 0x4F222FE6,
+0xE101DE4A, 0xBF3DE40A, 0x67E32E12, 0xE500776C,
+0xE204E130, 0x2752E40A, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x27522752, 0x27522752, 0x27522752, 0x27222712,
+0x27522752, 0x27522752, 0x27522752, 0x27522752,
+0x175ABF18, 0x2E62E600, 0x000B4F26, 0xD2346EF6,
+0xE441E101, 0x000B2212, 0xD1322242, 0xE605D432,
+0x000B2162, 0x000B2462, 0xD2300009, 0xE40AE601,
+0x2262AF00, 0x2FC62FB6, 0x2FE62FD6, 0x7FFC4F22,
+0x6C43DB2B, 0xED0060B2, 0x2B02CB03, 0xC90360B2,
+0x6E03A008, 0x89073DC2, 0xE46460B2, 0xB07CC903,
+0x7D016E03, 0x8BF52EE8, 0x8F043DC2, 0xD4212FE1,
+0x460BD621, 0x62F10009, 0x6023622D, 0x89FFC801,
+0x7F046023, 0x6EF64F26, 0x6CF66DF6, 0x6BF6000B,
+0x001C3B88, 0x00203AA0, 0x002018EE, 0x00203AA8,
+0x00203AB0, 0x00203AB8, 0x00203AC0, 0x0025E720,
+0x00203DA0, 0x002038F8, 0x001C5968, 0x001C3B40,
+0x000F8000, 0x001D4004, 0x001C3500, 0x002015E0,
+0x0020160C, 0x001C5814, 0x001C59D0, 0x001C5830,
+0x001C6268, 0x001C59A4, 0x001C639C, 0x001C581C,
+0x001C5860, 0x00203AC8, 0x002018A2, 0x8F014411,
+0x6043604B, 0x0009000B, 0x5651D52B, 0x46286052,
+0x306C000B, 0x2FC62FB6, 0x2FE62FD6, 0x4F124F22,
+0xBFF14F02, 0x6B036E43, 0xDD25DC24, 0x0009BFEC,
+0x3C0530B8, 0x4609060A, 0x46014609, 0x020A3D65,
+0x42094209, 0x32E24209, 0x4F068BF0, 0x4F264F16,
+0x6DF66EF6, 0x000B6CF6, 0x2FC66BF6, 0x2FE62FD6,
+0x4F124F22, 0xBFCF4F02, 0x6C036E43, 0xBFCBDD13,
+0x30C80009, 0x060A3D05, 0x46094609, 0x36E24601,
+0x4F068BF5, 0x4F264F16, 0x6DF66EF6, 0x6CF6000B,
+0x4F222FE6, 0xE102DE0B, 0xE403E500, 0xBFB92E12,
+0xE6062E52, 0xE7004618, 0x2E62E403, 0x4F262E72,
+0x6EF6AFB0, 0x0009000B, 0x001C1040, 0xCCCCCCCD,
+0x10624DD3, 0x001D4004, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE5007F98, 0x6453E710,
+0x6B534728, 0xEE1ADCBC, 0x6153655D, 0x315C4108,
+0x75014108, 0x6043317C, 0x0F16665D, 0xED0060B3,
+0x21B136E3, 0x81128111, 0x11D28113, 0x11D411D3,
+0x74048FEA, 0xD8B167F2, 0x1871D9B1, 0x58F12872,
+0x1981D1B0, 0x59F22982, 0x5DF45AF3, 0x54F65EF5,
+0x21921191, 0x11A211A3, 0x11D411D5, 0x11E611E7,
+0x11481149, 0xDAA855F7, 0x57F8EE00, 0x52F9DDA7,
+0x64E3D6A7, 0x2A521A51, 0xD8A7D9A6, 0x2D729AD5,
+0x6EED2622, 0x4D086DE3, 0x3DEC61E3, 0x4D084108,
+0x3D9C31EC, 0x410860B3, 0x81D12DB1, 0x4108E050,
+0x4008E7B7, 0x677C4108, 0x60B381D2, 0xE200318C,
+0x81D33472, 0x1D131DD2, 0x8D01D493, 0xD4901D24,
+0xB0B365D3, 0x64ED7E01, 0x8BDA34A2, 0x2FD2DA8C,
+0xDD9268A2, 0x2D824829, 0x7DFC64A2, 0xD287694D,
+0x6E222D92, 0x7D0C4E29, 0x68222DE2, 0x618D6AD3,
+0x2A16D784, 0xD48A6D72, 0x24D2D583, 0xD6895E72,
+0x517414E2, 0x1414EE00, 0xD1875876, 0x59781486,
+0x1498E710, 0x65E36252, 0x26E2142A, 0xE60064E3,
+0x6843644D, 0x384C4808, 0x381C4808, 0x0C866053,
+0x09CE28B1, 0x819160B3, 0x0ACE6053, 0x81A26043,
+0x0DCE6053, 0x81D360B3, 0x08CE6053, 0x18827401,
+0x624D09CE, 0x0ACE19E3, 0x1A643273, 0x75048FE0,
+0xE003D96A, 0x40186C92, 0x6D922CB1, 0x81D1DA6F,
+0x6E92E050, 0x81E24008, 0x60B36192, 0x64928113,
+0x1442E600, 0xD4696792, 0x689217A3, 0x1864E1FF,
+0x6563E703, 0x364C4608, 0x26127501, 0x3673665D,
+0xDC5B8BF8, 0x6DC2E003, 0x2DB14018, 0xD2606EC2,
+0x61C281E1, 0x1112EE00, 0xE02464C2, 0x65C21423,
+0x15E4D45B, 0xE58067C2, 0x68C28172, 0x818366E3,
+0x666D655C, 0x76046963, 0x394C6A6D, 0x8FF83A53,
+0xDB5429E2, 0x24B2DC54, 0x24C27404, 0x4F267F68,
+0x6DF66EF6, 0x6BF66CF6, 0x69F66AF6, 0x68F6000B,
+0x60116142, 0x8F03C803, 0xD23DE500, 0x8B063420,
+0xC9036011, 0x8B068802, 0x3420D239, 0x56128B03,
+0x52646513, 0x000B2422, 0x01136053, 0x2FE62FD6,
+0x7FEC4F22, 0x62536E53, 0x6D43E550, 0x4508E400,
+0xE101A001, 0x60435224, 0x81212211, 0x60538123,
+0x56E28122, 0x8BF53620, 0x16E4D238, 0xE61464F3,
+0x65E3420B, 0xE4FC65E1, 0x2E512549, 0x65F361F1,
+0x2F112149, 0xD13154D1, 0xE614410B, 0x607157D1,
+0x2701CB01, 0x7F141DE1, 0x6EF64F26, 0x6DF6000B,
+0x2FE62FD6, 0x7FEC4F22, 0x66536E53, 0x6D43E5FC,
+0x20596061, 0x2601CB01, 0x326052E2, 0x12E48B06,
+0x31E051E2, 0x52D18B04, 0x1E22A002, 0x5664AFF0,
+0x64F3D21E, 0x420BE614, 0x67E165E3, 0x2719E1FC,
+0x67F12E71, 0x271954D1, 0x65F3D118, 0x410BE614,
+0x52D12F71, 0xCB016021, 0x1DE12201, 0x4F267F14,
+0x000B6EF6, 0x00006DF6, 0x00203924, 0x002034F4,
+0x002034FC, 0x00203504, 0x0020352C, 0x00203910,
+0x00203918, 0x00100208, 0x001017C0, 0x001E210C,
+0x001C3D00, 0x00203964, 0x001000C8, 0x00117880,
+0x00117780, 0x00040020, 0x0026C401, 0x00200ED6,
+0x4F222FE6, 0xDE42624C, 0x42004208, 0x3E2CA005,
+0xD4405252, 0xBF695624, 0x65E22E62, 0x352052E1,
+0xD63D8BF6, 0x4F262622, 0x6EF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xDC394F22, 0x52C1DB39, 0x362066C2,
+0x6061891C, 0x8801C903, 0xDE348918, 0xBF37DD35,
+0x650364E3, 0x66B28503, 0x3262620D, 0xD4328907,
+0x0009BF76, 0x4D0BD431, 0xAFE60009, 0xBF3D0009,
+0xD42F64E3, 0x00094D0B, 0x0009AFDF, 0x2262D22D,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x2FD62FC6,
+0x4F222FE6, 0xDD29DC28, 0x6E4360C2, 0x04DE4008,
+0xE614D127, 0x65E3410B, 0xD127D726, 0x55E227E2,
+0x35E05254, 0x21228F04, 0x400860C2, 0x122202DE,
+0x605365C2, 0x75014008, 0x0DE606DE, 0xC90F6053,
+0x60632C02, 0x6EF64F26, 0x000B6DF6, 0x85436CF6,
+0x650D5643, 0x622D6262, 0x35277204, 0xE1008F0C,
+0x2268960C, 0xD6158B03, 0x72015261, 0xD6131621,
+0x6262E101, 0x26227201, 0x6013000B, 0x000001FF,
+0x00203504, 0x002034FC, 0x001C3D00, 0x0020352C,
+0x002038F4, 0x002018A2, 0x002034F4, 0x00203AF0,
+0x00203AF4, 0x001C3D28, 0x00203964, 0x00203924,
+0x00200ED6, 0x00203968, 0x0020396C, 0x00117754,
+0x2FC62FB6, 0x2FE62FD6, 0x7FF84F22, 0x6022D237,
+0x8D58C803, 0xDE362F01, 0xDB37DC36, 0x66C252C1,
+0x892F3620, 0xC9036061, 0x892B8801, 0xD233DD31,
+0x64D3420B, 0x1F016503, 0x880160B1, 0xD2308B04,
+0x64D3420B, 0x0009AFEA, 0x85615653, 0x8904C820,
+0xE050D72C, 0x7201027E, 0xD22B0726, 0x6453420B,
+0x89072008, 0x55F1D126, 0x64D3410B, 0xE601D727,
+0x2762AFD4, 0x55F1D226, 0x64E3420B, 0xE601D125,
+0x2162AFCC, 0xDD25DE24, 0xDC26DB25, 0x66D252D1,
+0x89183620, 0xC9036061, 0x89148801, 0xD117D41F,
+0x0009410B, 0x36E05603, 0x65038F04, 0x2B20E201,
+0x2C52AFEC, 0xD712D41C, 0x0009470B, 0xE601D115,
+0xAFE34618, 0x60F12162, 0x8907C804, 0x7F08D217,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6422B, 0x4F267F08,
+0x6DF66EF6, 0x000B6CF6, 0x00006BF6, 0x001E2100,
+0x00203504, 0x002034FC, 0x0020398C, 0x002014A0,
+0x002014CC, 0x00203494, 0x002016BE, 0x001E212C,
+0x00201530, 0x001C3D30, 0x00117880, 0x002034F4,
+0x00203914, 0x00203910, 0x0020352C, 0x00200610,
+0xE601D203, 0x1265D503, 0x000B2252, 0x00001266,
+0x001C1010, 0x0000C34F, 0x0009000B, 0x2FD62FC6,
+0x4F222FE6, 0x6D436C53, 0xEE00A004, 0x7E0164D4,
+0x644CBFF2, 0x8BF93EC2, 0x6EF64F26, 0x000B6DF6,
+0xE5006CF6, 0x6643A002, 0x76017501, 0x22286260,
+0xAFE38BFA, 0x2FE60009, 0x75076253, 0xE1086753,
+0x6043EE0A, 0x4409C90F, 0x650330E2, 0x8D014409,
+0xE630E637, 0x4110365C, 0x8FF22760, 0xE00077FF,
+0x000B8028, 0x000B6EF6, 0x000BE000, 0x2FE6E000,
+0x7FEC4F22, 0x6E436253, 0xBFDC65F3, 0xBFD06423,
+0xBFCE64E3, 0xD40364F3, 0x0009BFCB, 0x4F267F14,
+0x6EF6000B, 0x00203AF8, 0xE4FDD29F, 0xD79F6122,
+0x22122149, 0x74016022, 0x2202CB01, 0xD59C6622,
+0x22622649, 0xC8406070, 0x60528902, 0x2502CB04,
+0xE1F76452, 0x25422419, 0xE7016052, 0x2502CB40,
+0xE6026052, 0x2502C9CF, 0x47186052, 0x2502CB10,
+0xCB036052, 0x15622502, 0x1573000B, 0xD78ED58D,
+0xD48FD28E, 0xE600E100, 0x27112511, 0xAFCB2210,
+0x664C2461, 0x4600D28B, 0x6060362C, 0x000BCB10,
+0x654C2600, 0x4500D287, 0x6650352C, 0x2619E1EF,
+0x2560000B, 0xD284664C, 0x362C4600, 0xCB106060,
+0x2600000B, 0xD280654C, 0x352C4500, 0xE1EF6650,
+0x000B2619, 0x664C2560, 0x4600D27A, 0x6060362C,
+0x000BCB08, 0x654C2600, 0x4500D276, 0x6650352C,
+0x2619E1F7, 0x2560000B, 0xD273664C, 0x362C4600,
+0xCB086060, 0x2600000B, 0xD26F654C, 0x352C4500,
+0xE1F76650, 0x000B2619, 0x624C2560, 0x4200D669,
+0x6020326C, 0x4021C908, 0x40214021, 0x600C000B,
+0xD665624C, 0x326C4200, 0xC9086020, 0x40214021,
+0x000B4021, 0xD161600C, 0x341C644C, 0x000B6240,
+0xD15F602C, 0x341C644C, 0x000B6240, 0x2FE6602C,
+0x6E434F22, 0xE60A645C, 0x89143467, 0x0009BFEB,
+0x60EC640C, 0x8B028801, 0xA002E00F, 0x44092409,
+0x624C4409, 0x3263E60A, 0xBFE28905, 0x620C644C,
+0xC8806023, 0xE2008B00, 0x4F266023, 0x6EF6000B,
+0xD64C4F22, 0x88016062, 0xB2578B03, 0xA0030009,
+0xD2490009, 0x2260E640, 0xE200D648, 0x000B4F26,
+0x4F222622, 0x6062D643, 0x8B018802, 0x0009B2A0,
+0xE200D642, 0x000B4F26, 0xD53E2622, 0xE100D43E,
+0x2512E701, 0x2470000B, 0xE604D23B, 0x2260000B,
+0xD43B4F22, 0x410BD13B, 0xD53B0009, 0x6650E1FD,
+0x2619D23A, 0x2560E700, 0x000B4F26, 0x4F222270,
+0xD238D537, 0xD7386152, 0x2512611D, 0xE6FF6452,
+0x2542242B, 0xD22FD435, 0x420B666D, 0xD52E2762,
+0x6750E1FB, 0x4F262719, 0x2570000B, 0xD4304F22,
+0x410BD128, 0xD5280009, 0x6650E7F7, 0x4F262679,
+0x2560000B, 0x9425D524, 0x22496250, 0x2520000B,
+0xE4BFD521, 0x22496250, 0x2520000B, 0xD2254F22,
+0x600D8522, 0x89112008, 0x89458801, 0x89478803,
+0x89498805, 0x894F8806, 0x89558808, 0x895B8809,
+0x8961880A, 0x8967880B, 0x0009A06E, 0x0009B070,
+0x600CA06B, 0x0000FF7F, 0x001E2148, 0x001E1000,
+0x001E1108, 0x002039C4, 0x002039C6, 0x002039E5,
+0x002039A8, 0x001E103F, 0x001E105F, 0x001E102F,
+0x001E1090, 0x002039CC, 0x001E100B, 0x002039C8,
+0x00203AFC, 0x002018A2, 0x001E1028, 0x002039E4,
+0x001D4020, 0x98760000, 0x001C1000, 0x00203B08,
+0x00203B18, 0x0020399C, 0x0009B04C, 0x600CA035,
+0x0009B055, 0x600CA031, 0x6260D684, 0x8B2B2228,
+0x0009B061, 0x600CA029, 0x6260D680, 0x8B232228,
+0x0009B069, 0x600CA021, 0x6260D67C, 0x8B1B2228,
+0x0009B0C7, 0x600CA019, 0x6260D678, 0x8B132228,
+0x0009B0CD, 0x600CA011, 0x6260D674, 0x8B0B2228,
+0x0009B125, 0x600CA009, 0x6260D670, 0x8B032228,
+0x0009B13D, 0x600CA001, 0x4F26E000, 0x0009000B,
+0xD26CD16B, 0xD56C8412, 0x4000C90F, 0xD76B012D,
+0xE403D66B, 0xE20F611C, 0x2540E001, 0x25202712,
+0x2602000B, 0xE601D262, 0x30668523, 0xE0008D05,
+0xD663D260, 0xE0018122, 0x000B2602, 0xD25C0009,
+0x600D8523, 0x89052008, 0x8B0A8801, 0x6060D65D,
+0x2600CB01, 0xD457D65A, 0xE001E101, 0x000B2612,
+0x000B8142, 0xD152E000, 0x8513E501, 0x640D4518,
+0x66033453, 0xE0008D05, 0xD551D253, 0x2260E001,
+0x000B2502, 0x4F220009, 0x8513D149, 0x6453650D,
+0x62494419, 0x227D672E, 0x8801602C, 0x88028909,
+0x88038910, 0x8806891A, 0x88078935, 0xA04C893B,
+0xD5460009, 0x6652D746, 0x2762D446, 0x622C6261,
+0x2421A038, 0x2228625C, 0xD4438B3F, 0x6642D540,
+0x2562D440, 0x24018561, 0x6203A02C, 0x2008605C,
+0x88108907, 0x88208908, 0x88308909, 0xA02C890A,
+0xD23A0009, 0x6222A008, 0xA005D239, 0xD2396222,
+0x6222A002, 0x6262D638, 0xD432D531, 0x66212522,
+0xA00F626C, 0xD6352421, 0x6261D52D, 0x622CD42D,
+0xA0072562, 0xD6322421, 0x8561D529, 0x2562D429,
+0x62032401, 0x662D8515, 0x3617610D, 0x65038F01,
+0xB0CB2451, 0xA0010009, 0xE000E001, 0x000B4F26,
+0xD6190009, 0xD427E101, 0x65412610, 0xD118D717,
+0xE20F655D, 0x2752E001, 0x000B2620, 0x2FE62102,
+0xD20F4F22, 0x640C8523, 0x8B082448, 0xD511D61D,
+0x2621E200, 0x940F8451, 0xA0482049, 0xDE0D8051,
+0xC84060E0, 0xE2018D32, 0x89443427, 0xD216D615,
+0x2641420B, 0x0009A030, 0x0000FF7F, 0x002039E5,
+0x0020399C, 0x002039A8, 0x001E1100, 0x001E100C,
+0x002039C8, 0x001E1000, 0x001E1001, 0x002039D0,
+0x002039B0, 0x002039B4, 0x002039B8, 0x002039D4,
+0x002039D8, 0x002039DC, 0x002039E0, 0x00203E04,
+0x00203E0E, 0x002039C2, 0x00202886, 0x89123427,
+0xD294D693, 0x2641420B, 0xCB8084E1, 0x80E1B0F5,
+0xD69160E0, 0x2E00CB04, 0xC93F6060, 0xD68F2600,
+0xA001E001, 0xE0002602, 0x000B4F26, 0xD68C6EF6,
+0xC8806060, 0xD2868919, 0x88016021, 0xD2898B15,
+0x8524E501, 0x89103056, 0xE203D187, 0x2120D487,
+0xE00B6541, 0x0656655D, 0xE40FD585, 0x2140E702,
+0xD77E2571, 0x000BE001, 0x000B2702, 0x2FE6E000,
+0xDE804F22, 0xC88084E1, 0xD57A892C, 0x20088554,
+0x61038F28, 0x8553D77C, 0x64036672, 0x8566650C,
+0x3520620C, 0xD6798B1E, 0x651CD774, 0x2651644C,
+0x60E02741, 0x8904C840, 0x420BD275, 0xA0030009,
+0xD2680009, 0x0009420B, 0x0009B09F, 0xE201D167,
+0x60E02122, 0xCB04D464, 0x60402E00, 0x2400C93F,
+0x6023A001, 0x4F26E000, 0x6EF6000B, 0x2FB62FA6,
+0x2FD62FC6, 0xDA622FE6, 0x66A1E240, 0x3622DC5E,
+0x62638900, 0x6ED36D2C, 0x4E2136D8, 0x4E212A61,
+0xDB61D460, 0xE700A00F, 0x770162B2, 0x71026123,
+0x66212B12, 0x71026213, 0x61212B12, 0x651D666D,
+0x356C4528, 0x627C2452, 0x8BED32E3, 0xC90360D3,
+0x8B108803, 0x617367B2, 0x2B127102, 0x71026E13,
+0x2B126571, 0x655D6DE1, 0x422862DD, 0x325CE107,
+0xA00C2C10, 0x88022422, 0xA0038B01, 0x8801E203,
+0xE2018B05, 0x66B22C20, 0x655D6561, 0xE60F2452,
+0x67A12C60, 0x8B052778, 0xDD38DC44, 0xEB01EA00,
+0x2DB22CA2, 0x6DF66EF6, 0x6BF66CF6, 0x6AF6000B,
+0x2FE62FD6, 0xE240DD36, 0x362266D1, 0x62638900,
+0x3678672C, 0x7703DE38, 0x47212D61, 0x64E2D635,
+0xA00E4721, 0x6562E100, 0x62537101, 0x74012450,
+0x24204219, 0x45297401, 0x74012450, 0x24504519,
+0x621C7401, 0x8BEE3273, 0x66E24200, 0x420061D1,
+0x2118362C, 0x2E628F06, 0xDD1CD728, 0xE501E400,
+0x2D522742, 0x000B6EF6, 0x2FD66DF6, 0x4F222FE6,
+0xED0AEE01, 0x64E3BC85, 0xBC8A64E3, 0x62EC7E01,
+0x8BF732D7, 0xBC8DEE01, 0x64E364E3, 0x7E01BC92,
+0x32D762EC, 0x4F268BF7, 0x000B6EF6, 0xD1186DF6,
+0xD418920D, 0x72122122, 0x2422D617, 0xD7177204,
+0x72202622, 0x2722D116, 0x000B7230, 0x137A2122,
+0x002039C2, 0x00202992, 0x001E1015, 0x002039C8,
+0x001E1001, 0x0020399C, 0x001E1100, 0x002039C6,
+0x002039B4, 0x001E1000, 0x002039B8, 0x002039C4,
+0x00202886, 0x001E100C, 0x002039B0, 0x002039CC,
+0x002039D0, 0x002039D4, 0x002039D8, 0x002039DC,
+0x002039E0, 0x4F222FE6, 0xD6707FFC, 0x88016060,
+0xE2018951, 0x2620BFBB, 0xD56ED16D, 0xDE6E6010,
+0x64E36552, 0x7402C840, 0x8D22D16C, 0xD26C7502,
+0xE601D76C, 0xE7042722, 0x76016255, 0x626C2421,
+0x8FF93273, 0xD4637402, 0x6242E601, 0x640D8528,
+0x67494419, 0x275D657E, 0x81E4607C, 0xE417D562,
+0x67557601, 0x3243626C, 0x8FF92171, 0xA0207102,
+0xD25E0009, 0xE601D75B, 0xE7042722, 0x76016255,
+0x626C2421, 0x8FF93273, 0xD4527402, 0x6242E601,
+0x640D8528, 0x67494419, 0x275D657E, 0x81E4607C,
+0xE417D553, 0x67557601, 0x3243626C, 0x8FF92171,
+0x92897102, 0xD2462E21, 0x5E23D74E, 0x64F22FE2,
+0x604365F2, 0x2700C980, 0xC9606043, 0x80716103,
+0xC9036043, 0x80724519, 0x65F2605C, 0x817266F2,
+0x46194629, 0x606C4529, 0x4018645C, 0x8173304C,
+0x21185E23, 0x64F22FE2, 0x6E4C62F2, 0x602C4219,
+0x66F262F2, 0x46294018, 0x461930EC, 0x42298174,
+0x652C606C, 0x305C4018, 0x81758F07, 0x0009BC96,
+0x2228620C, 0xA00A8908, 0x60130009, 0x8B038840,
+0x0009B009, 0x0009A003, 0xE202D62F, 0x7F042622,
+0x000B4F26, 0x4F226EF6, 0x8552D52A, 0x8830600D,
+0x88318903, 0xA0348923, 0x85550009, 0xD428D727,
+0x85532701, 0x610DD627, 0x24124118, 0x460BD426,
+0xD7230009, 0xD226D425, 0x6572420B, 0xE230D120,
+0x42286712, 0x2729E620, 0x37604628, 0xD6218B03,
+0xA016E200, 0xD61F2622, 0xA012E202, 0xD1182622,
+0x6212E530, 0xE6204528, 0x46282259, 0x89083260,
+0xD41AD119, 0xE601D513, 0x2160450B, 0x472BD718,
+0x4F264F26, 0x0009000B, 0x0000060A, 0x002039E4,
+0x001E1000, 0x002039D0, 0x00203E04, 0x00203E10,
+0x00203DA8, 0x002039B8, 0x00203DD8, 0x00203DD6,
+0x00203DAA, 0x0020399C, 0x002039C8, 0x002039B4,
+0x002039B0, 0x002018A2, 0x00203B24, 0x00203B28,
+0x002018EE, 0x002039CC, 0x001E100B, 0x00203B3C,
+0x00114004, 0x4F222FE6, 0xDE967FFC, 0x200884E9,
+0x2F008D06, 0xD695D494, 0x0009460B, 0x64F0B19A,
+0x6620D293, 0x89022668, 0xC9BF60E0, 0x7F042E00,
+0x000B4F26, 0x000B6EF6, 0x2FE60009, 0xDE8D4F22,
+0x60E0D68D, 0xCBC0D48D, 0x62602E00, 0xC803602C,
+0x40218904, 0x70014021, 0x6603A002, 0x66034009,
+0xD687616D, 0xE500A004, 0x75016262, 0x74042422,
+0x3213625D, 0xD2838BF8, 0x0009420B, 0xC9BF84E2,
+0x4F2680E2, 0x6EF6000B, 0x2FE62FD6, 0x7FFC4F22,
+0x6260D67D, 0x89442228, 0xD572E100, 0x60502610,
+0xCB40D47A, 0x2500440B, 0x8D052008, 0x62E06E03,
+0x7104612C, 0x2F11A006, 0xD475D66D, 0xDD756760,
+0x657C4D0B, 0xE23C6D1D, 0x8B033D27, 0xD267D472,
+0x0009420B, 0x4D214D21, 0xA005D770, 0x66E6E400,
+0x357C4508, 0x74012562, 0x35D3654D, 0xD76C8BF7,
+0x6172E003, 0x81114018, 0x6E7260F1, 0x81E2700C,
+0xD4686172, 0xDD688113, 0x4D0BDE68, 0xE2016572,
+0xD4672E22, 0x420BD255, 0xD6560009, 0xC93F6060,
+0x7F042600, 0x6EF64F26, 0x6DF6000B, 0x2FC62FB6,
+0x2FE62FD6, 0xD25F4F22, 0x6B436E73, 0x420B6C53,
+0x20086D63, 0x64038D1C, 0xE50ED149, 0x32526210,
+0x60C38916, 0x804124B0, 0x814160D3, 0xA007E500,
+0x655D61BC, 0x00EC6053, 0x364C6653, 0x80647501,
+0x3213625D, 0xD63B8BF5, 0xC9BF6060, 0x2600A008,
+0xD23AD44D, 0x6EF64F26, 0x6CF66DF6, 0x6BF6422B,
+0x6EF64F26, 0x6CF66DF6, 0x6BF6000B, 0x7FC44F22,
+0x720262F3, 0x22512F41, 0x45297202, 0x60632251,
+0xE5C4E682, 0x67F38121, 0x655C666C, 0xE408BFB6,
+0x4F267F3C, 0x0009000B, 0x2F962F86, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0xE1007FC4, 0x6513ECFF,
+0x6B136CCD, 0xDE36D735, 0xEDFF64F3, 0xD835EA04,
+0x6053655C, 0x027D4000, 0x32C0622D, 0x66038D0D,
+0x09ED6063, 0x2491027D, 0x24217402, 0x698202ED,
+0x3928622D, 0x74022892, 0x75017104, 0x6063625C,
+0x07D532A2, 0x0EB58FE4, 0x2448641C, 0xE6808905,
+0x67F3E5C5, 0xBF79666C, 0x7F3C655C, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0xD11E68F6,
+0x6012D21E, 0xCB20E405, 0x2102E500, 0x000B2242,
+0x00002252, 0x001E1017, 0x00203B40, 0x002018A2,
+0x0020390E, 0x001E1015, 0x001E10BF, 0x00117800,
+0x001E10FC, 0x00200610, 0x00203914, 0x00202AEA,
+0x00203B44, 0x002018EE, 0x00203B60, 0x0011788C,
+0x00203910, 0x002034F4, 0x00201530, 0x001E2130,
+0x00203B68, 0x00202AAC, 0x00203B6C, 0x00203974,
+0x0020397C, 0x00203DA4, 0x001C3500, 0x001D4004,
+0xD564D163, 0xE400D764, 0x2142E20F, 0x17411154,
+0xD5622722, 0x9669D762, 0x15412572, 0x96661562,
+0xE6011565, 0xD55F1165, 0x666CE6F8, 0x25422542,
+0x25422542, 0x25422542, 0x25622542, 0x7601E727,
+0x67632572, 0x25627797, 0xE7042572, 0x2572E248,
+0xE2192522, 0xE2702522, 0x25422542, 0x25422542,
+0x25222542, 0x2522E20C, 0x25422542, 0x25422542,
+0x25422542, 0x25422542, 0x000B154A, 0xE2081145,
+0x0009422B, 0x2FE62FD6, 0x7FFC4F22, 0xC8206043,
+0x6E438D02, 0x0009BE67, 0xC81060E3, 0xBE648901,
+0x60E30009, 0x8901C840, 0x0009BE86, 0xC80160E3,
+0xDD3D8938, 0xC80260D0, 0x2F008D03, 0x460BD63B,
+0x60F00009, 0x8902C804, 0x460BD639, 0x62F00009,
+0xC8806023, 0x60D08902, 0x2D00C97F, 0xC8016023,
+0xD6348906, 0x0009460B, 0x0009A007, 0x51630601,
+0x8902C808, 0x460BD630, 0x60F00009, 0x8902C810,
+0x420BD22E, 0xD52E0009, 0x88026052, 0xD22D8B03,
+0xA005E604, 0x88012260, 0xD22A8B02, 0x2260E601,
+0x2522E200, 0xC88060E3, 0xD227892D, 0x60E36E20,
+0x8902C880, 0x420BD225, 0x60E30009, 0x8902C840,
+0x420BD223, 0x60E30009, 0x8902C802, 0x420BD221,
+0x60E30009, 0x890DC804, 0xDD20D11F, 0x0009410B,
+0x0009BF0D, 0x0009BF4C, 0xD51ED41D, 0x2470E708,
+0x25D2BF85, 0xC80860E3, 0xD21B8905, 0x4F267F04,
+0x422B6EF6, 0x7F046DF6, 0x6EF64F26, 0x6DF6000B,
+0x001C581C, 0xA000A000, 0x001D0100, 0x001D4000,
+0x00040021, 0x001C589C, 0x001E1021, 0x00201A90,
+0x00201AB2, 0x00202114, 0x00201ACA, 0x00201AD8,
+0x002039C8, 0x001E100B, 0x001E1028, 0x00201B44,
+0x00201B50, 0x00201AE0, 0x00201AFE, 0x12345678,
+0x001E1000, 0x0010F100, 0x00201B2C, 0x644CD6A7,
+0x000B346C, 0xD6A62450, 0x346C644C, 0x2450000B,
+0x644CD6A4, 0x000B346C, 0x625C2450, 0x4208616D,
+0x42084119, 0x42006019, 0x670E614C, 0xD49E321C,
+0x4200207D, 0x324CC90F, 0x2200000B, 0x4208625C,
+0x42004208, 0x324C644C, 0x4200D498, 0x000B324C,
+0x2FE62260, 0x614C4F12, 0x4100D493, 0x6710314C,
+0xE29F666D, 0x27294619, 0x6E536269, 0x672E6573,
+0x4221227D, 0x42214221, 0x7601662C, 0xE4014608,
+0x34E84608, 0x644C4600, 0x071A0467, 0x2150257B,
+0x000B4F16, 0x4F226EF6, 0xD2857FE8, 0x88016021,
+0xD2848B7B, 0x26686621, 0xD2838B77, 0x26686621,
+0xE50F8B73, 0xE401BFA2, 0xBFA4E501, 0xE586E400,
+0xE400655C, 0x2F50BFA4, 0xBFA1E401, 0xE602E506,
+0x60634618, 0x81F2E401, 0x6543BF9F, 0xE40185F2,
+0xBFAB6543, 0x85F26603, 0x6543E401, 0x6603BFB1,
+0xE40265F0, 0x6053756C, 0x80F8BF80, 0xBF82E402,
+0x84F8E512, 0x7090E402, 0x6503BF82, 0x4618E602,
+0x81F66063, 0xBF80E402, 0x85F6E500, 0x6603E402,
+0xE500BF8C, 0xE40285F6, 0xBF926603, 0xE5FEE500,
+0xE010655C, 0xBF61E403, 0xE5130F54, 0xE40EBF63,
+0x05FCE010, 0xBF63E40E, 0xE5007585, 0xBF64E403,
+0xE500E640, 0xBF71E403, 0xE500E640, 0xBF78E403,
+0xE5FFE640, 0xE014655C, 0xBF47E404, 0xE40F0F54,
+0xE504BF49, 0x05FCE014, 0xBF49E40F, 0xE5017584,
+0xBF4AE640, 0xE501E404, 0xBF57E640, 0xE501E404,
+0xE404E640, 0xAF5C7F18, 0x7F184F26, 0x000B4F26,
+0x4F220009, 0xD2427FF0, 0x88016021, 0xD2418B71,
+0x26686621, 0xD2408B6D, 0x26686621, 0xE50F8B69,
+0xE401BF1C, 0xBF1EE501, 0xE586E400, 0xE400655C,
+0x2F50BF1E, 0xBF1BE401, 0xE401E506, 0xBF1C6543,
+0xE401E640, 0xBF296543, 0xE401E640, 0xBF306543,
+0x65F0E640, 0x756CE402, 0xBEFF6053, 0xE40280F4,
+0xE512BF01, 0xE40284F4, 0xBF017090, 0xE6406503,
+0xBF02E402, 0xE640E500, 0xBF0FE402, 0xE640E500,
+0xBF16E402, 0xE5FEE500, 0x6053655C, 0xBEE5E403,
+0xE51380F8, 0xE40EBEE7, 0xE40E84F8, 0xBEE77085,
+0xE5006503, 0xBEE8E640, 0xE500E403, 0xBEF5E640,
+0xE500E403, 0xBEFCE640, 0xE5FFE403, 0x6053655C,
+0xBECBE404, 0xE40F80FC, 0xE504BECD, 0xE40F84FC,
+0xBECD7083, 0xE5016503, 0xBECEE640, 0xE501E404,
+0xBEDBE640, 0xE501E404, 0xE404E640, 0xAEE07F10,
+0x7F104F26, 0x000B4F26, 0x00000009, 0x001E102F,
+0x001E1080, 0x001E1090, 0x001E103F, 0x001E103E,
+0x002039C2, 0x002039C4, 0x002039C6, 0xD21DD11C,
+0x66206010, 0x676C7001, 0x3700C90F, 0xE5008D13,
+0x67106210, 0x7701622C, 0x64232170, 0xD6166010,
+0x44084408, 0x3428C90F, 0x62602100, 0x7201D513,
+0x44082620, 0x000B354C, 0xD10F6053, 0x25586510,
+0xE6008D13, 0xD60DD40B, 0x655C6540, 0x47086753,
+0x37584708, 0x47086540, 0x24507501, 0x367C6040,
+0x2400C90F, 0x72FF6210, 0x000B2120, 0x00006063,
+0x0020390D, 0x0020390C, 0x0020390E, 0x00203534,
+0x7FFC4F22, 0xE680D19F, 0x666C6212, 0xD29E2F22,
+0x67F36563, 0x420B7542, 0x7F04E404, 0x000B4F26,
+0xE6800009, 0xD298666C, 0xE7006563, 0x422B7540,
+0xE6806473, 0xD294666C, 0xE7006563, 0x422B7543,
+0x2F866473, 0x2FA62F96, 0x2FC62FB6, 0x2FE62FD6,
+0x7FCC4F22, 0xDC8ED28D, 0x72011F21, 0xDB8D1F22,
+0xD18EDE8D, 0x66125211, 0x8B013620, 0x0009A0E5,
+0xC9036061, 0x8B018801, 0x0009A0DF, 0xD288D487,
+0xED84420B, 0x2F025503, 0x30D0845C, 0xA0B88901,
+0xD1840009, 0x626C6610, 0x88016023, 0xD1828B68,
+0x62101FC3, 0x895B2228, 0xE003D480, 0x40186742,
+0x68421772, 0xD57EE900, 0x81816DB3, 0x7D042190,
+0x67D26AB2, 0x64E26852, 0x1F491F57, 0x740464E3,
+0x1FA46542, 0x65431F5A, 0x625275F8, 0x1F761FD5,
+0x6D531F2B, 0xDA74D773, 0x7D94D274, 0x68D21F88,
+0x6AA26972, 0xD1726022, 0x2202CB20, 0xE1401F1C,
+0x7601E600, 0x3213626D, 0x56F48BFB, 0x52F651F5,
+0x21222B62, 0x52F851F7, 0x212256F9, 0x2E6251FA,
+0x51FB2412, 0x2D822512, 0xD9662792, 0x29A2DD5F,
+0x6AD2D965, 0xD9646892, 0x68D21A84, 0x6081DA63,
+0x2801CB01, 0xD86266D2, 0x2A622962, 0xED015AFC,
+0x2AD2480B, 0x2AD24D18, 0x62D2DD5E, 0x2D227201,
+0xD15056F3, 0xE2026062, 0x2602CB01, 0x2120A03D,
+0x8B3A2228, 0xE401DD58, 0x2140E600, 0xE01C2D62,
+0xC801005C, 0xD4558B0A, 0xE600D755, 0xED7D2472,
+0x626C7601, 0x8BFB32D3, 0x24D2DD52, 0xE2FE68C2,
+0x2C822829, 0x095CE01E, 0xE01F5DF1, 0x0A5C2D90,
+0x751051F2, 0xED0621A0, 0xD74BE600, 0x8456D44B,
+0x27007601, 0x696C6854, 0x248039D3, 0x8FF67401,
+0xDA477701, 0x2A10E194, 0xE2007A01, 0x7A0F2A20,
+0xD130E805, 0x66102A80, 0x6023626C, 0x89088801,
+0xD240D42A, 0x420B65F2, 0xD131ED01, 0xAF304D18,
+0x65F221D2, 0x8553D43C, 0x620D6642, 0x89073262,
+0xD13BD43A, 0x0009410B, 0xE601D73A, 0x2762AF1A,
+0xD134D41E, 0x410B65F2, 0xD125ED01, 0xD637D436,
+0x460B4D18, 0xAF0D21D2, 0x7F340009, 0x6EF64F26,
+0x6CF66DF6, 0x6AF66BF6, 0x000B69F6, 0x4F2268F6,
+0x85467FF4, 0x2F01E681, 0x666C8547, 0x854881F1,
+0x81F2D209, 0x67F38542, 0x854381F3, 0x81F4E40C,
+0x65636053, 0x420B81F5, 0x7F0C7540, 0x000B4F26,
+0x00000009, 0x001C3D9C, 0x0020245C, 0x0011779A,
+0x001C36F8, 0x001C3B9C, 0x001C3704, 0x0020352C,
+0x002014A0, 0x0020391D, 0x0020391C, 0x00203918,
+0x001C3D98, 0x001C3BB4, 0x001C5960, 0x001C3500,
+0x001C3D30, 0x001C8960, 0x00203504, 0x001C3D00,
+0x0020160C, 0x00117730, 0x00203920, 0x001C582C,
+0x2000A000, 0x0000A000, 0x0011778C, 0x00117792,
+0x00117788, 0x002014CC, 0x002038F4, 0x002034F4,
+0x00201530, 0x001E2130, 0x00203D84, 0x002018A2,
+0x2F962F86, 0x2FB62FA6, 0x2FD62FC6, 0x4F222FE6,
+0xD19B7FEC, 0x2F12E000, 0x6103D49A, 0x1F4281F2,
+0xDD9ADA99, 0xD69A6813, 0xE0014808, 0x460BDE99,
+0x38EC4800, 0x65A21F03, 0x352052A1, 0xA23E8B01,
+0x60510009, 0x8801C903, 0xA2388B01, 0x52530009,
+0x32E0DE91, 0xD9918B10, 0x64A3490B, 0x4B0BDB90,
+0xDE906403, 0xD791D690, 0xEC01D591, 0x2E02E100,
+0x271026C0, 0x2502AFDF, 0xC8018551, 0xA1578B01,
+0x62510009, 0x4200622D, 0x5E53366A, 0x85E2226D,
+0xC903642C, 0x85E36603, 0x6053650D, 0x40214021,
+0x4500C93F, 0x322A6703, 0x6053252D, 0xC901D17F,
+0x60106C03, 0x8801D97F, 0xDB7F8B05, 0x2120E200,
+0xCB0160B2, 0xD17D2B02, 0x88016011, 0x65A28B0A,
+0x8D042448, 0x9B9E6251, 0xA00322B9, 0x919B2521,
+0x2521221B, 0x37B3EB10, 0x2448895E, 0xD4738B07,
+0x22286241, 0x60638903, 0xA05781F8, 0xD5706473,
+0x46084608, 0x85E26273, 0x46006B50, 0x362C4200,
+0x2BB8C910, 0x8F1F6463, 0x26686603, 0xD2698911,
+0x062D6043, 0x4119616D, 0x6B0E6019, 0x81F820BD,
+0x880160C3, 0x646C8F2C, 0x880F6073, 0xA0278B1B,
+0xD2610009, 0x052D6043, 0x4119615D, 0x670E6019,
+0x645C207D, 0x81F8A01C, 0x890F2668, 0x6043D25B,
+0x6B5D052D, 0x60B94B19, 0x201D610E, 0x60C381F8,
+0x8F0D8801, 0x6473645C, 0xEC00A00A, 0x6043D254,
+0x625D052D, 0x60294219, 0x207D670E, 0x81F8645C,
+0x880285F8, 0x85E1890A, 0x8D07C820, 0xE6DC6203,
+0x60232269, 0x81E1A002, 0x644CE4FF, 0x6210D149,
+0x89012228, 0x644CE4FF, 0x654DEBFF, 0x35B06BBC,
+0xDB368B2B, 0x64A34B0B, 0x410BD135, 0x54036403,
+0x85446E03, 0xC948DB40, 0xDC408808, 0xBEAE8B01,
+0x64B3E502, 0x65E34C0B, 0xDB3DEC01, 0xD13D2DC2,
+0x621260B2, 0x72017001, 0x21228805, 0x2B028F08,
+0x666CE680, 0x6563D238, 0x7549E700, 0x6473420B,
+0xA030D436, 0x7FFF0009, 0x85E28000, 0x20B9EBFC,
+0x610381E2, 0x942A85E3, 0x62032049, 0x450885F8,
+0x81E2201B, 0xC90160C3, 0x40084018, 0x40084008,
+0x4000225B, 0x6023220B, 0x85E481E3, 0x4118E108,
+0x81E4201B, 0xE40262A2, 0x20B98521, 0x67A28121,
+0xCB016071, 0x85F82701, 0x89033042, 0xECE785E2,
+0x81E220C9, 0x490BD41E, 0xA03B0009, 0x7E030009,
+0x001C3D30, 0x00203D90, 0x00203504, 0x001E212C,
+0x002033E8, 0x001C3D00, 0x00117780, 0x002014A0,
+0x0020166C, 0x0011770C, 0x0020391C, 0x0020391D,
+0x00203918, 0x002018A2, 0x001C36F8, 0x00203990,
+0x00203DA0, 0x00203B84, 0x00203C04, 0x00203C84,
+0x00203D04, 0x00203908, 0x002034FC, 0x002014CC,
+0x00203994, 0x00203998, 0x0020245C, 0x00203D88,
+0x00203D8C, 0x602262F2, 0x40094019, 0xC90F4009,
+0x8B0B880A, 0x60E2DE8C, 0x40094019, 0xC90F4009,
+0x8B038808, 0xCB0160A2, 0x2802A006, 0x65E2DE87,
+0x2E527501, 0x286266A2, 0x52F366F2, 0x2622AE83,
+0xD2838551, 0xDE83C802, 0xA0958B01, 0x420B0009,
+0x4E0B64A3, 0x5E036403, 0x85E46503, 0x4918E908,
+0xD77D209B, 0xE04C81E4, 0xDC7C0B7E, 0x7B01D97C,
+0x61C207B6, 0x71016690, 0x8D062668, 0xD4792C12,
+0x420BD279, 0xA070EB01, 0x62512DB2, 0x4B18EB0F,
+0x22B9E102, 0x32104118, 0x85518B0F, 0x2029E2FC,
+0x60518151, 0xCB0172E0, 0x85E12501, 0x202994A3,
+0x85E481E1, 0xA0522049, 0x675181E4, 0x4719677D,
+0x667E6779, 0x7701276D, 0x6903607C, 0x88014918,
+0x25918F3E, 0x6B12D161, 0x21B27B01, 0x660D85E3,
+0x40216063, 0xC93F4021, 0x6C034600, 0x262D322A,
+0xC8016063, 0xDB5ED15D, 0x967D8901, 0xE6002C6B,
+0x666C67CD, 0x40006063, 0x622D021D, 0x8D0E3270,
+0x60436403, 0xE9FF021D, 0x8B013290, 0x01C5A007,
+0x626C7601, 0x3292E904, 0x646C8BEB, 0x60434400,
+0xD15004BD, 0x0B457401, 0x669D6911, 0x89073670,
+0x602D6211, 0x890388FF, 0xE201DB4B, 0x2B2021C1,
+0xECFC8551, 0x815120C9, 0xCB016051, 0xDC472501,
+0x64A34C0B, 0x51F366F2, 0x85EF2612, 0x54F2D244,
+0x650D420B, 0x0009ADE7, 0xE500DC42, 0x420B2C52,
+0x4E0B64A3, 0x54036403, 0x85446E03, 0x6703E908,
+0x65034918, 0x27998541, 0xDB323790, 0x8F0BD932,
+0x6013610D, 0x8B07C820, 0xC9486053, 0x8B038808,
+0xE501BD4D, 0x0009A005, 0x2128D233, 0xBD468901,
+0x64B3E500, 0x490B65E3, 0xADBCEC01, 0x85F22DC2,
+0x7001EE04, 0x31E7610D, 0x8D0281F2, 0xADA97A08,
+0x7F140009, 0x6EF64F26, 0x6CF66DF6, 0x6AF66BF6,
+0x000B69F6, 0xF7FF68F6, 0x2FE68000, 0xD2234F22,
+0x60E36E22, 0x8D02C840, 0xBBF922E2, 0xE2400009,
+0x2E284218, 0xBC048901, 0x60E30009, 0x8905C810,
+0xD21CD41B, 0x0009420B, 0x0009BC03, 0xC80560E3,
+0xBD6D8901, 0x60E30009, 0x8902C802, 0xAC004F26,
+0x4F266EF6, 0x6EF6000B, 0x001C3D3C, 0x00117760,
+0x002014A0, 0x0020166C, 0x00203494, 0x00203DA4,
+0x00203908, 0x002034FC, 0x002014CC, 0x00203974,
+0x0020397C, 0x00203970, 0x00203972, 0x00201530,
+0x002018EE, 0x00203994, 0x00008000, 0x001C3510,
+0x00203D98, 0x002018A2, 0x080A0C0E, 0x00020406,
+0x1A1C1E20, 0x12141618, 0x2E303234, 0x26282A2C,
+0x3A3C3E40, 0x6C625648, 0x41112F26, 0xE2208F18,
+0x890B3123, 0x321CD204, 0xD1026220, 0x412B312C,
+0x00090009, 0x00203412, 0x002033C8, 0x000BE000,
+0x400062F6, 0x40004000, 0x40004000, 0x40004000,
+0x62F6000B, 0x40004000, 0x40004000, 0x40004000,
+0x40184000, 0x62F6000B, 0x40004000, 0x40004000,
+0x40004000, 0x40284000, 0x62F6000B, 0x40004000,
+0x40184000, 0x000B4028, 0xC90F62F6, 0x40054005,
+0x40054005, 0x62F6000B, 0x4005C907, 0x40054005,
+0x62F6000B, 0x4005C903, 0x000B4005, 0xC90162F6,
+0x000B4005, 0x000062F6, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x544F0D0A, 0x46205355, 0x00003A57,
+0x206C754A, 0x32203120, 0x20383030, 0x323A3132,
+0x34333A38, 0x00000000, 0x00000D0A, 0x00000043,
+0x42707372, 0x3D206675, 0x554E203D, 0x202C4C4C,
+0x6E49677A, 0x4E497274, 0x6D754E51, 0x0000003D,
+0x61766E49, 0x2064696C, 0x72657375, 0x20726F20,
+0x2079656B, 0x00214449, 0x52504545, 0x57204D4F,
+0x65746972, 0x6461202C, 0x003D7264, 0x6C617620,
+0x0000003D, 0x00000A0D, 0x435F4D5A, 0x465F444D,
+0x4C445F57, 0x494E495F, 0x00000054, 0x6E6B6E55,
+0x206E776F, 0x6D6D6F63, 0x3D646E61, 0x00000000,
+0x203A3051, 0x00000020, 0x203A3151, 0x00000020,
+0x203A3251, 0x00000020, 0x203A3351, 0x00000020,
+0x203A3451, 0x00000020, 0x2B434741, 0x73696F4E,
+0x61432065, 0x7262696C, 0x6F697461, 0x6166206E,
+0x6F206C69, 0x6974206E, 0x0D0A656D, 0x00000000,
+0x00000072, 0x00205220, 0x00000D0A, 0x62735576,
+0x7473725F, 0x00000A0D, 0x62735576, 0x7375735F,
+0x646E6570, 0x00000A0D, 0x62735576, 0x7365725F,
+0x000A0D6D, 0x00000044, 0x44387570, 0x72637365,
+0x6F747069, 0x3D584572, 0x00000000, 0x00000047,
+0x00000042, 0x72746E49, 0x6D652051, 0x2C797470,
+0x49677A20, 0x4972746E, 0x754E514E, 0x00003D6D,
+0x654C7245, 0x0000006E, 0x00000049, 0x20746F4E,
+0x756F6E65, 0x49206867, 0x4220514E, 0x0A0D6675,
+0x00000000, 0x000000FF, 0x00020001, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00020003, 0x01090108,
+0x0002010A, 0x02000003, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x000000FF, 0x00020001, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00020003, 0x01090108,
+0x0002010A, 0x00030003, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00FF010F, 0x01090108,
+0x010B010A, 0x0200010F, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x010E010D, 0x00FF010F, 0x01090108,
+0x010B010A, 0x010F010F, 0x02020201, 0x02040203,
+0x02060205, 0x02020200, 0x02040203, 0x020C020B,
+0x020E020D, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF,
+0x00FF00FF, 0x00205220, 0x00000046, 0x00000059,
+0x73204142, 0x003D7165, 0x49544120, 0x0000204D,
+0x00000000, 0x00000000, 0x002E0209, 0x80000101,
+0x000409FA, 0x00FF0400, 0x05070000, 0x02000201,
+0x82050700, 0x00020002, 0x03830507, 0x07010040,
+0x40030405, 0x02090100, 0x0101002E, 0x09FA8000,
+0x04000004, 0x000000FF, 0x02010507, 0x07000040,
+0x40028205, 0x05070000, 0x00400383, 0x04050701,
+0x00004002, 0x00000000, 0x00000000, 0x07090000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+const u32_t zcFwImageSize=15936;
diff --git a/drivers/staging/otus/hal/hpfwuinit.c b/drivers/staging/otus/hal/hpfwuinit.c
new file mode 100644
index 000000000000..ed80ffafaffc
--- /dev/null
+++ b/drivers/staging/otus/hal/hpfwuinit.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+
+const u32_t zcFwImage[] = {
+0x0009000B, 0x7FFC4F22, 0xD695D494, 0x0009460B,
+0xD494E570, 0x4518B01E, 0x89042008, 0xD690D492,
+0x462B7F04, 0xB0124F26, 0xD2900009, 0x420BD490,
+0xE6000009, 0x949AD58F, 0xC8406052, 0x2F028F03,
+0x8FF93642, 0x7F047601, 0x000B4F26, 0xD28A0009,
+0x0009422B, 0x2FD62FC6, 0x4F222FE6, 0xD6877FEC,
+0x626061F3, 0x2F208461, 0x846280F1, 0x80F27110,
+0x6D438463, 0x846480F3, 0x80F46413, 0x6C538465,
+0x846680F5, 0x80F6E500, 0xD77D8467, 0x846880F7,
+0x80F8EE04, 0x80F98469, 0x80FA846A, 0x80FB846B,
+0x80FC846C, 0x80FD846D, 0x80FE846E, 0x80FF846F,
+0x6653655C, 0x7501367C, 0x665C6260, 0x242036E3,
+0x74018FF6, 0x66F32F16, 0xE7107604, 0xB00D65C3,
+0x6E0364D3, 0xD46B7F04, 0x420BD26B, 0x60E36503,
+0x4F267F14, 0x6DF66EF6, 0x6CF6000B, 0x2FB62FA6,
+0x2FD62FC6, 0x4F222FE6, 0x3F3C933A, 0x4108E141,
+0x31FCE200, 0x11733526, 0x21521162, 0x11418D02,
+0xE0FFA098, 0x4A18EA01, 0x262066F3, 0x32A27201,
+0x76018FFB, 0x6BE3EE00, 0xE0446CF3, 0x00FE4008,
+0x450BD556, 0x660361B3, 0x4008E043, 0x6DC004FE,
+0x014C6063, 0x31EC3EDC, 0x60E36E1C, 0x7B0107FC,
+0x2C703BA2, 0x8FE80FD4, 0xE0427C01, 0xEB004008,
+0x70FC07FE, 0x6EB36CB3, 0xA0200AFE, 0x2710EDFF,
+0x7C01FEE0, 0x60C36CCC, 0x657002FC, 0x6BBC3B2C,
+0x01FC60B3, 0x0F1460C3, 0x0F2460B3, 0x04FC60C3,
+0x342C7E01, 0x01FC604C, 0x251A62D3, 0xD43C225A,
+0x2750602C, 0x064E4008, 0x2D6A4D19, 0x3EA27701,
+0x66D78BDF, 0x4018E001, 0x0F646563, 0x70014519,
+0x0F544629, 0x0F647001, 0x70014619, 0x90420F64,
+0xE0450EFE, 0xEA014008, 0xE0460FF6, 0x4A184008,
+0xED0067F3, 0x0FF637AC, 0x0FF67004, 0xE345E104,
+0x7C014308, 0x6CCC33FC, 0x60C36432, 0x5531024C,
+0x6BBC3B2C, 0x045C60B3, 0x60C35A32, 0x60B30A44,
+0x60C30F24, 0x6A7006FC, 0x606C362C, 0x66E005FC,
+0x6A5C64AC, 0x626C24AA, 0x89053420, 0x4D084D08,
+0xCB0460D3, 0x600BA006, 0x7D014110, 0x8FD67701,
+0xE0007E01, 0x3F3C9308, 0x6EF64F26, 0x6CF66DF6,
+0x000B6BF6, 0x01386AF6, 0x00000120, 0x00200D54,
+0x002002BE, 0x00102800, 0x00200D64, 0x0010F00A,
+0x0010F000, 0x001C001C, 0x00103252, 0x00200DA0,
+0x0010FFFC, 0x00200D7C, 0x0020032C, 0x00200370,
+0x00200954, 0x0009000B, 0x2FD62FC6, 0x4F222FE6,
+0x6D436C53, 0xEE00A004, 0x7E0164D4, 0x644CBFF2,
+0x8BF93EC2, 0x6EF64F26, 0x000B6DF6, 0xE5006CF6,
+0x6643A002, 0x76017501, 0x22286260, 0xAFE38BFA,
+0x2FE60009, 0x75076253, 0xE1086753, 0x6043EE0A,
+0x4409C90F, 0x650330E2, 0x8D014409, 0xE630E637,
+0x4110365C, 0x8FF22760, 0xE00077FF, 0x000B8028,
+0x4F226EF6, 0xBFE47FEC, 0xBFD865F3, 0x7F1464F3,
+0x000B4F26, 0x4F22E000, 0xBFDA7FEC, 0x64F365F3,
+0x7406BFCD, 0x4F267F14, 0xE000000B, 0x4F222FE6,
+0x62537FEC, 0x65F36E43, 0x6423BFCB, 0x64E3BFBF,
+0x64F3BFBD, 0xBFBAD403, 0x7F140009, 0x000B4F26,
+0x00006EF6, 0x00200DB0, 0x89004011, 0x4111600B,
+0x4F228906, 0x611BB004, 0x000B4F26, 0x0009600B,
+0x620D2F26, 0x8F413020, 0x40180019, 0x8B0D3016,
+0x31043104, 0x31043104, 0x31043104, 0x31043104,
+0x890062F6, 0x4119310C, 0x6013000B, 0x41296219,
+0x20084018, 0x31048927, 0x31043104, 0x31043104,
+0x31043104, 0x31043104, 0x31043104, 0x31043104,
+0x31043104, 0x61193104, 0x3204221D, 0x32043204,
+0x32043204, 0x32043204, 0x32043204, 0x32043204,
+0x32043204, 0x32043204, 0x89003204, 0x4229320C,
+0x000B6023, 0xE00062F6, 0x62F6000B, 0x42286213,
+0x42244129, 0x42243104, 0x42243104, 0x42243104,
+0x42243104, 0x42243104, 0x42243104, 0x42243104,
+0x42243104, 0x42243104, 0x42243104, 0x42243104,
+0x42243104, 0x42243104, 0x42243104, 0x42243104,
+0x89003104, 0x6013310C, 0x62F6000B, 0x2F262F16,
+0x51F552F3, 0x52F22129, 0x52F41210, 0x212951F6,
+0x121152F2, 0x000B62F6, 0x000061F6, 0x51F32F16,
+0x310050F1, 0x51F48B02, 0x310050F2, 0x000B0029,
+0x000061F6, 0x51F32F16, 0x310050F1, 0x51F48B06,
+0x310050F2, 0xCA010029, 0x61F6000B, 0x000BE001,
+0x000061F6, 0x50F0000B, 0x2F262F16, 0xE10052F2,
+0x12001211, 0x000B62F6, 0x000061F6, 0x2F162F06,
+0x8B264115, 0x3103E040, 0x2F26892B, 0x52F62F36,
+0xE02053F5, 0x8B053103, 0xE3006233, 0x89093100,
+0x3108A002, 0x8B0F2338, 0xD0064F22, 0x6023400B,
+0x4F266203, 0x112151F4, 0x63F61130, 0x61F662F6,
+0x60F6000B, 0x002007F4, 0x4100C709, 0x0123011D,
+0x51F20009, 0x110150F4, 0x110050F3, 0x000B61F6,
+0x51F260F6, 0x1101E000, 0x61F61100, 0x60F6000B,
+0x01300000, 0x0128012C, 0x01200124, 0x0118011C,
+0x0106010A, 0x00FE0102, 0x00E200E6, 0x00DA00DE,
+0x00CC00D0, 0x00C400C8, 0x00A800AC, 0x00A000A4,
+0x008C0090, 0x00840088, 0x0066006A, 0x005E0062,
+0x42244300, 0x42244300, 0x42244300, 0x43286133,
+0x43084318, 0x42284308, 0x42084218, 0x41094208,
+0xAFAF4109, 0x4300221B, 0x43004224, 0x43004224,
+0x61334224, 0x43184328, 0x42184228, 0xAFA14119,
+0x4300221B, 0x43004224, 0x43004224, 0x61334224,
+0x43084328, 0x42284308, 0x42084208, 0x41094119,
+0xAF8F4109, 0x4300221B, 0x43004224, 0x43004224,
+0x61334224, 0x212D4328, 0x6213AF84, 0x42244300,
+0x42244300, 0x42244300, 0x43186133, 0x43084308,
+0x42084218, 0x41294208, 0x41094109, 0x221BAF72,
+0x42244300, 0x42244300, 0x42244300, 0x43186133,
+0x41294218, 0xAF654119, 0x4300221B, 0x43004224,
+0x43004224, 0x43004224, 0x43004224, 0x43004224,
+0x43004224, 0x4224AF56, 0x2F162F06, 0x8B264115,
+0x3103E040, 0x2F26892B, 0x52F62F36, 0xE02053F5,
+0x8B053103, 0xE2006323, 0x89093100, 0x3108A002,
+0x8B0F2228, 0xD0064F22, 0x6033400B, 0x4F266303,
+0x112151F4, 0x63F61130, 0x61F662F6, 0x60F6000B,
+0x002008B4, 0x4100C709, 0x0123011D, 0x51F20009,
+0x110150F4, 0x110050F3, 0x000B61F6, 0x51F260F6,
+0x1101E000, 0x61F61100, 0x60F6000B, 0x012E0000,
+0x0126012A, 0x011E0122, 0x0116011A, 0x01040108,
+0x00FC0100, 0x00E000E4, 0x00D800DC, 0x00CC00D0,
+0x00C400C8, 0x00A800AC, 0x00A000A4, 0x008C0090,
+0x00840088, 0x0066006A, 0x005E0062, 0x43254201,
+0x43254201, 0x43254201, 0x42296123, 0x42094219,
+0x43294209, 0x43094319, 0x41084309, 0xAFAF4108,
+0x4201231B, 0x42014325, 0x42014325, 0x61234325,
+0x42194229, 0x43194329, 0xAFA14118, 0x4201231B,
+0x42014325, 0x42014325, 0x61234325, 0x42094229,
+0x43294209, 0x43094309, 0x41084118, 0xAF8F4108,
+0x4201231B, 0x42014325, 0x42014325, 0x61234325,
+0xAF854229, 0x4201231D, 0x42014325, 0x42014325,
+0x61234325, 0x42094219, 0x43194209, 0x43094309,
+0x41084128, 0xAF734108, 0x4201231B, 0x42014325,
+0x42014325, 0x61234325, 0x43194219, 0x41184128,
+0x231BAF66, 0x43254201, 0x43254201, 0x43254201,
+0x43254201, 0x43254201, 0x43254201, 0xAF574201,
+0x00004325, 0x080A0C0E, 0x00020406, 0x1A1C1E20,
+0x12141618, 0x2E303234, 0x26282A2C, 0x3A3C3E40,
+0x6C625648, 0x41112F26, 0xE2208F18, 0x890B3123,
+0x321CD204, 0xD1026220, 0x412B312C, 0x00090009,
+0x0020081E, 0x002007D4, 0x000BE000, 0x400062F6,
+0x40004000, 0x40004000, 0x40004000, 0x62F6000B,
+0x40004000, 0x40004000, 0x40004000, 0x40184000,
+0x62F6000B, 0x40004000, 0x40004000, 0x40004000,
+0x40284000, 0x62F6000B, 0x40004000, 0x40184000,
+0x000B4028, 0xC90F62F6, 0x40054005, 0x40054005,
+0x62F6000B, 0x4005C907, 0x40054005, 0x62F6000B,
+0x4005C903, 0x000B4005, 0xC90162F6, 0x000B4005,
+0x000062F6, 0x080A0C0E, 0x00020406, 0x1A1C1E20,
+0x12141618, 0x2E303234, 0x26282A2C, 0x3A3C3E40,
+0x6C625648, 0x41112F26, 0xE2208F18, 0x890B3123,
+0x321CD204, 0xD1026220, 0x412B312C, 0x00090009,
+0x002008DE, 0x00200894, 0x000BE000, 0x400162F6,
+0x40014001, 0x40014001, 0x40014001, 0x62F6000B,
+0x40014001, 0x40014001, 0x40014001, 0x40194001,
+0x62F6000B, 0x40014001, 0x40014001, 0x40014001,
+0x40294001, 0x62F6000B, 0x40014001, 0x40194001,
+0x000B4029, 0x400462F6, 0x40044004, 0xC90F4004,
+0x62F6000B, 0x40044004, 0xC9074004, 0x62F6000B,
+0x40044004, 0x000BC903, 0x400462F6, 0x000BC901,
+0x000062F6, 0x00000000, 0x77073096, 0xEE0E612C,
+0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
+0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E,
+0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07,
+0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148,
+0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551,
+0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A,
+0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63,
+0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
+0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD,
+0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6,
+0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF,
+0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180,
+0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599,
+0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2,
+0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
+0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC,
+0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
+0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E,
+0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97,
+0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8,
+0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1,
+0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
+0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3,
+0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
+0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D,
+0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846,
+0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F,
+0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010,
+0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
+0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822,
+0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
+0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C,
+0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
+0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E,
+0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27,
+0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
+0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671,
+0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A,
+0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43,
+0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
+0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD,
+0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6,
+0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
+0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0,
+0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9,
+0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92,
+0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
+0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C,
+0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
+0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
+0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7,
+0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8,
+0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1,
+0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA,
+0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3,
+0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
+0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
+0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66,
+0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F,
+0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330,
+0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729,
+0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02,
+0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
+0x2D02EF8D, 0x544F0D0A, 0x50205355, 0x20312D48,
+0x003A5746, 0x72636564, 0x69747079, 0x65206E6F,
+0x726F7272, 0x0A0D2121, 0x00000000, 0x6564667A,
+0x70797263, 0x65725F74, 0x616C7567, 0x79726F74,
+0x6261745F, 0x7220656C, 0x203D7465, 0x00000000,
+0x45485441, 0x38731652, 0x89ACFF91, 0xEE55D178,
+0xEE000D0A, };
+
+const u32_t zcFwImageSize=3508;
diff --git a/drivers/staging/otus/hal/hpmain.c b/drivers/staging/otus/hal/hpmain.c
new file mode 100644
index 000000000000..2e65c466aae8
--- /dev/null
+++ b/drivers/staging/otus/hal/hpmain.c
@@ -0,0 +1,4643 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+#include "hpani.h"
+#include "hpusb.h"
+#include "otus.ini"
+
+extern const u32_t zcFwImage[];
+extern const u32_t zcFwImageSize;
+extern const u32_t zcDKFwImage[];
+extern const u32_t zcDKFwImageSize;
+extern const u32_t zcFwImageSPI[];
+extern const u32_t zcFwImageSPISize;
+
+#ifdef ZM_OTUS_LINUX_PHASE_2
+extern const u32_t zcFwBufImage[];
+extern const u32_t zcFwBufImageSize;
+extern const u32_t zcP2FwImage[];
+extern const u32_t zcP2FwImageSize;
+#endif
+extern void zfInitCmdQueue(zdev_t* dev);
+extern u16_t zfIssueCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen,
+ u16_t src, u8_t* buf);
+extern void zfIdlRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen);
+extern u16_t zfDelayWriteInternalReg(zdev_t* dev, u32_t addr, u32_t val);
+extern u16_t zfFlushDelayWrite(zdev_t* dev);
+extern void zfUsbInit(zdev_t* dev);
+extern u16_t zfFirmwareDownload(zdev_t* dev, u32_t* fw, u32_t len, u32_t offset);
+extern u16_t zfFirmwareDownloadNotJump(zdev_t* dev, u32_t* fw, u32_t len, u32_t offset);
+extern void zfUsbFree(zdev_t* dev);
+extern u16_t zfCwmIsExtChanBusy(u32_t ctlBusy, u32_t extBusy);
+extern void zfCoreCwmBusy(zdev_t* dev, u16_t busy);
+
+/* Prototypes */
+void zfInitRf(zdev_t* dev, u32_t frequency);
+void zfInitPhy(zdev_t* dev, u32_t frequency, u8_t bw40);
+void zfInitMac(zdev_t* dev);
+
+void zfSetPowerCalTable(zdev_t* dev, u32_t frequency, u8_t bw40, u8_t extOffset);
+void zfInitPowerCal(zdev_t* dev);
+
+#ifdef ZM_DRV_INIT_USB_MODE
+void zfInitUsbMode(zdev_t* dev);
+u16_t zfHpUsbReset(zdev_t* dev);
+#endif
+
+/* Bank 0 1 2 3 5 6 7 */
+void zfSetRfRegs(zdev_t* dev, u32_t frequency);
+/* Bank 4 */
+void zfSetBank4AndPowerTable(zdev_t* dev, u32_t frequency, u8_t bw40,
+ u8_t extOffset);
+/* Get param for turnoffdyn */
+void zfGetHwTurnOffdynParam(zdev_t* dev,
+ u32_t frequency, u8_t bw40, u8_t extOffset,
+ int* delta_slope_coeff_exp,
+ int* delta_slope_coeff_man,
+ int* delta_slope_coeff_exp_shgi,
+ int* delta_slope_coeff_man_shgi);
+
+void zfSelAdcClk(zdev_t* dev, u8_t bw40, u32_t frequency);
+u32_t zfHpEchoCommand(zdev_t* dev, u32_t value);
+
+
+
+#define zm_hp_priv(x) (((struct zsHpPriv*)wd->hpPrivate)->x)
+struct zsHpPriv zgHpPriv;
+
+#define ZM_FIRMWARE_WLAN_ADDR 0x200000
+#define ZM_FIRMWARE_SPI_ADDR 0x114000
+/* 0: real chip 1: FPGA test */
+#define ZM_FPGA_PHY 0
+
+#define reg_write(addr, val) zfDelayWriteInternalReg(dev, addr+0x1bc000, val)
+#define zm_min(A, B) ((A>B)? B:A)
+
+
+/******************** Intialization ********************/
+u16_t zfHpInit(zdev_t* dev, u32_t frequency)
+{
+ u16_t ret;
+ zmw_get_wlan_dev(dev);
+
+ /* Initializa HAL Plus private variables */
+ wd->hpPrivate = &zgHpPriv;
+
+ ((struct zsHpPriv*)wd->hpPrivate)->halCapability = ZM_HP_CAP_11N;
+
+ ((struct zsHpPriv*)wd->hpPrivate)->hwFrequency = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->hwBw40 = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->hwExtOffset = 0;
+
+ ((struct zsHpPriv*)wd->hpPrivate)->disableDfsCh = 0;
+
+ ((struct zsHpPriv*)wd->hpPrivate)->ledMode[0] = 1;
+ ((struct zsHpPriv*)wd->hpPrivate)->ledMode[1] = 1;
+ ((struct zsHpPriv*)wd->hpPrivate)->strongRSSI = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->rxStrongRSSI = 0;
+
+ ((struct zsHpPriv*)wd->hpPrivate)->slotType = 1;
+ ((struct zsHpPriv*)wd->hpPrivate)->aggPktNum = 0x10000a;
+
+ ((struct zsHpPriv*)wd->hpPrivate)->eepromImageIndex = 0;
+
+
+ ((struct zsHpPriv*)wd->hpPrivate)->eepromImageRdReq = 0;
+#ifdef ZM_OTUS_RX_STREAM_MODE
+ ((struct zsHpPriv*)wd->hpPrivate)->remainBuf = NULL;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxRemainLen = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxPktLen = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxPadLen = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxTransferLen = 0;
+#endif
+
+ ((struct zsHpPriv*)wd->hpPrivate)->enableBBHeavyClip = 1;
+ ((struct zsHpPriv*)wd->hpPrivate)->hwBBHeavyClip = 1; // force enable 8107
+ ((struct zsHpPriv*)wd->hpPrivate)->doBBHeavyClip = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->setValueHeavyClip = 0;
+
+
+ /* Initialize driver core */
+ zfInitCmdQueue(dev);
+
+ /* Initialize USB */
+ zfUsbInit(dev);
+
+#if ZM_SW_LOOP_BACK != 1
+
+ /* TODO : [Download FW] */
+ if (wd->modeMDKEnable)
+ {
+ /* download the MDK firmware */
+ if ((ret = zfFirmwareDownload(dev, (u32_t*)zcDKFwImage,
+ (u32_t)zcDKFwImageSize, ZM_FIRMWARE_WLAN_ADDR)) != ZM_SUCCESS)
+ {
+ /* TODO : exception handling */
+ //return 1;
+ }
+ }
+ else
+ {
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ /* donwload the normal frimware */
+ if ((ret = zfFirmwareDownload(dev, (u32_t*)zcFwImage,
+ (u32_t)zcFwImageSize, ZM_FIRMWARE_WLAN_ADDR)) != ZM_SUCCESS)
+ {
+ /* TODO : exception handling */
+ //return 1;
+ }
+ #else
+
+ // 1-PH fw: ReadMac() store some global variable
+ if ((ret = zfFirmwareDownloadNotJump(dev, (u32_t*)zcFwBufImage,
+ (u32_t)zcFwBufImageSize, 0x102800)) != ZM_SUCCESS)
+ {
+ DbgPrint("Dl zcFwBufImage failed!");
+ }
+
+ zfwSleep(dev, 1000);
+
+ if ((ret = zfFirmwareDownload(dev, (u32_t*)zcFwImage,
+ (u32_t)zcFwImageSize, ZM_FIRMWARE_WLAN_ADDR)) != ZM_SUCCESS)
+ {
+ DbgPrint("Dl zcFwBufImage failed!");
+ }
+ #endif
+ }
+#endif
+
+#ifdef ZM_DRV_INIT_USB_MODE
+ /* Init USB Mode */
+ zfInitUsbMode(dev);
+
+ /* Do the USB Reset */
+ zfHpUsbReset(dev);
+#endif
+
+/* Register setting */
+/* ZM_DRIVER_MODEL_TYPE_MDK
+ * 1=>for MDK, disable init RF, PHY, and MAC,
+ * 0=>normal init
+ */
+//#if ((ZM_SW_LOOP_BACK != 1) && (ZM_DRIVER_MODEL_TYPE_MDK !=1))
+#if ZM_SW_LOOP_BACK != 1
+ if(!wd->modeMDKEnable)
+ {
+ /* Init MAC */
+ zfInitMac(dev);
+
+ #if ZM_FW_LOOP_BACK != 1
+ /* Init PHY */
+ zfInitPhy(dev, frequency, 0);
+
+ /* Init RF */
+ zfInitRf(dev, frequency);
+
+ #if ZM_FPGA_PHY == 0
+ /* BringUp issue */
+ //zfDelayWriteInternalReg(dev, 0x9800+0x1bc000, 0x10000007);
+ //zfFlushDelayWrite(dev);
+ #endif
+
+ #endif /* end of ZM_FW_LOOP_BACK != 1 */
+ }
+#endif /* end of ((ZM_SW_LOOP_BACK != 1) && (ZM_DRIVER_MODEL_TYPE_MDK !=1)) */
+
+ zfHpEchoCommand(dev, 0xAABBCCDD);
+
+ return 0;
+}
+
+
+u16_t zfHpReinit(zdev_t* dev, u32_t frequency)
+{
+ u16_t ret;
+ zmw_get_wlan_dev(dev);
+
+ ((struct zsHpPriv*)wd->hpPrivate)->halReInit = 1;
+
+ ((struct zsHpPriv*)wd->hpPrivate)->strongRSSI = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->rxStrongRSSI = 0;
+
+#ifdef ZM_OTUS_RX_STREAM_MODE
+ if (((struct zsHpPriv*)wd->hpPrivate)->remainBuf != NULL)
+ {
+ zfwBufFree(dev, ((struct zsHpPriv*)wd->hpPrivate)->remainBuf, 0);
+ }
+ ((struct zsHpPriv*)wd->hpPrivate)->remainBuf = NULL;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxRemainLen = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxPktLen = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxPadLen = 0;
+ ((struct zsHpPriv*)wd->hpPrivate)->usbRxTransferLen = 0;
+#endif
+
+ zfInitCmdQueue(dev);
+ zfCoreReinit(dev);
+
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ /* Download firmware */
+ if ((ret = zfFirmwareDownload(dev, (u32_t*)zcFwImage,
+ (u32_t)zcFwImageSize, ZM_FIRMWARE_WLAN_ADDR)) != ZM_SUCCESS)
+ {
+ /* TODO : exception handling */
+ //return 1;
+ }
+ #else
+ if ((ret = zfFirmwareDownload(dev, (u32_t*)zcP2FwImage,
+ (u32_t)zcP2FwImageSize, ZM_FIRMWARE_WLAN_ADDR)) != ZM_SUCCESS)
+ {
+ /* TODO : exception handling */
+ //return 1;
+ }
+ #endif
+
+#ifdef ZM_DRV_INIT_USB_MODE
+ /* Init USB Mode */
+ zfInitUsbMode(dev);
+
+ /* Do the USB Reset */
+ zfHpUsbReset(dev);
+#endif
+
+ /* Init MAC */
+ zfInitMac(dev);
+
+ /* Init PHY */
+ zfInitPhy(dev, frequency, 0);
+ /* Init RF */
+ zfInitRf(dev, frequency);
+
+ #if ZM_FPGA_PHY == 0
+ /* BringUp issue */
+ //zfDelayWriteInternalReg(dev, 0x9800+0x1bc000, 0x10000007);
+ //zfFlushDelayWrite(dev);
+ #endif
+
+ zfHpEchoCommand(dev, 0xAABBCCDD);
+
+ return 0;
+}
+
+
+u16_t zfHpRelease(zdev_t* dev)
+{
+ /* Free USB resource */
+ zfUsbFree(dev);
+
+ return 0;
+}
+
+/* MDK mode setting for dontRetransmit */
+void zfHpConfigFM(zdev_t* dev, u32_t RxMaxSize, u32_t DontRetransmit)
+{
+ u32_t cmd[3];
+ u16_t ret;
+
+ cmd[0] = 8 | (ZM_CMD_CONFIG << 8);
+ cmd[1] = RxMaxSize; /* zgRxMaxSize */
+ cmd[2] = DontRetransmit; /* zgDontRetransmit */
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_OID_INTERNAL_WRITE, 0);
+}
+
+const u8_t zcXpdToPd[16] =
+{
+ /* 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF */
+ 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2
+};
+
+/******************** RF and PHY ********************/
+
+void zfInitPhy(zdev_t* dev, u32_t frequency, u8_t bw40)
+{
+ u16_t i, j, k;
+ u16_t entries;
+ u16_t modesIndex = 0;
+ u16_t freqIndex = 0;
+ u32_t tmp, tmp1;
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+ u32_t eepromBoardData[15][6] = {
+ /* Register A-20 A-20/40 G-20/40 G-20 G-Turbo */
+ {0x9964, 0, 0, 0, 0, 0},
+ {0x9960, 0, 0, 0, 0, 0},
+ {0xb960, 0, 0, 0, 0, 0},
+ {0x9844, 0, 0, 0, 0, 0},
+ {0x9850, 0, 0, 0, 0, 0},
+ {0x9834, 0, 0, 0, 0, 0},
+ {0x9828, 0, 0, 0, 0, 0},
+ {0xc864, 0, 0, 0, 0, 0},
+ {0x9848, 0, 0, 0, 0, 0},
+ {0xb848, 0, 0, 0, 0, 0},
+ {0xa20c, 0, 0, 0, 0, 0},
+ {0xc20c, 0, 0, 0, 0, 0},
+ {0x9920, 0, 0, 0, 0, 0},
+ {0xb920, 0, 0, 0, 0, 0},
+ {0xa258, 0, 0, 0, 0, 0},
+ };
+
+ /* #1 Save the initial value of the related RIFS register settings */
+ //((struct zsHpPriv*)wd->hpPrivate)->isInitialPhy++;
+
+ /*
+ * Setup the indices for the next set of register array writes
+ * PHY mode is static20 / 2040
+ * Frequency is 2.4GHz (B) / 5GHz (A)
+ */
+ if ( frequency > ZM_CH_G_14 )
+ {
+ /* 5GHz */
+ freqIndex = 1;
+ if (bw40)
+ {
+ modesIndex = 2;
+ zm_debug_msg0("init ar5416Modes in 2: A-20/40");
+ }
+ else
+ {
+ modesIndex = 1;
+ zm_debug_msg0("init ar5416Modes in 1: A-20");
+ }
+ }
+ else
+ {
+ /* 2.4GHz */
+ freqIndex = 2;
+ if (bw40)
+ {
+ modesIndex = 3;
+ zm_debug_msg0("init ar5416Modes in 3: G-20/40");
+ }
+ else
+ {
+ modesIndex = 4;
+ zm_debug_msg0("init ar5416Modes in 4: G-20");
+ }
+ }
+
+
+#if ZM_FPGA_PHY == 1
+ /* Starting External Hainan Register Initialization */
+ /* TODO: */
+
+ zfwSleep(dev, 10);
+#endif
+
+ /*
+ *Set correct Baseband to analog shift setting to access analog chips.
+ */
+ //reg_write(PHY_BASE, 0x00000007);
+// reg_write(0x9800, 0x00000007);
+
+ /*
+ * Write addac shifts
+ */
+ // do this in firmware
+
+
+
+ /* Zeroize board data */
+ for (j=0; j<15; j++)
+ {
+ for (k=1; k<=4; k++)
+ {
+ eepromBoardData[j][k] = 0;
+ }
+ }
+ /*
+ * Register setting by mode
+ */
+
+ entries = sizeof(ar5416Modes) / sizeof(*ar5416Modes);
+ zm_msg1_scan(ZM_LV_2, "Modes register setting entries=", entries);
+ for (i=0; i<entries; i++)
+ {
+#if 0
+ if ( ((struct zsHpPriv*)wd->hpPrivate)->hwNotFirstInit && (ar5416Modes[i][0] == 0xa27c) )
+ {
+ /* Force disable CR671 bit20 / 7823 */
+ /* The bug has to do with the polarity of the pdadc offset calibration. There */
+ /* is an initial calibration that is OK, and there is a continuous */
+ /* calibration that updates the pddac with the wrong polarity. Fortunately */
+ /* the second loop can be disabled with a bit called en_pd_dc_offset_thr. */
+
+ reg_write(ar5416Modes[i][0], (ar5416Modes[i][modesIndex]& 0xffefffff) );
+ ((struct zsHpPriv*)wd->hpPrivate)->hwNotFirstInit = 1;
+ }
+ else
+ {
+#endif
+ /* FirstTime Init or not 0xa27c(CR671) */
+ reg_write(ar5416Modes[i][0], ar5416Modes[i][modesIndex]);
+// }
+ /* Initialize board data */
+ for (j=0; j<15; j++)
+ {
+ if (ar5416Modes[i][0] == eepromBoardData[j][0])
+ {
+ for (k=1; k<=4; k++)
+ {
+ eepromBoardData[j][k] = ar5416Modes[i][k];
+ }
+ }
+ }
+ /* #1 Save the initial value of the related RIFS register settings */
+ //if( ((struct zsHpPriv*)wd->hpPrivate)->isInitialPhy == 1 )
+ {
+ switch(ar5416Modes[i][0])
+ {
+ case 0x9850 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initDesiredSigSize = ar5416Modes[i][modesIndex];
+ break;
+ case 0x985c :
+ ((struct zsHpPriv*)wd->hpPrivate)->initAGC = ar5416Modes[i][modesIndex];
+ break;
+ case 0x9860 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initAgcControl = ar5416Modes[i][modesIndex];
+ break;
+ case 0x9918 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initSearchStartDelay = ar5416Modes[i][modesIndex];
+ break;
+ case 0x99ec :
+ ((struct zsHpPriv*)wd->hpPrivate)->initRIFSSearchParams = ar5416Modes[i][modesIndex];
+ break;
+ case 0xa388 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initFastChannelChangeControl = ar5416Modes[i][modesIndex];
+ default :
+ break;
+ }
+ }
+ }
+#if 0
+ zfFlushDelayWrite(dev);
+
+ /*
+ * Common Register setting
+ */
+ entries = sizeof(ar5416Common) / sizeof(*ar5416Common);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416Common[i][0], ar5416Common[i][1]);
+ }
+ zfFlushDelayWrite(dev);
+
+ /*
+ * RF Gain setting by freqIndex
+ */
+ entries = sizeof(ar5416BB_RfGain) / sizeof(*ar5416BB_RfGain);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416BB_RfGain[i][0], ar5416BB_RfGain[i][freqIndex]);
+ }
+ zfFlushDelayWrite(dev);
+
+ /*
+ * Moved ar5416InitChainMask() here to ensure the swap bit is set before
+ * the pdadc table is written. Swap must occur before any radio dependent
+ * replicated register access. The pdadc curve addressing in particular
+ * depends on the consistent setting of the swap bit.
+ */
+ //ar5416InitChainMask(pDev);
+
+ /* Setup the transmit power values. */
+ // TODO
+#endif
+
+ /* Update 5G board data */
+ //Ant control common
+ tmp = hpPriv->eepromImage[0x100+0x144*2/4];
+ eepromBoardData[0][1] = tmp;
+ eepromBoardData[0][2] = tmp;
+ //Ant control chain 0
+ tmp = hpPriv->eepromImage[0x100+0x140*2/4];
+ eepromBoardData[1][1] = tmp;
+ eepromBoardData[1][2] = tmp;
+ //Ant control chain 2
+ tmp = hpPriv->eepromImage[0x100+0x142*2/4];
+ eepromBoardData[2][1] = tmp;
+ eepromBoardData[2][2] = tmp;
+ //SwSettle
+ tmp = hpPriv->eepromImage[0x100+0x146*2/4];
+ tmp = (tmp >> 16) & 0x7f;
+ eepromBoardData[3][1] &= (~((u32_t)0x3f80));
+ eepromBoardData[3][1] |= (tmp << 7);
+#if 0
+ //swSettleHt40
+ tmp = hpPriv->eepromImage[0x100+0x158*2/4];
+ tmp = (tmp) & 0x7f;
+ eepromBoardData[3][2] &= (~((u32_t)0x3f80));
+ eepromBoardData[3][2] |= (tmp << 7);
+#endif
+ //adcDesired, pdaDesired
+ tmp = hpPriv->eepromImage[0x100+0x148*2/4];
+ tmp = (tmp >> 24);
+ tmp1 = hpPriv->eepromImage[0x100+0x14a*2/4];
+ tmp1 = tmp1 & 0xff;
+ tmp = tmp + (tmp1<<8);
+ eepromBoardData[4][1] &= (~((u32_t)0xffff));
+ eepromBoardData[4][1] |= tmp;
+ eepromBoardData[4][2] &= (~((u32_t)0xffff));
+ eepromBoardData[4][2] |= tmp;
+ //TxEndToXpaOff, TxFrameToXpaOn
+ tmp = hpPriv->eepromImage[0x100+0x14a*2/4];
+ tmp = (tmp >> 24) & 0xff;
+ tmp1 = hpPriv->eepromImage[0x100+0x14c*2/4];
+ tmp1 = (tmp1 >> 8) & 0xff;
+ tmp = (tmp<<24) + (tmp<<16) + (tmp1<<8) + tmp1;
+ eepromBoardData[5][1] = tmp;
+ eepromBoardData[5][2] = tmp;
+ //TxEnaToRxOm
+ tmp = hpPriv->eepromImage[0x100+0x14c*2/4] & 0xff;
+ eepromBoardData[6][1] &= (~((u32_t)0xff0000));
+ eepromBoardData[6][1] |= (tmp<<16);
+ eepromBoardData[6][2] &= (~((u32_t)0xff0000));
+ eepromBoardData[6][2] |= (tmp<<16);
+ //Thresh62
+ tmp = hpPriv->eepromImage[0x100+0x14c*2/4];
+ tmp = (tmp >> 16) & 0x7f;
+ eepromBoardData[7][1] &= (~((u32_t)0x7f000));
+ eepromBoardData[7][1] |= (tmp<<12);
+ eepromBoardData[7][2] &= (~((u32_t)0x7f000));
+ eepromBoardData[7][2] |= (tmp<<12);
+ //TxRxAtten chain_0
+ tmp = hpPriv->eepromImage[0x100+0x146*2/4];
+ tmp = (tmp >> 24) & 0x3f;
+ eepromBoardData[8][1] &= (~((u32_t)0x3f000));
+ eepromBoardData[8][1] |= (tmp<<12);
+ eepromBoardData[8][2] &= (~((u32_t)0x3f000));
+ eepromBoardData[8][2] |= (tmp<<12);
+ //TxRxAtten chain_2
+ tmp = hpPriv->eepromImage[0x100+0x148*2/4] & 0x3f;
+ eepromBoardData[9][1] &= (~((u32_t)0x3f000));
+ eepromBoardData[9][1] |= (tmp<<12);
+ eepromBoardData[9][2] &= (~((u32_t)0x3f000));
+ eepromBoardData[9][2] |= (tmp<<12);
+ //TxRxMargin chain_0
+ tmp = hpPriv->eepromImage[0x100+0x148*2/4];
+ tmp = (tmp >> 8) & 0x3f;
+ eepromBoardData[10][1] &= (~((u32_t)0xfc0000));
+ eepromBoardData[10][1] |= (tmp<<18);
+ eepromBoardData[10][2] &= (~((u32_t)0xfc0000));
+ eepromBoardData[10][2] |= (tmp<<18);
+ //TxRxMargin chain_2
+ tmp = hpPriv->eepromImage[0x100+0x148*2/4];
+ tmp = (tmp >> 16) & 0x3f;
+ eepromBoardData[11][1] &= (~((u32_t)0xfc0000));
+ eepromBoardData[11][1] |= (tmp<<18);
+ eepromBoardData[11][2] &= (~((u32_t)0xfc0000));
+ eepromBoardData[11][2] |= (tmp<<18);
+ //iqCall chain_0, iqCallQ chain_0
+ tmp = hpPriv->eepromImage[0x100+0x14e*2/4];
+ tmp = (tmp >> 24) & 0x3f;
+ tmp1 = hpPriv->eepromImage[0x100+0x150*2/4];
+ tmp1 = (tmp1 >> 8) & 0x1f;
+ tmp = (tmp<<5) + tmp1;
+ eepromBoardData[12][1] &= (~((u32_t)0x7ff));
+ eepromBoardData[12][1] |= (tmp);
+ eepromBoardData[12][2] &= (~((u32_t)0x7ff));
+ eepromBoardData[12][2] |= (tmp);
+ //iqCall chain_2, iqCallQ chain_2
+ tmp = hpPriv->eepromImage[0x100+0x150*2/4];
+ tmp = tmp & 0x3f;
+ tmp1 = hpPriv->eepromImage[0x100+0x150*2/4];
+ tmp1 = (tmp1 >> 16) & 0x1f;
+ tmp = (tmp<<5) + tmp1;
+ eepromBoardData[13][1] &= (~((u32_t)0x7ff));
+ eepromBoardData[13][1] |= (tmp);
+ eepromBoardData[13][2] &= (~((u32_t)0x7ff));
+ eepromBoardData[13][2] |= (tmp);
+ //bsw_Margin chain_0
+ tmp = hpPriv->eepromImage[0x100+0x156*2/4];
+ tmp = (tmp >> 16) & 0xf;
+ eepromBoardData[10][1] &= (~((u32_t)0x3c00));
+ eepromBoardData[10][1] |= (tmp << 10);
+ eepromBoardData[10][2] &= (~((u32_t)0x3c00));
+ eepromBoardData[10][2] |= (tmp << 10);
+ //xpd gain mask
+ tmp = hpPriv->eepromImage[0x100+0x14e*2/4];
+ tmp = (tmp >> 8) & 0xf;
+ eepromBoardData[14][1] &= (~((u32_t)0xf0000));
+ eepromBoardData[14][1] |= (zcXpdToPd[tmp] << 16);
+ eepromBoardData[14][2] &= (~((u32_t)0xf0000));
+ eepromBoardData[14][2] |= (zcXpdToPd[tmp] << 16);
+#if 0
+ //bsw_Atten chain_0
+ tmp = hpPriv->eepromImage[0x100+0x156*2/4];
+ tmp = (tmp) & 0x1f;
+ eepromBoardData[10][1] &= (~((u32_t)0x1f));
+ eepromBoardData[10][1] |= (tmp);
+ eepromBoardData[10][2] &= (~((u32_t)0x1f));
+ eepromBoardData[10][2] |= (tmp);
+ //bsw_Margin chain_2
+ tmp = hpPriv->eepromImage[0x100+0x156*2/4];
+ tmp = (tmp >> 24) & 0xf;
+ eepromBoardData[11][1] &= (~((u32_t)0x3c00));
+ eepromBoardData[11][1] |= (tmp << 10);
+ eepromBoardData[11][2] &= (~((u32_t)0x3c00));
+ eepromBoardData[11][2] |= (tmp << 10);
+ //bsw_Atten chain_2
+ tmp = hpPriv->eepromImage[0x100+0x156*2/4];
+ tmp = (tmp >> 8) & 0x1f;
+ eepromBoardData[11][1] &= (~((u32_t)0x1f));
+ eepromBoardData[11][1] |= (tmp);
+ eepromBoardData[11][2] &= (~((u32_t)0x1f));
+ eepromBoardData[11][2] |= (tmp);
+#endif
+
+ /* Update 2.4G board data */
+ //Ant control common
+ tmp = hpPriv->eepromImage[0x100+0x170*2/4];
+ tmp = tmp >> 24;
+ tmp1 = hpPriv->eepromImage[0x100+0x172*2/4];
+ tmp = tmp + (tmp1 << 8);
+ eepromBoardData[0][3] = tmp;
+ eepromBoardData[0][4] = tmp;
+ //Ant control chain 0
+ tmp = hpPriv->eepromImage[0x100+0x16c*2/4];
+ tmp = tmp >> 24;
+ tmp1 = hpPriv->eepromImage[0x100+0x16e*2/4];
+ tmp = tmp + (tmp1 << 8);
+ eepromBoardData[1][3] = tmp;
+ eepromBoardData[1][4] = tmp;
+ //Ant control chain 2
+ tmp = hpPriv->eepromImage[0x100+0x16e*2/4];
+ tmp = tmp >> 24;
+ tmp1 = hpPriv->eepromImage[0x100+0x170*2/4];
+ tmp = tmp + (tmp1 << 8);
+ eepromBoardData[2][3] = tmp;
+ eepromBoardData[2][4] = tmp;
+ //SwSettle
+ tmp = hpPriv->eepromImage[0x100+0x174*2/4];
+ tmp = (tmp >> 8) & 0x7f;
+ eepromBoardData[3][4] &= (~((u32_t)0x3f80));
+ eepromBoardData[3][4] |= (tmp << 7);
+#if 0
+ //swSettleHt40
+ tmp = hpPriv->eepromImage[0x100+0x184*2/4];
+ tmp = (tmp >> 24) & 0x7f;
+ eepromBoardData[3][3] &= (~((u32_t)0x3f80));
+ eepromBoardData[3][3] |= (tmp << 7);
+#endif
+ //adcDesired, pdaDesired
+ tmp = hpPriv->eepromImage[0x100+0x176*2/4];
+ tmp = (tmp >> 16) & 0xff;
+ tmp1 = hpPriv->eepromImage[0x100+0x176*2/4];
+ tmp1 = tmp1 >> 24;
+ tmp = tmp + (tmp1<<8);
+ eepromBoardData[4][3] &= (~((u32_t)0xffff));
+ eepromBoardData[4][3] |= tmp;
+ eepromBoardData[4][4] &= (~((u32_t)0xffff));
+ eepromBoardData[4][4] |= tmp;
+ //TxEndToXpaOff, TxFrameToXpaOn
+ tmp = hpPriv->eepromImage[0x100+0x178*2/4];
+ tmp = (tmp >> 16) & 0xff;
+ tmp1 = hpPriv->eepromImage[0x100+0x17a*2/4];
+ tmp1 = tmp1 & 0xff;
+ tmp = (tmp << 24) + (tmp << 16) + (tmp1 << 8) + tmp1;
+ eepromBoardData[5][3] = tmp;
+ eepromBoardData[5][4] = tmp;
+ //TxEnaToRxOm
+ tmp = hpPriv->eepromImage[0x100+0x178*2/4];
+ tmp = (tmp >> 24);
+ eepromBoardData[6][3] &= (~((u32_t)0xff0000));
+ eepromBoardData[6][3] |= (tmp<<16);
+ eepromBoardData[6][4] &= (~((u32_t)0xff0000));
+ eepromBoardData[6][4] |= (tmp<<16);
+ //Thresh62
+ tmp = hpPriv->eepromImage[0x100+0x17a*2/4];
+ tmp = (tmp >> 8) & 0x7f;
+ eepromBoardData[7][3] &= (~((u32_t)0x7f000));
+ eepromBoardData[7][3] |= (tmp<<12);
+ eepromBoardData[7][4] &= (~((u32_t)0x7f000));
+ eepromBoardData[7][4] |= (tmp<<12);
+ //TxRxAtten chain_0
+ tmp = hpPriv->eepromImage[0x100+0x174*2/4];
+ tmp = (tmp >> 16) & 0x3f;
+ eepromBoardData[8][3] &= (~((u32_t)0x3f000));
+ eepromBoardData[8][3] |= (tmp<<12);
+ eepromBoardData[8][4] &= (~((u32_t)0x3f000));
+ eepromBoardData[8][4] |= (tmp<<12);
+ //TxRxAtten chain_2
+ tmp = hpPriv->eepromImage[0x100+0x174*2/4];
+ tmp = (tmp >> 24) & 0x3f;
+ eepromBoardData[9][3] &= (~((u32_t)0x3f000));
+ eepromBoardData[9][3] |= (tmp<<12);
+ eepromBoardData[9][4] &= (~((u32_t)0x3f000));
+ eepromBoardData[9][4] |= (tmp<<12);
+ //TxRxMargin chain_0
+ tmp = hpPriv->eepromImage[0x100+0x176*2/4];
+ tmp = (tmp) & 0x3f;
+ eepromBoardData[10][3] &= (~((u32_t)0xfc0000));
+ eepromBoardData[10][3] |= (tmp<<18);
+ eepromBoardData[10][4] &= (~((u32_t)0xfc0000));
+ eepromBoardData[10][4] |= (tmp<<18);
+ //TxRxMargin chain_2
+ tmp = hpPriv->eepromImage[0x100+0x176*2/4];
+ tmp = (tmp >> 8) & 0x3f;
+ eepromBoardData[11][3] &= (~((u32_t)0xfc0000));
+ eepromBoardData[11][3] |= (tmp<<18);
+ eepromBoardData[11][4] &= (~((u32_t)0xfc0000));
+ eepromBoardData[11][4] |= (tmp<<18);
+ //iqCall chain_0, iqCallQ chain_0
+ tmp = hpPriv->eepromImage[0x100+0x17c*2/4];
+ tmp = (tmp >> 16) & 0x3f;
+ tmp1 = hpPriv->eepromImage[0x100+0x17e*2/4];
+ tmp1 = (tmp1) & 0x1f;
+ tmp = (tmp<<5) + tmp1;
+ eepromBoardData[12][3] &= (~((u32_t)0x7ff));
+ eepromBoardData[12][3] |= (tmp);
+ eepromBoardData[12][4] &= (~((u32_t)0x7ff));
+ eepromBoardData[12][4] |= (tmp);
+ //iqCall chain_2, iqCallQ chain_2
+ tmp = hpPriv->eepromImage[0x100+0x17c*2/4];
+ tmp = (tmp>>24) & 0x3f;
+ tmp1 = hpPriv->eepromImage[0x100+0x17e*2/4];
+ tmp1 = (tmp1 >> 8) & 0x1f;
+ tmp = (tmp<<5) + tmp1;
+ eepromBoardData[13][3] &= (~((u32_t)0x7ff));
+ eepromBoardData[13][3] |= (tmp);
+ eepromBoardData[13][4] &= (~((u32_t)0x7ff));
+ eepromBoardData[13][4] |= (tmp);
+ //xpd gain mask
+ tmp = hpPriv->eepromImage[0x100+0x17c*2/4];
+ tmp = tmp & 0xf;
+ DbgPrint("xpd=0x%x, pd=0x%x\n", tmp, zcXpdToPd[tmp]);
+ eepromBoardData[14][3] &= (~((u32_t)0xf0000));
+ eepromBoardData[14][3] |= (zcXpdToPd[tmp] << 16);
+ eepromBoardData[14][4] &= (~((u32_t)0xf0000));
+ eepromBoardData[14][4] |= (zcXpdToPd[tmp] << 16);
+#if 0
+ //bsw_Margin chain_0
+ tmp = hpPriv->eepromImage[0x100+0x184*2/4];
+ tmp = (tmp >> 8) & 0xf;
+ eepromBoardData[10][3] &= (~((u32_t)0x3c00));
+ eepromBoardData[10][3] |= (tmp << 10);
+ eepromBoardData[10][4] &= (~((u32_t)0x3c00));
+ eepromBoardData[10][4] |= (tmp << 10);
+ //bsw_Atten chain_0
+ tmp = hpPriv->eepromImage[0x100+0x182*2/4];
+ tmp = (tmp>>24) & 0x1f;
+ eepromBoardData[10][3] &= (~((u32_t)0x1f));
+ eepromBoardData[10][3] |= (tmp);
+ eepromBoardData[10][4] &= (~((u32_t)0x1f));
+ eepromBoardData[10][4] |= (tmp);
+ //bsw_Margin chain_2
+ tmp = hpPriv->eepromImage[0x100+0x184*2/4];
+ tmp = (tmp >> 16) & 0xf;
+ eepromBoardData[11][3] &= (~((u32_t)0x3c00));
+ eepromBoardData[11][3] |= (tmp << 10);
+ eepromBoardData[11][4] &= (~((u32_t)0x3c00));
+ eepromBoardData[11][4] |= (tmp << 10);
+ //bsw_Atten chain_2
+ tmp = hpPriv->eepromImage[0x100+0x184*2/4];
+ tmp = (tmp) & 0x1f;
+ eepromBoardData[11][3] &= (~((u32_t)0x1f));
+ eepromBoardData[11][3] |= (tmp);
+ eepromBoardData[11][4] &= (~((u32_t)0x1f));
+ eepromBoardData[11][4] |= (tmp);
+#endif
+
+#if 0
+ for (j=0; j<14; j++)
+ {
+ DbgPrint("%04x, %08x, %08x, %08x, %08x\n", eepromBoardData[j][0], eepromBoardData[j][1], eepromBoardData[j][2], eepromBoardData[j][3], eepromBoardData[j][4]);
+ }
+#endif
+
+ if ((hpPriv->eepromImage[0x100+0x110*2/4]&0xff) == 0x80) //FEM TYPE
+ {
+ /* Update board data to registers */
+ for (j=0; j<15; j++)
+ {
+ reg_write(eepromBoardData[j][0], eepromBoardData[j][modesIndex]);
+
+ /* #1 Save the initial value of the related RIFS register settings */
+ //if( ((struct zsHpPriv*)wd->hpPrivate)->isInitialPhy == 1 )
+ {
+ switch(eepromBoardData[j][0])
+ {
+ case 0x9850 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initDesiredSigSize = eepromBoardData[j][modesIndex];
+ break;
+ case 0x985c :
+ ((struct zsHpPriv*)wd->hpPrivate)->initAGC = eepromBoardData[j][modesIndex];
+ break;
+ case 0x9860 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initAgcControl = eepromBoardData[j][modesIndex];
+ break;
+ case 0x9918 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initSearchStartDelay = eepromBoardData[j][modesIndex];
+ break;
+ case 0x99ec :
+ ((struct zsHpPriv*)wd->hpPrivate)->initRIFSSearchParams = eepromBoardData[j][modesIndex];
+ break;
+ case 0xa388 :
+ ((struct zsHpPriv*)wd->hpPrivate)->initFastChannelChangeControl = eepromBoardData[j][modesIndex];
+ default :
+ break;
+ }
+ }
+ }
+ } /* if ((hpPriv->eepromImage[0x100+0x110*2/4]&0xff) == 0x80) //FEM TYPE */
+
+
+ /* Bringup issue : force tx gain */
+ //reg_write(0xa258, 0x0cc65381);
+ //reg_write(0xa274, 0x0a1a7c15);
+ zfInitPowerCal(dev);
+
+ if(frequency > ZM_CH_G_14)
+ {
+ zfDelayWriteInternalReg(dev, 0x1d4014, 0x5143);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1d4014, 0x5163);
+ }
+
+ zfFlushDelayWrite(dev);
+}
+
+
+void zfInitRf(zdev_t* dev, u32_t frequency)
+{
+ u32_t cmd[8];
+ u16_t ret;
+ int delta_slope_coeff_exp;
+ int delta_slope_coeff_man;
+ int delta_slope_coeff_exp_shgi;
+ int delta_slope_coeff_man_shgi;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg1(" initRf frequency = ", frequency);
+
+ if (frequency == 0)
+ {
+ frequency = 2412;
+ }
+
+ /* Bank 0 1 2 3 5 6 7 */
+ zfSetRfRegs(dev, frequency);
+ /* Bank 4 */
+ zfSetBank4AndPowerTable(dev, frequency, 0, 0);
+
+ /* stroe frequency */
+ ((struct zsHpPriv*)wd->hpPrivate)->hwFrequency = (u16_t)frequency;
+
+ zfGetHwTurnOffdynParam(dev,
+ frequency, 0, 0,
+ &delta_slope_coeff_exp,
+ &delta_slope_coeff_man,
+ &delta_slope_coeff_exp_shgi,
+ &delta_slope_coeff_man_shgi);
+
+ /* related functions */
+ frequency = frequency*1000;
+ cmd[0] = 28 | (ZM_CMD_RF_INIT << 8);
+ cmd[1] = frequency;
+ cmd[2] = 0;//((struct zsHpPriv*)wd->hpPrivate)->hw_DYNAMIC_HT2040_EN;
+ cmd[3] = 1;//((wd->ExtOffset << 2) | ((struct zsHpPriv*)wd->hpPrivate)->hw_HT_ENABLE);
+ cmd[4] = delta_slope_coeff_exp;
+ cmd[5] = delta_slope_coeff_man;
+ cmd[6] = delta_slope_coeff_exp_shgi;
+ cmd[7] = delta_slope_coeff_man_shgi;
+
+ ret = zfIssueCmd(dev, cmd, 32, ZM_OID_INTERNAL_WRITE, 0);
+
+ // delay temporarily, wait for new PHY and RF
+ zfwSleep(dev, 1000);
+}
+
+int tn(int exp)
+{
+ int i;
+ int tmp = 1;
+ for(i=0; i<exp; i++)
+ tmp = tmp*2;
+
+ return tmp;
+}
+
+/*int zfFloor(double indata)
+{
+ if(indata<0)
+ return (int)indata-1;
+ else
+ return (int)indata;
+}
+*/
+u32_t reverse_bits(u32_t chan_sel)
+{
+ /* reverse_bits */
+ u32_t chansel = 0;
+ u8_t i;
+
+ for (i=0; i<8; i++)
+ chansel |= ((chan_sel>>(7-i) & 0x1) << i);
+ return chansel;
+}
+
+/* Bank 0 1 2 3 5 6 7 */
+void zfSetRfRegs(zdev_t* dev, u32_t frequency)
+{
+ u16_t entries;
+ u16_t freqIndex = 0;
+ u16_t i;
+
+ //zmw_get_wlan_dev(dev);
+
+ if ( frequency > ZM_CH_G_14 )
+ {
+ /* 5G */
+ freqIndex = 1;
+ zm_msg0_scan(ZM_LV_2, "Set to 5GHz");
+
+ }
+ else
+ {
+ /* 2.4G */
+ freqIndex = 2;
+ zm_msg0_scan(ZM_LV_2, "Set to 2.4GHz");
+ }
+
+#if 1
+ entries = sizeof(otusBank) / sizeof(*otusBank);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(otusBank[i][0], otusBank[i][freqIndex]);
+ }
+#else
+ /* Bank0 */
+ entries = sizeof(ar5416Bank0) / sizeof(*ar5416Bank0);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416Bank0[i][0], ar5416Bank0[i][1]);
+ }
+ /* Bank1 */
+ entries = sizeof(ar5416Bank1) / sizeof(*ar5416Bank1);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416Bank1[i][0], ar5416Bank1[i][1]);
+ }
+ /* Bank2 */
+ entries = sizeof(ar5416Bank2) / sizeof(*ar5416Bank2);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416Bank2[i][0], ar5416Bank2[i][1]);
+ }
+ /* Bank3 */
+ entries = sizeof(ar5416Bank3) / sizeof(*ar5416Bank3);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416Bank3[i][0], ar5416Bank3[i][freqIndex]);
+ }
+ /* Bank5 */
+ reg_write (0x98b0, 0x00000013);
+ reg_write (0x98e4, 0x00000002);
+ /* Bank6 */
+ entries = sizeof(ar5416Bank6) / sizeof(*ar5416Bank6);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416Bank6[i][0], ar5416Bank6[i][freqIndex]);
+ }
+ /* Bank7 */
+ entries = sizeof(ar5416Bank7) / sizeof(*ar5416Bank7);
+ for (i=0; i<entries; i++)
+ {
+ reg_write(ar5416Bank7[i][0], ar5416Bank7[i][1]);
+ }
+#endif
+
+ zfFlushDelayWrite(dev);
+}
+
+/* Bank 4 */
+void zfSetBank4AndPowerTable(zdev_t* dev, u32_t frequency, u8_t bw40,
+ u8_t extOffset)
+{
+ u32_t chup = 1;
+ u32_t bmode_LF_synth_freq = 0;
+ u32_t amode_refsel_1 = 0;
+ u32_t amode_refsel_0 = 1;
+ u32_t addr2 = 1;
+ u32_t addr1 = 0;
+ u32_t addr0 = 0;
+
+ u32_t d1;
+ u32_t d0;
+ u32_t tmp_0;
+ u32_t tmp_1;
+ u32_t data0;
+ u32_t data1;
+
+ u8_t chansel;
+ u8_t chan_sel;
+ u32_t temp_chan_sel;
+
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+
+
+ /* if enable 802.11h, need to record curent channel index in channel array */
+ if (wd->sta.DFSEnable)
+ {
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel == frequency)
+ break;
+ }
+ wd->regulationTable.CurChIndex = i;
+ }
+
+ if (bw40 == 1)
+ {
+ if (extOffset == 1)
+ {
+ frequency += 10;
+ }
+ else
+ {
+ frequency -= 10;
+ }
+
+ }
+
+
+ if ( frequency > 3000 )
+ {
+ if ( frequency % 10 )
+ {
+ /* 5M */
+ chan_sel = (u8_t)((frequency - 4800)/5);
+ chan_sel = (u8_t)(chan_sel & 0xff);
+ chansel = (u8_t)reverse_bits(chan_sel);
+ }
+ else
+ {
+ /* 10M : improve Tx EVM */
+ chan_sel = (u8_t)((frequency - 4800)/10);
+ chan_sel = (u8_t)(chan_sel & 0xff)<<1;
+ chansel = (u8_t)reverse_bits(chan_sel);
+
+ amode_refsel_1 = 1;
+ amode_refsel_0 = 0;
+ }
+ }
+ else
+ {
+ //temp_chan_sel = (((frequency - 672)*2) - 3040)/10;
+ if (frequency == 2484)
+ {
+ temp_chan_sel = 10 + (frequency - 2274)/5 ;
+ bmode_LF_synth_freq = 1;
+ }
+ else
+ {
+ temp_chan_sel = 16 + (frequency - 2272)/5 ;
+ bmode_LF_synth_freq = 0;
+ }
+ chan_sel = (u8_t)(temp_chan_sel << 2) & 0xff;
+ chansel = (u8_t)reverse_bits(chan_sel);
+ }
+
+ d1 = chansel; //# 8 bits of chan
+ d0 = addr0<<7 | addr1<<6 | addr2<<5
+ | amode_refsel_0<<3 | amode_refsel_1<<2
+ | bmode_LF_synth_freq<<1 | chup;
+
+ tmp_0 = d0 & 0x1f; //# 5-1
+ tmp_1 = d1 & 0x1f; //# 5-1
+ data0 = tmp_1<<5 | tmp_0;
+
+ tmp_0 = d0>>5 & 0x7; //# 8-6
+ tmp_1 = d1>>5 & 0x7; //# 8-6
+ data1 = tmp_1<<5 | tmp_0;
+
+ /* Bank4 */
+ reg_write (0x9800+(0x2c<<2), data0);
+ reg_write (0x9800+(0x3a<<2), data1);
+ //zm_debug_msg1("0x9800+(0x2c<<2 = ", data0);
+ //zm_debug_msg1("0x9800+(0x3a<<2 = ", data1);
+
+
+ zfFlushDelayWrite(dev);
+
+ zfwSleep(dev, 10);
+
+ return;
+}
+
+
+struct zsPhyFreqPara
+{
+ u32_t coeff_exp;
+ u32_t coeff_man;
+ u32_t coeff_exp_shgi;
+ u32_t coeff_man_shgi;
+};
+
+struct zsPhyFreqTable
+{
+ u32_t frequency;
+ struct zsPhyFreqPara FpgaDynamicHT;
+ struct zsPhyFreqPara FpgaStaticHT;
+ struct zsPhyFreqPara ChipST20Mhz;
+ struct zsPhyFreqPara Chip2040Mhz;
+ struct zsPhyFreqPara Chip2040ExtAbove;
+};
+
+const struct zsPhyFreqTable zgPhyFreqCoeff[] =
+{
+/*Index freq FPGA DYNAMIC_HT2040_EN FPGA STATIC_HT20 Real Chip static20MHz Real Chip 2040MHz Real Chip 2040Mhz */
+ /* fclk = 10.8 21.6 40 ext below 40 ext above 40 */
+/* 0 */ {2412, {5, 23476, 5, 21128}, {4, 23476, 4, 21128}, {3, 21737, 3, 19563}, {3, 21827, 3, 19644}, {3, 21647, 3, 19482}},
+/* 1 */ {2417, {5, 23427, 5, 21084}, {4, 23427, 4, 21084}, {3, 21692, 3, 19523}, {3, 21782, 3, 19604}, {3, 21602, 3, 19442}},
+/* 2 */ {2422, {5, 23379, 5, 21041}, {4, 23379, 4, 21041}, {3, 21647, 3, 19482}, {3, 21737, 3, 19563}, {3, 21558, 3, 19402}},
+/* 3 */ {2427, {5, 23330, 5, 20997}, {4, 23330, 4, 20997}, {3, 21602, 3, 19442}, {3, 21692, 3, 19523}, {3, 21514, 3, 19362}},
+/* 4 */ {2432, {5, 23283, 5, 20954}, {4, 23283, 4, 20954}, {3, 21558, 3, 19402}, {3, 21647, 3, 19482}, {3, 21470, 3, 19323}},
+/* 5 */ {2437, {5, 23235, 5, 20911}, {4, 23235, 4, 20911}, {3, 21514, 3, 19362}, {3, 21602, 3, 19442}, {3, 21426, 3, 19283}},
+/* 6 */ {2442, {5, 23187, 5, 20868}, {4, 23187, 4, 20868}, {3, 21470, 3, 19323}, {3, 21558, 3, 19402}, {3, 21382, 3, 19244}},
+/* 7 */ {2447, {5, 23140, 5, 20826}, {4, 23140, 4, 20826}, {3, 21426, 3, 19283}, {3, 21514, 3, 19362}, {3, 21339, 3, 19205}},
+/* 8 */ {2452, {5, 23093, 5, 20783}, {4, 23093, 4, 20783}, {3, 21382, 3, 19244}, {3, 21470, 3, 19323}, {3, 21295, 3, 19166}},
+/* 9 */ {2457, {5, 23046, 5, 20741}, {4, 23046, 4, 20741}, {3, 21339, 3, 19205}, {3, 21426, 3, 19283}, {3, 21252, 3, 19127}},
+/* 10 */ {2462, {5, 22999, 5, 20699}, {4, 22999, 4, 20699}, {3, 21295, 3, 19166}, {3, 21382, 3, 19244}, {3, 21209, 3, 19088}},
+/* 11 */ {2467, {5, 22952, 5, 20657}, {4, 22952, 4, 20657}, {3, 21252, 3, 19127}, {3, 21339, 3, 19205}, {3, 21166, 3, 19050}},
+/* 12 */ {2472, {5, 22906, 5, 20615}, {4, 22906, 4, 20615}, {3, 21209, 3, 19088}, {3, 21295, 3, 19166}, {3, 21124, 3, 19011}},
+/* 13 */ {2484, {5, 22795, 5, 20516}, {4, 22795, 4, 20516}, {3, 21107, 3, 18996}, {3, 21192, 3, 19073}, {3, 21022, 3, 18920}},
+/* 14 */ {4920, {6, 23018, 6, 20716}, {5, 23018, 5, 20716}, {4, 21313, 4, 19181}, {4, 21356, 4, 19220}, {4, 21269, 4, 19142}},
+/* 15 */ {4940, {6, 22924, 6, 20632}, {5, 22924, 5, 20632}, {4, 21226, 4, 19104}, {4, 21269, 4, 19142}, {4, 21183, 4, 19065}},
+/* 16 */ {4960, {6, 22832, 6, 20549}, {5, 22832, 5, 20549}, {4, 21141, 4, 19027}, {4, 21183, 4, 19065}, {4, 21098, 4, 18988}},
+/* 17 */ {4980, {6, 22740, 6, 20466}, {5, 22740, 5, 20466}, {4, 21056, 4, 18950}, {4, 21098, 4, 18988}, {4, 21014, 4, 18912}},
+/* 18 */ {5040, {6, 22469, 6, 20223}, {5, 22469, 5, 20223}, {4, 20805, 4, 18725}, {4, 20846, 4, 18762}, {4, 20764, 4, 18687}},
+/* 19 */ {5060, {6, 22381, 6, 20143}, {5, 22381, 5, 20143}, {4, 20723, 4, 18651}, {4, 20764, 4, 18687}, {4, 20682, 4, 18614}},
+/* 20 */ {5080, {6, 22293, 6, 20063}, {5, 22293, 5, 20063}, {4, 20641, 4, 18577}, {4, 20682, 4, 18614}, {4, 20601, 4, 18541}},
+/* 21 */ {5180, {6, 21862, 6, 19676}, {5, 21862, 5, 19676}, {4, 20243, 4, 18219}, {4, 20282, 4, 18254}, {4, 20204, 4, 18183}},
+/* 22 */ {5200, {6, 21778, 6, 19600}, {5, 21778, 5, 19600}, {4, 20165, 4, 18148}, {4, 20204, 4, 18183}, {4, 20126, 4, 18114}},
+/* 23 */ {5220, {6, 21695, 6, 19525}, {5, 21695, 5, 19525}, {4, 20088, 4, 18079}, {4, 20126, 4, 18114}, {4, 20049, 4, 18044}},
+/* 24 */ {5240, {6, 21612, 6, 19451}, {5, 21612, 5, 19451}, {4, 20011, 4, 18010}, {4, 20049, 4, 18044}, {4, 19973, 4, 17976}},
+/* 25 */ {5260, {6, 21530, 6, 19377}, {5, 21530, 5, 19377}, {4, 19935, 4, 17941}, {4, 19973, 4, 17976}, {4, 19897, 4, 17907}},
+/* 26 */ {5280, {6, 21448, 6, 19303}, {5, 21448, 5, 19303}, {4, 19859, 4, 17873}, {4, 19897, 4, 17907}, {4, 19822, 4, 17840}},
+/* 27 */ {5300, {6, 21367, 6, 19230}, {5, 21367, 5, 19230}, {4, 19784, 4, 17806}, {4, 19822, 4, 17840}, {4, 19747, 4, 17772}},
+/* 28 */ {5320, {6, 21287, 6, 19158}, {5, 21287, 5, 19158}, {4, 19710, 4, 17739}, {4, 19747, 4, 17772}, {4, 19673, 4, 17706}},
+/* 29 */ {5500, {6, 20590, 6, 18531}, {5, 20590, 5, 18531}, {4, 19065, 4, 17159}, {4, 19100, 4, 17190}, {4, 19030, 4, 17127}},
+/* 30 */ {5520, {6, 20516, 6, 18464}, {5, 20516, 5, 18464}, {4, 18996, 4, 17096}, {4, 19030, 4, 17127}, {4, 18962, 4, 17065}},
+/* 31 */ {5540, {6, 20442, 6, 18397}, {5, 20442, 5, 18397}, {4, 18927, 4, 17035}, {4, 18962, 4, 17065}, {4, 18893, 4, 17004}},
+/* 32 */ {5560, {6, 20368, 6, 18331}, {5, 20368, 5, 18331}, {4, 18859, 4, 16973}, {4, 18893, 4, 17004}, {4, 18825, 4, 16943}},
+/* 33 */ {5580, {6, 20295, 6, 18266}, {5, 20295, 5, 18266}, {4, 18792, 4, 16913}, {4, 18825, 4, 16943}, {4, 18758, 4, 16882}},
+/* 34 */ {5600, {6, 20223, 6, 18200}, {5, 20223, 5, 18200}, {4, 18725, 4, 16852}, {4, 18758, 4, 16882}, {4, 18691, 4, 16822}},
+/* 35 */ {5620, {6, 20151, 6, 18136}, {5, 20151, 5, 18136}, {4, 18658, 4, 16792}, {4, 18691, 4, 16822}, {4, 18625, 4, 16762}},
+/* 36 */ {5640, {6, 20079, 6, 18071}, {5, 20079, 5, 18071}, {4, 18592, 4, 16733}, {4, 18625, 4, 16762}, {4, 18559, 4, 16703}},
+/* 37 */ {5660, {6, 20008, 6, 18007}, {5, 20008, 5, 18007}, {4, 18526, 4, 16673}, {4, 18559, 4, 16703}, {4, 18493, 4, 16644}},
+/* 38 */ {5680, {6, 19938, 6, 17944}, {5, 19938, 5, 17944}, {4, 18461, 4, 16615}, {4, 18493, 4, 16644}, {4, 18428, 4, 16586}},
+/* 39 */ {5700, {6, 19868, 6, 17881}, {5, 19868, 5, 17881}, {4, 18396, 4, 16556}, {4, 18428, 4, 16586}, {4, 18364, 4, 16527}},
+/* 40 */ {5745, {6, 19712, 6, 17741}, {5, 19712, 5, 17741}, {4, 18252, 4, 16427}, {4, 18284, 4, 16455}, {4, 18220, 4, 16398}},
+/* 41 */ {5765, {6, 19644, 6, 17679}, {5, 19644, 5, 17679}, {4, 18189, 5, 32740}, {4, 18220, 4, 16398}, {4, 18157, 5, 32683}},
+/* 42 */ {5785, {6, 19576, 6, 17618}, {5, 19576, 5, 17618}, {4, 18126, 5, 32626}, {4, 18157, 5, 32683}, {4, 18094, 5, 32570}},
+/* 43 */ {5805, {6, 19508, 6, 17558}, {5, 19508, 5, 17558}, {4, 18063, 5, 32514}, {4, 18094, 5, 32570}, {4, 18032, 5, 32458}},
+/* 44 */ {5825, {6, 19441, 6, 17497}, {5, 19441, 5, 17497}, {4, 18001, 5, 32402}, {4, 18032, 5, 32458}, {4, 17970, 5, 32347}},
+/* 45 */ {5170, {6, 21904, 6, 19714}, {5, 21904, 5, 19714}, {4, 20282, 4, 18254}, {4, 20321, 4, 18289}, {4, 20243, 4, 18219}},
+/* 46 */ {5190, {6, 21820, 6, 19638}, {5, 21820, 5, 19638}, {4, 20204, 4, 18183}, {4, 20243, 4, 18219}, {4, 20165, 4, 18148}},
+/* 47 */ {5210, {6, 21736, 6, 19563}, {5, 21736, 5, 19563}, {4, 20126, 4, 18114}, {4, 20165, 4, 18148}, {4, 20088, 4, 18079}},
+/* 48 */ {5230, {6, 21653, 6, 19488}, {5, 21653, 5, 19488}, {4, 20049, 4, 18044}, {4, 20088, 4, 18079}, {4, 20011, 4, 18010}}
+};
+/* to reduce search time, please modify this define if you add or delete channel in table */
+#define First5GChannelIndex 14
+
+void zfGetHwTurnOffdynParam(zdev_t* dev,
+ u32_t frequency, u8_t bw40, u8_t extOffset,
+ int* delta_slope_coeff_exp,
+ int* delta_slope_coeff_man,
+ int* delta_slope_coeff_exp_shgi,
+ int* delta_slope_coeff_man_shgi)
+{
+ /* Get param for turnoffdyn */
+ u16_t i, arraySize;
+
+ //zmw_get_wlan_dev(dev);
+
+ arraySize = sizeof(zgPhyFreqCoeff)/sizeof(struct zsPhyFreqTable);
+ if (frequency < 3000)
+ {
+ /* 2.4GHz Channel */
+ for (i = 0; i < First5GChannelIndex; i++)
+ {
+ if (frequency == zgPhyFreqCoeff[i].frequency)
+ break;
+ }
+
+ if (i < First5GChannelIndex)
+ {
+ }
+ else
+ {
+ zm_msg1_scan(ZM_LV_0, "Unsupported 2.4G frequency = ", frequency);
+ return;
+ }
+ }
+ else
+ {
+ /* 5GHz Channel */
+ for (i = First5GChannelIndex; i < arraySize; i++)
+ {
+ if (frequency == zgPhyFreqCoeff[i].frequency)
+ break;
+ }
+
+ if (i < arraySize)
+ {
+ }
+ else
+ {
+ zm_msg1_scan(ZM_LV_0, "Unsupported 5G frequency = ", frequency);
+ return;
+ }
+ }
+
+ /* FPGA DYNAMIC_HT2040_EN fclk = 10.8 */
+ /* FPGA STATIC_HT20_ fclk = 21.6 */
+ /* Real Chip fclk = 40 */
+ #if ZM_FPGA_PHY == 1
+ //fclk = 10.8;
+ *delta_slope_coeff_exp = zgPhyFreqCoeff[i].FpgaDynamicHT.coeff_exp;
+ *delta_slope_coeff_man = zgPhyFreqCoeff[i].FpgaDynamicHT.coeff_man;
+ *delta_slope_coeff_exp_shgi = zgPhyFreqCoeff[i].FpgaDynamicHT.coeff_exp_shgi;
+ *delta_slope_coeff_man_shgi = zgPhyFreqCoeff[i].FpgaDynamicHT.coeff_man_shgi;
+ #else
+ //fclk = 40;
+ if (bw40)
+ {
+ /* ht2040 */
+ if (extOffset == 1) {
+ *delta_slope_coeff_exp = zgPhyFreqCoeff[i].Chip2040ExtAbove.coeff_exp;
+ *delta_slope_coeff_man = zgPhyFreqCoeff[i].Chip2040ExtAbove.coeff_man;
+ *delta_slope_coeff_exp_shgi = zgPhyFreqCoeff[i].Chip2040ExtAbove.coeff_exp_shgi;
+ *delta_slope_coeff_man_shgi = zgPhyFreqCoeff[i].Chip2040ExtAbove.coeff_man_shgi;
+ }
+ else {
+ *delta_slope_coeff_exp = zgPhyFreqCoeff[i].Chip2040Mhz.coeff_exp;
+ *delta_slope_coeff_man = zgPhyFreqCoeff[i].Chip2040Mhz.coeff_man;
+ *delta_slope_coeff_exp_shgi = zgPhyFreqCoeff[i].Chip2040Mhz.coeff_exp_shgi;
+ *delta_slope_coeff_man_shgi = zgPhyFreqCoeff[i].Chip2040Mhz.coeff_man_shgi;
+ }
+ }
+ else
+ {
+ /* static 20 */
+ *delta_slope_coeff_exp = zgPhyFreqCoeff[i].ChipST20Mhz.coeff_exp;
+ *delta_slope_coeff_man = zgPhyFreqCoeff[i].ChipST20Mhz.coeff_man;
+ *delta_slope_coeff_exp_shgi = zgPhyFreqCoeff[i].ChipST20Mhz.coeff_exp_shgi;
+ *delta_slope_coeff_man_shgi = zgPhyFreqCoeff[i].ChipST20Mhz.coeff_man_shgi;
+ }
+ #endif
+}
+
+/* Main routin frequency setting function */
+/* If 2.4G/5G switch, PHY need resetting BB and RF for band switch */
+/* Do the setting switch in zfSendFrequencyCmd() */
+void zfHpSetFrequencyEx(zdev_t* dev, u32_t frequency, u8_t bw40,
+ u8_t extOffset, u8_t initRF)
+{
+ u32_t cmd[9];
+ u32_t cmdB[3];
+ u16_t ret;
+ u8_t old_band;
+ u8_t new_band;
+ u32_t checkLoopCount;
+ u32_t tmpValue;
+
+ int delta_slope_coeff_exp;
+ int delta_slope_coeff_man;
+ int delta_slope_coeff_exp_shgi;
+ int delta_slope_coeff_man_shgi;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+
+ zm_msg1_scan(ZM_LV_1, "Frequency = ", frequency);
+ zm_msg1_scan(ZM_LV_1, "bw40 = ", bw40);
+ zm_msg1_scan(ZM_LV_1, "extOffset = ", extOffset);
+
+ if ( hpPriv->coldResetNeedFreq )
+ {
+ hpPriv->coldResetNeedFreq = 0;
+ initRF = 2;
+ zm_debug_msg0("zfHpSetFrequencyEx: Do ColdReset ");
+ }
+ if ( hpPriv->isSiteSurvey == 2 )
+ {
+ /* wait time for AGC and noise calibration : not in sitesurvey and connected */
+ checkLoopCount = 2000; /* 2000*100 = 200ms */
+ }
+ else
+ {
+ /* wait time for AGC and noise calibration : in sitesurvey */
+ checkLoopCount = 1000; /* 1000*100 = 100ms */
+ }
+
+ hpPriv->latestFrequency = frequency;
+ hpPriv->latestBw40 = bw40;
+ hpPriv->latestExtOffset = extOffset;
+
+ if ((hpPriv->dot11Mode == ZM_HAL_80211_MODE_IBSS_GENERAL) ||
+ (hpPriv->dot11Mode == ZM_HAL_80211_MODE_IBSS_WPA2PSK))
+ {
+ if ( frequency <= ZM_CH_G_14 )
+ {
+ /* workaround for 11g Ad Hoc beacon distribution */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC0_CW, 0x7f0007);
+ //zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_AC0_AIFS, 0x1c04901c);
+ }
+ }
+
+ /* AHB, DAC, ADC clock selection by static20/ht2040 */
+ zfSelAdcClk(dev, bw40, frequency);
+
+ /* clear bb_heavy_clip_enable */
+ reg_write(0x99e0, 0x200);
+ zfFlushDelayWrite(dev);
+
+ /* Set CTS/RTS rate */
+ if ( frequency > ZM_CH_G_14 )
+ {
+ //zfHpSetRTSCTSRate(dev, 0x10b010b); /* OFDM 6M */
+ new_band = 1;
+ }
+ else
+ {
+ //zfHpSetRTSCTSRate(dev, 0x30003); /* CCK 11M */
+ new_band = 0;
+ }
+
+ if (((struct zsHpPriv*)wd->hpPrivate)->hwFrequency > ZM_CH_G_14)
+ old_band = 1;
+ else
+ old_band = 0;
+
+ //Workaround for 2.4GHz only device
+ if ((hpPriv->OpFlags & 0x1) == 0)
+ {
+ if ((((struct zsHpPriv*)wd->hpPrivate)->hwFrequency == ZM_CH_G_1) && (frequency == ZM_CH_G_2))
+ {
+ /* Force to do band switching */
+ old_band = 1;
+ }
+ }
+
+ /* Notify channel switch to firmware */
+ /* TX/RX must be stopped by now */
+ cmd[0] = 0 | (ZM_CMD_FREQ_STRAT << 8);
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_INTERNAL_WRITE, 0);
+
+ if ((initRF != 0) || (new_band != old_band)
+ || (((struct zsHpPriv*)wd->hpPrivate)->hwBw40 != bw40))
+ {
+ /* band switch */
+ zm_msg0_scan(ZM_LV_1, "=====band switch=====");
+
+ if (initRF == 2 )
+ {
+ //Cold reset BB/ADDA
+ zfDelayWriteInternalReg(dev, 0x1d4004, 0x800);
+ zfFlushDelayWrite(dev);
+ zm_msg0_scan(ZM_LV_1, "Do cold reset BB/ADDA");
+ }
+ else
+ {
+ //Warm reset BB/ADDA
+ zfDelayWriteInternalReg(dev, 0x1d4004, 0x400);
+ zfFlushDelayWrite(dev);
+ }
+
+ /* reset workaround state to default */
+ hpPriv->rxStrongRSSI = 0;
+ hpPriv->strongRSSI = 0;
+
+ zfDelayWriteInternalReg(dev, 0x1d4004, 0x0);
+ zfFlushDelayWrite(dev);
+
+ zfInitPhy(dev, frequency, bw40);
+
+// zfiCheckRifs(dev);
+
+ /* Bank 0 1 2 3 5 6 7 */
+ zfSetRfRegs(dev, frequency);
+ /* Bank 4 */
+ zfSetBank4AndPowerTable(dev, frequency, bw40, extOffset);
+
+ cmd[0] = 32 | (ZM_CMD_RF_INIT << 8);
+ }
+ else //((new_band == old_band) && !initRF)
+ {
+ /* same band */
+
+ /* Force disable CR671 bit20 / 7823 */
+ /* The bug has to do with the polarity of the pdadc offset calibration. There */
+ /* is an initial calibration that is OK, and there is a continuous */
+ /* calibration that updates the pddac with the wrong polarity. Fortunately */
+ /* the second loop can be disabled with a bit called en_pd_dc_offset_thr. */
+#if 0
+ cmdB[0] = 8 | (ZM_CMD_BITAND << 8);;
+ cmdB[1] = (0xa27c + 0x1bc000);
+ cmdB[2] = 0xffefffff;
+ ret = zfIssueCmd(dev, cmdB, 12, ZM_OID_INTERNAL_WRITE, 0);
+#endif
+
+ /* Bank 4 */
+ zfSetBank4AndPowerTable(dev, frequency, bw40, extOffset);
+
+
+ cmd[0] = 32 | (ZM_CMD_FREQUENCY << 8);
+ }
+
+ /* Compatibility for new layout UB83 */
+ /* Setting code at CR1 here move from the func:zfHwHTEnable() in firmware */
+ if (((struct zsHpPriv*)wd->hpPrivate)->halCapability & ZM_HP_CAP_11N_ONE_TX_STREAM)
+ {
+ /* UB83 : one stream */
+ tmpValue = 0;
+ }
+ else
+ {
+ /* UB81, UB82 : two stream */
+ tmpValue = 0x100;
+ }
+
+ if (1) //if (((struct zsHpPriv*)wd->hpPrivate)->hw_HT_ENABLE == 1)
+ {
+ if (bw40 == 1)
+ {
+ if (extOffset == 1) {
+ reg_write(0x9804, tmpValue | 0x2d4); //3d4 for real
+ }
+ else {
+ reg_write(0x9804, tmpValue | 0x2c4); //3c4 for real
+ }
+ //# Dyn HT2040.Refer to Reg 1.
+ //#[3]:single length (4us) 1st HT long training symbol; use Walsh spatial spreading for 2 chains 2 streams TX
+ //#[c]:allow short GI for HT40 packets; enable HT detection.
+ //#[4]:enable 20/40 MHz channel detection.
+ }
+ else
+ {
+ reg_write(0x9804, tmpValue | 0x240);
+ //# Static HT20
+ //#[3]:single length (4us) 1st HT long training symbol; use Walsh spatial spreading for 2 chains 2 streams TX
+ //#[4]:Otus don't allow short GI for HT20 packets yet; enable HT detection.
+ //#[0]:disable 20/40 MHz channel detection.
+ }
+ }
+ else
+ {
+ reg_write(0x9804, 0x0);
+ //# Legacy;# Direct Mapping for each chain.
+ //#Be modified by Oligo to add dynanic for legacy.
+ if (bw40 == 1)
+ {
+ reg_write(0x9804, 0x4); //# Dyn Legacy .Refer to reg 1.
+ }
+ else
+ {
+ reg_write(0x9804, 0x0); //# Static Legacy
+ }
+ }
+ zfFlushDelayWrite(dev);
+ /* end of ub83 compatibility */
+
+ /* Set Power, TPC, Gain table... */
+ zfSetPowerCalTable(dev, frequency, bw40, extOffset);
+
+
+ /* store frequency */
+ ((struct zsHpPriv*)wd->hpPrivate)->hwFrequency = (u16_t)frequency;
+ ((struct zsHpPriv*)wd->hpPrivate)->hwBw40 = bw40;
+ ((struct zsHpPriv*)wd->hpPrivate)->hwExtOffset = extOffset;
+
+ zfGetHwTurnOffdynParam(dev,
+ frequency, bw40, extOffset,
+ &delta_slope_coeff_exp,
+ &delta_slope_coeff_man,
+ &delta_slope_coeff_exp_shgi,
+ &delta_slope_coeff_man_shgi);
+
+ /* related functions */
+ frequency = frequency*1000;
+ /* len[36] : type[0x30] : seq[?] */
+// cmd[0] = 28 | (ZM_CMD_FREQUENCY << 8);
+ cmd[1] = frequency;
+ cmd[2] = bw40;//((struct zsHpPriv*)wd->hpPrivate)->hw_DYNAMIC_HT2040_EN;
+ cmd[3] = (extOffset<<2)|0x1;//((wd->ExtOffset << 2) | ((struct zsHpPriv*)wd->hpPrivate)->hw_HT_ENABLE);
+ cmd[4] = delta_slope_coeff_exp;
+ cmd[5] = delta_slope_coeff_man;
+ cmd[6] = delta_slope_coeff_exp_shgi;
+ cmd[7] = delta_slope_coeff_man_shgi;
+ cmd[8] = checkLoopCount;
+
+ ret = zfIssueCmd(dev, cmd, 36, ZM_CMD_SET_FREQUENCY, 0);
+
+ // delay temporarily, wait for new PHY and RF
+ //zfwSleep(dev, 1000);
+}
+
+
+/******************** Key ********************/
+
+u16_t zfHpResetKeyCache(zdev_t* dev)
+{
+ u8_t i;
+ u32_t key[4] = {0, 0, 0, 0};
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ for(i=0;i<4;i++)
+ {
+ zfHpSetDefaultKey(dev, i, ZM_WEP64, key, NULL);
+ }
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ROLL_CALL_TBL_L, 0x00);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ROLL_CALL_TBL_H, 0x00);
+ zfFlushDelayWrite(dev);
+
+ hpPriv->camRollCallTable = (u64_t) 0;
+
+ return 0;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfSetKey */
+/* Set key. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2006.1 */
+/* */
+/************************************************************************/
+/* ! please use zfCoreSetKey() in 80211Core for SetKey */
+u32_t zfHpSetKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t type,
+ u16_t* mac, u32_t* key)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret;
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+#if 0 /* remove to zfCoreSetKey() */
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ wd->sta.flagKeyChanging++;
+ zm_debug_msg1(" zfHpSetKey++++ ", wd->sta.flagKeyChanging);
+ zmw_leave_critical_section(dev);
+#endif
+
+ cmd[0] = 0x0000281C;
+ cmd[1] = ((u32_t)keyId<<16) + (u32_t)user;
+ cmd[2] = ((u32_t)mac[0]<<16) + (u32_t)type;
+ cmd[3] = ((u32_t)mac[2]<<16) + ((u32_t)mac[1]);
+
+ for (i=0; i<4; i++)
+ {
+ cmd[4+i] = key[i];
+ }
+
+ if (user < 64)
+ {
+ hpPriv->camRollCallTable |= ((u64_t) 1) << user;
+ }
+
+ //ret = zfIssueCmd(dev, cmd, 32, ZM_OID_INTERNAL_WRITE, NULL);
+ ret = zfIssueCmd(dev, cmd, 32, ZM_CMD_SET_KEY, NULL);
+ return ret;
+}
+
+
+u32_t zfHpSetApPairwiseKey(zdev_t* dev, u16_t* staMacAddr, u8_t type,
+ u32_t* key, u32_t* micKey, u16_t staAid)
+{
+ if ((staAid!=0) && (staAid<64))
+ {
+ zfHpSetKey(dev, (staAid-1), 0, type, staMacAddr, key);
+ if ((type == ZM_TKIP)
+#ifdef ZM_ENABLE_CENC
+ || (type == ZM_CENC)
+#endif //ZM_ENABLE_CENC
+ )
+ zfHpSetKey(dev, (staAid-1), 1, type, staMacAddr, micKey);
+ return 0;
+ }
+ return 1;
+}
+
+u32_t zfHpSetApGroupKey(zdev_t* dev, u16_t* apMacAddr, u8_t type,
+ u32_t* key, u32_t* micKey, u16_t vapId)
+{
+ zfHpSetKey(dev, ZM_USER_KEY_DEFAULT - 1 - vapId, 0, type, apMacAddr, key); // 6D18 modify from 0 to 1 ??
+ if ((type == ZM_TKIP)
+#ifdef ZM_ENABLE_CENC
+ || (type == ZM_CENC)
+#endif //ZM_ENABLE_CENC
+ )
+ zfHpSetKey(dev, ZM_USER_KEY_DEFAULT - 1 - vapId, 1, type, apMacAddr, micKey);
+ return 0;
+}
+
+u32_t zfHpSetDefaultKey(zdev_t* dev, u8_t keyId, u8_t type, u32_t* key, u32_t* micKey)
+{
+ u16_t macAddr[3] = {0, 0, 0};
+
+ #ifdef ZM_ENABLE_IBSS_WPA2PSK
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+
+ if ( hpPriv->dot11Mode == ZM_HAL_80211_MODE_IBSS_WPA2PSK )
+ { /* If not wpa2psk , use traditional */
+ /* Because the bug of chip , defaultkey should follow the key map rule in register 700 */
+ if ( keyId == 0 )
+ zfHpSetKey(dev, ZM_USER_KEY_DEFAULT+keyId, 0, type, macAddr, key);
+ else
+ zfHpSetKey(dev, ZM_USER_KEY_DEFAULT+keyId, 1, type, macAddr, key);
+ }
+ else
+ zfHpSetKey(dev, ZM_USER_KEY_DEFAULT+keyId, 0, type, macAddr, key);
+ #else
+ zfHpSetKey(dev, ZM_USER_KEY_DEFAULT+keyId, 0, type, macAddr, key);
+ #endif
+ if ((type == ZM_TKIP)
+
+#ifdef ZM_ENABLE_CENC
+ || (type == ZM_CENC)
+#endif //ZM_ENABLE_CENC
+ )
+ {
+ zfHpSetKey(dev, ZM_USER_KEY_DEFAULT+keyId, 1, type, macAddr, micKey);
+ }
+
+ return 0;
+}
+
+u32_t zfHpSetPerUserKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t* mac, u8_t type, u32_t* key, u32_t* micKey)
+{
+#ifdef ZM_ENABLE_IBSS_WPA2PSK
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+
+ if ( hpPriv->dot11Mode == ZM_HAL_80211_MODE_IBSS_WPA2PSK )
+ { /* If not wpa2psk , use traditional */
+ if(keyId)
+ { /* Set Group Key */
+ zfHpSetKey(dev, user, 1, type, (u16_t *)mac, key);
+ }
+ else if(keyId == 0)
+ { /* Set Pairwise Key */
+ zfHpSetKey(dev, user, 0, type, (u16_t *)mac, key);
+ }
+ }
+ else
+ {
+ zfHpSetKey(dev, user, keyId, type, (u16_t *)mac, key);
+ }
+#else
+ zfHpSetKey(dev, user, keyId, type, (u16_t *)mac, key);
+#endif
+
+ if ((type == ZM_TKIP)
+#ifdef ZM_ENABLE_CENC
+ || (type == ZM_CENC)
+#endif //ZM_ENABLE_CENC
+ )
+ {
+ zfHpSetKey(dev, user, keyId + 1, type, (u16_t *)mac, micKey);
+ }
+ return 0;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfHpRemoveKey */
+/* Remove key. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Yuan-Gu Wei ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+u16_t zfHpRemoveKey(zdev_t* dev, u16_t user)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret = 0;
+
+ cmd[0] = 0x00002904;
+ cmd[1] = (u32_t)user;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_INTERNAL_WRITE, NULL);
+ return ret;
+}
+
+
+
+/******************** DMA ********************/
+u16_t zfHpStartRecv(zdev_t* dev)
+{
+ zfDelayWriteInternalReg(dev, 0x1c3d30, 0x100);
+ zfFlushDelayWrite(dev);
+
+ return 0;
+}
+
+u16_t zfHpStopRecv(zdev_t* dev)
+{
+ return 0;
+}
+
+
+/******************** MAC ********************/
+void zfInitMac(zdev_t* dev)
+{
+ /* ACK extension register */
+ // jhlee temp : change value 0x2c -> 0x40
+ // honda resolve short preamble problem : 0x40 -> 0x75
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ACK_EXTENSION, 0x40); // 0x28 -> 0x2c 6522:yflee
+
+ /* TxQ0/1/2/3 Retry MAX=2 => transmit 3 times and degrade rate for retry */
+ /* PB42 AP crash issue: */
+ /* Workaround the crash issue by CTS/RTS, set retry max to zero for */
+ /* workaround tx underrun which enable CTS/RTS */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_RETRY_MAX, 0); // 0x11111 => 0
+
+ /* use hardware MIC check */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_SNIFFER, 0x2000000);
+
+ /* Set Rx threshold to 1600 */
+#if ZM_LARGEPAYLOAD_TEST == 1
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_RX_THRESHOLD, 0xc4000);
+#else
+ #ifndef ZM_DISABLE_AMSDU8K_SUPPORT
+ /* The maximum A-MSDU length is 3839/7935 */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_RX_THRESHOLD, 0xc1f80);
+ #else
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_RX_THRESHOLD, 0xc0f80);
+ #endif
+#endif
+
+ //zfDelayWriteInternalReg(dev, ZM_MAC_REG_DYNAMIC_SIFS_ACK, 0x10A);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_RX_PE_DELAY, 0x70);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_EIFS_AND_SIFS, 0xa144000);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_SLOT_TIME, 9<<10);
+
+ /* CF-END mode */
+ zfDelayWriteInternalReg(dev, 0x1c3b2c, 0x19000000);
+
+ //NAV protects ACK only (in TXOP)
+ zfDelayWriteInternalReg(dev, 0x1c3b38, 0x201);
+
+
+ /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */
+ /* OTUS set AM to 0x1 */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_HT1, 0x8000170);
+
+ /* TODO : wep backoff protection 0x63c */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BACKOFF_PROTECT, 0x105);
+
+ /* AGG test code*/
+ /* Aggregation MAX number and timeout */
+ zfDelayWriteInternalReg(dev, 0x1c3b9c, 0x10000a);
+ /* Filter any control frames, BAR is bit 24 */
+ zfDelayWriteInternalReg(dev, 0x1c368c, 0x0500ffff);
+ /* Enable deaggregator */
+ zfDelayWriteInternalReg(dev, 0x1c3c40, 0x1);
+
+ /* Basic rate */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BASIC_RATE, 0x150f);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_MANDATORY_RATE, 0x150f);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_RTS_CTS_RATE, 0x10b01bb);
+
+ /* MIMO resposne control */
+ zfDelayWriteInternalReg(dev, 0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */
+
+ /* Enable LED0 and LED1 */
+ zfDelayWriteInternalReg(dev, 0x1d0100, 0x3);
+ zfDelayWriteInternalReg(dev, 0x1d0104, 0x3);
+
+ /* switch MAC to OTUS interface */
+ zfDelayWriteInternalReg(dev, 0x1c3600, 0x3);
+
+ /* RXMAC A-MPDU length threshold */
+ zfDelayWriteInternalReg(dev, 0x1c3c50, 0xffff);
+
+ /* Phy register read timeout */
+ zfDelayWriteInternalReg(dev, 0x1c3680, 0xf00008);
+
+ /* Disable Rx TimeOut : workaround for BB.
+ * OTUS would interrupt the rx frame that sent by OWL TxUnderRun
+ * because OTUS rx timeout behavior, then OTUS would not ack the BA for
+ * this AMPDU from OWL.
+ * Fix by Perry Hwang. 2007/05/10.
+ * 0x1c362c : Rx timeout value : bit 27~16
+ */
+ zfDelayWriteInternalReg(dev, 0x1c362c, 0x0);
+
+ //Set USB Rx stream mode MAX packet number to 2
+ // Max packet number = *0x1e1110 + 1
+ zfDelayWriteInternalReg(dev, 0x1e1110, 0x4);
+ //Set USB Rx stream mode timeout to 10us
+ zfDelayWriteInternalReg(dev, 0x1e1114, 0x80);
+
+ //Set CPU clock frequency to 88/80MHz
+ zfDelayWriteInternalReg(dev, 0x1D4008, 0x73);
+
+ //Set WLAN DMA interrupt mode : generate int per packet
+ zfDelayWriteInternalReg(dev, 0x1c3d7c, 0x110011);
+
+ /* 7807 */
+ /* enable func : Reset FIFO1 and FIFO2 when queue-gnt is low */
+ /* 0x1c3bb0 Bit2 */
+ /* Disable SwReset in firmware for TxHang, enable reset FIFO func. */
+ zfDelayWriteInternalReg(dev, 0x1c3bb0, 0x4);
+
+ /* Disables the CF_END frame */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_TXOP_NOT_ENOUGH_INDICATION, 0x141E0F48);
+
+ /* Disable the SW Decrypt*/
+ zfDelayWriteInternalReg(dev, 0x1c3678, 0x70);
+ zfFlushDelayWrite(dev);
+ //---------------------
+
+ /* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME STA default. */
+ zfUpdateDefaultQosParameter(dev, 0);
+
+ //zfSelAdcClk(dev, 0);
+
+ return;
+}
+
+
+u16_t zfHpSetSnifferMode(zdev_t* dev, u16_t on)
+{
+ if (on != 0)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_SNIFFER, 0x2000001);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_SNIFFER, 0x2000000);
+ }
+ zfFlushDelayWrite(dev);
+ return 0;
+}
+
+
+u16_t zfHpSetApStaMode(zdev_t* dev, u8_t mode)
+{
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+ hpPriv->dot11Mode = mode;
+
+ switch(mode)
+ {
+ case ZM_HAL_80211_MODE_AP:
+ zfDelayWriteInternalReg(dev, 0x1c3700, 0x0f0000a1);
+ zfDelayWriteInternalReg(dev, 0x1c3c40, 0x1);
+ break;
+
+ case ZM_HAL_80211_MODE_STA:
+ zfDelayWriteInternalReg(dev, 0x1c3700, 0x0f000002);
+ zfDelayWriteInternalReg(dev, 0x1c3c40, 0x1);
+ break;
+
+ case ZM_HAL_80211_MODE_IBSS_GENERAL:
+ zfDelayWriteInternalReg(dev, 0x1c3700, 0x0f000000);
+ zfDelayWriteInternalReg(dev, 0x1c3c40, 0x1);
+ break;
+
+ case ZM_HAL_80211_MODE_IBSS_WPA2PSK:
+ zfDelayWriteInternalReg(dev, 0x1c3700, 0x0f0000e0);
+ zfDelayWriteInternalReg(dev, 0x1c3c40, 0x41); // for multiple ( > 2 ) stations IBSS network
+ break;
+
+ default:
+ goto skip;
+ }
+
+ zfFlushDelayWrite(dev);
+
+skip:
+ return 0;
+}
+
+
+u16_t zfHpSetBssid(zdev_t* dev, u8_t* bssidSrc)
+{
+ u32_t address;
+ u16_t *bssid = (u16_t *)bssidSrc;
+
+ address = bssid[0] + (((u32_t)bssid[1]) << 16);
+ zfDelayWriteInternalReg(dev, 0x1c3618, address);
+
+ address = (u32_t)bssid[2];
+ zfDelayWriteInternalReg(dev, 0x1c361C, address);
+ zfFlushDelayWrite(dev);
+ return 0;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfHpUpdateQosParameter */
+/* Update TxQs CWMIN, CWMAX, AIFS and TXOP. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* cwminTbl : CWMIN parameter for TxQs */
+/* cwmaxTbl : CWMAX parameter for TxQs */
+/* aifsTbl: AIFS parameter for TxQs */
+/* txopTbl : TXOP parameter for TxQs */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+u8_t zfHpUpdateQosParameter(zdev_t* dev, u16_t* cwminTbl, u16_t* cwmaxTbl,
+ u16_t* aifsTbl, u16_t* txopTbl)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+
+ zm_msg0_mm(ZM_LV_0, "zfHalUpdateQosParameter()");
+
+ /* Note : Do not change cwmin for Q0 in Ad Hoc mode */
+ /* otherwise driver will fail in Wifi beacon distribution */
+ if (hpPriv->dot11Mode == ZM_HAL_80211_MODE_STA)
+ {
+#if 0 //Restore CWmin to improve down link throughput
+ //cheating in BE traffic
+ if (wd->sta.EnableHT == 1)
+ {
+ //cheating in BE traffic
+ cwminTbl[0] = 7;//15;
+ }
+#endif
+ cwmaxTbl[0] = 127;//1023;
+ aifsTbl[0] = 2*9+10;//3 * 9 + 10;
+ }
+
+ /* CWMIN and CWMAX */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC0_CW, cwminTbl[0]
+ + ((u32_t)cwmaxTbl[0]<<16));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_CW, cwminTbl[1]
+ + ((u32_t)cwmaxTbl[1]<<16));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC2_CW, cwminTbl[2]
+ + ((u32_t)cwmaxTbl[2]<<16));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC3_CW, cwminTbl[3]
+ + ((u32_t)cwmaxTbl[3]<<16));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC4_CW, cwminTbl[4]
+ + ((u32_t)cwmaxTbl[4]<<16));
+
+ /* AIFS */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_AC0_AIFS, aifsTbl[0]
+ +((u32_t)aifsTbl[0]<<12)+((u32_t)aifsTbl[0]<<24));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC3_AC2_AIFS, (aifsTbl[0]>>8)
+ +((u32_t)aifsTbl[0]<<4)+((u32_t)aifsTbl[0]<<16));
+
+ /* TXOP */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_AC0_TXOP, txopTbl[0]
+ + ((u32_t)txopTbl[1]<<16));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC3_AC2_TXOP, txopTbl[2]
+ + ((u32_t)txopTbl[3]<<16));
+
+ zfFlushDelayWrite(dev);
+
+ hpPriv->txop[0] = txopTbl[0];
+ hpPriv->txop[1] = txopTbl[1];
+ hpPriv->txop[2] = txopTbl[2];
+ hpPriv->txop[3] = txopTbl[3];
+ hpPriv->cwmin[0] = cwminTbl[0];
+ hpPriv->cwmax[0] = cwmaxTbl[0];
+ hpPriv->cwmin[1] = cwminTbl[1];
+ hpPriv->cwmax[1] = cwmaxTbl[1];
+
+ return 0;
+}
+
+
+void zfHpSetAtimWindow(zdev_t* dev, u16_t atimWin)
+{
+ zm_msg1_mm(ZM_LV_0, "Set ATIM window to ", atimWin);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ATIM_WINDOW, atimWin);
+ zfFlushDelayWrite(dev);
+}
+
+
+void zfHpSetBasicRateSet(zdev_t* dev, u16_t bRateBasic, u16_t gRateBasic)
+{
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BASIC_RATE, bRateBasic
+ | ((u16_t)gRateBasic<<8));
+ zfFlushDelayWrite(dev);
+}
+
+
+/* HT40 send by OFDM 6M */
+/* otherwise use reg 0x638 */
+void zfHpSetRTSCTSRate(zdev_t* dev, u32_t rate)
+{
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_RTS_CTS_RATE, rate);
+ zfFlushDelayWrite(dev);
+}
+
+void zfHpSetMacAddress(zdev_t* dev, u16_t* macAddr, u16_t macAddrId)
+{
+ if (macAddrId == 0)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_MAC_ADDR_L,
+ (((u32_t)macAddr[1])<<16) | macAddr[0]);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_MAC_ADDR_H, macAddr[2]);
+ }
+ else if (macAddrId <= 7)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ACK_TABLE+((macAddrId-1)*8),
+ macAddr[0] + ((u32_t)macAddr[1]<<16));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ACK_TABLE+((macAddrId-1)*8)+4,
+ macAddr[2]);
+ }
+ zfFlushDelayWrite(dev);
+}
+
+void zfHpSetMulticastList(zdev_t* dev, u8_t size, u8_t* pList, u8_t bAllMulticast)
+{
+ struct zsMulticastAddr* pMacList = (struct zsMulticastAddr*) pList;
+ u8_t i;
+ u32_t value;
+ u32_t swRegMulHashValueH, swRegMulHashValueL;
+
+ swRegMulHashValueH = 0x80000000;
+ swRegMulHashValueL = 0;
+
+ if ( bAllMulticast )
+ {
+ swRegMulHashValueH = swRegMulHashValueL = ~0;
+ }
+ else
+ {
+ for(i=0; i<size; i++)
+ {
+ value = pMacList[i].addr[5] >> 2;
+
+ if ( value < 32 )
+ {
+ swRegMulHashValueL |= (1 << value);
+ }
+ else
+ {
+ swRegMulHashValueH |= (1 << (value-32));
+ }
+ }
+ }
+
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_GROUP_HASH_TBL_L,
+ swRegMulHashValueL);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_GROUP_HASH_TBL_H,
+ swRegMulHashValueH);
+ zfFlushDelayWrite(dev);
+ return;
+}
+
+/******************** Beacon ********************/
+void zfHpEnableBeacon(zdev_t* dev, u16_t mode, u16_t bcnInterval, u16_t dtim, u8_t enableAtim)
+{
+ u32_t value;
+
+ zmw_get_wlan_dev(dev);
+
+ /* Beacon Ready */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_CTRL, 0);
+ /* Beacon DMA buffer address */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_ADDR, ZM_BEACON_BUFFER_ADDRESS);
+
+ value = bcnInterval;
+
+ value |= (((u32_t) dtim) << 16);
+
+ if (mode == ZM_MODE_AP)
+ {
+
+ value |= 0x1000000;
+ }
+ else if (mode == ZM_MODE_IBSS)
+ {
+ value |= 0x2000000;
+
+ if ( enableAtim )
+ {
+ value |= 0x4000000;
+ }
+ ((struct zsHpPriv*)wd->hpPrivate)->ibssBcnEnabled = 1;
+ ((struct zsHpPriv*)wd->hpPrivate)->ibssBcnInterval = value;
+ }
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_PRETBTT, (bcnInterval-6)<<16);
+
+ /* Beacon period and beacon enable */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PERIOD, value);
+ zfFlushDelayWrite(dev);
+}
+
+void zfHpDisableBeacon(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ ((struct zsHpPriv*)wd->hpPrivate)->ibssBcnEnabled = 0;
+
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PERIOD, 0);
+ zfFlushDelayWrite(dev);
+}
+
+void zfHpLedCtrl(zdev_t* dev, u16_t ledId, u8_t mode)
+{
+ u16_t state;
+ zmw_get_wlan_dev(dev);
+
+ //zm_debug_msg1("LED ID=", ledId);
+ //zm_debug_msg1("LED mode=", mode);
+ if (ledId < 2)
+ {
+ if (((struct zsHpPriv*)wd->hpPrivate)->ledMode[ledId] != mode)
+ {
+ ((struct zsHpPriv*)wd->hpPrivate)->ledMode[ledId] = mode;
+
+ state = ((struct zsHpPriv*)wd->hpPrivate)->ledMode[0]
+ | (((struct zsHpPriv*)wd->hpPrivate)->ledMode[1]<<1);
+ zfDelayWriteInternalReg(dev, 0x1d0104, state);
+ zfFlushDelayWrite(dev);
+ //zm_debug_msg0("Update LED");
+ }
+ }
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfHpResetTxRx */
+/* Reset Tx and Rx Desc. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Chao-Wen Yang ZyDAS Technology Corporation 2007.3 */
+/* */
+/************************************************************************/
+u16_t zfHpUsbReset(zdev_t* dev)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret = 0;
+
+ //zm_debug_msg0("CWY - Reset Tx and Rx");
+
+ cmd[0] = 0 | (ZM_CMD_RESET << 8);
+
+ ret = zfIssueCmd(dev, cmd, 4, ZM_OID_INTERNAL_WRITE, NULL);
+ return ret;
+}
+
+u16_t zfHpDKReset(zdev_t* dev, u8_t flag)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret = 0;
+
+ //zm_debug_msg0("CWY - Reset Tx and Rx");
+
+ cmd[0] = 4 | (ZM_CMD_DKRESET << 8);
+ cmd[1] = flag;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_INTERNAL_WRITE, NULL);
+ return ret;
+}
+
+u32_t zfHpCwmUpdate(zdev_t* dev)
+{
+ //u32_t cmd[3];
+ //u16_t ret;
+ //
+ //cmd[0] = 0x00000008;
+ //cmd[1] = 0x1c36e8;
+ //cmd[2] = 0x1c36ec;
+ //
+ //ret = zfIssueCmd(dev, cmd, 12, ZM_CWM_READ, 0);
+ //return ret;
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zfCoreCwmBusy(dev, zfCwmIsExtChanBusy(hpPriv->ctlBusy, hpPriv->extBusy));
+
+ hpPriv->ctlBusy = 0;
+ hpPriv->extBusy = 0;
+
+ return 0;
+}
+
+u32_t zfHpAniUpdate(zdev_t* dev)
+{
+ u32_t cmd[5];
+ u16_t ret;
+
+ cmd[0] = 0x00000010;
+ cmd[1] = 0x1c36e8;
+ cmd[2] = 0x1c36ec;
+ cmd[3] = 0x1c3cb4;
+ cmd[4] = 0x1c3cb8;
+
+ ret = zfIssueCmd(dev, cmd, 20, ZM_ANI_READ, 0);
+ return ret;
+}
+
+/*
+ * Update Beacon RSSI in ANI
+ */
+u32_t zfHpAniUpdateRssi(zdev_t* dev, u8_t rssi)
+{
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ hpPriv->stats.ast_nodestats.ns_avgbrssi = rssi;
+
+ return 0;
+}
+
+#define ZM_SEEPROM_MAC_ADDRESS_OFFSET (0x1400 + (0x106<<1))
+#define ZM_SEEPROM_REGDOMAIN_OFFSET (0x1400 + (0x104<<1))
+#define ZM_SEEPROM_VERISON_OFFSET (0x1400 + (0x102<<1))
+#define ZM_SEEPROM_HARDWARE_TYPE_OFFSET (0x1374)
+#define ZM_SEEPROM_HW_HEAVY_CLIP (0x161c)
+
+u32_t zfHpGetMacAddress(zdev_t* dev)
+{
+ u32_t cmd[7];
+ u16_t ret;
+
+ cmd[0] = 0x00000000 | 24;
+ cmd[1] = ZM_SEEPROM_MAC_ADDRESS_OFFSET;
+ cmd[2] = ZM_SEEPROM_MAC_ADDRESS_OFFSET+4;
+ cmd[3] = ZM_SEEPROM_REGDOMAIN_OFFSET;
+ cmd[4] = ZM_SEEPROM_VERISON_OFFSET;
+ cmd[5] = ZM_SEEPROM_HARDWARE_TYPE_OFFSET;
+ cmd[6] = ZM_SEEPROM_HW_HEAVY_CLIP;
+
+ ret = zfIssueCmd(dev, cmd, 28, ZM_MAC_READ, 0);
+ return ret;
+}
+
+u32_t zfHpGetTransmitPower(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+ u16_t tpc = 0;
+
+ if (hpPriv->hwFrequency < 3000) {
+ tpc = hpPriv->tPow2x2g[0] & 0x3f;
+ wd->maxTxPower2 &= 0x3f;
+ tpc = (tpc > wd->maxTxPower2)? wd->maxTxPower2 : tpc;
+ } else {
+ tpc = hpPriv->tPow2x5g[0] & 0x3f;
+ wd->maxTxPower5 &= 0x3f;
+ tpc = (tpc > wd->maxTxPower5)? wd->maxTxPower5 : tpc;
+ }
+
+ return tpc;
+}
+
+u8_t zfHpGetMinTxPower(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+ u8_t tpc = 0;
+
+ if (hpPriv->hwFrequency < 3000)
+ {
+ if(wd->BandWidth40)
+ {
+ //40M
+ tpc = (hpPriv->tPow2x2gHt40[7]&0x3f);
+ }
+ else
+ {
+ //20M
+ tpc = (hpPriv->tPow2x2gHt20[7]&0x3f);
+ }
+ }
+ else
+ {
+ if(wd->BandWidth40)
+ {
+ //40M
+ tpc = (hpPriv->tPow2x5gHt40[7]&0x3f);
+ }
+ else
+ {
+ //20M
+ tpc = (hpPriv->tPow2x5gHt20[7]&0x3f);
+ }
+ }
+
+ return tpc;
+}
+
+u8_t zfHpGetMaxTxPower(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+ u8_t tpc = 0;
+
+ if (hpPriv->hwFrequency < 3000)
+ {
+ tpc = (hpPriv->tPow2xCck[0]&0x3f);
+ }
+ else
+ {
+ tpc =(hpPriv->tPow2x5g[0]&0x3f);
+ }
+
+ return tpc;
+}
+
+u32_t zfHpLoadEEPROMFromFW(zdev_t* dev)
+{
+ u32_t cmd[16];
+ u32_t ret=0, i, j;
+ zmw_get_wlan_dev(dev);
+
+ i = ((struct zsHpPriv*)wd->hpPrivate)->eepromImageRdReq;
+
+ cmd[0] = ZM_HAL_MAX_EEPROM_PRQ*4;
+
+ for (j=0; j<ZM_HAL_MAX_EEPROM_PRQ; j++)
+ {
+ cmd[j+1] = 0x1000 + (((i*ZM_HAL_MAX_EEPROM_PRQ) + j)*4);
+ }
+
+ ret = zfIssueCmd(dev, cmd, (ZM_HAL_MAX_EEPROM_PRQ+1)*4, ZM_EEPROM_READ, 0);
+
+ return ret;
+}
+
+void zfHpHeartBeat(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+ u8_t polluted = 0;
+ u8_t ackTpc;
+
+ /* Workaround : Make OTUS fire more beacon in ad hoc mode in 2.4GHz */
+ if (hpPriv->ibssBcnEnabled != 0)
+ {
+ if (hpPriv->hwFrequency <= ZM_CH_G_14)
+ {
+ if ((wd->tick % 10) == 0)
+ {
+ if ((wd->tick % 40) == 0)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PERIOD, hpPriv->ibssBcnInterval-1);
+ polluted = 1;
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PERIOD, hpPriv->ibssBcnInterval);
+ polluted = 1;
+ }
+ }
+ }
+ }
+
+ if ((wd->tick & 0x3f) == 0x25)
+ {
+ /* Workaround for beacon stuck after SW reset */
+ if (hpPriv->ibssBcnEnabled != 0)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_ADDR, ZM_BEACON_BUFFER_ADDRESS);
+ polluted = 1;
+ }
+
+ //DbgPrint("hpPriv->aggMaxDurationBE=%d", hpPriv->aggMaxDurationBE);
+ //DbgPrint("wd->sta.avgSizeOfReceivePackets=%d", wd->sta.avgSizeOfReceivePackets);
+ if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ && (zfStaIsConnected(dev))
+ && (wd->sta.EnableHT == 1) //11n mode
+ && (wd->BandWidth40 == 1) //40MHz mode
+ && (wd->sta.enableDrvBA ==0) //Marvel AP
+ && (hpPriv->aggMaxDurationBE > 2000) //BE TXOP > 2ms
+ && (wd->sta.avgSizeOfReceivePackets > 1420))
+ {
+ zfDelayWriteInternalReg(dev, 0x1c3b9c, 0x8000a);
+ polluted = 1;
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c3b9c, hpPriv->aggPktNum);
+ polluted = 1;
+ }
+
+ if (wd->dynamicSIFSEnable == 0)
+ {
+ if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ && (zfStaIsConnected(dev))
+ && (wd->sta.EnableHT == 1) //11n mode
+ && (wd->BandWidth40 == 0) //20MHz mode
+ && (wd->sta.enableDrvBA ==0)) //Marvel AP
+ {
+ zfDelayWriteInternalReg(dev, 0x1c3698, 0x5144000);
+ polluted = 1;
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c3698, 0xA144000);
+ polluted = 1;
+ }
+ }
+ else
+ {
+ if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ && (zfStaIsConnected(dev))
+ && (wd->sta.EnableHT == 1) //11n mode
+ && (wd->sta.athOwlAp == 1)) //Atheros AP
+ {
+ if (hpPriv->retransmissionEvent)
+ {
+ switch(hpPriv->latestSIFS)
+ {
+ case 0:
+ hpPriv->latestSIFS = 1;
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_EIFS_AND_SIFS, 0x8144000);
+ break;
+ case 1:
+ hpPriv->latestSIFS = 2;
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_EIFS_AND_SIFS, 0xa144000);
+ break;
+ case 2:
+ hpPriv->latestSIFS = 3;
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_EIFS_AND_SIFS, 0xc144000);
+ break;
+ case 3:
+ hpPriv->latestSIFS = 0;
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_EIFS_AND_SIFS, 0xa144000);
+ break;
+ default:
+ hpPriv->latestSIFS = 0;
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_EIFS_AND_SIFS, 0xa144000);
+ break;
+ }
+ polluted = 1;
+ zm_debug_msg1("##### Correct Tx retransmission issue #####, ", hpPriv->latestSIFS);
+ hpPriv->retransmissionEvent = 0;
+ }
+ }
+ else
+ {
+ hpPriv->latestSIFS = 0;
+ hpPriv->retransmissionEvent = 0;
+ zfDelayWriteInternalReg(dev, 0x1c3698, 0xA144000);
+ polluted = 1;
+ }
+ }
+
+ if ((wd->sta.bScheduleScan == FALSE) && (wd->sta.bChannelScan == FALSE))
+ {
+#define ZM_SIGNAL_THRESHOLD 66
+ if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ && (zfStaIsConnected(dev))
+ && (wd->SignalStrength > ZM_SIGNAL_THRESHOLD))
+ {
+ /* remove state handle, always rewrite register setting */
+ //if (hpPriv->strongRSSI == 0)
+ {
+ hpPriv->strongRSSI = 1;
+ /* Strong RSSI, set ACK to one Tx stream and lower Tx power 7dbm */
+ if (hpPriv->currentAckRtsTpc > (14+10))
+ {
+ ackTpc = hpPriv->currentAckRtsTpc - 14;
+ }
+ else
+ {
+ ackTpc = 10;
+ }
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((ackTpc) << 20) | (0x1<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((ackTpc) << 5 ) | (0x1<<11) |
+ ((ackTpc) << 21) | (0x1<<27) );
+ polluted = 1;
+ }
+ }
+ else
+ {
+ /* remove state handle, always rewrite register setting */
+ //if (hpPriv->strongRSSI == 1)
+ {
+ hpPriv->strongRSSI = 0;
+ if (hpPriv->halCapability & ZM_HP_CAP_11N_ONE_TX_STREAM)
+ {
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((hpPriv->currentAckRtsTpc&0x3f) << 20) | (0x1<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((hpPriv->currentAckRtsTpc&0x3f) << 5 ) | (0x1<<11) |
+ ((hpPriv->currentAckRtsTpc&0x3f) << 21) | (0x1<<27) );
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((hpPriv->currentAckRtsTpc&0x3f) << 20) | (0x5<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((hpPriv->currentAckRtsTpc&0x3f) << 5 ) | (0x5<<11) |
+ ((hpPriv->currentAckRtsTpc&0x3f) << 21) | (0x5<<27) );
+ }
+ polluted = 1;
+ }
+ }
+#undef ZM_SIGNAL_THRESHOLD
+ }
+
+ if ((hpPriv->halCapability & ZM_HP_CAP_11N_ONE_TX_STREAM) == 0)
+ {
+ if ((wd->sta.bScheduleScan == FALSE) && (wd->sta.bChannelScan == FALSE))
+ {
+ #define ZM_RX_SIGNAL_THRESHOLD_H 71
+ #define ZM_RX_SIGNAL_THRESHOLD_L 66
+ u8_t rxSignalThresholdH = ZM_RX_SIGNAL_THRESHOLD_H;
+ u8_t rxSignalThresholdL = ZM_RX_SIGNAL_THRESHOLD_L;
+ #undef ZM_RX_SIGNAL_THRESHOLD_H
+ #undef ZM_RX_SIGNAL_THRESHOLD_L
+
+ if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ && (zfStaIsConnected(dev))
+ && (wd->SignalStrength > rxSignalThresholdH)
+ )//&& (hpPriv->rxStrongRSSI == 0))
+ {
+ hpPriv->rxStrongRSSI = 1;
+ //zfDelayWriteInternalReg(dev, 0x1c5964, 0x1220);
+ //zfDelayWriteInternalReg(dev, 0x1c5960, 0x900);
+ //zfDelayWriteInternalReg(dev, 0x1c6960, 0x900);
+ //zfDelayWriteInternalReg(dev, 0x1c7960, 0x900);
+ if ((hpPriv->eepromImage[0x100+0x110*2/4]&0xff) == 0x80) //FEM TYPE
+ {
+ if (hpPriv->hwFrequency <= ZM_CH_G_14)
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x900);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x9b49);
+ }
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x0900);
+ }
+ polluted = 1;
+ }
+ else if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ && (zfStaIsConnected(dev))
+ && (wd->SignalStrength > rxSignalThresholdL)
+ )//&& (hpPriv->rxStrongRSSI == 1))
+ {
+ //Do nothing to prevent frequently Rx switching
+ }
+ else
+ {
+ /* remove state handle, always rewrite register setting */
+ //if (hpPriv->rxStrongRSSI == 1)
+ {
+ hpPriv->rxStrongRSSI = 0;
+ //zfDelayWriteInternalReg(dev, 0x1c5964, 0x1120);
+ //zfDelayWriteInternalReg(dev, 0x1c5960, 0x9b40);
+ //zfDelayWriteInternalReg(dev, 0x1c6960, 0x9b40);
+ //zfDelayWriteInternalReg(dev, 0x1c7960, 0x9b40);
+ if ((hpPriv->eepromImage[0x100+0x110*2/4]&0xff) == 0x80) //FEM TYPE
+ {
+ if (hpPriv->hwFrequency <= ZM_CH_G_14)
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x9b49);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x0900);
+ }
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x9b40);
+ }
+ polluted = 1;
+ }
+ }
+
+ }
+ }
+
+ if (hpPriv->usbAcSendBytes[3] > (hpPriv->usbAcSendBytes[0]*2))
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_AC0_TXOP, hpPriv->txop[3]);
+ polluted = 1;
+ }
+ else if (hpPriv->usbAcSendBytes[2] > (hpPriv->usbAcSendBytes[0]*2))
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_AC0_TXOP, hpPriv->txop[2]);
+ polluted = 1;
+ }
+ else if (hpPriv->usbAcSendBytes[1] > (hpPriv->usbAcSendBytes[0]*2))
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC0_CW, hpPriv->cwmin[1]+((u32_t)hpPriv->cwmax[1]<<16));
+ polluted = 1;
+ }
+ else
+ {
+ if (hpPriv->slotType == 1)
+ {
+ if ((wd->sta.enableDrvBA ==0) //Marvel AP
+ && (hpPriv->aggMaxDurationBE > 2000)) //BE TXOP > 2ms
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC0_CW, (hpPriv->cwmin[0]/2)+((u32_t)hpPriv->cwmax[0]<<16));
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC0_CW, hpPriv->cwmin[0]+((u32_t)hpPriv->cwmax[0]<<16));
+ }
+ polluted = 1;
+ }
+ else
+ {
+ /* Compensation for 20us slot time */
+ //zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC0_CW, 58+((u32_t)hpPriv->cwmax[0]<<16));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC0_CW, hpPriv->cwmin[0]+((u32_t)hpPriv->cwmax[0]<<16));
+ polluted = 1;
+ }
+
+ if ((wd->sta.SWEncryptEnable & (ZM_SW_TKIP_ENCRY_EN|ZM_SW_WEP_ENCRY_EN)) == 0)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_AC0_TXOP, hpPriv->txop[0]);
+ polluted = 1;
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_AC1_AC0_TXOP, 0x30);
+ polluted = 1;
+ }
+
+ }
+ hpPriv->usbAcSendBytes[3] = 0;
+ hpPriv->usbAcSendBytes[2] = 0;
+ hpPriv->usbAcSendBytes[1] = 0;
+ hpPriv->usbAcSendBytes[0] = 0;
+ }
+
+ if (polluted == 1)
+ {
+ zfFlushDelayWrite(dev);
+ }
+
+ return;
+}
+
+/*
+ * 0x1d4008 : AHB, DAC, ADC clock selection
+ * bit1~0 AHB_CLK : AHB clock selection,
+ * 00 : OSC 40MHz;
+ * 01 : 20MHz in A mode, 22MHz in G mode;
+ * 10 : 40MHz in A mode, 44MHz in G mode;
+ * 11 : 80MHz in A mode, 88MHz in G mode.
+ * bit3~2 CLK_SEL : Select the clock source of clk160 in ADDAC.
+ * 00 : PLL divider's output;
+ * 01 : PLL divider's output divided by 2;
+ * 10 : PLL divider's output divided by 4;
+ * 11 : REFCLK from XTALOSCPAD.
+ */
+void zfSelAdcClk(zdev_t* dev, u8_t bw40, u32_t frequency)
+{
+ if(bw40 == 1)
+ {
+ //zfDelayWriteInternalReg(dev, 0x1D4008, 0x73);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_DYNAMIC_SIFS_ACK, 0x10A);
+ zfFlushDelayWrite(dev);
+ }
+ else
+ {
+ //zfDelayWriteInternalReg(dev, 0x1D4008, 0x70);
+ if ( frequency <= ZM_CH_G_14 )
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_DYNAMIC_SIFS_ACK, 0x105);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_DYNAMIC_SIFS_ACK, 0x104);
+ }
+ zfFlushDelayWrite(dev);
+ }
+}
+
+u32_t zfHpEchoCommand(zdev_t* dev, u32_t value)
+{
+ u32_t cmd[2];
+ u16_t ret;
+
+ cmd[0] = 0x00008004;
+ cmd[1] = value;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_CMD_ECHO, NULL);
+ return ret;
+}
+
+#ifdef ZM_DRV_INIT_USB_MODE
+
+#define ZM_USB_US_STREAM_MODE 0x00000000
+#define ZM_USB_US_PACKET_MODE 0x00000008
+#define ZM_USB_DS_ENABLE 0x00000001
+#define ZM_USB_US_ENABLE 0x00000002
+
+#define ZM_USB_RX_STREAM_4K 0x00000000
+#define ZM_USB_RX_STREAM_8K 0x00000010
+#define ZM_USB_RX_STREAM_16K 0x00000020
+#define ZM_USB_RX_STREAM_32K 0x00000030
+
+#define ZM_USB_TX_STREAM_MODE 0x00000040
+
+#define ZM_USB_MODE_CTRL_REG 0x001E1108
+
+void zfInitUsbMode(zdev_t* dev)
+{
+ u32_t mode;
+ zmw_get_wlan_dev(dev);
+
+ /* TODO: Set USB mode by reading registery */
+ mode = ZM_USB_DS_ENABLE | ZM_USB_US_ENABLE | ZM_USB_US_PACKET_MODE;
+
+ zfDelayWriteInternalReg(dev, ZM_USB_MODE_CTRL_REG, mode);
+ zfFlushDelayWrite(dev);
+}
+#endif
+
+void zfDumpEepBandEdges(struct ar5416Eeprom* eepromImage);
+void zfPrintTargetPower2G(u8_t* tPow2xCck, u8_t* tPow2x2g, u8_t* tPow2x2gHt20, u8_t* tPow2x2gHt40);
+void zfPrintTargetPower5G(u8_t* tPow2x5g, u8_t* tPow2x5gHt20, u8_t* tPow2x5gHt40);
+
+
+s32_t zfInterpolateFunc(s32_t x, s32_t x1, s32_t y1, s32_t x2, s32_t y2)
+{
+ s32_t y;
+
+ if (y2 == y1)
+ {
+ y = y1;
+ }
+ else if (x == x1)
+ {
+ y = y1;
+ }
+ else if (x == x2)
+ {
+ y = y2;
+ }
+ else if (x2 != x1)
+ {
+ y = y1 + (((y2-y1) * (x-x1))/(x2-x1));
+ }
+ else
+ {
+ y = y1;
+ }
+
+ return y;
+}
+
+//#define ZM_ENABLE_TPC_WINDOWS_DEBUG
+//#define ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+
+/* the tx power offset workaround for ART vs NDIS/MDK */
+#define HALTX_POWER_OFFSET 0
+
+u8_t zfInterpolateFuncX(u8_t x, u8_t x1, u8_t y1, u8_t x2, u8_t y2)
+{
+ s32_t y;
+ s32_t inc;
+
+ #define ZM_MULTIPLIER 8
+ y = zfInterpolateFunc((s32_t)x<<ZM_MULTIPLIER,
+ (s32_t)x1<<ZM_MULTIPLIER,
+ (s32_t)y1<<ZM_MULTIPLIER,
+ (s32_t)x2<<ZM_MULTIPLIER,
+ (s32_t)y2<<ZM_MULTIPLIER);
+
+ inc = (y & (1<<(ZM_MULTIPLIER-1))) >> (ZM_MULTIPLIER-1);
+ y = (y >> ZM_MULTIPLIER) + inc;
+ #undef ZM_MULTIPLIER
+
+ return (u8_t)y;
+}
+
+u8_t zfGetInterpolatedValue(u8_t x, u8_t* x_array, u8_t* y_array)
+{
+ s32_t y;
+ u16_t xIndex;
+
+ if (x <= x_array[1])
+ {
+ xIndex = 0;
+ }
+ else if (x <= x_array[2])
+ {
+ xIndex = 1;
+ }
+ else if (x <= x_array[3])
+ {
+ xIndex = 2;
+ }
+ else //(x > x_array[3])
+ {
+ xIndex = 3;
+ }
+
+ y = zfInterpolateFuncX(x,
+ x_array[xIndex],
+ y_array[xIndex],
+ x_array[xIndex+1],
+ y_array[xIndex+1]);
+
+ return (u8_t)y;
+}
+
+u8_t zfFindFreqIndex(u8_t f, u8_t* fArray, u8_t fArraySize)
+{
+ u8_t i;
+#ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("f=%d ", f);
+ for (i=0; i<fArraySize; i++)
+ {
+ DbgPrint("%d ", fArray[i]);
+ }
+ DbgPrint("\n");
+#endif
+ i=fArraySize-2;
+ while(1)
+ {
+ if (f >= fArray[i])
+ {
+ return i;
+ }
+ if (i!=0)
+ {
+ i--;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+
+
+
+
+void zfInitPowerCal(zdev_t* dev)
+{
+ //Program PHY Tx power relatives registers
+#define zm_write_phy_reg(cr, val) reg_write((cr*4)+0x9800, val)
+
+ zm_write_phy_reg(79, 0x7f);
+ zm_write_phy_reg(77, 0x3f3f3f3f);
+ zm_write_phy_reg(78, 0x3f3f3f3f);
+ zm_write_phy_reg(653, 0x3f3f3f3f);
+ zm_write_phy_reg(654, 0x3f3f3f3f);
+ zm_write_phy_reg(739, 0x3f3f3f3f);
+ zm_write_phy_reg(740, 0x3f3f3f3f);
+ zm_write_phy_reg(755, 0x3f3f3f3f);
+ zm_write_phy_reg(756, 0x3f3f3f3f);
+ zm_write_phy_reg(757, 0x3f3f3f3f);
+
+#undef zm_write_phy_reg
+}
+
+
+
+void zfPrintTp(u8_t* pwr0, u8_t* vpd0, u8_t* pwr1, u8_t* vpd1)
+{
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("pwr0 : %d, %d, %d, %d ,%d\n", pwr0[0], pwr0[1], pwr0[2], pwr0[3], pwr0[4]);
+ DbgPrint("vpd0 : %d, %d, %d, %d ,%d\n", vpd0[0], vpd0[1], vpd0[2], vpd0[3], vpd0[4]);
+ DbgPrint("pwr1 : %d, %d, %d, %d ,%d\n", pwr1[0], pwr1[1], pwr1[2], pwr1[3], pwr1[4]);
+ DbgPrint("vpd1 : %d, %d, %d, %d ,%d\n", vpd1[0], vpd1[1], vpd1[2], vpd1[3], vpd1[4]);
+ #endif
+}
+
+
+/*
+ * To find CTL index(0~23)
+ * return 24(AR5416_NUM_CTLS)=>no desired index found
+ */
+u8_t zfFindCtlEdgesIndex(zdev_t* dev, u8_t desired_CtlIndex)
+{
+ u8_t i;
+ struct zsHpPriv* hpPriv;
+ struct ar5416Eeprom* eepromImage;
+
+ zmw_get_wlan_dev(dev);
+
+ hpPriv = wd->hpPrivate;
+
+ eepromImage = (struct ar5416Eeprom*)&(hpPriv->eepromImage[(1024+512)/4]);
+
+ //for (i = 0; (i < AR5416_NUM_CTLS) && eepromImage->ctlIndex[i]; i++)
+ for (i = 0; i < AR5416_NUM_CTLS; i++)
+ {
+ if(desired_CtlIndex == eepromImage->ctlIndex[i])
+ break;
+ }
+ return i;
+}
+
+/**************************************************************************
+ * fbin2freq
+ *
+ * Get channel value from binary representation held in eeprom
+ * RETURNS: the frequency in MHz
+ */
+u32_t
+fbin2freq(u8_t fbin, u8_t is2GHz)
+{
+ /*
+ * Reserved value 0xFF provides an empty definition both as
+ * an fbin and as a frequency - do not convert
+ */
+ if (fbin == AR5416_BCHAN_UNUSED) {
+ return fbin;
+ }
+
+ return (u32_t)((is2GHz==1) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+
+u8_t zfGetMaxEdgePower(zdev_t* dev, CAL_CTL_EDGES *pCtlEdges, u32_t freq)
+{
+ u8_t i;
+ u8_t maxEdgePower;
+ u8_t is2GHz;
+ struct zsHpPriv* hpPriv;
+ struct ar5416Eeprom* eepromImage;
+
+ zmw_get_wlan_dev(dev);
+
+ hpPriv = wd->hpPrivate;
+
+ eepromImage = (struct ar5416Eeprom*)&(hpPriv->eepromImage[(1024+512)/4]);
+
+ if(freq > ZM_CH_G_14)
+ is2GHz = 0;
+ else
+ is2GHz = 1;
+
+ maxEdgePower = AR5416_MAX_RATE_POWER;
+
+ /* Get the edge power */
+ for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pCtlEdges[i].bChannel != AR5416_BCHAN_UNUSED) ; i++)
+ {
+ /*
+ * If there's an exact channel match or an inband flag set
+ * on the lower channel use the given rdEdgePower
+ */
+ if (freq == fbin2freq(pCtlEdges[i].bChannel, is2GHz))
+ {
+ maxEdgePower = pCtlEdges[i].tPower;
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("zfGetMaxEdgePower index i = %d \n", i));
+ #endif
+ break;
+ }
+ else if ((i > 0) && (freq < fbin2freq(pCtlEdges[i].bChannel, is2GHz)))
+ {
+ if (fbin2freq(pCtlEdges[i - 1].bChannel, is2GHz) < freq && pCtlEdges[i - 1].flag)
+ {
+ maxEdgePower = pCtlEdges[i - 1].tPower;
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("zfGetMaxEdgePower index i-1 = %d \n", i-1));
+ #endif
+ }
+ /* Leave loop - no more affecting edges possible in this monotonic increasing list */
+ break;
+ }
+
+ }
+
+ if( i == AR5416_NUM_BAND_EDGES )
+ {
+ if (freq > fbin2freq(pCtlEdges[i - 1].bChannel, is2GHz) && pCtlEdges[i - 1].flag)
+ {
+ maxEdgePower = pCtlEdges[i - 1].tPower;
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("zfGetMaxEdgePower index=>i-1 = %d \n", i-1));
+ #endif
+ }
+ }
+
+ zm_assert(maxEdgePower > 0);
+
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ if ( maxEdgePower == AR5416_MAX_RATE_POWER )
+ {
+ zm_dbg(("zfGetMaxEdgePower = %d !!!\n", AR5416_MAX_RATE_POWER));
+ }
+ #endif
+ return maxEdgePower;
+}
+
+u32_t zfAdjustHT40FreqOffset(zdev_t* dev, u32_t frequency, u8_t bw40, u8_t extOffset)
+{
+ u32_t newFreq = frequency;
+
+ if (bw40 == 1)
+ {
+ if (extOffset == 1)
+ {
+ newFreq += 10;
+ }
+ else
+ {
+ newFreq -= 10;
+ }
+ }
+ return newFreq;
+}
+
+u32_t zfHpCheckDoHeavyClip(zdev_t* dev, u32_t freq, CAL_CTL_EDGES *pCtlEdges, u8_t bw40)
+{
+ u32_t ret = 0;
+ u8_t i;
+ u8_t is2GHz;
+ struct zsHpPriv* hpPriv;
+
+ zmw_get_wlan_dev(dev);
+
+ hpPriv = wd->hpPrivate;
+
+ if(freq > ZM_CH_G_14)
+ is2GHz = 0;
+ else
+ is2GHz = 1;
+
+ /* HT40 force enable heavy clip */
+ if (bw40)
+ {
+ ret |= 0xf0;
+ }
+#if 1
+ /* HT20 : frequency bandedge */
+ for (i = 0; (i < AR5416_NUM_BAND_EDGES) && (pCtlEdges[i].bChannel != AR5416_BCHAN_UNUSED) ; i++)
+ {
+ if (freq == fbin2freq(pCtlEdges[i].bChannel, is2GHz))
+ {
+ if (pCtlEdges[i].flag == 0)
+ {
+ ret |= 0xf;
+ }
+ break;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+
+void zfSetPowerCalTable(zdev_t* dev, u32_t frequency, u8_t bw40, u8_t extOffset)
+{
+ struct ar5416Eeprom* eepromImage;
+ u8_t pwr0[5];
+ u8_t pwr1[5];
+ u8_t vpd0[5];
+ u8_t vpd1[5];
+ u8_t vpd_chain1[128];
+ u8_t vpd_chain3[128];
+ u16_t boundary1 = 18; //CR 667
+ u16_t powerTxMax = 63; //CR 79
+ u8_t i;
+ struct zsHpPriv* hpPriv;
+ u8_t fbin;
+ u8_t index, max2gIndex, max5gIndex;
+ u8_t chain0pwrPdg0[5];
+ u8_t chain0vpdPdg0[5];
+ u8_t chain0pwrPdg1[5];
+ u8_t chain0vpdPdg1[5];
+ u8_t chain2pwrPdg0[5];
+ u8_t chain2vpdPdg0[5];
+ u8_t chain2pwrPdg1[5];
+ u8_t chain2vpdPdg1[5];
+ u8_t fbinArray[8];
+
+ /* 4 CTL */
+ u8_t ctl_i;
+ u8_t desired_CtlIndex;
+
+ u8_t ctlEdgesMaxPowerCCK = AR5416_MAX_RATE_POWER;
+ u8_t ctlEdgesMaxPower2G = AR5416_MAX_RATE_POWER;
+ u8_t ctlEdgesMaxPower2GHT20 = AR5416_MAX_RATE_POWER;
+ u8_t ctlEdgesMaxPower2GHT40 = AR5416_MAX_RATE_POWER;
+ u8_t ctlEdgesMaxPower5G = AR5416_MAX_RATE_POWER;
+ u8_t ctlEdgesMaxPower5GHT20 = AR5416_MAX_RATE_POWER;
+ u8_t ctlEdgesMaxPower5GHT40 = AR5416_MAX_RATE_POWER;
+
+ u8_t ctlOffset;
+
+ zmw_get_wlan_dev(dev);
+
+ hpPriv = wd->hpPrivate;
+
+ eepromImage = (struct ar5416Eeprom*)&(hpPriv->eepromImage[(1024+512)/4]);
+
+ // Check the total bytes of the EEPROM structure to see the dongle have been calibrated or not.
+ if (eepromImage->baseEepHeader.length == 0xffff)
+ {
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("Warning! This dongle not been calibrated\n"));
+ #endif
+ return;
+ }
+
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("-----zfSetPowerCalTable : frequency=%d-----\n", frequency);
+ #endif
+ /* TODO : 1. boundary1 and powerTxMax should be refered to CR667 and CR79 */
+ /* in otus.ini file */
+
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ /* 2. Interpolate pwr and vpd test points from frequency */
+ DbgPrint("calFreqPier5G : %d, %d, %d, %d ,%d, %d, %d, %d\n",
+ eepromImage->calFreqPier5G[0]*5+4800,
+ eepromImage->calFreqPier5G[1]*5+4800,
+ eepromImage->calFreqPier5G[2]*5+4800,
+ eepromImage->calFreqPier5G[3]*5+4800,
+ eepromImage->calFreqPier5G[4]*5+4800,
+ eepromImage->calFreqPier5G[5]*5+4800,
+ eepromImage->calFreqPier5G[6]*5+4800,
+ eepromImage->calFreqPier5G[7]*5+4800
+ );
+ DbgPrint("calFreqPier2G : %d, %d, %d, %d\n",
+ eepromImage->calFreqPier2G[0]+2300,
+ eepromImage->calFreqPier2G[1]+2300,
+ eepromImage->calFreqPier2G[2]+2300,
+ eepromImage->calFreqPier2G[3]+2300
+ );
+ #endif
+ if (frequency < 3000)
+ {
+ for (i=0; i<4; i++)
+ {
+ if (eepromImage->calFreqPier2G[i] == 0xff)
+ {
+ break;
+ }
+ }
+ max2gIndex = i;
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("max2gIndex : %d\n", max2gIndex);
+ #endif
+ fbin = (u8_t)(frequency - 2300);
+ index = zfFindFreqIndex(fbin, eepromImage->calFreqPier2G, max2gIndex);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("2G index : %d\n", index);
+ DbgPrint("chain 0 index\n");
+ #endif
+ zfPrintTp(&eepromImage->calPierData2G[0][index].pwrPdg[0][0],
+ &eepromImage->calPierData2G[0][index].vpdPdg[0][0],
+ &eepromImage->calPierData2G[0][index].pwrPdg[1][0],
+ &eepromImage->calPierData2G[0][index].vpdPdg[1][0]
+ );
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("chain 0 index+1\n");
+ #endif
+ zfPrintTp(&eepromImage->calPierData2G[0][index+1].pwrPdg[0][0],
+ &eepromImage->calPierData2G[0][index+1].vpdPdg[0][0],
+ &eepromImage->calPierData2G[0][index+1].pwrPdg[1][0],
+ &eepromImage->calPierData2G[0][index+1].vpdPdg[1][0]
+ );
+
+ for (i=0; i<5; i++)
+ {
+ chain0pwrPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[0][index].pwrPdg[0][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[0][index+1].pwrPdg[0][i]
+ );
+ chain0vpdPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[0][index].vpdPdg[0][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[0][index+1].vpdPdg[0][i]
+ );
+ chain0pwrPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[0][index].pwrPdg[1][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[0][index+1].pwrPdg[1][i]
+ );
+ chain0vpdPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[0][index].vpdPdg[1][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[0][index+1].vpdPdg[1][i]
+ );
+
+ chain2pwrPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[1][index].pwrPdg[0][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[1][index+1].pwrPdg[0][i]
+ );
+ chain2vpdPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[1][index].vpdPdg[0][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[1][index+1].vpdPdg[0][i]
+ );
+ chain2pwrPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[1][index].pwrPdg[1][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[1][index+1].pwrPdg[1][i]
+ );
+ chain2vpdPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier2G[index],
+ eepromImage->calPierData2G[1][index].vpdPdg[1][i],
+ eepromImage->calFreqPier2G[index+1],
+ eepromImage->calPierData2G[1][index+1].vpdPdg[1][i]
+ );
+ }
+ }
+ else
+ {
+ for (i=0; i<8; i++)
+ {
+ if (eepromImage->calFreqPier5G[i] == 0xff)
+ {
+ break;
+ }
+ }
+ max5gIndex = i;
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("max5gIndex : %d\n", max5gIndex);
+ #endif
+ fbin = (u8_t)((frequency - 4800)/5);
+ index = zfFindFreqIndex(fbin, eepromImage->calFreqPier5G, max5gIndex);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("5G index : %d\n", index);
+ #endif
+
+ for (i=0; i<5; i++)
+ {
+ chain0pwrPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[0][index].pwrPdg[0][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[0][index+1].pwrPdg[0][i]
+ );
+ chain0vpdPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[0][index].vpdPdg[0][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[0][index+1].vpdPdg[0][i]
+ );
+ chain0pwrPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[0][index].pwrPdg[1][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[0][index+1].pwrPdg[1][i]
+ );
+ chain0vpdPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[0][index].vpdPdg[1][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[0][index+1].vpdPdg[1][i]
+ );
+
+ chain2pwrPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[1][index].pwrPdg[0][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[1][index+1].pwrPdg[0][i]
+ );
+ chain2vpdPdg0[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[1][index].vpdPdg[0][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[1][index+1].vpdPdg[0][i]
+ );
+ chain2pwrPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[1][index].pwrPdg[1][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[1][index+1].pwrPdg[1][i]
+ );
+ chain2vpdPdg1[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calFreqPier5G[index],
+ eepromImage->calPierData5G[1][index].vpdPdg[1][i],
+ eepromImage->calFreqPier5G[index+1],
+ eepromImage->calPierData5G[1][index+1].vpdPdg[1][i]
+ );
+ }
+
+ }
+
+
+ /* Chain 1 */
+ /* Get pwr and vpd test points from frequency */
+ for (i=0; i<5; i++)
+ {
+ pwr0[i] = chain0pwrPdg0[i]>>1;
+ vpd0[i] = chain0vpdPdg0[i];
+ pwr1[i] = chain0pwrPdg1[i]>>1;
+ vpd1[i] = chain0vpdPdg1[i];
+ }
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("Test Points\n");
+ DbgPrint("pwr0 : %d, %d, %d, %d ,%d\n", pwr0[0], pwr0[1], pwr0[2], pwr0[3], pwr0[4]);
+ DbgPrint("vpd0 : %d, %d, %d, %d ,%d\n", vpd0[0], vpd0[1], vpd0[2], vpd0[3], vpd0[4]);
+ DbgPrint("pwr1 : %d, %d, %d, %d ,%d\n", pwr1[0], pwr1[1], pwr1[2], pwr1[3], pwr1[4]);
+ DbgPrint("vpd1 : %d, %d, %d, %d ,%d\n", vpd1[0], vpd1[1], vpd1[2], vpd1[3], vpd1[4]);
+ #endif
+ /* Generate the vpd arrays */
+ for (i=0; i<boundary1+1+6; i++)
+ {
+ vpd_chain1[i] = zfGetInterpolatedValue(i, &pwr0[0], &vpd0[0]);
+ }
+ for (; i<powerTxMax+1+6+6; i++)
+ {
+ vpd_chain1[i] = zfGetInterpolatedValue(i-6-6, &pwr1[0], &vpd1[0]);
+ }
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("vpd_chain1\n");
+ for (i=0; i<powerTxMax+1+6+6; i+=10)
+ {
+ DbgPrint("%d, %d, %d, %d ,%d, %d, %d, %d, %d, %d\n",
+ vpd_chain1[i+0], vpd_chain1[i+1], vpd_chain1[i+2], vpd_chain1[i+3], vpd_chain1[i+4],
+ vpd_chain1[i+5], vpd_chain1[i+6], vpd_chain1[i+7], vpd_chain1[i+8], vpd_chain1[i+9]);
+ }
+ #endif
+ /* Write PHY regs 672-703 */
+ for (i=0; i<128; i+=4)
+ {
+ u32_t regAddr = 0x9800 + (672 * 4);
+ u32_t val;
+
+ val = ((u32_t)vpd_chain1[i+3]<<24) |
+ ((u32_t)vpd_chain1[i+2]<<16) |
+ ((u32_t)vpd_chain1[i+1]<<8) |
+ ((u32_t)vpd_chain1[i]);
+
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ reg_write(regAddr + i, val); /* CR672 */
+ #endif
+ }
+
+ /* Chain 2 */
+ /* Get pwr and vpd test points from frequency */
+ for (i=0; i<5; i++)
+ {
+ pwr0[i] = chain2pwrPdg0[i]>>1;
+ vpd0[i] = chain2vpdPdg0[i];
+ pwr1[i] = chain2pwrPdg1[i]>>1;
+ vpd1[i] = chain2vpdPdg1[i];
+ }
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("Test Points\n");
+ DbgPrint("pwr0 : %d, %d, %d, %d ,%d\n", pwr0[0], pwr0[1], pwr0[2], pwr0[3], pwr0[4]);
+ DbgPrint("vpd0 : %d, %d, %d, %d ,%d\n", vpd0[0], vpd0[1], vpd0[2], vpd0[3], vpd0[4]);
+ DbgPrint("pwr1 : %d, %d, %d, %d ,%d\n", pwr1[0], pwr1[1], pwr1[2], pwr1[3], pwr1[4]);
+ DbgPrint("vpd1 : %d, %d, %d, %d ,%d\n", vpd1[0], vpd1[1], vpd1[2], vpd1[3], vpd1[4]);
+ #endif
+ /* Generate the vpd arrays */
+ for (i=0; i<boundary1+1+6; i++)
+ {
+ vpd_chain3[i] = zfGetInterpolatedValue(i, &pwr0[0], &vpd0[0]);
+ }
+ for (; i<powerTxMax+1+6+6; i++)
+ {
+ vpd_chain3[i] = zfGetInterpolatedValue(i-6-6, &pwr1[0], &vpd1[0]);
+ }
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("vpd_chain3\n");
+ for (i=0; i<powerTxMax+1+6+6; i+=10)
+ {
+ DbgPrint("%d, %d, %d, %d ,%d, %d, %d, %d, %d, %d\n",
+ vpd_chain3[i+0], vpd_chain3[i+1], vpd_chain3[i+2], vpd_chain3[i+3], vpd_chain3[i+4],
+ vpd_chain3[i+5], vpd_chain3[i+6], vpd_chain3[i+7], vpd_chain3[i+8], vpd_chain3[i+9]);
+ }
+ #endif
+
+ /* Write PHY regs 672-703 + 0x1000 */
+ for (i=0; i<128; i+=4)
+ {
+ u32_t regAddr = 0x9800 + (672 * 4) + 0x1000;
+ u32_t val;
+
+ val = ((u32_t)vpd_chain3[i+3]<<24) |
+ ((u32_t)vpd_chain3[i+2]<<16) |
+ ((u32_t)vpd_chain3[i+1]<<8) |
+ ((u32_t)vpd_chain3[i]);
+
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ reg_write(regAddr + i, val); /* CR672 */
+ #endif
+ }
+
+ zfFlushDelayWrite(dev);
+
+ /* 3. Generate target power table */
+ if (frequency < 3000)
+ {
+ for (i=0; i<3; i++)
+ {
+ if (eepromImage->calTargetPowerCck[i].bChannel != 0xff)
+ {
+ fbinArray[i] = eepromImage->calTargetPowerCck[i].bChannel;
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ index = zfFindFreqIndex(fbin, fbinArray, i);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("CCK index=%d\n", index);
+ #endif
+ for (i=0; i<4; i++)
+ {
+ hpPriv->tPow2xCck[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calTargetPowerCck[index].bChannel,
+ eepromImage->calTargetPowerCck[index].tPow2x[i],
+ eepromImage->calTargetPowerCck[index+1].bChannel,
+ eepromImage->calTargetPowerCck[index+1].tPow2x[i]
+ );
+ }
+
+ for (i=0; i<4; i++)
+ {
+ if (eepromImage->calTargetPower2G[i].bChannel != 0xff)
+ {
+ fbinArray[i] = eepromImage->calTargetPower2G[i].bChannel;
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ index = zfFindFreqIndex(fbin, fbinArray, i);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("2G index=%d\n", index);
+ #endif
+ for (i=0; i<4; i++)
+ {
+ hpPriv->tPow2x2g[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calTargetPower2G[index].bChannel,
+ eepromImage->calTargetPower2G[index].tPow2x[i],
+ eepromImage->calTargetPower2G[index+1].bChannel,
+ eepromImage->calTargetPower2G[index+1].tPow2x[i]
+ );
+ }
+
+ for (i=0; i<4; i++)
+ {
+ if (eepromImage->calTargetPower2GHT20[i].bChannel != 0xff)
+ {
+ fbinArray[i] = eepromImage->calTargetPower2GHT20[i].bChannel;
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ index = zfFindFreqIndex(fbin, fbinArray, i);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("2G HT20 index=%d\n", index);
+ #endif
+ for (i=0; i<8; i++)
+ {
+ hpPriv->tPow2x2gHt20[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calTargetPower2GHT20[index].bChannel,
+ eepromImage->calTargetPower2GHT20[index].tPow2x[i],
+ eepromImage->calTargetPower2GHT20[index+1].bChannel,
+ eepromImage->calTargetPower2GHT20[index+1].tPow2x[i]
+ );
+ }
+
+ for (i=0; i<4; i++)
+ {
+ if (eepromImage->calTargetPower2GHT40[i].bChannel != 0xff)
+ {
+ fbinArray[i] = eepromImage->calTargetPower2GHT40[i].bChannel;
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ index = zfFindFreqIndex( (u8_t)zfAdjustHT40FreqOffset(dev, fbin, bw40, extOffset), fbinArray, i);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("2G HT40 index=%d\n", index);
+ #endif
+ for (i=0; i<8; i++)
+ {
+ hpPriv->tPow2x2gHt40[i] = zfInterpolateFuncX(
+ (u8_t)zfAdjustHT40FreqOffset(dev, fbin, bw40, extOffset),
+ eepromImage->calTargetPower2GHT40[index].bChannel,
+ eepromImage->calTargetPower2GHT40[index].tPow2x[i],
+ eepromImage->calTargetPower2GHT40[index+1].bChannel,
+ eepromImage->calTargetPower2GHT40[index+1].tPow2x[i]
+ );
+ }
+
+ zfPrintTargetPower2G(hpPriv->tPow2xCck,
+ hpPriv->tPow2x2g,
+ hpPriv->tPow2x2gHt20,
+ hpPriv->tPow2x2gHt40);
+ }
+ else
+ {
+ /* 5G */
+ for (i=0; i<8; i++)
+ {
+ if (eepromImage->calTargetPower5G[i].bChannel != 0xff)
+ {
+ fbinArray[i] = eepromImage->calTargetPower5G[i].bChannel;
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ index = zfFindFreqIndex(fbin, fbinArray, i);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("5G index=%d\n", index);
+ #endif
+ for (i=0; i<4; i++)
+ {
+ hpPriv->tPow2x5g[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calTargetPower5G[index].bChannel,
+ eepromImage->calTargetPower5G[index].tPow2x[i],
+ eepromImage->calTargetPower5G[index+1].bChannel,
+ eepromImage->calTargetPower5G[index+1].tPow2x[i]
+ );
+ }
+
+ for (i=0; i<8; i++)
+ {
+ if (eepromImage->calTargetPower5GHT20[i].bChannel != 0xff)
+ {
+ fbinArray[i] = eepromImage->calTargetPower5GHT20[i].bChannel;
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ index = zfFindFreqIndex(fbin, fbinArray, i);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("5G HT20 index=%d\n", index);
+ #endif
+ for (i=0; i<8; i++)
+ {
+ hpPriv->tPow2x5gHt20[i] = zfInterpolateFuncX(fbin,
+ eepromImage->calTargetPower5GHT20[index].bChannel,
+ eepromImage->calTargetPower5GHT20[index].tPow2x[i],
+ eepromImage->calTargetPower5GHT20[index+1].bChannel,
+ eepromImage->calTargetPower5GHT20[index+1].tPow2x[i]
+ );
+ }
+
+ for (i=0; i<8; i++)
+ {
+ if (eepromImage->calTargetPower5GHT40[i].bChannel != 0xff)
+ {
+ fbinArray[i] = eepromImage->calTargetPower5GHT40[i].bChannel;
+ }
+ else
+ {
+ break;
+ }
+
+ }
+ index = zfFindFreqIndex((u8_t)zfAdjustHT40FreqOffset(dev, fbin, bw40, extOffset), fbinArray, i);
+ #ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ DbgPrint("5G HT40 index=%d\n", index);
+ #endif
+ for (i=0; i<8; i++)
+ {
+ hpPriv->tPow2x5gHt40[i] = zfInterpolateFuncX(
+ (u8_t)zfAdjustHT40FreqOffset(dev, fbin, bw40, extOffset),
+ eepromImage->calTargetPower5GHT40[index].bChannel,
+ eepromImage->calTargetPower5GHT40[index].tPow2x[i],
+ eepromImage->calTargetPower5GHT40[index+1].bChannel,
+ eepromImage->calTargetPower5GHT40[index+1].tPow2x[i]
+ );
+ }
+
+ zfPrintTargetPower5G(
+ hpPriv->tPow2x5g,
+ hpPriv->tPow2x5gHt20,
+ hpPriv->tPow2x5gHt40);
+ }
+
+
+
+ /* 4. CTL */
+ /*
+ * 4.1 Get the bandedges tx power by frequency
+ * 2.4G we get ctlEdgesMaxPowerCCK
+ * ctlEdgesMaxPower2G
+ * ctlEdgesMaxPower2GHT20
+ * ctlEdgesMaxPower2GHT40
+ * 5G we get ctlEdgesMaxPower5G
+ * ctlEdgesMaxPower5GHT20
+ * ctlEdgesMaxPower5GHT40
+ * 4.2 Update (3.) target power table by 4.1
+ * 4.3 Tx power offset for ART - NDIS/MDK
+ * 4.4 Write MAC reg 0x694 for ACK's TPC
+ *
+ */
+
+ //zfDumpEepBandEdges(eepromImage);
+
+ /* get the cfg from Eeprom: regionCode => RegulatoryDomain : 0x10-FFC 0x30-eu 0x40-jap */
+ desired_CtlIndex = zfHpGetRegulatoryDomain(dev);
+ if ((desired_CtlIndex == 0x30) || (desired_CtlIndex == 0x40) || (desired_CtlIndex == 0x0))
+ {
+ /* skip CTL and heavy clip */
+ hpPriv->enableBBHeavyClip = 0;
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("RegulatoryDomain = 0, skip CTL and heavy clip\n"));
+ #endif
+ }
+ else
+ {
+ hpPriv->enableBBHeavyClip = 1;
+
+ if (desired_CtlIndex == 0xff)
+ {
+ /* desired index not found */
+ desired_CtlIndex = 0x10;
+ }
+
+ /* first part : 2.4G */
+ if (frequency <= ZM_CH_G_14)
+ {
+ /* 2.4G - CTL_11B */
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_11B);
+ if(ctl_i<AR5416_NUM_CTLS)
+ {
+ ctlEdgesMaxPowerCCK = zfGetMaxEdgePower(dev, eepromImage->ctlData[ctl_i].ctlEdges[1], frequency);
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("CTL_11B ctl_i = %d\n", ctl_i));
+ #endif
+
+ /* 2.4G - CTL_11G */
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_11G);
+ if(ctl_i<AR5416_NUM_CTLS)
+ {
+ ctlEdgesMaxPower2G = zfGetMaxEdgePower(dev, eepromImage->ctlData[ctl_i].ctlEdges[1], frequency);
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("CTL_11G ctl_i = %d\n", ctl_i));
+ #endif
+
+ /* 2.4G - CTL_2GHT20 */
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_2GHT20);
+ if(ctl_i<AR5416_NUM_CTLS)
+ {
+ ctlEdgesMaxPower2GHT20 = zfGetMaxEdgePower(dev, eepromImage->ctlData[ctl_i].ctlEdges[1], frequency);
+ }
+ else
+ {
+ /* workaround for no data in Eeprom, replace by normal 2G */
+ ctlEdgesMaxPower2GHT20 = ctlEdgesMaxPower2G;
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("CTL_2GHT20 ctl_i = %d\n", ctl_i));
+ #endif
+
+ /* 2.4G - CTL_2GHT40 */
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_2GHT40);
+ if(ctl_i<AR5416_NUM_CTLS)
+ {
+ ctlEdgesMaxPower2GHT40 = zfGetMaxEdgePower(dev, eepromImage->ctlData[ctl_i].ctlEdges[1],
+ zfAdjustHT40FreqOffset(dev, frequency, bw40, extOffset));
+ }
+ else
+ {
+ /* workaround for no data in Eeprom, replace by normal 2G */
+ ctlEdgesMaxPower2GHT40 = ctlEdgesMaxPower2G;
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("CTL_2GHT40 ctl_i = %d\n", ctl_i));
+ #endif
+
+
+ /* 7a17 : */
+ /* Max power (dBm) for channel range when using DFS define by madwifi*/
+ for (i=0; i<wd->regulationTable.allowChannelCnt; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel == frequency)
+ {
+ if (zfHpIsDfsChannel(dev, (u16_t)frequency))
+ {
+ zm_debug_msg1("frequency use DFS -- ", frequency);
+ ctlEdgesMaxPowerCCK = zm_min(ctlEdgesMaxPowerCCK, wd->regulationTable.allowChannel[i].maxRegTxPower*2);
+ ctlEdgesMaxPower2G = zm_min(ctlEdgesMaxPower2G, wd->regulationTable.allowChannel[i].maxRegTxPower*2);
+ ctlEdgesMaxPower2GHT20 = zm_min(ctlEdgesMaxPower2GHT20, wd->regulationTable.allowChannel[i].maxRegTxPower*2);
+ ctlEdgesMaxPower2GHT40 = zm_min(ctlEdgesMaxPower2GHT40, wd->regulationTable.allowChannel[i].maxRegTxPower*2);
+ }
+ break;
+ }
+ }
+
+ /* Apply ctl mode to correct target power set */
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_debug_msg1("ctlEdgesMaxPowerCCK = ", ctlEdgesMaxPowerCCK);
+ zm_debug_msg1("ctlEdgesMaxPower2G = ", ctlEdgesMaxPower2G);
+ zm_debug_msg1("ctlEdgesMaxPower2GHT20 = ", ctlEdgesMaxPower2GHT20);
+ zm_debug_msg1("ctlEdgesMaxPower2GHT40 = ", ctlEdgesMaxPower2GHT40);
+ #endif
+ for (i=0; i<4; i++)
+ {
+ hpPriv->tPow2xCck[i] = zm_min(hpPriv->tPow2xCck[i], ctlEdgesMaxPowerCCK) + HALTX_POWER_OFFSET;
+ }
+ hpPriv->tPow2x2g24HeavyClipOffset = 0;
+ if (hpPriv->enableBBHeavyClip)
+ {
+ ctlOffset = 2;
+ }
+ else
+ {
+ ctlOffset = 0;
+ }
+ for (i=0; i<4; i++)
+ {
+ if (((frequency == 2412) || (frequency == 2462)))
+ {
+ if (i != 0)
+ {
+ hpPriv->tPow2x2g[i] = zm_min(hpPriv->tPow2x2g[i], ctlEdgesMaxPower2G-ctlOffset) + HALTX_POWER_OFFSET;
+ }
+ else
+ {
+ hpPriv->tPow2x2g[i] = zm_min(hpPriv->tPow2x2g[i], ctlEdgesMaxPower2G) + HALTX_POWER_OFFSET;
+ if (hpPriv->tPow2x2g[i] > (ctlEdgesMaxPower2G-ctlOffset))
+ {
+ hpPriv->tPow2x2g24HeavyClipOffset = hpPriv->tPow2x2g[i] - (ctlEdgesMaxPower2G-ctlOffset);
+ }
+ }
+ }
+ else
+ {
+ hpPriv->tPow2x2g[i] = zm_min(hpPriv->tPow2x2g[i], ctlEdgesMaxPower2G) + HALTX_POWER_OFFSET;
+ }
+ }
+ for (i=0; i<8; i++)
+ {
+ if (((frequency == 2412) || (frequency == 2462)) && (i>=3))
+ {
+ hpPriv->tPow2x2gHt20[i] = zm_min(hpPriv->tPow2x2gHt20[i], ctlEdgesMaxPower2GHT20-ctlOffset) + HALTX_POWER_OFFSET;
+ }
+ else
+ {
+ hpPriv->tPow2x2gHt20[i] = zm_min(hpPriv->tPow2x2gHt20[i], ctlEdgesMaxPower2GHT20) + HALTX_POWER_OFFSET;
+ }
+ }
+ for (i=0; i<8; i++)
+ {
+ if ((frequency == 2412) && (i>=3))
+ {
+ hpPriv->tPow2x2gHt40[i] = zm_min(hpPriv->tPow2x2gHt40[i], ctlEdgesMaxPower2GHT40-ctlOffset) + HALTX_POWER_OFFSET;
+ }
+ else if ((frequency == 2462) && (i>=3))
+ {
+ hpPriv->tPow2x2gHt40[i] = zm_min(hpPriv->tPow2x2gHt40[i], ctlEdgesMaxPower2GHT40-(ctlOffset*2)) + HALTX_POWER_OFFSET;
+ }
+ else
+ {
+ hpPriv->tPow2x2gHt40[i] = zm_min(hpPriv->tPow2x2gHt40[i], ctlEdgesMaxPower2GHT40) + HALTX_POWER_OFFSET;
+ }
+ }
+ }
+ else
+ {
+ /* 5G - CTL_11A */
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_11A);
+ if(ctl_i<AR5416_NUM_CTLS)
+ {
+ ctlEdgesMaxPower5G = zfGetMaxEdgePower(dev, eepromImage->ctlData[ctl_i].ctlEdges[1], frequency);
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("CTL_11A ctl_i = %d\n", ctl_i));
+ #endif
+
+ /* 5G - CTL_5GHT20 */
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_5GHT20);
+ if(ctl_i<AR5416_NUM_CTLS)
+ {
+ ctlEdgesMaxPower5GHT20 = zfGetMaxEdgePower(dev, eepromImage->ctlData[ctl_i].ctlEdges[1], frequency);
+ }
+ else
+ {
+ /* workaround for no data in Eeprom, replace by normal 5G */
+ ctlEdgesMaxPower5GHT20 = ctlEdgesMaxPower5G;
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("CTL_5GHT20 ctl_i = %d\n", ctl_i));
+ #endif
+
+ /* 5G - CTL_5GHT40 */
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_5GHT40);
+ if(ctl_i<AR5416_NUM_CTLS)
+ {
+ ctlEdgesMaxPower5GHT40 = zfGetMaxEdgePower(dev, eepromImage->ctlData[ctl_i].ctlEdges[1],
+ zfAdjustHT40FreqOffset(dev, frequency, bw40, extOffset));
+ }
+ else
+ {
+ /* workaround for no data in Eeprom, replace by normal 5G */
+ ctlEdgesMaxPower5GHT40 = ctlEdgesMaxPower5G;
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("CTL_5GHT40 ctl_i = %d\n", ctl_i));
+ #endif
+
+ /* 7a17 : */
+ /* Max power (dBm) for channel range when using DFS define by madwifi*/
+ for (i=0; i<wd->regulationTable.allowChannelCnt; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel == frequency)
+ {
+ if (zfHpIsDfsChannel(dev, (u16_t)frequency))
+ {
+ zm_debug_msg1("frequency use DFS -- ", frequency);
+ ctlEdgesMaxPower5G = zm_min(ctlEdgesMaxPower5G, wd->regulationTable.allowChannel[i].maxRegTxPower*2);
+ ctlEdgesMaxPower5GHT20 = zm_min(ctlEdgesMaxPower5GHT20, wd->regulationTable.allowChannel[i].maxRegTxPower*2);
+ ctlEdgesMaxPower5GHT40 = zm_min(ctlEdgesMaxPower5GHT40, wd->regulationTable.allowChannel[i].maxRegTxPower*2);
+ }
+ break;
+ }
+ }
+
+
+ /* Apply ctl mode to correct target power set */
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_debug_msg1("ctlEdgesMaxPower5G = ", ctlEdgesMaxPower5G);
+ zm_debug_msg1("ctlEdgesMaxPower5GHT20 = ", ctlEdgesMaxPower5GHT20);
+ zm_debug_msg1("ctlEdgesMaxPower5GHT40 = ", ctlEdgesMaxPower5GHT40);
+ #endif
+ for (i=0; i<4; i++)
+ {
+ hpPriv->tPow2x5g[i] = zm_min(hpPriv->tPow2x5g[i], ctlEdgesMaxPower5G) + HALTX_POWER_OFFSET;
+ }
+ for (i=0; i<8; i++)
+ {
+ hpPriv->tPow2x5gHt20[i] = zm_min(hpPriv->tPow2x5gHt20[i], ctlEdgesMaxPower5GHT20) + HALTX_POWER_OFFSET;
+ }
+ for (i=0; i<8; i++)
+ {
+ hpPriv->tPow2x5gHt40[i] = zm_min(hpPriv->tPow2x5gHt40[i], ctlEdgesMaxPower5GHT40) + HALTX_POWER_OFFSET;
+ }
+
+ }/* end of bandedges of 5G */
+ }/* end of if ((desired_CtlIndex = zfHpGetRegulatoryDomain(dev)) == 0) */
+
+ /* workaround */
+ /* 5. BB heavy clip */
+ /* only 2.4G do heavy clip */
+ if (hpPriv->enableBBHeavyClip && hpPriv->hwBBHeavyClip && (frequency <= ZM_CH_G_14))
+ {
+ if (frequency <= ZM_CH_G_14)
+ {
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_11G);
+ }
+ else
+ {
+ ctl_i = zfFindCtlEdgesIndex(dev, desired_CtlIndex|CTL_11A);
+ }
+
+ hpPriv->setValueHeavyClip = zfHpCheckDoHeavyClip(dev, frequency, eepromImage->ctlData[ctl_i].ctlEdges[1], bw40);
+
+ if (hpPriv->setValueHeavyClip)
+ {
+ hpPriv->doBBHeavyClip = 1;
+ }
+ else
+ {
+ hpPriv->doBBHeavyClip = 0;
+ }
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ zm_dbg(("zfHpCheckDoHeavyClip ret = %02x, doBBHeavyClip = %d\n",
+ hpPriv->setValueHeavyClip, hpPriv->doBBHeavyClip));
+ #endif
+
+ if (hpPriv->doBBHeavyClip)
+ {
+ if (hpPriv->setValueHeavyClip & 0xf0)
+ {
+ hpPriv->tPow2x2gHt40[0] -= 1;
+ hpPriv->tPow2x2gHt40[1] -= 1;
+ hpPriv->tPow2x2gHt40[2] -= 1;
+ }
+
+ if (hpPriv->setValueHeavyClip & 0xf)
+ {
+ hpPriv->tPow2x2gHt20[0] += 1;
+ hpPriv->tPow2x2gHt20[1] += 1;
+ hpPriv->tPow2x2gHt20[2] += 1;
+ }
+ }
+ }
+ else
+ {
+ hpPriv->doBBHeavyClip = 0;
+ hpPriv->setValueHeavyClip = 0;
+ }
+
+ /* Final : write MAC register for some ctrl frame Tx power */
+ /* first part : 2.4G */
+ if (frequency <= ZM_CH_G_14)
+ {
+ /* Write MAC reg 0x694 for ACK's TPC */
+ /* Write MAC reg 0xbb4 RTS and SF-CTS frame power control */
+ /* Always use two stream for low legacy rate */
+ #if 0
+ //if (hpPriv->halCapability & ZM_HP_CAP_11N_ONE_TX_STREAM)
+ //{
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((hpPriv->tPow2x2g[0]&0x3f) << 20) | (0x1<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((hpPriv->tPow2x2g[0]&0x3f) << 5 ) | (0x1<<11) |
+ ((hpPriv->tPow2x2g[0]&0x3f) << 21) | (0x1<<27) );
+ //}
+ #endif
+ #if 1
+ //else
+ {
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((hpPriv->tPow2x2g[0]&0x3f) << 20) | (0x5<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((hpPriv->tPow2x2g[0]&0x3f) << 5 ) | (0x5<<11) |
+ ((hpPriv->tPow2x2g[0]&0x3f) << 21) | (0x5<<27) );
+ #endif
+ hpPriv->currentAckRtsTpc = hpPriv->tPow2x2g[0];
+ }
+ #endif
+ zfFlushDelayWrite(dev);
+
+ zfPrintTargetPower2G(hpPriv->tPow2xCck,
+ hpPriv->tPow2x2g,
+ hpPriv->tPow2x2gHt20,
+ hpPriv->tPow2x2gHt40);
+ }
+ else
+ {
+ /* Write MAC reg 0x694 for ACK's TPC */
+ /* Write MAC reg 0xbb4 RTS and SF-CTS frame power control */
+ /* Always use two stream for low legacy rate */
+ if (hpPriv->halCapability & ZM_HP_CAP_11N_ONE_TX_STREAM)
+ {
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((hpPriv->tPow2x5g[0]&0x3f) << 20) | (0x1<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((hpPriv->tPow2x5g[0]&0x3f) << 5 ) | (0x1<<11) |
+ ((hpPriv->tPow2x5g[0]&0x3f) << 21) | (0x1<<27) );
+ #endif
+ }
+ else
+ {
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((hpPriv->tPow2x5g[0]&0x3f) << 20) | (0x5<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((hpPriv->tPow2x5g[0]&0x3f) << 5 ) | (0x5<<11) |
+ ((hpPriv->tPow2x5g[0]&0x3f) << 21) | (0x5<<27) );
+ #endif
+ hpPriv->currentAckRtsTpc = hpPriv->tPow2x2g[0];
+ }
+
+
+ zfFlushDelayWrite(dev);
+
+ zfPrintTargetPower5G(
+ hpPriv->tPow2x5g,
+ hpPriv->tPow2x5gHt20,
+ hpPriv->tPow2x5gHt40);
+ }/* end of bandedges of 5G */
+
+}
+
+void zfDumpEepBandEdges(struct ar5416Eeprom* eepromImage)
+{
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ u8_t i, j, k;
+
+#if 0
+ zm_dbg(("\n === BandEdges index dump ==== \n"));
+
+ for (i = 0; i < AR5416_NUM_CTLS; i++)
+ {
+ zm_dbg(("%02x ", eepromImage->ctlIndex[i]));
+ }
+
+ zm_dbg(("\n === BandEdges data dump ==== \n"));
+
+ for (i = 0; i < AR5416_NUM_CTLS; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ for(k = 0; k < AR5416_NUM_BAND_EDGES; k++)
+ {
+ u8_t *pdata = (u8_t*)&(eepromImage->ctlData[i].ctlEdges[j][k]);
+ zm_dbg(("(%02x %02x)", pdata[0], pdata[1]));
+ }
+ zm_dbg(("\n"));
+ }
+ }
+#else
+ zm_dbg(("\n === BandEdges index dump ==== \n"));
+ for (i = 0; i < 24; i+=8)
+ {
+ zm_dbg(("%02x %02x %02x %02x %02x %02x %02x %02x",
+ eepromImage->ctlIndex[i+0], eepromImage->ctlIndex[i+1], eepromImage->ctlIndex[i+2], eepromImage->ctlIndex[i+3],
+ eepromImage->ctlIndex[i+4], eepromImage->ctlIndex[i+5], eepromImage->ctlIndex[i+6], eepromImage->ctlIndex[i+7]
+ ));
+ }
+
+ zm_dbg(("\n === BandEdges data dump ==== \n"));
+
+ for (i = 0; i < AR5416_NUM_CTLS; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ u8_t *pdata = (u8_t*)&(eepromImage->ctlData[i].ctlEdges[j]);
+ zm_dbg(("(%03d %02x) (%03d %02x) (%03d %02x) (%03d %02x) \n",
+ pdata[0], pdata[1], pdata[2], pdata[3],
+ pdata[4], pdata[5], pdata[6], pdata[7]
+ ));
+ zm_dbg(("(%03d %02x) (%03d %02x) (%03d %02x) (%03d %02x) \n",
+ pdata[8], pdata[9], pdata[10], pdata[11],
+ pdata[12], pdata[13], pdata[14], pdata[15]
+ ));
+ }
+ }
+#endif
+ #endif
+}
+
+void zfPrintTargetPower2G(u8_t* tPow2xCck, u8_t* tPow2x2g, u8_t* tPow2x2gHt20, u8_t* tPow2x2gHt40)
+{
+ //#ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ DbgPrint("targetPwr CCK : %d, %d, %d, %d\n",
+ tPow2xCck[0],
+ tPow2xCck[1],
+ tPow2xCck[2],
+ tPow2xCck[3]
+ );
+ DbgPrint("targetPwr 2G : %d, %d, %d, %d\n",
+ tPow2x2g[0],
+ tPow2x2g[1],
+ tPow2x2g[2],
+ tPow2x2g[3]
+ );
+ DbgPrint("targetPwr 2GHT20 : %d, %d, %d, %d, %d, %d, %d, %d\n",
+ tPow2x2gHt20[0],
+ tPow2x2gHt20[1],
+ tPow2x2gHt20[2],
+ tPow2x2gHt20[3],
+ tPow2x2gHt20[4],
+ tPow2x2gHt20[5],
+ tPow2x2gHt20[6],
+ tPow2x2gHt20[7]
+ );
+ DbgPrint("targetPwr 2GHT40 : %d, %d, %d, %d, %d, %d, %d, %d\n",
+ tPow2x2gHt40[0],
+ tPow2x2gHt40[1],
+ tPow2x2gHt40[2],
+ tPow2x2gHt40[3],
+ tPow2x2gHt40[4],
+ tPow2x2gHt40[5],
+ tPow2x2gHt40[6],
+ tPow2x2gHt40[7]
+ );
+ #endif
+ return;
+}
+
+void zfPrintTargetPower5G(u8_t* tPow2x5g, u8_t* tPow2x5gHt20, u8_t* tPow2x5gHt40)
+{
+ //#ifdef ZM_ENABLE_TPC_WINDOWS_DEBUG
+ #ifdef ZM_ENABLE_BANDEDGES_WINDOWS_DEBUG
+ DbgPrint("targetPwr 5G : %d, %d, %d, %d\n",
+ tPow2x5g[0],
+ tPow2x5g[1],
+ tPow2x5g[2],
+ tPow2x5g[3]
+ );
+ DbgPrint("targetPwr 5GHT20 : %d, %d, %d, %d, %d, %d, %d, %d\n",
+ tPow2x5gHt20[0],
+ tPow2x5gHt20[1],
+ tPow2x5gHt20[2],
+ tPow2x5gHt20[3],
+ tPow2x5gHt20[4],
+ tPow2x5gHt20[5],
+ tPow2x5gHt20[6],
+ tPow2x5gHt20[7]
+ );
+ DbgPrint("targetPwr 5GHT40 : %d, %d, %d, %d, %d, %d, %d, %d\n",
+ tPow2x5gHt40[0],
+ tPow2x5gHt40[1],
+ tPow2x5gHt40[2],
+ tPow2x5gHt40[3],
+ tPow2x5gHt40[4],
+ tPow2x5gHt40[5],
+ tPow2x5gHt40[6],
+ tPow2x5gHt40[7]
+ );
+ #endif
+ return;
+}
+
+void zfHpPowerSaveSetMode(zdev_t* dev, u8_t staMode, u8_t psMode, u16_t bcnInterval)
+{
+ if ( staMode == 0 )
+ {
+ if ( psMode == 0 )
+ {
+ // Turn off pre-TBTT interrupt
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_PRETBTT, 0);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PERIOD, 0);
+ zfFlushDelayWrite(dev);
+ }
+ else
+ {
+ // Turn on pre-TBTT interrupt
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_PRETBTT, (bcnInterval-6)<<16);
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PERIOD, bcnInterval);
+ zfFlushDelayWrite(dev);
+ }
+ }
+}
+
+void zfHpPowerSaveSetState(zdev_t* dev, u8_t psState)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+
+ //DbgPrint("INTO zfHpPowerSaveSetState");
+
+ if ( psState == 0 ) //power up
+ {
+ //DbgPrint("zfHpPowerSaveSetState Wake up from PS\n");
+ reg_write(0x982C, 0x0000a000); //wake up ADDAC
+ reg_write(0x9808, 0x0); //enable all agc gain and offset updates to a2
+ //# bank 3
+ if (((struct zsHpPriv*)wd->hpPrivate)->hwFrequency <= ZM_CH_G_14)
+ {
+ /* 11g */
+ //reg_write (0x98f0, 0x01c00018);
+ reg_write (0x98f0, 0x01c20098);//syn_on+RX_ON
+ }
+ else
+ {
+ /* 11a */
+ //reg_write (0x98f0, 0x01400018);
+ reg_write (0x98f0, 0x01420098);//syn_on+RX_ON
+ }
+
+ ////#bank 5
+ //reg_write(0x98b0, 0x00000013);
+ //reg_write(0x98e4, 0x00000002);
+
+
+ zfFlushDelayWrite(dev);
+ }
+ else //power down
+ {
+ //DbgPrint("zfHpPowerSaveSetState Go to PS\n");
+ //reg_write(0x982C, 0xa000a000);
+ reg_write(0x9808, 0x8000000); //disable all agc gain and offset updates to a2
+ reg_write(0x982C, 0xa000a000); //power down ADDAC
+ //# bank 3
+ if (((struct zsHpPriv*)wd->hpPrivate)->hwFrequency <= ZM_CH_G_14)
+ {
+ /* 11g */
+ reg_write (0x98f0, 0x00c00018);//syn_off+RX_off
+ }
+ else
+ {
+ /* 11a */
+ reg_write (0x98f0, 0x00400018);//syn_off+RX_off
+ }
+
+ ////#bank 5
+ //reg_write(0x98b0, 0x000e0013);
+ //reg_write(0x98e4, 0x00018002);
+
+
+ zfFlushDelayWrite(dev);
+ }
+}
+
+void zfHpSetAggPktNum(zdev_t* dev, u32_t num)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+
+ num = (num << 16) | (0xa);
+
+ hpPriv->aggPktNum = num;
+
+ //aggregation number will be update in HAL heart beat
+ //zfDelayWriteInternalReg(dev, 0x1c3b9c, num);
+ //zfFlushDelayWrite(dev);
+}
+
+void zfHpSetMPDUDensity(zdev_t* dev, u8_t density)
+{
+ u32_t value;
+
+ if (density > ZM_MPDU_DENSITY_8US)
+ {
+ return;
+ }
+
+ /* Default value in this register */
+ value = 0x140A00 | density;
+
+ zfDelayWriteInternalReg(dev, 0x1c3ba0, value);
+ zfFlushDelayWrite(dev);
+ return;
+}
+
+void zfHpSetSlotTime(zdev_t* dev, u8_t type)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = wd->hpPrivate;
+
+ if (type == 0)
+ {
+ //normal slot = 20us
+ hpPriv->slotType = 0;
+ }
+ else //if (type == 1)
+ {
+ //short slot = 9us
+ hpPriv->slotType = 1;
+ }
+
+ return;
+}
+
+void zfHpSetSlotTimeRegister(zdev_t* dev, u8_t type)
+{
+ if(type == 0)
+ {
+ //normal slot = 20us
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_SLOT_TIME, 20<<10);
+ }
+ else
+ {
+ //short slot = 9us
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_SLOT_TIME, 9<<10);
+ }
+}
+
+void zfHpSetRifs(zdev_t* dev, u8_t ht_enable, u8_t ht2040, u8_t g_mode)
+{
+ zfDelayWriteInternalReg(dev, 0x1c6388, 0x0c000000);
+
+ zfDelayWriteInternalReg(dev, 0x1c59ec, 0x0cc80caa);
+
+ if (ht_enable)
+ {
+ if (ht2040)
+ {
+ zfDelayWriteInternalReg(dev, 0x1c5918, 40);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c5918, 20);
+ }
+ }
+
+ if (g_mode)
+ {
+ zfDelayWriteInternalReg(dev, 0x1c5850, 0xec08b4e2);
+ zfDelayWriteInternalReg(dev, 0x1c585c, 0x313a5d5e);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c5850, 0xede8b4e0);
+ zfDelayWriteInternalReg(dev, 0x1c585c, 0x3139605e);
+ }
+
+ zfFlushDelayWrite(dev);
+ return;
+}
+
+void zfHpBeginSiteSurvey(zdev_t* dev, u8_t status)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ if ( status == 1 )
+ { // Connected
+ hpPriv->isSiteSurvey = 1;
+ }
+ else
+ { // Not connected
+ hpPriv->isSiteSurvey = 0;
+ }
+
+ /* reset workaround state to default */
+// if (hpPriv->rxStrongRSSI == 1)
+ {
+ hpPriv->rxStrongRSSI = 0;
+ if ((hpPriv->eepromImage[0x100+0x110*2/4]&0xff) == 0x80) //FEM TYPE
+ {
+ if (hpPriv->hwFrequency <= ZM_CH_G_14)
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x9b49);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x0900);
+ }
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, 0x1c8960, 0x9b40);
+ }
+ zfFlushDelayWrite(dev);
+ }
+// if (hpPriv->strongRSSI == 1)
+ {
+ hpPriv->strongRSSI = 0;
+ zfDelayWriteInternalReg(dev, 0x1c3694, ((hpPriv->currentAckRtsTpc&0x3f) << 20) | (0x5<<26));
+ zfDelayWriteInternalReg(dev, 0x1c3bb4, ((hpPriv->currentAckRtsTpc&0x3f) << 5 ) | (0x5<<11) |
+ ((hpPriv->currentAckRtsTpc&0x3f) << 21) | (0x5<<27) );
+ zfFlushDelayWrite(dev);
+ }
+}
+
+void zfHpFinishSiteSurvey(zdev_t* dev, u8_t status)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if ( status == 1 )
+ {
+ hpPriv->isSiteSurvey = 2;
+ }
+ else
+ {
+ hpPriv->isSiteSurvey = 0;
+ }
+ zmw_leave_critical_section(dev);
+}
+
+u16_t zfFwRetry(zdev_t* dev, u8_t enable)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret = 0;
+
+ cmd[0] = 4 | (0x92 << 8);
+ cmd[1] = (enable == 1) ? 0x01 : 0x00;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_INTERNAL_WRITE, NULL);
+ return ret;
+}
+
+u16_t zfHpEnableHwRetry(zdev_t* dev)
+{
+ u16_t ret;
+
+ ret = zfFwRetry(dev, 0);
+
+ zfDelayWriteInternalReg(dev, 0x1c3b28, 0x33333);
+ zfFlushDelayWrite(dev);
+
+ return ret;
+}
+
+u16_t zfHpDisableHwRetry(zdev_t* dev)
+{
+ u16_t ret;
+
+ ret = zfFwRetry(dev, 1);
+
+ zfDelayWriteInternalReg(dev, 0x1c3b28, 0x00000);
+ zfFlushDelayWrite(dev);
+
+ return ret;
+}
+
+/* Download SPI Fw */
+#define ZM_FIRMWARE_WLAN 0
+#define ZM_FIRMWARE_SPI_FLASH 1
+
+
+u16_t zfHpFirmwareDownload(zdev_t* dev, u8_t fwType)
+{
+ u16_t ret = ZM_SUCCESS;
+
+ if (fwType == ZM_FIRMWARE_WLAN)
+ {
+ ret = zfFirmwareDownload(dev, (u32_t*)zcFwImage,
+ (u32_t)zcFwImageSize, ZM_FIRMWARE_WLAN_ADDR);
+ }
+ else if (fwType == ZM_FIRMWARE_SPI_FLASH)
+ {
+ ret = zfFirmwareDownload(dev, (u32_t*)zcFwImageSPI,
+ (u32_t)zcFwImageSPISize, ZM_FIRMWARE_SPI_ADDR);
+ }
+ else
+ {
+ zm_debug_msg1("Unknown firmware type = ", fwType);
+ ret = ZM_ERR_FIRMWARE_WRONG_TYPE;
+ }
+
+ return ret;
+}
+
+/* Enable software decryption */
+void zfHpSWDecrypt(zdev_t* dev, u8_t enable)
+{
+ u32_t value = 0x70;
+
+ /* Bit 4 for enable software decryption */
+ if (enable == 1)
+ {
+ value = 0x78;
+ }
+
+ zfDelayWriteInternalReg(dev, 0x1c3678, value);
+ zfFlushDelayWrite(dev);
+}
+
+/* Enable software encryption */
+void zfHpSWEncrypt(zdev_t* dev, u8_t enable)
+{
+ /* Because encryption by software or hardware is judged by driver in Otus,
+ we don't need to do anything in the HAL layer.
+ */
+}
+
+u32_t zfHpCapability(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ return hpPriv->halCapability;
+}
+
+void zfHpSetRollCallTable(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ if (hpPriv->camRollCallTable != (u64_t) 0)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ROLL_CALL_TBL_L, (u32_t)(hpPriv->camRollCallTable & 0xffffffff));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_ROLL_CALL_TBL_H, (u32_t)((hpPriv->camRollCallTable >> 32) & 0xffffffff));
+ zfFlushDelayWrite(dev);
+ }
+}
+
+void zfHpSetTTSIFSTime(zdev_t* dev, u8_t sifs_time)
+{
+ u32_t reg_value = 0;
+ zmw_get_wlan_dev(dev);
+
+ sifs_time &= 0x3f;
+ reg_value = 0x14400b | (((u32_t)sifs_time)<<24);
+
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_EIFS_AND_SIFS, reg_value);
+ zfFlushDelayWrite(dev);
+}
+
+/* #3 Enable RIFS function if the RIFS pattern matched ! */
+void zfHpEnableRifs(zdev_t* dev, u8_t mode24g, u8_t modeHt, u8_t modeHt2040)
+{
+
+ /* # Enable Reset TDOMAIN
+ * $rddata = &$phyreg_read(0x9800+(738<<2));
+ * $wrdata = $rddata | (0x1 << 26) | (0x1 << 27);
+ * &$phyreg_write(0x9800+(738<<2), $wrdata);
+ */
+ reg_write (0x9800+(738<<2), 0x08000000 | (0x1 << 26) | (0x1 << 27));
+ //reg_write (0x9800+(738<<2), 0x08000000 | (0x1 << 26));
+
+ /* # reg 123: heavy clip factor, xr / RIFS search parameters */
+ reg_write (0x99ec, 0x0cc80caa);
+
+ /* # Reduce Search Start Delay for RIFS */
+ if (modeHt == 1) /* ($HT_ENABLE == 1) */
+ {
+ if (modeHt2040 == 0x1) /* ($DYNAMIC_HT2040_EN == 0x1) */
+ {
+ reg_write(0x9800+(70<<2), 40);/*40*/
+ }
+ else
+ {
+ reg_write(0x9800+(70<<2), 20);
+ if(mode24g == 0x0)
+ {
+ /* $rddata = &$phyreg_read(0x9800+(24<<2));#0x9860;0x1c5860
+ *$wrdata = ($rddata & 0xffffffc7) | (0x4 << 3);
+ * &$phyreg_write(0x9800+(24<<2), $wrdata);
+ */
+ reg_write(0x9800+(24<<2), (0x0004dd10 & 0xffffffc7) | (0x4 << 3));
+ }
+ }
+ }
+
+ if (mode24g == 0x1)
+ {
+ reg_write(0x9850, 0xece8b4e4);/*org*/
+ //reg_write(0x9850, 0xece8b4e2);
+ reg_write(0x985c, 0x313a5d5e);
+ }
+ else
+ {
+ reg_write(0x9850, 0xede8b4e4);
+ reg_write(0x985c, 0x3139605e);
+ }
+
+ zfFlushDelayWrite(dev);
+
+ return;
+}
+
+/* #4 Disable RIFS function if the RIFS timer is timeout ! */
+void zfHpDisableRifs(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ /* Disable RIFS function is to store these HW register initial value while the device plug-in and
+ re-write to these register if the RIFS function is disabled */
+
+ // reg : 9850
+ reg_write(0x9850, ((struct zsHpPriv*)wd->hpPrivate)->initDesiredSigSize);
+
+ // reg : 985c
+ reg_write(0x985c, ((struct zsHpPriv*)wd->hpPrivate)->initAGC);
+
+ // reg : 9860
+ reg_write(0x9800+(24<<2), ((struct zsHpPriv*)wd->hpPrivate)->initAgcControl);
+
+ // reg : 9918
+ reg_write(0x9800+(70<<2), ((struct zsHpPriv*)wd->hpPrivate)->initSearchStartDelay);
+
+ // reg : 991c
+ reg_write (0x99ec, ((struct zsHpPriv*)wd->hpPrivate)->initRIFSSearchParams);
+
+ // reg : a388
+ reg_write (0x9800+(738<<2), ((struct zsHpPriv*)wd->hpPrivate)->initFastChannelChangeControl);
+
+ zfFlushDelayWrite(dev);
+
+ return;
+}
diff --git a/drivers/staging/otus/hal/hpreg.c b/drivers/staging/otus/hal/hpreg.c
new file mode 100644
index 000000000000..3cfeba8620f6
--- /dev/null
+++ b/drivers/staging/otus/hal/hpreg.c
@@ -0,0 +1,2481 @@
+/*
+ * Copyright (c) 2000-2005 ZyDAS Technology Corporation
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : hpreg.c */
+/* */
+/* Abstract */
+/* This module contains Regulatory Table and related function. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "../80211core/cprecomp.h"
+#include "hpani.h"
+#include "hpreg.h"
+#include "hpusb.h"
+
+/* used throughout this file... */
+#define N(a) (sizeof (a) / sizeof (a[0]))
+
+#define HAL_MODE_11A_TURBO HAL_MODE_108A
+#define HAL_MODE_11G_TURBO HAL_MODE_108G
+
+#if 0
+enum {
+ /* test groups */
+ FCC = 0x10,
+ MKK = 0x40,
+ ETSI = 0x30,
+ SD_NO_CTL = 0xe0,
+ NO_CTL = 0xff,
+ /* test modes */
+ CTL_MODE_M = 0x0f,
+ CTL_11A = 0,
+ CTL_11B = 1,
+ CTL_11G = 2,
+ CTL_TURBO = 3,
+ CTL_108G = 4,
+ CTL_2GHT20 = 5,
+ CTL_5GHT20 = 6,
+ CTL_2GHT40 = 7,
+ CTL_5GHT40 = 8
+};
+#endif
+
+/*
+ * The following are flags for different requirements per reg domain.
+ * These requirements are either inhereted from the reg domain pair or
+ * from the unitary reg domain if the reg domain pair flags value is
+ * 0
+ */
+
+enum {
+ NO_REQ = 0x00000000,
+ DISALLOW_ADHOC_11A = 0x00000001,
+ DISALLOW_ADHOC_11A_TURB = 0x00000002,
+ NEED_NFC = 0x00000004,
+
+ ADHOC_PER_11D = 0x00000008, /* Start Ad-Hoc mode */
+ ADHOC_NO_11A = 0x00000010,
+
+ PUBLIC_SAFETY_DOMAIN = 0x00000020, /* public safety domain */
+ LIMIT_FRAME_4MS = 0x00000040, /* 4msec limit on the frame length */
+};
+
+#define MKK5GHZ_FLAG1 (DISALLOW_ADHOC_11A_TURB | NEED_NFC | LIMIT_FRAME_4MS)
+#define MKK5GHZ_FLAG2 (DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB | NEED_NFC| LIMIT_FRAME_4MS)
+
+typedef enum {
+ DFS_UNINIT_DOMAIN = 0, /* Uninitialized dfs domain */
+ DFS_FCC_DOMAIN = 1, /* FCC3 dfs domain */
+ DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */
+} HAL_DFS_DOMAIN;
+
+/*
+ * Used to set the RegDomain bitmask which chooses which frequency
+ * band specs are used.
+ */
+
+#define BMLEN 2 /* Use 2 64 bit uint for channel bitmask
+ NB: Must agree with macro below (BM) */
+#define BMZERO {(u64_t) 0, (u64_t) 0} /* BMLEN zeros */
+
+#if 0
+
+#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \
+ {((((_fa >= 0) && (_fa < 64)) ? (((u64_t) 1) << _fa) : (u64_t) 0) | \
+ (((_fb >= 0) && (_fb < 64)) ? (((u64_t) 1) << _fb) : (u64_t) 0) | \
+ (((_fc >= 0) && (_fc < 64)) ? (((u64_t) 1) << _fc) : (u64_t) 0) | \
+ (((_fd >= 0) && (_fd < 64)) ? (((u64_t) 1) << _fd) : (u64_t) 0) | \
+ (((_fe >= 0) && (_fe < 64)) ? (((u64_t) 1) << _fe) : (u64_t) 0) | \
+ (((_ff >= 0) && (_ff < 64)) ? (((u64_t) 1) << _ff) : (u64_t) 0) | \
+ (((_fg >= 0) && (_fg < 64)) ? (((u64_t) 1) << _fg) : (u64_t) 0) | \
+ (((_fh >= 0) && (_fh < 64)) ? (((u64_t) 1) << _fh) : (u64_t) 0) | \
+ (((_fi >= 0) && (_fi < 64)) ? (((u64_t) 1) << _fi) : (u64_t) 0) | \
+ (((_fj >= 0) && (_fj < 64)) ? (((u64_t) 1) << _fj) : (u64_t) 0) | \
+ (((_fk >= 0) && (_fk < 64)) ? (((u64_t) 1) << _fk) : (u64_t) 0) | \
+ (((_fl >= 0) && (_fl < 64)) ? (((u64_t) 1) << _fl) : (u64_t) 0) | \
+ ((((_fa > 63) && (_fa < 128)) ? (((u64_t) 1) << (_fa - 64)) : (u64_t) 0) | \
+ (((_fb > 63) && (_fb < 128)) ? (((u64_t) 1) << (_fb - 64)) : (u64_t) 0) | \
+ (((_fc > 63) && (_fc < 128)) ? (((u64_t) 1) << (_fc - 64)) : (u64_t) 0) | \
+ (((_fd > 63) && (_fd < 128)) ? (((u64_t) 1) << (_fd - 64)) : (u64_t) 0) | \
+ (((_fe > 63) && (_fe < 128)) ? (((u64_t) 1) << (_fe - 64)) : (u64_t) 0) | \
+ (((_ff > 63) && (_ff < 128)) ? (((u64_t) 1) << (_ff - 64)) : (u64_t) 0) | \
+ (((_fg > 63) && (_fg < 128)) ? (((u64_t) 1) << (_fg - 64)) : (u64_t) 0) | \
+ (((_fh > 63) && (_fh < 128)) ? (((u64_t) 1) << (_fh - 64)) : (u64_t) 0) | \
+ (((_fi > 63) && (_fi < 128)) ? (((u64_t) 1) << (_fi - 64)) : (u64_t) 0) | \
+ (((_fj > 63) && (_fj < 128)) ? (((u64_t) 1) << (_fj - 64)) : (u64_t) 0) | \
+ (((_fk > 63) && (_fk < 128)) ? (((u64_t) 1) << (_fk - 64)) : (u64_t) 0) | \
+ (((_fl > 63) && (_fl < 128)) ? (((u64_t) 1) << (_fl - 64)) : (u64_t) 0)))}
+
+#else
+
+#define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh, _fi, _fj, _fk, _fl) \
+ {((((_fa >= 0) && (_fa < 64)) ? (((u64_t) 1) << (_fa&0x3f)) : (u64_t) 0) | \
+ (((_fb >= 0) && (_fb < 64)) ? (((u64_t) 1) << (_fb&0x3f)) : (u64_t) 0) | \
+ (((_fc >= 0) && (_fc < 64)) ? (((u64_t) 1) << (_fc&0x3f)) : (u64_t) 0) | \
+ (((_fd >= 0) && (_fd < 64)) ? (((u64_t) 1) << (_fd&0x3f)) : (u64_t) 0) | \
+ (((_fe >= 0) && (_fe < 64)) ? (((u64_t) 1) << (_fe&0x3f)) : (u64_t) 0) | \
+ (((_ff >= 0) && (_ff < 64)) ? (((u64_t) 1) << (_ff&0x3f)) : (u64_t) 0) | \
+ (((_fg >= 0) && (_fg < 64)) ? (((u64_t) 1) << (_fg&0x3f)) : (u64_t) 0) | \
+ (((_fh >= 0) && (_fh < 64)) ? (((u64_t) 1) << (_fh&0x3f)) : (u64_t) 0) | \
+ (((_fi >= 0) && (_fi < 64)) ? (((u64_t) 1) << (_fi&0x3f)) : (u64_t) 0) | \
+ (((_fj >= 0) && (_fj < 64)) ? (((u64_t) 1) << (_fj&0x3f)) : (u64_t) 0) | \
+ (((_fk >= 0) && (_fk < 64)) ? (((u64_t) 1) << (_fk&0x3f)) : (u64_t) 0) | \
+ (((_fl >= 0) && (_fl < 64)) ? (((u64_t) 1) << (_fl&0x3f)) : (u64_t) 0) | \
+ ((((_fa > 63) && (_fa < 128)) ? (((u64_t) 1) << ((_fa - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fb > 63) && (_fb < 128)) ? (((u64_t) 1) << ((_fb - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fc > 63) && (_fc < 128)) ? (((u64_t) 1) << ((_fc - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fd > 63) && (_fd < 128)) ? (((u64_t) 1) << ((_fd - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fe > 63) && (_fe < 128)) ? (((u64_t) 1) << ((_fe - 64)&0x3f)) : (u64_t) 0) | \
+ (((_ff > 63) && (_ff < 128)) ? (((u64_t) 1) << ((_ff - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fg > 63) && (_fg < 128)) ? (((u64_t) 1) << ((_fg - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fh > 63) && (_fh < 128)) ? (((u64_t) 1) << ((_fh - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fi > 63) && (_fi < 128)) ? (((u64_t) 1) << ((_fi - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fj > 63) && (_fj < 128)) ? (((u64_t) 1) << ((_fj - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fk > 63) && (_fk < 128)) ? (((u64_t) 1) << ((_fk - 64)&0x3f)) : (u64_t) 0) | \
+ (((_fl > 63) && (_fl < 128)) ? (((u64_t) 1) << ((_fl - 64)&0x3f)) : (u64_t) 0)))}
+
+#endif
+
+/* Mask to check whether a domain is a multidomain or a single
+ domain */
+
+#define MULTI_DOMAIN_MASK 0xFF00
+
+
+/*
+ * The following describe the bit masks for different passive scan
+ * capability/requirements per regdomain.
+ */
+#define NO_PSCAN 0x0ULL
+#define PSCAN_FCC 0x0000000000000001ULL
+#define PSCAN_FCC_T 0x0000000000000002ULL
+#define PSCAN_ETSI 0x0000000000000004ULL
+#define PSCAN_MKK1 0x0000000000000008ULL
+#define PSCAN_MKK2 0x0000000000000010ULL
+#define PSCAN_MKKA 0x0000000000000020ULL
+#define PSCAN_MKKA_G 0x0000000000000040ULL
+#define PSCAN_ETSIA 0x0000000000000080ULL
+#define PSCAN_ETSIB 0x0000000000000100ULL
+#define PSCAN_ETSIC 0x0000000000000200ULL
+#define PSCAN_WWR 0x0000000000000400ULL
+#define PSCAN_MKKA1 0x0000000000000800ULL
+#define PSCAN_MKKA1_G 0x0000000000001000ULL
+#define PSCAN_MKKA2 0x0000000000002000ULL
+#define PSCAN_MKKA2_G 0x0000000000004000ULL
+#define PSCAN_MKK3 0x0000000000008000ULL
+#define PSCAN_DEFER 0x7FFFFFFFFFFFFFFFULL
+#define IS_ECM_CHAN 0x8000000000000000ULL
+
+/*
+ * THE following table is the mapping of regdomain pairs specified by
+ * an 8 bit regdomain value to the individual unitary reg domains
+ */
+
+typedef struct reg_dmn_pair_mapping {
+ u16_t regDmnEnum; /* 16 bit reg domain pair */
+ u16_t regDmn5GHz; /* 5GHz reg domain */
+ u16_t regDmn2GHz; /* 2GHz reg domain */
+ u32_t flags5GHz; /* Requirements flags (AdHoc
+ disallow, noise floor cal needed,
+ etc) */
+ u32_t flags2GHz; /* Requirements flags (AdHoc
+ disallow, noise floor cal needed,
+ etc) */
+ u64_t pscanMask; /* Passive Scan flags which
+ can override unitary domain
+ passive scan flags. This
+ value is used as a mask on
+ the unitary flags*/
+ u16_t singleCC; /* Country code of single country if
+ a one-on-one mapping exists */
+} REG_DMN_PAIR_MAPPING;
+
+static REG_DMN_PAIR_MAPPING regDomainPairs[] = {
+ {NO_ENUMRD, FCC2, DEBUG_REG_DMN, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {NULL1_WORLD, NULL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {NULL1_ETSIB, NULL1, ETSIB, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {NULL1_ETSIC, NULL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+ {FCC2_FCCA, FCC2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC2_WORLD, FCC2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC2_ETSIC, FCC2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC3_FCCA, FCC3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC3_WORLD, FCC3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC4_FCCA, FCC4, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC5_FCCA, FCC5, FCCA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC6_FCCA, FCC6, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC6_WORLD, FCC6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+ {ETSI1_WORLD, ETSI1, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {ETSI2_WORLD, ETSI2, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {ETSI3_WORLD, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {ETSI4_WORLD, ETSI4, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {ETSI5_WORLD, ETSI5, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {ETSI6_WORLD, ETSI6, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+
+ {ETSI3_ETSIA, ETSI3, WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {FRANCE_RES, ETSI3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+ {FCC1_WORLD, FCC1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {FCC1_FCCA, FCC1, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL1_WORLD, APL1, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL2_WORLD, APL2, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL3_WORLD, APL3, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL4_WORLD, APL4, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL5_WORLD, APL5, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL6_WORLD, APL6, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL8_WORLD, APL8, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL9_WORLD, APL9, WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+ {APL3_FCCA, APL3, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL1_ETSIC, APL1, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL2_ETSIC, APL2, ETSIC, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL2_FCCA, APL2, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {APL2_APLD, APL2, APLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0},
+ {APL7_FCCA, APL7, FCCA, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+
+ {MKK1_MKKA, MKK1, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA, CTRY_JAPAN },
+ {MKK1_MKKB, MKK1, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN1 },
+ {MKK1_FCCA, MKK1, FCCA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN2 },
+ {MKK1_MKKA1, MKK1, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN4 },
+ {MKK1_MKKA2, MKK1, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN5 },
+ {MKK1_MKKC, MKK1, MKKC, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN6 },
+
+ /* MKK2 */
+ {MKK2_MKKA, MKK2, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKK2 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN3 },
+
+ /* MKK3 */
+ {MKK3_MKKA, MKK3, MKKA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN25 },
+ {MKK3_MKKB, MKK3, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN7 },
+ {MKK3_MKKA1, MKK3, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN26 },
+ {MKK3_MKKA2, MKK3, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN8 },
+ {MKK3_MKKC, MKK3, MKKC, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN9 },
+ {MKK3_FCCA, MKK3, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN27 },
+
+ /* MKK4 */
+ {MKK4_MKKB, MKK4, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN10 },
+ {MKK4_MKKA1, MKK4, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN28 },
+ {MKK4_MKKA2, MKK4, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK3 |PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN11 },
+ {MKK4_MKKC, MKK4, MKKC, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN12 },
+ {MKK4_FCCA, MKK4, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN29 },
+ {MKK4_MKKA, MKK4, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA, CTRY_JAPAN36 },
+
+ /* MKK5 */
+ {MKK5_MKKB, MKK5, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN13 },
+ {MKK5_MKKA2, MKK5, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN14 },
+ {MKK5_MKKC, MKK5, MKKC, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK3, CTRY_JAPAN15 },
+
+ /* MKK6 */
+ {MKK6_MKKB, MKK6, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN16 },
+ {MKK6_MKKA2, MKK6, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN17 },
+ {MKK6_MKKC, MKK6, MKKC, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1, CTRY_JAPAN18 },
+ {MKK6_MKKA1, MKK6, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN30 },
+ {MKK6_FCCA, MKK6, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN31 },
+
+ /* MKK7 */
+ {MKK7_MKKB, MKK7, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN19 },
+ {MKK7_MKKA, MKK7, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN20 },
+ {MKK7_MKKC, MKK7, MKKC, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3, CTRY_JAPAN21 },
+ {MKK7_MKKA1, MKK7, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN32 },
+ {MKK7_FCCA, MKK7, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN33 },
+
+ /* MKK8 */
+ {MKK8_MKKB, MKK8, MKKA, MKK5GHZ_FLAG2, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA | PSCAN_MKKA_G, CTRY_JAPAN22 },
+ {MKK8_MKKA2, MKK8, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN23 },
+ {MKK8_MKKC, MKK8, MKKC, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 , CTRY_JAPAN24 },
+
+ /* MKK9 */
+ {MKK9_MKKA, MKK9, MKKA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN34 },
+ {MKK9_FCCA, MKK9, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN37 },
+ {MKK9_MKKA1, MKK9, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN38 },
+ {MKK9_MKKC, MKK9, MKKC, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN39 },
+ {MKK9_MKKA2, MKK9, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN40 },
+
+ /* MKK10 */
+ {MKK10_MKKA, MKK10, MKKA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN35 },
+ {MKK10_FCCA, MKK10, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN41 },
+ {MKK10_MKKA1, MKK10, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN42 },
+ {MKK10_MKKC, MKK10, MKKC, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN43 },
+ {MKK10_MKKA2, MKK10, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN44 },
+
+ /* MKK11 */
+ {MKK11_MKKA, MKK11, MKKA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN45 },
+ {MKK11_FCCA, MKK11, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN46 },
+ {MKK11_MKKA1, MKK11, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN47 },
+ {MKK11_MKKC, MKK11, MKKC, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN48 },
+ {MKK11_MKKA2, MKK11, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN49 },
+
+ /* MKK12 */
+ {MKK12_MKKA, MKK12, MKKA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN50 },
+ {MKK12_FCCA, MKK12, FCCA, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN51 },
+ {MKK12_MKKA1, MKK12, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKKA1 | PSCAN_MKKA1_G, CTRY_JAPAN52 },
+ {MKK12_MKKC, MKK12, MKKC, MKK5GHZ_FLAG1, NEED_NFC, NO_PSCAN, CTRY_JAPAN53 },
+ {MKK12_MKKA2, MKK12, MKKA, MKK5GHZ_FLAG1, NEED_NFC, PSCAN_MKK1 | PSCAN_MKK3 | PSCAN_MKKA2 | PSCAN_MKKA2_G, CTRY_JAPAN54 },
+
+
+ /* These are super domains */
+ {WOR0_WORLD, WOR0_WORLD, WOR0_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR1_WORLD, WOR1_WORLD, WOR1_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR2_WORLD, WOR2_WORLD, WOR2_WORLD, DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR3_WORLD, WOR3_WORLD, WOR3_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR4_WORLD, WOR4_WORLD, WOR4_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR5_ETSIC, WOR5_ETSIC, WOR5_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR01_WORLD, WOR01_WORLD, WOR01_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR02_WORLD, WOR02_WORLD, WOR02_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {EU1_WORLD, EU1_WORLD, EU1_WORLD, NO_REQ, NO_REQ, PSCAN_DEFER, 0 },
+ {WOR9_WORLD, WOR9_WORLD, WOR9_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+ {WORA_WORLD, WORA_WORLD, WORA_WORLD, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB, NO_REQ, PSCAN_DEFER, 0 },
+};
+
+/*
+ * The following table is the master list for all different freqeuncy
+ * bands with the complete matrix of all possible flags and settings
+ * for each band if it is used in ANY reg domain.
+ */
+
+#define DEF_REGDMN FCC1_FCCA
+#define DEF_DMN_5 FCC1
+#define DEF_DMN_2 FCCA
+#define COUNTRY_ERD_FLAG 0x8000
+#define WORLDWIDE_ROAMING_FLAG 0x4000
+#define SUPER_DOMAIN_MASK 0x0fff
+#define COUNTRY_CODE_MASK 0x03ff
+#define CF_INTERFERENCE (CHANNEL_CW_INT | CHANNEL_RADAR_INT)
+#define CHANNEL_14 (2484) /* 802.11g operation is not permitted on channel 14 */
+#define IS_11G_CH14(_ch,_cf) \
+ (((_ch) == CHANNEL_14) && ((_cf) == CHANNEL_G))
+
+#define YES TRUE
+#define NO FALSE
+
+enum {
+ CTRY_DEBUG = 0x1ff, /* debug country code */
+ CTRY_DEFAULT = 0 /* default country code */
+};
+
+typedef struct {
+ HAL_CTRY_CODE countryCode;
+ HAL_REG_DOMAIN regDmnEnum;
+ const char* isoName;
+ const char* name;
+ HAL_BOOL allow11g;
+ HAL_BOOL allow11aTurbo;
+ HAL_BOOL allow11gTurbo;
+ HAL_BOOL allow11na; /* HT-40 allowed in 5GHz? */
+ HAL_BOOL allow11ng; /* HT-40 allowed in 2GHz? */
+ u16_t outdoorChanStart;
+} COUNTRY_CODE_TO_ENUM_RD;
+
+static COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
+ {CTRY_DEBUG, NO_ENUMRD, "DB", "DEBUG", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_DEFAULT, DEF_REGDMN, "NA", "NO_COUNTRY_SET", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_ALBANIA, NULL1_WORLD, "AL", "ALBANIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_ALGERIA, NULL1_WORLD, "DZ", "ALGERIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_ARGENTINA, APL3_WORLD, "AR", "ARGENTINA", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_ARMENIA, ETSI4_WORLD, "AM", "ARMENIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_AUSTRALIA, FCC6_WORLD, "AU", "AUSTRALIA", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_AUSTRIA, ETSI2_WORLD, "AT", "AUSTRIA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ", "AZERBAIJAN", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_BAHRAIN, APL6_WORLD, "BH", "BAHRAIN", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_BELARUS, ETSI1_WORLD, "BY", "BELARUS", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_BELGIUM, ETSI1_WORLD, "BE", "BELGIUM", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_BELIZE, APL1_ETSIC, "BZ", "BELIZE", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_BOLIVIA, APL1_ETSIC, "BO", "BOLVIA", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_BRAZIL, FCC3_WORLD, "BR", "BRAZIL", NO, NO, NO, NO, NO, 7000 },
+ {CTRY_BRUNEI_DARUSSALAM,APL1_WORLD,"BN", "BRUNEI DARUSSALAM", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_BULGARIA, ETSI6_WORLD, "BG", "BULGARIA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_CANADA, FCC6_FCCA, "CA", "CANADA", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_CHILE, APL6_WORLD, "CL", "CHILE", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_CHINA, APL1_WORLD, "CN", "CHINA", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_COLOMBIA, FCC1_FCCA, "CO", "COLOMBIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_COSTA_RICA, FCC1_WORLD, "CR", "COSTA RICA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_CROATIA, ETSI3_WORLD, "HR", "CROATIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_CYPRUS, ETSI3_WORLD, "CY", "CYPRUS", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_CZECH, ETSI3_WORLD, "CZ", "CZECH REPUBLIC", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_DENMARK, ETSI1_WORLD, "DK", "DENMARK", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_DOMINICAN_REPUBLIC,FCC1_FCCA,"DO", "DOMINICAN REPUBLIC", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_ECUADOR, FCC1_WORLD, "EC", "ECUADOR", YES, NO, NO, NO, YES, 7000 },
+ {CTRY_EGYPT, ETSI3_WORLD, "EG", "EGYPT", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_EL_SALVADOR, FCC1_WORLD, "SV", "EL SALVADOR", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_ESTONIA, ETSI1_WORLD, "EE", "ESTONIA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_FINLAND, ETSI1_WORLD, "FI", "FINLAND", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_FRANCE, ETSI1_WORLD, "FR", "FRANCE", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_FRANCE2, ETSI3_WORLD, "F2", "FRANCE_RES", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_GEORGIA, ETSI4_WORLD, "GE", "GEORGIA", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_GERMANY, ETSI1_WORLD, "DE", "GERMANY", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_GREECE, ETSI1_WORLD, "GR", "GREECE", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_GUATEMALA, FCC1_FCCA, "GT", "GUATEMALA", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_HONDURAS, NULL1_WORLD, "HN", "HONDURAS", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_HONG_KONG, FCC2_WORLD, "HK", "HONG KONG", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_HUNGARY, ETSI4_WORLD, "HU", "HUNGARY", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_ICELAND, ETSI1_WORLD, "IS", "ICELAND", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_INDIA, APL6_WORLD, "IN", "INDIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_INDONESIA, APL1_WORLD, "ID", "INDONESIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_IRAN, APL1_WORLD, "IR", "IRAN", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_IRELAND, ETSI1_WORLD, "IE", "IRELAND", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_ISRAEL, ETSI3_WORLD, "IL", "ISRAEL", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_ISRAEL2, NULL1_ETSIB, "ISR","ISRAEL_RES", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_ITALY, ETSI1_WORLD, "IT", "ITALY", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_JAMAICA, ETSI1_WORLD, "JM", "JAMAICA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_JAPAN, MKK1_MKKA, "JP", "JAPAN", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN1, MKK1_MKKB, "J1", "JAPAN1", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN2, MKK1_FCCA, "J2", "JAPAN2", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN3, MKK2_MKKA, "J3", "JAPAN3", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN4, MKK1_MKKA1, "J4", "JAPAN4", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN5, MKK1_MKKA2, "J5", "JAPAN5", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN6, MKK1_MKKC, "J6", "JAPAN6", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN7, MKK3_MKKB, "J7", "JAPAN7", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN8, MKK3_MKKA2, "J8", "JAPAN8", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN9, MKK3_MKKC, "J9", "JAPAN9", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN10, MKK4_MKKB, "J10", "JAPAN10", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN11, MKK4_MKKA2, "J11", "JAPAN11", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN12, MKK4_MKKC, "J12", "JAPAN12", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN13, MKK5_MKKB, "J13", "JAPAN13", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN14, MKK5_MKKA2, "J14", "JAPAN14", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN15, MKK5_MKKC, "J15", "JAPAN15", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN16, MKK6_MKKB, "J16", "JAPAN16", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN17, MKK6_MKKA2, "J17", "JAPAN17", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN18, MKK6_MKKC, "J18", "JAPAN18", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN19, MKK7_MKKB, "J19", "JAPAN19", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN20, MKK7_MKKA, "J20", "JAPAN20", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN21, MKK7_MKKC, "J21", "JAPAN21", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN22, MKK8_MKKB, "J22", "JAPAN22", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN23, MKK8_MKKA2, "J23", "JAPAN23", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN24, MKK8_MKKC, "J24", "JAPAN24", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN25, MKK3_MKKA, "J25", "JAPAN25", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN26, MKK3_MKKA1, "J26", "JAPAN26", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN27, MKK3_FCCA, "J27", "JAPAN27", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN28, MKK4_MKKA1, "J28", "JAPAN28", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN29, MKK4_FCCA, "J29", "JAPAN29", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN30, MKK6_MKKA1, "J30", "JAPAN30", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN31, MKK6_FCCA, "J31", "JAPAN31", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN32, MKK7_MKKA1, "J32", "JAPAN32", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN33, MKK7_FCCA, "J33", "JAPAN33", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN34, MKK9_MKKA, "J34", "JAPAN34", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN35, MKK10_MKKA, "J35", "JAPAN35", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN36, MKK4_MKKA, "J36", "JAPAN36", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN37, MKK9_FCCA, "J37", "JAPAN37", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN38, MKK9_MKKA1, "J38", "JAPAN38", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN39, MKK9_MKKC, "J39", "JAPAN39", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN40, MKK10_MKKA2, "J40", "JAPAN40", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN41, MKK10_FCCA, "J41", "JAPAN41", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN42, MKK10_MKKA1, "J42", "JAPAN42", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN43, MKK10_MKKC, "J43", "JAPAN43", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN44, MKK10_MKKA2, "J44", "JAPAN44", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN45, MKK11_MKKA, "J45", "JAPAN45", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN46, MKK11_FCCA, "J46", "JAPAN46", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN47, MKK11_MKKA1, "J47", "JAPAN47", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN48, MKK11_MKKC, "J48", "JAPAN48", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN49, MKK11_MKKA2, "J49", "JAPAN49", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN50, MKK12_MKKA, "J50", "JAPAN50", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN51, MKK12_FCCA, "J51", "JAPAN51", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN52, MKK12_MKKA1, "J52", "JAPAN52", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN53, MKK12_MKKC, "J53", "JAPAN53", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JAPAN54, MKK12_MKKA2, "J54", "JAPAN54", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_JORDAN, ETSI2_WORLD, "JO", "JORDAN", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ", "KAZAKHSTAN", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_KOREA_NORTH, APL9_WORLD, "KP", "NORTH KOREA", YES, NO, NO, YES, YES, 7000 },
+ {CTRY_KOREA_ROC, APL9_WORLD, "KR", "KOREA REPUBLIC", YES, NO, NO, NO, NO, 7000 },
+ {CTRY_KOREA_ROC2, APL2_APLD, "K2", "KOREA REPUBLIC2",YES, NO, NO, NO, NO, 7000 },
+ {CTRY_KOREA_ROC3, APL9_WORLD, "K3", "KOREA REPUBLIC3",YES, NO, NO, NO, NO, 7000 },
+ {CTRY_KUWAIT, NULL1_WORLD, "KW", "KUWAIT", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_LATVIA, ETSI1_WORLD, "LV", "LATVIA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_LEBANON, NULL1_WORLD, "LB", "LEBANON", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_LIECHTENSTEIN,ETSI1_WORLD, "LI", "LIECHTENSTEIN", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_LITHUANIA, ETSI1_WORLD, "LT", "LITHUANIA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU", "LUXEMBOURG", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_MACAU, FCC2_WORLD, "MO", "MACAU", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_MACEDONIA, NULL1_WORLD, "MK", "MACEDONIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_MALAYSIA, APL8_WORLD, "MY", "MALAYSIA", NO, NO, NO, NO, NO, 7000 },
+ {CTRY_MALTA, ETSI1_WORLD, "MT", "MALTA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_MEXICO, FCC1_FCCA, "MX", "MEXICO", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_MONACO, ETSI4_WORLD, "MC", "MONACO", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_MOROCCO, NULL1_WORLD, "MA", "MOROCCO", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_NETHERLANDS, ETSI1_WORLD, "NL", "NETHERLANDS", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_NETHERLANDS_ANT, ETSI1_WORLD, "AN", "NETHERLANDS-ANTILLES", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ", "NEW ZEALAND", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_NORWAY, ETSI1_WORLD, "NO", "NORWAY", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_OMAN, APL6_WORLD, "OM", "OMAN", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_PAKISTAN, NULL1_WORLD, "PK", "PAKISTAN", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_PANAMA, FCC1_FCCA, "PA", "PANAMA", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_PERU, APL1_WORLD, "PE", "PERU", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_PHILIPPINES, APL1_WORLD, "PH", "PHILIPPINES", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_POLAND, ETSI1_WORLD, "PL", "POLAND", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_PORTUGAL, ETSI1_WORLD, "PT", "PORTUGAL", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_PUERTO_RICO, FCC1_FCCA, "PR", "PUERTO RICO", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_QATAR, NULL1_WORLD, "QA", "QATAR", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_ROMANIA, NULL1_WORLD, "RO", "ROMANIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_RUSSIA, NULL1_WORLD, "RU", "RUSSIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_SAUDI_ARABIA,NULL1_WORLD, "SA", "SAUDI ARABIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_SERBIA_MONT, ETSI1_WORLD, "CS", "SERBIA & MONTENEGRO", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_SINGAPORE, APL6_WORLD, "SG", "SINGAPORE", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_SLOVAKIA, ETSI1_WORLD, "SK", "SLOVAK REPUBLIC",YES, NO, YES, YES, YES, 7000 },
+ {CTRY_SLOVENIA, ETSI1_WORLD, "SI", "SLOVENIA", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_SOUTH_AFRICA,FCC3_WORLD, "ZA", "SOUTH AFRICA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_SPAIN, ETSI1_WORLD, "ES", "SPAIN", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_SRILANKA, FCC3_WORLD, "LK", "SRI LANKA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_SWEDEN, ETSI1_WORLD, "SE", "SWEDEN", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_SWITZERLAND, ETSI1_WORLD, "CH", "SWITZERLAND", YES, NO, YES, YES, YES, 7000 },
+ {CTRY_SYRIA, NULL1_WORLD, "SY", "SYRIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_TAIWAN, APL3_FCCA, "TW", "TAIWAN", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_THAILAND, NULL1_WORLD, "TH", "THAILAND", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_TRINIDAD_Y_TOBAGO,ETSI4_WORLD,"TT", "TRINIDAD & TOBAGO", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_TUNISIA, ETSI3_WORLD, "TN", "TUNISIA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_TURKEY, ETSI3_WORLD, "TR", "TURKEY", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_UKRAINE, NULL1_WORLD, "UA", "UKRAINE", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_UAE, NULL1_WORLD, "AE", "UNITED ARAB EMIRATES", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_UNITED_KINGDOM, ETSI1_WORLD,"GB", "UNITED KINGDOM", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_UNITED_STATES, FCC3_FCCA, "US", "UNITED STATES", YES, YES, YES, YES, YES, 5825 },
+ {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS", "UNITED STATES (PUBLIC SAFETY)", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_URUGUAY, FCC1_WORLD, "UY", "URUGUAY", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ", "UZBEKISTAN", YES, YES, YES, YES, YES, 7000 },
+ {CTRY_VENEZUELA, APL2_ETSIC, "VE", "VENEZUELA", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_VIET_NAM, NULL1_WORLD, "VN", "VIET NAM", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN", YES, NO, YES, NO, YES, 7000 },
+ {CTRY_ZIMBABWE, NULL1_WORLD, "ZW", "ZIMBABWE", YES, NO, YES, NO, YES, 7000 }
+};
+
+typedef struct RegDmnFreqBand {
+ u16_t lowChannel; /* Low channel center in MHz */
+ u16_t highChannel; /* High Channel center in MHz */
+ u8_t powerDfs; /* Max power (dBm) for channel
+ range when using DFS */
+ u8_t antennaMax; /* Max allowed antenna gain */
+ u8_t channelBW; /* Bandwidth of the channel */
+ u8_t channelSep; /* Channel separation within
+ the band */
+ u64_t useDfs; /* Use DFS in the RegDomain
+ if corresponding bit is set */
+ u64_t usePassScan; /* Use Passive Scan in the RegDomain
+ if corresponding bit is set */
+ u8_t regClassId; /* Regulatory class id */
+ u8_t useExtChanDfs; /* Regulatory class id */
+} REG_DMN_FREQ_BAND;
+
+/* Bit masks for DFS per regdomain */
+
+enum {
+ NO_DFS = 0x0000000000000000ULL,
+ DFS_FCC3 = 0x0000000000000001ULL,
+ DFS_ETSI = 0x0000000000000002ULL,
+ DFS_MKK4 = 0x0000000000000004ULL,
+};
+
+/* The table of frequency bands is indexed by a bitmask. The ordering
+ * must be consistent with the enum below. When adding a new
+ * frequency band, be sure to match the location in the enum with the
+ * comments
+ */
+
+/*
+ * 5GHz 11A channel tags
+ */
+
+enum {
+ F1_4915_4925,
+ F1_4935_4945,
+ F1_4920_4980,
+ F1_4942_4987,
+ F1_4945_4985,
+ F1_4950_4980,
+ F1_5035_5040,
+ F1_5040_5080,
+ F1_5055_5055,
+
+ F1_5120_5240,
+
+ F1_5170_5230,
+ F2_5170_5230,
+
+ F1_5180_5240,
+ F2_5180_5240,
+ F3_5180_5240,
+ F4_5180_5240,
+ F5_5180_5240,
+ F6_5180_5240,
+ F7_5180_5240,
+
+ F1_5180_5320,
+
+ F1_5240_5280,
+
+ F1_5260_5280,
+
+ F1_5260_5320,
+ F2_5260_5320,
+ F3_5260_5320,
+ F4_5260_5320,
+ F5_5260_5320,
+ F6_5260_5320,
+ F7_5260_5320,
+
+ F1_5260_5700,
+
+ F1_5280_5320,
+
+ F1_5500_5580,
+
+ F1_5500_5620,
+
+ F1_5500_5700,
+ F2_5500_5700,
+ F3_5500_5700,
+ F4_5500_5700,
+
+ F1_5660_5700,
+
+ F1_5745_5805,
+ F2_5745_5805,
+ F3_5745_5805,
+
+ F1_5745_5825,
+ F2_5745_5825,
+ F3_5745_5825,
+ F4_5745_5825,
+ F5_5745_5825,
+ F6_5745_5825,
+
+ W1_4920_4980,
+ W1_5040_5080,
+ W1_5170_5230,
+ W1_5180_5240,
+ W1_5260_5320,
+ W1_5745_5825,
+ W1_5500_5700,
+ W2_5260_5320,
+ W2_5180_5240,
+ W2_5825_5825,
+};
+
+static REG_DMN_FREQ_BAND regDmn5GhzFreq[] = {
+ { 4915, 4925, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16, 0 }, /* F1_4915_4925 */
+ { 4935, 4945, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 16, 0 }, /* F1_4935_4945 */
+ { 4920, 4980, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 7, 0 }, /* F1_4920_4980 */
+ { 4942, 4987, 27, 6, 5, 5, DFS_FCC3, PSCAN_FCC, 0, 0 }, /* F1_4942_4987 */
+ { 4945, 4985, 30, 6, 10, 5, DFS_FCC3, PSCAN_FCC, 0, 0 }, /* F1_4945_4985 */
+ { 4950, 4980, 33, 6, 20, 5, DFS_FCC3, PSCAN_FCC, 0, 0 }, /* F1_4950_4980 */
+ { 5035, 5040, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12, 0 }, /* F1_5035_5040 */
+ { 5040, 5080, 23, 0, 20, 20, NO_DFS, PSCAN_MKK2, 2, 0 }, /* F1_5040_5080 */
+ { 5055, 5055, 23, 0, 10, 5, NO_DFS, PSCAN_MKK2, 12, 0 }, /* F1_5055_5055 */
+
+ { 5120, 5240, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F1_5120_5240 */
+
+ { 5170, 5230, 23, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1, 0 }, /* F1_5170_5230 */
+ { 5170, 5230, 20, 0, 20, 20, NO_DFS, PSCAN_MKK1 | PSCAN_MKK2, 1, 0 }, /* F2_5170_5230 */
+
+ { 5180, 5240, 15, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F1_5180_5240 */
+ { 5180, 5240, 17, 6, 20, 20, NO_DFS, PSCAN_FCC, 1, 0 }, /* F2_5180_5240 */
+ { 5180, 5240, 18, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F3_5180_5240 */
+ { 5180, 5240, 20, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F4_5180_5240 */
+ { 5180, 5240, 23, 0, 20, 20, NO_DFS, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F5_5180_5240 */
+ { 5180, 5240, 23, 6, 20, 20, NO_DFS, PSCAN_FCC, 0, 0 }, /* F6_5180_5240 */
+ { 5180, 5240, 23, 6, 20, 20, NO_DFS, NO_PSCAN, 0 }, /* F7_5180_5240 */
+
+ { 5180, 5320, 20, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0, 0 }, /* F1_5180_5320 */
+
+ { 5240, 5280, 23, 0, 20, 20, DFS_FCC3, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F1_5240_5280 */
+
+ { 5260, 5280, 23, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F1_5260_5280 */
+
+ { 5260, 5320, 18, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F1_5260_5320 */
+
+ { 5260, 5320, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_FCC | PSCAN_ETSI | PSCAN_MKK3 , 0, 0 },
+ /* F2_5260_5320 */
+
+ { 5260, 5320, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2, 0 }, /* F3_5260_5320 */
+ { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 2, 0 }, /* F4_5260_5320 */
+ { 5260, 5320, 23, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0, 0 }, /* F5_5260_5320 */
+ { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F6_5260_5320 */
+ { 5260, 5320, 17, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0, 0 }, /* F7_5260_5320 */
+
+ { 5260, 5700, 5, 6, 20, 20, DFS_FCC3 | DFS_ETSI, NO_PSCAN, 0, 0 }, /* F1_5260_5700 */
+
+ { 5280, 5320, 17, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 0, 0 }, /* F1_5280_5320 */
+
+ { 5500, 5580, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0}, /* F1_5500_5580 */
+
+ { 5500, 5620, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0, 0 }, /* F1_5500_5620 */
+
+ { 5500, 5700, 20, 6, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC, 4, 0 }, /* F1_5500_5700 */
+ { 5500, 5700, 27, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F2_5500_5700 */
+ { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_FCC | PSCAN_ETSI, 0, 0 }, /* F3_5500_5700 */
+ { 5500, 5700, 20, 0, 20, 20, DFS_FCC3 | DFS_ETSI | DFS_MKK4, PSCAN_MKK3 | PSCAN_FCC, 0, 0 },
+ /* F4_5500_5700 */
+
+ { 5660, 5700, 23, 6, 20, 20, DFS_FCC3, PSCAN_FCC, 0}, /* F1_5660_5700 */
+
+ { 5745, 5805, 23, 0, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F1_5745_5805 */
+ { 5745, 5805, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F2_5745_5805 */
+ { 5745, 5805, 30, 6, 20, 20, DFS_ETSI, PSCAN_ETSI, 0, 0 }, /* F3_5745_5805 */
+ { 5745, 5825, 5, 6, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F1_5745_5825 */
+ { 5745, 5825, 17, 0, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F2_5745_5825 */
+ { 5745, 5825, 20, 0, 20, 20, DFS_ETSI, NO_PSCAN, 0, 0 }, /* F3_5745_5825 */
+ { 5745, 5825, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F4_5745_5825 */
+ { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 3, 0 }, /* F5_5745_5825 */
+ { 5745, 5825, 30, 6, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* F6_5745_5825 */
+
+ /*
+ * Below are the world roaming channels
+ * All WWR domains have no power limit, instead use the card's CTL
+ * or max power settings.
+ */
+ { 4920, 4980, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0, 0 }, /* W1_4920_4980 */
+ { 5040, 5080, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0 }, /* W1_5040_5080 */
+ { 5170, 5230, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0 }, /* W1_5170_5230 */
+ { 5180, 5240, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0 }, /* W1_5180_5240 */
+ { 5260, 5320, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0 }, /* W1_5260_5320 */
+ { 5745, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0, 0 }, /* W1_5745_5825 */
+ { 5500, 5700, 30, 0, 20, 20, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0 }, /* W1_5500_5700 */
+ { 5260, 5320, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* W2_5260_5320 */
+ { 5180, 5240, 30, 0, 20, 20, NO_DFS, NO_PSCAN, 0, 0 }, /* W2_5180_5240 */
+ { 5825, 5825, 30, 0, 20, 20, NO_DFS, PSCAN_WWR, 0, 0 }, /* W2_5825_5825 */
+};
+/*
+ * 5GHz Turbo (dynamic & static) tags
+ */
+
+enum {
+ T1_5130_5210,
+ T1_5250_5330,
+ T1_5370_5490,
+ T1_5530_5650,
+
+ T1_5150_5190,
+ T1_5230_5310,
+ T1_5350_5470,
+ T1_5510_5670,
+
+ T1_5200_5240,
+ T2_5200_5240,
+ T1_5210_5210,
+ T2_5210_5210,
+
+ T1_5280_5280,
+ T2_5280_5280,
+ T1_5250_5250,
+ T1_5290_5290,
+ T1_5250_5290,
+ T2_5250_5290,
+
+ T1_5540_5660,
+ T1_5760_5800,
+ T2_5760_5800,
+
+ T1_5765_5805,
+
+ WT1_5210_5250,
+ WT1_5290_5290,
+ WT1_5540_5660,
+ WT1_5760_5800,
+};
+
+static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = {
+ { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5130_5210 */
+ { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5250_5330 */
+ { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5370_5490 */
+ { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5530_5650 */
+
+ { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5150_5190 */
+ { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5230_5310 */
+ { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5350_5470 */
+ { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5510_5670 */
+
+ { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5200_5240 */
+ { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_5200_5240 */
+ { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5210_5210 */
+ { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_5210_5210 */
+
+ { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5280_5280 */
+ { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T2_5280_5280 */
+ { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5250_5250 */
+ { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5290_5290 */
+ { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5250_5290 */
+ { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T2_5250_5290 */
+
+ { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5540_5660 */
+ { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5760_5800 */
+ { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_5760_5800 */
+
+ { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5765_5805 */
+
+ /*
+ * Below are the WWR frequencies
+ */
+
+ { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5210_5250 */
+ { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5290_5290 */
+ { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5540_5660 */
+ { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0, 0}, /* WT1_5760_5800 */
+};
+
+/*
+ * 2GHz 11b channel tags
+ */
+enum {
+ F1_2312_2372,
+ F2_2312_2372,
+
+ F1_2412_2472,
+ F2_2412_2472,
+ F3_2412_2472,
+
+ F1_2412_2462,
+ F2_2412_2462,
+
+ F1_2432_2442,
+
+ F1_2457_2472,
+
+ F1_2467_2472,
+
+ F1_2484_2484,
+ F2_2484_2484,
+
+ F1_2512_2732,
+
+ W1_2312_2372,
+ W1_2412_2412,
+ W1_2417_2432,
+ W1_2437_2442,
+ W1_2447_2457,
+ W1_2462_2462,
+ W1_2467_2467,
+ W2_2467_2467,
+ W1_2472_2472,
+ W2_2472_2472,
+ W1_2484_2484,
+ W2_2484_2484,
+};
+
+static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = {
+ { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2312_2372 */
+ { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F2_2312_2372 */
+
+ { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2412_2472 */
+ { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0, 0}, /* F2_2412_2472 */
+ { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F3_2412_2472 */
+
+ { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2412_2462 */
+ { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0, 0}, /* F2_2412_2462 */
+ { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2432_2442 */
+
+ { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2457_2472 */
+
+ { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0, 0}, /* F1_2467_2472 */
+
+ { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2484_2484 */
+ { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0, 0}, /* F2_2484_2484 */
+
+ { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2512_2732 */
+
+ /*
+ * WWR have powers opened up to 20dBm. Limits should often come from CTL/Max powers
+ */
+
+ { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2312_2372 */
+ { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2412_2412 */
+ { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2417_2432 */
+ { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2437_2442 */
+ { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2447_2457 */
+ { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2462_2462 */
+ { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2467_2467 */
+ { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* W2_2467_2467 */
+ { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2472_2472 */
+ { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* W2_2472_2472 */
+ { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2484_2484 */
+ { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* W2_2484_2484 */
+};
+
+
+/*
+ * 2GHz 11g channel tags
+ */
+
+enum {
+ G1_2312_2372,
+ G2_2312_2372,
+
+ G1_2412_2472,
+ G2_2412_2472,
+ G3_2412_2472,
+
+ G1_2412_2462,
+ G2_2412_2462,
+
+ G1_2432_2442,
+
+ G1_2457_2472,
+
+ G1_2512_2732,
+
+ G1_2467_2472 ,
+
+ WG1_2312_2372,
+ WG1_2412_2412,
+ WG1_2417_2432,
+ WG1_2437_2442,
+ WG1_2447_2457,
+ WG1_2462_2462,
+ WG1_2467_2467,
+ WG2_2467_2467,
+ WG1_2472_2472,
+ WG2_2472_2472,
+
+};
+static REG_DMN_FREQ_BAND regDmn2Ghz11gFreq[] = {
+ { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G1_2312_2372 */
+ { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G2_2312_2372 */
+
+ { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G1_2412_2472 */
+ { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0, 0}, /* G2_2412_2472 */
+ { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G3_2412_2472 */
+
+ { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G1_2412_2462 */
+ { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA_G, 0, 0}, /* G2_2412_2462 */
+ { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G1_2432_2442 */
+
+ { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G1_2457_2472 */
+
+ { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* G1_2512_2732 */
+
+ { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0, 0 }, /* G1_2467_2472 */
+
+ /*
+ * WWR open up the power to 20dBm
+ */
+
+ { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* WG1_2312_2372 */
+ { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* WG1_2412_2412 */
+ { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* WG1_2417_2432 */
+ { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* WG1_2437_2442 */
+ { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* WG1_2447_2457 */
+ { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* WG1_2462_2462 */
+ { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* WG1_2467_2467 */
+ { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* WG2_2467_2467 */
+ { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* WG1_2472_2472 */
+ { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* WG2_2472_2472 */
+};
+/*
+ * 2GHz Dynamic turbo tags
+ */
+
+enum {
+ T1_2312_2372,
+ T1_2437_2437,
+ T2_2437_2437,
+ T3_2437_2437,
+ T1_2512_2732
+};
+
+static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = {
+ { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_2312_2372 */
+ { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_2437_2437 */
+ { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_2437_2437 */
+ { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0, 0}, /* T3_2437_2437 */
+ { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_2512_2732 */
+};
+
+
+
+/*
+ * 2GHz 11n frequency tags
+ */
+enum {
+ NG1_2422_2452,
+ NG2_2422_2452,
+ NG3_2422_2452,
+
+ NG_DEMO_ALL_CHANNELS,
+};
+
+static REG_DMN_FREQ_BAND regDmn2Ghz11ngFreq[] = {
+ { 2422, 2452, 20, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG1_2422_2452 */
+ { 2422, 2452, 27, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG2_2422_2452 */
+ { 2422, 2452, 30, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG3_2422_2452 */
+
+ { 2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG_DEMO_ALL_CHANNELS */
+};
+
+
+/*
+ * 5GHz 11n frequency tags
+ */
+enum {
+ NA1_5190_5230,
+ NA2_5190_5230,
+ NA3_5190_5230,
+ NA4_5190_5230,
+ NA5_5190_5230,
+
+ NA1_5270_5270,
+
+ NA1_5270_5310,
+ NA2_5270_5310,
+ NA3_5270_5310,
+ NA4_5270_5310,
+
+ NA1_5310_5310,
+
+ NA1_5510_5630,
+
+ NA1_5510_5670,
+ NA2_5510_5670,
+ NA3_5510_5670,
+
+ NA1_5755_5795,
+ NA2_5755_5795,
+ NA3_5755_5795,
+ NA4_5755_5795,
+ NA5_5755_5795,
+
+ NA1_5795_5795,
+
+ NA_DEMO_ALL_CHANNELS,
+};
+
+static REG_DMN_FREQ_BAND regDmn5Ghz11naFreq[] = {
+ /*
+ * ToDo: This table needs to be completely populated with 5GHz 11n properties
+ */
+ { 5190, 5230, 15, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA1_5190_5230 */
+ { 5190, 5230, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA2_5190_5230 */
+ { 5190, 5230, 18, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA3_5190_5230 */
+ { 5190, 5230, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA4_5190_5230 */
+ { 5190, 5230, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA5_5190_5230 */
+
+ { 5270, 5270, 23, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5270_5270 */
+
+ { 5270, 5310, 18, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5270_5310 */
+ { 5270, 5310, 20, 0, 40, 40, DFS_FCC3|DFS_ETSI|DFS_MKK4, NO_PSCAN, 0, 1}, /* NA2_5270_5310 */
+ { 5270, 5310, 23, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA3_5270_5310 */
+ { 5270, 5310, 30, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA4_5270_5310 */
+
+ { 5310, 5310, 17, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5310_5310 */
+
+ { 5510, 5630, 30, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5510_5630 */
+
+ { 5510, 5670, 20, 6, 40, 40, DFS_FCC3|DFS_ETSI|DFS_MKK4, NO_PSCAN, 0, 1}, /* NA1_5510_5670 */
+ { 5510, 5670, 27, 0, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA2_5510_5670 */
+ { 5510, 5670, 30, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 1}, /* NA3_5510_5670 */
+
+ { 5755, 5795, 17, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA1_5755_5795 */
+ { 5755, 5795, 20, 6, 40, 40, DFS_ETSI, NO_PSCAN, 0, 0}, /* NA2_5755_5795 */
+ { 5755, 5795, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA3_5755_5795 */
+ { 5755, 5795, 30, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA4_5755_5795 */
+ { 5755, 5795, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA5_5755_5795 */
+
+ { 5795, 5795, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA1_5795_5795 */
+
+ { 4920, 6100, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA_DEMO_ALL_CHANNELS */
+};
+
+typedef struct regDomain {
+ u16_t regDmnEnum; /* value from EnumRd table */
+ u8_t conformanceTestLimit;
+ u64_t dfsMask; /* DFS bitmask for 5Ghz tables */
+ u64_t pscan; /* Bitmask for passive scan */
+ u32_t flags; /* Requirement flags (AdHoc disallow, noise
+ floor cal needed, etc) */
+ u64_t chan11a[BMLEN];/* 128 bit bitmask for channel/band
+ selection */
+ u64_t chan11a_turbo[BMLEN];/* 128 bit bitmask for channel/band
+ selection */
+ u64_t chan11a_dyn_turbo[BMLEN]; /* 128 bit bitmask for channel/band
+ selection */
+ u64_t chan11b[BMLEN];/* 128 bit bitmask for channel/band
+ selection */
+ u64_t chan11g[BMLEN];/* 128 bit bitmask for channel/band
+ selection */
+ u64_t chan11g_turbo[BMLEN];/* 128 bit bitmask for channel/band
+ selection */
+ u64_t chan11ng[BMLEN];/* 128 bit bitmask for 11n in 2GHz */
+ u64_t chan11na[BMLEN];/* 128 bit bitmask for 11n in 5GHz */
+} REG_DOMAIN;
+
+static REG_DOMAIN regDomains[] = {
+
+ {DEBUG_REG_DMN, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F1_5120_5240, F1_5260_5700, F1_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T1_5130_5210, T1_5250_5330, T1_5370_5490, T1_5530_5650, T1_5150_5190, T1_5230_5310, T1_5350_5470, T1_5510_5670, -1, -1, -1, -1),
+ BM(T1_5200_5240, T1_5280_5280, T1_5540_5660, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(F1_2312_2372, F1_2412_2472, F1_2484_2484, F1_2512_2732, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(G1_2312_2372, G1_2412_2472, G1_2512_2732, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T1_2312_2372, T1_2437_2437, T1_2512_2732, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(NG_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(NA_DEMO_ALL_CHANNELS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL1, ETSI, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL2, ETSI, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F1_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA3_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL3, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F1_5280_5320, F2_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA1_5310_5310, NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL4, ETSI, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F4_5180_5240, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL5, ETSI, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F2_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA1_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL6, ETSI, DFS_ETSI, PSCAN_FCC_T | PSCAN_FCC , NO_REQ,
+ BM(F4_5180_5240, F2_5260_5320, F3_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T2_5210_5210, T1_5250_5290, T1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, NA2_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL7, FCC, NO_DFS, PSCAN_FCC_T | PSCAN_FCC , NO_REQ,
+ BM(F7_5260_5320, F4_5500_5700, F3_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA1_5310_5310, NA2_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+ {APL8, ETSI, NO_DFS, NO_PSCAN, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
+ BM(F6_5260_5320, F4_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5270_5310, NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {APL9, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A|DISALLOW_ADHOC_11A_TURB,
+ BM(F1_5180_5320, F1_5500_5620, F3_5745_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, NA1_5510_5630, NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSI1, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BM(W2_5180_5240, F2_5260_5320, F2_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, NA2_5510_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSI2, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BM(F3_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA3_5190_5230, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSI3, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BM(W2_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSI4, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BM(F3_5180_5240, F1_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA3_5190_5230, NA1_5270_5310, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSI5, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BM(F1_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA1_5190_5230, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {ETSI6, ETSI, DFS_ETSI, PSCAN_ETSI, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BM(F5_5180_5240, F1_5260_5280, F3_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA5_5190_5230, NA1_5270_5270, NA3_5510_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {FCC1, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F2_5180_5240, F4_5260_5320, F5_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T1_5210_5210, T2_5250_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T1_5200_5240, T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA2_5190_5230, NA3_5270_5310, NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {FCC2, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F6_5180_5240, F5_5260_5320, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T2_5200_5240, T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA5_5190_5230, NA3_5270_5310, NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {FCC3, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ,
+ BM(F2_5180_5240, F3_5260_5320, F1_5500_5700, F5_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T1_5210_5210, T1_5250_5250, T1_5290_5290, T2_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T1_5200_5240, T2_5280_5280, T1_5540_5660, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA2_5190_5230, NA2_5270_5310, NA3_5510_5670, NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {FCC4, FCC, DFS_FCC3, PSCAN_FCC | PSCAN_FCC_T, NO_REQ,
+ BM(F1_4942_4987, F1_4945_4985, F1_4950_4980, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {FCC5, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ BM(F2_5180_5240, F5_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA2_5190_5230, NA4_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {FCC6, FCC, DFS_FCC3, PSCAN_FCC, NO_REQ,
+ BM(F7_5180_5240, F5_5260_5320, F1_5500_5580, F1_5660_5700, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1),
+ BM(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T2_5200_5240, T1_5280_5280, T1_5765_5805, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA5_5190_5230, NA5_5755_5795, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ {MKK1, MKK, NO_DFS, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
+ BM(F1_5170_5230, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {MKK2, MKK, NO_DFS, PSCAN_MKK2, DISALLOW_ADHOC_11A_TURB,
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F1_5170_5230, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ /* UNI-1 even */
+ {MKK3, MKK, NO_DFS, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ BM(F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ /* UNI-1 even + UNI-2 */
+ {MKK4, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ BM(F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ /* UNI-1 even + UNI-2 + mid-band */
+ {MKK5, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ BM(F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, NA1_5510_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ /* UNI-1 odd + even */
+ {MKK6, MKK, DFS_MKK4, PSCAN_MKK1, DISALLOW_ADHOC_11A_TURB,
+ BM(F2_5170_5230, F4_5180_5240, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ /* UNI-1 odd + UNI-1 even + UNI-2 */
+ {MKK7, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3 , DISALLOW_ADHOC_11A_TURB,
+ BM(F2_5170_5230, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ /* UNI-1 odd + UNI-1 even + UNI-2 + mid-band */
+ {MKK8, MKK, DFS_MKK4, PSCAN_MKK1 | PSCAN_MKK3 , DISALLOW_ADHOC_11A_TURB,
+ BM(F2_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(NA4_5190_5230, NA2_5270_5310, NA1_5510_5670, -1, -1, -1, -1, -1, -1, -1, -1, -1)},
+
+ /* UNI-1 even + 4.9 GHZ */
+ {MKK9, MKK, NO_DFS, NO_PSCAN, DISALLOW_ADHOC_11A_TURB,
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F4_5180_5240, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ /* UNI-1 even + UNI-2 + 4.9 GHZ */
+ {MKK10, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ /* UNI-1 even + UNI-2 + 4.9 GHZ + mid-band */
+ {MKK11, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ /* UNI-1 even + UNI-1 odd + UNI-2 + 4.9 GHZ + mid-band */
+ {MKK12, MKK, DFS_MKK4, PSCAN_MKK3, DISALLOW_ADHOC_11A_TURB,
+ BM(F1_4915_4925, F1_4935_4945, F1_4920_4980, F1_5035_5040, F1_5055_5055, F1_5040_5080, F1_5170_5230, F4_5180_5240, F2_5260_5320, F4_5500_5700, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ /* Defined here to use when 2G channels are authorised for country K2 */
+ {APLD, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F2_2312_2372,F2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(G2_2312_2372,G2_2412_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BMZERO},
+
+ {ETSIA, NO_CTL, NO_DFS, PSCAN_ETSIA, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F1_2457_2472,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(G1_2457_2472,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {ETSIB, ETSI, NO_DFS, PSCAN_ETSIB, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F1_2432_2442,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(G1_2432_2442,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {ETSIC, ETSI, NO_DFS, PSCAN_ETSIC, DISALLOW_ADHOC_11A | DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F3_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(G3_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {FCCA, FCC, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F1_2412_2462,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(G1_2412_2462,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(NG2_2422_2452,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO},
+
+ {MKKA, MKK, NO_DFS, PSCAN_MKKA | PSCAN_MKKA_G | PSCAN_MKKA1 | PSCAN_MKKA1_G | PSCAN_MKKA2 | PSCAN_MKKA2_G, DISALLOW_ADHOC_11A_TURB,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F2_2412_2462, F1_2467_2472, F2_2484_2484, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(G2_2412_2462, G1_2467_2472, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(NG1_2422_2452,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO},
+
+ {MKKC, MKK, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(G2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(NG1_2422_2452,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO},
+
+ {WORLD, ETSI, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BM(F2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(G2_2412_2472,-1,-1,-1,-1,-1,-1,-1, -1, -1, -1, -1),
+ BM(T2_2437_2437,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(NG1_2422_2452,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO},
+
+ {WOR0_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1),
+ BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR01_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG1_2417_2432, WG1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR02_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ BM(W1_5260_5320, W1_5180_5240,W1_5170_5230,W1_5745_5825,W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412,W1_2437_2442,W1_2462_2462, W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462, WG1_2472_2472,WG1_2417_2432, WG1_2447_2457, WG1_2467_2467, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {EU1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ BM(W1_5260_5320, W1_5180_5240,W1_5170_5230,W1_5745_5825,W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412,W1_2437_2442,W1_2462_2462, W2_2472_2472,W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462, WG2_2472_2472,WG1_2417_2432, WG1_2447_2457, WG2_2467_2467, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR1_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1),
+ BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR2_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, W1_2484_2484, -1, -1, -1, -1),
+ BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR3_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_PER_11D,
+ BM(W1_5260_5320, W1_5180_5240, W1_5170_5230, W1_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412,W1_2437_2442,W1_2462_2462,W1_2472_2472,W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462,WG1_2472_2472,WG1_2417_2432,WG1_2447_2457,WG1_2467_2467,-1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR4_WORLD, NO_CTL, DFS_FCC3, PSCAN_WWR, ADHOC_NO_11A,
+ BM(W2_5260_5320, W2_5180_5240, F2_5745_5805, W2_5825_5825, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412,W1_2437_2442,W1_2462_2462, W1_2417_2432,W1_2447_2457,-1, -1, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412,WG1_2437_2442,WG1_2462_2462, WG1_2417_2432,WG1_2447_2457,-1, -1, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR5_ETSIC, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ BM(W1_5260_5320, W2_5180_5240, F6_5745_5825, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W2_2472_2472, W1_2417_2432, W1_2447_2457, W2_2467_2467, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG1_2472_2472, WG1_2417_2432, WG1_2447_2457, WG1_2467_2467, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WOR9_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1),
+ BM(WT1_5210_5250, WT1_5290_5290, WT1_5760_5800, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2417_2432, W1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG1_2417_2432, WG1_2447_2457, -1, -1, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {WORA_WORLD, NO_CTL, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, ADHOC_NO_11A,
+ BM(W1_5260_5320, W1_5180_5240, W1_5745_5825, W1_5500_5700, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO,
+ BM(W1_2412_2412, W1_2437_2442, W1_2462_2462, W1_2472_2472, W1_2417_2432, W1_2447_2457, W1_2467_2467, -1, -1, -1, -1, -1),
+ BM(WG1_2412_2412, WG1_2437_2442, WG1_2462_2462, WG1_2472_2472, WG1_2417_2432, WG1_2447_2457, WG1_2467_2467, -1, -1, -1, -1, -1),
+ BM(T3_2437_2437, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1),
+ BMZERO,
+ BMZERO},
+
+ {NULL1, NO_CTL, NO_DFS, NO_PSCAN, NO_REQ,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO,
+ BMZERO},
+};
+
+struct cmode {
+ u16_t mode;
+ u32_t flags;
+};
+
+static const struct cmode modes[] = {
+ { HAL_MODE_TURBO, CHANNEL_ST}, /* TURBO means 11a Static Turbo */
+ { HAL_MODE_11A, CHANNEL_A},
+ { HAL_MODE_11B, CHANNEL_B},
+ { HAL_MODE_11G, CHANNEL_G},
+ { HAL_MODE_11G_TURBO, CHANNEL_108G},
+ { HAL_MODE_11A_TURBO, CHANNEL_108A},
+ { HAL_MODE_11NA, CHANNEL_A_HT40},
+ { HAL_MODE_11NA, CHANNEL_A_HT20},
+ { HAL_MODE_11NG, CHANNEL_G_HT40},
+ { HAL_MODE_11NG, CHANNEL_G_HT20},
+};
+
+/*
+ * Return the Wireless Mode Regulatory Domain based
+ * on the country code and the wireless mode.
+ */
+u8_t GetWmRD(u16_t regionCode, u16_t channelFlag, REG_DOMAIN *rd)
+{
+ s16_t i, found, regDmn;
+ u64_t flags=NO_REQ;
+ REG_DMN_PAIR_MAPPING *regPair=NULL;
+
+ for (i=0, found=0; (i<N(regDomainPairs))&&(!found); i++)
+ {
+ if (regDomainPairs[i].regDmnEnum == regionCode)
+ {
+ regPair = &regDomainPairs[i];
+ found = 1;
+ }
+ }
+ if (!found)
+ {
+ zm_debug_msg1("Failed to find reg domain pair ", regionCode);
+ return FALSE;
+ }
+
+ if (channelFlag & ZM_REG_FLAG_CHANNEL_2GHZ)
+ {
+ regDmn = regPair->regDmn2GHz;
+ flags = regPair->flags2GHz;
+ }
+ else
+ {
+ regDmn = regPair->regDmn5GHz;
+ flags = regPair->flags5GHz;
+ }
+
+ /*
+ * We either started with a unitary reg domain or we've found the
+ * unitary reg domain of the pair
+ */
+
+ for (i=0;i<N(regDomains); i++)
+ {
+ if (regDomains[i].regDmnEnum == regDmn)
+ {
+ if (rd != NULL)
+ {
+ zfMemoryCopy((u8_t *)rd, (u8_t *)&regDomains[i],
+ sizeof(REG_DOMAIN));
+ }
+ }
+ }
+ rd->pscan &= regPair->pscanMask;
+ rd->flags = (u32_t)flags;
+ return TRUE;
+}
+
+/*
+ * Test to see if the bitmask array is all zeros
+ */
+u8_t isChanBitMaskZero(u64_t *bitmask)
+{
+ u16_t i;
+
+ for (i=0; i<BMLEN; i++) {
+ if (bitmask[i] != 0)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+u8_t IS_BIT_SET(u32_t bit, u64_t *bitmask)
+{
+ u32_t byteOffset, bitnum;
+ u64_t val;
+
+ byteOffset = bit/64;
+ bitnum = bit - byteOffset*64;
+ val = ((u64_t) 1) << bitnum;
+ if (bitmask[byteOffset] & val)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+void zfHpGetRegulationTable(zdev_t* dev, u16_t regionCode, u16_t c_lo, u16_t c_hi)
+{
+ REG_DOMAIN rd5GHz, rd2GHz;
+ const struct cmode *cm;
+ s16_t next=0,b;
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zmw_declare_for_critical_section();
+
+ if (!GetWmRD(regionCode, ~ZM_REG_FLAG_CHANNEL_2GHZ, &rd5GHz))
+ {
+ zm_debug_msg1("couldn't find unitary 5GHz reg domain for Region Code ", regionCode);
+ return;
+ }
+ if (!GetWmRD(regionCode, ZM_REG_FLAG_CHANNEL_2GHZ, &rd2GHz))
+ {
+ zm_debug_msg1("couldn't find unitary 2GHz reg domain for Region Code ", regionCode);
+ return;
+ }
+ if (wd->regulationTable.regionCode == regionCode)
+ {
+ zm_debug_msg1("current region code is the same with Region Code ", regionCode);
+ return;
+ }
+ else
+ {
+ wd->regulationTable.regionCode = regionCode;
+ }
+
+ next = 0;
+
+ zmw_enter_critical_section(dev);
+
+ for (cm = modes; cm < &modes[N(modes)]; cm++)
+ {
+ u16_t c;
+ u64_t *channelBM=NULL;
+ REG_DOMAIN *rd=NULL;
+ REG_DMN_FREQ_BAND *fband=NULL,*freqs=NULL;
+
+ switch (cm->mode)
+ {
+ case HAL_MODE_TURBO:
+ //we don't have turbo mode so we disable it
+ //zm_debug_msg0("CWY - HAL_MODE_TURBO");
+ channelBM = NULL;
+ //rd = &rd5GHz;
+ //channelBM = rd->chan11a_turbo;
+ //freqs = &regDmn5GhzTurboFreq[0];
+ //ctl = rd->conformanceTestLimit | CTL_TURBO;
+ break;
+ case HAL_MODE_11A:
+ if ((hpPriv->OpFlags & 0x1) != 0)
+ {
+ rd = &rd5GHz;
+ channelBM = rd->chan11a;
+ freqs = &regDmn5GhzFreq[0];
+ c_lo = 4920; //from channel 184
+ c_hi = 5825; //to channel 165
+ //ctl = rd->conformanceTestLimit;
+ //zm_debug_msg2("CWY - HAL_MODE_11A, channelBM = 0x", *channelBM);
+ }
+ //else
+ {
+ //channelBM = NULL;
+ }
+ break;
+ case HAL_MODE_11B:
+ //Disable 11B mode because it only has difference with 11G in PowerDFS Data,
+ //and we don't use this now.
+ //zm_debug_msg0("CWY - HAL_MODE_11B");
+ channelBM = NULL;
+ //rd = &rd2GHz;
+ //channelBM = rd->chan11b;
+ //freqs = &regDmn2GhzFreq[0];
+ //ctl = rd->conformanceTestLimit | CTL_11B;
+ //zm_debug_msg2("CWY - HAL_MODE_11B, channelBM = 0x", *channelBM);
+ break;
+ case HAL_MODE_11G:
+ if ((hpPriv->OpFlags & 0x2) != 0)
+ {
+ rd = &rd2GHz;
+ channelBM = rd->chan11g;
+ freqs = &regDmn2Ghz11gFreq[0];
+ c_lo = 2412; //from channel 1
+ //c_hi = 2462; //to channel 11
+ c_hi = 2472; //to channel 13
+ //ctl = rd->conformanceTestLimit | CTL_11G;
+ //zm_debug_msg2("CWY - HAL_MODE_11G, channelBM = 0x", *channelBM);
+ }
+ //else
+ {
+ //channelBM = NULL;
+ }
+ break;
+ case HAL_MODE_11G_TURBO:
+ //we don't have turbo mode so we disable it
+ //zm_debug_msg0("CWY - HAL_MODE_11G_TURBO");
+ channelBM = NULL;
+ //rd = &rd2GHz;
+ //channelBM = rd->chan11g_turbo;
+ //freqs = &regDmn2Ghz11gTurboFreq[0];
+ //ctl = rd->conformanceTestLimit | CTL_108G;
+ break;
+ case HAL_MODE_11A_TURBO:
+ //we don't have turbo mode so we disable it
+ //zm_debug_msg0("CWY - HAL_MODE_11A_TURBO");
+ channelBM = NULL;
+ //rd = &rd5GHz;
+ //channelBM = rd->chan11a_dyn_turbo;
+ //freqs = &regDmn5GhzTurboFreq[0];
+ //ctl = rd->conformanceTestLimit | CTL_108G;
+ break;
+ default:
+ zm_debug_msg1("Unkonwn HAL mode ", cm->mode);
+ continue;
+ }
+ if (channelBM == NULL)
+ {
+ //zm_debug_msg0("CWY - channelBM is NULL");
+ continue;
+ }
+ if (isChanBitMaskZero(channelBM))
+ {
+ //zm_debug_msg0("CWY - BitMask is Zero");
+ continue;
+ }
+
+ // RAY:Is it ok??
+ if (freqs == NULL )
+ {
+ continue;
+ }
+
+ for (b=0;b<64*BMLEN; b++)
+ {
+ if (IS_BIT_SET(b,channelBM))
+ {
+ fband = &freqs[b];
+
+ //zm_debug_msg1("CWY - lowChannel = ", fband->lowChannel);
+ //zm_debug_msg1("CWY - highChannel = ", fband->highChannel);
+ //zm_debug_msg1("CWY - channelSep = ", fband->channelSep);
+ for (c=fband->lowChannel; c <= fband->highChannel;
+ c += fband->channelSep)
+ {
+ ZM_HAL_CHANNEL icv;
+
+ //Disable all DFS channel
+ if ((hpPriv->disableDfsCh==0) || (!(fband->useDfs & rd->dfsMask)))
+ {
+ if( fband->channelBW < 20 )
+ {
+ /**************************************************************/
+ /* */
+ /* Temporary discard channel that BW < 20MHz (5 or 10MHz) */
+ /* Our architecture does not implemnt it !!! */
+ /* */
+ /**************************************************************/
+ continue;
+ }
+ if ((c >= c_lo) && (c <= c_hi))
+ {
+ icv.channel = c;
+ icv.channelFlags = cm->flags;
+ icv.maxRegTxPower = fband->powerDfs;
+ if (fband->usePassScan & rd->pscan)
+ icv.channelFlags |= ZM_REG_FLAG_CHANNEL_PASSIVE;
+ else
+ icv.channelFlags &= ~ZM_REG_FLAG_CHANNEL_PASSIVE;
+ if (fband->useDfs & rd->dfsMask)
+ icv.privFlags = ZM_REG_FLAG_CHANNEL_DFS;
+ else
+ icv.privFlags = 0;
+
+ /* For now disable radar for FCC3 */
+ if (fband->useDfs & rd->dfsMask & DFS_FCC3)
+ {
+ icv.privFlags &= ~ZM_REG_FLAG_CHANNEL_DFS;
+ icv.privFlags |= ZM_REG_FLAG_CHANNEL_DFS_CLEAR;
+ }
+
+ if(rd->flags & LIMIT_FRAME_4MS)
+ icv.privFlags |= ZM_REG_FLAG_CHANNEL_DFS_CLEAR;
+
+ icv.minTxPower = 0;
+ icv.maxTxPower = 0;
+
+ zm_assert(next < 60);
+
+ wd->regulationTable.allowChannel[next++] = icv;
+ }
+ }
+ }
+ }
+ }
+ }
+ wd->regulationTable.allowChannelCnt = next;
+
+ #if 0
+ {
+ /* debug print */
+ u32_t i;
+ DbgPrint("\n-------------------------------------------\n");
+ DbgPrint("zfHpGetRegulationTable print all channel info regincode = 0x%x\n", wd->regulationTable.regionCode);
+ DbgPrint("index channel channelFlags maxRegTxPower privFlags useDFS\n");
+
+ for (i=0; i<wd->regulationTable.allowChannelCnt; i++)
+ {
+ DbgPrint("%02d %d %04x %02d %x %x\n",
+ i,
+ wd->regulationTable.allowChannel[i].channel,
+ wd->regulationTable.allowChannel[i].channelFlags,
+ wd->regulationTable.allowChannel[i].maxRegTxPower,
+ wd->regulationTable.allowChannel[i].privFlags,
+ wd->regulationTable.allowChannel[i].privFlags & ZM_REG_FLAG_CHANNEL_DFS);
+ }
+ }
+ #endif
+
+ zmw_leave_critical_section(dev);
+}
+
+void zfHpGetRegulationTablefromRegionCode(zdev_t* dev, u16_t regionCode)
+{
+ u16_t c_lo = 2000, c_hi = 6000; //default channel is all enable
+ u8_t isoName[3] = {'N', 'A', 0};
+
+ zfCoreSetIsoName(dev, isoName);
+
+ zfHpGetRegulationTable(dev, regionCode, c_lo, c_hi);
+}
+
+void zfHpGetRegulationTablefromCountry(zdev_t* dev, u16_t CountryCode)
+{
+ u16_t i;
+ u16_t c_lo = 2000, c_hi = 6000; //default channel is all enable
+ u16_t RegDomain;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ for (i = 0; i < N(allCountries); i++)
+ {
+ if (CountryCode == allCountries[i].countryCode)
+ {
+ RegDomain = allCountries[i].regDmnEnum;
+
+ // read the ACU country code from EEPROM
+ zfCoreSetIsoName(dev, (u8_t*)allCountries[i].isoName);
+
+ //zm_debug_msg_s("CWY - Country Name = ", allCountries[i].name);
+
+ if (wd->regulationTable.regionCode != RegDomain)
+ {
+ //zm_debug_msg0("CWY - Change regulatory table");
+
+ zfHpGetRegulationTable(dev, RegDomain, c_lo, c_hi);
+ }
+ return;
+ }
+ }
+ zm_debug_msg1("Invalid CountryCode = ", CountryCode);
+}
+
+u8_t zfHpGetRegulationTablefromISO(zdev_t* dev, u8_t *countryInfo, u8_t length)
+{
+ u16_t i;
+ u16_t RegDomain;
+ u16_t c_lo = 2000, c_hi = 6000; //default channel is all enable
+ //u8_t strLen = 2;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if (countryInfo[4] != 0x20)
+ { // with (I)ndoor/(O)utdoor info
+ //strLen = 3;
+ }
+ //zm_debug_msg_s("Desired iso name = ", isoName);
+ for (i = 0; i < N(allCountries); i++)
+ {
+ //zm_debug_msg_s("Current iso name = ", allCountries[i].isoName);
+ if (zfMemoryIsEqual((u8_t *)allCountries[i].isoName, (u8_t *)&countryInfo[2], length-1))
+ {
+ //DbgPrint("Set current iso name = %s\n", allCountries[i].isoName);
+ //zm_debug_msg0("iso name hit!!");
+
+ RegDomain = allCountries[i].regDmnEnum;
+
+ if (wd->regulationTable.regionCode != RegDomain)
+ {
+ zfHpGetRegulationTable(dev, RegDomain, c_lo, c_hi);
+ }
+
+ //while (index < (countryInfo[1]+2))
+ //{
+ // if (countryInfo[index] <= 14)
+ // {
+ // /* calculate 2.4GHz low boundary channel frequency */
+ // ch = countryInfo[index];
+ // if ( ch == 14 )
+ // c_lo = ZM_CH_G_14;
+ // else
+ // c_lo = ZM_CH_G_1 + (ch - 1) * 5;
+ // /* calculate 2.4GHz high boundary channel frequency */
+ // ch = countryInfo[index] + countryInfo[index + 1] - 1;
+ // if ( ch == 14 )
+ // c_hi = ZM_CH_G_14;
+ // else
+ // c_hi = ZM_CH_G_1 + (ch - 1) * 5;
+ // }
+ // else
+ // {
+ // /* calculate 5GHz low boundary channel frequency */
+ // ch = countryInfo[index];
+ // if ( (ch >= 184)&&(ch <= 196) )
+ // c_lo = 4000 + ch*5;
+ // else
+ // c_lo = 5000 + ch*5;
+ // /* calculate 5GHz high boundary channel frequency */
+ // ch = countryInfo[index] + countryInfo[index + 1] - 1;
+ // if ( (ch >= 184)&&(ch <= 196) )
+ // c_hi = 4000 + ch*5;
+ // else
+ // c_hi = 5000 + ch*5;
+ // }
+ //
+ // zfHpGetRegulationTable(dev, RegDomain, c_lo, c_hi);
+ //
+ // index+=3;
+ //}
+
+ return 0;
+ }
+ }
+ //zm_debug_msg_s("Invalid iso name = ", &countryInfo[2]);
+ return 1;
+}
+
+const char* zfHpGetisoNamefromregionCode(zdev_t* dev, u16_t regionCode)
+{
+ u16_t i;
+
+ for (i = 0; i < N(allCountries); i++)
+ {
+ if (allCountries[i].regDmnEnum == regionCode)
+ {
+ return allCountries[i].isoName;
+ }
+ }
+ /* no matching item, return default */
+ return allCountries[0].isoName;
+}
+
+u16_t zfHpGetRegionCodeFromIsoName(zdev_t* dev, u8_t *countryIsoName)
+{
+ u16_t i;
+ u16_t regionCode;
+
+ /* if no matching item, return default */
+ regionCode = DEF_REGDMN;
+
+ for (i = 0; i < N(allCountries); i++)
+ {
+ if (zfMemoryIsEqual((u8_t *)allCountries[i].isoName, countryIsoName, 2))
+ {
+ regionCode = allCountries[i].regDmnEnum;
+ break;
+ }
+ }
+
+ return regionCode;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfHpDeleteAllowChannel */
+/* Delete Allow Channel. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* freq : frequency */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Chao-Wen Yang ZyDAS Technology Corporation 2007.3 */
+/* */
+/************************************************************************/
+u16_t zfHpDeleteAllowChannel(zdev_t* dev, u16_t freq)
+{
+ u16_t i, bandIndex = 0;
+ u16_t dfs5GBand[][2] = {{5150, 5240}, {5260, 5350}, {5450, 5700}, {5725, 5825}};
+
+ zmw_get_wlan_dev(dev);
+ /* Find which band does this frequency belong */
+ for (i = 0; i < 4; i++)
+ {
+ if ((freq >= dfs5GBand[i][0]) && (freq <= dfs5GBand[i][1]))
+ bandIndex = i + 1;
+ }
+
+ if (bandIndex == 0)
+ {
+ /* 2.4G, don't care */
+ return 0;
+ }
+ else
+ {
+ bandIndex--;
+ }
+ /* Set all channels in this band to passive scan */
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if ((wd->regulationTable.allowChannel[i].channel >= dfs5GBand[bandIndex][0]) &&
+ (wd->regulationTable.allowChannel[i].channel <= dfs5GBand[bandIndex][1]))
+ {
+ /* if channel is not passive, set it to be passive and mark it */
+ if ((wd->regulationTable.allowChannel[i].channelFlags &
+ ZM_REG_FLAG_CHANNEL_PASSIVE) == 0)
+ {
+ wd->regulationTable.allowChannel[i].channelFlags |=
+ (ZM_REG_FLAG_CHANNEL_PASSIVE | ZM_REG_FLAG_CHANNEL_CSA);
+ }
+ }
+ }
+
+ return 0;
+}
+
+u16_t zfHpAddAllowChannel(zdev_t* dev, u16_t freq)
+{
+ u16_t i, j, arrayIndex;
+
+ zmw_get_wlan_dev(dev);
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel == freq)
+ break;
+ }
+
+ if ( i == wd->regulationTable.allowChannelCnt)
+ {
+ for (j = 0; j < wd->regulationTable.allowChannelCnt; j++)
+ {
+ if (wd->regulationTable.allowChannel[j].channel > freq)
+ break;
+ }
+
+ //zm_debug_msg1("CWY - add frequency = ", freq);
+ //zm_debug_msg1("CWY - channel array index = ", j);
+
+ arrayIndex = j;
+
+ if (arrayIndex < wd->regulationTable.allowChannelCnt)
+ {
+ for (j = wd->regulationTable.allowChannelCnt; j > arrayIndex; j--)
+ wd->regulationTable.allowChannel[j] = wd->regulationTable.allowChannel[j - 1];
+ }
+ wd->regulationTable.allowChannel[arrayIndex].channel = freq;
+
+ wd->regulationTable.allowChannelCnt++;
+ }
+
+ return 0;
+}
+
+u16_t zfHpIsDfsChannelNCS(zdev_t* dev, u16_t freq)
+{
+ u8_t flag = ZM_REG_FLAG_CHANNEL_DFS;
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ //DbgPrint("DFS:freq=%d, chan=%d", freq, wd->regulationTable.allowChannel[i].channel);
+ if (wd->regulationTable.allowChannel[i].channel == freq)
+ {
+ flag = wd->regulationTable.allowChannel[i].privFlags;
+ break;
+ }
+ }
+
+ return (flag & (ZM_REG_FLAG_CHANNEL_DFS|ZM_REG_FLAG_CHANNEL_DFS_CLEAR));
+}
+
+u16_t zfHpIsDfsChannel(zdev_t* dev, u16_t freq)
+{
+ u8_t flag = ZM_REG_FLAG_CHANNEL_DFS;
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ //DbgPrint("DFS:freq=%d, chan=%d", freq, wd->regulationTable.allowChannel[i].channel);
+ if (wd->regulationTable.allowChannel[i].channel == freq)
+ {
+ flag = wd->regulationTable.allowChannel[i].privFlags;
+ break;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return (flag & (ZM_REG_FLAG_CHANNEL_DFS|ZM_REG_FLAG_CHANNEL_DFS_CLEAR));
+}
+
+u16_t zfHpIsAllowedChannel(zdev_t* dev, u16_t freq)
+{
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if (wd->regulationTable.allowChannel[i].channel == freq)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+u16_t zfHpFindFirstNonDfsChannel(zdev_t* dev, u16_t aBand)
+{
+ u16_t chan = 2412;
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ for (i = 0; i < wd->regulationTable.allowChannelCnt; i++)
+ {
+ if ((wd->regulationTable.allowChannel[i].privFlags & ZM_REG_FLAG_CHANNEL_DFS) != 0)
+ {
+ if (aBand)
+ {
+ if (wd->regulationTable.allowChannel[i].channel > 3000)
+ {
+ chan = wd->regulationTable.allowChannel[i].channel;
+ break;
+ }
+ }
+ else
+ {
+ if (wd->regulationTable.allowChannel[i].channel < 3000)
+ {
+ chan = wd->regulationTable.allowChannel[i].channel;
+ break;
+ }
+ }
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ return chan;
+}
+
+
+/* porting from ACU */
+/* save RegulatoryDomain in hpriv */
+u8_t zfHpGetRegulatoryDomain(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ switch (wd->regulationTable.regionCode)
+ {
+ case NO_ENUMRD:
+ return 0;
+ break;
+ case FCC1_FCCA:
+ case FCC1_WORLD:
+ case FCC4_FCCA:
+ case FCC5_FCCA:
+ case FCC2_WORLD:
+ case FCC2_ETSIC:
+ case FCC3_FCCA:
+ case FCC3_WORLD:
+ case FCC1:
+ case FCC2:
+ case FCC3:
+ case FCC4:
+ case FCC5:
+ case FCCA:
+ return 0x10;//WG_AMERICAS DOT11_REG_DOMAIN_FCC United States
+ break;
+
+ case FCC2_FCCA:
+ return 0x20;//DOT11_REG_DOMAIN_DOC Canada
+ break;
+
+ case ETSI1_WORLD:
+ case ETSI3_ETSIA:
+ case ETSI2_WORLD:
+ case ETSI3_WORLD:
+ case ETSI4_WORLD:
+ case ETSI4_ETSIC:
+ case ETSI5_WORLD:
+ case ETSI6_WORLD:
+ case ETSI_RESERVED:
+ case ETSI1:
+ case ETSI2:
+ case ETSI3:
+ case ETSI4:
+ case ETSI5:
+ case ETSI6:
+ case ETSIA:
+ case ETSIB:
+ case ETSIC:
+ return 0x30;//WG_EMEA DOT11_REG_DOMAIN_ETSI Most of Europe
+ break;
+
+ case MKK1_MKKA:
+ case MKK1_MKKB:
+ case MKK2_MKKA:
+ case MKK1_FCCA:
+ case MKK1_MKKA1:
+ case MKK1_MKKA2:
+ case MKK1_MKKC:
+ case MKK3_MKKB:
+ case MKK3_MKKA2:
+ case MKK3_MKKC:
+ case MKK4_MKKB:
+ case MKK4_MKKA2:
+ case MKK4_MKKC:
+ case MKK5_MKKB:
+ case MKK5_MKKA2:
+ case MKK5_MKKC:
+ case MKK6_MKKB:
+ case MKK6_MKKA2:
+ case MKK6_MKKC:
+ case MKK7_MKKB:
+ case MKK7_MKKA:
+ case MKK7_MKKC:
+ case MKK8_MKKB:
+ case MKK8_MKKA2:
+ case MKK8_MKKC:
+ case MKK6_MKKA1:
+ case MKK6_FCCA:
+ case MKK7_MKKA1:
+ case MKK7_FCCA:
+ case MKK9_FCCA:
+ case MKK9_MKKA1:
+ case MKK9_MKKC:
+ case MKK9_MKKA2:
+ case MKK10_FCCA:
+ case MKK10_MKKA1:
+ case MKK10_MKKC:
+ case MKK10_MKKA2:
+ case MKK11_MKKA:
+ case MKK11_FCCA:
+ case MKK11_MKKA1:
+ case MKK11_MKKC:
+ case MKK11_MKKA2:
+ case MKK12_MKKA:
+ case MKK12_FCCA:
+ case MKK12_MKKA1:
+ case MKK12_MKKC:
+ case MKK12_MKKA2:
+ case MKK3_MKKA:
+ case MKK3_MKKA1:
+ case MKK3_FCCA:
+ case MKK4_MKKA:
+ case MKK4_MKKA1:
+ case MKK4_FCCA:
+ case MKK9_MKKA:
+ case MKK10_MKKA:
+ case MKK1:
+ case MKK2:
+ case MKK3:
+ case MKK4:
+ case MKK5:
+ case MKK6:
+ case MKK7:
+ case MKK8:
+ case MKK9:
+ case MKK10:
+ case MKK11:
+ case MKK12:
+ case MKKA:
+ case MKKC:
+ return 0x40;//WG_JAPAN DOT11_REG_DOMAIN_MKK Japan
+ break;
+
+ default:
+ break;
+ }
+ return 0xFF;// Didn't input RegDmn by mean to distinguish by customer
+
+}
+
+
+void zfHpDisableDfsChannel(zdev_t* dev, u8_t disableFlag)
+{
+ zmw_get_wlan_dev(dev);
+
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+ hpPriv->disableDfsCh = disableFlag;
+ return;
+}
diff --git a/drivers/staging/otus/hal/hpreg.h b/drivers/staging/otus/hal/hpreg.h
new file mode 100644
index 000000000000..6f8c73fd42cc
--- /dev/null
+++ b/drivers/staging/otus/hal/hpreg.h
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2000-2005 ZyDAS Technology Corporation
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : hpreg.h */
+/* */
+/* Abstract */
+/* This module contains Regulatory Table definitions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+
+#ifndef _HPREG_H
+#define _HPREG_H
+
+typedef u16_t HAL_CTRY_CODE; /* country code */
+typedef u16_t HAL_REG_DOMAIN; /* regulatory domain code */
+typedef enum {
+ AH_FALSE = 0, /* NB: lots of code assumes false is zero */
+ AH_TRUE = 1,
+} HAL_BOOL;
+
+
+/*
+ * Country/Region Codes from MS WINNLS.H
+ * Numbering from ISO 3166
+ */
+enum CountryCode {
+ CTRY_ALBANIA = 8, /* Albania */
+ CTRY_ALGERIA = 12, /* Algeria */
+ CTRY_ARGENTINA = 32, /* Argentina */
+ CTRY_ARMENIA = 51, /* Armenia */
+ CTRY_AUSTRALIA = 36, /* Australia */
+ CTRY_AUSTRIA = 40, /* Austria */
+ CTRY_AZERBAIJAN = 31, /* Azerbaijan */
+ CTRY_BAHRAIN = 48, /* Bahrain */
+ CTRY_BELARUS = 112, /* Belarus */
+ CTRY_BELGIUM = 56, /* Belgium */
+ CTRY_BELIZE = 84, /* Belize */
+ CTRY_BOLIVIA = 68, /* Bolivia */
+ CTRY_BOSNIA = 70, /* Bosnia */
+ CTRY_BRAZIL = 76, /* Brazil */
+ CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */
+ CTRY_BULGARIA = 100, /* Bulgaria */
+ CTRY_CANADA = 124, /* Canada */
+ CTRY_CHILE = 152, /* Chile */
+ CTRY_CHINA = 156, /* People's Republic of China */
+ CTRY_COLOMBIA = 170, /* Colombia */
+ CTRY_COSTA_RICA = 188, /* Costa Rica */
+ CTRY_CROATIA = 191, /* Croatia */
+ CTRY_CYPRUS = 196, /* Cyprus */
+ CTRY_CZECH = 203, /* Czech Republic */
+ CTRY_DENMARK = 208, /* Denmark */
+ CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */
+ CTRY_ECUADOR = 218, /* Ecuador */
+ CTRY_EGYPT = 818, /* Egypt */
+ CTRY_EL_SALVADOR = 222, /* El Salvador */
+ CTRY_ESTONIA = 233, /* Estonia */
+ CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */
+ CTRY_FINLAND = 246, /* Finland */
+ CTRY_FRANCE = 250, /* France */
+ CTRY_FRANCE2 = 255, /* France2 */
+ CTRY_GEORGIA = 268, /* Georgia */
+ CTRY_GERMANY = 276, /* Germany */
+ CTRY_GREECE = 300, /* Greece */
+ CTRY_GUATEMALA = 320, /* Guatemala */
+ CTRY_HONDURAS = 340, /* Honduras */
+ CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */
+ CTRY_HUNGARY = 348, /* Hungary */
+ CTRY_ICELAND = 352, /* Iceland */
+ CTRY_INDIA = 356, /* India */
+ CTRY_INDONESIA = 360, /* Indonesia */
+ CTRY_IRAN = 364, /* Iran */
+ CTRY_IRAQ = 368, /* Iraq */
+ CTRY_IRELAND = 372, /* Ireland */
+ CTRY_ISRAEL = 376, /* Israel */
+ CTRY_ISRAEL2 = 377, /* Israel2 */
+ CTRY_ITALY = 380, /* Italy */
+ CTRY_JAMAICA = 388, /* Jamaica */
+ CTRY_JAPAN = 392, /* Japan */
+ CTRY_JAPAN1 = 393, /* Japan (JP1) */
+ CTRY_JAPAN2 = 394, /* Japan (JP0) */
+ CTRY_JAPAN3 = 395, /* Japan (JP1-1) */
+ CTRY_JAPAN4 = 396, /* Japan (JE1) */
+ CTRY_JAPAN5 = 397, /* Japan (JE2) */
+ CTRY_JAPAN6 = 399, /* Japan (JP6) */
+
+ CTRY_JAPAN7 = 4007, /* Japan (J7) */
+ CTRY_JAPAN8 = 4008, /* Japan (J8) */
+ CTRY_JAPAN9 = 4009, /* Japan (J9) */
+
+ CTRY_JAPAN10 = 4010, /* Japan (J10) */
+ CTRY_JAPAN11 = 4011, /* Japan (J11) */
+ CTRY_JAPAN12 = 4012, /* Japan (J12) */
+
+ CTRY_JAPAN13 = 4013, /* Japan (J13) */
+ CTRY_JAPAN14 = 4014, /* Japan (J14) */
+ CTRY_JAPAN15 = 4015, /* Japan (J15) */
+
+ CTRY_JAPAN16 = 4016, /* Japan (J16) */
+ CTRY_JAPAN17 = 4017, /* Japan (J17) */
+ CTRY_JAPAN18 = 4018, /* Japan (J18) */
+
+ CTRY_JAPAN19 = 4019, /* Japan (J19) */
+ CTRY_JAPAN20 = 4020, /* Japan (J20) */
+ CTRY_JAPAN21 = 4021, /* Japan (J21) */
+
+ CTRY_JAPAN22 = 4022, /* Japan (J22) */
+ CTRY_JAPAN23 = 4023, /* Japan (J23) */
+ CTRY_JAPAN24 = 4024, /* Japan (J24) */
+
+ CTRY_JAPAN25 = 4025, /* Japan (J25) */
+ CTRY_JAPAN26 = 4026, /* Japan (J26) */
+ CTRY_JAPAN27 = 4027, /* Japan (J27) */
+
+ CTRY_JAPAN28 = 4028, /* Japan (J28) */
+ CTRY_JAPAN29 = 4029, /* Japan (J29) */
+ CTRY_JAPAN30 = 4030, /* Japan (J30) */
+
+ CTRY_JAPAN31 = 4031, /* Japan (J31) */
+ CTRY_JAPAN32 = 4032, /* Japan (J32) */
+ CTRY_JAPAN33 = 4033, /* Japan (J33) */
+
+ CTRY_JAPAN34 = 4034, /* Japan (J34) */
+ CTRY_JAPAN35 = 4035, /* Japan (J35) */
+ CTRY_JAPAN36 = 4036, /* Japan (J36) */
+
+ CTRY_JAPAN37 = 4037, /* Japan (J37) */
+ CTRY_JAPAN38 = 4038, /* Japan (J38) */
+ CTRY_JAPAN39 = 4039, /* Japan (J39) */
+
+ CTRY_JAPAN40 = 4040, /* Japan (J40) */
+ CTRY_JAPAN41 = 4041, /* Japan (J41) */
+ CTRY_JAPAN42 = 4042, /* Japan (J42) */
+ CTRY_JAPAN43 = 4043, /* Japan (J43) */
+ CTRY_JAPAN44 = 4044, /* Japan (J44) */
+ CTRY_JAPAN45 = 4045, /* Japan (J45) */
+ CTRY_JAPAN46 = 4046, /* Japan (J46) */
+ CTRY_JAPAN47 = 4047, /* Japan (J47) */
+ CTRY_JAPAN48 = 4048, /* Japan (J48) */
+ CTRY_JAPAN49 = 4049, /* Japan (J49) */
+
+ CTRY_JAPAN50 = 4050, /* Japan (J50) */
+ CTRY_JAPAN51 = 4051, /* Japan (J51) */
+ CTRY_JAPAN52 = 4052, /* Japan (J52) */
+ CTRY_JAPAN53 = 4053, /* Japan (J53) */
+ CTRY_JAPAN54 = 4054, /* Japan (J54) */
+
+ CTRY_JORDAN = 400, /* Jordan */
+ CTRY_KAZAKHSTAN = 398, /* Kazakhstan */
+ CTRY_KENYA = 404, /* Kenya */
+ CTRY_KOREA_NORTH = 408, /* North Korea */
+ CTRY_KOREA_ROC = 410, /* South Korea */
+ CTRY_KOREA_ROC2 = 411, /* South Korea */
+ CTRY_KOREA_ROC3 = 412, /* South Korea */
+ CTRY_KUWAIT = 414, /* Kuwait */
+ CTRY_LATVIA = 428, /* Latvia */
+ CTRY_LEBANON = 422, /* Lebanon */
+ CTRY_LIBYA = 434, /* Libya */
+ CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */
+ CTRY_LITHUANIA = 440, /* Lithuania */
+ CTRY_LUXEMBOURG = 442, /* Luxembourg */
+ CTRY_MACAU = 446, /* Macau */
+ CTRY_MACEDONIA = 807, /* the Former Yugoslav Republic of Macedonia */
+ CTRY_MALAYSIA = 458, /* Malaysia */
+ CTRY_MALTA = 470, /* Malta */
+ CTRY_MEXICO = 484, /* Mexico */
+ CTRY_MONACO = 492, /* Principality of Monaco */
+ CTRY_MOROCCO = 504, /* Morocco */
+ CTRY_NETHERLANDS = 528, /* Netherlands */
+ CTRY_NETHERLANDS_ANT = 530, /* Netherlands-Antellis */
+ CTRY_NEW_ZEALAND = 554, /* New Zealand */
+ CTRY_NICARAGUA = 558, /* Nicaragua */
+ CTRY_NORWAY = 578, /* Norway */
+ CTRY_OMAN = 512, /* Oman */
+ CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */
+ CTRY_PANAMA = 591, /* Panama */
+ CTRY_PARAGUAY = 600, /* Paraguay */
+ CTRY_PERU = 604, /* Peru */
+ CTRY_PHILIPPINES = 608, /* Republic of the Philippines */
+ CTRY_POLAND = 616, /* Poland */
+ CTRY_PORTUGAL = 620, /* Portugal */
+ CTRY_PUERTO_RICO = 630, /* Puerto Rico */
+ CTRY_QATAR = 634, /* Qatar */
+ CTRY_ROMANIA = 642, /* Romania */
+ CTRY_RUSSIA = 643, /* Russia */
+ CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */
+ CTRY_SERBIA_MONT = 891, /* Serbia and Montenegro */
+ CTRY_SINGAPORE = 702, /* Singapore */
+ CTRY_SLOVAKIA = 703, /* Slovak Republic */
+ CTRY_SLOVENIA = 705, /* Slovenia */
+ CTRY_SOUTH_AFRICA = 710, /* South Africa */
+ CTRY_SPAIN = 724, /* Spain */
+ CTRY_SRILANKA = 144, /* Srilanka */
+ CTRY_SWEDEN = 752, /* Sweden */
+ CTRY_SWITZERLAND = 756, /* Switzerland */
+ CTRY_SYRIA = 760, /* Syria */
+ CTRY_TAIWAN = 158, /* Taiwan */
+ CTRY_THAILAND = 764, /* Thailand */
+ CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */
+ CTRY_TUNISIA = 788, /* Tunisia */
+ CTRY_TURKEY = 792, /* Turkey */
+ CTRY_UAE = 784, /* U.A.E. */
+ CTRY_UKRAINE = 804, /* Ukraine */
+ CTRY_UNITED_KINGDOM = 826, /* United Kingdom */
+ CTRY_UNITED_STATES = 840, /* United States */
+ CTRY_UNITED_STATES_FCC49 = 842, /* United States (Public Safety)*/
+ CTRY_URUGUAY = 858, /* Uruguay */
+ CTRY_UZBEKISTAN = 860, /* Uzbekistan */
+ CTRY_VENEZUELA = 862, /* Venezuela */
+ CTRY_VIET_NAM = 704, /* Viet Nam */
+ CTRY_YEMEN = 887, /* Yemen */
+ CTRY_ZIMBABWE = 716 /* Zimbabwe */
+};
+
+/* Enumerated Regulatory Domain Information 8 bit values indicate that
+ * the regdomain is really a pair of unitary regdomains. 12 bit values
+ * are the real unitary regdomains and are the only ones which have the
+ * frequency bitmasks and flags set.
+ */
+enum EnumRd {
+ /*
+ * The following regulatory domain definitions are
+ * found in the EEPROM. Each regulatory domain
+ * can operate in either a 5GHz or 2.4GHz wireless mode or
+ * both 5GHz and 2.4GHz wireless modes.
+ * In general, the value holds no special
+ * meaning and is used to decode into either specific
+ * 2.4GHz or 5GHz wireless mode for that particular
+ * regulatory domain.
+ */
+ NO_ENUMRD = 0x00,
+ NULL1_WORLD = 0x03, /* For 11b-only countries (no 11a allowed) */
+ NULL1_ETSIB = 0x07, /* Israel */
+ NULL1_ETSIC = 0x08,
+ FCC1_FCCA = 0x10, /* USA */
+ FCC1_WORLD = 0x11, /* Hong Kong */
+ FCC4_FCCA = 0x12, /* USA - Public Safety */
+ FCC5_FCCA = 0x13, /* USA - with no DFS (UNII-1 + UNII-3 only) */
+ FCC6_FCCA = 0x14, /* Canada */
+
+ FCC2_FCCA = 0x20, /* Canada */
+ FCC2_WORLD = 0x21, /* Australia & HK */
+ FCC2_ETSIC = 0x22,
+ FCC6_WORLD = 0x23, /* Australia */
+
+ FRANCE_RES = 0x31, /* Legacy France for OEM */
+ FCC3_FCCA = 0x3A, /* USA & Canada w/5470 band, 11h, DFS enabled */
+ FCC3_WORLD = 0x3B, /* USA & Canada w/5470 band, 11h, DFS enabled */
+
+ ETSI1_WORLD = 0x37,
+ ETSI3_ETSIA = 0x32, /* France (optional) */
+ ETSI2_WORLD = 0x35, /* Hungary & others */
+ ETSI3_WORLD = 0x36, /* France & others */
+ ETSI4_WORLD = 0x30,
+ ETSI4_ETSIC = 0x38,
+ ETSI5_WORLD = 0x39,
+ ETSI6_WORLD = 0x34, /* Bulgaria */
+ ETSI_RESERVED = 0x33, /* Reserved (Do not used) */
+
+ MKK1_MKKA = 0x40, /* Japan (JP1) */
+ MKK1_MKKB = 0x41, /* Japan (JP0) */
+ APL4_WORLD = 0x42, /* Singapore */
+ MKK2_MKKA = 0x43, /* Japan with 4.9G channels */
+ APL_RESERVED = 0x44, /* Reserved (Do not used) */
+ APL2_WORLD = 0x45, /* Korea */
+ APL2_APLC = 0x46,
+ APL3_WORLD = 0x47,
+ MKK1_FCCA = 0x48, /* Japan (JP1-1) */
+ APL2_APLD = 0x49, /* Korea with 2.3G channels */
+ MKK1_MKKA1 = 0x4A, /* Japan (JE1) */
+ MKK1_MKKA2 = 0x4B, /* Japan (JE2) */
+ MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */
+
+ APL3_FCCA = 0x50,
+ APL1_WORLD = 0x52, /* Latin America */
+ APL1_FCCA = 0x53,
+ APL1_APLA = 0x54,
+ APL1_ETSIC = 0x55,
+ APL2_ETSIC = 0x56, /* Venezuela */
+ APL2_FCCA = 0x57, /* new Latin America */
+ APL5_WORLD = 0x58, /* Chile */
+ APL6_WORLD = 0x5B, /* Singapore */
+ APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */
+ APL8_WORLD = 0x5D, /* Malaysia 5GHz */
+ APL9_WORLD = 0x5E, /* Korea 5GHz */
+
+ /*
+ * World mode SKUs
+ */
+ WOR0_WORLD = 0x60, /* World0 (WO0 SKU) */
+ WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */
+ WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */
+ WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */
+ WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */
+ WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */
+
+ WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */
+ WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */
+ EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */
+
+ WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */
+ WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */
+
+ MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */
+ MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */
+ MKK3_MKKC = 0x82, /* Japan UNI-1 even + MKKC */
+
+ MKK4_MKKB = 0x83, /* Japan UNI-1 even + UNI-2 + MKKB */
+ MKK4_MKKA2 = 0x84, /* Japan UNI-1 even + UNI-2 + MKKA2 */
+ MKK4_MKKC = 0x85, /* Japan UNI-1 even + UNI-2 + MKKC */
+
+ MKK5_MKKB = 0x86, /* Japan UNI-1 even + UNI-2 + mid-band + MKKB */
+ MKK5_MKKA2 = 0x87, /* Japan UNI-1 even + UNI-2 + mid-band + MKKA2 */
+ MKK5_MKKC = 0x88, /* Japan UNI-1 even + UNI-2 + mid-band + MKKC */
+
+ MKK6_MKKB = 0x89, /* Japan UNI-1 even + UNI-1 odd MKKB */
+ MKK6_MKKA2 = 0x8A, /* Japan UNI-1 even + UNI-1 odd + MKKA2 */
+ MKK6_MKKC = 0x8B, /* Japan UNI-1 even + UNI-1 odd + MKKC */
+
+ MKK7_MKKB = 0x8C, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKB */
+ MKK7_MKKA = 0x8D, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA2 */
+ MKK7_MKKC = 0x8E, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKC */
+
+ MKK8_MKKB = 0x8F, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB */
+ MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */
+ MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */
+
+ MKK6_MKKA1 = 0xF8, /* Japan UNI-1 even + UNI-1 odd + MKKA1 */
+ MKK6_FCCA = 0xF9, /* Japan UNI-1 even + UNI-1 odd + FCCA */
+ MKK7_MKKA1 = 0xFA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */
+ MKK7_FCCA = 0xFB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */
+ MKK9_FCCA = 0xFC, /* Japan UNI-1 even + 4.9GHz + FCCA */
+ MKK9_MKKA1 = 0xFD, /* Japan UNI-1 even + 4.9GHz + MKKA1 */
+ MKK9_MKKC = 0xFE, /* Japan UNI-1 even + 4.9GHz + MKKC */
+ MKK9_MKKA2 = 0xFF, /* Japan UNI-1 even + 4.9GHz + MKKA2 */
+
+ MKK10_FCCA = 0xD0, /* Japan UNI-1 even + UNI-2 + 4.9GHz + FCCA */
+ MKK10_MKKA1 = 0xD1, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA1 */
+ MKK10_MKKC = 0xD2, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKC */
+ MKK10_MKKA2 = 0xD3, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA2 */
+
+ MKK11_MKKA = 0xD4, /* Japan UNI-1 even + UNI-2 + Midband + 4.9GHz + MKKA */
+ MKK11_FCCA = 0xD5, /* Japan UNI-1 even + UNI-2 + Midband + 4.9GHz + FCCA */
+ MKK11_MKKA1 = 0xD6, /* Japan UNI-1 even + UNI-2 + Midband + 4.9GHz + MKKA1 */
+ MKK11_MKKC = 0xD7, /* Japan UNI-1 even + UNI-2 + Midband + 4.9GHz + MKKC */
+ MKK11_MKKA2 = 0xD8, /* Japan UNI-1 even + UNI-2 + Midband + 4.9GHz + MKKA2 */
+
+ MKK12_MKKA = 0xD9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + Midband + 4.9GHz + MKKA */
+ MKK12_FCCA = 0xDA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + Midband + 4.9GHz + FCCA */
+ MKK12_MKKA1 = 0xDB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + Midband + 4.9GHz + MKKA1 */
+ MKK12_MKKC = 0xDC, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + Midband + 4.9GHz + MKKC */
+ MKK12_MKKA2 = 0xDD, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + Midband + 4.9GHz + MKKA2 */
+
+ /* Following definitions are used only by s/w to map old
+ * Japan SKUs.
+ */
+ MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */
+ MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */
+ MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */
+ MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */
+ MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */
+ MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */
+ MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz + MKKA*/
+ MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA */
+
+ /*
+ * Regulator domains ending in a number (e.g. APL1,
+ * MK1, ETSI4, etc) apply to 5GHz channel and power
+ * information. Regulator domains ending in a letter
+ * (e.g. APLA, FCCA, etc) apply to 2.4GHz channel and
+ * power information.
+ */
+ APL1 = 0x0150, /* LAT & Asia */
+ APL2 = 0x0250, /* LAT & Asia */
+ APL3 = 0x0350, /* Taiwan */
+ APL4 = 0x0450, /* Jordan */
+ APL5 = 0x0550, /* Chile */
+ APL6 = 0x0650, /* Singapore */
+ APL7 = 0x0750, /* Taiwan Middle */
+ APL8 = 0x0850, /* Malaysia */
+ APL9 = 0x0950, /* Korea (South) ROC 3 */
+
+ ETSI1 = 0x0130, /* Europe & others */
+ ETSI2 = 0x0230, /* Europe & others */
+ ETSI3 = 0x0330, /* Europe & others */
+ ETSI4 = 0x0430, /* Europe & others */
+ ETSI5 = 0x0530, /* Europe & others */
+ ETSI6 = 0x0630, /* Europe & others */
+ ETSIA = 0x0A30, /* France */
+ ETSIB = 0x0B30, /* Israel */
+ ETSIC = 0x0C30, /* Latin America */
+
+ FCC1 = 0x0110, /* US & others */
+ FCC2 = 0x0120, /* Canada, Australia & New Zealand */
+ FCC3 = 0x0160, /* US w/new middle band & DFS */
+ FCC4 = 0x0165, /* US Public Safety */
+ FCC5 = 0x0510, /* US no DFS */
+ FCC6 = 0x0610, /* Canada & Australia */
+
+ FCCA = 0x0A10,
+
+ APLD = 0x0D50, /* South Korea */
+
+ MKK1 = 0x0140, /* Japan (UNI-1 odd)*/
+ MKK2 = 0x0240, /* Japan (4.9 GHz + UNI-1 odd) */
+ MKK3 = 0x0340, /* Japan (UNI-1 even) */
+ MKK4 = 0x0440, /* Japan (UNI-1 even + UNI-2) */
+ MKK5 = 0x0540, /* Japan (UNI-1 even + UNI-2 + mid-band) */
+ MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */
+ MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */
+ MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */
+ MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */
+ MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
+ MKK11 = 0x1140, /* Japan (UNI-1 even + UNI-2 + mid-band + 4.9 GHZ) */
+ MKK12 = 0x1240, /* Japan (UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9 GHZ) */
+ MKKA = 0x0A40, /* Japan */
+ MKKC = 0x0A50,
+
+ NULL1 = 0x0198,
+ WORLD = 0x0199,
+ DEBUG_REG_DMN = 0x01ff,
+};
+
+/* channelFlags */
+#define ZM_REG_FLAG_CHANNEL_CW_INT 0x0002 /* CW interference detected on channel */
+#define ZM_REG_FLAG_CHANNEL_TURBO 0x0010 /* Turbo Channel */
+#define ZM_REG_FLAG_CHANNEL_CCK 0x0020 /* CCK channel */
+#define ZM_REG_FLAG_CHANNEL_OFDM 0x0040 /* OFDM channel */
+#define ZM_REG_FLAG_CHANNEL_2GHZ 0x0080 /* 2 GHz spectrum channel. */
+#define ZM_REG_FLAG_CHANNEL_5GHZ 0x0100 /* 5 GHz spectrum channel */
+#define ZM_REG_FLAG_CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed in the channel */
+#define ZM_REG_FLAG_CHANNEL_DYN 0x0400 /* dynamic CCK-OFDM channel */
+#define ZM_REG_FLAG_CHANNEL_XR 0x0800 /* XR channel */
+#define ZM_REG_FLAG_CHANNEL_CSA 0x1000 /* Channel by CSA(Channel Switch Announcement) */
+#define ZM_REG_FLAG_CHANNEL_STURBO 0x2000 /* Static turbo, no 11a-only usage */
+#define ZM_REG_FLAG_CHANNEL_HALF 0x4000 /* Half rate channel */
+#define ZM_REG_FLAG_CHANNEL_QUARTER 0x8000 /* Quarter rate channel */
+
+/* channelFlags */
+#define CHANNEL_CW_INT 0x0002 /* CW interference detected on channel */
+#define CHANNEL_TURBO 0x0010 /* Turbo Channel */
+#define CHANNEL_CCK 0x0020 /* CCK channel */
+#define CHANNEL_OFDM 0x0040 /* OFDM channel */
+#define CHANNEL_2GHZ 0x0080 /* 2 GHz spectrum channel. */
+#define CHANNEL_5GHZ 0x0100 /* 5 GHz spectrum channel */
+#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed in the channel */
+#define CHANNEL_DYN 0x0400 /* dynamic CCK-OFDM channel */
+#define CHANNEL_XR 0x0800 /* XR channel */
+#define CHANNEL_STURBO 0x2000 /* Static turbo, no 11a-only usage */
+#define CHANNEL_HALF 0x4000 /* Half rate channel */
+#define CHANNEL_QUARTER 0x8000 /* Quarter rate channel */
+#define CHANNEL_HT20 0x10000 /* HT20 channel */
+#define CHANNEL_HT40 0x20000 /* HT40 channel */
+#define CHANNEL_HT40U 0x40000 /* control channel can be upper channel */
+#define CHANNEL_HT40L 0x80000 /* control channel can be lower channel */
+
+/* privFlags */
+#define ZM_REG_FLAG_CHANNEL_INTERFERENCE 0x01 /* Software use: channel interference
+ used for as AR as well as RADAR
+ interference detection */
+#define ZM_REG_FLAG_CHANNEL_DFS 0x02 /* DFS required on channel */
+#define ZM_REG_FLAG_CHANNEL_4MS_LIMIT 0x04 /* 4msec packet limit on this channel */
+#define ZM_REG_FLAG_CHANNEL_DFS_CLEAR 0x08 /* if channel has been checked for DFS */
+
+#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_PUREG (CHANNEL_2GHZ|CHANNEL_OFDM)
+#ifdef notdef
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_DYN)
+#else
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
+#endif
+#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_ST (CHANNEL_T|CHANNEL_STURBO)
+#define CHANNEL_108G (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_108A CHANNEL_T
+#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
+#define CHANNEL_G_HT (CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_HT20)
+#define CHANNEL_A_HT (CHANNEL_5GHZ | CHANNEL_OFDM | CHANNEL_HT20)
+
+#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20)
+#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20)
+#define CHANNEL_G_HT40 (CHANNEL_2GHZ|CHANNEL_HT20|CHANNEL_HT40)
+#define CHANNEL_A_HT40 (CHANNEL_5GHZ|CHANNEL_HT20|CHANNEL_HT40)
+#define CHANNEL_ALL \
+ (CHANNEL_OFDM|CHANNEL_CCK| CHANNEL_2GHZ | CHANNEL_5GHZ | CHANNEL_TURBO | CHANNEL_HT20 | CHANNEL_HT40)
+#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL &~ CHANNEL_TURBO)
+
+enum {
+ HAL_MODE_11A = 0x001, /* 11a channels */
+ HAL_MODE_TURBO = 0x002, /* 11a turbo-only channels */
+ HAL_MODE_11B = 0x004, /* 11b channels */
+ HAL_MODE_PUREG = 0x008, /* 11g channels (OFDM only) */
+#ifdef notdef
+ HAL_MODE_11G = 0x010, /* 11g channels (OFDM/CCK) */
+#else
+ HAL_MODE_11G = 0x008, /* XXX historical */
+#endif
+ HAL_MODE_108G = 0x020, /* 11a+Turbo channels */
+ HAL_MODE_108A = 0x040, /* 11g+Turbo channels */
+ HAL_MODE_XR = 0x100, /* XR channels */
+ HAL_MODE_11A_HALF_RATE = 0x200, /* 11A half rate channels */
+ HAL_MODE_11A_QUARTER_RATE = 0x400, /* 11A quarter rate channels */
+ HAL_MODE_11NG = 0x4000, /* 11ng channels */
+ HAL_MODE_11NA = 0x8000, /* 11na channels */
+ HAL_MODE_ALL = 0xffff
+};
+
+#endif /* #ifndef _HPREG_H */
diff --git a/drivers/staging/otus/hal/hprw.c b/drivers/staging/otus/hal/hprw.c
new file mode 100644
index 000000000000..db7d49576456
--- /dev/null
+++ b/drivers/staging/otus/hal/hprw.c
@@ -0,0 +1,1557 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "../80211core/cprecomp.h"
+#include "hpani.h"
+#include "hpusb.h"
+#include "hpreg.h"
+#include "../80211core/ratectrl.h"
+
+extern void zfIdlCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen);
+
+extern void zfCoreCwmBusy(zdev_t* dev, u16_t busy);
+u16_t zfDelayWriteInternalReg(zdev_t* dev, u32_t addr, u32_t val);
+u16_t zfFlushDelayWrite(zdev_t* dev);
+
+//#define zm_hp_priv(x) struct zsHpPriv* hpPriv=zgWlanDev.hpPrivate;
+
+void zfInitCmdQueue(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv = (struct zsHpPriv*)(wd->hpPrivate);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+#ifdef ZM_XP_USB_MULTCMD
+ hpPriv->cmdTail = hpPriv->cmdHead = hpPriv->cmdSend = 0;
+#else
+ hpPriv->cmdTail = hpPriv->cmdHead = 0;
+#endif
+ hpPriv->cmdPending = 0;
+ hpPriv->cmd.delayWcmdCount = 0;
+ zmw_leave_critical_section(dev);
+}
+
+u16_t zfPutCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen, u16_t src, u8_t* buf)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ /* Make sure command length < ZM_MAX_CMD_SIZE */
+ zm_assert(cmdLen <= ZM_MAX_CMD_SIZE);
+ /* Make sure command queue not full */
+ //zm_assert(((hpPriv->cmdTail+1) & (ZM_CMD_QUEUE_SIZE-1)) != hpPriv->cmdHead);
+ if (((hpPriv->cmdTail+1) & (ZM_CMD_QUEUE_SIZE-1)) == hpPriv->cmdHead ) {
+ zm_debug_msg0("CMD queue full!!");
+ return 0;
+ }
+
+ hpPriv->cmdQ[hpPriv->cmdTail].cmdLen = cmdLen;
+ hpPriv->cmdQ[hpPriv->cmdTail].src = src;
+ hpPriv->cmdQ[hpPriv->cmdTail].buf = buf;
+ for (i=0; i<(cmdLen>>2); i++)
+ {
+ hpPriv->cmdQ[hpPriv->cmdTail].cmd[i] = cmd[i];
+ }
+
+ hpPriv->cmdTail = (hpPriv->cmdTail+1) & (ZM_CMD_QUEUE_SIZE-1);
+
+ return 0;
+}
+
+u16_t zfGetCmd(zdev_t* dev, u32_t* cmd, u16_t* cmdLen, u16_t* src, u8_t** buf)
+{
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ if (hpPriv->cmdTail == hpPriv->cmdHead)
+ {
+ return 3;
+ }
+
+ *cmdLen = hpPriv->cmdQ[hpPriv->cmdHead].cmdLen;
+ *src = hpPriv->cmdQ[hpPriv->cmdHead].src;
+ *buf = hpPriv->cmdQ[hpPriv->cmdHead].buf;
+ for (i=0; i<((*cmdLen)>>2); i++)
+ {
+ cmd[i] = hpPriv->cmdQ[hpPriv->cmdHead].cmd[i];
+ }
+
+ hpPriv->cmdHead = (hpPriv->cmdHead+1) & (ZM_CMD_QUEUE_SIZE-1);
+
+ return 0;
+}
+
+#ifdef ZM_XP_USB_MULTCMD
+void zfSendCmdEx(zdev_t* dev)
+{
+ u32_t ncmd[ZM_MAX_CMD_SIZE/4];
+ u16_t ncmdLen = 0;
+ u16_t cmdFlag = 0;
+ u16_t i;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if (hpPriv->cmdPending == 0)
+ {
+ if (hpPriv->cmdTail != hpPriv->cmdSend)
+ {
+ cmdFlag = 1;
+ /* Get queueing command */
+ ncmdLen= hpPriv->cmdQ[hpPriv->cmdSend].cmdLen;
+ for (i=0; i<(ncmdLen>>2); i++)
+ {
+ ncmd[i] = hpPriv->cmdQ[hpPriv->cmdSend].cmd[i];
+ }
+ hpPriv->cmdSend = (hpPriv->cmdSend+1) & (ZM_CMD_QUEUE_SIZE-1);
+
+ hpPriv->cmdPending = 1;
+ }
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if ((cmdFlag == 1))
+ {
+ zfIdlCmd(dev, ncmd, ncmdLen);
+ }
+}
+
+void zfiSendCmdComp(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ hpPriv->cmdPending = 0;
+ zmw_leave_critical_section(dev);
+
+ zfSendCmdEx(dev);
+}
+#endif
+
+u16_t zfIssueCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen, u16_t src, u8_t* buf)
+{
+ u16_t cmdFlag = 0;
+ u16_t ret;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zmw_declare_for_critical_section();
+
+ zm_msg2_mm(ZM_LV_1, "cmdLen=", cmdLen);
+
+ zmw_enter_critical_section(dev);
+
+#ifdef ZM_XP_USB_MULTCMD
+ ret = zfPutCmd(dev, cmd, cmdLen, src, buf);
+ zmw_leave_critical_section(dev);
+
+ if (ret != 0)
+ {
+ return 1;
+ }
+
+ zfSendCmdEx(dev);
+#else
+ if (hpPriv->cmdPending == 0)
+ {
+ hpPriv->cmdPending = 1;
+ cmdFlag = 1;
+ }
+ ret = zfPutCmd(dev, cmd, cmdLen, src, buf);
+
+ zmw_leave_critical_section(dev);
+
+ if (ret != 0)
+ {
+ return 1;
+ }
+
+ if (cmdFlag == 1)
+ {
+ zfIdlCmd(dev, cmd, cmdLen);
+ }
+#endif
+ return 0;
+}
+
+void zfIdlRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen)
+{
+ u32_t cmd[ZM_MAX_CMD_SIZE/4];
+ u16_t cmdLen;
+ u16_t src;
+ u8_t* buf;
+ u32_t ncmd[ZM_MAX_CMD_SIZE/4];
+ u16_t ncmdLen = 0;
+ u16_t ret;
+ u16_t cmdFlag = 0;
+ u16_t i;
+ s32_t nf;
+ s32_t noisefloor[4];
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ ret = zfGetCmd(dev, cmd, &cmdLen, &src, &buf);
+ #if 0
+ zm_assert(ret == 0);
+ #else
+ if (ret != 0)
+ {
+ zm_debug_msg0("Error IdlRsp because none cmd!!\n");
+ #ifndef ZM_XP_USB_MULTCMD
+ zmw_leave_critical_section(dev);
+ return;
+ #endif
+ }
+ #endif
+#ifdef ZM_XP_USB_MULTCMD
+ zmw_leave_critical_section(dev);
+#else
+ if (hpPriv->cmdTail != hpPriv->cmdHead)
+ {
+ cmdFlag = 1;
+ /* Get queueing command */
+ ncmdLen= hpPriv->cmdQ[hpPriv->cmdHead].cmdLen;
+ for (i=0; i<(ncmdLen>>2); i++)
+ {
+ ncmd[i] = hpPriv->cmdQ[hpPriv->cmdHead].cmd[i];
+ }
+ }
+ else
+ {
+ hpPriv->cmdPending = 0;
+ }
+
+ zmw_leave_critical_section(dev);
+
+ if (cmdFlag == 1)
+ {
+ zfIdlCmd(dev, ncmd, ncmdLen);
+ }
+#endif
+ if (src == ZM_OID_READ)
+ {
+ ZM_PERFORMANCE_REG(dev, 0x11772c, rsp[1]);
+ zfwDbgReadRegDone(dev, cmd[1], rsp[1]);
+ }
+ else if (src == ZM_OID_FLASH_CHKSUM)
+ {
+ zfwDbgGetFlashChkSumDone(dev, rsp+1);
+ }
+ else if (src == ZM_OID_FLASH_READ)
+ {
+ u32_t datalen;
+ u16_t i;
+
+ datalen = (rsp[0] & 255);
+
+ zfwDbgReadFlashDone(dev, cmd[1], rsp+1, datalen);
+ }
+ else if (src == ZM_OID_FLASH_PROGRAM)
+ {
+ /* Non do */
+ }
+ else if (src == ZM_OID_WRITE)
+ {
+ zfwDbgWriteRegDone(dev, cmd[1], cmd[2]);
+ }
+ else if (src == ZM_OID_TALLY)
+ {
+ zfCollectHWTally(dev, rsp, 0);
+ }
+ else if (src == ZM_OID_TALLY_APD)
+ {
+ zfCollectHWTally(dev, rsp, 1);
+ zfwDbgReadTallyDone(dev);
+#ifdef ZM_ENABLE_BA_RATECTRL
+ zfRateCtrlAggrSta(dev);
+#endif
+ }
+ else if (src == ZM_OID_DKTX_STATUS)
+ {
+ zm_debug_msg0("src = zm_OID_DKTX_STATUS");
+ zfwDbgQueryHwTxBusyDone(dev, rsp[1]);
+ }
+ else if (src == ZM_CMD_SET_FREQUENCY)
+ {
+
+//#ifdef ZM_OTUS_ENABLE_RETRY_FREQ_CHANGE
+#if 0
+ zm_debug_msg1("Retry Set Frequency = ", rsp[1]);
+
+ #if 1
+ // Read the Noise Floor value !
+ nf = ((rsp[2]>>19) & 0x1ff);
+ if ((nf & 0x100) != 0x0)
+ {
+ noisefloor[0] = 0 - ((nf ^ 0x1ff) + 1);
+ }
+ else
+ {
+ noisefloor[0] = nf;
+ }
+
+ zm_debug_msg1("Noise Floor[1] = ", noisefloor[0]);
+
+ nf = ((rsp[3]>>19) & 0x1ff);
+ if ((nf & 0x100) != 0x0)
+ {
+ noisefloor[1] = 0 - ((nf ^ 0x1ff) + 1);
+ }
+ else
+ {
+ noisefloor[1] = nf;
+ }
+
+ zm_debug_msg1("Noise Floor[2] = ", noisefloor[1]);
+ zm_debug_msg1("Is Site Survey = ", hpPriv->isSiteSurvey);
+ #endif
+
+ if ( (rsp[1] && hpPriv->freqRetryCounter == 0) ||
+ (((noisefloor[0]>-60)||(noisefloor[1]>-60)) && hpPriv->freqRetryCounter==0) ||
+ ((abs(noisefloor[0]-noisefloor[1])>=9) && hpPriv->freqRetryCounter==0) )
+ {
+ zm_debug_msg0("Retry to issue the frequency change command");
+
+ if ( hpPriv->recordFreqRetryCounter == 1 )
+ {
+ zm_debug_msg0("Cold Reset");
+
+ zfHpSetFrequencyEx(dev, hpPriv->latestFrequency,
+ hpPriv->latestBw40,
+ hpPriv->latestExtOffset,
+ 2);
+
+ if ( hpPriv->isSiteSurvey != 2 )
+ {
+ hpPriv->freqRetryCounter++;
+ }
+ hpPriv->recordFreqRetryCounter = 0;
+ }
+ else
+ {
+ zfHpSetFrequencyEx(dev, hpPriv->latestFrequency,
+ hpPriv->latestBw40,
+ hpPriv->latestExtOffset,
+ 0);
+ }
+ hpPriv->recordFreqRetryCounter++;
+ }
+ else
+#endif
+
+/* ret: Bit0: AGC calibration 0=>finish 1=>unfinish */
+/* Bit1: Noise calibration 0=>finish 1=>unfinish */
+/* Bit2: Noise calibration finish, but NF value unexcepted => 1 */
+ if ( (rsp[1] & 0x1) || (rsp[1] & 0x4) )
+ {
+ zm_debug_msg1("Set Frequency fail : ret = ", rsp[1]);
+
+ /* 1. AGC Calibration fail */
+ /* 2. Noise Calibration finish but error NoiseFloor value */
+ /* and not in sitesurvey, try more twice */
+ if ( hpPriv->isSiteSurvey == 2 )
+ {
+ if ( hpPriv->recordFreqRetryCounter < 2 )
+ {
+ /* cold reset */
+ zfHpSetFrequencyEx(dev, hpPriv->latestFrequency,
+ hpPriv->latestBw40,
+ hpPriv->latestExtOffset,
+ 2);
+ hpPriv->recordFreqRetryCounter++;
+ zm_debug_msg1("Retry to issue the frequency change command(cold reset) counter = ", hpPriv->recordFreqRetryCounter);
+ }
+ else
+ {
+ /* Fail : we would not accept this result! */
+ zm_debug_msg0("\n\n\n\n Fail twice cold reset \n\n\n\n");
+ hpPriv->coldResetNeedFreq = 0;
+ hpPriv->recordFreqRetryCounter = 0;
+ zfCoreSetFrequencyComplete(dev);
+ }
+ }
+ else
+ {
+ /* in sitesurvey, coldreset in next channel */
+ hpPriv->coldResetNeedFreq = 1;
+ hpPriv->recordFreqRetryCounter = 0;
+ zfCoreSetFrequencyComplete(dev);
+ }
+ }
+ else if (rsp[1] & 0x2)
+ {
+ zm_debug_msg1("Set Frequency fail 2 : ret = ", rsp[1]);
+
+ /* Noise Calibration un-finish */
+ /* and not in sitesurvey, try more once */
+ if ( hpPriv->isSiteSurvey == 2 )
+ {
+ if ( hpPriv->recordFreqRetryCounter < 1 )
+ {
+ /* cold reset */
+ zfHpSetFrequencyEx(dev, hpPriv->latestFrequency,
+ hpPriv->latestBw40,
+ hpPriv->latestExtOffset,
+ 2);
+ hpPriv->recordFreqRetryCounter++;
+ zm_debug_msg1("2 Retry to issue the frequency change command(cold reset) counter = ", hpPriv->recordFreqRetryCounter);
+ }
+ else
+ {
+ /* Fail : we would not accept this result! */
+ zm_debug_msg0("\n\n\n\n 2 Fail twice cold reset \n\n\n\n");
+ hpPriv->coldResetNeedFreq = 0;
+ hpPriv->recordFreqRetryCounter = 0;
+ zfCoreSetFrequencyComplete(dev);
+ }
+ }
+ else
+ {
+ /* in sitesurvey, skip this frequency */
+ hpPriv->coldResetNeedFreq = 0;
+ hpPriv->recordFreqRetryCounter = 0;
+ zfCoreSetFrequencyComplete(dev);
+ }
+ }
+ //else if (rsp[1] & 0x4)
+ //{
+ // zm_debug_msg1("Set Frequency fail 3 : ret = ", rsp[1]);
+ // hpPriv->coldResetNeedFreq = 0;
+ // hpPriv->recordFreqRetryCounter = 0;
+ // zfCoreSetFrequencyComplete(dev);
+ //}
+ else
+ {
+ //hpPriv->freqRetryCounter = 0;
+ zm_debug_msg2(" return complete, ret = ", rsp[1]);
+
+ /* set bb_heavy_clip_enable */
+ if (hpPriv->enableBBHeavyClip && hpPriv->hwBBHeavyClip &&
+ hpPriv->doBBHeavyClip)
+ {
+ u32_t setValue = 0x200;
+
+ setValue |= hpPriv->setValueHeavyClip;
+
+ //zm_dbg(("Do heavy clip setValue = %d\n", setValue));
+
+ zfDelayWriteInternalReg(dev, 0x99e0+0x1bc000, setValue);
+ zfFlushDelayWrite(dev);
+ }
+
+ hpPriv->coldResetNeedFreq = 0;
+ hpPriv->recordFreqRetryCounter = 0;
+ zfCoreSetFrequencyComplete(dev);
+ }
+
+ #if 1
+ // Read the Noise Floor value !
+ nf = ((rsp[2]>>19) & 0x1ff);
+ if ((nf & 0x100) != 0x0)
+ {
+ noisefloor[0] = 0 - ((nf ^ 0x1ff) + 1);
+ }
+ else
+ {
+ noisefloor[0] = nf;
+ }
+
+ //zm_debug_msg1("Noise Floor[1] = ", noisefloor[0]);
+
+ nf = ((rsp[3]>>19) & 0x1ff);
+ if ((nf & 0x100) != 0x0)
+ {
+ noisefloor[1] = 0 - ((nf ^ 0x1ff) + 1);
+ }
+ else
+ {
+ noisefloor[1] = nf;
+ }
+
+ //zm_debug_msg1("Noise Floor[2] = ", noisefloor[1]);
+
+ nf = ((rsp[5]>>23) & 0x1ff);
+ if ((nf & 0x100) != 0x0)
+ {
+ noisefloor[2] = 0 - ((nf ^ 0x1ff) + 1);
+ }
+ else
+ {
+ noisefloor[2] = nf;
+ }
+
+ //zm_debug_msg1("Noise Floor ext[1] = ", noisefloor[2]);
+
+ nf = ((rsp[6]>>23) & 0x1ff);
+ if ((nf & 0x100) != 0x0)
+ {
+ noisefloor[3] = 0 - ((nf ^ 0x1ff) + 1);
+ }
+ else
+ {
+ noisefloor[3] = nf;
+ }
+
+ //zm_debug_msg1("Noise Floor ext[2] = ", noisefloor[3]);
+
+ //zm_debug_msg1("Is Site Survey = ", hpPriv->isSiteSurvey);
+ #endif
+ }
+ else if (src == ZM_CMD_SET_KEY)
+ {
+ zfCoreSetKeyComplete(dev);
+ }
+ else if (src == ZM_CWM_READ)
+ {
+ zm_msg2_mm(ZM_LV_0, "CWM rsp[1]=", rsp[1]);
+ zm_msg2_mm(ZM_LV_0, "CWM rsp[2]=", rsp[2]);
+ zfCoreCwmBusy(dev, zfCwmIsExtChanBusy(rsp[1], rsp[2]));
+ }
+ else if (src == ZM_MAC_READ)
+ {
+ /* rsp[1] = ZM_SEEPROM_MAC_ADDRESS_OFFSET; */
+ /* rsp[2] = ZM_SEEPROM_MAC_ADDRESS_OFFSET+4; */
+ /* rsp[3] = ZM_SEEPROM_REGDOMAIN_OFFSET; */
+ /* rsp[4] = ZM_SEEPROM_VERISON_OFFSET; */
+ /* rsp[5] = ZM_SEEPROM_HARDWARE_TYPE_OFFSET; */
+ /* rsp[6] = ZM_SEEPROM_HW_HEAVY_CLIP; */
+
+ u8_t addr[6], CCS, WWR;
+ u16_t CountryDomainCode;
+
+ /* BB heavy clip */
+ //hpPriv->eepromHeavyClipFlag = (u8_t)((rsp[6]>>24) & 0xff); // force enable 8107
+ //zm_msg2_mm(ZM_LV_0, "eepromHeavyClipFlag", hpPriv->eepromHeavyClipFlag);
+ #if 0
+ if (hpPriv->hwBBHeavyClip)
+ {
+ zm_msg0_mm(ZM_LV_0, "enable BB Heavy Clip");
+ }
+ else
+ {
+ zm_msg0_mm(ZM_LV_0, "Not enable BB Heavy Clip");
+ }
+ #endif
+ zm_msg2_mm(ZM_LV_0, "MAC rsp[1]=", rsp[1]);
+ zm_msg2_mm(ZM_LV_0, "MAC rsp[2]=", rsp[2]);
+
+ addr[0] = (u8_t)(rsp[1] & 0xff);
+ addr[1] = (u8_t)((rsp[1]>>8) & 0xff);
+ addr[2] = (u8_t)((rsp[1]>>16) & 0xff);
+ addr[3] = (u8_t)((rsp[1]>>24) & 0xff);
+ addr[4] = (u8_t)(rsp[2] & 0xff);
+ addr[5] = (u8_t)((rsp[2]>>8) & 0xff);
+/*#ifdef ZM_FB50
+ addr[0] = (u8_t)(0 & 0xff);
+ addr[1] = (u8_t)(3 & 0xff);
+ addr[2] = (u8_t)(127 & 0xff);
+ addr[3] = (u8_t)(0 & 0xff);
+ addr[4] = (u8_t)(9 & 0xff);
+ addr[5] = (u8_t)(11 & 0xff);
+#endif*/
+
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_MAC_ADDR_L,
+ ((((u32_t)addr[3])<<24) | (((u32_t)addr[2])<<16) | (((u32_t)addr[1])<<8) | addr[0]));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_MAC_ADDR_H,
+ ((((u32_t)addr[5])<<8) | addr[4]));
+ zfFlushDelayWrite(dev);
+
+ wd->ledStruct.ledMode[0] = (u16_t)(rsp[5]&0xffff);
+ wd->ledStruct.ledMode[1] = (u16_t)(rsp[5]>>16);
+ zm_msg2_mm(ZM_LV_0, "ledMode[0]=", wd->ledStruct.ledMode[0]);
+ zm_msg2_mm(ZM_LV_0, "ledMode[1]=", wd->ledStruct.ledMode[1]);
+
+ /* Regulatory Related Setting */
+ zm_msg2_mm(ZM_LV_0, "RegDomain rsp=", rsp[3]);
+ zm_msg2_mm(ZM_LV_0, "OpFlags+EepMisc=", rsp[4]);
+ hpPriv->OpFlags = (u8_t)((rsp[4]>>16) & 0xff);
+ if ((rsp[2] >> 24) == 0x1) //Tx mask == 0x1
+ {
+ zm_msg0_mm(ZM_LV_0, "OTUS 1x2");
+ hpPriv->halCapability |= ZM_HP_CAP_11N_ONE_TX_STREAM;
+ }
+ else
+ {
+ zm_msg0_mm(ZM_LV_0, "OTUS 2x2");
+ }
+ if (hpPriv->OpFlags & 0x1)
+ {
+ hpPriv->halCapability |= ZM_HP_CAP_5G;
+ }
+ if (hpPriv->OpFlags & 0x2)
+ {
+ hpPriv->halCapability |= ZM_HP_CAP_2G;
+ }
+
+
+ CCS = (u8_t)((rsp[3] & 0x8000) >> 15);
+ WWR = (u8_t)((rsp[3] & 0x4000) >> 14);
+ CountryDomainCode = (u16_t)(rsp[3] & 0x3FFF);
+
+ if (rsp[3] != 0xffffffff)
+ {
+ if (CCS)
+ {
+ //zm_debug_msg0("CWY - Get Regulation Table from Country Code");
+ zfHpGetRegulationTablefromCountry(dev, CountryDomainCode);
+ }
+ else
+ {
+ //zm_debug_msg0("CWY - Get Regulation Table from Reg Domain");
+ zfHpGetRegulationTablefromRegionCode(dev, CountryDomainCode);
+ }
+ if (WWR)
+ {
+ //zm_debug_msg0("CWY - Enable 802.11d");
+ /* below line shall be unmarked after A band is ready */
+ //zfiWlanSetDot11DMode(dev, 1);
+ }
+ }
+ else
+ {
+ zfHpGetRegulationTablefromRegionCode(dev, NO_ENUMRD);
+ }
+
+ zfCoreMacAddressNotify(dev, addr);
+
+ }
+ else if (src == ZM_EEPROM_READ)
+ {
+#if 0
+ u8_t addr[6], CCS, WWR;
+ u16_t CountryDomainCode;
+#endif
+ for (i=0; i<ZM_HAL_MAX_EEPROM_PRQ; i++)
+ {
+ if (hpPriv->eepromImageIndex < 1024)
+ {
+ hpPriv->eepromImage[hpPriv->eepromImageIndex++] = rsp[i+1];
+ }
+ }
+
+ if (hpPriv->eepromImageIndex == (ZM_HAL_MAX_EEPROM_REQ*ZM_HAL_MAX_EEPROM_PRQ))
+ {
+ #if 0
+ for (i=0; i<1024; i++)
+ {
+ zm_msg2_mm(ZM_LV_0, "index=", i);
+ zm_msg2_mm(ZM_LV_0, "eepromImage=", hpPriv->eepromImage[i]);
+ }
+ #endif
+ zm_msg2_mm(ZM_LV_0, "MAC [1]=", hpPriv->eepromImage[0x20c/4]);
+ zm_msg2_mm(ZM_LV_0, "MAC [2]=", hpPriv->eepromImage[0x210/4]);
+#if 0
+ addr[0] = (u8_t)(hpPriv->eepromImage[0x20c/4] & 0xff);
+ addr[1] = (u8_t)((hpPriv->eepromImage[0x20c/4]>>8) & 0xff);
+ addr[2] = (u8_t)((hpPriv->eepromImage[0x20c/4]>>16) & 0xff);
+ addr[3] = (u8_t)((hpPriv->eepromImage[0x20c/4]>>24) & 0xff);
+ addr[4] = (u8_t)(hpPriv->eepromImage[0x210/4] & 0xff);
+ addr[5] = (u8_t)((hpPriv->eepromImage[0x210/4]>>8) & 0xff);
+
+ zfCoreMacAddressNotify(dev, addr);
+
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_MAC_ADDR_L,
+ ((((u32_t)addr[3])<<24) | (((u32_t)addr[2])<<16) | (((u32_t)addr[1])<<8) | addr[0]));
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_MAC_ADDR_H,
+ ((((u32_t)addr[5])<<8) | addr[4]));
+ zfFlushDelayWrite(dev);
+
+ /* Regulatory Related Setting */
+ zm_msg2_mm(ZM_LV_0, "RegDomain =", hpPriv->eepromImage[0x208/4]);
+ CCS = (u8_t)((hpPriv->eepromImage[0x208/4] & 0x8000) >> 15);
+ WWR = (u8_t)((hpPriv->eepromImage[0x208/4] & 0x4000) >> 14);
+ /* below line shall be unmarked after A band is ready */
+ //CountryDomainCode = (u16_t)(hpPriv->eepromImage[0x208/4] & 0x3FFF);
+ CountryDomainCode = 8;
+ if (CCS)
+ {
+ //zm_debug_msg0("CWY - Get Regulation Table from Country Code");
+ zfHpGetRegulationTablefromCountry(dev, CountryDomainCode);
+ }
+ else
+ {
+ //zm_debug_msg0("CWY - Get Regulation Table from Reg Domain");
+ zfHpGetRegulationTablefromRegionCode(dev, CountryDomainCode);
+ }
+ if (WWR)
+ {
+ //zm_debug_msg0("CWY - Enable 802.11d");
+ /* below line shall be unmarked after A band is ready */
+ //zfiWlanSetDot11DMode(dev, 1);
+ }
+#endif
+ zfCoreHalInitComplete(dev);
+ }
+ else
+ {
+ hpPriv->eepromImageRdReq++;
+ zfHpLoadEEPROMFromFW(dev);
+ }
+ }
+ else if (src == ZM_EEPROM_WRITE)
+ {
+ zfwDbgWriteEepromDone(dev, cmd[1], cmd[2]);
+ }
+ else if (src == ZM_ANI_READ)
+ {
+ u32_t cycleTime, ctlClear;
+
+ zm_msg2_mm(ZM_LV_0, "ANI rsp[1]=", rsp[1]);
+ zm_msg2_mm(ZM_LV_0, "ANI rsp[2]=", rsp[2]);
+ zm_msg2_mm(ZM_LV_0, "ANI rsp[3]=", rsp[3]);
+ zm_msg2_mm(ZM_LV_0, "ANI rsp[4]=", rsp[4]);
+
+ hpPriv->ctlBusy += rsp[1];
+ hpPriv->extBusy += rsp[2];
+
+ cycleTime = 100000; //100 miniseconds
+
+ if (cycleTime > rsp[1])
+ {
+ ctlClear = (cycleTime - rsp[1]) / 100;
+ }
+ else
+ {
+ ctlClear = 0;
+ }
+ if (wd->aniEnable)
+ zfHpAniArPoll(dev, ctlClear, rsp[3], rsp[4]);
+ }
+ else if (src == ZM_CMD_ECHO)
+ {
+ if ( ((struct zsHpPriv*)wd->hpPrivate)->halReInit )
+ {
+ zfCoreHalInitComplete(dev);
+ ((struct zsHpPriv*)wd->hpPrivate)->halReInit = 0;
+ }
+ else
+ {
+ zfHpLoadEEPROMFromFW(dev);
+ }
+ }
+ else if (src == ZM_OID_FW_DL_INIT)
+ {
+ zfwDbgDownloadFwInitDone(dev);
+ }
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfWriteRegInternalReg */
+/* Write on chip internal register immediately. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* val : value */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+u32_t zfWriteRegInternalReg(zdev_t* dev, u32_t addr, u32_t val)
+{
+ u32_t cmd[3];
+ u16_t ret;
+
+ cmd[0] = 0x00000108;
+ cmd[1] = addr;
+ cmd[2] = val;
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_OID_INTERNAL_WRITE, NULL);
+ return ret;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfDelayWriteInternalReg */
+/* Write on chip internal register, write operation may be */
+/* postponed to form a multiple write command. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* val : value */
+/* */
+/* OUTPUTS */
+/* 0 : command been postponed */
+/* 1 : commands been executed */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+u16_t zfDelayWriteInternalReg(zdev_t* dev, u32_t addr, u32_t val)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t i;
+ u16_t ret;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zmw_declare_for_critical_section();
+
+ /* enter critical section */
+ zmw_enter_critical_section(dev);
+
+ /* Store command to global buffer */
+ hpPriv->cmd.delayWcmdAddr[hpPriv->cmd.delayWcmdCount] = addr;
+ hpPriv->cmd.delayWcmdVal[hpPriv->cmd.delayWcmdCount++] = val;
+
+ /* If pending command reach size limit */
+ if ((hpPriv->cmd.delayWcmdCount) >= ((ZM_MAX_CMD_SIZE - 4) >> 3))
+ {
+ cmd[0] = 0x00000100 + (hpPriv->cmd.delayWcmdCount<<3);
+
+ /* copy command to cmd buffer */
+ for (i=0; i<hpPriv->cmd.delayWcmdCount; i++)
+ {
+ cmd[1+(i<<1)] = hpPriv->cmd.delayWcmdAddr[i];
+ cmd[2+(i<<1)] = hpPriv->cmd.delayWcmdVal[i];
+ }
+ /* reset pending command */
+ hpPriv->cmd.delayWcmdCount = 0;
+
+ /* leave critical section */
+ zmw_leave_critical_section(dev);
+
+ /* issue write command */
+ ret = zfIssueCmd(dev, cmd, 4+(i<<3), ZM_OID_INTERNAL_WRITE, NULL);
+
+ return 1;
+ }
+ else
+ {
+ /* leave critical section */
+ zmw_leave_critical_section(dev);
+
+ return 0;
+ }
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfFlushDelayWrite */
+/* Flush pending write command. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0 : no pending command */
+/* 1 : commands been executed */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.11 */
+/* */
+/************************************************************************/
+u16_t zfFlushDelayWrite(zdev_t* dev)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t i;
+ u16_t ret;
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zmw_declare_for_critical_section();
+
+ /* enter critical section */
+ zmw_enter_critical_section(dev);
+
+ /* If there is pending command */
+ if (hpPriv->cmd.delayWcmdCount > 0)
+ {
+ cmd[0] = 0x00000100 + (hpPriv->cmd.delayWcmdCount<<3);
+
+ /* copy command to cmd buffer */
+ for (i=0; i<hpPriv->cmd.delayWcmdCount; i++)
+ {
+ cmd[1+(i<<1)] = hpPriv->cmd.delayWcmdAddr[i];
+ cmd[2+(i<<1)] = hpPriv->cmd.delayWcmdVal[i];
+ }
+ /* reset pending command */
+ hpPriv->cmd.delayWcmdCount = 0;
+
+ /* leave critical section */
+ zmw_leave_critical_section(dev);
+
+ /* issue write command */
+ ret = zfIssueCmd(dev, cmd, 4+(i<<3), ZM_OID_INTERNAL_WRITE, NULL);
+
+ return 1;
+ }
+ else
+ {
+ /* leave critical section */
+ zmw_leave_critical_section(dev);
+
+ return 0;
+ }
+}
+
+
+u32_t zfiDbgDelayWriteReg(zdev_t* dev, u32_t addr, u32_t val)
+{
+ zfDelayWriteInternalReg(dev, addr, val);
+ return 0;
+}
+
+u32_t zfiDbgFlushDelayWrite(zdev_t* dev)
+{
+ zfFlushDelayWrite(dev);
+ return 0;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgWriteReg */
+/* Write register. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* val : value */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u32_t zfiDbgWriteReg(zdev_t* dev, u32_t addr, u32_t val)
+{
+ u32_t cmd[3];
+ u16_t ret;
+
+ cmd[0] = 0x00000108;
+ cmd[1] = addr;
+ cmd[2] = val;
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_OID_WRITE, 0);
+ return ret;
+}
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgWriteFlash */
+/* Write flash. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* val : value */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Yjsung ZyDAS Technology Corporation 2007.02 */
+/* */
+/************************************************************************/
+u32_t zfiDbgWriteFlash(zdev_t* dev, u32_t addr, u32_t val)
+{
+ u32_t cmd[3];
+ u16_t ret;
+
+ //cmd[0] = 0x0000B008;
+ /* len[0] : type[0xB0] : seq[?] */
+ cmd[0] = 8 | (ZM_CMD_WFLASH << 8);
+ cmd[1] = addr;
+ cmd[2] = val;
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_OID_WRITE, 0);
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgWriteEeprom */
+/* Write EEPROM. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* val : value */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul ZyDAS Technology Corporation 2007.06 */
+/* */
+/************************************************************************/
+u32_t zfiDbgWriteEeprom(zdev_t* dev, u32_t addr, u32_t val)
+{
+ u32_t cmd[3];
+ u16_t ret;
+
+ //cmd[0] = 0x0000B008;
+ /* len[0] : type[0xB0] : seq[?] */
+ cmd[0] = 8 | (ZM_CMD_WREEPROM << 8);
+ cmd[1] = addr;
+ cmd[2] = val;
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_EEPROM_WRITE, 0);
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgBlockWriteEeprom */
+/* Block Write Eeprom. */
+/* */
+/* p.s: now,it will write 16 bytes register data per block (N=4) */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* buf : input data buffer pointer */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul ZyDAS Technology Corporation 2007.06 */
+/* */
+/************************************************************************/
+//#define N buflen/4
+//#define SIZE (2*N+1)
+
+u32_t zfiDbgBlockWriteEeprom(zdev_t* dev, u32_t addr, u32_t* buf)
+{
+ u32_t cmd[9]; //2N+1
+ u16_t ret,i;
+
+ //cmd[0] = 0x0000B008;
+ /* len[0] : type[0xB0] : seq[?] */
+
+ //cmd[0] = (8*N) | (ZM_CMD_WFLASH << 8);
+ cmd[0] = 32 | (ZM_CMD_WREEPROM << 8); //8N
+
+ for (i=0; i<4; i++) // i<N
+ {
+ cmd[(2*i)+1] = addr+(4*i);
+ cmd[(2*i)+2] = *(buf+i);
+ }
+
+ ret = zfIssueCmd(dev, cmd, 36, ZM_EEPROM_WRITE, 0); //8N+4
+
+ // added for EEPROMUpdate, wait a moment for prevent cmd queue full!
+ //zfwSleep(dev, 1);
+
+ return ret;
+}
+
+
+/* write EEPROM with wrlen : wrlen must be 4*n */
+/* command format : cmd_info(4) + addr(4) + eeprom(wrlen) */
+u32_t zfiDbgBlockWriteEeprom_v2(zdev_t* dev, u32_t addr, u32_t* buf, u32_t wrlen)
+{
+ u32_t cmd[16];
+ u16_t ret,i;
+
+ /* len[0] : type[0xB0] : seq[?] */
+ /* len = addr(4) + eeprom_block(wrlen) */
+ cmd[0] = (wrlen+4) | (ZM_CMD_MEM_WREEPROM << 8);
+ cmd[1] = addr;
+
+ for (i=0; i<(wrlen/4); i++) // i<wrlen/4
+ {
+ cmd[2+i] = *(buf+i);
+ }
+ /* cmd_info(4) + addr(4) + eeprom(wrlen) */
+ ret = zfIssueCmd(dev, cmd, (u16_t)(wrlen+8), ZM_EEPROM_WRITE, 0);
+
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfDbgOpenEeprom */
+/* Open EEPROM. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* */
+/* AUTHOR */
+/* Paul ZyDAS Technology Corporation 2007.06 */
+/* */
+/************************************************************************/
+void zfDbgOpenEeprom(zdev_t* dev)
+{
+ // unlock EEPROM
+ zfDelayWriteInternalReg(dev, 0x1D1400, 0x12345678);
+ zfDelayWriteInternalReg(dev, 0x1D1404, 0x55aa00ff);
+ zfDelayWriteInternalReg(dev, 0x1D1408, 0x13579ace);
+ zfDelayWriteInternalReg(dev, 0x1D1414, 0x0);
+ zfFlushDelayWrite(dev);
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfDbgCloseEeprom */
+/* Close EEPROM. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* */
+/* AUTHOR */
+/* Paul ZyDAS Technology Corporation 2007.05 */
+/* */
+/************************************************************************/
+void zfDbgCloseEeprom(zdev_t* dev)
+{
+ // lock EEPROM
+ zfDelayWriteInternalReg(dev, 0x1D1400, 0x87654321);
+ //zfDelayWriteInternalReg(dev, 0x1D1404, 0xffffffff);
+ //zfDelayWriteInternalReg(dev, 0x1D1408, 0xffffffff);
+ //zfDelayWriteInternalReg(dev, 0x1D1414, 0x100);
+ zfFlushDelayWrite(dev);
+}
+#if 0
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiSeriallyWriteEeprom */
+/* Write EEPROM Serially. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : start address of writing EEPROM */
+/* buf : input data buffer */
+/* buflen : size of input data buffer */
+/* (length of data write into EEPROM) */
+/* */
+/* OUTPUTS */
+/* */
+/* */
+/* */
+/* AUTHOR */
+/* Paul ZyDAS Technology Corporation 2007.06 */
+/* */
+/************************************************************************/
+u32_t zfiSeriallyWriteEeprom(zdev_t* dev, u32_t addr, u32_t* buf, u32_t buflen)
+{
+ u32_t count;
+ u16_t i,ret,blocksize;
+ u8_t temp[2];
+
+ // per 4 bytes = 1 count
+ count = buflen/4;
+
+ // Open EEPROM
+ zfDbgOpenEeprom(dev);
+
+ // Write EEPROM
+ for (i=0; i<count; i++)
+ {
+ if (zfwWriteEeprom(dev, (addr+(4*i)), *(buf+i), 0) != 0)
+ {
+ // Update failed, Close EEPROM
+ zm_debug_msg0("zfwWriteEeprom failed \n");
+ zfDbgCloseEeprom(dev);
+ return 1;
+ }
+ }
+
+ // Close EEPROM
+ zfDbgCloseEeprom(dev);
+ return 0;
+}
+#endif
+#if 0
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiSeriallyBlockWriteEeprom */
+/* Block Write EEPROM Serially. */
+/* (BlockWrite: per 16bytes write EEPROM once) */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* buf : input data buffer */
+/* buflen : access data size of buf */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul ZyDAS Technology Corporation 2007.05 */
+/* */
+/************************************************************************/
+u32_t zfiSeriallyBlockWriteEeprom(zdev_t* dev, u32_t addr, u32_t* buf, u32_t buflen)
+{
+ u32_t count;
+ u16_t i,ret,blocksize;
+ u8_t temp[2];
+
+ // per 4 bytes = 1 count
+ count = buflen/4;
+
+ // Open EEPROM
+ zfDbgOpenEeprom(dev);
+
+ // Write EEPROM
+ // EEPROM Write start address from: 0x1000!?
+ // per 16bytes(N=4) block write EEPROM once
+ for (i=0; i<(count/4); i++) // count/N
+ {
+ //zfiDbgBlockWriteEeprom(dev, (addr+(4*N*i)), buf+(N*i));
+ //zfiDbgBlockWriteEeprom(dev, (addr+(16*i)), buf+(4*i));
+ if (zfwBlockWriteEeprom(dev, (addr+(16*i)), buf+(4*i), 0) != 0)
+ {
+ zm_debug_msg0("zfiDbgBlockWriteEeprom failed \n");
+ // Close EEPROM
+ zfDbgCloseEeprom(dev);
+ return 1;
+ }
+ }
+
+ // Close EEPROM
+ zfDbgCloseEeprom(dev);
+ return 0;
+}
+#endif
+#if 0
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgDumpEeprom */
+/* Dump EEPROM. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : start address of dumping EEPROM */
+/* datalen : length of access EEPROM data */
+/* buf : point of buffer, the buffer saved dump data */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul ZyDAS Technology Corporation 2007.06 */
+/* */
+/************************************************************************/
+u32_t zfiDbgDumpEeprom(zdev_t* dev, u32_t addr, u32_t datalen, u32_t* buf)
+{
+ u32_t count;
+ u16_t i,ret;
+
+ count = datalen/4;
+
+ // over EEPROM length
+ if(datalen > 0x2000)
+ {
+ return 1;
+ }
+
+ for(i=0; i<count; i++)
+ {
+ buf[i] = zfwReadEeprom(dev, addr+(4*i));
+ }
+
+ return 0;
+}
+#endif
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgReadReg */
+/* Read register. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : register address */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u32_t zfiDbgReadReg(zdev_t* dev, u32_t addr)
+{
+ u32_t cmd[2];
+ u16_t ret;
+
+ cmd[0] = 0x00000004;
+ cmd[1] = addr;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_READ, 0);
+ return ret;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgReadTally */
+/* Read register. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+u32_t zfiDbgReadTally(zdev_t* dev)
+{
+ u32_t cmd[1];
+ u16_t ret;
+ zmw_get_wlan_dev(dev);
+
+ if ( ((struct zsHpPriv*)wd->hpPrivate)->halReInit )
+ {
+ return 1;
+ }
+
+ /* len[0] : type[0x81] : seq[?] */
+ cmd[0] = 0 | (ZM_CMD_TALLY << 8);
+ ret = zfIssueCmd(dev, cmd, 4, ZM_OID_TALLY, 0);
+
+ /* len[0] : type[0x82] : seq[?] */
+ cmd[0] = 0 | (ZM_CMD_TALLY_APD << 8);
+ ret = zfIssueCmd(dev, cmd, 4, ZM_OID_TALLY_APD, 0);
+
+ return ret;
+}
+
+
+u32_t zfiDbgSetIFSynthesizer(zdev_t* dev, u32_t value)
+{
+ u32_t cmd[2];
+ u16_t ret;
+
+ /* len[4] : type[0x32] : seq[?] */
+ cmd[0] = 0x4 | (ZM_OID_SYNTH << 8);
+ cmd[1] = value;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_SYNTH, 0);
+ return ret;
+}
+
+u32_t zfiDbgQueryHwTxBusy(zdev_t* dev)
+{
+ u32_t cmd[1];
+ u16_t ret;
+
+ /* len[4] : type[0xC0] : seq[?] */
+ cmd[0] = 0 | (ZM_CMD_DKTX_STATUS << 8);
+
+ ret = zfIssueCmd(dev, cmd, 4, ZM_OID_DKTX_STATUS, 0);
+ return ret;
+}
+
+//Paul++
+#if 0
+u16_t zfHpBlockEraseFlash(zdev_t *dev, u32_t addr)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret;
+
+ cmd[0] = 0x00000004 | (ZM_CMD_FLASH_ERASE << 8);
+ cmd[1] = addr;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_INTERNAL_WRITE, NULL);
+ return ret;
+}
+#endif
+
+#if 0
+u16_t zfiDbgProgramFlash(zdev_t *dev, u32_t offset, u32_t len, u32_t *data)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret;
+ u16_t i;
+
+
+ cmd[0] = (ZM_CMD_FLASH_PROG << 8) | ((len+8) & 0xff);
+ cmd[1] = offset;
+ cmd[2] = len;
+
+ for (i = 0; i < (len >> 2); i++)
+ {
+ cmd[3+i] = data[i];
+ }
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_OID_FLASH_PROGRAM, NULL);
+
+ return ret;
+}
+#endif
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgChipEraseFlash */
+/* Chip Erase Flash. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul Atheros Technology Corporation 2007.09 */
+/* */
+/************************************************************************/
+u16_t zfiDbgChipEraseFlash(zdev_t *dev)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u16_t ret;
+
+ cmd[0] = 0x00000000 | (ZM_CMD_FLASH_ERASE << 8);
+
+ ret = zfIssueCmd(dev, cmd, 4, ZM_OID_INTERNAL_WRITE, NULL);
+ return ret;
+}
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgGetFlashCheckSum */
+/* Get FlashCheckSum. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : Start address of getchksum */
+/* len : total lenth of calculate getchksum */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul Atheros Technology Corporation 2007.08 */
+/* */
+/************************************************************************/
+u32_t zfiDbgGetFlashCheckSum(zdev_t *dev, u32_t addr, u32_t len)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u32_t ret;
+
+ cmd[0] = 0x00000008 | (ZM_CMD_FLASH_CHKSUM << 8);
+ cmd[1] = addr;
+ cmd[2] = len;
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_OID_FLASH_CHKSUM, NULL);
+
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDbgReadFlash */
+/* Read Flash. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* addr : Start address of read flash */
+/* len : total lenth of read flash data */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul Atheros Technology Corporation 2007.09 */
+/* */
+/************************************************************************/
+u32_t zfiDbgReadFlash(zdev_t *dev, u32_t addr, u32_t len)
+{
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u32_t ret;
+
+ cmd[0] = len | (ZM_CMD_FLASH_READ << 8);
+ cmd[1] = addr;
+
+ ret = zfIssueCmd(dev, cmd, 8, ZM_OID_FLASH_READ, NULL);
+ return ret;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiDownloadFwSet */
+/* Before Download FW, */
+/* Command FW to Software reset and close watch dog control. */
+/* */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* 0 : success */
+/* other : fail */
+/* */
+/* AUTHOR */
+/* Paul Atheros Technology Corporation 2007.09 */
+/* */
+/************************************************************************/
+u32_t zfiDownloadFwSet(zdev_t *dev)
+{
+//softwarereset
+//close watch dog
+ u32_t cmd[(ZM_MAX_CMD_SIZE/4)];
+ u32_t ret;
+
+ cmd[0] = 0x00000008 | (ZM_CMD_FW_DL_INIT << 8);
+
+ ret = zfIssueCmd(dev, cmd, 12, ZM_OID_FW_DL_INIT, NULL);
+
+ return ret;
+}
+//Paul--
diff --git a/drivers/staging/otus/hal/hpusb.c b/drivers/staging/otus/hal/hpusb.c
new file mode 100644
index 000000000000..4b76de93fff0
--- /dev/null
+++ b/drivers/staging/otus/hal/hpusb.c
@@ -0,0 +1,1584 @@
+/*
+ * Copyright (c) 2000-2005 ZyDAS Technology Corporation
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : ud.c */
+/* */
+/* Abstract */
+/* This module contains USB descriptor functions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+#include "../80211core/cprecomp.h"
+#include "hpani.h"
+#include "hpusb.h"
+
+extern void zfwUsbCmd(zdev_t* dev, u8_t endpt, u32_t* cmd, u16_t cmdLen);
+
+extern void zfIdlRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen);
+extern u16_t zfDelayWriteInternalReg(zdev_t* dev, u32_t addr, u32_t val);
+extern u16_t zfFlushDelayWrite(zdev_t* dev);
+
+
+#define USB_ENDPOINT_TX_INDEX 1
+#define USB_ENDPOINT_RX_INDEX 2
+#define USB_ENDPOINT_INT_INDEX 3
+#define USB_ENDPOINT_CMD_INDEX 4
+
+void zfIdlCmd(zdev_t* dev, u32_t* cmd, u16_t cmdLen)
+{
+#if ZM_SW_LOOP_BACK != 1
+ zfwUsbCmd(dev, USB_ENDPOINT_CMD_INDEX, cmd, cmdLen);
+#endif
+
+ return;
+}
+
+
+/* zfAdjustCtrlSetting: fit OUTS format */
+/* convert MIMO2 to OUTS */
+void zfAdjustCtrlSetting(zdev_t* dev, u16_t* header, zbuf_t* buf)
+{
+ /* MIMO2 => OUTS FB-50 */
+ /* length not change, only modify format */
+
+ u32_t oldMT;
+ u32_t oldMCS;
+
+ u32_t phyCtrl;
+ u32_t oldPhyCtrl;
+
+ u16_t tpc = 0;
+
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ /* mm */
+ if (header == NULL)
+ {
+ oldPhyCtrl = zmw_buf_readh(dev, buf, 4) | ((u32_t)zmw_buf_readh(dev, buf, 6) << 16);
+ }
+ else
+ {
+ oldPhyCtrl = header[2] | ((u32_t)header[3] <<16);
+ }
+
+ phyCtrl = 0;
+
+
+ /* MT : Bit[1~0] */
+ oldMT = oldPhyCtrl&0x3;
+ phyCtrl |= oldMT;
+ if ( oldMT == 0x3 ) /* DL-OFDM (Duplicate Legacy OFDM) */
+ phyCtrl |= 0x1;
+
+
+ /* PT : Bit[2] HT PT: 0 Mixed mode 1 Green field */
+ phyCtrl |= (oldPhyCtrl&0x4);
+
+ /* Bandwidth control : Bit[4~3] */
+ if ( oldPhyCtrl&0x800000 ) /* Bit23 : 40M */
+ {
+ #if 0
+ if (oldMT == 0x3) /* DL-OFDM */
+ phyCtrl |= (0x3<<3); /* 40M duplicate */
+ else
+ phyCtrl |= (0x2<<3); /* 40M shared */
+ #else
+ if (oldMT == 0x2 && ((struct zsHpPriv*)wd->hpPrivate)->hwBw40)
+ {
+ phyCtrl |= (0x2<<3); /* 40M shared */
+ }
+ #endif
+ }
+ else {
+ oldPhyCtrl &= ~0x80000000;
+ }
+
+ /* MCS : Bit[24~18] */
+ oldMCS = (oldPhyCtrl&0x7f0000)>>16; /* Bit[22~16] */
+ phyCtrl |= (oldMCS<<18);
+
+ /* Short GI : Bit[31]*/
+ phyCtrl |= (oldPhyCtrl&0x80000000);
+
+ /* AM : Antenna mask */
+ //if ((oldMT == 2) && (oldMCS > 7))
+ if (hpPriv->halCapability & ZM_HP_CAP_11N_ONE_TX_STREAM)
+ {
+ phyCtrl |= (0x1<<15);
+ }
+ else
+ {
+ /* HT Tx 2 chain */
+ /* OFDM 6M/9M/12M/18M/24M Tx 2 chain */
+ /* OFDM 36M/48M/54M/ Tx 1 chain */
+ /* CCK Tx 2 chain */
+ if ((oldMT == 2) || (oldMT == 3))
+ {
+ phyCtrl |= (0x5<<15);
+ }
+ else if (oldMT == 1)
+ {
+ if ((oldMCS == 0xb) || (oldMCS == 0xf) ||
+ (oldMCS == 0xa) || (oldMCS == 0xe) ||
+ (oldMCS == 0x9)) //6M/9M/12M/18M/24M
+ {
+ phyCtrl |= (0x5<<15);
+ }
+ else
+ {
+ phyCtrl |= (0x1<<15);
+ }
+ }
+ else //(oldMT==0)
+ {
+ phyCtrl |= (0x5<<15);
+ }
+ }
+ //else
+ // phyCtrl |= (0x1<<15);
+
+ /* TPC */
+ /* TODO : accelerating these code */
+ if (hpPriv->hwFrequency < 3000)
+ {
+ if (oldMT == 0)
+ {
+ /* CCK */
+ tpc = (hpPriv->tPow2xCck[oldMCS]&0x3f);
+ }
+ else if (oldMT == 1)
+ {
+ /* OFDM */
+ if (oldMCS == 0xc)
+ {
+ tpc = (hpPriv->tPow2x2g[3]&0x3f);
+ }
+ else if (oldMCS == 0x8)
+ {
+ tpc = (hpPriv->tPow2x2g[2]&0x3f);
+ }
+ else if (oldMCS == 0xd)
+ {
+ tpc = (hpPriv->tPow2x2g[1]&0x3f);
+ }
+ else if (oldMCS == 0x9)
+ {
+ tpc = ((hpPriv->tPow2x2g[0]-hpPriv->tPow2x2g24HeavyClipOffset)&0x3f);
+ }
+ else
+ {
+ tpc = (hpPriv->tPow2x2g[0]&0x3f);
+ }
+ }
+ else if (oldMT == 2)
+ {
+ if ( oldPhyCtrl&0x800000 ) /* Bit23 : 40M */
+ {
+ /* HT 40 */
+ tpc = (hpPriv->tPow2x2gHt40[oldMCS&0x7]&0x3f);
+ }
+ else
+ {
+ /* HT 20 */
+ tpc = (hpPriv->tPow2x2gHt20[oldMCS&0x7]&0x3f);
+ }
+ }
+ }
+ else //5GHz
+ {
+ if (oldMT == 1)
+ {
+ /* OFDM */
+ if (oldMCS == 0xc)
+ {
+ tpc = (hpPriv->tPow2x5g[3]&0x3f);
+ }
+ else if (oldMCS == 0x8)
+ {
+ tpc = (hpPriv->tPow2x5g[2]&0x3f);
+ }
+ else if (oldMCS == 0xd)
+ {
+ tpc = (hpPriv->tPow2x5g[1]&0x3f);
+ }
+ else
+ {
+ tpc = (hpPriv->tPow2x5g[0]&0x3f);
+ }
+ }
+ else if (oldMT == 2)
+ {
+ if ( oldPhyCtrl&0x800000 ) /* Bit23 : 40M */
+ {
+ /* HT 40 */
+ tpc = (hpPriv->tPow2x5gHt40[oldMCS&0x7]&0x3f);
+ }
+ else
+ {
+ /* HT 20 */
+ tpc = (hpPriv->tPow2x5gHt20[oldMCS&0x7]&0x3f);
+ }
+ }
+ }
+
+ /* Tx power adjust for HT40 */
+ /* HT40 +1dBm */
+ if ((oldMT==2) && (oldPhyCtrl&0x800000) )
+ {
+ tpc += 2;
+ }
+ tpc &= 0x3f;
+
+ /* Evl force tx TPC */
+ if(wd->forceTxTPC)
+ {
+ tpc = (u16_t)(wd->forceTxTPC & 0x3f);
+ }
+
+ if (hpPriv->hwFrequency < 3000) {
+ wd->maxTxPower2 &= 0x3f;
+ tpc = (tpc > wd->maxTxPower2)? wd->maxTxPower2 : tpc;
+ } else {
+ wd->maxTxPower5 &= 0x3f;
+ tpc = (tpc > wd->maxTxPower5)? wd->maxTxPower5 : tpc;
+ }
+
+
+#define ZM_MIN_TPC 5
+#define ZM_TPC_OFFSET 5
+#define ZM_SIGNAL_THRESHOLD 56
+ if ((wd->sta.bScheduleScan == FALSE) && (wd->sta.bChannelScan == FALSE))
+ {
+ if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE )
+ && (zfStaIsConnected(dev))
+ && (wd->SignalStrength > ZM_SIGNAL_THRESHOLD))
+ {
+ if (tpc > ((ZM_MIN_TPC+ZM_TPC_OFFSET)*2))
+ {
+ tpc -= (ZM_TPC_OFFSET*2);
+ }
+ else if (tpc > (ZM_MIN_TPC*2))
+ {
+ tpc = (ZM_MIN_TPC*2);
+ }
+ }
+ }
+#undef ZM_MIN_TPC
+#undef ZM_TPC_OFFSET
+#undef ZM_SIGNAL_THRESHOLD
+
+ #ifndef ZM_OTUS_LINUX_PHASE_2
+ phyCtrl |= (tpc & 0x3f) << 9;
+ #endif
+
+ /* Set bits[8:6]BF-MCS for heavy clip */
+ if ((phyCtrl&0x3) == 2)
+ {
+ phyCtrl |= ((phyCtrl >> 12) & 0x1c0);
+ }
+
+ /* PHY control */
+ if (header == NULL)
+ {
+ zmw_buf_writeh(dev, buf, 4, (u16_t) (phyCtrl&0xffff));
+ zmw_buf_writeh(dev, buf, 6, (u16_t) (phyCtrl>>16));
+ }
+ else
+ {
+ //PHY control L
+ header[2] = (u16_t) (phyCtrl&0xffff);
+ //PHY control H
+ header[3] = (u16_t) (phyCtrl>>16);
+ }
+
+ zm_msg2_tx(ZM_LV_2, "old phy ctrl = ", oldPhyCtrl);
+ zm_msg2_tx(ZM_LV_2, "new phy ctrl = ", phyCtrl);
+ //DbgPrint("old phy ctrl =%08x \n", oldPhyCtrl);
+ //DbgPrint("new phy ctrl =%08x \n", phyCtrl);
+}
+
+
+#define EXTRA_INFO_LEN 24 //RSSI(7) + EVM(12) + PHY(1) + MACStatus(4)
+u16_t zfHpSend(zdev_t* dev, u16_t* header, u16_t headerLen,
+ u16_t* snap, u16_t snapLen,
+ u16_t* tail, u16_t tailLen, zbuf_t* buf, u16_t offset,
+ u16_t bufType, u8_t ac, u8_t keyIdx)
+{
+#if ZM_SW_LOOP_BACK == 1
+ zbuf_t *rxbuf;
+ u8_t *puRxBuf;
+ u8_t *pHdr;
+ u8_t *psnap;
+ u16_t plcplen = 12;
+ u16_t i;
+ u16_t swlpOffset;
+#endif /* #if ZM_SW_LOOP_BACK == 1 */
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zm_msg1_tx(ZM_LV_1, "zfHpSend(), len = ", 12 + headerLen-8 + snapLen + zfwBufGetSize(dev, buf) + 4 + 8);
+
+ /* Adjust ctrl setting : 6N14 yjsung */
+ zfAdjustCtrlSetting(dev, header, buf);
+
+#if ZM_SW_LOOP_BACK != 1
+ hpPriv->usbSendBytes += zfwBufGetSize(dev, buf);
+ hpPriv->usbAcSendBytes[ac&0x3] += zfwBufGetSize(dev, buf);
+
+ /* Submit USB Out Urb */
+ zfwUsbSend(dev, USB_ENDPOINT_TX_INDEX, (u8_t *)header, headerLen,
+ (u8_t *)snap, snapLen, (u8_t *)tail, tailLen, buf, offset);
+#endif
+
+#if ZM_SW_LOOP_BACK == 1
+
+ rxbuf = zfwBufAllocate(dev, plcplen + headerLen-8 + snapLen + (zfwBufGetSize(dev, buf)-offset) + 4 + EXTRA_INFO_LEN);
+ pHdr = (u8_t *) header+8;
+ psnap = (u8_t *) snap;
+
+ zmw_enter_critical_section(dev);
+ /* software loop back */
+ /* Copy WLAN header and packet buffer */
+ swlpOffset = plcplen;
+
+ for(i = 0; i < headerLen-8; i++)
+ {
+ zmw_rx_buf_writeb(dev, rxbuf, swlpOffset+i, pHdr[i]);
+ }
+
+ swlpOffset += headerLen-8;
+
+ /* Copy SNAP header */
+ for(i = 0; i < snapLen; i++)
+ {
+ zmw_rx_buf_writeb(dev, rxbuf, swlpOffset+i, psnap[i]);
+ }
+
+ swlpOffset += snapLen;
+
+ /* Copy body from tx buf to rxbuf */
+ for(i = 0; i < (zfwBufGetSize(dev, buf)-offset); i++)
+ {
+ u8_t value = zmw_rx_buf_readb(dev, buf, i+offset);
+ zmw_rx_buf_writeb(dev, rxbuf, swlpOffset+i, value);
+ }
+
+ /* total length = PLCP + MacHeader + Payload + FCS + RXstatus */
+ /* 12 + headerLen-8 + snapLen + buf length + 4 + 8 */
+ zfwSetBufSetSize(dev, rxbuf, swlpOffset + (zfwBufGetSize(dev, buf)-offset) + 4 + EXTRA_INFO_LEN );
+
+ zmw_leave_critical_section(dev);
+
+ zfwBufFree(dev, buf, 0);
+
+ //zfwDumpBuf(dev, rxbuf);
+ //-------------------------------------------------
+
+ //zfCoreRecv(dev, rxbuf);
+
+#endif /* #if ZM_SW_LOOP_BACK */
+
+ return ZM_SUCCESS;
+}
+
+/* Report moniter Hal rx information about rssi, evm, bandwidth, SG etc */
+void zfHpQueryMonHalRxInfo(zdev_t* dev, u8_t *monHalRxInfo)
+{
+ zmw_get_wlan_dev(dev);
+ zfMemoryCopy(monHalRxInfo,
+ (u8_t*)&(((struct zsHpPriv*)wd->hpPrivate)->halRxInfo),
+ sizeof(struct zsHalRxInfo));
+}
+
+
+u8_t zfIsDataFrame(zdev_t* dev, zbuf_t* buf)
+{
+ u8_t frameType;
+ u8_t mpduInd;
+
+ mpduInd = zmw_rx_buf_readb(dev, buf, zfwBufGetSize(dev, buf)-1);
+
+ /* sinlge or First */
+ if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x20)
+ {
+ frameType = zmw_rx_buf_readb(dev, buf, 12);
+ }
+ else
+ {
+ frameType = zmw_rx_buf_readb(dev, buf, 0);
+ }
+
+ if((frameType & 0xf) == ZM_WLAN_DATA_FRAME)
+ return 1;
+ else
+ return 0;
+}
+
+u32_t zfcConvertRateOFDM(zdev_t* dev, zbuf_t* buf)
+{
+ // What's the default value??
+ u32_t MCS = 0;
+
+ switch(zmw_rx_buf_readb(dev, buf, 0)& 0xf)
+ {
+ case 0xb:
+ MCS = 0x4;
+ break;
+ case 0xf:
+ MCS = 0x5;
+ break;
+ case 0xa:
+ MCS = 0x6;
+ break;
+ case 0xe:
+ MCS = 0x7;
+ break;
+ case 0x9:
+ MCS = 0x8;
+ break;
+ case 0xd:
+ MCS = 0x9;
+ break;
+ case 0x8:
+ MCS = 0xa;
+ break;
+ case 0xc:
+ MCS = 0xb;
+ break;
+ }
+ return MCS;
+}
+
+u16_t zfHpGetPayloadLen(zdev_t* dev,
+ zbuf_t* buf,
+ u16_t len,
+ u16_t plcpHdrLen,
+ u32_t *rxMT,
+ u32_t *rxMCS,
+ u32_t *rxBW,
+ u32_t *rxSG
+ )
+{
+ u8_t modulation,mpduInd;
+ u16_t low, high, msb;
+ s16_t payloadLen = 0;
+
+ zmw_get_wlan_dev(dev);
+
+ mpduInd = zmw_rx_buf_readb(dev, buf, len-1);
+ modulation = zmw_rx_buf_readb(dev, buf, (len-1)) & 0x3;
+ *rxMT = modulation;
+
+ //zm_debug_msg1(" modulation= ", modulation);
+ switch (modulation) {
+ case 0: /* CCK Mode */
+ low = zmw_rx_buf_readb(dev, buf, 2);
+ high = zmw_rx_buf_readb(dev, buf, 3);
+ payloadLen = (low | high << 8) - 4;
+ if (wd->enableHALDbgInfo)
+ {
+ *rxMCS = zmw_rx_buf_readb(dev, buf, 0);
+ *rxBW = 0;
+ *rxSG = 0;
+ }
+ break;
+ case 1: /* Legacy-OFDM mode */
+ low = zmw_rx_buf_readb(dev, buf, 0) >> 5;
+ high = zmw_rx_buf_readb(dev, buf, 1);
+ msb = zmw_rx_buf_readb(dev, buf, 2) & 0x1;
+ payloadLen = (low | (high << 3) | (msb << 11)) - 4;
+ if (wd->enableHALDbgInfo)
+ {
+ *rxMCS = zfcConvertRateOFDM(dev, buf);
+ *rxBW = 0;
+ *rxSG = 0;
+ }
+ break;
+ case 2: /* HT OFDM mode */
+ //zm_debug_msg1("aggregation= ", (zmw_rx_buf_readb(dev, buf, 6) >> 3) &0x1 );
+ if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x10) //single or last mpdu
+ payloadLen = len - 24 - 4 - plcpHdrLen; // - rxStatus - fcs
+ else {
+ payloadLen = len - 4 - 4 - plcpHdrLen; // - rxStatus - fcs
+ //zm_debug_msg1("first or middle mpdu, plcpHdrLen= ", plcpHdrLen);
+ }
+ if (wd->enableHALDbgInfo)
+ {
+ *rxMCS = zmw_rx_buf_readb(dev, buf, 3) & 0x7f;
+ *rxBW = (zmw_rx_buf_readb(dev, buf, 3) >> 7) & 0x1;
+ *rxSG = (zmw_rx_buf_readb(dev, buf, 6) >> 7) & 0x1;
+ }
+ break;
+ default:
+ break;
+
+ }
+ /* return the payload length - FCS */
+ if (payloadLen < 0) payloadLen = 0;
+ return payloadLen;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfiUsbRecv */
+/* Callback function for USB IN Transfer. */
+/* */
+/* INPUTS */
+/* dev: device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Yuan-Gu Wei ZyDAS Technology Corporation 2005.10 */
+/* */
+/************************************************************************/
+#define ZM_INT_USE_EP2 1
+#define ZM_INT_USE_EP2_HEADER_SIZE 12
+
+#if ZM_INT_USE_EP2 == 1
+void zfiUsbRegIn(zdev_t* dev, u32_t* rsp, u16_t rspLen);
+#endif
+
+#ifdef ZM_OTUS_RX_STREAM_MODE
+void zfiUsbRecvPerPkt(zdev_t *dev, zbuf_t *buf)
+#else
+void zfiUsbRecv(zdev_t *dev, zbuf_t *buf)
+#endif
+{
+
+
+#if ZM_FW_LOOP_BACK != 1
+ u8_t mpduInd;
+ u16_t plcpHdrLen;
+ u16_t crcPlusRxStatusLen;
+ u16_t len, payloadLen=0;
+ u16_t i; //CWYang(+)
+ struct zsAdditionInfo addInfo;
+ u32_t rxMT;
+ u32_t rxMCS;
+ u32_t rxBW;
+ u32_t rxSG;
+ zmw_get_wlan_dev(dev);
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ //zm_msg0_rx(ZM_LV_0, "zfiUsbRecv()");
+
+#if ZM_INT_USE_EP2 == 1
+
+ for (i=0; i<(ZM_INT_USE_EP2_HEADER_SIZE>>1); i++)
+ {
+ if (zmw_rx_buf_readh(dev, buf, i*2) != 0xffff)
+ break;
+ }
+
+ if (i==(ZM_INT_USE_EP2_HEADER_SIZE>>1))
+ {
+ u32_t rsp[ZM_USB_MAX_EPINT_BUFFER/4];
+ u16_t rspLen;
+ u32_t rspi;
+ u8_t* pdst = (u8_t*)rsp;
+
+ /* Interrupt Rsp */
+ rspLen = (u16_t) zfwBufGetSize(dev, buf)-ZM_INT_USE_EP2_HEADER_SIZE;
+
+ if (rspLen > 60)
+ {
+ zm_debug_msg1("Get error len by EP2 = \n", rspLen);
+ /* free USB buf */
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ for (rspi=0; rspi<rspLen; rspi++)
+ {
+ *pdst = zmw_rx_buf_readb(dev, buf, rspi+ZM_INT_USE_EP2_HEADER_SIZE);
+ pdst++;
+ }
+
+ //if (adapter->zfcbUsbRegIn)
+ // adapter->zfcbUsbRegIn(adapter, rsp, rspLen);
+ zfiUsbRegIn(dev, rsp, rspLen);
+
+ /* free USB buf */
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+#endif /* end of #if ZM_INT_USE_EP2 == 1 */
+
+ ZM_PERFORMANCE_RX_MPDU(dev, buf);
+
+ if (wd->swSniffer)
+ {
+ /* airopeek: Report everything up */
+ if (wd->zfcbRecv80211 != NULL)
+ {
+ wd->zfcbRecv80211(dev, buf, NULL);
+ }
+ }
+
+ /* Read the last byte */
+ len = zfwBufGetSize(dev, buf);
+ mpduInd = zmw_rx_buf_readb(dev, buf, len-1);
+
+ /* First MPDU */
+ if((mpduInd & 0x30) == 0x20)
+ {
+ u16_t duration;
+ if (zmw_rx_buf_readb(dev, buf, 36) == 0) //AC = BE
+ {
+ duration = zmw_rx_buf_readh(dev, buf, 14);
+ if (duration > hpPriv->aggMaxDurationBE)
+ {
+ hpPriv->aggMaxDurationBE = duration;
+ }
+ else
+ {
+ if (hpPriv->aggMaxDurationBE > 10)
+ {
+ hpPriv->aggMaxDurationBE--;
+ }
+ }
+ //DbgPrint("aggMaxDurationBE=%d", hpPriv->aggMaxDurationBE);
+ }
+ }
+
+#if 1
+ /* First MPDU or Single MPDU */
+ if(((mpduInd & 0x30) == 0x00) || ((mpduInd & 0x30) == 0x20))
+ //if ((mpduInd & 0x10) == 0x00)
+ {
+ plcpHdrLen = 12; // PLCP header length
+ }
+ else
+ {
+ if (zmw_rx_buf_readh(dev, buf, 4) == wd->macAddr[0] &&
+ zmw_rx_buf_readh(dev, buf, 6) == wd->macAddr[1] &&
+ zmw_rx_buf_readh(dev, buf, 8) == wd->macAddr[2]) {
+ plcpHdrLen = 0;
+ }
+ else if (zmw_rx_buf_readh(dev, buf, 16) == wd->macAddr[0] &&
+ zmw_rx_buf_readh(dev, buf, 18) == wd->macAddr[1] &&
+ zmw_rx_buf_readh(dev, buf, 20) == wd->macAddr[2]){
+ plcpHdrLen = 12;
+ }
+ else {
+ plcpHdrLen = 0;
+ }
+ }
+
+ /* Last MPDU or Single MPDU */
+ if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x10)
+ {
+ crcPlusRxStatusLen = EXTRA_INFO_LEN + 4; // Extra bytes + FCS
+ }
+ else
+ {
+ crcPlusRxStatusLen = 4 + 4; // Extra 4 bytes + FCS
+ }
+#else
+ plcpHdrLen = 12;
+ crcPlusRxStatusLen = EXTRA_INFO_LEN + 4; // Extra bytes + FCS
+#endif
+
+ if (len < (plcpHdrLen+10+crcPlusRxStatusLen))
+ {
+ zm_msg1_rx(ZM_LV_0, "Invalid Rx length=", len);
+ //zfwDumpBuf(dev, buf);
+
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ /* display RSSI combined */
+ /*
+ * zwwwwwwwwwwwwwswwwwwwwwswwwwwwswwwwwwswwwwwwwwwswwwwwwwwwwwww{
+ * x PLCP Header x MPDU x RSSI x EVM x PHY Err x MAC Status x
+ * uwwwwwwwwwwwwwqwwwwwwwwqwwwwwwqwwwwwwqwwwwwwwwwqwwwwwwwwwwwwwt
+ * x 12 x n x 7 x 12 x 1 x 4 x
+ * |wwwwwwwwwwwwwrwwwwwwwwrwwwwwwrwwwwwwrwwwwwwwwwrwwwwwwwwwwwww}
+ * RSSI filed (From BB and MAC just pass them to host)
+ * Byte1: RSSI for antenna 0.
+ * Byte2: RSSI for antenna 1.
+ * Byte3: RSSI for antenna 2.
+ * Byte4: RSSI for antenna 0 extension.
+ * Byte5: RSSI for antenna 1 extension.
+ * Byte6: RSSI for antenna 2 extension.
+ * Byte7: RSSI for antenna combined.
+ */
+
+ //zm_debug_msg1(" recv RSSI = ", zmw_rx_buf_readb(dev, buf, (len-1)-17));
+
+ payloadLen = zfHpGetPayloadLen(dev, buf, len, plcpHdrLen, &rxMT, &rxMCS, &rxBW, &rxSG);
+
+ /* Hal Rx info */
+ /* First MPDU or Single MPDU */
+ if(((mpduInd & 0x30) == 0x00) || ((mpduInd & 0x30) == 0x20))
+ {
+ if (wd->enableHALDbgInfo && zfIsDataFrame(dev, buf))
+ {
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataMT = rxMT;
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataMCS = rxMCS;
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataBW = rxBW;
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxDataSG = rxSG;
+ }
+ }
+
+ if ((plcpHdrLen + payloadLen) > len) {
+ zm_msg1_rx(ZM_LV_0, "Invalid payload length=", payloadLen);
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ //Store Rx Tail Infomation before Remove--CWYang(+)
+
+#if 0
+ for (i = 0; i < crcPlusRxStatusLen-4; i++)
+ {
+ addInfo.Tail.Byte[i] =
+ zmw_rx_buf_readb(dev, buf, len - crcPlusRxStatusLen + 4 + i);
+ }
+#else
+/*
+* Brief format of OUTS chip
+* zwwwwwwwwwwwwwswwwwwwwwswwwwwwswwwwwwswwwwwwwwwswwwwwwwwwwwww{
+* x PLCP Header x MPDU x RSSI x EVM x PHY Err x MAC Status x
+* uwwwwwwwwwwwwwqwwwwwwwwqwwwwwwqwwwwwwqwwwwwwwwwqwwwwwwwwwwwwwt
+* x 12 x n x 7 x 12 x 1 x 4 x
+* |wwwwwwwwwwwwwrwwwwwwwwrwwwwwwrwwwwwwrwwwwwwwwwrwwwwwwwwwwwww}
+* RSSI:
+* Byte 1 antenna 0
+* Byte 2 antenna 1
+* Byte 3 antenna 2
+* Byte 4 antenna 0 extension
+* Byte 5 antenna 1 extension
+* Byte 6 antenna 2 extension
+* Byte 7 antenna combined
+* EVM:
+* Byte 1 Stream 0 pilot 0
+* Byte 2 Stream 0 pilot 1
+* Byte 3 Stream 0 pilot 2
+* Byte 4 Stream 0 pilot 3
+* Byte 5 Stream 0 pilot 4
+* Byte 6 Stream 0 pilot 5
+* Byte 7 Stream 1 pilot 0
+* Byte 8 Stream 1 pilot 1
+* Byte 9 Stream 1 pilot 2
+* Byte 10 Stream 1 pilot 3
+* Byte 11 Stream 1 pilot 4
+* Byte 12 Stream 1 pilot 5
+*/
+
+ /* Fill the Tail information */
+ /* Last MPDU or Single MPDU */
+ if ((mpduInd & 0x30) == 0x00 || (mpduInd & 0x30) == 0x10)
+ {
+#define ZM_RX_RSSI_COMPENSATION 27
+ u8_t zm_rx_rssi_compensation = ZM_RX_RSSI_COMPENSATION;
+
+ /* RSSI information */
+ addInfo.Tail.Data.SignalStrength1 = zmw_rx_buf_readb(dev, buf,
+ (len-1) - 17) + ((hpPriv->rxStrongRSSI == 1)?zm_rx_rssi_compensation:0);
+#undef ZM_RX_RSSI_COMPENSATION
+
+ /* EVM */
+
+ /* TODO: for RD/BB debug message */
+ /* save current rx hw infomration, report to DrvCore/Application */
+ if (wd->enableHALDbgInfo && zfIsDataFrame(dev, buf))
+ {
+ u8_t trssi;
+ for (i=0; i<7; i++)
+ {
+ trssi = zmw_rx_buf_readb(dev, buf, (len-1) - 23 + i);
+ if (trssi&0x80)
+ {
+ trssi = ((~((u8_t)trssi) & 0x7f) + 1) & 0x7f;
+ }
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[i] = trssi;
+
+ }
+ if (rxMT==2)
+ {
+ //if (rxBW)
+ //{
+ for (i=0; i<12; i++)
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[i] =
+ zmw_rx_buf_readb(dev, buf, (len-1) - 16 + i);
+ //}
+ //else
+ //{
+ // for (i=0; i<4; i++)
+ // ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[i] =
+ // zmw_rx_buf_readb(dev, buf, (len-1) - 16 + i);
+ //}
+ }
+
+ #if 0
+ /* print */
+ zm_dbg(("MT(%d) MCS(%d) BW(%d) SG(%d) RSSI:%d,%d,%d,%d,%d,%d,%d EVM:(%d,%d,%d,%d,%d,%d)(%d,%d,%d,%d,%d,%d)\n",
+ rxMT,
+ rxMCS,
+ rxBW,
+ rxSG,
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[0],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[1],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[2],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[3],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[4],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[5],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRSSI[6],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[0],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[1],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[2],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[3],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[4],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[5],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[6],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[7],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[8],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[9],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[10],
+ ((struct zsHpPriv*)wd->hpPrivate)->halRxInfo.currentRxEVM[11]
+ ));
+ #endif
+ } /* if (wd->enableHALDbgInfo && zfIsDataFrame(dev, buf)) */
+
+ }
+ else
+ {
+ /* Mid or First aggregate frame without phy rx information */
+ addInfo.Tail.Data.SignalStrength1 = 0;
+ }
+
+ addInfo.Tail.Data.SignalStrength2 = 0;
+ addInfo.Tail.Data.SignalStrength3 = 0;
+ addInfo.Tail.Data.SignalQuality = 0;
+
+ addInfo.Tail.Data.SAIndex = zmw_rx_buf_readb(dev, buf, len - 4);
+ addInfo.Tail.Data.DAIndex = zmw_rx_buf_readb(dev, buf, len - 3);
+ addInfo.Tail.Data.ErrorIndication = zmw_rx_buf_readb(dev, buf, len - 2);
+ addInfo.Tail.Data.RxMacStatus = zmw_rx_buf_readb(dev, buf, len - 1);
+
+#endif
+ /* Remove CRC and Rx Status */
+ zfwBufSetSize(dev, buf, (len-crcPlusRxStatusLen));
+ //zfwBufSetSize(dev, buf, payloadLen + plcpHdrLen); /* payloadLen + PLCP 12 - FCS 4*/
+
+ //Store PLCP Header Infomation before Remove--CWYang(+)
+ if (plcpHdrLen != 0)
+ {
+ for (i = 0; i < plcpHdrLen; i++)
+ {
+ addInfo.PlcpHeader[i] = zmw_rx_buf_readb(dev, buf, i);
+ }
+ }
+ else
+ {
+ addInfo.PlcpHeader[0] = 0;
+ }
+ /* Remove PLCP header */
+ zfwBufRemoveHead(dev, buf, plcpHdrLen);
+
+ /* handle 802.11 frame */
+ zfCoreRecv(dev, buf, &addInfo);
+
+#else
+ /* Firmware loopback: Rx frame = Tx frame */
+ /* convert Rx frame to fit receive frame format */
+ zbuf_t *new_buf;
+ u8_t ctrl_offset = 8;
+ u8_t PLCP_Len = 12;
+ u8_t data;
+ u8_t i;
+
+
+ /* Tx: | ctrl_setting | Mac hdr | data | */
+ /* 8 24 x */
+
+ /* Rx: | PLCP | Mac hdr | data | FCS | Rxstatus | */
+ /* 12 24 x 4 8 */
+
+ /* new allocate a rx format size buf */
+ new_buf = zfwBufAllocate(dev, zfwBufGetSize(dev, buf)-8+12+4+EXTRA_INFO_LEN);
+
+ for (i=0; i<zfwBufGetSize(dev, buf)-ctrl_offset; i++)
+ {
+ data = zmw_rx_buf_readb(dev, buf, ctrl_offset+i);
+ zmw_rx_buf_writeb(dev, new_buf, PLCP_Len+i, data);
+ }
+
+ zfwBufSetSize(dev, new_buf, zfwBufGetSize(dev, buf)-8+12+4+EXTRA_INFO_LEN);
+
+ zfwBufFree(dev, buf, 0);
+
+ /* receive the new_buf */
+ //zfCoreRecv(dev, new_buf);
+
+#endif
+
+}
+
+#ifdef ZM_OTUS_RX_STREAM_MODE
+void zfiUsbRecv(zdev_t *dev, zbuf_t *buf)
+{
+ u16_t index = 0;
+ u16_t chkIdx;
+ u32_t status = 0;
+ u16_t ii;
+ zbuf_t *newBuf;
+ zbuf_t *rxBufPool[8];
+ u16_t rxBufPoolIndex = 0;
+ struct zsHpPriv *halPriv;
+ u8_t *srcBufPtr;
+ u32_t bufferLength;
+ u16_t usbRxRemainLen;
+ u16_t usbRxPktLen;
+
+ zmw_get_wlan_dev(dev);
+
+ halPriv = (struct zsHpPriv*)wd->hpPrivate;
+ srcBufPtr = zmw_buf_get_buffer(dev, buf);
+
+ bufferLength = zfwBufGetSize(dev, buf);
+
+ /* Zero Length Transfer */
+ if (!bufferLength)
+ {
+ zfwBufFree(dev, buf, 0);
+ return;
+ }
+
+ usbRxRemainLen = halPriv->usbRxRemainLen;
+ usbRxPktLen = halPriv->usbRxTransferLen;
+
+ /* Check whether there is any data in the last transfer */
+ if (usbRxRemainLen != 0 )
+ {
+ zbuf_t *remainBufPtr = halPriv->remainBuf;
+ u8_t* BufPtr = NULL;
+
+ if ( remainBufPtr != NULL )
+ {
+ BufPtr = zmw_buf_get_buffer(dev, remainBufPtr);
+ }
+
+ index = usbRxRemainLen;
+ usbRxRemainLen -= halPriv->usbRxPadLen;
+
+ /* Copy data */
+ if ( BufPtr != NULL )
+ {
+ zfwMemoryCopy(&(BufPtr[usbRxPktLen]), srcBufPtr, usbRxRemainLen);
+ }
+
+ usbRxPktLen += usbRxRemainLen;
+ halPriv->usbRxRemainLen = 0;
+
+ if ( remainBufPtr != NULL )
+ {
+ zfwBufSetSize(dev, remainBufPtr, usbRxPktLen);
+ rxBufPool[rxBufPoolIndex++] = remainBufPtr;
+ }
+ halPriv->remainBuf = NULL;
+ }
+
+ //zm_debug_msg1("length: %d\n", (int)pUsbRxTransfer->pRxUrb->UrbBulkOrInterruptTransfer.TransferBufferLength);
+
+ bufferLength = zfwBufGetSize(dev, buf);
+//printk("bufferLength %d\n", bufferLength);
+ while(index < bufferLength)
+ {
+ u16_t pktLen;
+ u16_t pktTag;
+ //u8_t *ptr = (u8_t*)((struct zsBuffer*)pUsbRxTransfer->buf)->data;
+ u8_t *ptr = srcBufPtr;
+
+ /* Retrieve packet length and tag */
+ pktLen = ptr[index] + (ptr[index+1] << 8);
+ pktTag = ptr[index+2] + (ptr[index+3] << 8);
+
+ if (pktTag == ZM_USB_STREAM_MODE_TAG)
+ {
+ u16_t padLen;
+
+ zm_assert(pktLen < ZM_WLAN_MAX_RX_SIZE);
+
+ //printk("Get a packet, pktLen: 0x%04x\n", pktLen);
+ #if 0
+ /* Dump data */
+ for (ii = index; ii < pkt_len+4;)
+ {
+ DbgPrint("0x%02x ",
+ (zmw_rx_buf_readb(adapter, pUsbRxTransfer->buf, ii) & 0xff));
+
+ if ((++ii % 16) == 0)
+ DbgPrint("\n");
+ }
+
+ DbgPrint("\n");
+ #endif
+
+ /* Calcuate the padding length, in the current design,
+ the length should be padded to 4 byte boundray. */
+ padLen = ZM_USB_STREAM_MODE_TAG_LEN - (pktLen & 0x3);
+
+ if(padLen == ZM_USB_STREAM_MODE_TAG_LEN)
+ padLen = 0;
+
+ chkIdx = index;
+ index = index + ZM_USB_STREAM_MODE_TAG_LEN + pktLen + padLen;
+
+ if (chkIdx > ZM_MAX_USB_IN_TRANSFER_SIZE)
+ {
+ zm_debug_msg1("chkIdx is too large, chkIdx: %d\n", chkIdx);
+ zm_assert(0);
+ status = 1;
+ break;
+ }
+
+ if (index > ZM_MAX_USB_IN_TRANSFER_SIZE)
+ {
+ //struct zsBuffer* BufPtr;
+ //struct zsBuffer* UsbBufPtr;
+ u8_t *BufPtr;
+ u8_t *UsbBufPtr;
+
+ halPriv->usbRxRemainLen = index - ZM_MAX_USB_IN_TRANSFER_SIZE; // - padLen;
+ halPriv->usbRxTransferLen = ZM_MAX_USB_IN_TRANSFER_SIZE -
+ chkIdx - ZM_USB_STREAM_MODE_TAG_LEN;
+ halPriv->usbRxPadLen = padLen;
+ //check_index = index;
+
+ if (halPriv->usbRxTransferLen > ZM_WLAN_MAX_RX_SIZE)
+ {
+ zm_debug_msg1("check_len is too large, chk_len: %d\n",
+ halPriv->usbRxTransferLen);
+ status = 1;
+ break;
+ }
+
+ /* Allocate a skb buffer */
+ newBuf = zfwBufAllocate(dev, ZM_WLAN_MAX_RX_SIZE);
+
+ if ( newBuf != NULL )
+ {
+ BufPtr = zmw_buf_get_buffer(dev, newBuf);
+ UsbBufPtr = srcBufPtr;
+
+ /* Copy the buffer */
+ zfwMemoryCopy(BufPtr, &(UsbBufPtr[chkIdx+ZM_USB_STREAM_MODE_TAG_LEN]), halPriv->usbRxTransferLen);
+
+ /* Record the buffer pointer */
+ halPriv->remainBuf = newBuf;
+ }
+ }
+ else
+ {
+ u8_t* BufPtr;
+ u8_t* UsbBufPtr;
+
+ /* Allocate a skb buffer */
+ newBuf = zfwBufAllocate(dev, ZM_WLAN_MAX_RX_SIZE);
+ if ( newBuf != NULL )
+ {
+ BufPtr = zmw_buf_get_buffer(dev, newBuf);
+ UsbBufPtr = srcBufPtr;
+
+ /* Copy the buffer */
+ zfwMemoryCopy(BufPtr, &(UsbBufPtr[chkIdx+ZM_USB_STREAM_MODE_TAG_LEN]), pktLen);
+
+ zfwBufSetSize(dev, newBuf, pktLen);
+ rxBufPool[rxBufPoolIndex++] = newBuf;
+ }
+ }
+ }
+ else
+ {
+ u16_t i;
+
+ DbgPrint("Can't find tag, pkt_len: 0x%04x, tag: 0x%04x\n",
+ pktLen, pktTag);
+
+ #if 0
+ for(i = 0; i < 32; i++)
+ {
+ DbgPrint("%02x ", buf->data[index-16+i]);
+
+ if ((i & 0xf) == 0xf)
+ DbgPrint("\n");
+ }
+ #endif
+
+ break;
+ }
+ }
+
+ /* Free buffer */
+ //zfwBufFree(adapter, pUsbRxTransfer->buf, 0);
+ zfwBufFree(dev, buf, 0);
+
+ for(ii = 0; ii < rxBufPoolIndex; ii++)
+ {
+ zfiUsbRecvPerPkt(dev, rxBufPool[ii]);
+ }
+}
+#endif
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfUsbInit */
+/* Initialize USB resource. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.12 */
+/* */
+/************************************************************************/
+void zfUsbInit(zdev_t* dev)
+{
+ /* Initialize Rx & INT endpoint for receiving data & interrupt */
+ zfwUsbEnableRxEpt(dev, USB_ENDPOINT_RX_INDEX);
+ zfwUsbEnableIntEpt(dev, USB_ENDPOINT_INT_INDEX);
+
+ return;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfUsbFree */
+/* Free PCI resource. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen ZyDAS Technology Corporation 2005.12 */
+/* */
+/************************************************************************/
+void zfUsbFree(zdev_t* dev)
+{
+ struct zsHpPriv *halPriv;
+
+ zmw_get_wlan_dev(dev);
+
+ halPriv = (struct zsHpPriv*)wd->hpPrivate;
+
+#ifdef ZM_OTUS_RX_STREAM_MODE
+ if ( halPriv->remainBuf != NULL )
+ {
+ zfwBufFree(dev, halPriv->remainBuf, 0);
+ }
+#endif
+
+ return;
+}
+
+void zfHpSendBeacon(zdev_t* dev, zbuf_t* buf, u16_t len)
+{
+ u32_t hw, lw;
+ u16_t i;
+ zmw_get_wlan_dev(dev);
+
+ /* Write to beacon buffer (ZM_BEACON_BUFFER_ADDRESS) */
+ for (i = 0; i<len; i+=4)
+ {
+ lw = zmw_tx_buf_readh(dev, buf, i);
+ hw = zmw_tx_buf_readh(dev, buf, i+2);
+
+ zfDelayWriteInternalReg(dev, ZM_BEACON_BUFFER_ADDRESS+i, (hw<<16)+lw);
+ }
+
+ /* Beacon PCLP header */
+ if (((struct zsHpPriv*)wd->hpPrivate)->hwFrequency < 3000)
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PLCP, ((len+4)<<(3+16))+0x0400);
+ }
+ else
+ {
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_PLCP, ((len+4)<<(16))+0x001b);
+ }
+
+ /* Beacon length (include CRC32) */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_LENGTH, len+4);
+
+ /* Beacon Ready */
+ zfDelayWriteInternalReg(dev, ZM_MAC_REG_BCN_CTRL, 1);
+ zfFlushDelayWrite(dev);
+
+ /* Free beacon buf */
+ zfwBufFree(dev, buf, 0);
+
+ return;
+}
+
+
+#define ZM_STATUS_TX_COMP 0x00
+#define ZM_STATUS_RETRY_COMP 0x01
+#define ZM_STATUS_TX_FAILED 0x02
+void zfiUsbRegIn(zdev_t* dev, u32_t* rsp, u16_t rspLen)
+{
+ //u8_t len, type, i;
+ u8_t type;
+ u8_t *u8rsp;
+ u16_t status;
+ u32_t bitmap;
+ zmw_get_wlan_dev(dev);
+
+ zm_msg0_mm(ZM_LV_3, "zfiUsbRegIn()");
+
+ u8rsp = (u8_t *)rsp;
+
+ //len = *u8rsp;
+ type = *(u8rsp+1);
+ u8rsp = u8rsp+4;
+
+
+ /* Interrupt event */
+ if ((type & 0xC0) == 0xC0)
+ {
+ if (type == 0xC0)
+ {
+ zfCoreEvent(dev, 0, u8rsp);
+
+ }
+ else if (type == 0xC1)
+ {
+#if 0
+ {
+ u16_t i;
+ DbgPrint("rspLen=%d\n", rspLen);
+ for (i=0; i<(rspLen/4); i++)
+ {
+ DbgPrint("rsp[%d]=0x%lx\n", i, rsp[i]);
+ }
+ }
+#endif
+ status = (u16_t)(rsp[3] >> 16);
+
+ ////6789
+ rsp[8] = rsp[8] >> 2 | (rsp[9] & 0x1) << 6;
+ switch (status)
+ {
+ case ZM_STATUS_RETRY_COMP :
+ zfCoreEvent(dev, 1, u8rsp);
+ break;
+ case ZM_STATUS_TX_FAILED :
+ zfCoreEvent(dev, 2, u8rsp);
+ break;
+ case ZM_STATUS_TX_COMP :
+ zfCoreEvent(dev, 3, u8rsp);
+ break;
+ }
+ }
+ else if (type == 0xC2)
+ {
+ zfBeaconCfgInterrupt(dev, u8rsp);
+ }
+ else if (type == 0xC3)
+ {
+ zfEndOfAtimWindowInterrupt(dev);
+ }
+ else if (type == 0xC4)
+ {
+#if 0
+ {
+ u16_t i;
+ DbgPrint("0xC2:rspLen=%d\n", rspLen);
+ for (i=0; i<(rspLen/4); i++)
+ {
+ DbgPrint("0xC2:rsp[%d]=0x%lx\n", i, rsp[i]);
+ }
+ }
+#endif
+ bitmap = (rsp[1] >> 16) + ((rsp[2] & 0xFFFF) << 16 );
+ //zfBawCore(dev, (u16_t)rsp[1] & 0xFFFF, bitmap, (u16_t)(rsp[2] >> 16) & 0xFF);
+ }
+ else if (type == 0xC5)
+ {
+ u16_t i;
+#if 0
+
+ for (i=0; i<(rspLen/4); i++) {
+ DbgPrint("0xC5:rsp[%d]=0x%lx\n", i, rsp[i]);
+ }
+#endif
+ for (i=1; i<(rspLen/4); i++) {
+ u8rsp = (u8_t *)(rsp+i);
+ //DbgPrint("0xC5:rsp[%d]=0x%lx\n", i, ((u32_t*)u8rsp)[0]);
+ zfCoreEvent(dev, 4, u8rsp);
+ }
+ }
+ else if (type == 0xC6)
+ {
+ zm_debug_msg0("\n\n WatchDog interrupt!!! : 0xC6 \n\n");
+ if (wd->zfcbHwWatchDogNotify != NULL)
+ {
+ wd->zfcbHwWatchDogNotify(dev);
+ }
+ }
+ else if (type == 0xC8)
+ {
+ //PZSW_ADAPTER adapter;
+
+ // for SPI flash program chk Flag
+ zfwDbgProgrameFlashChkDone(dev);
+ }
+ else if (type == 0xC9)
+ {
+ struct zsHpPriv* hpPriv=wd->hpPrivate;
+
+ zm_debug_msg0("##### Tx retransmission 5 times event #####");
+
+ /* correct tx retransmission issue */
+ hpPriv->retransmissionEvent = 1;
+ }
+ }
+ else
+ {
+ zfIdlRsp(dev, rsp, rspLen);
+ }
+}
+
+
+#define ZM_PROGRAM_RAM_ADDR 0x200000 //0x1000 //0x700000
+#define FIRMWARE_DOWNLOAD 0x30
+#define FIRMWARE_DOWNLOAD_COMP 0x31
+#define FIRMWARE_CONFIRM 0x32
+
+u16_t zfFirmwareDownload(zdev_t* dev, u32_t* fw, u32_t len, u32_t offset)
+{
+ u16_t ret = ZM_SUCCESS;
+ u32_t uCodeOfst = offset;
+ u8_t *image, *ptr;
+ u32_t result;
+
+ image = (u8_t*) fw;
+ ptr = image;
+
+ while (len > 0)
+ {
+ u32_t translen = (len > 4096) ? 4096 : len;
+
+ result = zfwUsbSubmitControl(dev, FIRMWARE_DOWNLOAD,
+ (u16_t) (uCodeOfst >> 8),
+ 0, image, translen);
+
+ if (result != ZM_SUCCESS)
+ {
+ zm_msg0_init(ZM_LV_0, "FIRMWARE_DOWNLOAD failed");
+ ret = 1;
+ goto exit;
+ }
+
+ len -= translen;
+ image += translen;
+ uCodeOfst += translen; // in Word (16 bit)
+
+ result = 0;
+ }
+
+ /* If download firmware success, issue a command to firmware */
+ if (ret == 0)
+ {
+ result = zfwUsbSubmitControl(dev, FIRMWARE_DOWNLOAD_COMP,
+ 0, 0, NULL, 0);
+
+ if (result != ZM_SUCCESS)
+ {
+ zm_msg0_init(ZM_LV_0, "FIRMWARE_DOWNLOAD_COMP failed");
+ ret = 1;
+ goto exit;
+ }
+ }
+
+#if 0
+ /* PCI code */
+ /* Wait for firmware ready */
+ result = zfwUsbSubmitControl(dev, FIRMWARE_CONFIRM, USB_DIR_IN | 0x40,
+ 0, 0, &ret_value, sizeof(ret_value), HZ);
+
+ if (result != 0)
+ {
+ zm_msg0_init(ZM_LV_0, "Can't receive firmware ready: ", result);
+ ret = 1;
+ }
+#endif
+
+exit:
+
+ return ret;
+
+}
+
+u16_t zfFirmwareDownloadNotJump(zdev_t* dev, u32_t* fw, u32_t len, u32_t offset)
+{
+ u16_t ret = ZM_SUCCESS;
+ u32_t uCodeOfst = offset;
+ u8_t *image, *ptr;
+ u32_t result;
+
+ image = (u8_t*) fw;
+ ptr = image;
+
+ while (len > 0)
+ {
+ u32_t translen = (len > 4096) ? 4096 : len;
+
+ result = zfwUsbSubmitControl(dev, FIRMWARE_DOWNLOAD,
+ (u16_t) (uCodeOfst >> 8),
+ 0, image, translen);
+
+ if (result != ZM_SUCCESS)
+ {
+ zm_msg0_init(ZM_LV_0, "FIRMWARE_DOWNLOAD failed");
+ ret = 1;
+ goto exit;
+ }
+
+ len -= translen;
+ image += translen;
+ uCodeOfst += translen; // in Word (16 bit)
+
+ result = 0;
+ }
+
+exit:
+
+ return ret;
+
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfIdlGetFreeTxdCount */
+/* Get free PCI PCI TxD count. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen ZyDAS Technology Corporation 2006.6 */
+/* */
+/************************************************************************/
+u32_t zfHpGetFreeTxdCount(zdev_t* dev)
+{
+ return zfwUsbGetFreeTxQSize(dev);
+}
+
+u32_t zfHpGetMaxTxdCount(zdev_t* dev)
+{
+ //return 8;
+ return zfwUsbGetMaxTxQSize(dev);
+}
+
+void zfiUsbRegOutComplete(zdev_t* dev)
+{
+ return;
+}
+
+extern void zfPushVtxq(zdev_t* dev);
+
+void zfiUsbOutComplete(zdev_t* dev, zbuf_t *buf, u8_t status, u8_t *hdr) {
+#ifndef ZM_ENABLE_AGGREGATION
+ if (buf) {
+ zfwBufFree(dev, buf, 0);
+ }
+#else
+ #ifdef ZM_BYPASS_AGGR_SCHEDULING
+ //Simply free the buf since BA retransmission is done in the firmware
+ if (buf)
+ {
+ zfwBufFree(dev, buf, 0);
+ }
+ zfPushVtxq(dev);
+ #else
+ zmw_get_wlan_dev(dev);
+
+ #ifdef ZM_ENABLE_FW_BA_RETRANSMISSION
+ //Simply free the buf since BA retransmission is done in the firmware
+ if (buf)
+ {
+ zfwBufFree(dev, buf, 0);
+ }
+ #else
+ u8_t agg;
+ u16_t frameType;
+
+ if(!hdr && buf) {
+ zfwBufFree(dev, buf, 0);
+ //zm_debug_msg0("buf Free due to hdr == NULL");
+ return;
+ }
+
+ if(hdr && buf) {
+ frameType = hdr[8] & 0xf;
+ agg = (u8_t)(hdr[2] >> 5 ) & 0x1;
+ //zm_debug_msg1("AGG=", agg);
+
+ if (!status) {
+ if (agg) {
+ //delete buf in ba fail queue??
+ //not ganna happen?
+ }
+ else {
+ zfwBufFree(dev, buf, 0);
+ }
+ }
+ else {
+ if (agg) {
+ //don't do anything
+ //zfwBufFree(dev, buf, 0);
+ }
+ else {
+ zfwBufFree(dev, buf, 0);
+ }
+ }
+ }
+ #endif
+
+ if (wd->state != ZM_WLAN_STATE_ENABLED) {
+ return;
+ }
+
+ if( (wd->wlanMode == ZM_MODE_AP) ||
+ (wd->wlanMode == ZM_MODE_INFRASTRUCTURE && wd->sta.EnableHT) ||
+ (wd->wlanMode == ZM_MODE_PSEUDO) ) {
+ zfAggTxScheduler(dev, 0);
+ }
+ #endif
+#endif
+
+ return;
+
+}
+
diff --git a/drivers/staging/otus/hal/hpusb.h b/drivers/staging/otus/hal/hpusb.h
new file mode 100644
index 000000000000..35a0c5668cea
--- /dev/null
+++ b/drivers/staging/otus/hal/hpusb.h
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2000-2005 ZyDAS Technology Corporation
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : ud_defs.h */
+/* */
+/* Abstract */
+/* This module contains USB data structure definitions. */
+/* */
+/* NOTES */
+/* None */
+/* */
+/************************************************************************/
+
+#ifndef _HPUSB_H
+#define _HPUSB_H
+
+#define ZM_OTUS_ENABLE_RETRY_FREQ_CHANGE
+#define ZM_BEACON_BUFFER_ADDRESS 0x117900
+
+#define ZM_MAX_CMD_SIZE 64
+#define ZM_HAL_MAX_EEPROM_REQ 510
+#define ZM_HAL_MAX_EEPROM_PRQ 2
+
+/* For USB STREAM mode */
+#ifdef ZM_DISABLE_AMSDU8K_SUPPORT
+#define ZM_MAX_USB_IN_TRANSFER_SIZE 4096
+#else
+#define ZM_MAX_USB_IN_TRANSFER_SIZE 8192
+#endif
+#define ZM_USB_STREAM_MODE_TAG_LEN 4
+#define ZM_USB_STREAM_MODE_TAG 0x4e00
+#define ZM_USB_MAX_EPINT_BUFFER 64
+
+struct zsCmdQ
+{
+ u16_t src;
+ u16_t cmdLen;
+ u8_t* buf;
+ u32_t cmd[ZM_MAX_CMD_SIZE/4];
+};
+
+struct zsCommand
+{
+ u16_t delayWcmdCount;
+ u32_t delayWcmdAddr[(ZM_CMD_QUEUE_SIZE-4)/4];
+ u32_t delayWcmdVal[(ZM_CMD_QUEUE_SIZE-4)/4];
+};
+
+struct zsHalRxInfo
+{
+ u32_t currentRSSI[7]; /* RSSI combined */
+ u32_t currentRxEVM[14];
+ u32_t currentRxDataMT;
+ u32_t currentRxDataMCS;
+ u32_t currentRxDataBW;
+ u32_t currentRxDataSG;
+};
+
+struct zsHpPriv
+{
+ u16_t hwFrequency;
+ u8_t hwBw40;
+ u8_t hwExtOffset;
+
+ u8_t disableDfsCh;
+
+ u32_t halCapability;
+
+ /* Fortunately the second loop can be disabled with a bit */
+ /* called en_pd_dc_offset_thr */
+ u8_t hwNotFirstInit;
+
+ /* command queue */
+ u16_t cmdHead;
+ u16_t cmdTail;
+#ifdef ZM_XP_USB_MULTCMD
+ u16_t cmdSend; // Used for Mult send USB cmd
+#endif
+ struct zsCmdQ cmdQ[ZM_CMD_QUEUE_SIZE];
+ u16_t cmdPending;
+ struct zsCommand cmd; /* buffer for delayed commands */
+ u8_t ledMode[2];
+ u32_t ctlBusy;
+ u32_t extBusy;
+
+ /*
+ * ANI & Radar support.
+ */
+ u32_t procPhyErr; /* Process Phy errs */
+ u8_t hasHwPhyCounters; /* Hardware has phy counters */
+ u32_t aniPeriod; /* ani update list period */
+ struct zsAniStats stats; /* various statistics */
+ struct zsAniState *curani; /* cached last reference */
+ struct zsAniState ani[50]; /* per-channel state */
+
+ /*
+ * Ani tables that change between the 5416 and 5312.
+ * These get set at attach time.
+ * XXX don't belong here
+ * XXX need better explanation
+ */
+ s32_t totalSizeDesired[5];
+ s32_t coarseHigh[5];
+ s32_t coarseLow[5];
+ s32_t firpwr[5];
+
+ /*
+ * ANI related PHY register value.
+ */
+ u32_t regPHYDesiredSZ;
+ u32_t regPHYFindSig;
+ u32_t regPHYAgcCtl1;
+ u32_t regPHYSfcorr;
+ u32_t regPHYSfcorrLow;
+ u32_t regPHYTiming5;
+ u32_t regPHYCckDetect;
+
+ u32_t eepromImage[1024];
+ u32_t eepromImageIndex;
+ u32_t eepromImageRdReq;
+
+ u8_t halReInit;
+
+ u8_t OpFlags;
+
+ u8_t tPow2xCck[4];
+ u8_t tPow2x2g[4];
+ u8_t tPow2x2g24HeavyClipOffset;
+ u8_t tPow2x2gHt20[8];
+ u8_t tPow2x2gHt40[8];
+ u8_t tPow2x5g[4];
+ u8_t tPow2x5gHt20[8];
+ u8_t tPow2x5gHt40[8];
+
+ /* hwBBHeavyClip : used compatibility */
+ /* 0 : dongle not support. */
+ /* !0: support heavy clip. */
+ u8_t hwBBHeavyClip;
+ u8_t enableBBHeavyClip; /* 0=>force disable 1=>enable */
+ u8_t doBBHeavyClip; /* set 1 if heavy clip need by each frequency switch */
+ u32_t setValueHeavyClip; /* save setting value for heavy clip when completed routine */
+
+ /*
+ * Rxdata RSSI, EVM, Rate etc...
+ */
+ struct zsHalRxInfo halRxInfo;
+
+ u32_t usbSendBytes;
+ u32_t usbAcSendBytes[4];
+
+ u16_t aggMaxDurationBE;
+ u32_t aggPktNum;
+
+ u16_t txop[4];
+ u16_t cwmin[4];
+ u16_t cwmax[4];
+ u8_t strongRSSI;
+ u8_t rxStrongRSSI;
+
+ u8_t slotType; //0->20us, 1=>9us
+
+#ifdef ZM_OTUS_RX_STREAM_MODE
+ u16_t usbRxRemainLen;
+ u16_t usbRxPktLen;
+ u16_t usbRxPadLen;
+ u16_t usbRxTransferLen;
+ zbuf_t *remainBuf;
+#endif
+
+ u8_t dot11Mode;
+
+ u8_t ibssBcnEnabled;
+ u32_t ibssBcnInterval;
+
+ // For re-issue the frequency change command
+ u32_t latestFrequency;
+ u8_t latestBw40;
+ u8_t latestExtOffset;
+ u8_t freqRetryCounter;
+
+ u8_t recordFreqRetryCounter;
+ u8_t isSiteSurvey;
+ u8_t coldResetNeedFreq;
+
+ u64_t camRollCallTable;
+ u8_t currentAckRtsTpc;
+
+ /* #1 Save the initial value of the related RIFS register settings */
+ //u32_t isInitialPhy;
+ u32_t initDesiredSigSize;
+ u32_t initAGC;
+ u32_t initAgcControl;
+ u32_t initSearchStartDelay;
+ u32_t initRIFSSearchParams;
+ u32_t initFastChannelChangeControl;
+
+ /* Dynamic SIFS for retransmission event */
+ u8_t retransmissionEvent;
+ u8_t latestSIFS;
+};
+
+extern u32_t zfHpLoadEEPROMFromFW(zdev_t* dev);
+
+
+typedef u8_t A_UINT8;
+typedef s8_t A_INT8;
+typedef u16_t A_UINT16;
+typedef u32_t A_UINT32;
+#define __ATTRIB_PACK
+
+#pragma pack (push, 1)
+
+#define AR5416_EEP_VER 0xE
+#define AR5416_EEP_VER_MINOR_MASK 0xFFF
+#define AR5416_EEP_NO_BACK_VER 0x1
+#define AR5416_EEP_MINOR_VER_2 0x2 // Adds modal params txFrameToPaOn, txFrametoDataStart, ht40PowerInc
+#define AR5416_EEP_MINOR_VER_3 0x3 // Adds modal params bswAtten, bswMargin, swSettle and base OpFlags for HT20/40 Disable
+
+// 16-bit offset location start of calibration struct
+#define AR5416_EEP_START_LOC 256
+#define AR5416_NUM_5G_CAL_PIERS 8
+#define AR5416_NUM_2G_CAL_PIERS 4
+#define AR5416_NUM_5G_20_TARGET_POWERS 8
+#define AR5416_NUM_5G_40_TARGET_POWERS 8
+#define AR5416_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_NUM_2G_20_TARGET_POWERS 4
+#define AR5416_NUM_2G_40_TARGET_POWERS 4
+#define AR5416_NUM_CTLS 24
+#define AR5416_NUM_BAND_EDGES 8
+#define AR5416_NUM_PD_GAINS 4
+#define AR5416_PD_GAINS_IN_MASK 4
+#define AR5416_PD_GAIN_ICEPTS 5
+#define AR5416_EEPROM_MODAL_SPURS 5
+#define AR5416_MAX_RATE_POWER 63
+#define AR5416_NUM_PDADC_VALUES 128
+#define AR5416_NUM_RATES 16
+#define AR5416_BCHAN_UNUSED 0xFF
+#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
+#define AR5416_OPFLAGS_11A 0x01
+#define AR5416_OPFLAGS_11G 0x02
+#define AR5416_OPFLAGS_5G_HT40 0x04
+#define AR5416_OPFLAGS_2G_HT40 0x08
+#define AR5416_OPFLAGS_5G_HT20 0x10
+#define AR5416_OPFLAGS_2G_HT20 0x20
+#define AR5416_EEPMISC_BIG_ENDIAN 0x01
+#define FREQ2FBIN(x,y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
+#define AR5416_MAX_CHAINS 2
+#define AR5416_ANT_16S 25
+
+#define AR5416_NUM_ANT_CHAIN_FIELDS 7
+#define AR5416_NUM_ANT_COMMON_FIELDS 4
+#define AR5416_SIZE_ANT_CHAIN_FIELD 3
+#define AR5416_SIZE_ANT_COMMON_FIELD 4
+#define AR5416_ANT_CHAIN_MASK 0x7
+#define AR5416_ANT_COMMON_MASK 0xf
+#define AR5416_CHAIN_0_IDX 0
+#define AR5416_CHAIN_1_IDX 1
+#define AR5416_CHAIN_2_IDX 2
+
+
+/* Capabilities Enum */
+typedef enum {
+ EEPCAP_COMPRESS_DIS = 0x0001,
+ EEPCAP_AES_DIS = 0x0002,
+ EEPCAP_FASTFRAME_DIS = 0x0004,
+ EEPCAP_BURST_DIS = 0x0008,
+ EEPCAP_MAXQCU_M = 0x01F0,
+ EEPCAP_MAXQCU_S = 4,
+ EEPCAP_HEAVY_CLIP_EN = 0x0200,
+ EEPCAP_KC_ENTRIES_M = 0xF000,
+ EEPCAP_KC_ENTRIES_S = 12,
+} EEPROM_CAPABILITIES;
+
+typedef enum Ar5416_Rates {
+ rate6mb, rate9mb, rate12mb, rate18mb,
+ rate24mb, rate36mb, rate48mb, rate54mb,
+ rate1l, rate2l, rate2s, rate5_5l,
+ rate5_5s, rate11l, rate11s, rateXr,
+ rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3,
+ rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7,
+ rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3,
+ rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7,
+ rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm,
+ Ar5416RateSize
+} AR5416_RATES;
+
+typedef struct eepFlags {
+ A_UINT8 opFlags;
+ A_UINT8 eepMisc;
+} __ATTRIB_PACK EEP_FLAGS;
+
+#define AR5416_CHECKSUM_LOCATION (AR5416_EEP_START_LOC + 1)
+typedef struct BaseEepHeader {
+ A_UINT16 length;
+ A_UINT16 checksum;
+ A_UINT16 version;
+ EEP_FLAGS opCapFlags;
+ A_UINT16 regDmn[2];
+ A_UINT8 macAddr[6];
+ A_UINT8 rxMask;
+ A_UINT8 txMask;
+ A_UINT16 rfSilent;
+ A_UINT16 blueToothOptions;
+ A_UINT16 deviceCap;
+ A_UINT32 binBuildNumber;
+ A_UINT8 deviceType;
+ A_UINT8 futureBase[33];
+} __ATTRIB_PACK BASE_EEP_HEADER; // 64 B
+
+typedef struct spurChanStruct {
+ A_UINT16 spurChan;
+ A_UINT8 spurRangeLow;
+ A_UINT8 spurRangeHigh;
+} __ATTRIB_PACK SPUR_CHAN;
+
+typedef struct ModalEepHeader {
+ A_UINT32 antCtrlChain[AR5416_MAX_CHAINS]; // 12
+ A_UINT32 antCtrlCommon; // 4
+ A_INT8 antennaGainCh[AR5416_MAX_CHAINS]; // 3
+ A_UINT8 switchSettling; // 1
+ A_UINT8 txRxAttenCh[AR5416_MAX_CHAINS]; // 3
+ A_UINT8 rxTxMarginCh[AR5416_MAX_CHAINS]; // 3
+ A_INT8 adcDesiredSize; // 1
+ A_INT8 pgaDesiredSize; // 1
+ A_UINT8 xlnaGainCh[AR5416_MAX_CHAINS]; // 3
+ A_UINT8 txEndToXpaOff; // 1
+ A_UINT8 txEndToRxOn; // 1
+ A_UINT8 txFrameToXpaOn; // 1
+ A_UINT8 thresh62; // 1
+ A_INT8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; // 3
+ A_UINT8 xpdGain; // 1
+ A_UINT8 xpd; // 1
+ A_INT8 iqCalICh[AR5416_MAX_CHAINS]; // 1
+ A_INT8 iqCalQCh[AR5416_MAX_CHAINS]; // 1
+ A_UINT8 pdGainOverlap; // 1
+ A_UINT8 ob; // 1
+ A_UINT8 db; // 1
+ A_UINT8 xpaBiasLvl; // 1
+ A_UINT8 pwrDecreaseFor2Chain; // 1
+ A_UINT8 pwrDecreaseFor3Chain; // 1 -> 48 B
+ A_UINT8 txFrameToDataStart; // 1
+ A_UINT8 txFrameToPaOn; // 1
+ A_UINT8 ht40PowerIncForPdadc; // 1
+ A_UINT8 bswAtten[AR5416_MAX_CHAINS]; // 3
+ A_UINT8 bswMargin[AR5416_MAX_CHAINS]; // 3
+ A_UINT8 swSettleHt40; // 1
+ A_UINT8 futureModal[22]; //
+ SPUR_CHAN spurChans[AR5416_EEPROM_MODAL_SPURS]; // 20 B
+} __ATTRIB_PACK MODAL_EEP_HEADER; // == 100 B
+
+typedef struct calDataPerFreq {
+ A_UINT8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+ A_UINT8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
+} __ATTRIB_PACK CAL_DATA_PER_FREQ;
+
+typedef struct CalTargetPowerLegacy {
+ A_UINT8 bChannel;
+ A_UINT8 tPow2x[4];
+} __ATTRIB_PACK CAL_TARGET_POWER_LEG;
+
+typedef struct CalTargetPowerHt {
+ A_UINT8 bChannel;
+ A_UINT8 tPow2x[8];
+} __ATTRIB_PACK CAL_TARGET_POWER_HT;
+
+#if defined(ARCH_BIG_ENDIAN) || defined(BIG_ENDIAN)
+typedef struct CalCtlEdges {
+ A_UINT8 bChannel;
+ A_UINT8 flag :2,
+ tPower :6;
+} __ATTRIB_PACK CAL_CTL_EDGES;
+#else
+typedef struct CalCtlEdges {
+ A_UINT8 bChannel;
+ A_UINT8 tPower :6,
+ flag :2;
+} __ATTRIB_PACK CAL_CTL_EDGES;
+#endif
+
+typedef struct CalCtlData {
+ CAL_CTL_EDGES ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+} __ATTRIB_PACK CAL_CTL_DATA;
+
+typedef struct ar5416Eeprom {
+ BASE_EEP_HEADER baseEepHeader; // 64 B
+ A_UINT8 custData[64]; // 64 B
+ MODAL_EEP_HEADER modalHeader[2]; // 200 B
+ A_UINT8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS];
+ A_UINT8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS];
+ CAL_DATA_PER_FREQ calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS];
+ CAL_DATA_PER_FREQ calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS];
+ CAL_TARGET_POWER_LEG calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS];
+ CAL_TARGET_POWER_HT calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS];
+ CAL_TARGET_POWER_HT calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS];
+ CAL_TARGET_POWER_LEG calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS];
+ CAL_TARGET_POWER_LEG calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS];
+ CAL_TARGET_POWER_HT calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS];
+ CAL_TARGET_POWER_HT calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS];
+ A_UINT8 ctlIndex[AR5416_NUM_CTLS];
+ CAL_CTL_DATA ctlData[AR5416_NUM_CTLS];
+ A_UINT8 padding;
+} __ATTRIB_PACK AR5416_EEPROM;
+
+#pragma pack (pop)
+
+typedef enum ConformanceTestLimits {
+ FCC = 0x10,
+ MKK = 0x40,
+ ETSI = 0x30,
+ SD_NO_CTL = 0xE0,
+ NO_CTL = 0xFF,
+ CTL_MODE_M = 0xF,
+ CTL_11A = 0,
+ CTL_11B = 1,
+ CTL_11G = 2,
+ CTL_TURBO = 3,
+ CTL_108G = 4,
+ CTL_2GHT20 = 5,
+ CTL_5GHT20 = 6,
+ CTL_2GHT40 = 7,
+ CTL_5GHT40 = 8,
+} ATH_CTLS;
+
+#endif /* #ifndef _HPUSB_H */
diff --git a/drivers/staging/otus/hal/otus.ini b/drivers/staging/otus/hal/otus.ini
new file mode 100644
index 000000000000..34efeb6c285b
--- /dev/null
+++ b/drivers/staging/otus/hal/otus.ini
@@ -0,0 +1,414 @@
+/* 8602 : update mismatch register between NDIS and ART */
+static const u32_t ar5416Modes[][6] = {
+/* Register A-20 A-20/40 G-20/40 G-20 G-Turbo */
+ {0x9800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0},
+ {0x9804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0},
+ {0x9808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x980c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, 0},
+ {0x9810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0},
+ {0x9814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0},
+ {0x9818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, 0},
+ {0x981c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0},
+ {0x9824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0},
+ {0x9828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0},
+ {0x982c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0},
+ {0x9830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0},
+ {0x9838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0},
+ {0x983c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, 0},
+ {0x9840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, 0},
+ {0x9844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, 0},
+ {0x9848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0},
+ {0x984c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, 0},
+ {0x9850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, 0},
+ {0x9854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, 0},
+ {0x9858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0},
+ {0x985c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0},
+ {0x9860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, 0},
+ {0x9868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0},
+ {0x986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0},
+ {0x9900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x990c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0},
+ {0x9918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, 0},
+ {0x991c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, 0},
+ {0x9920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, 0},
+ {0x9924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0},
+ {0x9928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0},
+ {0x992c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0},
+ {0x9934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0x9938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0x993c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0},
+ {0x9944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0},
+ {0x9948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, 0},
+ {0x994c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, 0},
+ {0x9954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0},
+ {0x9958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, 0},
+ {0x9960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0},
+ {0x9964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0},
+ {0x9970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, 0},
+ {0x9974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0},
+ {0x997c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x998c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x999c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x99a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x99a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0},
+ {0x99a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, 0},
+ {0x99ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0},
+ {0x99b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, 0},
+ {0x99b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, 0},
+ {0x99c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0},
+ {0x99c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0},
+ {0x99c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0},
+ {0x99cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0},
+ {0x99d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0},
+ {0x99d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x99d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x99dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x99e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, 0},
+ {0x99e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, 0},
+ {0x99e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, 0},
+ {0x99ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, 0},
+ {0x99f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x99fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, 0},
+ {0x9a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, 0},
+ {0x9a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0},
+ {0x9a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, 0},
+ {0x9a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, 0},
+ {0x9a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, 0},
+ {0x9a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, 0},
+ {0x9a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, 0},
+ {0x9a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, 0},
+ {0x9a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, 0},
+ {0x9a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, 0},
+ {0x9a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, 0},
+ {0x9a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, 0},
+ {0x9a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, 0},
+ {0x9a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, 0},
+ {0x9a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, 0},
+ {0x9a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, 0},
+ {0x9a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, 0},
+ {0x9a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, 0},
+ {0x9a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, 0},
+ {0x9a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, 0},
+ {0x9a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, 0},
+ {0x9a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, 0},
+ {0x9a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, 0},
+ {0x9a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, 0},
+ {0x9a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, 0},
+ {0x9a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, 0},
+ {0x9a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, 0},
+ {0x9a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, 0},
+ {0x9a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, 0},
+ {0x9a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, 0},
+ {0x9a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, 0},
+ {0x9a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, 0},
+ {0x9a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, 0},
+ {0x9a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, 0},
+ {0x9a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, 0},
+ {0x9a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, 0},
+ {0x9a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, 0},
+ {0x9a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, 0},
+ {0x9a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, 0},
+ {0x9aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, 0},
+ {0x9b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0},
+ {0x9b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, 0},
+ {0x9b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0},
+ {0x9b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0},
+ {0x9b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, 0},
+ {0x9b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0},
+ {0x9b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, 0},
+ {0x9b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, 0},
+ {0x9b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, 0},
+ {0x9b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, 0},
+ {0x9b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, 0},
+ {0x9b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0},
+ {0x9b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, 0},
+ {0x9b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0},
+ {0x9b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, 0},
+ {0x9b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0},
+ {0x9b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0},
+ {0x9b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, 0},
+ {0x9b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, 0},
+ {0x9b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0},
+ {0x9b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, 0},
+ {0x9b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0},
+ {0x9b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, 0},
+ {0x9b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0},
+ {0x9b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, 0},
+ {0x9b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0},
+ {0x9b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, 0},
+ {0x9b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, 0},
+ {0x9b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, 0},
+ {0x9b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, 0},
+ {0x9b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, 0},
+ {0x9b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, 0},
+ {0x9b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, 0},
+ {0x9b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, 0},
+ {0x9b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, 0},
+ {0x9b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, 0},
+ {0x9b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, 0},
+ {0x9b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, 0},
+ {0x9b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, 0},
+ {0x9ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, 0},
+ {0x9ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, 0},
+ {0x9bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0},
+ {0x9bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0},
+ {0x9c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0x9cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, 0},
+ {0xa204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, 0},
+ {0xa208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0},
+ {0xa20c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, 0},
+ {0xa210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, 0},
+ {0xa214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, 0},
+ {0xa218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, 0},
+ {0xa21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0},
+ {0xa220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, 0},
+ {0xa224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, 0},
+ {0xa228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, 0},
+ {0xa22c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, 0},
+ {0xa234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0xa238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0xa23c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0},
+ {0xa240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, 0},
+ {0xa244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0},
+ {0xa248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0},
+ {0xa24c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0},
+ {0xa250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0},
+ {0xa254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0},
+ {0xa25c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0},
+ {0xa260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0},
+ {0xa264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, 0},
+ {0xa268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa26c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, 0},
+ {0xa274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0},
+ {0xa278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0},
+ {0xa27c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, 0},
+ {0xa300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0},
+ {0xa304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0},
+ {0xa308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0},
+ {0xa30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0},
+ {0xa310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0},
+ {0xa314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0},
+ {0xa318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0},
+ {0xa31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0},
+ {0xa320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0},
+ {0xa324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0},
+ {0xa328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0},
+ {0xa32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa33c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0},
+ {0xa34c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0},
+ {0xa350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0},
+ {0xa354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0},
+ {0xa358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0},
+ {0xa388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, 0},
+ {0xa38c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0xa390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0xa394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0},
+ {0xa398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, 0},
+ {0xa39c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0},
+ {0xa3a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0xa3d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0xa3d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0},
+ {0xa3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0},
+ {0xa3dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0},
+ {0xa3e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, 0},
+ {0xa848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, 0},
+ {0xa920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, 0},
+ {0xa960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0},
+ {0xb20c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, 0},
+ {0xb26c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, 0},
+ {0xb848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, 0},
+ {0xb920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, 0},
+ {0xb960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0},
+ {0xc20c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, 0},
+ {0xc26c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, 0},
+ //{0xc864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0},
+ {0xc864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, 0},
+ {0xc95c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0},
+ {0xc968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, 0},
+ {0xc9bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, 0},
+ {0xd270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, 0},
+ {0xd35c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, 0},
+ {0xd360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, 0},
+ {0xd364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, 0},
+ {0xd368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, 0},
+ {0xd36c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0},
+ {0xd370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0},
+ {0xd374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, 0},
+ {0xd378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0},
+ {0xd37c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0},
+ {0xd380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0},
+ {0xd384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0}
+};
+
+
+static const u32_t otusBank[][3] = {
+ //# bank 0
+ {0x98b0, 0x1e5795e5, 0x1e5795e5},
+ {0x98e0, 0x02008020, 0x02008020},
+ //# bank 1
+ {0x98b0, 0x02108421, 0x02108421},
+ {0x98ec, 0x00000008, 0x00000008},
+ //# bank 2
+ {0x98b0, 0x0e73ff17, 0x0e73ff17},
+ {0x98e0, 0x00000420, 0x00000420},
+ //# bank 3
+ {0x98f0, 0x01400018, 0x01c00018},
+ //# bank 4
+ {0x98b0, 0x000001a1, 0x000001a1},
+ {0x98e8, 0x00000001, 0x00000001},
+ //# bank 5
+ {0x98b0, 0x00000013, 0x00000013},
+ {0x98e4, 0x00000002, 0x00000002},
+ //# bank 6
+ {0x98b0, 0x00000000, 0x00000000},
+ {0x98b0, 0x00000000, 0x00000000},
+ {0x98b0, 0x00000000, 0x00000000},
+ {0x98b0, 0x00000000, 0x00000000},
+ {0x98b0, 0x00000000, 0x00000000},
+ {0x98b0, 0x00004000, 0x00004000},
+ {0x98b0, 0x00006c00, 0x00006c00},
+ {0x98b0, 0x00002c00, 0x00002c00},
+ {0x98b0, 0x00004800, 0x00004800},
+ {0x98b0, 0x00004000, 0x00004000},
+ {0x98b0, 0x00006000, 0x00006000},
+ {0x98b0, 0x00001000, 0x00001000},
+ {0x98b0, 0x00004000, 0x00004000},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00087c00, 0x00087c00},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00005400, 0x00005400},
+ {0x98b0, 0x00000c00, 0x00000c00},
+ {0x98b0, 0x00001800, 0x00001800},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00006c00, 0x00006c00},
+ {0x98b0, 0x00006c00, 0x00006c00},
+ {0x98b0, 0x00007c00, 0x00007c00},
+ {0x98b0, 0x00002c00, 0x00002c00},
+ {0x98b0, 0x00003c00, 0x00003c00},
+ {0x98b0, 0x00003800, 0x00003800},
+ {0x98b0, 0x00001c00, 0x00001c00},
+ {0x98b0, 0x00000800, 0x00000800},
+ {0x98b0, 0x00000408, 0x00000408},
+ {0x98b0, 0x00004c15, 0x00004c15},
+ {0x98b0, 0x00004188, 0x00004188},
+ {0x98b0, 0x0000201e, 0x0000201e},
+ {0x98b0, 0x00010408, 0x00010408},
+ {0x98b0, 0x00000801, 0x00000801},
+ {0x98b0, 0x00000c08, 0x00000c08},
+ {0x98b0, 0x0000181e, 0x0000181e},
+ {0x98b0, 0x00001016, 0x00001016},
+ {0x98b0, 0x00002800, 0x00002800},
+ {0x98b0, 0x00004010, 0x00004010},
+ {0x98b0, 0x0000081c, 0x0000081c},
+ {0x98b0, 0x00000115, 0x00000115},
+ {0x98b0, 0x00000015, 0x00000015},
+ {0x98b0, 0x00000066, 0x00000066},
+ {0x98b0, 0x0000001c, 0x0000001c},
+ {0x98b0, 0x00000000, 0x00000000},
+ {0x98b0, 0x00000004, 0x00000004},
+ {0x98b0, 0x00000015, 0x00000015},
+ {0x98b0, 0x0000001f, 0x0000001f},
+ {0x98e0, 0x00000000, 0x00000400},
+ //# bank 7
+ {0x98b0, 0x000000a0, 0x000000a0},
+ {0x98b0, 0x00000000, 0x00000000},
+ {0x98b0, 0x00000040, 0x00000040},
+ {0x98f0, 0x0000001c, 0x0000001c}
+};
diff --git a/drivers/staging/otus/ioctl.c b/drivers/staging/otus/ioctl.c
new file mode 100644
index 000000000000..7a5c1e876b01
--- /dev/null
+++ b/drivers/staging/otus/ioctl.c
@@ -0,0 +1,2913 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : ioctl.c */
+/* */
+/* Abstract */
+/* This module contains Linux wireless extension related functons. */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+#include <linux/module.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+
+#include "usbdrv.h"
+
+#define ZD_IOCTL_WPA (SIOCDEVPRIVATE + 1)
+#define ZD_IOCTL_PARAM (SIOCDEVPRIVATE + 2)
+#define ZD_IOCTL_GETWPAIE (SIOCDEVPRIVATE + 3)
+#ifdef ZM_ENABLE_CENC
+#define ZM_IOCTL_CENC (SIOCDEVPRIVATE + 4)
+#endif //ZM_ENABLE_CENC
+#define ZD_PARAM_ROAMING 0x0001
+#define ZD_PARAM_PRIVACY 0x0002
+#define ZD_PARAM_WPA 0x0003
+#define ZD_PARAM_COUNTERMEASURES 0x0004
+#define ZD_PARAM_DROPUNENCRYPTED 0x0005
+#define ZD_PARAM_AUTH_ALGS 0x0006
+#define ZD_PARAM_WPS_FILTER 0x0007
+
+#ifdef ZM_ENABLE_CENC
+#define P80211_PACKET_CENCFLAG 0x0001
+#endif //ZM_ENABLE_CENC
+#define P80211_PACKET_SETKEY 0x0003
+
+#define ZD_CMD_SET_ENCRYPT_KEY 0x0001
+#define ZD_CMD_SET_MLME 0x0002
+#define ZD_CMD_SCAN_REQ 0x0003
+#define ZD_CMD_SET_GENERIC_ELEMENT 0x0004
+#define ZD_CMD_GET_TSC 0x0005
+
+#define ZD_CRYPT_ALG_NAME_LEN 16
+#define ZD_MAX_KEY_SIZE 32
+#define ZD_MAX_GENERIC_SIZE 64
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+extern u16_t zfLnxGetVapId(zdev_t* dev);
+
+static const u32_t channel_frequency_11A[] =
+{
+//Even element for Channel Number, Odd for Frequency
+ 36,5180,
+ 40,5200,
+ 44,5220,
+ 48,5240,
+ 52,5260,
+ 56,5280,
+ 60,5300,
+ 64,5320,
+ 100,5500,
+ 104,5520,
+ 108,5540,
+ 112,5560,
+ 116,5580,
+ 120,5600,
+ 124,5620,
+ 128,5640,
+ 132,5660,
+ 136,5680,
+ 140,5700,
+//
+ 184,4920,
+ 188,4940,
+ 192,4960,
+ 196,4980,
+ 8,5040,
+ 12,5060,
+ 16,5080,
+ 34,5170,
+ 38,5190,
+ 42,5210,
+ 46,5230,
+//
+ 149,5745,
+ 153,5765,
+ 157,5785,
+ 161,5805,
+ 165,5825
+//
+};
+
+int usbdrv_freq2chan(u32_t freq)
+{
+ /* 2.4G Hz */
+ if (freq > 2400 && freq < 3000)
+ {
+ return ((freq-2412)/5) + 1;
+ }
+ else
+ {
+ u16_t ii;
+ u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t);
+
+ for(ii = 1; ii < num_chan; ii += 2)
+ {
+ if (channel_frequency_11A[ii] == freq)
+ return channel_frequency_11A[ii-1];
+ }
+ }
+
+ return 0;
+}
+
+int usbdrv_chan2freq(int chan)
+{
+ int freq;
+
+ /* If channel number is out of range */
+ if (chan > 165 || chan <= 0)
+ return -1;
+
+ /* 2.4G band */
+ if (chan >= 1 && chan <= 13)
+ {
+ freq = (2412 + (chan - 1) * 5);
+ return freq;
+ }
+ else if (chan >= 36 && chan <= 165)
+ {
+ u16_t ii;
+ u16_t num_chan = sizeof(channel_frequency_11A)/sizeof(u32_t);
+
+ for(ii = 0; ii < num_chan; ii += 2)
+ {
+ if (channel_frequency_11A[ii] == chan)
+ return channel_frequency_11A[ii+1];
+ }
+
+ /* Can't find desired frequency */
+ if (ii == num_chan)
+ return -1;
+ }
+
+ /* Can't find deisred frequency */
+ return -1;
+}
+
+int usbdrv_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
+{
+#ifdef ZM_HOSTAPD_SUPPORT
+ //struct usbdrv_private *macp = dev->ml_priv;
+ char essidbuf[IW_ESSID_MAX_SIZE+1];
+ int i;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ memset(essidbuf, 0, sizeof(essidbuf));
+
+ printk(KERN_ERR "usbdrv_ioctl_setessid\n");
+
+ //printk("ssidlen=%d\n", erq->length); //for any, it is 1.
+ if (erq->flags) {
+ if (erq->length > (IW_ESSID_MAX_SIZE+1))
+ return -E2BIG;
+
+ if (copy_from_user(essidbuf, erq->pointer, erq->length))
+ return -EFAULT;
+ }
+
+ //zd_DisasocAll(2);
+ //wait_ms(100);
+
+ printk(KERN_ERR "essidbuf: ");
+
+ for(i = 0; i < erq->length; i++)
+ {
+ printk(KERN_ERR "%02x ", essidbuf[i]);
+ }
+
+ printk(KERN_ERR "\n");
+
+ essidbuf[erq->length] = '\0';
+ //memcpy(macp->wd.ws.ssid, essidbuf, erq->length);
+ //macp->wd.ws.ssidLen = strlen(essidbuf)+2;
+ //macp->wd.ws.ssid[1] = strlen(essidbuf); // Update ssid length
+
+ zfiWlanSetSSID(dev, essidbuf, erq->length);
+#if 0
+ printk(KERN_ERR "macp->wd.ws.ssid: ");
+
+ for(i = 0; i < macp->wd.ws.ssidLen; i++)
+ {
+ printk(KERN_ERR "%02x ", macp->wd.ws.ssid[i]);
+ }
+
+ printk(KERN_ERR "\n");
+#endif
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+
+#endif
+
+ return 0;
+}
+
+int usbdrv_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
+{
+ //struct usbdrv_private *macp = dev->ml_priv;
+ u8_t essidbuf[IW_ESSID_MAX_SIZE+1];
+ u8_t len;
+ u8_t i;
+
+
+ //len = macp->wd.ws.ssidLen;
+ //memcpy(essidbuf, macp->wd.ws.ssid, macp->wd.ws.ssidLen);
+ zfiWlanQuerySSID(dev, essidbuf, &len);
+
+ essidbuf[len] = 0;
+
+ printk(KERN_ERR "ESSID: ");
+
+ for(i = 0; i < len; i++)
+ {
+ printk(KERN_ERR "%c", essidbuf[i]);
+ }
+
+ printk(KERN_ERR "\n");
+
+ erq->flags= 1;
+ erq->length = strlen(essidbuf) + 1;
+
+ if (erq->pointer)
+ if (copy_to_user(erq->pointer, essidbuf, erq->length))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+int usbdrv_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
+{
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 14
+/*
+ * Encode a WPA or RSN information element as a custom
+ * element using the hostap format.
+ */
+u32 encode_ie(void *buf, u32 bufsize, const u8 *ie, u32 ielen, const u8 *leader, u32 leader_len)
+{
+ u8 *p;
+ u32 i;
+
+ if (bufsize < leader_len)
+ return 0;
+ p = buf;
+ memcpy(p, leader, leader_len);
+ bufsize -= leader_len;
+ p += leader_len;
+ for (i = 0; i < ielen && bufsize > 2; i++)
+ p += sprintf(p, "%02x", ie[i]);
+ return (i == ielen ? p - (u8 *)buf : 0);
+}
+#endif /* WIRELESS_EXT > 14 */
+
+/*------------------------------------------------------------------*/
+/*
+ * Translate scan data returned from the card to a card independent
+ * format that the Wireless Tools will understand
+ */
+char *usbdrv_translate_scan(struct net_device *dev,
+ struct iw_request_info *info, char *current_ev,
+ char *end_buf, struct zsBssInfo *list)
+{
+ struct iw_event iwe; /* Temporary buffer */
+ u16_t capabilities;
+ char *current_val; /* For rates */
+ char *last_ev;
+ int i;
+#if WIRELESS_EXT > 14
+ char buf[64*2 + 30];
+#endif
+
+ last_ev = current_ev;
+
+/* 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, list->bssid, ETH_ALEN);
+ current_ev = iwe_stream_add_event(
+ info,
+ current_ev,
+ end_buf, &iwe, IW_EV_ADDR_LEN);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+
+/* Other entries will be displayed in the order we give them */
+
+/* Add the ESSID */
+ iwe.u.data.length = list->ssid[1];
+ if(iwe.u.data.length > 32)
+ iwe.u.data.length = 32;
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(
+ info,
+ current_ev, end_buf, &iwe, &list->ssid[2]);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+
+/* Add mode */
+ iwe.cmd = SIOCGIWMODE;
+ capabilities = (list->capability[1] << 8) + list->capability[0];
+ if(capabilities & (0x01 | 0x02))
+ {
+ if(capabilities & 0x01)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ current_ev = iwe_stream_add_event(
+ info,
+ current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+ }
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+
+/* Add frequency */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = list->channel;
+/* Channel frequency in KHz */
+ if (iwe.u.freq.m > 14)
+ {
+ if ((184 <= iwe.u.freq.m) && (iwe.u.freq.m<=196))
+ iwe.u.freq.m = 4000 + iwe.u.freq.m * 5;
+ else
+ iwe.u.freq.m = 5000 + iwe.u.freq.m * 5;
+ }
+ else
+ {
+ if (iwe.u.freq.m == 14)
+ iwe.u.freq.m = 2484;
+ else
+ iwe.u.freq.m = 2412 + (iwe.u.freq.m - 1) * 5;
+ }
+ iwe.u.freq.e = 6;
+ current_ev = iwe_stream_add_event(
+ info,
+ current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+
+/* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+#if WIRELESS_EXT > 18
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED
+ |IW_QUAL_NOISE_UPDATED;
+#endif
+ iwe.u.qual.level = list->signalStrength;
+ iwe.u.qual.noise = 0;
+ iwe.u.qual.qual = list->signalQuality;
+ current_ev = iwe_stream_add_event(
+ info,
+ current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+
+/* Add encryption capability */
+
+ iwe.cmd = SIOCGIWENCODE;
+ if(capabilities & 0x10)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+
+ iwe.u.data.length = 0;
+ current_ev = iwe_stream_add_point(
+ info,
+ current_ev, end_buf, &iwe, list->ssid);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+
+/* Rate : stuffing multiple values in a single event require a bit
+ * more of magic */
+ current_val = current_ev + IW_EV_LCP_LEN;
+
+ iwe.cmd = SIOCGIWRATE;
+/* Those two flags are ignored... */
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+ for(i = 0 ; i < list->supportedRates[1] ; i++)
+ {
+/* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe.u.bitrate.value = ((list->supportedRates[i+2] & 0x7f) * 500000);
+/* Add new value to event */
+ current_val = iwe_stream_add_value(
+ info,
+ current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+
+ /* Ran out of buffer */
+ if (last_ev == current_val)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_val;
+ }
+
+ for (i = 0 ; i < list->extSupportedRates[1] ; i++)
+ {
+/* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe.u.bitrate.value = ((list->extSupportedRates[i+2] & 0x7f) * 500000);
+/* Add new value to event */
+ current_val = iwe_stream_add_value(
+ info,
+ current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+
+ /* Ran out of buffer */
+ if (last_ev == current_val)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+ }
+
+/* Check if we added any event */
+ if((current_val - current_ev) > IW_EV_LCP_LEN)
+ current_ev = current_val;
+#if WIRELESS_EXT > 14
+#define IEEE80211_ELEMID_RSN 0x30
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ snprintf(buf, sizeof(buf), "bcn_int=%d", (list->beaconInterval[1] << 8) + list->beaconInterval[0]);
+ iwe.u.data.length = strlen(buf);
+ current_ev = iwe_stream_add_point(
+ info,
+ current_ev, end_buf, &iwe, buf);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+
+ if (list->wpaIe[1] != 0)
+ {
+ static const char rsn_leader[] = "rsn_ie=";
+ static const char wpa_leader[] = "wpa_ie=";
+
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+ if (list->wpaIe[0] == IEEE80211_ELEMID_RSN)
+ iwe.u.data.length = encode_ie(buf, sizeof(buf),
+ list->wpaIe, list->wpaIe[1]+2,
+ rsn_leader, sizeof(rsn_leader)-1);
+ else
+ iwe.u.data.length = encode_ie(buf, sizeof(buf),
+ list->wpaIe, list->wpaIe[1]+2,
+ wpa_leader, sizeof(wpa_leader)-1);
+
+ if (iwe.u.data.length != 0)
+ current_ev = iwe_stream_add_point(
+ info,
+ current_ev, end_buf, &iwe, buf);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+ }
+ if (list->rsnIe[1] != 0)
+ {
+ static const char rsn_leader[] = "rsn_ie=";
+ memset(&iwe, 0, sizeof(iwe));
+ iwe.cmd = IWEVCUSTOM;
+
+ if (list->rsnIe[0] == IEEE80211_ELEMID_RSN)
+ {
+ iwe.u.data.length = encode_ie(buf, sizeof(buf),
+ list->rsnIe, list->rsnIe[1]+2,
+ rsn_leader, sizeof(rsn_leader)-1);
+ if (iwe.u.data.length != 0)
+ current_ev = iwe_stream_add_point(
+ info,
+ current_ev, end_buf, &iwe, buf);
+
+ /* Ran out of buffer */
+ if (last_ev == current_ev)
+ {
+ return end_buf;
+ }
+
+ last_ev = current_ev;
+ }
+ }
+#endif
+/* The other data in the scan result are not really
+ * interesting, so for now drop it */
+ return current_ev;
+}
+
+int usbdrvwext_giwname(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrq, char *extra)
+{
+ //struct usbdrv_private *macp = dev->ml_priv;
+
+ strcpy(wrq->name, "IEEE 802.11-MIMO");
+
+ return 0;
+}
+
+int usbdrvwext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ u32_t FreqKHz;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (freq->e > 1)
+ return -EINVAL;
+
+ if (freq->e == 1)
+ {
+ FreqKHz = (freq->m / 100000);
+
+ if (FreqKHz > 4000000)
+ {
+ if (FreqKHz > 5825000)
+ FreqKHz = 5825000;
+ else if (FreqKHz < 4920000)
+ FreqKHz = 4920000;
+ else if (FreqKHz < 5000000)
+ FreqKHz = (((FreqKHz - 4000000) / 5000) * 5000) + 4000000;
+ else
+ FreqKHz = (((FreqKHz - 5000000) / 5000) * 5000) + 5000000;
+ }
+ else
+ {
+ if (FreqKHz > 2484000)
+ FreqKHz = 2484000;
+ else if (FreqKHz < 2412000)
+ FreqKHz = 2412000;
+ else
+ FreqKHz = (((FreqKHz - 2412000) / 5000) * 5000) + 2412000;
+ }
+
+ }
+ else
+ {
+ FreqKHz = usbdrv_chan2freq(freq->m);
+
+ if (FreqKHz != -1)
+ FreqKHz *= 1000;
+ else
+ FreqKHz = 2412000;
+ }
+
+ //printk("freq->m: %d, freq->e: %d\n", freq->m, freq->e);
+ //printk("FreqKHz: %d\n", FreqKHz);
+
+ if (macp->DeviceOpened == 1)
+ {
+ zfiWlanSetFrequency(dev, FreqKHz, 0); // Immediate
+ //u8_t wpaieLen,wpaie[50];
+ //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+ //if (wpaieLen > 2)
+ // zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
+ }
+
+ return 0;
+}
+
+int usbdrvwext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ freq->m = zfiWlanQueryFrequency(dev);
+ freq->e = 3;
+
+ return 0;
+}
+
+int usbdrvwext_siwmode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrq, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u8_t WlanMode;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ switch(wrq->mode)
+ {
+ case IW_MODE_MASTER:
+ WlanMode = ZM_MODE_AP;
+ break;
+ case IW_MODE_INFRA:
+ WlanMode = ZM_MODE_INFRASTRUCTURE;
+ break;
+ case IW_MODE_ADHOC:
+ WlanMode = ZM_MODE_IBSS;
+ break;
+ default:
+ WlanMode = ZM_MODE_IBSS;
+ break;
+ }
+
+ zfiWlanSetWlanMode(dev,WlanMode);
+ zfiWlanDisable(dev, 1);
+ zfiWlanEnable(dev);
+
+ return 0;
+}
+
+int usbdrvwext_giwmode(struct net_device *dev,
+ struct iw_request_info *info,
+ __u32 *mode, char *extra)
+{
+ unsigned long irqFlag;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ switch(zfiWlanQueryWlanMode(dev))
+ {
+ case ZM_MODE_AP:
+ *mode = IW_MODE_MASTER;
+ break;
+ case ZM_MODE_INFRASTRUCTURE:
+ *mode = IW_MODE_INFRA;
+ break;
+ case ZM_MODE_IBSS:
+ *mode = IW_MODE_ADHOC;
+ break;
+ default:
+ *mode = IW_MODE_ADHOC;
+ break;
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+
+ return 0;
+}
+
+int usbdrvwext_siwsens(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *sens, char *extra)
+{
+ return 0;
+}
+
+int usbdrvwext_giwsens(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *sens, char *extra)
+{
+ sens->value = 0;
+ sens->fixed = 1;
+
+ return 0;
+}
+
+int usbdrvwext_giwrange(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+ int i, val;
+ //int num_band_a;
+ u16_t channels[60];
+ u16_t channel_num;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+#if WIRELESS_EXT > 9
+ range->txpower_capa = IW_TXPOW_DBM;
+// XXX what about min/max_pmp, min/max_pmt, etc.
+#endif
+
+#if WIRELESS_EXT > 10
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 13;
+
+ range->retry_capa = IW_RETRY_LIMIT;
+ range->retry_flags = IW_RETRY_LIMIT;
+ range->min_retry = 0;
+ range->max_retry = 255;
+#endif /* WIRELESS_EXT > 10 */
+
+ channel_num = zfiWlanQueryAllowChannels(dev, channels);
+
+ /* Gurantee reported channel numbers is less or equal to IW_MAX_FREQUENCIES */
+ if (channel_num > IW_MAX_FREQUENCIES)
+ channel_num = IW_MAX_FREQUENCIES;
+
+ val = 0;
+
+ for (i = 0; i < channel_num; i++)
+ {
+ range->freq[val].i = usbdrv_freq2chan(channels[i]);
+ range->freq[val].m = channels[i];
+ range->freq[val].e = 6;
+ val++;
+ }
+
+ range->num_channels = channel_num;
+ range->num_frequency = channel_num;
+
+#if 0
+ range->num_channels = 14; // Only 2.4G
+
+/* XXX need to filter against the regulatory domain &| active set */
+ val = 0;
+ for (i = 1; i <= 14; i++) // B,G Bands
+ {
+ range->freq[val].i = i;
+ if (i == 14)
+ range->freq[val].m = 2484000;
+ else
+ range->freq[val].m = (2412+(i-1)*5)*1000;
+ range->freq[val].e = 3;
+ val++;
+ }
+
+ num_band_a = (IW_MAX_FREQUENCIES - val);
+
+ for (i = 0; i < num_band_a; i++) // A Bands
+ {
+ range->freq[val].i = channel_frequency_11A[2 * i];
+ range->freq[val].m = channel_frequency_11A[2 * i + 1] * 1000;
+ range->freq[val].e = 3;
+ val++;
+ }
+ // MIMO Rate Not Defined Now
+ //For 802.11a, there are too more frequency. We can't return them all
+ range->num_frequency = val;
+#endif
+
+/* Max of /proc/net/wireless */
+ range->max_qual.qual = 100; //?? //92;
+ range->max_qual.level = 154; //??
+ range->max_qual.noise = 154; //??
+ range->sensitivity = 3; //??
+
+// XXX these need to be nsd-specific!
+ range->min_rts = 0;
+ range->max_rts = 2347;
+ range->min_frag = 256;
+ range->max_frag = 2346;
+ range->max_encoding_tokens = 4/*NUM_WEPKEYS*/; //??
+ range->num_encoding_sizes = 2; //??
+
+ range->encoding_size[0] = 5; //?? //WEP Key Encoding Size
+ range->encoding_size[1] = 13;//??
+
+// XXX what about num_bitrates/throughput?
+ range->num_bitrates = 0; //??
+
+/* estimated max throughput */
+// XXX need to cap it if we're running at ~2Mbps..
+
+ range->throughput = 300000000;
+
+ return 0;
+}
+
+int usbdrvwext_siwap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *MacAddr, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
+ zfiWlanSetMacAddress(dev,(u16_t *)&MacAddr->sa_data[0]);
+ else //STA Mode
+ zfiWlanSetBssid(dev,&MacAddr->sa_data[0]);
+
+ if (macp->DeviceOpened == 1)
+ {
+ //u8_t wpaieLen,wpaie[80];
+ //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+ //if (wpaieLen > 2)
+ // zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
+ }
+
+ return 0;
+}
+
+int usbdrvwext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *MacAddr, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
+ zfiWlanQueryMacAddress(dev, &MacAddr->sa_data[0]);
+ else //STA Mode
+ {
+ if (macp->adapterState == ZM_STATUS_MEDIA_CONNECT)
+ {
+ zfiWlanQueryBssid(dev, &MacAddr->sa_data[0]);
+ }
+ else
+ {
+ u8_t zero_addr[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ memcpy(&MacAddr->sa_data[0], zero_addr, sizeof(zero_addr));
+ }
+ }
+
+ return 0;
+}
+
+int usbdrvwext_iwaplist(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ //Don't know how to do yet--CWYang(+)
+ return 0;
+
+}
+
+int usbdrvwext_siwscan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ printk("CWY - usbdrvwext_siwscan\n");
+
+ zfiWlanScan(dev);
+
+ return 0;
+}
+
+int usbdrvwext_giwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ //struct zsWlanDev* wd = (struct zsWlanDev*) zmw_wlan_dev(dev);
+ char *current_ev = extra;
+ char *end_buf;
+ int i;
+ //struct zsBssList BssList;
+ struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1), GFP_KERNEL);
+ //BssList = wd->sta.pBssList;
+ //zmw_get_wlan_dev(dev);
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ if (data->length == 0)
+ {
+ end_buf = extra + IW_SCAN_MAX_DATA;
+ }
+ else
+ {
+ end_buf = extra + data->length;
+ }
+
+ printk("giwscan - Report Scan Results\n");
+ //printk("giwscan - BssList Sreucture Len : %d\n", sizeof(BssList));
+ //printk("giwscan - BssList Count : %d\n", wd->sta.pBssList->bssCount);
+ //printk("giwscan - UpdateBssList Count : %d\n", wd->sta.pUpdateBssList->bssCount);
+ zfiWlanQueryBssListV1(dev, pBssList);
+ //zfiWlanQueryBssList(dev, &BssList);
+
+/* Read and parse all entries */
+ printk("giwscan - pBssList->bssCount : %d\n", pBssList->bssCount);
+ //printk("giwscan - BssList.bssCount : %d\n", BssList.bssCount);
+
+ for (i = 0; i < pBssList->bssCount; i++)
+ {
+/* Translate to WE format this entry */
+ //current_ev = usbdrv_translate_scan(dev, info, current_ev,
+ // extra + IW_SCAN_MAX_DATA, &pBssList->bssInfo[i]);
+ current_ev = usbdrv_translate_scan(dev, info, current_ev,
+ end_buf, &pBssList->bssInfo[i]);
+
+#if WIRELESS_EXT > 16
+ if (current_ev == end_buf)
+ {
+ kfree(pBssList);
+ data->length = current_ev - extra;
+ return -E2BIG;
+ }
+#endif
+ }
+
+/* Length of data */
+ data->length = (current_ev - extra);
+ data->flags = 0; /* todo */
+
+ kfree(pBssList);
+
+ return 0;
+}
+
+int usbdrvwext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *essid, char *extra)
+{
+ char EssidBuf[IW_ESSID_MAX_SIZE+1];
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (essid->flags == 1)
+ {
+ if (essid->length > (IW_ESSID_MAX_SIZE+1))
+ return -E2BIG;
+
+ if (copy_from_user(&EssidBuf, essid->pointer, essid->length))
+ return -EFAULT;
+
+ EssidBuf[essid->length] = '\0';
+ //printk("siwessid - Set Essid : %s\n",EssidBuf);
+ //printk("siwessid - Essid Len : %d\n",essid->length);
+ //printk("siwessid - Essid Flag : %x\n",essid->flags);
+ if (macp->DeviceOpened == 1)
+ {
+ zfiWlanSetSSID(dev, EssidBuf, strlen(EssidBuf));
+ zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), FALSE);
+ zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev));
+ //u8_t wpaieLen,wpaie[50];
+ //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+ //if (wpaieLen > 2)
+ // zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
+ }
+ }
+
+ return 0;
+}
+
+int usbdrvwext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *essid, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u8_t EssidLen;
+ char EssidBuf[IW_ESSID_MAX_SIZE+1];
+ int ssid_len;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen);
+
+ /* Convert type from unsigned char to char */
+ ssid_len = (int)EssidLen;
+
+ /* Make sure the essid length is not greater than IW_ESSID_MAX_SIZE */
+ if (ssid_len > IW_ESSID_MAX_SIZE)
+ ssid_len = IW_ESSID_MAX_SIZE;
+
+ EssidBuf[ssid_len] = '\0';
+
+ essid->flags = 1;
+ essid->length = strlen(EssidBuf);
+
+ memcpy(extra, EssidBuf, essid->length);
+ // wireless.c in Kernel would handle copy_to_user -- line 679
+ /*if (essid->pointer)
+ {
+ if ( copy_to_user(essid->pointer, EssidBuf, essid->length) )
+ {
+ printk("giwessid - copy_to_user Fail\n");
+ return -EFAULT;
+ }
+ }*/
+
+ return 0;
+}
+
+int usbdrvwext_siwnickn(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+{
+ //Exist but junk--CWYang(+)
+ return 0;
+}
+
+int usbdrvwext_giwnickn(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *nickname)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u8_t EssidLen;
+ char EssidBuf[IW_ESSID_MAX_SIZE+1];
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ zfiWlanQuerySSID(dev, &EssidBuf[0], &EssidLen);
+ EssidBuf[EssidLen] = 0;
+
+ data->flags = 1;
+ data->length = strlen(EssidBuf);
+
+ memcpy(nickname, EssidBuf, data->length);
+
+ return 0;
+}
+
+int usbdrvwext_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frq, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ //Array to Define Rate Number that Send to Driver
+ u16_t zcIndextoRateBG[16] = {1000, 2000, 5500, 11000, 0, 0, 0, 0, 48000,
+ 24000, 12000, 6000, 54000, 36000, 18000, 9000};
+ u16_t zcRateToMCS[] = {0xff, 0, 1, 2, 3, 0xb, 0xf, 0xa, 0xe, 0x9, 0xd,
+ 0x8, 0xc};
+ u8_t i,RateIndex = 4;
+ u16_t RateKbps;
+
+ //printk("frq->disabled : 0x%x\n",frq->disabled);
+ //printk("frq->value : 0x%x\n",frq->value);
+
+ RateKbps = frq->value / 1000;
+ //printk("RateKbps : %d\n", RateKbps);
+ for (i = 0; i < 16; i++)
+ {
+ if (RateKbps == zcIndextoRateBG[i])
+ RateIndex = i;
+ }
+ if (zcIndextoRateBG[RateIndex] == 0)
+ RateIndex = 0xff;
+ //printk("RateIndex : %x\n", RateIndex);
+ for (i = 0; i < 13; i++)
+ if (RateIndex == zcRateToMCS[i])
+ break;
+ //printk("Index : %x\n", i);
+ if (RateKbps == 65000)
+ {
+ RateIndex = 20;
+ printk("RateIndex : %d\n", RateIndex);
+ }
+ if (macp->DeviceOpened == 1)
+ {
+ zfiWlanSetTxRate(dev, i);
+ //zfiWlanDisable(dev);
+ //zfiWlanEnable(dev);
+ }
+
+ return 0;
+}
+
+int usbdrvwext_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frq, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ frq->fixed = 0;
+ frq->disabled = 0;
+ frq->value = zfiWlanQueryRxRate(dev) * 1000;
+
+ return 0;
+}
+
+int usbdrvwext_siwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ int val = rts->value;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ if (rts->disabled)
+ val = 2347;
+
+ if ((val < 0) || (val > 2347))
+ return -EINVAL;
+
+ zfiWlanSetRtsThreshold(dev,val);
+
+ return 0;
+}
+
+int usbdrvwext_giwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ rts->value = zfiWlanQueryRtsThreshold(dev);
+ rts->disabled = (rts->value >= 2347);
+ rts->fixed = 1;
+
+ return 0;
+
+}
+
+int usbdrvwext_siwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t fragThreshold;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ if (frag->disabled)
+ fragThreshold = 0;
+ else
+ fragThreshold = frag->value;
+
+ zfiWlanSetFragThreshold(dev,fragThreshold);
+
+ return 0;
+}
+
+int usbdrvwext_giwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16 val;
+ unsigned long irqFlag;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ val = zfiWlanQueryFragThreshold(dev);
+
+ frag->value = val;
+
+ frag->disabled = (val >= 2346);
+ frag->fixed = 1;
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+
+ return 0;
+}
+
+int usbdrvwext_siwtxpow(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ //Not support yet--CWYng(+)
+ return 0;
+}
+
+int usbdrvwext_giwtxpow(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ //Not support yet--CWYng(+)
+ return 0;
+}
+
+int usbdrvwext_siwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ //Do nothing--CWYang(+)
+ return 0;
+}
+
+int usbdrvwext_giwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rrq, char *extra)
+{
+ //Do nothing--CWYang(+)
+ return 0;
+}
+
+int usbdrvwext_siwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+{
+ struct zsKeyInfo keyInfo;
+ int i, WepState = ZM_ENCRYPTION_WEP_DISABLED;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ if ((erq->flags & IW_ENCODE_DISABLED) == 0)
+ {
+ keyInfo.key = key;
+ keyInfo.keyLength = erq->length;
+ keyInfo.keyIndex = (erq->flags & IW_ENCODE_INDEX) - 1;
+ if (keyInfo.keyIndex >= 4)
+ keyInfo.keyIndex = 0;
+ keyInfo.flag = ZM_KEY_FLAG_DEFAULT_KEY;
+
+ zfiWlanSetKey(dev, keyInfo);
+ WepState = ZM_ENCRYPTION_WEP_ENABLED;
+ }
+ else
+ {
+ for (i = 1; i < 4; i++)
+ zfiWlanRemoveKey(dev, 0, i);
+ WepState = ZM_ENCRYPTION_WEP_DISABLED;
+ //zfiWlanSetEncryMode(dev, ZM_NO_WEP);
+ }
+
+ if (macp->DeviceOpened == 1)
+ {
+ zfiWlanSetWepStatus(dev, WepState);
+ zfiWlanSetFrequency(dev, zfiWlanQueryFrequency(dev), FALSE);
+ //zfiWlanSetEncryMode(dev, zfiWlanQueryEncryMode(dev));
+ //u8_t wpaieLen,wpaie[50];
+ //zfiWlanQueryWpaIe(dev, wpaie, &wpaieLen);
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+ //if (wpaieLen > 2)
+ // zfiWlanSetWpaIe(dev, wpaie, wpaieLen);
+ }
+
+ return 0;
+}
+
+int usbdrvwext_giwencode(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *erq, char *key)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u8_t EncryptionMode;
+ u8_t keyLen = 0;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ EncryptionMode = zfiWlanQueryEncryMode(dev);
+
+ if (EncryptionMode)
+ {
+ erq->flags = IW_ENCODE_ENABLED;
+ }
+ else
+ {
+ erq->flags = IW_ENCODE_DISABLED;
+ }
+
+/* We can't return the key, so set the proper flag and return zero */
+ erq->flags |= IW_ENCODE_NOKEY;
+ memset(key, 0, 16);
+
+/* Copy the key to the user buffer */
+ switch(EncryptionMode)
+ {
+ case ZM_WEP64:
+ keyLen = 5;
+ break;
+ case ZM_WEP128:
+ keyLen = 13;
+ break;
+ case ZM_WEP256:
+ keyLen = 29;
+ break;
+ case ZM_AES:
+ keyLen = 16;
+ break;
+ case ZM_TKIP:
+ keyLen = 32;
+ break;
+#ifdef ZM_ENABLE_CENC
+ case ZM_CENC:
+ keyLen = 32;
+ break;
+#endif //ZM_ENABLE_CENC
+ case ZM_NO_WEP:
+ keyLen = 0;
+ break;
+ default :
+ keyLen = 0;
+ printk("Unknown EncryMode\n");
+ break;
+
+ }
+ erq->length = keyLen;
+
+ return 0;
+}
+
+int usbdrvwext_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frq, char *extra)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u8_t PSMode;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ if (frq->disabled)
+ PSMode = ZM_STA_PS_NONE;
+ else
+ PSMode = ZM_STA_PS_MAX;
+
+ zfiWlanSetPowerSaveMode(dev,PSMode);
+
+ return 0;
+}
+
+int usbdrvwext_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frq, char *extra)
+{
+ unsigned long irqFlag;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if (macp->DeviceOpened != 1)
+ return 0;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ if (zfiWlanQueryPowerSaveMode(dev) == ZM_STA_PS_NONE)
+ frq->disabled = 1;
+ else
+ frq->disabled = 0;
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+
+ return 0;
+}
+
+//int usbdrvwext_setparam(struct net_device *dev, struct iw_request_info *info,
+// void *w, char *extra)
+//{
+// struct ieee80211vap *vap = dev->ml_priv;
+// struct ieee80211com *ic = vap->iv_ic;
+// struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn;
+// int *i = (int *) extra;
+// int param = i[0]; /* parameter id is 1st */
+// int value = i[1]; /* NB: most values are TYPE_INT */
+// int retv = 0;
+// int j, caps;
+// const struct ieee80211_authenticator *auth;
+// const struct ieee80211_aclator *acl;
+//
+// switch (param) {
+// case IEEE80211_PARAM_AUTHMODE:
+// switch (value) {
+// case IEEE80211_AUTH_WPA: /* WPA */
+// case IEEE80211_AUTH_8021X: /* 802.1x */
+// case IEEE80211_AUTH_OPEN: /* open */
+// case IEEE80211_AUTH_SHARED: /* shared-key */
+// case IEEE80211_AUTH_AUTO: /* auto */
+// auth = ieee80211_authenticator_get(value);
+// if (auth == NULL)
+// return -EINVAL;
+// break;
+// default:
+// return -EINVAL;
+// }
+// switch (value) {
+// case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */
+// vap->iv_flags |= IEEE80211_F_PRIVACY;
+// value = IEEE80211_AUTH_8021X;
+// break;
+// case IEEE80211_AUTH_OPEN: /* open */
+// vap->iv_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY);
+// break;
+// case IEEE80211_AUTH_SHARED: /* shared-key */
+// case IEEE80211_AUTH_AUTO: /* auto */
+// case IEEE80211_AUTH_8021X: /* 802.1x */
+// vap->iv_flags &= ~IEEE80211_F_WPA;
+// /* both require a key so mark the PRIVACY capability */
+// vap->iv_flags |= IEEE80211_F_PRIVACY;
+// break;
+// }
+// /* NB: authenticator attach/detach happens on state change */
+// vap->iv_bss->ni_authmode = value;
+// /* XXX mixed/mode/usage? */
+// vap->iv_auth = auth;
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_PROTMODE:
+// if (value > IEEE80211_PROT_RTSCTS)
+// return -EINVAL;
+// ic->ic_protmode = value;
+// /* NB: if not operating in 11g this can wait */
+// if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
+// IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_MCASTCIPHER:
+// if ((vap->iv_caps & cipher2cap(value)) == 0 &&
+// !ieee80211_crypto_available(value))
+// return -EINVAL;
+// rsn->rsn_mcastcipher = value;
+// if (vap->iv_flags & IEEE80211_F_WPA)
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_MCASTKEYLEN:
+// if (!(0 < value && value < IEEE80211_KEYBUF_SIZE))
+// return -EINVAL;
+// /* XXX no way to verify driver capability */
+// rsn->rsn_mcastkeylen = value;
+// if (vap->iv_flags & IEEE80211_F_WPA)
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_UCASTCIPHERS:
+// /*
+// * Convert cipher set to equivalent capabilities.
+// * NB: this logic intentionally ignores unknown and
+// * unsupported ciphers so folks can specify 0xff or
+// * similar and get all available ciphers.
+// */
+// caps = 0;
+// for (j = 1; j < 32; j++) /* NB: skip WEP */
+// if ((value & (1<<j)) &&
+// ((vap->iv_caps & cipher2cap(j)) ||
+// ieee80211_crypto_available(j)))
+// caps |= 1<<j;
+// if (caps == 0) /* nothing available */
+// return -EINVAL;
+// /* XXX verify ciphers ok for unicast use? */
+// /* XXX disallow if running as it'll have no effect */
+// rsn->rsn_ucastcipherset = caps;
+// if (vap->iv_flags & IEEE80211_F_WPA)
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_UCASTCIPHER:
+// if ((rsn->rsn_ucastcipherset & cipher2cap(value)) == 0)
+// return -EINVAL;
+// rsn->rsn_ucastcipher = value;
+// break;
+// case IEEE80211_PARAM_UCASTKEYLEN:
+// if (!(0 < value && value < IEEE80211_KEYBUF_SIZE))
+// return -EINVAL;
+// /* XXX no way to verify driver capability */
+// rsn->rsn_ucastkeylen = value;
+// break;
+// case IEEE80211_PARAM_KEYMGTALGS:
+// /* XXX check */
+// rsn->rsn_keymgmtset = value;
+// if (vap->iv_flags & IEEE80211_F_WPA)
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_RSNCAPS:
+// /* XXX check */
+// rsn->rsn_caps = value;
+// if (vap->iv_flags & IEEE80211_F_WPA)
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_WPA:
+// if (value > 3)
+// return -EINVAL;
+// /* XXX verify ciphers available */
+// vap->iv_flags &= ~IEEE80211_F_WPA;
+// switch (value) {
+// case 1:
+// vap->iv_flags |= IEEE80211_F_WPA1;
+// break;
+// case 2:
+// vap->iv_flags |= IEEE80211_F_WPA2;
+// break;
+// case 3:
+// vap->iv_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
+// break;
+// }
+// retv = ENETRESET; /* XXX? */
+// break;
+// case IEEE80211_PARAM_ROAMING:
+// if (!(IEEE80211_ROAMING_DEVICE <= value &&
+// value <= IEEE80211_ROAMING_MANUAL))
+// return -EINVAL;
+// ic->ic_roaming = value;
+// break;
+// case IEEE80211_PARAM_PRIVACY:
+// if (value) {
+// /* XXX check for key state? */
+// vap->iv_flags |= IEEE80211_F_PRIVACY;
+// } else
+// vap->iv_flags &= ~IEEE80211_F_PRIVACY;
+// break;
+// case IEEE80211_PARAM_DROPUNENCRYPTED:
+// if (value)
+// vap->iv_flags |= IEEE80211_F_DROPUNENC;
+// else
+// vap->iv_flags &= ~IEEE80211_F_DROPUNENC;
+// break;
+// case IEEE80211_PARAM_COUNTERMEASURES:
+// if (value) {
+// if ((vap->iv_flags & IEEE80211_F_WPA) == 0)
+// return -EINVAL;
+// vap->iv_flags |= IEEE80211_F_COUNTERM;
+// } else
+// vap->iv_flags &= ~IEEE80211_F_COUNTERM;
+// break;
+// case IEEE80211_PARAM_DRIVER_CAPS:
+// vap->iv_caps = value; /* NB: for testing */
+// break;
+// case IEEE80211_PARAM_MACCMD:
+// acl = vap->iv_acl;
+// switch (value) {
+// case IEEE80211_MACCMD_POLICY_OPEN:
+// case IEEE80211_MACCMD_POLICY_ALLOW:
+// case IEEE80211_MACCMD_POLICY_DENY:
+// if (acl == NULL) {
+// acl = ieee80211_aclator_get("mac");
+// if (acl == NULL || !acl->iac_attach(vap))
+// return -EINVAL;
+// vap->iv_acl = acl;
+// }
+// acl->iac_setpolicy(vap, value);
+// break;
+// case IEEE80211_MACCMD_FLUSH:
+// if (acl != NULL)
+// acl->iac_flush(vap);
+// /* NB: silently ignore when not in use */
+// break;
+// case IEEE80211_MACCMD_DETACH:
+// if (acl != NULL) {
+// vap->iv_acl = NULL;
+// acl->iac_detach(vap);
+// }
+// break;
+// }
+// break;
+// case IEEE80211_PARAM_WMM:
+// if (ic->ic_caps & IEEE80211_C_WME){
+// if (value) {
+// vap->iv_flags |= IEEE80211_F_WME;
+// vap->iv_ic->ic_flags |= IEEE80211_F_WME; /* XXX needed by ic_reset */
+// }
+// else {
+// vap->iv_flags &= ~IEEE80211_F_WME;
+// vap->iv_ic->ic_flags &= ~IEEE80211_F_WME; /* XXX needed by ic_reset */
+// }
+// retv = ENETRESET; /* Renegotiate for capabilities */
+// }
+// break;
+// case IEEE80211_PARAM_HIDESSID:
+// if (value)
+// vap->iv_flags |= IEEE80211_F_HIDESSID;
+// else
+// vap->iv_flags &= ~IEEE80211_F_HIDESSID;
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_APBRIDGE:
+// if (value == 0)
+// vap->iv_flags |= IEEE80211_F_NOBRIDGE;
+// else
+// vap->iv_flags &= ~IEEE80211_F_NOBRIDGE;
+// break;
+// case IEEE80211_PARAM_INACT:
+// vap->iv_inact_run = value / IEEE80211_INACT_WAIT;
+// break;
+// case IEEE80211_PARAM_INACT_AUTH:
+// vap->iv_inact_auth = value / IEEE80211_INACT_WAIT;
+// break;
+// case IEEE80211_PARAM_INACT_INIT:
+// vap->iv_inact_init = value / IEEE80211_INACT_WAIT;
+// break;
+// case IEEE80211_PARAM_ABOLT:
+// caps = 0;
+// /*
+// * Map abolt settings to capability bits;
+// * this also strips unknown/unwanted bits.
+// */
+// if (value & IEEE80211_ABOLT_TURBO_PRIME)
+// caps |= IEEE80211_ATHC_TURBOP;
+// if (value & IEEE80211_ABOLT_COMPRESSION)
+// caps |= IEEE80211_ATHC_COMP;
+// if (value & IEEE80211_ABOLT_FAST_FRAME)
+// caps |= IEEE80211_ATHC_FF;
+// if (value & IEEE80211_ABOLT_XR)
+// caps |= IEEE80211_ATHC_XR;
+// if (value & IEEE80211_ABOLT_AR)
+// caps |= IEEE80211_ATHC_AR;
+// if (value & IEEE80211_ABOLT_BURST)
+// caps |= IEEE80211_ATHC_BURST;
+// if (value & IEEE80211_ABOLT_WME_ELE)
+// caps |= IEEE80211_ATHC_WME;
+// /* verify requested capabilities are supported */
+// if ((caps & ic->ic_ath_cap) != caps)
+// return -EINVAL;
+// if (vap->iv_ath_cap != caps) {
+// if ((vap->iv_ath_cap ^ caps) & IEEE80211_ATHC_TURBOP) {
+// if (ieee80211_set_turbo(dev, caps & IEEE80211_ATHC_TURBOP))
+// return -EINVAL;
+// ieee80211_scan_flush(ic);
+// }
+// vap->iv_ath_cap = caps;
+// ic->ic_athcapsetup(vap->iv_ic, vap->iv_ath_cap);
+// retv = ENETRESET;
+// }
+// break;
+// case IEEE80211_PARAM_DTIM_PERIOD:
+// if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
+// vap->iv_opmode != IEEE80211_M_IBSS)
+// return -EINVAL;
+// if (IEEE80211_DTIM_MIN <= value &&
+// value <= IEEE80211_DTIM_MAX) {
+// vap->iv_dtim_period = value;
+// retv = ENETRESET; /* requires restart */
+// } else
+// retv = EINVAL;
+// break;
+// case IEEE80211_PARAM_BEACON_INTERVAL:
+// if (vap->iv_opmode != IEEE80211_M_HOSTAP &&
+// vap->iv_opmode != IEEE80211_M_IBSS)
+// return -EINVAL;
+// if (IEEE80211_BINTVAL_MIN <= value &&
+// value <= IEEE80211_BINTVAL_MAX) {
+// ic->ic_lintval = value; /* XXX multi-bss */
+// retv = ENETRESET; /* requires restart */
+// } else
+// retv = EINVAL;
+// break;
+// case IEEE80211_PARAM_DOTH:
+// if (value) {
+// ic->ic_flags |= IEEE80211_F_DOTH;
+// }
+// else
+// ic->ic_flags &= ~IEEE80211_F_DOTH;
+// retv = ENETRESET; /* XXX: need something this drastic? */
+// break;
+// case IEEE80211_PARAM_PWRTARGET:
+// ic->ic_curchanmaxpwr = value;
+// break;
+// case IEEE80211_PARAM_GENREASSOC:
+// IEEE80211_SEND_MGMT(vap->iv_bss, IEEE80211_FC0_SUBTYPE_REASSOC_REQ, 0);
+// break;
+// case IEEE80211_PARAM_COMPRESSION:
+// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_COMP, value);
+// break;
+// case IEEE80211_PARAM_WMM_AGGRMODE:
+// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_WME, value);
+// break;
+// case IEEE80211_PARAM_FF:
+// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_FF, value);
+// break;
+// case IEEE80211_PARAM_TURBO:
+// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_TURBOP, value);
+// if (retv == ENETRESET) {
+// if(ieee80211_set_turbo(dev,value))
+// return -EINVAL;
+// ieee80211_scan_flush(ic);
+// }
+// break;
+// case IEEE80211_PARAM_XR:
+// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_XR, value);
+// break;
+// case IEEE80211_PARAM_BURST:
+// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_BURST, value);
+// break;
+// case IEEE80211_PARAM_AR:
+// retv = ieee80211_setathcap(vap, IEEE80211_ATHC_AR, value);
+// break;
+// case IEEE80211_PARAM_PUREG:
+// if (value)
+// vap->iv_flags |= IEEE80211_F_PUREG;
+// else
+// vap->iv_flags &= ~IEEE80211_F_PUREG;
+// /* NB: reset only if we're operating on an 11g channel */
+// if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
+// IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan))
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_WDS:
+// if (value)
+// vap->iv_flags_ext |= IEEE80211_FEXT_WDS;
+// else
+// vap->iv_flags_ext &= ~IEEE80211_FEXT_WDS;
+// break;
+// case IEEE80211_PARAM_BGSCAN:
+// if (value) {
+// if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
+// return -EINVAL;
+// vap->iv_flags |= IEEE80211_F_BGSCAN;
+// } else {
+// /* XXX racey? */
+// vap->iv_flags &= ~IEEE80211_F_BGSCAN;
+// ieee80211_cancel_scan(vap); /* anything current */
+// }
+// break;
+// case IEEE80211_PARAM_BGSCAN_IDLE:
+// if (value >= IEEE80211_BGSCAN_IDLE_MIN)
+// vap->iv_bgscanidle = value*HZ/1000;
+// else
+// retv = EINVAL;
+// break;
+// case IEEE80211_PARAM_BGSCAN_INTERVAL:
+// if (value >= IEEE80211_BGSCAN_INTVAL_MIN)
+// vap->iv_bgscanintvl = value*HZ;
+// else
+// retv = EINVAL;
+// break;
+// case IEEE80211_PARAM_MCAST_RATE:
+// /* units are in KILObits per second */
+// if (value >= 256 && value <= 54000)
+// vap->iv_mcast_rate = value;
+// else
+// retv = EINVAL;
+// break;
+// case IEEE80211_PARAM_COVERAGE_CLASS:
+// if (value >= 0 && value <= IEEE80211_COVERAGE_CLASS_MAX) {
+// ic->ic_coverageclass = value;
+// if (IS_UP_AUTO(vap))
+// ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+// retv = 0;
+// }
+// else
+// retv = EINVAL;
+// break;
+// case IEEE80211_PARAM_COUNTRY_IE:
+// if (value)
+// ic->ic_flags_ext |= IEEE80211_FEXT_COUNTRYIE;
+// else
+// ic->ic_flags_ext &= ~IEEE80211_FEXT_COUNTRYIE;
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_REGCLASS:
+// if (value)
+// ic->ic_flags_ext |= IEEE80211_FEXT_REGCLASS;
+// else
+// ic->ic_flags_ext &= ~IEEE80211_FEXT_REGCLASS;
+// retv = ENETRESET;
+// break;
+// case IEEE80211_PARAM_SCANVALID:
+// vap->iv_scanvalid = value*HZ;
+// break;
+// case IEEE80211_PARAM_ROAM_RSSI_11A:
+// vap->iv_roam.rssi11a = value;
+// break;
+// case IEEE80211_PARAM_ROAM_RSSI_11B:
+// vap->iv_roam.rssi11bOnly = value;
+// break;
+// case IEEE80211_PARAM_ROAM_RSSI_11G:
+// vap->iv_roam.rssi11b = value;
+// break;
+// case IEEE80211_PARAM_ROAM_RATE_11A:
+// vap->iv_roam.rate11a = value;
+// break;
+// case IEEE80211_PARAM_ROAM_RATE_11B:
+// vap->iv_roam.rate11bOnly = value;
+// break;
+// case IEEE80211_PARAM_ROAM_RATE_11G:
+// vap->iv_roam.rate11b = value;
+// break;
+// case IEEE80211_PARAM_UAPSDINFO:
+// if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+// if (ic->ic_caps & IEEE80211_C_UAPSD) {
+// if (value)
+// IEEE80211_VAP_UAPSD_ENABLE(vap);
+// else
+// IEEE80211_VAP_UAPSD_DISABLE(vap);
+// retv = ENETRESET;
+// }
+// }
+// else if (vap->iv_opmode == IEEE80211_M_STA) {
+// vap->iv_uapsdinfo = value;
+// IEEE80211_VAP_UAPSD_ENABLE(vap);
+// retv = ENETRESET;
+// }
+// break;
+// case IEEE80211_PARAM_SLEEP:
+// /* XXX: Forced sleep for testing. Does not actually place the
+// * HW in sleep mode yet. this only makes sense for STAs.
+// */
+// if (value) {
+// /* goto sleep */
+// IEEE80211_VAP_GOTOSLEEP(vap);
+// }
+// else {
+// /* wakeup */
+// IEEE80211_VAP_WAKEUP(vap);
+// }
+// ieee80211_send_nulldata(ieee80211_ref_node(vap->iv_bss));
+// break;
+// case IEEE80211_PARAM_QOSNULL:
+// /* Force a QoS Null for testing. */
+// ieee80211_send_qosnulldata(vap->iv_bss, value);
+// break;
+// case IEEE80211_PARAM_PSPOLL:
+// /* Force a PS-POLL for testing. */
+// ieee80211_send_pspoll(vap->iv_bss);
+// break;
+// case IEEE80211_PARAM_EOSPDROP:
+// if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+// if (value) IEEE80211_VAP_EOSPDROP_ENABLE(vap);
+// else IEEE80211_VAP_EOSPDROP_DISABLE(vap);
+// }
+// break;
+// case IEEE80211_PARAM_MARKDFS:
+// if (value)
+// ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS;
+// else
+// ic->ic_flags_ext &= ~IEEE80211_FEXT_MARKDFS;
+// break;
+// case IEEE80211_PARAM_CHANBW:
+// switch (value) {
+// case 0:
+// ic->ic_chanbwflag = 0;
+// break;
+// case 1:
+// ic->ic_chanbwflag = IEEE80211_CHAN_HALF;
+// break;
+// case 2:
+// ic->ic_chanbwflag = IEEE80211_CHAN_QUARTER;
+// break;
+// default:
+// retv = EINVAL;
+// break;
+// }
+// break;
+// case IEEE80211_PARAM_SHORTPREAMBLE:
+// if (value) {
+// ic->ic_caps |= IEEE80211_C_SHPREAMBLE;
+// } else {
+// ic->ic_caps &= ~IEEE80211_C_SHPREAMBLE;
+// }
+// retv = ENETRESET;
+// break;
+// default:
+// retv = EOPNOTSUPP;
+// break;
+// }
+// /* XXX should any of these cause a rescan? */
+// if (retv == ENETRESET)
+// retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
+// return -retv;
+//}
+
+int usbdrvwext_setmode(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+{
+ return 0;
+}
+
+int usbdrvwext_getmode(struct net_device *dev, struct iw_request_info *info,
+ void *w, char *extra)
+{
+ //struct usbdrv_private *macp = dev->ml_priv;
+ struct iw_point *wri = (struct iw_point *)extra;
+ char mode[8];
+
+ strcpy(mode,"11g");
+ return (copy_to_user(wri->pointer, mode, 6) ? -EFAULT : 0);
+}
+
+int zfLnxPrivateIoctl(struct net_device *dev, struct zdap_ioctl* zdreq)
+{
+ //void* regp = macp->regp;
+ u16_t cmd;
+ //u32_t temp;
+ u32_t* p;
+ u32_t i;
+
+ cmd = zdreq->cmd;
+ switch(cmd)
+ {
+ case ZM_IOCTL_REG_READ:
+ zfiDbgReadReg(dev, zdreq->addr);
+ break;
+
+ case ZM_IOCTL_REG_WRITE:
+ zfiDbgWriteReg(dev, zdreq->addr, zdreq->value);
+ break;
+
+ case ZM_IOCTL_MEM_READ:
+ p = (u32_t *) bus_to_virt(zdreq->addr);
+ printk(KERN_DEBUG "usbdrv: read memory addr: 0x%08x value: 0x%08x\n", zdreq->addr, *p);
+ break;
+
+ case ZM_IOCTL_MEM_WRITE:
+ p = (u32_t *) bus_to_virt(zdreq->addr);
+ *p = zdreq->value;
+ printk(KERN_DEBUG "usbdrv: write value: 0x%08x to memory addr: 0x%08x\n", zdreq->value, zdreq->addr);
+ break;
+
+ case ZM_IOCTL_TALLY :
+ zfiWlanShowTally(dev);
+ if (zdreq->addr)
+ zfiWlanResetTally(dev);
+ break;
+
+ case ZM_IOCTL_TEST :
+ printk(KERN_DEBUG "ZM_IOCTL_TEST:len=%d\n", zdreq->addr);
+ //zfiWlanReadReg(dev, 0x10f400);
+ //zfiWlanReadReg(dev, 0x10f404);
+ printk("IOCTL TEST\n");
+ #if 1
+ //print packet
+ for (i=0; i<zdreq->addr; i++)
+ {
+ if ((i&0x7) == 0)
+ {
+ printk("\n");
+ }
+ printk("%02X ", (unsigned char)zdreq->data[i]);
+ }
+ printk("\n");
+ #endif
+
+
+ #if 0 //For Test?? 1 to 0 by CWYang(-)
+ {
+ struct sk_buff* s;
+
+ /* Allocate a skb */
+ s = alloc_skb(2000, GFP_ATOMIC);
+
+ /* Copy data to skb */
+ for (i=0; i<zdreq->addr; i++)
+ {
+ s->data[i] = zdreq->data[i];
+ }
+ s->len = zdreq->addr;
+
+ /* Call zfIdlRecv() */
+ zfiRecv80211(dev, s, NULL);
+ }
+ #endif
+
+ break;
+
+
+/****************************** ZDCONFIG ******************************/
+ case ZM_IOCTL_FRAG :
+ zfiWlanSetFragThreshold(dev, zdreq->addr);
+ break;
+
+ case ZM_IOCTL_RTS :
+ zfiWlanSetRtsThreshold(dev, zdreq->addr);
+ break;
+
+ case ZM_IOCTL_SCAN :
+ zfiWlanScan(dev);
+ break;
+
+ case ZM_IOCTL_KEY :
+ {
+ u8_t key[29];
+ struct zsKeyInfo keyInfo;
+ u32_t i;
+
+ for (i=0; i<29; i++)
+ {
+ key[i] = 0;
+ }
+
+ for (i=0; i<zdreq->addr; i++)
+ {
+ key[i] = zdreq->data[i];
+ }
+
+ printk("key len=%d, key=%02x%02x%02x%02x%02x...\n",
+ zdreq->addr, key[0], key[1], key[2], key[3], key[4]);
+
+ keyInfo.keyLength = zdreq->addr;
+ keyInfo.keyIndex = 0;
+ keyInfo.flag = 0;
+ keyInfo.key = key;
+ zfiWlanSetKey(dev, keyInfo);
+ }
+ break;
+
+ case ZM_IOCTL_RATE :
+ zfiWlanSetTxRate(dev, zdreq->addr);
+ break;
+
+ case ZM_IOCTL_ENCRYPTION_MODE :
+ zfiWlanSetEncryMode(dev, zdreq->addr);
+
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+ break;
+ //CWYang(+)
+ case ZM_IOCTL_SIGNAL_STRENGTH :
+ {
+ u8_t buffer[2];
+ zfiWlanQuerySignalInfo(dev, &buffer[0]);
+ printk("Current Signal Strength : %02d\n", buffer[0]);
+ }
+ break;
+ //CWYang(+)
+ case ZM_IOCTL_SIGNAL_QUALITY :
+ {
+ u8_t buffer[2];
+ zfiWlanQuerySignalInfo(dev, &buffer[0]);
+ printk("Current Signal Quality : %02d\n", buffer[1]);
+ }
+ break;
+
+ case ZM_IOCTL_SET_PIBSS_MODE:
+ if (zdreq->addr == 1)
+ zfiWlanSetWlanMode(dev, ZM_MODE_PSEUDO);
+ else
+ zfiWlanSetWlanMode(dev, ZM_MODE_INFRASTRUCTURE);
+
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+
+ break;
+/****************************** ZDCONFIG ******************************/
+
+ default :
+ printk(KERN_ERR "usbdrv: error command = %x\n", cmd);
+ break;
+ }
+
+ return 0;
+}
+
+int usbdrv_wpa_ioctl(struct net_device *dev, struct athr_wlan_param *zdparm)
+{
+ int ret = 0;
+ u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ u8_t mac_addr[80];
+ struct zsKeyInfo keyInfo;
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t vapId = 0;
+
+ //zmw_get_wlan_dev(dev);
+
+ switch(zdparm->cmd)
+ {
+ case ZD_CMD_SET_ENCRYPT_KEY:
+
+ /* Set up key information */
+ keyInfo.keyLength = zdparm->u.crypt.key_len;
+ keyInfo.keyIndex = zdparm->u.crypt.idx;
+ if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
+ keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR;
+ else
+ keyInfo.flag = 0;
+ keyInfo.key = zdparm->u.crypt.key;
+ keyInfo.initIv = zdparm->u.crypt.seq;
+ keyInfo.macAddr = (u16_t *)zdparm->sta_addr;
+
+ /* Identify the MAC address information */
+ if (memcmp(zdparm->sta_addr, bc_addr, sizeof(bc_addr)) == 0)
+ {
+ keyInfo.flag |= ZM_KEY_FLAG_GK;
+ }
+ else
+ {
+ keyInfo.flag |= ZM_KEY_FLAG_PK;
+ }
+
+ if (!strcmp(zdparm->u.crypt.alg, "NONE"))
+ {
+ //u8_t zero_mac[]={0,0,0,0,0,0};
+
+ /* Set key length to zero */
+ keyInfo.keyLength = 0;
+
+ if (zdparm->sta_addr[0] & 1)//del group key
+ {
+ //if (macp->cardSetting.WPAIeLen==0)
+ //{//802.1x dynamic WEP
+ // mDynKeyMode = 0;
+ // mKeyFormat[0] = 0;
+ // mPrivacyInvoked[0]=FALSE;
+ // mCap[0] &= ~CAP_PRIVACY;
+ // macp->cardSetting.EncryOnOff[0]=0;
+ //}
+ //mWpaBcKeyLen = mGkInstalled = 0;
+ }
+ else
+ {
+ //if (memcmp(zero_mac,zdparm->sta_addr, 6)==0)
+ //{
+ // mDynKeyMode=0;
+ // mKeyFormat[0]=0;
+ // pSetting->DynKeyMode=0;
+ // pSetting->EncryMode[0]=0;
+ // mDynKeyMode=0;
+ //}
+ }
+
+ printk(KERN_ERR "Set Encryption Type NONE\n");
+ return ret;
+ }
+ else if (!strcmp(zdparm->u.crypt.alg, "TKIP"))
+ {
+ zfiWlanSetEncryMode(dev, ZM_TKIP);
+ //Linux Supplicant will inverse Tx/Rx key
+ //So we inverse it back //CWYang(+)
+ //zfMemoryCopy(&temp[0], &keyInfo.key[16], 8);
+ //zfMemoryCopy(&keyInfo.key[16], keyInfo.key[24], 8);
+ //zfMemoryCopy(&keyInfo.key[24], &temp[0], 8);
+ //u8_t temp;
+ //int k;
+ //for (k = 0; k < 8; k++)
+ //{
+ // temp = keyInfo.key[16 + k];
+ // keyInfo.key[16 + k] = keyInfo.key[24 + k];
+ // keyInfo.key[24 + k] = temp;
+ //}
+ //CamEncryType = ZM_TKIP;
+ ////if (idx == 0)
+ //{// Pairwise key
+ // mKeyFormat[0] = CamEncryType;
+ // mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_TKIP;
+ //}
+ }
+ else if (!strcmp(zdparm->u.crypt.alg, "CCMP"))
+ {
+ zfiWlanSetEncryMode(dev, ZM_AES);
+ //CamEncryType = ZM_AES;
+ ////if (idx == 0)
+ //{// Pairwise key
+ // mKeyFormat[0] = CamEncryType;
+ // mDynKeyMode = pSetting->DynKeyMode = DYN_KEY_AES;
+ //}
+ }
+ else if (!strcmp(zdparm->u.crypt.alg, "WEP"))
+ {
+ if (keyInfo.keyLength == 5)
+ { // WEP 64
+ zfiWlanSetEncryMode(dev, ZM_WEP64);
+ // CamEncryType = ZM_WEP64;
+ // tmpDynKeyMode=DYN_KEY_WEP64;
+ }
+ else if (keyInfo.keyLength == 13)
+ {//keylen=13, WEP 128
+ zfiWlanSetEncryMode(dev, ZM_WEP128);
+ // CamEncryType = ZM_WEP128;
+ // tmpDynKeyMode=DYN_KEY_WEP128;
+ }
+ else
+ {
+ zfiWlanSetEncryMode(dev, ZM_WEP256);
+ }
+
+ // For Dynamic WEP key (Non-WPA Radius), the key ID range: 0-3
+ // In WPA/RSN mode, the key ID range: 1-3, usually, a broadcast key.
+ // For WEP key setting: we set mDynKeyMode and mKeyFormat in following case:
+ // 1. For 802.1x dynamically generated WEP key method.
+ // 2. For WPA/RSN mode, but key id == 0. (But this is an impossible case)
+ // So, only check case 1.
+ //if (macp->cardSetting.WPAIeLen==0)
+ //{
+ // mKeyFormat[0] = CamEncryType;
+ // mDynKeyMode = pSetting->DynKeyMode = tmpDynKeyMode;
+ // mPrivacyInvoked[0]=TRUE;
+ // mCap[0] |= CAP_PRIVACY;
+ // macp->cardSetting.EncryOnOff[0]=1;
+ //}
+ }
+
+ /* DUMP key context */
+//#ifdef WPA_DEBUG
+ if (keyInfo.keyLength > 0)
+ {
+ int ii;
+ printk("Otus: Key Context:\n");
+ for(ii = 0; ii < keyInfo.keyLength;)
+ {
+ printk("0x%02x ", keyInfo.key[ii]);
+ if((++ii % 16) == 0)
+ printk("\n");
+ }
+ printk("\n");
+ }
+//#endif
+
+ /* Set encrypt mode */
+ //zfiWlanSetEncryMode(dev, CamEncryType);
+ vapId = zfLnxGetVapId(dev);
+ if (vapId == 0xffff)
+ keyInfo.vapId = 0;
+ else
+ keyInfo.vapId = vapId + 1;
+ keyInfo.vapAddr[0] = keyInfo.macAddr[0];
+ keyInfo.vapAddr[1] = keyInfo.macAddr[1];
+ keyInfo.vapAddr[2] = keyInfo.macAddr[2];
+
+ zfiWlanSetKey(dev, keyInfo);
+
+ //zfiWlanDisable(dev);
+ //zfiWlanEnable(dev);
+ break;
+
+ case ZD_CMD_SET_MLME:
+ printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SET_MLME\n");
+
+ /* Translate STA's address */
+ sprintf(mac_addr, "%02x:%02x:%02x:%02x:%02x:%02x", zdparm->sta_addr[0], zdparm->sta_addr[1],
+ zdparm->sta_addr[2], zdparm->sta_addr[3], zdparm->sta_addr[4], zdparm->sta_addr[5]);
+
+ switch(zdparm->u.mlme.cmd)
+ {
+ case MLME_STA_DEAUTH:
+ printk(" -------Call zfiWlanDeauth, reason:%d\n",zdparm->u.mlme.reason_code);
+ if(zfiWlanDeauth(dev, (u16_t*) zdparm->sta_addr, zdparm->u.mlme.reason_code) != 0)
+ printk(KERN_ERR "Can't deauthencate STA: %s\n", mac_addr);
+ else
+ printk(KERN_ERR "Deauthenticate STA: %s with reason code: %d\n", mac_addr, zdparm->u.mlme.reason_code);
+ break;
+
+ case MLME_STA_DISASSOC:
+ printk(" -------Call zfiWlanDeauth, reason:%d\n",zdparm->u.mlme.reason_code);
+ if(zfiWlanDeauth(dev, (u16_t*) zdparm->sta_addr, zdparm->u.mlme.reason_code) != 0)
+ printk(KERN_ERR "Can't disassociate STA: %s\n", mac_addr);
+ else
+ printk(KERN_ERR "Disassociate STA: %s with reason code: %d\n", mac_addr, zdparm->u.mlme.reason_code);
+ break;
+
+ default:
+ printk(KERN_ERR "MLME command: 0x%04x not support\n", zdparm->u.mlme.cmd);
+ break;
+ }
+
+ break;
+
+ case ZD_CMD_SCAN_REQ:
+ printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SCAN_REQ\n");
+ break;
+
+ case ZD_CMD_SET_GENERIC_ELEMENT:
+ printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SET_GENERIC_ELEMENT\n");
+
+ /* Copy the WPA IE */
+ //zm_msg1_mm(ZM_LV_0, "CWY - wpaie Length : ", zdparm->u.generic_elem.len);
+ printk(KERN_ERR "wpaie Length : %d\n", zdparm->u.generic_elem.len);
+ if (zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) // AP Mode
+ {
+ zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len);
+ }
+ else
+ {
+ macp->supLen = zdparm->u.generic_elem.len;
+ memcpy(macp->supIe, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len);
+ }
+ zfiWlanSetWpaSupport(dev, 1);
+ //zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data, zdparm->u.generic_elem.len);
+ {
+ int ii;
+ u8_t len = zdparm->u.generic_elem.len;
+ u8_t *wpaie = (u8_t *)zdparm->u.generic_elem.data;
+
+ printk(KERN_ERR "wd->ap.wpaLen: %d\n", len);
+
+ /* DUMP WPA IE */
+ for(ii = 0; ii < len;)
+ {
+ printk(KERN_ERR "0x%02x ", wpaie[ii]);
+
+ if((++ii % 16) == 0)
+ printk(KERN_ERR "\n");
+ }
+ printk(KERN_ERR "\n");
+ }
+
+// #ifdef ZM_HOSTAPD_SUPPORT
+ //if (wd->wlanMode == ZM_MODE_AP)
+ //{// Update Beacon FIFO in the next TBTT.
+ // memcpy(&mWPAIe, pSetting->WPAIe, pSetting->WPAIeLen);
+ // printk(KERN_ERR "Copy WPA IE into mWPAIe\n");
+ //}
+// #endif
+ break;
+
+// #ifdef ZM_HOSTAPD_SUPPORT
+ case ZD_CMD_GET_TSC:
+ printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_GET_TSC\n");
+ break;
+// #endif
+
+ default:
+ printk(KERN_ERR "usbdrv_wpa_ioctl default: 0x%04x\n", zdparm->cmd);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+#ifdef ZM_ENABLE_CENC
+int usbdrv_cenc_ioctl(struct net_device *dev, struct zydas_cenc_param *zdparm)
+{
+ //struct usbdrv_private *macp = dev->ml_priv;
+ struct zsKeyInfo keyInfo;
+ u16_t apId;
+ u8_t bc_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ int ret = 0;
+ int ii;
+
+ /* Get the AP Id */
+ apId = zfLnxGetVapId(dev);
+
+ if (apId == 0xffff)
+ {
+ apId = 0;
+ }
+ else
+ {
+ apId = apId+1;
+ }
+
+ switch (zdparm->cmd)
+ {
+ case ZM_CMD_CENC_SETCENC:
+ printk(KERN_ERR "ZM_CMD_CENC_SETCENC\n");
+ printk(KERN_ERR "length: %d\n", zdparm->len);
+ printk(KERN_ERR "policy: %d\n", zdparm->u.info.cenc_policy);
+ break;
+ case ZM_CMD_CENC_SETKEY:
+ //ret = wai_ioctl_setkey(vap, ioctl_msg);
+ printk(KERN_ERR "ZM_CMD_CENC_SETKEY\n");
+
+ printk(KERN_ERR "MAC address= ");
+ for(ii = 0; ii < 6; ii++)
+ {
+ printk(KERN_ERR "0x%02x ", zdparm->u.crypt.sta_addr[ii]);
+ }
+ printk(KERN_ERR "\n");
+
+ printk(KERN_ERR "Key Index: %d\n", zdparm->u.crypt.keyid);
+ printk(KERN_ERR "Encryption key= ");
+ for(ii = 0; ii < 16; ii++)
+ {
+ printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]);
+ }
+ printk(KERN_ERR "\n");
+
+ printk(KERN_ERR "MIC key= ");
+ for(ii = 16; ii < ZM_CENC_KEY_SIZE; ii++)
+ {
+ printk(KERN_ERR "0x%02x ", zdparm->u.crypt.key[ii]);
+ }
+ printk(KERN_ERR "\n");
+
+ /* Set up key information */
+ keyInfo.keyLength = ZM_CENC_KEY_SIZE;
+ keyInfo.keyIndex = zdparm->u.crypt.keyid;
+ keyInfo.flag = ZM_KEY_FLAG_AUTHENTICATOR | ZM_KEY_FLAG_CENC;
+ keyInfo.key = zdparm->u.crypt.key;
+ keyInfo.macAddr = (u16_t *)zdparm->u.crypt.sta_addr;
+
+ /* Identify the MAC address information */
+ if (memcmp(zdparm->u.crypt.sta_addr, bc_addr, sizeof(bc_addr)) == 0)
+ {
+ keyInfo.flag |= ZM_KEY_FLAG_GK;
+ keyInfo.vapId = apId;
+ memcpy(keyInfo.vapAddr, dev->dev_addr, ETH_ALEN);
+ }
+ else
+ {
+ keyInfo.flag |= ZM_KEY_FLAG_PK;
+ }
+
+ zfiWlanSetKey(dev, keyInfo);
+
+ break;
+ case ZM_CMD_CENC_REKEY:
+ //ret = wai_ioctl_rekey(vap, ioctl_msg);
+ printk(KERN_ERR "ZM_CMD_CENC_REKEY\n");
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+
+ }
+
+ //if (retv == ENETRESET)
+ // retv = IS_UP_AUTO(vap) ? ieee80211_open(vap->iv_dev) : 0;
+
+ return ret;
+}
+#endif //ZM_ENABLE_CENC
+/////////////////////////////////////////
+int usbdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+// struct usbdrv_private *macp;
+// void *regp;
+ struct zdap_ioctl zdreq;
+ struct iwreq *wrq = (struct iwreq *)ifr;
+ struct athr_wlan_param zdparm;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ int err = 0;
+ int changed = 0;
+
+// regp = macp->regp;
+
+ if(!netif_running(dev))
+ return -EINVAL;
+
+ switch (cmd)
+ {
+ case SIOCGIWNAME:
+ strcpy(wrq->u.name, "IEEE 802.11-DS");
+ break;
+
+ case SIOCGIWAP:
+ err = usbdrvwext_giwap(dev, NULL, &wrq->u.ap_addr, NULL);
+ break;
+
+
+ case SIOCSIWAP:
+ err = usbdrvwext_siwap(dev, NULL, &wrq->u.ap_addr, NULL);
+ break;
+
+
+ case SIOCGIWMODE:
+ err = usbdrvwext_giwmode(dev, NULL, &wrq->u.mode, NULL);
+ break;
+
+
+ case SIOCSIWESSID:
+ printk(KERN_ERR "CWY - usbdrvwext_siwessid\n");
+ //err = usbdrv_ioctl_setessid(dev, &wrq->u.essid);
+ err = usbdrvwext_siwessid(dev, NULL, &wrq->u.essid, NULL);
+
+ if (! err)
+ changed = 1;
+ break;
+
+
+ case SIOCGIWESSID:
+ err = usbdrvwext_giwessid(dev, NULL, &wrq->u.essid, NULL);
+ break;
+
+
+ case SIOCSIWRTS:
+
+ err = usbdrv_ioctl_setrts(dev, &wrq->u.rts);
+ if (! err)
+ changed = 1;
+ break;
+
+
+ case SIOCIWFIRSTPRIV + 0x2: /* set_auth */
+ {
+ //printk("CWY - SIOCIWFIRSTPRIV + 0x2 (set_auth)\n");
+ if (! capable(CAP_NET_ADMIN))
+ {
+ err = -EPERM;
+ break;
+ }
+ {
+ int val = *( (int *) wrq->u.name );
+ if ((val < 0) || (val > 2))
+ {
+ err = -EINVAL;
+ break;
+ }
+ else
+ {
+ zfiWlanSetAuthenticationMode(dev, val);
+
+ if (macp->DeviceOpened == 1)
+ {
+ zfiWlanDisable(dev, 0);
+ zfiWlanEnable(dev);
+ }
+
+ err = 0;
+ changed = 1;
+ }
+ }
+ }
+ break;
+
+ case SIOCIWFIRSTPRIV + 0x3: /* get_auth */
+ {
+ int AuthMode = ZM_AUTH_MODE_OPEN;
+
+ //printk("CWY - SIOCIWFIRSTPRIV + 0x3 (get_auth)\n");
+
+ if (wrq->u.data.pointer)
+ {
+ wrq->u.data.flags = 1;
+
+ AuthMode = zfiWlanQueryAuthenticationMode(dev, 0);
+ if (AuthMode == ZM_AUTH_MODE_OPEN)
+ {
+ wrq->u.data.length = 12;
+
+ if (copy_to_user(wrq->u.data.pointer, "open system", 12))
+ {
+ return -EFAULT;
+ }
+ }
+ else if (AuthMode == ZM_AUTH_MODE_SHARED_KEY)
+ {
+ wrq->u.data.length = 11;
+
+ if (copy_to_user(wrq->u.data.pointer, "shared key", 11))
+ {
+ return -EFAULT;
+ }
+ }
+ else if (AuthMode == ZM_AUTH_MODE_AUTO)
+ {
+ wrq->u.data.length = 10;
+
+ if (copy_to_user(wrq->u.data.pointer, "auto mode", 10))
+ {
+ return -EFAULT;
+ }
+ }
+ else
+ {
+ return -EFAULT;
+ }
+ }
+ }
+ break;
+
+
+ case ZDAPIOCTL: //debug command
+ if (copy_from_user(&zdreq, ifr->ifr_data, sizeof (zdreq)))
+ {
+ printk(KERN_ERR "usbdrv: copy_from_user error\n");
+ return -EFAULT;
+ }
+
+ //printk(KERN_DEBUG "usbdrv: cmd=%2x, reg=0x%04lx, value=0x%08lx\n",
+ // zdreq.cmd, zdreq.addr, zdreq.value);
+
+ zfLnxPrivateIoctl(dev, &zdreq);
+
+ err = 0;
+ break;
+
+ case ZD_IOCTL_WPA:
+ if (copy_from_user(&zdparm, ifr->ifr_data, sizeof(struct athr_wlan_param)))
+ {
+ printk(KERN_ERR "usbdrv: copy_from_user error\n");
+ return -EFAULT;
+ }
+
+ usbdrv_wpa_ioctl(dev, &zdparm);
+ err = 0;
+ break;
+
+ case ZD_IOCTL_PARAM:
+ {
+ int *p;
+ int op;
+ int arg;
+
+ /* Point to the name field and retrieve the
+ * op and arg elements. */
+ p = (int *)wrq->u.name;
+ op = *p++;
+ arg = *p;
+
+ if(op == ZD_PARAM_ROAMING)
+ {
+ printk(KERN_ERR "************* ZD_PARAM_ROAMING: %d\n", arg);
+ //macp->cardSetting.ap_scan=(U8)arg;
+ }
+ if(op == ZD_PARAM_PRIVACY)
+ {
+ printk(KERN_ERR "ZD_IOCTL_PRIVACY: ");
+
+ /* Turn on the privacy invoke flag */
+ if(arg)
+ {
+ // mCap[0] |= CAP_PRIVACY;
+ // macp->cardSetting.EncryOnOff[0] = 1;
+ printk(KERN_ERR "enable\n");
+
+ }
+ else
+ {
+ // mCap[0] &= ~CAP_PRIVACY;
+ // macp->cardSetting.EncryOnOff[0] = 0;
+ printk(KERN_ERR "disable\n");
+ }
+ //changed=1;
+ }
+ if(op == ZD_PARAM_WPA)
+ {
+ printk(KERN_ERR "ZD_PARAM_WPA: ");
+
+ if(arg)
+ {
+ printk(KERN_ERR "enable\n");
+
+ if (zfiWlanQueryWlanMode(dev) != ZM_MODE_AP)
+ {
+ printk(KERN_ERR "Station Mode\n");
+ //zfiWlanQueryWpaIe(dev, (u8_t *)&wpaIe, &wpalen);
+ //printk("wpaIe : %2x,%2x,%2x\n", wpaIe[21], wpaIe[22], wpaIe[23]);
+ //printk("rsnIe : %2x,%2x,%2x\n", wpaIe[17], wpaIe[18], wpaIe[19]);
+ if ((macp->supIe[21] == 0x50) &&
+ (macp->supIe[22] == 0xf2) &&
+ (macp->supIe[23] == 0x2))
+ {
+ printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPAPSK\n");
+ //wd->sta.authMode = ZM_AUTH_MODE_WPAPSK;
+ //wd->ws.authMode = ZM_AUTH_MODE_WPAPSK;
+ zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPAPSK);
+ }
+ else if ((macp->supIe[21] == 0x50) &&
+ (macp->supIe[22] == 0xf2) &&
+ (macp->supIe[23] == 0x1))
+ {
+ printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA\n");
+ //wd->sta.authMode = ZM_AUTH_MODE_WPA;
+ //wd->ws.authMode = ZM_AUTH_MODE_WPA;
+ zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA);
+ }
+ else if ((macp->supIe[17] == 0xf) &&
+ (macp->supIe[18] == 0xac) &&
+ (macp->supIe[19] == 0x2))
+ {
+ printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK\n");
+ //wd->sta.authMode = ZM_AUTH_MODE_WPA2PSK;
+ //wd->ws.authMode = ZM_AUTH_MODE_WPA2PSK;
+ zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA2PSK);
+ }
+ else if ((macp->supIe[17] == 0xf) &&
+ (macp->supIe[18] == 0xac) &&
+ (macp->supIe[19] == 0x1))
+ {
+ printk(KERN_ERR "wd->sta.authMode = ZM_AUTH_MODE_WPA2\n");
+ //wd->sta.authMode = ZM_AUTH_MODE_WPA2;
+ //wd->ws.authMode = ZM_AUTH_MODE_WPA2;
+ zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_WPA2);
+ }
+ if ((macp->supIe[21] == 0x50) || (macp->supIe[22] == 0xf2))//WPA or WPAPSK
+ {
+ if (macp->supIe[11] == 0x2)
+ {
+ printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n");
+ //wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
+ //wd->ws.wepStatus = ZM_ENCRYPTION_TKIP;
+ zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP);
+ }
+ else
+ {
+ printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n");
+ //wd->sta.wepStatus = ZM_ENCRYPTION_AES;
+ //wd->ws.wepStatus = ZM_ENCRYPTION_AES;
+ zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES);
+ }
+ }
+ if ((macp->supIe[17] == 0xf) || (macp->supIe[18] == 0xac)) //WPA2 or WPA2PSK
+ {
+ if (macp->supIe[13] == 0x2)
+ {
+ printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_TKIP\n");
+ //wd->sta.wepStatus = ZM_ENCRYPTION_TKIP;
+ //wd->ws.wepStatus = ZM_ENCRYPTION_TKIP;
+ zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_TKIP);
+ }
+ else
+ {
+ printk(KERN_ERR "wd->sta.wepStatus = ZM_ENCRYPTION_AES\n");
+ //wd->sta.wepStatus = ZM_ENCRYPTION_AES;
+ //wd->ws.wepStatus = ZM_ENCRYPTION_AES;
+ zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_AES);
+ }
+ }
+ }
+ zfiWlanSetWpaSupport(dev, 1);
+ }
+ else
+ {
+ /* Reset the WPA related variables */
+ printk(KERN_ERR "disable\n");
+
+ zfiWlanSetWpaSupport(dev, 0);
+ zfiWlanSetAuthenticationMode(dev, ZM_AUTH_MODE_OPEN);
+ zfiWlanSetWepStatus(dev, ZM_ENCRYPTION_WEP_DISABLED);
+
+ /* Now we only set the length in the WPA IE
+ * field to zero. */
+ //macp->cardSetting.WPAIe[1] = 0;
+ }
+ }
+ if(op == ZD_PARAM_COUNTERMEASURES)
+ {
+ printk(KERN_ERR "================ZD_PARAM_COUNTERMEASURES: ");
+
+ if(arg)
+ {
+ // mCounterMeasureState=1;
+ printk(KERN_ERR "enable\n");
+ }
+ else
+ {
+ // mCounterMeasureState=0;
+ printk(KERN_ERR "disable\n");
+ }
+ }
+ if(op == ZD_PARAM_DROPUNENCRYPTED)
+ {
+ printk(KERN_ERR "ZD_PARAM_DROPUNENCRYPTED: ");
+
+ if(arg)
+ {
+ printk(KERN_ERR "enable\n");
+ }
+ else
+ {
+ printk(KERN_ERR "disable\n");
+ }
+ }
+ if(op == ZD_PARAM_AUTH_ALGS)
+ {
+ printk(KERN_ERR "ZD_PARAM_AUTH_ALGS: ");
+
+ if(arg == 0)
+ {
+ printk(KERN_ERR "OPEN_SYSTEM\n");
+ }
+ else
+ {
+ printk(KERN_ERR "SHARED_KEY\n");
+ }
+ }
+ if(op == ZD_PARAM_WPS_FILTER)
+ {
+ printk(KERN_ERR "ZD_PARAM_WPS_FILTER: ");
+
+ if(arg)
+ {
+ // mCounterMeasureState=1;
+ macp->forwardMgmt = 1;
+ printk(KERN_ERR "enable\n");
+ }
+ else
+ {
+ // mCounterMeasureState=0;
+ macp->forwardMgmt = 0;
+ printk(KERN_ERR "disable\n");
+ }
+ }
+ }
+ err = 0;
+ break;
+
+ case ZD_IOCTL_GETWPAIE:
+ {
+ struct ieee80211req_wpaie req_wpaie;
+ u16_t apId, i, j;
+
+ /* Get the AP Id */
+ apId = zfLnxGetVapId(dev);
+
+ if (apId == 0xffff)
+ {
+ apId = 0;
+ }
+ else
+ {
+ apId = apId+1;
+ }
+
+ if (copy_from_user(&req_wpaie, ifr->ifr_data, sizeof(struct ieee80211req_wpaie))){
+ printk(KERN_ERR "usbdrv: copy_from_user error\n");
+ return -EFAULT;
+ }
+
+ for(i = 0; i < ZM_OAL_MAX_STA_SUPPORT; i++)
+ {
+ for(j = 0; j < IEEE80211_ADDR_LEN; j++)
+ {
+ if (macp->stawpaie[i].wpa_macaddr[j] != req_wpaie.wpa_macaddr[j])
+ break;
+ }
+ if (j == 6)
+ break;
+ }
+ if (i < ZM_OAL_MAX_STA_SUPPORT)
+ {
+ //printk("ZD_IOCTL_GETWPAIE - sta index = %d\n", i);
+ memcpy(req_wpaie.wpa_ie, macp->stawpaie[i].wpa_ie, IEEE80211_MAX_IE_SIZE);
+ }
+
+ if (copy_to_user(wrq->u.data.pointer, &req_wpaie, sizeof(struct ieee80211req_wpaie)))
+ {
+ return -EFAULT;
+ }
+ }
+
+ err = 0;
+ break;
+#ifdef ZM_ENABLE_CENC
+ case ZM_IOCTL_CENC:
+ if (copy_from_user(&macp->zd_wpa_req, ifr->ifr_data, sizeof(struct athr_wlan_param)))
+ {
+ printk(KERN_ERR "usbdrv: copy_from_user error\n");
+ return -EFAULT;
+ }
+
+ usbdrv_cenc_ioctl(dev, (struct zydas_cenc_param *)&macp->zd_wpa_req);
+ err = 0;
+ break;
+#endif //ZM_ENABLE_CENC
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+
+ return err;
+}
diff --git a/drivers/staging/otus/oal_dt.h b/drivers/staging/otus/oal_dt.h
new file mode 100644
index 000000000000..e82b9770fca1
--- /dev/null
+++ b/drivers/staging/otus/oal_dt.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : oal_dt.h */
+/* */
+/* Abstract */
+/* This module contains data type definition. */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#ifndef _OAL_DT_H
+#define _OAL_DT_H
+
+/* Please include header files for buffer type in the beginning of this file */
+/* Please include header files for device type here */
+#include <linux/netdevice.h>
+
+typedef unsigned long long u64_t;
+typedef unsigned int u32_t;
+typedef unsigned short u16_t;
+typedef unsigned char u8_t;
+typedef long long s64_t;
+typedef long s32_t;
+typedef short s16_t;
+typedef char s8_t;
+
+#ifndef TRUE
+#define TRUE (1==1)
+#endif
+
+#ifndef FALSE
+#define FALSE (1==0)
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Please include header files for buffer type in the beginning of this file */
+typedef struct sk_buff zbuf_t;
+
+/* Please include header files for device type in the beginning of this file */
+typedef struct net_device zdev_t;
+
+#endif /* #ifndef _OAL_DT_H */
diff --git a/drivers/staging/otus/oal_marc.h b/drivers/staging/otus/oal_marc.h
new file mode 100644
index 000000000000..206111616a03
--- /dev/null
+++ b/drivers/staging/otus/oal_marc.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : oal_marc.h */
+/* */
+/* Abstract */
+/* This module contains warpper definitions. */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#ifndef _OAL_MARC_H
+#define _OAL_MARC_H
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#define ZM_OS_LINUX_FUNC
+
+/***** Critical section *****/
+/* Declare for critical section */
+#ifndef ZM_HALPLUS_LOCK
+#define zmw_get_wlan_dev(dev) struct zsWlanDev *wd = (struct zsWlanDev*) ((((struct usbdrv_private*)dev->priv)->wd))
+
+#define zmw_declare_for_critical_section() unsigned long irqFlag;
+
+/* Enter critical section */
+#define zmw_enter_critical_section(dev) \
+ spin_lock_irqsave(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag);
+
+/* leave critical section */
+#define zmw_leave_critical_section(dev) \
+ spin_unlock_irqrestore(&(((struct usbdrv_private *)(dev->priv))->cs_lock), irqFlag);
+#else
+#define zmw_get_wlan_dev(dev) struct zsWlanDev *wd = zfwGetWlanDev(dev);
+
+/* Declare for critical section */
+#define zmw_declare_for_critical_section()
+
+/* Enter critical section */
+#define zmw_enter_critical_section(dev) \
+ zfwEnterCriticalSection(dev);
+
+/* leave critical section */
+#define zmw_leave_critical_section(dev) \
+ zfwLeaveCriticalSection(dev);
+#endif
+
+/***** Byte order converting *****/
+#ifdef ZM_CONFIG_BIG_ENDIAN
+#define zmw_cpu_to_le32(v) (((v & 0xff000000) >> 24) | \
+ ((v & 0x00ff0000) >> 8) | \
+ ((v & 0x0000ff00) << 8) | \
+ ((v & 0x000000ff) << 24))
+
+#define zmw_le32_to_cpu(v) (((v & 0xff000000) >> 24) | \
+ ((v & 0x00ff0000) >> 8) | \
+ ((v & 0x0000ff00) << 8) | \
+ ((v & 0x000000ff) << 24))
+
+#define zmw_cpu_to_le16(v) (((v & 0xff00) >> 8) | \
+ ((v & 0x00ff) << 8))
+
+#define zmw_le16_to_cpu(v) (((v & 0xff00) >> 8) | \
+ ((v & 0x00ff) << 8))
+#else
+#define zmw_cpu_to_le32(v) (v)
+#define zmw_le32_to_cpu(v) (v)
+#define zmw_cpu_to_le16(v) (v)
+#define zmw_le16_to_cpu(v) (v)
+#endif
+
+/***** Buffer access *****/
+/* Called to read/write buffer */
+#ifndef ZM_HALPLUS_LOCK
+
+#define zmw_buf_readb(dev, buf, offset) *(u8_t*)((u8_t*)buf->data+offset)
+#define zmw_buf_readh(dev, buf, offset) zmw_cpu_to_le16(*(u16_t*)((u8_t*)buf->data+offset))
+#define zmw_buf_writeb(dev, buf, offset, value) *(u8_t*)((u8_t*)buf->data+offset) = value
+#define zmw_buf_writeh(dev, buf, offset, value) *(u16_t*)((u8_t*)buf->data+offset) = zmw_cpu_to_le16(value)
+#define zmw_buf_get_buffer(dev, buf) (u8_t*)(buf->data)
+
+#else
+
+#define zmw_buf_readb(dev, buf, offset) zfwBufReadByte(dev, buf, offset)
+#define zmw_buf_readh(dev, buf, offset) zfwBufReadHalfWord(dev, buf, offset)
+#define zmw_buf_writeb(dev, buf, offset, value) zfwBufWriteByte(dev, buf, offset, value)
+#define zmw_buf_writeh(dev, buf, offset, value) zfwBufWriteHalfWord(dev, buf, offset, value)
+#define zmw_buf_get_buffer(dev, buf) zfwGetBuffer(dev, buf)
+
+#endif
+
+/***** Debug message *****/
+#if 0
+#define zm_debug_msg0(msg) printk("%s:%s\n", __func__, msg);
+#define zm_debug_msg1(msg, val) printk("%s:%s%ld\n", __func__, \
+ msg, (u32_t)val);
+#define zm_debug_msg2(msg, val) printk("%s:%s%lxh\n", __func__, \
+ msg, (u32_t)val);
+#define zm_debug_msg_s(msg, val) printk("%s:%s%s\n", __func__, \
+ msg, val);
+#define zm_debug_msg_p(msg, val1, val2) printk("%s:%s%01ld.%02ld\n", __func__, \
+ msg, (val1/val2), (((val1*100)/val2)%100));
+#define zm_dbg(S) printk S
+#else
+#define zm_debug_msg0(msg)
+#define zm_debug_msg1(msg, val)
+#define zm_debug_msg2(msg, val)
+#define zm_debug_msg_s(msg, val)
+#define zm_debug_msg_p(msg, val1, val2)
+#define zm_dbg(S)
+#endif
+
+#define zm_assert(expr) if(!(expr)) { \
+ printk( "Atheors Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr,__FILE__,__func__,__LINE__); \
+ }
+
+#define DbgPrint printk
+
+#endif /* #ifndef _OAL_MARC_H */
diff --git a/drivers/staging/otus/usbdrv.c b/drivers/staging/otus/usbdrv.c
new file mode 100644
index 000000000000..dfe07072011f
--- /dev/null
+++ b/drivers/staging/otus/usbdrv.c
@@ -0,0 +1,1148 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : usbdrv.c */
+/* */
+/* Abstract */
+/* This module contains network interface up/down related functions.*/
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+/* src/usbdrv.c */
+
+#define ZM_PIBSS_MODE 0
+#define ZM_AP_MODE 0
+#define ZM_CHANNEL 11
+#define ZM_WEP_MOME 0
+#define ZM_SHARE_AUTH 0
+#define ZM_DISABLE_XMIT 0
+
+#include "usbdrv.h"
+#include "oal_dt.h"
+#include "80211core/pub_zfi.h"
+
+#include "linux/netlink.h"
+#include "linux/rtnetlink.h"
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+#ifdef ZM_HOSTAPD_SUPPORT
+#include "athr_common.h"
+#endif
+
+extern void zfDumpDescriptor(zdev_t* dev, u16_t type);
+//extern void zfiWlanQueryMacAddress(zdev_t* dev, u8_t* addr);
+
+// ISR handler
+irqreturn_t usbdrv_intr(int, void *, struct pt_regs *);
+
+// Network Device interface related function
+int usbdrv_open(struct net_device *);
+int usbdrv_close(struct net_device *);
+int usbdrv_change_mtu(struct net_device *, int);
+int usbdrv_set_mac(struct net_device *, void *);
+int usbdrv_xmit_frame(struct sk_buff *, struct net_device *);
+void usbdrv_set_multi(struct net_device *);
+struct net_device_stats *usbdrv_get_stats(struct net_device *);
+
+//wireless extension helper functions
+int usbdrv_ioctl_setessid(struct net_device *dev, struct iw_point *erq);
+int usbdrv_ioctl_getessid(struct net_device *dev, struct iw_point *erq);
+int usbdrv_ioctl_setrts(struct net_device *dev, struct iw_param *rrq);
+/* Wireless Extension Handler functions */
+int usbdrvwext_giwmode(struct net_device *dev, struct iw_request_info* info,
+ __u32 *mode, char *extra);
+int zfLnxPrivateIoctl(struct usbdrv_private *macp, struct zdap_ioctl *zdreq);
+
+void zfLnx10msTimer(struct net_device* dev);
+int zfUnregisterWdsDev(struct net_device* parentDev, u16_t wdsId);
+int zfRegisterWdsDev(struct net_device* parentDev, u16_t wdsId);
+int zfWdsOpen(struct net_device *dev);
+int zfWdsClose(struct net_device *dev);
+int zfLnxVapOpen(struct net_device *dev);
+int zfLnxVapClose(struct net_device *dev);
+int zfLnxVapXmitFrame(struct sk_buff *skb, struct net_device *dev);
+int zfLnxRegisterVapDev(struct net_device* parentDev, u16_t vapId);
+int usbdrv_wpa_ioctl(struct net_device *dev, struct athr_wlan_param *zdparm);
+extern u16_t zfLnxGetVapId(zdev_t* dev);
+extern u16_t zfLnxCheckTxBufferCnt(zdev_t *dev);
+extern UsbTxQ_t *zfLnxGetUsbTxBuffer(zdev_t *dev);
+
+extern u16_t zfLnxAuthNotify(zdev_t* dev, u16_t* macAddr);
+extern u16_t zfLnxAsocNotify(zdev_t* dev, u16_t* macAddr, u8_t* body, u16_t bodySize, u16_t port);
+extern u16_t zfLnxDisAsocNotify(zdev_t* dev, u8_t* macAddr, u16_t port);
+extern u16_t zfLnxApConnectNotify(zdev_t* dev, u8_t* macAddr, u16_t port);
+extern void zfLnxConnectNotify(zdev_t* dev, u16_t status, u16_t* bssid);
+extern void zfLnxScanNotify(zdev_t* dev, struct zsScanResult* result);
+extern void zfLnxStatisticsNotify(zdev_t* dev, struct zsStastics* result);
+extern void zfLnxMicFailureNotify(zdev_t* dev, u16_t* addr, u16_t status);
+extern void zfLnxApMicFailureNotify(zdev_t* dev, u8_t* addr, zbuf_t* buf);
+extern void zfLnxIbssPartnerNotify(zdev_t* dev, u16_t status, struct zsPartnerNotifyEvent *event);
+extern void zfLnxMacAddressNotify(zdev_t* dev, u8_t* addr);
+extern void zfLnxSendCompleteIndication(zdev_t* dev, zbuf_t* buf);
+extern void zfLnxRecvEth(zdev_t* dev, zbuf_t* buf, u16_t port);
+extern void zfLnxRestoreBufData(zdev_t* dev, zbuf_t* buf);
+#ifdef ZM_ENABLE_CENC
+extern u16_t zfLnxCencAsocNotify(zdev_t* dev, u16_t* macAddr, u8_t* body, u16_t bodySize, u16_t port);
+#endif //ZM_ENABLE_CENC
+extern void zfLnxWatchDogNotify(zdev_t* dev);
+extern void zfLnxRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo);
+extern u8_t zfLnxCreateThread(zdev_t *dev);
+
+/******************************************************************************
+* P U B L I C D A T A
+*******************************************************************************
+*/
+
+/* Definition of Wireless Extension */
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+//wireless extension helper functions
+extern int usbdrv_ioctl_setessid(struct net_device *dev, struct iw_point *erq);
+extern int usbdrv_ioctl_setrts(struct net_device *dev, struct iw_param *rrq);
+/* Wireless Extension Handler functions */
+extern int usbdrvwext_giwname(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrq, char *extra);
+extern int usbdrvwext_siwfreq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+extern int usbdrvwext_giwfreq(struct net_device *dev, struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+extern int usbdrvwext_siwmode(struct net_device *dev, struct iw_request_info *info,
+ union iwreq_data *wrq, char *extra);
+extern int usbdrvwext_giwmode(struct net_device *dev, struct iw_request_info *info,
+ __u32 *mode, char *extra);
+extern int usbdrvwext_siwsens(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *sens, char *extra);
+extern int usbdrvwext_giwsens(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *sens, char *extra);
+extern int usbdrvwext_giwrange(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+extern int usbdrvwext_siwap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *MacAddr, char *extra);
+extern int usbdrvwext_giwap(struct net_device *dev, struct iw_request_info *info,
+ struct sockaddr *MacAddr, char *extra);
+extern int usbdrvwext_iwaplist(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+extern int usbdrvwext_siwscan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+extern int usbdrvwext_giwscan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+extern int usbdrvwext_siwessid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *essid, char *extra);
+extern int usbdrvwext_giwessid(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *essid, char *extra);
+extern int usbdrvwext_siwnickn(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *nickname);
+extern int usbdrvwext_giwnickn(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *data, char *nickname);
+extern int usbdrvwext_siwrate(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frq, char *extra);
+extern int usbdrvwext_giwrate(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frq, char *extra);
+extern int usbdrvwext_siwrts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra);
+extern int usbdrvwext_giwrts(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rts, char *extra);
+extern int usbdrvwext_siwfrag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frag, char *extra);
+extern int usbdrvwext_giwfrag(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frag, char *extra);
+extern int usbdrvwext_siwtxpow(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra);
+extern int usbdrvwext_giwtxpow(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra);
+extern int usbdrvwext_siwretry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra);
+extern int usbdrvwext_giwretry(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *rrq, char *extra);
+extern int usbdrvwext_siwencode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *erq, char *key);
+extern int usbdrvwext_giwencode(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *erq, char *key);
+extern int usbdrvwext_siwpower(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frq, char *extra);
+extern int usbdrvwext_giwpower(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *frq, char *extra);
+extern int usbdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+struct iw_priv_args usbdrv_private_args[] = {
+// { SIOCIWFIRSTPRIV + 0x0, 0, 0, "list_bss" },
+// { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
+ { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_auth" }, /* 0 - open, 1 - shared key */
+ { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_CHAR | 12, "get_auth" },
+// { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble" }, /* 0 - long, 1 - short */
+// { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_CHAR | 6, "get_preamble" },
+// { SIOCIWFIRSTPRIV + 0x6, 0, 0, "cnt" },
+// { SIOCIWFIRSTPRIV + 0x7, 0, 0, "regs" },
+// { SIOCIWFIRSTPRIV + 0x8, 0, 0, "probe" },
+// { SIOCIWFIRSTPRIV + 0x9, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dbg_flag" },
+// { SIOCIWFIRSTPRIV + 0xA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "connect" },
+// { SIOCIWFIRSTPRIV + 0xB, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_mac_mode" },
+// { SIOCIWFIRSTPRIV + 0xC, 0, IW_PRIV_TYPE_CHAR | 12, "get_mac_mode" },
+};
+
+#if WIRELESS_EXT > 12
+static iw_handler usbdrvwext_handler[] = {
+ (iw_handler) NULL, /* SIOCSIWCOMMIT */
+ (iw_handler) usbdrvwext_giwname, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) usbdrvwext_siwfreq, /* SIOCSIWFREQ */
+ (iw_handler) usbdrvwext_giwfreq, /* SIOCGIWFREQ */
+ (iw_handler) usbdrvwext_siwmode, /* SIOCSIWMODE */
+ (iw_handler) usbdrvwext_giwmode, /* SIOCGIWMODE */
+ (iw_handler) usbdrvwext_siwsens, /* SIOCSIWSENS */
+ (iw_handler) usbdrvwext_giwsens, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* not used */ /* SIOCSIWRANGE */
+ (iw_handler) usbdrvwext_giwrange, /* SIOCGIWRANGE */
+ (iw_handler) NULL, /* not used */ /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* kernel code */ /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* not used */ /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* kernel code */ /* SIOCGIWSTATS */
+ (iw_handler) NULL, /* SIOCSIWSPY */
+ (iw_handler) NULL, /* SIOCGIWSPY */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) usbdrvwext_siwap, /* SIOCSIWAP */
+ (iw_handler) usbdrvwext_giwap, /* SIOCGIWAP */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) usbdrvwext_iwaplist, /* SIOCGIWAPLIST */
+#if WIRELESS_EXT > 13
+ (iw_handler) usbdrvwext_siwscan, /* SIOCSIWSCAN */
+ (iw_handler) usbdrvwext_giwscan, /* SIOCGIWSCAN */
+#else /* WIRELESS_EXT > 13 */
+ (iw_handler) NULL, /* null */ /* SIOCSIWSCAN */
+ (iw_handler) NULL, /* null */ /* SIOCGIWSCAN */
+#endif /* WIRELESS_EXT > 13 */
+ (iw_handler) usbdrvwext_siwessid, /* SIOCSIWESSID */
+ (iw_handler) usbdrvwext_giwessid, /* SIOCGIWESSID */
+
+ (iw_handler) usbdrvwext_siwnickn, /* SIOCSIWNICKN */
+ (iw_handler) usbdrvwext_giwnickn, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) usbdrvwext_siwrate, /* SIOCSIWRATE */
+ (iw_handler) usbdrvwext_giwrate, /* SIOCGIWRATE */
+ (iw_handler) usbdrvwext_siwrts, /* SIOCSIWRTS */
+ (iw_handler) usbdrvwext_giwrts, /* SIOCGIWRTS */
+ (iw_handler) usbdrvwext_siwfrag, /* SIOCSIWFRAG */
+ (iw_handler) usbdrvwext_giwfrag, /* SIOCGIWFRAG */
+ (iw_handler) usbdrvwext_siwtxpow, /* SIOCSIWTXPOW */
+ (iw_handler) usbdrvwext_giwtxpow, /* SIOCGIWTXPOW */
+ (iw_handler) usbdrvwext_siwretry, /* SIOCSIWRETRY */
+ (iw_handler) usbdrvwext_giwretry, /* SIOCGIWRETRY */
+ (iw_handler) usbdrvwext_siwencode, /* SIOCSIWENCODE */
+ (iw_handler) usbdrvwext_giwencode, /* SIOCGIWENCODE */
+ (iw_handler) usbdrvwext_siwpower, /* SIOCSIWPOWER */
+ (iw_handler) usbdrvwext_giwpower, /* SIOCGIWPOWER */
+};
+
+static const iw_handler usbdrv_private_handler[] =
+{
+ //(iw_handler) usbdrvwext_setparam, /* SIOCWFIRSTPRIV+0 */
+ //(iw_handler) usbdrvwext_getparam, /* SIOCWFIRSTPRIV+1 */
+ //(iw_handler) usbdrvwext_setkey, /* SIOCWFIRSTPRIV+2 */
+ //(iw_handler) usbdrvwext_setwmmparams, /* SIOCWFIRSTPRIV+3 */
+ //(iw_handler) usbdrvwext_delkey, /* SIOCWFIRSTPRIV+4 */
+ //(iw_handler) usbdrvwext_getwmmparams, /* SIOCWFIRSTPRIV+5 */
+ //(iw_handler) usbdrvwext_setmlme, /* SIOCWFIRSTPRIV+6 */
+ //(iw_handler) usbdrvwext_getchaninfo, /* SIOCWFIRSTPRIV+7 */
+ //(iw_handler) usbdrvwext_setoptie, /* SIOCWFIRSTPRIV+8 */
+ //(iw_handler) usbdrvwext_getoptie, /* SIOCWFIRSTPRIV+9 */
+ //(iw_handler) usbdrvwext_addmac, /* SIOCWFIRSTPRIV+10 */
+ //(iw_handler) usbdrvwext_getscanresults, /* SIOCWFIRSTPRIV+11 */
+ //(iw_handler) usbdrvwext_delmac, /* SIOCWFIRSTPRIV+12 */
+ //(iw_handler) usbdrvwext_getchanlist, /* SIOCWFIRSTPRIV+13 */
+ //(iw_handler) usbdrvwext_setchanlist, /* SIOCWFIRSTPRIV+14 */
+ //(iw_handler) NULL, /* SIOCWFIRSTPRIV+15 */
+ //(iw_handler) usbdrvwext_chanswitch, /* SIOCWFIRSTPRIV+16 */
+ //(iw_handler) usbdrvwext_setmode, /* SIOCWFIRSTPRIV+17 */
+ //(iw_handler) usbdrvwext_getmode, /* SIOCWFIRSTPRIV+18 */
+ NULL, /* SIOCIWFIRSTPRIV */
+};
+
+static struct iw_handler_def p80211wext_handler_def = {
+ .num_standard = sizeof(usbdrvwext_handler) / sizeof(iw_handler),
+ .num_private = sizeof(usbdrv_private_handler)/sizeof(iw_handler),
+ .num_private_args = sizeof(usbdrv_private_args)/sizeof(struct iw_priv_args),
+ .standard = usbdrvwext_handler,
+ .private = (iw_handler *) usbdrv_private_handler,
+ .private_args = (struct iw_priv_args *) usbdrv_private_args
+};
+#endif
+
+/* WDS */
+//struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER];
+//void zfInitWdsStruct(void);
+
+/* VAP */
+struct zsVapStruct vap[ZM_VAP_PORT_NUMBER];
+void zfLnxInitVapStruct(void);
+
+
+/**
+ * usbdrv_intr - interrupt handler
+ * @irq: the IRQ number
+ * @dev_inst: the net_device struct
+ * @regs: registers (unused)
+ *
+ * This routine is the ISR for the usbdrv board. It services
+ * the RX & TX queues & starts the RU if it has stopped due
+ * to no resources.
+ */
+irqreturn_t usbdrv_intr(int irq, void *dev_inst, struct pt_regs *regs)
+{
+ struct net_device *dev;
+ struct usbdrv_private *macp;
+
+ dev = dev_inst;
+ macp = dev->ml_priv;
+
+
+ /* Read register error, card may be unpluged */
+ if (0)//(intr_status == -1)
+ return IRQ_NONE;
+
+ /* the device is closed, don't continue or else bad things may happen. */
+ if (!netif_running(dev)) {
+ return IRQ_NONE;
+ }
+
+ if (macp->driver_isolated) {
+ return IRQ_NONE;
+ }
+
+#if (WLAN_HOSTIF == WLAN_PCI)
+ //zfiIsrPci(dev);
+#endif
+
+ return IRQ_HANDLED;
+}
+
+int usbdrv_open(struct net_device *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ int rc = 0;
+ u16_t size;
+ void* mem;
+ //unsigned char addr[6];
+ struct zsCbFuncTbl cbFuncTbl;
+
+ printk("Enter open()\n");
+
+//#ifndef CONFIG_SMP
+// read_lock(&(macp->isolate_lock));
+//#endif
+ if (macp->driver_isolated) {
+ rc = -EBUSY;
+ goto exit;
+ }
+
+ size = zfiGlobalDataSize(dev);
+ if ((mem = kmalloc(size, GFP_KERNEL)) == NULL)
+ {
+ rc = -EBUSY;
+ goto exit;
+ }
+ macp->wd = mem;
+
+ memset(&cbFuncTbl, 0, sizeof(struct zsCbFuncTbl));
+ cbFuncTbl.zfcbAuthNotify = zfLnxAuthNotify;
+ cbFuncTbl.zfcbAuthNotify = zfLnxAuthNotify;
+ cbFuncTbl.zfcbAsocNotify = zfLnxAsocNotify;
+ cbFuncTbl.zfcbDisAsocNotify = zfLnxDisAsocNotify;
+ cbFuncTbl.zfcbApConnectNotify = zfLnxApConnectNotify;
+ cbFuncTbl.zfcbConnectNotify = zfLnxConnectNotify;
+ cbFuncTbl.zfcbScanNotify = zfLnxScanNotify;
+ cbFuncTbl.zfcbMicFailureNotify = zfLnxMicFailureNotify;
+ cbFuncTbl.zfcbApMicFailureNotify = zfLnxApMicFailureNotify;
+ cbFuncTbl.zfcbIbssPartnerNotify = zfLnxIbssPartnerNotify;
+ cbFuncTbl.zfcbMacAddressNotify = zfLnxMacAddressNotify;
+ cbFuncTbl.zfcbSendCompleteIndication = zfLnxSendCompleteIndication;
+ cbFuncTbl.zfcbRecvEth = zfLnxRecvEth;
+ cbFuncTbl.zfcbRecv80211 = zfLnxRecv80211;
+ cbFuncTbl.zfcbRestoreBufData = zfLnxRestoreBufData;
+#ifdef ZM_ENABLE_CENC
+ cbFuncTbl.zfcbCencAsocNotify = zfLnxCencAsocNotify;
+#endif //ZM_ENABLE_CENC
+ cbFuncTbl.zfcbHwWatchDogNotify = zfLnxWatchDogNotify;
+ zfiWlanOpen(dev, &cbFuncTbl);
+
+#if 0
+ {
+ //u16_t mac[3] = {0x1300, 0xb6d4, 0x5aaf};
+ u16_t mac[3] = {0x8000, 0x00ab, 0x0000};
+ //zfiWlanSetMacAddress(dev, mac);
+ }
+ /* MAC address */
+ zfiWlanQueryMacAddress(dev, addr);
+ dev->dev_addr[0] = addr[0];
+ dev->dev_addr[1] = addr[1];
+ dev->dev_addr[2] = addr[2];
+ dev->dev_addr[3] = addr[3];
+ dev->dev_addr[4] = addr[4];
+ dev->dev_addr[5] = addr[5];
+#endif
+ //zfwMacAddressNotify() will be called to setup dev->dev_addr[]
+
+ zfLnxCreateThread(dev);
+
+ mod_timer(&(macp->hbTimer10ms), jiffies + (1*HZ)/100); //10 ms
+
+ netif_carrier_on(dev);
+
+ netif_start_queue(dev);
+
+#if ZM_AP_MODE == 1
+ zfiWlanSetWlanMode(dev, ZM_MODE_AP);
+ zfiWlanSetBasicRate(dev, 0xf, 0, 0);
+ zfiWlanSetSSID(dev, "OTUS_CWY", 8);
+ zfiWlanSetDtimCount(dev, 3);
+
+ #if ZM_WEP_MOME == 1
+ {
+ u8_t key[16] = {0x12, 0x34, 0x56, 0x78, 0x90};
+ struct zsKeyInfo keyInfo;
+
+ keyInfo.keyLength = 5;
+ keyInfo.keyIndex = 0;
+ keyInfo.flag = 0;
+ keyInfo.key = key;
+ zfiWlanSetKey(dev, keyInfo);
+
+ zfiWlanSetEncryMode(dev, ZM_WEP64);
+ }
+
+ #if ZM_SHARE_AUTH == 1
+ zfiWlanSetAuthenticationMode(dev, 1);
+ #endif //#if ZM_SHARE_AUTH == 1
+ #endif //#if ZM_WEP_MOME == 1
+
+#elif ZM_PIBSS_MODE == 1
+ zfiWlanSetWlanMode(dev, ZM_MODE_PSEUDO);
+#else
+ zfiWlanSetWlanMode(dev, ZM_MODE_INFRASTRUCTURE);
+#endif
+ //zfiWlanSetChannel(dev, ZM_CHANNEL, FALSE);
+ zfiWlanSetFrequency(dev, 2462000, FALSE);
+ zfiWlanSetRtsThreshold(dev, 32767);
+ zfiWlanSetFragThreshold(dev, 0);
+
+ zfiWlanEnable(dev);
+
+#ifdef ZM_ENABLE_CENC
+ macp->netlink_sk = netlink_kernel_create(NETLINK_USERSOCK, 1, NULL, THIS_MODULE);
+
+ if (macp->netlink_sk == NULL)
+ {
+ printk(KERN_ERR "Can't create NETLINK socket\n");
+ }
+#endif
+
+ macp->DeviceOpened = 1;
+exit:
+//#ifndef CONFIG_SMP
+// read_unlock(&(macp->isolate_lock));
+//#endif
+ //zfRegisterWdsDev(dev, 0);
+ //zfLnxRegisterVapDev(dev, 0);
+
+ return rc;
+}
+
+
+
+
+/**
+ * usbdrv_get_stats - get driver statistics
+ * @dev: adapter's net_device struct
+ *
+ * This routine is called when the OS wants the adapter's stats returned.
+ * It returns the address of the net_device_stats stucture for the device.
+ * If the statistics are currently being updated, then they might be incorrect
+ * for a short while. However, since this cannot actually cause damage, no
+ * locking is used.
+ */
+
+struct net_device_stats * usbdrv_get_stats(struct net_device *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ macp->drv_stats.net_stats.tx_errors =
+ macp->drv_stats.net_stats.tx_carrier_errors +
+ macp->drv_stats.net_stats.tx_aborted_errors;
+
+ macp->drv_stats.net_stats.rx_errors =
+ macp->drv_stats.net_stats.rx_crc_errors +
+ macp->drv_stats.net_stats.rx_frame_errors +
+ macp->drv_stats.net_stats.rx_length_errors;
+
+
+ return &(macp->drv_stats.net_stats);
+}
+
+
+/**
+ * usbdrv_set_mac - set the MAC address
+ * @dev: adapter's net_device struct
+ * @addr: the new address
+ *
+ * This routine sets the ethernet address of the board
+ * Returns:
+ * 0 - if successful
+ * -1 - otherwise
+ */
+
+int usbdrv_set_mac(struct net_device *dev, void *addr)
+{
+ struct usbdrv_private *macp;
+ int rc = -1;
+
+ macp = dev->ml_priv;
+ read_lock(&(macp->isolate_lock));
+
+ if (macp->driver_isolated) {
+ goto exit;
+ }
+
+ rc = 0;
+
+
+exit:
+ read_unlock(&(macp->isolate_lock));
+ return rc;
+}
+
+
+
+void
+usbdrv_isolate_driver(struct usbdrv_private *macp)
+{
+#ifndef CONFIG_SMP
+ write_lock_irq(&(macp->isolate_lock));
+#endif
+ macp->driver_isolated = TRUE;
+#ifndef CONFIG_SMP
+ write_unlock_irq(&(macp->isolate_lock));
+#endif
+
+ if (netif_running(macp->device))
+ {
+ netif_carrier_off(macp->device);
+ netif_stop_queue(macp->device);
+ }
+}
+
+#define VLAN_SIZE 4
+int usbdrv_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if ((new_mtu < 68) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE)))
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+void zfLnxUnlinkAllUrbs(struct usbdrv_private *macp);
+
+int usbdrv_close(struct net_device *dev)
+{
+extern void zfHpLedCtrl(struct net_device *dev, u16_t ledId, u8_t mode);
+
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ printk(KERN_DEBUG "usbdrv_close\n");
+
+ netif_carrier_off(macp->device);
+
+ del_timer_sync(&macp->hbTimer10ms);
+
+ printk(KERN_DEBUG "usbdrv_netif_carrier_off\n");
+
+ usbdrv_isolate_driver(macp);
+
+ printk(KERN_DEBUG "usbdrv_isolate_driver\n");
+
+ netif_carrier_off(macp->device);
+#ifdef ZM_ENABLE_CENC
+ /* CENC */
+ if (macp->netlink_sk != NULL)
+ {
+ // sock_release(macp->netlink_sk);
+ printk(KERN_ERR "usbdrv close netlink socket\n");
+ }
+#endif //ZM_ENABLE_CENC
+#if (WLAN_HOSTIF == WLAN_PCI)
+ //free_irq(dev->irq, dev);
+#endif
+
+ /* Turn off LED */
+ zfHpLedCtrl(dev, 0, 0);
+ zfHpLedCtrl(dev, 1, 0);
+
+ /* Delay for a while */
+ mdelay(10);
+
+ /* clear WPA/RSN IE */
+ macp->supIe[1] = 0;
+
+ /* set the isolate flag to false, so usbdrv_open can be called */
+ macp->driver_isolated = FALSE;
+
+ zfiWlanClose(dev);
+ kfree(macp->wd);
+
+ zfLnxUnlinkAllUrbs(macp);
+
+ return 0;
+}
+
+
+
+
+int usbdrv_xmit_frame(struct sk_buff *skb, struct net_device *dev)
+{
+ int notify_stop = FALSE;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+#if 0
+ /* Test code */
+ {
+ struct sk_buff* s;
+
+ s = skb_copy_expand(skb, 8, 0, GFP_ATOMIC);
+ skb_push(s, 8);
+ s->data[0] = 'z';
+ s->data[1] = 'y';
+ s->data[2] = 'd';
+ s->data[3] = 'a';
+ s->data[4] = 's';
+ printk("len1=%d, len2=%d", skb->len, s->len);
+ netlink_broadcast(rtnl, s, 0, RTMGRP_LINK, GFP_ATOMIC);
+ }
+#endif
+
+#if ZM_DISABLE_XMIT
+ dev_kfree_skb_irq(skb);
+#else
+ zfiTxSendEth(dev, skb, 0);
+#endif
+ macp->drv_stats.net_stats.tx_bytes += skb->len;
+ macp->drv_stats.net_stats.tx_packets++;
+
+ //dev_kfree_skb_irq(skb);
+
+ if (notify_stop) {
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+ }
+
+ return 0;
+}
+
+
+
+
+void usbdrv_set_multi(struct net_device *dev)
+{
+
+
+ if (!(dev->flags & IFF_UP))
+ return;
+
+ return;
+
+}
+
+
+
+/**
+ * usbdrv_clear_structs - free resources
+
+ * @dev: adapter's net_device struct
+ *
+ * Free all device specific structs, unmap i/o address, etc.
+ */
+void usbdrv_clear_structs(struct net_device *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+
+#if (WLAN_HOSTIF == WLAN_PCI)
+ iounmap(macp->regp);
+
+ pci_release_regions(macp->pdev);
+ pci_disable_device(macp->pdev);
+ pci_set_drvdata(macp->pdev, NULL);
+#endif
+
+ kfree(macp);
+
+ kfree(dev);
+
+}
+
+void usbdrv_remove1(struct pci_dev *pcid)
+{
+ struct net_device *dev;
+ struct usbdrv_private *macp;
+
+ if (!(dev = (struct net_device *) pci_get_drvdata(pcid)))
+ return;
+
+ macp = dev->ml_priv;
+ unregister_netdev(dev);
+
+ usbdrv_clear_structs(dev);
+}
+
+
+void zfLnx10msTimer(struct net_device* dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ mod_timer(&(macp->hbTimer10ms), jiffies + (1*HZ)/100); //10 ms
+ zfiHeartBeat(dev);
+ return;
+}
+
+void zfLnxInitVapStruct(void)
+{
+ u16_t i;
+
+ for (i=0; i<ZM_VAP_PORT_NUMBER; i++)
+ {
+ vap[i].dev = NULL;
+ vap[i].openFlag = 0;
+ }
+}
+
+int zfLnxVapOpen(struct net_device *dev)
+{
+ u16_t vapId;
+
+ vapId = zfLnxGetVapId(dev);
+
+ if (vap[vapId].openFlag == 0)
+ {
+ vap[vapId].openFlag = 1;
+ printk("zfLnxVapOpen : device name=%s, vap ID=%d\n", dev->name, vapId);
+ zfiWlanSetSSID(dev, "vap1", 4);
+ zfiWlanEnable(dev);
+ netif_start_queue(dev);
+ }
+ else
+ {
+ printk("VAP opened error : vap ID=%d\n", vapId);
+ }
+ return 0;
+}
+
+int zfLnxVapClose(struct net_device *dev)
+{
+ u16_t vapId;
+
+ vapId = zfLnxGetVapId(dev);
+
+ if (vapId != 0xffff)
+ {
+ if (vap[vapId].openFlag == 1)
+ {
+ printk("zfLnxVapClose: device name=%s, vap ID=%d\n", dev->name, vapId);
+
+ netif_stop_queue(dev);
+ vap[vapId].openFlag = 0;
+ }
+ else
+ {
+ printk("VAP port was not opened : vap ID=%d\n", vapId);
+ }
+ }
+ return 0;
+}
+
+int zfLnxVapXmitFrame(struct sk_buff *skb, struct net_device *dev)
+{
+ int notify_stop = FALSE;
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t vapId;
+
+ vapId = zfLnxGetVapId(dev);
+ //printk("zfLnxVapXmitFrame: vap ID=%d\n", vapId);
+ //printk("zfLnxVapXmitFrame(), skb=%lxh\n", (u32_t)skb);
+
+ if (vapId >= ZM_VAP_PORT_NUMBER)
+ {
+ dev_kfree_skb_irq(skb);
+ return 0;
+ }
+#if 1
+ if (vap[vapId].openFlag == 0)
+ {
+ dev_kfree_skb_irq(skb);
+ return 0;
+ }
+#endif
+
+
+ zfiTxSendEth(dev, skb, 0x1);
+
+ macp->drv_stats.net_stats.tx_bytes += skb->len;
+ macp->drv_stats.net_stats.tx_packets++;
+
+ //dev_kfree_skb_irq(skb);
+
+ if (notify_stop) {
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+ }
+
+ return 0;
+}
+
+int zfLnxRegisterVapDev(struct net_device* parentDev, u16_t vapId)
+{
+ /* Allocate net device structure */
+ vap[vapId].dev = alloc_etherdev(0);
+ printk("Register vap dev=%x\n", (u32_t)vap[vapId].dev);
+
+ if(vap[vapId].dev == NULL) {
+ printk("alloc_etherdev fail\n");
+ return -ENOMEM;
+ }
+
+ /* Setup the default settings */
+ ether_setup(vap[vapId].dev);
+
+ /* MAC address */
+ memcpy(vap[vapId].dev->dev_addr, parentDev->dev_addr, ETH_ALEN);
+
+ vap[vapId].dev->irq = parentDev->irq;
+ vap[vapId].dev->base_addr = parentDev->base_addr;
+ vap[vapId].dev->mem_start = parentDev->mem_start;
+ vap[vapId].dev->mem_end = parentDev->mem_end;
+ vap[vapId].dev->ml_priv = parentDev->ml_priv;
+
+ //dev->hard_start_xmit = &zd1212_wds_xmit_frame;
+ vap[vapId].dev->hard_start_xmit = &zfLnxVapXmitFrame;
+ vap[vapId].dev->open = &zfLnxVapOpen;
+ vap[vapId].dev->stop = &zfLnxVapClose;
+ vap[vapId].dev->get_stats = &usbdrv_get_stats;
+ vap[vapId].dev->change_mtu = &usbdrv_change_mtu;
+#ifdef ZM_HOSTAPD_SUPPORT
+ vap[vapId].dev->do_ioctl = usbdrv_ioctl;
+#else
+ vap[vapId].dev->do_ioctl = NULL;
+#endif
+ vap[vapId].dev->destructor = free_netdev;
+
+ vap[vapId].dev->tx_queue_len = 0;
+
+ vap[vapId].dev->dev_addr[0] = parentDev->dev_addr[0];
+ vap[vapId].dev->dev_addr[1] = parentDev->dev_addr[1];
+ vap[vapId].dev->dev_addr[2] = parentDev->dev_addr[2];
+ vap[vapId].dev->dev_addr[3] = parentDev->dev_addr[3];
+ vap[vapId].dev->dev_addr[4] = parentDev->dev_addr[4];
+ vap[vapId].dev->dev_addr[5] = parentDev->dev_addr[5] + (vapId+1);
+
+ /* Stop the network queue first */
+ netif_stop_queue(vap[vapId].dev);
+
+ sprintf(vap[vapId].dev->name, "vap%d", vapId);
+ printk("Register VAP dev success : %s\n", vap[vapId].dev->name);
+
+ if(register_netdevice(vap[vapId].dev) != 0) {
+ printk("register VAP device fail\n");
+ vap[vapId].dev = NULL;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int zfLnxUnregisterVapDev(struct net_device* parentDev, u16_t vapId)
+{
+ int ret = 0;
+
+ printk("Unregister VAP dev : %s\n", vap[vapId].dev->name);
+
+ if(vap[vapId].dev != NULL) {
+ printk("Unregister vap dev=%x\n", (u32_t)vap[vapId].dev);
+ //
+ //unregister_netdevice(wds[wdsId].dev);
+ unregister_netdev(vap[vapId].dev);
+
+ printk("VAP unregister_netdevice\n");
+ vap[vapId].dev = NULL;
+ }
+ else {
+ printk("unregister VAP device: %d fail\n", vapId);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+
+
+# define SUBMIT_URB(u,f) usb_submit_urb(u,f)
+# define USB_ALLOC_URB(u,f) usb_alloc_urb(u,f)
+
+//extern void zfiWlanQueryMacAddress(zdev_t* dev, u8_t* addr);
+
+extern int usbdrv_open(struct net_device *dev);
+extern int usbdrv_close(struct net_device *dev);
+extern int usbdrv_xmit_frame(struct sk_buff *skb, struct net_device *dev);
+extern int usbdrv_xmit_frame(struct sk_buff *skb, struct net_device *dev);
+extern int usbdrv_change_mtu(struct net_device *dev, int new_mtu);
+extern void usbdrv_set_multi(struct net_device *dev);
+extern int usbdrv_set_mac(struct net_device *dev, void *addr);
+extern struct net_device_stats * usbdrv_get_stats(struct net_device *dev);
+extern int usbdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+extern UsbTxQ_t *zfLnxGetUsbTxBuffer(struct net_device *dev);
+
+int zfLnxAllocAllUrbs(struct usbdrv_private *macp)
+{
+ struct usb_interface *interface = macp->interface;
+ struct usb_host_interface *iface_desc = &interface->altsetting[0];
+
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+
+ /* descriptor matches, let's find the endpoints needed */
+ /* check out the endpoints */
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
+ {
+ endpoint = &iface_desc->endpoint[i].desc;
+ if ((endpoint->bEndpointAddress & 0x80) &&
+ ((endpoint->bmAttributes & 3) == 0x02))
+ {
+ /* we found a bulk in endpoint */
+ printk(KERN_ERR "bulk in: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize));
+ }
+
+ if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+ ((endpoint->bmAttributes & 3) == 0x02))
+ {
+ /* we found a bulk out endpoint */
+ printk(KERN_ERR "bulk out: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize));
+ }
+
+ if ((endpoint->bEndpointAddress & 0x80) &&
+ ((endpoint->bmAttributes & 3) == 0x03))
+ {
+ /* we found a interrupt in endpoint */
+ printk(KERN_ERR "interrupt in: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize));
+ printk(KERN_ERR "interrupt in: int_interval = %d\n", endpoint->bInterval);
+ }
+
+ if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+ ((endpoint->bmAttributes & 3) == 0x03))
+ {
+ /* we found a interrupt out endpoint */
+ printk(KERN_ERR "interrupt out: wMaxPacketSize = %x\n", le16_to_cpu(endpoint->wMaxPacketSize));
+ printk(KERN_ERR "interrupt out: int_interval = %d\n", endpoint->bInterval);
+ }
+ }
+
+ /* Allocate all Tx URBs */
+ for (i = 0; i < ZM_MAX_TX_URB_NUM; i++)
+ {
+ macp->WlanTxDataUrb[i] = USB_ALLOC_URB(0, GFP_KERNEL);
+
+ if (macp->WlanTxDataUrb[i] == 0)
+ {
+ int j;
+
+ /* Free all urbs */
+ for (j = 0; j < i; j++)
+ {
+ usb_free_urb(macp->WlanTxDataUrb[j]);
+ }
+
+ return 0;
+ }
+ }
+
+ /* Allocate all Rx URBs */
+ for (i = 0; i < ZM_MAX_RX_URB_NUM; i++)
+ {
+ macp->WlanRxDataUrb[i] = USB_ALLOC_URB(0, GFP_KERNEL);
+
+ if (macp->WlanRxDataUrb[i] == 0)
+ {
+ int j;
+
+ /* Free all urbs */
+ for (j = 0; j < i; j++)
+ {
+ usb_free_urb(macp->WlanRxDataUrb[j]);
+ }
+
+ for (j = 0; j < ZM_MAX_TX_URB_NUM; j++)
+ {
+ usb_free_urb(macp->WlanTxDataUrb[j]);
+ }
+
+ return 0;
+ }
+ }
+
+ /* Allocate Register Read/Write USB */
+ macp->RegOutUrb = USB_ALLOC_URB(0, GFP_KERNEL);
+ macp->RegInUrb = USB_ALLOC_URB(0, GFP_KERNEL);
+
+ return 1;
+}
+
+void zfLnxFreeAllUrbs(struct usbdrv_private *macp)
+{
+ int i;
+
+ /* Free all Tx URBs */
+ for (i = 0; i < ZM_MAX_TX_URB_NUM; i++)
+ {
+ if (macp->WlanTxDataUrb[i] != NULL)
+ {
+ usb_free_urb(macp->WlanTxDataUrb[i]);
+ }
+ }
+
+ /* Free all Rx URBs */
+ for (i = 0; i < ZM_MAX_RX_URB_NUM; i++)
+ {
+ if (macp->WlanRxDataUrb[i] != NULL)
+ {
+ usb_free_urb(macp->WlanRxDataUrb[i]);
+ }
+ }
+
+ /* Free USB Register Read/Write URB */
+ usb_free_urb(macp->RegOutUrb);
+ usb_free_urb(macp->RegInUrb);
+}
+
+void zfLnxUnlinkAllUrbs(struct usbdrv_private *macp)
+{
+ int i;
+
+ /* Unlink all Tx URBs */
+ for (i = 0; i < ZM_MAX_TX_URB_NUM; i++)
+ {
+ if (macp->WlanTxDataUrb[i] != NULL)
+ {
+ usb_unlink_urb(macp->WlanTxDataUrb[i]);
+ }
+ }
+
+ /* Unlink all Rx URBs */
+ for (i = 0; i < ZM_MAX_RX_URB_NUM; i++)
+ {
+ if (macp->WlanRxDataUrb[i] != NULL)
+ {
+ usb_unlink_urb(macp->WlanRxDataUrb[i]);
+ }
+ }
+
+ /* Unlink USB Register Read/Write URB */
+ usb_unlink_urb(macp->RegOutUrb);
+
+ usb_unlink_urb(macp->RegInUrb);
+}
+
+u8_t zfLnxInitSetup(struct net_device *dev, struct usbdrv_private *macp)
+{
+ //unsigned char addr[6];
+
+ //init_MUTEX(&macp->ps_sem);
+ //init_MUTEX(&macp->reg_sem);
+ //init_MUTEX(&macp->bcn_sem);
+ //init_MUTEX(&macp->config_sem);
+
+ spin_lock_init(&(macp->cs_lock));
+#if 0
+ /* MAC address */
+ zfiWlanQueryMacAddress(dev, addr);
+ dev->dev_addr[0] = addr[0];
+ dev->dev_addr[1] = addr[1];
+ dev->dev_addr[2] = addr[2];
+ dev->dev_addr[3] = addr[3];
+ dev->dev_addr[4] = addr[4];
+ dev->dev_addr[5] = addr[5];
+#endif
+#if WIRELESS_EXT > 12
+ dev->wireless_handlers = (struct iw_handler_def *)&p80211wext_handler_def;
+#endif
+
+ dev->open = usbdrv_open;
+ dev->hard_start_xmit = usbdrv_xmit_frame;
+ dev->stop = usbdrv_close;
+ dev->change_mtu = &usbdrv_change_mtu;
+ dev->get_stats = usbdrv_get_stats;
+ dev->set_multicast_list = usbdrv_set_multi;
+ dev->set_mac_address = usbdrv_set_mac;
+ dev->do_ioctl = usbdrv_ioctl;
+
+ dev->flags |= IFF_MULTICAST;
+
+ dev->dev_addr[0] = 0x00;
+ dev->dev_addr[1] = 0x03;
+ dev->dev_addr[2] = 0x7f;
+ dev->dev_addr[3] = 0x11;
+ dev->dev_addr[4] = 0x22;
+ dev->dev_addr[5] = 0x33;
+
+ /* Initialize Heart Beat timer */
+ init_timer(&macp->hbTimer10ms);
+ macp->hbTimer10ms.data = (unsigned long)dev;
+ macp->hbTimer10ms.function = (void *)&zfLnx10msTimer;
+
+ /* Initialize WDS and VAP data structure */
+ //zfInitWdsStruct();
+ zfLnxInitVapStruct();
+
+ return 1;
+}
+
+u8_t zfLnxClearStructs(struct net_device *dev)
+{
+ u16_t ii;
+ u16_t TxQCnt;
+
+ TxQCnt = zfLnxCheckTxBufferCnt(dev);
+
+ printk(KERN_ERR "TxQCnt: %d\n", TxQCnt);
+
+ for(ii = 0; ii < TxQCnt; ii++)
+ {
+ UsbTxQ_t *TxQ = zfLnxGetUsbTxBuffer(dev);
+
+ printk(KERN_ERR "dev_kfree_skb_any\n");
+ /* Free buffer */
+ dev_kfree_skb_any(TxQ->buf);
+ }
+
+ return 0;
+}
diff --git a/drivers/staging/otus/usbdrv.h b/drivers/staging/otus/usbdrv.h
new file mode 100644
index 000000000000..a11b3b36a906
--- /dev/null
+++ b/drivers/staging/otus/usbdrv.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : usbdrv.h */
+/* */
+/* Abstract */
+/* This module contains network interface up/down related definition*/
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#ifndef _USBDRV_H
+#define _USBDRV_H
+
+#define WLAN_USB 0
+#define WLAN_PCI 1
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/uaccess.h>
+#include <linux/wireless.h>
+#include <linux/if_arp.h>
+#include <linux/io.h>
+
+#include "zdcompat.h"
+
+#include "oal_dt.h"
+#include "oal_marc.h"
+#include "80211core/pub_zfi.h"
+//#include "pub_zfw.h"
+#include "80211core/pub_usb.h"
+
+#include <linux/usb.h>
+/* Please include header files for device type in the beginning of this file */
+#define urb_t struct urb
+
+#define usb_complete_t usb_complete_t
+#define pipe_t u32_t
+
+/* USB Endpoint definition */
+#define USB_WLAN_TX_PIPE 1
+#define USB_WLAN_RX_PIPE 2
+#define USB_REG_IN_PIPE 3
+#define USB_REG_OUT_PIPE 4
+
+#if (WLAN_HOSTIF == WLAN_USB)
+#include <linux/usb.h>
+#endif
+
+#ifdef ZM_HOSTAPD_SUPPORT
+#include "athr_common.h"
+#endif
+
+/**************************************************************************
+** Descriptor Data Structure
+***************************************************************************/
+struct driver_stats {
+ struct net_device_stats net_stats;
+};
+
+#define ZM_MAX_RX_BUFFER_SIZE 8192
+
+#if ZM_USB_TX_STREAM_MODE == 1
+#define ZM_MAX_TX_AGGREGATE_NUM 4
+#define ZM_USB_TX_BUF_SIZE 8096
+#define ZM_MAX_TX_URB_NUM 4
+#else
+#define ZM_USB_TX_BUF_SIZE 2048
+#define ZM_MAX_TX_URB_NUM 8
+#endif
+#define ZM_USB_REG_MAX_BUF_SIZE 64
+#define ZM_MAX_RX_URB_NUM 16
+#define ZM_MAX_TX_BUF_NUM 128
+
+typedef struct UsbTxQ
+{
+ zbuf_t *buf;
+ u8_t hdr[80];
+ u16_t hdrlen;
+ u8_t snap[8];
+ u16_t snapLen;
+ u8_t tail[16];
+ u16_t tailLen;
+ u16_t offset;
+} UsbTxQ_t;
+
+
+struct zdap_ioctl {
+ u16_t cmd; /* Command to run */
+ u32_t addr; /* Length of the data buffer */
+ u32_t value; /* Pointer to the data buffer */
+ u8_t data[0x100];
+};
+
+#define ZM_OAL_MAX_STA_SUPPORT 16
+
+struct usbdrv_private
+{
+ //linux used
+ struct net_device *device;
+#if (WLAN_HOSTIF == WLAN_PCI)
+ struct pci_dev *pdev;
+#endif
+#if (WLAN_HOSTIF == WLAN_USB)
+ struct usb_device *udev;
+ struct usb_interface *interface;
+#endif
+ struct driver_stats drv_stats;
+ char ifname[IFNAMSIZ];
+ int using_dac;
+ u8_t rev_id; /* adapter PCI revision ID */
+ rwlock_t isolate_lock;
+ spinlock_t cs_lock;
+ int driver_isolated;
+#if (WLAN_HOSTIF == WLAN_PCI)
+ void *regp;
+#endif
+
+ /* timer for heart beat */
+ struct timer_list hbTimer10ms;
+
+ /* For driver core */
+ void* wd;
+
+#if (WLAN_HOSTIF == WLAN_USB)
+ u8_t txUsbBuf[ZM_MAX_TX_URB_NUM][ZM_USB_TX_BUF_SIZE];
+ u8_t regUsbReadBuf[ZM_USB_REG_MAX_BUF_SIZE];
+ u8_t regUsbWriteBuf[ZM_USB_REG_MAX_BUF_SIZE];
+ urb_t *WlanTxDataUrb[ZM_MAX_TX_URB_NUM];
+ urb_t *WlanRxDataUrb[ZM_MAX_RX_URB_NUM];
+ urb_t *RegOutUrb;
+ urb_t *RegInUrb;
+ UsbTxQ_t UsbTxBufQ[ZM_MAX_TX_BUF_NUM];
+ zbuf_t *UsbRxBufQ[ZM_MAX_RX_URB_NUM];
+ u16_t TxBufHead;
+ u16_t TxBufTail;
+ u16_t TxBufCnt;
+ u16_t TxUrbHead;
+ u16_t TxUrbTail;
+ u16_t TxUrbCnt;
+ u16_t RxBufHead;
+ u16_t RxBufTail;
+ u16_t RxBufCnt;
+#endif
+
+#if ZM_USB_STREAM_MODE == 1
+ zbuf_t *reamin_buf;
+#endif
+
+#ifdef ZM_HOSTAPD_SUPPORT
+ struct athr_wlan_param athr_wpa_req;
+#endif
+ struct sock *netlink_sk;
+ u8_t DeviceOpened; //CWYang(+)
+ u8_t supIe[50];
+ u8_t supLen;
+ struct ieee80211req_wpaie stawpaie[ZM_OAL_MAX_STA_SUPPORT];
+ u8_t forwardMgmt;
+
+ struct zfCbUsbFuncTbl usbCbFunctions;
+
+ /* For keventd */
+ u32_t flags;
+ unsigned long kevent_flags;
+ u16_t kevent_ready;
+
+ struct semaphore ioctl_sem;
+ struct work_struct kevent;
+ wait_queue_head_t wait_queue_event;
+#ifdef ZM_HALPLUS_LOCK
+ unsigned long hal_irqFlag;
+#endif
+ u16_t adapterState;
+};
+
+/* WDS */
+#define ZM_WDS_PORT_NUMBER 6
+
+struct zsWdsStruct
+{
+ struct net_device* dev;
+ u16_t openFlag;
+};
+
+/* VAP */
+#define ZM_VAP_PORT_NUMBER 7
+
+struct zsVapStruct
+{
+ struct net_device* dev;
+ u16_t openFlag;
+};
+
+/***************************************/
+
+#define ZM_IOCTL_REG_READ 0x01
+#define ZM_IOCTL_REG_WRITE 0x02
+#define ZM_IOCTL_MEM_DUMP 0x03
+#define ZM_IOCTL_REG_DUMP 0x05
+#define ZM_IOCTL_TXD_DUMP 0x06
+#define ZM_IOCTL_RXD_DUMP 0x07
+#define ZM_IOCTL_MEM_READ 0x0B
+#define ZM_IOCTL_MEM_WRITE 0x0C
+#define ZM_IOCTL_DMA_TEST 0x10
+#define ZM_IOCTL_REG_TEST 0x11
+#define ZM_IOCTL_TEST 0x80
+#define ZM_IOCTL_TALLY 0x81 //CWYang(+)
+#define ZM_IOCTL_RTS 0xA0
+#define ZM_IOCTL_MIX_MODE 0xA1
+#define ZM_IOCTL_FRAG 0xA2
+#define ZM_IOCTL_SCAN 0xA3
+#define ZM_IOCTL_KEY 0xA4
+#define ZM_IOCTL_RATE 0xA5
+#define ZM_IOCTL_ENCRYPTION_MODE 0xA6
+#define ZM_IOCTL_GET_TXCNT 0xA7
+#define ZM_IOCTL_GET_DEAGG_CNT 0xA8
+#define ZM_IOCTL_DURATION_MODE 0xA9
+#define ZM_IOCTL_SET_AES_KEY 0xAA
+#define ZM_IOCTL_SET_AES_MODE 0xAB
+#define ZM_IOCTL_SIGNAL_STRENGTH 0xAC //CWYang(+)
+#define ZM_IOCTL_SIGNAL_QUALITY 0xAD //CWYang(+)
+#define ZM_IOCTL_SET_PIBSS_MODE 0xAE
+
+#define ZDAPIOCTL SIOCDEVPRIVATE
+
+enum devState {
+ Opened,
+ Enabled,
+ Disabled,
+ Closed
+};
+
+#endif /* _USBDRV_H */
+
diff --git a/drivers/staging/otus/wrap_buf.c b/drivers/staging/otus/wrap_buf.c
new file mode 100644
index 000000000000..62496a0f8e3f
--- /dev/null
+++ b/drivers/staging/otus/wrap_buf.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : wrap_buf.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for buffer management */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+
+
+/* Called to allocate buffer, must return a continue buffer space */
+zbuf_t* zfwBufAllocate(zdev_t* dev, u16_t len)
+{
+ zbuf_t* buf;
+
+ /* Allocate SKB for packet*/
+ buf = dev_alloc_skb(len);
+
+ return buf;
+}
+
+
+/* Called to free buffer, replace below 3 functions */
+void zfwBufFree(zdev_t* dev, zbuf_t* buf, u16_t status)
+{
+ dev_kfree_skb_any(buf);
+}
+
+/* Called to adjust buffer size and head pointer */
+u16_t zfwBufRemoveHead(zdev_t* dev, zbuf_t* buf, u16_t size)
+{
+ //zm_assert(buf->len > size);
+
+ buf->data += size;
+ buf->len -= size;
+ return 0;
+}
+
+
+
+
+/* return tail if head==NULL, called to chain multiple buffer together */
+/* Used to chain Rx buffer to form a frame. if the prepared Rx buffer */
+/* is greater than an ethernet frame(1518+32 byte), then this function */
+/* will only be called with head=NULL. */
+u16_t zfwBufChain(zdev_t* dev, zbuf_t** head, zbuf_t* tail)
+{
+
+ *head = tail;
+ return 0;
+}
+
+
+/* Called when doing infra-bss forwarding */
+u16_t zfwBufCopy(zdev_t* dev, zbuf_t* dst, zbuf_t* src)
+{
+ memcpy(dst->data, src->data, src->len);
+ dst->tail = dst->data;
+ skb_put(dst, src->len);
+ return 0;
+}
+
+
+/* Called to adjust buffer size and tail pointer */
+u16_t zfwBufSetSize(zdev_t* dev, zbuf_t* buf, u16_t size)
+{
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+ buf->tail = 0;
+ buf->len = 0;
+#else
+ buf->tail = buf->data;
+ buf->len = 0;
+#endif
+
+ skb_put(buf, size);
+ return 0;
+}
+
+u16_t zfwBufGetSize(zdev_t* dev, zbuf_t* buf)
+{
+ return buf->len;
+}
+
+void zfwCopyBufContext(zdev_t* dev, zbuf_t* source, zbuf_t* dst)
+{
+}
diff --git a/drivers/staging/otus/wrap_dbg.c b/drivers/staging/otus/wrap_dbg.c
new file mode 100644
index 000000000000..53763d9d2d85
--- /dev/null
+++ b/drivers/staging/otus/wrap_dbg.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : wrap_dbg.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for debug functions */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+void zfwDumpBuf(zdev_t* dev, zbuf_t* buf)
+{
+ u16_t i;
+
+ for (i=0; i<buf->len; i++)
+ {
+ printk("%02x ", *(((u8_t*)buf->data)+i));
+ if ((i&0xf)==0xf)
+ {
+ printk("\n");
+ }
+ }
+ printk("\n");
+}
+
+
+void zfwDbgReadRegDone(zdev_t* dev, u32_t addr, u32_t val)
+{
+ printk("Read addr:%x = %x\n", addr, val);
+}
+
+void zfwDbgWriteRegDone(zdev_t* dev, u32_t addr, u32_t val)
+{
+ printk("Write addr:%x = %x\n", addr, val);
+}
+
+void zfwDbgReadTallyDone(zdev_t* dev)
+{
+ //printk("Read Tall Done\n");
+}
+
+void zfwDbgWriteEepromDone(zdev_t* dev, u32_t addr, u32_t val)
+{
+}
+
+void zfwDbgQueryHwTxBusyDone(zdev_t* dev, u32_t val)
+{
+}
+
+//For Evl ++
+void zfwDbgReadFlashDone(zdev_t* dev, u32_t addr, u32_t* rspdata, u32_t datalen)
+{
+ printk("Read Flash addr:%x length:%x\n", addr, datalen);
+}
+
+void zfwDbgProgrameFlashDone(zdev_t* dev)
+{
+ printk("Program Flash Done\n");
+}
+
+void zfwDbgProgrameFlashChkDone(zdev_t* dev)
+{
+ printk("Program Flash Done\n");
+}
+
+void zfwDbgGetFlashChkSumDone(zdev_t* dev, u32_t* rspdata)
+{
+ printk("Get Flash ChkSum Done\n");
+}
+
+void zfwDbgDownloadFwInitDone(zdev_t* dev)
+{
+ printk("Download FW Init Done\n");
+}
+//For Evl --
+
+/* Leave an empty line below to remove warning message on some compiler */
diff --git a/drivers/staging/otus/wrap_ev.c b/drivers/staging/otus/wrap_ev.c
new file mode 100644
index 000000000000..966b787eef62
--- /dev/null
+++ b/drivers/staging/otus/wrap_ev.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : wrap_ev.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for events */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+
+/***** Management *****/
+u16_t zfLnxAuthNotify(zdev_t* dev, u16_t* macAddr)
+{
+ return 0;
+}
+
+u16_t zfLnxAsocNotify(zdev_t* dev, u16_t* macAddr, u8_t* body, u16_t bodySize, u16_t port)
+{
+//#ifdef ZM_HOSTAPD_SUPPORT
+ struct usbdrv_private *macp = dev->ml_priv;
+ union iwreq_data wreq;
+ u8_t *addr = (u8_t *) macAddr;
+ u16_t i, j;
+
+ memset(&wreq, 0, sizeof(wreq));
+ memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN);
+ wreq.addr.sa_family = ARPHRD_ETHER;
+ printk(KERN_DEBUG "join_event of MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ for(i = 0; i < ZM_OAL_MAX_STA_SUPPORT; i++)
+ {
+ for(j = 0; j < IEEE80211_ADDR_LEN; j++)
+ {
+ if ((macp->stawpaie[i].wpa_macaddr[j] != 0) &&
+ (macp->stawpaie[i].wpa_macaddr[j] != addr[j]))
+ break;
+ }
+ if (j == 6)
+ break;
+ }
+ if (i < ZM_OAL_MAX_STA_SUPPORT)
+ {
+ //printk("zfwAsocNotify - store wpa ie in macp, index = %d\n", i);
+ memcpy(macp->stawpaie[i].wpa_macaddr, macAddr, IEEE80211_ADDR_LEN);
+ memcpy(macp->stawpaie[i].wpa_ie, body, bodySize);
+ }
+ //if(macp->cardSetting.BssType == INFRASTRUCTURE_BSS) {
+ // //wireless_send_event(macp->device, SIOCGIWSCAN, &wreq, NULL);
+ // wireless_send_event(macp->device, SIOCGIWAP, &wreq, NULL);
+ //}
+#if WIRELESS_EXT >= 15
+ //else if(macp->cardSetting.BssType == AP_BSS) {
+// if (port == 0)
+// {
+ wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
+// }
+// else
+// {
+// /* Check whether the VAP device is valid */
+// if (vap[port].dev != NULL)
+// {
+// wireless_send_event(vap[port].dev, IWEVREGISTERED, &wreq, NULL);
+// }
+// else
+// {
+// printk(KERN_ERR "Can' find a valid VAP device, port: %d\n", port);
+// }
+// }
+ //}
+#endif
+//#endif
+
+ return 0;
+}
+
+
+/* Notification that a STA is disassociated from AP */
+/* AP mode only */
+u16_t zfLnxDisAsocNotify(zdev_t* dev, u8_t* macAddr, u16_t port)
+{
+ union iwreq_data wreq;
+ u8_t *addr = (u8_t *) macAddr;
+
+ memset(&wreq, 0, sizeof(wreq));
+ memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN);
+ wreq.addr.sa_family = ARPHRD_ETHER;
+ printk(KERN_DEBUG "zfwDisAsocNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+
+ return 0;
+}
+
+/* Notification that a STA is connect to AP */
+/* AP mode only */
+u16_t zfLnxApConnectNotify(zdev_t* dev, u8_t* macAddr, u16_t port)
+{
+ union iwreq_data wreq;
+ u8_t *addr = (u8_t *) macAddr;
+
+ memset(&wreq, 0, sizeof(wreq));
+ memcpy(wreq.addr.sa_data, macAddr, ETH_ALEN);
+ wreq.addr.sa_family = ARPHRD_ETHER;
+ printk(KERN_DEBUG "zfwApConnectNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+
+ return 0;
+}
+
+
+
+void zfLnxConnectNotify(zdev_t* dev, u16_t status, u16_t* bssid)
+{
+ union iwreq_data wreq;
+ u8_t *addr = (u8_t *) bssid;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if (bssid != NULL)
+ {
+ memset(&wreq, 0, sizeof(wreq));
+ if (status == ZM_STATUS_MEDIA_CONNECT)
+ memcpy(wreq.addr.sa_data, bssid, ETH_ALEN);
+ wreq.addr.sa_family = ARPHRD_ETHER;
+
+ if (status == ZM_STATUS_MEDIA_CONNECT)
+ {
+#ifdef ZM_CONFIG_BIG_ENDIAN
+ printk(KERN_DEBUG "Connected to AP, MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[1], addr[0], addr[3], addr[2], addr[5], addr[4]);
+#else
+ printk(KERN_DEBUG "Connected to AP, MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+#endif
+
+ netif_start_queue(dev);
+ }
+ else if ((status == ZM_STATUS_MEDIA_DISCONNECT) ||
+ (status == ZM_STATUS_MEDIA_DISABLED) ||
+ (status == ZM_STATUS_MEDIA_CONNECTION_DISABLED) ||
+ (status == ZM_STATUS_MEDIA_CONNECTION_RESET) ||
+ (status == ZM_STATUS_MEDIA_RESET) ||
+ (status == ZM_STATUS_MEDIA_DISCONNECT_DEAUTH) ||
+ (status == ZM_STATUS_MEDIA_DISCONNECT_DISASOC) ||
+ (status == ZM_STATUS_MEDIA_DISCONNECT_BEACON_MISS) ||
+ (status == ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND) ||
+ (status == ZM_STATUS_MEDIA_DISCONNECT_TIMEOUT))
+ {
+ printk(KERN_DEBUG "Disconnection Notify\n");
+
+ netif_stop_queue(dev);
+ }
+
+ /* Save the connected status */
+ macp->adapterState = status;
+
+ if(zfiWlanQueryWlanMode(dev) == ZM_MODE_INFRASTRUCTURE) {
+ // //wireless_send_event(dev, SIOCGIWSCAN, &wreq, NULL);
+ wireless_send_event(dev, SIOCGIWAP, &wreq, NULL);
+ }
+#if WIRELESS_EXT >= 15
+ else if(zfiWlanQueryWlanMode(dev) == ZM_MODE_AP) {
+ //if (port == 0)
+ //{
+ wireless_send_event(dev, IWEVREGISTERED, &wreq, NULL);
+ //}
+ //else
+ //{
+ // /* Check whether the VAP device is valid */
+ // if (vap[port].dev != NULL)
+ // {
+ // wireless_send_event(vap[port].dev, IWEVREGISTERED, &wreq, NULL);
+ // }
+ // else
+ // {
+ // printk(KERN_ERR "Can' find a valid VAP device, port: %d\n", port);
+ // }
+ //}
+ }
+#endif
+ }
+ //return 0;
+}
+
+void zfLnxScanNotify(zdev_t* dev, struct zsScanResult* result)
+{
+ return;
+}
+
+void zfLnxStatisticsNotify(zdev_t* dev, struct zsStastics* result)
+{
+ return;
+}
+
+//void zfwMicFailureNotify(zdev_t* dev, u8_t* message, u16_t event)
+void zfLnxMicFailureNotify(zdev_t* dev, u16_t* addr, u16_t status)
+{
+ static const char *tag = "MLME-MICHAELMICFAILURE.indication";
+ union iwreq_data wrqu;
+ char buf[128];
+
+ /* TODO: needed parameters: count, type, src address */
+ //snprintf(buf, sizeof(buf), "%s(%scast addr=%s)", tag,
+ // (status == ZM_MIC_GROUP_ERROR) ? "broad" : "uni",
+ // ether_sprintf((u8_t *)addr));
+
+ if (zfiWlanQueryWlanMode(dev) == ZM_MODE_INFRASTRUCTURE)
+ {
+ strcpy(buf, tag);
+ }
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = strlen(buf);
+ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
+}
+
+
+void zfLnxApMicFailureNotify(zdev_t* dev, u8_t* addr, zbuf_t* buf)
+{
+ union iwreq_data wreq;
+
+ memset(&wreq, 0, sizeof(wreq));
+ memcpy(wreq.addr.sa_data, addr, ETH_ALEN);
+ wreq.addr.sa_family = ARPHRD_ETHER;
+ printk(KERN_DEBUG "zfwApMicFailureNotify(), MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ return;
+}
+
+// status = 0 => partner lost
+// = 1 => partner alive
+//void zfwIbssPartnerNotify(zdev_t* dev, u8_t status)
+void zfLnxIbssPartnerNotify(zdev_t* dev, u16_t status, struct zsPartnerNotifyEvent *event)
+{
+}
+
+void zfLnxMacAddressNotify(zdev_t* dev, u8_t* addr)
+{
+ dev->dev_addr[0] = addr[0];
+ dev->dev_addr[1] = addr[1];
+ dev->dev_addr[2] = addr[2];
+ dev->dev_addr[3] = addr[3];
+ dev->dev_addr[4] = addr[4];
+ dev->dev_addr[5] = addr[5];
+}
+
+void zfLnxSendCompleteIndication(zdev_t* dev, zbuf_t* buf)
+{
+}
+
+
+void zfLnxRestoreBufData(zdev_t* dev, zbuf_t* buf) {
+
+}
+/* Leave an empty line below to remove warning message on some compiler */
diff --git a/drivers/staging/otus/wrap_mem.c b/drivers/staging/otus/wrap_mem.c
new file mode 100644
index 000000000000..8081bb2f8878
--- /dev/null
+++ b/drivers/staging/otus/wrap_mem.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : wrap_mem.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for memory management */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+/* Memory management */
+/* Called to allocate uncached memory, allocated memory must */
+/* in 4-byte boundary */
+void* zfwMemAllocate(zdev_t* dev, u32_t size)
+{
+ void* mem = NULL;
+ mem = kmalloc(size, GFP_ATOMIC);
+ return mem;
+}
+
+
+/* Called to free allocated memory */
+void zfwMemFree(zdev_t* dev, void* mem, u32_t size)
+{
+ kfree(mem);
+ return;
+}
+
+void zfwMemoryCopy(u8_t* dst, u8_t* src, u16_t length)
+{
+ //u16_t i;
+
+ memcpy(dst, src, length);
+ //for(i=0; i<length; i++)
+ //{
+ // dst[i] = src[i];
+ //}
+ return;
+}
+
+void zfwZeroMemory(u8_t* va, u16_t length)
+{
+ //u16_t i;
+ memset(va, 0, length);
+ //for(i=0; i<length; i++)
+ //{
+ // va[i] = 0;
+ //}
+ return;
+}
+
+void zfwMemoryMove(u8_t* dst, u8_t* src, u16_t length)
+{
+ memcpy(dst, src, length);
+ return;
+}
+
+u8_t zfwMemoryIsEqual(u8_t* m1, u8_t* m2, u16_t length)
+{
+ //u16_t i;
+ int ret;
+
+ ret = memcmp(m1, m2, length);
+
+ return ((ret==0)?TRUE:FALSE);
+ //for(i=0; i<length; i++)
+ //{
+ // if ( m1[i] != m2[i] )
+ // {
+ // return FALSE;
+ // }
+ //}
+
+ //return TRUE;
+}
+
+/* Leave an empty line below to remove warning message on some compiler */
diff --git a/drivers/staging/otus/wrap_mis.c b/drivers/staging/otus/wrap_mis.c
new file mode 100644
index 000000000000..337918b9de9a
--- /dev/null
+++ b/drivers/staging/otus/wrap_mis.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : wrap_mis.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for misc functions */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+//extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER];
+extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER];
+extern u16_t zfLnxGetVapId(zdev_t* dev);
+
+/* Simply return 0xffff if VAP function is not supported */
+u16_t zfwGetVapId(zdev_t* dev)
+{
+ return zfLnxGetVapId(dev);
+}
+
+void zfwSleep(zdev_t* dev, u32_t ms)
+{
+ if (in_interrupt() == 0)
+ {
+ mdelay(ms);
+ }
+ else
+ {
+ int ii;
+ int iter = 100000 * ms;
+
+ for (ii = 0; ii < iter; ii++)
+ {
+
+ }
+ }
+}
+
+#ifdef ZM_HALPLUS_LOCK
+asmlinkage struct zsWlanDev *zfwGetWlanDev(zdev_t* dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ return macp->wd;
+}
+
+asmlinkage void zfwEnterCriticalSection(zdev_t* dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ spin_lock_irqsave(&macp->cs_lock, macp->hal_irqFlag);
+}
+
+asmlinkage void zfwLeaveCriticalSection(zdev_t* dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ spin_unlock_irqrestore(&macp->cs_lock, macp->hal_irqFlag);
+}
+
+asmlinkage u8_t zfwBufReadByte(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ return *(u8_t*)((u8_t*)buf->data+offset);
+}
+
+asmlinkage u16_t zfwBufReadHalfWord(zdev_t* dev, zbuf_t* buf, u16_t offset)
+{
+ return zmw_cpu_to_le16(*(u16_t*)((u8_t*)buf->data+offset));
+}
+
+asmlinkage void zfwBufWriteByte(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t value)
+{
+ *(u8_t*)((u8_t*)buf->data+offset) = value;
+}
+
+asmlinkage void zfwBufWriteHalfWord(zdev_t* dev, zbuf_t* buf, u16_t offset, u16_t value)
+{
+ *(u16_t*)((u8_t*)buf->data+offset) = zmw_cpu_to_le16(value);
+}
+
+asmlinkage u8_t *zfwGetBuffer(zdev_t* dev, zbuf_t* buf)
+{
+ return (u8_t*)(buf->data);
+}
+#endif
+
+/* Leave an empty line below to remove warning message on some compiler */
diff --git a/drivers/staging/otus/wrap_pkt.c b/drivers/staging/otus/wrap_pkt.c
new file mode 100644
index 000000000000..5db0004c8739
--- /dev/null
+++ b/drivers/staging/otus/wrap_pkt.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : wrap_pkt.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for packet handling */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+
+
+//extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER];
+extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER];
+
+
+/***** Rx *****/
+void zfLnxRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo)
+{
+ u16_t frameType;
+ u16_t frameCtrl;
+ u16_t frameSubtype;
+ zbuf_t *skb1;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ //frameCtrl = zmw_buf_readb(dev, buf, 0);
+ frameCtrl = *(u8_t*)((u8_t*)buf->data);
+ frameType = frameCtrl & 0xf;
+ frameSubtype = frameCtrl & 0xf0;
+
+ if ((frameType == 0x0) && (macp->forwardMgmt))
+ {
+ switch (frameSubtype)
+ {
+ /* Beacon */
+ case 0x80 :
+ /* Probe response */
+ case 0x50 :
+ skb1 = skb_copy(buf, GFP_ATOMIC);
+ if(skb1 != NULL)
+ {
+ skb1->dev = dev;
+ skb1->mac_header = skb1->data;
+ skb1->ip_summed = CHECKSUM_NONE;
+ skb1->pkt_type = PACKET_OTHERHOST;
+ skb1->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */
+ netif_rx(skb1);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ zfiRecv80211(dev, buf, addInfo);
+ return;
+}
+
+#define ZM_AVOID_UDP_LARGE_PACKET_FAIL
+void zfLnxRecvEth(zdev_t* dev, zbuf_t* buf, u16_t port)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+#ifdef ZM_AVOID_UDP_LARGE_PACKET_FAIL
+ zbuf_t *new_buf;
+
+ //new_buf = dev_alloc_skb(2048);
+ new_buf = dev_alloc_skb(buf->len);
+
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+ new_buf->tail = 0;
+ new_buf->len = 0;
+#else
+ new_buf->tail = new_buf->data;
+ new_buf->len = 0;
+#endif
+
+ skb_put(new_buf, buf->len);
+ memcpy(new_buf->data, buf->data, buf->len);
+
+ /* Free buffer */
+ dev_kfree_skb_any(buf);
+
+ if (port == 0)
+ {
+ new_buf->dev = dev;
+ new_buf->protocol = eth_type_trans(new_buf, dev);
+ }
+ else
+ {
+ /* VAP */
+ if (vap[0].dev != NULL)
+ {
+ new_buf->dev = vap[0].dev;
+ new_buf->protocol = eth_type_trans(new_buf, vap[0].dev);
+ }
+ else
+ {
+ new_buf->dev = dev;
+ new_buf->protocol = eth_type_trans(new_buf, dev);
+ }
+ }
+
+ new_buf->ip_summed = CHECKSUM_NONE;
+ dev->last_rx = jiffies;
+
+ switch(netif_rx(new_buf))
+#else
+ if (port == 0)
+ {
+ buf->dev = dev;
+ buf->protocol = eth_type_trans(buf, dev);
+ }
+ else
+ {
+ /* VAP */
+ if (vap[0].dev != NULL)
+ {
+ buf->dev = vap[0].dev;
+ buf->protocol = eth_type_trans(buf, vap[0].dev);
+ }
+ else
+ {
+ buf->dev = dev;
+ buf->protocol = eth_type_trans(buf, dev);
+ }
+ }
+
+ buf->ip_summed = CHECKSUM_NONE;
+ dev->last_rx = jiffies;
+
+ switch(netif_rx(buf))
+#endif
+ {
+ case NET_RX_BAD:
+ case NET_RX_DROP:
+ case NET_RX_CN_MOD:
+ case NET_RX_CN_HIGH:
+ break;
+ default:
+ macp->drv_stats.net_stats.rx_packets++;
+ macp->drv_stats.net_stats.rx_bytes += buf->len;
+ break;
+ }
+
+ return;
+}
+
+/* Leave an empty line below to remove warning message on some compiler */
diff --git a/drivers/staging/otus/wrap_sec.c b/drivers/staging/otus/wrap_sec.c
new file mode 100644
index 000000000000..f688d064175d
--- /dev/null
+++ b/drivers/staging/otus/wrap_sec.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : wrap_sec.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for CENC. */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+#ifdef ZM_ENABLE_CENC
+extern int zfLnxCencSendMsg(struct sock *netlink_sk, u_int8_t *msg, int len);
+
+u16_t zfLnxCencAsocNotify(zdev_t* dev, u16_t* macAddr, u8_t* body, u16_t bodySize, u16_t port)
+{
+ struct usbdrv_private *macp = (struct usbdrv_private *)dev->priv;
+ struct zydas_cenc_sta_info cenc_info;
+ //struct sock *netlink_sk;
+ u8_t ie_len;
+ int ii;
+
+ /* Create NETLINK socket */
+ //netlink_sk = netlink_kernel_create(NETLINK_USERSOCK, NULL);
+
+ if (macp->netlink_sk == NULL)
+ {
+ printk(KERN_ERR "NETLINK Socket is NULL\n");
+ return -1;
+ }
+
+ memset(&cenc_info, 0, sizeof(cenc_info));
+
+ //memcpy(cenc_info.gsn, vap->iv_cencmsk_keys.wk_txiv, ZM_CENC_IV_LEN);
+ zfiWlanQueryGSN(dev, cenc_info.gsn, port);
+ cenc_info.datalen += ZM_CENC_IV_LEN;
+ ie_len = body[1] + 2;
+ memcpy(cenc_info.wie, body, ie_len);
+ cenc_info.datalen += ie_len;
+
+ memcpy(cenc_info.sta_mac, macAddr, 6);
+ cenc_info.msg_type = ZM_CENC_WAI_REQUEST;
+ cenc_info.datalen += 6 + 2;
+
+ printk(KERN_ERR "===== zfwCencSendMsg, bodySize: %d =====\n", bodySize);
+
+ for(ii = 0; ii < bodySize; ii++)
+ {
+ printk(KERN_ERR "%02x ", body[ii]);
+
+ if ((ii & 0xf) == 0xf)
+ {
+ printk(KERN_ERR "\n");
+ }
+ }
+
+ zfLnxCencSendMsg(macp->netlink_sk, (u8_t *)&cenc_info, cenc_info.datalen+4);
+
+ /* Close NETLINK socket */
+ //sock_release(netlink_sk);
+
+ return 0;
+}
+#endif //ZM_ENABLE_CENC
+
+u8_t zfwCencHandleBeaconProbrespon(zdev_t* dev, u8_t *pWIEc,
+ u8_t *pPeerSSIDc, u8_t *pPeerAddrc)
+{
+ return 0;
+}
+
+u8_t zfwGetPktEncExemptionActionType(zdev_t* dev, zbuf_t* buf)
+{
+ return ZM_ENCRYPTION_EXEMPT_NO_EXEMPTION;
+}
+
+void copyToIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src,
+ u16_t offset, u16_t length)
+{
+ u16_t i;
+
+ for(i=0; i<length;i++)
+ {
+ //zmw_tx_buf_writeb(dev, buf, offset+i, src[i]);
+ *(u8_t*)((u8_t*)buf->data+offset+i) = src[i];
+ }
+}
+
+u16_t zfwStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ //zm_msg1_mm(ZM_LV_0, "CWY - add wpaie content Length : ", macp->supIe[1]);
+ if (macp->supIe[1] != 0)
+ {
+ copyToIntTxBuffer(dev, buf, macp->supIe, offset, macp->supIe[1]+2);
+ //memcpy(buf->data[offset], macp->supIe, macp->supIe[1]+2);
+ offset += (macp->supIe[1]+2);
+ }
+
+ return offset;
+}
+
+/* Leave an empty line below to remove warning message on some compiler */
diff --git a/drivers/staging/otus/wrap_usb.c b/drivers/staging/otus/wrap_usb.c
new file mode 100644
index 000000000000..c076e5645224
--- /dev/null
+++ b/drivers/staging/otus/wrap_usb.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : wrap_usb.c */
+/* */
+/* Abstract */
+/* This module contains wrapper functions for USB management */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+extern void zfLnxInitUsbTxQ(zdev_t* dev);
+extern void zfLnxInitUsbRxQ(zdev_t* dev);
+extern u32_t zfLnxSubmitRegInUrb(zdev_t *dev);
+u32_t zfLnxUsbOut(zdev_t* dev, u8_t *hdr, u16_t hdrlen, u8_t *snap, u16_t snapLen,
+ u8_t *tail, u16_t tailLen, zbuf_t *buf, u16_t offset);
+u32_t zfLnxUsbWriteReg(zdev_t* dev, u32_t* cmd, u16_t cmdLen);
+
+void zfwUsbRegisterCallBack(zdev_t* dev, struct zfCbUsbFuncTbl *zfUsbFunc) {
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ macp->usbCbFunctions.zfcbUsbRecv = zfUsbFunc->zfcbUsbRecv;
+ macp->usbCbFunctions.zfcbUsbRegIn = zfUsbFunc->zfcbUsbRegIn;
+ macp->usbCbFunctions.zfcbUsbOutComplete = zfUsbFunc->zfcbUsbOutComplete;
+
+ return;
+}
+
+u32_t zfwUsbGetFreeTxQSize(zdev_t* dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u32_t freeTxQSize;
+ unsigned long irqFlag;
+ //zmw_declare_for_critical_section();
+
+ //zmw_enter_critical_section(dev);
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ freeTxQSize = ZM_MAX_TX_BUF_NUM - macp->TxBufCnt;
+
+ //zmw_leave_critical_section(dev);
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+
+ return freeTxQSize;
+}
+
+u32_t zfwUsbGetMaxTxQSize(zdev_t* dev)
+{
+ return ZM_MAX_TX_BUF_NUM;
+}
+
+u32_t zfwUsbEnableIntEpt(zdev_t *dev, u8_t endpt)
+{
+ /* Initialize USB TxQ */
+ zfLnxInitUsbTxQ(dev);
+
+ /* Initialize USB RxQ */
+ zfLnxInitUsbRxQ(dev);
+
+ /* Initialize USB Register In URB */
+ //zfwUsbSubmitRegIn(dev);
+ /* Initialize USB Register In URB */
+ zfLnxSubmitRegInUrb(dev);
+
+ return 0;
+}
+
+int zfwUsbEnableRxEpt(zdev_t* dev, u8_t endpt)
+{
+ return 0;
+}
+
+u32_t zfwUsbSubmitControl(zdev_t* dev, u8_t req, u16_t value, u16_t index, void *data, u32_t size)
+{
+ int result = 0;
+ u32_t ret = 0;
+ struct usbdrv_private *macp = dev->ml_priv;
+ u8_t* buf;
+
+ if (size > 0)
+ {
+ buf = kmalloc(size, GFP_KERNEL);
+ memcpy(buf, (u8_t*)data, size);
+ }
+ else
+ {
+ buf = NULL;
+ }
+
+#if 0
+ printk(KERN_ERR "req = 0x%02x\n", req);
+ printk(KERN_ERR "value = 0x%04x\n", value);
+ printk(KERN_ERR "index = 0x%04x\n", index);
+ printk(KERN_ERR "data = 0x%lx\n", (u32_t) data);
+ printk(KERN_ERR "size = %ld\n", size);
+#endif
+
+ result = usb_control_msg(macp->udev, usb_sndctrlpipe(macp->udev, 0),
+ req, USB_DIR_OUT | 0x40, value, index, buf, size, HZ);
+
+ if (result < 0)
+ {
+ printk("zfwUsbSubmitControl() failed, result=0x%x\n", result);
+ ret = 1;
+ }
+ kfree(buf);
+
+ return ret;
+}
+
+void zfwUsbCmd(zdev_t* dev, u8_t endpt, u32_t* cmd, u16_t cmdLen)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u32_t ret;
+
+ //MPUsbCommand(dev, endpt, cmd, cmdLen);
+ ret = zfLnxUsbWriteReg(dev, cmd, cmdLen);
+
+ /* if zfLnxUsbWriteReg() return error, free and allocate urb, resend again */
+ if (ret != 0)
+ {
+ usb_free_urb(macp->RegOutUrb);
+ macp->RegOutUrb = usb_alloc_urb(0, GFP_ATOMIC);
+ ret = zfLnxUsbWriteReg(dev, cmd, cmdLen);
+ }
+}
+
+u32_t zfwUsbSend(zdev_t* dev, u8_t endpt, u8_t *hdr, u16_t hdrlen, u8_t *snap, u16_t snapLen,
+ u8_t *tail, u16_t tailLen, zbuf_t *buf, u16_t offset)
+{
+ u32_t status;
+
+#ifdef ZM_CONFIG_BIG_ENDIAN
+ u32_t ii = 0;
+ u16_t *pc = NULL;
+
+ pc = (u16_t *)hdr;
+ for(ii=0; ii<(hdrlen>>1); ii++)
+ {
+ pc[ii] = cpu_to_le16(pc[ii]);
+ }
+
+ pc = (u16_t *)snap;
+ for(ii=0; ii<(snapLen>>1); ii++)
+ {
+ pc[ii] = cpu_to_le16(pc[ii]);
+ }
+
+ pc = (u16_t *)tail;
+ for(ii=0; ii<(tailLen>>1); ii++)
+ {
+ pc[ii] = cpu_to_le16(pc[ii]);
+ }
+#endif
+
+ status = zfLnxUsbOut(dev, hdr, hdrlen, snap, snapLen, tail, tailLen, buf, offset);
+ if ( status == 0 )
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+/* Leave an empty line below to remove warning message on some compiler */
diff --git a/drivers/staging/otus/wwrap.c b/drivers/staging/otus/wwrap.c
new file mode 100644
index 000000000000..1bb5f596d6c3
--- /dev/null
+++ b/drivers/staging/otus/wwrap.c
@@ -0,0 +1,1134 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Module Name : wwrap.c */
+/* Abstract */
+/* This module contains wrapper functions. */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+
+/* Please include your header files here */
+#include "oal_dt.h"
+#include "usbdrv.h"
+
+#include <linux/netlink.h>
+
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif
+
+extern void zfiRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo);
+extern void zfCoreRecv(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo);
+extern void zfIdlChkRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen);
+extern void zfIdlRsp(zdev_t* dev, u32_t *rsp, u16_t rspLen);
+
+
+
+//extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER];
+extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER];
+
+u32_t zfLnxUsbSubmitTxData(zdev_t* dev);
+u32_t zfLnxUsbIn(zdev_t* dev, urb_t *urb, zbuf_t *buf);
+u32_t zfLnxSubmitRegInUrb(zdev_t *dev);
+u32_t zfLnxUsbSubmitBulkUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction,
+ void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context);
+u32_t zfLnxUsbSubmitIntUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction,
+ void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context,
+ u32_t interval);
+
+u16_t zfLnxGetFreeTxUrb(zdev_t *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t idx;
+ unsigned long irqFlag;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ //idx = ((macp->TxUrbTail + 1) & (ZM_MAX_TX_URB_NUM - 1));
+
+ //if (idx != macp->TxUrbHead)
+ if (macp->TxUrbCnt != 0)
+ {
+ idx = macp->TxUrbTail;
+ macp->TxUrbTail = ((macp->TxUrbTail + 1) & (ZM_MAX_TX_URB_NUM - 1));
+ macp->TxUrbCnt--;
+ }
+ else
+ {
+ //printk(KERN_ERR "macp->TxUrbCnt: %d\n", macp->TxUrbCnt);
+ idx = 0xffff;
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return idx;
+}
+
+void zfLnxPutTxUrb(zdev_t *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t idx;
+ unsigned long irqFlag;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ idx = ((macp->TxUrbHead + 1) & (ZM_MAX_TX_URB_NUM - 1));
+
+ //if (idx != macp->TxUrbTail)
+ if (macp->TxUrbCnt < ZM_MAX_TX_URB_NUM)
+ {
+ macp->TxUrbHead = idx;
+ macp->TxUrbCnt++;
+ }
+ else
+ {
+ printk("UsbTxUrbQ inconsistent: TxUrbHead: %d, TxUrbTail: %d\n",
+ macp->TxUrbHead, macp->TxUrbTail);
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+}
+
+u16_t zfLnxCheckTxBufferCnt(zdev_t *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t TxBufCnt;
+ unsigned long irqFlag;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ TxBufCnt = macp->TxBufCnt;
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return TxBufCnt;
+}
+
+UsbTxQ_t *zfLnxGetUsbTxBuffer(zdev_t *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t idx;
+ UsbTxQ_t *TxQ;
+ unsigned long irqFlag;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ idx = ((macp->TxBufHead+1) & (ZM_MAX_TX_BUF_NUM - 1));
+
+ //if (idx != macp->TxBufTail)
+ if (macp->TxBufCnt > 0)
+ {
+ //printk("CWY - zfwGetUsbTxBuffer ,macp->TxBufCnt = %d\n", macp->TxBufCnt);
+ TxQ = (UsbTxQ_t *)&(macp->UsbTxBufQ[macp->TxBufHead]);
+ macp->TxBufHead = ((macp->TxBufHead+1) & (ZM_MAX_TX_BUF_NUM - 1));
+ macp->TxBufCnt--;
+ }
+ else
+ {
+ if (macp->TxBufHead != macp->TxBufTail)
+ {
+ printk(KERN_ERR "zfwGetUsbTxBuf UsbTxBufQ inconsistent: TxBufHead: %d, TxBufTail: %d\n",
+ macp->TxBufHead, macp->TxBufTail);
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return NULL;
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return TxQ;
+}
+
+u16_t zfLnxPutUsbTxBuffer(zdev_t *dev, u8_t *hdr, u16_t hdrlen,
+ u8_t *snap, u16_t snapLen, u8_t *tail, u16_t tailLen,
+ zbuf_t *buf, u16_t offset)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t idx;
+ UsbTxQ_t *TxQ;
+ unsigned long irqFlag;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ idx = ((macp->TxBufTail+1) & (ZM_MAX_TX_BUF_NUM - 1));
+
+ /* For Tx debug */
+ //zm_assert(macp->TxBufCnt >= 0); // deleted because of always true
+
+ //if (idx != macp->TxBufHead)
+ if (macp->TxBufCnt < ZM_MAX_TX_BUF_NUM)
+ {
+ //printk("CWY - zfwPutUsbTxBuffer ,macp->TxBufCnt = %d\n", macp->TxBufCnt);
+ TxQ = (UsbTxQ_t *)&(macp->UsbTxBufQ[macp->TxBufTail]);
+ memcpy(TxQ->hdr, hdr, hdrlen);
+ TxQ->hdrlen = hdrlen;
+ memcpy(TxQ->snap, snap, snapLen);
+ TxQ->snapLen = snapLen;
+ memcpy(TxQ->tail, tail, tailLen);
+ TxQ->tailLen = tailLen;
+ TxQ->buf = buf;
+ TxQ->offset = offset;
+
+ macp->TxBufTail = ((macp->TxBufTail+1) & (ZM_MAX_TX_BUF_NUM - 1));
+ macp->TxBufCnt++;
+ }
+ else
+ {
+ printk(KERN_ERR "zfLnxPutUsbTxBuffer UsbTxBufQ inconsistent: TxBufHead: %d, TxBufTail: %d, TxBufCnt: %d\n",
+ macp->TxBufHead, macp->TxBufTail, macp->TxBufCnt);
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return 0xffff;
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return 0;
+}
+
+zbuf_t *zfLnxGetUsbRxBuffer(zdev_t *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ //u16_t idx;
+ zbuf_t *buf;
+ unsigned long irqFlag;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ //idx = ((macp->RxBufHead+1) & (ZM_MAX_RX_URB_NUM - 1));
+
+ //if (idx != macp->RxBufTail)
+ if (macp->RxBufCnt != 0)
+ {
+ buf = macp->UsbRxBufQ[macp->RxBufHead];
+ macp->RxBufHead = ((macp->RxBufHead+1) & (ZM_MAX_RX_URB_NUM - 1));
+ macp->RxBufCnt--;
+ }
+ else
+ {
+ printk("RxBufQ inconsistent: RxBufHead: %d, RxBufTail: %d\n",
+ macp->RxBufHead, macp->RxBufTail);
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return NULL;
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return buf;
+}
+
+u32_t zfLnxPutUsbRxBuffer(zdev_t *dev, zbuf_t *buf)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u16_t idx;
+ unsigned long irqFlag;
+
+ spin_lock_irqsave(&macp->cs_lock, irqFlag);
+
+ idx = ((macp->RxBufTail+1) & (ZM_MAX_RX_URB_NUM - 1));
+
+ //if (idx != macp->RxBufHead)
+ if (macp->RxBufCnt != ZM_MAX_RX_URB_NUM)
+ {
+ macp->UsbRxBufQ[macp->RxBufTail] = buf;
+ macp->RxBufTail = idx;
+ macp->RxBufCnt++;
+ }
+ else
+ {
+ printk("RxBufQ inconsistent: RxBufHead: %d, RxBufTail: %d\n",
+ macp->RxBufHead, macp->RxBufTail);
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return 0xffff;
+ }
+
+ spin_unlock_irqrestore(&macp->cs_lock, irqFlag);
+ return 0;
+}
+
+void zfLnxUsbDataOut_callback(urb_t *urb)
+{
+ zdev_t* dev = urb->context;
+ //UsbTxQ_t *TxData;
+
+ /* Give the urb back */
+ zfLnxPutTxUrb(dev);
+
+ /* Check whether there is any pending buffer needed */
+ /* to be sent */
+ if (zfLnxCheckTxBufferCnt(dev) != 0)
+ {
+ //TxData = zfwGetUsbTxBuffer(dev);
+
+ //if (TxData == NULL)
+ //{
+ // printk("Get a NULL buffer from zfwGetUsbTxBuffer\n");
+ // return;
+ //}
+ //else
+ //{
+ zfLnxUsbSubmitTxData(dev);
+ //}
+ }
+}
+
+void zfLnxUsbDataIn_callback(urb_t *urb)
+{
+ zdev_t* dev = urb->context;
+ struct usbdrv_private *macp = dev->ml_priv;
+ zbuf_t *buf;
+ zbuf_t *new_buf;
+ int status;
+
+#if ZM_USB_STREAM_MODE == 1
+ static int remain_len = 0, check_pad = 0, check_len = 0;
+ int index = 0;
+ int chk_idx;
+ u16_t pkt_len;
+ u16_t pkt_tag;
+ u16_t ii;
+ zbuf_t *rxBufPool[8];
+ u16_t rxBufPoolIndex = 0;
+#endif
+
+ /* Check status for URB */
+ if (urb->status != 0){
+ printk("zfLnxUsbDataIn_callback() : status=0x%x\n", urb->status);
+ if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)
+ && (urb->status != -ESHUTDOWN))
+ {
+ if (urb->status == -EPIPE){
+ //printk(KERN_ERR "nonzero read bulk status received: -EPIPE");
+ status = -1;
+ }
+
+ if (urb->status == -EPROTO){
+ //printk(KERN_ERR "nonzero read bulk status received: -EPROTO");
+ status = -1;
+ }
+ }
+
+ //printk(KERN_ERR "urb->status: 0x%08x\n", urb->status);
+
+ /* Dequeue skb buffer */
+ buf = zfLnxGetUsbRxBuffer(dev);
+ dev_kfree_skb_any(buf);
+ #if 0
+ /* Enqueue skb buffer */
+ zfLnxPutUsbRxBuffer(dev, buf);
+
+ /* Submit a Rx urb */
+ zfLnxUsbIn(dev, urb, buf);
+ #endif
+ return;
+ }
+
+ if (urb->actual_length == 0)
+ {
+ printk(KERN_ERR "Get an URB whose length is zero");
+ status = -1;
+ }
+
+ /* Dequeue skb buffer */
+ buf = zfLnxGetUsbRxBuffer(dev);
+
+ //zfwBufSetSize(dev, buf, urb->actual_length);
+#ifdef NET_SKBUFF_DATA_USES_OFFSET
+ buf->tail = 0;
+ buf->len = 0;
+#else
+ buf->tail = buf->data;
+ buf->len = 0;
+#endif
+
+ if ((buf->tail + urb->actual_length) > buf->end)
+ BUG();
+
+ skb_put(buf, urb->actual_length);
+
+#if ZM_USB_STREAM_MODE == 1
+ if (remain_len != 0)
+ {
+ zbuf_t *remain_buf = macp->reamin_buf;
+
+ index = remain_len;
+ remain_len -= check_pad;
+
+ /* Copy data */
+ memcpy(&(remain_buf->data[check_len]), buf->data, remain_len);
+ check_len += remain_len;
+ remain_len = 0;
+
+ rxBufPool[rxBufPoolIndex++] = remain_buf;
+ }
+
+ while(index < urb->actual_length)
+ {
+ pkt_len = buf->data[index] + (buf->data[index+1] << 8);
+ pkt_tag = buf->data[index+2] + (buf->data[index+3] << 8);
+
+ if (pkt_tag == 0x4e00)
+ {
+ int pad_len;
+
+ //printk("Get a packet, index: %d, pkt_len: 0x%04x\n", index, pkt_len);
+ #if 0
+ /* Dump data */
+ for (ii = index; ii < pkt_len+4;)
+ {
+ printk("%02x ", (buf->data[ii] & 0xff));
+
+ if ((++ii % 16) == 0)
+ printk("\n");
+ }
+
+ printk("\n");
+ #endif
+
+ pad_len = 4 - (pkt_len & 0x3);
+
+ if(pad_len == 4)
+ pad_len = 0;
+
+ chk_idx = index;
+ index = index + 4 + pkt_len + pad_len;
+
+ if (index > ZM_MAX_RX_BUFFER_SIZE)
+ {
+ remain_len = index - ZM_MAX_RX_BUFFER_SIZE; // - pad_len;
+ check_len = ZM_MAX_RX_BUFFER_SIZE - chk_idx - 4;
+ check_pad = pad_len;
+
+ /* Allocate a skb buffer */
+ //new_buf = zfwBufAllocate(dev, ZM_MAX_RX_BUFFER_SIZE);
+ new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE);
+
+ /* Set skb buffer length */
+ #ifdef NET_SKBUFF_DATA_USES_OFFSET
+ new_buf->tail = 0;
+ new_buf->len = 0;
+ #else
+ new_buf->tail = new_buf->data;
+ new_buf->len = 0;
+ #endif
+
+ skb_put(new_buf, pkt_len);
+
+ /* Copy the buffer */
+ memcpy(new_buf->data, &(buf->data[chk_idx+4]), check_len);
+
+ /* Record the buffer pointer */
+ macp->reamin_buf = new_buf;
+ }
+ else
+ {
+ #ifdef ZM_DONT_COPY_RX_BUFFER
+ if (rxBufPoolIndex == 0)
+ {
+ new_buf = skb_clone(buf, GFP_ATOMIC);
+
+ new_buf->data = &(buf->data[chk_idx+4]);
+ new_buf->len = pkt_len;
+ }
+ else
+ {
+ #endif
+ /* Allocate a skb buffer */
+ new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE);
+
+ /* Set skb buffer length */
+ #ifdef NET_SKBUFF_DATA_USES_OFFSET
+ new_buf->tail = 0;
+ new_buf->len = 0;
+ #else
+ new_buf->tail = new_buf->data;
+ new_buf->len = 0;
+ #endif
+
+ skb_put(new_buf, pkt_len);
+
+ /* Copy the buffer */
+ memcpy(new_buf->data, &(buf->data[chk_idx+4]), pkt_len);
+
+ #ifdef ZM_DONT_COPY_RX_BUFFER
+ }
+ #endif
+ rxBufPool[rxBufPoolIndex++] = new_buf;
+ }
+ }
+ else
+ {
+ printk(KERN_ERR "Can't find tag, pkt_len: 0x%04x, tag: 0x%04x\n", pkt_len, pkt_tag);
+
+ /* Free buffer */
+ dev_kfree_skb_any(buf);
+
+ /* Allocate a skb buffer */
+ new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE);
+
+ /* Enqueue skb buffer */
+ zfLnxPutUsbRxBuffer(dev, new_buf);
+
+ /* Submit a Rx urb */
+ zfLnxUsbIn(dev, urb, new_buf);
+
+ return;
+ }
+ }
+
+ /* Free buffer */
+ dev_kfree_skb_any(buf);
+#endif
+
+ /* Allocate a skb buffer */
+ new_buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE);
+
+ /* Enqueue skb buffer */
+ zfLnxPutUsbRxBuffer(dev, new_buf);
+
+ /* Submit a Rx urb */
+ zfLnxUsbIn(dev, urb, new_buf);
+
+#if ZM_USB_STREAM_MODE == 1
+ for(ii = 0; ii < rxBufPoolIndex; ii++)
+ {
+ macp->usbCbFunctions.zfcbUsbRecv(dev, rxBufPool[ii]);
+ }
+#else
+ /* pass data to upper layer */
+ macp->usbCbFunctions.zfcbUsbRecv(dev, buf);
+#endif
+}
+
+void zfLnxUsbRegOut_callback(urb_t *urb)
+{
+ //dev_t* dev = urb->context;
+
+ //printk(KERN_ERR "zfwUsbRegOut_callback\n");
+}
+
+void zfLnxUsbRegIn_callback(urb_t *urb)
+{
+ zdev_t* dev = urb->context;
+ u32_t rsp[64/4];
+ int status;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ /* Check status for URB */
+ if (urb->status != 0){
+ printk("zfLnxUsbRegIn_callback() : status=0x%x\n", urb->status);
+ if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)
+ && (urb->status != -ESHUTDOWN))
+ {
+ if (urb->status == -EPIPE){
+ //printk(KERN_ERR "nonzero read bulk status received: -EPIPE");
+ status = -1;
+ }
+
+ if (urb->status == -EPROTO){
+ //printk(KERN_ERR "nonzero read bulk status received: -EPROTO");
+ status = -1;
+ }
+ }
+
+ //printk(KERN_ERR "urb->status: 0x%08x\n", urb->status);
+ return;
+ }
+
+ if (urb->actual_length == 0)
+ {
+ printk(KERN_ERR "Get an URB whose length is zero");
+ status = -1;
+ }
+
+ /* Copy data into respone buffer */
+ memcpy(rsp, macp->regUsbReadBuf, urb->actual_length);
+
+ /* Notify to upper layer */
+ //zfIdlChkRsp(dev, rsp, (u16_t)urb->actual_length);
+ //zfiUsbRegIn(dev, rsp, (u16_t)urb->actual_length);
+ macp->usbCbFunctions.zfcbUsbRegIn(dev, rsp, (u16_t)urb->actual_length);
+
+ /* Issue another USB IN URB */
+ zfLnxSubmitRegInUrb(dev);
+}
+
+u32_t zfLnxSubmitRegInUrb(zdev_t *dev)
+{
+ u32_t ret;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ /* Submit a rx urb */
+ //ret = zfLnxUsbSubmitBulkUrb(macp->RegInUrb, macp->udev,
+ // USB_REG_IN_PIPE, USB_DIR_IN, macp->regUsbReadBuf,
+ // ZM_USB_REG_MAX_BUF_SIZE, zfLnxUsbRegIn_callback, dev);
+ //CWYang(-)
+ //if (ret != 0)
+ // printk("zfwUsbSubmitBulkUrb fail, status: 0x%08x\n", (int)ret);
+
+ ret = zfLnxUsbSubmitIntUrb(macp->RegInUrb, macp->udev,
+ USB_REG_IN_PIPE, USB_DIR_IN, macp->regUsbReadBuf,
+ ZM_USB_REG_MAX_BUF_SIZE, zfLnxUsbRegIn_callback, dev, 1);
+
+ return ret;
+}
+
+u32_t zfLnxUsbSubmitTxData(zdev_t* dev)
+{
+ u32_t i;
+ u32_t ret;
+ u16_t freeTxUrb;
+ u8_t *puTxBuf = NULL;
+ UsbTxQ_t *TxData;
+ int len = 0;
+ struct usbdrv_private *macp = dev->ml_priv;
+#if ZM_USB_TX_STREAM_MODE == 1
+ u8_t ii;
+ u16_t offset = 0;
+ u16_t usbTxAggCnt;
+ u16_t *pUsbTxHdr;
+ UsbTxQ_t *TxQPool[ZM_MAX_TX_AGGREGATE_NUM];
+#endif
+
+ /* First check whether there is a free URB */
+ freeTxUrb = zfLnxGetFreeTxUrb(dev);
+
+ /* If there is no any free Tx Urb */
+ if (freeTxUrb == 0xffff)
+ {
+ //printk(KERN_ERR "Can't get free Tx Urb\n");
+ //printk("CWY - Can't get free Tx Urb\n");
+ return 0xffff;
+ }
+
+#if ZM_USB_TX_STREAM_MODE == 1
+ usbTxAggCnt = zfLnxCheckTxBufferCnt(dev);
+
+ if (usbTxAggCnt >= ZM_MAX_TX_AGGREGATE_NUM)
+ {
+ usbTxAggCnt = ZM_MAX_TX_AGGREGATE_NUM;
+ }
+ else
+ {
+ usbTxAggCnt = 1;
+ }
+
+ //printk("usbTxAggCnt: %d\n", usbTxAggCnt);
+#endif
+
+#if ZM_USB_TX_STREAM_MODE == 1
+ for(ii = 0; ii < usbTxAggCnt; ii++)
+ {
+#endif
+ /* Dequeue the packet from UsbTxBufQ */
+ TxData = zfLnxGetUsbTxBuffer(dev);
+ if (TxData == NULL)
+ {
+ /* Give the urb back */
+ zfLnxPutTxUrb(dev);
+ return 0xffff;
+ }
+
+ /* Point to the freeTxUrb buffer */
+ puTxBuf = macp->txUsbBuf[freeTxUrb];
+
+#if ZM_USB_TX_STREAM_MODE == 1
+ puTxBuf += offset;
+ pUsbTxHdr = (u16_t *)puTxBuf;
+
+ /* Add the packet length and tag information */
+ *pUsbTxHdr++ = TxData->hdrlen + TxData->snapLen +
+ (TxData->buf->len - TxData->offset) + TxData->tailLen;
+
+ *pUsbTxHdr++ = 0x697e;
+
+ puTxBuf += 4;
+#endif // #ifdef ZM_USB_TX_STREAM_MODE
+
+ /* Copy WLAN header and packet buffer into USB buffer */
+ for(i = 0; i < TxData->hdrlen; i++)
+ {
+ *puTxBuf++ = TxData->hdr[i];
+ }
+
+ /* Copy SNAP header */
+ for(i = 0; i < TxData->snapLen; i++)
+ {
+ *puTxBuf++ = TxData->snap[i];
+ }
+
+ /* Copy packet buffer */
+ for(i = 0; i < TxData->buf->len - TxData->offset; i++)
+ {
+ //*puTxBuf++ = zmw_rx_buf_readb(dev, TxData->buf, i);
+ *puTxBuf++ = *(u8_t*)((u8_t*)TxData->buf->data+i+TxData->offset);
+ }
+
+ /* Copy tail */
+ for(i = 0; i < TxData->tailLen; i++)
+ {
+ *puTxBuf++ = TxData->tail[i];
+ }
+
+ len = TxData->hdrlen+TxData->snapLen+TxData->buf->len+TxData->tailLen-TxData->offset;
+
+ #if 0
+ if (TxData->hdrlen != 0)
+ {
+ puTxBuf = macp->txUsbBuf[freeTxUrb];
+ for (i = 0; i < len; i++)
+ {
+ printk("%02x ", puTxBuf[i]);
+ if (i % 16 == 15)
+ printk("\n");
+ }
+ printk("\n");
+ }
+ #endif
+ #if 0
+ /* For debug purpose */
+ if(TxData->hdr[9] & 0x40)
+ {
+ int i;
+ u16_t ctrlLen = TxData->hdr[0] + (TxData->hdr[1] << 8);
+
+ if (ctrlLen != len + 4)
+ {
+ /* Dump control setting */
+ for(i = 0; i < 8; i++)
+ {
+ printk(KERN_ERR "0x%02x ", TxData->hdr[i]);
+ }
+ printk(KERN_ERR "\n");
+
+ printk(KERN_ERR "ctrLen: %d, hdrLen: %d, snapLen: %d\n", ctrlLen, TxData->hdrlen, TxData->snapLen);
+ printk(KERN_ERR "bufLen: %d, tailLen: %d, len: %d\n", TxData->buf->len, TxData->tailLen, len);
+ }
+ }
+ #endif
+
+#if ZM_USB_TX_STREAM_MODE == 1
+ // Add the Length and Tag
+ len += 4;
+
+ //printk("%d packet, length: %d\n", ii+1, len);
+
+ if (ii < (ZM_MAX_TX_AGGREGATE_NUM-1))
+ {
+ /* Pad the buffer to firmware descriptor boundary */
+ offset += (((len-1) / 4) + 1) * 4;
+ }
+
+ if (ii == (ZM_MAX_TX_AGGREGATE_NUM-1))
+ {
+ len += offset;
+ }
+
+ TxQPool[ii] = TxData;
+
+ //DbgPrint("%d packet, offset: %d\n", ii+1, pUsbTxTransfer->offset);
+
+ /* free packet */
+ //zfBufFree(dev, txData->buf);
+ }
+#endif
+ //printk("CWY - call zfwUsbSubmitBulkUrb(), len = 0x%d\n", len);
+ /* Submit a tx urb */
+ ret = zfLnxUsbSubmitBulkUrb(macp->WlanTxDataUrb[freeTxUrb], macp->udev,
+ USB_WLAN_TX_PIPE, USB_DIR_OUT, macp->txUsbBuf[freeTxUrb],
+ len, zfLnxUsbDataOut_callback, dev);
+ //CWYang(-)
+ //if (ret != 0)
+ // printk("zfwUsbSubmitBulkUrb fail, status: 0x%08x\n", (int)ret);
+
+ /* free packet */
+ //dev_kfree_skb_any(TxData->buf);
+#if ZM_USB_TX_STREAM_MODE == 1
+ for(ii = 0; ii < usbTxAggCnt; ii++)
+ macp->usbCbFunctions.zfcbUsbOutComplete(dev, TxQPool[ii]->buf, 1, TxQPool[ii]->hdr);
+#else
+ macp->usbCbFunctions.zfcbUsbOutComplete(dev, TxData->buf, 1, TxData->hdr);
+#endif
+
+ return ret;
+}
+
+
+
+u32_t zfLnxUsbIn(zdev_t* dev, urb_t *urb, zbuf_t *buf)
+{
+ u32_t ret;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ /* Submit a rx urb */
+ ret = zfLnxUsbSubmitBulkUrb(urb, macp->udev, USB_WLAN_RX_PIPE,
+ USB_DIR_IN, buf->data, ZM_MAX_RX_BUFFER_SIZE,
+ zfLnxUsbDataIn_callback, dev);
+ //CWYang(-)
+ //if (ret != 0)
+ // printk("zfwUsbSubmitBulkUrb fail, status: 0x%08x\n", (int)ret);
+
+ return ret;
+}
+
+u32_t zfLnxUsbWriteReg(zdev_t* dev, u32_t* cmd, u16_t cmdLen)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+ u32_t ret;
+
+#ifdef ZM_CONFIG_BIG_ENDIAN
+ int ii = 0;
+
+ for(ii=0; ii<(cmdLen>>2); ii++)
+ cmd[ii] = cpu_to_le32(cmd[ii]);
+#endif
+
+ memcpy(macp->regUsbWriteBuf, cmd, cmdLen);
+
+ /* Issue an USB Out transfer */
+ /* Submit a tx urb */
+ ret = zfLnxUsbSubmitIntUrb(macp->RegOutUrb, macp->udev,
+ USB_REG_OUT_PIPE, USB_DIR_OUT, macp->regUsbWriteBuf,
+ cmdLen, zfLnxUsbRegOut_callback, dev, 1);
+
+ return ret;
+}
+
+
+u32_t zfLnxUsbOut(zdev_t* dev, u8_t *hdr, u16_t hdrlen, u8_t *snap, u16_t snapLen,
+ u8_t *tail, u16_t tailLen, zbuf_t *buf, u16_t offset)
+{
+ u32_t ret;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ /* Check length of tail buffer */
+ //zm_assert((tailLen <= 16));
+
+ /* Enqueue the packet into UsbTxBufQ */
+ if (zfLnxPutUsbTxBuffer(dev, hdr, hdrlen, snap, snapLen, tail, tailLen, buf, offset) == 0xffff)
+ {
+ /* free packet */
+ //printk("CWY - zfwPutUsbTxBuffer Error, free packet\n");
+ //dev_kfree_skb_any(buf);
+ macp->usbCbFunctions.zfcbUsbOutComplete(dev, buf, 0, hdr);
+ return 0xffff;
+ }
+
+ //return 0;
+ //printk("CWY - call zfwUsbSubmitTxData()\n");
+ ret = zfLnxUsbSubmitTxData(dev);
+ return ret;
+}
+
+void zfLnxInitUsbTxQ(zdev_t* dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ printk(KERN_ERR "zfwInitUsbTxQ\n");
+
+ /* Zero memory for UsbTxBufQ */
+ memset(macp->UsbTxBufQ, 0, sizeof(UsbTxQ_t) * ZM_MAX_TX_URB_NUM);
+
+ macp->TxBufHead = 0;
+ macp->TxBufTail = 0;
+ macp->TxUrbHead = 0;
+ macp->TxUrbTail = 0;
+ macp->TxUrbCnt = ZM_MAX_TX_URB_NUM;
+}
+
+void zfLnxInitUsbRxQ(zdev_t* dev)
+{
+ u16_t i;
+ zbuf_t *buf;
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ /* Zero memory for UsbRxBufQ */
+ memset(macp->UsbRxBufQ, 0, sizeof(zbuf_t *) * ZM_MAX_RX_URB_NUM);
+
+ macp->RxBufHead = 0;
+
+ for (i = 0; i < ZM_MAX_RX_URB_NUM; i++)
+ {
+ //buf = zfwBufAllocate(dev, ZM_MAX_RX_BUFFER_SIZE);
+ buf = dev_alloc_skb(ZM_MAX_RX_BUFFER_SIZE);
+ macp->UsbRxBufQ[i] = buf;
+ }
+
+ //macp->RxBufTail = ZM_MAX_RX_URB_NUM - 1;
+ macp->RxBufTail = 0;
+
+ /* Submit all Rx urbs */
+ for (i = 0; i < ZM_MAX_RX_URB_NUM; i++)
+ {
+ zfLnxPutUsbRxBuffer(dev, macp->UsbRxBufQ[i]);
+ zfLnxUsbIn(dev, macp->WlanRxDataUrb[i], macp->UsbRxBufQ[i]);
+ }
+}
+
+
+
+u32_t zfLnxUsbSubmitBulkUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction,
+ void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context)
+{
+ u32_t ret;
+
+ if(direction == USB_DIR_OUT)
+ {
+ usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, epnum),
+ transfer_buffer, buffer_length, complete, context);
+
+ urb->transfer_flags |= URB_ZERO_PACKET;
+ }
+ else
+ {
+ usb_fill_bulk_urb(urb, usb, usb_rcvbulkpipe(usb, epnum),
+ transfer_buffer, buffer_length, complete, context);
+ }
+
+ if (epnum == 4)
+ {
+ if (urb->hcpriv)
+ {
+ //printk("CWY - urb->hcpriv set by unknown reason, reset it\n");
+ //urb->hcpriv = 0;
+ }
+ }
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if ((epnum == 4) & (ret != 0))
+ {
+ //printk("CWY - ret = %x\n", ret);
+ }
+ return ret;
+}
+
+u32_t zfLnxUsbSubmitIntUrb(urb_t *urb, struct usb_device *usb, u16_t epnum, u16_t direction,
+ void *transfer_buffer, int buffer_length, usb_complete_t complete, void *context,
+ u32_t interval)
+{
+ u32_t ret;
+
+ if(direction == USB_DIR_OUT)
+ {
+ usb_fill_int_urb(urb, usb, usb_sndbulkpipe(usb, epnum),
+ transfer_buffer, buffer_length, complete, context, interval);
+ }
+ else
+ {
+ usb_fill_int_urb(urb, usb, usb_rcvbulkpipe(usb, epnum),
+ transfer_buffer, buffer_length, complete, context, interval);
+ }
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+
+ return ret;
+}
+
+#ifdef ZM_ENABLE_CENC
+int zfLnxCencSendMsg(struct sock *netlink_sk, u_int8_t *msg, int len)
+{
+#define COMMTYPE_GROUP 8
+#define WAI_K_MSG 0x11
+
+ int ret = -1;
+ int size;
+ unsigned char *old_tail;
+ struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+ char *pos = NULL;
+
+ size = NLMSG_SPACE(len);
+ skb = alloc_skb(size, GFP_ATOMIC);
+
+ if(skb == NULL)
+ {
+ printk("dev_alloc_skb failure \n");
+ goto out;
+ }
+ old_tail = skb->tail;
+
+ /*дݱϢ*/
+ nlh = NLMSG_PUT(skb, 0, 0, WAI_K_MSG, size-sizeof(*nlh));
+ pos = NLMSG_DATA(nlh);
+ memset(pos, 0, len);
+
+ /*䵽ûռ*/
+ memcpy(pos, msg, len);
+ /*㾭ֽڶʵʳ*/
+ nlh->nlmsg_len = skb->tail - old_tail;
+ NETLINK_CB(skb).dst_group = COMMTYPE_GROUP;
+ netlink_broadcast(netlink_sk, skb, 0, COMMTYPE_GROUP, GFP_ATOMIC);
+ ret = 0;
+out:
+ return ret;
+nlmsg_failure: /*NLMSG_PUT ʧܣ׽ֻ*/
+ if(skb)
+ kfree_skb(skb);
+ goto out;
+
+#undef COMMTYPE_GROUP
+#undef WAI_K_MSG
+}
+#endif //ZM_ENABLE_CENC
+
+/* Simply return 0xffff if VAP function is not supported */
+u16_t zfLnxGetVapId(zdev_t* dev)
+{
+ u16_t i;
+
+ for (i=0; i<ZM_VAP_PORT_NUMBER; i++)
+ {
+ if (vap[i].dev == dev)
+ {
+ return i;
+ }
+ }
+ return 0xffff;
+}
+
+u32_t zfwReadReg(zdev_t* dev, u32_t offset)
+{
+ return 0;
+}
+
+#ifndef INIT_WORK
+#define work_struct tq_struct
+
+#define schedule_work(a) schedule_task(a)
+
+#define flush_scheduled_work flush_scheduled_tasks
+#define INIT_WORK(_wq, _routine, _data) INIT_TQUEUE(_wq, _routine, _data)
+#define PREPARE_WORK(_wq, _routine, _data) PREPARE_TQUEUE(_wq, _routine, _data)
+#endif
+
+#define KEVENT_WATCHDOG 0x00000001
+
+u32_t smp_kevent_Lock = 0;
+
+void kevent(struct work_struct *work)
+{
+ struct usbdrv_private *macp =
+ container_of(work, struct usbdrv_private, kevent);
+ zdev_t *dev = macp->device;
+
+ if (macp == NULL)
+ {
+ return;
+ }
+
+ if (test_and_set_bit(0, (void *)&smp_kevent_Lock))
+ {
+ //schedule_work(&macp->kevent);
+ return;
+ }
+
+ down(&macp->ioctl_sem);
+
+ if (test_and_clear_bit(KEVENT_WATCHDOG, &macp->kevent_flags))
+ {
+ extern u16_t zfHpStartRecv(zdev_t *dev);
+ //zfiHwWatchDogReinit(dev);
+ printk(("\n ************ Hw watchDog occur!! ************** \n"));
+ zfiWlanSuspend(dev);
+ zfiWlanResume(dev,0);
+ zfHpStartRecv(dev);
+ }
+
+ clear_bit(0, (void *)&smp_kevent_Lock);
+ up(&macp->ioctl_sem);
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfLnxCreateThread */
+/* Create a Thread */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* */
+/* OUTPUTS */
+/* always 0 */
+/* */
+/* AUTHOR */
+/* Yuan-Gu Wei Atheros Communications, INC. 2007.3 */
+/* */
+/************************************************************************/
+u8_t zfLnxCreateThread(zdev_t *dev)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ /* Create Mutex and keventd */
+ INIT_WORK(&macp->kevent, kevent);
+ init_MUTEX(&macp->ioctl_sem);
+
+ return 0;
+}
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfLnxSignalThread */
+/* Signal Thread with Flag */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* flag : signal thread flag */
+/* */
+/* OUTPUTS */
+/* none */
+/* */
+/* AUTHOR */
+/* Yuan-Gu Wei Atheros Communications, INC. 2007.3 */
+/* */
+/************************************************************************/
+void zfLnxSignalThread(zdev_t *dev, int flag)
+{
+ struct usbdrv_private *macp = dev->ml_priv;
+
+ if (macp == NULL)
+ {
+ printk("macp is NULL\n");
+ return;
+ }
+
+ if (0 && macp->kevent_ready != 1)
+ {
+ printk("Kevent not ready\n");
+ return;
+ }
+
+ set_bit(flag, &macp->kevent_flags);
+
+ if (!schedule_work(&macp->kevent))
+ {
+ //Fails is Normal
+ //printk(KERN_ERR "schedule_task failed, flag = %x\n", flag);
+ }
+}
+
+/* Notify wrapper todo redownload firmware and reinit procedure when */
+/* hardware watchdog occur : zfiHwWatchDogReinit() */
+void zfLnxWatchDogNotify(zdev_t* dev)
+{
+ zfLnxSignalThread(dev, KEVENT_WATCHDOG);
+}
+
+/* Query Durantion of Active Scan */
+void zfwGetActiveScanDur(zdev_t* dev, u8_t* Dur)
+{
+ *Dur = 30; // default 30 ms
+}
+
+void zfwGetShowZeroLengthSSID(zdev_t* dev, u8_t* Dur)
+{
+ *Dur = 0;
+}
+
diff --git a/drivers/staging/otus/zdcompat.h b/drivers/staging/otus/zdcompat.h
new file mode 100644
index 000000000000..8acf400fbc0b
--- /dev/null
+++ b/drivers/staging/otus/zdcompat.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : zdcompat.h */
+/* */
+/* Abstract */
+/* This module contains function defintion for compatibility. */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#ifndef _ZDCOMPAT_H
+#define _ZDCOMPAT_H
+
+
+#ifndef DECLARE_TASKLET
+#define tasklet_schedule(a) schedule_task(a)
+#endif
+
+#undef netdevice_t
+typedef struct net_device netdevice_t;
+
+#ifdef WIRELESS_EXT
+#if (WIRELESS_EXT < 13)
+struct iw_request_info
+{
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+#endif
+#endif
+
+#ifndef IRQ_NONE
+typedef void irqreturn_t;
+#define IRQ_NONE
+#define IRQ_HANDLED
+#define IRQ_RETVAL(x)
+#endif
+
+#ifndef in_atomic
+#define in_atomic() 0
+#endif
+
+#define USB_QUEUE_BULK 0
+
+
+#endif
diff --git a/drivers/staging/otus/zdusb.c b/drivers/staging/otus/zdusb.c
new file mode 100644
index 000000000000..78f1d2224fa1
--- /dev/null
+++ b/drivers/staging/otus/zdusb.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : zdusb.c */
+/* */
+/* Abstract */
+/* This module contains plug and play handling for USB device driver*/
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "usbdrv.h"
+#include "zdusb.h"
+
+int zfLnxAllocAllUrbs(struct usbdrv_private *macp);
+void zfLnxFreeAllUrbs(struct usbdrv_private *macp);
+void zfLnxUnlinkAllUrbs(struct usbdrv_private *macp);
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Atheros 802.11n Wireless LAN adapter");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static const char driver_name[] = "Otus";
+
+/* table of devices that work with this driver */
+static struct usb_device_id zd1221_ids [] = {
+ { USB_DEVICE(VENDOR_ATHR, PRODUCT_AR9170) },
+ { USB_DEVICE(VENDOR_DLINK, PRODUCT_DWA160A) },
+ { USB_DEVICE(0x0846, 0x9010) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, zd1221_ids);
+
+extern u8_t zfLnxInitSetup(struct net_device *dev, struct usbdrv_private *macp);
+extern int usbdrv_close(struct net_device *dev);
+extern u8_t zfLnxClearStructs(struct net_device *dev);
+extern int zfWdsClose(struct net_device *dev);
+extern int zfUnregisterWdsDev(struct net_device* parentDev, u16_t wdsId);
+extern int zfLnxVapClose(struct net_device *dev);
+extern int zfLnxUnregisterVapDev(struct net_device* parentDev, u16_t vapId);
+
+/* WDS */
+extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER];
+
+/* VAP */
+extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER];
+
+static int zfLnxProbe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(interface);
+
+ struct net_device *net = NULL;
+ struct usbdrv_private *macp = NULL;
+ int vendor_id, product_id;
+ int result = 0;
+
+ usb_get_dev(dev);
+
+ vendor_id = dev->descriptor.idVendor;
+ product_id = dev->descriptor.idProduct;
+
+#ifdef HMAC_DEBUG
+ printk(KERN_NOTICE "vendor_id = %04x\n", vendor_id);
+ printk(KERN_NOTICE "product_id = %04x\n", product_id);
+
+ if (dev->speed == USB_SPEED_HIGH)
+ printk(KERN_NOTICE "USB 2.0 Host\n");
+ else
+ printk(KERN_NOTICE "USB 1.1 Host\n");
+#endif
+
+ if (!(macp = kmalloc(sizeof(struct usbdrv_private), GFP_KERNEL)))
+ {
+ printk(KERN_ERR "out of memory allocating device structure\n");
+ result = -ENOMEM;
+ goto fail;
+ }
+
+ /* Zero the memory */
+ memset(macp, 0, sizeof(struct usbdrv_private));
+
+ net = alloc_etherdev(0);
+
+ if (net == NULL)
+ {
+ printk(KERN_ERR "zfLnxProbe: Not able to alloc etherdev struct\n");
+ result = -ENOMEM;
+ goto fail1;
+ }
+
+ strcpy(net->name, "ath%d");
+
+ net->ml_priv = macp; //kernel 2.6
+ macp->udev = dev;
+ macp->device = net;
+
+ /* set up the endpoint information */
+ /* check out the endpoints */
+ macp->interface = interface;
+
+ //init_waitqueue_head(&macp->regSet_wait);
+ //init_waitqueue_head(&macp->iorwRsp_wait);
+ //init_waitqueue_head(&macp->term_wait);
+
+ if (!zfLnxAllocAllUrbs(macp))
+ {
+ result = -ENOMEM;
+ goto fail2;
+ }
+
+ if (!zfLnxInitSetup(net, macp))
+ {
+ result = -EIO;
+ goto fail3;
+ }
+ else
+ {
+ usb_set_intfdata(interface, macp);
+ SET_NETDEV_DEV(net, &interface->dev);
+
+ if (register_netdev(net) != 0)
+ {
+ usb_set_intfdata(interface, NULL);
+ goto fail3;
+ }
+ }
+
+ netif_carrier_off(net);
+ goto done;
+
+fail3:
+ zfLnxFreeAllUrbs(macp);
+fail2:
+ free_netdev(net); //kernel 2.6
+fail1:
+ kfree(macp);
+
+fail:
+ usb_put_dev(dev);
+ macp = NULL;
+
+done:
+ return result;
+}
+
+static void zfLnxDisconnect(struct usb_interface *interface)
+{
+ struct usbdrv_private *macp = (struct usbdrv_private *) usb_get_intfdata(interface);
+
+ printk(KERN_DEBUG "zfLnxDisconnect\n");
+
+ if (!macp)
+ {
+ printk(KERN_ERR "unregistering non-existant device\n");
+ return;
+ }
+
+ if (macp->driver_isolated)
+ {
+ if (macp->device->flags & IFF_UP)
+ usbdrv_close(macp->device);
+ }
+
+#if 0
+ /* Close WDS */
+ //zfWdsClose(wds[0].dev);
+ /* Unregister WDS */
+ //zfUnregisterWdsDev(macp->device, 0);
+
+ /* Close VAP */
+ zfLnxVapClose(vap[0].dev);
+ /* Unregister VAP */
+ zfLnxUnregisterVapDev(macp->device, 0);
+#endif
+
+ zfLnxClearStructs(macp->device);
+
+ unregister_netdev(macp->device);
+
+ usb_put_dev(interface_to_usbdev(interface));
+
+ //printk(KERN_ERR "3. zfLnxUnlinkAllUrbs\n");
+ //zfLnxUnlinkAllUrbs(macp);
+
+ /* Free network interface */
+ free_netdev(macp->device);
+
+ zfLnxFreeAllUrbs(macp);
+ //zfLnxClearStructs(macp->device);
+ kfree(macp);
+ macp = NULL;
+
+ usb_set_intfdata(interface, NULL);
+}
+
+static struct usb_driver zd1221_driver = {
+ .name = driver_name,
+ .probe = zfLnxProbe,
+ .disconnect = zfLnxDisconnect,
+ .id_table = zd1221_ids,
+};
+
+int __init zfLnxIinit(void)
+{
+ printk(KERN_NOTICE "%s - version %s\n", DRIVER_NAME, VERSIONID);
+ return usb_register(&zd1221_driver);
+}
+
+void __exit zfLnxExit(void)
+{
+ usb_deregister(&zd1221_driver);
+}
+
+module_init(zfLnxIinit);
+module_exit(zfLnxExit);
diff --git a/drivers/staging/otus/zdusb.h b/drivers/staging/otus/zdusb.h
new file mode 100644
index 000000000000..656dc212ade5
--- /dev/null
+++ b/drivers/staging/otus/zdusb.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* */
+/* Module Name : zdusb.h */
+/* */
+/* Abstract */
+/* This module contains definitions for USB device driver */
+/* */
+/* NOTES */
+/* Platform dependent. */
+/* */
+/************************************************************************/
+
+#ifndef _ZDUSB_H
+#define _ZDUSB_H
+
+#ifndef DRIVER_NAME
+#define DRIVER_NAME "arusb"
+#endif
+
+#define VERSIONID "0.0.0.999"
+
+/* Define these values to match your device */
+#define VENDOR_ATHR 0x0CF3 //Atheros
+#define PRODUCT_AR9170 0x9170
+
+#define VENDOR_DLINK 0x07D1 //Dlink
+#define PRODUCT_DWA160A 0x3C10
+
+#endif
diff --git a/drivers/staging/panel/Kconfig b/drivers/staging/panel/Kconfig
new file mode 100644
index 000000000000..c4b30f2a549b
--- /dev/null
+++ b/drivers/staging/panel/Kconfig
@@ -0,0 +1,278 @@
+config PANEL
+ tristate "Parallel port LCD/Keypad Panel support"
+ depends on PARPORT
+ ---help---
+ Say Y here if you have an HD44780 or KS-0074 LCD connected to your
+ parallel port. This driver also features 4 and 6-key keypads. The LCD
+ is accessible through the /dev/lcd char device (10, 156), and the
+ keypad through /dev/keypad (10, 185). Both require misc device to be
+ enabled. This code can either be compiled as a module, or linked into
+ the kernel and started at boot. If you don't understand what all this
+ is about, say N.
+
+config PANEL_PARPORT
+ int "Default parallel port number (0=LPT1)"
+ depends on PANEL
+ range 0 255
+ default "0"
+ ---help---
+ This is the index of the parallel port the panel is connected to. One
+ driver instance only supports one parallel port, so if your keypad
+ and LCD are connected to two separate ports, you have to start two
+ modules with different arguments. Numbering starts with '0' for LPT1,
+ and so on.
+
+config PANEL_PROFILE
+ int "Default panel profile (0-5, 0=custom)"
+ depends on PANEL
+ range 0 5
+ default "5"
+ ---help---
+ To ease configuration, the driver supports different configuration
+ profiles for past and recent wirings. These profiles can also be
+ used to define an approximative configuration, completed by a few
+ other options. Here are the profiles :
+
+ 0 = custom (see further)
+ 1 = 2x16 parallel LCD, old keypad
+ 2 = 2x16 serial LCD (KS-0074), new keypad
+ 3 = 2x16 parallel LCD (Hantronix), no keypad
+ 4 = 2x16 parallel LCD (Nexcom NSA1045) with Nexcom's keypad
+ 5 = 2x40 parallel LCD (old one), with old keypad
+
+ Custom configurations allow you to define how your display is
+ wired to the parallel port, and how it works. This is only intended
+ for experts.
+
+config PANEL_KEYPAD
+ depends on PANEL && PANEL_PROFILE="0"
+ int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)"
+ range 0 4
+ default 0
+ ---help---
+ This enables and configures a keypad connected to the parallel port.
+ The keys will be read from character device 10,185. Valid values are :
+
+ 0 : do not enable this driver
+ 1 : old 6 keys keypad
+ 2 : new 6 keys keypad, as used on the server at www.ant-computing.com
+ 3 : Nexcom NSA1045's 4 keys keypad
+
+ New profiles can be described in the driver source. The driver also
+ supports simultaneous keys pressed when the keypad supports them.
+
+config PANEL_LCD
+ depends on PANEL && PANEL_PROFILE="0"
+ int "LCD type (0=none, 1=custom, 2=old //, 3=ks0074, 4=hantronix, 5=Nexcom)"
+ range 0 5
+ default 0
+ ---help---
+ This enables and configures an LCD connected to the parallel port.
+ The driver includes an interpreter for escape codes starting with
+ '\e[L' which are specific to the LCD, and a few ANSI codes. The
+ driver will be registered as character device 10,156, usually
+ under the name '/dev/lcd'. There are a total of 6 supported types :
+
+ 0 : do not enable the driver
+ 1 : custom configuration and wiring (see further)
+ 2 : 2x16 & 2x40 parallel LCD (old wiring)
+ 3 : 2x16 serial LCD (KS-0074 based)
+ 4 : 2x16 parallel LCD (Hantronix wiring)
+ 5 : 2x16 parallel LCD (Nexcom wiring)
+
+ When type '1' is specified, other options will appear to configure
+ more precise aspects (wiring, dimensions, protocol, ...). Please note
+ that those values changed from the 2.4 driver for better consistency.
+
+config PANEL_LCD_HEIGHT
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Number of lines on the LCD (1-2)"
+ range 1 2
+ default 2
+ ---help---
+ This is the number of visible character lines on the LCD in custom profile.
+ It can either be 1 or 2.
+
+config PANEL_LCD_WIDTH
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Number of characters per line on the LCD (1-40)"
+ range 1 40
+ default 40
+ ---help---
+ This is the number of characters per line on the LCD in custom profile.
+ Common values are 16,20,24,40.
+
+config PANEL_LCD_BWIDTH
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Internal LCD line width (1-40, 40 by default)"
+ range 1 40
+ default 40
+ ---help---
+ Most LCDs use a standard controller which supports hardware lines of 40
+ characters, although sometimes only 16, 20 or 24 of them are really wired
+ to the terminal. This results in some non-visible but adressable characters,
+ and is the case for most parallel LCDs. Other LCDs, and some serial ones,
+ however, use the same line width internally as what is visible. The KS0074
+ for example, uses 16 characters per line for 16 visible characters per line.
+
+ This option lets you configure the value used by your LCD in 'custom' profile.
+ If you don't know, put '40' here.
+
+config PANEL_LCD_HWIDTH
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Hardware LCD line width (1-64, 64 by default)"
+ range 1 64
+ default 64
+ ---help---
+ Most LCDs use a single address bit to differentiate line 0 and line 1. Since
+ some of them need to be able to address 40 chars with the lower bits, they
+ often use the immediately superior power of 2, which is 64, to address the
+ next line.
+
+ If you don't know what your LCD uses, in doubt let 16 here for a 2x16, and
+ 64 here for a 2x40.
+
+config PANEL_LCD_CHARSET
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "LCD character set (0=normal, 1=KS0074)"
+ range 0 1
+ default 0
+ ---help---
+ Some controllers such as the KS0074 use a somewhat strange character set
+ where many symbols are at unusual places. The driver knows how to map
+ 'standard' ASCII characters to the character sets used by these controllers.
+ Valid values are :
+
+ 0 : normal (untranslated) character set
+ 1 : KS0074 character set
+
+ If you don't know, use the normal one (0).
+
+config PANEL_LCD_PROTO
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "LCD communication mode (0=parallel 8 bits, 1=serial)"
+ range 0 1
+ default 0
+ ---help---
+ This driver now supports any serial or parallel LCD wired to a parallel
+ port. But before assigning signals, the driver needs to know if it will
+ be driving a serial LCD or a parallel one. Serial LCDs only use 2 wires
+ (SDA/SCL), while parallel ones use 2 or 3 wires for the control signals
+ (E, RS, sometimes RW), and 4 or 8 for the data. Use 0 here for a 8 bits
+ parallel LCD, and 1 for a serial LCD.
+
+config PANEL_LCD_PIN_E
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
+ int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) "
+ range -17 17
+ default 14
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'E'
+ signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'E' pin in custom profile is '14' (AUTOFEED).
+
+config PANEL_LCD_PIN_RS
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
+ int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) "
+ range -17 17
+ default 17
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'RS'
+ signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'RS' pin in custom profile is '17' (SELECT IN).
+
+config PANEL_LCD_PIN_RW
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0"
+ int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) "
+ range -17 17
+ default 16
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'RW'
+ signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'RW' pin in custom profile is '16' (INIT).
+
+config PANEL_LCD_PIN_SCL
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
+ int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) "
+ range -17 17
+ default 1
+ ---help---
+ This describes the number of the parallel port pin to which the serial
+ LCD 'SCL' signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'SCL' pin in custom profile is '1' (STROBE).
+
+config PANEL_LCD_PIN_SDA
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0"
+ int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) "
+ range -17 17
+ default 2
+ ---help---
+ This describes the number of the parallel port pin to which the serial
+ LCD 'SDA' signal has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'SDA' pin in custom profile is '2' (D0).
+
+config PANEL_LCD_PIN_BL
+ depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1"
+ int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) "
+ range -17 17
+ default 0
+ ---help---
+ This describes the number of the parallel port pin to which the LCD 'BL' signal
+ has been connected. It can be :
+
+ 0 : no connection (eg: connected to ground)
+ 1..17 : directly connected to any of these pins on the DB25 plug
+ -1..-17 : connected to the same pin through an inverter (eg: transistor).
+
+ Default for the 'BL' pin in custom profile is '0' (uncontrolled).
+
+config PANEL_CHANGE_MESSAGE
+ depends on PANEL
+ bool "Change LCD initialization message ?"
+ default "n"
+ ---help---
+ This allows you to replace the boot message indicating the kernel version
+ and the driver version with a custom message. This is useful on appliances
+ where a simple 'Starting system' message can be enough to stop a customer
+ from worrying.
+
+ If you say 'Y' here, you'll be able to choose a message yourself. Otherwise,
+ say 'N' and keep the default message with the version.
+
+config PANEL_BOOT_MESSAGE
+ depends on PANEL && PANEL_CHANGE_MESSAGE="y"
+ string "New initialization message"
+ default ""
+ ---help---
+ This allows you to replace the boot message indicating the kernel version
+ and the driver version with a custom message. This is useful on appliances
+ where a simple 'Starting system' message can be enough to stop a customer
+ from worrying.
+
+ An empty message will only clear the display at driver init time. Any other
+ printf()-formatted message is valid with newline and escape codes.
diff --git a/drivers/staging/panel/Makefile b/drivers/staging/panel/Makefile
new file mode 100644
index 000000000000..747c238b82f9
--- /dev/null
+++ b/drivers/staging/panel/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PANEL) += panel.o
diff --git a/drivers/staging/panel/TODO b/drivers/staging/panel/TODO
new file mode 100644
index 000000000000..a4be749bcdfc
--- /dev/null
+++ b/drivers/staging/panel/TODO
@@ -0,0 +1,9 @@
+TODO:
+ - checkpatch.pl cleanups
+ - Lindent
+ - review major/minor usages
+ - review userspace api
+ - see if all of this could be easier done in userspace instead.
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
+Willy Tarreau <willy@meta-x.org>
diff --git a/drivers/staging/panel/lcd-panel-cgram.txt b/drivers/staging/panel/lcd-panel-cgram.txt
new file mode 100644
index 000000000000..f9ceef4322a3
--- /dev/null
+++ b/drivers/staging/panel/lcd-panel-cgram.txt
@@ -0,0 +1,24 @@
+Some LCDs allow you to define up to 8 characters, mapped to ASCII
+characters 0 to 7. The escape code to define a new character is
+'\e[LG' followed by one digit from 0 to 7, representing the character
+number, and up to 8 couples of hex digits terminated by a semi-colon
+(';'). Each couple of digits represents a line, with 1-bits for each
+illuminated pixel with LSB on the right. Lines are numberred from the
+top of the character to the bottom. On a 5x7 matrix, only the 5 lower
+bits of the 7 first bytes are used for each character. If the string
+is incomplete, only complete lines will be redefined. Here are some
+examples :
+
+ printf "\e[LG0010101050D1F0C04;" => 0 = [enter]
+ printf "\e[LG1040E1F0000000000;" => 1 = [up]
+ printf "\e[LG2000000001F0E0400;" => 2 = [down]
+ printf "\e[LG3040E1F001F0E0400;" => 3 = [up-down]
+ printf "\e[LG40002060E1E0E0602;" => 4 = [left]
+ printf "\e[LG500080C0E0F0E0C08;" => 5 = [right]
+ printf "\e[LG60016051516141400;" => 6 = "IP"
+
+ printf "\e[LG00103071F1F070301;" => big speaker
+ printf "\e[LG00002061E1E060200;" => small speaker
+
+Willy
+
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
new file mode 100644
index 000000000000..5ffe269c2382
--- /dev/null
+++ b/drivers/staging/panel/panel.c
@@ -0,0 +1,2193 @@
+/*
+ * Front panel driver for Linux
+ * Copyright (C) 2000-2008, Willy Tarreau <w@1wt.eu>
+ *
+ * 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 code drives an LCD module (/dev/lcd), and a keypad (/dev/keypad)
+ * connected to a parallel printer port.
+ *
+ * The LCD module may either be an HD44780-like 8-bit parallel LCD, or a 1-bit
+ * serial module compatible with Samsung's KS0074. The pins may be connected in
+ * any combination, everything is programmable.
+ *
+ * The keypad consists in a matrix of push buttons connecting input pins to
+ * data output pins or to the ground. The combinations have to be hard-coded
+ * in the driver, though several profiles exist and adding new ones is easy.
+ *
+ * Several profiles are provided for commonly found LCD+keypad modules on the
+ * market, such as those found in Nexcom's appliances.
+ *
+ * FIXME:
+ * - the initialization/deinitialization process is very dirty and should
+ * be rewritten. It may even be buggy.
+ *
+ * TODO:
+ * - document 24 keys keyboard (3 rows of 8 cols, 32 diodes + 2 inputs)
+ * - make the LCD a part of a virtual screen of Vx*Vy
+ * - make the inputs list smp-safe
+ * - change the keyboard to a double mapping : signals -> key_id -> values
+ * so that applications can change values without knowing signals
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/parport.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/utsrelease.h>
+
+#include <linux/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define LCD_MINOR 156
+#define KEYPAD_MINOR 185
+
+#define PANEL_VERSION "0.9.5"
+
+#define LCD_MAXBYTES 256 /* max burst write */
+
+#define KEYPAD_BUFFER 64
+#define INPUT_POLL_TIME (HZ/50) /* poll the keyboard this every second */
+#define KEYPAD_REP_START (10) /* a key starts to repeat after this times INPUT_POLL_TIME */
+#define KEYPAD_REP_DELAY (2) /* a key repeats this times INPUT_POLL_TIME */
+
+#define FLASH_LIGHT_TEMPO (200) /* keep the light on this times INPUT_POLL_TIME for each flash */
+
+/* converts an r_str() input to an active high, bits string : 000BAOSE */
+#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3)
+
+#define PNL_PBUSY 0x80 /* inverted input, active low */
+#define PNL_PACK 0x40 /* direct input, active low */
+#define PNL_POUTPA 0x20 /* direct input, active high */
+#define PNL_PSELECD 0x10 /* direct input, active high */
+#define PNL_PERRORP 0x08 /* direct input, active low */
+
+#define PNL_PBIDIR 0x20 /* bi-directional ports */
+#define PNL_PINTEN 0x10 /* high to read data in or-ed with data out */
+#define PNL_PSELECP 0x08 /* inverted output, active low */
+#define PNL_PINITP 0x04 /* direct output, active low */
+#define PNL_PAUTOLF 0x02 /* inverted output, active low */
+#define PNL_PSTROBE 0x01 /* inverted output */
+
+#define PNL_PD0 0x01
+#define PNL_PD1 0x02
+#define PNL_PD2 0x04
+#define PNL_PD3 0x08
+#define PNL_PD4 0x10
+#define PNL_PD5 0x20
+#define PNL_PD6 0x40
+#define PNL_PD7 0x80
+
+#define PIN_NONE 0
+#define PIN_STROBE 1
+#define PIN_D0 2
+#define PIN_D1 3
+#define PIN_D2 4
+#define PIN_D3 5
+#define PIN_D4 6
+#define PIN_D5 7
+#define PIN_D6 8
+#define PIN_D7 9
+#define PIN_AUTOLF 14
+#define PIN_INITP 16
+#define PIN_SELECP 17
+#define PIN_NOT_SET 127
+
+#define LCD_FLAG_S 0x0001
+#define LCD_FLAG_ID 0x0002
+#define LCD_FLAG_B 0x0004 /* blink on */
+#define LCD_FLAG_C 0x0008 /* cursor on */
+#define LCD_FLAG_D 0x0010 /* display on */
+#define LCD_FLAG_F 0x0020 /* large font mode */
+#define LCD_FLAG_N 0x0040 /* 2-rows mode */
+#define LCD_FLAG_L 0x0080 /* backlight enabled */
+
+#define LCD_ESCAPE_LEN 24 /* 24 chars max for an LCD escape command */
+#define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */
+
+/* macros to simplify use of the parallel port */
+#define r_ctr(x) (parport_read_control((x)->port))
+#define r_dtr(x) (parport_read_data((x)->port))
+#define r_str(x) (parport_read_status((x)->port))
+#define w_ctr(x, y) do { parport_write_control((x)->port, (y)); } while (0)
+#define w_dtr(x, y) do { parport_write_data((x)->port, (y)); } while (0)
+
+/* this defines which bits are to be used and which ones to be ignored */
+static __u8 scan_mask_o; /* logical or of the output bits involved in the scan matrix */
+static __u8 scan_mask_i; /* logical or of the input bits involved in the scan matrix */
+
+typedef __u64 pmask_t;
+
+enum input_type {
+ INPUT_TYPE_STD,
+ INPUT_TYPE_KBD,
+};
+
+enum input_state {
+ INPUT_ST_LOW,
+ INPUT_ST_RISING,
+ INPUT_ST_HIGH,
+ INPUT_ST_FALLING,
+};
+
+struct logical_input {
+ struct list_head list;
+ pmask_t mask;
+ pmask_t value;
+ enum input_type type;
+ enum input_state state;
+ __u8 rise_time, fall_time;
+ __u8 rise_timer, fall_timer, high_timer;
+
+ union {
+ struct { /* this structure is valid when type == INPUT_TYPE_STD */
+ void (*press_fct) (int);
+ void (*release_fct) (int);
+ int press_data;
+ int release_data;
+ } std;
+ struct { /* this structure is valid when type == INPUT_TYPE_KBD */
+ /* strings can be full-length (ie. non null-terminated) */
+ char press_str[sizeof(void *) + sizeof(int)];
+ char repeat_str[sizeof(void *) + sizeof(int)];
+ char release_str[sizeof(void *) + sizeof(int)];
+ } kbd;
+ } u;
+};
+
+LIST_HEAD(logical_inputs); /* list of all defined logical inputs */
+
+/* physical contacts history
+ * Physical contacts are a 45 bits string of 9 groups of 5 bits each.
+ * The 8 lower groups correspond to output bits 0 to 7, and the 9th group
+ * corresponds to the ground.
+ * Within each group, bits are stored in the same order as read on the port :
+ * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0).
+ * So, each __u64 (or pmask_t) is represented like this :
+ * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE
+ * <-----unused------><gnd><d07><d06><d05><d04><d03><d02><d01><d00>
+ */
+static pmask_t phys_read; /* what has just been read from the I/O ports */
+static pmask_t phys_read_prev; /* previous phys_read */
+static pmask_t phys_curr; /* stabilized phys_read (phys_read|phys_read_prev) */
+static pmask_t phys_prev; /* previous phys_curr */
+static char inputs_stable; /* 0 means that at least one logical signal needs be computed */
+
+/* these variables are specific to the keypad */
+static char keypad_buffer[KEYPAD_BUFFER];
+static int keypad_buflen;
+static int keypad_start;
+static char keypressed;
+static wait_queue_head_t keypad_read_wait;
+
+/* lcd-specific variables */
+static unsigned long int lcd_flags; /* contains the LCD config state */
+static unsigned long int lcd_addr_x; /* contains the LCD X offset */
+static unsigned long int lcd_addr_y; /* contains the LCD Y offset */
+static char lcd_escape[LCD_ESCAPE_LEN + 1]; /* current escape sequence, 0 terminated */
+static int lcd_escape_len = -1; /* not in escape state. >=0 = escape cmd len */
+
+/*
+ * Bit masks to convert LCD signals to parallel port outputs.
+ * _d_ are values for data port, _c_ are for control port.
+ * [0] = signal OFF, [1] = signal ON, [2] = mask
+ */
+#define BIT_CLR 0
+#define BIT_SET 1
+#define BIT_MSK 2
+#define BIT_STATES 3
+/*
+ * one entry for each bit on the LCD
+ */
+#define LCD_BIT_E 0
+#define LCD_BIT_RS 1
+#define LCD_BIT_RW 2
+#define LCD_BIT_BL 3
+#define LCD_BIT_CL 4
+#define LCD_BIT_DA 5
+#define LCD_BITS 6
+
+/*
+ * each bit can be either connected to a DATA or CTRL port
+ */
+#define LCD_PORT_C 0
+#define LCD_PORT_D 1
+#define LCD_PORTS 2
+
+static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES];
+
+/*
+ * LCD protocols
+ */
+#define LCD_PROTO_PARALLEL 0
+#define LCD_PROTO_SERIAL 1
+
+/*
+ * LCD character sets
+ */
+#define LCD_CHARSET_NORMAL 0
+#define LCD_CHARSET_KS0074 1
+
+/*
+ * LCD types
+ */
+#define LCD_TYPE_NONE 0
+#define LCD_TYPE_OLD 1
+#define LCD_TYPE_KS0074 2
+#define LCD_TYPE_HANTRONIX 3
+#define LCD_TYPE_NEXCOM 4
+#define LCD_TYPE_CUSTOM 5
+
+/*
+ * keypad types
+ */
+#define KEYPAD_TYPE_NONE 0
+#define KEYPAD_TYPE_OLD 1
+#define KEYPAD_TYPE_NEW 2
+#define KEYPAD_TYPE_NEXCOM 3
+
+/*
+ * panel profiles
+ */
+#define PANEL_PROFILE_CUSTOM 0
+#define PANEL_PROFILE_OLD 1
+#define PANEL_PROFILE_NEW 2
+#define PANEL_PROFILE_HANTRONIX 3
+#define PANEL_PROFILE_NEXCOM 4
+#define PANEL_PROFILE_LARGE 5
+
+/*
+ * Construct custom config from the kernel's configuration
+ */
+#define DEFAULT_PROFILE PANEL_PROFILE_LARGE
+#define DEFAULT_PARPORT 0
+#define DEFAULT_LCD LCD_TYPE_OLD
+#define DEFAULT_KEYPAD KEYPAD_TYPE_OLD
+#define DEFAULT_LCD_WIDTH 40
+#define DEFAULT_LCD_BWIDTH 40
+#define DEFAULT_LCD_HWIDTH 64
+#define DEFAULT_LCD_HEIGHT 2
+#define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL
+
+#define DEFAULT_LCD_PIN_E PIN_AUTOLF
+#define DEFAULT_LCD_PIN_RS PIN_SELECP
+#define DEFAULT_LCD_PIN_RW PIN_INITP
+#define DEFAULT_LCD_PIN_SCL PIN_STROBE
+#define DEFAULT_LCD_PIN_SDA PIN_D0
+#define DEFAULT_LCD_PIN_BL PIN_NOT_SET
+#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL
+
+#ifdef CONFIG_PANEL_PROFILE
+#undef DEFAULT_PROFILE
+#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE
+#endif
+
+#ifdef CONFIG_PANEL_PARPORT
+#undef DEFAULT_PARPORT
+#define DEFAULT_PARPORT CONFIG_PANEL_PARPORT
+#endif
+
+#if DEFAULT_PROFILE == 0 /* custom */
+#ifdef CONFIG_PANEL_KEYPAD
+#undef DEFAULT_KEYPAD
+#define DEFAULT_KEYPAD CONFIG_PANEL_KEYPAD
+#endif
+
+#ifdef CONFIG_PANEL_LCD
+#undef DEFAULT_LCD
+#define DEFAULT_LCD CONFIG_PANEL_LCD
+#endif
+
+#ifdef CONFIG_PANEL_LCD_WIDTH
+#undef DEFAULT_LCD_WIDTH
+#define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH
+#endif
+
+#ifdef CONFIG_PANEL_LCD_BWIDTH
+#undef DEFAULT_LCD_BWIDTH
+#define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH
+#endif
+
+#ifdef CONFIG_PANEL_LCD_HWIDTH
+#undef DEFAULT_LCD_HWIDTH
+#define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH
+#endif
+
+#ifdef CONFIG_PANEL_LCD_HEIGHT
+#undef DEFAULT_LCD_HEIGHT
+#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT
+#endif
+
+#ifdef CONFIG_PANEL_LCD_PROTO
+#undef DEFAULT_LCD_PROTO
+#define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO
+#endif
+
+#ifdef CONFIG_PANEL_LCD_PIN_E
+#undef DEFAULT_LCD_PIN_E
+#define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E
+#endif
+
+#ifdef CONFIG_PANEL_LCD_PIN_RS
+#undef DEFAULT_LCD_PIN_RS
+#define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS
+#endif
+
+#ifdef CONFIG_PANEL_LCD_PIN_RW
+#undef DEFAULT_LCD_PIN_RW
+#define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW
+#endif
+
+#ifdef CONFIG_PANEL_LCD_PIN_SCL
+#undef DEFAULT_LCD_PIN_SCL
+#define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL
+#endif
+
+#ifdef CONFIG_PANEL_LCD_PIN_SDA
+#undef DEFAULT_LCD_PIN_SDA
+#define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA
+#endif
+
+#ifdef CONFIG_PANEL_LCD_PIN_BL
+#undef DEFAULT_LCD_PIN_BL
+#define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL
+#endif
+
+#ifdef CONFIG_PANEL_LCD_CHARSET
+#undef DEFAULT_LCD_CHARSET
+#define DEFAULT_LCD_CHARSET
+#endif
+
+#endif /* DEFAULT_PROFILE == 0 */
+
+/* global variables */
+static int keypad_open_cnt; /* #times opened */
+static int lcd_open_cnt; /* #times opened */
+static struct pardevice *pprt;
+
+static int lcd_initialized;
+static int keypad_initialized;
+
+static int light_tempo;
+
+static char lcd_must_clear;
+static char lcd_left_shift;
+static char init_in_progress;
+
+static void (*lcd_write_cmd) (int);
+static void (*lcd_write_data) (int);
+static void (*lcd_clear_fast) (void);
+
+static DEFINE_SPINLOCK(pprt_lock);
+static struct timer_list scan_timer;
+
+MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver");
+
+static int parport = -1;
+module_param(parport, int, 0000);
+MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)");
+
+static int lcd_height = -1;
+module_param(lcd_height, int, 0000);
+MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD");
+
+static int lcd_width = -1;
+module_param(lcd_width, int, 0000);
+MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD");
+
+static int lcd_bwidth = -1; /* internal buffer width (usually 40) */
+module_param(lcd_bwidth, int, 0000);
+MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)");
+
+static int lcd_hwidth = -1; /* hardware buffer width (usually 64) */
+module_param(lcd_hwidth, int, 0000);
+MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)");
+
+static int lcd_enabled = -1;
+module_param(lcd_enabled, int, 0000);
+MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead");
+
+static int keypad_enabled = -1;
+module_param(keypad_enabled, int, 0000);
+MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead");
+
+static int lcd_type = -1;
+module_param(lcd_type, int, 0000);
+MODULE_PARM_DESC(lcd_type,
+ "LCD type: 0=none, 1=old //, 2=serial ks0074, 3=hantronix //, 4=nexcom //, 5=compiled-in");
+
+static int lcd_proto = -1;
+module_param(lcd_proto, int, 0000);
+MODULE_PARM_DESC(lcd_proto, "LCD communication: 0=parallel (//), 1=serial");
+
+static int lcd_charset = -1;
+module_param(lcd_charset, int, 0000);
+MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074");
+
+static int keypad_type = -1;
+module_param(keypad_type, int, 0000);
+MODULE_PARM_DESC(keypad_type,
+ "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys");
+
+static int profile = DEFAULT_PROFILE;
+module_param(profile, int, 0000);
+MODULE_PARM_DESC(profile,
+ "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; 4=16x2 nexcom; default=40x2, old kp");
+
+/*
+ * These are the parallel port pins the LCD control signals are connected to.
+ * Set this to 0 if the signal is not used. Set it to its opposite value
+ * (negative) if the signal is negated. -MAXINT is used to indicate that the
+ * pin has not been explicitly specified.
+ *
+ * WARNING! no check will be performed about collisions with keypad !
+ */
+
+static int lcd_e_pin = PIN_NOT_SET;
+module_param(lcd_e_pin, int, 0000);
+MODULE_PARM_DESC(lcd_e_pin,
+ "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)");
+
+static int lcd_rs_pin = PIN_NOT_SET;
+module_param(lcd_rs_pin, int, 0000);
+MODULE_PARM_DESC(lcd_rs_pin,
+ "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)");
+
+static int lcd_rw_pin = PIN_NOT_SET;
+module_param(lcd_rw_pin, int, 0000);
+MODULE_PARM_DESC(lcd_rw_pin,
+ "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)");
+
+static int lcd_bl_pin = PIN_NOT_SET;
+module_param(lcd_bl_pin, int, 0000);
+MODULE_PARM_DESC(lcd_bl_pin,
+ "# of the // port pin connected to LCD backlight, with polarity (-17..17)");
+
+static int lcd_da_pin = PIN_NOT_SET;
+module_param(lcd_da_pin, int, 0000);
+MODULE_PARM_DESC(lcd_da_pin,
+ "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)");
+
+static int lcd_cl_pin = PIN_NOT_SET;
+module_param(lcd_cl_pin, int, 0000);
+MODULE_PARM_DESC(lcd_cl_pin,
+ "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)");
+
+static unsigned char *lcd_char_conv;
+
+/* for some LCD drivers (ks0074) we need a charset conversion table. */
+static unsigned char lcd_char_conv_ks0074[256] = {
+ /* 0|8 1|9 2|A 3|B 4|C 5|D 6|E 7|F */
+ /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ /* 0x08 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ /* 0x10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ /* 0x18 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ /* 0x20 */ 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27,
+ /* 0x28 */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ /* 0x30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ /* 0x38 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ /* 0x40 */ 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ /* 0x48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ /* 0x50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ /* 0x58 */ 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4,
+ /* 0x60 */ 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ /* 0x68 */ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ /* 0x70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ /* 0x78 */ 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20,
+ /* 0x80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /* 0x88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ /* 0x90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ /* 0x98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ /* 0xA0 */ 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f,
+ /* 0xA8 */ 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96,
+ /* 0xB0 */ 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd,
+ /* 0xB8 */ 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60,
+ /* 0xC0 */ 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9,
+ /* 0xC8 */ 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3,
+ /* 0xD0 */ 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78,
+ /* 0xD8 */ 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe,
+ /* 0xE0 */ 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8,
+ /* 0xE8 */ 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69,
+ /* 0xF0 */ 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25,
+ /* 0xF8 */ 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79,
+};
+
+char old_keypad_profile[][4][9] = {
+ {"S0", "Left\n", "Left\n", ""},
+ {"S1", "Down\n", "Down\n", ""},
+ {"S2", "Up\n", "Up\n", ""},
+ {"S3", "Right\n", "Right\n", ""},
+ {"S4", "Esc\n", "Esc\n", ""},
+ {"S5", "Ret\n", "Ret\n", ""},
+ {"", "", "", ""}
+};
+
+/* signals, press, repeat, release */
+char new_keypad_profile[][4][9] = {
+ {"S0", "Left\n", "Left\n", ""},
+ {"S1", "Down\n", "Down\n", ""},
+ {"S2", "Up\n", "Up\n", ""},
+ {"S3", "Right\n", "Right\n", ""},
+ {"S4s5", "", "Esc\n", "Esc\n"},
+ {"s4S5", "", "Ret\n", "Ret\n"},
+ {"S4S5", "Help\n", "", ""},
+ /* add new signals above this line */
+ {"", "", "", ""}
+};
+
+/* signals, press, repeat, release */
+char nexcom_keypad_profile[][4][9] = {
+ {"a-p-e-", "Down\n", "Down\n", ""},
+ {"a-p-E-", "Ret\n", "Ret\n", ""},
+ {"a-P-E-", "Esc\n", "Esc\n", ""},
+ {"a-P-e-", "Up\n", "Up\n", ""},
+ /* add new signals above this line */
+ {"", "", "", ""}
+};
+
+static char (*keypad_profile)[4][9] = old_keypad_profile;
+
+/* FIXME: this should be converted to a bit array containing signals states */
+static struct {
+ unsigned char e; /* parallel LCD E (data latch on falling edge) */
+ unsigned char rs; /* parallel LCD RS (0 = cmd, 1 = data) */
+ unsigned char rw; /* parallel LCD R/W (0 = W, 1 = R) */
+ unsigned char bl; /* parallel LCD backlight (0 = off, 1 = on) */
+ unsigned char cl; /* serial LCD clock (latch on rising edge) */
+ unsigned char da; /* serial LCD data */
+} bits;
+
+static void init_scan_timer(void);
+
+/* sets data port bits according to current signals values */
+static int set_data_bits(void)
+{
+ int val, bit;
+
+ val = r_dtr(pprt);
+ for (bit = 0; bit < LCD_BITS; bit++)
+ val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK];
+
+ val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e]
+ | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs]
+ | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw]
+ | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl]
+ | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl]
+ | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da];
+
+ w_dtr(pprt, val);
+ return val;
+}
+
+/* sets ctrl port bits according to current signals values */
+static int set_ctrl_bits(void)
+{
+ int val, bit;
+
+ val = r_ctr(pprt);
+ for (bit = 0; bit < LCD_BITS; bit++)
+ val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK];
+
+ val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e]
+ | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs]
+ | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw]
+ | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl]
+ | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl]
+ | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da];
+
+ w_ctr(pprt, val);
+ return val;
+}
+
+/* sets ctrl & data port bits according to current signals values */
+static void set_bits(void)
+{
+ set_data_bits();
+ set_ctrl_bits();
+}
+
+/*
+ * Converts a parallel port pin (from -25 to 25) to data and control ports
+ * masks, and data and control port bits. The signal will be considered
+ * unconnected if it's on pin 0 or an invalid pin (<-25 or >25).
+ *
+ * Result will be used this way :
+ * out(dport, in(dport) & d_val[2] | d_val[signal_state])
+ * out(cport, in(cport) & c_val[2] | c_val[signal_state])
+ */
+void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val)
+{
+ int d_bit, c_bit, inv;
+
+ d_val[0] = c_val[0] = d_val[1] = c_val[1] = 0;
+ d_val[2] = c_val[2] = 0xFF;
+
+ if (pin == 0)
+ return;
+
+ inv = (pin < 0);
+ if (inv)
+ pin = -pin;
+
+ d_bit = c_bit = 0;
+
+ switch (pin) {
+ case PIN_STROBE: /* strobe, inverted */
+ c_bit = PNL_PSTROBE;
+ inv = !inv;
+ break;
+ case PIN_D0...PIN_D7: /* D0 - D7 = 2 - 9 */
+ d_bit = 1 << (pin - 2);
+ break;
+ case PIN_AUTOLF: /* autofeed, inverted */
+ c_bit = PNL_PAUTOLF;
+ inv = !inv;
+ break;
+ case PIN_INITP: /* init, direct */
+ c_bit = PNL_PINITP;
+ break;
+ case PIN_SELECP: /* select_in, inverted */
+ c_bit = PNL_PSELECP;
+ inv = !inv;
+ break;
+ default: /* unknown pin, ignore */
+ break;
+ }
+
+ if (c_bit) {
+ c_val[2] &= ~c_bit;
+ c_val[!inv] = c_bit;
+ } else if (d_bit) {
+ d_val[2] &= ~d_bit;
+ d_val[!inv] = d_bit;
+ }
+}
+
+/* sleeps that many milliseconds with a reschedule */
+static void long_sleep(int ms)
+{
+
+ if (in_interrupt())
+ mdelay(ms);
+ else {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout((ms * HZ + 999) / 1000);
+ }
+}
+
+/* send a serial byte to the LCD panel. The caller is responsible for locking if needed. */
+static void lcd_send_serial(int byte)
+{
+ int bit;
+
+ /* the data bit is set on D0, and the clock on STROBE.
+ * LCD reads D0 on STROBE's rising edge.
+ */
+ for (bit = 0; bit < 8; bit++) {
+ bits.cl = BIT_CLR; /* CLK low */
+ set_bits();
+ bits.da = byte & 1;
+ set_bits();
+ udelay(2); /* maintain the data during 2 us before CLK up */
+ bits.cl = BIT_SET; /* CLK high */
+ set_bits();
+ udelay(1); /* maintain the strobe during 1 us */
+ byte >>= 1;
+ }
+}
+
+/* turn the backlight on or off */
+static void lcd_backlight(int on)
+{
+ if (lcd_bl_pin == PIN_NONE)
+ return;
+
+ /* The backlight is activated by seting the AUTOFEED line to +5V */
+ spin_lock(&pprt_lock);
+ bits.bl = on;
+ set_bits();
+ spin_unlock(&pprt_lock);
+}
+
+/* send a command to the LCD panel in serial mode */
+static void lcd_write_cmd_s(int cmd)
+{
+ spin_lock(&pprt_lock);
+ lcd_send_serial(0x1F); /* R/W=W, RS=0 */
+ lcd_send_serial(cmd & 0x0F);
+ lcd_send_serial((cmd >> 4) & 0x0F);
+ udelay(40); /* the shortest command takes at least 40 us */
+ spin_unlock(&pprt_lock);
+}
+
+/* send data to the LCD panel in serial mode */
+static void lcd_write_data_s(int data)
+{
+ spin_lock(&pprt_lock);
+ lcd_send_serial(0x5F); /* R/W=W, RS=1 */
+ lcd_send_serial(data & 0x0F);
+ lcd_send_serial((data >> 4) & 0x0F);
+ udelay(40); /* the shortest data takes at least 40 us */
+ spin_unlock(&pprt_lock);
+}
+
+/* send a command to the LCD panel in 8 bits parallel mode */
+static void lcd_write_cmd_p8(int cmd)
+{
+ spin_lock(&pprt_lock);
+ /* present the data to the data port */
+ w_dtr(pprt, cmd);
+ udelay(20); /* maintain the data during 20 us before the strobe */
+
+ bits.e = BIT_SET;
+ bits.rs = BIT_CLR;
+ bits.rw = BIT_CLR;
+ set_ctrl_bits();
+
+ udelay(40); /* maintain the strobe during 40 us */
+
+ bits.e = BIT_CLR;
+ set_ctrl_bits();
+
+ udelay(120); /* the shortest command takes at least 120 us */
+ spin_unlock(&pprt_lock);
+}
+
+/* send data to the LCD panel in 8 bits parallel mode */
+static void lcd_write_data_p8(int data)
+{
+ spin_lock(&pprt_lock);
+ /* present the data to the data port */
+ w_dtr(pprt, data);
+ udelay(20); /* maintain the data during 20 us before the strobe */
+
+ bits.e = BIT_SET;
+ bits.rs = BIT_SET;
+ bits.rw = BIT_CLR;
+ set_ctrl_bits();
+
+ udelay(40); /* maintain the strobe during 40 us */
+
+ bits.e = BIT_CLR;
+ set_ctrl_bits();
+
+ udelay(45); /* the shortest data takes at least 45 us */
+ spin_unlock(&pprt_lock);
+}
+
+static void lcd_gotoxy(void)
+{
+ lcd_write_cmd(0x80 /* set DDRAM address */
+ | (lcd_addr_y ? lcd_hwidth : 0)
+ /* we force the cursor to stay at the end of the line if it wants to go farther */
+ | ((lcd_addr_x < lcd_bwidth) ? lcd_addr_x &
+ (lcd_hwidth - 1) : lcd_bwidth - 1));
+}
+
+static void lcd_print(char c)
+{
+ if (lcd_addr_x < lcd_bwidth) {
+ if (lcd_char_conv != NULL)
+ c = lcd_char_conv[(unsigned char)c];
+ lcd_write_data(c);
+ lcd_addr_x++;
+ }
+ /* prevents the cursor from wrapping onto the next line */
+ if (lcd_addr_x == lcd_bwidth)
+ lcd_gotoxy();
+}
+
+/* fills the display with spaces and resets X/Y */
+static void lcd_clear_fast_s(void)
+{
+ int pos;
+ lcd_addr_x = lcd_addr_y = 0;
+ lcd_gotoxy();
+
+ spin_lock(&pprt_lock);
+ for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) {
+ lcd_send_serial(0x5F); /* R/W=W, RS=1 */
+ lcd_send_serial(' ' & 0x0F);
+ lcd_send_serial((' ' >> 4) & 0x0F);
+ udelay(40); /* the shortest data takes at least 40 us */
+ }
+ spin_unlock(&pprt_lock);
+
+ lcd_addr_x = lcd_addr_y = 0;
+ lcd_gotoxy();
+}
+
+/* fills the display with spaces and resets X/Y */
+static void lcd_clear_fast_p8(void)
+{
+ int pos;
+ lcd_addr_x = lcd_addr_y = 0;
+ lcd_gotoxy();
+
+ spin_lock(&pprt_lock);
+ for (pos = 0; pos < lcd_height * lcd_hwidth; pos++) {
+ /* present the data to the data port */
+ w_dtr(pprt, ' ');
+ udelay(20); /* maintain the data during 20 us before the strobe */
+
+ bits.e = BIT_SET;
+ bits.rs = BIT_SET;
+ bits.rw = BIT_CLR;
+ set_ctrl_bits();
+
+ udelay(40); /* maintain the strobe during 40 us */
+
+ bits.e = BIT_CLR;
+ set_ctrl_bits();
+
+ udelay(45); /* the shortest data takes at least 45 us */
+ }
+ spin_unlock(&pprt_lock);
+
+ lcd_addr_x = lcd_addr_y = 0;
+ lcd_gotoxy();
+}
+
+/* clears the display and resets X/Y */
+static void lcd_clear_display(void)
+{
+ lcd_write_cmd(0x01); /* clear display */
+ lcd_addr_x = lcd_addr_y = 0;
+ /* we must wait a few milliseconds (15) */
+ long_sleep(15);
+}
+
+static void lcd_init_display(void)
+{
+
+ lcd_flags = ((lcd_height > 1) ? LCD_FLAG_N : 0)
+ | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B;
+
+ long_sleep(20); /* wait 20 ms after power-up for the paranoid */
+
+ lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */
+ long_sleep(10);
+ lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */
+ long_sleep(10);
+ lcd_write_cmd(0x30); /* 8bits, 1 line, small fonts */
+ long_sleep(10);
+
+ lcd_write_cmd(0x30 /* set font height and lines number */
+ | ((lcd_flags & LCD_FLAG_F) ? 4 : 0)
+ | ((lcd_flags & LCD_FLAG_N) ? 8 : 0)
+ );
+ long_sleep(10);
+
+ lcd_write_cmd(0x08); /* display off, cursor off, blink off */
+ long_sleep(10);
+
+ lcd_write_cmd(0x08 /* set display mode */
+ | ((lcd_flags & LCD_FLAG_D) ? 4 : 0)
+ | ((lcd_flags & LCD_FLAG_C) ? 2 : 0)
+ | ((lcd_flags & LCD_FLAG_B) ? 1 : 0)
+ );
+
+ lcd_backlight((lcd_flags & LCD_FLAG_L) ? 1 : 0);
+
+ long_sleep(10);
+
+ lcd_write_cmd(0x06); /* entry mode set : increment, cursor shifting */
+
+ lcd_clear_display();
+}
+
+/*
+ * These are the file operation function for user access to /dev/lcd
+ * This function can also be called from inside the kernel, by
+ * setting file and ppos to NULL.
+ *
+ */
+
+static ssize_t lcd_write(struct file *file,
+ const char *buf, size_t count, loff_t *ppos)
+{
+
+ const char *tmp = buf;
+ char c;
+
+ for (; count-- > 0; (ppos ? (*ppos)++ : 0), ++tmp) {
+ if (!in_interrupt() && (((count + 1) & 0x1f) == 0))
+ schedule(); /* let's be a little nice with other processes that need some CPU */
+
+ if (ppos == NULL && file == NULL)
+ c = *tmp; /* let's not use get_user() from the kernel ! */
+ else if (get_user(c, tmp))
+ return -EFAULT;
+
+ /* first, we'll test if we're in escape mode */
+ if ((c != '\n') && lcd_escape_len >= 0) { /* yes, let's add this char to the buffer */
+ lcd_escape[lcd_escape_len++] = c;
+ lcd_escape[lcd_escape_len] = 0;
+ } else {
+ lcd_escape_len = -1; /* aborts any previous escape sequence */
+
+ switch (c) {
+ case LCD_ESCAPE_CHAR: /* start of an escape sequence */
+ lcd_escape_len = 0;
+ lcd_escape[lcd_escape_len] = 0;
+ break;
+ case '\b': /* go back one char and clear it */
+ if (lcd_addr_x > 0) {
+ if (lcd_addr_x < lcd_bwidth) /* check if we're not at the end of the line */
+ lcd_write_cmd(0x10); /* back one char */
+ lcd_addr_x--;
+ }
+ lcd_write_data(' '); /* replace with a space */
+ lcd_write_cmd(0x10); /* back one char again */
+ break;
+ case '\014': /* quickly clear the display */
+ lcd_clear_fast();
+ break;
+ case '\n': /* flush the remainder of the current line and go to the
+ beginning of the next line */
+ for (; lcd_addr_x < lcd_bwidth; lcd_addr_x++)
+ lcd_write_data(' ');
+ lcd_addr_x = 0;
+ lcd_addr_y = (lcd_addr_y + 1) % lcd_height;
+ lcd_gotoxy();
+ break;
+ case '\r': /* go to the beginning of the same line */
+ lcd_addr_x = 0;
+ lcd_gotoxy();
+ break;
+ case '\t': /* print a space instead of the tab */
+ lcd_print(' ');
+ break;
+ default: /* simply print this char */
+ lcd_print(c);
+ break;
+ }
+ }
+
+ /* now we'll see if we're in an escape mode and if the current
+ escape sequence can be understood.
+ */
+ if (lcd_escape_len >= 2) { /* minimal length for an escape command */
+ int processed = 0; /* 1 means the command has been processed */
+
+ if (!strcmp(lcd_escape, "[2J")) { /* Clear the display */
+ lcd_clear_fast(); /* clear display */
+ processed = 1;
+ } else if (!strcmp(lcd_escape, "[H")) { /* Cursor to home */
+ lcd_addr_x = lcd_addr_y = 0;
+ lcd_gotoxy();
+ processed = 1;
+ }
+ /* codes starting with ^[[L */
+ else if ((lcd_escape_len >= 3) &&
+ (lcd_escape[0] == '[') && (lcd_escape[1] == 'L')) { /* LCD special codes */
+
+ char *esc = lcd_escape + 2;
+ int oldflags = lcd_flags;
+
+ /* check for display mode flags */
+ switch (*esc) {
+ case 'D': /* Display ON */
+ lcd_flags |= LCD_FLAG_D;
+ processed = 1;
+ break;
+ case 'd': /* Display OFF */
+ lcd_flags &= ~LCD_FLAG_D;
+ processed = 1;
+ break;
+ case 'C': /* Cursor ON */
+ lcd_flags |= LCD_FLAG_C;
+ processed = 1;
+ break;
+ case 'c': /* Cursor OFF */
+ lcd_flags &= ~LCD_FLAG_C;
+ processed = 1;
+ break;
+ case 'B': /* Blink ON */
+ lcd_flags |= LCD_FLAG_B;
+ processed = 1;
+ break;
+ case 'b': /* Blink OFF */
+ lcd_flags &= ~LCD_FLAG_B;
+ processed = 1;
+ break;
+ case '+': /* Back light ON */
+ lcd_flags |= LCD_FLAG_L;
+ processed = 1;
+ break;
+ case '-': /* Back light OFF */
+ lcd_flags &= ~LCD_FLAG_L;
+ processed = 1;
+ break;
+ case '*': /* flash back light using the keypad timer */
+ if (scan_timer.function != NULL) {
+ if (light_tempo == 0
+ && ((lcd_flags & LCD_FLAG_L)
+ == 0))
+ lcd_backlight(1);
+ light_tempo = FLASH_LIGHT_TEMPO;
+ }
+ processed = 1;
+ break;
+ case 'f': /* Small Font */
+ lcd_flags &= ~LCD_FLAG_F;
+ processed = 1;
+ break;
+ case 'F': /* Large Font */
+ lcd_flags |= LCD_FLAG_F;
+ processed = 1;
+ break;
+ case 'n': /* One Line */
+ lcd_flags &= ~LCD_FLAG_N;
+ processed = 1;
+ break;
+ case 'N': /* Two Lines */
+ lcd_flags |= LCD_FLAG_N;
+ break;
+
+ case 'l': /* Shift Cursor Left */
+ if (lcd_addr_x > 0) {
+ if (lcd_addr_x < lcd_bwidth)
+ lcd_write_cmd(0x10); /* back one char if not at end of line */
+ lcd_addr_x--;
+ }
+ processed = 1;
+ break;
+
+ case 'r': /* shift cursor right */
+ if (lcd_addr_x < lcd_width) {
+ if (lcd_addr_x < (lcd_bwidth - 1))
+ lcd_write_cmd(0x14); /* allow the cursor to pass the end of the line */
+ lcd_addr_x++;
+ }
+ processed = 1;
+ break;
+
+ case 'L': /* shift display left */
+ lcd_left_shift++;
+ lcd_write_cmd(0x18);
+ processed = 1;
+ break;
+
+ case 'R': /* shift display right */
+ lcd_left_shift--;
+ lcd_write_cmd(0x1C);
+ processed = 1;
+ break;
+
+ case 'k':{ /* kill end of line */
+ int x;
+ for (x = lcd_addr_x; x < lcd_bwidth; x++)
+ lcd_write_data(' ');
+ lcd_gotoxy(); /* restore cursor position */
+ processed = 1;
+ break;
+ }
+ case 'I': /* reinitialize display */
+ lcd_init_display();
+ lcd_left_shift = 0;
+ processed = 1;
+ break;
+
+ case 'G': /* Generator : LGcxxxxx...xx; */ {
+ /* must have <c> between '0' and '7', representing the numerical
+ * ASCII code of the redefined character, and <xx...xx> a sequence
+ * of 16 hex digits representing 8 bytes for each character. Most
+ * LCDs will only use 5 lower bits of the 7 first bytes.
+ */
+
+ unsigned char cgbytes[8];
+ unsigned char cgaddr;
+ int cgoffset;
+ int shift;
+ char value;
+ int addr;
+
+ if (strchr(esc, ';') == NULL)
+ break;
+
+ esc++;
+
+ cgaddr = *(esc++) - '0';
+ if (cgaddr > 7) {
+ processed = 1;
+ break;
+ }
+
+ cgoffset = 0;
+ shift = 0;
+ value = 0;
+ while (*esc && cgoffset < 8) {
+ shift ^= 4;
+ if (*esc >= '0' && *esc <= '9')
+ value |= (*esc - '0') << shift;
+ else if (*esc >= 'A' && *esc <= 'Z')
+ value |= (*esc - 'A' + 10) << shift;
+ else if (*esc >= 'a' && *esc <= 'z')
+ value |= (*esc - 'a' + 10) << shift;
+ else {
+ esc++;
+ continue;
+ }
+
+ if (shift == 0) {
+ cgbytes[cgoffset++] = value;
+ value = 0;
+ }
+
+ esc++;
+ }
+
+ lcd_write_cmd(0x40 | (cgaddr * 8));
+ for (addr = 0; addr < cgoffset; addr++)
+ lcd_write_data(cgbytes[addr]);
+
+ lcd_gotoxy(); /* ensures that we stop writing to CGRAM */
+ processed = 1;
+ break;
+ }
+ case 'x': /* gotoxy : LxXXX[yYYY]; */
+ case 'y': /* gotoxy : LyYYY[xXXX]; */
+ if (strchr(esc, ';') == NULL)
+ break;
+
+ while (*esc) {
+ if (*esc == 'x') {
+ esc++;
+ lcd_addr_x = 0;
+ while (isdigit(*esc)) {
+ lcd_addr_x =
+ lcd_addr_x *
+ 10 + (*esc -
+ '0');
+ esc++;
+ }
+ } else if (*esc == 'y') {
+ esc++;
+ lcd_addr_y = 0;
+ while (isdigit(*esc)) {
+ lcd_addr_y =
+ lcd_addr_y *
+ 10 + (*esc -
+ '0');
+ esc++;
+ }
+ } else
+ break;
+ }
+
+ lcd_gotoxy();
+ processed = 1;
+ break;
+ } /* end of switch */
+
+ /* Check wether one flag was changed */
+ if (oldflags != lcd_flags) {
+ /* check wether one of B,C,D flags was changed */
+ if ((oldflags ^ lcd_flags) &
+ (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
+ /* set display mode */
+ lcd_write_cmd(0x08 |
+ ((lcd_flags & LCD_FLAG_D) ? 4 : 0) |
+ ((lcd_flags & LCD_FLAG_C) ? 2 : 0) |
+ ((lcd_flags & LCD_FLAG_B) ? 1 : 0));
+ /* check wether one of F,N flags was changed */
+ else if ((oldflags ^ lcd_flags) &
+ (LCD_FLAG_F | LCD_FLAG_N))
+ lcd_write_cmd(0x30 |
+ ((lcd_flags & LCD_FLAG_F) ? 4 : 0) |
+ ((lcd_flags & LCD_FLAG_N) ? 8 : 0));
+ /* check wether L flag was changed */
+ else if ((oldflags ^ lcd_flags) &
+ (LCD_FLAG_L)) {
+ if (lcd_flags & (LCD_FLAG_L))
+ lcd_backlight(1);
+ else if (light_tempo == 0) /* switch off the light only when the tempo lighting is gone */
+ lcd_backlight(0);
+ }
+ }
+ }
+
+ /* LCD special escape codes */
+ /* flush the escape sequence if it's been processed or if it is
+ getting too long. */
+ if (processed || (lcd_escape_len >= LCD_ESCAPE_LEN))
+ lcd_escape_len = -1;
+ } /* escape codes */
+ }
+
+ return tmp - buf;
+}
+
+static int lcd_open(struct inode *inode, struct file *file)
+{
+ if (lcd_open_cnt)
+ return -EBUSY; /* open only once at a time */
+
+ if (file->f_mode & FMODE_READ) /* device is write-only */
+ return -EPERM;
+
+ if (lcd_must_clear) {
+ lcd_clear_display();
+ lcd_must_clear = 0;
+ }
+ lcd_open_cnt++;
+ return 0;
+}
+
+static int lcd_release(struct inode *inode, struct file *file)
+{
+ lcd_open_cnt--;
+ return 0;
+}
+
+static struct file_operations lcd_fops = {
+ .write = lcd_write,
+ .open = lcd_open,
+ .release = lcd_release,
+};
+
+static struct miscdevice lcd_dev = {
+ LCD_MINOR,
+ "lcd",
+ &lcd_fops
+};
+
+/* public function usable from the kernel for any purpose */
+void panel_lcd_print(char *s)
+{
+ if (lcd_enabled && lcd_initialized)
+ lcd_write(NULL, s, strlen(s), NULL);
+}
+
+/* initialize the LCD driver */
+void lcd_init(void)
+{
+ switch (lcd_type) {
+ case LCD_TYPE_OLD: /* parallel mode, 8 bits */
+ if (lcd_proto < 0)
+ lcd_proto = LCD_PROTO_PARALLEL;
+ if (lcd_charset < 0)
+ lcd_charset = LCD_CHARSET_NORMAL;
+ if (lcd_e_pin == PIN_NOT_SET)
+ lcd_e_pin = PIN_STROBE;
+ if (lcd_rs_pin == PIN_NOT_SET)
+ lcd_rs_pin = PIN_AUTOLF;
+
+ if (lcd_width < 0)
+ lcd_width = 40;
+ if (lcd_bwidth < 0)
+ lcd_bwidth = 40;
+ if (lcd_hwidth < 0)
+ lcd_hwidth = 64;
+ if (lcd_height < 0)
+ lcd_height = 2;
+ break;
+ case LCD_TYPE_KS0074: /* serial mode, ks0074 */
+ if (lcd_proto < 0)
+ lcd_proto = LCD_PROTO_SERIAL;
+ if (lcd_charset < 0)
+ lcd_charset = LCD_CHARSET_KS0074;
+ if (lcd_bl_pin == PIN_NOT_SET)
+ lcd_bl_pin = PIN_AUTOLF;
+ if (lcd_cl_pin == PIN_NOT_SET)
+ lcd_cl_pin = PIN_STROBE;
+ if (lcd_da_pin == PIN_NOT_SET)
+ lcd_da_pin = PIN_D0;
+
+ if (lcd_width < 0)
+ lcd_width = 16;
+ if (lcd_bwidth < 0)
+ lcd_bwidth = 40;
+ if (lcd_hwidth < 0)
+ lcd_hwidth = 16;
+ if (lcd_height < 0)
+ lcd_height = 2;
+ break;
+ case LCD_TYPE_NEXCOM: /* parallel mode, 8 bits, generic */
+ if (lcd_proto < 0)
+ lcd_proto = LCD_PROTO_PARALLEL;
+ if (lcd_charset < 0)
+ lcd_charset = LCD_CHARSET_NORMAL;
+ if (lcd_e_pin == PIN_NOT_SET)
+ lcd_e_pin = PIN_AUTOLF;
+ if (lcd_rs_pin == PIN_NOT_SET)
+ lcd_rs_pin = PIN_SELECP;
+ if (lcd_rw_pin == PIN_NOT_SET)
+ lcd_rw_pin = PIN_INITP;
+
+ if (lcd_width < 0)
+ lcd_width = 16;
+ if (lcd_bwidth < 0)
+ lcd_bwidth = 40;
+ if (lcd_hwidth < 0)
+ lcd_hwidth = 64;
+ if (lcd_height < 0)
+ lcd_height = 2;
+ break;
+ case LCD_TYPE_CUSTOM: /* customer-defined */
+ if (lcd_proto < 0)
+ lcd_proto = DEFAULT_LCD_PROTO;
+ if (lcd_charset < 0)
+ lcd_charset = DEFAULT_LCD_CHARSET;
+ /* default geometry will be set later */
+ break;
+ case LCD_TYPE_HANTRONIX: /* parallel mode, 8 bits, hantronix-like */
+ default:
+ if (lcd_proto < 0)
+ lcd_proto = LCD_PROTO_PARALLEL;
+ if (lcd_charset < 0)
+ lcd_charset = LCD_CHARSET_NORMAL;
+ if (lcd_e_pin == PIN_NOT_SET)
+ lcd_e_pin = PIN_STROBE;
+ if (lcd_rs_pin == PIN_NOT_SET)
+ lcd_rs_pin = PIN_SELECP;
+
+ if (lcd_width < 0)
+ lcd_width = 16;
+ if (lcd_bwidth < 0)
+ lcd_bwidth = 40;
+ if (lcd_hwidth < 0)
+ lcd_hwidth = 64;
+ if (lcd_height < 0)
+ lcd_height = 2;
+ break;
+ }
+
+ /* this is used to catch wrong and default values */
+ if (lcd_width <= 0)
+ lcd_width = DEFAULT_LCD_WIDTH;
+ if (lcd_bwidth <= 0)
+ lcd_bwidth = DEFAULT_LCD_BWIDTH;
+ if (lcd_hwidth <= 0)
+ lcd_hwidth = DEFAULT_LCD_HWIDTH;
+ if (lcd_height <= 0)
+ lcd_height = DEFAULT_LCD_HEIGHT;
+
+ if (lcd_proto == LCD_PROTO_SERIAL) { /* SERIAL */
+ lcd_write_cmd = lcd_write_cmd_s;
+ lcd_write_data = lcd_write_data_s;
+ lcd_clear_fast = lcd_clear_fast_s;
+
+ if (lcd_cl_pin == PIN_NOT_SET)
+ lcd_cl_pin = DEFAULT_LCD_PIN_SCL;
+ if (lcd_da_pin == PIN_NOT_SET)
+ lcd_da_pin = DEFAULT_LCD_PIN_SDA;
+
+ } else { /* PARALLEL */
+ lcd_write_cmd = lcd_write_cmd_p8;
+ lcd_write_data = lcd_write_data_p8;
+ lcd_clear_fast = lcd_clear_fast_p8;
+
+ if (lcd_e_pin == PIN_NOT_SET)
+ lcd_e_pin = DEFAULT_LCD_PIN_E;
+ if (lcd_rs_pin == PIN_NOT_SET)
+ lcd_rs_pin = DEFAULT_LCD_PIN_RS;
+ if (lcd_rw_pin == PIN_NOT_SET)
+ lcd_rw_pin = DEFAULT_LCD_PIN_RW;
+ }
+
+ if (lcd_bl_pin == PIN_NOT_SET)
+ lcd_bl_pin = DEFAULT_LCD_PIN_BL;
+
+ if (lcd_e_pin == PIN_NOT_SET)
+ lcd_e_pin = PIN_NONE;
+ if (lcd_rs_pin == PIN_NOT_SET)
+ lcd_rs_pin = PIN_NONE;
+ if (lcd_rw_pin == PIN_NOT_SET)
+ lcd_rw_pin = PIN_NONE;
+ if (lcd_bl_pin == PIN_NOT_SET)
+ lcd_bl_pin = PIN_NONE;
+ if (lcd_cl_pin == PIN_NOT_SET)
+ lcd_cl_pin = PIN_NONE;
+ if (lcd_da_pin == PIN_NOT_SET)
+ lcd_da_pin = PIN_NONE;
+
+ if (lcd_charset < 0)
+ lcd_charset = DEFAULT_LCD_CHARSET;
+
+ if (lcd_charset == LCD_CHARSET_KS0074)
+ lcd_char_conv = lcd_char_conv_ks0074;
+ else
+ lcd_char_conv = NULL;
+
+ if (lcd_bl_pin != PIN_NONE)
+ init_scan_timer();
+
+ pin_to_bits(lcd_e_pin, lcd_bits[LCD_PORT_D][LCD_BIT_E],
+ lcd_bits[LCD_PORT_C][LCD_BIT_E]);
+ pin_to_bits(lcd_rs_pin, lcd_bits[LCD_PORT_D][LCD_BIT_RS],
+ lcd_bits[LCD_PORT_C][LCD_BIT_RS]);
+ pin_to_bits(lcd_rw_pin, lcd_bits[LCD_PORT_D][LCD_BIT_RW],
+ lcd_bits[LCD_PORT_C][LCD_BIT_RW]);
+ pin_to_bits(lcd_bl_pin, lcd_bits[LCD_PORT_D][LCD_BIT_BL],
+ lcd_bits[LCD_PORT_C][LCD_BIT_BL]);
+ pin_to_bits(lcd_cl_pin, lcd_bits[LCD_PORT_D][LCD_BIT_CL],
+ lcd_bits[LCD_PORT_C][LCD_BIT_CL]);
+ pin_to_bits(lcd_da_pin, lcd_bits[LCD_PORT_D][LCD_BIT_DA],
+ lcd_bits[LCD_PORT_C][LCD_BIT_DA]);
+
+ /* before this line, we must NOT send anything to the display.
+ * Since lcd_init_display() needs to write data, we have to
+ * enable mark the LCD initialized just before.
+ */
+ lcd_initialized = 1;
+ lcd_init_display();
+
+ /* display a short message */
+#ifdef CONFIG_PANEL_CHANGE_MESSAGE
+#ifdef CONFIG_PANEL_BOOT_MESSAGE
+ panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE);
+#endif
+#else
+ panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-"
+ PANEL_VERSION);
+#endif
+ lcd_addr_x = lcd_addr_y = 0;
+ lcd_must_clear = 1; /* clear the display on the next device opening */
+ lcd_gotoxy();
+}
+
+/*
+ * These are the file operation function for user access to /dev/keypad
+ */
+
+static ssize_t keypad_read(struct file *file,
+ char *buf, size_t count, loff_t *ppos)
+{
+
+ unsigned i = *ppos;
+ char *tmp = buf;
+
+ if (keypad_buflen == 0) {
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ interruptible_sleep_on(&keypad_read_wait);
+ if (signal_pending(current))
+ return -EINTR;
+ }
+
+ for (; count-- > 0 && (keypad_buflen > 0); ++i, ++tmp, --keypad_buflen) {
+ put_user(keypad_buffer[keypad_start], tmp);
+ keypad_start = (keypad_start + 1) % KEYPAD_BUFFER;
+ }
+ *ppos = i;
+
+ return tmp - buf;
+}
+
+static int keypad_open(struct inode *inode, struct file *file)
+{
+
+ if (keypad_open_cnt)
+ return -EBUSY; /* open only once at a time */
+
+ if (file->f_mode & FMODE_WRITE) /* device is read-only */
+ return -EPERM;
+
+ keypad_buflen = 0; /* flush the buffer on opening */
+ keypad_open_cnt++;
+ return 0;
+}
+
+static int keypad_release(struct inode *inode, struct file *file)
+{
+ keypad_open_cnt--;
+ return 0;
+}
+
+static struct file_operations keypad_fops = {
+ .read = keypad_read, /* read */
+ .open = keypad_open, /* open */
+ .release = keypad_release, /* close */
+};
+
+static struct miscdevice keypad_dev = {
+ KEYPAD_MINOR,
+ "keypad",
+ &keypad_fops
+};
+
+static void keypad_send_key(char *string, int max_len)
+{
+ if (init_in_progress)
+ return;
+
+ /* send the key to the device only if a process is attached to it. */
+ if (keypad_open_cnt > 0) {
+ while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) {
+ keypad_buffer[(keypad_start + keypad_buflen++) %
+ KEYPAD_BUFFER] = *string++;
+ }
+ wake_up_interruptible(&keypad_read_wait);
+ }
+}
+
+/* this function scans all the bits involving at least one logical signal, and puts the
+ * results in the bitfield "phys_read" (one bit per established contact), and sets
+ * "phys_read_prev" to "phys_read".
+ *
+ * Note: to debounce input signals, we will only consider as switched a signal which is
+ * stable across 2 measures. Signals which are different between two reads will be kept
+ * as they previously were in their logical form (phys_prev). A signal which has just
+ * switched will have a 1 in (phys_read ^ phys_read_prev).
+ */
+static void phys_scan_contacts(void)
+{
+ int bit, bitval;
+ char oldval;
+ char bitmask;
+ char gndmask;
+
+ phys_prev = phys_curr;
+ phys_read_prev = phys_read;
+ phys_read = 0; /* flush all signals */
+
+ oldval = r_dtr(pprt) | scan_mask_o; /* keep track of old value, with all outputs disabled */
+ w_dtr(pprt, oldval & ~scan_mask_o); /* activate all keyboard outputs (active low) */
+ bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; /* will have a 1 for each bit set to gnd */
+ w_dtr(pprt, oldval); /* disable all matrix signals */
+
+ /* now that all outputs are cleared, the only active input bits are
+ * directly connected to the ground
+ */
+ gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; /* 1 for each grounded input */
+
+ phys_read |= (pmask_t) gndmask << 40; /* grounded inputs are signals 40-44 */
+
+ if (bitmask != gndmask) {
+ /* since clearing the outputs changed some inputs, we know that some
+ * input signals are currently tied to some outputs. So we'll scan them.
+ */
+ for (bit = 0; bit < 8; bit++) {
+ bitval = 1 << bit;
+
+ if (!(scan_mask_o & bitval)) /* skip unused bits */
+ continue;
+
+ w_dtr(pprt, oldval & ~bitval); /* enable this output */
+ bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask;
+ phys_read |= (pmask_t) bitmask << (5 * bit);
+ }
+ w_dtr(pprt, oldval); /* disable all outputs */
+ }
+ /* this is easy: use old bits when they are flapping, use new ones when stable */
+ phys_curr =
+ (phys_prev & (phys_read ^ phys_read_prev)) | (phys_read &
+ ~(phys_read ^
+ phys_read_prev));
+}
+
+static void panel_process_inputs(void)
+{
+ struct list_head *item;
+ struct logical_input *input;
+
+#if 0
+ printk(KERN_DEBUG
+ "entering panel_process_inputs with pp=%016Lx & pc=%016Lx\n",
+ phys_prev, phys_curr);
+#endif
+
+ keypressed = 0;
+ inputs_stable = 1;
+ list_for_each(item, &logical_inputs) {
+ input = list_entry(item, struct logical_input, list);
+
+ switch (input->state) {
+ case INPUT_ST_LOW:
+ if ((phys_curr & input->mask) != input->value)
+ break;
+ /* if all needed ones were already set previously, this means that
+ * this logical signal has been activated by the releasing of
+ * another combined signal, so we don't want to match.
+ * eg: AB -(release B)-> A -(release A)-> 0 : don't match A.
+ */
+ if ((phys_prev & input->mask) == input->value)
+ break;
+ input->rise_timer = 0;
+ input->state = INPUT_ST_RISING;
+ /* no break here, fall through */
+ case INPUT_ST_RISING:
+ if ((phys_curr & input->mask) != input->value) {
+ input->state = INPUT_ST_LOW;
+ break;
+ }
+ if (input->rise_timer < input->rise_time) {
+ inputs_stable = 0;
+ input->rise_timer++;
+ break;
+ }
+ input->high_timer = 0;
+ input->state = INPUT_ST_HIGH;
+ /* no break here, fall through */
+ case INPUT_ST_HIGH:
+#if 0
+ /* FIXME:
+ * this is an invalid test. It tries to catch transitions from single-key
+ * to multiple-key, but doesn't take into account the contacts polarity.
+ * The only solution to the problem is to parse keys from the most complex
+ * to the simplest combinations, and mark them as 'caught' once a combination
+ * matches, then unmatch it for all other ones.
+ */
+
+ /* try to catch dangerous transitions cases :
+ * someone adds a bit, so this signal was a false
+ * positive resulting from a transition. We should invalidate
+ * the signal immediately and not call the release function.
+ * eg: 0 -(press A)-> A -(press B)-> AB : don't match A's release.
+ */
+ if (((phys_prev & input->mask) == input->value)
+ && ((phys_curr & input->mask) > input->value)) {
+ input->state = INPUT_ST_LOW; /* invalidate */
+ break;
+ }
+#endif
+
+ if ((phys_curr & input->mask) == input->value) {
+ if ((input->type == INPUT_TYPE_STD)
+ && (input->high_timer == 0)) {
+ input->high_timer++;
+ if (input->u.std.press_fct != NULL)
+ input->u.std.press_fct(input->u.
+ std.
+ press_data);
+ } else if (input->type == INPUT_TYPE_KBD) {
+ keypressed = 1; /* will turn on the light */
+
+ if (input->high_timer == 0) {
+ if (input->u.kbd.press_str[0])
+ keypad_send_key(input->
+ u.kbd.
+ press_str,
+ sizeof
+ (input->
+ u.kbd.
+ press_str));
+ }
+
+ if (input->u.kbd.repeat_str[0]) {
+ if (input->high_timer >=
+ KEYPAD_REP_START) {
+ input->high_timer -=
+ KEYPAD_REP_DELAY;
+ keypad_send_key(input->
+ u.kbd.
+ repeat_str,
+ sizeof
+ (input->
+ u.kbd.
+ repeat_str));
+ }
+ inputs_stable = 0; /* we will need to come back here soon */
+ }
+
+ if (input->high_timer < 255)
+ input->high_timer++;
+ }
+ break;
+ } else {
+ /* else signal falling down. Let's fall through. */
+ input->state = INPUT_ST_FALLING;
+ input->fall_timer = 0;
+ }
+ /* no break here, fall through */
+ case INPUT_ST_FALLING:
+#if 0
+ /* FIXME !!! same comment as above */
+ if (((phys_prev & input->mask) == input->value)
+ && ((phys_curr & input->mask) > input->value)) {
+ input->state = INPUT_ST_LOW; /* invalidate */
+ break;
+ }
+#endif
+
+ if ((phys_curr & input->mask) == input->value) {
+ if (input->type == INPUT_TYPE_KBD) {
+ keypressed = 1; /* will turn on the light */
+
+ if (input->u.kbd.repeat_str[0]) {
+ if (input->high_timer >= KEYPAD_REP_START)
+ input->high_timer -= KEYPAD_REP_DELAY;
+ keypad_send_key(input->u.kbd.repeat_str,
+ sizeof(input->u.kbd.repeat_str));
+ inputs_stable = 0; /* we will need to come back here soon */
+ }
+
+ if (input->high_timer < 255)
+ input->high_timer++;
+ }
+ input->state = INPUT_ST_HIGH;
+ break;
+ } else if (input->fall_timer >= input->fall_time) {
+ /* call release event */
+ if (input->type == INPUT_TYPE_STD) {
+ if (input->u.std.release_fct != NULL)
+ input->u.std.release_fct(input->u.std.release_data);
+
+ } else if (input->type == INPUT_TYPE_KBD) {
+ if (input->u.kbd.release_str[0])
+ keypad_send_key(input->u.kbd.release_str,
+ sizeof(input->u.kbd.release_str));
+ }
+
+ input->state = INPUT_ST_LOW;
+ break;
+ } else {
+ input->fall_timer++;
+ inputs_stable = 0;
+ break;
+ }
+ }
+ }
+}
+
+static void panel_scan_timer(void)
+{
+ if (keypad_enabled && keypad_initialized) {
+ if (spin_trylock(&pprt_lock)) {
+ phys_scan_contacts();
+ spin_unlock(&pprt_lock); /* no need for the parport anymore */
+ }
+
+ if (!inputs_stable || phys_curr != phys_prev)
+ panel_process_inputs();
+ }
+
+ if (lcd_enabled && lcd_initialized) {
+ if (keypressed) {
+ if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0))
+ lcd_backlight(1);
+ light_tempo = FLASH_LIGHT_TEMPO;
+ } else if (light_tempo > 0) {
+ light_tempo--;
+ if (light_tempo == 0 && ((lcd_flags & LCD_FLAG_L) == 0))
+ lcd_backlight(0);
+ }
+ }
+
+ mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME);
+}
+
+static void init_scan_timer(void)
+{
+ if (scan_timer.function != NULL)
+ return; /* already started */
+
+ init_timer(&scan_timer);
+ scan_timer.expires = jiffies + INPUT_POLL_TIME;
+ scan_timer.data = 0;
+ scan_timer.function = (void *)&panel_scan_timer;
+ add_timer(&scan_timer);
+}
+
+/* converts a name of the form "({BbAaPpSsEe}{01234567-})*" to a series of bits.
+ * if <omask> or <imask> are non-null, they will be or'ed with the bits corresponding
+ * to out and in bits respectively.
+ * returns 1 if ok, 0 if error (in which case, nothing is written).
+ */
+static int input_name2mask(char *name, pmask_t *mask, pmask_t *value,
+ char *imask, char *omask)
+{
+ static char sigtab[10] = "EeSsPpAaBb";
+ char im, om;
+ pmask_t m, v;
+
+ om = im = m = v = 0ULL;
+ while (*name) {
+ int in, out, bit, neg;
+ for (in = 0; (in < sizeof(sigtab)) && (sigtab[in] != *name); in++)
+ ;
+ if (in >= sizeof(sigtab))
+ return 0; /* input name not found */
+ neg = (in & 1); /* odd (lower) names are negated */
+ in >>= 1;
+ im |= (1 << in);
+
+ name++;
+ if (isdigit(*name)) {
+ out = *name - '0';
+ om |= (1 << out);
+ } else if (*name == '-')
+ out = 8;
+ else
+ return 0; /* unknown bit name */
+
+ bit = (out * 5) + in;
+
+ m |= 1ULL << bit;
+ if (!neg)
+ v |= 1ULL << bit;
+ name++;
+ }
+ *mask = m;
+ *value = v;
+ if (imask)
+ *imask |= im;
+ if (omask)
+ *omask |= om;
+ return 1;
+}
+
+/* tries to bind a key to the signal name <name>. The key will send the
+ * strings <press>, <repeat>, <release> for these respective events.
+ * Returns the pointer to the new key if ok, NULL if the key could not be bound.
+ */
+static struct logical_input *panel_bind_key(char *name, char *press,
+ char *repeat, char *release)
+{
+ struct logical_input *key;
+
+ key = kmalloc(sizeof(struct logical_input), GFP_KERNEL);
+ if (!key) {
+ printk(KERN_ERR "panel: not enough memory\n");
+ return NULL;
+ }
+ memset(key, 0, sizeof(struct logical_input));
+ if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i,
+ &scan_mask_o))
+ return NULL;
+
+ key->type = INPUT_TYPE_KBD;
+ key->state = INPUT_ST_LOW;
+ key->rise_time = 1;
+ key->fall_time = 1;
+
+#if 0
+ printk(KERN_DEBUG "bind: <%s> : m=%016Lx v=%016Lx\n", name, key->mask,
+ key->value);
+#endif
+ strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str));
+ strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str));
+ strncpy(key->u.kbd.release_str, release,
+ sizeof(key->u.kbd.release_str));
+ list_add(&key->list, &logical_inputs);
+ return key;
+}
+
+#if 0
+/* tries to bind a callback function to the signal name <name>. The function
+ * <press_fct> will be called with the <press_data> arg when the signal is
+ * activated, and so on for <release_fct>/<release_data>
+ * Returns the pointer to the new signal if ok, NULL if the signal could not be bound.
+ */
+static struct logical_input *panel_bind_callback(char *name,
+ void (*press_fct) (int),
+ int press_data,
+ void (*release_fct) (int),
+ int release_data)
+{
+ struct logical_input *callback;
+
+ callback = kmalloc(sizeof(struct logical_input), GFP_KERNEL);
+ if (!callback) {
+ printk(KERN_ERR "panel: not enough memory\n");
+ return NULL;
+ }
+ memset(callback, 0, sizeof(struct logical_input));
+ if (!input_name2mask(name, &callback->mask, &callback->value,
+ &scan_mask_i, &scan_mask_o))
+ return NULL;
+
+ callback->type = INPUT_TYPE_STD;
+ callback->state = INPUT_ST_LOW;
+ callback->rise_time = 1;
+ callback->fall_time = 1;
+ callback->u.std.press_fct = press_fct;
+ callback->u.std.press_data = press_data;
+ callback->u.std.release_fct = release_fct;
+ callback->u.std.release_data = release_data;
+ list_add(&callback->list, &logical_inputs);
+ return callback;
+}
+#endif
+
+static void keypad_init(void)
+{
+ int keynum;
+ init_waitqueue_head(&keypad_read_wait);
+ keypad_buflen = 0; /* flushes any eventual noisy keystroke */
+
+ /* Let's create all known keys */
+
+ for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) {
+ panel_bind_key(keypad_profile[keynum][0],
+ keypad_profile[keynum][1],
+ keypad_profile[keynum][2],
+ keypad_profile[keynum][3]);
+ }
+
+ init_scan_timer();
+ keypad_initialized = 1;
+}
+
+/**************************************************/
+/* device initialization */
+/**************************************************/
+
+static int panel_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (lcd_enabled && lcd_initialized) {
+ switch (code) {
+ case SYS_DOWN:
+ panel_lcd_print
+ ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+");
+ break;
+ case SYS_HALT:
+ panel_lcd_print
+ ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+");
+ break;
+ case SYS_POWER_OFF:
+ panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+");
+ break;
+ default:
+ break;
+ }
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block panel_notifier = {
+ panel_notify_sys,
+ NULL,
+ 0
+};
+
+static void panel_attach(struct parport *port)
+{
+ if (port->number != parport)
+ return;
+
+ if (pprt) {
+ printk(KERN_ERR
+ "panel_attach(): port->number=%d parport=%d, already registered !\n",
+ port->number, parport);
+ return;
+ }
+
+ pprt = parport_register_device(port, "panel", NULL, NULL, /* pf, kf */
+ NULL,
+ /*PARPORT_DEV_EXCL */
+ 0, (void *)&pprt);
+
+ if (parport_claim(pprt)) {
+ printk(KERN_ERR
+ "Panel: could not claim access to parport%d. Aborting.\n",
+ parport);
+ return;
+ }
+
+ /* must init LCD first, just in case an IRQ from the keypad is generated at keypad init */
+ if (lcd_enabled) {
+ lcd_init();
+ misc_register(&lcd_dev);
+ }
+
+ if (keypad_enabled) {
+ keypad_init();
+ misc_register(&keypad_dev);
+ }
+}
+
+static void panel_detach(struct parport *port)
+{
+ if (port->number != parport)
+ return;
+
+ if (!pprt) {
+ printk(KERN_ERR
+ "panel_detach(): port->number=%d parport=%d, nothing to unregister.\n",
+ port->number, parport);
+ return;
+ }
+
+ if (keypad_enabled && keypad_initialized)
+ misc_deregister(&keypad_dev);
+
+ if (lcd_enabled && lcd_initialized)
+ misc_deregister(&lcd_dev);
+
+ parport_release(pprt);
+ parport_unregister_device(pprt);
+ pprt = NULL;
+}
+
+static struct parport_driver panel_driver = {
+ .name = "panel",
+ .attach = panel_attach,
+ .detach = panel_detach,
+};
+
+/* init function */
+int panel_init(void)
+{
+ /* for backwards compatibility */
+ if (keypad_type < 0)
+ keypad_type = keypad_enabled;
+
+ if (lcd_type < 0)
+ lcd_type = lcd_enabled;
+
+ if (parport < 0)
+ parport = DEFAULT_PARPORT;
+
+ /* take care of an eventual profile */
+ switch (profile) {
+ case PANEL_PROFILE_CUSTOM: /* custom profile */
+ if (keypad_type < 0)
+ keypad_type = DEFAULT_KEYPAD;
+ if (lcd_type < 0)
+ lcd_type = DEFAULT_LCD;
+ break;
+ case PANEL_PROFILE_OLD: /* 8 bits, 2*16, old keypad */
+ if (keypad_type < 0)
+ keypad_type = KEYPAD_TYPE_OLD;
+ if (lcd_type < 0)
+ lcd_type = LCD_TYPE_OLD;
+ if (lcd_width < 0)
+ lcd_width = 16;
+ if (lcd_hwidth < 0)
+ lcd_hwidth = 16;
+ break;
+ case PANEL_PROFILE_NEW: /* serial, 2*16, new keypad */
+ if (keypad_type < 0)
+ keypad_type = KEYPAD_TYPE_NEW;
+ if (lcd_type < 0)
+ lcd_type = LCD_TYPE_KS0074;
+ break;
+ case PANEL_PROFILE_HANTRONIX: /* 8 bits, 2*16 hantronix-like, no keypad */
+ if (keypad_type < 0)
+ keypad_type = KEYPAD_TYPE_NONE;
+ if (lcd_type < 0)
+ lcd_type = LCD_TYPE_HANTRONIX;
+ break;
+ case PANEL_PROFILE_NEXCOM: /* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */
+ if (keypad_type < 0)
+ keypad_type = KEYPAD_TYPE_NEXCOM;
+ if (lcd_type < 0)
+ lcd_type = LCD_TYPE_NEXCOM;
+ break;
+ case PANEL_PROFILE_LARGE: /* 8 bits, 2*40, old keypad */
+ if (keypad_type < 0)
+ keypad_type = KEYPAD_TYPE_OLD;
+ if (lcd_type < 0)
+ lcd_type = LCD_TYPE_OLD;
+ break;
+ }
+
+ lcd_enabled = (lcd_type > 0);
+ keypad_enabled = (keypad_type > 0);
+
+ switch (keypad_type) {
+ case KEYPAD_TYPE_OLD:
+ keypad_profile = old_keypad_profile;
+ break;
+ case KEYPAD_TYPE_NEW:
+ keypad_profile = new_keypad_profile;
+ break;
+ case KEYPAD_TYPE_NEXCOM:
+ keypad_profile = nexcom_keypad_profile;
+ break;
+ default:
+ keypad_profile = NULL;
+ break;
+ }
+
+ /* tells various subsystems about the fact that we are initializing */
+ init_in_progress = 1;
+
+ if (parport_register_driver(&panel_driver)) {
+ printk(KERN_ERR
+ "Panel: could not register with parport. Aborting.\n");
+ return -EIO;
+ }
+
+ if (!lcd_enabled && !keypad_enabled) {
+ /* no device enabled, let's release the parport */
+ if (pprt) {
+ parport_release(pprt);
+ parport_unregister_device(pprt);
+ }
+ parport_unregister_driver(&panel_driver);
+ printk(KERN_ERR "Panel driver version " PANEL_VERSION
+ " disabled.\n");
+ return -ENODEV;
+ }
+
+ register_reboot_notifier(&panel_notifier);
+
+ if (pprt)
+ printk(KERN_INFO "Panel driver version " PANEL_VERSION
+ " registered on parport%d (io=0x%lx).\n", parport,
+ pprt->port->base);
+ else
+ printk(KERN_INFO "Panel driver version " PANEL_VERSION
+ " not yet registered\n");
+ /* tells various subsystems about the fact that initialization is finished */
+ init_in_progress = 0;
+ return 0;
+}
+
+static int __init panel_init_module(void)
+{
+ return panel_init();
+}
+
+static void __exit panel_cleanup_module(void)
+{
+ unregister_reboot_notifier(&panel_notifier);
+
+ if (scan_timer.function != NULL)
+ del_timer(&scan_timer);
+
+ if (keypad_enabled)
+ misc_deregister(&keypad_dev);
+
+ if (lcd_enabled) {
+ panel_lcd_print("\x0cLCD driver " PANEL_VERSION
+ "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
+ misc_deregister(&lcd_dev);
+ }
+
+ /* TODO: free all input signals */
+
+ parport_release(pprt);
+ parport_unregister_device(pprt);
+ parport_unregister_driver(&panel_driver);
+}
+
+module_init(panel_init_module);
+module_exit(panel_cleanup_module);
+MODULE_AUTHOR("Willy Tarreau");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * tab-width: 8
+ * End:
+ */
diff --git a/drivers/staging/poch/README b/drivers/staging/poch/README
index f65e979743ba..842afd464993 100644
--- a/drivers/staging/poch/README
+++ b/drivers/staging/poch/README
@@ -1,5 +1,12 @@
TODO:
- - fix transmit overflows
+ - Rx block size is limited to < 2048, hardware bug?
+ - Group size is limited to < page size, kernel alloc/mmap API issues
+ - fix/workaround cache issues in circular buffer header
+ - test whether Tx is transmitting data from provided buffers
+ - handle device unplug case
+ - handle temperature above threshold
+ - use bus address instead of physical address for DMA
+ - support for snapshot mode
- audit userspace interfaces
- get reserved major/minor if needed
diff --git a/drivers/staging/poch/poch.c b/drivers/staging/poch/poch.c
index 0e113f9a1581..0d111ddfabb2 100644
--- a/drivers/staging/poch/poch.c
+++ b/drivers/staging/poch/poch.c
@@ -126,9 +126,11 @@
#define FPGA_INT_TX_ACQ_DONE (0x1 << 1)
#define FPGA_INT_RX_ACQ_DONE (0x1)
-#define FPGA_RX_ADC_CTL_REG 0x214
-#define FPGA_RX_ADC_CTL_CONT_CAP (0x0)
-#define FPGA_RX_ADC_CTL_SNAP_CAP (0x1)
+#define FPGA_RX_CTL_REG 0x214
+#define FPGA_RX_CTL_FIFO_FLUSH (0x1 << 9)
+#define FPGA_RX_CTL_SYNTH_DATA (0x1 << 8)
+#define FPGA_RX_CTL_CONT_CAP (0x0 << 1)
+#define FPGA_RX_CTL_SNAP_CAP (0x1 << 1)
#define FPGA_RX_ARM_REG 0x21C
@@ -299,6 +301,14 @@ static ssize_t show_direction(struct device *dev,
}
static DEVICE_ATTR(dir, S_IRUSR|S_IRGRP, show_direction, NULL);
+static unsigned long npages(unsigned long bytes)
+{
+ if (bytes % PAGE_SIZE == 0)
+ return bytes / PAGE_SIZE;
+ else
+ return (bytes / PAGE_SIZE) + 1;
+}
+
static ssize_t show_mmap_size(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -309,10 +319,8 @@ static ssize_t show_mmap_size(struct device *dev,
unsigned long header_pages;
unsigned long total_group_pages;
- /* FIXME: We do not have to add 1, if group_size a multiple of
- PAGE_SIZE. */
- group_pages = (channel->group_size / PAGE_SIZE) + 1;
- header_pages = (channel->header_size / PAGE_SIZE) + 1;
+ group_pages = npages(channel->group_size);
+ header_pages = npages(channel->header_size);
total_group_pages = group_pages * channel->group_count;
mmap_size = (header_pages + total_group_pages) * PAGE_SIZE;
@@ -350,8 +358,8 @@ static int poch_channel_alloc_groups(struct channel_info *channel)
unsigned long group_pages;
unsigned long header_pages;
- group_pages = (channel->group_size / PAGE_SIZE) + 1;
- header_pages = (channel->header_size / PAGE_SIZE) + 1;
+ group_pages = npages(channel->group_size);
+ header_pages = npages(channel->header_size);
for (i = 0; i < channel->group_count; i++) {
struct poch_group_info *group;
@@ -384,18 +392,45 @@ static int poch_channel_alloc_groups(struct channel_info *channel)
group->user_offset =
(header_pages + (i * group_pages)) * PAGE_SIZE;
- printk(KERN_INFO PFX "%ld: user_offset: 0x%lx dma: 0x%x\n", i,
- group->user_offset, group->dma_addr);
+ printk(KERN_INFO PFX "%ld: user_offset: 0x%lx\n", i,
+ group->user_offset);
}
return 0;
}
-static void channel_latch_attr(struct channel_info *channel)
+static int channel_latch_attr(struct channel_info *channel)
{
channel->group_count = atomic_read(&channel->sys_group_count);
channel->group_size = atomic_read(&channel->sys_group_size);
channel->block_size = atomic_read(&channel->sys_block_size);
+
+ if (channel->group_count == 0) {
+ printk(KERN_ERR PFX "invalid group count %lu",
+ channel->group_count);
+ return -EINVAL;
+ }
+
+ if (channel->group_size == 0 ||
+ channel->group_size < channel->block_size) {
+ printk(KERN_ERR PFX "invalid group size %lu",
+ channel->group_size);
+ return -EINVAL;
+ }
+
+ if (channel->block_size == 0 || (channel->block_size % 8) != 0) {
+ printk(KERN_ERR PFX "invalid block size %lu",
+ channel->block_size);
+ return -EINVAL;
+ }
+
+ if (channel->group_size % channel->block_size != 0) {
+ printk(KERN_ERR PFX
+ "group size should be multiple of block size");
+ return -EINVAL;
+ }
+
+ return 0;
}
/*
@@ -432,7 +467,10 @@ static void channel_dma_init(struct channel_info *channel)
}
printk(KERN_WARNING "block_size, group_size, group_count\n");
- iowrite32(channel->block_size, fpga + block_size_reg);
+ /*
+ * Block size is represented in no. of 64 bit transfers.
+ */
+ iowrite32(channel->block_size / 8, fpga + block_size_reg);
iowrite32(channel->group_size / channel->block_size,
fpga + block_count_reg);
iowrite32(channel->group_count, fpga + group_count_reg);
@@ -447,27 +485,30 @@ static void channel_dma_init(struct channel_info *channel)
/* The DMA address page register is shared between the RX and
* TX channels, so acquire lock.
*/
- spin_lock(channel->iomem_lock);
for (i = 0; i < channel->group_count; i++) {
page = i / 32;
group_in_page = i % 32;
group_reg = group_regs_base + (group_in_page * 4);
+ spin_lock(channel->iomem_lock);
iowrite32(page, fpga + FPGA_DMA_ADR_PAGE_REG);
iowrite32(channel->groups[i].dma_addr, fpga + group_reg);
+ spin_unlock(channel->iomem_lock);
}
+
for (i = 0; i < channel->group_count; i++) {
page = i / 32;
group_in_page = i % 32;
group_reg = group_regs_base + (group_in_page * 4);
+ spin_lock(channel->iomem_lock);
iowrite32(page, fpga + FPGA_DMA_ADR_PAGE_REG);
printk(KERN_INFO PFX "%ld: read dma_addr: 0x%x\n", i,
ioread32(fpga + group_reg));
+ spin_unlock(channel->iomem_lock);
}
- spin_unlock(channel->iomem_lock);
}
@@ -538,7 +579,9 @@ static int poch_channel_init(struct channel_info *channel,
printk(KERN_WARNING "channel_latch_attr\n");
- channel_latch_attr(channel);
+ ret = channel_latch_attr(channel);
+ if (ret != 0)
+ goto out;
channel->transfer = 0;
@@ -781,6 +824,11 @@ static int poch_open(struct inode *inode, struct file *filp)
iowrite32(FPGA_TX_CTL_FIFO_FLUSH
| FPGA_TX_CTL_OUTPUT_CARDBUS,
fpga + FPGA_TX_CTL_REG);
+ } else {
+ /* Flush RX FIFO and output data to cardbus. */
+ iowrite32(FPGA_RX_CTL_CONT_CAP
+ | FPGA_RX_CTL_FIFO_FLUSH,
+ fpga + FPGA_RX_CTL_REG);
}
atomic_inc(&channel->inited);
@@ -847,8 +895,8 @@ static int poch_mmap(struct file *filp, struct vm_area_struct *vma)
return -EINVAL;
}
- group_pages = (channel->group_size / PAGE_SIZE) + 1;
- header_pages = (channel->header_size / PAGE_SIZE) + 1;
+ group_pages = npages(channel->group_size);
+ header_pages = npages(channel->header_size);
total_group_pages = group_pages * channel->group_count;
size = vma->vm_end - vma->vm_start;
@@ -903,14 +951,7 @@ static int poch_channel_available(struct channel_info *channel)
spin_lock_irq(&channel->group_offsets_lock);
for (i = 0; i < channel->group_count; i++) {
- if (channel->dir == CHANNEL_DIR_RX
- && channel->header->group_offsets[i] == -1) {
- spin_unlock_irq(&channel->group_offsets_lock);
- return 1;
- }
-
- if (channel->dir == CHANNEL_DIR_TX
- && channel->header->group_offsets[i] != -1) {
+ if (channel->header->group_offsets[i] != -1) {
spin_unlock_irq(&channel->group_offsets_lock);
return 1;
}
@@ -985,7 +1026,7 @@ static int poch_ioctl(struct inode *inode, struct file *filp,
}
break;
case POCH_IOC_GET_COUNTERS:
- if (access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters)))
+ if (!access_ok(VERIFY_WRITE, argp, sizeof(struct poch_counters)))
return -EFAULT;
spin_lock_irq(&channel->counters_lock);
@@ -1058,10 +1099,7 @@ static void poch_irq_dma(struct channel_info *channel)
for (i = 0; i < groups_done; i++) {
j = (prev_transfer + i) % channel->group_count;
- if (channel->dir == CHANNEL_DIR_RX)
- group_offsets[j] = -1;
- else
- group_offsets[j] = groups[j].user_offset;
+ group_offsets[j] = groups[j].user_offset;
}
spin_unlock(&channel->group_offsets_lock);
@@ -1283,7 +1321,7 @@ static int __devinit poch_pci_probe(struct pci_dev *pdev,
}
ret = request_irq(pdev->irq, poch_irq_handler, IRQF_SHARED,
- dev->bus_id, poch_dev);
+ dev_name(dev), poch_dev);
if (ret) {
dev_err(dev, "error requesting IRQ %u\n", pdev->irq);
ret = -ENOMEM;
@@ -1350,12 +1388,12 @@ static void poch_pci_remove(struct pci_dev *pdev)
unsigned int minor = MINOR(poch_dev->cdev.dev);
unsigned int id = minor / poch_dev->nchannels;
- /* FIXME: unmap fpga_iomem and bridge_iomem */
-
poch_class_dev_unregister(poch_dev, id);
cdev_del(&poch_dev->cdev);
idr_remove(&poch_ids, id);
free_irq(pdev->irq, poch_dev);
+ iounmap(poch_dev->fpga_iomem);
+ iounmap(poch_dev->bridge_iomem);
uio_unregister_device(uio);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/staging/rspiusb/Kconfig b/drivers/staging/rspiusb/Kconfig
new file mode 100644
index 000000000000..d225f6794d02
--- /dev/null
+++ b/drivers/staging/rspiusb/Kconfig
@@ -0,0 +1,6 @@
+config USB_RSPI
+ tristate "Princeton Instruments USB camera support"
+ default n
+ depends on USB && BROKEN
+ help
+ This driver is for the Princeton Instruments USB camera device.
diff --git a/drivers/staging/rspiusb/Makefile b/drivers/staging/rspiusb/Makefile
new file mode 100644
index 000000000000..cc7aed92b0e3
--- /dev/null
+++ b/drivers/staging/rspiusb/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_RSPI) += rspiusb.o
diff --git a/drivers/staging/rspiusb/TODO b/drivers/staging/rspiusb/TODO
new file mode 100644
index 000000000000..cd6336a9254d
--- /dev/null
+++ b/drivers/staging/rspiusb/TODO
@@ -0,0 +1,22 @@
+This driver is for the Princeton Instruments USB camera.
+
+It needs lots of work to get it into the main drivers/usb/ subdirectory:
+
+Any patches to do any of the following changes are greatly appreciated:
+
+ - make checkpatch.pl clean
+ - coding style fixups (typedefs, etc.)
+ - get it to build properly
+ - audit ioctls
+ - remove ioctls if possible
+ - assign proper minor number
+ - remove dbg() macro
+ - lots of general cleanups
+ - review locking
+
+Please send patches to:
+ Greg Kroah-Hartman <gregkh@suse.de>
+and CC:
+ Judd Montgomery <judd@jpilot.org>
+ Jeff Frontz <jeff.frontz@gmail.com>
+as they have this device and can test any needed changes.
diff --git a/drivers/staging/rspiusb/rspiusb.c b/drivers/staging/rspiusb/rspiusb.c
new file mode 100644
index 000000000000..ca281d6cbd7a
--- /dev/null
+++ b/drivers/staging/rspiusb/rspiusb.c
@@ -0,0 +1,887 @@
+/*
+ * rspiusb.c
+ *
+ * Copyright (C) 2005, 2006 Princeton Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/completion.h>
+#include <linux/scatterlist.h>
+#include <linux/usb.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/ioctl.h>
+#include "rspiusb.h"
+
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+
+/* Version Information */
+#define DRIVER_VERSION "V1.0.1"
+#define DRIVER_AUTHOR "Princeton Instruments"
+#define DRIVER_DESC "PI USB2.0 Device Driver for Linux"
+
+/* Define these values to match your devices */
+#define VENDOR_ID 0x0BD7
+#define ST133_PID 0xA010
+#define PIXIS_PID 0xA026
+
+/* Get a minor range for your devices from the usb maintainer */
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define PIUSB_MINOR_BASE 0
+#else
+#define PIUSB_MINOR_BASE 192
+#endif
+
+/* prevent races between open() and disconnect() */
+static DECLARE_MUTEX(disconnect_sem);
+
+/* Structure to hold all of our device specific stuff */
+struct device_extension {
+ struct usb_device *udev; /* save off the usb device pointer */
+ struct usb_interface *interface; /* the interface for this device */
+ unsigned char minor; /* the starting minor number for this device */
+ size_t bulk_in_size_returned;
+ int bulk_in_byte_trk;
+ struct urb ***PixelUrb;
+ int frameIdx;
+ int urbIdx;
+ unsigned int *maplist_numPagesMapped;
+ int open; /* if the port is open or not */
+ int present; /* if the device is not disconnected */
+ int userBufMapped; /* has the user buffer been mapped? */
+ struct scatterlist **sgl; /* scatter-gather list for user buffer */
+ unsigned int *sgEntries;
+ struct kref kref;
+ int gotPixelData;
+ int pendingWrite;
+ char **pendedPixelUrbs;
+ int iama; /*PIXIS or ST133 */
+ int num_frames; /* the number of frames that will fit in the user buffer */
+ int active_frame;
+ unsigned long frameSize;
+ struct semaphore sem;
+ //FX2 specific endpoints
+ unsigned int hEP[8];
+};
+#define to_pi_dev(d) container_of( d, struct device_extension, kref )
+
+static int MapUserBuffer(struct ioctl_struct *, struct device_extension *);
+static int UnMapUserBuffer(struct device_extension *);
+static int piusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg);
+static int piusb_output(struct ioctl_struct *, unsigned char *, int, struct device_extension *);
+static struct usb_driver piusb_driver;
+
+/* table of devices that work with this driver */
+static struct usb_device_id pi_device_table[] = {
+ {USB_DEVICE(VENDOR_ID, ST133_PID)},
+ {USB_DEVICE(VENDOR_ID, PIXIS_PID)},
+ {0, } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, pi_device_table);
+
+static int lastErr = 0;
+static int errCnt = 0;
+
+static void piusb_delete(struct kref *kref)
+{
+ struct device_extension *pdx = to_pi_dev(kref);
+
+ dev_dbg(&pdx->udev->dev, "%s\n", __func__);
+ usb_put_dev(pdx->udev);
+ kfree(pdx);
+}
+
+static int piusb_open(struct inode *inode, struct file *file)
+{
+ struct device_extension *pdx = NULL;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+
+ dbg("Piusb_Open()");
+ subminor = iminor(inode);
+ interface = usb_find_interface(&piusb_driver, subminor);
+ if (!interface) {
+ printk(KERN_ERR "%s - error, can't find device for minor %d\n",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto exit_no_device;
+ }
+
+ pdx = usb_get_intfdata(interface);
+ if (!pdx) {
+ retval = -ENODEV;
+ goto exit_no_device;
+ }
+ dbg("Alternate Setting = %d", interface->num_altsetting);
+
+ pdx->frameIdx = pdx->urbIdx = 0;
+ pdx->gotPixelData = 0;
+ pdx->pendingWrite = 0;
+ pdx->frameSize = 0;
+ pdx->num_frames = 0;
+ pdx->active_frame = 0;
+ pdx->bulk_in_byte_trk = 0;
+ pdx->userBufMapped = 0;
+ pdx->pendedPixelUrbs = NULL;
+ pdx->sgEntries = NULL;
+ pdx->sgl = NULL;
+ pdx->maplist_numPagesMapped = NULL;
+ pdx->PixelUrb = NULL;
+ pdx->bulk_in_size_returned = 0;
+ /* increment our usage count for the device */
+ kref_get(&pdx->kref);
+ /* save our object in the file's private structure */
+ file->private_data = pdx;
+ exit_no_device:
+ return retval;
+}
+
+static int piusb_release(struct inode *inode, struct file *file)
+{
+ struct device_extension *pdx;
+ int retval = 0;
+
+ dbg("Piusb_Release()");
+ pdx = (struct device_extension *)file->private_data;
+ if (pdx == NULL) {
+ dbg("%s - object is NULL", __func__);
+ return -ENODEV;
+ }
+ /* decrement the count on our device */
+ kref_put(&pdx->kref, piusb_delete);
+ return retval;
+}
+
+/**
+ * piusb_ioctl
+ */
+static int piusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct device_extension *pdx;
+ char dummyCtlBuf[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ unsigned long devRB = 0;
+ int i = 0;
+ int err = 0;
+ int retval = 0;
+ struct ioctl_struct ctrl;
+ unsigned char *uBuf;
+ int numbytes = 0;
+ unsigned short controlData = 0;
+
+ pdx = (struct device_extension *)file->private_data;
+ /* verify that the device wasn't unplugged */
+ if (!pdx->present) {
+ dbg("No Device Present\n");
+ return -ENODEV;
+ }
+ /* fill in your device specific stuff here */
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+ if (err) {
+ dev_err(&pdx->udev->dev, "return with error = %d\n", err);
+ return -EFAULT;
+ }
+ switch (cmd) {
+ case PIUSB_GETVNDCMD:
+ if (copy_from_user
+ (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct)))
+ info("copy_from_user failed\n");
+ dbg("%s %x\n", "Get Vendor Command = ", ctrl.cmd);
+ retval =
+ usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0),
+ ctrl.cmd, USB_DIR_IN, 0, 0, &devRB,
+ ctrl.numbytes, HZ * 10);
+ if (ctrl.cmd == 0xF1) {
+ dbg("FW Version returned from HW = %ld.%ld",
+ (devRB >> 8), (devRB & 0xFF));
+ }
+ return devRB;
+ case PIUSB_SETVNDCMD:
+ if (copy_from_user
+ (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct)))
+ info("copy_from_user failed\n");
+// dbg( "%s %x", "Set Vendor Command = ",ctrl.cmd );
+ controlData = ctrl.pData[0];
+ controlData |= (ctrl.pData[1] << 8);
+// dbg( "%s %d", "Vendor Data =",controlData );
+ retval = usb_control_msg(pdx->udev, usb_sndctrlpipe(pdx->udev, 0), ctrl.cmd, (USB_DIR_OUT | USB_TYPE_VENDOR), /* | USB_RECIP_ENDPOINT), */
+ controlData,
+ 0,
+ &dummyCtlBuf, ctrl.numbytes, HZ * 10);
+ return retval;
+ break;
+ case PIUSB_ISHIGHSPEED:
+ return ((pdx->udev->speed == USB_SPEED_HIGH) ? 1 : 0);
+ break;
+ case PIUSB_WRITEPIPE:
+ if (copy_from_user(&ctrl, (void __user *)arg, _IOC_SIZE(cmd)))
+ info("copy_from_user WRITE_DUMMY failed\n");
+ if (!access_ok(VERIFY_READ, ctrl.pData, ctrl.numbytes)) {
+ dbg("can't access pData");
+ return 0;
+ }
+ piusb_output(&ctrl, ctrl.pData /*uBuf */ , ctrl.numbytes, pdx);
+ return ctrl.numbytes;
+ break;
+ case PIUSB_USERBUFFER:
+ if (copy_from_user
+ (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct)))
+ info("copy_from_user failed\n");
+ return MapUserBuffer((struct ioctl_struct *) & ctrl, pdx);
+ break;
+ case PIUSB_UNMAP_USERBUFFER:
+ UnMapUserBuffer(pdx);
+ return 0;
+ break;
+ case PIUSB_READPIPE:
+ if (copy_from_user
+ (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct)))
+ info("copy_from_user failed\n");
+ switch (ctrl.endpoint) {
+ case 0: //ST133 Pixel Data or PIXIS IO
+ if (pdx->iama == PIXIS_PID) {
+ unsigned int numToRead = 0;
+ unsigned int totalRead = 0;
+ uBuf = kmalloc(ctrl.numbytes, GFP_KERNEL);
+ if (!uBuf) {
+ dbg("Alloc for uBuf failed");
+ return 0;
+ }
+ numbytes = ctrl.numbytes;
+ numToRead = numbytes;
+ dbg("numbytes to read = %d", numbytes);
+ dbg("endpoint # %d", ctrl.endpoint);
+ if (copy_from_user(uBuf, ctrl.pData, numbytes))
+ dbg("copying ctrl.pData to dummyBuf failed");
+ do {
+ i = usb_bulk_msg(pdx->udev, pdx->hEP[ctrl.endpoint], (uBuf + totalRead), (numToRead > 64) ? 64 : numToRead, &numbytes, HZ * 10); //EP0 can only handle 64 bytes at a time
+ if (i) {
+ dbg("CMD = %s, Address = 0x%02X", ((uBuf[3] == 0x02) ? "WRITE" : "READ"), uBuf[1]);
+ dbg("Number of bytes Attempted to read = %d", (int)ctrl.numbytes);
+ dbg("Blocking ReadI/O Failed with status %d", i);
+ kfree(uBuf);
+ return -1;
+ } else {
+ dbg("Pixis EP0 Read %d bytes",
+ numbytes);
+ totalRead += numbytes;
+ numToRead -= numbytes;
+ }
+ }
+ while (numToRead);
+ memcpy(ctrl.pData, uBuf, totalRead);
+ dbg("Total Bytes Read from PIXIS EP0 = %d",
+ totalRead);
+ ctrl.numbytes = totalRead;
+ if (copy_to_user
+ ((struct ioctl_struct *) arg, &ctrl,
+ sizeof(struct ioctl_struct)))
+ dbg("copy_to_user failed in IORB");
+ kfree(uBuf);
+ return ctrl.numbytes;
+ } else //ST133 Pixel Data
+ {
+ if (!pdx->gotPixelData)
+ return 0;
+ else {
+ pdx->gotPixelData = 0;
+ ctrl.numbytes =
+ pdx->bulk_in_size_returned;
+ pdx->bulk_in_size_returned -=
+ pdx->frameSize;
+ for (i = 0; i < pdx->maplist_numPagesMapped[pdx->active_frame]; i++)
+ SetPageDirty(pdx->sgl[pdx->active_frame][i].page_link);
+ pdx->active_frame =
+ ((pdx->active_frame +
+ 1) % pdx->num_frames);
+ return ctrl.numbytes;
+ }
+ }
+ break;
+ case 1: //ST133IO
+ case 4: //PIXIS IO
+ uBuf = kmalloc(ctrl.numbytes, GFP_KERNEL);
+ if (!uBuf) {
+ dbg("Alloc for uBuf failed");
+ return 0;
+ }
+ numbytes = ctrl.numbytes;
+// dbg( "numbytes to read = %d", numbytes );
+ if (copy_from_user(uBuf, ctrl.pData, numbytes))
+ dbg("copying ctrl.pData to dummyBuf failed");
+ i = usb_bulk_msg(pdx->udev, pdx->hEP[ctrl.endpoint],
+ uBuf, numbytes, &numbytes, HZ * 10);
+ if (i) {
+ dbg("Blocking ReadI/O Failed with status %d",
+ i);
+ kfree(uBuf);
+ return -1;
+ } else {
+ ctrl.numbytes = numbytes;
+ memcpy(ctrl.pData, uBuf, numbytes);
+ if (copy_to_user
+ ((struct ioctl_struct *) arg, &ctrl,
+ sizeof(struct ioctl_struct)))
+ dbg("copy_to_user failed in IORB");
+ kfree(uBuf);
+ return ctrl.numbytes;
+ }
+ break;
+
+ case 2: //PIXIS Ping
+ case 3: //PIXIS Pong
+ if (!pdx->gotPixelData)
+ return 0;
+ else {
+ pdx->gotPixelData = 0;
+ ctrl.numbytes = pdx->bulk_in_size_returned;
+ pdx->bulk_in_size_returned -= pdx->frameSize;
+ for (i = 0;
+ i <
+ pdx->maplist_numPagesMapped[pdx->
+ active_frame];
+ i++)
+ SetPageDirty(pdx->sgl[pdx->active_frame][i].page_link);
+ pdx->active_frame =
+ ((pdx->active_frame + 1) % pdx->num_frames);
+ return ctrl.numbytes;
+ }
+ break;
+ }
+ break;
+ case PIUSB_WHATCAMERA:
+ return pdx->iama;
+ case PIUSB_SETFRAMESIZE:
+ dbg("PIUSB_SETFRAMESIZE");
+ if (copy_from_user
+ (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct)))
+ info("copy_from_user failed\n");
+ pdx->frameSize = ctrl.numbytes;
+ pdx->num_frames = ctrl.numFrames;
+ if (!pdx->sgl)
+ pdx->sgl =
+ kmalloc(sizeof(struct scatterlist *) *
+ pdx->num_frames, GFP_KERNEL);
+ if (!pdx->sgEntries)
+ pdx->sgEntries =
+ kmalloc(sizeof(unsigned int) * pdx->num_frames,
+ GFP_KERNEL);
+ if (!pdx->PixelUrb)
+ pdx->PixelUrb =
+ kmalloc(sizeof(struct urb **) * pdx->num_frames,
+ GFP_KERNEL);
+ if (!pdx->maplist_numPagesMapped)
+ pdx->maplist_numPagesMapped =
+ vmalloc(sizeof(unsigned int) * pdx->num_frames);
+ if (!pdx->pendedPixelUrbs)
+ pdx->pendedPixelUrbs =
+ kmalloc(sizeof(char *) * pdx->num_frames,
+ GFP_KERNEL);
+ return 0;
+ default:
+ dbg("%s\n", "No IOCTL found");
+ break;
+
+ }
+ /* return that we did not understand this ioctl call */
+ dbg("Returning -ENOTTY");
+ return -ENOTTY;
+}
+
+static void piusb_write_bulk_callback(struct urb *urb)
+{
+ struct device_extension *pdx = urb->context;
+ int status = urb->status;
+
+ /* sync/async unlink faults aren't errors */
+ if (status && !(status == -ENOENT || status == -ECONNRESET))
+ dev_dbg(&urb->dev->dev,
+ "%s - nonzero write bulk status received: %d",
+ __func__, status);
+
+ pdx->pendingWrite = 0;
+ usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
+}
+
+int piusb_output(struct ioctl_struct * io, unsigned char *uBuf, int len,
+ struct device_extension *pdx)
+{
+ struct urb *urb = NULL;
+ int err = 0;
+ unsigned char *kbuf = NULL;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (urb != NULL) {
+ kbuf =
+ usb_buffer_alloc(pdx->udev, len, GFP_KERNEL,
+ &urb->transfer_dma);
+ if (!kbuf) {
+ info("buffer_alloc failed\n");
+ return -ENOMEM;
+ }
+ memcpy(kbuf, uBuf, len);
+ usb_fill_bulk_urb(urb, pdx->udev, pdx->hEP[io->endpoint], kbuf,
+ len, piusb_write_bulk_callback, pdx);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err) {
+ dev_err(&pdx->udev->dev,
+ "WRITE ERROR:submit urb error = %d\n", err);
+ }
+ pdx->pendingWrite = 1;
+ usb_free_urb(urb);
+ }
+ return -EINPROGRESS;
+}
+
+static int UnMapUserBuffer(struct device_extension *pdx)
+{
+ int i = 0;
+ int k = 0;
+ unsigned int epAddr;
+ for (k = 0; k < pdx->num_frames; k++) {
+ dbg("Killing Urbs for Frame %d", k);
+ for (i = 0; i < pdx->sgEntries[k]; i++) {
+ usb_kill_urb(pdx->PixelUrb[k][i]);
+ usb_free_urb(pdx->PixelUrb[k][i]);
+ pdx->pendedPixelUrbs[k][i] = 0;
+ }
+ dbg("Urb error count = %d", errCnt);
+ errCnt = 0;
+ dbg("Urbs free'd and Killed for Frame %d", k);
+ }
+
+ for (k = 0; k < pdx->num_frames; k++) {
+ if (pdx->iama == PIXIS_PID) //if so, which EP should we map this frame to
+ {
+ if (k % 2) //check to see if this should use EP4(PONG)
+ {
+ epAddr = pdx->hEP[3]; //PONG, odd frames
+ } else {
+ epAddr = pdx->hEP[2]; //PING, even frames and zero
+ }
+ } else //ST133 only has 1 endpoint for Pixel data transfer
+ {
+ epAddr = pdx->hEP[0];
+ }
+ usb_buffer_unmap_sg(pdx->udev, epAddr, pdx->sgl[k],
+ pdx->maplist_numPagesMapped[k]);
+ for (i = 0; i < pdx->maplist_numPagesMapped[k]; i++) {
+ page_cache_release(pdx->sgl[k][i].page_link);
+ }
+ kfree(pdx->sgl[k]);
+ kfree(pdx->PixelUrb[k]);
+ kfree(pdx->pendedPixelUrbs[k]);
+ pdx->sgl[k] = NULL;
+ pdx->PixelUrb[k] = NULL;
+ pdx->pendedPixelUrbs[k] = NULL;
+ }
+ kfree(pdx->sgEntries);
+ vfree(pdx->maplist_numPagesMapped);
+ pdx->sgEntries = NULL;
+ pdx->maplist_numPagesMapped = NULL;
+ kfree(pdx->sgl);
+ kfree(pdx->pendedPixelUrbs);
+ kfree(pdx->PixelUrb);
+ pdx->sgl = NULL;
+ pdx->pendedPixelUrbs = NULL;
+ pdx->PixelUrb = NULL;
+ return 0;
+}
+
+static void piusb_readPIXEL_callback(struct urb *urb)
+{
+ int i = 0;
+ struct device_extension *pdx = urb->context;
+ int status = urb->status;
+
+ if (status && !(status == -ENOENT || status == -ECONNRESET)) {
+ dbg("%s - nonzero read bulk status received: %d", __func__,
+ status);
+ dbg("Error in read EP2 callback");
+ dbg("FrameIndex = %d", pdx->frameIdx);
+ dbg("Bytes received before problem occurred = %d",
+ pdx->bulk_in_byte_trk);
+ dbg("Urb Idx = %d", pdx->urbIdx);
+ pdx->pendedPixelUrbs[pdx->frameIdx][pdx->urbIdx] = 0;
+ } else {
+ pdx->bulk_in_byte_trk += urb->actual_length;
+ {
+ i = usb_submit_urb(urb, GFP_ATOMIC); //resubmit the URB
+ if (i) {
+ errCnt++;
+ if (i != lastErr) {
+ dbg("submit urb in callback failed with error code %d", i);
+ lastErr = i;
+ }
+ } else {
+ pdx->urbIdx++; //point to next URB when we callback
+ if (pdx->bulk_in_byte_trk >= pdx->frameSize) {
+ pdx->bulk_in_size_returned =
+ pdx->bulk_in_byte_trk;
+ pdx->bulk_in_byte_trk = 0;
+ pdx->gotPixelData = 1;
+ pdx->frameIdx =
+ ((pdx->frameIdx +
+ 1) % pdx->num_frames);
+ pdx->urbIdx = 0;
+ }
+ }
+ }
+ }
+}
+
+/* MapUserBuffer(
+ inputs:
+ struct ioctl_struct *io - structure containing user address, frame #, and size
+ struct device_extension *pdx - the PIUSB device extension
+ returns:
+ int - status of the task
+ Notes:
+ MapUserBuffer maps a buffer passed down through an ioctl. The user buffer is Page Aligned by the app
+ and then passed down. The function get_free_pages(...) does the actual mapping of the buffer from user space to
+ kernel space. From there a scatterlist is created from all the pages. The next function called is to usb_buffer_map_sg
+ which allocated DMA addresses for each page, even coalescing them if possible. The DMA address is placed in the scatterlist
+ structure. The function returns the number of DMA addresses. This may or may not be equal to the number of pages that
+ the user buffer uses. We then build an URB for each DMA address and then submit them.
+*/
+//int MapUserBuffer( unsigned long uaddr, unsigned long numbytes, unsigned long frameInfo, struct device_extension *pdx )
+static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx)
+{
+ unsigned long uaddr;
+ unsigned long numbytes;
+ int frameInfo; //which frame we're mapping
+ unsigned int epAddr = 0;
+ unsigned long count = 0;
+ int i = 0;
+ int k = 0;
+ int err = 0;
+ struct page **maplist_p;
+ int numPagesRequired;
+ frameInfo = io->numFrames;
+ uaddr = (unsigned long)io->pData;
+ numbytes = io->numbytes;
+
+ if (pdx->iama == PIXIS_PID) //if so, which EP should we map this frame to
+ {
+ if (frameInfo % 2) //check to see if this should use EP4(PONG)
+ {
+ epAddr = pdx->hEP[3]; //PONG, odd frames
+ } else {
+ epAddr = pdx->hEP[2]; //PING, even frames and zero
+ }
+ dbg("Pixis Frame #%d: EP=%d", frameInfo,
+ (epAddr == pdx->hEP[2]) ? 2 : 4);
+ } else //ST133 only has 1 endpoint for Pixel data transfer
+ {
+ epAddr = pdx->hEP[0];
+ dbg("ST133 Frame #%d: EP=2", frameInfo);
+ }
+ count = numbytes;
+ dbg("UserAddress = 0x%08lX", uaddr);
+ dbg("numbytes = %d", (int)numbytes);
+ //number of pages to map the entire user space DMA buffer
+ numPagesRequired =
+ ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
+ dbg("Number of pages needed = %d", numPagesRequired);
+ maplist_p = vmalloc(numPagesRequired * sizeof(struct page)); //, GFP_ATOMIC);
+ if (!maplist_p) {
+ dbg("Can't Allocate Memory for maplist_p");
+ return -ENOMEM;
+ }
+ //map the user buffer to kernel memory
+ down_write(&current->mm->mmap_sem);
+ pdx->maplist_numPagesMapped[frameInfo] = get_user_pages(current, current->mm, (uaddr & PAGE_MASK), numPagesRequired, WRITE, 0, //Don't Force
+ maplist_p,
+ NULL);
+ up_write(&current->mm->mmap_sem);
+ dbg("Number of pages mapped = %d",
+ pdx->maplist_numPagesMapped[frameInfo]);
+ for (i = 0; i < pdx->maplist_numPagesMapped[frameInfo]; i++)
+ flush_dcache_page(maplist_p[i]);
+ if (!pdx->maplist_numPagesMapped[frameInfo]) {
+ dbg("get_user_pages() failed");
+ vfree(maplist_p);
+ return -ENOMEM;
+ }
+ //need to create a scatterlist that spans each frame that can fit into the mapped buffer
+ pdx->sgl[frameInfo] =
+ kmalloc((pdx->maplist_numPagesMapped[frameInfo] *
+ sizeof(struct scatterlist)), GFP_ATOMIC);
+ if (!pdx->sgl[frameInfo]) {
+ vfree(maplist_p);
+ dbg("can't allocate mem for sgl");
+ return -ENOMEM;
+ }
+ pdx->sgl[frameInfo][0].page_link = maplist_p[0];
+ pdx->sgl[frameInfo][0].offset = uaddr & ~PAGE_MASK;
+ if (pdx->maplist_numPagesMapped[frameInfo] > 1) {
+ pdx->sgl[frameInfo][0].length =
+ PAGE_SIZE - pdx->sgl[frameInfo][0].offset;
+ count -= pdx->sgl[frameInfo][0].length;
+ for (k = 1; k < pdx->maplist_numPagesMapped[frameInfo]; k++) {
+ pdx->sgl[frameInfo][k].offset = 0;
+ pdx->sgl[frameInfo][k].page_link = maplist_p[k];
+ pdx->sgl[frameInfo][k].length =
+ (count < PAGE_SIZE) ? count : PAGE_SIZE;
+ count -= PAGE_SIZE; //example had PAGE_SIZE here;
+ }
+ } else {
+ pdx->sgl[frameInfo][0].length = count;
+ }
+ pdx->sgEntries[frameInfo] =
+ usb_buffer_map_sg(pdx->udev, epAddr, pdx->sgl[frameInfo],
+ pdx->maplist_numPagesMapped[frameInfo]);
+ dbg("number of sgEntries = %d", pdx->sgEntries[frameInfo]);
+ pdx->userBufMapped = 1;
+ vfree(maplist_p);
+ //Create and Send the URB's for each s/g entry
+ pdx->PixelUrb[frameInfo] =
+ kmalloc(pdx->sgEntries[frameInfo] * sizeof(struct urb *),
+ GFP_KERNEL);
+ if (!pdx->PixelUrb[frameInfo]) {
+ dbg("Can't Allocate Memory for Urb");
+ return -ENOMEM;
+ }
+ for (i = 0; i < pdx->sgEntries[frameInfo]; i++) {
+ pdx->PixelUrb[frameInfo][i] = usb_alloc_urb(0, GFP_KERNEL); //0 because we're using BULK transfers
+ usb_fill_bulk_urb(pdx->PixelUrb[frameInfo][i],
+ pdx->udev,
+ epAddr,
+ (dma_addr_t *) sg_dma_address(&pdx->
+ sgl[frameInfo]
+ [i]),
+ sg_dma_len(&pdx->sgl[frameInfo][i]),
+ piusb_readPIXEL_callback, (void *)pdx);
+ pdx->PixelUrb[frameInfo][i]->transfer_dma =
+ sg_dma_address(&pdx->sgl[frameInfo][i]);
+ pdx->PixelUrb[frameInfo][i]->transfer_flags =
+ URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
+ }
+ pdx->PixelUrb[frameInfo][--i]->transfer_flags &= ~URB_NO_INTERRUPT; //only interrupt when last URB completes
+ pdx->pendedPixelUrbs[frameInfo] =
+ kmalloc((pdx->sgEntries[frameInfo] * sizeof(char)), GFP_KERNEL);
+ if (!pdx->pendedPixelUrbs[frameInfo])
+ dbg("Can't allocate Memory for pendedPixelUrbs");
+ for (i = 0; i < pdx->sgEntries[frameInfo]; i++) {
+ err = usb_submit_urb(pdx->PixelUrb[frameInfo][i], GFP_ATOMIC);
+ if (err) {
+ dbg("%s %d\n", "submit urb error =", err);
+ pdx->pendedPixelUrbs[frameInfo][i] = 0;
+ return err;
+ } else
+ pdx->pendedPixelUrbs[frameInfo][i] = 1;;
+ }
+ return 0;
+}
+
+static struct file_operations piusb_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = piusb_ioctl,
+ .open = piusb_open,
+ .release = piusb_release,
+};
+
+static struct usb_class_driver piusb_class = {
+ .name = "usb/rspiusb%d",
+ .fops = &piusb_fops,
+ .minor_base = PIUSB_MINOR_BASE,
+};
+
+/**
+ * piusb_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int piusb_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct device_extension *pdx = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+ int retval = -ENOMEM;
+
+ dev_dbg(&interface->dev, "%s - Looking for PI USB Hardware", __func__);
+
+ pdx = kzalloc(sizeof(struct device_extension), GFP_KERNEL);
+ if (pdx == NULL) {
+ dev_err(&interface->dev, "Out of memory\n");
+ goto error;
+ }
+ kref_init(&pdx->kref);
+ pdx->udev = usb_get_dev(interface_to_usbdev(interface));
+ pdx->interface = interface;
+ iface_desc = interface->cur_altsetting;
+
+ /* See if the device offered us matches what we can accept */
+ if ((pdx->udev->descriptor.idVendor != VENDOR_ID)
+ || ((pdx->udev->descriptor.idProduct != PIXIS_PID)
+ && (pdx->udev->descriptor.idProduct != ST133_PID))) {
+ return -ENODEV;
+ }
+ pdx->iama = pdx->udev->descriptor.idProduct;
+
+ if (debug) {
+ if (pdx->udev->descriptor.idProduct == PIXIS_PID)
+ dbg("PIUSB:Pixis Camera Found");
+ else
+ dbg("PIUSB:ST133 USB Controller Found");
+ if (pdx->udev->speed == USB_SPEED_HIGH)
+ dbg("Highspeed(USB2.0) Device Attached");
+ else
+ dbg("Lowspeed (USB1.1) Device Attached");
+
+ dbg("NumEndpoints in Configuration: %d",
+ iface_desc->desc.bNumEndpoints);
+ }
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+ if (debug) {
+ dbg("Endpoint[%d]->bDescriptorType = %d", i,
+ endpoint->bDescriptorType);
+ dbg("Endpoint[%d]->bEndpointAddress = 0x%02X", i,
+ endpoint->bEndpointAddress);
+ dbg("Endpoint[%d]->bbmAttributes = %d", i,
+ endpoint->bmAttributes);
+ dbg("Endpoint[%d]->MaxPacketSize = %d\n", i,
+ endpoint->wMaxPacketSize);
+ }
+ if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_BULK) {
+ if (endpoint->bEndpointAddress & USB_DIR_IN)
+ pdx->hEP[i] =
+ usb_rcvbulkpipe(pdx->udev,
+ endpoint->bEndpointAddress);
+ else
+ pdx->hEP[i] =
+ usb_sndbulkpipe(pdx->udev,
+ endpoint->bEndpointAddress);
+ }
+ }
+ usb_set_intfdata(interface, pdx);
+ retval = usb_register_dev(interface, &piusb_class);
+ if (retval) {
+ err("Not able to get a minor for this device.");
+ usb_set_intfdata(interface, NULL);
+ goto error;
+ }
+ pdx->present = 1;
+
+ /* we can register the device now, as it is ready */
+ pdx->minor = interface->minor;
+ /* let the user know what node this device is now attached to */
+ dbg("PI USB2.0 device now attached to piusb-%d", pdx->minor);
+ return 0;
+
+ error:
+ if (pdx)
+ kref_put(&pdx->kref, piusb_delete);
+ return retval;
+}
+
+/**
+ * piusb_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ *
+ * This routine guarantees that the driver will not submit any more urbs
+ * by clearing pdx->udev. It is also supposed to terminate any currently
+ * active urbs. Unfortunately, usb_bulk_msg(), used in piusb_read(), does
+ * not provide any way to do this. But at least we can cancel an active
+ * write.
+ */
+static void piusb_disconnect(struct usb_interface *interface)
+{
+ struct device_extension *pdx;
+ int minor = interface->minor;
+ lock_kernel();
+ pdx = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+ /* give back our minor */
+ usb_deregister_dev(interface, &piusb_class);
+ unlock_kernel();
+ /* prevent device read, write and ioctl */
+ pdx->present = 0;
+ kref_put(&pdx->kref, piusb_delete);
+ dbg("PI USB2.0 device #%d now disconnected\n", minor);
+}
+
+static struct usb_driver piusb_driver = {
+ .name = "sub",
+ .probe = piusb_probe,
+ .disconnect = piusb_disconnect,
+ .id_table = pi_device_table,
+};
+
+/**
+ * piusb_init
+ */
+static int __init piusb_init(void)
+{
+ int result;
+ /* register this driver with the USB subsystem */
+ result = usb_register(&piusb_driver);
+ if (result) {
+ printk(KERN_ERR KBUILD_MODNAME
+ ": usb_register failed. Error number %d\n", result);
+ return result;
+ }
+ printk(KERN_INFO KBUILD_MODNAME ":%s: %s\n", DRIVER_DESC,
+ DRIVER_VERSION);
+ return 0;
+}
+
+/**
+ * piusb_exit
+ */
+static void __exit piusb_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&piusb_driver);
+}
+
+module_init(piusb_init);
+module_exit(piusb_exit);
+
+/* Module parameters */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/rspiusb/rspiusb.h b/drivers/staging/rspiusb/rspiusb.h
new file mode 100644
index 000000000000..965cd2d8c194
--- /dev/null
+++ b/drivers/staging/rspiusb/rspiusb.h
@@ -0,0 +1,25 @@
+#ifndef __RSPIUSB_H
+#define __RSPIUSB_H
+
+#define PIUSB_MAGIC 'm'
+#define PIUSB_IOCTL_BASE 192
+#define PIUSB_GETVNDCMD _IOR(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 1, struct ioctl_struct)
+#define PIUSB_SETVNDCMD _IOW(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 2, struct ioctl_struct)
+#define PIUSB_WRITEPIPE _IOW(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 3, struct ioctl_struct)
+#define PIUSB_READPIPE _IOR(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 4, struct ioctl_struct)
+#define PIUSB_SETFRAMESIZE _IOW(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 5, struct ioctl_struct)
+#define PIUSB_WHATCAMERA _IO(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 6)
+#define PIUSB_USERBUFFER _IOW(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 7, struct ioctl_struct)
+#define PIUSB_ISHIGHSPEED _IO(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 8)
+#define PIUSB_UNMAP_USERBUFFER _IOW(PIUSB_MAGIC, PIUSB_IOCTL_BASE + 9, struct ioctl_struct)
+
+struct ioctl_struct {
+ unsigned char cmd;
+ unsigned long numbytes;
+ unsigned char dir; //1=out;0=in
+ int endpoint;
+ int numFrames;
+ unsigned char *pData;
+};
+
+#endif
diff --git a/drivers/staging/rt2860/2860_main_dev.c b/drivers/staging/rt2860/2860_main_dev.c
new file mode 100644
index 000000000000..08ca81f43cc8
--- /dev/null
+++ b/drivers/staging/rt2860/2860_main_dev.c
@@ -0,0 +1,1377 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ 2870_main_dev.c
+
+ Abstract:
+ Create and register network interface.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+*/
+
+#include "rt_config.h"
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+// record whether the card in the card list is used in the card file
+extern UINT8 MC_CardUsed[];
+#endif // MULTIPLE_CARD_SUPPORT //
+
+
+extern INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
+ IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
+
+static void rx_done_tasklet(unsigned long data);
+static void mgmt_dma_done_tasklet(unsigned long data);
+static void ac0_dma_done_tasklet(unsigned long data);
+static void ac1_dma_done_tasklet(unsigned long data);
+static void ac2_dma_done_tasklet(unsigned long data);
+static void ac3_dma_done_tasklet(unsigned long data);
+static void hcca_dma_done_tasklet(unsigned long data);
+static void fifo_statistic_full_tasklet(unsigned long data);
+
+
+/*---------------------------------------------------------------------*/
+/* Symbol & Macro Definitions */
+/*---------------------------------------------------------------------*/
+#define RT2860_INT_RX_DLY (1<<0) // bit 0
+#define RT2860_INT_TX_DLY (1<<1) // bit 1
+#define RT2860_INT_RX_DONE (1<<2) // bit 2
+#define RT2860_INT_AC0_DMA_DONE (1<<3) // bit 3
+#define RT2860_INT_AC1_DMA_DONE (1<<4) // bit 4
+#define RT2860_INT_AC2_DMA_DONE (1<<5) // bit 5
+#define RT2860_INT_AC3_DMA_DONE (1<<6) // bit 6
+#define RT2860_INT_HCCA_DMA_DONE (1<<7) // bit 7
+#define RT2860_INT_MGMT_DONE (1<<8) // bit 8
+
+#define INT_RX RT2860_INT_RX_DONE
+
+#define INT_AC0_DLY (RT2860_INT_AC0_DMA_DONE) //| RT2860_INT_TX_DLY)
+#define INT_AC1_DLY (RT2860_INT_AC1_DMA_DONE) //| RT2860_INT_TX_DLY)
+#define INT_AC2_DLY (RT2860_INT_AC2_DMA_DONE) //| RT2860_INT_TX_DLY)
+#define INT_AC3_DLY (RT2860_INT_AC3_DMA_DONE) //| RT2860_INT_TX_DLY)
+#define INT_HCCA_DLY (RT2860_INT_HCCA_DMA_DONE) //| RT2860_INT_TX_DLY)
+#define INT_MGMT_DLY RT2860_INT_MGMT_DONE
+
+/*---------------------------------------------------------------------*/
+/* Prototypes of Functions Used */
+/*---------------------------------------------------------------------*/
+/* function declarations */
+static INT __devinit rt2860_init_one (struct pci_dev *pci_dev, const struct pci_device_id *ent);
+static VOID __devexit rt2860_remove_one(struct pci_dev *pci_dev);
+static INT __devinit rt2860_probe(struct pci_dev *pci_dev, const struct pci_device_id *ent);
+void init_thread_task(PRTMP_ADAPTER pAd);
+static void __exit rt2860_cleanup_module(void);
+static int __init rt2860_init_module(void);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#ifdef CONFIG_PM
+static int rt2860_suspend(struct pci_dev *pci_dev, pm_message_t state);
+static int rt2860_resume(struct pci_dev *pci_dev);
+#endif // CONFIG_PM //
+#endif
+
+
+//
+// Ralink PCI device table, include all supported chipsets
+//
+static struct pci_device_id rt2860_pci_tbl[] __devinitdata =
+{
+ {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCI_DEVICE_ID)}, //RT28602.4G
+ {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2860_PCIe_DEVICE_ID)},
+ {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2760_PCI_DEVICE_ID)},
+ {PCI_DEVICE(NIC_PCI_VENDOR_ID, NIC2790_PCIe_DEVICE_ID)},
+ {PCI_DEVICE(VEN_AWT_PCI_VENDOR_ID, VEN_AWT_PCIe_DEVICE_ID)},
+ {0,} // terminate list
+};
+
+MODULE_DEVICE_TABLE(pci, rt2860_pci_tbl);
+#ifdef CONFIG_STA_SUPPORT
+MODULE_LICENSE("GPL");
+#ifdef MODULE_VERSION
+MODULE_VERSION(STA_DRIVER_VERSION);
+#endif
+#endif // CONFIG_STA_SUPPORT //
+
+
+//
+// Our PCI driver structure
+//
+static struct pci_driver rt2860_driver =
+{
+ name: "rt2860",
+ id_table: rt2860_pci_tbl,
+ probe: rt2860_init_one,
+#if LINUX_VERSION_CODE >= 0x20412
+ remove: __devexit_p(rt2860_remove_one),
+#else
+ remove: __devexit(rt2860_remove_one),
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#ifdef CONFIG_PM
+ suspend: rt2860_suspend,
+ resume: rt2860_resume,
+#endif
+#endif
+};
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#ifdef CONFIG_PM
+
+VOID RT2860RejectPendingPackets(
+ IN PRTMP_ADAPTER pAd)
+{
+ // clear PS packets
+ // clear TxSw packets
+}
+
+static int rt2860_suspend(
+ struct pci_dev *pci_dev,
+ pm_message_t state)
+{
+ struct net_device *net_dev = pci_get_drvdata(pci_dev);
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL;
+ INT32 retval;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n"));
+
+ if (net_dev == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
+ }
+ else
+ {
+ pAd = net_dev->ml_priv;
+
+ /* we can not use IFF_UP because ra0 down but ra1 up */
+ /* and 1 suspend/resume function for 1 module, not for each interface */
+ /* so Linux will call suspend/resume function once */
+ if (VIRTUAL_IF_NUM(pAd) > 0)
+ {
+ // avoid users do suspend after interface is down
+
+ // stop interface
+ netif_carrier_off(net_dev);
+ netif_stop_queue(net_dev);
+
+ // mark device as removed from system and therefore no longer available
+ netif_device_detach(net_dev);
+
+ // mark halt flag
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+ // take down the device
+ rt28xx_close((PNET_DEV)net_dev);
+
+ RT_MOD_DEC_USE_COUNT();
+ }
+ }
+
+ // reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html
+ // enable device to generate PME# when suspended
+ // pci_choose_state(): Choose the power state of a PCI device to be suspended
+ retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1);
+ // save the PCI configuration space of a device before suspending
+ pci_save_state(pci_dev);
+ // disable PCI device after use
+ pci_disable_device(pci_dev);
+
+ retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_suspend()\n"));
+ return retval;
+}
+
+static int rt2860_resume(
+ struct pci_dev *pci_dev)
+{
+ struct net_device *net_dev = pci_get_drvdata(pci_dev);
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL;
+ INT32 retval;
+
+
+ // set the power state of a PCI device
+ // PCI has 4 power states, DO (normal) ~ D3(less power)
+ // in include/linux/pci.h, you can find that
+ // #define PCI_D0 ((pci_power_t __force) 0)
+ // #define PCI_D1 ((pci_power_t __force) 1)
+ // #define PCI_D2 ((pci_power_t __force) 2)
+ // #define PCI_D3hot ((pci_power_t __force) 3)
+ // #define PCI_D3cold ((pci_power_t __force) 4)
+ // #define PCI_UNKNOWN ((pci_power_t __force) 5)
+ // #define PCI_POWER_ERROR ((pci_power_t __force) -1)
+ retval = pci_set_power_state(pci_dev, PCI_D0);
+
+ // restore the saved state of a PCI device
+ pci_restore_state(pci_dev);
+
+ // initialize device before it's used by a driver
+ if (pci_enable_device(pci_dev))
+ {
+ printk("pci enable fail!\n");
+ return 0;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_resume()\n"));
+
+ if (net_dev == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
+ }
+ else
+ pAd = net_dev->ml_priv;
+
+ if (pAd != NULL)
+ {
+ /* we can not use IFF_UP because ra0 down but ra1 up */
+ /* and 1 suspend/resume function for 1 module, not for each interface */
+ /* so Linux will call suspend/resume function once */
+ if (VIRTUAL_IF_NUM(pAd) > 0)
+ {
+ // mark device as attached from system and restart if needed
+ netif_device_attach(net_dev);
+
+ if (rt28xx_open((PNET_DEV)net_dev) != 0)
+ {
+ // open fail
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n"));
+ return 0;
+ }
+
+ // increase MODULE use count
+ RT_MOD_INC_USE_COUNT();
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+ netif_start_queue(net_dev);
+ netif_carrier_on(net_dev);
+ netif_wake_queue(net_dev);
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_resume()\n"));
+ return 0;
+}
+#endif // CONFIG_PM //
+#endif
+
+
+static INT __init rt2860_init_module(VOID)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ return pci_register_driver(&rt2860_driver);
+#else
+ return pci_module_init(&rt2860_driver);
+#endif
+}
+
+
+//
+// Driver module unload function
+//
+static VOID __exit rt2860_cleanup_module(VOID)
+{
+ pci_unregister_driver(&rt2860_driver);
+}
+
+module_init(rt2860_init_module);
+module_exit(rt2860_cleanup_module);
+
+
+static INT __devinit rt2860_init_one (
+ IN struct pci_dev *pci_dev,
+ IN const struct pci_device_id *ent)
+{
+ INT rc;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_init_one\n"));
+
+ // wake up and enable device
+ if (pci_enable_device (pci_dev))
+ {
+ rc = -EIO;
+ }
+ else
+ {
+ rc = rt2860_probe(pci_dev, ent);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_init_one\n"));
+ return rc;
+}
+
+
+static VOID __devexit rt2860_remove_one(
+ IN struct pci_dev *pci_dev)
+{
+ struct net_device *net_dev = pci_get_drvdata(pci_dev);
+ RTMP_ADAPTER *pAd = net_dev->ml_priv;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_remove_one\n"));
+
+ if (pAd != NULL)
+ {
+#ifdef MULTIPLE_CARD_SUPPORT
+ if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD))
+ MC_CardUsed[pAd->MC_RowID] = 0; // not clear MAC address
+#endif // MULTIPLE_CARD_SUPPORT //
+
+
+
+
+ // Unregister network device
+ unregister_netdev(net_dev);
+
+ // Unmap CSR base address
+ iounmap((char *)(net_dev->base_addr));
+
+ RTMPFreeAdapter(pAd);
+
+ // release memory region
+ release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));
+ }
+ else
+ {
+ // Unregister network device
+ unregister_netdev(net_dev);
+
+ // Unmap CSR base address
+ iounmap((char *)(net_dev->base_addr));
+
+ // release memory region
+ release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));
+ }
+
+ // Free pre-allocated net_device memory
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ free_netdev(net_dev);
+#else
+ kfree(net_dev);
+#endif
+}
+
+//
+// PCI device probe & initialization function
+//
+static INT __devinit rt2860_probe(
+ IN struct pci_dev *pci_dev,
+ IN const struct pci_device_id *ent)
+{
+ PRTMP_ADAPTER pAd;
+ INT rv = 0;
+
+ rv = (INT)rt28xx_probe((void *)pci_dev, (void *)ent, 0, &pAd);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE);
+ return rv;
+}
+
+
+void init_thread_task(IN PRTMP_ADAPTER pAd)
+{
+ POS_COOKIE pObj;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ tasklet_init(&pObj->rx_done_task, rx_done_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->mgmt_dma_done_task, mgmt_dma_done_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->ac0_dma_done_task, ac0_dma_done_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->ac1_dma_done_task, ac1_dma_done_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->ac2_dma_done_task, ac2_dma_done_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->ac3_dma_done_task, ac3_dma_done_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->hcca_dma_done_task, hcca_dma_done_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->tbtt_task, tbtt_tasklet, (unsigned long)pAd);
+ tasklet_init(&pObj->fifo_statistic_full_task, fifo_statistic_full_tasklet, (unsigned long)pAd);
+}
+
+void kill_thread_task(IN PRTMP_ADAPTER pAd)
+{
+ POS_COOKIE pObj;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ tasklet_kill(&pObj->rx_done_task);
+ tasklet_kill(&pObj->mgmt_dma_done_task);
+ tasklet_kill(&pObj->ac0_dma_done_task);
+ tasklet_kill(&pObj->ac1_dma_done_task);
+ tasklet_kill(&pObj->ac2_dma_done_task);
+ tasklet_kill(&pObj->ac3_dma_done_task);
+ tasklet_kill(&pObj->hcca_dma_done_task);
+ tasklet_kill(&pObj->tbtt_task);
+ tasklet_kill(&pObj->fifo_statistic_full_task);
+}
+
+
+static void rt2860_int_enable(PRTMP_ADAPTER pAd, unsigned int mode)
+{
+ u32 regValue;
+
+ pAd->int_disable_mask &= ~(mode);
+ regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask);
+ RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 1:enable
+
+ if (regValue != 0)
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
+}
+
+
+static void rt2860_int_disable(PRTMP_ADAPTER pAd, unsigned int mode)
+{
+ u32 regValue;
+
+ pAd->int_disable_mask |= mode;
+ regValue = pAd->int_enable_reg & ~(pAd->int_disable_mask);
+ RTMP_IO_WRITE32(pAd, INT_MASK_CSR, regValue); // 0: disable
+
+ if (regValue == 0)
+ {
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
+ }
+}
+
+static void mgmt_dma_done_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ INT_SOURCE_CSR_STRUC IntSource;
+ POS_COOKIE pObj;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IntSource.word = 0;
+ IntSource.field.MgmtDmaDone = 1;
+ pAd->int_pending &= ~INT_MGMT_DLY;
+
+ RTMPHandleMgmtRingDmaDoneInterrupt(pAd);
+
+ // if you use RTMP_SEM_LOCK, sometimes kernel will hang up, no any
+ // bug report output
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ /*
+ * double check to avoid lose of interrupts
+ */
+ if (pAd->int_pending & INT_MGMT_DLY)
+ {
+ tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable TxDataInt again */
+ rt2860_int_enable(pAd, INT_MGMT_DLY);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+}
+
+static void rx_done_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ BOOLEAN bReschedule = 0;
+ POS_COOKIE pObj;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ pAd->int_pending &= ~(INT_RX);
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ bReschedule = STARxDoneInterruptHandle(pAd, 0);
+#endif // CONFIG_STA_SUPPORT //
+
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ /*
+ * double check to avoid rotting packet
+ */
+ if (pAd->int_pending & INT_RX || bReschedule)
+ {
+ tasklet_hi_schedule(&pObj->rx_done_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable RxINT again */
+ rt2860_int_enable(pAd, INT_RX);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+
+}
+
+void fifo_statistic_full_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ POS_COOKIE pObj;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ pAd->int_pending &= ~(FifoStaFullInt);
+ NICUpdateFifoStaCounters(pAd);
+
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ /*
+ * double check to avoid rotting packet
+ */
+ if (pAd->int_pending & FifoStaFullInt)
+ {
+ tasklet_hi_schedule(&pObj->fifo_statistic_full_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable RxINT again */
+
+ rt2860_int_enable(pAd, FifoStaFullInt);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+
+}
+
+static void hcca_dma_done_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ INT_SOURCE_CSR_STRUC IntSource;
+ POS_COOKIE pObj;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+
+ IntSource.word = 0;
+ IntSource.field.HccaDmaDone = 1;
+ pAd->int_pending &= ~INT_HCCA_DLY;
+
+ RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
+
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ /*
+ * double check to avoid lose of interrupts
+ */
+ if (pAd->int_pending & INT_HCCA_DLY)
+ {
+ tasklet_hi_schedule(&pObj->hcca_dma_done_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable TxDataInt again */
+ rt2860_int_enable(pAd, INT_HCCA_DLY);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+}
+
+static void ac3_dma_done_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ INT_SOURCE_CSR_STRUC IntSource;
+ POS_COOKIE pObj;
+ BOOLEAN bReschedule = 0;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IntSource.word = 0;
+ IntSource.field.Ac3DmaDone = 1;
+ pAd->int_pending &= ~INT_AC3_DLY;
+
+ bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
+
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ /*
+ * double check to avoid lose of interrupts
+ */
+ if ((pAd->int_pending & INT_AC3_DLY) || bReschedule)
+ {
+ tasklet_hi_schedule(&pObj->ac3_dma_done_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable TxDataInt again */
+ rt2860_int_enable(pAd, INT_AC3_DLY);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+}
+
+static void ac2_dma_done_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ INT_SOURCE_CSR_STRUC IntSource;
+ POS_COOKIE pObj;
+ BOOLEAN bReschedule = 0;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IntSource.word = 0;
+ IntSource.field.Ac2DmaDone = 1;
+ pAd->int_pending &= ~INT_AC2_DLY;
+
+ bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
+
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+
+ /*
+ * double check to avoid lose of interrupts
+ */
+ if ((pAd->int_pending & INT_AC2_DLY) || bReschedule)
+ {
+ tasklet_hi_schedule(&pObj->ac2_dma_done_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable TxDataInt again */
+ rt2860_int_enable(pAd, INT_AC2_DLY);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+}
+
+static void ac1_dma_done_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ INT_SOURCE_CSR_STRUC IntSource;
+ POS_COOKIE pObj;
+ BOOLEAN bReschedule = 0;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IntSource.word = 0;
+ IntSource.field.Ac1DmaDone = 1;
+ pAd->int_pending &= ~INT_AC1_DLY;
+
+ bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
+
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ /*
+ * double check to avoid lose of interrupts
+ */
+ if ((pAd->int_pending & INT_AC1_DLY) || bReschedule)
+ {
+ tasklet_hi_schedule(&pObj->ac1_dma_done_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable TxDataInt again */
+ rt2860_int_enable(pAd, INT_AC1_DLY);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+}
+
+static void ac0_dma_done_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) data;
+ INT_SOURCE_CSR_STRUC IntSource;
+ POS_COOKIE pObj;
+ BOOLEAN bReschedule = 0;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+ IntSource.word = 0;
+ IntSource.field.Ac0DmaDone = 1;
+ pAd->int_pending &= ~INT_AC0_DLY;
+
+ bReschedule = RTMPHandleTxRingDmaDoneInterrupt(pAd, IntSource);
+
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ /*
+ * double check to avoid lose of interrupts
+ */
+ if ((pAd->int_pending & INT_AC0_DLY) || bReschedule)
+ {
+ tasklet_hi_schedule(&pObj->ac0_dma_done_task);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+ return;
+ }
+
+ /* enable TxDataInt again */
+ rt2860_int_enable(pAd, INT_AC0_DLY);
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+}
+
+
+int print_int_count;
+
+IRQ_HANDLE_TYPE
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19))
+rt2860_interrupt(int irq, void *dev_instance)
+#else
+rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+#endif
+{
+ struct net_device *net_dev = (struct net_device *) dev_instance;
+ PRTMP_ADAPTER pAd = net_dev->ml_priv;
+ INT_SOURCE_CSR_STRUC IntSource;
+ POS_COOKIE pObj;
+
+ pObj = (POS_COOKIE) pAd->OS_Cookie;
+
+
+ /* Note 03312008: we can not return here before
+ RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word);
+ RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word);
+ Or kernel will panic after ifconfig ra0 down sometimes */
+
+
+ //
+ // Inital the Interrupt source.
+ //
+ IntSource.word = 0x00000000L;
+// McuIntSource.word = 0x00000000L;
+
+ //
+ // Get the interrupt sources & saved to local variable
+ //
+ //RTMP_IO_READ32(pAd, where, &McuIntSource.word);
+ //RTMP_IO_WRITE32(pAd, , McuIntSource.word);
+
+ //
+ // Flag fOP_STATUS_DOZE On, means ASIC put to sleep, elase means ASICK WakeUp
+ // And at the same time, clock maybe turned off that say there is no DMA service.
+ // when ASIC get to sleep.
+ // To prevent system hang on power saving.
+ // We need to check it before handle the INT_SOURCE_CSR, ASIC must be wake up.
+ //
+ // RT2661 => when ASIC is sleeping, MAC register cannot be read and written.
+ // RT2860 => when ASIC is sleeping, MAC register can be read and written.
+
+ {
+ RTMP_IO_READ32(pAd, INT_SOURCE_CSR, &IntSource.word);
+ RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, IntSource.word); // write 1 to clear
+ }
+
+ // Do nothing if Reset in progress
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ return IRQ_HANDLED;
+#else
+ return;
+#endif
+ }
+
+ //
+ // Handle interrupt, walk through all bits
+ // Should start from highest priority interrupt
+ // The priority can be adjust by altering processing if statement
+ //
+
+ pAd->bPCIclkOff = FALSE;
+
+ // If required spinlock, each interrupt service routine has to acquire
+ // and release itself.
+ //
+
+ // Do nothing if NIC doesn't exist
+ if (IntSource.word == 0xffffffff)
+ {
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ return IRQ_HANDLED;
+#else
+ return;
+#endif
+ }
+
+ if (IntSource.word & TxCoherent)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, (">>>TxCoherent<<<\n"));
+ RTMPHandleRxCoherentInterrupt(pAd);
+ }
+
+ if (IntSource.word & RxCoherent)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, (">>>RxCoherent<<<\n"));
+ RTMPHandleRxCoherentInterrupt(pAd);
+ }
+
+ if (IntSource.word & FifoStaFullInt)
+ {
+#if 1
+ if ((pAd->int_disable_mask & FifoStaFullInt) == 0)
+ {
+ /* mask FifoStaFullInt */
+ rt2860_int_disable(pAd, FifoStaFullInt);
+ tasklet_hi_schedule(&pObj->fifo_statistic_full_task);
+ }
+ pAd->int_pending |= FifoStaFullInt;
+#else
+ NICUpdateFifoStaCounters(pAd);
+#endif
+ }
+
+ if (IntSource.word & INT_MGMT_DLY)
+ {
+ if ((pAd->int_disable_mask & INT_MGMT_DLY) ==0 )
+ {
+ rt2860_int_disable(pAd, INT_MGMT_DLY);
+ tasklet_hi_schedule(&pObj->mgmt_dma_done_task);
+ }
+ pAd->int_pending |= INT_MGMT_DLY ;
+ }
+
+ if (IntSource.word & INT_RX)
+ {
+ if ((pAd->int_disable_mask & INT_RX) == 0)
+ {
+ /* mask RxINT */
+ rt2860_int_disable(pAd, INT_RX);
+ tasklet_hi_schedule(&pObj->rx_done_task);
+ }
+ pAd->int_pending |= INT_RX;
+ }
+
+ if (IntSource.word & INT_HCCA_DLY)
+ {
+
+ if ((pAd->int_disable_mask & INT_HCCA_DLY) == 0)
+ {
+ /* mask TxDataInt */
+ rt2860_int_disable(pAd, INT_HCCA_DLY);
+ tasklet_hi_schedule(&pObj->hcca_dma_done_task);
+ }
+ pAd->int_pending |= INT_HCCA_DLY;
+ }
+
+ if (IntSource.word & INT_AC3_DLY)
+ {
+
+ if ((pAd->int_disable_mask & INT_AC3_DLY) == 0)
+ {
+ /* mask TxDataInt */
+ rt2860_int_disable(pAd, INT_AC3_DLY);
+ tasklet_hi_schedule(&pObj->ac3_dma_done_task);
+ }
+ pAd->int_pending |= INT_AC3_DLY;
+ }
+
+ if (IntSource.word & INT_AC2_DLY)
+ {
+
+ if ((pAd->int_disable_mask & INT_AC2_DLY) == 0)
+ {
+ /* mask TxDataInt */
+ rt2860_int_disable(pAd, INT_AC2_DLY);
+ tasklet_hi_schedule(&pObj->ac2_dma_done_task);
+ }
+ pAd->int_pending |= INT_AC2_DLY;
+ }
+
+ if (IntSource.word & INT_AC1_DLY)
+ {
+
+ pAd->int_pending |= INT_AC1_DLY;
+
+ if ((pAd->int_disable_mask & INT_AC1_DLY) == 0)
+ {
+ /* mask TxDataInt */
+ rt2860_int_disable(pAd, INT_AC1_DLY);
+ tasklet_hi_schedule(&pObj->ac1_dma_done_task);
+ }
+
+ }
+
+ if (IntSource.word & INT_AC0_DLY)
+ {
+ pAd->int_pending |= INT_AC0_DLY;
+
+ if ((pAd->int_disable_mask & INT_AC0_DLY) == 0)
+ {
+ /* mask TxDataInt */
+ rt2860_int_disable(pAd, INT_AC0_DLY);
+ tasklet_hi_schedule(&pObj->ac0_dma_done_task);
+ }
+
+ }
+
+ if (IntSource.word & PreTBTTInt)
+ {
+ RTMPHandlePreTBTTInterrupt(pAd);
+ }
+
+ if (IntSource.word & TBTTInt)
+ {
+ RTMPHandleTBTTInterrupt(pAd);
+ }
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (IntSource.word & AutoWakeupInt)
+ RTMPHandleTwakeupInterrupt(pAd);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ return IRQ_HANDLED;
+#endif
+
+}
+
+/*
+========================================================================
+Routine Description:
+ Check the chipset vendor/product ID.
+
+Arguments:
+ _dev_p Point to the PCI or USB device
+
+Return Value:
+ TRUE Check ok
+ FALSE Check fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RT28XXChipsetCheck(
+ IN void *_dev_p)
+{
+ /* always TRUE */
+ return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Init net device structure.
+
+Arguments:
+ _dev_p Point to the PCI or USB device
+ *net_dev Point to the net device
+ *pAd the raxx interface data pointer
+
+Return Value:
+ TRUE Init ok
+ FALSE Init fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RT28XXNetDevInit(
+ IN void *_dev_p,
+ IN struct net_device *net_dev,
+ IN RTMP_ADAPTER *pAd)
+{
+ struct pci_dev *pci_dev = (struct pci_dev *)_dev_p;
+ const CHAR *print_name;
+ ULONG csr_addr;
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ print_name = pci_dev ? pci_name(pci_dev) : "rt2860";
+#else
+ print_name = pci_dev ? pci_dev->slot_name : "rt2860";
+#endif // LINUX_VERSION_CODE //
+
+ net_dev->base_addr = 0;
+ net_dev->irq = 0;
+
+ if (pci_request_regions(pci_dev, print_name))
+ goto err_out_free_netdev;
+
+ // interrupt IRQ number
+ net_dev->irq = pci_dev->irq;
+
+ // map physical address to virtual address for accessing register
+ csr_addr = (unsigned long) ioremap(pci_resource_start(pci_dev, 0),
+ pci_resource_len(pci_dev, 0));
+
+ if (!csr_addr)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("ioremap failed for device %s, region 0x%lX @ 0x%lX\n",
+ print_name, (ULONG)pci_resource_len(pci_dev, 0),
+ (ULONG)pci_resource_start(pci_dev, 0)));
+ goto err_out_free_res;
+ }
+
+ // Save CSR virtual address and irq to device structure
+ net_dev->base_addr = csr_addr;
+ pAd->CSRBaseAddress = (PUCHAR)net_dev->base_addr;
+
+ // Set DMA master
+ pci_set_master(pci_dev);
+
+ net_dev->priv_flags = INT_MAIN;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: at 0x%lx, VA 0x%lx, IRQ %d. \n",
+ net_dev->name, (ULONG)pci_resource_start(pci_dev, 0),
+ (ULONG)csr_addr, pci_dev->irq));
+ return TRUE;
+
+
+ /* --------------------------- ERROR HANDLE --------------------------- */
+err_out_free_res:
+ pci_release_regions(pci_dev);
+err_out_free_netdev:
+ /* free netdev in caller, not here */
+ return FALSE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Init net device structure.
+
+Arguments:
+ _dev_p Point to the PCI or USB device
+ *pAd the raxx interface data pointer
+
+Return Value:
+ TRUE Config ok
+ FALSE Config fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RT28XXProbePostConfig(
+ IN void *_dev_p,
+ IN RTMP_ADAPTER *pAd,
+ IN INT32 argc)
+{
+ /* no use */
+ return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Disable DMA.
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RT28XXDMADisable(
+ IN RTMP_ADAPTER *pAd)
+{
+ WPDMA_GLO_CFG_STRUC GloCfg;
+
+
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+ GloCfg.word &= 0xff0;
+ GloCfg.field.EnTXWriteBackDDONE =1;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Enable DMA.
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RT28XXDMAEnable(
+ IN RTMP_ADAPTER *pAd)
+{
+ WPDMA_GLO_CFG_STRUC GloCfg;
+ int i = 0;
+
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x4);
+ do
+ {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+ if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
+ break;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy\n"));
+ RTMPusecDelay(1000);
+ i++;
+ }while ( i <200);
+
+ RTMPusecDelay(50);
+
+ GloCfg.field.EnTXWriteBackDDONE = 1;
+ GloCfg.field.WPDMABurstSIZE = 2;
+ GloCfg.field.EnableRxDMA = 1;
+ GloCfg.field.EnableTxDMA = 1;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== WRITE DMA offset 0x208 = 0x%x\n", GloCfg.word));
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+
+}
+
+/*
+========================================================================
+Routine Description:
+ Write Beacon buffer to Asic.
+
+Arguments:
+ *pAd the raxx interface data pointer
+
+Return Value:
+ None
+
+Note:
+========================================================================
+*/
+VOID RT28xx_UpdateBeaconToAsic(
+ IN RTMP_ADAPTER *pAd,
+ IN INT apidx,
+ IN ULONG FrameLen,
+ IN ULONG UpdatePos)
+{
+ ULONG CapInfoPos = 0;
+ UCHAR *ptr, *ptr_update, *ptr_capinfo;
+ UINT i;
+ BOOLEAN bBcnReq = FALSE;
+ UCHAR bcn_idx = 0;
+
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s() : No valid Interface be found.\n", __func__));
+ return;
+ }
+
+ if (bBcnReq == FALSE)
+ {
+ /* when the ra interface is down, do not send its beacon frame */
+ /* clear all zero */
+ for(i=0; i<TXWI_SIZE; i+=4)
+ RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, 0x00);
+ }
+ else
+ {
+ ptr = (PUCHAR)&pAd->BeaconTxWI;
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange(ptr, TYPE_TXWI);
+#endif
+ for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
+ {
+ UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
+ RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[bcn_idx] + i, longptr);
+ ptr += 4;
+ }
+
+ // Update CapabilityInfo in Beacon
+ for (i = CapInfoPos; i < (CapInfoPos+2); i++)
+ {
+ RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_capinfo);
+ ptr_capinfo ++;
+ }
+
+ if (FrameLen > UpdatePos)
+ {
+ for (i= UpdatePos; i< (FrameLen); i++)
+ {
+ RTMP_IO_WRITE8(pAd, pAd->BeaconOffset[bcn_idx] + TXWI_SIZE + i, *ptr_update);
+ ptr_update ++;
+ }
+ }
+
+ }
+
+}
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPInitPCIeLinkCtrlValue(
+ IN PRTMP_ADAPTER pAd)
+{
+}
+
+VOID RTMPFindHostPCIDev(
+ IN PRTMP_ADAPTER pAd)
+{
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+ Level = RESTORE_HALT : Restore PCI host and Ralink PCIe Link Control field to its default value.
+ Level = Other Value : Restore from dot11 power save or radio off status. And force PCI host Link Control fields to 0x1
+
+ ========================================================================
+*/
+VOID RTMPPCIeLinkCtrlValueRestore(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Level)
+{
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+ Max : limit Host PCI and Ralink PCIe device's LINK CONTROL field's value.
+ Because now frequently set our device to mode 1 or mode 3 will cause problem.
+
+ ========================================================================
+*/
+VOID RTMPPCIeLinkCtrlSetting(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Max)
+{
+}
+#endif // CONFIG_STA_SUPPORT //
+
+VOID rt2860_stop(struct net_device *net_dev)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)NULL;
+ if (net_dev == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
+ }
+ else
+ pAd = net_dev->ml_priv;
+
+ if (pAd != NULL)
+ {
+ // stop interface
+ netif_carrier_off(net_dev);
+ netif_stop_queue(net_dev);
+
+ // mark device as removed from system and therefore no longer available
+ netif_device_detach(net_dev);
+
+ // mark halt flag
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+ // take down the device
+ rt28xx_close((PNET_DEV)net_dev);
+ RT_MOD_DEC_USE_COUNT();
+ }
+ return;
+}
+
+/*
+ * invaild or writeback cache
+ * and convert virtual address to physical address
+ */
+dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction)
+{
+ PRTMP_ADAPTER pAd;
+ POS_COOKIE pObj;
+
+ /*
+ ------ Porting Information ------
+ > For Tx Alloc:
+ mgmt packets => sd_idx = 0
+ SwIdx: pAd->MgmtRing.TxCpuIdx
+ pTxD : pAd->MgmtRing.Cell[SwIdx].AllocVa;
+
+ data packets => sd_idx = 1
+ TxIdx : pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx
+ QueIdx: pTxBlk->QueIdx
+ pTxD : pAd->TxRing[pTxBlk->QueIdx].Cell[TxIdx].AllocVa;
+
+ > For Rx Alloc:
+ sd_idx = -1
+ */
+
+ pAd = (PRTMP_ADAPTER)handle;
+ pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ if (sd_idx == 1)
+ {
+ PTX_BLK pTxBlk;
+ pTxBlk = (PTX_BLK)ptr;
+ return pci_map_single(pObj->pci_dev, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, direction);
+ }
+ else
+ {
+ return pci_map_single(pObj->pci_dev, ptr, size, direction);
+ }
+
+}
+
+void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction)
+{
+ PRTMP_ADAPTER pAd;
+ POS_COOKIE pObj;
+
+ pAd=(PRTMP_ADAPTER)handle;
+ pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ pci_unmap_single(pObj->pci_dev, dma_addr, size, direction);
+
+}
+
diff --git a/drivers/staging/rt2860/Kconfig b/drivers/staging/rt2860/Kconfig
new file mode 100644
index 000000000000..7f44e5e72463
--- /dev/null
+++ b/drivers/staging/rt2860/Kconfig
@@ -0,0 +1,5 @@
+config RT2860
+ tristate "Ralink 2860 wireless support"
+ depends on PCI && X86 && WLAN_80211
+ ---help---
+ This is an experimental driver for the Ralink 2860 wireless chip.
diff --git a/drivers/staging/rt2860/Makefile b/drivers/staging/rt2860/Makefile
new file mode 100644
index 000000000000..6162212b588c
--- /dev/null
+++ b/drivers/staging/rt2860/Makefile
@@ -0,0 +1,43 @@
+obj-$(CONFIG_RT2860) += rt2860sta.o
+
+# TODO: all of these should be removed
+EXTRA_CFLAGS += -DLINUX -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT
+EXTRA_CFLAGS += -DRT2860
+EXTRA_CFLAGS += -DCONFIG_STA_SUPPORT
+EXTRA_CFLAGS += -DDBG
+EXTRA_CFLAGS += -DDOT11_N_SUPPORT
+EXTRA_CFLAGS += -DWPA_SUPPLICANT_SUPPORT
+EXTRA_CFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT
+
+rt2860sta-objs := \
+ common/md5.o \
+ common/mlme.o \
+ common/rtmp_wep.o \
+ common/action.o \
+ common/cmm_data.o \
+ common/rtmp_init.o \
+ common/rtmp_tkip.o \
+ common/cmm_sync.o \
+ common/eeprom.o \
+ common/cmm_sanity.o \
+ common/cmm_info.o \
+ common/cmm_wpa.o \
+ common/dfs.o \
+ common/spectrum.o \
+ sta/assoc.o \
+ sta/aironet.o \
+ sta/auth.o \
+ sta/auth_rsp.o \
+ sta/sync.o \
+ sta/sanity.o \
+ sta/rtmp_data.o \
+ sta/connect.o \
+ sta/wpa.o \
+ rt_linux.o \
+ rt_profile.o \
+ rt_main_dev.o \
+ sta_ioctl.o \
+ common/ba_action.o \
+ common/2860_rtmp_init.o \
+ 2860_main_dev.o \
+ common/cmm_data_2860.o
diff --git a/drivers/staging/rt2860/TODO b/drivers/staging/rt2860/TODO
new file mode 100644
index 000000000000..2f70b0faca3d
--- /dev/null
+++ b/drivers/staging/rt2860/TODO
@@ -0,0 +1,17 @@
+I'm hesitant to add a TODO file here, as the wireless developers would
+really have people help them out on the "clean" rt2860 driver that can
+be found at the rt2860.sf.net site.
+
+But, if you wish to clean up this driver instead, here's a short list of
+things that need to be done to get it into a more mergable shape:
+
+TODO:
+ - checkpatch.pl clean
+ - sparse clean
+ - port to in-kernel 80211 stack
+ - remove reading from /etc/ config files
+ - review by the wireless developer community
+
+Please send any patches or complaints about this driver to Greg
+Kroah-Hartman <greg@kroah.com> and don't bother the upstream wireless
+kernel developers about it, they want nothing to do with it.
diff --git a/drivers/staging/rt2860/aironet.h b/drivers/staging/rt2860/aironet.h
new file mode 100644
index 000000000000..1e07b19b8cdc
--- /dev/null
+++ b/drivers/staging/rt2860/aironet.h
@@ -0,0 +1,210 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ aironet.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Paul Lin 04-06-15 Initial
+*/
+
+#ifndef __AIRONET_H__
+#define __AIRONET_H__
+
+// Measurement Type definition
+#define MSRN_TYPE_UNUSED 0
+#define MSRN_TYPE_CHANNEL_LOAD_REQ 1
+#define MSRN_TYPE_NOISE_HIST_REQ 2
+#define MSRN_TYPE_BEACON_REQ 3
+#define MSRN_TYPE_FRAME_REQ 4
+
+// Scan Mode in Beacon Request
+#define MSRN_SCAN_MODE_PASSIVE 0
+#define MSRN_SCAN_MODE_ACTIVE 1
+#define MSRN_SCAN_MODE_BEACON_TABLE 2
+
+// PHY type definition for Aironet beacon report, CCX 2 table 36-9
+#define PHY_FH 1
+#define PHY_DSS 2
+#define PHY_UNUSED 3
+#define PHY_OFDM 4
+#define PHY_HR_DSS 5
+#define PHY_ERP 6
+
+// RPI table in dBm
+#define RPI_0 0 // Power <= -87
+#define RPI_1 1 // -87 < Power <= -82
+#define RPI_2 2 // -82 < Power <= -77
+#define RPI_3 3 // -77 < Power <= -72
+#define RPI_4 4 // -72 < Power <= -67
+#define RPI_5 5 // -67 < Power <= -62
+#define RPI_6 6 // -62 < Power <= -57
+#define RPI_7 7 // -57 < Power
+
+// Cisco Aironet IAPP definetions
+#define AIRONET_IAPP_TYPE 0x32
+#define AIRONET_IAPP_SUBTYPE_REQUEST 0x01
+#define AIRONET_IAPP_SUBTYPE_REPORT 0x81
+
+// Measurement Request detail format
+typedef struct _MEASUREMENT_REQUEST {
+ UCHAR Channel;
+ UCHAR ScanMode; // Use only in beacon request, other requests did not use this field
+ USHORT Duration;
+} MEASUREMENT_REQUEST, *PMEASUREMENT_REQUEST;
+
+// Beacon Measurement Report
+// All these field might change to UCHAR, because we didn't do anything to these report.
+// We copy all these beacons and report to CCX 2 AP.
+typedef struct _BEACON_REPORT {
+ UCHAR Channel;
+ UCHAR Spare;
+ USHORT Duration;
+ UCHAR PhyType; // Definiation is listed above table 36-9
+ UCHAR RxPower;
+ UCHAR BSSID[6];
+ UCHAR ParentTSF[4];
+ UCHAR TargetTSF[8];
+ USHORT BeaconInterval;
+ USHORT CapabilityInfo;
+} BEACON_REPORT, *PBEACON_REPORT;
+
+// Frame Measurement Report (Optional)
+typedef struct _FRAME_REPORT {
+ UCHAR Channel;
+ UCHAR Spare;
+ USHORT Duration;
+ UCHAR TA;
+ UCHAR BSSID[6];
+ UCHAR RSSI;
+ UCHAR Count;
+} FRAME_REPORT, *PFRAME_REPORT;
+
+#pragma pack(1)
+// Channel Load Report
+typedef struct _CHANNEL_LOAD_REPORT {
+ UCHAR Channel;
+ UCHAR Spare;
+ USHORT Duration;
+ UCHAR CCABusy;
+} CHANNEL_LOAD_REPORT, *PCHANNEL_LOAD_REPORT;
+#pragma pack()
+
+// Nosie Histogram Report
+typedef struct _NOISE_HIST_REPORT {
+ UCHAR Channel;
+ UCHAR Spare;
+ USHORT Duration;
+ UCHAR Density[8];
+} NOISE_HIST_REPORT, *PNOISE_HIST_REPORT;
+
+// Radio Management Capability element
+typedef struct _RADIO_MANAGEMENT_CAPABILITY {
+ UCHAR Eid; // TODO: Why the Eid is 1 byte, not normal 2 bytes???
+ UCHAR Length;
+ UCHAR AironetOui[3]; // AIronet OUI (00 40 96)
+ UCHAR Type; // Type / Version
+ USHORT Status; // swap16 required
+} RADIO_MANAGEMENT_CAPABILITY, *PRADIO_MANAGEMENT_CAPABILITY;
+
+// Measurement Mode Bit definition
+typedef struct _MEASUREMENT_MODE {
+ UCHAR Rsvd:4;
+ UCHAR Report:1;
+ UCHAR NotUsed:1;
+ UCHAR Enable:1;
+ UCHAR Parallel:1;
+} MEASUREMENT_MODE, *PMEASUREMENT_MODE;
+
+// Measurement Request element, This is little endian mode
+typedef struct _MEASUREMENT_REQUEST_ELEMENT {
+ USHORT Eid;
+ USHORT Length; // swap16 required
+ USHORT Token; // non-zero unique token
+ UCHAR Mode; // Measurement Mode
+ UCHAR Type; // Measurement type
+} MEASUREMENT_REQUEST_ELEMENT, *PMEASUREMENT_REQUEST_ELEMENT;
+
+// Measurement Report element, This is little endian mode
+typedef struct _MEASUREMENT_REPORT_ELEMENT {
+ USHORT Eid;
+ USHORT Length; // swap16 required
+ USHORT Token; // non-zero unique token
+ UCHAR Mode; // Measurement Mode
+ UCHAR Type; // Measurement type
+} MEASUREMENT_REPORT_ELEMENT, *PMEASUREMENT_REPORT_ELEMENT;
+
+// Cisco Aironet IAPP Frame Header, Network byte order used
+typedef struct _AIRONET_IAPP_HEADER {
+ UCHAR CiscoSnapHeader[8]; // 8 bytes Cisco snap header
+ USHORT Length; // IAPP ID & length, remember to swap16 in LE system
+ UCHAR Type; // IAPP type
+ UCHAR SubType; // IAPP subtype
+ UCHAR DA[6]; // Destination MAC address
+ UCHAR SA[6]; // Source MAC address
+ USHORT Token; // Dialog token, no need to swap16 since it is for yoken usage only
+} AIRONET_IAPP_HEADER, *PAIRONET_IAPP_HEADER;
+
+// Radio Measurement Request frame
+typedef struct _AIRONET_RM_REQUEST_FRAME {
+ AIRONET_IAPP_HEADER IAPP; // Common header
+ UCHAR Delay; // Activation Delay
+ UCHAR Offset; // Measurement offset
+} AIRONET_RM_REQUEST_FRAME, *PAIRONET_RM_REQUEST_FRAME;
+
+// Radio Measurement Report frame
+typedef struct _AIRONET_RM_REPORT_FRAME {
+ AIRONET_IAPP_HEADER IAPP; // Common header
+} AIRONET_RM_REPORT_FRAME, *PAIRONET_RM_REPORT_FRAME;
+
+// Saved element request actions which will saved in StaCfg.
+typedef struct _RM_REQUEST_ACTION {
+ MEASUREMENT_REQUEST_ELEMENT ReqElem; // Saved request element
+ MEASUREMENT_REQUEST Measurement; // Saved measurement within the request element
+} RM_REQUEST_ACTION, *PRM_REQUEST_ACTION;
+
+// CCX administration control
+typedef union _CCX_CONTROL {
+ struct {
+ UINT32 Enable:1; // Enable CCX2
+ UINT32 LeapEnable:1; // Enable LEAP at CCX2
+ UINT32 RMEnable:1; // Radio Measurement Enable
+ UINT32 DCRMEnable:1; // Non serving channel Radio Measurement enable
+ UINT32 QOSEnable:1; // Enable QOS for CCX 2.0 support
+ UINT32 FastRoamEnable:1; // Enable fast roaming
+ UINT32 Rsvd:2; // Not used
+ UINT32 dBmToRoam:8; // the condition to roam when receiving Rssi less than this value. It's negative value.
+ UINT32 TuLimit:16; // Limit for different channel scan
+ } field;
+ UINT32 word;
+} CCX_CONTROL, *PCCX_CONTROL;
+
+#endif // __AIRONET_H__
diff --git a/drivers/staging/rt2860/ap.h b/drivers/staging/rt2860/ap.h
new file mode 100644
index 000000000000..df6db2813121
--- /dev/null
+++ b/drivers/staging/rt2860/ap.h
@@ -0,0 +1,557 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ ap.h
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 08-01-2002 created
+ James Tan 09-06-2002 modified (Revise NTCRegTable)
+ John Chang 12-22-2004 modified for RT2561/2661. merge with STA driver
+*/
+#ifndef __AP_H__
+#define __AP_H__
+
+
+
+// ========================= AP RTMP.h ================================
+
+
+
+// =============================================================
+// Function Prototypes
+// =============================================================
+
+// ap_data.c
+
+BOOLEAN APBridgeToWirelessSta(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHeader,
+ IN UINT HdrLen,
+ IN PUCHAR pData,
+ IN UINT DataLen,
+ IN ULONG fromwdsidx);
+
+BOOLEAN APHandleRxDoneInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APSendPackets(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PPNDIS_PACKET ppPacketArray,
+ IN UINT NumberOfPackets);
+
+NDIS_STATUS APSendPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+
+NDIS_STATUS APHardTransmit(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR QueIdx);
+
+VOID APRxEAPOLFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+NDIS_STATUS APCheckRxError(
+ IN PRTMP_ADAPTER pAd,
+ IN PRT28XX_RXD_STRUC pRxD,
+ IN UCHAR Wcid);
+
+BOOLEAN APCheckClass2Class3Error(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN PHEADER_802_11 pHeader);
+
+VOID APHandleRxPsPoll(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN USHORT Aid,
+ IN BOOLEAN isActive);
+
+VOID RTMPDescriptorEndianChange(
+ IN PUCHAR pData,
+ IN ULONG DescriptorType);
+
+VOID RTMPFrameEndianChange(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG Dir,
+ IN BOOLEAN FromRxDoneInt);
+
+// ap_assoc.c
+
+VOID APAssocStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID APPeerAssocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerReassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerDisassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MbssKickOutStas(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx,
+ IN USHORT Reason);
+
+VOID APMlmeKickOutSta(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pStaAddr,
+ IN UCHAR Wcid,
+ IN USHORT Reason);
+
+VOID APMlmeDisassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APCls3errAction(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN PHEADER_802_11 pHeader);
+
+
+USHORT APBuildAssociation(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN USHORT CapabilityInfo,
+ IN UCHAR MaxSupportedRateIn500Kbps,
+ IN UCHAR *RSN,
+ IN UCHAR *pRSNLen,
+ IN BOOLEAN bWmmCapable,
+ IN ULONG RalinkIe,
+#ifdef DOT11N_DRAFT3
+ IN EXT_CAP_INFO_ELEMENT ExtCapInfo,
+#endif // DOT11N_DRAFT3 //
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN UCHAR HtCapabilityLen,
+ OUT USHORT *pAid);
+
+// ap_auth.c
+
+void APAuthStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID APMlmeDeauthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APCls2errAction(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN PHEADER_802_11 pHeader);
+
+// ap_authrsp.c
+
+VOID APAuthRspStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTATE_MACHINE Sm,
+ IN STATE_MACHINE_FUNC Trans[]);
+
+VOID APPeerAuthAtAuthRspIdleAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerDeauthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerAuthSimpleRspGenAndSend(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHdr80211,
+ IN USHORT Alg,
+ IN USHORT Seq,
+ IN USHORT StatusCode);
+
+// ap_connect.c
+
+BOOLEAN BeaconTransmitRequired(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx);
+
+VOID APMakeBssBeacon(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx);
+
+VOID APUpdateBeaconFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx);
+
+VOID APMakeAllBssBeacon(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APUpdateAllBeaconFrame(
+ IN PRTMP_ADAPTER pAd);
+
+
+// ap_sync.c
+
+VOID APSyncStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID APScanTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID APInvalidStateWhenScan(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APScanTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerProbeReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerBeaconAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APMlmeScanReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APPeerBeaconAtScanAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APScanCnclAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID ApSiteSurvey(
+ IN PRTMP_ADAPTER pAd);
+
+VOID SupportRate(
+ IN PUCHAR SupRate,
+ IN UCHAR SupRateLen,
+ IN PUCHAR ExtRate,
+ IN UCHAR ExtRateLen,
+ OUT PUCHAR *Rates,
+ OUT PUCHAR RatesLen,
+ OUT PUCHAR pMaxSupportRate);
+
+
+BOOLEAN ApScanRunning(
+ IN PRTMP_ADAPTER pAd);
+
+#ifdef DOT11N_DRAFT3
+VOID APOverlappingBSSScan(
+ IN RTMP_ADAPTER *pAd);
+#endif // DOT11N_DRAFT3 //
+
+// ap_wpa.c
+
+VOID APWpaStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+// ap_mlme.c
+
+VOID APMlmePeriodicExec(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APMlmeSelectTxRateTable(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR *ppTable,
+ IN PUCHAR pTableSize,
+ IN PUCHAR pInitTxRateIdx);
+
+VOID APMlmeSetTxRate(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PRTMP_TX_RATE_SWITCH pTxRate);
+
+VOID APMlmeDynamicTxRateSwitching(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APQuickResponeForRateUpExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+BOOLEAN APMsgTypeSubst(
+ IN PRTMP_ADAPTER pAd,
+ IN PFRAME_802_11 pFrame,
+ OUT INT *Machine,
+ OUT INT *MsgType);
+
+VOID APQuickResponeForRateUpExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+
+VOID RTMPSetPiggyBack(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bPiggyBack);
+
+VOID APAsicEvaluateRxAnt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APAsicRxAntEvalTimeout(
+ IN PRTMP_ADAPTER pAd);
+
+// ap.c
+
+VOID APSwitchChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN INT Channel);
+
+NDIS_STATUS APInitialize(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APShutdown(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APStartUp(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APStop(
+ IN PRTMP_ADAPTER pAd);
+
+VOID APCleanupPsQueue(
+ IN PRTMP_ADAPTER pAd,
+ IN PQUEUE_HEADER pQueue);
+
+VOID MacTableReset(
+ IN PRTMP_ADAPTER pAd);
+
+MAC_TABLE_ENTRY *MacTableInsertEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR apidx,
+ IN BOOLEAN CleanAll);
+
+BOOLEAN MacTableDeleteEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT wcid,
+ IN PUCHAR pAddr);
+
+MAC_TABLE_ENTRY *MacTableLookup(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr);
+
+VOID MacTableMaintenance(
+ IN PRTMP_ADAPTER pAd);
+
+UINT32 MacTableAssocStaNumGet(
+ IN PRTMP_ADAPTER pAd);
+
+MAC_TABLE_ENTRY *APSsPsInquiry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ OUT SST *Sst,
+ OUT USHORT *Aid,
+ OUT UCHAR *PsMode,
+ OUT UCHAR *Rate);
+
+BOOLEAN APPsIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN ULONG Wcid,
+ IN UCHAR Psm);
+
+VOID ApLogEvent(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN USHORT Event);
+
+#ifdef DOT11_N_SUPPORT
+VOID APUpdateOperationMode(
+ IN PRTMP_ADAPTER pAd);
+#endif // DOT11_N_SUPPORT //
+
+VOID APUpdateCapabilityAndErpIe(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN ApCheckAccessControlList(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR Apidx);
+
+VOID ApUpdateAccessControlList(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Apidx);
+
+VOID ApEnqueueNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR TxRate,
+ IN UCHAR PID,
+ IN UCHAR apidx,
+ IN BOOLEAN bQosNull,
+ IN BOOLEAN bEOSP,
+ IN UCHAR OldUP);
+
+VOID ApSendFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PVOID pBuffer,
+ IN ULONG Length,
+ IN UCHAR TxRate,
+ IN UCHAR PID);
+
+VOID ApEnqueueAckFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR TxRate,
+ IN UCHAR apidx);
+
+UCHAR APAutoSelectChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN Optimal);
+
+// ap_sanity.c
+
+
+BOOLEAN PeerAssocReqCmmSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN isRessoc,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pListenInterval,
+ OUT PUCHAR pApAddr,
+ OUT UCHAR *pSsidLen,
+ OUT char *Ssid,
+ OUT UCHAR *pRatesLen,
+ OUT UCHAR Rates[],
+ OUT UCHAR *RSN,
+ OUT UCHAR *pRSNLen,
+ OUT BOOLEAN *pbWmmCapable,
+ OUT ULONG *pRalinkIe,
+#ifdef DOT11N_DRAFT3
+ OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo,
+#endif // DOT11N_DRAFT3 //
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability);
+
+BOOLEAN PeerDisassocReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *Reason);
+
+BOOLEAN PeerDeauthReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *Reason);
+
+BOOLEAN APPeerAuthSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr1,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *Alg,
+ OUT USHORT *Seq,
+ OUT USHORT *Status,
+ CHAR *ChlgText);
+
+BOOLEAN APPeerProbeReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT CHAR Ssid[],
+ OUT UCHAR *SsidLen);
+
+BOOLEAN APPeerBeaconAndProbeRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT PUCHAR pBssid,
+ OUT CHAR Ssid[],
+ OUT UCHAR *SsidLen,
+ OUT UCHAR *BssType,
+ OUT USHORT *BeaconPeriod,
+ OUT UCHAR *Channel,
+ OUT LARGE_INTEGER *Timestamp,
+ OUT USHORT *CapabilityInfo,
+ OUT UCHAR Rate[],
+ OUT UCHAR *RateLen,
+ OUT BOOLEAN *ExtendedRateIeExist,
+ OUT UCHAR *Erp);
+
+// ap_info.c
+
+#ifdef WIN_NDIS
+NDIS_STATUS APQueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID pInformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG pBytesWritten,
+ OUT PULONG pBytesNeeded);
+
+NDIS_STATUS APSetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID pInformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG pBytesRead,
+ OUT PULONG pBytesNeeded);
+#endif
+
+
+// ================== end of AP RTMP.h ========================
+
+
+#endif // __AP_H__
+
diff --git a/drivers/staging/rt2860/chlist.h b/drivers/staging/rt2860/chlist.h
new file mode 100644
index 000000000000..9e15b9daeb80
--- /dev/null
+++ b/drivers/staging/rt2860/chlist.h
@@ -0,0 +1,1296 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ chlist.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Fonchi Wu 2007-12-19 created
+*/
+
+#ifndef __CHLIST_H__
+#define __CHLIST_H__
+
+#include "rtmp_type.h"
+#include "rtmp_def.h"
+
+
+#define ODOR 0
+#define IDOR 1
+#define BOTH 2
+
+#define BAND_5G 0
+#define BAND_24G 1
+#define BAND_BOTH 2
+
+typedef struct _CH_DESP {
+ UCHAR FirstChannel;
+ UCHAR NumOfCh;
+ CHAR MaxTxPwr; // dBm
+ UCHAR Geography; // 0:out door, 1:in door, 2:both
+ BOOLEAN DfsReq; // Dfs require, 0: No, 1: yes.
+} CH_DESP, *PCH_DESP;
+
+typedef struct _CH_REGION {
+ UCHAR CountReg[3];
+ UCHAR DfsType; // 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56
+ CH_DESP ChDesp[10];
+} CH_REGION, *PCH_REGION;
+
+static CH_REGION ChRegion[] =
+{
+ { // Antigua and Berbuda
+ "AG",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Argentina
+ "AR",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Aruba
+ "AW",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Australia
+ "AU",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Austria
+ "AT",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Bahamas
+ "BS",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Barbados
+ "BB",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Bermuda
+ "BM",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Brazil
+ "BR",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 24, BOTH, FALSE}, // 5G, ch 100~140
+ { 149, 5, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Belgium
+ "BE",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 18, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 18, IDOR, FALSE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // Bulgaria
+ "BG",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Canada
+ "CA",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Cayman IsLands
+ "KY",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Chile
+ "CL",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // China
+ "CN",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Colombia
+ "CO",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Costa Rica
+ "CR",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Cyprus
+ "CY",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Czech_Republic
+ "CZ",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // Denmark
+ "DK",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Dominican Republic
+ "DO",
+ CE,
+ {
+ { 1, 0, 20, BOTH, FALSE}, // 2.4 G, ch 0
+ { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Equador
+ "EC",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 100, 11, 27, BOTH, FALSE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // El Salvador
+ "SV",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 30, BOTH, TRUE}, // 5G, ch 52~64
+ { 149, 4, 36, BOTH, TRUE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Finland
+ "FI",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // France
+ "FR",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // Germany
+ "DE",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Greece
+ "GR",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Guam
+ "GU",
+ CE,
+ {
+ { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, FALSE}, // 5G, ch 100~140
+ { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Guatemala
+ "GT",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Haiti
+ "HT",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 17, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Honduras
+ "HN",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Hong Kong
+ "HK",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64
+ { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Hungary
+ "HU",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // Iceland
+ "IS",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // India
+ "IN",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 149, 4, 24, IDOR, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Indonesia
+ "ID",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Ireland
+ "IE",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Israel
+ "IL",
+ CE,
+ {
+ { 1, 3, 20, IDOR, FALSE}, // 2.4 G, ch 1~3
+ { 4, 6, 20, BOTH, FALSE}, // 2.4 G, ch 4~9
+ { 10, 4, 20, IDOR, FALSE}, // 2.4 G, ch 10~13
+ { 0}, // end
+ }
+ },
+
+ { // Italy
+ "IT",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, ODOR, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Japan
+ "JP",
+ JAP,
+ {
+ { 1, 14, 20, BOTH, FALSE}, // 2.4 G, ch 1~14
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 0}, // end
+ }
+ },
+
+ { // Jordan
+ "JO",
+ CE,
+ {
+ { 1, 13, 20, IDOR, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 149, 4, 23, IDOR, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Latvia
+ "LV",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Liechtenstein
+ "LI",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Lithuania
+ "LT",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Luxemburg
+ "LU",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Malaysia
+ "MY",
+ CE,
+ {
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Malta
+ "MT",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Marocco
+ "MA",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48
+ { 0}, // end
+ }
+ },
+
+ { // Mexico
+ "MX",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 5, 30, IDOR, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Netherlands
+ "NL",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // New Zealand
+ "NZ",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 24, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Norway
+ "NO",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 24, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 24, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Peru
+ "PE",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Portugal
+ "PT",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Poland
+ "PL",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Romania
+ "RO",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Russia
+ "RU",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 149, 4, 20, IDOR, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Saudi Arabia
+ "SA",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 4, 23, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Serbia_and_Montenegro
+ "CS",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 0}, // end
+ }
+ },
+
+ { // Singapore
+ "SG",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64
+ { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Slovakia
+ "SK",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Slovenia
+ "SI",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // South Africa
+ "ZA",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 149, 4, 30, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // South Korea
+ "KR",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 20, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 8, 20, BOTH, FALSE}, // 5G, ch 100~128
+ { 149, 4, 20, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Spain
+ "ES",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 17, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Sweden
+ "SE",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Switzerland
+ "CH",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~13
+ { 36, 4, 23, IDOR, TRUE}, // 5G, ch 36~48
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // Taiwan
+ "TW",
+ CE,
+ {
+ { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 52, 4, 23, IDOR, FALSE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // Turkey
+ "TR",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 36, 4, 23, BOTH, FALSE}, // 5G, ch 36~48
+ { 52, 4, 23, BOTH, FALSE}, // 5G, ch 52~64
+ { 0}, // end
+ }
+ },
+
+ { // UK
+ "GB",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 36, 4, 23, IDOR, FALSE}, // 5G, ch 52~64
+ { 52, 4, 23, IDOR, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 0}, // end
+ }
+ },
+
+ { // Ukraine
+ "UA",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 0}, // end
+ }
+ },
+
+ { // United_Arab_Emirates
+ "AE",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 0}, // end
+ }
+ },
+
+ { // United_States
+ "US",
+ CE,
+ {
+ { 1, 11, 30, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 36, 4, 17, IDOR, FALSE}, // 5G, ch 52~64
+ { 52, 4, 24, BOTH, TRUE}, // 5G, ch 52~64
+ { 100, 11, 30, BOTH, TRUE}, // 5G, ch 100~140
+ { 149, 5, 30, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+
+ { // Venezuela
+ "VE",
+ CE,
+ {
+ { 1, 13, 20, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 149, 4, 27, BOTH, FALSE}, // 5G, ch 149~161
+ { 0}, // end
+ }
+ },
+
+ { // Default
+ "",
+ CE,
+ {
+ { 1, 11, 20, BOTH, FALSE}, // 2.4 G, ch 1~11
+ { 36, 4, 20, BOTH, FALSE}, // 5G, ch 52~64
+ { 52, 4, 20, BOTH, FALSE}, // 5G, ch 52~64
+ { 100, 11, 20, BOTH, FALSE}, // 5G, ch 100~140
+ { 149, 5, 20, BOTH, FALSE}, // 5G, ch 149~165
+ { 0}, // end
+ }
+ },
+};
+
+static inline PCH_REGION GetChRegion(
+ IN PUCHAR CntryCode)
+{
+ INT loop = 0;
+ PCH_REGION pChRegion = NULL;
+
+ while (strcmp(ChRegion[loop].CountReg, "") != 0)
+ {
+ if (strncmp(ChRegion[loop].CountReg, CntryCode, 2) == 0)
+ {
+ pChRegion = &ChRegion[loop];
+ break;
+ }
+ loop++;
+ }
+
+ if (pChRegion == NULL)
+ pChRegion = &ChRegion[loop];
+ return pChRegion;
+}
+
+static inline VOID ChBandCheck(
+ IN UCHAR PhyMode,
+ OUT PUCHAR pChType)
+{
+ switch(PhyMode)
+ {
+ case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11AN_MIXED:
+#endif // DOT11_N_SUPPORT //
+ *pChType = BAND_5G;
+ break;
+ case PHY_11ABG_MIXED:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11AGN_MIXED:
+ case PHY_11ABGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+ *pChType = BAND_BOTH;
+ break;
+
+ default:
+ *pChType = BAND_24G;
+ break;
+ }
+}
+
+static inline UCHAR FillChList(
+ IN PRTMP_ADAPTER pAd,
+ IN PCH_DESP pChDesp,
+ IN UCHAR Offset,
+ IN UCHAR increment)
+{
+ INT i, j, l;
+ UCHAR channel;
+
+ j = Offset;
+ for (i = 0; i < pChDesp->NumOfCh; i++)
+ {
+ channel = pChDesp->FirstChannel + i * increment;
+ for (l=0; l<MAX_NUM_OF_CHANNELS; l++)
+ {
+ if (channel == pAd->TxPower[l].Channel)
+ {
+ pAd->ChannelList[j].Power = pAd->TxPower[l].Power;
+ pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2;
+ break;
+ }
+ }
+ if (l == MAX_NUM_OF_CHANNELS)
+ continue;
+
+ pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment;
+ pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr;
+ pAd->ChannelList[j].DfsReq = pChDesp->DfsReq;
+ j++;
+ }
+ pAd->ChannelListNum = j;
+
+ return j;
+}
+
+static inline VOID CreateChList(
+ IN PRTMP_ADAPTER pAd,
+ IN PCH_REGION pChRegion,
+ IN UCHAR Geography)
+{
+ INT i;
+ UCHAR offset = 0;
+ PCH_DESP pChDesp;
+ UCHAR ChType;
+ UCHAR increment;
+
+ if (pChRegion == NULL)
+ return;
+
+ ChBandCheck(pAd->CommonCfg.PhyMode, &ChType);
+
+ for (i=0; i<10; i++)
+ {
+ pChDesp = &pChRegion->ChDesp[i];
+ if (pChDesp->FirstChannel == 0)
+ break;
+
+ if (ChType == BAND_5G)
+ {
+ if (pChDesp->FirstChannel <= 14)
+ continue;
+ }
+ else if (ChType == BAND_24G)
+ {
+ if (pChDesp->FirstChannel > 14)
+ continue;
+ }
+
+ if ((pChDesp->Geography == BOTH)
+ || (pChDesp->Geography == Geography))
+ {
+ if (pChDesp->FirstChannel > 14)
+ increment = 4;
+ else
+ increment = 1;
+ offset = FillChList(pAd, pChDesp, offset, increment);
+ }
+ }
+}
+
+static inline VOID BuildChannelListEx(
+ IN PRTMP_ADAPTER pAd)
+{
+ PCH_REGION pChReg;
+
+ pChReg = GetChRegion(pAd->CommonCfg.CountryCode);
+ CreateChList(pAd, pChReg, pAd->CommonCfg.Geography);
+}
+
+static inline VOID BuildBeaconChList(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf,
+ OUT PULONG pBufLen)
+{
+ INT i;
+ ULONG TmpLen;
+ PCH_REGION pChRegion;
+ PCH_DESP pChDesp;
+ UCHAR ChType;
+
+ pChRegion = GetChRegion(pAd->CommonCfg.CountryCode);
+
+ if (pChRegion == NULL)
+ return;
+
+ ChBandCheck(pAd->CommonCfg.PhyMode, &ChType);
+ *pBufLen = 0;
+
+ for (i=0; i<10; i++)
+ {
+ pChDesp = &pChRegion->ChDesp[i];
+ if (pChDesp->FirstChannel == 0)
+ break;
+
+ if (ChType == BAND_5G)
+ {
+ if (pChDesp->FirstChannel <= 14)
+ continue;
+ }
+ else if (ChType == BAND_24G)
+ {
+ if (pChDesp->FirstChannel > 14)
+ continue;
+ }
+
+ if ((pChDesp->Geography == BOTH)
+ || (pChDesp->Geography == pAd->CommonCfg.Geography))
+ {
+ MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen,
+ 1, &pChDesp->FirstChannel,
+ 1, &pChDesp->NumOfCh,
+ 1, &pChDesp->MaxTxPwr,
+ END_OF_ARGS);
+ *pBufLen += TmpLen;
+ }
+ }
+}
+
+
+#ifdef DOT11_N_SUPPORT
+static inline BOOLEAN IsValidChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel)
+
+{
+ INT i;
+
+ for (i = 0; i < pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].Channel == channel)
+ break;
+ }
+
+ if (i == pAd->ChannelListNum)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+static inline UCHAR GetExtCh(
+ IN UCHAR Channel,
+ IN UCHAR Direction)
+{
+ CHAR ExtCh;
+
+ if (Direction == EXTCHA_ABOVE)
+ ExtCh = Channel + 4;
+ else
+ ExtCh = (Channel - 4) > 0 ? (Channel - 4) : 0;
+
+ return ExtCh;
+}
+
+
+static inline VOID N_ChannelCheck(
+ IN PRTMP_ADAPTER pAd)
+{
+ //UCHAR ChannelNum = pAd->ChannelListNum;
+ UCHAR Channel = pAd->CommonCfg.Channel;
+
+ if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
+ {
+ if (Channel > 14)
+ {
+ if ((Channel == 36) || (Channel == 44) || (Channel == 52) || (Channel == 60) || (Channel == 100) || (Channel == 108) ||
+ (Channel == 116) || (Channel == 124) || (Channel == 132) || (Channel == 149) || (Channel == 157))
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+ }
+ else if ((Channel == 40) || (Channel == 48) || (Channel == 56) || (Channel == 64) || (Channel == 104) || (Channel == 112) ||
+ (Channel == 120) || (Channel == 128) || (Channel == 136) || (Channel == 153) || (Channel == 161))
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ }
+ }
+ else
+ {
+ do
+ {
+ UCHAR ExtCh;
+ UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
+ ExtCh = GetExtCh(Channel, Dir);
+ if (IsValidChannel(pAd, ExtCh))
+ break;
+
+ Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE;
+ ExtCh = GetExtCh(Channel, Dir);
+ if (IsValidChannel(pAd, ExtCh))
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir;
+ break;
+ }
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ } while(FALSE);
+
+ if (Channel == 14)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ //pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; // We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT()
+ }
+#if 0
+ switch (pAd->CommonCfg.CountryRegion & 0x7f)
+ {
+ case REGION_0_BG_BAND: // 1 -11
+ case REGION_1_BG_BAND: // 1 - 13
+ case REGION_5_BG_BAND: // 1 - 14
+ if (Channel <= 4)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+ }
+ else if (Channel >= 8)
+ {
+ if ((ChannelNum - Channel) < 4)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ }
+ break;
+
+ case REGION_2_BG_BAND: // 10 - 11
+ case REGION_3_BG_BAND: // 10 - 13
+ case REGION_4_BG_BAND: // 14
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ break;
+
+ case REGION_6_BG_BAND: // 3 - 9
+ if (Channel <= 5)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+ else if (Channel == 6)
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ else if (Channel >= 7)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ break;
+
+ case REGION_7_BG_BAND: // 5 - 13
+ if (Channel <= 8)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+ else if (Channel >= 10)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ break;
+
+ default: // Error. should never happen
+ break;
+ }
+#endif
+ }
+ }
+
+
+}
+
+
+static inline VOID N_SetCenCh(
+ IN PRTMP_ADAPTER pAd)
+{
+ if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+ {
+ if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE)
+ {
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
+ }
+ else
+ {
+ if (pAd->CommonCfg.Channel == 14)
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 1;
+ else
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
+ }
+ }
+ else
+ {
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+ }
+}
+#endif // DOT11_N_SUPPORT //
+
+
+static inline UINT8 GetCuntryMaxTxPwr(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 channel)
+{
+ int i;
+ for (i = 0; i < pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].Channel == channel)
+ break;
+ }
+
+ if (i == pAd->ChannelListNum)
+ return 0xff;
+ else
+ return pAd->ChannelList[i].MaxTxPwr;
+}
+#endif // __CHLIST_H__
+
diff --git a/drivers/staging/rt2860/common/2860_rtmp_init.c b/drivers/staging/rt2860/common/2860_rtmp_init.c
new file mode 100644
index 000000000000..546f304ec330
--- /dev/null
+++ b/drivers/staging/rt2860/common/2860_rtmp_init.c
@@ -0,0 +1,922 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ 2860_rtmp_init.c
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 2002-08-01 created
+ John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme
+ Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
+*/
+#include "../rt_config.h"
+
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Allocate DMA memory blocks for send, receive
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_RESOURCES
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTMPAllocTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG RingBasePaHigh;
+ ULONG RingBasePaLow;
+ PVOID RingBaseVa;
+ INT index, num;
+ PTXD_STRUC pTxD;
+ PRXD_STRUC pRxD;
+ ULONG ErrorValue = 0;
+ PRTMP_TX_RING pTxRing;
+ PRTMP_DMABUF pDmaBuf;
+ PNDIS_PACKET pPacket;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n"));
+ do
+ {
+ //
+ // Allocate all ring descriptors, include TxD, RxD, MgmtD.
+ // Although each size is different, to prevent cacheline and alignment
+ // issue, I intentional set them all to 64 bytes.
+ //
+ for (num=0; num<NUM_OF_TX_RING; num++)
+ {
+ ULONG BufBasePaHigh;
+ ULONG BufBasePaLow;
+ PVOID BufBaseVa;
+
+ //
+ // Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)
+ //
+ pAd->TxDescRing[num].AllocSize = TX_RING_SIZE * TXD_SIZE;
+ RTMP_AllocateTxDescMemory(
+ pAd,
+ num,
+ pAd->TxDescRing[num].AllocSize,
+ FALSE,
+ &pAd->TxDescRing[num].AllocVa,
+ &pAd->TxDescRing[num].AllocPa);
+
+ if (pAd->TxDescRing[num].AllocVa == NULL)
+ {
+ ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
+ DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
+ Status = NDIS_STATUS_RESOURCES;
+ break;
+ }
+
+ // Zero init this memory block
+ NdisZeroMemory(pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocSize);
+
+ // Save PA & VA for further operation
+ RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxDescRing[num].AllocPa);
+ RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxDescRing[num].AllocPa);
+ RingBaseVa = pAd->TxDescRing[num].AllocVa;
+
+ //
+ // Allocate all 1st TXBuf's memory for this TxRing
+ //
+ pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE;
+ RTMP_AllocateFirstTxBuffer(
+ pAd,
+ num,
+ pAd->TxBufSpace[num].AllocSize,
+ FALSE,
+ &pAd->TxBufSpace[num].AllocVa,
+ &pAd->TxBufSpace[num].AllocPa);
+
+ if (pAd->TxBufSpace[num].AllocVa == NULL)
+ {
+ ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
+ DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
+ Status = NDIS_STATUS_RESOURCES;
+ break;
+ }
+
+ // Zero init this memory block
+ NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize);
+
+ // Save PA & VA for further operation
+ BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa);
+ BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa);
+ BufBaseVa = pAd->TxBufSpace[num].AllocVa;
+
+ //
+ // Initialize Tx Ring Descriptor and associated buffer memory
+ //
+ pTxRing = &pAd->TxRing[num];
+ for (index = 0; index < TX_RING_SIZE; index++)
+ {
+ pTxRing->Cell[index].pNdisPacket = NULL;
+ pTxRing->Cell[index].pNextNdisPacket = NULL;
+ // Init Tx Ring Size, Va, Pa variables
+ pTxRing->Cell[index].AllocSize = TXD_SIZE;
+ pTxRing->Cell[index].AllocVa = RingBaseVa;
+ RTMP_SetPhysicalAddressHigh(pTxRing->Cell[index].AllocPa, RingBasePaHigh);
+ RTMP_SetPhysicalAddressLow (pTxRing->Cell[index].AllocPa, RingBasePaLow);
+
+ // Setup Tx Buffer size & address. only 802.11 header will store in this space
+ pDmaBuf = &pTxRing->Cell[index].DmaBuf;
+ pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE;
+ pDmaBuf->AllocVa = BufBaseVa;
+ RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh);
+ RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow);
+
+ // link the pre-allocated TxBuf to TXD
+ pTxD = (PTXD_STRUC) pTxRing->Cell[index].AllocVa;
+ pTxD->SDPtr0 = BufBasePaLow;
+ // advance to next ring descriptor address
+ pTxD->DMADONE = 1;
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ RingBasePaLow += TXD_SIZE;
+ RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
+
+ // advance to next TxBuf address
+ BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE;
+ BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index));
+ }
+ if (Status == NDIS_STATUS_RESOURCES)
+ break;
+
+ //
+ // Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler
+ //
+ pAd->MgmtDescRing.AllocSize = MGMT_RING_SIZE * TXD_SIZE;
+ RTMP_AllocateMgmtDescMemory(
+ pAd,
+ pAd->MgmtDescRing.AllocSize,
+ FALSE,
+ &pAd->MgmtDescRing.AllocVa,
+ &pAd->MgmtDescRing.AllocPa);
+
+ if (pAd->MgmtDescRing.AllocVa == NULL)
+ {
+ ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
+ DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
+ Status = NDIS_STATUS_RESOURCES;
+ break;
+ }
+
+ // Zero init this memory block
+ NdisZeroMemory(pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocSize);
+
+ // Save PA & VA for further operation
+ RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa);
+ RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->MgmtDescRing.AllocPa);
+ RingBaseVa = pAd->MgmtDescRing.AllocVa;
+
+ //
+ // Initialize MGMT Ring and associated buffer memory
+ //
+ for (index = 0; index < MGMT_RING_SIZE; index++)
+ {
+ pAd->MgmtRing.Cell[index].pNdisPacket = NULL;
+ pAd->MgmtRing.Cell[index].pNextNdisPacket = NULL;
+ // Init MGMT Ring Size, Va, Pa variables
+ pAd->MgmtRing.Cell[index].AllocSize = TXD_SIZE;
+ pAd->MgmtRing.Cell[index].AllocVa = RingBaseVa;
+ RTMP_SetPhysicalAddressHigh(pAd->MgmtRing.Cell[index].AllocPa, RingBasePaHigh);
+ RTMP_SetPhysicalAddressLow (pAd->MgmtRing.Cell[index].AllocPa, RingBasePaLow);
+
+ // Offset to next ring descriptor address
+ RingBasePaLow += TXD_SIZE;
+ RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE;
+
+ // link the pre-allocated TxBuf to TXD
+ pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[index].AllocVa;
+ pTxD->DMADONE = 1;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ // no pre-allocated buffer required in MgmtRing for scatter-gather case
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index));
+
+ //
+ // Allocate RX ring descriptor's memory except Tx ring which allocated eariler
+ //
+ pAd->RxDescRing.AllocSize = RX_RING_SIZE * RXD_SIZE;
+ RTMP_AllocateRxDescMemory(
+ pAd,
+ pAd->RxDescRing.AllocSize,
+ FALSE,
+ &pAd->RxDescRing.AllocVa,
+ &pAd->RxDescRing.AllocPa);
+
+ if (pAd->RxDescRing.AllocVa == NULL)
+ {
+ ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
+ DBGPRINT_ERR(("Failed to allocate a big buffer\n"));
+ Status = NDIS_STATUS_RESOURCES;
+ break;
+ }
+
+ // Zero init this memory block
+ NdisZeroMemory(pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocSize);
+
+
+ printk("RX DESC %p size = %ld\n", pAd->RxDescRing.AllocVa,
+ pAd->RxDescRing.AllocSize);
+
+ // Save PA & VA for further operation
+ RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing.AllocPa);
+ RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing.AllocPa);
+ RingBaseVa = pAd->RxDescRing.AllocVa;
+
+ //
+ // Initialize Rx Ring and associated buffer memory
+ //
+ for (index = 0; index < RX_RING_SIZE; index++)
+ {
+ // Init RX Ring Size, Va, Pa variables
+ pAd->RxRing.Cell[index].AllocSize = RXD_SIZE;
+ pAd->RxRing.Cell[index].AllocVa = RingBaseVa;
+ RTMP_SetPhysicalAddressHigh(pAd->RxRing.Cell[index].AllocPa, RingBasePaHigh);
+ RTMP_SetPhysicalAddressLow (pAd->RxRing.Cell[index].AllocPa, RingBasePaLow);
+
+ // Offset to next ring descriptor address
+ RingBasePaLow += RXD_SIZE;
+ RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE;
+
+ // Setup Rx associated Buffer size & allocate share memory
+ pDmaBuf = &pAd->RxRing.Cell[index].DmaBuf;
+ pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE;
+ pPacket = RTMP_AllocateRxPacketBuffer(
+ pAd,
+ pDmaBuf->AllocSize,
+ FALSE,
+ &pDmaBuf->AllocVa,
+ &pDmaBuf->AllocPa);
+
+ /* keep allocated rx packet */
+ pAd->RxRing.Cell[index].pNdisPacket = pPacket;
+
+ // Error handling
+ if (pDmaBuf->AllocVa == NULL)
+ {
+ ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY;
+ DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n"));
+ Status = NDIS_STATUS_RESOURCES;
+ break;
+ }
+
+ // Zero init this memory block
+ NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize);
+
+ // Write RxD buffer address & allocated buffer length
+ pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
+ pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa);
+ pRxD->DDONE = 0;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
+#endif
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Rx Ring: total %d entry allocated\n", index));
+
+ } while (FALSE);
+
+
+ NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME));
+ pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+
+ if (pAd->FragFrame.pFragPacket == NULL)
+ {
+ Status = NDIS_STATUS_RESOURCES;
+ }
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // Log error inforamtion
+ NdisWriteErrorLogEntry(
+ pAd->AdapterHandle,
+ NDIS_ERROR_CODE_OUT_OF_RESOURCES,
+ 1,
+ ErrorValue);
+ }
+
+ DBGPRINT_S(Status, ("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status));
+ return Status;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Initialize transmit data structures
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+ Initialize all transmit releated private buffer, include those define
+ in RTMP_ADAPTER structure and all private data structures.
+
+ ========================================================================
+*/
+VOID NICInitTxRxRingAndBacklogQueue(
+ IN PRTMP_ADAPTER pAd)
+{
+ //WPDMA_GLO_CFG_STRUC GloCfg;
+ int i;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<--> NICInitTxRxRingAndBacklogQueue\n"));
+
+ // Initialize all transmit related software queues
+ InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BE]);
+ InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_BK]);
+ InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VI]);
+ InitializeQueueHeader(&pAd->TxSwQueue[QID_AC_VO]);
+ InitializeQueueHeader(&pAd->TxSwQueue[QID_HCCA]);
+
+ // Init RX Ring index pointer
+ pAd->RxRing.RxSwReadIdx = 0;
+ pAd->RxRing.RxCpuIdx = RX_RING_SIZE - 1;
+
+ // Init TX rings index pointer
+ for (i=0; i<NUM_OF_TX_RING; i++)
+ {
+ pAd->TxRing[i].TxSwFreeIdx = 0;
+ pAd->TxRing[i].TxCpuIdx = 0;
+ }
+
+ // init MGMT ring index pointer
+ pAd->MgmtRing.TxSwFreeIdx = 0;
+ pAd->MgmtRing.TxCpuIdx = 0;
+
+ pAd->PrivateInfo.TxRingFullCnt = 0;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero.
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ Reset NIC to initial state AS IS system boot up time.
+
+ ========================================================================
+*/
+VOID RTMPRingCleanUp(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR RingType)
+{
+ PTXD_STRUC pTxD;
+ PRXD_STRUC pRxD;
+ PQUEUE_ENTRY pEntry;
+ PNDIS_PACKET pPacket;
+ int i;
+ PRTMP_TX_RING pTxRing;
+ unsigned long IrqFlags;
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount));
+ switch (RingType)
+ {
+ case QID_AC_BK:
+ case QID_AC_BE:
+ case QID_AC_VI:
+ case QID_AC_VO:
+ case QID_HCCA:
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ pTxRing = &pAd->TxRing[RingType];
+
+ // We have to clean all descriptors in case some error happened with reset
+ for (i=0; i<TX_RING_SIZE; i++) // We have to scan all TX ring
+ {
+ pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
+
+ pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket;
+ // release scatter-and-gather NDIS_PACKET
+ if (pPacket)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ pTxRing->Cell[i].pNdisPacket = NULL;
+ }
+
+ pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNextNdisPacket;
+ // release scatter-and-gather NDIS_PACKET
+ if (pPacket)
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ pTxRing->Cell[i].pNextNdisPacket = NULL;
+ }
+ }
+
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + RingType * 0x10, &pTxRing->TxDmaIdx);
+ pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
+ pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + RingType * 0x10, pTxRing->TxCpuIdx);
+
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ while (pAd->TxSwQueue[RingType].Head != NULL)
+ {
+ pEntry = RemoveHeadQueue(&pAd->TxSwQueue[RingType]);
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ DBGPRINT(RT_DEBUG_TRACE,("Release 1 NDIS packet from s/w backlog queue\n"));
+ }
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ break;
+
+ case QID_MGMT:
+ // We have to clean all descriptors in case some error happened with reset
+ NdisAcquireSpinLock(&pAd->MgmtRingLock);
+
+ for (i=0; i<MGMT_RING_SIZE; i++)
+ {
+ pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[i].AllocVa;
+
+ pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNdisPacket;
+ // rlease scatter-and-gather NDIS_PACKET
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+ pAd->MgmtRing.Cell[i].pNdisPacket = NULL;
+
+ pPacket = (PNDIS_PACKET) pAd->MgmtRing.Cell[i].pNextNdisPacket;
+ // release scatter-and-gather NDIS_PACKET
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+ pAd->MgmtRing.Cell[i].pNextNdisPacket = NULL;
+
+ }
+
+ RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pAd->MgmtRing.TxDmaIdx);
+ pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx;
+ pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx;
+ RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
+
+ NdisReleaseSpinLock(&pAd->MgmtRingLock);
+ pAd->RalinkCounters.MgmtRingFullCount = 0;
+ break;
+
+ case QID_RX:
+ // We have to clean all descriptors in case some error happened with reset
+ NdisAcquireSpinLock(&pAd->RxRingLock);
+
+ for (i=0; i<RX_RING_SIZE; i++)
+ {
+ pRxD = (PRXD_STRUC) pAd->RxRing.Cell[i].AllocVa;
+ pRxD->DDONE = 0 ;
+ }
+
+ RTMP_IO_READ32(pAd, RX_DRX_IDX, &pAd->RxRing.RxDmaIdx);
+ pAd->RxRing.RxSwReadIdx = pAd->RxRing.RxDmaIdx;
+ pAd->RxRing.RxCpuIdx = ((pAd->RxRing.RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxDmaIdx-1));
+ RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
+
+ NdisReleaseSpinLock(&pAd->RxRingLock);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+NDIS_STATUS AdapterBlockAllocateMemory(
+ IN PVOID handle,
+ OUT PVOID *ppAd)
+{
+ PPCI_DEV pci_dev;
+ dma_addr_t *phy_addr;
+ POS_COOKIE pObj = (POS_COOKIE) handle;
+
+ pci_dev = pObj->pci_dev;
+ phy_addr = &pObj->pAd_pa;
+
+ *ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr);
+
+ if (*ppAd)
+ {
+ NdisZeroMemory(*ppAd, sizeof(RTMP_ADAPTER));
+ ((PRTMP_ADAPTER)*ppAd)->OS_Cookie = handle;
+ return (NDIS_STATUS_SUCCESS);
+ } else {
+ return (NDIS_STATUS_FAILURE);
+ }
+}
+
+
+void RTMP_AllocateTxDescMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT Index,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
+{
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
+
+}
+
+void RTMP_AllocateMgmtDescMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
+{
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
+
+}
+
+void RTMP_AllocateRxDescMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
+{
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
+
+}
+
+void RTMP_FreeRxDescMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN PVOID VirtualAddress,
+ IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
+{
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ PCI_FREE_CONSISTENT(pObj->pci_dev, Length, VirtualAddress, PhysicalAddress);
+}
+
+
+void RTMP_AllocateFirstTxBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT Index,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
+{
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
+}
+
+/*
+ * FUNCTION: Allocate a common buffer for DMA
+ * ARGUMENTS:
+ * AdapterHandle: AdapterHandle
+ * Length: Number of bytes to allocate
+ * Cached: Whether or not the memory can be cached
+ * VirtualAddress: Pointer to memory is returned here
+ * PhysicalAddress: Physical address corresponding to virtual address
+ */
+
+void RTMP_AllocateSharedMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
+{
+ POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ *VirtualAddress = (PVOID)PCI_ALLOC_CONSISTENT(pObj->pci_dev,sizeof(char)*Length, PhysicalAddress);
+}
+
+VOID RTMPFreeTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd)
+{
+ int index, num , j;
+ PRTMP_TX_RING pTxRing;
+ PTXD_STRUC pTxD;
+ PNDIS_PACKET pPacket;
+ unsigned int IrqFlags;
+
+ POS_COOKIE pObj =(POS_COOKIE) pAd->OS_Cookie;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n"));
+
+ // Free TxSwQueue Packet
+ for (index=0; index <NUM_OF_TX_RING; index++)
+ {
+ PQUEUE_ENTRY pEntry;
+ PNDIS_PACKET pPacket;
+ PQUEUE_HEADER pQueue;
+
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ pQueue = &pAd->TxSwQueue[index];
+ while (pQueue->Head)
+ {
+ pEntry = RemoveHeadQueue(pQueue);
+ pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+ }
+
+ // Free Tx Ring Packet
+ for (index=0;index< NUM_OF_TX_RING;index++)
+ {
+ pTxRing = &pAd->TxRing[index];
+
+ for (j=0; j< TX_RING_SIZE; j++)
+ {
+ pTxD = (PTXD_STRUC) (pTxRing->Cell[j].AllocVa);
+ pPacket = pTxRing->Cell[j].pNdisPacket;
+
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNdisPacket as NULL after clear
+ pTxRing->Cell[j].pNdisPacket = NULL;
+
+ pPacket = pTxRing->Cell[j].pNextNdisPacket;
+
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNextNdisPacket as NULL after clear
+ pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
+
+ }
+ }
+
+ for (index = RX_RING_SIZE - 1 ; index >= 0; index--)
+ {
+ if ((pAd->RxRing.Cell[index].DmaBuf.AllocVa) && (pAd->RxRing.Cell[index].pNdisPacket))
+ {
+ PCI_UNMAP_SINGLE(pObj->pci_dev, pAd->RxRing.Cell[index].DmaBuf.AllocPa, pAd->RxRing.Cell[index].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
+ RELEASE_NDIS_PACKET(pAd, pAd->RxRing.Cell[index].pNdisPacket, NDIS_STATUS_SUCCESS);
+ }
+ }
+ NdisZeroMemory(pAd->RxRing.Cell, RX_RING_SIZE * sizeof(RTMP_DMACB));
+
+ if (pAd->RxDescRing.AllocVa)
+ {
+ PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->RxDescRing.AllocSize, pAd->RxDescRing.AllocVa, pAd->RxDescRing.AllocPa);
+ }
+ NdisZeroMemory(&pAd->RxDescRing, sizeof(RTMP_DMABUF));
+
+ if (pAd->MgmtDescRing.AllocVa)
+ {
+ PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa);
+ }
+ NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF));
+
+ for (num = 0; num < NUM_OF_TX_RING; num++)
+ {
+ if (pAd->TxBufSpace[num].AllocVa)
+ {
+ PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxBufSpace[num].AllocSize, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa);
+ }
+ NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF));
+
+ if (pAd->TxDescRing[num].AllocVa)
+ {
+ PCI_FREE_CONSISTENT(pObj->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa);
+ }
+ NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF));
+ }
+
+ if (pAd->FragFrame.pFragPacket)
+ RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n"));
+}
+
+
+/*
+ * FUNCTION: Allocate a packet buffer for DMA
+ * ARGUMENTS:
+ * AdapterHandle: AdapterHandle
+ * Length: Number of bytes to allocate
+ * Cached: Whether or not the memory can be cached
+ * VirtualAddress: Pointer to memory is returned here
+ * PhysicalAddress: Physical address corresponding to virtual address
+ * Notes:
+ * Cached is ignored: always cached memory
+ */
+PNDIS_PACKET RTMP_AllocateRxPacketBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
+{
+ PNDIS_PACKET pkt;
+
+ pkt = RTPKT_TO_OSPKT(DEV_ALLOC_SKB(Length));
+
+ if (pkt == NULL) {
+ DBGPRINT(RT_DEBUG_ERROR, ("can't allocate rx %ld size packet\n",Length));
+ }
+
+ if (pkt) {
+ RTMP_SET_PACKET_SOURCE(pkt, PKTSRC_NDIS);
+ *VirtualAddress = (PVOID) RTPKT_TO_OSPKT(pkt)->data;
+ *PhysicalAddress = PCI_MAP_SINGLE(pAd, *VirtualAddress, Length, -1, PCI_DMA_FROMDEVICE);
+ } else {
+ *VirtualAddress = (PVOID) NULL;
+ *PhysicalAddress = (NDIS_PHYSICAL_ADDRESS) NULL;
+ }
+
+ return (PNDIS_PACKET) pkt;
+}
+
+
+VOID Invalid_Remaining_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG VirtualAddress)
+{
+ NDIS_PHYSICAL_ADDRESS PhysicalAddress;
+
+ PhysicalAddress = PCI_MAP_SINGLE(pAd, (void *)(VirtualAddress+1600), RX_BUFFER_NORMSIZE-1600, -1, PCI_DMA_FROMDEVICE);
+}
+
+PNDIS_PACKET GetPacketFromRxRing(
+ IN PRTMP_ADAPTER pAd,
+ OUT PRT28XX_RXD_STRUC pSaveRxD,
+ OUT BOOLEAN *pbReschedule,
+ IN OUT UINT32 *pRxPending)
+{
+ PRXD_STRUC pRxD;
+#ifdef RT_BIG_ENDIAN
+ PRXD_STRUC pDestRxD;
+ RXD_STRUC RxD;
+#endif
+ PNDIS_PACKET pRxPacket = NULL;
+ PNDIS_PACKET pNewPacket;
+ PVOID AllocVa;
+ NDIS_PHYSICAL_ADDRESS AllocPa;
+ BOOLEAN bReschedule = FALSE;
+
+ RTMP_SEM_LOCK(&pAd->RxRingLock);
+
+ if (*pRxPending == 0)
+ {
+ // Get how may packets had been received
+ RTMP_IO_READ32(pAd, RX_DRX_IDX , &pAd->RxRing.RxDmaIdx);
+
+ if (pAd->RxRing.RxSwReadIdx == pAd->RxRing.RxDmaIdx)
+ {
+ // no more rx packets
+ bReschedule = FALSE;
+ goto done;
+ }
+
+ // get rx pending count
+ if (pAd->RxRing.RxDmaIdx > pAd->RxRing.RxSwReadIdx)
+ *pRxPending = pAd->RxRing.RxDmaIdx - pAd->RxRing.RxSwReadIdx;
+ else
+ *pRxPending = pAd->RxRing.RxDmaIdx + RX_RING_SIZE - pAd->RxRing.RxSwReadIdx;
+
+ }
+
+#ifdef RT_BIG_ENDIAN
+ pDestRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
+ RxD = *pDestRxD;
+ pRxD = &RxD;
+ RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
+#else
+ // Point to Rx indexed rx ring descriptor
+ pRxD = (PRXD_STRUC) pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].AllocVa;
+#endif
+
+ if (pRxD->DDONE == 0)
+ {
+ *pRxPending = 0;
+ // DMAIndx had done but DDONE bit not ready
+ bReschedule = TRUE;
+ goto done;
+ }
+
+
+ // return rx descriptor
+ NdisMoveMemory(pSaveRxD, pRxD, RXD_SIZE);
+
+ pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa);
+
+ if (pNewPacket)
+ {
+ // unmap the rx buffer
+ PCI_UNMAP_SINGLE(pAd, pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa,
+ pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize, PCI_DMA_FROMDEVICE);
+ pRxPacket = pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket;
+
+ pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocSize = RX_BUFFER_AGGRESIZE;
+ pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].pNdisPacket = (PNDIS_PACKET) pNewPacket;
+ pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocVa = AllocVa;
+ pAd->RxRing.Cell[pAd->RxRing.RxSwReadIdx].DmaBuf.AllocPa = AllocPa;
+ /* update SDP0 to new buffer of rx packet */
+ pRxD->SDP0 = AllocPa;
+ }
+ else
+ {
+ //printk("No Rx Buffer\n");
+ pRxPacket = NULL;
+ bReschedule = TRUE;
+ }
+
+ pRxD->DDONE = 0;
+
+ // had handled one rx packet
+ *pRxPending = *pRxPending - 1;
+
+ // update rx descriptor and kick rx
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);
+ WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD);
+#endif
+ INC_RING_INDEX(pAd->RxRing.RxSwReadIdx, RX_RING_SIZE);
+
+ pAd->RxRing.RxCpuIdx = (pAd->RxRing.RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pAd->RxRing.RxSwReadIdx-1);
+ RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
+
+done:
+ RTMP_SEM_UNLOCK(&pAd->RxRingLock);
+ *pbReschedule = bReschedule;
+ return pRxPacket;
+}
+/* End of 2860_rtmp_init.c */
+
diff --git a/drivers/staging/rt2860/common/action.c b/drivers/staging/rt2860/common/action.c
new file mode 100644
index 000000000000..d6f530fb857f
--- /dev/null
+++ b/drivers/staging/rt2860/common/action.c
@@ -0,0 +1,1031 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ action.c
+
+ Abstract:
+ Handle association related requests either from WSTA or from local MLME
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Jan Lee 2006 created for rt2860
+ */
+
+#include "../rt_config.h"
+#include "action.h"
+
+
+static VOID ReservedAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+/*
+ ==========================================================================
+ Description:
+ association state machine init, including state transition and timer init
+ Parameters:
+ S - pointer to the association state machine
+ Note:
+ The state machine looks like the following
+
+ ASSOC_IDLE
+ MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action
+ MT2_PEER_DISASSOC_REQ peer_disassoc_action
+ MT2_PEER_ASSOC_REQ drop
+ MT2_PEER_REASSOC_REQ drop
+ MT2_CLS3ERR cls3err_action
+ ==========================================================================
+ */
+VOID ActionStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE);
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction);
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction);
+#ifdef QOS_DLS_SUPPORT
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)PeerDLSAction);
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction);
+#endif // DOT11_N_SUPPORT //
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction);
+
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction);
+ StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction);
+}
+
+#ifdef DOT11_N_SUPPORT
+VOID MlmeADDBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ MLME_ADDBA_REQ_STRUCT *pInfo;
+ UCHAR Addr[6];
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG Idx;
+ FRAME_ADDBA_REQ Frame;
+ ULONG FrameLen;
+ BA_ORI_ENTRY *pBAEntry = NULL;
+
+ pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg;
+ NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ));
+
+ if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr))
+ {
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n"));
+ return;
+ }
+ // 1. find entry
+ Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
+ if (Idx == 0)
+ {
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n"));
+ return;
+ }
+ else
+ {
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (ADHOC_ON(pAd))
+ ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ else
+#ifdef QOS_DLS_SUPPORT
+ if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls)
+ ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ else
+#endif // QOS_DLS_SUPPORT //
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pInfo->pAddr);
+
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ Frame.Category = CATEGORY_BA;
+ Frame.Action = ADDBA_REQ;
+ Frame.BaParm.AMSDUSupported = 0;
+ Frame.BaParm.BAPolicy = IMMED_BA;
+ Frame.BaParm.TID = pInfo->TID;
+ Frame.BaParm.BufSize = pInfo->BaBufSize;
+ Frame.Token = pInfo->Token;
+ Frame.TimeOutValue = pInfo->TimeOutValue;
+ Frame.BaStartSeq.field.FragNum = 0;
+ Frame.BaStartSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID];
+
+ *(USHORT *)(&Frame.BaParm) = cpu2le16(*(USHORT *)(&Frame.BaParm));
+ Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue);
+ Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word);
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ADDBA_REQ), &Frame,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize));
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ send DELBA and delete BaEntry if any
+ Parametrs:
+ Elem - MLME message MLME_DELBA_REQ_STRUCT
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeDELBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MLME_DELBA_REQ_STRUCT *pInfo;
+ PUCHAR pOutBuffer = NULL;
+ PUCHAR pOutBuffer2 = NULL;
+ NDIS_STATUS NStatus;
+ ULONG Idx;
+ FRAME_DELBA_REQ Frame;
+ ULONG FrameLen;
+ FRAME_BAR FrameBar;
+
+ pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg;
+ // must send back DELBA
+ NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ));
+ DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator));
+
+ if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen))
+ {
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n"));
+ return;
+ }
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n"));
+ return;
+ }
+
+ // SEND BAR (Send BAR to refresh peer reordering buffer.)
+ Idx = pAd->MacTab.Content[pInfo->Wcid].BAOriWcidArray[pInfo->TID];
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+
+ FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL funciton.
+ FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.Content[pInfo->Wcid].TxSeq[pInfo->TID]; // make sure sequence not clear in DEL funciton.
+ FrameBar.BarControl.TID = pInfo->TID; // make sure sequence not clear in DEL funciton.
+ FrameBar.BarControl.ACKPolicy = IMMED_BA; // make sure sequence not clear in DEL funciton.
+ FrameBar.BarControl.Compressed = 1; // make sure sequence not clear in DEL funciton.
+ FrameBar.BarControl.MTID = 0; // make sure sequence not clear in DEL funciton.
+
+ MakeOutgoingFrame(pOutBuffer2, &FrameLen,
+ sizeof(FRAME_BAR), &FrameBar,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer2);
+ DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n"));
+
+ // SEND DELBA FRAME
+ FrameLen = 0;
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (ADHOC_ON(pAd))
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ else
+#ifdef QOS_DLS_SUPPORT
+ if (pAd->MacTab.Content[pInfo->Wcid].ValidAsDls)
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[pInfo->Wcid].Addr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ else
+#endif // QOS_DLS_SUPPORT //
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[pInfo->Wcid].Addr);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ Frame.Category = CATEGORY_BA;
+ Frame.Action = DELBA;
+ Frame.DelbaParm.Initiator = pInfo->Initiator;
+ Frame.DelbaParm.TID = pInfo->TID;
+ Frame.ReasonCode = 39; // Time Out
+ *(USHORT *)(&Frame.DelbaParm) = cpu2le16(*(USHORT *)(&Frame.DelbaParm));
+ Frame.ReasonCode = cpu2le16(Frame.ReasonCode);
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_DELBA_REQ), &Frame,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator));
+ }
+}
+#endif // DOT11_N_SUPPORT //
+
+VOID MlmeQOSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID MlmeDLSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+VOID MlmeInvalidAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ //PUCHAR pOutBuffer = NULL;
+ //Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11
+}
+
+VOID PeerQOSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+#ifdef QOS_DLS_SUPPORT
+VOID PeerDLSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+
+ switch(Action)
+ {
+ case ACTION_DLS_REQUEST:
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ PeerDlsReqAction(pAd, Elem);
+#endif // CONFIG_STA_SUPPORT //
+ break;
+
+ case ACTION_DLS_RESPONSE:
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ PeerDlsRspAction(pAd, Elem);
+#endif // CONFIG_STA_SUPPORT //
+ break;
+
+ case ACTION_DLS_TEARDOWN:
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ PeerDlsTearDownAction(pAd, Elem);
+#endif // CONFIG_STA_SUPPORT //
+ break;
+ }
+}
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+VOID PeerBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+
+ switch(Action)
+ {
+ case ADDBA_REQ:
+ PeerAddBAReqAction(pAd,Elem);
+ break;
+ case ADDBA_RESP:
+ PeerAddBARspAction(pAd,Elem);
+ break;
+ case DELBA:
+ PeerDelBAAction(pAd,Elem);
+ break;
+ }
+}
+
+
+#ifdef DOT11N_DRAFT3
+
+#ifdef CONFIG_STA_SUPPORT
+VOID StaPublicAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Bss2040Coexist)
+{
+ BSS_2040_COEXIST_IE BssCoexist;
+ MLME_SCAN_REQ_STRUCT ScanReq;
+
+ BssCoexist.word = Bss2040Coexist;
+ // AP asks Station to return a 20/40 BSS Coexistence mgmt frame. So we first starts a scan, then send back 20/40 BSS Coexistence mgmt frame
+ if ((BssCoexist.field.InfoReq == 1) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)))
+ {
+ // Clear record first. After scan , will update those bit and send back to transmiter.
+ pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1;
+ pAd->CommonCfg.BSSCoexist2040.field.Intolerant40 = 0;
+ pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 0;
+ // Fill out stuff for scan request
+ ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+ }
+}
+
+
+/*
+Description : Build Intolerant Channel Rerpot from Trigger event table.
+return : how many bytes copied.
+*/
+ULONG BuildIntolerantChannelRep(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDest)
+{
+ ULONG FrameLen = 0;
+ ULONG ReadOffset = 0;
+ UCHAR i;
+ UCHAR LastRegClass = 0xff;
+ PUCHAR pLen;
+
+ for ( i = 0;i < MAX_TRIGGER_EVENT;i++)
+ {
+ if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid == TRUE)
+ {
+ if (pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass == LastRegClass)
+ {
+ *(pDest + ReadOffset) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
+ *pLen++;
+ ReadOffset++;
+ FrameLen++;
+ }
+ else
+ {
+ *(pDest + ReadOffset) = IE_2040_BSS_INTOLERANT_REPORT; // IE
+ *(pDest + ReadOffset + 1) = 2; // Len = RegClass byte + channel byte.
+ pLen = pDest + ReadOffset + 1;
+ LastRegClass = pAd->CommonCfg.TriggerEventTab.EventA[i].RegClass;
+ *(pDest + ReadOffset + 2) = LastRegClass; // Len = RegClass byte + channel byte.
+ *(pDest + ReadOffset + 3) = (UCHAR)pAd->CommonCfg.TriggerEventTab.EventA[i].Channel;
+ FrameLen += 4;
+ ReadOffset += 4;
+ }
+
+ }
+ }
+ return FrameLen;
+}
+
+
+/*
+Description : Send 20/40 BSS Coexistence Action frame If one trigger event is triggered.
+*/
+VOID Send2040CoexistAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN BOOLEAN bAddIntolerantCha)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ FRAME_ACTION_HDR Frame;
+ ULONG FrameLen;
+ ULONG IntolerantChaRepLen;
+
+ IntolerantChaRepLen = 0;
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction() allocate memory failed \n"));
+ return;
+ }
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->CommonCfg.Bssid);
+ Frame.Category = CATEGORY_PUBLIC;
+ Frame.Action = ACTION_BSS_2040_COEXIST;
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ACTION_HDR), &Frame,
+ END_OF_ARGS);
+
+ *(pOutBuffer + FrameLen) = pAd->CommonCfg.BSSCoexist2040.word;
+ FrameLen++;
+
+ if (bAddIntolerantCha == TRUE)
+ IntolerantChaRepLen = BuildIntolerantChannelRep(pAd, pOutBuffer + FrameLen);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen + IntolerantChaRepLen);
+ DBGPRINT(RT_DEBUG_ERROR,("ACT - Send2040CoexistAction( BSSCoexist2040 = 0x%x ) \n", pAd->CommonCfg.BSSCoexist2040.word));
+
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ After scan, Update 20/40 BSS Coexistence IE and send out.
+ According to 802.11n D3.03 11.14.10
+
+ Parameters:
+ ==========================================================================
+ */
+VOID Update2040CoexistFrameAndNotify(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN BOOLEAN bAddIntolerantCha)
+{
+ BSS_2040_COEXIST_IE OldValue;
+
+ OldValue.word = pAd->CommonCfg.BSSCoexist2040.word;
+ if ((pAd->CommonCfg.TriggerEventTab.EventANo > 0) || (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0))
+ pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq = 1;
+
+ // Need to check !!!!
+ // How STA will set Intolerant40 if implementation dependent. Now we don't set this bit first.!!!!!
+ // So Only check BSS20WidthReq change.
+ if (OldValue.field.BSS20WidthReq != pAd->CommonCfg.BSSCoexist2040.field.BSS20WidthReq)
+ {
+ Send2040CoexistAction(pAd, Wcid, bAddIntolerantCha);
+ }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+BOOLEAN ChannelSwitchSanityCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR NewChannel,
+ IN UCHAR Secondary)
+{
+ UCHAR i;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return FALSE;
+
+ if ((NewChannel > 7) && (Secondary == 1))
+ return FALSE;
+
+ if ((NewChannel < 5) && (Secondary == 3))
+ return FALSE;
+
+ // 0. Check if new channel is in the channellist.
+ for (i = 0;i < pAd->ChannelListNum;i++)
+ {
+ if (pAd->ChannelList[i].Channel == NewChannel)
+ {
+ break;
+ }
+ }
+
+ if (i == pAd->ChannelListNum)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+VOID ChannelSwitchAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR NewChannel,
+ IN UCHAR Secondary)
+{
+ UCHAR BBPValue = 0;
+ ULONG MACValue;
+
+ DBGPRINT(RT_DEBUG_TRACE,("SPECTRUM - ChannelSwitchAction(NewChannel = %d , Secondary = %d) \n", NewChannel, Secondary));
+
+ if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE)
+ return;
+
+ // 1. Switches to BW = 20.
+ if (Secondary == 0)
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+ BBPValue&= (~0x18);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+ if (pAd->MACVersion == 0x28600100)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+ }
+ pAd->CommonCfg.BBPCurrentBW = BW_20;
+ pAd->CommonCfg.Channel = NewChannel;
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel,FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!20MHz !!! \n" ));
+ }
+ // 1. Switches to BW = 40 And Station supports BW = 40.
+ else if (((Secondary == 1) || (Secondary == 3)) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1))
+ {
+ pAd->CommonCfg.Channel = NewChannel;
+
+ if (Secondary == 1)
+ {
+ // Secondary above.
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2;
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
+ MACValue &= 0xfe;
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+ BBPValue&= (~0x18);
+ BBPValue|= (0x10);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
+ BBPValue&= (~0x20);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
+ }
+ else
+ {
+ // Secondary below.
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2;
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &MACValue);
+ MACValue &= 0xfe;
+ MACValue |= 0x1;
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, MACValue);
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+ BBPValue&= (~0x18);
+ BBPValue|= (0x10);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPValue);
+ BBPValue&= (~0x20);
+ BBPValue|= (0x20);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPValue);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
+ }
+ pAd->CommonCfg.BBPCurrentBW = BW_40;
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+ pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1;
+ }
+}
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+VOID PeerPublicAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+#ifdef DOT11N_DRAFT3
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+#endif // DOT11N_DRAFT3 //
+
+ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return;
+
+#ifdef DOT11N_DRAFT3
+ switch(Action)
+ {
+ case ACTION_BSS_2040_COEXIST: // Format defined in IEEE 7.4.7a.1 in 11n Draf3.03
+ {
+ //UCHAR BssCoexist;
+ BSS_2040_COEXIST_ELEMENT *pCoexistInfo;
+ BSS_2040_COEXIST_IE *pBssCoexistIe;
+ BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL;
+
+ if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) )
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen));
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n"));
+ hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen);
+
+
+ pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2];
+ //hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));
+ if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT)))
+ {
+ pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT));
+ }
+ //hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));
+
+ pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (INFRA_ON(pAd))
+ {
+ StaPublicAction(pAd, pCoexistInfo);
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ }
+ break;
+ }
+
+#endif // DOT11N_DRAFT3 //
+
+}
+
+
+static VOID ReservedAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Category;
+
+ if (Elem->MsgLen <= LENGTH_802_11)
+ {
+ return;
+ }
+
+ Category = Elem->Msg[LENGTH_802_11];
+ DBGPRINT(RT_DEBUG_TRACE,("Rcv reserved category(%d) Action Frame\n", Category));
+ hex_dump("Reserved Action Frame", &Elem->Msg[0], Elem->MsgLen);
+}
+
+VOID PeerRMAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ return;
+}
+
+#ifdef DOT11_N_SUPPORT
+static VOID respond_ht_information_exchange_action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+ FRAME_HT_INFO HTINFOframe, *pFrame;
+ UCHAR *pAddr;
+
+
+ // 2. Always send back ADDBA Response
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - respond_ht_information_exchange_action() allocate memory failed \n"));
+ return;
+ }
+
+ // get RA
+ pFrame = (FRAME_HT_INFO *) &Elem->Msg[0];
+ pAddr = pFrame->Hdr.Addr2;
+
+ NdisZeroMemory(&HTINFOframe, sizeof(FRAME_HT_INFO));
+ // 2-1. Prepare ADDBA Response frame.
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (ADHOC_ON(pAd))
+ ActHeaderInit(pAd, &HTINFOframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ else
+ ActHeaderInit(pAd, &HTINFOframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ HTINFOframe.Category = CATEGORY_HT;
+ HTINFOframe.Action = HT_INFO_EXCHANGE;
+ HTINFOframe.HT_Info.Request = 0;
+ HTINFOframe.HT_Info.Forty_MHz_Intolerant = pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant;
+ HTINFOframe.HT_Info.STA_Channel_Width = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_HT_INFO), &HTINFOframe,
+ END_OF_ARGS);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+
+#ifdef DOT11N_DRAFT3
+VOID SendNotifyBWActionFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR apidx)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ FRAME_ACTION_HDR Frame;
+ ULONG FrameLen;
+ PUCHAR pAddr1;
+
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n"));
+ return;
+ }
+
+ if (Wcid == MCAST_WCID)
+ pAddr1 = &BROADCAST_ADDR[0];
+ else
+ pAddr1 = pAd->MacTab.Content[Wcid].Addr;
+ ActHeaderInit(pAd, &Frame.Hdr, pAddr1, pAd->ApCfg.MBSSID[apidx].Bssid, pAd->ApCfg.MBSSID[apidx].Bssid);
+
+ Frame.Category = CATEGORY_HT;
+ Frame.Action = NOTIFY_BW_ACTION;
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ACTION_HDR), &Frame,
+ END_OF_ARGS);
+
+ *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth;
+ FrameLen++;
+
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth));
+
+}
+#endif // DOT11N_DRAFT3 //
+
+
+VOID PeerHTAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+
+ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return;
+
+ switch(Action)
+ {
+ case NOTIFY_BW_ACTION:
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Notify Channel bandwidth action----> \n"));
+#ifdef CONFIG_STA_SUPPORT
+ if(pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
+ {
+ // Note, this is to patch DIR-1353 AP. When the AP set to Wep, it will use legacy mode. But AP still keeps
+ // sending BW_Notify Action frame, and cause us to linkup and linkdown.
+ // In legacy mode, don't need to parse HT action frame.
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION -Ignore HT Notify Channel BW when link as legacy mode. BW = %d---> \n",
+ Elem->Msg[LENGTH_802_11+2] ));
+ break;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ if (Elem->Msg[LENGTH_802_11+2] == 0) // 7.4.8.2. if value is 1, keep the same as supported channel bandwidth.
+ pAd->MacTab.Content[Elem->Wcid].HTPhyMode.field.BW = 0;
+
+ break;
+ case SMPS_ACTION:
+ // 7.3.1.25
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n"));
+ if (((Elem->Msg[LENGTH_802_11+2]&0x1) == 0))
+ {
+ pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_ENABLE;
+ }
+ else if (((Elem->Msg[LENGTH_802_11+2]&0x2) == 0))
+ {
+ pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_STATIC;
+ }
+ else
+ {
+ pAd->MacTab.Content[Elem->Wcid].MmpsMode = MMPS_DYNAMIC;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("Aid(%d) MIMO PS = %d\n", Elem->Wcid, pAd->MacTab.Content[Elem->Wcid].MmpsMode));
+ // rt2860c : add something for smps change.
+ break;
+
+ case SETPCO_ACTION:
+ break;
+ case MIMO_CHA_MEASURE_ACTION:
+ break;
+ case HT_INFO_EXCHANGE:
+ {
+ HT_INFORMATION_OCTET *pHT_info;
+
+ pHT_info = (HT_INFORMATION_OCTET *) &Elem->Msg[LENGTH_802_11+2];
+ // 7.4.8.10
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - HT Information Exchange action----> \n"));
+ if (pHT_info->Request)
+ {
+ respond_ht_information_exchange_action(pAd, Elem);
+ }
+ }
+ break;
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Retry sending ADDBA Reqest.
+
+ IRQL = DISPATCH_LEVEL
+
+ Parametrs:
+ p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+ Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+ FALSE , then continue indicaterx at this moment.
+ ==========================================================================
+ */
+VOID ORIBATimerTimeout(
+ IN PRTMP_ADAPTER pAd)
+{
+ MAC_TABLE_ENTRY *pEntry;
+ INT i, total;
+ UCHAR TID;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+ total = pAd->MacTab.Size * NUM_OF_TID;
+
+ for (i = 1; ((i <MAX_LEN_OF_BA_ORI_TABLE) && (total > 0)) ; i++)
+ {
+ if (pAd->BATable.BAOriEntry[i].ORI_BA_Status == Originator_Done)
+ {
+ pEntry = &pAd->MacTab.Content[pAd->BATable.BAOriEntry[i].Wcid];
+ TID = pAd->BATable.BAOriEntry[i].TID;
+
+ ASSERT(pAd->BATable.BAOriEntry[i].Wcid < MAX_LEN_OF_MAC_TABLE);
+ }
+ total --;
+ }
+}
+
+
+VOID SendRefreshBAR(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ FRAME_BAR FrameBar;
+ ULONG FrameLen;
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ USHORT Sequence;
+ UCHAR i, TID;
+ USHORT idx;
+ BA_ORI_ENTRY *pBAEntry;
+
+ for (i = 0; i <NUM_OF_TID; i++)
+ {
+ idx = pEntry->BAOriWcidArray[i];
+ if (idx == 0)
+ {
+ continue;
+ }
+ pBAEntry = &pAd->BATable.BAOriEntry[idx];
+
+ if (pBAEntry->ORI_BA_Status == Originator_Done)
+ {
+ TID = pBAEntry->TID;
+
+ ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE);
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
+ return;
+ }
+
+ Sequence = pEntry->TxSeq[TID];
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+
+ FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
+ FrameBar.StartingSeq.field.StartSeq = Sequence; // make sure sequence not clear in DEL funciton.
+ FrameBar.BarControl.TID = TID; // make sure sequence not clear in DEL funciton.
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_BAR), &FrameBar,
+ END_OF_ARGS);
+ if (1) // Now we always send BAR.
+ {
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ }
+ MlmeFreeMemory(pAd, pOutBuffer);
+ }
+ }
+}
+#endif // DOT11_N_SUPPORT //
+
+VOID ActHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN PUCHAR Addr1,
+ IN PUCHAR Addr2,
+ IN PUCHAR Addr3)
+{
+ NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+ pHdr80211->FC.Type = BTYPE_MGMT;
+ pHdr80211->FC.SubType = SUBTYPE_ACTION;
+
+ COPY_MAC_ADDR(pHdr80211->Addr1, Addr1);
+ COPY_MAC_ADDR(pHdr80211->Addr2, Addr2);
+ COPY_MAC_ADDR(pHdr80211->Addr3, Addr3);
+}
+
+VOID BarHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PFRAME_BAR pCntlBar,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA)
+{
+ NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR));
+ pCntlBar->FC.Type = BTYPE_CNTL;
+ pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ;
+ pCntlBar->BarControl.MTID = 0;
+ pCntlBar->BarControl.Compressed = 1;
+ pCntlBar->BarControl.ACKPolicy = 0;
+
+
+ pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA));
+
+ COPY_MAC_ADDR(pCntlBar->Addr1, pDA);
+ COPY_MAC_ADDR(pCntlBar->Addr2, pSA);
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Insert Category and action code into the action frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. category code of the frame.
+ 4. action code of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID InsertActField(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN UINT8 Category,
+ IN UINT8 ActCode)
+{
+ ULONG TempLen;
+
+ MakeOutgoingFrame( pFrameBuf, &TempLen,
+ 1, &Category,
+ 1, &ActCode,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+ return;
+}
diff --git a/drivers/staging/rt2860/common/action.h b/drivers/staging/rt2860/common/action.h
new file mode 100644
index 000000000000..ce3877dce81b
--- /dev/null
+++ b/drivers/staging/rt2860/common/action.h
@@ -0,0 +1,68 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ aironet.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Paul Lin 04-06-15 Initial
+*/
+
+#ifndef __ACTION_H__
+#define __ACTION_H__
+
+typedef struct PACKED __HT_INFO_OCTET
+{
+#ifdef RT_BIG_ENDIAN
+ UCHAR Reserved:5;
+ UCHAR STA_Channel_Width:1;
+ UCHAR Forty_MHz_Intolerant:1;
+ UCHAR Request:1;
+#else
+ UCHAR Request:1;
+ UCHAR Forty_MHz_Intolerant:1;
+ UCHAR STA_Channel_Width:1;
+ UCHAR Reserved:5;
+#endif
+} HT_INFORMATION_OCTET;
+
+
+typedef struct PACKED __FRAME_HT_INFO
+{
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+ HT_INFORMATION_OCTET HT_Info;
+} FRAME_HT_INFO, *PFRAME_HT_INFO;
+
+#endif /* __ACTION_H__ */
+
+
diff --git a/drivers/staging/rt2860/common/ba_action.c b/drivers/staging/rt2860/common/ba_action.c
new file mode 100644
index 000000000000..591d1e2158da
--- /dev/null
+++ b/drivers/staging/rt2860/common/ba_action.c
@@ -0,0 +1,1802 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#ifdef DOT11_N_SUPPORT
+
+#include "../rt_config.h"
+
+
+
+#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
+
+#define ORI_SESSION_MAX_RETRY 8
+#define ORI_BA_SESSION_TIMEOUT (2000) // ms
+#define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
+
+#define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
+#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms
+
+#define RESET_RCV_SEQ (0xFFFF)
+
+static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
+
+
+BA_ORI_ENTRY *BATableAllocOriEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx);
+
+BA_REC_ENTRY *BATableAllocRecEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx);
+
+VOID BAOriSessionSetupTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID BARecSessionIdleTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+
+BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
+BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
+
+#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
+ Announce_Reordering_Packet(_pAd, _mpdu_blk);
+
+VOID BA_MaxWinSizeReasign(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntryPeer,
+ OUT UCHAR *pWinSize)
+{
+ UCHAR MaxSize;
+
+
+ if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3
+ {
+ if (pAd->MACVersion >= RALINK_3070_VERSION)
+ {
+ if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
+ MaxSize = 7; // for non-open mode
+ else
+ MaxSize = 13;
+ }
+ else
+ MaxSize = 31;
+ }
+ else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
+ {
+ if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
+ MaxSize = 7; // for non-open mode
+ else
+ MaxSize = 13;
+ }
+ else
+ MaxSize = 7;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
+ *pWinSize, MaxSize));
+
+ if ((*pWinSize) > MaxSize)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
+ *pWinSize, MaxSize));
+
+ *pWinSize = MaxSize;
+ }
+}
+
+void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd,
+ IN struct reordering_mpdu *mpdu)
+{
+ PNDIS_PACKET pPacket;
+
+ pPacket = mpdu->pPacket;
+
+ if (mpdu->bAMSDU)
+ {
+ ASSERT(0);
+ BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
+ }
+ else
+ {
+ //
+ // pass this 802.3 packet to upper layer or forward this packet to WM directly
+ //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
+#endif // CONFIG_STA_SUPPORT //
+ }
+}
+
+/*
+ * Insert a reordering mpdu into sorted linked list by sequence no.
+ */
+BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
+{
+
+ struct reordering_mpdu **ppScan = &list->next;
+
+ while (*ppScan != NULL)
+ {
+ if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
+ {
+ ppScan = &(*ppScan)->next;
+ }
+ else if ((*ppScan)->Sequence == mpdu->Sequence)
+ {
+ /* give up this duplicated frame */
+ return(FALSE);
+ }
+ else
+ {
+ /* find position */
+ break;
+ }
+ }
+
+ mpdu->next = *ppScan;
+ *ppScan = mpdu;
+ list->qlen++;
+ return TRUE;
+}
+
+
+/*
+ * caller lock critical section if necessary
+ */
+static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
+{
+ list->qlen++;
+ mpdu_blk->next = list->next;
+ list->next = mpdu_blk;
+}
+
+/*
+ * caller lock critical section if necessary
+ */
+static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
+{
+ struct reordering_mpdu *mpdu_blk = NULL;
+
+ ASSERT(list);
+
+ if (list->qlen)
+ {
+ list->qlen--;
+ mpdu_blk = list->next;
+ if (mpdu_blk)
+ {
+ list->next = mpdu_blk->next;
+ mpdu_blk->next = NULL;
+ }
+ }
+ return mpdu_blk;
+}
+
+
+static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
+{
+ return(ba_dequeue(list));
+}
+
+
+static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
+ {
+ ASSERT(list);
+
+ return(list->next);
+ }
+
+
+/*
+ * free all resource for reordering mechanism
+ */
+void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
+{
+ BA_TABLE *Tab;
+ PBA_REC_ENTRY pBAEntry;
+ struct reordering_mpdu *mpdu_blk;
+ int i;
+
+ Tab = &pAd->BATable;
+
+ /* I. release all pending reordering packet */
+ NdisAcquireSpinLock(&pAd->BATabLock);
+ for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ pBAEntry = &Tab->BARecEntry[i];
+ if (pBAEntry->REC_BA_Status != Recipient_NONE)
+ {
+ while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
+ {
+ ASSERT(mpdu_blk->pPacket);
+ RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+ }
+ }
+ NdisReleaseSpinLock(&pAd->BATabLock);
+
+ ASSERT(pBAEntry->list.qlen == 0);
+ /* II. free memory of reordering mpdu table */
+ NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+ os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
+ NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+}
+
+
+
+/*
+ * Allocate all resource for reordering mechanism
+ */
+BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
+{
+ int i;
+ PUCHAR mem;
+ struct reordering_mpdu *mpdu_blk;
+ struct reordering_list *freelist;
+
+ /* allocate spinlock */
+ NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
+
+ /* initialize freelist */
+ freelist = &pAd->mpdu_blk_pool.freelist;
+ freelist->next = NULL;
+ freelist->qlen = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
+
+ /* allocate number of mpdu_blk memory */
+ os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
+
+ pAd->mpdu_blk_pool.mem = mem;
+
+ if (mem == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
+ return(FALSE);
+ }
+
+ /* build mpdu_blk free list */
+ for (i=0; i<num; i++)
+ {
+ /* get mpdu_blk */
+ mpdu_blk = (struct reordering_mpdu *) mem;
+ /* initial mpdu_blk */
+ NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
+ /* next mpdu_blk */
+ mem += sizeof(struct reordering_mpdu);
+ /* insert mpdu_blk into freelist */
+ ba_enqueue(freelist, mpdu_blk);
+ }
+
+ return(TRUE);
+}
+
+//static int blk_count=0; // sample take off, no use
+
+static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
+{
+ struct reordering_mpdu *mpdu_blk;
+
+ NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+ mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
+ if (mpdu_blk)
+ {
+// blk_count++;
+ /* reset mpdu_blk */
+ NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
+ }
+ NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+ return mpdu_blk;
+}
+
+static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
+{
+ ASSERT(mpdu_blk);
+
+ NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
+// blk_count--;
+ ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
+ NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
+}
+
+
+static USHORT ba_indicate_reordering_mpdus_in_order(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN USHORT StartSeq)
+{
+ struct reordering_mpdu *mpdu_blk;
+ USHORT LastIndSeq = RESET_RCV_SEQ;
+
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+ while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
+ {
+ /* find in-order frame */
+ if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
+ {
+ break;
+ }
+ /* dequeue in-order frame from reodering list */
+ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
+ /* pass this frame up */
+ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+ /* move to next sequence */
+ StartSeq = mpdu_blk->Sequence;
+ LastIndSeq = StartSeq;
+ /* free mpdu_blk */
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+
+ /* update last indicated sequence */
+ return LastIndSeq;
+}
+
+static void ba_indicate_reordering_mpdus_le_seq(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN USHORT Sequence)
+{
+ struct reordering_mpdu *mpdu_blk;
+
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+ while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
+ {
+ /* find in-order frame */
+ if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
+ {
+ /* dequeue in-order frame from reodering list */
+ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
+ /* pass this frame up */
+ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+ /* free mpdu_blk */
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+ else
+ {
+ break;
+ }
+ }
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+}
+
+
+static void ba_refresh_reordering_mpdus(
+ IN PRTMP_ADAPTER pAd,
+ PBA_REC_ENTRY pBAEntry)
+{
+ struct reordering_mpdu *mpdu_blk;
+
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+ /* dequeue in-order frame from reodering list */
+ while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
+ {
+ /* pass this frame up */
+ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
+
+ pBAEntry->LastIndSeq = mpdu_blk->Sequence;
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+
+ /* update last indicated sequence */
+ }
+ ASSERT(pBAEntry->list.qlen == 0);
+ pBAEntry->LastIndSeq = RESET_RCV_SEQ;
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+}
+
+
+//static
+void ba_flush_reordering_timeout_mpdus(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN ULONG Now32)
+
+{
+ USHORT Sequence;
+
+// if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
+// (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
+// (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
+// (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
+ if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6)))
+ &&(pBAEntry->list.qlen > 1)
+ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
+ (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
+ pBAEntry->LastIndSeq));
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ }
+ else
+ if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
+ && (pBAEntry->list.qlen > 0)
+ )
+ {
+// printk("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
+// (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT,
+// pBAEntry->LastIndSeq);
+ //
+ // force LastIndSeq to shift to LastIndSeq+1
+ //
+ Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ pBAEntry->LastIndSeq = Sequence;
+ //
+ // indicate in-order mpdus
+ //
+ Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
+ if (Sequence != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = Sequence;
+ }
+
+ //printk("%x, flush one!\n", pBAEntry->LastIndSeq);
+
+ }
+#if 0
+ else if (
+ (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT))) &&
+ (pBAEntry->list.qlen > 1))
+ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%lx-%lx = %d > %d): %x\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
+ (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
+ pBAEntry->LastIndSeq));
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ }
+#endif
+}
+
+
+/*
+ * generate ADDBA request to
+ * set up BA agreement
+ */
+VOID BAOriSessionSetUp(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN UCHAR TID,
+ IN USHORT TimeOut,
+ IN ULONG DelayTime,
+ IN BOOLEAN isForced)
+
+{
+ //MLME_ADDBA_REQ_STRUCT AddbaReq;
+ BA_ORI_ENTRY *pBAEntry = NULL;
+ USHORT Idx;
+ BOOLEAN Cancelled;
+
+ if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
+ return;
+
+ // if this entry is limited to use legacy tx mode, it doesn't generate BA.
+ if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
+ return;
+
+ if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
+ {
+ // try again after 3 secs
+ DelayTime = 3000;
+// printk("DeCline BA from Peer\n");
+// return;
+ }
+
+
+ Idx = pEntry->BAOriWcidArray[TID];
+ if (Idx == 0)
+ {
+ // allocate a BA session
+ pBAEntry = BATableAllocOriEntry(pAd, &Idx);
+ if (pBAEntry == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
+ return;
+ }
+ }
+ else
+ {
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+ }
+
+ if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
+ {
+ return;
+ }
+
+ pEntry->BAOriWcidArray[TID] = Idx;
+
+ // Initialize BA session
+ pBAEntry->ORI_BA_Status = Originator_WaitRes;
+ pBAEntry->Wcid = pEntry->Aid;
+ pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
+ pBAEntry->Sequence = BA_ORI_INIT_SEQ;
+ pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
+ pBAEntry->TID = TID;
+ pBAEntry->TimeOutValue = TimeOut;
+ pBAEntry->pAdapter = pAd;
+
+ if (!(pEntry->TXBAbitmap & (1<<TID)))
+ {
+ RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
+ }
+ else
+ RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+
+ // set timer to send ADDBA request
+ RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
+}
+
+VOID BAOriSessionAdd(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PFRAME_ADDBA_RSP pFrame)
+{
+ BA_ORI_ENTRY *pBAEntry = NULL;
+ BOOLEAN Cancelled;
+ UCHAR TID;
+ USHORT Idx;
+ PUCHAR pOutBuffer2 = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+ FRAME_BAR FrameBar;
+
+ TID = pFrame->BaParm.TID;
+ Idx = pEntry->BAOriWcidArray[TID];
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+
+ // Start fill in parameters.
+ if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
+ {
+ pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
+ BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
+
+ pBAEntry->TimeOutValue = pFrame->TimeOutValue;
+ pBAEntry->ORI_BA_Status = Originator_Done;
+ // reset sequence number
+ pBAEntry->Sequence = BA_ORI_INIT_SEQ;
+ // Set Bitmap flag.
+ pEntry->TXBAbitmap |= (1<<TID);
+ RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+
+ pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __func__, pEntry->TXBAbitmap,
+ pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
+
+ // SEND BAR ;
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
+ return;
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+
+ FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
+ FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton.
+ FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton.
+ MakeOutgoingFrame(pOutBuffer2, &FrameLen,
+ sizeof(FRAME_BAR), &FrameBar,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer2);
+
+
+ if (pBAEntry->ORIBATimer.TimerValue)
+ RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
+ }
+}
+
+BOOLEAN BARecSessionAdd(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PFRAME_ADDBA_REQ pFrame)
+{
+ BA_REC_ENTRY *pBAEntry = NULL;
+ BOOLEAN Status = TRUE;
+ BOOLEAN Cancelled;
+ USHORT Idx;
+ UCHAR TID;
+ UCHAR BAWinSize;
+ //UINT32 Value;
+ //UINT offset;
+
+
+ ASSERT(pEntry);
+
+ // find TID
+ TID = pFrame->BaParm.TID;
+
+ BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+
+ // Intel patch
+ if (BAWinSize == 0)
+ {
+ BAWinSize = 64;
+ }
+
+ Idx = pEntry->BARecWcidArray[TID];
+
+
+ if (Idx == 0)
+ {
+ pBAEntry = BATableAllocRecEntry(pAd, &Idx);
+ }
+ else
+ {
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ // flush all pending reordering mpdus
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, pAd->BATable.numAsRecipient, Idx,
+ pFrame->BaParm.BufSize, BAWinSize));
+
+ // Start fill in parameters.
+ if (pBAEntry != NULL)
+ {
+ ASSERT(pBAEntry->list.qlen == 0);
+
+ pBAEntry->REC_BA_Status = Recipient_HandleRes;
+ pBAEntry->BAWinSize = BAWinSize;
+ pBAEntry->Wcid = pEntry->Aid;
+ pBAEntry->TID = TID;
+ pBAEntry->TimeOutValue = pFrame->TimeOutValue;
+ pBAEntry->REC_BA_Status = Recipient_Accept;
+ // initial sequence number
+ pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq;
+
+ printk("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq);
+
+ if (pEntry->RXBAbitmap & (1<<TID))
+ {
+ RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
+ }
+ else
+ {
+ RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
+ }
+
+#if 0 // for debugging
+ RTMPSetTimer(&pBAEntry->RECBATimer, REC_BA_SESSION_IDLE_TIMEOUT);
+#endif
+
+ // Set Bitmap flag.
+ pEntry->RXBAbitmap |= (1<<TID);
+ pEntry->BARecWcidArray[TID] = Idx;
+
+ pEntry->BADeclineBitmap &= ~(1<<TID);
+
+ // Set BA session mask in WCID table.
+ RT28XX_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
+
+ DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
+ pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
+ }
+ else
+ {
+ Status = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
+ PRINT_MAC(pEntry->Addr), TID));
+ }
+ return(Status);
+}
+
+
+BA_REC_ENTRY *BATableAllocRecEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx)
+{
+ int i;
+ BA_REC_ENTRY *pBAEntry = NULL;
+
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
+ {
+ printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient,
+ MAX_BARECI_SESSION);
+ goto done;
+ }
+
+ // reserve idx 0 to identify BAWcidArray[TID] as empty
+ for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ pBAEntry =&pAd->BATable.BARecEntry[i];
+ if ((pBAEntry->REC_BA_Status == Recipient_NONE))
+ {
+ // get one
+ pAd->BATable.numAsRecipient++;
+ pBAEntry->REC_BA_Status = Recipient_USED;
+ *Idx = i;
+ break;
+ }
+ }
+
+done:
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ return pBAEntry;
+}
+
+BA_ORI_ENTRY *BATableAllocOriEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Idx)
+{
+ int i;
+ BA_ORI_ENTRY *pBAEntry = NULL;
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
+ {
+ goto done;
+ }
+
+ // reserve idx 0 to identify BAWcidArray[TID] as empty
+ for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
+ {
+ pBAEntry =&pAd->BATable.BAOriEntry[i];
+ if ((pBAEntry->ORI_BA_Status == Originator_NONE))
+ {
+ // get one
+ pAd->BATable.numAsOriginator++;
+ pBAEntry->ORI_BA_Status = Originator_USED;
+ pBAEntry->pAdapter = pAd;
+ *Idx = i;
+ break;
+ }
+ }
+
+done:
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ return pBAEntry;
+}
+
+
+VOID BATableFreeOriEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Idx)
+{
+ BA_ORI_ENTRY *pBAEntry = NULL;
+ MAC_TABLE_ENTRY *pEntry;
+
+
+ if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
+ return;
+
+ pBAEntry =&pAd->BATable.BAOriEntry[Idx];
+
+ if (pBAEntry->ORI_BA_Status != Originator_NONE)
+ {
+ pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+ pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
+
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+ if (pBAEntry->ORI_BA_Status == Originator_Done)
+ {
+ pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
+ DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
+ // Erase Bitmap flag.
+ }
+
+ ASSERT(pAd->BATable.numAsOriginator != 0);
+
+ pAd->BATable.numAsOriginator -= 1;
+
+ pBAEntry->ORI_BA_Status = Originator_NONE;
+ pBAEntry->Token = 0;
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ }
+}
+
+
+VOID BATableFreeRecEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Idx)
+{
+ BA_REC_ENTRY *pBAEntry = NULL;
+ MAC_TABLE_ENTRY *pEntry;
+
+
+ if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
+ return;
+
+ pBAEntry =&pAd->BATable.BARecEntry[Idx];
+
+ if (pBAEntry->REC_BA_Status != Recipient_NONE)
+ {
+ pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+ pEntry->BARecWcidArray[pBAEntry->TID] = 0;
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ ASSERT(pAd->BATable.numAsRecipient != 0);
+
+ pAd->BATable.numAsRecipient -= 1;
+
+ pBAEntry->REC_BA_Status = Recipient_NONE;
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ }
+}
+
+
+VOID BAOriSessionTearDown(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR TID,
+ IN BOOLEAN bPassive,
+ IN BOOLEAN bForceSend)
+{
+ ULONG Idx = 0;
+ BA_ORI_ENTRY *pBAEntry;
+ BOOLEAN Cancelled;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ {
+ return;
+ }
+
+ //
+ // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
+ //
+ Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
+ if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
+ {
+ if (bForceSend == TRUE)
+ {
+ // force send specified TID DelBA
+ MLME_DELBA_REQ_STRUCT DelbaReq;
+ MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+ NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+ NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+ COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+ DelbaReq.Wcid = Wcid;
+ DelbaReq.TID = TID;
+ DelbaReq.Initiator = ORIGINATOR;
+#if 1
+ Elem->MsgLen = sizeof(DelbaReq);
+ NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+ MlmeDELBAAction(pAd, Elem);
+ kfree(Elem);
+#else
+ MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
+ RT28XX_MLME_HANDLER(pAd);
+#endif
+ }
+
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
+
+ pBAEntry = &pAd->BATable.BAOriEntry[Idx];
+ DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
+ //
+ // Prepare DelBA action frame and send to the peer.
+ //
+ if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
+ {
+ MLME_DELBA_REQ_STRUCT DelbaReq;
+ MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+ NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+ NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+ COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+ DelbaReq.Wcid = Wcid;
+ DelbaReq.TID = pBAEntry->TID;
+ DelbaReq.Initiator = ORIGINATOR;
+#if 1
+ Elem->MsgLen = sizeof(DelbaReq);
+ NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+ MlmeDELBAAction(pAd, Elem);
+ kfree(Elem);
+#else
+ MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
+ RT28XX_MLME_HANDLER(pAd);
+#endif
+ }
+ RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
+ BATableFreeOriEntry(pAd, Idx);
+
+ if (bPassive)
+ {
+ //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
+ }
+}
+
+VOID BARecSessionTearDown(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR TID,
+ IN BOOLEAN bPassive)
+{
+ ULONG Idx = 0;
+ BA_REC_ENTRY *pBAEntry;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ {
+ return;
+ }
+
+ //
+ // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
+ //
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ if (Idx == 0)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
+
+
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
+ //
+ // Prepare DelBA action frame and send to the peer.
+ //
+ if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
+ {
+ MLME_DELBA_REQ_STRUCT DelbaReq;
+ BOOLEAN Cancelled;
+ MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+ //ULONG offset;
+ //UINT32 VALUE;
+
+ RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
+
+ //
+ // 1. Send DELBA Action Frame
+ //
+ if (bPassive == FALSE)
+ {
+ NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
+ NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
+
+ COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
+ DelbaReq.Wcid = Wcid;
+ DelbaReq.TID = TID;
+ DelbaReq.Initiator = RECIPIENT;
+#if 1
+ Elem->MsgLen = sizeof(DelbaReq);
+ NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
+ MlmeDELBAAction(pAd, Elem);
+ kfree(Elem);
+#else
+ MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
+ RT28XX_MLME_HANDLER(pAd);
+#endif
+ }
+
+
+ //
+ // 2. Free resource of BA session
+ //
+ // flush all pending reordering mpdus
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+
+ NdisAcquireSpinLock(&pAd->BATabLock);
+
+ // Erase Bitmap flag.
+ pBAEntry->LastIndSeq = RESET_RCV_SEQ;
+ pBAEntry->BAWinSize = 0;
+ // Erase Bitmap flag at software mactable
+ pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
+ pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
+
+ RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
+
+ NdisReleaseSpinLock(&pAd->BATabLock);
+
+ }
+
+ BATableFreeRecEntry(pAd, Idx);
+}
+
+VOID BASessionTearDownALL(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid)
+{
+ int i;
+
+ for (i=0; i<NUM_OF_TID; i++)
+ {
+ BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
+ BARecSessionTearDown(pAd, Wcid, i, FALSE);
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Retry sending ADDBA Reqest.
+
+ IRQL = DISPATCH_LEVEL
+
+ Parametrs:
+ p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+ Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+ FALSE , then continue indicaterx at this moment.
+ ==========================================================================
+ */
+VOID BAOriSessionSetupTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
+ MAC_TABLE_ENTRY *pEntry;
+ PRTMP_ADAPTER pAd;
+
+ if (pBAEntry == NULL)
+ return;
+
+ pAd = pBAEntry->pAdapter;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Do nothing if monitor mode is on
+ if (MONITOR_ON(pAd))
+ return;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RALINK_ATE
+ // Nothing to do in ATE mode.
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+ pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
+
+ if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
+ {
+ MLME_ADDBA_REQ_STRUCT AddbaReq;
+
+ NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
+ COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
+ AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
+ AddbaReq.TID = pBAEntry->TID;
+ AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
+ AddbaReq.TimeOutValue = 0;
+ AddbaReq.Token = pBAEntry->Token;
+ MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
+ RT28XX_MLME_HANDLER(pAd);
+ DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
+
+ pBAEntry->Token++;
+ RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
+ }
+ else
+ {
+ BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ Retry sending ADDBA Reqest.
+
+ IRQL = DISPATCH_LEVEL
+
+ Parametrs:
+ p8023Header: if this is already 802.3 format, p8023Header is NULL
+
+ Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
+ FALSE , then continue indicaterx at this moment.
+ ==========================================================================
+ */
+VOID BARecSessionIdleTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+
+ BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
+ PRTMP_ADAPTER pAd;
+ ULONG Now32;
+
+ if (pBAEntry == NULL)
+ return;
+
+ if ((pBAEntry->REC_BA_Status == Recipient_Accept))
+ {
+ NdisGetSystemUpTime(&Now32);
+
+ if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
+ {
+ pAd = pBAEntry->pAdapter;
+ // flush all pending reordering mpdus
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ printk("%ld: REC BA session Timeout\n", Now32);
+ }
+ }
+}
+
+
+VOID PeerAddBAReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ // 7.4.4.1
+ //ULONG Idx;
+ UCHAR Status = 1;
+ UCHAR pAddr[6];
+ FRAME_ADDBA_RSP ADDframe;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ PFRAME_ADDBA_REQ pAddreqFrame = NULL;
+ //UCHAR BufSize;
+ ULONG FrameLen;
+ PULONG ptemp;
+ PMAC_TABLE_ENTRY pMacEntry;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid));
+
+ //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
+
+ //ADDBA Request from unknown peer, ignore this.
+ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return;
+
+ pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
+ DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
+ ptemp = (PULONG)Elem->Msg;
+ //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8)));
+
+ if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
+ {
+
+ if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
+ {
+ pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
+ printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid);
+ if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
+ Status = 0;
+ else
+ Status = 38; // more parameters have invalid values
+ }
+ else
+ {
+ Status = 37; // the request has been declined.
+ }
+ }
+
+ if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
+ ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
+
+ pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
+ // 2. Always send back ADDBA Response
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
+ return;
+ }
+
+ NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
+ // 2-1. Prepare ADDBA Response frame.
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (ADHOC_ON(pAd))
+ ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ else
+#ifdef QOS_DLS_SUPPORT
+ if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls)
+ ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ else
+#endif // QOS_DLS_SUPPORT //
+ ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ ADDframe.Category = CATEGORY_BA;
+ ADDframe.Action = ADDBA_RESP;
+ ADDframe.Token = pAddreqFrame->Token;
+ // What is the Status code?? need to check.
+ ADDframe.StatusCode = Status;
+ ADDframe.BaParm.BAPolicy = IMMED_BA;
+ ADDframe.BaParm.AMSDUSupported = 0;
+ ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
+ ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+ if (ADDframe.BaParm.BufSize == 0)
+ {
+ ADDframe.BaParm.BufSize = 64;
+ }
+ ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
+
+ *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
+ ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
+ ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_ADDBA_RSP), &ADDframe,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, ADDframe.BaParm.TID,
+ ADDframe.BaParm.BufSize));
+}
+
+
+VOID PeerAddBARspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ //UCHAR Idx, i;
+ //PUCHAR pOutBuffer = NULL;
+ PFRAME_ADDBA_RSP pFrame = NULL;
+ //PBA_ORI_ENTRY pBAEntry;
+
+ //ADDBA Response from unknown peer, ignore this.
+ if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid));
+
+ //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
+
+ if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
+ {
+ pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
+ switch (pFrame->StatusCode)
+ {
+ case 0:
+ // I want a BAsession with this peer as an originator.
+ BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
+ break;
+ default:
+ // check status == USED ???
+ BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
+ break;
+ }
+ // Rcv Decline StatusCode
+ if ((pFrame->StatusCode == 37)
+#ifdef CONFIG_STA_SUPPORT
+ || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
+#endif // CONFIG_STA_SUPPORT //
+ )
+ {
+ pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
+ }
+ }
+}
+
+VOID PeerDelBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+
+{
+ //UCHAR Idx;
+ //PUCHAR pOutBuffer = NULL;
+ PFRAME_DELBA_REQ pDelFrame = NULL;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __func__));
+ //DELBA Request from unknown peer, ignore this.
+ if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
+ {
+ pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
+ if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
+ BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
+ //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
+ BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
+ }
+ }
+}
+
+
+BOOLEAN CntlEnqueueForRecv(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN ULONG MsgLen,
+ IN PFRAME_BA_REQ pMsg)
+{
+ PFRAME_BA_REQ pFrame = pMsg;
+ //PRTMP_REORDERBUF pBuffer;
+ //PRTMP_REORDERBUF pDmaBuf;
+ PBA_REC_ENTRY pBAEntry;
+ //BOOLEAN Result;
+ ULONG Idx;
+ //UCHAR NumRxPkt;
+ UCHAR TID;//, i;
+
+ TID = (UCHAR)pFrame->BARControl.TID;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID));
+ //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return FALSE;
+
+ // First check the size, it MUST not exceed the mlme queue size
+ if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+ {
+ DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
+ return FALSE;
+ }
+ else if (MsgLen != sizeof(FRAME_BA_REQ))
+ {
+ DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+ else if (MsgLen != sizeof(FRAME_BA_REQ))
+ {
+ DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+
+ if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
+ {
+ // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ }
+ else
+ {
+ return FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
+
+ if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
+ {
+ //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq);
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
+ pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
+ }
+ //ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ return TRUE;
+}
+
+/*
+Description : Send PSMP Action frame If PSMP mode switches.
+*/
+VOID SendPSMPAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR Psmp)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ //ULONG Idx;
+ FRAME_PSMP_ACTION Frame;
+ ULONG FrameLen;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
+ return;
+ }
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
+#endif // CONFIG_STA_SUPPORT //
+
+ Frame.Category = CATEGORY_HT;
+ Frame.Action = SMPS_ACTION;
+ switch (Psmp)
+ {
+ case MMPS_ENABLE:
+ Frame.Psmp = 0;
+ break;
+ case MMPS_DYNAMIC:
+ Frame.Psmp = 3;
+ break;
+ case MMPS_STATIC:
+ Frame.Psmp = 1;
+ break;
+ }
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(FRAME_PSMP_ACTION), &Frame,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
+}
+
+
+#define RADIO_MEASUREMENT_REQUEST_ACTION 0
+
+typedef struct PACKED
+{
+ UCHAR RegulatoryClass;
+ UCHAR ChannelNumber;
+ USHORT RandomInterval;
+ USHORT MeasurementDuration;
+ UCHAR MeasurementMode;
+ UCHAR BSSID[MAC_ADDR_LEN];
+ UCHAR ReportingCondition;
+ UCHAR Threshold;
+ UCHAR SSIDIE[2]; // 2 byte
+} BEACON_REQUEST;
+
+typedef struct PACKED
+{
+ UCHAR ID;
+ UCHAR Length;
+ UCHAR Token;
+ UCHAR RequestMode;
+ UCHAR Type;
+} MEASUREMENT_REQ;
+
+
+
+
+void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ PNDIS_PACKET pRxPkt;
+ UCHAR Header802_3[LENGTH_802_3];
+
+ // 1. get 802.3 Header
+ // 2. remove LLC
+ // a. pointer pRxBlk->pData to payload
+ // b. modify pRxBlk->DataSize
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif // CONFIG_STA_SUPPORT //
+
+ ASSERT(pRxBlk->pRxPacket);
+ pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+
+ RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+ RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData;
+ RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize;
+ RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len;
+
+ //
+ // copy 802.3 header, if necessary
+ //
+ if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef LINUX
+ NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
+#endif
+#ifdef UCOS
+ NdisMoveMemory(net_pkt_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
+#endif
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+}
+
+
+#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
+ do \
+ { \
+ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
+ { \
+ Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
+ { \
+ Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ else \
+ { \
+ Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
+ } \
+ } while (0);
+
+
+
+static VOID ba_enqueue_reordering_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ struct reordering_mpdu *mpdu_blk;
+ UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
+
+ mpdu_blk = ba_mpdu_blk_alloc(pAd);
+ if (mpdu_blk != NULL)
+ {
+ // Write RxD buffer address & allocated buffer length
+ NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
+
+ mpdu_blk->Sequence = Sequence;
+
+ mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
+
+ convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
+
+ STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+ //
+ // it is necessary for reordering packet to record
+ // which BSS it come from
+ //
+ RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+
+ mpdu_blk->pPacket = pRxBlk->pRxPacket;
+
+ if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
+ {
+ // had been already within reordering list
+ // don't indicate
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
+ ba_mpdu_blk_free(pAd, mpdu_blk);
+ }
+
+ ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
+ NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
+ }
+ else
+ {
+#if 0
+ DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
+ blk_count, pBAEntry->list.qlen));
+#else
+ DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
+ pBAEntry->list.qlen));
+#endif
+ /*
+ * flush all pending reordering mpdus
+ * and receving mpdu to upper layer
+ * make tcp/ip to take care reordering mechanism
+ */
+ //ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
+
+ pBAEntry->LastIndSeq = Sequence;
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Indicate this packet to upper layer or put it into reordering buffer
+
+ Parametrs:
+ pRxBlk : carry necessary packet info 802.11 format
+ FromWhichBSSID : the packet received from which BSS
+
+ Return :
+ none
+
+ Note :
+ the packet queued into reordering buffer need to cover to 802.3 format
+ or pre_AMSDU format
+ ==========================================================================
+ */
+
+VOID Indicate_AMPDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ USHORT Idx;
+ PBA_REC_ENTRY pBAEntry = NULL;
+ UINT16 Sequence = pRxBlk->pHeader->Sequence;
+ ULONG Now32;
+ UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
+ UCHAR TID = pRxBlk->pRxWI->TID;
+
+
+ if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
+ {
+#if 0 // sample take off, no use
+ static int err_size;
+
+ err_size++;
+ if (err_size > 20) {
+ printk("AMPDU DataSize = %d\n", pRxBlk->DataSize);
+ hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24);
+ hex_dump("Payload", pRxBlk->pData, 64);
+ err_size = 0;
+ }
+#endif
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+
+#if 0 // test
+ /* Rec BA Session had been torn down */
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ return;
+#endif
+
+ if (Wcid < MAX_LEN_OF_MAC_TABLE)
+ {
+ Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
+ if (Idx == 0)
+ {
+ /* Rec BA Session had been torn down */
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+ pBAEntry = &pAd->BATable.BARecEntry[Idx];
+ }
+ else
+ {
+ // impossible !!!
+ ASSERT(0);
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ ASSERT(pBAEntry);
+
+ // update last rx time
+ NdisGetSystemUpTime(&Now32);
+
+ pBAEntry->rcvSeq = Sequence;
+
+
+ ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
+ pBAEntry->LastIndSeqAtTimer = Now32;
+
+ //
+ // Reset Last Indicate Sequence
+ //
+ if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
+ {
+ ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
+
+ // reset rcv sequence of BA session
+ pBAEntry->LastIndSeq = Sequence;
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+
+
+ //
+ // I. Check if in order.
+ //
+ if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+ {
+ USHORT LastIndSeq;
+
+ pBAEntry->LastIndSeq = Sequence;
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+ LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+ if (LastIndSeq != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = LastIndSeq;
+ }
+ pBAEntry->LastIndSeqAtTimer = Now32;
+ }
+ //
+ // II. Drop Duplicated Packet
+ //
+ else if (Sequence == pBAEntry->LastIndSeq)
+ {
+
+ // drop and release packet
+ pBAEntry->nDropPacket++;
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ }
+ //
+ // III. Drop Old Received Packet
+ //
+ else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
+ {
+
+ // drop and release packet
+ pBAEntry->nDropPacket++;
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ }
+ //
+ // IV. Receive Sequence within Window Size
+ //
+ else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
+ {
+ ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+ }
+ //
+ // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
+ //
+ else
+ {
+#if 0
+ ba_refresh_reordering_mpdus(pAd, pBAEntry);
+ INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
+#else
+ LONG WinStartSeq, TmpSeq;
+
+
+ TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
+ if (TmpSeq < 0)
+ {
+ TmpSeq = (MAXSEQ+1) + TmpSeq;
+ }
+ WinStartSeq = (TmpSeq+1) & MAXSEQ;
+ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
+ pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
+
+ pBAEntry->LastIndSeqAtTimer = Now32;
+
+ ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
+
+ TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
+ if (TmpSeq != RESET_RCV_SEQ)
+ {
+ pBAEntry->LastIndSeq = TmpSeq;
+ }
+#endif
+ }
+}
+
+#endif // DOT11_N_SUPPORT //
+
diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c
new file mode 100644
index 000000000000..b67b9eba7229
--- /dev/null
+++ b/drivers/staging/rt2860/common/cmm_data.c
@@ -0,0 +1,3466 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+*/
+
+#include "../rt_config.h"
+
+#define MAX_TX_IN_TBTT (16)
+
+
+UCHAR SNAP_802_1H[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+UCHAR SNAP_BRIDGE_TUNNEL[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
+// Add Cisco Aironet SNAP heade for CCX2 support
+UCHAR SNAP_AIRONET[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x00};
+UCHAR CKIP_LLC_SNAP[] = {0xaa, 0xaa, 0x03, 0x00, 0x40, 0x96, 0x00, 0x02};
+UCHAR EAPOL_LLC_SNAP[]= {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e};
+UCHAR EAPOL[] = {0x88, 0x8e};
+UCHAR TPID[] = {0x81, 0x00}; /* VLAN related */
+
+UCHAR IPX[] = {0x81, 0x37};
+UCHAR APPLE_TALK[] = {0x80, 0xf3};
+UCHAR RateIdToPlcpSignal[12] = {
+ 0, /* RATE_1 */ 1, /* RATE_2 */ 2, /* RATE_5_5 */ 3, /* RATE_11 */ // see BBP spec
+ 11, /* RATE_6 */ 15, /* RATE_9 */ 10, /* RATE_12 */ 14, /* RATE_18 */ // see IEEE802.11a-1999 p.14
+ 9, /* RATE_24 */ 13, /* RATE_36 */ 8, /* RATE_48 */ 12 /* RATE_54 */ }; // see IEEE802.11a-1999 p.14
+
+UCHAR OfdmSignalToRateId[16] = {
+ RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 0, 1, 2, 3 respectively
+ RATE_54, RATE_54, RATE_54, RATE_54, // OFDM PLCP Signal = 4, 5, 6, 7 respectively
+ RATE_48, RATE_24, RATE_12, RATE_6, // OFDM PLCP Signal = 8, 9, 10, 11 respectively
+ RATE_54, RATE_36, RATE_18, RATE_9, // OFDM PLCP Signal = 12, 13, 14, 15 respectively
+};
+
+UCHAR OfdmRateToRxwiMCS[12] = {
+ 0, 0, 0, 0,
+ 0, 1, 2, 3, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
+ 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
+};
+UCHAR RxwiMCSToOfdmRate[12] = {
+ RATE_6, RATE_9, RATE_12, RATE_18,
+ RATE_24, RATE_36, RATE_48, RATE_54, // OFDM rate 6,9,12,18 = rxwi mcs 0,1,2,3
+ 4, 5, 6, 7, // OFDM rate 24,36,48,54 = rxwi mcs 4,5,6,7
+};
+
+char* MCSToMbps[] = {"1Mbps","2Mbps","5.5Mbps","11Mbps","06Mbps","09Mbps","12Mbps","18Mbps","24Mbps","36Mbps","48Mbps","54Mbps","MM-0","MM-1","MM-2","MM-3","MM-4","MM-5","MM-6","MM-7","MM-8","MM-9","MM-10","MM-11","MM-12","MM-13","MM-14","MM-15","MM-32","ee1","ee2","ee3"};
+
+UCHAR default_cwmin[]={CW_MIN_IN_BITS, CW_MIN_IN_BITS, CW_MIN_IN_BITS-1, CW_MIN_IN_BITS-2};
+UCHAR default_sta_aifsn[]={3,7,2,2};
+
+UCHAR MapUserPriorityToAccessCategory[8] = {QID_AC_BE, QID_AC_BK, QID_AC_BK, QID_AC_BE, QID_AC_VI, QID_AC_VI, QID_AC_VO, QID_AC_VO};
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ API for MLME to transmit management frame to AP (BSS Mode)
+ or station (IBSS Mode)
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Pointer to the outgoing 802.11 frame
+ Length Size of outgoing management frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS MiniportMMRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PUCHAR pData,
+ IN UINT Length)
+{
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG FreeNum;
+#ifdef RT2860
+ unsigned long IrqFlags = 0;
+#endif // RT2860 //
+ UCHAR IrqState;
+ UCHAR rtmpHwHdr[TXINFO_SIZE + TXWI_SIZE]; //RTMP_HW_HDR_LEN];
+
+ ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
+
+ QueIdx=3;
+
+ // 2860C use Tx Ring
+
+ IrqState = pAd->irq_disabled;
+#ifdef RT2860
+ if ((pAd->MACVersion == 0x28600100) && (!IrqState))
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+#endif // RT2860 //
+
+ do
+ {
+ // Reset is in progress, stop immediately
+ if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
+ !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
+ {
+ Status = NDIS_STATUS_FAILURE;
+ break;
+ }
+
+ // Check Free priority queue
+ // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
+
+ // 2860C use Tx Ring
+ if (pAd->MACVersion == 0x28600100)
+ {
+ FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
+ }
+ else
+ {
+ FreeNum = GET_MGMTRING_FREENO(pAd);
+ }
+
+ if ((FreeNum > 0))
+ {
+ // We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870
+ NdisZeroMemory(&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE));
+ Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&rtmpHwHdr, (TXINFO_SIZE + TXWI_SIZE), pData, Length);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
+ break;
+ }
+
+ //pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+ //pAd->CommonCfg.MlmeRate = RATE_2;
+
+
+ Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
+ if (Status != NDIS_STATUS_SUCCESS)
+ RTMPFreeNdisPacket(pAd, pPacket);
+ }
+ else
+ {
+ pAd->RalinkCounters.MgmtRingFullCount++;
+ DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing, MgmtRingFullCount=%ld!\n",
+ QueIdx, pAd->RalinkCounters.MgmtRingFullCount));
+ }
+
+ } while (FALSE);
+
+#ifdef RT2860
+ // 2860C use Tx Ring
+ if ((pAd->MACVersion == 0x28600100) && (!IrqState))
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+#endif // RT2860 //
+
+ return Status;
+}
+
+
+#ifdef RT2860
+NDIS_STATUS MiniportMMRequestUnlock(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PUCHAR pData,
+ IN UINT Length)
+{
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG FreeNum;
+ TXWI_STRUC TXWI;
+ ULONG SW_TX_IDX;
+ PTXD_STRUC pTxD;
+
+ QueIdx = 3;
+ ASSERT(Length <= MGMT_DMA_BUFFER_SIZE);
+
+ do
+ {
+ // Reset is in progress, stop immediately
+ if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)||
+ !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
+ {
+ Status = NDIS_STATUS_FAILURE;
+ break;
+ }
+
+ // Check Free priority queue
+ // Since we use PBF Queue2 for management frame. Its corresponding DMA ring should be using TxRing.
+ // 2860C use Tx Ring
+ if (pAd->MACVersion == 0x28600100)
+ {
+ FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
+ SW_TX_IDX = pAd->TxRing[QueIdx].TxCpuIdx;
+ pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SW_TX_IDX].AllocVa;
+ }
+ else
+ {
+ FreeNum = GET_MGMTRING_FREENO(pAd);
+ SW_TX_IDX = pAd->MgmtRing.TxCpuIdx;
+ pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SW_TX_IDX].AllocVa;
+ }
+ if ((FreeNum > 0))
+ {
+ NdisZeroMemory(&TXWI, TXWI_SIZE);
+ Status = RTMPAllocateNdisPacket(pAd, &pPacket, (PUCHAR)&TXWI, TXWI_SIZE, pData, Length);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"));
+ break;
+ }
+
+ Status = MlmeHardTransmit(pAd, QueIdx, pPacket);
+ if (Status != NDIS_STATUS_SUCCESS)
+ RTMPFreeNdisPacket(pAd, pPacket);
+ }
+ else
+ {
+ pAd->RalinkCounters.MgmtRingFullCount++;
+ DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in MgmtRing\n", QueIdx));
+ }
+
+ } while (FALSE);
+
+
+ return Status;
+}
+#endif // RT2860 //
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware transmit function
+
+ Arguments:
+ pAd Pointer to our adapter
+ pBuffer Pointer to memory of outgoing frame
+ Length Size of outgoing management frame
+
+ Return Value:
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_PENDING
+ NDIS_STATUS_SUCCESS
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS MlmeHardTransmit(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket)
+{
+ if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+#ifdef RT2860
+ if ( pAd->MACVersion == 0x28600100 )
+ return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket);
+ else
+#endif // RT2860 //
+ return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket);
+
+}
+
+
+#ifdef RT2860
+NDIS_STATUS MlmeHardTransmitTxRing(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket)
+{
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ PHEADER_802_11 pHeader_802_11;
+ BOOLEAN bAckRequired, bInsertTimestamp;
+ ULONG SrcBufPA;
+ UCHAR MlmeRate;
+ ULONG SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
+ PTXWI_STRUC pFirstTxWI;
+ ULONG FreeNum;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+ if (pSrcBufVA == NULL)
+ {
+ // The buffer shouldn't be NULL
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // Make sure MGMT ring resource won't be used by other threads
+ //NdisAcquireSpinLock(&pAd->TxRingLock);
+
+ FreeNum = GET_TXRING_FREENO(pAd, QueIdx);
+
+ if (FreeNum == 0)
+ {
+ //NdisReleaseSpinLock(&pAd->TxRingLock);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ SwIdx = pAd->TxRing[QueIdx].TxCpuIdx;
+
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+
+ if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket)
+ {
+ printk("MlmeHardTransmit Error\n");
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // outgoing frame always wakeup PHY to prevent frame lost
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ AsicForceWakeup(pAd, TRUE);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ pFirstTxWI =(PTXWI_STRUC)pSrcBufVA;
+
+ pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXWI_SIZE);
+ if (pHeader_802_11->Addr1[0] & 0x01)
+ {
+ MlmeRate = pAd->CommonCfg.BasicMlmeRate;
+ }
+ else
+ {
+ MlmeRate = pAd->CommonCfg.MlmeRate;
+ }
+
+ if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
+ {
+ pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
+ }
+
+ // Verify Mlme rate for a / g bands.
+ if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
+ MlmeRate = RATE_6;
+
+ //
+ // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
+ // Snice it's been set to 0 while on MgtMacHeaderInit
+ // By the way this will cause frame to be send on PWR_SAVE failed.
+ //
+ //
+ // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
+#ifdef CONFIG_STA_SUPPORT
+ // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
+ if (pHeader_802_11->FC.Type != BTYPE_DATA)
+ {
+ if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) || !(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
+ {
+ pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
+ }
+ else
+ {
+ pHeader_802_11->FC.PwrMgmt = pAd->CommonCfg.bAPSDForcePowerSave;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ bInsertTimestamp = FALSE;
+ if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
+ {
+ bAckRequired = FALSE;
+ }
+ else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
+ {
+ if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
+ {
+ bAckRequired = FALSE;
+ pHeader_802_11->Duration = 0;
+ }
+ else
+ {
+ bAckRequired = TRUE;
+ pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
+ if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
+ {
+ bInsertTimestamp = TRUE;
+ }
+ }
+ }
+ pHeader_802_11->Sequence = pAd->Sequence++;
+ if (pAd->Sequence > 0xfff)
+ pAd->Sequence = 0;
+ // Before radar detection done, mgmt frame can not be sent but probe req
+ // Because we need to use probe req to trigger driver to send probe req in passive scan
+ if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
+ return (NDIS_STATUS_FAILURE);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
+#endif
+ //
+ // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
+ // should always has only one ohysical buffer, and the whole frame size equals
+ // to the first scatter buffer size
+ //
+
+ // Initialize TX Descriptor
+ // For inter-frame gap, the number is for this frame and next frame
+ // For MLME rate, we will fix as 2Mb to match other vendor's implement
+
+// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
+ // Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.
+ if (pMacEntry == NULL)
+ {
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, RESERVED_WCID, (SrcBufLen - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
+ }
+ else
+ {
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
+ bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, pMacEntry->Aid, (SrcBufLen - TXWI_SIZE),
+ pMacEntry->MaxHTPhyMode.field.MCS, 0,
+ (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
+ IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
+ }
+
+ pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket;
+ pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL;
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
+#endif
+ SrcBufPA = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);
+
+
+ RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_EDCA);
+ pTxD->LastSec0 = 1;
+ pTxD->LastSec1 = 1;
+ pTxD->SDLen0 = SrcBufLen;
+ pTxD->SDLen1 = 0;
+ pTxD->SDPtr0 = SrcBufPA;
+ pTxD->DMADONE = 0;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif
+
+ pAd->RalinkCounters.KickTxCount++;
+ pAd->RalinkCounters.OneSecTxDoneCount++;
+
+ // Increase TX_CTX_IDX, but write to register later.
+ INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
+
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx*0x10, pAd->TxRing[QueIdx].TxCpuIdx);
+
+ return NDIS_STATUS_SUCCESS;
+}
+#endif // RT2860 //
+
+
+NDIS_STATUS MlmeHardTransmitMgmtRing(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket)
+{
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+ PHEADER_802_11 pHeader_802_11;
+ BOOLEAN bAckRequired, bInsertTimestamp;
+ UCHAR MlmeRate;
+ PTXWI_STRUC pFirstTxWI;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+ RTMP_SEM_LOCK(&pAd->MgmtRingLock);
+
+
+ if (pSrcBufVA == NULL)
+ {
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return NDIS_STATUS_FAILURE;
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // outgoing frame always wakeup PHY to prevent frame lost
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ AsicForceWakeup(pAd, TRUE);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ pFirstTxWI = (PTXWI_STRUC)(pSrcBufVA + TXINFO_SIZE);
+ pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWI_SIZE); //TXWI_SIZE);
+
+ if (pHeader_802_11->Addr1[0] & 0x01)
+ {
+ MlmeRate = pAd->CommonCfg.BasicMlmeRate;
+ }
+ else
+ {
+ MlmeRate = pAd->CommonCfg.MlmeRate;
+ }
+
+ // Verify Mlme rate for a / g bands.
+ if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) // 11A band
+ MlmeRate = RATE_6;
+
+ if ((pHeader_802_11->FC.Type == BTYPE_DATA) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL))
+ {
+ pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1);
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Fixed W52 with Activity scan issue in ABG_MIXED and ABGN_MIXED mode.
+ if (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED
+#ifdef DOT11_N_SUPPORT
+ || pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED
+#endif // DOT11_N_SUPPORT //
+ )
+ {
+ if (pAd->LatchRfRegs.Channel > 14)
+ pAd->CommonCfg.MlmeTransmit.field.MODE = 1;
+ else
+ pAd->CommonCfg.MlmeTransmit.field.MODE = 0;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ //
+ // Should not be hard code to set PwrMgmt to 0 (PWR_ACTIVE)
+ // Snice it's been set to 0 while on MgtMacHeaderInit
+ // By the way this will cause frame to be send on PWR_SAVE failed.
+ //
+ // pHeader_802_11->FC.PwrMgmt = 0; // (pAd->StaCfg.Psm == PWR_SAVE);
+ //
+ // In WMM-UAPSD, mlme frame should be set psm as power saving but probe request frame
+#ifdef CONFIG_STA_SUPPORT
+ // Data-Null packets alse pass through MMRequest in RT2860, however, we hope control the psm bit to pass APSD
+ if ((pHeader_802_11->FC.Type != BTYPE_DATA) && (pHeader_802_11->FC.Type != BTYPE_CNTL))
+ {
+ if ((pAd->StaCfg.Psm == PWR_SAVE) &&
+ (pHeader_802_11->FC.SubType == SUBTYPE_ACTION))
+ pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+ else
+ pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ bInsertTimestamp = FALSE;
+ if (pHeader_802_11->FC.Type == BTYPE_CNTL) // must be PS-POLL
+ {
+#ifdef CONFIG_STA_SUPPORT
+ //Set PM bit in ps-poll, to fix WLK 1.2 PowerSaveMode_ext failure issue.
+ if ((pAd->OpMode == OPMODE_STA) && (pHeader_802_11->FC.SubType == SUBTYPE_PS_POLL))
+ {
+ pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ bAckRequired = FALSE;
+ }
+ else // BTYPE_MGMT or BTYPE_DATA(must be NULL frame)
+ {
+ if (pHeader_802_11->Addr1[0] & 0x01) // MULTICAST, BROADCAST
+ {
+ bAckRequired = FALSE;
+ pHeader_802_11->Duration = 0;
+ }
+ else
+ {
+ bAckRequired = TRUE;
+ pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14);
+ if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP)
+ {
+ bInsertTimestamp = TRUE;
+ }
+ }
+ }
+
+ pHeader_802_11->Sequence = pAd->Sequence++;
+ if (pAd->Sequence >0xfff)
+ pAd->Sequence = 0;
+
+ // Before radar detection done, mgmt frame can not be sent but probe req
+ // Because we need to use probe req to trigger driver to send probe req in passive scan
+ if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n"));
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return (NDIS_STATUS_FAILURE);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE);
+#endif
+
+ //
+ // fill scatter-and-gather buffer list into TXD. Internally created NDIS PACKET
+ // should always has only one ohysical buffer, and the whole frame size equals
+ // to the first scatter buffer size
+ //
+
+ // Initialize TX Descriptor
+ // For inter-frame gap, the number is for this frame and next frame
+ // For MLME rate, we will fix as 2Mb to match other vendor's implement
+
+// management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not.
+ if (pMacEntry == NULL)
+ {
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE, bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, RESERVED_WCID, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE), PID_MGMT, 0, (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS, IFS_BACKOFF, FALSE, &pAd->CommonCfg.MlmeTransmit);
+ }
+ else
+ {
+ RTMPWriteTxWI(pAd, pFirstTxWI, FALSE, FALSE,
+ bInsertTimestamp, FALSE, bAckRequired, FALSE,
+ 0, pMacEntry->Aid, (SrcBufLen - TXINFO_SIZE - TXWI_SIZE),
+ pMacEntry->MaxHTPhyMode.field.MCS, 0,
+ (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS,
+ IFS_BACKOFF, FALSE, &pMacEntry->MaxHTPhyMode);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange((PUCHAR)pFirstTxWI, TYPE_TXWI);
+#endif
+
+ // Now do hardware-depened kick out.
+ HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen);
+
+ // Make sure to release MGMT ring resource
+ RTMP_SEM_UNLOCK(&pAd->MgmtRingLock);
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/********************************************************************************
+
+ New DeQueue Procedures.
+
+ ********************************************************************************/
+
+#define DEQUEUE_LOCK(lock, bIntContext, IrqFlags) \
+ do{ \
+ if (bIntContext == FALSE) \
+ RTMP_IRQ_LOCK((lock), IrqFlags); \
+ }while(0)
+
+#define DEQUEUE_UNLOCK(lock, bIntContext, IrqFlags) \
+ do{ \
+ if (bIntContext == FALSE) \
+ RTMP_IRQ_UNLOCK((lock), IrqFlags); \
+ }while(0)
+
+/*
+ ========================================================================
+ Tx Path design algorithm:
+ Basically, we divide the packets into four types, Broadcast/Multicast, 11N Rate(AMPDU, AMSDU, Normal), B/G Rate(ARALINK, Normal),
+ Specific Packet Type. Following show the classification rule and policy for each kinds of packets.
+ Classification Rule=>
+ Multicast: (*addr1 & 0x01) == 0x01
+ Specific : bDHCPFrame, bARPFrame, bEAPOLFrame, etc.
+ 11N Rate : If peer support HT
+ (1).AMPDU -- If TXBA is negotiated.
+ (2).AMSDU -- If AMSDU is capable for both peer and ourself.
+ *). AMSDU can embedded in a AMPDU, but now we didn't support it.
+ (3).Normal -- Other packets which send as 11n rate.
+
+ B/G Rate : If peer is b/g only.
+ (1).ARALINK-- If both of peer/us supprot Ralink proprietary Aggregation and the TxRate is large than RATE_6
+ (2).Normal -- Other packets which send as b/g rate.
+ Fragment:
+ The packet must be unicast, NOT A-RALINK, NOT A-MSDU, NOT 11n, then can consider about fragment.
+
+ Classified Packet Handle Rule=>
+ Multicast:
+ No ACK, //pTxBlk->bAckRequired = FALSE;
+ No WMM, //pTxBlk->bWMM = FALSE;
+ No piggyback, //pTxBlk->bPiggyBack = FALSE;
+ Force LowRate, //pTxBlk->bForceLowRate = TRUE;
+ Specific : Basically, for specific packet, we should handle it specifically, but now all specific packets are use
+ the same policy to handle it.
+ Force LowRate, //pTxBlk->bForceLowRate = TRUE;
+
+ 11N Rate :
+ No piggyback, //pTxBlk->bPiggyBack = FALSE;
+
+ (1).AMSDU
+ pTxBlk->bWMM = TRUE;
+ (2).AMPDU
+ pTxBlk->bWMM = TRUE;
+ (3).Normal
+
+ B/G Rate :
+ (1).ARALINK
+
+ (2).Normal
+ ========================================================================
+*/
+static UCHAR TxPktClassification(
+ IN RTMP_ADAPTER *pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ UCHAR TxFrameType = TX_UNKOWN_FRAME;
+ UCHAR Wcid;
+ MAC_TABLE_ENTRY *pMacEntry = NULL;
+#ifdef DOT11_N_SUPPORT
+ BOOLEAN bHTRate = FALSE;
+#endif // DOT11_N_SUPPORT //
+
+ Wcid = RTMP_GET_PACKET_WCID(pPacket);
+ if (Wcid == MCAST_WCID)
+ { // Handle for RA is Broadcast/Multicast Address.
+ return TX_MCAST_FRAME;
+ }
+
+ // Handle for unicast packets
+ pMacEntry = &pAd->MacTab.Content[Wcid];
+ if (RTMP_GET_PACKET_LOWRATE(pPacket))
+ { // It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+#ifdef DOT11_N_SUPPORT
+ else if (IS_HT_RATE(pMacEntry))
+ { // it's a 11n capable packet
+
+ // Depends on HTPhyMode to check if the peer support the HTRate transmission.
+ // Currently didn't support A-MSDU embedded in A-MPDU
+ bHTRate = TRUE;
+ if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE))
+ TxFrameType = TX_LEGACY_FRAME;
+#ifdef UAPSD_AP_SUPPORT
+ else if (RTMP_GET_PACKET_EOSP(pPacket))
+ TxFrameType = TX_LEGACY_FRAME;
+#endif // UAPSD_AP_SUPPORT //
+ else if((pMacEntry->TXBAbitmap & (1<<(RTMP_GET_PACKET_UP(pPacket)))) != 0)
+ return TX_AMPDU_FRAME;
+ else if(CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED))
+ return TX_AMSDU_FRAME;
+ else
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+#endif // DOT11_N_SUPPORT //
+ else
+ { // it's a legacy b/g packet.
+ if ((CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE) && pAd->CommonCfg.bAggregationCapable) &&
+ (RTMP_GET_PACKET_TXRATE(pPacket) >= RATE_6) &&
+ (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
+ { // if peer support Ralink Aggregation, we use it.
+ TxFrameType = TX_RALINK_FRAME;
+ }
+ else
+ {
+ TxFrameType = TX_LEGACY_FRAME;
+ }
+ }
+
+ // Currently, our fragment only support when a unicast packet send as NOT-ARALINK, NOT-AMSDU and NOT-AMPDU.
+ if ((RTMP_GET_PACKET_FRAGMENTS(pPacket) > 1) && (TxFrameType == TX_LEGACY_FRAME))
+ TxFrameType = TX_FRAG_FRAME;
+
+ return TxFrameType;
+}
+
+
+BOOLEAN RTMP_FillTxBlkInfo(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk)
+{
+ PACKET_INFO PacketInfo;
+ PNDIS_PACKET pPacket;
+ PMAC_TABLE_ENTRY pMacEntry = NULL;
+
+ pPacket = pTxBlk->pPacket;
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen);
+
+ pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket);
+ pTxBlk->apidx = RTMP_GET_PACKET_IF(pPacket);
+ pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket);
+ pTxBlk->FrameGap = IFS_HTTXOP; // ASIC determine Frame Gap
+
+ if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame);
+ else
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame);
+
+ // Default to clear this flag
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bForceNonQoS);
+
+
+ if (pTxBlk->Wcid == MCAST_WCID)
+ {
+ pTxBlk->pMacEntry = NULL;
+ {
+#ifdef MCAST_RATE_SPECIFIC
+ PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket);
+ if (((*pDA & 0x01) == 0x01) && (*pDA != 0xff))
+ pTxBlk->pTransmit = &pAd->CommonCfg.MCastPhyMode;
+ else
+#endif // MCAST_RATE_SPECIFIC //
+ pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+ }
+
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); // AckRequired = FALSE, when broadcast packet in Adhoc mode.
+ //TX_BLK_SET_FLAG(pTxBlk, fTX_bForceLowRate);
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAllowFrag);
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ if (RTMP_GET_PACKET_MOREDATA(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+ }
+
+ }
+ else
+ {
+ pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid];
+ pTxBlk->pTransmit = &pTxBlk->pMacEntry->HTPhyMode;
+
+ pMacEntry = pTxBlk->pMacEntry;
+
+
+ // For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.
+ if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] != NORMAL_ACK)
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired);
+ else
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired);
+
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+
+ // If support WMM, enable it.
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ if (pTxBlk->TxFrameType == TX_LEGACY_FRAME)
+ {
+ if ( (RTMP_GET_PACKET_LOWRATE(pPacket)) ||
+ ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)))
+ { // Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate.
+ pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode;
+#ifdef DOT11_N_SUPPORT
+ // Modify the WMM bit for ICV issue. If we have a packet with EOSP field need to set as 1, how to handle it???
+ if (IS_HT_STA(pTxBlk->pMacEntry) &&
+ (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RALINK_CHIPSET)) &&
+ ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)))
+ {
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bWMM);
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bForceNonQoS);
+ }
+#endif // DOT11_N_SUPPORT //
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if ( (IS_HT_RATE(pMacEntry) == FALSE) &&
+ (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)))
+ { // Currently piggy-back only support when peer is operate in b/g mode.
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bPiggyBack);
+ }
+#endif // DOT11_N_SUPPORT //
+
+ if (RTMP_GET_PACKET_MOREDATA(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData);
+ }
+#ifdef UAPSD_AP_SUPPORT
+ if (RTMP_GET_PACKET_EOSP(pPacket))
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP);
+ }
+#endif // UAPSD_AP_SUPPORT //
+ }
+ else if (pTxBlk->TxFrameType == TX_FRAG_FRAME)
+ {
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bAllowFrag);
+ }
+
+ pMacEntry->DebugTxCount++;
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN CanDoAggregateTransmit(
+ IN RTMP_ADAPTER *pAd,
+ IN NDIS_PACKET *pPacket,
+ IN TX_BLK *pTxBlk)
+{
+
+ //printk("Check if can do aggregation! TxFrameType=%d!\n", pTxBlk->TxFrameType);
+
+ if (RTMP_GET_PACKET_WCID(pPacket) == MCAST_WCID)
+ return FALSE;
+
+ if (RTMP_GET_PACKET_DHCP(pPacket) ||
+ RTMP_GET_PACKET_EAPOL(pPacket) ||
+ RTMP_GET_PACKET_WAI(pPacket))
+ return FALSE;
+
+ if ((pTxBlk->TxFrameType == TX_AMSDU_FRAME) &&
+ ((pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))> (RX_BUFFER_AGGRESIZE - 100)))
+ { // For AMSDU, allow the packets with total length < max-amsdu size
+ return FALSE;
+ }
+
+ if ((pTxBlk->TxFrameType == TX_RALINK_FRAME) &&
+ (pTxBlk->TxPacketList.Number == 2))
+ { // For RALINK-Aggregation, allow two frames in one batch.
+ return FALSE;
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ if ((INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) // must be unicast to AP
+ return TRUE;
+ else
+#endif // CONFIG_STA_SUPPORT //
+ return FALSE;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ To do the enqueue operation and extract the first item of waiting
+ list. If a number of available shared memory segments could meet
+ the request of extracted item, the extracted item will be fragmented
+ into shared memory segments.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pQueue Pointer to Waiting Queue
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPDeQueuePacket(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bIntContext,
+ IN UCHAR QIdx, /* BulkOutPipeId */
+ IN UCHAR Max_Tx_Packets)
+{
+ PQUEUE_ENTRY pEntry = NULL;
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ UCHAR Count=0;
+ PQUEUE_HEADER pQueue;
+ ULONG FreeNumber[NUM_OF_TX_RING];
+ UCHAR QueIdx, sQIdx, eQIdx;
+ unsigned long IrqFlags = 0;
+ BOOLEAN hasTxDesc = FALSE;
+ TX_BLK TxBlk;
+ TX_BLK *pTxBlk;
+
+#ifdef DBG_DIAGNOSE
+ BOOLEAN firstRound;
+ RtmpDiagStruct *pDiagStruct = &pAd->DiagStruct;
+#endif
+
+
+ if (QIdx == NUM_OF_TX_RING)
+ {
+ sQIdx = 0;
+ eQIdx = 3; // 4 ACs, start from 0.
+ }
+ else
+ {
+ sQIdx = eQIdx = QIdx;
+ }
+
+ for (QueIdx=sQIdx; QueIdx <= eQIdx; QueIdx++)
+ {
+ Count=0;
+
+ RT28XX_START_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+#ifdef DBG_DIAGNOSE
+ firstRound = ((QueIdx == 0) ? TRUE : FALSE);
+#endif // DBG_DIAGNOSE //
+
+ while (1)
+ {
+ if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_NIC_NOT_EXIST))))
+ {
+ RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+ return;
+ }
+
+ if (Count >= Max_Tx_Packets)
+ break;
+
+ DEQUEUE_LOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ if (&pAd->TxSwQueue[QueIdx] == NULL)
+ {
+#ifdef DBG_DIAGNOSE
+ if (firstRound == TRUE)
+ pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][0]++;
+#endif // DBG_DIAGNOSE //
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+#ifdef RT2860
+ FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
+
+#ifdef DBG_DIAGNOSE
+ if (firstRound == TRUE)
+ {
+ UCHAR txDescNumLevel, txSwQNumLevel;
+
+ txDescNumLevel = (TX_RING_SIZE - FreeNumber[QueIdx]); // Number of occupied hw desc.
+ txDescNumLevel = ((txDescNumLevel <=15) ? txDescNumLevel : 15);
+ pDiagStruct->TxDescCnt[pDiagStruct->ArrayCurIdx][txDescNumLevel]++;
+
+ txSwQNumLevel = ((pAd->TxSwQueue[QueIdx].Number <=7) ? pAd->TxSwQueue[QueIdx].Number : 8);
+ pDiagStruct->TxSWQueCnt[pDiagStruct->ArrayCurIdx][txSwQNumLevel]++;
+
+ firstRound = FALSE;
+ }
+#endif // DBG_DIAGNOSE //
+
+ if (FreeNumber[QueIdx] <= 5)
+ {
+ // free Tx(QueIdx) resources
+ RTMPFreeTXDUponTxDmaDone(pAd, QueIdx);
+ FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
+ }
+#endif // RT2860 //
+
+ // probe the Queue Head
+ pQueue = &pAd->TxSwQueue[QueIdx];
+ if ((pEntry = pQueue->Head) == NULL)
+ {
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+ pTxBlk = &TxBlk;
+ NdisZeroMemory((PUCHAR)pTxBlk, sizeof(TX_BLK));
+ pTxBlk->QueIdx = QueIdx;
+
+ pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
+
+ // Early check to make sure we have enoguh Tx Resource.
+ hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+ if (!hasTxDesc)
+ {
+ pAd->PrivateInfo.TxRingFullCnt++;
+
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+
+ break;
+ }
+
+ pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket);
+ pEntry = RemoveHeadQueue(pQueue);
+ pTxBlk->TotalFrameNum++;
+ pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
+ pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+ pTxBlk->pPacket = pPacket;
+ InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+
+ if (pTxBlk->TxFrameType == TX_RALINK_FRAME || pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+ {
+ // Enhance SW Aggregation Mechanism
+ if (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, FreeNumber[QueIdx], pTxBlk->TxFrameType))
+ {
+ InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ break;
+ }
+
+ do{
+ if((pEntry = pQueue->Head) == NULL)
+ break;
+
+ // For TX_AMSDU_FRAME/TX_RALINK_FRAME, Need to check if next pakcet can do aggregation.
+ pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
+ FreeNumber[QueIdx] = GET_TXRING_FREENO(pAd, QueIdx);
+ hasTxDesc = RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, FreeNumber[QueIdx], pPacket);
+ if ((hasTxDesc == FALSE) || (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE))
+ break;
+
+ //Remove the packet from the TxSwQueue and insert into pTxBlk
+ pEntry = RemoveHeadQueue(pQueue);
+ ASSERT(pEntry);
+ pPacket = QUEUE_ENTRY_TO_PKT(pEntry);
+ pTxBlk->TotalFrameNum++;
+ pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); // The real fragment number maybe vary
+ pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket);
+ InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket));
+ }while(1);
+
+ if (pTxBlk->TxPacketList.Number == 1)
+ pTxBlk->TxFrameType = TX_LEGACY_FRAME;
+ }
+
+
+ Count += pTxBlk->TxPacketList.Number;
+
+ // Do HardTransmit now.
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ Status = STAHardTransmit(pAd, pTxBlk, QueIdx);
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RT2860
+ DEQUEUE_UNLOCK(&pAd->irq_lock, bIntContext, IrqFlags);
+ // static rate also need NICUpdateFifoStaCounters() function.
+ //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
+ NICUpdateFifoStaCounters(pAd);
+#endif // RT2860 //
+ }
+
+ RT28XX_STOP_DEQUEUE(pAd, QueIdx, IrqFlags);
+
+
+#ifdef BLOCK_NET_IF
+ if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE)
+ && (pAd->TxSwQueue[QueIdx].Number < 1))
+ {
+ releaseNetIf(&pAd->blockQueueTab[QueIdx]);
+ }
+#endif // BLOCK_NET_IF //
+
+ }
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculates the duration which is required to transmit out frames
+ with given size and specified rate.
+
+ Arguments:
+ pAd Pointer to our adapter
+ Rate Transmit rate
+ Size Frame size in units of byte
+
+ Return Value:
+ Duration number in units of usec
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+USHORT RTMPCalcDuration(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Rate,
+ IN ULONG Size)
+{
+ ULONG Duration = 0;
+
+ if (Rate < RATE_FIRST_OFDM_RATE) // CCK
+ {
+ if ((Rate > RATE_1) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED))
+ Duration = 96; // 72+24 preamble+plcp
+ else
+ Duration = 192; // 144+48 preamble+plcp
+
+ Duration += (USHORT)((Size << 4) / RateIdTo500Kbps[Rate]);
+ if ((Size << 4) % RateIdTo500Kbps[Rate])
+ Duration ++;
+ }
+ else if (Rate <= RATE_LAST_OFDM_RATE)// OFDM rates
+ {
+ Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
+ Duration += 4 * (USHORT)((11 + Size * 4) / RateIdTo500Kbps[Rate]);
+ if ((11 + Size * 4) % RateIdTo500Kbps[Rate])
+ Duration += 4;
+ }
+ else //mimo rate
+ {
+ Duration = 20 + 6; // 16+4 preamble+plcp + Signal Extension
+ }
+
+ return (USHORT)Duration;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculates the duration which is required to transmit out frames
+ with given size and specified rate.
+
+ Arguments:
+ pTxWI Pointer to head of each MPDU to HW.
+ Ack Setting for Ack requirement bit
+ Fragment Setting for Fragment bit
+ RetryMode Setting for retry mode
+ Ifs Setting for IFS gap
+ Rate Setting for transmit rate
+ Service Setting for service
+ Length Frame length
+ TxPreamble Short or Long preamble when using CCK rates
+ QueIdx - 0-3, according to 802.11e/d4.4 June/2003
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ See also : BASmartHardTransmit() !!!
+
+ ========================================================================
+*/
+VOID RTMPWriteTxWI(
+ IN PRTMP_ADAPTER pAd,
+ IN PTXWI_STRUC pOutTxWI,
+ IN BOOLEAN FRAG,
+ IN BOOLEAN CFACK,
+ IN BOOLEAN InsTimestamp,
+ IN BOOLEAN AMPDU,
+ IN BOOLEAN Ack,
+ IN BOOLEAN NSeq, // HW new a sequence.
+ IN UCHAR BASize,
+ IN UCHAR WCID,
+ IN ULONG Length,
+ IN UCHAR PID,
+ IN UCHAR TID,
+ IN UCHAR TxRate,
+ IN UCHAR Txopmode,
+ IN BOOLEAN CfAck,
+ IN HTTRANSMIT_SETTING *pTransmit)
+{
+ PMAC_TABLE_ENTRY pMac = NULL;
+ TXWI_STRUC TxWI;
+ PTXWI_STRUC pTxWI;
+
+ if (WCID < MAX_LEN_OF_MAC_TABLE)
+ pMac = &pAd->MacTab.Content[WCID];
+
+ //
+ // Always use Long preamble before verifiation short preamble functionality works well.
+ // Todo: remove the following line if short preamble functionality works
+ //
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ NdisZeroMemory(&TxWI, TXWI_SIZE);
+ pTxWI = &TxWI;
+
+ pTxWI->FRAG= FRAG;
+
+ pTxWI->CFACK = CFACK;
+ pTxWI->TS= InsTimestamp;
+ pTxWI->AMPDU = AMPDU;
+ pTxWI->ACK = Ack;
+ pTxWI->txop= Txopmode;
+
+ pTxWI->NSEQ = NSeq;
+ // John tune the performace with Intel Client in 20 MHz performance
+#ifdef DOT11_N_SUPPORT
+ BASize = pAd->CommonCfg.TxBASize;
+
+ if( BASize >7 )
+ BASize =7;
+ pTxWI->BAWinSize = BASize;
+ pTxWI->ShortGI = pTransmit->field.ShortGI;
+ pTxWI->STBC = pTransmit->field.STBC;
+#endif // DOT11_N_SUPPORT //
+
+ pTxWI->WirelessCliID = WCID;
+ pTxWI->MPDUtotalByteCount = Length;
+ pTxWI->PacketId = PID;
+
+ // If CCK or OFDM, BW must be 20
+ pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+#ifdef DOT11N_DRAFT3
+ if (pTxWI->BW)
+ pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif // DOT11N_DRAFT3 //
+
+ pTxWI->MCS = pTransmit->field.MCS;
+ pTxWI->PHYMODE = pTransmit->field.MODE;
+ pTxWI->CFACK = CfAck;
+
+#ifdef DOT11_N_SUPPORT
+ if (pMac)
+ {
+ if (pAd->CommonCfg.bMIMOPSEnable)
+ {
+ if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+ {
+ // Dynamic MIMO Power Save Mode
+ pTxWI->MIMOps = 1;
+ }
+ else if (pMac->MmpsMode == MMPS_STATIC)
+ {
+ // Static MIMO Power Save Mode
+ if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
+ {
+ pTxWI->MCS = 7;
+ pTxWI->MIMOps = 0;
+ }
+ }
+ }
+ //pTxWI->MIMOps = (pMac->PsMode == PWR_MMPS)? 1:0;
+ if (pMac->bIAmBadAtheros && (pMac->WepStatus != Ndis802_11WEPDisabled))
+ {
+ pTxWI->MpduDensity = 7;
+ }
+ else
+ {
+ pTxWI->MpduDensity = pMac->MpduDensity;
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+ pTxWI->PacketId = pTxWI->MCS;
+ NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
+}
+
+
+VOID RTMPWriteTxWI_Data(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PTXWI_STRUC pTxWI,
+ IN TX_BLK *pTxBlk)
+{
+ HTTRANSMIT_SETTING *pTransmit;
+ PMAC_TABLE_ENTRY pMacEntry;
+#ifdef DOT11_N_SUPPORT
+ UCHAR BASize;
+#endif // DOT11_N_SUPPORT //
+
+
+ ASSERT(pTxWI);
+
+ pTransmit = pTxBlk->pTransmit;
+ pMacEntry = pTxBlk->pMacEntry;
+
+
+ //
+ // Always use Long preamble before verifiation short preamble functionality works well.
+ // Todo: remove the following line if short preamble functionality works
+ //
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ NdisZeroMemory(pTxWI, TXWI_SIZE);
+
+ pTxWI->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag);
+ pTxWI->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired);
+ pTxWI->txop = pTxBlk->FrameGap;
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+ if (pMacEntry &&
+ (pAd->StaCfg.BssType == BSS_INFRA) &&
+ (pMacEntry->ValidAsDls == TRUE))
+ pTxWI->WirelessCliID = BSSID_WCID;
+ else
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+ pTxWI->WirelessCliID = pTxBlk->Wcid;
+
+ pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+ pTxWI->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack);
+
+ // If CCK or OFDM, BW must be 20
+ pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ if (pTxWI->BW)
+ pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif // DOT11N_DRAFT3 //
+ pTxWI->AMPDU = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE);
+
+ // John tune the performace with Intel Client in 20 MHz performance
+ BASize = pAd->CommonCfg.TxBASize;
+ if((pTxBlk->TxFrameType == TX_AMPDU_FRAME) && (pMacEntry))
+ {
+ UCHAR RABAOriIdx = 0; //The RA's BA Originator table index.
+
+ RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority];
+ BASize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize;
+ }
+
+ pTxWI->TxBF = pTransmit->field.TxBF;
+ pTxWI->BAWinSize = BASize;
+ pTxWI->ShortGI = pTransmit->field.ShortGI;
+ pTxWI->STBC = pTransmit->field.STBC;
+#endif // DOT11_N_SUPPORT //
+
+ pTxWI->MCS = pTransmit->field.MCS;
+ pTxWI->PHYMODE = pTransmit->field.MODE;
+
+#ifdef DOT11_N_SUPPORT
+ if (pMacEntry)
+ {
+ if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+ {
+ // Dynamic MIMO Power Save Mode
+ pTxWI->MIMOps = 1;
+ }
+ else if (pMacEntry->MmpsMode == MMPS_STATIC)
+ {
+ // Static MIMO Power Save Mode
+ if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)
+ {
+ pTxWI->MCS = 7;
+ pTxWI->MIMOps = 0;
+ }
+ }
+
+ if (pMacEntry->bIAmBadAtheros && (pMacEntry->WepStatus != Ndis802_11WEPDisabled))
+ {
+ pTxWI->MpduDensity = 7;
+ }
+ else
+ {
+ pTxWI->MpduDensity = pMacEntry->MpduDensity;
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+#ifdef DBG_DIAGNOSE
+ if (pTxBlk->QueIdx== 0)
+ {
+ pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
+ pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
+ }
+#endif // DBG_DIAGNOSE //
+
+ // for rate adapation
+ pTxWI->PacketId = pTxWI->MCS;
+}
+
+
+VOID RTMPWriteTxWI_Cache(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PTXWI_STRUC pTxWI,
+ IN TX_BLK *pTxBlk)
+{
+ PHTTRANSMIT_SETTING pTransmit;
+ PMAC_TABLE_ENTRY pMacEntry;
+
+ //
+ // update TXWI
+ //
+ pMacEntry = pTxBlk->pMacEntry;
+ pTransmit = pTxBlk->pTransmit;
+
+ if (pMacEntry->bAutoTxRateSwitch)
+ {
+ pTxWI->txop = IFS_HTTXOP;
+
+ // If CCK or OFDM, BW must be 20
+ pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+ pTxWI->ShortGI = pTransmit->field.ShortGI;
+ pTxWI->STBC = pTransmit->field.STBC;
+
+ pTxWI->MCS = pTransmit->field.MCS;
+ pTxWI->PHYMODE = pTransmit->field.MODE;
+
+ // set PID for TxRateSwitching
+ pTxWI->PacketId = pTransmit->field.MCS;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ pTxWI->AMPDU = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE);
+ pTxWI->MIMOps = 0;
+
+#ifdef DOT11N_DRAFT3
+ if (pTxWI->BW)
+ pTxWI->BW = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW);
+#endif // DOT11N_DRAFT3 //
+
+ if (pAd->CommonCfg.bMIMOPSEnable)
+ {
+ // MIMO Power Save Mode
+ if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7))
+ {
+ // Dynamic MIMO Power Save Mode
+ pTxWI->MIMOps = 1;
+ }
+ else if (pMacEntry->MmpsMode == MMPS_STATIC)
+ {
+ // Static MIMO Power Save Mode
+ if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7))
+ {
+ pTxWI->MCS = 7;
+ pTxWI->MIMOps = 0;
+ }
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+#ifdef DBG_DIAGNOSE
+ if (pTxBlk->QueIdx== 0)
+ {
+ pAd->DiagStruct.TxDataCnt[pAd->DiagStruct.ArrayCurIdx]++;
+ pAd->DiagStruct.TxMcsCnt[pAd->DiagStruct.ArrayCurIdx][pTxWI->MCS]++;
+ }
+#endif // DBG_DIAGNOSE //
+
+ pTxWI->MPDUtotalByteCount = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculates the duration which is required to transmit out frames
+ with given size and specified rate.
+
+ Arguments:
+ pTxD Pointer to transmit descriptor
+ Ack Setting for Ack requirement bit
+ Fragment Setting for Fragment bit
+ RetryMode Setting for retry mode
+ Ifs Setting for IFS gap
+ Rate Setting for transmit rate
+ Service Setting for service
+ Length Frame length
+ TxPreamble Short or Long preamble when using CCK rates
+ QueIdx - 0-3, according to 802.11e/d4.4 June/2003
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPWriteTxDescriptor(
+ IN PRTMP_ADAPTER pAd,
+ IN PTXD_STRUC pTxD,
+ IN BOOLEAN bWIV,
+ IN UCHAR QueueSEL)
+{
+ //
+ // Always use Long preamble before verifiation short preamble functionality works well.
+ // Todo: remove the following line if short preamble functionality works
+ //
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+
+ pTxD->WIV = (bWIV) ? 1: 0;
+ pTxD->QSEL= (QueueSEL);
+ if (pAd->bGenOneHCCA == TRUE)
+ pTxD->QSEL= FIFO_HCCA;
+ pTxD->DMADONE = 0;
+}
+
+
+// should be called only when -
+// 1. MEADIA_CONNECTED
+// 2. AGGREGATION_IN_USED
+// 3. Fragmentation not in used
+// 4. either no previous frame (pPrevAddr1=NULL) .OR. previoud frame is aggregatible
+BOOLEAN TxFrameIsAggregatible(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pPrevAddr1,
+ IN PUCHAR p8023hdr)
+{
+
+ // can't aggregate EAPOL (802.1x) frame
+ if ((p8023hdr[12] == 0x88) && (p8023hdr[13] == 0x8e))
+ return FALSE;
+
+ // can't aggregate multicast/broadcast frame
+ if (p8023hdr[0] & 0x01)
+ return FALSE;
+
+ if (INFRA_ON(pAd)) // must be unicast to AP
+ return TRUE;
+ else if ((pPrevAddr1 == NULL) || MAC_ADDR_EQUAL(pPrevAddr1, p8023hdr)) // unicast to same STA
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Check the MSDU Aggregation policy
+ 1.HT aggregation is A-MSDU
+ 2.legaacy rate aggregation is software aggregation by Ralink.
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN PeerIsAggreOn(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG TxRate,
+ IN PMAC_TABLE_ENTRY pMacEntry)
+{
+ ULONG AFlags = (fCLIENT_STATUS_AMSDU_INUSED | fCLIENT_STATUS_AGGREGATION_CAPABLE);
+
+ if (pMacEntry != NULL && CLIENT_STATUS_TEST_FLAG(pMacEntry, AFlags))
+ {
+#ifdef DOT11_N_SUPPORT
+ if (pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
+ {
+ return TRUE;
+ }
+#endif // DOT11_N_SUPPORT //
+
+#ifdef AGGREGATION_SUPPORT
+ if (TxRate >= RATE_6 && pAd->CommonCfg.bAggregationCapable && (!(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))))
+ { // legacy Ralink Aggregation support
+ return TRUE;
+ }
+#endif // AGGREGATION_SUPPORT //
+ }
+
+ return FALSE;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Check and fine the packet waiting in SW queue with highest priority
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ pQueue Pointer to Waiting Queue
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+PQUEUE_HEADER RTMPCheckTxSwQueue(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pQueIdx)
+{
+
+ ULONG Number;
+
+ Number = pAd->TxSwQueue[QID_AC_BK].Number
+ + pAd->TxSwQueue[QID_AC_BE].Number
+ + pAd->TxSwQueue[QID_AC_VI].Number
+ + pAd->TxSwQueue[QID_AC_VO].Number
+ + pAd->TxSwQueue[QID_HCCA].Number;
+
+ if (pAd->TxSwQueue[QID_AC_VO].Head != NULL)
+ {
+ *pQueIdx = QID_AC_VO;
+ return (&pAd->TxSwQueue[QID_AC_VO]);
+ }
+ else if (pAd->TxSwQueue[QID_AC_VI].Head != NULL)
+ {
+ *pQueIdx = QID_AC_VI;
+ return (&pAd->TxSwQueue[QID_AC_VI]);
+ }
+ else if (pAd->TxSwQueue[QID_AC_BE].Head != NULL)
+ {
+ *pQueIdx = QID_AC_BE;
+ return (&pAd->TxSwQueue[QID_AC_BE]);
+ }
+ else if (pAd->TxSwQueue[QID_AC_BK].Head != NULL)
+ {
+ *pQueIdx = QID_AC_BK;
+ return (&pAd->TxSwQueue[QID_AC_BK]);
+ }
+ else if (pAd->TxSwQueue[QID_HCCA].Head != NULL)
+ {
+ *pQueIdx = QID_HCCA;
+ return (&pAd->TxSwQueue[QID_HCCA]);
+ }
+
+ // No packet pending in Tx Sw queue
+ *pQueIdx = QID_AC_BK;
+
+ return (NULL);
+}
+
+
+#ifdef RT2860
+BOOLEAN RTMPFreeTXDUponTxDmaDone(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx)
+{
+ PRTMP_TX_RING pTxRing;
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+#endif
+ PNDIS_PACKET pPacket;
+ UCHAR FREE = 0;
+ TXD_STRUC TxD, *pOriTxD;
+ //ULONG IrqFlags;
+ BOOLEAN bReschedule = FALSE;
+
+
+ ASSERT(QueIdx < NUM_OF_TX_RING);
+ pTxRing = &pAd->TxRing[QueIdx];
+
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF, &pTxRing->TxDmaIdx);
+ while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx)
+ {
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+ PHEADER_802_11 pHeader80211;
+
+ if ((ATE_ON(pAd)) && (pAd->ate.bQATxStart == TRUE))
+ {
+ if (pAd->ate.QID == QueIdx)
+ {
+ pAd->ate.TxDoneCount++;
+ //pAd->ate.Repeat++;
+ pAd->RalinkCounters.KickTxCount++;
+
+ /* always use QID_AC_BE and FIFO_EDCA */
+ ASSERT(pAd->ate.QID == 0);
+ pAd->ate.TxAc0++;
+
+ FREE++;
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
+ pOriTxD = pTxD;
+ NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
+ pTxD = &TxD;
+#else
+ pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
+ pOriTxD = pDestTxD ;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ pTxD->DMADONE = 0;
+
+ pHeader80211 = pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa + sizeof(TXWI_STRUC);
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE);
+#endif
+ pHeader80211->Sequence = ++pAd->ate.seq;
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE);
+#endif
+
+ if ((pAd->ate.bQATxStart == TRUE) && (pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.TxDoneCount < pAd->ate.TxCount))
+ {
+ pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
+ pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
+ INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
+ /* get tx_tdx_idx again */
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
+ goto kick_out;
+ }
+ else if ((pAd->ate.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ate.TxDoneCount == pAd->ate.TxCount))//<========================PETER
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n"));
+ // Tx status enters idle mode.
+ pAd->ate.TxStatus = 0;
+ }
+ else if (!(pAd->ate.Mode & ATE_TXFRAME))
+ {
+ /* not complete sending yet, but someone press the Stop TX botton. */
+ DBGPRINT(RT_DEBUG_ERROR,("not complete sending yet, but someone pressed the Stop TX bottom\n"));
+ DBGPRINT(RT_DEBUG_ERROR,("pAd->ate.Mode = 0x%02x\n", pAd->ate.Mode));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_OFF,("pTxRing->TxSwFreeIdx = %d\n", pTxRing->TxSwFreeIdx));
+ }
+#ifndef RT_BIG_ENDIAN
+ NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
+#else
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ *pDestTxD = TxD;
+#endif // RT_BIG_ENDIAN //
+
+ INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
+ continue;
+ }
+ }
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+ // static rate also need NICUpdateFifoStaCounters() function.
+ //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))
+ NICUpdateFifoStaCounters(pAd);
+
+ /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */
+ FREE++;
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
+ pOriTxD = pTxD;
+ NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
+ pTxD = &TxD;
+#else
+ pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa);
+ pOriTxD = pDestTxD ;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+
+ pTxD->DMADONE = 0;
+
+
+#ifdef RALINK_ATE
+ /* Execution of this block is not allowed when ATE is running. */
+ if (!(ATE_ON(pAd)))
+#endif // RALINK_ATE //
+/*====================================================================*/
+ {
+ pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket;
+ if (pPacket)
+ {
+#ifdef CONFIG_5VT_ENHANCE
+ if (RTMP_GET_PACKET_5VT(pPacket))
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
+ else
+#endif // CONFIG_5VT_ENHANCE //
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNdisPacket as NULL after clear
+ pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL;
+
+ pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket;
+
+ ASSERT(pPacket == NULL);
+ if (pPacket)
+ {
+#ifdef CONFIG_5VT_ENHANCE
+ if (RTMP_GET_PACKET_5VT(pPacket))
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, 16, PCI_DMA_TODEVICE);
+ else
+#endif // CONFIG_5VT_ENHANCE //
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNextNdisPacket as NULL after clear
+ pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL;
+ }
+/*====================================================================*/
+
+ pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0);
+ pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx] ++;
+ INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE);
+ /* get tx_tdx_idx again */
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QueIdx * RINGREG_DIFF , &pTxRing->TxDmaIdx);
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ *pDestTxD = TxD;
+#else
+ NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
+#endif
+
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+kick_out:
+#endif // RALINK_28xx_QA //
+
+ //
+ // ATE_TXCONT mode also need to send some normal frames, so let it in.
+ // ATE_STOP must be changed not to be 0xff
+ // to prevent it from running into this block.
+ //
+ if ((pAd->ate.Mode & ATE_TXFRAME) && (pAd->ate.QID == QueIdx))
+ {
+ // TxDoneCount++ has been done if QA is used.
+ if (pAd->ate.bQATxStart == FALSE)
+ {
+ pAd->ate.TxDoneCount++;
+ }
+ if (((pAd->ate.TxCount - pAd->ate.TxDoneCount + 1) >= TX_RING_SIZE))
+ {
+ /* Note : We increase TxCpuIdx here, not TxSwFreeIdx ! */
+ INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE);
+#ifndef RT_BIG_ENDIAN//<==========================PETER
+ pTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
+ pOriTxD = pTxD;
+ NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC));
+ pTxD = &TxD;
+#else
+ pDestTxD = (PTXD_STRUC) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa);
+ pOriTxD = pDestTxD ;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ pTxD->DMADONE = 0;
+#ifndef RT_BIG_ENDIAN//<==========================PETER
+ NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC));
+#else
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ *pDestTxD = TxD;
+#endif
+ // kick Tx-Ring.
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QueIdx * RINGREG_DIFF, pAd->TxRing[QueIdx].TxCpuIdx);
+ pAd->RalinkCounters.KickTxCount++;
+ }
+ }
+#endif // RALINK_ATE //
+ }
+
+
+ return bReschedule;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process TX Rings DMA Done interrupt, running in DPC level
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
+ IN PRTMP_ADAPTER pAd,
+ IN INT_SOURCE_CSR_STRUC TxRingBitmap)
+{
+ unsigned long IrqFlags;
+ BOOLEAN bReschedule = FALSE;
+
+ // Make sure Tx ring resource won't be used by other threads
+
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+
+ if (TxRingBitmap.field.Ac0DmaDone)
+ bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE);
+
+ if (TxRingBitmap.field.HccaDmaDone)
+ bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA);
+
+ if (TxRingBitmap.field.Ac3DmaDone)
+ bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO);
+
+ if (TxRingBitmap.field.Ac2DmaDone)
+ bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI);
+
+ if (TxRingBitmap.field.Ac1DmaDone)
+ bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK);
+
+ // Make sure to release Tx ring resource
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+
+ // Dequeue outgoing frames from TxSwQueue[] and process it
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+
+ return bReschedule;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process MGMT ring DMA done interrupt, running in DPC level
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPHandleMgmtRingDmaDoneInterrupt(
+ IN PRTMP_ADAPTER pAd)
+{
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ PNDIS_PACKET pPacket;
+ UCHAR FREE = 0;
+ PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
+
+ NdisAcquireSpinLock(&pAd->MgmtRingLock);
+
+ RTMP_IO_READ32(pAd, TX_MGMTDTX_IDX, &pMgmtRing->TxDmaIdx);
+ while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx)
+ {
+ FREE++;
+#ifdef RT_BIG_ENDIAN
+ pDestTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#else
+ pTxD = (PTXD_STRUC) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa);
+#endif
+ pTxD->DMADONE = 0;
+ pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket;
+
+
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNdisPacket = NULL;
+
+ pPacket = pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ pMgmtRing->Cell[pMgmtRing->TxSwFreeIdx].pNextNdisPacket = NULL;
+ INC_RING_INDEX(pMgmtRing->TxSwFreeIdx, MGMT_RING_SIZE);
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD);
+#endif
+ }
+ NdisReleaseSpinLock(&pAd->MgmtRingLock);
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Arguments:
+ Adapter Pointer to our adapter. Dequeue all power safe delayed braodcast frames after beacon.
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPHandleTBTTInterrupt(
+ IN PRTMP_ADAPTER pAd)
+{
+ {
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ {
+ }
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Arguments:
+ Adapter Pointer to our adapter. Rewrite beacon content before next send-out.
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPHandlePreTBTTInterrupt(
+ IN PRTMP_ADAPTER pAd)
+{
+ {
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandlePreTBTTInterrupt...\n"));
+ }
+ }
+
+
+}
+
+VOID RTMPHandleRxCoherentInterrupt(
+ IN PRTMP_ADAPTER pAd)
+{
+ WPDMA_GLO_CFG_STRUC GloCfg;
+
+ if (pAd == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n"));
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n"));
+
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word);
+
+ GloCfg.field.EnTXWriteBackDDONE = 0;
+ GloCfg.field.EnableRxDMA = 0;
+ GloCfg.field.EnableTxDMA = 0;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+
+ RTMPRingCleanUp(pAd, QID_AC_BE);
+ RTMPRingCleanUp(pAd, QID_AC_BK);
+ RTMPRingCleanUp(pAd, QID_AC_VI);
+ RTMPRingCleanUp(pAd, QID_AC_VO);
+ RTMPRingCleanUp(pAd, QID_HCCA);
+ RTMPRingCleanUp(pAd, QID_MGMT);
+ RTMPRingCleanUp(pAd, QID_RX);
+
+ RTMPEnableRxTx(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n"));
+}
+
+
+VOID DBGPRINT_TX_RING(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx)
+{
+ UINT32 Ac0Base;
+ UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
+ int i;
+ PULONG ptemp;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
+ switch (QueIdx)
+ {
+ case QID_AC_BE:
+ RTMP_IO_READ32(pAd, TX_BASE_PTR0, &Ac0Base);
+ RTMP_IO_READ32(pAd, TX_CTX_IDX0, &Ac0SwIdx);
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0, &Ac0HwIdx);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BE DESCRIPTOR \n " ));
+ for (i=0;i<TX_RING_SIZE;i++)
+ {
+ ptemp= (PULONG)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
+ }
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
+ break;
+ case QID_AC_BK:
+ RTMP_IO_READ32(pAd, TX_BASE_PTR1, &Ac0Base);
+ RTMP_IO_READ32(pAd, TX_CTX_IDX1, &Ac0SwIdx);
+ RTMP_IO_READ32(pAd, TX_DTX_IDX1, &Ac0HwIdx);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_BK DESCRIPTOR \n " ));
+ for (i=0;i<TX_RING_SIZE;i++)
+ {
+ ptemp= (PULONG)pAd->TxRing[QID_AC_BK].Cell[i].AllocVa;
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
+ }
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
+ break;
+ case QID_AC_VI:
+ RTMP_IO_READ32(pAd, TX_BASE_PTR2, &Ac0Base);
+ RTMP_IO_READ32(pAd, TX_CTX_IDX2, &Ac0SwIdx);
+ RTMP_IO_READ32(pAd, TX_DTX_IDX2, &Ac0HwIdx);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VI DESCRIPTOR \n " ));
+ for (i=0;i<TX_RING_SIZE;i++)
+ {
+ ptemp= (PULONG)pAd->TxRing[QID_AC_VI].Cell[i].AllocVa;
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
+ }
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
+ break;
+ case QID_AC_VO:
+ RTMP_IO_READ32(pAd, TX_BASE_PTR3, &Ac0Base);
+ RTMP_IO_READ32(pAd, TX_CTX_IDX3, &Ac0SwIdx);
+ RTMP_IO_READ32(pAd, TX_DTX_IDX3, &Ac0HwIdx);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("All QID_AC_VO DESCRIPTOR \n " ));
+ for (i=0;i<TX_RING_SIZE;i++)
+ {
+ ptemp= (PULONG)pAd->TxRing[QID_AC_VO].Cell[i].AllocVa;
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
+ }
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
+ break;
+ case QID_MGMT:
+ RTMP_IO_READ32(pAd, TX_BASE_PTR5, &Ac0Base);
+ RTMP_IO_READ32(pAd, TX_CTX_IDX5, &Ac0SwIdx);
+ RTMP_IO_READ32(pAd, TX_DTX_IDX5, &Ac0HwIdx);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" All QID_MGMT DESCRIPTOR \n " ));
+ for (i=0;i<MGMT_RING_SIZE;i++)
+ {
+ ptemp= (PULONG)pAd->MgmtRing.Cell[i].AllocVa;
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08lx: %08lx: %08lx: %08lx\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
+ }
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" \n " ));
+ break;
+
+ default:
+ DBGPRINT_ERR(("DBGPRINT_TX_RING(Ring %d) not supported\n", QueIdx));
+ break;
+ }
+ AC0freeIdx = pAd->TxRing[QueIdx].TxSwFreeIdx;
+
+ DBGPRINT(RT_DEBUG_TRACE,("TxRing%d, TX_DTX_IDX=%d, TX_CTX_IDX=%d\n", QueIdx, Ac0HwIdx, Ac0SwIdx));
+ DBGPRINT_RAW(RT_DEBUG_TRACE,(" TxSwFreeIdx[%d]", AC0freeIdx));
+ DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
+
+
+}
+
+
+VOID DBGPRINT_RX_RING(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 Ac0Base;
+ UINT32 Ac0HwIdx = 0, Ac0SwIdx = 0, AC0freeIdx;
+ int i;
+ UINT32 *ptemp;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("=====================================================\n " ));
+ RTMP_IO_READ32(pAd, RX_BASE_PTR, &Ac0Base);
+ RTMP_IO_READ32(pAd, RX_CRX_IDX, &Ac0SwIdx);
+ RTMP_IO_READ32(pAd, RX_DRX_IDX, &Ac0HwIdx);
+ AC0freeIdx = pAd->RxRing.RxSwReadIdx;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("All RX DSP \n " ));
+ for (i=0;i<RX_RING_SIZE;i++)
+ {
+ ptemp = (UINT32 *)pAd->RxRing.Cell[i].AllocVa;
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("[%02d] %08x: %08x: %08x: %08x\n " , i, *ptemp,*(ptemp+1),*(ptemp+2),*(ptemp+3)));
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("RxRing, RX_DRX_IDX=%d, RX_CRX_IDX=%d \n", Ac0HwIdx, Ac0SwIdx));
+ DBGPRINT_RAW(RT_DEBUG_TRACE,(" RxSwReadIdx [%d]=", AC0freeIdx));
+ DBGPRINT_RAW(RT_DEBUG_TRACE,(" pending-NDIS=%ld\n", pAd->RalinkCounters.PendingNdisPacketCount));
+}
+#endif // RT2860 //
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Suspend MSDU transmission
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPSuspendMsduTransmission(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n"));
+
+
+ //
+ // Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and
+ // use Lowbound as R66 value on ScanNextChannel(...)
+ //
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
+
+ // set BBP_R66 to 0x30/0x40 when scanning (AsicSwitchChannel will set R66 according to channel when scanning)
+ RTMPSetAGCInitValue(pAd, BW_20);
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Resume MSDU transmission
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPResumeMsduTransmission(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n"));
+
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, pAd->BbpTuning.R66CurrentValue);
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+}
+
+
+UINT deaggregate_AMSDU_announce(
+ IN PRTMP_ADAPTER pAd,
+ PNDIS_PACKET pPacket,
+ IN PUCHAR pData,
+ IN ULONG DataSize)
+{
+ USHORT PayloadSize;
+ USHORT SubFrameSize;
+ PHEADER_802_3 pAMSDUsubheader;
+ UINT nMSDU;
+ UCHAR Header802_3[14];
+
+ PUCHAR pPayload, pDA, pSA, pRemovedLLCSNAP;
+ PNDIS_PACKET pClonePacket;
+
+
+
+ nMSDU = 0;
+
+ while (DataSize > LENGTH_802_3)
+ {
+
+ nMSDU++;
+
+ pAMSDUsubheader = (PHEADER_802_3)pData;
+ PayloadSize = pAMSDUsubheader->Octet[1] + (pAMSDUsubheader->Octet[0]<<8);
+ SubFrameSize = PayloadSize + LENGTH_802_3;
+
+
+ if ((DataSize < SubFrameSize) || (PayloadSize > 1518 ))
+ {
+ break;
+ }
+
+ pPayload = pData + LENGTH_802_3;
+ pDA = pData;
+ pSA = pData + MAC_ADDR_LEN;
+
+ // convert to 802.3 header
+ CONVERT_TO_802_3(Header802_3, pDA, pSA, pPayload, PayloadSize, pRemovedLLCSNAP);
+
+#ifdef CONFIG_STA_SUPPORT
+ if ((Header802_3[12] == 0x88) && (Header802_3[13] == 0x8E) )
+ {
+ // avoid local heap overflow, use dyanamic allocation
+ MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+ memmove(Elem->Msg+(LENGTH_802_11 + LENGTH_802_1_H), pPayload, PayloadSize);
+ Elem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + PayloadSize;
+ WpaEAPOLKeyAction(pAd, Elem);
+ kfree(Elem);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (pRemovedLLCSNAP)
+ {
+ pPayload -= LENGTH_802_3;
+ PayloadSize += LENGTH_802_3;
+ NdisMoveMemory(pPayload, &Header802_3[0], LENGTH_802_3);
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ pClonePacket = ClonePacket(pAd, pPacket, pPayload, PayloadSize);
+ if (pClonePacket)
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pClonePacket, RTMP_GET_PACKET_IF(pPacket));
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+
+ // A-MSDU has padding to multiple of 4 including subframe header.
+ // align SubFrameSize up to multiple of 4
+ SubFrameSize = (SubFrameSize+3)&(~0x3);
+
+
+ if (SubFrameSize > 1528 || SubFrameSize < 32)
+ {
+ break;
+ }
+
+ if (DataSize > SubFrameSize)
+ {
+ pData += SubFrameSize;
+ DataSize -= SubFrameSize;
+ }
+ else
+ {
+ // end of A-MSDU
+ DataSize = 0;
+ }
+ }
+
+ // finally release original rx packet
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+
+ return nMSDU;
+}
+
+
+UINT BA_Reorder_AMSDU_Annnounce(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ PUCHAR pData;
+ USHORT DataSize;
+ UINT nMSDU = 0;
+
+ pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
+ DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
+
+ nMSDU = deaggregate_AMSDU_announce(pAd, pPacket, pData, DataSize);
+
+ return nMSDU;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Look up the MAC address in the MAC table. Return NULL if not found.
+ Return:
+ pEntry - pointer to the MAC entry; NULL is not found
+ ==========================================================================
+*/
+MAC_TABLE_ENTRY *MacTableLookup(
+ IN PRTMP_ADAPTER pAd,
+ PUCHAR pAddr)
+{
+ ULONG HashIdx;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ pEntry = pAd->MacTab.Hash[HashIdx];
+
+ while (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsWDS || pEntry->ValidAsApCli || pEntry->ValidAsMesh))
+ {
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+ {
+ break;
+ }
+ else
+ pEntry = pEntry->pNext;
+ }
+
+ return pEntry;
+}
+
+MAC_TABLE_ENTRY *MacTableInsertEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR apidx,
+ IN BOOLEAN CleanAll)
+{
+ UCHAR HashIdx;
+ int i, FirstWcid;
+ MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
+
+ // if FULL, return
+ if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
+ return NULL;
+
+ FirstWcid = 1;
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ if (pAd->StaCfg.BssType == BSS_INFRA)
+ FirstWcid = 2;
+#endif // CONFIG_STA_SUPPORT //
+
+ // allocate one MAC entry
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+ for (i = FirstWcid; i< MAX_LEN_OF_MAC_TABLE; i++) // skip entry#0 so that "entry index == AID" for fast lookup
+ {
+ // pick up the first available vacancy
+ if ((pAd->MacTab.Content[i].ValidAsCLI == FALSE) &&
+ (pAd->MacTab.Content[i].ValidAsWDS == FALSE) &&
+ (pAd->MacTab.Content[i].ValidAsApCli== FALSE) &&
+ (pAd->MacTab.Content[i].ValidAsMesh == FALSE)
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+ && (pAd->MacTab.Content[i].ValidAsDls == FALSE)
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+ )
+ {
+ pEntry = &pAd->MacTab.Content[i];
+ if (CleanAll == TRUE)
+ {
+ pEntry->MaxSupportedRate = RATE_11;
+ pEntry->CurrTxRate = RATE_11;
+ NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
+ pEntry->PairwiseKey.KeyLen = 0;
+ pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
+ }
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+ if (apidx >= MIN_NET_DEVICE_FOR_DLS)
+ {
+ pEntry->ValidAsCLI = FALSE;
+ pEntry->ValidAsWDS = FALSE;
+ pEntry->ValidAsApCli = FALSE;
+ pEntry->ValidAsMesh = FALSE;
+ pEntry->ValidAsDls = TRUE;
+ pEntry->isCached = FALSE;
+ }
+ else
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pEntry->ValidAsCLI = TRUE;
+ pEntry->ValidAsWDS = FALSE;
+ pEntry->ValidAsApCli = FALSE;
+ pEntry->ValidAsMesh = FALSE;
+ pEntry->ValidAsDls = FALSE;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ pEntry->bIAmBadAtheros = FALSE;
+ pEntry->pAd = pAd;
+ pEntry->CMTimerRunning = FALSE;
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+ pEntry->RSNIE_Len = 0;
+ NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
+ pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
+
+ if (pEntry->ValidAsMesh)
+ pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_MESH);
+ else if (pEntry->ValidAsApCli)
+ pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_APCLI);
+ else if (pEntry->ValidAsWDS)
+ pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_WDS);
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+ else if (pEntry->ValidAsDls)
+ pEntry->apidx = (apidx - MIN_NET_DEVICE_FOR_DLS);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+ else
+ pEntry->apidx = apidx;
+
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pEntry->AuthMode = pAd->StaCfg.AuthMode;
+ pEntry->WepStatus = pAd->StaCfg.WepStatus;
+ pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+#ifdef RT2860
+ AsicRemovePairwiseKeyEntry(pAd, pEntry->apidx, (UCHAR)i);
+#endif // RT2860 //
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ pEntry->GTKState = REKEY_NEGOTIATING;
+ pEntry->PairwiseKey.KeyLen = 0;
+ pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
+#ifdef CONFIG_STA_SUPPORT
+ if ((pAd->OpMode == OPMODE_STA) &&
+ (pAd->StaCfg.BssType == BSS_ADHOC))
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+ else
+#ifdef QOS_DLS_SUPPORT
+ if (pEntry->ValidAsDls == TRUE)
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+ else
+#endif //QOS_DLS_SUPPORT
+#endif // CONFIG_STA_SUPPORT //
+ pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND;
+ COPY_MAC_ADDR(pEntry->Addr, pAddr);
+ pEntry->Sst = SST_NOT_AUTH;
+ pEntry->AuthState = AS_NOT_AUTH;
+ pEntry->Aid = (USHORT)i; //0;
+ pEntry->CapabilityInfo = 0;
+ pEntry->PsMode = PWR_ACTIVE;
+ pEntry->PsQIdleCount = 0;
+ pEntry->NoDataIdleCount = 0;
+ pEntry->ContinueTxFailCnt = 0;
+ InitializeQueueHeader(&pEntry->PsQueue);
+
+
+ pAd->MacTab.Size ++;
+ // Add this entry into ASIC RX WCID search table
+ RT28XX_STA_ENTRY_ADD(pAd, pEntry);
+
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertEntry - allocate entry #%d, Total= %d\n",i, pAd->MacTab.Size));
+ break;
+ }
+ }
+
+ // add this MAC entry into HASH table
+ if (pEntry)
+ {
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ if (pAd->MacTab.Hash[HashIdx] == NULL)
+ {
+ pAd->MacTab.Hash[HashIdx] = pEntry;
+ }
+ else
+ {
+ pCurrEntry = pAd->MacTab.Hash[HashIdx];
+ while (pCurrEntry->pNext != NULL)
+ pCurrEntry = pCurrEntry->pNext;
+ pCurrEntry->pNext = pEntry;
+ }
+ }
+
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+ return pEntry;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Delete a specified client from MAC table
+ ==========================================================================
+ */
+BOOLEAN MacTableDeleteEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT wcid,
+ IN PUCHAR pAddr)
+{
+ USHORT HashIdx;
+ MAC_TABLE_ENTRY *pEntry, *pPrevEntry, *pProbeEntry;
+ BOOLEAN Cancelled;
+
+ if (wcid >= MAX_LEN_OF_MAC_TABLE)
+ return FALSE;
+
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ pEntry = &pAd->MacTab.Content[wcid];
+
+ if (pEntry && (pEntry->ValidAsCLI || pEntry->ValidAsApCli || pEntry->ValidAsWDS || pEntry->ValidAsMesh
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+ || pEntry->ValidAsDls
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+ ))
+ {
+ if (MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+ {
+
+ // Delete this entry from ASIC on-chip WCID Table
+ RT28XX_STA_ENTRY_MAC_RESET(pAd, wcid);
+
+#ifdef DOT11_N_SUPPORT
+ // free resources of BA
+ BASessionTearDownALL(pAd, pEntry->Aid);
+#endif // DOT11_N_SUPPORT //
+
+
+ pPrevEntry = NULL;
+ pProbeEntry = pAd->MacTab.Hash[HashIdx];
+ ASSERT(pProbeEntry);
+
+ // update Hash list
+ do
+ {
+ if (pProbeEntry == pEntry)
+ {
+ if (pPrevEntry == NULL)
+ {
+ pAd->MacTab.Hash[HashIdx] = pEntry->pNext;
+ }
+ else
+ {
+ pPrevEntry->pNext = pEntry->pNext;
+ }
+ break;
+ }
+
+ pPrevEntry = pProbeEntry;
+ pProbeEntry = pProbeEntry->pNext;
+ } while (pProbeEntry);
+
+ // not found !!!
+ ASSERT(pProbeEntry != NULL);
+
+ RT28XX_STA_ENTRY_KEY_DEL(pAd, BSS0, wcid);
+
+
+ if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
+ {
+ RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+ }
+
+
+ NdisZeroMemory(pEntry, sizeof(MAC_TABLE_ENTRY));
+ pAd->MacTab.Size --;
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableDeleteEntry1 - Total= %d\n", pAd->MacTab.Size));
+ }
+ else
+ {
+ printk("\n%s: Impossible Wcid = %d !!!!!\n", __func__, wcid);
+ }
+ }
+
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+ //Reset operating mode when no Sta.
+ if (pAd->MacTab.Size == 0)
+ {
+#ifdef DOT11_N_SUPPORT
+ pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0;
+#endif // DOT11_N_SUPPORT //
+ AsicUpdateProtect(pAd, 0 /*pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode*/, (ALLN_SETPROTECT), TRUE, 0 /*pAd->MacTab.fAnyStationNonGF*/);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This routine reset the entire MAC table. All packets pending in
+ the power-saving queues are freed here.
+ ==========================================================================
+ */
+VOID MacTableReset(
+ IN PRTMP_ADAPTER pAd)
+{
+ int i;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableReset\n"));
+ //NdisAcquireSpinLock(&pAd->MacTabLock);
+
+ for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+#ifdef RT2860
+ RT28XX_STA_ENTRY_MAC_RESET(pAd, i);
+#endif // RT2860 //
+ if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
+ {
+
+#ifdef DOT11_N_SUPPORT
+ // free resources of BA
+ BASessionTearDownALL(pAd, i);
+#endif // DOT11_N_SUPPORT //
+
+ pAd->MacTab.Content[i].ValidAsCLI = FALSE;
+
+
+
+
+ //AsicDelWcidTab(pAd, i);
+ }
+ }
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID AssocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
+ IN PUCHAR pAddr,
+ IN USHORT CapabilityInfo,
+ IN ULONG Timeout,
+ IN USHORT ListenIntv)
+{
+ COPY_MAC_ADDR(AssocReq->Addr, pAddr);
+ // Add mask to support 802.11b mode only
+ AssocReq->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; // not cf-pollable, not cf-poll-request
+ AssocReq->Timeout = Timeout;
+ AssocReq->ListenIntv = ListenIntv;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID DisassocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
+ IN PUCHAR pAddr,
+ IN USHORT Reason)
+{
+ COPY_MAC_ADDR(DisassocReq->Addr, pAddr);
+ DisassocReq->Reason = Reason;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Check the out going frame, if this is an DHCP or ARP datagram
+ will be duplicate another frame at low data rate transmit.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pPacket Pointer to outgoing Ndis frame
+
+ Return Value:
+ TRUE To be duplicate at Low data rate transmit. (1mb)
+ FALSE Do nothing.
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ MAC header + IP Header + UDP Header
+ 14 Bytes 20 Bytes
+
+ UDP Header
+ 00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
+ Source Port
+ 16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|
+ Destination Port
+
+ port 0x43 means Bootstrap Protocol, server.
+ Port 0x44 means Bootstrap Protocol, client.
+
+ ========================================================================
+*/
+
+BOOLEAN RTMPCheckDHCPFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ PACKET_INFO PacketInfo;
+ ULONG NumberOfBytesRead = 0;
+ ULONG CurrentOffset = 0;
+ PVOID pVirtualAddress = NULL;
+ UINT NdisBufferLength;
+ PUCHAR pSrc;
+ USHORT Protocol;
+ UCHAR ByteOffset36 = 0;
+ UCHAR ByteOffset38 = 0;
+ BOOLEAN ReadFirstParm = TRUE;
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, (PUCHAR *)&pVirtualAddress, &NdisBufferLength);
+
+ NumberOfBytesRead += NdisBufferLength;
+ pSrc = (PUCHAR) pVirtualAddress;
+ Protocol = *(pSrc + 12) * 256 + *(pSrc + 13);
+
+ //
+ // Check DHCP & BOOTP protocol
+ //
+ while (NumberOfBytesRead <= PacketInfo.TotalPacketLength)
+ {
+ if ((NumberOfBytesRead >= 35) && (ReadFirstParm == TRUE))
+ {
+ CurrentOffset = 35 - (NumberOfBytesRead - NdisBufferLength);
+ ByteOffset36 = *(pSrc + CurrentOffset);
+ ReadFirstParm = FALSE;
+ }
+
+ if (NumberOfBytesRead >= 37)
+ {
+ CurrentOffset = 37 - (NumberOfBytesRead - NdisBufferLength);
+ ByteOffset38 = *(pSrc + CurrentOffset);
+ //End of Read
+ break;
+ }
+ return FALSE;
+ }
+
+ // Check for DHCP & BOOTP protocol
+ if ((ByteOffset36 != 0x44) || (ByteOffset38 != 0x43))
+ {
+ //
+ // 2054 (hex 0806) for ARP datagrams
+ // if this packet is not ARP datagrams, then do nothing
+ // ARP datagrams will also be duplicate at 1mb broadcast frames
+ //
+ if (Protocol != 0x0806 )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN RTMPCheckEtherType(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ USHORT TypeLen;
+ UCHAR Byte0, Byte1;
+ PUCHAR pSrcBuf;
+ UINT32 pktLen;
+ UINT16 srcPort, dstPort;
+ BOOLEAN status = TRUE;
+
+
+ pSrcBuf = GET_OS_PKT_DATAPTR(pPacket);
+ pktLen = GET_OS_PKT_LEN(pPacket);
+
+ ASSERT(pSrcBuf);
+
+ RTMP_SET_PACKET_SPECIFIC(pPacket, 0);
+
+ // get Ethernet protocol field
+ TypeLen = (pSrcBuf[12] << 8) + pSrcBuf[13];
+
+ pSrcBuf += LENGTH_802_3; // Skip the Ethernet Header.
+
+ if (TypeLen <= 1500)
+ { // 802.3, 802.3 LLC
+ /*
+ DestMAC(6) + SrcMAC(6) + Lenght(2) +
+ DSAP(1) + SSAP(1) + Control(1) +
+ if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header.
+ => + SNAP (5, OriginationID(3) + etherType(2))
+ */
+ if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03)
+ {
+ Sniff2BytesFromNdisBuffer(pSrcBuf, 6, &Byte0, &Byte1);
+ RTMP_SET_PACKET_LLCSNAP(pPacket, 1);
+ TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+ pSrcBuf += 8; // Skip this LLC/SNAP header
+ }
+ else
+ {
+ //It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it.
+ }
+ }
+
+ // If it's a VLAN packet, get the real Type/Length field.
+ if (TypeLen == 0x8100)
+ {
+ /* 0x8100 means VLAN packets */
+
+ /* Dest. MAC Address (6-bytes) +
+ Source MAC Address (6-bytes) +
+ Length/Type = 802.1Q Tag Type (2-byte) +
+ Tag Control Information (2-bytes) +
+ Length / Type (2-bytes) +
+ data payload (0-n bytes) +
+ Pad (0-p bytes) +
+ Frame Check Sequence (4-bytes) */
+
+ RTMP_SET_PACKET_VLAN(pPacket, 1);
+ Sniff2BytesFromNdisBuffer(pSrcBuf, 2, &Byte0, &Byte1);
+ TypeLen = (USHORT)((Byte0 << 8) + Byte1);
+
+ pSrcBuf += 4; // Skip the VLAN Header.
+ }
+
+ switch (TypeLen)
+ {
+ case 0x0800:
+ {
+ ASSERT((pktLen > 34));
+ if (*(pSrcBuf + 9) == 0x11)
+ { // udp packet
+ ASSERT((pktLen > 34)); // 14 for ethernet header, 20 for IP header
+
+ pSrcBuf += 20; // Skip the IP header
+ srcPort = OS_NTOHS(*((UINT16 *)pSrcBuf));
+ dstPort = OS_NTOHS(*((UINT16 *)(pSrcBuf +2)));
+
+ if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44))
+ { //It's a BOOTP/DHCP packet
+ RTMP_SET_PACKET_DHCP(pPacket, 1);
+ }
+ }
+ }
+ break;
+ case 0x0806:
+ {
+ //ARP Packet.
+ RTMP_SET_PACKET_DHCP(pPacket, 1);
+ }
+ break;
+ case 0x888e:
+ {
+ // EAPOL Packet.
+ RTMP_SET_PACKET_EAPOL(pPacket, 1);
+ }
+ break;
+ default:
+ status = FALSE;
+ break;
+ }
+
+ return status;
+
+}
+
+
+
+VOID Update_Rssi_Sample(
+ IN PRTMP_ADAPTER pAd,
+ IN RSSI_SAMPLE *pRssi,
+ IN PRXWI_STRUC pRxWI)
+ {
+ CHAR rssi0 = pRxWI->RSSI0;
+ CHAR rssi1 = pRxWI->RSSI1;
+ CHAR rssi2 = pRxWI->RSSI2;
+
+ if (rssi0 != 0)
+ {
+ pRssi->LastRssi0 = ConvertToRssi(pAd, (CHAR)rssi0, RSSI_0);
+ pRssi->AvgRssi0X8 = (pRssi->AvgRssi0X8 - pRssi->AvgRssi0) + pRssi->LastRssi0;
+ pRssi->AvgRssi0 = pRssi->AvgRssi0X8 >> 3;
+ }
+
+ if (rssi1 != 0)
+ {
+ pRssi->LastRssi1 = ConvertToRssi(pAd, (CHAR)rssi1, RSSI_1);
+ pRssi->AvgRssi1X8 = (pRssi->AvgRssi1X8 - pRssi->AvgRssi1) + pRssi->LastRssi1;
+ pRssi->AvgRssi1 = pRssi->AvgRssi1X8 >> 3;
+ }
+
+ if (rssi2 != 0)
+ {
+ pRssi->LastRssi2 = ConvertToRssi(pAd, (CHAR)rssi2, RSSI_2);
+ pRssi->AvgRssi2X8 = (pRssi->AvgRssi2X8 - pRssi->AvgRssi2) + pRssi->LastRssi2;
+ pRssi->AvgRssi2 = pRssi->AvgRssi2X8 >> 3;
+ }
+}
+
+
+
+// Normal legacy Rx packet indication
+VOID Indicate_Legacy_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ UCHAR Header802_3[LENGTH_802_3];
+
+ // 1. get 802.3 Header
+ // 2. remove LLC
+ // a. pointer pRxBlk->pData to payload
+ // b. modify pRxBlk->DataSize
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif // CONFIG_STA_SUPPORT //
+
+ if (pRxBlk->DataSize > MAX_RX_PKT_LEN)
+ {
+
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+
+ STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
+
+
+ wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
+
+ //
+ // pass this 802.3 packet to upper layer or forward this packet to WM directly
+ //
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxPacket, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+
+}
+
+
+// Normal, AMPDU or AMSDU
+VOID CmmRxnonRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
+ {
+ Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
+ {
+ // handle A-MSDU
+ Indicate_AMSDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+ Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ }
+}
+
+
+VOID CmmRxRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ UCHAR Header802_3[LENGTH_802_3];
+ UINT16 Msdu2Size;
+ UINT16 Payload1Size, Payload2Size;
+ PUCHAR pData2;
+ PNDIS_PACKET pPacket2 = NULL;
+
+
+
+ Msdu2Size = *(pRxBlk->pData) + (*(pRxBlk->pData+1) << 8);
+
+ if ((Msdu2Size <= 1536) && (Msdu2Size < pRxBlk->DataSize))
+ {
+ /* skip two byte MSDU2 len */
+ pRxBlk->pData += 2;
+ pRxBlk->DataSize -= 2;
+ }
+ else
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ // get 802.3 Header and remove LLC
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
+#endif // CONFIG_STA_SUPPORT //
+
+
+ ASSERT(pRxBlk->pRxPacket);
+
+ // Ralink Aggregation frame
+ pAd->RalinkCounters.OneSecRxAggregationCount ++;
+ Payload1Size = pRxBlk->DataSize - Msdu2Size;
+ Payload2Size = Msdu2Size - LENGTH_802_3;
+
+ pData2 = pRxBlk->pData + Payload1Size + LENGTH_802_3;
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ pPacket2 = duplicate_pkt(pAd, (pData2-LENGTH_802_3), LENGTH_802_3, pData2, Payload2Size, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+
+ if (!pPacket2)
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ // update payload size of 1st packet
+ pRxBlk->DataSize = Payload1Size;
+ wlan_802_11_to_802_3_packet(pAd, pRxBlk, Header802_3, FromWhichBSSID);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pRxBlk->pRxPacket, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+
+ if (pPacket2)
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket2, FromWhichBSSID);
+#endif // CONFIG_STA_SUPPORT //
+ }
+}
+
+
+#define RESET_FRAGFRAME(_fragFrame) \
+ { \
+ _fragFrame.RxSize = 0; \
+ _fragFrame.Sequence = 0; \
+ _fragFrame.LastFrag = 0; \
+ _fragFrame.Flags = 0; \
+ }
+
+
+PNDIS_PACKET RTMPDeFragmentDataFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk)
+{
+ PHEADER_802_11 pHeader = pRxBlk->pHeader;
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ UCHAR *pData = pRxBlk->pData;
+ USHORT DataSize = pRxBlk->DataSize;
+ PNDIS_PACKET pRetPacket = NULL;
+ UCHAR *pFragBuffer = NULL;
+ BOOLEAN bReassDone = FALSE;
+ UCHAR HeaderRoom = 0;
+
+
+ ASSERT(pHeader);
+
+ HeaderRoom = pData - (UCHAR *)pHeader;
+
+ // Re-assemble the fragmented packets
+ if (pHeader->Frag == 0) // Frag. Number is 0 : First frag or only one pkt
+ {
+ // the first pkt of fragment, record it.
+ if (pHeader->FC.MoreFrag)
+ {
+ ASSERT(pAd->FragFrame.pFragPacket);
+ pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+ pAd->FragFrame.RxSize = DataSize + HeaderRoom;
+ NdisMoveMemory(pFragBuffer, pHeader, pAd->FragFrame.RxSize);
+ pAd->FragFrame.Sequence = pHeader->Sequence;
+ pAd->FragFrame.LastFrag = pHeader->Frag; // Should be 0
+ ASSERT(pAd->FragFrame.LastFrag == 0);
+ goto done; // end of processing this frame
+ }
+ }
+ else //Middle & End of fragment
+ {
+ if ((pHeader->Sequence != pAd->FragFrame.Sequence) ||
+ (pHeader->Frag != (pAd->FragFrame.LastFrag + 1)))
+ {
+ // Fragment is not the same sequence or out of fragment number order
+ // Reset Fragment control blk
+ RESET_FRAGFRAME(pAd->FragFrame);
+ DBGPRINT(RT_DEBUG_ERROR, ("Fragment is not the same sequence or out of fragment number order.\n"));
+ goto done; // give up this frame
+ }
+ else if ((pAd->FragFrame.RxSize + DataSize) > MAX_FRAME_SIZE)
+ {
+ // Fragment frame is too large, it exeeds the maximum frame size.
+ // Reset Fragment control blk
+ RESET_FRAGFRAME(pAd->FragFrame);
+ DBGPRINT(RT_DEBUG_ERROR, ("Fragment frame is too large, it exeeds the maximum frame size.\n"));
+ goto done; // give up this frame
+ }
+
+ //
+ // Broadcom AP(BCM94704AGR) will send out LLC in fragment's packet, LLC only can accpet at first fragment.
+ // In this case, we will dropt it.
+ //
+ if (NdisEqualMemory(pData, SNAP_802_1H, sizeof(SNAP_802_1H)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Find another LLC at Middle or End fragment(SN=%d, Frag=%d)\n", pHeader->Sequence, pHeader->Frag));
+ goto done; // give up this frame
+ }
+
+ pFragBuffer = GET_OS_PKT_DATAPTR(pAd->FragFrame.pFragPacket);
+
+ // concatenate this fragment into the re-assembly buffer
+ NdisMoveMemory((pFragBuffer + pAd->FragFrame.RxSize), pData, DataSize);
+ pAd->FragFrame.RxSize += DataSize;
+ pAd->FragFrame.LastFrag = pHeader->Frag; // Update fragment number
+
+ // Last fragment
+ if (pHeader->FC.MoreFrag == FALSE)
+ {
+ bReassDone = TRUE;
+ }
+ }
+
+done:
+ // always release rx fragmented packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+
+ // return defragmented packet if packet is reassembled completely
+ // otherwise return NULL
+ if (bReassDone)
+ {
+ PNDIS_PACKET pNewFragPacket;
+
+ // allocate a new packet buffer for fragment
+ pNewFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE);
+ if (pNewFragPacket)
+ {
+ // update RxBlk
+ pRetPacket = pAd->FragFrame.pFragPacket;
+ pAd->FragFrame.pFragPacket = pNewFragPacket;
+ pRxBlk->pHeader = (PHEADER_802_11) GET_OS_PKT_DATAPTR(pRetPacket);
+ pRxBlk->pData = (UCHAR *)pRxBlk->pHeader + HeaderRoom;
+ pRxBlk->DataSize = pAd->FragFrame.RxSize - HeaderRoom;
+ pRxBlk->pRxPacket = pRetPacket;
+ }
+ else
+ {
+ RESET_FRAGFRAME(pAd->FragFrame);
+ }
+ }
+
+ return pRetPacket;
+}
+
+
+VOID Indicate_AMSDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ UINT nMSDU;
+
+ update_os_packet_info(pAd, pRxBlk, FromWhichBSSID);
+ RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
+ nMSDU = deaggregate_AMSDU_announce(pAd, pRxBlk->pRxPacket, pRxBlk->pData, pRxBlk->DataSize);
+}
+
+VOID Indicate_EAPOL_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pEntry = &pAd->MacTab.Content[BSSID_WCID];
+ STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+ return;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ if (pEntry == NULL)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Indicate_EAPOL_Packet: drop and release the invalid packet.\n"));
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+}
+
+#define BCN_TBTT_OFFSET 64 //defer 64 us
+VOID ReSyncBeaconTime(
+ IN PRTMP_ADAPTER pAd)
+{
+
+ UINT32 Offset;
+
+
+ Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET);
+
+ pAd->TbttTickCount++;
+
+ //
+ // The updated BeaconInterval Value will affect Beacon Interval after two TBTT
+ // beacasue the original BeaconInterval had been loaded into next TBTT_TIMER
+ //
+ if (Offset == (BCN_TBTT_OFFSET-2))
+ {
+ BCN_TIME_CFG_STRUC csr;
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; // ASIC register in units of 1/16 TU = 64us
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+ }
+ else
+ {
+ if (Offset == (BCN_TBTT_OFFSET-1))
+ {
+ BCN_TIME_CFG_STRUC csr;
+
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; // ASIC register in units of 1/16 TU
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+ }
+ }
+}
+
diff --git a/drivers/staging/rt2860/common/cmm_data_2860.c b/drivers/staging/rt2860/common/cmm_data_2860.c
new file mode 100644
index 000000000000..419e50c3fc4c
--- /dev/null
+++ b/drivers/staging/rt2860/common/cmm_data_2860.c
@@ -0,0 +1,1240 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+*/
+
+/*
+ All functions in this file must be PCI-depended, or you should out your function
+ in other files.
+
+*/
+#include "../rt_config.h"
+
+extern RTMP_RF_REGS RF2850RegTable[];
+extern UCHAR NUM_OF_2850_CHNL;
+
+USHORT RtmpPCI_WriteTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN BOOLEAN bIsLast,
+ OUT USHORT *FreeNumber)
+{
+
+ UCHAR *pDMAHeaderBufVA;
+ USHORT TxIdx, RetTxIdx;
+ PTXD_STRUC pTxD;
+ UINT32 BufBasePaLow;
+ PRTMP_TX_RING pTxRing;
+ USHORT hwHeaderLen;
+
+ //
+ // get Tx Ring Resource
+ //
+ pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
+ TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
+ pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
+ BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
+
+ // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
+ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+ {
+ hwHeaderLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
+ }
+ else
+ {
+ hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+ }
+ NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
+
+ pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
+ pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
+
+ //
+ // build Tx Descriptor
+ //
+
+ pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+ NdisZeroMemory(pTxD, TXD_SIZE);
+
+ pTxD->SDPtr0 = BufBasePaLow;
+ pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
+ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
+ pTxD->SDLen1 = pTxBlk->SrcBufLen;
+ pTxD->LastSec0 = 0;
+ pTxD->LastSec1 = (bIsLast) ? 1 : 0;
+
+ RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
+
+ RetTxIdx = TxIdx;
+ //
+ // Update Tx index
+ //
+ INC_RING_INDEX(TxIdx, TX_RING_SIZE);
+ pTxRing->TxCpuIdx = TxIdx;
+
+ *FreeNumber -= 1;
+
+ return RetTxIdx;
+}
+
+
+USHORT RtmpPCI_WriteSingleTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN BOOLEAN bIsLast,
+ OUT USHORT *FreeNumber)
+{
+
+ UCHAR *pDMAHeaderBufVA;
+ USHORT TxIdx, RetTxIdx;
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ UINT32 BufBasePaLow;
+ PRTMP_TX_RING pTxRing;
+ USHORT hwHeaderLen;
+
+ //
+ // get Tx Ring Resource
+ //
+ pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
+ TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
+ pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
+ BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
+
+ // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
+ hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+ NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, TXINFO_SIZE + TXWI_SIZE + hwHeaderLen);
+
+ pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
+ pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
+
+ //
+ // build Tx Descriptor
+ //
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+#endif
+ NdisZeroMemory(pTxD, TXD_SIZE);
+
+ pTxD->SDPtr0 = BufBasePaLow;
+ pTxD->SDLen0 = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen; // include padding
+ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
+ pTxD->SDLen1 = pTxBlk->SrcBufLen;
+ pTxD->LastSec0 = 0;
+ pTxD->LastSec1 = (bIsLast) ? 1 : 0;
+
+ RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
+ RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif // RT_BIG_ENDIAN //
+
+ RetTxIdx = TxIdx;
+ //
+ // Update Tx index
+ //
+ INC_RING_INDEX(TxIdx, TX_RING_SIZE);
+ pTxRing->TxCpuIdx = TxIdx;
+
+ *FreeNumber -= 1;
+
+ return RetTxIdx;
+}
+
+
+USHORT RtmpPCI_WriteMultiTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR frameNum,
+ OUT USHORT *FreeNumber)
+{
+ BOOLEAN bIsLast;
+ UCHAR *pDMAHeaderBufVA;
+ USHORT TxIdx, RetTxIdx;
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ UINT32 BufBasePaLow;
+ PRTMP_TX_RING pTxRing;
+ USHORT hwHdrLen;
+ UINT32 firstDMALen;
+
+ bIsLast = ((frameNum == (pTxBlk->TotalFrameNum - 1)) ? 1 : 0);
+
+ //
+ // get Tx Ring Resource
+ //
+ pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
+ TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
+ pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
+ BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
+
+ if (frameNum == 0)
+ {
+ // copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
+ if (pTxBlk->TxFrameType == TX_AMSDU_FRAME)
+ //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_AMSDU_SUBFRAMEHEAD, 4)+LENGTH_AMSDU_SUBFRAMEHEAD;
+ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_AMSDU_SUBFRAMEHEAD + pTxBlk->HdrPadLen + LENGTH_AMSDU_SUBFRAMEHEAD;
+ else if (pTxBlk->TxFrameType == TX_RALINK_FRAME)
+ //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen-LENGTH_ARALINK_HEADER_FIELD, 4)+LENGTH_ARALINK_HEADER_FIELD;
+ hwHdrLen = pTxBlk->MpduHeaderLen - LENGTH_ARALINK_HEADER_FIELD + pTxBlk->HdrPadLen + LENGTH_ARALINK_HEADER_FIELD;
+ else
+ //hwHdrLen = ROUND_UP(pTxBlk->MpduHeaderLen, 4);
+ hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+ firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHdrLen;
+ }
+ else
+ {
+ firstDMALen = pTxBlk->MpduHeaderLen;
+ }
+
+ NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
+
+ pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
+ pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
+
+ //
+ // build Tx Descriptor
+ //
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+#endif
+ NdisZeroMemory(pTxD, TXD_SIZE);
+
+ pTxD->SDPtr0 = BufBasePaLow;
+ pTxD->SDLen0 = firstDMALen; // include padding
+ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);;
+ pTxD->SDLen1 = pTxBlk->SrcBufLen;
+ pTxD->LastSec0 = 0;
+ pTxD->LastSec1 = (bIsLast) ? 1 : 0;
+
+ RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
+
+#ifdef RT_BIG_ENDIAN
+ if (frameNum == 0)
+ RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA+ TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
+
+ if (frameNum != 0)
+ RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
+
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif // RT_BIG_ENDIAN //
+
+ RetTxIdx = TxIdx;
+ //
+ // Update Tx index
+ //
+ INC_RING_INDEX(TxIdx, TX_RING_SIZE);
+ pTxRing->TxCpuIdx = TxIdx;
+
+ *FreeNumber -= 1;
+
+ return RetTxIdx;
+
+}
+
+
+VOID RtmpPCI_FinalWriteTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN USHORT totalMPDUSize,
+ IN USHORT FirstTxIdx)
+{
+
+ PTXWI_STRUC pTxWI;
+ PRTMP_TX_RING pTxRing;
+
+ //
+ // get Tx Ring Resource
+ //
+ pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
+ pTxWI = (PTXWI_STRUC) pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa;
+ pTxWI->MPDUtotalByteCount = totalMPDUSize;
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+#endif // RT_BIG_ENDIAN //
+
+}
+
+
+VOID RtmpPCIDataLastTxIdx(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN USHORT LastTxIdx)
+{
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ PRTMP_TX_RING pTxRing;
+
+ //
+ // get Tx Ring Resource
+ //
+ pTxRing = &pAd->TxRing[QueIdx];
+
+ //
+ // build Tx Descriptor
+ //
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC) pTxRing->Cell[LastTxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+#endif
+
+ pTxD->LastSec1 = 1;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif // RT_BIG_ENDIAN //
+
+}
+
+
+USHORT RtmpPCI_WriteFragTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR fragNum,
+ OUT USHORT *FreeNumber)
+{
+ UCHAR *pDMAHeaderBufVA;
+ USHORT TxIdx, RetTxIdx;
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ UINT32 BufBasePaLow;
+ PRTMP_TX_RING pTxRing;
+ USHORT hwHeaderLen;
+ UINT32 firstDMALen;
+
+ //
+ // Get Tx Ring Resource
+ //
+ pTxRing = &pAd->TxRing[pTxBlk->QueIdx];
+ TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx;
+ pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
+ BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
+
+ //
+ // Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer
+ //
+ hwHeaderLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen;
+
+ firstDMALen = TXINFO_SIZE + TXWI_SIZE + hwHeaderLen;
+ NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen);
+
+
+ //
+ // Build Tx Descriptor
+ //
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+#endif
+ NdisZeroMemory(pTxD, TXD_SIZE);
+
+ if (fragNum == pTxBlk->TotalFragNum)
+ {
+ pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket;
+ pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
+ }
+
+ pTxD->SDPtr0 = BufBasePaLow;
+ pTxD->SDLen0 = firstDMALen; // include padding
+ pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, PCI_DMA_TODEVICE);
+ pTxD->SDLen1 = pTxBlk->SrcBufLen;
+ pTxD->LastSec0 = 0;
+ pTxD->LastSec1 = 1;
+
+ RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
+
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange((PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE), TYPE_TXWI);
+ RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TXINFO_SIZE + TXWI_SIZE), DIR_WRITE, FALSE);
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif // RT_BIG_ENDIAN //
+
+ RetTxIdx = TxIdx;
+ pTxBlk->Priv += pTxBlk->SrcBufLen;
+
+ //
+ // Update Tx index
+ //
+ INC_RING_INDEX(TxIdx, TX_RING_SIZE);
+ pTxRing->TxCpuIdx = TxIdx;
+
+ *FreeNumber -= 1;
+
+ return RetTxIdx;
+
+}
+
+/*
+ Must be run in Interrupt context
+ This function handle PCI specific TxDesc and cpu index update and kick the packet out.
+ */
+int RtmpPCIMgmtKickOut(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pSrcBufVA,
+ IN UINT SrcBufLen)
+{
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ ULONG SwIdx = pAd->MgmtRing.TxCpuIdx;
+
+#ifdef RT_BIG_ENDIAN
+ pDestTxD = (PTXD_STRUC)pAd->MgmtRing.Cell[SwIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#else
+ pTxD = (PTXD_STRUC) pAd->MgmtRing.Cell[SwIdx].AllocVa;
+#endif
+
+ pAd->MgmtRing.Cell[SwIdx].pNdisPacket = pPacket;
+ pAd->MgmtRing.Cell[SwIdx].pNextNdisPacket = NULL;
+
+ RTMPWriteTxDescriptor(pAd, pTxD, TRUE, FIFO_MGMT);
+ pTxD->LastSec0 = 1;
+ pTxD->LastSec1 = 1;
+ pTxD->DMADONE = 0;
+ pTxD->SDLen1 = 0;
+ pTxD->SDPtr0 = PCI_MAP_SINGLE(pAd, pSrcBufVA, SrcBufLen, 0, PCI_DMA_TODEVICE);;
+ pTxD->SDLen0 = SrcBufLen;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif
+
+ pAd->RalinkCounters.KickTxCount++;
+ pAd->RalinkCounters.OneSecTxDoneCount++;
+
+ // Increase TX_CTX_IDX, but write to register later.
+ INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE);
+
+ RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
+
+ return 0;
+}
+
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+ ========================================================================
+
+ Routine Description:
+ Check Rx descriptor, return NDIS_STATUS_FAILURE if any error dound
+
+ Arguments:
+ pRxD Pointer to the Rx descriptor
+
+ Return Value:
+ NDIS_STATUS_SUCCESS No err
+ NDIS_STATUS_FAILURE Error
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTMPCheckRxError(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHeader,
+ IN PRXWI_STRUC pRxWI,
+ IN PRT28XX_RXD_STRUC pRxD)
+{
+ PCIPHER_KEY pWpaKey;
+ INT dBm;
+
+ // Phy errors & CRC errors
+ if (/*(pRxD->PhyErr) ||*/ (pRxD->Crc))
+ {
+ // Check RSSI for Noise Hist statistic collection.
+ dBm = (INT) (pRxWI->RSSI0) - pAd->BbpRssiToDbmDelta;
+ if (dBm <= -87)
+ pAd->StaCfg.RPIDensity[0] += 1;
+ else if (dBm <= -82)
+ pAd->StaCfg.RPIDensity[1] += 1;
+ else if (dBm <= -77)
+ pAd->StaCfg.RPIDensity[2] += 1;
+ else if (dBm <= -72)
+ pAd->StaCfg.RPIDensity[3] += 1;
+ else if (dBm <= -67)
+ pAd->StaCfg.RPIDensity[4] += 1;
+ else if (dBm <= -62)
+ pAd->StaCfg.RPIDensity[5] += 1;
+ else if (dBm <= -57)
+ pAd->StaCfg.RPIDensity[6] += 1;
+ else if (dBm > -57)
+ pAd->StaCfg.RPIDensity[7] += 1;
+
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ // Add Rx size to channel load counter, we should ignore error counts
+ pAd->StaCfg.CLBusyBytes += (pRxD->SDL0 + 14);
+
+ // Drop ToDs promiscous frame, it is opened due to CCX 2 channel load statistics
+ if (pHeader != NULL)
+ {
+ if (pHeader->FC.ToDs)
+ {
+ return(NDIS_STATUS_FAILURE);
+ }
+ }
+
+ // Drop not U2M frames, cant's drop here because we will drop beacon in this case
+ // I am kind of doubting the U2M bit operation
+ // if (pRxD->U2M == 0)
+ // return(NDIS_STATUS_FAILURE);
+
+ // drop decyption fail frame
+ if (pRxD->CipherErr)
+ {
+ if (pRxD->CipherErr == 2)
+ {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV ok but MICErr "));}
+ else if (pRxD->CipherErr == 1)
+ {DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: ICV Err "));}
+ else if (pRxD->CipherErr == 3)
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("pRxD ERROR: Key not valid "));
+
+ if (((pRxD->CipherErr & 1) == 1) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
+ RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE,(" %d (len=%d, Mcast=%d, MyBss=%d, Wcid=%d, KeyId=%d)\n",
+ pRxD->CipherErr,
+ pRxD->SDL0,
+ pRxD->Mcast | pRxD->Bcast,
+ pRxD->MyBss,
+ pRxWI->WirelessCliID,
+ pRxWI->KeyIndex));
+
+ //
+ // MIC Error
+ //
+ if (pRxD->CipherErr == 2)
+ {
+ pWpaKey = &pAd->SharedKey[BSS0][pRxWI->KeyIndex];
+#ifdef WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP)
+ WpaSendMicFailureToWpaSupplicant(pAd,
+ (pWpaKey->Type == PAIRWISEKEY) ? TRUE:FALSE);
+ else
+#endif // WPA_SUPPLICANT_SUPPORT //
+ RTMPReportMicError(pAd, pWpaKey);
+
+ if (((pRxD->CipherErr & 2) == 2) && pAd->CommonCfg.bWirelessEvent && INFRA_ON(pAd))
+ RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error\n"));
+ }
+
+ if (pHeader == NULL)
+ return(NDIS_STATUS_SUCCESS);
+
+ return(NDIS_STATUS_FAILURE);
+ }
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine sends command to firmware and turn our chip to power save mode.
+ Both RadioOff and .11 power save function needs to call this routine.
+ Input:
+ Level = GUIRADIO_OFF : GUI Radio Off mode
+ Level = DOT11POWERSAVE : 802.11 power save mode
+ Level = RTMP_HALT : When Disable device.
+
+ ==========================================================================
+ */
+VOID RT28xxPciAsicRadioOff(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Level,
+ IN USHORT TbttNumToNextWakeUp)
+{
+ WPDMA_GLO_CFG_STRUC DmaCfg;
+ UCHAR i, tempBBP_R3 = 0;
+ BOOLEAN brc = FALSE, Cancelled;
+ UINT32 TbTTTime = 0;
+ UINT32 PsPollTime = 0, MACValue;
+ ULONG BeaconPeriodTime;
+ UINT32 RxDmaIdx, RxCpuIdx;
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, pAd->RxRing.RxCpuIdx, pAd->RxRing.RxDmaIdx));
+
+ // Check Rx DMA busy status, if more than half is occupied, give up this radio off.
+ RTMP_IO_READ32(pAd, RX_DRX_IDX , &RxDmaIdx);
+ RTMP_IO_READ32(pAd, RX_CRX_IDX , &RxCpuIdx);
+ if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return1. RxDmaIdx = %d , RxCpuIdx = %d. \n", RxDmaIdx, RxCpuIdx));
+ return;
+ }
+ else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicRadioOff ===> return2. RxCpuIdx = %d. RxDmaIdx = %d , \n", RxCpuIdx, RxDmaIdx));
+ return;
+ }
+
+ // Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.
+ pAd->bPCIclkOffDisableTx = TRUE;
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
+
+ if (Level == DOT11POWERSAVE)
+ {
+ RTMP_IO_READ32(pAd, TBTT_TIMER, &TbTTTime);
+ TbTTTime &= 0x1ffff;
+ // 00. check if need to do sleep in this DTIM period. If next beacon will arrive within 30ms , ...doesn't necessarily sleep.
+ // TbTTTime uint = 64us, LEAD_TIME unit = 1024us, PsPollTime unit = 1ms
+ if (((64*TbTTTime) <((LEAD_TIME*1024) + 40000)) && (TbttNumToNextWakeUp == 0))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("TbTTTime = 0x%x , give up this sleep. \n", TbTTTime));
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+ pAd->bPCIclkOffDisableTx = FALSE;
+ return;
+ }
+ else
+ {
+ PsPollTime = (64*TbTTTime- LEAD_TIME*1024)/1000;
+ PsPollTime -= 3;
+
+ BeaconPeriodTime = pAd->CommonCfg.BeaconPeriod*102/100;
+ if (TbttNumToNextWakeUp > 0)
+ PsPollTime += ((TbttNumToNextWakeUp -1) * BeaconPeriodTime);
+
+ pAd->Mlme.bPsPollTimerRunning = TRUE;
+ RTMPSetTimer(&pAd->Mlme.PsPollTimer, PsPollTime);
+ }
+ }
+ }
+
+ // 0. Disable Tx DMA.
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
+ DmaCfg.field.EnableTxDMA = 0;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
+
+ // 1. Wait DMA not busy
+ i = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
+ if ((DmaCfg.field.TxDMABusy == 0) && (DmaCfg.field.RxDMABusy == 0))
+ break;
+ RTMPusecDelay(20);
+ i++;
+ }while(i < 50);
+
+ if (i >= 50)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("DMA keeps busy. return on RT28xxPciAsicRadioOff ()\n"));
+ pAd->bPCIclkOffDisableTx = FALSE;
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
+ DmaCfg.field.EnableTxDMA = 1;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
+ return;
+ }
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
+
+ // Set to 1R.
+ tempBBP_R3 = (pAd->StaCfg.BBPR3 & 0xE7);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, tempBBP_R3);
+
+ // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
+ if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
+ && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+ {
+ // Must using 40MHz.
+ AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
+ }
+ else
+ {
+ // Must using 20MHz.
+ AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
+ }
+
+ // When PCI clock is off, don't want to service interrupt.
+ RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt);
+
+ RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
+ // Disable MAC Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
+ MACValue &= 0xf7;
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
+
+ // 2. Send Sleep command
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
+ AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us.
+ // 2-1. Wait command success
+ // Status = 1 : success, Status = 2, already sleep, Status = 3, Maybe MAC is busy so can't finish this task.
+ brc = AsicCheckCommanOk(pAd, PowerSafeCID);
+
+ if (brc == FALSE)
+ {
+ // try again
+ AsicSendCommandToMcu(pAd, 0x30, PowerSafeCID, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout unit:40us.
+ //RTMPusecDelay(200);
+ brc = AsicCheckCommanOk(pAd, PowerSafeCID);
+ }
+
+ // 3. After 0x30 command is ok, send radio off command. lowbyte = 0 for power safe.
+ // If 0x30 command is not ok this time, we can ignore 0x35 command. It will make sure not cause firmware'r problem.
+ if ((Level == DOT11POWERSAVE) && (brc == TRUE))
+ {
+ AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 0, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
+ // 3-1. Wait command success
+ AsicCheckCommanOk(pAd, PowerRadioOffCID);
+ }
+ else if (brc == TRUE)
+ {
+ AsicSendCommandToMcu(pAd, 0x35, PowerRadioOffCID, 1, 0x00); // lowbyte = 0 means to do power safe, NOT turn off radio.
+ // 3-1. Wait command success
+ AsicCheckCommanOk(pAd, PowerRadioOffCID);
+ }
+
+ // Wait DMA not busy
+ i = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
+ if (DmaCfg.field.RxDMABusy == 0)
+ break;
+ RTMPusecDelay(20);
+ i++;
+ }while(i < 50);
+
+ if (i >= 50)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("DMA Rx keeps busy. on RT28xxPciAsicRadioOff ()\n"));
+ }
+ // disable DMA Rx.
+ {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
+ DmaCfg.field.EnableRxDMA = 0;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
+ }
+
+ if (Level == DOT11POWERSAVE)
+ {
+ AUTO_WAKEUP_STRUC AutoWakeupCfg;
+ //RTMPSetTimer(&pAd->Mlme.PsPollTimer, 90);
+
+ // we have decided to SLEEP, so at least do it for a BEACON period.
+ if (TbttNumToNextWakeUp == 0)
+ TbttNumToNextWakeUp = 1;
+
+ AutoWakeupCfg.word = 0;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+
+ // 1. Set auto wake up timer.
+ AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
+ AutoWakeupCfg.field.EnableAutoWakeup = 1;
+ AutoWakeupCfg.field.AutoLeadTime = LEAD_TIME;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+ }
+
+ // 4-1. If it's to disable our device. Need to restore PCI Configuration Space to its original value.
+ if (Level == RTMP_HALT)
+ {
+ if ((brc == TRUE) && (i < 50))
+ RTMPPCIeLinkCtrlSetting(pAd, 1);
+ }
+ // 4. Set PCI configuration Space Link Comtrol fields. Only Radio Off needs to call this function
+ else
+ {
+ if ((brc == TRUE) && (i < 50))
+ RTMPPCIeLinkCtrlSetting(pAd, 3);
+ }
+
+ pAd->bPCIclkOffDisableTx = FALSE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ This routine sends command to firmware and turn our chip to wake up mode from power save mode.
+ Both RadioOn and .11 power save function needs to call this routine.
+ Input:
+ Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value.
+ Level = other value : normal wake up function.
+
+ ==========================================================================
+ */
+BOOLEAN RT28xxPciAsicRadioOn(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Level)
+{
+ WPDMA_GLO_CFG_STRUC DmaCfg;
+ BOOLEAN Cancelled, brv = TRUE;
+ UINT32 MACValue;
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ pAd->Mlme.bPsPollTimerRunning = FALSE;
+ RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
+ if ((Level == GUIRADIO_OFF) || (Level == GUI_IDLE_POWER_SAVE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RT28xxPciAsicRadioOn ()\n"));
+ // 1. Set PCI Link Control in Configuration Space.
+ RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
+ RTMPusecDelay(6000);
+ }
+ }
+
+ pAd->bPCIclkOff = FALSE;
+
+ // 2. Send wake up command.
+ AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00);
+
+ // 2-1. wait command ok.
+ brv = AsicCheckCommanOk(pAd, PowerWakeCID);
+ if (brv)
+ {
+ //RTMP_IO_WRITE32(pAd, INT_MASK_CSR, (DELAYINTMASK|RxINT));
+ NICEnableInterrupt(pAd);
+
+ // 3. Enable Tx DMA.
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
+ DmaCfg.field.EnableTxDMA = 1;
+ DmaCfg.field.EnableRxDMA = 1;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
+
+ // Eable MAC Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL , &MACValue);
+ MACValue |= 0x8;
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , MACValue);
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
+ if (Level == GUI_IDLE_POWER_SAVE)
+ {
+ // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
+ if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
+ && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+ {
+ // Must using 40MHz.
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+ }
+ else
+ {
+ // Must using 20MHz.
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ }
+ }
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+VOID RT28xxPciStaAsicForceWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bFromTx)
+{
+ AUTO_WAKEUP_STRUC AutoWakeupCfg;
+
+ if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ return;
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
+ return;
+ }
+
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ // Support PCIe Advance Power Save
+ if (bFromTx == TRUE)
+ {
+ pAd->Mlme.bPsPollTimerRunning = FALSE;
+ RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
+ RTMPusecDelay(3000);
+ DBGPRINT(RT_DEBUG_TRACE, ("=======AsicForceWakeup===bFromTx\n"));
+ }
+
+ AutoWakeupCfg.word = 0;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+
+ if (RT28xxPciAsicRadioOn(pAd, DOT11POWERSAVE))
+ {
+ // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
+ if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
+ && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+ {
+ // Must using 40MHz.
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+ }
+ else
+ {
+ // Must using 20MHz.
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ }
+ }
+ }
+ else
+ {
+ // PCI, 2860-PCIe
+ AsicSendCommandToMcu(pAd, 0x31, 0xff, 0x00, 0x00);
+ AutoWakeupCfg.word = 0;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+ }
+
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
+ DBGPRINT(RT_DEBUG_TRACE, ("<=======RT28xxPciStaAsicForceWakeup\n"));
+}
+
+VOID RT28xxPciStaAsicSleepThenAutoWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT TbttNumToNextWakeUp)
+{
+ if (pAd->StaCfg.bRadio == FALSE)
+ {
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+ return;
+ }
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ ULONG Now = 0;
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WAKEUP_NOW))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("waking up now!\n"));
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+ return;
+ }
+
+ NdisGetSystemUpTime(&Now);
+ // If last send NULL fram time is too close to this receiving beacon (within 8ms), don't go to sleep for this DTM.
+ // Because Some AP can't queuing outgoing frames immediately.
+ if (((pAd->Mlme.LastSendNULLpsmTime + 8) >= Now) && (pAd->Mlme.LastSendNULLpsmTime <= Now))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu : RxCountSinceLastNULL = %lu. \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
+ return;
+ }
+ else if ((pAd->RalinkCounters.RxCountSinceLastNULL > 0) && ((pAd->Mlme.LastSendNULLpsmTime + pAd->CommonCfg.BeaconPeriod) >= Now))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Now = %lu, LastSendNULLpsmTime=%lu: RxCountSinceLastNULL = %lu > 0 \n", Now, pAd->Mlme.LastSendNULLpsmTime, pAd->RalinkCounters.RxCountSinceLastNULL));
+ return;
+ }
+
+ RT28xxPciAsicRadioOff(pAd, DOT11POWERSAVE, TbttNumToNextWakeUp);
+ }
+ else
+ {
+ AUTO_WAKEUP_STRUC AutoWakeupCfg;
+ // we have decided to SLEEP, so at least do it for a BEACON period.
+ if (TbttNumToNextWakeUp == 0)
+ TbttNumToNextWakeUp = 1;
+
+ AutoWakeupCfg.word = 0;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+ AutoWakeupCfg.field.NumofSleepingTbtt = TbttNumToNextWakeUp - 1;
+ AutoWakeupCfg.field.EnableAutoWakeup = 1;
+ AutoWakeupCfg.field.AutoLeadTime = 5;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+ AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x00); // send POWER-SAVE command to MCU. Timeout 40us.
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- %s, TbttNumToNextWakeUp=%d \n", __func__, TbttNumToNextWakeUp));
+ }
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_DOZE);
+}
+
+VOID PsPollWakeExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+ unsigned long flags;
+
+ DBGPRINT(RT_DEBUG_TRACE,("-->PsPollWakeExec \n"));
+ RTMP_INT_LOCK(&pAd->irq_lock, flags);
+ if (pAd->Mlme.bPsPollTimerRunning)
+ {
+ RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
+ }
+ pAd->Mlme.bPsPollTimerRunning = FALSE;
+ RTMP_INT_UNLOCK(&pAd->irq_lock, flags);
+}
+
+VOID RadioOnExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+ WPDMA_GLO_CFG_STRUC DmaCfg;
+ BOOLEAN Cancelled;
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on fOP_STATUS_DOZE == TRUE; \n"));
+ RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
+ return;
+ }
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("-->RadioOnExec() return on SCAN_IN_PROGRESS; \n"));
+ RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
+ return;
+ }
+ pAd->Mlme.bPsPollTimerRunning = FALSE;
+ RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
+ if (pAd->StaCfg.bRadio == TRUE)
+ {
+ pAd->bPCIclkOff = FALSE;
+ RTMPRingCleanUp(pAd, QID_AC_BK);
+ RTMPRingCleanUp(pAd, QID_AC_BE);
+ RTMPRingCleanUp(pAd, QID_AC_VI);
+ RTMPRingCleanUp(pAd, QID_AC_VO);
+ RTMPRingCleanUp(pAd, QID_HCCA);
+ RTMPRingCleanUp(pAd, QID_MGMT);
+ RTMPRingCleanUp(pAd, QID_RX);
+
+ // 2. Send wake up command.
+ AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x02);
+ // 2-1. wait command ok.
+ AsicCheckCommanOk(pAd, PowerWakeCID);
+
+ // When PCI clock is off, don't want to service interrupt. So when back to clock on, enable interrupt.
+ NICEnableInterrupt(pAd);
+
+ // 3. Enable Tx DMA.
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &DmaCfg.word);
+ DmaCfg.field.EnableTxDMA = 1;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, DmaCfg.word);
+
+ // In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.
+ if (INFRA_ON(pAd) && (pAd->CommonCfg.CentralChannel != pAd->CommonCfg.Channel)
+ && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+ {
+ // Must using 40MHz.
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+ }
+ else
+ {
+ // Must using 20MHz.
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ }
+
+ // Clear Radio off flag
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+ // Set LED
+ RTMPSetLED(pAd, LED_RADIO_ON);
+
+ if (pAd->StaCfg.Psm == PWR_ACTIVE)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, pAd->StaCfg.BBPR3);
+ }
+ }
+ else
+ {
+ RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0);
+ }
+}
+
+#endif // CONFIG_STA_SUPPORT //
+
+VOID RT28xxPciMlmeRadioOn(
+ IN PRTMP_ADAPTER pAd)
+{
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
+
+ if ((pAd->OpMode == OPMODE_AP) ||
+ ((pAd->OpMode == OPMODE_STA) && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))))
+ {
+ NICResetFromError(pAd);
+
+ RTMPRingCleanUp(pAd, QID_AC_BK);
+ RTMPRingCleanUp(pAd, QID_AC_BE);
+ RTMPRingCleanUp(pAd, QID_AC_VI);
+ RTMPRingCleanUp(pAd, QID_AC_VO);
+ RTMPRingCleanUp(pAd, QID_HCCA);
+ RTMPRingCleanUp(pAd, QID_MGMT);
+ RTMPRingCleanUp(pAd, QID_RX);
+
+ // Enable Tx/Rx
+ RTMPEnableRxTx(pAd);
+
+ // Clear Radio off flag
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+ // Set LED
+ RTMPSetLED(pAd, LED_RADIO_ON);
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ if ((pAd->OpMode == OPMODE_STA) &&
+ (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)))
+ {
+ BOOLEAN Cancelled;
+
+ RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_WAKEUP);
+
+ pAd->Mlme.bPsPollTimerRunning = FALSE;
+ RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
+ RTMPSetTimer(&pAd->Mlme.RadioOnOffTimer, 10);
+ }
+#endif // CONFIG_STA_SUPPORT //
+}
+
+VOID RT28xxPciMlmeRadioOFF(
+ IN PRTMP_ADAPTER pAd)
+{
+ WPDMA_GLO_CFG_STRUC GloCfg;
+ UINT32 i;
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __func__));
+
+ // Set LED
+ RTMPSetLED(pAd, LED_RADIO_OFF);
+ // Set Radio off flag
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ BOOLEAN Cancelled;
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+ {
+ RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+ }
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ BOOLEAN Cancelled;
+ pAd->Mlme.bPsPollTimerRunning = FALSE;
+ RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
+ }
+
+ // Link down first if any association exists
+ if (INFRA_ON(pAd) || ADHOC_ON(pAd))
+ LinkDown(pAd, FALSE);
+ RTMPusecDelay(10000);
+ //==========================================
+ // Clean up old bss table
+ BssTableInit(&pAd->ScanTab);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // Disable Tx/Rx DMA
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
+ GloCfg.field.EnableTxDMA = 0;
+ GloCfg.field.EnableRxDMA = 0;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings
+
+
+ // MAC_SYS_CTRL => value = 0x0 => 40mA
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0);
+
+ // PWR_PIN_CFG => value = 0x0 => 40mA
+ RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0);
+
+ // TX_PIN_CFG => value = 0x0 => 20mA
+ RTMP_IO_WRITE32(pAd, TX_PIN_CFG, 0);
+
+ if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+ {
+ // Must using 40MHz.
+ AsicTurnOffRFClk(pAd, pAd->CommonCfg.CentralChannel);
+ }
+ else
+ {
+ // Must using 20MHz.
+ AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel);
+ }
+
+ // Waiting for DMA idle
+ i = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+ if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
+ break;
+
+ RTMPusecDelay(1000);
+ }while (i++ < 100);
+}
diff --git a/drivers/staging/rt2860/common/cmm_info.c b/drivers/staging/rt2860/common/cmm_info.c
new file mode 100644
index 000000000000..dd92ac6eaed2
--- /dev/null
+++ b/drivers/staging/rt2860/common/cmm_info.c
@@ -0,0 +1,3417 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+*/
+
+#include "../rt_config.h"
+
+INT Show_SSID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_WirelessMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_TxBurst_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_TxPreamble_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_TxPower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_Channel_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_BGProtection_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_RTSThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_FragThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+#ifdef DOT11_N_SUPPORT
+INT Show_HtBw_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtMcs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtGi_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtOpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtExtcha_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtMpduDensity_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtBaWinSize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtRdg_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtAmsdu_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_HtAutoBa_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+#endif // DOT11_N_SUPPORT //
+
+INT Show_CountryRegion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_CountryRegionABand_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_CountryCode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+#ifdef AGGREGATION_SUPPORT
+INT Show_PktAggregate_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+#endif // AGGREGATION_SUPPORT //
+
+#ifdef WMM_SUPPORT
+INT Show_WmmCapable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+#endif // WMM_SUPPORT //
+
+INT Show_IEEE80211H_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+#ifdef CONFIG_STA_SUPPORT
+INT Show_NetworkType_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+#endif // CONFIG_STA_SUPPORT //
+
+INT Show_AuthMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_EncrypType_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_DefaultKeyID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_Key1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_Key2_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_Key3_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_Key4_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+INT Show_WPAPSK_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf);
+
+static struct {
+ CHAR *name;
+ INT (*show_proc)(PRTMP_ADAPTER pAdapter, PUCHAR arg);
+} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = {
+ {"SSID", Show_SSID_Proc},
+ {"WirelessMode", Show_WirelessMode_Proc},
+ {"TxBurst", Show_TxBurst_Proc},
+ {"TxPreamble", Show_TxPreamble_Proc},
+ {"TxPower", Show_TxPower_Proc},
+ {"Channel", Show_Channel_Proc},
+ {"BGProtection", Show_BGProtection_Proc},
+ {"RTSThreshold", Show_RTSThreshold_Proc},
+ {"FragThreshold", Show_FragThreshold_Proc},
+#ifdef DOT11_N_SUPPORT
+ {"HtBw", Show_HtBw_Proc},
+ {"HtMcs", Show_HtMcs_Proc},
+ {"HtGi", Show_HtGi_Proc},
+ {"HtOpMode", Show_HtOpMode_Proc},
+ {"HtExtcha", Show_HtExtcha_Proc},
+ {"HtMpduDensity", Show_HtMpduDensity_Proc},
+ {"HtBaWinSize", Show_HtBaWinSize_Proc},
+ {"HtRdg", Show_HtRdg_Proc},
+ {"HtAmsdu", Show_HtAmsdu_Proc},
+ {"HtAutoBa", Show_HtAutoBa_Proc},
+#endif // DOT11_N_SUPPORT //
+ {"CountryRegion", Show_CountryRegion_Proc},
+ {"CountryRegionABand", Show_CountryRegionABand_Proc},
+ {"CountryCode", Show_CountryCode_Proc},
+#ifdef AGGREGATION_SUPPORT
+ {"PktAggregate", Show_PktAggregate_Proc},
+#endif
+
+#ifdef WMM_SUPPORT
+ {"WmmCapable", Show_WmmCapable_Proc},
+#endif
+ {"IEEE80211H", Show_IEEE80211H_Proc},
+#ifdef CONFIG_STA_SUPPORT
+ {"NetworkType", Show_NetworkType_Proc},
+#endif // CONFIG_STA_SUPPORT //
+ {"AuthMode", Show_AuthMode_Proc},
+ {"EncrypType", Show_EncrypType_Proc},
+ {"DefaultKeyID", Show_DefaultKeyID_Proc},
+ {"Key1", Show_Key1_Proc},
+ {"Key2", Show_Key2_Proc},
+ {"Key3", Show_Key3_Proc},
+ {"Key4", Show_Key4_Proc},
+ {"WPAPSK", Show_WPAPSK_Proc},
+ {NULL, NULL}
+};
+
+/*
+ ==========================================================================
+ Description:
+ Get Driver version.
+
+ Return:
+ ==========================================================================
+*/
+INT Set_DriverVersion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ DBGPRINT(RT_DEBUG_TRACE, ("Driver version-%s\n", STA_DRIVER_VERSION));
+#endif // CONFIG_STA_SUPPORT //
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Country Region.
+ This command will not work, if the field of CountryRegion in eeprom is programmed.
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_CountryRegion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG region;
+
+ region = simple_strtol(arg, 0, 10);
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ return -EOPNOTSUPP;
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+ // Country can be set only when EEPROM not programmed
+ if (pAd->CommonCfg.CountryRegion & 0x80)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameter of CountryRegion in eeprom is programmed \n"));
+ return FALSE;
+ }
+
+ if((region >= 0) && (region <= REGION_MAXIMUM_BG_BAND))
+ {
+ pAd->CommonCfg.CountryRegion = (UCHAR) region;
+ }
+ else if (region == REGION_31_BG_BAND)
+ {
+ pAd->CommonCfg.CountryRegion = (UCHAR) region;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegion_Proc::parameters out of range\n"));
+ return FALSE;
+ }
+
+ // if set country region, driver needs to be reset
+ BuildChannelList(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegion_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegion));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Country Region for A band.
+ This command will not work, if the field of CountryRegion in eeprom is programmed.
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_CountryRegionABand_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG region;
+
+ region = simple_strtol(arg, 0, 10);
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ return -EOPNOTSUPP;
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+ // Country can be set only when EEPROM not programmed
+ if (pAd->CommonCfg.CountryRegionForABand & 0x80)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameter of CountryRegion in eeprom is programmed \n"));
+ return FALSE;
+ }
+
+ if((region >= 0) && (region <= REGION_MAXIMUM_A_BAND))
+ {
+ pAd->CommonCfg.CountryRegionForABand = (UCHAR) region;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryRegionABand_Proc::parameters out of range\n"));
+ return FALSE;
+ }
+
+ // if set country region, driver needs to be reset
+ BuildChannelList(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Wireless Mode
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_WirelessMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG WirelessMode;
+ INT success = TRUE;
+
+ WirelessMode = simple_strtol(arg, 0, 10);
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ INT MaxPhyMode = PHY_11G;
+
+#ifdef DOT11_N_SUPPORT
+ MaxPhyMode = PHY_11N_5G;
+#endif // DOT11_N_SUPPORT //
+
+ if (WirelessMode <= MaxPhyMode)
+ {
+ RTMPSetPhyMode(pAd, WirelessMode);
+#ifdef DOT11_N_SUPPORT
+ if (WirelessMode >= PHY_11ABGN_MIXED)
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+ pAd->CommonCfg.REGBACapability.field.AutoBA = TRUE;
+ }
+ else
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+ pAd->CommonCfg.REGBACapability.field.AutoBA = FALSE;
+ }
+#endif // DOT11_N_SUPPORT //
+ // Set AdhocMode rates
+ if (pAd->StaCfg.BssType == BSS_ADHOC)
+ {
+ MlmeUpdateTxRates(pAd, FALSE, 0);
+ MakeIbssBeacon(pAd); // re-build BEACON frame
+ AsicEnableIbssSync(pAd); // copy to on-chip memory
+ }
+ }
+ else
+ {
+ success = FALSE;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // it is needed to set SSID to take effect
+ if (success == TRUE)
+ {
+#ifdef DOT11_N_SUPPORT
+ SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_WirelessMode_Proc::(=%ld)\n", WirelessMode));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n"));
+ }
+
+ return success;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Channel
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_Channel_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ INT success = TRUE;
+ UCHAR Channel;
+
+ Channel = (UCHAR) simple_strtol(arg, 0, 10);
+
+ // check if this channel is valid
+ if (ChannelSanity(pAd, Channel) == TRUE)
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pAd->CommonCfg.Channel = Channel;
+
+ if (MONITOR_ON(pAd))
+ {
+#ifdef DOT11_N_SUPPORT
+ N_ChannelCheck(pAd);
+ if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED &&
+ pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+ {
+ N_SetCenCh(pAd);
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+ DBGPRINT(RT_DEBUG_TRACE, ("BW_40, control_channel(%d), CentralChannel(%d) \n",
+ pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel));
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ DBGPRINT(RT_DEBUG_TRACE, ("BW_20, Channel(%d)\n", pAd->CommonCfg.Channel));
+ }
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+ success = TRUE;
+ }
+ else
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ success = FALSE;
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+
+ if (success == TRUE)
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel));
+
+ return success;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Short Slot Time Enable or Disable
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ShortSlot_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG ShortSlot;
+
+ ShortSlot = simple_strtol(arg, 0, 10);
+
+ if (ShortSlot == 1)
+ pAd->CommonCfg.bUseShortSlotTime = TRUE;
+ else if (ShortSlot == 0)
+ pAd->CommonCfg.bUseShortSlotTime = FALSE;
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ShortSlot_Proc::(ShortSlot=%d)\n", pAd->CommonCfg.bUseShortSlotTime));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Tx power
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_TxPower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG TxPower;
+ INT success = FALSE;
+
+ TxPower = (ULONG) simple_strtol(arg, 0, 10);
+ if (TxPower <= 100)
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pAd->CommonCfg.TxPowerDefault = TxPower;
+ pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ success = TRUE;
+ }
+ else
+ success = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage));
+
+ return success;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set 11B/11G Protection
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_BGProtection_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ switch (simple_strtol(arg, 0, 10))
+ {
+ case 0: //AUTO
+ pAd->CommonCfg.UseBGProtection = 0;
+ break;
+ case 1: //Always On
+ pAd->CommonCfg.UseBGProtection = 1;
+ break;
+ case 2: //Always OFF
+ pAd->CommonCfg.UseBGProtection = 2;
+ break;
+ default: //Invalid argument
+ return FALSE;
+ }
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_BGProtection_Proc::(BGProtection=%ld)\n", pAd->CommonCfg.UseBGProtection));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set TxPreamble
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_TxPreamble_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ RT_802_11_PREAMBLE Preamble;
+
+ Preamble = simple_strtol(arg, 0, 10);
+
+
+ switch (Preamble)
+ {
+ case Rt802_11PreambleShort:
+ pAd->CommonCfg.TxPreamble = Preamble;
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ MlmeSetTxPreamble(pAd, Rt802_11PreambleShort);
+#endif // CONFIG_STA_SUPPORT //
+ break;
+ case Rt802_11PreambleLong:
+#ifdef CONFIG_STA_SUPPORT
+ case Rt802_11PreambleAuto:
+ // if user wants AUTO, initialize to LONG here, then change according to AP's
+ // capability upon association.
+#endif // CONFIG_STA_SUPPORT //
+ pAd->CommonCfg.TxPreamble = Preamble;
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ MlmeSetTxPreamble(pAd, Rt802_11PreambleLong);
+#endif // CONFIG_STA_SUPPORT //
+ break;
+ default: //Invalid argument
+ return FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPreamble_Proc::(TxPreamble=%ld)\n", pAd->CommonCfg.TxPreamble));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set RTS Threshold
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_RTSThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ NDIS_802_11_RTS_THRESHOLD RtsThresh;
+
+ RtsThresh = simple_strtol(arg, 0, 10);
+
+ if((RtsThresh > 0) && (RtsThresh <= MAX_RTS_THRESHOLD))
+ pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh;
+#ifdef CONFIG_STA_SUPPORT
+ else if (RtsThresh == 0)
+ pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD;
+#endif // CONFIG_STA_SUPPORT //
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_RTSThreshold_Proc::(RTSThreshold=%d)\n", pAd->CommonCfg.RtsThreshold));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set Fragment Threshold
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_FragThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ NDIS_802_11_FRAGMENTATION_THRESHOLD FragThresh;
+
+ FragThresh = simple_strtol(arg, 0, 10);
+
+ if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+ {
+ //Illegal FragThresh so we set it to default
+ pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+ }
+ else if (FragThresh % 2 == 1)
+ {
+ // The length of each fragment shall always be an even number of octets, except for the last fragment
+ // of an MSDU or MMPDU, which may be either an even or an odd number of octets.
+ pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1);
+ }
+ else
+ {
+ pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (pAd->CommonCfg.FragmentThreshold == MAX_FRAG_THRESHOLD)
+ pAd->CommonCfg.bUseZeroToDisableFragment = TRUE;
+ else
+ pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_FragThreshold_Proc::(FragThreshold=%d)\n", pAd->CommonCfg.FragmentThreshold));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set TxBurst
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_TxBurst_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG TxBurst;
+
+ TxBurst = simple_strtol(arg, 0, 10);
+ if (TxBurst == 1)
+ pAd->CommonCfg.bEnableTxBurst = TRUE;
+ else if (TxBurst == 0)
+ pAd->CommonCfg.bEnableTxBurst = FALSE;
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_TxBurst_Proc::(TxBurst=%d)\n", pAd->CommonCfg.bEnableTxBurst));
+
+ return TRUE;
+}
+
+#ifdef AGGREGATION_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ Set TxBurst
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_PktAggregate_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG aggre;
+
+ aggre = simple_strtol(arg, 0, 10);
+
+ if (aggre == 1)
+ pAd->CommonCfg.bAggregationCapable = TRUE;
+ else if (aggre == 0)
+ pAd->CommonCfg.bAggregationCapable = FALSE;
+ else
+ return FALSE; //Invalid argument
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable));
+
+ return TRUE;
+}
+#endif
+
+/*
+ ==========================================================================
+ Description:
+ Set IEEE80211H.
+ This parameter is 1 when needs radar detection, otherwise 0
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_IEEE80211H_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG ieee80211h;
+
+ ieee80211h = simple_strtol(arg, 0, 10);
+
+ if (ieee80211h == 1)
+ pAd->CommonCfg.bIEEE80211H = TRUE;
+ else if (ieee80211h == 0)
+ pAd->CommonCfg.bIEEE80211H = FALSE;
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_IEEE80211H_Proc::(IEEE80211H=%d)\n", pAd->CommonCfg.bIEEE80211H));
+
+ return TRUE;
+}
+
+
+#ifdef DBG
+/*
+ ==========================================================================
+ Description:
+ For Debug information
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_Debug_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("==> Set_Debug_Proc *******************\n"));
+
+ if(simple_strtol(arg, 0, 10) <= RT_DEBUG_LOUD)
+ RTDebugLevel = simple_strtol(arg, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== Set_Debug_Proc(RTDebugLevel = %ld)\n", RTDebugLevel));
+
+ return TRUE;
+}
+#endif
+
+INT Show_DescInfo_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+#ifdef RT2860
+ INT i, QueIdx=0;
+ PRT28XX_RXD_STRUC pRxD;
+ PTXD_STRUC pTxD;
+ PRTMP_TX_RING pTxRing = &pAd->TxRing[QueIdx];
+ PRTMP_MGMT_RING pMgmtRing = &pAd->MgmtRing;
+ PRTMP_RX_RING pRxRing = &pAd->RxRing;
+
+ for(i=0;i<TX_RING_SIZE;i++)
+ {
+ pTxD = (PTXD_STRUC) pTxRing->Cell[i].AllocVa;
+ printk("Desc #%d\n",i);
+ hex_dump("Tx Descriptor", (char *)pTxD, 16);
+ printk("pTxD->DMADONE = %x\n", pTxD->DMADONE);
+ }
+ printk("---------------------------------------------------\n");
+ for(i=0;i<MGMT_RING_SIZE;i++)
+ {
+ pTxD = (PTXD_STRUC) pMgmtRing->Cell[i].AllocVa;
+ printk("Desc #%d\n",i);
+ hex_dump("Mgmt Descriptor", (char *)pTxD, 16);
+ printk("pMgmt->DMADONE = %x\n", pTxD->DMADONE);
+ }
+ printk("---------------------------------------------------\n");
+ for(i=0;i<RX_RING_SIZE;i++)
+ {
+ pRxD = (PRT28XX_RXD_STRUC) pRxRing->Cell[i].AllocVa;
+ printk("Desc #%d\n",i);
+ hex_dump("Rx Descriptor", (char *)pRxD, 16);
+ printk("pRxD->DDONE = %x\n", pRxD->DDONE);
+ }
+#endif // RT2860 //
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Reset statistics counter
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ arg
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ResetStatCounter_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n"));
+
+ // add the most up-to-date h/w raw counters into software counters
+ NICUpdateRawCounters(pAd);
+
+ NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11));
+ NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3));
+ NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK));
+
+ return TRUE;
+}
+
+BOOLEAN RTMPCheckStrPrintAble(
+ IN CHAR *pInPutStr,
+ IN UCHAR strLen)
+{
+ UCHAR i=0;
+
+ for (i=0; i<strLen; i++)
+ {
+ if ((pInPutStr[i] < 0x21) ||
+ (pInPutStr[i] > 0x7E))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Remove WPA Key process
+
+ Arguments:
+ pAd Pointer to our adapter
+ pBuf Pointer to the where the key stored
+
+ Return Value:
+ NDIS_SUCCESS Add key successfully
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPSetDesiredRates(
+ IN PRTMP_ADAPTER pAdapter,
+ IN LONG Rates)
+{
+ NDIS_802_11_RATES aryRates;
+
+ memset(&aryRates, 0x00, sizeof(NDIS_802_11_RATES));
+ switch (pAdapter->CommonCfg.PhyMode)
+ {
+ case PHY_11A: // A only
+ switch (Rates)
+ {
+ case 6000000: //6M
+ aryRates[0] = 0x0c; // 6M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0;
+ break;
+ case 9000000: //9M
+ aryRates[0] = 0x12; // 9M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1;
+ break;
+ case 12000000: //12M
+ aryRates[0] = 0x18; // 12M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2;
+ break;
+ case 18000000: //18M
+ aryRates[0] = 0x24; // 18M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3;
+ break;
+ case 24000000: //24M
+ aryRates[0] = 0x30; // 24M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4;
+ break;
+ case 36000000: //36M
+ aryRates[0] = 0x48; // 36M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5;
+ break;
+ case 48000000: //48M
+ aryRates[0] = 0x60; // 48M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6;
+ break;
+ case 54000000: //54M
+ aryRates[0] = 0x6c; // 54M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7;
+ break;
+ case -1: //Auto
+ default:
+ aryRates[0] = 0x6c; // 54Mbps
+ aryRates[1] = 0x60; // 48Mbps
+ aryRates[2] = 0x48; // 36Mbps
+ aryRates[3] = 0x30; // 24Mbps
+ aryRates[4] = 0x24; // 18M
+ aryRates[5] = 0x18; // 12M
+ aryRates[6] = 0x12; // 9M
+ aryRates[7] = 0x0c; // 6M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+ break;
+ }
+ break;
+ case PHY_11BG_MIXED: // B/G Mixed
+ case PHY_11B: // B only
+ case PHY_11ABG_MIXED: // A/B/G Mixed
+ default:
+ switch (Rates)
+ {
+ case 1000000: //1M
+ aryRates[0] = 0x02;
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0;
+ break;
+ case 2000000: //2M
+ aryRates[0] = 0x04;
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1;
+ break;
+ case 5000000: //5.5M
+ aryRates[0] = 0x0b; // 5.5M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2;
+ break;
+ case 11000000: //11M
+ aryRates[0] = 0x16; // 11M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3;
+ break;
+ case 6000000: //6M
+ aryRates[0] = 0x0c; // 6M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_0;
+ break;
+ case 9000000: //9M
+ aryRates[0] = 0x12; // 9M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_1;
+ break;
+ case 12000000: //12M
+ aryRates[0] = 0x18; // 12M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_2;
+ break;
+ case 18000000: //18M
+ aryRates[0] = 0x24; // 18M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_3;
+ break;
+ case 24000000: //24M
+ aryRates[0] = 0x30; // 24M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_4;
+ break;
+ case 36000000: //36M
+ aryRates[0] = 0x48; // 36M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_5;
+ break;
+ case 48000000: //48M
+ aryRates[0] = 0x60; // 48M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_6;
+ break;
+ case 54000000: //54M
+ aryRates[0] = 0x6c; // 54M
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_7;
+ break;
+ case -1: //Auto
+ default:
+ if (pAdapter->CommonCfg.PhyMode == PHY_11B)
+ { //B Only
+ aryRates[0] = 0x16; // 11Mbps
+ aryRates[1] = 0x0b; // 5.5Mbps
+ aryRates[2] = 0x04; // 2Mbps
+ aryRates[3] = 0x02; // 1Mbps
+ }
+ else
+ { //(B/G) Mixed or (A/B/G) Mixed
+ aryRates[0] = 0x6c; // 54Mbps
+ aryRates[1] = 0x60; // 48Mbps
+ aryRates[2] = 0x48; // 36Mbps
+ aryRates[3] = 0x30; // 24Mbps
+ aryRates[4] = 0x16; // 11Mbps
+ aryRates[5] = 0x0b; // 5.5Mbps
+ aryRates[6] = 0x04; // 2Mbps
+ aryRates[7] = 0x02; // 1Mbps
+ }
+ pAdapter->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+ break;
+ }
+ break;
+ }
+
+ NdisZeroMemory(pAdapter->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+ NdisMoveMemory(pAdapter->CommonCfg.DesireRate, &aryRates, sizeof(NDIS_802_11_RATES));
+ DBGPRINT(RT_DEBUG_TRACE, (" RTMPSetDesiredRates (%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x)\n",
+ pAdapter->CommonCfg.DesireRate[0],pAdapter->CommonCfg.DesireRate[1],
+ pAdapter->CommonCfg.DesireRate[2],pAdapter->CommonCfg.DesireRate[3],
+ pAdapter->CommonCfg.DesireRate[4],pAdapter->CommonCfg.DesireRate[5],
+ pAdapter->CommonCfg.DesireRate[6],pAdapter->CommonCfg.DesireRate[7] ));
+ // Changing DesiredRate may affect the MAX TX rate we used to TX frames out
+ MlmeUpdateTxRates(pAdapter, FALSE, 0);
+}
+
+NDIS_STATUS RTMPWPARemoveKeyProc(
+ IN PRTMP_ADAPTER pAd,
+ IN PVOID pBuf)
+{
+ PNDIS_802_11_REMOVE_KEY pKey;
+ ULONG KeyIdx;
+ NDIS_STATUS Status = NDIS_STATUS_FAILURE;
+ BOOLEAN bTxKey; // Set the key as transmit key
+ BOOLEAN bPairwise; // Indicate the key is pairwise key
+ BOOLEAN bKeyRSC; // indicate the receive SC set by KeyRSC value.
+ // Otherwise, it will set by the NIC.
+ BOOLEAN bAuthenticator; // indicate key is set by authenticator.
+ INT i;
+
+ DBGPRINT(RT_DEBUG_TRACE,("---> RTMPWPARemoveKeyProc\n"));
+
+ pKey = (PNDIS_802_11_REMOVE_KEY) pBuf;
+ KeyIdx = pKey->KeyIndex & 0xff;
+ // Bit 31 of Add-key, Tx Key
+ bTxKey = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE;
+ // Bit 30 of Add-key PairwiseKey
+ bPairwise = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE;
+ // Bit 29 of Add-key KeyRSC
+ bKeyRSC = (pKey->KeyIndex & 0x20000000) ? TRUE : FALSE;
+ // Bit 28 of Add-key Authenticator
+ bAuthenticator = (pKey->KeyIndex & 0x10000000) ? TRUE : FALSE;
+
+ // 1. If bTx is TRUE, return failure information
+ if (bTxKey == TRUE)
+ return(NDIS_STATUS_INVALID_DATA);
+
+ // 2. Check Pairwise Key
+ if (bPairwise)
+ {
+ // a. If BSSID is broadcast, remove all pairwise keys.
+ // b. If not broadcast, remove the pairwise specified by BSSID
+ for (i = 0; i < SHARE_KEY_NUM; i++)
+ {
+ if (MAC_ADDR_EQUAL(pAd->SharedKey[BSS0][i].BssId, pKey->BSSID))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%d)\n", i));
+ pAd->SharedKey[BSS0][i].KeyLen = 0;
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE;
+ AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)i);
+ Status = NDIS_STATUS_SUCCESS;
+ break;
+ }
+ }
+ }
+ // 3. Group Key
+ else
+ {
+ // a. If BSSID is broadcast, remove all group keys indexed
+ // b. If BSSID matched, delete the group key indexed.
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveKeyProc(KeyIdx=%ld)\n", KeyIdx));
+ pAd->SharedKey[BSS0][KeyIdx].KeyLen = 0;
+ pAd->SharedKey[BSS0][KeyIdx].CipherAlg = CIPHER_NONE;
+ AsicRemoveSharedKeyEntry(pAd, BSS0, (UCHAR)KeyIdx);
+ Status = NDIS_STATUS_SUCCESS;
+ }
+
+ return (Status);
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+ ========================================================================
+
+ Routine Description:
+ Remove All WPA Keys
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPWPARemoveAllKeys(
+ IN PRTMP_ADAPTER pAd)
+{
+
+ UCHAR i;
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPWPARemoveAllKeys(AuthMode=%d, WepStatus=%d)\n", pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus));
+
+ // For WEP/CKIP, there is no need to remove it, since WinXP won't set it again after
+ // Link up. And it will be replaced if user changed it.
+ if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+ return;
+
+ // For WPA-None, there is no need to remove it, since WinXP won't set it again after
+ // Link up. And it will be replaced if user changed it.
+ if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+ return;
+
+ // set BSSID wcid entry of the Pair-wise Key table as no-security mode
+ AsicRemovePairwiseKeyEntry(pAd, BSS0, BSSID_WCID);
+
+ // set all shared key mode as no-security.
+ for (i = 0; i < SHARE_KEY_NUM; i++)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("remove %s key #%d\n", CipherName[pAd->SharedKey[BSS0][i].CipherAlg], i));
+ NdisZeroMemory(&pAd->SharedKey[BSS0][i], sizeof(CIPHER_KEY));
+
+ AsicRemoveSharedKeyEntry(pAd, BSS0, i);
+ }
+
+}
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+ ========================================================================
+ Routine Description:
+ Change NIC PHY mode. Re-association may be necessary. possible settings
+ include - PHY_11B, PHY_11BG_MIXED, PHY_11A, and PHY_11ABG_MIXED
+
+ Arguments:
+ pAd - Pointer to our adapter
+ phymode -
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPSetPhyMode(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG phymode)
+{
+ INT i;
+ // the selected phymode must be supported by the RF IC encoded in E2PROM
+
+ // if no change, do nothing
+ /* bug fix
+ if (pAd->CommonCfg.PhyMode == phymode)
+ return;
+ */
+ pAd->CommonCfg.PhyMode = (UCHAR)phymode;
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPSetPhyMode : PhyMode=%d, channel=%d \n", pAd->CommonCfg.PhyMode, pAd->CommonCfg.Channel));
+#ifdef EXT_BUILD_CHANNEL_LIST
+ BuildChannelListEx(pAd);
+#else
+ BuildChannelList(pAd);
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+ // sanity check user setting
+ for (i = 0; i < pAd->ChannelListNum; i++)
+ {
+ if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel)
+ break;
+ }
+
+ if (i == pAd->ChannelListNum)
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ pAd->CommonCfg.Channel = FirstChannel(pAd);
+#endif // CONFIG_STA_SUPPORT //
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetPhyMode: channel is out of range, use first channel=%d \n", pAd->CommonCfg.Channel));
+ }
+
+ NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+ NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES);
+ NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES);
+ switch (phymode) {
+ case PHY_11B:
+ pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRateLen = 4;
+ pAd->CommonCfg.ExtRateLen = 0;
+ pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps
+ //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; // This MODE is only FYI. not use
+ break;
+
+ case PHY_11G:
+ case PHY_11BG_MIXED:
+ case PHY_11ABG_MIXED:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11N_2_4G:
+ case PHY_11ABGN_MIXED:
+ case PHY_11BGN_MIXED:
+ case PHY_11GN_MIXED:
+#endif // DOT11_N_SUPPORT //
+ pAd->CommonCfg.SupRate[0] = 0x82; // 1 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[1] = 0x84; // 2 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[2] = 0x8B; // 5.5 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[3] = 0x96; // 11 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[4] = 0x12; // 9 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRate[5] = 0x24; // 18 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRate[6] = 0x48; // 36 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRateLen = 8;
+ pAd->CommonCfg.ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.ExtRate[1] = 0x18; // 12 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.ExtRate[2] = 0x30; // 24 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.ExtRate[3] = 0x60; // 48 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.ExtRateLen = 4;
+ pAd->CommonCfg.DesireRate[0] = 2; // 1 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[1] = 4; // 2 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[2] = 11; // 5.5 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[3] = 22; // 11 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[4] = 12; // 6 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[5] = 18; // 9 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[6] = 24; // 12 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[7] = 36; // 18 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[8] = 48; // 24 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[9] = 72; // 36 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[10] = 96; // 48 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[11] = 108; // 54 mbps, in units of 0.5 Mbps
+ break;
+
+ case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11AN_MIXED:
+ case PHY_11AGN_MIXED:
+ case PHY_11N_5G:
+#endif // DOT11_N_SUPPORT //
+ pAd->CommonCfg.SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate
+ pAd->CommonCfg.SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.SupRateLen = 8;
+ pAd->CommonCfg.ExtRateLen = 0;
+ pAd->CommonCfg.DesireRate[0] = 12; // 6 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[1] = 18; // 9 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[2] = 24; // 12 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[3] = 36; // 18 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[4] = 48; // 24 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[5] = 72; // 36 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[6] = 96; // 48 mbps, in units of 0.5 Mbps
+ pAd->CommonCfg.DesireRate[7] = 108; // 54 mbps, in units of 0.5 Mbps
+ //pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; // This MODE is only FYI. not use
+ break;
+
+ default:
+ break;
+ }
+
+
+ pAd->CommonCfg.BandState = UNKNOWN_BAND;
+}
+
+
+#ifdef DOT11_N_SUPPORT
+/*
+ ========================================================================
+ Routine Description:
+ Caller ensures we has 802.11n support.
+ Calls at setting HT from AP/STASetinformation
+
+ Arguments:
+ pAd - Pointer to our adapter
+ phymode -
+
+ ========================================================================
+*/
+VOID RTMPSetHT(
+ IN PRTMP_ADAPTER pAd,
+ IN OID_SET_HT_PHYMODE *pHTPhyMode)
+{
+ //ULONG *pmcs;
+ UINT32 Value = 0;
+ UCHAR BBPValue = 0;
+ UCHAR BBP3Value = 0;
+ UCHAR RxStream = pAd->CommonCfg.RxStream;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : HT_mode(%d), ExtOffset(%d), MCS(%d), BW(%d), STBC(%d), SHORTGI(%d)\n",
+ pHTPhyMode->HtMode, pHTPhyMode->ExtOffset,
+ pHTPhyMode->MCS, pHTPhyMode->BW,
+ pHTPhyMode->STBC, pHTPhyMode->SHORTGI));
+
+ // Don't zero supportedHyPhy structure.
+ RTMPZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability));
+ RTMPZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo));
+ RTMPZeroMemory(&pAd->CommonCfg.NewExtChanOffset, sizeof(pAd->CommonCfg.NewExtChanOffset));
+ RTMPZeroMemory(&pAd->CommonCfg.DesiredHtPhy, sizeof(pAd->CommonCfg.DesiredHtPhy));
+
+ if (pAd->CommonCfg.bRdg)
+ {
+ pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 1;
+ pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 1;
+ }
+ else
+ {
+ pAd->CommonCfg.HtCapability.ExtHtCapInfo.PlusHTC = 0;
+ pAd->CommonCfg.HtCapability.ExtHtCapInfo.RDGSupport = 0;
+ }
+
+ pAd->CommonCfg.HtCapability.HtCapParm.MaxRAmpduFactor = 3;
+ pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor = 3;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : RxBAWinLimit = %d\n", pAd->CommonCfg.BACapability.field.RxBAWinLimit));
+
+ // Mimo power save, A-MSDU size,
+ pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable;
+ pAd->CommonCfg.DesiredHtPhy.AmsduSize = (UCHAR)pAd->CommonCfg.BACapability.field.AmsduSize;
+ pAd->CommonCfg.DesiredHtPhy.MimoPs = (UCHAR)pAd->CommonCfg.BACapability.field.MMPSmode;
+ pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+
+ pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+ pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+ pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetHT : AMsduSize = %d, MimoPs = %d, MpduDensity = %d, MaxRAmpduFactor = %d\n",
+ pAd->CommonCfg.DesiredHtPhy.AmsduSize,
+ pAd->CommonCfg.DesiredHtPhy.MimoPs,
+ pAd->CommonCfg.DesiredHtPhy.MpduDensity,
+ pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor));
+
+ if(pHTPhyMode->HtMode == HTMODE_GF)
+ {
+ pAd->CommonCfg.HtCapability.HtCapInfo.GF = 1;
+ pAd->CommonCfg.DesiredHtPhy.GF = 1;
+ }
+ else
+ pAd->CommonCfg.DesiredHtPhy.GF = 0;
+
+ // Decide Rx MCSSet
+ switch (RxStream)
+ {
+ case 1:
+ pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff;
+ pAd->CommonCfg.HtCapability.MCSSet[1] = 0x00;
+ break;
+
+ case 2:
+ pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff;
+ pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff;
+ break;
+
+ case 3: // 3*3
+ pAd->CommonCfg.HtCapability.MCSSet[0] = 0xff;
+ pAd->CommonCfg.HtCapability.MCSSet[1] = 0xff;
+ pAd->CommonCfg.HtCapability.MCSSet[2] = 0xff;
+ break;
+ }
+
+ if (pAd->CommonCfg.bForty_Mhz_Intolerant && (pAd->CommonCfg.Channel <= 14) && (pHTPhyMode->BW == BW_40) )
+ {
+ pHTPhyMode->BW = BW_20;
+ pAd->CommonCfg.HtCapability.HtCapInfo.Forty_Mhz_Intolerant = 1;
+ }
+
+ if(pHTPhyMode->BW == BW_40)
+ {
+ pAd->CommonCfg.HtCapability.MCSSet[4] = 0x1; // MCS 32
+ pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 1;
+ if (pAd->CommonCfg.Channel <= 14)
+ pAd->CommonCfg.HtCapability.HtCapInfo.CCKmodein40 = 1;
+
+ pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 1;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = (pHTPhyMode->ExtOffset == EXTCHA_BELOW)? (EXTCHA_BELOW): EXTCHA_ABOVE;
+ // Set Regsiter for extension channel position.
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBP3Value);
+ if ((pHTPhyMode->ExtOffset == EXTCHA_BELOW))
+ {
+ Value |= 0x1;
+ BBP3Value |= (0x20);
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+ }
+ else if ((pHTPhyMode->ExtOffset == EXTCHA_ABOVE))
+ {
+ Value &= 0xfe;
+ BBP3Value &= (~0x20);
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+ }
+
+ // Turn on BBP 40MHz mode now only as AP .
+ // Sta can turn on BBP 40MHz after connection with 40MHz AP. Sta only broadcast 40MHz capability before connection.
+ if ((pAd->OpMode == OPMODE_AP) || INFRA_ON(pAd) || ADHOC_ON(pAd)
+ )
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+ BBPValue &= (~0x18);
+ BBPValue |= 0x10;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBP3Value);
+ pAd->CommonCfg.BBPCurrentBW = BW_40;
+ }
+ }
+ else
+ {
+ pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = 0;
+ pAd->CommonCfg.DesiredHtPhy.ChannelWidth = 0;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = EXTCHA_NONE;
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+ // Turn on BBP 20MHz mode by request here.
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+ BBPValue &= (~0x18);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+ pAd->CommonCfg.BBPCurrentBW = BW_20;
+ }
+ }
+
+ if(pHTPhyMode->STBC == STBC_USE)
+ {
+ pAd->CommonCfg.HtCapability.HtCapInfo.TxSTBC = 1;
+ pAd->CommonCfg.DesiredHtPhy.TxSTBC = 1;
+ pAd->CommonCfg.HtCapability.HtCapInfo.RxSTBC = 1;
+ pAd->CommonCfg.DesiredHtPhy.RxSTBC = 1;
+ }
+ else
+ {
+ pAd->CommonCfg.DesiredHtPhy.TxSTBC = 0;
+ pAd->CommonCfg.DesiredHtPhy.RxSTBC = 0;
+ }
+
+
+ if(pHTPhyMode->SHORTGI == GI_400)
+ {
+ pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 1;
+ pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 1;
+ pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 1;
+ pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 1;
+ }
+ else
+ {
+ pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor20 = 0;
+ pAd->CommonCfg.HtCapability.HtCapInfo.ShortGIfor40 = 0;
+ pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 = 0;
+ pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 = 0;
+ }
+
+ // We support link adaptation for unsolicit MCS feedback, set to 2.
+ pAd->CommonCfg.HtCapability.ExtHtCapInfo.MCSFeedback = MCSFBK_NONE; //MCSFBK_UNSOLICIT;
+ pAd->CommonCfg.AddHTInfo.ControlChan = pAd->CommonCfg.Channel;
+ // 1, the extension channel above the control channel.
+
+ // EDCA parameters used for AP's own transmission
+ if (pAd->CommonCfg.APEdcaParm.bValid == FALSE)
+ {
+ pAd->CommonCfg.APEdcaParm.bValid = TRUE;
+ pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3;
+ pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7;
+ pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1;
+ pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1;
+
+ pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4;
+ pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4;
+ pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3;
+ pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2;
+
+ pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6;
+ pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10;
+ pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4;
+ pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3;
+
+ pAd->CommonCfg.APEdcaParm.Txop[0] = 0;
+ pAd->CommonCfg.APEdcaParm.Txop[1] = 0;
+ pAd->CommonCfg.APEdcaParm.Txop[2] = 94;
+ pAd->CommonCfg.APEdcaParm.Txop[3] = 47;
+ }
+ AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ RTMPSetIndividualHT(pAd, 0);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Caller ensures we has 802.11n support.
+ Calls at setting HT from AP/STASetinformation
+
+ Arguments:
+ pAd - Pointer to our adapter
+ phymode -
+
+ ========================================================================
+*/
+VOID RTMPSetIndividualHT(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apidx)
+{
+ PRT_HT_PHY_INFO pDesired_ht_phy = NULL;
+ UCHAR TxStream = pAd->CommonCfg.TxStream;
+ UCHAR DesiredMcs = MCS_AUTO;
+
+ do
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pDesired_ht_phy = &pAd->StaCfg.DesiredHtPhyInfo;
+ DesiredMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
+ //pAd->StaCfg.bAutoTxRateSwitch = (DesiredMcs == MCS_AUTO) ? TRUE : FALSE;
+ break;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ } while (FALSE);
+
+ if (pDesired_ht_phy == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPSetIndividualHT: invalid apidx(%d)\n", apidx));
+ return;
+ }
+ RTMPZeroMemory(pDesired_ht_phy, sizeof(RT_HT_PHY_INFO));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetIndividualHT : Desired MCS = %d\n", DesiredMcs));
+ // Check the validity of MCS
+ if ((TxStream == 1) && ((DesiredMcs >= MCS_8) && (DesiredMcs <= MCS_15)))
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS(%d) is invalid in 1S, reset it as MCS_7\n", DesiredMcs));
+ DesiredMcs = MCS_7;
+ }
+
+ if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_20) && (DesiredMcs == MCS_32))
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("RTMPSetIndividualHT: MCS_32 is only supported in 40-MHz, reset it as MCS_0\n"));
+ DesiredMcs = MCS_0;
+ }
+
+ pDesired_ht_phy->bHtEnable = TRUE;
+
+ // Decide desired Tx MCS
+ switch (TxStream)
+ {
+ case 1:
+ if (DesiredMcs == MCS_AUTO)
+ {
+ pDesired_ht_phy->MCSSet[0]= 0xff;
+ pDesired_ht_phy->MCSSet[1]= 0x00;
+ }
+ else if (DesiredMcs <= MCS_7)
+ {
+ pDesired_ht_phy->MCSSet[0]= 1<<DesiredMcs;
+ pDesired_ht_phy->MCSSet[1]= 0x00;
+ }
+ break;
+
+ case 2:
+ if (DesiredMcs == MCS_AUTO)
+ {
+ pDesired_ht_phy->MCSSet[0]= 0xff;
+ pDesired_ht_phy->MCSSet[1]= 0xff;
+ }
+ else if (DesiredMcs <= MCS_15)
+ {
+ ULONG mode;
+
+ mode = DesiredMcs / 8;
+ if (mode < 2)
+ pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8));
+ }
+ break;
+
+ case 3: // 3*3
+ if (DesiredMcs == MCS_AUTO)
+ {
+ /* MCS0 ~ MCS23, 3 bytes */
+ pDesired_ht_phy->MCSSet[0]= 0xff;
+ pDesired_ht_phy->MCSSet[1]= 0xff;
+ pDesired_ht_phy->MCSSet[2]= 0xff;
+ }
+ else if (DesiredMcs <= MCS_23)
+ {
+ ULONG mode;
+
+ mode = DesiredMcs / 8;
+ if (mode < 3)
+ pDesired_ht_phy->MCSSet[mode] = (1 << (DesiredMcs - mode * 8));
+ }
+ break;
+ }
+
+ if(pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BW_40)
+ {
+ if (DesiredMcs == MCS_AUTO || DesiredMcs == MCS_32)
+ pDesired_ht_phy->MCSSet[4] = 0x1;
+ }
+
+ // update HT Rate setting
+ if (pAd->OpMode == OPMODE_STA)
+ MlmeUpdateHtTxRates(pAd, BSS0);
+ else
+ MlmeUpdateHtTxRates(pAd, apidx);
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ Update HT IE from our capability.
+
+ Arguments:
+ Send all HT IE in beacon/probe rsp/assoc rsp/action frame.
+
+
+ ========================================================================
+*/
+VOID RTMPUpdateHTIE(
+ IN RT_HT_CAPABILITY *pRtHt,
+ IN UCHAR *pMcsSet,
+ OUT HT_CAPABILITY_IE *pHtCapability,
+ OUT ADD_HT_INFO_IE *pAddHtInfo)
+{
+ RTMPZeroMemory(pHtCapability, sizeof(HT_CAPABILITY_IE));
+ RTMPZeroMemory(pAddHtInfo, sizeof(ADD_HT_INFO_IE));
+
+ pHtCapability->HtCapInfo.ChannelWidth = pRtHt->ChannelWidth;
+ pHtCapability->HtCapInfo.MimoPs = pRtHt->MimoPs;
+ pHtCapability->HtCapInfo.GF = pRtHt->GF;
+ pHtCapability->HtCapInfo.ShortGIfor20 = pRtHt->ShortGIfor20;
+ pHtCapability->HtCapInfo.ShortGIfor40 = pRtHt->ShortGIfor40;
+ pHtCapability->HtCapInfo.TxSTBC = pRtHt->TxSTBC;
+ pHtCapability->HtCapInfo.RxSTBC = pRtHt->RxSTBC;
+ pHtCapability->HtCapInfo.AMsduSize = pRtHt->AmsduSize;
+ pHtCapability->HtCapParm.MaxRAmpduFactor = pRtHt->MaxRAmpduFactor;
+ pHtCapability->HtCapParm.MpduDensity = pRtHt->MpduDensity;
+
+ pAddHtInfo->AddHtInfo.ExtChanOffset = pRtHt->ExtChanOffset ;
+ pAddHtInfo->AddHtInfo.RecomWidth = pRtHt->RecomWidth;
+ pAddHtInfo->AddHtInfo2.OperaionMode = pRtHt->OperaionMode;
+ pAddHtInfo->AddHtInfo2.NonGfPresent = pRtHt->NonGfPresent;
+ RTMPMoveMemory(pAddHtInfo->MCSSet, /*pRtHt->MCSSet*/pMcsSet, 4); // rt2860 only support MCS max=32, no need to copy all 16 uchar.
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPUpdateHTIE <== \n"));
+}
+#endif // DOT11_N_SUPPORT //
+
+/*
+ ========================================================================
+ Description:
+ Add Client security information into ASIC WCID table and IVEIV table.
+ Return:
+ ========================================================================
+*/
+VOID RTMPAddWcidAttributeEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIdx,
+ IN UCHAR KeyIdx,
+ IN UCHAR CipherAlg,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ UINT32 WCIDAttri = 0;
+ USHORT offset;
+ UCHAR IVEIV = 0;
+ USHORT Wcid = 0;
+
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (BssIdx > BSS0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for Infra link. \n", BssIdx));
+ return;
+ }
+
+ // 1. In ADHOC mode, the AID is wcid number. And NO mesh link exists.
+ // 2. In Infra mode, the AID:1 MUST be wcid of infra STA.
+ // the AID:2~ assign to mesh link entry.
+ if (pEntry && ADHOC_ON(pAd))
+ Wcid = pEntry->Aid;
+ else if (pEntry && INFRA_ON(pAd))
+ {
+#ifdef QOS_DLS_SUPPORT
+ if (pEntry->ValidAsDls == TRUE)
+ Wcid = pEntry->Aid;
+ else
+#endif // QOS_DLS_SUPPORT //
+ Wcid = BSSID_WCID;
+ }
+ else
+ Wcid = MCAST_WCID;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ // Update WCID attribute table
+ offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (pEntry && pEntry->ValidAsMesh)
+ WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE;
+#ifdef QOS_DLS_SUPPORT
+ else if ((pEntry) && (pEntry->ValidAsDls) &&
+ ((CipherAlg == CIPHER_TKIP) ||
+ (CipherAlg == CIPHER_TKIP_NO_MIC) ||
+ (CipherAlg == CIPHER_AES) ||
+ (CipherAlg == CIPHER_NONE)))
+ WCIDAttri = (CipherAlg<<1) | PAIRWISEKEYTABLE;
+#endif // QOS_DLS_SUPPORT //
+ else
+ WCIDAttri = (CipherAlg<<1) | SHAREDKEYTABLE;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+
+
+ // Update IV/EIV table
+ offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE);
+
+ // WPA mode
+ if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) || (CipherAlg == CIPHER_AES))
+ {
+ // Eiv bit on. keyid always is 0 for pairwise key
+ IVEIV = (KeyIdx <<6) | 0x20;
+ }
+ else
+ {
+ // WEP KeyIdx is default tx key.
+ IVEIV = (KeyIdx << 6);
+ }
+
+ // For key index and ext IV bit, so only need to update the position(offset+3).
+#ifdef RT2860
+ RTMP_IO_WRITE8(pAd, offset+3, IVEIV);
+#endif // RT2860 //
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg]));
+ DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri));
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ Parse encryption type
+Arguments:
+ pAdapter Pointer to our adapter
+ wrq Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ ==========================================================================
+*/
+CHAR *GetEncryptType(CHAR enc)
+{
+ if(enc == Ndis802_11WEPDisabled)
+ return "NONE";
+ if(enc == Ndis802_11WEPEnabled)
+ return "WEP";
+ if(enc == Ndis802_11Encryption2Enabled)
+ return "TKIP";
+ if(enc == Ndis802_11Encryption3Enabled)
+ return "AES";
+ if(enc == Ndis802_11Encryption4Enabled)
+ return "TKIPAES";
+ else
+ return "UNKNOW";
+}
+
+CHAR *GetAuthMode(CHAR auth)
+{
+ if(auth == Ndis802_11AuthModeOpen)
+ return "OPEN";
+ if(auth == Ndis802_11AuthModeShared)
+ return "SHARED";
+ if(auth == Ndis802_11AuthModeAutoSwitch)
+ return "AUTOWEP";
+ if(auth == Ndis802_11AuthModeWPA)
+ return "WPA";
+ if(auth == Ndis802_11AuthModeWPAPSK)
+ return "WPAPSK";
+ if(auth == Ndis802_11AuthModeWPANone)
+ return "WPANONE";
+ if(auth == Ndis802_11AuthModeWPA2)
+ return "WPA2";
+ if(auth == Ndis802_11AuthModeWPA2PSK)
+ return "WPA2PSK";
+ if(auth == Ndis802_11AuthModeWPA1WPA2)
+ return "WPA1WPA2";
+ if(auth == Ndis802_11AuthModeWPA1PSKWPA2PSK)
+ return "WPA1PSKWPA2PSK";
+
+ return "UNKNOW";
+}
+
+#if 1 //#ifndef UCOS
+/*
+ ==========================================================================
+ Description:
+ Get site survey results
+ Arguments:
+ pAdapter Pointer to our adapter
+ wrq Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ Usage:
+ 1.) UI needs to wait 4 seconds after issue a site survey command
+ 2.) iwpriv ra0 get_site_survey
+ 3.) UI needs to prepare at least 4096bytes to get the results
+ ==========================================================================
+*/
+#define LINE_LEN (4+33+20+8+10+9+7+3) // Channel+SSID+Bssid+WepStatus+AuthMode+Signal+WiressMode+NetworkType
+VOID RTMPIoctlGetSiteSurvey(
+ IN PRTMP_ADAPTER pAdapter,
+ IN struct iwreq *wrq)
+{
+ CHAR *msg;
+ INT i=0;
+ INT WaitCnt;
+ INT Status=0;
+ CHAR Ssid[MAX_LEN_OF_SSID +1];
+ INT Rssi = 0, max_len = LINE_LEN;
+ UINT Rssi_Quality = 0;
+ NDIS_802_11_NETWORK_TYPE wireless_mode;
+
+ os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len));
+
+ if (msg == NULL)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - msg memory alloc fail.\n"));
+ return;
+ }
+
+ memset(msg, 0 ,(MAX_LEN_OF_BSS_TABLE)*max_len );
+ memset(Ssid, 0 ,(MAX_LEN_OF_SSID +1));
+ sprintf(msg,"%s","\n");
+ sprintf(msg+strlen(msg),"%-4s%-33s%-20s%-8s%-10s%-9s%-7s%-3s\n",
+ "Ch", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", " NT");
+
+ WaitCnt = 0;
+#ifdef CONFIG_STA_SUPPORT
+ pAdapter->StaCfg.bScanReqIsFromWebUI = TRUE;
+ while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200))
+ OS_WAIT(500);
+#endif // CONFIG_STA_SUPPORT //
+
+ for(i=0; i<pAdapter->ScanTab.BssNr ;i++)
+ {
+ if( pAdapter->ScanTab.BssEntry[i].Channel==0)
+ break;
+
+ if((strlen(msg)+max_len ) >= IW_SCAN_MAX_DATA)
+ break;
+
+ //Channel
+ sprintf(msg+strlen(msg),"%-4d", pAdapter->ScanTab.BssEntry[i].Channel);
+ //SSID
+ memcpy(Ssid, pAdapter->ScanTab.BssEntry[i].Ssid, pAdapter->ScanTab.BssEntry[i].SsidLen);
+ Ssid[pAdapter->ScanTab.BssEntry[i].SsidLen] = '\0';
+ sprintf(msg+strlen(msg),"%-33s", Ssid);
+ //BSSID
+ sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ",
+ pAdapter->ScanTab.BssEntry[i].Bssid[0],
+ pAdapter->ScanTab.BssEntry[i].Bssid[1],
+ pAdapter->ScanTab.BssEntry[i].Bssid[2],
+ pAdapter->ScanTab.BssEntry[i].Bssid[3],
+ pAdapter->ScanTab.BssEntry[i].Bssid[4],
+ pAdapter->ScanTab.BssEntry[i].Bssid[5]);
+ //Encryption Type
+ sprintf(msg+strlen(msg),"%-8s",GetEncryptType(pAdapter->ScanTab.BssEntry[i].WepStatus));
+ //Authentication Mode
+ if (pAdapter->ScanTab.BssEntry[i].WepStatus == Ndis802_11WEPEnabled)
+ sprintf(msg+strlen(msg),"%-10s", "UNKNOW");
+ else
+ sprintf(msg+strlen(msg),"%-10s",GetAuthMode(pAdapter->ScanTab.BssEntry[i].AuthMode));
+ // Rssi
+ Rssi = (INT)pAdapter->ScanTab.BssEntry[i].Rssi;
+ if (Rssi >= -50)
+ Rssi_Quality = 100;
+ else if (Rssi >= -80) // between -50 ~ -80dbm
+ Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10);
+ else if (Rssi >= -90) // between -80 ~ -90dbm
+ Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10);
+ else // < -84 dbm
+ Rssi_Quality = 0;
+ sprintf(msg+strlen(msg),"%-9d", Rssi_Quality);
+ // Wireless Mode
+ wireless_mode = NetworkTypeInUseSanity(&pAdapter->ScanTab.BssEntry[i]);
+ if (wireless_mode == Ndis802_11FH ||
+ wireless_mode == Ndis802_11DS)
+ sprintf(msg+strlen(msg),"%-7s", "11b");
+ else if (wireless_mode == Ndis802_11OFDM5)
+ sprintf(msg+strlen(msg),"%-7s", "11a");
+ else if (wireless_mode == Ndis802_11OFDM5_N)
+ sprintf(msg+strlen(msg),"%-7s", "11a/n");
+ else if (wireless_mode == Ndis802_11OFDM24)
+ sprintf(msg+strlen(msg),"%-7s", "11b/g");
+ else if (wireless_mode == Ndis802_11OFDM24_N)
+ sprintf(msg+strlen(msg),"%-7s", "11b/g/n");
+ else
+ sprintf(msg+strlen(msg),"%-7s", "unknow");
+ //Network Type
+ if (pAdapter->ScanTab.BssEntry[i].BssType == BSS_ADHOC)
+ sprintf(msg+strlen(msg),"%-3s", " Ad");
+ else
+ sprintf(msg+strlen(msg),"%-3s", " In");
+
+ sprintf(msg+strlen(msg),"\n");
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ pAdapter->StaCfg.bScanReqIsFromWebUI = FALSE;
+#endif // CONFIG_STA_SUPPORT //
+ wrq->u.data.length = strlen(msg);
+ Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", wrq->u.data.length));
+ os_free_mem(NULL, (PUCHAR)msg);
+}
+
+
+#define MAC_LINE_LEN (14+4+4+10+10+10+6+6) // Addr+aid+psm+datatime+rxbyte+txbyte+current tx rate+last tx rate
+VOID RTMPIoctlGetMacTable(
+ IN PRTMP_ADAPTER pAd,
+ IN struct iwreq *wrq)
+{
+ INT i;
+ RT_802_11_MAC_TABLE MacTab;
+ char *msg;
+
+ MacTab.Num = 0;
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (pAd->MacTab.Content[i].ValidAsCLI && (pAd->MacTab.Content[i].Sst == SST_ASSOC))
+ {
+ COPY_MAC_ADDR(MacTab.Entry[MacTab.Num].Addr, &pAd->MacTab.Content[i].Addr);
+ MacTab.Entry[MacTab.Num].Aid = (UCHAR)pAd->MacTab.Content[i].Aid;
+ MacTab.Entry[MacTab.Num].Psm = pAd->MacTab.Content[i].PsMode;
+#ifdef DOT11_N_SUPPORT
+ MacTab.Entry[MacTab.Num].MimoPs = pAd->MacTab.Content[i].MmpsMode;
+#endif // DOT11_N_SUPPORT //
+
+ // Fill in RSSI per entry
+ MacTab.Entry[MacTab.Num].AvgRssi0 = pAd->MacTab.Content[i].RssiSample.AvgRssi0;
+ MacTab.Entry[MacTab.Num].AvgRssi1 = pAd->MacTab.Content[i].RssiSample.AvgRssi1;
+ MacTab.Entry[MacTab.Num].AvgRssi2 = pAd->MacTab.Content[i].RssiSample.AvgRssi2;
+
+ // the connected time per entry
+ MacTab.Entry[MacTab.Num].ConnectedTime = pAd->MacTab.Content[i].StaConnectTime;
+ MacTab.Entry[MacTab.Num].TxRate.field.MCS = pAd->MacTab.Content[i].HTPhyMode.field.MCS;
+ MacTab.Entry[MacTab.Num].TxRate.field.BW = pAd->MacTab.Content[i].HTPhyMode.field.BW;
+ MacTab.Entry[MacTab.Num].TxRate.field.ShortGI = pAd->MacTab.Content[i].HTPhyMode.field.ShortGI;
+ MacTab.Entry[MacTab.Num].TxRate.field.STBC = pAd->MacTab.Content[i].HTPhyMode.field.STBC;
+ MacTab.Entry[MacTab.Num].TxRate.field.rsv = pAd->MacTab.Content[i].HTPhyMode.field.rsv;
+ MacTab.Entry[MacTab.Num].TxRate.field.MODE = pAd->MacTab.Content[i].HTPhyMode.field.MODE;
+ MacTab.Entry[MacTab.Num].TxRate.word = pAd->MacTab.Content[i].HTPhyMode.word;
+
+ MacTab.Num += 1;
+ }
+ }
+ wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE);
+ if (copy_to_user(wrq->u.data.pointer, &MacTab, wrq->u.data.length))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __func__));
+ }
+
+ msg = (CHAR *) kmalloc(sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN), MEM_ALLOC_FLAG);
+ memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN );
+ sprintf(msg,"%s","\n");
+ sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-10s%-10s%-10s%-6s%-6s\n",
+ "MAC", "AID", "PSM", "LDT", "RxB", "TxB","CTxR", "LTxR");
+
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i];
+ if (pEntry->ValidAsCLI && (pEntry->Sst == SST_ASSOC))
+ {
+ if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) )
+ break;
+ sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ",
+ pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+ pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid);
+ sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode);
+ sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); // ToDo
+ sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); // ToDo
+ sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); // ToDo
+ sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]);
+ sprintf(msg+strlen(msg),"%-6d\n",0/*RateIdToMbps[pAd->MacTab.Content[i].LastTxRate]*/); // ToDo
+ }
+ }
+ // for compatible with old API just do the printk to console
+ //wrq->u.data.length = strlen(msg);
+ //if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s", msg));
+ }
+
+ kfree(msg);
+}
+#endif // UCOS //
+
+#ifdef DOT11_N_SUPPORT
+INT Set_BASetup_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR mac[6], tid;
+ char *token, sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+/*
+ The BASetup inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the tid value.
+*/
+ //printk("\n%s\n", arg);
+
+ if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ tid = simple_strtol((token+1), 0, 10);
+ if (tid > 15)
+ return FALSE;
+
+ *token = '\0';
+ for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+ {
+ if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+ return FALSE;
+ AtoH(token, (PUCHAR)(&mac[i]), 1);
+ }
+ if(i != 6)
+ return FALSE;
+
+ printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", mac[0], mac[1],
+ mac[2], mac[3], mac[4], mac[5], tid);
+
+ pEntry = MacTableLookup(pAd, mac);
+
+ if (pEntry) {
+ printk("\nSetup BA Session: Tid = %d\n", tid);
+ BAOriSessionSetUp(pAd, pEntry, tid, 0, 100, TRUE);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+INT Set_BADecline_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG bBADecline;
+
+ bBADecline = simple_strtol(arg, 0, 10);
+
+ if (bBADecline == 0)
+ {
+ pAd->CommonCfg.bBADecline = FALSE;
+ }
+ else if (bBADecline == 1)
+ {
+ pAd->CommonCfg.bBADecline = TRUE;
+ }
+ else
+ {
+ return FALSE; //Invalid argument
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_BADecline_Proc::(BADecline=%d)\n", pAd->CommonCfg.bBADecline));
+
+ return TRUE;
+}
+
+INT Set_BAOriTearDown_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR mac[6], tid;
+ char *token, sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+/*
+ The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the tid value.
+*/
+ if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ tid = simple_strtol((token+1), 0, 10);
+ if (tid > NUM_OF_TID)
+ return FALSE;
+
+ *token = '\0';
+ for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+ {
+ if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+ return FALSE;
+ AtoH(token, (PUCHAR)(&mac[i]), 1);
+ }
+ if(i != 6)
+ return FALSE;
+
+ printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1],
+ mac[2], mac[3], mac[4], mac[5], tid);
+
+ pEntry = MacTableLookup(pAd, mac);
+
+ if (pEntry) {
+ printk("\nTear down Ori BA Session: Tid = %d\n", tid);
+ BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, TRUE);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+INT Set_BARecTearDown_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR mac[6], tid;
+ char *token, sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+ //printk("\n%s\n", arg);
+/*
+ The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the tid value.
+*/
+ if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ tid = simple_strtol((token+1), 0, 10);
+ if (tid > NUM_OF_TID)
+ return FALSE;
+
+ *token = '\0';
+ for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+ {
+ if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+ return FALSE;
+ AtoH(token, (PUCHAR)(&mac[i]), 1);
+ }
+ if(i != 6)
+ return FALSE;
+
+ printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1],
+ mac[2], mac[3], mac[4], mac[5], tid);
+
+ pEntry = MacTableLookup(pAd, mac);
+
+ if (pEntry) {
+ printk("\nTear down Rec BA Session: Tid = %d\n", tid);
+ BARecSessionTearDown(pAd, pEntry->Aid, tid, FALSE);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+INT Set_HtBw_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG HtBw;
+
+ HtBw = simple_strtol(arg, 0, 10);
+ if (HtBw == BW_40)
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+ else if (HtBw == BW_20)
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBw_Proc::(HtBw=%d)\n", pAd->CommonCfg.RegTransmitSetting.field.BW));
+
+ return TRUE;
+}
+
+INT Set_HtMcs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG HtMcs, Mcs_tmp;
+#ifdef CONFIG_STA_SUPPORT
+ BOOLEAN bAutoRate = FALSE;
+#endif // CONFIG_STA_SUPPORT //
+
+ Mcs_tmp = simple_strtol(arg, 0, 10);
+
+ if (Mcs_tmp <= 15 || Mcs_tmp == 32)
+ HtMcs = Mcs_tmp;
+ else
+ HtMcs = MCS_AUTO;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS = HtMcs;
+ pAd->StaCfg.bAutoTxRateSwitch = (HtMcs == MCS_AUTO) ? TRUE:FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d, bAutoTxRateSwitch = %d)\n",
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS, pAd->StaCfg.bAutoTxRateSwitch));
+
+ if ((pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED) ||
+ (pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE < MODE_HTMIX))
+ {
+ if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) &&
+ (HtMcs >= 0 && HtMcs <= 3) &&
+ (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_CCK))
+ {
+ RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs] * 1000000));
+ }
+ else if ((pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO) &&
+ (HtMcs >= 0 && HtMcs <= 7) &&
+ (pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode == FIXED_TXMODE_OFDM))
+ {
+ RTMPSetDesiredRates(pAd, (LONG) (RateIdToMbps[HtMcs+4] * 1000000));
+ }
+ else
+ bAutoRate = TRUE;
+
+ if (bAutoRate)
+ {
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+ RTMPSetDesiredRates(pAd, -1);
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(FixedTxMode=%d)\n",pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode));
+ }
+ if (ADHOC_ON(pAd))
+ return TRUE;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ SetCommonHT(pAd);
+
+ return TRUE;
+}
+
+INT Set_HtGi_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG HtGi;
+
+ HtGi = simple_strtol(arg, 0, 10);
+
+ if ( HtGi == GI_400)
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400;
+ else if ( HtGi == GI_800 )
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtGi_Proc::(ShortGI=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.ShortGI));
+
+ return TRUE;
+}
+
+
+INT Set_HtTxBASize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR Size;
+
+ Size = simple_strtol(arg, 0, 10);
+
+ if (Size <=0 || Size >=64)
+ {
+ Size = 8;
+ }
+ pAd->CommonCfg.TxBASize = Size-1;
+ DBGPRINT(RT_DEBUG_ERROR, ("Set_HtTxBASize ::(TxBASize= %d)\n", Size));
+
+ return TRUE;
+}
+
+
+INT Set_HtOpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == HTMODE_GF)
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF;
+ else if ( Value == HTMODE_MM )
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtOpMode_Proc::(HtOpMode=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.HTMODE));
+
+ return TRUE;
+
+}
+
+INT Set_HtStbc_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == STBC_USE)
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE;
+ else if ( Value == STBC_NONE )
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_Stbc_Proc::(HtStbc=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.STBC));
+
+ return TRUE;
+}
+
+INT Set_HtHtc_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->HTCEnable = FALSE;
+ else if ( Value ==1 )
+ pAd->HTCEnable = TRUE;
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtHtc_Proc::(HtHtc=%d)\n",pAd->HTCEnable));
+
+ return TRUE;
+}
+
+INT Set_HtExtcha_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == 0)
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ else if ( Value ==1 )
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtExtcha_Proc::(HtExtcha=%d)\n",pAd->CommonCfg.RegTransmitSetting.field.EXTCHA));
+
+ return TRUE;
+}
+
+INT Set_HtMpduDensity_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value <=7 && Value >= 0)
+ pAd->CommonCfg.BACapability.field.MpduDensity = Value;
+ else
+ pAd->CommonCfg.BACapability.field.MpduDensity = 4;
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMpduDensity_Proc::(HtMpduDensity=%d)\n",pAd->CommonCfg.BACapability.field.MpduDensity));
+
+ return TRUE;
+}
+
+INT Set_HtBaWinSize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+
+ if (Value >=1 && Value <= 64)
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value;
+ }
+ else
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64;
+ }
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtBaWinSize_Proc::(HtBaWinSize=%d)\n",pAd->CommonCfg.BACapability.field.RxBAWinLimit));
+
+ return TRUE;
+}
+
+INT Set_HtRdg_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value == 0)
+ pAd->CommonCfg.bRdg = FALSE;
+ else if ( Value ==1 )
+ {
+ pAd->HTCEnable = TRUE;
+ pAd->CommonCfg.bRdg = TRUE;
+ }
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg));
+
+ return TRUE;
+}
+
+INT Set_HtLinkAdapt_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->bLinkAdapt = FALSE;
+ else if ( Value ==1 )
+ {
+ pAd->HTCEnable = TRUE;
+ pAd->bLinkAdapt = TRUE;
+ }
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtLinkAdapt_Proc::(HtLinkAdapt=%d)\n",pAd->bLinkAdapt));
+
+ return TRUE;
+}
+
+INT Set_HtAmsdu_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE;
+ else if ( Value == 1 )
+ pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable));
+
+ return TRUE;
+}
+
+INT Set_HtAutoBa_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+ else if (Value == 1)
+ pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+ else
+ return FALSE; //Invalid argument
+
+ pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA;
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAutoBa_Proc::(HtAutoBa=%d)\n",pAd->CommonCfg.BACapability.field.AutoBA));
+
+ return TRUE;
+
+}
+
+INT Set_HtProtect_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->CommonCfg.bHTProtect = FALSE;
+ else if (Value == 1)
+ pAd->CommonCfg.bHTProtect = TRUE;
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect));
+
+ return TRUE;
+}
+
+INT Set_SendPSMPAction_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR mac[6], mode;
+ char *token, sepValue[] = ":", DASH = '-';
+ INT i;
+ MAC_TABLE_ENTRY *pEntry;
+
+ //printk("\n%s\n", arg);
+/*
+ The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d,
+ =>The six 2 digit hex-decimal number previous are the Mac address,
+ =>The seventh decimal number is the mode value.
+*/
+ if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format.
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ mode = simple_strtol((token+1), 0, 10);
+ if (mode > MMPS_ENABLE)
+ return FALSE;
+
+ *token = '\0';
+ for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+ {
+ if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+ return FALSE;
+ AtoH(token, (PUCHAR)(&mac[i]), 1);
+ }
+ if(i != 6)
+ return FALSE;
+
+ printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", mac[0], mac[1],
+ mac[2], mac[3], mac[4], mac[5], mode);
+
+ pEntry = MacTableLookup(pAd, mac);
+
+ if (pEntry) {
+ printk("\nSendPSMPAction MIPS mode = %d\n", mode);
+ SendPSMPAction(pAd, pEntry->Aid, mode);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+
+}
+
+INT Set_HtMIMOPSmode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ if (Value <=3 && Value >= 0)
+ pAd->CommonCfg.BACapability.field.MMPSmode = Value;
+ else
+ pAd->CommonCfg.BACapability.field.MMPSmode = 3;
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMIMOPSmode_Proc::(MIMOPS mode=%d)\n",pAd->CommonCfg.BACapability.field.MMPSmode));
+
+ return TRUE;
+}
+
+
+INT Set_ForceShortGI_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->WIFItestbed.bShortGI = FALSE;
+ else if (Value == 1)
+ pAd->WIFItestbed.bShortGI = TRUE;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceShortGI_Proc::(ForceShortGI=%d)\n", pAd->WIFItestbed.bShortGI));
+
+ return TRUE;
+}
+
+
+
+INT Set_ForceGF_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->WIFItestbed.bGreenField = FALSE;
+ else if (Value == 1)
+ pAd->WIFItestbed.bGreenField = TRUE;
+ else
+ return FALSE; //Invalid argument
+
+ SetCommonHT(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_ForceGF_Proc::(ForceGF=%d)\n", pAd->WIFItestbed.bGreenField));
+
+ return TRUE;
+}
+
+INT Set_HtMimoPs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+ if (Value == 0)
+ pAd->CommonCfg.bMIMOPSEnable = FALSE;
+ else if (Value == 1)
+ pAd->CommonCfg.bMIMOPSEnable = TRUE;
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMimoPs_Proc::(HtMimoPs=%d)\n",pAd->CommonCfg.bMIMOPSEnable));
+
+ return TRUE;
+}
+#endif // DOT11_N_SUPPORT //
+
+
+#ifdef DOT11_N_SUPPORT
+INT SetCommonHT(
+ IN PRTMP_ADAPTER pAd)
+{
+ OID_SET_HT_PHYMODE SetHT;
+
+ if (pAd->CommonCfg.PhyMode < PHY_11ABGN_MIXED)
+ return FALSE;
+
+ SetHT.PhyMode = pAd->CommonCfg.PhyMode;
+ SetHT.TransmitNo = ((UCHAR)pAd->Antenna.field.TxPath);
+ SetHT.HtMode = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.HTMODE;
+ SetHT.ExtOffset = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
+ SetHT.MCS = MCS_AUTO;
+ SetHT.BW = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.BW;
+ SetHT.STBC = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.STBC;
+ SetHT.SHORTGI = (UCHAR)pAd->CommonCfg.RegTransmitSetting.field.ShortGI;
+
+ RTMPSetHT(pAd, &SetHT);
+
+ return TRUE;
+}
+#endif // DOT11_N_SUPPORT //
+
+INT Set_FixedTxMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR fix_tx_mode = FIXED_TXMODE_HT;
+
+ if (strcmp(arg, "OFDM") == 0 || strcmp(arg, "ofdm") == 0)
+ {
+ fix_tx_mode = FIXED_TXMODE_OFDM;
+ }
+ else if (strcmp(arg, "CCK") == 0 || strcmp(arg, "cck") == 0)
+ {
+ fix_tx_mode = FIXED_TXMODE_CCK;
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode;
+#endif // CONFIG_STA_SUPPORT //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_FixedTxMode_Proc::(FixedTxMode=%d)\n", fix_tx_mode));
+
+ return TRUE;
+}
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+INT Set_OpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+#ifdef RT2860
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+#endif // RT2860 //
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Can not switch operate mode on interface up !! \n"));
+ return FALSE;
+ }
+
+ if (Value == 0)
+ pAd->OpMode = OPMODE_STA;
+ else if (Value == 1)
+ pAd->OpMode = OPMODE_AP;
+ else
+ return FALSE; //Invalid argument
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Set_OpMode_Proc::(OpMode=%s)\n", pAd->OpMode == 1 ? "AP Mode" : "STA Mode"));
+
+ return TRUE;
+}
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+
+/////////////////////////////////////////////////////////////////////////
+PCHAR RTMPGetRalinkAuthModeStr(
+ IN NDIS_802_11_AUTHENTICATION_MODE authMode)
+{
+ switch(authMode)
+ {
+ case Ndis802_11AuthModeOpen:
+ return "OPEN";
+ default:
+ case Ndis802_11AuthModeWPAPSK:
+ return "WPAPSK";
+ case Ndis802_11AuthModeShared:
+ return "SHARED";
+ case Ndis802_11AuthModeWPA:
+ return "WPA";
+ case Ndis802_11AuthModeWPA2:
+ return "WPA2";
+ case Ndis802_11AuthModeWPA2PSK:
+ return "WPA2PSK";
+ case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+ return "WPAPSKWPA2PSK";
+ case Ndis802_11AuthModeWPA1WPA2:
+ return "WPA1WPA2";
+ case Ndis802_11AuthModeWPANone:
+ return "WPANONE";
+ }
+}
+
+PCHAR RTMPGetRalinkEncryModeStr(
+ IN USHORT encryMode)
+{
+ switch(encryMode)
+ {
+ default:
+ case Ndis802_11WEPDisabled:
+ return "NONE";
+ case Ndis802_11WEPEnabled:
+ return "WEP";
+ case Ndis802_11Encryption2Enabled:
+ return "TKIP";
+ case Ndis802_11Encryption3Enabled:
+ return "AES";
+ case Ndis802_11Encryption4Enabled:
+ return "TKIPAES";
+ }
+}
+
+INT RTMPShowCfgValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pName,
+ IN PUCHAR pBuf)
+{
+ INT Status = 0;
+
+ for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++)
+ {
+ if (!strcmp(pName, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name))
+ {
+ if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->show_proc(pAd, pBuf))
+ Status = -EINVAL;
+ break; //Exit for loop.
+ }
+ }
+
+ if(PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name == NULL)
+ {
+ sprintf(pBuf, "\n");
+ for (PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC = RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name; PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC++)
+ sprintf(pBuf, "%s%s\n", pBuf, PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC->name);
+ }
+
+ return Status;
+}
+
+INT Show_SSID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.Ssid);
+#endif // CONFIG_STA_SUPPORT //
+ return 0;
+}
+
+INT Show_WirelessMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ switch(pAd->CommonCfg.PhyMode)
+ {
+ case PHY_11BG_MIXED:
+ sprintf(pBuf, "\t11B/G");
+ break;
+ case PHY_11B:
+ sprintf(pBuf, "\t11B");
+ break;
+ case PHY_11A:
+ sprintf(pBuf, "\t11A");
+ break;
+ case PHY_11ABG_MIXED:
+ sprintf(pBuf, "\t11A/B/G");
+ break;
+ case PHY_11G:
+ sprintf(pBuf, "\t11G");
+ break;
+#ifdef DOT11_N_SUPPORT
+ case PHY_11ABGN_MIXED:
+ sprintf(pBuf, "\t11A/B/G/N");
+ break;
+ case PHY_11N_2_4G:
+ sprintf(pBuf, "\t11N only with 2.4G");
+ break;
+ case PHY_11GN_MIXED:
+ sprintf(pBuf, "\t11G/N");
+ break;
+ case PHY_11AN_MIXED:
+ sprintf(pBuf, "\t11A/N");
+ break;
+ case PHY_11BGN_MIXED:
+ sprintf(pBuf, "\t11B/G/N");
+ break;
+ case PHY_11AGN_MIXED:
+ sprintf(pBuf, "\t11A/G/N");
+ break;
+ case PHY_11N_5G:
+ sprintf(pBuf, "\t11N only with 5G");
+ break;
+#endif // DOT11_N_SUPPORT //
+ default:
+ sprintf(pBuf, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode);
+ break;
+ }
+ return 0;
+}
+
+
+INT Show_TxBurst_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.bEnableTxBurst ? "TRUE":"FALSE");
+ return 0;
+}
+
+INT Show_TxPreamble_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ switch(pAd->CommonCfg.TxPreamble)
+ {
+ case Rt802_11PreambleShort:
+ sprintf(pBuf, "\tShort");
+ break;
+ case Rt802_11PreambleLong:
+ sprintf(pBuf, "\tLong");
+ break;
+ case Rt802_11PreambleAuto:
+ sprintf(pBuf, "\tAuto");
+ break;
+ default:
+ sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.TxPreamble);
+ break;
+ }
+
+ return 0;
+}
+
+INT Show_TxPower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%lu", pAd->CommonCfg.TxPowerPercentage);
+ return 0;
+}
+
+INT Show_Channel_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%d", pAd->CommonCfg.Channel);
+ return 0;
+}
+
+INT Show_BGProtection_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ switch(pAd->CommonCfg.UseBGProtection)
+ {
+ case 1: //Always On
+ sprintf(pBuf, "\tON");
+ break;
+ case 2: //Always OFF
+ sprintf(pBuf, "\tOFF");
+ break;
+ case 0: //AUTO
+ sprintf(pBuf, "\tAuto");
+ break;
+ default:
+ sprintf(pBuf, "\tUnknow Value(%lu)", pAd->CommonCfg.UseBGProtection);
+ break;
+ }
+ return 0;
+}
+
+INT Show_RTSThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%u", pAd->CommonCfg.RtsThreshold);
+ return 0;
+}
+
+INT Show_FragThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%u", pAd->CommonCfg.FragmentThreshold);
+ return 0;
+}
+
+#ifdef DOT11_N_SUPPORT
+INT Show_HtBw_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)
+ {
+ sprintf(pBuf, "\t40 MHz");
+ }
+ else
+ {
+ sprintf(pBuf, "\t20 MHz");
+ }
+ return 0;
+}
+
+INT Show_HtMcs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ sprintf(pBuf, "\t%u", pAd->StaCfg.DesiredTransmitSetting.field.MCS);
+#endif // CONFIG_STA_SUPPORT //
+ return 0;
+}
+
+INT Show_HtGi_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ switch(pAd->CommonCfg.RegTransmitSetting.field.ShortGI)
+ {
+ case GI_400:
+ sprintf(pBuf, "\tGI_400");
+ break;
+ case GI_800:
+ sprintf(pBuf, "\tGI_800");
+ break;
+ default:
+ sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.ShortGI);
+ break;
+ }
+ return 0;
+}
+
+INT Show_HtOpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ switch(pAd->CommonCfg.RegTransmitSetting.field.HTMODE)
+ {
+ case HTMODE_GF:
+ sprintf(pBuf, "\tGF");
+ break;
+ case HTMODE_MM:
+ sprintf(pBuf, "\tMM");
+ break;
+ default:
+ sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.HTMODE);
+ break;
+ }
+ return 0;
+}
+
+INT Show_HtExtcha_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ switch(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA)
+ {
+ case EXTCHA_BELOW:
+ sprintf(pBuf, "\tBelow");
+ break;
+ case EXTCHA_ABOVE:
+ sprintf(pBuf, "\tAbove");
+ break;
+ default:
+ sprintf(pBuf, "\tUnknow Value(%u)", pAd->CommonCfg.RegTransmitSetting.field.EXTCHA);
+ break;
+ }
+ return 0;
+}
+
+
+INT Show_HtMpduDensity_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.MpduDensity);
+ return 0;
+}
+
+INT Show_HtBaWinSize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%u", pAd->CommonCfg.BACapability.field.RxBAWinLimit);
+ return 0;
+}
+
+INT Show_HtRdg_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.bRdg ? "TRUE":"FALSE");
+ return 0;
+}
+
+INT Show_HtAmsdu_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AmsduEnable ? "TRUE":"FALSE");
+ return 0;
+}
+
+INT Show_HtAutoBa_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.BACapability.field.AutoBA ? "TRUE":"FALSE");
+ return 0;
+}
+#endif // DOT11_N_SUPPORT //
+
+INT Show_CountryRegion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegion);
+ return 0;
+}
+
+INT Show_CountryRegionABand_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%d", pAd->CommonCfg.CountryRegionForABand);
+ return 0;
+}
+
+INT Show_CountryCode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.CountryCode);
+ return 0;
+}
+
+#ifdef AGGREGATION_SUPPORT
+INT Show_PktAggregate_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE");
+ return 0;
+}
+#endif // AGGREGATION_SUPPORT //
+
+#ifdef WMM_SUPPORT
+INT Show_WmmCapable_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.bWmmCapable ? "TRUE":"FALSE");
+#endif // CONFIG_STA_SUPPORT //
+
+ return 0;
+}
+#endif // WMM_SUPPORT //
+
+INT Show_IEEE80211H_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ sprintf(pBuf, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE");
+ return 0;
+}
+
+#ifdef CONFIG_STA_SUPPORT
+INT Show_NetworkType_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ switch(pAd->StaCfg.BssType)
+ {
+ case BSS_ADHOC:
+ sprintf(pBuf, "\tAdhoc");
+ break;
+ case BSS_INFRA:
+ sprintf(pBuf, "\tInfra");
+ break;
+ case BSS_ANY:
+ sprintf(pBuf, "\tAny");
+ break;
+ case BSS_MONITOR:
+ sprintf(pBuf, "\tMonitor");
+ break;
+ default:
+ sprintf(pBuf, "\tUnknow Value(%d)", pAd->StaCfg.BssType);
+ break;
+ }
+ return 0;
+}
+#endif // CONFIG_STA_SUPPORT //
+
+INT Show_AuthMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ AuthMode = pAd->StaCfg.AuthMode;
+#endif // CONFIG_STA_SUPPORT //
+
+ if ((AuthMode >= Ndis802_11AuthModeOpen) &&
+ (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ sprintf(pBuf, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode));
+ else
+ sprintf(pBuf, "\tUnknow Value(%d)", AuthMode);
+
+ return 0;
+}
+
+INT Show_EncrypType_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ WepStatus = pAd->StaCfg.WepStatus;
+#endif // CONFIG_STA_SUPPORT //
+
+ if ((WepStatus >= Ndis802_11WEPEnabled) &&
+ (WepStatus <= Ndis802_11Encryption4KeyAbsent))
+ sprintf(pBuf, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus));
+ else
+ sprintf(pBuf, "\tUnknow Value(%d)", WepStatus);
+
+ return 0;
+}
+
+INT Show_DefaultKeyID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ UCHAR DefaultKeyId = 0;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ DefaultKeyId = pAd->StaCfg.DefaultKeyId;
+#endif // CONFIG_STA_SUPPORT //
+
+ sprintf(pBuf, "\t%d", DefaultKeyId);
+
+ return 0;
+}
+
+INT Show_WepKey_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN INT KeyIdx,
+ OUT PUCHAR pBuf)
+{
+ UCHAR Key[16] = {0}, KeyLength = 0;
+ INT index = BSS0;
+
+ KeyLength = pAd->SharedKey[index][KeyIdx].KeyLen;
+ NdisMoveMemory(Key, pAd->SharedKey[index][KeyIdx].Key, KeyLength);
+
+ //check key string is ASCII or not
+ if (RTMPCheckStrPrintAble(Key, KeyLength))
+ sprintf(pBuf, "\t%s", Key);
+ else
+ {
+ int idx;
+ sprintf(pBuf, "\t");
+ for (idx = 0; idx < KeyLength; idx++)
+ sprintf(pBuf+strlen(pBuf), "%02X", Key[idx]);
+ }
+ return 0;
+}
+
+INT Show_Key1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ Show_WepKey_Proc(pAd, 0, pBuf);
+ return 0;
+}
+
+INT Show_Key2_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ Show_WepKey_Proc(pAd, 1, pBuf);
+ return 0;
+}
+
+INT Show_Key3_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ Show_WepKey_Proc(pAd, 2, pBuf);
+ return 0;
+}
+
+INT Show_Key4_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ Show_WepKey_Proc(pAd, 3, pBuf);
+ return 0;
+}
+
+INT Show_WPAPSK_Proc(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pBuf)
+{
+ INT idx;
+ UCHAR PMK[32] = {0};
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ NdisMoveMemory(PMK, pAd->StaCfg.PMK, 32);
+#endif // CONFIG_STA_SUPPORT //
+
+ sprintf(pBuf, "\tPMK = ");
+ for (idx = 0; idx < 32; idx++)
+ sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]);
+
+ return 0;
+}
+
diff --git a/drivers/staging/rt2860/common/cmm_sanity.c b/drivers/staging/rt2860/common/cmm_sanity.c
new file mode 100644
index 000000000000..b0f070d43135
--- /dev/null
+++ b/drivers/staging/rt2860/common/cmm_sanity.c
@@ -0,0 +1,1633 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ sanity.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Chang 2004-09-01 add WMM support
+*/
+#include "../rt_config.h"
+
+
+extern UCHAR CISCO_OUI[];
+
+extern UCHAR WPA_OUI[];
+extern UCHAR RSN_OUI[];
+extern UCHAR WME_INFO_ELEM[];
+extern UCHAR WME_PARM_ELEM[];
+extern UCHAR Ccx2QosInfo[];
+extern UCHAR RALINK_OUI[];
+extern UCHAR BROADCOM_OUI[];
+extern UCHAR WPS_OUI[];
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN MlmeAddBAReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2)
+{
+ PMLME_ADDBA_REQ_STRUCT pInfo;
+
+ pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg;
+
+ if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT)))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n"));
+ return FALSE;
+ }
+
+ if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n"));
+ return FALSE;
+ }
+
+ if ((pInfo->pAddr[0]&0x01) == 0x01)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN MlmeDelBAReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen)
+{
+ MLME_DELBA_REQ_STRUCT *pInfo;
+ pInfo = (MLME_DELBA_REQ_STRUCT *)Msg;
+
+ if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n"));
+ return FALSE;
+ }
+
+ if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n"));
+ return FALSE;
+ }
+
+ if ((pInfo->TID & 0xf0))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n"));
+ return FALSE;
+ }
+
+ if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN PeerAddBAReqActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
+ PFRAME_ADDBA_REQ pAddFrame;
+ pAddFrame = (PFRAME_ADDBA_REQ)(pMsg);
+ if (MsgLen < (sizeof(FRAME_ADDBA_REQ)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+ // we support immediate BA.
+ *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm));
+ pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue);
+ pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word);
+
+ if (pAddFrame->BaParm.BAPolicy != IMMED_BA)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy));
+ DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported));
+ return FALSE;
+ }
+
+ // we support immediate BA.
+ if (pAddFrame->BaParm.TID &0xfff0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request incorrect TID = %d\n", pAddFrame->BaParm.TID));
+ return FALSE;
+ }
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+ return TRUE;
+}
+
+BOOLEAN PeerAddBARspActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen)
+{
+ PFRAME_ADDBA_RSP pAddFrame;
+
+ pAddFrame = (PFRAME_ADDBA_RSP)(pMsg);
+ if (MsgLen < (sizeof(FRAME_ADDBA_RSP)))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response frame length size = %ld incorrect\n", MsgLen));
+ return FALSE;
+ }
+ // we support immediate BA.
+ *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm));
+ pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode);
+ pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue);
+
+ if (pAddFrame->BaParm.BAPolicy != IMMED_BA)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Response Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy));
+ return FALSE;
+ }
+
+ // we support immediate BA.
+ if (pAddFrame->BaParm.TID &0xfff0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("PeerAddBARspActionSanity: ADDBA Response incorrect TID = %d\n", pAddFrame->BaParm.TID));
+ return FALSE;
+ }
+ return TRUE;
+
+}
+
+BOOLEAN PeerDelBAActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN VOID *pMsg,
+ IN ULONG MsgLen )
+{
+ //PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
+ PFRAME_DELBA_REQ pDelFrame;
+ if (MsgLen != (sizeof(FRAME_DELBA_REQ)))
+ return FALSE;
+
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return FALSE;
+
+ pDelFrame = (PFRAME_DELBA_REQ)(pMsg);
+
+ *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm));
+ pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode);
+
+ if (pDelFrame->DelbaParm.TID &0xfff0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerBeaconAndProbeRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ IN UCHAR MsgChannel,
+ OUT PUCHAR pAddr2,
+ OUT PUCHAR pBssid,
+ OUT CHAR Ssid[],
+ OUT UCHAR *pSsidLen,
+ OUT UCHAR *pBssType,
+ OUT USHORT *pBeaconPeriod,
+ OUT UCHAR *pChannel,
+ OUT UCHAR *pNewChannel,
+ OUT LARGE_INTEGER *pTimestamp,
+ OUT CF_PARM *pCfParm,
+ OUT USHORT *pAtimWin,
+ OUT USHORT *pCapabilityInfo,
+ OUT UCHAR *pErp,
+ OUT UCHAR *pDtimCount,
+ OUT UCHAR *pDtimPeriod,
+ OUT UCHAR *pBcastFlag,
+ OUT UCHAR *pMessageToMe,
+ OUT UCHAR SupRate[],
+ OUT UCHAR *pSupRateLen,
+ OUT UCHAR ExtRate[],
+ OUT UCHAR *pExtRateLen,
+ OUT UCHAR *pCkipFlag,
+ OUT UCHAR *pAironetCellPowerLimit,
+ OUT PEDCA_PARM pEdcaParm,
+ OUT PQBSS_LOAD_PARM pQbssLoad,
+ OUT PQOS_CAPABILITY_PARM pQosCapability,
+ OUT ULONG *pRalinkIe,
+ OUT UCHAR *pHtCapabilityLen,
+#ifdef CONFIG_STA_SUPPORT
+ OUT UCHAR *pPreNHtCapabilityLen,
+#endif // CONFIG_STA_SUPPORT //
+ OUT HT_CAPABILITY_IE *pHtCapability,
+ OUT UCHAR *AddHtInfoLen,
+ OUT ADD_HT_INFO_IE *AddHtInfo,
+ OUT UCHAR *NewExtChannelOffset, // Ht extension channel offset(above or below)
+ OUT USHORT *LengthVIE,
+ OUT PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+ CHAR *Ptr;
+#ifdef CONFIG_STA_SUPPORT
+ CHAR TimLen;
+#endif // CONFIG_STA_SUPPORT //
+ PFRAME_802_11 pFrame;
+ PEID_STRUCT pEid;
+ UCHAR SubType;
+ UCHAR Sanity;
+ //UCHAR ECWMin, ECWMax;
+ //MAC_CSR9_STRUC Csr9;
+ ULONG Length = 0;
+
+ // For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel
+ // 1. If the AP is 11n enabled, then check the control channel.
+ // 2. If the AP didn't have any info about channel, use the channel we received this frame as the channel. (May inaccuracy!!)
+ UCHAR CtrlChannel = 0;
+
+ // Add for 3 necessary EID field check
+ Sanity = 0;
+
+ *pAtimWin = 0;
+ *pErp = 0;
+ *pDtimCount = 0;
+ *pDtimPeriod = 0;
+ *pBcastFlag = 0;
+ *pMessageToMe = 0;
+ *pExtRateLen = 0;
+ *pCkipFlag = 0; // Default of CkipFlag is 0
+ *pAironetCellPowerLimit = 0xFF; // Default of AironetCellPowerLimit is 0xFF
+ *LengthVIE = 0; // Set the length of VIE to init value 0
+ *pHtCapabilityLen = 0; // Set the length of VIE to init value 0
+#ifdef CONFIG_STA_SUPPORT
+ if (pAd->OpMode == OPMODE_STA)
+ *pPreNHtCapabilityLen = 0; // Set the length of VIE to init value 0
+#endif // CONFIG_STA_SUPPORT //
+ *AddHtInfoLen = 0; // Set the length of VIE to init value 0
+ *pRalinkIe = 0;
+ *pNewChannel = 0;
+ *NewExtChannelOffset = 0xff; //Default 0xff means no such IE
+ pCfParm->bValid = FALSE; // default: no IE_CF found
+ pQbssLoad->bValid = FALSE; // default: no IE_QBSS_LOAD found
+ pEdcaParm->bValid = FALSE; // default: no IE_EDCA_PARAMETER found
+ pQosCapability->bValid = FALSE; // default: no IE_QOS_CAPABILITY found
+
+ pFrame = (PFRAME_802_11)Msg;
+
+ // get subtype from header
+ SubType = (UCHAR)pFrame->Hdr.FC.SubType;
+
+ // get Addr2 and BSSID from header
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+ COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3);
+
+ Ptr = pFrame->Octet;
+ Length += LENGTH_802_11;
+
+ // get timestamp from payload and advance the pointer
+ NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN);
+
+ pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart);
+ pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart);
+
+ Ptr += TIMESTAMP_LEN;
+ Length += TIMESTAMP_LEN;
+
+ // get beacon interval from payload and advance the pointer
+ NdisMoveMemory(pBeaconPeriod, Ptr, 2);
+ Ptr += 2;
+ Length += 2;
+
+ // get capability info from payload and advance the pointer
+ NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+ Ptr += 2;
+ Length += 2;
+
+ if (CAP_IS_ESS_ON(*pCapabilityInfo))
+ *pBssType = BSS_INFRA;
+ else
+ *pBssType = BSS_ADHOC;
+
+ pEid = (PEID_STRUCT) Ptr;
+
+ // get variable fields from payload and advance the pointer
+ while ((Length + 2 + pEid->Len) <= MsgLen)
+ {
+ //
+ // Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.
+ //
+ if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n",
+ (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN));
+ break;
+ }
+
+ switch(pEid->Eid)
+ {
+ case IE_SSID:
+ // Already has one SSID EID in this beacon, ignore the second one
+ if (Sanity & 0x1)
+ break;
+ if(pEid->Len <= MAX_LEN_OF_SSID)
+ {
+ NdisMoveMemory(Ssid, pEid->Octet, pEid->Len);
+ *pSsidLen = pEid->Len;
+ Sanity |= 0x1;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len));
+ return FALSE;
+ }
+ break;
+
+ case IE_SUPP_RATES:
+ if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ Sanity |= 0x2;
+ NdisMoveMemory(SupRate, pEid->Octet, pEid->Len);
+ *pSupRateLen = pEid->Len;
+
+ // TODO: 2004-09-14 not a good design here, cause it exclude extra rates
+ // from ScanTab. We should report as is. And filter out unsupported
+ // rates in MlmeAux.
+ // Check against the supported rates
+ // RTMPCheckRates(pAd, SupRate, pSupRateLen);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",pEid->Len));
+ return FALSE;
+ }
+ break;
+
+ case IE_HT_CAP:
+ if (pEid->Len >= SIZE_HT_CAP_IE) //Note: allow extension.!!
+ {
+ NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE));
+ *pHtCapabilityLen = SIZE_HT_CAP_IE; // Nnow we only support 26 bytes.
+
+ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+ *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ *pPreNHtCapabilityLen = 0; // Nnow we only support 26 bytes.
+
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_HT_CAP. pEid->Len = %d\n", pEid->Len));
+ }
+
+ break;
+ case IE_ADD_HT:
+ if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
+ {
+ // This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only
+ // copy first sizeof(ADD_HT_INFO_IE)
+ NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
+ *AddHtInfoLen = SIZE_ADD_HT_INFO_IE;
+
+ CtrlChannel = AddHtInfo->ControlChan;
+
+ *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2));
+ *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3));
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_ADD_HT. \n"));
+ }
+
+ break;
+ case IE_SECONDARY_CH_OFFSET:
+ if (pEid->Len == 1)
+ {
+ *NewExtChannelOffset = pEid->Octet[0];
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - wrong IE_SECONDARY_CH_OFFSET. \n"));
+ }
+
+ break;
+ case IE_FH_PARM:
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n"));
+ break;
+
+ case IE_DS_PARM:
+ if(pEid->Len == 1)
+ {
+ *pChannel = *pEid->Octet;
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (ChannelSanity(pAd, *pChannel) == 0)
+ {
+
+ return FALSE;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+ Sanity |= 0x4;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",pEid->Len));
+ return FALSE;
+ }
+ break;
+
+ case IE_CF_PARM:
+ if(pEid->Len == 6)
+ {
+ pCfParm->bValid = TRUE;
+ pCfParm->CfpCount = pEid->Octet[0];
+ pCfParm->CfpPeriod = pEid->Octet[1];
+ pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3];
+ pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5];
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n"));
+ return FALSE;
+ }
+ break;
+
+ case IE_IBSS_PARM:
+ if(pEid->Len == 2)
+ {
+ NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n"));
+ return FALSE;
+ }
+ break;
+
+#ifdef CONFIG_STA_SUPPORT
+ case IE_TIM:
+ if(INFRA_ON(pAd) && SubType == SUBTYPE_BEACON)
+ {
+ GetTimBit((PUCHAR)pEid, pAd->StaActive.Aid, &TimLen, pBcastFlag, pDtimCount, pDtimPeriod, pMessageToMe);
+ }
+ break;
+#endif // CONFIG_STA_SUPPORT //
+ case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
+ if(pEid->Len == 3)
+ {
+ *pNewChannel = pEid->Octet[1]; //extract new channel number
+ }
+ break;
+
+ // New for WPA
+ // CCX v2 has the same IE, we need to parse that too
+ // Wifi WMM use the same IE vale, need to parse that too
+ // case IE_WPA:
+ case IE_VENDOR_SPECIFIC:
+ // Check the OUI version, filter out non-standard usage
+ if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7))
+ {
+ //*pRalinkIe = pEid->Octet[3];
+ if (pEid->Octet[3] != 0)
+ *pRalinkIe = pEid->Octet[3];
+ else
+ *pRalinkIe = 0xf0000000; // Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag.
+ }
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+ // This HT IE is before IEEE draft set HT IE value.2006-09-28 by Jan.
+
+ // Other vendors had production before IE_HT_CAP value is assigned. To backward support those old-firmware AP,
+ // Check broadcom-defiend pre-802.11nD1.0 OUI for HT related IE, including HT Capatilities IE and HT Information IE
+ else if ((*pHtCapabilityLen == 0) && NdisEqualMemory(pEid->Octet, PRE_N_HT_OUI, 3) && (pEid->Len >= 4) && (pAd->OpMode == OPMODE_STA))
+ {
+ if ((pEid->Octet[3] == OUI_PREN_HT_CAP) && (pEid->Len >= 30) && (*pHtCapabilityLen == 0))
+ {
+ NdisMoveMemory(pHtCapability, &pEid->Octet[4], sizeof(HT_CAPABILITY_IE));
+ *pPreNHtCapabilityLen = SIZE_HT_CAP_IE;
+ }
+
+ if ((pEid->Octet[3] == OUI_PREN_ADD_HT) && (pEid->Len >= 26))
+ {
+ NdisMoveMemory(AddHtInfo, &pEid->Octet[4], sizeof(ADD_HT_INFO_IE));
+ *AddHtInfoLen = SIZE_ADD_HT_INFO_IE;
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+ else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+ {
+ // Copy to pVIE which will report to microsoft bssid list.
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
+ {
+ PUCHAR ptr;
+ int i;
+
+ // parsing EDCA parameters
+ pEdcaParm->bValid = TRUE;
+ pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10;
+ pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20;
+ pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40;
+ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+ pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
+ ptr = &pEid->Octet[8];
+ for (i=0; i<4; i++)
+ {
+ UCHAR aci = (*ptr & 0x60) >> 5; // b5~6 is AC INDEX
+ pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); // b5 is ACM
+ pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; // b0~3 is AIFSN
+ pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; // b0~4 is Cwmin
+ pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; // b5~8 is Cwmax
+ pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); // in unit of 32-us
+ ptr += 4; // point to next AC
+ }
+ }
+ else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7))
+ {
+ // parsing EDCA parameters
+ pEdcaParm->bValid = TRUE;
+ pEdcaParm->bQAck = FALSE; // pEid->Octet[0] & 0x10;
+ pEdcaParm->bQueueRequest = FALSE; // pEid->Octet[0] & 0x20;
+ pEdcaParm->bTxopRequest = FALSE; // pEid->Octet[0] & 0x40;
+ pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
+ pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
+
+ // use default EDCA parameter
+ pEdcaParm->bACM[QID_AC_BE] = 0;
+ pEdcaParm->Aifsn[QID_AC_BE] = 3;
+ pEdcaParm->Cwmin[QID_AC_BE] = CW_MIN_IN_BITS;
+ pEdcaParm->Cwmax[QID_AC_BE] = CW_MAX_IN_BITS;
+ pEdcaParm->Txop[QID_AC_BE] = 0;
+
+ pEdcaParm->bACM[QID_AC_BK] = 0;
+ pEdcaParm->Aifsn[QID_AC_BK] = 7;
+ pEdcaParm->Cwmin[QID_AC_BK] = CW_MIN_IN_BITS;
+ pEdcaParm->Cwmax[QID_AC_BK] = CW_MAX_IN_BITS;
+ pEdcaParm->Txop[QID_AC_BK] = 0;
+
+ pEdcaParm->bACM[QID_AC_VI] = 0;
+ pEdcaParm->Aifsn[QID_AC_VI] = 2;
+ pEdcaParm->Cwmin[QID_AC_VI] = CW_MIN_IN_BITS-1;
+ pEdcaParm->Cwmax[QID_AC_VI] = CW_MAX_IN_BITS;
+ pEdcaParm->Txop[QID_AC_VI] = 96; // AC_VI: 96*32us ~= 3ms
+
+ pEdcaParm->bACM[QID_AC_VO] = 0;
+ pEdcaParm->Aifsn[QID_AC_VO] = 2;
+ pEdcaParm->Cwmin[QID_AC_VO] = CW_MIN_IN_BITS-2;
+ pEdcaParm->Cwmax[QID_AC_VO] = CW_MAX_IN_BITS-1;
+ pEdcaParm->Txop[QID_AC_VO] = 48; // AC_VO: 48*32us ~= 1.5ms
+ }
+ break;
+
+ case IE_EXT_SUPP_RATES:
+ if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
+ *pExtRateLen = pEid->Len;
+
+ // TODO: 2004-09-14 not a good design here, cause it exclude extra rates
+ // from ScanTab. We should report as is. And filter out unsupported
+ // rates in MlmeAux.
+ // Check against the supported rates
+ // RTMPCheckRates(pAd, ExtRate, pExtRateLen);
+ }
+ break;
+
+ case IE_ERP:
+ if (pEid->Len == 1)
+ {
+ *pErp = (UCHAR)pEid->Octet[0];
+ }
+ break;
+
+ case IE_AIRONET_CKIP:
+ // 0. Check Aironet IE length, it must be larger or equal to 28
+ // Cisco AP350 used length as 28
+ // Cisco AP12XX used length as 30
+ if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2))
+ break;
+
+ // 1. Copy CKIP flag byte to buffer for process
+ *pCkipFlag = *(pEid->Octet + 8);
+ break;
+
+ case IE_AP_TX_POWER:
+ // AP Control of Client Transmit Power
+ //0. Check Aironet IE length, it must be 6
+ if (pEid->Len != 0x06)
+ break;
+
+ // Get cell power limit in dBm
+ if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1)
+ *pAironetCellPowerLimit = *(pEid->Octet + 4);
+ break;
+
+ // WPA2 & 802.11i RSN
+ case IE_RSN:
+ // There is no OUI for version anymore, check the group cipher OUI before copying
+ if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+ {
+ // Copy to pVIE which will report to microsoft bssid list.
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ }
+ break;
+#ifdef CONFIG_STA_SUPPORT
+#ifdef EXT_BUILD_CHANNEL_LIST
+ case IE_COUNTRY:
+ Ptr = (PUCHAR) pVIE;
+ NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2);
+ *LengthVIE += (pEid->Len + 2);
+ break;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+
+ default:
+ break;
+ }
+
+ Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len]
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+
+ // For some 11a AP. it did not have the channel EID, patch here
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ UCHAR LatchRfChannel = MsgChannel;
+ if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0))
+ {
+ if (CtrlChannel != 0)
+ *pChannel = CtrlChannel;
+ else
+ *pChannel = LatchRfChannel;
+ Sanity |= 0x4;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ if (Sanity != 0x7)
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", Sanity));
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+
+}
+
+#ifdef DOT11N_DRAFT3
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check for some IE addressed in 802.11n d3.03.
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerBeaconAndProbeRspSanity2(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT UCHAR *RegClass)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 pFrame;
+ PEID_STRUCT pEid;
+ ULONG Length = 0;
+
+ pFrame = (PFRAME_802_11)Msg;
+
+ *RegClass = 0;
+ Ptr = pFrame->Octet;
+ Length += LENGTH_802_11;
+
+ // get timestamp from payload and advance the pointer
+ Ptr += TIMESTAMP_LEN;
+ Length += TIMESTAMP_LEN;
+
+ // get beacon interval from payload and advance the pointer
+ Ptr += 2;
+ Length += 2;
+
+ // get capability info from payload and advance the pointer
+ Ptr += 2;
+ Length += 2;
+
+ pEid = (PEID_STRUCT) Ptr;
+
+ // get variable fields from payload and advance the pointer
+ while ((Length + 2 + pEid->Len) <= MsgLen)
+ {
+ switch(pEid->Eid)
+ {
+ case IE_SUPP_REG_CLASS:
+ if(pEid->Len > 0)
+ {
+ *RegClass = *pEid->Octet;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",pEid->Len));
+ return FALSE;
+ }
+ break;
+ }
+
+ Length = Length + 2 + pEid->Len; // Eid[1] + Len[1]+ content[Len]
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+
+ return TRUE;
+
+}
+#endif // DOT11N_DRAFT3 //
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+ */
+BOOLEAN MlmeScanReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT UCHAR *pBssType,
+ OUT CHAR Ssid[],
+ OUT UCHAR *pSsidLen,
+ OUT UCHAR *pScanType)
+{
+ MLME_SCAN_REQ_STRUCT *Info;
+
+ Info = (MLME_SCAN_REQ_STRUCT *)(Msg);
+ *pBssType = Info->BssType;
+ *pSsidLen = Info->SsidLen;
+ NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen);
+ *pScanType = Info->ScanType;
+
+ if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY)
+ && (*pScanType == SCAN_ACTIVE || *pScanType == SCAN_PASSIVE
+#ifdef CONFIG_STA_SUPPORT
+ || *pScanType == SCAN_CISCO_PASSIVE || *pScanType == SCAN_CISCO_ACTIVE
+ || *pScanType == SCAN_CISCO_CHANNEL_LOAD || *pScanType == SCAN_CISCO_NOISE
+#endif // CONFIG_STA_SUPPORT //
+ ))
+ {
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n"));
+ return FALSE;
+ }
+}
+
+// IRQL = DISPATCH_LEVEL
+UCHAR ChannelSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel)
+{
+ int i;
+
+ for (i = 0; i < pAd->ChannelListNum; i ++)
+ {
+ if (channel == pAd->ChannelList[i].Channel)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerDeauthSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *pReason)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+ NdisMoveMemory(pReason, &pFrame->Octet[0], 2);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerAuthSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr,
+ OUT USHORT *pAlg,
+ OUT USHORT *pSeq,
+ OUT USHORT *pStatus,
+ CHAR *pChlgText)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+ COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2);
+ NdisMoveMemory(pAlg, &pFrame->Octet[0], 2);
+ NdisMoveMemory(pSeq, &pFrame->Octet[2], 2);
+ NdisMoveMemory(pStatus, &pFrame->Octet[4], 2);
+
+ if ((*pAlg == Ndis802_11AuthModeOpen)
+#ifdef LEAP_SUPPORT
+ || (*pAlg == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+ )
+ {
+ if (*pSeq == 1 || *pSeq == 2)
+ {
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n"));
+ return FALSE;
+ }
+ }
+ else if (*pAlg == Ndis802_11AuthModeShared)
+ {
+ if (*pSeq == 1 || *pSeq == 4)
+ {
+ return TRUE;
+ }
+ else if (*pSeq == 2 || *pSeq == 3)
+ {
+ NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN);
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n"));
+ return FALSE;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n"));
+ return FALSE;
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+ */
+BOOLEAN MlmeAuthReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr,
+ OUT ULONG *pTimeout,
+ OUT USHORT *pAlg)
+{
+ MLME_AUTH_REQ_STRUCT *pInfo;
+
+ pInfo = (MLME_AUTH_REQ_STRUCT *)Msg;
+ COPY_MAC_ADDR(pAddr, pInfo->Addr);
+ *pTimeout = pInfo->Timeout;
+ *pAlg = pInfo->Alg;
+
+ if (((*pAlg == Ndis802_11AuthModeShared) ||(*pAlg == Ndis802_11AuthModeOpen)
+#ifdef LEAP_SUPPORT
+ || (*pAlg == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+ ) &&
+ ((*pAddr & 0x01) == 0))
+ {
+ return TRUE;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n"));
+ return FALSE;
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN MlmeAssocReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pApAddr,
+ OUT USHORT *pCapabilityInfo,
+ OUT ULONG *pTimeout,
+ OUT USHORT *pListenIntv)
+{
+ MLME_ASSOC_REQ_STRUCT *pInfo;
+
+ pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg;
+ *pTimeout = pInfo->Timeout; // timeout
+ COPY_MAC_ADDR(pApAddr, pInfo->Addr); // AP address
+ *pCapabilityInfo = pInfo->CapabilityInfo; // capability info
+ *pListenIntv = pInfo->ListenIntv;
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ MLME message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN PeerDisassocSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *pReason)
+{
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+
+ COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
+ NdisMoveMemory(pReason, &pFrame->Octet[0], 2);
+
+ return TRUE;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Sanity check NetworkType (11b, 11g or 11a)
+
+ Arguments:
+ pBss - Pointer to BSS table.
+
+ Return Value:
+ Ndis802_11DS .......(11b)
+ Ndis802_11OFDM24....(11g)
+ Ndis802_11OFDM5.....(11a)
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(
+ IN PBSS_ENTRY pBss)
+{
+ NDIS_802_11_NETWORK_TYPE NetWorkType;
+ UCHAR rate, i;
+
+ NetWorkType = Ndis802_11DS;
+
+ if (pBss->Channel <= 14)
+ {
+ //
+ // First check support Rate.
+ //
+ for (i = 0; i < pBss->SupRateLen; i++)
+ {
+ rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit
+ if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
+ {
+ continue;
+ }
+ else
+ {
+ //
+ // Otherwise (even rate > 108) means Ndis802_11OFDM24
+ //
+ NetWorkType = Ndis802_11OFDM24;
+ break;
+ }
+ }
+
+ //
+ // Second check Extend Rate.
+ //
+ if (NetWorkType != Ndis802_11OFDM24)
+ {
+ for (i = 0; i < pBss->ExtRateLen; i++)
+ {
+ rate = pBss->SupRate[i] & 0x7f; // Mask out basic rate set bit
+ if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
+ {
+ continue;
+ }
+ else
+ {
+ //
+ // Otherwise (even rate > 108) means Ndis802_11OFDM24
+ //
+ NetWorkType = Ndis802_11OFDM24;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ NetWorkType = Ndis802_11OFDM5;
+ }
+
+ if (pBss->HtCapabilityLen != 0)
+ {
+ if (NetWorkType == Ndis802_11OFDM5)
+ NetWorkType = Ndis802_11OFDM5_N;
+ else
+ NetWorkType = Ndis802_11OFDM24_N;
+ }
+
+ return NetWorkType;
+}
+
+/*
+ ==========================================================================
+ Description:
+ WPA message sanity check
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+ */
+BOOLEAN PeerWpaMessageSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN PEAPOL_PACKET pMsg,
+ IN ULONG MsgLen,
+ IN UCHAR MsgType,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ UCHAR mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE];
+ BOOLEAN bReplayDiff = FALSE;
+ BOOLEAN bWPA2 = FALSE;
+ KEY_INFO EapolKeyInfo;
+ UCHAR GroupKeyIndex = 0;
+
+
+ NdisZeroMemory(mic, sizeof(mic));
+ NdisZeroMemory(digest, sizeof(digest));
+ NdisZeroMemory(KEYDATA, sizeof(KEYDATA));
+ NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo));
+
+ NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+
+ *((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo));
+
+ // Choose WPA2 or not
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
+ bWPA2 = TRUE;
+
+ // 0. Check MsgType
+ if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType));
+ return FALSE;
+ }
+
+ // 1. Replay counter check
+ if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) // For supplicant
+ {
+ // First validate replay counter, only accept message with larger replay counter.
+ // Let equal pass, some AP start with all zero replay counter
+ UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
+
+ NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
+ if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY) != 1) &&
+ (RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
+ {
+ bReplayDiff = TRUE;
+ }
+ }
+ else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) // For authenticator
+ {
+ // check Replay Counter coresponds to MSG from authenticator, otherwise discard
+ if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY))
+ {
+ bReplayDiff = TRUE;
+ }
+ }
+
+ // Replay Counter different condition
+ if (bReplayDiff)
+ {
+ // send wireless event - for replay counter different
+ if (pAd->CommonCfg.bWirelessEvent)
+ RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ if (MsgType < EAPOL_GROUP_MSG_1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
+ }
+
+ hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+ hex_dump("Current replay counter ", pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
+ return FALSE;
+ }
+
+ // 2. Verify MIC except Pairwise Msg1
+ if (MsgType != EAPOL_PAIR_MSG_1)
+ {
+ UCHAR rcvd_mic[LEN_KEY_DESC_MIC];
+
+ // Record the received MIC for check later
+ NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+ NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+
+ if (pEntry->WepStatus == Ndis802_11Encryption2Enabled) // TKIP
+ {
+ hmac_md5(pEntry->PTK, LEN_EAP_MICK, (PUCHAR)pMsg, MsgLen, mic);
+ }
+ else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled) // AES
+ {
+ HMAC_SHA1((PUCHAR)pMsg, MsgLen, pEntry->PTK, LEN_EAP_MICK, digest);
+ NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
+ }
+
+ if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC))
+ {
+ // send wireless event - for MIC different
+ if (pAd->CommonCfg.bWirelessEvent)
+ RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ if (MsgType < EAPOL_GROUP_MSG_1)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
+ }
+
+ hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC);
+ hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC);
+
+ return FALSE;
+ }
+ }
+
+ // Extract the context of the Key Data field if it exist
+ // The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is un-encrypted.
+ // The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted.
+ if (pMsg->KeyDesc.KeyDataLen[1] > 0)
+ {
+ // Decrypt this field
+ if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ if(pEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ // AES
+ AES_GTK_KEY_UNWRAP(&pEntry->PTK[16], KEYDATA, pMsg->KeyDesc.KeyDataLen[1],pMsg->KeyDesc.KeyData);
+ }
+ else
+ {
+ INT i;
+ UCHAR Key[32];
+ // Decrypt TKIP GTK
+ // Construct 32 bytes RC4 Key
+ NdisMoveMemory(Key, pMsg->KeyDesc.KeyIv, 16);
+ NdisMoveMemory(&Key[16], &pEntry->PTK[16], 16);
+ ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, Key, 32);
+ //discard first 256 bytes
+ for(i = 0; i < 256; i++)
+ ARCFOUR_BYTE(&pAd->PrivateInfo.WEPCONTEXT);
+ // Decrypt GTK. Becareful, there is no ICV to check the result is correct or not
+ ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]);
+ }
+
+ if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
+ GroupKeyIndex = EapolKeyInfo.KeyIndex;
+
+ }
+ else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2))
+ {
+ NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, pMsg->KeyDesc.KeyDataLen[1]);
+ }
+ else
+ {
+
+ return TRUE;
+ }
+
+ // Parse Key Data field to
+ // 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2)
+ // 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2
+ // 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2)
+ if (!RTMPParseEapolKeyData(pAd, KEYDATA, pMsg->KeyDesc.KeyDataLen[1], GroupKeyIndex, MsgType, bWPA2, pEntry))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+
+}
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+BOOLEAN MlmeDlsReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PRT_802_11_DLS *pDLS,
+ OUT PUSHORT pReason)
+{
+ MLME_DLS_REQ_STRUCT *pInfo;
+
+ pInfo = (MLME_DLS_REQ_STRUCT *)Msg;
+
+ *pDLS = pInfo->pDLS;
+ *pReason = pInfo->Reason;
+
+ return TRUE;
+}
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef QOS_DLS_SUPPORT
+BOOLEAN PeerDlsReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pDlsTimeout,
+ OUT UCHAR *pRatesLen,
+ OUT UCHAR Rates[],
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
+ PEID_STRUCT eid_ptr;
+
+ // to prevent caller from using garbage output value
+ *pCapabilityInfo = 0;
+ *pDlsTimeout = 0;
+ *pHtCapabilityLen = 0;
+
+ Ptr = Fr->Octet;
+
+ // offset to destination MAC address (Category and Action field)
+ Ptr += 2;
+
+ // get DA from payload and advance the pointer
+ NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ // get SA from payload and advance the pointer
+ NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ // get capability info from payload and advance the pointer
+ NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+ Ptr += 2;
+
+ // get capability info from payload and advance the pointer
+ NdisMoveMemory(pDlsTimeout, Ptr, 2);
+ Ptr += 2;
+
+ // Category and Action field + DA + SA + capability + Timeout
+ eid_ptr = (PEID_STRUCT) &Fr->Octet[18];
+
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_SUPP_RATES:
+ if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
+ {
+ NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len);
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0]));
+ DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7]));
+ *pRatesLen = eid_ptr->Len;
+ }
+ else
+ {
+ *pRatesLen = 8;
+ Rates[0] = 0x82;
+ Rates[1] = 0x84;
+ Rates[2] = 0x8b;
+ Rates[3] = 0x96;
+ Rates[4] = 0x12;
+ Rates[5] = 0x24;
+ Rates[6] = 0x48;
+ Rates[7] = 0x6c;
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
+ }
+ break;
+
+ case IE_EXT_SUPP_RATES:
+ if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len);
+ *pRatesLen = (*pRatesLen) + eid_ptr->Len;
+ }
+ else
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen));
+ *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES;
+ }
+ break;
+
+ case IE_HT_CAP:
+ if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
+ {
+ NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE));
+
+ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+ *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+ *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - IE_HT_CAP\n"));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return TRUE;
+}
+
+BOOLEAN PeerDlsRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pStatus,
+ OUT UCHAR *pRatesLen,
+ OUT UCHAR Rates[],
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
+ PEID_STRUCT eid_ptr;
+
+ // to prevent caller from using garbage output value
+ *pStatus = 0;
+ *pCapabilityInfo = 0;
+ *pHtCapabilityLen = 0;
+
+ Ptr = Fr->Octet;
+
+ // offset to destination MAC address (Category and Action field)
+ Ptr += 2;
+
+ // get status code from payload and advance the pointer
+ NdisMoveMemory(pStatus, Ptr, 2);
+ Ptr += 2;
+
+ // get DA from payload and advance the pointer
+ NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ // get SA from payload and advance the pointer
+ NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ if (pStatus == 0)
+ {
+ // get capability info from payload and advance the pointer
+ NdisMoveMemory(pCapabilityInfo, Ptr, 2);
+ Ptr += 2;
+ }
+
+ // Category and Action field + status code + DA + SA + capability
+ eid_ptr = (PEID_STRUCT) &Fr->Octet[18];
+
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_SUPP_RATES:
+ if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
+ {
+ NdisMoveMemory(Rates, eid_ptr->Octet, eid_ptr->Len);
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n",eid_ptr->Len, Rates[0]));
+ DBGPRINT(RT_DEBUG_TRACE, ("Rates[1]=%x %x %x %x %x %x %x\n", Rates[1], Rates[2], Rates[3], Rates[4], Rates[5], Rates[6], Rates[7]));
+ *pRatesLen = eid_ptr->Len;
+ }
+ else
+ {
+ *pRatesLen = 8;
+ Rates[0] = 0x82;
+ Rates[1] = 0x84;
+ Rates[2] = 0x8b;
+ Rates[3] = 0x96;
+ Rates[4] = 0x12;
+ Rates[5] = 0x24;
+ Rates[6] = 0x48;
+ Rates[7] = 0x6c;
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
+ }
+ break;
+
+ case IE_EXT_SUPP_RATES:
+ if (eid_ptr->Len + *pRatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, eid_ptr->Len);
+ *pRatesLen = (*pRatesLen) + eid_ptr->Len;
+ }
+ else
+ {
+ NdisMoveMemory(&Rates[*pRatesLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pRatesLen));
+ *pRatesLen = MAX_LEN_OF_SUPPORTED_RATES;
+ }
+ break;
+
+ case IE_HT_CAP:
+ if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
+ {
+ NdisMoveMemory(pHtCapability, eid_ptr->Octet, sizeof(HT_CAPABILITY_IE));
+
+ *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
+ *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
+ *pHtCapabilityLen = sizeof(HT_CAPABILITY_IE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - IE_HT_CAP\n"));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerDlsRspSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return TRUE;
+}
+
+BOOLEAN PeerDlsTearDownSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pReason)
+{
+ CHAR *Ptr;
+ PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
+
+ // to prevent caller from using garbage output value
+ *pReason = 0;
+
+ Ptr = Fr->Octet;
+
+ // offset to destination MAC address (Category and Action field)
+ Ptr += 2;
+
+ // get DA from payload and advance the pointer
+ NdisMoveMemory(pDA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ // get SA from payload and advance the pointer
+ NdisMoveMemory(pSA, Ptr, MAC_ADDR_LEN);
+ Ptr += MAC_ADDR_LEN;
+
+ // get reason code from payload and advance the pointer
+ NdisMoveMemory(pReason, Ptr, 2);
+ Ptr += 2;
+
+ return TRUE;
+}
+#endif // QOS_DLS_SUPPORT //
+
diff --git a/drivers/staging/rt2860/common/cmm_sync.c b/drivers/staging/rt2860/common/cmm_sync.c
new file mode 100644
index 000000000000..40e4109118e0
--- /dev/null
+++ b/drivers/staging/rt2860/common/cmm_sync.c
@@ -0,0 +1,702 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ sync.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Chang 2004-09-01 modified for rt2561/2661
+*/
+#include "../rt_config.h"
+
+// 2.4 Ghz channel plan index in the TxPower arrays.
+#define BG_BAND_REGION_0_START 0 // 1,2,3,4,5,6,7,8,9,10,11
+#define BG_BAND_REGION_0_SIZE 11
+#define BG_BAND_REGION_1_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13
+#define BG_BAND_REGION_1_SIZE 13
+#define BG_BAND_REGION_2_START 9 // 10,11
+#define BG_BAND_REGION_2_SIZE 2
+#define BG_BAND_REGION_3_START 9 // 10,11,12,13
+#define BG_BAND_REGION_3_SIZE 4
+#define BG_BAND_REGION_4_START 13 // 14
+#define BG_BAND_REGION_4_SIZE 1
+#define BG_BAND_REGION_5_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14
+#define BG_BAND_REGION_5_SIZE 14
+#define BG_BAND_REGION_6_START 2 // 3,4,5,6,7,8,9
+#define BG_BAND_REGION_6_SIZE 7
+#define BG_BAND_REGION_7_START 4 // 5,6,7,8,9,10,11,12,13
+#define BG_BAND_REGION_7_SIZE 9
+#define BG_BAND_REGION_31_START 0 // 1,2,3,4,5,6,7,8,9,10,11,12,13,14
+#define BG_BAND_REGION_31_SIZE 14
+
+// 5 Ghz channel plan index in the TxPower arrays.
+UCHAR A_BAND_REGION_0_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_1_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+UCHAR A_BAND_REGION_2_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64};
+UCHAR A_BAND_REGION_3_CHANNEL_LIST[]={52, 56, 60, 64, 149, 153, 157, 161};
+UCHAR A_BAND_REGION_4_CHANNEL_LIST[]={149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_5_CHANNEL_LIST[]={149, 153, 157, 161};
+UCHAR A_BAND_REGION_6_CHANNEL_LIST[]={36, 40, 44, 48};
+UCHAR A_BAND_REGION_7_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_8_CHANNEL_LIST[]={52, 56, 60, 64};
+UCHAR A_BAND_REGION_9_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_10_CHANNEL_LIST[]={36, 40, 44, 48, 149, 153, 157, 161, 165};
+UCHAR A_BAND_REGION_11_CHANNEL_LIST[]={36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161};
+
+//BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8.
+UCHAR BaSizeArray[4] = {8,16,32,64};
+
+/*
+ ==========================================================================
+ Description:
+ Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type,
+ and 3) PHY-mode user selected.
+ The outcome is used by driver when doing site survey.
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID BuildChannelList(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i, j, index=0, num=0;
+ PUCHAR pChannelList = NULL;
+
+ NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER));
+
+ // if not 11a-only mode, channel list starts from 2.4Ghz band
+ if ((pAd->CommonCfg.PhyMode != PHY_11A)
+#ifdef DOT11_N_SUPPORT
+ && (pAd->CommonCfg.PhyMode != PHY_11AN_MIXED) && (pAd->CommonCfg.PhyMode != PHY_11N_5G)
+#endif // DOT11_N_SUPPORT //
+ )
+ {
+ switch (pAd->CommonCfg.CountryRegion & 0x7f)
+ {
+ case REGION_0_BG_BAND: // 1 -11
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_0_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_0_SIZE);
+ index += BG_BAND_REGION_0_SIZE;
+ break;
+ case REGION_1_BG_BAND: // 1 - 13
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_1_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_1_SIZE);
+ index += BG_BAND_REGION_1_SIZE;
+ break;
+ case REGION_2_BG_BAND: // 10 - 11
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_2_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_2_SIZE);
+ index += BG_BAND_REGION_2_SIZE;
+ break;
+ case REGION_3_BG_BAND: // 10 - 13
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_3_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_3_SIZE);
+ index += BG_BAND_REGION_3_SIZE;
+ break;
+ case REGION_4_BG_BAND: // 14
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_4_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_4_SIZE);
+ index += BG_BAND_REGION_4_SIZE;
+ break;
+ case REGION_5_BG_BAND: // 1 - 14
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_5_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_5_SIZE);
+ index += BG_BAND_REGION_5_SIZE;
+ break;
+ case REGION_6_BG_BAND: // 3 - 9
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_6_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_6_SIZE);
+ index += BG_BAND_REGION_6_SIZE;
+ break;
+ case REGION_7_BG_BAND: // 5 - 13
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_7_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_7_SIZE);
+ index += BG_BAND_REGION_7_SIZE;
+ break;
+ case REGION_31_BG_BAND: // 1 - 14
+ NdisMoveMemory(&pAd->ChannelList[index], &pAd->TxPower[BG_BAND_REGION_31_START], sizeof(CHANNEL_TX_POWER) * BG_BAND_REGION_31_SIZE);
+ index += BG_BAND_REGION_31_SIZE;
+ break;
+ default: // Error. should never happen
+ break;
+ }
+ for (i=0; i<index; i++)
+ pAd->ChannelList[i].MaxTxPwr = 20;
+ }
+
+ if ((pAd->CommonCfg.PhyMode == PHY_11A) || (pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED)
+#ifdef DOT11_N_SUPPORT
+ || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED)
+ || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)
+#endif // DOT11_N_SUPPORT //
+ )
+ {
+ switch (pAd->CommonCfg.CountryRegionForABand & 0x7f)
+ {
+ case REGION_0_A_BAND:
+ num = sizeof(A_BAND_REGION_0_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_0_CHANNEL_LIST;
+ break;
+ case REGION_1_A_BAND:
+ num = sizeof(A_BAND_REGION_1_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_1_CHANNEL_LIST;
+ break;
+ case REGION_2_A_BAND:
+ num = sizeof(A_BAND_REGION_2_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_2_CHANNEL_LIST;
+ break;
+ case REGION_3_A_BAND:
+ num = sizeof(A_BAND_REGION_3_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_3_CHANNEL_LIST;
+ break;
+ case REGION_4_A_BAND:
+ num = sizeof(A_BAND_REGION_4_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_4_CHANNEL_LIST;
+ break;
+ case REGION_5_A_BAND:
+ num = sizeof(A_BAND_REGION_5_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_5_CHANNEL_LIST;
+ break;
+ case REGION_6_A_BAND:
+ num = sizeof(A_BAND_REGION_6_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_6_CHANNEL_LIST;
+ break;
+ case REGION_7_A_BAND:
+ num = sizeof(A_BAND_REGION_7_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_7_CHANNEL_LIST;
+ break;
+ case REGION_8_A_BAND:
+ num = sizeof(A_BAND_REGION_8_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_8_CHANNEL_LIST;
+ break;
+ case REGION_9_A_BAND:
+ num = sizeof(A_BAND_REGION_9_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_9_CHANNEL_LIST;
+ break;
+
+ case REGION_10_A_BAND:
+ num = sizeof(A_BAND_REGION_10_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_10_CHANNEL_LIST;
+ break;
+
+ case REGION_11_A_BAND:
+ num = sizeof(A_BAND_REGION_11_CHANNEL_LIST)/sizeof(UCHAR);
+ pChannelList = A_BAND_REGION_11_CHANNEL_LIST;
+ break;
+
+ default: // Error. should never happen
+ DBGPRINT(RT_DEBUG_WARN,("countryregion=%d not support", pAd->CommonCfg.CountryRegionForABand));
+ break;
+ }
+
+ if (num != 0)
+ {
+ UCHAR RadarCh[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+ for (i=0; i<num; i++)
+ {
+ for (j=0; j<MAX_NUM_OF_CHANNELS; j++)
+ {
+ if (pChannelList[i] == pAd->TxPower[j].Channel)
+ NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
+ }
+ for (j=0; j<15; j++)
+ {
+ if (pChannelList[i] == RadarCh[j])
+ pAd->ChannelList[index+i].DfsReq = TRUE;
+ }
+ pAd->ChannelList[index+i].MaxTxPwr = 20;
+ }
+ index += num;
+ }
+ }
+
+ pAd->ChannelListNum = index;
+ DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n",
+ pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum));
+#ifdef DBG
+ for (i=0;i<pAd->ChannelListNum;i++)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, \n ", pAd->ChannelList[i].Channel, pAd->ChannelList[i].Power, pAd->ChannelList[i].Power2));
+ }
+#endif
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine return the first channel number according to the country
+ code selection and RF IC selection (signal band or dual band). It is called
+ whenever driver need to start a site survey of all supported channels.
+ Return:
+ ch - the first channel number of current country code setting
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+UCHAR FirstChannel(
+ IN PRTMP_ADAPTER pAd)
+{
+ return pAd->ChannelList[0].Channel;
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine returns the next channel number. This routine is called
+ during driver need to start a site survey of all supported channels.
+ Return:
+ next_channel - the next channel number valid in current country code setting.
+ Note:
+ return 0 if no more next channel
+ ==========================================================================
+ */
+UCHAR NextChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel)
+{
+ int i;
+ UCHAR next_channel = 0;
+
+ for (i = 0; i < (pAd->ChannelListNum - 1); i++)
+ if (channel == pAd->ChannelList[i].Channel)
+ {
+ next_channel = pAd->ChannelList[i+1].Channel;
+ break;
+ }
+ return next_channel;
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine is for Cisco Compatible Extensions 2.X
+ Spec31. AP Control of Client Transmit Power
+ Return:
+ None
+ Note:
+ Required by Aironet dBm(mW)
+ 0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW),
+ 17dBm(50mw), 20dBm(100mW)
+
+ We supported
+ 3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%),
+ 14dBm(75%), 15dBm(100%)
+
+ The client station's actual transmit power shall be within +/- 5dB of
+ the minimum value or next lower value.
+ ==========================================================================
+ */
+VOID ChangeToCellPowerLimit(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR AironetCellPowerLimit)
+{
+ //valud 0xFF means that hasn't found power limit information
+ //from the AP's Beacon/Probe response.
+ if (AironetCellPowerLimit == 0xFF)
+ return;
+
+ if (AironetCellPowerLimit < 6) //Used Lowest Power Percentage.
+ pAd->CommonCfg.TxPowerPercentage = 6;
+ else if (AironetCellPowerLimit < 9)
+ pAd->CommonCfg.TxPowerPercentage = 10;
+ else if (AironetCellPowerLimit < 12)
+ pAd->CommonCfg.TxPowerPercentage = 25;
+ else if (AironetCellPowerLimit < 14)
+ pAd->CommonCfg.TxPowerPercentage = 50;
+ else if (AironetCellPowerLimit < 15)
+ pAd->CommonCfg.TxPowerPercentage = 75;
+ else
+ pAd->CommonCfg.TxPowerPercentage = 100; //else used maximum
+
+ if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault)
+ pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
+
+}
+
+CHAR ConvertToRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi,
+ IN UCHAR RssiNumber)
+{
+ UCHAR RssiOffset, LNAGain;
+
+ // Rssi equals to zero should be an invalid value
+ if (Rssi == 0)
+ return -99;
+
+ LNAGain = GET_LNA_GAIN(pAd);
+ if (pAd->LatchRfRegs.Channel > 14)
+ {
+ if (RssiNumber == 0)
+ RssiOffset = pAd->ARssiOffset0;
+ else if (RssiNumber == 1)
+ RssiOffset = pAd->ARssiOffset1;
+ else
+ RssiOffset = pAd->ARssiOffset2;
+ }
+ else
+ {
+ if (RssiNumber == 0)
+ RssiOffset = pAd->BGRssiOffset0;
+ else if (RssiNumber == 1)
+ RssiOffset = pAd->BGRssiOffset1;
+ else
+ RssiOffset = pAd->BGRssiOffset2;
+ }
+
+ return (-12 - RssiOffset - LNAGain - Rssi);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Scan next channel
+ ==========================================================================
+ */
+VOID ScanNextChannel(
+ IN PRTMP_ADAPTER pAd)
+{
+ HEADER_802_11 Hdr80211;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ UCHAR SsidLen = 0, ScanType = pAd->MlmeAux.ScanType, BBPValue = 0;
+#ifdef CONFIG_STA_SUPPORT
+ USHORT Status;
+ PHEADER_802_11 pHdr80211;
+#endif // CONFIG_STA_SUPPORT //
+ UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (MONITOR_ON(pAd))
+ return;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RALINK_ATE
+ // Nothing to do in ATE mode.
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+ if (pAd->MlmeAux.Channel == 0)
+ {
+ if ((pAd->CommonCfg.BBPCurrentBW == BW_40)
+#ifdef CONFIG_STA_SUPPORT
+ && (INFRA_ON(pAd)
+ || (pAd->OpMode == OPMODE_AP))
+#endif // CONFIG_STA_SUPPORT //
+ )
+ {
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPValue);
+ BBPValue &= (~0x18);
+ BBPValue |= 0x10;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BBPValue);
+ DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to 40MHz channel %d, Total BSS[%02d]\n",pAd->CommonCfg.CentralChannel, pAd->ScanTab.BssNr));
+ }
+ else
+ {
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to channel %d, Total BSS[%02d]\n",pAd->CommonCfg.Channel, pAd->ScanTab.BssNr));
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ //
+ // To prevent data lost.
+ // Send an NULL data with turned PSM bit on to current associated AP before SCAN progress.
+ // Now, we need to send an NULL data with turned PSM bit off to AP, when scan progress done
+ //
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) && (INFRA_ON(pAd)))
+ {
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);
+ if (NStatus == NDIS_STATUS_SUCCESS)
+ {
+ pHdr80211 = (PHEADER_802_11) pOutBuffer;
+ MgtMacHeaderInit(pAd, pHdr80211, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+ pHdr80211->Duration = 0;
+ pHdr80211->FC.Type = BTYPE_DATA;
+ pHdr80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
+
+ // Send using priority queue
+ MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqAction -- Send PSM Data frame\n"));
+ MlmeFreeMemory(pAd, pOutBuffer);
+ RTMPusecDelay(5000);
+ }
+ }
+
+ pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+ Status = MLME_SUCCESS;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+ }
+ else
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // BBP and RF are not accessible in PS mode, we has to wake them up first
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ AsicForceWakeup(pAd, TRUE);
+
+ // leave PSM during scanning. otherwise we may lost ProbeRsp & BEACON
+ if (pAd->StaCfg.Psm == PWR_SAVE)
+ MlmeSetPsmBit(pAd, PWR_ACTIVE);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ AsicSwitchChannel(pAd, pAd->MlmeAux.Channel, TRUE);
+ AsicLockChannel(pAd, pAd->MlmeAux.Channel);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (pAd->MlmeAux.Channel > 14)
+ {
+ if ((pAd->CommonCfg.bIEEE80211H == 1) && RadarChannelCheck(pAd, pAd->MlmeAux.Channel))
+ {
+ ScanType = SCAN_PASSIVE;
+ ScanTimeIn5gChannel = MIN_CHANNEL_TIME;
+ }
+ }
+
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+ // carrier detection
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ {
+ ScanType = SCAN_PASSIVE;
+ ScanTimeIn5gChannel = MIN_CHANNEL_TIME;
+ }
+#endif // CARRIER_DETECTION_SUPPORT //
+ }
+
+#endif // CONFIG_STA_SUPPORT //
+
+ //Global country domain(ch1-11:active scan, ch12-14 passive scan)
+ if ((pAd->MlmeAux.Channel <= 14) && (pAd->MlmeAux.Channel >= 12) && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_31_BG_BAND))
+ {
+ ScanType = SCAN_PASSIVE;
+ }
+
+ // We need to shorten active scan time in order for WZC connect issue
+ // Chnage the channel scan time for CISCO stuff based on its IAPP announcement
+ if (ScanType == FAST_SCAN_ACTIVE)
+ RTMPSetTimer(&pAd->MlmeAux.ScanTimer, FAST_ACTIVE_SCAN_TIME);
+#ifdef CONFIG_STA_SUPPORT
+ else if (((ScanType == SCAN_CISCO_ACTIVE) ||
+ (ScanType == SCAN_CISCO_PASSIVE) ||
+ (ScanType == SCAN_CISCO_CHANNEL_LOAD) ||
+ (ScanType == SCAN_CISCO_NOISE)) && (pAd->OpMode == OPMODE_STA))
+ {
+ if (pAd->StaCfg.CCXScanTime < 25)
+ RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime * 2);
+ else
+ RTMPSetTimer(&pAd->MlmeAux.ScanTimer, pAd->StaCfg.CCXScanTime);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ else // must be SCAN_PASSIVE or SCAN_ACTIVE
+ {
+ if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED)
+#ifdef DOT11_N_SUPPORT
+ || (pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) || (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED)
+#endif // DOT11_N_SUPPORT //
+ )
+ {
+ if (pAd->MlmeAux.Channel > 14)
+ RTMPSetTimer(&pAd->MlmeAux.ScanTimer, ScanTimeIn5gChannel);
+ else
+ RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MIN_CHANNEL_TIME);
+ }
+ else
+ RTMPSetTimer(&pAd->MlmeAux.ScanTimer, MAX_CHANNEL_TIME);
+ }
+
+ if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE) ||
+ (ScanType == SCAN_CISCO_ACTIVE))
+ {
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("SYNC - ScanNextChannel() allocate memory fail\n"));
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_SCAN_CONF, 2, &Status);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ return;
+ }
+
+ // There is no need to send broadcast probe request if active scan is in effect.
+ if ((ScanType == SCAN_ACTIVE) || (ScanType == FAST_SCAN_ACTIVE)
+ )
+ SsidLen = pAd->MlmeAux.SsidLen;
+ else
+ SsidLen = 0;
+
+ MgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, BROADCAST_ADDR);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &Hdr80211,
+ 1, &SsidIe,
+ 1, &SsidLen,
+ SsidLen, pAd->MlmeAux.Ssid,
+ 1, &SupRateIe,
+ 1, &pAd->CommonCfg.SupRateLen,
+ pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate,
+ END_OF_ARGS);
+
+ if (pAd->CommonCfg.ExtRateLen)
+ {
+ ULONG Tmp;
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
+ 1, &ExtRateIe,
+ 1, &pAd->CommonCfg.ExtRateLen,
+ pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate,
+ END_OF_ARGS);
+ FrameLen += Tmp;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+ {
+ ULONG Tmp;
+ UCHAR HtLen;
+ UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+#ifdef RT_BIG_ENDIAN
+ HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+ if (pAd->bBroadComHT == TRUE)
+ {
+ HtLen = pAd->MlmeAux.HtCapabilityLen + 4;
+#ifdef RT_BIG_ENDIAN
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, SIZE_HT_CAP_IE);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
+ 1, &WpaIe,
+ 1, &HtLen,
+ 4, &BROADCOM[0],
+ pAd->MlmeAux.HtCapabilityLen, &HtCapabilityTmp,
+ END_OF_ARGS);
+#else
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
+ 1, &WpaIe,
+ 1, &HtLen,
+ 4, &BROADCOM[0],
+ pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
+ END_OF_ARGS);
+#endif // RT_BIG_ENDIAN //
+ }
+ else
+ {
+ HtLen = pAd->MlmeAux.HtCapabilityLen;
+#ifdef RT_BIG_ENDIAN
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &HtCapabilityTmp,
+ END_OF_ARGS);
+#else
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &pAd->CommonCfg.HtCapability,
+ END_OF_ARGS);
+#endif // RT_BIG_ENDIAN //
+ }
+ FrameLen += Tmp;
+
+#ifdef DOT11N_DRAFT3
+ if (pAd->CommonCfg.BACapability.field.b2040CoexistScanSup == 1)
+ {
+ ULONG Tmp;
+ HtLen = 1;
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &Tmp,
+ 1, &ExtHtCapIe,
+ 1, &HtLen,
+ 1, &pAd->CommonCfg.BSSCoexist2040.word,
+ END_OF_ARGS);
+
+ FrameLen += Tmp;
+ }
+#endif // DOT11N_DRAFT3 //
+ }
+#endif // DOT11_N_SUPPORT //
+
+
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ }
+
+ // For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ pAd->Mlme.SyncMachine.CurrState = SCAN_LISTEN;
+#endif // CONFIG_STA_SUPPORT //
+
+ }
+}
+
+VOID MgtProbReqMacHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN UCHAR SubType,
+ IN UCHAR ToDs,
+ IN PUCHAR pDA,
+ IN PUCHAR pBssid)
+{
+ NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+
+ pHdr80211->FC.Type = BTYPE_MGMT;
+ pHdr80211->FC.SubType = SubType;
+ if (SubType == SUBTYPE_ACK)
+ pHdr80211->FC.Type = BTYPE_CNTL;
+ pHdr80211->FC.ToDs = ToDs;
+ COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
+ COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
+}
+
+
diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c
new file mode 100644
index 000000000000..81c332ac2524
--- /dev/null
+++ b/drivers/staging/rt2860/common/cmm_wpa.c
@@ -0,0 +1,1606 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ wpa.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Jan Lee 03-07-22 Initial
+ Paul Lin 03-11-28 Modify for supplicant
+*/
+#include "../rt_config.h"
+// WPA OUI
+UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00};
+UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01};
+UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02};
+UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04};
+UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01};
+UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02};
+// WPA2 OUI
+UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01};
+UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02};
+UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04};
+UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01};
+UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02};
+// MSA OUI
+UCHAR OUI_MSA_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x05}; // Not yet final - IEEE 802.11s-D1.06
+UCHAR OUI_MSA_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x06}; // Not yet final - IEEE 802.11s-D1.06
+
+/*
+ ========================================================================
+
+ Routine Description:
+ The pseudo-random function(PRF) that hashes various inputs to
+ derive a pseudo-random value. To add liveness to the pseudo-random
+ value, a nonce should be one of the inputs.
+
+ It is used to generate PTK, GTK or some specific random value.
+
+ Arguments:
+ UCHAR *key, - the key material for HMAC_SHA1 use
+ INT key_len - the length of key
+ UCHAR *prefix - a prefix label
+ INT prefix_len - the length of the label
+ UCHAR *data - a specific data with variable length
+ INT data_len - the length of a specific data
+ INT len - the output lenght
+
+ Return Value:
+ UCHAR *output - the calculated result
+
+ Note:
+ 802.11i-2004 Annex H.3
+
+ ========================================================================
+*/
+VOID PRF(
+ IN UCHAR *key,
+ IN INT key_len,
+ IN UCHAR *prefix,
+ IN INT prefix_len,
+ IN UCHAR *data,
+ IN INT data_len,
+ OUT UCHAR *output,
+ IN INT len)
+{
+ INT i;
+ UCHAR *input;
+ INT currentindex = 0;
+ INT total_len;
+
+ // Allocate memory for input
+ os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
+
+ if (input == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
+ return;
+ }
+
+ // Generate concatenation input
+ NdisMoveMemory(input, prefix, prefix_len);
+
+ // Concatenate a single octet containing 0
+ input[prefix_len] = 0;
+
+ // Concatenate specific data
+ NdisMoveMemory(&input[prefix_len + 1], data, data_len);
+ total_len = prefix_len + 1 + data_len;
+
+ // Concatenate a single octet containing 0
+ // This octet shall be update later
+ input[total_len] = 0;
+ total_len++;
+
+ // Iterate to calculate the result by hmac-sha-1
+ // Then concatenate to last result
+ for (i = 0; i < (len + 19) / 20; i++)
+ {
+ HMAC_SHA1(input, total_len, key, key_len, &output[currentindex]);
+ currentindex += 20;
+
+ // update the last octet
+ input[total_len - 1]++;
+ }
+ os_free_mem(NULL, input);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
+ It shall be called by 4-way handshake processing.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ PMK - pointer to PMK
+ ANonce - pointer to ANonce
+ AA - pointer to Authenticator Address
+ SNonce - pointer to SNonce
+ SA - pointer to Supplicant Address
+ len - indicate the length of PTK (octet)
+
+ Return Value:
+ Output pointer to the PTK
+
+ Note:
+ Refer to IEEE 802.11i-2004 8.5.1.2
+
+ ========================================================================
+*/
+VOID WpaCountPTK(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR *PMK,
+ IN UCHAR *ANonce,
+ IN UCHAR *AA,
+ IN UCHAR *SNonce,
+ IN UCHAR *SA,
+ OUT UCHAR *output,
+ IN UINT len)
+{
+ UCHAR concatenation[76];
+ UINT CurrPos = 0;
+ UCHAR temp[32];
+ UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
+ 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
+
+ // initiate the concatenation input
+ NdisZeroMemory(temp, sizeof(temp));
+ NdisZeroMemory(concatenation, 76);
+
+ // Get smaller address
+ if (RTMPCompareMemory(SA, AA, 6) == 1)
+ NdisMoveMemory(concatenation, AA, 6);
+ else
+ NdisMoveMemory(concatenation, SA, 6);
+ CurrPos += 6;
+
+ // Get larger address
+ if (RTMPCompareMemory(SA, AA, 6) == 1)
+ NdisMoveMemory(&concatenation[CurrPos], SA, 6);
+ else
+ NdisMoveMemory(&concatenation[CurrPos], AA, 6);
+
+ // store the larger mac address for backward compatible of
+ // ralink proprietary STA-key issue
+ NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
+ CurrPos += 6;
+
+ // Get smaller Nonce
+ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
+ NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
+ else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
+ NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
+ else
+ NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
+ CurrPos += 32;
+
+ // Get larger Nonce
+ if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
+ NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
+ else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
+ NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
+ else
+ NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
+ CurrPos += 32;
+
+ hex_dump("concatenation=", concatenation, 76);
+
+ // Use PRF to generate PTK
+ PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Generate random number by software.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ macAddr - pointer to local MAC address
+
+ Return Value:
+
+ Note:
+ 802.1ii-2004 Annex H.5
+
+ ========================================================================
+*/
+VOID GenRandom(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR *macAddr,
+ OUT UCHAR *random)
+{
+ INT i, curr;
+ UCHAR local[80], KeyCounter[32];
+ UCHAR result[80];
+ ULONG CurrentTime;
+ UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
+
+ // Zero the related information
+ NdisZeroMemory(result, 80);
+ NdisZeroMemory(local, 80);
+ NdisZeroMemory(KeyCounter, 32);
+
+ for (i = 0; i < 32; i++)
+ {
+ // copy the local MAC address
+ COPY_MAC_ADDR(local, macAddr);
+ curr = MAC_ADDR_LEN;
+
+ // concatenate the current time
+ NdisGetSystemUpTime(&CurrentTime);
+ NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
+ curr += sizeof(CurrentTime);
+
+ // concatenate the last result
+ NdisMoveMemory(&local[curr], result, 32);
+ curr += 32;
+
+ // concatenate a variable
+ NdisMoveMemory(&local[curr], &i, 2);
+ curr += 2;
+
+ // calculate the result
+ PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
+ }
+
+ NdisMoveMemory(random, result, 32);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build cipher suite in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ ElementID - indicate the WPA1 or WPA2
+ WepStatus - indicate the encryption type
+ bMixCipher - a boolean to indicate the pairwise cipher and group
+ cipher are the same or not
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+static VOID RTMPInsertRsnIeCipher(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ElementID,
+ IN UINT WepStatus,
+ IN BOOLEAN bMixCipher,
+ IN UCHAR FlexibleCipher,
+ OUT PUCHAR pRsnIe,
+ OUT UCHAR *rsn_len)
+{
+ UCHAR PairwiseCnt;
+
+ *rsn_len = 0;
+
+ // decide WPA2 or WPA1
+ if (ElementID == Wpa2Ie)
+ {
+ RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
+
+ // Assign the verson as 1
+ pRsnie_cipher->version = 1;
+
+ switch (WepStatus)
+ {
+ // TKIP mode
+ case Ndis802_11Encryption2Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
+ *rsn_len = sizeof(RSNIE2);
+ break;
+
+ // AES mode
+ case Ndis802_11Encryption3Enabled:
+ if (bMixCipher)
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+ else
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
+ *rsn_len = sizeof(RSNIE2);
+ break;
+
+ // TKIP-AES mix mode
+ case Ndis802_11Encryption4Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
+
+ PairwiseCnt = 1;
+ // Insert WPA2 TKIP as the first pairwise cipher
+ if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
+ // Insert WPA2 AES as the secondary pairwise cipher
+ if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
+ PairwiseCnt = 2;
+ }
+ }
+ else
+ {
+ // Insert WPA2 AES as the first pairwise cipher
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
+ }
+
+ pRsnie_cipher->ucount = PairwiseCnt;
+ *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
+ break;
+ }
+
+ // swap for big-endian platform
+ pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
+ pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
+ }
+ else
+ {
+ RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
+
+ // Assign OUI and version
+ NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
+ pRsnie_cipher->version = 1;
+
+ switch (WepStatus)
+ {
+ // TKIP mode
+ case Ndis802_11Encryption2Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
+ *rsn_len = sizeof(RSNIE);
+ break;
+
+ // AES mode
+ case Ndis802_11Encryption3Enabled:
+ if (bMixCipher)
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+ else
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
+ pRsnie_cipher->ucount = 1;
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
+ *rsn_len = sizeof(RSNIE);
+ break;
+
+ // TKIP-AES mix mode
+ case Ndis802_11Encryption4Enabled:
+ NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
+
+ PairwiseCnt = 1;
+ // Insert WPA TKIP as the first pairwise cipher
+ if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
+ // Insert WPA AES as the secondary pairwise cipher
+ if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
+ {
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
+ PairwiseCnt = 2;
+ }
+ }
+ else
+ {
+ // Insert WPA AES as the first pairwise cipher
+ NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
+ }
+
+ pRsnie_cipher->ucount = PairwiseCnt;
+ *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
+ break;
+ }
+
+ // swap for big-endian platform
+ pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
+ pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
+ }
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build AKM suite in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ ElementID - indicate the WPA1 or WPA2
+ AuthMode - indicate the authentication mode
+ apidx - indicate the interface index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+static VOID RTMPInsertRsnIeAKM(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ElementID,
+ IN UINT AuthMode,
+ IN UCHAR apidx,
+ OUT PUCHAR pRsnIe,
+ OUT UCHAR *rsn_len)
+{
+ RSNIE_AUTH *pRsnie_auth;
+
+ pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
+
+ // decide WPA2 or WPA1
+ if (ElementID == Wpa2Ie)
+ {
+ switch (AuthMode)
+ {
+ case Ndis802_11AuthModeWPA2:
+ case Ndis802_11AuthModeWPA1WPA2:
+ pRsnie_auth->acount = 1;
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
+ break;
+
+ case Ndis802_11AuthModeWPA2PSK:
+ case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+ pRsnie_auth->acount = 1;
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
+ break;
+ }
+ }
+ else
+ {
+ switch (AuthMode)
+ {
+ case Ndis802_11AuthModeWPA:
+ case Ndis802_11AuthModeWPA1WPA2:
+ pRsnie_auth->acount = 1;
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
+ break;
+
+ case Ndis802_11AuthModeWPAPSK:
+ case Ndis802_11AuthModeWPA1PSKWPA2PSK:
+ pRsnie_auth->acount = 1;
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
+ break;
+
+ case Ndis802_11AuthModeWPANone:
+ pRsnie_auth->acount = 1;
+ NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
+ break;
+ }
+ }
+
+ pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
+
+ (*rsn_len) += sizeof(RSNIE_AUTH); // update current RSNIE length
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build capability in RSN-IE.
+ It only shall be called by RTMPMakeRSNIE.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ ElementID - indicate the WPA1 or WPA2
+ apidx - indicate the interface index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+static VOID RTMPInsertRsnIeCap(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR ElementID,
+ IN UCHAR apidx,
+ OUT PUCHAR pRsnIe,
+ OUT UCHAR *rsn_len)
+{
+ RSN_CAPABILITIES *pRSN_Cap;
+
+ // it could be ignored in WPA1 mode
+ if (ElementID == WpaIe)
+ return;
+
+ pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
+
+
+ pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
+
+ (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Build RSN IE context. It is not included element-ID and length.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ AuthMode - indicate the authentication mode
+ WepStatus - indicate the encryption type
+ apidx - indicate the interface index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPMakeRSNIE(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT AuthMode,
+ IN UINT WepStatus,
+ IN UCHAR apidx)
+{
+ PUCHAR pRsnIe = NULL; // primary RSNIE
+ UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE
+ UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
+ UCHAR PrimaryRsnie;
+ BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different
+ UCHAR p_offset;
+ WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
+
+ rsnielen_cur_p = NULL;
+ rsnielen_ex_cur_p = NULL;
+
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+ {
+ if (AuthMode < Ndis802_11AuthModeWPA)
+ return;
+ }
+ else
+#endif // WPA_SUPPLICANT_SUPPORT //
+ {
+ // Support WPAPSK or WPA2PSK in STA-Infra mode
+ // Support WPANone in STA-Adhoc mode
+ if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
+ (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+ (AuthMode != Ndis802_11AuthModeWPANone)
+ )
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
+
+ // Zero RSNIE context
+ pAd->StaCfg.RSNIE_Len = 0;
+ NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
+
+ // Pointer to RSNIE
+ rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
+ pRsnIe = pAd->StaCfg.RSN_IE;
+
+ bMixCipher = pAd->StaCfg.bMixCipher;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ // indicate primary RSNIE as WPA or WPA2
+ if ((AuthMode == Ndis802_11AuthModeWPA) ||
+ (AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (AuthMode == Ndis802_11AuthModeWPANone) ||
+ (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
+ (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ PrimaryRsnie = WpaIe;
+ else
+ PrimaryRsnie = Wpa2Ie;
+
+ {
+ // Build the primary RSNIE
+ // 1. insert cipher suite
+ RTMPInsertRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
+
+ // 2. insert AKM
+ RTMPInsertRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
+
+ // 3. insert capability
+ RTMPInsertRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
+ }
+
+ // 4. update the RSNIE length
+ *rsnielen_cur_p = p_offset;
+
+ hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
+
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ Check whether the received frame is EAP frame.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ pEntry - pointer to active entry
+ pData - the received frame
+ DataByteCount - the received frame's length
+ FromWhichBSSID - indicate the interface index
+
+ Return:
+ TRUE - This frame is EAP frame
+ FALSE - otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPCheckWPAframe(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR pData,
+ IN ULONG DataByteCount,
+ IN UCHAR FromWhichBSSID)
+{
+ ULONG Body_len;
+ BOOLEAN Cancelled;
+
+
+ if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
+ return FALSE;
+
+
+ // Skip LLC header
+ if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
+ // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
+ NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
+ {
+ pData += 6;
+ }
+ // Skip 2-bytes EAPoL type
+ if (NdisEqualMemory(EAPOL, pData, 2))
+ {
+ pData += 2;
+ }
+ else
+ return FALSE;
+
+ switch (*(pData+1))
+ {
+ case EAPPacket:
+ Body_len = (*(pData+2)<<8) | (*(pData+3));
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
+ break;
+ case EAPOLStart:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
+ if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
+ RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
+ pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
+ }
+ break;
+ case EAPOLLogoff:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
+ break;
+ case EAPOLKey:
+ Body_len = (*(pData+2)<<8) | (*(pData+3));
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
+ break;
+ case EAPOLASFAlert:
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
+ break;
+ default:
+ return FALSE;
+
+ }
+ return TRUE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ ENCRYPT AES GTK before sending in EAPOL frame.
+ AES GTK length = 128 bit, so fix blocks for aes-key-wrap as 2 in this function.
+ This function references to RFC 3394 for aes key wrap algorithm.
+ Return:
+ ==========================================================================
+*/
+VOID AES_GTK_KEY_WRAP(
+ IN UCHAR *key,
+ IN UCHAR *plaintext,
+ IN UCHAR p_len,
+ OUT UCHAR *ciphertext)
+{
+ UCHAR A[8], BIN[16], BOUT[16];
+ UCHAR R[512];
+ INT num_blocks = p_len/8; // unit:64bits
+ INT i, j;
+ aes_context aesctx;
+ UCHAR xor;
+
+ rtmp_aes_set_key(&aesctx, key, 128);
+
+ // Init IA
+ for (i = 0; i < 8; i++)
+ A[i] = 0xa6;
+
+ //Input plaintext
+ for (i = 0; i < num_blocks; i++)
+ {
+ for (j = 0 ; j < 8; j++)
+ R[8 * (i + 1) + j] = plaintext[8 * i + j];
+ }
+
+ // Key Mix
+ for (j = 0; j < 6; j++)
+ {
+ for(i = 1; i <= num_blocks; i++)
+ {
+ //phase 1
+ NdisMoveMemory(BIN, A, 8);
+ NdisMoveMemory(&BIN[8], &R[8 * i], 8);
+ rtmp_aes_encrypt(&aesctx, BIN, BOUT);
+
+ NdisMoveMemory(A, &BOUT[0], 8);
+ xor = num_blocks * j + i;
+ A[7] = BOUT[7] ^ xor;
+ NdisMoveMemory(&R[8 * i], &BOUT[8], 8);
+ }
+ }
+
+ // Output ciphertext
+ NdisMoveMemory(ciphertext, A, 8);
+
+ for (i = 1; i <= num_blocks; i++)
+ {
+ for (j = 0 ; j < 8; j++)
+ ciphertext[8 * i + j] = R[8 * i + j];
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Misc function to decrypt AES body
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ This function references to RFC 3394 for aes key unwrap algorithm.
+
+ ========================================================================
+*/
+VOID AES_GTK_KEY_UNWRAP(
+ IN UCHAR *key,
+ OUT UCHAR *plaintext,
+ IN UCHAR c_len,
+ IN UCHAR *ciphertext)
+
+{
+ UCHAR A[8], BIN[16], BOUT[16];
+ UCHAR xor;
+ INT i, j;
+ aes_context aesctx;
+ UCHAR *R;
+ INT num_blocks = c_len/8; // unit:64bits
+
+
+ os_alloc_mem(NULL, (PUCHAR *)&R, 512);
+
+ if (R == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!AES_GTK_KEY_UNWRAP: no memory!!!\n"));
+ return;
+ } /* End of if */
+
+ // Initialize
+ NdisMoveMemory(A, ciphertext, 8);
+ //Input plaintext
+ for(i = 0; i < (c_len-8); i++)
+ {
+ R[ i] = ciphertext[i + 8];
+ }
+
+ rtmp_aes_set_key(&aesctx, key, 128);
+
+ for(j = 5; j >= 0; j--)
+ {
+ for(i = (num_blocks-1); i > 0; i--)
+ {
+ xor = (num_blocks -1 )* j + i;
+ NdisMoveMemory(BIN, A, 8);
+ BIN[7] = A[7] ^ xor;
+ NdisMoveMemory(&BIN[8], &R[(i-1)*8], 8);
+ rtmp_aes_decrypt(&aesctx, BIN, BOUT);
+ NdisMoveMemory(A, &BOUT[0], 8);
+ NdisMoveMemory(&R[(i-1)*8], &BOUT[8], 8);
+ }
+ }
+
+ // OUTPUT
+ for(i = 0; i < c_len; i++)
+ {
+ plaintext[i] = R[i];
+ }
+
+
+ os_free_mem(NULL, R);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Report the EAP message type
+
+ Arguments:
+ msg - EAPOL_PAIR_MSG_1
+ EAPOL_PAIR_MSG_2
+ EAPOL_PAIR_MSG_3
+ EAPOL_PAIR_MSG_4
+ EAPOL_GROUP_MSG_1
+ EAPOL_GROUP_MSG_2
+
+ Return:
+ message type string
+
+ ==========================================================================
+*/
+CHAR *GetEapolMsgType(CHAR msg)
+{
+ if(msg == EAPOL_PAIR_MSG_1)
+ return "Pairwise Message 1";
+ else if(msg == EAPOL_PAIR_MSG_2)
+ return "Pairwise Message 2";
+ else if(msg == EAPOL_PAIR_MSG_3)
+ return "Pairwise Message 3";
+ else if(msg == EAPOL_PAIR_MSG_4)
+ return "Pairwise Message 4";
+ else if(msg == EAPOL_GROUP_MSG_1)
+ return "Group Message 1";
+ else if(msg == EAPOL_GROUP_MSG_2)
+ return "Group Message 2";
+ else
+ return "Invalid Message";
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Check Sanity RSN IE of EAPoL message
+
+ Arguments:
+
+ Return Value:
+
+
+ ========================================================================
+*/
+BOOLEAN RTMPCheckRSNIE(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN UCHAR DataLen,
+ IN MAC_TABLE_ENTRY *pEntry,
+ OUT UCHAR *Offset)
+{
+ PUCHAR pVIE;
+ UCHAR len;
+ PEID_STRUCT pEid;
+ BOOLEAN result = FALSE;
+
+ pVIE = pData;
+ len = DataLen;
+ *Offset = 0;
+
+ while (len > sizeof(RSNIE2))
+ {
+ pEid = (PEID_STRUCT) pVIE;
+ // WPA RSN IE
+ if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
+ {
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
+ (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
+ (pEntry->RSNIE_Len == (pEid->Len + 2)))
+ {
+ result = TRUE;
+ }
+
+ *Offset += (pEid->Len + 2);
+ }
+ // WPA2 RSN IE
+ else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
+ {
+ if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
+ (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
+ (pEntry->RSNIE_Len == (pEid->Len + 2))/* ToDo-AlbertY for mesh*/)
+ {
+ result = TRUE;
+ }
+
+ *Offset += (pEid->Len + 2);
+ }
+ else
+ {
+ break;
+ }
+
+ pVIE += (pEid->Len + 2);
+ len -= (pEid->Len + 2);
+ }
+
+
+ return result;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
+ GTK is encaptulated in KDE format at p.83 802.11i D10
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+ 802.11i D10
+
+ ========================================================================
+*/
+BOOLEAN RTMPParseEapolKeyData(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKeyData,
+ IN UCHAR KeyDataLen,
+ IN UCHAR GroupKeyIndex,
+ IN UCHAR MsgType,
+ IN BOOLEAN bWPA2,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ PKDE_ENCAP pKDE = NULL;
+ PUCHAR pMyKeyData = pKeyData;
+ UCHAR KeyDataLength = KeyDataLen;
+ UCHAR GTKLEN = 0;
+ UCHAR DefaultIdx = 0;
+ UCHAR skip_offset;
+
+ // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
+ if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
+ {
+ // Check RSN IE whether it is WPA2/WPA2PSK
+ if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
+ {
+ // send wireless event - for RSN IE different
+ if (pAd->CommonCfg.bWirelessEvent)
+ RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
+ hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
+ hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
+
+ return FALSE;
+ }
+ else
+ {
+ if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
+ {
+ // skip RSN IE
+ pMyKeyData += skip_offset;
+ KeyDataLength -= skip_offset;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
+ }
+ else
+ return TRUE;
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
+
+ // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
+ if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
+ {
+ if (KeyDataLength >= 8) // KDE format exclude GTK length
+ {
+ pKDE = (PKDE_ENCAP) pMyKeyData;
+
+
+ DefaultIdx = pKDE->GTKEncap.Kid;
+
+ // Sanity check - KED length
+ if (KeyDataLength < (pKDE->Len + 2))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
+ return FALSE;
+ }
+
+ // Get GTK length - refer to IEEE 802.11i-2004 p.82
+ GTKLEN = pKDE->Len -6;
+ if (GTKLEN < LEN_AES_KEY)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
+ return FALSE;
+ }
+
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
+ return FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
+ // skip it
+ pMyKeyData += 8;
+ KeyDataLength -= 8;
+
+ }
+ else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
+ {
+ DefaultIdx = GroupKeyIndex;
+ DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
+ }
+
+ // Sanity check - shared key index must be 1 ~ 3
+ if (DefaultIdx < 1 || DefaultIdx > 3)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
+ return FALSE;
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+ // Todo
+#endif // CONFIG_STA_SUPPORT //
+
+ return TRUE;
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct EAPoL message for WPA handshaking
+ Its format is below,
+
+ +--------------------+
+ | Protocol Version | 1 octet
+ +--------------------+
+ | Protocol Type | 1 octet
+ +--------------------+
+ | Body Length | 2 octets
+ +--------------------+
+ | Descriptor Type | 1 octet
+ +--------------------+
+ | Key Information | 2 octets
+ +--------------------+
+ | Key Length | 1 octet
+ +--------------------+
+ | Key Repaly Counter | 8 octets
+ +--------------------+
+ | Key Nonce | 32 octets
+ +--------------------+
+ | Key IV | 16 octets
+ +--------------------+
+ | Key RSC | 8 octets
+ +--------------------+
+ | Key ID or Reserved | 8 octets
+ +--------------------+
+ | Key MIC | 16 octets
+ +--------------------+
+ | Key Data Length | 2 octets
+ +--------------------+
+ | Key Data | n octets
+ +--------------------+
+
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID ConstructEapolMsg(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR AuthMode,
+ IN UCHAR WepStatus,
+ IN UCHAR GroupKeyWepStatus,
+ IN UCHAR MsgType,
+ IN UCHAR DefaultKeyIdx,
+ IN UCHAR *ReplayCounter,
+ IN UCHAR *KeyNonce,
+ IN UCHAR *TxRSC,
+ IN UCHAR *PTK,
+ IN UCHAR *GTK,
+ IN UCHAR *RSNIE,
+ IN UCHAR RSNIE_Len,
+ OUT PEAPOL_PACKET pMsg)
+{
+ BOOLEAN bWPA2 = FALSE;
+
+ // Choose WPA2 or not
+ if ((AuthMode == Ndis802_11AuthModeWPA2) || (AuthMode == Ndis802_11AuthModeWPA2PSK))
+ bWPA2 = TRUE;
+
+ // Init Packet and Fill header
+ pMsg->ProVer = EAPOL_VER;
+ pMsg->ProType = EAPOLKey;
+
+ // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
+ pMsg->Body_Len[1] = LEN_EAPOL_KEY_MSG;
+
+ // Fill in EAPoL descriptor
+ if (bWPA2)
+ pMsg->KeyDesc.Type = WPA2_KEY_DESC;
+ else
+ pMsg->KeyDesc.Type = WPA1_KEY_DESC;
+
+ // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
+ // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
+ pMsg->KeyDesc.KeyInfo.KeyDescVer =
+ (((WepStatus == Ndis802_11Encryption3Enabled) || (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
+
+ // Specify Key Type as Group(0) or Pairwise(1)
+ if (MsgType >= EAPOL_GROUP_MSG_1)
+ pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
+ else
+ pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
+
+ // Specify Key Index, only group_msg1_WPA1
+ if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
+ pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
+
+ if (MsgType == EAPOL_PAIR_MSG_3)
+ pMsg->KeyDesc.KeyInfo.Install = 1;
+
+ if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
+ pMsg->KeyDesc.KeyInfo.KeyAck = 1;
+
+ if (MsgType != EAPOL_PAIR_MSG_1)
+ pMsg->KeyDesc.KeyInfo.KeyMic = 1;
+
+ if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
+ {
+ pMsg->KeyDesc.KeyInfo.Secure = 1;
+ }
+
+ if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
+ {
+ pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
+ }
+
+ // key Information element has done.
+ *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
+
+ // Fill in Key Length
+ {
+ if (MsgType >= EAPOL_GROUP_MSG_1)
+ {
+ // the length of group key cipher
+ pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
+ }
+ else
+ {
+ // the length of pairwise key cipher
+ pMsg->KeyDesc.KeyLength[1] = ((WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
+ }
+ }
+
+ // Fill in replay counter
+ NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+ // Fill Key Nonce field
+ // ANonce : pairwise_msg1 & pairwise_msg3
+ // SNonce : pairwise_msg2
+ // GNonce : group_msg1_wpa1
+ if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
+ NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
+
+ // Fill key IV - WPA2 as 0, WPA1 as random
+ if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ // Suggest IV be random number plus some number,
+ NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
+ pMsg->KeyDesc.KeyIv[15] += 2;
+ }
+
+ // Fill Key RSC field
+ // It contains the RSC for the GTK being installed.
+ if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
+ }
+
+ // Clear Key MIC field for MIC calculation later
+ NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+
+ ConstructEapolKeyData(pAd,
+ AuthMode,
+ WepStatus,
+ GroupKeyWepStatus,
+ MsgType,
+ DefaultKeyIdx,
+ bWPA2,
+ PTK,
+ GTK,
+ RSNIE,
+ RSNIE_Len,
+ pMsg);
+
+ // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
+ if (MsgType != EAPOL_PAIR_MSG_1)
+ {
+ CalculateMIC(pAd, WepStatus, PTK, pMsg);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
+ DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", pMsg->Body_Len[1]));
+ DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", pMsg->KeyDesc.KeyLength[1]));
+
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Construct the Key Data field of EAPoL message
+
+ Arguments:
+ pAd Pointer to our adapter
+ Elem Message body
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID ConstructEapolKeyData(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR AuthMode,
+ IN UCHAR WepStatus,
+ IN UCHAR GroupKeyWepStatus,
+ IN UCHAR MsgType,
+ IN UCHAR DefaultKeyIdx,
+ IN BOOLEAN bWPA2Capable,
+ IN UCHAR *PTK,
+ IN UCHAR *GTK,
+ IN UCHAR *RSNIE,
+ IN UCHAR RSNIE_LEN,
+ OUT PEAPOL_PACKET pMsg)
+{
+ UCHAR *mpool, *Key_Data, *Rc4GTK;
+ UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
+ UCHAR data_offset;
+
+
+ if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
+ return;
+
+ // allocate memory pool
+ os_alloc_mem(pAd, (PUCHAR *)&mpool, 1500);
+
+ if (mpool == NULL)
+ return;
+
+ /* Rc4GTK Len = 512 */
+ Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
+ /* Key_Data Len = 512 */
+ Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
+
+ NdisZeroMemory(Key_Data, 512);
+ pMsg->KeyDesc.KeyDataLen[1] = 0;
+ data_offset = 0;
+
+ // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
+ if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
+ {
+ if (bWPA2Capable)
+ Key_Data[data_offset + 0] = IE_WPA2;
+ else
+ Key_Data[data_offset + 0] = IE_WPA;
+
+ Key_Data[data_offset + 1] = RSNIE_LEN;
+ NdisMoveMemory(&Key_Data[data_offset + 2], RSNIE, RSNIE_LEN);
+ data_offset += (2 + RSNIE_LEN);
+ }
+
+ // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
+ if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
+ {
+ // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h
+ Key_Data[data_offset + 0] = 0xDD;
+
+ if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+ {
+ Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
+ }
+ else
+ {
+ Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
+ }
+
+ Key_Data[data_offset + 2] = 0x00;
+ Key_Data[data_offset + 3] = 0x0F;
+ Key_Data[data_offset + 4] = 0xAC;
+ Key_Data[data_offset + 5] = 0x01;
+
+ // GTK KDE format - 802.11i-2004 Figure-43x
+ Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
+ Key_Data[data_offset + 7] = 0x00; // Reserved Byte
+
+ data_offset += 8;
+ }
+
+
+ // Encapsulate GTK and encrypt the key-data field with KEK.
+ // Only for pairwise_msg3_WPA2 and group_msg1
+ if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
+ {
+ // Fill in GTK
+ if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+ {
+ NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
+ data_offset += LEN_AES_KEY;
+ }
+ else
+ {
+ NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
+ data_offset += TKIP_GTK_LENGTH;
+ }
+
+ // Still dont know why, but if not append will occur "GTK not include in MSG3"
+ // Patch for compatibility between zero config and funk
+ if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
+ {
+ if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+ {
+ Key_Data[data_offset + 0] = 0xDD;
+ Key_Data[data_offset + 1] = 0;
+ data_offset += 2;
+ }
+ else
+ {
+ Key_Data[data_offset + 0] = 0xDD;
+ Key_Data[data_offset + 1] = 0;
+ Key_Data[data_offset + 2] = 0;
+ Key_Data[data_offset + 3] = 0;
+ Key_Data[data_offset + 4] = 0;
+ Key_Data[data_offset + 5] = 0;
+ data_offset += 6;
+ }
+ }
+
+ // Encrypt the data material in key data field
+ if (WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ AES_GTK_KEY_WRAP(&PTK[16], Key_Data, data_offset, Rc4GTK);
+ // AES wrap function will grow 8 bytes in length
+ data_offset += 8;
+ }
+ else
+ {
+ // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
+ // put TxTsc in Key RSC field
+ pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32.
+
+ // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
+ NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
+ NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &PTK[16], LEN_EAP_EK);
+ ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV)
+ pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
+ WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
+ }
+
+ NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
+ }
+ else
+ {
+ NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
+ }
+
+ // set key data length field and total length
+ pMsg->KeyDesc.KeyDataLen[1] = data_offset;
+ pMsg->Body_Len[1] += data_offset;
+
+ os_free_mem(pAd, mpool);
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calcaulate MIC. It is used during 4-ways handsharking.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ PeerWepStatus - indicate the encryption type
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID CalculateMIC(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR PeerWepStatus,
+ IN UCHAR *PTK,
+ OUT PEAPOL_PACKET pMsg)
+{
+ UCHAR *OutBuffer;
+ ULONG FrameLen = 0;
+ UCHAR mic[LEN_KEY_DESC_MIC];
+ UCHAR digest[80];
+
+ // allocate memory for MIC calculation
+ os_alloc_mem(pAd, (PUCHAR *)&OutBuffer, 512);
+
+ if (OutBuffer == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
+ return;
+ }
+
+ // make a frame for calculating MIC.
+ MakeOutgoingFrame(OutBuffer, &FrameLen,
+ pMsg->Body_Len[1] + 4, pMsg,
+ END_OF_ARGS);
+
+ NdisZeroMemory(mic, sizeof(mic));
+
+ // Calculate MIC
+ if (PeerWepStatus == Ndis802_11Encryption3Enabled)
+ {
+ HMAC_SHA1(OutBuffer, FrameLen, PTK, LEN_EAP_MICK, digest);
+ NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
+ }
+ else
+ {
+ hmac_md5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic);
+ }
+
+ // store the calculated MIC
+ NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
+
+ os_free_mem(pAd, OutBuffer);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Some received frames can't decrypt by Asic, so decrypt them by software.
+
+ Arguments:
+ pAd - pointer to our pAdapter context
+ PeerWepStatus - indicate the encryption type
+
+ Return Value:
+ NDIS_STATUS_SUCCESS - decryption successful
+ NDIS_STATUS_FAILURE - decryption failure
+
+ ========================================================================
+*/
+NDIS_STATUS RTMPSoftDecryptBroadCastData(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher,
+ IN PCIPHER_KEY pShard_key)
+{
+ PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
+
+
+
+ // handle WEP decryption
+ if (GroupCipher == Ndis802_11Encryption1Enabled)
+ {
+ if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
+ {
+
+ //Minus IV[4] & ICV[4]
+ pRxWI->MPDUtotalByteCount -= 8;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
+ // give up this frame
+ return NDIS_STATUS_FAILURE;
+ }
+ }
+ // handle TKIP decryption
+ else if (GroupCipher == Ndis802_11Encryption2Enabled)
+ {
+ if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
+ {
+
+ //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
+ pRxWI->MPDUtotalByteCount -= 20;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
+ // give up this frame
+ return NDIS_STATUS_FAILURE;
+ }
+ }
+ // handle AES decryption
+ else if (GroupCipher == Ndis802_11Encryption3Enabled)
+ {
+ if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
+ {
+
+ //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
+ pRxWI->MPDUtotalByteCount -= 16;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
+ // give up this frame
+ return NDIS_STATUS_FAILURE;
+ }
+ }
+ else
+ {
+ // give up this frame
+ return NDIS_STATUS_FAILURE;
+ }
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
diff --git a/drivers/staging/rt2860/common/dfs.c b/drivers/staging/rt2860/common/dfs.c
new file mode 100644
index 000000000000..b09bba5cb206
--- /dev/null
+++ b/drivers/staging/rt2860/common/dfs.c
@@ -0,0 +1,453 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ ap_dfs.c
+
+ Abstract:
+ Support DFS function.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Fonchi 03-12-2007 created
+*/
+
+#include "../rt_config.h"
+
+typedef struct _RADAR_DURATION_TABLE
+{
+ ULONG RDDurRegion;
+ ULONG RadarSignalDuration;
+ ULONG Tolerance;
+} RADAR_DURATION_TABLE, *PRADAR_DURATION_TABLE;
+
+
+static UCHAR RdIdleTimeTable[MAX_RD_REGION][4] =
+{
+ {9, 250, 250, 250}, // CE
+ {4, 250, 250, 250}, // FCC
+ {4, 250, 250, 250}, // JAP
+ {15, 250, 250, 250}, // JAP_W53
+ {4, 250, 250, 250} // JAP_W56
+};
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Bbp Radar detection routine
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+
+ ========================================================================
+*/
+VOID BbpRadarDetectionStart(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT8 RadarPeriod;
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 114, 0x02);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 121, 0x20);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 122, 0x00);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 123, 0x08/*0x80*/);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 124, 0x28);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, 125, 0xff);
+
+#if 0
+ // toggle Rx enable bit for radar detection.
+ // it's Andy's recommand.
+ {
+ UINT32 Value;
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= (0x1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ Value &= ~(0x1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ }
+#endif
+ RadarPeriod = ((UINT)RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + (UINT)pAd->CommonCfg.RadarDetect.DfsSessionTime) < 250 ?
+ (RdIdleTimeTable[pAd->CommonCfg.RadarDetect.RDDurRegion][0] + pAd->CommonCfg.RadarDetect.DfsSessionTime) : 250;
+
+ RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
+ RTMP_IO_WRITE8(pAd, 0x7021, 0x40);
+
+ RadarDetectionStart(pAd, 0, RadarPeriod);
+ return;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Bbp Radar detection routine
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+
+ ========================================================================
+*/
+VOID BbpRadarDetectionStop(
+ IN PRTMP_ADAPTER pAd)
+{
+ RTMP_IO_WRITE8(pAd, 0x7020, 0x1d);
+ RTMP_IO_WRITE8(pAd, 0x7021, 0x60);
+
+ RadarDetectionStop(pAd);
+ return;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Radar detection routine
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+
+ ========================================================================
+*/
+VOID RadarDetectionStart(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN CTSProtect,
+ IN UINT8 CTSPeriod)
+{
+ UINT8 DfsActiveTime = (pAd->CommonCfg.RadarDetect.DfsSessionTime & 0x1f);
+ UINT8 CtsProtect = (CTSProtect == 1) ? 0x02 : 0x01; // CTS protect.
+
+ if (CTSProtect != 0)
+ {
+ switch(pAd->CommonCfg.RadarDetect.RDDurRegion)
+ {
+ case FCC:
+ case JAP_W56:
+ CtsProtect = 0x03;
+ break;
+
+ case CE:
+ case JAP_W53:
+ default:
+ CtsProtect = 0x02;
+ break;
+ }
+ }
+ else
+ CtsProtect = 0x01;
+
+
+ // send start-RD with CTS protection command to MCU
+ // highbyte [7] reserve
+ // highbyte [6:5] 0x: stop Carrier/Radar detection
+ // highbyte [10]: Start Carrier/Radar detection without CTS protection, 11: Start Carrier/Radar detection with CTS protection
+ // highbyte [4:0] Radar/carrier detection duration. In 1ms.
+
+ // lowbyte [7:0] Radar/carrier detection period, in 1ms.
+ AsicSendCommandToMcu(pAd, 0x60, 0xff, CTSPeriod, DfsActiveTime | (CtsProtect << 5));
+ //AsicSendCommandToMcu(pAd, 0x63, 0xff, 10, 0);
+
+ return;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Radar detection routine
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ TRUE Found radar signal
+ FALSE Not found radar signal
+
+ ========================================================================
+*/
+VOID RadarDetectionStop(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE,("RadarDetectionStop.\n"));
+ AsicSendCommandToMcu(pAd, 0x60, 0xff, 0x00, 0x00); // send start-RD with CTS protection command to MCU
+
+ return;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Radar channel check routine
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ TRUE need to do radar detect
+ FALSE need not to do radar detect
+
+ ========================================================================
+*/
+BOOLEAN RadarChannelCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Ch)
+{
+#if 1
+ INT i;
+ BOOLEAN result = FALSE;
+
+ for (i=0; i<pAd->ChannelListNum; i++)
+ {
+ if (Ch == pAd->ChannelList[i].Channel)
+ {
+ result = pAd->ChannelList[i].DfsReq;
+ break;
+ }
+ }
+
+ return result;
+#else
+ INT i;
+ UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+
+ for (i=0; i<15; i++)
+ {
+ if (Ch == Channel[i])
+ {
+ break;
+ }
+ }
+
+ if (i != 15)
+ return TRUE;
+ else
+ return FALSE;
+#endif
+}
+
+ULONG JapRadarType(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG i;
+ const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
+
+ if (pAd->CommonCfg.RadarDetect.RDDurRegion != JAP)
+ {
+ return pAd->CommonCfg.RadarDetect.RDDurRegion;
+ }
+
+ for (i=0; i<15; i++)
+ {
+ if (pAd->CommonCfg.Channel == Channel[i])
+ {
+ break;
+ }
+ }
+
+ if (i < 4)
+ return JAP_W53;
+ else if (i < 15)
+ return JAP_W56;
+ else
+ return JAP; // W52
+
+}
+
+ULONG RTMPBbpReadRadarDuration(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT8 byteValue = 0;
+ ULONG result;
+
+ BBP_IO_READ8_BY_REG_ID(pAd, BBP_R115, &byteValue);
+
+ result = 0;
+ switch (byteValue)
+ {
+ case 1: // radar signal detected by pulse mode.
+ case 2: // radar signal detected by width mode.
+ result = RTMPReadRadarDuration(pAd);
+ break;
+
+ case 0: // No radar signal.
+ default:
+
+ result = 0;
+ break;
+ }
+
+ return result;
+}
+
+ULONG RTMPReadRadarDuration(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG result = 0;
+
+#ifdef DFS_SUPPORT
+ UINT8 duration1 = 0, duration2 = 0, duration3 = 0;
+
+ BBP_IO_READ8_BY_REG_ID(pAd, BBP_R116, &duration1);
+ BBP_IO_READ8_BY_REG_ID(pAd, BBP_R117, &duration2);
+ BBP_IO_READ8_BY_REG_ID(pAd, BBP_R118, &duration3);
+ result = (duration1 << 16) + (duration2 << 8) + duration3;
+#endif // DFS_SUPPORT //
+
+ return result;
+
+}
+
+VOID RTMPCleanRadarDuration(
+ IN PRTMP_ADAPTER pAd)
+{
+ return;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Radar wave detection. The API should be invoke each second.
+
+ Arguments:
+ pAd - Adapter pointer
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID ApRadarDetectPeriodic(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT i;
+
+ pAd->CommonCfg.RadarDetect.InServiceMonitorCount++;
+
+ for (i=0; i<pAd->ChannelListNum; i++)
+ {
+ if (pAd->ChannelList[i].RemainingTimeForUse > 0)
+ {
+ pAd->ChannelList[i].RemainingTimeForUse --;
+ if ((pAd->Mlme.PeriodicRound%5) == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse));
+ }
+ }
+ }
+
+ //radar detect
+ if ((pAd->CommonCfg.Channel > 14)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+ {
+ RadarDetectPeriodic(pAd);
+ }
+
+ return;
+}
+
+// Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt()
+// Before switch channel, driver needs doing channel switch announcement.
+VOID RadarDetectPeriodic(
+ IN PRTMP_ADAPTER pAd)
+{
+ // need to check channel availability, after switch channel
+ if (pAd->CommonCfg.RadarDetect.RDMode != RD_SILENCE_MODE)
+ return;
+
+ // channel availability check time is 60sec, use 65 for assurance
+ if (pAd->CommonCfg.RadarDetect.RDCount++ > pAd->CommonCfg.RadarDetect.ChMovingTime)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n"));
+ BbpRadarDetectionStop(pAd);
+ AsicEnableBssSync(pAd);
+ pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
+
+
+ return;
+ }
+
+ return;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ change channel moving time for DFS testing.
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ wrq Pointer to the ioctl argument
+
+ Return Value:
+ None
+
+ Note:
+ Usage:
+ 1.) iwpriv ra0 set ChMovTime=[value]
+ ==========================================================================
+*/
+INT Set_ChMovingTime_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT8 Value;
+
+ Value = simple_strtol(arg, 0, 10);
+
+ pAd->CommonCfg.RadarDetect.ChMovingTime = Value;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__,
+ pAd->CommonCfg.RadarDetect.ChMovingTime));
+
+ return TRUE;
+}
+
+INT Set_LongPulseRadarTh_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT8 Value;
+
+ Value = simple_strtol(arg, 0, 10) > 10 ? 10 : simple_strtol(arg, 0, 10);
+
+ pAd->CommonCfg.RadarDetect.LongPulseRadarTh = Value;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s:: %d\n", __func__,
+ pAd->CommonCfg.RadarDetect.LongPulseRadarTh));
+
+ return TRUE;
+}
+
+
diff --git a/drivers/staging/rt2860/common/eeprom.c b/drivers/staging/rt2860/common/eeprom.c
new file mode 100644
index 000000000000..bed2d666629c
--- /dev/null
+++ b/drivers/staging/rt2860/common/eeprom.c
@@ -0,0 +1,244 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ eeprom.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+*/
+#include "../rt_config.h"
+
+// IRQL = PASSIVE_LEVEL
+VOID RaiseClock(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 *x)
+{
+ *x = *x | EESK;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
+ RTMPusecDelay(1); // Max frequency = 1MHz in Spec. definition
+}
+
+// IRQL = PASSIVE_LEVEL
+VOID LowerClock(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 *x)
+{
+ *x = *x & ~EESK;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
+ RTMPusecDelay(1);
+}
+
+// IRQL = PASSIVE_LEVEL
+USHORT ShiftInBits(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x,i;
+ USHORT data=0;
+
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ x &= ~( EEDO | EEDI);
+
+ for(i=0; i<16; i++)
+ {
+ data = data << 1;
+ RaiseClock(pAd, &x);
+
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ x &= ~(EEDI);
+ if(x & EEDO)
+ data |= 1;
+
+ LowerClock(pAd, &x);
+ }
+
+ return data;
+}
+
+// IRQL = PASSIVE_LEVEL
+VOID ShiftOutBits(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT data,
+ IN USHORT count)
+{
+ UINT32 x,mask;
+
+ mask = 0x01 << (count - 1);
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ x &= ~(EEDO | EEDI);
+
+ do
+ {
+ x &= ~EEDI;
+ if(data & mask) x |= EEDI;
+
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ mask = mask >> 1;
+ } while(mask);
+
+ x &= ~EEDI;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+}
+
+// IRQL = PASSIVE_LEVEL
+VOID EEpromCleanup(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x;
+
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ x &= ~(EECS | EEDI);
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+}
+
+VOID EWEN(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x;
+
+ // reset bits and set EECS
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ // kick a pulse
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ // output the read_opcode and six pulse in that order
+ ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
+ ShiftOutBits(pAd, 0, 6);
+
+ EEpromCleanup(pAd);
+}
+
+VOID EWDS(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 x;
+
+ // reset bits and set EECS
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ // kick a pulse
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ // output the read_opcode and six pulse in that order
+ ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
+ ShiftOutBits(pAd, 0, 6);
+
+ EEpromCleanup(pAd);
+}
+
+// IRQL = PASSIVE_LEVEL
+USHORT RTMP_EEPROM_READ16(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset)
+{
+ UINT32 x;
+ USHORT data;
+
+ Offset /= 2;
+ // reset bits and set EECS
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ // kick a pulse
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ // output the read_opcode and register number in that order
+ ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
+ ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
+
+ // Now read the data (16 bits) in from the selected EEPROM word
+ data = ShiftInBits(pAd);
+
+ EEpromCleanup(pAd);
+
+ return data;
+} //ReadEEprom
+
+VOID RTMP_EEPROM_WRITE16(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Data)
+{
+ UINT32 x;
+
+ Offset /= 2;
+
+ EWEN(pAd);
+
+ // reset bits and set EECS
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+ x &= ~(EEDI | EEDO | EESK);
+ x |= EECS;
+ RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
+
+ // kick a pulse
+ RaiseClock(pAd, &x);
+ LowerClock(pAd, &x);
+
+ // output the read_opcode ,register number and data in that order
+ ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
+ ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
+ ShiftOutBits(pAd, Data, 16); // 16-bit access
+
+ // read DO status
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
+
+ EEpromCleanup(pAd);
+
+ RTMPusecDelay(10000); //delay for twp(MAX)=10ms
+
+ EWDS(pAd);
+
+ EEpromCleanup(pAd);
+}
+
diff --git a/drivers/staging/rt2860/common/firmware.h b/drivers/staging/rt2860/common/firmware.h
new file mode 100644
index 000000000000..e72996f42c07
--- /dev/null
+++ b/drivers/staging/rt2860/common/firmware.h
@@ -0,0 +1,558 @@
+/*
+ Copyright (c) 2007, Ralink Technology Corporation
+ All rights reserved.
+
+ Redistribution. Redistribution and use in binary form, without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions must reproduce the above copyright notice and the
+ following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of Ralink Technology Corporation nor the names of its
+ suppliers may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+ * No reverse engineering, decompilation, or disassembly of this software
+ is permitted.
+
+ Limited patent license. Ralink Technology Corporation grants a world-wide,
+ royalty-free, non-exclusive license under patents it now or hereafter
+ owns or controls to make, have made, use, import, offer to sell and
+ sell ("Utilize") this software, but solely to the extent that any
+ such patent is necessary to Utilize the software alone, or in
+ combination with an operating system licensed under an approved Open
+ Source license as listed by the Open Source Initiative at
+ http://opensource.org/licenses. The patent license shall not apply to
+ any other combinations which include this software. No hardware per
+ se is licensed hereunder.
+
+ DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+*/
+/* AUTO GEN PLEASE DO NOT MODIFY IT */
+/* AUTO GEN PLEASE DO NOT MODIFY IT */
+
+
+UCHAR FirmwareImage [] = {
+0x02, 0x03, 0x5e, 0x02, 0x02, 0xb1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x82, 0xff, 0xff,
+0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x33, 0xc0, 0xe0,
+0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03,
+0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14,
+0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x2f,
+0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14,
+0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24,
+0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5,
+0x50, 0x85, 0x2f, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55,
+0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x2f, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf,
+0x2f, 0x12, 0x02, 0x8d, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0,
+0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf,
+0x2f, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0,
+0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x53, 0xc2,
+0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d,
+0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x30, 0x90,
+0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10,
+0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a,
+0x0d, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0xc2, 0x05,
+0xd2, 0xaf, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0xe8, 0xc0, 0xe0,
+0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, 0xeb, 0xc0, 0xe0, 0xec, 0xc0, 0xe0, 0xed, 0xc0, 0xe0, 0xee,
+0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x12, 0xd2, 0xaf, 0xd0,
+0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, 0xe0, 0xfd, 0xd0, 0xe0, 0xfc, 0xd0, 0xe0, 0xfb, 0xd0, 0xe0,
+0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, 0xf8, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0,
+0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0xc2,
+0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0c, 0x30, 0x58, 0x0a, 0xe5, 0x54, 0x60, 0x04, 0x15, 0x54,
+0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, 0x0a, 0xe5, 0x50, 0x60, 0x04, 0x15, 0x50, 0x80, 0x02, 0xc2,
+0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, 0x04, 0x15, 0x46, 0xd2, 0x04, 0x30, 0x45, 0x03, 0x12, 0x10,
+0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32,
+0x12, 0x02, 0xd3, 0x30, 0x45, 0x03, 0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12,
+0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, 0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b,
+0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, 0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09,
+0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, 0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12,
+0x02, 0xec, 0x80, 0xbf, 0xc2, 0x43, 0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5,
+0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, 0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18,
+0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, 0x74, 0x08, 0xf0, 0xc2, 0x19, 0xc2, 0x18, 0xc2, 0x1a, 0x22,
+0xc8, 0xef, 0xc8, 0xe6, 0xfa, 0x08, 0xe6, 0x4a, 0x60, 0x0c, 0xc8, 0xef, 0xc8, 0x08, 0xe6, 0x16,
+0x18, 0x70, 0x01, 0x16, 0xc3, 0x22, 0xed, 0x24, 0xff, 0xfd, 0xec, 0x34, 0xff, 0xc8, 0xef, 0xc8,
+0xf6, 0x08, 0xc6, 0xed, 0xc6, 0xd3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12,
+0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83,
+0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60,
+0x1f, 0xe4, 0xfe, 0x12, 0x03, 0x6a, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x03, 0x6a, 0xef, 0xf0, 0x74,
+0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3,
+0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf,
+0x30, 0x45, 0x03, 0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0,
+0xd0, 0xe0, 0x32, 0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x02, 0x14, 0x12, 0x03, 0x1c, 0xe4, 0xf5,
+0x22, 0xf5, 0x47, 0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x30, 0x45, 0x03, 0x12,
+0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, 0x43, 0x87, 0x01, 0x22,
+0xc0, 0x2a, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x0a, 0x22, 0xc0, 0x2a,
+0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x18, 0x22, 0x75, 0x89, 0x02, 0xe4,
+0xf5, 0x8c, 0xf5, 0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75,
+0xa8, 0x05, 0x22, 0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x03, 0x80, 0x1e, 0x80,
+0xf5, 0x22, 0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x03, 0x16, 0xc3, 0x22, 0xed, 0x14, 0xf6, 0xd3, 0x22,
+0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x06, 0x16, 0xe6, 0x24, 0xff, 0xb3, 0x22, 0xc3, 0x22, 0x78, 0x7f,
+0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0xd0, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4,
+0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x03, 0x7e, 0x93, 0x90, 0x03, 0x00, 0x73, 0x0a, 0x18,
+0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x3b, 0x02, 0x10, 0x3c, 0x02, 0x12, 0xb8, 0x02,
+0x12, 0xb9, 0x02, 0x13, 0x3e, 0x02, 0x13, 0x3f, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x16, 0x56, 0x02,
+0x17, 0x6b, 0x02, 0x14, 0x2a, 0x02, 0x13, 0x40, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x00,
+0xd8, 0x30, 0x06, 0x06, 0x20, 0x0e, 0x03, 0x12, 0x18, 0x5e, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0,
+0x20, 0xe7, 0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0,
+0x12, 0x02, 0x67, 0x11, 0x4e, 0x30, 0x11, 0x25, 0x31, 0x10, 0x87, 0x33, 0x10, 0xaa, 0x34, 0x10,
+0xc3, 0x35, 0x11, 0x57, 0x50, 0x11, 0x7b, 0x51, 0x11, 0x84, 0x52, 0x11, 0x84, 0x53, 0x11, 0x84,
+0x54, 0x11, 0xc5, 0x55, 0x11, 0xdc, 0x70, 0x12, 0x07, 0x71, 0x12, 0x34, 0x72, 0x12, 0x5e, 0x80,
+0x12, 0x81, 0x83, 0x00, 0x00, 0x12, 0xb7, 0x75, 0x24, 0x05, 0x75, 0x25, 0xdc, 0x90, 0x70, 0x9f,
+0x74, 0x12, 0xf0, 0xd2, 0x18, 0xd2, 0x61, 0x75, 0x35, 0x0d, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
+0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0xc2, 0x18, 0x90, 0x01, 0x14, 0xe0,
+0x54, 0xfd, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7,
+0x02, 0x12, 0xaa, 0xe5, 0x55, 0x64, 0x02, 0x70, 0x37, 0x90, 0x70, 0x10, 0xe0, 0x60, 0x08, 0x90,
+0x01, 0x0d, 0x74, 0x09, 0xf0, 0x80, 0x25, 0xe5, 0x34, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14,
+0x60, 0x14, 0x24, 0x03, 0x70, 0x16, 0x90, 0x01, 0x0d, 0x74, 0x08, 0xf0, 0x80, 0x0e, 0x90, 0x01,
+0x0d, 0x74, 0x0b, 0xf0, 0x80, 0x06, 0x90, 0x01, 0x0d, 0x74, 0x1b, 0xf0, 0x7d, 0x01, 0x80, 0x02,
+0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x90,
+0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
+0x12, 0xb7, 0x02, 0x12, 0xaa, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf, 0x56, 0x12,
+0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4,
+0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, 0x90, 0x70,
+0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60,
+0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60,
+0x03, 0x02, 0x12, 0xb7, 0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24,
+0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70,
+0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff,
+0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
+0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
+0x12, 0xb7, 0x02, 0x12, 0xaa, 0xe5, 0x47, 0xb4, 0x07, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x07,
+0xf5, 0x26, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x22, 0x90, 0x70, 0x10, 0xe0,
+0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02,
+0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
+0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0,
+0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
+0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
+0x12, 0xb7, 0x80, 0x76, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x26, 0xff, 0xc2, 0x19, 0xc2, 0x18,
+0xc2, 0x1a, 0x75, 0x34, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74,
+0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x5b, 0x80, 0x4c, 0x90, 0x70,
+0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
+0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x38, 0x80,
+0x29, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x34, 0xd3, 0x94, 0x00, 0x40, 0x07, 0x90, 0x01, 0x0d, 0xe0,
+0x54, 0xfb, 0xf0, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
+0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x0d, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01,
+0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x13, 0x3d,
+0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0xa2, 0x19,
+0xe4, 0x33, 0x90, 0x70, 0x90, 0xf0, 0xa2, 0x18, 0xe4, 0x33, 0xa3, 0xf0, 0x30, 0x19, 0x4d, 0x90,
+0x70, 0x98, 0x74, 0x23, 0xf0, 0xa3, 0xe5, 0x25, 0xf0, 0xe5, 0x24, 0xa3, 0xf0, 0x7f, 0x35, 0x7d,
+0x32, 0x12, 0x03, 0x42, 0x50, 0x09, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf7, 0xf0, 0xd2, 0x06, 0xe5,
+0x35, 0xd3, 0x94, 0x10, 0x40, 0x1e, 0x30, 0x1a, 0x1b, 0xc2, 0x1a, 0xa2, 0x18, 0x92, 0x19, 0x20,
+0x19, 0x12, 0x90, 0x04, 0x09, 0xe0, 0x54, 0xdd, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x08, 0xf0,
+0xc2, 0x61, 0xd2, 0x03, 0xe5, 0x35, 0xb4, 0x0b, 0x14, 0xd2, 0x03, 0x22, 0xe4, 0xf5, 0x35, 0xa2,
+0x18, 0x92, 0x19, 0x30, 0x19, 0x07, 0x90, 0x04, 0x09, 0xe0, 0x44, 0x22, 0xf0, 0x22, 0x22, 0x22,
+0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x02, 0x67, 0x13, 0x62, 0x00, 0x13, 0xf5, 0x04, 0x13,
+0xf1, 0x08, 0x13, 0xcc, 0x10, 0x13, 0x76, 0x20, 0x13, 0x96, 0x60, 0x13, 0xa7, 0xa0, 0x00, 0x00,
+0x13, 0xf7, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60,
+0x03, 0x02, 0x13, 0xf7, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4,
+0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70,
+0x66, 0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5,
+0x47, 0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b,
+0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06,
+0x70, 0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04,
+0x06, 0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75,
+0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80,
+0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x38, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff,
+0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3,
+0xe5, 0x4a, 0xf0, 0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3,
+0xe5, 0x42, 0xf0, 0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0,
+0x70, 0x03, 0x12, 0x16, 0x36, 0x12, 0x14, 0x3f, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2,
+0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x1c, 0x80, 0x08, 0xe5, 0x4e, 0x45,
+0x4f, 0x24, 0xff, 0x92, 0x1c, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x1d, 0x74,
+0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x38, 0x70, 0x13, 0x30, 0x1c, 0x05, 0xe5,
+0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x1d, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5,
+0x38, 0x70, 0x05, 0x75, 0x38, 0x0c, 0x80, 0x02, 0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f,
+0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5,
+0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x38,
+0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x38, 0x70, 0x05, 0x75, 0x38, 0x07, 0x80, 0x02,
+0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5, 0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5,
+0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a,
+0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0,
+0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x15, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2,
+0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
+0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x15, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2,
+0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
+0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x15, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2,
+0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
+0x71, 0x92, 0x70, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x46, 0x90,
+0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe,
+0x60, 0x1f, 0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x35, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0d,
+0x80, 0x07, 0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x04, 0x54, 0xfe, 0xf0, 0x22, 0x44, 0x01, 0xf0,
+0x22, 0xe5, 0x46, 0x30, 0xe3, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02, 0x28, 0xe0,
+0x54, 0xfe, 0x4f, 0xf0, 0x22, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x03, 0x02, 0x16, 0x35, 0xf5, 0x27,
+0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x26, 0x14, 0x60, 0x26, 0x14, 0x60, 0x2e, 0x14,
+0x60, 0x36, 0x24, 0x03, 0x70, 0x5f, 0xe5, 0x46, 0x13, 0x13, 0x13, 0x54, 0x1f, 0x75, 0xf0, 0x03,
+0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff,
+0x80, 0x02, 0xa2, 0x47, 0x92, 0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x3f, 0xe5, 0x46, 0x30,
+0xe3, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe3, 0x0d, 0x54, 0x70, 0xc3,
+0x94, 0x60, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47,
+0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47,
+0xb3, 0x92, 0x39, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02, 0x28, 0xe0,
+0x54, 0xfc, 0x45, 0x27, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45,
+0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59,
+0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x30, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a,
+0x14, 0x60, 0x6a, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x4c, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x20,
+0x19, 0x1c, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x04, 0x34,
+0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, 0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20,
+0x12, 0x16, 0x4c, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x02, 0x17, 0x4c,
+0xe5, 0x50, 0x70, 0x06, 0x75, 0x30, 0x03, 0x02, 0x17, 0x4c, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03,
+0x70, 0x15, 0x7f, 0x20, 0x12, 0x16, 0x4c, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb,
+0xf0, 0x75, 0x51, 0x02, 0x02, 0x17, 0x4c, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x7a, 0x20, 0x19, 0x0f,
+0x90, 0x02, 0x08, 0xe0, 0x20, 0xe3, 0x6c, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x64, 0x90,
+0x12, 0x04, 0x74, 0x0a, 0xf0, 0x30, 0x1b, 0x11, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3,
+0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x04, 0x01, 0xe0,
+0x44, 0x10, 0xf0, 0xe5, 0x34, 0xf4, 0x90, 0x04, 0x01, 0x60, 0x06, 0xe0, 0x54, 0xfb, 0xf0, 0x80,
+0x04, 0xe0, 0x54, 0xf9, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x04, 0xf0, 0xe5,
+0x34, 0xf4, 0x60, 0x14, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40,
+0x07, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x30, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5,
+0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x30, 0x03, 0xf5, 0x51, 0xe5, 0x30, 0x60, 0x18,
+0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0x20, 0x19, 0x0e, 0xad, 0x30, 0xaf, 0x40, 0x12, 0x18,
+0x2a, 0xe5, 0x30, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x0e,
+0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x18, 0x2a, 0xe5, 0x52,
+0x14, 0x60, 0x55, 0x14, 0x60, 0x2f, 0x24, 0x02, 0x60, 0x03, 0x02, 0x18, 0x27, 0xe5, 0x34, 0xf4,
+0x60, 0x23, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40, 0x16, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x02, 0xf0,
+0x90, 0x01, 0x0d, 0xe0, 0x20, 0xe3, 0x03, 0x02, 0x18, 0x27, 0x7f, 0x50, 0x12, 0x16, 0x51, 0x75,
+0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x34, 0xf4, 0x60, 0x0a, 0xe5, 0x54, 0x70, 0x69, 0x90, 0x01,
+0x0d, 0xe5, 0x33, 0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, 0x12, 0x16, 0x51,
+0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x80, 0x4f, 0xe5, 0x54, 0x70, 0x4b, 0x90, 0x04, 0x01, 0xe0,
+0x44, 0x0e, 0xf0, 0x20, 0x19, 0x04, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f,
+0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03,
+0xf0, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44,
+0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41,
+0x12, 0x18, 0x2a, 0x80, 0x02, 0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe,
+0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14,
+0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4,
+0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x20, 0x19,
+0x03, 0x02, 0x19, 0x0f, 0x90, 0x70, 0x80, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x37, 0xe0, 0x30, 0xe5,
+0x03, 0x02, 0x19, 0x0b, 0x90, 0x04, 0x28, 0xe0, 0xf5, 0x31, 0xa3, 0xe0, 0xf5, 0x30, 0xf5, 0x32,
+0xe4, 0xf5, 0x37, 0x90, 0x70, 0x81, 0xe0, 0x04, 0xf0, 0x90, 0x70, 0x82, 0xe0, 0x04, 0xf0, 0xe5,
+0x32, 0x75, 0xf0, 0x80, 0xa4, 0x24, 0x00, 0xff, 0xe5, 0xf0, 0x34, 0x80, 0xfe, 0xe5, 0x30, 0x65,
+0x32, 0x70, 0x05, 0xfc, 0x7d, 0x18, 0x80, 0x04, 0x7c, 0x00, 0x7d, 0x00, 0xef, 0x2d, 0xff, 0xee,
+0x3c, 0xfe, 0x12, 0x19, 0x10, 0x50, 0x25, 0x90, 0x70, 0x83, 0xe0, 0x04, 0xf0, 0x90, 0x01, 0x14,
+0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x30, 0xe1, 0x06, 0x90, 0x70, 0x92, 0x74, 0x45, 0xf0, 0x90, 0x70,
+0x93, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x90, 0x70, 0x94, 0xf0, 0xe5, 0x32, 0x65, 0x31,
+0x60, 0x10, 0xe4, 0x25, 0x32, 0xff, 0xe4, 0x34, 0x80, 0x8f, 0x82, 0xf5, 0x83, 0xe0, 0xf5, 0x32,
+0x80, 0x97, 0x90, 0x04, 0x10, 0x74, 0x01, 0xf0, 0x90, 0x04, 0x28, 0xe5, 0x31, 0xf0, 0xa3, 0xe5,
+0x30, 0xf0, 0x90, 0x04, 0x11, 0x74, 0x01, 0xf0, 0x02, 0x18, 0x6a, 0xc2, 0x06, 0xd2, 0x1a, 0x22,
+0x90, 0x70, 0x84, 0xe5, 0x37, 0xf0, 0xc3, 0x94, 0x06, 0x50, 0x19, 0x8f, 0x82, 0x8e, 0x83, 0xe0,
+0xb4, 0xff, 0x07, 0x05, 0x37, 0xe4, 0xf5, 0x36, 0x80, 0x59, 0xe4, 0xf5, 0x37, 0x8f, 0x82, 0x8e,
+0x83, 0xf0, 0x80, 0x4f, 0xe5, 0x36, 0x75, 0xf0, 0x06, 0x84, 0x74, 0x08, 0x25, 0xf0, 0xf5, 0x82,
+0xe4, 0x34, 0x10, 0xf5, 0x83, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0x6d, 0x70, 0x30,
+0x90, 0x70, 0x88, 0xe0, 0x04, 0xf0, 0xa3, 0xe0, 0xfd, 0xd3, 0x95, 0x37, 0x40, 0x02, 0x80, 0x02,
+0xad, 0x37, 0x90, 0x70, 0x89, 0xed, 0xf0, 0x05, 0x37, 0x05, 0x36, 0xe5, 0x36, 0x75, 0xf0, 0x06,
+0x84, 0x74, 0x8a, 0x25, 0xf0, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x03,
+0xe4, 0xf5, 0x37, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0xef, 0x54, 0x7f, 0x60, 0x0a, 0xe5, 0x37, 0xc3,
+0x94, 0x4e, 0x50, 0x03, 0x02, 0x19, 0x10, 0xe5, 0x37, 0xb4, 0x4e, 0x03, 0xd3, 0x80, 0x01, 0xc3,
+0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x94, 0xeb, } ;
diff --git a/drivers/staging/rt2860/common/md5.c b/drivers/staging/rt2860/common/md5.c
new file mode 100644
index 000000000000..774776b4b8c3
--- /dev/null
+++ b/drivers/staging/rt2860/common/md5.c
@@ -0,0 +1,1427 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ md5.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ jan 10-28-03 Initial
+ Rita 11-23-04 Modify MD5 and SHA-1
+ Rita 10-14-05 Modify SHA-1 in big-endian platform
+ */
+#include "../rt_config.h"
+
+/**
+ * md5_mac:
+ * @key: pointer to the key used for MAC generation
+ * @key_len: length of the key in bytes
+ * @data: pointer to the data area for which the MAC is generated
+ * @data_len: length of the data in bytes
+ * @mac: pointer to the buffer holding space for the MAC; the buffer should
+ * have space for 128-bit (16 bytes) MD5 hash value
+ *
+ * md5_mac() determines the message authentication code by using secure hash
+ * MD5(key | data | key).
+ */
+void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac)
+{
+ MD5_CTX context;
+
+ MD5Init(&context);
+ MD5Update(&context, key, key_len);
+ MD5Update(&context, data, data_len);
+ MD5Update(&context, key, key_len);
+ MD5Final(mac, &context);
+}
+
+/**
+ * hmac_md5:
+ * @key: pointer to the key used for MAC generation
+ * @key_len: length of the key in bytes
+ * @data: pointer to the data area for which the MAC is generated
+ * @data_len: length of the data in bytes
+ * @mac: pointer to the buffer holding space for the MAC; the buffer should
+ * have space for 128-bit (16 bytes) MD5 hash value
+ *
+ * hmac_md5() determines the message authentication code using HMAC-MD5.
+ * This implementation is based on the sample code presented in RFC 2104.
+ */
+void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac)
+{
+ MD5_CTX context;
+ u8 k_ipad[65]; /* inner padding - key XORd with ipad */
+ u8 k_opad[65]; /* outer padding - key XORd with opad */
+ u8 tk[16];
+ int i;
+
+ //assert(key != NULL && data != NULL && mac != NULL);
+
+ /* if key is longer than 64 bytes reset it to key = MD5(key) */
+ if (key_len > 64) {
+ MD5_CTX ttcontext;
+
+ MD5Init(&ttcontext);
+ MD5Update(&ttcontext, key, key_len);
+ MD5Final(tk, &ttcontext);
+ //key=(PUCHAR)ttcontext.buf;
+ key = tk;
+ key_len = 16;
+ }
+
+ /* the HMAC_MD5 transform looks like:
+ *
+ * MD5(K XOR opad, MD5(K XOR ipad, text))
+ *
+ * where K is an n byte key
+ * ipad is the byte 0x36 repeated 64 times
+ * opad is the byte 0x5c repeated 64 times
+ * and text is the data being protected */
+
+ /* start out by storing key in pads */
+ NdisZeroMemory(k_ipad, sizeof(k_ipad));
+ NdisZeroMemory(k_opad, sizeof(k_opad));
+ //assert(key_len < sizeof(k_ipad));
+ NdisMoveMemory(k_ipad, key, key_len);
+ NdisMoveMemory(k_opad, key, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < 64; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner MD5 */
+ MD5Init(&context); /* init context for 1st pass */
+ MD5Update(&context, k_ipad, 64); /* start with inner pad */
+ MD5Update(&context, data, data_len); /* then text of datagram */
+ MD5Final(mac, &context); /* finish up 1st pass */
+
+ /* perform outer MD5 */
+ MD5Init(&context); /* init context for 2nd pass */
+ MD5Update(&context, k_opad, 64); /* start with outer pad */
+ MD5Update(&context, mac, 16); /* then results of 1st hash */
+ MD5Final(mac, &context); /* finish up 2nd pass */
+}
+
+#ifndef RT_BIG_ENDIAN
+#define byteReverse(buf, len) /* Nothing */
+#else
+void byteReverse(unsigned char *buf, unsigned longs);
+void byteReverse(unsigned char *buf, unsigned longs)
+{
+ do {
+ *(UINT32 *)buf = SWAP32(*(UINT32 *)buf);
+ buf += 4;
+ } while (--longs);
+}
+#endif
+
+
+/* ========================== MD5 implementation =========================== */
+// four base functions for MD5
+#define MD5_F1(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define MD5_F2(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define MD5_F3(x, y, z) ((x) ^ (y) ^ (z))
+#define MD5_F4(x, y, z) ((y) ^ ((x) | (~z)))
+#define CYCLIC_LEFT_SHIFT(w, s) (((w) << (s)) | ((w) >> (32-(s))))
+
+#define MD5Step(f, w, x, y, z, data, t, s) \
+ ( w += f(x, y, z) + data + t, w = (CYCLIC_LEFT_SHIFT(w, s)) & 0xffffffff, w += x )
+
+
+/*
+ * Function Description:
+ * Initiate MD5 Context satisfied in RFC 1321
+ *
+ * Arguments:
+ * pCtx Pointer to MD5 context
+ *
+ * Return Value:
+ * None
+ */
+VOID MD5Init(MD5_CTX *pCtx)
+{
+ pCtx->Buf[0]=0x67452301;
+ pCtx->Buf[1]=0xefcdab89;
+ pCtx->Buf[2]=0x98badcfe;
+ pCtx->Buf[3]=0x10325476;
+
+ pCtx->LenInBitCount[0]=0;
+ pCtx->LenInBitCount[1]=0;
+}
+
+
+/*
+ * Function Description:
+ * Update MD5 Context, allow of an arrary of octets as the next portion
+ * of the message
+ *
+ * Arguments:
+ * pCtx Pointer to MD5 context
+ * pData Pointer to input data
+ * LenInBytes The length of input data (unit: byte)
+ *
+ * Return Value:
+ * None
+ *
+ * Note:
+ * Called after MD5Init or MD5Update(itself)
+ */
+VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes)
+{
+
+ UINT32 TfTimes;
+ UINT32 temp;
+ unsigned int i;
+
+ temp = pCtx->LenInBitCount[0];
+
+ pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3));
+
+ if (pCtx->LenInBitCount[0] < temp)
+ pCtx->LenInBitCount[1]++; //carry in
+
+ pCtx->LenInBitCount[1] += LenInBytes >> 29;
+
+ // mod 64 bytes
+ temp = (temp >> 3) & 0x3f;
+
+ // process lacks of 64-byte data
+ if (temp)
+ {
+ UCHAR *pAds = (UCHAR *) pCtx->Input + temp;
+
+ if ((temp+LenInBytes) < 64)
+ {
+ NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes);
+ return;
+ }
+
+ NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp);
+ byteReverse(pCtx->Input, 16);
+ MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+ pData += 64-temp;
+ LenInBytes -= 64-temp;
+ } // end of if (temp)
+
+
+ TfTimes = (LenInBytes >> 6);
+
+ for (i=TfTimes; i>0; i--)
+ {
+ NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64);
+ byteReverse(pCtx->Input, 16);
+ MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+ pData += 64;
+ LenInBytes -= 64;
+ } // end of for
+
+ // buffering lacks of 64-byte data
+ if(LenInBytes)
+ NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes);
+
+}
+
+
+/*
+ * Function Description:
+ * Append padding bits and length of original message in the tail
+ * The message digest has to be completed in the end
+ *
+ * Arguments:
+ * Digest Output of Digest-Message for MD5
+ * pCtx Pointer to MD5 context
+ *
+ * Return Value:
+ * None
+ *
+ * Note:
+ * Called after MD5Update
+ */
+VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx)
+{
+ UCHAR Remainder;
+ UCHAR PadLenInBytes;
+ UCHAR *pAppend=0;
+ unsigned int i;
+
+ Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f);
+
+ PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder);
+
+ pAppend = (UCHAR *)pCtx->Input + Remainder;
+
+ // padding bits without crossing block(64-byte based) boundary
+ if (Remainder < 56)
+ {
+ *pAppend = 0x80;
+ PadLenInBytes --;
+
+ NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes);
+
+ // add data-length field, from low to high
+ for (i=0; i<4; i++)
+ {
+ pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff);
+ pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff);
+ }
+
+ byteReverse(pCtx->Input, 16);
+ MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+ } // end of if
+
+ // padding bits with crossing block(64-byte based) boundary
+ else
+ {
+ // the first block ===
+ *pAppend = 0x80;
+ PadLenInBytes --;
+
+ NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1));
+ PadLenInBytes -= (64 - Remainder - 1);
+
+ byteReverse(pCtx->Input, 16);
+ MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+
+ // the second block ===
+ NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes);
+
+ // add data-length field
+ for (i=0; i<4; i++)
+ {
+ pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff);
+ pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff);
+ }
+
+ byteReverse(pCtx->Input, 16);
+ MD5Transform(pCtx->Buf, (UINT32 *)pCtx->Input);
+ } // end of else
+
+
+ NdisMoveMemory((UCHAR *)Digest, (UINT32 *)pCtx->Buf, 16); // output
+ byteReverse((UCHAR *)Digest, 4);
+ NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free
+}
+
+
+/*
+ * Function Description:
+ * The central algorithm of MD5, consists of four rounds and sixteen
+ * steps per round
+ *
+ * Arguments:
+ * Buf Buffers of four states (output: 16 bytes)
+ * Mes Input data (input: 64 bytes)
+ *
+ * Return Value:
+ * None
+ *
+ * Note:
+ * Called by MD5Update or MD5Final
+ */
+VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16])
+{
+ UINT32 Reg[4], Temp;
+ unsigned int i;
+
+ static UCHAR LShiftVal[16] =
+ {
+ 7, 12, 17, 22,
+ 5, 9 , 14, 20,
+ 4, 11, 16, 23,
+ 6, 10, 15, 21,
+ };
+
+
+ // [equal to 4294967296*abs(sin(index))]
+ static UINT32 MD5Table[64] =
+ {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+ };
+
+
+ for (i=0; i<4; i++)
+ Reg[i]=Buf[i];
+
+
+ // 64 steps in MD5 algorithm
+ for (i=0; i<16; i++)
+ {
+ MD5Step(MD5_F1, Reg[0], Reg[1], Reg[2], Reg[3], Mes[i],
+ MD5Table[i], LShiftVal[i & 0x3]);
+
+ // one-word right shift
+ Temp = Reg[3];
+ Reg[3] = Reg[2];
+ Reg[2] = Reg[1];
+ Reg[1] = Reg[0];
+ Reg[0] = Temp;
+ }
+ for (i=16; i<32; i++)
+ {
+ MD5Step(MD5_F2, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(5*(i & 0xf)+1) & 0xf],
+ MD5Table[i], LShiftVal[(0x1 << 2)+(i & 0x3)]);
+
+ // one-word right shift
+ Temp = Reg[3];
+ Reg[3] = Reg[2];
+ Reg[2] = Reg[1];
+ Reg[1] = Reg[0];
+ Reg[0] = Temp;
+ }
+ for (i=32; i<48; i++)
+ {
+ MD5Step(MD5_F3, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(3*(i & 0xf)+5) & 0xf],
+ MD5Table[i], LShiftVal[(0x1 << 3)+(i & 0x3)]);
+
+ // one-word right shift
+ Temp = Reg[3];
+ Reg[3] = Reg[2];
+ Reg[2] = Reg[1];
+ Reg[1] = Reg[0];
+ Reg[0] = Temp;
+ }
+ for (i=48; i<64; i++)
+ {
+ MD5Step(MD5_F4, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(7*(i & 0xf)) & 0xf],
+ MD5Table[i], LShiftVal[(0x3 << 2)+(i & 0x3)]);
+
+ // one-word right shift
+ Temp = Reg[3];
+ Reg[3] = Reg[2];
+ Reg[2] = Reg[1];
+ Reg[1] = Reg[0];
+ Reg[0] = Temp;
+ }
+
+
+ // (temporary)output
+ for (i=0; i<4; i++)
+ Buf[i] += Reg[i];
+
+}
+
+
+
+/* ========================= SHA-1 implementation ========================== */
+// four base functions for SHA-1
+#define SHA1_F1(b, c, d) (((b) & (c)) | ((~b) & (d)))
+#define SHA1_F2(b, c, d) ((b) ^ (c) ^ (d))
+#define SHA1_F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
+
+
+#define SHA1Step(f, a, b, c, d, e, w, k) \
+ ( e += ( f(b, c, d) + w + k + CYCLIC_LEFT_SHIFT(a, 5)) & 0xffffffff, \
+ b = CYCLIC_LEFT_SHIFT(b, 30) )
+
+//Initiate SHA-1 Context satisfied in RFC 3174
+VOID SHAInit(SHA_CTX *pCtx)
+{
+ pCtx->Buf[0]=0x67452301;
+ pCtx->Buf[1]=0xefcdab89;
+ pCtx->Buf[2]=0x98badcfe;
+ pCtx->Buf[3]=0x10325476;
+ pCtx->Buf[4]=0xc3d2e1f0;
+
+ pCtx->LenInBitCount[0]=0;
+ pCtx->LenInBitCount[1]=0;
+}
+
+/*
+ * Function Description:
+ * Update SHA-1 Context, allow of an arrary of octets as the next
+ * portion of the message
+ *
+ * Arguments:
+ * pCtx Pointer to SHA-1 context
+ * pData Pointer to input data
+ * LenInBytes The length of input data (unit: byte)
+ *
+ * Return Value:
+ * error indicate more than pow(2,64) bits of data
+ *
+ * Note:
+ * Called after SHAInit or SHAUpdate(itself)
+ */
+UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes)
+{
+ UINT32 TfTimes;
+ UINT32 temp1,temp2;
+ unsigned int i;
+ UCHAR err=1;
+
+ temp1 = pCtx->LenInBitCount[0];
+ temp2 = pCtx->LenInBitCount[1];
+
+ pCtx->LenInBitCount[0] = (UINT32) (pCtx->LenInBitCount[0] + (LenInBytes << 3));
+ if (pCtx->LenInBitCount[0] < temp1)
+ pCtx->LenInBitCount[1]++; //carry in
+
+
+ pCtx->LenInBitCount[1] = (UINT32) (pCtx->LenInBitCount[1] +(LenInBytes >> 29));
+ if (pCtx->LenInBitCount[1] < temp2)
+ return (err); //check total length of original data
+
+
+ // mod 64 bytes
+ temp1 = (temp1 >> 3) & 0x3f;
+
+ // process lacks of 64-byte data
+ if (temp1)
+ {
+ UCHAR *pAds = (UCHAR *) pCtx->Input + temp1;
+
+ if ((temp1+LenInBytes) < 64)
+ {
+ NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes);
+ return (0);
+ }
+
+ NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp1);
+ byteReverse((UCHAR *)pCtx->Input, 16);
+
+ NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+ SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+ pData += 64-temp1;
+ LenInBytes -= 64-temp1;
+ } // end of if (temp1)
+
+
+ TfTimes = (LenInBytes >> 6);
+
+ for (i=TfTimes; i>0; i--)
+ {
+ NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64);
+ byteReverse((UCHAR *)pCtx->Input, 16);
+
+ NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+ SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+ pData += 64;
+ LenInBytes -= 64;
+ } // end of for
+
+ // buffering lacks of 64-byte data
+ if(LenInBytes)
+ NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes);
+
+ return (0);
+
+}
+
+// Append padding bits and length of original message in the tail
+// The message digest has to be completed in the end
+VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20])
+{
+ UCHAR Remainder;
+ UCHAR PadLenInBytes;
+ UCHAR *pAppend=0;
+ unsigned int i;
+
+ Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f);
+
+ pAppend = (UCHAR *)pCtx->Input + Remainder;
+
+ PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder);
+
+ // padding bits without crossing block(64-byte based) boundary
+ if (Remainder < 56)
+ {
+ *pAppend = 0x80;
+ PadLenInBytes --;
+
+ NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes);
+
+ // add data-length field, from high to low
+ for (i=0; i<4; i++)
+ {
+ pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff);
+ pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff);
+ }
+
+ byteReverse((UCHAR *)pCtx->Input, 16);
+ NdisZeroMemory((UCHAR *)pCtx->Input + 64, 14);
+ SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+ } // end of if
+
+ // padding bits with crossing block(64-byte based) boundary
+ else
+ {
+ // the first block ===
+ *pAppend = 0x80;
+ PadLenInBytes --;
+
+ NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1));
+ PadLenInBytes -= (64 - Remainder - 1);
+
+ byteReverse((UCHAR *)pCtx->Input, 16);
+ NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+ SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+
+
+ // the second block ===
+ NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes);
+
+ // add data-length field
+ for (i=0; i<4; i++)
+ {
+ pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff);
+ pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff);
+ }
+
+ byteReverse((UCHAR *)pCtx->Input, 16);
+ NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
+ SHATransform(pCtx->Buf, (UINT32 *)pCtx->Input);
+ } // end of else
+
+
+ //Output, bytereverse
+ for (i=0; i<20; i++)
+ {
+ Digest [i] = (UCHAR)(pCtx->Buf[i>>2] >> 8*(3-(i & 0x3)));
+ }
+
+ NdisZeroMemory(pCtx, sizeof(pCtx)); // memory free
+}
+
+
+// The central algorithm of SHA-1, consists of four rounds and
+// twenty steps per round
+VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20])
+{
+ UINT32 Reg[5],Temp;
+ unsigned int i;
+ UINT32 W[80];
+
+ static UINT32 SHA1Table[4] = { 0x5a827999, 0x6ed9eba1,
+ 0x8f1bbcdc, 0xca62c1d6 };
+
+ Reg[0]=Buf[0];
+ Reg[1]=Buf[1];
+ Reg[2]=Buf[2];
+ Reg[3]=Buf[3];
+ Reg[4]=Buf[4];
+
+ //the first octet of a word is stored in the 0th element, bytereverse
+ for(i = 0; i < 16; i++)
+ {
+ W[i] = (Mes[i] >> 24) & 0xff;
+ W[i] |= (Mes[i] >> 8 ) & 0xff00;
+ W[i] |= (Mes[i] << 8 ) & 0xff0000;
+ W[i] |= (Mes[i] << 24) & 0xff000000;
+ }
+
+
+ for (i = 0; i < 64; i++)
+ W[16+i] = CYCLIC_LEFT_SHIFT(W[i] ^ W[2+i] ^ W[8+i] ^ W[13+i], 1);
+
+
+ // 80 steps in SHA-1 algorithm
+ for (i=0; i<80; i++)
+ {
+ if (i<20)
+ SHA1Step(SHA1_F1, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+ W[i], SHA1Table[0]);
+
+ else if (i>=20 && i<40)
+ SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+ W[i], SHA1Table[1]);
+
+ else if (i>=40 && i<60)
+ SHA1Step(SHA1_F3, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+ W[i], SHA1Table[2]);
+
+ else
+ SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
+ W[i], SHA1Table[3]);
+
+
+ // one-word right shift
+ Temp = Reg[4];
+ Reg[4] = Reg[3];
+ Reg[3] = Reg[2];
+ Reg[2] = Reg[1];
+ Reg[1] = Reg[0];
+ Reg[0] = Temp;
+
+ } // end of for-loop
+
+
+ // (temporary)output
+ for (i=0; i<5; i++)
+ Buf[i] += Reg[i];
+
+}
+
+
+/* ========================= AES En/Decryption ========================== */
+
+/* forward S-box */
+static uint32 FSb[256] =
+{
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/* forward table */
+#define FT \
+\
+ V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \
+ V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \
+ V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \
+ V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \
+ V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \
+ V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \
+ V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \
+ V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \
+ V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \
+ V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \
+ V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \
+ V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \
+ V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \
+ V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \
+ V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \
+ V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \
+ V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \
+ V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \
+ V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \
+ V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \
+ V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \
+ V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \
+ V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \
+ V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \
+ V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \
+ V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \
+ V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \
+ V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \
+ V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \
+ V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \
+ V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \
+ V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \
+ V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \
+ V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \
+ V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \
+ V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \
+ V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \
+ V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \
+ V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \
+ V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \
+ V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \
+ V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \
+ V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \
+ V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \
+ V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \
+ V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \
+ V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \
+ V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \
+ V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \
+ V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \
+ V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \
+ V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \
+ V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \
+ V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \
+ V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \
+ V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \
+ V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \
+ V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \
+ V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \
+ V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \
+ V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \
+ V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \
+ V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \
+ V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static uint32 FT0[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static uint32 FT1[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static uint32 FT2[256] = { FT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static uint32 FT3[256] = { FT };
+#undef V
+
+#undef FT
+
+/* reverse S-box */
+
+static uint32 RSb[256] =
+{
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/* reverse table */
+
+#define RT \
+\
+ V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \
+ V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \
+ V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \
+ V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \
+ V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \
+ V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \
+ V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \
+ V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \
+ V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \
+ V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \
+ V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \
+ V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \
+ V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \
+ V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \
+ V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \
+ V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \
+ V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \
+ V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \
+ V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \
+ V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \
+ V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \
+ V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \
+ V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \
+ V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \
+ V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \
+ V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \
+ V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \
+ V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \
+ V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \
+ V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \
+ V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \
+ V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \
+ V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \
+ V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \
+ V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \
+ V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \
+ V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \
+ V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \
+ V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \
+ V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \
+ V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \
+ V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \
+ V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \
+ V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \
+ V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \
+ V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \
+ V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \
+ V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \
+ V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \
+ V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \
+ V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \
+ V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \
+ V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \
+ V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \
+ V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \
+ V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \
+ V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \
+ V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \
+ V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \
+ V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \
+ V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \
+ V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \
+ V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \
+ V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static uint32 RT0[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static uint32 RT1[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static uint32 RT2[256] = { RT };
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static uint32 RT3[256] = { RT };
+#undef V
+
+#undef RT
+
+/* round constants */
+
+static uint32 RCON[10] =
+{
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000
+};
+
+/* key schedule tables */
+
+static int KT_init = 1;
+
+static uint32 KT0[256];
+static uint32 KT1[256];
+static uint32 KT2[256];
+static uint32 KT3[256];
+
+/* platform-independant 32-bit integer manipulation macros */
+
+#define GET_UINT32(n,b,i) \
+{ \
+ (n) = ( (uint32) (b)[(i) ] << 24 ) \
+ | ( (uint32) (b)[(i) + 1] << 16 ) \
+ | ( (uint32) (b)[(i) + 2] << 8 ) \
+ | ( (uint32) (b)[(i) + 3] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (uint8) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (uint8) ( (n) ); \
+}
+
+/* AES key scheduling routine */
+
+int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits )
+{
+ int i;
+ uint32 *RK, *SK;
+
+ switch( nbits )
+ {
+ case 128: ctx->nr = 10; break;
+ case 192: ctx->nr = 12; break;
+ case 256: ctx->nr = 14; break;
+ default : return( 1 );
+ }
+
+ RK = ctx->erk;
+
+ for( i = 0; i < (nbits >> 5); i++ )
+ {
+ GET_UINT32( RK[i], key, i * 4 );
+ }
+
+ /* setup encryption round keys */
+
+ switch( nbits )
+ {
+ case 128:
+
+ for( i = 0; i < 10; i++, RK += 4 )
+ {
+ RK[4] = RK[0] ^ RCON[i] ^
+ ( FSb[ (uint8) ( RK[3] >> 16 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( RK[3] >> 8 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( RK[3] ) ] << 8 ) ^
+ ( FSb[ (uint8) ( RK[3] >> 24 ) ] );
+
+ RK[5] = RK[1] ^ RK[4];
+ RK[6] = RK[2] ^ RK[5];
+ RK[7] = RK[3] ^ RK[6];
+ }
+ break;
+
+ case 192:
+
+ for( i = 0; i < 8; i++, RK += 6 )
+ {
+ RK[6] = RK[0] ^ RCON[i] ^
+ ( FSb[ (uint8) ( RK[5] >> 16 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( RK[5] >> 8 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( RK[5] ) ] << 8 ) ^
+ ( FSb[ (uint8) ( RK[5] >> 24 ) ] );
+
+ RK[7] = RK[1] ^ RK[6];
+ RK[8] = RK[2] ^ RK[7];
+ RK[9] = RK[3] ^ RK[8];
+ RK[10] = RK[4] ^ RK[9];
+ RK[11] = RK[5] ^ RK[10];
+ }
+ break;
+
+ case 256:
+
+ for( i = 0; i < 7; i++, RK += 8 )
+ {
+ RK[8] = RK[0] ^ RCON[i] ^
+ ( FSb[ (uint8) ( RK[7] >> 16 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( RK[7] >> 8 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( RK[7] ) ] << 8 ) ^
+ ( FSb[ (uint8) ( RK[7] >> 24 ) ] );
+
+ RK[9] = RK[1] ^ RK[8];
+ RK[10] = RK[2] ^ RK[9];
+ RK[11] = RK[3] ^ RK[10];
+
+ RK[12] = RK[4] ^
+ ( FSb[ (uint8) ( RK[11] >> 24 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( RK[11] >> 16 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( RK[11] >> 8 ) ] << 8 ) ^
+ ( FSb[ (uint8) ( RK[11] ) ] );
+
+ RK[13] = RK[5] ^ RK[12];
+ RK[14] = RK[6] ^ RK[13];
+ RK[15] = RK[7] ^ RK[14];
+ }
+ break;
+ }
+
+ /* setup decryption round keys */
+
+ if( KT_init )
+ {
+ for( i = 0; i < 256; i++ )
+ {
+ KT0[i] = RT0[ FSb[i] ];
+ KT1[i] = RT1[ FSb[i] ];
+ KT2[i] = RT2[ FSb[i] ];
+ KT3[i] = RT3[ FSb[i] ];
+ }
+
+ KT_init = 0;
+ }
+
+ SK = ctx->drk;
+
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+
+ for( i = 1; i < ctx->nr; i++ )
+ {
+ RK -= 8;
+
+ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+ KT1[ (uint8) ( *RK >> 16 ) ] ^
+ KT2[ (uint8) ( *RK >> 8 ) ] ^
+ KT3[ (uint8) ( *RK ) ]; RK++;
+
+ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+ KT1[ (uint8) ( *RK >> 16 ) ] ^
+ KT2[ (uint8) ( *RK >> 8 ) ] ^
+ KT3[ (uint8) ( *RK ) ]; RK++;
+
+ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+ KT1[ (uint8) ( *RK >> 16 ) ] ^
+ KT2[ (uint8) ( *RK >> 8 ) ] ^
+ KT3[ (uint8) ( *RK ) ]; RK++;
+
+ *SK++ = KT0[ (uint8) ( *RK >> 24 ) ] ^
+ KT1[ (uint8) ( *RK >> 16 ) ] ^
+ KT2[ (uint8) ( *RK >> 8 ) ] ^
+ KT3[ (uint8) ( *RK ) ]; RK++;
+ }
+
+ RK -= 8;
+
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+
+ return( 0 );
+}
+
+/* AES 128-bit block encryption routine */
+
+void rtmp_aes_encrypt(aes_context *ctx, uint8 input[16], uint8 output[16] )
+{
+ uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+ RK = ctx->erk;
+ GET_UINT32( X0, input, 0 ); X0 ^= RK[0];
+ GET_UINT32( X1, input, 4 ); X1 ^= RK[1];
+ GET_UINT32( X2, input, 8 ); X2 ^= RK[2];
+ GET_UINT32( X3, input, 12 ); X3 ^= RK[3];
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ RK += 4; \
+ \
+ X0 = RK[0] ^ FT0[ (uint8) ( Y0 >> 24 ) ] ^ \
+ FT1[ (uint8) ( Y1 >> 16 ) ] ^ \
+ FT2[ (uint8) ( Y2 >> 8 ) ] ^ \
+ FT3[ (uint8) ( Y3 ) ]; \
+ \
+ X1 = RK[1] ^ FT0[ (uint8) ( Y1 >> 24 ) ] ^ \
+ FT1[ (uint8) ( Y2 >> 16 ) ] ^ \
+ FT2[ (uint8) ( Y3 >> 8 ) ] ^ \
+ FT3[ (uint8) ( Y0 ) ]; \
+ \
+ X2 = RK[2] ^ FT0[ (uint8) ( Y2 >> 24 ) ] ^ \
+ FT1[ (uint8) ( Y3 >> 16 ) ] ^ \
+ FT2[ (uint8) ( Y0 >> 8 ) ] ^ \
+ FT3[ (uint8) ( Y1 ) ]; \
+ \
+ X3 = RK[3] ^ FT0[ (uint8) ( Y3 >> 24 ) ] ^ \
+ FT1[ (uint8) ( Y0 >> 16 ) ] ^ \
+ FT2[ (uint8) ( Y1 >> 8 ) ] ^ \
+ FT3[ (uint8) ( Y2 ) ]; \
+}
+
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */
+
+ if( ctx->nr > 10 )
+ {
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */
+ }
+
+ if( ctx->nr > 12 )
+ {
+ AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */
+ AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */
+ }
+
+ /* last round */
+
+ RK += 4;
+
+ X0 = RK[0] ^ ( FSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^
+ ( FSb[ (uint8) ( Y3 ) ] );
+
+ X1 = RK[1] ^ ( FSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^
+ ( FSb[ (uint8) ( Y0 ) ] );
+
+ X2 = RK[2] ^ ( FSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^
+ ( FSb[ (uint8) ( Y1 ) ] );
+
+ X3 = RK[3] ^ ( FSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^
+ ( FSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^
+ ( FSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^
+ ( FSb[ (uint8) ( Y2 ) ] );
+
+ PUT_UINT32( X0, output, 0 );
+ PUT_UINT32( X1, output, 4 );
+ PUT_UINT32( X2, output, 8 );
+ PUT_UINT32( X3, output, 12 );
+}
+
+/* AES 128-bit block decryption routine */
+
+void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] )
+{
+ uint32 *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+ RK = ctx->drk;
+
+ GET_UINT32( X0, input, 0 ); X0 ^= RK[0];
+ GET_UINT32( X1, input, 4 ); X1 ^= RK[1];
+ GET_UINT32( X2, input, 8 ); X2 ^= RK[2];
+ GET_UINT32( X3, input, 12 ); X3 ^= RK[3];
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ RK += 4; \
+ \
+ X0 = RK[0] ^ RT0[ (uint8) ( Y0 >> 24 ) ] ^ \
+ RT1[ (uint8) ( Y3 >> 16 ) ] ^ \
+ RT2[ (uint8) ( Y2 >> 8 ) ] ^ \
+ RT3[ (uint8) ( Y1 ) ]; \
+ \
+ X1 = RK[1] ^ RT0[ (uint8) ( Y1 >> 24 ) ] ^ \
+ RT1[ (uint8) ( Y0 >> 16 ) ] ^ \
+ RT2[ (uint8) ( Y3 >> 8 ) ] ^ \
+ RT3[ (uint8) ( Y2 ) ]; \
+ \
+ X2 = RK[2] ^ RT0[ (uint8) ( Y2 >> 24 ) ] ^ \
+ RT1[ (uint8) ( Y1 >> 16 ) ] ^ \
+ RT2[ (uint8) ( Y0 >> 8 ) ] ^ \
+ RT3[ (uint8) ( Y3 ) ]; \
+ \
+ X3 = RK[3] ^ RT0[ (uint8) ( Y3 >> 24 ) ] ^ \
+ RT1[ (uint8) ( Y2 >> 16 ) ] ^ \
+ RT2[ (uint8) ( Y1 >> 8 ) ] ^ \
+ RT3[ (uint8) ( Y0 ) ]; \
+}
+
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 1 */
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 2 */
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 3 */
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 4 */
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 5 */
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 6 */
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 7 */
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 8 */
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 9 */
+
+ if( ctx->nr > 10 )
+ {
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 10 */
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 11 */
+ }
+
+ if( ctx->nr > 12 )
+ {
+ AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); /* round 12 */
+ AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); /* round 13 */
+ }
+
+ /* last round */
+
+ RK += 4;
+
+ X0 = RK[0] ^ ( RSb[ (uint8) ( Y0 >> 24 ) ] << 24 ) ^
+ ( RSb[ (uint8) ( Y3 >> 16 ) ] << 16 ) ^
+ ( RSb[ (uint8) ( Y2 >> 8 ) ] << 8 ) ^
+ ( RSb[ (uint8) ( Y1 ) ] );
+
+ X1 = RK[1] ^ ( RSb[ (uint8) ( Y1 >> 24 ) ] << 24 ) ^
+ ( RSb[ (uint8) ( Y0 >> 16 ) ] << 16 ) ^
+ ( RSb[ (uint8) ( Y3 >> 8 ) ] << 8 ) ^
+ ( RSb[ (uint8) ( Y2 ) ] );
+
+ X2 = RK[2] ^ ( RSb[ (uint8) ( Y2 >> 24 ) ] << 24 ) ^
+ ( RSb[ (uint8) ( Y1 >> 16 ) ] << 16 ) ^
+ ( RSb[ (uint8) ( Y0 >> 8 ) ] << 8 ) ^
+ ( RSb[ (uint8) ( Y3 ) ] );
+
+ X3 = RK[3] ^ ( RSb[ (uint8) ( Y3 >> 24 ) ] << 24 ) ^
+ ( RSb[ (uint8) ( Y2 >> 16 ) ] << 16 ) ^
+ ( RSb[ (uint8) ( Y1 >> 8 ) ] << 8 ) ^
+ ( RSb[ (uint8) ( Y0 ) ] );
+
+ PUT_UINT32( X0, output, 0 );
+ PUT_UINT32( X1, output, 4 );
+ PUT_UINT32( X2, output, 8 );
+ PUT_UINT32( X3, output, 12 );
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ SHA1 function
+
+ Arguments:
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID HMAC_SHA1(
+ IN UCHAR *text,
+ IN UINT text_len,
+ IN UCHAR *key,
+ IN UINT key_len,
+ IN UCHAR *digest)
+{
+ SHA_CTX context;
+ UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */
+ UCHAR k_opad[65]; /* outer padding - key XORd with opad */
+ INT i;
+
+ // if key is longer than 64 bytes reset it to key=SHA1(key)
+ if (key_len > 64)
+ {
+ SHA_CTX tctx;
+ SHAInit(&tctx);
+ SHAUpdate(&tctx, key, key_len);
+ SHAFinal(&tctx, key);
+ key_len = 20;
+ }
+ NdisZeroMemory(k_ipad, sizeof(k_ipad));
+ NdisZeroMemory(k_opad, sizeof(k_opad));
+ NdisMoveMemory(k_ipad, key, key_len);
+ NdisMoveMemory(k_opad, key, key_len);
+
+ // XOR key with ipad and opad values
+ for (i = 0; i < 64; i++)
+ {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ // perform inner SHA1
+ SHAInit(&context); /* init context for 1st pass */
+ SHAUpdate(&context, k_ipad, 64); /* start with inner pad */
+ SHAUpdate(&context, text, text_len); /* then text of datagram */
+ SHAFinal(&context, digest); /* finish up 1st pass */
+
+ //perform outer SHA1
+ SHAInit(&context); /* init context for 2nd pass */
+ SHAUpdate(&context, k_opad, 64); /* start with outer pad */
+ SHAUpdate(&context, digest, 20); /* then results of 1st hash */
+ SHAFinal(&context, digest); /* finish up 2nd pass */
+
+}
+
+/*
+* F(P, S, c, i) = U1 xor U2 xor ... Uc
+* U1 = PRF(P, S || Int(i))
+* U2 = PRF(P, U1)
+* Uc = PRF(P, Uc-1)
+*/
+
+void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output)
+{
+ unsigned char digest[36], digest1[SHA_DIGEST_LEN];
+ int i, j;
+
+ /* U1 = PRF(P, S || int(i)) */
+ memcpy(digest, ssid, ssidlength);
+ digest[ssidlength] = (unsigned char)((count>>24) & 0xff);
+ digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff);
+ digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff);
+ digest[ssidlength+3] = (unsigned char)(count & 0xff);
+ HMAC_SHA1(digest, ssidlength+4, (unsigned char*) password, (int) strlen(password), digest1); // for WPA update
+
+ /* output = U1 */
+ memcpy(output, digest1, SHA_DIGEST_LEN);
+
+ for (i = 1; i < iterations; i++)
+ {
+ /* Un = PRF(P, Un-1) */
+ HMAC_SHA1(digest1, SHA_DIGEST_LEN, (unsigned char*) password, (int) strlen(password), digest); // for WPA update
+ memcpy(digest1, digest, SHA_DIGEST_LEN);
+
+ /* output = output xor Un */
+ for (j = 0; j < SHA_DIGEST_LEN; j++)
+ {
+ output[j] ^= digest[j];
+ }
+ }
+}
+/*
+* password - ascii string up to 63 characters in length
+* ssid - octet string up to 32 octets
+* ssidlength - length of ssid in octets
+* output must be 40 octets in length and outputs 256 bits of key
+*/
+int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output)
+{
+ if ((strlen(password) > 63) || (ssidlength > 32))
+ return 0;
+
+ F(password, ssid, ssidlength, 4096, 1, output);
+ F(password, ssid, ssidlength, 4096, 2, &output[SHA_DIGEST_LEN]);
+ return 1;
+}
+
+
diff --git a/drivers/staging/rt2860/common/mlme.c b/drivers/staging/rt2860/common/mlme.c
new file mode 100644
index 000000000000..229747095aec
--- /dev/null
+++ b/drivers/staging/rt2860/common/mlme.c
@@ -0,0 +1,8667 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ mlme.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Chang 2004-08-25 Modify from RT2500 code base
+ John Chang 2004-09-06 modified for RT2600
+*/
+
+#include "../rt_config.h"
+#include <stdarg.h>
+
+UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
+
+UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
+UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
+UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
+UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
+UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
+UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
+UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
+#endif // DOT11_N_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+UCHAR RateSwitchTable[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x11, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x00, 0, 40, 101,
+ 0x01, 0x00, 1, 40, 50,
+ 0x02, 0x00, 2, 35, 45,
+ 0x03, 0x00, 3, 20, 45,
+ 0x04, 0x21, 0, 30, 50,
+ 0x05, 0x21, 1, 20, 50,
+ 0x06, 0x21, 2, 20, 50,
+ 0x07, 0x21, 3, 15, 50,
+ 0x08, 0x21, 4, 15, 30,
+ 0x09, 0x21, 5, 10, 25,
+ 0x0a, 0x21, 6, 8, 25,
+ 0x0b, 0x21, 7, 8, 25,
+ 0x0c, 0x20, 12, 15, 30,
+ 0x0d, 0x20, 13, 8, 20,
+ 0x0e, 0x20, 14, 8, 20,
+ 0x0f, 0x20, 15, 8, 25,
+ 0x10, 0x22, 15, 8, 25,
+ 0x11, 0x00, 0, 0, 0,
+ 0x12, 0x00, 0, 0, 0,
+ 0x13, 0x00, 0, 0, 0,
+ 0x14, 0x00, 0, 0, 0,
+ 0x15, 0x00, 0, 0, 0,
+ 0x16, 0x00, 0, 0, 0,
+ 0x17, 0x00, 0, 0, 0,
+ 0x18, 0x00, 0, 0, 0,
+ 0x19, 0x00, 0, 0, 0,
+ 0x1a, 0x00, 0, 0, 0,
+ 0x1b, 0x00, 0, 0, 0,
+ 0x1c, 0x00, 0, 0, 0,
+ 0x1d, 0x00, 0, 0, 0,
+ 0x1e, 0x00, 0, 0, 0,
+ 0x1f, 0x00, 0, 0, 0,
+};
+
+UCHAR RateSwitchTable11B[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x04, 0x03, 0, 0, 0, // Initial used item after association
+ 0x00, 0x00, 0, 40, 101,
+ 0x01, 0x00, 1, 40, 50,
+ 0x02, 0x00, 2, 35, 45,
+ 0x03, 0x00, 3, 20, 45,
+};
+
+UCHAR RateSwitchTable11BG[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0a, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x00, 0, 40, 101,
+ 0x01, 0x00, 1, 40, 50,
+ 0x02, 0x00, 2, 35, 45,
+ 0x03, 0x00, 3, 20, 45,
+ 0x04, 0x10, 2, 20, 35,
+ 0x05, 0x10, 3, 16, 35,
+ 0x06, 0x10, 4, 10, 25,
+ 0x07, 0x10, 5, 16, 25,
+ 0x08, 0x10, 6, 10, 25,
+ 0x09, 0x10, 7, 10, 13,
+};
+
+UCHAR RateSwitchTable11G[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x08, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x10, 0, 20, 101,
+ 0x01, 0x10, 1, 20, 35,
+ 0x02, 0x10, 2, 20, 35,
+ 0x03, 0x10, 3, 16, 35,
+ 0x04, 0x10, 4, 10, 25,
+ 0x05, 0x10, 5, 16, 25,
+ 0x06, 0x10, 6, 10, 25,
+ 0x07, 0x10, 7, 10, 13,
+};
+
+#ifdef DOT11_N_SUPPORT
+UCHAR RateSwitchTable11N1S[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x09, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30, 101,
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x21, 5, 10, 25,
+ 0x06, 0x21, 6, 8, 14,
+ 0x07, 0x21, 7, 8, 14,
+ 0x08, 0x23, 7, 8, 14,
+};
+
+UCHAR RateSwitchTable11N2S[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0a, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30, 101,
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x20, 12, 15, 30,
+ 0x06, 0x20, 13, 8, 20,
+ 0x07, 0x20, 14, 8, 20,
+ 0x08, 0x20, 15, 8, 25,
+ 0x09, 0x22, 15, 8, 25,
+};
+
+UCHAR RateSwitchTable11N3S[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0a, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30, 101,
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x20, 12, 15, 30,
+ 0x06, 0x20, 13, 8, 20,
+ 0x07, 0x20, 14, 8, 20,
+ 0x08, 0x20, 15, 8, 25,
+ 0x09, 0x22, 15, 8, 25,
+};
+
+UCHAR RateSwitchTable11N2SForABand[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0b, 0x09, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30, 101,
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x21, 5, 15, 30,
+ 0x06, 0x20, 12, 15, 30,
+ 0x07, 0x20, 13, 8, 20,
+ 0x08, 0x20, 14, 8, 20,
+ 0x09, 0x20, 15, 8, 25,
+ 0x0a, 0x22, 15, 8, 25,
+};
+
+UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0b, 0x09, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30, 101,
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x21, 5, 15, 30,
+ 0x06, 0x20, 12, 15, 30,
+ 0x07, 0x20, 13, 8, 20,
+ 0x08, 0x20, 14, 8, 20,
+ 0x09, 0x20, 15, 8, 25,
+ 0x0a, 0x22, 15, 8, 25,
+};
+
+UCHAR RateSwitchTable11BGN1S[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0d, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x00, 0, 40, 101,
+ 0x01, 0x00, 1, 40, 50,
+ 0x02, 0x00, 2, 35, 45,
+ 0x03, 0x00, 3, 20, 45,
+ 0x04, 0x21, 0, 30,101, //50
+ 0x05, 0x21, 1, 20, 50,
+ 0x06, 0x21, 2, 20, 50,
+ 0x07, 0x21, 3, 15, 50,
+ 0x08, 0x21, 4, 15, 30,
+ 0x09, 0x21, 5, 10, 25,
+ 0x0a, 0x21, 6, 8, 14,
+ 0x0b, 0x21, 7, 8, 14,
+ 0x0c, 0x23, 7, 8, 14,
+};
+
+UCHAR RateSwitchTable11BGN2S[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0a, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30,101, //50
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x20, 12, 15, 30,
+ 0x06, 0x20, 13, 8, 20,
+ 0x07, 0x20, 14, 8, 20,
+ 0x08, 0x20, 15, 8, 25,
+ 0x09, 0x22, 15, 8, 25,
+};
+
+UCHAR RateSwitchTable11BGN3S[] = { // 3*3
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0a, 0x00, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30,101, //50
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 20, 50,
+ 0x04, 0x21, 4, 15, 50,
+ 0x05, 0x20, 20, 15, 30,
+ 0x06, 0x20, 21, 8, 20,
+ 0x07, 0x20, 22, 8, 20,
+ 0x08, 0x20, 23, 8, 25,
+ 0x09, 0x22, 23, 8, 25,
+};
+
+UCHAR RateSwitchTable11BGN2SForABand[] = {
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0b, 0x09, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30,101, //50
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x21, 5, 15, 30,
+ 0x06, 0x20, 12, 15, 30,
+ 0x07, 0x20, 13, 8, 20,
+ 0x08, 0x20, 14, 8, 20,
+ 0x09, 0x20, 15, 8, 25,
+ 0x0a, 0x22, 15, 8, 25,
+};
+
+UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
+// Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
+ 0x0c, 0x09, 0, 0, 0, // Initial used item after association
+ 0x00, 0x21, 0, 30,101, //50
+ 0x01, 0x21, 1, 20, 50,
+ 0x02, 0x21, 2, 20, 50,
+ 0x03, 0x21, 3, 15, 50,
+ 0x04, 0x21, 4, 15, 30,
+ 0x05, 0x21, 5, 15, 30,
+ 0x06, 0x21, 12, 15, 30,
+ 0x07, 0x20, 20, 15, 30,
+ 0x08, 0x20, 21, 8, 20,
+ 0x09, 0x20, 22, 8, 20,
+ 0x0a, 0x20, 23, 8, 25,
+ 0x0b, 0x22, 23, 8, 25,
+};
+#endif // DOT11_N_SUPPORT //
+
+PUCHAR ReasonString[] = {
+ /* 0 */ "Reserved",
+ /* 1 */ "Unspecified Reason",
+ /* 2 */ "Previous Auth no longer valid",
+ /* 3 */ "STA is leaving / has left",
+ /* 4 */ "DIS-ASSOC due to inactivity",
+ /* 5 */ "AP unable to hanle all associations",
+ /* 6 */ "class 2 error",
+ /* 7 */ "class 3 error",
+ /* 8 */ "STA is leaving / has left",
+ /* 9 */ "require auth before assoc/re-assoc",
+ /* 10 */ "Reserved",
+ /* 11 */ "Reserved",
+ /* 12 */ "Reserved",
+ /* 13 */ "invalid IE",
+ /* 14 */ "MIC error",
+ /* 15 */ "4-way handshake timeout",
+ /* 16 */ "2-way (group key) handshake timeout",
+ /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
+ /* 18 */
+};
+
+extern UCHAR OfdmRateToRxwiMCS[];
+// since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
+// otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
+ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
+ 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
+ 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
+
+UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
+UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+// e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
+// this value, then it's quaranteed capable of operating in 36 mbps TX rate in
+// clean environment.
+// TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
+CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
+
+UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
+USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
+
+UCHAR SsidIe = IE_SSID;
+UCHAR SupRateIe = IE_SUPP_RATES;
+UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
+#ifdef DOT11_N_SUPPORT
+UCHAR HtCapIe = IE_HT_CAP;
+UCHAR AddHtInfoIe = IE_ADD_HT;
+UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
+#ifdef DOT11N_DRAFT3
+UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+UCHAR ErpIe = IE_ERP;
+UCHAR DsIe = IE_DS_PARM;
+UCHAR TimIe = IE_TIM;
+UCHAR WpaIe = IE_WPA;
+UCHAR Wpa2Ie = IE_WPA2;
+UCHAR IbssIe = IE_IBSS_PARM;
+UCHAR Ccx2Ie = IE_CCX_V2;
+
+extern UCHAR WPA_OUI[];
+
+UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
+
+UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+// Reset the RFIC setting to new series
+RTMP_RF_REGS RF2850RegTable[] = {
+// ch R1 R2 R3(TX0~4=0) R4
+ {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
+ {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
+ {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
+ {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
+ {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
+ {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
+ {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
+ {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
+ {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
+ {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
+ {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
+ {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
+ {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
+ {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
+
+ // 802.11 UNI / HyperLan 2
+ {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
+ {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
+ {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
+ {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
+ {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
+ {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
+ {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
+ {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
+ {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
+ {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
+ {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
+ {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
+
+ // 802.11 HyperLan 2
+ {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
+
+ // 2008.04.30 modified
+ // The system team has AN to improve the EVM value
+ // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
+ {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
+ {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
+ {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
+
+ {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
+ {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
+ {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
+ {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
+ {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
+ {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
+ {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
+ {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
+ {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
+ {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
+ {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
+ {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
+
+ // 802.11 UNII
+ {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
+ {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
+ {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
+ {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
+ {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
+ {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
+ {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
+
+ // Japan
+ {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
+ {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
+ {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
+ {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
+ {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
+ {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
+ {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
+
+ // still lack of MMAC(Japan) ch 34,38,42,46
+};
+UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
+
+FREQUENCY_ITEM FreqItems3020[] =
+{
+ /**************************************************/
+ // ISM : 2.4 to 2.483 GHz //
+ /**************************************************/
+ // 11g
+ /**************************************************/
+ //-CH---N-------R---K-----------
+ {1, 241, 2, 2},
+ {2, 241, 2, 7},
+ {3, 242, 2, 2},
+ {4, 242, 2, 7},
+ {5, 243, 2, 2},
+ {6, 243, 2, 7},
+ {7, 244, 2, 2},
+ {8, 244, 2, 7},
+ {9, 245, 2, 2},
+ {10, 245, 2, 7},
+ {11, 246, 2, 2},
+ {12, 246, 2, 7},
+ {13, 247, 2, 2},
+ {14, 248, 2, 4},
+};
+#define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
+
+/*
+ ==========================================================================
+ Description:
+ initialize the MLME task and its data structure (queue, spinlock,
+ timer, state machines).
+
+ IRQL = PASSIVE_LEVEL
+
+ Return:
+ always return NDIS_STATUS_SUCCESS
+
+ ==========================================================================
+*/
+NDIS_STATUS MlmeInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
+
+ do
+ {
+ Status = MlmeQueueInit(&pAd->Mlme.Queue);
+ if(Status != NDIS_STATUS_SUCCESS)
+ break;
+
+ pAd->Mlme.bRunning = FALSE;
+ NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ BssTableInit(&pAd->ScanTab);
+
+ // init STA state machines
+ AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
+ AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
+ AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
+ SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
+ WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
+ AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
+
+#ifdef QOS_DLS_SUPPORT
+ DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
+#endif // QOS_DLS_SUPPORT //
+
+
+ // Since we are using switch/case to implement it, the init is different from the above
+ // state machine init
+ MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+ ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
+
+ // Init mlme periodic timer
+ RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
+
+ // Set mlme periodic timer
+ RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
+
+ // software-based RX Antenna diversity
+ RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
+
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef RT2860
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ // only PCIe cards need these two timers
+ RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
+ RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
+ }
+ }
+#endif // RT2860 //
+#endif // CONFIG_STA_SUPPORT //
+
+ } while (FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
+
+ return Status;
+}
+
+/*
+ ==========================================================================
+ Description:
+ main loop of the MLME
+ Pre:
+ Mlme has to be initialized, and there are something inside the queue
+ Note:
+ This function is invoked from MPSetInformation and MPReceive;
+ This task guarantee only one MlmeHandler will run.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeHandler(
+ IN PRTMP_ADAPTER pAd)
+{
+ MLME_QUEUE_ELEM *Elem = NULL;
+#ifdef APCLI_SUPPORT
+ SHORT apcliIfIndex;
+#endif
+
+ // Only accept MLME and Frame from peer side, no other (control/data) frame should
+ // get into this state machine
+
+ NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+ if(pAd->Mlme.bRunning)
+ {
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+ return;
+ }
+ else
+ {
+ pAd->Mlme.bRunning = TRUE;
+ }
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+
+ while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
+ break;
+ }
+
+#ifdef RALINK_ATE
+ if(ATE_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
+ break;
+ }
+#endif // RALINK_ATE //
+
+ //From message type, determine which state machine I should drive
+ if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
+ {
+
+ // if dequeue success
+ switch (Elem->Machine)
+ {
+ // STA state machines
+#ifdef CONFIG_STA_SUPPORT
+ case ASSOC_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
+ break;
+ case AUTH_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
+ break;
+ case AUTH_RSP_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
+ break;
+ case SYNC_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
+ break;
+ case MLME_CNTL_STATE_MACHINE:
+ MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
+ break;
+ case WPA_PSK_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
+ break;
+#ifdef LEAP_SUPPORT
+ case LEAP_STATE_MACHINE:
+ LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
+ break;
+#endif
+ case AIRONET_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
+ break;
+
+#ifdef QOS_DLS_SUPPORT
+ case DLS_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
+ break;
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+ case ACTION_STATE_MACHINE:
+ StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
+ break;
+
+
+
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
+ break;
+ } // end of switch
+
+ // free MLME element
+ Elem->Occupied = FALSE;
+ Elem->MsgLen = 0;
+
+ }
+ else {
+ DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
+ }
+ }
+
+ NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+ pAd->Mlme.bRunning = FALSE;
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Destructor of MLME (Destroy queue, state machine, spin lock and timer)
+ Parameters:
+ Adapter - NIC Adapter pointer
+ Post:
+ The MLME task will no longer work properly
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeHalt(
+ IN PRTMP_ADAPTER pAd)
+{
+ BOOLEAN Cancelled;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
+
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ // disable BEACON generation and other BEACON related hardware timers
+ AsicDisableSync(pAd);
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef QOS_DLS_SUPPORT
+ UCHAR i;
+#endif // QOS_DLS_SUPPORT //
+ // Cancel pending timers
+ RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
+#ifdef RT2860
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
+ }
+#endif // RT2860 //
+
+#ifdef QOS_DLS_SUPPORT
+ for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
+ }
+#endif // QOS_DLS_SUPPORT //
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
+
+
+
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ // Set LED
+ RTMPSetLED(pAd, LED_HALT);
+ RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
+ }
+
+ RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
+
+ MlmeQueueDestroy(&pAd->Mlme.Queue);
+ NdisFreeSpinLock(&pAd->Mlme.TaskLock);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
+}
+
+VOID MlmeResetRalinkCounters(
+ IN PRTMP_ADAPTER pAd)
+{
+ pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
+ // clear all OneSecxxx counters.
+ pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
+ pAd->RalinkCounters.OneSecFalseCCACnt = 0;
+ pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
+ pAd->RalinkCounters.OneSecRxOkCnt = 0;
+ pAd->RalinkCounters.OneSecTxFailCount = 0;
+ pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
+ pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
+ pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
+
+ // TODO: for debug only. to be removed
+ pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
+ pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
+ pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
+ pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
+ pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
+ pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
+ pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
+ pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
+ pAd->RalinkCounters.OneSecTxDoneCount = 0;
+ pAd->RalinkCounters.OneSecRxCount = 0;
+ pAd->RalinkCounters.OneSecTxAggregationCount = 0;
+ pAd->RalinkCounters.OneSecRxAggregationCount = 0;
+
+ return;
+}
+
+unsigned long rx_AMSDU;
+unsigned long rx_Total;
+
+/*
+ ==========================================================================
+ Description:
+ This routine is executed periodically to -
+ 1. Decide if it's a right time to turn on PwrMgmt bit of all
+ outgoiing frames
+ 2. Calculate ChannelQuality based on statistics of the last
+ period, so that TX rate won't toggling very frequently between a
+ successful TX and a failed TX.
+ 3. If the calculated ChannelQuality indicated current connection not
+ healthy, then a ROAMing attempt is tried here.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
+VOID MlmePeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ ULONG TxTotalCnt;
+ PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef RT2860
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
+ // Move code to here, because following code will return when radio is off
+ if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && (pAd->StaCfg.bHardwareRadio == TRUE) &&
+ (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
+ (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
+ (pAd->bPCIclkOff == FALSE))
+ {
+ UINT32 data = 0;
+
+ // Read GPIO pin2 as Hardware controlled radio state
+ RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
+ if (data & 0x04)
+ {
+ pAd->StaCfg.bHwRadio = TRUE;
+ }
+ else
+ {
+ pAd->StaCfg.bHwRadio = FALSE;
+ }
+ if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
+ {
+ pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
+ if (pAd->StaCfg.bRadio == TRUE)
+ {
+ MlmeRadioOn(pAd);
+ // Update extra information
+ pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+ }
+ else
+ {
+ MlmeRadioOff(pAd);
+ // Update extra information
+ pAd->ExtraInfo = HW_RADIO_OFF;
+ }
+ }
+ }
+ }
+#endif // RT2860 //
+#endif // CONFIG_STA_SUPPORT //
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_RADIO_MEASUREMENT |
+ fRTMP_ADAPTER_RESET_IN_PROGRESS))))
+ return;
+
+ RT28XX_MLME_PRE_SANITY_CHECK(pAd);
+
+#ifdef RALINK_ATE
+ /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
+ if (ATE_ON(pAd))
+ {
+ if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
+ {
+ pAd->Mlme.PeriodicRound ++;
+ return;
+ }
+ }
+#endif // RALINK_ATE //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Do nothing if monitor mode is on
+ if (MONITOR_ON(pAd))
+ return;
+
+ if (pAd->Mlme.PeriodicRound & 0x1)
+ {
+ // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
+ if (((pAd->MACVersion & 0xffff) == 0x0101) &&
+ (STA_TGN_WIFI_ON(pAd)) &&
+ (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
+
+ {
+ RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
+ pAd->CommonCfg.IOTestParm.bToggle = TRUE;
+ }
+ else if ((STA_TGN_WIFI_ON(pAd)) &&
+ ((pAd->MACVersion & 0xffff) == 0x0101))
+ {
+ RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
+ pAd->CommonCfg.IOTestParm.bToggle = FALSE;
+ }
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ pAd->bUpdateBcnCntDone = FALSE;
+
+// RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
+ pAd->Mlme.PeriodicRound ++;
+
+ // execute every 500ms
+ if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
+ {
+#ifdef CONFIG_STA_SUPPORT
+ // perform dynamic tx rate switching based on past TX history
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+ )
+ && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
+ MlmeDynamicTxRateSwitching(pAd);
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ // Normal 1 second Mlme PeriodicExec.
+ if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
+ {
+ pAd->Mlme.OneSecPeriodicRound ++;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ {
+ /* request from Baron : move this routine from later to here */
+ /* for showing Rx error count in ATE RXFRAME */
+ NICUpdateRawCounters(pAd);
+ if (pAd->ate.bRxFer == 1)
+ {
+ pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
+ ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
+ pAd->ate.RxCntPerSec = 0;
+
+ if (pAd->ate.RxAntennaSel == 0)
+ ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
+ pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
+ else
+ ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
+ }
+ MlmeResetRalinkCounters(pAd);
+ return;
+ }
+#endif // RALINK_ATE //
+
+
+ if (rx_Total)
+ {
+
+ // reset counters
+ rx_AMSDU = 0;
+ rx_Total = 0;
+ }
+
+ // Media status changed, report to NDIS
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
+ {
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ {
+ pAd->IndicateMediaState = NdisMediaStateConnected;
+ RTMP_IndicateMediaState(pAd);
+
+ }
+ else
+ {
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ RTMP_IndicateMediaState(pAd);
+ }
+ }
+
+ NdisGetSystemUpTime(&pAd->Mlme.Now32);
+
+ // add the most up-to-date h/w raw counters into software variable, so that
+ // the dynamic tuning mechanism below are based on most up-to-date information
+ NICUpdateRawCounters(pAd);
+
+
+#ifdef DOT11_N_SUPPORT
+ // Need statistics after read counter. So put after NICUpdateRawCounters
+ ORIBATimerTimeout(pAd);
+#endif // DOT11_N_SUPPORT //
+
+
+ // The time period for checking antenna is according to traffic
+ if (pAd->Mlme.bEnableAutoAntennaCheck)
+ {
+ TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+ pAd->RalinkCounters.OneSecTxRetryOkCount +
+ pAd->RalinkCounters.OneSecTxFailCount;
+
+ if (TxTotalCnt > 50)
+ {
+ if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
+ {
+ AsicEvaluateRxAnt(pAd);
+ }
+ }
+ else
+ {
+ if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
+ {
+ AsicEvaluateRxAnt(pAd);
+ }
+ }
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ STAMlmePeriodicExec(pAd);
+#endif // CONFIG_STA_SUPPORT //
+
+ MlmeResetRalinkCounters(pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef RT2860
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
+#endif // RT2860 //
+ {
+ // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
+ // and sending CTS-to-self over and over.
+ // Software Patch Solution:
+ // 1. Polling debug state register 0x10F4 every one second.
+ // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
+ // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
+
+ UINT32 MacReg = 0;
+
+ RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
+ if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
+ {
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
+ RTMPusecDelay(1);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
+
+ DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
+ }
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ RT28XX_MLME_HANDLER(pAd);
+ }
+
+
+ pAd->bUpdateBcnCntDone = FALSE;
+}
+
+#ifdef CONFIG_STA_SUPPORT
+VOID STAMlmePeriodicExec(
+ PRTMP_ADAPTER pAd)
+{
+ ULONG TxTotalCnt;
+
+//
+// We return here in ATE mode, because the statistics
+// that ATE needs are not collected via this routine.
+//
+#ifdef RALINK_ATE
+ // It is supposed that we will never reach here in ATE mode.
+ ASSERT(!(ATE_ON(pAd)));
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
+#endif // WPA_SUPPLICANT_SUPPORT //
+ {
+ // WPA MIC error should block association attempt for 60 seconds
+ if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
+ pAd->StaCfg.bBlockAssoc = FALSE;
+ }
+
+ if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
+ {
+ if (pAd->IndicateMediaState == NdisMediaStateConnected)
+ {
+ RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+ }
+ pAd->PreMediaState = pAd->IndicateMediaState;
+ }
+
+
+
+
+ AsicStaBbpTuning(pAd);
+
+ TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+ pAd->RalinkCounters.OneSecTxRetryOkCount +
+ pAd->RalinkCounters.OneSecTxFailCount;
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ {
+ // update channel quality for Roaming and UI LinkQuality display
+ MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
+ }
+
+ // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
+ // Radio is currently in noisy environment
+ if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+ AsicAdjustTxPower(pAd);
+
+ if (INFRA_ON(pAd))
+ {
+#ifdef QOS_DLS_SUPPORT
+ // Check DLS time out, then tear down those session
+ RTMPCheckDLSTimeOut(pAd);
+#endif // QOS_DLS_SUPPORT //
+
+ // Is PSM bit consistent with user power management policy?
+ // This is the only place that will set PSM bit ON.
+ if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
+
+ pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
+
+ if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
+ (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
+ ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
+ {
+ RTMPSetAGCInitValue(pAd, BW_20);
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
+ }
+
+ {
+ if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
+ {
+ // When APSD is enabled, the period changes as 20 sec
+ if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
+ RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+ }
+ else
+ {
+ // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
+ if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
+ {
+ if (pAd->CommonCfg.bWmmCapable)
+ RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+ else
+ RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
+ }
+ }
+ }
+
+ if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
+ pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
+ pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
+
+ // Lost AP, send disconnect & link down event
+ LinkDown(pAd, FALSE);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP)
+ {
+ union iwreq_data wrqu;
+ //send disassociate event to wpa_supplicant
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+ MlmeAutoReconnectLastSSID(pAd);
+ }
+ else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
+ {
+ pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
+ MlmeAutoReconnectLastSSID(pAd);
+ }
+
+ // Add auto seamless roaming
+ if (pAd->StaCfg.bFastRoaming)
+ {
+ SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
+
+ if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
+ {
+ MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
+ }
+ }
+ }
+ else if (ADHOC_ON(pAd))
+ {
+ // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
+ // the "TX BEACON competition" for the entire past 1 sec.
+ // So that even when ASIC's BEACONgen engine been blocked
+ // by peer's BEACON due to slower system clock, this STA still can send out
+ // minimum BEACON to tell the peer I'm alive.
+ // drawback is that this BEACON won't be well aligned at TBTT boundary.
+ // EnqueueBeaconFrame(pAd); // software send BEACON
+
+ // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
+ // restore outgoing BEACON to support B/G-mixed mode
+ if ((pAd->CommonCfg.Channel <= 14) &&
+ (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
+ (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
+ ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
+ NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+ pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
+ MlmeUpdateTxRates(pAd, FALSE, 0);
+ MakeIbssBeacon(pAd); // re-build BEACON frame
+ AsicEnableIbssSync(pAd); // copy to on-chip memory
+ pAd->StaCfg.AdhocBOnlyJoined = FALSE;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+ {
+ if ((pAd->StaCfg.AdhocBGJoined) &&
+ ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
+ pAd->StaCfg.AdhocBGJoined = FALSE;
+ }
+
+ if ((pAd->StaCfg.Adhoc20NJoined) &&
+ ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
+ pAd->StaCfg.Adhoc20NJoined = FALSE;
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+ //radar detect
+ if ((pAd->CommonCfg.Channel > 14)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+ {
+ RadarDetectPeriodic(pAd);
+ }
+
+ // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
+ // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
+ // join later.
+ if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
+ OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ {
+ MLME_START_REQ_STRUCT StartReq;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
+ LinkDown(pAd, FALSE);
+
+ StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
+ }
+ }
+ else // no INFRA nor ADHOC connection
+ {
+
+ if (pAd->StaCfg.bScanReqIsFromWebUI &&
+ ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
+ goto SKIP_AUTO_SCAN_CONN;
+ else
+ pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
+
+ if ((pAd->StaCfg.bAutoReconnect == TRUE)
+ && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
+ && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
+ {
+ if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
+ {
+ MLME_SCAN_REQ_STRUCT ScanReq;
+
+ if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
+ ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+ // Reset Missed scan number
+ pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
+ }
+ else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
+ MlmeAutoReconnectLastSSID(pAd);
+ }
+ else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+ {
+ if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
+ {
+ MlmeAutoScan(pAd);
+ pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
+ }
+ else
+ {
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ {
+ if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
+ MlmeAutoReconnectLastSSID(pAd);
+ }
+ else
+#endif // CARRIER_DETECTION_SUPPORT //
+ MlmeAutoReconnectLastSSID(pAd);
+ }
+ }
+ }
+ }
+
+SKIP_AUTO_SCAN_CONN:
+
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
+ {
+ pAd->MacTab.fAnyBASession = TRUE;
+ AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
+ }
+ else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
+ {
+ pAd->MacTab.fAnyBASession = FALSE;
+ AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
+ }
+#endif // DOT11_N_SUPPORT //
+
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
+ TriEventCounterMaintenance(pAd);
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+ return;
+}
+
+// Link down report
+VOID LinkDownExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ RTMP_IndicateMediaState(pAd);
+ pAd->ExtraInfo = GENERAL_LINK_DOWN;
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeAutoScan(
+ IN PRTMP_ADAPTER pAd)
+{
+ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+ if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
+ MlmeEnqueue(pAd,
+ MLME_CNTL_STATE_MACHINE,
+ OID_802_11_BSSID_LIST_SCAN,
+ 0,
+ NULL);
+ RT28XX_MLME_HANDLER(pAd);
+ }
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeAutoReconnectLastSSID(
+ IN PRTMP_ADAPTER pAd)
+{
+
+
+ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+ if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
+ (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
+ {
+ NDIS_802_11_SSID OidSsid;
+ OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
+ NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
+ MlmeEnqueue(pAd,
+ MLME_CNTL_STATE_MACHINE,
+ OID_802_11_SSID,
+ sizeof(NDIS_802_11_SSID),
+ &OidSsid);
+ RT28XX_MLME_HANDLER(pAd);
+ }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+ ==========================================================================
+ Validate SSID for connection try and rescan purpose
+ Valid SSID will have visible chars only.
+ The valid length is from 0 to 32.
+ IRQL = DISPATCH_LEVEL
+ ==========================================================================
+ */
+BOOLEAN MlmeValidateSSID(
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen)
+{
+ int index;
+
+ if (SsidLen > MAX_LEN_OF_SSID)
+ return (FALSE);
+
+ // Check each character value
+ for (index = 0; index < SsidLen; index++)
+ {
+ if (pSsid[index] < 0x20)
+ return (FALSE);
+ }
+
+ // All checked
+ return (TRUE);
+}
+
+VOID MlmeSelectTxRateTable(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR *ppTable,
+ IN PUCHAR pTableSize,
+ IN PUCHAR pInitTxRateIdx)
+{
+ do
+ {
+ // decide the rate table for tuning
+ if (pAd->CommonCfg.TxRateTableSize > 0)
+ {
+ *ppTable = RateSwitchTable;
+ *pTableSize = RateSwitchTable[0];
+ *pInitTxRateIdx = RateSwitchTable[1];
+
+ break;
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
+ {
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
+ !pAd->StaCfg.AdhocBOnlyJoined &&
+ !pAd->StaCfg.AdhocBGJoined &&
+ (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
+ ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
+ {// 11N 1S Adhoc
+ *ppTable = RateSwitchTable11N1S;
+ *pTableSize = RateSwitchTable11N1S[0];
+ *pInitTxRateIdx = RateSwitchTable11N1S[1];
+
+ }
+ else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
+ !pAd->StaCfg.AdhocBOnlyJoined &&
+ !pAd->StaCfg.AdhocBGJoined &&
+ (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
+ (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
+ (pAd->Antenna.field.TxPath == 2))
+ {// 11N 2S Adhoc
+ if (pAd->LatchRfRegs.Channel <= 14)
+ {
+ *ppTable = RateSwitchTable11N2S;
+ *pTableSize = RateSwitchTable11N2S[0];
+ *pInitTxRateIdx = RateSwitchTable11N2S[1];
+ }
+ else
+ {
+ *ppTable = RateSwitchTable11N2SForABand;
+ *pTableSize = RateSwitchTable11N2SForABand[0];
+ *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
+ }
+
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ if (pAd->CommonCfg.PhyMode == PHY_11B)
+ {
+ *ppTable = RateSwitchTable11B;
+ *pTableSize = RateSwitchTable11B[0];
+ *pInitTxRateIdx = RateSwitchTable11B[1];
+
+ }
+ else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
+ {
+ // USe B Table when Only b-only Station in my IBSS .
+ *ppTable = RateSwitchTable11B;
+ *pTableSize = RateSwitchTable11B[0];
+ *pInitTxRateIdx = RateSwitchTable11B[1];
+
+ }
+ else if (pAd->LatchRfRegs.Channel <= 14)
+ {
+ *ppTable = RateSwitchTable11BG;
+ *pTableSize = RateSwitchTable11BG[0];
+ *pInitTxRateIdx = RateSwitchTable11BG[1];
+
+ }
+ else
+ {
+ *ppTable = RateSwitchTable11G;
+ *pTableSize = RateSwitchTable11G[0];
+ *pInitTxRateIdx = RateSwitchTable11G[1];
+
+ }
+ break;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+ if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
+ ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
+ {// 11BGN 1S AP
+ *ppTable = RateSwitchTable11BGN1S;
+ *pTableSize = RateSwitchTable11BGN1S[0];
+ *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
+
+ break;
+ }
+
+ if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
+ (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
+ {// 11BGN 2S AP
+ if (pAd->LatchRfRegs.Channel <= 14)
+ {
+ *ppTable = RateSwitchTable11BGN2S;
+ *pTableSize = RateSwitchTable11BGN2S[0];
+ *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
+
+ }
+ else
+ {
+ *ppTable = RateSwitchTable11BGN2SForABand;
+ *pTableSize = RateSwitchTable11BGN2SForABand[0];
+ *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
+
+ }
+ break;
+ }
+
+ if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
+ {// 11N 1S AP
+ *ppTable = RateSwitchTable11N1S;
+ *pTableSize = RateSwitchTable11N1S[0];
+ *pInitTxRateIdx = RateSwitchTable11N1S[1];
+
+ break;
+ }
+
+ if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
+ {// 11N 2S AP
+ if (pAd->LatchRfRegs.Channel <= 14)
+ {
+ *ppTable = RateSwitchTable11N2S;
+ *pTableSize = RateSwitchTable11N2S[0];
+ *pInitTxRateIdx = RateSwitchTable11N2S[1];
+ }
+ else
+ {
+ *ppTable = RateSwitchTable11N2SForABand;
+ *pTableSize = RateSwitchTable11N2SForABand[0];
+ *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
+ }
+
+ break;
+ }
+#endif // DOT11_N_SUPPORT //
+ //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+ if ((pEntry->RateLen == 4)
+#ifdef DOT11_N_SUPPORT
+ && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif // DOT11_N_SUPPORT //
+ )
+ {// B only AP
+ *ppTable = RateSwitchTable11B;
+ *pTableSize = RateSwitchTable11B[0];
+ *pInitTxRateIdx = RateSwitchTable11B[1];
+
+ break;
+ }
+
+ //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+ if ((pEntry->RateLen > 8)
+#ifdef DOT11_N_SUPPORT
+ && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif // DOT11_N_SUPPORT //
+ )
+ {// B/G mixed AP
+ *ppTable = RateSwitchTable11BG;
+ *pTableSize = RateSwitchTable11BG[0];
+ *pInitTxRateIdx = RateSwitchTable11BG[1];
+
+ break;
+ }
+
+ //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+ if ((pEntry->RateLen == 8)
+#ifdef DOT11_N_SUPPORT
+ && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
+#endif // DOT11_N_SUPPORT //
+ )
+ {// G only AP
+ *ppTable = RateSwitchTable11G;
+ *pTableSize = RateSwitchTable11G[0];
+ *pInitTxRateIdx = RateSwitchTable11G[1];
+
+ break;
+ }
+#ifdef DOT11_N_SUPPORT
+#endif // DOT11_N_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef DOT11_N_SUPPORT
+ //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
+ if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
+#endif // DOT11_N_SUPPORT //
+ { // Legacy mode
+ if (pAd->CommonCfg.MaxTxRate <= RATE_11)
+ {
+ *ppTable = RateSwitchTable11B;
+ *pTableSize = RateSwitchTable11B[0];
+ *pInitTxRateIdx = RateSwitchTable11B[1];
+ }
+ else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
+ {
+ *ppTable = RateSwitchTable11G;
+ *pTableSize = RateSwitchTable11G[0];
+ *pInitTxRateIdx = RateSwitchTable11G[1];
+
+ }
+ else
+ {
+ *ppTable = RateSwitchTable11BG;
+ *pTableSize = RateSwitchTable11BG[0];
+ *pInitTxRateIdx = RateSwitchTable11BG[1];
+ }
+ break;
+ }
+#ifdef DOT11_N_SUPPORT
+ if (pAd->LatchRfRegs.Channel <= 14)
+ {
+ if (pAd->CommonCfg.TxStream == 1)
+ {
+ *ppTable = RateSwitchTable11N1S;
+ *pTableSize = RateSwitchTable11N1S[0];
+ *pInitTxRateIdx = RateSwitchTable11N1S[1];
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
+ }
+ else
+ {
+ *ppTable = RateSwitchTable11N2S;
+ *pTableSize = RateSwitchTable11N2S[0];
+ *pInitTxRateIdx = RateSwitchTable11N2S[1];
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
+ }
+ }
+ else
+ {
+ if (pAd->CommonCfg.TxStream == 1)
+ {
+ *ppTable = RateSwitchTable11N1S;
+ *pTableSize = RateSwitchTable11N1S[0];
+ *pInitTxRateIdx = RateSwitchTable11N1S[1];
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
+ }
+ else
+ {
+ *ppTable = RateSwitchTable11N2SForABand;
+ *pTableSize = RateSwitchTable11N2SForABand[0];
+ *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
+ pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
+ }
+#endif // CONFIG_STA_SUPPORT //
+ } while(FALSE);
+}
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ This routine checks if there're other APs out there capable for
+ roaming. Caller should call this routine only when Link up in INFRA mode
+ and channel quality is below CQI_GOOD_THRESHOLD.
+
+ IRQL = DISPATCH_LEVEL
+
+ Output:
+ ==========================================================================
+ */
+VOID MlmeCheckForRoaming(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now32)
+{
+ USHORT i;
+ BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
+ BSS_ENTRY *pBss;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
+ // put all roaming candidates into RoamTab, and sort in RSSI order
+ BssTableInit(pRoamTab);
+ for (i = 0; i < pAd->ScanTab.BssNr; i++)
+ {
+ pBss = &pAd->ScanTab.BssEntry[i];
+
+ if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
+ continue; // AP disappear
+ if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
+ continue; // RSSI too weak. forget it.
+ if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
+ continue; // skip current AP
+ if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
+ continue; // only AP with stronger RSSI is eligible for roaming
+
+ // AP passing all above rules is put into roaming candidate table
+ NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
+ pRoamTab->BssNr += 1;
+ }
+
+ if (pRoamTab->BssNr > 0)
+ {
+ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+ if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+ {
+ pAd->RalinkCounters.PoorCQIRoamingCount ++;
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+ }
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine checks if there're other APs out there capable for
+ roaming. Caller should call this routine only when link up in INFRA mode
+ and channel quality is below CQI_GOOD_THRESHOLD.
+
+ IRQL = DISPATCH_LEVEL
+
+ Output:
+ ==========================================================================
+ */
+VOID MlmeCheckForFastRoaming(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now)
+{
+ USHORT i;
+ BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
+ BSS_ENTRY *pBss;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
+ // put all roaming candidates into RoamTab, and sort in RSSI order
+ BssTableInit(pRoamTab);
+ for (i = 0; i < pAd->ScanTab.BssNr; i++)
+ {
+ pBss = &pAd->ScanTab.BssEntry[i];
+
+ if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
+ continue; // RSSI too weak. forget it.
+ if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
+ continue; // skip current AP
+ if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
+ continue; // skip different SSID
+ if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
+ continue; // skip AP without better RSSI
+
+ DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi));
+ // AP passing all above rules is put into roaming candidate table
+ NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
+ pRoamTab->BssNr += 1;
+ }
+
+ if (pRoamTab->BssNr > 0)
+ {
+ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+ if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
+ {
+ pAd->RalinkCounters.PoorCQIRoamingCount ++;
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+ }
+ }
+ // Maybe site survey required
+ else
+ {
+ if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
+ {
+ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
+ DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
+ pAd->StaCfg.ScanCnt = 2;
+ pAd->StaCfg.LastScanTime = Now;
+ MlmeAutoScan(pAd);
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine calculates TxPER, RxPER of the past N-sec period. And
+ according to the calculation result, ChannelQuality is calculated here
+ to decide if current AP is still doing the job.
+
+ If ChannelQuality is not good, a ROAMing attempt may be tried later.
+ Output:
+ StaCfg.ChannelQuality - 0..100
+
+ IRQL = DISPATCH_LEVEL
+
+ NOTE: This routine decide channle quality based on RX CRC error ratio.
+ Caller should make sure a function call to NICUpdateRawCounters(pAd)
+ is performed right before this routine, so that this routine can decide
+ channel quality based on the most up-to-date information
+ ==========================================================================
+ */
+VOID MlmeCalculateChannelQuality(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now32)
+{
+ ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
+ ULONG RxCnt, RxPER;
+ UCHAR NorRssi;
+ CHAR MaxRssi;
+ ULONG BeaconLostTime = BEACON_LOST_TIME;
+
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+ // longer beacon lost time when carrier detection enabled
+ if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+ {
+ BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
+ }
+#endif // CARRIER_DETECTION_SUPPORT //
+
+ MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
+
+ //
+ // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
+ //
+ TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
+ TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
+ if (TxCnt < 5)
+ {
+ TxPER = 0;
+ TxPRR = 0;
+ }
+ else
+ {
+ TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
+ TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
+ }
+
+ //
+ // calculate RX PER - don't take RxPER into consideration if too few sample
+ //
+ RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
+ if (RxCnt < 5)
+ RxPER = 0;
+ else
+ RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
+
+ //
+ // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
+ //
+ if (INFRA_ON(pAd) &&
+ (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
+ (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
+ pAd->Mlme.ChannelQuality = 0;
+ }
+ else
+ {
+ // Normalize Rssi
+ if (MaxRssi > -40)
+ NorRssi = 100;
+ else if (MaxRssi < -90)
+ NorRssi = 0;
+ else
+ NorRssi = (MaxRssi + 90) * 2;
+
+ // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
+ pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
+ TX_WEIGHTING * (100 - TxPRR) +
+ RX_WEIGHTING* (100 - RxPER)) / 100;
+ if (pAd->Mlme.ChannelQuality >= 100)
+ pAd->Mlme.ChannelQuality = 100;
+ }
+
+}
+
+VOID MlmeSetTxRate(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PRTMP_TX_RATE_SWITCH pTxRate)
+{
+ UCHAR MaxMode = MODE_OFDM;
+
+#ifdef DOT11_N_SUPPORT
+ MaxMode = MODE_HTGREENFIELD;
+
+ if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
+ pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
+ else
+#endif // DOT11_N_SUPPORT //
+ pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
+
+ if (pTxRate->CurrMCS < MCS_AUTO)
+ pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
+
+ if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
+ pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
+
+ if (ADHOC_ON(pAd))
+ {
+ // If peer adhoc is b-only mode, we can't send 11g rate.
+ pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+ pEntry->HTPhyMode.field.STBC = STBC_NONE;
+
+ //
+ // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
+ //
+ pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
+ pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
+ pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+
+ // Patch speed error in status page
+ pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
+ }
+ else
+ {
+ if (pTxRate->Mode <= MaxMode)
+ pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
+
+#ifdef DOT11_N_SUPPORT
+ if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
+ pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
+ else
+#endif // DOT11_N_SUPPORT //
+ pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+
+#ifdef DOT11_N_SUPPORT
+ // Reexam each bandwidth's SGI support.
+ if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
+ {
+ if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
+ pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+ if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
+ pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
+ }
+
+ // Turn RTS/CTS rate to 6Mbps.
+ if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
+ {
+ pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ if (pAd->MacTab.fAnyBASession)
+ {
+ AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+ }
+ else
+ {
+ AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+ }
+ }
+ else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
+ {
+ pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ if (pAd->MacTab.fAnyBASession)
+ {
+ AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+ }
+ else
+ {
+ AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+ }
+ }
+ else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
+ {
+ AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+
+ }
+ else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
+ {
+ AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
+ }
+#endif // DOT11_N_SUPPORT //
+
+ pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
+ pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
+ pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
+ pAd->WIFItestbed.bGreenField)
+ pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
+#endif // DOT11_N_SUPPORT //
+ }
+
+ pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine calculates the acumulated TxPER of eaxh TxRate. And
+ according to the calculation result, change CommonCfg.TxRate which
+ is the stable TX Rate we expect the Radio situation could sustained.
+
+ CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
+ Output:
+ CommonCfg.TxRate -
+
+ IRQL = DISPATCH_LEVEL
+
+ NOTE:
+ call this routine every second
+ ==========================================================================
+ */
+VOID MlmeDynamicTxRateSwitching(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
+ ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
+ ULONG TxErrorRatio = 0;
+ BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
+ PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
+ PUCHAR pTable;
+ UCHAR TableSize = 0;
+ UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
+ CHAR Rssi, RssiOffset = 0;
+ TX_STA_CNT1_STRUC StaTx1;
+ TX_STA_CNT0_STRUC TxStaCnt0;
+ ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
+ MAC_TABLE_ENTRY *pEntry;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ {
+ return;
+ }
+#endif // RALINK_ATE //
+
+ /*if (pAd->Antenna.field.RxPath > 1)
+ Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
+ else
+ Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
+
+ //
+ // walk through MAC table, see if need to change AP's TX rate toward each entry
+ //
+ for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ pEntry = &pAd->MacTab.Content[i];
+
+ // check if this entry need to switch rate automatically
+ if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
+ continue;
+
+ if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
+ {
+ Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
+
+ // Update statistic counter
+ RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
+ RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
+ pAd->bUpdateBcnCntDone = TRUE;
+ TxRetransmit = StaTx1.field.TxRetransmit;
+ TxSuccess = StaTx1.field.TxSuccess;
+ TxFailCount = TxStaCnt0.field.TxFailCount;
+ TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+ pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
+ pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
+ pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
+ pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
+ pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
+ pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
+
+ // if no traffic in the past 1-sec period, don't change TX rate,
+ // but clear all bad history. because the bad history may affect the next
+ // Chariot throughput test
+ AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+ pAd->RalinkCounters.OneSecTxRetryOkCount +
+ pAd->RalinkCounters.OneSecTxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+ }
+ else
+ {
+ Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
+
+ TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
+ pEntry->OneSecTxRetryOkCount +
+ pEntry->OneSecTxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
+ }
+
+ CurrRateIdx = pEntry->CurrTxRateIndex;
+
+ MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
+
+ if (CurrRateIdx >= TableSize)
+ {
+ CurrRateIdx = TableSize - 1;
+ }
+
+ // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
+ // So need to sync here.
+ pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
+ if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
+ //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+ )
+ {
+
+ // Need to sync Real Tx rate and our record.
+ // Then return for next DRS.
+ pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
+ pEntry->CurrTxRateIndex = InitTxRateIdx;
+ MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
+
+ // reset all OneSecTx counters
+ RESET_ONE_SEC_TX_CNT(pEntry);
+ continue;
+ }
+
+ // decide the next upgrade rate and downgrade rate, if any
+ if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
+ {
+ UpRateIdx = CurrRateIdx + 1;
+ DownRateIdx = CurrRateIdx -1;
+ }
+ else if (CurrRateIdx == 0)
+ {
+ UpRateIdx = CurrRateIdx + 1;
+ DownRateIdx = CurrRateIdx;
+ }
+ else if (CurrRateIdx == (TableSize - 1))
+ {
+ UpRateIdx = CurrRateIdx;
+ DownRateIdx = CurrRateIdx - 1;
+ }
+
+ pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
+
+#ifdef DOT11_N_SUPPORT
+ if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
+ {
+ TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
+ TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+ TrainUp = pCurrTxRate->TrainUp;
+ TrainDown = pCurrTxRate->TrainDown;
+ }
+
+ //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
+
+ //
+ // Keep the last time TxRateChangeAction status.
+ //
+ pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
+
+
+
+ //
+ // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
+ // (criteria copied from RT2500 for Netopia case)
+ //
+ if (TxTotalCnt <= 15)
+ {
+ CHAR idx = 0;
+ UCHAR TxRateIdx;
+ //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
+ UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
+ UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
+ UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
+
+ // check the existence and index of each needed MCS
+ while (idx < pTable[0])
+ {
+ pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
+
+ if (pCurrTxRate->CurrMCS == MCS_0)
+ {
+ MCS0 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_1)
+ {
+ MCS1 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_2)
+ {
+ MCS2 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_3)
+ {
+ MCS3 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_4)
+ {
+ MCS4 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_5)
+ {
+ MCS5 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_6)
+ {
+ MCS6 = idx;
+ }
+ //else if (pCurrTxRate->CurrMCS == MCS_7)
+ else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
+ {
+ MCS7 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_12)
+ {
+ MCS12 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_13)
+ {
+ MCS13 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_14)
+ {
+ MCS14 = idx;
+ }
+ //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
+ else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
+ {
+ MCS15 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
+ {
+ MCS20 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_21)
+ {
+ MCS21 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_22)
+ {
+ MCS22 = idx;
+ }
+ else if (pCurrTxRate->CurrMCS == MCS_23)
+ {
+ MCS23 = idx;
+ }
+ idx ++;
+ }
+
+ if (pAd->LatchRfRegs.Channel <= 14)
+ {
+ if (pAd->NicConfig2.field.ExternalLNAForG)
+ {
+ RssiOffset = 2;
+ }
+ else
+ {
+ RssiOffset = 5;
+ }
+ }
+ else
+ {
+ if (pAd->NicConfig2.field.ExternalLNAForA)
+ {
+ RssiOffset = 5;
+ }
+ else
+ {
+ RssiOffset = 8;
+ }
+ }
+#ifdef DOT11_N_SUPPORT
+ /*if (MCS15)*/
+ if ((pTable == RateSwitchTable11BGN3S) ||
+ (pTable == RateSwitchTable11N3S) ||
+ (pTable == RateSwitchTable))
+ {// N mode with 3 stream // 3*3
+ if (MCS23 && (Rssi >= -70))
+ TxRateIdx = MCS15;
+ else if (MCS22 && (Rssi >= -72))
+ TxRateIdx = MCS14;
+ else if (MCS21 && (Rssi >= -76))
+ TxRateIdx = MCS13;
+ else if (MCS20 && (Rssi >= -78))
+ TxRateIdx = MCS12;
+ else if (MCS4 && (Rssi >= -82))
+ TxRateIdx = MCS4;
+ else if (MCS3 && (Rssi >= -84))
+ TxRateIdx = MCS3;
+ else if (MCS2 && (Rssi >= -86))
+ TxRateIdx = MCS2;
+ else if (MCS1 && (Rssi >= -88))
+ TxRateIdx = MCS1;
+ else
+ TxRateIdx = MCS0;
+ }
+ else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
+ {// N mode with 2 stream
+ if (MCS15 && (Rssi >= (-70+RssiOffset)))
+ TxRateIdx = MCS15;
+ else if (MCS14 && (Rssi >= (-72+RssiOffset)))
+ TxRateIdx = MCS14;
+ else if (MCS13 && (Rssi >= (-76+RssiOffset)))
+ TxRateIdx = MCS13;
+ else if (MCS12 && (Rssi >= (-78+RssiOffset)))
+ TxRateIdx = MCS12;
+ else if (MCS4 && (Rssi >= (-82+RssiOffset)))
+ TxRateIdx = MCS4;
+ else if (MCS3 && (Rssi >= (-84+RssiOffset)))
+ TxRateIdx = MCS3;
+ else if (MCS2 && (Rssi >= (-86+RssiOffset)))
+ TxRateIdx = MCS2;
+ else if (MCS1 && (Rssi >= (-88+RssiOffset)))
+ TxRateIdx = MCS1;
+ else
+ TxRateIdx = MCS0;
+ }
+ else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
+ {// N mode with 1 stream
+ if (MCS7 && (Rssi > (-72+RssiOffset)))
+ TxRateIdx = MCS7;
+ else if (MCS6 && (Rssi > (-74+RssiOffset)))
+ TxRateIdx = MCS6;
+ else if (MCS5 && (Rssi > (-77+RssiOffset)))
+ TxRateIdx = MCS5;
+ else if (MCS4 && (Rssi > (-79+RssiOffset)))
+ TxRateIdx = MCS4;
+ else if (MCS3 && (Rssi > (-81+RssiOffset)))
+ TxRateIdx = MCS3;
+ else if (MCS2 && (Rssi > (-83+RssiOffset)))
+ TxRateIdx = MCS2;
+ else if (MCS1 && (Rssi > (-86+RssiOffset)))
+ TxRateIdx = MCS1;
+ else
+ TxRateIdx = MCS0;
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {// Legacy mode
+ if (MCS7 && (Rssi > -70))
+ TxRateIdx = MCS7;
+ else if (MCS6 && (Rssi > -74))
+ TxRateIdx = MCS6;
+ else if (MCS5 && (Rssi > -78))
+ TxRateIdx = MCS5;
+ else if (MCS4 && (Rssi > -82))
+ TxRateIdx = MCS4;
+ else if (MCS4 == 0) // for B-only mode
+ TxRateIdx = MCS3;
+ else if (MCS3 && (Rssi > -85))
+ TxRateIdx = MCS3;
+ else if (MCS2 && (Rssi > -87))
+ TxRateIdx = MCS2;
+ else if (MCS1 && (Rssi > -90))
+ TxRateIdx = MCS1;
+ else
+ TxRateIdx = MCS0;
+ }
+
+ {
+ pEntry->CurrTxRateIndex = TxRateIdx;
+ pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
+ MlmeSetTxRate(pAd, pEntry, pNextTxRate);
+ }
+
+ NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+ NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+ pEntry->fLastSecAccordingRSSI = TRUE;
+ // reset all OneSecTx counters
+ RESET_ONE_SEC_TX_CNT(pEntry);
+
+ continue;
+ }
+
+ if (pEntry->fLastSecAccordingRSSI == TRUE)
+ {
+ pEntry->fLastSecAccordingRSSI = FALSE;
+ pEntry->LastSecTxRateChangeAction = 0;
+ // reset all OneSecTx counters
+ RESET_ONE_SEC_TX_CNT(pEntry);
+
+ continue;
+ }
+
+ do
+ {
+ BOOLEAN bTrainUpDown = FALSE;
+
+ pEntry->CurrTxRateStableTime ++;
+
+ // downgrade TX quality if PER >= Rate-Down threshold
+ if (TxErrorRatio >= TrainDown)
+ {
+ bTrainUpDown = TRUE;
+ pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+ }
+ // upgrade TX quality if PER <= Rate-Up threshold
+ else if (TxErrorRatio <= TrainUp)
+ {
+ bTrainUpDown = TRUE;
+ bUpgradeQuality = TRUE;
+ if (pEntry->TxQuality[CurrRateIdx])
+ pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
+
+ if (pEntry->TxRateUpPenalty)
+ pEntry->TxRateUpPenalty --;
+ else if (pEntry->TxQuality[UpRateIdx])
+ pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
+ }
+
+ pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
+
+ if (bTrainUpDown)
+ {
+ // perform DRS - consider TxRate Down first, then rate up.
+ if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
+ {
+ pEntry->CurrTxRateIndex = DownRateIdx;
+ }
+ else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
+ {
+ pEntry->CurrTxRateIndex = UpRateIdx;
+ }
+ }
+ } while (FALSE);
+
+ // if rate-up happen, clear all bad history of all TX rates
+ if (pEntry->CurrTxRateIndex > CurrRateIdx)
+ {
+ pEntry->CurrTxRateStableTime = 0;
+ pEntry->TxRateUpPenalty = 0;
+ pEntry->LastSecTxRateChangeAction = 1; // rate UP
+ NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+ NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+
+ //
+ // For TxRate fast train up
+ //
+ if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
+ {
+ RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
+
+ pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
+ }
+ bTxRateChanged = TRUE;
+ }
+ // if rate-down happen, only clear DownRate's bad history
+ else if (pEntry->CurrTxRateIndex < CurrRateIdx)
+ {
+ pEntry->CurrTxRateStableTime = 0;
+ pEntry->TxRateUpPenalty = 0; // no penalty
+ pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
+ pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
+ pEntry->PER[pEntry->CurrTxRateIndex] = 0;
+
+ //
+ // For TxRate fast train down
+ //
+ if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
+ {
+ RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
+
+ pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
+ }
+ bTxRateChanged = TRUE;
+ }
+ else
+ {
+ pEntry->LastSecTxRateChangeAction = 0; // rate no change
+ bTxRateChanged = FALSE;
+ }
+
+ pEntry->LastTxOkCount = TxSuccess;
+
+ // reset all OneSecTx counters
+ RESET_ONE_SEC_TX_CNT(pEntry);
+
+ pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
+ if (bTxRateChanged && pNextTxRate)
+ {
+ MlmeSetTxRate(pAd, pEntry, pNextTxRate);
+ }
+ }
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Station side, Auto TxRate faster train up timer call back function.
+
+ Arguments:
+ SystemSpecific1 - Not used.
+ FunctionContext - Pointer to our Adapter context.
+ SystemSpecific2 - Not used.
+ SystemSpecific3 - Not used.
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID StaQuickResponeForRateUpExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
+ UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
+ ULONG TxTotalCnt;
+ ULONG TxErrorRatio = 0;
+ BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
+ PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
+ PUCHAR pTable;
+ UCHAR TableSize = 0;
+ UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
+ TX_STA_CNT1_STRUC StaTx1;
+ TX_STA_CNT0_STRUC TxStaCnt0;
+ CHAR Rssi, ratio;
+ ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
+ MAC_TABLE_ENTRY *pEntry;
+ ULONG i;
+
+ pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
+
+ //
+ // walk through MAC table, see if need to change AP's TX rate toward each entry
+ //
+ for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ pEntry = &pAd->MacTab.Content[i];
+
+ // check if this entry need to switch rate automatically
+ if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
+ continue;
+
+ //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
+ if (pAd->Antenna.field.TxPath > 1)
+ Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
+ else
+ Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
+
+ CurrRateIdx = pAd->CommonCfg.TxRateIndex;
+
+ MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
+
+ // decide the next upgrade rate and downgrade rate, if any
+ if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
+ {
+ UpRateIdx = CurrRateIdx + 1;
+ DownRateIdx = CurrRateIdx -1;
+ }
+ else if (CurrRateIdx == 0)
+ {
+ UpRateIdx = CurrRateIdx + 1;
+ DownRateIdx = CurrRateIdx;
+ }
+ else if (CurrRateIdx == (TableSize - 1))
+ {
+ UpRateIdx = CurrRateIdx;
+ DownRateIdx = CurrRateIdx - 1;
+ }
+
+ pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
+
+#ifdef DOT11_N_SUPPORT
+ if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
+ {
+ TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
+ TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+ TrainUp = pCurrTxRate->TrainUp;
+ TrainDown = pCurrTxRate->TrainDown;
+ }
+
+ if (pAd->MacTab.Size == 1)
+ {
+ // Update statistic counter
+ RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
+ RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
+
+ TxRetransmit = StaTx1.field.TxRetransmit;
+ TxSuccess = StaTx1.field.TxSuccess;
+ TxFailCount = TxStaCnt0.field.TxFailCount;
+ TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
+
+ pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
+ pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
+ pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
+ pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
+ pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
+ pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
+ }
+ else
+ {
+ TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
+ pEntry->OneSecTxRetryOkCount +
+ pEntry->OneSecTxFailCount;
+
+ if (TxTotalCnt)
+ TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
+ }
+
+
+ //
+ // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
+ // (criteria copied from RT2500 for Netopia case)
+ //
+ if (TxTotalCnt <= 12)
+ {
+ NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+ NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+
+ if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
+ {
+ pAd->CommonCfg.TxRateIndex = DownRateIdx;
+ pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+ }
+ else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
+ {
+ pAd->CommonCfg.TxRateIndex = UpRateIdx;
+ }
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
+ return;
+ }
+
+ do
+ {
+ ULONG OneSecTxNoRetryOKRationCount;
+
+ if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
+ ratio = 5;
+ else
+ ratio = 4;
+
+ // downgrade TX quality if PER >= Rate-Down threshold
+ if (TxErrorRatio >= TrainDown)
+ {
+ pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+ }
+
+ pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
+
+ OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
+
+ // perform DRS - consider TxRate Down first, then rate up.
+ if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
+ {
+ if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
+ {
+ pAd->CommonCfg.TxRateIndex = DownRateIdx;
+ pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
+
+ }
+
+ }
+ else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
+ {
+ if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
+ {
+
+ }
+ else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
+ {
+ pAd->CommonCfg.TxRateIndex = UpRateIdx;
+ }
+ }
+ }while (FALSE);
+
+ // if rate-up happen, clear all bad history of all TX rates
+ if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
+ {
+ pAd->DrsCounters.TxRateUpPenalty = 0;
+ NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
+ NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
+ }
+ // if rate-down happen, only clear DownRate's bad history
+ else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
+
+ pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
+ pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
+ pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
+ }
+ else
+ {
+ bTxRateChanged = FALSE;
+ }
+
+ pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
+ if (bTxRateChanged && pNextTxRate)
+ {
+ MlmeSetTxRate(pAd, pEntry, pNextTxRate);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ This routine is executed periodically inside MlmePeriodicExec() after
+ association with an AP.
+ It checks if StaCfg.Psm is consistent with user policy (recorded in
+ StaCfg.WindowsPowerMode). If not, enforce user policy. However,
+ there're some conditions to consider:
+ 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
+ the time when Mibss==TRUE
+ 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
+ if outgoing traffic available in TxRing or MgmtRing.
+ Output:
+ 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeCheckPsmChange(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now32)
+{
+ ULONG PowerMode;
+
+ // condition -
+ // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
+ // 2. user wants either MAX_PSP or FAST_PSP
+ // 3. but current psm is not in PWR_SAVE
+ // 4. CNTL state machine is not doing SCANning
+ // 5. no TX SUCCESS event for the past 1-sec period
+#ifdef NDIS51_MINIPORT
+ if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
+ PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
+ else
+#endif
+ PowerMode = pAd->StaCfg.WindowsPowerMode;
+
+ if (INFRA_ON(pAd) &&
+ (PowerMode != Ndis802_11PowerModeCAM) &&
+ (pAd->StaCfg.Psm == PWR_ACTIVE) &&
+ (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
+ {
+ NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
+ pAd->RalinkCounters.RxCountSinceLastNULL = 0;
+ MlmeSetPsmBit(pAd, PWR_SAVE);
+ if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
+ {
+ RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
+ }
+ else
+ {
+ RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
+ }
+ }
+}
+
+// IRQL = PASSIVE_LEVEL
+// IRQL = DISPATCH_LEVEL
+VOID MlmeSetPsmBit(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT psm)
+{
+ AUTO_RSP_CFG_STRUC csr4;
+
+ pAd->StaCfg.Psm = psm;
+ RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
+ csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
+ RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeSetTxPreamble(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT TxPreamble)
+{
+ AUTO_RSP_CFG_STRUC csr4;
+
+ //
+ // Always use Long preamble before verifiation short preamble functionality works well.
+ // Todo: remove the following line if short preamble functionality works
+ //
+ //TxPreamble = Rt802_11PreambleLong;
+
+ RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
+ if (TxPreamble == Rt802_11PreambleLong)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ csr4.field.AutoResponderPreamble = 0;
+ }
+ else
+ {
+ // NOTE: 1Mbps should always use long preamble
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ csr4.field.AutoResponderPreamble = 1;
+ }
+
+ RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Update basic rate bitmap
+ ==========================================================================
+ */
+
+VOID UpdateBasicRateBitmap(
+ IN PRTMP_ADAPTER pAdapter)
+{
+ INT i, j;
+ /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
+ UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
+ UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
+ UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
+ ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
+
+
+ /* if A mode, always use fix BasicRateBitMap */
+ //if (pAdapter->CommonCfg.Channel == PHY_11A)
+ if (pAdapter->CommonCfg.Channel > 14)
+ pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
+ /* End of if */
+
+ if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
+ {
+ /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
+ return;
+ } /* End of if */
+
+ for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ sup_p[i] &= 0x7f;
+ ext_p[i] &= 0x7f;
+ } /* End of for */
+
+ for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ if (bitmap & (1 << i))
+ {
+ for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
+ {
+ if (sup_p[j] == rate[i])
+ sup_p[j] |= 0x80;
+ /* End of if */
+ } /* End of for */
+
+ for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
+ {
+ if (ext_p[j] == rate[i])
+ ext_p[j] |= 0x80;
+ /* End of if */
+ } /* End of for */
+ } /* End of if */
+ } /* End of for */
+} /* End of UpdateBasicRateBitmap */
+
+// IRQL = PASSIVE_LEVEL
+// IRQL = DISPATCH_LEVEL
+// bLinkUp is to identify the inital link speed.
+// TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
+VOID MlmeUpdateTxRates(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bLinkUp,
+ IN UCHAR apidx)
+{
+ int i, num;
+ UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
+ UCHAR MinSupport = RATE_54;
+ ULONG BasicRateBitmap = 0;
+ UCHAR CurrBasicRate = RATE_1;
+ UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
+ PHTTRANSMIT_SETTING pHtPhy = NULL;
+ PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
+ PHTTRANSMIT_SETTING pMinHtPhy = NULL;
+ BOOLEAN *auto_rate_cur_p;
+ UCHAR HtMcs = MCS_AUTO;
+
+ // find max desired rate
+ UpdateBasicRateBitmap(pAd);
+
+ num = 0;
+ auto_rate_cur_p = NULL;
+ for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
+ {
+ case 2: Rate = RATE_1; num++; break;
+ case 4: Rate = RATE_2; num++; break;
+ case 11: Rate = RATE_5_5; num++; break;
+ case 22: Rate = RATE_11; num++; break;
+ case 12: Rate = RATE_6; num++; break;
+ case 18: Rate = RATE_9; num++; break;
+ case 24: Rate = RATE_12; num++; break;
+ case 36: Rate = RATE_18; num++; break;
+ case 48: Rate = RATE_24; num++; break;
+ case 72: Rate = RATE_36; num++; break;
+ case 96: Rate = RATE_48; num++; break;
+ case 108: Rate = RATE_54; num++; break;
+ //default: Rate = RATE_1; break;
+ }
+ if (MaxDesire < Rate) MaxDesire = Rate;
+ }
+
+//===========================================================================
+//===========================================================================
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pHtPhy = &pAd->StaCfg.HTPhyMode;
+ pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
+ pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
+ HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
+
+ if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
+ (pAd->CommonCfg.PhyMode == PHY_11B) &&
+ (MaxDesire > RATE_11))
+ {
+ MaxDesire = RATE_11;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ pAd->CommonCfg.MaxDesiredRate = MaxDesire;
+ pMinHtPhy->word = 0;
+ pMaxHtPhy->word = 0;
+ pHtPhy->word = 0;
+
+ // Auto rate switching is enabled only if more than one DESIRED RATES are
+ // specified; otherwise disabled
+ if (num <= 1)
+ {
+ *auto_rate_cur_p = FALSE;
+ }
+ else
+ {
+ *auto_rate_cur_p = TRUE;
+ }
+
+#if 1
+ if (HtMcs != MCS_AUTO)
+ {
+ *auto_rate_cur_p = FALSE;
+ }
+ else
+ {
+ *auto_rate_cur_p = TRUE;
+ }
+#endif
+
+#ifdef CONFIG_STA_SUPPORT
+ if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
+ {
+ pSupRate = &pAd->StaActive.SupRate[0];
+ pExtRate = &pAd->StaActive.ExtRate[0];
+ SupRateLen = pAd->StaActive.SupRateLen;
+ ExtRateLen = pAd->StaActive.ExtRateLen;
+ }
+ else
+#endif // CONFIG_STA_SUPPORT //
+ {
+ pSupRate = &pAd->CommonCfg.SupRate[0];
+ pExtRate = &pAd->CommonCfg.ExtRate[0];
+ SupRateLen = pAd->CommonCfg.SupRateLen;
+ ExtRateLen = pAd->CommonCfg.ExtRateLen;
+ }
+
+ // find max supported rate
+ for (i=0; i<SupRateLen; i++)
+ {
+ switch (pSupRate[i] & 0x7f)
+ {
+ case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
+ case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
+ case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
+ case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
+ case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
+ case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
+ case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
+ case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
+ case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
+ case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
+ case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
+ case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
+ default: Rate = RATE_1; break;
+ }
+ if (MaxSupport < Rate) MaxSupport = Rate;
+
+ if (MinSupport > Rate) MinSupport = Rate;
+ }
+
+ for (i=0; i<ExtRateLen; i++)
+ {
+ switch (pExtRate[i] & 0x7f)
+ {
+ case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
+ case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
+ case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
+ case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
+ case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
+ case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
+ case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
+ case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
+ case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
+ case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
+ case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
+ case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
+ default: Rate = RATE_1; break;
+ }
+ if (MaxSupport < Rate) MaxSupport = Rate;
+
+ if (MinSupport > Rate) MinSupport = Rate;
+ }
+
+ RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
+
+ // calculate the exptected ACK rate for each TX rate. This info is used to caculate
+ // the DURATION field of outgoing uniicast DATA/MGMT frame
+ for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
+ {
+ if (BasicRateBitmap & (0x01 << i))
+ CurrBasicRate = (UCHAR)i;
+ pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
+ // max tx rate = min {max desire rate, max supported rate}
+ if (MaxSupport < MaxDesire)
+ pAd->CommonCfg.MaxTxRate = MaxSupport;
+ else
+ pAd->CommonCfg.MaxTxRate = MaxDesire;
+
+ pAd->CommonCfg.MinTxRate = MinSupport;
+ if (*auto_rate_cur_p)
+ {
+ short dbm = 0;
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
+#endif // CONFIG_STA_SUPPORT //
+ if (bLinkUp == TRUE)
+ pAd->CommonCfg.TxRate = RATE_24;
+ else
+ pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+
+ if (dbm < -75)
+ pAd->CommonCfg.TxRate = RATE_11;
+ else if (dbm < -70)
+ pAd->CommonCfg.TxRate = RATE_24;
+
+ // should never exceed MaxTxRate (consider 11B-only mode)
+ if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
+ pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+
+ pAd->CommonCfg.TxRateIndex = 0;
+ }
+ else
+ {
+ pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
+ pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
+ pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
+
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
+ }
+
+ if (pAd->CommonCfg.TxRate <= RATE_11)
+ {
+ pMaxHtPhy->field.MODE = MODE_CCK;
+ pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
+ pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
+ }
+ else
+ {
+ pMaxHtPhy->field.MODE = MODE_OFDM;
+ pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
+ if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
+ {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
+ else
+ {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
+ }
+
+ pHtPhy->word = (pMaxHtPhy->word);
+ if (bLinkUp && (pAd->OpMode == OPMODE_STA))
+ {
+ pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
+ pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
+ pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
+ }
+ else
+ {
+ switch (pAd->CommonCfg.PhyMode)
+ {
+ case PHY_11BG_MIXED:
+ case PHY_11B:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11BGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+ pAd->CommonCfg.MlmeRate = RATE_1;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
+ pAd->CommonCfg.RtsRate = RATE_11;
+ break;
+ case PHY_11G:
+ case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11AGN_MIXED:
+ case PHY_11GN_MIXED:
+ case PHY_11N_2_4G:
+ case PHY_11AN_MIXED:
+ case PHY_11N_5G:
+#endif // DOT11_N_SUPPORT //
+ pAd->CommonCfg.MlmeRate = RATE_6;
+ pAd->CommonCfg.RtsRate = RATE_6;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ break;
+ case PHY_11ABG_MIXED:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11ABGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+ if (pAd->CommonCfg.Channel <= 14)
+ {
+ pAd->CommonCfg.MlmeRate = RATE_1;
+ pAd->CommonCfg.RtsRate = RATE_1;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
+ }
+ else
+ {
+ pAd->CommonCfg.MlmeRate = RATE_6;
+ pAd->CommonCfg.RtsRate = RATE_6;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ }
+ break;
+ default: // error
+ pAd->CommonCfg.MlmeRate = RATE_6;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ pAd->CommonCfg.RtsRate = RATE_1;
+ break;
+ }
+ //
+ // Keep Basic Mlme Rate.
+ //
+ pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
+ if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
+ pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
+ else
+ pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
+ pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
+ RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
+ /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
+ DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
+ RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
+ pAd->CommonCfg.MlmeTransmit.word, pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word ,pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word ));
+}
+
+#ifdef DOT11_N_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ This function update HT Rate setting.
+ Input Wcid value is valid for 2 case :
+ 1. it's used for Station in infra mode that copy AP rate to Mactable.
+ 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeUpdateHtTxRates(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apidx)
+{
+ UCHAR StbcMcs; //j, StbcMcs, bitmask;
+ CHAR i; // 3*3
+ RT_HT_CAPABILITY *pRtHtCap = NULL;
+ RT_HT_PHY_INFO *pActiveHtPhy = NULL;
+ ULONG BasicMCS;
+ UCHAR j, bitmask;
+ PRT_HT_PHY_INFO pDesireHtPhy = NULL;
+ PHTTRANSMIT_SETTING pHtPhy = NULL;
+ PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
+ PHTTRANSMIT_SETTING pMinHtPhy = NULL;
+ BOOLEAN *auto_rate_cur_p;
+
+ DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
+
+ auto_rate_cur_p = NULL;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
+ pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
+ pHtPhy = &pAd->StaCfg.HTPhyMode;
+ pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
+ pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
+
+ auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+ if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
+ {
+ if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
+ return;
+
+ pRtHtCap = &pAd->StaActive.SupportedHtPhy;
+ pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
+ StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
+ BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
+ if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
+ pMaxHtPhy->field.STBC = STBC_USE;
+ else
+ pMaxHtPhy->field.STBC = STBC_NONE;
+ }
+ else
+#endif // CONFIG_STA_SUPPORT //
+ {
+ if (pDesireHtPhy->bHtEnable == FALSE)
+ return;
+
+ pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
+ StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
+ BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
+ if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
+ pMaxHtPhy->field.STBC = STBC_USE;
+ else
+ pMaxHtPhy->field.STBC = STBC_NONE;
+ }
+
+ // Decide MAX ht rate.
+ if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+ pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
+ else
+ pMaxHtPhy->field.MODE = MODE_HTMIX;
+
+ if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
+ pMaxHtPhy->field.BW = BW_40;
+ else
+ pMaxHtPhy->field.BW = BW_20;
+
+ if (pMaxHtPhy->field.BW == BW_20)
+ pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
+ else
+ pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
+
+ for (i=23; i>=0; i--) // 3*3
+ {
+ j = i/8;
+ bitmask = (1<<(i-(j*8)));
+
+ if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
+ {
+ pMaxHtPhy->field.MCS = i;
+ break;
+ }
+
+ if (i==0)
+ break;
+ }
+
+ // Copy MIN ht rate. rt2860???
+ pMinHtPhy->field.BW = BW_20;
+ pMinHtPhy->field.MCS = 0;
+ pMinHtPhy->field.STBC = 0;
+ pMinHtPhy->field.ShortGI = 0;
+ //If STA assigns fixed rate. update to fixed here.
+#ifdef CONFIG_STA_SUPPORT
+ if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
+ {
+ if (pDesireHtPhy->MCSSet[4] != 0)
+ {
+ pMaxHtPhy->field.MCS = 32;
+ pMinHtPhy->field.MCS = 32;
+ DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
+ }
+
+ for (i=23; (CHAR)i >= 0; i--) // 3*3
+ {
+ j = i/8;
+ bitmask = (1<<(i-(j*8)));
+ if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
+ {
+ pMaxHtPhy->field.MCS = i;
+ pMinHtPhy->field.MCS = i;
+ break;
+ }
+ if (i==0)
+ break;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+
+ // Decide ht rate
+ pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
+ pHtPhy->field.BW = pMaxHtPhy->field.BW;
+ pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
+ pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
+ pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
+
+ // use default now. rt2860
+ if (pDesireHtPhy->MCSSet[0] != 0xff)
+ *auto_rate_cur_p = FALSE;
+ else
+ *auto_rate_cur_p = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
+ DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
+ pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
+ DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
+}
+#endif // DOT11_N_SUPPORT //
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeRadioOff(
+ IN PRTMP_ADAPTER pAd)
+{
+ RT28XX_MLME_RADIO_OFF(pAd);
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeRadioOn(
+ IN PRTMP_ADAPTER pAd)
+{
+ RT28XX_MLME_RADIO_ON(pAd);
+}
+
+// ===========================================================================================
+// bss_table.c
+// ===========================================================================================
+
+
+/*! \brief initialize BSS table
+ * \param p_tab pointer to the table
+ * \return none
+ * \pre
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID BssTableInit(
+ IN BSS_TABLE *Tab)
+{
+ int i;
+
+ Tab->BssNr = 0;
+ Tab->BssOverlapNr = 0;
+ for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
+ {
+ NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
+ Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
+ }
+}
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableInit(
+ IN PRTMP_ADAPTER pAd,
+ IN BA_TABLE *Tab)
+{
+ int i;
+
+ Tab->numAsOriginator = 0;
+ Tab->numAsRecipient = 0;
+ NdisAllocateSpinLock(&pAd->BATabLock);
+ for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
+ {
+ Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
+ NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
+ }
+ for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
+ {
+ Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
+ }
+}
+#endif // DOT11_N_SUPPORT //
+
+/*! \brief search the BSS table by SSID
+ * \param p_tab pointer to the bss table
+ * \param ssid SSID string
+ * \return index of the table, BSS_NOT_FOUND if not in the table
+ * \pre
+ * \post
+ * \note search by sequential search
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+ULONG BssTableSearch(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN UCHAR Channel)
+{
+ UCHAR i;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+ //
+ // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
+ // We should distinguish this case.
+ //
+ if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+ ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+ MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
+ {
+ return i;
+ }
+ }
+ return (ULONG)BSS_NOT_FOUND;
+}
+
+ULONG BssSsidTableSearch(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen,
+ IN UCHAR Channel)
+{
+ UCHAR i;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+ //
+ // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
+ // We should distinguish this case.
+ //
+ if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+ ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+ MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
+ SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
+ {
+ return i;
+ }
+ }
+ return (ULONG)BSS_NOT_FOUND;
+}
+
+ULONG BssTableSearchWithSSID(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR Bssid,
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen,
+ IN UCHAR Channel)
+{
+ UCHAR i;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+ if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
+ ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
+ MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
+ (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
+ (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
+ (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
+ {
+ return i;
+ }
+ }
+ return (ULONG)BSS_NOT_FOUND;
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID BssTableDeleteEntry(
+ IN OUT BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN UCHAR Channel)
+{
+ UCHAR i, j;
+
+ for (i = 0; i < Tab->BssNr; i++)
+ {
+ if ((Tab->BssEntry[i].Channel == Channel) &&
+ (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
+ {
+ for (j = i; j < Tab->BssNr - 1; j++)
+ {
+ NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
+ }
+ NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
+ Tab->BssNr -= 1;
+ return;
+ }
+ }
+}
+
+#ifdef DOT11_N_SUPPORT
+/*
+ ========================================================================
+ Routine Description:
+ Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
+
+ Arguments:
+ // IRQL = DISPATCH_LEVEL
+ ========================================================================
+*/
+VOID BATableDeleteORIEntry(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN BA_ORI_ENTRY *pBAORIEntry)
+{
+
+ if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
+ {
+ NdisAcquireSpinLock(&pAd->BATabLock);
+ if (pBAORIEntry->ORI_BA_Status == Originator_Done)
+ {
+ pAd->BATable.numAsOriginator -= 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
+ // Erase Bitmap flag.
+ }
+ pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
+ pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
+ pBAORIEntry->ORI_BA_Status = Originator_NONE;
+ pBAORIEntry->Token = 1;
+ // Not clear Sequence here.
+ NdisReleaseSpinLock(&pAd->BATabLock);
+ }
+}
+#endif // DOT11_N_SUPPORT //
+
+/*! \brief
+ * \param
+ * \return
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID BssEntrySet(
+ IN PRTMP_ADAPTER pAd,
+ OUT BSS_ENTRY *pBss,
+ IN PUCHAR pBssid,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen,
+ IN UCHAR BssType,
+ IN USHORT BeaconPeriod,
+ IN PCF_PARM pCfParm,
+ IN USHORT AtimWin,
+ IN USHORT CapabilityInfo,
+ IN UCHAR SupRate[],
+ IN UCHAR SupRateLen,
+ IN UCHAR ExtRate[],
+ IN UCHAR ExtRateLen,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
+ IN UCHAR HtCapabilityLen,
+ IN UCHAR AddHtInfoLen,
+ IN UCHAR NewExtChanOffset,
+ IN UCHAR Channel,
+ IN CHAR Rssi,
+ IN LARGE_INTEGER TimeStamp,
+ IN UCHAR CkipFlag,
+ IN PEDCA_PARM pEdcaParm,
+ IN PQOS_CAPABILITY_PARM pQosCapability,
+ IN PQBSS_LOAD_PARM pQbssLoad,
+ IN USHORT LengthVIE,
+ IN PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+ COPY_MAC_ADDR(pBss->Bssid, pBssid);
+ // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
+ pBss->Hidden = 1;
+ if (SsidLen > 0)
+ {
+ // For hidden SSID AP, it might send beacon with SSID len equal to 0
+ // Or send beacon /probe response with SSID len matching real SSID length,
+ // but SSID is all zero. such as "00-00-00-00" with length 4.
+ // We have to prevent this case overwrite correct table
+ if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
+ {
+ NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
+ pBss->SsidLen = SsidLen;
+ pBss->Hidden = 0;
+ }
+ }
+ else
+ pBss->SsidLen = 0;
+ pBss->BssType = BssType;
+ pBss->BeaconPeriod = BeaconPeriod;
+ if (BssType == BSS_INFRA)
+ {
+ if (pCfParm->bValid)
+ {
+ pBss->CfpCount = pCfParm->CfpCount;
+ pBss->CfpPeriod = pCfParm->CfpPeriod;
+ pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
+ pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
+ }
+ }
+ else
+ {
+ pBss->AtimWin = AtimWin;
+ }
+
+ pBss->CapabilityInfo = CapabilityInfo;
+ // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
+ // Combine with AuthMode, they will decide the connection methods.
+ pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
+ ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
+ if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
+ NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
+ else
+ NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
+ pBss->SupRateLen = SupRateLen;
+ ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
+ NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
+ NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
+ NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
+ pBss->NewExtChanOffset = NewExtChanOffset;
+ pBss->ExtRateLen = ExtRateLen;
+ pBss->Channel = Channel;
+ pBss->CentralChannel = Channel;
+ pBss->Rssi = Rssi;
+ // Update CkipFlag. if not exists, the value is 0x0
+ pBss->CkipFlag = CkipFlag;
+
+ // New for microsoft Fixed IEs
+ NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
+ pBss->FixIEs.BeaconInterval = BeaconPeriod;
+ pBss->FixIEs.Capabilities = CapabilityInfo;
+
+ // New for microsoft Variable IEs
+ if (LengthVIE != 0)
+ {
+ pBss->VarIELen = LengthVIE;
+ NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
+ }
+ else
+ {
+ pBss->VarIELen = 0;
+ }
+
+ pBss->AddHtInfoLen = 0;
+ pBss->HtCapabilityLen = 0;
+#ifdef DOT11_N_SUPPORT
+ if (HtCapabilityLen> 0)
+ {
+ pBss->HtCapabilityLen = HtCapabilityLen;
+ NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
+ if (AddHtInfoLen > 0)
+ {
+ pBss->AddHtInfoLen = AddHtInfoLen;
+ NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
+
+ if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
+ {
+ pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
+ }
+ else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
+ {
+ pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
+ }
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+ BssCipherParse(pBss);
+
+ // new for QOS
+ if (pEdcaParm)
+ NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
+ else
+ pBss->EdcaParm.bValid = FALSE;
+ if (pQosCapability)
+ NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
+ else
+ pBss->QosCapability.bValid = FALSE;
+ if (pQbssLoad)
+ NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
+ else
+ pBss->QbssLoad.bValid = FALSE;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ PEID_STRUCT pEid;
+ USHORT Length = 0;
+
+
+ NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
+ NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
+#ifdef EXT_BUILD_CHANNEL_LIST
+ NdisZeroMemory(&pBss->CountryString[0], 3);
+ pBss->bHasCountryIE = FALSE;
+#endif // EXT_BUILD_CHANNEL_LIST //
+ pEid = (PEID_STRUCT) pVIE;
+ while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
+ {
+ switch(pEid->Eid)
+ {
+ case IE_WPA:
+ if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+ {
+ if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
+ {
+ pBss->WpaIE.IELen = 0;
+ break;
+ }
+ pBss->WpaIE.IELen = pEid->Len + 2;
+ NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
+ }
+ break;
+ case IE_RSN:
+ if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+ {
+ if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
+ {
+ pBss->RsnIE.IELen = 0;
+ break;
+ }
+ pBss->RsnIE.IELen = pEid->Len + 2;
+ NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
+ }
+ break;
+#ifdef EXT_BUILD_CHANNEL_LIST
+ case IE_COUNTRY:
+ NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
+ pBss->bHasCountryIE = TRUE;
+ break;
+#endif // EXT_BUILD_CHANNEL_LIST //
+ }
+ Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
+ pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+}
+
+/*!
+ * \brief insert an entry into the bss table
+ * \param p_tab The BSS table
+ * \param Bssid BSSID
+ * \param ssid SSID
+ * \param ssid_len Length of SSID
+ * \param bss_type
+ * \param beacon_period
+ * \param timestamp
+ * \param p_cf
+ * \param atim_win
+ * \param cap
+ * \param rates
+ * \param rates_len
+ * \param channel_idx
+ * \return none
+ * \pre
+ * \post
+ * \note If SSID is identical, the old entry will be replaced by the new one
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+ULONG BssTableSetEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen,
+ IN UCHAR BssType,
+ IN USHORT BeaconPeriod,
+ IN CF_PARM *CfParm,
+ IN USHORT AtimWin,
+ IN USHORT CapabilityInfo,
+ IN UCHAR SupRate[],
+ IN UCHAR SupRateLen,
+ IN UCHAR ExtRate[],
+ IN UCHAR ExtRateLen,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
+ IN UCHAR HtCapabilityLen,
+ IN UCHAR AddHtInfoLen,
+ IN UCHAR NewExtChanOffset,
+ IN UCHAR ChannelNo,
+ IN CHAR Rssi,
+ IN LARGE_INTEGER TimeStamp,
+ IN UCHAR CkipFlag,
+ IN PEDCA_PARM pEdcaParm,
+ IN PQOS_CAPABILITY_PARM pQosCapability,
+ IN PQBSS_LOAD_PARM pQbssLoad,
+ IN USHORT LengthVIE,
+ IN PNDIS_802_11_VARIABLE_IEs pVIE)
+{
+ ULONG Idx;
+
+ Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
+ if (Idx == BSS_NOT_FOUND)
+ {
+ if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
+ {
+ //
+ // It may happen when BSS Table was full.
+ // The desired AP will not be added into BSS Table
+ // In this case, if we found the desired AP then overwrite BSS Table.
+ //
+ if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ {
+ if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
+ SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
+ {
+ Idx = Tab->BssOverlapNr;
+ BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
+ CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
+ NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
+ Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
+ }
+ return Idx;
+ }
+ else
+ {
+ return BSS_NOT_FOUND;
+ }
+ }
+ Idx = Tab->BssNr;
+ BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
+ CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
+ NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
+ Tab->BssNr++;
+ }
+ else
+ {
+ BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
+ CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
+ NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
+ }
+
+ return Idx;
+}
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+VOID TriEventInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i;
+
+ for (i = 0;i < MAX_TRIGGER_EVENT;i++)
+ pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
+
+ pAd->CommonCfg.TriggerEventTab.EventANo = 0;
+ pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
+}
+
+ULONG TriEventTableSetEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT TRIGGER_EVENT_TAB *Tab,
+ IN PUCHAR pBssid,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN UCHAR HtCapabilityLen,
+ IN UCHAR RegClass,
+ IN UCHAR ChannelNo)
+{
+ // Event A
+ if (HtCapabilityLen == 0)
+ {
+ if (Tab->EventANo < MAX_TRIGGER_EVENT)
+ {
+ RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
+ Tab->EventA[Tab->EventANo].bValid = TRUE;
+ Tab->EventA[Tab->EventANo].Channel = ChannelNo;
+ Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
+ if (RegClass != 0)
+ {
+ // Beacon has Regulatory class IE. So use beacon's
+ Tab->EventA[Tab->EventANo].RegClass = RegClass;
+ }
+ else
+ {
+ // Use Station's Regulatory class instead.
+ if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
+ {
+ if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
+ {
+ Tab->EventA[Tab->EventANo].RegClass = 32;
+ }
+ else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
+ Tab->EventA[Tab->EventANo].RegClass = 33;
+ }
+ else
+ Tab->EventA[Tab->EventANo].RegClass = ??;
+
+ }
+
+ Tab->EventANo ++;
+ }
+ }
+ else if (pHtCapability->HtCapInfo.Intolerant40)
+ {
+ Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
+ }
+
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Trigger Event table Maintainence called once every second.
+
+ Arguments:
+ // IRQL = DISPATCH_LEVEL
+ ========================================================================
+*/
+VOID TriEventCounterMaintenance(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i;
+ BOOLEAN bNotify = FALSE;
+ for (i = 0;i < MAX_TRIGGER_EVENT;i++)
+ {
+ if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
+ {
+ pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
+ if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
+ {
+ pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
+ pAd->CommonCfg.TriggerEventTab.EventANo --;
+ // Need to send 20/40 Coexistence Notify frame if has status change.
+ bNotify = TRUE;
+ }
+ }
+ }
+ if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
+ {
+ pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
+ if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
+ bNotify = TRUE;
+ }
+
+ if (bNotify == TRUE)
+ Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
+}
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+// IRQL = DISPATCH_LEVEL
+VOID BssTableSsidSort(
+ IN PRTMP_ADAPTER pAd,
+ OUT BSS_TABLE *OutTab,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen)
+{
+ INT i;
+ BssTableInit(OutTab);
+
+ for (i = 0; i < pAd->ScanTab.BssNr; i++)
+ {
+ BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
+ BOOLEAN bIsHiddenApIncluded = FALSE;
+
+ if (((pAd->CommonCfg.bIEEE80211H == 1) &&
+ (pAd->MlmeAux.Channel > 14) &&
+ RadarChannelCheck(pAd, pInBss->Channel))
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+ || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
+#endif // CARRIER_DETECTION_SUPPORT //
+ )
+ {
+ if (pInBss->Hidden)
+ bIsHiddenApIncluded = TRUE;
+ }
+
+ if ((pInBss->BssType == pAd->StaCfg.BssType) &&
+ (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
+ {
+ BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
+
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
+ if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
+ (pInBss->bHasCountryIE == FALSE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
+ continue;
+ }
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+#ifdef DOT11_N_SUPPORT
+ // 2.4G/5G N only mode
+ if ((pInBss->HtCapabilityLen == 0) &&
+ ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
+ continue;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // New for WPA2
+ // Check the Authmode first
+ if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+ {
+ // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
+ if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
+ // None matched
+ continue;
+
+ // Check cipher suite, AP must have more secured cipher than station setting
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ // If it's not mixed mode, we should only let BSS pass with the same encryption
+ if (pInBss->WPA.bMixMode == FALSE)
+ if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
+ continue;
+
+ // check group cipher
+ if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
+ continue;
+
+ // check pairwise cipher, skip if none matched
+ // If profile set to AES, let it pass without question.
+ // If profile set to TKIP, we must find one mateched
+ if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
+ continue;
+ }
+ else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ // If it's not mixed mode, we should only let BSS pass with the same encryption
+ if (pInBss->WPA2.bMixMode == FALSE)
+ if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
+ continue;
+
+ // check group cipher
+ if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
+ continue;
+
+ // check pairwise cipher, skip if none matched
+ // If profile set to AES, let it pass without question.
+ // If profile set to TKIP, we must find one mateched
+ if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
+ continue;
+ }
+ }
+ // Bss Type matched, SSID matched.
+ // We will check wepstatus for qualification Bss
+ else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
+ //
+ // For the SESv2 case, we will not qualify WepStatus.
+ //
+ if (!pInBss->bSES)
+ continue;
+ }
+
+ // Since the AP is using hidden SSID, and we are trying to connect to ANY
+ // It definitely will fail. So, skip it.
+ // CCX also require not even try to connect it!!
+ if (SsidLen == 0)
+ continue;
+
+#ifdef DOT11_N_SUPPORT
+ // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
+ // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
+ if ((pInBss->CentralChannel != pInBss->Channel) &&
+ (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
+ {
+ if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ SetCommonHT(pAd);
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+ }
+ else
+ {
+ if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
+ {
+ SetCommonHT(pAd);
+ }
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // copy matching BSS from InTab to OutTab
+ NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
+
+ OutTab->BssNr++;
+ }
+ else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
+ {
+ BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
+
+
+#ifdef DOT11_N_SUPPORT
+ // 2.4G/5G N only mode
+ if ((pInBss->HtCapabilityLen == 0) &&
+ ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
+ continue;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // New for WPA2
+ // Check the Authmode first
+ if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+ {
+ // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
+ if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
+ // None matched
+ continue;
+
+ // Check cipher suite, AP must have more secured cipher than station setting
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ // If it's not mixed mode, we should only let BSS pass with the same encryption
+ if (pInBss->WPA.bMixMode == FALSE)
+ if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
+ continue;
+
+ // check group cipher
+ if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
+ continue;
+
+ // check pairwise cipher, skip if none matched
+ // If profile set to AES, let it pass without question.
+ // If profile set to TKIP, we must find one mateched
+ if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
+ continue;
+ }
+ else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ // If it's not mixed mode, we should only let BSS pass with the same encryption
+ if (pInBss->WPA2.bMixMode == FALSE)
+ if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
+ continue;
+
+ // check group cipher
+ if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
+ continue;
+
+ // check pairwise cipher, skip if none matched
+ // If profile set to AES, let it pass without question.
+ // If profile set to TKIP, we must find one mateched
+ if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
+ (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
+ continue;
+ }
+ }
+ // Bss Type matched, SSID matched.
+ // We will check wepstatus for qualification Bss
+ else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
+ continue;
+
+#ifdef DOT11_N_SUPPORT
+ // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
+ // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
+ if ((pInBss->CentralChannel != pInBss->Channel) &&
+ (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
+ {
+ if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ SetCommonHT(pAd);
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // copy matching BSS from InTab to OutTab
+ NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
+
+ OutTab->BssNr++;
+ }
+
+ if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
+ break;
+ }
+
+ BssTableSortByRssi(OutTab);
+}
+
+
+// IRQL = DISPATCH_LEVEL
+VOID BssTableSortByRssi(
+ IN OUT BSS_TABLE *OutTab)
+{
+ INT i, j;
+ BSS_ENTRY TmpBss;
+
+ for (i = 0; i < OutTab->BssNr - 1; i++)
+ {
+ for (j = i+1; j < OutTab->BssNr; j++)
+ {
+ if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
+ {
+ NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
+ NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
+ NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
+ }
+ }
+ }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+VOID BssCipherParse(
+ IN OUT PBSS_ENTRY pBss)
+{
+ PEID_STRUCT pEid;
+ PUCHAR pTmp;
+ PRSN_IE_HEADER_STRUCT pRsnHeader;
+ PCIPHER_SUITE_STRUCT pCipher;
+ PAKM_SUITE_STRUCT pAKM;
+ USHORT Count;
+ INT Length;
+ NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
+
+ //
+ // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
+ //
+ if (pBss->Privacy)
+ {
+ pBss->WepStatus = Ndis802_11WEPEnabled;
+ }
+ else
+ {
+ pBss->WepStatus = Ndis802_11WEPDisabled;
+ }
+ // Set default to disable & open authentication before parsing variable IE
+ pBss->AuthMode = Ndis802_11AuthModeOpen;
+ pBss->AuthModeAux = Ndis802_11AuthModeOpen;
+
+ // Init WPA setting
+ pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
+ pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
+ pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
+ pBss->WPA.RsnCapability = 0;
+ pBss->WPA.bMixMode = FALSE;
+
+ // Init WPA2 setting
+ pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
+ pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
+ pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
+ pBss->WPA2.RsnCapability = 0;
+ pBss->WPA2.bMixMode = FALSE;
+
+
+ Length = (INT) pBss->VarIELen;
+
+ while (Length > 0)
+ {
+ // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
+ pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
+ pEid = (PEID_STRUCT) pTmp;
+ switch (pEid->Eid)
+ {
+ case IE_WPA:
+ //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
+ if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
+ {
+ pTmp += 11;
+ switch (*pTmp)
+ {
+ case 1:
+ case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+ pBss->WepStatus = Ndis802_11Encryption1Enabled;
+ pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
+ pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 2:
+ pBss->WepStatus = Ndis802_11Encryption2Enabled;
+ pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
+ pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 4:
+ pBss->WepStatus = Ndis802_11Encryption3Enabled;
+ pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
+ pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+ break;
+ default:
+ break;
+ }
+
+ // if Cisco IE_WPA, break
+ break;
+ }
+ else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
+ {
+ pBss->bSES = TRUE;
+ break;
+ }
+ else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
+ {
+ // if unsupported vendor specific IE
+ break;
+ }
+ // Skip OUI, version, and multicast suite
+ // This part should be improved in the future when AP supported multiple cipher suite.
+ // For now, it's OK since almost all APs have fixed cipher suite supported.
+ // pTmp = (PUCHAR) pEid->Octet;
+ pTmp += 11;
+
+ // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
+ // Value Meaning
+ // 0 None
+ // 1 WEP-40
+ // 2 Tkip
+ // 3 WRAP
+ // 4 AES
+ // 5 WEP-104
+ // Parse group cipher
+ switch (*pTmp)
+ {
+ case 1:
+ case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+ pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 2:
+ pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ // number of unicast suite
+ pTmp += 1;
+
+ // skip all unicast cipher suites
+ //Count = *(PUSHORT) pTmp;
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ // Parsing all unicast cipher suite
+ while (Count > 0)
+ {
+ // Skip OUI
+ pTmp += 3;
+ TmpCipher = Ndis802_11WEPDisabled;
+ switch (*pTmp)
+ {
+ case 1:
+ case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+ TmpCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 2:
+ TmpCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ TmpCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ if (TmpCipher > pBss->WPA.PairCipher)
+ {
+ // Move the lower cipher suite to PairCipherAux
+ pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
+ pBss->WPA.PairCipher = TmpCipher;
+ }
+ else
+ {
+ pBss->WPA.PairCipherAux = TmpCipher;
+ }
+ pTmp++;
+ Count--;
+ }
+
+ // 4. get AKM suite counts
+ //Count = *(PUSHORT) pTmp;
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+ pTmp += 3;
+
+ switch (*pTmp)
+ {
+ case 1:
+ // Set AP support WPA mode
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPA;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPA;
+ break;
+ case 2:
+ // Set AP support WPA mode
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
+ break;
+ default:
+ break;
+ }
+ pTmp += 1;
+
+ // Fixed for WPA-None
+ if (pBss->BssType == BSS_ADHOC)
+ {
+ pBss->AuthMode = Ndis802_11AuthModeWPANone;
+ pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
+ pBss->WepStatus = pBss->WPA.GroupCipher;
+ // Patched bugs for old driver
+ if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
+ pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
+ }
+ else
+ pBss->WepStatus = pBss->WPA.PairCipher;
+
+ // Check the Pair & Group, if different, turn on mixed mode flag
+ if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
+ pBss->WPA.bMixMode = TRUE;
+
+ break;
+
+ case IE_RSN:
+ pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
+
+ // 0. Version must be 1
+ if (le2cpu16(pRsnHeader->Version) != 1)
+ break;
+ pTmp += sizeof(RSN_IE_HEADER_STRUCT);
+
+ // 1. Check group cipher
+ pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+ if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
+ break;
+
+ // Parse group cipher
+ switch (pCipher->Type)
+ {
+ case 1:
+ case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+ pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 2:
+ pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ // set to correct offset for next parsing
+ pTmp += sizeof(CIPHER_SUITE_STRUCT);
+
+ // 2. Get pairwise cipher counts
+ //Count = *(PUSHORT) pTmp;
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ // 3. Get pairwise cipher
+ // Parsing all unicast cipher suite
+ while (Count > 0)
+ {
+ // Skip OUI
+ pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
+ TmpCipher = Ndis802_11WEPDisabled;
+ switch (pCipher->Type)
+ {
+ case 1:
+ case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
+ TmpCipher = Ndis802_11Encryption1Enabled;
+ break;
+ case 2:
+ TmpCipher = Ndis802_11Encryption2Enabled;
+ break;
+ case 4:
+ TmpCipher = Ndis802_11Encryption3Enabled;
+ break;
+ default:
+ break;
+ }
+ if (TmpCipher > pBss->WPA2.PairCipher)
+ {
+ // Move the lower cipher suite to PairCipherAux
+ pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
+ pBss->WPA2.PairCipher = TmpCipher;
+ }
+ else
+ {
+ pBss->WPA2.PairCipherAux = TmpCipher;
+ }
+ pTmp += sizeof(CIPHER_SUITE_STRUCT);
+ Count--;
+ }
+
+ // 4. get AKM suite counts
+ //Count = *(PUSHORT) pTmp;
+ Count = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ // 5. Get AKM ciphers
+ pAKM = (PAKM_SUITE_STRUCT) pTmp;
+ if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
+ break;
+
+ switch (pAKM->Type)
+ {
+ case 1:
+ // Set AP support WPA mode
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPA2;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
+ break;
+ case 2:
+ // Set AP support WPA mode
+ if (pBss->AuthMode == Ndis802_11AuthModeOpen)
+ pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
+ else
+ pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
+ break;
+ default:
+ break;
+ }
+ pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
+
+ // Fixed for WPA-None
+ if (pBss->BssType == BSS_ADHOC)
+ {
+ pBss->AuthMode = Ndis802_11AuthModeWPANone;
+ pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
+ pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
+ pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
+ pBss->WepStatus = pBss->WPA.GroupCipher;
+ // Patched bugs for old driver
+ if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
+ pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
+ }
+ pBss->WepStatus = pBss->WPA2.PairCipher;
+
+ // 6. Get RSN capability
+ //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
+ pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
+ pTmp += sizeof(USHORT);
+
+ // Check the Pair & Group, if different, turn on mixed mode flag
+ if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
+ pBss->WPA2.bMixMode = TRUE;
+
+ break;
+ default:
+ break;
+ }
+ Length -= (pEid->Len + 2);
+ }
+}
+
+// ===========================================================================================
+// mac_table.c
+// ===========================================================================================
+
+/*! \brief generates a random mac address value for IBSS BSSID
+ * \param Addr the bssid location
+ * \return none
+ * \pre
+ * \post
+ */
+VOID MacAddrRandomBssid(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pAddr)
+{
+ INT i;
+
+ for (i = 0; i < MAC_ADDR_LEN; i++)
+ {
+ pAddr[i] = RandomByte(pAd);
+ }
+
+ pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
+}
+
+/*! \brief init the management mac frame header
+ * \param p_hdr mac header
+ * \param subtype subtype of the frame
+ * \param p_ds destination address, don't care if it is a broadcast address
+ * \return none
+ * \pre the station has the following information in the pAd->StaCfg
+ * - bssid
+ * - station address
+ * \post
+ * \note this function initializes the following field
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID MgtMacHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN UCHAR SubType,
+ IN UCHAR ToDs,
+ IN PUCHAR pDA,
+ IN PUCHAR pBssid)
+{
+ NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
+
+ pHdr80211->FC.Type = BTYPE_MGMT;
+ pHdr80211->FC.SubType = SubType;
+ pHdr80211->FC.ToDs = ToDs;
+ COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
+#endif // CONFIG_STA_SUPPORT //
+ COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
+}
+
+// ===========================================================================================
+// mem_mgmt.c
+// ===========================================================================================
+
+/*!***************************************************************************
+ * This routine build an outgoing frame, and fill all information specified
+ * in argument list to the frame body. The actual frame size is the summation
+ * of all arguments.
+ * input params:
+ * Buffer - pointer to a pre-allocated memory segment
+ * args - a list of <int arg_size, arg> pairs.
+ * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
+ * function will FAIL!!!
+ * return:
+ * Size of the buffer
+ * usage:
+ * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ****************************************************************************/
+ULONG MakeOutgoingFrame(
+ OUT CHAR *Buffer,
+ OUT ULONG *FrameLen, ...)
+{
+ CHAR *p;
+ int leng;
+ ULONG TotLeng;
+ va_list Args;
+
+ // calculates the total length
+ TotLeng = 0;
+ va_start(Args, FrameLen);
+ do
+ {
+ leng = va_arg(Args, int);
+ if (leng == END_OF_ARGS)
+ {
+ break;
+ }
+ p = va_arg(Args, PVOID);
+ NdisMoveMemory(&Buffer[TotLeng], p, leng);
+ TotLeng = TotLeng + leng;
+ } while(TRUE);
+
+ va_end(Args); /* clean up */
+ *FrameLen = TotLeng;
+ return TotLeng;
+}
+
+// ===========================================================================================
+// mlme_queue.c
+// ===========================================================================================
+
+/*! \brief Initialize The MLME Queue, used by MLME Functions
+ * \param *Queue The MLME Queue
+ * \return Always Return NDIS_STATE_SUCCESS in this implementation
+ * \pre
+ * \post
+ * \note Because this is done only once (at the init stage), no need to be locked
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+NDIS_STATUS MlmeQueueInit(
+ IN MLME_QUEUE *Queue)
+{
+ INT i;
+
+ NdisAllocateSpinLock(&Queue->Lock);
+
+ Queue->Num = 0;
+ Queue->Head = 0;
+ Queue->Tail = 0;
+
+ for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
+ {
+ Queue->Entry[i].Occupied = FALSE;
+ Queue->Entry[i].MsgLen = 0;
+ NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
+ }
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
+ * \param *Queue The MLME Queue
+ * \param Machine The State Machine Id
+ * \param MsgType The Message Type
+ * \param MsgLen The Message length
+ * \param *Msg The message pointer
+ * \return TRUE if enqueue is successful, FALSE if the queue is full
+ * \pre
+ * \post
+ * \note The message has to be initialized
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeEnqueue(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Machine,
+ IN ULONG MsgType,
+ IN ULONG MsgLen,
+ IN VOID *Msg)
+{
+ INT Tail;
+ MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return FALSE;
+
+ // First check the size, it MUST not exceed the mlme queue size
+ if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+ {
+ DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
+ return FALSE;
+ }
+
+ if (MlmeQueueFull(Queue))
+ {
+ return FALSE;
+ }
+
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Tail = Queue->Tail;
+ Queue->Tail++;
+ Queue->Num++;
+ if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
+ {
+ Queue->Tail = 0;
+ }
+
+ Queue->Entry[Tail].Wcid = RESERVED_WCID;
+ Queue->Entry[Tail].Occupied = TRUE;
+ Queue->Entry[Tail].Machine = Machine;
+ Queue->Entry[Tail].MsgType = MsgType;
+ Queue->Entry[Tail].MsgLen = MsgLen;
+
+ if (Msg != NULL)
+ {
+ NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
+ }
+
+ NdisReleaseSpinLock(&(Queue->Lock));
+ return TRUE;
+}
+
+/*! \brief This function is used when Recv gets a MLME message
+ * \param *Queue The MLME Queue
+ * \param TimeStampHigh The upper 32 bit of timestamp
+ * \param TimeStampLow The lower 32 bit of timestamp
+ * \param Rssi The receiving RSSI strength
+ * \param MsgLen The length of the message
+ * \param *Msg The message pointer
+ * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeEnqueueForRecv(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN ULONG TimeStampHigh,
+ IN ULONG TimeStampLow,
+ IN UCHAR Rssi0,
+ IN UCHAR Rssi1,
+ IN UCHAR Rssi2,
+ IN ULONG MsgLen,
+ IN VOID *Msg,
+ IN UCHAR Signal)
+{
+ INT Tail, Machine;
+ PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
+ INT MsgType;
+ MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode */
+ if(ATE_ON(pAd))
+ return FALSE;
+#endif // RALINK_ATE //
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ {
+ DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
+ return FALSE;
+ }
+
+ // First check the size, it MUST not exceed the mlme queue size
+ if (MsgLen > MGMT_DMA_BUFFER_SIZE)
+ {
+ DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
+ return FALSE;
+ }
+
+ if (MlmeQueueFull(Queue))
+ {
+ return FALSE;
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
+ {
+ DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
+ return FALSE;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // OK, we got all the informations, it is time to put things into queue
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Tail = Queue->Tail;
+ Queue->Tail++;
+ Queue->Num++;
+ if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
+ {
+ Queue->Tail = 0;
+ }
+ Queue->Entry[Tail].Occupied = TRUE;
+ Queue->Entry[Tail].Machine = Machine;
+ Queue->Entry[Tail].MsgType = MsgType;
+ Queue->Entry[Tail].MsgLen = MsgLen;
+ Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
+ Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
+ Queue->Entry[Tail].Rssi0 = Rssi0;
+ Queue->Entry[Tail].Rssi1 = Rssi1;
+ Queue->Entry[Tail].Rssi2 = Rssi2;
+ Queue->Entry[Tail].Signal = Signal;
+ Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
+
+ Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
+
+ if (Msg != NULL)
+ {
+ NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
+ }
+
+ NdisReleaseSpinLock(&(Queue->Lock));
+
+ RT28XX_MLME_HANDLER(pAd);
+
+ return TRUE;
+}
+
+
+/*! \brief Dequeue a message from the MLME Queue
+ * \param *Queue The MLME Queue
+ * \param *Elem The message dequeued from MLME Queue
+ * \return TRUE if the Elem contains something, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeDequeue(
+ IN MLME_QUEUE *Queue,
+ OUT MLME_QUEUE_ELEM **Elem)
+{
+ NdisAcquireSpinLock(&(Queue->Lock));
+ *Elem = &(Queue->Entry[Queue->Head]);
+ Queue->Num--;
+ Queue->Head++;
+ if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
+ {
+ Queue->Head = 0;
+ }
+ NdisReleaseSpinLock(&(Queue->Lock));
+ return TRUE;
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID MlmeRestartStateMachine(
+ IN PRTMP_ADAPTER pAd)
+{
+#ifdef RT2860
+ MLME_QUEUE_ELEM *Elem = NULL;
+#endif // RT2860 //
+#ifdef CONFIG_STA_SUPPORT
+ BOOLEAN Cancelled;
+#endif // CONFIG_STA_SUPPORT //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
+
+#ifdef RT2860
+ NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+ if(pAd->Mlme.bRunning)
+ {
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+ return;
+ }
+ else
+ {
+ pAd->Mlme.bRunning = TRUE;
+ }
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+
+ // Remove all Mlme queues elements
+ while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
+ {
+ //From message type, determine which state machine I should drive
+ if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
+ {
+ // free MLME element
+ Elem->Occupied = FALSE;
+ Elem->MsgLen = 0;
+
+ }
+ else {
+ DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
+ }
+ }
+#endif // RT2860 //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef QOS_DLS_SUPPORT
+ UCHAR i;
+#endif // QOS_DLS_SUPPORT //
+ // Cancel all timer events
+ // Be careful to cancel new added timer
+ RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
+
+#ifdef QOS_DLS_SUPPORT
+ for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
+ }
+#endif // QOS_DLS_SUPPORT //
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // Change back to original channel in case of doing scan
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+ // Resume MSDU which is turned off durning scan
+ RTMPResumeMsduTransmission(pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Set all state machines back IDLE
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
+ pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
+ pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
+#ifdef QOS_DLS_SUPPORT
+ pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
+#endif // QOS_DLS_SUPPORT //
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RT2860
+ // Remove running state
+ NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
+ pAd->Mlme.bRunning = FALSE;
+ NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
+#endif // RT2860 //
+}
+
+/*! \brief test if the MLME Queue is empty
+ * \param *Queue The MLME Queue
+ * \return TRUE if the Queue is empty, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeQueueEmpty(
+ IN MLME_QUEUE *Queue)
+{
+ BOOLEAN Ans;
+
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Ans = (Queue->Num == 0);
+ NdisReleaseSpinLock(&(Queue->Lock));
+
+ return Ans;
+}
+
+/*! \brief test if the MLME Queue is full
+ * \param *Queue The MLME Queue
+ * \return TRUE if the Queue is empty, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ */
+BOOLEAN MlmeQueueFull(
+ IN MLME_QUEUE *Queue)
+{
+ BOOLEAN Ans;
+
+ NdisAcquireSpinLock(&(Queue->Lock));
+ Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
+ NdisReleaseSpinLock(&(Queue->Lock));
+
+ return Ans;
+}
+
+/*! \brief The destructor of MLME Queue
+ * \param
+ * \return
+ * \pre
+ * \post
+ * \note Clear Mlme Queue, Set Queue->Num to Zero.
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID MlmeQueueDestroy(
+ IN MLME_QUEUE *pQueue)
+{
+ NdisAcquireSpinLock(&(pQueue->Lock));
+ pQueue->Num = 0;
+ pQueue->Head = 0;
+ pQueue->Tail = 0;
+ NdisReleaseSpinLock(&(pQueue->Lock));
+ NdisFreeSpinLock(&(pQueue->Lock));
+}
+
+/*! \brief To substitute the message type if the message is coming from external
+ * \param pFrame The frame received
+ * \param *Machine The state machine
+ * \param *MsgType the message type for the state machine
+ * \return TRUE if the substitution is successful, FALSE otherwise
+ * \pre
+ * \post
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+#ifdef CONFIG_STA_SUPPORT
+BOOLEAN MsgTypeSubst(
+ IN PRTMP_ADAPTER pAd,
+ IN PFRAME_802_11 pFrame,
+ OUT INT *Machine,
+ OUT INT *MsgType)
+{
+ USHORT Seq;
+ UCHAR EAPType;
+ PUCHAR pData;
+
+ // Pointer to start of data frames including SNAP header
+ pData = (PUCHAR) pFrame + LENGTH_802_11;
+
+ // The only data type will pass to this function is EAPOL frame
+ if (pFrame->Hdr.FC.Type == BTYPE_DATA)
+ {
+ if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
+ {
+ // Cisco Aironet SNAP header
+ *Machine = AIRONET_STATE_MACHINE;
+ *MsgType = MT2_AIRONET_MSG;
+ return (TRUE);
+ }
+#ifdef LEAP_SUPPORT
+ if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
+ {
+ // LEAP frames
+ *Machine = LEAP_STATE_MACHINE;
+ EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
+ return (LeapMsgTypeSubst(EAPType, MsgType));
+ }
+ else
+#endif // LEAP_SUPPORT //
+ {
+ *Machine = WPA_PSK_STATE_MACHINE;
+ EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
+ return(WpaMsgTypeSubst(EAPType, MsgType));
+ }
+ }
+
+ switch (pFrame->Hdr.FC.SubType)
+ {
+ case SUBTYPE_ASSOC_REQ:
+ *Machine = ASSOC_STATE_MACHINE;
+ *MsgType = MT2_PEER_ASSOC_REQ;
+ break;
+ case SUBTYPE_ASSOC_RSP:
+ *Machine = ASSOC_STATE_MACHINE;
+ *MsgType = MT2_PEER_ASSOC_RSP;
+ break;
+ case SUBTYPE_REASSOC_REQ:
+ *Machine = ASSOC_STATE_MACHINE;
+ *MsgType = MT2_PEER_REASSOC_REQ;
+ break;
+ case SUBTYPE_REASSOC_RSP:
+ *Machine = ASSOC_STATE_MACHINE;
+ *MsgType = MT2_PEER_REASSOC_RSP;
+ break;
+ case SUBTYPE_PROBE_REQ:
+ *Machine = SYNC_STATE_MACHINE;
+ *MsgType = MT2_PEER_PROBE_REQ;
+ break;
+ case SUBTYPE_PROBE_RSP:
+ *Machine = SYNC_STATE_MACHINE;
+ *MsgType = MT2_PEER_PROBE_RSP;
+ break;
+ case SUBTYPE_BEACON:
+ *Machine = SYNC_STATE_MACHINE;
+ *MsgType = MT2_PEER_BEACON;
+ break;
+ case SUBTYPE_ATIM:
+ *Machine = SYNC_STATE_MACHINE;
+ *MsgType = MT2_PEER_ATIM;
+ break;
+ case SUBTYPE_DISASSOC:
+ *Machine = ASSOC_STATE_MACHINE;
+ *MsgType = MT2_PEER_DISASSOC_REQ;
+ break;
+ case SUBTYPE_AUTH:
+ // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
+ NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
+ if (Seq == 1 || Seq == 3)
+ {
+ *Machine = AUTH_RSP_STATE_MACHINE;
+ *MsgType = MT2_PEER_AUTH_ODD;
+ }
+ else if (Seq == 2 || Seq == 4)
+ {
+ *Machine = AUTH_STATE_MACHINE;
+ *MsgType = MT2_PEER_AUTH_EVEN;
+ }
+ else
+ {
+ return FALSE;
+ }
+ break;
+ case SUBTYPE_DEAUTH:
+ *Machine = AUTH_RSP_STATE_MACHINE;
+ *MsgType = MT2_PEER_DEAUTH;
+ break;
+ case SUBTYPE_ACTION:
+ *Machine = ACTION_STATE_MACHINE;
+ // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
+ if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
+ {
+ *MsgType = MT2_ACT_INVALID;
+ }
+ else
+ {
+ *MsgType = (pFrame->Octet[0]&0x7F);
+ }
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+}
+#endif // CONFIG_STA_SUPPORT //
+
+// ===========================================================================================
+// state_machine.c
+// ===========================================================================================
+
+/*! \brief Initialize the state machine.
+ * \param *S pointer to the state machine
+ * \param Trans State machine transition function
+ * \param StNr number of states
+ * \param MsgNr number of messages
+ * \param DefFunc default function, when there is invalid state/message combination
+ * \param InitState initial state of the state machine
+ * \param Base StateMachine base, internal use only
+ * \pre p_sm should be a legal pointer
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID StateMachineInit(
+ IN STATE_MACHINE *S,
+ IN STATE_MACHINE_FUNC Trans[],
+ IN ULONG StNr,
+ IN ULONG MsgNr,
+ IN STATE_MACHINE_FUNC DefFunc,
+ IN ULONG InitState,
+ IN ULONG Base)
+{
+ ULONG i, j;
+
+ // set number of states and messages
+ S->NrState = StNr;
+ S->NrMsg = MsgNr;
+ S->Base = Base;
+
+ S->TransFunc = Trans;
+
+ // init all state transition to default function
+ for (i = 0; i < StNr; i++)
+ {
+ for (j = 0; j < MsgNr; j++)
+ {
+ S->TransFunc[i * MsgNr + j] = DefFunc;
+ }
+ }
+
+ // set the starting state
+ S->CurrState = InitState;
+}
+
+/*! \brief This function fills in the function pointer into the cell in the state machine
+ * \param *S pointer to the state machine
+ * \param St state
+ * \param Msg incoming message
+ * \param f the function to be executed when (state, message) combination occurs at the state machine
+ * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
+ * \post
+
+ IRQL = PASSIVE_LEVEL
+
+ */
+VOID StateMachineSetAction(
+ IN STATE_MACHINE *S,
+ IN ULONG St,
+ IN ULONG Msg,
+ IN STATE_MACHINE_FUNC Func)
+{
+ ULONG MsgIdx;
+
+ MsgIdx = Msg - S->Base;
+
+ if (St < S->NrState && MsgIdx < S->NrMsg)
+ {
+ // boundary checking before setting the action
+ S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
+ }
+}
+
+/*! \brief This function does the state transition
+ * \param *Adapter the NIC adapter pointer
+ * \param *S the state machine
+ * \param *Elem the message to be executed
+ * \return None
+
+ IRQL = DISPATCH_LEVEL
+
+ */
+VOID StateMachinePerformAction(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
+}
+
+/*
+ ==========================================================================
+ Description:
+ The drop function, when machine executes this, the message is simply
+ ignored. This function does nothing, the message is freed in
+ StateMachinePerformAction()
+ ==========================================================================
+ */
+VOID Drop(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+}
+
+// ===========================================================================================
+// lfsr.c
+// ===========================================================================================
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+VOID LfsrInit(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Seed)
+{
+ if (Seed == 0)
+ pAd->Mlme.ShiftReg = 1;
+ else
+ pAd->Mlme.ShiftReg = Seed;
+}
+
+/*
+ ==========================================================================
+ Description:
+ ==========================================================================
+ */
+UCHAR RandomByte(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG i;
+ UCHAR R, Result;
+
+ R = 0;
+
+ if (pAd->Mlme.ShiftReg == 0)
+ NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
+
+ for (i = 0; i < 8; i++)
+ {
+ if (pAd->Mlme.ShiftReg & 0x00000001)
+ {
+ pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
+ Result = 1;
+ }
+ else
+ {
+ pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
+ Result = 0;
+ }
+ R = (R << 1) | Result;
+ }
+
+ return R;
+}
+
+VOID AsicUpdateAutoFallBackTable(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pRateTable)
+{
+ UCHAR i;
+ HT_FBK_CFG0_STRUC HtCfg0;
+ HT_FBK_CFG1_STRUC HtCfg1;
+ LG_FBK_CFG0_STRUC LgCfg0;
+ LG_FBK_CFG1_STRUC LgCfg1;
+ PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
+
+ // set to initial value
+ HtCfg0.word = 0x65432100;
+ HtCfg1.word = 0xedcba988;
+ LgCfg0.word = 0xedcba988;
+ LgCfg1.word = 0x00002100;
+
+ pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
+ for (i = 1; i < *((PUCHAR) pRateTable); i++)
+ {
+ pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
+ switch (pCurrTxRate->Mode)
+ {
+ case 0: //CCK
+ break;
+ case 1: //OFDM
+ {
+ switch(pCurrTxRate->CurrMCS)
+ {
+ case 0:
+ LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ case 1:
+ LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ case 2:
+ LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ case 3:
+ LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ case 4:
+ LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ case 5:
+ LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ case 6:
+ LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ case 7:
+ LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
+ break;
+ }
+ }
+ break;
+#ifdef DOT11_N_SUPPORT
+ case 2: //HT-MIX
+ case 3: //HT-GF
+ {
+ if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
+ {
+ switch(pCurrTxRate->CurrMCS)
+ {
+ case 0:
+ HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
+ break;
+ case 1:
+ HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
+ break;
+ case 2:
+ HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
+ break;
+ case 3:
+ HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
+ break;
+ case 4:
+ HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
+ break;
+ case 5:
+ HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
+ break;
+ case 6:
+ HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
+ break;
+ case 7:
+ HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
+ break;
+ case 8:
+ HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
+ break;
+ case 9:
+ HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
+ break;
+ case 10:
+ HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
+ break;
+ case 11:
+ HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
+ break;
+ case 12:
+ HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
+ break;
+ case 13:
+ HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
+ break;
+ case 14:
+ HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
+ break;
+ case 15:
+ HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
+ }
+ }
+ }
+ break;
+#endif // DOT11_N_SUPPORT //
+ }
+
+ pNextTxRate = pCurrTxRate;
+ }
+
+ RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
+ RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
+ RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
+ RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set MAC register value according operation mode.
+ OperationMode AND bNonGFExist are for MM and GF Proteciton.
+ If MM or GF mask is not set, those passing argument doesn't not take effect.
+
+ Operation mode meaning:
+ = 0 : Pure HT, no preotection.
+ = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
+ = 0x10: No Transmission in 40M is protected.
+ = 0x11: Transmission in both 40M and 20M shall be protected
+ if (bNonGFExist)
+ we should choose not to use GF. But still set correct ASIC registers.
+ ========================================================================
+*/
+VOID AsicUpdateProtect(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT OperationMode,
+ IN UCHAR SetMask,
+ IN BOOLEAN bDisableBGProtect,
+ IN BOOLEAN bNonGFExist)
+{
+ PROT_CFG_STRUC ProtCfg, ProtCfg4;
+ UINT32 Protect[6];
+ USHORT offset;
+ UCHAR i;
+ UINT32 MacReg = 0;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+#ifdef DOT11_N_SUPPORT
+ if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
+ {
+ return;
+ }
+
+ if (pAd->BATable.numAsOriginator)
+ {
+ //
+ // enable the RTS/CTS to avoid channel collision
+ //
+ SetMask = ALLN_SETPROTECT;
+ OperationMode = 8;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // Config ASIC RTS threshold register
+ RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
+ MacReg &= 0xFF0000FF;
+#if 0
+ MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
+#else
+ // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
+ if ((
+#ifdef DOT11_N_SUPPORT
+ (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
+#endif // DOT11_N_SUPPORT //
+ (pAd->CommonCfg.bAggregationCapable == TRUE))
+ && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
+ {
+ MacReg |= (0x1000 << 8);
+ }
+ else
+ {
+ MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
+ }
+#endif
+
+ RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
+
+ // Initial common protection settings
+ RTMPZeroMemory(Protect, sizeof(Protect));
+ ProtCfg4.word = 0;
+ ProtCfg.word = 0;
+ ProtCfg.field.TxopAllowGF40 = 1;
+ ProtCfg.field.TxopAllowGF20 = 1;
+ ProtCfg.field.TxopAllowMM40 = 1;
+ ProtCfg.field.TxopAllowMM20 = 1;
+ ProtCfg.field.TxopAllowOfdm = 1;
+ ProtCfg.field.TxopAllowCck = 1;
+ ProtCfg.field.RTSThEn = 1;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+
+ // update PHY mode and rate
+ if (pAd->CommonCfg.Channel > 14)
+ ProtCfg.field.ProtectRate = 0x4000;
+ ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
+
+ // Handle legacy(B/G) protection
+ if (bDisableBGProtect)
+ {
+ //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
+ ProtCfg.field.ProtectCtrl = 0;
+ Protect[0] = ProtCfg.word;
+ Protect[1] = ProtCfg.word;
+ }
+ else
+ {
+ //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
+ ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
+ Protect[0] = ProtCfg.word;
+ ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
+ Protect[1] = ProtCfg.word;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ // Decide HT frame protection.
+ if ((SetMask & ALLN_SETPROTECT) != 0)
+ {
+ switch(OperationMode)
+ {
+ case 0x0:
+ // NO PROTECT
+ // 1.All STAs in the BSS are 20/40 MHz HT
+ // 2. in ai 20/40MHz BSS
+ // 3. all STAs are 20MHz in a 20MHz BSS
+ // Pure HT. no protection.
+
+ // MM20_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 010111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
+ Protect[2] = 0x01744004;
+
+ // MM40_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 111111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
+ Protect[3] = 0x03f44084;
+
+ // CF20_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 010111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
+ Protect[4] = 0x01744004;
+
+ // CF40_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 111111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
+ Protect[5] = 0x03f44084;
+
+ if (bNonGFExist)
+ {
+ // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
+ // PROT_CTRL(17:16) -- 01 (RTS/CTS)
+ Protect[4] = 0x01754004;
+ Protect[5] = 0x03f54084;
+ }
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+ break;
+
+ case 1:
+ // This is "HT non-member protection mode."
+ // If there may be non-HT STAs my BSS
+ ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
+ ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+ {
+ ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
+ ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
+ }
+ //Assign Protection method for 20&40 MHz packets
+ ProtCfg.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+ ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+ Protect[2] = ProtCfg.word;
+ Protect[3] = ProtCfg4.word;
+ Protect[4] = ProtCfg.word;
+ Protect[5] = ProtCfg4.word;
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+ break;
+
+ case 2:
+ // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
+ ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
+ ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
+
+ //Assign Protection method for 40MHz packets
+ ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+ Protect[2] = ProtCfg.word;
+ Protect[3] = ProtCfg4.word;
+ if (bNonGFExist)
+ {
+ ProtCfg.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+ }
+ Protect[4] = ProtCfg.word;
+ Protect[5] = ProtCfg4.word;
+
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+ break;
+
+ case 3:
+ // HT mixed mode. PROTECT ALL!
+ // Assign Rate
+ ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
+ ProtCfg4.word = 0x03f44084;
+ // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
+ {
+ ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
+ ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
+ }
+ //Assign Protection method for 20&40 MHz packets
+ ProtCfg.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+ ProtCfg4.field.ProtectCtrl = ASIC_RTS;
+ ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
+ Protect[2] = ProtCfg.word;
+ Protect[3] = ProtCfg4.word;
+ Protect[4] = ProtCfg.word;
+ Protect[5] = ProtCfg4.word;
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+ break;
+
+ case 8:
+ // Special on for Atheros problem n chip.
+ Protect[2] = 0x01754004;
+ Protect[3] = 0x03f54084;
+ Protect[4] = 0x01754004;
+ Protect[5] = 0x03f54084;
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
+ break;
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+ offset = CCK_PROT_CFG;
+ for (i = 0;i < 6;i++)
+ {
+ if ((SetMask & (1<< i)))
+ {
+ RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSwitchChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel,
+ IN BOOLEAN bScan)
+{
+ ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
+ CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
+ UCHAR index;
+ UINT32 Value = 0; //BbpReg, Value;
+ RTMP_RF_REGS *RFRegTable;
+
+ // Search Tx power value
+ for (index = 0; index < pAd->ChannelListNum; index++)
+ {
+ if (Channel == pAd->ChannelList[index].Channel)
+ {
+ TxPwer = pAd->ChannelList[index].Power;
+ TxPwer2 = pAd->ChannelList[index].Power2;
+ break;
+ }
+ }
+
+ if (index == MAX_NUM_OF_CHANNELS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
+ }
+
+ {
+ RFRegTable = RF2850RegTable;
+
+ switch (pAd->RfIcType)
+ {
+ case RFIC_2820:
+ case RFIC_2850:
+ case RFIC_2720:
+ case RFIC_2750:
+
+ for (index = 0; index < NUM_OF_2850_CHNL; index++)
+ {
+ if (Channel == RFRegTable[index].Channel)
+ {
+ R2 = RFRegTable[index].R2;
+ if (pAd->Antenna.field.TxPath == 1)
+ {
+ R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
+ }
+
+ if (pAd->Antenna.field.RxPath == 2)
+ {
+ R2 |= 0x40; // write 1 to off Rxpath.
+ }
+ else if (pAd->Antenna.field.RxPath == 1)
+ {
+ R2 |= 0x20040; // write 1 to off RxPath
+ }
+
+ if (Channel > 14)
+ {
+ // initialize R3, R4
+ R3 = (RFRegTable[index].R3 & 0xffffc1ff);
+ R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
+
+ // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
+ // R3
+ if ((TxPwer >= -7) && (TxPwer < 0))
+ {
+ TxPwer = (7+TxPwer);
+ TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+ R3 |= (TxPwer << 10);
+ DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
+ }
+ else
+ {
+ TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+ R3 |= (TxPwer << 10) | (1 << 9);
+ }
+
+ // R4
+ if ((TxPwer2 >= -7) && (TxPwer2 < 0))
+ {
+ TxPwer2 = (7+TxPwer2);
+ TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+ R4 |= (TxPwer2 << 7);
+ DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
+ }
+ else
+ {
+ TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+ R4 |= (TxPwer2 << 7) | (1 << 6);
+ }
+ }
+ else
+ {
+ R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
+ R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
+ }
+
+ // Based on BBP current mode before changing RF channel.
+ if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
+ {
+ R4 |=0x200000;
+ }
+
+ // Update variables
+ pAd->LatchRfRegs.Channel = Channel;
+ pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
+ pAd->LatchRfRegs.R2 = R2;
+ pAd->LatchRfRegs.R3 = R3;
+ pAd->LatchRfRegs.R4 = R4;
+
+ // Set RF value 1's set R3[bit2] = [0]
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+ RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+ RTMPusecDelay(200);
+
+ // Set RF value 2's set R3[bit2] = [1]
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+ RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+ RTMPusecDelay(200);
+
+ // Set RF value 3's set R3[bit2] = [0]
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+ RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Change BBP setting during siwtch from a->g, g->a
+ if (Channel <= 14)
+ {
+ ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue.
+ //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
+
+ // Rx High power VGA offset for LNA select
+ if (pAd->NicConfig2.field.ExternalLNAForG)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
+ }
+ else
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
+ }
+
+ // 5G band selection PIN, bit1 and bit2 are complement
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+ Value &= (~0x6);
+ Value |= (0x04);
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+ // Turn off unused PA or LNA when only 1T or 1R
+ if (pAd->Antenna.field.TxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFFFF3;
+ }
+ if (pAd->Antenna.field.RxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFF3FF;
+ }
+
+ RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+ }
+ else
+ {
+ ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);//(0x44 - GET_LNA_GAIN(pAd))); // According the Rory's suggestion to solve the middle range issue.
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
+
+ // Rx High power VGA offset for LNA select
+ if (pAd->NicConfig2.field.ExternalLNAForA)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
+ }
+ else
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
+ }
+
+ // 5G band selection PIN, bit1 and bit2 are complement
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+ Value &= (~0x6);
+ Value |= (0x02);
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+ // Turn off unused PA or LNA when only 1T or 1R
+ if (pAd->Antenna.field.TxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFFFF3;
+ }
+ if (pAd->Antenna.field.RxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFF3FF;
+ }
+
+ RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+ }
+
+ // R66 should be set according to Channel and use 20MHz when scanning
+ //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
+ if (bScan)
+ RTMPSetAGCInitValue(pAd, BW_20);
+ else
+ RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
+
+ //
+ // On 11A, We should delay and wait RF/BBP to be stable
+ // and the appropriate time should be 1000 micro seconds
+ // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
+ //
+ RTMPusecDelay(1000);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%lu, Pwr1=%lu, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
+ Channel,
+ pAd->RfIcType,
+ (R3 & 0x00003e00) >> 9,
+ (R4 & 0x000007c0) >> 6,
+ pAd->Antenna.field.TxPath,
+ pAd->LatchRfRegs.R1,
+ pAd->LatchRfRegs.R2,
+ pAd->LatchRfRegs.R3,
+ pAd->LatchRfRegs.R4));
+}
+
+/*
+ ==========================================================================
+ Description:
+ This function is required for 2421 only, and should not be used during
+ site survey. It's only required after NIC decided to stay at a channel
+ for a longer period.
+ When this function is called, it's always after AsicSwitchChannel().
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicLockChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel)
+{
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicAntennaSelect(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel)
+{
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Antenna miscellaneous setting.
+
+ Arguments:
+ pAd Pointer to our adapter
+ BandState Indicate current Band State.
+
+ Return Value:
+ None
+
+ IRQL <= DISPATCH_LEVEL
+
+ Note:
+ 1.) Frame End type control
+ only valid for G only (RF_2527 & RF_2529)
+ 0: means DPDT, set BBP R4 bit 5 to 1
+ 1: means SPDT, set BBP R4 bit 5 to 0
+
+
+ ========================================================================
+*/
+VOID AsicAntennaSetting(
+ IN PRTMP_ADAPTER pAd,
+ IN ABGBAND_STATE BandState)
+{
+}
+
+VOID AsicRfTuningExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+}
+
+/*
+ ==========================================================================
+ Description:
+ Gives CCK TX rate 2 more dB TX power.
+ This routine works only in LINK UP in INFRASTRUCTURE mode.
+
+ calculate desired Tx power in RF R3.Tx0~5, should consider -
+ 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
+ 1. TxPowerPercentage
+ 2. auto calibration based on TSSI feedback
+ 3. extra 2 db for CCK
+ 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
+
+ NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
+ it should be called AFTER MlmeDynamicTxRatSwitching()
+ ==========================================================================
+ */
+VOID AsicAdjustTxPower(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT i, j;
+ CHAR DeltaPwr = 0;
+ BOOLEAN bAutoTxAgc = FALSE;
+ UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
+ UCHAR BbpR1 = 0, BbpR49 = 0, idx;
+ PCHAR pTxAgcCompensate;
+ ULONG TxPwr[5];
+ CHAR Value;
+
+ if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+ {
+ if (pAd->CommonCfg.CentralChannel > 14)
+ {
+ TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
+ TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
+ TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
+ TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
+ TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
+ }
+ else
+ {
+ TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
+ TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
+ TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
+ TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
+ TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
+ }
+ }
+ else
+ {
+ if (pAd->CommonCfg.Channel > 14)
+ {
+ TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
+ TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
+ TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
+ TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
+ TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
+ }
+ else
+ {
+ TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
+ TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
+ TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
+ TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
+ TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
+ }
+ }
+
+ // TX power compensation for temperature variation based on TSSI. try every 4 second
+ if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
+ {
+ if (pAd->CommonCfg.Channel <= 14)
+ {
+ /* bg channel */
+ bAutoTxAgc = pAd->bAutoTxAgcG;
+ TssiRef = pAd->TssiRefG;
+ pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
+ pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
+ TxAgcStep = pAd->TxAgcStepG;
+ pTxAgcCompensate = &pAd->TxAgcCompensateG;
+ }
+ else
+ {
+ /* a channel */
+ bAutoTxAgc = pAd->bAutoTxAgcA;
+ TssiRef = pAd->TssiRefA;
+ pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
+ pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
+ TxAgcStep = pAd->TxAgcStepA;
+ pTxAgcCompensate = &pAd->TxAgcCompensateA;
+ }
+
+ if (bAutoTxAgc)
+ {
+ /* BbpR1 is unsigned char */
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
+
+ /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
+ /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
+ /* step value is defined in pAd->TxAgcStepG for tx power value */
+
+ /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
+ /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+ above value are examined in mass factory production */
+ /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
+
+ /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
+ /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
+ /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
+
+ if (BbpR49 > pTssiMinusBoundary[1])
+ {
+ // Reading is larger than the reference value
+ // check for how large we need to decrease the Tx power
+ for (idx = 1; idx < 5; idx++)
+ {
+ if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
+ break;
+ }
+ // The index is the step we should decrease, idx = 0 means there is nothing to compensate
+ *pTxAgcCompensate = -(TxAgcStep * (idx-1));
+
+ DeltaPwr += (*pTxAgcCompensate);
+ DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
+ BbpR49, TssiRef, TxAgcStep, idx-1));
+ }
+ else if (BbpR49 < pTssiPlusBoundary[1])
+ {
+ // Reading is smaller than the reference value
+ // check for how large we need to increase the Tx power
+ for (idx = 1; idx < 5; idx++)
+ {
+ if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
+ break;
+ }
+ // The index is the step we should increase, idx = 0 means there is nothing to compensate
+ *pTxAgcCompensate = TxAgcStep * (idx-1);
+ DeltaPwr += (*pTxAgcCompensate);
+ DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+ BbpR49, TssiRef, TxAgcStep, idx-1));
+ }
+ else
+ {
+ *pTxAgcCompensate = 0;
+ DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+ BbpR49, TssiRef, TxAgcStep, 0));
+ }
+ }
+ }
+ else
+ {
+ if (pAd->CommonCfg.Channel <= 14)
+ {
+ bAutoTxAgc = pAd->bAutoTxAgcG;
+ pTxAgcCompensate = &pAd->TxAgcCompensateG;
+ }
+ else
+ {
+ bAutoTxAgc = pAd->bAutoTxAgcA;
+ pTxAgcCompensate = &pAd->TxAgcCompensateA;
+ }
+
+ if (bAutoTxAgc)
+ DeltaPwr += (*pTxAgcCompensate);
+ }
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
+ BbpR1 &= 0xFC;
+
+#ifdef SINGLE_SKU
+ // Handle regulatory max tx power constrain
+ do
+ {
+ UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
+ UCHAR AdjustMaxTxPwr[40];
+
+ if (pAd->CommonCfg.Channel > 14) // 5G band
+ TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
+ else // 2.4G band
+ TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
+ CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
+
+ // error handling, range check
+ if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
+ break;
+ }
+
+ criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
+
+ // Adjust max tx power according to the relationship of tx power in E2PROM
+ for (i=0; i<5; i++)
+ {
+ // CCK will have 4dBm larger than OFDM
+ // Therefore, we should separate to parse the tx power field
+ if (i == 0)
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
+
+ if (j < 4)
+ {
+ // CCK will have 4dBm larger than OFDM
+ AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
+ }
+ else
+ {
+ AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
+ }
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+ }
+ }
+ else
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
+
+ AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+ }
+ }
+ }
+
+ // Adjust tx power according to the relationship
+ for (i=0; i<5; i++)
+ {
+ if (TxPwr[i] != 0xffffffff)
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
+
+ // The system tx power is larger than the regulatory, the power should be restrain
+ if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
+ {
+ // decrease to zero and don't need to take care BBPR1
+ if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
+ Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
+ else
+ Value = 0;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+ }
+ else
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
+
+ TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
+ }
+ }
+ }
+ } while (FALSE);
+#endif // SINGLE_SKU //
+
+ /* calculate delta power based on the percentage specified from UI */
+ // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
+ // We lower TX power here according to the percentage specified from UI
+ if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
+ ;
+ else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
+ ;
+ else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
+ {
+ DeltaPwr -= 1;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
+ {
+ DeltaPwr -= 3;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
+ {
+ BbpR1 |= 0x01;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
+ {
+ BbpR1 |= 0x01;
+ DeltaPwr -= 3;
+ }
+ else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
+ {
+ BbpR1 |= 0x02;
+ }
+
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
+
+ /* reset different new tx power for different TX rate */
+ for(i=0; i<5; i++)
+ {
+ if (TxPwr[i] != 0xffffffff)
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
+
+ if ((Value + DeltaPwr) < 0)
+ {
+ Value = 0; /* min */
+ }
+ else if ((Value + DeltaPwr) > 0xF)
+ {
+ Value = 0xF; /* max */
+ }
+ else
+ {
+ Value += DeltaPwr; /* temperature compensation */
+ }
+
+ /* fill new value to CSR offset */
+ TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
+ }
+
+ /* write tx power value to CSR */
+ /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
+ TX power for OFDM 6M/9M
+ TX power for CCK5.5M/11M
+ TX power for CCK1M/2M */
+ /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
+ }
+ }
+
+}
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
+ automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
+ the wakeup timer timeout. Driver has to issue a separate command to wake
+ PHY up.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSleepThenAutoWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT TbttNumToNextWakeUp)
+{
+ RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
+}
+
+/*
+ ==========================================================================
+ Description:
+ AsicForceWakeup() is used whenever manual wakeup is required
+ AsicForceSleep() should only be used when not in INFRA BSS. When
+ in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
+ ==========================================================================
+ */
+VOID AsicForceSleep(
+ IN PRTMP_ADAPTER pAd)
+{
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
+ expired.
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+ ==========================================================================
+ */
+VOID AsicForceWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bFromTx)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
+ RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
+}
+#endif // CONFIG_STA_SUPPORT //
+/*
+ ==========================================================================
+ Description:
+ Set My BSSID
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSetBssid(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pBssid)
+{
+ ULONG Addr4;
+ DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
+ pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
+
+ Addr4 = (ULONG)(pBssid[0]) |
+ (ULONG)(pBssid[1] << 8) |
+ (ULONG)(pBssid[2] << 16) |
+ (ULONG)(pBssid[3] << 24);
+ RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
+
+ Addr4 = 0;
+ // always one BSSID in STA mode
+ Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
+
+ RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
+}
+
+VOID AsicSetMcastWC(
+ IN PRTMP_ADAPTER pAd)
+{
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
+ USHORT offset;
+
+ pEntry->Sst = SST_ASSOC;
+ pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
+ pEntry->PsMode = PWR_ACTIVE;
+ pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
+ offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicDelWcidTab(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid)
+{
+ ULONG Addr0 = 0x0, Addr1 = 0x0;
+ ULONG offset;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
+ offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
+ RTMP_IO_WRITE32(pAd, offset, Addr0);
+ offset += 4;
+ RTMP_IO_WRITE32(pAd, offset, Addr1);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicEnableRDG(
+ IN PRTMP_ADAPTER pAd)
+{
+ TX_LINK_CFG_STRUC TxLinkCfg;
+ UINT32 Data = 0;
+
+ RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+ TxLinkCfg.field.TxRDGEn = 1;
+ RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+ Data &= 0xFFFFFF00;
+ Data |= 0x80;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+
+ //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicDisableRDG(
+ IN PRTMP_ADAPTER pAd)
+{
+ TX_LINK_CFG_STRUC TxLinkCfg;
+ UINT32 Data = 0;
+
+
+ RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+ TxLinkCfg.field.TxRDGEn = 0;
+ RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+
+ Data &= 0xFFFFFF00;
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
+#ifdef DOT11_N_SUPPORT
+ && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
+#endif // DOT11_N_SUPPORT //
+ )
+ {
+ // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
+ if (pAd->CommonCfg.bEnableTxBurst)
+ Data |= 0x20;
+ }
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicDisableSync(
+ IN PRTMP_ADAPTER pAd)
+{
+ BCN_TIME_CFG_STRUC csr;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
+
+ // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
+ // that NIC will never wakes up because TSF stops and no more
+ // TBTT interrupts
+ pAd->TbttTickCount = 0;
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+ csr.field.bBeaconGen = 0;
+ csr.field.bTBTTEnable = 0;
+ csr.field.TsfSyncMode = 0;
+ csr.field.bTsfTicking = 0;
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicEnableBssSync(
+ IN PRTMP_ADAPTER pAd)
+{
+ BCN_TIME_CFG_STRUC csr;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
+
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
+ csr.field.bTsfTicking = 1;
+ csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
+ csr.field.bBeaconGen = 0; // do NOT generate BEACON
+ csr.field.bTBTTEnable = 1;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Note:
+ BEACON frame in shared memory should be built ok before this routine
+ can be called. Otherwise, a garbage frame maybe transmitted out every
+ Beacon period.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicEnableIbssSync(
+ IN PRTMP_ADAPTER pAd)
+{
+ BCN_TIME_CFG_STRUC csr9;
+ PUCHAR ptr;
+ UINT i;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
+
+ RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
+ csr9.field.bBeaconGen = 0;
+ csr9.field.bTBTTEnable = 0;
+ csr9.field.bTsfTicking = 0;
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
+
+#ifdef RT2860
+ // move BEACON TXD and frame content to on-chip memory
+ ptr = (PUCHAR)&pAd->BeaconTxWI;
+ for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
+ {
+ UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
+ RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
+ ptr += 4;
+ }
+
+ // start right after the 16-byte TXWI field
+ ptr = pAd->BeaconBuf;
+ for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
+ {
+ UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
+ RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
+ ptr +=4;
+ }
+#endif // RT2860 //
+
+ // start sending BEACON
+ csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
+ csr9.field.bTsfTicking = 1;
+ csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
+ csr9.field.bTBTTEnable = 1;
+ csr9.field.bBeaconGen = 1;
+ RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSetEdcaParm(
+ IN PRTMP_ADAPTER pAd,
+ IN PEDCA_PARM pEdcaParm)
+{
+ EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
+ AC_TXOP_CSR0_STRUC csr0;
+ AC_TXOP_CSR1_STRUC csr1;
+ AIFSN_CSR_STRUC AifsnCsr;
+ CWMIN_CSR_STRUC CwminCsr;
+ CWMAX_CSR_STRUC CwmaxCsr;
+ int i;
+
+ Ac0Cfg.word = 0;
+ Ac1Cfg.word = 0;
+ Ac2Cfg.word = 0;
+ Ac3Cfg.word = 0;
+ if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
+ for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
+ CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
+ }
+
+ //========================================================
+ // MAC Register has a copy .
+ //========================================================
+ if( pAd->CommonCfg.bEnableTxBurst )
+ {
+ // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
+ Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
+ }
+ else
+ Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
+ Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac0Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
+
+ Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
+ Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac1Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
+
+ if (pAd->CommonCfg.PhyMode == PHY_11B)
+ {
+ Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
+ Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
+ }
+ else
+ {
+ Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
+ Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
+ }
+ Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac2Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
+ Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
+ Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
+ Ac3Cfg.field.Aifsn = 2;
+ RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
+
+ //========================================================
+ // DMA Register has a copy too.
+ //========================================================
+ csr0.field.Ac0Txop = 0; // QID_AC_BE
+ csr0.field.Ac1Txop = 0; // QID_AC_BK
+ RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+ if (pAd->CommonCfg.PhyMode == PHY_11B)
+ {
+ csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
+ csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
+ }
+ else
+ {
+ csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
+ csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
+ }
+ RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
+
+ CwminCsr.word = 0;
+ CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
+ CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
+ CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
+ CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
+ RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
+
+ CwmaxCsr.word = 0;
+ CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
+ CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
+ CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
+ CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
+ RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
+
+ RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
+
+ NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
+ }
+ else
+ {
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
+ //========================================================
+ // MAC Register has a copy.
+ //========================================================
+ //
+ // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
+ // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
+ //
+ //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
+
+ Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
+ Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
+ Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
+ Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
+
+ Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
+ Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
+ Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
+ Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
+
+ Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
+ Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
+ Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
+ Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Tuning for Wi-Fi WMM S06
+ if (pAd->CommonCfg.bWiFiTest &&
+ pEdcaParm->Aifsn[QID_AC_VI] == 10)
+ Ac2Cfg.field.Aifsn -= 1;
+
+ // Tuning for TGn Wi-Fi 5.2.32
+ // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
+ if (STA_TGN_WIFI_ON(pAd) &&
+ pEdcaParm->Aifsn[QID_AC_VI] == 10)
+ {
+ Ac0Cfg.field.Aifsn = 3;
+ Ac2Cfg.field.AcTxop = 5;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
+ Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
+ Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
+ Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
+
+//#ifdef WIFI_TEST
+ if (pAd->CommonCfg.bWiFiTest)
+ {
+ if (Ac3Cfg.field.AcTxop == 102)
+ {
+ Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
+ Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
+ Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
+ Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
+ Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
+ } /* End of if */
+ }
+//#endif // WIFI_TEST //
+
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
+ RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
+ RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
+ RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
+
+
+ //========================================================
+ // DMA Register has a copy too.
+ //========================================================
+ csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
+ csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
+ RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+
+ csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
+ csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
+ RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
+
+ CwminCsr.word = 0;
+ CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
+ CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
+ CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
+#endif // CONFIG_STA_SUPPORT //
+ RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
+
+ CwmaxCsr.word = 0;
+ CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
+ CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
+ CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
+ CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
+ RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
+
+ AifsnCsr.word = 0;
+ AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
+ AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
+ AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Tuning for Wi-Fi WMM S06
+ if (pAd->CommonCfg.bWiFiTest &&
+ pEdcaParm->Aifsn[QID_AC_VI] == 10)
+ AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
+
+ // Tuning for TGn Wi-Fi 5.2.32
+ // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
+ if (STA_TGN_WIFI_ON(pAd) &&
+ pEdcaParm->Aifsn[QID_AC_VI] == 10)
+ {
+ AifsnCsr.field.Aifsn0 = 3;
+ AifsnCsr.field.Aifsn2 = 7;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
+#endif // CONFIG_STA_SUPPORT //
+ RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
+
+ NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
+ if (!ADHOC_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[0],
+ pEdcaParm->Cwmin[0],
+ pEdcaParm->Cwmax[0],
+ pEdcaParm->Txop[0]<<5,
+ pEdcaParm->bACM[0]));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[1],
+ pEdcaParm->Cwmin[1],
+ pEdcaParm->Cwmax[1],
+ pEdcaParm->Txop[1]<<5,
+ pEdcaParm->bACM[1]));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[2],
+ pEdcaParm->Cwmin[2],
+ pEdcaParm->Cwmax[2],
+ pEdcaParm->Txop[2]<<5,
+ pEdcaParm->bACM[2]));
+ DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
+ pEdcaParm->Aifsn[3],
+ pEdcaParm->Cwmin[3],
+ pEdcaParm->Cwmax[3],
+ pEdcaParm->Txop[3]<<5,
+ pEdcaParm->bACM[3]));
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicSetSlotTime(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bUseShortSlotTime)
+{
+ ULONG SlotTime;
+ UINT32 RegValue = 0;
+
+#ifdef CONFIG_STA_SUPPORT
+ if (pAd->CommonCfg.Channel > 14)
+ bUseShortSlotTime = TRUE;
+#endif // CONFIG_STA_SUPPORT //
+
+ if (bUseShortSlotTime)
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
+ else
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
+
+ SlotTime = (bUseShortSlotTime)? 9 : 20;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // force using short SLOT time for FAE to demo performance when TxBurst is ON
+ if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
+#ifdef DOT11_N_SUPPORT
+ || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
+#endif // DOT11_N_SUPPORT //
+ )
+ {
+ // In this case, we will think it is doing Wi-Fi test
+ // And we will not set to short slot when bEnableTxBurst is TRUE.
+ }
+ else if (pAd->CommonCfg.bEnableTxBurst)
+ SlotTime = 9;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ //
+ // For some reasons, always set it to short slot time.
+ //
+ // ToDo: Should consider capability with 11B
+ //
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (pAd->StaCfg.BssType == BSS_ADHOC)
+ SlotTime = 20;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
+ RegValue = RegValue & 0xFFFFFF00;
+
+ RegValue |= SlotTime;
+
+ RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
+}
+
+/*
+ ========================================================================
+ Description:
+ Add Shared key information into ASIC.
+ Update shared key, TxMic and RxMic to Asic Shared key table
+ Update its cipherAlg to Asic Shared key Mode.
+
+ Return:
+ ========================================================================
+*/
+VOID AsicAddSharedKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx,
+ IN UCHAR CipherAlg,
+ IN PUCHAR pKey,
+ IN PUCHAR pTxMic,
+ IN PUCHAR pRxMic)
+{
+ ULONG offset; //, csr0;
+ SHAREDKEY_MODE_STRUC csr1;
+#ifdef RT2860
+ INT i;
+#endif // RT2860 //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
+//============================================================================================
+
+ DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
+ if (pRxMic)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
+ }
+ if (pTxMic)
+ {
+ DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
+ }
+//============================================================================================
+ //
+ // fill key material - key + TX MIC + RX MIC
+ //
+#ifdef RT2860
+ offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
+ for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
+ }
+
+ offset += MAX_LEN_OF_SHARE_KEY;
+ if (pTxMic)
+ {
+ for (i=0; i<8; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
+ }
+ }
+
+ offset += 8;
+ if (pRxMic)
+ {
+ for (i=0; i<8; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
+ }
+ }
+#endif // RT2860 //
+
+
+ //
+ // Update cipher algorithm. WSTA always use BSS0
+ //
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
+ DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
+ if ((BssIndex%2) == 0)
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss0Key0CipherAlg = CipherAlg;
+ else if (KeyIdx == 1)
+ csr1.field.Bss0Key1CipherAlg = CipherAlg;
+ else if (KeyIdx == 2)
+ csr1.field.Bss0Key2CipherAlg = CipherAlg;
+ else
+ csr1.field.Bss0Key3CipherAlg = CipherAlg;
+ }
+ else
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss1Key0CipherAlg = CipherAlg;
+ else if (KeyIdx == 1)
+ csr1.field.Bss1Key1CipherAlg = CipherAlg;
+ else if (KeyIdx == 2)
+ csr1.field.Bss1Key2CipherAlg = CipherAlg;
+ else
+ csr1.field.Bss1Key3CipherAlg = CipherAlg;
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
+
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID AsicRemoveSharedKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx)
+{
+ //ULONG SecCsr0;
+ SHAREDKEY_MODE_STRUC csr1;
+
+ DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
+
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
+ if ((BssIndex%2) == 0)
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss0Key0CipherAlg = 0;
+ else if (KeyIdx == 1)
+ csr1.field.Bss0Key1CipherAlg = 0;
+ else if (KeyIdx == 2)
+ csr1.field.Bss0Key2CipherAlg = 0;
+ else
+ csr1.field.Bss0Key3CipherAlg = 0;
+ }
+ else
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss1Key0CipherAlg = 0;
+ else if (KeyIdx == 1)
+ csr1.field.Bss1Key1CipherAlg = 0;
+ else if (KeyIdx == 2)
+ csr1.field.Bss1Key2CipherAlg = 0;
+ else
+ csr1.field.Bss1Key3CipherAlg = 0;
+ }
+ DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
+ ASSERT(BssIndex < 4);
+ ASSERT(KeyIdx < 4);
+
+}
+
+
+VOID AsicUpdateWCIDAttribute(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN UCHAR BssIndex,
+ IN UCHAR CipherAlg,
+ IN BOOLEAN bUsePairewiseKeyTable)
+{
+ ULONG WCIDAttri = 0, offset;
+
+ //
+ // Update WCID attribute.
+ // Only TxKey could update WCID attribute.
+ //
+ offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
+ WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
+ RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+}
+
+VOID AsicUpdateWCIDIVEIV(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN ULONG uIV,
+ IN ULONG uEIV)
+{
+ ULONG offset;
+
+ offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
+
+ RTMP_IO_WRITE32(pAd, offset, uIV);
+ RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
+}
+
+VOID AsicUpdateRxWCIDTable(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN PUCHAR pAddr)
+{
+ ULONG offset;
+ ULONG Addr;
+
+ offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
+ Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
+ RTMP_IO_WRITE32(pAd, offset, Addr);
+ Addr = pAddr[4] + (pAddr[5] << 8);
+ RTMP_IO_WRITE32(pAd, offset + 4, Addr);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set Cipher Key, Cipher algorithm, IV/EIV to Asic
+
+ Arguments:
+ pAd Pointer to our adapter
+ WCID WCID Entry number.
+ BssIndex BSSID index, station or none multiple BSSID support
+ this value should be 0.
+ KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
+ pCipherKey Pointer to Cipher Key.
+ bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
+ otherwise PairewiseKey table
+ bTxKey This is the transmit key if enabled.
+
+ Return Value:
+ None
+
+ Note:
+ This routine will set the relative key stuff to Asic including WCID attribute,
+ Cipher Key, Cipher algorithm and IV/EIV.
+
+ IV/EIV will be update if this CipherKey is the transmission key because
+ ASIC will base on IV's KeyID value to select Cipher Key.
+
+ If bTxKey sets to FALSE, this is not the TX key, but it could be
+ RX key
+
+ For AP mode bTxKey must be always set to TRUE.
+ ========================================================================
+*/
+VOID AsicAddKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx,
+ IN PCIPHER_KEY pCipherKey,
+ IN BOOLEAN bUsePairewiseKeyTable,
+ IN BOOLEAN bTxKey)
+{
+ ULONG offset;
+ UCHAR IV4 = 0;
+ PUCHAR pKey = pCipherKey->Key;
+ PUCHAR pTxMic = pCipherKey->TxMic;
+ PUCHAR pRxMic = pCipherKey->RxMic;
+ PUCHAR pTxtsc = pCipherKey->TxTsc;
+ UCHAR CipherAlg = pCipherKey->CipherAlg;
+ SHAREDKEY_MODE_STRUC csr1;
+#ifdef RT2860
+ UCHAR i;
+#endif // RT2860 //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
+ //
+ // 1.) decide key table offset
+ //
+ if (bUsePairewiseKeyTable)
+ offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
+ else
+ offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
+
+ //
+ // 2.) Set Key to Asic
+ //
+ //for (i = 0; i < KeyLen; i++)
+#ifdef RT2860
+ for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
+ }
+ offset += MAX_LEN_OF_PEER_KEY;
+
+ //
+ // 3.) Set MIC key if available
+ //
+ if (pTxMic)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
+ }
+ }
+ offset += LEN_TKIP_TXMICK;
+
+ if (pRxMic)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
+ }
+ }
+#endif // RT2860 //
+
+
+ //
+ // 4.) Modify IV/EIV if needs
+ // This will force Asic to use this key ID by setting IV.
+ //
+ if (bTxKey)
+ {
+#ifdef RT2860
+ offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
+ //
+ // Write IV
+ //
+ RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
+ RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
+ RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
+
+ IV4 = (KeyIdx << 6);
+ if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
+ IV4 |= 0x20; // turn on extension bit means EIV existence
+
+ RTMP_IO_WRITE8(pAd, offset + 3, IV4);
+
+ //
+ // Write EIV
+ //
+ offset += 4;
+ for (i = 0; i < 4; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
+ }
+#endif // RT2860 //
+
+ AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
+ }
+
+ if (!bUsePairewiseKeyTable)
+ {
+ //
+ // Only update the shared key security mode
+ //
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
+ if ((BssIndex % 2) == 0)
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss0Key0CipherAlg = CipherAlg;
+ else if (KeyIdx == 1)
+ csr1.field.Bss0Key1CipherAlg = CipherAlg;
+ else if (KeyIdx == 2)
+ csr1.field.Bss0Key2CipherAlg = CipherAlg;
+ else
+ csr1.field.Bss0Key3CipherAlg = CipherAlg;
+ }
+ else
+ {
+ if (KeyIdx == 0)
+ csr1.field.Bss1Key0CipherAlg = CipherAlg;
+ else if (KeyIdx == 1)
+ csr1.field.Bss1Key1CipherAlg = CipherAlg;
+ else if (KeyIdx == 2)
+ csr1.field.Bss1Key2CipherAlg = CipherAlg;
+ else
+ csr1.field.Bss1Key3CipherAlg = CipherAlg;
+ }
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
+}
+
+
+/*
+ ========================================================================
+ Description:
+ Add Pair-wise key material into ASIC.
+ Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
+
+ Return:
+ ========================================================================
+*/
+VOID AsicAddPairwiseKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR WCID,
+ IN CIPHER_KEY *pCipherKey)
+{
+ INT i;
+ ULONG offset;
+ PUCHAR pKey = pCipherKey->Key;
+ PUCHAR pTxMic = pCipherKey->TxMic;
+ PUCHAR pRxMic = pCipherKey->RxMic;
+#ifdef DBG
+ UCHAR CipherAlg = pCipherKey->CipherAlg;
+#endif // DBG //
+
+ // EKEY
+ offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
+#ifdef RT2860
+ for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
+ }
+#endif // RT2860 //
+ for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
+ {
+ UINT32 Value;
+ RTMP_IO_READ32(pAd, offset + i, &Value);
+ }
+
+ offset += MAX_LEN_OF_PEER_KEY;
+
+ // MIC KEY
+ if (pTxMic)
+ {
+#ifdef RT2860
+ for (i=0; i<8; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
+ }
+#endif // RT2860 //
+ }
+ offset += 8;
+ if (pRxMic)
+ {
+#ifdef RT2860
+ for (i=0; i<8; i++)
+ {
+ RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
+ }
+#endif // RT2860 //
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
+ DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
+ if (pRxMic)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
+ }
+ if (pTxMic)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
+ }
+}
+/*
+ ========================================================================
+ Description:
+ Remove Pair-wise key material from ASIC.
+
+ Return:
+ ========================================================================
+*/
+VOID AsicRemovePairwiseKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIdx,
+ IN UCHAR Wcid)
+{
+ ULONG WCIDAttri;
+ USHORT offset;
+
+ // re-set the entry's WCID attribute as OPEN-NONE.
+ offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
+ WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
+ RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
+}
+
+BOOLEAN AsicSendCommandToMcu(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Command,
+ IN UCHAR Token,
+ IN UCHAR Arg0,
+ IN UCHAR Arg1)
+{
+ HOST_CMD_CSR_STRUC H2MCmd;
+ H2M_MAILBOX_STRUC H2MMailbox;
+ ULONG i = 0;
+#ifdef RT2860
+#ifdef RALINK_ATE
+ static UINT32 j = 0;
+#endif // RALINK_ATE //
+#endif // RT2860 //
+ do
+ {
+ RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
+ if (H2MMailbox.field.Owner == 0)
+ break;
+
+ RTMPusecDelay(2);
+ } while(i++ < 100);
+
+ if (i >= 100)
+ {
+#ifdef RT2860
+#ifdef RALINK_ATE
+ if (pAd->ate.bFWLoading == TRUE)
+ {
+ /* reloading firmware when received iwpriv cmd "ATE=ATESTOP" */
+ if (j > 0)
+ {
+ if (j % 64 != 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("#"));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("\n"));
+ }
+ ++j;
+ }
+ else if (j == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Loading firmware. Please wait for a moment...\n"));
+ ++j;
+ }
+ }
+ else
+#endif // RALINK_ATE //
+#endif // RT2860 //
+ {
+ DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
+ }
+ return FALSE;
+ }
+
+#ifdef RT2860
+#ifdef RALINK_ATE
+ else if (pAd->ate.bFWLoading == TRUE)
+ {
+ /* reloading of firmware is completed */
+ pAd->ate.bFWLoading = FALSE;
+ DBGPRINT(RT_DEBUG_ERROR, ("\n"));
+ j = 0;
+ }
+#endif // RALINK_ATE //
+#endif // RT2860 //
+
+ H2MMailbox.field.Owner = 1; // pass ownership to MCU
+ H2MMailbox.field.CmdToken = Token;
+ H2MMailbox.field.HighByte = Arg1;
+ H2MMailbox.field.LowByte = Arg0;
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
+
+ H2MCmd.word = 0;
+ H2MCmd.field.HostCommand = Command;
+ RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
+
+ if (Command != 0x80)
+ {
+ }
+
+ return TRUE;
+}
+
+#ifdef RT2860
+BOOLEAN AsicCheckCommanOk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Command)
+{
+ UINT32 CmdStatus = 0, CID = 0, i;
+ UINT32 ThisCIDMask = 0;
+
+ i = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
+ // Find where the command is. Because this is randomly specified by firmware.
+ if ((CID & CID0MASK) == Command)
+ {
+ ThisCIDMask = CID0MASK;
+ break;
+ }
+ else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
+ {
+ ThisCIDMask = CID1MASK;
+ break;
+ }
+ else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
+ {
+ ThisCIDMask = CID2MASK;
+ break;
+ }
+ else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
+ {
+ ThisCIDMask = CID3MASK;
+ break;
+ }
+
+ RTMPusecDelay(100);
+ i++;
+ }while (i < 200);
+
+ // Get CommandStatus Value
+ RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
+
+ // This command's status is at the same position as command. So AND command position's bitmask to read status.
+ if (i < 200)
+ {
+ // If Status is 1, the comamnd is success.
+ if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
+ || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
+ return TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
+ }
+ // Clear Command and Status.
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
+
+ return FALSE;
+}
+#endif // RT2860 //
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Verify the support rate for different PHY type
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPCheckRates(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT UCHAR SupRate[],
+ IN OUT UCHAR *SupRateLen)
+{
+ UCHAR RateIdx, i, j;
+ UCHAR NewRate[12], NewRateLen;
+
+ NewRateLen = 0;
+
+ if (pAd->CommonCfg.PhyMode == PHY_11B)
+ RateIdx = 4;
+ else
+ RateIdx = 12;
+
+ // Check for support rates exclude basic rate bit
+ for (i = 0; i < *SupRateLen; i++)
+ for (j = 0; j < RateIdx; j++)
+ if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
+ NewRate[NewRateLen++] = SupRate[i];
+
+ *SupRateLen = NewRateLen;
+ NdisMoveMemory(SupRate, NewRate, NewRateLen);
+}
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef DOT11_N_SUPPORT
+BOOLEAN RTMPCheckChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CentralChannel,
+ IN UCHAR Channel)
+{
+ UCHAR k;
+ UCHAR UpperChannel = 0, LowerChannel = 0;
+ UCHAR NoEffectChannelinList = 0;
+
+ // Find upper and lower channel according to 40MHz current operation.
+ if (CentralChannel < Channel)
+ {
+ UpperChannel = Channel;
+ if (CentralChannel > 2)
+ LowerChannel = CentralChannel - 2;
+ else
+ return FALSE;
+ }
+ else if (CentralChannel > Channel)
+ {
+ UpperChannel = CentralChannel + 2;
+ LowerChannel = Channel;
+ }
+
+ for (k = 0;k < pAd->ChannelListNum;k++)
+ {
+ if (pAd->ChannelList[k].Channel == UpperChannel)
+ {
+ NoEffectChannelinList ++;
+ }
+ if (pAd->ChannelList[k].Channel == LowerChannel)
+ {
+ NoEffectChannelinList ++;
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
+ if (NoEffectChannelinList == 2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Verify the support rate for HT phy type
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+BOOLEAN RTMPCheckHt(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN ADD_HT_INFO_IE *pAddHtInfo)
+{
+ if (Wcid >= MAX_LEN_OF_MAC_TABLE)
+ return FALSE;
+
+ // If use AMSDU, set flag.
+ if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
+ CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
+ // Save Peer Capability
+ if (pHtCapability->HtCapInfo.ShortGIfor20)
+ CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
+ if (pHtCapability->HtCapInfo.ShortGIfor40)
+ CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
+ if (pHtCapability->HtCapInfo.TxSTBC)
+ CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
+ if (pHtCapability->HtCapInfo.RxSTBC)
+ CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
+ if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
+ {
+ CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
+ }
+
+ if (Wcid < MAX_LEN_OF_MAC_TABLE)
+ {
+ pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
+ }
+
+ // Will check ChannelWidth for MCSSet[4] below
+ pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
+ switch (pAd->CommonCfg.RxStream)
+ {
+ case 1:
+ pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
+ pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
+ pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
+ pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
+ break;
+ case 2:
+ pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
+ pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
+ pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
+ pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
+ break;
+ case 3:
+ pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
+ pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
+ pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
+ pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
+ break;
+ }
+
+ pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
+ pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
+ pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
+
+ pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
+
+ // Send Assoc Req with my HT capability.
+ pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
+ pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
+ pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
+ pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
+ pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
+ pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
+ pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
+ pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
+ pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
+ pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
+ if (pAd->CommonCfg.bRdg)
+ {
+ pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
+ pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
+ }
+
+ if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
+ pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
+
+ COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
+ return TRUE;
+}
+#endif // DOT11_N_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Verify the support rate for different PHY type
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPUpdateMlmeRate(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR MinimumRate;
+ UCHAR ProperMlmeRate; //= RATE_54;
+ UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
+ BOOLEAN bMatch = FALSE;
+
+ switch (pAd->CommonCfg.PhyMode)
+ {
+ case PHY_11B:
+ ProperMlmeRate = RATE_11;
+ MinimumRate = RATE_1;
+ break;
+ case PHY_11BG_MIXED:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11ABGN_MIXED:
+ case PHY_11BGN_MIXED:
+#endif // DOT11_N_SUPPORT //
+ if ((pAd->MlmeAux.SupRateLen == 4) &&
+ (pAd->MlmeAux.ExtRateLen == 0))
+ // B only AP
+ ProperMlmeRate = RATE_11;
+ else
+ ProperMlmeRate = RATE_24;
+
+ if (pAd->MlmeAux.Channel <= 14)
+ MinimumRate = RATE_1;
+ else
+ MinimumRate = RATE_6;
+ break;
+ case PHY_11A:
+#ifdef DOT11_N_SUPPORT
+ case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
+ case PHY_11GN_MIXED:
+ case PHY_11AGN_MIXED:
+ case PHY_11AN_MIXED:
+ case PHY_11N_5G:
+#endif // DOT11_N_SUPPORT //
+ ProperMlmeRate = RATE_24;
+ MinimumRate = RATE_6;
+ break;
+ case PHY_11ABG_MIXED:
+ ProperMlmeRate = RATE_24;
+ if (pAd->MlmeAux.Channel <= 14)
+ MinimumRate = RATE_1;
+ else
+ MinimumRate = RATE_6;
+ break;
+ default: // error
+ ProperMlmeRate = RATE_1;
+ MinimumRate = RATE_1;
+ break;
+ }
+
+ for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
+ {
+ for (j = 0; j < RateIdx; j++)
+ {
+ if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
+ {
+ if (j == ProperMlmeRate)
+ {
+ bMatch = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (bMatch)
+ break;
+ }
+
+ if (bMatch == FALSE)
+ {
+ for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
+ {
+ for (j = 0; j < RateIdx; j++)
+ {
+ if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
+ {
+ if (j == ProperMlmeRate)
+ {
+ bMatch = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (bMatch)
+ break;
+ }
+ }
+
+ if (bMatch == FALSE)
+ {
+ ProperMlmeRate = MinimumRate;
+ }
+
+ pAd->CommonCfg.MlmeRate = MinimumRate;
+ pAd->CommonCfg.RtsRate = ProperMlmeRate;
+ if (pAd->CommonCfg.MlmeRate >= RATE_6)
+ {
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ }
+ else
+ {
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
+}
+
+CHAR RTMPMaxRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi0,
+ IN CHAR Rssi1,
+ IN CHAR Rssi2)
+{
+ CHAR larger = -127;
+
+ if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
+ {
+ larger = Rssi0;
+ }
+
+ if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
+ {
+ larger = max(Rssi0, Rssi1);
+ }
+
+ if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
+ {
+ larger = max(larger, Rssi2);
+ }
+
+ if (larger == -127)
+ larger = 0;
+
+ return larger;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Periodic evaluate antenna link status
+
+ Arguments:
+ pAd - Adapter pointer
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID AsicEvaluateRxAnt(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR BBPR3 = 0;
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_NIC_NOT_EXIST |
+ fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
+ return;
+
+ if (pAd->StaCfg.Psm == PWR_SAVE)
+ return;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
+ BBPR3 &= (~0x18);
+ if(pAd->Antenna.field.RxPath == 3)
+ {
+ BBPR3 |= (0x10);
+ }
+ else if(pAd->Antenna.field.RxPath == 2)
+ {
+ BBPR3 |= (0x8);
+ }
+ else if(pAd->Antenna.field.RxPath == 1)
+ {
+ BBPR3 |= (0x0);
+ }
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
+#ifdef CONFIG_STA_SUPPORT
+#ifdef RT2860
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ pAd->StaCfg.BBPR3 = BBPR3;
+#endif // RT2860 //
+#endif // CONFIG_STA_SUPPORT //
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+ )
+ {
+ ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
+ pAd->RalinkCounters.OneSecTxRetryOkCount +
+ pAd->RalinkCounters.OneSecTxFailCount;
+
+ if (TxTotalCnt > 50)
+ {
+ RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
+ pAd->Mlme.bLowThroughput = FALSE;
+ }
+ else
+ {
+ RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
+ pAd->Mlme.bLowThroughput = TRUE;
+ }
+ }
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ After evaluation, check antenna link status
+
+ Arguments:
+ pAd - Adapter pointer
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID AsicRxAntEvalTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+#ifdef CONFIG_STA_SUPPORT
+ UCHAR BBPR3 = 0;
+ CHAR larger = -127, rssi0, rssi1, rssi2;
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ if (pAd->StaCfg.Psm == PWR_SAVE)
+ return;
+
+
+ // if the traffic is low, use average rssi as the criteria
+ if (pAd->Mlme.bLowThroughput == TRUE)
+ {
+ rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
+ rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
+ rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
+ }
+ else
+ {
+ rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
+ rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
+ rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
+ }
+
+ if(pAd->Antenna.field.RxPath == 3)
+ {
+ larger = max(rssi0, rssi1);
+
+ if (larger > (rssi2 + 20))
+ pAd->Mlme.RealRxPath = 2;
+ else
+ pAd->Mlme.RealRxPath = 3;
+ }
+ else if(pAd->Antenna.field.RxPath == 2)
+ {
+ if (rssi0 > (rssi1 + 20))
+ pAd->Mlme.RealRxPath = 1;
+ else
+ pAd->Mlme.RealRxPath = 2;
+ }
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
+ BBPR3 &= (~0x18);
+ if(pAd->Mlme.RealRxPath == 3)
+ {
+ BBPR3 |= (0x10);
+ }
+ else if(pAd->Mlme.RealRxPath == 2)
+ {
+ BBPR3 |= (0x8);
+ }
+ else if(pAd->Mlme.RealRxPath == 1)
+ {
+ BBPR3 |= (0x0);
+ }
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
+#ifdef RT2860
+ pAd->StaCfg.BBPR3 = BBPR3;
+#endif // RT2860 //
+ }
+
+#endif // CONFIG_STA_SUPPORT //
+
+}
+
+
+
+VOID APSDPeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ return;
+
+ pAd->CommonCfg.TriggerTimerCount++;
+
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Set/reset MAC registers according to bPiggyBack parameter
+
+ Arguments:
+ pAd - Adapter pointer
+ bPiggyBack - Enable / Disable Piggy-Back
+
+ Return Value:
+ None
+
+ ========================================================================
+*/
+VOID RTMPSetPiggyBack(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bPiggyBack)
+{
+ TX_LINK_CFG_STRUC TxLinkCfg;
+
+ RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
+
+ TxLinkCfg.field.TxCFAckEn = bPiggyBack;
+ RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ check if this entry need to switch rate automatically
+
+ Arguments:
+ pAd
+ pEntry
+
+ Return Value:
+ TURE
+ FALSE
+
+ ========================================================================
+*/
+BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ BOOLEAN result = TRUE;
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // only associated STA counts
+ if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
+ {
+ result = pAd->StaCfg.bAutoTxRateSwitch;
+ }
+ else
+ result = FALSE;
+
+#ifdef QOS_DLS_SUPPORT
+ if (pEntry && (pEntry->ValidAsDls))
+ result = pAd->StaCfg.bAutoTxRateSwitch;
+#endif // QOS_DLS_SUPPORT //
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+ return result;
+}
+
+
+BOOLEAN RTMPAutoRateSwitchCheck(
+ IN PRTMP_ADAPTER pAd)
+{
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (pAd->StaCfg.bAutoTxRateSwitch)
+ return TRUE;
+ }
+#endif // CONFIG_STA_SUPPORT //
+ return FALSE;
+}
+
+
+/*
+ ========================================================================
+ Routine Description:
+ check if this entry need to fix tx legacy rate
+
+ Arguments:
+ pAd
+ pEntry
+
+ Return Value:
+ TURE
+ FALSE
+
+ ========================================================================
+*/
+UCHAR RTMPStaFixedTxMode(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry)
+{
+ UCHAR tx_mode = FIXED_TXMODE_HT;
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ return tx_mode;
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
+
+ Arguments:
+ pAd
+ pEntry
+
+ Return Value:
+ TURE
+ FALSE
+
+ ========================================================================
+*/
+VOID RTMPUpdateLegacyTxSetting(
+ UCHAR fixed_tx_mode,
+ PMAC_TABLE_ENTRY pEntry)
+{
+ HTTRANSMIT_SETTING TransmitSetting;
+
+ if (fixed_tx_mode == FIXED_TXMODE_HT)
+ return;
+
+ TransmitSetting.word = 0;
+
+ TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
+ TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
+
+ if (fixed_tx_mode == FIXED_TXMODE_CCK)
+ {
+ TransmitSetting.field.MODE = MODE_CCK;
+ // CCK mode allow MCS 0~3
+ if (TransmitSetting.field.MCS > MCS_3)
+ TransmitSetting.field.MCS = MCS_3;
+ }
+ else
+ {
+ TransmitSetting.field.MODE = MODE_OFDM;
+ // OFDM mode allow MCS 0~7
+ if (TransmitSetting.field.MCS > MCS_7)
+ TransmitSetting.field.MCS = MCS_7;
+ }
+
+ if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
+ {
+ pEntry->HTPhyMode.word = TransmitSetting.word;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
+ pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
+ }
+}
+
+#ifdef CONFIG_STA_SUPPORT
+/*
+ ==========================================================================
+ Description:
+ dynamic tune BBP R66 to find a balance between sensibility and
+ noise isolation
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AsicStaBbpTuning(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
+ CHAR Rssi;
+
+ // 2860C did not support Fase CCA, therefore can't tune
+ if (pAd->MACVersion == 0x28600100)
+ return;
+
+ //
+ // work as a STA
+ //
+ if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
+ return;
+
+ if ((pAd->OpMode == OPMODE_STA)
+ && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
+ )
+ && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+#ifdef RT2860
+ && (pAd->bPCIclkOff == FALSE)
+#endif // RT2860 //
+ )
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
+ R66 = OrigR66Value;
+
+ if (pAd->Antenna.field.RxPath > 1)
+ Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
+ else
+ Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
+
+ if (pAd->LatchRfRegs.Channel <= 14)
+ { //BG band
+ {
+ if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+ {
+ R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
+ if (OrigR66Value != R66)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ }
+ else
+ {
+ R66 = 0x2E + GET_LNA_GAIN(pAd);
+ if (OrigR66Value != R66)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ }
+ }
+ }
+ else
+ { //A band
+ if (pAd->CommonCfg.BBPCurrentBW == BW_20)
+ {
+ if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+ {
+ R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
+ if (OrigR66Value != R66)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ }
+ else
+ {
+ R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
+ if (OrigR66Value != R66)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ }
+ }
+ else
+ {
+ if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
+ {
+ R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
+ if (OrigR66Value != R66)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ }
+ else
+ {
+ R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
+ if (OrigR66Value != R66)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ }
+ }
+ }
+
+
+ }
+}
+#endif // CONFIG_STA_SUPPORT //
+
+VOID RTMPSetAGCInitValue(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BandWidth)
+{
+ UCHAR R66 = 0x30;
+
+ if (pAd->LatchRfRegs.Channel <= 14)
+ { // BG band
+ R66 = 0x2E + GET_LNA_GAIN(pAd);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ else
+ { //A band
+ if (BandWidth == BW_20)
+ {
+ R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+#ifdef DOT11_N_SUPPORT
+ else
+ {
+ R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+#endif // DOT11_N_SUPPORT //
+ }
+
+}
+
+VOID AsicTurnOffRFClk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel)
+{
+
+ // RF R2 bit 18 = 0
+ UINT32 R1 = 0, R2 = 0, R3 = 0;
+ UCHAR index;
+ RTMP_RF_REGS *RFRegTable;
+
+ RFRegTable = RF2850RegTable;
+
+ switch (pAd->RfIcType)
+ {
+ case RFIC_2820:
+ case RFIC_2850:
+ case RFIC_2720:
+ case RFIC_2750:
+
+ for (index = 0; index < NUM_OF_2850_CHNL; index++)
+ {
+ if (Channel == RFRegTable[index].Channel)
+ {
+ R1 = RFRegTable[index].R1 & 0xffffdfff;
+ R2 = RFRegTable[index].R2 & 0xfffbffff;
+ R3 = RFRegTable[index].R3 & 0xfff3ffff;
+
+ RTMP_RF_IO_WRITE32(pAd, R1);
+ RTMP_RF_IO_WRITE32(pAd, R2);
+
+ // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
+ // Set RF R2 bit18=0, R3 bit[18:19]=0
+ //if (pAd->StaCfg.bRadio == FALSE)
+ if (1)
+ {
+ RTMP_RF_IO_WRITE32(pAd, R3);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
+ Channel, pAd->RfIcType, R2, R3));
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
+ Channel, pAd->RfIcType, R2));
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+VOID AsicTurnOnRFClk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel)
+{
+
+ // RF R2 bit 18 = 0
+ UINT32 R1 = 0, R2 = 0, R3 = 0;
+ UCHAR index;
+ RTMP_RF_REGS *RFRegTable;
+
+ RFRegTable = RF2850RegTable;
+
+ switch (pAd->RfIcType)
+ {
+ case RFIC_2820:
+ case RFIC_2850:
+ case RFIC_2720:
+ case RFIC_2750:
+
+ for (index = 0; index < NUM_OF_2850_CHNL; index++)
+ {
+ if (Channel == RFRegTable[index].Channel)
+ {
+ R3 = pAd->LatchRfRegs.R3;
+ R3 &= 0xfff3ffff;
+ R3 |= 0x00080000;
+ RTMP_RF_IO_WRITE32(pAd, R3);
+
+ R1 = RFRegTable[index].R1;
+ RTMP_RF_IO_WRITE32(pAd, R1);
+
+ R2 = RFRegTable[index].R2;
+ if (pAd->Antenna.field.TxPath == 1)
+ {
+ R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
+ }
+
+ if (pAd->Antenna.field.RxPath == 2)
+ {
+ R2 |= 0x40; // write 1 to off Rxpath.
+ }
+ else if (pAd->Antenna.field.RxPath == 1)
+ {
+ R2 |= 0x20040; // write 1 to off RxPath
+ }
+ RTMP_RF_IO_WRITE32(pAd, R2);
+
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
+ Channel,
+ pAd->RfIcType,
+ R2));
+}
+
diff --git a/drivers/staging/rt2860/common/netif_block.c b/drivers/staging/rt2860/common/netif_block.c
new file mode 100644
index 000000000000..d3f7d087e7f0
--- /dev/null
+++ b/drivers/staging/rt2860/common/netif_block.c
@@ -0,0 +1,144 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#include "../rt_config.h"
+#include "netif_block.h"
+
+static NETIF_ENTRY freeNetIfEntryPool[FREE_NETIF_POOL_SIZE];
+static LIST_HEADER freeNetIfEntryList;
+
+void initblockQueueTab(
+ IN PRTMP_ADAPTER pAd)
+{
+ int i;
+
+ initList(&freeNetIfEntryList);
+ for (i = 0; i < FREE_NETIF_POOL_SIZE; i++)
+ insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)&freeNetIfEntryPool[i]);
+
+ for (i=0; i < NUM_OF_TX_RING; i++)
+ initList(&pAd->blockQueueTab[i].NetIfList);
+
+ return;
+}
+
+BOOLEAN blockNetIf(
+ IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry,
+ IN PNET_DEV pNetDev)
+{
+ PNETIF_ENTRY pNetIfEntry = NULL;
+
+ if ((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(&freeNetIfEntryList)) != NULL)
+ {
+ netif_stop_queue(pNetDev);
+ pNetIfEntry->pNetDev = pNetDev;
+ insertTailList(&pBlockQueueEntry->NetIfList, (PLIST_ENTRY)pNetIfEntry);
+
+ pBlockQueueEntry->SwTxQueueBlockFlag = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("netif_stop_queue(%s)\n", pNetDev->name));
+ }
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+VOID releaseNetIf(
+ IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry)
+{
+ PNETIF_ENTRY pNetIfEntry = NULL;
+ PLIST_HEADER pNetIfList = &pBlockQueueEntry->NetIfList;
+
+ while((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(pNetIfList)) != NULL)
+ {
+ PNET_DEV pNetDev = pNetIfEntry->pNetDev;
+ netif_wake_queue(pNetDev);
+ insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)pNetIfEntry);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("netif_wake_queue(%s)\n", pNetDev->name));
+ }
+ pBlockQueueEntry->SwTxQueueBlockFlag = FALSE;
+ return;
+}
+
+
+VOID StopNetIfQueue(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket)
+{
+ PNET_DEV NetDev = NULL;
+ UCHAR IfIdx = 0;
+ BOOLEAN valid = FALSE;
+
+#ifdef APCLI_SUPPORT
+ if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_APCLI)
+ {
+ IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI) % MAX_APCLI_NUM;
+ NetDev = pAd->ApCfg.ApCliTab[IfIdx].dev;
+ }
+ else
+#endif // APCLI_SUPPORT //
+#ifdef WDS_SUPPORT
+ if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS)
+ {
+ IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS) % MAX_WDS_ENTRY;
+ NetDev = pAd->WdsTab.WdsEntry[IfIdx].dev;
+ }
+ else
+#endif // WDS_SUPPORT //
+ {
+#ifdef MBSS_SUPPORT
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_MBSSID) % MAX_MBSSID_NUM;
+ NetDev = pAd->ApCfg.MBSSID[IfIdx].MSSIDDev;
+ }
+ else
+ {
+ IfIdx = MAIN_MBSSID;
+ NetDev = pAd->net_dev;
+ }
+#else
+ IfIdx = MAIN_MBSSID;
+ NetDev = pAd->net_dev;
+#endif
+ }
+
+ // WMM support 4 software queues.
+ // One software queue full doesn't mean device have no capbility to transmit packet.
+ // So disable block Net-If queue function while WMM enable.
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ valid = (pAd->CommonCfg.bWmmCapable == TRUE) ? FALSE : TRUE;
+#endif // CONFIG_STA_SUPPORT //
+
+ if (valid)
+ blockNetIf(&pAd->blockQueueTab[QueIdx], NetDev);
+ return;
+}
+
diff --git a/drivers/staging/rt2860/common/netif_block.h b/drivers/staging/rt2860/common/netif_block.h
new file mode 100644
index 000000000000..6e5151c41095
--- /dev/null
+++ b/drivers/staging/rt2860/common/netif_block.h
@@ -0,0 +1,58 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#ifndef __NET_IF_BLOCK_H__
+#define __NET_IF_BLOCK_H__
+
+//#include <linux/device.h>
+#include "link_list.h"
+#include "rtmp.h"
+
+#define FREE_NETIF_POOL_SIZE 32
+
+typedef struct _NETIF_ENTRY
+{
+ struct _NETIF_ENTRY *pNext;
+ PNET_DEV pNetDev;
+} NETIF_ENTRY, *PNETIF_ENTRY;
+
+void initblockQueueTab(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN blockNetIf(
+ IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry,
+ IN PNET_DEV pNetDev);
+
+VOID releaseNetIf(
+ IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry);
+
+VOID StopNetIfQueue(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket);
+#endif // __NET_IF_BLOCK_H__
+
diff --git a/drivers/staging/rt2860/common/rtmp_init.c b/drivers/staging/rt2860/common/rtmp_init.c
new file mode 100644
index 000000000000..563f2c5bb856
--- /dev/null
+++ b/drivers/staging/rt2860/common/rtmp_init.c
@@ -0,0 +1,3744 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_init.c
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 2002-08-01 created
+ John Chang 2004-08-20 RT2561/2661 use scatter-gather scheme
+ Jan Lee 2006-09-15 RT2860. Change for 802.11n , EEPROM, Led, BA, HT.
+*/
+#include "../rt_config.h"
+#include "firmware.h"
+#include <linux/bitrev.h>
+
+UCHAR BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
+ULONG BIT32[] = {0x00000001, 0x00000002, 0x00000004, 0x00000008,
+ 0x00000010, 0x00000020, 0x00000040, 0x00000080,
+ 0x00000100, 0x00000200, 0x00000400, 0x00000800,
+ 0x00001000, 0x00002000, 0x00004000, 0x00008000,
+ 0x00010000, 0x00020000, 0x00040000, 0x00080000,
+ 0x00100000, 0x00200000, 0x00400000, 0x00800000,
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000};
+
+char* CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128"};
+
+const unsigned short ccitt_16Table[] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+};
+#define ByteCRC16(v, crc) \
+ (unsigned short)((crc << 8) ^ ccitt_16Table[((crc >> 8) ^ (v)) & 255])
+
+//
+// BBP register initialization set
+//
+REG_PAIR BBPRegTable[] = {
+ {BBP_R65, 0x2C}, // fix rssi issue
+ {BBP_R66, 0x38}, // Also set this default value to pAd->BbpTuning.R66CurrentValue at initial
+ {BBP_R69, 0x12},
+ {BBP_R70, 0xa}, // BBP_R70 will change to 0x8 in ApStartUp and LinkUp for rt2860C, otherwise value is 0xa
+ {BBP_R73, 0x10},
+ {BBP_R81, 0x37},
+ {BBP_R82, 0x62},
+ {BBP_R83, 0x6A},
+ {BBP_R84, 0x99}, // 0x19 is for rt2860E and after. This is for extension channel overlapping IOT. 0x99 is for rt2860D and before
+ {BBP_R86, 0x00}, // middle range issue, Rory @2008-01-28
+ {BBP_R91, 0x04}, // middle range issue, Rory @2008-01-28
+ {BBP_R92, 0x00}, // middle range issue, Rory @2008-01-28
+ {BBP_R103, 0x00}, // near range high-power issue, requested from Gary @2008-0528
+ {BBP_R105, 0x05}, // 0x05 is for rt2860E to turn on FEQ control. It is safe for rt2860D and before, because Bit 7:2 are reserved in rt2860D and before.
+};
+#define NUM_BBP_REG_PARMS (sizeof(BBPRegTable) / sizeof(REG_PAIR))
+
+//
+// RF register initialization set
+//
+
+//
+// ASIC register initialization sets
+//
+
+RTMP_REG_PAIR MACRegTable[] = {
+#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200)
+ {BCN_OFFSET0, 0xf8f0e8e0}, /* 0x3800(e0), 0x3A00(e8), 0x3C00(f0), 0x3E00(f8), 512B for each beacon */
+ {BCN_OFFSET1, 0x6f77d0c8}, /* 0x3200(c8), 0x3400(d0), 0x1DC0(77), 0x1BC0(6f), 512B for each beacon */
+#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100)
+ {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
+ {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */
+#else
+ #error You must re-calculate new value for BCN_OFFSET0 & BCN_OFFSET1 in MACRegTable[]!!!
+#endif // HW_BEACON_OFFSET //
+
+ {LEGACY_BASIC_RATE, 0x0000013f}, // Basic rate set bitmap
+ {HT_BASIC_RATE, 0x00008003}, // Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.
+ {MAC_SYS_CTRL, 0x00}, // 0x1004, , default Disable RX
+ {RX_FILTR_CFG, 0x17f97}, //0x1400 , RX filter control,
+ {BKOFF_SLOT_CFG, 0x209}, // default set short slot time, CC_DELAY_TIME should be 2
+ {TX_SW_CFG0, 0x0}, // Gary,2008-05-21 for CWC test
+ {TX_SW_CFG1, 0x80606}, // Gary,2006-08-23
+ {TX_LINK_CFG, 0x1020}, // Gary,2006-08-23
+ {TX_TIMEOUT_CFG, 0x000a2090}, // CCK has some problem. So increase timieout value. 2006-10-09// MArvek RT , Modify for 2860E ,2007-08-01
+ {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, // 0x3018, MAX frame length. Max PSDU = 16kbytes.
+ {LED_CFG, 0x7f031e46}, // Gary, 2006-08-23
+ {PBF_MAX_PCNT, 0x1F3FBF9F}, //0x1F3f7f9f}, //Jan, 2006/04/20
+ {TX_RTY_CFG, 0x47d01f0f}, // Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03
+ {AUTO_RSP_CFG, 0x00000013}, // Initial Auto_Responder, because QA will turn off Auto-Responder
+ {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled.
+ {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, // Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled.
+ {GF20_PROT_CFG, 0x01744004}, // set 19:18 --> Short NAV for MIMO PS
+ {GF40_PROT_CFG, 0x03F44084},
+ {MM20_PROT_CFG, 0x01744004},
+#ifdef RT2860
+ {MM40_PROT_CFG, 0x03F54084},
+#endif // RT2860 //
+ {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, //Extension channel backoff.
+ {TX_RTS_CFG, 0x00092b20},
+ {EXP_ACK_TIME, 0x002400ca}, // default value
+ {TXOP_HLDR_ET, 0x00000002},
+
+ /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us
+ is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0
+ and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping
+ will always lost. So we change the SIFS of CCK from 10us to 16us. */
+ {XIFS_TIME_CFG, 0x33a41010},
+ {PWR_PIN_CFG, 0x00000003}, // patch for 2880-E
+};
+
+
+#ifdef CONFIG_STA_SUPPORT
+RTMP_REG_PAIR STAMACRegTable[] = {
+ {WMM_AIFSN_CFG, 0x00002273},
+ {WMM_CWMIN_CFG, 0x00002344},
+ {WMM_CWMAX_CFG, 0x000034aa},
+};
+#endif // CONFIG_STA_SUPPORT //
+
+#define NUM_MAC_REG_PARMS (sizeof(MACRegTable) / sizeof(RTMP_REG_PAIR))
+#ifdef CONFIG_STA_SUPPORT
+#define NUM_STA_MAC_REG_PARMS (sizeof(STAMACRegTable) / sizeof(RTMP_REG_PAIR))
+#endif // CONFIG_STA_SUPPORT //
+
+
+// New 8k byte firmware size for RT3071/RT3072
+#define FIRMWAREIMAGE_MAX_LENGTH 0x2000
+#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(UCHAR))
+#define FIRMWARE_MAJOR_VERSION 0
+
+#define FIRMWAREIMAGEV1_LENGTH 0x1000
+#define FIRMWAREIMAGEV2_LENGTH 0x1000
+
+#ifdef RT2860
+#define FIRMWARE_MINOR_VERSION 2
+#endif // RT2860 //
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Allocate RTMP_ADAPTER data block and do some initialization
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTMPAllocAdapterBlock(
+ IN PVOID handle,
+ OUT PRTMP_ADAPTER *ppAdapter)
+{
+ PRTMP_ADAPTER pAd;
+ NDIS_STATUS Status;
+ INT index;
+ UCHAR *pBeaconBuf = NULL;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocAdapterBlock\n"));
+
+ *ppAdapter = NULL;
+
+ do
+ {
+ // Allocate RTMP_ADAPTER memory block
+ pBeaconBuf = kmalloc(MAX_BEACON_SIZE, MEM_ALLOC_FLAG);
+ if (pBeaconBuf == NULL)
+ {
+ Status = NDIS_STATUS_FAILURE;
+ DBGPRINT_ERR(("Failed to allocate memory - BeaconBuf!\n"));
+ break;
+ }
+
+ Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n"));
+ break;
+ }
+ pAd->BeaconBuf = pBeaconBuf;
+ printk("\n\n=== pAd = %p, size = %d ===\n\n", pAd, (UINT32)sizeof(RTMP_ADAPTER));
+
+
+ // Init spin locks
+ NdisAllocateSpinLock(&pAd->MgmtRingLock);
+#ifdef RT2860
+ NdisAllocateSpinLock(&pAd->RxRingLock);
+#endif // RT2860 //
+
+ for (index =0 ; index < NUM_OF_TX_RING; index++)
+ {
+ NdisAllocateSpinLock(&pAd->TxSwQueueLock[index]);
+ NdisAllocateSpinLock(&pAd->DeQueueLock[index]);
+ pAd->DeQueueRunning[index] = FALSE;
+ }
+
+ NdisAllocateSpinLock(&pAd->irq_lock);
+
+ } while (FALSE);
+
+ if ((Status != NDIS_STATUS_SUCCESS) && (pBeaconBuf))
+ kfree(pBeaconBuf);
+
+ *ppAdapter = pAd;
+
+ DBGPRINT_S(Status, ("<-- RTMPAllocAdapterBlock, Status=%x\n", Status));
+ return Status;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read initial Tx power per MCS and BW from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPReadTxPwrPerRate(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG data, Adata, Gdata;
+ USHORT i, value, value2;
+ INT Apwrdelta, Gpwrdelta;
+ UCHAR t1,t2,t3,t4;
+ BOOLEAN bValid, bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE;
+
+ //
+ // Get power delta for 20MHz and 40MHz.
+ //
+ DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n"));
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2);
+ Apwrdelta = 0;
+ Gpwrdelta = 0;
+
+ if ((value2 & 0xff) != 0xff)
+ {
+ if ((value2 & 0x80))
+ Gpwrdelta = (value2&0xf);
+
+ if ((value2 & 0x40))
+ bGpwrdeltaMinus = FALSE;
+ else
+ bGpwrdeltaMinus = TRUE;
+ }
+ if ((value2 & 0xff00) != 0xff00)
+ {
+ if ((value2 & 0x8000))
+ Apwrdelta = ((value2&0xf00)>>8);
+
+ if ((value2 & 0x4000))
+ bApwrdeltaMinus = FALSE;
+ else
+ bApwrdeltaMinus = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta));
+
+ //
+ // Get Txpower per MCS for 20MHz in 2.4G.
+ //
+ for (i=0; i<5; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value);
+ data = value;
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Apwrdelta)
+ t1 = (value&0xf)-(Apwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Apwrdelta)
+ t2 = ((value&0xf0)>>4)-(Apwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Apwrdelta)
+ t3 = ((value&0xf00)>>8)-(Apwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Apwrdelta)
+ t4 = ((value&0xf000)>>12)-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+ if (bGpwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Gpwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Gpwrdelta)
+ t1 = (value&0xf)-(Gpwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Gpwrdelta)
+ t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Gpwrdelta)
+ t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Gpwrdelta)
+ t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+ else
+ t4 = 0;
+ }
+ Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value);
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Apwrdelta)
+ t1 = (value&0xf)-(Apwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Apwrdelta)
+ t2 = ((value&0xf0)>>4)-(Apwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Apwrdelta)
+ t3 = ((value&0xf00)>>8)-(Apwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Apwrdelta)
+ t4 = ((value&0xf000)>>12)-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+ if (bGpwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Gpwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Gpwrdelta)
+ t1 = (value&0xf)-(Gpwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Gpwrdelta)
+ t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Gpwrdelta)
+ t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Gpwrdelta)
+ t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+ else
+ t4 = 0;
+ }
+ Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+ data |= (value<<16);
+
+ pAd->Tx20MPwrCfgABand[i] = pAd->Tx40MPwrCfgABand[i] = Adata;
+ pAd->Tx20MPwrCfgGBand[i] = pAd->Tx40MPwrCfgGBand[i] = Gdata;
+
+ if (data != 0xffffffff)
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%lx, Adata = %lx, Gdata = %lx \n", data, Adata, Gdata));
+ }
+
+ //
+ // Check this block is valid for 40MHz in 2.4G. If invalid, use parameter for 20MHz in 2.4G
+ //
+ bValid = TRUE;
+ for (i=0; i<6; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + 2 + i*2, value);
+ if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
+ {
+ bValid = FALSE;
+ break;
+ }
+ }
+
+ //
+ // Get Txpower per MCS for 40MHz in 2.4G.
+ //
+ if (bValid)
+ {
+ for (i=0; i<4; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4, value);
+ if (bGpwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Gpwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Gpwrdelta)
+ t1 = (value&0xf)-(Gpwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Gpwrdelta)
+ t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Gpwrdelta)
+ t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Gpwrdelta)
+ t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+ else
+ t4 = 0;
+ }
+ Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_2_4G + i*4 + 2, value);
+ if (bGpwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Gpwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Gpwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Gpwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Gpwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Gpwrdelta)
+ t1 = (value&0xf)-(Gpwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Gpwrdelta)
+ t2 = ((value&0xf0)>>4)-(Gpwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Gpwrdelta)
+ t3 = ((value&0xf00)>>8)-(Gpwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Gpwrdelta)
+ t4 = ((value&0xf000)>>12)-(Gpwrdelta);
+ else
+ t4 = 0;
+ }
+ Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+
+ if (i == 0)
+ pAd->Tx40MPwrCfgGBand[i+1] = (pAd->Tx40MPwrCfgGBand[i+1] & 0x0000FFFF) | (Gdata & 0xFFFF0000);
+ else
+ pAd->Tx40MPwrCfgGBand[i+1] = Gdata;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 2.4G band, Gdata = %lx \n", Gdata));
+ }
+ }
+
+ //
+ // Check this block is valid for 20MHz in 5G. If invalid, use parameter for 20MHz in 2.4G
+ //
+ bValid = TRUE;
+ for (i=0; i<8; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + 2 + i*2, value);
+ if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
+ {
+ bValid = FALSE;
+ break;
+ }
+ }
+
+ //
+ // Get Txpower per MCS for 20MHz in 5G.
+ //
+ if (bValid)
+ {
+ for (i=0; i<5; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4, value);
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Apwrdelta)
+ t1 = (value&0xf)-(Apwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Apwrdelta)
+ t2 = ((value&0xf0)>>4)-(Apwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Apwrdelta)
+ t3 = ((value&0xf00)>>8)-(Apwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Apwrdelta)
+ t4 = ((value&0xf000)>>12)-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_5G + i*4 + 2, value);
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Apwrdelta)
+ t1 = (value&0xf)-(Apwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Apwrdelta)
+ t2 = ((value&0xf0)>>4)-(Apwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Apwrdelta)
+ t3 = ((value&0xf00)>>8)-(Apwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Apwrdelta)
+ t4 = ((value&0xf000)>>12)-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+
+ if (i == 0)
+ pAd->Tx20MPwrCfgABand[i] = (pAd->Tx20MPwrCfgABand[i] & 0x0000FFFF) | (Adata & 0xFFFF0000);
+ else
+ pAd->Tx20MPwrCfgABand[i] = Adata;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 5GHz band, Adata = %lx \n", Adata));
+ }
+ }
+
+ //
+ // Check this block is valid for 40MHz in 5G. If invalid, use parameter for 20MHz in 2.4G
+ //
+ bValid = TRUE;
+ for (i=0; i<6; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + 2 + i*2, value);
+ if (((value & 0x00FF) == 0x00FF) || ((value & 0xFF00) == 0xFF00))
+ {
+ bValid = FALSE;
+ break;
+ }
+ }
+
+ //
+ // Get Txpower per MCS for 40MHz in 5G.
+ //
+ if (bValid)
+ {
+ for (i=0; i<4; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4, value);
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Apwrdelta)
+ t1 = (value&0xf)-(Apwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Apwrdelta)
+ t2 = ((value&0xf0)>>4)-(Apwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Apwrdelta)
+ t3 = ((value&0xf00)>>8)-(Apwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Apwrdelta)
+ t4 = ((value&0xf000)>>12)-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12);
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_40MHZ_5G + i*4 + 2, value);
+ if (bApwrdeltaMinus == FALSE)
+ {
+ t1 = (value&0xf)+(Apwrdelta);
+ if (t1 > 0xf)
+ t1 = 0xf;
+ t2 = ((value&0xf0)>>4)+(Apwrdelta);
+ if (t2 > 0xf)
+ t2 = 0xf;
+ t3 = ((value&0xf00)>>8)+(Apwrdelta);
+ if (t3 > 0xf)
+ t3 = 0xf;
+ t4 = ((value&0xf000)>>12)+(Apwrdelta);
+ if (t4 > 0xf)
+ t4 = 0xf;
+ }
+ else
+ {
+ if ((value&0xf) > Apwrdelta)
+ t1 = (value&0xf)-(Apwrdelta);
+ else
+ t1 = 0;
+ if (((value&0xf0)>>4) > Apwrdelta)
+ t2 = ((value&0xf0)>>4)-(Apwrdelta);
+ else
+ t2 = 0;
+ if (((value&0xf00)>>8) > Apwrdelta)
+ t3 = ((value&0xf00)>>8)-(Apwrdelta);
+ else
+ t3 = 0;
+ if (((value&0xf000)>>12) > Apwrdelta)
+ t4 = ((value&0xf000)>>12)-(Apwrdelta);
+ else
+ t4 = 0;
+ }
+ Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28));
+
+ if (i == 0)
+ pAd->Tx40MPwrCfgABand[i+1] = (pAd->Tx40MPwrCfgABand[i+1] & 0x0000FFFF) | (Adata & 0xFFFF0000);
+ else
+ pAd->Tx40MPwrCfgABand[i+1] = Adata;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("40MHz BW, 5GHz band, Adata = %lx \n", Adata));
+ }
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read initial channel power parameters from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPReadChannelPwr(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR i, choffset;
+ EEPROM_TX_PWR_STRUC Power;
+ EEPROM_TX_PWR_STRUC Power2;
+
+ // Read Tx power value for all channels
+ // Value from 1 - 0x7f. Default value is 24.
+ // Power value : 2.4G 0x00 (0) ~ 0x1F (31)
+ // : 5.5G 0xF9 (-7) ~ 0x0F (15)
+
+ // 0. 11b/g, ch1 - ch 14
+ for (i = 0; i < 7; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word);
+ pAd->TxPower[i * 2].Channel = i * 2 + 1;
+ pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2;
+
+ if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0))
+ pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER;
+ else
+ pAd->TxPower[i * 2].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0))
+ pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER;
+ else
+ pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0))
+ pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER;
+ else
+ pAd->TxPower[i * 2].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0))
+ pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER;
+ else
+ pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1;
+ }
+
+ // 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz)
+ // 1.1 Fill up channel
+ choffset = 14;
+ for (i = 0; i < 4; i++)
+ {
+ pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0;
+ pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2;
+ pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4;
+ pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
+ }
+
+ // 1.2 Fill up power
+ for (i = 0; i < 6; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word);
+
+ if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+ }
+
+ // 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz)
+ // 2.1 Fill up channel
+ choffset = 14 + 12;
+ for (i = 0; i < 5; i++)
+ {
+ pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0;
+ pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2;
+ pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4;
+ pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
+ }
+ pAd->TxPower[3 * 5 + choffset + 0].Channel = 140;
+ pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ // 2.2 Fill up power
+ for (i = 0; i < 8; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
+
+ if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+ }
+
+ // 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165 (including central frequency in BW 40MHz)
+ // 3.1 Fill up channel
+ choffset = 14 + 12 + 16;
+ for (i = 0; i < 2; i++)
+ {
+ pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0;
+ pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2;
+ pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER;
+
+ pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4;
+ pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER;
+ }
+ pAd->TxPower[3 * 2 + choffset + 0].Channel = 165;
+ pAd->TxPower[3 * 2 + choffset + 0].Power = DEFAULT_RF_TX_POWER;
+ pAd->TxPower[3 * 2 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER;
+
+ // 3.2 Fill up power
+ for (i = 0; i < 4; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word);
+
+ if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7))
+ pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7))
+ pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1;
+ }
+
+ // 4. Print and Debug
+ choffset = 14 + 12 + 16 + 7;
+
+
+#if 0
+ // Init the 802.11j channel number for TX channel power
+ // 0. 20MHz
+ for (i = 0; i < 3; i++)
+ {
+ pAd->TxPower11J[i].Channel = 8 + i * 4;
+ pAd->TxPower11J[i].BW = BW_20;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ pAd->TxPower11J[i + 3].Channel = 34 + i * 4;
+ pAd->TxPower11J[i + 3].BW = BW_20;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ pAd->TxPower11J[i + 7].Channel = 184 + i * 4;
+ pAd->TxPower11J[i + 7].BW = BW_20;
+ }
+
+ // 0. 10MHz
+ for (i = 0; i < 2; i++)
+ {
+ pAd->TxPower11J[i + 11].Channel = 7 + i;
+ pAd->TxPower11J[i + 11].BW = BW_10;
+ }
+ pAd->TxPower11J[13].Channel = 11;
+ pAd->TxPower11J[13].BW = BW_10;
+
+ for (i = 0; i < 3; i++)
+ {
+ pAd->TxPower11J[i + 14].Channel = 183 + i;
+ pAd->TxPower11J[i + 14].BW= BW_10;
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ pAd->TxPower11J[i + 17].Channel = 187 + i;
+ pAd->TxPower11J[i + 17].BW = BW_10;
+ }
+ for (i = 0; i < 10; i++)
+ {
+ Power.word = RTMP_EEPROM_READ16(pAd, EEPROM_Japan_TX_PWR_OFFSET + i * 2);
+ Power2.word = RTMP_EEPROM_READ16(pAd, EEPROM_Japan_TX2_PWR_OFFSET + i * 2);
+
+ if ((Power.field.Byte0 < 36) && (Power.field.Byte0 > -6))
+ pAd->TxPower11J[i * 2].Power = Power.field.Byte0;
+
+ if ((Power.field.Byte1 < 36) && (Power.field.Byte1 > -6))
+ pAd->TxPower11J[i * 2 + 1].Power = Power.field.Byte1;
+
+ if ((Power2.field.Byte0 < 36) && (Power2.field.Byte0 > -6))
+ pAd->TxPower11J[i * 2].Power2 = Power2.field.Byte0;
+
+ if ((Power2.field.Byte1 < 36) && (Power2.field.Byte1 > -6))
+ pAd->TxPower11J[i * 2 + 1].Power2 = Power2.field.Byte1;
+ }
+#endif
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read the following from the registry
+ 1. All the parameters
+ 2. NetworkAddres
+
+ Arguments:
+ Adapter Pointer to our adapter
+ WrapperConfigurationContext For use by NdisOpenConfiguration
+
+ Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_RESOURCES
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS NICReadRegParameters(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ )
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ DBGPRINT_S(Status, ("<-- NICReadRegParameters, Status=%x\n", Status));
+ return Status;
+}
+
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read initial parameters from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID NICReadEEPROMParameters(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR mac_addr)
+{
+ UINT32 data = 0;
+ USHORT i, value, value2;
+ UCHAR TmpPhy;
+ EEPROM_TX_PWR_STRUC Power;
+ EEPROM_VERSION_STRUC Version;
+ EEPROM_ANTENNA_STRUC Antenna;
+ EEPROM_NIC_CONFIG2_STRUC NicConfig2;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICReadEEPROMParameters\n"));
+
+ // Init EEPROM Address Number, before access EEPROM; if 93c46, EEPROMAddressNum=6, else if 93c66, EEPROMAddressNum=8
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &data);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> E2PROM_CSR = 0x%x\n", data));
+
+ if((data & 0x30) == 0)
+ pAd->EEPROMAddressNum = 6; // 93C46
+ else if((data & 0x30) == 0x10)
+ pAd->EEPROMAddressNum = 8; // 93C66
+ else
+ pAd->EEPROMAddressNum = 8; // 93C86
+ DBGPRINT(RT_DEBUG_TRACE, ("--> EEPROMAddressNum = %d\n", pAd->EEPROMAddressNum ));
+
+ // RT2860 MAC no longer auto load MAC address from E2PROM. Driver has to intialize
+ // MAC address registers according to E2PROM setting
+ if (mac_addr == NULL ||
+ strlen(mac_addr) != 17 ||
+ mac_addr[2] != ':' || mac_addr[5] != ':' || mac_addr[8] != ':' ||
+ mac_addr[11] != ':' || mac_addr[14] != ':')
+ {
+ USHORT Addr01,Addr23,Addr45 ;
+
+ RT28xx_EEPROM_READ16(pAd, 0x04, Addr01);
+ RT28xx_EEPROM_READ16(pAd, 0x06, Addr23);
+ RT28xx_EEPROM_READ16(pAd, 0x08, Addr45);
+
+ pAd->PermanentAddress[0] = (UCHAR)(Addr01 & 0xff);
+ pAd->PermanentAddress[1] = (UCHAR)(Addr01 >> 8);
+ pAd->PermanentAddress[2] = (UCHAR)(Addr23 & 0xff);
+ pAd->PermanentAddress[3] = (UCHAR)(Addr23 >> 8);
+ pAd->PermanentAddress[4] = (UCHAR)(Addr45 & 0xff);
+ pAd->PermanentAddress[5] = (UCHAR)(Addr45 >> 8);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from E2PROM \n"));
+ }
+ else
+ {
+ INT j;
+ PUCHAR macptr;
+
+ macptr = mac_addr;
+
+ for (j=0; j<MAC_ADDR_LEN; j++)
+ {
+ AtoH(macptr, &pAd->PermanentAddress[j], 1);
+ macptr=macptr+3;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Initialize MAC Address from module parameter \n"));
+ }
+
+
+ {
+ //more conveninet to test mbssid, so ap's bssid &0xf1
+ if (pAd->PermanentAddress[0] == 0xff)
+ pAd->PermanentAddress[0] = RandomByte(pAd)&0xf8;
+
+ //if (pAd->PermanentAddress[5] == 0xff)
+ // pAd->PermanentAddress[5] = RandomByte(pAd)&0xf8;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAd->PermanentAddress[0], pAd->PermanentAddress[1],
+ pAd->PermanentAddress[2], pAd->PermanentAddress[3],
+ pAd->PermanentAddress[4], pAd->PermanentAddress[5]));
+ if (pAd->bLocalAdminMAC == FALSE)
+ {
+ MAC_DW0_STRUC csr2;
+ MAC_DW1_STRUC csr3;
+ COPY_MAC_ADDR(pAd->CurrentAddress, pAd->PermanentAddress);
+ csr2.field.Byte0 = pAd->CurrentAddress[0];
+ csr2.field.Byte1 = pAd->CurrentAddress[1];
+ csr2.field.Byte2 = pAd->CurrentAddress[2];
+ csr2.field.Byte3 = pAd->CurrentAddress[3];
+ RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word);
+ csr3.word = 0;
+ csr3.field.Byte4 = pAd->CurrentAddress[4];
+ csr3.field.Byte5 = pAd->CurrentAddress[5];
+ csr3.field.U2MeMask = 0xff;
+ RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word);
+ DBGPRINT_RAW(RT_DEBUG_TRACE,("E2PROM MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAd->PermanentAddress[0], pAd->PermanentAddress[1],
+ pAd->PermanentAddress[2], pAd->PermanentAddress[3],
+ pAd->PermanentAddress[4], pAd->PermanentAddress[5]));
+ }
+ }
+
+ // if not return early. cause fail at emulation.
+ // Init the channel number for TX channel power
+ RTMPReadChannelPwr(pAd);
+
+ // if E2PROM version mismatch with driver's expectation, then skip
+ // all subsequent E2RPOM retieval and set a system error bit to notify GUI
+ RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word);
+ pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256;
+ DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber));
+
+ if (Version.field.Version > VALID_EEPROM_VERSION)
+ {
+ DBGPRINT_ERR(("E2PROM: WRONG VERSION 0x%x, should be %d\n",Version.field.Version, VALID_EEPROM_VERSION));
+ /*pAd->SystemErrorBitmap |= 0x00000001;
+
+ // hard-code default value when no proper E2PROM installed
+ pAd->bAutoTxAgcA = FALSE;
+ pAd->bAutoTxAgcG = FALSE;
+
+ // Default the channel power
+ for (i = 0; i < MAX_NUM_OF_CHANNELS; i++)
+ pAd->TxPower[i].Power = DEFAULT_RF_TX_POWER;
+
+ // Default the channel power
+ for (i = 0; i < MAX_NUM_OF_11JCHANNELS; i++)
+ pAd->TxPower11J[i].Power = DEFAULT_RF_TX_POWER;
+
+ for(i = 0; i < NUM_EEPROM_BBP_PARMS; i++)
+ pAd->EEPROMDefaultValue[i] = 0xffff;
+ return; */
+ }
+
+ // Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value);
+ pAd->EEPROMDefaultValue[0] = value;
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value);
+ pAd->EEPROMDefaultValue[1] = value;
+
+ RT28xx_EEPROM_READ16(pAd, 0x38, value); // Country Region
+ pAd->EEPROMDefaultValue[2] = value;
+
+ for(i = 0; i < 8; i++)
+ {
+ RT28xx_EEPROM_READ16(pAd, EEPROM_BBP_BASE_OFFSET + i*2, value);
+ pAd->EEPROMDefaultValue[i+3] = value;
+ }
+
+ // We have to parse NIC configuration 0 at here.
+ // If TSSI did not have preloaded value, it should reset the TxAutoAgc to false
+ // Therefore, we have to read TxAutoAgc control beforehand.
+ // Read Tx AGC control bit
+ Antenna.word = pAd->EEPROMDefaultValue[0];
+ if (Antenna.word == 0xFFFF)
+ {
+ Antenna.word = 0;
+ Antenna.field.RfIcType = RFIC_2820;
+ Antenna.field.TxPath = 1;
+ Antenna.field.RxPath = 2;
+ DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", Antenna.word));
+ }
+
+ // Choose the desired Tx&Rx stream.
+ if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath))
+ pAd->CommonCfg.TxStream = Antenna.field.TxPath;
+
+ if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath))
+ {
+ pAd->CommonCfg.RxStream = Antenna.field.RxPath;
+
+ if ((pAd->MACVersion < RALINK_2883_VERSION) &&
+ (pAd->CommonCfg.RxStream > 2))
+ {
+ // only 2 Rx streams for RT2860 series
+ pAd->CommonCfg.RxStream = 2;
+ }
+ }
+
+ // 3*3
+ // read value from EEPROM and set them to CSR174 ~ 177 in chain0 ~ chain2
+ // yet implement
+ for(i=0; i<3; i++)
+ {
+ }
+
+ NicConfig2.word = pAd->EEPROMDefaultValue[1];
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ NicConfig2.word = 0;
+ if ((NicConfig2.word & 0x00ff) == 0xff)
+ {
+ NicConfig2.word &= 0xff00;
+ }
+
+ if ((NicConfig2.word >> 8) == 0xff)
+ {
+ NicConfig2.word &= 0x00ff;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ if (NicConfig2.field.DynamicTxAgcControl == 1)
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
+ else
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("NICReadEEPROMParameters: RxPath = %d, TxPath = %d\n", Antenna.field.RxPath, Antenna.field.TxPath));
+
+ // Save the antenna for future use
+ pAd->Antenna.word = Antenna.word;
+
+ //
+ // Reset PhyMode if we don't support 802.11a
+ // Only RFIC_2850 & RFIC_2750 support 802.11a
+ //
+ if ((Antenna.field.RfIcType != RFIC_2850) && (Antenna.field.RfIcType != RFIC_2750))
+ {
+ if ((pAd->CommonCfg.PhyMode == PHY_11ABG_MIXED) ||
+ (pAd->CommonCfg.PhyMode == PHY_11A))
+ pAd->CommonCfg.PhyMode = PHY_11BG_MIXED;
+#ifdef DOT11_N_SUPPORT
+ else if ((pAd->CommonCfg.PhyMode == PHY_11ABGN_MIXED) ||
+ (pAd->CommonCfg.PhyMode == PHY_11AN_MIXED) ||
+ (pAd->CommonCfg.PhyMode == PHY_11AGN_MIXED) ||
+ (pAd->CommonCfg.PhyMode == PHY_11N_5G))
+ pAd->CommonCfg.PhyMode = PHY_11BGN_MIXED;
+#endif // DOT11_N_SUPPORT //
+ }
+
+ // Read TSSI reference and TSSI boundary for temperature compensation. This is ugly
+ // 0. 11b/g
+ {
+ /* these are tempature reference value (0x00 ~ 0xFE)
+ ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+ TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) +
+ TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */
+ RT28xx_EEPROM_READ16(pAd, 0x6E, Power.word);
+ pAd->TssiMinusBoundaryG[4] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryG[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0x70, Power.word);
+ pAd->TssiMinusBoundaryG[2] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryG[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0x72, Power.word);
+ pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */
+ pAd->TssiPlusBoundaryG[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0x74, Power.word);
+ pAd->TssiPlusBoundaryG[2] = Power.field.Byte0;
+ pAd->TssiPlusBoundaryG[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0x76, Power.word);
+ pAd->TssiPlusBoundaryG[4] = Power.field.Byte0;
+ pAd->TxAgcStepG = Power.field.Byte1;
+ pAd->TxAgcCompensateG = 0;
+ pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG;
+ pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG;
+
+ // Disable TxAgc if the based value is not right
+ if (pAd->TssiRefG == 0xff)
+ pAd->bAutoTxAgcG = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
+ pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1],
+ pAd->TssiRefG,
+ pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4],
+ pAd->TxAgcStepG, pAd->bAutoTxAgcG));
+ }
+ // 1. 11a
+ {
+ RT28xx_EEPROM_READ16(pAd, 0xD4, Power.word);
+ pAd->TssiMinusBoundaryA[4] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryA[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0xD6, Power.word);
+ pAd->TssiMinusBoundaryA[2] = Power.field.Byte0;
+ pAd->TssiMinusBoundaryA[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0xD8, Power.word);
+ pAd->TssiRefA = Power.field.Byte0;
+ pAd->TssiPlusBoundaryA[1] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0xDA, Power.word);
+ pAd->TssiPlusBoundaryA[2] = Power.field.Byte0;
+ pAd->TssiPlusBoundaryA[3] = Power.field.Byte1;
+ RT28xx_EEPROM_READ16(pAd, 0xDC, Power.word);
+ pAd->TssiPlusBoundaryA[4] = Power.field.Byte0;
+ pAd->TxAgcStepA = Power.field.Byte1;
+ pAd->TxAgcCompensateA = 0;
+ pAd->TssiMinusBoundaryA[0] = pAd->TssiRefA;
+ pAd->TssiPlusBoundaryA[0] = pAd->TssiRefA;
+
+ // Disable TxAgc if the based value is not right
+ if (pAd->TssiRefA == 0xff)
+ pAd->bAutoTxAgcA = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n",
+ pAd->TssiMinusBoundaryA[4], pAd->TssiMinusBoundaryA[3], pAd->TssiMinusBoundaryA[2], pAd->TssiMinusBoundaryA[1],
+ pAd->TssiRefA,
+ pAd->TssiPlusBoundaryA[1], pAd->TssiPlusBoundaryA[2], pAd->TssiPlusBoundaryA[3], pAd->TssiPlusBoundaryA[4],
+ pAd->TxAgcStepA, pAd->bAutoTxAgcA));
+ }
+ pAd->BbpRssiToDbmDelta = 0x0;
+
+ // Read frequency offset setting for RF
+ RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value);
+ if ((value & 0x00FF) != 0x00FF)
+ pAd->RfFreqOffset = (ULONG) (value & 0x00FF);
+ else
+ pAd->RfFreqOffset = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%lx \n", pAd->RfFreqOffset));
+
+ //CountryRegion byte offset (38h)
+ value = pAd->EEPROMDefaultValue[2] >> 8; // 2.4G band
+ value2 = pAd->EEPROMDefaultValue[2] & 0x00FF; // 5G band
+
+ if ((value <= REGION_MAXIMUM_BG_BAND) && (value2 <= REGION_MAXIMUM_A_BAND))
+ {
+ pAd->CommonCfg.CountryRegion = ((UCHAR) value) | 0x80;
+ pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | 0x80;
+ TmpPhy = pAd->CommonCfg.PhyMode;
+ pAd->CommonCfg.PhyMode = 0xff;
+ RTMPSetPhyMode(pAd, TmpPhy);
+#ifdef DOT11_N_SUPPORT
+ SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+ }
+
+ //
+ // Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch.
+ // The valid value are (-10 ~ 10)
+ //
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value);
+ pAd->BGRssiOffset0 = value & 0x00ff;
+ pAd->BGRssiOffset1 = (value >> 8);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value);
+ pAd->BGRssiOffset2 = value & 0x00ff;
+ pAd->ALNAGain1 = (value >> 8);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value);
+ pAd->BLNAGain = value & 0x00ff;
+ pAd->ALNAGain0 = (value >> 8);
+
+ // Validate 11b/g RSSI_0 offset.
+ if ((pAd->BGRssiOffset0 < -10) || (pAd->BGRssiOffset0 > 10))
+ pAd->BGRssiOffset0 = 0;
+
+ // Validate 11b/g RSSI_1 offset.
+ if ((pAd->BGRssiOffset1 < -10) || (pAd->BGRssiOffset1 > 10))
+ pAd->BGRssiOffset1 = 0;
+
+ // Validate 11b/g RSSI_2 offset.
+ if ((pAd->BGRssiOffset2 < -10) || (pAd->BGRssiOffset2 > 10))
+ pAd->BGRssiOffset2 = 0;
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value);
+ pAd->ARssiOffset0 = value & 0x00ff;
+ pAd->ARssiOffset1 = (value >> 8);
+ RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value);
+ pAd->ARssiOffset2 = value & 0x00ff;
+ pAd->ALNAGain2 = (value >> 8);
+
+ if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00))
+ pAd->ALNAGain1 = pAd->ALNAGain0;
+ if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00))
+ pAd->ALNAGain2 = pAd->ALNAGain0;
+
+ // Validate 11a RSSI_0 offset.
+ if ((pAd->ARssiOffset0 < -10) || (pAd->ARssiOffset0 > 10))
+ pAd->ARssiOffset0 = 0;
+
+ // Validate 11a RSSI_1 offset.
+ if ((pAd->ARssiOffset1 < -10) || (pAd->ARssiOffset1 > 10))
+ pAd->ARssiOffset1 = 0;
+
+ //Validate 11a RSSI_2 offset.
+ if ((pAd->ARssiOffset2 < -10) || (pAd->ARssiOffset2 > 10))
+ pAd->ARssiOffset2 = 0;
+
+ //
+ // Get LED Setting.
+ //
+ RT28xx_EEPROM_READ16(pAd, 0x3a, value);
+ pAd->LedCntl.word = (value&0xff00) >> 8;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_LED1_OFFSET, value);
+ pAd->Led1 = value;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_LED2_OFFSET, value);
+ pAd->Led2 = value;
+ RT28xx_EEPROM_READ16(pAd, EEPROM_LED3_OFFSET, value);
+ pAd->Led3 = value;
+
+ RTMPReadTxPwrPerRate(pAd);
+
+#ifdef SINGLE_SKU
+ //pAd->CommonCfg.DefineMaxTxPwr = RTMP_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR);
+ RT28xx_EEPROM_READ16(pAd, EEPROM_DEFINE_MAX_TXPWR, pAd->CommonCfg.DefineMaxTxPwr);
+#endif // SINGLE_SKU //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICReadEEPROMParameters\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set default value from EEPROM
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID NICInitAsicFromEEPROM(
+ IN PRTMP_ADAPTER pAd)
+{
+#ifdef CONFIG_STA_SUPPORT
+ UINT32 data = 0;
+ UCHAR BBPR1 = 0;
+#endif // CONFIG_STA_SUPPORT //
+ USHORT i;
+ EEPROM_ANTENNA_STRUC Antenna;
+ EEPROM_NIC_CONFIG2_STRUC NicConfig2;
+ UCHAR BBPR3 = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n"));
+ for(i = 3; i < NUM_EEPROM_BBP_PARMS; i++)
+ {
+ UCHAR BbpRegIdx, BbpValue;
+
+ if ((pAd->EEPROMDefaultValue[i] != 0xFFFF) && (pAd->EEPROMDefaultValue[i] != 0))
+ {
+ BbpRegIdx = (UCHAR)(pAd->EEPROMDefaultValue[i] >> 8);
+ BbpValue = (UCHAR)(pAd->EEPROMDefaultValue[i] & 0xff);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BbpRegIdx, BbpValue);
+ }
+ }
+
+ Antenna.word = pAd->Antenna.word;
+ pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath;
+ pAd->RfIcType = (UCHAR) Antenna.field.RfIcType;
+
+ NicConfig2.word = pAd->EEPROMDefaultValue[1];
+
+
+ // Save the antenna for future use
+ pAd->NicConfig2.word = NicConfig2.word;
+
+ //
+ // Send LED Setting to MCU.
+ //
+ if (pAd->LedCntl.word == 0xFF)
+ {
+ pAd->LedCntl.word = 0x01;
+ pAd->Led1 = 0x5555;
+ pAd->Led2 = 0x2221;
+
+#ifdef RT2860
+ pAd->Led3 = 0xA9F8;
+#endif // RT2860 //
+ }
+
+ AsicSendCommandToMcu(pAd, 0x52, 0xff, (UCHAR)pAd->Led1, (UCHAR)(pAd->Led1 >> 8));
+ AsicSendCommandToMcu(pAd, 0x53, 0xff, (UCHAR)pAd->Led2, (UCHAR)(pAd->Led2 >> 8));
+ AsicSendCommandToMcu(pAd, 0x54, 0xff, (UCHAR)pAd->Led3, (UCHAR)(pAd->Led3 >> 8));
+ pAd->LedIndicatorStregth = 0xFF;
+ RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, before link up
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Read Hardware controlled Radio state enable bit
+ if (NicConfig2.field.HardwareRadioControl == 1)
+ {
+ pAd->StaCfg.bHardwareRadio = TRUE;
+
+ // Read GPIO pin2 as Hardware controlled radio state
+ RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
+ if ((data & 0x04) == 0)
+ {
+ pAd->StaCfg.bHwRadio = FALSE;
+ pAd->StaCfg.bRadio = FALSE;
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+ }
+ }
+ else
+ pAd->StaCfg.bHardwareRadio = FALSE;
+
+ if (pAd->StaCfg.bRadio == FALSE)
+ {
+ RTMPSetLED(pAd, LED_RADIO_OFF);
+ }
+ else
+ {
+ RTMPSetLED(pAd, LED_RADIO_ON);
+#ifdef RT2860
+ AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
+ AsicSendCommandToMcu(pAd, 0x31, PowerWakeCID, 0x00, 0x00);
+ // 2-1. wait command ok.
+ AsicCheckCommanOk(pAd, PowerWakeCID);
+#endif // RT2860 //
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // Turn off patching for cardbus controller
+ if (NicConfig2.field.CardbusAcceleration == 1)
+ {
+ }
+
+ if (NicConfig2.field.DynamicTxAgcControl == 1)
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE;
+ else
+ pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE;
+ //
+ // Since BBP has been progamed, to make sure BBP setting will be
+ // upate inside of AsicAntennaSelect, so reset to UNKNOWN_BAND!!
+ //
+ pAd->CommonCfg.BandState = UNKNOWN_BAND;
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
+ BBPR3 &= (~0x18);
+ if(pAd->Antenna.field.RxPath == 3)
+ {
+ BBPR3 |= (0x10);
+ }
+ else if(pAd->Antenna.field.RxPath == 2)
+ {
+ BBPR3 |= (0x8);
+ }
+ else if(pAd->Antenna.field.RxPath == 1)
+ {
+ BBPR3 |= (0x0);
+ }
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Handle the difference when 1T
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBPR1);
+ if(pAd->Antenna.field.TxPath == 1)
+ {
+ BBPR1 &= (~0x18);
+ }
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BBPR1);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Use Hw Radio Control Pin=%d; if used Pin=%d;\n", pAd->CommonCfg.bHardwareRadio, pAd->CommonCfg.bHardwareRadio));
+ }
+#endif // CONFIG_STA_SUPPORT //
+ DBGPRINT(RT_DEBUG_TRACE, ("TxPath = %d, RxPath = %d, RFIC=%d, Polar+LED mode=%x\n", pAd->Antenna.field.TxPath, pAd->Antenna.field.RxPath, pAd->RfIcType, pAd->LedCntl.word));
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitAsicFromEEPROM\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Initialize NIC hardware
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS NICInitializeAdapter(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bHardReset)
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ WPDMA_GLO_CFG_STRUC GloCfg;
+#ifdef RT2860
+ UINT32 Value;
+ DELAY_INT_CFG_STRUC IntCfg;
+#endif // RT2860 //
+ ULONG i =0, j=0;
+ AC_TXOP_CSR0_STRUC csr0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAdapter\n"));
+
+ // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:
+retry:
+ i = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+ if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
+ break;
+
+ RTMPusecDelay(1000);
+ i++;
+ }while ( i<100);
+ DBGPRINT(RT_DEBUG_TRACE, ("<== DMA offset 0x208 = 0x%x\n", GloCfg.word));
+ GloCfg.word &= 0xff0;
+ GloCfg.field.EnTXWriteBackDDONE =1;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+
+ // Record HW Beacon offset
+ pAd->BeaconOffset[0] = HW_BEACON_BASE0;
+ pAd->BeaconOffset[1] = HW_BEACON_BASE1;
+ pAd->BeaconOffset[2] = HW_BEACON_BASE2;
+ pAd->BeaconOffset[3] = HW_BEACON_BASE3;
+ pAd->BeaconOffset[4] = HW_BEACON_BASE4;
+ pAd->BeaconOffset[5] = HW_BEACON_BASE5;
+ pAd->BeaconOffset[6] = HW_BEACON_BASE6;
+ pAd->BeaconOffset[7] = HW_BEACON_BASE7;
+
+ //
+ // write all shared Ring's base address into ASIC
+ //
+
+ // asic simulation sequence put this ahead before loading firmware.
+ // pbf hardware reset
+#ifdef RT2860
+ RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0x1003f); // 0x10000 for reset rx, 0x3f resets all 6 tx rings.
+ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f);
+ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00);
+#endif // RT2860 //
+
+ // Initialze ASIC for TX & Rx operation
+ if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS)
+ {
+ if (j++ == 0)
+ {
+ NICLoadFirmware(pAd);
+ goto retry;
+ }
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+#ifdef RT2860
+ // Write AC_BK base address register
+ Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BK].Cell[0].AllocPa);
+ RTMP_IO_WRITE32(pAd, TX_BASE_PTR1, Value);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR1 : 0x%x\n", Value));
+
+ // Write AC_BE base address register
+ Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_BE].Cell[0].AllocPa);
+ RTMP_IO_WRITE32(pAd, TX_BASE_PTR0, Value);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR0 : 0x%x\n", Value));
+
+ // Write AC_VI base address register
+ Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VI].Cell[0].AllocPa);
+ RTMP_IO_WRITE32(pAd, TX_BASE_PTR2, Value);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR2 : 0x%x\n", Value));
+
+ // Write AC_VO base address register
+ Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_AC_VO].Cell[0].AllocPa);
+ RTMP_IO_WRITE32(pAd, TX_BASE_PTR3, Value);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR3 : 0x%x\n", Value));
+
+ // Write HCCA base address register
+ Value = RTMP_GetPhysicalAddressLow(pAd->TxRing[QID_HCCA].Cell[0].AllocPa);
+ RTMP_IO_WRITE32(pAd, TX_BASE_PTR4, Value);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR4 : 0x%x\n", Value));
+
+ // Write MGMT_BASE_CSR register
+ Value = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa);
+ RTMP_IO_WRITE32(pAd, TX_BASE_PTR5, Value);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> TX_BASE_PTR5 : 0x%x\n", Value));
+
+ // Write RX_BASE_CSR register
+ Value = RTMP_GetPhysicalAddressLow(pAd->RxRing.Cell[0].AllocPa);
+ RTMP_IO_WRITE32(pAd, RX_BASE_PTR, Value);
+ DBGPRINT(RT_DEBUG_TRACE, ("--> RX_BASE_PTR : 0x%x\n", Value));
+
+ // Init RX Ring index pointer
+ pAd->RxRing.RxSwReadIdx = 0;
+ pAd->RxRing.RxCpuIdx = RX_RING_SIZE-1;
+ RTMP_IO_WRITE32(pAd, RX_CRX_IDX, pAd->RxRing.RxCpuIdx);
+
+ // Init TX rings index pointer
+ {
+ for (i=0; i<NUM_OF_TX_RING; i++)
+ {
+ pAd->TxRing[i].TxSwFreeIdx = 0;
+ pAd->TxRing[i].TxCpuIdx = 0;
+ RTMP_IO_WRITE32(pAd, (TX_CTX_IDX0 + i * 0x10) , pAd->TxRing[i].TxCpuIdx);
+ }
+ }
+
+ // init MGMT ring index pointer
+ pAd->MgmtRing.TxSwFreeIdx = 0;
+ pAd->MgmtRing.TxCpuIdx = 0;
+ RTMP_IO_WRITE32(pAd, TX_MGMTCTX_IDX, pAd->MgmtRing.TxCpuIdx);
+
+ //
+ // set each Ring's SIZE into ASIC. Descriptor Size is fixed by design.
+ //
+
+ // Write TX_RING_CSR0 register
+ Value = TX_RING_SIZE;
+ RTMP_IO_WRITE32(pAd, TX_MAX_CNT0, Value);
+ RTMP_IO_WRITE32(pAd, TX_MAX_CNT1, Value);
+ RTMP_IO_WRITE32(pAd, TX_MAX_CNT2, Value);
+ RTMP_IO_WRITE32(pAd, TX_MAX_CNT3, Value);
+ RTMP_IO_WRITE32(pAd, TX_MAX_CNT4, Value);
+ Value = MGMT_RING_SIZE;
+ RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, Value);
+
+ // Write RX_RING_CSR register
+ Value = RX_RING_SIZE;
+ RTMP_IO_WRITE32(pAd, RX_MAX_CNT, Value);
+#endif // RT2860 //
+
+
+ // WMM parameter
+ csr0.word = 0;
+ RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
+ if (pAd->CommonCfg.PhyMode == PHY_11B)
+ {
+ csr0.field.Ac0Txop = 192; // AC_VI: 192*32us ~= 6ms
+ csr0.field.Ac1Txop = 96; // AC_VO: 96*32us ~= 3ms
+ }
+ else
+ {
+ csr0.field.Ac0Txop = 96; // AC_VI: 96*32us ~= 3ms
+ csr0.field.Ac1Txop = 48; // AC_VO: 48*32us ~= 1.5ms
+ }
+ RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr0.word);
+
+
+#ifdef RT2860
+ // 3. Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits:
+ i = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word);
+ if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0))
+ break;
+
+ RTMPusecDelay(1000);
+ i++;
+ }while ( i < 100);
+
+ GloCfg.word &= 0xff0;
+ GloCfg.field.EnTXWriteBackDDONE =1;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word);
+
+ IntCfg.word = 0;
+ RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word);
+#endif // RT2860 //
+
+
+ // reset action
+ // Load firmware
+ // Status = NICLoadFirmware(pAd);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAdapter\n"));
+ return Status;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Initialize ASIC
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS NICInitializeAsic(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bHardReset)
+{
+ ULONG Index = 0;
+ UCHAR R0 = 0xff;
+ UINT32 MacCsr12 = 0, Counter = 0;
+ USHORT KeyIdx;
+ INT i,apidx;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n"));
+
+#ifdef RT2860
+ if (bHardReset == TRUE)
+ {
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x3);
+ }
+ else
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
+
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
+ // Initialize MAC register to default value
+ for (Index = 0; Index < NUM_MAC_REG_PARMS; Index++)
+ {
+ RTMP_IO_WRITE32(pAd, MACRegTable[Index].Register, MACRegTable[Index].Value);
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ for (Index = 0; Index < NUM_STA_MAC_REG_PARMS; Index++)
+ {
+ RTMP_IO_WRITE32(pAd, STAMACRegTable[Index].Register, STAMACRegTable[Index].Value);
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+#endif // RT2860 //
+
+
+ //
+ // Before program BBP, we need to wait BBP/RF get wake up.
+ //
+ Index = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacCsr12);
+
+ if ((MacCsr12 & 0x03) == 0) // if BB.RF is stable
+ break;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Check MAC_STATUS_CFG = Busy = %x\n", MacCsr12));
+ RTMPusecDelay(1000);
+ } while (Index++ < 100);
+
+ // The commands to firmware should be after these commands, these commands will init firmware
+ // PCI and USB are not the same because PCI driver needs to wait for PCI bus ready
+ RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0); // initialize BBP R/W access agent
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0);
+ RTMPusecDelay(1000);
+
+ // Read BBP register, make sure BBP is up and running before write new data
+ Index = 0;
+ do
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R0, &R0);
+ DBGPRINT(RT_DEBUG_TRACE, ("BBP version = %x\n", R0));
+ } while ((++Index < 20) && ((R0 == 0xff) || (R0 == 0x00)));
+ //ASSERT(Index < 20); //this will cause BSOD on Check-build driver
+
+ if ((R0 == 0xff) || (R0 == 0x00))
+ return NDIS_STATUS_FAILURE;
+
+ // Initialize BBP register to default value
+ for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, BBPRegTable[Index].Value);
+ }
+
+ // for rt2860E and after, init BBP_R84 with 0x19. This is for extension channel overlapping IOT.
+ if ((pAd->MACVersion&0xffff) != 0x0101)
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R84, 0x19);
+
+
+ if (pAd->MACVersion == 0x28600100)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x12);
+ }
+
+ if (pAd->MACVersion >= RALINK_2880E_VERSION && pAd->MACVersion < RALINK_3070_VERSION) // 3*3
+ {
+ // enlarge MAX_LEN_CFG
+ UINT32 csr;
+ RTMP_IO_READ32(pAd, MAX_LEN_CFG, &csr);
+ csr &= 0xFFF;
+ csr |= 0x2000;
+ RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, csr);
+ }
+
+
+ // Add radio off control
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if (pAd->StaCfg.bRadio == FALSE)
+ {
+// RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x00001818);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
+ DBGPRINT(RT_DEBUG_TRACE, ("Set Radio Off\n"));
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // Clear raw counters
+ RTMP_IO_READ32(pAd, RX_STA_CNT0, &Counter);
+ RTMP_IO_READ32(pAd, RX_STA_CNT1, &Counter);
+ RTMP_IO_READ32(pAd, RX_STA_CNT2, &Counter);
+ RTMP_IO_READ32(pAd, TX_STA_CNT0, &Counter);
+ RTMP_IO_READ32(pAd, TX_STA_CNT1, &Counter);
+ RTMP_IO_READ32(pAd, TX_STA_CNT2, &Counter);
+
+ // ASIC will keep garbage value after boot
+ // Clear all seared key table when initial
+ // This routine can be ignored in radio-ON/OFF operation.
+ if (bHardReset)
+ {
+ for (KeyIdx = 0; KeyIdx < 4; KeyIdx++)
+ {
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4*KeyIdx, 0);
+ }
+
+ // Clear all pairwise key table when initial
+ for (KeyIdx = 0; KeyIdx < 256; KeyIdx++)
+ {
+ RTMP_IO_WRITE32(pAd, MAC_WCID_ATTRIBUTE_BASE + (KeyIdx * HW_WCID_ATTRI_SIZE), 1);
+ }
+ }
+
+
+ // It isn't necessary to clear this space when not hard reset.
+ if (bHardReset == TRUE)
+ {
+ // clear all on-chip BEACON frame space
+ for (apidx = 0; apidx < HW_BEACON_MAX_COUNT; apidx++)
+ {
+ for (i = 0; i < HW_BEACON_OFFSET>>2; i+=4)
+ RTMP_IO_WRITE32(pAd, pAd->BeaconOffset[apidx] + i, 0x00);
+ }
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // for rt2860E and after, init TXOP_CTRL_CFG with 0x583f. This is for extension channel overlapping IOT.
+ if ((pAd->MACVersion&0xffff) != 0x0101)
+ RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x583f);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n"));
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Reset NIC Asics
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+ Reset NIC to initial state AS IS system boot up time.
+
+ ========================================================================
+*/
+VOID NICIssueReset(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 Value = 0;
+ DBGPRINT(RT_DEBUG_TRACE, ("--> NICIssueReset\n"));
+
+ // Disable Rx, register value supposed will remain after reset
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= (0xfffffff3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+ // Issue reset and clear from reset state
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x03); // 2004-09-17 change from 0x01
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- NICIssueReset\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Check ASIC registers and find any reason the system might hang
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+BOOLEAN NICCheckForHang(
+ IN PRTMP_ADAPTER pAd)
+{
+ return (FALSE);
+}
+
+VOID NICUpdateFifoStaCounters(
+ IN PRTMP_ADAPTER pAd)
+{
+ TX_STA_FIFO_STRUC StaFifo;
+ MAC_TABLE_ENTRY *pEntry;
+ UCHAR i = 0;
+ UCHAR pid = 0, wcid = 0;
+ CHAR reTry;
+ UCHAR succMCS;
+
+#ifdef RALINK_ATE
+ /* Nothing to do in ATE mode */
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+ do
+ {
+ RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word);
+
+ if (StaFifo.field.bValid == 0)
+ break;
+
+ wcid = (UCHAR)StaFifo.field.wcid;
+
+
+ /* ignore NoACK and MGMT frame use 0xFF as WCID */
+ if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE))
+ {
+ i++;
+ continue;
+ }
+
+ /* PID store Tx MCS Rate */
+ pid = (UCHAR)StaFifo.field.PidType;
+
+ pEntry = &pAd->MacTab.Content[wcid];
+
+ pEntry->DebugFIFOCount++;
+
+#ifdef DOT11_N_SUPPORT
+ if (StaFifo.field.TxBF) // 3*3
+ pEntry->TxBFCount++;
+#endif // DOT11_N_SUPPORT //
+
+#ifdef UAPSD_AP_SUPPORT
+ UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess);
+#endif // UAPSD_AP_SUPPORT //
+
+ if (!StaFifo.field.TxSuccess)
+ {
+ pEntry->FIFOCount++;
+ pEntry->OneSecTxFailCount++;
+
+ if (pEntry->FIFOCount >= 1)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("#"));
+#if 0
+ SendRefreshBAR(pAd, pEntry);
+ pEntry->NoBADataCountDown = 64;
+#else
+#ifdef DOT11_N_SUPPORT
+ pEntry->NoBADataCountDown = 64;
+#endif // DOT11_N_SUPPORT //
+
+ if(pEntry->PsMode == PWR_ACTIVE)
+ {
+#ifdef DOT11_N_SUPPORT
+ int tid;
+ for (tid=0; tid<NUM_OF_TID; tid++)
+ {
+ BAOriSessionTearDown(pAd, pEntry->Aid, tid, FALSE, FALSE);
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // Update the continuous transmission counter except PS mode
+ pEntry->ContinueTxFailCnt++;
+ }
+ else
+ {
+ // Clear the FIFOCount when sta in Power Save mode. Basically we assume
+ // this tx error happened due to sta just go to sleep.
+ pEntry->FIFOCount = 0;
+ pEntry->ContinueTxFailCnt = 0;
+ }
+#endif
+ //pEntry->FIFOCount = 0;
+ }
+ //pEntry->bSendBAR = TRUE;
+ }
+ else
+ {
+#ifdef DOT11_N_SUPPORT
+ if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0))
+ {
+ pEntry->NoBADataCountDown--;
+ if (pEntry->NoBADataCountDown==0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("@\n"));
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+ pEntry->FIFOCount = 0;
+ pEntry->OneSecTxNoRetryOkCount++;
+ // update NoDataIdleCount when sucessful send packet to STA.
+ pEntry->NoDataIdleCount = 0;
+ pEntry->ContinueTxFailCnt = 0;
+ }
+
+ succMCS = StaFifo.field.SuccessRate & 0x7F;
+
+ reTry = pid - succMCS;
+
+ if (StaFifo.field.TxSuccess)
+ {
+ pEntry->TXMCSExpected[pid]++;
+ if (pid == succMCS)
+ {
+ pEntry->TXMCSSuccessful[pid]++;
+ }
+ else
+ {
+ pEntry->TXMCSAutoFallBack[pid][succMCS]++;
+ }
+ }
+ else
+ {
+ pEntry->TXMCSFailed[pid]++;
+ }
+
+ if (reTry > 0)
+ {
+ if ((pid >= 12) && succMCS <=7)
+ {
+ reTry -= 4;
+ }
+ pEntry->OneSecTxRetryOkCount += reTry;
+ }
+
+ i++;
+ // ASIC store 16 stack
+ } while ( i < (2*TX_RING_SIZE) );
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Read statistical counters from hardware registers and record them
+ in software variables for later on query
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID NICUpdateRawCounters(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 OldValue;
+ RX_STA_CNT0_STRUC RxStaCnt0;
+ RX_STA_CNT1_STRUC RxStaCnt1;
+ RX_STA_CNT2_STRUC RxStaCnt2;
+ TX_STA_CNT0_STRUC TxStaCnt0;
+ TX_STA_CNT1_STRUC StaTx1;
+ TX_STA_CNT2_STRUC StaTx2;
+ TX_AGG_CNT_STRUC TxAggCnt;
+ TX_AGG_CNT0_STRUC TxAggCnt0;
+ TX_AGG_CNT1_STRUC TxAggCnt1;
+ TX_AGG_CNT2_STRUC TxAggCnt2;
+ TX_AGG_CNT3_STRUC TxAggCnt3;
+ TX_AGG_CNT4_STRUC TxAggCnt4;
+ TX_AGG_CNT5_STRUC TxAggCnt5;
+ TX_AGG_CNT6_STRUC TxAggCnt6;
+ TX_AGG_CNT7_STRUC TxAggCnt7;
+
+ RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word);
+ RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word);
+
+ {
+ RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word);
+ // Update RX PLCP error counter
+ pAd->PrivateInfo.PhyRxErrCnt += RxStaCnt1.field.PlcpErr;
+ // Update False CCA counter
+ pAd->RalinkCounters.OneSecFalseCCACnt += RxStaCnt1.field.FalseCca;
+ }
+
+ // Update FCS counters
+ OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart;
+ pAd->WlanCounters.FCSErrorCount.u.LowPart += (RxStaCnt0.field.CrcErr); // >> 7);
+ if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue)
+ pAd->WlanCounters.FCSErrorCount.u.HighPart++;
+
+ // Add FCS error count to private counters
+ pAd->RalinkCounters.OneSecRxFcsErrCnt += RxStaCnt0.field.CrcErr;
+ OldValue = pAd->RalinkCounters.RealFcsErrCount.u.LowPart;
+ pAd->RalinkCounters.RealFcsErrCount.u.LowPart += RxStaCnt0.field.CrcErr;
+ if (pAd->RalinkCounters.RealFcsErrCount.u.LowPart < OldValue)
+ pAd->RalinkCounters.RealFcsErrCount.u.HighPart++;
+
+ // Update Duplicate Rcv check
+ pAd->RalinkCounters.DuplicateRcv += RxStaCnt2.field.RxDupliCount;
+ pAd->WlanCounters.FrameDuplicateCount.u.LowPart += RxStaCnt2.field.RxDupliCount;
+ // Update RX Overflow counter
+ pAd->Counters8023.RxNoBuffer += (RxStaCnt2.field.RxFifoOverflowCount);
+
+ if (!pAd->bUpdateBcnCntDone)
+ {
+ // Update BEACON sent count
+ RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
+ RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
+ RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word);
+ pAd->RalinkCounters.OneSecBeaconSentCnt += TxStaCnt0.field.TxBeaconCount;
+ pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
+ pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
+ pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
+ pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
+ pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
+ pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
+ }
+
+ {
+ RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word);
+ RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word);
+ pAd->RalinkCounters.TxAggCount += TxAggCnt.field.AggTxCount;
+ pAd->RalinkCounters.TxNonAggCount += TxAggCnt.field.NonAggTxCount;
+ pAd->RalinkCounters.TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count;
+ pAd->RalinkCounters.TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count;
+
+ pAd->RalinkCounters.TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count;
+ pAd->RalinkCounters.TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count;
+ pAd->RalinkCounters.TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count;
+ pAd->RalinkCounters.TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count;
+
+ pAd->RalinkCounters.TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count;
+ pAd->RalinkCounters.TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count;
+ pAd->RalinkCounters.TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count;
+ pAd->RalinkCounters.TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count;
+
+ pAd->RalinkCounters.TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count;
+ pAd->RalinkCounters.TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count;
+ pAd->RalinkCounters.TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count;
+ pAd->RalinkCounters.TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count;
+
+ pAd->RalinkCounters.TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count;
+ pAd->RalinkCounters.TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count;
+
+ // Calculate the transmitted A-MPDU count
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count;
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count / 2);
+
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3);
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count / 4);
+
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5);
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6);
+
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7);
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count / 8);
+
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9);
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10);
+
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11);
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12);
+
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13);
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14);
+
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15);
+ pAd->RalinkCounters.TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count / 16);
+ }
+
+#ifdef DBG_DIAGNOSE
+ {
+ RtmpDiagStruct *pDiag;
+ COUNTER_RALINK *pRalinkCounters;
+ UCHAR ArrayCurIdx, i;
+
+ pDiag = &pAd->DiagStruct;
+ pRalinkCounters = &pAd->RalinkCounters;
+ ArrayCurIdx = pDiag->ArrayCurIdx;
+
+ if (pDiag->inited == 0)
+ {
+ NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_));
+ pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0;
+ pDiag->inited = 1;
+ }
+ else
+ {
+ // Tx
+ pDiag->TxFailCnt[ArrayCurIdx] = TxStaCnt0.field.TxFailCount;
+ pDiag->TxAggCnt[ArrayCurIdx] = TxAggCnt.field.AggTxCount;
+ pDiag->TxNonAggCnt[ArrayCurIdx] = TxAggCnt.field.NonAggTxCount;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][0] = TxAggCnt0.field.AggSize1Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][1] = TxAggCnt0.field.AggSize2Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][2] = TxAggCnt1.field.AggSize3Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][3] = TxAggCnt1.field.AggSize4Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][4] = TxAggCnt2.field.AggSize5Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][5] = TxAggCnt2.field.AggSize6Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][6] = TxAggCnt3.field.AggSize7Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][7] = TxAggCnt3.field.AggSize8Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][8] = TxAggCnt4.field.AggSize9Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][9] = TxAggCnt4.field.AggSize10Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][10] = TxAggCnt5.field.AggSize11Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][11] = TxAggCnt5.field.AggSize12Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][12] = TxAggCnt6.field.AggSize13Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][13] = TxAggCnt6.field.AggSize14Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][14] = TxAggCnt7.field.AggSize15Count;
+ pDiag->TxAMPDUCnt[ArrayCurIdx][15] = TxAggCnt7.field.AggSize16Count;
+
+ pDiag->RxCrcErrCnt[ArrayCurIdx] = RxStaCnt0.field.CrcErr;
+
+ INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME);
+ ArrayCurIdx = pDiag->ArrayCurIdx;
+ for (i =0; i < 9; i++)
+ {
+ pDiag->TxDescCnt[ArrayCurIdx][i]= 0;
+ pDiag->TxSWQueCnt[ArrayCurIdx][i] =0;
+ pDiag->TxMcsCnt[ArrayCurIdx][i] = 0;
+ pDiag->RxMcsCnt[ArrayCurIdx][i] = 0;
+ }
+ pDiag->TxDataCnt[ArrayCurIdx] = 0;
+ pDiag->TxFailCnt[ArrayCurIdx] = 0;
+ pDiag->RxDataCnt[ArrayCurIdx] = 0;
+ pDiag->RxCrcErrCnt[ArrayCurIdx] = 0;
+ for (i = 9; i < 24; i++) // 3*3
+ {
+ pDiag->TxDescCnt[ArrayCurIdx][i] = 0;
+ pDiag->TxMcsCnt[ArrayCurIdx][i] = 0;
+ pDiag->RxMcsCnt[ArrayCurIdx][i] = 0;
+}
+
+ if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx)
+ INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME);
+ }
+
+ }
+#endif // DBG_DIAGNOSE //
+
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Reset NIC from error
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+ Reset NIC from error state
+
+ ========================================================================
+*/
+VOID NICResetFromError(
+ IN PRTMP_ADAPTER pAd)
+{
+ // Reset BBP (according to alex, reset ASIC will force reset BBP
+ // Therefore, skip the reset BBP
+ // RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2);
+
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
+ // Remove ASIC from reset state
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
+
+ NICInitializeAdapter(pAd, FALSE);
+ NICInitAsicFromEEPROM(pAd);
+
+ // Switch to current channel, since during reset process, the connection should remains on.
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ erase 8051 firmware image in MAC ASIC
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+VOID NICEraseFirmware(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG i;
+
+ for(i=0; i<MAX_FIRMWARE_IMAGE_SIZE; i+=4)
+ RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, 0);
+
+}/* End of NICEraseFirmware */
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Load 8051 firmware RT2561.BIN file into MAC ASIC
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ NDIS_STATUS_SUCCESS firmware image load ok
+ NDIS_STATUS_FAILURE image not found
+
+ IRQL = PASSIVE_LEVEL
+
+ ========================================================================
+*/
+NDIS_STATUS NICLoadFirmware(
+ IN PRTMP_ADAPTER pAd)
+{
+#ifdef BIN_IN_FILE
+#define NICLF_DEFAULT_USE() \
+ flg_default_firm_use = TRUE; \
+ printk("%s - Use default firmware!\n", __func__);
+
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PUCHAR src;
+ struct file *srcf;
+ INT retval, orgfsuid, orgfsgid, i;
+ mm_segment_t orgfs;
+ PUCHAR pFirmwareImage;
+ UINT FileLength = 0;
+ UINT32 MacReg;
+ ULONG Index;
+ ULONG firm;
+ BOOLEAN flg_default_firm_use = FALSE;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> %s\n", __func__));
+
+ /* init */
+ pFirmwareImage = NULL;
+ src = RTMP_FIRMWARE_FILE_NAME;
+
+ /* save uid and gid used for filesystem access.
+ set user and group to 0 (root) */
+ orgfsuid = current->fsuid;
+ orgfsgid = current->fsgid;
+ current->fsuid = current->fsgid = 0;
+ orgfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ pAd->FirmwareVersion = (FIRMWARE_MAJOR_VERSION << 8) + \
+ FIRMWARE_MINOR_VERSION;
+
+
+ /* allocate firmware buffer */
+ pFirmwareImage = kmalloc(MAX_FIRMWARE_IMAGE_SIZE, MEM_ALLOC_FLAG);
+ if (pFirmwareImage == NULL)
+ {
+ /* allocate fail, use default firmware array in firmware.h */
+ printk("%s - Allocate memory fail!\n", __func__);
+ NICLF_DEFAULT_USE();
+ }
+ else
+ {
+ /* allocate ok! zero the firmware buffer */
+ memset(pFirmwareImage, 0x00, MAX_FIRMWARE_IMAGE_SIZE);
+ } /* End of if */
+
+
+ /* if ok, read firmware file from *.bin file */
+ if (flg_default_firm_use == FALSE)
+ {
+ do
+ {
+ /* open the bin file */
+ srcf = filp_open(src, O_RDONLY, 0);
+
+ if (IS_ERR(srcf))
+ {
+ printk("%s - Error %ld opening %s\n",
+ __func__, -PTR_ERR(srcf), src);
+ NICLF_DEFAULT_USE();
+ break;
+ } /* End of if */
+
+ /* the object must have a read method */
+ if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL))
+ {
+ printk("%s - %s does not have a write method\n", __func__, src);
+ NICLF_DEFAULT_USE();
+ break;
+ } /* End of if */
+
+ /* read the firmware from the file *.bin */
+ FileLength = srcf->f_op->read(srcf,
+ pFirmwareImage,
+ MAX_FIRMWARE_IMAGE_SIZE,
+ &srcf->f_pos);
+
+ if (FileLength != MAX_FIRMWARE_IMAGE_SIZE)
+ {
+ printk("%s: error file length (=%d) in RT2860AP.BIN\n",
+ __func__, FileLength);
+ NICLF_DEFAULT_USE();
+ break;
+ }
+ else
+ {
+ PUCHAR ptr = pFirmwareImage;
+ USHORT crc = 0xffff;
+
+
+ /* calculate firmware CRC */
+ for(i=0; i<(MAX_FIRMWARE_IMAGE_SIZE-2); i++, ptr++)
+ crc = ByteCRC16(bitrev8(*ptr), crc);
+ /* End of for */
+
+ if ((pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2] != \
+ (UCHAR)bitrev8((UCHAR)(crc>>8))) ||
+ (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1] != \
+ (UCHAR)bitrev8((UCHAR)crc)))
+ {
+ /* CRC fail */
+ printk("%s: CRC = 0x%02x 0x%02x "
+ "error, should be 0x%02x 0x%02x\n",
+ __func__,
+ pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-2],
+ pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-1],
+ (UCHAR)(crc>>8), (UCHAR)(crc));
+ NICLF_DEFAULT_USE();
+ break;
+ }
+ else
+ {
+ /* firmware is ok */
+ pAd->FirmwareVersion = \
+ (pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4] << 8) +
+ pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3];
+
+ /* check if firmware version of the file is too old */
+ if ((pAd->FirmwareVersion) < \
+ ((FIRMWARE_MAJOR_VERSION << 8) +
+ FIRMWARE_MINOR_VERSION))
+ {
+ printk("%s: firmware version too old!\n", __func__);
+ NICLF_DEFAULT_USE();
+ break;
+ } /* End of if */
+ } /* End of if */
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("NICLoadFirmware: CRC ok, ver=%d.%d\n",
+ pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-4],
+ pFirmwareImage[MAX_FIRMWARE_IMAGE_SIZE-3]));
+ } /* End of if (FileLength == MAX_FIRMWARE_IMAGE_SIZE) */
+ break;
+ } while(TRUE);
+
+ /* close firmware file */
+ if (IS_ERR(srcf))
+ ;
+ else
+ {
+ retval = filp_close(srcf, NULL);
+ if (retval)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("--> Error %d closing %s\n", -retval, src));
+ } /* End of if */
+ } /* End of if */
+ } /* End of if */
+
+
+ /* write firmware to ASIC */
+ if (flg_default_firm_use == TRUE)
+ {
+ /* use default fimeware, free allocated buffer */
+ if (pFirmwareImage != NULL)
+ kfree(pFirmwareImage);
+ /* End of if */
+
+ /* use default *.bin array */
+ pFirmwareImage = FirmwareImage;
+ FileLength = sizeof(FirmwareImage);
+ } /* End of if */
+
+ /* enable Host program ram write selection */
+ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x10000);
+
+ for(i=0; i<FileLength; i+=4)
+ {
+ firm = pFirmwareImage[i] +
+ (pFirmwareImage[i+3] << 24) +
+ (pFirmwareImage[i+2] << 16) +
+ (pFirmwareImage[i+1] << 8);
+
+ RTMP_IO_WRITE32(pAd, FIRMWARE_IMAGE_BASE + i, firm);
+ } /* End of for */
+
+ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00000);
+ RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0x00001);
+
+ /* initialize BBP R/W access agent */
+ RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, 0);
+ RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, 0);
+
+ if (flg_default_firm_use == FALSE)
+ {
+ /* use file firmware, free allocated buffer */
+ if (pFirmwareImage != NULL)
+ kfree(pFirmwareImage);
+ /* End of if */
+ } /* End of if */
+
+ set_fs(orgfs);
+ current->fsuid = orgfsuid;
+ current->fsgid = orgfsgid;
+#else
+
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PUCHAR pFirmwareImage;
+ ULONG FileLength, Index;
+ //ULONG firm;
+ UINT32 MacReg = 0;
+
+ pFirmwareImage = FirmwareImage;
+ FileLength = sizeof(FirmwareImage);
+ RT28XX_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength);
+#endif
+
+ /* check if MCU is ready */
+ Index = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &MacReg);
+
+ if (MacReg & 0x80)
+ break;
+
+ RTMPusecDelay(1000);
+ } while (Index++ < 1000);
+
+ if (Index >= 1000)
+ {
+ Status = NDIS_STATUS_FAILURE;
+ DBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware: MCU is not ready\n\n\n"));
+ } /* End of if */
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("<=== %s (status=%d)\n", __func__, Status));
+ return Status;
+} /* End of NICLoadFirmware */
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Load Tx rate switching parameters
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ NDIS_STATUS_SUCCESS firmware image load ok
+ NDIS_STATUS_FAILURE image not found
+
+ IRQL = PASSIVE_LEVEL
+
+ Rate Table Format:
+ 1. (B0: Valid Item number) (B1:Initial item from zero)
+ 2. Item Number(Dec) Mode(Hex) Current MCS(Dec) TrainUp(Dec) TrainDown(Dec)
+
+ ========================================================================
+*/
+NDIS_STATUS NICLoadRateSwitchingParams(
+ IN PRTMP_ADAPTER pAd)
+{
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ if pSrc1 all zero with length Length, return 0.
+ If not all zero, return 1
+
+ Arguments:
+ pSrc1
+
+ Return Value:
+ 1: not all zero
+ 0: all zero
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+ULONG RTMPNotAllZero(
+ IN PVOID pSrc1,
+ IN ULONG Length)
+{
+ PUCHAR pMem1;
+ ULONG Index = 0;
+
+ pMem1 = (PUCHAR) pSrc1;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ if (pMem1[Index] != 0x0)
+ {
+ break;
+ }
+ }
+
+ if (Index == Length)
+ {
+ return (0);
+ }
+ else
+ {
+ return (1);
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Compare two memory block
+
+ Arguments:
+ pSrc1 Pointer to first memory address
+ pSrc2 Pointer to second memory address
+
+ Return Value:
+ 0: memory is equal
+ 1: pSrc1 memory is larger
+ 2: pSrc2 memory is larger
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+ULONG RTMPCompareMemory(
+ IN PVOID pSrc1,
+ IN PVOID pSrc2,
+ IN ULONG Length)
+{
+ PUCHAR pMem1;
+ PUCHAR pMem2;
+ ULONG Index = 0;
+
+ pMem1 = (PUCHAR) pSrc1;
+ pMem2 = (PUCHAR) pSrc2;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ if (pMem1[Index] > pMem2[Index])
+ return (1);
+ else if (pMem1[Index] < pMem2[Index])
+ return (2);
+ }
+
+ // Equal
+ return (0);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Zero out memory block
+
+ Arguments:
+ pSrc1 Pointer to memory address
+ Length Size
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPZeroMemory(
+ IN PVOID pSrc,
+ IN ULONG Length)
+{
+ PUCHAR pMem;
+ ULONG Index = 0;
+
+ pMem = (PUCHAR) pSrc;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ pMem[Index] = 0x00;
+ }
+}
+
+VOID RTMPFillMemory(
+ IN PVOID pSrc,
+ IN ULONG Length,
+ IN UCHAR Fill)
+{
+ PUCHAR pMem;
+ ULONG Index = 0;
+
+ pMem = (PUCHAR) pSrc;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ pMem[Index] = Fill;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy data from memory block 1 to memory block 2
+
+ Arguments:
+ pDest Pointer to destination memory address
+ pSrc Pointer to source memory address
+ Length Copy size
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPMoveMemory(
+ OUT PVOID pDest,
+ IN PVOID pSrc,
+ IN ULONG Length)
+{
+ PUCHAR pMem1;
+ PUCHAR pMem2;
+ UINT Index;
+
+ ASSERT((Length==0) || (pDest && pSrc));
+
+ pMem1 = (PUCHAR) pDest;
+ pMem2 = (PUCHAR) pSrc;
+
+ for (Index = 0; Index < Length; Index++)
+ {
+ pMem1[Index] = pMem2[Index];
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Initialize port configuration structure
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID UserCfgInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT key_index, bss_index;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit\n"));
+
+ //
+ // part I. intialize common configuration
+ //
+
+ for(key_index=0; key_index<SHARE_KEY_NUM; key_index++)
+ {
+ for(bss_index = 0; bss_index < MAX_MBSSID_NUM; bss_index++)
+ {
+ pAd->SharedKey[bss_index][key_index].KeyLen = 0;
+ pAd->SharedKey[bss_index][key_index].CipherAlg = CIPHER_NONE;
+ }
+ }
+
+ pAd->Antenna.word = 0;
+ pAd->CommonCfg.BBPCurrentBW = BW_20;
+
+ pAd->LedCntl.word = 0;
+#ifdef RT2860
+ pAd->LedIndicatorStregth = 0;
+ pAd->RLnkCtrlOffset = 0;
+ pAd->HostLnkCtrlOffset = 0;
+#endif // RT2860 //
+
+ pAd->bAutoTxAgcA = FALSE; // Default is OFF
+ pAd->bAutoTxAgcG = FALSE; // Default is OFF
+ pAd->RfIcType = RFIC_2820;
+
+ // Init timer for reset complete event
+ pAd->CommonCfg.CentralChannel = 1;
+ pAd->bForcePrintTX = FALSE;
+ pAd->bForcePrintRX = FALSE;
+ pAd->bStaFifoTest = FALSE;
+ pAd->bProtectionTest = FALSE;
+ pAd->bHCCATest = FALSE;
+ pAd->bGenOneHCCA = FALSE;
+ pAd->CommonCfg.Dsifs = 10; // in units of usec
+ pAd->CommonCfg.TxPower = 100; //mW
+ pAd->CommonCfg.TxPowerPercentage = 0xffffffff; // AUTO
+ pAd->CommonCfg.TxPowerDefault = 0xffffffff; // AUTO
+ pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; // use Long preamble on TX by defaut
+ pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+ pAd->CommonCfg.RtsThreshold = 2347;
+ pAd->CommonCfg.FragmentThreshold = 2346;
+ pAd->CommonCfg.UseBGProtection = 0; // 0: AUTO
+ pAd->CommonCfg.bEnableTxBurst = TRUE; //0;
+ pAd->CommonCfg.PhyMode = 0xff; // unknown
+ pAd->CommonCfg.BandState = UNKNOWN_BAND;
+ pAd->CommonCfg.RadarDetect.CSPeriod = 10;
+ pAd->CommonCfg.RadarDetect.CSCount = 0;
+ pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
+ pAd->CommonCfg.RadarDetect.ChMovingTime = 65;
+ pAd->CommonCfg.RadarDetect.LongPulseRadarTh = 3;
+ pAd->CommonCfg.bAPSDCapable = FALSE;
+ pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
+ pAd->CommonCfg.TriggerTimerCount = 0;
+ pAd->CommonCfg.bAPSDForcePowerSave = FALSE;
+ pAd->CommonCfg.bCountryFlag = FALSE;
+ pAd->CommonCfg.TxStream = 0;
+ pAd->CommonCfg.RxStream = 0;
+
+ NdisZeroMemory(&pAd->BeaconTxWI, sizeof(pAd->BeaconTxWI));
+
+#ifdef DOT11_N_SUPPORT
+ NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability));
+ pAd->HTCEnable = FALSE;
+ pAd->bBroadComHT = FALSE;
+ pAd->CommonCfg.bRdg = FALSE;
+
+#ifdef DOT11N_DRAFT3
+ pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; // Unit : TU. 5~1000
+ pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; // Unit : TU. 10~1000
+ pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; // Unit : Second
+ pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; // Unit : TU. 200~10000
+ pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; // Unit : TU. 20~10000
+ pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor;
+ pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; // Unit : percentage
+ pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor);
+#endif // DOT11N_DRAFT3 //
+
+ NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo));
+ pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+ pAd->CommonCfg.BACapability.field.MpduDensity = 0;
+ pAd->CommonCfg.BACapability.field.Policy = IMMED_BA;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; //32;
+ pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; //32;
+ DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word));
+
+ pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+ BATableInit(pAd, &pAd->BATable);
+
+ pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1;
+ pAd->CommonCfg.bHTProtect = 1;
+ pAd->CommonCfg.bMIMOPSEnable = TRUE;
+ pAd->CommonCfg.bBADecline = FALSE;
+ pAd->CommonCfg.bDisableReordering = FALSE;
+
+ pAd->CommonCfg.TxBASize = 7;
+
+ pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word;
+#endif // DOT11_N_SUPPORT //
+
+ //pAd->CommonCfg.HTPhyMode.field.BW = BW_20;
+ //pAd->CommonCfg.HTPhyMode.field.MCS = MCS_AUTO;
+ //pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800;
+ //pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE;
+ pAd->CommonCfg.TxRate = RATE_6;
+
+ pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6;
+ pAd->CommonCfg.MlmeTransmit.field.BW = BW_20;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+
+ pAd->CommonCfg.BeaconPeriod = 100; // in mSec
+
+ //
+ // part II. intialize STA specific configuration
+ //
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_DIRECT);
+ RX_FILTER_CLEAR_FLAG(pAd, fRX_FILTER_ACCEPT_MULTICAST);
+ RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_BROADCAST);
+ RX_FILTER_SET_FLAG(pAd, fRX_FILTER_ACCEPT_ALL_MULTICAST);
+
+ pAd->StaCfg.Psm = PWR_ACTIVE;
+
+ pAd->StaCfg.OrigWepStatus = Ndis802_11EncryptionDisabled;
+ pAd->StaCfg.PairCipher = Ndis802_11EncryptionDisabled;
+ pAd->StaCfg.GroupCipher = Ndis802_11EncryptionDisabled;
+ pAd->StaCfg.bMixCipher = FALSE;
+ pAd->StaCfg.DefaultKeyId = 0;
+
+ // 802.1x port control
+ pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+ pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ pAd->StaCfg.LastMicErrorTime = 0;
+ pAd->StaCfg.MicErrCnt = 0;
+ pAd->StaCfg.bBlockAssoc = FALSE;
+ pAd->StaCfg.WpaState = SS_NOTUSE;
+
+ pAd->CommonCfg.NdisRadioStateOff = FALSE; // New to support microsoft disable radio with OID command
+
+ pAd->StaCfg.RssiTrigger = 0;
+ NdisZeroMemory(&pAd->StaCfg.RssiSample, sizeof(RSSI_SAMPLE));
+ pAd->StaCfg.RssiTriggerMode = RSSI_TRIGGERED_UPON_BELOW_THRESHOLD;
+ pAd->StaCfg.AtimWin = 0;
+ pAd->StaCfg.DefaultListenCount = 3;//default listen count;
+ pAd->StaCfg.BssType = BSS_INFRA; // BSS_INFRA or BSS_ADHOC or BSS_MONITOR
+ pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WAKEUP_NOW);
+
+ pAd->StaCfg.bAutoTxRateSwitch = TRUE;
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+ }
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ pAd->StaCfg.IEEE80211dClientMode = Rt802_11_D_None;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+
+ // global variables mXXXX used in MAC protocol state machines
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
+
+ // PHY specification
+ pAd->CommonCfg.PhyMode = PHY_11BG_MIXED; // default PHY mode
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); // CCK use LONG preamble
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // user desired power mode
+ pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
+ pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
+ pAd->StaCfg.bWindowsACCAMEnable = FALSE;
+
+#ifdef LEAP_SUPPORT
+ // CCX v1.0 releated init value
+ RTMPInitTimer(pAd, &pAd->StaCfg.LeapAuthTimer, GET_TIMER_FUNCTION(LeapAuthTimeout), pAd, FALSE);
+ pAd->StaCfg.LeapAuthMode = CISCO_AuthModeLEAPNone;
+ pAd->StaCfg.bCkipOn = FALSE;
+#endif // LEAP_SUPPORT //
+
+ RTMPInitTimer(pAd, &pAd->StaCfg.StaQuickResponeForRateUpTimer, GET_TIMER_FUNCTION(StaQuickResponeForRateUpExec), pAd, FALSE);
+ pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
+
+ // Patch for Ndtest
+ pAd->StaCfg.ScanCnt = 0;
+
+ // CCX 2.0 control flag init
+ pAd->StaCfg.CCXEnable = FALSE;
+ pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED;
+ pAd->StaCfg.CCXQosECWMin = 4;
+ pAd->StaCfg.CCXQosECWMax = 10;
+
+ pAd->StaCfg.bHwRadio = TRUE; // Default Hardware Radio status is On
+ pAd->StaCfg.bSwRadio = TRUE; // Default Software Radio status is On
+ pAd->StaCfg.bRadio = TRUE; // bHwRadio && bSwRadio
+ pAd->StaCfg.bHardwareRadio = FALSE; // Default is OFF
+ pAd->StaCfg.bShowHiddenSSID = FALSE; // Default no show
+
+ // Nitro mode control
+ pAd->StaCfg.bAutoReconnect = TRUE;
+
+ // Save the init time as last scan time, the system should do scan after 2 seconds.
+ // This patch is for driver wake up from standby mode, system will do scan right away.
+ pAd->StaCfg.LastScanTime = 0;
+ NdisZeroMemory(pAd->nickname, IW_ESSID_MAX_SIZE+1);
+ sprintf(pAd->nickname, "%s", STA_NIC_DEVICE_NAME);
+ RTMPInitTimer(pAd, &pAd->StaCfg.WpaDisassocAndBlockAssocTimer, GET_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc), pAd, FALSE);
+#ifdef WPA_SUPPLICANT_SUPPORT
+ pAd->StaCfg.IEEE8021X = FALSE;
+ pAd->StaCfg.IEEE8021x_required_keys = FALSE;
+ pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_DISABLE;
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ pAd->StaCfg.WpaSupplicantUP = WPA_SUPPLICANT_ENABLE;
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // Default for extra information is not valid
+ pAd->ExtraInfo = EXTRA_INFO_CLEAR;
+
+ // Default Config change flag
+ pAd->bConfigChanged = FALSE;
+
+ //
+ // part III. AP configurations
+ //
+
+
+ //
+ // part IV. others
+ //
+ // dynamic BBP R66:sensibity tuning to overcome background noise
+ pAd->BbpTuning.bEnable = TRUE;
+ pAd->BbpTuning.FalseCcaLowerThreshold = 100;
+ pAd->BbpTuning.FalseCcaUpperThreshold = 512;
+ pAd->BbpTuning.R66Delta = 4;
+ pAd->Mlme.bEnableAutoAntennaCheck = TRUE;
+
+ //
+ // Also initial R66CurrentValue, RTUSBResumeMsduTransmission might use this value.
+ // if not initial this value, the default value will be 0.
+ //
+ pAd->BbpTuning.R66CurrentValue = 0x38;
+
+ pAd->Bbp94 = BBPR94_DEFAULT;
+ pAd->BbpForCCK = FALSE;
+
+ // initialize MAC table and allocate spin lock
+ NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE));
+ InitializeQueueHeader(&pAd->MacTab.McastPsQueue);
+ NdisAllocateSpinLock(&pAd->MacTabLock);
+
+#ifdef RALINK_ATE
+ NdisZeroMemory(&pAd->ate, sizeof(ATE_INFO));
+ pAd->ate.Mode = ATE_STOP;
+ pAd->ate.TxCount = 200;/* to exceed TX_RING_SIZE ... */
+ pAd->ate.TxLength = 1024;
+ pAd->ate.TxWI.ShortGI = 0;// LONG GI : 800 ns
+ pAd->ate.TxWI.PHYMODE = MODE_CCK;
+ pAd->ate.TxWI.MCS = 3;
+ pAd->ate.TxWI.BW = BW_20;
+ pAd->ate.Channel = 1;
+ pAd->ate.QID = QID_AC_BE;
+ pAd->ate.Addr1[0] = 0x00;
+ pAd->ate.Addr1[1] = 0x11;
+ pAd->ate.Addr1[2] = 0x22;
+ pAd->ate.Addr1[3] = 0xAA;
+ pAd->ate.Addr1[4] = 0xBB;
+ pAd->ate.Addr1[5] = 0xCC;
+ NdisMoveMemory(pAd->ate.Addr2, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS);
+ NdisMoveMemory(pAd->ate.Addr3, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS);
+ pAd->ate.bRxFer = 0;
+ pAd->ate.bQATxStart = FALSE;
+ pAd->ate.bQARxStart = FALSE;
+#ifdef RT2860
+ pAd->ate.bFWLoading = FALSE;
+#endif // RT2860 //
+#ifdef RALINK_28xx_QA
+ //pAd->ate.Repeat = 0;
+ pAd->ate.TxStatus = 0;
+ pAd->ate.AtePid = THREAD_PID_INIT_VALUE;
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+
+ pAd->CommonCfg.bWiFiTest = FALSE;
+#ifdef RT2860
+ pAd->bPCIclkOff = FALSE;
+#endif // RT2860 //
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n"));
+}
+
+// IRQL = PASSIVE_LEVEL
+UCHAR BtoH(char ch)
+{
+ if (ch >= '0' && ch <= '9') return (ch - '0'); // Handle numerals
+ if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); // Handle capitol hex digits
+ if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); // Handle small hex digits
+ return(255);
+}
+
+//
+// FUNCTION: AtoH(char *, UCHAR *, int)
+//
+// PURPOSE: Converts ascii string to network order hex
+//
+// PARAMETERS:
+// src - pointer to input ascii string
+// dest - pointer to output hex
+// destlen - size of dest
+//
+// COMMENTS:
+//
+// 2 ascii bytes make a hex byte so must put 1st ascii byte of pair
+// into upper nibble and 2nd ascii byte of pair into lower nibble.
+//
+// IRQL = PASSIVE_LEVEL
+
+void AtoH(char * src, UCHAR * dest, int destlen)
+{
+ char * srcptr;
+ PUCHAR destTemp;
+
+ srcptr = src;
+ destTemp = (PUCHAR) dest;
+
+ while(destlen--)
+ {
+ *destTemp = BtoH(*srcptr++) << 4; // Put 1st ascii byte in upper nibble.
+ *destTemp += BtoH(*srcptr++); // Add 2nd ascii byte to above.
+ destTemp++;
+ }
+}
+
+VOID RTMPPatchMacBbpBug(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG Index;
+
+ // Initialize BBP register to default value
+ for (Index = 0; Index < NUM_BBP_REG_PARMS; Index++)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBPRegTable[Index].Register, (UCHAR)BBPRegTable[Index].Value);
+ }
+
+ // Initialize RF register to default value
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+ // Re-init BBP register from EEPROM value
+ NICInitAsicFromEEPROM(pAd);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init timer objects
+
+ Arguments:
+ pAd Pointer to our adapter
+ pTimer Timer structure
+ pTimerFunc Function to execute when timer expired
+ Repeat Ture for period timer
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInitTimer(
+ IN PRTMP_ADAPTER pAd,
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN PVOID pTimerFunc,
+ IN PVOID pData,
+ IN BOOLEAN Repeat)
+{
+ //
+ // Set Valid to TRUE for later used.
+ // It will crash if we cancel a timer or set a timer
+ // that we haven't initialize before.
+ //
+ pTimer->Valid = TRUE;
+
+ pTimer->PeriodicType = Repeat;
+ pTimer->State = FALSE;
+ pTimer->cookie = (ULONG) pData;
+
+
+ RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init timer objects
+
+ Arguments:
+ pTimer Timer structure
+ Value Timer value in milliseconds
+
+ Return Value:
+ None
+
+ Note:
+ To use this routine, must call RTMPInitTimer before.
+
+ ========================================================================
+*/
+VOID RTMPSetTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN ULONG Value)
+{
+ if (pTimer->Valid)
+ {
+ pTimer->TimerValue = Value;
+ pTimer->State = FALSE;
+ if (pTimer->PeriodicType == TRUE)
+ {
+ pTimer->Repeat = TRUE;
+ RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value);
+ }
+ else
+ {
+ pTimer->Repeat = FALSE;
+ RTMP_OS_Add_Timer(&pTimer->TimerObj, Value);
+ }
+ }
+ else
+ {
+ DBGPRINT_ERR(("RTMPSetTimer failed, Timer hasn't been initialize!\n"));
+ }
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init timer objects
+
+ Arguments:
+ pTimer Timer structure
+ Value Timer value in milliseconds
+
+ Return Value:
+ None
+
+ Note:
+ To use this routine, must call RTMPInitTimer before.
+
+ ========================================================================
+*/
+VOID RTMPModTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN ULONG Value)
+{
+ BOOLEAN Cancel;
+
+ if (pTimer->Valid)
+ {
+ pTimer->TimerValue = Value;
+ pTimer->State = FALSE;
+ if (pTimer->PeriodicType == TRUE)
+ {
+ RTMPCancelTimer(pTimer, &Cancel);
+ RTMPSetTimer(pTimer, Value);
+ }
+ else
+ {
+ RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value);
+ }
+ }
+ else
+ {
+ DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n"));
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Cancel timer objects
+
+ Arguments:
+ Adapter Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ 1.) To use this routine, must call RTMPInitTimer before.
+ 2.) Reset NIC to initial state AS IS system boot up time.
+
+ ========================================================================
+*/
+VOID RTMPCancelTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ OUT BOOLEAN *pCancelled)
+{
+ if (pTimer->Valid)
+ {
+ if (pTimer->State == FALSE)
+ pTimer->Repeat = FALSE;
+ RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled);
+
+ if (*pCancelled == TRUE)
+ pTimer->State = TRUE;
+
+ }
+ else
+ {
+ //
+ // NdisMCancelTimer just canced the timer and not mean release the timer.
+ // And don't set the "Valid" to False. So that we can use this timer again.
+ //
+ DBGPRINT_ERR(("RTMPCancelTimer failed, Timer hasn't been initialize!\n"));
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set LED Status
+
+ Arguments:
+ pAd Pointer to our adapter
+ Status LED Status
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPSetLED(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Status)
+{
+ //ULONG data;
+ UCHAR HighByte = 0;
+ UCHAR LowByte;
+
+// In ATE mode of RT2860 AP/STA, we have erased 8051 firmware.
+// So LED mode is not supported when ATE is running.
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+ LowByte = pAd->LedCntl.field.LedMode&0x7f;
+ switch (Status)
+ {
+ case LED_LINK_DOWN:
+ HighByte = 0x20;
+ AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+ pAd->LedIndicatorStregth = 0;
+ break;
+ case LED_LINK_UP:
+ if (pAd->CommonCfg.Channel > 14)
+ HighByte = 0xa0;
+ else
+ HighByte = 0x60;
+ AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+ break;
+ case LED_RADIO_ON:
+ HighByte = 0x20;
+ AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+ break;
+ case LED_HALT:
+ LowByte = 0; // Driver sets MAC register and MAC controls LED
+ case LED_RADIO_OFF:
+ HighByte = 0;
+ AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+ break;
+ case LED_WPS:
+ HighByte = 0x10;
+ AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+ break;
+ case LED_ON_SITE_SURVEY:
+ HighByte = 0x08;
+ AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+ break;
+ case LED_POWER_UP:
+ HighByte = 0x04;
+ AsicSendCommandToMcu(pAd, 0x50, 0xff, LowByte, HighByte);
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status %d\n", Status));
+ break;
+ }
+
+ //
+ // Keep LED status for LED SiteSurvey mode.
+ // After SiteSurvey, we will set the LED mode to previous status.
+ //
+ if ((Status != LED_ON_SITE_SURVEY) && (Status != LED_POWER_UP))
+ pAd->LedStatus = Status;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSetLED::Mode=%d,HighByte=0x%02x,LowByte=0x%02x\n", pAd->LedCntl.field.LedMode, HighByte, LowByte));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set LED Signal Stregth
+
+ Arguments:
+ pAd Pointer to our adapter
+ Dbm Signal Stregth
+
+ Return Value:
+ None
+
+ IRQL = PASSIVE_LEVEL
+
+ Note:
+ Can be run on any IRQL level.
+
+ According to Microsoft Zero Config Wireless Signal Stregth definition as belows.
+ <= -90 No Signal
+ <= -81 Very Low
+ <= -71 Low
+ <= -67 Good
+ <= -57 Very Good
+ > -57 Excellent
+ ========================================================================
+*/
+VOID RTMPSetSignalLED(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_802_11_RSSI Dbm)
+{
+ UCHAR nLed = 0;
+
+ //
+ // if not Signal Stregth, then do nothing.
+ //
+ if (pAd->LedCntl.field.LedMode != LED_MODE_SIGNAL_STREGTH)
+ {
+ return;
+ }
+
+ if (Dbm <= -90)
+ nLed = 0;
+ else if (Dbm <= -81)
+ nLed = 1;
+ else if (Dbm <= -71)
+ nLed = 3;
+ else if (Dbm <= -67)
+ nLed = 7;
+ else if (Dbm <= -57)
+ nLed = 15;
+ else
+ nLed = 31;
+
+ //
+ // Update Signal Stregth to firmware if changed.
+ //
+ if (pAd->LedIndicatorStregth != nLed)
+ {
+ AsicSendCommandToMcu(pAd, 0x51, 0xff, nLed, pAd->LedCntl.field.Polarity);
+ pAd->LedIndicatorStregth = nLed;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Enable RX
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL <= DISPATCH_LEVEL
+
+ Note:
+ Before Enable RX, make sure you have enabled Interrupt.
+ ========================================================================
+*/
+VOID RTMPEnableRxTx(
+ IN PRTMP_ADAPTER pAd)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n"));
+
+ // Enable Rx DMA.
+ RT28XXDMAEnable(pAd);
+
+ // enable RX of MAC block
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ UINT32 rx_filter_flag = APNORMAL;
+
+
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, rx_filter_flag); // enable RX of DMA block
+ }
+ else
+ {
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
+ }
+
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
+ DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n"));
+}
+
+
diff --git a/drivers/staging/rt2860/common/rtmp_tkip.c b/drivers/staging/rt2860/common/rtmp_tkip.c
new file mode 100644
index 000000000000..a87ea3a5d3ea
--- /dev/null
+++ b/drivers/staging/rt2860/common/rtmp_tkip.c
@@ -0,0 +1,1607 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_tkip.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Wu 02-25-02 Initial
+*/
+
+#include "../rt_config.h"
+
+// Rotation functions on 32 bit values
+#define ROL32( A, n ) \
+ ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
+#define ROR32( A, n ) ROL32( (A), 32-(n) )
+
+UINT Tkip_Sbox_Lower[256] =
+{
+ 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54,
+ 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A,
+ 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B,
+ 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B,
+ 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F,
+ 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F,
+ 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5,
+ 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F,
+ 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB,
+ 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97,
+ 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED,
+ 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A,
+ 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94,
+ 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3,
+ 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04,
+ 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D,
+ 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39,
+ 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95,
+ 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83,
+ 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76,
+ 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4,
+ 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B,
+ 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0,
+ 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18,
+ 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51,
+ 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85,
+ 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12,
+ 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9,
+ 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7,
+ 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A,
+ 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8,
+ 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A
+};
+
+UINT Tkip_Sbox_Upper[256] =
+{
+ 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91,
+ 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC,
+ 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB,
+ 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B,
+ 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83,
+ 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A,
+ 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F,
+ 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA,
+ 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B,
+ 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13,
+ 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6,
+ 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85,
+ 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11,
+ 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B,
+ 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1,
+ 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF,
+ 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E,
+ 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6,
+ 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B,
+ 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD,
+ 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8,
+ 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2,
+ 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49,
+ 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10,
+ 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97,
+ 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F,
+ 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C,
+ 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27,
+ 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33,
+ 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5,
+ 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0,
+ 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C
+};
+
+/*****************************/
+/******** SBOX Table *********/
+/*****************************/
+
+UCHAR SboxTable[256] =
+{
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+ 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+ 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+ 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+ 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+ 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+ 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+ 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+ 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+ 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+ 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+ 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+};
+
+VOID xor_32(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out);
+
+VOID xor_128(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out);
+
+VOID next_key(
+ IN PUCHAR key,
+ IN INT round);
+
+VOID byte_sub(
+ IN PUCHAR in,
+ OUT PUCHAR out);
+
+VOID shift_row(
+ IN PUCHAR in,
+ OUT PUCHAR out);
+
+VOID mix_column(
+ IN PUCHAR in,
+ OUT PUCHAR out);
+
+UCHAR RTMPCkipSbox(
+ IN UCHAR a);
+//
+// Expanded IV for TKIP function.
+//
+typedef struct PACKED _IV_CONTROL_
+{
+ union PACKED
+ {
+ struct PACKED
+ {
+ UCHAR rc0;
+ UCHAR rc1;
+ UCHAR rc2;
+
+ union PACKED
+ {
+ struct PACKED
+ {
+#ifdef RT_BIG_ENDIAN
+ UCHAR KeyID:2;
+ UCHAR ExtIV:1;
+ UCHAR Rsvd:5;
+#else
+ UCHAR Rsvd:5;
+ UCHAR ExtIV:1;
+ UCHAR KeyID:2;
+#endif
+ } field;
+ UCHAR Byte;
+ } CONTROL;
+ } field;
+
+ ULONG word;
+ } IV16;
+
+ ULONG IV32;
+} TKIP_IV, *PTKIP_IV;
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Convert from UCHAR[] to ULONG in a portable way
+
+ Arguments:
+ pMICKey pointer to MIC Key
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+ULONG RTMPTkipGetUInt32(
+ IN PUCHAR pMICKey)
+{
+ ULONG res = 0;
+ INT i;
+
+ for (i = 0; i < 4; i++)
+ {
+ res |= (*pMICKey++) << (8 * i);
+ }
+
+ return res;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Convert from ULONG to UCHAR[] in a portable way
+
+ Arguments:
+ pDst pointer to destination for convert ULONG to UCHAR[]
+ val the value for convert
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipPutUInt32(
+ IN OUT PUCHAR pDst,
+ IN ULONG val)
+{
+ INT i;
+
+ for(i = 0; i < 4; i++)
+ {
+ *pDst++ = (UCHAR) (val & 0xff);
+ val >>= 8;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set the MIC Key.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pMICKey pointer to MIC Key
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipSetMICKey(
+ IN PTKIP_KEY_INFO pTkip,
+ IN PUCHAR pMICKey)
+{
+ // Set the key
+ pTkip->K0 = RTMPTkipGetUInt32(pMICKey);
+ pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4);
+ // and reset the message
+ pTkip->L = pTkip->K0;
+ pTkip->R = pTkip->K1;
+ pTkip->nBytesInM = 0;
+ pTkip->M = 0;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculate the MIC Value.
+
+ Arguments:
+ pAd Pointer to our adapter
+ uChar Append this uChar
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipAppendByte(
+ IN PTKIP_KEY_INFO pTkip,
+ IN UCHAR uChar)
+{
+ // Append the byte to our word-sized buffer
+ pTkip->M |= (uChar << (8* pTkip->nBytesInM));
+ pTkip->nBytesInM++;
+ // Process the word if it is full.
+ if( pTkip->nBytesInM >= 4 )
+ {
+ pTkip->L ^= pTkip->M;
+ pTkip->R ^= ROL32( pTkip->L, 17 );
+ pTkip->L += pTkip->R;
+ pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8);
+ pTkip->L += pTkip->R;
+ pTkip->R ^= ROL32( pTkip->L, 3 );
+ pTkip->L += pTkip->R;
+ pTkip->R ^= ROR32( pTkip->L, 2 );
+ pTkip->L += pTkip->R;
+ // Clear the buffer
+ pTkip->M = 0;
+ pTkip->nBytesInM = 0;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculate the MIC Value.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pSrc Pointer to source data for Calculate MIC Value
+ Len Indicate the length of the source data
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPTkipAppend(
+ IN PTKIP_KEY_INFO pTkip,
+ IN PUCHAR pSrc,
+ IN UINT nBytes)
+{
+ // This is simple
+ while(nBytes > 0)
+ {
+ RTMPTkipAppendByte(pTkip, *pSrc++);
+ nBytes--;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get the MIC Value.
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ the MIC Value is store in pAd->PrivateInfo.MIC
+ ========================================================================
+*/
+VOID RTMPTkipGetMIC(
+ IN PTKIP_KEY_INFO pTkip)
+{
+ // Append the minimum padding
+ RTMPTkipAppendByte(pTkip, 0x5a );
+ RTMPTkipAppendByte(pTkip, 0 );
+ RTMPTkipAppendByte(pTkip, 0 );
+ RTMPTkipAppendByte(pTkip, 0 );
+ RTMPTkipAppendByte(pTkip, 0 );
+ // and then zeroes until the length is a multiple of 4
+ while( pTkip->nBytesInM != 0 )
+ {
+ RTMPTkipAppendByte(pTkip, 0 );
+ }
+ // The appendByte function has already computed the result.
+ RTMPTkipPutUInt32(pTkip->MIC, pTkip->L);
+ RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init Tkip function.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pTKey Pointer to the Temporal Key (TK), TK shall be 128bits.
+ KeyId TK Key ID
+ pTA Pointer to transmitter address
+ pMICKey pointer to MIC Key
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInitTkipEngine(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKey,
+ IN UCHAR KeyId,
+ IN PUCHAR pTA,
+ IN PUCHAR pMICKey,
+ IN PUCHAR pTSC,
+ OUT PULONG pIV16,
+ OUT PULONG pIV32)
+{
+ TKIP_IV tkipIv;
+
+ // Prepare 8 bytes TKIP encapsulation for MPDU
+ NdisZeroMemory(&tkipIv, sizeof(TKIP_IV));
+ tkipIv.IV16.field.rc0 = *(pTSC + 1);
+ tkipIv.IV16.field.rc1 = (tkipIv.IV16.field.rc0 | 0x20) & 0x7f;
+ tkipIv.IV16.field.rc2 = *pTSC;
+ tkipIv.IV16.field.CONTROL.field.ExtIV = 1; // 0: non-extended IV, 1: an extended IV
+ tkipIv.IV16.field.CONTROL.field.KeyID = KeyId;
+ NdisMoveMemory(&tkipIv.IV32, (pTSC + 2), 4); // Copy IV
+
+ *pIV16 = tkipIv.IV16.word;
+ *pIV32 = tkipIv.IV32;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init MIC Value calculation function which include set MIC key &
+ calculate first 16 bytes (DA + SA + priority + 0)
+
+ Arguments:
+ pAd Pointer to our adapter
+ pTKey Pointer to the Temporal Key (TK), TK shall be 128bits.
+ pDA Pointer to DA address
+ pSA Pointer to SA address
+ pMICKey pointer to MIC Key
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInitMICEngine(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKey,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN UCHAR UserPriority,
+ IN PUCHAR pMICKey)
+{
+ ULONG Priority = UserPriority;
+
+ // Init MIC value calculation
+ RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey);
+ // DA
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN);
+ // SA
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN);
+ // Priority + 3 bytes of 0
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Compare MIC value of received MSDU
+
+ Arguments:
+ pAd Pointer to our adapter
+ pSrc Pointer to the received Plain text data
+ pDA Pointer to DA address
+ pSA Pointer to SA address
+ pMICKey pointer to MIC Key
+ Len the length of the received plain text data exclude MIC value
+
+ Return Value:
+ TRUE MIC value matched
+ FALSE MIC value mismatched
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPTkipCompareMICValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pSrc,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN PUCHAR pMICKey,
+ IN UCHAR UserPriority,
+ IN UINT Len)
+{
+ UCHAR OldMic[8];
+ ULONG Priority = UserPriority;
+
+ // Init MIC value calculation
+ RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey);
+ // DA
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN);
+ // SA
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN);
+ // Priority + 3 bytes of 0
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4);
+
+ // Calculate MIC value from plain text data
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len);
+
+ // Get MIC valude from received frame
+ NdisMoveMemory(OldMic, pSrc + Len, 8);
+
+ // Get MIC value from decrypted plain data
+ RTMPTkipGetMIC(&pAd->PrivateInfo.Rx);
+
+ // Move MIC value from MSDU, this steps should move to data path.
+ // Since the MIC value might cross MPDUs.
+ if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8))
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); //MIC error.
+
+
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Compare MIC value of received MSDU
+
+ Arguments:
+ pAd Pointer to our adapter
+ pLLC LLC header
+ pSrc Pointer to the received Plain text data
+ pDA Pointer to DA address
+ pSA Pointer to SA address
+ pMICKey pointer to MIC Key
+ Len the length of the received plain text data exclude MIC value
+
+ Return Value:
+ TRUE MIC value matched
+ FALSE MIC value mismatched
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPTkipCompareMICValueWithLLC(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pLLC,
+ IN PUCHAR pSrc,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN PUCHAR pMICKey,
+ IN UINT Len)
+{
+ UCHAR OldMic[8];
+ ULONG Priority = 0;
+
+ // Init MIC value calculation
+ RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey);
+ // DA
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN);
+ // SA
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN);
+ // Priority + 3 bytes of 0
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4);
+
+ // Start with LLC header
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pLLC, 8);
+
+ // Calculate MIC value from plain text data
+ RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len);
+
+ // Get MIC valude from received frame
+ NdisMoveMemory(OldMic, pSrc + Len, 8);
+
+ // Get MIC value from decrypted plain data
+ RTMPTkipGetMIC(&pAd->PrivateInfo.Rx);
+
+ // Move MIC value from MSDU, this steps should move to data path.
+ // Since the MIC value might cross MPDUs.
+ if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8))
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValueWithLLC(): TKIP MIC Error !\n")); //MIC error.
+
+
+ return (FALSE);
+ }
+ return (TRUE);
+}
+/*
+ ========================================================================
+
+ Routine Description:
+ Copy frame from waiting queue into relative ring buffer and set
+ appropriate ASIC register to kick hardware transmit function
+
+ Arguments:
+ pAd Pointer to our adapter
+ PNDIS_PACKET Pointer to Ndis Packet for MIC calculation
+ pEncap Pointer to LLC encap data
+ LenEncap Total encap length, might be 0 which indicates no encap
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPCalculateMICValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pEncap,
+ IN PCIPHER_KEY pKey,
+ IN UCHAR apidx)
+{
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+ PUCHAR pSrc;
+ UCHAR UserPriority;
+ UCHAR vlan_offset = 0;
+
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+ UserPriority = RTMP_GET_PACKET_UP(pPacket);
+ pSrc = pSrcBufVA;
+
+ // determine if this is a vlan packet
+ if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100)
+ vlan_offset = 4;
+
+ {
+ RTMPInitMICEngine(
+ pAd,
+ pKey->Key,
+ pSrc,
+ pSrc + 6,
+ UserPriority,
+ pKey->TxMic);
+ }
+
+
+ if (pEncap != NULL)
+ {
+ // LLC encapsulation
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6);
+ // Protocol Type
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2);
+ }
+ SrcBufLen -= (14 + vlan_offset);
+ pSrc += (14 + vlan_offset);
+ do
+ {
+ if (SrcBufLen > 0)
+ {
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen);
+ }
+
+ break; // No need handle next packet
+
+ } while (TRUE); // End of copying payload
+
+ // Compute the final MIC Value
+ RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
+}
+
+
+/************************************************************/
+/* tkip_sbox() */
+/* Returns a 16 bit value from a 64K entry table. The Table */
+/* is synthesized from two 256 entry byte wide tables. */
+/************************************************************/
+
+UINT tkip_sbox(UINT index)
+{
+ UINT index_low;
+ UINT index_high;
+ UINT left, right;
+
+ index_low = (index % 256);
+ index_high = ((index >> 8) % 256);
+
+ left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256);
+ right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256);
+
+ return (left ^ right);
+}
+
+UINT rotr1(UINT a)
+{
+ unsigned int b;
+
+ if ((a & 0x01) == 0x01)
+ {
+ b = (a >> 1) | 0x8000;
+ }
+ else
+ {
+ b = (a >> 1) & 0x7fff;
+ }
+ b = b % 65536;
+ return b;
+}
+
+VOID RTMPTkipMixKey(
+ UCHAR *key,
+ UCHAR *ta,
+ ULONG pnl, /* Least significant 16 bits of PN */
+ ULONG pnh, /* Most significant 32 bits of PN */
+ UCHAR *rc4key,
+ UINT *p1k)
+{
+
+ UINT tsc0;
+ UINT tsc1;
+ UINT tsc2;
+
+ UINT ppk0;
+ UINT ppk1;
+ UINT ppk2;
+ UINT ppk3;
+ UINT ppk4;
+ UINT ppk5;
+
+ INT i;
+ INT j;
+
+ tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
+ tsc1 = (unsigned int)(pnh % 65536);
+ tsc2 = (unsigned int)(pnl % 65536); /* lsb */
+
+ /* Phase 1, step 1 */
+ p1k[0] = tsc1;
+ p1k[1] = tsc0;
+ p1k[2] = (UINT)(ta[0] + (ta[1]*256));
+ p1k[3] = (UINT)(ta[2] + (ta[3]*256));
+ p1k[4] = (UINT)(ta[4] + (ta[5]*256));
+
+ /* Phase 1, step 2 */
+ for (i=0; i<8; i++)
+ {
+ j = 2*(i & 1);
+ p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536;
+ p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536;
+ p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536;
+ p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536;
+ p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536;
+ p1k[4] = (p1k[4] + i) % 65536;
+ }
+
+ /* Phase 2, Step 1 */
+ ppk0 = p1k[0];
+ ppk1 = p1k[1];
+ ppk2 = p1k[2];
+ ppk3 = p1k[3];
+ ppk4 = p1k[4];
+ ppk5 = (p1k[4] + tsc2) % 65536;
+
+ /* Phase2, Step 2 */
+ ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536);
+ ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536);
+ ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536);
+ ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536);
+ ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536);
+ ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536);
+
+ ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12]));
+ ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14]));
+ ppk2 = ppk2 + rotr1(ppk1);
+ ppk3 = ppk3 + rotr1(ppk2);
+ ppk4 = ppk4 + rotr1(ppk3);
+ ppk5 = ppk5 + rotr1(ppk4);
+
+ /* Phase 2, Step 3 */
+ /* Phase 2, Step 3 */
+
+ tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
+ tsc1 = (unsigned int)(pnh % 65536);
+ tsc2 = (unsigned int)(pnl % 65536); /* lsb */
+
+ rc4key[0] = (tsc2 >> 8) % 256;
+ rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f;
+ rc4key[2] = tsc2 % 256;
+ rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256;
+
+ rc4key[4] = ppk0 % 256;
+ rc4key[5] = (ppk0 >> 8) % 256;
+
+ rc4key[6] = ppk1 % 256;
+ rc4key[7] = (ppk1 >> 8) % 256;
+
+ rc4key[8] = ppk2 % 256;
+ rc4key[9] = (ppk2 >> 8) % 256;
+
+ rc4key[10] = ppk3 % 256;
+ rc4key[11] = (ppk3 >> 8) % 256;
+
+ rc4key[12] = ppk4 % 256;
+ rc4key[13] = (ppk4 >> 8) % 256;
+
+ rc4key[14] = ppk5 % 256;
+ rc4key[15] = (ppk5 >> 8) % 256;
+}
+
+
+/************************************************/
+/* construct_mic_header1() */
+/* Builds the first MIC header block from */
+/* header fields. */
+/************************************************/
+
+void construct_mic_header1(
+ unsigned char *mic_header1,
+ int header_length,
+ unsigned char *mpdu)
+{
+ mic_header1[0] = (unsigned char)((header_length - 2) / 256);
+ mic_header1[1] = (unsigned char)((header_length - 2) % 256);
+ mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
+ mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
+ mic_header1[4] = mpdu[4]; /* A1 */
+ mic_header1[5] = mpdu[5];
+ mic_header1[6] = mpdu[6];
+ mic_header1[7] = mpdu[7];
+ mic_header1[8] = mpdu[8];
+ mic_header1[9] = mpdu[9];
+ mic_header1[10] = mpdu[10]; /* A2 */
+ mic_header1[11] = mpdu[11];
+ mic_header1[12] = mpdu[12];
+ mic_header1[13] = mpdu[13];
+ mic_header1[14] = mpdu[14];
+ mic_header1[15] = mpdu[15];
+}
+
+/************************************************/
+/* construct_mic_header2() */
+/* Builds the last MIC header block from */
+/* header fields. */
+/************************************************/
+
+void construct_mic_header2(
+ unsigned char *mic_header2,
+ unsigned char *mpdu,
+ int a4_exists,
+ int qc_exists)
+{
+ int i;
+
+ for (i = 0; i<16; i++) mic_header2[i]=0x00;
+
+ mic_header2[0] = mpdu[16]; /* A3 */
+ mic_header2[1] = mpdu[17];
+ mic_header2[2] = mpdu[18];
+ mic_header2[3] = mpdu[19];
+ mic_header2[4] = mpdu[20];
+ mic_header2[5] = mpdu[21];
+
+ // In Sequence Control field, mute sequence numer bits (12-bit)
+ mic_header2[6] = mpdu[22] & 0x0f; /* SC */
+ mic_header2[7] = 0x00; /* mpdu[23]; */
+
+ if ((!qc_exists) & a4_exists)
+ {
+ for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
+
+ }
+
+ if (qc_exists && (!a4_exists))
+ {
+ mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
+ mic_header2[9] = mpdu[25] & 0x00;
+ }
+
+ if (qc_exists && a4_exists)
+ {
+ for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i]; /* A4 */
+
+ mic_header2[14] = mpdu[30] & 0x0f;
+ mic_header2[15] = mpdu[31] & 0x00;
+ }
+}
+
+
+/************************************************/
+/* construct_mic_iv() */
+/* Builds the MIC IV from header fields and PN */
+/************************************************/
+
+void construct_mic_iv(
+ unsigned char *mic_iv,
+ int qc_exists,
+ int a4_exists,
+ unsigned char *mpdu,
+ unsigned int payload_length,
+ unsigned char *pn_vector)
+{
+ int i;
+
+ mic_iv[0] = 0x59;
+ if (qc_exists && a4_exists)
+ mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
+ if (qc_exists && !a4_exists)
+ mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
+ if (!qc_exists)
+ mic_iv[1] = 0x00;
+ for (i = 2; i < 8; i++)
+ mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
+#ifdef CONSISTENT_PN_ORDER
+ for (i = 8; i < 14; i++)
+ mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */
+#else
+ for (i = 8; i < 14; i++)
+ mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
+#endif
+ i = (payload_length / 256);
+ i = (payload_length % 256);
+ mic_iv[14] = (unsigned char) (payload_length / 256);
+ mic_iv[15] = (unsigned char) (payload_length % 256);
+
+}
+
+
+
+/************************************/
+/* bitwise_xor() */
+/* A 128 bit, bitwise exclusive or */
+/************************************/
+
+void bitwise_xor(unsigned char *ina, unsigned char *inb, unsigned char *out)
+{
+ int i;
+ for (i=0; i<16; i++)
+ {
+ out[i] = ina[i] ^ inb[i];
+ }
+}
+
+
+void aes128k128d(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
+{
+ int round;
+ int i;
+ unsigned char intermediatea[16];
+ unsigned char intermediateb[16];
+ unsigned char round_key[16];
+
+ for(i=0; i<16; i++) round_key[i] = key[i];
+
+ for (round = 0; round < 11; round++)
+ {
+ if (round == 0)
+ {
+ xor_128(round_key, data, ciphertext);
+ next_key(round_key, round);
+ }
+ else if (round == 10)
+ {
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ xor_128(intermediateb, round_key, ciphertext);
+ }
+ else /* 1 - 9 */
+ {
+ byte_sub(ciphertext, intermediatea);
+ shift_row(intermediatea, intermediateb);
+ mix_column(&intermediateb[0], &intermediatea[0]);
+ mix_column(&intermediateb[4], &intermediatea[4]);
+ mix_column(&intermediateb[8], &intermediatea[8]);
+ mix_column(&intermediateb[12], &intermediatea[12]);
+ xor_128(intermediatea, round_key, ciphertext);
+ next_key(round_key, round);
+ }
+ }
+
+}
+
+void construct_ctr_preload(
+ unsigned char *ctr_preload,
+ int a4_exists,
+ int qc_exists,
+ unsigned char *mpdu,
+ unsigned char *pn_vector,
+ int c)
+{
+
+ int i = 0;
+ for (i=0; i<16; i++) ctr_preload[i] = 0x00;
+ i = 0;
+
+ ctr_preload[0] = 0x01; /* flag */
+ if (qc_exists && a4_exists) ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
+ if (qc_exists && !a4_exists) ctr_preload[1] = mpdu[24] & 0x0f;
+
+ for (i = 2; i < 8; i++)
+ ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
+#ifdef CONSISTENT_PN_ORDER
+ for (i = 8; i < 14; i++)
+ ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */
+#else
+ for (i = 8; i < 14; i++)
+ ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */
+#endif
+ ctr_preload[14] = (unsigned char) (c / 256); // Ctr
+ ctr_preload[15] = (unsigned char) (c % 256);
+
+}
+
+
+//
+// TRUE: Success!
+// FALSE: Decrypt Error!
+//
+BOOLEAN RTMPSoftDecryptTKIP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataByteCnt,
+ IN UCHAR UserPriority,
+ IN PCIPHER_KEY pWpaKey)
+{
+ UCHAR KeyID;
+ UINT HeaderLen;
+ UCHAR fc0;
+ UCHAR fc1;
+ USHORT fc;
+ UINT frame_type;
+ UINT frame_subtype;
+ UINT from_ds;
+ UINT to_ds;
+ INT a4_exists;
+ INT qc_exists;
+ USHORT duration;
+ USHORT seq_control;
+ USHORT qos_control;
+ UCHAR TA[MAC_ADDR_LEN];
+ UCHAR DA[MAC_ADDR_LEN];
+ UCHAR SA[MAC_ADDR_LEN];
+ UCHAR RC4Key[16];
+ UINT p1k[5]; //for mix_key;
+ ULONG pnl;/* Least significant 16 bits of PN */
+ ULONG pnh;/* Most significant 32 bits of PN */
+ UINT num_blocks;
+ UINT payload_remainder;
+ ARCFOURCONTEXT ArcFourContext;
+ UINT crc32 = 0;
+ UINT trailfcs = 0;
+ UCHAR MIC[8];
+ UCHAR TrailMIC[8];
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+ fc0 = *pData;
+ fc1 = *(pData + 1);
+
+ fc = *((PUSHORT)pData);
+
+ frame_type = ((fc0 >> 2) & 0x03);
+ frame_subtype = ((fc0 >> 4) & 0x0f);
+
+ from_ds = (fc1 & 0x2) >> 1;
+ to_ds = (fc1 & 0x1);
+
+ a4_exists = (from_ds & to_ds);
+ qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */
+ (frame_subtype == 0x09) || /* Likely to change. */
+ (frame_subtype == 0x0a) ||
+ (frame_subtype == 0x0b)
+ );
+
+ HeaderLen = 24;
+ if (a4_exists)
+ HeaderLen += 6;
+
+ KeyID = *((PUCHAR)(pData+ HeaderLen + 3));
+ KeyID = KeyID >> 6;
+
+ if (pWpaKey[KeyID].KeyLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP failed!(KeyID[%d] Length can not be 0)\n", KeyID));
+ return FALSE;
+ }
+
+ duration = *((PUSHORT)(pData+2));
+
+ seq_control = *((PUSHORT)(pData+22));
+
+ if (qc_exists)
+ {
+ if (a4_exists)
+ {
+ qos_control = *((PUSHORT)(pData+30));
+ }
+ else
+ {
+ qos_control = *((PUSHORT)(pData+24));
+ }
+ }
+
+ if (to_ds == 0 && from_ds == 1)
+ {
+ NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN);
+ NdisMoveMemory(SA, pData+16, MAC_ADDR_LEN);
+ NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN); //BSSID
+ }
+ else if (to_ds == 0 && from_ds == 0 )
+ {
+ NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN);
+ NdisMoveMemory(DA, pData+4, MAC_ADDR_LEN);
+ NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN);
+ }
+ else if (to_ds == 1 && from_ds == 0)
+ {
+ NdisMoveMemory(SA, pData+10, MAC_ADDR_LEN);
+ NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN);
+ NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN);
+ }
+ else if (to_ds == 1 && from_ds == 1)
+ {
+ NdisMoveMemory(TA, pData+10, MAC_ADDR_LEN);
+ NdisMoveMemory(DA, pData+16, MAC_ADDR_LEN);
+ NdisMoveMemory(SA, pData+22, MAC_ADDR_LEN);
+ }
+
+ num_blocks = (DataByteCnt - 16) / 16;
+ payload_remainder = (DataByteCnt - 16) % 16;
+
+ pnl = (*(pData + HeaderLen)) * 256 + *(pData + HeaderLen + 2);
+ pnh = *((PULONG)(pData + HeaderLen + 4));
+ pnh = cpu2le32(pnh);
+ RTMPTkipMixKey(pWpaKey[KeyID].Key, TA, pnl, pnh, RC4Key, p1k);
+
+ ARCFOUR_INIT(&ArcFourContext, RC4Key, 16);
+
+ ARCFOUR_DECRYPT(&ArcFourContext, pData + HeaderLen, pData + HeaderLen + 8, DataByteCnt - HeaderLen - 8);
+ NdisMoveMemory(&trailfcs, pData + DataByteCnt - 8 - 4, 4);
+ crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 4); //Skip IV+EIV 8 bytes & Skip last 4 bytes(FCS).
+ crc32 ^= 0xffffffff; /* complement */
+
+ if(crc32 != cpu2le32(trailfcs))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptTKIP, WEP Data ICV Error !\n")); //ICV error.
+
+ return (FALSE);
+ }
+
+ NdisMoveMemory(TrailMIC, pData + DataByteCnt - 8 - 8 - 4, 8);
+ RTMPInitMICEngine(pAd, pWpaKey[KeyID].Key, DA, SA, UserPriority, pWpaKey[KeyID].RxMic);
+ RTMPTkipAppend(&pAd->PrivateInfo.Tx, pData + HeaderLen, DataByteCnt - HeaderLen - 8 - 12);
+ RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
+ NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, 8);
+
+ if (!NdisEqualMemory(MIC, TrailMIC, 8))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptTKIP, WEP Data MIC Error !\n")); //MIC error.
+ return (FALSE);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+ return TRUE;
+}
+
+
+
+
+BOOLEAN RTMPSoftDecryptAES(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataByteCnt,
+ IN PCIPHER_KEY pWpaKey)
+{
+ UCHAR KeyID;
+ UINT HeaderLen;
+ UCHAR PN[6];
+ UINT payload_len;
+ UINT num_blocks;
+ UINT payload_remainder;
+ USHORT fc;
+ UCHAR fc0;
+ UCHAR fc1;
+ UINT frame_type;
+ UINT frame_subtype;
+ UINT from_ds;
+ UINT to_ds;
+ INT a4_exists;
+ INT qc_exists;
+ UCHAR aes_out[16];
+ int payload_index;
+ UINT i;
+ UCHAR ctr_preload[16];
+ UCHAR chain_buffer[16];
+ UCHAR padded_buffer[16];
+ UCHAR mic_iv[16];
+ UCHAR mic_header1[16];
+ UCHAR mic_header2[16];
+ UCHAR MIC[8];
+ UCHAR TrailMIC[8];
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+ fc0 = *pData;
+ fc1 = *(pData + 1);
+
+ fc = *((PUSHORT)pData);
+
+ frame_type = ((fc0 >> 2) & 0x03);
+ frame_subtype = ((fc0 >> 4) & 0x0f);
+
+ from_ds = (fc1 & 0x2) >> 1;
+ to_ds = (fc1 & 0x1);
+
+ a4_exists = (from_ds & to_ds);
+ qc_exists = ((frame_subtype == 0x08) || /* Assumed QoS subtypes */
+ (frame_subtype == 0x09) || /* Likely to change. */
+ (frame_subtype == 0x0a) ||
+ (frame_subtype == 0x0b)
+ );
+
+ HeaderLen = 24;
+ if (a4_exists)
+ HeaderLen += 6;
+
+ KeyID = *((PUCHAR)(pData+ HeaderLen + 3));
+ KeyID = KeyID >> 6;
+
+ if (pWpaKey[KeyID].KeyLen == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSoftDecryptAES failed!(KeyID[%d] Length can not be 0)\n", KeyID));
+ return FALSE;
+ }
+
+ PN[0] = *(pData+ HeaderLen);
+ PN[1] = *(pData+ HeaderLen + 1);
+ PN[2] = *(pData+ HeaderLen + 4);
+ PN[3] = *(pData+ HeaderLen + 5);
+ PN[4] = *(pData+ HeaderLen + 6);
+ PN[5] = *(pData+ HeaderLen + 7);
+
+ payload_len = DataByteCnt - HeaderLen - 8 - 8; // 8 bytes for CCMP header , 8 bytes for MIC
+ payload_remainder = (payload_len) % 16;
+ num_blocks = (payload_len) / 16;
+
+
+
+ // Find start of payload
+ payload_index = HeaderLen + 8; //IV+EIV
+
+ for (i=0; i< num_blocks; i++)
+ {
+ construct_ctr_preload(ctr_preload,
+ a4_exists,
+ qc_exists,
+ pData,
+ PN,
+ i+1 );
+
+ aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out);
+
+ bitwise_xor(aes_out, pData + payload_index, chain_buffer);
+ NdisMoveMemory(pData + payload_index - 8, chain_buffer, 16);
+ payload_index += 16;
+ }
+
+ //
+ // If there is a short final block, then pad it
+ // encrypt it and copy the unpadded part back
+ //
+ if (payload_remainder > 0)
+ {
+ construct_ctr_preload(ctr_preload,
+ a4_exists,
+ qc_exists,
+ pData,
+ PN,
+ num_blocks + 1);
+
+ NdisZeroMemory(padded_buffer, 16);
+ NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder);
+
+ aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out);
+
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ NdisMoveMemory(pData + payload_index - 8, chain_buffer, payload_remainder);
+ payload_index += payload_remainder;
+ }
+
+ //
+ // Descrypt the MIC
+ //
+ construct_ctr_preload(ctr_preload,
+ a4_exists,
+ qc_exists,
+ pData,
+ PN,
+ 0);
+ NdisZeroMemory(padded_buffer, 16);
+ NdisMoveMemory(padded_buffer, pData + payload_index, 8);
+
+ aes128k128d(pWpaKey[KeyID].Key, ctr_preload, aes_out);
+
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+
+ NdisMoveMemory(TrailMIC, chain_buffer, 8);
+
+ //
+ // Calculate MIC
+ //
+
+ //Force the protected frame bit on
+ *(pData + 1) = *(pData + 1) | 0x40;
+
+ // Find start of payload
+ // Because the CCMP header has been removed
+ payload_index = HeaderLen;
+
+ construct_mic_iv(
+ mic_iv,
+ qc_exists,
+ a4_exists,
+ pData,
+ payload_len,
+ PN);
+
+ construct_mic_header1(
+ mic_header1,
+ HeaderLen,
+ pData);
+
+ construct_mic_header2(
+ mic_header2,
+ pData,
+ a4_exists,
+ qc_exists);
+
+ aes128k128d(pWpaKey[KeyID].Key, mic_iv, aes_out);
+ bitwise_xor(aes_out, mic_header1, chain_buffer);
+ aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+ bitwise_xor(aes_out, mic_header2, chain_buffer);
+ aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+
+ // iterate through each 16 byte payload block
+ for (i = 0; i < num_blocks; i++)
+ {
+ bitwise_xor(aes_out, pData + payload_index, chain_buffer);
+ payload_index += 16;
+ aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+ }
+
+ // Add on the final payload block if it needs padding
+ if (payload_remainder > 0)
+ {
+ NdisZeroMemory(padded_buffer, 16);
+ NdisMoveMemory(padded_buffer, pData + payload_index, payload_remainder);
+
+ bitwise_xor(aes_out, padded_buffer, chain_buffer);
+ aes128k128d(pWpaKey[KeyID].Key, chain_buffer, aes_out);
+ }
+ // aes_out contains padded mic, discard most significant
+ // 8 bytes to generate 64 bit MIC
+ for (i = 0 ; i < 8; i++) MIC[i] = aes_out[i];
+
+ if (!NdisEqualMemory(MIC, TrailMIC, 8))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPSoftDecryptAES, MIC Error !\n")); //MIC error.
+ return FALSE;
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pData, DIR_READ, FALSE);
+#endif
+
+ return TRUE;
+}
+
+/****************************************/
+/* aes128k128d() */
+/* Performs a 128 bit AES encrypt with */
+/* 128 bit data. */
+/****************************************/
+VOID xor_128(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out)
+{
+ INT i;
+
+ for (i=0;i<16; i++)
+ {
+ out[i] = a[i] ^ b[i];
+ }
+}
+
+VOID next_key(
+ IN PUCHAR key,
+ IN INT round)
+{
+ UCHAR rcon;
+ UCHAR sbox_key[4];
+ UCHAR rcon_table[12] =
+ {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+ 0x1b, 0x36, 0x36, 0x36
+ };
+
+ sbox_key[0] = RTMPCkipSbox(key[13]);
+ sbox_key[1] = RTMPCkipSbox(key[14]);
+ sbox_key[2] = RTMPCkipSbox(key[15]);
+ sbox_key[3] = RTMPCkipSbox(key[12]);
+
+ rcon = rcon_table[round];
+
+ xor_32(&key[0], sbox_key, &key[0]);
+ key[0] = key[0] ^ rcon;
+
+ xor_32(&key[4], &key[0], &key[4]);
+ xor_32(&key[8], &key[4], &key[8]);
+ xor_32(&key[12], &key[8], &key[12]);
+}
+
+VOID xor_32(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out)
+{
+ INT i;
+
+ for (i=0;i<4; i++)
+ {
+ out[i] = a[i] ^ b[i];
+ }
+}
+
+VOID byte_sub(
+ IN PUCHAR in,
+ OUT PUCHAR out)
+{
+ INT i;
+
+ for (i=0; i< 16; i++)
+ {
+ out[i] = RTMPCkipSbox(in[i]);
+ }
+}
+
+UCHAR RTMPCkipSbox(
+ IN UCHAR a)
+{
+ return SboxTable[(int)a];
+}
+
+VOID shift_row(
+ IN PUCHAR in,
+ OUT PUCHAR out)
+{
+ out[0] = in[0];
+ out[1] = in[5];
+ out[2] = in[10];
+ out[3] = in[15];
+ out[4] = in[4];
+ out[5] = in[9];
+ out[6] = in[14];
+ out[7] = in[3];
+ out[8] = in[8];
+ out[9] = in[13];
+ out[10] = in[2];
+ out[11] = in[7];
+ out[12] = in[12];
+ out[13] = in[1];
+ out[14] = in[6];
+ out[15] = in[11];
+}
+
+VOID mix_column(
+ IN PUCHAR in,
+ OUT PUCHAR out)
+{
+ INT i;
+ UCHAR add1b[4];
+ UCHAR add1bf7[4];
+ UCHAR rotl[4];
+ UCHAR swap_halfs[4];
+ UCHAR andf7[4];
+ UCHAR rotr[4];
+ UCHAR temp[4];
+ UCHAR tempb[4];
+
+ for (i=0 ; i<4; i++)
+ {
+ if ((in[i] & 0x80)== 0x80)
+ add1b[i] = 0x1b;
+ else
+ add1b[i] = 0x00;
+ }
+
+ swap_halfs[0] = in[2]; /* Swap halfs */
+ swap_halfs[1] = in[3];
+ swap_halfs[2] = in[0];
+ swap_halfs[3] = in[1];
+
+ rotl[0] = in[3]; /* Rotate left 8 bits */
+ rotl[1] = in[0];
+ rotl[2] = in[1];
+ rotl[3] = in[2];
+
+ andf7[0] = in[0] & 0x7f;
+ andf7[1] = in[1] & 0x7f;
+ andf7[2] = in[2] & 0x7f;
+ andf7[3] = in[3] & 0x7f;
+
+ for (i = 3; i>0; i--) /* logical shift left 1 bit */
+ {
+ andf7[i] = andf7[i] << 1;
+ if ((andf7[i-1] & 0x80) == 0x80)
+ {
+ andf7[i] = (andf7[i] | 0x01);
+ }
+ }
+ andf7[0] = andf7[0] << 1;
+ andf7[0] = andf7[0] & 0xfe;
+
+ xor_32(add1b, andf7, add1bf7);
+
+ xor_32(in, add1bf7, rotr);
+
+ temp[0] = rotr[0]; /* Rotate right 8 bits */
+ rotr[0] = rotr[1];
+ rotr[1] = rotr[2];
+ rotr[2] = rotr[3];
+ rotr[3] = temp[0];
+
+ xor_32(add1bf7, rotr, temp);
+ xor_32(swap_halfs, rotl,tempb);
+ xor_32(temp, tempb, out);
+}
+
diff --git a/drivers/staging/rt2860/common/rtmp_wep.c b/drivers/staging/rt2860/common/rtmp_wep.c
new file mode 100644
index 000000000000..ffe26c237950
--- /dev/null
+++ b/drivers/staging/rt2860/common/rtmp_wep.c
@@ -0,0 +1,499 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_wep.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Wu 10-28-02 Initial
+*/
+
+#include "../rt_config.h"
+
+UINT FCSTAB_32[256] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Init WEP function.
+
+ Arguments:
+ pAd Pointer to our adapter
+ pKey Pointer to the WEP KEY
+ KeyId WEP Key ID
+ KeyLen the length of WEP KEY
+ pDest Pointer to the destination which Encryption data will store in.
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPInitWepEngine(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKey,
+ IN UCHAR KeyId,
+ IN UCHAR KeyLen,
+ IN OUT PUCHAR pDest)
+{
+ UINT i;
+ UCHAR WEPKEY[] = {
+ //IV
+ 0x00, 0x11, 0x22,
+ //WEP KEY
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC
+ };
+
+ pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32.
+
+#ifdef CONFIG_STA_SUPPORT
+ if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10) && (pAd->OpMode == OPMODE_STA))
+ {
+ ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, pKey, KeyLen); //INIT SBOX, KEYLEN+3(IV)
+ NdisMoveMemory(pDest, pKey, 3); //Append Init Vector
+ }
+ else
+#endif // CONFIG_STA_SUPPORT //
+ {
+ NdisMoveMemory(WEPKEY + 3, pKey, KeyLen);
+
+ for(i = 0; i < 3; i++)
+ WEPKEY[i] = RandomByte(pAd); //Call mlme RandomByte() function.
+ ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, KeyLen + 3); //INIT SBOX, KEYLEN+3(IV)
+
+ NdisMoveMemory(pDest, WEPKEY, 3); //Append Init Vector
+ }
+ *(pDest+3) = (KeyId << 6); //Append KEYID
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Encrypt transimitted data
+
+ Arguments:
+ pAd Pointer to our adapter
+ pSrc Pointer to the transimitted source data that will be encrypt
+ pDest Pointer to the destination where entryption data will be store in.
+ Len Indicate the length of the source data
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPEncryptData(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pSrc,
+ IN PUCHAR pDest,
+ IN UINT Len)
+{
+ pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, pSrc, Len);
+ ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, pSrc, Len);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Decrypt received WEP data
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ pSrc Pointer to the received data
+ Len the length of the received data
+
+ Return Value:
+ TRUE Decrypt WEP data success
+ FALSE Decrypt WEP data failed
+
+ Note:
+
+ ========================================================================
+*/
+BOOLEAN RTMPSoftDecryptWEP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataByteCnt,
+ IN PCIPHER_KEY pGroupKey)
+{
+ UINT trailfcs;
+ UINT crc32;
+ UCHAR KeyIdx;
+ UCHAR WEPKEY[] = {
+ //IV
+ 0x00, 0x11, 0x22,
+ //WEP KEY
+ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC
+ };
+ UCHAR *pPayload = (UCHAR *)pData + LENGTH_802_11;
+ ULONG payload_len = DataByteCnt - LENGTH_802_11;
+
+ NdisMoveMemory(WEPKEY, pPayload, 3); //Get WEP IV
+
+ KeyIdx = (*(pPayload + 3) & 0xc0) >> 6;
+ if (pGroupKey[KeyIdx].KeyLen == 0)
+ return (FALSE);
+
+ NdisMoveMemory(WEPKEY + 3, pGroupKey[KeyIdx].Key, pGroupKey[KeyIdx].KeyLen);
+ ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, WEPKEY, pGroupKey[KeyIdx].KeyLen + 3);
+ ARCFOUR_DECRYPT(&pAd->PrivateInfo.WEPCONTEXT, pPayload, pPayload + 4, payload_len - 4);
+ NdisMoveMemory(&trailfcs, pPayload + payload_len - 8, 4);
+ crc32 = RTMP_CALC_FCS32(PPPINITFCS32, pPayload, payload_len - 8); //Skip last 4 bytes(FCS).
+ crc32 ^= 0xffffffff; /* complement */
+
+ if(crc32 != cpu2le32(trailfcs))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("! WEP Data CRC Error !\n")); //CRC error.
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ The Stream Cipher Encryption Algorithm "ARCFOUR" initialize
+
+ Arguments:
+ Ctx Pointer to ARCFOUR CONTEXT (SBOX)
+ pKey Pointer to the WEP KEY
+ KeyLen Indicate the length fo the WEP KEY
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID ARCFOUR_INIT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pKey,
+ IN UINT KeyLen)
+{
+ UCHAR t, u;
+ UINT keyindex;
+ UINT stateindex;
+ PUCHAR state;
+ UINT counter;
+
+ state = Ctx->STATE;
+ Ctx->X = 0;
+ Ctx->Y = 0;
+ for (counter = 0; counter < 256; counter++)
+ state[counter] = (UCHAR)counter;
+ keyindex = 0;
+ stateindex = 0;
+ for (counter = 0; counter < 256; counter++)
+ {
+ t = state[counter];
+ stateindex = (stateindex + pKey[keyindex] + t) & 0xff;
+ u = state[stateindex];
+ state[stateindex] = t;
+ state[counter] = u;
+ if (++keyindex >= KeyLen)
+ keyindex = 0;
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get bytes from ARCFOUR CONTEXT (S-BOX)
+
+ Arguments:
+ Ctx Pointer to ARCFOUR CONTEXT (SBOX)
+
+ Return Value:
+ UCHAR - the value of the ARCFOUR CONTEXT (S-BOX)
+
+ Note:
+
+ ========================================================================
+*/
+UCHAR ARCFOUR_BYTE(
+ IN PARCFOURCONTEXT Ctx)
+{
+ UINT x;
+ UINT y;
+ UCHAR sx, sy;
+ PUCHAR state;
+
+ state = Ctx->STATE;
+ x = (Ctx->X + 1) & 0xff;
+ sx = state[x];
+ y = (sx + Ctx->Y) & 0xff;
+ sy = state[y];
+ Ctx->X = x;
+ Ctx->Y = y;
+ state[y] = sx;
+ state[x] = sy;
+
+ return(state[(sx + sy) & 0xff]);
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ The Stream Cipher Decryption Algorithm
+
+ Arguments:
+ Ctx Pointer to ARCFOUR CONTEXT (SBOX)
+ pDest Pointer to the Destination
+ pSrc Pointer to the Source data
+ Len Indicate the length of the Source data
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID ARCFOUR_DECRYPT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pDest,
+ IN PUCHAR pSrc,
+ IN UINT Len)
+{
+ UINT i;
+
+ for (i = 0; i < Len; i++)
+ pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ The Stream Cipher Encryption Algorithm
+
+ Arguments:
+ Ctx Pointer to ARCFOUR CONTEXT (SBOX)
+ pDest Pointer to the Destination
+ pSrc Pointer to the Source data
+ Len Indicate the length of the Source dta
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+VOID ARCFOUR_ENCRYPT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pDest,
+ IN PUCHAR pSrc,
+ IN UINT Len)
+{
+ UINT i;
+
+ for (i = 0; i < Len; i++)
+ pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx);
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ The Stream Cipher Encryption Algorithm which conform to the special requirement to encrypt GTK.
+
+ Arguments:
+ Ctx Pointer to ARCFOUR CONTEXT (SBOX)
+ pDest Pointer to the Destination
+ pSrc Pointer to the Source data
+ Len Indicate the length of the Source dta
+
+
+ ========================================================================
+*/
+
+VOID WPAARCFOUR_ENCRYPT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pDest,
+ IN PUCHAR pSrc,
+ IN UINT Len)
+{
+ UINT i;
+ //discard first 256 bytes
+ for (i = 0; i < 256; i++)
+ ARCFOUR_BYTE(Ctx);
+
+ for (i = 0; i < Len; i++)
+ pDest[i] = pSrc[i] ^ ARCFOUR_BYTE(Ctx);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Calculate a new FCS given the current FCS and the new data.
+
+ Arguments:
+ Fcs the original FCS value
+ Cp pointer to the data which will be calculate the FCS
+ Len the length of the data
+
+ Return Value:
+ UINT - FCS 32 bits
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+UINT RTMP_CALC_FCS32(
+ IN UINT Fcs,
+ IN PUCHAR Cp,
+ IN INT Len)
+{
+ while (Len--)
+ Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]);
+
+ return (Fcs);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get last FCS and encrypt it to the destination
+
+ Arguments:
+ pDest Pointer to the Destination
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID RTMPSetICV(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDest)
+{
+ pAd->PrivateInfo.FCSCRC32 ^= 0xffffffff; /* complement */
+ pAd->PrivateInfo.FCSCRC32 = cpu2le32(pAd->PrivateInfo.FCSCRC32);
+
+ ARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, pDest, (PUCHAR) &pAd->PrivateInfo.FCSCRC32, 4);
+}
+
diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c
new file mode 100644
index 000000000000..0265a6d1df1a
--- /dev/null
+++ b/drivers/staging/rt2860/common/spectrum.c
@@ -0,0 +1,1877 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+
+ Module Name:
+ action.c
+
+ Abstract:
+ Handle association related requests either from WSTA or from local MLME
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ Fonchi Wu 2008 created for 802.11h
+ */
+
+#include "../rt_config.h"
+#include "action.h"
+
+VOID MeasureReqTabInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
+
+ pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
+ if (pAd->CommonCfg.pMeasureReqTab)
+ NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB));
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__));
+
+ return;
+}
+
+VOID MeasureReqTabExit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock);
+
+ if (pAd->CommonCfg.pMeasureReqTab)
+ kfree(pAd->CommonCfg.pMeasureReqTab);
+ pAd->CommonCfg.pMeasureReqTab = NULL;
+
+ return;
+}
+
+static PMEASURE_REQ_ENTRY MeasureReqLookUp(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DialogToken)
+{
+ UINT HashIdx;
+ PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
+ PMEASURE_REQ_ENTRY pEntry = NULL;
+ PMEASURE_REQ_ENTRY pPrevEntry = NULL;
+
+ if (pTab == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
+ return NULL;
+ }
+
+ RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
+
+ HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
+ pEntry = pTab->Hash[HashIdx];
+
+ while (pEntry)
+ {
+ if (pEntry->DialogToken == DialogToken)
+ break;
+ else
+ {
+ pPrevEntry = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+
+ RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
+
+ return pEntry;
+}
+
+static PMEASURE_REQ_ENTRY MeasureReqInsert(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DialogToken)
+{
+ INT i;
+ ULONG HashIdx;
+ PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
+ PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
+ ULONG Now;
+
+ if(pTab == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
+ return NULL;
+ }
+
+ pEntry = MeasureReqLookUp(pAd, DialogToken);
+ if (pEntry == NULL)
+ {
+ RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
+ for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
+ {
+ NdisGetSystemUpTime(&Now);
+ pEntry = &pTab->Content[i];
+
+ if ((pEntry->Valid == TRUE)
+ && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
+ {
+ PMEASURE_REQ_ENTRY pPrevEntry = NULL;
+ ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+ PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+ // update Hash list
+ do
+ {
+ if (pProbeEntry == pEntry)
+ {
+ if (pPrevEntry == NULL)
+ {
+ pTab->Hash[HashIdx] = pEntry->pNext;
+ }
+ else
+ {
+ pPrevEntry->pNext = pEntry->pNext;
+ }
+ break;
+ }
+
+ pPrevEntry = pProbeEntry;
+ pProbeEntry = pProbeEntry->pNext;
+ } while (pProbeEntry);
+
+ NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
+ pTab->Size--;
+
+ break;
+ }
+
+ if (pEntry->Valid == FALSE)
+ break;
+ }
+
+ if (i < MAX_MEASURE_REQ_TAB_SIZE)
+ {
+ NdisGetSystemUpTime(&Now);
+ pEntry->lastTime = Now;
+ pEntry->Valid = TRUE;
+ pEntry->DialogToken = DialogToken;
+ pTab->Size++;
+ }
+ else
+ {
+ pEntry = NULL;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__));
+ }
+
+ // add this Neighbor entry into HASH table
+ if (pEntry)
+ {
+ HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
+ if (pTab->Hash[HashIdx] == NULL)
+ {
+ pTab->Hash[HashIdx] = pEntry;
+ }
+ else
+ {
+ pCurrEntry = pTab->Hash[HashIdx];
+ while (pCurrEntry->pNext != NULL)
+ pCurrEntry = pCurrEntry->pNext;
+ pCurrEntry->pNext = pEntry;
+ }
+ }
+
+ RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
+ }
+
+ return pEntry;
+}
+
+static VOID MeasureReqDelete(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DialogToken)
+{
+ PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
+ PMEASURE_REQ_ENTRY pEntry = NULL;
+
+ if(pTab == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
+ return;
+ }
+
+ // if empty, return
+ if (pTab->Size == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
+ return;
+ }
+
+ pEntry = MeasureReqLookUp(pAd, DialogToken);
+ if (pEntry != NULL)
+ {
+ PMEASURE_REQ_ENTRY pPrevEntry = NULL;
+ ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+ PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+ RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
+ // update Hash list
+ do
+ {
+ if (pProbeEntry == pEntry)
+ {
+ if (pPrevEntry == NULL)
+ {
+ pTab->Hash[HashIdx] = pEntry->pNext;
+ }
+ else
+ {
+ pPrevEntry->pNext = pEntry->pNext;
+ }
+ break;
+ }
+
+ pPrevEntry = pProbeEntry;
+ pProbeEntry = pProbeEntry->pNext;
+ } while (pProbeEntry);
+
+ NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
+ pTab->Size--;
+
+ RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
+ }
+
+ return;
+}
+
+VOID TpcReqTabInit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
+
+ pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
+ if (pAd->CommonCfg.pTpcReqTab)
+ NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__));
+
+ return;
+}
+
+VOID TpcReqTabExit(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock);
+
+ if (pAd->CommonCfg.pTpcReqTab)
+ kfree(pAd->CommonCfg.pTpcReqTab);
+ pAd->CommonCfg.pTpcReqTab = NULL;
+
+ return;
+}
+
+static PTPC_REQ_ENTRY TpcReqLookUp(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DialogToken)
+{
+ UINT HashIdx;
+ PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
+ PTPC_REQ_ENTRY pEntry = NULL;
+ PTPC_REQ_ENTRY pPrevEntry = NULL;
+
+ if (pTab == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
+ return NULL;
+ }
+
+ RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
+
+ HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
+ pEntry = pTab->Hash[HashIdx];
+
+ while (pEntry)
+ {
+ if (pEntry->DialogToken == DialogToken)
+ break;
+ else
+ {
+ pPrevEntry = pEntry;
+ pEntry = pEntry->pNext;
+ }
+ }
+
+ RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
+
+ return pEntry;
+}
+
+
+static PTPC_REQ_ENTRY TpcReqInsert(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DialogToken)
+{
+ INT i;
+ ULONG HashIdx;
+ PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
+ PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
+ ULONG Now;
+
+ if(pTab == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
+ return NULL;
+ }
+
+ pEntry = TpcReqLookUp(pAd, DialogToken);
+ if (pEntry == NULL)
+ {
+ RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
+ for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
+ {
+ NdisGetSystemUpTime(&Now);
+ pEntry = &pTab->Content[i];
+
+ if ((pEntry->Valid == TRUE)
+ && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
+ {
+ PTPC_REQ_ENTRY pPrevEntry = NULL;
+ ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+ PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+ // update Hash list
+ do
+ {
+ if (pProbeEntry == pEntry)
+ {
+ if (pPrevEntry == NULL)
+ {
+ pTab->Hash[HashIdx] = pEntry->pNext;
+ }
+ else
+ {
+ pPrevEntry->pNext = pEntry->pNext;
+ }
+ break;
+ }
+
+ pPrevEntry = pProbeEntry;
+ pProbeEntry = pProbeEntry->pNext;
+ } while (pProbeEntry);
+
+ NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
+ pTab->Size--;
+
+ break;
+ }
+
+ if (pEntry->Valid == FALSE)
+ break;
+ }
+
+ if (i < MAX_TPC_REQ_TAB_SIZE)
+ {
+ NdisGetSystemUpTime(&Now);
+ pEntry->lastTime = Now;
+ pEntry->Valid = TRUE;
+ pEntry->DialogToken = DialogToken;
+ pTab->Size++;
+ }
+ else
+ {
+ pEntry = NULL;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__));
+ }
+
+ // add this Neighbor entry into HASH table
+ if (pEntry)
+ {
+ HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
+ if (pTab->Hash[HashIdx] == NULL)
+ {
+ pTab->Hash[HashIdx] = pEntry;
+ }
+ else
+ {
+ pCurrEntry = pTab->Hash[HashIdx];
+ while (pCurrEntry->pNext != NULL)
+ pCurrEntry = pCurrEntry->pNext;
+ pCurrEntry->pNext = pEntry;
+ }
+ }
+
+ RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
+ }
+
+ return pEntry;
+}
+
+static VOID TpcReqDelete(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 DialogToken)
+{
+ PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
+ PTPC_REQ_ENTRY pEntry = NULL;
+
+ if(pTab == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
+ return;
+ }
+
+ // if empty, return
+ if (pTab->Size == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
+ return;
+ }
+
+ pEntry = TpcReqLookUp(pAd, DialogToken);
+ if (pEntry != NULL)
+ {
+ PTPC_REQ_ENTRY pPrevEntry = NULL;
+ ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
+ PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
+
+ RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
+ // update Hash list
+ do
+ {
+ if (pProbeEntry == pEntry)
+ {
+ if (pPrevEntry == NULL)
+ {
+ pTab->Hash[HashIdx] = pEntry->pNext;
+ }
+ else
+ {
+ pPrevEntry->pNext = pEntry->pNext;
+ }
+ break;
+ }
+
+ pPrevEntry = pProbeEntry;
+ pProbeEntry = pProbeEntry->pNext;
+ } while (pProbeEntry);
+
+ NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
+ pTab->Size--;
+
+ RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
+ }
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Get Current TimeS tamp.
+
+ Parametrs:
+
+ Return : Current Time Stamp.
+ ==========================================================================
+ */
+static UINT64 GetCurrentTimeStamp(
+ IN PRTMP_ADAPTER pAd)
+{
+ // get current time stamp.
+ return 0;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Get Current Transmit Power.
+
+ Parametrs:
+
+ Return : Current Time Stamp.
+ ==========================================================================
+ */
+static UINT8 GetCurTxPwr(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 Wcid)
+{
+ return 16; /* 16 dBm */
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert Dialog Token into frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. Dialog token.
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID InsertDialogToken(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN UINT8 DialogToken)
+{
+ ULONG TempLen;
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &DialogToken,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert TPC Request IE into frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+
+ Return : None.
+ ==========================================================================
+ */
+ static VOID InsertTpcReqIE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen)
+{
+ ULONG TempLen;
+ ULONG Len = 0;
+ UINT8 ElementID = IE_TPC_REQUEST;
+
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &ElementID,
+ 1, &Len,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert TPC Report IE into frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. Transmit Power.
+ 4. Link Margin.
+
+ Return : None.
+ ==========================================================================
+ */
+ static VOID InsertTpcReportIE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN UINT8 TxPwr,
+ IN UINT8 LinkMargin)
+{
+ ULONG TempLen;
+ ULONG Len = sizeof(TPC_REPORT_INFO);
+ UINT8 ElementID = IE_TPC_REPORT;
+ TPC_REPORT_INFO TpcReportIE;
+
+ TpcReportIE.TxPwr = TxPwr;
+ TpcReportIE.LinkMargin = LinkMargin;
+
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &ElementID,
+ 1, &Len,
+ Len, &TpcReportIE,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert Channel Switch Announcement IE into frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. channel switch announcement mode.
+ 4. new selected channel.
+ 5. channel switch announcement count.
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID InsertChSwAnnIE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN UINT8 ChSwMode,
+ IN UINT8 NewChannel,
+ IN UINT8 ChSwCnt)
+{
+ ULONG TempLen;
+ ULONG Len = sizeof(CH_SW_ANN_INFO);
+ UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
+ CH_SW_ANN_INFO ChSwAnnIE;
+
+ ChSwAnnIE.ChSwMode = ChSwMode;
+ ChSwAnnIE.Channel = NewChannel;
+ ChSwAnnIE.ChSwCnt = ChSwCnt;
+
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &ElementID,
+ 1, &Len,
+ Len, &ChSwAnnIE,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert Measure Request IE into frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. Measure Token.
+ 4. Measure Request Mode.
+ 5. Measure Request Type.
+ 6. Measure Channel.
+ 7. Measure Start time.
+ 8. Measure Duration.
+
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID InsertMeasureReqIE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN PMEASURE_REQ_INFO pMeasureReqIE)
+{
+ ULONG TempLen;
+ UINT8 Len = sizeof(MEASURE_REQ_INFO);
+ UINT8 ElementID = IE_MEASUREMENT_REQUEST;
+
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &ElementID,
+ 1, &Len,
+ Len, pMeasureReqIE,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Insert Measure Report IE into frame.
+
+ Parametrs:
+ 1. frame buffer pointer.
+ 2. frame length.
+ 3. Measure Token.
+ 4. Measure Request Mode.
+ 5. Measure Request Type.
+ 6. Length of Report Infomation
+ 7. Pointer of Report Infomation Buffer.
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID InsertMeasureReportIE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN PMEASURE_REPORT_INFO pMeasureReportIE,
+ IN UINT8 ReportLnfoLen,
+ IN PUINT8 pReportInfo)
+{
+ ULONG TempLen;
+ ULONG Len;
+ UINT8 ElementID = IE_MEASUREMENT_REPORT;
+
+ Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
+
+ MakeOutgoingFrame(pFrameBuf, &TempLen,
+ 1, &ElementID,
+ 1, &Len,
+ Len, pMeasureReportIE,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+
+ if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
+ {
+ MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
+ ReportLnfoLen, pReportInfo,
+ END_OF_ARGS);
+
+ *pFrameLen = *pFrameLen + TempLen;
+ }
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Prepare Measurement request action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueMeasurementReq(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 MeasureToken,
+ IN UINT8 MeasureReqMode,
+ IN UINT8 MeasureReqType,
+ IN UINT8 MeasureCh,
+ IN UINT16 MeasureDuration)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+ HEADER_802_11 ActHdr;
+ MEASURE_REQ_INFO MeasureReqIE;
+ UINT8 RmReqDailogToken = RandomByte(pAd);
+ UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
+
+ // build action frame header.
+ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+ pAd->CurrentAddress);
+
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
+ return;
+ }
+ NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+ FrameLen = sizeof(HEADER_802_11);
+
+ InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ);
+
+ // fill Dialog Token
+ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken);
+
+ // prepare Measurement IE.
+ NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
+ MeasureReqIE.Token = RmReqDailogToken;
+ MeasureReqIE.ReqMode.word = MeasureReqMode;
+ MeasureReqIE.ReqType = MeasureReqType;
+ MeasureReqIE.MeasureReq.ChNum = MeasureCh;
+ MeasureReqIE.MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
+ MeasureReqIE.MeasureReq.MeasureDuration = cpu2le16(MeasureDuration);
+ InsertMeasureReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureReqIE);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Prepare Measurement report action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueMeasurementRep(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 DialogToken,
+ IN UINT8 MeasureToken,
+ IN UINT8 MeasureReqMode,
+ IN UINT8 MeasureReqType,
+ IN UINT8 ReportInfoLen,
+ IN PUINT8 pReportInfo)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+ HEADER_802_11 ActHdr;
+ MEASURE_REPORT_INFO MeasureRepIE;
+
+ // build action frame header.
+ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+ pAd->CurrentAddress);
+
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
+ return;
+ }
+ NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+ FrameLen = sizeof(HEADER_802_11);
+
+ InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
+
+ // fill Dialog Token
+ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
+
+ // prepare Measurement IE.
+ NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
+ MeasureRepIE.Token = MeasureToken;
+ MeasureRepIE.ReportMode.word = MeasureReqMode;
+ MeasureRepIE.ReportType = MeasureReqType;
+ InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Prepare TPC Request action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueTPCReq(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UCHAR DialogToken)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+
+ HEADER_802_11 ActHdr;
+
+ // build action frame header.
+ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+ pAd->CurrentAddress);
+
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
+ return;
+ }
+ NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+ FrameLen = sizeof(HEADER_802_11);
+
+ InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
+
+ // fill Dialog Token
+ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
+
+ // Insert TPC Request IE.
+ InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Prepare TPC Report action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueTPCRep(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 DialogToken,
+ IN UINT8 TxPwr,
+ IN UINT8 LinkMargin)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+
+ HEADER_802_11 ActHdr;
+
+ // build action frame header.
+ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+ pAd->CurrentAddress);
+
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
+ return;
+ }
+ NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+ FrameLen = sizeof(HEADER_802_11);
+
+ InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
+
+ // fill Dialog Token
+ InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
+
+ // Insert TPC Request IE.
+ InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Prepare Channel Switch Announcement action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+ 2. Channel switch announcement mode.
+ 2. a New selected channel.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueChSwAnn(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 ChSwMode,
+ IN UINT8 NewCh)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen;
+
+ HEADER_802_11 ActHdr;
+
+ // build action frame header.
+ MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
+ pAd->CurrentAddress);
+
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
+ return;
+ }
+ NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
+ FrameLen = sizeof(HEADER_802_11);
+
+ InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
+
+ InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ return;
+}
+
+static BOOLEAN DfsRequirementCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT8 Channel)
+{
+ BOOLEAN Result = FALSE;
+ INT i;
+
+ do
+ {
+ // check DFS procedure is running.
+ // make sure DFS procedure won't start twice.
+ if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
+ {
+ Result = FALSE;
+ break;
+ }
+
+ // check the new channel carried from Channel Switch Announcemnet is valid.
+ for (i=0; i<pAd->ChannelListNum; i++)
+ {
+ if ((Channel == pAd->ChannelList[i].Channel)
+ &&(pAd->ChannelList[i].RemainingTimeForUse == 0))
+ {
+ // found radar signal in the channel. the channel can't use at least for 30 minutes.
+ pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec
+ Result = TRUE;
+ break;
+ }
+ }
+ } while(FALSE);
+
+ return Result;
+}
+
+VOID NotifyChSwAnnToPeerAPs(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pRA,
+ IN PUCHAR pTA,
+ IN UINT8 ChSwMode,
+ IN UINT8 Channel)
+{
+#ifdef WDS_SUPPORT
+ if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address.
+ {
+ INT i;
+ // info neighbor APs that Radar signal found throgh WDS link.
+ for (i = 0; i < MAX_WDS_ENTRY; i++)
+ {
+ if (ValidWdsEntry(pAd, i))
+ {
+ PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr;
+
+ // DA equal to SA. have no necessary orignal AP which found Radar signal.
+ if (MAC_ADDR_EQUAL(pTA, pDA))
+ continue;
+
+ // send Channel Switch Action frame to info Neighbro APs.
+ EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel);
+ }
+ }
+ }
+#endif // WDS_SUPPORT //
+}
+
+static VOID StartDFSProcedure(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel,
+ IN UINT8 ChSwMode)
+{
+ // start DFS procedure
+ pAd->CommonCfg.Channel = Channel;
+#ifdef DOT11_N_SUPPORT
+ N_ChannelCheck(pAd);
+#endif // DOT11_N_SUPPORT //
+ pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
+ pAd->CommonCfg.RadarDetect.CSCount = 0;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Channel Switch Announcement action frame sanity check.
+
+ Parametrs:
+ 1. MLME message containing the received frame
+ 2. message length.
+ 3. Channel switch announcement infomation buffer.
+
+
+ Return : None.
+ ==========================================================================
+ */
+
+/*
+ Channel Switch Announcement IE.
+ +----+-----+-----------+------------+-----------+
+ | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
+ +----+-----+-----------+------------+-----------+
+ 1 1 1 1 1
+*/
+static BOOLEAN PeerChSwAnnSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PCH_SW_ANN_INFO pChSwAnnInfo)
+{
+ PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+ PUCHAR pFramePtr = Fr->Octet;
+ BOOLEAN result = FALSE;
+ PEID_STRUCT eid_ptr;
+
+ // skip 802.11 header.
+ MsgLen -= sizeof(HEADER_802_11);
+
+ // skip category and action code.
+ pFramePtr += 2;
+ MsgLen -= 2;
+
+ if (pChSwAnnInfo == NULL)
+ return result;
+
+ eid_ptr = (PEID_STRUCT)pFramePtr;
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
+ NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
+ NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
+ NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
+
+ result = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return result;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Measurement request action frame sanity check.
+
+ Parametrs:
+ 1. MLME message containing the received frame
+ 2. message length.
+ 3. Measurement request infomation buffer.
+
+ Return : None.
+ ==========================================================================
+ */
+static BOOLEAN PeerMeasureReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUINT8 pDialogToken,
+ OUT PMEASURE_REQ_INFO pMeasureReqInfo)
+{
+ PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+ PUCHAR pFramePtr = Fr->Octet;
+ BOOLEAN result = FALSE;
+ PEID_STRUCT eid_ptr;
+ PUCHAR ptr;
+ UINT64 MeasureStartTime;
+ UINT16 MeasureDuration;
+
+ // skip 802.11 header.
+ MsgLen -= sizeof(HEADER_802_11);
+
+ // skip category and action code.
+ pFramePtr += 2;
+ MsgLen -= 2;
+
+ if (pMeasureReqInfo == NULL)
+ return result;
+
+ NdisMoveMemory(pDialogToken, pFramePtr, 1);
+ pFramePtr += 1;
+ MsgLen -= 1;
+
+ eid_ptr = (PEID_STRUCT)pFramePtr;
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_MEASUREMENT_REQUEST:
+ NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
+ NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
+ NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
+ ptr = eid_ptr->Octet + 3;
+ NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1);
+ NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
+ pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime);
+ NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
+ pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration);
+
+ result = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return result;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Measurement report action frame sanity check.
+
+ Parametrs:
+ 1. MLME message containing the received frame
+ 2. message length.
+ 3. Measurement report infomation buffer.
+ 4. basic report infomation buffer.
+
+ Return : None.
+ ==========================================================================
+ */
+
+/*
+ Measurement Report IE.
+ +----+-----+-------+-------------+--------------+----------------+
+ | ID | Len | Token | Report Mode | Measure Type | Measure Report |
+ +----+-----+-------+-------------+--------------+----------------+
+ 1 1 1 1 1 variable
+
+ Basic Report.
+ +--------+------------+----------+-----+
+ | Ch Num | Start Time | Duration | Map |
+ +--------+------------+----------+-----+
+ 1 8 2 1
+
+ Map Field Bit Format.
+ +-----+---------------+---------------------+-------+------------+----------+
+ | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
+ +-----+---------------+---------------------+-------+------------+----------+
+ 0 1 2 3 4 5-7
+*/
+static BOOLEAN PeerMeasureReportSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUINT8 pDialogToken,
+ OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
+ OUT PUINT8 pReportBuf)
+{
+ PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+ PUCHAR pFramePtr = Fr->Octet;
+ BOOLEAN result = FALSE;
+ PEID_STRUCT eid_ptr;
+ PUCHAR ptr;
+
+ // skip 802.11 header.
+ MsgLen -= sizeof(HEADER_802_11);
+
+ // skip category and action code.
+ pFramePtr += 2;
+ MsgLen -= 2;
+
+ if (pMeasureReportInfo == NULL)
+ return result;
+
+ NdisMoveMemory(pDialogToken, pFramePtr, 1);
+ pFramePtr += 1;
+ MsgLen -= 1;
+
+ eid_ptr = (PEID_STRUCT)pFramePtr;
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_MEASUREMENT_REPORT:
+ NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
+ NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
+ NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
+ if (pMeasureReportInfo->ReportType == RM_BASIC)
+ {
+ PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
+ ptr = eid_ptr->Octet + 3;
+ NdisMoveMemory(&pReport->ChNum, ptr, 1);
+ NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
+ NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
+ NdisMoveMemory(&pReport->Map, ptr + 11, 1);
+
+ }
+ else if (pMeasureReportInfo->ReportType == RM_CCA)
+ {
+ PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
+ ptr = eid_ptr->Octet + 3;
+ NdisMoveMemory(&pReport->ChNum, ptr, 1);
+ NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
+ NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
+ NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
+
+ }
+ else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
+ {
+ PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
+ ptr = eid_ptr->Octet + 3;
+ NdisMoveMemory(&pReport->ChNum, ptr, 1);
+ NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
+ NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
+ NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
+ }
+ result = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return result;
+}
+
+/*
+ ==========================================================================
+ Description:
+ TPC Request action frame sanity check.
+
+ Parametrs:
+ 1. MLME message containing the received frame
+ 2. message length.
+ 3. Dialog Token.
+
+ Return : None.
+ ==========================================================================
+ */
+static BOOLEAN PeerTpcReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUINT8 pDialogToken)
+{
+ PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+ PUCHAR pFramePtr = Fr->Octet;
+ BOOLEAN result = FALSE;
+ PEID_STRUCT eid_ptr;
+
+ MsgLen -= sizeof(HEADER_802_11);
+
+ // skip category and action code.
+ pFramePtr += 2;
+ MsgLen -= 2;
+
+ if (pDialogToken == NULL)
+ return result;
+
+ NdisMoveMemory(pDialogToken, pFramePtr, 1);
+ pFramePtr += 1;
+ MsgLen -= 1;
+
+ eid_ptr = (PEID_STRUCT)pFramePtr;
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_TPC_REQUEST:
+ result = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return result;
+}
+
+/*
+ ==========================================================================
+ Description:
+ TPC Report action frame sanity check.
+
+ Parametrs:
+ 1. MLME message containing the received frame
+ 2. message length.
+ 3. Dialog Token.
+ 4. TPC Report IE.
+
+ Return : None.
+ ==========================================================================
+ */
+static BOOLEAN PeerTpcRepSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUINT8 pDialogToken,
+ OUT PTPC_REPORT_INFO pTpcRepInfo)
+{
+ PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
+ PUCHAR pFramePtr = Fr->Octet;
+ BOOLEAN result = FALSE;
+ PEID_STRUCT eid_ptr;
+
+ MsgLen -= sizeof(HEADER_802_11);
+
+ // skip category and action code.
+ pFramePtr += 2;
+ MsgLen -= 2;
+
+ if (pDialogToken == NULL)
+ return result;
+
+ NdisMoveMemory(pDialogToken, pFramePtr, 1);
+ pFramePtr += 1;
+ MsgLen -= 1;
+
+ eid_ptr = (PEID_STRUCT)pFramePtr;
+ while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
+ {
+ switch(eid_ptr->Eid)
+ {
+ case IE_TPC_REPORT:
+ NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
+ NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
+ result = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
+ }
+
+ return result;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Channel Switch Announcement action frame handler.
+
+ Parametrs:
+ Elme - MLME message containing the received frame
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID PeerChSwAnnAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ CH_SW_ANN_INFO ChSwAnnInfo;
+ PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+#ifdef CONFIG_STA_SUPPORT
+ UCHAR index = 0, Channel = 0, NewChannel = 0;
+ ULONG Bssidx = 0;
+#endif // CONFIG_STA_SUPPORT //
+
+ NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
+ if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
+ return;
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+ if (pAd->OpMode == OPMODE_STA)
+ {
+ Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
+ if (Bssidx == BSS_NOT_FOUND)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
+ hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
+
+ Channel = pAd->CommonCfg.Channel;
+ NewChannel = ChSwAnnInfo.Channel;
+
+ if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
+ {
+ // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
+ // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
+ AsicSwitchChannel(pAd, 1, FALSE);
+ AsicLockChannel(pAd, 1);
+ LinkDown(pAd, FALSE);
+ MlmeQueueInit(&pAd->Mlme.Queue);
+ BssTableInit(&pAd->ScanTab);
+ RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
+
+ // channel sanity check
+ for (index = 0 ; index < pAd->ChannelListNum; index++)
+ {
+ if (pAd->ChannelList[index].Channel == NewChannel)
+ {
+ pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
+ pAd->CommonCfg.Channel = NewChannel;
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
+ break;
+ }
+ }
+
+ if (index >= pAd->ChannelListNum)
+ {
+ DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
+ }
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ return;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Measurement Request action frame handler.
+
+ Parametrs:
+ Elme - MLME message containing the received frame
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID PeerMeasureReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+ UINT8 DialogToken;
+ MEASURE_REQ_INFO MeasureReqInfo;
+ MEASURE_REPORT_MODE ReportMode;
+
+ if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo))
+ {
+ ReportMode.word = 0;
+ ReportMode.field.Incapable = 1;
+ EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
+ }
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Measurement Report action frame handler.
+
+ Parametrs:
+ Elme - MLME message containing the received frame
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID PeerMeasureReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MEASURE_REPORT_INFO MeasureReportInfo;
+ PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+ UINT8 DialogToken;
+ PUINT8 pMeasureReportInfo;
+
+// if (pAd->CommonCfg.bIEEE80211H != TRUE)
+// return;
+
+ if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
+ return;
+ }
+
+ NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
+ NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
+ if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
+ {
+ do {
+ PMEASURE_REQ_ENTRY pEntry = NULL;
+
+ // Not a autonomous measure report.
+ // check the dialog token field. drop it if the dialog token doesn't match.
+ if ((DialogToken != 0)
+ && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
+ break;
+
+ if (pEntry != NULL)
+ MeasureReqDelete(pAd, pEntry->DialogToken);
+
+ if (MeasureReportInfo.ReportType == RM_BASIC)
+ {
+ PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
+ if ((pBasicReport->Map.field.Radar)
+ && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
+ {
+ NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
+ StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
+ }
+ }
+ } while (FALSE);
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
+
+ kfree(pMeasureReportInfo);
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ TPC Request action frame handler.
+
+ Parametrs:
+ Elme - MLME message containing the received frame
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID PeerTpcReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
+ PUCHAR pFramePtr = pFr->Octet;
+ UINT8 DialogToken;
+ UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
+ UINT8 LinkMargin = 0;
+ CHAR RealRssi;
+
+ // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
+ // STA may incorporate rate information and channel conditions, including interference, into its computation
+ // of link margin.
+
+ RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
+ ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
+ ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
+
+ // skip Category and action code.
+ pFramePtr += 2;
+
+ // Dialog token.
+ NdisMoveMemory(&DialogToken, pFramePtr, 1);
+
+ LinkMargin = (RealRssi / MIN_RCV_PWR);
+ if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
+ EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ TPC Report action frame handler.
+
+ Parametrs:
+ Elme - MLME message containing the received frame
+
+ Return : None.
+ ==========================================================================
+ */
+static VOID PeerTpcRepAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UINT8 DialogToken;
+ TPC_REPORT_INFO TpcRepInfo;
+ PTPC_REQ_ENTRY pEntry = NULL;
+
+ NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
+ if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
+ {
+ if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
+ {
+ TpcReqDelete(pAd, pEntry->DialogToken);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
+ __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
+ }
+ }
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Spectrun action frames Handler such as channel switch annoucement,
+ measurement report, measurement request actions frames.
+
+ Parametrs:
+ Elme - MLME message containing the received frame
+
+ Return : None.
+ ==========================================================================
+ */
+VOID PeerSpectrumAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+
+ UCHAR Action = Elem->Msg[LENGTH_802_11+1];
+
+ if (pAd->CommonCfg.bIEEE80211H != TRUE)
+ return;
+
+ switch(Action)
+ {
+ case SPEC_MRQ:
+ // current rt2860 unable do such measure specified in Measurement Request.
+ // reject all measurement request.
+ PeerMeasureReqAction(pAd, Elem);
+ break;
+
+ case SPEC_MRP:
+ PeerMeasureReportAction(pAd, Elem);
+ break;
+
+ case SPEC_TPCRQ:
+ PeerTpcReqAction(pAd, Elem);
+ break;
+
+ case SPEC_TPCRP:
+ PeerTpcRepAction(pAd, Elem);
+ break;
+
+ case SPEC_CHANNEL_SWITCH:
+{
+#ifdef DOT11N_DRAFT3
+ SEC_CHA_OFFSET_IE Secondary;
+ CHA_SWITCH_ANNOUNCE_IE ChannelSwitch;
+
+ // 802.11h only has Channel Switch Announcement IE.
+ RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE));
+
+ // 802.11n D3.03 adds secondary channel offset element in the end.
+ if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE)))
+ {
+ RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE));
+ }
+ else
+ {
+ Secondary.SecondaryChannelOffset = 0;
+ }
+
+ if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3))
+ {
+ ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset);
+ }
+#endif // DOT11N_DRAFT3 //
+}
+ PeerChSwAnnAction(pAd, Elem);
+ break;
+ }
+
+ return;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ Parametrs:
+
+ Return : None.
+ ==========================================================================
+ */
+INT Set_MeasureReq_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT Aid = 1;
+ UINT ArgIdx;
+ PUCHAR thisChar;
+
+ MEASURE_REQ_MODE MeasureReqMode;
+ UINT8 MeasureReqToken = RandomByte(pAd);
+ UINT8 MeasureReqType = RM_BASIC;
+ UINT8 MeasureCh = 1;
+
+ ArgIdx = 1;
+ while ((thisChar = strsep((char **)&arg, "-")) != NULL)
+ {
+ switch(ArgIdx)
+ {
+ case 1: // Aid.
+ Aid = simple_strtol(thisChar, 0, 16);
+ break;
+
+ case 2: // Measurement Request Type.
+ MeasureReqType = simple_strtol(thisChar, 0, 16);
+ if (MeasureReqType > 3)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
+ return TRUE;
+ }
+ break;
+
+ case 3: // Measurement channel.
+ MeasureCh = simple_strtol(thisChar, 0, 16);
+ break;
+ }
+ ArgIdx++;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
+ if (!VALID_WCID(Aid))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
+ return TRUE;
+ }
+
+ MeasureReqMode.word = 0;
+ MeasureReqMode.field.Enable = 1;
+
+ MeasureReqInsert(pAd, MeasureReqToken);
+
+ EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr,
+ MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000);
+
+ return TRUE;
+}
+
+INT Set_TpcReq_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT Aid;
+
+ UINT8 TpcReqToken = RandomByte(pAd);
+
+ Aid = simple_strtol(arg, 0, 16);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
+ if (!VALID_WCID(Aid))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
+ return TRUE;
+ }
+
+ TpcReqInsert(pAd, TpcReqToken);
+
+ EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
+
+ return TRUE;
+}
+
diff --git a/drivers/staging/rt2860/config.mk b/drivers/staging/rt2860/config.mk
new file mode 100644
index 000000000000..f57d7bbffb24
--- /dev/null
+++ b/drivers/staging/rt2860/config.mk
@@ -0,0 +1,245 @@
+# Support ATE function
+HAS_ATE=n
+
+# Support 28xx QA ATE function
+HAS_28xx_QA=n
+
+# Support Wpa_Supplicant
+HAS_WPA_SUPPLICANT=n
+
+# Support Native WpaSupplicant for Network Maganger
+HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n
+
+#Support Net interface block while Tx-Sw queue full
+HAS_BLOCK_NET_IF=n
+
+#Support DFS function
+HAS_DFS_SUPPORT=n
+
+#Support Carrier-Sense function
+HAS_CS_SUPPORT=n
+
+#ifdef MULTI_CARD
+# Support for Multiple Cards
+HAS_MC_SUPPORT=n
+#endif // MULTI_CARD //
+
+#Support for IEEE802.11e DLS
+HAS_QOS_DLS_SUPPORT=n
+
+#Support for EXT_CHANNEL
+HAS_EXT_BUILD_CHANNEL_LIST=n
+
+#Support for Net-SNMP
+HAS_SNMP_SUPPORT=n
+
+#Support features of Single SKU.
+HAS_SINGLE_SKU_SUPPORT=n
+
+#Support features of 802.11n
+HAS_DOT11_N_SUPPORT=y
+
+
+#################################################
+
+CC := $(CROSS_COMPILE)gcc
+LD := $(CROSS_COMPILE)ld
+
+WFLAGS := -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs
+
+
+#################################################
+
+#ifdef CONFIG_STA_SUPPORT
+# config for STA mode
+
+ifeq ($(RT28xx_MODE),STA)
+WFLAGS += -DCONFIG_STA_SUPPORT -DDBG
+
+ifeq ($(HAS_WPA_SUPPLICANT),y)
+WFLAGS += -DWPA_SUPPLICANT_SUPPORT
+endif
+
+ifeq ($(HAS_NATIVE_WPA_SUPPLICANT_SUPPORT),y)
+WFLAGS += -DNATIVE_WPA_SUPPLICANT_SUPPORT
+endif
+
+ifeq ($(HAS_ATE),y)
+WFLAGS += -DRALINK_ATE
+ifeq ($(HAS_28xx_QA),y)
+WFLAGS += -DRALINK_28xx_QA
+endif
+endif
+
+ifeq ($(HAS_SNMP_SUPPORT),y)
+WFLAGS += -DSNMP_SUPPORT
+endif
+
+ifeq ($(HAS_QOS_DLS_SUPPORT),y)
+WFLAGS += -DQOS_DLS_SUPPORT
+endif
+
+ifeq ($(HAS_DOT11_N_SUPPORT),y)
+WFLAGS += -DDOT11_N_SUPPORT
+endif
+
+ifeq ($(HAS_CS_SUPPORT),y)
+WFLAGS += -DCARRIER_DETECTION_SUPPORT
+endif
+
+ifeq ($(HAS_SINGLE_SKU_SUPPORT),y)
+WFLAGS += -DSINGLE_SKU
+endif
+
+endif
+# endif of ifeq ($(RT28xx_MODE),STA)
+#endif // CONFIG_STA_SUPPORT //
+
+#################################################
+
+#################################################
+
+#
+# Common compiler flag
+#
+
+
+ifeq ($(HAS_EXT_BUILD_CHANNEL_LIST),y)
+WFLAGS += -DEXT_BUILD_CHANNEL_LIST
+endif
+
+ifeq ($(CHIPSET),2860)
+WFLAGS +=-DRT2860
+endif
+
+ifeq ($(CHIPSET),2870)
+WFLAGS +=-DRT2870
+endif
+
+ifeq ($(PLATFORM),5VT)
+#WFLAGS += -DCONFIG_5VT_ENHANCE
+endif
+
+ifeq ($(HAS_BLOCK_NET_IF),y)
+WFLAGS += -DBLOCK_NET_IF
+endif
+
+ifeq ($(HAS_DFS_SUPPORT),y)
+WFLAGS += -DDFS_SUPPORT
+endif
+
+#ifdef MULTI_CARD
+ifeq ($(HAS_MC_SUPPORT),y)
+WFLAGS += -DMULTIPLE_CARD_SUPPORT
+endif
+#endif // MULTI_CARD //
+
+ifeq ($(HAS_LLTD),y)
+WFLAGS += -DLLTD_SUPPORT
+endif
+
+ifeq ($(PLATFORM),IXP)
+WFLAGS += -DRT_BIG_ENDIAN
+endif
+
+ifeq ($(PLATFORM),IKANOS_V160)
+WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0
+endif
+
+ifeq ($(PLATFORM),IKANOS_V180)
+WFLAGS += -DRT_BIG_ENDIAN -DIKANOS_VX_1X0
+endif
+
+ifeq ($(PLATFORM),INF_TWINPASS)
+WFLAGS += -DRT_BIG_ENDIAN -DINF_TWINPASS
+endif
+
+ifeq ($(PLATFORM),INF_DANUBE)
+WFLAGS += -DINF_DANUBE -DRT_BIG_ENDIAN
+endif
+
+ifeq ($(PLATFORM),CAVM_OCTEON)
+WFLAGS += -DRT_BIG_ENDIAN
+endif
+
+ifeq ($(PLATFORM),BRCM_6358)
+WFLAGS += -DRT_BIG_ENDIAN
+endif
+
+ifeq ($(PLATFORM),INF_AMAZON_SE)
+#WFLAGS += -DRT_BIG_ENDIAN -DINF_AMAZON_SE -DBG_FT_SUPPORT
+WFLAGS += -DRT_BIG_ENDIAN -DINF_AMAZON_SE
+endif
+
+#kernel build options for 2.4
+# move to Makefile outside LINUX_SRC := /opt/star/kernel/linux-2.4.27-star
+
+ifeq ($(PLATFORM),STAR)
+CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -Uarm -fno-common -pipe -mapcs-32 -D__LINUX_ARM_ARCH__=4 -march=armv4 -mshort-load-bytes -msoft-float -Uarm -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS)
+
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),SIGMA)
+CFLAGS := -D__KERNEL__ -I$(RT28xx_DIR)/include -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -DEM86XX_CHIP=EM86XX_CHIPID_TANGO2 -DEM86XX_REVISION=6 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT2860_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mabi=32 -march=mips32r2 -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap -DMODULE $(WFLAGS)
+
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),SIGMA_8622)
+CFLAGS := -D__KERNEL__ -I$(CROSS_COMPILE_INCLUDE)/include -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fno-strict-aliasing -fno-common -fno-common -pipe -fno-builtin -D__linux__ -DNO_MM -mapcs-32 -march=armv4 -mtune=arm7tdmi -msoft-float -DMODULE -mshort-load-bytes -nostdinc -iwithprefix -DMODULE $(WFLAGS)
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),5VT)
+CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm926ej-s --param max-inline-insns-single=40000 -Uarm -Wdeclaration-after-statement -Wno-pointer-sign -DMODULE $(WFLAGS)
+
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),IKANOS_V160)
+CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -march=lx4189 -Wa, -DMODULE $(WFLAGS)
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),IKANOS_V180)
+CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(LINUX_SRC)/include/asm/gcc -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-tango2 -I$(LINUX_SRC)/include/asm-mips/mach-generic -I$(RT28xx_DIR)/include -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -ffreestanding -O2 -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -mips32r2 -Wa, -DMODULE $(WFLAGS)
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),INF_TWINPASS)
+CFLAGS := -D__KERNEL__ -DMODULE -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -G 0 -mno-abicalls -fno-pic -march=4kc -mips32 -Wa,--trap -pipe -mlong-calls $(WFLAGS)
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),INF_DANUBE)
+CFLAGS := -I$(RT28xx_DIR)/include $(WFLAGS) -Wundef -fno-strict-aliasing -fno-common -ffreestanding -Os -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic -pipe -msoft-float -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-generic
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),BRCM_6358)
+CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include -nostdinc -iwithprefix include -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -I $(LINUX_SRC)/include/asm/gcc -G 0 -mno-abicalls -fno-pic -pipe -finline-limit=100000 -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -I$(LINUX_SRC)/include/asm-mips/mach-bcm963xx -I$(LINUX_SRC)/include/asm-mips/mach-generic -Os -fomit-frame-pointer -Wdeclaration-after-statement -DMODULE -mlong-calls
+export CFLAGS
+endif
+
+ifeq ($(PLATFORM),PC)
+ ifneq (,$(findstring 2.4,$(LINUX_SRC)))
+ # Linux 2.4
+ CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common -pipe -mpreferred-stack-boundary=2 -march=i686 -DMODULE -DMODVERSIONS -include $(LINUX_SRC)/include/linux/modversions.h $(WFLAGS)
+ export CFLAGS
+ else
+ # Linux 2.6
+ EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include
+ endif
+endif
+
+ifeq ($(PLATFORM),IXP)
+ EXTRA_CFLAGS := -v $(WFLAGS) -I$(RT28xx_DIR)/include -mbig-endian
+endif
+
+ifeq ($(PLATFORM),CAVM_OCTEON)
+ EXTRA_CFLAGS := $(WFLAGS) -I$(RT28xx_DIR)/include \
+ -mabi=64 $(WFLAGS)
+export CFLAGS
+endif
+
diff --git a/drivers/staging/rt2860/dfs.h b/drivers/staging/rt2860/dfs.h
new file mode 100644
index 000000000000..752a6352d9dd
--- /dev/null
+++ b/drivers/staging/rt2860/dfs.h
@@ -0,0 +1,100 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ dfs.h
+
+ Abstract:
+ Support DFS function.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Fonchi 03-12-2007 created
+*/
+
+#define RADAR_PULSE 1
+#define RADAR_WIDTH 2
+
+#define WIDTH_RD_IDLE 0
+#define WIDTH_RD_CHECK 1
+
+
+VOID BbpRadarDetectionStart(
+ IN PRTMP_ADAPTER pAd);
+
+VOID BbpRadarDetectionStop(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RadarDetectionStart(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN CTS_Protect,
+ IN UINT8 CTSPeriod);
+
+VOID RadarDetectionStop(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RadarDetectPeriodic(
+ IN PRTMP_ADAPTER pAd);
+
+
+BOOLEAN RadarChannelCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Ch);
+
+ULONG JapRadarType(
+ IN PRTMP_ADAPTER pAd);
+
+ULONG RTMPBbpReadRadarDuration(
+ IN PRTMP_ADAPTER pAd);
+
+ULONG RTMPReadRadarDuration(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPCleanRadarDuration(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPPrepareRDCTSFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN ULONG Duration,
+ IN UCHAR RTSRate,
+ IN ULONG CTSBaseAddr,
+ IN UCHAR FrameGap);
+
+VOID RTMPPrepareRadarDetectParams(
+ IN PRTMP_ADAPTER pAd);
+
+
+INT Set_ChMovingTime_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_LongPulseRadarTh_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+
diff --git a/drivers/staging/rt2860/leap.h b/drivers/staging/rt2860/leap.h
new file mode 100644
index 000000000000..6818c1ff4d73
--- /dev/null
+++ b/drivers/staging/rt2860/leap.h
@@ -0,0 +1,215 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ leap.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+*/
+#ifndef __LEAP_H__
+#define __LEAP_H__
+
+// Messages for Associate state machine
+#define LEAP_MACHINE_BASE 30
+
+#define LEAP_MSG_REQUEST_IDENTITY 31
+#define LEAP_MSG_REQUEST_LEAP 32
+#define LEAP_MSG_SUCCESS 33
+#define LEAP_MSG_FAILED 34
+#define LEAP_MSG_RESPONSE_LEAP 35
+#define LEAP_MSG_EAPOLKEY 36
+#define LEAP_MSG_UNKNOWN 37
+#define LEAP_MSG 38
+//! assoc state-machine states
+#define LEAP_IDLE 0
+#define LEAP_WAIT_IDENTITY_REQUEST 1
+#define LEAP_WAIT_CHANLLENGE_REQUEST 2
+#define LEAP_WAIT_SUCCESS 3
+#define LEAP_WAIT_CHANLLENGE_RESPONSE 4
+#define LEAP_WAIT_EAPOLKEY 5
+
+#define LEAP_REASON_INVALID_AUTH 0x01
+#define LEAP_REASON_AUTH_TIMEOUT 0x02
+#define LEAP_REASON_CHALLENGE_FROM_AP_FAILED 0x03
+#define LEAP_REASON_CHALLENGE_TO_AP_FAILED 0x04
+
+#define CISCO_AuthModeLEAP 0x80
+#define CISCO_AuthModeLEAPNone 0x00
+#define LEAP_AUTH_TIMEOUT 30000
+#define LEAP_CHALLENGE_RESPONSE_LENGTH 24
+#define LEAP_CHALLENGE_REQUEST_LENGTH 8
+
+typedef struct _LEAP_EAPOL_HEADER_ {
+ UCHAR Version;
+ UCHAR Type;
+ UCHAR Length[2];
+} LEAP_EAPOL_HEADER, *PLEAP_EAPOL_HEADER;
+
+typedef struct _LEAP_EAPOL_PACKET_ {
+ UCHAR Code;
+ UCHAR Identifier;
+ UCHAR Length[2];
+ UCHAR Type;
+} LEAP_EAPOL_PACKET, *PLEAP_EAPOL_PACKET;
+
+typedef struct _LEAP_EAP_CONTENTS_ {
+ UCHAR Version;
+ UCHAR Reserved;
+ UCHAR Length;
+} LEAP_EAP_CONTENTS, *PLEAP_EAP_CONTENTS;
+
+/*** EAPOL key ***/
+typedef struct _EAPOL_KEY_HEADER_ {
+ UCHAR Type;
+ UCHAR Length[2];
+ UCHAR Counter[8];
+ UCHAR IV[16];
+ UCHAR Index;
+ UCHAR Signature[16];
+} EAPOL_KEY_HEADER, *PEAPOL_KEY_HEADER;
+
+BOOLEAN LeapMsgTypeSubst(
+ IN UCHAR EAPType,
+ OUT ULONG *MsgType);
+
+VOID LeapMachinePerformAction(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID LeapMacHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN UCHAR wep,
+ IN PUCHAR pAddr3);
+
+VOID LeapStartAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID LeapIdentityAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID LeapPeerChallengeAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID HashPwd(
+ IN PUCHAR pwd,
+ IN INT pwdlen,
+ OUT PUCHAR hash);
+
+VOID PeerChallengeResponse(
+ IN PUCHAR szChallenge,
+ IN PUCHAR smbPasswd,
+ OUT PUCHAR szResponse);
+
+VOID ParityKey(
+ OUT PUCHAR szOut,
+ IN PUCHAR szIn);
+
+VOID DesKey(
+ OUT ULONG k[16][2],
+ IN PUCHAR key,
+ IN INT decrypt);
+
+VOID Des(
+ IN ULONG ks[16][2],
+ OUT UCHAR block[8]);
+
+VOID DesEncrypt(
+ IN PUCHAR szClear,
+ IN PUCHAR szKey,
+ OUT PUCHAR szOut);
+
+VOID LeapNetworkChallengeAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID LeapNetworkChallengeResponse(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID HashpwdHash(
+ IN PUCHAR hash,
+ IN PUCHAR hashhash);
+
+VOID ProcessSessionKey(
+ OUT PUCHAR SessionKey,
+ IN PUCHAR hash2,
+ IN PUCHAR ChallengeToRadius,
+ IN PUCHAR ChallengeResponseFromRadius,
+ IN PUCHAR ChallengeFromRadius,
+ IN PUCHAR ChallengeResponseToRadius);
+
+VOID LeapEapolKeyAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID RogueApTableInit(
+ IN ROGUEAP_TABLE *Tab);
+
+ULONG RogueApTableSearch(
+ IN ROGUEAP_TABLE *Tab,
+ IN PUCHAR pAddr);
+
+VOID RogueApEntrySet(
+ IN PRTMP_ADAPTER pAd,
+ OUT ROGUEAP_ENTRY *pRogueAp,
+ IN PUCHAR pAddr,
+ IN UCHAR FaileCode);
+
+ULONG RogueApTableSetEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT ROGUEAP_TABLE *Tab,
+ IN PUCHAR pAddr,
+ IN UCHAR FaileCode);
+
+VOID RogueApTableDeleteEntry(
+ IN OUT ROGUEAP_TABLE *Tab,
+ IN PUCHAR pAddr);
+
+VOID LeapAuthTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID LeapSendRogueAPReport(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN CCKMAssocRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen);
+
+#endif // __LEAP_H__
diff --git a/drivers/staging/rt2860/link_list.h b/drivers/staging/rt2860/link_list.h
new file mode 100644
index 000000000000..f6521133fd5e
--- /dev/null
+++ b/drivers/staging/rt2860/link_list.h
@@ -0,0 +1,134 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#ifndef __LINK_LIST_H__
+#define __LINK_LIST_H__
+
+typedef struct _LIST_ENTRY
+{
+ struct _LIST_ENTRY *pNext;
+} LIST_ENTRY, *PLIST_ENTRY;
+
+typedef struct _LIST_HEADR
+{
+ PLIST_ENTRY pHead;
+ PLIST_ENTRY pTail;
+ UCHAR size;
+} LIST_HEADER, *PLIST_HEADER;
+
+static inline VOID initList(
+ IN PLIST_HEADER pList)
+{
+ pList->pHead = pList->pTail = NULL;
+ pList->size = 0;
+ return;
+}
+
+static inline VOID insertTailList(
+ IN PLIST_HEADER pList,
+ IN PLIST_ENTRY pEntry)
+{
+ pEntry->pNext = NULL;
+ if (pList->pTail)
+ pList->pTail->pNext = pEntry;
+ else
+ pList->pHead = pEntry;
+ pList->pTail = pEntry;
+ pList->size++;
+
+ return;
+}
+
+static inline PLIST_ENTRY removeHeadList(
+ IN PLIST_HEADER pList)
+{
+ PLIST_ENTRY pNext;
+ PLIST_ENTRY pEntry;
+
+ pEntry = pList->pHead;
+ if (pList->pHead != NULL)
+ {
+ pNext = pList->pHead->pNext;
+ pList->pHead = pNext;
+ if (pNext == NULL)
+ pList->pTail = NULL;
+ pList->size--;
+ }
+ return pEntry;
+}
+
+static inline int getListSize(
+ IN PLIST_HEADER pList)
+{
+ return pList->size;
+}
+
+static inline PLIST_ENTRY delEntryList(
+ IN PLIST_HEADER pList,
+ IN PLIST_ENTRY pEntry)
+{
+ PLIST_ENTRY pCurEntry;
+ PLIST_ENTRY pPrvEntry;
+
+ if(pList->pHead == NULL)
+ return NULL;
+
+ if(pEntry == pList->pHead)
+ {
+ pCurEntry = pList->pHead;
+ pList->pHead = pCurEntry->pNext;
+
+ if(pList->pHead == NULL)
+ pList->pTail = NULL;
+
+ pList->size--;
+ return pCurEntry;
+ }
+
+ pPrvEntry = pList->pHead;
+ pCurEntry = pPrvEntry->pNext;
+ while(pCurEntry != NULL)
+ {
+ if (pEntry == pCurEntry)
+ {
+ pPrvEntry->pNext = pCurEntry->pNext;
+
+ if(pEntry == pList->pTail)
+ pList->pTail = pPrvEntry;
+
+ pList->size--;
+ break;
+ }
+ pPrvEntry = pCurEntry;
+ pCurEntry = pPrvEntry->pNext;
+ }
+
+ return pCurEntry;
+}
+
+#endif // ___LINK_LIST_H__ //
+
diff --git a/drivers/staging/rt2860/md4.h b/drivers/staging/rt2860/md4.h
new file mode 100644
index 000000000000..f1e5b526350a
--- /dev/null
+++ b/drivers/staging/rt2860/md4.h
@@ -0,0 +1,42 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#ifndef __MD4_H__
+#define __MD4_H__
+
+/* MD4 context. */
+typedef struct _MD4_CTX_ {
+ ULONG state[4]; /* state (ABCD) */
+ ULONG count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ UCHAR buffer[64]; /* input buffer */
+} MD4_CTX;
+
+VOID MD4Init (MD4_CTX *);
+VOID MD4Update (MD4_CTX *, PUCHAR, UINT);
+VOID MD4Final (UCHAR [16], MD4_CTX *);
+
+#endif //__MD4_H__ \ No newline at end of file
diff --git a/drivers/staging/rt2860/md5.h b/drivers/staging/rt2860/md5.h
new file mode 100644
index 000000000000..d85db12170d5
--- /dev/null
+++ b/drivers/staging/rt2860/md5.h
@@ -0,0 +1,107 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ md5.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ jan 10-28-03 Initial
+ Rita 11-23-04 Modify MD5 and SHA-1
+*/
+
+#ifndef uint8
+#define uint8 unsigned char
+#endif
+
+#ifndef uint32
+#define uint32 unsigned long int
+#endif
+
+
+#ifndef __MD5_H__
+#define __MD5_H__
+
+#define MD5_MAC_LEN 16
+
+typedef struct _MD5_CTX {
+ UINT32 Buf[4]; // buffers of four states
+ UCHAR Input[64]; // input message
+ UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits
+} MD5_CTX;
+
+VOID MD5Init(MD5_CTX *pCtx);
+VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes);
+VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx);
+VOID MD5Transform(UINT32 Buf[4], UINT32 Mes[16]);
+
+void md5_mac(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac);
+void hmac_md5(u8 *key, size_t key_len, u8 *data, size_t data_len, u8 *mac);
+
+//
+// SHA context
+//
+typedef struct _SHA_CTX
+{
+ UINT32 Buf[5]; // buffers of five states
+ UCHAR Input[80]; // input message
+ UINT32 LenInBitCount[2]; // length counter for input message, 0 up to 64 bits
+
+} SHA_CTX;
+
+VOID SHAInit(SHA_CTX *pCtx);
+UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, UINT32 LenInBytes);
+VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20]);
+VOID SHATransform(UINT32 Buf[5], UINT32 Mes[20]);
+
+#define SHA_DIGEST_LEN 20
+#endif // __MD5_H__
+
+/******************************************************************************/
+#ifndef _AES_H
+#define _AES_H
+
+typedef struct
+{
+ uint32 erk[64]; /* encryption round keys */
+ uint32 drk[64]; /* decryption round keys */
+ int nr; /* number of rounds */
+}
+aes_context;
+
+int rtmp_aes_set_key( aes_context *ctx, uint8 *key, int nbits );
+void rtmp_aes_encrypt( aes_context *ctx, uint8 input[16], uint8 output[16] );
+void rtmp_aes_decrypt( aes_context *ctx, uint8 input[16], uint8 output[16] );
+
+void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output);
+int PasswordHash(char *password, unsigned char *ssid, int ssidlength, unsigned char *output);
+
+#endif /* aes.h */
+
diff --git a/drivers/staging/rt2860/mlme.h b/drivers/staging/rt2860/mlme.h
new file mode 100644
index 000000000000..5cb61652b668
--- /dev/null
+++ b/drivers/staging/rt2860/mlme.h
@@ -0,0 +1,1447 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ mlme.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Chang 2003-08-28 Created
+ John Chang 2004-09-06 modified for RT2600
+
+*/
+#ifndef __MLME_H__
+#define __MLME_H__
+
+// maximum supported capability information -
+// ESS, IBSS, Privacy, Short Preamble, Spectrum mgmt, Short Slot
+#define SUPPORTED_CAPABILITY_INFO 0x0533
+
+#define END_OF_ARGS -1
+#define LFSR_MASK 0x80000057
+#define MLME_TASK_EXEC_INTV 100/*200*/ //
+#define LEAD_TIME 5
+#define MLME_TASK_EXEC_MULTIPLE 10 /*5*/ // MLME_TASK_EXEC_MULTIPLE * MLME_TASK_EXEC_INTV = 1 sec
+#define REORDER_EXEC_INTV 100 // 0.1 sec
+
+// The definition of Radar detection duration region
+#define CE 0
+#define FCC 1
+#define JAP 2
+#define JAP_W53 3
+#define JAP_W56 4
+#define MAX_RD_REGION 5
+
+#ifdef NDIS51_MINIPORT
+#define BEACON_LOST_TIME 4000 // 2048 msec = 2 sec
+#else
+#define BEACON_LOST_TIME 4 * OS_HZ // 2048 msec = 2 sec
+#endif
+
+#define DLS_TIMEOUT 1200 // unit: msec
+#define AUTH_TIMEOUT 300 // unit: msec
+#define ASSOC_TIMEOUT 300 // unit: msec
+#define JOIN_TIMEOUT 2 * OS_HZ // unit: msec
+#define SHORT_CHANNEL_TIME 90 // unit: msec
+#define MIN_CHANNEL_TIME 110 // unit: msec, for dual band scan
+#define MAX_CHANNEL_TIME 140 // unit: msec, for single band scan
+#define FAST_ACTIVE_SCAN_TIME 30 // Active scan waiting for probe response time
+#define CW_MIN_IN_BITS 4 // actual CwMin = 2^CW_MIN_IN_BITS - 1
+
+
+#ifdef CONFIG_STA_SUPPORT
+#ifndef CONFIG_AP_SUPPORT
+#define CW_MAX_IN_BITS 10 // actual CwMax = 2^CW_MAX_IN_BITS - 1
+#endif
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+extern UINT32 CW_MAX_IN_BITS;
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+// Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720).
+// SHould not refer to this constant anymore
+//#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm
+#define RSSI_FOR_MID_TX_POWER -55 // -55 db is considered mid-distance
+#define RSSI_FOR_LOW_TX_POWER -45 // -45 db is considered very short distance and
+ // eligible to use a lower TX power
+#define RSSI_FOR_LOWEST_TX_POWER -30
+//#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP
+#define LOW_TX_POWER_DELTA 6 // -3 db from full TX power upon very short distance. 1 grade is 0.5 db
+#define LOWEST_TX_POWER_DELTA 16 // -8 db from full TX power upon shortest distance. 1 grade is 0.5 db
+
+#define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD 0
+#define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD 1
+#define RSSI_THRESHOLD_FOR_ROAMING 25
+#define RSSI_DELTA 5
+
+// Channel Quality Indication
+#define CQI_IS_GOOD(cqi) ((cqi) >= 50)
+//#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50))
+#define CQI_IS_POOR(cqi) (cqi < 50) //(((cqi) >= 5) && ((cqi) < 20))
+#define CQI_IS_BAD(cqi) (cqi < 5)
+#define CQI_IS_DEAD(cqi) (cqi == 0)
+
+// weighting factor to calculate Channel quality, total should be 100%
+#define RSSI_WEIGHTING 50
+#define TX_WEIGHTING 30
+#define RX_WEIGHTING 20
+
+#define BSS_NOT_FOUND 0xFFFFFFFF
+
+
+#ifdef CONFIG_STA_SUPPORT
+#define MAX_LEN_OF_MLME_QUEUE 40 //10
+#endif // CONFIG_STA_SUPPORT //
+
+#define SCAN_PASSIVE 18 // scan with no probe request, only wait beacon and probe response
+#define SCAN_ACTIVE 19 // scan with probe request, and wait beacon and probe response
+#define SCAN_CISCO_PASSIVE 20 // Single channel passive scan
+#define SCAN_CISCO_ACTIVE 21 // Single channel active scan
+#define SCAN_CISCO_NOISE 22 // Single channel passive scan for noise histogram collection
+#define SCAN_CISCO_CHANNEL_LOAD 23 // Single channel passive scan for channel load collection
+#define FAST_SCAN_ACTIVE 24 // scan with probe request, and wait beacon and probe response
+
+#ifdef DOT11N_DRAFT3
+#define SCAN_2040_BSS_COEXIST 26
+#endif // DOT11N_DRAFT3 //
+
+#define MAC_ADDR_IS_GROUP(Addr) (((Addr[0]) & 0x01))
+#define MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5])
+#define MAC_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) % HASH_TABLE_SIZE)
+#define TID_MAC_HASH(Addr,TID) (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5])
+#define TID_MAC_HASH_INDEX(Addr,TID) (TID_MAC_HASH(Addr,TID) % HASH_TABLE_SIZE)
+
+// LED Control
+// assoiation ON. one LED ON. another blinking when TX, OFF when idle
+// no association, both LED off
+#define ASIC_LED_ACT_ON(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00031e46)
+#define ASIC_LED_ACT_OFF(pAd) RTMP_IO_WRITE32(pAd, MAC_CSR14, 0x00001e46)
+
+// bit definition of the 2-byte pBEACON->Capability field
+#define CAP_IS_ESS_ON(x) (((x) & 0x0001) != 0)
+#define CAP_IS_IBSS_ON(x) (((x) & 0x0002) != 0)
+#define CAP_IS_CF_POLLABLE_ON(x) (((x) & 0x0004) != 0)
+#define CAP_IS_CF_POLL_REQ_ON(x) (((x) & 0x0008) != 0)
+#define CAP_IS_PRIVACY_ON(x) (((x) & 0x0010) != 0)
+#define CAP_IS_SHORT_PREAMBLE_ON(x) (((x) & 0x0020) != 0)
+#define CAP_IS_PBCC_ON(x) (((x) & 0x0040) != 0)
+#define CAP_IS_AGILITY_ON(x) (((x) & 0x0080) != 0)
+#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) // 802.11e d9
+#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) // 802.11e d9
+#define CAP_IS_SHORT_SLOT(x) (((x) & 0x0400) != 0)
+#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) // 802.11e d9
+#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) // 802.11e d9
+#define CAP_IS_DSSS_OFDM(x) (((x) & 0x2000) != 0)
+#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) // 802.11e d9
+
+#define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum) (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000))
+
+#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) // 802.11g
+#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) // 802.11g
+#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) // 802.11g
+
+#define DRS_TX_QUALITY_WORST_BOUND 8// 3 // just test by gary
+#define DRS_PENALTY 8
+
+#define BA_NOTUSE 2
+//BA Policy subfiled value in ADDBA frame
+#define IMMED_BA 1
+#define DELAY_BA 0
+
+// BA Initiator subfield in DELBA frame
+#define ORIGINATOR 1
+#define RECIPIENT 0
+
+// ADDBA Status Code
+#define ADDBA_RESULTCODE_SUCCESS 0
+#define ADDBA_RESULTCODE_REFUSED 37
+#define ADDBA_RESULTCODE_INVALID_PARAMETERS 38
+
+// DELBA Reason Code
+#define DELBA_REASONCODE_QSTA_LEAVING 36
+#define DELBA_REASONCODE_END_BA 37
+#define DELBA_REASONCODE_UNKNOWN_BA 38
+#define DELBA_REASONCODE_TIMEOUT 39
+
+// reset all OneSecTx counters
+#define RESET_ONE_SEC_TX_CNT(__pEntry) \
+if (((__pEntry)) != NULL) \
+{ \
+ (__pEntry)->OneSecTxRetryOkCount = 0; \
+ (__pEntry)->OneSecTxFailCount = 0; \
+ (__pEntry)->OneSecTxNoRetryOkCount = 0; \
+}
+
+//
+// 802.11 frame formats
+//
+// HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT LSIGTxopProSup:1;
+ USHORT Forty_Mhz_Intolerant:1;
+ USHORT PSMP:1;
+ USHORT CCKmodein40:1;
+ USHORT AMsduSize:1;
+ USHORT DelayedBA:1; //rt2860c not support
+ USHORT RxSTBC:2;
+ USHORT TxSTBC:1;
+ USHORT ShortGIfor40:1; //for40MHz
+ USHORT ShortGIfor20:1;
+ USHORT GF:1; //green field
+ USHORT MimoPs:2;//momi power safe
+ USHORT ChannelWidth:1;
+ USHORT AdvCoding:1;
+#else
+ USHORT AdvCoding:1;
+ USHORT ChannelWidth:1;
+ USHORT MimoPs:2;//momi power safe
+ USHORT GF:1; //green field
+ USHORT ShortGIfor20:1;
+ USHORT ShortGIfor40:1; //for40MHz
+ USHORT TxSTBC:1;
+ USHORT RxSTBC:2;
+ USHORT DelayedBA:1; //rt2860c not support
+ USHORT AMsduSize:1; // only support as zero
+ USHORT CCKmodein40:1;
+ USHORT PSMP:1;
+ USHORT Forty_Mhz_Intolerant:1;
+ USHORT LSIGTxopProSup:1;
+#endif /* !RT_BIG_ENDIAN */
+} HT_CAP_INFO, *PHT_CAP_INFO;
+
+// HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ UCHAR rsv:3;//momi power safe
+ UCHAR MpduDensity:3;
+ UCHAR MaxRAmpduFactor:2;
+#else
+ UCHAR MaxRAmpduFactor:2;
+ UCHAR MpduDensity:3;
+ UCHAR rsv:3;//momi power safe
+#endif /* !RT_BIG_ENDIAN */
+} HT_CAP_PARM, *PHT_CAP_PARM;
+
+// HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+ UCHAR MCSSet[10];
+ UCHAR SupRate[2]; // unit : 1Mbps
+#ifdef RT_BIG_ENDIAN
+ UCHAR rsv:3;
+ UCHAR MpduDensity:1;
+ UCHAR TxStream:2;
+ UCHAR TxRxNotEqual:1;
+ UCHAR TxMCSSetDefined:1;
+#else
+ UCHAR TxMCSSetDefined:1;
+ UCHAR TxRxNotEqual:1;
+ UCHAR TxStream:2;
+ UCHAR MpduDensity:1;
+ UCHAR rsv:3;
+#endif // RT_BIG_ENDIAN //
+ UCHAR rsv3[3];
+} HT_MCS_SET, *PHT_MCS_SET;
+
+// HT Capability INFO field in HT Cap IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT rsv2:4;
+ USHORT RDGSupport:1; //reverse Direction Grant support
+ USHORT PlusHTC:1; //+HTC control field support
+ USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv.
+ USHORT rsv:5;//momi power safe
+ USHORT TranTime:2;
+ USHORT Pco:1;
+#else
+ USHORT Pco:1;
+ USHORT TranTime:2;
+ USHORT rsv:5;//momi power safe
+ USHORT MCSFeedback:2; //0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv.
+ USHORT PlusHTC:1; //+HTC control field support
+ USHORT RDGSupport:1; //reverse Direction Grant support
+ USHORT rsv2:4;
+#endif /* RT_BIG_ENDIAN */
+} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO;
+
+// HT Beamforming field in HT Cap IE .
+typedef struct PACKED _HT_BF_CAP{
+#ifdef RT_BIG_ENDIAN
+ ULONG rsv:3;
+ ULONG ChanEstimation:2;
+ ULONG CSIRowBFSup:2;
+ ULONG ComSteerBFAntSup:2;
+ ULONG NoComSteerBFAntSup:2;
+ ULONG CSIBFAntSup:2;
+ ULONG MinGrouping:2;
+ ULONG ExpComBF:2;
+ ULONG ExpNoComBF:2;
+ ULONG ExpCSIFbk:2;
+ ULONG ExpComSteerCapable:1;
+ ULONG ExpNoComSteerCapable:1;
+ ULONG ExpCSICapable:1;
+ ULONG Calibration:2;
+ ULONG ImpTxBFCapable:1;
+ ULONG TxNDPCapable:1;
+ ULONG RxNDPCapable:1;
+ ULONG TxSoundCapable:1;
+ ULONG RxSoundCapable:1;
+ ULONG TxBFRecCapable:1;
+#else
+ ULONG TxBFRecCapable:1;
+ ULONG RxSoundCapable:1;
+ ULONG TxSoundCapable:1;
+ ULONG RxNDPCapable:1;
+ ULONG TxNDPCapable:1;
+ ULONG ImpTxBFCapable:1;
+ ULONG Calibration:2;
+ ULONG ExpCSICapable:1;
+ ULONG ExpNoComSteerCapable:1;
+ ULONG ExpComSteerCapable:1;
+ ULONG ExpCSIFbk:2;
+ ULONG ExpNoComBF:2;
+ ULONG ExpComBF:2;
+ ULONG MinGrouping:2;
+ ULONG CSIBFAntSup:2;
+ ULONG NoComSteerBFAntSup:2;
+ ULONG ComSteerBFAntSup:2;
+ ULONG CSIRowBFSup:2;
+ ULONG ChanEstimation:2;
+ ULONG rsv:3;
+#endif // RT_BIG_ENDIAN //
+} HT_BF_CAP, *PHT_BF_CAP;
+
+// HT antenna selection field in HT Cap IE .
+typedef struct PACKED _HT_AS_CAP{
+#ifdef RT_BIG_ENDIAN
+ UCHAR rsv:1;
+ UCHAR TxSoundPPDU:1;
+ UCHAR RxASel:1;
+ UCHAR AntIndFbk:1;
+ UCHAR ExpCSIFbk:1;
+ UCHAR AntIndFbkTxASEL:1;
+ UCHAR ExpCSIFbkTxASEL:1;
+ UCHAR AntSelect:1;
+#else
+ UCHAR AntSelect:1;
+ UCHAR ExpCSIFbkTxASEL:1;
+ UCHAR AntIndFbkTxASEL:1;
+ UCHAR ExpCSIFbk:1;
+ UCHAR AntIndFbk:1;
+ UCHAR RxASel:1;
+ UCHAR TxSoundPPDU:1;
+ UCHAR rsv:1;
+#endif // RT_BIG_ENDIAN //
+} HT_AS_CAP, *PHT_AS_CAP;
+
+// Draft 1.0 set IE length 26, but is extensible..
+#define SIZE_HT_CAP_IE 26
+// The structure for HT Capability IE.
+typedef struct PACKED _HT_CAPABILITY_IE{
+ HT_CAP_INFO HtCapInfo;
+ HT_CAP_PARM HtCapParm;
+// HT_MCS_SET HtMCSSet;
+ UCHAR MCSSet[16];
+ EXT_HT_CAP_INFO ExtHtCapInfo;
+ HT_BF_CAP TxBFCap; // beamforming cap. rt2860c not support beamforming.
+ HT_AS_CAP ASCap; //antenna selection.
+} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE;
+
+
+// 802.11n draft3 related structure definitions.
+// 7.3.2.60
+#define dot11OBSSScanPassiveDwell 20 // in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan.
+#define dot11OBSSScanActiveDwell 10 // in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan.
+#define dot11BSSWidthTriggerScanInterval 300 // in sec. max interval between scan operations to be performed to detect BSS channel width trigger events.
+#define dot11OBSSScanPassiveTotalPerChannel 200 // in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan.
+#define dot11OBSSScanActiveTotalPerChannel 20 //in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan
+#define dot11BSSWidthChannelTransactionDelayFactor 5 // min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maxima
+ // interval between overlapping BSS scan operations.
+#define dot11BSSScanActivityThreshold 25 // in %%, max total time that a STA may be active on the medium during a period of
+ // (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without
+ // being obligated to perform OBSS Scan operations. default is 25(== 0.25%)
+
+typedef struct PACKED _OVERLAP_BSS_SCAN_IE{
+ USHORT ScanPassiveDwell;
+ USHORT ScanActiveDwell;
+ USHORT TriggerScanInt; // Trigger scan interval
+ USHORT PassiveTalPerChannel; // passive total per channel
+ USHORT ActiveTalPerChannel; // active total per channel
+ USHORT DelayFactor; // BSS width channel transition delay factor
+ USHORT ScanActThre; // Scan Activity threshold
+}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE;
+
+
+// 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST
+typedef union PACKED _BSS_2040_COEXIST_IE{
+ struct PACKED {
+ #ifdef RT_BIG_ENDIAN
+ UCHAR rsv:5;
+ UCHAR BSS20WidthReq:1;
+ UCHAR Intolerant40:1;
+ UCHAR InfoReq:1;
+ #else
+ UCHAR InfoReq:1;
+ UCHAR Intolerant40:1; // Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS.
+ UCHAR BSS20WidthReq:1; // Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS.
+ UCHAR rsv:5;
+#endif // RT_BIG_ENDIAN //
+ } field;
+ UCHAR word;
+} BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE;
+
+
+typedef struct _TRIGGER_EVENTA{
+ BOOLEAN bValid;
+ UCHAR BSSID[6];
+ UCHAR RegClass; // Regulatory Class
+ USHORT Channel;
+ ULONG CDCounter; // Maintain a seperate count down counter for each Event A.
+} TRIGGER_EVENTA, *PTRIGGER_EVENTA;
+
+// 20/40 trigger event table
+// If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP.
+#define MAX_TRIGGER_EVENT 64
+typedef struct _TRIGGER_EVENT_TAB{
+ UCHAR EventANo;
+ TRIGGER_EVENTA EventA[MAX_TRIGGER_EVENT];
+ ULONG EventBCountDown; // Count down counter for Event B.
+} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB;
+
+// 7.3.27 20/40 Bss Coexistence Mgmt capability used in extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY).
+// This is the first octet and was defined in 802.11n D3.03 and 802.11yD9.0
+typedef struct PACKED _EXT_CAP_INFO_ELEMENT{
+#ifdef RT_BIG_ENDIAN
+ UCHAR rsv2:5;
+ UCHAR ExtendChannelSwitch:1;
+ UCHAR rsv:1;
+ UCHAR BssCoexistMgmtSupport:1;
+#else
+ UCHAR BssCoexistMgmtSupport:1;
+ UCHAR rsv:1;
+ UCHAR ExtendChannelSwitch:1;
+ UCHAR rsv2:5;
+#endif // RT_BIG_ENDIAN //
+}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT;
+
+
+// 802.11n 7.3.2.61
+typedef struct PACKED _BSS_2040_COEXIST_ELEMENT{
+ UCHAR ElementID; // ID = IE_2040_BSS_COEXIST = 72
+ UCHAR Len;
+ BSS_2040_COEXIST_IE BssCoexistIe;
+}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT;
+
+
+//802.11n 7.3.2.59
+typedef struct PACKED _BSS_2040_INTOLERANT_CH_REPORT{
+ UCHAR ElementID; // ID = IE_2040_BSS_INTOLERANT_REPORT = 73
+ UCHAR Len;
+ UCHAR RegulatoryClass;
+ UCHAR ChList[0];
+}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT;
+
+
+// The structure for channel switch annoucement IE. This is in 802.11n D3.03
+typedef struct PACKED _CHA_SWITCH_ANNOUNCE_IE{
+ UCHAR SwitchMode; //channel switch mode
+ UCHAR NewChannel; //
+ UCHAR SwitchCount; //
+} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE;
+
+
+// The structure for channel switch annoucement IE. This is in 802.11n D3.03
+typedef struct PACKED _SEC_CHA_OFFSET_IE{
+ UCHAR SecondaryChannelOffset; // 1: Secondary above, 3: Secondary below, 0: no Secondary
+} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE;
+
+
+// This structure is extracted from struct RT_HT_CAPABILITY
+typedef struct {
+ BOOLEAN bHtEnable; // If we should use ht rate.
+ BOOLEAN bPreNHt; // If we should use ht rate.
+ //Substract from HT Capability IE
+ UCHAR MCSSet[16]; //only supoort MCS=0-15,32 ,
+} RT_HT_PHY_INFO, *PRT_HT_PHY_INFO;
+
+//This structure substracts ralink supports from all 802.11n-related features.
+//Features not listed here but contained in 802.11n spec are not supported in rt2860.
+typedef struct {
+#ifdef RT_BIG_ENDIAN
+ USHORT rsv:5;
+ USHORT AmsduSize:1; // Max receiving A-MSDU size
+ USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n
+ USHORT RxSTBC:2; // 2 bits
+ USHORT TxSTBC:1;
+ USHORT ShortGIfor40:1; //for40MHz
+ USHORT ShortGIfor20:1;
+ USHORT GF:1; //green field
+ USHORT MimoPs:2;//mimo power safe MMPS_
+ USHORT ChannelWidth:1;
+#else
+ USHORT ChannelWidth:1;
+ USHORT MimoPs:2;//mimo power safe MMPS_
+ USHORT GF:1; //green field
+ USHORT ShortGIfor20:1;
+ USHORT ShortGIfor40:1; //for40MHz
+ USHORT TxSTBC:1;
+ USHORT RxSTBC:2; // 2 bits
+ USHORT AmsduEnable:1; // Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n
+ USHORT AmsduSize:1; // Max receiving A-MSDU size
+ USHORT rsv:5;
+#endif
+
+ //Substract from Addiont HT INFO IE
+#ifdef RT_BIG_ENDIAN
+ UCHAR RecomWidth:1;
+ UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n
+ UCHAR MpduDensity:3;
+ UCHAR MaxRAmpduFactor:2;
+#else
+ UCHAR MaxRAmpduFactor:2;
+ UCHAR MpduDensity:3;
+ UCHAR ExtChanOffset:2; // Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n
+ UCHAR RecomWidth:1;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+ USHORT rsv2:11;
+ USHORT OBSS_NonHTExist:1;
+ USHORT rsv3:1;
+ USHORT NonGfPresent:1;
+ USHORT OperaionMode:2;
+#else
+ USHORT OperaionMode:2;
+ USHORT NonGfPresent:1;
+ USHORT rsv3:1;
+ USHORT OBSS_NonHTExist:1;
+ USHORT rsv2:11;
+#endif
+
+ // New Extension Channel Offset IE
+ UCHAR NewExtChannelOffset;
+ // Extension Capability IE = 127
+ UCHAR BSSCoexist2040;
+} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY;
+
+// field in Addtional HT Information IE .
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ UCHAR SerInterGranu:3;
+ UCHAR S_PSMPSup:1;
+ UCHAR RifsMode:1;
+ UCHAR RecomWidth:1;
+ UCHAR ExtChanOffset:2;
+#else
+ UCHAR ExtChanOffset:2;
+ UCHAR RecomWidth:1;
+ UCHAR RifsMode:1;
+ UCHAR S_PSMPSup:1; //Indicate support for scheduled PSMP
+ UCHAR SerInterGranu:3; //service interval granularity
+#endif
+} ADD_HTINFO, *PADD_HTINFO;
+
+typedef struct PACKED{
+#ifdef RT_BIG_ENDIAN
+ USHORT rsv2:11;
+ USHORT OBSS_NonHTExist:1;
+ USHORT rsv:1;
+ USHORT NonGfPresent:1;
+ USHORT OperaionMode:2;
+#else
+ USHORT OperaionMode:2;
+ USHORT NonGfPresent:1;
+ USHORT rsv:1;
+ USHORT OBSS_NonHTExist:1;
+ USHORT rsv2:11;
+#endif
+} ADD_HTINFO2, *PADD_HTINFO2;
+
+
+// TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved.
+typedef struct PACKED{
+#ifdef RT_BIG_ENDIAN
+ USHORT rsv:4;
+ USHORT PcoPhase:1;
+ USHORT PcoActive:1;
+ USHORT LsigTxopProt:1;
+ USHORT STBCBeacon:1;
+ USHORT DualCTSProtect:1;
+ USHORT DualBeacon:1;
+ USHORT StbcMcs:6;
+#else
+ USHORT StbcMcs:6;
+ USHORT DualBeacon:1;
+ USHORT DualCTSProtect:1;
+ USHORT STBCBeacon:1;
+ USHORT LsigTxopProt:1; // L-SIG TXOP protection full support
+ USHORT PcoActive:1;
+ USHORT PcoPhase:1;
+ USHORT rsv:4;
+#endif // RT_BIG_ENDIAN //
+} ADD_HTINFO3, *PADD_HTINFO3;
+
+#define SIZE_ADD_HT_INFO_IE 22
+typedef struct PACKED{
+ UCHAR ControlChan;
+ ADD_HTINFO AddHtInfo;
+ ADD_HTINFO2 AddHtInfo2;
+ ADD_HTINFO3 AddHtInfo3;
+ UCHAR MCSSet[16]; // Basic MCS set
+} ADD_HT_INFO_IE, *PADD_HT_INFO_IE;
+
+typedef struct PACKED{
+ UCHAR NewExtChanOffset;
+} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE;
+
+
+// 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1.
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ UINT32 RDG:1; //RDG / More PPDU
+ UINT32 ACConstraint:1; //feedback request
+ UINT32 rsv:5; //calibration sequence
+ UINT32 ZLFAnnouce:1; // ZLF announcement
+ UINT32 CSISTEERING:2; //CSI/ STEERING
+ UINT32 FBKReq:2; //feedback request
+ UINT32 CalSeq:2; //calibration sequence
+ UINT32 CalPos:2; // calibration position
+ UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available
+ UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB.
+ UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110.
+ UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback
+ UINT32 TRQ:1; //sounding request
+ UINT32 MA:1; //management action payload exist in (QoS Null+HTC)
+#else
+ UINT32 MA:1; //management action payload exist in (QoS Null+HTC)
+ UINT32 TRQ:1; //sounding request
+ UINT32 MRQ:1; //MCS feedback. Request for a MCS feedback
+ UINT32 MRSorASI:3; // MRQ Sequence identifier. unchanged during entire procedure. 0x000-0x110.
+ UINT32 MFS:3; //SET to the received value of MRS. 0x111 for unsolicited MFB.
+ UINT32 MFBorASC:7; //Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available
+ UINT32 CalPos:2; // calibration position
+ UINT32 CalSeq:2; //calibration sequence
+ UINT32 FBKReq:2; //feedback request
+ UINT32 CSISTEERING:2; //CSI/ STEERING
+ UINT32 ZLFAnnouce:1; // ZLF announcement
+ UINT32 rsv:5; //calibration sequence
+ UINT32 ACConstraint:1; //feedback request
+ UINT32 RDG:1; //RDG / More PPDU
+#endif /* !RT_BIG_ENDIAN */
+} HT_CONTROL, *PHT_CONTROL;
+
+// 2-byte QOS CONTROL field
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT Txop_QueueSize:8;
+ USHORT AMsduPresent:1;
+ USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA
+ USHORT EOSP:1;
+ USHORT TID:4;
+#else
+ USHORT TID:4;
+ USHORT EOSP:1;
+ USHORT AckPolicy:2; //0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA
+ USHORT AMsduPresent:1;
+ USHORT Txop_QueueSize:8;
+#endif /* !RT_BIG_ENDIAN */
+} QOS_CONTROL, *PQOS_CONTROL;
+
+// 2-byte Frame control field
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT Order:1; // Strict order expected
+ USHORT Wep:1; // Wep data
+ USHORT MoreData:1; // More data bit
+ USHORT PwrMgmt:1; // Power management bit
+ USHORT Retry:1; // Retry status bit
+ USHORT MoreFrag:1; // More fragment bit
+ USHORT FrDs:1; // From DS indication
+ USHORT ToDs:1; // To DS indication
+ USHORT SubType:4; // MSDU subtype
+ USHORT Type:2; // MSDU type
+ USHORT Ver:2; // Protocol version
+#else
+ USHORT Ver:2; // Protocol version
+ USHORT Type:2; // MSDU type
+ USHORT SubType:4; // MSDU subtype
+ USHORT ToDs:1; // To DS indication
+ USHORT FrDs:1; // From DS indication
+ USHORT MoreFrag:1; // More fragment bit
+ USHORT Retry:1; // Retry status bit
+ USHORT PwrMgmt:1; // Power management bit
+ USHORT MoreData:1; // More data bit
+ USHORT Wep:1; // Wep data
+ USHORT Order:1; // Strict order expected
+#endif /* !RT_BIG_ENDIAN */
+} FRAME_CONTROL, *PFRAME_CONTROL;
+
+typedef struct PACKED _HEADER_802_11 {
+ FRAME_CONTROL FC;
+ USHORT Duration;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+ UCHAR Addr3[MAC_ADDR_LEN];
+#ifdef RT_BIG_ENDIAN
+ USHORT Sequence:12;
+ USHORT Frag:4;
+#else
+ USHORT Frag:4;
+ USHORT Sequence:12;
+#endif /* !RT_BIG_ENDIAN */
+ UCHAR Octet[0];
+} HEADER_802_11, *PHEADER_802_11;
+
+typedef struct PACKED _FRAME_802_11 {
+ HEADER_802_11 Hdr;
+ UCHAR Octet[1];
+} FRAME_802_11, *PFRAME_802_11;
+
+// QoSNull embedding of management action. When HT Control MA field set to 1.
+typedef struct PACKED _MA_BODY {
+ UCHAR Category;
+ UCHAR Action;
+ UCHAR Octet[1];
+} MA_BODY, *PMA_BODY;
+
+typedef struct PACKED _HEADER_802_3 {
+ UCHAR DAAddr1[MAC_ADDR_LEN];
+ UCHAR SAAddr2[MAC_ADDR_LEN];
+ UCHAR Octet[2];
+} HEADER_802_3, *PHEADER_802_3;
+////Block ACK related format
+// 2-byte BA Parameter field in DELBA frames to terminate an already set up bA
+typedef struct PACKED{
+#ifdef RT_BIG_ENDIAN
+ USHORT TID:4; // value of TC os TS
+ USHORT Initiator:1; // 1: originator 0:recipient
+ USHORT Rsv:11; // always set to 0
+#else
+ USHORT Rsv:11; // always set to 0
+ USHORT Initiator:1; // 1: originator 0:recipient
+ USHORT TID:4; // value of TC os TS
+#endif /* !RT_BIG_ENDIAN */
+} DELBA_PARM, *PDELBA_PARM;
+
+// 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT BufSize:10; // number of buffe of size 2304 octetsr
+ USHORT TID:4; // value of TC os TS
+ USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA
+ USHORT AMSDUSupported:1; // 0: not permitted 1: permitted
+#else
+ USHORT AMSDUSupported:1; // 0: not permitted 1: permitted
+ USHORT BAPolicy:1; // 1: immediately BA 0:delayed BA
+ USHORT TID:4; // value of TC os TS
+ USHORT BufSize:10; // number of buffe of size 2304 octetsr
+#endif /* !RT_BIG_ENDIAN */
+} BA_PARM, *PBA_PARM;
+
+// 2-byte BA Starting Seq CONTROL field
+typedef union PACKED {
+ struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent
+ USHORT FragNum:4; // always set to 0
+#else
+ USHORT FragNum:4; // always set to 0
+ USHORT StartSeq:12; // sequence number of the 1st MSDU for which this BAR is sent
+#endif /* RT_BIG_ENDIAN */
+ } field;
+ USHORT word;
+} BASEQ_CONTROL, *PBASEQ_CONTROL;
+
+//BAControl and BARControl are the same
+// 2-byte BA CONTROL field in BA frame
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT TID:4;
+ USHORT Rsv:9;
+ USHORT Compressed:1;
+ USHORT MTID:1; //EWC V1.24
+ USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK
+#else
+ USHORT ACKPolicy:1; // only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK
+ USHORT MTID:1; //EWC V1.24
+ USHORT Compressed:1;
+ USHORT Rsv:9;
+ USHORT TID:4;
+#endif /* !RT_BIG_ENDIAN */
+} BA_CONTROL, *PBA_CONTROL;
+
+// 2-byte BAR CONTROL field in BAR frame
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT TID:4;
+ USHORT Rsv1:9;
+ USHORT Compressed:1;
+ USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ
+ USHORT ACKPolicy:1;
+#else
+ USHORT ACKPolicy:1; // 0:normal ack, 1:no ack.
+ USHORT MTID:1; //if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ
+ USHORT Compressed:1;
+ USHORT Rsv1:9;
+ USHORT TID:4;
+#endif /* !RT_BIG_ENDIAN */
+} BAR_CONTROL, *PBAR_CONTROL;
+
+// BARControl in MTBAR frame
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT NumTID:4;
+ USHORT Rsv1:9;
+ USHORT Compressed:1;
+ USHORT MTID:1;
+ USHORT ACKPolicy:1;
+#else
+ USHORT ACKPolicy:1;
+ USHORT MTID:1;
+ USHORT Compressed:1;
+ USHORT Rsv1:9;
+ USHORT NumTID:4;
+#endif /* !RT_BIG_ENDIAN */
+} MTBAR_CONTROL, *PMTBAR_CONTROL;
+
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ USHORT TID:4;
+ USHORT Rsv1:12;
+#else
+ USHORT Rsv1:12;
+ USHORT TID:4;
+#endif /* !RT_BIG_ENDIAN */
+} PER_TID_INFO, *PPER_TID_INFO;
+
+typedef struct {
+ PER_TID_INFO PerTID;
+ BASEQ_CONTROL BAStartingSeq;
+} EACH_TID, *PEACH_TID;
+
+
+typedef struct PACKED _PSPOLL_FRAME {
+ FRAME_CONTROL FC;
+ USHORT Aid;
+ UCHAR Bssid[MAC_ADDR_LEN];
+ UCHAR Ta[MAC_ADDR_LEN];
+} PSPOLL_FRAME, *PPSPOLL_FRAME;
+
+typedef struct PACKED _RTS_FRAME {
+ FRAME_CONTROL FC;
+ USHORT Duration;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+}RTS_FRAME, *PRTS_FRAME;
+
+// BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap.
+typedef struct PACKED _FRAME_BA_REQ {
+ FRAME_CONTROL FC;
+ USHORT Duration;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+ BAR_CONTROL BARControl;
+ BASEQ_CONTROL BAStartingSeq;
+} FRAME_BA_REQ, *PFRAME_BA_REQ;
+
+typedef struct PACKED _FRAME_MTBA_REQ {
+ FRAME_CONTROL FC;
+ USHORT Duration;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+ MTBAR_CONTROL MTBARControl;
+ PER_TID_INFO PerTIDInfo;
+ BASEQ_CONTROL BAStartingSeq;
+} FRAME_MTBA_REQ, *PFRAME_MTBA_REQ;
+
+// Compressed format is mandantory in HT STA
+typedef struct PACKED _FRAME_MTBA {
+ FRAME_CONTROL FC;
+ USHORT Duration;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+ BA_CONTROL BAControl;
+ BASEQ_CONTROL BAStartingSeq;
+ UCHAR BitMap[8];
+} FRAME_MTBA, *PFRAME_MTBA;
+
+typedef struct PACKED _FRAME_PSMP_ACTION {
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+ UCHAR Psmp; // 7.3.1.25
+} FRAME_PSMP_ACTION, *PFRAME_PSMP_ACTION;
+
+typedef struct PACKED _FRAME_ACTION_HDR {
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+} FRAME_ACTION_HDR, *PFRAME_ACTION_HDR;
+
+//Action Frame
+//Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20
+typedef struct PACKED _CHAN_SWITCH_ANNOUNCE {
+ UCHAR ElementID; // ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37
+ UCHAR Len;
+ CHA_SWITCH_ANNOUNCE_IE CSAnnounceIe;
+} CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE;
+
+
+//802.11n : 7.3.2.20a
+typedef struct PACKED _SECOND_CHAN_OFFSET {
+ UCHAR ElementID; // ID = IE_SECONDARY_CH_OFFSET = 62
+ UCHAR Len;
+ SEC_CHA_OFFSET_IE SecChOffsetIe;
+} SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET;
+
+
+typedef struct PACKED _FRAME_SPETRUM_CS {
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+ CHAN_SWITCH_ANNOUNCE CSAnnounce;
+ SECOND_CHAN_OFFSET SecondChannel;
+} FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS;
+
+
+typedef struct PACKED _FRAME_ADDBA_REQ {
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+ UCHAR Token; // 1
+ BA_PARM BaParm; // 2 - 10
+ USHORT TimeOutValue; // 0 - 0
+ BASEQ_CONTROL BaStartSeq; // 0-0
+} FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ;
+
+typedef struct PACKED _FRAME_ADDBA_RSP {
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+ UCHAR Token;
+ USHORT StatusCode;
+ BA_PARM BaParm; //0 - 2
+ USHORT TimeOutValue;
+} FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP;
+
+typedef struct PACKED _FRAME_DELBA_REQ {
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+ DELBA_PARM DelbaParm;
+ USHORT ReasonCode;
+} FRAME_DELBA_REQ, *PFRAME_DELBA_REQ;
+
+
+//7.2.1.7
+typedef struct PACKED _FRAME_BAR {
+ FRAME_CONTROL FC;
+ USHORT Duration;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+ BAR_CONTROL BarControl;
+ BASEQ_CONTROL StartingSeq;
+} FRAME_BAR, *PFRAME_BAR;
+
+//7.2.1.7
+typedef struct PACKED _FRAME_BA {
+ FRAME_CONTROL FC;
+ USHORT Duration;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+ BAR_CONTROL BarControl;
+ BASEQ_CONTROL StartingSeq;
+ UCHAR bitmask[8];
+} FRAME_BA, *PFRAME_BA;
+
+
+// Radio Measuement Request Frame Format
+typedef struct PACKED _FRAME_RM_REQ_ACTION {
+ HEADER_802_11 Hdr;
+ UCHAR Category;
+ UCHAR Action;
+ UCHAR Token;
+ USHORT Repetition;
+ UCHAR data[0];
+} FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION;
+
+typedef struct PACKED {
+ UCHAR ID;
+ UCHAR Length;
+ UCHAR ChannelSwitchMode;
+ UCHAR NewRegClass;
+ UCHAR NewChannelNum;
+ UCHAR ChannelSwitchCount;
+} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE;
+
+
+//
+// _Limit must be the 2**n - 1
+// _SEQ1 , _SEQ2 must be within 0 ~ _Limit
+//
+#define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit) ((_SEQ1 == ((_SEQ2+1) & _Limit)))
+#define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit) (((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))
+#define SEQ_LARGER(_SEQ1, _SEQ2, _Limit) ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1))))
+#define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) && \
+ SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit))
+
+//
+// Contention-free parameter (without ID and Length)
+//
+typedef struct PACKED {
+ BOOLEAN bValid; // 1: variable contains valid value
+ UCHAR CfpCount;
+ UCHAR CfpPeriod;
+ USHORT CfpMaxDuration;
+ USHORT CfpDurRemaining;
+} CF_PARM, *PCF_PARM;
+
+typedef struct _CIPHER_SUITE {
+ NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher 1, this one has more secured cipher suite
+ NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; // Unicast cipher 2 if AP announce two unicast cipher suite
+ NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Group cipher
+ USHORT RsnCapability; // RSN capability from beacon
+ BOOLEAN bMixMode; // Indicate Pair & Group cipher might be different
+} CIPHER_SUITE, *PCIPHER_SUITE;
+
+// EDCA configuration from AP's BEACON/ProbeRsp
+typedef struct {
+ BOOLEAN bValid; // 1: variable contains valid value
+ BOOLEAN bAdd; // 1: variable contains valid value
+ BOOLEAN bQAck;
+ BOOLEAN bQueueRequest;
+ BOOLEAN bTxopRequest;
+ BOOLEAN bAPSDCapable;
+// BOOLEAN bMoreDataAck;
+ UCHAR EdcaUpdateCount;
+ UCHAR Aifsn[4]; // 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO
+ UCHAR Cwmin[4];
+ UCHAR Cwmax[4];
+ USHORT Txop[4]; // in unit of 32-us
+ BOOLEAN bACM[4]; // 1: Admission Control of AC_BK is mandattory
+} EDCA_PARM, *PEDCA_PARM;
+
+// QBSS LOAD information from QAP's BEACON/ProbeRsp
+typedef struct {
+ BOOLEAN bValid; // 1: variable contains valid value
+ USHORT StaNum;
+ UCHAR ChannelUtilization;
+ USHORT RemainingAdmissionControl; // in unit of 32-us
+} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM;
+
+// QBSS Info field in QSTA's assoc req
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ UCHAR Rsv2:1;
+ UCHAR MaxSPLength:2;
+ UCHAR Rsv1:1;
+ UCHAR UAPSD_AC_BE:1;
+ UCHAR UAPSD_AC_BK:1;
+ UCHAR UAPSD_AC_VI:1;
+ UCHAR UAPSD_AC_VO:1;
+#else
+ UCHAR UAPSD_AC_VO:1;
+ UCHAR UAPSD_AC_VI:1;
+ UCHAR UAPSD_AC_BK:1;
+ UCHAR UAPSD_AC_BE:1;
+ UCHAR Rsv1:1;
+ UCHAR MaxSPLength:2;
+ UCHAR Rsv2:1;
+#endif /* !RT_BIG_ENDIAN */
+} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM;
+
+// QBSS Info field in QAP's Beacon/ProbeRsp
+typedef struct PACKED {
+#ifdef RT_BIG_ENDIAN
+ UCHAR UAPSD:1;
+ UCHAR Rsv:3;
+ UCHAR ParamSetCount:4;
+#else
+ UCHAR ParamSetCount:4;
+ UCHAR Rsv:3;
+ UCHAR UAPSD:1;
+#endif /* !RT_BIG_ENDIAN */
+} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM;
+
+// QOS Capability reported in QAP's BEACON/ProbeRsp
+// QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq
+typedef struct {
+ BOOLEAN bValid; // 1: variable contains valid value
+ BOOLEAN bQAck;
+ BOOLEAN bQueueRequest;
+ BOOLEAN bTxopRequest;
+// BOOLEAN bMoreDataAck;
+ UCHAR EdcaUpdateCount;
+} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM;
+
+#ifdef CONFIG_STA_SUPPORT
+typedef struct {
+ UCHAR IELen;
+ UCHAR IE[MAX_CUSTOM_LEN];
+} WPA_IE_;
+#endif // CONFIG_STA_SUPPORT //
+
+
+typedef struct {
+ UCHAR Bssid[MAC_ADDR_LEN];
+ UCHAR Channel;
+ UCHAR CentralChannel; //Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel.
+ UCHAR BssType;
+ USHORT AtimWin;
+ USHORT BeaconPeriod;
+
+ UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR SupRateLen;
+ UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR ExtRateLen;
+ HT_CAPABILITY_IE HtCapability;
+ UCHAR HtCapabilityLen;
+ ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
+ UCHAR AddHtInfoLen;
+ UCHAR NewExtChanOffset;
+ CHAR Rssi;
+ UCHAR Privacy; // Indicate security function ON/OFF. Don't mess up with auth mode.
+ UCHAR Hidden;
+
+ USHORT DtimPeriod;
+ USHORT CapabilityInfo;
+
+ USHORT CfpCount;
+ USHORT CfpPeriod;
+ USHORT CfpMaxDuration;
+ USHORT CfpDurRemaining;
+ UCHAR SsidLen;
+ CHAR Ssid[MAX_LEN_OF_SSID];
+
+ ULONG LastBeaconRxTime; // OS's timestamp
+
+ BOOLEAN bSES;
+
+ // New for WPA2
+ CIPHER_SUITE WPA; // AP announced WPA cipher suite
+ CIPHER_SUITE WPA2; // AP announced WPA2 cipher suite
+
+ // New for microsoft WPA support
+ NDIS_802_11_FIXED_IEs FixIEs;
+ NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; // Addition mode for WPA2 / WPA capable AP
+ NDIS_802_11_AUTHENTICATION_MODE AuthMode;
+ NDIS_802_11_WEP_STATUS WepStatus; // Unicast Encryption Algorithm extract from VAR_IE
+ USHORT VarIELen; // Length of next VIE include EID & Length
+ UCHAR VarIEs[MAX_VIE_LEN];
+
+ // CCX Ckip information
+ UCHAR CkipFlag;
+
+ // CCX 2 TSF
+ UCHAR PTSF[4]; // Parent TSF
+ UCHAR TTSF[8]; // Target TSF
+
+ // 802.11e d9, and WMM
+ EDCA_PARM EdcaParm;
+ QOS_CAPABILITY_PARM QosCapability;
+ QBSS_LOAD_PARM QbssLoad;
+#ifdef CONFIG_STA_SUPPORT
+ WPA_IE_ WpaIE;
+ WPA_IE_ RsnIE;
+#ifdef EXT_BUILD_CHANNEL_LIST
+ UCHAR CountryString[3];
+ BOOLEAN bHasCountryIE;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+} BSS_ENTRY, *PBSS_ENTRY;
+
+typedef struct {
+ UCHAR BssNr;
+ UCHAR BssOverlapNr;
+ BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE];
+} BSS_TABLE, *PBSS_TABLE;
+
+
+typedef struct _MLME_QUEUE_ELEM {
+ ULONG Machine;
+ ULONG MsgType;
+ ULONG MsgLen;
+ UCHAR Msg[MGMT_DMA_BUFFER_SIZE];
+ LARGE_INTEGER TimeStamp;
+ UCHAR Rssi0;
+ UCHAR Rssi1;
+ UCHAR Rssi2;
+ UCHAR Signal;
+ UCHAR Channel;
+ UCHAR Wcid;
+ BOOLEAN Occupied;
+} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM;
+
+typedef struct _MLME_QUEUE {
+ ULONG Num;
+ ULONG Head;
+ ULONG Tail;
+ NDIS_SPIN_LOCK Lock;
+ MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE];
+} MLME_QUEUE, *PMLME_QUEUE;
+
+typedef VOID (*STATE_MACHINE_FUNC)(VOID *Adaptor, MLME_QUEUE_ELEM *Elem);
+
+typedef struct _STATE_MACHINE {
+ ULONG Base;
+ ULONG NrState;
+ ULONG NrMsg;
+ ULONG CurrState;
+ STATE_MACHINE_FUNC *TransFunc;
+} STATE_MACHINE, *PSTATE_MACHINE;
+
+
+// MLME AUX data structure that hold temporarliy settings during a connection attempt.
+// Once this attemp succeeds, all settings will be copy to pAd->StaActive.
+// A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of
+// several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely
+// separate this under-trial settings away from pAd->StaActive so that once
+// this new attempt failed, driver can auto-recover back to the active settings.
+typedef struct _MLME_AUX {
+ UCHAR BssType;
+ UCHAR Ssid[MAX_LEN_OF_SSID];
+ UCHAR SsidLen;
+ UCHAR Bssid[MAC_ADDR_LEN];
+ UCHAR AutoReconnectSsid[MAX_LEN_OF_SSID];
+ UCHAR AutoReconnectSsidLen;
+ USHORT Alg;
+ UCHAR ScanType;
+ UCHAR Channel;
+ UCHAR CentralChannel;
+ USHORT Aid;
+ USHORT CapabilityInfo;
+ USHORT BeaconPeriod;
+ USHORT CfpMaxDuration;
+ USHORT CfpPeriod;
+ USHORT AtimWin;
+
+ // Copy supported rate from desired AP's beacon. We are trying to match
+ // AP's supported and extended rate settings.
+ UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR SupRateLen;
+ UCHAR ExtRateLen;
+ HT_CAPABILITY_IE HtCapability;
+ UCHAR HtCapabilityLen;
+ ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
+ UCHAR NewExtChannelOffset;
+ //RT_HT_CAPABILITY SupportedHtPhy;
+
+ // new for QOS
+ QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP
+ EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP
+ QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP
+
+ // new to keep Ralink specific feature
+ ULONG APRalinkIe;
+
+ BSS_TABLE SsidBssTab; // AP list for the same SSID
+ BSS_TABLE RoamTab; // AP list eligible for roaming
+ ULONG BssIdx;
+ ULONG RoamIdx;
+
+ BOOLEAN CurrReqIsFromNdis;
+
+ RALINK_TIMER_STRUCT BeaconTimer, ScanTimer;
+ RALINK_TIMER_STRUCT AuthTimer;
+ RALINK_TIMER_STRUCT AssocTimer, ReassocTimer, DisassocTimer;
+} MLME_AUX, *PMLME_AUX;
+
+typedef struct _MLME_ADDBA_REQ_STRUCT{
+ UCHAR Wcid; //
+ UCHAR pAddr[MAC_ADDR_LEN];
+ UCHAR BaBufSize;
+ USHORT TimeOutValue;
+ UCHAR TID;
+ UCHAR Token;
+ USHORT BaStartSeq;
+} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT;
+
+
+typedef struct _MLME_DELBA_REQ_STRUCT{
+ UCHAR Wcid; //
+ UCHAR Addr[MAC_ADDR_LEN];
+ UCHAR TID;
+ UCHAR Initiator;
+} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT;
+
+// assoc struct is equal to reassoc
+typedef struct _MLME_ASSOC_REQ_STRUCT{
+ UCHAR Addr[MAC_ADDR_LEN];
+ USHORT CapabilityInfo;
+ USHORT ListenIntv;
+ ULONG Timeout;
+} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT;
+
+typedef struct _MLME_DISASSOC_REQ_STRUCT{
+ UCHAR Addr[MAC_ADDR_LEN];
+ USHORT Reason;
+} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT;
+
+typedef struct _MLME_AUTH_REQ_STRUCT {
+ UCHAR Addr[MAC_ADDR_LEN];
+ USHORT Alg;
+ ULONG Timeout;
+} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT;
+
+typedef struct _MLME_DEAUTH_REQ_STRUCT {
+ UCHAR Addr[MAC_ADDR_LEN];
+ USHORT Reason;
+} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT;
+
+typedef struct {
+ ULONG BssIdx;
+} MLME_JOIN_REQ_STRUCT;
+
+typedef struct _MLME_SCAN_REQ_STRUCT {
+ UCHAR Bssid[MAC_ADDR_LEN];
+ UCHAR BssType;
+ UCHAR ScanType;
+ UCHAR SsidLen;
+ CHAR Ssid[MAX_LEN_OF_SSID];
+} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT;
+
+typedef struct _MLME_START_REQ_STRUCT {
+ CHAR Ssid[MAX_LEN_OF_SSID];
+ UCHAR SsidLen;
+} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT;
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+// structure for DLS
+typedef struct _RT_802_11_DLS {
+ USHORT TimeOut; // Use to time out while slience, unit: second , set by UI
+ USHORT CountDownTimer; // Use to time out while slience,unit: second , used by driver only
+ NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI
+ UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only
+ BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link
+ RALINK_TIMER_STRUCT Timer; // Use to time out while handshake
+ USHORT Sequence;
+ USHORT MacTabMatchWCID; // ASIC
+ BOOLEAN bHTCap;
+ PVOID pAd;
+} RT_802_11_DLS, *PRT_802_11_DLS;
+
+typedef struct _MLME_DLS_REQ_STRUCT {
+ PRT_802_11_DLS pDLS;
+ USHORT Reason;
+} MLME_DLS_REQ_STRUCT, *PMLME_DLS_REQ_STRUCT;
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+typedef struct PACKED {
+ UCHAR Eid;
+ UCHAR Len;
+ CHAR Octet[1];
+} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT;
+
+typedef struct PACKED _RTMP_TX_RATE_SWITCH
+{
+ UCHAR ItemNo;
+#ifdef RT_BIG_ENDIAN
+ UCHAR Rsv2:2;
+ UCHAR Mode:2;
+ UCHAR Rsv1:1;
+ UCHAR BW:1;
+ UCHAR ShortGI:1;
+ UCHAR STBC:1;
+#else
+ UCHAR STBC:1;
+ UCHAR ShortGI:1;
+ UCHAR BW:1;
+ UCHAR Rsv1:1;
+ UCHAR Mode:2;
+ UCHAR Rsv2:2;
+#endif
+ UCHAR CurrMCS;
+ UCHAR TrainUp;
+ UCHAR TrainDown;
+} RRTMP_TX_RATE_SWITCH, *PRTMP_TX_RATE_SWITCH;
+
+// ========================== AP mlme.h ===============================
+#define TBTT_PRELOAD_TIME 384 // usec. LomgPreamble + 24-byte at 1Mbps
+#define DEFAULT_DTIM_PERIOD 1
+
+#define MAC_TABLE_AGEOUT_TIME 300 // unit: sec
+#define MAC_TABLE_ASSOC_TIMEOUT 5 // unit: sec
+#define MAC_TABLE_FULL(Tab) ((Tab).size == MAX_LEN_OF_MAC_TABLE)
+
+// AP shall drop the sta if contine Tx fail count reach it.
+#define MAC_ENTRY_LIFE_CHECK_CNT 20 // packet cnt.
+
+// Value domain of pMacEntry->Sst
+typedef enum _Sst {
+ SST_NOT_AUTH, // 0: equivalent to IEEE 802.11/1999 state 1
+ SST_AUTH, // 1: equivalent to IEEE 802.11/1999 state 2
+ SST_ASSOC // 2: equivalent to IEEE 802.11/1999 state 3
+} SST;
+
+// value domain of pMacEntry->AuthState
+typedef enum _AuthState {
+ AS_NOT_AUTH,
+ AS_AUTH_OPEN, // STA has been authenticated using OPEN SYSTEM
+ AS_AUTH_KEY, // STA has been authenticated using SHARED KEY
+ AS_AUTHENTICATING // STA is waiting for AUTH seq#3 using SHARED KEY
+} AUTH_STATE;
+
+//for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114
+typedef enum _ApWpaState {
+ AS_NOTUSE, // 0
+ AS_DISCONNECT, // 1
+ AS_DISCONNECTED, // 2
+ AS_INITIALIZE, // 3
+ AS_AUTHENTICATION, // 4
+ AS_AUTHENTICATION2, // 5
+ AS_INITPMK, // 6
+ AS_INITPSK, // 7
+ AS_PTKSTART, // 8
+ AS_PTKINIT_NEGOTIATING, // 9
+ AS_PTKINITDONE, // 10
+ AS_UPDATEKEYS, // 11
+ AS_INTEGRITY_FAILURE, // 12
+ AS_KEYUPDATE, // 13
+} AP_WPA_STATE;
+
+// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114
+typedef enum _GTKState {
+ REKEY_NEGOTIATING,
+ REKEY_ESTABLISHED,
+ KEYERROR,
+} GTK_STATE;
+
+// for-wpa value domain of pMacEntry->WpaState 802.1i D3 p.114
+typedef enum _WpaGTKState {
+ SETKEYS,
+ SETKEYS_DONE,
+} WPA_GTK_STATE;
+// ====================== end of AP mlme.h ============================
+
+
+#endif // MLME_H__
diff --git a/drivers/staging/rt2860/oid.h b/drivers/staging/rt2860/oid.h
new file mode 100644
index 000000000000..f2f91b607c47
--- /dev/null
+++ b/drivers/staging/rt2860/oid.h
@@ -0,0 +1,995 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ oid.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+*/
+#ifndef _OID_H_
+#define _OID_H_
+
+
+#define TRUE 1
+#define FALSE 0
+//
+// IEEE 802.11 Structures and definitions
+//
+#define MAX_TX_POWER_LEVEL 100 /* mW */
+#define MAX_RSSI_TRIGGER -10 /* dBm */
+#define MIN_RSSI_TRIGGER -200 /* dBm */
+#define MAX_FRAG_THRESHOLD 2346 /* byte count */
+#define MIN_FRAG_THRESHOLD 256 /* byte count */
+#define MAX_RTS_THRESHOLD 2347 /* byte count */
+
+// new types for Media Specific Indications
+// Extension channel offset
+#define EXTCHA_NONE 0
+#define EXTCHA_ABOVE 0x1
+#define EXTCHA_BELOW 0x3
+
+// BW
+#define BAND_WIDTH_20 0
+#define BAND_WIDTH_40 1
+#define BAND_WIDTH_BOTH 2
+#define BAND_WIDTH_10 3 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field.
+// SHORTGI
+#define GAP_INTERVAL_400 1 // only support in HT mode
+#define GAP_INTERVAL_800 0
+#define GAP_INTERVAL_BOTH 2
+
+#define NdisMediaStateConnected 1
+#define NdisMediaStateDisconnected 0
+
+#define NDIS_802_11_LENGTH_SSID 32
+#define NDIS_802_11_LENGTH_RATES 8
+#define NDIS_802_11_LENGTH_RATES_EX 16
+#define MAC_ADDR_LENGTH 6
+#define MAX_NUM_OF_CHS 49 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc
+#define MAX_NUMBER_OF_EVENT 10 // entry # in EVENT table
+#define MAX_NUMBER_OF_MAC 32 // if MAX_MBSSID_NUM is 8, this value can't be larger than 211
+#define MAX_NUMBER_OF_ACL 64
+#define MAX_LENGTH_OF_SUPPORT_RATES 12 // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
+#define MAX_NUMBER_OF_DLS_ENTRY 4
+
+#ifndef UNDER_CE
+
+#define OID_GEN_MACHINE_NAME 0x0001021A
+
+#ifdef RALINK_ATE
+#define RT_QUERY_ATE_TXDONE_COUNT 0x0401
+#endif // RALINK_ATE //
+#define RT_QUERY_SIGNAL_CONTEXT 0x0402
+#define RT_SET_IAPP_PID 0x0404
+#define RT_SET_APD_PID 0x0405
+#define RT_SET_DEL_MAC_ENTRY 0x0406
+
+//
+// IEEE 802.11 OIDs
+//
+#define OID_GET_SET_TOGGLE 0x8000
+
+#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0103
+#define OID_802_11_NETWORK_TYPE_IN_USE 0x0104
+#define OID_802_11_RSSI_TRIGGER 0x0107
+#define RT_OID_802_11_RSSI 0x0108 //rt2860 only , kathy
+#define RT_OID_802_11_RSSI_1 0x0109 //rt2860 only , kathy
+#define RT_OID_802_11_RSSI_2 0x010A //rt2860 only , kathy
+#define OID_802_11_NUMBER_OF_ANTENNAS 0x010B
+#define OID_802_11_RX_ANTENNA_SELECTED 0x010C
+#define OID_802_11_TX_ANTENNA_SELECTED 0x010D
+#define OID_802_11_SUPPORTED_RATES 0x010E
+#define OID_802_11_ADD_WEP 0x0112
+#define OID_802_11_REMOVE_WEP 0x0113
+#define OID_802_11_DISASSOCIATE 0x0114
+#define OID_802_11_PRIVACY_FILTER 0x0118
+#define OID_802_11_ASSOCIATION_INFORMATION 0x011E
+#define OID_802_11_TEST 0x011F
+#define RT_OID_802_11_COUNTRY_REGION 0x0507
+#define OID_802_11_BSSID_LIST_SCAN 0x0508
+#define OID_802_11_SSID 0x0509
+#define OID_802_11_BSSID 0x050A
+#define RT_OID_802_11_RADIO 0x050B
+#define RT_OID_802_11_PHY_MODE 0x050C
+#define RT_OID_802_11_STA_CONFIG 0x050D
+#define OID_802_11_DESIRED_RATES 0x050E
+#define RT_OID_802_11_PREAMBLE 0x050F
+#define OID_802_11_WEP_STATUS 0x0510
+#define OID_802_11_AUTHENTICATION_MODE 0x0511
+#define OID_802_11_INFRASTRUCTURE_MODE 0x0512
+#define RT_OID_802_11_RESET_COUNTERS 0x0513
+#define OID_802_11_RTS_THRESHOLD 0x0514
+#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0515
+#define OID_802_11_POWER_MODE 0x0516
+#define OID_802_11_TX_POWER_LEVEL 0x0517
+#define RT_OID_802_11_ADD_WPA 0x0518
+#define OID_802_11_REMOVE_KEY 0x0519
+#define OID_802_11_ADD_KEY 0x0520
+#define OID_802_11_CONFIGURATION 0x0521
+#define OID_802_11_TX_PACKET_BURST 0x0522
+#define RT_OID_802_11_QUERY_NOISE_LEVEL 0x0523
+#define RT_OID_802_11_EXTRA_INFO 0x0524
+#ifdef DBG
+#define RT_OID_802_11_HARDWARE_REGISTER 0x0525
+#endif
+#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS
+#define OID_802_11_DEAUTHENTICATION 0x0526
+#define OID_802_11_DROP_UNENCRYPTED 0x0527
+#define OID_802_11_MIC_FAILURE_REPORT_FRAME 0x0528
+
+// For 802.1x daemin using to require current driver configuration
+#define OID_802_11_RADIUS_QUERY_SETTING 0x0540
+
+#define RT_OID_DEVICE_NAME 0x0607
+#define RT_OID_VERSION_INFO 0x0608
+#define OID_802_11_BSSID_LIST 0x0609
+#define OID_802_3_CURRENT_ADDRESS 0x060A
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x060B
+#define RT_OID_802_11_QUERY_LINK_STATUS 0x060C
+#define OID_802_11_RSSI 0x060D
+#define OID_802_11_STATISTICS 0x060E
+#define OID_GEN_RCV_OK 0x060F
+#define OID_GEN_RCV_NO_BUFFER 0x0610
+#define RT_OID_802_11_QUERY_EEPROM_VERSION 0x0611
+#define RT_OID_802_11_QUERY_FIRMWARE_VERSION 0x0612
+#define RT_OID_802_11_QUERY_LAST_RX_RATE 0x0613
+#define RT_OID_802_11_TX_POWER_LEVEL_1 0x0614
+#define RT_OID_802_11_QUERY_PIDVID 0x0615
+//for WPA_SUPPLICANT_SUPPORT
+#define OID_SET_COUNTERMEASURES 0x0616
+#define OID_802_11_SET_IEEE8021X 0x0617
+#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618
+#define OID_802_11_PMKID 0x0620
+#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621
+#define RT_OID_WE_VERSION_COMPILED 0x0622
+#define RT_OID_NEW_DRIVER 0x0623
+
+
+//rt2860 , kathy
+#define RT_OID_802_11_SNR_0 0x0630
+#define RT_OID_802_11_SNR_1 0x0631
+#define RT_OID_802_11_QUERY_LAST_TX_RATE 0x0632
+#define RT_OID_802_11_QUERY_HT_PHYMODE 0x0633
+#define RT_OID_802_11_SET_HT_PHYMODE 0x0634
+#define OID_802_11_RELOAD_DEFAULTS 0x0635
+#define RT_OID_802_11_QUERY_APSD_SETTING 0x0636
+#define RT_OID_802_11_SET_APSD_SETTING 0x0637
+#define RT_OID_802_11_QUERY_APSD_PSM 0x0638
+#define RT_OID_802_11_SET_APSD_PSM 0x0639
+#define RT_OID_802_11_QUERY_DLS 0x063A
+#define RT_OID_802_11_SET_DLS 0x063B
+#define RT_OID_802_11_QUERY_DLS_PARAM 0x063C
+#define RT_OID_802_11_SET_DLS_PARAM 0x063D
+#define RT_OID_802_11_QUERY_WMM 0x063E
+#define RT_OID_802_11_SET_WMM 0x063F
+#define RT_OID_802_11_QUERY_IMME_BA_CAP 0x0640
+#define RT_OID_802_11_SET_IMME_BA_CAP 0x0641
+#define RT_OID_802_11_QUERY_BATABLE 0x0642
+#define RT_OID_802_11_ADD_IMME_BA 0x0643
+#define RT_OID_802_11_TEAR_IMME_BA 0x0644
+#define RT_OID_DRIVER_DEVICE_NAME 0x0645
+#define RT_OID_802_11_QUERY_DAT_HT_PHYMODE 0x0646
+#define RT_OID_QUERY_MULTIPLE_CARD_SUPPORT 0x0647
+
+// Ralink defined OIDs
+// Dennis Lee move to platform specific
+
+#define RT_OID_802_11_BSSID (OID_GET_SET_TOGGLE | OID_802_11_BSSID)
+#define RT_OID_802_11_SSID (OID_GET_SET_TOGGLE | OID_802_11_SSID)
+#define RT_OID_802_11_INFRASTRUCTURE_MODE (OID_GET_SET_TOGGLE | OID_802_11_INFRASTRUCTURE_MODE)
+#define RT_OID_802_11_ADD_WEP (OID_GET_SET_TOGGLE | OID_802_11_ADD_WEP)
+#define RT_OID_802_11_ADD_KEY (OID_GET_SET_TOGGLE | OID_802_11_ADD_KEY)
+#define RT_OID_802_11_REMOVE_WEP (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_WEP)
+#define RT_OID_802_11_REMOVE_KEY (OID_GET_SET_TOGGLE | OID_802_11_REMOVE_KEY)
+#define RT_OID_802_11_DISASSOCIATE (OID_GET_SET_TOGGLE | OID_802_11_DISASSOCIATE)
+#define RT_OID_802_11_AUTHENTICATION_MODE (OID_GET_SET_TOGGLE | OID_802_11_AUTHENTICATION_MODE)
+#define RT_OID_802_11_PRIVACY_FILTER (OID_GET_SET_TOGGLE | OID_802_11_PRIVACY_FILTER)
+#define RT_OID_802_11_BSSID_LIST_SCAN (OID_GET_SET_TOGGLE | OID_802_11_BSSID_LIST_SCAN)
+#define RT_OID_802_11_WEP_STATUS (OID_GET_SET_TOGGLE | OID_802_11_WEP_STATUS)
+#define RT_OID_802_11_RELOAD_DEFAULTS (OID_GET_SET_TOGGLE | OID_802_11_RELOAD_DEFAULTS)
+#define RT_OID_802_11_NETWORK_TYPE_IN_USE (OID_GET_SET_TOGGLE | OID_802_11_NETWORK_TYPE_IN_USE)
+#define RT_OID_802_11_TX_POWER_LEVEL (OID_GET_SET_TOGGLE | OID_802_11_TX_POWER_LEVEL)
+#define RT_OID_802_11_RSSI_TRIGGER (OID_GET_SET_TOGGLE | OID_802_11_RSSI_TRIGGER)
+#define RT_OID_802_11_FRAGMENTATION_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_FRAGMENTATION_THRESHOLD)
+#define RT_OID_802_11_RTS_THRESHOLD (OID_GET_SET_TOGGLE | OID_802_11_RTS_THRESHOLD)
+#define RT_OID_802_11_RX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_RX_ANTENNA_SELECTED)
+#define RT_OID_802_11_TX_ANTENNA_SELECTED (OID_GET_SET_TOGGLE | OID_802_11_TX_ANTENNA_SELECTED)
+#define RT_OID_802_11_SUPPORTED_RATES (OID_GET_SET_TOGGLE | OID_802_11_SUPPORTED_RATES)
+#define RT_OID_802_11_DESIRED_RATES (OID_GET_SET_TOGGLE | OID_802_11_DESIRED_RATES)
+#define RT_OID_802_11_CONFIGURATION (OID_GET_SET_TOGGLE | OID_802_11_CONFIGURATION)
+#define RT_OID_802_11_POWER_MODE (OID_GET_SET_TOGGLE | OID_802_11_POWER_MODE)
+
+typedef enum _NDIS_802_11_STATUS_TYPE
+{
+ Ndis802_11StatusType_Authentication,
+ Ndis802_11StatusType_MediaStreamMode,
+ Ndis802_11StatusType_PMKID_CandidateList,
+ Ndis802_11StatusTypeMax // not a real type, defined as an upper bound
+} NDIS_802_11_STATUS_TYPE, *PNDIS_802_11_STATUS_TYPE;
+
+typedef UCHAR NDIS_802_11_MAC_ADDRESS[6];
+
+typedef struct _NDIS_802_11_STATUS_INDICATION
+{
+ NDIS_802_11_STATUS_TYPE StatusType;
+} NDIS_802_11_STATUS_INDICATION, *PNDIS_802_11_STATUS_INDICATION;
+
+// mask for authentication/integrity fields
+#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f
+
+#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
+#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
+#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
+#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
+
+typedef struct _NDIS_802_11_AUTHENTICATION_REQUEST
+{
+ ULONG Length; // Length of structure
+ NDIS_802_11_MAC_ADDRESS Bssid;
+ ULONG Flags;
+} NDIS_802_11_AUTHENTICATION_REQUEST, *PNDIS_802_11_AUTHENTICATION_REQUEST;
+
+//Added new types for PMKID Candidate lists.
+typedef struct _PMKID_CANDIDATE {
+ NDIS_802_11_MAC_ADDRESS BSSID;
+ ULONG Flags;
+} PMKID_CANDIDATE, *PPMKID_CANDIDATE;
+
+typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST
+{
+ ULONG Version; // Version of the structure
+ ULONG NumCandidates; // No. of pmkid candidates
+ PMKID_CANDIDATE CandidateList[1];
+} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST;
+
+//Flags for PMKID Candidate list structure
+#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01
+
+// Added new types for OFDM 5G and 2.4G
+typedef enum _NDIS_802_11_NETWORK_TYPE
+{
+ Ndis802_11FH,
+ Ndis802_11DS,
+ Ndis802_11OFDM5,
+ Ndis802_11OFDM5_N,
+ Ndis802_11OFDM24,
+ Ndis802_11OFDM24_N,
+ Ndis802_11Automode,
+ Ndis802_11NetworkTypeMax // not a real type, defined as an upper bound
+} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE;
+
+typedef struct _NDIS_802_11_NETWORK_TYPE_LIST
+{
+ UINT NumberOfItems; // in list below, at least 1
+ NDIS_802_11_NETWORK_TYPE NetworkType [1];
+} NDIS_802_11_NETWORK_TYPE_LIST, *PNDIS_802_11_NETWORK_TYPE_LIST;
+
+typedef enum _NDIS_802_11_POWER_MODE
+{
+ Ndis802_11PowerModeCAM,
+ Ndis802_11PowerModeMAX_PSP,
+ Ndis802_11PowerModeFast_PSP,
+ Ndis802_11PowerModeLegacy_PSP,
+ Ndis802_11PowerModeMax // not a real mode, defined as an upper bound
+} NDIS_802_11_POWER_MODE, *PNDIS_802_11_POWER_MODE;
+
+typedef ULONG NDIS_802_11_TX_POWER_LEVEL; // in milliwatts
+
+//
+// Received Signal Strength Indication
+//
+typedef LONG NDIS_802_11_RSSI; // in dBm
+
+typedef struct _NDIS_802_11_CONFIGURATION_FH
+{
+ ULONG Length; // Length of structure
+ ULONG HopPattern; // As defined by 802.11, MSB set
+ ULONG HopSet; // to one if non-802.11
+ ULONG DwellTime; // units are Kusec
+} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH;
+
+typedef struct _NDIS_802_11_CONFIGURATION
+{
+ ULONG Length; // Length of structure
+ ULONG BeaconPeriod; // units are Kusec
+ ULONG ATIMWindow; // units are Kusec
+ ULONG DSConfig; // Frequency, units are kHz
+ NDIS_802_11_CONFIGURATION_FH FHConfig;
+} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION;
+
+typedef struct _NDIS_802_11_STATISTICS
+{
+ ULONG Length; // Length of structure
+ LARGE_INTEGER TransmittedFragmentCount;
+ LARGE_INTEGER MulticastTransmittedFrameCount;
+ LARGE_INTEGER FailedCount;
+ LARGE_INTEGER RetryCount;
+ LARGE_INTEGER MultipleRetryCount;
+ LARGE_INTEGER RTSSuccessCount;
+ LARGE_INTEGER RTSFailureCount;
+ LARGE_INTEGER ACKFailureCount;
+ LARGE_INTEGER FrameDuplicateCount;
+ LARGE_INTEGER ReceivedFragmentCount;
+ LARGE_INTEGER MulticastReceivedFrameCount;
+ LARGE_INTEGER FCSErrorCount;
+ LARGE_INTEGER TKIPLocalMICFailures;
+ LARGE_INTEGER TKIPRemoteMICErrors;
+ LARGE_INTEGER TKIPICVErrors;
+ LARGE_INTEGER TKIPCounterMeasuresInvoked;
+ LARGE_INTEGER TKIPReplays;
+ LARGE_INTEGER CCMPFormatErrors;
+ LARGE_INTEGER CCMPReplays;
+ LARGE_INTEGER CCMPDecryptErrors;
+ LARGE_INTEGER FourWayHandshakeFailures;
+} NDIS_802_11_STATISTICS, *PNDIS_802_11_STATISTICS;
+
+typedef ULONG NDIS_802_11_KEY_INDEX;
+typedef ULONGLONG NDIS_802_11_KEY_RSC;
+
+#define MAX_RADIUS_SRV_NUM 2 // 802.1x failover number
+
+typedef struct PACKED _RADIUS_SRV_INFO {
+ UINT32 radius_ip;
+ UINT32 radius_port;
+ UCHAR radius_key[64];
+ UCHAR radius_key_len;
+} RADIUS_SRV_INFO, *PRADIUS_SRV_INFO;
+
+typedef struct PACKED _RADIUS_KEY_INFO
+{
+ UCHAR radius_srv_num;
+ RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM];
+ UCHAR ieee8021xWEP; // dynamic WEP
+ UCHAR key_index;
+ UCHAR key_length; // length of key in bytes
+ UCHAR key_material[13];
+} RADIUS_KEY_INFO, *PRADIUS_KEY_INFO;
+
+// It's used by 802.1x daemon to require relative configuration
+typedef struct PACKED _RADIUS_CONF
+{
+ UINT32 Length; // Length of this structure
+ UCHAR mbss_num; // indicate multiple BSS number
+ UINT32 own_ip_addr;
+ UINT32 retry_interval;
+ UINT32 session_timeout_interval;
+ UCHAR EAPifname[IFNAMSIZ];
+ UCHAR EAPifname_len;
+ UCHAR PreAuthifname[IFNAMSIZ];
+ UCHAR PreAuthifname_len;
+ RADIUS_KEY_INFO RadiusInfo[8/*MAX_MBSSID_NUM*/];
+} RADIUS_CONF, *PRADIUS_CONF;
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+// Key mapping keys require a BSSID
+typedef struct _NDIS_802_11_KEY
+{
+ UINT Length; // Length of this structure
+ UINT KeyIndex;
+ UINT KeyLength; // length of key in bytes
+ NDIS_802_11_MAC_ADDRESS BSSID;
+ NDIS_802_11_KEY_RSC KeyRSC;
+ UCHAR KeyMaterial[1]; // variable length depending on above field
+} NDIS_802_11_KEY, *PNDIS_802_11_KEY;
+#endif // CONFIG_STA_SUPPORT //
+
+typedef struct _NDIS_802_11_REMOVE_KEY
+{
+ UINT Length; // Length of this structure
+ UINT KeyIndex;
+ NDIS_802_11_MAC_ADDRESS BSSID;
+} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY;
+
+typedef struct _NDIS_802_11_WEP
+{
+ UINT Length; // Length of this structure
+ UINT KeyIndex; // 0 is the per-client key, 1-N are the
+ // global keys
+ UINT KeyLength; // length of key in bytes
+ UCHAR KeyMaterial[1];// variable length depending on above field
+} NDIS_802_11_WEP, *PNDIS_802_11_WEP;
+
+
+typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE
+{
+ Ndis802_11IBSS,
+ Ndis802_11Infrastructure,
+ Ndis802_11AutoUnknown,
+ Ndis802_11Monitor,
+ Ndis802_11InfrastructureMax // Not a real value, defined as upper bound
+} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE;
+
+// Add new authentication modes
+typedef enum _NDIS_802_11_AUTHENTICATION_MODE
+{
+ Ndis802_11AuthModeOpen,
+ Ndis802_11AuthModeShared,
+ Ndis802_11AuthModeAutoSwitch,
+ Ndis802_11AuthModeWPA,
+ Ndis802_11AuthModeWPAPSK,
+ Ndis802_11AuthModeWPANone,
+ Ndis802_11AuthModeWPA2,
+ Ndis802_11AuthModeWPA2PSK,
+ Ndis802_11AuthModeWPA1WPA2,
+ Ndis802_11AuthModeWPA1PSKWPA2PSK,
+ Ndis802_11AuthModeMax // Not a real mode, defined as upper bound
+} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE;
+
+typedef UCHAR NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES]; // Set of 8 data rates
+typedef UCHAR NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX]; // Set of 16 data rates
+
+typedef struct PACKED _NDIS_802_11_SSID
+{
+ UINT SsidLength; // length of SSID field below, in bytes;
+ // this can be zero.
+ UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; // SSID information field
+} NDIS_802_11_SSID, *PNDIS_802_11_SSID;
+
+
+typedef struct PACKED _NDIS_WLAN_BSSID
+{
+ ULONG Length; // Length of this structure
+ NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID
+ UCHAR Reserved[2];
+ NDIS_802_11_SSID Ssid; // SSID
+ ULONG Privacy; // WEP encryption requirement
+ NDIS_802_11_RSSI Rssi; // receive signal strength in dBm
+ NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
+ NDIS_802_11_CONFIGURATION Configuration;
+ NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
+ NDIS_802_11_RATES SupportedRates;
+} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID;
+
+typedef struct PACKED _NDIS_802_11_BSSID_LIST
+{
+ UINT NumberOfItems; // in list below, at least 1
+ NDIS_WLAN_BSSID Bssid[1];
+} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST;
+
+// Added Capabilities, IELength and IEs for each BSSID
+typedef struct PACKED _NDIS_WLAN_BSSID_EX
+{
+ ULONG Length; // Length of this structure
+ NDIS_802_11_MAC_ADDRESS MacAddress; // BSSID
+ UCHAR Reserved[2];
+ NDIS_802_11_SSID Ssid; // SSID
+ UINT Privacy; // WEP encryption requirement
+ NDIS_802_11_RSSI Rssi; // receive signal
+ // strength in dBm
+ NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
+ NDIS_802_11_CONFIGURATION Configuration;
+ NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
+ NDIS_802_11_RATES_EX SupportedRates;
+ ULONG IELength;
+ UCHAR IEs[1];
+} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX;
+
+typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX
+{
+ UINT NumberOfItems; // in list below, at least 1
+ NDIS_WLAN_BSSID_EX Bssid[1];
+} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX;
+
+typedef struct PACKED _NDIS_802_11_FIXED_IEs
+{
+ UCHAR Timestamp[8];
+ USHORT BeaconInterval;
+ USHORT Capabilities;
+} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs;
+
+typedef struct _NDIS_802_11_VARIABLE_IEs
+{
+ UCHAR ElementID;
+ UCHAR Length; // Number of bytes in data field
+ UCHAR data[1];
+} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs;
+
+typedef ULONG NDIS_802_11_FRAGMENTATION_THRESHOLD;
+
+typedef ULONG NDIS_802_11_RTS_THRESHOLD;
+
+typedef ULONG NDIS_802_11_ANTENNA;
+
+typedef enum _NDIS_802_11_PRIVACY_FILTER
+{
+ Ndis802_11PrivFilterAcceptAll,
+ Ndis802_11PrivFilter8021xWEP
+} NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER;
+
+// Added new encryption types
+// Also aliased typedef to new name
+typedef enum _NDIS_802_11_WEP_STATUS
+{
+ Ndis802_11WEPEnabled,
+ Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
+ Ndis802_11WEPDisabled,
+ Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
+ Ndis802_11WEPKeyAbsent,
+ Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
+ Ndis802_11WEPNotSupported,
+ Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
+ Ndis802_11Encryption2Enabled,
+ Ndis802_11Encryption2KeyAbsent,
+ Ndis802_11Encryption3Enabled,
+ Ndis802_11Encryption3KeyAbsent,
+ Ndis802_11Encryption4Enabled, // TKIP or AES mix
+ Ndis802_11Encryption4KeyAbsent,
+} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS,
+ NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS;
+
+typedef enum _NDIS_802_11_RELOAD_DEFAULTS
+{
+ Ndis802_11ReloadWEPKeys
+} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS;
+
+#define NDIS_802_11_AI_REQFI_CAPABILITIES 1
+#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2
+#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4
+
+#define NDIS_802_11_AI_RESFI_CAPABILITIES 1
+#define NDIS_802_11_AI_RESFI_STATUSCODE 2
+#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4
+
+typedef struct _NDIS_802_11_AI_REQFI
+{
+ USHORT Capabilities;
+ USHORT ListenInterval;
+ NDIS_802_11_MAC_ADDRESS CurrentAPAddress;
+} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI;
+
+typedef struct _NDIS_802_11_AI_RESFI
+{
+ USHORT Capabilities;
+ USHORT StatusCode;
+ USHORT AssociationId;
+} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI;
+
+typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION
+{
+ ULONG Length;
+ USHORT AvailableRequestFixedIEs;
+ NDIS_802_11_AI_REQFI RequestFixedIEs;
+ ULONG RequestIELength;
+ ULONG OffsetRequestIEs;
+ USHORT AvailableResponseFixedIEs;
+ NDIS_802_11_AI_RESFI ResponseFixedIEs;
+ ULONG ResponseIELength;
+ ULONG OffsetResponseIEs;
+} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION;
+
+typedef struct _NDIS_802_11_AUTHENTICATION_EVENT
+{
+ NDIS_802_11_STATUS_INDICATION Status;
+ NDIS_802_11_AUTHENTICATION_REQUEST Request[1];
+} NDIS_802_11_AUTHENTICATION_EVENT, *PNDIS_802_11_AUTHENTICATION_EVENT;
+
+// 802.11 Media stream constraints, associated with OID_802_11_MEDIA_STREAM_MODE
+typedef enum _NDIS_802_11_MEDIA_STREAM_MODE
+{
+ Ndis802_11MediaStreamOff,
+ Ndis802_11MediaStreamOn,
+} NDIS_802_11_MEDIA_STREAM_MODE, *PNDIS_802_11_MEDIA_STREAM_MODE;
+
+// PMKID Structures
+typedef UCHAR NDIS_802_11_PMKID_VALUE[16];
+
+#ifdef CONFIG_STA_SUPPORT
+typedef struct _BSSID_INFO
+{
+ NDIS_802_11_MAC_ADDRESS BSSID;
+ NDIS_802_11_PMKID_VALUE PMKID;
+} BSSID_INFO, *PBSSID_INFO;
+
+typedef struct _NDIS_802_11_PMKID
+{
+ UINT Length;
+ UINT BSSIDInfoCount;
+ BSSID_INFO BSSIDInfo[1];
+} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID;
+#endif // CONFIG_STA_SUPPORT //
+
+
+typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION
+{
+ NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported;
+ NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported;
+} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION;
+
+typedef struct _NDIS_802_11_CAPABILITY
+{
+ ULONG Length;
+ ULONG Version;
+ ULONG NoOfPMKIDs;
+ ULONG NoOfAuthEncryptPairsSupported;
+ NDIS_802_11_AUTHENTICATION_ENCRYPTION AuthenticationEncryptionSupported[1];
+} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY;
+
+//#endif //of WIN 2k
+#endif //UNDER_CE
+
+#if WIRELESS_EXT <= 11
+#ifndef SIOCDEVPRIVATE
+#define SIOCDEVPRIVATE 0x8BE0
+#endif
+#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
+#endif
+
+#ifdef CONFIG_STA_SUPPORT
+#define RTPRIV_IOCTL_SET (SIOCIWFIRSTPRIV + 0x02)
+
+#ifdef DBG
+#define RTPRIV_IOCTL_BBP (SIOCIWFIRSTPRIV + 0x03)
+#define RTPRIV_IOCTL_MAC (SIOCIWFIRSTPRIV + 0x05)
+#define RTPRIV_IOCTL_E2P (SIOCIWFIRSTPRIV + 0x07)
+#endif
+
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+#define RTPRIV_IOCTL_ATE (SIOCIWFIRSTPRIV + 0x08)
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+#define RTPRIV_IOCTL_STATISTICS (SIOCIWFIRSTPRIV + 0x09)
+#define RTPRIV_IOCTL_ADD_PMKID_CACHE (SIOCIWFIRSTPRIV + 0x0A)
+#define RTPRIV_IOCTL_RADIUS_DATA (SIOCIWFIRSTPRIV + 0x0C)
+#define RTPRIV_IOCTL_GSITESURVEY (SIOCIWFIRSTPRIV + 0x0D)
+#define RT_PRIV_IOCTL (SIOCIWFIRSTPRIV + 0x0E) // Sync. with RT61 (for wpa_supplicant)
+#define RTPRIV_IOCTL_GET_MAC_TABLE (SIOCIWFIRSTPRIV + 0x0F)
+
+#define RTPRIV_IOCTL_SHOW (SIOCIWFIRSTPRIV + 0x11)
+enum {
+ SHOW_CONN_STATUS = 4,
+ SHOW_DRVIER_VERION = 5,
+ SHOW_BA_INFO = 6,
+ SHOW_DESC_INFO = 7,
+ RAIO_OFF = 10,
+ RAIO_ON = 11,
+#ifdef QOS_DLS_SUPPORT
+ SHOW_DLS_ENTRY_INFO = 19,
+#endif // QOS_DLS_SUPPORT //
+ SHOW_CFG_VALUE = 20,
+};
+
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef SNMP_SUPPORT
+//SNMP ieee 802dot11, kathy , 2008_0220
+// dot11res(3)
+#define RT_OID_802_11_MANUFACTUREROUI 0x0700
+#define RT_OID_802_11_MANUFACTURERNAME 0x0701
+#define RT_OID_802_11_RESOURCETYPEIDNAME 0x0702
+
+// dot11smt(1)
+#define RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED 0x0703
+#define RT_OID_802_11_POWERMANAGEMENTMODE 0x0704
+#define OID_802_11_WEPDEFAULTKEYVALUE 0x0705 // read , write
+#define OID_802_11_WEPDEFAULTKEYID 0x0706
+#define RT_OID_802_11_WEPKEYMAPPINGLENGTH 0x0707
+#define OID_802_11_SHORTRETRYLIMIT 0x0708
+#define OID_802_11_LONGRETRYLIMIT 0x0709
+#define RT_OID_802_11_PRODUCTID 0x0710
+#define RT_OID_802_11_MANUFACTUREID 0x0711
+
+// //dot11Phy(4)
+#define OID_802_11_CURRENTCHANNEL 0x0712
+
+//dot11mac
+#define RT_OID_802_11_MAC_ADDRESS 0x0713
+#endif // SNMP_SUPPORT //
+
+#define OID_802_11_BUILD_CHANNEL_EX 0x0714
+#define OID_802_11_GET_CH_LIST 0x0715
+#define OID_802_11_GET_COUNTRY_CODE 0x0716
+#define OID_802_11_GET_CHANNEL_GEOGRAPHY 0x0717
+
+#ifdef LLTD_SUPPORT
+// for consistency with RT61
+#define RT_OID_GET_PHY_MODE 0x761
+#endif // LLTD_SUPPORT //
+
+// New for MeetingHouse Api support
+#define OID_MH_802_1X_SUPPORTED 0xFFEDC100
+
+// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!!
+typedef union _HTTRANSMIT_SETTING {
+#ifdef RT_BIG_ENDIAN
+ struct {
+ USHORT MODE:2; // Use definition MODE_xxx.
+ USHORT TxBF:1;
+ USHORT rsv:2;
+ USHORT STBC:2; //SPACE
+ USHORT ShortGI:1;
+ USHORT BW:1; //channel bandwidth 20MHz or 40 MHz
+ USHORT MCS:7; // MCS
+ } field;
+#else
+ struct {
+ USHORT MCS:7; // MCS
+ USHORT BW:1; //channel bandwidth 20MHz or 40 MHz
+ USHORT ShortGI:1;
+ USHORT STBC:2; //SPACE
+ USHORT rsv:2;
+ USHORT TxBF:1;
+ USHORT MODE:2; // Use definition MODE_xxx.
+ } field;
+#endif
+ USHORT word;
+ } HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING;
+
+typedef enum _RT_802_11_PREAMBLE {
+ Rt802_11PreambleLong,
+ Rt802_11PreambleShort,
+ Rt802_11PreambleAuto
+} RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE;
+
+// Only for STA, need to sync with AP
+// 2005-03-08 match current RaConfig.
+typedef enum _RT_802_11_PHY_MODE {
+ PHY_11BG_MIXED = 0,
+ PHY_11B,
+ PHY_11A,
+ PHY_11ABG_MIXED,
+ PHY_11G,
+#ifdef DOT11_N_SUPPORT
+ PHY_11ABGN_MIXED, // both band 5
+ PHY_11N_2_4G, // 11n-only with 2.4G band 6
+ PHY_11GN_MIXED, // 2.4G band 7
+ PHY_11AN_MIXED, // 5G band 8
+ PHY_11BGN_MIXED, // if check 802.11b. 9
+ PHY_11AGN_MIXED, // if check 802.11b. 10
+ PHY_11N_5G, // 11n-only with 5G band 11
+#endif // DOT11_N_SUPPORT //
+} RT_802_11_PHY_MODE;
+
+// put all proprietery for-query objects here to reduce # of Query_OID
+typedef struct _RT_802_11_LINK_STATUS {
+ ULONG CurrTxRate; // in units of 0.5Mbps
+ ULONG ChannelQuality; // 0..100 %
+ ULONG TxByteCount; // both ok and fail
+ ULONG RxByteCount; // both ok and fail
+ ULONG CentralChannel; // 40MHz central channel number
+} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS;
+
+typedef struct _RT_802_11_EVENT_LOG {
+ LARGE_INTEGER SystemTime; // timestammp via NdisGetCurrentSystemTime()
+ UCHAR Addr[MAC_ADDR_LENGTH];
+ USHORT Event; // EVENT_xxx
+} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG;
+
+typedef struct _RT_802_11_EVENT_TABLE {
+ ULONG Num;
+ ULONG Rsv; // to align Log[] at LARGE_INEGER boundary
+ RT_802_11_EVENT_LOG Log[MAX_NUMBER_OF_EVENT];
+} RT_802_11_EVENT_TABLE, PRT_802_11_EVENT_TABLE;
+
+// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!!
+typedef union _MACHTTRANSMIT_SETTING {
+ struct {
+ USHORT MCS:7; // MCS
+ USHORT BW:1; //channel bandwidth 20MHz or 40 MHz
+ USHORT ShortGI:1;
+ USHORT STBC:2; //SPACE
+ USHORT rsv:3;
+ USHORT MODE:2; // Use definition MODE_xxx.
+ } field;
+ USHORT word;
+ } MACHTTRANSMIT_SETTING, *PMACHTTRANSMIT_SETTING;
+
+typedef struct _RT_802_11_MAC_ENTRY {
+ UCHAR Addr[MAC_ADDR_LENGTH];
+ UCHAR Aid;
+ UCHAR Psm; // 0:PWR_ACTIVE, 1:PWR_SAVE
+ UCHAR MimoPs; // 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled
+ CHAR AvgRssi0;
+ CHAR AvgRssi1;
+ CHAR AvgRssi2;
+ UINT32 ConnectedTime;
+ MACHTTRANSMIT_SETTING TxRate;
+} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY;
+
+typedef struct _RT_802_11_MAC_TABLE {
+ ULONG Num;
+ RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC];
+} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE;
+
+// structure for query/set hardware register - MAC, BBP, RF register
+typedef struct _RT_802_11_HARDWARE_REGISTER {
+ ULONG HardwareType; // 0:MAC, 1:BBP, 2:RF register, 3:EEPROM
+ ULONG Offset; // Q/S register offset addr
+ ULONG Data; // R/W data buffer
+} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER;
+
+typedef struct _RT_802_11_AP_CONFIG {
+ ULONG EnableTxBurst; // 0-disable, 1-enable
+ ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate
+ ULONG IsolateInterStaTraffic; // 0-disable, 1-enable isolation
+ ULONG HideSsid; // 0-disable, 1-enable hiding
+ ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF
+ ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time
+ ULONG Rsv1; // must be 0
+ ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY
+} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG;
+
+// structure to query/set STA_CONFIG
+typedef struct _RT_802_11_STA_CONFIG {
+ ULONG EnableTxBurst; // 0-disable, 1-enable
+ ULONG EnableTurboRate; // 0-disable, 1-enable 72/100mbps turbo rate
+ ULONG UseBGProtection; // 0-AUTO, 1-always ON, 2-always OFF
+ ULONG UseShortSlotTime; // 0-no use, 1-use 9-us short slot time when applicable
+ ULONG AdhocMode; // 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only
+ ULONG HwRadioStatus; // 0-OFF, 1-ON, default is 1, Read-Only
+ ULONG Rsv1; // must be 0
+ ULONG SystemErrorBitmap; // ignore upon SET, return system error upon QUERY
+} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG;
+
+//
+// For OID Query or Set about BA structure
+//
+typedef struct _OID_BACAP_STRUC {
+ UCHAR RxBAWinLimit;
+ UCHAR TxBAWinLimit;
+ UCHAR Policy; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid
+ UCHAR MpduDensity; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid
+ UCHAR AmsduEnable; //Enable AMSDU transmisstion
+ UCHAR AmsduSize; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935};
+ UCHAR MMPSmode; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable
+ BOOLEAN AutoBA; // Auto BA will automatically
+} OID_BACAP_STRUC, *POID_BACAP_STRUC;
+
+typedef struct _RT_802_11_ACL_ENTRY {
+ UCHAR Addr[MAC_ADDR_LENGTH];
+ USHORT Rsv;
+} RT_802_11_ACL_ENTRY, *PRT_802_11_ACL_ENTRY;
+
+typedef struct PACKED _RT_802_11_ACL {
+ ULONG Policy; // 0-disable, 1-positive list, 2-negative list
+ ULONG Num;
+ RT_802_11_ACL_ENTRY Entry[MAX_NUMBER_OF_ACL];
+} RT_802_11_ACL, *PRT_802_11_ACL;
+
+typedef struct _RT_802_11_WDS {
+ ULONG Num;
+ NDIS_802_11_MAC_ADDRESS Entry[24/*MAX_NUM_OF_WDS_LINK*/];
+ ULONG KeyLength;
+ UCHAR KeyMaterial[32];
+} RT_802_11_WDS, *PRT_802_11_WDS;
+
+typedef struct _RT_802_11_TX_RATES_ {
+ UCHAR SupRateLen;
+ UCHAR SupRate[MAX_LENGTH_OF_SUPPORT_RATES];
+ UCHAR ExtRateLen;
+ UCHAR ExtRate[MAX_LENGTH_OF_SUPPORT_RATES];
+} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES;
+
+
+// Definition of extra information code
+#define GENERAL_LINK_UP 0x0 // Link is Up
+#define GENERAL_LINK_DOWN 0x1 // Link is Down
+#define HW_RADIO_OFF 0x2 // Hardware radio off
+#define SW_RADIO_OFF 0x3 // Software radio off
+#define AUTH_FAIL 0x4 // Open authentication fail
+#define AUTH_FAIL_KEYS 0x5 // Shared authentication fail
+#define ASSOC_FAIL 0x6 // Association failed
+#define EAP_MIC_FAILURE 0x7 // Deauthencation because MIC failure
+#define EAP_4WAY_TIMEOUT 0x8 // Deauthencation on 4-way handshake timeout
+#define EAP_GROUP_KEY_TIMEOUT 0x9 // Deauthencation on group key handshake timeout
+#define EAP_SUCCESS 0xa // EAP succeed
+#define DETECT_RADAR_SIGNAL 0xb // Radar signal occur in current channel
+#define EXTRA_INFO_MAX 0xb // Indicate Last OID
+
+#define EXTRA_INFO_CLEAR 0xffffffff
+
+// This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use.
+typedef struct {
+ RT_802_11_PHY_MODE PhyMode; //
+ UCHAR TransmitNo;
+ UCHAR HtMode; //HTMODE_GF or HTMODE_MM
+ UCHAR ExtOffset; //extension channel above or below
+ UCHAR MCS;
+ UCHAR BW;
+ UCHAR STBC;
+ UCHAR SHORTGI;
+ UCHAR rsv;
+} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE;
+
+#ifdef LLTD_SUPPORT
+typedef struct _RT_LLTD_ASSOICATION_ENTRY {
+ UCHAR Addr[ETH_LENGTH_OF_ADDRESS];
+ unsigned short MOR; // maximum operational rate
+ UCHAR phyMode;
+} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY;
+
+typedef struct _RT_LLTD_ASSOICATION_TABLE {
+ unsigned int Num;
+ RT_LLTD_ASSOICATION_ENTRY Entry[MAX_NUMBER_OF_MAC];
+} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE;
+#endif // LLTD_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+//rt2860, kathy 2007-0118
+// structure for DLS
+typedef struct _RT_802_11_DLS_UI {
+ USHORT TimeOut; // unit: second , set by UI
+ USHORT CountDownTimer; // unit: second , used by driver only
+ NDIS_802_11_MAC_ADDRESS MacAddr; // set by UI
+ UCHAR Status; // 0: none , 1: wait STAkey, 2: finish DLS setup , set by driver only
+ BOOLEAN Valid; // 1: valid , 0: invalid , set by UI, use to setup or tear down DLS link
+} RT_802_11_DLS_UI, *PRT_802_11_DLS_UI;
+
+typedef struct _RT_802_11_DLS_INFO {
+ RT_802_11_DLS_UI Entry[MAX_NUMBER_OF_DLS_ENTRY];
+ UCHAR num;
+} RT_802_11_DLS_INFO, *PRT_802_11_DLS_INFO;
+
+typedef enum _RT_802_11_DLS_MODE {
+ DLS_NONE,
+ DLS_WAIT_KEY,
+ DLS_FINISH
+} RT_802_11_DLS_MODE;
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+#define RT_ASSOC_EVENT_FLAG 0x0101
+#define RT_DISASSOC_EVENT_FLAG 0x0102
+#define RT_REQIE_EVENT_FLAG 0x0103
+#define RT_RESPIE_EVENT_FLAG 0x0104
+#define RT_ASSOCINFO_EVENT_FLAG 0x0105
+#define RT_PMKIDCAND_FLAG 0x0106
+#define RT_INTERFACE_DOWN 0x0107
+#define RT_INTERFACE_UP 0x0108
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+#define MAX_CUSTOM_LEN 128
+
+#ifdef CONFIG_STA_SUPPORT
+typedef enum _RT_802_11_D_CLIENT_MODE
+{
+ Rt802_11_D_None,
+ Rt802_11_D_Flexible,
+ Rt802_11_D_Strict,
+} RT_802_11_D_CLIENT_MODE, *PRT_802_11_D_CLIENT_MODE;
+#endif // CONFIG_STA_SUPPORT //
+
+typedef struct _RT_CHANNEL_LIST_INFO
+{
+ UCHAR ChannelList[MAX_NUM_OF_CHS]; // list all supported channels for site survey
+ UCHAR ChannelListNum; // number of channel in ChannelList[]
+} RT_CHANNEL_LIST_INFO, *PRT_CHANNEL_LIST_INFO;
+
+
+#endif // _OID_H_
+
diff --git a/drivers/staging/rt2860/rt2860.h b/drivers/staging/rt2860/rt2860.h
new file mode 100644
index 000000000000..017201906628
--- /dev/null
+++ b/drivers/staging/rt2860/rt2860.h
@@ -0,0 +1,349 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#ifndef __RT2860_H__
+#define __RT2860_H__
+
+#define RT28xx_CHIP_NAME "RT2860"
+
+#define TXINFO_SIZE 0
+#define TXPADDING_SIZE 0
+
+/* ----------------- EEPROM Related MACRO ----------------- */
+#define RT28xx_EEPROM_READ16(pAd, offset, var) \
+ var = RTMP_EEPROM_READ16(pAd, offset)
+
+#define RT28xx_EEPROM_WRITE16(pAd, offset, var) \
+ RTMP_EEPROM_WRITE16(pAd, offset, var)
+
+/* ----------------- TASK/THREAD Related MACRO ----------------- */
+#define RT28XX_TASK_THREAD_INIT(pAd, Status) \
+ init_thread_task(pAd); NICInitTxRxRingAndBacklogQueue(pAd); \
+ Status = NDIS_STATUS_SUCCESS;
+
+/* function declarations */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define IRQ_HANDLE_TYPE irqreturn_t
+#else
+#define IRQ_HANDLE_TYPE void
+#endif
+
+IRQ_HANDLE_TYPE
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19))
+rt2860_interrupt(int irq, void *dev_instance);
+#else
+rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+#endif
+
+/* ----------------- Frimware Related MACRO ----------------- */
+#define RT28XX_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \
+ do{ \
+ ULONG _i, _firm; \
+ RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x10000); \
+ \
+ for(_i=0; _i<_FwLen; _i+=4) \
+ { \
+ _firm = _pFwImage[_i] + \
+ (_pFwImage[_i+3] << 24) + \
+ (_pFwImage[_i+2] << 16) + \
+ (_pFwImage[_i+1] << 8); \
+ RTMP_IO_WRITE32(_pAd, FIRMWARE_IMAGE_BASE + _i, _firm); \
+ } \
+ RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00000); \
+ RTMP_IO_WRITE32(_pAd, PBF_SYS_CTRL, 0x00001); \
+ \
+ /* initialize BBP R/W access agent */ \
+ RTMP_IO_WRITE32(_pAd, H2M_BBP_AGENT, 0); \
+ RTMP_IO_WRITE32(_pAd, H2M_MAILBOX_CSR, 0); \
+ }while(0)
+
+/* ----------------- TX Related MACRO ----------------- */
+#define RT28XX_START_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0)
+#define RT28XX_STOP_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0)
+
+
+#define RT28XX_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \
+ ((freeNum) >= (ULONG)(pTxBlk->TotalFragNum + RTMP_GET_PACKET_FRAGMENTS(pPacket) + 3)) /* rough estimate we will use 3 more descriptor. */
+#define RT28XX_RELEASE_DESC_RESOURCE(pAd, QueIdx) \
+ do{}while(0)
+
+#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \
+ (((freeNum != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 0)) || (freeNum<3))
+ //(((freeNum) != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 1 /*0*/))
+
+
+#define HAL_KickOutMgmtTx(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) \
+ RtmpPCIMgmtKickOut(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen)
+
+#define RTMP_PKT_TAIL_PADDING 0
+
+#define fRTMP_ADAPTER_NEED_STOP_TX 0
+
+#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \
+ /* RtmpPCI_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)*/
+
+#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \
+ RtmpPCI_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)
+
+#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \
+ RtmpPCI_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber)
+
+#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \
+ RtmpPCI_WriteMultiTxResource(pAd, pTxBlk, frameNum, pFreeNumber)
+
+#define HAL_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) \
+ RtmpPCI_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx)
+
+#define HAL_LastTxIdx(_pAd, _QueIdx,_LastTxIdx) \
+ /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx)*/
+
+#define HAL_KickOutTx(_pAd, _pTxBlk, _QueIdx) \
+ RTMP_IO_WRITE32((_pAd), TX_CTX_IDX0+((_QueIdx)*0x10), (_pAd)->TxRing[(_QueIdx)].TxCpuIdx)
+/* RtmpPCIDataKickOut(_pAd, _pTxBlk, _QueIdx)*/
+
+#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \
+ MiniportMMRequest(_pAd, _QueIdx, _pNullFrame, _frameLen)
+
+#define GET_TXRING_FREENO(_pAd, _QueIdx) \
+ (_pAd->TxRing[_QueIdx].TxSwFreeIdx > _pAd->TxRing[_QueIdx].TxCpuIdx) ? \
+ (_pAd->TxRing[_QueIdx].TxSwFreeIdx - _pAd->TxRing[_QueIdx].TxCpuIdx - 1) \
+ : \
+ (_pAd->TxRing[_QueIdx].TxSwFreeIdx + TX_RING_SIZE - _pAd->TxRing[_QueIdx].TxCpuIdx - 1);
+
+
+#define GET_MGMTRING_FREENO(_pAd) \
+ (_pAd->MgmtRing.TxSwFreeIdx > _pAd->MgmtRing.TxCpuIdx) ? \
+ (_pAd->MgmtRing.TxSwFreeIdx - _pAd->MgmtRing.TxCpuIdx - 1) \
+ : \
+ (_pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->MgmtRing.TxCpuIdx - 1);
+
+
+/* ----------------- RX Related MACRO ----------------- */
+
+// no use
+#define RT28XX_RCV_PKT_GET_INIT(pAd)
+#define RT28XX_RV_A_BUF_END
+//#define RT28XX_RV_ALL_BUF_END
+
+
+/* ----------------- ASIC Related MACRO ----------------- */
+// no use
+#define RT28XX_DMA_POST_WRITE(pAd)
+
+// reset MAC of a station entry to 0x000000000000
+#define RT28XX_STA_ENTRY_MAC_RESET(pAd, Wcid) \
+ AsicDelWcidTab(pAd, Wcid);
+
+// add this entry into ASIC RX WCID search table
+#define RT28XX_STA_ENTRY_ADD(pAd, pEntry) \
+ AsicUpdateRxWCIDTable(pAd, pEntry->Aid, pEntry->Addr);
+
+// remove Pair-wise key material from ASIC
+#define RT28XX_STA_ENTRY_KEY_DEL(pAd, BssIdx, Wcid) \
+ AsicRemovePairwiseKeyEntry(pAd, BssIdx, (UCHAR)Wcid);
+
+// add Client security information into ASIC WCID table and IVEIV table
+#define RT28XX_STA_SECURITY_INFO_ADD(pAd, apidx, KeyID, pEntry) \
+ RTMPAddWcidAttributeEntry(pAd, apidx, KeyID, \
+ pAd->SharedKey[apidx][KeyID].CipherAlg, pEntry);
+
+#define RT28XX_SECURITY_KEY_ADD(pAd, apidx, KeyID, pEntry) \
+ { /* update pairwise key information to ASIC Shared Key Table */ \
+ AsicAddSharedKeyEntry(pAd, apidx, KeyID, \
+ pAd->SharedKey[apidx][KeyID].CipherAlg, \
+ pAd->SharedKey[apidx][KeyID].Key, \
+ pAd->SharedKey[apidx][KeyID].TxMic, \
+ pAd->SharedKey[apidx][KeyID].RxMic); \
+ /* update ASIC WCID attribute table and IVEIV table */ \
+ RTMPAddWcidAttributeEntry(pAd, apidx, KeyID, \
+ pAd->SharedKey[apidx][KeyID].CipherAlg, \
+ pEntry); }
+
+
+// Insert the BA bitmap to ASIC for the Wcid entry
+#define RT28XX_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID) \
+ do{ \
+ UINT32 _Value = 0, _Offset; \
+ _Offset = MAC_WCID_BASE + (_Aid) * HW_WCID_ENTRY_SIZE + 4; \
+ RTMP_IO_READ32((_pAd), _Offset, &_Value); \
+ _Value |= (0x10000<<(_TID)); \
+ RTMP_IO_WRITE32((_pAd), _Offset, _Value); \
+ }while(0)
+
+
+// Remove the BA bitmap from ASIC for the Wcid entry
+// bitmap field starts at 0x10000 in ASIC WCID table
+#define RT28XX_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID) \
+ do{ \
+ UINT32 _Value = 0, _Offset; \
+ _Offset = MAC_WCID_BASE + (_Wcid) * HW_WCID_ENTRY_SIZE + 4; \
+ RTMP_IO_READ32((_pAd), _Offset, &_Value); \
+ _Value &= (~(0x10000 << (_TID))); \
+ RTMP_IO_WRITE32((_pAd), _Offset, _Value); \
+ }while(0)
+
+
+/* ----------------- PCI/USB Related MACRO ----------------- */
+
+#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \
+ ((POS_COOKIE)handle)->pci_dev = dev_p;
+
+// set driver data
+#define RT28XX_DRVDATA_SET(_a) pci_set_drvdata(_a, net_dev);
+
+#define RT28XX_UNMAP() \
+{ if (net_dev->base_addr) { \
+ iounmap((void *)(net_dev->base_addr)); \
+ release_mem_region(pci_resource_start(dev_p, 0), \
+ pci_resource_len(dev_p, 0)); } \
+ if (net_dev->irq) pci_release_regions(dev_p); }
+
+#ifdef PCI_MSI_SUPPORT
+#define RTMP_MSI_ENABLE(_pAd) \
+{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \
+ (_pAd)->HaveMsi = pci_enable_msi(_pObj->pci_dev) == 0 ? TRUE : FALSE; }
+
+#define RTMP_MSI_DISABLE(_pAd) \
+{ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \
+ if (_pAd->HaveMsi == TRUE) \
+ pci_disable_msi(_pObj->pci_dev); \
+ _pAd->HaveMsi = FALSE; }
+#else
+#define RTMP_MSI_ENABLE(_pAd)
+#define RTMP_MSI_DISABLE(_pAd)
+#endif // PCI_MSI_SUPPORT //
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#define SA_SHIRQ IRQF_SHARED
+#endif
+
+#define RT28XX_IRQ_REQUEST(net_dev) \
+{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->ml_priv); \
+ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \
+ RTMP_MSI_ENABLE(_pAd); \
+ if ((retval = request_irq(_pObj->pci_dev->irq, \
+ rt2860_interrupt, SA_SHIRQ, \
+ (net_dev)->name, (net_dev)))) { \
+ printk("RT2860: request_irq ERROR(%d)\n", retval); \
+ return retval; } }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define RT28XX_IRQ_RELEASE(net_dev) \
+{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->ml_priv); \
+ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \
+ synchronize_irq(_pObj->pci_dev->irq); \
+ free_irq(_pObj->pci_dev->irq, (net_dev)); \
+ RTMP_MSI_DISABLE(_pAd); }
+#else
+#define RT28XX_IRQ_RELEASE(net_dev) \
+{ PRTMP_ADAPTER _pAd = (PRTMP_ADAPTER)((net_dev)->priv); \
+ POS_COOKIE _pObj = (POS_COOKIE)(_pAd->OS_Cookie); \
+ free_irq(_pObj->pci_dev->irq, (net_dev)); \
+ RTMP_MSI_DISABLE(_pAd); }
+#endif
+
+#define RT28XX_IRQ_INIT(pAd) \
+ { pAd->int_enable_reg = ((DELAYINTMASK) | \
+ (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03); \
+ pAd->int_disable_mask = 0; \
+ pAd->int_pending = 0; }
+
+#define RT28XX_IRQ_ENABLE(pAd) \
+ { /* clear garbage ints */ \
+ RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); \
+ NICEnableInterrupt(pAd); }
+
+#define RT28XX_PUT_DEVICE(dev_p)
+
+
+/* ----------------- MLME Related MACRO ----------------- */
+#define RT28XX_MLME_HANDLER(pAd) MlmeHandler(pAd)
+
+#define RT28XX_MLME_PRE_SANITY_CHECK(pAd)
+
+#define RT28XX_MLME_STA_QUICK_RSP_WAKE_UP(pAd) \
+ RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
+
+#define RT28XX_MLME_RESET_STATE_MACHINE(pAd) \
+ MlmeRestartStateMachine(pAd)
+
+#define RT28XX_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \
+ HandleCounterMeasure(_pAd, _pEntry)
+
+/* ----------------- Power Save Related MACRO ----------------- */
+#define RT28XX_PS_POLL_ENQUEUE(pAd) EnqueuePsPoll(pAd)
+
+//
+// Device ID & Vendor ID, these values should match EEPROM value
+//
+#define NIC2860_PCI_DEVICE_ID 0x0601
+#define NIC2860_PCIe_DEVICE_ID 0x0681
+#define NIC2760_PCI_DEVICE_ID 0x0701 // 1T/2R Cardbus ???
+#define NIC2790_PCIe_DEVICE_ID 0x0781 // 1T/2R miniCard
+
+#define NIC_PCI_VENDOR_ID 0x1814
+
+#define VEN_AWT_PCIe_DEVICE_ID 0x1059
+#define VEN_AWT_PCI_VENDOR_ID 0x1A3B
+
+// For RTMPPCIePowerLinkCtrlRestore () function
+#define RESTORE_HALT 1
+#define RESTORE_WAKEUP 2
+#define RESTORE_CLOSE 3
+
+#define PowerSafeCID 1
+#define PowerRadioOffCID 2
+#define PowerWakeCID 3
+#define CID0MASK 0x000000ff
+#define CID1MASK 0x0000ff00
+#define CID2MASK 0x00ff0000
+#define CID3MASK 0xff000000
+
+#define PCI_REG_READ_WORD(pci_dev, offset, Configuration) \
+ if (pci_read_config_word(pci_dev, offset, &reg16) == 0) \
+ Configuration = le2cpu16(reg16); \
+ else \
+ Configuration = 0;
+
+#define PCI_REG_WIRTE_WORD(pci_dev, offset, Configuration) \
+ reg16 = cpu2le16(Configuration); \
+ pci_write_config_word(pci_dev, offset, reg16); \
+
+#define RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx) \
+ RT28xxPciStaAsicForceWakeup(pAd, bFromTx);
+
+#define RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp) \
+ RT28xxPciStaAsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
+
+#define RT28XX_MLME_RADIO_ON(pAd) \
+ RT28xxPciMlmeRadioOn(pAd);
+
+#define RT28XX_MLME_RADIO_OFF(pAd) \
+ RT28xxPciMlmeRadioOFF(pAd);
+
+#endif //__RT2860_H__
+
diff --git a/drivers/staging/rt2860/rt28xx.h b/drivers/staging/rt2860/rt28xx.h
new file mode 100644
index 000000000000..ff23043e560e
--- /dev/null
+++ b/drivers/staging/rt2860/rt28xx.h
@@ -0,0 +1,2714 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rt28xx.h
+
+ Abstract:
+ RT28xx ASIC related definition & structures
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Jan Lee Jan-3-2006 created for RT2860c
+*/
+
+#ifndef __RT28XX_H__
+#define __RT28XX_H__
+
+
+//
+// PCI registers - base address 0x0000
+//
+#define PCI_CFG 0x0000
+#define PCI_EECTRL 0x0004
+#define PCI_MCUCTRL 0x0008
+
+//
+// SCH/DMA registers - base address 0x0200
+//
+// INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit
+//
+#define DMA_CSR0 0x200
+#define INT_SOURCE_CSR 0x200
+#ifdef RT_BIG_ENDIAN
+typedef union _INT_SOURCE_CSR_STRUC {
+ struct {
+ UINT32 :14;
+ UINT32 TxCoherent:1;
+ UINT32 RxCoherent:1;
+ UINT32 GPTimer:1;
+ UINT32 AutoWakeup:1;//bit14
+ UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c
+ UINT32 PreTBTT:1;
+ UINT32 TBTTInt:1;
+ UINT32 RxTxCoherent:1;
+ UINT32 MCUCommandINT:1;
+ UINT32 MgmtDmaDone:1;
+ UINT32 HccaDmaDone:1;
+ UINT32 Ac3DmaDone:1;
+ UINT32 Ac2DmaDone:1;
+ UINT32 Ac1DmaDone:1;
+ UINT32 Ac0DmaDone:1;
+ UINT32 RxDone:1;
+ UINT32 TxDelayINT:1; //delayed interrupt, not interrupt until several int or time limit hit
+ UINT32 RxDelayINT:1; //dealyed interrupt
+ } field;
+ UINT32 word;
+} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC;
+#else
+typedef union _INT_SOURCE_CSR_STRUC {
+ struct {
+ UINT32 RxDelayINT:1;
+ UINT32 TxDelayINT:1;
+ UINT32 RxDone:1;
+ UINT32 Ac0DmaDone:1;//4
+ UINT32 Ac1DmaDone:1;
+ UINT32 Ac2DmaDone:1;
+ UINT32 Ac3DmaDone:1;
+ UINT32 HccaDmaDone:1; // bit7
+ UINT32 MgmtDmaDone:1;
+ UINT32 MCUCommandINT:1;//bit 9
+ UINT32 RxTxCoherent:1;
+ UINT32 TBTTInt:1;
+ UINT32 PreTBTT:1;
+ UINT32 TXFifoStatusInt:1;//FIFO Statistics is full, sw should read 0x171c
+ UINT32 AutoWakeup:1;//bit14
+ UINT32 GPTimer:1;
+ UINT32 RxCoherent:1;//bit16
+ UINT32 TxCoherent:1;
+ UINT32 :14;
+ } field;
+ UINT32 word;
+} INT_SOURCE_CSR_STRUC, *PINT_SOURCE_CSR_STRUC;
+#endif
+
+//
+// INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF
+//
+#define INT_MASK_CSR 0x204
+#ifdef RT_BIG_ENDIAN
+typedef union _INT_MASK_CSR_STRUC {
+ struct {
+ UINT32 TxCoherent:1;
+ UINT32 RxCoherent:1;
+ UINT32 :20;
+ UINT32 MCUCommandINT:1;
+ UINT32 MgmtDmaDone:1;
+ UINT32 HccaDmaDone:1;
+ UINT32 Ac3DmaDone:1;
+ UINT32 Ac2DmaDone:1;
+ UINT32 Ac1DmaDone:1;
+ UINT32 Ac0DmaDone:1;
+ UINT32 RxDone:1;
+ UINT32 TxDelay:1;
+ UINT32 RXDelay_INT_MSK:1;
+ } field;
+ UINT32 word;
+}INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC;
+#else
+typedef union _INT_MASK_CSR_STRUC {
+ struct {
+ UINT32 RXDelay_INT_MSK:1;
+ UINT32 TxDelay:1;
+ UINT32 RxDone:1;
+ UINT32 Ac0DmaDone:1;
+ UINT32 Ac1DmaDone:1;
+ UINT32 Ac2DmaDone:1;
+ UINT32 Ac3DmaDone:1;
+ UINT32 HccaDmaDone:1;
+ UINT32 MgmtDmaDone:1;
+ UINT32 MCUCommandINT:1;
+ UINT32 :20;
+ UINT32 RxCoherent:1;
+ UINT32 TxCoherent:1;
+ } field;
+ UINT32 word;
+} INT_MASK_CSR_STRUC, *PINT_MASK_CSR_STRUC;
+#endif
+#define WPDMA_GLO_CFG 0x208
+#ifdef RT_BIG_ENDIAN
+typedef union _WPDMA_GLO_CFG_STRUC {
+ struct {
+ UINT32 HDR_SEG_LEN:16;
+ UINT32 RXHdrScater:8;
+ UINT32 BigEndian:1;
+ UINT32 EnTXWriteBackDDONE:1;
+ UINT32 WPDMABurstSIZE:2;
+ UINT32 RxDMABusy:1;
+ UINT32 EnableRxDMA:1;
+ UINT32 TxDMABusy:1;
+ UINT32 EnableTxDMA:1;
+ } field;
+ UINT32 word;
+}WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC;
+#else
+typedef union _WPDMA_GLO_CFG_STRUC {
+ struct {
+ UINT32 EnableTxDMA:1;
+ UINT32 TxDMABusy:1;
+ UINT32 EnableRxDMA:1;
+ UINT32 RxDMABusy:1;
+ UINT32 WPDMABurstSIZE:2;
+ UINT32 EnTXWriteBackDDONE:1;
+ UINT32 BigEndian:1;
+ UINT32 RXHdrScater:8;
+ UINT32 HDR_SEG_LEN:16;
+ } field;
+ UINT32 word;
+} WPDMA_GLO_CFG_STRUC, *PWPDMA_GLO_CFG_STRUC;
+#endif
+#define WPDMA_RST_IDX 0x20c
+#ifdef RT_BIG_ENDIAN
+typedef union _WPDMA_RST_IDX_STRUC {
+ struct {
+ UINT32 :15;
+ UINT32 RST_DRX_IDX0:1;
+ UINT32 rsv:10;
+ UINT32 RST_DTX_IDX5:1;
+ UINT32 RST_DTX_IDX4:1;
+ UINT32 RST_DTX_IDX3:1;
+ UINT32 RST_DTX_IDX2:1;
+ UINT32 RST_DTX_IDX1:1;
+ UINT32 RST_DTX_IDX0:1;
+ } field;
+ UINT32 word;
+}WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC;
+#else
+typedef union _WPDMA_RST_IDX_STRUC {
+ struct {
+ UINT32 RST_DTX_IDX0:1;
+ UINT32 RST_DTX_IDX1:1;
+ UINT32 RST_DTX_IDX2:1;
+ UINT32 RST_DTX_IDX3:1;
+ UINT32 RST_DTX_IDX4:1;
+ UINT32 RST_DTX_IDX5:1;
+ UINT32 rsv:10;
+ UINT32 RST_DRX_IDX0:1;
+ UINT32 :15;
+ } field;
+ UINT32 word;
+} WPDMA_RST_IDX_STRUC, *PWPDMA_RST_IDX_STRUC;
+#endif
+#define DELAY_INT_CFG 0x0210
+#ifdef RT_BIG_ENDIAN
+typedef union _DELAY_INT_CFG_STRUC {
+ struct {
+ UINT32 TXDLY_INT_EN:1;
+ UINT32 TXMAX_PINT:7;
+ UINT32 TXMAX_PTIME:8;
+ UINT32 RXDLY_INT_EN:1;
+ UINT32 RXMAX_PINT:7;
+ UINT32 RXMAX_PTIME:8;
+ } field;
+ UINT32 word;
+}DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC;
+#else
+typedef union _DELAY_INT_CFG_STRUC {
+ struct {
+ UINT32 RXMAX_PTIME:8;
+ UINT32 RXMAX_PINT:7;
+ UINT32 RXDLY_INT_EN:1;
+ UINT32 TXMAX_PTIME:8;
+ UINT32 TXMAX_PINT:7;
+ UINT32 TXDLY_INT_EN:1;
+ } field;
+ UINT32 word;
+} DELAY_INT_CFG_STRUC, *PDELAY_INT_CFG_STRUC;
+#endif
+#define WMM_AIFSN_CFG 0x0214
+#ifdef RT_BIG_ENDIAN
+typedef union _AIFSN_CSR_STRUC {
+ struct {
+ UINT32 Rsv:16;
+ UINT32 Aifsn3:4; // for AC_VO
+ UINT32 Aifsn2:4; // for AC_VI
+ UINT32 Aifsn1:4; // for AC_BK
+ UINT32 Aifsn0:4; // for AC_BE
+ } field;
+ UINT32 word;
+} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC;
+#else
+typedef union _AIFSN_CSR_STRUC {
+ struct {
+ UINT32 Aifsn0:4; // for AC_BE
+ UINT32 Aifsn1:4; // for AC_BK
+ UINT32 Aifsn2:4; // for AC_VI
+ UINT32 Aifsn3:4; // for AC_VO
+ UINT32 Rsv:16;
+ } field;
+ UINT32 word;
+} AIFSN_CSR_STRUC, *PAIFSN_CSR_STRUC;
+#endif
+//
+// CWMIN_CSR: CWmin for each EDCA AC
+//
+#define WMM_CWMIN_CFG 0x0218
+#ifdef RT_BIG_ENDIAN
+typedef union _CWMIN_CSR_STRUC {
+ struct {
+ UINT32 Rsv:16;
+ UINT32 Cwmin3:4; // for AC_VO
+ UINT32 Cwmin2:4; // for AC_VI
+ UINT32 Cwmin1:4; // for AC_BK
+ UINT32 Cwmin0:4; // for AC_BE
+ } field;
+ UINT32 word;
+} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC;
+#else
+typedef union _CWMIN_CSR_STRUC {
+ struct {
+ UINT32 Cwmin0:4; // for AC_BE
+ UINT32 Cwmin1:4; // for AC_BK
+ UINT32 Cwmin2:4; // for AC_VI
+ UINT32 Cwmin3:4; // for AC_VO
+ UINT32 Rsv:16;
+ } field;
+ UINT32 word;
+} CWMIN_CSR_STRUC, *PCWMIN_CSR_STRUC;
+#endif
+
+//
+// CWMAX_CSR: CWmin for each EDCA AC
+//
+#define WMM_CWMAX_CFG 0x021c
+#ifdef RT_BIG_ENDIAN
+typedef union _CWMAX_CSR_STRUC {
+ struct {
+ UINT32 Rsv:16;
+ UINT32 Cwmax3:4; // for AC_VO
+ UINT32 Cwmax2:4; // for AC_VI
+ UINT32 Cwmax1:4; // for AC_BK
+ UINT32 Cwmax0:4; // for AC_BE
+ } field;
+ UINT32 word;
+} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC;
+#else
+typedef union _CWMAX_CSR_STRUC {
+ struct {
+ UINT32 Cwmax0:4; // for AC_BE
+ UINT32 Cwmax1:4; // for AC_BK
+ UINT32 Cwmax2:4; // for AC_VI
+ UINT32 Cwmax3:4; // for AC_VO
+ UINT32 Rsv:16;
+ } field;
+ UINT32 word;
+} CWMAX_CSR_STRUC, *PCWMAX_CSR_STRUC;
+#endif
+
+
+//
+// AC_TXOP_CSR0: AC_BK/AC_BE TXOP register
+//
+#define WMM_TXOP0_CFG 0x0220
+#ifdef RT_BIG_ENDIAN
+typedef union _AC_TXOP_CSR0_STRUC {
+ struct {
+ USHORT Ac1Txop; // for AC_BE, in unit of 32us
+ USHORT Ac0Txop; // for AC_BK, in unit of 32us
+ } field;
+ UINT32 word;
+} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC;
+#else
+typedef union _AC_TXOP_CSR0_STRUC {
+ struct {
+ USHORT Ac0Txop; // for AC_BK, in unit of 32us
+ USHORT Ac1Txop; // for AC_BE, in unit of 32us
+ } field;
+ UINT32 word;
+} AC_TXOP_CSR0_STRUC, *PAC_TXOP_CSR0_STRUC;
+#endif
+
+//
+// AC_TXOP_CSR1: AC_VO/AC_VI TXOP register
+//
+#define WMM_TXOP1_CFG 0x0224
+#ifdef RT_BIG_ENDIAN
+typedef union _AC_TXOP_CSR1_STRUC {
+ struct {
+ USHORT Ac3Txop; // for AC_VO, in unit of 32us
+ USHORT Ac2Txop; // for AC_VI, in unit of 32us
+ } field;
+ UINT32 word;
+} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC;
+#else
+typedef union _AC_TXOP_CSR1_STRUC {
+ struct {
+ USHORT Ac2Txop; // for AC_VI, in unit of 32us
+ USHORT Ac3Txop; // for AC_VO, in unit of 32us
+ } field;
+ UINT32 word;
+} AC_TXOP_CSR1_STRUC, *PAC_TXOP_CSR1_STRUC;
+#endif
+#define RINGREG_DIFF 0x10
+#define GPIO_CTRL_CFG 0x0228 //MAC_CSR13
+#define MCU_CMD_CFG 0x022c
+#define TX_BASE_PTR0 0x0230 //AC_BK base address
+#define TX_MAX_CNT0 0x0234
+#define TX_CTX_IDX0 0x0238
+#define TX_DTX_IDX0 0x023c
+#define TX_BASE_PTR1 0x0240 //AC_BE base address
+#define TX_MAX_CNT1 0x0244
+#define TX_CTX_IDX1 0x0248
+#define TX_DTX_IDX1 0x024c
+#define TX_BASE_PTR2 0x0250 //AC_VI base address
+#define TX_MAX_CNT2 0x0254
+#define TX_CTX_IDX2 0x0258
+#define TX_DTX_IDX2 0x025c
+#define TX_BASE_PTR3 0x0260 //AC_VO base address
+#define TX_MAX_CNT3 0x0264
+#define TX_CTX_IDX3 0x0268
+#define TX_DTX_IDX3 0x026c
+#define TX_BASE_PTR4 0x0270 //HCCA base address
+#define TX_MAX_CNT4 0x0274
+#define TX_CTX_IDX4 0x0278
+#define TX_DTX_IDX4 0x027c
+#define TX_BASE_PTR5 0x0280 //MGMT base address
+#define TX_MAX_CNT5 0x0284
+#define TX_CTX_IDX5 0x0288
+#define TX_DTX_IDX5 0x028c
+#define TX_MGMTMAX_CNT TX_MAX_CNT5
+#define TX_MGMTCTX_IDX TX_CTX_IDX5
+#define TX_MGMTDTX_IDX TX_DTX_IDX5
+#define RX_BASE_PTR 0x0290 //RX base address
+#define RX_MAX_CNT 0x0294
+#define RX_CRX_IDX 0x0298
+#define RX_DRX_IDX 0x029c
+#define USB_DMA_CFG 0x02a0
+#ifdef RT_BIG_ENDIAN
+typedef union _USB_DMA_CFG_STRUC {
+ struct {
+ UINT32 TxBusy:1; //USB DMA TX FSM busy . debug only
+ UINT32 RxBusy:1; //USB DMA RX FSM busy . debug only
+ UINT32 EpoutValid:6; //OUT endpoint data valid. debug only
+ UINT32 TxBulkEn:1; //Enable USB DMA Tx
+ UINT32 RxBulkEn:1; //Enable USB DMA Rx
+ UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation
+ UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full.
+ UINT32 TxClear:1; //Clear USB DMA TX path
+ UINT32 rsv:2;
+ UINT32 phyclear:1; //phy watch dog enable. write 1
+ UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 1024 bytes
+ UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns
+ } field;
+ UINT32 word;
+} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC;
+#else
+typedef union _USB_DMA_CFG_STRUC {
+ struct {
+ UINT32 RxBulkAggTOut:8; //Rx Bulk Aggregation TimeOut in unit of 33ns
+ UINT32 RxBulkAggLmt:8; //Rx Bulk Aggregation Limit in unit of 256 bytes
+ UINT32 phyclear:1; //phy watch dog enable. write 1
+ UINT32 rsv:2;
+ UINT32 TxClear:1; //Clear USB DMA TX path
+ UINT32 TxopHalt:1; //Halt TXOP count down when TX buffer is full.
+ UINT32 RxBulkAggEn:1; //Enable Rx Bulk Aggregation
+ UINT32 RxBulkEn:1; //Enable USB DMA Rx
+ UINT32 TxBulkEn:1; //Enable USB DMA Tx
+ UINT32 EpoutValid:6; //OUT endpoint data valid
+ UINT32 RxBusy:1; //USB DMA RX FSM busy
+ UINT32 TxBusy:1; //USB DMA TX FSM busy
+ } field;
+ UINT32 word;
+} USB_DMA_CFG_STRUC, *PUSB_DMA_CFG_STRUC;
+#endif
+
+//
+// 3 PBF registers
+//
+//
+// Most are for debug. Driver doesn't touch PBF register.
+#define PBF_SYS_CTRL 0x0400
+#define PBF_CFG 0x0408
+#define PBF_MAX_PCNT 0x040C
+#define PBF_CTRL 0x0410
+#define PBF_INT_STA 0x0414
+#define PBF_INT_ENA 0x0418
+#define TXRXQ_PCNT 0x0438
+#define PBF_DBG 0x043c
+#define PBF_CAP_CTRL 0x0440
+
+//
+// 4 MAC registers
+//
+//
+// 4.1 MAC SYSTEM configuration registers (offset:0x1000)
+//
+#define MAC_CSR0 0x1000
+#ifdef RT_BIG_ENDIAN
+typedef union _ASIC_VER_ID_STRUC {
+ struct {
+ USHORT ASICVer; // version : 2860
+ USHORT ASICRev; // reversion : 0
+ } field;
+ UINT32 word;
+} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC;
+#else
+typedef union _ASIC_VER_ID_STRUC {
+ struct {
+ USHORT ASICRev; // reversion : 0
+ USHORT ASICVer; // version : 2860
+ } field;
+ UINT32 word;
+} ASIC_VER_ID_STRUC, *PASIC_VER_ID_STRUC;
+#endif
+#define MAC_SYS_CTRL 0x1004 //MAC_CSR1
+#define MAC_ADDR_DW0 0x1008 // MAC ADDR DW0
+#define MAC_ADDR_DW1 0x100c // MAC ADDR DW1
+//
+// MAC_CSR2: STA MAC register 0
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _MAC_DW0_STRUC {
+ struct {
+ UCHAR Byte3; // MAC address byte 3
+ UCHAR Byte2; // MAC address byte 2
+ UCHAR Byte1; // MAC address byte 1
+ UCHAR Byte0; // MAC address byte 0
+ } field;
+ UINT32 word;
+} MAC_DW0_STRUC, *PMAC_DW0_STRUC;
+#else
+typedef union _MAC_DW0_STRUC {
+ struct {
+ UCHAR Byte0; // MAC address byte 0
+ UCHAR Byte1; // MAC address byte 1
+ UCHAR Byte2; // MAC address byte 2
+ UCHAR Byte3; // MAC address byte 3
+ } field;
+ UINT32 word;
+} MAC_DW0_STRUC, *PMAC_DW0_STRUC;
+#endif
+
+//
+// MAC_CSR3: STA MAC register 1
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _MAC_DW1_STRUC {
+ struct {
+ UCHAR Rsvd1;
+ UCHAR U2MeMask;
+ UCHAR Byte5; // MAC address byte 5
+ UCHAR Byte4; // MAC address byte 4
+ } field;
+ UINT32 word;
+} MAC_DW1_STRUC, *PMAC_DW1_STRUC;
+#else
+typedef union _MAC_DW1_STRUC {
+ struct {
+ UCHAR Byte4; // MAC address byte 4
+ UCHAR Byte5; // MAC address byte 5
+ UCHAR U2MeMask;
+ UCHAR Rsvd1;
+ } field;
+ UINT32 word;
+} MAC_DW1_STRUC, *PMAC_DW1_STRUC;
+#endif
+
+#define MAC_BSSID_DW0 0x1010 // MAC BSSID DW0
+#define MAC_BSSID_DW1 0x1014 // MAC BSSID DW1
+
+//
+// MAC_CSR5: BSSID register 1
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _MAC_CSR5_STRUC {
+ struct {
+ USHORT Rsvd:11;
+ USHORT MBssBcnNum:3;
+ USHORT BssIdMode:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID
+ UCHAR Byte5; // BSSID byte 5
+ UCHAR Byte4; // BSSID byte 4
+ } field;
+ UINT32 word;
+} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC;
+#else
+typedef union _MAC_CSR5_STRUC {
+ struct {
+ UCHAR Byte4; // BSSID byte 4
+ UCHAR Byte5; // BSSID byte 5
+ USHORT BssIdMask:2; // 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID
+ USHORT MBssBcnNum:3;
+ USHORT Rsvd:11;
+ } field;
+ UINT32 word;
+} MAC_CSR5_STRUC, *PMAC_CSR5_STRUC;
+#endif
+
+#define MAX_LEN_CFG 0x1018 // rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
+#define BBP_CSR_CFG 0x101c //
+//
+// BBP_CSR_CFG: BBP serial control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _BBP_CSR_CFG_STRUC {
+ struct {
+ UINT32 :12;
+ UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel
+ UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles
+ UINT32 Busy:1; // 1: ASIC is busy execute BBP programming.
+ UINT32 fRead:1; // 0: Write BBP, 1: Read BBP
+ UINT32 RegNum:8; // Selected BBP register
+ UINT32 Value:8; // Register value to program into BBP
+ } field;
+ UINT32 word;
+} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC;
+#else
+typedef union _BBP_CSR_CFG_STRUC {
+ struct {
+ UINT32 Value:8; // Register value to program into BBP
+ UINT32 RegNum:8; // Selected BBP register
+ UINT32 fRead:1; // 0: Write BBP, 1: Read BBP
+ UINT32 Busy:1; // 1: ASIC is busy execute BBP programming.
+ UINT32 BBP_PAR_DUR:1; // 0: 4 MAC clock cycles 1: 8 MAC clock cycles
+ UINT32 BBP_RW_MODE:1; // 0: use serial mode 1:parallel
+ UINT32 :12;
+ } field;
+ UINT32 word;
+} BBP_CSR_CFG_STRUC, *PBBP_CSR_CFG_STRUC;
+#endif
+#define RF_CSR_CFG0 0x1020
+//
+// RF_CSR_CFG: RF control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _RF_CSR_CFG0_STRUC {
+ struct {
+ UINT32 Busy:1; // 0: idle 1: 8busy
+ UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate
+ UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby
+ UINT32 bitwidth:5; // Selected BBP register
+ UINT32 RegIdAndContent:24; // Register value to program into BBP
+ } field;
+ UINT32 word;
+} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC;
+#else
+typedef union _RF_CSR_CFG0_STRUC {
+ struct {
+ UINT32 RegIdAndContent:24; // Register value to program into BBP
+ UINT32 bitwidth:5; // Selected BBP register
+ UINT32 StandbyMode:1; // 0: high when stand by 1: low when standby
+ UINT32 Sel:1; // 0:RF_LE0 activate 1:RF_LE1 activate
+ UINT32 Busy:1; // 0: idle 1: 8busy
+ } field;
+ UINT32 word;
+} RF_CSR_CFG0_STRUC, *PRF_CSR_CFG0_STRUC;
+#endif
+#define RF_CSR_CFG1 0x1024
+#ifdef RT_BIG_ENDIAN
+typedef union _RF_CSR_CFG1_STRUC {
+ struct {
+ UINT32 rsv:7; // 0: idle 1: 8busy
+ UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec)
+ UINT32 RegIdAndContent:24; // Register value to program into BBP
+ } field;
+ UINT32 word;
+} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC;
+#else
+typedef union _RF_CSR_CFG1_STRUC {
+ struct {
+ UINT32 RegIdAndContent:24; // Register value to program into BBP
+ UINT32 RFGap:5; // Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec)
+ UINT32 rsv:7; // 0: idle 1: 8busy
+ } field;
+ UINT32 word;
+} RF_CSR_CFG1_STRUC, *PRF_CSR_CFG1_STRUC;
+#endif
+#define RF_CSR_CFG2 0x1028 //
+#ifdef RT_BIG_ENDIAN
+typedef union _RF_CSR_CFG2_STRUC {
+ struct {
+ UINT32 rsv:8; // 0: idle 1: 8busy
+ UINT32 RegIdAndContent:24; // Register value to program into BBP
+ } field;
+ UINT32 word;
+} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC;
+#else
+typedef union _RF_CSR_CFG2_STRUC {
+ struct {
+ UINT32 RegIdAndContent:24; // Register value to program into BBP
+ UINT32 rsv:8; // 0: idle 1: 8busy
+ } field;
+ UINT32 word;
+} RF_CSR_CFG2_STRUC, *PRF_CSR_CFG2_STRUC;
+#endif
+#define LED_CFG 0x102c // MAC_CSR14
+#ifdef RT_BIG_ENDIAN
+typedef union _LED_CFG_STRUC {
+ struct {
+ UINT32 :1;
+ UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high
+ UINT32 YLedMode:2; // yellow Led Mode
+ UINT32 GLedMode:2; // green Led Mode
+ UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on
+ UINT32 rsv:2;
+ UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms
+ UINT32 OffPeriod:8; // blinking off period unit 1ms
+ UINT32 OnPeriod:8; // blinking on period unit 1ms
+ } field;
+ UINT32 word;
+} LED_CFG_STRUC, *PLED_CFG_STRUC;
+#else
+typedef union _LED_CFG_STRUC {
+ struct {
+ UINT32 OnPeriod:8; // blinking on period unit 1ms
+ UINT32 OffPeriod:8; // blinking off period unit 1ms
+ UINT32 SlowBlinkPeriod:6; // slow blinking period. unit:1ms
+ UINT32 rsv:2;
+ UINT32 RLedMode:2; // red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on
+ UINT32 GLedMode:2; // green Led Mode
+ UINT32 YLedMode:2; // yellow Led Mode
+ UINT32 LedPolar:1; // Led Polarity. 0: active low1: active high
+ UINT32 :1;
+ } field;
+ UINT32 word;
+} LED_CFG_STRUC, *PLED_CFG_STRUC;
+#endif
+//
+// 4.2 MAC TIMING configuration registers (offset:0x1100)
+//
+#define XIFS_TIME_CFG 0x1100 // MAC_CSR8 MAC_CSR9
+#ifdef RT_BIG_ENDIAN
+typedef union _IFS_SLOT_CFG_STRUC {
+ struct {
+ UINT32 rsv:2;
+ UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer
+ UINT32 EIFS:9; // unit 1us
+ UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND
+ UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX
+ UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX
+ } field;
+ UINT32 word;
+} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC;
+#else
+typedef union _IFS_SLOT_CFG_STRUC {
+ struct {
+ UINT32 CckmSifsTime:8; // unit 1us. Applied after CCK RX/TX
+ UINT32 OfdmSifsTime:8; // unit 1us. Applied after OFDM RX/TX
+ UINT32 OfdmXifsTime:4; //OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND
+ UINT32 EIFS:9; // unit 1us
+ UINT32 BBRxendEnable:1; // reference RXEND signal to begin XIFS defer
+ UINT32 rsv:2;
+ } field;
+ UINT32 word;
+} IFS_SLOT_CFG_STRUC, *PIFS_SLOT_CFG_STRUC;
+#endif
+
+#define BKOFF_SLOT_CFG 0x1104 // mac_csr9 last 8 bits
+#define NAV_TIME_CFG 0x1108 // NAV (MAC_CSR15)
+#define CH_TIME_CFG 0x110C // Count as channel busy
+#define PBF_LIFE_TIMER 0x1110 //TX/RX MPDU timestamp timer (free run)Unit: 1us
+#define BCN_TIME_CFG 0x1114 // TXRX_CSR9
+
+#define BCN_OFFSET0 0x042C
+#define BCN_OFFSET1 0x0430
+
+//
+// BCN_TIME_CFG : Synchronization control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _BCN_TIME_CFG_STRUC {
+ struct {
+ UINT32 TxTimestampCompensate:8;
+ UINT32 :3;
+ UINT32 bBeaconGen:1; // Enable beacon generator
+ UINT32 bTBTTEnable:1;
+ UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
+ UINT32 bTsfTicking:1; // Enable TSF auto counting
+ UINT32 BeaconInterval:16; // in unit of 1/16 TU
+ } field;
+ UINT32 word;
+} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC;
+#else
+typedef union _BCN_TIME_CFG_STRUC {
+ struct {
+ UINT32 BeaconInterval:16; // in unit of 1/16 TU
+ UINT32 bTsfTicking:1; // Enable TSF auto counting
+ UINT32 TsfSyncMode:2; // Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
+ UINT32 bTBTTEnable:1;
+ UINT32 bBeaconGen:1; // Enable beacon generator
+ UINT32 :3;
+ UINT32 TxTimestampCompensate:8;
+ } field;
+ UINT32 word;
+} BCN_TIME_CFG_STRUC, *PBCN_TIME_CFG_STRUC;
+#endif
+#define TBTT_SYNC_CFG 0x1118 // txrx_csr10
+#define TSF_TIMER_DW0 0x111C // Local TSF timer lsb 32 bits. Read-only
+#define TSF_TIMER_DW1 0x1120 // msb 32 bits. Read-only.
+#define TBTT_TIMER 0x1124 // TImer remains till next TBTT. Read-only. TXRX_CSR14
+#define INT_TIMER_CFG 0x1128 //
+#define INT_TIMER_EN 0x112c // GP-timer and pre-tbtt Int enable
+#define CH_IDLE_STA 0x1130 // channel idle time
+#define CH_BUSY_STA 0x1134 // channle busy time
+//
+// 4.2 MAC POWER configuration registers (offset:0x1200)
+//
+#define MAC_STATUS_CFG 0x1200 // old MAC_CSR12
+#define PWR_PIN_CFG 0x1204 // old MAC_CSR12
+#define AUTO_WAKEUP_CFG 0x1208 // old MAC_CSR10
+//
+// AUTO_WAKEUP_CFG: Manual power control / status register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _AUTO_WAKEUP_STRUC {
+ struct {
+ UINT32 :16;
+ UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake
+ UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set
+ UINT32 AutoLeadTime:8;
+ } field;
+ UINT32 word;
+} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC;
+#else
+typedef union _AUTO_WAKEUP_STRUC {
+ struct {
+ UINT32 AutoLeadTime:8;
+ UINT32 NumofSleepingTbtt:7; // ForceWake has high privilege than PutToSleep when both set
+ UINT32 EnableAutoWakeup:1; // 0:sleep, 1:awake
+ UINT32 :16;
+ } field;
+ UINT32 word;
+} AUTO_WAKEUP_STRUC, *PAUTO_WAKEUP_STRUC;
+#endif
+//
+// 4.3 MAC TX configuration registers (offset:0x1300)
+//
+
+#define EDCA_AC0_CFG 0x1300 //AC_TXOP_CSR0 0x3474
+#define EDCA_AC1_CFG 0x1304
+#define EDCA_AC2_CFG 0x1308
+#define EDCA_AC3_CFG 0x130c
+#ifdef RT_BIG_ENDIAN
+typedef union _EDCA_AC_CFG_STRUC {
+ struct {
+ UINT32 :12; //
+ UINT32 Cwmax:4; //unit power of 2
+ UINT32 Cwmin:4; //
+ UINT32 Aifsn:4; // # of slot time
+ UINT32 AcTxop:8; // in unit of 32us
+ } field;
+ UINT32 word;
+} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC;
+#else
+typedef union _EDCA_AC_CFG_STRUC {
+ struct {
+ UINT32 AcTxop:8; // in unit of 32us
+ UINT32 Aifsn:4; // # of slot time
+ UINT32 Cwmin:4; //
+ UINT32 Cwmax:4; //unit power of 2
+ UINT32 :12; //
+ } field;
+ UINT32 word;
+} EDCA_AC_CFG_STRUC, *PEDCA_AC_CFG_STRUC;
+#endif
+
+#define EDCA_TID_AC_MAP 0x1310
+#define TX_PWR_CFG_0 0x1314
+#define TX_PWR_CFG_1 0x1318
+#define TX_PWR_CFG_2 0x131C
+#define TX_PWR_CFG_3 0x1320
+#define TX_PWR_CFG_4 0x1324
+#define TX_PIN_CFG 0x1328
+#define TX_BAND_CFG 0x132c // 0x1 use upper 20MHz. 0 juse lower 20MHz
+#define TX_SW_CFG0 0x1330
+#define TX_SW_CFG1 0x1334
+#define TX_SW_CFG2 0x1338
+#define TXOP_THRES_CFG 0x133c
+#define TXOP_CTRL_CFG 0x1340
+#define TX_RTS_CFG 0x1344
+
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_RTS_CFG_STRUC {
+ struct {
+ UINT32 rsv:7;
+ UINT32 RtsFbkEn:1; // enable rts rate fallback
+ UINT32 RtsThres:16; // unit:byte
+ UINT32 AutoRtsRetryLimit:8;
+ } field;
+ UINT32 word;
+} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC;
+#else
+typedef union _TX_RTS_CFG_STRUC {
+ struct {
+ UINT32 AutoRtsRetryLimit:8;
+ UINT32 RtsThres:16; // unit:byte
+ UINT32 RtsFbkEn:1; // enable rts rate fallback
+ UINT32 rsv:7; // 1: HT non-STBC control frame enable
+ } field;
+ UINT32 word;
+} TX_RTS_CFG_STRUC, *PTX_RTS_CFG_STRUC;
+#endif
+#define TX_TIMEOUT_CFG 0x1348
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_TIMEOUT_CFG_STRUC {
+ struct {
+ UINT32 rsv2:8;
+ UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
+ UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure
+ UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us
+ UINT32 rsv:4;
+ } field;
+ UINT32 word;
+} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC;
+#else
+typedef union _TX_TIMEOUT_CFG_STRUC {
+ struct {
+ UINT32 rsv:4;
+ UINT32 MpduLifeTime:4; // expiration time = 2^(9+MPDU LIFE TIME) us
+ UINT32 RxAckTimeout:8; // unit:slot. Used for TX precedure
+ UINT32 TxopTimeout:8; //TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
+ UINT32 rsv2:8; // 1: HT non-STBC control frame enable
+ } field;
+ UINT32 word;
+} TX_TIMEOUT_CFG_STRUC, *PTX_TIMEOUT_CFG_STRUC;
+#endif
+#define TX_RTY_CFG 0x134c
+#ifdef RT_BIG_ENDIAN
+typedef union PACKED _TX_RTY_CFG_STRUC {
+ struct {
+ UINT32 rsv:1;
+ UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable
+ UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer
+ UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer
+ UINT32 LongRtyThre:12; // Long retry threshoold
+ UINT32 LongRtyLimit:8; //long retry limit
+ UINT32 ShortRtyLimit:8; // short retry limit
+
+ } field;
+ UINT32 word;
+} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC;
+#else
+typedef union PACKED _TX_RTY_CFG_STRUC {
+ struct {
+ UINT32 ShortRtyLimit:8; // short retry limit
+ UINT32 LongRtyLimit:8; //long retry limit
+ UINT32 LongRtyThre:12; // Long retry threshoold
+ UINT32 NonAggRtyMode:1; // Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer
+ UINT32 AggRtyMode:1; // Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer
+ UINT32 TxautoFBEnable:1; // Tx retry PHY rate auto fallback enable
+ UINT32 rsv:1; // 1: HT non-STBC control frame enable
+ } field;
+ UINT32 word;
+} TX_RTY_CFG_STRUC, *PTX_RTY_CFG_STRUC;
+#endif
+#define TX_LINK_CFG 0x1350
+#ifdef RT_BIG_ENDIAN
+typedef union PACKED _TX_LINK_CFG_STRUC {
+ struct PACKED {
+ UINT32 RemotMFS:8; //remote MCS feedback sequence number
+ UINT32 RemotMFB:8; // remote MCS feedback
+ UINT32 rsv:3; //
+ UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable
+ UINT32 TxRDGEn:1; // RDG TX enable
+ UINT32 TxMRQEn:1; // MCS request TX enable
+ UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7)
+ UINT32 MFBEnable:1; // TX apply remote MFB 1:enable
+ UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us
+ } field;
+ UINT32 word;
+} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC;
+#else
+typedef union PACKED _TX_LINK_CFG_STRUC {
+ struct PACKED {
+ UINT32 RemoteMFBLifeTime:8; //remote MFB life time. unit : 32us
+ UINT32 MFBEnable:1; // TX apply remote MFB 1:enable
+ UINT32 RemoteUMFSEnable:1; // remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7)
+ UINT32 TxMRQEn:1; // MCS request TX enable
+ UINT32 TxRDGEn:1; // RDG TX enable
+ UINT32 TxCFAckEn:1; // Piggyback CF-ACK enable
+ UINT32 rsv:3; //
+ UINT32 RemotMFB:8; // remote MCS feedback
+ UINT32 RemotMFS:8; //remote MCS feedback sequence number
+ } field;
+ UINT32 word;
+} TX_LINK_CFG_STRUC, *PTX_LINK_CFG_STRUC;
+#endif
+#define HT_FBK_CFG0 0x1354
+#ifdef RT_BIG_ENDIAN
+typedef union PACKED _HT_FBK_CFG0_STRUC {
+ struct {
+ UINT32 HTMCS7FBK:4;
+ UINT32 HTMCS6FBK:4;
+ UINT32 HTMCS5FBK:4;
+ UINT32 HTMCS4FBK:4;
+ UINT32 HTMCS3FBK:4;
+ UINT32 HTMCS2FBK:4;
+ UINT32 HTMCS1FBK:4;
+ UINT32 HTMCS0FBK:4;
+ } field;
+ UINT32 word;
+} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC;
+#else
+typedef union PACKED _HT_FBK_CFG0_STRUC {
+ struct {
+ UINT32 HTMCS0FBK:4;
+ UINT32 HTMCS1FBK:4;
+ UINT32 HTMCS2FBK:4;
+ UINT32 HTMCS3FBK:4;
+ UINT32 HTMCS4FBK:4;
+ UINT32 HTMCS5FBK:4;
+ UINT32 HTMCS6FBK:4;
+ UINT32 HTMCS7FBK:4;
+ } field;
+ UINT32 word;
+} HT_FBK_CFG0_STRUC, *PHT_FBK_CFG0_STRUC;
+#endif
+#define HT_FBK_CFG1 0x1358
+#ifdef RT_BIG_ENDIAN
+typedef union _HT_FBK_CFG1_STRUC {
+ struct {
+ UINT32 HTMCS15FBK:4;
+ UINT32 HTMCS14FBK:4;
+ UINT32 HTMCS13FBK:4;
+ UINT32 HTMCS12FBK:4;
+ UINT32 HTMCS11FBK:4;
+ UINT32 HTMCS10FBK:4;
+ UINT32 HTMCS9FBK:4;
+ UINT32 HTMCS8FBK:4;
+ } field;
+ UINT32 word;
+} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC;
+#else
+typedef union _HT_FBK_CFG1_STRUC {
+ struct {
+ UINT32 HTMCS8FBK:4;
+ UINT32 HTMCS9FBK:4;
+ UINT32 HTMCS10FBK:4;
+ UINT32 HTMCS11FBK:4;
+ UINT32 HTMCS12FBK:4;
+ UINT32 HTMCS13FBK:4;
+ UINT32 HTMCS14FBK:4;
+ UINT32 HTMCS15FBK:4;
+ } field;
+ UINT32 word;
+} HT_FBK_CFG1_STRUC, *PHT_FBK_CFG1_STRUC;
+#endif
+#define LG_FBK_CFG0 0x135c
+#ifdef RT_BIG_ENDIAN
+typedef union _LG_FBK_CFG0_STRUC {
+ struct {
+ UINT32 OFDMMCS7FBK:4; //initial value is 6
+ UINT32 OFDMMCS6FBK:4; //initial value is 5
+ UINT32 OFDMMCS5FBK:4; //initial value is 4
+ UINT32 OFDMMCS4FBK:4; //initial value is 3
+ UINT32 OFDMMCS3FBK:4; //initial value is 2
+ UINT32 OFDMMCS2FBK:4; //initial value is 1
+ UINT32 OFDMMCS1FBK:4; //initial value is 0
+ UINT32 OFDMMCS0FBK:4; //initial value is 0
+ } field;
+ UINT32 word;
+} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC;
+#else
+typedef union _LG_FBK_CFG0_STRUC {
+ struct {
+ UINT32 OFDMMCS0FBK:4; //initial value is 0
+ UINT32 OFDMMCS1FBK:4; //initial value is 0
+ UINT32 OFDMMCS2FBK:4; //initial value is 1
+ UINT32 OFDMMCS3FBK:4; //initial value is 2
+ UINT32 OFDMMCS4FBK:4; //initial value is 3
+ UINT32 OFDMMCS5FBK:4; //initial value is 4
+ UINT32 OFDMMCS6FBK:4; //initial value is 5
+ UINT32 OFDMMCS7FBK:4; //initial value is 6
+ } field;
+ UINT32 word;
+} LG_FBK_CFG0_STRUC, *PLG_FBK_CFG0_STRUC;
+#endif
+#define LG_FBK_CFG1 0x1360
+#ifdef RT_BIG_ENDIAN
+typedef union _LG_FBK_CFG1_STRUC {
+ struct {
+ UINT32 rsv:16;
+ UINT32 CCKMCS3FBK:4; //initial value is 2
+ UINT32 CCKMCS2FBK:4; //initial value is 1
+ UINT32 CCKMCS1FBK:4; //initial value is 0
+ UINT32 CCKMCS0FBK:4; //initial value is 0
+ } field;
+ UINT32 word;
+} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC;
+#else
+typedef union _LG_FBK_CFG1_STRUC {
+ struct {
+ UINT32 CCKMCS0FBK:4; //initial value is 0
+ UINT32 CCKMCS1FBK:4; //initial value is 0
+ UINT32 CCKMCS2FBK:4; //initial value is 1
+ UINT32 CCKMCS3FBK:4; //initial value is 2
+ UINT32 rsv:16;
+ } field;
+ UINT32 word;
+} LG_FBK_CFG1_STRUC, *PLG_FBK_CFG1_STRUC;
+#endif
+
+//=======================================================
+//================ Protection Paramater================================
+//=======================================================
+#define CCK_PROT_CFG 0x1364 //CCK Protection
+#define ASIC_SHORTNAV 1
+#define ASIC_LONGNAV 2
+#define ASIC_RTS 1
+#define ASIC_CTS 2
+#ifdef RT_BIG_ENDIAN
+typedef union _PROT_CFG_STRUC {
+ struct {
+ UINT32 rsv:5;
+ UINT32 RTSThEn:1; //RTS threshold enable on CCK TX
+ UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow.
+ UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow.
+ UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv
+ UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv
+ UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd).
+ } field;
+ UINT32 word;
+} PROT_CFG_STRUC, *PPROT_CFG_STRUC;
+#else
+typedef union _PROT_CFG_STRUC {
+ struct {
+ UINT32 ProtectRate:16; //Protection control frame rate for CCK TX(RTS/CTS/CFEnd).
+ UINT32 ProtectCtrl:2; //Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv
+ UINT32 ProtectNav:2; //TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv
+ UINT32 TxopAllowCck:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowOfdm:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowMM20:1; //CCK TXOP allowance. 0:disallow.
+ UINT32 TxopAllowMM40:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowGF20:1; //CCK TXOP allowance.0:disallow.
+ UINT32 TxopAllowGF40:1; //CCK TXOP allowance.0:disallow.
+ UINT32 RTSThEn:1; //RTS threshold enable on CCK TX
+ UINT32 rsv:5;
+ } field;
+ UINT32 word;
+} PROT_CFG_STRUC, *PPROT_CFG_STRUC;
+#endif
+
+#define OFDM_PROT_CFG 0x1368 //OFDM Protection
+#define MM20_PROT_CFG 0x136C //MM20 Protection
+#define MM40_PROT_CFG 0x1370 //MM40 Protection
+#define GF20_PROT_CFG 0x1374 //GF20 Protection
+#define GF40_PROT_CFG 0x1378 //GR40 Protection
+#define EXP_CTS_TIME 0x137C //
+#define EXP_ACK_TIME 0x1380 //
+
+//
+// 4.4 MAC RX configuration registers (offset:0x1400)
+//
+#define RX_FILTR_CFG 0x1400 //TXRX_CSR0
+#define AUTO_RSP_CFG 0x1404 //TXRX_CSR4
+//
+// TXRX_CSR4: Auto-Responder/
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _AUTO_RSP_CFG_STRUC {
+ struct {
+ UINT32 :24;
+ UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame
+ UINT32 DualCTSEn:1; // Power bit value in conrtrol frame
+ UINT32 rsv:1; // Power bit value in conrtrol frame
+ UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble
+ UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode
+ UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode
+ UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble
+ UINT32 AutoResponderEnable:1;
+ } field;
+ UINT32 word;
+} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC;
+#else
+typedef union _AUTO_RSP_CFG_STRUC {
+ struct {
+ UINT32 AutoResponderEnable:1;
+ UINT32 BACAckPolicyEnable:1; // 0:long, 1:short preamble
+ UINT32 CTS40MMode:1; // Response CTS 40MHz duplicate mode
+ UINT32 CTS40MRef:1; // Response CTS 40MHz duplicate mode
+ UINT32 AutoResponderPreamble:1; // 0:long, 1:short preamble
+ UINT32 rsv:1; // Power bit value in conrtrol frame
+ UINT32 DualCTSEn:1; // Power bit value in conrtrol frame
+ UINT32 AckCtsPsmBit:1; // Power bit value in conrtrol frame
+ UINT32 :24;
+ } field;
+ UINT32 word;
+} AUTO_RSP_CFG_STRUC, *PAUTO_RSP_CFG_STRUC;
+#endif
+
+#define LEGACY_BASIC_RATE 0x1408 // TXRX_CSR5 0x3054
+#define HT_BASIC_RATE 0x140c
+#define HT_CTRL_CFG 0x1410
+#define SIFS_COST_CFG 0x1414
+#define RX_PARSER_CFG 0x1418 //Set NAV for all received frames
+
+//
+// 4.5 MAC Security configuration (offset:0x1500)
+//
+#define TX_SEC_CNT0 0x1500 //
+#define RX_SEC_CNT0 0x1504 //
+#define CCMP_FC_MUTE 0x1508 //
+//
+// 4.6 HCCA/PSMP (offset:0x1600)
+//
+#define TXOP_HLDR_ADDR0 0x1600
+#define TXOP_HLDR_ADDR1 0x1604
+#define TXOP_HLDR_ET 0x1608
+#define QOS_CFPOLL_RA_DW0 0x160c
+#define QOS_CFPOLL_A1_DW1 0x1610
+#define QOS_CFPOLL_QC 0x1614
+//
+// 4.7 MAC Statistis registers (offset:0x1700)
+//
+#define RX_STA_CNT0 0x1700 //
+#define RX_STA_CNT1 0x1704 //
+#define RX_STA_CNT2 0x1708 //
+
+//
+// RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _RX_STA_CNT0_STRUC {
+ struct {
+ USHORT PhyErr;
+ USHORT CrcErr;
+ } field;
+ UINT32 word;
+} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC;
+#else
+typedef union _RX_STA_CNT0_STRUC {
+ struct {
+ USHORT CrcErr;
+ USHORT PhyErr;
+ } field;
+ UINT32 word;
+} RX_STA_CNT0_STRUC, *PRX_STA_CNT0_STRUC;
+#endif
+
+//
+// RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _RX_STA_CNT1_STRUC {
+ struct {
+ USHORT PlcpErr;
+ USHORT FalseCca;
+ } field;
+ UINT32 word;
+} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC;
+#else
+typedef union _RX_STA_CNT1_STRUC {
+ struct {
+ USHORT FalseCca;
+ USHORT PlcpErr;
+ } field;
+ UINT32 word;
+} RX_STA_CNT1_STRUC, *PRX_STA_CNT1_STRUC;
+#endif
+
+//
+// RX_STA_CNT2_STRUC:
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _RX_STA_CNT2_STRUC {
+ struct {
+ USHORT RxFifoOverflowCount;
+ USHORT RxDupliCount;
+ } field;
+ UINT32 word;
+} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC;
+#else
+typedef union _RX_STA_CNT2_STRUC {
+ struct {
+ USHORT RxDupliCount;
+ USHORT RxFifoOverflowCount;
+ } field;
+ UINT32 word;
+} RX_STA_CNT2_STRUC, *PRX_STA_CNT2_STRUC;
+#endif
+#define TX_STA_CNT0 0x170C //
+//
+// STA_CSR3: TX Beacon count
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_STA_CNT0_STRUC {
+ struct {
+ USHORT TxBeaconCount;
+ USHORT TxFailCount;
+ } field;
+ UINT32 word;
+} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC;
+#else
+typedef union _TX_STA_CNT0_STRUC {
+ struct {
+ USHORT TxFailCount;
+ USHORT TxBeaconCount;
+ } field;
+ UINT32 word;
+} TX_STA_CNT0_STRUC, *PTX_STA_CNT0_STRUC;
+#endif
+#define TX_STA_CNT1 0x1710 //
+//
+// TX_STA_CNT1: TX tx count
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_STA_CNT1_STRUC {
+ struct {
+ USHORT TxRetransmit;
+ USHORT TxSuccess;
+ } field;
+ UINT32 word;
+} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC;
+#else
+typedef union _TX_STA_CNT1_STRUC {
+ struct {
+ USHORT TxSuccess;
+ USHORT TxRetransmit;
+ } field;
+ UINT32 word;
+} TX_STA_CNT1_STRUC, *PTX_STA_CNT1_STRUC;
+#endif
+#define TX_STA_CNT2 0x1714 //
+//
+// TX_STA_CNT2: TX tx count
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_STA_CNT2_STRUC {
+ struct {
+ USHORT TxUnderFlowCount;
+ USHORT TxZeroLenCount;
+ } field;
+ UINT32 word;
+} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC;
+#else
+typedef union _TX_STA_CNT2_STRUC {
+ struct {
+ USHORT TxZeroLenCount;
+ USHORT TxUnderFlowCount;
+ } field;
+ UINT32 word;
+} TX_STA_CNT2_STRUC, *PTX_STA_CNT2_STRUC;
+#endif
+#define TX_STA_FIFO 0x1718 //
+//
+// TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union PACKED _TX_STA_FIFO_STRUC {
+ struct {
+ UINT32 Reserve:2;
+ UINT32 TxBF:1; // 3*3
+ UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+ UINT32 wcid:8; //wireless client index
+ UINT32 TxAckRequired:1; // ack required
+ UINT32 TxAggre:1; // Tx is aggregated
+ UINT32 TxSuccess:1; // Tx success. whether success or not
+ UINT32 PidType:4;
+ UINT32 bValid:1; // 1:This register contains a valid TX result
+ } field;
+ UINT32 word;
+} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC;
+#else
+typedef union PACKED _TX_STA_FIFO_STRUC {
+ struct {
+ UINT32 bValid:1; // 1:This register contains a valid TX result
+ UINT32 PidType:4;
+ UINT32 TxSuccess:1; // Tx No retry success
+ UINT32 TxAggre:1; // Tx Retry Success
+ UINT32 TxAckRequired:1; // Tx fail
+ UINT32 wcid:8; //wireless client index
+// UINT32 SuccessRate:16; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+ UINT32 SuccessRate:13; //include MCS, mode ,shortGI, BW settingSame format as TXWI Word 0 Bit 31-16.
+ UINT32 TxBF:1;
+ UINT32 Reserve:2;
+ } field;
+ UINT32 word;
+} TX_STA_FIFO_STRUC, *PTX_STA_FIFO_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT 0x171c
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT_STRUC {
+ struct {
+ USHORT AggTxCount;
+ USHORT NonAggTxCount;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC;
+#else
+typedef union _TX_AGG_CNT_STRUC {
+ struct {
+ USHORT NonAggTxCount;
+ USHORT AggTxCount;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT_STRUC, *PTX_AGG_CNT_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT0 0x1720
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT0_STRUC {
+ struct {
+ USHORT AggSize2Count;
+ USHORT AggSize1Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC;
+#else
+typedef union _TX_AGG_CNT0_STRUC {
+ struct {
+ USHORT AggSize1Count;
+ USHORT AggSize2Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT0_STRUC, *PTX_AGG_CNT0_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT1 0x1724
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT1_STRUC {
+ struct {
+ USHORT AggSize4Count;
+ USHORT AggSize3Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC;
+#else
+typedef union _TX_AGG_CNT1_STRUC {
+ struct {
+ USHORT AggSize3Count;
+ USHORT AggSize4Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT1_STRUC, *PTX_AGG_CNT1_STRUC;
+#endif
+#define TX_AGG_CNT2 0x1728
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT2_STRUC {
+ struct {
+ USHORT AggSize6Count;
+ USHORT AggSize5Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC;
+#else
+typedef union _TX_AGG_CNT2_STRUC {
+ struct {
+ USHORT AggSize5Count;
+ USHORT AggSize6Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT2_STRUC, *PTX_AGG_CNT2_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT3 0x172c
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT3_STRUC {
+ struct {
+ USHORT AggSize8Count;
+ USHORT AggSize7Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC;
+#else
+typedef union _TX_AGG_CNT3_STRUC {
+ struct {
+ USHORT AggSize7Count;
+ USHORT AggSize8Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT3_STRUC, *PTX_AGG_CNT3_STRUC;
+#endif
+// Debug counter
+#define TX_AGG_CNT4 0x1730
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT4_STRUC {
+ struct {
+ USHORT AggSize10Count;
+ USHORT AggSize9Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC;
+#else
+typedef union _TX_AGG_CNT4_STRUC {
+ struct {
+ USHORT AggSize9Count;
+ USHORT AggSize10Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT4_STRUC, *PTX_AGG_CNT4_STRUC;
+#endif
+#define TX_AGG_CNT5 0x1734
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT5_STRUC {
+ struct {
+ USHORT AggSize12Count;
+ USHORT AggSize11Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC;
+#else
+typedef union _TX_AGG_CNT5_STRUC {
+ struct {
+ USHORT AggSize11Count;
+ USHORT AggSize12Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT5_STRUC, *PTX_AGG_CNT5_STRUC;
+#endif
+#define TX_AGG_CNT6 0x1738
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT6_STRUC {
+ struct {
+ USHORT AggSize14Count;
+ USHORT AggSize13Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC;
+#else
+typedef union _TX_AGG_CNT6_STRUC {
+ struct {
+ USHORT AggSize13Count;
+ USHORT AggSize14Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT6_STRUC, *PTX_AGG_CNT6_STRUC;
+#endif
+#define TX_AGG_CNT7 0x173c
+#ifdef RT_BIG_ENDIAN
+typedef union _TX_AGG_CNT7_STRUC {
+ struct {
+ USHORT AggSize16Count;
+ USHORT AggSize15Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC;
+#else
+typedef union _TX_AGG_CNT7_STRUC {
+ struct {
+ USHORT AggSize15Count;
+ USHORT AggSize16Count;
+ } field;
+ UINT32 word;
+} TX_AGG_CNT7_STRUC, *PTX_AGG_CNT7_STRUC;
+#endif
+#define MPDU_DENSITY_CNT 0x1740
+#ifdef RT_BIG_ENDIAN
+typedef union _MPDU_DEN_CNT_STRUC {
+ struct {
+ USHORT RXZeroDelCount; //RX zero length delimiter count
+ USHORT TXZeroDelCount; //TX zero length delimiter count
+ } field;
+ UINT32 word;
+} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC;
+#else
+typedef union _MPDU_DEN_CNT_STRUC {
+ struct {
+ USHORT TXZeroDelCount; //TX zero length delimiter count
+ USHORT RXZeroDelCount; //RX zero length delimiter count
+ } field;
+ UINT32 word;
+} MPDU_DEN_CNT_STRUC, *PMPDU_DEN_CNT_STRUC;
+#endif
+//
+// TXRX control registers - base address 0x3000
+//
+// rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first..
+#define TXRX_CSR1 0x77d0
+
+//
+// Security key table memory, base address = 0x1000
+//
+#define MAC_WCID_BASE 0x1800 //8-bytes(use only 6-bytes) * 256 entry =
+#define HW_WCID_ENTRY_SIZE 8
+#define PAIRWISE_KEY_TABLE_BASE 0x4000 // 32-byte * 256-entry = -byte
+#define HW_KEY_ENTRY_SIZE 0x20
+#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte
+#define MAC_IVEIV_TABLE_BASE 0x6000 // 8-byte * 256-entry = -byte
+#define HW_IVEIV_ENTRY_SIZE 8
+#define MAC_WCID_ATTRIBUTE_BASE 0x6800 // 4-byte * 256-entry = -byte
+#define HW_WCID_ATTRI_SIZE 4
+#define WCID_RESERVED 0x6bfc
+#define SHARED_KEY_TABLE_BASE 0x6c00 // 32-byte * 16-entry = 512-byte
+#define SHARED_KEY_MODE_BASE 0x7000 // 32-byte * 16-entry = 512-byte
+#define HW_SHARED_KEY_MODE_SIZE 4
+#define SHAREDKEYTABLE 0
+#define PAIRWISEKEYTABLE 1
+
+
+#ifdef RT_BIG_ENDIAN
+typedef union _SHAREDKEY_MODE_STRUC {
+ struct {
+ UINT32 :1;
+ UINT32 Bss1Key3CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss1Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss1Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss1Key0CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss0Key3CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss0Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss0Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss0Key0CipherAlg:3;
+ } field;
+ UINT32 word;
+} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC;
+#else
+typedef union _SHAREDKEY_MODE_STRUC {
+ struct {
+ UINT32 Bss0Key0CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss0Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss0Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss0Key3CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss1Key0CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss1Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss1Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss1Key3CipherAlg:3;
+ UINT32 :1;
+ } field;
+ UINT32 word;
+} SHAREDKEY_MODE_STRUC, *PSHAREDKEY_MODE_STRUC;
+#endif
+// 64-entry for pairwise key table
+typedef struct _HW_WCID_ENTRY { // 8-byte per entry
+ UCHAR Address[6];
+ UCHAR Rsv[2];
+} HW_WCID_ENTRY, PHW_WCID_ENTRY;
+
+
+
+//
+// Other on-chip shared memory space, base = 0x2000
+//
+
+// CIS space - base address = 0x2000
+#define HW_CIS_BASE 0x2000
+
+// Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function.
+#define HW_CS_CTS_BASE 0x7700
+// DFS CTS frame base address. It's where mac stores CTS frame for DFS.
+#define HW_DFS_CTS_BASE 0x7780
+#define HW_CTS_FRAME_SIZE 0x80
+
+// 2004-11-08 john - since NULL frame won't be that long (256 byte). We steal 16 tail bytes
+// to save debugging settings
+#define HW_DEBUG_SETTING_BASE 0x77f0 // 0x77f0~0x77ff total 16 bytes
+#define HW_DEBUG_SETTING_BASE2 0x7770 // 0x77f0~0x77ff total 16 bytes
+
+// In order to support maximum 8 MBSS and its maximum length is 512 for each beacon
+// Three section discontinue memory segments will be used.
+// 1. The original region for BCN 0~3
+// 2. Extract memory from FCE table for BCN 4~5
+// 3. Extract memory from Pair-wise key table for BCN 6~7
+// It occupied those memory of wcid 238~253 for BCN 6
+// and wcid 222~237 for BCN 7
+#define HW_BEACON_MAX_SIZE 0x1000 /* unit: byte */
+#define HW_BEACON_BASE0 0x7800
+#define HW_BEACON_BASE1 0x7A00
+#define HW_BEACON_BASE2 0x7C00
+#define HW_BEACON_BASE3 0x7E00
+#define HW_BEACON_BASE4 0x7200
+#define HW_BEACON_BASE5 0x7400
+#define HW_BEACON_BASE6 0x5DC0
+#define HW_BEACON_BASE7 0x5BC0
+
+#define HW_BEACON_MAX_COUNT 8
+#define HW_BEACON_OFFSET 0x0200
+#define HW_BEACON_CONTENT_LEN (HW_BEACON_OFFSET - TXWI_SIZE)
+
+// HOST-MCU shared memory - base address = 0x2100
+#define HOST_CMD_CSR 0x404
+#define H2M_MAILBOX_CSR 0x7010
+#define H2M_MAILBOX_CID 0x7014
+#define H2M_MAILBOX_STATUS 0x701c
+#define H2M_INT_SRC 0x7024
+#define H2M_BBP_AGENT 0x7028
+#define M2H_CMD_DONE_CSR 0x000c
+#define MCU_TXOP_ARRAY_BASE 0x000c // TODO: to be provided by Albert
+#define MCU_TXOP_ENTRY_SIZE 32 // TODO: to be provided by Albert
+#define MAX_NUM_OF_TXOP_ENTRY 16 // TODO: must be same with 8051 firmware
+#define MCU_MBOX_VERSION 0x01 // TODO: to be confirmed by Albert
+#define MCU_MBOX_VERSION_OFFSET 5 // TODO: to be provided by Albert
+
+//
+// Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT,
+//
+//
+// DMA RING DESCRIPTOR
+//
+#define E2PROM_CSR 0x0004
+#define IO_CNTL_CSR 0x77d0
+
+#ifdef RT2860
+// 8051 firmware image for RT2860 - base address = 0x4000
+#define FIRMWARE_IMAGE_BASE 0x2000
+#define MAX_FIRMWARE_IMAGE_SIZE 0x2000 // 8kbyte
+#endif // RT2860 //
+
+
+// ================================================================
+// Tx / Rx / Mgmt ring descriptor definition
+// ================================================================
+
+// the following PID values are used to mark outgoing frame type in TXD->PID so that
+// proper TX statistics can be collected based on these categories
+// b3-2 of PID field -
+#define PID_MGMT 0x05
+#define PID_BEACON 0x0c
+#define PID_DATA_NORMALUCAST 0x02
+#define PID_DATA_AMPDU 0x04
+#define PID_DATA_NO_ACK 0x08
+#define PID_DATA_NOT_NORM_ACK 0x03
+// value domain of pTxD->HostQId (4-bit: 0~15)
+#define QID_AC_BK 1 // meet ACI definition in 802.11e
+#define QID_AC_BE 0 // meet ACI definition in 802.11e
+#define QID_AC_VI 2
+#define QID_AC_VO 3
+#define QID_HCCA 4
+#define NUM_OF_TX_RING 5
+#define QID_MGMT 13
+#define QID_RX 14
+#define QID_OTHER 15
+
+
+// ------------------------------------------------------
+// BBP & RF definition
+// ------------------------------------------------------
+#define BUSY 1
+#define IDLE 0
+
+#define RF_R00 0
+#define RF_R01 1
+#define RF_R02 2
+#define RF_R03 3
+#define RF_R04 4
+#define RF_R05 5
+#define RF_R06 6
+#define RF_R07 7
+#define RF_R08 8
+#define RF_R09 9
+#define RF_R10 10
+#define RF_R11 11
+#define RF_R12 12
+#define RF_R13 13
+#define RF_R14 14
+#define RF_R15 15
+#define RF_R16 16
+#define RF_R17 17
+#define RF_R18 18
+#define RF_R19 19
+#define RF_R20 20
+#define RF_R21 21
+#define RF_R22 22
+#define RF_R23 23
+#define RF_R24 24
+#define RF_R25 25
+#define RF_R26 26
+#define RF_R27 27
+#define RF_R28 28
+#define RF_R29 29
+#define RF_R30 30
+#define RF_R31 31
+
+#define BBP_R0 0 // version
+#define BBP_R1 1 // TSSI
+#define BBP_R2 2 // TX configure
+#define BBP_R3 3
+#define BBP_R4 4
+#define BBP_R5 5
+#define BBP_R6 6
+#define BBP_R14 14 // RX configure
+#define BBP_R16 16
+#define BBP_R17 17 // RX sensibility
+#define BBP_R18 18
+#define BBP_R21 21
+#define BBP_R22 22
+#define BBP_R24 24
+#define BBP_R25 25
+#define BBP_R49 49 //TSSI
+#define BBP_R50 50
+#define BBP_R51 51
+#define BBP_R52 52
+#define BBP_R55 55
+#define BBP_R62 62 // Rx SQ0 Threshold HIGH
+#define BBP_R63 63
+#define BBP_R64 64
+#define BBP_R65 65
+#define BBP_R66 66
+#define BBP_R67 67
+#define BBP_R68 68
+#define BBP_R69 69
+#define BBP_R70 70 // Rx AGC SQ CCK Xcorr threshold
+#define BBP_R73 73
+#define BBP_R75 75
+#define BBP_R77 77
+#define BBP_R81 81
+#define BBP_R82 82
+#define BBP_R83 83
+#define BBP_R84 84
+#define BBP_R86 86
+#define BBP_R91 91
+#define BBP_R92 92
+#define BBP_R94 94 // Tx Gain Control
+#define BBP_R103 103
+#define BBP_R105 105
+#define BBP_R113 113
+#define BBP_R114 114
+#define BBP_R115 115
+#define BBP_R116 116
+#define BBP_R117 117
+#define BBP_R118 118
+#define BBP_R119 119
+#define BBP_R120 120
+#define BBP_R121 121
+#define BBP_R122 122
+#define BBP_R123 123
+
+
+#define BBPR94_DEFAULT 0x06 // Add 1 value will gain 1db
+
+#define RSSI_FOR_VERY_LOW_SENSIBILITY -35
+#define RSSI_FOR_LOW_SENSIBILITY -58
+#define RSSI_FOR_MID_LOW_SENSIBILITY -80
+#define RSSI_FOR_MID_SENSIBILITY -90
+
+//-------------------------------------------------------------------------
+// EEPROM definition
+//-------------------------------------------------------------------------
+#define EEDO 0x08
+#define EEDI 0x04
+#define EECS 0x02
+#define EESK 0x01
+#define EERL 0x80
+
+#define EEPROM_WRITE_OPCODE 0x05
+#define EEPROM_READ_OPCODE 0x06
+#define EEPROM_EWDS_OPCODE 0x10
+#define EEPROM_EWEN_OPCODE 0x13
+
+#define NUM_EEPROM_BBP_PARMS 19 // Include NIC Config 0, 1, CR, TX ALC step, BBPs
+#define NUM_EEPROM_TX_G_PARMS 7
+#define EEPROM_NIC1_OFFSET 0x34 // The address is from NIC config 0, not BBP register ID
+#define EEPROM_NIC2_OFFSET 0x36 // The address is from NIC config 0, not BBP register ID
+#define EEPROM_BBP_BASE_OFFSET 0xf0 // The address is from NIC config 0, not BBP register ID
+#define EEPROM_G_TX_PWR_OFFSET 0x52
+#define EEPROM_G_TX2_PWR_OFFSET 0x60
+#define EEPROM_LED1_OFFSET 0x3c
+#define EEPROM_LED2_OFFSET 0x3e
+#define EEPROM_LED3_OFFSET 0x40
+#define EEPROM_LNA_OFFSET 0x44
+#define EEPROM_RSSI_BG_OFFSET 0x46
+#define EEPROM_RSSI_A_OFFSET 0x4a
+#define EEPROM_DEFINE_MAX_TXPWR 0x4e
+#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde // 20MHZ 2.4G tx power.
+#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee // 40MHZ 2.4G tx power.
+#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa // 20MHZ 5G tx power.
+#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a // 40MHZ 5G tx power.
+#define EEPROM_A_TX_PWR_OFFSET 0x78
+#define EEPROM_A_TX2_PWR_OFFSET 0xa6
+#define EEPROM_VERSION_OFFSET 0x02
+#define EEPROM_FREQ_OFFSET 0x3a
+#define EEPROM_TXPOWER_BYRATE 0xde // 20MHZ power.
+#define EEPROM_TXPOWER_DELTA 0x50 // 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ.
+#define VALID_EEPROM_VERSION 1
+
+// PairKeyMode definition
+#define PKMODE_NONE 0
+#define PKMODE_WEP64 1
+#define PKMODE_WEP128 2
+#define PKMODE_TKIP 3
+#define PKMODE_AES 4
+#define PKMODE_CKIP64 5
+#define PKMODE_CKIP128 6
+#define PKMODE_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table
+
+// =================================================================================
+// WCID format
+// =================================================================================
+//7.1 WCID ENTRY format : 8bytes
+typedef struct _WCID_ENTRY_STRUC {
+ UCHAR RXBABitmap7; // bit0 for TID8, bit7 for TID 15
+ UCHAR RXBABitmap0; // bit0 for TID0, bit7 for TID 7
+ UCHAR MAC[6]; // 0 for shared key table. 1 for pairwise key table
+} WCID_ENTRY_STRUC, *PWCID_ENTRY_STRUC;
+
+//8.1.1 SECURITY KEY format : 8DW
+// 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table
+typedef struct _HW_KEY_ENTRY { // 32-byte per entry
+ UCHAR Key[16];
+ UCHAR TxMic[8];
+ UCHAR RxMic[8];
+} HW_KEY_ENTRY, *PHW_KEY_ENTRY;
+
+//8.1.2 IV/EIV format : 2DW
+
+//8.1.3 RX attribute entry format : 1DW
+#ifdef RT_BIG_ENDIAN
+typedef struct _MAC_ATTRIBUTE_STRUC {
+ UINT32 rsv:22;
+ UINT32 RXWIUDF:3;
+ UINT32 BSSIDIdx:3; //multipleBSS index for the WCID
+ UINT32 PairKeyMode:3;
+ UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table
+} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC;
+#else
+typedef struct _MAC_ATTRIBUTE_STRUC {
+ UINT32 KeyTab:1; // 0 for shared key table. 1 for pairwise key table
+ UINT32 PairKeyMode:3;
+ UINT32 BSSIDIdx:3; //multipleBSS index for the WCID
+ UINT32 RXWIUDF:3;
+ UINT32 rsv:22;
+} MAC_ATTRIBUTE_STRUC, *PMAC_ATTRIBUTE_STRUC;
+#endif
+
+
+// =================================================================================
+// TX / RX ring descriptor format
+// =================================================================================
+
+// the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO.
+// MAC block use this TXINFO to control the transmission behavior of this frame.
+#define FIFO_MGMT 0
+#define FIFO_HCCA 1
+#define FIFO_EDCA 2
+
+//
+// TX descriptor format, Tx ring, Mgmt Ring
+//
+#ifdef RT_BIG_ENDIAN
+typedef struct PACKED _TXD_STRUC {
+ // Word 0
+ UINT32 SDPtr0;
+ // Word 1
+ UINT32 DMADONE:1;
+ UINT32 LastSec0:1;
+ UINT32 SDLen0:14;
+ UINT32 Burst:1;
+ UINT32 LastSec1:1;
+ UINT32 SDLen1:14;
+ // Word 2
+ UINT32 SDPtr1;
+ // Word 3
+ UINT32 ICO:1;
+ UINT32 UCO:1;
+ UINT32 TCO:1;
+ UINT32 rsv:2;
+ UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA
+ UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition
+ UINT32 rsv2:24;
+} TXD_STRUC, *PTXD_STRUC;
+#else
+typedef struct PACKED _TXD_STRUC {
+ // Word 0
+ UINT32 SDPtr0;
+ // Word 1
+ UINT32 SDLen1:14;
+ UINT32 LastSec1:1;
+ UINT32 Burst:1;
+ UINT32 SDLen0:14;
+ UINT32 LastSec0:1;
+ UINT32 DMADONE:1;
+ //Word2
+ UINT32 SDPtr1;
+ //Word3
+ UINT32 rsv2:24;
+ UINT32 WIV:1; // Wireless Info Valid. 1 if Driver already fill WI, o if DMA needs to copy WI to correctposition
+ UINT32 QSEL:2; // select on-chip FIFO ID for 2nd-stage output scheduler.0:MGMT, 1:HCCA 2:EDCA
+ UINT32 rsv:2;
+ UINT32 TCO:1; //
+ UINT32 UCO:1; //
+ UINT32 ICO:1; //
+} TXD_STRUC, *PTXD_STRUC;
+#endif
+
+
+//
+// TXD Wireless Information format for Tx ring and Mgmt Ring
+//
+//txop : for txop mode
+// 0:txop for the MPDU frame will be handles by ASIC by register
+// 1/2/3:the MPDU frame is send after PIFS/backoff/SIFS
+#ifdef RT_BIG_ENDIAN
+typedef struct PACKED _TXWI_STRUC {
+ // Word 0
+ UINT32 PHYMODE:2;
+ UINT32 TxBF:1; // 3*3
+ UINT32 rsv2:1;
+ UINT32 Ifs:1; //
+ UINT32 STBC:2; //channel bandwidth 20MHz or 40 MHz
+ UINT32 ShortGI:1;
+ UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz
+ UINT32 MCS:7;
+
+ UINT32 rsv:6;
+ UINT32 txop:2; //tx back off mode 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful.
+ UINT32 MpduDensity:3;
+ UINT32 AMPDU:1;
+
+ UINT32 TS:1;
+ UINT32 CFACK:1;
+ UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode
+ UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment.
+ // Word 1
+ UINT32 PacketId:4;
+ UINT32 MPDUtotalByteCount:12;
+ UINT32 WirelessCliID:8;
+ UINT32 BAWinSize:6;
+ UINT32 NSEQ:1;
+ UINT32 ACK:1;
+ // Word 2
+ UINT32 IV;
+ // Word 3
+ UINT32 EIV;
+} TXWI_STRUC, *PTXWI_STRUC;
+#else
+typedef struct PACKED _TXWI_STRUC {
+ // Word 0
+ UINT32 FRAG:1; // 1 to inform TKIP engine this is a fragment.
+ UINT32 MIMOps:1; // the remote peer is in dynamic MIMO-PS mode
+ UINT32 CFACK:1;
+ UINT32 TS:1;
+
+ UINT32 AMPDU:1;
+ UINT32 MpduDensity:3;
+ UINT32 txop:2; //FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful.
+ UINT32 rsv:6;
+
+ UINT32 MCS:7;
+ UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz
+ UINT32 ShortGI:1;
+ UINT32 STBC:2; // 1: STBC support MCS =0-7, 2,3 : RESERVE
+ UINT32 Ifs:1; //
+ UINT32 rsv2:1;
+ UINT32 TxBF:1; // 3*3
+ UINT32 PHYMODE:2;
+ // Word 1
+ UINT32 ACK:1;
+ UINT32 NSEQ:1;
+ UINT32 BAWinSize:6;
+ UINT32 WirelessCliID:8;
+ UINT32 MPDUtotalByteCount:12;
+ UINT32 PacketId:4;
+ //Word2
+ UINT32 IV;
+ //Word3
+ UINT32 EIV;
+} TXWI_STRUC, *PTXWI_STRUC;
+#endif
+//
+// Rx descriptor format, Rx Ring
+//
+#ifdef RT2860
+#ifdef RT_BIG_ENDIAN
+typedef struct PACKED _RXD_STRUC {
+ // Word 0
+ UINT32 SDP0;
+ // Word 1
+ UINT32 DDONE:1;
+ UINT32 LS0:1;
+ UINT32 SDL0:14;
+ UINT32 Rsv:2;
+ UINT32 SDL1:14;
+ // Word 2
+ UINT32 SDP1;
+ // Word 3
+ UINT32 Rsv1:13;
+ UINT32 PlcpRssil:1;// To be moved
+ UINT32 PlcpSignal:1; // To be moved
+ UINT32 Decrypted:1; // this frame is being decrypted.
+ UINT32 AMPDU:1;
+ UINT32 L2PAD:1;
+ UINT32 RSSI:1;
+ UINT32 HTC:1;
+ UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header. obsolete.
+ UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid
+ UINT32 Crc:1; // 1: CRC error
+ UINT32 MyBss:1; // 1: this frame belongs to the same BSSID
+ UINT32 Bcast:1; // 1: this is a broadcast frame
+ UINT32 Mcast:1; // 1: this is a multicast frame
+ UINT32 U2M:1; // 1: this RX frame is unicast to me
+ UINT32 FRAG:1;
+ UINT32 NULLDATA:1;
+ UINT32 DATA:1;
+ UINT32 BA:1;
+
+} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC;
+#else
+typedef struct PACKED _RXD_STRUC {
+ // Word 0
+ UINT32 SDP0;
+ // Word 1
+ UINT32 SDL1:14;
+ UINT32 Rsv:2;
+ UINT32 SDL0:14;
+ UINT32 LS0:1;
+ UINT32 DDONE:1;
+ // Word 2
+ UINT32 SDP1;
+ // Word 3
+ UINT32 BA:1;
+ UINT32 DATA:1;
+ UINT32 NULLDATA:1;
+ UINT32 FRAG:1;
+ UINT32 U2M:1; // 1: this RX frame is unicast to me
+ UINT32 Mcast:1; // 1: this is a multicast frame
+ UINT32 Bcast:1; // 1: this is a broadcast frame
+ UINT32 MyBss:1; // 1: this frame belongs to the same BSSID
+ UINT32 Crc:1; // 1: CRC error
+ UINT32 CipherErr:2; // 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid
+ UINT32 AMSDU:1; // rx with 802.3 header, not 802.11 header.
+ UINT32 HTC:1;
+ UINT32 RSSI:1;
+ UINT32 L2PAD:1;
+ UINT32 AMPDU:1;
+ UINT32 Decrypted:1; // this frame is being decrypted.
+ UINT32 PlcpSignal:1; // To be moved
+ UINT32 PlcpRssil:1;// To be moved
+ UINT32 Rsv1:13;
+} RXD_STRUC, *PRXD_STRUC, RT28XX_RXD_STRUC, *PRT28XX_RXD_STRUC;
+#endif
+#endif // RT2860 //
+//
+// RXWI wireless information format, in PBF. invisible in driver.
+//
+#ifdef RT_BIG_ENDIAN
+typedef struct PACKED _RXWI_STRUC {
+ // Word 0
+ UINT32 TID:4;
+ UINT32 MPDUtotalByteCount:12;
+ UINT32 UDF:3;
+ UINT32 BSSID:3;
+ UINT32 KeyIndex:2;
+ UINT32 WirelessCliID:8;
+ // Word 1
+ UINT32 PHYMODE:2; // 1: this RX frame is unicast to me
+ UINT32 rsv:3;
+ UINT32 STBC:2;
+ UINT32 ShortGI:1;
+ UINT32 BW:1;
+ UINT32 MCS:7;
+ UINT32 SEQUENCE:12;
+ UINT32 FRAG:4;
+ // Word 2
+ UINT32 rsv1:8;
+ UINT32 RSSI2:8;
+ UINT32 RSSI1:8;
+ UINT32 RSSI0:8;
+ // Word 3
+ UINT32 rsv2:16;
+ UINT32 SNR1:8;
+ UINT32 SNR0:8;
+} RXWI_STRUC, *PRXWI_STRUC;
+#else
+typedef struct PACKED _RXWI_STRUC {
+ // Word 0
+ UINT32 WirelessCliID:8;
+ UINT32 KeyIndex:2;
+ UINT32 BSSID:3;
+ UINT32 UDF:3;
+ UINT32 MPDUtotalByteCount:12;
+ UINT32 TID:4;
+ // Word 1
+ UINT32 FRAG:4;
+ UINT32 SEQUENCE:12;
+ UINT32 MCS:7;
+ UINT32 BW:1;
+ UINT32 ShortGI:1;
+ UINT32 STBC:2;
+ UINT32 rsv:3;
+ UINT32 PHYMODE:2; // 1: this RX frame is unicast to me
+ //Word2
+ UINT32 RSSI0:8;
+ UINT32 RSSI1:8;
+ UINT32 RSSI2:8;
+ UINT32 rsv1:8;
+ //Word3
+ UINT32 SNR0:8;
+ UINT32 SNR1:8;
+ UINT32 rsv2:16;
+} RXWI_STRUC, *PRXWI_STRUC;
+#endif
+
+
+// =================================================================================
+// HOST-MCU communication data structure
+// =================================================================================
+
+//
+// H2M_MAILBOX_CSR: Host-to-MCU Mailbox
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _H2M_MAILBOX_STRUC {
+ struct {
+ UINT32 Owner:8;
+ UINT32 CmdToken:8; // 0xff tells MCU not to report CmdDoneInt after excuting the command
+ UINT32 HighByte:8;
+ UINT32 LowByte:8;
+ } field;
+ UINT32 word;
+} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC;
+#else
+typedef union _H2M_MAILBOX_STRUC {
+ struct {
+ UINT32 LowByte:8;
+ UINT32 HighByte:8;
+ UINT32 CmdToken:8;
+ UINT32 Owner:8;
+ } field;
+ UINT32 word;
+} H2M_MAILBOX_STRUC, *PH2M_MAILBOX_STRUC;
+#endif
+
+//
+// M2H_CMD_DONE_CSR: MCU-to-Host command complete indication
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _M2H_CMD_DONE_STRUC {
+ struct {
+ UINT32 CmdToken3;
+ UINT32 CmdToken2;
+ UINT32 CmdToken1;
+ UINT32 CmdToken0;
+ } field;
+ UINT32 word;
+} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC;
+#else
+typedef union _M2H_CMD_DONE_STRUC {
+ struct {
+ UINT32 CmdToken0;
+ UINT32 CmdToken1;
+ UINT32 CmdToken2;
+ UINT32 CmdToken3;
+ } field;
+ UINT32 word;
+} M2H_CMD_DONE_STRUC, *PM2H_CMD_DONE_STRUC;
+#endif
+
+
+
+//
+// MCU_LEDCS: MCU LED Control Setting.
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _MCU_LEDCS_STRUC {
+ struct {
+ UCHAR Polarity:1;
+ UCHAR LedMode:7;
+ } field;
+ UCHAR word;
+} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC;
+#else
+typedef union _MCU_LEDCS_STRUC {
+ struct {
+ UCHAR LedMode:7;
+ UCHAR Polarity:1;
+ } field;
+ UCHAR word;
+} MCU_LEDCS_STRUC, *PMCU_LEDCS_STRUC;
+#endif
+// =================================================================================
+// Register format
+// =================================================================================
+
+
+
+//NAV_TIME_CFG :NAV
+#ifdef RT_BIG_ENDIAN
+typedef union _NAV_TIME_CFG_STRUC {
+ struct {
+ USHORT rsv:6;
+ USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable
+ USHORT Eifs:9; // in unit of 1-us
+ UCHAR SlotTime; // in unit of 1-us
+ UCHAR Sifs; // in unit of 1-us
+ } field;
+ UINT32 word;
+} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC;
+#else
+typedef union _NAV_TIME_CFG_STRUC {
+ struct {
+ UCHAR Sifs; // in unit of 1-us
+ UCHAR SlotTime; // in unit of 1-us
+ USHORT Eifs:9; // in unit of 1-us
+ USHORT ZeroSifs:1; // Applied zero SIFS timer after OFDM RX 0: disable
+ USHORT rsv:6;
+ } field;
+ UINT32 word;
+} NAV_TIME_CFG_STRUC, *PNAV_TIME_CFG_STRUC;
+#endif
+
+
+
+
+
+//
+// RX_FILTR_CFG: /RX configuration register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union RX_FILTR_CFG_STRUC {
+ struct {
+ UINT32 :15;
+ UINT32 DropRsvCntlType:1;
+
+ UINT32 DropBAR:1; //
+ UINT32 DropBA:1; //
+ UINT32 DropPsPoll:1; // Drop Ps-Poll
+ UINT32 DropRts:1; // Drop Ps-Poll
+
+ UINT32 DropCts:1; // Drop Ps-Poll
+ UINT32 DropAck:1; // Drop Ps-Poll
+ UINT32 DropCFEnd:1; // Drop Ps-Poll
+ UINT32 DropCFEndAck:1; // Drop Ps-Poll
+
+ UINT32 DropDuplicate:1; // Drop duplicate frame
+ UINT32 DropBcast:1; // Drop broadcast frames
+ UINT32 DropMcast:1; // Drop multicast frames
+ UINT32 DropVerErr:1; // Drop version error frame
+
+ UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true
+ UINT32 DropNotToMe:1; // Drop not to me unicast frame
+ UINT32 DropPhyErr:1; // Drop physical error
+ UINT32 DropCRCErr:1; // Drop CRC error
+ } field;
+ UINT32 word;
+} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC;
+#else
+typedef union _RX_FILTR_CFG_STRUC {
+ struct {
+ UINT32 DropCRCErr:1; // Drop CRC error
+ UINT32 DropPhyErr:1; // Drop physical error
+ UINT32 DropNotToMe:1; // Drop not to me unicast frame
+ UINT32 DropNotMyBSSID:1; // Drop fram ToDs bit is true
+
+ UINT32 DropVerErr:1; // Drop version error frame
+ UINT32 DropMcast:1; // Drop multicast frames
+ UINT32 DropBcast:1; // Drop broadcast frames
+ UINT32 DropDuplicate:1; // Drop duplicate frame
+
+ UINT32 DropCFEndAck:1; // Drop Ps-Poll
+ UINT32 DropCFEnd:1; // Drop Ps-Poll
+ UINT32 DropAck:1; // Drop Ps-Poll
+ UINT32 DropCts:1; // Drop Ps-Poll
+
+ UINT32 DropRts:1; // Drop Ps-Poll
+ UINT32 DropPsPoll:1; // Drop Ps-Poll
+ UINT32 DropBA:1; //
+ UINT32 DropBAR:1; //
+
+ UINT32 DropRsvCntlType:1;
+ UINT32 :15;
+ } field;
+ UINT32 word;
+} RX_FILTR_CFG_STRUC, *PRX_FILTR_CFG_STRUC;
+#endif
+
+
+
+
+//
+// PHY_CSR4: RF serial control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _PHY_CSR4_STRUC {
+ struct {
+ UINT32 Busy:1; // 1: ASIC is busy execute RF programming.
+ UINT32 PLL_LD:1; // RF PLL_LD status
+ UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program
+ UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22)
+ UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip.
+ } field;
+ UINT32 word;
+} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC;
+#else
+typedef union _PHY_CSR4_STRUC {
+ struct {
+ UINT32 RFRegValue:24; // Register value (include register id) serial out to RF/IF chip.
+ UINT32 NumberOfBits:5; // Number of bits used in RFRegValue (I:20, RFMD:22)
+ UINT32 IFSelect:1; // 1: select IF to program, 0: select RF to program
+ UINT32 PLL_LD:1; // RF PLL_LD status
+ UINT32 Busy:1; // 1: ASIC is busy execute RF programming.
+ } field;
+ UINT32 word;
+} PHY_CSR4_STRUC, *PPHY_CSR4_STRUC;
+#endif
+
+
+//
+// SEC_CSR5: shared key table security mode register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _SEC_CSR5_STRUC {
+ struct {
+ UINT32 :1;
+ UINT32 Bss3Key3CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss3Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss3Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss3Key0CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss2Key3CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss2Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss2Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss2Key0CipherAlg:3;
+ } field;
+ UINT32 word;
+} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC;
+#else
+typedef union _SEC_CSR5_STRUC {
+ struct {
+ UINT32 Bss2Key0CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss2Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss2Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss2Key3CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss3Key0CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss3Key1CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss3Key2CipherAlg:3;
+ UINT32 :1;
+ UINT32 Bss3Key3CipherAlg:3;
+ UINT32 :1;
+ } field;
+ UINT32 word;
+} SEC_CSR5_STRUC, *PSEC_CSR5_STRUC;
+#endif
+
+
+//
+// HOST_CMD_CSR: For HOST to interrupt embedded processor
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _HOST_CMD_CSR_STRUC {
+ struct {
+ UINT32 Rsv:24;
+ UINT32 HostCommand:8;
+ } field;
+ UINT32 word;
+} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC;
+#else
+typedef union _HOST_CMD_CSR_STRUC {
+ struct {
+ UINT32 HostCommand:8;
+ UINT32 Rsv:24;
+ } field;
+ UINT32 word;
+} HOST_CMD_CSR_STRUC, *PHOST_CMD_CSR_STRUC;
+#endif
+
+
+//
+// AIFSN_CSR: AIFSN for each EDCA AC
+//
+
+
+
+//
+// E2PROM_CSR: EEPROM control register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _E2PROM_CSR_STRUC {
+ struct {
+ UINT32 Rsvd:25;
+ UINT32 LoadStatus:1; // 1:loading, 0:done
+ UINT32 Type:1; // 1: 93C46, 0:93C66
+ UINT32 EepromDO:1;
+ UINT32 EepromDI:1;
+ UINT32 EepromCS:1;
+ UINT32 EepromSK:1;
+ UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared.
+ } field;
+ UINT32 word;
+} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC;
+#else
+typedef union _E2PROM_CSR_STRUC {
+ struct {
+ UINT32 Reload:1; // Reload EEPROM content, write one to reload, self-cleared.
+ UINT32 EepromSK:1;
+ UINT32 EepromCS:1;
+ UINT32 EepromDI:1;
+ UINT32 EepromDO:1;
+ UINT32 Type:1; // 1: 93C46, 0:93C66
+ UINT32 LoadStatus:1; // 1:loading, 0:done
+ UINT32 Rsvd:25;
+ } field;
+ UINT32 word;
+} E2PROM_CSR_STRUC, *PE2PROM_CSR_STRUC;
+#endif
+
+
+// -------------------------------------------------------------------
+// E2PROM data layout
+// -------------------------------------------------------------------
+
+//
+// EEPROM antenna select format
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _EEPROM_ANTENNA_STRUC {
+ struct {
+ USHORT Rsv:4;
+ USHORT RfIcType:4; // see E2PROM document
+ USHORT TxPath:4; // 1: 1T, 2: 2T
+ USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R
+ } field;
+ USHORT word;
+} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC;
+#else
+typedef union _EEPROM_ANTENNA_STRUC {
+ struct {
+ USHORT RxPath:4; // 1: 1R, 2: 2R, 3: 3R
+ USHORT TxPath:4; // 1: 1T, 2: 2T
+ USHORT RfIcType:4; // see E2PROM document
+ USHORT Rsv:4;
+ } field;
+ USHORT word;
+} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef union _EEPROM_NIC_CINFIG2_STRUC {
+ struct {
+ USHORT Rsv2:6; // must be 0
+ USHORT BW40MAvailForA:1; // 0:enable, 1:disable
+ USHORT BW40MAvailForG:1; // 0:enable, 1:disable
+ USHORT EnableWPSPBC:1; // WPS PBC Control bit
+ USHORT BW40MSidebandForA:1;
+ USHORT BW40MSidebandForG:1;
+ USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable
+ USHORT ExternalLNAForA:1; // external LNA enable for 5G
+ USHORT ExternalLNAForG:1; // external LNA enable for 2.4G
+ USHORT DynamicTxAgcControl:1; //
+ USHORT HardwareRadioControl:1; // Whether RF is controlled by driver or HW. 1:enable hw control, 0:disable
+ } field;
+ USHORT word;
+} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC;
+#else
+typedef union _EEPROM_NIC_CINFIG2_STRUC {
+ struct {
+ USHORT HardwareRadioControl:1; // 1:enable, 0:disable
+ USHORT DynamicTxAgcControl:1; //
+ USHORT ExternalLNAForG:1; //
+ USHORT ExternalLNAForA:1; // external LNA enable for 2.4G
+ USHORT CardbusAcceleration:1; // !!! NOTE: 0 - enable, 1 - disable
+ USHORT BW40MSidebandForG:1;
+ USHORT BW40MSidebandForA:1;
+ USHORT EnableWPSPBC:1; // WPS PBC Control bit
+ USHORT BW40MAvailForG:1; // 0:enable, 1:disable
+ USHORT BW40MAvailForA:1; // 0:enable, 1:disable
+ USHORT Rsv2:6; // must be 0
+ } field;
+ USHORT word;
+} EEPROM_NIC_CONFIG2_STRUC, *PEEPROM_NIC_CONFIG2_STRUC;
+#endif
+
+//
+// TX_PWR Value valid range 0xFA(-6) ~ 0x24(36)
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _EEPROM_TX_PWR_STRUC {
+ struct {
+ CHAR Byte1; // High Byte
+ CHAR Byte0; // Low Byte
+ } field;
+ USHORT word;
+} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC;
+#else
+typedef union _EEPROM_TX_PWR_STRUC {
+ struct {
+ CHAR Byte0; // Low Byte
+ CHAR Byte1; // High Byte
+ } field;
+ USHORT word;
+} EEPROM_TX_PWR_STRUC, *PEEPROM_TX_PWR_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef union _EEPROM_VERSION_STRUC {
+ struct {
+ UCHAR Version; // High Byte
+ UCHAR FaeReleaseNumber; // Low Byte
+ } field;
+ USHORT word;
+} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC;
+#else
+typedef union _EEPROM_VERSION_STRUC {
+ struct {
+ UCHAR FaeReleaseNumber; // Low Byte
+ UCHAR Version; // High Byte
+ } field;
+ USHORT word;
+} EEPROM_VERSION_STRUC, *PEEPROM_VERSION_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef union _EEPROM_LED_STRUC {
+ struct {
+ USHORT Rsvd:3; // Reserved
+ USHORT LedMode:5; // Led mode.
+ USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting.
+ USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting.
+ USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting.
+ USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting.
+ USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting.
+ USHORT PolarityACT:1; // Polarity ACT setting.
+ USHORT PolarityRDY_A:1; // Polarity RDY_A setting.
+ USHORT PolarityRDY_G:1; // Polarity RDY_G setting.
+ } field;
+ USHORT word;
+} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC;
+#else
+typedef union _EEPROM_LED_STRUC {
+ struct {
+ USHORT PolarityRDY_G:1; // Polarity RDY_G setting.
+ USHORT PolarityRDY_A:1; // Polarity RDY_A setting.
+ USHORT PolarityACT:1; // Polarity ACT setting.
+ USHORT PolarityGPIO_0:1; // Polarity GPIO#0 setting.
+ USHORT PolarityGPIO_1:1; // Polarity GPIO#1 setting.
+ USHORT PolarityGPIO_2:1; // Polarity GPIO#2 setting.
+ USHORT PolarityGPIO_3:1; // Polarity GPIO#3 setting.
+ USHORT PolarityGPIO_4:1; // Polarity GPIO#4 setting.
+ USHORT LedMode:5; // Led mode.
+ USHORT Rsvd:3; // Reserved
+ } field;
+ USHORT word;
+} EEPROM_LED_STRUC, *PEEPROM_LED_STRUC;
+#endif
+
+#ifdef RT_BIG_ENDIAN
+typedef union _EEPROM_TXPOWER_DELTA_STRUC {
+ struct {
+ UCHAR TxPowerEnable:1;// Enable
+ UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value
+ UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4)
+ } field;
+ UCHAR value;
+} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC;
+#else
+typedef union _EEPROM_TXPOWER_DELTA_STRUC {
+ struct {
+ UCHAR DeltaValue:6; // Tx Power dalta value (MAX=4)
+ UCHAR Type:1; // 1: plus the delta value, 0: minus the delta value
+ UCHAR TxPowerEnable:1;// Enable
+ } field;
+ UCHAR value;
+} EEPROM_TXPOWER_DELTA_STRUC, *PEEPROM_TXPOWER_DELTA_STRUC;
+#endif
+
+//
+// QOS_CSR0: TXOP holder address0 register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _QOS_CSR0_STRUC {
+ struct {
+ UCHAR Byte3; // MAC address byte 3
+ UCHAR Byte2; // MAC address byte 2
+ UCHAR Byte1; // MAC address byte 1
+ UCHAR Byte0; // MAC address byte 0
+ } field;
+ UINT32 word;
+} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC;
+#else
+typedef union _QOS_CSR0_STRUC {
+ struct {
+ UCHAR Byte0; // MAC address byte 0
+ UCHAR Byte1; // MAC address byte 1
+ UCHAR Byte2; // MAC address byte 2
+ UCHAR Byte3; // MAC address byte 3
+ } field;
+ UINT32 word;
+} QOS_CSR0_STRUC, *PQOS_CSR0_STRUC;
+#endif
+
+//
+// QOS_CSR1: TXOP holder address1 register
+//
+#ifdef RT_BIG_ENDIAN
+typedef union _QOS_CSR1_STRUC {
+ struct {
+ UCHAR Rsvd1;
+ UCHAR Rsvd0;
+ UCHAR Byte5; // MAC address byte 5
+ UCHAR Byte4; // MAC address byte 4
+ } field;
+ UINT32 word;
+} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC;
+#else
+typedef union _QOS_CSR1_STRUC {
+ struct {
+ UCHAR Byte4; // MAC address byte 4
+ UCHAR Byte5; // MAC address byte 5
+ UCHAR Rsvd0;
+ UCHAR Rsvd1;
+ } field;
+ UINT32 word;
+} QOS_CSR1_STRUC, *PQOS_CSR1_STRUC;
+#endif
+
+#define RF_CSR_CFG 0x500
+#ifdef RT_BIG_ENDIAN
+typedef union _RF_CSR_CFG_STRUC {
+ struct {
+ UINT Rsvd1:14; // Reserved
+ UINT RF_CSR_KICK:1; // kick RF register read/write
+ UINT RF_CSR_WR:1; // 0: read 1: write
+ UINT Rsvd2:3; // Reserved
+ UINT TESTCSR_RFACC_REGNUM:5; // RF register ID
+ UINT RF_CSR_DATA:8; // DATA
+ } field;
+ UINT word;
+} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC;
+#else
+typedef union _RF_CSR_CFG_STRUC {
+ struct {
+ UINT RF_CSR_DATA:8; // DATA
+ UINT TESTCSR_RFACC_REGNUM:5; // RF register ID
+ UINT Rsvd2:3; // Reserved
+ UINT RF_CSR_WR:1; // 0: read 1: write
+ UINT RF_CSR_KICK:1; // kick RF register read/write
+ UINT Rsvd1:14; // Reserved
+ } field;
+ UINT word;
+} RF_CSR_CFG_STRUC, *PRF_CSR_CFG_STRUC;
+#endif
+
+#endif // __RT28XX_H__
diff --git a/drivers/staging/rt2860/rt_ate.c b/drivers/staging/rt2860/rt_ate.c
new file mode 100644
index 000000000000..f3316ec0b156
--- /dev/null
+++ b/drivers/staging/rt2860/rt_ate.c
@@ -0,0 +1,6025 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#include "rt_config.h"
+
+#ifdef RALINK_ATE
+UCHAR TemplateFrame[24] = {0x08/* Data type */,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xAA,0xBB,0x12,0x34,0x56,0x00,0x11,0x22,0xAA,0xBB,0xCC,0x00,0x00}; // 802.11 MAC Header, Type:Data, Length:24bytes
+extern RTMP_RF_REGS RF2850RegTable[];
+extern UCHAR NUM_OF_2850_CHNL;
+
+static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; /* CCK Mode. */
+static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; /* OFDM Mode. */
+static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}; /* HT Mix Mode. */
+
+static INT TxDmaBusy(
+ IN PRTMP_ADAPTER pAd);
+
+static INT RxDmaBusy(
+ IN PRTMP_ADAPTER pAd);
+
+static VOID RtmpDmaEnable(
+ IN PRTMP_ADAPTER pAd,
+ IN INT Enable);
+
+static VOID BbpSoftReset(
+ IN PRTMP_ADAPTER pAd);
+
+static VOID RtmpRfIoWrite(
+ IN PRTMP_ADAPTER pAd);
+
+static INT ATESetUpFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 TxIdx);
+
+static INT ATETxPwrHandler(
+ IN PRTMP_ADAPTER pAd,
+ IN char index);
+
+static INT ATECmdHandler(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+static int CheckMCSValid(
+ IN UCHAR Mode,
+ IN UCHAR Mcs);
+
+#ifdef RT2860
+static VOID ATEWriteTxWI(
+ IN PRTMP_ADAPTER pAd,
+ IN PTXWI_STRUC pOutTxWI,
+ IN BOOLEAN FRAG,
+ IN BOOLEAN CFACK,
+ IN BOOLEAN InsTimestamp,
+ IN BOOLEAN AMPDU,
+ IN BOOLEAN Ack,
+ IN BOOLEAN NSeq, // HW new a sequence.
+ IN UCHAR BASize,
+ IN UCHAR WCID,
+ IN ULONG Length,
+ IN UCHAR PID,
+ IN UCHAR TID,
+ IN UCHAR TxRate,
+ IN UCHAR Txopmode,
+ IN BOOLEAN CfAck,
+ IN HTTRANSMIT_SETTING *pTransmit);
+#endif // RT2860 //
+
+
+static VOID SetJapanFilter(
+ IN PRTMP_ADAPTER pAd);
+
+/*=========================end of prototype=========================*/
+
+#ifdef RT2860
+static INT TxDmaBusy(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT result;
+ WPDMA_GLO_CFG_STRUC GloCfg;
+
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
+ if (GloCfg.field.TxDMABusy)
+ result = 1;
+ else
+ result = 0;
+
+ return result;
+}
+
+static INT RxDmaBusy(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT result;
+ WPDMA_GLO_CFG_STRUC GloCfg;
+
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
+ if (GloCfg.field.RxDMABusy)
+ result = 1;
+ else
+ result = 0;
+
+ return result;
+}
+
+static VOID RtmpDmaEnable(
+ IN PRTMP_ADAPTER pAd,
+ IN INT Enable)
+{
+ BOOLEAN value;
+ ULONG WaitCnt;
+ WPDMA_GLO_CFG_STRUC GloCfg;
+
+ value = Enable > 0 ? 1 : 0;
+
+ // check DMA is in busy mode.
+ WaitCnt = 0;
+ while (TxDmaBusy(pAd) || RxDmaBusy(pAd))
+ {
+ RTMPusecDelay(10);
+ if (WaitCnt++ > 100)
+ break;
+ }
+
+ RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); // disable DMA
+ GloCfg.field.EnableTxDMA = value;
+ GloCfg.field.EnableRxDMA = value;
+ RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); // abort all TX rings
+ RTMPusecDelay(5000);
+
+ return;
+}
+#endif // RT2860 //
+
+
+static VOID BbpSoftReset(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR BbpData = 0;
+
+ // Soft reset, set BBP R21 bit0=1->0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData);
+ BbpData |= 0x00000001; //set bit0=1
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData);
+
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &BbpData);
+ BbpData &= ~(0x00000001); //set bit0=0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, BbpData);
+
+ return;
+}
+
+static VOID RtmpRfIoWrite(
+ IN PRTMP_ADAPTER pAd)
+{
+ // Set RF value 1's set R3[bit2] = [0]
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+ RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+ RTMPusecDelay(200);
+
+ // Set RF value 2's set R3[bit2] = [1]
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+ RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+ RTMPusecDelay(200);
+
+ // Set RF value 3's set R3[bit2] = [0]
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
+ RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
+ RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
+
+ return;
+}
+
+static int CheckMCSValid(
+ UCHAR Mode,
+ UCHAR Mcs)
+{
+ int i;
+ PCHAR pRateTab;
+
+ switch(Mode)
+ {
+ case 0:
+ pRateTab = CCKRateTable;
+ break;
+ case 1:
+ pRateTab = OFDMRateTable;
+ break;
+ case 2:
+ case 3:
+ pRateTab = HTMIXRateTable;
+ break;
+ default:
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("unrecognizable Tx Mode %d\n", Mode));
+ return -1;
+ break;
+ }
+
+ i = 0;
+ while(pRateTab[i] != -1)
+ {
+ if (pRateTab[i] == Mcs)
+ return 0;
+ i++;
+ }
+
+ return -1;
+}
+
+#if 1
+static INT ATETxPwrHandler(
+ IN PRTMP_ADAPTER pAd,
+ IN char index)
+{
+ ULONG R;
+ CHAR TxPower;
+ UCHAR Bbp94 = 0;
+ BOOLEAN bPowerReduce = FALSE;
+
+#ifdef RALINK_28xx_QA
+ if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE))
+ {
+ /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power
+ ** are not synchronized.
+ */
+/*
+ pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx;
+ pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx;
+*/
+ return 0;
+ }
+ else
+#endif // RALINK_28xx_QA //
+ {
+ TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1;
+
+ if (pAd->ate.Channel <= 14)
+ {
+ if (TxPower > 31)
+ {
+ //
+ // R3, R4 can't large than 31 (0x24), 31 ~ 36 used by BBP 94
+ //
+ R = 31;
+ if (TxPower <= 36)
+ Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31);
+ }
+ else if (TxPower < 0)
+ {
+ //
+ // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94
+ //
+ R = 0;
+ if (TxPower >= -6)
+ Bbp94 = BBPR94_DEFAULT + TxPower;
+ }
+ else
+ {
+ // 0 ~ 31
+ R = (ULONG) TxPower;
+ Bbp94 = BBPR94_DEFAULT;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%ld, BBP_R94=%d)\n", __func__, TxPower, R, Bbp94));
+ }
+ else// 5.5 GHz
+ {
+ if (TxPower > 15)
+ {
+ //
+ // R3, R4 can't large than 15 (0x0F)
+ //
+ R = 15;
+ }
+ else if (TxPower < 0)
+ {
+ //
+ // R3, R4 can't less than 0
+ //
+ // -1 ~ -7
+ ASSERT((TxPower >= -7));
+ R = (ULONG)(TxPower + 7);
+ bPowerReduce = TRUE;
+ }
+ else
+ {
+ // 0 ~ 15
+ R = (ULONG) TxPower;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R=%lu)\n", __func__, TxPower, R));
+ }
+
+ if (pAd->ate.Channel <= 14)
+ {
+ if (index == 0)
+ {
+ R = R << 9; // shift TX power control to correct RF(R3) register bit position
+ R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+ pAd->LatchRfRegs.R3 = R;
+ }
+ else
+ {
+ R = R << 6; // shift TX power control to correct RF(R4) register bit position
+ R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+ pAd->LatchRfRegs.R4 = R;
+ }
+ }
+ else// 5.5GHz
+ {
+ if (bPowerReduce == FALSE)
+ {
+ if (index == 0)
+ {
+ R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position
+ R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+ pAd->LatchRfRegs.R3 = R;
+ }
+ else
+ {
+ R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position
+ R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+ pAd->LatchRfRegs.R4 = R;
+ }
+ }
+ else
+ {
+ if (index == 0)
+ {
+ R = (R << 10); // shift TX power control to correct RF(R3) register bit position
+ R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+
+ /* Clear bit 9 of R3 to reduce 7dB. */
+ pAd->LatchRfRegs.R3 = (R & (~(1 << 9)));
+ }
+ else
+ {
+ R = (R << 7); // shift TX power control to correct RF(R4) register bit position
+ R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+
+ /* Clear bit 6 of R4 to reduce 7dB. */
+ pAd->LatchRfRegs.R4 = (R & (~(1 << 6)));
+ }
+ }
+ }
+
+ RtmpRfIoWrite(pAd);
+
+ return 0;
+ }
+}
+#else// 1 //
+static INT ATETxPwrHandler(
+ IN PRTMP_ADAPTER pAd,
+ IN char index)
+{
+ ULONG R;
+ CHAR TxPower;
+ UCHAR Bbp94 = 0;
+
+#ifdef RALINK_28xx_QA
+ if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE))
+ {
+ // TODO: how to get current TxPower0/1 from pAd->LatchRfRegs ?
+ /* When QA is used for Tx, pAd->ate.TxPower0/1 and real tx power
+ ** are not synchronized.
+ */
+/*
+ pAd->ate.TxPower0 = pAd->LatchRfRegs.xxx;
+ pAd->ate.TxPower1 = pAd->LatchRfRegs.xxx;
+*/
+ return 0;
+ }
+ else
+#endif // RALINK_28xx_QA //
+ {
+ TxPower = index == 0 ? pAd->ate.TxPower0 : pAd->ate.TxPower1;
+
+ if (TxPower > 31)
+ {
+ //
+ // R3, R4 can't large than 36 (0x24), 31 ~ 36 used by BBP 94
+ //
+ R = 31;
+ if (TxPower <= 36)
+ Bbp94 = BBPR94_DEFAULT + (UCHAR)(TxPower - 31);
+ }
+ else if (TxPower < 0)
+ {
+ //
+ // R3, R4 can't less than 0, -1 ~ -6 used by BBP 94
+ //
+ R = 0;
+ if (TxPower >= -6)
+ Bbp94 = BBPR94_DEFAULT + TxPower;
+ }
+ else
+ {
+ // 0 ~ 31
+ R = (ULONG) TxPower;
+ Bbp94 = BBPR94_DEFAULT;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("%s (TxPower=%d, R3=%ld, BBP_R94=%d)\n", __func__, TxPower, R, Bbp94));
+
+ if (pAd->ate.Channel <= 14)
+ {
+ if (index == 0)
+ {
+ R = R << 9; // shift TX power control to correct RF(R3) register bit position
+ R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+ pAd->LatchRfRegs.R3 = R;
+ }
+ else
+ {
+ R = R << 6; // shift TX power control to correct RF(R4) register bit position
+ R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+ pAd->LatchRfRegs.R4 = R;
+ }
+ }
+ else
+ {
+ if (index == 0)
+ {
+ R = (R << 10) | (1 << 9); // shift TX power control to correct RF(R3) register bit position
+ R |= (pAd->LatchRfRegs.R3 & 0xffffc1ff);
+ pAd->LatchRfRegs.R3 = R;
+ }
+ else
+ {
+ R = (R << 7) | (1 << 6); // shift TX power control to correct RF(R4) register bit position
+ R |= (pAd->LatchRfRegs.R4 & 0xfffff83f);
+ pAd->LatchRfRegs.R4 = R;
+ }
+ }
+
+ RtmpRfIoWrite(pAd);
+
+ return 0;
+ }
+}
+#endif // 1 //
+/*
+ ==========================================================================
+ Description:
+ Set ATE operation mode to
+ 0. ATESTART = Start ATE Mode
+ 1. ATESTOP = Stop ATE Mode
+ 2. TXCONT = Continuous Transmit
+ 3. TXCARR = Transmit Carrier
+ 4. TXFRAME = Transmit Frames
+ 5. RXFRAME = Receive Frames
+#ifdef RALINK_28xx_QA
+ 6. TXSTOP = Stop Any Type of Transmition
+ 7. RXSTOP = Stop Receiving Frames
+#endif // RALINK_28xx_QA //
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+#ifdef RT2860
+static INT ATECmdHandler(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT32 Value = 0;
+ UCHAR BbpData;
+ UINT32 MacData = 0;
+ PTXD_STRUC pTxD;
+ INT index;
+ UINT i=0, atemode;
+ PRXD_STRUC pRxD;
+ PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE];
+#ifndef UCOS
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+#endif // UCOS //
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("===> ATECmdHandler()\n"));
+
+ ATEAsicSwitchChannel(pAd);
+ AsicLockChannel(pAd, pAd->ate.Channel);
+
+ RTMPusecDelay(5000);
+
+ // read MAC_SYS_CTRL and backup MAC_SYS_CTRL value.
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+
+ // Default value in BBP R22 is 0x0.
+ BbpData = 0;
+
+ // clean bit4 to stop continuous Tx production test.
+ MacData &= 0xFFFFFFEF;
+
+ if (!strcmp(arg, "ATESTART")) //Enter ATE mode and set Tx/Rx Idle
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTART\n"));
+
+#ifndef UCOS
+ // check if we have removed the firmware
+ if (!(ATE_ON(pAd)))
+ {
+ NICEraseFirmware(pAd);
+ }
+#endif // !UCOS //
+ atemode = pAd->ate.Mode;
+ pAd->ate.Mode = ATE_START;
+// pAd->ate.TxDoneCount = pAd->ate.TxCount;
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+ if (atemode & ATE_TXCARR)
+ {
+ // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0]
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+ }
+ else if (atemode & ATE_TXCARRSUPP)
+ {
+ // No Cont. TX set BBP R22 bit7=0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= ~(1 << 7); //set bit7=0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+ // No Carrier Suppression set BBP R24 bit0=0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData);
+ BbpData &= 0xFFFFFFFE; //clear bit0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData);
+ }
+ // We should free some resource which was allocated when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT.
+ else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP))
+ {
+ PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE];
+
+ if (atemode & ATE_TXCONT)
+ {
+ // No Cont. TX set BBP R22 bit7=0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= ~(1 << 7); //set bit7=0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+ }
+ // Abort Tx, Rx DMA.
+ RtmpDmaEnable(pAd, 0);
+ for (i=0; i<TX_RING_SIZE; i++)
+ {
+ PNDIS_PACKET pPacket;
+
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ pTxD->DMADONE = 0;
+ pPacket = pTxRing->Cell[i].pNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNdisPacket as NULL after clear
+ pTxRing->Cell[i].pNdisPacket = NULL;
+
+ pPacket = pTxRing->Cell[i].pNextNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNextNdisPacket as NULL after clear
+ pTxRing->Cell[i].pNextNdisPacket = NULL;
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif
+ }
+ // Start Tx, RX DMA
+ RtmpDmaEnable(pAd, 1);
+ }
+ // reset Rx statistics.
+ pAd->ate.LastSNR0 = 0;
+ pAd->ate.LastSNR1 = 0;
+ pAd->ate.LastRssi0 = 0;
+ pAd->ate.LastRssi1 = 0;
+ pAd->ate.LastRssi2 = 0;
+ pAd->ate.AvgRssi0 = 0;
+ pAd->ate.AvgRssi1 = 0;
+ pAd->ate.AvgRssi2 = 0;
+ pAd->ate.AvgRssi0X8 = 0;
+ pAd->ate.AvgRssi1X8 = 0;
+ pAd->ate.AvgRssi2X8 = 0;
+ pAd->ate.NumOfAvgRssiSample = 0;
+
+#ifdef RALINK_28xx_QA
+ // Tx frame
+ pAd->ate.bQATxStart = FALSE;
+ pAd->ate.bQARxStart = FALSE;
+ pAd->ate.seq = 0;
+
+ // counters
+ pAd->ate.U2M = 0;
+ pAd->ate.OtherData = 0;
+ pAd->ate.Beacon = 0;
+ pAd->ate.OtherCount = 0;
+ pAd->ate.TxAc0 = 0;
+ pAd->ate.TxAc1 = 0;
+ pAd->ate.TxAc2 = 0;
+ pAd->ate.TxAc3 = 0;
+ pAd->ate.TxHCCA = 0;
+ pAd->ate.TxMgmt = 0;
+ pAd->ate.RSSI0 = 0;
+ pAd->ate.RSSI1 = 0;
+ pAd->ate.RSSI2 = 0;
+ pAd->ate.SNR0 = 0;
+ pAd->ate.SNR1 = 0;
+
+ // control
+ pAd->ate.TxDoneCount = 0;
+ pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running
+#endif // RALINK_28xx_QA //
+
+ // Soft reset BBP.
+ BbpSoftReset(pAd);
+
+
+#ifdef CONFIG_STA_SUPPORT
+ //
+ // LinkDown() has "AsicDisableSync();" and "RTMP_BBP_IO_R/W8_BY_REG_ID();" inside.
+ //
+// LinkDown(pAd, FALSE);
+// AsicEnableBssSync(pAd);
+#ifndef UCOS
+ netif_stop_queue(pAd->net_dev);
+#endif // !UCOS //
+ //
+ // If we skip "LinkDown()", we should disable protection
+ // to prevent from sending out RTS or CTS-to-self.
+ //
+ ATEDisableAsicProtect(pAd);
+ RTMPStationStop(pAd);
+#endif // CONFIG_STA_SUPPORT //
+
+ /* Disable Tx */
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 2);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+ /* Disable Rx */
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ }
+ else if (!strcmp(arg, "ATESTOP"))
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: ATESTOP\n"));
+
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData); // recover the MAC_SYS_CTRL register back.
+
+ // Disable Tx, Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= (0xfffffff3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+ // Abort Tx, RX DMA.
+ RtmpDmaEnable(pAd, 0);
+
+#ifndef UCOS
+ pAd->ate.bFWLoading = TRUE;
+ Status = NICLoadFirmware(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("NICLoadFirmware failed, Status[=0x%08x]\n", Status));
+ return FALSE;
+ }
+#endif // !UCOS //
+ pAd->ate.Mode = ATE_STOP;
+
+
+#ifdef CONFIG_STA_SUPPORT
+ //
+ // Even the firmware has been loaded,
+ // we still could use ATE_BBP_IO_READ8_BY_REG_ID().
+ // But this is not suggested.
+ //
+ BbpSoftReset(pAd);
+#endif // CONFIG_STA_SUPPORT //
+
+ NICDisableInterrupt(pAd);
+
+ NICInitializeAdapter(pAd, TRUE);
+
+
+ // Reinitialize Rx Ring before Rx DMA is enabled.
+ // The nightmare of >>>RxCoherent<<< was gone !
+ for (index = 0; index < RX_RING_SIZE; index++)
+ {
+ pRxD = (PRXD_STRUC) pAd->RxRing.Cell[index].AllocVa;
+ pRxD->DDONE = 0;
+ }
+
+ // We should read EEPROM for all cases.
+ NICReadEEPROMParameters(pAd, NULL);
+ NICInitAsicFromEEPROM(pAd);
+
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+ //
+ // Enable Interrupt
+ //
+
+ //
+ // These steps are only for APAutoSelectChannel().
+ //
+#if 0
+ //pAd->bStaFifoTest = TRUE;
+ pAd->int_enable_reg = ((DELAYINTMASK) | (RxINT|TxDataInt|TxMgmtInt)) & ~(0x03);
+ pAd->int_disable_mask = 0;
+ pAd->int_pending = 0;
+#endif
+ RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); // clear garbage interrupts
+ NICEnableInterrupt(pAd);
+
+
+/*=========================================================================*/
+ /* restore RX_FILTR_CFG */
+#ifdef CONFIG_STA_SUPPORT
+ /* restore RX_FILTR_CFG due to that QA maybe set it to 0x3 */
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL);
+#endif // CONFIG_STA_SUPPORT //
+/*=========================================================================*/
+
+ // Enable Tx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= (1 << 2);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+ // Enable Tx, Rx DMA.
+ RtmpDmaEnable(pAd, 1);
+
+ // Enable Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= (1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+
+#ifdef CONFIG_STA_SUPPORT
+ RTMPStationStart(pAd);
+#endif // CONFIG_STA_SUPPORT //
+#ifndef UCOS
+ netif_start_queue(pAd->net_dev);
+#endif // !UCOS //
+ }
+ else if (!strcmp(arg, "TXCARR")) // Tx Carrier
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCARR\n"));
+ pAd->ate.Mode |= ATE_TXCARR;
+
+ // QA has done the following steps if it is used.
+ if (pAd->ate.bQATxStart == FALSE)
+ {
+ // Soft reset BBP.
+ BbpSoftReset(pAd);
+
+ // Carrier Test set BBP R22 bit7=1, bit6=1, bit[5~0]=0x01
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0]
+ BbpData |= 0x000000C1; //set bit7=1, bit6=1, bit[5~0]=0x01
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+ // set MAC_SYS_CTRL(0x1004) Continuous Tx Production Test (bit4) = 1
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value = Value | 0x00000010;
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ }
+ }
+ else if (!strcmp(arg, "TXCONT")) // Tx Continue
+ {
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ /* set MAC_SYS_CTRL(0x1004) bit4(Continuous Tx Production Test)
+ and bit2(MAC TX enable) back to zero. */
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+ MacData &= 0xFFFFFFEB;
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+ // set BBP R22 bit7=0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= 0xFFFFFF7F; //set bit7=0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+ }
+
+ /* for TxCont mode.
+ ** Step 1: Send 50 packets first then wait for a moment.
+ ** Step 2: Send more 50 packet then start continue mode.
+ */
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXCONT\n"));
+ // Step 1: send 50 packets first.
+ pAd->ate.Mode |= ATE_TXCONT;
+ pAd->ate.TxCount = 50;
+ /* Do it after Tx/Rx DMA is aborted. */
+// pAd->ate.TxDoneCount = 0;
+
+ // Soft reset BBP.
+ BbpSoftReset(pAd);
+
+ // Abort Tx, RX DMA.
+ RtmpDmaEnable(pAd, 0);
+
+ // Fix can't smooth kick
+ {
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx);
+ pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
+ pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx);
+ }
+
+ pAd->ate.TxDoneCount = 0;
+
+ /* Only needed if we have to send some normal frames. */
+ SetJapanFilter(pAd);
+
+ for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++)
+ {
+ PNDIS_PACKET pPacket;
+ UINT32 TxIdx = pTxRing->TxCpuIdx;
+
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ // Clean current cell.
+ pPacket = pTxRing->Cell[TxIdx].pNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNdisPacket as NULL after clear
+ pTxRing->Cell[TxIdx].pNdisPacket = NULL;
+
+ pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNextNdisPacket as NULL after clear
+ pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif
+
+ if (ATESetUpFrame(pAd, TxIdx) != 0)
+ break;
+
+ INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE);
+ }
+
+ // Setup frame format.
+ ATESetUpFrame(pAd, pTxRing->TxCpuIdx);
+
+ // Start Tx, RX DMA.
+ RtmpDmaEnable(pAd, 1);
+
+ // Enable Tx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= (1 << 2);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+ // Disable Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ pAd->ate.TxStatus = 1;
+ //pAd->ate.Repeat = 0;
+ }
+#endif // RALINK_28xx_QA //
+
+ // kick Tx-Ring.
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx);
+
+ RTMPusecDelay(5000);
+
+
+ // Step 2: send more 50 packets then start continue mode.
+ // Abort Tx, RX DMA.
+ RtmpDmaEnable(pAd, 0);
+
+ // Cont. TX set BBP R22 bit7=1
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData |= 0x00000080; //set bit7=1
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+ pAd->ate.TxCount = 50;
+
+ // Fix can't smooth kick
+ {
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx);
+ pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
+ pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx);
+ }
+
+ pAd->ate.TxDoneCount = 0;
+
+ SetJapanFilter(pAd);
+
+ for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++)
+ {
+ PNDIS_PACKET pPacket;
+ UINT32 TxIdx = pTxRing->TxCpuIdx;
+
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ // clean current cell.
+ pPacket = pTxRing->Cell[TxIdx].pNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNdisPacket as NULL after clear
+ pTxRing->Cell[TxIdx].pNdisPacket = NULL;
+
+ pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNextNdisPacket as NULL after clear
+ pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif
+
+ if (ATESetUpFrame(pAd, TxIdx) != 0)
+ break;
+
+ INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE);
+ }
+
+ ATESetUpFrame(pAd, pTxRing->TxCpuIdx);
+
+ // Start Tx, RX DMA.
+ RtmpDmaEnable(pAd, 1);
+
+ // Enable Tx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= (1 << 2);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+ // Disable Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ pAd->ate.TxStatus = 1;
+ //pAd->ate.Repeat = 0;
+ }
+#endif // RALINK_28xx_QA //
+
+ // kick Tx-Ring.
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx);
+
+ RTMPusecDelay(500);
+
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacData);
+ MacData |= 0x00000010;
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+ }
+ else if (!strcmp(arg, "TXFRAME")) // Tx Frames
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXFRAME(Count=%d)\n", pAd->ate.TxCount));
+ pAd->ate.Mode |= ATE_TXFRAME;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+ // Soft reset BBP.
+ BbpSoftReset(pAd);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+ // Abort Tx, RX DMA.
+ RtmpDmaEnable(pAd, 0);
+
+ // Fix can't smooth kick
+ {
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * 0x10, &pTxRing->TxDmaIdx);
+ pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx;
+ pTxRing->TxCpuIdx = pTxRing->TxDmaIdx;
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * 0x10, pTxRing->TxCpuIdx);
+ }
+
+ pAd->ate.TxDoneCount = 0;
+
+ SetJapanFilter(pAd);
+
+ for (i = 0; (i < TX_RING_SIZE-1) && (i < pAd->ate.TxCount); i++)
+ {
+ PNDIS_PACKET pPacket;
+ UINT32 TxIdx = pTxRing->TxCpuIdx;
+
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ // Clean current cell.
+ pPacket = pTxRing->Cell[TxIdx].pNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNdisPacket as NULL after clear
+ pTxRing->Cell[TxIdx].pNdisPacket = NULL;
+
+ pPacket = pTxRing->Cell[TxIdx].pNextNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNextNdisPacket as NULL after clear
+ pTxRing->Cell[TxIdx].pNextNdisPacket = NULL;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif
+
+ if (ATESetUpFrame(pAd, TxIdx) != 0)
+ break;
+
+ INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE);
+
+ }
+
+ ATESetUpFrame(pAd, pTxRing->TxCpuIdx);
+
+ // Start Tx, Rx DMA.
+ RtmpDmaEnable(pAd, 1);
+
+ // Enable Tx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= (1 << 2);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+#ifdef RALINK_28xx_QA
+ // add this for LoopBack mode
+ if (pAd->ate.bQARxStart == FALSE)
+ {
+ // Disable Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ }
+
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ pAd->ate.TxStatus = 1;
+ //pAd->ate.Repeat = 0;
+ }
+#else
+ // Disable Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+#endif // RALINK_28xx_QA //
+
+ RTMP_IO_READ32(pAd, TX_DTX_IDX0 + QID_AC_BE * RINGREG_DIFF, &pAd->TxRing[QID_AC_BE].TxDmaIdx);
+ // kick Tx-Ring.
+ RTMP_IO_WRITE32(pAd, TX_CTX_IDX0 + QID_AC_BE * RINGREG_DIFF, pAd->TxRing[QID_AC_BE].TxCpuIdx);
+
+ pAd->RalinkCounters.KickTxCount++;
+ }
+#ifdef RALINK_28xx_QA
+ else if (!strcmp(arg, "TXSTOP"))
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: TXSTOP\n"));
+ atemode = pAd->ate.Mode;
+ pAd->ate.Mode &= ATE_TXSTOP;
+ pAd->ate.bQATxStart = FALSE;
+// pAd->ate.TxDoneCount = pAd->ate.TxCount;
+
+ if (atemode & ATE_TXCARR)
+ {
+ // No Carrier Test set BBP R22 bit7=0, bit6=0, bit[5~0]=0x0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= 0xFFFFFF00; //clear bit7, bit6, bit[5~0]
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+ }
+ else if (atemode & ATE_TXCARRSUPP)
+ {
+ // No Cont. TX set BBP R22 bit7=0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= ~(1 << 7); //set bit7=0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+
+ // No Carrier Suppression set BBP R24 bit0=0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R24, &BbpData);
+ BbpData &= 0xFFFFFFFE; //clear bit0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, BbpData);
+ }
+ // We should free some resource which allocate when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT.
+ else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP))
+ {
+
+ PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE];
+
+ if (atemode & ATE_TXCONT)
+ {
+ // No Cont. TX set BBP R22 bit7=0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &BbpData);
+ BbpData &= ~(1 << 7); //set bit7=0
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+ }
+
+ // Abort Tx, Rx DMA.
+ RtmpDmaEnable(pAd, 0);
+ for (i=0; i<TX_RING_SIZE; i++)
+ {
+ PNDIS_PACKET pPacket;
+
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC)pAd->TxRing[QID_AC_BE].Cell[i].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+#endif
+ pTxD->DMADONE = 0;
+ pPacket = pTxRing->Cell[i].pNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNdisPacket as NULL after clear
+ pTxRing->Cell[i].pNdisPacket = NULL;
+
+ pPacket = pTxRing->Cell[i].pNextNdisPacket;
+ if (pPacket)
+ {
+ PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, PCI_DMA_TODEVICE);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS);
+ }
+ //Always assign pNextNdisPacket as NULL after clear
+ pTxRing->Cell[i].pNextNdisPacket = NULL;
+#ifdef RT_BIG_ENDIAN
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif
+ }
+ // Enable Tx, Rx DMA
+ RtmpDmaEnable(pAd, 1);
+
+ }
+
+ // control
+// pAd->ate.TxDoneCount = 0;
+ pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running
+
+ // Soft reset BBP.
+ BbpSoftReset(pAd);
+
+ // Disable Tx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 2);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ }
+ else if (!strcmp(arg, "RXSTOP"))
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXSTOP\n"));
+ atemode = pAd->ate.Mode;
+ pAd->ate.Mode &= ATE_RXSTOP;
+ pAd->ate.bQARxStart = FALSE;
+// pAd->ate.TxDoneCount = pAd->ate.TxCount;
+
+ if (atemode & ATE_TXCARR)
+ {
+ ;
+ }
+ else if (atemode & ATE_TXCARRSUPP)
+ {
+ ;
+ }
+
+ // We should free some resource which was allocated when ATE_TXFRAME , ATE_STOP, and ATE_TXCONT.
+ else if ((atemode & ATE_TXFRAME) || (atemode == ATE_STOP))
+ {
+ if (atemode & ATE_TXCONT)
+ {
+ ;
+ }
+ }
+
+ // control
+// pAd->ate.TxDoneCount = 0;
+// pAd->ate.TxStatus = 0; // task Tx status // 0 --> task is idle, 1 --> task is running
+
+ // Soft reset BBP.
+ BbpSoftReset(pAd);
+
+ // Disable Rx
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ }
+#endif // RALINK_28xx_QA //
+ else if (!strcmp(arg, "RXFRAME")) // Rx Frames
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: RXFRAME\n"));
+
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, BbpData);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacData);
+
+ pAd->ate.Mode |= ATE_RXFRAME;
+
+ // Disable Tx of MAC block.
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value &= ~(1 << 2);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+
+ // Enable Rx of MAC block.
+ RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value);
+ Value |= (1 << 3);
+ RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value);
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATE: Invalid arg!\n"));
+ return FALSE;
+ }
+ RTMPusecDelay(5000);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== ATECmdHandler()\n"));
+
+ return TRUE;
+}
+#endif // RT2860 //
+/* */
+/* */
+/*=======================End of RT2860=======================*/
+
+
+/*======================Start of RT2870======================*/
+/* */
+/* */
+
+
+INT Set_ATE_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ if (ATECmdHandler(pAd, arg))
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Success\n"));
+
+
+ return TRUE;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_Proc Failed\n"));
+ return FALSE;
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE ADDR1=DA for TxFrame(AP : To DS = 0 ; From DS = 1)
+ or
+ Set ATE ADDR3=DA for TxFrame(STA : To DS = 1 ; From DS = 0)
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_DA_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ CHAR *value;
+ INT i;
+
+ if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
+ return FALSE;
+
+ for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":"))
+ {
+ if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+ return FALSE; //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+ AtoH(value, &pAd->ate.Addr3[i++], 1);
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ if(i != 6)
+ return FALSE; //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_DA_Proc (DA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr3[0],
+ pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]));
+#endif // CONFIG_STA_SUPPORT //
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_DA_Proc Success\n"));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE ADDR3=SA for TxFrame(AP : To DS = 0 ; From DS = 1)
+ or
+ Set ATE ADDR2=SA for TxFrame(STA : To DS = 1 ; From DS = 0)
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_SA_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ CHAR *value;
+ INT i;
+
+ if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
+ return FALSE;
+
+ for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":"))
+ {
+ if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+ return FALSE; //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+ AtoH(value, &pAd->ate.Addr2[i++], 1);
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ if(i != 6)
+ return FALSE; //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_SA_Proc (SA = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr2[0],
+ pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]));
+#endif // CONFIG_STA_SUPPORT //
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_SA_Proc Success\n"));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE ADDR2=BSSID for TxFrame(AP : To DS = 0 ; From DS = 1)
+ or
+ Set ATE ADDR1=BSSID for TxFrame(STA : To DS = 1 ; From DS = 0)
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_BSSID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ CHAR *value;
+ INT i;
+
+ if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
+ return FALSE;
+
+ for (i=0, value = rstrtok(arg, ":"); value; value = rstrtok(NULL, ":"))
+ {
+ if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+ return FALSE; //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+ AtoH(value, &pAd->ate.Addr1[i++], 1);
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ if(i != 6)
+ return FALSE; //Invalid
+
+
+#ifdef CONFIG_STA_SUPPORT
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_BSSID_Proc (BSSID = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAd->ate.Addr1[0],
+ pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]));
+#endif // CONFIG_STA_SUPPORT //
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_BSSID_Proc Success\n"));
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx Channel
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_CHANNEL_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR channel;
+
+ channel = simple_strtol(arg, 0, 10);
+
+ if ((channel < 1) || (channel > 216))// to allow A band channel : ((channel < 1) || (channel > 14))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_CHANNEL_Proc::Out of range, it should be in range of 1~14.\n"));
+ return FALSE;
+ }
+ pAd->ate.Channel = channel;
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_CHANNEL_Proc (ATE Channel = %d)\n", pAd->ate.Channel));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_CHANNEL_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx Power0
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_POWER0_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ CHAR TxPower;
+
+ TxPower = simple_strtol(arg, 0, 10);
+
+ if (pAd->ate.Channel <= 14)
+ {
+ if ((TxPower > 31) || (TxPower < 0))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower));
+ return FALSE;
+ }
+ }
+ else// 5.5GHz
+ {
+ if ((TxPower > 15) || (TxPower < -7))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER0_Proc::Out of range (Value=%d)\n", TxPower));
+ return FALSE;
+ }
+ }
+
+ pAd->ate.TxPower0 = TxPower;
+ ATETxPwrHandler(pAd, 0);
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER0_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx Power1
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_POWER1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ CHAR TxPower;
+
+ TxPower = simple_strtol(arg, 0, 10);
+
+ if (pAd->ate.Channel <= 14)
+ {
+ if ((TxPower > 31) || (TxPower < 0))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower));
+ return FALSE;
+ }
+ }
+ else
+ {
+ if ((TxPower > 15) || (TxPower < -7))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_POWER1_Proc::Out of range (Value=%d)\n", TxPower));
+ return FALSE;
+ }
+ }
+
+ pAd->ate.TxPower1 = TxPower;
+ ATETxPwrHandler(pAd, 1);
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_POWER1_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx Antenna
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_Antenna_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ CHAR value;
+
+ value = simple_strtol(arg, 0, 10);
+
+ if ((value > 2) || (value < 0))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_Antenna_Proc::Out of range (Value=%d)\n", value));
+ return FALSE;
+ }
+
+ pAd->ate.TxAntennaSel = value;
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_Antenna_Proc (Antenna = %d)\n", pAd->ate.TxAntennaSel));
+ ATEDBGPRINT(RT_DEBUG_TRACE,("Ralink: Set_ATE_TX_Antenna_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Rx Antenna
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_RX_Antenna_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ CHAR value;
+
+ value = simple_strtol(arg, 0, 10);
+
+ if ((value > 3) || (value < 0))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_RX_Antenna_Proc::Out of range (Value=%d)\n", value));
+ return FALSE;
+ }
+
+ pAd->ate.RxAntennaSel = value;
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_Antenna_Proc (Antenna = %d)\n", pAd->ate.RxAntennaSel));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_Antenna_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE RF frequence offset
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_FREQOFFSET_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR RFFreqOffset;
+ ULONG R4;
+
+ RFFreqOffset = simple_strtol(arg, 0, 10);
+
+ if(RFFreqOffset >= 64)
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_FREQOFFSET_Proc::Out of range, it should be in range of 0~63.\n"));
+ return FALSE;
+ }
+
+ pAd->ate.RFFreqOffset = RFFreqOffset;
+ R4 = pAd->ate.RFFreqOffset << 15; // shift TX power control to correct RF register bit position
+ R4 |= (pAd->LatchRfRegs.R4 & ((~0x001f8000)));
+ pAd->LatchRfRegs.R4 = R4;
+
+ RtmpRfIoWrite(pAd);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_FREQOFFSET_Proc (RFFreqOffset = %d)\n", pAd->ate.RFFreqOffset));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_FREQOFFSET_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE RF BW
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_BW_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ int i;
+ UCHAR value = 0;
+ UCHAR BBPCurrentBW;
+
+ BBPCurrentBW = simple_strtol(arg, 0, 10);
+
+ if(BBPCurrentBW == 0)
+ pAd->ate.TxWI.BW = BW_20;
+ else
+ pAd->ate.TxWI.BW = BW_40;
+
+ if(pAd->ate.TxWI.BW == BW_20)
+ {
+ if(pAd->ate.Channel <= 14)
+ {
+ for (i=0; i<5; i++)
+ {
+ if (pAd->Tx20MPwrCfgGBand[i] != 0xffffffff)
+ {
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgGBand[i]);
+ RTMPusecDelay(5000);
+ }
+ }
+ }
+ else
+ {
+ for (i=0; i<5; i++)
+ {
+ if (pAd->Tx20MPwrCfgABand[i] != 0xffffffff)
+ {
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx20MPwrCfgABand[i]);
+ RTMPusecDelay(5000);
+ }
+ }
+ }
+
+ //Set BBP R4 bit[4:3]=0:0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value);
+ value &= (~0x18);
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value);
+
+ //Set BBP R66=0x3C
+ value = 0x3C;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value);
+ //Set BBP R68=0x0B
+ //to improve Rx sensitivity.
+ value = 0x0B;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value);
+ //Set BBP R69=0x16
+ value = 0x16;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value);
+ //Set BBP R70=0x08
+ value = 0x08;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value);
+ //Set BBP R73=0x11
+ value = 0x11;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value);
+
+ // If Channel=14, Bandwidth=20M and Mode=CCK, Set BBP R4 bit5=1
+ // (Japan filter coefficients)
+ // This segment of code will only works when ATETXMODE and ATECHANNEL
+ // were set to MODE_CCK and 14 respectively before ATETXBW is set to 0.
+ //=====================================================================
+ if (pAd->ate.Channel == 14)
+ {
+ int TxMode = pAd->ate.TxWI.PHYMODE;
+ if (TxMode == MODE_CCK)
+ {
+ // when Channel==14 && Mode==CCK && BandWidth==20M, BBP R4 bit5=1
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value);
+ value |= 0x20; //set bit5=1
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value);
+ }
+ }
+
+ //=====================================================================
+ // If bandwidth != 40M, RF Reg4 bit 21 = 0.
+ pAd->LatchRfRegs.R4 &= ~0x00200000;
+ RtmpRfIoWrite(pAd);
+ }
+ else if(pAd->ate.TxWI.BW == BW_40)
+ {
+ if(pAd->ate.Channel <= 14)
+ {
+ for (i=0; i<5; i++)
+ {
+ if (pAd->Tx40MPwrCfgGBand[i] != 0xffffffff)
+ {
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgGBand[i]);
+ RTMPusecDelay(5000);
+ }
+ }
+ }
+ else
+ {
+ for (i=0; i<5; i++)
+ {
+ if (pAd->Tx40MPwrCfgABand[i] != 0xffffffff)
+ {
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, pAd->Tx40MPwrCfgABand[i]);
+ RTMPusecDelay(5000);
+ }
+ }
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->ate.TxWI.PHYMODE >= MODE_HTMIX) && (pAd->ate.TxWI.MCS == 7))
+ {
+ value = 0x28;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R67, value);
+ }
+#endif // DOT11_N_SUPPORT //
+ }
+
+ //Set BBP R4 bit[4:3]=1:0
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &value);
+ value &= (~0x18);
+ value |= 0x10;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, value);
+
+ //Set BBP R66=0x3C
+ value = 0x3C;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, value);
+ //Set BBP R68=0x0C
+ //to improve Rx sensitivity.
+ value = 0x0C;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R68, value);
+ //Set BBP R69=0x1A
+ value = 0x1A;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, value);
+ //Set BBP R70=0x0A
+ value = 0x0A;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, value);
+ //Set BBP R73=0x16
+ value = 0x16;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, value);
+
+ // If bandwidth = 40M, set RF Reg4 bit 21 = 1.
+ pAd->LatchRfRegs.R4 |= 0x00200000;
+ RtmpRfIoWrite(pAd);
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_BW_Proc (BBPCurrentBW = %d)\n", pAd->ate.TxWI.BW));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_BW_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx frame length
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_LENGTH_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ pAd->ate.TxLength = simple_strtol(arg, 0, 10);
+
+ if((pAd->ate.TxLength < 24) || (pAd->ate.TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */)))
+ {
+ pAd->ate.TxLength = (MAX_FRAME_SIZE - 34/* == 2312 */);
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_LENGTH_Proc::Out of range, it should be in range of 24~%d.\n", (MAX_FRAME_SIZE - 34/* == 2312 */)));
+ return FALSE;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_LENGTH_Proc (TxLength = %d)\n", pAd->ate.TxLength));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_LENGTH_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx frame count
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_COUNT_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ pAd->ate.TxCount = simple_strtol(arg, 0, 10);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAd->ate.TxCount));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx frame MCS
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_MCS_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR MCS;
+ int result;
+
+ MCS = simple_strtol(arg, 0, 10);
+ result = CheckMCSValid(pAd->ate.TxWI.PHYMODE, MCS);
+
+ if (result != -1)
+ {
+ pAd->ate.TxWI.MCS = (UCHAR)MCS;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MCS_Proc::Out of range, refer to rate table.\n"));
+ return FALSE;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MCS_Proc (MCS = %d)\n", pAd->ate.TxWI.MCS));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MCS_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx frame Mode
+ 0: MODE_CCK
+ 1: MODE_OFDM
+ 2: MODE_HTMIX
+ 3: MODE_HTGREENFIELD
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_MODE_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ pAd->ate.TxWI.PHYMODE = simple_strtol(arg, 0, 10);
+
+ if(pAd->ate.TxWI.PHYMODE > 3)
+ {
+ pAd->ate.TxWI.PHYMODE = 0;
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::Out of range. it should be in range of 0~3\n"));
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD.\n"));
+ return FALSE;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_MODE_Proc (TxMode = %d)\n", pAd->ate.TxWI.PHYMODE));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_MODE_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set ATE Tx frame GI
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+INT Set_ATE_TX_GI_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ pAd->ate.TxWI.ShortGI = simple_strtol(arg, 0, 10);
+
+ if(pAd->ate.TxWI.ShortGI > 1)
+ {
+ pAd->ate.TxWI.ShortGI = 0;
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_GI_Proc::Out of range\n"));
+ return FALSE;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_GI_Proc (GI = %d)\n", pAd->ate.TxWI.ShortGI));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_GI_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ ==========================================================================
+ */
+INT Set_ATE_RX_FER_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ pAd->ate.bRxFer = simple_strtol(arg, 0, 10);
+
+ if (pAd->ate.bRxFer == 1)
+ {
+ pAd->ate.RxCntPerSec = 0;
+ pAd->ate.RxTotalCnt = 0;
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_RX_FER_Proc (bRxFer = %d)\n", pAd->ate.bRxFer));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_RX_FER_Proc Success\n"));
+
+
+ return TRUE;
+}
+
+INT Set_ATE_Read_RF_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ate_print(KERN_EMERG "R1 = %lx\n", pAd->LatchRfRegs.R1);
+ ate_print(KERN_EMERG "R2 = %lx\n", pAd->LatchRfRegs.R2);
+ ate_print(KERN_EMERG "R3 = %lx\n", pAd->LatchRfRegs.R3);
+ ate_print(KERN_EMERG "R4 = %lx\n", pAd->LatchRfRegs.R4);
+
+ return TRUE;
+}
+
+INT Set_ATE_Write_RF1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT32 value = simple_strtol(arg, 0, 16);
+
+ pAd->LatchRfRegs.R1 = value;
+ RtmpRfIoWrite(pAd);
+
+ return TRUE;
+}
+
+INT Set_ATE_Write_RF2_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT32 value = simple_strtol(arg, 0, 16);
+
+ pAd->LatchRfRegs.R2 = value;
+ RtmpRfIoWrite(pAd);
+
+ return TRUE;
+}
+
+INT Set_ATE_Write_RF3_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT32 value = simple_strtol(arg, 0, 16);
+
+ pAd->LatchRfRegs.R3 = value;
+ RtmpRfIoWrite(pAd);
+
+ return TRUE;
+}
+
+INT Set_ATE_Write_RF4_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UINT32 value = simple_strtol(arg, 0, 16);
+
+ pAd->LatchRfRegs.R4 = value;
+ RtmpRfIoWrite(pAd);
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Load and Write EEPROM from a binary file prepared in advance.
+
+ Return:
+ TRUE if all parameters are OK, FALSE otherwise
+ ==========================================================================
+*/
+#ifndef UCOS
+INT Set_ATE_Load_E2P_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ BOOLEAN ret = FALSE;
+ PUCHAR src = EEPROM_BIN_FILE_NAME;
+ struct file *srcf;
+ INT32 retval, orgfsuid, orgfsgid;
+ mm_segment_t orgfs;
+ USHORT WriteEEPROM[(EEPROM_SIZE/2)];
+ UINT32 FileLength = 0;
+ UINT32 value = simple_strtol(arg, 0, 10);
+
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("===> %s (value=%d)\n\n", __func__, value));
+
+ if (value > 0)
+ {
+ /* zero the e2p buffer */
+ NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE);
+
+ /* save uid and gid used for filesystem access.
+ ** set user and group to 0 (root)
+ */
+ orgfsuid = current->fsuid;
+ orgfsgid = current->fsgid;
+ /* as root */
+ current->fsuid = current->fsgid = 0;
+ orgfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ do
+ {
+ /* open the bin file */
+ srcf = filp_open(src, O_RDONLY, 0);
+
+ if (IS_ERR(srcf))
+ {
+ ate_print("%s - Error %ld opening %s\n", __func__, -PTR_ERR(srcf), src);
+ break;
+ }
+
+ /* the object must have a read method */
+ if ((srcf->f_op == NULL) || (srcf->f_op->read == NULL))
+ {
+ ate_print("%s - %s does not have a read method\n", __func__, src);
+ break;
+ }
+
+ /* read the firmware from the file *.bin */
+ FileLength = srcf->f_op->read(srcf,
+ (PUCHAR)WriteEEPROM,
+ EEPROM_SIZE,
+ &srcf->f_pos);
+
+ if (FileLength != EEPROM_SIZE)
+ {
+ ate_print("%s: error file length (=%d) in e2p.bin\n",
+ __func__, FileLength);
+ break;
+ }
+ else
+ {
+ /* write the content of .bin file to EEPROM */
+ rt_ee_write_all(pAd, WriteEEPROM);
+ ret = TRUE;
+ }
+ break;
+ } while(TRUE);
+
+ /* close firmware file */
+ if (IS_ERR(srcf))
+ {
+ ;
+ }
+ else
+ {
+ retval = filp_close(srcf, NULL);
+ if (retval)
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("--> Error %d closing %s\n", -retval, src));
+
+ }
+ }
+
+ /* restore */
+ set_fs(orgfs);
+ current->fsuid = orgfsuid;
+ current->fsgid = orgfsgid;
+ }
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("<=== %s (ret=%d)\n", __func__, ret));
+
+ return ret;
+
+}
+#else
+INT Set_ATE_Load_E2P_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ USHORT WriteEEPROM[(EEPROM_SIZE/2)];
+ struct iwreq *wrq = (struct iwreq *)arg;
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("===> %s (wrq->u.data.length = %d)\n\n", __func__, wrq->u.data.length));
+
+ if (wrq->u.data.length != EEPROM_SIZE)
+ {
+ ate_print("%s: error length (=%d) from host\n",
+ __func__, wrq->u.data.length);
+ return FALSE;
+ }
+ else/* (wrq->u.data.length == EEPROM_SIZE) */
+ {
+ /* zero the e2p buffer */
+ NdisZeroMemory((PUCHAR)WriteEEPROM, EEPROM_SIZE);
+
+ /* fill the local buffer */
+ NdisMoveMemory((PUCHAR)WriteEEPROM, wrq->u.data.pointer, wrq->u.data.length);
+
+ do
+ {
+ /* write the content of .bin file to EEPROM */
+ rt_ee_write_all(pAd, WriteEEPROM);
+
+ } while(FALSE);
+ }
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("<=== %s\n", __func__));
+
+ return TRUE;
+
+}
+#endif // !UCOS //
+
+INT Set_ATE_Read_E2P_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ USHORT buffer[EEPROM_SIZE/2];
+ USHORT *p;
+ int i;
+
+ rt_ee_read_all(pAd, (USHORT *)buffer);
+ p = buffer;
+ for (i = 0; i < (EEPROM_SIZE/2); i++)
+ {
+ ate_print("%4.4x ", *p);
+ if (((i+1) % 16) == 0)
+ ate_print("\n");
+ p++;
+ }
+ return TRUE;
+}
+
+INT Set_ATE_Show_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ate_print("Mode=%d\n", pAd->ate.Mode);
+ ate_print("TxPower0=%d\n", pAd->ate.TxPower0);
+ ate_print("TxPower1=%d\n", pAd->ate.TxPower1);
+ ate_print("TxAntennaSel=%d\n", pAd->ate.TxAntennaSel);
+ ate_print("RxAntennaSel=%d\n", pAd->ate.RxAntennaSel);
+ ate_print("BBPCurrentBW=%d\n", pAd->ate.TxWI.BW);
+ ate_print("GI=%d\n", pAd->ate.TxWI.ShortGI);
+ ate_print("MCS=%d\n", pAd->ate.TxWI.MCS);
+ ate_print("TxMode=%d\n", pAd->ate.TxWI.PHYMODE);
+ ate_print("Addr1=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAd->ate.Addr1[0], pAd->ate.Addr1[1], pAd->ate.Addr1[2], pAd->ate.Addr1[3], pAd->ate.Addr1[4], pAd->ate.Addr1[5]);
+ ate_print("Addr2=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAd->ate.Addr2[0], pAd->ate.Addr2[1], pAd->ate.Addr2[2], pAd->ate.Addr2[3], pAd->ate.Addr2[4], pAd->ate.Addr2[5]);
+ ate_print("Addr3=%02x:%02x:%02x:%02x:%02x:%02x\n",
+ pAd->ate.Addr3[0], pAd->ate.Addr3[1], pAd->ate.Addr3[2], pAd->ate.Addr3[3], pAd->ate.Addr3[4], pAd->ate.Addr3[5]);
+ ate_print("Channel=%d\n", pAd->ate.Channel);
+ ate_print("TxLength=%d\n", pAd->ate.TxLength);
+ ate_print("TxCount=%u\n", pAd->ate.TxCount);
+ ate_print("RFFreqOffset=%d\n", pAd->ate.RFFreqOffset);
+ ate_print(KERN_EMERG "Set_ATE_Show_Proc Success\n");
+ return TRUE;
+}
+
+INT Set_ATE_Help_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ate_print("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME\n");
+ ate_print("ATEDA\n");
+ ate_print("ATESA\n");
+ ate_print("ATEBSSID\n");
+ ate_print("ATECHANNEL, range:0~14(unless A band !)\n");
+ ate_print("ATETXPOW0, set power level of antenna 1.\n");
+ ate_print("ATETXPOW1, set power level of antenna 2.\n");
+ ate_print("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n");
+ ate_print("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n");
+ ate_print("ATETXFREQOFFSET, set frequency offset, range 0~63\n");
+ ate_print("ATETXBW, set BandWidth, 0:20MHz, 1:40MHz.\n");
+ ate_print("ATETXLEN, set Frame length, range 24~%d\n", (MAX_FRAME_SIZE - 34/* == 2312 */));
+ ate_print("ATETXCNT, set how many frame going to transmit.\n");
+ ate_print("ATETXMCS, set MCS, reference to rate table.\n");
+ ate_print("ATETXMODE, set Mode 0:CCK, 1:OFDM, 2:HT-Mix, 3:GreenField, reference to rate table.\n");
+ ate_print("ATETXGI, set GI interval, 0:Long, 1:Short\n");
+ ate_print("ATERXFER, 0:disable Rx Frame error rate. 1:enable Rx Frame error rate.\n");
+ ate_print("ATERRF, show all RF registers.\n");
+ ate_print("ATEWRF1, set RF1 register.\n");
+ ate_print("ATEWRF2, set RF2 register.\n");
+ ate_print("ATEWRF3, set RF3 register.\n");
+ ate_print("ATEWRF4, set RF4 register.\n");
+ ate_print("ATELDE2P, load EEPROM from .bin file.\n");
+ ate_print("ATERE2P, display all EEPROM content.\n");
+ ate_print("ATESHOW, display all parameters of ATE.\n");
+ ate_print("ATEHELP, online help.\n");
+
+ return TRUE;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ AsicSwitchChannel() dedicated for ATE.
+
+ ==========================================================================
+*/
+VOID ATEAsicSwitchChannel(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT32 R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0, Value = 0;
+ CHAR TxPwer = 0, TxPwer2 = 0;
+ UCHAR index, BbpValue = 0, R66 = 0x30;
+ RTMP_RF_REGS *RFRegTable;
+ UCHAR Channel;
+
+#ifdef RALINK_28xx_QA
+ if ((pAd->ate.bQATxStart == TRUE) || (pAd->ate.bQARxStart == TRUE))
+ {
+ if (pAd->ate.Channel != pAd->LatchRfRegs.Channel)
+ {
+ pAd->ate.Channel = pAd->LatchRfRegs.Channel;
+ }
+ return;
+ }
+ else
+#endif // RALINK_28xx_QA //
+ Channel = pAd->ate.Channel;
+
+ // Select antenna
+ AsicAntennaSelect(pAd, Channel);
+
+ // fill Tx power value
+ TxPwer = pAd->ate.TxPower0;
+ TxPwer2 = pAd->ate.TxPower1;
+
+ RFRegTable = RF2850RegTable;
+
+ switch (pAd->RfIcType)
+ {
+ /* But only 2850 and 2750 support 5.5GHz band... */
+ case RFIC_2820:
+ case RFIC_2850:
+ case RFIC_2720:
+ case RFIC_2750:
+
+ for (index = 0; index < NUM_OF_2850_CHNL; index++)
+ {
+ if (Channel == RFRegTable[index].Channel)
+ {
+ R2 = RFRegTable[index].R2;
+ if (pAd->Antenna.field.TxPath == 1)
+ {
+ R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
+ }
+
+ if (pAd->Antenna.field.RxPath == 2)
+ {
+ switch (pAd->ate.RxAntennaSel)
+ {
+ case 1:
+ R2 |= 0x20040;
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+ BbpValue &= 0xE4;
+ BbpValue |= 0x00;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+ break;
+ case 2:
+ R2 |= 0x10040;
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+ BbpValue &= 0xE4;
+ BbpValue |= 0x01;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+ break;
+ default:
+ R2 |= 0x40;
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+ BbpValue &= 0xE4;
+ /* Only enable two Antenna to receive. */
+ BbpValue |= 0x08;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+ break;
+ }
+ }
+ else if (pAd->Antenna.field.RxPath == 1)
+ {
+ R2 |= 0x20040; // write 1 to off RxPath
+ }
+
+ if (pAd->Antenna.field.TxPath == 2)
+ {
+ if (pAd->ate.TxAntennaSel == 1)
+ {
+ R2 |= 0x4000; // If TX Antenna select is 1 , bit 14 = 1; Disable Ant 2
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue);
+ BbpValue &= 0xE7; //11100111B
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue);
+ }
+ else if (pAd->ate.TxAntennaSel == 2)
+ {
+ R2 |= 0x8000; // If TX Antenna select is 2 , bit 15 = 1; Disable Ant 1
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue);
+ BbpValue &= 0xE7;
+ BbpValue |= 0x08;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue);
+ }
+ else
+ {
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpValue);
+ BbpValue &= 0xE7;
+ BbpValue |= 0x10;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpValue);
+ }
+ }
+ if (pAd->Antenna.field.RxPath == 3)
+ {
+ switch (pAd->ate.RxAntennaSel)
+ {
+ case 1:
+ R2 |= 0x20040;
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+ BbpValue &= 0xE4;
+ BbpValue |= 0x00;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+ break;
+ case 2:
+ R2 |= 0x10040;
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+ BbpValue &= 0xE4;
+ BbpValue |= 0x01;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+ break;
+ case 3:
+ R2 |= 0x30000;
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+ BbpValue &= 0xE4;
+ BbpValue |= 0x02;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+ break;
+ default:
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BbpValue);
+ BbpValue &= 0xE4;
+ BbpValue |= 0x10;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BbpValue);
+ break;
+ }
+ }
+
+ if (Channel > 14)
+ {
+ // initialize R3, R4
+ R3 = (RFRegTable[index].R3 & 0xffffc1ff);
+ R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15);
+
+ // According the Rory's suggestion to solve the middle range issue.
+ // 5.5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
+ // R3
+ if ((TxPwer >= -7) && (TxPwer < 0))
+ {
+ TxPwer = (7+TxPwer);
+ TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+ R3 |= (TxPwer << 10);
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer=%d \n", TxPwer));
+ }
+ else
+ {
+ TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
+ R3 |= (TxPwer << 10) | (1 << 9);
+ }
+
+ // R4
+ if ((TxPwer2 >= -7) && (TxPwer2 < 0))
+ {
+ TxPwer2 = (7+TxPwer2);
+ TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+ R4 |= (TxPwer2 << 7);
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ATEAsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
+ }
+ else
+ {
+ TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
+ R4 |= (TxPwer2 << 7) | (1 << 6);
+ }
+ }
+ else
+ {
+ R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
+ R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->ate.RFFreqOffset << 15) | (TxPwer2 <<6);// Set freq offset & TxPwr1
+ }
+
+ // Based on BBP current mode before changing RF channel.
+ if (pAd->ate.TxWI.BW == BW_40)
+ {
+ R4 |=0x200000;
+ }
+
+ // Update variables
+ pAd->LatchRfRegs.Channel = Channel;
+ pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
+ pAd->LatchRfRegs.R2 = R2;
+ pAd->LatchRfRegs.R3 = R3;
+ pAd->LatchRfRegs.R4 = R4;
+
+ RtmpRfIoWrite(pAd);
+
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // Change BBP setting during switch from a->g, g->a
+ if (Channel <= 14)
+ {
+ ULONG TxPinCfg = 0x00050F0A;// 2007.10.09 by Brian : 0x0005050A ==> 0x00050F0A
+
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+
+ /* For 1T/2R chip only... */
+ if (pAd->NicConfig2.field.ExternalLNAForG)
+ {
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
+ }
+ else
+ {
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
+ }
+
+ // According the Rory's suggestion to solve the middle range issue.
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue);
+ ASSERT((BbpValue == 0x00));
+ if ((BbpValue != 0x00))
+ {
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00);
+ }
+
+ // 5.5GHz band selection PIN, bit1 and bit2 are complement
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+ Value &= (~0x6);
+ Value |= (0x04);
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+ // Turn off unused PA or LNA when only 1T or 1R.
+ if (pAd->Antenna.field.TxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFFFF3;
+ }
+ if (pAd->Antenna.field.RxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFF3FF;
+ }
+
+ RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+ }
+ else
+ {
+ ULONG TxPinCfg = 0x00050F05;//2007.10.09 by Brian : 0x00050505 ==> 0x00050F05
+
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
+
+ // According the Rory's suggestion to solve the middle range issue.
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R86, &BbpValue);
+ ASSERT((BbpValue == 0x00));
+ if ((BbpValue != 0x00))
+ {
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0x00);
+ }
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R91, &BbpValue);
+ ASSERT((BbpValue == 0x04));
+
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R92, &BbpValue);
+ ASSERT((BbpValue == 0x00));
+
+ // 5.5GHz band selection PIN, bit1 and bit2 are complement
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
+ Value &= (~0x6);
+ Value |= (0x02);
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
+
+ // Turn off unused PA or LNA when only 1T or 1R.
+ if (pAd->Antenna.field.TxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFFFF3;
+ }
+ if (pAd->Antenna.field.RxPath == 1)
+ {
+ TxPinCfg &= 0xFFFFF3FF;
+ }
+
+ RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
+ }
+
+ // R66 should be set according to Channel and use 20MHz when scanning
+ if (Channel <= 14)
+ {
+ // BG band
+ R66 = 0x2E + GET_LNA_GAIN(pAd);
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ else
+ {
+ // 5.5 GHz band
+ if (pAd->ate.TxWI.BW == BW_20)
+ {
+ R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ else
+ {
+ R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
+ }
+ }
+
+ //
+ // On 11A, We should delay and wait RF/BBP to be stable
+ // and the appropriate time should be 1000 micro seconds
+ // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
+ //
+ RTMPusecDelay(1000);
+
+ if (Channel > 14)
+ {
+ // When 5.5GHz band the LSB of TxPwr will be used to reduced 7dB or not.
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
+ Channel,
+ pAd->RfIcType,
+ pAd->Antenna.field.TxPath,
+ pAd->LatchRfRegs.R1,
+ pAd->LatchRfRegs.R2,
+ pAd->LatchRfRegs.R3,
+ pAd->LatchRfRegs.R4));
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%u, Pwr1=%u, %dT) to , R1=0x%08lx, R2=0x%08lx, R3=0x%08lx, R4=0x%08lx\n",
+ Channel,
+ pAd->RfIcType,
+ (R3 & 0x00003e00) >> 9,
+ (R4 & 0x000007c0) >> 6,
+ pAd->Antenna.field.TxPath,
+ pAd->LatchRfRegs.R1,
+ pAd->LatchRfRegs.R2,
+ pAd->LatchRfRegs.R3,
+ pAd->LatchRfRegs.R4));
+ }
+}
+
+//
+// In fact, no one will call this routine so far !
+//
+/*
+ ==========================================================================
+ Description:
+ Gives CCK TX rate 2 more dB TX power.
+ This routine works only in ATE mode.
+
+ calculate desired Tx power in RF R3.Tx0~5, should consider -
+ 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
+ 1. TxPowerPercentage
+ 2. auto calibration based on TSSI feedback
+ 3. extra 2 db for CCK
+ 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
+
+ NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
+ it should be called AFTER MlmeDynamicTxRateSwitching()
+ ==========================================================================
+ */
+VOID ATEAsicAdjustTxPower(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT i, j;
+ CHAR DeltaPwr = 0;
+ BOOLEAN bAutoTxAgc = FALSE;
+ UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
+ UCHAR BbpR49 = 0, idx;
+ PCHAR pTxAgcCompensate;
+ ULONG TxPwr[5];
+ CHAR Value;
+
+ /* no one calls this procedure so far */
+ if (pAd->ate.TxWI.BW == BW_40)
+ {
+ if (pAd->ate.Channel > 14)
+ {
+ TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
+ TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
+ TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
+ TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
+ TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
+ }
+ else
+ {
+ TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
+ TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
+ TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
+ TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
+ TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
+ }
+ }
+ else
+ {
+ if (pAd->ate.Channel > 14)
+ {
+ TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
+ TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
+ TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
+ TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
+ TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
+ }
+ else
+ {
+ TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
+ TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
+ TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
+ TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
+ TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
+ }
+ }
+
+ // TX power compensation for temperature variation based on TSSI.
+ // Do it per 4 seconds.
+ if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
+ {
+ if (pAd->ate.Channel <= 14)
+ {
+ /* bg channel */
+ bAutoTxAgc = pAd->bAutoTxAgcG;
+ TssiRef = pAd->TssiRefG;
+ pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
+ pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
+ TxAgcStep = pAd->TxAgcStepG;
+ pTxAgcCompensate = &pAd->TxAgcCompensateG;
+ }
+ else
+ {
+ /* a channel */
+ bAutoTxAgc = pAd->bAutoTxAgcA;
+ TssiRef = pAd->TssiRefA;
+ pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
+ pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
+ TxAgcStep = pAd->TxAgcStepA;
+ pTxAgcCompensate = &pAd->TxAgcCompensateA;
+ }
+
+ if (bAutoTxAgc)
+ {
+ /* BbpR49 is unsigned char */
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
+
+ /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
+ /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
+ /* step value is defined in pAd->TxAgcStepG for tx power value */
+
+ /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
+ /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
+ above value are examined in mass factory production */
+ /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
+
+ /* plus is 0x10 ~ 0x40, minus is 0x60 ~ 0x90 */
+ /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
+ /* if value is 0x65, tx power will be -= TxAgcStep*(2-1) */
+
+ if (BbpR49 > pTssiMinusBoundary[1])
+ {
+ // Reading is larger than the reference value.
+ // Check for how large we need to decrease the Tx power.
+ for (idx = 1; idx < 5; idx++)
+ {
+ if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
+ break;
+ }
+ // The index is the step we should decrease, idx = 0 means there is nothing to compensate
+// if (R3 > (ULONG) (TxAgcStep * (idx-1)))
+ *pTxAgcCompensate = -(TxAgcStep * (idx-1));
+// else
+// *pTxAgcCompensate = -((UCHAR)R3);
+
+ DeltaPwr += (*pTxAgcCompensate);
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
+ BbpR49, TssiRef, TxAgcStep, idx-1));
+ }
+ else if (BbpR49 < pTssiPlusBoundary[1])
+ {
+ // Reading is smaller than the reference value
+ // check for how large we need to increase the Tx power
+ for (idx = 1; idx < 5; idx++)
+ {
+ if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
+ break;
+ }
+ // The index is the step we should increase, idx = 0 means there is nothing to compensate
+ *pTxAgcCompensate = TxAgcStep * (idx-1);
+ DeltaPwr += (*pTxAgcCompensate);
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+ BbpR49, TssiRef, TxAgcStep, idx-1));
+ }
+ else
+ {
+ *pTxAgcCompensate = 0;
+ ATEDBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
+ BbpR49, TssiRef, TxAgcStep, 0));
+ }
+ }
+ }
+ else
+ {
+ if (pAd->ate.Channel <= 14)
+ {
+ bAutoTxAgc = pAd->bAutoTxAgcG;
+ pTxAgcCompensate = &pAd->TxAgcCompensateG;
+ }
+ else
+ {
+ bAutoTxAgc = pAd->bAutoTxAgcA;
+ pTxAgcCompensate = &pAd->TxAgcCompensateA;
+ }
+
+ if (bAutoTxAgc)
+ DeltaPwr += (*pTxAgcCompensate);
+ }
+
+ /* calculate delta power based on the percentage specified from UI */
+ // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
+ // We lower TX power here according to the percentage specified from UI
+ if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
+ ;
+ else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
+ ;
+ else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW
+ {
+ DeltaPwr -= 1;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW
+ {
+ DeltaPwr -= 3;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW
+ {
+ DeltaPwr -= 6;
+ }
+ else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW
+ {
+ DeltaPwr -= 9;
+ }
+ else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW
+ {
+ DeltaPwr -= 12;
+ }
+
+ /* reset different new tx power for different TX rate */
+ for(i=0; i<5; i++)
+ {
+ if (TxPwr[i] != 0xffffffff)
+ {
+ for (j=0; j<8; j++)
+ {
+ Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
+
+ if ((Value + DeltaPwr) < 0)
+ {
+ Value = 0; /* min */
+ }
+ else if ((Value + DeltaPwr) > 0xF)
+ {
+ Value = 0xF; /* max */
+ }
+ else
+ {
+ Value += DeltaPwr; /* temperature compensation */
+ }
+
+ /* fill new value to CSR offset */
+ TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
+ }
+
+ /* write tx power value to CSR */
+ /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
+ TX power for OFDM 6M/9M
+ TX power for CCK5.5M/11M
+ TX power for CCK1M/2M */
+ /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
+ RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
+
+
+ }
+ }
+
+}
+
+/*
+ ========================================================================
+ Routine Description:
+ Write TxWI for ATE mode.
+
+ Return Value:
+ None
+ ========================================================================
+*/
+#ifdef RT2860
+static VOID ATEWriteTxWI(
+ IN PRTMP_ADAPTER pAd,
+ IN PTXWI_STRUC pOutTxWI,
+ IN BOOLEAN FRAG,
+ IN BOOLEAN CFACK,
+ IN BOOLEAN InsTimestamp,
+ IN BOOLEAN AMPDU,
+ IN BOOLEAN Ack,
+ IN BOOLEAN NSeq, // HW new a sequence.
+ IN UCHAR BASize,
+ IN UCHAR WCID,
+ IN ULONG Length,
+ IN UCHAR PID,
+ IN UCHAR TID,
+ IN UCHAR TxRate,
+ IN UCHAR Txopmode,
+ IN BOOLEAN CfAck,
+ IN HTTRANSMIT_SETTING *pTransmit)
+{
+ TXWI_STRUC TxWI;
+ PTXWI_STRUC pTxWI;
+
+ //
+ // Always use Long preamble before verifiation short preamble functionality works well.
+ // Todo: remove the following line if short preamble functionality works
+ //
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
+ NdisZeroMemory(&TxWI, TXWI_SIZE);
+ pTxWI = &TxWI;
+
+ pTxWI->FRAG= FRAG;
+
+ pTxWI->CFACK = CFACK;
+ pTxWI->TS= InsTimestamp;
+ pTxWI->AMPDU = AMPDU;
+ pTxWI->ACK = Ack;
+ pTxWI->txop= Txopmode;
+
+ pTxWI->NSEQ = NSeq;
+ // John tune the performace with Intel Client in 20 MHz performance
+ if( BASize >7 )
+ BASize =7;
+
+ pTxWI->BAWinSize = BASize;
+ pTxWI->WirelessCliID = WCID;
+ pTxWI->MPDUtotalByteCount = Length;
+ pTxWI->PacketId = PID;
+
+ // If CCK or OFDM, BW must be 20
+ pTxWI->BW = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW);
+ pTxWI->ShortGI = pTransmit->field.ShortGI;
+ pTxWI->STBC = pTransmit->field.STBC;
+
+ pTxWI->MCS = pTransmit->field.MCS;
+ pTxWI->PHYMODE = pTransmit->field.MODE;
+ pTxWI->CFACK = CfAck;
+ pTxWI->MIMOps = 0;
+ pTxWI->MpduDensity = 0;
+
+ pTxWI->PacketId = pTxWI->MCS;
+ NdisMoveMemory(pOutTxWI, &TxWI, sizeof(TXWI_STRUC));
+
+ return;
+}
+#endif // RT2860 //
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Disable protection for ATE.
+ ========================================================================
+*/
+VOID ATEDisableAsicProtect(
+ IN PRTMP_ADAPTER pAd)
+{
+ PROT_CFG_STRUC ProtCfg, ProtCfg4;
+ UINT32 Protect[6];
+ USHORT offset;
+ UCHAR i;
+ UINT32 MacReg = 0;
+
+ // Config ASIC RTS threshold register
+ RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
+ MacReg &= 0xFF0000FF;
+ MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
+ RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
+
+ // Initial common protection settings
+ RTMPZeroMemory(Protect, sizeof(Protect));
+ ProtCfg4.word = 0;
+ ProtCfg.word = 0;
+ ProtCfg.field.TxopAllowGF40 = 1;
+ ProtCfg.field.TxopAllowGF20 = 1;
+ ProtCfg.field.TxopAllowMM40 = 1;
+ ProtCfg.field.TxopAllowMM20 = 1;
+ ProtCfg.field.TxopAllowOfdm = 1;
+ ProtCfg.field.TxopAllowCck = 1;
+ ProtCfg.field.RTSThEn = 1;
+ ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
+
+ // Handle legacy(B/G) protection
+ ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
+ ProtCfg.field.ProtectCtrl = 0;
+ Protect[0] = ProtCfg.word;
+ Protect[1] = ProtCfg.word;
+
+ // NO PROTECT
+ // 1.All STAs in the BSS are 20/40 MHz HT
+ // 2. in ai 20/40MHz BSS
+ // 3. all STAs are 20MHz in a 20MHz BSS
+ // Pure HT. no protection.
+
+ // MM20_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 010111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
+ Protect[2] = 0x01744004;
+
+ // MM40_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 111111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
+ Protect[3] = 0x03f44084;
+
+ // CF20_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 010111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
+ Protect[4] = 0x01744004;
+
+ // CF40_PROT_CFG
+ // Reserved (31:27)
+ // PROT_TXOP(25:20) -- 111111
+ // PROT_NAV(19:18) -- 01 (Short NAV protection)
+ // PROT_CTRL(17:16) -- 00 (None)
+ // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
+ Protect[5] = 0x03f44084;
+
+ pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
+
+ offset = CCK_PROT_CFG;
+ for (i = 0;i < 6;i++)
+ RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
+
+}
+
+
+/* There are two ways to convert Rssi */
+#if 1
+//
+// The way used with GET_LNA_GAIN().
+//
+CHAR ATEConvertToRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi,
+ IN UCHAR RssiNumber)
+{
+ UCHAR RssiOffset, LNAGain;
+
+ // Rssi equals to zero should be an invalid value
+ if (Rssi == 0)
+ return -99;
+
+ LNAGain = GET_LNA_GAIN(pAd);
+ if (pAd->LatchRfRegs.Channel > 14)
+ {
+ if (RssiNumber == 0)
+ RssiOffset = pAd->ARssiOffset0;
+ else if (RssiNumber == 1)
+ RssiOffset = pAd->ARssiOffset1;
+ else
+ RssiOffset = pAd->ARssiOffset2;
+ }
+ else
+ {
+ if (RssiNumber == 0)
+ RssiOffset = pAd->BGRssiOffset0;
+ else if (RssiNumber == 1)
+ RssiOffset = pAd->BGRssiOffset1;
+ else
+ RssiOffset = pAd->BGRssiOffset2;
+ }
+
+ return (-12 - RssiOffset - LNAGain - Rssi);
+}
+#else
+//
+// The way originally used in ATE of rt2860ap.
+//
+CHAR ATEConvertToRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi,
+ IN UCHAR RssiNumber)
+{
+ UCHAR RssiOffset, LNAGain;
+
+ // Rssi equals to zero should be an invalid value
+ if (Rssi == 0)
+ return -99;
+
+ if (pAd->LatchRfRegs.Channel > 14)
+ {
+ LNAGain = pAd->ALNAGain;
+ if (RssiNumber == 0)
+ RssiOffset = pAd->ARssiOffset0;
+ else if (RssiNumber == 1)
+ RssiOffset = pAd->ARssiOffset1;
+ else
+ RssiOffset = pAd->ARssiOffset2;
+ }
+ else
+ {
+ LNAGain = pAd->BLNAGain;
+ if (RssiNumber == 0)
+ RssiOffset = pAd->BGRssiOffset0;
+ else if (RssiNumber == 1)
+ RssiOffset = pAd->BGRssiOffset1;
+ else
+ RssiOffset = pAd->BGRssiOffset2;
+ }
+
+ return (-32 - RssiOffset + LNAGain - Rssi);
+}
+#endif /* end of #if 1 */
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Set Japan filter coefficients if needed.
+ Note:
+ This routine should only be called when
+ entering TXFRAME mode or TXCONT mode.
+
+ ========================================================================
+*/
+static VOID SetJapanFilter(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR BbpData = 0;
+
+ //
+ // If Channel=14 and Bandwidth=20M and Mode=CCK, set BBP R4 bit5=1
+ // (Japan Tx filter coefficients)when (TXFRAME or TXCONT).
+ //
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BbpData);
+
+ if ((pAd->ate.TxWI.PHYMODE == MODE_CCK) && (pAd->ate.Channel == 14) && (pAd->ate.TxWI.BW == BW_20))
+ {
+ BbpData |= 0x20; // turn on
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("SetJapanFilter!!!\n"));
+ }
+ else
+ {
+ BbpData &= 0xdf; // turn off
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("ClearJapanFilter!!!\n"));
+ }
+
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, BbpData);
+}
+
+VOID ATESampleRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN PRXWI_STRUC pRxWI)
+{
+ /* There are two ways to collect RSSI. */
+#if 1
+ //pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
+ if (pRxWI->RSSI0 != 0)
+ {
+ pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0);
+ pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0;
+ pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3;
+ }
+ if (pRxWI->RSSI1 != 0)
+ {
+ pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1);
+ pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1;
+ pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3;
+ }
+ if (pRxWI->RSSI2 != 0)
+ {
+ pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2);
+ pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2;
+ pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3;
+ }
+
+ pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);// CHAR ==> UCHAR ?
+ pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);// CHAR ==> UCHAR ?
+
+ pAd->ate.NumOfAvgRssiSample ++;
+#else
+ pAd->ate.LastSNR0 = (CHAR)(pRxWI->SNR0);
+ pAd->ate.LastSNR1 = (CHAR)(pRxWI->SNR1);
+ pAd->ate.RxCntPerSec++;
+ pAd->ate.LastRssi0 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI0, RSSI_0);
+ pAd->ate.LastRssi1 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI1, RSSI_1);
+ pAd->ate.LastRssi2 = ATEConvertToRssi(pAd, (CHAR) pRxWI->RSSI2, RSSI_2);
+ pAd->ate.AvgRssi0X8 = (pAd->ate.AvgRssi0X8 - pAd->ate.AvgRssi0) + pAd->ate.LastRssi0;
+ pAd->ate.AvgRssi0 = pAd->ate.AvgRssi0X8 >> 3;
+ pAd->ate.AvgRssi1X8 = (pAd->ate.AvgRssi1X8 - pAd->ate.AvgRssi1) + pAd->ate.LastRssi1;
+ pAd->ate.AvgRssi1 = pAd->ate.AvgRssi1X8 >> 3;
+ pAd->ate.AvgRssi2X8 = (pAd->ate.AvgRssi2X8 - pAd->ate.AvgRssi2) + pAd->ate.LastRssi2;
+ pAd->ate.AvgRssi2 = pAd->ate.AvgRssi2X8 >> 3;
+ pAd->ate.NumOfAvgRssiSample ++;
+#endif
+}
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPStationStop(
+ IN PRTMP_ADAPTER pAd)
+{
+// BOOLEAN Cancelled;
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStop\n"));
+
+#if 0
+ RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
+#endif
+ // For rx statistics, we need to keep this timer running.
+// RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStop\n"));
+}
+
+VOID RTMPStationStart(
+ IN PRTMP_ADAPTER pAd)
+{
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("==> RTMPStationStart\n"));
+#ifdef RT2860
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ //
+ // We did not cancel this timer when entering ATE mode.
+ //
+// RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
+#endif // RT2860 //
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("<== RTMPStationStart\n"));
+}
+#endif // CONFIG_STA_SUPPORT //
+
+/*
+ ==========================================================================
+ Description:
+ Setup Frame format.
+ NOTE:
+ This routine should only be used in ATE mode.
+ ==========================================================================
+ */
+#ifdef RT2860
+static INT ATESetUpFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 TxIdx)
+{
+ UINT j;
+ PTXD_STRUC pTxD;
+#ifdef RT_BIG_ENDIAN
+ PTXD_STRUC pDestTxD;
+ TXD_STRUC TxD;
+#endif
+ PNDIS_PACKET pPacket;
+ PUCHAR pDest;
+ PVOID AllocVa;
+ NDIS_PHYSICAL_ADDRESS AllocPa;
+ HTTRANSMIT_SETTING TxHTPhyMode;
+
+ PRTMP_TX_RING pTxRing = &pAd->TxRing[QID_AC_BE];
+ PTXWI_STRUC pTxWI = (PTXWI_STRUC) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
+ PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa;
+
+#ifdef RALINK_28xx_QA
+ PHEADER_802_11 pHeader80211;
+#endif // RALINK_28xx_QA //
+
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ // always use QID_AC_BE and FIFO_EDCA
+
+ // fill TxWI
+ TxHTPhyMode.field.BW = pAd->ate.TxWI.BW;
+ TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI;
+ TxHTPhyMode.field.STBC = 0;
+ TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS;
+ TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE;
+ ATEWriteTxWI(pAd, pTxWI, pAd->ate.TxWI.FRAG, pAd->ate.TxWI.CFACK, pAd->ate.TxWI.TS, pAd->ate.TxWI.AMPDU, pAd->ate.TxWI.ACK, pAd->ate.TxWI.NSEQ,
+ pAd->ate.TxWI.BAWinSize, 0, pAd->ate.TxWI.MPDUtotalByteCount, pAd->ate.TxWI.PacketId, 0, 0, pAd->ate.TxWI.txop/*IFS_HTTXOP*/, pAd->ate.TxWI.CFACK/*FALSE*/, &TxHTPhyMode);
+ }
+ else
+ {
+ TxHTPhyMode.field.BW = pAd->ate.TxWI.BW;
+ TxHTPhyMode.field.ShortGI = pAd->ate.TxWI.ShortGI;
+ TxHTPhyMode.field.STBC = 0;
+ TxHTPhyMode.field.MCS = pAd->ate.TxWI.MCS;
+ TxHTPhyMode.field.MODE = pAd->ate.TxWI.PHYMODE;
+ ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ 4, 0, pAd->ate.TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode);
+ }
+
+ // fill 802.11 header.
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE, pAd->ate.Header, pAd->ate.HLen);
+ }
+ else
+#endif // RALINK_28xx_QA //
+ {
+ NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE, TemplateFrame, LENGTH_802_11);
+ NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+4, pAd->ate.Addr1, ETH_LENGTH_OF_ADDRESS);
+ NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+10, pAd->ate.Addr2, ETH_LENGTH_OF_ADDRESS);
+ NdisMoveMemory(pDMAHeaderBufVA+TXWI_SIZE+16, pAd->ate.Addr3, ETH_LENGTH_OF_ADDRESS);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA)+TXWI_SIZE), DIR_READ, FALSE);
+#endif // RT_BIG_ENDIAN //
+
+ /* alloc buffer for payload */
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ /* Why not use RTMP_AllocateTxPacketBuffer() instead of RTMP_AllocateRxPacketBuffer()? */
+ pPacket = RTMP_AllocateRxPacketBuffer(pAd, pAd->ate.DLen + 0x100, FALSE, &AllocVa, &AllocPa);
+ }
+ else
+#endif // RALINK_28xx_QA //
+ {
+ /* Why not use RTMP_AllocateTxPacketBuffer() instead of RTMP_AllocateRxPacketBuffer()? */
+ pPacket = RTMP_AllocateRxPacketBuffer(pAd, pAd->ate.TxLength, FALSE, &AllocVa, &AllocPa);
+ }
+
+ if (pPacket == NULL)
+ {
+ pAd->ate.TxCount = 0;
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("%s fail to alloc packet space.\n", __func__));
+ return -1;
+ }
+ pTxRing->Cell[TxIdx].pNextNdisPacket = pPacket;
+
+ pDest = (PUCHAR) AllocVa;
+
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ RTPKT_TO_OSPKT(pPacket)->len = pAd->ate.DLen;
+ }
+ else
+#endif // RALINK_28xx_QA //
+ {
+ RTPKT_TO_OSPKT(pPacket)->len = pAd->ate.TxLength - LENGTH_802_11;
+ }
+
+ // Prepare frame payload
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ // copy pattern
+ if ((pAd->ate.PLen != 0))
+ {
+ int j;
+
+ for (j = 0; j < pAd->ate.DLen; j+=pAd->ate.PLen)
+ {
+ memcpy(RTPKT_TO_OSPKT(pPacket)->data + j, pAd->ate.Pattern, pAd->ate.PLen);
+ }
+ }
+ }
+ else
+#endif // RALINK_28xx_QA //
+ {
+ for(j = 0; j < RTPKT_TO_OSPKT(pPacket)->len; j++)
+ pDest[j] = 0xA5;
+ }
+
+ //
+ // build Tx Descriptor
+ //
+#ifndef RT_BIG_ENDIAN
+ pTxD = (PTXD_STRUC) pTxRing->Cell[TxIdx].AllocVa;
+#else
+ pDestTxD = (PTXD_STRUC)pTxRing->Cell[TxIdx].AllocVa;
+ TxD = *pDestTxD;
+ pTxD = &TxD;
+#endif // !RT_BIG_ENDIAN //
+
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQATxStart == TRUE)
+ {
+ // prepare TxD
+ NdisZeroMemory(pTxD, TXD_SIZE);
+ RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
+ // build TX DESC
+ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
+ pTxD->SDLen0 = TXWI_SIZE + pAd->ate.HLen;
+ pTxD->LastSec0 = 0;
+ pTxD->SDPtr1 = AllocPa;
+ pTxD->SDLen1 = RTPKT_TO_OSPKT(pPacket)->len;
+ pTxD->LastSec1 = 1;
+
+ pDest = (PUCHAR)pTxWI;
+ pDest += TXWI_SIZE;
+ pHeader80211 = (PHEADER_802_11)pDest;
+
+ // modify sequence number....
+ if (pAd->ate.TxDoneCount == 0)
+ {
+ pAd->ate.seq = pHeader80211->Sequence;
+ }
+ else
+ pHeader80211->Sequence = ++pAd->ate.seq;
+ }
+ else
+#endif // RALINK_28xx_QA //
+ {
+ NdisZeroMemory(pTxD, TXD_SIZE);
+ RTMPWriteTxDescriptor(pAd, pTxD, FALSE, FIFO_EDCA);
+ // build TX DESC
+ pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa);
+ pTxD->SDLen0 = TXWI_SIZE + LENGTH_802_11;
+ pTxD->LastSec0 = 0;
+ pTxD->SDPtr1 = AllocPa;
+ pTxD->SDLen1 = RTPKT_TO_OSPKT(pPacket)->len;
+ pTxD->LastSec1 = 1;
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+ RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA)+TXWI_SIZE), DIR_WRITE, FALSE);
+ RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);
+ WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD);
+#endif // RT_BIG_ENDIAN //
+ return 0;
+}
+/* */
+/* */
+/*=======================End of RT2860=======================*/
+#endif // RT2860 //
+
+
+VOID rt_ee_read_all(PRTMP_ADAPTER pAd, USHORT *Data)
+{
+ USHORT i;
+ USHORT value;
+
+ for (i = 0 ; i < EEPROM_SIZE/2 ; )
+ {
+ /* "value" is expecially for some compilers... */
+ RT28xx_EEPROM_READ16(pAd, i*2, value);
+ Data[i] = value;
+ i++;
+ }
+}
+
+VOID rt_ee_write_all(PRTMP_ADAPTER pAd, USHORT *Data)
+{
+ USHORT i;
+ USHORT value;
+
+ for (i = 0 ; i < EEPROM_SIZE/2 ; )
+ {
+ /* "value" is expecially for some compilers... */
+ value = Data[i];
+ RT28xx_EEPROM_WRITE16(pAd, i*2, value);
+ i ++;
+ }
+}
+#ifdef RALINK_28xx_QA
+VOID ATE_QA_Statistics(
+ IN PRTMP_ADAPTER pAd,
+ IN PRXWI_STRUC pRxWI,
+ IN PRT28XX_RXD_STRUC pRxD,
+ IN PHEADER_802_11 pHeader)
+{
+ // update counter first
+ if (pHeader != NULL)
+ {
+ if (pHeader->FC.Type == BTYPE_DATA)
+ {
+ if (pRxD->U2M)
+ pAd->ate.U2M++;
+ else
+ pAd->ate.OtherData++;
+ }
+ else if (pHeader->FC.Type == BTYPE_MGMT)
+ {
+ if (pHeader->FC.SubType == SUBTYPE_BEACON)
+ pAd->ate.Beacon++;
+ else
+ pAd->ate.OtherCount++;
+ }
+ else if (pHeader->FC.Type == BTYPE_CNTL)
+ {
+ pAd->ate.OtherCount++;
+ }
+ }
+ pAd->ate.RSSI0 = pRxWI->RSSI0;
+ pAd->ate.RSSI1 = pRxWI->RSSI1;
+ pAd->ate.RSSI2 = pRxWI->RSSI2;
+ pAd->ate.SNR0 = pRxWI->SNR0;
+ pAd->ate.SNR1 = pRxWI->SNR1;
+}
+
+/* command id with Cmd Type == 0x0008(for 28xx)/0x0005(for iNIC) */
+#define RACFG_CMD_RF_WRITE_ALL 0x0000
+#define RACFG_CMD_E2PROM_READ16 0x0001
+#define RACFG_CMD_E2PROM_WRITE16 0x0002
+#define RACFG_CMD_E2PROM_READ_ALL 0x0003
+#define RACFG_CMD_E2PROM_WRITE_ALL 0x0004
+#define RACFG_CMD_IO_READ 0x0005
+#define RACFG_CMD_IO_WRITE 0x0006
+#define RACFG_CMD_IO_READ_BULK 0x0007
+#define RACFG_CMD_BBP_READ8 0x0008
+#define RACFG_CMD_BBP_WRITE8 0x0009
+#define RACFG_CMD_BBP_READ_ALL 0x000a
+#define RACFG_CMD_GET_COUNTER 0x000b
+#define RACFG_CMD_CLEAR_COUNTER 0x000c
+
+#define RACFG_CMD_RSV1 0x000d
+#define RACFG_CMD_RSV2 0x000e
+#define RACFG_CMD_RSV3 0x000f
+
+#define RACFG_CMD_TX_START 0x0010
+#define RACFG_CMD_GET_TX_STATUS 0x0011
+#define RACFG_CMD_TX_STOP 0x0012
+#define RACFG_CMD_RX_START 0x0013
+#define RACFG_CMD_RX_STOP 0x0014
+#define RACFG_CMD_GET_NOISE_LEVEL 0x0015
+
+#define RACFG_CMD_ATE_START 0x0080
+#define RACFG_CMD_ATE_STOP 0x0081
+
+#define RACFG_CMD_ATE_START_TX_CARRIER 0x0100
+#define RACFG_CMD_ATE_START_TX_CONT 0x0101
+#define RACFG_CMD_ATE_START_TX_FRAME 0x0102
+#define RACFG_CMD_ATE_SET_BW 0x0103
+#define RACFG_CMD_ATE_SET_TX_POWER0 0x0104
+#define RACFG_CMD_ATE_SET_TX_POWER1 0x0105
+#define RACFG_CMD_ATE_SET_FREQ_OFFSET 0x0106
+#define RACFG_CMD_ATE_GET_STATISTICS 0x0107
+#define RACFG_CMD_ATE_RESET_COUNTER 0x0108
+#define RACFG_CMD_ATE_SEL_TX_ANTENNA 0x0109
+#define RACFG_CMD_ATE_SEL_RX_ANTENNA 0x010a
+#define RACFG_CMD_ATE_SET_PREAMBLE 0x010b
+#define RACFG_CMD_ATE_SET_CHANNEL 0x010c
+#define RACFG_CMD_ATE_SET_ADDR1 0x010d
+#define RACFG_CMD_ATE_SET_ADDR2 0x010e
+#define RACFG_CMD_ATE_SET_ADDR3 0x010f
+#define RACFG_CMD_ATE_SET_RATE 0x0110
+#define RACFG_CMD_ATE_SET_TX_FRAME_LEN 0x0111
+#define RACFG_CMD_ATE_SET_TX_FRAME_COUNT 0x0112
+#define RACFG_CMD_ATE_START_RX_FRAME 0x0113
+#define RACFG_CMD_ATE_E2PROM_READ_BULK 0x0114
+#define RACFG_CMD_ATE_E2PROM_WRITE_BULK 0x0115
+#define RACFG_CMD_ATE_IO_WRITE_BULK 0x0116
+#define RACFG_CMD_ATE_BBP_READ_BULK 0x0117
+#define RACFG_CMD_ATE_BBP_WRITE_BULK 0x0118
+#define RACFG_CMD_ATE_RF_READ_BULK 0x0119
+#define RACFG_CMD_ATE_RF_WRITE_BULK 0x011a
+
+
+
+#define A2Hex(_X, _p) \
+{ \
+ UCHAR *p; \
+ _X = 0; \
+ p = _p; \
+ while (((*p >= 'a') && (*p <= 'f')) || ((*p >= 'A') && (*p <= 'F')) || ((*p >= '0') && (*p <= '9'))) \
+ { \
+ if ((*p >= 'a') && (*p <= 'f')) \
+ _X = _X * 16 + *p - 87; \
+ else if ((*p >= 'A') && (*p <= 'F')) \
+ _X = _X * 16 + *p - 55; \
+ else if ((*p >= '0') && (*p <= '9')) \
+ _X = _X * 16 + *p - 48; \
+ p++; \
+ } \
+}
+
+
+static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len);
+static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len);
+static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len);
+
+#ifdef UCOS
+int ate_copy_to_user(
+ IN PUCHAR payload,
+ IN PUCHAR msg,
+ IN INT len)
+{
+ memmove(payload, msg, len);
+ return 0;
+}
+
+#undef copy_to_user
+#define copy_to_user(x,y,z) ate_copy_to_user((PUCHAR)x, (PUCHAR)y, z)
+#endif // UCOS //
+
+#define LEN_OF_ARG 16
+
+VOID RtmpDoAte(
+ IN PRTMP_ADAPTER pAdapter,
+ IN struct iwreq *wrq)
+{
+ unsigned short Command_Id;
+ struct ate_racfghdr *pRaCfg;
+ INT Status = NDIS_STATUS_SUCCESS;
+
+
+
+ if((pRaCfg = kmalloc(sizeof(struct ate_racfghdr), GFP_KERNEL)) == NULL)
+ {
+ Status = -EINVAL;
+ return;
+ }
+
+ NdisZeroMemory(pRaCfg, sizeof(struct ate_racfghdr));
+
+ if (copy_from_user((PUCHAR)pRaCfg, wrq->u.data.pointer, wrq->u.data.length))
+ {
+ Status = -EFAULT;
+ kfree(pRaCfg);
+ return;
+ }
+
+
+ Command_Id = ntohs(pRaCfg->command_id);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __func__, Command_Id));
+
+ switch (Command_Id)
+ {
+ // We will get this command when QA starts.
+ case RACFG_CMD_ATE_START:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START\n"));
+
+ // prepare feedback as soon as we can to avoid QA timeout.
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_ATE_START\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START is done !\n"));
+ }
+ Set_ATE_Proc(pAdapter, "ATESTART");
+ }
+ break;
+
+ // We will get this command either QA is closed or ated is killed by user.
+ case RACFG_CMD_ATE_STOP:
+ {
+#ifndef UCOS
+ INT32 ret;
+#endif // !UCOS //
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_STOP\n"));
+
+ // Distinguish this command came from QA(via ated)
+ // or ate daemon according to the existence of pid in payload.
+ // No need to prepare feedback if this cmd came directly from ate daemon.
+ pRaCfg->length = ntohs(pRaCfg->length);
+
+ if (pRaCfg->length == sizeof(pAdapter->ate.AtePid))
+ {
+ // This command came from QA.
+ // Get the pid of ATE daemon.
+ memcpy((UCHAR *)&pAdapter->ate.AtePid,
+ (&pRaCfg->data[0]) - 2/* == &(pRaCfg->status) */,
+ sizeof(pAdapter->ate.AtePid));
+
+ // prepare feedback as soon as we can to avoid QA timeout.
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_STOP\n"));
+ Status = -EFAULT;
+ }
+
+ //
+ // kill ATE daemon when leaving ATE mode.
+ // We must kill ATE daemon first before setting ATESTOP,
+ // or Microsoft will report sth. wrong.
+#ifndef UCOS
+ ret = KILL_THREAD_PID(pAdapter->ate.AtePid, SIGTERM, 1);
+ if (ret)
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("%s: unable to signal thread\n", pAdapter->net_dev->name));
+ }
+#endif // !UCOS //
+ }
+
+ // AP might have in ATE_STOP mode due to cmd from QA.
+ if (ATE_ON(pAdapter))
+ {
+ // Someone has killed ate daemon while QA GUI is still open.
+ Set_ATE_Proc(pAdapter, "ATESTOP");
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_AP_START is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_RF_WRITE_ALL:
+ {
+ UINT32 R1, R2, R3, R4;
+ USHORT channel;
+
+ memcpy(&R1, pRaCfg->data-2, 4);
+ memcpy(&R2, pRaCfg->data+2, 4);
+ memcpy(&R3, pRaCfg->data+6, 4);
+ memcpy(&R4, pRaCfg->data+10, 4);
+ memcpy(&channel, pRaCfg->data+14, 2);
+
+ pAdapter->LatchRfRegs.R1 = ntohl(R1);
+ pAdapter->LatchRfRegs.R2 = ntohl(R2);
+ pAdapter->LatchRfRegs.R3 = ntohl(R3);
+ pAdapter->LatchRfRegs.R4 = ntohl(R4);
+ pAdapter->LatchRfRegs.Channel = ntohs(channel);
+
+ RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R1);
+ RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R2);
+ RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R3);
+ RTMP_RF_IO_WRITE32(pAdapter, pAdapter->LatchRfRegs.R4);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RF_WRITE_ALL\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RF_WRITE_ALL is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_E2PROM_READ16:
+ {
+ USHORT offset, value, tmp;
+
+ offset = ntohs(pRaCfg->status);
+ /* "tmp" is expecially for some compilers... */
+ RT28xx_EEPROM_READ16(pAdapter, offset, tmp);
+ value = tmp;
+ value = htons(value);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("EEPROM Read offset = 0x%04x, value = 0x%04x\n", offset, value));
+
+ // prepare feedback
+ pRaCfg->length = htons(4);
+ pRaCfg->status = htons(0);
+ memcpy(pRaCfg->data, &value, 2);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("sizeof(struct ate_racfghdr) = %d\n", sizeof(struct ate_racfghdr)));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ16\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ16 is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_E2PROM_WRITE16:
+ {
+ USHORT offset, value;
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&value, pRaCfg->data, 2);
+ value = ntohs(value);
+ RT28xx_EEPROM_WRITE16(pAdapter, offset, value);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE16\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_WRITE16 is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_E2PROM_READ_ALL:
+ {
+ USHORT buffer[EEPROM_SIZE/2];
+
+ rt_ee_read_all(pAdapter,(USHORT *)buffer);
+ memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer, EEPROM_SIZE);
+
+ // prepare feedback
+ pRaCfg->length = htons(2+EEPROM_SIZE);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_READ_ALL\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_E2PROM_READ_ALL is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_E2PROM_WRITE_ALL:
+ {
+ USHORT buffer[EEPROM_SIZE/2];
+
+ NdisZeroMemory((UCHAR *)buffer, EEPROM_SIZE);
+ memcpy_exs(pAdapter, (UCHAR *)buffer, (UCHAR *)&pRaCfg->status, EEPROM_SIZE);
+ rt_ee_write_all(pAdapter,(USHORT *)buffer);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_E2PROM_WRITE_ALL\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_E2PROM_WRITE_ALL is done !\n"));
+ }
+
+ }
+ break;
+
+ case RACFG_CMD_IO_READ:
+ {
+ UINT32 offset;
+ UINT32 value;
+
+ memcpy(&offset, &pRaCfg->status, 4);
+ offset = ntohl(offset);
+
+ // We do not need the base address.
+ // So just extract the offset out.
+ offset &= 0x0000FFFF;
+ RTMP_IO_READ32(pAdapter, offset, &value);
+ value = htonl(value);
+
+ // prepare feedback
+ pRaCfg->length = htons(6);
+ pRaCfg->status = htons(0);
+ memcpy(pRaCfg->data, &value, 4);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_IO_WRITE:
+ {
+ UINT32 offset, value;
+
+ memcpy(&offset, pRaCfg->data-2, 4);
+ memcpy(&value, pRaCfg->data+2, 4);
+
+ offset = ntohl(offset);
+
+ // We do not need the base address.
+ // So just extract out the offset.
+ offset &= 0x0000FFFF;
+ value = ntohl(value);
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_IO_WRITE: offset = %x, value = %x\n", offset, value));
+ RTMP_IO_WRITE32(pAdapter, offset, value);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_WRITE\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_WRITE is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_IO_READ_BULK:
+ {
+ UINT32 offset;
+ USHORT len;
+
+ memcpy(&offset, &pRaCfg->status, 4);
+ offset = ntohl(offset);
+
+ // We do not need the base address.
+ // So just extract the offset.
+ offset &= 0x0000FFFF;
+ memcpy(&len, pRaCfg->data+2, 2);
+ len = ntohs(len);
+
+ if (len > 371)
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("len is too large, make it smaller\n"));
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(1);
+ break;
+ }
+
+ RTMP_IO_READ_BULK(pAdapter, pRaCfg->data, (UCHAR *)offset, len*4);// unit in four bytes
+
+ // prepare feedback
+ pRaCfg->length = htons(2+len*4);// unit in four bytes
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_IO_READ_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_IO_READ_BULK is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_BBP_READ8:
+ {
+ USHORT offset;
+ UCHAR value;
+
+ value = 0;
+ offset = ntohs(pRaCfg->status);
+
+ if (ATE_ON(pAdapter))
+ {
+ ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value);
+ }
+ else
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, offset, &value);
+ }
+ // prepare feedback
+ pRaCfg->length = htons(3);
+ pRaCfg->status = htons(0);
+ pRaCfg->data[0] = value;
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("BBP value = %x\n", value));
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ8\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ8 is done !\n"));
+ }
+ }
+ break;
+ case RACFG_CMD_BBP_WRITE8:
+ {
+ USHORT offset;
+ UCHAR value;
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&value, pRaCfg->data, 1);
+
+ if (ATE_ON(pAdapter))
+ {
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value);
+ }
+ else
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, offset, value);
+ }
+
+ if ((offset == BBP_R1) || (offset == BBP_R3))
+ {
+ SyncTxRxConfig(pAdapter, offset, value);
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_WRITE8\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_WRITE8 is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_BBP_READ_ALL:
+ {
+ USHORT j;
+
+ for (j = 0; j < 137; j++)
+ {
+ pRaCfg->data[j] = 0;
+
+ if (ATE_ON(pAdapter))
+ {
+ ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]);
+ }
+ else
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j]);
+ }
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2+137);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_BBP_READ_ALL\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_BBP_READ_ALL is done !\n"));
+ }
+ }
+
+ break;
+
+ case RACFG_CMD_ATE_E2PROM_READ_BULK:
+ {
+ USHORT offset;
+ USHORT len;
+ USHORT buffer[EEPROM_SIZE/2];
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&len, pRaCfg->data, 2);
+ len = ntohs(len);
+
+ rt_ee_read_all(pAdapter,(USHORT *)buffer);
+ if (offset + len <= EEPROM_SIZE)
+ memcpy_exs(pAdapter, pRaCfg->data, (UCHAR *)buffer+offset, len);
+ else
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("exceed EEPROM size\n"));
+
+ // prepare feedback
+ pRaCfg->length = htons(2+len);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_READ_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_E2PROM_READ_BULK is done !\n"));
+ }
+
+ }
+ break;
+
+ case RACFG_CMD_ATE_E2PROM_WRITE_BULK:
+ {
+ USHORT offset;
+ USHORT len;
+ USHORT buffer[EEPROM_SIZE/2];
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&len, pRaCfg->data, 2);
+ len = ntohs(len);
+
+ rt_ee_read_all(pAdapter,(USHORT *)buffer);
+ memcpy_exs(pAdapter, (UCHAR *)buffer + offset, (UCHAR *)pRaCfg->data + 2, len);
+ rt_ee_write_all(pAdapter,(USHORT *)buffer);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_E2PROM_WRITE_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_E2PROM_WRITE_BULK is done !\n"));
+ }
+
+ }
+ break;
+
+ case RACFG_CMD_ATE_IO_WRITE_BULK:
+ {
+ UINT32 offset, i, value;
+ USHORT len;
+
+ memcpy(&offset, &pRaCfg->status, 4);
+ offset = ntohl(offset);
+ memcpy(&len, pRaCfg->data+2, 2);
+ len = ntohs(len);
+
+ for (i = 0; i < len; i += 4)
+ {
+ memcpy_exl(pAdapter, (UCHAR *)&value, pRaCfg->data+4+i, 4);
+ printk("Write %x %x\n", offset + i, value);
+ RTMP_IO_WRITE32(pAdapter, (offset +i) & 0xffff, value);
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_IO_WRITE_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("RACFG_CMD_ATE_IO_WRITE_BULK is done !\n"));
+ }
+
+ }
+ break;
+
+ case RACFG_CMD_ATE_BBP_READ_BULK:
+ {
+ USHORT offset;
+ USHORT len;
+ USHORT j;
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&len, pRaCfg->data, 2);
+ len = ntohs(len);
+
+
+ for (j = offset; j < (offset+len); j++)
+ {
+ pRaCfg->data[j - offset] = 0;
+
+ if (pAdapter->ate.Mode == ATE_STOP)
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]);
+ }
+ else
+ {
+ ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, j, &pRaCfg->data[j - offset]);
+ }
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2+len);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_READ_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_READ_BULK is done !\n"));
+ }
+
+ }
+ break;
+
+ case RACFG_CMD_ATE_BBP_WRITE_BULK:
+ {
+ USHORT offset;
+ USHORT len;
+ USHORT j;
+ UCHAR *value;
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&len, pRaCfg->data, 2);
+ len = ntohs(len);
+
+ for (j = offset; j < (offset+len); j++)
+ {
+ value = pRaCfg->data + 2 + (j - offset);
+ if (pAdapter->ate.Mode == ATE_STOP)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value);
+ }
+ else
+ {
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAdapter, j, *value);
+ }
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_BBP_WRITE_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_BBP_WRITE_BULK is done !\n"));
+ }
+ }
+ break;
+
+#ifdef CONFIG_RALINK_RT3052
+ case RACFG_CMD_ATE_RF_READ_BULK:
+ {
+ USHORT offset;
+ USHORT len;
+ USHORT j;
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&len, pRaCfg->data, 2);
+ len = ntohs(len);
+
+ for (j = offset; j < (offset+len); j++)
+ {
+ pRaCfg->data[j - offset] = 0;
+ RT30xxReadRFRegister(pAdapter, j, &pRaCfg->data[j - offset]);
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2+len);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_READ_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_READ_BULK is done !\n"));
+ }
+
+ }
+ break;
+
+ case RACFG_CMD_ATE_RF_WRITE_BULK:
+ {
+ USHORT offset;
+ USHORT len;
+ USHORT j;
+ UCHAR *value;
+
+ offset = ntohs(pRaCfg->status);
+ memcpy(&len, pRaCfg->data, 2);
+ len = ntohs(len);
+
+ for (j = offset; j < (offset+len); j++)
+ {
+ value = pRaCfg->data + 2 + (j - offset);
+ RT30xxWriteRFRegister(pAdapter, j, *value);
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RF_WRITE_BULK\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RF_WRITE_BULK is done !\n"));
+ }
+
+ }
+ break;
+#endif
+
+
+ case RACFG_CMD_GET_NOISE_LEVEL:
+ {
+ UCHAR channel;
+ INT32 buffer[3][10];/* 3 : RxPath ; 10 : no. of per rssi samples */
+
+ channel = (ntohs(pRaCfg->status) & 0x00FF);
+ CalNoiseLevel(pAdapter, channel, buffer);
+ memcpy_exl(pAdapter, (UCHAR *)pRaCfg->data, (UCHAR *)&(buffer[0][0]), (sizeof(INT32)*3*10));
+
+ // prepare feedback
+ pRaCfg->length = htons(2 + (sizeof(INT32)*3*10));
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_NOISE_LEVEL\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_NOISE_LEVEL is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_GET_COUNTER:
+ {
+ memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.U2M, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->ate.OtherData, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->ate.Beacon, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->ate.OtherCount, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->ate.TxAc0, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->ate.TxAc1, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->ate.TxAc2, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->ate.TxAc3, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->ate.TxHCCA, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->ate.TxMgmt, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&pAdapter->ate.RSSI0, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&pAdapter->ate.RSSI1, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&pAdapter->ate.RSSI2, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[52], (UCHAR *)&pAdapter->ate.SNR0, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[56], (UCHAR *)&pAdapter->ate.SNR1, 4);
+
+ pRaCfg->length = htons(2+60);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_COUNTER\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_COUNTER is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_CLEAR_COUNTER:
+ {
+ pAdapter->ate.U2M = 0;
+ pAdapter->ate.OtherData = 0;
+ pAdapter->ate.Beacon = 0;
+ pAdapter->ate.OtherCount = 0;
+ pAdapter->ate.TxAc0 = 0;
+ pAdapter->ate.TxAc1 = 0;
+ pAdapter->ate.TxAc2 = 0;
+ pAdapter->ate.TxAc3 = 0;
+ pAdapter->ate.TxHCCA = 0;
+ pAdapter->ate.TxMgmt = 0;
+ pAdapter->ate.TxDoneCount = 0;
+
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_CLEAR_COUNTER\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_CLEAR_COUNTER is done !\n"));
+ }
+ }
+
+ break;
+
+ case RACFG_CMD_TX_START:
+ {
+ USHORT *p;
+ USHORT err = 1;
+ UCHAR Bbp22Value = 0, Bbp24Value = 0;
+
+ if ((pAdapter->ate.TxStatus != 0) && (pAdapter->ate.Mode & ATE_TXFRAME))
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("Ate Tx is already running, to run next Tx, you must stop it first\n"));
+ err = 2;
+ goto TX_START_ERROR;
+ }
+ else if ((pAdapter->ate.TxStatus != 0) && !(pAdapter->ate.Mode & ATE_TXFRAME))
+ {
+ int i = 0;
+
+ while ((i++ < 10) && (pAdapter->ate.TxStatus != 0))
+ {
+ RTMPusecDelay(5000);
+ }
+
+ // force it to stop
+ pAdapter->ate.TxStatus = 0;
+ pAdapter->ate.TxDoneCount = 0;
+ //pAdapter->ate.Repeat = 0;
+ pAdapter->ate.bQATxStart = FALSE;
+ }
+
+ // If pRaCfg->length == 0, this "RACFG_CMD_TX_START" is for Carrier test or Carrier Suppression.
+ if (ntohs(pRaCfg->length) != 0)
+ {
+ // Get frame info
+
+ NdisMoveMemory(&pAdapter->ate.TxWI, pRaCfg->data + 2, 16);
+#ifdef RT_BIG_ENDIAN
+ RTMPWIEndianChange((PUCHAR)&pAdapter->ate.TxWI, TYPE_TXWI);
+#endif // RT_BIG_ENDIAN //
+
+ NdisMoveMemory(&pAdapter->ate.TxCount, pRaCfg->data + 18, 4);
+ pAdapter->ate.TxCount = ntohl(pAdapter->ate.TxCount);
+
+ p = (USHORT *)(&pRaCfg->data[22]);
+ //p = pRaCfg->data + 22;
+ // always use QID_AC_BE
+ pAdapter->ate.QID = 0;
+ p = (USHORT *)(&pRaCfg->data[24]);
+ //p = pRaCfg->data + 24;
+ pAdapter->ate.HLen = ntohs(*p);
+
+ if (pAdapter->ate.HLen > 32)
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.HLen > 32\n"));
+ err = 3;
+ goto TX_START_ERROR;
+ }
+
+ NdisMoveMemory(&pAdapter->ate.Header, pRaCfg->data + 26, pAdapter->ate.HLen);
+
+
+ pAdapter->ate.PLen = ntohs(pRaCfg->length) - (pAdapter->ate.HLen + 28);
+
+ if (pAdapter->ate.PLen > 32)
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR,("pAdapter->ate.PLen > 32\n"));
+ err = 4;
+ goto TX_START_ERROR;
+ }
+
+ NdisMoveMemory(&pAdapter->ate.Pattern, pRaCfg->data + 26 + pAdapter->ate.HLen, pAdapter->ate.PLen);
+ pAdapter->ate.DLen = pAdapter->ate.TxWI.MPDUtotalByteCount - pAdapter->ate.HLen;
+ }
+
+ ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, BBP_R22, &Bbp22Value);
+
+ switch (Bbp22Value)
+ {
+ case BBP22_TXFRAME:
+ {
+ if (pAdapter->ate.TxCount == 0)
+ {
+#ifdef RT2860
+ pAdapter->ate.TxCount = 0xFFFFFFFF;
+#endif // RT2860 //
+ }
+ ATEDBGPRINT(RT_DEBUG_TRACE,("START TXFRAME\n"));
+ pAdapter->ate.bQATxStart = TRUE;
+ Set_ATE_Proc(pAdapter, "TXFRAME");
+ }
+ break;
+
+ case BBP22_TXCONT_OR_CARRSUPP:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("BBP22_TXCONT_OR_CARRSUPP\n"));
+ ATE_BBP_IO_READ8_BY_REG_ID(pAdapter, 24, &Bbp24Value);
+
+ switch (Bbp24Value)
+ {
+ case BBP24_TXCONT:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCONT\n"));
+ pAdapter->ate.bQATxStart = TRUE;
+ Set_ATE_Proc(pAdapter, "TXCONT");
+ }
+ break;
+
+ case BBP24_CARRSUPP:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARRSUPP\n"));
+ pAdapter->ate.bQATxStart = TRUE;
+ pAdapter->ate.Mode |= ATE_TXCARRSUPP;
+ }
+ break;
+
+ default:
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !"));
+ }
+ break;
+ }
+ }
+ break;
+
+ case BBP22_TXCARR:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("START TXCARR\n"));
+ pAdapter->ate.bQATxStart = TRUE;
+ Set_ATE_Proc(pAdapter, "TXCARR");
+ }
+ break;
+
+ default:
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR,("Unknown Start TX subtype !"));
+ }
+ break;
+ }
+
+ if (pAdapter->ate.bQATxStart == TRUE)
+ {
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() was failed in case RACFG_CMD_TX_START\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_START is done !\n"));
+ }
+ break;
+ }
+
+TX_START_ERROR:
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(err);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_TX_START\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("feedback of TX_START_ERROR is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_GET_TX_STATUS:
+ {
+ UINT32 count;
+
+ // prepare feedback
+ pRaCfg->length = htons(6);
+ pRaCfg->status = htons(0);
+ count = htonl(pAdapter->ate.TxDoneCount);
+ NdisMoveMemory(pRaCfg->data, &count, 4);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_GET_TX_STATUS\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_GET_TX_STATUS is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_TX_STOP:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_TX_STOP\n"));
+
+ Set_ATE_Proc(pAdapter, "TXSTOP");
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("copy_to_user() fail in case RACFG_CMD_TX_STOP\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_TX_STOP is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_RX_START:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n"));
+
+ pAdapter->ate.bQARxStart = TRUE;
+ Set_ATE_Proc(pAdapter, "RXFRAME");
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_RX_STOP:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_STOP\n"));
+
+ Set_ATE_Proc(pAdapter, "RXSTOP");
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_STOP\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_STOP is done !\n"));
+ }
+ }
+ break;
+
+ /* The following cases are for new ATE GUI(not QA). */
+ /*==================================================*/
+ case RACFG_CMD_ATE_START_TX_CARRIER:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CARRIER\n"));
+
+ Set_ATE_Proc(pAdapter, "TXCARR");
+
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CARRIER\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CARRIER is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_START_TX_CONT:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_CONT\n"));
+
+ Set_ATE_Proc(pAdapter, "TXCONT");
+
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_CONT\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_CONT is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_START_TX_FRAME:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_START_TX_FRAME\n"));
+
+ Set_ATE_Proc(pAdapter, "TXFRAME");
+
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("wrq->u.data.length = %d\n", wrq->u.data.length));
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_START_TX_FRAME\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_START_TX_FRAME is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_BW:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_BW\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+
+ Set_ATE_TX_BW_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_BW\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_BW is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_TX_POWER0:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER0\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_POWER0_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER0\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER0 is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_TX_POWER1:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_POWER1\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_POWER1_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_POWER1\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_POWER1 is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_FREQ_OFFSET:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_FREQ_OFFSET\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_FREQOFFSET_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_FREQ_OFFSET\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_FREQ_OFFSET is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_GET_STATISTICS:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_GET_STATISTICS\n"));
+
+ memcpy_exl(pAdapter, &pRaCfg->data[0], (UCHAR *)&pAdapter->ate.TxDoneCount, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[4], (UCHAR *)&pAdapter->WlanCounters.RetryCount.u.LowPart, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[8], (UCHAR *)&pAdapter->WlanCounters.FailedCount.u.LowPart, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[12], (UCHAR *)&pAdapter->WlanCounters.RTSSuccessCount.u.LowPart, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[16], (UCHAR *)&pAdapter->WlanCounters.RTSFailureCount.u.LowPart, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[20], (UCHAR *)&pAdapter->WlanCounters.ReceivedFragmentCount.QuadPart, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[24], (UCHAR *)&pAdapter->WlanCounters.FCSErrorCount.u.LowPart, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[28], (UCHAR *)&pAdapter->Counters8023.RxNoBuffer, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[32], (UCHAR *)&pAdapter->WlanCounters.FrameDuplicateCount.u.LowPart, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[36], (UCHAR *)&pAdapter->RalinkCounters.OneSecFalseCCACnt, 4);
+
+ if (pAdapter->ate.RxAntennaSel == 0)
+ {
+ INT32 RSSI0 = 0;
+ INT32 RSSI1 = 0;
+ INT32 RSSI2 = 0;
+
+ RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta);
+ RSSI1 = (INT32)(pAdapter->ate.LastRssi1 - pAdapter->BbpRssiToDbmDelta);
+ RSSI2 = (INT32)(pAdapter->ate.LastRssi2 - pAdapter->BbpRssiToDbmDelta);
+ memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[44], (UCHAR *)&RSSI1, 4);
+ memcpy_exl(pAdapter, &pRaCfg->data[48], (UCHAR *)&RSSI2, 4);
+ pRaCfg->length = htons(2+52);
+ }
+ else
+ {
+ INT32 RSSI0 = 0;
+
+ RSSI0 = (INT32)(pAdapter->ate.LastRssi0 - pAdapter->BbpRssiToDbmDelta);
+ memcpy_exl(pAdapter, &pRaCfg->data[40], (UCHAR *)&RSSI0, 4);
+ pRaCfg->length = htons(2+44);
+ }
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_GET_STATISTICS\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_GET_STATISTICS is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_RESET_COUNTER:
+ {
+ SHORT value = 1;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_RESET_COUNTER\n"));
+
+ sprintf((PCHAR)str, "%d", value);
+ Set_ResetStatCounter_Proc(pAdapter, str);
+
+ pAdapter->ate.TxDoneCount = 0;
+
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_RESET_COUNTER\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_RESET_COUNTER is done !\n"));
+ }
+ }
+
+ break;
+
+ case RACFG_CMD_ATE_SEL_TX_ANTENNA:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_TX_ANTENNA\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_Antenna_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_TX_ANTENNA\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_TX_ANTENNA is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SEL_RX_ANTENNA:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SEL_RX_ANTENNA\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_RX_Antenna_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SEL_RX_ANTENNA\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SEL_RX_ANTENNA is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_PREAMBLE:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_PREAMBLE\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_MODE_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_PREAMBLE\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_PREAMBLE is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_CHANNEL:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_CHANNEL\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_CHANNEL_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_CHANNEL\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_CHANNEL is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_ADDR1:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR1\n"));
+
+ // Addr is an array of UCHAR,
+ // so no need to perform endian swap.
+ memcpy(pAdapter->ate.Addr1, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR1\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR1 is done !\n (ADDR1 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr1[0],
+ pAdapter->ate.Addr1[1], pAdapter->ate.Addr1[2], pAdapter->ate.Addr1[3], pAdapter->ate.Addr1[4], pAdapter->ate.Addr1[5]));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_ADDR2:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR2\n"));
+
+ // Addr is an array of UCHAR,
+ // so no need to perform endian swap.
+ memcpy(pAdapter->ate.Addr2, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR2\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR2 is done !\n (ADDR2 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr2[0],
+ pAdapter->ate.Addr2[1], pAdapter->ate.Addr2[2], pAdapter->ate.Addr2[3], pAdapter->ate.Addr2[4], pAdapter->ate.Addr2[5]));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_ADDR3:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_ADDR3\n"));
+
+ // Addr is an array of UCHAR,
+ // so no need to perform endian swap.
+ memcpy(pAdapter->ate.Addr3, (PUCHAR)(pRaCfg->data - 2), MAC_ADDR_LEN);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_ADDR3\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_ADDR3 is done !\n (ADDR3 = %2X:%2X:%2X:%2X:%2X:%2X)\n", pAdapter->ate.Addr3[0],
+ pAdapter->ate.Addr3[1], pAdapter->ate.Addr3[2], pAdapter->ate.Addr3[3], pAdapter->ate.Addr3[4], pAdapter->ate.Addr3[5]));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_RATE:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_RATE\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_MCS_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_RATE\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_RATE is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_TX_FRAME_LEN:
+ {
+ SHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_LEN\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_LENGTH_Proc(pAdapter, str);
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_LEN\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_LEN is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_SET_TX_FRAME_COUNT:
+ {
+ USHORT value = 0;
+ UCHAR str[LEN_OF_ARG];
+
+ NdisZeroMemory(str, LEN_OF_ARG);
+
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n"));
+
+ memcpy((PUCHAR)&value, (PUCHAR)&(pRaCfg->status), 2);
+ value = ntohs(value);
+#ifdef RT2860
+ /* TX_FRAME_COUNT == 0 means tx infinitely */
+ if (value == 0)
+ {
+ /* Use TxCount = 0xFFFFFFFF to approximate the infinity. */
+ pAdapter->ate.TxCount = 0xFFFFFFFF;
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_TX_COUNT_Proc (TxCount = %d)\n", pAdapter->ate.TxCount));
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("Ralink: Set_ATE_TX_COUNT_Proc Success\n"));
+
+
+ }
+ else
+#endif // RT2860 //
+ {
+ sprintf((PCHAR)str, "%d", value);
+ Set_ATE_TX_COUNT_Proc(pAdapter, str);
+ }
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_ATE_SET_TX_FRAME_COUNT\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_ATE_SET_TX_FRAME_COUNT is done !\n"));
+ }
+ }
+ break;
+
+ case RACFG_CMD_ATE_START_RX_FRAME:
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE,("RACFG_CMD_RX_START\n"));
+
+ Set_ATE_Proc(pAdapter, "RXFRAME");
+
+ // prepare feedback
+ pRaCfg->length = htons(2);
+ pRaCfg->status = htons(0);
+ wrq->u.data.length = sizeof(pRaCfg->magic_no) + sizeof(pRaCfg->command_type)
+ + sizeof(pRaCfg->command_id) + sizeof(pRaCfg->length)
+ + sizeof(pRaCfg->sequence) + ntohs(pRaCfg->length);
+
+ if (copy_to_user(wrq->u.data.pointer, pRaCfg, wrq->u.data.length))
+ {
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("copy_to_user() fail in case RACFG_CMD_RX_START\n"));
+ Status = -EFAULT;
+ }
+ else
+ {
+ ATEDBGPRINT(RT_DEBUG_TRACE, ("RACFG_CMD_RX_START is done !\n"));
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ ASSERT(pRaCfg != NULL);
+ if (pRaCfg != NULL)
+ {
+ kfree(pRaCfg);
+ }
+ return;
+}
+
+VOID BubbleSort(INT32 n, INT32 a[])
+{
+ INT32 k, j, temp;
+
+ for (k = n-1; k>0; k--)
+ {
+ for (j = 0; j<k; j++)
+ {
+ if(a[j] > a[j+1])
+ {
+ temp = a[j];
+ a[j]=a[j+1];
+ a[j+1]=temp;
+ }
+ }
+ }
+}
+
+VOID CalNoiseLevel(PRTMP_ADAPTER pAd, UCHAR channel, INT32 RSSI[3][10])
+{
+ INT32 RSSI0, RSSI1, RSSI2;
+ CHAR Rssi0Offset, Rssi1Offset, Rssi2Offset;
+ UCHAR BbpR50Rssi0 = 0, BbpR51Rssi1 = 0, BbpR52Rssi2 = 0;
+ UCHAR Org_BBP66value = 0, Org_BBP69value = 0, Org_BBP70value = 0, data = 0;
+ USHORT LNA_Gain = 0;
+ INT32 j = 0;
+ UCHAR Org_Channel = pAd->ate.Channel;
+ USHORT GainValue = 0, OffsetValue = 0;
+
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &Org_BBP66value);
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R69, &Org_BBP69value);
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R70, &Org_BBP70value);
+
+ //**********************************************************************
+ // Read the value of LNA gain and Rssi offset
+ //**********************************************************************
+ RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, GainValue);
+
+ // for Noise Level
+ if (channel <= 14)
+ {
+ LNA_Gain = GainValue & 0x00FF;
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, OffsetValue);
+ Rssi0Offset = OffsetValue & 0x00FF;
+ Rssi1Offset = (OffsetValue & 0xFF00) >> 8;
+ RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_BG_OFFSET + 2)/* 0x48 */, OffsetValue);
+ Rssi2Offset = OffsetValue & 0x00FF;
+ }
+ else
+ {
+ LNA_Gain = (GainValue & 0xFF00) >> 8;
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, OffsetValue);
+ Rssi0Offset = OffsetValue & 0x00FF;
+ Rssi1Offset = (OffsetValue & 0xFF00) >> 8;
+ RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET + 2)/* 0x4C */, OffsetValue);
+ Rssi2Offset = OffsetValue & 0x00FF;
+ }
+ //**********************************************************************
+ {
+ pAd->ate.Channel = channel;
+ ATEAsicSwitchChannel(pAd);
+ mdelay(5);
+
+ data = 0x10;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, data);
+ data = 0x40;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, data);
+ data = 0x40;
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, data);
+ mdelay(5);
+
+ // Start Rx
+ pAd->ate.bQARxStart = TRUE;
+ Set_ATE_Proc(pAd, "RXFRAME");
+
+ mdelay(5);
+
+ for (j = 0; j < 10; j++)
+ {
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R50, &BbpR50Rssi0);
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R51, &BbpR51Rssi1);
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R52, &BbpR52Rssi2);
+
+ mdelay(10);
+
+ // Calculate RSSI 0
+ if (BbpR50Rssi0 == 0)
+ {
+ RSSI0 = -100;
+ }
+ else
+ {
+ RSSI0 = (INT32)(-12 - BbpR50Rssi0 - LNA_Gain - Rssi0Offset);
+ }
+ RSSI[0][j] = RSSI0;
+
+ if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+ {
+ // Calculate RSSI 1
+ if (BbpR51Rssi1 == 0)
+ {
+ RSSI1 = -100;
+ }
+ else
+ {
+ RSSI1 = (INT32)(-12 - BbpR51Rssi1 - LNA_Gain - Rssi1Offset);
+ }
+ RSSI[1][j] = RSSI1;
+ }
+
+ if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+ {
+ // Calculate RSSI 2
+ if (BbpR52Rssi2 == 0)
+ RSSI2 = -100;
+ else
+ RSSI2 = (INT32)(-12 - BbpR52Rssi2 - LNA_Gain - Rssi2Offset);
+
+ RSSI[2][j] = RSSI2;
+ }
+ }
+
+ // Stop Rx
+ Set_ATE_Proc(pAd, "RXSTOP");
+
+ mdelay(5);
+
+#if 0// Debug Message................
+ ate_print("\n**********************************************************\n");
+ ate_print("Noise Level: Channel %d\n", channel);
+ ate_print("RSSI0 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ RSSI[0][0], RSSI[0][1], RSSI[0][2],
+ RSSI[0][3], RSSI[0][4], RSSI[0][5],
+ RSSI[0][6], RSSI[0][7], RSSI[0][8],
+ RSSI[0][9]);
+ if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+ {
+ ate_print("RSSI1 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ RSSI[1][0], RSSI[1][1], RSSI[1][2],
+ RSSI[1][3], RSSI[1][4], RSSI[1][5],
+ RSSI[1][6], RSSI[1][7], RSSI[1][8],
+ RSSI[1][9]);
+ }
+ if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+ {
+ ate_print("RSSI2 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ RSSI[2][0], RSSI[2][1], RSSI[2][2],
+ RSSI[2][3], RSSI[2][4], RSSI[2][5],
+ RSSI[2][6], RSSI[2][7], RSSI[2][8],
+ RSSI[2][9]);
+ }
+#endif // 0 //
+ BubbleSort(10, RSSI[0]); // 1R
+
+ if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+ {
+ BubbleSort(10, RSSI[1]);
+ }
+
+ if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+ {
+ BubbleSort(10, RSSI[2]);
+ }
+
+#if 0// Debug Message................
+ ate_print("\nAfter Sorting....Channel %d\n", channel);
+ ate_print("RSSI0 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ RSSI[0][0], RSSI[0][1], RSSI[0][2],
+ RSSI[0][3], RSSI[0][4], RSSI[0][5],
+ RSSI[0][6], RSSI[0][7], RSSI[0][8],
+ RSSI[0][9]);
+ if ( pAd->Antenna.field.RxPath >= 2 ) // 2R
+ {
+ ate_print("RSSI1 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ RSSI[1][0], RSSI[1][1], RSSI[1][2],
+ RSSI[1][3], RSSI[1][4], RSSI[1][5],
+ RSSI[1][6], RSSI[1][7], RSSI[1][8],
+ RSSI[1][9]);
+ }
+ if ( pAd->Antenna.field.RxPath >= 3 ) // 3R
+ {
+ ate_print("RSSI2 = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ RSSI[2][0], RSSI[2][1], RSSI[2][2],
+ RSSI[2][3], RSSI[2][4], RSSI[2][5],
+ RSSI[2][6], RSSI[2][7], RSSI[2][8],
+ RSSI[2][9]);
+ }
+ ate_print("**********************************************************\n");
+#endif // 0 //
+ }
+
+ pAd->ate.Channel = Org_Channel;
+ ATEAsicSwitchChannel(pAd);
+
+ // Restore original value
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, Org_BBP66value);
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, Org_BBP69value);
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, Org_BBP70value);
+
+ return;
+}
+
+BOOLEAN SyncTxRxConfig(PRTMP_ADAPTER pAd, USHORT offset, UCHAR value)
+{
+ UCHAR tmp = 0, bbp_data = 0;
+
+ if (ATE_ON(pAd))
+ {
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data);
+ }
+ else
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &bbp_data);
+ }
+
+ /* confirm again */
+ ASSERT(bbp_data == value);
+
+ switch(offset)
+ {
+ case BBP_R1:
+ /* Need to sync. tx configuration with legacy ATE. */
+ tmp = (bbp_data & ((1 << 4) | (1 << 3))/* 0x18 */) >> 3;
+ switch(tmp)
+ {
+ /* The BBP R1 bit[4:3] = 2 :: Both DACs will be used by QA. */
+ case 2:
+ /* All */
+ pAd->ate.TxAntennaSel = 0;
+ break;
+ /* The BBP R1 bit[4:3] = 0 :: DAC 0 will be used by QA. */
+ case 0:
+ /* Antenna one */
+ pAd->ate.TxAntennaSel = 1;
+ break;
+ /* The BBP R1 bit[4:3] = 1 :: DAC 1 will be used by QA. */
+ case 1:
+ /* Antenna two */
+ pAd->ate.TxAntennaSel = 2;
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("%s -- Sth. wrong! : return FALSE; \n", __func__));
+ return FALSE;
+ }
+ break;/* case BBP_R1 */
+
+ case BBP_R3:
+ /* Need to sync. rx configuration with legacy ATE. */
+ tmp = (bbp_data & ((1 << 1) | (1 << 0))/* 0x03 */);
+ switch(tmp)
+ {
+ /* The BBP R3 bit[1:0] = 3 :: All ADCs will be used by QA. */
+ case 3:
+ /* All */
+ pAd->ate.RxAntennaSel = 0;
+ break;
+ /* The BBP R3 bit[1:0] = 0 :: ADC 0 will be used by QA, */
+ /* unless the BBP R3 bit[4:3] = 2 */
+ case 0:
+ /* Antenna one */
+ pAd->ate.RxAntennaSel = 1;
+ tmp = ((bbp_data & ((1 << 4) | (1 << 3))/* 0x03 */) >> 3);
+ if (tmp == 2)// 3R
+ {
+ /* Default : All ADCs will be used by QA */
+ pAd->ate.RxAntennaSel = 0;
+ }
+ break;
+ /* The BBP R3 bit[1:0] = 1 :: ADC 1 will be used by QA. */
+ case 1:
+ /* Antenna two */
+ pAd->ate.RxAntennaSel = 2;
+ break;
+ /* The BBP R3 bit[1:0] = 2 :: ADC 2 will be used by QA. */
+ case 2:
+ /* Antenna three */
+ pAd->ate.RxAntennaSel = 3;
+ break;
+ default:
+ DBGPRINT(RT_DEBUG_ERROR, ("%s -- Impossible! : return FALSE; \n", __func__));
+ return FALSE;
+ }
+ break;/* case BBP_R3 */
+
+ default:
+ DBGPRINT(RT_DEBUG_ERROR, ("%s -- Sth. wrong! : return FALSE; \n", __func__));
+ return FALSE;
+
+ }
+ return TRUE;
+}
+
+static VOID memcpy_exl(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len)
+{
+ ULONG i, Value = 0;
+ ULONG *pDst, *pSrc;
+ UCHAR *p8;
+
+ p8 = src;
+ pDst = (ULONG *) dst;
+ pSrc = (ULONG *) src;
+
+ for (i = 0 ; i < (len/4); i++)
+ {
+ /* For alignment issue, we need a variable "Value". */
+ memmove(&Value, pSrc, 4);
+ Value = htonl(Value);
+ memmove(pDst, &Value, 4);
+ pDst++;
+ pSrc++;
+ }
+ if ((len % 4) != 0)
+ {
+ /* wish that it will never reach here */
+ memmove(&Value, pSrc, (len % 4));
+ Value = htonl(Value);
+ memmove(pDst, &Value, (len % 4));
+ }
+}
+
+static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len)
+{
+ ULONG i;
+ UCHAR *pDst, *pSrc;
+
+ pDst = dst;
+ pSrc = src;
+
+ for (i = 0; i < (len/2); i++)
+ {
+ memmove(pDst, pSrc, 2);
+ *((USHORT *)pDst) = htons(*((USHORT *)pDst));
+ pDst+=2;
+ pSrc+=2;
+ }
+
+ if ((len % 2) != 0)
+ {
+ memmove(pDst, pSrc, 1);
+ }
+}
+
+static VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, UINT32 len)
+{
+ UINT32 i, Value;
+ UINT32 *pDst, *pSrc;
+
+ pDst = (UINT32 *) dst;
+ pSrc = (UINT32 *) src;
+
+ for (i = 0 ; i < (len/4); i++)
+ {
+ RTMP_IO_READ32(pAd, (ULONG)pSrc, &Value);
+ Value = htonl(Value);
+ memmove(pDst, &Value, 4);
+ pDst++;
+ pSrc++;
+ }
+ return;
+}
+
+// TODO:
+#if 0
+/* These work only when RALINK_ATE is defined */
+INT Set_TxStart_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ULONG value = simple_strtol(arg, 0, 10);
+ UCHAR buffer[26] = {0x88, 0x02, 0x2c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00, 0x55, 0x44, 0x33, 0x22, 0x11, 0xc0, 0x22, 0x00, 0x00};
+ POS_COOKIE pObj;
+
+ if (pAd->ate.TxStatus != 0)
+ return FALSE;
+
+ pAd->ate.TxInfo = 0x04000000;
+ bzero(&pAd->ate.TxWI, sizeof(TXWI_STRUC));
+ pAd->ate.TxWI.PHYMODE = 0;// MODE_CCK
+ pAd->ate.TxWI.MPDUtotalByteCount = 1226;
+ pAd->ate.TxWI.MCS = 3;
+ //pAd->ate.Mode = ATE_START;
+ pAd->ate.Mode |= ATE_TXFRAME;
+ pAd->ate.TxCount = value;
+ pAd->ate.QID = 0;
+ pAd->ate.HLen = 26;
+ pAd->ate.PLen = 0;
+ pAd->ate.DLen = 1200;
+ memcpy(pAd->ate.Header, buffer, 26);
+ pAd->ate.bQATxStart = TRUE;
+ //pObj = (POS_COOKIE) pAd->OS_Cookie;
+ //tasklet_hi_schedule(&pObj->AteTxTask);
+ return TRUE;
+}
+#endif /* end of #if 0 */
+
+INT Set_TxStop_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ATEDBGPRINT(RT_DEBUG_TRACE,("Set_TxStop_Proc\n"));
+
+ if (Set_ATE_Proc(pAd, "TXSTOP"))
+ {
+ return TRUE;
+}
+ else
+ {
+ return FALSE;
+ }
+}
+
+INT Set_RxStop_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ ATEDBGPRINT(RT_DEBUG_TRACE,("Set_RxStop_Proc\n"));
+
+ if (Set_ATE_Proc(pAd, "RXSTOP"))
+ {
+ return TRUE;
+}
+ else
+ {
+ return FALSE;
+ }
+}
+
+#if 0
+INT Set_EEWrite_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ USHORT offset = 0, value;
+ PUCHAR p2 = arg;
+
+ while((*p2 != ':') && (*p2 != '\0'))
+ {
+ p2++;
+ }
+
+ if (*p2 == ':')
+ {
+ A2Hex(offset, arg);
+ A2Hex(value, p2+ 1);
+ }
+ else
+ {
+ A2Hex(value, arg);
+ }
+
+ if (offset >= EEPROM_SIZE)
+ {
+ ate_print("Offset can not exceed EEPROM_SIZE( == 0x%04x)\n", EEPROM_SIZE);
+ return FALSE;
+ }
+
+ RTMP_EEPROM_WRITE16(pAd, offset, value);
+
+ return TRUE;
+}
+
+INT Set_BBPRead_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR value = 0, offset;
+
+ A2Hex(offset, arg);
+
+ if (ATE_ON(pAd))
+ {
+ ATE_BBP_IO_READ8_BY_REG_ID(pAd, offset, &value);
+ }
+ else
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, offset, &value);
+ }
+
+ ate_print("%x\n", value);
+
+ return TRUE;
+}
+
+
+INT Set_BBPWrite_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ USHORT offset = 0;
+ PUCHAR p2 = arg;
+ UCHAR value;
+
+ while((*p2 != ':') && (*p2 != '\0'))
+ {
+ p2++;
+ }
+
+ if (*p2 == ':')
+ {
+ A2Hex(offset, arg);
+ A2Hex(value, p2+ 1);
+ }
+ else
+ {
+ A2Hex(value, arg);
+ }
+
+ if (ATE_ON(pAd))
+ {
+ ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value);
+ }
+ else
+ {
+ RTNP_BBP_IO_WRITE8_BY_REG_ID(pAd, offset, value);
+ }
+
+ return TRUE;
+}
+
+INT Set_RFWrite_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ PUCHAR p2, p3, p4;
+ ULONG R1, R2, R3, R4;
+
+ p2 = arg;
+
+ while((*p2 != ':') && (*p2 != '\0'))
+ {
+ p2++;
+ }
+
+ if (*p2 != ':')
+ return FALSE;
+
+ p3 = p2 + 1;
+
+ while((*p3 != ':') && (*p3 != '\0'))
+ {
+ p3++;
+ }
+
+ if (*p3 != ':')
+ return FALSE;
+
+ p4 = p3 + 1;
+
+ while((*p4 != ':') && (*p4 != '\0'))
+ {
+ p4++;
+ }
+
+ if (*p4 != ':')
+ return FALSE;
+
+
+ A2Hex(R1, arg);
+ A2Hex(R2, p2 + 1);
+ A2Hex(R3, p3 + 1);
+ A2Hex(R4, p4 + 1);
+
+ RTMP_RF_IO_WRITE32(pAd, R1);
+ RTMP_RF_IO_WRITE32(pAd, R2);
+ RTMP_RF_IO_WRITE32(pAd, R3);
+ RTMP_RF_IO_WRITE32(pAd, R4);
+
+ return TRUE;
+}
+#endif // end of #if 0 //
+#endif // RALINK_28xx_QA //
+
+#endif // RALINK_ATE //
+
diff --git a/drivers/staging/rt2860/rt_ate.h b/drivers/staging/rt2860/rt_ate.h
new file mode 100644
index 000000000000..48aa70d2f010
--- /dev/null
+++ b/drivers/staging/rt2860/rt_ate.h
@@ -0,0 +1,353 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#ifndef __ATE_H__
+#define __ATE_H__
+
+#ifndef UCOS
+#define ate_print printk
+#define ATEDBGPRINT DBGPRINT
+#ifdef RT2860
+#define EEPROM_SIZE 0x200
+#ifdef CONFIG_STA_SUPPORT
+#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin"
+#endif // CONFIG_STA_SUPPORT //
+#endif // RT2860 //
+
+#else // !UCOS //
+#define fATE_LOAD_EEPROM 0x0C43
+#ifdef CONFIG_PRINTK
+extern INT ConsoleResponse(IN PUCHAR buff);
+extern int (*remote_display)(char *);
+extern void puts (const char *s);
+
+/* specificly defined to redirect and show ate-related messages to host. */
+/* Try to define ate_print as a macro. */
+#define ate_print(fmt, args...) \
+do{ int (*org_remote_display)(char *) = NULL; \
+ org_remote_display = remote_display;\
+ /* Save original "remote_display" */\
+ remote_display = (int (*)(char *))ConsoleResponse; \
+ printk(fmt, ## args); \
+ /* Restore the remote_display function pointer */ \
+ remote_display = org_remote_display; }while(0)
+
+#define ATEDBGPRINT(Level, Fmt) \
+{ \
+ if ((Level) <= RTDebugLevel) \
+ { \
+ ate_print Fmt; \
+ } \
+}
+#endif // CONFIG_PRINTK //
+#endif // !UCOS //
+
+#define ATE_ON(_p) (((_p)->ate.Mode) != ATE_STOP)
+
+/* RT2880_iNIC will define "RT2860". */
+#ifdef RT2860
+#define ATE_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \
+{ \
+ BBP_CSR_CFG_STRUC BbpCsr; \
+ int i, k; \
+ for (i=0; i<MAX_BUSY_COUNT; i++) \
+ { \
+ RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == BUSY) \
+ { \
+ continue; \
+ } \
+ BbpCsr.word = 0; \
+ BbpCsr.field.fRead = 1; \
+ BbpCsr.field.BBP_RW_MODE = 1; \
+ BbpCsr.field.Busy = 1; \
+ BbpCsr.field.RegNum = _I; \
+ RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \
+ for (k=0; k<MAX_BUSY_COUNT; k++) \
+ { \
+ RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == IDLE) \
+ break; \
+ } \
+ if ((BbpCsr.field.Busy == IDLE) && \
+ (BbpCsr.field.RegNum == _I)) \
+ { \
+ *(_pV) = (UCHAR)BbpCsr.field.Value; \
+ break; \
+ } \
+ } \
+ if (BbpCsr.field.Busy == BUSY) \
+ { \
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("BBP read R%d fail\n", _I)); \
+ *(_pV) = (_A)->BbpWriteLatch[_I]; \
+ } \
+}
+
+#define ATE_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \
+{ \
+ BBP_CSR_CFG_STRUC BbpCsr; \
+ int BusyCnt; \
+ for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++) \
+ { \
+ RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == BUSY) \
+ continue; \
+ BbpCsr.word = 0; \
+ BbpCsr.field.fRead = 0; \
+ BbpCsr.field.BBP_RW_MODE = 1; \
+ BbpCsr.field.Busy = 1; \
+ BbpCsr.field.Value = _V; \
+ BbpCsr.field.RegNum = _I; \
+ RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \
+ (_A)->BbpWriteLatch[_I] = _V; \
+ break; \
+ } \
+ if (BusyCnt == MAX_BUSY_COUNT) \
+ { \
+ ATEDBGPRINT(RT_DEBUG_ERROR, ("BBP write R%d fail\n", _I)); \
+ } \
+}
+#endif // RT2860 //
+
+/* RT2880_iNIC will define RT2860. */
+#ifdef RT2860
+#define EEPROM_SIZE 0x200
+/* iNIC has its own EEPROM_BIN_FILE_NAME */
+#ifndef UCOS
+#ifdef CONFIG_STA_SUPPORT
+#define EEPROM_BIN_FILE_NAME "/etc/Wireless/RT2860STA/e2p.bin"
+#endif // CONFIG_STA_SUPPORT //
+#endif // !UCOS //
+#endif // RT2860 //
+
+
+
+VOID rt_ee_read_all(
+ IN PRTMP_ADAPTER pAd,
+ OUT USHORT *Data);
+
+
+VOID rt_ee_write_all(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT *Data);
+
+INT Set_ATE_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_DA_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_SA_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_BSSID_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_CHANNEL_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_POWER0_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_POWER1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_Antenna_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_RX_Antenna_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_FREQOFFSET_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_BW_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_LENGTH_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_COUNT_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_MCS_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_MODE_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_TX_GI_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+
+INT Set_ATE_RX_FER_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Read_RF_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Write_RF1_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Write_RF2_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Write_RF3_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Write_RF4_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Load_E2P_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Read_E2P_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Show_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ATE_Help_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+#ifdef RALINK_ATE
+#ifdef RALINK_28xx_QA
+VOID ATE_QA_Statistics(
+ IN PRTMP_ADAPTER pAd,
+ IN PRXWI_STRUC pRxWI,
+ IN PRT28XX_RXD_STRUC p28xxRxD,
+ IN PHEADER_802_11 pHeader);
+
+VOID RtmpDoAte(
+ IN PRTMP_ADAPTER pAdapter,
+ IN struct iwreq *wrq);
+
+VOID BubbleSort(
+ IN INT32 n,
+ IN INT32 a[]);
+
+VOID CalNoiseLevel(
+ IN PRTMP_ADAPTER pAdapter,
+ IN UCHAR channel,
+ OUT INT32 buffer[3][10]);
+
+BOOLEAN SyncTxRxConfig(
+ IN PRTMP_ADAPTER pAdapter,
+ IN USHORT offset,
+ IN UCHAR value);
+
+#if 0
+INT Set_TxStart_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif // 0 //
+
+INT Set_TxStop_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_RxStop_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+#if 0
+INT Set_EERead_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_EEWrite_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_BBPRead_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_BBPWrite_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_RFWrite_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif // end of #if 0 //
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+VOID ATEAsicSwitchChannel(
+ IN PRTMP_ADAPTER pAd);
+
+VOID ATEAsicAdjustTxPower(
+ IN PRTMP_ADAPTER pAd);
+
+VOID ATEDisableAsicProtect(
+ IN PRTMP_ADAPTER pAd);
+
+CHAR ATEConvertToRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi,
+ IN UCHAR RssiNumber);
+
+VOID ATESampleRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN PRXWI_STRUC pRxWI);
+
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPStationStop(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPStationStart(
+ IN PRTMP_ADAPTER pAd);
+#endif // CONFIG_STA_SUPPORT //
+#endif // __ATE_H__ //
diff --git a/drivers/staging/rt2860/rt_config.h b/drivers/staging/rt2860/rt_config.h
new file mode 100644
index 000000000000..7ee7a405b026
--- /dev/null
+++ b/drivers/staging/rt2860/rt_config.h
@@ -0,0 +1,101 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rt_config.h
+
+ Abstract:
+ Central header file to maintain all include files for all NDIS
+ miniport driver routines.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 08-01-2002 created
+
+*/
+#ifndef __RT_CONFIG_H__
+#define __RT_CONFIG_H__
+
+#include "rtmp_type.h"
+#ifdef UCOS
+#include "includes.h"
+#include <stdio.h>
+#include "rt_ucos.h"
+#endif
+
+#ifdef LINUX
+#include "rt_linux.h"
+#endif
+#include "rtmp_def.h"
+#include "rt28xx.h"
+
+#ifdef RT2860
+#include "rt2860.h"
+#endif // RT2860 //
+
+
+#include "oid.h"
+#include "mlme.h"
+#include "wpa.h"
+#include "md5.h"
+#include "rtmp.h"
+#include "ap.h"
+#include "dfs.h"
+#include "chlist.h"
+#include "spectrum.h"
+
+#ifdef LEAP_SUPPORT
+#include "leap.h"
+#endif // LEAP_SUPPORT //
+
+#ifdef BLOCK_NET_IF
+#include "netif_block.h"
+#endif // BLOCK_NET_IF //
+
+#ifdef IGMP_SNOOP_SUPPORT
+#include "igmp_snoop.h"
+#endif // IGMP_SNOOP_SUPPORT //
+
+#ifdef RALINK_ATE
+#include "rt_ate.h"
+#endif // RALINK_ATE //
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifndef WPA_SUPPLICANT_SUPPORT
+#error "Build for being controlled by NetworkManager or wext, please set HAS_WPA_SUPPLICANT=y and HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y"
+#endif // WPA_SUPPLICANT_SUPPORT //
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef IKANOS_VX_1X0
+#include "vr_ikans.h"
+#endif // IKANOS_VX_1X0 //
+
+#endif // __RT_CONFIG_H__
+
diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c
new file mode 100644
index 000000000000..f14500931efb
--- /dev/null
+++ b/drivers/staging/rt2860/rt_linux.c
@@ -0,0 +1,1054 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#include "rt_config.h"
+
+ULONG RTDebugLevel = RT_DEBUG_ERROR;
+
+BUILD_TIMER_FUNCTION(MlmePeriodicExec);
+BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout);
+BUILD_TIMER_FUNCTION(APSDPeriodicExec);
+BUILD_TIMER_FUNCTION(AsicRfTuningExec);
+
+
+#ifdef CONFIG_STA_SUPPORT
+BUILD_TIMER_FUNCTION(BeaconTimeout);
+BUILD_TIMER_FUNCTION(ScanTimeout);
+BUILD_TIMER_FUNCTION(AuthTimeout);
+BUILD_TIMER_FUNCTION(AssocTimeout);
+BUILD_TIMER_FUNCTION(ReassocTimeout);
+BUILD_TIMER_FUNCTION(DisassocTimeout);
+BUILD_TIMER_FUNCTION(LinkDownExec);
+#ifdef LEAP_SUPPORT
+BUILD_TIMER_FUNCTION(LeapAuthTimeout);
+#endif
+BUILD_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
+BUILD_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
+#ifdef RT2860
+BUILD_TIMER_FUNCTION(PsPollWakeExec);
+BUILD_TIMER_FUNCTION(RadioOnExec);
+#endif // RT2860 //
+#ifdef QOS_DLS_SUPPORT
+BUILD_TIMER_FUNCTION(DlsTimeoutAction);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+// for wireless system event message
+char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
+ // system status event
+ "had associated successfully", /* IW_ASSOC_EVENT_FLAG */
+ "had disassociated", /* IW_DISASSOC_EVENT_FLAG */
+ "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */
+ "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */
+ "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */
+ "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
+ "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */
+ "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */
+ "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */
+ "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */
+ "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
+ "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
+ "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
+ "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
+ "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
+ "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */
+ "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */
+ "scan completed" /* IW_SCAN_COMPLETED_EVENT_FLAG */
+ "scan terminate!! Busy!! Enqueue fail!!" /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
+ };
+
+// for wireless IDS_spoof_attack event message
+char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
+ "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */
+ "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
+ "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
+ "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
+ "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */
+ "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */
+ "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */
+ "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */
+ "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
+ "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */
+ };
+
+// for wireless IDS_flooding_attack event message
+char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
+ "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */
+ "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
+ "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
+ "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
+ "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */
+ "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */
+ "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
+ };
+
+/* timeout -- ms */
+VOID RTMP_SetPeriodicTimer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN unsigned long timeout)
+{
+ timeout = ((timeout*HZ) / 1000);
+ pTimer->expires = jiffies + timeout;
+ add_timer(pTimer);
+}
+
+/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
+VOID RTMP_OS_Init_Timer(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN TIMER_FUNCTION function,
+ IN PVOID data)
+{
+ init_timer(pTimer);
+ pTimer->data = (unsigned long)data;
+ pTimer->function = function;
+}
+
+
+VOID RTMP_OS_Add_Timer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN unsigned long timeout)
+{
+ if (timer_pending(pTimer))
+ return;
+
+ timeout = ((timeout*HZ) / 1000);
+ pTimer->expires = jiffies + timeout;
+ add_timer(pTimer);
+}
+
+VOID RTMP_OS_Mod_Timer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN unsigned long timeout)
+{
+ timeout = ((timeout*HZ) / 1000);
+ mod_timer(pTimer, jiffies + timeout);
+}
+
+VOID RTMP_OS_Del_Timer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ OUT BOOLEAN *pCancelled)
+{
+ if (timer_pending(pTimer))
+ {
+ *pCancelled = del_timer_sync(pTimer);
+ }
+ else
+ {
+ *pCancelled = TRUE;
+ }
+
+}
+
+VOID RTMP_OS_Release_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PQUEUE_ENTRY pEntry)
+{
+ //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
+}
+
+// Unify all delay routine by using udelay
+VOID RTMPusecDelay(
+ IN ULONG usec)
+{
+ ULONG i;
+
+ for (i = 0; i < (usec / 50); i++)
+ udelay(50);
+
+ if (usec % 50)
+ udelay(usec % 50);
+}
+
+void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
+{
+ time->u.LowPart = jiffies;
+}
+
+// pAd MUST allow to be NULL
+NDIS_STATUS os_alloc_mem(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR *mem,
+ IN ULONG size)
+{
+ *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
+ if (*mem)
+ return (NDIS_STATUS_SUCCESS);
+ else
+ return (NDIS_STATUS_FAILURE);
+}
+
+// pAd MUST allow to be NULL
+NDIS_STATUS os_free_mem(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR mem)
+{
+
+ ASSERT(mem);
+ kfree(mem);
+ return (NDIS_STATUS_SUCCESS);
+}
+
+
+PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length)
+{
+ struct sk_buff *pkt;
+
+ pkt = dev_alloc_skb(Length);
+
+ if (pkt == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
+ }
+
+ if (pkt)
+ {
+ RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+ }
+
+ return (PNDIS_PACKET) pkt;
+}
+
+
+PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress)
+{
+ struct sk_buff *pkt;
+
+ pkt = dev_alloc_skb(Length);
+
+ if (pkt == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
+ }
+
+ if (pkt)
+ {
+ RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+ *VirtualAddress = (PVOID) pkt->data;
+ }
+ else
+ {
+ *VirtualAddress = (PVOID) NULL;
+ }
+
+ return (PNDIS_PACKET) pkt;
+}
+
+
+VOID build_tx_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pFrame,
+ IN ULONG FrameLen)
+{
+
+ struct sk_buff *pTxPkt;
+
+ ASSERT(pPacket);
+ pTxPkt = RTPKT_TO_OSPKT(pPacket);
+
+ NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
+}
+
+VOID RTMPFreeAdapter(
+ IN PRTMP_ADAPTER pAd)
+{
+ POS_COOKIE os_cookie;
+ int index;
+
+ os_cookie=(POS_COOKIE)pAd->OS_Cookie;
+
+ kfree(pAd->BeaconBuf);
+
+
+ NdisFreeSpinLock(&pAd->MgmtRingLock);
+
+#ifdef RT2860
+ NdisFreeSpinLock(&pAd->RxRingLock);
+#endif // RT2860 //
+
+ for (index =0 ; index < NUM_OF_TX_RING; index++)
+ {
+ NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
+ NdisFreeSpinLock(&pAd->DeQueueLock[index]);
+ pAd->DeQueueRunning[index] = FALSE;
+ }
+
+ NdisFreeSpinLock(&pAd->irq_lock);
+
+ vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
+ kfree(os_cookie);
+}
+
+BOOLEAN OS_Need_Clone_Packet(void)
+{
+ return (FALSE);
+}
+
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
+ must have only one NDIS BUFFER
+ return - byte copied. 0 means can't create NDIS PACKET
+ NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
+
+ Arguments:
+ pAd Pointer to our adapter
+ pInsAMSDUHdr EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
+ *pSrcTotalLen return total packet length. This lenght is calculated with 802.3 format packet.
+
+ Return Value:
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_FAILURE
+
+ Note:
+
+ ========================================================================
+*/
+NDIS_STATUS RTMPCloneNdisPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN pInsAMSDUHdr,
+ IN PNDIS_PACKET pInPacket,
+ OUT PNDIS_PACKET *ppOutPacket)
+{
+
+ struct sk_buff *pkt;
+
+ ASSERT(pInPacket);
+ ASSERT(ppOutPacket);
+
+ // 1. Allocate a packet
+ pkt = dev_alloc_skb(2048);
+
+ if (pkt == NULL)
+ {
+ return NDIS_STATUS_FAILURE;
+ }
+
+ skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
+ NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
+ *ppOutPacket = OSPKT_TO_RTPKT(pkt);
+
+
+ RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+
+ printk("###Clone###\n");
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
+NDIS_STATUS RTMPAllocateNdisPacket(
+ IN PRTMP_ADAPTER pAd,
+ OUT PNDIS_PACKET *ppPacket,
+ IN PUCHAR pHeader,
+ IN UINT HeaderLen,
+ IN PUCHAR pData,
+ IN UINT DataLen)
+{
+ PNDIS_PACKET pPacket;
+ ASSERT(pData);
+ ASSERT(DataLen);
+
+ // 1. Allocate a packet
+ pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + TXPADDING_SIZE);
+ if (pPacket == NULL)
+ {
+ *ppPacket = NULL;
+#ifdef DEBUG
+ printk("RTMPAllocateNdisPacket Fail\n\n");
+#endif
+ return NDIS_STATUS_FAILURE;
+ }
+
+ // 2. clone the frame content
+ if (HeaderLen > 0)
+ NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
+ if (DataLen > 0)
+ NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
+
+ // 3. update length of packet
+ skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
+
+ RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+// printk("%s : pPacket = %p, len = %d\n", __func__, pPacket, GET_OS_PKT_LEN(pPacket));
+ *ppPacket = pPacket;
+ return NDIS_STATUS_SUCCESS;
+}
+
+/*
+ ========================================================================
+ Description:
+ This routine frees a miniport internally allocated NDIS_PACKET and its
+ corresponding NDIS_BUFFER and allocated memory.
+ ========================================================================
+*/
+VOID RTMPFreeNdisPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
+}
+
+
+// IRQL = DISPATCH_LEVEL
+// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
+// scatter gather buffer
+NDIS_STATUS Sniff2BytesFromNdisBuffer(
+ IN PNDIS_BUFFER pFirstBuffer,
+ IN UCHAR DesiredOffset,
+ OUT PUCHAR pByte0,
+ OUT PUCHAR pByte1)
+{
+ *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
+ *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
+
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+void RTMP_QueryPacketInfo(
+ IN PNDIS_PACKET pPacket,
+ OUT PACKET_INFO *pPacketInfo,
+ OUT PUCHAR *pSrcBufVA,
+ OUT UINT *pSrcBufLen)
+{
+ pPacketInfo->BufferCount = 1;
+ pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
+ pPacketInfo->PhysicalBufferCount = 1;
+ pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
+
+ *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
+ *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
+}
+
+void RTMP_QueryNextPacketInfo(
+ IN PNDIS_PACKET *ppPacket,
+ OUT PACKET_INFO *pPacketInfo,
+ OUT PUCHAR *pSrcBufVA,
+ OUT UINT *pSrcBufLen)
+{
+ PNDIS_PACKET pPacket = NULL;
+
+ if (*ppPacket)
+ pPacket = GET_OS_PKT_NEXT(*ppPacket);
+
+ if (pPacket)
+ {
+ pPacketInfo->BufferCount = 1;
+ pPacketInfo->pFirstBuffer = GET_OS_PKT_DATAPTR(pPacket);
+ pPacketInfo->PhysicalBufferCount = 1;
+ pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
+
+ *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
+ *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
+ *ppPacket = GET_OS_PKT_NEXT(pPacket);
+ }
+ else
+ {
+ pPacketInfo->BufferCount = 0;
+ pPacketInfo->pFirstBuffer = NULL;
+ pPacketInfo->PhysicalBufferCount = 0;
+ pPacketInfo->TotalPacketLength = 0;
+
+ *pSrcBufVA = NULL;
+ *pSrcBufLen = 0;
+ *ppPacket = NULL;
+ }
+}
+
+// not yet support MBSS
+PNET_DEV get_netdev_from_bssid(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR FromWhichBSSID)
+{
+ PNET_DEV dev_p = NULL;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ dev_p = pAd->net_dev;
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ ASSERT(dev_p);
+ return dev_p; /* return one of MBSS */
+}
+
+PNDIS_PACKET DuplicatePacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR FromWhichBSSID)
+{
+ struct sk_buff *skb;
+ PNDIS_PACKET pRetPacket = NULL;
+ USHORT DataSize;
+ UCHAR *pData;
+
+ DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
+ pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
+
+
+ skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
+ if (skb)
+ {
+ skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+ pRetPacket = OSPKT_TO_RTPKT(skb);
+ }
+
+ return pRetPacket;
+
+}
+
+PNDIS_PACKET duplicate_pkt(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHeader802_3,
+ IN UINT HdrLen,
+ IN PUCHAR pData,
+ IN ULONG DataSize,
+ IN UCHAR FromWhichBSSID)
+{
+ struct sk_buff *skb;
+ PNDIS_PACKET pPacket = NULL;
+
+
+ if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
+ {
+ skb_reserve(skb, 2);
+ NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
+ skb_put(skb, HdrLen);
+ NdisMoveMemory(skb->tail, pData, DataSize);
+ skb_put(skb, DataSize);
+ skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+ pPacket = OSPKT_TO_RTPKT(skb);
+ }
+
+ return pPacket;
+}
+
+
+#define TKIP_TX_MIC_SIZE 8
+PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ struct sk_buff *skb, *newskb;
+
+
+ skb = RTPKT_TO_OSPKT(pPacket);
+ if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
+ {
+ // alloc a new skb and copy the packet
+ newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
+ dev_kfree_skb_any(skb);
+ if (newskb == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
+ return NULL;
+ }
+ skb = newskb;
+ }
+
+ return OSPKT_TO_RTPKT(skb);
+}
+
+
+
+
+PNDIS_PACKET ClonePacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pData,
+ IN ULONG DataSize)
+{
+ struct sk_buff *pRxPkt;
+ struct sk_buff *pClonedPkt;
+
+ ASSERT(pPacket);
+ pRxPkt = RTPKT_TO_OSPKT(pPacket);
+
+ // clone the packet
+ pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
+
+ if (pClonedPkt)
+ {
+ // set the correct dataptr and data len
+ pClonedPkt->dev = pRxPkt->dev;
+ pClonedPkt->data = pData;
+ pClonedPkt->len = DataSize;
+ pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
+ ASSERT(DataSize < 1530);
+ }
+ return pClonedPkt;
+}
+
+//
+// change OS packet DataPtr and DataLen
+//
+void update_os_packet_info(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ struct sk_buff *pOSPkt;
+
+ ASSERT(pRxBlk->pRxPacket);
+ pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+
+ pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+ pOSPkt->data = pRxBlk->pData;
+ pOSPkt->len = pRxBlk->DataSize;
+ pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+}
+
+
+void wlan_802_11_to_802_3_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN PUCHAR pHeader802_3,
+ IN UCHAR FromWhichBSSID)
+{
+ struct sk_buff *pOSPkt;
+
+ ASSERT(pRxBlk->pRxPacket);
+ ASSERT(pHeader802_3);
+
+ pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+
+ pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+ pOSPkt->data = pRxBlk->pData;
+ pOSPkt->len = pRxBlk->DataSize;
+ pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+
+ //
+ // copy 802.3 header
+ //
+ //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+
+
+void announce_802_3_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket)
+{
+
+ struct sk_buff *pRxPkt;
+
+ ASSERT(pPacket);
+
+ pRxPkt = RTPKT_TO_OSPKT(pPacket);
+
+ /* Push up the protocol stack */
+#ifdef IKANOS_VX_1X0
+ IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len);
+#else
+ pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
+
+ netif_rx(pRxPkt);
+#endif // IKANOS_VX_1X0 //
+}
+
+
+PRTMP_SCATTER_GATHER_LIST
+rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
+{
+ sg->NumberOfElements = 1;
+ sg->Elements[0].Address = GET_OS_PKT_DATAPTR(pPacket);
+ sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
+ return (sg);
+}
+
+void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
+{
+ unsigned char *pt;
+ int x;
+
+ if (RTDebugLevel < RT_DEBUG_TRACE)
+ return;
+
+ pt = pSrcBufVA;
+ printk("%s: %p, len = %d\n",str, pSrcBufVA, SrcBufLen);
+ for (x=0; x<SrcBufLen; x++)
+ {
+ if (x % 16 == 0)
+ printk("0x%04x : ", x);
+ printk("%02x ", ((unsigned char)pt[x]));
+ if (x%16 == 15) printk("\n");
+ }
+ printk("\n");
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Send log message through wireless event
+
+ Support standard iw_event with IWEVCUSTOM. It is used below.
+
+ iwreq_data.data.flags is used to store event_flag that is defined by user.
+ iwreq_data.data.length is the length of the event log.
+
+ The format of the event log is composed of the entry's MAC address and
+ the desired log message (refer to pWirelessEventText).
+
+ ex: 11:22:33:44:55:66 has associated successfully
+
+ p.s. The requirement of Wireless Extension is v15 or newer.
+
+ ========================================================================
+*/
+VOID RTMPSendWirelessEvent(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Event_flag,
+ IN PUCHAR pAddr,
+ IN UCHAR BssIdx,
+ IN CHAR Rssi)
+{
+#if WIRELESS_EXT >= 15
+
+ union iwreq_data wrqu;
+ PUCHAR pBuf = NULL, pBufPtr = NULL;
+ USHORT event, type, BufLen;
+ UCHAR event_table_len = 0;
+
+ type = Event_flag & 0xFF00;
+ event = Event_flag & 0x00FF;
+
+ switch (type)
+ {
+ case IW_SYS_EVENT_FLAG_START:
+ event_table_len = IW_SYS_EVENT_TYPE_NUM;
+ break;
+
+ case IW_SPOOF_EVENT_FLAG_START:
+ event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
+ break;
+
+ case IW_FLOOD_EVENT_FLAG_START:
+ event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
+ break;
+ }
+
+ if (event_table_len == 0)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __func__, type));
+ return;
+ }
+
+ if (event >= event_table_len)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __func__, event));
+ return;
+ }
+
+ //Allocate memory and copy the msg.
+ if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
+ {
+ //Prepare the payload
+ memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
+
+ pBufPtr = pBuf;
+
+ if (pAddr)
+ pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
+ else if (BssIdx < MAX_MBSSID_NUM)
+ pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx);
+ else
+ pBufPtr += sprintf(pBufPtr, "(RT2860) ");
+
+ if (type == IW_SYS_EVENT_FLAG_START)
+ pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
+ else if (type == IW_SPOOF_EVENT_FLAG_START)
+ pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
+ else if (type == IW_FLOOD_EVENT_FLAG_START)
+ pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
+ else
+ pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
+
+ pBufPtr[pBufPtr - pBuf] = '\0';
+ BufLen = pBufPtr - pBuf;
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = Event_flag;
+ wrqu.data.length = BufLen;
+
+ //send wireless event
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, pBuf);
+
+ //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __func__, pBuf));
+
+ kfree(pBuf);
+ }
+ else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __func__));
+#else
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __func__));
+#endif /* WIRELESS_EXT >= 15 */
+}
+
+
+#ifdef CONFIG_STA_SUPPORT
+void send_monitor_packets(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk)
+{
+ struct sk_buff *pOSPkt;
+ wlan_ng_prism2_header *ph;
+ int rate_index = 0;
+ USHORT header_len = 0;
+ UCHAR temp_header[40] = {0};
+
+ u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96, 108, 109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38
+ 54, 108, 162, 216, 324, 432, 486, 540, 14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10,
+ 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80};
+
+
+ ASSERT(pRxBlk->pRxPacket);
+ if (pRxBlk->DataSize < 10)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __func__, pRxBlk->DataSize));
+ goto err_free_sk_buff;
+ }
+
+ if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __func__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
+ goto err_free_sk_buff;
+ }
+
+ pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
+ pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
+ if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
+ {
+ pRxBlk->DataSize -= LENGTH_802_11;
+ if ((pRxBlk->pHeader->FC.ToDs == 1) &&
+ (pRxBlk->pHeader->FC.FrDs == 1))
+ header_len = LENGTH_802_11_WITH_ADDR4;
+ else
+ header_len = LENGTH_802_11;
+
+ // QOS
+ if (pRxBlk->pHeader->FC.SubType & 0x08)
+ {
+ header_len += 2;
+ // Data skip QOS contorl field
+ pRxBlk->DataSize -=2;
+ }
+
+ // Order bit: A-Ralink or HTC+
+ if (pRxBlk->pHeader->FC.Order)
+ {
+ header_len += 4;
+ // Data skip HTC contorl field
+ pRxBlk->DataSize -= 4;
+ }
+
+ // Copy Header
+ if (header_len <= 40)
+ NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
+
+ // skip HW padding
+ if (pRxBlk->RxD.L2PAD)
+ pRxBlk->pData += (header_len + 2);
+ else
+ pRxBlk->pData += header_len;
+ } //end if
+
+
+ if (pRxBlk->DataSize < pOSPkt->len) {
+ skb_trim(pOSPkt,pRxBlk->DataSize);
+ } else {
+ skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
+ } //end if
+
+ if ((pRxBlk->pData - pOSPkt->data) > 0) {
+ skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
+ skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
+ } //end if
+
+ if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
+ if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __func__));
+ goto err_free_sk_buff;
+ } //end if
+ } //end if
+
+ if (header_len > 0)
+ NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
+
+ ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
+ NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
+
+ ph->msgcode = DIDmsg_lnxind_wlansniffrm;
+ ph->msglen = sizeof(wlan_ng_prism2_header);
+ strcpy(ph->devname, pAd->net_dev->name);
+
+ ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
+ ph->hosttime.status = 0;
+ ph->hosttime.len = 4;
+ ph->hosttime.data = jiffies;
+
+ ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
+ ph->mactime.status = 0;
+ ph->mactime.len = 0;
+ ph->mactime.data = 0;
+
+ ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
+ ph->istx.status = 0;
+ ph->istx.len = 0;
+ ph->istx.data = 0;
+
+ ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
+ ph->channel.status = 0;
+ ph->channel.len = 4;
+
+ ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
+
+ ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+ ph->rssi.status = 0;
+ ph->rssi.len = 4;
+ ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));;
+
+ ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
+ ph->signal.status = 0;
+ ph->signal.len = 4;
+ ph->signal.data = 0; //rssi + noise;
+
+ ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
+ ph->noise.status = 0;
+ ph->noise.len = 4;
+ ph->noise.data = 0;
+
+#ifdef DOT11_N_SUPPORT
+ if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
+ {
+ rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
+ rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
+ else
+ rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
+ if (rate_index < 0)
+ rate_index = 0;
+ if (rate_index > 255)
+ rate_index = 255;
+
+ ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+ ph->rate.status = 0;
+ ph->rate.len = 4;
+ ph->rate.data = ralinkrate[rate_index];
+
+ ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
+ ph->frmlen.status = 0;
+ ph->frmlen.len = 4;
+ ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
+
+
+ pOSPkt->pkt_type = PACKET_OTHERHOST;
+ pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
+ pOSPkt->ip_summed = CHECKSUM_NONE;
+ netif_rx(pOSPkt);
+
+ return;
+
+err_free_sk_buff:
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify)
+{
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ daemonize(pThreadName /*"%s",pAd->net_dev->name*/);
+
+ allow_signal(SIGTERM);
+ allow_signal(SIGKILL);
+ current->flags |= PF_NOFREEZE;
+#else
+ unsigned long flags;
+
+ daemonize();
+ reparent_to_init();
+ strcpy(current->comm, pThreadName);
+
+ siginitsetinv(&current->blocked, sigmask(SIGTERM) | sigmask(SIGKILL));
+
+ /* Allow interception of SIGKILL only
+ * Don't allow other signals to interrupt the transmission */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)
+ spin_lock_irqsave(&current->sigmask_lock, flags);
+ flush_signals(current);
+ recalc_sigpending(current);
+ spin_unlock_irqrestore(&current->sigmask_lock, flags);
+#endif
+#endif
+
+ /* signal that we've started the thread */
+ complete(pNotify);
+
+}
+
+void RTMP_IndicateMediaState(
+ IN PRTMP_ADAPTER pAd)
+{
+ if (pAd->CommonCfg.bWirelessEvent)
+ {
+ if (pAd->IndicateMediaState == NdisMediaStateConnected)
+ {
+ RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+ }
+ else
+ {
+ RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+ }
+ }
+}
+
diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h
new file mode 100644
index 000000000000..0fd58f5109f2
--- /dev/null
+++ b/drivers/staging/rt2860/rt_linux.h
@@ -0,0 +1,926 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+/***********************************************************************/
+/* */
+/* Program: rt_linux.c */
+/* Created: 4/21/2006 1:17:38 PM */
+/* Author: Wu Xi-Kun */
+/* Comments: `description` */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* History: */
+/* Revision 1.1 4/21/2006 1:17:38 PM xsikun */
+/* Initial revision */
+/* */
+/***********************************************************************/
+
+#include "rtmp_type.h"
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/wireless.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/if_arp.h>
+#include <linux/ctype.h>
+#include <linux/vmalloc.h>
+
+
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+// load firmware
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+#include <asm/uaccess.h>
+
+
+#define MEM_ALLOC_FLAG (GFP_ATOMIC) //(GFP_DMA | GFP_ATOMIC)
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+
+//#define CONFIG_CKIP_SUPPORT
+
+#undef __inline
+#define __inline static inline
+
+typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_dev);
+
+// add by kathy
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef RT2860
+#define STA_PROFILE_PATH "/etc/Wireless/RT2860STA/RT2860STA.dat"
+#define STA_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860STA/RT2860STA.bin"
+#define STA_NIC_DEVICE_NAME "RT2860STA"
+#define STA_DRIVER_VERSION "1.8.0.0"
+#ifdef MULTIPLE_CARD_SUPPORT
+#define CARD_INFO_PATH "/etc/Wireless/RT2860STA/RT2860STACard.dat"
+#endif // MULTIPLE_CARD_SUPPORT //
+#endif // RT2860 //
+
+
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef RT2860
+#ifndef PCI_DEVICE
+#define PCI_DEVICE(vend,dev) \
+ .vendor = (vend), .device = (dev), \
+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
+#endif // PCI_DEVICE //
+#endif // RT2860 //
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+
+#define RTMP_TIME_AFTER(a,b) \
+ (typecheck(unsigned long, (unsigned long)a) && \
+ typecheck(unsigned long, (unsigned long)b) && \
+ ((long)(b) - (long)(a) < 0))
+
+#define RTMP_TIME_AFTER_EQ(a,b) \
+ (typecheck(unsigned long, (unsigned long)a) && \
+ typecheck(unsigned long, (unsigned long)b) && \
+ ((long)(a) - (long)(b) >= 0))
+#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a)
+#else
+#define RTMP_TIME_AFTER(a,b) time_after(a, b)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#define RT_MOD_INC_USE_COUNT() \
+ if (!try_module_get(THIS_MODULE)) \
+ { \
+ DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot reserve module\n", __func__)); \
+ return -1; \
+ }
+
+#define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE);
+#else
+#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT;
+#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT;
+#endif
+
+#define OS_HZ HZ
+
+#define ETH_LENGTH_OF_ADDRESS 6
+
+#define IN
+#define OUT
+
+#define NDIS_STATUS INT
+#define NDIS_STATUS_SUCCESS 0x00
+#define NDIS_STATUS_FAILURE 0x01
+#define NDIS_STATUS_INVALID_DATA 0x02
+#define NDIS_STATUS_RESOURCES 0x03
+
+#define MIN_NET_DEVICE_FOR_AID 0x00 //0x00~0x3f
+#define MIN_NET_DEVICE_FOR_MBSSID 0x00 //0x00,0x10,0x20,0x30
+#define MIN_NET_DEVICE_FOR_WDS 0x10 //0x40,0x50,0x60,0x70
+#define MIN_NET_DEVICE_FOR_APCLI 0x20
+#define MIN_NET_DEVICE_FOR_MESH 0x30
+#ifdef CONFIG_STA_SUPPORT
+#define MIN_NET_DEVICE_FOR_DLS 0x40
+#endif // CONFIG_STA_SUPPORT //
+
+
+#ifdef CONFIG_STA_SUPPORT
+#define NDIS_PACKET_TYPE_DIRECTED 0
+#define NDIS_PACKET_TYPE_MULTICAST 1
+#define NDIS_PACKET_TYPE_BROADCAST 2
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 3
+#endif // CONFIG_STA_SUPPORT //
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+typedef struct pid * THREAD_PID;
+#define THREAD_PID_INIT_VALUE NULL
+#define GET_PID(_v) find_get_pid(_v)
+#define GET_PID_NUMBER(_v) pid_nr(_v)
+#define CHECK_PID_LEGALITY(_pid) if (pid_nr(_pid) >= 0)
+#define KILL_THREAD_PID(_A, _B, _C) kill_pid(_A, _B, _C)
+#else
+typedef pid_t THREAD_PID;
+#define THREAD_PID_INIT_VALUE -1
+#define GET_PID(_v) _v
+#define GET_PID_NUMBER(_v) _v
+#define CHECK_PID_LEGALITY(_pid) if (_pid >= 0)
+#define KILL_THREAD_PID(_A, _B, _C) kill_proc(_A, _B, _C)
+#endif
+
+struct os_lock {
+ spinlock_t lock;
+ unsigned long flags;
+};
+
+
+struct os_cookie {
+#ifdef RT2860
+ struct pci_dev *pci_dev;
+ struct pci_dev *parent_pci_dev;
+ dma_addr_t pAd_pa;
+#endif // RT2860 //
+
+
+ struct tasklet_struct rx_done_task;
+ struct tasklet_struct mgmt_dma_done_task;
+ struct tasklet_struct ac0_dma_done_task;
+ struct tasklet_struct ac1_dma_done_task;
+ struct tasklet_struct ac2_dma_done_task;
+ struct tasklet_struct ac3_dma_done_task;
+ struct tasklet_struct hcca_dma_done_task;
+ struct tasklet_struct tbtt_task;
+#ifdef RT2860
+ struct tasklet_struct fifo_statistic_full_task;
+#endif // RT2860 //
+
+
+ unsigned long apd_pid; //802.1x daemon pid
+ INT ioctl_if_type;
+ INT ioctl_if;
+};
+
+typedef struct _VIRTUAL_ADAPTER
+{
+ struct net_device *RtmpDev;
+ struct net_device *VirtualDev;
+} VIRTUAL_ADAPTER, PVIRTUAL_ADAPTER;
+
+#undef ASSERT
+#define ASSERT(x) \
+{ \
+ if (!(x)) \
+ { \
+ printk(KERN_WARNING __FILE__ ":%d assert " #x "failed\n", __LINE__); \
+ } \
+}
+
+typedef struct os_cookie * POS_COOKIE;
+typedef struct pci_dev * PPCI_DEV;
+typedef struct net_device * PNET_DEV;
+typedef void * PNDIS_PACKET;
+typedef char NDIS_PACKET;
+typedef PNDIS_PACKET * PPNDIS_PACKET;
+typedef dma_addr_t NDIS_PHYSICAL_ADDRESS;
+typedef dma_addr_t * PNDIS_PHYSICAL_ADDRESS;
+typedef spinlock_t NDIS_SPIN_LOCK;
+typedef struct timer_list NDIS_MINIPORT_TIMER;
+typedef void * NDIS_HANDLE;
+typedef char * PNDIS_BUFFER;
+
+
+
+void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen);
+
+dma_addr_t linux_pci_map_single(void *handle, void *ptr, size_t size, int sd_idx, int direction);
+void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size, int direction);
+
+
+////////////////////////////////////////
+// MOVE TO rtmp.h ?
+/////////////////////////////////////////
+#define PKTSRC_NDIS 0x7f
+#define PKTSRC_DRIVER 0x0f
+#define PRINT_MAC(addr) \
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
+
+
+#define RT2860_PCI_DEVICE_ID 0x0601
+
+#ifdef RT2860
+#define PCI_MAP_SINGLE(_handle, _ptr, _size, _sd_idx, _dir) \
+ linux_pci_map_single(_handle, _ptr, _size, _sd_idx, _dir)
+
+#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) \
+ linux_pci_unmap_single(_handle, _ptr, _size, _dir)
+
+#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \
+ pci_alloc_consistent(_pci_dev, _size, _ptr)
+
+#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \
+ pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr)
+
+#define DEV_ALLOC_SKB(_length) \
+ dev_alloc_skb(_length)
+#endif // RT2860 //
+
+
+
+#define BEACON_FRAME_DMA_CACHE_WBACK(_ptr, _size) \
+ dma_cache_wback(_ptr, _size)
+
+
+//////////////////////////////////////////
+//
+//////////////////////////////////////////
+
+
+#define NdisMIndicateStatus(_w, _x, _y, _z)
+
+
+typedef struct timer_list RTMP_OS_TIMER;
+
+
+
+typedef struct _RALINK_TIMER_STRUCT {
+ RTMP_OS_TIMER TimerObj; // Ndis Timer object
+ BOOLEAN Valid; // Set to True when call RTMPInitTimer
+ BOOLEAN State; // True if timer cancelled
+ BOOLEAN PeriodicType; // True if timer is periodic timer
+ BOOLEAN Repeat; // True if periodic timer
+ ULONG TimerValue; // Timer value in milliseconds
+ ULONG cookie; // os specific object
+} RALINK_TIMER_STRUCT, *PRALINK_TIMER_STRUCT;
+
+
+
+
+//#define DBG 1
+
+//
+// MACRO for debugging information
+//
+
+#ifdef DBG
+extern ULONG RTDebugLevel;
+
+#define DBGPRINT_RAW(Level, Fmt) \
+{ \
+ if (Level <= RTDebugLevel) \
+ { \
+ printk Fmt; \
+ } \
+}
+
+#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt)
+
+
+#define DBGPRINT_ERR(Fmt) \
+{ \
+ printk("ERROR!!! "); \
+ printk Fmt; \
+}
+
+#define DBGPRINT_S(Status, Fmt) \
+{ \
+ printk Fmt; \
+}
+
+
+#else
+#define DBGPRINT(Level, Fmt)
+#define DBGPRINT_RAW(Level, Fmt)
+#define DBGPRINT_S(Status, Fmt)
+#define DBGPRINT_ERR(Fmt)
+#endif
+
+
+//
+// spin_lock enhanced for Nested spin lock
+//
+#define NdisAllocateSpinLock(__lock) \
+{ \
+ spin_lock_init((spinlock_t *)(__lock)); \
+}
+
+#define NdisFreeSpinLock(lock) \
+{ \
+}
+
+
+#define RTMP_SEM_LOCK(__lock) \
+{ \
+ spin_lock_bh((spinlock_t *)(__lock)); \
+}
+
+#define RTMP_SEM_UNLOCK(__lock) \
+{ \
+ spin_unlock_bh((spinlock_t *)(__lock)); \
+}
+
+// sample, use semaphore lock to replace IRQ lock, 2007/11/15
+#define RTMP_IRQ_LOCK(__lock, __irqflags) \
+{ \
+ __irqflags = 0; \
+ spin_lock_bh((spinlock_t *)(__lock)); \
+ pAd->irq_disabled |= 1; \
+}
+
+#define RTMP_IRQ_UNLOCK(__lock, __irqflag) \
+{ \
+ pAd->irq_disabled &= 0; \
+ spin_unlock_bh((spinlock_t *)(__lock)); \
+}
+
+#define RTMP_INT_LOCK(__lock, __irqflags) \
+{ \
+ spin_lock_irqsave((spinlock_t *)__lock, __irqflags); \
+}
+
+#define RTMP_INT_UNLOCK(__lock, __irqflag) \
+{ \
+ spin_unlock_irqrestore((spinlock_t *)(__lock), ((unsigned long)__irqflag)); \
+}
+
+#ifdef RT2860
+#if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0)
+//Patch for ASIC turst read/write bug, needs to remove after metel fix
+#define RTMP_IO_READ32(_A, _R, _pV) \
+{ \
+ if ((_A)->bPCIclkOff == FALSE) \
+ { \
+ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \
+ (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \
+ (*_pV = SWAP32(*((UINT32 *)(_pV)))); \
+ } \
+}
+#define RTMP_IO_READ8(_A, _R, _pV) \
+{ \
+ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \
+ (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \
+}
+#define RTMP_IO_WRITE32(_A, _R, _V) \
+{ \
+ if ((_A)->bPCIclkOff == FALSE) \
+ { \
+ UINT32 _Val; \
+ _Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \
+ _Val = SWAP32(_V); \
+ writel(_Val, (void *)((_A)->CSRBaseAddress + (_R))); \
+ } \
+}
+#define RTMP_IO_WRITE8(_A, _R, _V) \
+{ \
+ UINT Val; \
+ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \
+ writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \
+}
+#define RTMP_IO_WRITE16(_A, _R, _V) \
+{ \
+ UINT Val; \
+ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \
+ writew(SWAP16((_V)), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \
+}
+#else
+//Patch for ASIC turst read/write bug, needs to remove after metel fix
+#define RTMP_IO_READ32(_A, _R, _pV) \
+{ \
+ if ((_A)->bPCIclkOff == FALSE) \
+ { \
+ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \
+ (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \
+ } \
+ else \
+ *_pV = 0; \
+}
+#define RTMP_IO_READ8(_A, _R, _pV) \
+{ \
+ (*_pV = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0))); \
+ (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \
+}
+#define RTMP_IO_WRITE32(_A, _R, _V) \
+{ \
+ if ((_A)->bPCIclkOff == FALSE) \
+ { \
+ UINT Val; \
+ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \
+ writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \
+ } \
+}
+#if defined(BRCM_6358)
+#define RTMP_IO_WRITE8(_A, _R, _V) \
+{ \
+ ULONG Val; \
+ UCHAR _i; \
+ _i = (_R & 0x3); \
+ Val = readl((void *)((_A)->CSRBaseAddress + (_R - _i))); \
+ Val = Val & (~(0x000000ff << ((_i)*8))); \
+ Val = Val | ((ULONG)_V << ((_i)*8)); \
+ writel((Val), (void *)((_A)->CSRBaseAddress + (_R - _i))); \
+}
+#else
+#define RTMP_IO_WRITE8(_A, _R, _V) \
+{ \
+ UINT Val; \
+ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \
+ writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \
+}
+#endif
+#define RTMP_IO_WRITE16(_A, _R, _V) \
+{ \
+ UINT Val; \
+ Val = readl((void *)((_A)->CSRBaseAddress + MAC_CSR0)); \
+ writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \
+}
+#endif
+#endif // RT2860 //
+
+
+#ifndef wait_event_interruptible_timeout
+#define __wait_event_interruptible_timeout(wq, condition, ret) \
+do { \
+ wait_queue_t __wait; \
+ init_waitqueue_entry(&__wait, current); \
+ add_wait_queue(&wq, &__wait); \
+ for (;;) { \
+ set_current_state(TASK_INTERRUPTIBLE); \
+ if (condition) \
+ break; \
+ if (!signal_pending(current)) { \
+ ret = schedule_timeout(ret); \
+ if (!ret) \
+ break; \
+ continue; \
+ } \
+ ret = -ERESTARTSYS; \
+ break; \
+ } \
+ current->state = TASK_RUNNING; \
+ remove_wait_queue(&wq, &__wait); \
+} while (0)
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) \
+ __wait_event_interruptible_timeout(wq, condition, __ret); \
+ __ret; \
+})
+#endif
+#define ONE_TICK 1
+#define OS_WAIT(_time) \
+{ int _i; \
+ long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\
+ wait_queue_head_t _wait; \
+ init_waitqueue_head(&_wait); \
+ for (_i=0; _i<(_loop); _i++) \
+ wait_event_interruptible_timeout(_wait, 0, ONE_TICK); }
+
+
+/* Modified by Wu Xi-Kun 4/21/2006 */
+typedef void (*TIMER_FUNCTION)(unsigned long);
+
+#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN)
+
+#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE)
+#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA)
+
+#ifdef RT2860
+#define BUILD_TIMER_FUNCTION(_func) \
+void linux_##_func(unsigned long data) \
+{ \
+ PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) data; \
+ \
+ _func(NULL, (PVOID) pTimer->cookie, NULL, pTimer); \
+ if (pTimer->Repeat) \
+ RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); \
+}
+#endif // RT2860 //
+
+
+
+#define DECLARE_TIMER_FUNCTION(_func) \
+void linux_##_func(unsigned long data)
+
+#define GET_TIMER_FUNCTION(_func) \
+ linux_##_func
+
+DECLARE_TIMER_FUNCTION(MlmePeriodicExec);
+DECLARE_TIMER_FUNCTION(MlmeRssiReportExec);
+DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout);
+DECLARE_TIMER_FUNCTION(APSDPeriodicExec);
+DECLARE_TIMER_FUNCTION(AsicRfTuningExec);
+
+
+#ifdef CONFIG_STA_SUPPORT
+DECLARE_TIMER_FUNCTION(BeaconTimeout);
+DECLARE_TIMER_FUNCTION(ScanTimeout);
+DECLARE_TIMER_FUNCTION(AuthTimeout);
+DECLARE_TIMER_FUNCTION(AssocTimeout);
+DECLARE_TIMER_FUNCTION(ReassocTimeout);
+DECLARE_TIMER_FUNCTION(DisassocTimeout);
+DECLARE_TIMER_FUNCTION(LinkDownExec);
+#ifdef LEAP_SUPPORT
+DECLARE_TIMER_FUNCTION(LeapAuthTimeout);
+#endif
+DECLARE_TIMER_FUNCTION(StaQuickResponeForRateUpExec);
+DECLARE_TIMER_FUNCTION(WpaDisassocApAndBlockAssoc);
+DECLARE_TIMER_FUNCTION(PsPollWakeExec);
+DECLARE_TIMER_FUNCTION(RadioOnExec);
+
+#ifdef QOS_DLS_SUPPORT
+DECLARE_TIMER_FUNCTION(DlsTimeoutAction);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time);
+
+
+/*
+ * packet helper
+ * - convert internal rt packet to os packet or
+ * os packet to rt packet
+ */
+#define RTPKT_TO_OSPKT(_p) ((struct sk_buff *)(_p))
+#define OSPKT_TO_RTPKT(_p) ((PNDIS_PACKET)(_p))
+
+#define GET_OS_PKT_DATAPTR(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt)->data)
+
+#define GET_OS_PKT_LEN(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt)->len)
+
+#define GET_OS_PKT_DATATAIL(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt)->tail)
+
+#define GET_OS_PKT_HEAD(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt)->head)
+
+#define GET_OS_PKT_END(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt)->end)
+
+#define GET_OS_PKT_NETDEV(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt)->dev)
+
+#define GET_OS_PKT_TYPE(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt))
+
+#define GET_OS_PKT_NEXT(_pkt) \
+ (RTPKT_TO_OSPKT(_pkt)->next)
+
+
+#define OS_NTOHS(_Val) \
+ (ntohs(_Val))
+#define OS_HTONS(_Val) \
+ (htons(_Val))
+#define OS_NTOHL(_Val) \
+ (ntohl(_Val))
+#define OS_HTONL(_Val) \
+ (htonl(_Val))
+
+/* statistics counter */
+#define STATS_INC_RX_PACKETS(_pAd, _dev)
+#define STATS_INC_TX_PACKETS(_pAd, _dev)
+
+#define STATS_INC_RX_BYTESS(_pAd, _dev, len)
+#define STATS_INC_TX_BYTESS(_pAd, _dev, len)
+
+#define STATS_INC_RX_ERRORS(_pAd, _dev)
+#define STATS_INC_TX_ERRORS(_pAd, _dev)
+
+#define STATS_INC_RX_DROPPED(_pAd, _dev)
+#define STATS_INC_TX_DROPPED(_pAd, _dev)
+
+
+#define CB_OFF 10
+
+
+// check DDK NDIS_PACKET data structure and find out only MiniportReservedEx[0..7] can be used by our driver without
+// ambiguity. Fields after pPacket->MiniportReservedEx[8] may be used by other wrapper layer thus crashes the driver
+//
+
+// User Priority
+#define RTMP_SET_PACKET_UP(_p, _prio) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0] = _prio)
+#define RTMP_GET_PACKET_UP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+0])
+
+// Fragment #
+#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1] = _num)
+#define RTMP_GET_PACKET_FRAGMENTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+1])
+
+// 0x0 ~0x7f: TX to AP's own BSS which has the specified AID. if AID>127, set bit 7 in RTMP_SET_PACKET_EMACTAB too.
+//(this value also as MAC(on-chip WCID) table index)
+// 0x80~0xff: TX to a WDS link. b0~6: WDS index
+#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2] = _wdsidx)
+#define RTMP_GET_PACKET_WCID(_p) ((UCHAR)(RTPKT_TO_OSPKT(_p)->cb[CB_OFF+2]))
+
+// 0xff: PKTSRC_NDIS, others: local TX buffer index. This value affects how to a packet
+#define RTMP_SET_PACKET_SOURCE(_p, _pktsrc) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3] = _pktsrc)
+#define RTMP_GET_PACKET_SOURCE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+3])
+
+// RTS/CTS-to-self protection method
+#define RTMP_SET_PACKET_RTS(_p, _num) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4] = _num)
+#define RTMP_GET_PACKET_RTS(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+4])
+// see RTMP_S(G)ET_PACKET_EMACTAB
+
+// TX rate index
+#define RTMP_SET_PACKET_TXRATE(_p, _rate) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5] = _rate)
+#define RTMP_GET_PACKET_TXRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+5])
+
+// From which Interface
+#define RTMP_SET_PACKET_IF(_p, _ifdx) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6] = _ifdx)
+#define RTMP_GET_PACKET_IF(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+6])
+#define RTMP_SET_PACKET_NET_DEVICE_MBSSID(_p, _bss) RTMP_SET_PACKET_IF((_p), (_bss))
+#define RTMP_SET_PACKET_NET_DEVICE_WDS(_p, _bss) RTMP_SET_PACKET_IF((_p), ((_bss) + MIN_NET_DEVICE_FOR_WDS))
+#define RTMP_SET_PACKET_NET_DEVICE_APCLI(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_APCLI))
+#define RTMP_SET_PACKET_NET_DEVICE_MESH(_p, _idx) RTMP_SET_PACKET_IF((_p), ((_idx) + MIN_NET_DEVICE_FOR_MESH))
+#define RTMP_GET_PACKET_NET_DEVICE_MBSSID(_p) RTMP_GET_PACKET_IF((_p))
+#define RTMP_GET_PACKET_NET_DEVICE(_p) RTMP_GET_PACKET_IF((_p))
+
+#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7] = _morebit)
+#define RTMP_GET_PACKET_MOREDATA(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+7])
+
+
+#if 0
+//#define RTMP_SET_PACKET_DHCP(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg)
+//#define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11])
+#else
+//
+// Sepcific Pakcet Type definition
+//
+#define RTMP_PACKET_SPECIFIC_CB_OFFSET 11
+
+#define RTMP_PACKET_SPECIFIC_DHCP 0x01
+#define RTMP_PACKET_SPECIFIC_EAPOL 0x02
+#define RTMP_PACKET_SPECIFIC_IPV4 0x04
+#define RTMP_PACKET_SPECIFIC_WAI 0x08
+#define RTMP_PACKET_SPECIFIC_VLAN 0x10
+#define RTMP_PACKET_SPECIFIC_LLCSNAP 0x20
+
+//Specific
+#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] = _flg)
+
+//DHCP
+#define RTMP_SET_PACKET_DHCP(_p, _flg) \
+ do{ \
+ if (_flg) \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DHCP); \
+ else \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_DHCP); \
+ }while(0)
+#define RTMP_GET_PACKET_DHCP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DHCP)
+
+//EAPOL
+#define RTMP_SET_PACKET_EAPOL(_p, _flg) \
+ do{ \
+ if (_flg) \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_EAPOL); \
+ else \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_EAPOL); \
+ }while(0)
+#define RTMP_GET_PACKET_EAPOL(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_EAPOL)
+
+//WAI
+#define RTMP_SET_PACKET_WAI(_p, _flg) \
+ do{ \
+ if (_flg) \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_WAI); \
+ else \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_WAI); \
+ }while(0)
+#define RTMP_GET_PACKET_WAI(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_WAI)
+
+#define RTMP_GET_PACKET_LOWRATE(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & (RTMP_PACKET_SPECIFIC_EAPOL | RTMP_PACKET_SPECIFIC_DHCP | RTMP_PACKET_SPECIFIC_WAI))
+
+//VLAN
+#define RTMP_SET_PACKET_VLAN(_p, _flg) \
+ do{ \
+ if (_flg) \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_VLAN); \
+ else \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_VLAN); \
+ }while(0)
+#define RTMP_GET_PACKET_VLAN(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_VLAN)
+
+//LLC/SNAP
+#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \
+ do{ \
+ if (_flg) \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \
+ else \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_LLCSNAP); \
+ }while(0)
+
+#define RTMP_GET_PACKET_LLCSNAP(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_LLCSNAP)
+
+// IP
+#define RTMP_SET_PACKET_IPV4(_p, _flg) \
+ do{ \
+ if (_flg) \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_IPV4); \
+ else \
+ (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (!RTMP_PACKET_SPECIFIC_IPV4); \
+ }while(0)
+
+#define RTMP_GET_PACKET_IPV4(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_IPV4)
+
+#endif
+
+
+// If this flag is set, it indicates that this EAPoL frame MUST be clear.
+#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12] = _flg)
+#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+12])
+
+#define RTMP_SET_PACKET_5VT(_p, _flg) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22] = _flg)
+#define RTMP_GET_PACKET_5VT(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+22])
+
+#ifdef CONFIG_5VT_ENHANCE
+#define BRIDGE_TAG 0x35564252 // depends on 5VT define in br_input.c
+#endif
+
+
+#define NDIS_SET_PACKET_STATUS(_p, _status)
+
+
+#define GET_SG_LIST_FROM_PACKET(_p, _sc) \
+ rt_get_sg_list_from_packet(_p, _sc)
+
+#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length)
+#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length)
+#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length)
+#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length))
+#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length))
+
+
+#define RTMP_INC_REF(_A) 0
+#define RTMP_DEC_REF(_A) 0
+#define RTMP_GET_REF(_A) 0
+
+
+
+/*
+ * ULONG
+ * RTMP_GetPhysicalAddressLow(
+ * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress);
+ */
+#define RTMP_GetPhysicalAddressLow(PhysicalAddress) (PhysicalAddress)
+
+/*
+ * ULONG
+ * RTMP_GetPhysicalAddressHigh(
+ * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress);
+ */
+#define RTMP_GetPhysicalAddressHigh(PhysicalAddress) (0)
+
+/*
+ * VOID
+ * RTMP_SetPhysicalAddressLow(
+ * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
+ * IN ULONG Value);
+ */
+#define RTMP_SetPhysicalAddressLow(PhysicalAddress, Value) \
+ PhysicalAddress = Value;
+
+/*
+ * VOID
+ * RTMP_SetPhysicalAddressHigh(
+ * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress,
+ * IN ULONG Value);
+ */
+#define RTMP_SetPhysicalAddressHigh(PhysicalAddress, Value)
+
+
+//CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx);
+#define QUEUE_ENTRY_TO_PACKET(pEntry) \
+ (PNDIS_PACKET)(pEntry)
+
+#define PACKET_TO_QUEUE_ENTRY(pPacket) \
+ (PQUEUE_ENTRY)(pPacket)
+
+
+#ifndef CONTAINING_RECORD
+#define CONTAINING_RECORD(address, type, field) \
+((type *)((PCHAR)(address) - offsetof(type, field)))
+#endif
+
+
+#define RELEASE_NDIS_PACKET(_pAd, _pPacket, _Status) \
+{ \
+ RTMPFreeNdisPacket(_pAd, _pPacket); \
+}
+
+
+#define SWITCH_PhyAB(_pAA, _pBB) \
+{ \
+ ULONG AABasePaHigh; \
+ ULONG AABasePaLow; \
+ ULONG BBBasePaHigh; \
+ ULONG BBBasePaLow; \
+ BBBasePaHigh = RTMP_GetPhysicalAddressHigh(_pBB); \
+ BBBasePaLow = RTMP_GetPhysicalAddressLow(_pBB); \
+ AABasePaHigh = RTMP_GetPhysicalAddressHigh(_pAA); \
+ AABasePaLow = RTMP_GetPhysicalAddressLow(_pAA); \
+ RTMP_SetPhysicalAddressHigh(_pAA, BBBasePaHigh); \
+ RTMP_SetPhysicalAddressLow(_pAA, BBBasePaLow); \
+ RTMP_SetPhysicalAddressHigh(_pBB, AABasePaHigh); \
+ RTMP_SetPhysicalAddressLow(_pBB, AABasePaLow); \
+}
+
+
+#define NdisWriteErrorLogEntry(_a, _b, _c, _d)
+#define NdisMAllocateMapRegisters(_a, _b, _c, _d, _e) NDIS_STATUS_SUCCESS
+
+
+#define NdisAcquireSpinLock RTMP_SEM_LOCK
+#define NdisReleaseSpinLock RTMP_SEM_UNLOCK
+
+static inline void NdisGetSystemUpTime(ULONG *time)
+{
+ *time = jiffies;
+}
+
+//pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx);
+#define QUEUE_ENTRY_TO_PKT(pEntry) \
+ ((PNDIS_PACKET) (pEntry))
+
+int rt28xx_packet_xmit(struct sk_buff *skb);
+
+
+
+void rtmp_os_thread_init(PUCHAR pThreadName, PVOID pNotify);
+
+#ifdef RT2860
+#if !defined(PCI_CAP_ID_EXP)
+#define PCI_CAP_ID_EXP 0x10
+#endif
+
+#if !defined(PCI_EXP_LNKCTL)
+#define PCI_EXP_LNKCTL 0x10
+#endif
+
+#if !defined(PCI_CLASS_BRIDGE_PCI)
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#endif
+
+#define PCIBUS_INTEL_VENDOR 0x8086
+#endif // RT2860 //
+
+
diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c
new file mode 100644
index 000000000000..3873c478f4ec
--- /dev/null
+++ b/drivers/staging/rt2860/rt_main_dev.c
@@ -0,0 +1,1686 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rt_main_dev.c
+
+ Abstract:
+ Create and register network interface.
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Sample Mar/21/07 Merge RT2870 and RT2860 drivers.
+*/
+
+#include "rt_config.h"
+
+#define FORTY_MHZ_INTOLERANT_INTERVAL (60*1000) // 1 min
+
+#ifdef MULTIPLE_CARD_SUPPORT
+// record whether the card in the card list is used in the card file
+UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD];
+// record used card mac address in the card list
+static UINT8 MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6];
+#endif // MULTIPLE_CARD_SUPPORT //
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+UINT32 CW_MAX_IN_BITS;
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+/*---------------------------------------------------------------------*/
+/* Private Variables Used */
+/*---------------------------------------------------------------------*/
+//static RALINK_TIMER_STRUCT PeriodicTimer;
+
+char *mac = ""; // default 00:00:00:00:00:00
+char *hostname = ""; // default CMPC
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
+MODULE_PARM (mac, "s");
+#else
+module_param (mac, charp, 0);
+#endif
+MODULE_PARM_DESC (mac, "rt28xx: wireless mac addr");
+
+
+/*---------------------------------------------------------------------*/
+/* Prototypes of Functions Used */
+/*---------------------------------------------------------------------*/
+#ifdef DOT11_N_SUPPORT
+extern BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num);
+extern void ba_reordering_resource_release(PRTMP_ADAPTER pAd);
+#endif // DOT11_N_SUPPORT //
+extern NDIS_STATUS NICLoadRateSwitchingParams(IN PRTMP_ADAPTER pAd);
+
+#ifdef RT2860
+extern void init_thread_task(PRTMP_ADAPTER pAd);
+#endif // RT2860 //
+
+// public function prototype
+INT __devinit rt28xx_probe(IN void *_dev_p, IN void *_dev_id_p,
+ IN UINT argc, OUT PRTMP_ADAPTER *ppAd);
+
+// private function prototype
+static int rt28xx_init(IN struct net_device *net_dev);
+INT rt28xx_send_packets(IN struct sk_buff *skb_p, IN struct net_device *net_dev);
+
+#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1
+struct net_device *alloc_netdev(
+ int sizeof_priv,
+ const char *mask,
+ void (*setup)(struct net_device *));
+#endif // LINUX_VERSION_CODE //
+
+static void CfgInitHook(PRTMP_ADAPTER pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+extern const struct iw_handler_def rt28xx_iw_handler_def;
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+extern const struct iw_handler_def rt28xx_ap_iw_handler_def;
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+#if WIRELESS_EXT >= 12
+// This function will be called when query /proc
+struct iw_statistics *rt28xx_get_wireless_stats(
+ IN struct net_device *net_dev);
+#endif
+
+struct net_device_stats *RT28xx_get_ether_stats(
+ IN struct net_device *net_dev);
+
+/*
+========================================================================
+Routine Description:
+ Close raxx interface.
+
+Arguments:
+ *net_dev the raxx interface pointer
+
+Return Value:
+ 0 Open OK
+ otherwise Open Fail
+
+Note:
+ 1. if open fail, kernel will not call the close function.
+ 2. Free memory for
+ (1) Mlme Memory Handler: MlmeHalt()
+ (2) TX & RX: RTMPFreeTxRxRingMemory()
+ (3) BA Reordering: ba_reordering_resource_release()
+========================================================================
+*/
+int MainVirtualIF_close(IN struct net_device *net_dev)
+{
+ RTMP_ADAPTER *pAd = net_dev->ml_priv;
+
+ // Sanity check for pAd
+ if (pAd == NULL)
+ return 0; // close ok
+
+ netif_carrier_off(pAd->net_dev);
+ netif_stop_queue(pAd->net_dev);
+
+
+ VIRTUAL_IF_DOWN(pAd);
+
+ RT_MOD_DEC_USE_COUNT();
+
+ return 0; // close ok
+}
+
+/*
+========================================================================
+Routine Description:
+ Open raxx interface.
+
+Arguments:
+ *net_dev the raxx interface pointer
+
+Return Value:
+ 0 Open OK
+ otherwise Open Fail
+
+Note:
+ 1. if open fail, kernel will not call the close function.
+ 2. Free memory for
+ (1) Mlme Memory Handler: MlmeHalt()
+ (2) TX & RX: RTMPFreeTxRxRingMemory()
+ (3) BA Reordering: ba_reordering_resource_release()
+========================================================================
+*/
+int MainVirtualIF_open(IN struct net_device *net_dev)
+{
+ RTMP_ADAPTER *pAd = net_dev->ml_priv;
+
+ // Sanity check for pAd
+ if (pAd == NULL)
+ return 0; // close ok
+
+ if (VIRTUAL_IF_UP(pAd) != 0)
+ return -1;
+
+ // increase MODULE use count
+ RT_MOD_INC_USE_COUNT();
+
+ netif_start_queue(net_dev);
+ netif_carrier_on(net_dev);
+ netif_wake_queue(net_dev);
+
+ return 0;
+}
+
+/*
+========================================================================
+Routine Description:
+ Close raxx interface.
+
+Arguments:
+ *net_dev the raxx interface pointer
+
+Return Value:
+ 0 Open OK
+ otherwise Open Fail
+
+Note:
+ 1. if open fail, kernel will not call the close function.
+ 2. Free memory for
+ (1) Mlme Memory Handler: MlmeHalt()
+ (2) TX & RX: RTMPFreeTxRxRingMemory()
+ (3) BA Reordering: ba_reordering_resource_release()
+========================================================================
+*/
+int rt28xx_close(IN PNET_DEV dev)
+{
+ struct net_device * net_dev = (struct net_device *)dev;
+ RTMP_ADAPTER *pAd = net_dev->ml_priv;
+ BOOLEAN Cancelled = FALSE;
+ UINT32 i = 0;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n"));
+
+ // Sanity check for pAd
+ if (pAd == NULL)
+ return 0; // close ok
+
+
+#ifdef WDS_SUPPORT
+ WdsDown(pAd);
+#endif // WDS_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef RT2860
+ RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE);
+#endif // RT2860 //
+
+ // If dirver doesn't wake up firmware here,
+ // NICLoadFirmware will hang forever when interface is up again.
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ {
+ AsicForceWakeup(pAd, TRUE);
+ }
+
+#ifdef QOS_DLS_SUPPORT
+ // send DLS-TEAR_DOWN message,
+ if (pAd->CommonCfg.bDLSCapable)
+ {
+ UCHAR i;
+
+ // tear down local dls table entry
+ for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+ {
+ RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ }
+ }
+
+ // tear down peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+ {
+ RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ }
+ }
+ RT28XX_MLME_HANDLER(pAd);
+ }
+#endif // QOS_DLS_SUPPORT //
+
+ if (INFRA_ON(pAd) &&
+ (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
+ {
+ MLME_DISASSOC_REQ_STRUCT DisReq;
+ MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
+
+ COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid);
+ DisReq.Reason = REASON_DEAUTH_STA_LEAVING;
+
+ MsgElem->Machine = ASSOC_STATE_MACHINE;
+ MsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
+ MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
+ NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT));
+
+ // Prevent to connect AP again in STAMlmePeriodicExec
+ pAd->MlmeAux.AutoReconnectSsidLen= 32;
+ NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
+ MlmeDisassocReqAction(pAd, MsgElem);
+ kfree(MsgElem);
+
+ RTMPusecDelay(1000);
+ }
+
+
+#ifdef CCX_SUPPORT
+ RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &Cancelled);
+#endif
+
+ RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled);
+ RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ // send wireless event to wpa_supplicant for infroming interface down.
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_INTERFACE_DOWN;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+ MlmeRadioOff(pAd);
+#ifdef RT2860
+ pAd->bPCIclkOff = FALSE;
+#endif // RT2860 //
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+
+ for (i = 0 ; i < NUM_OF_TX_RING; i++)
+ {
+ while (pAd->DeQueueRunning[i] == TRUE)
+ {
+ printk("Waiting for TxQueue[%d] done..........\n", i);
+ RTMPusecDelay(1000);
+ }
+ }
+
+ // Stop Mlme state machine
+ MlmeHalt(pAd);
+
+ // Close kernel threads or tasklets
+ kill_thread_task(pAd);
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ MacTableReset(pAd);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+
+ MeasureReqTabExit(pAd);
+ TpcReqTabExit(pAd);
+
+
+#ifdef RT2860
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE))
+ {
+ NICDisableInterrupt(pAd);
+ }
+
+ // Disable Rx, register value supposed will remain after reset
+ NICIssueReset(pAd);
+
+ // Free IRQ
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ {
+ // Deregister interrupt function
+ RT28XX_IRQ_RELEASE(net_dev)
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+ }
+#endif // RT2860 //
+
+
+ // Free Ring or USB buffers
+ RTMPFreeTxRxRingMemory(pAd);
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);
+
+#ifdef DOT11_N_SUPPORT
+ // Free BA reorder resource
+ ba_reordering_resource_release(pAd);
+#endif // DOT11_N_SUPPORT //
+
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+ return 0; // close ok
+} /* End of rt28xx_close */
+
+static int rt28xx_init(IN struct net_device *net_dev)
+{
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)net_dev->ml_priv;
+ UINT index;
+ UCHAR TmpPhy;
+ NDIS_STATUS Status;
+ UINT32 MacCsr0 = 0;
+
+
+#ifdef DOT11_N_SUPPORT
+ // Allocate BA Reordering memory
+ ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM);
+#endif // DOT11_N_SUPPORT //
+
+ // Make sure MAC gets ready.
+ index = 0;
+ do
+ {
+ RTMP_IO_READ32(pAd, MAC_CSR0, &MacCsr0);
+ pAd->MACVersion = MacCsr0;
+
+ if ((pAd->MACVersion != 0x00) && (pAd->MACVersion != 0xFFFFFFFF))
+ break;
+
+ RTMPusecDelay(10);
+ } while (index++ < 100);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MAC_CSR0 [ Ver:Rev=0x%08x]\n", pAd->MACVersion));
+
+ // Disable DMA
+ RT28XXDMADisable(pAd);
+
+
+ // Load 8051 firmware
+ Status = NICLoadFirmware(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("NICLoadFirmware failed, Status[=0x%08x]\n", Status));
+ goto err1;
+ }
+
+ NICLoadRateSwitchingParams(pAd);
+
+ // Disable interrupts here which is as soon as possible
+ // This statement should never be true. We might consider to remove it later
+#ifdef RT2860
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE))
+ {
+ NICDisableInterrupt(pAd);
+ }
+#endif // RT2860 //
+
+ Status = RTMPAllocTxRxRingMemory(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("RTMPAllocDMAMemory failed, Status[=0x%08x]\n", Status));
+ goto err1;
+ }
+
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+
+ // initialize MLME
+ //
+
+ Status = MlmeInit(pAd);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status));
+ goto err2;
+ }
+
+ // Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default
+ //
+ UserCfgInit(pAd);
+
+
+ RT28XX_TASK_THREAD_INIT(pAd, Status);
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err1;
+
+ CfgInitHook(pAd);
+
+
+#ifdef BLOCK_NET_IF
+ initblockQueueTab(pAd);
+#endif // BLOCK_NET_IF //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ NdisAllocateSpinLock(&pAd->MacTabLock);
+#endif // CONFIG_STA_SUPPORT //
+
+ MeasureReqTabInit(pAd);
+ TpcReqTabInit(pAd);
+
+ //
+ // Init the hardware, we need to init asic before read registry, otherwise mac register will be reset
+ //
+ Status = NICInitializeAdapter(pAd, TRUE);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status));
+ if (Status != NDIS_STATUS_SUCCESS)
+ goto err3;
+ }
+
+ // Read parameters from Config File
+ Status = RTMPReadParametersHook(pAd);
+
+ printk("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT_ERR(("NICReadRegParameters failed, Status[=0x%08x]\n",Status));
+ goto err4;
+ }
+
+
+
+ //Init Ba Capability parameters.
+#ifdef DOT11_N_SUPPORT
+ pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+ pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable;
+ pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+ pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+ // UPdata to HT IE
+ pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode;
+ pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize;
+ pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity;
+#endif // DOT11_N_SUPPORT //
+
+ printk("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
+
+ // We should read EEPROM for all cases. rt2860b
+ NICReadEEPROMParameters(pAd, mac);
+
+ printk("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode);
+
+ NICInitAsicFromEEPROM(pAd); //rt2860b
+
+ // Set PHY to appropriate mode
+ TmpPhy = pAd->CommonCfg.PhyMode;
+ pAd->CommonCfg.PhyMode = 0xff;
+ RTMPSetPhyMode(pAd, TmpPhy);
+#ifdef DOT11_N_SUPPORT
+ SetCommonHT(pAd);
+#endif // DOT11_N_SUPPORT //
+
+ // No valid channels.
+ if (pAd->ChannelListNum == 0)
+ {
+ printk("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n");
+ goto err4;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ printk("MCS Set = %02x %02x %02x %02x %02x\n", pAd->CommonCfg.HtCapability.MCSSet[0],
+ pAd->CommonCfg.HtCapability.MCSSet[1], pAd->CommonCfg.HtCapability.MCSSet[2],
+ pAd->CommonCfg.HtCapability.MCSSet[3], pAd->CommonCfg.HtCapability.MCSSet[4]);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef IKANOS_VX_1X0
+ VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress);
+#endif // IKANOS_VX_1X0 //
+
+ //
+ // Initialize RF register to default value
+ //
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+ // 8051 firmware require the signal during booting time.
+ AsicSendCommandToMcu(pAd, 0x72, 0xFF, 0x00, 0x00);
+
+ if (pAd && (Status != NDIS_STATUS_SUCCESS))
+ {
+ //
+ // Undo everything if it failed
+ //
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
+ {
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
+ }
+ }
+ else if (pAd)
+ {
+ // Microsoft HCT require driver send a disconnect event after driver initialization.
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
+ DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n"));
+
+
+ }// end of else
+
+
+ DBGPRINT_S(Status, ("<==== RTMPInitialize, Status=%x\n", Status));
+
+ return TRUE;
+
+
+err4:
+err3:
+ MlmeHalt(pAd);
+err2:
+ RTMPFreeTxRxRingMemory(pAd);
+err1:
+
+#ifdef DOT11_N_SUPPORT
+ os_free_mem(pAd, pAd->mpdu_blk_pool.mem); // free BA pool
+#endif // DOT11_N_SUPPORT //
+ RT28XX_IRQ_RELEASE(net_dev);
+
+ // shall not set ml_priv to NULL here because the ml_priv didn't been free yet.
+ //net_dev->ml_priv = 0;
+#ifdef INF_AMAZON_SE
+err0:
+#endif // INF_AMAZON_SE //
+ printk("!!! %s Initialized fail !!!\n", RT28xx_CHIP_NAME);
+ return FALSE;
+} /* End of rt28xx_init */
+
+
+/*
+========================================================================
+Routine Description:
+ Open raxx interface.
+
+Arguments:
+ *net_dev the raxx interface pointer
+
+Return Value:
+ 0 Open OK
+ otherwise Open Fail
+
+Note:
+========================================================================
+*/
+int rt28xx_open(IN PNET_DEV dev)
+{
+ struct net_device * net_dev = (struct net_device *)dev;
+ PRTMP_ADAPTER pAd = net_dev->ml_priv;
+ int retval = 0;
+ POS_COOKIE pObj;
+
+
+ // Sanity check for pAd
+ if (pAd == NULL)
+ {
+ /* if 1st open fail, pAd will be free;
+ So the net_dev->ml_priv will be NULL in 2rd open */
+ return -1;
+ }
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ CW_MAX_IN_BITS = 6;
+ }
+ else if (pAd->OpMode == OPMODE_STA)
+ {
+ CW_MAX_IN_BITS = 10;
+ }
+
+#if WIRELESS_EXT >= 12
+ if (net_dev->priv_flags == INT_MAIN)
+ {
+ if (pAd->OpMode == OPMODE_AP)
+ net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_ap_iw_handler_def;
+ else if (pAd->OpMode == OPMODE_STA)
+ net_dev->wireless_handlers = (struct iw_handler_def *) &rt28xx_iw_handler_def;
+ }
+#endif // WIRELESS_EXT >= 12 //
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef RT2860
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // If dirver doesn't wake up firmware here,
+ // NICLoadFirmware will hang forever when interface is up again.
+ // RT2860 PCI
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE) &&
+ OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ AUTO_WAKEUP_STRUC AutoWakeupCfg;
+ AsicForceWakeup(pAd, TRUE);
+ AutoWakeupCfg.word = 0;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+ }
+ }
+#endif // RT2860 //
+#endif // CONFIG_STA_SUPPORT //
+
+ // Init
+ pObj = (POS_COOKIE)pAd->OS_Cookie;
+
+ // reset Adapter flags
+ RTMP_CLEAR_FLAGS(pAd);
+
+ // Request interrupt service routine for PCI device
+ // register the interrupt routine with the os
+ RT28XX_IRQ_REQUEST(net_dev);
+
+
+ // Init BssTab & ChannelInfo tabbles for auto channel select.
+
+
+ // Chip & other init
+ if (rt28xx_init(net_dev) == FALSE)
+ goto err;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ NdisZeroMemory(pAd->StaCfg.dev_name, 16);
+ NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name));
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // Set up the Mac address
+ NdisMoveMemory(net_dev->dev_addr, (void *) pAd->CurrentAddress, 6);
+
+ // Init IRQ parameters
+ RT28XX_IRQ_INIT(pAd);
+
+ // Various AP function init
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ // send wireless event to wpa_supplicant for infroming interface down.
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_INTERFACE_UP;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // Enable Interrupt
+ RT28XX_IRQ_ENABLE(pAd);
+
+ // Now Enable RxTx
+ RTMPEnableRxTx(pAd);
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP);
+
+ {
+ UINT32 reg = 0;
+ RTMP_IO_READ32(pAd, 0x1300, &reg); // clear garbage interrupts
+ printk("0x1300 = %08x\n", reg);
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef RT2860
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ RTMPInitPCIeLinkCtrlValue(pAd);
+#endif // RT2860 //
+#endif // CONFIG_STA_SUPPORT //
+
+ return (retval);
+
+err:
+ return (-1);
+} /* End of rt28xx_open */
+
+
+/* Must not be called for mdev and apdev */
+static NDIS_STATUS rt_ieee80211_if_setup(struct net_device *dev, PRTMP_ADAPTER pAd)
+{
+ NDIS_STATUS Status;
+ INT i=0;
+ CHAR slot_name[IFNAMSIZ];
+ struct net_device *device;
+
+
+ //ether_setup(dev);
+ dev->hard_start_xmit = rt28xx_send_packets;
+
+#ifdef IKANOS_VX_1X0
+ dev->hard_start_xmit = IKANOS_DataFramesTx;
+#endif // IKANOS_VX_1X0 //
+
+#ifdef CONFIG_STA_SUPPORT
+#if WIRELESS_EXT >= 12
+ if (pAd->OpMode == OPMODE_STA)
+ {
+ dev->wireless_handlers = &rt28xx_iw_handler_def;
+ }
+#endif //WIRELESS_EXT >= 12
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+#if WIRELESS_EXT >= 12
+ if (pAd->OpMode == OPMODE_AP)
+ {
+ dev->wireless_handlers = &rt28xx_ap_iw_handler_def;
+ }
+#endif //WIRELESS_EXT >= 12
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+#if WIRELESS_EXT < 21
+ dev->get_wireless_stats = rt28xx_get_wireless_stats;
+#endif
+ dev->get_stats = RT28xx_get_ether_stats;
+ dev->open = MainVirtualIF_open; //rt28xx_open;
+ dev->stop = MainVirtualIF_close; //rt28xx_close;
+ dev->priv_flags = INT_MAIN;
+ dev->do_ioctl = rt28xx_ioctl;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ dev->validate_addr = NULL;
+#endif
+ // find available device name
+ for (i = 0; i < 8; i++)
+ {
+#ifdef MULTIPLE_CARD_SUPPORT
+ if (pAd->MC_RowID >= 0)
+ sprintf(slot_name, "ra%02d_%d", pAd->MC_RowID, i);
+ else
+#endif // MULTIPLE_CARD_SUPPORT //
+ sprintf(slot_name, "ra%d", i);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+ device = dev_get_by_name(dev_net(dev), slot_name);
+#else
+ device = dev_get_by_name(dev->nd_net, slot_name);
+#endif
+#else
+ device = dev_get_by_name(slot_name);
+#endif
+ if (device != NULL) dev_put(device);
+#else
+ for (device = dev_base; device != NULL; device = device->next)
+ {
+ if (strncmp(device->name, slot_name, 4) == 0)
+ break;
+ }
+#endif
+ if(device == NULL)
+ break;
+ }
+
+ if(i == 8)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("No available slot name\n"));
+ Status = NDIS_STATUS_FAILURE;
+ }
+ else
+ {
+#ifdef MULTIPLE_CARD_SUPPORT
+ if (pAd->MC_RowID >= 0)
+ sprintf(dev->name, "ra%02d_%d", pAd->MC_RowID, i);
+ else
+#endif // MULTIPLE_CARD_SUPPORT //
+ sprintf(dev->name, "ra%d", i);
+ Status = NDIS_STATUS_SUCCESS;
+ }
+
+ return Status;
+
+}
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+/*
+========================================================================
+Routine Description:
+ Get card profile path.
+
+Arguments:
+ pAd
+
+Return Value:
+ TRUE - Find a card profile
+ FALSE - use default profile
+
+Note:
+========================================================================
+*/
+extern INT RTMPGetKeyParameter(
+ IN PCHAR key,
+ OUT PCHAR dest,
+ IN INT destsize,
+ IN PCHAR buffer);
+
+BOOLEAN RTMP_CardInfoRead(
+ IN PRTMP_ADAPTER pAd)
+{
+#define MC_SELECT_CARDID 0 /* use CARD ID (0 ~ 31) to identify different cards */
+#define MC_SELECT_MAC 1 /* use CARD MAC to identify different cards */
+#define MC_SELECT_CARDTYPE 2 /* use CARD type (abgn or bgn) to identify different cards */
+
+#define LETTER_CASE_TRANSLATE(txt_p, card_id) \
+ { UINT32 _len; char _char; \
+ for(_len=0; _len<strlen(card_id); _len++) { \
+ _char = *(txt_p + _len); \
+ if (('A' <= _char) && (_char <= 'Z')) \
+ *(txt_p+_len) = 'a'+(_char-'A'); \
+ } }
+
+ struct file *srcf;
+ INT retval, orgfsuid, orgfsgid;
+ mm_segment_t orgfs;
+ CHAR *buffer, *tmpbuf, card_id_buf[30], RFIC_word[30];
+ BOOLEAN flg_match_ok = FALSE;
+ INT32 card_select_method;
+ INT32 card_free_id, card_nouse_id, card_same_mac_id, card_match_id;
+ EEPROM_ANTENNA_STRUC antenna;
+ USHORT addr01, addr23, addr45;
+ UINT8 mac[6];
+ UINT32 data, card_index;
+ UCHAR *start_ptr;
+
+
+ // init
+ buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ if (buffer == NULL)
+ return FALSE;
+
+ tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ if(tmpbuf == NULL)
+ {
+ kfree(buffer);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ orgfsuid = current->fsuid;
+ orgfsgid = current->fsgid;
+ current->fsuid = current->fsgid = 0;
+ orgfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ // get RF IC type
+ RTMP_IO_READ32(pAd, E2PROM_CSR, &data);
+
+ if ((data & 0x30) == 0)
+ pAd->EEPROMAddressNum = 6; // 93C46
+ else if ((data & 0x30) == 0x10)
+ pAd->EEPROMAddressNum = 8; // 93C66
+ else
+ pAd->EEPROMAddressNum = 8; // 93C86
+
+ RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, antenna.word);
+
+ if ((antenna.field.RfIcType == RFIC_2850) ||
+ (antenna.field.RfIcType == RFIC_2750))
+ {
+ /* ABGN card */
+ strcpy(RFIC_word, "abgn");
+ }
+ else
+ {
+ /* BGN card */
+ strcpy(RFIC_word, "bgn");
+ }
+
+ // get MAC address
+ RT28xx_EEPROM_READ16(pAd, 0x04, addr01);
+ RT28xx_EEPROM_READ16(pAd, 0x06, addr23);
+ RT28xx_EEPROM_READ16(pAd, 0x08, addr45);
+
+ mac[0] = (UCHAR)(addr01 & 0xff);
+ mac[1] = (UCHAR)(addr01 >> 8);
+ mac[2] = (UCHAR)(addr23 & 0xff);
+ mac[3] = (UCHAR)(addr23 >> 8);
+ mac[4] = (UCHAR)(addr45 & 0xff);
+ mac[5] = (UCHAR)(addr45 >> 8);
+
+ // open card information file
+ srcf = filp_open(CARD_INFO_PATH, O_RDONLY, 0);
+ if (IS_ERR(srcf))
+ {
+ /* card information file does not exist */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("--> Error %ld opening %s\n", -PTR_ERR(srcf), CARD_INFO_PATH));
+ return FALSE;
+ }
+
+ if (srcf->f_op && srcf->f_op->read)
+ {
+ /* card information file exists so reading the card information */
+ memset(buffer, 0x00, MAX_INI_BUFFER_SIZE);
+ retval = srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos);
+ if (retval < 0)
+ {
+ /* read fail */
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("--> Read %s error %d\n", CARD_INFO_PATH, -retval));
+ }
+ else
+ {
+ /* get card selection method */
+ memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE);
+ card_select_method = MC_SELECT_CARDTYPE; // default
+
+ if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer))
+ {
+ if (strcmp(tmpbuf, "CARDID") == 0)
+ card_select_method = MC_SELECT_CARDID;
+ else if (strcmp(tmpbuf, "MAC") == 0)
+ card_select_method = MC_SELECT_MAC;
+ else if (strcmp(tmpbuf, "CARDTYPE") == 0)
+ card_select_method = MC_SELECT_CARDTYPE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("MC> Card Selection = %d\n", card_select_method));
+
+ // init
+ card_free_id = -1;
+ card_nouse_id = -1;
+ card_same_mac_id = -1;
+ card_match_id = -1;
+
+ // search current card information records
+ for(card_index=0;
+ card_index<MAX_NUM_OF_MULTIPLE_CARD;
+ card_index++)
+ {
+ if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) &&
+ (*(UINT16 *)&MC_CardMac[card_index][4] == 0))
+ {
+ // MAC is all-0 so the entry is available
+ MC_CardUsed[card_index] = 0;
+
+ if (card_free_id < 0)
+ card_free_id = card_index; // 1st free entry
+ }
+ else
+ {
+ if (memcmp(MC_CardMac[card_index], mac, 6) == 0)
+ {
+ // we find the entry with same MAC
+ if (card_same_mac_id < 0)
+ card_same_mac_id = card_index; // 1st same entry
+ }
+ else
+ {
+ // MAC is not all-0 but used flag == 0
+ if ((MC_CardUsed[card_index] == 0) &&
+ (card_nouse_id < 0))
+ {
+ card_nouse_id = card_index; // 1st available entry
+ }
+ }
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("MC> Free = %d, Same = %d, NOUSE = %d\n",
+ card_free_id, card_same_mac_id, card_nouse_id));
+
+ if ((card_same_mac_id >= 0) &&
+ ((card_select_method == MC_SELECT_CARDID) ||
+ (card_select_method == MC_SELECT_CARDTYPE)))
+ {
+ // same MAC entry is found
+ card_match_id = card_same_mac_id;
+
+ if (card_select_method == MC_SELECT_CARDTYPE)
+ {
+ // for CARDTYPE
+ sprintf(card_id_buf, "%02dCARDTYPE%s",
+ card_match_id, RFIC_word);
+
+ if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL)
+ {
+ // we found the card ID
+ LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+ }
+ }
+ }
+ else
+ {
+ // the card is 1st plug-in, try to find the match card profile
+ switch(card_select_method)
+ {
+ case MC_SELECT_CARDID: // CARDID
+ default:
+ if (card_free_id >= 0)
+ card_match_id = card_free_id;
+ else
+ card_match_id = card_nouse_id;
+ break;
+
+ case MC_SELECT_MAC: // MAC
+ sprintf(card_id_buf, "MAC%02x:%02x:%02x:%02x:%02x:%02x",
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+
+ /* try to find the key word in the card file */
+ if ((start_ptr=rtstrstruncasecmp(buffer, card_id_buf)) != NULL)
+ {
+ LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+
+ /* get the row ID (2 ASCII characters) */
+ start_ptr -= 2;
+ card_id_buf[0] = *(start_ptr);
+ card_id_buf[1] = *(start_ptr+1);
+ card_id_buf[2] = 0x00;
+
+ card_match_id = simple_strtol(card_id_buf, 0, 10);
+ }
+ break;
+
+ case MC_SELECT_CARDTYPE: // CARDTYPE
+ card_nouse_id = -1;
+
+ for(card_index=0;
+ card_index<MAX_NUM_OF_MULTIPLE_CARD;
+ card_index++)
+ {
+ sprintf(card_id_buf, "%02dCARDTYPE%s",
+ card_index, RFIC_word);
+
+ if ((start_ptr=rtstrstruncasecmp(buffer,
+ card_id_buf)) != NULL)
+ {
+ LETTER_CASE_TRANSLATE(start_ptr, card_id_buf);
+
+ if (MC_CardUsed[card_index] == 0)
+ {
+ /* current the card profile is not used */
+ if ((*(UINT32 *)&MC_CardMac[card_index][0] == 0) &&
+ (*(UINT16 *)&MC_CardMac[card_index][4] == 0))
+ {
+ // find it and no previous card use it
+ card_match_id = card_index;
+ break;
+ }
+ else
+ {
+ // ever a card use it
+ if (card_nouse_id < 0)
+ card_nouse_id = card_index;
+ }
+ }
+ }
+ }
+
+ // if not find a free one, use the available one
+ if (card_match_id < 0)
+ card_match_id = card_nouse_id;
+ break;
+ }
+ }
+
+ if (card_match_id >= 0)
+ {
+ // make up search keyword
+ switch(card_select_method)
+ {
+ case MC_SELECT_CARDID: // CARDID
+ sprintf(card_id_buf, "%02dCARDID", card_match_id);
+ break;
+
+ case MC_SELECT_MAC: // MAC
+ sprintf(card_id_buf,
+ "%02dmac%02x:%02x:%02x:%02x:%02x:%02x",
+ card_match_id,
+ mac[0], mac[1], mac[2],
+ mac[3], mac[4], mac[5]);
+ break;
+
+ case MC_SELECT_CARDTYPE: // CARDTYPE
+ default:
+ sprintf(card_id_buf, "%02dcardtype%s",
+ card_match_id, RFIC_word);
+ break;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf));
+
+ // read card file path
+ if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer))
+ {
+ if (strlen(tmpbuf) < sizeof(pAd->MC_FileName))
+ {
+ // backup card information
+ pAd->MC_RowID = card_match_id; /* base 0 */
+ MC_CardUsed[card_match_id] = 1;
+ memcpy(MC_CardMac[card_match_id], mac, sizeof(mac));
+
+ // backup card file path
+ NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf));
+ pAd->MC_FileName[strlen(tmpbuf)] = '\0';
+ flg_match_ok = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("Card Profile Name = %s\n", pAd->MC_FileName));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("Card Profile Name length too large!\n"));
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("Can not find search key word in card.dat!\n"));
+ }
+
+ if ((flg_match_ok != TRUE) &&
+ (card_match_id < MAX_NUM_OF_MULTIPLE_CARD))
+ {
+ MC_CardUsed[card_match_id] = 0;
+ memset(MC_CardMac[card_match_id], 0, sizeof(mac));
+ }
+ } // if (card_match_id >= 0)
+ }
+ }
+
+ // close file
+ retval = filp_close(srcf, NULL);
+ set_fs(orgfs);
+ current->fsuid = orgfsuid;
+ current->fsgid = orgfsgid;
+ kfree(buffer);
+ kfree(tmpbuf);
+ return flg_match_ok;
+}
+#endif // MULTIPLE_CARD_SUPPORT //
+
+
+/*
+========================================================================
+Routine Description:
+ Probe RT28XX chipset.
+
+Arguments:
+ _dev_p Point to the PCI or USB device
+ _dev_id_p Point to the PCI or USB device ID
+
+Return Value:
+ 0 Probe OK
+ -ENODEV Probe Fail
+
+Note:
+========================================================================
+*/
+INT __devinit rt28xx_probe(
+ IN void *_dev_p,
+ IN void *_dev_id_p,
+ IN UINT argc,
+ OUT PRTMP_ADAPTER *ppAd)
+{
+ struct net_device *net_dev;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) NULL;
+ INT status;
+ PVOID handle;
+#ifdef RT2860
+ struct pci_dev *dev_p = (struct pci_dev *)_dev_p;
+#endif // RT2860 //
+
+
+#ifdef CONFIG_STA_SUPPORT
+ DBGPRINT(RT_DEBUG_TRACE, ("STA Driver version-%s\n", STA_DRIVER_VERSION));
+#endif // CONFIG_STA_SUPPORT //
+
+#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1
+ net_dev = alloc_netdev(sizeof(PRTMP_ADAPTER), "eth%d", ether_setup);
+#else
+ net_dev = alloc_etherdev(sizeof(PRTMP_ADAPTER));
+#endif
+ if (net_dev == NULL)
+ {
+ printk("alloc_netdev failed\n");
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+ module_put(THIS_MODULE);
+#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
+#else
+ MOD_DEC_USE_COUNT;
+#endif
+ goto err_out;
+ }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+ SET_MODULE_OWNER(net_dev);
+#endif
+
+ netif_stop_queue(net_dev);
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+/* for supporting Network Manager */
+/* Set the sysfs physical device reference for the network logical device
+ * if set prior to registration will cause a symlink during initialization.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ SET_NETDEV_DEV(net_dev, &(dev_p->dev));
+#endif
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+ // Allocate RTMP_ADAPTER miniport adapter structure
+ handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL);
+ RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p);
+
+ status = RTMPAllocAdapterBlock(handle, &pAd);
+ if (status != NDIS_STATUS_SUCCESS)
+ goto err_out_free_netdev;
+
+ net_dev->ml_priv = (PVOID)pAd;
+ pAd->net_dev = net_dev; // must be before RT28XXNetDevInit()
+
+ RT28XXNetDevInit(_dev_p, net_dev, pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+ pAd->StaCfg.OriDevType = net_dev->type;
+#endif // CONFIG_STA_SUPPORT //
+
+ // Post config
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ if (RT28XXProbePostConfig(_dev_p, pAd, argc) == FALSE)
+ goto err_out_unmap;
+#else
+ if (RT28XXProbePostConfig(_dev_p, pAd, 0) == FALSE)
+ goto err_out_unmap;
+#endif // LINUX_VERSION_CODE //
+
+#ifdef CONFIG_STA_SUPPORT
+ pAd->OpMode = OPMODE_STA;
+#endif // CONFIG_STA_SUPPORT //
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+ // find its profile path
+ pAd->MC_RowID = -1; // use default profile path
+ RTMP_CardInfoRead(pAd);
+
+ if (pAd->MC_RowID == -1)
+#ifdef CONFIG_STA_SUPPORT
+ strcpy(pAd->MC_FileName, STA_PROFILE_PATH);
+#endif // CONFIG_STA_SUPPORT //
+
+ DBGPRINT(RT_DEBUG_TRACE,
+ ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName));
+#endif // MULTIPLE_CARD_SUPPORT //
+
+ // sample move
+ if (rt_ieee80211_if_setup(net_dev, pAd) != NDIS_STATUS_SUCCESS)
+ goto err_out_unmap;
+
+ // Register this device
+ status = register_netdev(net_dev);
+ if (status)
+ goto err_out_unmap;
+
+ // Set driver data
+ RT28XX_DRVDATA_SET(_dev_p);
+
+ *ppAd = pAd;
+ return 0; // probe ok
+
+
+ /* --------------------------- ERROR HANDLE --------------------------- */
+err_out_unmap:
+ RTMPFreeAdapter(pAd);
+ RT28XX_UNMAP();
+
+err_out_free_netdev:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ free_netdev(net_dev);
+#else
+ kfree(net_dev);
+#endif
+
+err_out:
+ RT28XX_PUT_DEVICE(dev_p);
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ return (LONG)NULL;
+#else
+ return -ENODEV; /* probe fail */
+#endif // LINUX_VERSION_CODE //
+} /* End of rt28xx_probe */
+
+
+/*
+========================================================================
+Routine Description:
+ The entry point for Linux kernel sent packet to our driver.
+
+Arguments:
+ sk_buff *skb the pointer refer to a sk_buffer.
+
+Return Value:
+ 0
+
+Note:
+ This function is the entry point of Tx Path for Os delivery packet to
+ our driver. You only can put OS-depened & STA/AP common handle procedures
+ in here.
+========================================================================
+*/
+int rt28xx_packet_xmit(struct sk_buff *skb)
+{
+ struct net_device *net_dev = skb->dev;
+ PRTMP_ADAPTER pAd = net_dev->ml_priv;
+ int status = 0;
+ PNDIS_PACKET pPacket = (PNDIS_PACKET) skb;
+
+ /* RT2870STA does this in RTMPSendPackets() */
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES);
+ return 0;
+ }
+#endif // RALINK_ATE //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ // Drop send request since we are in monitor mode
+ if (MONITOR_ON(pAd))
+ {
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ goto done;
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ // EapolStart size is 18
+ if (skb->len < 14)
+ {
+ //printk("bad packet size: %d\n", pkt->len);
+ hex_dump("bad packet", skb->data, skb->len);
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ goto done;
+ }
+
+ RTMP_SET_PACKET_5VT(pPacket, 0);
+#ifdef CONFIG_5VT_ENHANCE
+ if (*(int*)(skb->cb) == BRIDGE_TAG) {
+ RTMP_SET_PACKET_5VT(pPacket, 1);
+ }
+#endif
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+
+ STASendPackets((NDIS_HANDLE)pAd, (PPNDIS_PACKET) &pPacket, 1);
+ }
+
+#endif // CONFIG_STA_SUPPORT //
+
+ status = 0;
+done:
+
+ return status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+ Send a packet to WLAN.
+
+Arguments:
+ skb_p points to our adapter
+ dev_p which WLAN network interface
+
+Return Value:
+ 0: transmit successfully
+ otherwise: transmit fail
+
+Note:
+========================================================================
+*/
+INT rt28xx_send_packets(
+ IN struct sk_buff *skb_p,
+ IN struct net_device *net_dev)
+{
+ RTMP_ADAPTER *pAd = net_dev->ml_priv;
+ if (!(net_dev->flags & IFF_UP))
+ {
+ RELEASE_NDIS_PACKET(pAd, (PNDIS_PACKET)skb_p, NDIS_STATUS_FAILURE);
+ return 0;
+ }
+
+ NdisZeroMemory((PUCHAR)&skb_p->cb[CB_OFF], 15);
+ RTMP_SET_PACKET_NET_DEVICE_MBSSID(skb_p, MAIN_MBSSID);
+
+ return rt28xx_packet_xmit(skb_p);
+
+} /* End of MBSS_VirtualIF_PacketSend */
+
+
+
+
+#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1
+struct net_device *alloc_netdev(
+ int sizeof_priv,
+ const char *mask,
+ void (*setup)(struct net_device *))
+{
+ struct net_device *dev;
+ INT alloc_size;
+
+
+ /* ensure 32-byte alignment of the private area */
+ alloc_size = sizeof (*dev) + sizeof_priv + 31;
+
+ dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL);
+ if (dev == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,
+ ("alloc_netdev: Unable to allocate device memory.\n"));
+ return NULL;
+ }
+
+ memset(dev, 0, alloc_size);
+
+ if (sizeof_priv)
+ dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
+
+ setup(dev);
+ strcpy(dev->name, mask);
+
+ return dev;
+}
+#endif // LINUX_VERSION_CODE //
+
+
+void CfgInitHook(PRTMP_ADAPTER pAd)
+{
+ pAd->bBroadComHT = TRUE;
+} /* End of CfgInitHook */
+
+
+#if WIRELESS_EXT >= 12
+// This function will be called when query /proc
+struct iw_statistics *rt28xx_get_wireless_stats(
+ IN struct net_device *net_dev)
+{
+ PRTMP_ADAPTER pAd = net_dev->ml_priv;
+
+
+ DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_get_wireless_stats --->\n"));
+
+ pAd->iw_stats.status = 0; // Status - device dependent for now
+
+ // link quality
+ pAd->iw_stats.qual.qual = ((pAd->Mlme.ChannelQuality * 12)/10 + 10);
+ if(pAd->iw_stats.qual.qual > 100)
+ pAd->iw_stats.qual.qual = 100;
+
+#ifdef CONFIG_STA_SUPPORT
+ if (pAd->OpMode == OPMODE_STA)
+ pAd->iw_stats.qual.level = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
+#endif // CONFIG_STA_SUPPORT //
+
+ pAd->iw_stats.qual.noise = pAd->BbpWriteLatch[66]; // noise level (dBm)
+
+ pAd->iw_stats.qual.noise += 256 - 143;
+ pAd->iw_stats.qual.updated = 1; // Flags to know if updated
+#ifdef IW_QUAL_DBM
+ pAd->iw_stats.qual.updated |= IW_QUAL_DBM; // Level + Noise are dBm
+#endif // IW_QUAL_DBM //
+
+ pAd->iw_stats.discard.nwid = 0; // Rx : Wrong nwid/essid
+ pAd->iw_stats.miss.beacon = 0; // Missed beacons/superframe
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<--- rt28xx_get_wireless_stats\n"));
+ return &pAd->iw_stats;
+} /* End of rt28xx_get_wireless_stats */
+#endif // WIRELESS_EXT //
+
+
+
+void tbtt_tasklet(unsigned long data)
+{
+#define MAX_TX_IN_TBTT (16)
+
+}
+
+INT rt28xx_ioctl(
+ IN struct net_device *net_dev,
+ IN OUT struct ifreq *rq,
+ IN INT cmd)
+{
+ VIRTUAL_ADAPTER *pVirtualAd = NULL;
+ RTMP_ADAPTER *pAd = NULL;
+ INT ret = 0;
+
+ if (net_dev->priv_flags == INT_MAIN)
+ {
+ pAd = net_dev->ml_priv;
+ }
+ else
+ {
+ pVirtualAd = net_dev->ml_priv;
+ pAd = pVirtualAd->RtmpDev->ml_priv;
+ }
+
+ if (pAd == NULL)
+ {
+ /* if 1st open fail, pAd will be free;
+ So the net_dev->ml_priv will be NULL in 2rd open */
+ return -ENETDOWN;
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ ret = rt28xx_sta_ioctl(net_dev, rq, cmd);
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ return ret;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ return ethernet statistics counter
+
+ Arguments:
+ net_dev Pointer to net_device
+
+ Return Value:
+ net_device_stats*
+
+ Note:
+
+ ========================================================================
+*/
+struct net_device_stats *RT28xx_get_ether_stats(
+ IN struct net_device *net_dev)
+{
+ RTMP_ADAPTER *pAd = NULL;
+
+ if (net_dev)
+ pAd = net_dev->ml_priv;
+
+ if (pAd)
+ {
+
+ pAd->stats.rx_packets = pAd->WlanCounters.ReceivedFragmentCount.QuadPart;
+ pAd->stats.tx_packets = pAd->WlanCounters.TransmittedFragmentCount.QuadPart;
+
+ pAd->stats.rx_bytes = pAd->RalinkCounters.ReceivedByteCount;
+ pAd->stats.tx_bytes = pAd->RalinkCounters.TransmittedByteCount;
+
+ pAd->stats.rx_errors = pAd->Counters8023.RxErrors;
+ pAd->stats.tx_errors = pAd->Counters8023.TxErrors;
+
+ pAd->stats.rx_dropped = 0;
+ pAd->stats.tx_dropped = 0;
+
+ pAd->stats.multicast = pAd->WlanCounters.MulticastReceivedFrameCount.QuadPart; // multicast packets received
+ pAd->stats.collisions = pAd->Counters8023.OneCollision + pAd->Counters8023.MoreCollisions; // Collision packets
+
+ pAd->stats.rx_length_errors = 0;
+ pAd->stats.rx_over_errors = pAd->Counters8023.RxNoBuffer; // receiver ring buff overflow
+ pAd->stats.rx_crc_errors = 0;//pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error
+ pAd->stats.rx_frame_errors = pAd->Counters8023.RcvAlignmentErrors; // recv'd frame alignment error
+ pAd->stats.rx_fifo_errors = pAd->Counters8023.RxNoBuffer; // recv'r fifo overrun
+ pAd->stats.rx_missed_errors = 0; // receiver missed packet
+
+ // detailed tx_errors
+ pAd->stats.tx_aborted_errors = 0;
+ pAd->stats.tx_carrier_errors = 0;
+ pAd->stats.tx_fifo_errors = 0;
+ pAd->stats.tx_heartbeat_errors = 0;
+ pAd->stats.tx_window_errors = 0;
+
+ // for cslip etc
+ pAd->stats.rx_compressed = 0;
+ pAd->stats.tx_compressed = 0;
+
+ return &pAd->stats;
+ }
+ else
+ return NULL;
+}
+
diff --git a/drivers/staging/rt2860/rt_profile.c b/drivers/staging/rt2860/rt_profile.c
new file mode 100644
index 000000000000..326a3cb52b9c
--- /dev/null
+++ b/drivers/staging/rt2860/rt_profile.c
@@ -0,0 +1,1981 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+ */
+
+#include "rt_config.h"
+
+#ifdef DOT11_N_SUPPORT
+static void HTParametersHook(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR *pValueStr,
+ IN CHAR *pInput);
+#endif // DOT11_N_SUPPORT //
+
+#define ETH_MAC_ADDR_STR_LEN 17 // in format of xx:xx:xx:xx:xx:xx
+
+// We assume the s1 is a sting, s2 is a memory space with 6 bytes. and content of s1 will be changed.
+BOOLEAN rtstrmactohex(char *s1, char *s2)
+{
+ int i = 0;
+ char *ptokS = s1, *ptokE = s1;
+
+ if (strlen(s1) != ETH_MAC_ADDR_STR_LEN)
+ return FALSE;
+
+ while((*ptokS) != '\0')
+ {
+ if((ptokE = strchr(ptokS, ':')) != NULL)
+ *ptokE++ = '\0';
+ if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1))))
+ break; // fail
+ AtoH(ptokS, &s2[i++], 1);
+ ptokS = ptokE;
+ if (i == 6)
+ break; // parsing finished
+ }
+
+ return ( i == 6 ? TRUE : FALSE);
+
+}
+
+
+// we assume the s1 and s2 both are strings.
+BOOLEAN rtstrcasecmp(char *s1, char *s2)
+{
+ char *p1 = s1, *p2 = s2;
+
+ if (strlen(s1) != strlen(s2))
+ return FALSE;
+
+ while(*p1 != '\0')
+ {
+ if((*p1 != *p2) && ((*p1 ^ *p2) != 0x20))
+ return FALSE;
+ p1++;
+ p2++;
+ }
+
+ return TRUE;
+}
+
+// we assume the s1 (buffer) and s2 (key) both are strings.
+char * rtstrstruncasecmp(char * s1, char * s2)
+{
+ INT l1, l2, i;
+ char temp1, temp2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *) s1;
+
+ l1 = strlen(s1);
+
+ while (l1 >= l2)
+ {
+ l1--;
+
+ for(i=0; i<l2; i++)
+ {
+ temp1 = *(s1+i);
+ temp2 = *(s2+i);
+
+ if (('a' <= temp1) && (temp1 <= 'z'))
+ temp1 = 'A'+(temp1-'a');
+ if (('a' <= temp2) && (temp2 <= 'z'))
+ temp2 = 'A'+(temp2-'a');
+
+ if (temp1 != temp2)
+ break;
+ }
+
+ if (i == l2)
+ return (char *) s1;
+
+ s1++;
+ }
+
+ return NULL; // not found
+}
+
+//add by kathy
+
+ /**
+ * strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+char * rtstrstr(const char * s1,const char * s2)
+{
+ INT l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *) s1;
+
+ l1 = strlen(s1);
+
+ while (l1 >= l2)
+ {
+ l1--;
+ if (!memcmp(s1,s2,l2))
+ return (char *) s1;
+ s1++;
+ }
+
+ return NULL;
+}
+
+/**
+ * rstrtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ * * WARNING: strtok is deprecated, use strsep instead. However strsep is not compatible with old architecture.
+ */
+char * __rstrtok;
+char * rstrtok(char * s,const char * ct)
+{
+ char *sbegin, *send;
+
+ sbegin = s ? s : __rstrtok;
+ if (!sbegin)
+ {
+ return NULL;
+ }
+
+ sbegin += strspn(sbegin,ct);
+ if (*sbegin == '\0')
+ {
+ __rstrtok = NULL;
+ return( NULL );
+ }
+
+ send = strpbrk( sbegin, ct);
+ if (send && *send != '\0')
+ *send++ = '\0';
+
+ __rstrtok = send;
+
+ return (sbegin);
+}
+
+/**
+ * delimitcnt - return the count of a given delimiter in a given string.
+ * @s: The string to be searched.
+ * @ct: The delimiter to search for.
+ * Notice : We suppose the delimiter is a single-char string(for example : ";").
+ */
+INT delimitcnt(char * s,const char * ct)
+{
+ INT count = 0;
+ /* point to the beginning of the line */
+ const char *token = s;
+
+ for ( ;; )
+ {
+ token = strpbrk(token, ct); /* search for delimiters */
+
+ if ( token == NULL )
+ {
+ /* advanced to the terminating null character */
+ break;
+ }
+ /* skip the delimiter */
+ ++token;
+
+ /*
+ * Print the found text: use len with %.*s to specify field width.
+ */
+
+ /* accumulate delimiter count */
+ ++count;
+ }
+ return count;
+}
+
+/*
+ * converts the Internet host address from the standard numbers-and-dots notation
+ * into binary data.
+ * returns nonzero if the address is valid, zero if not.
+ */
+int rtinet_aton(const char *cp, unsigned int *addr)
+{
+ unsigned int val;
+ int base, n;
+ char c;
+ unsigned int parts[4];
+ unsigned int *pp = parts;
+
+ for (;;)
+ {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, other=decimal.
+ */
+ val = 0;
+ base = 10;
+ if (*cp == '0')
+ {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp) != '\0')
+ {
+ if (isdigit((unsigned char) c))
+ {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit((unsigned char) c))
+ {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.')
+ {
+ /*
+ * Internet format: a.b.c.d a.b.c (with c treated as 16-bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xff)
+ return 0;
+ *pp++ = val, cp++;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Check for trailing junk.
+ */
+ while (*cp)
+ if (!isspace((unsigned char) *cp++))
+ return 0;
+
+ /*
+ * Concoct the address according to the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n)
+ {
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return 0;
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+
+ *addr = htonl(val);
+ return 1;
+
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Find key section for Get key parameter.
+
+ Arguments:
+ buffer Pointer to the buffer to start find the key section
+ section the key of the secion to be find
+
+ Return Value:
+ NULL Fail
+ Others Success
+ ========================================================================
+*/
+PUCHAR RTMPFindSection(
+ IN PCHAR buffer)
+{
+ CHAR temp_buf[32];
+ PUCHAR ptr;
+
+ strcpy(temp_buf, "Default");
+
+ if((ptr = rtstrstr(buffer, temp_buf)) != NULL)
+ return (ptr+strlen("\n"));
+ else
+ return NULL;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get key parameter.
+
+ Arguments:
+ key Pointer to key string
+ dest Pointer to destination
+ destsize The datasize of the destination
+ buffer Pointer to the buffer to start find the key
+
+ Return Value:
+ TRUE Success
+ FALSE Fail
+
+ Note:
+ This routine get the value with the matched key (case case-sensitive)
+ ========================================================================
+*/
+INT RTMPGetKeyParameter(
+ IN PCHAR key,
+ OUT PCHAR dest,
+ IN INT destsize,
+ IN PCHAR buffer)
+{
+ UCHAR *temp_buf1 = NULL;
+ UCHAR *temp_buf2 = NULL;
+ CHAR *start_ptr;
+ CHAR *end_ptr;
+ CHAR *ptr;
+ CHAR *offset = 0;
+ INT len;
+
+ //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE);
+
+ if(temp_buf1 == NULL)
+ return (FALSE);
+
+ //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE);
+ if(temp_buf2 == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ return (FALSE);
+ }
+
+ //find section
+ if((offset = RTMPFindSection(buffer)) == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ strcpy(temp_buf1, "\n");
+ strcat(temp_buf1, key);
+ strcat(temp_buf1, "=");
+
+ //search key
+ if((start_ptr=rtstrstr(offset, temp_buf1))==NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ start_ptr+=strlen("\n");
+ if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL)
+ end_ptr=start_ptr+strlen(start_ptr);
+
+ if (end_ptr<start_ptr)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+ temp_buf2[end_ptr-start_ptr]='\0';
+ len = strlen(temp_buf2);
+ strcpy(temp_buf1, temp_buf2);
+ if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ strcpy(temp_buf2, start_ptr+1);
+ ptr = temp_buf2;
+ //trim space or tab
+ while(*ptr != 0x00)
+ {
+ if( (*ptr == ' ') || (*ptr == '\t') )
+ ptr++;
+ else
+ break;
+ }
+
+ len = strlen(ptr);
+ memset(dest, 0x00, destsize);
+ strncpy(dest, ptr, len >= destsize ? destsize: len);
+
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return TRUE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get key parameter.
+
+ Arguments:
+ key Pointer to key string
+ dest Pointer to destination
+ destsize The datasize of the destination
+ buffer Pointer to the buffer to start find the key
+
+ Return Value:
+ TRUE Success
+ FALSE Fail
+
+ Note:
+ This routine get the value with the matched key (case case-sensitive).
+ It is called for parsing SSID and any key string.
+ ========================================================================
+*/
+INT RTMPGetCriticalParameter(
+ IN PCHAR key,
+ OUT PCHAR dest,
+ IN INT destsize,
+ IN PCHAR buffer)
+{
+ UCHAR *temp_buf1 = NULL;
+ UCHAR *temp_buf2 = NULL;
+ CHAR *start_ptr;
+ CHAR *end_ptr;
+ CHAR *ptr;
+ CHAR *offset = 0;
+ INT len;
+
+ //temp_buf1 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE);
+
+ if(temp_buf1 == NULL)
+ return (FALSE);
+
+ //temp_buf2 = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE);
+ if(temp_buf2 == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ return (FALSE);
+ }
+
+ //find section
+ if((offset = RTMPFindSection(buffer)) == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ strcpy(temp_buf1, "\n");
+ strcat(temp_buf1, key);
+ strcat(temp_buf1, "=");
+
+ //search key
+ if((start_ptr=rtstrstr(offset, temp_buf1))==NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ start_ptr+=strlen("\n");
+ if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL)
+ end_ptr=start_ptr+strlen(start_ptr);
+
+ if (end_ptr<start_ptr)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+ temp_buf2[end_ptr-start_ptr]='\0';
+ len = strlen(temp_buf2);
+ strcpy(temp_buf1, temp_buf2);
+ if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ strcpy(temp_buf2, start_ptr+1);
+ ptr = temp_buf2;
+
+ //trim tab
+ /* We cannot trim space(' ') for SSID and key string. */
+ while(*ptr != 0x00)
+ {
+ //if( (*ptr == ' ') || (*ptr == '\t') )
+ if( (*ptr == '\t') )
+ ptr++;
+ else
+ break;
+ }
+
+ len = strlen(ptr);
+ memset(dest, 0x00, destsize);
+ strncpy(dest, ptr, len >= destsize ? destsize: len);
+
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return TRUE;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Get multiple key parameter.
+
+ Arguments:
+ key Pointer to key string
+ dest Pointer to destination
+ destsize The datasize of the destination
+ buffer Pointer to the buffer to start find the key
+
+ Return Value:
+ TRUE Success
+ FALSE Fail
+
+ Note:
+ This routine get the value with the matched key (case case-sensitive)
+ ========================================================================
+*/
+INT RTMPGetKeyParameterWithOffset(
+ IN PCHAR key,
+ OUT PCHAR dest,
+ OUT USHORT *end_offset,
+ IN INT destsize,
+ IN PCHAR buffer,
+ IN BOOLEAN bTrimSpace)
+{
+ UCHAR *temp_buf1 = NULL;
+ UCHAR *temp_buf2 = NULL;
+ CHAR *start_ptr;
+ CHAR *end_ptr;
+ CHAR *ptr;
+ CHAR *offset = 0;
+ INT len;
+
+ if (*end_offset >= MAX_INI_BUFFER_SIZE)
+ return (FALSE);
+
+ os_alloc_mem(NULL, &temp_buf1, MAX_PARAM_BUFFER_SIZE);
+
+ if(temp_buf1 == NULL)
+ return (FALSE);
+
+ os_alloc_mem(NULL, &temp_buf2, MAX_PARAM_BUFFER_SIZE);
+ if(temp_buf2 == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ return (FALSE);
+ }
+
+ //find section
+ if(*end_offset == 0)
+ {
+ if ((offset = RTMPFindSection(buffer)) == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+ }
+ else
+ offset = buffer + (*end_offset);
+
+ strcpy(temp_buf1, "\n");
+ strcat(temp_buf1, key);
+ strcat(temp_buf1, "=");
+
+ //search key
+ if((start_ptr=rtstrstr(offset, temp_buf1))==NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ start_ptr+=strlen("\n");
+ if((end_ptr=rtstrstr(start_ptr, "\n"))==NULL)
+ end_ptr=start_ptr+strlen(start_ptr);
+
+ if (end_ptr<start_ptr)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ *end_offset = end_ptr - buffer;
+
+ NdisMoveMemory(temp_buf2, start_ptr, end_ptr-start_ptr);
+ temp_buf2[end_ptr-start_ptr]='\0';
+ len = strlen(temp_buf2);
+ strcpy(temp_buf1, temp_buf2);
+ if((start_ptr=rtstrstr(temp_buf1, "=")) == NULL)
+ {
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return (FALSE);
+ }
+
+ strcpy(temp_buf2, start_ptr+1);
+ ptr = temp_buf2;
+ //trim space or tab
+ while(*ptr != 0x00)
+ {
+ if((bTrimSpace && (*ptr == ' ')) || (*ptr == '\t') )
+ ptr++;
+ else
+ break;
+ }
+
+ len = strlen(ptr);
+ memset(dest, 0x00, destsize);
+ strncpy(dest, ptr, len >= destsize ? destsize: len);
+
+ os_free_mem(NULL, temp_buf1);
+ os_free_mem(NULL, temp_buf2);
+ return TRUE;
+}
+
+
+static int rtmp_parse_key_buffer_from_file(IN PRTMP_ADAPTER pAd,IN char *buffer,IN ULONG KeyType,IN INT BSSIdx,IN INT KeyIdx)
+{
+ PUCHAR keybuff;
+ INT i = BSSIdx, idx = KeyIdx;
+ ULONG KeyLen;
+ UCHAR CipherAlg = CIPHER_WEP64;
+
+ keybuff = buffer;
+ KeyLen = strlen(keybuff);
+
+ if (KeyType == 1)
+ {//Ascii
+ if( (KeyLen == 5) || (KeyLen == 13))
+ {
+ pAd->SharedKey[i][idx].KeyLen = KeyLen;
+ NdisMoveMemory(pAd->SharedKey[i][idx].Key, keybuff, KeyLen);
+ if (KeyLen == 5)
+ CipherAlg = CIPHER_WEP64;
+ else
+ CipherAlg = CIPHER_WEP128;
+ pAd->SharedKey[i][idx].CipherAlg = CipherAlg;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii"));
+ return 1;
+ }
+ else
+ {//Invalid key length
+ DBGPRINT(RT_DEBUG_ERROR, ("Key%dStr is Invalid key length! KeyLen = %ld!\n", idx+1, KeyLen));
+ return 0;
+ }
+ }
+ else
+ {//Hex type
+ if( (KeyLen == 10) || (KeyLen == 26))
+ {
+ pAd->SharedKey[i][idx].KeyLen = KeyLen / 2;
+ AtoH(keybuff, pAd->SharedKey[i][idx].Key, KeyLen / 2);
+ if (KeyLen == 10)
+ CipherAlg = CIPHER_WEP64;
+ else
+ CipherAlg = CIPHER_WEP128;
+ pAd->SharedKey[i][idx].CipherAlg = CipherAlg;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Key%dStr=%s and type=%s\n", i, idx+1, keybuff, (KeyType == 0) ? "Hex":"Ascii"));
+ return 1;
+ }
+ else
+ {//Invalid key length
+ DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) Key%dStr is Invalid key length! KeyLen = %ld!\n", i, idx+1, KeyLen));
+ return 0;
+ }
+ }
+}
+static void rtmp_read_key_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer)
+{
+ char tok_str[16];
+ PUCHAR macptr;
+ INT i = 0, idx;
+ ULONG KeyType[MAX_MBSSID_NUM];
+ ULONG KeyIdx;
+
+ NdisZeroMemory(KeyType, MAX_MBSSID_NUM);
+
+ //DefaultKeyID
+ if(RTMPGetKeyParameter("DefaultKeyID", tmpbuf, 25, buffer))
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ KeyIdx = simple_strtol(tmpbuf, 0, 10);
+ if((KeyIdx >= 1 ) && (KeyIdx <= 4))
+ pAd->StaCfg.DefaultKeyId = (UCHAR) (KeyIdx - 1);
+ else
+ pAd->StaCfg.DefaultKeyId = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("DefaultKeyID(0~3)=%d\n", pAd->StaCfg.DefaultKeyId));
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+
+ for (idx = 0; idx < 4; idx++)
+ {
+ sprintf(tok_str, "Key%dType", idx + 1);
+ //Key1Type
+ if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ KeyType[i] = simple_strtol(macptr, 0, 10);
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ sprintf(tok_str, "Key%dStr", idx + 1);
+ if (RTMPGetCriticalParameter(tok_str, tmpbuf, 128, buffer))
+ {
+ rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx);
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+ }
+}
+
+
+#ifdef CONFIG_STA_SUPPORT
+static void rtmp_read_sta_wmm_parms_from_file(IN PRTMP_ADAPTER pAd, char *tmpbuf, char *buffer)
+{
+ PUCHAR macptr;
+ INT i=0;
+ BOOLEAN bWmmEnable = FALSE;
+
+ //WmmCapable
+ if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable
+ {
+ pAd->CommonCfg.bWmmCapable = TRUE;
+ bWmmEnable = TRUE;
+ }
+ else //Disable
+ {
+ pAd->CommonCfg.bWmmCapable = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WmmCapable=%d\n", pAd->CommonCfg.bWmmCapable));
+ }
+
+#ifdef QOS_DLS_SUPPORT
+ //DLSCapable
+ if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable
+ {
+ pAd->CommonCfg.bDLSCapable = TRUE;
+ }
+ else //Disable
+ {
+ pAd->CommonCfg.bDLSCapable = FALSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("bDLSCapable=%d\n", pAd->CommonCfg.bDLSCapable));
+ }
+#endif // QOS_DLS_SUPPORT //
+
+ //AckPolicy for AC_BK, AC_BE, AC_VI, AC_VO
+ if(RTMPGetKeyParameter("AckPolicy", tmpbuf, 32, buffer))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ pAd->CommonCfg.AckPolicy[i] = (UCHAR)simple_strtol(macptr, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AckPolicy[%d]=%d\n", i, pAd->CommonCfg.AckPolicy[i]));
+ }
+ }
+
+ if (bWmmEnable)
+ {
+ //APSDCapable
+ if(RTMPGetKeyParameter("APSDCapable", tmpbuf, 10, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable
+ pAd->CommonCfg.bAPSDCapable = TRUE;
+ else
+ pAd->CommonCfg.bAPSDCapable = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("APSDCapable=%d\n", pAd->CommonCfg.bAPSDCapable));
+ }
+
+ //APSDAC for AC_BE, AC_BK, AC_VI, AC_VO
+ if(RTMPGetKeyParameter("APSDAC", tmpbuf, 32, buffer))
+ {
+ BOOLEAN apsd_ac[4];
+
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ apsd_ac[i] = (BOOLEAN)simple_strtol(macptr, 0, 10);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("APSDAC%d %d\n", i, apsd_ac[i]));
+ }
+
+ pAd->CommonCfg.bAPSDAC_BE = apsd_ac[0];
+ pAd->CommonCfg.bAPSDAC_BK = apsd_ac[1];
+ pAd->CommonCfg.bAPSDAC_VI = apsd_ac[2];
+ pAd->CommonCfg.bAPSDAC_VO = apsd_ac[3];
+ }
+ }
+
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+NDIS_STATUS RTMPReadParametersHook(
+ IN PRTMP_ADAPTER pAd)
+{
+ PUCHAR src = NULL;
+ struct file *srcf;
+ INT retval, orgfsuid, orgfsgid;
+ mm_segment_t orgfs;
+ CHAR *buffer;
+ CHAR *tmpbuf;
+ ULONG RtsThresh;
+ ULONG FragThresh;
+#ifdef CONFIG_STA_SUPPORT
+ UCHAR keyMaterial[40];
+#endif // CONFIG_STA_SUPPORT //
+
+
+ PUCHAR macptr;
+ INT i = 0;
+
+ buffer = kmalloc(MAX_INI_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ if(buffer == NULL)
+ return NDIS_STATUS_FAILURE;
+
+ tmpbuf = kmalloc(MAX_PARAM_BUFFER_SIZE, MEM_ALLOC_FLAG);
+ if(tmpbuf == NULL)
+ {
+ kfree(buffer);
+ return NDIS_STATUS_FAILURE;
+ }
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ src = STA_PROFILE_PATH;
+#endif // CONFIG_STA_SUPPORT //
+#ifdef MULTIPLE_CARD_SUPPORT
+ src = pAd->MC_FileName;
+#endif // MULTIPLE_CARD_SUPPORT //
+
+ // Save uid and gid used for filesystem access.
+ // Set user and group to 0 (root)
+ orgfsuid = current_fsuid();
+ orgfsgid = current_fsgid();
+ /* Hm, can't really do this nicely anymore, so rely on these files
+ * being set to the proper permission to read them... */
+ /* current->cred->fsuid = current->cred->fsgid = 0; */
+ orgfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ if (src && *src)
+ {
+ srcf = filp_open(src, O_RDONLY, 0);
+ if (IS_ERR(srcf))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("--> Error %ld opening %s\n", -PTR_ERR(srcf),src));
+ }
+ else
+ {
+ // The object must have a read method
+ if (srcf->f_op && srcf->f_op->read)
+ {
+ memset(buffer, 0x00, MAX_INI_BUFFER_SIZE);
+ retval=srcf->f_op->read(srcf, buffer, MAX_INI_BUFFER_SIZE, &srcf->f_pos);
+ if (retval < 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval));
+ }
+ else
+ {
+ // set file parameter to portcfg
+ //CountryRegion
+ if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, buffer))
+ {
+ pAd->CommonCfg.CountryRegion = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion));
+ }
+ //CountryRegionABand
+ if(RTMPGetKeyParameter("CountryRegionABand", tmpbuf, 25, buffer))
+ {
+ pAd->CommonCfg.CountryRegionForABand= (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryRegionABand=%d\n", pAd->CommonCfg.CountryRegionForABand));
+ }
+ //CountryCode
+ if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, buffer))
+ {
+ NdisMoveMemory(pAd->CommonCfg.CountryCode, tmpbuf , 2);
+#ifdef CONFIG_STA_SUPPORT
+#ifdef EXT_BUILD_CHANNEL_LIST
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ NdisMoveMemory(pAd->StaCfg.StaOriCountryCode, tmpbuf , 2);
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+ if (strlen(pAd->CommonCfg.CountryCode) != 0)
+ {
+ pAd->CommonCfg.bCountryFlag = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("CountryCode=%s\n", pAd->CommonCfg.CountryCode));
+ }
+ //ChannelGeography
+ if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, buffer))
+ {
+ UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ if (Geography <= BOTH)
+ {
+ pAd->CommonCfg.Geography = Geography;
+ pAd->CommonCfg.CountryCode[2] =
+ (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O');
+#ifdef CONFIG_STA_SUPPORT
+#ifdef EXT_BUILD_CHANNEL_LIST
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ pAd->StaCfg.StaOriGeography = pAd->CommonCfg.Geography;
+#endif // EXT_BUILD_CHANNEL_LIST //
+#endif // CONFIG_STA_SUPPORT //
+ DBGPRINT(RT_DEBUG_TRACE, ("ChannelGeography=%d\n", pAd->CommonCfg.Geography));
+ }
+ }
+ else
+ {
+ pAd->CommonCfg.Geography = BOTH;
+ pAd->CommonCfg.CountryCode[2] = ' ';
+ }
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ //SSID
+ if (RTMPGetCriticalParameter("SSID", tmpbuf, 256, buffer))
+ {
+ if (strlen(tmpbuf) <= 32)
+ {
+ pAd->CommonCfg.SsidLen = (UCHAR) strlen(tmpbuf);
+ NdisZeroMemory(pAd->CommonCfg.Ssid, NDIS_802_11_LENGTH_SSID);
+ NdisMoveMemory(pAd->CommonCfg.Ssid, tmpbuf, pAd->CommonCfg.SsidLen);
+ pAd->MlmeAux.AutoReconnectSsidLen = pAd->CommonCfg.SsidLen;
+ NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, NDIS_802_11_LENGTH_SSID);
+ NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, tmpbuf, pAd->MlmeAux.AutoReconnectSsidLen);
+ pAd->MlmeAux.SsidLen = pAd->CommonCfg.SsidLen;
+ NdisZeroMemory(pAd->MlmeAux.Ssid, NDIS_802_11_LENGTH_SSID);
+ NdisMoveMemory(pAd->MlmeAux.Ssid, tmpbuf, pAd->MlmeAux.SsidLen);
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::(SSID=%s)\n", __func__, tmpbuf));
+ }
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ //NetworkType
+ if (RTMPGetKeyParameter("NetworkType", tmpbuf, 25, buffer))
+ {
+ pAd->bConfigChanged = TRUE;
+ if (strcmp(tmpbuf, "Adhoc") == 0)
+ pAd->StaCfg.BssType = BSS_ADHOC;
+ else //Default Infrastructure mode
+ pAd->StaCfg.BssType = BSS_INFRA;
+ // Reset Ralink supplicant to not use, it will be set to start when UI set PMK key
+ pAd->StaCfg.WpaState = SS_NOTUSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::(NetworkType=%d)\n", __func__, pAd->StaCfg.BssType));
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+ //Channel
+ if(RTMPGetKeyParameter("Channel", tmpbuf, 10, buffer))
+ {
+ pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel));
+ }
+ //WirelessMode
+ if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 10, buffer))
+ {
+ int value = 0, maxPhyMode = PHY_11G;
+
+#ifdef DOT11_N_SUPPORT
+ maxPhyMode = PHY_11N_5G;
+#endif // DOT11_N_SUPPORT //
+
+ value = simple_strtol(tmpbuf, 0, 10);
+
+ if (value <= maxPhyMode)
+ {
+ pAd->CommonCfg.PhyMode = value;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode));
+ }
+ //BasicRate
+ if(RTMPGetKeyParameter("BasicRate", tmpbuf, 10, buffer))
+ {
+ pAd->CommonCfg.BasicRateBitmap = (ULONG) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("BasicRate=%ld\n", pAd->CommonCfg.BasicRateBitmap));
+ }
+ //BeaconPeriod
+ if(RTMPGetKeyParameter("BeaconPeriod", tmpbuf, 10, buffer))
+ {
+ pAd->CommonCfg.BeaconPeriod = (USHORT) simple_strtol(tmpbuf, 0, 10);
+ DBGPRINT(RT_DEBUG_TRACE, ("BeaconPeriod=%d\n", pAd->CommonCfg.BeaconPeriod));
+ }
+ //TxPower
+ if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, buffer))
+ {
+ pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10);
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ pAd->CommonCfg.TxPowerDefault = pAd->CommonCfg.TxPowerPercentage;
+#endif // CONFIG_STA_SUPPORT //
+ DBGPRINT(RT_DEBUG_TRACE, ("TxPower=%ld\n", pAd->CommonCfg.TxPowerPercentage));
+ }
+ //BGProtection
+ if(RTMPGetKeyParameter("BGProtection", tmpbuf, 10, buffer))
+ {
+ switch (simple_strtol(tmpbuf, 0, 10))
+ {
+ case 1: //Always On
+ pAd->CommonCfg.UseBGProtection = 1;
+ break;
+ case 2: //Always OFF
+ pAd->CommonCfg.UseBGProtection = 2;
+ break;
+ case 0: //AUTO
+ default:
+ pAd->CommonCfg.UseBGProtection = 0;
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("BGProtection=%ld\n", pAd->CommonCfg.UseBGProtection));
+ }
+ //OLBCDetection
+ if(RTMPGetKeyParameter("DisableOLBC", tmpbuf, 10, buffer))
+ {
+ switch (simple_strtol(tmpbuf, 0, 10))
+ {
+ case 1: //disable OLBC Detection
+ pAd->CommonCfg.DisableOLBCDetect = 1;
+ break;
+ case 0: //enable OLBC Detection
+ pAd->CommonCfg.DisableOLBCDetect = 0;
+ break;
+ default:
+ pAd->CommonCfg.DisableOLBCDetect= 0;
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("OLBCDetection=%ld\n", pAd->CommonCfg.DisableOLBCDetect));
+ }
+ //TxPreamble
+ if(RTMPGetKeyParameter("TxPreamble", tmpbuf, 10, buffer))
+ {
+ switch (simple_strtol(tmpbuf, 0, 10))
+ {
+ case Rt802_11PreambleShort:
+ pAd->CommonCfg.TxPreamble = Rt802_11PreambleShort;
+ break;
+ case Rt802_11PreambleLong:
+ default:
+ pAd->CommonCfg.TxPreamble = Rt802_11PreambleLong;
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("TxPreamble=%ld\n", pAd->CommonCfg.TxPreamble));
+ }
+ //RTSThreshold
+ if(RTMPGetKeyParameter("RTSThreshold", tmpbuf, 10, buffer))
+ {
+ RtsThresh = simple_strtol(tmpbuf, 0, 10);
+ if( (RtsThresh >= 1) && (RtsThresh <= MAX_RTS_THRESHOLD) )
+ pAd->CommonCfg.RtsThreshold = (USHORT)RtsThresh;
+ else
+ pAd->CommonCfg.RtsThreshold = MAX_RTS_THRESHOLD;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTSThreshold=%d\n", pAd->CommonCfg.RtsThreshold));
+ }
+ //FragThreshold
+ if(RTMPGetKeyParameter("FragThreshold", tmpbuf, 10, buffer))
+ {
+ FragThresh = simple_strtol(tmpbuf, 0, 10);
+ pAd->CommonCfg.bUseZeroToDisableFragment = FALSE;
+
+ if (FragThresh > MAX_FRAG_THRESHOLD || FragThresh < MIN_FRAG_THRESHOLD)
+ { //illegal FragThresh so we set it to default
+ pAd->CommonCfg.FragmentThreshold = MAX_FRAG_THRESHOLD;
+ pAd->CommonCfg.bUseZeroToDisableFragment = TRUE;
+ }
+ else if (FragThresh % 2 == 1)
+ {
+ // The length of each fragment shall always be an even number of octets, except for the last fragment
+ // of an MSDU or MMPDU, which may be either an even or an odd number of octets.
+ pAd->CommonCfg.FragmentThreshold = (USHORT)(FragThresh - 1);
+ }
+ else
+ {
+ pAd->CommonCfg.FragmentThreshold = (USHORT)FragThresh;
+ }
+ //pAd->CommonCfg.AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
+ DBGPRINT(RT_DEBUG_TRACE, ("FragThreshold=%d\n", pAd->CommonCfg.FragmentThreshold));
+ }
+ //TxBurst
+ if(RTMPGetKeyParameter("TxBurst", tmpbuf, 10, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable
+ pAd->CommonCfg.bEnableTxBurst = TRUE;
+ else //Disable
+ pAd->CommonCfg.bEnableTxBurst = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("TxBurst=%d\n", pAd->CommonCfg.bEnableTxBurst));
+ }
+
+#ifdef AGGREGATION_SUPPORT
+ //PktAggregate
+ if(RTMPGetKeyParameter("PktAggregate", tmpbuf, 10, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable
+ pAd->CommonCfg.bAggregationCapable = TRUE;
+ else //Disable
+ pAd->CommonCfg.bAggregationCapable = FALSE;
+#ifdef PIGGYBACK_SUPPORT
+ pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable;
+#endif // PIGGYBACK_SUPPORT //
+ DBGPRINT(RT_DEBUG_TRACE, ("PktAggregate=%d\n", pAd->CommonCfg.bAggregationCapable));
+ }
+#else
+ pAd->CommonCfg.bAggregationCapable = FALSE;
+ pAd->CommonCfg.bPiggyBackCapable = FALSE;
+#endif // AGGREGATION_SUPPORT //
+
+ // WmmCapable
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ rtmp_read_sta_wmm_parms_from_file(pAd, tmpbuf, buffer);
+#endif // CONFIG_STA_SUPPORT //
+
+ //ShortSlot
+ if(RTMPGetKeyParameter("ShortSlot", tmpbuf, 10, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0) //Enable
+ pAd->CommonCfg.bUseShortSlotTime = TRUE;
+ else //Disable
+ pAd->CommonCfg.bUseShortSlotTime = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ShortSlot=%d\n", pAd->CommonCfg.bUseShortSlotTime));
+ }
+ //IEEE80211H
+ if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, buffer))
+ {
+ for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++)
+ {
+ if(simple_strtol(macptr, 0, 10) != 0) //Enable
+ pAd->CommonCfg.bIEEE80211H = TRUE;
+ else //Disable
+ pAd->CommonCfg.bIEEE80211H = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H));
+ }
+ }
+ //CSPeriod
+ if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0)
+ pAd->CommonCfg.RadarDetect.CSPeriod = simple_strtol(tmpbuf, 0, 10);
+ else
+ pAd->CommonCfg.RadarDetect.CSPeriod = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->CommonCfg.RadarDetect.CSPeriod));
+ }
+
+ //RDRegion
+ if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, buffer))
+ {
+ if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0))
+ {
+ pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W53;
+ pAd->CommonCfg.RadarDetect.DfsSessionTime = 15;
+ }
+ else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0))
+ {
+ pAd->CommonCfg.RadarDetect.RDDurRegion = JAP_W56;
+ pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+ }
+ else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0))
+ {
+ pAd->CommonCfg.RadarDetect.RDDurRegion = JAP;
+ pAd->CommonCfg.RadarDetect.DfsSessionTime = 5;
+ }
+ else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0))
+ {
+ pAd->CommonCfg.RadarDetect.RDDurRegion = FCC;
+ pAd->CommonCfg.RadarDetect.DfsSessionTime = 5;
+ }
+ else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0))
+ {
+ pAd->CommonCfg.RadarDetect.RDDurRegion = CE;
+ pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+ }
+ else
+ {
+ pAd->CommonCfg.RadarDetect.RDDurRegion = CE;
+ pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RadarDetect.RDDurRegion));
+ }
+ else
+ {
+ pAd->CommonCfg.RadarDetect.RDDurRegion = CE;
+ pAd->CommonCfg.RadarDetect.DfsSessionTime = 13;
+ }
+
+ //WirelessEvent
+ if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, buffer))
+ {
+#if WIRELESS_EXT >= 15
+ if(simple_strtol(tmpbuf, 0, 10) != 0)
+ pAd->CommonCfg.bWirelessEvent = simple_strtol(tmpbuf, 0, 10);
+ else
+ pAd->CommonCfg.bWirelessEvent = 0; // disable
+#else
+ pAd->CommonCfg.bWirelessEvent = 0; // disable
+#endif
+ DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent));
+ }
+ if(RTMPGetKeyParameter("WiFiTest", tmpbuf, 10, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) != 0)
+ pAd->CommonCfg.bWiFiTest= simple_strtol(tmpbuf, 0, 10);
+ else
+ pAd->CommonCfg.bWiFiTest = 0; // disable
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WiFiTest=%d\n", pAd->CommonCfg.bWiFiTest));
+ }
+ //AuthMode
+ if(RTMPGetKeyParameter("AuthMode", tmpbuf, 128, buffer))
+ {
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if ((strcmp(tmpbuf, "WEPAUTO") == 0) || (strcmp(tmpbuf, "wepauto") == 0))
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeAutoSwitch;
+ else if ((strcmp(tmpbuf, "SHARED") == 0) || (strcmp(tmpbuf, "shared") == 0))
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeShared;
+ else if ((strcmp(tmpbuf, "WPAPSK") == 0) || (strcmp(tmpbuf, "wpapsk") == 0))
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPAPSK;
+ else if ((strcmp(tmpbuf, "WPANONE") == 0) || (strcmp(tmpbuf, "wpanone") == 0))
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPANone;
+ else if ((strcmp(tmpbuf, "WPA2PSK") == 0) || (strcmp(tmpbuf, "wpa2psk") == 0))
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2PSK;
+#ifdef WPA_SUPPLICANT_SUPPORT
+ else if ((strcmp(tmpbuf, "WPA") == 0) || (strcmp(tmpbuf, "wpa") == 0))
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA;
+ else if ((strcmp(tmpbuf, "WPA2") == 0) || (strcmp(tmpbuf, "wpa2") == 0))
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeWPA2;
+#endif // WPA_SUPPLICANT_SUPPORT //
+ else
+ pAd->StaCfg.AuthMode = Ndis802_11AuthModeOpen;
+
+ pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __func__, pAd->StaCfg.WepStatus));
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+ //EncrypType
+ if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, buffer))
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if ((strcmp(tmpbuf, "WEP") == 0) || (strcmp(tmpbuf, "wep") == 0))
+ pAd->StaCfg.WepStatus = Ndis802_11WEPEnabled;
+ else if ((strcmp(tmpbuf, "TKIP") == 0) || (strcmp(tmpbuf, "tkip") == 0))
+ pAd->StaCfg.WepStatus = Ndis802_11Encryption2Enabled;
+ else if ((strcmp(tmpbuf, "AES") == 0) || (strcmp(tmpbuf, "aes") == 0))
+ pAd->StaCfg.WepStatus = Ndis802_11Encryption3Enabled;
+ else
+ pAd->StaCfg.WepStatus = Ndis802_11WEPDisabled;
+
+ // Update all wepstatus related
+ pAd->StaCfg.PairCipher = pAd->StaCfg.WepStatus;
+ pAd->StaCfg.GroupCipher = pAd->StaCfg.WepStatus;
+ pAd->StaCfg.OrigWepStatus = pAd->StaCfg.WepStatus;
+ pAd->StaCfg.bMixCipher = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::(EncrypType=%d)\n", __func__, pAd->StaCfg.WepStatus));
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ if(RTMPGetCriticalParameter("WPAPSK", tmpbuf, 512, buffer))
+ {
+ int err=0;
+
+ tmpbuf[strlen(tmpbuf)] = '\0'; // make STA can process .$^& for WPAPSK input
+
+ if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPAPSK) &&
+ (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) &&
+ (pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPANone)
+ )
+ {
+ err = 1;
+ }
+ else if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) < 64))
+ {
+ PasswordHash((char *)tmpbuf, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, keyMaterial);
+ NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32);
+
+ }
+ else if (strlen(tmpbuf) == 64)
+ {
+ AtoH(tmpbuf, keyMaterial, 32);
+ NdisMoveMemory(pAd->StaCfg.PMK, keyMaterial, 32);
+ }
+ else
+ {
+ err = 1;
+ DBGPRINT(RT_DEBUG_ERROR, ("%s::(WPAPSK key-string required 8 ~ 64 characters!)\n", __func__));
+ }
+
+ if (err == 0)
+ {
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ // Start STA supplicant state machine
+ pAd->StaCfg.WpaState = SS_START;
+ }
+ else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+ {
+ pAd->StaCfg.WpaState = SS_NOTUSE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("%s::(WPAPSK=%s)\n", __func__, tmpbuf));
+ }
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ //DefaultKeyID, KeyType, KeyStr
+ rtmp_read_key_parms_from_file(pAd, tmpbuf, buffer);
+
+#ifdef DOT11_N_SUPPORT
+ HTParametersHook(pAd, tmpbuf, buffer);
+#endif // DOT11_N_SUPPORT //
+
+
+#ifdef CARRIER_DETECTION_SUPPORT
+ //CarrierDetect
+ if(RTMPGetKeyParameter("CarrierDetect", tmpbuf, 128, buffer))
+ {
+ if ((strncmp(tmpbuf, "0", 1) == 0))
+ pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+ else if ((strncmp(tmpbuf, "1", 1) == 0))
+ pAd->CommonCfg.CarrierDetect.Enable = TRUE;
+ else
+ pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetect.Enable=%d\n", pAd->CommonCfg.CarrierDetect.Enable));
+ }
+ else
+ pAd->CommonCfg.CarrierDetect.Enable = FALSE;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ //PSMode
+ if (RTMPGetKeyParameter("PSMode", tmpbuf, 10, buffer))
+ {
+ if (pAd->StaCfg.BssType == BSS_INFRA)
+ {
+ if ((strcmp(tmpbuf, "MAX_PSP") == 0) || (strcmp(tmpbuf, "max_psp") == 0))
+ {
+ // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+ // to exclude certain situations.
+ // MlmeSetPsm(pAd, PWR_SAVE);
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+ if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+ pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
+ pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP;
+ pAd->StaCfg.DefaultListenCount = 5;
+ }
+ else if ((strcmp(tmpbuf, "Fast_PSP") == 0) || (strcmp(tmpbuf, "fast_psp") == 0)
+ || (strcmp(tmpbuf, "FAST_PSP") == 0))
+ {
+ // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+ // to exclude certain situations.
+ // MlmeSetPsmBit(pAd, PWR_SAVE);
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+ if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+ pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP;
+ pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP;
+ pAd->StaCfg.DefaultListenCount = 3;
+ }
+ else if ((strcmp(tmpbuf, "Legacy_PSP") == 0) || (strcmp(tmpbuf, "legacy_psp") == 0)
+ || (strcmp(tmpbuf, "LEGACY_PSP") == 0))
+ {
+ // do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
+ // to exclude certain situations.
+ // MlmeSetPsmBit(pAd, PWR_SAVE);
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+ if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+ pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP;
+ pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP;
+ pAd->StaCfg.DefaultListenCount = 3;
+ }
+ else
+ { //Default Ndis802_11PowerModeCAM
+ // clear PSM bit immediately
+ MlmeSetPsmBit(pAd, PWR_ACTIVE);
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
+ if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
+ pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
+ pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode));
+ }
+ }
+ // FastRoaming
+ if (RTMPGetKeyParameter("FastRoaming", tmpbuf, 32, buffer))
+ {
+ if (simple_strtol(tmpbuf, 0, 10) == 0)
+ pAd->StaCfg.bFastRoaming = FALSE;
+ else
+ pAd->StaCfg.bFastRoaming = TRUE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("FastRoaming=%d\n", pAd->StaCfg.bFastRoaming));
+ }
+ // RoamThreshold
+ if (RTMPGetKeyParameter("RoamThreshold", tmpbuf, 32, buffer))
+ {
+ long lInfo = simple_strtol(tmpbuf, 0, 10);
+
+ if (lInfo > 90 || lInfo < 60)
+ pAd->StaCfg.dBmToRoam = -70;
+ else
+ pAd->StaCfg.dBmToRoam = (CHAR)(-1)*lInfo;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RoamThreshold=%d dBm\n", pAd->StaCfg.dBmToRoam));
+ }
+
+ if(RTMPGetKeyParameter("TGnWifiTest", tmpbuf, 10, buffer))
+ {
+ if(simple_strtol(tmpbuf, 0, 10) == 0)
+ pAd->StaCfg.bTGnWifiTest = FALSE;
+ else
+ pAd->StaCfg.bTGnWifiTest = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("TGnWifiTest=%d\n", pAd->StaCfg.bTGnWifiTest));
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> %s does not have a write method\n", src));
+ }
+
+ retval=filp_close(srcf,NULL);
+
+ if (retval)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src));
+ }
+ }
+ }
+
+ set_fs(orgfs);
+
+#if 0
+ current->cred->fsuid = orgfsuid;
+ current->cred->fsgid = orgfsgid;
+#endif
+
+ kfree(buffer);
+ kfree(tmpbuf);
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+#ifdef DOT11_N_SUPPORT
+static void HTParametersHook(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR *pValueStr,
+ IN CHAR *pInput)
+{
+
+ INT Value;
+
+ if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bHTProtect = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bHTProtect = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+ if (RTMPGetKeyParameter("HT_MIMOPSEnable", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bMIMOPSEnable = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bMIMOPSEnable = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPSEnable = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+
+ if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value > MMPS_ENABLE)
+ {
+ pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+ }
+ else
+ {
+ //TODO: add mimo power saving mechanism
+ pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_ENABLE;
+ //pAd->CommonCfg.BACapability.field.MMPSmode = Value;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", Value));
+ }
+
+ if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bBADecline = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bBADecline = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+
+ if (RTMPGetKeyParameter("HT_DisableReordering", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bDisableReordering = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bDisableReordering = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: DisableReordering = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+ if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.BACapability.field.AutoBA = TRUE;
+ }
+ pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+ // Tx_+HTC frame
+ if (RTMPGetKeyParameter("HT_HTC", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->HTCEnable = FALSE;
+ }
+ else
+ {
+ pAd->HTCEnable = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx +HTC frame = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+ // Enable HT Link Adaptation Control
+ if (RTMPGetKeyParameter("HT_LinkAdapt", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->bLinkAdapt = FALSE;
+ }
+ else
+ {
+ pAd->HTCEnable = TRUE;
+ pAd->bLinkAdapt = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Link Adaptation Control = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)"));
+ }
+
+ // Reverse Direction Mechanism
+ if (RTMPGetKeyParameter("HT_RDG", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bRdg = FALSE;
+ }
+ else
+ {
+ pAd->HTCEnable = TRUE;
+ pAd->CommonCfg.bRdg = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)"));
+ }
+
+
+
+
+ // Tx A-MSUD ?
+ if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.BACapability.field.AmsduEnable = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.BACapability.field.AmsduEnable = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable"));
+ }
+
+ // MPDU Density
+ if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value <=7 && Value >= 0)
+ {
+ pAd->CommonCfg.BACapability.field.MpduDensity = Value;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", Value));
+ }
+ else
+ {
+ pAd->CommonCfg.BACapability.field.MpduDensity = 4;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4));
+ }
+ }
+
+ // Max Rx BA Window Size
+ if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value >=1 && Value <= 64)
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = Value;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = Value;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", Value));
+ }
+ else
+ {
+ pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = 64;
+ pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = 64 (Defualt)\n"));
+ }
+
+ }
+
+ // Guard Interval
+ if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == GI_400)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" ));
+ }
+
+ // HT Operation Mode : Mixed Mode , Green Field
+ if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == HTMODE_GF)
+ {
+
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" ));
+ }
+
+ // Fixed Tx mode : CCK, OFDM
+ if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput))
+ {
+ UCHAR fix_tx_mode;
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ fix_tx_mode = FIXED_TXMODE_HT;
+
+ if (strcmp(pValueStr, "OFDM") == 0 || strcmp(pValueStr, "ofdm") == 0)
+ {
+ fix_tx_mode = FIXED_TXMODE_OFDM;
+ }
+ else if (strcmp(pValueStr, "CCK") == 0 || strcmp(pValueStr, "cck") == 0)
+ {
+ fix_tx_mode = FIXED_TXMODE_CCK;
+ }
+ else if (strcmp(pValueStr, "HT") == 0 || strcmp(pValueStr, "ht") == 0)
+ {
+ fix_tx_mode = FIXED_TXMODE_HT;
+ }
+ else
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ // 1 : CCK
+ // 2 : OFDM
+ // otherwise : HT
+ if (Value == FIXED_TXMODE_CCK || Value == FIXED_TXMODE_OFDM)
+ fix_tx_mode = Value;
+ else
+ fix_tx_mode = FIXED_TXMODE_HT;
+ }
+
+ pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode;
+ DBGPRINT(RT_DEBUG_TRACE, ("Fixed Tx Mode = %d\n", fix_tx_mode));
+
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+
+ // Channel Width
+ if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == BW_40)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
+ }
+
+#ifdef MCAST_RATE_SPECIFIC
+ pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW;
+#endif // MCAST_RATE_SPECIFIC //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" ));
+ }
+
+ if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if (Value == 0)
+ {
+
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" ));
+ }
+
+ // MSC
+ if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput))
+ {
+
+#ifdef CONFIG_STA_SUPPORT
+ IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+
+ if ((Value >= 0 && Value <= 23) || (Value == 32)) // 3*3
+ {
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS = Value;
+ pAd->StaCfg.bAutoTxRateSwitch = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = %d\n", pAd->StaCfg.DesiredTransmitSetting.field.MCS));
+ }
+ else
+ {
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS = MCS_AUTO;
+ pAd->StaCfg.bAutoTxRateSwitch = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: MCS = AUTO\n"));
+ }
+ }
+#endif // CONFIG_STA_SUPPORT //
+ }
+
+ // STBC
+ if (RTMPGetKeyParameter("HT_STBC", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == STBC_USE)
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_USE;
+ }
+ else
+ {
+ pAd->CommonCfg.RegTransmitSetting.field.STBC = STBC_NONE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: STBC = %d\n", pAd->CommonCfg.RegTransmitSetting.field.STBC));
+ }
+
+ // 40_Mhz_Intolerant
+ if (RTMPGetKeyParameter("HT_40MHZ_INTOLERANT", pValueStr, 25, pInput))
+ {
+ Value = simple_strtol(pValueStr, 0, 10);
+ if (Value == 0)
+ {
+ pAd->CommonCfg.bForty_Mhz_Intolerant = FALSE;
+ }
+ else
+ {
+ pAd->CommonCfg.bForty_Mhz_Intolerant = TRUE;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: 40MHZ INTOLERANT = %d\n", pAd->CommonCfg.bForty_Mhz_Intolerant));
+ }
+ //HT_TxStream
+ if(RTMPGetKeyParameter("HT_TxStream", pValueStr, 10, pInput))
+ {
+ switch (simple_strtol(pValueStr, 0, 10))
+ {
+ case 1:
+ pAd->CommonCfg.TxStream = 1;
+ break;
+ case 2:
+ pAd->CommonCfg.TxStream = 2;
+ break;
+ case 3: // 3*3
+ default:
+ pAd->CommonCfg.TxStream = 3;
+
+ if (pAd->MACVersion < RALINK_2883_VERSION)
+ pAd->CommonCfg.TxStream = 2; // only 2 tx streams for RT2860 series
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx Stream = %d\n", pAd->CommonCfg.TxStream));
+ }
+ //HT_RxStream
+ if(RTMPGetKeyParameter("HT_RxStream", pValueStr, 10, pInput))
+ {
+ switch (simple_strtol(pValueStr, 0, 10))
+ {
+ case 1:
+ pAd->CommonCfg.RxStream = 1;
+ break;
+ case 2:
+ pAd->CommonCfg.RxStream = 2;
+ break;
+ case 3:
+ default:
+ pAd->CommonCfg.RxStream = 3;
+
+ if (pAd->MACVersion < RALINK_2883_VERSION)
+ pAd->CommonCfg.RxStream = 2; // only 2 rx streams for RT2860 series
+ break;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("HT: Rx Stream = %d\n", pAd->CommonCfg.RxStream));
+ }
+
+}
+#endif // DOT11_N_SUPPORT //
+
diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h
new file mode 100644
index 000000000000..411954206c28
--- /dev/null
+++ b/drivers/staging/rt2860/rtmp.h
@@ -0,0 +1,7177 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp.h
+
+ Abstract:
+ Miniport generic portion header file
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 2002-08-01 created
+ James Tan 2002-09-06 modified (Revise NTCRegTable)
+ John Chang 2004-09-06 modified for RT2600
+*/
+#ifndef __RTMP_H__
+#define __RTMP_H__
+
+#include "link_list.h"
+#include "spectrum_def.h"
+
+
+#ifdef CONFIG_STA_SUPPORT
+#include "aironet.h"
+#endif // CONFIG_STA_SUPPORT //
+
+//#define DBG_DIAGNOSE 1
+
+#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT)
+#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) if(_pAd->OpMode == OPMODE_AP)
+#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) if(_pAd->OpMode == OPMODE_STA)
+#else
+#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd)
+#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd)
+#endif
+
+#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++)
+#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--)
+#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt)
+
+
+
+//
+// NDIS Version definitions
+//
+#ifdef NDIS50_MINIPORT
+#define RTMP_NDIS_MAJOR_VERSION 5
+#define RTMP_NDIS_MINOR_VERSION 0
+#endif
+
+#ifdef NDIS51_MINIPORT
+#define RTMP_NDIS_MAJOR_VERSION 5
+#define RTMP_NDIS_MINOR_VERSION 1
+#endif
+
+extern char NIC_VENDOR_DESC[];
+extern int NIC_VENDOR_DESC_LEN;
+
+extern unsigned char SNAP_AIRONET[];
+extern unsigned char CipherSuiteCiscoCCKM[];
+extern unsigned char CipherSuiteCiscoCCKMLen;
+extern unsigned char CipherSuiteCiscoCCKM24[];
+extern unsigned char CipherSuiteCiscoCCKM24Len;
+extern unsigned char CipherSuiteCCXTkip[];
+extern unsigned char CipherSuiteCCXTkipLen;
+extern unsigned char CISCO_OUI[];
+extern UCHAR BaSizeArray[4];
+
+extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN];
+extern UCHAR MULTICAST_ADDR[MAC_ADDR_LEN];
+extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN];
+extern ULONG BIT32[32];
+extern UCHAR BIT8[8];
+extern char* CipherName[];
+extern char* MCSToMbps[];
+extern UCHAR RxwiMCSToOfdmRate[12];
+extern UCHAR SNAP_802_1H[6];
+extern UCHAR SNAP_BRIDGE_TUNNEL[6];
+extern UCHAR SNAP_AIRONET[8];
+extern UCHAR CKIP_LLC_SNAP[8];
+extern UCHAR EAPOL_LLC_SNAP[8];
+extern UCHAR EAPOL[2];
+extern UCHAR IPX[2];
+extern UCHAR APPLE_TALK[2];
+extern UCHAR RateIdToPlcpSignal[12]; // see IEEE802.11a-1999 p.14
+extern UCHAR OfdmRateToRxwiMCS[];
+extern UCHAR OfdmSignalToRateId[16] ;
+extern UCHAR default_cwmin[4];
+extern UCHAR default_cwmax[4];
+extern UCHAR default_sta_aifsn[4];
+extern UCHAR MapUserPriorityToAccessCategory[8];
+
+extern USHORT RateUpPER[];
+extern USHORT RateDownPER[];
+extern UCHAR Phy11BNextRateDownward[];
+extern UCHAR Phy11BNextRateUpward[];
+extern UCHAR Phy11BGNextRateDownward[];
+extern UCHAR Phy11BGNextRateUpward[];
+extern UCHAR Phy11ANextRateDownward[];
+extern UCHAR Phy11ANextRateUpward[];
+extern CHAR RssiSafeLevelForTxRate[];
+extern UCHAR RateIdToMbps[];
+extern USHORT RateIdTo500Kbps[];
+
+extern UCHAR CipherSuiteWpaNoneTkip[];
+extern UCHAR CipherSuiteWpaNoneTkipLen;
+
+extern UCHAR CipherSuiteWpaNoneAes[];
+extern UCHAR CipherSuiteWpaNoneAesLen;
+
+extern UCHAR SsidIe;
+extern UCHAR SupRateIe;
+extern UCHAR ExtRateIe;
+
+#ifdef DOT11_N_SUPPORT
+extern UCHAR HtCapIe;
+extern UCHAR AddHtInfoIe;
+extern UCHAR NewExtChanIe;
+#ifdef DOT11N_DRAFT3
+extern UCHAR ExtHtCapIe;
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+extern UCHAR ErpIe;
+extern UCHAR DsIe;
+extern UCHAR TimIe;
+extern UCHAR WpaIe;
+extern UCHAR Wpa2Ie;
+extern UCHAR IbssIe;
+extern UCHAR Ccx2Ie;
+
+extern UCHAR WPA_OUI[];
+extern UCHAR RSN_OUI[];
+extern UCHAR WME_INFO_ELEM[];
+extern UCHAR WME_PARM_ELEM[];
+extern UCHAR Ccx2QosInfo[];
+extern UCHAR Ccx2IeInfo[];
+extern UCHAR RALINK_OUI[];
+extern UCHAR PowerConstraintIE[];
+
+
+extern UCHAR RateSwitchTable[];
+extern UCHAR RateSwitchTable11B[];
+extern UCHAR RateSwitchTable11G[];
+extern UCHAR RateSwitchTable11BG[];
+
+#ifdef DOT11_N_SUPPORT
+extern UCHAR RateSwitchTable11BGN1S[];
+extern UCHAR RateSwitchTable11BGN2S[];
+extern UCHAR RateSwitchTable11BGN2SForABand[];
+extern UCHAR RateSwitchTable11N1S[];
+extern UCHAR RateSwitchTable11N2S[];
+extern UCHAR RateSwitchTable11N2SForABand[];
+
+#ifdef CONFIG_STA_SUPPORT
+extern UCHAR PRE_N_HT_OUI[];
+#endif // CONFIG_STA_SUPPORT //
+#endif // DOT11_N_SUPPORT //
+
+#define MAXSEQ (0xFFF)
+
+#ifdef RALINK_ATE
+typedef struct _ATE_INFO {
+ UCHAR Mode;
+ CHAR TxPower0;
+ CHAR TxPower1;
+ CHAR TxAntennaSel;
+ CHAR RxAntennaSel;
+ TXWI_STRUC TxWI; // TXWI
+ USHORT QID;
+ UCHAR Addr1[MAC_ADDR_LEN];
+ UCHAR Addr2[MAC_ADDR_LEN];
+ UCHAR Addr3[MAC_ADDR_LEN];
+ UCHAR Channel;
+ UINT32 TxLength;
+ UINT32 TxCount;
+ UINT32 TxDoneCount; // Tx DMA Done
+ UINT32 RFFreqOffset;
+ BOOLEAN bRxFer;
+ BOOLEAN bQATxStart; // Have compiled QA in and use it to ATE tx.
+ BOOLEAN bQARxStart; // Have compiled QA in and use it to ATE rx.
+#ifdef RT2860
+ BOOLEAN bFWLoading; // Reload firmware when ATE is done.
+#endif // RT2860 //
+ UINT32 RxTotalCnt;
+ UINT32 RxCntPerSec;
+
+ CHAR LastSNR0; // last received SNR
+ CHAR LastSNR1; // last received SNR for 2nd antenna
+ CHAR LastRssi0; // last received RSSI
+ CHAR LastRssi1; // last received RSSI for 2nd antenna
+ CHAR LastRssi2; // last received RSSI for 3rd antenna
+ CHAR AvgRssi0; // last 8 frames' average RSSI
+ CHAR AvgRssi1; // last 8 frames' average RSSI
+ CHAR AvgRssi2; // last 8 frames' average RSSI
+ SHORT AvgRssi0X8; // sum of last 8 frames' RSSI
+ SHORT AvgRssi1X8; // sum of last 8 frames' RSSI
+ SHORT AvgRssi2X8; // sum of last 8 frames' RSSI
+
+ UINT32 NumOfAvgRssiSample;
+
+#ifdef RALINK_28xx_QA
+ // Tx frame
+ USHORT HLen; // Header Length
+ USHORT PLen; // Pattern Length
+ UCHAR Header[32]; // Header buffer
+ UCHAR Pattern[32]; // Pattern buffer
+ USHORT DLen; // Data Length
+ USHORT seq;
+ UINT32 CID;
+ THREAD_PID AtePid;
+ // counters
+ UINT32 U2M;
+ UINT32 OtherData;
+ UINT32 Beacon;
+ UINT32 OtherCount;
+ UINT32 TxAc0;
+ UINT32 TxAc1;
+ UINT32 TxAc2;
+ UINT32 TxAc3;
+ UINT32 TxHCCA;
+ UINT32 TxMgmt;
+ UINT32 RSSI0;
+ UINT32 RSSI1;
+ UINT32 RSSI2;
+ UINT32 SNR0;
+ UINT32 SNR1;
+ // control
+ //UINT32 Repeat; // Tx Cpu count
+ UCHAR TxStatus; // task Tx status // 0 --> task is idle, 1 --> task is running
+#endif // RALINK_28xx_QA //
+} ATE_INFO, *PATE_INFO;
+
+#ifdef RALINK_28xx_QA
+struct ate_racfghdr {
+ UINT32 magic_no;
+ USHORT command_type;
+ USHORT command_id;
+ USHORT length;
+ USHORT sequence;
+ USHORT status;
+ UCHAR data[2046];
+} __attribute__((packed));
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+#ifdef DOT11_N_SUPPORT
+struct reordering_mpdu
+{
+ struct reordering_mpdu *next;
+ PNDIS_PACKET pPacket; /* coverted to 802.3 frame */
+ int Sequence; /* sequence number of MPDU */
+ BOOLEAN bAMSDU;
+};
+
+struct reordering_list
+{
+ struct reordering_mpdu *next;
+ int qlen;
+};
+
+struct reordering_mpdu_pool
+{
+ PVOID mem;
+ NDIS_SPIN_LOCK lock;
+ struct reordering_list freelist;
+};
+#endif // DOT11_N_SUPPORT //
+
+typedef struct _RSSI_SAMPLE {
+ CHAR LastRssi0; // last received RSSI
+ CHAR LastRssi1; // last received RSSI
+ CHAR LastRssi2; // last received RSSI
+ CHAR AvgRssi0;
+ CHAR AvgRssi1;
+ CHAR AvgRssi2;
+ SHORT AvgRssi0X8;
+ SHORT AvgRssi1X8;
+ SHORT AvgRssi2X8;
+} RSSI_SAMPLE;
+
+//
+// Queue structure and macros
+//
+typedef struct _QUEUE_ENTRY {
+ struct _QUEUE_ENTRY *Next;
+} QUEUE_ENTRY, *PQUEUE_ENTRY;
+
+// Queue structure
+typedef struct _QUEUE_HEADER {
+ PQUEUE_ENTRY Head;
+ PQUEUE_ENTRY Tail;
+ ULONG Number;
+} QUEUE_HEADER, *PQUEUE_HEADER;
+
+#define InitializeQueueHeader(QueueHeader) \
+{ \
+ (QueueHeader)->Head = (QueueHeader)->Tail = NULL; \
+ (QueueHeader)->Number = 0; \
+}
+
+#define RemoveHeadQueue(QueueHeader) \
+(QueueHeader)->Head; \
+{ \
+ PQUEUE_ENTRY pNext; \
+ if ((QueueHeader)->Head != NULL) \
+ { \
+ pNext = (QueueHeader)->Head->Next; \
+ (QueueHeader)->Head = pNext; \
+ if (pNext == NULL) \
+ (QueueHeader)->Tail = NULL; \
+ (QueueHeader)->Number--; \
+ } \
+}
+
+#define InsertHeadQueue(QueueHeader, QueueEntry) \
+{ \
+ ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \
+ (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \
+ if ((QueueHeader)->Tail == NULL) \
+ (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \
+ (QueueHeader)->Number++; \
+}
+
+#define InsertTailQueue(QueueHeader, QueueEntry) \
+{ \
+ ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \
+ if ((QueueHeader)->Tail) \
+ (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \
+ else \
+ (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \
+ (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \
+ (QueueHeader)->Number++; \
+}
+
+//
+// Macros for flag and ref count operations
+//
+#define RTMP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F))
+#define RTMP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F))
+#define RTMP_CLEAR_FLAGS(_M) ((_M)->Flags = 0)
+#define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0)
+#define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F))
+
+#define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F))
+#define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F))
+#define OPSTATUS_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0)
+
+#define CLIENT_STATUS_SET_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags |= (_F))
+#define CLIENT_STATUS_CLEAR_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags &= ~(_F))
+#define CLIENT_STATUS_TEST_FLAG(_pEntry,_F) (((_pEntry)->ClientStatusFlags & (_F)) != 0)
+
+#define RX_FILTER_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter |= (_F))
+#define RX_FILTER_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter &= ~(_F))
+#define RX_FILTER_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.PacketFilter & (_F)) != 0)
+
+#ifdef CONFIG_STA_SUPPORT
+#define STA_NO_SECURITY_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
+#define STA_WEP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption1Enabled)
+#define STA_TKIP_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
+#define STA_AES_ON(_p) (_p->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+
+#define STA_TGN_WIFI_ON(_p) (_p->StaCfg.bTGnWifiTest == TRUE)
+#endif // CONFIG_STA_SUPPORT //
+
+#define CKIP_KP_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x10) && ((_p)->StaCfg.bCkipCmicOn == TRUE))
+#define CKIP_CMIC_ON(_p) ((((_p)->StaCfg.CkipFlag) & 0x08) && ((_p)->StaCfg.bCkipCmicOn == TRUE))
+
+
+#define INC_RING_INDEX(_idx, _RingSize) \
+{ \
+ (_idx) = (_idx+1) % (_RingSize); \
+}
+
+#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000)
+
+#define RING_PACKET_INIT(_TxRing, _idx) \
+{ \
+ _TxRing->Cell[_idx].pNdisPacket = NULL; \
+ _TxRing->Cell[_idx].pNextNdisPacket = NULL; \
+}
+
+#define TXDT_INIT(_TxD) \
+{ \
+ NdisZeroMemory(_TxD, TXD_SIZE); \
+ _TxD->DMADONE = 1; \
+}
+
+//Set last data segment
+#define RING_SET_LASTDS(_TxD, _IsSD0) \
+{ \
+ if (_IsSD0) {_TxD->LastSec0 = 1;} \
+ else {_TxD->LastSec1 = 1;} \
+}
+
+// Increase TxTsc value for next transmission
+// TODO:
+// When i==6, means TSC has done one full cycle, do re-keying stuff follow specs
+// Should send a special event microsoft defined to request re-key
+#define INC_TX_TSC(_tsc) \
+{ \
+ int i=0; \
+ while (++_tsc[i] == 0x0) \
+ { \
+ i++; \
+ if (i == 6) \
+ break; \
+ } \
+}
+
+#ifdef DOT11_N_SUPPORT
+// StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here.
+#define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \
+{ \
+ _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth; \
+ _pAd->StaActive.SupportedHtPhy.MimoPs = _pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs; \
+ _pAd->StaActive.SupportedHtPhy.GF = _pAd->MlmeAux.HtCapability.HtCapInfo.GF; \
+ _pAd->StaActive.SupportedHtPhy.ShortGIfor20 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20; \
+ _pAd->StaActive.SupportedHtPhy.ShortGIfor40 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40; \
+ _pAd->StaActive.SupportedHtPhy.TxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC; \
+ _pAd->StaActive.SupportedHtPhy.RxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC; \
+ _pAd->StaActive.SupportedHtPhy.ExtChanOffset = _pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset; \
+ _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth; \
+ _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; \
+ _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent; \
+ NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\
+}
+
+#define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability) \
+{ \
+ _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize); \
+ _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs); \
+ _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \
+}
+#endif // DOT11_N_SUPPORT //
+
+//
+// MACRO for 32-bit PCI register read / write
+//
+// Usage : RTMP_IO_READ32(
+// PRTMP_ADAPTER pAd,
+// ULONG Register_Offset,
+// PULONG pValue)
+//
+// RTMP_IO_WRITE32(
+// PRTMP_ADAPTER pAd,
+// ULONG Register_Offset,
+// ULONG Value)
+//
+
+//
+// BBP & RF are using indirect access. Before write any value into it.
+// We have to make sure there is no outstanding command pending via checking busy bit.
+//
+#define MAX_BUSY_COUNT 100 // Number of retry before failing access BBP & RF indirect register
+//
+#ifdef RT2860
+#define RTMP_RF_IO_WRITE32(_A, _V) \
+{ \
+ PHY_CSR4_STRUC Value; \
+ ULONG BusyCnt = 0; \
+ if ((_A)->bPCIclkOff) \
+ { \
+ return; \
+ } \
+ do { \
+ RTMP_IO_READ32(_A, RF_CSR_CFG0, &Value.word); \
+ if (Value.field.Busy == IDLE) \
+ break; \
+ BusyCnt++; \
+ } while (BusyCnt < MAX_BUSY_COUNT); \
+ if (BusyCnt < MAX_BUSY_COUNT) \
+ { \
+ RTMP_IO_WRITE32(_A, RF_CSR_CFG0, _V); \
+ } \
+}
+
+#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \
+{ \
+ BBP_CSR_CFG_STRUC BbpCsr; \
+ int i, k; \
+ for (i=0; i<MAX_BUSY_COUNT; i++) \
+ { \
+ RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == BUSY) \
+ { \
+ continue; \
+ } \
+ BbpCsr.word = 0; \
+ BbpCsr.field.fRead = 1; \
+ BbpCsr.field.BBP_RW_MODE = 1; \
+ BbpCsr.field.Busy = 1; \
+ BbpCsr.field.RegNum = _I; \
+ RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \
+ for (k=0; k<MAX_BUSY_COUNT; k++) \
+ { \
+ RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == IDLE) \
+ break; \
+ } \
+ if ((BbpCsr.field.Busy == IDLE) && \
+ (BbpCsr.field.RegNum == _I)) \
+ { \
+ *(_pV) = (UCHAR)BbpCsr.field.Value; \
+ break; \
+ } \
+ } \
+ if (BbpCsr.field.Busy == BUSY) \
+ { \
+ DBGPRINT_ERR(("DFS BBP read R%d fail\n", _I)); \
+ *(_pV) = (_A)->BbpWriteLatch[_I]; \
+ } \
+}
+
+//#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) {}
+// Read BBP register by register's ID. Generate PER to test BA
+#define RTMP_BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \
+{ \
+ BBP_CSR_CFG_STRUC BbpCsr; \
+ int i, k; \
+ if ((_A)->bPCIclkOff == FALSE) \
+ { \
+ for (i=0; i<MAX_BUSY_COUNT; i++) \
+ { \
+ RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == BUSY) \
+ { \
+ continue; \
+ } \
+ BbpCsr.word = 0; \
+ BbpCsr.field.fRead = 1; \
+ BbpCsr.field.BBP_RW_MODE = 1; \
+ BbpCsr.field.Busy = 1; \
+ BbpCsr.field.RegNum = _I; \
+ RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \
+ AsicSendCommandToMcu(_A, 0x80, 0xff, 0x0, 0x0); \
+ RTMPusecDelay(1000); \
+ for (k=0; k<MAX_BUSY_COUNT; k++) \
+ { \
+ RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == IDLE) \
+ break; \
+ } \
+ if ((BbpCsr.field.Busy == IDLE) && \
+ (BbpCsr.field.RegNum == _I)) \
+ { \
+ *(_pV) = (UCHAR)BbpCsr.field.Value; \
+ break; \
+ } \
+ } \
+ if (BbpCsr.field.Busy == BUSY) \
+ { \
+ DBGPRINT_ERR(("BBP read R%d=0x%x fail\n", _I, BbpCsr.word)); \
+ *(_pV) = (_A)->BbpWriteLatch[_I]; \
+ RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \
+ BbpCsr.field.Busy = 0; \
+ RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \
+ } \
+ } \
+}
+
+#define BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \
+{ \
+ BBP_CSR_CFG_STRUC BbpCsr; \
+ int BusyCnt; \
+ for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++) \
+ { \
+ RTMP_IO_READ32(_A, BBP_CSR_CFG, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == BUSY) \
+ continue; \
+ BbpCsr.word = 0; \
+ BbpCsr.field.fRead = 0; \
+ BbpCsr.field.BBP_RW_MODE = 1; \
+ BbpCsr.field.Busy = 1; \
+ BbpCsr.field.Value = _V; \
+ BbpCsr.field.RegNum = _I; \
+ RTMP_IO_WRITE32(_A, BBP_CSR_CFG, BbpCsr.word); \
+ (_A)->BbpWriteLatch[_I] = _V; \
+ break; \
+ } \
+ if (BusyCnt == MAX_BUSY_COUNT) \
+ { \
+ DBGPRINT_ERR(("BBP write R%d fail\n", _I)); \
+ } \
+}
+
+// Write BBP register by register's ID & value
+#define RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, _I, _V) \
+{ \
+ BBP_CSR_CFG_STRUC BbpCsr; \
+ int BusyCnt; \
+ if ((_A)->bPCIclkOff == FALSE) \
+ { \
+ for (BusyCnt=0; BusyCnt<MAX_BUSY_COUNT; BusyCnt++) \
+ { \
+ RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \
+ if (BbpCsr.field.Busy == BUSY) \
+ continue; \
+ BbpCsr.word = 0; \
+ BbpCsr.field.fRead = 0; \
+ BbpCsr.field.BBP_RW_MODE = 1; \
+ BbpCsr.field.Busy = 1; \
+ BbpCsr.field.Value = _V; \
+ BbpCsr.field.RegNum = _I; \
+ RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \
+ AsicSendCommandToMcu(_A, 0x80, 0xff, 0x0, 0x0); \
+ if (_A->OpMode == OPMODE_AP) \
+ RTMPusecDelay(1000); \
+ (_A)->BbpWriteLatch[_I] = _V; \
+ break; \
+ } \
+ if (BusyCnt == MAX_BUSY_COUNT) \
+ { \
+ DBGPRINT_ERR(("BBP write R%d=0x%x fail\n", _I, BbpCsr.word)); \
+ RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word); \
+ BbpCsr.field.Busy = 0; \
+ RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word); \
+ } \
+ } \
+}
+#endif // RT2860 //
+
+
+#define MAP_CHANNEL_ID_TO_KHZ(ch, khz) { \
+ switch (ch) \
+ { \
+ case 1: khz = 2412000; break; \
+ case 2: khz = 2417000; break; \
+ case 3: khz = 2422000; break; \
+ case 4: khz = 2427000; break; \
+ case 5: khz = 2432000; break; \
+ case 6: khz = 2437000; break; \
+ case 7: khz = 2442000; break; \
+ case 8: khz = 2447000; break; \
+ case 9: khz = 2452000; break; \
+ case 10: khz = 2457000; break; \
+ case 11: khz = 2462000; break; \
+ case 12: khz = 2467000; break; \
+ case 13: khz = 2472000; break; \
+ case 14: khz = 2484000; break; \
+ case 36: /* UNII */ khz = 5180000; break; \
+ case 40: /* UNII */ khz = 5200000; break; \
+ case 44: /* UNII */ khz = 5220000; break; \
+ case 48: /* UNII */ khz = 5240000; break; \
+ case 52: /* UNII */ khz = 5260000; break; \
+ case 56: /* UNII */ khz = 5280000; break; \
+ case 60: /* UNII */ khz = 5300000; break; \
+ case 64: /* UNII */ khz = 5320000; break; \
+ case 149: /* UNII */ khz = 5745000; break; \
+ case 153: /* UNII */ khz = 5765000; break; \
+ case 157: /* UNII */ khz = 5785000; break; \
+ case 161: /* UNII */ khz = 5805000; break; \
+ case 165: /* UNII */ khz = 5825000; break; \
+ case 100: /* HiperLAN2 */ khz = 5500000; break; \
+ case 104: /* HiperLAN2 */ khz = 5520000; break; \
+ case 108: /* HiperLAN2 */ khz = 5540000; break; \
+ case 112: /* HiperLAN2 */ khz = 5560000; break; \
+ case 116: /* HiperLAN2 */ khz = 5580000; break; \
+ case 120: /* HiperLAN2 */ khz = 5600000; break; \
+ case 124: /* HiperLAN2 */ khz = 5620000; break; \
+ case 128: /* HiperLAN2 */ khz = 5640000; break; \
+ case 132: /* HiperLAN2 */ khz = 5660000; break; \
+ case 136: /* HiperLAN2 */ khz = 5680000; break; \
+ case 140: /* HiperLAN2 */ khz = 5700000; break; \
+ case 34: /* Japan MMAC */ khz = 5170000; break; \
+ case 38: /* Japan MMAC */ khz = 5190000; break; \
+ case 42: /* Japan MMAC */ khz = 5210000; break; \
+ case 46: /* Japan MMAC */ khz = 5230000; break; \
+ case 184: /* Japan */ khz = 4920000; break; \
+ case 188: /* Japan */ khz = 4940000; break; \
+ case 192: /* Japan */ khz = 4960000; break; \
+ case 196: /* Japan */ khz = 4980000; break; \
+ case 208: /* Japan, means J08 */ khz = 5040000; break; \
+ case 212: /* Japan, means J12 */ khz = 5060000; break; \
+ case 216: /* Japan, means J16 */ khz = 5080000; break; \
+ default: khz = 2412000; break; \
+ } \
+ }
+
+#define MAP_KHZ_TO_CHANNEL_ID(khz, ch) { \
+ switch (khz) \
+ { \
+ case 2412000: ch = 1; break; \
+ case 2417000: ch = 2; break; \
+ case 2422000: ch = 3; break; \
+ case 2427000: ch = 4; break; \
+ case 2432000: ch = 5; break; \
+ case 2437000: ch = 6; break; \
+ case 2442000: ch = 7; break; \
+ case 2447000: ch = 8; break; \
+ case 2452000: ch = 9; break; \
+ case 2457000: ch = 10; break; \
+ case 2462000: ch = 11; break; \
+ case 2467000: ch = 12; break; \
+ case 2472000: ch = 13; break; \
+ case 2484000: ch = 14; break; \
+ case 5180000: ch = 36; /* UNII */ break; \
+ case 5200000: ch = 40; /* UNII */ break; \
+ case 5220000: ch = 44; /* UNII */ break; \
+ case 5240000: ch = 48; /* UNII */ break; \
+ case 5260000: ch = 52; /* UNII */ break; \
+ case 5280000: ch = 56; /* UNII */ break; \
+ case 5300000: ch = 60; /* UNII */ break; \
+ case 5320000: ch = 64; /* UNII */ break; \
+ case 5745000: ch = 149; /* UNII */ break; \
+ case 5765000: ch = 153; /* UNII */ break; \
+ case 5785000: ch = 157; /* UNII */ break; \
+ case 5805000: ch = 161; /* UNII */ break; \
+ case 5825000: ch = 165; /* UNII */ break; \
+ case 5500000: ch = 100; /* HiperLAN2 */ break; \
+ case 5520000: ch = 104; /* HiperLAN2 */ break; \
+ case 5540000: ch = 108; /* HiperLAN2 */ break; \
+ case 5560000: ch = 112; /* HiperLAN2 */ break; \
+ case 5580000: ch = 116; /* HiperLAN2 */ break; \
+ case 5600000: ch = 120; /* HiperLAN2 */ break; \
+ case 5620000: ch = 124; /* HiperLAN2 */ break; \
+ case 5640000: ch = 128; /* HiperLAN2 */ break; \
+ case 5660000: ch = 132; /* HiperLAN2 */ break; \
+ case 5680000: ch = 136; /* HiperLAN2 */ break; \
+ case 5700000: ch = 140; /* HiperLAN2 */ break; \
+ case 5170000: ch = 34; /* Japan MMAC */ break; \
+ case 5190000: ch = 38; /* Japan MMAC */ break; \
+ case 5210000: ch = 42; /* Japan MMAC */ break; \
+ case 5230000: ch = 46; /* Japan MMAC */ break; \
+ case 4920000: ch = 184; /* Japan */ break; \
+ case 4940000: ch = 188; /* Japan */ break; \
+ case 4960000: ch = 192; /* Japan */ break; \
+ case 4980000: ch = 196; /* Japan */ break; \
+ case 5040000: ch = 208; /* Japan, means J08 */ break; \
+ case 5060000: ch = 212; /* Japan, means J12 */ break; \
+ case 5080000: ch = 216; /* Japan, means J16 */ break; \
+ default: ch = 1; break; \
+ } \
+ }
+
+//
+// Common fragment list structure - Identical to the scatter gather frag list structure
+//
+#define NIC_MAX_PHYS_BUF_COUNT 8
+
+typedef struct _RTMP_SCATTER_GATHER_ELEMENT {
+ PVOID Address;
+ ULONG Length;
+ PULONG Reserved;
+} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT;
+
+
+typedef struct _RTMP_SCATTER_GATHER_LIST {
+ ULONG NumberOfElements;
+ PULONG Reserved;
+ RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT];
+} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST;
+
+//
+// Some utility macros
+//
+#ifndef min
+#define min(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
+#endif
+
+#ifndef max
+#define max(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
+#endif
+
+#define GET_LNA_GAIN(_pAd) ((_pAd->LatchRfRegs.Channel <= 14) ? (_pAd->BLNAGain) : ((_pAd->LatchRfRegs.Channel <= 64) ? (_pAd->ALNAGain0) : ((_pAd->LatchRfRegs.Channel <= 128) ? (_pAd->ALNAGain1) : (_pAd->ALNAGain2))))
+
+#define INC_COUNTER64(Val) (Val.QuadPart++)
+
+#define INFRA_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_INFRA_ON))
+#define ADHOC_ON(_p) (OPSTATUS_TEST_FLAG(_p, fOP_STATUS_ADHOC_ON))
+#define MONITOR_ON(_p) (((_p)->StaCfg.BssType) == BSS_MONITOR)
+#define IDLE_ON(_p) (!INFRA_ON(_p) && !ADHOC_ON(_p))
+
+// Check LEAP & CCKM flags
+#define LEAP_ON(_p) (((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP)
+#define LEAP_CCKM_ON(_p) ((((_p)->StaCfg.LeapAuthMode) == CISCO_AuthModeLEAP) && ((_p)->StaCfg.LeapAuthInfo.CCKM == TRUE))
+
+// if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required
+#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(_pBufVA, _pExtraLlcSnapEncap) \
+{ \
+ if (((*(_pBufVA + 12) << 8) + *(_pBufVA + 13)) > 1500) \
+ { \
+ _pExtraLlcSnapEncap = SNAP_802_1H; \
+ if (NdisEqualMemory(IPX, _pBufVA + 12, 2) || \
+ NdisEqualMemory(APPLE_TALK, _pBufVA + 12, 2)) \
+ { \
+ _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \
+ } \
+ } \
+ else \
+ { \
+ _pExtraLlcSnapEncap = NULL; \
+ } \
+}
+
+// New Define for new Tx Path.
+#define EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(_pBufVA, _pExtraLlcSnapEncap) \
+{ \
+ if (((*(_pBufVA) << 8) + *(_pBufVA + 1)) > 1500) \
+ { \
+ _pExtraLlcSnapEncap = SNAP_802_1H; \
+ if (NdisEqualMemory(IPX, _pBufVA, 2) || \
+ NdisEqualMemory(APPLE_TALK, _pBufVA, 2)) \
+ { \
+ _pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; \
+ } \
+ } \
+ else \
+ { \
+ _pExtraLlcSnapEncap = NULL; \
+ } \
+}
+
+
+#define MAKE_802_3_HEADER(_p, _pMac1, _pMac2, _pType) \
+{ \
+ NdisMoveMemory(_p, _pMac1, MAC_ADDR_LEN); \
+ NdisMoveMemory((_p + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN); \
+ NdisMoveMemory((_p + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \
+}
+
+// if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), keep it that way.
+// else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, preserve the LLC/SNAP field
+// else remove the LLC/SNAP field from the result Ethernet frame
+// Patch for WHQL only, which did not turn on Netbios but use IPX within its payload
+// Note:
+// _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO
+// _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed
+#define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP) \
+{ \
+ char LLC_Len[2]; \
+ \
+ _pRemovedLLCSNAP = NULL; \
+ if (NdisEqualMemory(SNAP_802_1H, _pData, 6) || \
+ NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6)) \
+ { \
+ PUCHAR pProto = _pData + 6; \
+ \
+ if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) && \
+ NdisEqualMemory(SNAP_802_1H, _pData, 6)) \
+ { \
+ LLC_Len[0] = (UCHAR)(_DataSize / 256); \
+ LLC_Len[1] = (UCHAR)(_DataSize % 256); \
+ MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \
+ } \
+ else \
+ { \
+ MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, pProto); \
+ _pRemovedLLCSNAP = _pData; \
+ _DataSize -= LENGTH_802_1_H; \
+ _pData += LENGTH_802_1_H; \
+ } \
+ } \
+ else \
+ { \
+ LLC_Len[0] = (UCHAR)(_DataSize / 256); \
+ LLC_Len[1] = (UCHAR)(_DataSize % 256); \
+ MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \
+ } \
+}
+
+#define SWITCH_AB( _pAA, _pBB) \
+{ \
+ PVOID pCC; \
+ pCC = _pBB; \
+ _pBB = _pAA; \
+ _pAA = pCC; \
+}
+
+// Enqueue this frame to MLME engine
+// We need to enqueue the whole frame because MLME need to pass data type
+// information from 802.11 header
+#ifdef RT2860
+#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _PlcpSignal) \
+{ \
+ UINT32 High32TSF, Low32TSF; \
+ RTMP_IO_READ32(_pAd, TSF_TIMER_DW1, &High32TSF); \
+ RTMP_IO_READ32(_pAd, TSF_TIMER_DW0, &Low32TSF); \
+ MlmeEnqueueForRecv(_pAd, Wcid, High32TSF, Low32TSF, (UCHAR)_Rssi0, (UCHAR)_Rssi1,(UCHAR)_Rssi2,_FrameSize, _pFrame, (UCHAR)_PlcpSignal); \
+}
+#endif // RT2860 //
+
+#define NDIS_QUERY_BUFFER(_NdisBuf, _ppVA, _pBufLen) \
+ NdisQueryBuffer(_NdisBuf, _ppVA, _pBufLen)
+
+#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN)
+#define SSID_EQUAL(ssid1, len1, ssid2, len2) ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1)))
+
+//
+// Check if it is Japan W53(ch52,56,60,64) channel.
+//
+#define JapanChannelCheck(channel) ((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64))
+
+#ifdef CONFIG_STA_SUPPORT
+#define STA_PORT_SECURED(_pAd) \
+{ \
+ _pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; \
+ NdisAcquireSpinLock(&_pAd->MacTabLock); \
+ _pAd->MacTab.Content[BSSID_WCID].PortSecured = _pAd->StaCfg.PortSecured; \
+ NdisReleaseSpinLock(&_pAd->MacTabLock); \
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+//
+// Register set pair for initialzation register set definition
+//
+typedef struct _RTMP_REG_PAIR
+{
+ ULONG Register;
+ ULONG Value;
+} RTMP_REG_PAIR, *PRTMP_REG_PAIR;
+
+typedef struct _REG_PAIR
+{
+ UCHAR Register;
+ UCHAR Value;
+} REG_PAIR, *PREG_PAIR;
+
+//
+// Register set pair for initialzation register set definition
+//
+typedef struct _RTMP_RF_REGS
+{
+ UCHAR Channel;
+ ULONG R1;
+ ULONG R2;
+ ULONG R3;
+ ULONG R4;
+} RTMP_RF_REGS, *PRTMP_RF_REGS;
+
+typedef struct _FREQUENCY_ITEM {
+ UCHAR Channel;
+ UCHAR N;
+ UCHAR R;
+ UCHAR K;
+} FREQUENCY_ITEM, *PFREQUENCY_ITEM;
+
+//
+// Data buffer for DMA operation, the buffer must be contiguous physical memory
+// Both DMA to / from CPU use the same structure.
+//
+typedef struct _RTMP_DMABUF
+{
+ ULONG AllocSize;
+ PVOID AllocVa; // TxBuf virtual address
+ NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address
+} RTMP_DMABUF, *PRTMP_DMABUF;
+
+
+typedef union _HEADER_802_11_SEQ{
+#ifdef RT_BIG_ENDIAN
+ struct {
+ USHORT Sequence:12;
+ USHORT Frag:4;
+ } field;
+#else
+ struct {
+ USHORT Frag:4;
+ USHORT Sequence:12;
+ } field;
+#endif
+ USHORT value;
+} HEADER_802_11_SEQ, *PHEADER_802_11_SEQ;
+
+//
+// Data buffer for DMA operation, the buffer must be contiguous physical memory
+// Both DMA to / from CPU use the same structure.
+//
+typedef struct _RTMP_REORDERBUF
+{
+ BOOLEAN IsFull;
+ PVOID AllocVa; // TxBuf virtual address
+ UCHAR Header802_3[14];
+ HEADER_802_11_SEQ Sequence; //support compressed bitmap BA, so no consider fragment in BA
+ UCHAR DataOffset;
+ USHORT Datasize;
+ ULONG AllocSize;
+#ifdef RT2860
+ NDIS_PHYSICAL_ADDRESS AllocPa; // TxBuf physical address
+#endif // RT2860 //
+} RTMP_REORDERBUF, *PRTMP_REORDERBUF;
+
+//
+// Control block (Descriptor) for all ring descriptor DMA operation, buffer must be
+// contiguous physical memory. NDIS_PACKET stored the binding Rx packet descriptor
+// which won't be released, driver has to wait until upper layer return the packet
+// before giveing up this rx ring descriptor to ASIC. NDIS_BUFFER is assocaited pair
+// to describe the packet buffer. For Tx, NDIS_PACKET stored the tx packet descriptor
+// which driver should ACK upper layer when the tx is physically done or failed.
+//
+typedef struct _RTMP_DMACB
+{
+ ULONG AllocSize; // Control block size
+ PVOID AllocVa; // Control block virtual address
+ NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address
+ PNDIS_PACKET pNdisPacket;
+ PNDIS_PACKET pNextNdisPacket;
+
+ RTMP_DMABUF DmaBuf; // Associated DMA buffer structure
+} RTMP_DMACB, *PRTMP_DMACB;
+
+typedef struct _RTMP_TX_BUF
+{
+ PQUEUE_ENTRY Next;
+ UCHAR Index;
+ ULONG AllocSize; // Control block size
+ PVOID AllocVa; // Control block virtual address
+ NDIS_PHYSICAL_ADDRESS AllocPa; // Control block physical address
+} RTMP_TXBUF, *PRTMP_TXBUF;
+
+typedef struct _RTMP_RX_BUF
+{
+ BOOLEAN InUse;
+ ULONG ByBaRecIndex;
+ RTMP_REORDERBUF MAP_RXBuf[MAX_RX_REORDERBUF];
+} RTMP_RXBUF, *PRTMP_RXBUF;
+typedef struct _RTMP_TX_RING
+{
+ RTMP_DMACB Cell[TX_RING_SIZE];
+ UINT32 TxCpuIdx;
+ UINT32 TxDmaIdx;
+ UINT32 TxSwFreeIdx; // software next free tx index
+} RTMP_TX_RING, *PRTMP_TX_RING;
+
+typedef struct _RTMP_RX_RING
+{
+ RTMP_DMACB Cell[RX_RING_SIZE];
+ UINT32 RxCpuIdx;
+ UINT32 RxDmaIdx;
+ INT32 RxSwReadIdx; // software next read index
+} RTMP_RX_RING, *PRTMP_RX_RING;
+
+typedef struct _RTMP_MGMT_RING
+{
+ RTMP_DMACB Cell[MGMT_RING_SIZE];
+ UINT32 TxCpuIdx;
+ UINT32 TxDmaIdx;
+ UINT32 TxSwFreeIdx; // software next free tx index
+} RTMP_MGMT_RING, *PRTMP_MGMT_RING;
+
+//
+// Statistic counter structure
+//
+typedef struct _COUNTER_802_3
+{
+ // General Stats
+ ULONG GoodTransmits;
+ ULONG GoodReceives;
+ ULONG TxErrors;
+ ULONG RxErrors;
+ ULONG RxNoBuffer;
+
+ // Ethernet Stats
+ ULONG RcvAlignmentErrors;
+ ULONG OneCollision;
+ ULONG MoreCollisions;
+
+} COUNTER_802_3, *PCOUNTER_802_3;
+
+typedef struct _COUNTER_802_11 {
+ ULONG Length;
+ LARGE_INTEGER LastTransmittedFragmentCount;
+ LARGE_INTEGER TransmittedFragmentCount;
+ LARGE_INTEGER MulticastTransmittedFrameCount;
+ LARGE_INTEGER FailedCount;
+ LARGE_INTEGER RetryCount;
+ LARGE_INTEGER MultipleRetryCount;
+ LARGE_INTEGER RTSSuccessCount;
+ LARGE_INTEGER RTSFailureCount;
+ LARGE_INTEGER ACKFailureCount;
+ LARGE_INTEGER FrameDuplicateCount;
+ LARGE_INTEGER ReceivedFragmentCount;
+ LARGE_INTEGER MulticastReceivedFrameCount;
+ LARGE_INTEGER FCSErrorCount;
+} COUNTER_802_11, *PCOUNTER_802_11;
+
+typedef struct _COUNTER_RALINK {
+ ULONG TransmittedByteCount; // both successful and failure, used to calculate TX throughput
+ ULONG ReceivedByteCount; // both CRC okay and CRC error, used to calculate RX throughput
+ ULONG BeenDisassociatedCount;
+ ULONG BadCQIAutoRecoveryCount;
+ ULONG PoorCQIRoamingCount;
+ ULONG MgmtRingFullCount;
+ ULONG RxCountSinceLastNULL;
+ ULONG RxCount;
+ ULONG RxRingErrCount;
+ ULONG KickTxCount;
+ ULONG TxRingErrCount;
+ LARGE_INTEGER RealFcsErrCount;
+ ULONG PendingNdisPacketCount;
+
+ ULONG OneSecOsTxCount[NUM_OF_TX_RING];
+ ULONG OneSecDmaDoneCount[NUM_OF_TX_RING];
+ UINT32 OneSecTxDoneCount;
+ ULONG OneSecRxCount;
+ UINT32 OneSecTxAggregationCount;
+ UINT32 OneSecRxAggregationCount;
+
+ UINT32 OneSecFrameDuplicateCount;
+
+
+ UINT32 OneSecTxNoRetryOkCount;
+ UINT32 OneSecTxRetryOkCount;
+ UINT32 OneSecTxFailCount;
+ UINT32 OneSecFalseCCACnt; // CCA error count, for debug purpose, might move to global counter
+ UINT32 OneSecRxOkCnt; // RX without error
+ UINT32 OneSecRxOkDataCnt; // unicast-to-me DATA frame count
+ UINT32 OneSecRxFcsErrCnt; // CRC error
+ UINT32 OneSecBeaconSentCnt;
+ UINT32 LastOneSecTotalTxCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount
+ UINT32 LastOneSecRxOkDataCnt; // OneSecRxOkDataCnt
+ ULONG DuplicateRcv;
+ ULONG TxAggCount;
+ ULONG TxNonAggCount;
+ ULONG TxAgg1MPDUCount;
+ ULONG TxAgg2MPDUCount;
+ ULONG TxAgg3MPDUCount;
+ ULONG TxAgg4MPDUCount;
+ ULONG TxAgg5MPDUCount;
+ ULONG TxAgg6MPDUCount;
+ ULONG TxAgg7MPDUCount;
+ ULONG TxAgg8MPDUCount;
+ ULONG TxAgg9MPDUCount;
+ ULONG TxAgg10MPDUCount;
+ ULONG TxAgg11MPDUCount;
+ ULONG TxAgg12MPDUCount;
+ ULONG TxAgg13MPDUCount;
+ ULONG TxAgg14MPDUCount;
+ ULONG TxAgg15MPDUCount;
+ ULONG TxAgg16MPDUCount;
+
+ LARGE_INTEGER TransmittedOctetsInAMSDU;
+ LARGE_INTEGER TransmittedAMSDUCount;
+ LARGE_INTEGER ReceivedOctesInAMSDUCount;
+ LARGE_INTEGER ReceivedAMSDUCount;
+ LARGE_INTEGER TransmittedAMPDUCount;
+ LARGE_INTEGER TransmittedMPDUsInAMPDUCount;
+ LARGE_INTEGER TransmittedOctetsInAMPDUCount;
+ LARGE_INTEGER MPDUInReceivedAMPDUCount;
+} COUNTER_RALINK, *PCOUNTER_RALINK;
+
+typedef struct _PID_COUNTER {
+ ULONG TxAckRequiredCount; // CRC error
+ ULONG TxAggreCount;
+ ULONG TxSuccessCount; // OneSecTxNoRetryOkCount + OneSecTxRetryOkCount + OneSecTxFailCount
+ ULONG LastSuccessRate;
+} PID_COUNTER, *PPID_COUNTER;
+
+typedef struct _COUNTER_DRS {
+ // to record the each TX rate's quality. 0 is best, the bigger the worse.
+ USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH];
+ UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH];
+ UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition
+ ULONG CurrTxRateStableTime; // # of second in current TX rate
+ BOOLEAN fNoisyEnvironment;
+ BOOLEAN fLastSecAccordingRSSI;
+ UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down
+ UCHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction
+ ULONG LastTxOkCount;
+} COUNTER_DRS, *PCOUNTER_DRS;
+
+//
+// Arcfour Structure Added by PaulWu
+//
+typedef struct _ARCFOUR
+{
+ UINT X;
+ UINT Y;
+ UCHAR STATE[256];
+} ARCFOURCONTEXT, *PARCFOURCONTEXT;
+
+// MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI too. just copy to TXWI.
+typedef struct _RECEIVE_SETTING {
+#ifdef RT_BIG_ENDIAN
+ USHORT MIMO:1;
+ USHORT OFDM:1;
+ USHORT rsv:3;
+ USHORT STBC:2; //SPACE
+ USHORT ShortGI:1;
+ USHORT Mode:2; //channel bandwidth 20MHz or 40 MHz
+ USHORT NumOfRX:2; // MIMO. WE HAVE 3R
+#else
+ USHORT NumOfRX:2; // MIMO. WE HAVE 3R
+ USHORT Mode:2; //channel bandwidth 20MHz or 40 MHz
+ USHORT ShortGI:1;
+ USHORT STBC:2; //SPACE
+ USHORT rsv:3;
+ USHORT OFDM:1;
+ USHORT MIMO:1;
+#endif
+ } RECEIVE_SETTING, *PRECEIVE_SETTING;
+
+// Shared key data structure
+typedef struct _WEP_KEY {
+ UCHAR KeyLen; // Key length for each key, 0: entry is invalid
+ UCHAR Key[MAX_LEN_OF_KEY]; // right now we implement 4 keys, 128 bits max
+} WEP_KEY, *PWEP_KEY;
+
+typedef struct _CIPHER_KEY {
+ UCHAR Key[16]; // right now we implement 4 keys, 128 bits max
+ UCHAR RxMic[8]; // make alignment
+ UCHAR TxMic[8];
+ UCHAR TxTsc[6]; // 48bit TSC value
+ UCHAR RxTsc[6]; // 48bit TSC value
+ UCHAR CipherAlg; // 0-none, 1:WEP64, 2:WEP128, 3:TKIP, 4:AES, 5:CKIP64, 6:CKIP128
+ UCHAR KeyLen;
+#ifdef CONFIG_STA_SUPPORT
+ UCHAR BssId[6];
+#endif // CONFIG_STA_SUPPORT //
+ // Key length for each key, 0: entry is invalid
+ UCHAR Type; // Indicate Pairwise/Group when reporting MIC error
+} CIPHER_KEY, *PCIPHER_KEY;
+
+typedef struct _BBP_TUNING_STRUCT {
+ BOOLEAN Enable;
+ UCHAR FalseCcaCountUpperBound; // 100 per sec
+ UCHAR FalseCcaCountLowerBound; // 10 per sec
+ UCHAR R17LowerBound; // specified in E2PROM
+ UCHAR R17UpperBound; // 0x68 according to David Tung
+ UCHAR CurrentR17Value;
+} BBP_TUNING, *PBBP_TUNING;
+
+typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT {
+ UCHAR EvaluatePeriod; // 0:not evalute status, 1: evaluate status, 2: switching status
+ UCHAR Pair1PrimaryRxAnt; // 0:Ant-E1, 1:Ant-E2
+ UCHAR Pair1SecondaryRxAnt; // 0:Ant-E1, 1:Ant-E2
+ UCHAR Pair2PrimaryRxAnt; // 0:Ant-E3, 1:Ant-E4
+ UCHAR Pair2SecondaryRxAnt; // 0:Ant-E3, 1:Ant-E4
+ SHORT Pair1AvgRssi[2]; // AvgRssi[0]:E1, AvgRssi[1]:E2
+ SHORT Pair2AvgRssi[2]; // AvgRssi[0]:E3, AvgRssi[1]:E4
+ SHORT Pair1LastAvgRssi; //
+ SHORT Pair2LastAvgRssi; //
+ ULONG RcvPktNumWhenEvaluate;
+ BOOLEAN FirstPktArrivedWhenEvaluate;
+ RALINK_TIMER_STRUCT RxAntDiversityTimer;
+} SOFT_RX_ANT_DIVERSITY, *PSOFT_RX_ANT_DIVERSITY;
+
+typedef struct _LEAP_AUTH_INFO {
+ BOOLEAN Enabled; //Ture: Enable LEAP Authentication
+ BOOLEAN CCKM; //Ture: Use Fast Reauthentication with CCKM
+ UCHAR Reserve[2];
+ UCHAR UserName[256]; //LEAP, User name
+ ULONG UserNameLen;
+ UCHAR Password[256]; //LEAP, User Password
+ ULONG PasswordLen;
+} LEAP_AUTH_INFO, *PLEAP_AUTH_INFO;
+
+typedef struct {
+ UCHAR Addr[MAC_ADDR_LEN];
+ UCHAR ErrorCode[2]; //00 01-Invalid authentication type
+ //00 02-Authentication timeout
+ //00 03-Challenge from AP failed
+ //00 04-Challenge to AP failed
+ BOOLEAN Reported;
+} ROGUEAP_ENTRY, *PROGUEAP_ENTRY;
+
+typedef struct {
+ UCHAR RogueApNr;
+ ROGUEAP_ENTRY RogueApEntry[MAX_LEN_OF_BSS_TABLE];
+} ROGUEAP_TABLE, *PROGUEAP_TABLE;
+
+typedef struct {
+ BOOLEAN Enable;
+ UCHAR Delta;
+ BOOLEAN PlusSign;
+} CCK_TX_POWER_CALIBRATE, *PCCK_TX_POWER_CALIBRATE;
+
+//
+// Receive Tuple Cache Format
+//
+typedef struct _TUPLE_CACHE {
+ BOOLEAN Valid;
+ UCHAR MacAddress[MAC_ADDR_LEN];
+ USHORT Sequence;
+ USHORT Frag;
+} TUPLE_CACHE, *PTUPLE_CACHE;
+
+//
+// Fragment Frame structure
+//
+typedef struct _FRAGMENT_FRAME {
+ PNDIS_PACKET pFragPacket;
+ ULONG RxSize;
+ USHORT Sequence;
+ USHORT LastFrag;
+ ULONG Flags; // Some extra frame information. bit 0: LLC presented
+} FRAGMENT_FRAME, *PFRAGMENT_FRAME;
+
+
+//
+// Packet information for NdisQueryPacket
+//
+typedef struct _PACKET_INFO {
+ UINT PhysicalBufferCount; // Physical breaks of buffer descripor chained
+ UINT BufferCount ; // Number of Buffer descriptor chained
+ UINT TotalPacketLength ; // Self explained
+ PNDIS_BUFFER pFirstBuffer; // Pointer to first buffer descriptor
+} PACKET_INFO, *PPACKET_INFO;
+
+//
+// Tkip Key structure which RC4 key & MIC calculation
+//
+typedef struct _TKIP_KEY_INFO {
+ UINT nBytesInM; // # bytes in M for MICKEY
+ ULONG IV16;
+ ULONG IV32;
+ ULONG K0; // for MICKEY Low
+ ULONG K1; // for MICKEY Hig
+ ULONG L; // Current state for MICKEY
+ ULONG R; // Current state for MICKEY
+ ULONG M; // Message accumulator for MICKEY
+ UCHAR RC4KEY[16];
+ UCHAR MIC[8];
+} TKIP_KEY_INFO, *PTKIP_KEY_INFO;
+
+//
+// Private / Misc data, counters for driver internal use
+//
+typedef struct __PRIVATE_STRUC {
+ UINT SystemResetCnt; // System reset counter
+ UINT TxRingFullCnt; // Tx ring full occurrance number
+ UINT PhyRxErrCnt; // PHY Rx error count, for debug purpose, might move to global counter
+ // Variables for WEP encryption / decryption in rtmp_wep.c
+ UINT FCSCRC32;
+ ARCFOURCONTEXT WEPCONTEXT;
+ // Tkip stuff
+ TKIP_KEY_INFO Tx;
+ TKIP_KEY_INFO Rx;
+} PRIVATE_STRUC, *PPRIVATE_STRUC;
+
+// structure to tune BBP R66 (BBP TUNING)
+typedef struct _BBP_R66_TUNING {
+ BOOLEAN bEnable;
+ USHORT FalseCcaLowerThreshold; // default 100
+ USHORT FalseCcaUpperThreshold; // default 512
+ UCHAR R66Delta;
+ UCHAR R66CurrentValue;
+ BOOLEAN R66LowerUpperSelect; //Before LinkUp, Used LowerBound or UpperBound as R66 value.
+} BBP_R66_TUNING, *PBBP_R66_TUNING;
+
+// structure to store channel TX power
+typedef struct _CHANNEL_TX_POWER {
+ USHORT RemainingTimeForUse; //unit: sec
+ UCHAR Channel;
+#ifdef DOT11N_DRAFT3
+ BOOLEAN bEffectedChannel; // For BW 40 operating in 2.4GHz , the "effected channel" is the channel that is covered in 40Mhz.
+#endif // DOT11N_DRAFT3 //
+ CHAR Power;
+ CHAR Power2;
+ UCHAR MaxTxPwr;
+ UCHAR DfsReq;
+} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER;
+
+// structure to store 802.11j channel TX power
+typedef struct _CHANNEL_11J_TX_POWER {
+ UCHAR Channel;
+ UCHAR BW; // BW_10 or BW_20
+ CHAR Power;
+ CHAR Power2;
+ USHORT RemainingTimeForUse; //unit: sec
+} CHANNEL_11J_TX_POWER, *PCHANNEL_11J_TX_POWER;
+
+typedef enum _ABGBAND_STATE_ {
+ UNKNOWN_BAND,
+ BG_BAND,
+ A_BAND,
+} ABGBAND_STATE;
+
+typedef struct _MLME_STRUCT {
+#ifdef CONFIG_STA_SUPPORT
+ // STA state machines
+ STATE_MACHINE CntlMachine;
+ STATE_MACHINE AssocMachine;
+ STATE_MACHINE AuthMachine;
+ STATE_MACHINE AuthRspMachine;
+ STATE_MACHINE SyncMachine;
+ STATE_MACHINE WpaPskMachine;
+ STATE_MACHINE LeapMachine;
+ STATE_MACHINE AironetMachine;
+ STATE_MACHINE_FUNC AssocFunc[ASSOC_FUNC_SIZE];
+ STATE_MACHINE_FUNC AuthFunc[AUTH_FUNC_SIZE];
+ STATE_MACHINE_FUNC AuthRspFunc[AUTH_RSP_FUNC_SIZE];
+ STATE_MACHINE_FUNC SyncFunc[SYNC_FUNC_SIZE];
+ STATE_MACHINE_FUNC WpaPskFunc[WPA_PSK_FUNC_SIZE];
+ STATE_MACHINE_FUNC AironetFunc[AIRONET_FUNC_SIZE];
+#endif // CONFIG_STA_SUPPORT //
+ STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE];
+ // Action
+ STATE_MACHINE ActMachine;
+
+
+#ifdef QOS_DLS_SUPPORT
+ STATE_MACHINE DlsMachine;
+ STATE_MACHINE_FUNC DlsFunc[DLS_FUNC_SIZE];
+#endif // QOS_DLS_SUPPORT //
+
+
+
+
+ ULONG ChannelQuality; // 0..100, Channel Quality Indication for Roaming
+ ULONG Now32; // latch the value of NdisGetSystemUpTime()
+ ULONG LastSendNULLpsmTime;
+
+ BOOLEAN bRunning;
+ NDIS_SPIN_LOCK TaskLock;
+ MLME_QUEUE Queue;
+
+ UINT ShiftReg;
+
+ RALINK_TIMER_STRUCT PeriodicTimer;
+ RALINK_TIMER_STRUCT APSDPeriodicTimer;
+ RALINK_TIMER_STRUCT LinkDownTimer;
+ RALINK_TIMER_STRUCT LinkUpTimer;
+#ifdef RT2860
+ UCHAR bPsPollTimerRunning;
+ RALINK_TIMER_STRUCT PsPollTimer;
+ RALINK_TIMER_STRUCT RadioOnOffTimer;
+#endif // RT2860 //
+ ULONG PeriodicRound;
+ ULONG OneSecPeriodicRound;
+
+ UCHAR RealRxPath;
+ BOOLEAN bLowThroughput;
+ BOOLEAN bEnableAutoAntennaCheck;
+ RALINK_TIMER_STRUCT RxAntEvalTimer;
+
+
+} MLME_STRUCT, *PMLME_STRUCT;
+
+// structure for radar detection and channel switch
+typedef struct _RADAR_DETECT_STRUCT {
+ UCHAR CSCount; //Channel switch counter
+ UCHAR CSPeriod; //Channel switch period (beacon count)
+ UCHAR RDCount; //Radar detection counter
+ UCHAR RDMode; //Radar Detection mode
+ UCHAR RDDurRegion; //Radar detection duration region
+ UCHAR BBPR16;
+ UCHAR BBPR17;
+ UCHAR BBPR18;
+ UCHAR BBPR21;
+ UCHAR BBPR22;
+ UCHAR BBPR64;
+ ULONG InServiceMonitorCount; // unit: sec
+ UINT8 DfsSessionTime;
+ BOOLEAN bFastDfs;
+ UINT8 ChMovingTime;
+ UINT8 LongPulseRadarTh;
+} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT;
+
+#ifdef CARRIER_DETECTION_SUPPORT
+typedef enum CD_STATE_n
+{
+ CD_NORMAL,
+ CD_SILENCE,
+ CD_MAX_STATE
+} CD_STATE;
+
+typedef struct CARRIER_DETECTION_s
+{
+ BOOLEAN Enable;
+ UINT8 CDSessionTime;
+ UINT8 CDPeriod;
+ CD_STATE CD_State;
+} CARRIER_DETECTION, *PCARRIER_DETECTION;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+typedef enum _REC_BLOCKACK_STATUS
+{
+ Recipient_NONE=0,
+ Recipient_USED,
+ Recipient_HandleRes,
+ Recipient_Accept
+} REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS;
+
+typedef enum _ORI_BLOCKACK_STATUS
+{
+ Originator_NONE=0,
+ Originator_USED,
+ Originator_WaitRes,
+ Originator_Done
+} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS;
+
+#ifdef DOT11_N_SUPPORT
+typedef struct _BA_ORI_ENTRY{
+ UCHAR Wcid;
+ UCHAR TID;
+ UCHAR BAWinSize;
+ UCHAR Token;
+// Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header.
+ USHORT Sequence;
+ USHORT TimeOutValue;
+ ORI_BLOCKACK_STATUS ORI_BA_Status;
+ RALINK_TIMER_STRUCT ORIBATimer;
+ PVOID pAdapter;
+} BA_ORI_ENTRY, *PBA_ORI_ENTRY;
+
+typedef struct _BA_REC_ENTRY {
+ UCHAR Wcid;
+ UCHAR TID;
+ UCHAR BAWinSize; // 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU.
+ USHORT LastIndSeq;
+ USHORT TimeOutValue;
+ RALINK_TIMER_STRUCT RECBATimer;
+ ULONG LastIndSeqAtTimer;
+ ULONG nDropPacket;
+ ULONG rcvSeq;
+ REC_BLOCKACK_STATUS REC_BA_Status;
+ NDIS_SPIN_LOCK RxReRingLock; // Rx Ring spinlock
+ PVOID pAdapter;
+ struct reordering_list list;
+} BA_REC_ENTRY, *PBA_REC_ENTRY;
+
+
+typedef struct {
+ ULONG numAsRecipient; // I am recipient of numAsRecipient clients. These client are in the BARecEntry[]
+ ULONG numAsOriginator; // I am originator of numAsOriginator clients. These clients are in the BAOriEntry[]
+ BA_ORI_ENTRY BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE];
+ BA_REC_ENTRY BARecEntry[MAX_LEN_OF_BA_REC_TABLE];
+} BA_TABLE, *PBA_TABLE;
+
+//For QureyBATableOID use;
+typedef struct PACKED _OID_BA_REC_ENTRY{
+ UCHAR MACAddr[MAC_ADDR_LEN];
+ UCHAR BaBitmap; // if (BaBitmap&(1<<TID)), this session with{MACAddr, TID}exists, so read BufSize[TID] for BufferSize
+ UCHAR rsv;
+ UCHAR BufSize[8];
+ REC_BLOCKACK_STATUS REC_BA_Status[8];
+} OID_BA_REC_ENTRY, *POID_BA_REC_ENTRY;
+
+//For QureyBATableOID use;
+typedef struct PACKED _OID_BA_ORI_ENTRY{
+ UCHAR MACAddr[MAC_ADDR_LEN];
+ UCHAR BaBitmap; // if (BaBitmap&(1<<TID)), this session with{MACAddr, TID}exists, so read BufSize[TID] for BufferSize, read ORI_BA_Status[TID] for status
+ UCHAR rsv;
+ UCHAR BufSize[8];
+ ORI_BLOCKACK_STATUS ORI_BA_Status[8];
+} OID_BA_ORI_ENTRY, *POID_BA_ORI_ENTRY;
+
+typedef struct _QUERYBA_TABLE{
+ OID_BA_ORI_ENTRY BAOriEntry[32];
+ OID_BA_REC_ENTRY BARecEntry[32];
+ UCHAR OriNum;// Number of below BAOriEntry
+ UCHAR RecNum;// Number of below BARecEntry
+} QUERYBA_TABLE, *PQUERYBA_TABLE;
+
+typedef union _BACAP_STRUC {
+#ifdef RT_BIG_ENDIAN
+ struct {
+ UINT32 :4;
+ UINT32 b2040CoexistScanSup:1; //As Sta, support do 2040 coexistence scan for AP. As Ap, support monitor trigger event to check if can use BW 40MHz.
+ UINT32 bHtAdhoc:1; // adhoc can use ht rate.
+ UINT32 MMPSmode:2; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable
+ UINT32 AmsduSize:1; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935};
+ UINT32 AmsduEnable:1; //Enable AMSDU transmisstion
+ UINT32 MpduDensity:3;
+ UINT32 Policy:2; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use
+ UINT32 AutoBA:1; // automatically BA
+ UINT32 TxBAWinLimit:8;
+ UINT32 RxBAWinLimit:8;
+ } field;
+#else
+ struct {
+ UINT32 RxBAWinLimit:8;
+ UINT32 TxBAWinLimit:8;
+ UINT32 AutoBA:1; // automatically BA
+ UINT32 Policy:2; // 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use
+ UINT32 MpduDensity:3;
+ UINT32 AmsduEnable:1; //Enable AMSDU transmisstion
+ UINT32 AmsduSize:1; // 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935};
+ UINT32 MMPSmode:2; // MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable
+ UINT32 bHtAdhoc:1; // adhoc can use ht rate.
+ UINT32 b2040CoexistScanSup:1; //As Sta, support do 2040 coexistence scan for AP. As Ap, support monitor trigger event to check if can use BW 40MHz.
+ UINT32 :4;
+ } field;
+#endif
+ UINT32 word;
+} BACAP_STRUC, *PBACAP_STRUC;
+#endif // DOT11_N_SUPPORT //
+
+//This structure is for all 802.11n card InterOptibilityTest action. Reset all Num every n second. (Details see MLMEPeriodic)
+typedef struct _IOT_STRUC {
+ UCHAR Threshold[2];
+ UCHAR ReorderTimeOutNum[MAX_LEN_OF_BA_REC_TABLE]; // compare with threshold[0]
+ UCHAR RefreshNum[MAX_LEN_OF_BA_REC_TABLE]; // compare with threshold[1]
+ ULONG OneSecInWindowCount;
+ ULONG OneSecFrameDuplicateCount;
+ ULONG OneSecOutWindowCount;
+ UCHAR DelOriAct;
+ UCHAR DelRecAct;
+ UCHAR RTSShortProt;
+ UCHAR RTSLongProt;
+ BOOLEAN bRTSLongProtOn;
+#ifdef CONFIG_STA_SUPPORT
+ BOOLEAN bLastAtheros;
+ BOOLEAN bCurrentAtheros;
+ BOOLEAN bNowAtherosBurstOn;
+ BOOLEAN bNextDisableRxBA;
+ BOOLEAN bToggle;
+#endif // CONFIG_STA_SUPPORT //
+} IOT_STRUC, *PIOT_STRUC;
+
+// This is the registry setting for 802.11n transmit setting. Used in advanced page.
+typedef union _REG_TRANSMIT_SETTING {
+#ifdef RT_BIG_ENDIAN
+ struct {
+ UINT32 rsv:13;
+ UINT32 EXTCHA:2;
+ UINT32 HTMODE:1;
+ UINT32 TRANSNO:2;
+ UINT32 STBC:1; //SPACE
+ UINT32 ShortGI:1;
+ UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz
+ UINT32 TxBF:1; // 3*3
+ UINT32 rsv0:10;
+ } field;
+#else
+ struct {
+ UINT32 rsv0:10;
+ UINT32 TxBF:1;
+ UINT32 BW:1; //channel bandwidth 20MHz or 40 MHz
+ UINT32 ShortGI:1;
+ UINT32 STBC:1; //SPACE
+ UINT32 TRANSNO:2;
+ UINT32 HTMODE:1;
+ UINT32 EXTCHA:2;
+ UINT32 rsv:13;
+ } field;
+#endif
+ UINT32 word;
+} REG_TRANSMIT_SETTING, *PREG_TRANSMIT_SETTING;
+
+typedef union _DESIRED_TRANSMIT_SETTING {
+#ifdef RT_BIG_ENDIAN
+ struct {
+ USHORT rsv:3;
+ USHORT FixedTxMode:2; // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode.
+ USHORT PhyMode:4;
+ USHORT MCS:7; // MCS
+ } field;
+#else
+ struct {
+ USHORT MCS:7; // MCS
+ USHORT PhyMode:4;
+ USHORT FixedTxMode:2; // If MCS isn't AUTO, fix rate in CCK, OFDM or HT mode.
+ USHORT rsv:3;
+ } field;
+#endif
+ USHORT word;
+ } DESIRED_TRANSMIT_SETTING, *PDESIRED_TRANSMIT_SETTING;
+
+typedef struct {
+ BOOLEAN IsRecipient;
+ UCHAR MACAddr[MAC_ADDR_LEN];
+ UCHAR TID;
+ UCHAR nMSDU;
+ USHORT TimeOut;
+ BOOLEAN bAllTid; // If True, delete all TID for BA sessions with this MACaddr.
+} OID_ADD_BA_ENTRY, *POID_ADD_BA_ENTRY;
+
+//
+// Multiple SSID structure
+//
+#define WLAN_MAX_NUM_OF_TIM ((MAX_LEN_OF_MAC_TABLE >> 3) + 1) /* /8 + 1 */
+#define WLAN_CT_TIM_BCMC_OFFSET 0 /* unit: 32B */
+
+/* clear bcmc TIM bit */
+#define WLAN_MR_TIM_BCMC_CLEAR(apidx) \
+ pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] &= ~BIT8[0];
+
+/* set bcmc TIM bit */
+#define WLAN_MR_TIM_BCMC_SET(apidx) \
+ pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] |= BIT8[0];
+
+/* clear a station PS TIM bit */
+#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, wcid) \
+ { UCHAR tim_offset = wcid >> 3; \
+ UCHAR bit_offset = wcid & 0x7; \
+ ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~BIT8[bit_offset]); }
+
+/* set a station PS TIM bit */
+#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, wcid) \
+ { UCHAR tim_offset = wcid >> 3; \
+ UCHAR bit_offset = wcid & 0x7; \
+ ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= BIT8[bit_offset]; }
+
+
+typedef struct _MULTISSID_STRUCT {
+ UCHAR Bssid[MAC_ADDR_LEN];
+ UCHAR SsidLen;
+ CHAR Ssid[MAX_LEN_OF_SSID];
+ USHORT CapabilityInfo;
+
+ PNET_DEV MSSIDDev;
+
+ NDIS_802_11_AUTHENTICATION_MODE AuthMode;
+ NDIS_802_11_WEP_STATUS WepStatus;
+ NDIS_802_11_WEP_STATUS GroupKeyWepStatus;
+ WPA_MIX_PAIR_CIPHER WpaMixPairCipher;
+
+ ULONG TxCount;
+ ULONG RxCount;
+ ULONG ReceivedByteCount;
+ ULONG TransmittedByteCount;
+ ULONG RxErrorCount;
+ ULONG RxDropCount;
+
+ HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI.
+ RT_HT_PHY_INFO DesiredHtPhyInfo;
+ DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting. this is for reading registry setting only. not useful.
+ BOOLEAN bAutoTxRateSwitch;
+
+ UCHAR DefaultKeyId;
+
+ UCHAR TxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11, ...
+ UCHAR DesiredRates[MAX_LEN_OF_SUPPORTED_RATES];// OID_802_11_DESIRED_RATES
+ UCHAR DesiredRatesIndex;
+ UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11
+
+ UCHAR TimBitmaps[WLAN_MAX_NUM_OF_TIM];
+
+ // WPA
+ UCHAR GMK[32];
+ UCHAR PMK[32];
+ UCHAR GTK[32];
+ BOOLEAN IEEE8021X;
+ BOOLEAN PreAuth;
+ UCHAR GNonce[32];
+ UCHAR PortSecured;
+ NDIS_802_11_PRIVACY_FILTER PrivacyFilter;
+ UCHAR BANClass3Data;
+ ULONG IsolateInterStaTraffic;
+
+ UCHAR RSNIE_Len[2];
+ UCHAR RSN_IE[2][MAX_LEN_OF_RSNIE];
+
+
+ UCHAR TimIELocationInBeacon;
+ UCHAR CapabilityInfoLocationInBeacon;
+ // outgoing BEACON frame buffer and corresponding TXWI
+ // PTXWI_STRUC BeaconTxWI; //
+ CHAR BeaconBuf[MAX_BEACON_SIZE]; // NOTE: BeaconBuf should be 4-byte aligned
+
+ BOOLEAN bHideSsid;
+ UINT16 StationKeepAliveTime; // unit: second
+
+ USHORT VLAN_VID;
+ USHORT VLAN_Priority;
+
+ RT_802_11_ACL AccessControlList;
+
+ // EDCA Qos
+ BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM
+ BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS
+
+ UCHAR DlsPTK[64]; // Due to windows dirver count on meetinghouse to handle 4-way shake
+
+ // For 802.1x daemon setting per BSS
+ UCHAR radius_srv_num;
+ RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM];
+
+#ifdef RTL865X_SOC
+ unsigned int mylinkid;
+#endif
+
+
+ UINT32 RcvdConflictSsidCount;
+ UINT32 RcvdSpoofedAssocRespCount;
+ UINT32 RcvdSpoofedReassocRespCount;
+ UINT32 RcvdSpoofedProbeRespCount;
+ UINT32 RcvdSpoofedBeaconCount;
+ UINT32 RcvdSpoofedDisassocCount;
+ UINT32 RcvdSpoofedAuthCount;
+ UINT32 RcvdSpoofedDeauthCount;
+ UINT32 RcvdSpoofedUnknownMgmtCount;
+ UINT32 RcvdReplayAttackCount;
+
+ CHAR RssiOfRcvdConflictSsid;
+ CHAR RssiOfRcvdSpoofedAssocResp;
+ CHAR RssiOfRcvdSpoofedReassocResp;
+ CHAR RssiOfRcvdSpoofedProbeResp;
+ CHAR RssiOfRcvdSpoofedBeacon;
+ CHAR RssiOfRcvdSpoofedDisassoc;
+ CHAR RssiOfRcvdSpoofedAuth;
+ CHAR RssiOfRcvdSpoofedDeauth;
+ CHAR RssiOfRcvdSpoofedUnknownMgmt;
+ CHAR RssiOfRcvdReplayAttack;
+
+ BOOLEAN bBcnSntReq;
+ UCHAR BcnBufIdx;
+} MULTISSID_STRUCT, *PMULTISSID_STRUCT;
+
+
+
+#ifdef DOT11N_DRAFT3
+typedef enum _BSS2040COEXIST_FLAG{
+ BSS_2040_COEXIST_DISABLE = 0,
+ BSS_2040_COEXIST_TIMER_FIRED = 1,
+ BSS_2040_COEXIST_INFO_SYNC = 2,
+ BSS_2040_COEXIST_INFO_NOTIFY = 4,
+}BSS2040COEXIST_FLAG;
+#endif // DOT11N_DRAFT3 //
+
+// configuration common to OPMODE_AP as well as OPMODE_STA
+typedef struct _COMMON_CONFIG {
+
+ BOOLEAN bCountryFlag;
+ UCHAR CountryCode[3];
+ UCHAR Geography;
+ UCHAR CountryRegion; // Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel
+ UCHAR CountryRegionForABand; // Enum of country region for A band
+ UCHAR PhyMode; // PHY_11A, PHY_11B, PHY_11BG_MIXED, PHY_ABG_MIXED
+ USHORT Dsifs; // in units of usec
+ ULONG PacketFilter; // Packet filter for receiving
+
+ CHAR Ssid[MAX_LEN_OF_SSID]; // NOT NULL-terminated
+ UCHAR SsidLen; // the actual ssid length in used
+ UCHAR LastSsidLen; // the actual ssid length in used
+ CHAR LastSsid[MAX_LEN_OF_SSID]; // NOT NULL-terminated
+ UCHAR LastBssid[MAC_ADDR_LEN];
+
+ UCHAR Bssid[MAC_ADDR_LEN];
+ USHORT BeaconPeriod;
+ UCHAR Channel;
+ UCHAR CentralChannel; // Central Channel when using 40MHz is indicating. not real channel.
+
+ UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR SupRateLen;
+ UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR ExtRateLen;
+ UCHAR DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; // OID_802_11_DESIRED_RATES
+ UCHAR MaxDesiredRate;
+ UCHAR ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES];
+
+ ULONG BasicRateBitmap; // backup basic ratebitmap
+
+ BOOLEAN bAPSDCapable;
+ BOOLEAN bInServicePeriod;
+ BOOLEAN bAPSDAC_BE;
+ BOOLEAN bAPSDAC_BK;
+ BOOLEAN bAPSDAC_VI;
+ BOOLEAN bAPSDAC_VO;
+ BOOLEAN bNeedSendTriggerFrame;
+ BOOLEAN bAPSDForcePowerSave; // Force power save mode, should only use in APSD-STAUT
+ ULONG TriggerTimerCount;
+ UCHAR MaxSPLength;
+ UCHAR BBPCurrentBW; // BW_10, BW_20, BW_40
+ REG_TRANSMIT_SETTING RegTransmitSetting; //registry transmit setting. this is for reading registry setting only. not useful.
+ UCHAR TxRate; // Same value to fill in TXD. TxRate is 6-bit
+ UCHAR MaxTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11
+ UCHAR TxRateIndex; // Tx rate index in RateSwitchTable
+ UCHAR TxRateTableSize; // Valid Tx rate table size in RateSwitchTable
+ UCHAR MinTxRate; // RATE_1, RATE_2, RATE_5_5, RATE_11
+ UCHAR RtsRate; // RATE_xxx
+ HTTRANSMIT_SETTING MlmeTransmit; // MGMT frame PHY rate setting when operatin at Ht rate.
+ UCHAR MlmeRate; // RATE_xxx, used to send MLME frames
+ UCHAR BasicMlmeRate; // Default Rate for sending MLME frames
+
+ USHORT RtsThreshold; // in unit of BYTE
+ USHORT FragmentThreshold; // in unit of BYTE
+
+ UCHAR TxPower; // in unit of mW
+ ULONG TxPowerPercentage; // 0~100 %
+ ULONG TxPowerDefault; // keep for TxPowerPercentage
+
+#ifdef DOT11_N_SUPPORT
+ BACAP_STRUC BACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0
+ BACAP_STRUC REGBACapability; // NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0
+#endif // DOT11_N_SUPPORT //
+ IOT_STRUC IOTestParm; // 802.11n InterOpbility Test Parameter;
+ ULONG TxPreamble; // Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto
+ BOOLEAN bUseZeroToDisableFragment; // Microsoft use 0 as disable
+ ULONG UseBGProtection; // 0: auto, 1: always use, 2: always not use
+ BOOLEAN bUseShortSlotTime; // 0: disable, 1 - use short slot (9us)
+ BOOLEAN bEnableTxBurst; // 1: enble TX PACKET BURST, 0: disable TX PACKET BURST
+ BOOLEAN bAggregationCapable; // 1: enable TX aggregation when the peer supports it
+ BOOLEAN bPiggyBackCapable; // 1: enable TX piggy-back according MAC's version
+ BOOLEAN bIEEE80211H; // 1: enable IEEE802.11h spec.
+ ULONG DisableOLBCDetect; // 0: enable OLBC detect; 1 disable OLBC detect
+
+#ifdef DOT11_N_SUPPORT
+ BOOLEAN bRdg;
+#endif // DOT11_N_SUPPORT //
+ BOOLEAN bWmmCapable; // 0:disable WMM, 1:enable WMM
+ QOS_CAPABILITY_PARM APQosCapability; // QOS capability of the current associated AP
+ EDCA_PARM APEdcaParm; // EDCA parameters of the current associated AP
+ QBSS_LOAD_PARM APQbssLoad; // QBSS load of the current associated AP
+ UCHAR AckPolicy[4]; // ACK policy of the specified AC. see ACK_xxx
+#ifdef CONFIG_STA_SUPPORT
+ BOOLEAN bDLSCapable; // 0:disable DLS, 1:enable DLS
+#endif // CONFIG_STA_SUPPORT //
+ // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular
+ // BOOLEAN control, either ON or OFF. These flags should always be accessed via
+ // OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros.
+ // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition
+ ULONG OpStatusFlags;
+
+ BOOLEAN NdisRadioStateOff; //For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff.
+ ABGBAND_STATE BandState; // For setting BBP used on B/G or A mode.
+
+ // IEEE802.11H--DFS.
+ RADAR_DETECT_STRUCT RadarDetect;
+
+#ifdef CARRIER_DETECTION_SUPPORT
+ CARRIER_DETECTION CarrierDetect;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+ // HT
+ UCHAR BASize; // USer desired BAWindowSize. Should not exceed our max capability
+ //RT_HT_CAPABILITY SupportedHtPhy;
+ RT_HT_CAPABILITY DesiredHtPhy;
+ HT_CAPABILITY_IE HtCapability;
+ ADD_HT_INFO_IE AddHTInfo; // Useful as AP.
+ //This IE is used with channel switch announcement element when changing to a new 40MHz.
+ //This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp.
+ NEW_EXT_CHAN_IE NewExtChanOffset; //7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present
+
+#ifdef DOT11N_DRAFT3
+ UCHAR Bss2040CoexistFlag; // bit 0: bBssCoexistTimerRunning, bit 1: NeedSyncAddHtInfo.
+ RALINK_TIMER_STRUCT Bss2040CoexistTimer;
+
+ //This IE is used for 20/40 BSS Coexistence.
+ BSS_2040_COEXIST_IE BSS2040CoexistInfo;
+ // ====== 11n D3.0 =======================>
+ USHORT Dot11OBssScanPassiveDwell; // Unit : TU. 5~1000
+ USHORT Dot11OBssScanActiveDwell; // Unit : TU. 10~1000
+ USHORT Dot11BssWidthTriggerScanInt; // Unit : Second
+ USHORT Dot11OBssScanPassiveTotalPerChannel; // Unit : TU. 200~10000
+ USHORT Dot11OBssScanActiveTotalPerChannel; // Unit : TU. 20~10000
+ USHORT Dot11BssWidthChanTranDelayFactor;
+ USHORT Dot11OBssScanActivityThre; // Unit : percentage
+
+ ULONG Dot11BssWidthChanTranDelay; // multiple of (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor)
+ ULONG CountDownCtr; // CountDown Counter from (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor)
+
+ NDIS_SPIN_LOCK TriggerEventTabLock;
+ BSS_2040_COEXIST_IE LastBSSCoexist2040;
+ BSS_2040_COEXIST_IE BSSCoexist2040;
+ TRIGGER_EVENT_TAB TriggerEventTab;
+ UCHAR ChannelListIdx;
+ // <====== 11n D3.0 =======================
+ BOOLEAN bOverlapScanning;
+#endif // DOT11N_DRAFT3 //
+
+ BOOLEAN bHTProtect;
+ BOOLEAN bMIMOPSEnable;
+ BOOLEAN bBADecline;
+ BOOLEAN bDisableReordering;
+ BOOLEAN bForty_Mhz_Intolerant;
+ BOOLEAN bExtChannelSwitchAnnouncement;
+ BOOLEAN bRcvBSSWidthTriggerEvents;
+ ULONG LastRcvBSSWidthTriggerEventsTime;
+
+ UCHAR TxBASize;
+#endif // DOT11_N_SUPPORT //
+
+ // Enable wireless event
+ BOOLEAN bWirelessEvent;
+ BOOLEAN bWiFiTest; // Enable this parameter for WiFi test
+
+ // Tx & Rx Stream number selection
+ UCHAR TxStream;
+ UCHAR RxStream;
+
+ // transmit phy mode, trasmit rate for Multicast.
+#ifdef MCAST_RATE_SPECIFIC
+ UCHAR McastTransmitMcs;
+ UCHAR McastTransmitPhyMode;
+#endif // MCAST_RATE_SPECIFIC //
+
+ BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled
+
+
+
+ NDIS_SPIN_LOCK MeasureReqTabLock;
+ PMEASURE_REQ_TAB pMeasureReqTab;
+
+ NDIS_SPIN_LOCK TpcReqTabLock;
+ PTPC_REQ_TAB pTpcReqTab;
+
+ // transmit phy mode, trasmit rate for Multicast.
+#ifdef MCAST_RATE_SPECIFIC
+ HTTRANSMIT_SETTING MCastPhyMode;
+#endif // MCAST_RATE_SPECIFIC //
+
+#ifdef SINGLE_SKU
+ UINT16 DefineMaxTxPwr;
+#endif // SINGLE_SKU //
+
+
+} COMMON_CONFIG, *PCOMMON_CONFIG;
+
+
+#ifdef CONFIG_STA_SUPPORT
+/* Modified by Wu Xi-Kun 4/21/2006 */
+// STA configuration and status
+typedef struct _STA_ADMIN_CONFIG {
+ // GROUP 1 -
+ // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe
+ // the user intended configuration, but not necessary fully equal to the final
+ // settings in ACTIVE BSS after negotiation/compromize with the BSS holder (either
+ // AP or IBSS holder).
+ // Once initialized, user configuration can only be changed via OID_xxx
+ UCHAR BssType; // BSS_INFRA or BSS_ADHOC
+ USHORT AtimWin; // used when starting a new IBSS
+
+ // GROUP 2 -
+ // User configuration loaded from Registry, E2PROM or OID_xxx. These settings describe
+ // the user intended configuration, and should be always applied to the final
+ // settings in ACTIVE BSS without compromising with the BSS holder.
+ // Once initialized, user configuration can only be changed via OID_xxx
+ UCHAR RssiTrigger;
+ UCHAR RssiTriggerMode; // RSSI_TRIGGERED_UPON_BELOW_THRESHOLD or RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD
+ USHORT DefaultListenCount; // default listen count;
+ ULONG WindowsPowerMode; // Power mode for AC power
+ ULONG WindowsBatteryPowerMode; // Power mode for battery if exists
+ BOOLEAN bWindowsACCAMEnable; // Enable CAM power mode when AC on
+ BOOLEAN bAutoReconnect; // Set to TRUE when setting OID_802_11_SSID with no matching BSSID
+ ULONG WindowsPowerProfile; // Windows power profile, for NDIS5.1 PnP
+
+ // MIB:ieee802dot11.dot11smt(1).dot11StationConfigTable(1)
+ USHORT Psm; // power management mode (PWR_ACTIVE|PWR_SAVE)
+ USHORT DisassocReason;
+ UCHAR DisassocSta[MAC_ADDR_LEN];
+ USHORT DeauthReason;
+ UCHAR DeauthSta[MAC_ADDR_LEN];
+ USHORT AuthFailReason;
+ UCHAR AuthFailSta[MAC_ADDR_LEN];
+
+ NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X
+ NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined
+ NDIS_802_11_WEP_STATUS WepStatus;
+ NDIS_802_11_WEP_STATUS OrigWepStatus; // Original wep status set from OID
+
+ // Add to support different cipher suite for WPA2/WPA mode
+ NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite
+ NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite
+ BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites
+ USHORT RsnCapability;
+
+ NDIS_802_11_WEP_STATUS GroupKeyWepStatus;
+
+ UCHAR PMK[32]; // WPA PSK mode PMK
+ UCHAR PTK[64]; // WPA PSK mode PTK
+ UCHAR GTK[32]; // GTK from authenticator
+ BSSID_INFO SavedPMK[PMKID_NO];
+ UINT SavedPMKNum; // Saved PMKID number
+
+ UCHAR DefaultKeyId;
+
+
+ // WPA 802.1x port control, WPA_802_1X_PORT_SECURED, WPA_802_1X_PORT_NOT_SECURED
+ UCHAR PortSecured;
+
+ // For WPA countermeasures
+ ULONG LastMicErrorTime; // record last MIC error time
+ ULONG MicErrCnt; // Should be 0, 1, 2, then reset to zero (after disassoiciation).
+ BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred.
+ // For WPA-PSK supplicant state
+ WPA_STATE WpaState; // Default is SS_NOTUSE and handled by microsoft 802.1x
+ UCHAR ReplayCounter[8];
+ UCHAR ANonce[32]; // ANonce for WPA-PSK from aurhenticator
+ UCHAR SNonce[32]; // SNonce for WPA-PSK
+
+ UCHAR LastSNR0; // last received BEACON's SNR
+ UCHAR LastSNR1; // last received BEACON's SNR for 2nd antenna
+ RSSI_SAMPLE RssiSample;
+ ULONG NumOfAvgRssiSample;
+
+ ULONG LastBeaconRxTime; // OS's timestamp of the last BEACON RX time
+ ULONG Last11bBeaconRxTime; // OS's timestamp of the last 11B BEACON RX time
+ ULONG Last11gBeaconRxTime; // OS's timestamp of the last 11G BEACON RX time
+ ULONG Last20NBeaconRxTime; // OS's timestamp of the last 20MHz N BEACON RX time
+
+ ULONG LastScanTime; // Record last scan time for issue BSSID_SCAN_LIST
+ ULONG ScanCnt; // Scan counts since most recent SSID, BSSID, SCAN OID request
+ BOOLEAN bSwRadio; // Software controlled Radio On/Off, TRUE: On
+ BOOLEAN bHwRadio; // Hardware controlled Radio On/Off, TRUE: On
+ BOOLEAN bRadio; // Radio state, And of Sw & Hw radio state
+ BOOLEAN bHardwareRadio; // Hardware controlled Radio enabled
+ BOOLEAN bShowHiddenSSID; // Show all known SSID in SSID list get operation
+
+ BOOLEAN AdhocBOnlyJoined; // Indicate Adhoc B Join.
+ BOOLEAN AdhocBGJoined; // Indicate Adhoc B/G Join.
+ BOOLEAN Adhoc20NJoined; // Indicate Adhoc 20MHz N Join.
+
+ // New for WPA, windows want us to to keep association information and
+ // Fixed IEs from last association response
+ NDIS_802_11_ASSOCIATION_INFORMATION AssocInfo;
+ USHORT ReqVarIELen; // Length of next VIE include EID & Length
+ UCHAR ReqVarIEs[MAX_VIE_LEN]; // The content saved here should be little-endian format.
+ USHORT ResVarIELen; // Length of next VIE include EID & Length
+ UCHAR ResVarIEs[MAX_VIE_LEN];
+
+ UCHAR RSNIE_Len;
+ UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be little-endian format.
+
+ // New variables used for CCX 1.0
+ BOOLEAN bCkipOn;
+ BOOLEAN bCkipCmicOn;
+ UCHAR CkipFlag;
+ UCHAR GIV[3]; //for CCX iv
+ UCHAR RxSEQ[4];
+ UCHAR TxSEQ[4];
+ UCHAR CKIPMIC[4];
+ UCHAR LeapAuthMode;
+ LEAP_AUTH_INFO LeapAuthInfo;
+ UCHAR HashPwd[16];
+ UCHAR NetworkChallenge[8];
+ UCHAR NetworkChallengeResponse[24];
+ UCHAR PeerChallenge[8];
+
+ UCHAR PeerChallengeResponse[24];
+ UCHAR SessionKey[16]; //Network session keys (NSK)
+ RALINK_TIMER_STRUCT LeapAuthTimer;
+ ROGUEAP_TABLE RogueApTab; //Cisco CCX1 Rogue AP Detection
+
+ // New control flags for CCX
+ CCX_CONTROL CCXControl; // Master administration state
+ BOOLEAN CCXEnable; // Actual CCX state
+ UCHAR CCXScanChannel; // Selected channel for CCX beacon request
+ USHORT CCXScanTime; // Time out to wait for beacon and probe response
+ UCHAR CCXReqType; // Current processing CCX request type
+ BSS_TABLE CCXBssTab; // BSS Table
+ UCHAR FrameReportBuf[2048]; // Buffer for creating frame report
+ USHORT FrameReportLen; // Current Frame report length
+ ULONG CLBusyBytes; // Save the total bytes received durning channel load scan time
+ USHORT RPIDensity[8]; // Array for RPI density collection
+ // Start address of each BSS table within FrameReportBuf
+ // It's important to update the RxPower of the corresponding Bss
+ USHORT BssReportOffset[MAX_LEN_OF_BSS_TABLE];
+ USHORT BeaconToken; // Token for beacon report
+ ULONG LastBssIndex; // Most current reported Bss index
+ RM_REQUEST_ACTION MeasurementRequest[16]; // Saved measurement request
+ UCHAR RMReqCnt; // Number of measurement request saved.
+ UCHAR CurrentRMReqIdx; // Number of measurement request saved.
+ BOOLEAN ParallelReq; // Parallel measurement, only one request performed,
+ // It must be the same channel with maximum duration
+ USHORT ParallelDuration; // Maximum duration for parallel measurement
+ UCHAR ParallelChannel; // Only one channel with parallel measurement
+ USHORT IAPPToken; // IAPP dialog token
+ UCHAR CCXQosECWMin; // Cisco QOS ECWMin for AC 0
+ UCHAR CCXQosECWMax; // Cisco QOS ECWMax for AC 0
+ // Hack for channel load and noise histogram parameters
+ UCHAR NHFactor; // Parameter for Noise histogram
+ UCHAR CLFactor; // Parameter for channel load
+
+ UCHAR KRK[16]; //Key Refresh Key.
+ UCHAR BTK[32]; //Base Transient Key
+ BOOLEAN CCKMLinkUpFlag;
+ ULONG CCKMRN; //(Re)Association request number.
+ LARGE_INTEGER CCKMBeaconAtJoinTimeStamp; //TSF timer for Re-assocaite to the new AP
+ UCHAR AironetCellPowerLimit; //in dBm
+ UCHAR AironetIPAddress[4]; //eg. 192.168.1.1
+ BOOLEAN CCXAdjacentAPReportFlag; //flag for determining report Assoc Lost time
+ CHAR CCXAdjacentAPSsid[MAX_LEN_OF_SSID]; //Adjacent AP's SSID report
+ UCHAR CCXAdjacentAPSsidLen; // the actual ssid length in used
+ UCHAR CCXAdjacentAPBssid[MAC_ADDR_LEN]; //Adjacent AP's BSSID report
+ USHORT CCXAdjacentAPChannel;
+ ULONG CCXAdjacentAPLinkDownTime; //for Spec S32.
+
+ RALINK_TIMER_STRUCT StaQuickResponeForRateUpTimer;
+ BOOLEAN StaQuickResponeForRateUpTimerRunning;
+
+ UCHAR DtimCount; // 0.. DtimPeriod-1
+ UCHAR DtimPeriod; // default = 3
+
+#ifdef QOS_DLS_SUPPORT
+ RT_802_11_DLS DLSEntry[MAX_NUM_OF_DLS_ENTRY];
+ UCHAR DlsReplayCounter[8];
+#endif // QOS_DLS_SUPPORT //
+ ////////////////////////////////////////////////////////////////////////////////////////
+ // This is only for WHQL test.
+ BOOLEAN WhqlTest;
+ ////////////////////////////////////////////////////////////////////////////////////////
+
+ RALINK_TIMER_STRUCT WpaDisassocAndBlockAssocTimer;
+ // Fast Roaming
+ BOOLEAN bFastRoaming; // 0:disable fast roaming, 1:enable fast roaming
+ CHAR dBmToRoam; // the condition to roam when receiving Rssi less than this value. It's negative value.
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+ BOOLEAN IEEE8021X;
+ BOOLEAN IEEE8021x_required_keys;
+ CIPHER_KEY DesireSharedKey[4]; // Record user desired WEP keys
+ UCHAR DesireSharedKeyId;
+
+ // 0: driver ignores wpa_supplicant
+ // 1: wpa_supplicant initiates scanning and AP selection
+ // 2: driver takes care of scanning, AP selection, and IEEE 802.11 association parameters
+ UCHAR WpaSupplicantUP;
+ UCHAR WpaSupplicantScanCount;
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+ CHAR dev_name[16];
+ USHORT OriDevType;
+
+ BOOLEAN bTGnWifiTest;
+ BOOLEAN bScanReqIsFromWebUI;
+
+ HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI.
+ DESIRED_TRANSMIT_SETTING DesiredTransmitSetting;
+ RT_HT_PHY_INFO DesiredHtPhyInfo;
+ BOOLEAN bAutoTxRateSwitch;
+
+#ifdef RT2860
+ UCHAR BBPR3;
+#endif // RT2860 //
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ UCHAR IEEE80211dClientMode;
+ UCHAR StaOriCountryCode[3];
+ UCHAR StaOriGeography;
+#endif // EXT_BUILD_CHANNEL_LIST //
+} STA_ADMIN_CONFIG, *PSTA_ADMIN_CONFIG;
+
+// This data structure keep the current active BSS/IBSS's configuration that this STA
+// had agreed upon joining the network. Which means these parameters are usually decided
+// by the BSS/IBSS creator instead of user configuration. Data in this data structurre
+// is valid only when either ADHOC_ON(pAd) or INFRA_ON(pAd) is TRUE.
+// Normally, after SCAN or failed roaming attempts, we need to recover back to
+// the current active settings.
+typedef struct _STA_ACTIVE_CONFIG {
+ USHORT Aid;
+ USHORT AtimWin; // in kusec; IBSS parameter set element
+ USHORT CapabilityInfo;
+ USHORT CfpMaxDuration;
+ USHORT CfpPeriod;
+
+ // Copy supported rate from desired AP's beacon. We are trying to match
+ // AP's supported and extended rate settings.
+ UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR SupRateLen;
+ UCHAR ExtRateLen;
+ // Copy supported ht from desired AP's beacon. We are trying to match
+ RT_HT_PHY_INFO SupportedPhyInfo;
+ RT_HT_CAPABILITY SupportedHtPhy;
+} STA_ACTIVE_CONFIG, *PSTA_ACTIVE_CONFIG;
+#endif // CONFIG_STA_SUPPORT //
+
+// ----------- start of AP --------------------------
+// AUTH-RSP State Machine Aux data structure
+typedef struct _AP_MLME_AUX {
+ UCHAR Addr[MAC_ADDR_LEN];
+ USHORT Alg;
+ CHAR Challenge[CIPHER_TEXT_LEN];
+} AP_MLME_AUX, *PAP_MLME_AUX;
+
+// structure to define WPA Group Key Rekey Interval
+typedef struct PACKED _RT_802_11_WPA_REKEY {
+ ULONG ReKeyMethod; // mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based
+ ULONG ReKeyInterval; // time-based: seconds, packet-based: kilo-packets
+} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY;
+
+typedef struct _MAC_TABLE_ENTRY {
+ //Choose 1 from ValidAsWDS and ValidAsCLI to validize.
+ BOOLEAN ValidAsCLI; // Sta mode, set this TRUE after Linkup,too.
+ BOOLEAN ValidAsWDS; // This is WDS Entry. only for AP mode.
+ BOOLEAN ValidAsApCli; //This is a AP-Client entry, only for AP mode which enable AP-Client functions.
+ BOOLEAN ValidAsMesh;
+ BOOLEAN ValidAsDls; // This is DLS Entry. only for STA mode.
+ BOOLEAN isCached;
+ BOOLEAN bIAmBadAtheros; // Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection.
+
+ UCHAR EnqueueEapolStartTimerRunning; // Enqueue EAPoL-Start for triggering EAP SM
+ //jan for wpa
+ // record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB
+ UCHAR CMTimerRunning;
+ UCHAR apidx; // MBSS number
+ UCHAR RSNIE_Len;
+ UCHAR RSN_IE[MAX_LEN_OF_RSNIE];
+ UCHAR ANonce[LEN_KEY_DESC_NONCE];
+ UCHAR R_Counter[LEN_KEY_DESC_REPLAY];
+ UCHAR PTK[64];
+ UCHAR ReTryCounter;
+ RALINK_TIMER_STRUCT RetryTimer;
+ RALINK_TIMER_STRUCT EnqueueStartForPSKTimer; // A timer which enqueue EAPoL-Start for triggering PSK SM
+ NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined
+ NDIS_802_11_WEP_STATUS WepStatus;
+ AP_WPA_STATE WpaState;
+ GTK_STATE GTKState;
+ USHORT PortSecured;
+ NDIS_802_11_PRIVACY_FILTER PrivacyFilter; // PrivacyFilter enum for 802.1X
+ CIPHER_KEY PairwiseKey;
+ PVOID pAd;
+ INT PMKID_CacheIdx;
+ UCHAR PMKID[LEN_PMKID];
+
+
+ UCHAR Addr[MAC_ADDR_LEN];
+ UCHAR PsMode;
+ SST Sst;
+ AUTH_STATE AuthState; // for SHARED KEY authentication state machine used only
+ BOOLEAN IsReassocSta; // Indicate whether this is a reassociation procedure
+ USHORT Aid;
+ USHORT CapabilityInfo;
+ UCHAR LastRssi;
+ ULONG NoDataIdleCount;
+ UINT16 StationKeepAliveCount; // unit: second
+ ULONG PsQIdleCount;
+ QUEUE_HEADER PsQueue;
+
+ UINT32 StaConnectTime; // the live time of this station since associated with AP
+
+
+#ifdef DOT11_N_SUPPORT
+ BOOLEAN bSendBAR;
+ USHORT NoBADataCountDown;
+
+ UINT32 CachedBuf[16]; // UINT (4 bytes) for alignment
+ UINT TxBFCount; // 3*3
+#endif // DOT11_N_SUPPORT //
+ UINT FIFOCount;
+ UINT DebugFIFOCount;
+ UINT DebugTxCount;
+ BOOLEAN bDlsInit;
+
+
+//====================================================
+//WDS entry needs these
+// rt2860 add this. if ValidAsWDS==TRUE, MatchWDSTabIdx is the index in WdsTab.MacTab
+ UINT MatchWDSTabIdx;
+ UCHAR MaxSupportedRate;
+ UCHAR CurrTxRate;
+ UCHAR CurrTxRateIndex;
+ // to record the each TX rate's quality. 0 is best, the bigger the worse.
+ USHORT TxQuality[MAX_STEP_OF_TX_RATE_SWITCH];
+ UINT32 OneSecTxNoRetryOkCount;
+ UINT32 OneSecTxRetryOkCount;
+ UINT32 OneSecTxFailCount;
+ UINT32 ContinueTxFailCnt;
+ UINT32 CurrTxRateStableTime; // # of second in current TX rate
+ UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition
+//====================================================
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+ UINT MatchDlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+ BOOLEAN fNoisyEnvironment;
+ BOOLEAN fLastSecAccordingRSSI;
+ UCHAR LastSecTxRateChangeAction; // 0: no change, 1:rate UP, 2:rate down
+ CHAR LastTimeTxRateChangeAction; //Keep last time value of LastSecTxRateChangeAction
+ ULONG LastTxOkCount;
+ UCHAR PER[MAX_STEP_OF_TX_RATE_SWITCH];
+
+ // a bitmap of BOOLEAN flags. each bit represent an operation status of a particular
+ // BOOLEAN control, either ON or OFF. These flags should always be accessed via
+ // CLIENT_STATUS_TEST_FLAG(), CLIENT_STATUS_SET_FLAG(), CLIENT_STATUS_CLEAR_FLAG() macros.
+ // see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition. fCLIENT_STATUS_AMSDU_INUSED
+ ULONG ClientStatusFlags;
+
+ // TODO: Shall we move that to DOT11_N_SUPPORT???
+ HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;// For transmit phy setting in TXWI.
+
+#ifdef DOT11_N_SUPPORT
+ // HT EWC MIMO-N used parameters
+ USHORT RXBAbitmap; // fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format
+ USHORT TXBAbitmap; // This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI
+ USHORT TXAutoBAbitmap;
+ USHORT BADeclineBitmap;
+ USHORT BARecWcidArray[NUM_OF_TID]; // The mapping wcid of recipient session. if RXBAbitmap bit is masked
+ USHORT BAOriWcidArray[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked
+ USHORT BAOriSequence[NUM_OF_TID]; // The mapping wcid of originator session. if TXBAbitmap bit is masked
+
+ // 802.11n features.
+ UCHAR MpduDensity;
+ UCHAR MaxRAmpduFactor;
+ UCHAR AMsduSize;
+ UCHAR MmpsMode; // MIMO power save more.
+
+ HT_CAPABILITY_IE HTCapability;
+
+#ifdef DOT11N_DRAFT3
+ UCHAR BSS2040CoexistenceMgmtSupport;
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+ BOOLEAN bAutoTxRateSwitch;
+
+ UCHAR RateLen;
+ struct _MAC_TABLE_ENTRY *pNext;
+ USHORT TxSeq[NUM_OF_TID];
+ USHORT NonQosDataSeq;
+
+ RSSI_SAMPLE RssiSample;
+
+ UINT32 TXMCSExpected[16];
+ UINT32 TXMCSSuccessful[16];
+ UINT32 TXMCSFailed[16];
+ UINT32 TXMCSAutoFallBack[16][16];
+} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY;
+
+typedef struct _MAC_TABLE {
+ USHORT Size;
+ MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE];
+ MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE];
+ QUEUE_HEADER McastPsQueue;
+ ULONG PsQIdleCount;
+ BOOLEAN fAnyStationInPsm;
+ BOOLEAN fAnyStationBadAtheros; // Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip.
+ BOOLEAN fAnyTxOPForceDisable; // Check if it is necessary to disable BE TxOP
+#ifdef DOT11_N_SUPPORT
+ BOOLEAN fAnyStationIsLegacy; // Check if I use legacy rate to transmit to my BSS Station/
+ BOOLEAN fAnyStationNonGF; // Check if any Station can't support GF.
+ BOOLEAN fAnyStation20Only; // Check if any Station can't support GF.
+ BOOLEAN fAnyStationMIMOPSDynamic; // Check if any Station is MIMO Dynamic
+ BOOLEAN fAnyBASession; // Check if there is BA session. Force turn on RTS/CTS
+#endif // DOT11_N_SUPPORT //
+} MAC_TABLE, *PMAC_TABLE;
+
+#ifdef DOT11_N_SUPPORT
+#define IS_HT_STA(_pMacEntry) \
+ (_pMacEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX)
+
+#define IS_HT_RATE(_pMacEntry) \
+ (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
+
+#define PEER_IS_HT_RATE(_pMacEntry) \
+ (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX)
+#endif // DOT11_N_SUPPORT //
+
+typedef struct _WDS_ENTRY {
+ BOOLEAN Valid;
+ UCHAR Addr[MAC_ADDR_LEN];
+ ULONG NoDataIdleCount;
+ struct _WDS_ENTRY *pNext;
+} WDS_ENTRY, *PWDS_ENTRY;
+
+typedef struct _WDS_TABLE_ENTRY {
+ USHORT Size;
+ UCHAR WdsAddr[MAC_ADDR_LEN];
+ WDS_ENTRY *Hash[HASH_TABLE_SIZE];
+ WDS_ENTRY Content[MAX_LEN_OF_MAC_TABLE];
+ UCHAR MaxSupportedRate;
+ UCHAR CurrTxRate;
+ USHORT TxQuality[MAX_LEN_OF_SUPPORTED_RATES];
+ USHORT OneSecTxOkCount;
+ USHORT OneSecTxRetryOkCount;
+ USHORT OneSecTxFailCount;
+ ULONG CurrTxRateStableTime; // # of second in current TX rate
+ UCHAR TxRateUpPenalty; // extra # of second penalty due to last unstable condition
+} WDS_TABLE_ENTRY, *PWDS_TABLE_ENTRY;
+
+typedef struct _RT_802_11_WDS_ENTRY {
+ PNET_DEV dev;
+ UCHAR Valid;
+ UCHAR PhyMode;
+ UCHAR PeerWdsAddr[MAC_ADDR_LEN];
+ UCHAR MacTabMatchWCID; // ASIC
+ NDIS_802_11_WEP_STATUS WepStatus;
+ UCHAR KeyIdx;
+ CIPHER_KEY WdsKey;
+ HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;
+ RT_HT_PHY_INFO DesiredHtPhyInfo;
+ BOOLEAN bAutoTxRateSwitch;
+ DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting.
+} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY;
+
+typedef struct _WDS_TABLE {
+ UCHAR Mode;
+ ULONG Size;
+ RT_802_11_WDS_ENTRY WdsEntry[MAX_WDS_ENTRY];
+} WDS_TABLE, *PWDS_TABLE;
+
+typedef struct _APCLI_STRUCT {
+ PNET_DEV dev;
+#ifdef RTL865X_SOC
+ unsigned int mylinkid;
+#endif
+ BOOLEAN Enable; // Set it as 1 if the apcli interface was configured to "1" or by iwpriv cmd "ApCliEnable"
+ BOOLEAN Valid; // Set it as 1 if the apcli interface associated success to remote AP.
+ UCHAR MacTabWCID; //WCID value, which point to the entry of ASIC Mac table.
+ UCHAR SsidLen;
+ CHAR Ssid[MAX_LEN_OF_SSID];
+
+ UCHAR CfgSsidLen;
+ CHAR CfgSsid[MAX_LEN_OF_SSID];
+ UCHAR CfgApCliBssid[ETH_LENGTH_OF_ADDRESS];
+ UCHAR CurrentAddress[ETH_LENGTH_OF_ADDRESS];
+
+ ULONG ApCliRcvBeaconTime;
+
+ ULONG CtrlCurrState;
+ ULONG SyncCurrState;
+ ULONG AuthCurrState;
+ ULONG AssocCurrState;
+ ULONG WpaPskCurrState;
+
+ USHORT AuthReqCnt;
+ USHORT AssocReqCnt;
+
+ ULONG ClientStatusFlags;
+ UCHAR MpduDensity;
+
+ NDIS_802_11_AUTHENTICATION_MODE AuthMode; // This should match to whatever microsoft defined
+ NDIS_802_11_WEP_STATUS WepStatus;
+
+ // Add to support different cipher suite for WPA2/WPA mode
+ NDIS_802_11_ENCRYPTION_STATUS GroupCipher; // Multicast cipher suite
+ NDIS_802_11_ENCRYPTION_STATUS PairCipher; // Unicast cipher suite
+ BOOLEAN bMixCipher; // Indicate current Pair & Group use different cipher suites
+ USHORT RsnCapability;
+
+ UCHAR PSK[100]; // reserve PSK key material
+ UCHAR PSKLen;
+ UCHAR PMK[32]; // WPA PSK mode PMK
+ UCHAR GTK[32]; // GTK from authenticator
+
+ CIPHER_KEY SharedKey[SHARE_KEY_NUM];
+ UCHAR DefaultKeyId;
+
+ // store RSN_IE built by driver
+ UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; // The content saved here should be convert to little-endian format.
+ UCHAR RSNIE_Len;
+
+ // For WPA countermeasures
+ ULONG LastMicErrorTime; // record last MIC error time
+ BOOLEAN bBlockAssoc; // Block associate attempt for 60 seconds after counter measure occurred.
+
+ // For WPA-PSK supplicant state
+ UCHAR SNonce[32]; // SNonce for WPA-PSK
+ UCHAR GNonce[32]; // GNonce for WPA-PSK from authenticator
+
+#ifdef WSC_AP_SUPPORT
+ WSC_CTRL WscControl;
+#endif // WSC_AP_SUPPORT //
+
+ HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode;
+ RT_HT_PHY_INFO DesiredHtPhyInfo;
+ BOOLEAN bAutoTxRateSwitch;
+ DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; // Desired transmit setting.
+} APCLI_STRUCT, *PAPCLI_STRUCT;
+
+// ----------- end of AP ----------------------------
+
+#ifdef BLOCK_NET_IF
+typedef struct _BLOCK_QUEUE_ENTRY
+{
+ BOOLEAN SwTxQueueBlockFlag;
+ LIST_HEADER NetIfList;
+} BLOCK_QUEUE_ENTRY, *PBLOCK_QUEUE_ENTRY;
+#endif // BLOCK_NET_IF //
+
+struct wificonf
+{
+ BOOLEAN bShortGI;
+ BOOLEAN bGreenField;
+};
+
+
+
+
+typedef struct _INF_PCI_CONFIG
+{
+ PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use
+}INF_PCI_CONFIG;
+
+typedef struct _INF_USB_CONFIG
+{
+ UINT BulkInEpAddr; // bulk-in endpoint address
+ UINT BulkOutEpAddr[6]; // bulk-out endpoint address
+
+}INF_USB_CONFIG;
+
+#ifdef IKANOS_VX_1X0
+ typedef void (*IkanosWlanTxCbFuncP)(void *, void *);
+
+ struct IKANOS_TX_INFO
+ {
+ struct net_device *netdev;
+ IkanosWlanTxCbFuncP *fp;
+ };
+#endif // IKANOS_VX_1X0 //
+
+#ifdef NINTENDO_AP
+typedef struct _NINDO_CTRL_BLOCK {
+
+ RT_NINTENDO_TABLE DS_TABLE;
+
+#ifdef CHIP25XX
+ spinlock_t NINTENDO_TABLE_Lock;
+#else
+ NDIS_SPIN_LOCK NINTENDO_TABLE_Lock;
+#endif // CHIP25XX //
+
+ UCHAR NINTENDO_UP_BUFFER[512];
+ UCHAR Local_KeyIdx;
+ CIPHER_KEY Local_SharedKey;
+ UCHAR Local_bHideSsid;
+ UCHAR Local_AuthMode;
+ UCHAR Local_WepStatus;
+ USHORT Local_CapabilityInfo;
+} NINDO_CTRL_BLOCK;
+#endif // NINTENDO_AP //
+
+
+#ifdef DBG_DIAGNOSE
+#define DIAGNOSE_TIME 10 // 10 sec
+typedef struct _RtmpDiagStrcut_
+{ // Diagnosis Related element
+ unsigned char inited;
+ unsigned char qIdx;
+ unsigned char ArrayStartIdx;
+ unsigned char ArrayCurIdx;
+ // Tx Related Count
+ USHORT TxDataCnt[DIAGNOSE_TIME];
+ USHORT TxFailCnt[DIAGNOSE_TIME];
+ USHORT TxDescCnt[DIAGNOSE_TIME][24]; // 3*3 // TxDesc queue length in scale of 0~14, >=15
+ USHORT TxMcsCnt[DIAGNOSE_TIME][24]; // 3*3
+ USHORT TxSWQueCnt[DIAGNOSE_TIME][9]; // TxSwQueue length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8
+
+ USHORT TxAggCnt[DIAGNOSE_TIME];
+ USHORT TxNonAggCnt[DIAGNOSE_TIME];
+ USHORT TxAMPDUCnt[DIAGNOSE_TIME][24]; // 3*3 // 10 sec, TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1.
+ USHORT TxRalinkCnt[DIAGNOSE_TIME]; // TxRalink Aggregation Count in 1 sec scale.
+ USHORT TxAMSDUCnt[DIAGNOSE_TIME]; // TxAMSUD Aggregation Count in 1 sec scale.
+
+ // Rx Related Count
+ USHORT RxDataCnt[DIAGNOSE_TIME]; // Rx Total Data count.
+ USHORT RxCrcErrCnt[DIAGNOSE_TIME];
+ USHORT RxMcsCnt[DIAGNOSE_TIME][24]; // 3*3
+}RtmpDiagStruct;
+#endif // DBG_DIAGNOSE //
+
+
+//
+// The miniport adapter structure
+//
+typedef struct _RTMP_ADAPTER
+{
+ PVOID OS_Cookie; // save specific structure relative to OS
+ PNET_DEV net_dev;
+ ULONG VirtualIfCnt;
+
+#ifdef RT2860
+ USHORT LnkCtrlBitMask;
+ USHORT RLnkCtrlConfiguration;
+ USHORT RLnkCtrlOffset;
+ USHORT HostLnkCtrlConfiguration;
+ USHORT HostLnkCtrlOffset;
+ USHORT PCIePowerSaveLevel;
+ BOOLEAN bPCIclkOff; // flag that indicate if the PICE power status in Configuration SPace..
+ BOOLEAN bPCIclkOffDisableTx; //
+
+
+/*****************************************************************************************/
+/* PCI related parameters */
+/*****************************************************************************************/
+ PUCHAR CSRBaseAddress; // PCI MMIO Base Address, all access will use
+
+ UINT int_enable_reg;
+ UINT int_disable_mask;
+ UINT int_pending;
+
+
+ RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; // Shared memory of all 1st pre-allocated TxBuf associated with each TXD
+ RTMP_DMABUF RxDescRing; // Shared memory for RX descriptors
+ RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; // Shared memory for Tx descriptors
+ RTMP_TX_RING TxRing[NUM_OF_TX_RING]; // AC0~4 + HCCA
+#endif // RT2860 //
+
+
+ NDIS_SPIN_LOCK irq_lock;
+ UCHAR irq_disabled;
+
+
+
+/*****************************************************************************************/
+ /* Both PCI/USB related parameters */
+/*****************************************************************************************/
+
+
+/*****************************************************************************************/
+/* Tx related parameters */
+/*****************************************************************************************/
+ BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; // for ensuring RTUSBDeQueuePacket get call once
+ NDIS_SPIN_LOCK DeQueueLock[NUM_OF_TX_RING];
+
+
+ // resource for software backlog queues
+ QUEUE_HEADER TxSwQueue[NUM_OF_TX_RING]; // 4 AC + 1 HCCA
+ NDIS_SPIN_LOCK TxSwQueueLock[NUM_OF_TX_RING]; // TxSwQueue spinlock
+
+ RTMP_DMABUF MgmtDescRing; // Shared memory for MGMT descriptors
+ RTMP_MGMT_RING MgmtRing;
+ NDIS_SPIN_LOCK MgmtRingLock; // Prio Ring spinlock
+
+
+/*****************************************************************************************/
+/* Rx related parameters */
+/*****************************************************************************************/
+
+#ifdef RT2860
+ RTMP_RX_RING RxRing;
+ NDIS_SPIN_LOCK RxRingLock; // Rx Ring spinlock
+#endif // RT2860 //
+
+
+
+/*****************************************************************************************/
+/* ASIC related parameters */
+/*****************************************************************************************/
+ UINT32 MACVersion; // MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101)..
+
+ // ---------------------------
+ // E2PROM
+ // ---------------------------
+ ULONG EepromVersion; // byte 0: version, byte 1: revision, byte 2~3: unused
+ UCHAR EEPROMAddressNum; // 93c46=6 93c66=8
+ USHORT EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS];
+ ULONG FirmwareVersion; // byte 0: Minor version, byte 1: Major version, otherwise unused.
+
+ // ---------------------------
+ // BBP Control
+ // ---------------------------
+ UCHAR BbpWriteLatch[140]; // record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID
+ UCHAR BbpRssiToDbmDelta;
+ BBP_R66_TUNING BbpTuning;
+
+ // ----------------------------
+ // RFIC control
+ // ----------------------------
+ UCHAR RfIcType; // RFIC_xxx
+ ULONG RfFreqOffset; // Frequency offset for channel switching
+ RTMP_RF_REGS LatchRfRegs; // latch th latest RF programming value since RF IC doesn't support READ
+
+ EEPROM_ANTENNA_STRUC Antenna; // Since ANtenna definition is different for a & g. We need to save it for future reference.
+ EEPROM_NIC_CONFIG2_STRUC NicConfig2;
+
+ // This soft Rx Antenna Diversity mechanism is used only when user set
+ // RX Antenna = DIVERSITY ON
+ SOFT_RX_ANT_DIVERSITY RxAnt;
+
+ UCHAR RFProgSeq;
+ CHANNEL_TX_POWER TxPower[MAX_NUM_OF_CHANNELS]; // Store Tx power value for all channels.
+ CHANNEL_TX_POWER ChannelList[MAX_NUM_OF_CHANNELS]; // list all supported channels for site survey
+ CHANNEL_11J_TX_POWER TxPower11J[MAX_NUM_OF_11JCHANNELS]; // 802.11j channel and bw
+ CHANNEL_11J_TX_POWER ChannelList11J[MAX_NUM_OF_11JCHANNELS]; // list all supported channels for site survey
+
+ UCHAR ChannelListNum; // number of channel in ChannelList[]
+ UCHAR Bbp94;
+ BOOLEAN BbpForCCK;
+ ULONG Tx20MPwrCfgABand[5];
+ ULONG Tx20MPwrCfgGBand[5];
+ ULONG Tx40MPwrCfgABand[5];
+ ULONG Tx40MPwrCfgGBand[5];
+
+ BOOLEAN bAutoTxAgcA; // Enable driver auto Tx Agc control
+ UCHAR TssiRefA; // Store Tssi reference value as 25 temperature.
+ UCHAR TssiPlusBoundaryA[5]; // Tssi boundary for increase Tx power to compensate.
+ UCHAR TssiMinusBoundaryA[5]; // Tssi boundary for decrease Tx power to compensate.
+ UCHAR TxAgcStepA; // Store Tx TSSI delta increment / decrement value
+ CHAR TxAgcCompensateA; // Store the compensation (TxAgcStep * (idx-1))
+
+ BOOLEAN bAutoTxAgcG; // Enable driver auto Tx Agc control
+ UCHAR TssiRefG; // Store Tssi reference value as 25 temperature.
+ UCHAR TssiPlusBoundaryG[5]; // Tssi boundary for increase Tx power to compensate.
+ UCHAR TssiMinusBoundaryG[5]; // Tssi boundary for decrease Tx power to compensate.
+ UCHAR TxAgcStepG; // Store Tx TSSI delta increment / decrement value
+ CHAR TxAgcCompensateG; // Store the compensation (TxAgcStep * (idx-1))
+
+ //+++For RT2870, the parameteres is start from BGRssiOffset1 ~ BGRssiOffset3
+ CHAR BGRssiOffset0; // Store B/G RSSI#0 Offset value on EEPROM 0x46h
+ CHAR BGRssiOffset1; // Store B/G RSSI#1 Offset value
+ CHAR BGRssiOffset2; // Store B/G RSSI#2 Offset value
+ //---
+
+ //+++For RT2870, the parameteres is start from ARssiOffset1 ~ ARssiOffset3
+ CHAR ARssiOffset0; // Store A RSSI#0 Offset value on EEPROM 0x4Ah
+ CHAR ARssiOffset1; // Store A RSSI#1 Offset value
+ CHAR ARssiOffset2; // Store A RSSI#2 Offset value
+ //---
+
+ CHAR BLNAGain; // Store B/G external LNA#0 value on EEPROM 0x44h
+ CHAR ALNAGain0; // Store A external LNA#0 value for ch36~64
+ CHAR ALNAGain1; // Store A external LNA#1 value for ch100~128
+ CHAR ALNAGain2; // Store A external LNA#2 value for ch132~165
+
+ // ----------------------------
+ // LED control
+ // ----------------------------
+ MCU_LEDCS_STRUC LedCntl;
+ USHORT Led1; // read from EEPROM 0x3c
+ USHORT Led2; // EEPROM 0x3e
+ USHORT Led3; // EEPROM 0x40
+ UCHAR LedIndicatorStregth;
+ UCHAR RssiSingalstrengthOffet;
+ BOOLEAN bLedOnScanning;
+ UCHAR LedStatus;
+
+/*****************************************************************************************/
+/* 802.11 related parameters */
+/*****************************************************************************************/
+ // outgoing BEACON frame buffer and corresponding TXD
+ TXWI_STRUC BeaconTxWI;
+ PUCHAR BeaconBuf;
+ USHORT BeaconOffset[HW_BEACON_MAX_COUNT];
+
+ // pre-build PS-POLL and NULL frame upon link up. for efficiency purpose.
+ PSPOLL_FRAME PsPollFrame;
+ HEADER_802_11 NullFrame;
+
+//=========AP===========
+
+
+//=======STA===========
+#ifdef CONFIG_STA_SUPPORT
+/* Modified by Wu Xi-Kun 4/21/2006 */
+ // -----------------------------------------------
+ // STA specific configuration & operation status
+ // used only when pAd->OpMode == OPMODE_STA
+ // -----------------------------------------------
+ STA_ADMIN_CONFIG StaCfg; // user desired settings
+ STA_ACTIVE_CONFIG StaActive; // valid only when ADHOC_ON(pAd) || INFRA_ON(pAd)
+ CHAR nickname[IW_ESSID_MAX_SIZE+1]; // nickname, only used in the iwconfig i/f
+ NDIS_MEDIA_STATE PreMediaState;
+#endif // CONFIG_STA_SUPPORT //
+
+//=======Common===========
+ // OP mode: either AP or STA
+ UCHAR OpMode; // OPMODE_STA, OPMODE_AP
+
+ NDIS_MEDIA_STATE IndicateMediaState; // Base on Indication state, default is NdisMediaStateDisConnected
+
+ // MAT related parameters
+
+ // configuration: read from Registry & E2PROM
+ BOOLEAN bLocalAdminMAC; // Use user changed MAC
+ UCHAR PermanentAddress[MAC_ADDR_LEN]; // Factory default MAC address
+ UCHAR CurrentAddress[MAC_ADDR_LEN]; // User changed MAC address
+
+ // ------------------------------------------------------
+ // common configuration to both OPMODE_STA and OPMODE_AP
+ // ------------------------------------------------------
+ COMMON_CONFIG CommonCfg;
+ MLME_STRUCT Mlme;
+
+ // AP needs those vaiables for site survey feature.
+ MLME_AUX MlmeAux; // temporary settings used during MLME state machine
+ BSS_TABLE ScanTab; // store the latest SCAN result
+
+ //About MacTab, the sta driver will use #0 and #1 for multicast and AP.
+ MAC_TABLE MacTab; // ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table.
+ NDIS_SPIN_LOCK MacTabLock;
+
+#ifdef DOT11_N_SUPPORT
+ BA_TABLE BATable;
+#endif // DOT11_N_SUPPORT //
+ NDIS_SPIN_LOCK BATabLock;
+ RALINK_TIMER_STRUCT RECBATimer;
+
+ // encryption/decryption KEY tables
+ CIPHER_KEY SharedKey[MAX_MBSSID_NUM][4]; // STA always use SharedKey[BSS0][0..3]
+
+ // RX re-assembly buffer for fragmentation
+ FRAGMENT_FRAME FragFrame; // Frame storage for fragment frame
+
+ // various Counters
+ COUNTER_802_3 Counters8023; // 802.3 counters
+ COUNTER_802_11 WlanCounters; // 802.11 MIB counters
+ COUNTER_RALINK RalinkCounters; // Ralink propriety counters
+ COUNTER_DRS DrsCounters; // counters for Dynamic TX Rate Switching
+ PRIVATE_STRUC PrivateInfo; // Private information & counters
+
+ // flags, see fRTMP_ADAPTER_xxx flags
+ ULONG Flags; // Represent current device status
+
+ // current TX sequence #
+ USHORT Sequence;
+
+#ifdef UNDER_CE
+ NDIS_HANDLE hGiISR;
+#endif
+
+
+ // Control disconnect / connect event generation
+ //+++Didn't used anymore
+ ULONG LinkDownTime;
+ //---
+ ULONG LastRxRate;
+ ULONG LastTxRate;
+ //+++Used only for Station
+ BOOLEAN bConfigChanged; // Config Change flag for the same SSID setting
+ //---
+
+ ULONG ExtraInfo; // Extra information for displaying status
+ ULONG SystemErrorBitmap; // b0: E2PROM version error
+
+ //+++Didn't used anymore
+ ULONG MacIcVersion; // MAC/BBP serial interface issue solved after ver.D
+ //---
+
+ // ---------------------------
+ // System event log
+ // ---------------------------
+ RT_802_11_EVENT_TABLE EventTab;
+
+
+ BOOLEAN HTCEnable;
+
+ /*****************************************************************************************/
+ /* Statistic related parameters */
+ /*****************************************************************************************/
+
+ BOOLEAN bUpdateBcnCntDone;
+ ULONG watchDogMacDeadlock; // prevent MAC/BBP into deadlock condition
+ // ----------------------------
+ // DEBUG paramerts
+ // ----------------------------
+ BOOLEAN bBanAllBaSetup;
+ BOOLEAN bPromiscuous;
+
+ // ----------------------------
+ // rt2860c emulation-use Parameters
+ // ----------------------------
+ ULONG rtsaccu[30];
+ ULONG ctsaccu[30];
+ ULONG cfendaccu[30];
+ ULONG bacontent[16];
+ ULONG rxint[RX_RING_SIZE+1];
+ UCHAR rcvba[60];
+ BOOLEAN bLinkAdapt;
+ BOOLEAN bForcePrintTX;
+ BOOLEAN bForcePrintRX;
+ BOOLEAN bDisablescanning; //defined in RT2870 USB
+ BOOLEAN bStaFifoTest;
+ BOOLEAN bProtectionTest;
+ BOOLEAN bHCCATest;
+ BOOLEAN bGenOneHCCA;
+ BOOLEAN bBroadComHT;
+ //+++Following add from RT2870 USB.
+ ULONG BulkOutReq;
+ ULONG BulkOutComplete;
+ ULONG BulkOutCompleteOther;
+ ULONG BulkOutCompleteCancel; // seems not use now?
+ ULONG BulkInReq;
+ ULONG BulkInComplete;
+ ULONG BulkInCompleteFail;
+ //---
+
+ struct wificonf WIFItestbed;
+
+#ifdef RALINK_ATE
+ ATE_INFO ate;
+#endif // RALINK_ATE //
+
+#ifdef DOT11_N_SUPPORT
+ struct reordering_mpdu_pool mpdu_blk_pool;
+#endif // DOT11_N_SUPPORT //
+
+ ULONG OneSecondnonBEpackets; // record non BE packets per second
+
+#if WIRELESS_EXT >= 12
+ struct iw_statistics iw_stats;
+#endif
+
+ struct net_device_stats stats;
+
+#ifdef BLOCK_NET_IF
+ BLOCK_QUEUE_ENTRY blockQueueTab[NUM_OF_TX_RING];
+#endif // BLOCK_NET_IF //
+
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+ INT32 MC_RowID;
+ UCHAR MC_FileName[256];
+#endif // MULTIPLE_CARD_SUPPORT //
+
+ ULONG TbttTickCount;
+#ifdef PCI_MSI_SUPPORT
+ BOOLEAN HaveMsi;
+#endif // PCI_MSI_SUPPORT //
+
+
+ UCHAR is_on;
+
+#define TIME_BASE (1000000/OS_HZ)
+#define TIME_ONE_SECOND (1000000/TIME_BASE)
+ UCHAR flg_be_adjust;
+ ULONG be_adjust_last_time;
+
+#ifdef NINTENDO_AP
+ NINDO_CTRL_BLOCK nindo_ctrl_block;
+#endif // NINTENDO_AP //
+
+
+#ifdef IKANOS_VX_1X0
+ struct IKANOS_TX_INFO IkanosTxInfo;
+ struct IKANOS_TX_INFO IkanosRxInfo[MAX_MBSSID_NUM + MAX_WDS_ENTRY + MAX_APCLI_NUM + MAX_MESH_NUM];
+#endif // IKANOS_VX_1X0 //
+
+
+#ifdef DBG_DIAGNOSE
+ RtmpDiagStruct DiagStruct;
+#endif // DBG_DIAGNOSE //
+
+
+ UINT8 PM_FlgSuspend;
+} RTMP_ADAPTER, *PRTMP_ADAPTER;
+
+//
+// Cisco IAPP format
+//
+typedef struct _CISCO_IAPP_CONTENT_
+{
+ USHORT Length; //IAPP Length
+ UCHAR MessageType; //IAPP type
+ UCHAR FunctionCode; //IAPP function type
+ UCHAR DestinaionMAC[MAC_ADDR_LEN];
+ UCHAR SourceMAC[MAC_ADDR_LEN];
+ USHORT Tag; //Tag(element IE) - Adjacent AP report
+ USHORT TagLength; //Length of element not including 4 byte header
+ UCHAR OUI[4]; //0x00, 0x40, 0x96, 0x00
+ UCHAR PreviousAP[MAC_ADDR_LEN]; //MAC Address of access point
+ USHORT Channel;
+ USHORT SsidLen;
+ UCHAR Ssid[MAX_LEN_OF_SSID];
+ USHORT Seconds; //Seconds that the client has been disassociated.
+} CISCO_IAPP_CONTENT, *PCISCO_IAPP_CONTENT;
+
+#define DELAYINTMASK 0x0003fffb
+#define INTMASK 0x0003fffb
+#define IndMask 0x0003fffc
+#define RxINT 0x00000005 // Delayed Rx or indivi rx
+#define TxDataInt 0x000000fa // Delayed Tx or indivi tx
+#define TxMgmtInt 0x00000102 // Delayed Tx or indivi tx
+#define TxCoherent 0x00020000 // tx coherent
+#define RxCoherent 0x00010000 // rx coherent
+#define McuCommand 0x00000200 // mcu
+#define PreTBTTInt 0x00001000 // Pre-TBTT interrupt
+#define TBTTInt 0x00000800 // TBTT interrupt
+#define GPTimeOutInt 0x00008000 // GPtimeout interrupt
+#define AutoWakeupInt 0x00004000 // AutoWakeupInt interrupt
+#define FifoStaFullInt 0x00002000 // fifo statistics full interrupt
+
+
+typedef struct _RX_BLK_
+{
+ RT28XX_RXD_STRUC RxD;
+ PRXWI_STRUC pRxWI;
+ PHEADER_802_11 pHeader;
+ PNDIS_PACKET pRxPacket;
+ UCHAR *pData;
+ USHORT DataSize;
+ USHORT Flags;
+ UCHAR UserPriority; // for calculate TKIP MIC using
+} RX_BLK;
+
+
+#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag)
+#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag)
+#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag))
+
+
+#define fRX_WDS 0x0001
+#define fRX_AMSDU 0x0002
+#define fRX_ARALINK 0x0004
+#define fRX_HTC 0x0008
+#define fRX_PAD 0x0010
+#define fRX_AMPDU 0x0020
+#define fRX_QOS 0x0040
+#define fRX_INFRA 0x0080
+#define fRX_EAP 0x0100
+#define fRX_MESH 0x0200
+#define fRX_APCLI 0x0400
+#define fRX_DLS 0x0800
+#define fRX_WPI 0x1000
+
+#define LENGTH_AMSDU_SUBFRAMEHEAD 14
+#define LENGTH_ARALINK_SUBFRAMEHEAD 14
+#define LENGTH_ARALINK_HEADER_FIELD 2
+
+#define TX_UNKOWN_FRAME 0x00
+#define TX_MCAST_FRAME 0x01
+#define TX_LEGACY_FRAME 0x02
+#define TX_AMPDU_FRAME 0x04
+#define TX_AMSDU_FRAME 0x08
+#define TX_RALINK_FRAME 0x10
+#define TX_FRAG_FRAME 0x20
+
+
+// Currently the sizeof(TX_BLK) is 148 bytes.
+typedef struct _TX_BLK_
+{
+ UCHAR QueIdx;
+ UCHAR TxFrameType; // Indicate the Transmission type of the all frames in one batch
+ UCHAR TotalFrameNum; // Total frame number want to send-out in one batch
+ USHORT TotalFragNum; // Total frame fragments required in one batch
+ USHORT TotalFrameLen; // Total length of all frames want to send-out in one batch
+
+ QUEUE_HEADER TxPacketList;
+ MAC_TABLE_ENTRY *pMacEntry; // NULL: packet with 802.11 RA field is multicast/broadcast address
+ HTTRANSMIT_SETTING *pTransmit;
+
+ // Following structure used for the characteristics of a specific packet.
+ PNDIS_PACKET pPacket;
+ PUCHAR pSrcBufHeader; // Reference to the head of sk_buff->data
+ PUCHAR pSrcBufData; // Reference to the sk_buff->data, will changed depends on hanlding progresss
+ UINT SrcBufLen; // Length of packet payload which not including Layer 2 header
+ PUCHAR pExtraLlcSnapEncap; // NULL means no extra LLC/SNAP is required
+ UCHAR HeaderBuf[80]; // TempBuffer for TX_INFO + TX_WI + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP
+ UCHAR MpduHeaderLen; // 802.11 header length NOT including the padding
+ UCHAR HdrPadLen; // recording Header Padding Length;
+ UCHAR apidx; // The interface associated to this packet
+ UCHAR Wcid; // The MAC entry associated to this packet
+ UCHAR UserPriority; // priority class of packet
+ UCHAR FrameGap; // what kind of IFS this packet use
+ UCHAR MpduReqNum; // number of fragments of this frame
+ UCHAR TxRate; // TODO: Obsoleted? Should change to MCS?
+ UCHAR CipherAlg; // cipher alogrithm
+ PCIPHER_KEY pKey;
+
+
+
+ USHORT Flags; //See following definitions for detail.
+
+ //YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer.
+ ULONG Priv; // Hardware specific value saved in here.
+} TX_BLK, *PTX_BLK;
+
+
+#define fTX_bRtsRequired 0x0001 // Indicate if need send RTS frame for protection. Not used in RT2860/RT2870.
+#define fTX_bAckRequired 0x0002 // the packet need ack response
+#define fTX_bPiggyBack 0x0004 // Legacy device use Piggback or not
+#define fTX_bHTRate 0x0008 // allow to use HT rate
+#define fTX_bForceNonQoS 0x0010 // force to transmit frame without WMM-QoS in HT mode
+#define fTX_bAllowFrag 0x0020 // allow to fragment the packet, A-MPDU, A-MSDU, A-Ralink is not allowed to fragment
+#define fTX_bMoreData 0x0040 // there are more data packets in PowerSave Queue
+#define fTX_bWMM 0x0080 // QOS Data
+
+#define fTX_bClearEAPFrame 0x0100
+
+#define TX_BLK_ASSIGN_FLAG(_pTxBlk, _flag, value) \
+ do { \
+ if (value) \
+ (_pTxBlk->Flags |= _flag) \
+ else \
+ (_pTxBlk->Flags &= ~(_flag)) \
+ }while(0)
+
+#define TX_BLK_SET_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags |= _flag)
+#define TX_BLK_TEST_FLAG(_pTxBlk, _flag) (((_pTxBlk->Flags & _flag) == _flag) ? 1 : 0)
+#define TX_BLK_CLEAR_FLAG(_pTxBlk, _flag) (_pTxBlk->Flags &= ~(_flag))
+
+
+
+
+
+//------------------------------------------------------------------------------------------
+
+
+#ifdef RT2860
+//
+// Enable & Disable NIC interrupt via writing interrupt mask register
+// Since it use ADAPTER structure, it have to be put after structure definition.
+//
+__inline VOID NICDisableInterrupt(
+ IN PRTMP_ADAPTER pAd)
+{
+ RTMP_IO_WRITE32(pAd, INT_MASK_CSR, 0x0); // 0: disable
+ //RTMP_IO_WRITE32(pAd, PBF_INT_ENA, 0x0); // 0x418 is for firmware . SW doesn't handle here.
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
+}
+
+__inline VOID NICEnableInterrupt(
+ IN PRTMP_ADAPTER pAd)
+{
+ //
+ // Flag "fOP_STATUS_DOZE" On, means ASIC put to sleep, else means ASIC WakeUp
+ // To prevent System hang, we should enalbe the interrupt when
+ // ASIC is already Wake Up.
+ //
+ // RT2661 => when ASIC is sleeping, MAC register cannot be read and written.
+ // RT2860 => when ASIC is sleeping, MAC register can be read and written.
+ //if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ {
+ RTMP_IO_WRITE32(pAd, INT_MASK_CSR, pAd->int_enable_reg /*DELAYINTMASK*/); // 1:enable
+ }
+ //else
+ // DBGPRINT(RT_DEBUG_TRACE, ("fOP_STATUS_DOZE !\n"));
+
+ //RTMP_IO_WRITE32(pAd, PBF_INT_ENA, 0x00000030); // 1 : enable
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
+}
+#endif // RT2860 //
+
+#ifdef RT_BIG_ENDIAN
+static inline VOID WriteBackToDescriptor(
+ IN PUCHAR Dest,
+ IN PUCHAR Src,
+ IN BOOLEAN DoEncrypt,
+ IN ULONG DescriptorType)
+{
+ UINT32 *p1, *p2;
+
+ p1 = ((UINT32 *)Dest);
+ p2 = ((UINT32 *)Src);
+
+ *p1 = *p2;
+ *(p1+2) = *(p2+2);
+ *(p1+3) = *(p2+3);
+ *(p1+1) = *(p2+1); // Word 1; this must be written back last
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Endian conversion of Tx/Rx descriptor .
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Pointer to Tx/Rx descriptor
+ DescriptorType Direction of the frame
+
+ Return Value:
+ None
+
+ Note:
+ Call this function when read or update descriptor
+ ========================================================================
+*/
+static inline VOID RTMPWIEndianChange(
+ IN PUCHAR pData,
+ IN ULONG DescriptorType)
+{
+ int size;
+ int i;
+
+ size = ((DescriptorType == TYPE_TXWI) ? TXWI_SIZE : RXWI_SIZE);
+
+ if(DescriptorType == TYPE_TXWI)
+ {
+ *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); // Byte 0~3
+ *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData+4))); // Byte 4~7
+ }
+ else
+ {
+ for(i=0; i < size/4 ; i++)
+ *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i));
+ }
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Endian conversion of Tx/Rx descriptor .
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Pointer to Tx/Rx descriptor
+ DescriptorType Direction of the frame
+
+ Return Value:
+ None
+
+ Note:
+ Call this function when read or update descriptor
+ ========================================================================
+*/
+#ifdef RT2860
+static inline VOID RTMPDescriptorEndianChange(
+ IN PUCHAR pData,
+ IN ULONG DescriptorType)
+{
+ *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); // Byte 0~3
+ *((UINT32 *)(pData + 8)) = SWAP32(*((UINT32 *)(pData+8))); // Byte 8~11
+ *((UINT32 *)(pData +12)) = SWAP32(*((UINT32 *)(pData + 12))); // Byte 12~15
+ *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData + 4))); // Byte 4~7, this must be swapped last
+}
+#endif // RT2860 //
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Endian conversion of all kinds of 802.11 frames .
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Pointer to the 802.11 frame structure
+ Dir Direction of the frame
+ FromRxDoneInt Caller is from RxDone interrupt
+
+ Return Value:
+ None
+
+ Note:
+ Call this function when read or update buffer data
+ ========================================================================
+*/
+static inline VOID RTMPFrameEndianChange(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG Dir,
+ IN BOOLEAN FromRxDoneInt)
+{
+ PHEADER_802_11 pFrame;
+ PUCHAR pMacHdr;
+
+ // swab 16 bit fields - Frame Control field
+ if(Dir == DIR_READ)
+ {
+ *(USHORT *)pData = SWAP16(*(USHORT *)pData);
+ }
+
+ pFrame = (PHEADER_802_11) pData;
+ pMacHdr = (PUCHAR) pFrame;
+
+ // swab 16 bit fields - Duration/ID field
+ *(USHORT *)(pMacHdr + 2) = SWAP16(*(USHORT *)(pMacHdr + 2));
+
+ // swab 16 bit fields - Sequence Control field
+ *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22));
+
+ if(pFrame->FC.Type == BTYPE_MGMT)
+ {
+ switch(pFrame->FC.SubType)
+ {
+ case SUBTYPE_ASSOC_REQ:
+ case SUBTYPE_REASSOC_REQ:
+ // swab 16 bit fields - CapabilityInfo field
+ pMacHdr += sizeof(HEADER_802_11);
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+ // swab 16 bit fields - Listen Interval field
+ pMacHdr += 2;
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+ break;
+
+ case SUBTYPE_ASSOC_RSP:
+ case SUBTYPE_REASSOC_RSP:
+ // swab 16 bit fields - CapabilityInfo field
+ pMacHdr += sizeof(HEADER_802_11);
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+ // swab 16 bit fields - Status Code field
+ pMacHdr += 2;
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+ // swab 16 bit fields - AID field
+ pMacHdr += 2;
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+ break;
+
+ case SUBTYPE_AUTH:
+ // If from APHandleRxDoneInterrupt routine, it is still a encrypt format.
+ // The convertion is delayed to RTMPHandleDecryptionDoneInterrupt.
+ if(!FromRxDoneInt && pFrame->FC.Wep == 1)
+ break;
+ else
+ {
+ // swab 16 bit fields - Auth Alg No. field
+ pMacHdr += sizeof(HEADER_802_11);
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+ // swab 16 bit fields - Auth Seq No. field
+ pMacHdr += 2;
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+ // swab 16 bit fields - Status Code field
+ pMacHdr += 2;
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+ }
+ break;
+
+ case SUBTYPE_BEACON:
+ case SUBTYPE_PROBE_RSP:
+ // swab 16 bit fields - BeaconInterval field
+ pMacHdr += (sizeof(HEADER_802_11) + TIMESTAMP_LEN);
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+
+ // swab 16 bit fields - CapabilityInfo field
+ pMacHdr += sizeof(USHORT);
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+ break;
+
+ case SUBTYPE_DEAUTH:
+ case SUBTYPE_DISASSOC:
+ // swab 16 bit fields - Reason code field
+ pMacHdr += sizeof(HEADER_802_11);
+ *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr);
+ break;
+ }
+ }
+ else if( pFrame->FC.Type == BTYPE_DATA )
+ {
+ }
+ else if(pFrame->FC.Type == BTYPE_CNTL)
+ {
+ switch(pFrame->FC.SubType)
+ {
+ case SUBTYPE_BLOCK_ACK_REQ:
+ {
+ PFRAME_BA_REQ pBAReq = (PFRAME_BA_REQ)pFrame;
+ *(USHORT *)(&pBAReq->BARControl) = SWAP16(*(USHORT *)(&pBAReq->BARControl));
+ pBAReq->BAStartingSeq.word = SWAP16(pBAReq->BAStartingSeq.word);
+ }
+ break;
+ case SUBTYPE_BLOCK_ACK:
+ // For Block Ack packet, the HT_CONTROL field is in the same offset with Addr3
+ *(UINT32 *)(&pFrame->Addr3[0]) = SWAP32(*(UINT32 *)(&pFrame->Addr3[0]));
+ break;
+
+ case SUBTYPE_ACK:
+ //For ACK packet, the HT_CONTROL field is in the same offset with Addr2
+ *(UINT32 *)(&pFrame->Addr2[0])= SWAP32(*(UINT32 *)(&pFrame->Addr2[0]));
+ break;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("Invalid Frame Type!!!\n"));
+ }
+
+ // swab 16 bit fields - Frame Control
+ if(Dir == DIR_WRITE)
+ {
+ *(USHORT *)pData = SWAP16(*(USHORT *)pData);
+ }
+}
+#endif // RT_BIG_ENDIAN //
+
+
+static inline VOID ConvertMulticastIP2MAC(
+ IN PUCHAR pIpAddr,
+ IN PUCHAR *ppMacAddr,
+ IN UINT16 ProtoType)
+{
+ if (pIpAddr == NULL)
+ return;
+
+ if (ppMacAddr == NULL || *ppMacAddr == NULL)
+ return;
+
+ switch (ProtoType)
+ {
+ case ETH_P_IPV6:
+// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS);
+ *(*ppMacAddr) = 0x33;
+ *(*ppMacAddr + 1) = 0x33;
+ *(*ppMacAddr + 2) = pIpAddr[12];
+ *(*ppMacAddr + 3) = pIpAddr[13];
+ *(*ppMacAddr + 4) = pIpAddr[14];
+ *(*ppMacAddr + 5) = pIpAddr[15];
+ break;
+
+ case ETH_P_IP:
+ default:
+// memset(*ppMacAddr, 0, ETH_LENGTH_OF_ADDRESS);
+ *(*ppMacAddr) = 0x01;
+ *(*ppMacAddr + 1) = 0x00;
+ *(*ppMacAddr + 2) = 0x5e;
+ *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f;
+ *(*ppMacAddr + 4) = pIpAddr[2];
+ *(*ppMacAddr + 5) = pIpAddr[3];
+ break;
+ }
+
+ return;
+}
+
+BOOLEAN RTMPCheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+VOID RTMPHalt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+//
+// Private routines in rtmp_init.c
+//
+NDIS_STATUS RTMPAllocAdapterBlock(
+ IN PVOID handle,
+ OUT PRTMP_ADAPTER *ppAdapter
+ );
+
+NDIS_STATUS RTMPAllocTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd
+ );
+
+NDIS_STATUS RTMPFindAdapter(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ );
+
+NDIS_STATUS RTMPReadParametersHook(
+ IN PRTMP_ADAPTER pAd
+ );
+
+VOID RTMPFreeAdapter(
+ IN PRTMP_ADAPTER pAd
+ );
+
+NDIS_STATUS NICReadRegParameters(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ );
+
+
+VOID NICReadEEPROMParameters(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR mac_addr);
+
+VOID NICInitAsicFromEEPROM(
+ IN PRTMP_ADAPTER pAd);
+
+VOID NICInitTxRxRingAndBacklogQueue(
+ IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS NICInitializeAdapter(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bHardReset);
+
+NDIS_STATUS NICInitializeAsic(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bHardReset);
+
+VOID NICIssueReset(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPRingCleanUp(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR RingType);
+
+VOID RxTest(
+ IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS DbgSendPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+VOID UserCfgInit(
+ IN PRTMP_ADAPTER pAd);
+
+VOID NICResetFromError(
+ IN PRTMP_ADAPTER pAd);
+
+VOID NICEraseFirmware(
+ IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS NICLoadFirmware(
+ IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS NICLoadRateSwitchingParams(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN NICCheckForHang(
+ IN PRTMP_ADAPTER pAd);
+
+VOID NICUpdateFifoStaCounters(
+ IN PRTMP_ADAPTER pAd);
+
+VOID NICUpdateRawCounters(
+ IN PRTMP_ADAPTER pAd);
+
+ULONG RTMPNotAllZero(
+ IN PVOID pSrc1,
+ IN ULONG Length);
+
+VOID RTMPZeroMemory(
+ IN PVOID pSrc,
+ IN ULONG Length);
+
+ULONG RTMPCompareMemory(
+ IN PVOID pSrc1,
+ IN PVOID pSrc2,
+ IN ULONG Length);
+
+VOID RTMPMoveMemory(
+ OUT PVOID pDest,
+ IN PVOID pSrc,
+ IN ULONG Length);
+
+VOID AtoH(
+ char *src,
+ UCHAR *dest,
+ int destlen);
+
+UCHAR BtoH(
+ char ch);
+
+VOID RTMPPatchMacBbpBug(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPPatchCardBus(
+ IN PRTMP_ADAPTER pAdapter);
+
+VOID RTMPPatchRalinkCardBus(
+ IN PRTMP_ADAPTER pAdapter,
+ IN ULONG Bus);
+
+ULONG RTMPReadCBConfig(
+ IN ULONG Bus,
+ IN ULONG Slot,
+ IN ULONG Func,
+ IN ULONG Offset);
+
+VOID RTMPWriteCBConfig(
+ IN ULONG Bus,
+ IN ULONG Slot,
+ IN ULONG Func,
+ IN ULONG Offset,
+ IN ULONG Value);
+
+VOID RTMPInitTimer(
+ IN PRTMP_ADAPTER pAd,
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN PVOID pTimerFunc,
+ IN PVOID pData,
+ IN BOOLEAN Repeat);
+
+VOID RTMPSetTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN ULONG Value);
+
+
+VOID RTMPModTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ IN ULONG Value);
+
+VOID RTMPCancelTimer(
+ IN PRALINK_TIMER_STRUCT pTimer,
+ OUT BOOLEAN *pCancelled);
+
+VOID RTMPSetLED(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Status);
+
+VOID RTMPSetSignalLED(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_802_11_RSSI Dbm);
+
+VOID RTMPEnableRxTx(
+ IN PRTMP_ADAPTER pAd);
+
+//
+// prototype in action.c
+//
+VOID ActionStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID MlmeADDBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDELBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDLSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeInvalidAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeQOSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef DOT11_N_SUPPORT
+VOID PeerAddBAReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAddBARspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDelBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBAAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+#endif // DOT11_N_SUPPORT //
+
+VOID SendPSMPAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR Psmp);
+
+
+#ifdef DOT11N_DRAFT3
+VOID SendBSS2040CoexistMgmtAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR apidx,
+ IN UCHAR InfoReq);
+
+VOID SendNotifyBWActionFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR apidx);
+
+BOOLEAN ChannelSwitchSanityCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR NewChannel,
+ IN UCHAR Secondary);
+
+VOID ChannelSwitchAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR Channel,
+ IN UCHAR Secondary);
+
+ULONG BuildIntolerantChannelRep(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDest);
+
+VOID Update2040CoexistFrameAndNotify(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN BOOLEAN bAddIntolerantCha);
+
+VOID Send2040CoexistAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN BOOLEAN bAddIntolerantCha);
+#endif // DOT11N_DRAFT3 //
+
+VOID PeerRMAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerPublicAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID StaPublicAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Bss2040Coexist);
+#endif // CONFIG_STA_SUPPORT //
+
+
+VOID PeerBSSTranAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef DOT11_N_SUPPORT
+VOID PeerHTAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+#endif // DOT11_N_SUPPORT //
+
+VOID PeerQOSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef QOS_DLS_SUPPORT
+VOID PeerDLSAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+#endif // QOS_DLS_SUPPORT //
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+VOID DlsParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_DLS_REQ_STRUCT *pDlsReq,
+ IN PRT_802_11_DLS pDls,
+ IN USHORT reason);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+VOID RECBATimerTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID ORIBATimerTimeout(
+ IN PRTMP_ADAPTER pAd);
+
+VOID SendRefreshBAR(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry);
+#endif // DOT11_N_SUPPORT //
+
+VOID ActHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN PUCHAR Addr1,
+ IN PUCHAR Addr2,
+ IN PUCHAR Addr3);
+
+VOID BarHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PFRAME_BAR pCntlBar,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA);
+
+VOID InsertActField(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pFrameBuf,
+ OUT PULONG pFrameLen,
+ IN UINT8 Category,
+ IN UINT8 ActCode);
+
+BOOLEAN QosBADataParse(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bAMSDU,
+ IN PUCHAR p8023Header,
+ IN UCHAR WCID,
+ IN UCHAR TID,
+ IN USHORT Sequence,
+ IN UCHAR DataOffset,
+ IN USHORT Datasize,
+ IN UINT CurRxIndex);
+
+#ifdef DOT11_N_SUPPORT
+BOOLEAN CntlEnqueueForRecv(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN ULONG MsgLen,
+ IN PFRAME_BA_REQ pMsg);
+
+VOID BaAutoManSwitch(
+ IN PRTMP_ADAPTER pAd);
+#endif // DOT11_N_SUPPORT //
+
+VOID HTIOTCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BatRecIdx);
+
+//
+// Private routines in rtmp_data.c
+//
+BOOLEAN RTMPHandleRxDoneInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPHandleTxDoneInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(
+ IN PRTMP_ADAPTER pAd,
+ IN INT_SOURCE_CSR_STRUC TxRingBitmap);
+
+VOID RTMPHandleMgmtRingDmaDoneInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPHandleTBTTInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPHandlePreTBTTInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+void RTMPHandleTwakeupInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPHandleRxCoherentInterrupt(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN TxFrameIsAggregatible(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pPrevAddr1,
+ IN PUCHAR p8023hdr);
+
+BOOLEAN PeerIsAggreOn(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG TxRate,
+ IN PMAC_TABLE_ENTRY pMacEntry);
+
+NDIS_STATUS Sniff2BytesFromNdisBuffer(
+ IN PNDIS_BUFFER pFirstBuffer,
+ IN UCHAR DesiredOffset,
+ OUT PUCHAR pByte0,
+ OUT PUCHAR pByte1);
+
+NDIS_STATUS STASendPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+VOID STASendPackets(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PPNDIS_PACKET ppPacketArray,
+ IN UINT NumberOfPackets);
+
+VOID RTMPDeQueuePacket(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bIntContext,
+ IN UCHAR QueIdx,
+ IN UCHAR Max_Tx_Packets);
+
+NDIS_STATUS RTMPHardTransmit(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR QueIdx,
+ OUT PULONG pFreeTXDLeft);
+
+NDIS_STATUS STAHardTransmit(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR QueIdx);
+
+VOID STARxEAPOLFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+NDIS_STATUS RTMPFreeTXDRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR RingType,
+ IN UCHAR NumberRequired,
+ IN PUCHAR FreeNumberIs);
+
+NDIS_STATUS MlmeHardTransmit(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket);
+
+NDIS_STATUS MlmeHardTransmitMgmtRing(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket);
+
+NDIS_STATUS MlmeHardTransmitTxRing(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket);
+
+USHORT RTMPCalcDuration(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Rate,
+ IN ULONG Size);
+
+VOID RTMPWriteTxWI(
+ IN PRTMP_ADAPTER pAd,
+ IN PTXWI_STRUC pTxWI,
+ IN BOOLEAN FRAG,
+ IN BOOLEAN CFACK,
+ IN BOOLEAN InsTimestamp,
+ IN BOOLEAN AMPDU,
+ IN BOOLEAN Ack,
+ IN BOOLEAN NSeq, // HW new a sequence.
+ IN UCHAR BASize,
+ IN UCHAR WCID,
+ IN ULONG Length,
+ IN UCHAR PID,
+ IN UCHAR TID,
+ IN UCHAR TxRate,
+ IN UCHAR Txopmode,
+ IN BOOLEAN CfAck,
+ IN HTTRANSMIT_SETTING *pTransmit);
+
+
+VOID RTMPWriteTxWI_Data(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PTXWI_STRUC pTxWI,
+ IN TX_BLK *pTxBlk);
+
+
+VOID RTMPWriteTxWI_Cache(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PTXWI_STRUC pTxWI,
+ IN TX_BLK *pTxBlk);
+
+VOID RTMPWriteTxDescriptor(
+ IN PRTMP_ADAPTER pAd,
+ IN PTXD_STRUC pTxD,
+ IN BOOLEAN bWIV,
+ IN UCHAR QSEL);
+
+VOID RTMPSuspendMsduTransmission(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPResumeMsduTransmission(
+ IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS MiniportMMRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN PUCHAR pData,
+ IN UINT Length);
+
+VOID RTMPSendNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR TxRate,
+ IN BOOLEAN bQosNull);
+
+VOID RTMPSendDisassociationFrame(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPSendRTSFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN unsigned int NextMpduSize,
+ IN UCHAR TxRate,
+ IN UCHAR RTSRate,
+ IN USHORT AckDuration,
+ IN UCHAR QueIdx,
+ IN UCHAR FrameGap);
+
+
+NDIS_STATUS RTMPApplyPacketFilter(
+ IN PRTMP_ADAPTER pAd,
+ IN PRT28XX_RXD_STRUC pRxD,
+ IN PHEADER_802_11 pHeader);
+
+PQUEUE_HEADER RTMPCheckTxSwQueue(
+ IN PRTMP_ADAPTER pAd,
+ OUT UCHAR *QueIdx);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPReportMicError(
+ IN PRTMP_ADAPTER pAd,
+ IN PCIPHER_KEY pWpaKey);
+
+VOID WpaMicFailureReportFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID WpaDisassocApAndBlockAssoc(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+#endif // CONFIG_STA_SUPPORT //
+
+NDIS_STATUS RTMPCloneNdisPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN pInsAMSDUHdr,
+ IN PNDIS_PACKET pInPacket,
+ OUT PNDIS_PACKET *ppOutPacket);
+
+NDIS_STATUS RTMPAllocateNdisPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET *pPacket,
+ IN PUCHAR pHeader,
+ IN UINT HeaderLen,
+ IN PUCHAR pData,
+ IN UINT DataLen);
+
+VOID RTMPFreeNdisPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+BOOLEAN RTMPFreeTXDUponTxDmaDone(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx);
+
+BOOLEAN RTMPCheckDHCPFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+
+BOOLEAN RTMPCheckEtherType(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+
+VOID RTMPCckBbpTuning(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT TxRate);
+
+//
+// Private routines in rtmp_wep.c
+//
+VOID RTMPInitWepEngine(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKey,
+ IN UCHAR KeyId,
+ IN UCHAR KeyLen,
+ IN PUCHAR pDest);
+
+VOID RTMPEncryptData(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pSrc,
+ IN PUCHAR pDest,
+ IN UINT Len);
+
+BOOLEAN RTMPDecryptData(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PUCHAR pSrc,
+ IN UINT Len,
+ IN UINT idx);
+
+BOOLEAN RTMPSoftDecryptWEP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataByteCnt,
+ IN PCIPHER_KEY pGroupKey);
+
+VOID RTMPSetICV(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDest);
+
+VOID ARCFOUR_INIT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pKey,
+ IN UINT KeyLen);
+
+UCHAR ARCFOUR_BYTE(
+ IN PARCFOURCONTEXT Ctx);
+
+VOID ARCFOUR_DECRYPT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pDest,
+ IN PUCHAR pSrc,
+ IN UINT Len);
+
+VOID ARCFOUR_ENCRYPT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pDest,
+ IN PUCHAR pSrc,
+ IN UINT Len);
+
+VOID WPAARCFOUR_ENCRYPT(
+ IN PARCFOURCONTEXT Ctx,
+ IN PUCHAR pDest,
+ IN PUCHAR pSrc,
+ IN UINT Len);
+
+UINT RTMP_CALC_FCS32(
+ IN UINT Fcs,
+ IN PUCHAR Cp,
+ IN INT Len);
+
+//
+// MLME routines
+//
+
+// Asic/RF/BBP related functions
+
+VOID AsicAdjustTxPower(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicUpdateProtect(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT OperaionMode,
+ IN UCHAR SetMask,
+ IN BOOLEAN bDisableBGProtect,
+ IN BOOLEAN bNonGFExist);
+
+VOID AsicSwitchChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel,
+ IN BOOLEAN bScan);
+
+VOID AsicLockChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel) ;
+
+VOID AsicAntennaSelect(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel);
+
+VOID AsicAntennaSetting(
+ IN PRTMP_ADAPTER pAd,
+ IN ABGBAND_STATE BandState);
+
+VOID AsicRfTuningExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID AsicSleepThenAutoWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT TbttNumToNextWakeUp);
+
+VOID AsicForceSleep(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicForceWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bFromTx);
+#endif // CONFIG_STA_SUPPORT //
+
+VOID AsicSetBssid(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pBssid);
+
+VOID AsicSetMcastWC(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicDelWcidTab(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid);
+
+VOID AsicEnableRDG(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicDisableRDG(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicDisableSync(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicEnableBssSync(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicEnableIbssSync(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicSetEdcaParm(
+ IN PRTMP_ADAPTER pAd,
+ IN PEDCA_PARM pEdcaParm);
+
+VOID AsicSetSlotTime(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bUseShortSlotTime);
+
+VOID AsicAddSharedKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx,
+ IN UCHAR CipherAlg,
+ IN PUCHAR pKey,
+ IN PUCHAR pTxMic,
+ IN PUCHAR pRxMic);
+
+VOID AsicRemoveSharedKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx);
+
+VOID AsicUpdateWCIDAttribute(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN UCHAR BssIndex,
+ IN UCHAR CipherAlg,
+ IN BOOLEAN bUsePairewiseKeyTable);
+
+VOID AsicUpdateWCIDIVEIV(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN ULONG uIV,
+ IN ULONG uEIV);
+
+VOID AsicUpdateRxWCIDTable(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN PUCHAR pAddr);
+
+VOID AsicAddKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT WCID,
+ IN UCHAR BssIndex,
+ IN UCHAR KeyIdx,
+ IN PCIPHER_KEY pCipherKey,
+ IN BOOLEAN bUsePairewiseKeyTable,
+ IN BOOLEAN bTxKey);
+
+VOID AsicAddPairwiseKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UCHAR WCID,
+ IN CIPHER_KEY *pCipherKey);
+
+VOID AsicRemovePairwiseKeyEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIdx,
+ IN UCHAR Wcid);
+
+BOOLEAN AsicSendCommandToMcu(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Command,
+ IN UCHAR Token,
+ IN UCHAR Arg0,
+ IN UCHAR Arg1);
+
+#ifdef RT2860
+BOOLEAN AsicCheckCommanOk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Command);
+#endif // RT2860 //
+
+VOID MacAddrRandomBssid(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pAddr);
+
+VOID MgtMacHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN UCHAR SubType,
+ IN UCHAR ToDs,
+ IN PUCHAR pDA,
+ IN PUCHAR pBssid);
+
+VOID MlmeRadioOff(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeRadioOn(
+ IN PRTMP_ADAPTER pAd);
+
+
+VOID BssTableInit(
+ IN BSS_TABLE *Tab);
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableInit(
+ IN PRTMP_ADAPTER pAd,
+ IN BA_TABLE *Tab);
+#endif // DOT11_N_SUPPORT //
+
+ULONG BssTableSearch(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN UCHAR Channel);
+
+ULONG BssSsidTableSearch(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR pBssid,
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen,
+ IN UCHAR Channel);
+
+ULONG BssTableSearchWithSSID(
+ IN BSS_TABLE *Tab,
+ IN PUCHAR Bssid,
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen,
+ IN UCHAR Channel);
+
+VOID BssTableDeleteEntry(
+ IN OUT PBSS_TABLE pTab,
+ IN PUCHAR pBssid,
+ IN UCHAR Channel);
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableDeleteORIEntry(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN BA_ORI_ENTRY *pBAORIEntry);
+
+VOID BATableDeleteRECEntry(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN BA_REC_ENTRY *pBARECEntry);
+
+VOID BATableTearORIEntry(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR TID,
+ IN UCHAR Wcid,
+ IN BOOLEAN bForceDelete,
+ IN BOOLEAN ALL);
+
+VOID BATableTearRECEntry(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR TID,
+ IN UCHAR WCID,
+ IN BOOLEAN ALL);
+#endif // DOT11_N_SUPPORT //
+
+VOID BssEntrySet(
+ IN PRTMP_ADAPTER pAd,
+ OUT PBSS_ENTRY pBss,
+ IN PUCHAR pBssid,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen,
+ IN UCHAR BssType,
+ IN USHORT BeaconPeriod,
+ IN PCF_PARM CfParm,
+ IN USHORT AtimWin,
+ IN USHORT CapabilityInfo,
+ IN UCHAR SupRate[],
+ IN UCHAR SupRateLen,
+ IN UCHAR ExtRate[],
+ IN UCHAR ExtRateLen,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
+ IN UCHAR HtCapabilityLen,
+ IN UCHAR AddHtInfoLen,
+ IN UCHAR NewExtChanOffset,
+ IN UCHAR Channel,
+ IN CHAR Rssi,
+ IN LARGE_INTEGER TimeStamp,
+ IN UCHAR CkipFlag,
+ IN PEDCA_PARM pEdcaParm,
+ IN PQOS_CAPABILITY_PARM pQosCapability,
+ IN PQBSS_LOAD_PARM pQbssLoad,
+ IN USHORT LengthVIE,
+ IN PNDIS_802_11_VARIABLE_IEs pVIE);
+
+ULONG BssTableSetEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT PBSS_TABLE pTab,
+ IN PUCHAR pBssid,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen,
+ IN UCHAR BssType,
+ IN USHORT BeaconPeriod,
+ IN CF_PARM *CfParm,
+ IN USHORT AtimWin,
+ IN USHORT CapabilityInfo,
+ IN UCHAR SupRate[],
+ IN UCHAR SupRateLen,
+ IN UCHAR ExtRate[],
+ IN UCHAR ExtRateLen,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
+ IN UCHAR HtCapabilityLen,
+ IN UCHAR AddHtInfoLen,
+ IN UCHAR NewExtChanOffset,
+ IN UCHAR Channel,
+ IN CHAR Rssi,
+ IN LARGE_INTEGER TimeStamp,
+ IN UCHAR CkipFlag,
+ IN PEDCA_PARM pEdcaParm,
+ IN PQOS_CAPABILITY_PARM pQosCapability,
+ IN PQBSS_LOAD_PARM pQbssLoad,
+ IN USHORT LengthVIE,
+ IN PNDIS_802_11_VARIABLE_IEs pVIE);
+
+#ifdef DOT11_N_SUPPORT
+VOID BATableInsertEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Aid,
+ IN USHORT TimeOutValue,
+ IN USHORT StartingSeq,
+ IN UCHAR TID,
+ IN UCHAR BAWinSize,
+ IN UCHAR OriginatorStatus,
+ IN BOOLEAN IsRecipient);
+
+#ifdef DOT11N_DRAFT3
+VOID Bss2040CoexistTimeOut(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+
+VOID TriEventInit(
+ IN PRTMP_ADAPTER pAd);
+
+ULONG TriEventTableSetEntry(
+ IN PRTMP_ADAPTER pAd,
+ OUT TRIGGER_EVENT_TAB *Tab,
+ IN PUCHAR pBssid,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN UCHAR HtCapabilityLen,
+ IN UCHAR RegClass,
+ IN UCHAR ChannelNo);
+
+VOID TriEventCounterMaintenance(
+ IN PRTMP_ADAPTER pAd);
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+VOID BssTableSsidSort(
+ IN PRTMP_ADAPTER pAd,
+ OUT BSS_TABLE *OutTab,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen);
+
+VOID BssTableSortByRssi(
+ IN OUT BSS_TABLE *OutTab);
+
+VOID BssCipherParse(
+ IN OUT PBSS_ENTRY pBss);
+
+NDIS_STATUS MlmeQueueInit(
+ IN MLME_QUEUE *Queue);
+
+VOID MlmeQueueDestroy(
+ IN MLME_QUEUE *Queue);
+
+BOOLEAN MlmeEnqueue(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Machine,
+ IN ULONG MsgType,
+ IN ULONG MsgLen,
+ IN VOID *Msg);
+
+BOOLEAN MlmeEnqueueForRecv(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid,
+ IN ULONG TimeStampHigh,
+ IN ULONG TimeStampLow,
+ IN UCHAR Rssi0,
+ IN UCHAR Rssi1,
+ IN UCHAR Rssi2,
+ IN ULONG MsgLen,
+ IN PVOID Msg,
+ IN UCHAR Signal);
+
+
+BOOLEAN MlmeDequeue(
+ IN MLME_QUEUE *Queue,
+ OUT MLME_QUEUE_ELEM **Elem);
+
+VOID MlmeRestartStateMachine(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN MlmeQueueEmpty(
+ IN MLME_QUEUE *Queue);
+
+BOOLEAN MlmeQueueFull(
+ IN MLME_QUEUE *Queue);
+
+BOOLEAN MsgTypeSubst(
+ IN PRTMP_ADAPTER pAd,
+ IN PFRAME_802_11 pFrame,
+ OUT INT *Machine,
+ OUT INT *MsgType);
+
+VOID StateMachineInit(
+ IN STATE_MACHINE *Sm,
+ IN STATE_MACHINE_FUNC Trans[],
+ IN ULONG StNr,
+ IN ULONG MsgNr,
+ IN STATE_MACHINE_FUNC DefFunc,
+ IN ULONG InitState,
+ IN ULONG Base);
+
+VOID StateMachineSetAction(
+ IN STATE_MACHINE *S,
+ IN ULONG St,
+ ULONG Msg,
+ IN STATE_MACHINE_FUNC F);
+
+VOID StateMachinePerformAction(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID Drop(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID AssocStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID ReassocTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID AssocTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID DisassocTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+//----------------------------------------------
+VOID MlmeDisassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeAssocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeReassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDisassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAssocRspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerReassocRspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDisassocAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID DisassocTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID AssocTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID ReassocTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID Cls3errAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr);
+
+VOID SwitchBetweenWepAndCkip(
+ IN PRTMP_ADAPTER pAd);
+
+VOID InvalidStateWhenAssoc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenReassoc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenDisassociate(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+
+VOID ComposePsPoll(
+ IN PRTMP_ADAPTER pAd);
+
+VOID ComposeNullFrame(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AssocPostProc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr2,
+ IN USHORT CapabilityInfo,
+ IN USHORT Aid,
+ IN UCHAR SupRate[],
+ IN UCHAR SupRateLen,
+ IN UCHAR ExtRate[],
+ IN UCHAR ExtRateLen,
+ IN PEDCA_PARM pEdcaParm,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN UCHAR HtCapabilityLen,
+ IN ADD_HT_INFO_IE *pAddHtInfo);
+
+VOID AuthStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTATE_MACHINE sm,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID AuthTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID MlmeAuthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAuthRspAtSeq2Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAuthRspAtSeq4Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID AuthTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID Cls2errAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr);
+
+VOID MlmeDeauthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenAuth(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+//=============================================
+
+VOID AuthRspStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTATE_MACHINE Sm,
+ IN STATE_MACHINE_FUNC Trans[]);
+
+VOID PeerDeauthAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerAuthSimpleRspGenAndSend(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHdr80211,
+ IN USHORT Alg,
+ IN USHORT Seq,
+ IN USHORT Reason,
+ IN USHORT Status);
+
+//
+// Private routines in dls.c
+//
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef QOS_DLS_SUPPORT
+void DlsStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID MlmeDlsReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDlsReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDlsRspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeDlsTearDownAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerDlsTearDownAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID RTMPCheckDLSTimeOut(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN RTMPRcvFrameDLSCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHeader,
+ IN ULONG Len,
+ IN PRT28XX_RXD_STRUC pRxD);
+
+INT RTMPCheckDLSFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA);
+
+VOID RTMPSendDLSTearDownFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA);
+
+NDIS_STATUS RTMPSendSTAKeyRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA);
+
+NDIS_STATUS RTMPSendSTAKeyHandShake(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA);
+
+VOID DlsTimeoutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+BOOLEAN MlmeDlsReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PRT_802_11_DLS *pDLS,
+ OUT PUSHORT pReason);
+
+INT Set_DlsEntryInfo_Display_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+MAC_TABLE_ENTRY *MacTableInsertDlsEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UINT DlsEntryIdx);
+
+BOOLEAN MacTableDeleteDlsEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT wcid,
+ IN PUCHAR pAddr);
+
+MAC_TABLE_ENTRY *DlsEntryTableLookup(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN BOOLEAN bResetIdelCount);
+
+MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR wcid,
+ IN PUCHAR pAddr,
+ IN BOOLEAN bResetIdelCount);
+
+INT Set_DlsAddEntry_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_DlsTearDownEntry_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif // QOS_DLS_SUPPORT //
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef QOS_DLS_SUPPORT
+BOOLEAN PeerDlsReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pDlsTimeout,
+ OUT UCHAR *pRatesLen,
+ OUT UCHAR Rates[],
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability);
+
+BOOLEAN PeerDlsRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pStatus,
+ OUT UCHAR *pRatesLen,
+ OUT UCHAR Rates[],
+ OUT UCHAR *pHtCapabilityLen,
+ OUT HT_CAPABILITY_IE *pHtCapability);
+
+BOOLEAN PeerDlsTearDownSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pDA,
+ OUT PUCHAR pSA,
+ OUT USHORT *pReason);
+#endif // QOS_DLS_SUPPORT //
+
+//========================================
+
+VOID SyncStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID BeaconTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID ScanTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID MlmeScanReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenScan(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenJoin(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID InvalidStateWhenStart(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeacon(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID EnqueueProbeRequest(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN ScanRunning(
+ IN PRTMP_ADAPTER pAd);
+//=========================================
+
+VOID MlmeCntlInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID MlmeCntlMachinePerformAction(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlIdleProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlOidScanProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlOidSsidProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM * Elem);
+
+VOID CntlOidRTBssidProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM * Elem);
+
+VOID CntlMlmeRoamingProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM * Elem);
+
+VOID CntlWaitDisassocProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitJoinProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitReassocProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitStartProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitAuthProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitAuthProc2(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CntlWaitAssocProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+#ifdef QOS_DLS_SUPPORT
+VOID CntlOidDLSSetupProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+#endif // QOS_DLS_SUPPORT //
+
+VOID LinkUp(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssType);
+
+VOID LinkDown(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN IsReqFromAP);
+
+VOID IterateOnBssTab(
+ IN PRTMP_ADAPTER pAd);
+
+VOID IterateOnBssTab2(
+ IN PRTMP_ADAPTER pAd);;
+
+VOID JoinParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_JOIN_REQ_STRUCT *JoinReq,
+ IN ULONG BssIdx);
+
+VOID AssocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq,
+ IN PUCHAR pAddr,
+ IN USHORT CapabilityInfo,
+ IN ULONG Timeout,
+ IN USHORT ListenIntv);
+
+VOID ScanParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_SCAN_REQ_STRUCT *ScanReq,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen,
+ IN UCHAR BssType,
+ IN UCHAR ScanType);
+
+VOID DisassocParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq,
+ IN PUCHAR pAddr,
+ IN USHORT Reason);
+
+VOID StartParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_START_REQ_STRUCT *StartReq,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen);
+
+VOID AuthParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_AUTH_REQ_STRUCT *AuthReq,
+ IN PUCHAR pAddr,
+ IN USHORT Alg);
+
+VOID EnqueuePsPoll(
+ IN PRTMP_ADAPTER pAd);
+
+VOID EnqueueBeaconFrame(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeJoinReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeScanReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID MlmeStartReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID ScanTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID BeaconTimeoutAtJoinAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeaconAtScanAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeaconAtJoinAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerBeacon(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerProbeReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID ScanNextChannel(
+ IN PRTMP_ADAPTER pAd);
+
+ULONG MakeIbssBeacon(
+ IN PRTMP_ADAPTER pAd);
+
+VOID CCXAdjacentAPReport(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN MlmeScanReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT UCHAR *BssType,
+ OUT CHAR ssid[],
+ OUT UCHAR *SsidLen,
+ OUT UCHAR *ScanType);
+
+BOOLEAN PeerBeaconAndProbeRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ IN UCHAR MsgChannel,
+ OUT PUCHAR pAddr2,
+ OUT PUCHAR pBssid,
+ OUT CHAR Ssid[],
+ OUT UCHAR *pSsidLen,
+ OUT UCHAR *pBssType,
+ OUT USHORT *pBeaconPeriod,
+ OUT UCHAR *pChannel,
+ OUT UCHAR *pNewChannel,
+ OUT LARGE_INTEGER *pTimestamp,
+ OUT CF_PARM *pCfParm,
+ OUT USHORT *pAtimWin,
+ OUT USHORT *pCapabilityInfo,
+ OUT UCHAR *pErp,
+ OUT UCHAR *pDtimCount,
+ OUT UCHAR *pDtimPeriod,
+ OUT UCHAR *pBcastFlag,
+ OUT UCHAR *pMessageToMe,
+ OUT UCHAR SupRate[],
+ OUT UCHAR *pSupRateLen,
+ OUT UCHAR ExtRate[],
+ OUT UCHAR *pExtRateLen,
+ OUT UCHAR *pCkipFlag,
+ OUT UCHAR *pAironetCellPowerLimit,
+ OUT PEDCA_PARM pEdcaParm,
+ OUT PQBSS_LOAD_PARM pQbssLoad,
+ OUT PQOS_CAPABILITY_PARM pQosCapability,
+ OUT ULONG *pRalinkIe,
+ OUT UCHAR *pHtCapabilityLen,
+#ifdef CONFIG_STA_SUPPORT
+ OUT UCHAR *pPreNHtCapabilityLen,
+#endif // CONFIG_STA_SUPPORT //
+ OUT HT_CAPABILITY_IE *pHtCapability,
+ OUT UCHAR *AddHtInfoLen,
+ OUT ADD_HT_INFO_IE *AddHtInfo,
+ OUT UCHAR *NewExtChannel,
+ OUT USHORT *LengthVIE,
+ OUT PNDIS_802_11_VARIABLE_IEs pVIE);
+
+BOOLEAN PeerAddBAReqActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2);
+
+BOOLEAN PeerAddBARspActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen);
+
+BOOLEAN PeerDelBAActionSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN VOID *pMsg,
+ IN ULONG MsgLen);
+
+BOOLEAN MlmeAssocReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pApAddr,
+ OUT USHORT *CapabilityInfo,
+ OUT ULONG *Timeout,
+ OUT USHORT *ListenIntv);
+
+BOOLEAN MlmeAuthReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr,
+ OUT ULONG *Timeout,
+ OUT USHORT *Alg);
+
+BOOLEAN MlmeStartReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT CHAR Ssid[],
+ OUT UCHAR *Ssidlen);
+
+BOOLEAN PeerAuthSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr,
+ OUT USHORT *Alg,
+ OUT USHORT *Seq,
+ OUT USHORT *Status,
+ OUT CHAR ChlgText[]);
+
+BOOLEAN PeerAssocRspSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *pMsg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *pCapabilityInfo,
+ OUT USHORT *pStatus,
+ OUT USHORT *pAid,
+ OUT UCHAR SupRate[],
+ OUT UCHAR *pSupRateLen,
+ OUT UCHAR ExtRate[],
+ OUT UCHAR *pExtRateLen,
+ OUT HT_CAPABILITY_IE *pHtCapability,
+ OUT ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
+ OUT UCHAR *pHtCapabilityLen,
+ OUT UCHAR *pAddHtInfoLen,
+ OUT UCHAR *pNewExtChannelOffset,
+ OUT PEDCA_PARM pEdcaParm,
+ OUT UCHAR *pCkipFlag);
+
+BOOLEAN PeerDisassocSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *Reason);
+
+BOOLEAN PeerWpaMessageSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN PEAPOL_PACKET pMsg,
+ IN ULONG MsgLen,
+ IN UCHAR MsgType,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+BOOLEAN PeerDeauthSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT USHORT *Reason);
+
+BOOLEAN PeerProbeReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2,
+ OUT CHAR Ssid[],
+ OUT UCHAR *pSsidLen);
+
+BOOLEAN GetTimBit(
+ IN CHAR *Ptr,
+ IN USHORT Aid,
+ OUT UCHAR *TimLen,
+ OUT UCHAR *BcastFlag,
+ OUT UCHAR *DtimCount,
+ OUT UCHAR *DtimPeriod,
+ OUT UCHAR *MessageToMe);
+
+UCHAR ChannelSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel);
+
+NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(
+ IN PBSS_ENTRY pBss);
+
+BOOLEAN MlmeDelBAReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen);
+
+BOOLEAN MlmeAddBAReqSanity(
+ IN PRTMP_ADAPTER pAd,
+ IN VOID *Msg,
+ IN ULONG MsgLen,
+ OUT PUCHAR pAddr2);
+
+ULONG MakeOutgoingFrame(
+ OUT CHAR *Buffer,
+ OUT ULONG *Length, ...);
+
+VOID LfsrInit(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Seed);
+
+UCHAR RandomByte(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicUpdateAutoFallBackTable(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pTxRate);
+
+VOID MlmePeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID LinkDownExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID LinkUpExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID STAMlmePeriodicExec(
+ PRTMP_ADAPTER pAd);
+
+VOID MlmeAutoScan(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeAutoReconnectLastSSID(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN MlmeValidateSSID(
+ IN PUCHAR pSsid,
+ IN UCHAR SsidLen);
+
+VOID MlmeCheckForRoaming(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now32);
+
+VOID MlmeCheckForFastRoaming(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now);
+
+VOID MlmeDynamicTxRateSwitching(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeSetTxRate(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PRTMP_TX_RATE_SWITCH pTxRate);
+
+VOID MlmeSelectTxRateTable(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR *ppTable,
+ IN PUCHAR pTableSize,
+ IN PUCHAR pInitTxRateIdx);
+
+VOID MlmeCalculateChannelQuality(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now);
+
+VOID MlmeCheckPsmChange(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Now32);
+
+VOID MlmeSetPsmBit(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT psm);
+
+VOID MlmeSetTxPreamble(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT TxPreamble);
+
+VOID UpdateBasicRateBitmap(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeUpdateTxRates(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bLinkUp,
+ IN UCHAR apidx);
+
+#ifdef DOT11_N_SUPPORT
+VOID MlmeUpdateHtTxRates(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apidx);
+#endif // DOT11_N_SUPPORT //
+
+VOID RTMPCheckRates(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT UCHAR SupRate[],
+ IN OUT UCHAR *SupRateLen);
+
+#ifdef CONFIG_STA_SUPPORT
+BOOLEAN RTMPCheckChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR CentralChannel,
+ IN UCHAR Channel);
+#endif // CONFIG_STA_SUPPORT //
+
+BOOLEAN RTMPCheckHt(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN OUT HT_CAPABILITY_IE *pHtCapability,
+ IN OUT ADD_HT_INFO_IE *pAddHtInfo);
+
+VOID StaQuickResponeForRateUpExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID AsicBbpTuning1(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicBbpTuning2(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPUpdateMlmeRate(
+ IN PRTMP_ADAPTER pAd);
+
+CHAR RTMPMaxRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi0,
+ IN CHAR Rssi1,
+ IN CHAR Rssi2);
+
+VOID AsicEvaluateRxAnt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID AsicRxAntEvalTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID APSDPeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry);
+
+UCHAR RTMPStaFixedTxMode(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry);
+
+VOID RTMPUpdateLegacyTxSetting(
+ UCHAR fixed_tx_mode,
+ PMAC_TABLE_ENTRY pEntry);
+
+BOOLEAN RTMPAutoRateSwitchCheck(
+ IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS MlmeInit(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeHandler(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeHalt(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MlmeResetRalinkCounters(
+ IN PRTMP_ADAPTER pAd);
+
+VOID BuildChannelList(
+ IN PRTMP_ADAPTER pAd);
+
+UCHAR FirstChannel(
+ IN PRTMP_ADAPTER pAd);
+
+UCHAR NextChannel(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR channel);
+
+VOID ChangeToCellPowerLimit(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR AironetCellPowerLimit);
+
+VOID RaiseClock(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 *x);
+
+VOID LowerClock(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT32 *x);
+
+USHORT ShiftInBits(
+ IN PRTMP_ADAPTER pAd);
+
+VOID ShiftOutBits(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT data,
+ IN USHORT count);
+
+VOID EEpromCleanup(
+ IN PRTMP_ADAPTER pAd);
+
+VOID EWDS(
+ IN PRTMP_ADAPTER pAd);
+
+VOID EWEN(
+ IN PRTMP_ADAPTER pAd);
+
+USHORT RTMP_EEPROM_READ16(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset);
+
+VOID RTMP_EEPROM_WRITE16(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Offset,
+ IN USHORT Data);
+
+//
+// Prototypes of function definition in rtmp_tkip.c
+//
+VOID RTMPInitTkipEngine(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pTKey,
+ IN UCHAR KeyId,
+ IN PUCHAR pTA,
+ IN PUCHAR pMICKey,
+ IN PUCHAR pTSC,
+ OUT PULONG pIV16,
+ OUT PULONG pIV32);
+
+VOID RTMPInitMICEngine(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKey,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN UCHAR UserPriority,
+ IN PUCHAR pMICKey);
+
+BOOLEAN RTMPTkipCompareMICValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pSrc,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN PUCHAR pMICKey,
+ IN UCHAR UserPriority,
+ IN UINT Len);
+
+VOID RTMPCalculateMICValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pEncap,
+ IN PCIPHER_KEY pKey,
+ IN UCHAR apidx);
+
+BOOLEAN RTMPTkipCompareMICValueWithLLC(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pLLC,
+ IN PUCHAR pSrc,
+ IN PUCHAR pDA,
+ IN PUCHAR pSA,
+ IN PUCHAR pMICKey,
+ IN UINT Len);
+
+VOID RTMPTkipAppendByte(
+ IN PTKIP_KEY_INFO pTkip,
+ IN UCHAR uChar);
+
+VOID RTMPTkipAppend(
+ IN PTKIP_KEY_INFO pTkip,
+ IN PUCHAR pSrc,
+ IN UINT nBytes);
+
+VOID RTMPTkipGetMIC(
+ IN PTKIP_KEY_INFO pTkip);
+
+BOOLEAN RTMPSoftDecryptTKIP(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataByteCnt,
+ IN UCHAR UserPriority,
+ IN PCIPHER_KEY pWpaKey);
+
+BOOLEAN RTMPSoftDecryptAES(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataByteCnt,
+ IN PCIPHER_KEY pWpaKey);
+
+//
+// Prototypes of function definition in cmm_info.c
+//
+NDIS_STATUS RTMPWPARemoveKeyProc(
+ IN PRTMP_ADAPTER pAd,
+ IN PVOID pBuf);
+
+VOID RTMPWPARemoveAllKeys(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN RTMPCheckStrPrintAble(
+ IN CHAR *pInPutStr,
+ IN UCHAR strLen);
+
+VOID RTMPSetPhyMode(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG phymode);
+
+VOID RTMPUpdateHTIE(
+ IN RT_HT_CAPABILITY *pRtHt,
+ IN UCHAR *pMcsSet,
+ OUT HT_CAPABILITY_IE *pHtCapability,
+ OUT ADD_HT_INFO_IE *pAddHtInfo);
+
+VOID RTMPAddWcidAttributeEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssIdx,
+ IN UCHAR KeyIdx,
+ IN UCHAR CipherAlg,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+CHAR *GetEncryptType(
+ CHAR enc);
+
+CHAR *GetAuthMode(
+ CHAR auth);
+
+VOID RTMPIoctlGetSiteSurvey(
+ IN PRTMP_ADAPTER pAdapter,
+ IN struct iwreq *wrq);
+
+VOID RTMPIoctlGetMacTable(
+ IN PRTMP_ADAPTER pAd,
+ IN struct iwreq *wrq);
+
+VOID RTMPIndicateWPA2Status(
+ IN PRTMP_ADAPTER pAdapter);
+
+VOID RTMPOPModeSwitching(
+ IN PRTMP_ADAPTER pAd);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPAddBSSIDCipher(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Aid,
+ IN PNDIS_802_11_KEY pKey,
+ IN UCHAR CipherAlg);
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef DOT11_N_SUPPORT
+VOID RTMPSetHT(
+ IN PRTMP_ADAPTER pAd,
+ IN OID_SET_HT_PHYMODE *pHTPhyMode);
+
+VOID RTMPSetIndividualHT(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apidx);
+#endif // DOT11_N_SUPPORT //
+
+VOID RTMPSendWirelessEvent(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Event_flag,
+ IN PUCHAR pAddr,
+ IN UCHAR BssIdx,
+ IN CHAR Rssi);
+
+VOID NICUpdateCntlCounters(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHeader,
+ IN UCHAR SubType,
+ IN PRXWI_STRUC pRxWI);
+//
+// prototype in wpa.c
+//
+BOOLEAN WpaMsgTypeSubst(
+ IN UCHAR EAPType,
+ OUT INT *MsgType);
+
+VOID WpaPskStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID WpaEAPOLKeyAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID WpaPairMsg1Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID WpaPairMsg3Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID WpaGroupMsg1Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID WpaMacHeaderInit(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT PHEADER_802_11 pHdr80211,
+ IN UCHAR wep,
+ IN PUCHAR pAddr1);
+
+VOID Wpa2PairMsg1Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID Wpa2PairMsg3Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+BOOLEAN ParseKeyData(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKeyData,
+ IN UCHAR KeyDataLen,
+ IN UCHAR bPairewise);
+
+VOID RTMPToWirelessSta(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHeader802_3,
+ IN UINT HdrLen,
+ IN PUCHAR pData,
+ IN UINT DataLen,
+ IN BOOLEAN is4wayFrame);
+
+VOID HMAC_SHA1(
+ IN UCHAR *text,
+ IN UINT text_len,
+ IN UCHAR *key,
+ IN UINT key_len,
+ IN UCHAR *digest);
+
+VOID PRF(
+ IN UCHAR *key,
+ IN INT key_len,
+ IN UCHAR *prefix,
+ IN INT prefix_len,
+ IN UCHAR *data,
+ IN INT data_len,
+ OUT UCHAR *output,
+ IN INT len);
+
+VOID CCKMPRF(
+ IN UCHAR *key,
+ IN INT key_len,
+ IN UCHAR *data,
+ IN INT data_len,
+ OUT UCHAR *output,
+ IN INT len);
+
+VOID WpaCountPTK(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR *PMK,
+ IN UCHAR *ANonce,
+ IN UCHAR *AA,
+ IN UCHAR *SNonce,
+ IN UCHAR *SA,
+ OUT UCHAR *output,
+ IN UINT len);
+
+VOID GenRandom(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR *macAddr,
+ OUT UCHAR *random);
+
+//
+// prototype in aironet.c
+//
+VOID AironetStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[]);
+
+VOID AironetMsgAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID AironetRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID ChannelLoadRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index);
+
+VOID NoiseHistRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index);
+
+VOID BeaconRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index);
+
+VOID AironetReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID ChannelLoadReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index);
+
+VOID NoiseHistReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index);
+
+VOID AironetFinalReportAction(
+ IN PRTMP_ADAPTER pAd);
+
+VOID BeaconReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index);
+
+VOID AironetAddBeaconReport(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Index,
+ IN PMLME_QUEUE_ELEM pElem);
+
+VOID AironetCreateBeaconReportFromBssTable(
+ IN PRTMP_ADAPTER pAd);
+
+VOID DBGPRINT_TX_RING(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx);
+
+VOID DBGPRINT_RX_RING(
+ IN PRTMP_ADAPTER pAd);
+
+CHAR ConvertToRssi(
+ IN PRTMP_ADAPTER pAd,
+ IN CHAR Rssi,
+ IN UCHAR RssiNumber);
+
+
+#ifdef DOT11N_DRAFT3
+VOID BuildEffectedChannelList(
+ IN PRTMP_ADAPTER pAd);
+#endif // DOT11N_DRAFT3 //
+
+
+VOID APAsicEvaluateRxAnt(
+ IN PRTMP_ADAPTER pAd);
+
+
+VOID APAsicRxAntEvalTimeout(
+ IN PRTMP_ADAPTER pAd);
+
+//
+// function prototype in cmm_wpa.c
+//
+BOOLEAN RTMPCheckWPAframe(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR pData,
+ IN ULONG DataByteCount,
+ IN UCHAR FromWhichBSSID);
+
+VOID AES_GTK_KEY_UNWRAP(
+ IN UCHAR *key,
+ OUT UCHAR *plaintext,
+ IN UCHAR c_len,
+ IN UCHAR *ciphertext);
+
+BOOLEAN RTMPCheckRSNIE(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN UCHAR DataLen,
+ IN MAC_TABLE_ENTRY *pEntry,
+ OUT UCHAR *Offset);
+
+BOOLEAN RTMPParseEapolKeyData(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pKeyData,
+ IN UCHAR KeyDataLen,
+ IN UCHAR GroupKeyIndex,
+ IN UCHAR MsgType,
+ IN BOOLEAN bWPA2,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+VOID ConstructEapolMsg(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR PeerAuthMode,
+ IN UCHAR PeerWepStatus,
+ IN UCHAR MyGroupKeyWepStatus,
+ IN UCHAR MsgType,
+ IN UCHAR DefaultKeyIdx,
+ IN UCHAR *ReplayCounter,
+ IN UCHAR *KeyNonce,
+ IN UCHAR *TxRSC,
+ IN UCHAR *PTK,
+ IN UCHAR *GTK,
+ IN UCHAR *RSNIE,
+ IN UCHAR RSNIE_Len,
+ OUT PEAPOL_PACKET pMsg);
+
+VOID CalculateMIC(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR PeerWepStatus,
+ IN UCHAR *PTK,
+ OUT PEAPOL_PACKET pMsg);
+
+NDIS_STATUS RTMPSoftDecryptBroadCastData(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher,
+ IN PCIPHER_KEY pShard_key);
+
+VOID ConstructEapolKeyData(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR PeerAuthMode,
+ IN UCHAR PeerWepStatus,
+ IN UCHAR GroupKeyWepStatus,
+ IN UCHAR MsgType,
+ IN UCHAR DefaultKeyIdx,
+ IN BOOLEAN bWPA2Capable,
+ IN UCHAR *PTK,
+ IN UCHAR *GTK,
+ IN UCHAR *RSNIE,
+ IN UCHAR RSNIE_LEN,
+ OUT PEAPOL_PACKET pMsg);
+
+VOID RTMPMakeRSNIE(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT AuthMode,
+ IN UINT WepStatus,
+ IN UCHAR apidx);
+
+//
+// function prototype in ap_wpa.c
+//
+
+BOOLEAN APWpaMsgTypeSubst(
+ IN UCHAR EAPType,
+ OUT INT *MsgType) ;
+
+MAC_TABLE_ENTRY *PACInquiry(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid);
+
+BOOLEAN RTMPCheckMcast(
+ IN PRTMP_ADAPTER pAd,
+ IN PEID_STRUCT eid_ptr,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+BOOLEAN RTMPCheckUcast(
+ IN PRTMP_ADAPTER pAd,
+ IN PEID_STRUCT eid_ptr,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+BOOLEAN RTMPCheckAUTH(
+ IN PRTMP_ADAPTER pAd,
+ IN PEID_STRUCT eid_ptr,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+VOID WPAStart4WayHS(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN ULONG TimeInterval);
+
+VOID WPAStart2WayGroupHS(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+VOID APWpaEAPPacketAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLStartAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLLogoffAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLKeyAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID APWpaEAPOLASFAlertAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID HandleCounterMeasure(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+VOID PeerPairMsg2Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerPairMsg4Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID CMTimerExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID WPARetryExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID EnqueueStartForPSKExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID RTMPHandleSTAKey(
+ IN PRTMP_ADAPTER pAdapter,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN MLME_QUEUE_ELEM *Elem);
+
+VOID PeerGroupMsg2Action(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN VOID *Msg,
+ IN UINT MsgLen);
+
+VOID PairDisAssocAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN USHORT Reason);
+
+VOID MlmeDeAuthAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN USHORT Reason);
+
+VOID GREKEYPeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID CountGTK(
+ IN UCHAR *PMK,
+ IN UCHAR *GNonce,
+ IN UCHAR *AA,
+ OUT UCHAR *output,
+ IN UINT len);
+
+VOID GetSmall(
+ IN PVOID pSrc1,
+ IN PVOID pSrc2,
+ OUT PUCHAR out,
+ IN ULONG Length);
+
+VOID GetLarge(
+ IN PVOID pSrc1,
+ IN PVOID pSrc2,
+ OUT PUCHAR out,
+ IN ULONG Length);
+
+VOID APGenRandom(
+ IN PRTMP_ADAPTER pAd,
+ OUT UCHAR *random);
+
+VOID AES_GTK_KEY_WRAP(
+ IN UCHAR *key,
+ IN UCHAR *plaintext,
+ IN UCHAR p_len,
+ OUT UCHAR *ciphertext);
+
+VOID WpaSend(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PUCHAR pPacket,
+ IN ULONG Len);
+
+VOID APToWirelessSta(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN PUCHAR pHeader802_3,
+ IN UINT HdrLen,
+ IN PUCHAR pData,
+ IN UINT DataLen,
+ IN BOOLEAN bClearFrame);
+
+VOID RTMPAddPMKIDCache(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx,
+ IN PUCHAR pAddr,
+ IN UCHAR *PMKID,
+ IN UCHAR *PMK);
+
+INT RTMPSearchPMKIDCache(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx,
+ IN PUCHAR pAddr);
+
+VOID RTMPDeletePMKIDCache(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx,
+ IN INT idx);
+
+VOID RTMPMaintainPMKIDCache(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPSendTriggerFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PVOID pBuffer,
+ IN ULONG Length,
+ IN UCHAR TxRate,
+ IN BOOLEAN bQosNull);
+
+
+/* timeout -- ms */
+VOID RTMP_SetPeriodicTimer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN unsigned long timeout);
+
+VOID RTMP_OS_Init_Timer(
+ IN PRTMP_ADAPTER pAd,
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN TIMER_FUNCTION function,
+ IN PVOID data);
+
+VOID RTMP_OS_Add_Timer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN unsigned long timeout);
+
+VOID RTMP_OS_Mod_Timer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ IN unsigned long timeout);
+
+
+VOID RTMP_OS_Del_Timer(
+ IN NDIS_MINIPORT_TIMER *pTimer,
+ OUT BOOLEAN *pCancelled);
+
+
+VOID RTMP_OS_Release_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PQUEUE_ENTRY pEntry);
+
+VOID RTMPusecDelay(
+ IN ULONG usec);
+
+NDIS_STATUS os_alloc_mem(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR *mem,
+ IN ULONG size);
+
+NDIS_STATUS os_free_mem(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR mem);
+
+
+void RTMP_AllocateSharedMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+VOID RTMPFreeTxRxRingMemory(
+ IN PRTMP_ADAPTER pAd);
+
+NDIS_STATUS AdapterBlockAllocateMemory(
+ IN PVOID handle,
+ OUT PVOID *ppAd);
+
+void RTMP_AllocateTxDescMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT Index,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+void RTMP_AllocateFirstTxBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN UINT Index,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+void RTMP_AllocateMgmtDescMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+void RTMP_AllocateRxDescMemory(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+PNDIS_PACKET RTMP_AllocateRxPacketBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress,
+ OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress);
+
+PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length,
+ IN BOOLEAN Cached,
+ OUT PVOID *VirtualAddress);
+
+PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Length);
+
+void RTMP_QueryPacketInfo(
+ IN PNDIS_PACKET pPacket,
+ OUT PACKET_INFO *pPacketInfo,
+ OUT PUCHAR *pSrcBufVA,
+ OUT UINT *pSrcBufLen);
+
+void RTMP_QueryNextPacketInfo(
+ IN PNDIS_PACKET *ppPacket,
+ OUT PACKET_INFO *pPacketInfo,
+ OUT PUCHAR *pSrcBufVA,
+ OUT UINT *pSrcBufLen);
+
+
+BOOLEAN RTMP_FillTxBlkInfo(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk);
+
+
+PRTMP_SCATTER_GATHER_LIST
+rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg);
+
+
+ void announce_802_3_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+
+UINT BA_Reorder_AMSDU_Annnounce(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket);
+
+
+UINT Handle_AMSDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pData,
+ IN ULONG DataSize,
+ IN UCHAR FromWhichBSSID);
+
+
+void convert_802_11_to_802_3_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR p8023hdr,
+ IN PUCHAR pData,
+ IN ULONG DataSize,
+ IN UCHAR FromWhichBSSID);
+
+
+PNET_DEV get_netdev_from_bssid(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR FromWhichBSSID);
+
+
+PNDIS_PACKET duplicate_pkt(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHeader802_3,
+ IN UINT HdrLen,
+ IN PUCHAR pData,
+ IN ULONG DataSize,
+ IN UCHAR FromWhichBSSID);
+
+
+PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pOldPkt);
+
+PNDIS_PACKET duplicate_pkt_with_VLAN(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHeader802_3,
+ IN UINT HdrLen,
+ IN PUCHAR pData,
+ IN ULONG DataSize,
+ IN UCHAR FromWhichBSSID);
+
+PNDIS_PACKET duplicate_pkt_with_WPI(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UINT32 ext_head_len,
+ IN UINT32 ext_tail_len);
+
+UCHAR VLAN_8023_Header_Copy(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pHeader802_3,
+ IN UINT HdrLen,
+ OUT PUCHAR pData,
+ IN UCHAR FromWhichBSSID);
+
+#ifdef DOT11_N_SUPPORT
+void ba_flush_reordering_timeout_mpdus(
+ IN PRTMP_ADAPTER pAd,
+ IN PBA_REC_ENTRY pBAEntry,
+ IN ULONG Now32);
+
+
+VOID BAOriSessionSetUp(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN UCHAR TID,
+ IN USHORT TimeOut,
+ IN ULONG DelayTime,
+ IN BOOLEAN isForced);
+
+VOID BASessionTearDownALL(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid);
+#endif // DOT11_N_SUPPORT //
+
+BOOLEAN OS_Need_Clone_Packet(void);
+
+
+VOID build_tx_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pFrame,
+ IN ULONG FrameLen);
+
+
+VOID BAOriSessionTearDown(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR TID,
+ IN BOOLEAN bPassive,
+ IN BOOLEAN bForceSend);
+
+VOID BARecSessionTearDown(
+ IN OUT PRTMP_ADAPTER pAd,
+ IN UCHAR Wcid,
+ IN UCHAR TID,
+ IN BOOLEAN bPassive);
+
+BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num);
+void ba_reordering_resource_release(PRTMP_ADAPTER pAd);
+
+ULONG AutoChBssInsertEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pBssid,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen,
+ IN UCHAR ChannelNo,
+ IN CHAR Rssi);
+
+void AutoChBssTableInit(
+ IN PRTMP_ADAPTER pAd);
+
+void ChannelInfoInit(
+ IN PRTMP_ADAPTER pAd);
+
+void AutoChBssTableDestroy(
+ IN PRTMP_ADAPTER pAd);
+
+void ChannelInfoDestroy(
+ IN PRTMP_ADAPTER pAd);
+
+UCHAR New_ApAutoSelectChannel(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN rtstrmactohex(
+ IN char *s1,
+ IN char *s2);
+
+BOOLEAN rtstrcasecmp(
+ IN char *s1,
+ IN char *s2);
+
+char *rtstrstruncasecmp(
+ IN char *s1,
+ IN char *s2);
+
+char *rtstrstr(
+ IN const char * s1,
+ IN const char * s2);
+
+char *rstrtok(
+ IN char * s,
+ IN const char * ct);
+
+int rtinet_aton(
+ const char *cp,
+ unsigned int *addr);
+
+////////// common ioctl functions //////////
+INT Set_DriverVersion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_CountryRegion_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_CountryRegionABand_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_WirelessMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_Channel_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ShortSlot_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_TxPower_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_BGProtection_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_TxPreamble_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_RTSThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_FragThreshold_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_TxBurst_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+#ifdef AGGREGATION_SUPPORT
+INT Set_PktAggregate_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif
+
+INT Set_IEEE80211H_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+#ifdef DBG
+INT Set_Debug_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif
+
+INT Show_DescInfo_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ResetStatCounter_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+#ifdef DOT11_N_SUPPORT
+INT Set_BASetup_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_BADecline_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_BAOriTearDown_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_BARecTearDown_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtBw_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtMcs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtGi_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtOpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtStbc_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtHtc_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtExtcha_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtMpduDensity_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtBaWinSize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtRdg_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtLinkAdapt_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtAmsdu_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtAutoBa_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtProtect_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtMimoPs_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+
+INT Set_ForceShortGI_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_ForceGF_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT SetCommonHT(
+ IN PRTMP_ADAPTER pAd);
+
+INT Set_SendPSMPAction_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_HtMIMOPSmode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+
+INT Set_HtTxBASize_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif // DOT11_N_SUPPORT //
+
+
+
+#ifdef CONFIG_STA_SUPPORT
+//Dls , kathy
+VOID RTMPSendDLSTearDownFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA);
+
+#ifdef DOT11_N_SUPPORT
+//Block ACK
+VOID QueryBATABLE(
+ IN PRTMP_ADAPTER pAd,
+ OUT PQUERYBA_TABLE pBAT);
+#endif // DOT11_N_SUPPORT //
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+INT WpaCheckEapCode(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pFrame,
+ IN USHORT FrameLen,
+ IN USHORT OffSet);
+
+VOID WpaSendMicFailureToWpaSupplicant(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bUnicast);
+
+VOID SendAssocIEsToWpaSupplicant(
+ IN PRTMP_ADAPTER pAd);
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+int wext_notify_event_assoc(
+ IN RTMP_ADAPTER *pAd);
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+#endif // CONFIG_STA_SUPPORT //
+
+
+
+#ifdef DOT11_N_SUPPORT
+VOID Handle_BSS_Width_Trigger_Events(
+ IN PRTMP_ADAPTER pAd);
+
+void build_ext_channel_switch_ie(
+ IN PRTMP_ADAPTER pAd,
+ IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE);
+#endif // DOT11_N_SUPPORT //
+
+
+BOOLEAN APRxDoneInterruptHandle(
+ IN PRTMP_ADAPTER pAd);
+
+BOOLEAN STARxDoneInterruptHandle(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN argc);
+
+#ifdef DOT11_N_SUPPORT
+// AMPDU packet indication
+VOID Indicate_AMPDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+// AMSDU packet indication
+VOID Indicate_AMSDU_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+#endif // DOT11_N_SUPPORT //
+
+// Normal legacy Rx packet indication
+VOID Indicate_Legacy_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+VOID Indicate_EAPOL_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+void update_os_packet_info(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+void wlan_802_11_to_802_3_packet(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN PUCHAR pHeader802_3,
+ IN UCHAR FromWhichBSSID);
+
+UINT deaggregate_AMSDU_announce(
+ IN PRTMP_ADAPTER pAd,
+ PNDIS_PACKET pPacket,
+ IN PUCHAR pData,
+ IN ULONG DataSize);
+
+
+#ifdef CONFIG_STA_SUPPORT
+// remove LLC and get 802_3 Header
+#define RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(_pRxBlk, _pHeader802_3) \
+{ \
+ PUCHAR _pRemovedLLCSNAP = NULL, _pDA, _pSA; \
+ \
+ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_MESH)) \
+ { \
+ _pDA = _pRxBlk->pHeader->Addr3; \
+ _pSA = (PUCHAR)_pRxBlk->pHeader + sizeof(HEADER_802_11); \
+ } \
+ else \
+ { \
+ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_INFRA)) \
+ { \
+ _pDA = _pRxBlk->pHeader->Addr1; \
+ if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_DLS)) \
+ _pSA = _pRxBlk->pHeader->Addr2; \
+ else \
+ _pSA = _pRxBlk->pHeader->Addr3; \
+ } \
+ else \
+ { \
+ _pDA = _pRxBlk->pHeader->Addr1; \
+ _pSA = _pRxBlk->pHeader->Addr2; \
+ } \
+ } \
+ \
+ CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData, \
+ _pRxBlk->DataSize, _pRemovedLLCSNAP); \
+}
+#endif // CONFIG_STA_SUPPORT //
+
+
+BOOLEAN APFowardWirelessStaToWirelessSta(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN ULONG FromWhichBSSID);
+
+VOID Announce_or_Forward_802_3_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR FromWhichBSSID);
+
+VOID Sta_Announce_or_Forward_802_3_Packet(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR FromWhichBSSID);
+
+
+#ifdef CONFIG_STA_SUPPORT
+#define ANNOUNCE_OR_FORWARD_802_3_PACKET(_pAd, _pPacket, _FromWhichBSS)\
+ Sta_Announce_or_Forward_802_3_Packet(_pAd, _pPacket, _FromWhichBSS);
+ //announce_802_3_packet(_pAd, _pPacket);
+#endif // CONFIG_STA_SUPPORT //
+
+
+PNDIS_PACKET DuplicatePacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN UCHAR FromWhichBSSID);
+
+
+PNDIS_PACKET ClonePacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pData,
+ IN ULONG DataSize);
+
+
+// Normal, AMPDU or AMSDU
+VOID CmmRxnonRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+VOID CmmRxRalinkFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID);
+
+VOID Update_Rssi_Sample(
+ IN PRTMP_ADAPTER pAd,
+ IN RSSI_SAMPLE *pRssi,
+ IN PRXWI_STRUC pRxWI);
+
+PNDIS_PACKET GetPacketFromRxRing(
+ IN PRTMP_ADAPTER pAd,
+ OUT PRT28XX_RXD_STRUC pSaveRxD,
+ OUT BOOLEAN *pbReschedule,
+ IN OUT UINT32 *pRxPending);
+
+PNDIS_PACKET RTMPDeFragmentDataFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk);
+
+////////////////////////////////////////
+
+
+
+
+
+#ifdef SNMP_SUPPORT
+//for snmp , kathy
+typedef struct _DefaultKeyIdxValue
+{
+ UCHAR KeyIdx;
+ UCHAR Value[16];
+} DefaultKeyIdxValue, *PDefaultKeyIdxValue;
+#endif
+
+
+#ifdef CONFIG_STA_SUPPORT
+enum {
+ DIDmsg_lnxind_wlansniffrm = 0x00000044,
+ DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044,
+ DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044,
+ DIDmsg_lnxind_wlansniffrm_channel = 0x00030044,
+ DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044,
+ DIDmsg_lnxind_wlansniffrm_sq = 0x00050044,
+ DIDmsg_lnxind_wlansniffrm_signal = 0x00060044,
+ DIDmsg_lnxind_wlansniffrm_noise = 0x00070044,
+ DIDmsg_lnxind_wlansniffrm_rate = 0x00080044,
+ DIDmsg_lnxind_wlansniffrm_istx = 0x00090044,
+ DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044
+};
+enum {
+ P80211ENUM_msgitem_status_no_value = 0x00
+};
+enum {
+ P80211ENUM_truth_false = 0x00,
+ P80211ENUM_truth_true = 0x01
+};
+
+/* Definition from madwifi */
+typedef struct {
+ UINT32 did;
+ UINT16 status;
+ UINT16 len;
+ UINT32 data;
+} p80211item_uint32_t;
+
+typedef struct {
+ UINT32 msgcode;
+ UINT32 msglen;
+#define WLAN_DEVNAMELEN_MAX 16
+ UINT8 devname[WLAN_DEVNAMELEN_MAX];
+ p80211item_uint32_t hosttime;
+ p80211item_uint32_t mactime;
+ p80211item_uint32_t channel;
+ p80211item_uint32_t rssi;
+ p80211item_uint32_t sq;
+ p80211item_uint32_t signal;
+ p80211item_uint32_t noise;
+ p80211item_uint32_t rate;
+ p80211item_uint32_t istx;
+ p80211item_uint32_t frmlen;
+} wlan_ng_prism2_header;
+
+/* The radio capture header precedes the 802.11 header. */
+typedef struct PACKED _ieee80211_radiotap_header {
+ UINT8 it_version; /* Version 0. Only increases
+ * for drastic changes,
+ * introduction of compatible
+ * new fields does not count.
+ */
+ UINT8 it_pad;
+ UINT16 it_len; /* length of the whole
+ * header in bytes, including
+ * it_version, it_pad,
+ * it_len, and data fields.
+ */
+ UINT32 it_present; /* A bitmap telling which
+ * fields are present. Set bit 31
+ * (0x80000000) to extend the
+ * bitmap by another 32 bits.
+ * Additional extensions are made
+ * by setting bit 31.
+ */
+}ieee80211_radiotap_header ;
+
+enum ieee80211_radiotap_type {
+ IEEE80211_RADIOTAP_TSFT = 0,
+ IEEE80211_RADIOTAP_FLAGS = 1,
+ IEEE80211_RADIOTAP_RATE = 2,
+ IEEE80211_RADIOTAP_CHANNEL = 3,
+ IEEE80211_RADIOTAP_FHSS = 4,
+ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+ IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+ IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+ IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+ IEEE80211_RADIOTAP_ANTENNA = 11,
+ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+ IEEE80211_RADIOTAP_DB_ANTNOISE = 13
+};
+
+#define WLAN_RADIOTAP_PRESENT ( \
+ (1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_RATE) | \
+ 0)
+
+typedef struct _wlan_radiotap_header {
+ ieee80211_radiotap_header wt_ihdr;
+ INT64 wt_tsft;
+ UINT8 wt_flags;
+ UINT8 wt_rate;
+} wlan_radiotap_header;
+/* Definition from madwifi */
+
+void send_monitor_packets(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk);
+
+#if WIRELESS_EXT >= 12
+// This function will be called when query /proc
+struct iw_statistics *rt28xx_get_wireless_stats(
+ IN struct net_device *net_dev);
+#endif
+
+VOID RTMPSetDesiredRates(
+ IN PRTMP_ADAPTER pAdapter,
+ IN LONG Rates);
+#endif // CONFIG_STA_SUPPORT //
+
+INT Set_FixedTxMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+INT Set_OpMode_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+#endif // CONFIG_APSTA_MIXED_SUPPORT //
+
+static inline char* GetPhyMode(
+ int Mode)
+{
+ switch(Mode)
+ {
+ case MODE_CCK:
+ return "CCK";
+
+ case MODE_OFDM:
+ return "OFDM";
+#ifdef DOT11_N_SUPPORT
+ case MODE_HTMIX:
+ return "HTMIX";
+
+ case MODE_HTGREENFIELD:
+ return "GREEN";
+#endif // DOT11_N_SUPPORT //
+ default:
+ return "N/A";
+ }
+}
+
+
+static inline char* GetBW(
+ int BW)
+{
+ switch(BW)
+ {
+ case BW_10:
+ return "10M";
+
+ case BW_20:
+ return "20M";
+#ifdef DOT11_N_SUPPORT
+ case BW_40:
+ return "40M";
+#endif // DOT11_N_SUPPORT //
+ default:
+ return "N/A";
+ }
+}
+
+
+VOID RT28xxThreadTerminate(
+ IN RTMP_ADAPTER *pAd);
+
+BOOLEAN RT28XXChipsetCheck(
+ IN void *_dev_p);
+
+BOOLEAN RT28XXNetDevInit(
+ IN void *_dev_p,
+ IN struct net_device *net_dev,
+ IN RTMP_ADAPTER *pAd);
+
+BOOLEAN RT28XXProbePostConfig(
+ IN void *_dev_p,
+ IN RTMP_ADAPTER *pAd,
+ IN INT32 argc);
+
+VOID RT28XXDMADisable(
+ IN RTMP_ADAPTER *pAd);
+
+VOID RT28XXDMAEnable(
+ IN RTMP_ADAPTER *pAd);
+
+VOID RT28xx_UpdateBeaconToAsic(
+ IN RTMP_ADAPTER * pAd,
+ IN INT apidx,
+ IN ULONG BeaconLen,
+ IN ULONG UpdatePos);
+
+INT rt28xx_ioctl(
+ IN struct net_device *net_dev,
+ IN OUT struct ifreq *rq,
+ IN INT cmd);
+
+
+#ifdef CONFIG_STA_SUPPORT
+INT rt28xx_sta_ioctl(
+ IN struct net_device *net_dev,
+ IN OUT struct ifreq *rq,
+ IN INT cmd);
+#endif // CONFIG_STA_SUPPORT //
+
+BOOLEAN RT28XXSecurityKeyAdd(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG apidx,
+ IN ULONG KeyIdx,
+ IN MAC_TABLE_ENTRY *pEntry);
+
+////////////////////////////////////////
+PNDIS_PACKET GetPacketFromRxRing(
+ IN PRTMP_ADAPTER pAd,
+ OUT PRT28XX_RXD_STRUC pSaveRxD,
+ OUT BOOLEAN *pbReschedule,
+ IN OUT UINT32 *pRxPending);
+
+
+void kill_thread_task(PRTMP_ADAPTER pAd);
+
+void tbtt_tasklet(unsigned long data);
+
+#ifdef RT2860
+//
+// Function Prototype in cmm_data_2860.c
+//
+USHORT RtmpPCI_WriteTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN BOOLEAN bIsLast,
+ OUT USHORT *FreeNumber);
+
+USHORT RtmpPCI_WriteSingleTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN BOOLEAN bIsLast,
+ OUT USHORT *FreeNumber);
+
+USHORT RtmpPCI_WriteMultiTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR frameNum,
+ OUT USHORT *FreeNumber);
+
+USHORT RtmpPCI_WriteFragTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR fragNum,
+ OUT USHORT *FreeNumber);
+
+USHORT RtmpPCI_WriteSubTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN BOOLEAN bIsLast,
+ OUT USHORT *FreeNumber);
+
+VOID RtmpPCI_FinalWriteTxResource(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN USHORT totalMPDUSize,
+ IN USHORT FirstTxIdx);
+
+VOID RtmpPCIDataLastTxIdx(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN USHORT LastTxIdx);
+
+VOID RtmpPCIDataKickOut(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR QueIdx);
+
+
+int RtmpPCIMgmtKickOut(
+ IN RTMP_ADAPTER *pAd,
+ IN UCHAR QueIdx,
+ IN PNDIS_PACKET pPacket,
+ IN PUCHAR pSrcBufVA,
+ IN UINT SrcBufLen);
+
+
+NDIS_STATUS RTMPCheckRxError(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHeader,
+ IN PRXWI_STRUC pRxWI,
+ IN PRT28XX_RXD_STRUC pRxD);
+
+#ifdef CONFIG_STA_SUPPORT
+VOID RTMPInitPCIeLinkCtrlValue(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPFindHostPCIDev(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPPCIeLinkCtrlValueRestore(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Level);
+
+VOID RTMPPCIeLinkCtrlSetting(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT Max);
+
+VOID RT28xxPciAsicRadioOff(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Level,
+ IN USHORT TbttNumToNextWakeUp);
+
+BOOLEAN RT28xxPciAsicRadioOn(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Level);
+
+VOID RT28xxPciStaAsicForceWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN bFromTx);
+
+VOID RT28xxPciStaAsicSleepThenAutoWakeup(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT TbttNumToNextWakeUp);
+
+VOID PsPollWakeExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+
+VOID RadioOnExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3);
+#endif // CONFIG_STA_SUPPORT //
+
+VOID RT28xxPciMlmeRadioOn(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RT28xxPciMlmeRadioOFF(
+ IN PRTMP_ADAPTER pAd);
+#endif // RT2860 //
+
+VOID AsicTurnOffRFClk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel);
+
+VOID AsicTurnOnRFClk(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Channel);
+
+
+////////////////////////////////////////
+
+VOID QBSS_LoadInit(
+ IN RTMP_ADAPTER *pAd);
+
+UINT32 QBSS_LoadElementAppend(
+ IN RTMP_ADAPTER *pAd,
+ OUT UINT8 *buf_p);
+
+VOID QBSS_LoadUpdate(
+ IN RTMP_ADAPTER *pAd);
+
+///////////////////////////////////////
+INT RTMPShowCfgValue(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pName,
+ IN PUCHAR pBuf);
+
+PCHAR RTMPGetRalinkAuthModeStr(
+ IN NDIS_802_11_AUTHENTICATION_MODE authMode);
+
+PCHAR RTMPGetRalinkEncryModeStr(
+ IN USHORT encryMode);
+//////////////////////////////////////
+
+#ifdef CONFIG_STA_SUPPORT
+VOID AsicStaBbpTuning(
+ IN PRTMP_ADAPTER pAd);
+#endif // CONFIG_STA_SUPPORT //
+
+void RTMP_IndicateMediaState(
+ IN PRTMP_ADAPTER pAd);
+
+VOID ReSyncBeaconTime(
+ IN PRTMP_ADAPTER pAd);
+
+VOID RTMPSetAGCInitValue(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BandWidth);
+
+int rt28xx_close(IN PNET_DEV dev);
+int rt28xx_open(IN PNET_DEV dev);
+
+__inline INT VIRTUAL_IF_UP(PRTMP_ADAPTER pAd)
+{
+extern VOID MeshMakeBeacon(IN PRTMP_ADAPTER pAd, IN UCHAR idx);
+extern VOID MeshUpdateBeaconFrame(IN PRTMP_ADAPTER pAd, IN UCHAR idx);
+
+ if (VIRTUAL_IF_NUM(pAd) == 0)
+ {
+ if (rt28xx_open(pAd->net_dev) != 0)
+ return -1;
+ }
+ else
+ {
+ }
+ VIRTUAL_IF_INC(pAd);
+ return 0;
+}
+
+__inline VOID VIRTUAL_IF_DOWN(PRTMP_ADAPTER pAd)
+{
+ VIRTUAL_IF_DEC(pAd);
+ if (VIRTUAL_IF_NUM(pAd) == 0)
+ rt28xx_close(pAd->net_dev);
+ return;
+}
+
+
+#endif // __RTMP_H__
+
diff --git a/drivers/staging/rt2860/rtmp_ckipmic.h b/drivers/staging/rt2860/rtmp_ckipmic.h
new file mode 100644
index 000000000000..a3d949a39d39
--- /dev/null
+++ b/drivers/staging/rt2860/rtmp_ckipmic.h
@@ -0,0 +1,113 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_ckipmic.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+*/
+#ifndef __RTMP_CKIPMIC_H__
+#define __RTMP_CKIPMIC_H__
+
+typedef struct _MIC_CONTEXT {
+ /* --- MMH context */
+ UCHAR CK[16]; /* the key */
+ UCHAR coefficient[16]; /* current aes counter mode coefficients */
+ ULONGLONG accum; /* accumulated mic, reduced to u32 in final() */
+ UINT position; /* current position (byte offset) in message */
+ UCHAR part[4]; /* for conversion of message to u32 for mmh */
+} MIC_CONTEXT, *PMIC_CONTEXT;
+
+VOID CKIP_key_permute(
+ OUT UCHAR *PK, /* output permuted key */
+ IN UCHAR *CK, /* input CKIP key */
+ IN UCHAR toDsFromDs, /* input toDs/FromDs bits */
+ IN UCHAR *piv); /* input pointer to IV */
+
+VOID RTMPCkipMicInit(
+ IN PMIC_CONTEXT pContext,
+ IN PUCHAR CK);
+
+VOID RTMPMicUpdate(
+ IN PMIC_CONTEXT pContext,
+ IN PUCHAR pOctets,
+ IN INT len);
+
+ULONG RTMPMicGetCoefficient(
+ IN PMIC_CONTEXT pContext);
+
+VOID xor_128(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out);
+
+UCHAR RTMPCkipSbox(
+ IN UCHAR a);
+
+VOID xor_32(
+ IN PUCHAR a,
+ IN PUCHAR b,
+ OUT PUCHAR out);
+
+VOID next_key(
+ IN PUCHAR key,
+ IN INT round);
+
+VOID byte_sub(
+ IN PUCHAR in,
+ OUT PUCHAR out);
+
+VOID shift_row(
+ IN PUCHAR in,
+ OUT PUCHAR out);
+
+VOID mix_column(
+ IN PUCHAR in,
+ OUT PUCHAR out);
+
+VOID RTMPAesEncrypt(
+ IN PUCHAR key,
+ IN PUCHAR data,
+ IN PUCHAR ciphertext);
+
+VOID RTMPMicFinal(
+ IN PMIC_CONTEXT pContext,
+ OUT UCHAR digest[4]);
+
+VOID RTMPCkipInsertCMIC(
+ IN PRTMP_ADAPTER pAd,
+ OUT PUCHAR pMIC,
+ IN PUCHAR p80211hdr,
+ IN PNDIS_PACKET pPacket,
+ IN PCIPHER_KEY pKey,
+ IN PUCHAR mic_snap);
+
+#endif //__RTMP_CKIPMIC_H__
diff --git a/drivers/staging/rt2860/rtmp_def.h b/drivers/staging/rt2860/rtmp_def.h
new file mode 100644
index 000000000000..be982147883f
--- /dev/null
+++ b/drivers/staging/rt2860/rtmp_def.h
@@ -0,0 +1,1588 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_def.h
+
+ Abstract:
+ Miniport related definition header
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 08-01-2002 created
+ John Chang 08-05-2003 add definition for 11g & other drafts
+*/
+#ifndef __RTMP_DEF_H__
+#define __RTMP_DEF_H__
+
+#include "oid.h"
+
+//
+// Debug information verbosity: lower values indicate higher urgency
+//
+#define RT_DEBUG_OFF 0
+#define RT_DEBUG_ERROR 1
+#define RT_DEBUG_WARN 2
+#define RT_DEBUG_TRACE 3
+#define RT_DEBUG_INFO 4
+#define RT_DEBUG_LOUD 5
+
+#define NIC_TAG ((ULONG)'0682')
+#define NIC_DBG_STRING ("**RT28xx**")
+
+#ifdef SNMP_SUPPORT
+// for snmp
+// to get manufacturer OUI, kathy, 2008_0220
+#define ManufacturerOUI_LEN 3
+#define ManufacturerNAME ("Ralink Technology Company.")
+#define ResourceTypeIdName ("Ralink_ID")
+#endif
+
+
+#define RALINK_2883_VERSION ((UINT32)0x28830300)
+#define RALINK_2880E_VERSION ((UINT32)0x28720200)
+#define RALINK_3070_VERSION ((UINT32)0x30700200)
+
+//
+// NDIS version in use by the NIC driver.
+// The high byte is the major version. The low byte is the minor version.
+//
+#ifdef NDIS51_MINIPORT
+#define NIC_DRIVER_VERSION 0x0501
+#else
+#define NIC_DRIVER_VERSION 0x0500
+#endif
+
+//
+// NDIS media type, current is ethernet, change if native wireless supported
+//
+#define NIC_MEDIA_TYPE NdisMedium802_3
+#define NIC_PCI_HDR_LENGTH 0xe2
+#define NIC_MAX_PACKET_SIZE 2304
+#define NIC_HEADER_SIZE 14
+#define MAX_MAP_REGISTERS_NEEDED 32
+#define MIN_MAP_REGISTERS_NEEDED 2 //Todo: should consider fragment issue.
+
+//
+// interface type, we use PCI
+//
+#define NIC_INTERFACE_TYPE NdisInterfacePci
+#define NIC_INTERRUPT_MODE NdisInterruptLevelSensitive
+
+//
+// buffer size passed in NdisMQueryAdapterResources
+// We should only need three adapter resources (IO, interrupt and memory),
+// Some devices get extra resources, so have room for 10 resources
+// UF_SIZE (sizeof(NDIS_RESOURCE_LIST) + (10*sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)))
+
+
+#define NIC_RESOURCE_B//
+// IO space length
+//
+#define NIC_MAP_IOSPACE_LENGTH sizeof(CSR_STRUC)
+
+#define MAX_RX_PKT_LEN 1520
+
+//
+// Entry number for each DMA descriptor ring
+//
+
+#ifdef RT2860
+#define TX_RING_SIZE 64 //64
+#define MGMT_RING_SIZE 128
+#define RX_RING_SIZE 128 //64
+#define MAX_TX_PROCESS TX_RING_SIZE //8
+#define MAX_DMA_DONE_PROCESS TX_RING_SIZE
+#define MAX_TX_DONE_PROCESS TX_RING_SIZE //8
+#define LOCAL_TXBUF_SIZE 2
+#endif // RT2860 //
+
+
+#ifdef MULTIPLE_CARD_SUPPORT
+// MC: Multple Cards
+#define MAX_NUM_OF_MULTIPLE_CARD 32
+#endif // MULTIPLE_CARD_SUPPORT //
+
+#define MAX_RX_PROCESS 128 //64 //32
+#define NUM_OF_LOCAL_TXBUF 2
+#define TXD_SIZE 16
+#define TXWI_SIZE 16
+#define RXD_SIZE 16
+#define RXWI_SIZE 16
+// TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header
+#define TX_DMA_1ST_BUFFER_SIZE 96 // only the 1st physical buffer is pre-allocated
+#define MGMT_DMA_BUFFER_SIZE 1536 //2048
+#define RX_BUFFER_AGGRESIZE 3840 //3904 //3968 //4096 //2048 //4096
+#define RX_BUFFER_NORMSIZE 3840 //3904 //3968 //4096 //2048 //4096
+#define TX_BUFFER_NORMSIZE RX_BUFFER_NORMSIZE
+#define MAX_FRAME_SIZE 2346 // Maximum 802.11 frame size
+#define MAX_AGGREGATION_SIZE 3840 //3904 //3968 //4096
+#define MAX_NUM_OF_TUPLE_CACHE 2
+#define MAX_MCAST_LIST_SIZE 32
+#define MAX_LEN_OF_VENDOR_DESC 64
+//#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ
+#define MAX_SIZE_OF_MCAST_PSQ 32
+
+#define MAX_RX_PROCESS_CNT (RX_RING_SIZE)
+
+
+#define MAX_PACKETS_IN_QUEUE (512) //(512) // to pass WMM A5-WPAPSK
+#define MAX_PACKETS_IN_MCAST_PS_QUEUE 32
+#define MAX_PACKETS_IN_PS_QUEUE 128 //32
+#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */
+
+
+
+// RxFilter
+#define STANORMAL 0x17f97
+#define APNORMAL 0x15f97
+//
+// RTMP_ADAPTER flags
+//
+#define fRTMP_ADAPTER_MAP_REGISTER 0x00000001
+#define fRTMP_ADAPTER_INTERRUPT_IN_USE 0x00000002
+#define fRTMP_ADAPTER_HARDWARE_ERROR 0x00000004
+#define fRTMP_ADAPTER_SCATTER_GATHER 0x00000008
+#define fRTMP_ADAPTER_SEND_PACKET_ERROR 0x00000010
+#define fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS 0x00000020
+#define fRTMP_ADAPTER_HALT_IN_PROGRESS 0x00000040
+#define fRTMP_ADAPTER_RESET_IN_PROGRESS 0x00000080
+#define fRTMP_ADAPTER_NIC_NOT_EXIST 0x00000100
+#define fRTMP_ADAPTER_TX_RING_ALLOCATED 0x00000200
+#define fRTMP_ADAPTER_REMOVE_IN_PROGRESS 0x00000400
+#define fRTMP_ADAPTER_MIMORATE_INUSED 0x00000800
+#define fRTMP_ADAPTER_RX_RING_ALLOCATED 0x00001000
+#define fRTMP_ADAPTER_INTERRUPT_ACTIVE 0x00002000
+#define fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS 0x00004000
+#define fRTMP_ADAPTER_REASSOC_IN_PROGRESS 0x00008000
+#define fRTMP_ADAPTER_MEDIA_STATE_PENDING 0x00010000
+#define fRTMP_ADAPTER_RADIO_OFF 0x00020000
+#define fRTMP_ADAPTER_BULKOUT_RESET 0x00040000
+#define fRTMP_ADAPTER_BULKIN_RESET 0x00080000
+#define fRTMP_ADAPTER_RDG_ACTIVE 0x00100000
+#define fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE 0x00200000
+#define fRTMP_ADAPTER_SCAN_2040 0x04000000
+#define fRTMP_ADAPTER_RADIO_MEASUREMENT 0x08000000
+
+#define fRTMP_ADAPTER_START_UP 0x10000000 //Devive already initialized and enabled Tx/Rx.
+#define fRTMP_ADAPTER_MEDIA_STATE_CHANGE 0x20000000
+#define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000
+
+//
+// STA operation status flags
+//
+#define fOP_STATUS_INFRA_ON 0x00000001
+#define fOP_STATUS_ADHOC_ON 0x00000002
+#define fOP_STATUS_BG_PROTECTION_INUSED 0x00000004
+#define fOP_STATUS_SHORT_SLOT_INUSED 0x00000008
+#define fOP_STATUS_SHORT_PREAMBLE_INUSED 0x00000010
+#define fOP_STATUS_RECEIVE_DTIM 0x00000020
+#define fOP_STATUS_MEDIA_STATE_CONNECTED 0x00000080
+#define fOP_STATUS_WMM_INUSED 0x00000100
+#define fOP_STATUS_AGGREGATION_INUSED 0x00000200
+#define fOP_STATUS_DOZE 0x00000400 // debug purpose
+#define fOP_STATUS_PIGGYBACK_INUSED 0x00000800 // piggy-back, and aggregation
+#define fOP_STATUS_APSD_INUSED 0x00001000
+#define fOP_STATUS_TX_AMSDU_INUSED 0x00002000
+#define fOP_STATUS_MAX_RETRY_ENABLED 0x00004000
+#define fOP_STATUS_WAKEUP_NOW 0x00008000
+#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE 0x00020000
+
+#ifdef DOT11N_DRAFT3
+#define fOP_STATUS_SCAN_2040 0x00040000
+#endif // DOT11N_DRAFT3 //
+
+#define CCKSETPROTECT 0x1
+#define OFDMSETPROTECT 0x2
+#define MM20SETPROTECT 0x4
+#define MM40SETPROTECT 0x8
+#define GF20SETPROTECT 0x10
+#define GR40SETPROTECT 0x20
+#define ALLN_SETPROTECT (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT)
+
+//
+// AP's client table operation status flags
+//
+#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 // CLIENT can parse QOS DATA frame
+#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 // CLIENT can receive Ralink's proprietary TX aggregation frame
+#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 // CLIENT support piggy-back
+#define fCLIENT_STATUS_AMSDU_INUSED 0x00000008
+#define fCLIENT_STATUS_SGI20_CAPABLE 0x00000010
+#define fCLIENT_STATUS_SGI40_CAPABLE 0x00000020
+#define fCLIENT_STATUS_TxSTBC_CAPABLE 0x00000040
+#define fCLIENT_STATUS_RxSTBC_CAPABLE 0x00000080
+#define fCLIENT_STATUS_HTC_CAPABLE 0x00000100
+#define fCLIENT_STATUS_RDG_CAPABLE 0x00000200
+#define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE 0x00000400
+#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */
+
+#ifdef DOT11N_DRAFT3
+#define fCLIENT_STATUS_BSSCOEXIST_CAPABLE 0x00001000
+#endif // DOT11N_DRAFT3 //
+
+#define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000
+//
+// STA configuration flags
+//
+
+// 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case
+#define HT_NO_PROTECT 0
+#define HT_LEGACY_PROTECT 1
+#define HT_40_PROTECT 2
+#define HT_2040_PROTECT 3
+#define HT_RTSCTS_6M 7
+//following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE.
+#define HT_ATHEROS 8 // rt2860c has problem with atheros chip. we need to turn on RTS/CTS .
+#define HT_FORCERTSCTS 9 // Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary.
+
+//
+// RX Packet Filter control flags. Apply on pAd->PacketFilter
+//
+#define fRX_FILTER_ACCEPT_DIRECT NDIS_PACKET_TYPE_DIRECTED
+#define fRX_FILTER_ACCEPT_MULTICAST NDIS_PACKET_TYPE_MULTICAST
+#define fRX_FILTER_ACCEPT_BROADCAST NDIS_PACKET_TYPE_BROADCAST
+#define fRX_FILTER_ACCEPT_ALL_MULTICAST NDIS_PACKET_TYPE_ALL_MULTICAST
+
+//
+// Error code section
+//
+// NDIS_ERROR_CODE_ADAPTER_NOT_FOUND
+#define ERRLOG_READ_PCI_SLOT_FAILED 0x00000101L
+#define ERRLOG_WRITE_PCI_SLOT_FAILED 0x00000102L
+#define ERRLOG_VENDOR_DEVICE_NOMATCH 0x00000103L
+
+// NDIS_ERROR_CODE_ADAPTER_DISABLED
+#define ERRLOG_BUS_MASTER_DISABLED 0x00000201L
+
+// NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION
+#define ERRLOG_INVALID_SPEED_DUPLEX 0x00000301L
+#define ERRLOG_SET_SECONDARY_FAILED 0x00000302L
+
+// NDIS_ERROR_CODE_OUT_OF_RESOURCES
+#define ERRLOG_OUT_OF_MEMORY 0x00000401L
+#define ERRLOG_OUT_OF_SHARED_MEMORY 0x00000402L
+#define ERRLOG_OUT_OF_MAP_REGISTERS 0x00000403L
+#define ERRLOG_OUT_OF_BUFFER_POOL 0x00000404L
+#define ERRLOG_OUT_OF_NDIS_BUFFER 0x00000405L
+#define ERRLOG_OUT_OF_PACKET_POOL 0x00000406L
+#define ERRLOG_OUT_OF_NDIS_PACKET 0x00000407L
+#define ERRLOG_OUT_OF_LOOKASIDE_MEMORY 0x00000408L
+
+// NDIS_ERROR_CODE_HARDWARE_FAILURE
+#define ERRLOG_SELFTEST_FAILED 0x00000501L
+#define ERRLOG_INITIALIZE_ADAPTER 0x00000502L
+#define ERRLOG_REMOVE_MINIPORT 0x00000503L
+
+// NDIS_ERROR_CODE_RESOURCE_CONFLICT
+#define ERRLOG_MAP_IO_SPACE 0x00000601L
+#define ERRLOG_QUERY_ADAPTER_RESOURCES 0x00000602L
+#define ERRLOG_NO_IO_RESOURCE 0x00000603L
+#define ERRLOG_NO_INTERRUPT_RESOURCE 0x00000604L
+#define ERRLOG_NO_MEMORY_RESOURCE 0x00000605L
+
+
+// WDS definition
+#define MAX_WDS_ENTRY 4
+#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table
+
+#define WDS_DISABLE_MODE 0
+#define WDS_RESTRICT_MODE 1
+#define WDS_BRIDGE_MODE 2
+#define WDS_REPEATER_MODE 3
+#define WDS_LAZY_MODE 4
+
+
+#define MAX_MESH_NUM 0
+
+#define MAX_APCLI_NUM 0
+#ifdef APCLI_SUPPORT
+#undef MAX_APCLI_NUM
+#define MAX_APCLI_NUM 1
+#endif // APCLI_SUPPORT //
+
+#define MAX_MBSSID_NUM 1
+#ifdef MBSS_SUPPORT
+#undef MAX_MBSSID_NUM
+#define MAX_MBSSID_NUM (8 - MAX_MESH_NUM - MAX_APCLI_NUM)
+#endif // MBSS_SUPPORT //
+
+/* sanity check for apidx */
+#define MBSS_MR_APIDX_SANITY_CHECK(apidx) \
+ { if (apidx > MAX_MBSSID_NUM) { \
+ printk("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __func__, apidx); \
+ apidx = MAIN_MBSSID; } }
+
+#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE )
+
+#define MAIN_MBSSID 0
+#define FIRST_MBSSID 1
+
+
+#define MAX_BEACON_SIZE 512
+// If the MAX_MBSSID_NUM is larger than 6,
+// it shall reserve some WCID space(wcid 222~253) for beacon frames.
+// - these wcid 238~253 are reserved for beacon#6(ra6).
+// - these wcid 222~237 are reserved for beacon#7(ra7).
+#if defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 8)
+#define HW_RESERVED_WCID 222
+#elif defined(MAX_MBSSID_NUM) && (MAX_MBSSID_NUM == 7)
+#define HW_RESERVED_WCID 238
+#else
+#define HW_RESERVED_WCID 255
+#endif
+
+// Then dedicate wcid of DFS and Carrier-Sense.
+#define DFS_CTS_WCID (HW_RESERVED_WCID - 1)
+#define CS_CTS_WCID (HW_RESERVED_WCID - 2)
+#define LAST_SPECIFIC_WCID (HW_RESERVED_WCID - 2)
+
+// If MAX_MBSSID_NUM is 8, the maximum available wcid for the associated STA is 211.
+// If MAX_MBSSID_NUM is 7, the maximum available wcid for the associated STA is 228.
+#define MAX_AVAILABLE_CLIENT_WCID (LAST_SPECIFIC_WCID - MAX_MBSSID_NUM - 1)
+
+// TX need WCID to find Cipher Key
+// these wcid 212 ~ 219 are reserved for bc/mc packets if MAX_MBSSID_NUM is 8.
+#define GET_GroupKey_WCID(__wcid, __bssidx) \
+ { \
+ __wcid = LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM) + __bssidx; \
+ }
+
+#define IsGroupKeyWCID(__wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM))))
+
+
+// definition to support multiple BSSID
+#define BSS0 0
+#define BSS1 1
+#define BSS2 2
+#define BSS3 3
+#define BSS4 4
+#define BSS5 5
+#define BSS6 6
+#define BSS7 7
+
+
+//============================================================
+// Length definitions
+#define PEER_KEY_NO 2
+#define MAC_ADDR_LEN 6
+#define TIMESTAMP_LEN 8
+#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES // 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
+#define MAX_LEN_OF_KEY 32 // 32 octets == 256 bits, Redefine for WPA
+#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination
+#define MAX_NUM_OF_11JCHANNELS 20 // 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination
+#define MAX_LEN_OF_SSID 32
+#define CIPHER_TEXT_LEN 128
+#define HASH_TABLE_SIZE 256
+#define MAX_VIE_LEN 1024 // New for WPA cipher suite variable IE sizes.
+#define MAX_SUPPORT_MCS 32
+
+//============================================================
+// ASIC WCID Table definition.
+//============================================================
+#define BSSID_WCID 1 // in infra mode, always put bssid with this WCID
+#define MCAST_WCID 0x0
+#define BSS0Mcast_WCID 0x0
+#define BSS1Mcast_WCID 0xf8
+#define BSS2Mcast_WCID 0xf9
+#define BSS3Mcast_WCID 0xfa
+#define BSS4Mcast_WCID 0xfb
+#define BSS5Mcast_WCID 0xfc
+#define BSS6Mcast_WCID 0xfd
+#define BSS7Mcast_WCID 0xfe
+#define RESERVED_WCID 0xff
+
+#define MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL
+
+#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC // if MAX_MBSSID_NUM is 8, this value can't be larger than 211
+
+#if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID
+#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!!
+#endif
+
+#define MAX_NUM_OF_WDS_LINK_PERBSSID 3
+#define MAX_NUM_OF_WDS_LINK (MAX_NUM_OF_WDS_LINK_PERBSSID*MAX_MBSSID_NUM)
+#define MAX_NUM_OF_EVENT MAX_NUMBER_OF_EVENT
+#define WDS_LINK_START_WCID (MAX_LEN_OF_MAC_TABLE-1)
+
+#define NUM_OF_TID 8
+#define MAX_AID_BA 4
+#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient
+#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2)// (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator
+#define MAX_LEN_OF_BSS_TABLE 64
+#define MAX_REORDERING_MPDU_NUM 512
+
+// key related definitions
+#define SHARE_KEY_NUM 4
+#define MAX_LEN_OF_SHARE_KEY 16 // byte count
+#define MAX_LEN_OF_PEER_KEY 16 // byte count
+#define PAIRWISE_KEY_NUM 64 // in MAC ASIC pairwise key table
+#define GROUP_KEY_NUM 4
+#define PMK_LEN 32
+#define WDS_PAIRWISE_KEY_OFFSET 60 // WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table
+#define PMKID_NO 4 // Number of PMKID saved supported
+#define MAX_LEN_OF_MLME_BUFFER 2048
+
+// power status related definitions
+#define PWR_ACTIVE 0
+#define PWR_SAVE 1
+#define PWR_MMPS 2 //MIMO power save
+
+// Auth and Assoc mode related definitions
+#define AUTH_MODE_OPEN 0x00
+#define AUTH_MODE_KEY 0x01
+
+// BSS Type definitions
+#define BSS_ADHOC 0 // = Ndis802_11IBSS
+#define BSS_INFRA 1 // = Ndis802_11Infrastructure
+#define BSS_ANY 2 // = Ndis802_11AutoUnknown
+#define BSS_MONITOR 3 // = Ndis802_11Monitor
+
+
+// Reason code definitions
+#define REASON_RESERVED 0
+#define REASON_UNSPECIFY 1
+#define REASON_NO_LONGER_VALID 2
+#define REASON_DEAUTH_STA_LEAVING 3
+#define REASON_DISASSOC_INACTIVE 4
+#define REASON_DISASSPC_AP_UNABLE 5
+#define REASON_CLS2ERR 6
+#define REASON_CLS3ERR 7
+#define REASON_DISASSOC_STA_LEAVING 8
+#define REASON_STA_REQ_ASSOC_NOT_AUTH 9
+#define REASON_INVALID_IE 13
+#define REASON_MIC_FAILURE 14
+#define REASON_4_WAY_TIMEOUT 15
+#define REASON_GROUP_KEY_HS_TIMEOUT 16
+#define REASON_IE_DIFFERENT 17
+#define REASON_MCIPHER_NOT_VALID 18
+#define REASON_UCIPHER_NOT_VALID 19
+#define REASON_AKMP_NOT_VALID 20
+#define REASON_UNSUPPORT_RSNE_VER 21
+#define REASON_INVALID_RSNE_CAP 22
+#define REASON_8021X_AUTH_FAIL 23
+#define REASON_CIPHER_SUITE_REJECTED 24
+#define REASON_DECLINED 37
+
+#define REASON_QOS_UNSPECIFY 32
+#define REASON_QOS_LACK_BANDWIDTH 33
+#define REASON_POOR_CHANNEL_CONDITION 34
+#define REASON_QOS_OUTSIDE_TXOP_LIMITION 35
+#define REASON_QOS_QSTA_LEAVING_QBSS 36
+#define REASON_QOS_UNWANTED_MECHANISM 37
+#define REASON_QOS_MECH_SETUP_REQUIRED 38
+#define REASON_QOS_REQUEST_TIMEOUT 39
+#define REASON_QOS_CIPHER_NOT_SUPPORT 45
+
+// Status code definitions
+#define MLME_SUCCESS 0
+#define MLME_UNSPECIFY_FAIL 1
+#define MLME_CANNOT_SUPPORT_CAP 10
+#define MLME_REASSOC_DENY_ASSOC_EXIST 11
+#define MLME_ASSOC_DENY_OUT_SCOPE 12
+#define MLME_ALG_NOT_SUPPORT 13
+#define MLME_SEQ_NR_OUT_OF_SEQUENCE 14
+#define MLME_REJ_CHALLENGE_FAILURE 15
+#define MLME_REJ_TIMEOUT 16
+#define MLME_ASSOC_REJ_UNABLE_HANDLE_STA 17
+#define MLME_ASSOC_REJ_DATA_RATE 18
+
+#define MLME_ASSOC_REJ_NO_EXT_RATE 22
+#define MLME_ASSOC_REJ_NO_EXT_RATE_PBCC 23
+#define MLME_ASSOC_REJ_NO_CCK_OFDM 24
+
+#define MLME_QOS_UNSPECIFY 32
+#define MLME_REQUEST_DECLINED 37
+#define MLME_REQUEST_WITH_INVALID_PARAM 38
+#define MLME_DLS_NOT_ALLOW_IN_QBSS 48
+#define MLME_DEST_STA_NOT_IN_QBSS 49
+#define MLME_DEST_STA_IS_NOT_A_QSTA 50
+
+#define MLME_INVALID_FORMAT 0x51
+#define MLME_FAIL_NO_RESOURCE 0x52
+#define MLME_STATE_MACHINE_REJECT 0x53
+#define MLME_MAC_TABLE_FAIL 0x54
+
+// IE code
+#define IE_SSID 0
+#define IE_SUPP_RATES 1
+#define IE_FH_PARM 2
+#define IE_DS_PARM 3
+#define IE_CF_PARM 4
+#define IE_TIM 5
+#define IE_IBSS_PARM 6
+#define IE_COUNTRY 7 // 802.11d
+#define IE_802_11D_REQUEST 10 // 802.11d
+#define IE_QBSS_LOAD 11 // 802.11e d9
+#define IE_EDCA_PARAMETER 12 // 802.11e d9
+#define IE_TSPEC 13 // 802.11e d9
+#define IE_TCLAS 14 // 802.11e d9
+#define IE_SCHEDULE 15 // 802.11e d9
+#define IE_CHALLENGE_TEXT 16
+#define IE_POWER_CONSTRAINT 32 // 802.11h d3.3
+#define IE_POWER_CAPABILITY 33 // 802.11h d3.3
+#define IE_TPC_REQUEST 34 // 802.11h d3.3
+#define IE_TPC_REPORT 35 // 802.11h d3.3
+#define IE_SUPP_CHANNELS 36 // 802.11h d3.3
+#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 // 802.11h d3.3
+#define IE_MEASUREMENT_REQUEST 38 // 802.11h d3.3
+#define IE_MEASUREMENT_REPORT 39 // 802.11h d3.3
+#define IE_QUIET 40 // 802.11h d3.3
+#define IE_IBSS_DFS 41 // 802.11h d3.3
+#define IE_ERP 42 // 802.11g
+#define IE_TS_DELAY 43 // 802.11e d9
+#define IE_TCLAS_PROCESSING 44 // 802.11e d9
+#define IE_QOS_CAPABILITY 46 // 802.11e d6
+#define IE_HT_CAP 45 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD
+#define IE_AP_CHANNEL_REPORT 51 // 802.11k d6
+#define IE_HT_CAP2 52 // 802.11n d1. HT CAPABILITY. ELEMENT ID TBD
+#define IE_RSN 48 // 802.11i d3.0
+#define IE_WPA2 48 // WPA2
+#define IE_EXT_SUPP_RATES 50 // 802.11g
+#define IE_SUPP_REG_CLASS 59 // 802.11y. Supported regulatory classes.
+#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 // 802.11n
+#define IE_ADD_HT 61 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD
+#define IE_ADD_HT2 53 // 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD
+
+
+// For 802.11n D3.03
+//#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet
+#define IE_SECONDARY_CH_OFFSET 62 // 802.11n D3.03 Secondary Channel Offset element
+#define IE_2040_BSS_COEXIST 72 // 802.11n D3.0.3
+#define IE_2040_BSS_INTOLERANT_REPORT 73 // 802.11n D3.03
+#define IE_OVERLAPBSS_SCAN_PARM 74 // 802.11n D3.03
+#define IE_EXT_CAPABILITY 127 // 802.11n D3.03
+
+
+#define IE_WPA 221 // WPA
+#define IE_VENDOR_SPECIFIC 221 // Wifi WMM (WME)
+
+#define OUI_BROADCOM_HT 51 //
+#define OUI_BROADCOM_HTADD 52 //
+#define OUI_PREN_HT_CAP 51 //
+#define OUI_PREN_ADD_HT 52 //
+
+// CCX information
+#define IE_AIRONET_CKIP 133 // CCX1.0 ID 85H for CKIP
+#define IE_AP_TX_POWER 150 // CCX 2.0 for AP transmit power
+#define IE_MEASUREMENT_CAPABILITY 221 // CCX 2.0
+#define IE_CCX_V2 221
+#define IE_AIRONET_IPADDRESS 149 // CCX ID 95H for IP Address
+#define IE_AIRONET_CCKMREASSOC 156 // CCX ID 9CH for CCKM Reassociation Request element
+#define CKIP_NEGOTIATION_LENGTH 30
+#define AIRONET_IPADDRESS_LENGTH 10
+#define AIRONET_CCKMREASSOC_LENGTH 24
+
+// ========================================================
+// MLME state machine definition
+// ========================================================
+
+// STA MLME state mahcines
+#define ASSOC_STATE_MACHINE 1
+#define AUTH_STATE_MACHINE 2
+#define AUTH_RSP_STATE_MACHINE 3
+#define SYNC_STATE_MACHINE 4
+#define MLME_CNTL_STATE_MACHINE 5
+#define WPA_PSK_STATE_MACHINE 6
+#define LEAP_STATE_MACHINE 7
+#define AIRONET_STATE_MACHINE 8
+#define ACTION_STATE_MACHINE 9
+
+// AP MLME state machines
+#define AP_ASSOC_STATE_MACHINE 11
+#define AP_AUTH_STATE_MACHINE 12
+#define AP_AUTH_RSP_STATE_MACHINE 13
+#define AP_SYNC_STATE_MACHINE 14
+#define AP_CNTL_STATE_MACHINE 15
+#define AP_WPA_STATE_MACHINE 16
+
+#ifdef QOS_DLS_SUPPORT
+#define DLS_STATE_MACHINE 26
+#endif // QOS_DLS_SUPPORT //
+
+//
+// STA's CONTROL/CONNECT state machine: states, events, total function #
+//
+#define CNTL_IDLE 0
+#define CNTL_WAIT_DISASSOC 1
+#define CNTL_WAIT_JOIN 2
+#define CNTL_WAIT_REASSOC 3
+#define CNTL_WAIT_START 4
+#define CNTL_WAIT_AUTH 5
+#define CNTL_WAIT_ASSOC 6
+#define CNTL_WAIT_AUTH2 7
+#define CNTL_WAIT_OID_LIST_SCAN 8
+#define CNTL_WAIT_OID_DISASSOC 9
+
+#define MT2_ASSOC_CONF 34
+#define MT2_AUTH_CONF 35
+#define MT2_DEAUTH_CONF 36
+#define MT2_DISASSOC_CONF 37
+#define MT2_REASSOC_CONF 38
+#define MT2_PWR_MGMT_CONF 39
+#define MT2_JOIN_CONF 40
+#define MT2_SCAN_CONF 41
+#define MT2_START_CONF 42
+#define MT2_GET_CONF 43
+#define MT2_SET_CONF 44
+#define MT2_RESET_CONF 45
+#define MT2_MLME_ROAMING_REQ 52
+
+#define CNTL_FUNC_SIZE 1
+
+//
+// STA's ASSOC state machine: states, events, total function #
+//
+#define ASSOC_IDLE 0
+#define ASSOC_WAIT_RSP 1
+#define REASSOC_WAIT_RSP 2
+#define DISASSOC_WAIT_RSP 3
+#define MAX_ASSOC_STATE 4
+
+#define ASSOC_MACHINE_BASE 0
+#define MT2_MLME_ASSOC_REQ 0
+#define MT2_MLME_REASSOC_REQ 1
+#define MT2_MLME_DISASSOC_REQ 2
+#define MT2_PEER_DISASSOC_REQ 3
+#define MT2_PEER_ASSOC_REQ 4
+#define MT2_PEER_ASSOC_RSP 5
+#define MT2_PEER_REASSOC_REQ 6
+#define MT2_PEER_REASSOC_RSP 7
+#define MT2_DISASSOC_TIMEOUT 8
+#define MT2_ASSOC_TIMEOUT 9
+#define MT2_REASSOC_TIMEOUT 10
+#define MAX_ASSOC_MSG 11
+
+#define ASSOC_FUNC_SIZE (MAX_ASSOC_STATE * MAX_ASSOC_MSG)
+
+//
+// ACT state machine: states, events, total function #
+//
+#define ACT_IDLE 0
+#define MAX_ACT_STATE 1
+
+#define ACT_MACHINE_BASE 0
+
+//Those PEER_xx_CATE number is based on real Categary value in IEEE spec. Please don'es modify it by your self.
+//Category
+#define MT2_PEER_SPECTRUM_CATE 0
+#define MT2_PEER_QOS_CATE 1
+#define MT2_PEER_DLS_CATE 2
+#define MT2_PEER_BA_CATE 3
+#define MT2_PEER_PUBLIC_CATE 4
+#define MT2_PEER_RM_CATE 5
+#define MT2_PEER_HT_CATE 7 // 7.4.7
+#define MAX_PEER_CATE_MSG 7
+#define MT2_MLME_ADD_BA_CATE 8
+#define MT2_MLME_ORI_DELBA_CATE 9
+#define MT2_MLME_REC_DELBA_CATE 10
+#define MT2_MLME_QOS_CATE 11
+#define MT2_MLME_DLS_CATE 12
+#define MT2_ACT_INVALID 13
+#define MAX_ACT_MSG 14
+
+//Category field
+#define CATEGORY_SPECTRUM 0
+#define CATEGORY_QOS 1
+#define CATEGORY_DLS 2
+#define CATEGORY_BA 3
+#define CATEGORY_PUBLIC 4
+#define CATEGORY_RM 5
+#define CATEGORY_HT 7
+
+
+// DLS Action frame definition
+#define ACTION_DLS_REQUEST 0
+#define ACTION_DLS_RESPONSE 1
+#define ACTION_DLS_TEARDOWN 2
+
+//Spectrum Action field value 802.11h 7.4.1
+#define SPEC_MRQ 0 // Request
+#define SPEC_MRP 1 //Report
+#define SPEC_TPCRQ 2
+#define SPEC_TPCRP 3
+#define SPEC_CHANNEL_SWITCH 4
+
+
+//BA Action field value
+#define ADDBA_REQ 0
+#define ADDBA_RESP 1
+#define DELBA 2
+
+//Public's Action field value in Public Category. Some in 802.11y and some in 11n
+#define ACTION_BSS_2040_COEXIST 0 // 11n
+#define ACTION_DSE_ENABLEMENT 1 // 11y D9.0
+#define ACTION_DSE_DEENABLEMENT 2 // 11y D9.0
+#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 // 11y D9.0
+#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 // 11y D9.0
+#define ACTION_DSE_MEASUREMENT_REQ 5 // 11y D9.0
+#define ACTION_DSE_MEASUREMENT_REPORT 6 // 11y D9.0
+#define ACTION_MEASUREMENT_PILOT_ACTION 7 // 11y D9.0
+#define ACTION_DSE_POWER_CONSTRAINT 8 // 11y D9.0
+
+
+//HT Action field value
+#define NOTIFY_BW_ACTION 0
+#define SMPS_ACTION 1
+#define PSMP_ACTION 2
+#define SETPCO_ACTION 3
+#define MIMO_CHA_MEASURE_ACTION 4
+#define MIMO_N_BEACONFORM 5
+#define MIMO_BEACONFORM 6
+#define ANTENNA_SELECT 7
+#define HT_INFO_EXCHANGE 8
+
+#define ACT_FUNC_SIZE (MAX_ACT_STATE * MAX_ACT_MSG)
+//
+// STA's AUTHENTICATION state machine: states, evvents, total function #
+//
+#define AUTH_REQ_IDLE 0
+#define AUTH_WAIT_SEQ2 1
+#define AUTH_WAIT_SEQ4 2
+#define MAX_AUTH_STATE 3
+
+#define AUTH_MACHINE_BASE 0
+#define MT2_MLME_AUTH_REQ 0
+#define MT2_PEER_AUTH_EVEN 1
+#define MT2_AUTH_TIMEOUT 2
+#define MAX_AUTH_MSG 3
+
+#define AUTH_FUNC_SIZE (MAX_AUTH_STATE * MAX_AUTH_MSG)
+
+//
+// STA's AUTH_RSP state machine: states, events, total function #
+//
+#define AUTH_RSP_IDLE 0
+#define AUTH_RSP_WAIT_CHAL 1
+#define MAX_AUTH_RSP_STATE 2
+
+#define AUTH_RSP_MACHINE_BASE 0
+#define MT2_AUTH_CHALLENGE_TIMEOUT 0
+#define MT2_PEER_AUTH_ODD 1
+#define MT2_PEER_DEAUTH 2
+#define MAX_AUTH_RSP_MSG 3
+
+#define AUTH_RSP_FUNC_SIZE (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG)
+
+//
+// STA's SYNC state machine: states, events, total function #
+//
+#define SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state
+#define JOIN_WAIT_BEACON 1
+#define SCAN_LISTEN 2
+#define MAX_SYNC_STATE 3
+
+#define SYNC_MACHINE_BASE 0
+#define MT2_MLME_SCAN_REQ 0
+#define MT2_MLME_JOIN_REQ 1
+#define MT2_MLME_START_REQ 2
+#define MT2_PEER_BEACON 3
+#define MT2_PEER_PROBE_RSP 4
+#define MT2_PEER_ATIM 5
+#define MT2_SCAN_TIMEOUT 6
+#define MT2_BEACON_TIMEOUT 7
+#define MT2_ATIM_TIMEOUT 8
+#define MT2_PEER_PROBE_REQ 9
+#define MAX_SYNC_MSG 10
+
+#define SYNC_FUNC_SIZE (MAX_SYNC_STATE * MAX_SYNC_MSG)
+
+//Messages for the DLS state machine
+#define DLS_IDLE 0
+#define MAX_DLS_STATE 1
+
+#define DLS_MACHINE_BASE 0
+#define MT2_MLME_DLS_REQ 0
+#define MT2_PEER_DLS_REQ 1
+#define MT2_PEER_DLS_RSP 2
+#define MT2_MLME_DLS_TEAR_DOWN 3
+#define MT2_PEER_DLS_TEAR_DOWN 4
+#define MAX_DLS_MSG 5
+
+#define DLS_FUNC_SIZE (MAX_DLS_STATE * MAX_DLS_MSG)
+
+//
+// STA's WPA-PSK State machine: states, events, total function #
+//
+#define WPA_PSK_IDLE 0
+#define MAX_WPA_PSK_STATE 1
+
+#define WPA_MACHINE_BASE 0
+#define MT2_EAPPacket 0
+#define MT2_EAPOLStart 1
+#define MT2_EAPOLLogoff 2
+#define MT2_EAPOLKey 3
+#define MT2_EAPOLASFAlert 4
+#define MAX_WPA_PSK_MSG 5
+
+#define WPA_PSK_FUNC_SIZE (MAX_WPA_PSK_STATE * MAX_WPA_PSK_MSG)
+
+//
+// STA's CISCO-AIRONET State machine: states, events, total function #
+//
+#define AIRONET_IDLE 0
+#define AIRONET_SCANNING 1
+#define MAX_AIRONET_STATE 2
+
+#define AIRONET_MACHINE_BASE 0
+#define MT2_AIRONET_MSG 0
+#define MT2_AIRONET_SCAN_REQ 1
+#define MT2_AIRONET_SCAN_DONE 2
+#define MAX_AIRONET_MSG 3
+
+#define AIRONET_FUNC_SIZE (MAX_AIRONET_STATE * MAX_AIRONET_MSG)
+
+//
+// AP's CONTROL/CONNECT state machine: states, events, total function #
+//
+#define AP_CNTL_FUNC_SIZE 1
+
+//
+// AP's ASSOC state machine: states, events, total function #
+//
+#define AP_ASSOC_IDLE 0
+#define AP_MAX_ASSOC_STATE 1
+
+#define AP_ASSOC_MACHINE_BASE 0
+#define APMT2_MLME_DISASSOC_REQ 0
+#define APMT2_PEER_DISASSOC_REQ 1
+#define APMT2_PEER_ASSOC_REQ 2
+#define APMT2_PEER_REASSOC_REQ 3
+#define APMT2_CLS3ERR 4
+#define AP_MAX_ASSOC_MSG 5
+
+#define AP_ASSOC_FUNC_SIZE (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG)
+
+//
+// AP's AUTHENTICATION state machine: states, events, total function #
+//
+#define AP_AUTH_REQ_IDLE 0
+#define AP_MAX_AUTH_STATE 1
+
+#define AP_AUTH_MACHINE_BASE 0
+#define APMT2_MLME_DEAUTH_REQ 0
+#define APMT2_CLS2ERR 1
+#define AP_MAX_AUTH_MSG 2
+
+#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG)
+
+//
+// AP's AUTH-RSP state machine: states, events, total function #
+//
+#define AP_AUTH_RSP_IDLE 0
+#define AP_MAX_AUTH_RSP_STATE 1
+
+#define AP_AUTH_RSP_MACHINE_BASE 0
+#define APMT2_AUTH_CHALLENGE_TIMEOUT 0
+#define APMT2_PEER_AUTH_ODD 1
+#define APMT2_PEER_DEAUTH 2
+#define AP_MAX_AUTH_RSP_MSG 3
+
+#define AP_AUTH_RSP_FUNC_SIZE (AP_MAX_AUTH_RSP_STATE * AP_MAX_AUTH_RSP_MSG)
+
+//
+// AP's SYNC state machine: states, events, total function #
+//
+#define AP_SYNC_IDLE 0
+#define AP_SCAN_LISTEN 1
+#define AP_MAX_SYNC_STATE 2
+
+#define AP_SYNC_MACHINE_BASE 0
+#define APMT2_PEER_PROBE_REQ 0
+#define APMT2_PEER_BEACON 1
+#define APMT2_MLME_SCAN_REQ 2
+#define APMT2_PEER_PROBE_RSP 3
+#define APMT2_SCAN_TIMEOUT 4
+#define APMT2_MLME_SCAN_CNCL 5
+#define AP_MAX_SYNC_MSG 6
+
+#define AP_SYNC_FUNC_SIZE (AP_MAX_SYNC_STATE * AP_MAX_SYNC_MSG)
+
+//
+// AP's WPA state machine: states, events, total function #
+//
+#define AP_WPA_PTK 0
+#define AP_MAX_WPA_PTK_STATE 1
+
+#define AP_WPA_MACHINE_BASE 0
+#define APMT2_EAPPacket 0
+#define APMT2_EAPOLStart 1
+#define APMT2_EAPOLLogoff 2
+#define APMT2_EAPOLKey 3
+#define APMT2_EAPOLASFAlert 4
+#define AP_MAX_WPA_MSG 5
+
+#define AP_WPA_FUNC_SIZE (AP_MAX_WPA_PTK_STATE * AP_MAX_WPA_MSG)
+
+#ifdef APCLI_SUPPORT
+//ApCli authentication state machine
+#define APCLI_AUTH_REQ_IDLE 0
+#define APCLI_AUTH_WAIT_SEQ2 1
+#define APCLI_AUTH_WAIT_SEQ4 2
+#define APCLI_MAX_AUTH_STATE 3
+
+#define APCLI_AUTH_MACHINE_BASE 0
+#define APCLI_MT2_MLME_AUTH_REQ 0
+#define APCLI_MT2_MLME_DEAUTH_REQ 1
+#define APCLI_MT2_PEER_AUTH_EVEN 2
+#define APCLI_MT2_PEER_DEAUTH 3
+#define APCLI_MT2_AUTH_TIMEOUT 4
+#define APCLI_MAX_AUTH_MSG 5
+
+#define APCLI_AUTH_FUNC_SIZE (APCLI_MAX_AUTH_STATE * APCLI_MAX_AUTH_MSG)
+
+//ApCli association state machine
+#define APCLI_ASSOC_IDLE 0
+#define APCLI_ASSOC_WAIT_RSP 1
+#define APCLI_MAX_ASSOC_STATE 2
+
+#define APCLI_ASSOC_MACHINE_BASE 0
+#define APCLI_MT2_MLME_ASSOC_REQ 0
+#define APCLI_MT2_MLME_DISASSOC_REQ 1
+#define APCLI_MT2_PEER_DISASSOC_REQ 2
+#define APCLI_MT2_PEER_ASSOC_RSP 3
+#define APCLI_MT2_ASSOC_TIMEOUT 4
+#define APCLI_MAX_ASSOC_MSG 5
+
+#define APCLI_ASSOC_FUNC_SIZE (APCLI_MAX_ASSOC_STATE * APCLI_MAX_ASSOC_MSG)
+
+//ApCli sync state machine
+#define APCLI_SYNC_IDLE 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state
+#define APCLI_JOIN_WAIT_PROBE_RSP 1
+#define APCLI_MAX_SYNC_STATE 2
+
+#define APCLI_SYNC_MACHINE_BASE 0
+#define APCLI_MT2_MLME_PROBE_REQ 0
+#define APCLI_MT2_PEER_PROBE_RSP 1
+#define APCLI_MT2_PROBE_TIMEOUT 2
+#define APCLI_MAX_SYNC_MSG 3
+
+#define APCLI_SYNC_FUNC_SIZE (APCLI_MAX_SYNC_STATE * APCLI_MAX_SYNC_MSG)
+
+//ApCli ctrl state machine
+#define APCLI_CTRL_DISCONNECTED 0 // merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state
+#define APCLI_CTRL_PROBE 1
+#define APCLI_CTRL_AUTH 2
+#define APCLI_CTRL_AUTH_2 3
+#define APCLI_CTRL_ASSOC 4
+#define APCLI_CTRL_DEASSOC 5
+#define APCLI_CTRL_CONNECTED 6
+#define APCLI_MAX_CTRL_STATE 7
+
+#define APCLI_CTRL_MACHINE_BASE 0
+#define APCLI_CTRL_JOIN_REQ 0
+#define APCLI_CTRL_PROBE_RSP 1
+#define APCLI_CTRL_AUTH_RSP 2
+#define APCLI_CTRL_DISCONNECT_REQ 3
+#define APCLI_CTRL_PEER_DISCONNECT_REQ 4
+#define APCLI_CTRL_ASSOC_RSP 5
+#define APCLI_CTRL_DEASSOC_RSP 6
+#define APCLI_CTRL_JOIN_REQ_TIMEOUT 7
+#define APCLI_CTRL_AUTH_REQ_TIMEOUT 8
+#define APCLI_CTRL_ASSOC_REQ_TIMEOUT 9
+#define APCLI_MAX_CTRL_MSG 10
+
+#define APCLI_CTRL_FUNC_SIZE (APCLI_MAX_CTRL_STATE * APCLI_MAX_CTRL_MSG)
+
+#endif // APCLI_SUPPORT //
+
+
+// =============================================================================
+
+// value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header
+#define BTYPE_MGMT 0
+#define BTYPE_CNTL 1
+#define BTYPE_DATA 2
+
+// value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header
+#define SUBTYPE_ASSOC_REQ 0
+#define SUBTYPE_ASSOC_RSP 1
+#define SUBTYPE_REASSOC_REQ 2
+#define SUBTYPE_REASSOC_RSP 3
+#define SUBTYPE_PROBE_REQ 4
+#define SUBTYPE_PROBE_RSP 5
+#define SUBTYPE_BEACON 8
+#define SUBTYPE_ATIM 9
+#define SUBTYPE_DISASSOC 10
+#define SUBTYPE_AUTH 11
+#define SUBTYPE_DEAUTH 12
+#define SUBTYPE_ACTION 13
+#define SUBTYPE_ACTION_NO_ACK 14
+
+// value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header
+#define SUBTYPE_WRAPPER 7
+#define SUBTYPE_BLOCK_ACK_REQ 8
+#define SUBTYPE_BLOCK_ACK 9
+#define SUBTYPE_PS_POLL 10
+#define SUBTYPE_RTS 11
+#define SUBTYPE_CTS 12
+#define SUBTYPE_ACK 13
+#define SUBTYPE_CFEND 14
+#define SUBTYPE_CFEND_CFACK 15
+
+// value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header
+#define SUBTYPE_DATA 0
+#define SUBTYPE_DATA_CFACK 1
+#define SUBTYPE_DATA_CFPOLL 2
+#define SUBTYPE_DATA_CFACK_CFPOLL 3
+#define SUBTYPE_NULL_FUNC 4
+#define SUBTYPE_CFACK 5
+#define SUBTYPE_CFPOLL 6
+#define SUBTYPE_CFACK_CFPOLL 7
+#define SUBTYPE_QDATA 8
+#define SUBTYPE_QDATA_CFACK 9
+#define SUBTYPE_QDATA_CFPOLL 10
+#define SUBTYPE_QDATA_CFACK_CFPOLL 11
+#define SUBTYPE_QOS_NULL 12
+#define SUBTYPE_QOS_CFACK 13
+#define SUBTYPE_QOS_CFPOLL 14
+#define SUBTYPE_QOS_CFACK_CFPOLL 15
+
+// ACK policy of QOS Control field bit 6:5
+#define NORMAL_ACK 0x00 // b6:5 = 00
+#define NO_ACK 0x20 // b6:5 = 01
+#define NO_EXPLICIT_ACK 0x40 // b6:5 = 10
+#define BLOCK_ACK 0x60 // b6:5 = 11
+
+//
+// rtmp_data.c use these definition
+//
+#define LENGTH_802_11 24
+#define LENGTH_802_11_AND_H 30
+#define LENGTH_802_11_CRC_H 34
+#define LENGTH_802_11_CRC 28
+#define LENGTH_802_11_WITH_ADDR4 30
+#define LENGTH_802_3 14
+#define LENGTH_802_3_TYPE 2
+#define LENGTH_802_1_H 8
+#define LENGTH_EAPOL_H 4
+#define LENGTH_WMMQOS_H 2
+#define LENGTH_CRC 4
+#define MAX_SEQ_NUMBER 0x0fff
+#define LENGTH_802_3_NO_TYPE 12
+#define LENGTH_802_1Q 4 /* VLAN related */
+
+// STA_CSR4.field.TxResult
+#define TX_RESULT_SUCCESS 0
+#define TX_RESULT_ZERO_LENGTH 1
+#define TX_RESULT_UNDER_RUN 2
+#define TX_RESULT_OHY_ERROR 4
+#define TX_RESULT_RETRY_FAIL 6
+
+// All PHY rate summary in TXD
+// Preamble MODE in TxD
+#define MODE_CCK 0
+#define MODE_OFDM 1
+#ifdef DOT11_N_SUPPORT
+#define MODE_HTMIX 2
+#define MODE_HTGREENFIELD 3
+#endif // DOT11_N_SUPPORT //
+// MCS for CCK. BW.SGI.STBC are reserved
+#define MCS_LONGP_RATE_1 0 // long preamble CCK 1Mbps
+#define MCS_LONGP_RATE_2 1 // long preamble CCK 1Mbps
+#define MCS_LONGP_RATE_5_5 2
+#define MCS_LONGP_RATE_11 3
+#define MCS_SHORTP_RATE_1 4 // long preamble CCK 1Mbps. short is forbidden in 1Mbps
+#define MCS_SHORTP_RATE_2 5 // short preamble CCK 2Mbps
+#define MCS_SHORTP_RATE_5_5 6
+#define MCS_SHORTP_RATE_11 7
+// To send duplicate legacy OFDM. set BW=BW_40. SGI.STBC are reserved
+#define MCS_RATE_6 0 // legacy OFDM
+#define MCS_RATE_9 1 // OFDM
+#define MCS_RATE_12 2 // OFDM
+#define MCS_RATE_18 3 // OFDM
+#define MCS_RATE_24 4 // OFDM
+#define MCS_RATE_36 5 // OFDM
+#define MCS_RATE_48 6 // OFDM
+#define MCS_RATE_54 7 // OFDM
+// HT
+#define MCS_0 0 // 1S
+#define MCS_1 1
+#define MCS_2 2
+#define MCS_3 3
+#define MCS_4 4
+#define MCS_5 5
+#define MCS_6 6
+#define MCS_7 7
+#define MCS_8 8 // 2S
+#define MCS_9 9
+#define MCS_10 10
+#define MCS_11 11
+#define MCS_12 12
+#define MCS_13 13
+#define MCS_14 14
+#define MCS_15 15
+#define MCS_16 16 // 3*3
+#define MCS_17 17
+#define MCS_18 18
+#define MCS_19 19
+#define MCS_20 20
+#define MCS_21 21
+#define MCS_22 22
+#define MCS_23 23
+#define MCS_32 32
+#define MCS_AUTO 33
+
+#ifdef DOT11_N_SUPPORT
+// OID_HTPHYMODE
+// MODE
+#define HTMODE_MM 0
+#define HTMODE_GF 1
+#endif // DOT11_N_SUPPORT //
+
+// Fixed Tx MODE - HT, CCK or OFDM
+#define FIXED_TXMODE_HT 0
+#define FIXED_TXMODE_CCK 1
+#define FIXED_TXMODE_OFDM 2
+// BW
+#define BW_20 BAND_WIDTH_20
+#define BW_40 BAND_WIDTH_40
+#define BW_BOTH BAND_WIDTH_BOTH
+#define BW_10 BAND_WIDTH_10 // 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field.
+
+#ifdef DOT11_N_SUPPORT
+// SHORTGI
+#define GI_400 GAP_INTERVAL_400 // only support in HT mode
+#define GI_BOTH GAP_INTERVAL_BOTH
+#endif // DOT11_N_SUPPORT //
+#define GI_800 GAP_INTERVAL_800
+// STBC
+#define STBC_NONE 0
+#ifdef DOT11_N_SUPPORT
+#define STBC_USE 1 // limited use in rt2860b phy
+#define RXSTBC_ONE 1 // rx support of one spatial stream
+#define RXSTBC_TWO 2 // rx support of 1 and 2 spatial stream
+#define RXSTBC_THR 3 // rx support of 1~3 spatial stream
+// MCS FEEDBACK
+#define MCSFBK_NONE 0 // not support mcs feedback /
+#define MCSFBK_RSV 1 // reserved
+#define MCSFBK_UNSOLICIT 2 // only support unsolict mcs feedback
+#define MCSFBK_MRQ 3 // response to both MRQ and unsolict mcs feedback
+
+// MIMO power safe
+#define MMPS_STATIC 0
+#define MMPS_DYNAMIC 1
+#define MMPS_RSV 2
+#define MMPS_ENABLE 3
+
+
+// A-MSDU size
+#define AMSDU_0 0
+#define AMSDU_1 1
+
+#endif // DOT11_N_SUPPORT //
+
+// MCS use 7 bits
+#define TXRATEMIMO 0x80
+#define TXRATEMCS 0x7F
+#define TXRATEOFDM 0x7F
+#define RATE_1 0
+#define RATE_2 1
+#define RATE_5_5 2
+#define RATE_11 3
+#define RATE_6 4 // OFDM
+#define RATE_9 5 // OFDM
+#define RATE_12 6 // OFDM
+#define RATE_18 7 // OFDM
+#define RATE_24 8 // OFDM
+#define RATE_36 9 // OFDM
+#define RATE_48 10 // OFDM
+#define RATE_54 11 // OFDM
+#define RATE_FIRST_OFDM_RATE RATE_6
+#define RATE_LAST_OFDM_RATE RATE_54
+#define RATE_6_5 12 // HT mix
+#define RATE_13 13 // HT mix
+#define RATE_19_5 14 // HT mix
+#define RATE_26 15 // HT mix
+#define RATE_39 16 // HT mix
+#define RATE_52 17 // HT mix
+#define RATE_58_5 18 // HT mix
+#define RATE_65 19 // HT mix
+#define RATE_78 20 // HT mix
+#define RATE_104 21 // HT mix
+#define RATE_117 22 // HT mix
+#define RATE_130 23 // HT mix
+//#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only
+#define HTRATE_0 12
+#define RATE_FIRST_MM_RATE HTRATE_0
+#define RATE_FIRST_HT_RATE HTRATE_0
+#define RATE_LAST_HT_RATE HTRATE_0
+
+// pTxWI->txop
+#define IFS_HTTXOP 0 // The txop will be handles by ASIC.
+#define IFS_PIFS 1
+#define IFS_SIFS 2
+#define IFS_BACKOFF 3
+
+// pTxD->RetryMode
+#define LONG_RETRY 1
+#define SHORT_RETRY 0
+
+// Country Region definition
+#define REGION_MINIMUM_BG_BAND 0
+#define REGION_0_BG_BAND 0 // 1-11
+#define REGION_1_BG_BAND 1 // 1-13
+#define REGION_2_BG_BAND 2 // 10-11
+#define REGION_3_BG_BAND 3 // 10-13
+#define REGION_4_BG_BAND 4 // 14
+#define REGION_5_BG_BAND 5 // 1-14
+#define REGION_6_BG_BAND 6 // 3-9
+#define REGION_7_BG_BAND 7 // 5-13
+#define REGION_31_BG_BAND 31 // 5-13
+#define REGION_MAXIMUM_BG_BAND 7
+
+#define REGION_MINIMUM_A_BAND 0
+#define REGION_0_A_BAND 0 // 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165
+#define REGION_1_A_BAND 1 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+#define REGION_2_A_BAND 2 // 36, 40, 44, 48, 52, 56, 60, 64
+#define REGION_3_A_BAND 3 // 52, 56, 60, 64, 149, 153, 157, 161
+#define REGION_4_A_BAND 4 // 149, 153, 157, 161, 165
+#define REGION_5_A_BAND 5 // 149, 153, 157, 161
+#define REGION_6_A_BAND 6 // 36, 40, 44, 48
+#define REGION_7_A_BAND 7 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165
+#define REGION_8_A_BAND 8 // 52, 56, 60, 64
+#define REGION_9_A_BAND 9 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165
+#define REGION_10_A_BAND 10 // 36, 40, 44, 48, 149, 153, 157, 161, 165
+#define REGION_11_A_BAND 11 // 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161
+#define REGION_MAXIMUM_A_BAND 11
+
+// pTxD->CipherAlg
+#define CIPHER_NONE 0
+#define CIPHER_WEP64 1
+#define CIPHER_WEP128 2
+#define CIPHER_TKIP 3
+#define CIPHER_AES 4
+#define CIPHER_CKIP64 5
+#define CIPHER_CKIP128 6
+#define CIPHER_TKIP_NO_MIC 7 // MIC appended by driver: not a valid value in hardware key table
+#define CIPHER_SMS4 8
+
+// value domain of pAd->RfIcType
+#define RFIC_2820 1 // 2.4G 2T3R
+#define RFIC_2850 2 // 2.4G/5G 2T3R
+#define RFIC_2720 3 // 2.4G 1T2R
+#define RFIC_2750 4 // 2.4G/5G 1T2R
+#define RFIC_3020 5 // 2.4G 1T1R
+#define RFIC_2020 6 // 2.4G B/G
+
+// LED Status.
+#define LED_LINK_DOWN 0
+#define LED_LINK_UP 1
+#define LED_RADIO_OFF 2
+#define LED_RADIO_ON 3
+#define LED_HALT 4
+#define LED_WPS 5
+#define LED_ON_SITE_SURVEY 6
+#define LED_POWER_UP 7
+
+// value domain of pAd->LedCntl.LedMode and E2PROM
+#define LED_MODE_DEFAULT 0
+#define LED_MODE_TWO_LED 1
+#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8
+
+// RC4 init value, used fro WEP & TKIP
+#define PPPINITFCS32 0xffffffff /* Initial FCS value */
+
+// value domain of pAd->StaCfg.PortSecured. 802.1X controlled port definition
+#define WPA_802_1X_PORT_SECURED 1
+#define WPA_802_1X_PORT_NOT_SECURED 2
+
+#define PAIRWISE_KEY 1
+#define GROUP_KEY 2
+
+//definition of DRS
+#define MAX_STEP_OF_TX_RATE_SWITCH 32
+
+
+// pre-allocated free NDIS PACKET/BUFFER poll for internal usage
+#define MAX_NUM_OF_FREE_NDIS_PACKET 128
+
+//Block ACK
+#define MAX_TX_REORDERBUF 64
+#define MAX_RX_REORDERBUF 64
+#define DEFAULT_TX_TIMEOUT 30
+#define DEFAULT_RX_TIMEOUT 30
+
+// definition of Recipient or Originator
+#define I_RECIPIENT TRUE
+#define I_ORIGINATOR FALSE
+
+#define DEFAULT_BBP_TX_POWER 0
+#define DEFAULT_RF_TX_POWER 5
+
+#define MAX_INI_BUFFER_SIZE 4096
+#define MAX_PARAM_BUFFER_SIZE (2048) // enough for ACL (18*64)
+ //18 : the length of Mac address acceptable format "01:02:03:04:05:06;")
+ //64 : MAX_NUM_OF_ACL_LIST
+// definition of pAd->OpMode
+#define OPMODE_STA 0
+#define OPMODE_AP 1
+//#define OPMODE_L3_BRG 2 // as AP and STA at the same time
+
+#ifdef RT_BIG_ENDIAN
+#define DIR_READ 0
+#define DIR_WRITE 1
+#define TYPE_TXD 0
+#define TYPE_RXD 1
+#define TYPE_TXINFO 0
+#define TYPE_RXINFO 1
+#define TYPE_TXWI 0
+#define TYPE_RXWI 1
+#endif
+
+// ========================= AP rtmp_def.h ===========================
+// value domain for pAd->EventTab.Log[].Event
+#define EVENT_RESET_ACCESS_POINT 0 // Log = "hh:mm:ss Restart Access Point"
+#define EVENT_ASSOCIATED 1 // Log = "hh:mm:ss STA 00:01:02:03:04:05 associated"
+#define EVENT_DISASSOCIATED 2 // Log = "hh:mm:ss STA 00:01:02:03:04:05 left this BSS"
+#define EVENT_AGED_OUT 3 // Log = "hh:mm:ss STA 00:01:02:03:04:05 was aged-out and removed from this BSS"
+#define EVENT_COUNTER_M 4
+#define EVENT_INVALID_PSK 5
+#define EVENT_MAX_EVENT_TYPE 6
+// ==== end of AP rtmp_def.h ============
+
+// definition RSSI Number
+#define RSSI_0 0
+#define RSSI_1 1
+#define RSSI_2 2
+
+// definition of radar detection
+#define RD_NORMAL_MODE 0 // Not found radar signal
+#define RD_SWITCHING_MODE 1 // Found radar signal, and doing channel switch
+#define RD_SILENCE_MODE 2 // After channel switch, need to be silence a while to ensure radar not found
+
+//Driver defined cid for mapping status and command.
+#define SLEEPCID 0x11
+#define WAKECID 0x22
+#define QUERYPOWERCID 0x33
+#define OWNERMCU 0x1
+#define OWNERCPU 0x0
+
+// MBSSID definition
+#define ENTRY_NOT_FOUND 0xFF
+
+
+/* After Linux 2.6.9,
+ * VLAN module use Private (from user) interface flags (netdevice->priv_flags).
+ * #define IFF_802_1Q_VLAN 0x1 -- 802.1Q VLAN device. in if.h
+ * ref to ip_sabotage_out() [ out->priv_flags & IFF_802_1Q_VLAN ] in br_netfilter.c
+ *
+ * For this reason, we MUST use EVEN value in priv_flags
+ */
+#define INT_MAIN 0x0100
+#define INT_MBSSID 0x0200
+#define INT_WDS 0x0300
+#define INT_APCLI 0x0400
+#define INT_MESH 0x0500
+
+// Use bitmap to allow coexist of ATE_TXFRAME and ATE_RXFRAME(i.e.,to support LoopBack mode)
+#ifdef RALINK_ATE
+#define ATE_START 0x00 // Start ATE
+#define ATE_STOP 0x80 // Stop ATE
+#define ATE_TXCONT 0x05 // Continuous Transmit
+#define ATE_TXCARR 0x09 // Transmit Carrier
+#define ATE_TXCARRSUPP 0x11 // Transmit Carrier Suppression
+#define ATE_TXFRAME 0x01 // Transmit Frames
+#define ATE_RXFRAME 0x02 // Receive Frames
+#ifdef RALINK_28xx_QA
+#define ATE_TXSTOP 0xe2 // Stop Transmition(i.e., TXCONT, TXCARR, TXCARRSUPP, and TXFRAME)
+#define ATE_RXSTOP 0xfd // Stop receiving Frames
+#define BBP22_TXFRAME 0x00 // Transmit Frames
+#define BBP22_TXCONT_OR_CARRSUPP 0x80 // Continuous Transmit or Carrier Suppression
+#define BBP22_TXCARR 0xc1 // Transmit Carrier
+#define BBP24_TXCONT 0x00 // Continuous Transmit
+#define BBP24_CARRSUPP 0x01 // Carrier Suppression
+#endif // RALINK_28xx_QA //
+#endif // RALINK_ATE //
+
+// WEP Key TYPE
+#define WEP_HEXADECIMAL_TYPE 0
+#define WEP_ASCII_TYPE 1
+
+
+
+// WIRELESS EVENTS definition
+/* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */
+#define IW_CUSTOM_MAX_LEN 255 /* In bytes */
+
+// For system event - start
+#define IW_SYS_EVENT_FLAG_START 0x0200
+#define IW_ASSOC_EVENT_FLAG 0x0200
+#define IW_DISASSOC_EVENT_FLAG 0x0201
+#define IW_DEAUTH_EVENT_FLAG 0x0202
+#define IW_AGEOUT_EVENT_FLAG 0x0203
+#define IW_COUNTER_MEASURES_EVENT_FLAG 0x0204
+#define IW_REPLAY_COUNTER_DIFF_EVENT_FLAG 0x0205
+#define IW_RSNIE_DIFF_EVENT_FLAG 0x0206
+#define IW_MIC_DIFF_EVENT_FLAG 0x0207
+#define IW_ICV_ERROR_EVENT_FLAG 0x0208
+#define IW_MIC_ERROR_EVENT_FLAG 0x0209
+#define IW_GROUP_HS_TIMEOUT_EVENT_FLAG 0x020A
+#define IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG 0x020B
+#define IW_RSNIE_SANITY_FAIL_EVENT_FLAG 0x020C
+#define IW_SET_KEY_DONE_WPA1_EVENT_FLAG 0x020D
+#define IW_SET_KEY_DONE_WPA2_EVENT_FLAG 0x020E
+#define IW_STA_LINKUP_EVENT_FLAG 0x020F
+#define IW_STA_LINKDOWN_EVENT_FLAG 0x0210
+#define IW_SCAN_COMPLETED_EVENT_FLAG 0x0211
+#define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG 0x0212
+// if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END
+#define IW_SYS_EVENT_FLAG_END 0x0212
+#define IW_SYS_EVENT_TYPE_NUM (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1)
+// For system event - end
+
+// For spoof attack event - start
+#define IW_SPOOF_EVENT_FLAG_START 0x0300
+#define IW_CONFLICT_SSID_EVENT_FLAG 0x0300
+#define IW_SPOOF_ASSOC_RESP_EVENT_FLAG 0x0301
+#define IW_SPOOF_REASSOC_RESP_EVENT_FLAG 0x0302
+#define IW_SPOOF_PROBE_RESP_EVENT_FLAG 0x0303
+#define IW_SPOOF_BEACON_EVENT_FLAG 0x0304
+#define IW_SPOOF_DISASSOC_EVENT_FLAG 0x0305
+#define IW_SPOOF_AUTH_EVENT_FLAG 0x0306
+#define IW_SPOOF_DEAUTH_EVENT_FLAG 0x0307
+#define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG 0x0308
+#define IW_REPLAY_ATTACK_EVENT_FLAG 0x0309
+// if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END
+#define IW_SPOOF_EVENT_FLAG_END 0x0309
+#define IW_SPOOF_EVENT_TYPE_NUM (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1)
+// For spoof attack event - end
+
+// For flooding attack event - start
+#define IW_FLOOD_EVENT_FLAG_START 0x0400
+#define IW_FLOOD_AUTH_EVENT_FLAG 0x0400
+#define IW_FLOOD_ASSOC_REQ_EVENT_FLAG 0x0401
+#define IW_FLOOD_REASSOC_REQ_EVENT_FLAG 0x0402
+#define IW_FLOOD_PROBE_REQ_EVENT_FLAG 0x0403
+#define IW_FLOOD_DISASSOC_EVENT_FLAG 0x0404
+#define IW_FLOOD_DEAUTH_EVENT_FLAG 0x0405
+#define IW_FLOOD_EAP_REQ_EVENT_FLAG 0x0406
+// if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END
+#define IW_FLOOD_EVENT_FLAG_END 0x0406
+#define IW_FLOOD_EVENT_TYPE_NUM (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1)
+// For flooding attack - end
+
+// End - WIRELESS EVENTS definition
+
+#ifdef CONFIG_STA_SUPPORT
+// definition for DLS, kathy
+#define MAX_NUM_OF_INIT_DLS_ENTRY 1
+#define MAX_NUM_OF_DLS_ENTRY MAX_NUMBER_OF_DLS_ENTRY
+
+//Block ACK , rt2860, kathy
+#define MAX_TX_REORDERBUF 64
+#define MAX_RX_REORDERBUF 64
+#define DEFAULT_TX_TIMEOUT 30
+#define DEFAULT_RX_TIMEOUT 30
+#ifndef CONFIG_AP_SUPPORT
+#define MAX_BARECI_SESSION 8
+#endif
+
+#ifndef IW_ESSID_MAX_SIZE
+/* Maximum size of the ESSID and pAd->nickname strings */
+#define IW_ESSID_MAX_SIZE 32
+#endif
+#endif // CONFIG_STA_SUPPORT //
+
+#ifdef MCAST_RATE_SPECIFIC
+#define MCAST_DISABLE 0
+#define MCAST_CCK 1
+#define MCAST_OFDM 2
+#define MCAST_HTMIX 3
+#endif // MCAST_RATE_SPECIFIC //
+
+// For AsicRadioOff/AsicRadioOn function
+#define DOT11POWERSAVE 0
+#define GUIRADIO_OFF 1
+#define RTMP_HALT 2
+#define GUI_IDLE_POWER_SAVE 3
+// --
+
+
+// definition for WpaSupport flag
+#define WPA_SUPPLICANT_DISABLE 0
+#define WPA_SUPPLICANT_ENABLE 1
+#define WPA_SUPPLICANT_ENABLE_WITH_WEB_UI 2
+
+// Endian byte swapping codes
+#define SWAP16(x) \
+ ((UINT16)( \
+ (((UINT16)(x) & (UINT16) 0x00ffU) << 8) | \
+ (((UINT16)(x) & (UINT16) 0xff00U) >> 8) ))
+
+#define SWAP32(x) \
+ ((UINT32)( \
+ (((UINT32)(x) & (UINT32) 0x000000ffUL) << 24) | \
+ (((UINT32)(x) & (UINT32) 0x0000ff00UL) << 8) | \
+ (((UINT32)(x) & (UINT32) 0x00ff0000UL) >> 8) | \
+ (((UINT32)(x) & (UINT32) 0xff000000UL) >> 24) ))
+
+#define SWAP64(x) \
+ ((UINT64)( \
+ (UINT64)(((UINT64)(x) & (UINT64) 0x00000000000000ffULL) << 56) | \
+ (UINT64)(((UINT64)(x) & (UINT64) 0x000000000000ff00ULL) << 40) | \
+ (UINT64)(((UINT64)(x) & (UINT64) 0x0000000000ff0000ULL) << 24) | \
+ (UINT64)(((UINT64)(x) & (UINT64) 0x00000000ff000000ULL) << 8) | \
+ (UINT64)(((UINT64)(x) & (UINT64) 0x000000ff00000000ULL) >> 8) | \
+ (UINT64)(((UINT64)(x) & (UINT64) 0x0000ff0000000000ULL) >> 24) | \
+ (UINT64)(((UINT64)(x) & (UINT64) 0x00ff000000000000ULL) >> 40) | \
+ (UINT64)(((UINT64)(x) & (UINT64) 0xff00000000000000ULL) >> 56) ))
+
+#ifdef RT_BIG_ENDIAN
+
+#define cpu2le64(x) SWAP64((x))
+#define le2cpu64(x) SWAP64((x))
+#define cpu2le32(x) SWAP32((x))
+#define le2cpu32(x) SWAP32((x))
+#define cpu2le16(x) SWAP16((x))
+#define le2cpu16(x) SWAP16((x))
+#define cpu2be64(x) ((UINT64)(x))
+#define be2cpu64(x) ((UINT64)(x))
+#define cpu2be32(x) ((UINT32)(x))
+#define be2cpu32(x) ((UINT32)(x))
+#define cpu2be16(x) ((UINT16)(x))
+#define be2cpu16(x) ((UINT16)(x))
+
+#else // Little_Endian
+
+#define cpu2le64(x) ((UINT64)(x))
+#define le2cpu64(x) ((UINT64)(x))
+#define cpu2le32(x) ((UINT32)(x))
+#define le2cpu32(x) ((UINT32)(x))
+#define cpu2le16(x) ((UINT16)(x))
+#define le2cpu16(x) ((UINT16)(x))
+#define cpu2be64(x) SWAP64((x))
+#define be2cpu64(x) SWAP64((x))
+#define cpu2be32(x) SWAP32((x))
+#define be2cpu32(x) SWAP32((x))
+#define cpu2be16(x) SWAP16((x))
+#define be2cpu16(x) SWAP16((x))
+
+#endif // RT_BIG_ENDIAN
+
+#endif // __RTMP_DEF_H__
+
+
diff --git a/drivers/staging/rt2860/rtmp_type.h b/drivers/staging/rt2860/rtmp_type.h
new file mode 100644
index 000000000000..1fd7df1e1791
--- /dev/null
+++ b/drivers/staging/rt2860/rtmp_type.h
@@ -0,0 +1,94 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_type.h
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Name Date Modification logs
+ Paul Lin 1-2-2004
+*/
+#ifndef __RTMP_TYPE_H__
+#define __RTMP_TYPE_H__
+
+#define PACKED __attribute__ ((packed))
+
+// Put platform dependent declaration here
+// For example, linux type definition
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+typedef unsigned long long UINT64;
+typedef int INT32;
+typedef long long INT64;
+
+typedef unsigned char * PUINT8;
+typedef unsigned short * PUINT16;
+typedef unsigned int * PUINT32;
+typedef unsigned long long * PUINT64;
+typedef int * PINT32;
+typedef long long * PINT64;
+
+typedef signed char CHAR;
+typedef signed short SHORT;
+typedef signed int INT;
+typedef signed long LONG;
+typedef signed long long LONGLONG;
+
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned int UINT;
+typedef unsigned long ULONG;
+typedef unsigned long long ULONGLONG;
+
+typedef unsigned char BOOLEAN;
+typedef void VOID;
+
+typedef VOID * PVOID;
+typedef CHAR * PCHAR;
+typedef UCHAR * PUCHAR;
+typedef USHORT * PUSHORT;
+typedef LONG * PLONG;
+typedef ULONG * PULONG;
+typedef UINT * PUINT;
+
+typedef unsigned int NDIS_MEDIA_STATE;
+
+typedef union _LARGE_INTEGER {
+ struct {
+ UINT LowPart;
+ INT32 HighPart;
+ } u;
+ INT64 QuadPart;
+} LARGE_INTEGER;
+
+#endif // __RTMP_TYPE_H__
+
diff --git a/drivers/staging/rt2860/spectrum.h b/drivers/staging/rt2860/spectrum.h
new file mode 100644
index 000000000000..60f25dbdba9f
--- /dev/null
+++ b/drivers/staging/rt2860/spectrum.h
@@ -0,0 +1,322 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+*/
+
+#ifndef __SPECTRUM_H__
+#define __SPECTRUM_H__
+
+#include "rtmp_type.h"
+#include "spectrum_def.h"
+
+typedef struct PACKED _TPC_REPORT_INFO
+{
+ UINT8 TxPwr;
+ UINT8 LinkMargin;
+} TPC_REPORT_INFO, *PTPC_REPORT_INFO;
+
+typedef struct PACKED _CH_SW_ANN_INFO
+{
+ UINT8 ChSwMode;
+ UINT8 Channel;
+ UINT8 ChSwCnt;
+} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO;
+
+typedef union PACKED _MEASURE_REQ_MODE
+{
+#ifdef RT_BIG_ENDIAN
+ struct PACKED
+ {
+ UINT8 Rev1:4;
+ UINT8 Report:1;
+ UINT8 Request:1;
+ UINT8 Enable:1;
+ UINT8 Rev0:1;
+ } field;
+#else
+ struct PACKED
+ {
+ UINT8 Rev0:1;
+ UINT8 Enable:1;
+ UINT8 Request:1;
+ UINT8 Report:1;
+ UINT8 Rev1:4;
+ } field;
+#endif // RT_BIG_ENDIAN //
+ UINT8 word;
+} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE;
+
+typedef struct PACKED _MEASURE_REQ
+{
+ UINT8 ChNum;
+ UINT64 MeasureStartTime;
+ UINT16 MeasureDuration;
+} MEASURE_REQ, *PMEASURE_REQ;
+
+typedef struct PACKED _MEASURE_REQ_INFO
+{
+ UINT8 Token;
+ MEASURE_REQ_MODE ReqMode;
+ UINT8 ReqType;
+ MEASURE_REQ MeasureReq;
+} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO;
+
+typedef union PACKED _MEASURE_BASIC_REPORT_MAP
+{
+#ifdef RT_BIG_ENDIAN
+ struct PACKED
+ {
+ UINT8 Rev:3;
+ UINT8 Unmeasure:1;
+ UINT8 Radar:1;
+ UINT8 UnidentifiedSignal:1;
+ UINT8 OfdmPreamble:1;
+ UINT8 BSS:1;
+ } field;
+#else
+ struct PACKED
+ {
+ UINT8 BSS:1;
+ UINT8 OfdmPreamble:1;
+ UINT8 UnidentifiedSignal:1;
+ UINT8 Radar:1;
+ UINT8 Unmeasure:1;
+ UINT8 Rev:3;
+ } field;
+#endif // RT_BIG_ENDIAN //
+ UINT8 word;
+} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP;
+
+typedef struct PACKED _MEASURE_BASIC_REPORT
+{
+ UINT8 ChNum;
+ UINT64 MeasureStartTime;
+ UINT16 MeasureDuration;
+ MEASURE_BASIC_REPORT_MAP Map;
+} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT;
+
+typedef struct PACKED _MEASURE_CCA_REPORT
+{
+ UINT8 ChNum;
+ UINT64 MeasureStartTime;
+ UINT16 MeasureDuration;
+ UINT8 CCA_Busy_Fraction;
+} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT;
+
+typedef struct PACKED _MEASURE_RPI_REPORT
+{
+ UINT8 ChNum;
+ UINT64 MeasureStartTime;
+ UINT16 MeasureDuration;
+ UINT8 RPI_Density[8];
+} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT;
+
+typedef union PACKED _MEASURE_REPORT_MODE
+{
+ struct PACKED
+ {
+#ifdef RT_BIG_ENDIAN
+ UINT8 Rev:5;
+ UINT8 Refused:1;
+ UINT8 Incapable:1;
+ UINT8 Late:1;
+#else
+ UINT8 Late:1;
+ UINT8 Incapable:1;
+ UINT8 Refused:1;
+ UINT8 Rev:5;
+#endif // RT_BIG_ENDIAN //
+ } field;
+ UINT8 word;
+} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE;
+
+typedef struct PACKED _MEASURE_REPORT_INFO
+{
+ UINT8 Token;
+ MEASURE_REPORT_MODE ReportMode;
+ UINT8 ReportType;
+ UINT8 Octect[0];
+} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO;
+
+typedef struct PACKED _QUIET_INFO
+{
+ UINT8 QuietCnt;
+ UINT8 QuietPeriod;
+ UINT8 QuietDuration;
+ UINT8 QuietOffset;
+} QUIET_INFO, *PQUIET_INFO;
+
+/*
+ ==========================================================================
+ Description:
+ Prepare Measurement request action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueMeasurementReq(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 MeasureToken,
+ IN UINT8 MeasureReqMode,
+ IN UINT8 MeasureReqType,
+ IN UINT8 MeasureCh,
+ IN UINT16 MeasureDuration);
+
+/*
+ ==========================================================================
+ Description:
+ Prepare Measurement report action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueMeasurementRep(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 DialogToken,
+ IN UINT8 MeasureToken,
+ IN UINT8 MeasureReqMode,
+ IN UINT8 MeasureReqType,
+ IN UINT8 ReportInfoLen,
+ IN PUINT8 pReportInfo);
+
+/*
+ ==========================================================================
+ Description:
+ Prepare TPC Request action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueTPCReq(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UCHAR DialogToken);
+
+/*
+ ==========================================================================
+ Description:
+ Prepare TPC Report action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueTPCRep(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 DialogToken,
+ IN UINT8 TxPwr,
+ IN UINT8 LinkMargin);
+
+/*
+ ==========================================================================
+ Description:
+ Prepare Channel Switch Announcement action frame and enqueue it into
+ management queue waiting for transmition.
+
+ Parametrs:
+ 1. the destination mac address of the frame.
+ 2. Channel switch announcement mode.
+ 2. a New selected channel.
+
+ Return : None.
+ ==========================================================================
+ */
+VOID EnqueueChSwAnn(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN UINT8 ChSwMode,
+ IN UINT8 NewCh);
+
+/*
+ ==========================================================================
+ Description:
+ Spectrun action frames Handler such as channel switch annoucement,
+ measurement report, measurement request actions frames.
+
+ Parametrs:
+ Elme - MLME message containing the received frame
+
+ Return : None.
+ ==========================================================================
+ */
+VOID PeerSpectrumAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem);
+
+/*
+ ==========================================================================
+ Description:
+
+ Parametrs:
+
+ Return : None.
+ ==========================================================================
+ */
+INT Set_MeasureReq_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+INT Set_TpcReq_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg);
+
+VOID MeasureReqTabInit(
+ IN PRTMP_ADAPTER pAd);
+
+VOID MeasureReqTabExit(
+ IN PRTMP_ADAPTER pAd);
+
+VOID TpcReqTabInit(
+ IN PRTMP_ADAPTER pAd);
+
+VOID TpcReqTabExit(
+ IN PRTMP_ADAPTER pAd);
+
+VOID NotifyChSwAnnToPeerAPs(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pRA,
+ IN PUCHAR pTA,
+ IN UINT8 ChSwMode,
+ IN UINT8 Channel);
+#endif // __SPECTRUM_H__ //
+
diff --git a/drivers/staging/rt2860/spectrum_def.h b/drivers/staging/rt2860/spectrum_def.h
new file mode 100644
index 000000000000..4ca4817bba05
--- /dev/null
+++ b/drivers/staging/rt2860/spectrum_def.h
@@ -0,0 +1,95 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ spectrum_def.h
+
+ Abstract:
+ Handle association related requests either from WSTA or from local MLME
+
+ Revision History:
+ Who When What
+ --------- ---------- ----------------------------------------------
+ Fonchi Wu 2008 created for 802.11h
+ */
+
+#ifndef __SPECTRUM_DEF_H__
+#define __SPECTRUM_DEF_H__
+
+#define MAX_MEASURE_REQ_TAB_SIZE 3
+#define MAX_HASH_MEASURE_REQ_TAB_SIZE MAX_MEASURE_REQ_TAB_SIZE
+
+#define MAX_TPC_REQ_TAB_SIZE 3
+#define MAX_HASH_TPC_REQ_TAB_SIZE MAX_TPC_REQ_TAB_SIZE
+
+#define MIN_RCV_PWR 100 /* Negative value ((dBm) */
+
+#define RM_TPC_REQ 0
+#define RM_MEASURE_REQ 1
+
+#define RM_BASIC 0
+#define RM_CCA 1
+#define RM_RPI_HISTOGRAM 2
+
+#define TPC_REQ_AGE_OUT 500 /* ms */
+#define MQ_REQ_AGE_OUT 500 /* ms */
+
+#define TPC_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_HASH_TPC_REQ_TAB_SIZE)
+#define MQ_DIALOGTOKEN_HASH_INDEX(_DialogToken) ((_DialogToken) % MAX_MEASURE_REQ_TAB_SIZE)
+
+typedef struct _MEASURE_REQ_ENTRY
+{
+ struct _MEASURE_REQ_ENTRY *pNext;
+ ULONG lastTime;
+ BOOLEAN Valid;
+ UINT8 DialogToken;
+ UINT8 MeasureDialogToken[3]; // 0:basic measure, 1: CCA measure, 2: RPI_Histogram measure.
+} MEASURE_REQ_ENTRY, *PMEASURE_REQ_ENTRY;
+
+typedef struct _MEASURE_REQ_TAB
+{
+ UCHAR Size;
+ PMEASURE_REQ_ENTRY Hash[MAX_HASH_MEASURE_REQ_TAB_SIZE];
+ MEASURE_REQ_ENTRY Content[MAX_MEASURE_REQ_TAB_SIZE];
+} MEASURE_REQ_TAB, *PMEASURE_REQ_TAB;
+
+typedef struct _TPC_REQ_ENTRY
+{
+ struct _TPC_REQ_ENTRY *pNext;
+ ULONG lastTime;
+ BOOLEAN Valid;
+ UINT8 DialogToken;
+} TPC_REQ_ENTRY, *PTPC_REQ_ENTRY;
+
+typedef struct _TPC_REQ_TAB
+{
+ UCHAR Size;
+ PTPC_REQ_ENTRY Hash[MAX_HASH_TPC_REQ_TAB_SIZE];
+ TPC_REQ_ENTRY Content[MAX_TPC_REQ_TAB_SIZE];
+} TPC_REQ_TAB, *PTPC_REQ_TAB;
+
+#endif // __SPECTRUM_DEF_H__ //
+
diff --git a/drivers/staging/rt2860/sta/aironet.c b/drivers/staging/rt2860/sta/aironet.c
new file mode 100644
index 000000000000..4af4a1906181
--- /dev/null
+++ b/drivers/staging/rt2860/sta/aironet.c
@@ -0,0 +1,1312 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ aironet.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Paul Lin 04-06-15 Initial
+*/
+#include "../rt_config.h"
+
+/*
+ ==========================================================================
+ Description:
+ association state machine init, including state transition and timer init
+ Parameters:
+ S - pointer to the association state machine
+ ==========================================================================
+ */
+VOID AironetStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(S, Trans, MAX_AIRONET_STATE, MAX_AIRONET_MSG, (STATE_MACHINE_FUNC)Drop, AIRONET_IDLE, AIRONET_MACHINE_BASE);
+ StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_MSG, (STATE_MACHINE_FUNC)AironetMsgAction);
+ StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_SCAN_REQ, (STATE_MACHINE_FUNC)AironetRequestAction);
+ StateMachineSetAction(S, AIRONET_SCANNING, MT2_AIRONET_SCAN_DONE, (STATE_MACHINE_FUNC)AironetReportAction);
+}
+
+/*
+ ==========================================================================
+ Description:
+ This is state machine function.
+ When receiving EAPOL packets which is for 802.1x key management.
+ Use both in WPA, and WPAPSK case.
+ In this function, further dispatch to different functions according to the received packet. 3 categories are :
+ 1. normal 4-way pairwisekey and 2-way groupkey handshake
+ 2. MIC error (Countermeasures attack) report packet from STA.
+ 3. Request for pairwise/group key update from STA
+ Return:
+ ==========================================================================
+*/
+VOID AironetMsgAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Length;
+ UCHAR Index, i;
+ PUCHAR pData;
+ PAIRONET_RM_REQUEST_FRAME pRMReq;
+ PRM_REQUEST_ACTION pReqElem;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n"));
+
+ // 0. Get Aironet IAPP header first
+ pRMReq = (PAIRONET_RM_REQUEST_FRAME) &Elem->Msg[LENGTH_802_11];
+ pData = (PUCHAR) &Elem->Msg[LENGTH_802_11];
+
+ // 1. Change endian format form network to little endian
+ Length = be2cpu16(pRMReq->IAPP.Length);
+
+ // 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled
+ if (pAd->StaCfg.CCXEnable != TRUE)
+ return;
+
+ // 2.1 Radio measurement must be on
+ if (pAd->StaCfg.CCXControl.field.RMEnable != 1)
+ return;
+
+ // 2.2. Debug print all bit information
+ DBGPRINT(RT_DEBUG_TRACE, ("IAPP ID & Length %d\n", Length));
+ DBGPRINT(RT_DEBUG_TRACE, ("IAPP Type %x\n", pRMReq->IAPP.Type));
+ DBGPRINT(RT_DEBUG_TRACE, ("IAPP SubType %x\n", pRMReq->IAPP.SubType));
+ DBGPRINT(RT_DEBUG_TRACE, ("IAPP Dialog Token %x\n", pRMReq->IAPP.Token));
+ DBGPRINT(RT_DEBUG_TRACE, ("IAPP Activation Delay %x\n", pRMReq->Delay));
+ DBGPRINT(RT_DEBUG_TRACE, ("IAPP Measurement Offset %x\n", pRMReq->Offset));
+
+ // 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension
+ if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n"));
+ return;
+ }
+
+ // 4. Check IAPP frame subtype, it must be 0x01 for Cisco Aironet extension request.
+ // Since we are acting as client only, we will disregards reply subtype.
+ if (pRMReq->IAPP.SubType != AIRONET_IAPP_SUBTYPE_REQUEST)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n"));
+ return;
+ }
+
+ // 5. Verify Destination MAC and Source MAC, both should be all zeros.
+ if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n"));
+ return;
+ }
+
+ if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n"));
+ return;
+ }
+
+ // 6. Reinit all report related fields
+ NdisZeroMemory(pAd->StaCfg.FrameReportBuf, 2048);
+ NdisZeroMemory(pAd->StaCfg.BssReportOffset, sizeof(USHORT) * MAX_LEN_OF_BSS_TABLE);
+ NdisZeroMemory(pAd->StaCfg.MeasurementRequest, sizeof(RM_REQUEST_ACTION) * 4);
+
+ // 7. Point to the start of first element report element
+ pAd->StaCfg.FrameReportLen = LENGTH_802_11 + sizeof(AIRONET_IAPP_HEADER);
+ DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
+ pAd->StaCfg.LastBssIndex = 0xff;
+ pAd->StaCfg.RMReqCnt = 0;
+ pAd->StaCfg.ParallelReq = FALSE;
+ pAd->StaCfg.ParallelDuration = 0;
+ pAd->StaCfg.ParallelChannel = 0;
+ pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token;
+ pAd->StaCfg.CurrentRMReqIdx = 0;
+ pAd->StaCfg.CLBusyBytes = 0;
+ // Reset the statistics
+ for (i = 0; i < 8; i++)
+ pAd->StaCfg.RPIDensity[i] = 0;
+
+ Index = 0;
+
+ // 8. Save dialog token for report
+ pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token;
+
+ // Save Activation delay & measurement offset, Not really needed
+
+ // 9. Point to the first request element
+ pData += sizeof(AIRONET_RM_REQUEST_FRAME);
+ // Length should exclude the CISCO Aironet SNAP header
+ Length -= (sizeof(AIRONET_RM_REQUEST_FRAME) - LENGTH_802_1_H);
+
+ // 10. Start Parsing the Measurement elements.
+ // Be careful about multiple MR elements within one frames.
+ while (Length > 0)
+ {
+ pReqElem = (PRM_REQUEST_ACTION) pData;
+ switch (pReqElem->ReqElem.Eid)
+ {
+ case IE_MEASUREMENT_REQUEST:
+ // From the example, it seems we only need to support one request in one frame
+ // There is no multiple request in one frame.
+ // Besides, looks like we need to take care the measurement request only.
+ // The measurement request is always 4 bytes.
+
+ // Start parsing this type of request.
+ // 0. Eid is IE_MEASUREMENT_REQUEST
+ // 1. Length didn't include Eid and Length field, it always be 8.
+ // 2. Measurement Token, we nned to save it for the corresponding report.
+ // 3. Measurement Mode, Although there are definitions, but we din't see value other than
+ // 0 from test specs examples.
+ // 4. Measurement Type, this is what we need to do.
+ switch (pReqElem->ReqElem.Type)
+ {
+ case MSRN_TYPE_CHANNEL_LOAD_REQ:
+ case MSRN_TYPE_NOISE_HIST_REQ:
+ case MSRN_TYPE_BEACON_REQ:
+ // Check the Enable non-serving channel measurement control
+ if (pAd->StaCfg.CCXControl.field.DCRMEnable == 0)
+ {
+ // Check channel before enqueue the action
+ if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
+ break;
+ }
+ else
+ {
+ // If off channel measurement, check the TU duration limit
+ if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
+ if (pReqElem->Measurement.Duration > pAd->StaCfg.CCXControl.field.TuLimit)
+ break;
+ }
+
+ // Save requests and execute actions later
+ NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION));
+ Index += 1;
+ break;
+
+ case MSRN_TYPE_FRAME_REQ:
+ // Since it's option, we will support later
+ // FrameRequestAction(pAd, pData);
+ break;
+
+ default:
+ break;
+ }
+
+ // Point to next Measurement request
+ pData += sizeof(RM_REQUEST_ACTION);
+ Length -= sizeof(RM_REQUEST_ACTION);
+ break;
+
+ // We accept request only, all others are dropped
+ case IE_MEASUREMENT_REPORT:
+ case IE_AP_TX_POWER:
+ case IE_MEASUREMENT_CAPABILITY:
+ default:
+ return;
+ }
+ }
+
+ // 11. Update some flags and index
+ pAd->StaCfg.RMReqCnt = Index;
+
+ if (Index)
+ {
+ MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID AironetRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PRM_REQUEST_ACTION pReq;
+
+ // 1. Point to next request element
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+ // 2. Parse measurement type and call appropriate functions
+ if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
+ // Channel Load measurement request
+ ChannelLoadRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+ else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
+ // Noise Histogram measurement request
+ NoiseHistRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+ else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
+ // Beacon measurement request
+ BeaconRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+ else
+ // Unknown. Do nothing and return, this should never happen
+ return;
+
+ // 3. Peek into the next request, if it's parallel, we will update the scan time to the largest one
+ if ((pAd->StaCfg.CurrentRMReqIdx + 1) < pAd->StaCfg.RMReqCnt)
+ {
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx + 1];
+ // Check for parallel bit
+ if ((pReq->ReqElem.Mode & 0x01) && (pReq->Measurement.Channel == pAd->StaCfg.CCXScanChannel))
+ {
+ // Update parallel mode request information
+ pAd->StaCfg.ParallelReq = TRUE;
+ pAd->StaCfg.CCXScanTime = ((pReq->Measurement.Duration > pAd->StaCfg.CCXScanTime) ?
+ (pReq->Measurement.Duration) : (pAd->StaCfg.CCXScanTime));
+ }
+ }
+
+ // 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used
+ RT28XX_MLME_HANDLER(pAd);
+
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Prepare channel load report action, special scan operation added
+ to support
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Start from element ID
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID ChannelLoadRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index)
+{
+ PRM_REQUEST_ACTION pReq;
+ MLME_SCAN_REQ_STRUCT ScanReq;
+ UCHAR ZeroSsid[32];
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ PHEADER_802_11 pNullFrame;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n"));
+
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
+ NdisZeroMemory(ZeroSsid, 32);
+
+ // Prepare for special scan request
+ // The scan definition is different with our Active, Passive scan definition.
+ // For CCX2, Active means send out probe request with broadcast BSSID.
+ // Passive means no probe request sent, only listen to the beacons.
+ // The channel scanned is fixed as specified, no need to scan all channels.
+ // The scan wait time is specified in the request too.
+ // Passive scan Mode
+
+ // Control state machine is not idle, reject the request
+ if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
+ return;
+
+ // Fill out stuff for scan request
+ ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_CHANNEL_LOAD);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+ // Reset some internal control flags to make sure this scan works.
+ BssTableInit(&pAd->StaCfg.CCXBssTab);
+ pAd->StaCfg.ScanCnt = 0;
+ pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+ pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
+
+ // If it's non serving channel scan, send out a null frame with PSM bit on.
+ if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+ {
+ // Use MLME enqueue method
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ pNullFrame = (PHEADER_802_11) pOutBuffer;;
+ // Make the power save Null frame with PSM bit on
+ MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+ pNullFrame->Duration = 0;
+ pNullFrame->FC.Type = BTYPE_DATA;
+ pNullFrame->FC.PwrMgmt = PWR_SAVE;
+
+ // Send using priority queue
+ MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+ RTMPusecDelay(5000);
+ }
+
+ pAd->StaCfg.CCXReqType = MSRN_TYPE_CHANNEL_LOAD_REQ;
+ pAd->StaCfg.CLBusyBytes = 0;
+ // Enable Rx with promiscuous reception
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
+
+ // Set channel load measurement flag
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Prepare noise histogram report action, special scan operation added
+ to support
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Start from element ID
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID NoiseHistRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index)
+{
+ PRM_REQUEST_ACTION pReq;
+ MLME_SCAN_REQ_STRUCT ScanReq;
+ UCHAR ZeroSsid[32], i;
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ PHEADER_802_11 pNullFrame;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n"));
+
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
+ NdisZeroMemory(ZeroSsid, 32);
+
+ // Prepare for special scan request
+ // The scan definition is different with our Active, Passive scan definition.
+ // For CCX2, Active means send out probe request with broadcast BSSID.
+ // Passive means no probe request sent, only listen to the beacons.
+ // The channel scanned is fixed as specified, no need to scan all channels.
+ // The scan wait time is specified in the request too.
+ // Passive scan Mode
+
+ // Control state machine is not idle, reject the request
+ if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
+ return;
+
+ // Fill out stuff for scan request
+ ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+ // Reset some internal control flags to make sure this scan works.
+ BssTableInit(&pAd->StaCfg.CCXBssTab);
+ pAd->StaCfg.ScanCnt = 0;
+ pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+ pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
+ pAd->StaCfg.CCXReqType = MSRN_TYPE_NOISE_HIST_REQ;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
+
+ // If it's non serving channel scan, send out a null frame with PSM bit on.
+ if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+ {
+ // Use MLME enqueue method
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ pNullFrame = (PHEADER_802_11) pOutBuffer;
+ // Make the power save Null frame with PSM bit on
+ MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+ pNullFrame->Duration = 0;
+ pNullFrame->FC.Type = BTYPE_DATA;
+ pNullFrame->FC.PwrMgmt = PWR_SAVE;
+
+ // Send using priority queue
+ MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+ RTMPusecDelay(5000);
+ }
+
+ // Reset the statistics
+ for (i = 0; i < 8; i++)
+ pAd->StaCfg.RPIDensity[i] = 0;
+
+ // Enable Rx with promiscuous reception
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
+
+ // Set channel load measurement flag
+ RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Prepare Beacon report action, special scan operation added
+ to support
+
+ Arguments:
+ pAd Pointer to our adapter
+ pData Start from element ID
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID BeaconRequestAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index)
+{
+ PRM_REQUEST_ACTION pReq;
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ PHEADER_802_11 pNullFrame;
+ MLME_SCAN_REQ_STRUCT ScanReq;
+ UCHAR ZeroSsid[32];
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n"));
+
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
+ NdisZeroMemory(ZeroSsid, 32);
+
+ // Prepare for special scan request
+ // The scan definition is different with our Active, Passive scan definition.
+ // For CCX2, Active means send out probe request with broadcast BSSID.
+ // Passive means no probe request sent, only listen to the beacons.
+ // The channel scanned is fixed as specified, no need to scan all channels.
+ // The scan wait time is specified in the request too.
+ if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE)
+ {
+ // Passive scan Mode
+ DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n"));
+
+ // Control state machine is not idle, reject the request
+ if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
+ return;
+
+ // Fill out stuff for scan request
+ ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+ // Reset some internal control flags to make sure this scan works.
+ BssTableInit(&pAd->StaCfg.CCXBssTab);
+ pAd->StaCfg.ScanCnt = 0;
+ pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+ pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
+ pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ;
+ DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
+
+ // If it's non serving channel scan, send out a null frame with PSM bit on.
+ if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+ {
+ // Use MLME enqueue method
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ pNullFrame = (PHEADER_802_11) pOutBuffer;
+ // Make the power save Null frame with PSM bit on
+ MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+ pNullFrame->Duration = 0;
+ pNullFrame->FC.Type = BTYPE_DATA;
+ pNullFrame->FC.PwrMgmt = PWR_SAVE;
+
+ // Send using priority queue
+ MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+ RTMPusecDelay(5000);
+ }
+
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+ }
+ else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE)
+ {
+ // Active scan Mode
+ DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n"));
+
+ // Control state machine is not idle, reject the request
+ if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
+ return;
+
+ // Fill out stuff for scan request
+ ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+
+ // Reset some internal control flags to make sure this scan works.
+ BssTableInit(&pAd->StaCfg.CCXBssTab);
+ pAd->StaCfg.ScanCnt = 0;
+ pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
+ pAd->StaCfg.CCXScanTime = pReq->Measurement.Duration;
+ pAd->StaCfg.CCXReqType = MSRN_TYPE_BEACON_REQ;
+ DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
+
+ // If it's non serving channel scan, send out a null frame with PSM bit on.
+ if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
+ {
+ // Use MLME enqueue method
+ NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ pNullFrame = (PHEADER_802_11) pOutBuffer;
+ // Make the power save Null frame with PSM bit on
+ MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
+ pNullFrame->Duration = 0;
+ pNullFrame->FC.Type = BTYPE_DATA;
+ pNullFrame->FC.PwrMgmt = PWR_SAVE;
+
+ // Send using priority queue
+ MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
+ MlmeFreeMemory(pAd, pOutBuffer);
+ DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
+ RTMPusecDelay(5000);
+ }
+
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+ }
+ else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE)
+ {
+ // Beacon report Mode, report all the APS in current bss table
+ DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n"));
+
+ // Copy current BSS table to CCX table, we can omit this step later on.
+ NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE));
+
+ // Create beacon report from Bss table
+ AironetCreateBeaconReportFromBssTable(pAd);
+
+ // Set state to scanning
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
+
+ // Enqueue report request
+ // Cisco scan request is finished, prepare beacon report
+ MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
+ }
+ else
+ {
+ // Wrong scan Mode
+ DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n"));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID AironetReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PRM_REQUEST_ACTION pReq;
+ ULONG Now32;
+
+ NdisGetSystemUpTime(&Now32);
+ pAd->StaCfg.LastBeaconRxTime = Now32;
+
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n"));
+
+ // 1. Parse measurement type and call appropriate functions
+ if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
+ // Channel Load measurement request
+ ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+ else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
+ // Noise Histogram measurement request
+ NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+ else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
+ // Beacon measurement request
+ BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+ else
+ // Unknown. Do nothing and return
+ ;
+
+ // 2. Point to the correct index of action element, start from 0
+ pAd->StaCfg.CurrentRMReqIdx++;
+
+ // 3. Check for parallel actions
+ if (pAd->StaCfg.ParallelReq == TRUE)
+ {
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+ // Process next action right away
+ if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
+ // Channel Load measurement request
+ ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+ else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
+ // Noise Histogram measurement request
+ NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
+
+ pAd->StaCfg.ParallelReq = FALSE;
+ pAd->StaCfg.CurrentRMReqIdx++;
+ }
+
+ if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt)
+ {
+ // 4. There is no more unprocessed measurement request, go for transmit this report
+ AironetFinalReportAction(pAd);
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+ }
+ else
+ {
+ pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
+
+ if (pReq->Measurement.Channel != pAd->CommonCfg.Channel)
+ {
+ RTMPusecDelay(100000);
+ }
+
+ // 5. There are more requests to be measure
+ MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID AironetFinalReportAction(
+ IN PRTMP_ADAPTER pAd)
+{
+ PUCHAR pDest;
+ PAIRONET_IAPP_HEADER pIAPP;
+ PHEADER_802_11 pHeader;
+ UCHAR AckRate = RATE_2;
+ USHORT AckDuration = 0;
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n"));
+
+ // 0. Set up the frame pointer, Frame was inited at the end of message action
+ pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11];
+
+ // 1. Update report IAPP fields
+ pIAPP = (PAIRONET_IAPP_HEADER) pDest;
+
+ // 2. Copy Cisco SNAP header
+ NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H);
+
+ // 3. network order for this 16bit length
+ pIAPP->Length = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H);
+
+ // 3.1 sanity check the report length, ignore it if there is nothing to report
+ if (be2cpu16(pIAPP->Length) <= 18)
+ return;
+
+ // 4. Type must be 0x32
+ pIAPP->Type = AIRONET_IAPP_TYPE;
+
+ // 5. SubType for report must be 0x81
+ pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT;
+
+ // 6. DA is not used and must be zero, although the whole frame was cleared at the start of function
+ // We will do it again here. We can use BSSID instead
+ COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid);
+
+ // 7. SA is the client reporting which must be our MAC
+ COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress);
+
+ // 8. Copy the saved dialog token
+ pIAPP->Token = pAd->StaCfg.IAPPToken;
+
+ // 9. Make the Report frame 802.11 header
+ // Reuse function in wpa.c
+ pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf;
+ pAd->Sequence ++;
+ WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid);
+
+ // ACK size is 14 include CRC, and its rate is based on real time information
+ AckRate = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate];
+ AckDuration = RTMPCalcDuration(pAd, AckRate, 14);
+ pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration;
+
+ // Use MLME enqueue method
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ // 10. Prepare report frame with dynamic outbuffer. Just simply copy everything.
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf,
+ END_OF_ARGS);
+
+ // 11. Send using priority queue
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID ChannelLoadReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index)
+{
+ PMEASUREMENT_REPORT_ELEMENT pReport;
+ PCHANNEL_LOAD_REPORT pLoad;
+ PUCHAR pDest;
+ UCHAR CCABusyFraction;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n"));
+
+ // Disable Rx with promiscuous reception, make it back to normal
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
+
+ // 0. Setup pointer for processing beacon & probe response
+ pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+ pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+
+ // 1. Fill Measurement report element field.
+ pReport->Eid = IE_MEASUREMENT_REPORT;
+ // Fixed Length at 9, not include Eid and length fields
+ pReport->Length = 9;
+ pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
+ pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
+ pReport->Type = MSRN_TYPE_CHANNEL_LOAD_REQ;
+
+ // 2. Fill channel report measurement data
+ pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+ pLoad = (PCHANNEL_LOAD_REPORT) pDest;
+ pLoad->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
+ pLoad->Spare = 0;
+ pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
+
+ // 3. Calculate the CCA Busy Fraction
+ // (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed
+ // = (Bytes + ACK) / 12 / duration
+ // 9 is the good value for pAd->StaCfg.CLFactor
+ // CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration);
+ CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration);
+ if (CCABusyFraction < 10)
+ CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 3 / pLoad->Duration) + 1;
+
+ pLoad->CCABusy = CCABusyFraction;
+ DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
+ pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(CHANNEL_LOAD_REPORT));
+ DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
+
+ // 4. Clear channel load measurement flag
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+ // 5. reset to idle state
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID NoiseHistReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index)
+{
+ PMEASUREMENT_REPORT_ELEMENT pReport;
+ PNOISE_HIST_REPORT pNoise;
+ PUCHAR pDest;
+ UCHAR i,NoiseCnt;
+ USHORT TotalRPICnt, TotalRPISum;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n"));
+
+ // 0. Disable Rx with promiscuous reception, make it back to normal
+ RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
+ // 1. Setup pointer for processing beacon & probe response
+ pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+ pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+
+ // 2. Fill Measurement report element field.
+ pReport->Eid = IE_MEASUREMENT_REPORT;
+ // Fixed Length at 16, not include Eid and length fields
+ pReport->Length = 16;
+ pReport->Token = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
+ pReport->Mode = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
+ pReport->Type = MSRN_TYPE_NOISE_HIST_REQ;
+
+ // 3. Fill noise histogram report measurement data
+ pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+ pNoise = (PNOISE_HIST_REPORT) pDest;
+ pNoise->Channel = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
+ pNoise->Spare = 0;
+ pNoise->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
+ // 4. Fill Noise histogram, the total RPI counts should be 0.4 * TU
+ // We estimate 4000 normal packets received durning 10 seconds test.
+ // Adjust it if required.
+ // 3 is a good value for pAd->StaCfg.NHFactor
+ // TotalRPICnt = pNoise->Duration * 3 / 10;
+ TotalRPICnt = pNoise->Duration * pAd->StaCfg.NHFactor / 10;
+ TotalRPISum = 0;
+
+ for (i = 0; i < 8; i++)
+ {
+ TotalRPISum += pAd->StaCfg.RPIDensity[i];
+ DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i]));
+ }
+
+ // Double check if the counter is larger than our expectation.
+ // We will replace it with the total number plus a fraction.
+ if (TotalRPISum > TotalRPICnt)
+ TotalRPICnt = TotalRPISum + pNoise->Duration / 20;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt));
+
+ // 5. Initialize noise count for the total summation of 0xff
+ NoiseCnt = 0;
+ for (i = 1; i < 8; i++)
+ {
+ pNoise->Density[i] = (UCHAR) (pAd->StaCfg.RPIDensity[i] * 255 / TotalRPICnt);
+ if ((pNoise->Density[i] == 0) && (pAd->StaCfg.RPIDensity[i] != 0))
+ pNoise->Density[i]++;
+ NoiseCnt += pNoise->Density[i];
+ DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[%d] = 0x%02x\n", i, pNoise->Density[i]));
+ }
+
+ // 6. RPI[0] represents the rest of counts
+ pNoise->Density[0] = 0xff - NoiseCnt;
+ DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[0] = 0x%02x\n", pNoise->Density[0]));
+
+ pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT));
+
+ // 7. Clear channel load measurement flag
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
+
+ // 8. reset to idle state
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Prepare Beacon report action,
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ Note:
+
+ ========================================================================
+*/
+VOID BeaconReportAction(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR Index)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n"));
+
+ // Looks like we don't have anything thing need to do here.
+ // All measurement report already finished in AddBeaconReport
+ // The length is in the FrameReportLen
+
+ // reset Beacon index for next beacon request
+ pAd->StaCfg.LastBssIndex = 0xff;
+
+ // reset to idle state
+ pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n"));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+ Index Current BSSID in CCXBsstab entry index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID AironetAddBeaconReport(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Index,
+ IN PMLME_QUEUE_ELEM pElem)
+{
+ PVOID pMsg;
+ PUCHAR pSrc, pDest;
+ UCHAR ReqIdx;
+ ULONG MsgLen;
+ USHORT Length;
+ PFRAME_802_11 pFrame;
+ PMEASUREMENT_REPORT_ELEMENT pReport;
+ PEID_STRUCT pEid;
+ PBEACON_REPORT pBeaconReport;
+ PBSS_ENTRY pBss;
+
+ // 0. Setup pointer for processing beacon & probe response
+ pMsg = pElem->Msg;
+ MsgLen = pElem->MsgLen;
+ pFrame = (PFRAME_802_11) pMsg;
+ pSrc = pFrame->Octet; // Start from AP TSF
+ pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
+ ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
+
+ // 1 Check the Index, if we already create this entry, only update the average RSSI
+ if ((Index <= pAd->StaCfg.LastBssIndex) && (pAd->StaCfg.LastBssIndex != 0xff))
+ {
+ pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.BssReportOffset[Index]];
+ // Point to bss report information
+ pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+ pBeaconReport = (PBEACON_REPORT) pDest;
+
+ // Update Rx power, in dBm
+ // Get the original RSSI readback from BBP
+ pBeaconReport->RxPower += pAd->BbpRssiToDbmDelta;
+ // Average the Rssi reading
+ pBeaconReport->RxPower = (pBeaconReport->RxPower + pBss->Rssi) / 2;
+ // Get to dBm format
+ pBeaconReport->RxPower -= pAd->BbpRssiToDbmDelta;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
+ pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
+ pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
+ DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld] Rssi %d, Avg Rssi %d\n", Index, (pBss->Rssi - pAd->BbpRssiToDbmDelta), pBeaconReport->RxPower - 256));
+ DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.BssReportOffset[Index]));
+
+ // Update other information here
+
+ // Done
+ return;
+ }
+
+ // 2. Update reported Index
+ pAd->StaCfg.LastBssIndex = Index;
+
+ // 3. Setup the buffer address for copying this BSSID into reporting frame
+ // The offset should start after 802.11 header and report frame header.
+ pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+
+ // 4. Save the start offset of each Bss in report frame
+ pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen;
+
+ // 5. Fill Measurement report fields
+ pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+ pReport->Eid = IE_MEASUREMENT_REPORT;
+ pReport->Length = 0;
+ pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
+ pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
+ pReport->Type = MSRN_TYPE_BEACON_REQ;
+ Length = sizeof(MEASUREMENT_REPORT_ELEMENT);
+ pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+
+ // 6. Start thebeacon report format
+ pBeaconReport = (PBEACON_REPORT) pDest;
+ pDest += sizeof(BEACON_REPORT);
+ Length += sizeof(BEACON_REPORT);
+
+ // 7. Copy Channel number
+ pBeaconReport->Channel = pBss->Channel;
+ pBeaconReport->Spare = 0;
+ pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
+ pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
+ // 8. Rx power, in dBm
+ pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
+ pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
+ pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
+ DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld], Rssi %d\n", Index, pBeaconReport->RxPower - 256));
+ DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.FrameReportLen));
+
+ pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
+ COPY_MAC_ADDR(pBeaconReport->BSSID, pFrame->Hdr.Addr3);
+ NdisMoveMemory(pBeaconReport->ParentTSF, pSrc, 4);
+ NdisMoveMemory(pBeaconReport->TargetTSF, &pElem->TimeStamp.u.LowPart, 4);
+ NdisMoveMemory(&pBeaconReport->TargetTSF[4], &pElem->TimeStamp.u.HighPart, 4);
+
+ // 9. Skip the beacon frame and offset to start of capabilityinfo since we already processed capabilityinfo
+ pSrc += (TIMESTAMP_LEN + 2);
+ pBeaconReport->CapabilityInfo = *(USHORT *)pSrc;
+
+ // 10. Point to start of element ID
+ pSrc += 2;
+ pEid = (PEID_STRUCT) pSrc;
+
+ // 11. Start process all variable Eid oayload and add the appropriate to the frame report
+ while (((PUCHAR) pEid + pEid->Len + 1) < ((PUCHAR) pFrame + MsgLen))
+ {
+ // Only limited EID are required to report for CCX 2. It includes SSID, Supported rate,
+ // FH paramenter set, DS parameter set, CF parameter set, IBSS parameter set,
+ // TIM (report first 4 bytes only, radio measurement capability
+ switch (pEid->Eid)
+ {
+ case IE_SSID:
+ case IE_SUPP_RATES:
+ case IE_FH_PARM:
+ case IE_DS_PARM:
+ case IE_CF_PARM:
+ case IE_IBSS_PARM:
+ NdisMoveMemory(pDest, pEid, pEid->Len + 2);
+ pDest += (pEid->Len + 2);
+ Length += (pEid->Len + 2);
+ break;
+
+ case IE_MEASUREMENT_CAPABILITY:
+ // Since this IE is duplicated with WPA security IE, we has to do sanity check before
+ // recognize it.
+ // 1. It also has fixed 6 bytes IE length.
+ if (pEid->Len != 6)
+ break;
+ // 2. Check the Cisco Aironet OUI
+ if (NdisEqualMemory(CISCO_OUI, (pSrc + 2), 3))
+ {
+ // Matched, this is what we want
+ NdisMoveMemory(pDest, pEid, pEid->Len + 2);
+ pDest += (pEid->Len + 2);
+ Length += (pEid->Len + 2);
+ }
+ break;
+
+ case IE_TIM:
+ if (pEid->Len > 4)
+ {
+ // May truncate and report the first 4 bytes only, with the eid & len, total should be 6
+ NdisMoveMemory(pDest, pEid, 6);
+ pDest += 6;
+ Length += 6;
+ }
+ else
+ {
+ NdisMoveMemory(pDest, pEid, pEid->Len + 2);
+ pDest += (pEid->Len + 2);
+ Length += (pEid->Len + 2);
+ }
+ break;
+
+ default:
+ break;
+ }
+ // 12. Move to next element ID
+ pSrc += (2 + pEid->Len);
+ pEid = (PEID_STRUCT) pSrc;
+ }
+
+ // 13. Update the length in the header, not include EID and length
+ pReport->Length = Length - 4;
+
+ // 14. Update the frame report buffer data length
+ pAd->StaCfg.FrameReportLen += Length;
+ DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+
+ Arguments:
+ Index Current BSSID in CCXBsstab entry index
+
+ Return Value:
+
+ Note:
+
+ ========================================================================
+*/
+VOID AironetCreateBeaconReportFromBssTable(
+ IN PRTMP_ADAPTER pAd)
+{
+ PMEASUREMENT_REPORT_ELEMENT pReport;
+ PBEACON_REPORT pBeaconReport;
+ UCHAR Index, ReqIdx;
+ USHORT Length;
+ PUCHAR pDest;
+ PBSS_ENTRY pBss;
+
+ // 0. setup base pointer
+ ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
+
+ for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++)
+ {
+ // 1. Setup the buffer address for copying this BSSID into reporting frame
+ // The offset should start after 802.11 header and report frame header.
+ pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
+ pBss = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
+ Length = 0;
+
+ // 2. Fill Measurement report fields
+ pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
+ pReport->Eid = IE_MEASUREMENT_REPORT;
+ pReport->Length = 0;
+ pReport->Token = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
+ pReport->Mode = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
+ pReport->Type = MSRN_TYPE_BEACON_REQ;
+ Length = sizeof(MEASUREMENT_REPORT_ELEMENT);
+ pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
+
+ // 3. Start the beacon report format
+ pBeaconReport = (PBEACON_REPORT) pDest;
+ pDest += sizeof(BEACON_REPORT);
+ Length += sizeof(BEACON_REPORT);
+
+ // 4. Copy Channel number
+ pBeaconReport->Channel = pBss->Channel;
+ pBeaconReport->Spare = 0;
+ pBeaconReport->Duration = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
+ pBeaconReport->PhyType = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
+ pBeaconReport->RxPower = pBss->Rssi - pAd->BbpRssiToDbmDelta;
+ pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
+ pBeaconReport->CapabilityInfo = pBss->CapabilityInfo;
+ COPY_MAC_ADDR(pBeaconReport->BSSID, pBss->Bssid);
+ NdisMoveMemory(pBeaconReport->ParentTSF, pBss->PTSF, 4);
+ NdisMoveMemory(pBeaconReport->TargetTSF, pBss->TTSF, 8);
+
+ // 5. Create SSID
+ *pDest++ = 0x00;
+ *pDest++ = pBss->SsidLen;
+ NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen);
+ pDest += pBss->SsidLen;
+ Length += (2 + pBss->SsidLen);
+
+ // 6. Create SupportRates
+ *pDest++ = 0x01;
+ *pDest++ = pBss->SupRateLen;
+ NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen);
+ pDest += pBss->SupRateLen;
+ Length += (2 + pBss->SupRateLen);
+
+ // 7. DS Parameter
+ *pDest++ = 0x03;
+ *pDest++ = 1;
+ *pDest++ = pBss->Channel;
+ Length += 3;
+
+ // 8. IBSS parameter if presents
+ if (pBss->BssType == BSS_ADHOC)
+ {
+ *pDest++ = 0x06;
+ *pDest++ = 2;
+ *(PUSHORT) pDest = pBss->AtimWin;
+ pDest += 2;
+ Length += 4;
+ }
+
+ // 9. Update length field, not include EID and length
+ pReport->Length = Length - 4;
+
+ // 10. Update total frame size
+ pAd->StaCfg.FrameReportLen += Length;
+ }
+}
diff --git a/drivers/staging/rt2860/sta/assoc.c b/drivers/staging/rt2860/sta/assoc.c
new file mode 100644
index 000000000000..42db753eed70
--- /dev/null
+++ b/drivers/staging/rt2860/sta/assoc.c
@@ -0,0 +1,1826 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ assoc.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John 2004-9-3 porting from RT2500
+*/
+#include "../rt_config.h"
+
+UCHAR CipherWpaTemplate[] = {
+ 0xdd, // WPA IE
+ 0x16, // Length
+ 0x00, 0x50, 0xf2, 0x01, // oui
+ 0x01, 0x00, // Version
+ 0x00, 0x50, 0xf2, 0x02, // Multicast
+ 0x01, 0x00, // Number of unicast
+ 0x00, 0x50, 0xf2, 0x02, // unicast
+ 0x01, 0x00, // number of authentication method
+ 0x00, 0x50, 0xf2, 0x01 // authentication
+ };
+
+UCHAR CipherWpa2Template[] = {
+ 0x30, // RSN IE
+ 0x14, // Length
+ 0x01, 0x00, // Version
+ 0x00, 0x0f, 0xac, 0x02, // group cipher, TKIP
+ 0x01, 0x00, // number of pairwise
+ 0x00, 0x0f, 0xac, 0x02, // unicast
+ 0x01, 0x00, // number of authentication method
+ 0x00, 0x0f, 0xac, 0x02, // authentication
+ 0x00, 0x00, // RSN capability
+ };
+
+UCHAR Ccx2IeInfo[] = { 0x00, 0x40, 0x96, 0x03, 0x02};
+
+/*
+ ==========================================================================
+ Description:
+ association state machine init, including state transition and timer init
+ Parameters:
+ S - pointer to the association state machine
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+VOID AssocStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(S, Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE);
+
+ // first column
+ StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)MlmeAssocReqAction);
+ StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)MlmeReassocReqAction);
+ StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction);
+ StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+
+ // second column
+ StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
+ StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
+ StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
+ StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+ StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
+ //
+ // Patch 3Com AP MOde:3CRWE454G72
+ // We send Assoc request frame to this AP, it always send Reassoc Rsp not Associate Rsp.
+ //
+ StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerAssocRspAction);
+ StateMachineSetAction(S, ASSOC_WAIT_RSP, MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)AssocTimeoutAction);
+
+ // third column
+ StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
+ StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
+ StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
+ StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+ StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_REASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
+ //
+ // Patch, AP doesn't send Reassociate Rsp frame to Station.
+ //
+ StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)PeerReassocRspAction);
+ StateMachineSetAction(S, REASSOC_WAIT_RSP, MT2_REASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ReassocTimeoutAction);
+
+ // fourth column
+ StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAssoc);
+ StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_REASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenReassoc);
+ StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenDisassociate);
+ StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocAction);
+ StateMachineSetAction(S, DISASSOC_WAIT_RSP, MT2_DISASSOC_TIMEOUT, (STATE_MACHINE_FUNC)DisassocTimeoutAction);
+
+ // initialize the timer
+ RTMPInitTimer(pAd, &pAd->MlmeAux.AssocTimer, GET_TIMER_FUNCTION(AssocTimeout), pAd, FALSE);
+ RTMPInitTimer(pAd, &pAd->MlmeAux.ReassocTimer, GET_TIMER_FUNCTION(ReassocTimeout), pAd, FALSE);
+ RTMPInitTimer(pAd, &pAd->MlmeAux.DisassocTimer, GET_TIMER_FUNCTION(DisassocTimeout), pAd, FALSE);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Association timeout procedure. After association timeout, this function
+ will be called and it will put a message into the MLME queue
+ Parameters:
+ Standard timer parameters
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AssocTimeout(IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_ASSOC_TIMEOUT, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Reassociation timeout procedure. After reassociation timeout, this
+ function will be called and put a message into the MLME queue
+ Parameters:
+ Standard timer parameters
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID ReassocTimeout(IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_REASSOC_TIMEOUT, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Disassociation timeout procedure. After disassociation timeout, this
+ function will be called and put a message into the MLME queue
+ Parameters:
+ Standard timer parameters
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID DisassocTimeout(IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_DISASSOC_TIMEOUT, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+}
+
+/*
+ ==========================================================================
+ Description:
+ mlme assoc req handling procedure
+ Parameters:
+ Adapter - Adapter pointer
+ Elem - MLME Queue Element
+ Pre:
+ the station has been authenticated and the following information is stored in the config
+ -# SSID
+ -# supported rates and their length
+ -# listen interval (Adapter->StaCfg.default_listen_count)
+ -# Transmit power (Adapter->StaCfg.tx_power)
+ Post :
+ -# An association request frame is generated and sent to the air
+ -# Association timer starts
+ -# Association state -> ASSOC_WAIT_RSP
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeAssocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR ApAddr[6];
+ HEADER_802_11 AssocHdr;
+ UCHAR Ccx2Len = 5;
+ UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
+ USHORT ListenIntv;
+ ULONG Timeout;
+ USHORT CapabilityInfo;
+ BOOLEAN TimerCancelled;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ ULONG tmp;
+ USHORT VarIesOffset;
+ UCHAR CkipFlag;
+ UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH];
+ UCHAR AironetCkipIe = IE_AIRONET_CKIP;
+ UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH;
+ UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS;
+ UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH;
+ UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00};
+ USHORT Status;
+
+ // Block all authentication request durning WPA block period
+ if (pAd->StaCfg.bBlockAssoc == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block Assoc request durning WPA block period!\n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+ }
+ // check sanity first
+ else if (MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
+ {
+ RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
+ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
+
+ // Get an unused nonpaged memory
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() allocate memory failed \n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+ return;
+ }
+
+ // Add by James 03/06/27
+ pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+ // Association don't need to report MAC address
+ pAd->StaCfg.AssocInfo.AvailableRequestFixedIEs =
+ NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_LISTENINTERVAL;
+ pAd->StaCfg.AssocInfo.RequestFixedIEs.Capabilities = CapabilityInfo;
+ pAd->StaCfg.AssocInfo.RequestFixedIEs.ListenInterval = ListenIntv;
+ // Only reassociate need this
+ //COPY_MAC_ADDR(pAd->StaCfg.AssocInfo.RequestFixedIEs.CurrentAPAddress, ApAddr);
+ pAd->StaCfg.AssocInfo.OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+
+ NdisZeroMemory(pAd->StaCfg.ReqVarIEs, MAX_VIE_LEN);
+ // First add SSID
+ VarIesOffset = 0;
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SsidIe, 1);
+ VarIesOffset += 1;
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SsidLen, 1);
+ VarIesOffset += 1;
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+ VarIesOffset += pAd->MlmeAux.SsidLen;
+
+ // Second add Supported rates
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &SupRateIe, 1);
+ VarIesOffset += 1;
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->MlmeAux.SupRateLen, 1);
+ VarIesOffset += 1;
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->MlmeAux.SupRate, pAd->MlmeAux.SupRateLen);
+ VarIesOffset += pAd->MlmeAux.SupRateLen;
+ // End Add by James
+
+ if ((pAd->CommonCfg.Channel > 14) &&
+ (pAd->CommonCfg.bIEEE80211H == TRUE))
+ CapabilityInfo |= 0x0100;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send ASSOC request...\n"));
+ MgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr);
+
+ // Build basic frame first
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &AssocHdr,
+ 2, &CapabilityInfo,
+ 2, &ListenIntv,
+ 1, &SsidIe,
+ 1, &pAd->MlmeAux.SsidLen,
+ pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
+ 1, &SupRateIe,
+ 1, &pAd->MlmeAux.SupRateLen,
+ pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
+ END_OF_ARGS);
+
+ if (pAd->MlmeAux.ExtRateLen != 0)
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &ExtRateIe,
+ 1, &pAd->MlmeAux.ExtRateLen,
+ pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ // HT
+ if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ ULONG TmpLen;
+ UCHAR HtLen;
+ UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+ if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
+ {
+ HtLen = SIZE_HT_CAP_IE + 4;
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
+ 1, &WpaIe,
+ 1, &HtLen,
+ 4, &BROADCOM[0],
+ pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
+ END_OF_ARGS);
+ }
+ else
+ {
+#ifdef RT_BIG_ENDIAN
+ HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+
+#ifndef RT_BIG_ENDIAN
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
+ 1, &HtCapIe,
+ 1, &pAd->MlmeAux.HtCapabilityLen,
+ pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
+ END_OF_ARGS);
+#else
+ NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE));
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->MlmeAux.HtCapability, pAd->MlmeAux.HtCapabilityLen);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
+ 1, &HtCapIe,
+ 1, &pAd->MlmeAux.HtCapabilityLen,
+ pAd->MlmeAux.HtCapabilityLen,&HtCapabilityTmp,
+ END_OF_ARGS);
+#endif
+ }
+ FrameLen += TmpLen;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
+ // Case I: (Aggregation + Piggy-Back)
+ // 1. user enable aggregation, AND
+ // 2. Mac support piggy-back
+ // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
+ // Case II: (Aggregation)
+ // 1. user enable aggregation, AND
+ // 2. AP annouces it's AGGREGATION-capable in BEACON
+ if (pAd->CommonCfg.bAggregationCapable)
+ {
+ if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
+ {
+ ULONG TmpLen;
+ UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
+ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
+ 9, RalinkIe,
+ END_OF_ARGS);
+ FrameLen += TmpLen;
+ }
+ else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
+ {
+ ULONG TmpLen;
+ UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
+ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
+ 9, RalinkIe,
+ END_OF_ARGS);
+ FrameLen += TmpLen;
+ }
+ }
+ else
+ {
+ ULONG TmpLen;
+ UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00};
+ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
+ 9, RalinkIe,
+ END_OF_ARGS);
+ FrameLen += TmpLen;
+ }
+
+ if (pAd->MlmeAux.APEdcaParm.bValid)
+ {
+ if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
+ {
+ QBSS_STA_INFO_PARM QosInfo;
+
+ NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
+ QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
+ QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
+ QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
+ QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
+ QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
+ WmeIe[8] |= *(PUCHAR)&QosInfo;
+ }
+ else
+ {
+ // The Parameter Set Count is set to 0 in the association request frames
+ // WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f);
+ }
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 9, &WmeIe[0],
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+ //
+ // Let WPA(#221) Element ID on the end of this association frame.
+ // Otherwise some AP will fail on parsing Element ID and set status fail on Assoc Rsp.
+ // For example: Put Vendor Specific IE on the front of WPA IE.
+ // This happens on AP (Model No:Linksys WRK54G)
+ //
+ if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
+ )
+ )
+ {
+ UCHAR RSNIe = IE_WPA;
+
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2))
+ {
+ RSNIe = IE_WPA2;
+ }
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifdef SIOCSIWGENIE
+ if (pAd->StaCfg.WpaSupplicantUP != 1)
+#endif // SIOCSIWGENIE //
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+ RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0);
+
+ // Check for WPA PMK cache list
+ if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2)
+ {
+ INT idx;
+ BOOLEAN FoundPMK = FALSE;
+ // Search chched PMKID, append it if existed
+ for (idx = 0; idx < PMKID_NO; idx++)
+ {
+ if (NdisEqualMemory(ApAddr, &pAd->StaCfg.SavedPMK[idx].BSSID, 6))
+ {
+ FoundPMK = TRUE;
+ break;
+ }
+ }
+
+ if (FoundPMK)
+ {
+ // Set PMK number
+ *(PUSHORT) &pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len] = 1;
+ NdisMoveMemory(&pAd->StaCfg.RSN_IE[pAd->StaCfg.RSNIE_Len + 2], &pAd->StaCfg.SavedPMK[idx].PMKID, 16);
+ pAd->StaCfg.RSNIE_Len += 18;
+ }
+ }
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifdef SIOCSIWGENIE
+ if (pAd->StaCfg.WpaSupplicantUP == 1)
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
+ END_OF_ARGS);
+ }
+ else
+#endif
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &RSNIe,
+ 1, &pAd->StaCfg.RSNIE_Len,
+ pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
+ END_OF_ARGS);
+ }
+
+ FrameLen += tmp;
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+#ifdef SIOCSIWGENIE
+ if (pAd->StaCfg.WpaSupplicantUP != 1)
+#endif
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+ {
+ // Append Variable IE
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &RSNIe, 1);
+ VarIesOffset += 1;
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, &pAd->StaCfg.RSNIE_Len, 1);
+ VarIesOffset += 1;
+ }
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
+ VarIesOffset += pAd->StaCfg.RSNIE_Len;
+
+ // Set Variable IEs Length
+ pAd->StaCfg.ReqVarIELen = VarIesOffset;
+ }
+
+ // We have update that at PeerBeaconAtJoinRequest()
+ CkipFlag = pAd->StaCfg.CkipFlag;
+ if (CkipFlag != 0)
+ {
+ NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH);
+ CkipNegotiationBuffer[2] = 0x66;
+ // Make it try KP & MIC, since we have to follow the result from AssocRsp
+ CkipNegotiationBuffer[8] = 0x18;
+ CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22;
+ CkipFlag = 0x18;
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &AironetCkipIe,
+ 1, &AironetCkipLen,
+ AironetCkipLen, CkipNegotiationBuffer,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+ // Add CCX v2 request if CCX2 admin state is on
+ if (pAd->StaCfg.CCXControl.field.Enable == 1)
+ {
+
+ //
+ // Add AironetIPAddressIE for Cisco CCX 2.X
+ // Add CCX Version
+ //
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &AironetIPAddressIE,
+ 1, &AironetIPAddressLen,
+ AironetIPAddressLen, AironetIPAddressBuffer,
+ 1, &Ccx2Ie,
+ 1, &Ccx2Len,
+ Ccx2Len, Ccx2IeInfo,
+ END_OF_ARGS);
+ FrameLen += tmp;
+
+ //
+ // Add CipherSuite CCKM or LeapTkip if setting.
+ //
+#ifdef LEAP_SUPPORT
+ if (LEAP_CCKM_ON(pAd))
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ CipherSuiteCiscoCCKMLen, CipherSuiteCiscoCCKM,
+ END_OF_ARGS);
+ FrameLen += tmp;
+
+ // Third add RSN
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen); //Save CipherSuite
+ VarIesOffset += CipherSuiteCiscoCCKMLen;
+ }
+ else if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled))
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ CipherSuiteCCXTkipLen, CipherSuiteCCXTkip,
+ END_OF_ARGS);
+ FrameLen += tmp;
+
+ // Third add RSN
+ NdisMoveMemory(pAd->StaCfg.ReqVarIEs + VarIesOffset, CipherSuiteCCXTkip, CipherSuiteCCXTkipLen);
+ VarIesOffset += CipherSuiteCCXTkipLen;
+ }
+#endif // LEAP_SUPPORT //
+
+ // Add by James 03/06/27
+ // Set Variable IEs Length
+ pAd->StaCfg.ReqVarIELen = VarIesOffset;
+ pAd->StaCfg.AssocInfo.RequestIELength = VarIesOffset;
+
+ // OffsetResponseIEs follow ReqVarIE
+ pAd->StaCfg.AssocInfo.OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAd->StaCfg.ReqVarIELen;
+ // End Add by James
+ }
+
+
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ RTMPSetTimer(&pAd->MlmeAux.AssocTimer, Timeout);
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_WAIT_RSP;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeAssocReqAction() sanity check failed. BUG!!!!!! \n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_INVALID_FORMAT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+ }
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ mlme reassoc req handling procedure
+ Parameters:
+ Elem -
+ Pre:
+ -# SSID (Adapter->StaCfg.ssid[])
+ -# BSSID (AP address, Adapter->StaCfg.bssid)
+ -# Supported rates (Adapter->StaCfg.supported_rates[])
+ -# Supported rates length (Adapter->StaCfg.supported_rates_len)
+ -# Tx power (Adapter->StaCfg.tx_power)
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeReassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR ApAddr[6];
+ HEADER_802_11 ReassocHdr;
+ UCHAR Ccx2Len = 5;
+ UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
+ USHORT CapabilityInfo, ListenIntv;
+ ULONG Timeout;
+ ULONG FrameLen = 0;
+ BOOLEAN TimerCancelled;
+ NDIS_STATUS NStatus;
+ ULONG tmp;
+ PUCHAR pOutBuffer = NULL;
+//CCX 2.X
+#ifdef LEAP_SUPPORT
+ UCHAR CkipFlag;
+ UCHAR CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH];
+ UCHAR AironetCkipIe = IE_AIRONET_CKIP;
+ UCHAR AironetCkipLen = CKIP_NEGOTIATION_LENGTH;
+ UCHAR AironetIPAddressIE = IE_AIRONET_IPADDRESS;
+ UCHAR AironetIPAddressLen = AIRONET_IPADDRESS_LENGTH;
+ UCHAR AironetIPAddressBuffer[AIRONET_IPADDRESS_LENGTH] = {0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00};
+ UCHAR AironetCCKMReassocIE = IE_AIRONET_CCKMREASSOC;
+ UCHAR AironetCCKMReassocLen = AIRONET_CCKMREASSOC_LENGTH;
+ UCHAR AironetCCKMReassocBuffer[AIRONET_CCKMREASSOC_LENGTH];
+ UCHAR AironetOUI[] = {0x00, 0x40, 0x96, 0x00};
+ UCHAR MICMN[16];
+ UCHAR CalcMicBuffer[80];
+ ULONG CalcMicBufferLen = 0;
+#endif // LEAP_SUPPORT //
+ USHORT Status;
+
+ // Block all authentication request durning WPA block period
+ if (pAd->StaCfg.bBlockAssoc == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Block ReAssoc request durning WPA block period!\n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+ }
+ // the parameters are the same as the association
+ else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv))
+ {
+ RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() allocate memory failed \n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+ return;
+ }
+
+ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, ApAddr);
+
+ // make frame, use bssid as the AP address??
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send RE-ASSOC request...\n"));
+ MgtMacHeaderInit(pAd, &ReassocHdr, SUBTYPE_REASSOC_REQ, 0, ApAddr, ApAddr);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &ReassocHdr,
+ 2, &CapabilityInfo,
+ 2, &ListenIntv,
+ MAC_ADDR_LEN, ApAddr,
+ 1, &SsidIe,
+ 1, &pAd->MlmeAux.SsidLen,
+ pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid,
+ 1, &SupRateIe,
+ 1, &pAd->MlmeAux.SupRateLen,
+ pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
+ END_OF_ARGS);
+
+ if (pAd->MlmeAux.ExtRateLen != 0)
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &ExtRateIe,
+ 1, &pAd->MlmeAux.ExtRateLen,
+ pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+ if (pAd->MlmeAux.APEdcaParm.bValid)
+ {
+ if (pAd->CommonCfg.bAPSDCapable && pAd->MlmeAux.APEdcaParm.bAPSDCapable)
+ {
+ QBSS_STA_INFO_PARM QosInfo;
+
+ NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM));
+ QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE;
+ QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK;
+ QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI;
+ QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO;
+ QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength;
+ WmeIe[8] |= *(PUCHAR)&QosInfo;
+ }
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 9, &WmeIe[0],
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ // HT
+ if ((pAd->MlmeAux.HtCapabilityLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ ULONG TmpLen;
+ UCHAR HtLen;
+ UCHAR BROADCOM[4] = {0x0, 0x90, 0x4c, 0x33};
+ if (pAd->StaActive.SupportedPhyInfo.bPreNHt == TRUE)
+ {
+ HtLen = SIZE_HT_CAP_IE + 4;
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
+ 1, &WpaIe,
+ 1, &HtLen,
+ 4, &BROADCOM[0],
+ pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
+ END_OF_ARGS);
+ }
+ else
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen,
+ 1, &HtCapIe,
+ 1, &pAd->MlmeAux.HtCapabilityLen,
+ pAd->MlmeAux.HtCapabilityLen, &pAd->MlmeAux.HtCapability,
+ END_OF_ARGS);
+ }
+ FrameLen += TmpLen;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION
+ // Case I: (Aggregation + Piggy-Back)
+ // 1. user enable aggregation, AND
+ // 2. Mac support piggy-back
+ // 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON
+ // Case II: (Aggregation)
+ // 1. user enable aggregation, AND
+ // 2. AP annouces it's AGGREGATION-capable in BEACON
+ if (pAd->CommonCfg.bAggregationCapable)
+ {
+ if ((pAd->CommonCfg.bPiggyBackCapable) && ((pAd->MlmeAux.APRalinkIe & 0x00000003) == 3))
+ {
+ ULONG TmpLen;
+ UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00};
+ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
+ 9, RalinkIe,
+ END_OF_ARGS);
+ FrameLen += TmpLen;
+ }
+ else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
+ {
+ ULONG TmpLen;
+ UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
+ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
+ 9, RalinkIe,
+ END_OF_ARGS);
+ FrameLen += TmpLen;
+ }
+ }
+ else
+ {
+ ULONG TmpLen;
+ UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x04, 0x00, 0x00, 0x00};
+ MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
+ 9, RalinkIe,
+ END_OF_ARGS);
+ FrameLen += TmpLen;
+ }
+#ifdef LEAP_SUPPORT
+ if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
+ {
+ CkipFlag = pAd->StaCfg.CkipFlag; // We have update that at PeerBeaconAtJoinRequest()
+ if (CkipFlag != 0)
+ {
+ NdisZeroMemory(CkipNegotiationBuffer, CKIP_NEGOTIATION_LENGTH);
+ CkipNegotiationBuffer[2] = 0x66;
+ // Make it try KP & MIC, since we have to follow the result from AssocRsp
+ CkipNegotiationBuffer[8] = 0x18;
+ CkipNegotiationBuffer[CKIP_NEGOTIATION_LENGTH - 1] = 0x22;
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &AironetCkipIe,
+ 1, &AironetCkipLen,
+ AironetCkipLen, CkipNegotiationBuffer,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &AironetIPAddressIE,
+ 1, &AironetIPAddressLen,
+ AironetIPAddressLen, AironetIPAddressBuffer,
+ END_OF_ARGS);
+ FrameLen += tmp;
+
+ //
+ // The RN is incremented before each reassociation request.
+ //
+ pAd->StaCfg.CCKMRN++;
+ //
+ // Calculate MIC = hmac-md5(krk, STA-ID|BSSID|RSNIE|TSF|RN);
+ //
+ COPY_MAC_ADDR(CalcMicBuffer, pAd->CurrentAddress);
+ CalcMicBufferLen = MAC_ADDR_LEN;
+ COPY_MAC_ADDR(CalcMicBuffer + CalcMicBufferLen, pAd->MlmeAux.Bssid);
+ CalcMicBufferLen += MAC_ADDR_LEN;
+ NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, CipherSuiteCiscoCCKM, CipherSuiteCiscoCCKMLen);
+ CalcMicBufferLen += CipherSuiteCiscoCCKMLen;
+ NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR) &pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp));
+ CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMBeaconAtJoinTimeStamp);
+ NdisMoveMemory(CalcMicBuffer + CalcMicBufferLen, (PUCHAR)&pAd->StaCfg.CCKMRN, sizeof(pAd->StaCfg.CCKMRN));
+ CalcMicBufferLen += sizeof(pAd->StaCfg.CCKMRN);
+ hmac_md5(pAd->StaCfg.KRK, LEN_EAP_MICK, CalcMicBuffer, CalcMicBufferLen, MICMN);
+
+ //
+ // fill up CCKM reassociation request element
+ //
+ NdisMoveMemory(AironetCCKMReassocBuffer, AironetOUI, 4);
+ NdisMoveMemory(AironetCCKMReassocBuffer + 4, (PUCHAR)&pAd->StaCfg.CCKMBeaconAtJoinTimeStamp, 8);
+ NdisMoveMemory(AironetCCKMReassocBuffer + 12, (PUCHAR) &pAd->StaCfg.CCKMRN, 4);
+ NdisMoveMemory(AironetCCKMReassocBuffer +16, MICMN, 8);
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &AironetCCKMReassocIE,
+ 1, &AironetCCKMReassocLen,
+ AironetCCKMReassocLen, AironetCCKMReassocBuffer,
+ END_OF_ARGS);
+ FrameLen += tmp;
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ CipherSuiteCiscoCCKMLen,CipherSuiteCiscoCCKM,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+#endif // LEAP_SUPPORT //
+
+ // Add CCX v2 request if CCX2 admin state is on
+ if (pAd->StaCfg.CCXControl.field.Enable == 1)
+ {
+ //
+ // Add CCX Version
+ //
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &Ccx2Ie,
+ 1, &Ccx2Len,
+ Ccx2Len, Ccx2IeInfo,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ RTMPSetTimer(&pAd->MlmeAux.ReassocTimer, Timeout); /* in mSec */
+ pAd->Mlme.AssocMachine.CurrState = REASSOC_WAIT_RSP;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("ASSOC - MlmeReassocReqAction() sanity check failed. BUG!!!! \n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_INVALID_FORMAT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ Upper layer issues disassoc request
+ Parameters:
+ Elem -
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeDisassocReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PMLME_DISASSOC_REQ_STRUCT pDisassocReq;
+ HEADER_802_11 DisassocHdr;
+ PHEADER_802_11 pDisassocHdr;
+ PUCHAR pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+ NDIS_STATUS NStatus;
+ BOOLEAN TimerCancelled;
+ ULONG Timeout = 0;
+ USHORT Status;
+
+#ifdef QOS_DLS_SUPPORT
+ // send DLS-TEAR_DOWN message,
+ if (pAd->CommonCfg.bDLSCapable)
+ {
+ UCHAR i;
+
+ // tear down local dls table entry
+ for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+ {
+ RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ }
+ }
+
+ // tear down peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+ {
+ RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ }
+ }
+ }
+#endif // QOS_DLS_SUPPORT //
+
+ // skip sanity check
+ pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg);
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MlmeDisassocReqAction() allocate memory failed\n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
+ return;
+ }
+
+
+
+ RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &TimerCancelled);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Send DISASSOC request[BSSID::%02x:%02x:%02x:%02x:%02x:%02x (Reason=%d)\n",
+ pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2],
+ pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5], pDisassocReq->Reason));
+ MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr); // patch peap ttls switching issue
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&DisassocHdr,
+ 2, &pDisassocReq->Reason,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+ // To patch Instance and Buffalo(N) AP
+ // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
+ // Therefore, we send both of them.
+ pDisassocHdr = (PHEADER_802_11)pOutBuffer;
+ pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ pAd->StaCfg.DisassocReason = REASON_DISASSOC_STA_LEAVING;
+ COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pDisassocReq->Addr);
+
+ RTMPSetTimer(&pAd->MlmeAux.DisassocTimer, Timeout); /* in mSec */
+ pAd->Mlme.AssocMachine.CurrState = DISASSOC_WAIT_RSP;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+ {
+ union iwreq_data wrqu;
+ //send disassociate event to wpa_supplicant
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ peer sends assoc rsp back
+ Parameters:
+ Elme - MLME message containing the received frame
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerAssocRspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT CapabilityInfo, Status, Aid;
+ UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
+ UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
+ UCHAR Addr2[MAC_ADDR_LEN];
+ BOOLEAN TimerCancelled;
+ UCHAR CkipFlag;
+ EDCA_PARM EdcaParm;
+ HT_CAPABILITY_IE HtCapability;
+ ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
+ UCHAR HtCapabilityLen;
+ UCHAR AddHtInfoLen;
+ UCHAR NewExtChannelOffset = 0xff;
+
+ if (PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
+ &HtCapability,&AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
+ {
+ // The frame is for me ?
+ if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status));
+#ifdef DOT11_N_SUPPORT
+ DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocRspAction():MacTable [%d].AMsduSize = %d. ClientStatusFlags = 0x%lx \n",Elem->Wcid, pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+#endif // DOT11_N_SUPPORT //
+ RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &TimerCancelled);
+ if(Status == MLME_SUCCESS)
+ {
+ // go to procedure listed on page 376
+ AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
+ &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+ {
+ union iwreq_data wrqu;
+
+ SendAssocIEsToWpaSupplicant(pAd);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_ASSOC_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ wext_notify_event_assoc(pAd);
+
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+
+ pAd->StaCfg.CkipFlag = CkipFlag;
+ if (CkipFlag & 0x18)
+ {
+ NdisZeroMemory(pAd->StaCfg.TxSEQ, 4);
+ NdisZeroMemory(pAd->StaCfg.RxSEQ, 4);
+ NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4);
+ pAd->StaCfg.GIV[0] = RandomByte(pAd);
+ pAd->StaCfg.GIV[1] = RandomByte(pAd);
+ pAd->StaCfg.GIV[2] = RandomByte(pAd);
+ pAd->StaCfg.bCkipOn = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("<CCX> pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag));
+ }
+ }
+ else
+ {
+ // Faile on Association, we need to check the status code
+ // Is that a Rogue AP?
+#ifdef LEAP_SUPPORT
+ if ((pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP) && (Status == MLME_ALG_NOT_SUPPORT))
+ { //Possibly Rogue AP
+ RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, pAd->MlmeAux.Bssid, LEAP_REASON_INVALID_AUTH);
+ }
+#endif // LEAP_SUPPORT //
+ }
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerAssocRspAction() sanity check fail\n"));
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ peer sends reassoc rsp
+ Parametrs:
+ Elem - MLME message cntaining the received frame
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerReassocRspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT CapabilityInfo;
+ USHORT Status;
+ USHORT Aid;
+ UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen;
+ UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen;
+ UCHAR Addr2[MAC_ADDR_LEN];
+ UCHAR CkipFlag;
+ BOOLEAN TimerCancelled;
+ EDCA_PARM EdcaParm;
+ HT_CAPABILITY_IE HtCapability;
+ ADD_HT_INFO_IE AddHtInfo; // AP might use this additional ht info IE
+ UCHAR HtCapabilityLen;
+ UCHAR AddHtInfoLen;
+ UCHAR NewExtChannelOffset = 0xff;
+
+ if(PeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen,
+ &HtCapability, &AddHtInfo, &HtCapabilityLen, &AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag))
+ {
+ if(MAC_ADDR_EQUAL(Addr2, pAd->MlmeAux.Bssid)) // The frame is for me ?
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive REASSOC_RSP to me (status=%d)\n", Status));
+ RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &TimerCancelled);
+
+ if(Status == MLME_SUCCESS)
+ {
+ // go to procedure listed on page 376
+ AssocPostProc(pAd, Addr2, CapabilityInfo, Aid, SupRate, SupRateLen, ExtRate, ExtRateLen,
+ &EdcaParm, &HtCapability, HtCapabilityLen, &AddHtInfo);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+ {
+ union iwreq_data wrqu;
+
+ SendAssocIEsToWpaSupplicant(pAd);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_ASSOC_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ wext_notify_event_assoc(pAd);
+
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+ }
+
+ //
+ // Cisco Leap CCKM supported Re-association.
+ //
+#ifdef LEAP_SUPPORT
+ if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
+ {
+ if (CCKMAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen) == TRUE)
+ {
+ pAd->StaCfg.CkipFlag = CkipFlag;
+ if (CkipFlag & 0x18)
+ {
+ NdisZeroMemory(pAd->StaCfg.TxSEQ, 4);
+ NdisZeroMemory(pAd->StaCfg.RxSEQ, 4);
+ NdisZeroMemory(pAd->StaCfg.CKIPMIC, 4);
+ pAd->StaCfg.GIV[0] = RandomByte(pAd);
+ pAd->StaCfg.GIV[1] = RandomByte(pAd);
+ pAd->StaCfg.GIV[2] = RandomByte(pAd);
+ pAd->StaCfg.bCkipOn = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("<CCX> pAd->StaCfg.CkipFlag = 0x%02x\n", pAd->StaCfg.CkipFlag));
+ }
+
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - CCKMAssocRspSanity() sanity check fail\n"));
+ }
+ }
+ else
+#endif // LEAP_SUPPORT //
+ {
+ // CkipFlag is no use for reassociate
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+ }
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerReassocRspAction() sanity check fail\n"));
+ }
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ procedures on IEEE 802.11/1999 p.376
+ Parametrs:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AssocPostProc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr2,
+ IN USHORT CapabilityInfo,
+ IN USHORT Aid,
+ IN UCHAR SupRate[],
+ IN UCHAR SupRateLen,
+ IN UCHAR ExtRate[],
+ IN UCHAR ExtRateLen,
+ IN PEDCA_PARM pEdcaParm,
+ IN HT_CAPABILITY_IE *pHtCapability,
+ IN UCHAR HtCapabilityLen,
+ IN ADD_HT_INFO_IE *pAddHtInfo) // AP might use this additional ht info IE
+{
+ ULONG Idx;
+
+ pAd->MlmeAux.BssType = BSS_INFRA;
+ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pAddr2);
+ pAd->MlmeAux.Aid = Aid;
+ pAd->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
+#ifdef DOT11_N_SUPPORT
+ // Some HT AP might lost WMM IE. We add WMM ourselves. beacuase HT requires QoS on.
+ if ((HtCapabilityLen > 0) && (pEdcaParm->bValid == FALSE))
+ {
+ pEdcaParm->bValid = TRUE;
+ pEdcaParm->Aifsn[0] = 3;
+ pEdcaParm->Aifsn[1] = 7;
+ pEdcaParm->Aifsn[2] = 2;
+ pEdcaParm->Aifsn[3] = 2;
+
+ pEdcaParm->Cwmin[0] = 4;
+ pEdcaParm->Cwmin[1] = 4;
+ pEdcaParm->Cwmin[2] = 3;
+ pEdcaParm->Cwmin[3] = 2;
+
+ pEdcaParm->Cwmax[0] = 10;
+ pEdcaParm->Cwmax[1] = 10;
+ pEdcaParm->Cwmax[2] = 4;
+ pEdcaParm->Cwmax[3] = 3;
+
+ pEdcaParm->Txop[0] = 0;
+ pEdcaParm->Txop[1] = 0;
+ pEdcaParm->Txop[2] = 96;
+ pEdcaParm->Txop[3] = 48;
+
+ }
+#endif // DOT11_N_SUPPORT //
+
+ NdisMoveMemory(&pAd->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
+
+ // filter out un-supported rates
+ pAd->MlmeAux.SupRateLen = SupRateLen;
+ NdisMoveMemory(pAd->MlmeAux.SupRate, SupRate, SupRateLen);
+ RTMPCheckRates(pAd, pAd->MlmeAux.SupRate, &pAd->MlmeAux.SupRateLen);
+
+ // filter out un-supported rates
+ pAd->MlmeAux.ExtRateLen = ExtRateLen;
+ NdisMoveMemory(pAd->MlmeAux.ExtRate, ExtRate, ExtRateLen);
+ RTMPCheckRates(pAd, pAd->MlmeAux.ExtRate, &pAd->MlmeAux.ExtRateLen);
+
+#ifdef DOT11_N_SUPPORT
+ if (HtCapabilityLen > 0)
+ {
+ RTMPCheckHt(pAd, BSSID_WCID, pHtCapability, pAddHtInfo);
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> AP.AMsduSize = %d. ClientStatusFlags = 0x%lx \n", pAd->MacTab.Content[BSSID_WCID].AMsduSize, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> (Mmps=%d, AmsduSize=%d, )\n",
+ pAd->MacTab.Content[BSSID_WCID].MmpsMode, pAd->MacTab.Content[BSSID_WCID].AMsduSize));
+#endif // DOT11_N_SUPPORT //
+
+ // Set New WPA information
+ Idx = BssTableSearch(&pAd->ScanTab, pAddr2, pAd->MlmeAux.Channel);
+ if (Idx == BSS_NOT_FOUND)
+ {
+ DBGPRINT_ERR(("ASSOC - Can't find BSS after receiving Assoc response\n"));
+ }
+ else
+ {
+ // Init variable
+ pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = 0;
+ NdisZeroMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, MAX_LEN_OF_RSNIE);
+
+ // Store appropriate RSN_IE for WPA SM negotiation later
+ if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ScanTab.BssEntry[Idx].VarIELen != 0))
+ {
+ PUCHAR pVIE;
+ USHORT len;
+ PEID_STRUCT pEid;
+
+ pVIE = pAd->ScanTab.BssEntry[Idx].VarIEs;
+ len = pAd->ScanTab.BssEntry[Idx].VarIELen;
+
+ while (len > 0)
+ {
+ pEid = (PEID_STRUCT) pVIE;
+ // For WPA/WPAPSK
+ if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
+ && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
+ pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
+ DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA SM negotiation \n"));
+ }
+ // For WPA2/WPA2PSK
+ else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
+ && (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2 || pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ NdisMoveMemory(pAd->MacTab.Content[BSSID_WCID].RSN_IE, pVIE, (pEid->Len + 2));
+ pAd->MacTab.Content[BSSID_WCID].RSNIE_Len = (pEid->Len + 2);
+ DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> Store RSN_IE for WPA2 SM negotiation \n"));
+ }
+
+ pVIE += (pEid->Len + 2);
+ len -= (pEid->Len + 2);
+ }
+ }
+
+ if (pAd->MacTab.Content[BSSID_WCID].RSNIE_Len == 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AssocPostProc===> no RSN_IE \n"));
+ }
+ else
+ {
+ hex_dump("RSN_IE", pAd->MacTab.Content[BSSID_WCID].RSN_IE, pAd->MacTab.Content[BSSID_WCID].RSNIE_Len);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+ left part of IEEE 802.11/1999 p.374
+ Parameters:
+ Elem - MLME message containing the received frame
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerDisassocAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Addr2[MAC_ADDR_LEN];
+ USHORT Reason;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction()\n"));
+ if(PeerDisassocSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() Reason = %d\n", Reason));
+ if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, Addr2))
+ {
+
+ if (pAd->CommonCfg.bWirelessEvent)
+ {
+ RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+ }
+
+
+#ifdef LEAP_SUPPORT
+ if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+ {
+ // Cisco_LEAP has start a timer
+ // We should cancel it if using LEAP
+ RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled);
+ //Check is it mach the LEAP Authentication failed as possible a Rogue AP
+ //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Association.
+ if ((pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE) && (pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED))
+ {
+ RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT);
+ }
+ }
+#endif // LEAP_SUPPORT //
+ //
+ // Get Current System time and Turn on AdjacentAPReport
+ //
+ NdisGetSystemUpTime(&pAd->StaCfg.CCXAdjacentAPLinkDownTime);
+ pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
+ LinkDown(pAd, TRUE);
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
+ {
+ union iwreq_data wrqu;
+ //send disassociate event to wpa_supplicant
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - PeerDisassocAction() sanity check fail\n"));
+ }
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ what the state machine will do after assoc timeout
+ Parameters:
+ Elme -
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AssocTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - AssocTimeoutAction\n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_REJ_TIMEOUT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+}
+
+/*
+ ==========================================================================
+ Description:
+ what the state machine will do after reassoc timeout
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID ReassocTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - ReassocTimeoutAction\n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_REJ_TIMEOUT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+}
+
+/*
+ ==========================================================================
+ Description:
+ what the state machine will do after disassoc timeout
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID DisassocTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - DisassocTimeoutAction\n"));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_SUCCESS;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
+}
+
+VOID InvalidStateWhenAssoc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenAssoc(state=%ld), reset ASSOC state machine\n",
+ pAd->Mlme.AssocMachine.CurrState));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_ASSOC_CONF, 2, &Status);
+}
+
+VOID InvalidStateWhenReassoc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenReassoc(state=%ld), reset ASSOC state machine\n",
+ pAd->Mlme.AssocMachine.CurrState));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_REASSOC_CONF, 2, &Status);
+}
+
+VOID InvalidStateWhenDisassociate(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - InvalidStateWhenDisassoc(state=%ld), reset ASSOC state machine\n",
+ pAd->Mlme.AssocMachine.CurrState));
+ pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DISASSOC_CONF, 2, &Status);
+}
+
+/*
+ ==========================================================================
+ Description:
+ right part of IEEE 802.11/1999 page 374
+ Note:
+ This event should never cause ASSOC state machine perform state
+ transition, and has no relationship with CNTL machine. So we separate
+ this routine as a service outside of ASSOC state transition table.
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID Cls3errAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr)
+{
+ HEADER_802_11 DisassocHdr;
+ PHEADER_802_11 pDisassocHdr;
+ PUCHAR pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+ NDIS_STATUS NStatus;
+ USHORT Reason = REASON_CLS3ERR;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame\n"));
+ MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pAddr, pAd->CommonCfg.Bssid); // patch peap ttls switching issue
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&DisassocHdr,
+ 2, &Reason,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+ // To patch Instance and Buffalo(N) AP
+ // Driver has to send deauth to Instance AP, but Buffalo(N) needs to send disassoc to reset Authenticator's state machine
+ // Therefore, we send both of them.
+ pDisassocHdr = (PHEADER_802_11)pOutBuffer;
+ pDisassocHdr->FC.SubType = SUBTYPE_DEAUTH;
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ pAd->StaCfg.DisassocReason = REASON_CLS3ERR;
+ COPY_MAC_ADDR(pAd->StaCfg.DisassocSta, pAddr);
+}
+
+ /*
+ ==========================================================================
+ Description:
+ Switch between WEP and CKIP upon new association up.
+ Parameters:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID SwitchBetweenWepAndCkip(
+ IN PRTMP_ADAPTER pAd)
+{
+ int i;
+ SHAREDKEY_MODE_STRUC csr1;
+
+ // if KP is required. change the CipherAlg in hardware shard key table from WEP
+ // to CKIP. else remain as WEP
+ if (pAd->StaCfg.bCkipOn && (pAd->StaCfg.CkipFlag & 0x10))
+ {
+ // modify hardware key table so that MAC use correct algorithm to decrypt RX
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word);
+ if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP64)
+ csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP64;
+ else if (csr1.field.Bss0Key0CipherAlg == CIPHER_WEP128)
+ csr1.field.Bss0Key0CipherAlg = CIPHER_CKIP128;
+
+ if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP64)
+ csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP64;
+ else if (csr1.field.Bss0Key1CipherAlg == CIPHER_WEP128)
+ csr1.field.Bss0Key1CipherAlg = CIPHER_CKIP128;
+
+ if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP64)
+ csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP64;
+ else if (csr1.field.Bss0Key2CipherAlg == CIPHER_WEP128)
+ csr1.field.Bss0Key2CipherAlg = CIPHER_CKIP128;
+
+ if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP64)
+ csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP64;
+ else if (csr1.field.Bss0Key3CipherAlg == CIPHER_WEP128)
+ csr1.field.Bss0Key3CipherAlg = CIPHER_CKIP128;
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg]));
+
+ // modify software key table so that driver can specify correct algorithm in TXD upon TX
+ for (i=0; i<SHARE_KEY_NUM; i++)
+ {
+ if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP64)
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP64;
+ else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_WEP128)
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_CKIP128;
+ }
+ }
+
+ // else if KP NOT inused. change the CipherAlg in hardware shard key table from CKIP
+ // to WEP.
+ else
+ {
+ // modify hardware key table so that MAC use correct algorithm to decrypt RX
+ RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE, &csr1.word);
+ if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP64)
+ csr1.field.Bss0Key0CipherAlg = CIPHER_WEP64;
+ else if (csr1.field.Bss0Key0CipherAlg == CIPHER_CKIP128)
+ csr1.field.Bss0Key0CipherAlg = CIPHER_WEP128;
+
+ if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP64)
+ csr1.field.Bss0Key1CipherAlg = CIPHER_WEP64;
+ else if (csr1.field.Bss0Key1CipherAlg == CIPHER_CKIP128)
+ csr1.field.Bss0Key1CipherAlg = CIPHER_WEP128;
+
+ if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP64)
+ csr1.field.Bss0Key2CipherAlg = CIPHER_WEP64;
+ else if (csr1.field.Bss0Key2CipherAlg == CIPHER_CKIP128)
+ csr1.field.Bss0Key2CipherAlg = CIPHER_WEP128;
+
+ if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP64)
+ csr1.field.Bss0Key3CipherAlg = CIPHER_WEP64;
+ else if (csr1.field.Bss0Key3CipherAlg == CIPHER_CKIP128)
+ csr1.field.Bss0Key3CipherAlg = CIPHER_WEP128;
+
+ // modify software key table so that driver can specify correct algorithm in TXD upon TX
+ for (i=0; i<SHARE_KEY_NUM; i++)
+ {
+ if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP64)
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP64;
+ else if (pAd->SharedKey[BSS0][i].CipherAlg == CIPHER_CKIP128)
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_WEP128;
+ }
+
+ //
+ // On WPA-NONE, must update CipherAlg.
+ // Because the OID_802_11_WEP_STATUS was been set after OID_802_11_ADD_KEY
+ // and CipherAlg will be CIPHER_NONE by Windows ZeroConfig.
+ // So we need to update CipherAlg after connect.
+ //
+ if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+ {
+ for (i = 0; i < SHARE_KEY_NUM; i++)
+ {
+ if (pAd->SharedKey[BSS0][i].KeyLen != 0)
+ {
+ if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled)
+ {
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_TKIP;
+ }
+ else if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_AES;
+ }
+ }
+ else
+ {
+ pAd->SharedKey[BSS0][i].CipherAlg = CIPHER_NONE;
+ }
+ }
+
+ csr1.field.Bss0Key0CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+ csr1.field.Bss0Key1CipherAlg = pAd->SharedKey[BSS0][1].CipherAlg;
+ csr1.field.Bss0Key2CipherAlg = pAd->SharedKey[BSS0][2].CipherAlg;
+ csr1.field.Bss0Key3CipherAlg = pAd->SharedKey[BSS0][3].CipherAlg;
+ }
+ RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE, csr1.word);
+ DBGPRINT(RT_DEBUG_TRACE, ("SwitchBetweenWepAndCkip: modify BSS0 cipher to %s\n", CipherName[csr1.field.Bss0Key0CipherAlg]));
+ }
+}
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+VOID SendAssocIEsToWpaSupplicant(
+ IN PRTMP_ADAPTER pAd)
+{
+ union iwreq_data wrqu;
+ unsigned char custom[IW_CUSTOM_MAX] = {0};
+
+ if ((pAd->StaCfg.ReqVarIELen + 17) <= IW_CUSTOM_MAX)
+ {
+ sprintf(custom, "ASSOCINFO_ReqIEs=");
+ NdisMoveMemory(custom+17, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = pAd->StaCfg.ReqVarIELen + 17;
+ wrqu.data.flags = RT_REQIE_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_ASSOCINFO_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen + 17 > MAX_CUSTOM_LEN\n"));
+
+ return;
+}
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+int wext_notify_event_assoc(
+ IN RTMP_ADAPTER *pAd)
+{
+ union iwreq_data wrqu;
+ char custom[IW_CUSTOM_MAX] = {0};
+
+#if WIRELESS_EXT > 17
+ if (pAd->StaCfg.ReqVarIELen <= IW_CUSTOM_MAX)
+ {
+ wrqu.data.length = pAd->StaCfg.ReqVarIELen;
+ memcpy(custom, pAd->StaCfg.ReqVarIEs, pAd->StaCfg.ReqVarIELen);
+ wireless_send_event(pAd->net_dev, IWEVASSOCREQIE, &wrqu, custom);
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n"));
+#else
+ if (((pAd->StaCfg.ReqVarIELen*2) + 17) <= IW_CUSTOM_MAX)
+ {
+ UCHAR idx;
+ wrqu.data.length = (pAd->StaCfg.ReqVarIELen*2) + 17;
+ sprintf(custom, "ASSOCINFO(ReqIEs=");
+ for (idx=0; idx<pAd->StaCfg.ReqVarIELen; idx++)
+ sprintf(custom, "%s%02x", custom, pAd->StaCfg.ReqVarIEs[idx]);
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, custom);
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("(pAd->StaCfg.ReqVarIELen*2) + 17 > MAX_CUSTOM_LEN\n"));
+#endif
+
+ return 0;
+
+}
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
diff --git a/drivers/staging/rt2860/sta/auth.c b/drivers/staging/rt2860/sta/auth.c
new file mode 100644
index 000000000000..73fb8d6ea76f
--- /dev/null
+++ b/drivers/staging/rt2860/sta/auth.c
@@ -0,0 +1,474 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ auth.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John 2004-9-3 porting from RT2500
+*/
+#include "../rt_config.h"
+
+/*
+ ==========================================================================
+ Description:
+ authenticate state machine init, including state transition and timer init
+ Parameters:
+ Sm - pointer to the auth state machine
+ Note:
+ The state machine looks like this
+
+ AUTH_REQ_IDLE AUTH_WAIT_SEQ2 AUTH_WAIT_SEQ4
+ MT2_MLME_AUTH_REQ mlme_auth_req_action invalid_state_when_auth invalid_state_when_auth
+ MT2_PEER_AUTH_EVEN drop peer_auth_even_at_seq2_action peer_auth_even_at_seq4_action
+ MT2_AUTH_TIMEOUT Drop auth_timeout_action auth_timeout_action
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+
+void AuthStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE);
+
+ // the first column
+ StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction);
+
+ // the second column
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
+
+ // the third column
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action);
+ StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
+
+ RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE);
+}
+
+/*
+ ==========================================================================
+ Description:
+ function to be executed at timer thread when auth timer expires
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AuthTimeout(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
+
+ DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n"));
+
+ // Do nothing if the driver is starting halt state.
+ // This might happen when timer already been fired before cancel timer with mlmehalt
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
+ return;
+
+ // send a de-auth to reset AP's state machine (Patch AP-Dir635)
+ if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2)
+ Cls2errAction(pAd, pAd->MlmeAux.Bssid);
+
+
+ MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL);
+ RT28XX_MLME_HANDLER(pAd);
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeAuthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Addr[6];
+ USHORT Alg, Seq, Status;
+ ULONG Timeout;
+ HEADER_802_11 AuthHdr;
+ BOOLEAN TimerCancelled;
+ NDIS_STATUS NStatus;
+ PUCHAR pOutBuffer = NULL;
+ ULONG FrameLen = 0;
+
+ // Block all authentication request durning WPA block period
+ if (pAd->StaCfg.bBlockAssoc == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg))
+ {
+ // reset timer
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr);
+ pAd->MlmeAux.Alg = Alg;
+ Seq = 1;
+ Status = MLME_SUCCESS;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg));
+ MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&AuthHdr,
+ 2, &Alg,
+ 2, &Seq,
+ 2, &Status,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2;
+ }
+ else
+ {
+ DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_INVALID_FORMAT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerAuthRspAtSeq2Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Addr2[MAC_ADDR_LEN];
+ USHORT Seq, Status, RemoteStatus, Alg;
+ UCHAR ChlgText[CIPHER_TEXT_LEN];
+ UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8];
+ UCHAR Element[2];
+ HEADER_802_11 AuthHdr;
+ BOOLEAN TimerCancelled;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ USHORT Status2;
+
+ if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
+ {
+ if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status));
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+
+ if (Status == MLME_SUCCESS)
+ {
+ // Authentication Mode "LEAP" has allow for CCX 1.X
+ if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen)
+#ifdef LEAP_SUPPORT
+ || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+ )
+ {
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+#ifdef LEAP_SUPPORT
+ pAd->Mlme.LeapMachine.CurrState = LEAP_IDLE;
+#endif // LEAP_SUPPORT //
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ else
+ {
+ // 2. shared key, need to be challenged
+ Seq++;
+ RemoteStatus = MLME_SUCCESS;
+
+ // Get an unused nonpaged memory
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if(NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status2 = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2);
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n"));
+ MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid);
+ AuthHdr.FC.Wep = 1;
+ // Encrypt challenge text & auth information
+ RTMPInitWepEngine(
+ pAd,
+ pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
+ pAd->StaCfg.DefaultKeyId,
+ pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen,
+ CyperChlgText);
+
+ Alg = cpu2le16(*(USHORT *)&Alg);
+ Seq = cpu2le16(*(USHORT *)&Seq);
+ RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus);
+
+ RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2);
+ RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2);
+ RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2);
+ Element[0] = 16;
+ Element[1] = 128;
+ RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2);
+ RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128);
+ RTMPSetICV(pAd, CyperChlgText + 140);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &AuthHdr,
+ CIPHER_TEXT_LEN + 16, CyperChlgText,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4;
+ }
+ }
+ else
+ {
+#ifdef LEAP_SUPPORT
+ if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+ {
+ //Invalid Authentication possible rogue AP
+ //Add this Ap to Rogue AP.
+ RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_INVALID_AUTH);
+ }
+#endif // LEAP_SUPPORT //
+ pAd->StaCfg.AuthFailReason = Status;
+ COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n"));
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerAuthRspAtSeq4Action(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR Addr2[MAC_ADDR_LEN];
+ USHORT Alg, Seq, Status;
+ CHAR ChlgText[CIPHER_TEXT_LEN];
+ BOOLEAN TimerCancelled;
+
+ if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
+ {
+ if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n"));
+ RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
+
+ if (Status != MLME_SUCCESS)
+ {
+ pAd->StaCfg.AuthFailReason = Status;
+ COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
+ }
+
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n"));
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeDeauthReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MLME_DEAUTH_REQ_STRUCT *pInfo;
+ HEADER_802_11 DeauthHdr;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ USHORT Status;
+
+ pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_FAIL_NO_RESOURCE;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
+ return;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason));
+ MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&DeauthHdr,
+ 2, &pInfo->Reason,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ pAd->StaCfg.DeauthReason = pInfo->Reason;
+ COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr);
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_SUCCESS;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
+
+ // send wireless event - for deauthentication
+ if (pAd->CommonCfg.bWirelessEvent)
+ RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID AuthTimeoutAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n"));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_REJ_TIMEOUT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID InvalidStateWhenAuth(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Status;
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState));
+ pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
+ Status = MLME_STATE_MACHINE_REJECT;
+ MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
+}
+
+/*
+ ==========================================================================
+ Description:
+ Some STA/AP
+ Note:
+ This action should never trigger AUTH state transition, therefore we
+ separate it from AUTH state machine, and make it as a standalone service
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID Cls2errAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr)
+{
+ HEADER_802_11 DeauthHdr;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ USHORT Reason = REASON_CLS2ERR;
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n"));
+ MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11),&DeauthHdr,
+ 2, &Reason,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ pAd->StaCfg.DeauthReason = Reason;
+ COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr);
+}
+
+
diff --git a/drivers/staging/rt2860/sta/auth_rsp.c b/drivers/staging/rt2860/sta/auth_rsp.c
new file mode 100644
index 000000000000..f7aa4b99cf56
--- /dev/null
+++ b/drivers/staging/rt2860/sta/auth_rsp.c
@@ -0,0 +1,167 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ auth_rsp.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John 2004-10-1 copy from RT2560
+*/
+#include "../rt_config.h"
+
+/*
+ ==========================================================================
+ Description:
+ authentication state machine init procedure
+ Parameters:
+ Sm - the state machine
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+VOID AuthRspStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN PSTATE_MACHINE Sm,
+ IN STATE_MACHINE_FUNC Trans[])
+{
+ StateMachineInit(Sm, Trans, MAX_AUTH_RSP_STATE, MAX_AUTH_RSP_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_RSP_IDLE, AUTH_RSP_MACHINE_BASE);
+
+ // column 1
+ StateMachineSetAction(Sm, AUTH_RSP_IDLE, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction);
+
+ // column 2
+ StateMachineSetAction(Sm, AUTH_RSP_WAIT_CHAL, MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)PeerDeauthAction);
+
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID PeerAuthSimpleRspGenAndSend(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHdr80211,
+ IN USHORT Alg,
+ IN USHORT Seq,
+ IN USHORT Reason,
+ IN USHORT Status)
+{
+ HEADER_802_11 AuthHdr;
+ ULONG FrameLen = 0;
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+
+ if (Reason != MLME_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Peer AUTH fail...\n"));
+ return;
+ }
+
+ //Get an unused nonpaged memory
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Send AUTH response (seq#2)...\n"));
+ MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr80211->Addr2, pAd->MlmeAux.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &AuthHdr,
+ 2, &Alg,
+ 2, &Seq,
+ 2, &Reason,
+ END_OF_ARGS);
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID PeerDeauthAction(
+ IN PRTMP_ADAPTER pAd,
+ IN PMLME_QUEUE_ELEM Elem)
+{
+ UCHAR Addr2[MAC_ADDR_LEN];
+ USHORT Reason;
+
+ if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Reason))
+ {
+ if (INFRA_ON(pAd) && MAC_ADDR_EQUAL(Addr2, pAd->CommonCfg.Bssid))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - receive DE-AUTH from our AP (Reason=%d)\n", Reason));
+
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+
+
+ // send wireless event - for deauthentication
+ if (pAd->CommonCfg.bWirelessEvent)
+ RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+ LinkDown(pAd, TRUE);
+
+ // Authentication Mode Cisco_LEAP has start a timer
+ // We should cancel it if using LEAP
+#ifdef LEAP_SUPPORT
+ if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+ {
+ RTMPCancelTimer(&pAd->StaCfg.LeapAuthTimer, &TimerCancelled);
+ //Check is it mach the LEAP Authentication failed as possible a Rogue AP
+ //on it's PortSecured not equal to WPA_802_1X_PORT_SECURED while process the Authenticaton.
+ if ((pAd->StaCfg.PortSecured != WPA_802_1X_PORT_SECURED) && (pAd->Mlme.LeapMachine.CurrState != LEAP_IDLE))
+ {
+ RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_AUTH_TIMEOUT);
+ }
+ }
+#endif // LEAP_SUPPORT //
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("AUTH_RSP - PeerDeauthAction() sanity check fail\n"));
+ }
+}
+
diff --git a/drivers/staging/rt2860/sta/connect.c b/drivers/staging/rt2860/sta/connect.c
new file mode 100644
index 000000000000..36f28f8b4aa4
--- /dev/null
+++ b/drivers/staging/rt2860/sta/connect.c
@@ -0,0 +1,2751 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ connect.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John 2004-08-08 Major modification from RT2560
+*/
+#include "../rt_config.h"
+
+UCHAR CipherSuiteWpaNoneTkip[] = {
+ 0x00, 0x50, 0xf2, 0x01, // oui
+ 0x01, 0x00, // Version
+ 0x00, 0x50, 0xf2, 0x02, // Multicast
+ 0x01, 0x00, // Number of unicast
+ 0x00, 0x50, 0xf2, 0x02, // unicast
+ 0x01, 0x00, // number of authentication method
+ 0x00, 0x50, 0xf2, 0x00 // authentication
+ };
+UCHAR CipherSuiteWpaNoneTkipLen = (sizeof(CipherSuiteWpaNoneTkip) / sizeof(UCHAR));
+
+UCHAR CipherSuiteWpaNoneAes[] = {
+ 0x00, 0x50, 0xf2, 0x01, // oui
+ 0x01, 0x00, // Version
+ 0x00, 0x50, 0xf2, 0x04, // Multicast
+ 0x01, 0x00, // Number of unicast
+ 0x00, 0x50, 0xf2, 0x04, // unicast
+ 0x01, 0x00, // number of authentication method
+ 0x00, 0x50, 0xf2, 0x00 // authentication
+ };
+UCHAR CipherSuiteWpaNoneAesLen = (sizeof(CipherSuiteWpaNoneAes) / sizeof(UCHAR));
+
+// The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS,
+// or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS
+// All settings successfuly negotiated furing MLME state machines become final settings
+// and are copied to pAd->StaActive
+#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \
+{ \
+ (_pAd)->CommonCfg.SsidLen = (_pAd)->MlmeAux.SsidLen; \
+ NdisMoveMemory((_pAd)->CommonCfg.Ssid, (_pAd)->MlmeAux.Ssid, (_pAd)->MlmeAux.SsidLen); \
+ COPY_MAC_ADDR((_pAd)->CommonCfg.Bssid, (_pAd)->MlmeAux.Bssid); \
+ (_pAd)->CommonCfg.Channel = (_pAd)->MlmeAux.Channel; \
+ (_pAd)->CommonCfg.CentralChannel = (_pAd)->MlmeAux.CentralChannel; \
+ (_pAd)->StaActive.Aid = (_pAd)->MlmeAux.Aid; \
+ (_pAd)->StaActive.AtimWin = (_pAd)->MlmeAux.AtimWin; \
+ (_pAd)->StaActive.CapabilityInfo = (_pAd)->MlmeAux.CapabilityInfo; \
+ (_pAd)->CommonCfg.BeaconPeriod = (_pAd)->MlmeAux.BeaconPeriod; \
+ (_pAd)->StaActive.CfpMaxDuration = (_pAd)->MlmeAux.CfpMaxDuration; \
+ (_pAd)->StaActive.CfpPeriod = (_pAd)->MlmeAux.CfpPeriod; \
+ (_pAd)->StaActive.SupRateLen = (_pAd)->MlmeAux.SupRateLen; \
+ NdisMoveMemory((_pAd)->StaActive.SupRate, (_pAd)->MlmeAux.SupRate, (_pAd)->MlmeAux.SupRateLen);\
+ (_pAd)->StaActive.ExtRateLen = (_pAd)->MlmeAux.ExtRateLen; \
+ NdisMoveMemory((_pAd)->StaActive.ExtRate, (_pAd)->MlmeAux.ExtRate, (_pAd)->MlmeAux.ExtRateLen);\
+ NdisMoveMemory(&(_pAd)->CommonCfg.APEdcaParm, &(_pAd)->MlmeAux.APEdcaParm, sizeof(EDCA_PARM));\
+ NdisMoveMemory(&(_pAd)->CommonCfg.APQosCapability, &(_pAd)->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM));\
+ NdisMoveMemory(&(_pAd)->CommonCfg.APQbssLoad, &(_pAd)->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM));\
+ COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].Addr, (_pAd)->MlmeAux.Bssid); \
+ (_pAd)->MacTab.Content[BSSID_WCID].Aid = (_pAd)->MlmeAux.Aid; \
+ (_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.CipherAlg = (_pAd)->StaCfg.PairCipher;\
+ COPY_MAC_ADDR((_pAd)->MacTab.Content[BSSID_WCID].PairwiseKey.BssId, (_pAd)->MlmeAux.Bssid);\
+ (_pAd)->MacTab.Content[BSSID_WCID].RateLen = (_pAd)->StaActive.SupRateLen + (_pAd)->StaActive.ExtRateLen;\
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+*/
+VOID MlmeCntlInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ // Control state machine differs from other state machines, the interface
+ // follows the standard interface
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID MlmeCntlMachinePerformAction(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *S,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ switch(pAd->Mlme.CntlMachine.CurrState)
+ {
+ case CNTL_IDLE:
+ {
+ CntlIdleProc(pAd, Elem);
+ }
+ break;
+ case CNTL_WAIT_DISASSOC:
+ CntlWaitDisassocProc(pAd, Elem);
+ break;
+ case CNTL_WAIT_JOIN:
+ CntlWaitJoinProc(pAd, Elem);
+ break;
+
+ // CNTL_WAIT_REASSOC is the only state in CNTL machine that does
+ // not triggered directly or indirectly by "RTMPSetInformation(OID_xxx)".
+ // Therefore not protected by NDIS's "only one outstanding OID request"
+ // rule. Which means NDIS may SET OID in the middle of ROAMing attempts.
+ // Current approach is to block new SET request at RTMPSetInformation()
+ // when CntlMachine.CurrState is not CNTL_IDLE
+ case CNTL_WAIT_REASSOC:
+ CntlWaitReassocProc(pAd, Elem);
+ break;
+
+ case CNTL_WAIT_START:
+ CntlWaitStartProc(pAd, Elem);
+ break;
+ case CNTL_WAIT_AUTH:
+ CntlWaitAuthProc(pAd, Elem);
+ break;
+ case CNTL_WAIT_AUTH2:
+ CntlWaitAuthProc2(pAd, Elem);
+ break;
+ case CNTL_WAIT_ASSOC:
+ CntlWaitAssocProc(pAd, Elem);
+ break;
+
+ case CNTL_WAIT_OID_LIST_SCAN:
+ if(Elem->MsgType == MT2_SCAN_CONF)
+ {
+ // Resume TxRing after SCANING complete. We hope the out-of-service time
+ // won't be too long to let upper layer time-out the waiting frames
+ RTMPResumeMsduTransmission(pAd);
+ if (pAd->StaCfg.CCXReqType != MSRN_TYPE_UNUSED)
+ {
+ // Cisco scan request is finished, prepare beacon report
+ MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
+ }
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+
+ //
+ // Set LED status to previous status.
+ //
+ if (pAd->bLedOnScanning)
+ {
+ pAd->bLedOnScanning = FALSE;
+ RTMPSetLED(pAd, pAd->LedStatus);
+ }
+#ifdef DOT11N_DRAFT3
+ // AP sent a 2040Coexistence mgmt frame, then station perform a scan, and then send back the respone.
+ if (pAd->CommonCfg.BSSCoexist2040.field.InfoReq == 1)
+ {
+ Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
+ }
+#endif // DOT11N_DRAFT3 //
+ }
+ break;
+
+ case CNTL_WAIT_OID_DISASSOC:
+ if (Elem->MsgType == MT2_DISASSOC_CONF)
+ {
+ LinkDown(pAd, FALSE);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ }
+ break;
+ default:
+ DBGPRINT_ERR(("!ERROR! CNTL - Illegal message type(=%ld)", Elem->MsgType));
+ break;
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlIdleProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MLME_DISASSOC_REQ_STRUCT DisassocReq;
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+ return;
+
+ switch(Elem->MsgType)
+ {
+ case OID_802_11_SSID:
+ CntlOidSsidProc(pAd, Elem);
+ break;
+
+ case OID_802_11_BSSID:
+ CntlOidRTBssidProc(pAd,Elem);
+ break;
+
+ case OID_802_11_BSSID_LIST_SCAN:
+ CntlOidScanProc(pAd,Elem);
+ break;
+
+ case OID_802_11_DISASSOCIATE:
+#ifdef RALINK_ATE
+ if(ATE_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n"));
+ break;
+ }
+#endif // RALINK_ATE //
+ DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
+#ifdef WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_ENABLE_WITH_WEB_UI)
+#endif // WPA_SUPPLICANT_SUPPORT //
+ {
+ // Set the AutoReconnectSsid to prevent it reconnect to old SSID
+ // Since calling this indicate user don't want to connect to that SSID anymore.
+ pAd->MlmeAux.AutoReconnectSsidLen= 32;
+ NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
+ }
+ break;
+
+ case MT2_MLME_ROAMING_REQ:
+ CntlMlmeRoamingProc(pAd, Elem);
+ break;
+
+ case OID_802_11_MIC_FAILURE_REPORT_FRAME:
+ WpaMicFailureReportFrame(pAd, Elem);
+ break;
+
+#ifdef QOS_DLS_SUPPORT
+ case RT_OID_802_11_SET_DLS_PARAM:
+ CntlOidDLSSetupProc(pAd, Elem);
+ break;
+#endif // QOS_DLS_SUPPORT //
+
+ default:
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Illegal message in CntlIdleProc(MsgType=%ld)\n",Elem->MsgType));
+ break;
+ }
+}
+
+VOID CntlOidScanProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MLME_SCAN_REQ_STRUCT ScanReq;
+ ULONG BssIdx = BSS_NOT_FOUND;
+ BSS_ENTRY CurrBss;
+
+#ifdef RALINK_ATE
+/* Disable scanning when ATE is running. */
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+
+ // record current BSS if network is connected.
+ // 2003-2-13 do not include current IBSS if this is the only STA in this IBSS.
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ {
+ BssIdx = BssSsidTableSearch(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->CommonCfg.Channel);
+ if (BssIdx != BSS_NOT_FOUND)
+ {
+ NdisMoveMemory(&CurrBss, &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY));
+ }
+ }
+
+ // clean up previous SCAN result, add current BSS back to table if any
+ BssTableInit(&pAd->ScanTab);
+ if (BssIdx != BSS_NOT_FOUND)
+ {
+ // DDK Note: If the NIC is associated with a particular BSSID and SSID
+ // that are not contained in the list of BSSIDs generated by this scan, the
+ // BSSID description of the currently associated BSSID and SSID should be
+ // appended to the list of BSSIDs in the NIC's database.
+ // To ensure this, we append this BSS as the first entry in SCAN result
+ NdisMoveMemory(&pAd->ScanTab.BssEntry[0], &CurrBss, sizeof(BSS_ENTRY));
+ pAd->ScanTab.BssNr = 1;
+ }
+
+ ScanParmFill(pAd, &ScanReq, "", 0, BSS_ANY, SCAN_ACTIVE);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ,
+ sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Before calling this routine, user desired SSID should already been
+ recorded in CommonCfg.Ssid[]
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlOidSsidProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM * Elem)
+{
+ PNDIS_802_11_SSID pOidSsid = (NDIS_802_11_SSID *)Elem->Msg;
+ MLME_DISASSOC_REQ_STRUCT DisassocReq;
+ ULONG Now;
+
+ // Step 1. record the desired user settings to MlmeAux
+ NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pAd->MlmeAux.Ssid, pOidSsid->Ssid, pOidSsid->SsidLength);
+ pAd->MlmeAux.SsidLen = (UCHAR)pOidSsid->SsidLength;
+ NdisZeroMemory(pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+ pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
+
+
+ //
+ // Update Reconnect Ssid, that user desired to connect.
+ //
+ NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
+ NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+ pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
+
+ // step 2. find all matching BSS in the lastest SCAN result (inBssTab)
+ // & log them into MlmeAux.SsidBssTab for later-on iteration. Sort by RSSI order
+ BssTableSsidSort(pAd, &pAd->MlmeAux.SsidBssTab, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - %d BSS of %d BSS match the desire (%d)SSID - %s\n",
+ pAd->MlmeAux.SsidBssTab.BssNr, pAd->ScanTab.BssNr, pAd->MlmeAux.SsidLen, pAd->MlmeAux.Ssid));
+ NdisGetSystemUpTime(&Now);
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
+ (pAd->CommonCfg.SsidLen == pAd->MlmeAux.SsidBssTab.BssEntry[0].SsidLen) &&
+ NdisEqualMemory(pAd->CommonCfg.Ssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Ssid, pAd->CommonCfg.SsidLen) &&
+ MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pAd->MlmeAux.SsidBssTab.BssEntry[0].Bssid))
+ {
+ // Case 1. already connected with an AP who has the desired SSID
+ // with highest RSSI
+
+ // Add checking Mode "LEAP" for CCX 1.0
+ if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+#ifdef LEAP_SUPPORT
+ || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+ ) &&
+ (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+ {
+ // case 1.1 For WPA, WPA-PSK, if the 1x port is not secured, we have to redo
+ // connection process
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
+ DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+ sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+ }
+ else if (pAd->bConfigChanged == TRUE)
+ {
+ // case 1.2 Important Config has changed, we have to reconnect to the same AP
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP Because config changed...\n"));
+ DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+ sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+ }
+ else
+ {
+ // case 1.3. already connected to the SSID with highest RSSI.
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - already with this BSSID. ignore this SET_SSID request\n"));
+ //
+ // (HCT 12.1) 1c_wlan_mediaevents required
+ // media connect events are indicated when associating with the same AP
+ //
+ if (INFRA_ON(pAd))
+ {
+ //
+ // Since MediaState already is NdisMediaStateConnected
+ // We just indicate the connect event again to meet the WHQL required.
+ //
+ pAd->IndicateMediaState = NdisMediaStateConnected;
+ RTMP_IndicateMediaState(pAd);
+ pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up
+ }
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+ }
+ }
+ else if (INFRA_ON(pAd))
+ {
+ //
+ // For RT61
+ // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: )
+ // RT61 may lost SSID, and not connect to NDTEST_WEP_AP2 and will connect to NDTEST_WEP_AP2 by Autoreconnect
+ // But media status is connected, so the SSID not report correctly.
+ //
+ if (!SSID_EQUAL(pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen))
+ {
+ //
+ // Different SSID means not Roaming case, so we let LinkDown() to Indicate a disconnect event.
+ //
+ pAd->MlmeAux.CurrReqIsFromNdis = TRUE;
+ }
+ // case 2. active INFRA association existent
+ // roaming is done within miniport driver, nothing to do with configuration
+ // utility. so upon a new SET(OID_802_11_SSID) is received, we just
+ // disassociate with the current associated AP,
+ // then perform a new association with this new SSID, no matter the
+ // new/old SSID are the same or not.
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - disassociate with current AP...\n"));
+ DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+ sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+ }
+ else
+ {
+ if (ADHOC_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - drop current ADHOC\n"));
+ LinkDown(pAd, FALSE);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ RTMP_IndicateMediaState(pAd);
+ pAd->ExtraInfo = GENERAL_LINK_DOWN;
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
+ }
+
+ if ((pAd->MlmeAux.SsidBssTab.BssNr == 0) &&
+ (pAd->StaCfg.bAutoReconnect == TRUE) &&
+ (pAd->MlmeAux.BssType == BSS_INFRA) &&
+ (MlmeValidateSSID(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen) == TRUE)
+ )
+ {
+ MLME_SCAN_REQ_STRUCT ScanReq;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CntlOidSsidProc():CNTL - No matching BSS, start a new scan\n"));
+ ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, BSS_ANY, SCAN_ACTIVE);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
+ // Reset Missed scan number
+ pAd->StaCfg.LastScanTime = Now;
+ }
+ else
+ {
+ pAd->MlmeAux.BssIdx = 0;
+ IterateOnBssTab(pAd);
+ }
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlOidRTBssidProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM * Elem)
+{
+ ULONG BssIdx;
+ PUCHAR pOidBssid = (PUCHAR)Elem->Msg;
+ MLME_DISASSOC_REQ_STRUCT DisassocReq;
+ MLME_JOIN_REQ_STRUCT JoinReq;
+
+#ifdef RALINK_ATE
+/* No need to perform this routine when ATE is running. */
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+ // record user desired settings
+ COPY_MAC_ADDR(pAd->MlmeAux.Bssid, pOidBssid);
+ pAd->MlmeAux.BssType = pAd->StaCfg.BssType;
+
+ //
+ // Update Reconnect Ssid, that user desired to connect.
+ //
+ NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID);
+ pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen;
+ NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+
+ // find the desired BSS in the latest SCAN result table
+ BssIdx = BssTableSearch(&pAd->ScanTab, pOidBssid, pAd->MlmeAux.Channel);
+ if (BssIdx == BSS_NOT_FOUND)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - BSSID not found. reply NDIS_STATUS_NOT_ACCEPTED\n"));
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ return;
+ }
+
+ // copy the matched BSS entry from ScanTab to MlmeAux.SsidBssTab. Why?
+ // Because we need this entry to become the JOIN target in later on SYNC state machine
+ pAd->MlmeAux.BssIdx = 0;
+ pAd->MlmeAux.SsidBssTab.BssNr = 1;
+ NdisMoveMemory(&pAd->MlmeAux.SsidBssTab.BssEntry[0], &pAd->ScanTab.BssEntry[BssIdx], sizeof(BSS_ENTRY));
+
+ // 2002-11-26 skip the following checking. i.e. if user wants to re-connect to same AP
+ // we just follow normal procedure. The reason of user doing this may because he/she changed
+ // AP to another channel, but we still received BEACON from it thus don't claim Link Down.
+ // Since user knows he's changed AP channel, he'll re-connect again. By skipping the following
+ // checking, we'll disassociate then re-do normal association with this AP at the new channel.
+ // 2003-1-6 Re-enable this feature based on microsoft requirement which prefer not to re-do
+ // connection when setting the same BSSID.
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
+ MAC_ADDR_EQUAL(pAd->CommonCfg.Bssid, pOidBssid))
+ {
+ // already connected to the same BSSID, go back to idle state directly
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - already in this BSSID. ignore this SET_BSSID request\n"));
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ memcpy(wrqu.ap_addr.sa_data, pAd->MlmeAux.Bssid, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+ }
+ else
+ {
+ if (INFRA_ON(pAd))
+ {
+ // disassoc from current AP first
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - disassociate with current AP ...\n"));
+ DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_DISASSOC_STA_LEAVING);
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
+ sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
+ }
+ else
+ {
+ if (ADHOC_ON(pAd))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - drop current ADHOC\n"));
+ LinkDown(pAd, FALSE);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ RTMP_IndicateMediaState(pAd);
+ pAd->ExtraInfo = GENERAL_LINK_DOWN;
+ DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event C!\n"));
+ }
+
+ // Change the wepstatus to original wepstatus
+ pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus;
+ pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus;
+ pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
+
+ // Check cipher suite, AP must have more secured cipher than station setting
+ // Set the Pairwise and Group cipher to match the intended AP setting
+ // We can only connect to AP with less secured cipher setting
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.GroupCipher;
+
+ if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher)
+ pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipher;
+ else if (pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled)
+ pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA.PairCipherAux;
+ else // There is no PairCipher Aux, downgrade our capability to TKIP
+ pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+ }
+ else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ pAd->StaCfg.GroupCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.GroupCipher;
+
+ if (pAd->StaCfg.WepStatus == pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher)
+ pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipher;
+ else if (pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled)
+ pAd->StaCfg.PairCipher = pAd->ScanTab.BssEntry[BssIdx].WPA2.PairCipherAux;
+ else // There is no PairCipher Aux, downgrade our capability to TKIP
+ pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+
+ // RSN capability
+ pAd->StaCfg.RsnCapability = pAd->ScanTab.BssEntry[BssIdx].WPA2.RsnCapability;
+ }
+
+ // Set Mix cipher flag
+ pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
+ if (pAd->StaCfg.bMixCipher == TRUE)
+ {
+ // If mix cipher, re-build RSNIE
+ RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
+ }
+ // No active association, join the BSS immediately
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - joining %02x:%02x:%02x:%02x:%02x:%02x ...\n",
+ pOidBssid[0],pOidBssid[1],pOidBssid[2],pOidBssid[3],pOidBssid[4],pOidBssid[5]));
+
+ JoinParmFill(pAd, &JoinReq, pAd->MlmeAux.BssIdx);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT), &JoinReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
+ }
+ }
+}
+
+// Roaming is the only external request triggering CNTL state machine
+// despite of other "SET OID" operation. All "SET OID" related oerations
+// happen in sequence, because no other SET OID will be sent to this device
+// until the the previous SET operation is complete (successful o failed).
+// So, how do we quarantee this ROAMING request won't corrupt other "SET OID"?
+// or been corrupted by other "SET OID"?
+//
+// IRQL = DISPATCH_LEVEL
+VOID CntlMlmeRoamingProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ // TODO:
+ // AP in different channel may show lower RSSI than actual value??
+ // should we add a weighting factor to compensate it?
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - Roaming in MlmeAux.RoamTab...\n"));
+
+ NdisMoveMemory(&pAd->MlmeAux.SsidBssTab, &pAd->MlmeAux.RoamTab, sizeof(pAd->MlmeAux.RoamTab));
+ pAd->MlmeAux.SsidBssTab.BssNr = pAd->MlmeAux.RoamTab.BssNr;
+
+ BssTableSortByRssi(&pAd->MlmeAux.SsidBssTab);
+ pAd->MlmeAux.BssIdx = 0;
+ IterateOnBssTab(pAd);
+}
+
+#ifdef QOS_DLS_SUPPORT
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlOidDLSSetupProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PRT_802_11_DLS pDLS = (PRT_802_11_DLS)Elem->Msg;
+ MLME_DLS_REQ_STRUCT MlmeDlsReq;
+ INT i;
+ USHORT reason = REASON_UNSPECIFY;
+
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - (OID set %02x:%02x:%02x:%02x:%02x:%02x with Valid=%d, Status=%d, TimeOut=%d, CountDownTimer=%d)\n",
+ pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5],
+ pDLS->Valid, pDLS->Status, pDLS->TimeOut, pDLS->CountDownTimer));
+
+ if (!pAd->CommonCfg.bDLSCapable)
+ return;
+
+ // DLS will not be supported when Adhoc mode
+ if (INFRA_ON(pAd))
+ {
+ for (i = 0; i < MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+ (pDLS->TimeOut == pAd->StaCfg.DLSEntry[i].TimeOut) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ // 1. Same setting, just drop it
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - setting unchanged\n"));
+ break;
+ }
+ else if (!pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+ MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ // 2. Disable DLS link case, just tear down DLS link
+ reason = REASON_QOS_UNWANTED_MECHANISM;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - start tear down procedure\n"));
+ break;
+ }
+ else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && !pAd->StaCfg.DLSEntry[i].Valid)
+ {
+ // 3. Enable case, start DLS setup procedure
+ NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI));
+
+ //Update countdown timer
+ pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS setup case\n"));
+ break;
+ }
+ else if ((i < MAX_NUM_OF_DLS_ENTRY) && pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid &&
+ (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) && !MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ // 4. update mac case, tear down old DLS and setup new DLS
+ reason = REASON_QOS_UNWANTED_MECHANISM;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ NdisMoveMemory(&pAd->StaCfg.DLSEntry[i], pDLS, sizeof(RT_802_11_DLS_UI));
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS tear down and restart case\n"));
+ break;
+ }
+ else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid &&
+ MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr) && (pAd->StaCfg.DLSEntry[i].TimeOut != pDLS->TimeOut))
+ {
+ // 5. update timeout case, start DLS setup procedure (no tear down)
+ pAd->StaCfg.DLSEntry[i].TimeOut = pDLS->TimeOut;
+ //Update countdown timer
+ pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS update timeout case\n"));
+ break;
+ }
+ else if (pDLS->Valid && pAd->StaCfg.DLSEntry[i].Valid &&
+ (pAd->StaCfg.DLSEntry[i].Status != DLS_FINISH) && MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ // 6. re-setup case, start DLS setup procedure (no tear down)
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_REQ, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ DBGPRINT(RT_DEBUG_TRACE,("CNTL - DLS retry setup procedure\n"));
+ break;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_WARN,("CNTL - DLS not changed in entry - %d - Valid=%d, Status=%d, TimeOut=%d\n",
+ i, pAd->StaCfg.DLSEntry[i].Valid, pAd->StaCfg.DLSEntry[i].Status, pAd->StaCfg.DLSEntry[i].TimeOut));
+ }
+ }
+ }
+}
+#endif // QOS_DLS_SUPPORT //
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlWaitDisassocProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ MLME_START_REQ_STRUCT StartReq;
+
+ if (Elem->MsgType == MT2_DISASSOC_CONF)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Dis-associate successful\n"));
+
+ if (pAd->CommonCfg.bWirelessEvent)
+ {
+ RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+ }
+
+ LinkDown(pAd, FALSE);
+
+ // case 1. no matching BSS, and user wants ADHOC, so we just start a new one
+ if ((pAd->MlmeAux.SsidBssTab.BssNr==0) && (pAd->StaCfg.BssType == BSS_ADHOC))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - No matching BSS, start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid));
+ StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
+ }
+ // case 2. try each matched BSS
+ else
+ {
+ pAd->MlmeAux.BssIdx = 0;
+
+ IterateOnBssTab(pAd);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlWaitJoinProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Reason;
+ MLME_AUTH_REQ_STRUCT AuthReq;
+
+ if (Elem->MsgType == MT2_JOIN_CONF)
+ {
+ NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+ if (Reason == MLME_SUCCESS)
+ {
+ // 1. joined an IBSS, we are pretty much done here
+ if (pAd->MlmeAux.BssType == BSS_ADHOC)
+ {
+ //
+ // 5G bands rules of Japan:
+ // Ad hoc must be disabled in W53(ch52,56,60,64) channels.
+ //
+ if ( (pAd->CommonCfg.bIEEE80211H == 1) &&
+ RadarChannelCheck(pAd, pAd->CommonCfg.Channel)
+ )
+ {
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Join adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel));
+ return;
+ }
+
+ LinkUp(pAd, BSS_ADHOC);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - join the IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
+ pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2],
+ pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5]));
+
+ pAd->IndicateMediaState = NdisMediaStateConnected;
+ pAd->ExtraInfo = GENERAL_LINK_UP;
+ }
+ // 2. joined a new INFRA network, start from authentication
+ else
+ {
+#ifdef LEAP_SUPPORT
+ // Add AuthMode "LEAP" for CCX 1.X
+ if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+ {
+ AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP);
+ }
+ else
+#endif // LEAP_SUPPORT //
+ {
+ // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch))
+ {
+ AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared);
+ }
+ else
+ {
+ AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
+ }
+ }
+ MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
+ sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH;
+ }
+ }
+ else
+ {
+ // 3. failed, try next BSS
+ pAd->MlmeAux.BssIdx++;
+ IterateOnBssTab(pAd);
+ }
+ }
+}
+
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlWaitStartProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Result;
+
+ if (Elem->MsgType == MT2_START_CONF)
+ {
+ NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT));
+ if (Result == MLME_SUCCESS)
+ {
+ //
+ // 5G bands rules of Japan:
+ // Ad hoc must be disabled in W53(ch52,56,60,64) channels.
+ //
+ if ( (pAd->CommonCfg.bIEEE80211H == 1) &&
+ RadarChannelCheck(pAd, pAd->CommonCfg.Channel)
+ )
+ {
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Channel=%d, Start adhoc on W53(52,56,60,64) Channels are not accepted\n", pAd->CommonCfg.Channel));
+ return;
+ }
+#ifdef DOT11_N_SUPPORT
+ if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
+ {
+ N_ChannelCheck(pAd);
+ SetCommonHT(pAd);
+ NdisMoveMemory(&pAd->MlmeAux.AddHtInfo, &pAd->CommonCfg.AddHTInfo, sizeof(ADD_HT_INFO_IE));
+ RTMPCheckHt(pAd, BSSID_WCID, &pAd->CommonCfg.HtCapability, &pAd->CommonCfg.AddHTInfo);
+ pAd->StaActive.SupportedPhyInfo.bHtEnable = TRUE;
+ NdisZeroMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], 16);
+ NdisMoveMemory(&pAd->StaActive.SupportedPhyInfo.MCSSet[0], &pAd->CommonCfg.HtCapability.MCSSet[0], 16);
+ COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
+
+ if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
+ (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE))
+ {
+ pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel + 2;
+ }
+ else if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
+ (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW))
+ {
+ pAd->MlmeAux.CentralChannel = pAd->CommonCfg.Channel - 2;
+ }
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+ pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
+ }
+ LinkUp(pAd, BSS_ADHOC);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ // Before send beacon, driver need do radar detection
+ if ((pAd->CommonCfg.Channel > 14 )
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+ {
+ pAd->CommonCfg.RadarDetect.RDMode = RD_SILENCE_MODE;
+ pAd->CommonCfg.RadarDetect.RDCount = 0;
+#ifdef DFS_SUPPORT
+ BbpRadarDetectionStart(pAd);
+#endif // DFS_SUPPORT //
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - start a new IBSS = %02x:%02x:%02x:%02x:%02x:%02x ...\n",
+ pAd->CommonCfg.Bssid[0],pAd->CommonCfg.Bssid[1],pAd->CommonCfg.Bssid[2],
+ pAd->CommonCfg.Bssid[3],pAd->CommonCfg.Bssid[4],pAd->CommonCfg.Bssid[5]));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Start IBSS fail. BUG!!!!!\n"));
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlWaitAuthProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Reason;
+ MLME_ASSOC_REQ_STRUCT AssocReq;
+ MLME_AUTH_REQ_STRUCT AuthReq;
+
+ if (Elem->MsgType == MT2_AUTH_CONF)
+ {
+ NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+ if (Reason == MLME_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
+ AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo,
+ ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
+
+#ifdef LEAP_SUPPORT
+ //
+ // Cisco Leap CCKM supported Re-association.
+ //
+ if (LEAP_CCKM_ON(pAd) && (pAd->StaCfg.CCKMLinkUpFlag == TRUE))
+ {
+ //if CCKM is turn on , that's mean Fast Reauthentication
+ //Use CCKM Reassociation instead of normal association for Fast Roaming.
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ,
+ sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC;
+ }
+ else
+#endif // LEAP_SUPPORT //
+ {
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ,
+ sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC;
+ }
+ }
+ else
+ {
+ // This fail may because of the AP already keep us in its MAC table without
+ // ageing-out. The previous authentication attempt must have let it remove us.
+ // so try Authentication again may help. For D-Link DWL-900AP+ compatibility.
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try again...\n"));
+#ifdef LEAP_SUPPORT
+ //Add AuthMode "LEAP" for CCX 1.X
+ if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+ {
+ AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, CISCO_AuthModeLEAP);
+ }
+ else
+#endif // LEAP_SUPPORT //
+ {
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeShared) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch))
+ {
+ // either Ndis802_11AuthModeShared or Ndis802_11AuthModeAutoSwitch, try shared key first
+ AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeShared);
+ }
+ else
+ {
+ AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
+ }
+ }
+ MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
+ sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2;
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlWaitAuthProc2(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Reason;
+ MLME_ASSOC_REQ_STRUCT AssocReq;
+ MLME_AUTH_REQ_STRUCT AuthReq;
+
+ if (Elem->MsgType == MT2_AUTH_CONF)
+ {
+ NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+ if (Reason == MLME_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH OK\n"));
+ AssocParmFill(pAd, &AssocReq, pAd->MlmeAux.Bssid, pAd->MlmeAux.CapabilityInfo,
+ ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_ASSOC_REQ,
+ sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_ASSOC;
+ }
+ else
+ {
+#ifdef LEAP_SUPPORT
+ // Process LEAP first, since it use different control variable
+ // We don't want to affect other poven operation
+ if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+ {
+ // LEAP Auth not success, try next BSS
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - *LEAP* AUTH FAIL, give up; try next BSS\n"));
+ DBGPRINT(RT_DEBUG_TRACE, ("Total match BSSID [=%d]\n", pAd->MlmeAux.SsidBssTab.BssNr));
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ pAd->MlmeAux.BssIdx++;
+ IterateOnBssTab(pAd);
+ }
+ else
+#endif // LEAP_SUPPORT //
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeAutoSwitch) &&
+ (pAd->MlmeAux.Alg == Ndis802_11AuthModeShared))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, try OPEN system...\n"));
+ AuthParmFill(pAd, &AuthReq, pAd->MlmeAux.Bssid, Ndis802_11AuthModeOpen);
+ MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_MLME_AUTH_REQ,
+ sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_AUTH2;
+ }
+ else
+ {
+ // not success, try next BSS
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - AUTH FAIL, give up; try next BSS\n"));
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE; //???????
+ pAd->MlmeAux.BssIdx++;
+ IterateOnBssTab(pAd);
+ }
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlWaitAssocProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Reason;
+
+ if (Elem->MsgType == MT2_ASSOC_CONF)
+ {
+ NdisMoveMemory(&Reason, Elem->Msg, sizeof(USHORT));
+ if (Reason == MLME_SUCCESS)
+ {
+ LinkUp(pAd, BSS_INFRA);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association successful on BSS #%ld\n",pAd->MlmeAux.BssIdx));
+
+ if (pAd->CommonCfg.bWirelessEvent)
+ {
+ RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+ }
+ }
+ else
+ {
+ // not success, try next BSS
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Association fails on BSS #%ld\n",pAd->MlmeAux.BssIdx));
+ pAd->MlmeAux.BssIdx++;
+ IterateOnBssTab(pAd);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID CntlWaitReassocProc(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT Result;
+
+ if (Elem->MsgType == MT2_REASSOC_CONF)
+ {
+ NdisMoveMemory(&Result, Elem->Msg, sizeof(USHORT));
+ if (Result == MLME_SUCCESS)
+ {
+ //
+ // NDIS requires a new Link UP indication but no Link Down for RE-ASSOC
+ //
+ LinkUp(pAd, BSS_INFRA);
+
+ // send wireless event - for association
+ if (pAd->CommonCfg.bWirelessEvent)
+ RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+
+
+#ifdef LEAP_SUPPORT
+ if (LEAP_CCKM_ON(pAd))
+ {
+ STA_PORT_SECURED(pAd);
+ pAd->StaCfg.WpaState = SS_FINISH;
+ }
+#endif // LEAP_SUPPORT //
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition successful on BSS #%ld\n", pAd->MlmeAux.RoamIdx));
+ }
+ else
+ {
+ // reassoc failed, try to pick next BSS in the BSS Table
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - Re-assocition fails on BSS #%ld\n", pAd->MlmeAux.RoamIdx));
+ pAd->MlmeAux.RoamIdx++;
+ IterateOnBssTab2(pAd);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID LinkUp(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR BssType)
+{
+ ULONG Now;
+ UINT32 Data;
+ BOOLEAN Cancelled;
+ UCHAR Value = 0, idx;
+ MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry;
+
+ pEntry = &pAd->MacTab.Content[BSSID_WCID];
+
+ //
+ // ASSOC - DisassocTimeoutAction
+ // CNTL - Dis-associate successful
+ // !!! LINK DOWN !!!
+ // [88888] OID_802_11_SSID should have returned NDTEST_WEP_AP2(Returned: )
+ //
+ // To prevent DisassocTimeoutAction to call Link down after we link up,
+ // cancel the DisassocTimer no matter what it start or not.
+ //
+ RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
+
+ COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
+
+#ifdef DOT11_N_SUPPORT
+ COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(pAd);
+#endif // DOT11_N_SUPPORT //
+ // It's quite difficult to tell if a newly added KEY is WEP or CKIP until a new BSS
+ // is formed (either ASSOC/RE-ASSOC done or IBSS started. LinkUP should be a safe place
+ // to examine if cipher algorithm switching is required.
+ //rt2860b. Don't know why need this
+ SwitchBetweenWepAndCkip(pAd);
+
+#ifdef RT2860
+ // Before power save before link up function, We will force use 1R.
+ // So after link up, check Rx antenna # again.
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
+ if(pAd->Antenna.field.RxPath == 3)
+ {
+ Value |= (0x10);
+ }
+ else if(pAd->Antenna.field.RxPath == 2)
+ {
+ Value |= (0x8);
+ }
+ else if(pAd->Antenna.field.RxPath == 1)
+ {
+ Value |= (0x0);
+ }
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
+ pAd->StaCfg.BBPR3 = Value;
+#endif // RT2860 //
+
+ if (BssType == BSS_ADHOC)
+ {
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
+
+#ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
+ // No carrier detection when adhoc
+ // CarrierDetectionStop(pAd);
+ pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL;
+#endif // CARRIER_DETECTION_SUPPORT //
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!Adhoc LINK UP !!! \n" ));
+ }
+ else
+ {
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_INFRA_ON);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!Infra LINK UP !!! \n" ));
+ }
+
+ // 3*3
+ // reset Tx beamforming bit
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+ Value &= (~0x01);
+ Value |= pAd->CommonCfg.RegTransmitSetting.field.TxBF;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+#ifdef DOT11_N_SUPPORT
+ // Change to AP channel
+ if ((pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+ {
+ // Must using 40MHz.
+ pAd->CommonCfg.BBPCurrentBW = BW_40;
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+ Value &= (~0x18);
+ Value |= 0x10;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+ // RX : control channel at lower
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
+ Value &= (~0x20);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
+#ifdef RT2860
+ pAd->StaCfg.BBPR3 = Value;
+#endif // RT2860 //
+
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
+ Data &= 0xfffffffe;
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
+
+ if (pAd->MACVersion == 0x28600100)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!40MHz Lower LINK UP !!! Control Channel at Below. Central = %d \n", pAd->CommonCfg.CentralChannel ));
+ }
+ else if ((pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel) && (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_40))
+ {
+ // Must using 40MHz.
+ pAd->CommonCfg.BBPCurrentBW = BW_40;
+ AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel);
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+ Value &= (~0x18);
+ Value |= 0x10;
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
+ Data |= 0x1;
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
+ Value |= (0x20);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
+#ifdef RT2860
+ pAd->StaCfg.BBPR3 = Value;
+#endif // RT2860 //
+
+ if (pAd->MACVersion == 0x28600100)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x1A);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x16);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! 40MHz Upper LINK UP !!! Control Channel at UpperCentral = %d \n", pAd->CommonCfg.CentralChannel ));
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+ pAd->CommonCfg.BBPCurrentBW = BW_20;
+ pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &Value);
+ Value &= (~0x18);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, Value);
+
+ RTMP_IO_READ32(pAd, TX_BAND_CFG, &Data);
+ Data &= 0xfffffffe;
+ RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Data);
+
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &Value);
+ Value &= (~0x20);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, Value);
+#ifdef RT2860
+ pAd->StaCfg.BBPR3 = Value;
+#endif // RT2860 //
+
+ if (pAd->MACVersion == 0x28600100)
+ {
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x16);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x08);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x11);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!rt2860C !!! \n" ));
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! 20MHz LINK UP !!! \n" ));
+ }
+
+ RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
+ //
+ // Save BBP_R66 value, it will be used in RTUSBResumeMsduTransmission
+ //
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &pAd->BbpTuning.R66CurrentValue);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (BssType=%d, AID=%d, ssid=%s, Channel=%d, CentralChannel = %d)\n",
+ BssType, pAd->StaActive.Aid, pAd->CommonCfg.Ssid, pAd->CommonCfg.Channel, pAd->CommonCfg.CentralChannel));
+
+#ifdef DOT11_N_SUPPORT
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! (Density =%d, )\n", pAd->MacTab.Content[BSSID_WCID].MpduDensity));
+#endif // DOT11_N_SUPPORT //
+
+ AsicSetBssid(pAd, pAd->CommonCfg.Bssid);
+
+ AsicSetSlotTime(pAd, TRUE);
+ AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
+
+ // Call this for RTS protectionfor legacy rate, we will always enable RTS threshold, but normally it will not hit
+ AsicUpdateProtect(pAd, 0, (OFDMSETPROTECT | CCKSETPROTECT), TRUE, FALSE);
+
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
+ {
+ // Update HT protectionfor based on AP's operating mode.
+ if (pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent == 1)
+ {
+ AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, TRUE);
+ }
+ else
+ AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
+ }
+#endif // DOT11_N_SUPPORT //
+
+ NdisZeroMemory(&pAd->DrsCounters, sizeof(COUNTER_DRS));
+
+ NdisGetSystemUpTime(&Now);
+ pAd->StaCfg.LastBeaconRxTime = Now; // last RX timestamp
+
+ if ((pAd->CommonCfg.TxPreamble != Rt802_11PreambleLong) &&
+ CAP_IS_SHORT_PREAMBLE_ON(pAd->StaActive.CapabilityInfo))
+ {
+ MlmeSetTxPreamble(pAd, Rt802_11PreambleShort);
+ }
+
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+
+ if (pAd->CommonCfg.RadarDetect.RDMode == RD_SILENCE_MODE)
+ {
+#ifdef DFS_SUPPORT
+ RadarDetectionStop(pAd);
+#endif // DFS_SUPPORT //
+ }
+ pAd->CommonCfg.RadarDetect.RDMode = RD_NORMAL_MODE;
+
+ if (BssType == BSS_ADHOC)
+ {
+ MakeIbssBeacon(pAd);
+ if ((pAd->CommonCfg.Channel > 14)
+ && (pAd->CommonCfg.bIEEE80211H == 1)
+ && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
+ {
+ ; //Do nothing
+ }
+ else
+ {
+ AsicEnableIbssSync(pAd);
+ }
+
+ // In ad hoc mode, use MAC table from index 1.
+ // p.s ASIC use all 0xff as termination of WCID table search.To prevent it's 0xff-ff-ff-ff-ff-ff, Write 0 here.
+ RTMP_IO_WRITE32(pAd, MAC_WCID_BASE, 0x00);
+ RTMP_IO_WRITE32(pAd, 0x1808, 0x00);
+
+ // If WEP is enabled, add key material and cipherAlg into Asic
+ // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000)
+
+ if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)
+ {
+ PUCHAR Key;
+ UCHAR CipherAlg;
+
+ for (idx=0; idx < SHARE_KEY_NUM; idx++)
+ {
+ CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
+ Key = pAd->SharedKey[BSS0][idx].Key;
+
+ if (pAd->SharedKey[BSS0][idx].KeyLen > 0)
+ {
+ // Set key material and cipherAlg to Asic
+ AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
+
+ if (idx == pAd->StaCfg.DefaultKeyId)
+ {
+ // Update WCID attribute table and IVEIV table for this group key table
+ RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
+ }
+ }
+
+
+ }
+ }
+ // If WPANone is enabled, add key material and cipherAlg into Asic
+ // Fill in Shared Key Table(offset: 0x6c00) and Shared Key Mode(offset: 0x7000)
+ else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+ {
+ pAd->StaCfg.DefaultKeyId = 0; // always be zero
+
+ NdisZeroMemory(&pAd->SharedKey[BSS0][0], sizeof(CIPHER_KEY));
+ pAd->SharedKey[BSS0][0].KeyLen = LEN_TKIP_EK;
+ NdisMoveMemory(pAd->SharedKey[BSS0][0].Key, pAd->StaCfg.PMK, LEN_TKIP_EK);
+
+ if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+ {
+ NdisMoveMemory(pAd->SharedKey[BSS0][0].RxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_RXMICK);
+ NdisMoveMemory(pAd->SharedKey[BSS0][0].TxMic, &pAd->StaCfg.PMK[16], LEN_TKIP_TXMICK);
+ }
+
+ // Decide its ChiperAlg
+ if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
+ pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_TKIP;
+ else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
+ pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Unknow Cipher (=%d), set Cipher to AES\n", pAd->StaCfg.PairCipher));
+ pAd->SharedKey[BSS0][0].CipherAlg = CIPHER_AES;
+ }
+
+ // Set key material and cipherAlg to Asic
+ AsicAddSharedKeyEntry(pAd,
+ BSS0,
+ 0,
+ pAd->SharedKey[BSS0][0].CipherAlg,
+ pAd->SharedKey[BSS0][0].Key,
+ pAd->SharedKey[BSS0][0].TxMic,
+ pAd->SharedKey[BSS0][0].RxMic);
+
+ // Update WCID attribute table and IVEIV table for this group key table
+ RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pAd->SharedKey[BSS0][0].CipherAlg, NULL);
+
+ }
+
+ }
+ else // BSS_INFRA
+ {
+ // Check the new SSID with last SSID
+ while (Cancelled == TRUE)
+ {
+ if (pAd->CommonCfg.LastSsidLen == pAd->CommonCfg.SsidLen)
+ {
+ if (RTMPCompareMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen) == 0)
+ {
+ // Link to the old one no linkdown is required.
+ break;
+ }
+ }
+ // Send link down event before set to link up
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ RTMP_IndicateMediaState(pAd);
+ pAd->ExtraInfo = GENERAL_LINK_DOWN;
+ DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event AA!\n"));
+ break;
+ }
+
+ //
+ // On WPA mode, Remove All Keys if not connect to the last BSSID
+ // Key will be set after 4-way handshake.
+ //
+ if ((pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
+ {
+ ULONG IV;
+
+ // Remove all WPA keys
+ RTMPWPARemoveAllKeys(pAd);
+ pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+
+ // Fixed connection failed with Range Maximizer - 515 AP (Marvell Chip) when security is WPAPSK/TKIP
+ // If IV related values are too large in GroupMsg2, AP would ignore this message.
+ IV = 0;
+ IV |= (pAd->StaCfg.DefaultKeyId << 30);
+ AsicUpdateWCIDIVEIV(pAd, BSSID_WCID, IV, 0);
+ }
+ // NOTE:
+ // the decision of using "short slot time" or not may change dynamically due to
+ // new STA association to the AP. so we have to decide that upon parsing BEACON, not here
+
+ // NOTE:
+ // the decision to use "RTC/CTS" or "CTS-to-self" protection or not may change dynamically
+ // due to new STA association to the AP. so we have to decide that upon parsing BEACON, not here
+
+ ComposePsPoll(pAd);
+ ComposeNullFrame(pAd);
+
+ AsicEnableBssSync(pAd);
+
+ // Add BSSID to WCID search table
+ AsicUpdateRxWCIDTable(pAd, BSSID_WCID, pAd->CommonCfg.Bssid);
+
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+ // add this BSSID entry into HASH table
+ {
+ UCHAR HashIdx;
+
+ //pEntry = &pAd->MacTab.Content[BSSID_WCID];
+ HashIdx = MAC_ADDR_HASH_INDEX(pAd->CommonCfg.Bssid);
+ if (pAd->MacTab.Hash[HashIdx] == NULL)
+ {
+ pAd->MacTab.Hash[HashIdx] = pEntry;
+ }
+ else
+ {
+ pCurrEntry = pAd->MacTab.Hash[HashIdx];
+ while (pCurrEntry->pNext != NULL)
+ pCurrEntry = pCurrEntry->pNext;
+ pCurrEntry->pNext = pEntry;
+ }
+ }
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+
+ // If WEP is enabled, add paiewise and shared key
+#ifdef WPA_SUPPLICANT_SUPPORT
+ if (((pAd->StaCfg.WpaSupplicantUP)&&
+ (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)&&
+ (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_SECURED)) ||
+ ((pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)&&
+ (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)))
+#else
+ if (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled)
+#endif // WPA_SUPPLICANT_SUPPORT //
+ {
+ PUCHAR Key;
+ UCHAR CipherAlg;
+
+ for (idx=0; idx < SHARE_KEY_NUM; idx++)
+ {
+ CipherAlg = pAd->SharedKey[BSS0][idx].CipherAlg;
+ Key = pAd->SharedKey[BSS0][idx].Key;
+
+ if (pAd->SharedKey[BSS0][idx].KeyLen > 0)
+ {
+ // Set key material and cipherAlg to Asic
+ AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
+
+ if (idx == pAd->StaCfg.DefaultKeyId)
+ {
+ // Assign group key info
+ RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
+
+ // Assign pairwise key info
+ RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
+ }
+ }
+ }
+ }
+
+ // only INFRASTRUCTURE mode need to indicate connectivity immediately; ADHOC mode
+ // should wait until at least 2 active nodes in this BSSID.
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+
+ // For GUI ++
+ if (pAd->StaCfg.AuthMode < Ndis802_11AuthModeWPA)
+ {
+ pAd->IndicateMediaState = NdisMediaStateConnected;
+ pAd->ExtraInfo = GENERAL_LINK_UP;
+ }
+ // --
+ RTMP_IndicateMediaState(pAd);
+
+ // Add BSSID in my MAC Table.
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+ RTMPMoveMemory(pAd->MacTab.Content[BSSID_WCID].Addr, pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
+ pAd->MacTab.Content[BSSID_WCID].Aid = BSSID_WCID;
+ pAd->MacTab.Content[BSSID_WCID].pAd = pAd;
+ pAd->MacTab.Content[BSSID_WCID].ValidAsCLI = TRUE; //Although this is bssid..still set ValidAsCl
+ pAd->MacTab.Size = 1; // infra mode always set MACtab size =1.
+ pAd->MacTab.Content[BSSID_WCID].Sst = SST_ASSOC;
+ pAd->MacTab.Content[BSSID_WCID].AuthState = SST_ASSOC;
+ pAd->MacTab.Content[BSSID_WCID].WepStatus = pAd->StaCfg.WepStatus;
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !!! ClientStatusFlags=%lx)\n",
+ pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+
+ MlmeUpdateTxRates(pAd, TRUE, BSS0);
+#ifdef DOT11_N_SUPPORT
+ MlmeUpdateHtTxRates(pAd, BSS0);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK UP !! (StaActive.bHtEnable =%d, )\n", pAd->StaActive.SupportedPhyInfo.bHtEnable));
+#endif // DOT11_N_SUPPORT //
+
+ //
+ // Report Adjacent AP report.
+ //
+#ifdef LEAP_SUPPORT
+ CCXAdjacentAPReport(pAd);
+#endif // LEAP_SUPPORT //
+
+ if (pAd->CommonCfg.bAggregationCapable)
+ {
+ if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->MlmeAux.APRalinkIe & 0x00000003) == 3)
+ {
+
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+ RTMPSetPiggyBack(pAd, TRUE);
+ DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n"));
+ }
+ else if (pAd->MlmeAux.APRalinkIe & 0x00000001)
+ {
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+ }
+ }
+
+ if (pAd->MlmeAux.APRalinkIe != 0x0)
+ {
+#ifdef DOT11_N_SUPPORT
+ if (CLIENT_STATUS_TEST_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RDG_CAPABLE))
+ {
+ AsicEnableRDG(pAd);
+ }
+#endif // DOT11_N_SUPPORT //
+ OPSTATUS_SET_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
+ CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET);
+ }
+ else
+ {
+ OPSTATUS_CLEAR_FLAG(pAd, fCLIENT_STATUS_RALINK_CHIPSET);
+ CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_RALINK_CHIPSET);
+ }
+ }
+
+#ifdef DOT11_N_SUPPORT
+ DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_CONNECT Event B!.BACapability = %x. ClientStatusFlags = %lx\n", pAd->CommonCfg.BACapability.word, pAd->MacTab.Content[BSSID_WCID].ClientStatusFlags));
+#endif // DOT11_N_SUPPORT //
+
+ // Set LED
+ RTMPSetLED(pAd, LED_LINK_UP);
+
+ pAd->Mlme.PeriodicRound = 0;
+ pAd->Mlme.OneSecPeriodicRound = 0;
+ pAd->bConfigChanged = FALSE; // Reset config flag
+ pAd->ExtraInfo = GENERAL_LINK_UP; // Update extra information to link is up
+
+ // Set asic auto fall back
+ {
+ PUCHAR pTable;
+ UCHAR TableSize = 0;
+
+ MlmeSelectTxRateTable(pAd, &pAd->MacTab.Content[BSSID_WCID], &pTable, &TableSize, &pAd->CommonCfg.TxRateIndex);
+ AsicUpdateAutoFallBackTable(pAd, pTable);
+ }
+
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+ pEntry->HTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
+ pEntry->MaxHTPhyMode.word = pAd->StaCfg.HTPhyMode.word;
+ if (pAd->StaCfg.bAutoTxRateSwitch == FALSE)
+ {
+ pEntry->bAutoTxRateSwitch = FALSE;
+#ifdef DOT11_N_SUPPORT
+ if (pEntry->HTPhyMode.field.MCS == 32)
+ pEntry->HTPhyMode.field.ShortGI = GI_800;
+
+ if ((pEntry->HTPhyMode.field.MCS > MCS_7) || (pEntry->HTPhyMode.field.MCS == 32))
+ pEntry->HTPhyMode.field.STBC = STBC_NONE;
+#endif // DOT11_N_SUPPORT //
+ // If the legacy mode is set, overwrite the transmit setting of this entry.
+ if (pEntry->HTPhyMode.field.MODE <= MODE_OFDM)
+ RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+ }
+ else
+ pEntry->bAutoTxRateSwitch = TRUE;
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+ // Let Link Status Page display first initial rate.
+ pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
+ // Select DAC according to HT or Legacy
+ if (pAd->StaActive.SupportedPhyInfo.MCSSet[0] != 0x00)
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
+ Value &= (~0x18);
+ if (pAd->Antenna.field.TxPath == 2)
+ {
+ Value |= 0x10;
+ }
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
+ }
+ else
+ {
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &Value);
+ Value &= (~0x18);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, Value);
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
+ {
+ }
+ else if (pEntry->MaxRAmpduFactor == 0)
+ {
+ // If HT AP doesn't support MaxRAmpduFactor = 1, we need to set max PSDU to 0.
+ // Because our Init value is 1 at MACRegTable.
+ RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x0fff);
+ }
+#endif // DOT11_N_SUPPORT //
+
+ // Patch for Marvel AP to gain high throughput
+ // Need to set as following,
+ // 1. Set txop in register-EDCA_AC0_CFG as 0x60
+ // 2. Set EnTXWriteBackDDONE in register-WPDMA_GLO_CFG as zero
+ // 3. PBF_MAX_PCNT as 0x1F3FBF9F
+ // 4. kick per two packets when dequeue
+ //
+ // Txop can only be modified when RDG is off, WMM is disable and TxBurst is enable
+ //
+ // if 1. Legacy AP WMM on, or 2. 11n AP, AMPDU disable. Force turn off burst no matter what bEnableTxBurst is.
+#ifdef DOT11_N_SUPPORT
+ if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
+ || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE)))
+ {
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+ Data &= 0xFFFFFF00;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+
+ RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
+ DBGPRINT(RT_DEBUG_TRACE, ("Txburst 1\n"));
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ if (pAd->CommonCfg.bEnableTxBurst)
+ {
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+ Data &= 0xFFFFFF00;
+ Data |= 0x60;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+ pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = TRUE;
+
+ RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3FBF9F);
+ DBGPRINT(RT_DEBUG_TRACE, ("Txburst 2\n"));
+ }
+ else
+ {
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
+ Data &= 0xFFFFFF00;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
+
+ RTMP_IO_WRITE32(pAd, PBF_MAX_PCNT, 0x1F3F7F9F);
+ DBGPRINT(RT_DEBUG_TRACE, ("Txburst 3\n"));
+ }
+
+#ifdef DOT11_N_SUPPORT
+ // Re-check to turn on TX burst or not.
+ if ((pAd->CommonCfg.IOTestParm.bLastAtheros == TRUE) && ((STA_WEP_ON(pAd))||(STA_TKIP_ON(pAd))))
+ {
+ pAd->CommonCfg.IOTestParm.bNextDisableRxBA = TRUE;
+ if (pAd->CommonCfg.bEnableTxBurst)
+ {
+ UINT32 MACValue = 0;
+ // Force disable TXOP value in this case. The same action in MLMEUpdateProtect too.
+ // I didn't change PBF_MAX_PCNT setting.
+ RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &MACValue);
+ MACValue &= 0xFFFFFF00;
+ RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, MACValue);
+ pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
+ }
+ }
+ else
+ {
+ pAd->CommonCfg.IOTestParm.bNextDisableRxBA = FALSE;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ pAd->CommonCfg.IOTestParm.bLastAtheros = FALSE;
+ COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!!pAd->bNextDisableRxBA= %d \n", pAd->CommonCfg.IOTestParm.bNextDisableRxBA));
+ // BSSID add in one MAC entry too. Because in Tx, ASIC need to check Cipher and IV/EIV, BAbitmap
+ // Pther information in MACTab.Content[BSSID_WCID] is not necessary for driver.
+ // Note: As STA, The MACTab.Content[BSSID_WCID]. PairwiseKey and Shared Key for BSS0 are the same.
+
+ if (pAd->StaCfg.WepStatus <= Ndis802_11WEPDisabled)
+ {
+ pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+ pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+ }
+
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+ pEntry->PortSecured = pAd->StaCfg.PortSecured;
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+ //
+ // Patch Atheros AP TX will breakdown issue.
+ // AP Model: DLink DWL-8200AP
+ //
+ if (INFRA_ON(pAd) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && STA_TKIP_ON(pAd))
+ {
+ RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x01);
+ }
+ else
+ {
+ RTMP_IO_WRITE32(pAd, RX_PARSER_CFG, 0x00);
+ }
+
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ if ((pAd->CommonCfg.BACapability.field.b2040CoexistScanSup) && (pAd->CommonCfg.Channel <= 11))
+ {
+ OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SCAN_2040);
+ BuildEffectedChannelList(pAd);
+ }
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+}
+
+/*
+ ==========================================================================
+
+ Routine Description:
+ Disconnect current BSSID
+
+ Arguments:
+ pAd - Pointer to our adapter
+ IsReqFromAP - Request from AP
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ We need more information to know it's this requst from AP.
+ If yes! we need to do extra handling, for example, remove the WPA key.
+ Otherwise on 4-way handshaking will faied, since the WPA key didn't be
+ remove while auto reconnect.
+ Disconnect request from AP, it means we will start afresh 4-way handshaking
+ on WPA mode.
+
+ ==========================================================================
+*/
+VOID LinkDown(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN IsReqFromAP)
+{
+ UCHAR i, ByteValue = 0;
+
+ // Do nothing if monitor mode is on
+ if (MONITOR_ON(pAd))
+ return;
+
+#ifdef RALINK_ATE
+ // Nothing to do in ATE mode.
+ if (ATE_ON(pAd))
+ return;
+#endif // RALINK_ATE //
+
+ if (pAd->CommonCfg.bWirelessEvent)
+ {
+ RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN !!!\n"));
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
+
+#ifdef RT2860
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
+ {
+ BOOLEAN Cancelled;
+ pAd->Mlme.bPsPollTimerRunning = FALSE;
+ RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
+ }
+
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ {
+ AUTO_WAKEUP_STRUC AutoWakeupCfg;
+ AsicForceWakeup(pAd, TRUE);
+ AutoWakeupCfg.word = 0;
+ RTMP_IO_WRITE32(pAd, AUTO_WAKEUP_CFG, AutoWakeupCfg.word);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE);
+ }
+
+ pAd->bPCIclkOff = FALSE;
+#endif // RT2860 //
+ if (ADHOC_ON(pAd)) // Adhoc mode link down
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 1!!!\n"));
+
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ RTMP_IndicateMediaState(pAd);
+ pAd->ExtraInfo = GENERAL_LINK_DOWN;
+ BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel);
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! MacTab.Size=%d !!!\n", pAd->MacTab.Size));
+ }
+ else // Infra structure mode
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("!!! LINK DOWN 2!!!\n"));
+
+#ifdef QOS_DLS_SUPPORT
+ // DLS tear down frame must be sent before link down
+ // send DLS-TEAR_DOWN message
+ if (pAd->CommonCfg.bDLSCapable)
+ {
+ // tear down local dls table entry
+ for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+
+ // tear down peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+ }
+#endif // QOS_DLS_SUPPORT //
+
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED);
+
+ // Saved last SSID for linkup comparison
+ pAd->CommonCfg.LastSsidLen = pAd->CommonCfg.SsidLen;
+ NdisMoveMemory(pAd->CommonCfg.LastSsid, pAd->CommonCfg.Ssid, pAd->CommonCfg.LastSsidLen);
+ COPY_MAC_ADDR(pAd->CommonCfg.LastBssid, pAd->CommonCfg.Bssid);
+ if (pAd->MlmeAux.CurrReqIsFromNdis == TRUE)
+ {
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ RTMP_IndicateMediaState(pAd);
+ pAd->ExtraInfo = GENERAL_LINK_DOWN;
+ DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event A!\n"));
+ pAd->MlmeAux.CurrReqIsFromNdis = FALSE;
+ }
+ else
+ {
+ //
+ // If disassociation request is from NDIS, then we don't need to delete BSSID from entry.
+ // Otherwise lost beacon or receive De-Authentication from AP,
+ // then we should delete BSSID from BssTable.
+ // If we don't delete from entry, roaming will fail.
+ //
+ BssTableDeleteEntry(&pAd->ScanTab, pAd->CommonCfg.Bssid, pAd->CommonCfg.Channel);
+ }
+
+ // restore back to -
+ // 1. long slot (20 us) or short slot (9 us) time
+ // 2. turn on/off RTS/CTS and/or CTS-to-self protection
+ // 3. short preamble
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED);
+
+ if (pAd->StaCfg.CCXAdjacentAPReportFlag == TRUE)
+ {
+ //
+ // Record current AP's information.
+ // for later used reporting Adjacent AP report.
+ //
+ pAd->StaCfg.CCXAdjacentAPChannel = pAd->CommonCfg.Channel;
+ pAd->StaCfg.CCXAdjacentAPSsidLen = pAd->CommonCfg.SsidLen;
+ NdisMoveMemory(pAd->StaCfg.CCXAdjacentAPSsid, pAd->CommonCfg.Ssid, pAd->StaCfg.CCXAdjacentAPSsidLen);
+ COPY_MAC_ADDR(pAd->StaCfg.CCXAdjacentAPBssid, pAd->CommonCfg.Bssid);
+ }
+
+#ifdef EXT_BUILD_CHANNEL_LIST
+ // Country IE of the AP will be evaluated and will be used.
+ if (pAd->StaCfg.IEEE80211dClientMode != Rt802_11_D_None)
+ {
+ NdisMoveMemory(&pAd->CommonCfg.CountryCode[0], &pAd->StaCfg.StaOriCountryCode[0], 2);
+ pAd->CommonCfg.Geography = pAd->StaCfg.StaOriGeography;
+ BuildChannelListEx(pAd);
+ }
+#endif // EXT_BUILD_CHANNEL_LIST //
+
+ }
+
+ for (i=1; i<MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (pAd->MacTab.Content[i].ValidAsCLI == TRUE)
+ MacTableDeleteEntry(pAd, pAd->MacTab.Content[i].Aid, pAd->MacTab.Content[i].Addr);
+ }
+
+ pAd->StaCfg.CCXQosECWMin = 4;
+ pAd->StaCfg.CCXQosECWMax = 10;
+
+ AsicSetSlotTime(pAd, TRUE); //FALSE);
+ AsicSetEdcaParm(pAd, NULL);
+
+ // Set LED
+ RTMPSetLED(pAd, LED_LINK_DOWN);
+ pAd->LedIndicatorStregth = 0xF0;
+ RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
+
+ AsicDisableSync(pAd);
+
+ pAd->Mlme.PeriodicRound = 0;
+ pAd->Mlme.OneSecPeriodicRound = 0;
+
+ if (pAd->StaCfg.BssType == BSS_INFRA)
+ {
+ // Remove StaCfg Information after link down
+ NdisZeroMemory(pAd->CommonCfg.Bssid, MAC_ADDR_LEN);
+ NdisZeroMemory(pAd->CommonCfg.Ssid, MAX_LEN_OF_SSID);
+ pAd->CommonCfg.SsidLen = 0;
+ }
+#ifdef DOT11_N_SUPPORT
+ NdisZeroMemory(&pAd->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE));
+ NdisZeroMemory(&pAd->MlmeAux.AddHtInfo, sizeof(ADD_HT_INFO_IE));
+ pAd->MlmeAux.HtCapabilityLen = 0;
+ pAd->MlmeAux.NewExtChannelOffset = 0xff;
+#endif // DOT11_N_SUPPORT //
+
+ // Reset WPA-PSK state. Only reset when supplicant enabled
+ if (pAd->StaCfg.WpaState != SS_NOTUSE)
+ {
+ pAd->StaCfg.WpaState = SS_START;
+ // Clear Replay counter
+ NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
+
+#ifdef QOS_DLS_SUPPORT
+ if (pAd->CommonCfg.bDLSCapable)
+ NdisZeroMemory(pAd->StaCfg.DlsReplayCounter, 8);
+#endif // QOS_DLS_SUPPORT //
+ }
+
+
+ //
+ // if link down come from AP, we need to remove all WPA keys on WPA mode.
+ // otherwise will cause 4-way handshaking failed, since the WPA key not empty.
+ //
+ if ((IsReqFromAP) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
+ {
+ // Remove all WPA keys
+ RTMPWPARemoveAllKeys(pAd);
+ }
+
+ // 802.1x port control
+#ifdef WPA_SUPPLICANT_SUPPORT
+ // Prevent clear PortSecured here with static WEP
+ // NetworkManger set security policy first then set SSID to connect AP.
+ if (pAd->StaCfg.WpaSupplicantUP &&
+ (pAd->StaCfg.WepStatus == Ndis802_11WEPEnabled) &&
+ (pAd->StaCfg.IEEE8021X == FALSE))
+ {
+ pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED;
+ }
+ else
+#endif // WPA_SUPPLICANT_SUPPORT //
+ {
+ pAd->StaCfg.PortSecured = WPA_802_1X_PORT_NOT_SECURED;
+ pAd->StaCfg.PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
+ }
+
+ NdisAcquireSpinLock(&pAd->MacTabLock);
+ pAd->MacTab.Content[BSSID_WCID].PortSecured = pAd->StaCfg.PortSecured;
+ NdisReleaseSpinLock(&pAd->MacTabLock);
+
+ pAd->StaCfg.MicErrCnt = 0;
+
+ // Turn off Ckip control flag
+ pAd->StaCfg.bCkipOn = FALSE;
+ pAd->StaCfg.CCXEnable = FALSE;
+
+ pAd->IndicateMediaState = NdisMediaStateDisconnected;
+ // Update extra information to link is up
+ pAd->ExtraInfo = GENERAL_LINK_DOWN;
+
+ pAd->StaCfg.AdhocBOnlyJoined = FALSE;
+ pAd->StaCfg.AdhocBGJoined = FALSE;
+ pAd->StaCfg.Adhoc20NJoined = FALSE;
+ pAd->StaActive.SupportedPhyInfo.bHtEnable = FALSE;
+
+ // Reset the Current AP's IP address
+ NdisZeroMemory(pAd->StaCfg.AironetIPAddress, 4);
+
+ // Clean association information
+ NdisZeroMemory(&pAd->StaCfg.AssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION));
+ pAd->StaCfg.AssocInfo.Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+ pAd->StaCfg.ReqVarIELen = 0;
+ pAd->StaCfg.ResVarIELen = 0;
+
+ //
+ // Reset RSSI value after link down
+ //
+ pAd->StaCfg.RssiSample.AvgRssi0 = 0;
+ pAd->StaCfg.RssiSample.AvgRssi0X8 = 0;
+ pAd->StaCfg.RssiSample.AvgRssi1 = 0;
+ pAd->StaCfg.RssiSample.AvgRssi1X8 = 0;
+ pAd->StaCfg.RssiSample.AvgRssi2 = 0;
+ pAd->StaCfg.RssiSample.AvgRssi2X8 = 0;
+
+ // Restore MlmeRate
+ pAd->CommonCfg.MlmeRate = pAd->CommonCfg.BasicMlmeRate;
+ pAd->CommonCfg.RtsRate = pAd->CommonCfg.BasicMlmeRate;
+
+#ifdef DOT11_N_SUPPORT
+ //
+ // After Link down, reset piggy-back setting in ASIC. Disable RDG.
+ //
+ if (pAd->CommonCfg.BBPCurrentBW == BW_40)
+ {
+ pAd->CommonCfg.BBPCurrentBW = BW_20;
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &ByteValue);
+ ByteValue &= (~0x18);
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, ByteValue);
+ }
+#endif // DOT11_N_SUPPORT //
+ // Reset DAC
+ RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &ByteValue);
+ ByteValue &= (~0x18);
+ if (pAd->Antenna.field.TxPath == 2)
+ {
+ ByteValue |= 0x10;
+ }
+ RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, ByteValue);
+
+ RTMPSetPiggyBack(pAd,FALSE);
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
+
+#ifdef DOT11_N_SUPPORT
+ pAd->CommonCfg.BACapability.word = pAd->CommonCfg.REGBACapability.word;
+#endif // DOT11_N_SUPPORT //
+
+ // Restore all settings in the following.
+ AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE);
+ AsicDisableRDG(pAd);
+ pAd->CommonCfg.IOTestParm.bCurrentAtheros = FALSE;
+ pAd->CommonCfg.IOTestParm.bNowAtherosBurstOn = FALSE;
+
+#ifdef DOT11_N_SUPPORT
+#ifdef DOT11N_DRAFT3
+ OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SCAN_2040);
+ pAd->CommonCfg.BSSCoexist2040.word = 0;
+ TriEventInit(pAd);
+ for (i = 0; i < (pAd->ChannelListNum - 1); i++)
+ {
+ pAd->ChannelList[i].bEffectedChannel = FALSE;
+ }
+#endif // DOT11N_DRAFT3 //
+#endif // DOT11_N_SUPPORT //
+
+ RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, 0x1fff);
+ RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS);
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP) {
+ union iwreq_data wrqu;
+ //send disassociate event to wpa_supplicant
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
+ wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+#endif // WPA_SUPPLICANT_SUPPORT //
+
+#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
+ {
+ union iwreq_data wrqu;
+ memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
+ wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
+ }
+#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID IterateOnBssTab(
+ IN PRTMP_ADAPTER pAd)
+{
+ MLME_START_REQ_STRUCT StartReq;
+ MLME_JOIN_REQ_STRUCT JoinReq;
+ ULONG BssIdx;
+
+ // Change the wepstatus to original wepstatus
+ pAd->StaCfg.WepStatus = pAd->StaCfg.OrigWepStatus;
+ pAd->StaCfg.PairCipher = pAd->StaCfg.OrigWepStatus;
+ pAd->StaCfg.GroupCipher = pAd->StaCfg.OrigWepStatus;
+
+ BssIdx = pAd->MlmeAux.BssIdx;
+ if (BssIdx < pAd->MlmeAux.SsidBssTab.BssNr)
+ {
+ // Check cipher suite, AP must have more secured cipher than station setting
+ // Set the Pairwise and Group cipher to match the intended AP setting
+ // We can only connect to AP with less secured cipher setting
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.GroupCipher;
+
+ if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher)
+ pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipher;
+ else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux != Ndis802_11WEPDisabled)
+ pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA.PairCipherAux;
+ else // There is no PairCipher Aux, downgrade our capability to TKIP
+ pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+ }
+ else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ pAd->StaCfg.GroupCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.GroupCipher;
+
+ if (pAd->StaCfg.WepStatus == pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher)
+ pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipher;
+ else if (pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux != Ndis802_11WEPDisabled)
+ pAd->StaCfg.PairCipher = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.PairCipherAux;
+ else // There is no PairCipher Aux, downgrade our capability to TKIP
+ pAd->StaCfg.PairCipher = Ndis802_11Encryption2Enabled;
+
+ // RSN capability
+ pAd->StaCfg.RsnCapability = pAd->MlmeAux.SsidBssTab.BssEntry[BssIdx].WPA2.RsnCapability;
+ }
+
+ // Set Mix cipher flag
+ pAd->StaCfg.bMixCipher = (pAd->StaCfg.PairCipher == pAd->StaCfg.GroupCipher) ? FALSE : TRUE;
+ if (pAd->StaCfg.bMixCipher == TRUE)
+ {
+ // If mix cipher, re-build RSNIE
+ RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, 0);
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.SsidBssTab.BssNr));
+ JoinParmFill(pAd, &JoinReq, BssIdx);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_JOIN_REQ, sizeof(MLME_JOIN_REQ_STRUCT),
+ &JoinReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_JOIN;
+ }
+ else if (pAd->StaCfg.BssType == BSS_ADHOC)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All BSS fail; start a new ADHOC (Ssid=%s)...\n",pAd->MlmeAux.Ssid));
+ StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
+ MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
+ }
+ else // no more BSS
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All roaming failed, stay @ ch #%d\n", pAd->CommonCfg.Channel));
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ }
+}
+
+// for re-association only
+// IRQL = DISPATCH_LEVEL
+VOID IterateOnBssTab2(
+ IN PRTMP_ADAPTER pAd)
+{
+ MLME_REASSOC_REQ_STRUCT ReassocReq;
+ ULONG BssIdx;
+ BSS_ENTRY *pBss;
+
+ BssIdx = pAd->MlmeAux.RoamIdx;
+ pBss = &pAd->MlmeAux.RoamTab.BssEntry[BssIdx];
+
+ if (BssIdx < pAd->MlmeAux.RoamTab.BssNr)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - iterate BSS %ld of %d\n", BssIdx, pAd->MlmeAux.RoamTab.BssNr));
+
+ AsicSwitchChannel(pAd, pBss->Channel, FALSE);
+ AsicLockChannel(pAd, pBss->Channel);
+
+ // reassociate message has the same structure as associate message
+ AssocParmFill(pAd, &ReassocReq, pBss->Bssid, pBss->CapabilityInfo,
+ ASSOC_TIMEOUT, pAd->StaCfg.DefaultListenCount);
+ MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_REASSOC_REQ,
+ sizeof(MLME_REASSOC_REQ_STRUCT), &ReassocReq);
+
+ pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_REASSOC;
+ }
+ else // no more BSS
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("CNTL - All fast roaming failed, back to ch #%d\n",pAd->CommonCfg.Channel));
+ AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
+ AsicLockChannel(pAd, pAd->CommonCfg.Channel);
+ pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID JoinParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_JOIN_REQ_STRUCT *JoinReq,
+ IN ULONG BssIdx)
+{
+ JoinReq->BssIdx = BssIdx;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID ScanParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_SCAN_REQ_STRUCT *ScanReq,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen,
+ IN UCHAR BssType,
+ IN UCHAR ScanType)
+{
+ NdisZeroMemory(ScanReq->Ssid, MAX_LEN_OF_SSID);
+ ScanReq->SsidLen = SsidLen;
+ NdisMoveMemory(ScanReq->Ssid, Ssid, SsidLen);
+ ScanReq->BssType = BssType;
+ ScanReq->ScanType = ScanType;
+}
+
+#ifdef QOS_DLS_SUPPORT
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID DlsParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_DLS_REQ_STRUCT *pDlsReq,
+ IN PRT_802_11_DLS pDls,
+ IN USHORT reason)
+{
+ pDlsReq->pDLS = pDls;
+ pDlsReq->Reason = reason;
+}
+#endif // QOS_DLS_SUPPORT //
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID StartParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_START_REQ_STRUCT *StartReq,
+ IN CHAR Ssid[],
+ IN UCHAR SsidLen)
+{
+ ASSERT(SsidLen <= MAX_LEN_OF_SSID);
+ NdisMoveMemory(StartReq->Ssid, Ssid, SsidLen);
+ StartReq->SsidLen = SsidLen;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+VOID AuthParmFill(
+ IN PRTMP_ADAPTER pAd,
+ IN OUT MLME_AUTH_REQ_STRUCT *AuthReq,
+ IN PUCHAR pAddr,
+ IN USHORT Alg)
+{
+ COPY_MAC_ADDR(AuthReq->Addr, pAddr);
+ AuthReq->Alg = Alg;
+ AuthReq->Timeout = AUTH_TIMEOUT;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+#ifdef RT2860
+VOID ComposePsPoll(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisZeroMemory(&pAd->PsPollFrame, sizeof(PSPOLL_FRAME));
+ pAd->PsPollFrame.FC.Type = BTYPE_CNTL;
+ pAd->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL;
+ pAd->PsPollFrame.Aid = pAd->StaActive.Aid | 0xC000;
+ COPY_MAC_ADDR(pAd->PsPollFrame.Bssid, pAd->CommonCfg.Bssid);
+ COPY_MAC_ADDR(pAd->PsPollFrame.Ta, pAd->CurrentAddress);
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID ComposeNullFrame(
+ IN PRTMP_ADAPTER pAd)
+{
+ NdisZeroMemory(&pAd->NullFrame, sizeof(HEADER_802_11));
+ pAd->NullFrame.FC.Type = BTYPE_DATA;
+ pAd->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC;
+ pAd->NullFrame.FC.ToDs = 1;
+ COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid);
+ COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid);
+}
+#endif // RT2860 //
+
+
+
+
+/*
+ ==========================================================================
+ Description:
+ Pre-build a BEACON frame in the shared memory
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+*/
+ULONG MakeIbssBeacon(
+ IN PRTMP_ADAPTER pAd)
+{
+ UCHAR DsLen = 1, IbssLen = 2;
+ UCHAR LocalErpIe[3] = {IE_ERP, 1, 0x04};
+ HEADER_802_11 BcnHdr;
+ USHORT CapabilityInfo;
+ LARGE_INTEGER FakeTimestamp;
+ ULONG FrameLen = 0;
+ PTXWI_STRUC pTxWI = &pAd->BeaconTxWI;
+ CHAR *pBeaconFrame = pAd->BeaconBuf;
+ BOOLEAN Privacy;
+ UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR SupRateLen = 0;
+ UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR ExtRateLen = 0;
+ UCHAR RSNIe = IE_WPA;
+
+ if ((pAd->CommonCfg.PhyMode == PHY_11B) && (pAd->CommonCfg.Channel <= 14))
+ {
+ SupRate[0] = 0x82; // 1 mbps
+ SupRate[1] = 0x84; // 2 mbps
+ SupRate[2] = 0x8b; // 5.5 mbps
+ SupRate[3] = 0x96; // 11 mbps
+ SupRateLen = 4;
+ ExtRateLen = 0;
+ }
+ else if (pAd->CommonCfg.Channel > 14)
+ {
+ SupRate[0] = 0x8C; // 6 mbps, in units of 0.5 Mbps, basic rate
+ SupRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps
+ SupRate[2] = 0x98; // 12 mbps, in units of 0.5 Mbps, basic rate
+ SupRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps
+ SupRate[4] = 0xb0; // 24 mbps, in units of 0.5 Mbps, basic rate
+ SupRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps
+ SupRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps
+ SupRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps
+ SupRateLen = 8;
+ ExtRateLen = 0;
+
+ //
+ // Also Update MlmeRate & RtsRate for G only & A only
+ //
+ pAd->CommonCfg.MlmeRate = RATE_6;
+ pAd->CommonCfg.RtsRate = RATE_6;
+ pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
+ pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
+ pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
+ }
+ else
+ {
+ SupRate[0] = 0x82; // 1 mbps
+ SupRate[1] = 0x84; // 2 mbps
+ SupRate[2] = 0x8b; // 5.5 mbps
+ SupRate[3] = 0x96; // 11 mbps
+ SupRateLen = 4;
+
+ ExtRate[0] = 0x0C; // 6 mbps, in units of 0.5 Mbps,
+ ExtRate[1] = 0x12; // 9 mbps, in units of 0.5 Mbps
+ ExtRate[2] = 0x18; // 12 mbps, in units of 0.5 Mbps,
+ ExtRate[3] = 0x24; // 18 mbps, in units of 0.5 Mbps
+ ExtRate[4] = 0x30; // 24 mbps, in units of 0.5 Mbps,
+ ExtRate[5] = 0x48; // 36 mbps, in units of 0.5 Mbps
+ ExtRate[6] = 0x60; // 48 mbps, in units of 0.5 Mbps
+ ExtRate[7] = 0x6c; // 54 mbps, in units of 0.5 Mbps
+ ExtRateLen = 8;
+ }
+
+ pAd->StaActive.SupRateLen = SupRateLen;
+ NdisMoveMemory(pAd->StaActive.SupRate, SupRate, SupRateLen);
+ pAd->StaActive.ExtRateLen = ExtRateLen;
+ NdisMoveMemory(pAd->StaActive.ExtRate, ExtRate, ExtRateLen);
+
+ // compose IBSS beacon frame
+ MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, 0, BROADCAST_ADDR, pAd->CommonCfg.Bssid);
+ Privacy = (pAd->StaCfg.WepStatus == Ndis802_11Encryption1Enabled) ||
+ (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) ||
+ (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled);
+ CapabilityInfo = CAP_GENERATE(0, 1, Privacy, (pAd->CommonCfg.TxPreamble == Rt802_11PreambleShort), 0, 0);
+
+ MakeOutgoingFrame(pBeaconFrame, &FrameLen,
+ sizeof(HEADER_802_11), &BcnHdr,
+ TIMESTAMP_LEN, &FakeTimestamp,
+ 2, &pAd->CommonCfg.BeaconPeriod,
+ 2, &CapabilityInfo,
+ 1, &SsidIe,
+ 1, &pAd->CommonCfg.SsidLen,
+ pAd->CommonCfg.SsidLen, pAd->CommonCfg.Ssid,
+ 1, &SupRateIe,
+ 1, &SupRateLen,
+ SupRateLen, SupRate,
+ 1, &DsIe,
+ 1, &DsLen,
+ 1, &pAd->CommonCfg.Channel,
+ 1, &IbssIe,
+ 1, &IbssLen,
+ 2, &pAd->StaActive.AtimWin,
+ END_OF_ARGS);
+
+ // add ERP_IE and EXT_RAE IE of in 802.11g
+ if (ExtRateLen)
+ {
+ ULONG tmp;
+
+ MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp,
+ 3, LocalErpIe,
+ 1, &ExtRateIe,
+ 1, &ExtRateLen,
+ ExtRateLen, ExtRate,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+ // If adhoc secruity is set for WPA-None, append the cipher suite IE
+ if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPANone)
+ {
+ ULONG tmp;
+ RTMPMakeRSNIE(pAd, pAd->StaCfg.AuthMode, pAd->StaCfg.WepStatus, BSS0);
+
+ MakeOutgoingFrame(pBeaconFrame + FrameLen, &tmp,
+ 1, &RSNIe,
+ 1, &pAd->StaCfg.RSNIE_Len,
+ pAd->StaCfg.RSNIE_Len, pAd->StaCfg.RSN_IE,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ ULONG TmpLen;
+ UCHAR HtLen, HtLen1;
+
+#ifdef RT_BIG_ENDIAN
+ HT_CAPABILITY_IE HtCapabilityTmp;
+ ADD_HT_INFO_IE addHTInfoTmp;
+ USHORT b2lTmp, b2lTmp2;
+#endif
+
+ // add HT Capability IE
+ HtLen = sizeof(pAd->CommonCfg.HtCapability);
+ HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo);
+#ifndef RT_BIG_ENDIAN
+ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &pAd->CommonCfg.HtCapability,
+ 1, &AddHtInfoIe,
+ 1, &HtLen1,
+ HtLen1, &pAd->CommonCfg.AddHTInfo,
+ END_OF_ARGS);
+#else
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+ NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, HtLen1);
+ *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2));
+ *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3));
+
+ MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &HtCapabilityTmp,
+ 1, &AddHtInfoIe,
+ 1, &HtLen1,
+ HtLen1, &addHTInfoTmp,
+ END_OF_ARGS);
+#endif
+ FrameLen += TmpLen;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ //beacon use reserved WCID 0xff
+ if (pAd->CommonCfg.Channel > 14)
+ {
+ RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen,
+ PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &pAd->CommonCfg.MlmeTransmit);
+ }
+ else
+ {
+ // Set to use 1Mbps for Adhoc beacon.
+ HTTRANSMIT_SETTING Transmit;
+ Transmit.word = 0;
+ RTMPWriteTxWI(pAd, pTxWI, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0xff, FrameLen,
+ PID_MGMT, PID_BEACON, RATE_1, IFS_HTTXOP, FALSE, &Transmit);
+ }
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, pBeaconFrame, DIR_WRITE, FALSE);
+ RTMPWIEndianChange((PUCHAR)pTxWI, TYPE_TXWI);
+#endif
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MakeIbssBeacon (len=%ld), SupRateLen=%d, ExtRateLen=%d, Channel=%d, PhyMode=%d\n",
+ FrameLen, SupRateLen, ExtRateLen, pAd->CommonCfg.Channel, pAd->CommonCfg.PhyMode));
+ return FrameLen;
+}
+
+
diff --git a/drivers/staging/rt2860/sta/dls.c b/drivers/staging/rt2860/sta/dls.c
new file mode 100644
index 000000000000..78fb28976fd7
--- /dev/null
+++ b/drivers/staging/rt2860/sta/dls.c
@@ -0,0 +1,2201 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ dls.c
+
+ Abstract:
+ Handle WMM-DLS state machine
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Rory Chen 02-14-2006
+ Arvin Tai 06-03-2008 Modified for RT28xx
+ */
+
+#include "../rt_config.h"
+
+/*
+ ==========================================================================
+ Description:
+ dls state machine init, including state transition and timer init
+ Parameters:
+ Sm - pointer to the dls state machine
+ Note:
+ The state machine looks like this
+
+ DLS_IDLE
+ MT2_MLME_DLS_REQUEST MlmeDlsReqAction
+ MT2_PEER_DLS_REQUEST PeerDlsReqAction
+ MT2_PEER_DLS_RESPONSE PeerDlsRspAction
+ MT2_MLME_DLS_TEARDOWN MlmeTearDownAction
+ MT2_PEER_DLS_TEARDOWN PeerTearDownAction
+
+ IRQL = PASSIVE_LEVEL
+
+ ==========================================================================
+ */
+void DlsStateMachineInit(
+ IN PRTMP_ADAPTER pAd,
+ IN STATE_MACHINE *Sm,
+ OUT STATE_MACHINE_FUNC Trans[])
+{
+ UCHAR i;
+
+ StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE);
+
+ // the first column
+ StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction);
+ StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction);
+ StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction);
+ StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction);
+ StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction);
+
+ for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ pAd->StaCfg.DLSEntry[i].pAd = pAd;
+ RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE);
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeDlsReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ HEADER_802_11 DlsReqHdr;
+ PRT_802_11_DLS pDLS = NULL;
+ UCHAR Category = CATEGORY_DLS;
+ UCHAR Action = ACTION_DLS_REQUEST;
+ ULONG tmp;
+ USHORT reason;
+ ULONG Timeout;
+ BOOLEAN TimerCancelled;
+
+ if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n"));
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n"));
+ return;
+ }
+
+ ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+
+ // Build basic frame first
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &DlsReqHdr,
+ 1, &Category,
+ 1, &Action,
+ 6, &pDLS->MacAddr,
+ 6, pAd->CurrentAddress,
+ 2, &pAd->StaActive.CapabilityInfo,
+ 2, &pDLS->TimeOut,
+ 1, &SupRateIe,
+ 1, &pAd->MlmeAux.SupRateLen,
+ pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
+ END_OF_ARGS);
+
+ if (pAd->MlmeAux.ExtRateLen != 0)
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &ExtRateIe,
+ 1, &pAd->MlmeAux.ExtRateLen,
+ pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ UCHAR HtLen;
+
+#ifdef RT_BIG_ENDIAN
+ HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+
+ // add HT Capability IE
+ HtLen = sizeof(HT_CAPABILITY_IE);
+#ifndef RT_BIG_ENDIAN
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &pAd->CommonCfg.HtCapability,
+ END_OF_ARGS);
+#else
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &HtCapabilityTmp,
+ END_OF_ARGS);
+#endif
+ FrameLen = FrameLen + tmp;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
+ Timeout = DLS_TIMEOUT;
+ RTMPSetTimer(&pDLS->Timer, Timeout);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerDlsReqAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ USHORT StatusCode = MLME_SUCCESS;
+ HEADER_802_11 DlsRspHdr;
+ UCHAR Category = CATEGORY_DLS;
+ UCHAR Action = ACTION_DLS_RESPONSE;
+ ULONG tmp;
+ USHORT CapabilityInfo;
+ UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
+ USHORT DLSTimeOut;
+ SHORT i;
+ ULONG Timeout;
+ BOOLEAN TimerCancelled;
+ PRT_802_11_DLS pDLS = NULL;
+ UCHAR MaxSupportedRateIn500Kbps = 0;
+ UCHAR SupportedRatesLen;
+ UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR HtCapabilityLen;
+ HT_CAPABILITY_IE HtCapability;
+
+ if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut,
+ &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
+ return;
+
+ // supported rates array may not be sorted. sort it and find the maximum rate
+ for (i = 0; i < SupportedRatesLen; i++)
+ {
+ if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
+ MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n"));
+ return;
+ }
+
+ if (!INFRA_ON(pAd))
+ {
+ StatusCode = MLME_REQUEST_DECLINED;
+ }
+ else if (!pAd->CommonCfg.bWmmCapable)
+ {
+ StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA;
+ }
+ else if (!pAd->CommonCfg.bDLSCapable)
+ {
+ StatusCode = MLME_REQUEST_DECLINED;
+ }
+ else
+ {
+ // find table to update parameters
+ for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+ pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+ else
+ {
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+ }
+
+ pAd->StaCfg.DLSEntry[i].Sequence = 0;
+ pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
+ pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
+ if (HtCapabilityLen != 0)
+ pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+ else
+ pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+ pDLS = &pAd->StaCfg.DLSEntry[i];
+ break;
+ }
+ }
+
+ // can not find in table, create a new one
+ if (i < 0)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n"));
+ for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--)
+ {
+ if (!pAd->StaCfg.DLSEntry[i].Valid)
+ {
+ MAC_TABLE_ENTRY *pEntry;
+ UCHAR MaxSupportedRate = RATE_11;
+
+ if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+ }
+ else
+ {
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+ }
+
+ pAd->StaCfg.DLSEntry[i].Sequence = 0;
+ pAd->StaCfg.DLSEntry[i].Valid = TRUE;
+ pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
+ pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
+ NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN);
+ if (HtCapabilityLen != 0)
+ pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+ else
+ pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+ pDLS = &pAd->StaCfg.DLSEntry[i];
+ pEntry = MacTableInsertDlsEntry(pAd, SA, i);
+
+ switch (MaxSupportedRateIn500Kbps)
+ {
+ case 108: MaxSupportedRate = RATE_54; break;
+ case 96: MaxSupportedRate = RATE_48; break;
+ case 72: MaxSupportedRate = RATE_36; break;
+ case 48: MaxSupportedRate = RATE_24; break;
+ case 36: MaxSupportedRate = RATE_18; break;
+ case 24: MaxSupportedRate = RATE_12; break;
+ case 18: MaxSupportedRate = RATE_9; break;
+ case 12: MaxSupportedRate = RATE_6; break;
+ case 22: MaxSupportedRate = RATE_11; break;
+ case 11: MaxSupportedRate = RATE_5_5; break;
+ case 4: MaxSupportedRate = RATE_2; break;
+ case 2: MaxSupportedRate = RATE_1; break;
+ default: MaxSupportedRate = RATE_11; break;
+ }
+
+ pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
+
+ if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
+ pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
+ pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ pEntry->HTPhyMode.field.MODE = MODE_CCK;
+ pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ pEntry->HTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ }
+
+ pEntry->MaxHTPhyMode.field.BW = BW_20;
+ pEntry->MinHTPhyMode.field.BW = BW_20;
+
+#ifdef DOT11_N_SUPPORT
+ pEntry->HTCapability.MCSSet[0] = 0;
+ pEntry->HTCapability.MCSSet[1] = 0;
+
+ // If this Entry supports 802.11n, upgrade to HT rate.
+ if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ UCHAR j, bitmask; //k,bitmask;
+ CHAR ii;
+
+ DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
+ SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+ if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+ pAd->MacTab.fAnyStationNonGF = TRUE;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+ }
+
+ if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+ {
+ pEntry->MaxHTPhyMode.field.BW= BW_40;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.BW = BW_20;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
+ pAd->MacTab.fAnyStation20Only = TRUE;
+ }
+
+ // find max fixed rate
+ for (ii=15; ii>=0; ii--)
+ {
+ j = ii/8;
+ bitmask = (1<<(ii-(j*8)));
+ if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
+ {
+ pEntry->MaxHTPhyMode.field.MCS = ii;
+ break;
+ }
+ if (ii==0)
+ break;
+ }
+
+
+ if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
+ {
+
+ printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS);
+ if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
+ {
+ // Fix MCS as HT Duplicated Mode
+ pEntry->MaxHTPhyMode.field.BW = 1;
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+ pEntry->MaxHTPhyMode.field.STBC = 0;
+ pEntry->MaxHTPhyMode.field.ShortGI = 0;
+ pEntry->MaxHTPhyMode.field.MCS = 32;
+ }
+ else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
+ {
+ // STA supports fixed MCS
+ pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ }
+ }
+
+ pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+ pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
+ pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
+ pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
+ pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+ if (HtCapability.HtCapInfo.ShortGIfor20)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+ if (HtCapability.HtCapInfo.ShortGIfor40)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+ if (HtCapability.HtCapInfo.TxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+ if (HtCapability.HtCapInfo.RxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+ if (HtCapability.ExtHtCapInfo.PlusHTC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+ if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+ if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+
+ NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
+ }
+#endif // DOT11_N_SUPPORT //
+
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+ pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+
+ if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+ {
+ PUCHAR pTable;
+ UCHAR TableSize = 0;
+
+ MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
+ pEntry->bAutoTxRateSwitch = TRUE;
+ }
+ else
+ {
+ pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
+ pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ pEntry->bAutoTxRateSwitch = FALSE;
+
+ RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+ }
+ pEntry->RateLen = SupportedRatesLen;
+
+ break;
+ }
+ }
+ }
+ StatusCode = MLME_SUCCESS;
+
+ // can not find in table, create a new one
+ if (i < 0)
+ {
+ StatusCode = MLME_QOS_UNSPECIFY;
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY));
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n",
+ i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+ }
+ }
+
+ ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+
+ // Build basic frame first
+ if (StatusCode == MLME_SUCCESS)
+ {
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &DlsRspHdr,
+ 1, &Category,
+ 1, &Action,
+ 2, &StatusCode,
+ 6, SA,
+ 6, pAd->CurrentAddress,
+ 2, &pAd->StaActive.CapabilityInfo,
+ 1, &SupRateIe,
+ 1, &pAd->MlmeAux.SupRateLen,
+ pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
+ END_OF_ARGS);
+
+ if (pAd->MlmeAux.ExtRateLen != 0)
+ {
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &ExtRateIe,
+ 1, &pAd->MlmeAux.ExtRateLen,
+ pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
+ END_OF_ARGS);
+ FrameLen += tmp;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ UCHAR HtLen;
+
+#ifdef RT_BIG_ENDIAN
+ HT_CAPABILITY_IE HtCapabilityTmp;
+#endif
+
+ // add HT Capability IE
+ HtLen = sizeof(HT_CAPABILITY_IE);
+#ifndef RT_BIG_ENDIAN
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &pAd->CommonCfg.HtCapability,
+ END_OF_ARGS);
+#else
+ NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
+ *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
+ *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
+
+ MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
+ 1, &HtCapIe,
+ 1, &HtLen,
+ HtLen, &HtCapabilityTmp,
+ END_OF_ARGS);
+#endif
+ FrameLen = FrameLen + tmp;
+ }
+#endif // DOT11_N_SUPPORT //
+
+ if (pDLS && (pDLS->Status != DLS_FINISH))
+ {
+ RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
+ Timeout = DLS_TIMEOUT;
+ RTMPSetTimer(&pDLS->Timer, Timeout);
+ }
+ }
+ else
+ {
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &DlsRspHdr,
+ 1, &Category,
+ 1, &Action,
+ 2, &StatusCode,
+ 6, SA,
+ 6, pAd->CurrentAddress,
+ END_OF_ARGS);
+ }
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerDlsRspAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ USHORT CapabilityInfo;
+ UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
+ USHORT StatusCode;
+ SHORT i;
+ BOOLEAN TimerCancelled;
+ UCHAR MaxSupportedRateIn500Kbps = 0;
+ UCHAR SupportedRatesLen;
+ UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
+ UCHAR HtCapabilityLen;
+ HT_CAPABILITY_IE HtCapability;
+
+ if (!pAd->CommonCfg.bDLSCapable)
+ return;
+
+ if (!INFRA_ON(pAd))
+ return;
+
+ if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode,
+ &SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
+ return;
+
+ // supported rates array may not be sorted. sort it and find the maximum rate
+ for (i=0; i<SupportedRatesLen; i++)
+ {
+ if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
+ MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n",
+ SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode, CapabilityInfo));
+
+ for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ if (StatusCode == MLME_SUCCESS)
+ {
+ MAC_TABLE_ENTRY *pEntry;
+ UCHAR MaxSupportedRate = RATE_11;
+
+ pEntry = MacTableInsertDlsEntry(pAd, SA, i);
+
+ switch (MaxSupportedRateIn500Kbps)
+ {
+ case 108: MaxSupportedRate = RATE_54; break;
+ case 96: MaxSupportedRate = RATE_48; break;
+ case 72: MaxSupportedRate = RATE_36; break;
+ case 48: MaxSupportedRate = RATE_24; break;
+ case 36: MaxSupportedRate = RATE_18; break;
+ case 24: MaxSupportedRate = RATE_12; break;
+ case 18: MaxSupportedRate = RATE_9; break;
+ case 12: MaxSupportedRate = RATE_6; break;
+ case 22: MaxSupportedRate = RATE_11; break;
+ case 11: MaxSupportedRate = RATE_5_5; break;
+ case 4: MaxSupportedRate = RATE_2; break;
+ case 2: MaxSupportedRate = RATE_1; break;
+ default: MaxSupportedRate = RATE_11; break;
+ }
+
+ pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
+
+ if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
+ pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
+ pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ pEntry->HTPhyMode.field.MODE = MODE_CCK;
+ pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ pEntry->HTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ }
+
+ pEntry->MaxHTPhyMode.field.BW = BW_20;
+ pEntry->MinHTPhyMode.field.BW = BW_20;
+
+#ifdef DOT11_N_SUPPORT
+ pEntry->HTCapability.MCSSet[0] = 0;
+ pEntry->HTCapability.MCSSet[1] = 0;
+
+ // If this Entry supports 802.11n, upgrade to HT rate.
+ if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ UCHAR j, bitmask; //k,bitmask;
+ CHAR ii;
+
+ DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
+ SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+ if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+ pAd->MacTab.fAnyStationNonGF = TRUE;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+ }
+
+ if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+ {
+ pEntry->MaxHTPhyMode.field.BW= BW_40;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.BW = BW_20;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
+ pAd->MacTab.fAnyStation20Only = TRUE;
+ }
+
+ // find max fixed rate
+ for (ii=15; ii>=0; ii--)
+ {
+ j = ii/8;
+ bitmask = (1<<(ii-(j*8)));
+ if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
+ {
+ pEntry->MaxHTPhyMode.field.MCS = ii;
+ break;
+ }
+ if (ii==0)
+ break;
+ }
+
+ if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
+ {
+ if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
+ {
+ // Fix MCS as HT Duplicated Mode
+ pEntry->MaxHTPhyMode.field.BW = 1;
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+ pEntry->MaxHTPhyMode.field.STBC = 0;
+ pEntry->MaxHTPhyMode.field.ShortGI = 0;
+ pEntry->MaxHTPhyMode.field.MCS = 32;
+ }
+ else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
+ {
+ // STA supports fixed MCS
+ pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ }
+ }
+
+ pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+ pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
+ pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
+ pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
+ pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+ if (HtCapability.HtCapInfo.ShortGIfor20)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+ if (HtCapability.HtCapInfo.ShortGIfor40)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+ if (HtCapability.HtCapInfo.TxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+ if (HtCapability.HtCapInfo.RxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+ if (HtCapability.ExtHtCapInfo.PlusHTC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+ if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+ if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+
+ NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
+ }
+#endif // DOT11_N_SUPPORT //
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+ pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+
+ if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+ {
+ PUCHAR pTable;
+ UCHAR TableSize = 0;
+
+ MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
+ pEntry->bAutoTxRateSwitch = TRUE;
+ }
+ else
+ {
+ pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
+ pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ pEntry->bAutoTxRateSwitch = FALSE;
+
+ RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+ }
+ pEntry->RateLen = SupportedRatesLen;
+
+ if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+ {
+ // If support WPA or WPA2, start STAKey hand shake,
+ // If failed hand shake, just tear down peer DLS
+ if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
+ {
+ MLME_DLS_REQ_STRUCT MlmeDlsReq;
+ USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
+
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
+ }
+ else
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
+ }
+ }
+ else
+ {
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+ }
+
+ //initialize seq no for DLS frames.
+ pAd->StaCfg.DLSEntry[i].Sequence = 0;
+ if (HtCapabilityLen != 0)
+ pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+ else
+ pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+ }
+ else
+ {
+ // DLS setup procedure failed.
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
+ }
+ }
+ }
+
+ if (i >= MAX_NUM_OF_INIT_DLS_ENTRY)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n"));
+ for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ if (StatusCode == MLME_SUCCESS)
+ {
+ MAC_TABLE_ENTRY *pEntry;
+ UCHAR MaxSupportedRate = RATE_11;
+
+ pEntry = MacTableInsertDlsEntry(pAd, SA, i);
+
+ switch (MaxSupportedRateIn500Kbps)
+ {
+ case 108: MaxSupportedRate = RATE_54; break;
+ case 96: MaxSupportedRate = RATE_48; break;
+ case 72: MaxSupportedRate = RATE_36; break;
+ case 48: MaxSupportedRate = RATE_24; break;
+ case 36: MaxSupportedRate = RATE_18; break;
+ case 24: MaxSupportedRate = RATE_12; break;
+ case 18: MaxSupportedRate = RATE_9; break;
+ case 12: MaxSupportedRate = RATE_6; break;
+ case 22: MaxSupportedRate = RATE_11; break;
+ case 11: MaxSupportedRate = RATE_5_5; break;
+ case 4: MaxSupportedRate = RATE_2; break;
+ case 2: MaxSupportedRate = RATE_1; break;
+ default: MaxSupportedRate = RATE_11; break;
+ }
+
+ pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
+
+ if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
+ pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
+ pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ pEntry->HTPhyMode.field.MODE = MODE_CCK;
+ pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ pEntry->HTPhyMode.field.MODE = MODE_OFDM;
+ pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
+ }
+
+ pEntry->MaxHTPhyMode.field.BW = BW_20;
+ pEntry->MinHTPhyMode.field.BW = BW_20;
+
+#ifdef DOT11_N_SUPPORT
+ pEntry->HTCapability.MCSSet[0] = 0;
+ pEntry->HTCapability.MCSSet[1] = 0;
+
+ // If this Entry supports 802.11n, upgrade to HT rate.
+ if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
+ {
+ UCHAR j, bitmask; //k,bitmask;
+ CHAR ii;
+
+ DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
+ SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+
+ if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+ pAd->MacTab.fAnyStationNonGF = TRUE;
+ pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
+ }
+
+ if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
+ {
+ pEntry->MaxHTPhyMode.field.BW= BW_40;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
+ }
+ else
+ {
+ pEntry->MaxHTPhyMode.field.BW = BW_20;
+ pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
+ pAd->MacTab.fAnyStation20Only = TRUE;
+ }
+
+ // find max fixed rate
+ for (ii=15; ii>=0; ii--)
+ {
+ j = ii/8;
+ bitmask = (1<<(ii-(j*8)));
+ if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
+ {
+ pEntry->MaxHTPhyMode.field.MCS = ii;
+ break;
+ }
+ if (ii==0)
+ break;
+ }
+
+ if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
+ {
+ printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
+ pAd->StaCfg.DesiredTransmitSetting.field.MCS);
+ if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
+ {
+ // Fix MCS as HT Duplicated Mode
+ pEntry->MaxHTPhyMode.field.BW = 1;
+ pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
+ pEntry->MaxHTPhyMode.field.STBC = 0;
+ pEntry->MaxHTPhyMode.field.ShortGI = 0;
+ pEntry->MaxHTPhyMode.field.MCS = 32;
+ }
+ else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
+ {
+ // STA supports fixed MCS
+ pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ }
+ }
+
+ pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
+ pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
+ pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
+ pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
+ pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+
+ if (HtCapability.HtCapInfo.ShortGIfor20)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
+ if (HtCapability.HtCapInfo.ShortGIfor40)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
+ if (HtCapability.HtCapInfo.TxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
+ if (HtCapability.HtCapInfo.RxSTBC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
+ if (HtCapability.ExtHtCapInfo.PlusHTC)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
+ if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
+ if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
+
+ NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
+ }
+#endif // DOT11_N_SUPPORT //
+
+ pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
+ pEntry->CurrTxRate = pEntry->MaxSupportedRate;
+ CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
+
+ if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
+ {
+ PUCHAR pTable;
+ UCHAR TableSize = 0;
+
+ MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
+ pEntry->bAutoTxRateSwitch = TRUE;
+ }
+ else
+ {
+ pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
+ pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
+ pEntry->bAutoTxRateSwitch = FALSE;
+
+ RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
+ }
+ pEntry->RateLen = SupportedRatesLen;
+
+ if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
+ {
+ // If support WPA or WPA2, start STAKey hand shake,
+ // If failed hand shake, just tear down peer DLS
+ if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
+ {
+ MLME_DLS_REQ_STRUCT MlmeDlsReq;
+ USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
+
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
+ }
+ else
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
+ }
+ }
+ else
+ {
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
+ }
+ pAd->StaCfg.DLSEntry[i].Sequence = 0;
+ if (HtCapabilityLen != 0)
+ pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
+ else
+ pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
+ }
+ else
+ {
+ // DLS setup procedure failed.
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
+ }
+ }
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID MlmeDlsTearDownAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ UCHAR Category = CATEGORY_DLS;
+ UCHAR Action = ACTION_DLS_TEARDOWN;
+ USHORT ReasonCode = REASON_QOS_UNSPECIFY;
+ HEADER_802_11 DlsTearDownHdr;
+ PRT_802_11_DLS pDLS;
+ BOOLEAN TimerCancelled;
+ UCHAR i;
+
+ if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode));
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n"));
+ return;
+ }
+
+ ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+
+ // Build basic frame first
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &DlsTearDownHdr,
+ 1, &Category,
+ 1, &Action,
+ 6, &pDLS->MacAddr,
+ 6, pAd->CurrentAddress,
+ 2, &ReasonCode,
+ END_OF_ARGS);
+
+ MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+ RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
+
+ // Remove key in local dls table entry
+ for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+
+ // clear peer dls table entry
+ for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID PeerDlsTearDownAction(
+ IN PRTMP_ADAPTER pAd,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
+ USHORT ReasonCode;
+ UINT i;
+ BOOLEAN TimerCancelled;
+
+ if (!pAd->CommonCfg.bDLSCapable)
+ return;
+
+ if (!INFRA_ON(pAd))
+ return;
+
+ if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode));
+
+ // clear local dls table entry
+ for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+ //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+ MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+
+ // clear peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+ //AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+ //AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
+ MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID RTMPCheckDLSTimeOut(
+ IN PRTMP_ADAPTER pAd)
+{
+ ULONG i;
+ MLME_DLS_REQ_STRUCT MlmeDlsReq;
+ USHORT reason = REASON_QOS_UNSPECIFY;
+
+ if (! pAd->CommonCfg.bDLSCapable)
+ return;
+
+ if (! INFRA_ON(pAd))
+ return;
+
+ // If timeout value is equaled to zero, it means always not be timeout.
+
+ // update local dls table entry
+ for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+ && (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
+ {
+ pAd->StaCfg.DLSEntry[i].CountDownTimer --;
+
+ if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
+ {
+ reason = REASON_QOS_REQUEST_TIMEOUT;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ }
+ }
+ }
+
+ // update peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+ && (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
+ {
+ pAd->StaCfg.DLSEntry[i].CountDownTimer --;
+
+ if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
+ {
+ reason = REASON_QOS_REQUEST_TIMEOUT;
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ }
+ }
+ }
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+BOOLEAN RTMPRcvFrameDLSCheck(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHeader,
+ IN ULONG Len,
+ IN PRT28XX_RXD_STRUC pRxD)
+{
+ ULONG i;
+ BOOLEAN bFindEntry = FALSE;
+ BOOLEAN bSTAKeyFrame = FALSE;
+ PEAPOL_PACKET pEap;
+ PUCHAR pProto, pAddr = NULL;
+ PUCHAR pSTAKey = NULL;
+ UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
+ UCHAR Mic[16], OldMic[16];
+ UCHAR digest[80];
+ UCHAR DlsPTK[80];
+ UCHAR temp[64];
+ BOOLEAN TimerCancelled;
+ CIPHER_KEY PairwiseKey;
+
+
+ if (! pAd->CommonCfg.bDLSCapable)
+ return bSTAKeyFrame;
+
+ if (! INFRA_ON(pAd))
+ return bSTAKeyFrame;
+
+ if (! (pHeader->FC.SubType & 0x08))
+ return bSTAKeyFrame;
+
+ if (Len < LENGTH_802_11 + 6 + 2 + 2)
+ return bSTAKeyFrame;
+
+ pProto = (PUCHAR)pHeader + LENGTH_802_11 + 2 + 6; // QOS Control field , 0xAA 0xAA 0xAA 0x00 0x00 0x00
+ pAddr = pHeader->Addr2;
+
+ // L2PAD bit on will pad 2 bytes at LLC
+ if (pRxD->L2PAD)
+ {
+ pProto += 2;
+ }
+
+ if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
+ {
+ pEap = (PEAPOL_PACKET) (pProto + 2);
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len,
+ (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16),
+ pEap->KeyDesc.KeyInfo.KeyMic,
+ pEap->KeyDesc.KeyInfo.Install,
+ pEap->KeyDesc.KeyInfo.KeyAck,
+ pEap->KeyDesc.KeyInfo.Secure,
+ pEap->KeyDesc.KeyInfo.EKD_DL,
+ pEap->KeyDesc.KeyInfo.Error,
+ pEap->KeyDesc.KeyInfo.Request));
+
+ if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic
+ && pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure
+ && pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request)
+ {
+ // First validate replay counter, only accept message with larger replay counter
+ // Let equal pass, some AP start with all zero replay counter
+ NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
+ if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
+ (RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
+ return bSTAKeyFrame;
+
+ //RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+ RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
+ pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
+ pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5],
+ pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
+
+ // put these code segment to get the replay counter
+ if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
+ return bSTAKeyFrame;
+
+ // Check MIC value
+ // Save the MIC and replace with zero
+ // use proprietary PTK
+ NdisZeroMemory(temp, 64);
+ NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+ WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
+
+ NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+ NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+ if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ // AES
+ HMAC_SHA1((PUCHAR) pEap, pEap->Body_Len[1] + 4, DlsPTK, LEN_EAP_MICK, digest);
+ NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
+ }
+ else
+ {
+ hmac_md5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic);
+ }
+
+ if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n"));
+ return bSTAKeyFrame;
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n"));
+#if 1
+ if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C)
+ && (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02))
+ {
+ pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
+ pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n",
+ pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
+
+ bSTAKeyFrame = TRUE;
+ }
+#else
+ if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0F)
+ && (pEap->KeyDesc.KeyData[4] == 0xAC) && (pEap->KeyDesc.KeyData[5] == 0x02))
+ {
+ pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
+ pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%d, KeyDataLen=%d\n",
+ pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
+
+ bSTAKeyFrame = TRUE;
+ }
+#endif
+
+ }
+ else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE))
+ {
+#if 0
+ RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+
+#endif
+ RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
+ pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
+ pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5],
+ pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
+
+ }
+ }
+
+ // If timeout value is equaled to zero, it means always not be timeout.
+ // update local dls table entry
+ for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ if (bSTAKeyFrame)
+ {
+ PMAC_TABLE_ENTRY pEntry;
+
+ // STAKey frame, add pairwise key table
+ pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+
+ PairwiseKey.KeyLen = LEN_TKIP_EK;
+ NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
+ NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
+ NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
+
+ PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
+
+ pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
+ //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast
+ //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
+ // Add Pair-wise key to Asic
+#ifdef RT2860
+ AsicAddPairwiseKeyEntry(pAd,
+ pAd->StaCfg.DLSEntry[i].MacAddr,
+ (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
+ &PairwiseKey);
+
+ RTMPAddWcidAttributeEntry(pAd,
+ BSS0,
+ 0,
+ PairwiseKey.CipherAlg,
+ pEntry);
+
+#endif // RT2860 //
+ NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n"));
+
+ RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n"));
+ }
+ else
+ {
+ // Data frame, update timeout value
+ if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+ {
+ pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+ //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
+ }
+ }
+
+ bFindEntry = TRUE;
+ }
+ }
+
+ // update peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ if (bSTAKeyFrame)
+ {
+ PMAC_TABLE_ENTRY pEntry = NULL;
+
+ // STAKey frame, add pairwise key table, and send STAkey Msg-2
+ pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
+ RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
+
+ PairwiseKey.KeyLen = LEN_TKIP_EK;
+ NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
+ NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
+ NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
+
+ PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
+
+ pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
+ //AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast
+ //AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
+ // Add Pair-wise key to Asic
+#ifdef RT2860
+ AsicAddPairwiseKeyEntry(pAd,
+ pAd->StaCfg.DLSEntry[i].MacAddr,
+ (UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
+ &PairwiseKey);
+
+ RTMPAddWcidAttributeEntry(pAd,
+ BSS0,
+ 0,
+ PairwiseKey.CipherAlg,
+ pEntry);
+#endif // RT2860 //
+ NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n"));
+
+ // If support WPA or WPA2, start STAKey hand shake,
+ // If failed hand shake, just tear down peer DLS
+ if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS)
+ {
+ MLME_DLS_REQ_STRUCT MlmeDlsReq;
+ USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
+
+ pAd->StaCfg.DLSEntry[i].Valid = FALSE;
+ pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
+ DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n"));
+ }
+ }
+ else
+ {
+ // Data frame, update timeout value
+ if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+ {
+ pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
+ }
+ }
+
+ bFindEntry = TRUE;
+ }
+ }
+
+
+ return bSTAKeyFrame;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Check if the frame can be sent through DLS direct link interface
+
+ Arguments:
+ pAd Pointer to adapter
+
+ Return Value:
+ DLS entry index
+
+ Note:
+
+ ========================================================================
+*/
+INT RTMPCheckDLSFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA)
+{
+ INT rval = -1;
+ INT i;
+
+ if (!pAd->CommonCfg.bDLSCapable)
+ return rval;
+
+ if (!INFRA_ON(pAd))
+ return rval;
+
+ do{
+ // check local dls table entry
+ for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+ MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ rval = i;
+ break;
+ }
+ }
+
+ // check peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
+ MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ rval = i;
+ break;
+ }
+ }
+ } while (FALSE);
+
+ return rval;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+VOID RTMPSendDLSTearDownFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA)
+{
+ PUCHAR pOutBuffer = NULL;
+ NDIS_STATUS NStatus;
+ HEADER_802_11 DlsTearDownHdr;
+ ULONG FrameLen = 0;
+ USHORT Reason = REASON_QOS_QSTA_LEAVING_QBSS;
+ UCHAR Category = CATEGORY_DLS;
+ UCHAR Action = ACTION_DLS_TEARDOWN;
+ UCHAR i = 0;
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n"));
+
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n"));
+ return;
+ }
+
+ ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(HEADER_802_11), &DlsTearDownHdr,
+ 1, &Category,
+ 1, &Action,
+ 6, pDA,
+ 6, pAd->CurrentAddress,
+ 2, &Reason,
+ END_OF_ARGS);
+
+ MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ // Remove key in local dls table entry
+ for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+ && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+
+ // Remove key in peer dls table entry
+ for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
+ && MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
+ {
+ MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
+ }
+ }
+
+ DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i));
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+NDIS_STATUS RTMPSendSTAKeyRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA)
+{
+ UCHAR Header802_3[14];
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ EAPOL_PACKET Packet;
+ UCHAR Mic[16];
+ UCHAR digest[80];
+ PUCHAR pOutBuffer = NULL;
+ PNDIS_PACKET pNdisPacket;
+ UCHAR temp[64];
+ UCHAR DlsPTK[80];
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
+
+ pAd->Sequence ++;
+ MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+ // Zero message body
+ NdisZeroMemory(&Packet, sizeof(Packet));
+ Packet.ProVer = EAPOL_VER;
+ Packet.ProType = EAPOLKey;
+ Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE andPeer MAC address
+
+ // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ Packet.KeyDesc.Type = WPA1_KEY_DESC;
+ }
+ else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ Packet.KeyDesc.Type = WPA2_KEY_DESC;
+ }
+
+ // Key descriptor version
+ Packet.KeyDesc.KeyInfo.KeyDescVer =
+ (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
+
+ Packet.KeyDesc.KeyInfo.KeyMic = 1;
+ Packet.KeyDesc.KeyInfo.Secure = 1;
+ Packet.KeyDesc.KeyInfo.Request = 1;
+
+ Packet.KeyDesc.KeyDataLen[1] = 12;
+
+ // use our own OUI to distinguish proprietary with standard.
+ Packet.KeyDesc.KeyData[0] = 0xDD;
+ Packet.KeyDesc.KeyData[1] = 0x0A;
+ Packet.KeyDesc.KeyData[2] = 0x00;
+ Packet.KeyDesc.KeyData[3] = 0x0C;
+ Packet.KeyDesc.KeyData[4] = 0x43;
+ Packet.KeyDesc.KeyData[5] = 0x03;
+ NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
+
+ NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
+
+ // Allocate buffer for transmitting message
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return NStatus;
+
+ // Prepare EAPOL frame for MIC calculation
+ // Be careful, only EAPOL frame is counted for MIC calculation
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ Packet.Body_Len[1] + 4, &Packet,
+ END_OF_ARGS);
+
+ // use proprietary PTK
+ NdisZeroMemory(temp, 64);
+ NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+ WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
+
+ // calculate MIC
+ if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ // AES
+ NdisZeroMemory(digest, sizeof(digest));
+ HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest);
+ NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
+ }
+ else
+ {
+ NdisZeroMemory(Mic, sizeof(Mic));
+ hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+ NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+ }
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(Header802_3), Header802_3,
+ Packet.Body_Len[1] + 4, &Packet,
+ END_OF_ARGS);
+
+ NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
+ if (NStatus == NDIS_STATUS_SUCCESS)
+ {
+ RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
+ STASendPacket(pAd, pNdisPacket);
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ }
+
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
+
+ return NStatus;
+}
+
+/*
+ ==========================================================================
+ Description:
+
+ IRQL = DISPATCH_LEVEL
+
+ ==========================================================================
+ */
+NDIS_STATUS RTMPSendSTAKeyHandShake(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA)
+{
+ UCHAR Header802_3[14];
+ NDIS_STATUS NStatus;
+ ULONG FrameLen = 0;
+ EAPOL_PACKET Packet;
+ UCHAR Mic[16];
+ UCHAR digest[80];
+ PUCHAR pOutBuffer = NULL;
+ PNDIS_PACKET pNdisPacket;
+ UCHAR temp[64];
+ UCHAR DlsPTK[80]; // Due to dirver can not get PTK, use proprietary PTK
+
+ DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
+
+ pAd->Sequence ++;
+ MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
+
+ // Zero message body
+ NdisZeroMemory(&Packet, sizeof(Packet));
+ Packet.ProVer = EAPOL_VER;
+ Packet.ProType = EAPOLKey;
+ Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE and Peer MAC address
+
+ // STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
+ if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ Packet.KeyDesc.Type = WPA1_KEY_DESC;
+ }
+ else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ Packet.KeyDesc.Type = WPA2_KEY_DESC;
+ }
+
+ // Key descriptor version
+ Packet.KeyDesc.KeyInfo.KeyDescVer =
+ (((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
+
+ Packet.KeyDesc.KeyInfo.KeyMic = 1;
+ Packet.KeyDesc.KeyInfo.Secure = 1;
+
+ Packet.KeyDesc.KeyDataLen[1] = 12;
+
+ // use our own OUI to distinguish proprietary with standard.
+ Packet.KeyDesc.KeyData[0] = 0xDD;
+ Packet.KeyDesc.KeyData[1] = 0x0A;
+ Packet.KeyDesc.KeyData[2] = 0x00;
+ Packet.KeyDesc.KeyData[3] = 0x0C;
+ Packet.KeyDesc.KeyData[4] = 0x43;
+ Packet.KeyDesc.KeyData[5] = 0x03;
+ NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
+
+ NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
+
+ // Allocate buffer for transmitting message
+ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
+ if (NStatus != NDIS_STATUS_SUCCESS)
+ return NStatus;
+
+ // Prepare EAPOL frame for MIC calculation
+ // Be careful, only EAPOL frame is counted for MIC calculation
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ Packet.Body_Len[1] + 4, &Packet,
+ END_OF_ARGS);
+
+ // use proprietary PTK
+ NdisZeroMemory(temp, 64);
+ NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+ WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
+
+ // calculate MIC
+ if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ // AES
+ NdisZeroMemory(digest, sizeof(digest));
+ HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest);
+ NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
+ }
+ else
+ {
+ NdisZeroMemory(Mic, sizeof(Mic));
+ hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
+ NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
+ }
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ sizeof(Header802_3), Header802_3,
+ Packet.Body_Len[1] + 4, &Packet,
+ END_OF_ARGS);
+
+ NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
+ if (NStatus == NDIS_STATUS_SUCCESS)
+ {
+ RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
+ STASendPacket(pAd, pNdisPacket);
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+ }
+
+ MlmeFreeMemory(pAd, pOutBuffer);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
+
+ return NStatus;
+}
+
+VOID DlsTimeoutAction(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ MLME_DLS_REQ_STRUCT MlmeDlsReq;
+ USHORT reason;
+ PRT_802_11_DLS pDLS = (PRT_802_11_DLS)FunctionContext;
+ PRTMP_ADAPTER pAd = pDLS->pAd;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5]));
+
+ if ((pDLS) && (pDLS->Valid))
+ {
+ reason = REASON_QOS_REQUEST_TIMEOUT;
+ pDLS->Valid = FALSE;
+ pDLS->Status = DLS_NONE;
+ DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason);
+ MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
+ RT28XX_MLME_HANDLER(pAd);
+ }
+}
+
+/*
+================================================================
+Description : because DLS and CLI share the same WCID table in ASIC.
+Mesh entry also insert to pAd->MacTab.content[]. Such is marked as ValidAsDls = TRUE.
+Also fills the pairwise key.
+Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls
+from index MAX_AID_BA.
+================================================================
+*/
+MAC_TABLE_ENTRY *MacTableInsertDlsEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN UINT DlsEntryIdx)
+{
+ PMAC_TABLE_ENTRY pEntry = NULL;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n"));
+ // if FULL, return
+ if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
+ return NULL;
+
+ do
+ {
+ if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL)
+ break;
+
+ // allocate one MAC entry
+ pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE);
+ if (pEntry)
+ {
+ pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid;
+ pEntry->MatchDlsEntryIdx = DlsEntryIdx;
+ pEntry->AuthMode = pAd->StaCfg.AuthMode;
+ pEntry->WepStatus = pAd->StaCfg.WepStatus;
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size));
+
+ // If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry
+ if ((pEntry->ValidAsDls) && (pEntry->WepStatus == Ndis802_11WEPEnabled))
+ {
+ UCHAR KeyIdx = 0;
+ UCHAR CipherAlg = 0;
+
+ KeyIdx = pAd->StaCfg.DefaultKeyId;
+
+ CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+
+ RTMPAddWcidAttributeEntry(pAd,
+ BSS0,
+ pAd->StaCfg.DefaultKeyId,
+ pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
+ pEntry);
+ }
+
+ break;
+ }
+ } while(FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n"));
+
+ return pEntry;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Delete all Mesh Entry in pAd->MacTab
+ ==========================================================================
+ */
+BOOLEAN MacTableDeleteDlsEntry(
+ IN PRTMP_ADAPTER pAd,
+ IN USHORT wcid,
+ IN PUCHAR pAddr)
+{
+ DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n"));
+
+ if (!VALID_WCID(wcid))
+ return FALSE;
+
+ MacTableDeleteEntry(pAd, wcid, pAddr);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n"));
+
+ return TRUE;
+}
+
+MAC_TABLE_ENTRY *DlsEntryTableLookup(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pAddr,
+ IN BOOLEAN bResetIdelCount)
+{
+ ULONG HashIdx;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+
+ RTMP_SEM_LOCK(&pAd->MacTabLock);
+ HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
+ pEntry = pAd->MacTab.Hash[HashIdx];
+
+ while (pEntry)
+ {
+ if ((pEntry->ValidAsDls == TRUE)
+ && MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
+ {
+ if(bResetIdelCount)
+ pEntry->NoDataIdleCount = 0;
+ break;
+ }
+ else
+ pEntry = pEntry->pNext;
+ }
+
+ RTMP_SEM_UNLOCK(&pAd->MacTabLock);
+ return pEntry;
+}
+
+MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR wcid,
+ IN PUCHAR pAddr,
+ IN BOOLEAN bResetIdelCount)
+{
+ ULONG DLsIndex;
+ PMAC_TABLE_ENTRY pCurEntry = NULL;
+ PMAC_TABLE_ENTRY pEntry = NULL;
+
+ if (!VALID_WCID(wcid))
+ return NULL;
+
+ RTMP_SEM_LOCK(&pAd->MacTabLock);
+
+ do
+ {
+ pCurEntry = &pAd->MacTab.Content[wcid];
+
+ DLsIndex = 0xff;
+ if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE))
+ {
+ DLsIndex = pCurEntry->MatchDlsEntryIdx;
+ }
+
+ if (DLsIndex == 0xff)
+ break;
+
+ if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr))
+ {
+ if(bResetIdelCount)
+ pCurEntry->NoDataIdleCount = 0;
+ pEntry = pCurEntry;
+ break;
+ }
+ } while(FALSE);
+
+ RTMP_SEM_UNLOCK(&pAd->MacTabLock);
+
+ return pEntry;
+}
+
+INT Set_DlsEntryInfo_Display_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ INT i;
+
+ printk("\n%-19s%-8s\n", "MAC", "TIMEOUT\n");
+ for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
+ {
+ if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
+ {
+ PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID];
+
+ printk("%02x:%02x:%02x:%02x:%02x:%02x ",
+ pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2],
+ pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5]);
+ printk("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut);
+
+ printk("\n");
+ printk("\n%-19s%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n",
+ "MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC");
+ printk("%02X:%02X:%02X:%02X:%02X:%02X ",
+ pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
+ pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
+ printk("%-4d", (int)pEntry->Aid);
+ printk("%-4d", (int)pEntry->apidx);
+ printk("%-4d", (int)pEntry->PsMode);
+ printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE));
+ printk("%-8d", (int)pEntry->MmpsMode);
+ printk("%-7d", pEntry->RssiSample.AvgRssi0);
+ printk("%-7d", pEntry->RssiSample.AvgRssi1);
+ printk("%-7d", pEntry->RssiSample.AvgRssi2);
+ printk("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE));
+ printk("%-6s", GetBW(pEntry->HTPhyMode.field.BW));
+ printk("%-6d", pEntry->HTPhyMode.field.MCS);
+ printk("%-6d", pEntry->HTPhyMode.field.ShortGI);
+ printk("%-6d", pEntry->HTPhyMode.field.STBC);
+ printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount,
+ (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0);
+ printk("\n");
+
+ }
+ }
+
+ return TRUE;
+}
+
+INT Set_DlsAddEntry_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR mac[MAC_ADDR_LEN];
+ USHORT Timeout;
+ char *token, sepValue[] = ":", DASH = '-';
+ INT i;
+ RT_802_11_DLS Dls;
+
+ if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format.
+ return FALSE;
+
+ token = strchr(arg, DASH);
+ if ((token != NULL) && (strlen(token)>1))
+ {
+ Timeout = simple_strtol((token+1), 0, 10);
+
+ *token = '\0';
+ for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
+ {
+ if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
+ return FALSE;
+ AtoH(token, (PUCHAR)(&mac[i]), 1);
+ }
+ if(i != 6)
+ return FALSE;
+
+ printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1],
+ mac[2], mac[3], mac[4], mac[5], (int)Timeout);
+
+ NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
+ Dls.TimeOut = Timeout;
+ COPY_MAC_ADDR(Dls.MacAddr, mac);
+ Dls.Valid = 1;
+
+ MlmeEnqueue(pAd,
+ MLME_CNTL_STATE_MACHINE,
+ RT_OID_802_11_SET_DLS_PARAM,
+ sizeof(RT_802_11_DLS),
+ &Dls);
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+INT Set_DlsTearDownEntry_Proc(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR arg)
+{
+ UCHAR macAddr[MAC_ADDR_LEN];
+ CHAR *value;
+ INT i;
+ RT_802_11_DLS Dls;
+
+ if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
+ return FALSE;
+
+ for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":"))
+ {
+ if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
+ return FALSE; //Invalid
+
+ AtoH(value, &macAddr[i++], 2);
+ }
+
+ printk("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1],
+ macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
+
+ NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
+ COPY_MAC_ADDR(Dls.MacAddr, macAddr);
+ Dls.Valid = 0;
+
+ MlmeEnqueue(pAd,
+ MLME_CNTL_STATE_MACHINE,
+ RT_OID_802_11_SET_DLS_PARAM,
+ sizeof(RT_802_11_DLS),
+ &Dls);
+
+ return TRUE;
+}
+
diff --git a/drivers/staging/rt2860/sta/rtmp_data.c b/drivers/staging/rt2860/sta/rtmp_data.c
new file mode 100644
index 000000000000..36aff247cd95
--- /dev/null
+++ b/drivers/staging/rt2860/sta/rtmp_data.c
@@ -0,0 +1,2614 @@
+/*
+ *************************************************************************
+ * Ralink Tech Inc.
+ * 5F., No.36, Taiyuan St., Jhubei City,
+ * Hsinchu County 302,
+ * Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002-2007, Ralink Technology, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; 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. *
+ * *
+ *************************************************************************
+
+ Module Name:
+ rtmp_data.c
+
+ Abstract:
+ Data path subroutines
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ John Aug/17/04 major modification for RT2561/2661
+ Jan Lee Mar/17/06 major modification for RT2860 New Ring Design
+*/
+#include "../rt_config.h"
+
+
+
+VOID STARxEAPOLFrameIndicate(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+ PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
+ PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
+ UCHAR *pTmpBuf;
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP)
+ {
+ // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon)
+ // TBD : process fragmented EAPol frames
+ {
+ // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable
+ if ( pAd->StaCfg.IEEE8021X == TRUE &&
+ (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H)))
+ {
+ PUCHAR Key;
+ UCHAR CipherAlg;
+ int idx = 0;
+
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n"));
+ STA_PORT_SECURED(pAd);
+
+ if (pAd->StaCfg.IEEE8021x_required_keys == FALSE)
+ {
+ idx = pAd->StaCfg.DesireSharedKeyId;
+ CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg;
+ Key = pAd->StaCfg.DesireSharedKey[idx].Key;
+
+ if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0)
+ {
+#ifdef RT2860
+ MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID];
+
+ // Set key material and cipherAlg to Asic
+ AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL);
+
+ // Assign group key info
+ RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL);
+
+ // Assign pairwise key info
+ RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry);
+
+ pAd->IndicateMediaState = NdisMediaStateConnected;
+ pAd->ExtraInfo = GENERAL_LINK_UP;
+#endif // RT2860 //
+ // For Preventing ShardKey Table is cleared by remove key procedure.
+ pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg;
+ pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen;
+ NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key,
+ pAd->StaCfg.DesireSharedKey[idx].Key,
+ pAd->StaCfg.DesireSharedKey[idx].KeyLen);
+ }
+ }
+ }
+
+ Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+ }
+ else
+#endif // WPA_SUPPLICANT_SUPPORT //
+ {
+ // Special DATA frame that has to pass to MLME
+ // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process
+ // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process
+ {
+ pTmpBuf = pRxBlk->pData - LENGTH_802_11;
+ NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11);
+ REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
+ DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize));
+ }
+ }
+
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+
+}
+
+VOID STARxDataFrameAnnounce(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk,
+ IN UCHAR FromWhichBSSID)
+{
+
+ // non-EAP frame
+ if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID))
+ {
+ {
+ // drop all non-EAP DATA frame before
+ // this client's Port-Access-Control is secured
+ if (pRxBlk->pHeader->FC.Wep)
+ {
+ // unsupported cipher suite
+ if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled)
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+ }
+ else
+ {
+ // encryption in-use but receive a non-EAPOL clear text frame, drop it
+ if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) &&
+ (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+ }
+ }
+ RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP);
+ if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK))
+ {
+ // Normal legacy, AMPDU or AMSDU
+ CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID);
+
+ }
+ else
+ {
+ // ARALINK
+ CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+ }
+#ifdef QOS_DLS_SUPPORT
+ RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);
+#endif // QOS_DLS_SUPPORT //
+ }
+ else
+ {
+ RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);
+#ifdef DOT11_N_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0))
+ {
+ Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID);
+ }
+ else
+#endif // DOT11_N_SUPPORT //
+ {
+ // Determin the destination of the EAP frame
+ // to WPA state machine or upper layer
+ STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID);
+ }
+ }
+}
+
+
+// For TKIP frame, calculate the MIC value
+BOOLEAN STACheckTkipMICValue(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry,
+ IN RX_BLK *pRxBlk)
+{
+ PHEADER_802_11 pHeader = pRxBlk->pHeader;
+ UCHAR *pData = pRxBlk->pData;
+ USHORT DataSize = pRxBlk->DataSize;
+ UCHAR UserPriority = pRxBlk->UserPriority;
+ PCIPHER_KEY pWpaKey;
+ UCHAR *pDA, *pSA;
+
+ pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex];
+
+ pDA = pHeader->Addr1;
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA))
+ {
+ pSA = pHeader->Addr3;
+ }
+ else
+ {
+ pSA = pHeader->Addr2;
+ }
+
+ if (RTMPTkipCompareMICValue(pAd,
+ pData,
+ pDA,
+ pSA,
+ pWpaKey->RxMic,
+ UserPriority,
+ DataSize) == FALSE)
+ {
+ DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));
+
+#ifdef WPA_SUPPLICANT_SUPPORT
+ if (pAd->StaCfg.WpaSupplicantUP)
+ {
+ WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE);
+ }
+ else
+#endif // WPA_SUPPLICANT_SUPPORT //
+ {
+ RTMPReportMicError(pAd, pWpaKey);
+ }
+
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+//
+// All Rx routines use RX_BLK structure to hande rx events
+// It is very important to build pRxBlk attributes
+// 1. pHeader pointer to 802.11 Header
+// 2. pData pointer to payload including LLC (just skip Header)
+// 3. set payload size including LLC to DataSize
+// 4. set some flags with RX_BLK_SET_FLAG()
+//
+VOID STAHandleRxDataFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk)
+{
+ PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
+ PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
+ PHEADER_802_11 pHeader = pRxBlk->pHeader;
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+ BOOLEAN bFragment = FALSE;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ UCHAR FromWhichBSSID = BSS0;
+ UCHAR UserPriority = 0;
+
+ {
+ // before LINK UP, all DATA frames are rejected
+ if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+#ifdef QOS_DLS_SUPPORT
+ //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
+ if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD))
+ {
+ return;
+ }
+#endif // QOS_DLS_SUPPORT //
+
+ // Drop not my BSS frames
+ if (pRxD->MyBss == 0)
+ {
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+ }
+
+ pAd->RalinkCounters.RxCountSinceLastNULL++;
+ if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08))
+ {
+ UCHAR *pData;
+ DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n"));
+
+ // Qos bit 4
+ pData = (PUCHAR)pHeader + LENGTH_802_11;
+ if ((*pData >> 4) & 0x01)
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("RxDone- Rcv EOSP frame, driver may fall into sleep\n"));
+ pAd->CommonCfg.bInServicePeriod = FALSE;
+
+ // Force driver to fall into sleep mode when rcv EOSP frame
+ if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
+ {
+ USHORT TbttNumToNextWakeUp;
+ USHORT NextDtim = pAd->StaCfg.DtimPeriod;
+ ULONG Now;
+
+ NdisGetSystemUpTime(&Now);
+ NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod;
+
+ TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount;
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim))
+ TbttNumToNextWakeUp = NextDtim;
+
+ MlmeSetPsmBit(pAd, PWR_SAVE);
+ // if WMM-APSD is failed, try to disable following line
+ AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp);
+ }
+ }
+
+ if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n"));
+ }
+ }
+
+ // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame
+ if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ // Drop not my BSS frame (we can not only check the MyBss bit in RxD)
+#ifdef QOS_DLS_SUPPORT
+ if (!pAd->CommonCfg.bDLSCapable)
+ {
+#endif // QOS_DLS_SUPPORT //
+ if (INFRA_ON(pAd))
+ {
+ // Infrastructure mode, check address 2 for BSSID
+ if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6))
+ {
+ // Receive frame not my BSSID
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+ }
+ else // Ad-Hoc mode or Not associated
+ {
+ // Ad-Hoc mode, check address 3 for BSSID
+ if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6))
+ {
+ // Receive frame not my BSSID
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+ }
+#ifdef QOS_DLS_SUPPORT
+ }
+#endif // QOS_DLS_SUPPORT //
+
+ //
+ // find pEntry
+ //
+ if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE)
+ {
+ pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
+ }
+ else
+ {
+ // 1. release packet if infra mode
+ // 2. new a pEntry if ad-hoc mode
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ // infra or ad-hoc
+ if (INFRA_ON(pAd))
+ {
+ RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);
+#ifdef QOS_DLS_SUPPORT
+ if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0))
+ RX_BLK_SET_FLAG(pRxBlk, fRX_DLS);
+ else
+#endif // QOS_DLS_SUPPORT //
+ ASSERT(pRxWI->WirelessCliID == BSSID_WCID);
+ }
+
+ // check Atheros Client
+ if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry ))
+ {
+ pEntry->bIAmBadAtheros = TRUE;
+ pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE;
+ pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE;
+ if (!STA_AES_ON(pAd))
+ {
+ AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE);
+ }
+ }
+ }
+
+ pRxBlk->pData = (UCHAR *)pHeader;
+
+ //
+ // update RxBlk->pData, DataSize
+ // 802.11 Header, QOS, HTC, Hw Padding
+ //
+
+ // 1. skip 802.11 HEADER
+ {
+ pRxBlk->pData += LENGTH_802_11;
+ pRxBlk->DataSize -= LENGTH_802_11;
+ }
+
+ // 2. QOS
+ if (pHeader->FC.SubType & 0x08)
+ {
+ RX_BLK_SET_FLAG(pRxBlk, fRX_QOS);
+ UserPriority = *(pRxBlk->pData) & 0x0f;
+ // bit 7 in QoS Control field signals the HT A-MSDU format
+ if ((*pRxBlk->pData) & 0x80)
+ {
+ RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU);
+ }
+
+ // skip QOS contorl field
+ pRxBlk->pData += 2;
+ pRxBlk->DataSize -=2;
+ }
+ pRxBlk->UserPriority = UserPriority;
+
+ // 3. Order bit: A-Ralink or HTC+
+ if (pHeader->FC.Order)
+ {
+#ifdef AGGREGATION_SUPPORT
+ if ((pRxWI->PHYMODE <= MODE_OFDM) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED)))
+ {
+ RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK);
+ }
+ else
+#endif
+ {
+#ifdef DOT11_N_SUPPORT
+ RX_BLK_SET_FLAG(pRxBlk, fRX_HTC);
+ // skip HTC contorl field
+ pRxBlk->pData += 4;
+ pRxBlk->DataSize -= 4;
+#endif // DOT11_N_SUPPORT //
+ }
+ }
+
+ // 4. skip HW padding
+ if (pRxD->L2PAD)
+ {
+ // just move pData pointer
+ // because DataSize excluding HW padding
+ RX_BLK_SET_FLAG(pRxBlk, fRX_PAD);
+ pRxBlk->pData += 2;
+ }
+
+#ifdef DOT11_N_SUPPORT
+ if (pRxD->BA)
+ {
+ RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU);
+ }
+#endif // DOT11_N_SUPPORT //
+
+
+ //
+ // Case I Process Broadcast & Multicast data frame
+ //
+ if (pRxD->Bcast || pRxD->Mcast)
+ {
+ INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount);
+
+ // Drop Mcast/Bcast frame with fragment bit on
+ if (pHeader->FC.MoreFrag)
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ // Filter out Bcast frame which AP relayed for us
+ if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress))
+ {
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
+ return;
+ }
+ else if (pRxD->U2M)
+ {
+ pAd->LastRxRate = (USHORT)((pRxWI->MCS) + (pRxWI->BW <<7) + (pRxWI->ShortGI <<8)+ (pRxWI->PHYMODE <<14)) ;
+
+
+#ifdef QOS_DLS_SUPPORT
+ if (RX_BLK_TEST_FLAG(pRxBlk, fRX_DLS))
+ {
+ MAC_TABLE_ENTRY *pDlsEntry = NULL;
+
+ pDlsEntry = DlsEntryTableLookupByWcid(pAd, pRxWI->WirelessCliID, pHeader->Addr2, TRUE);
+ if(pDlsEntry)
+ Update_Rssi_Sample(pAd, &pDlsEntry->RssiSample, pRxWI);
+ }
+ else
+#endif // QOS_DLS_SUPPORT //
+ if (ADHOC_ON(pAd))
+ {
+ pEntry = MacTableLookup(pAd, pHeader->Addr2);
+ if (pEntry)
+ Update_Rssi_Sample(pAd, &pEntry->RssiSample, pRxWI);
+ }
+
+
+ Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
+
+ pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
+ pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
+
+ pAd->RalinkCounters.OneSecRxOkDataCnt++;
+
+
+ if (!((pHeader->Frag == 0) && (pHeader->FC.MoreFrag == 0)))
+ {
+ // re-assemble the fragmented packets
+ // return complete frame (pRxPacket) or NULL
+ bFragment = TRUE;
+ pRxPacket = RTMPDeFragmentDataFrame(pAd, pRxBlk);
+ }
+
+ if (pRxPacket)
+ {
+ pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID];
+
+ // process complete frame
+ if (bFragment && (pRxD->Decrypted) && (pEntry->WepStatus == Ndis802_11Encryption2Enabled))
+ {
+ // Minus MIC length
+ pRxBlk->DataSize -= 8;
+
+ // For TKIP frame, calculate the MIC value
+ if (STACheckTkipMICValue(pAd, pEntry, pRxBlk) == FALSE)
+ {
+ return;
+ }
+ }
+
+ STARxDataFrameAnnounce(pAd, pEntry, pRxBlk, FromWhichBSSID);
+ return;
+ }
+ else
+ {
+ // just return
+ // because RTMPDeFragmentDataFrame() will release rx packet,
+ // if packet is fragmented
+ return;
+ }
+ }
+
+ ASSERT(0);
+ // release packet
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+}
+
+VOID STAHandleRxMgmtFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk)
+{
+ PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD);
+ PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
+ PHEADER_802_11 pHeader = pRxBlk->pHeader;
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+
+ do
+ {
+
+ // We should collect RSSI not only U2M data but also my beacon
+ if ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->CommonCfg.Bssid, &pHeader->Addr2)))
+ {
+ Update_Rssi_Sample(pAd, &pAd->StaCfg.RssiSample, pRxWI);
+
+ pAd->StaCfg.LastSNR0 = (UCHAR)(pRxWI->SNR0);
+ pAd->StaCfg.LastSNR1 = (UCHAR)(pRxWI->SNR1);
+ }
+
+ // First check the size, it MUST not exceed the mlme queue size
+ if (pRxWI->MPDUtotalByteCount > MGMT_DMA_BUFFER_SIZE)
+ {
+ DBGPRINT_ERR(("STAHandleRxMgmtFrame: frame too large, size = %d \n", pRxWI->MPDUtotalByteCount));
+ break;
+ }
+
+ REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pHeader, pRxWI->MPDUtotalByteCount,
+ pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal);
+ } while (FALSE);
+
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
+}
+
+VOID STAHandleRxControlFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN RX_BLK *pRxBlk)
+{
+#ifdef DOT11_N_SUPPORT
+ PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
+#endif // DOT11_N_SUPPORT //
+ PHEADER_802_11 pHeader = pRxBlk->pHeader;
+ PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket;
+
+ switch (pHeader->FC.SubType)
+ {
+ case SUBTYPE_BLOCK_ACK_REQ:
+#ifdef DOT11_N_SUPPORT
+ {
+ CntlEnqueueForRecv(pAd, pRxWI->WirelessCliID, (pRxWI->MPDUtotalByteCount), (PFRAME_BA_REQ)pHeader);
+ }
+ break;
+#endif // DOT11_N_SUPPORT //
+ case SUBTYPE_BLOCK_ACK:
+ case SUBTYPE_ACK:
+ default:
+ break;
+ }
+
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Process RxDone interrupt, running in DPC level
+
+ Arguments:
+ pAd Pointer to our adapter
+
+ Return Value:
+ None
+
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+ This routine has to maintain Rx ring read pointer.
+ Need to consider QOS DATA format when converting to 802.3
+ ========================================================================
+*/
+BOOLEAN STARxDoneInterruptHandle(
+ IN PRTMP_ADAPTER pAd,
+ IN BOOLEAN argc)
+{
+ NDIS_STATUS Status;
+ UINT32 RxProcessed, RxPending;
+ BOOLEAN bReschedule = FALSE;
+ RT28XX_RXD_STRUC *pRxD;
+ UCHAR *pData;
+ PRXWI_STRUC pRxWI;
+ PNDIS_PACKET pRxPacket;
+ PHEADER_802_11 pHeader;
+ RX_BLK RxCell;
+
+ RxProcessed = RxPending = 0;
+
+ // process whole rx ring
+ while (1)
+ {
+
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF |
+ fRTMP_ADAPTER_RESET_IN_PROGRESS |
+ fRTMP_ADAPTER_HALT_IN_PROGRESS |
+ fRTMP_ADAPTER_NIC_NOT_EXIST) ||
+ !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP))
+ {
+ break;
+ }
+
+#ifdef RT2860
+ if (RxProcessed++ > MAX_RX_PROCESS_CNT)
+ {
+ // need to reschedule rx handle
+ bReschedule = TRUE;
+ break;
+ }
+#endif // RT2860 //
+
+ RxProcessed ++; // test
+
+ // 1. allocate a new data packet into rx ring to replace received packet
+ // then processing the received packet
+ // 2. the callee must take charge of release of packet
+ // 3. As far as driver is concerned ,
+ // the rx packet must
+ // a. be indicated to upper layer or
+ // b. be released if it is discarded
+ pRxPacket = GetPacketFromRxRing(pAd, &(RxCell.RxD), &bReschedule, &RxPending);
+ if (pRxPacket == NULL)
+ {
+ // no more packet to process
+ break;
+ }
+
+ // get rx ring descriptor
+ pRxD = &(RxCell.RxD);
+ // get rx data buffer
+ pData = GET_OS_PKT_DATAPTR(pRxPacket);
+ pRxWI = (PRXWI_STRUC) pData;
+ pHeader = (PHEADER_802_11) (pData+RXWI_SIZE) ;
+
+#ifdef RT_BIG_ENDIAN
+ RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, TRUE);
+ RTMPWIEndianChange((PUCHAR)pRxWI, TYPE_RXWI);
+#endif
+
+ // build RxCell
+ RxCell.pRxWI = pRxWI;
+ RxCell.pHeader = pHeader;
+ RxCell.pRxPacket = pRxPacket;
+ RxCell.pData = (UCHAR *) pHeader;
+ RxCell.DataSize = pRxWI->MPDUtotalByteCount;
+ RxCell.Flags = 0;
+
+ // Increase Total receive byte counter after real data received no mater any error or not
+ pAd->RalinkCounters.ReceivedByteCount += pRxWI->MPDUtotalByteCount;
+ pAd->RalinkCounters.RxCount ++;
+
+ INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount);
+
+ if (pRxWI->MPDUtotalByteCount < 14)
+ Status = NDIS_STATUS_FAILURE;
+
+ if (MONITOR_ON(pAd))
+ {
+ send_monitor_packets(pAd, &RxCell);
+ break;
+ }
+ /* RT2870 invokes STARxDoneInterruptHandle() in rtusb_bulk.c */
+#ifdef RALINK_ATE
+ if (ATE_ON(pAd))
+ {
+ pAd->ate.RxCntPerSec++;
+ ATESampleRssi(pAd, pRxWI);
+#ifdef RALINK_28xx_QA
+ if (pAd->ate.bQARxStart == TRUE)
+ {
+ /* (*pRxD) has been swapped in GetPacketFromRxRing() */
+ ATE_QA_Statistics(pAd, pRxWI, pRxD, pHeader);
+ }
+#endif // RALINK_28xx_QA //
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS);
+ continue;
+ }
+#endif // RALINK_ATE //
+
+ // Check for all RxD errors
+ Status = RTMPCheckRxError(pAd, pHeader, pRxWI, pRxD);
+
+ // Handle the received frame
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ switch (pHeader->FC.Type)
+ {
+ // CASE I, receive a DATA frame
+ case BTYPE_DATA:
+ {
+ // process DATA frame
+ STAHandleRxDataFrame(pAd, &RxCell);
+ }
+ break;
+ // CASE II, receive a MGMT frame
+ case BTYPE_MGMT:
+ {
+ STAHandleRxMgmtFrame(pAd, &RxCell);
+ }
+ break;
+ // CASE III. receive a CNTL frame
+ case BTYPE_CNTL:
+ {
+ STAHandleRxControlFrame(pAd, &RxCell);
+ }
+ break;
+ // discard other type
+ default:
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ break;
+ }
+ }
+ else
+ {
+ pAd->Counters8023.RxErrors++;
+ // discard this frame
+ RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE);
+ }
+ }
+
+ return bReschedule;
+}
+
+/*
+ ========================================================================
+
+ Routine Description:
+ Arguments:
+ pAd Pointer to our adapter
+
+ IRQL = DISPATCH_LEVEL
+
+ ========================================================================
+*/
+VOID RTMPHandleTwakeupInterrupt(
+ IN PRTMP_ADAPTER pAd)
+{
+ AsicForceWakeup(pAd, FALSE);
+}
+
+/*
+========================================================================
+Routine Description:
+ Early checking and OS-depened parsing for Tx packet send to our STA driver.
+
+Arguments:
+ NDIS_HANDLE MiniportAdapterContext Pointer refer to the device handle, i.e., the pAd.
+ PPNDIS_PACKET ppPacketArray The packet array need to do transmission.
+ UINT NumberOfPackets Number of packet in packet array.
+
+Return Value:
+ NONE
+
+Note:
+ This function do early checking and classification for send-out packet.
+ You only can put OS-depened & STA related code in here.
+========================================================================
+*/
+VOID STASendPackets(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PPNDIS_PACKET ppPacketArray,
+ IN UINT NumberOfPackets)
+{
+ UINT Index;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) MiniportAdapterContext;
+ PNDIS_PACKET pPacket;
+ BOOLEAN allowToSend = FALSE;
+
+
+ for (Index = 0; Index < NumberOfPackets; Index++)
+ {
+ pPacket = ppPacketArray[Index];
+
+ do
+ {
+ if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
+ RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
+ {
+ // Drop send request since hardware is in reset state
+ break;
+ }
+ else if (!INFRA_ON(pAd) && !ADHOC_ON(pAd))
+ {
+ // Drop send request since there are no physical connection yet
+ break;
+ }
+ else
+ {
+ // Record that orignal packet source is from NDIS layer,so that
+ // later on driver knows how to release this NDIS PACKET
+#ifdef QOS_DLS_SUPPORT
+ MAC_TABLE_ENTRY *pEntry;
+ PUCHAR pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
+
+ pEntry = MacTableLookup(pAd, pSrcBufVA);
+ if (pEntry && (pEntry->ValidAsDls == TRUE))
+ {
+ RTMP_SET_PACKET_WCID(pPacket, pEntry->Aid);
+ }
+ else
+#endif // QOS_DLS_SUPPORT //
+ RTMP_SET_PACKET_WCID(pPacket, 0); // this field is useless when in STA mode
+ RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+ NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_PENDING);
+ pAd->RalinkCounters.PendingNdisPacketCount++;
+
+ allowToSend = TRUE;
+ }
+ } while(FALSE);
+
+ if (allowToSend == TRUE)
+ STASendPacket(pAd, pPacket);
+ else
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ }
+
+ // Dequeue outgoing frames from TxSwQueue[] and process it
+ RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
+
+}
+
+
+/*
+========================================================================
+Routine Description:
+ This routine is used to do packet parsing and classification for Tx packet
+ to STA device, and it will en-queue packets to our TxSwQueue depends on AC
+ class.
+
+Arguments:
+ pAd Pointer to our adapter
+ pPacket Pointer to send packet
+
+Return Value:
+ NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQueue.
+ NDIS_STATUS_FAILURE If failed to do en-queue.
+
+Note:
+ You only can put OS-indepened & STA related code in here.
+========================================================================
+*/
+NDIS_STATUS STASendPacket(
+ IN PRTMP_ADAPTER pAd,
+ IN PNDIS_PACKET pPacket)
+{
+ PACKET_INFO PacketInfo;
+ PUCHAR pSrcBufVA;
+ UINT SrcBufLen;
+ UINT AllowFragSize;
+ UCHAR NumberOfFrag;
+ UCHAR QueIdx, UserPriority;
+ MAC_TABLE_ENTRY *pEntry = NULL;
+ unsigned int IrqFlags;
+ UCHAR FlgIsIP = 0;
+ UCHAR Rate;
+
+ // Prepare packet information structure for buffer descriptor
+ // chained within a single NDIS packet.
+ RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
+
+ if (pSrcBufVA == NULL)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> pSrcBufVA == NULL !!!SrcBufLen=%x\n",SrcBufLen));
+ // Resourece is low, system did not allocate virtual address
+ // return NDIS_STATUS_FAILURE directly to upper layer
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ return NDIS_STATUS_FAILURE;
+ }
+
+
+ if (SrcBufLen < 14)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("STASendPacket --> Ndis Packet buffer error !!!\n"));
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ return (NDIS_STATUS_FAILURE);
+ }
+
+ // In HT rate adhoc mode, A-MPDU is often used. So need to lookup BA Table and MAC Entry.
+ // Note multicast packets in adhoc also use BSSID_WCID index.
+ {
+ if(INFRA_ON(pAd))
+ {
+#ifdef QOS_DLS_SUPPORT
+ USHORT tmpWcid;
+
+ tmpWcid = RTMP_GET_PACKET_WCID(pPacket);
+ if (VALID_WCID(tmpWcid) &&
+ (pAd->MacTab.Content[tmpWcid].ValidAsDls== TRUE))
+ {
+ pEntry = &pAd->MacTab.Content[tmpWcid];
+ Rate = pAd->MacTab.Content[tmpWcid].CurrTxRate;
+ }
+ else
+#endif // QOS_DLS_SUPPORT //
+ {
+ pEntry = &pAd->MacTab.Content[BSSID_WCID];
+ RTMP_SET_PACKET_WCID(pPacket, BSSID_WCID);
+ Rate = pAd->CommonCfg.TxRate;
+ }
+ }
+ else if (ADHOC_ON(pAd))
+ {
+ if (*pSrcBufVA & 0x01)
+ {
+ RTMP_SET_PACKET_WCID(pPacket, MCAST_WCID);
+ pEntry = &pAd->MacTab.Content[MCAST_WCID];
+ }
+ else
+ {
+ pEntry = MacTableLookup(pAd, pSrcBufVA);
+ }
+ Rate = pAd->CommonCfg.TxRate;
+ }
+ }
+
+ if (!pEntry)
+ {
+ DBGPRINT(RT_DEBUG_ERROR,("STASendPacket->Cannot find pEntry(%2x:%2x:%2x:%2x:%2x:%2x) in MacTab!\n", PRINT_MAC(pSrcBufVA)));
+ // Resourece is low, system did not allocate virtual address
+ // return NDIS_STATUS_FAILURE directly to upper layer
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+ return NDIS_STATUS_FAILURE;
+ }
+
+ if (ADHOC_ON(pAd)
+ )
+ {
+ RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
+ }
+
+ //
+ // Check the Ethernet Frame type of this packet, and set the RTMP_SET_PACKET_SPECIFIC flags.
+ // Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL).
+ RTMPCheckEtherType(pAd, pPacket);
+
+
+
+ //
+ // WPA 802.1x secured port control - drop all non-802.1x frame before port secured
+ //
+ if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+#ifdef WPA_SUPPLICANT_SUPPORT
+ || (pAd->StaCfg.IEEE8021X == TRUE)
+#endif // WPA_SUPPLICANT_SUPPORT //
+#ifdef LEAP_SUPPORT
+ || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
+#endif // LEAP_SUPPORT //
+ )
+ && ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->StaCfg.MicErrCnt >= 2))
+ && (RTMP_GET_PACKET_EAPOL(pPacket)== FALSE)
+ )
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("STASendPacket --> Drop packet before port secured !!!\n"));
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+
+ return (NDIS_STATUS_FAILURE);
+ }
+
+
+ // STEP 1. Decide number of fragments required to deliver this MSDU.
+ // The estimation here is not very accurate because difficult to
+ // take encryption overhead into consideration here. The result
+ // "NumberOfFrag" is then just used to pre-check if enough free
+ // TXD are available to hold this MSDU.
+
+
+ if (*pSrcBufVA & 0x01) // fragmentation not allowed on multicast & broadcast
+ NumberOfFrag = 1;
+ else if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))
+ NumberOfFrag = 1; // Aggregation overwhelms fragmentation
+ else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED))
+ NumberOfFrag = 1; // Aggregation overwhelms fragmentation
+#ifdef DOT11_N_SUPPORT
+ else if ((pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTMIX) || (pAd->StaCfg.HTPhyMode.field.MODE == MODE_HTGREENFIELD))
+ NumberOfFrag = 1; // MIMO RATE overwhelms fragmentation
+#endif // DOT11_N_SUPPORT //
+ else
+ {
+ // The calculated "NumberOfFrag" is a rough estimation because of various
+ // encryption/encapsulation overhead not taken into consideration. This number is just
+ // used to make sure enough free TXD are available before fragmentation takes place.
+ // In case the actual required number of fragments of an NDIS packet
+ // excceeds "NumberOfFrag"caculated here and not enough free TXD available, the
+ // last fragment (i.e. last MPDU) will be dropped in RTMPHardTransmit() due to out of
+ // resource, and the NDIS packet will be indicated NDIS_STATUS_FAILURE. This should
+ // rarely happen and the penalty is just like a TX RETRY fail. Affordable.
+
+ AllowFragSize = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC;
+ NumberOfFrag = ((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) / AllowFragSize) + 1;
+ // To get accurate number of fragmentation, Minus 1 if the size just match to allowable fragment size
+ if (((PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H) % AllowFragSize) == 0)
+ {
+ NumberOfFrag--;
+ }
+ }
+
+ // Save fragment number to Ndis packet reserved field
+ RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag);
+
+
+ // STEP 2. Check the requirement of RTS:
+ // If multiple fragment required, RTS is required only for the first fragment
+ // if the fragment size large than RTS threshold
+ // For RT28xx, Let ASIC send RTS/CTS
+ RTMP_SET_PACKET_RTS(pPacket, 0);
+ RTMP_SET_PACKET_TXRATE(pPacket, pAd->CommonCfg.TxRate);
+
+ //
+ // STEP 3. Traffic classification. outcome = <UserPriority, QueIdx>
+ //
+ UserPriority = 0;
+ QueIdx = QID_AC_BE;
+ if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED))
+ {
+ USHORT Protocol;
+ UCHAR LlcSnapLen = 0, Byte0, Byte1;
+ do
+ {
+ // get Ethernet protocol field
+ Protocol = (USHORT)((pSrcBufVA[12] << 8) + pSrcBufVA[13]);
+ if (Protocol <= 1500)
+ {
+ // get Ethernet protocol field from LLC/SNAP
+ if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + 6, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
+ break;
+
+ Protocol = (USHORT)((Byte0 << 8) + Byte1);
+ LlcSnapLen = 8;
+ }
+
+ // always AC_BE for non-IP packet
+ if (Protocol != 0x0800)
+ break;
+
+ // get IP header
+ if (Sniff2BytesFromNdisBuffer(PacketInfo.pFirstBuffer, LENGTH_802_3 + LlcSnapLen, &Byte0, &Byte1) != NDIS_STATUS_SUCCESS)
+ break;
+
+ // return AC_BE if packet is not IPv4
+ if ((Byte0 & 0xf0) != 0x40)
+ break;
+
+ FlgIsIP = 1;
+ UserPriority = (Byte1 & 0xe0) >> 5;
+ QueIdx = MapUserPriorityToAccessCategory[UserPriority];
+
+ // TODO: have to check ACM bit. apply TSPEC if ACM is ON
+ // TODO: downgrade UP & QueIdx before passing ACM
+ if (pAd->CommonCfg.APEdcaParm.bACM[QueIdx])
+ {
+ UserPriority = 0;
+ QueIdx = QID_AC_BE;
+ }
+ } while (FALSE);
+ }
+
+ RTMP_SET_PACKET_UP(pPacket, UserPriority);
+
+
+
+ // Make sure SendTxWait queue resource won't be used by other threads
+ RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
+ if (pAd->TxSwQueue[QueIdx].Number >= MAX_PACKETS_IN_QUEUE)
+ {
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+#ifdef BLOCK_NET_IF
+ StopNetIfQueue(pAd, QueIdx, pPacket);
+#endif // BLOCK_NET_IF //
+ RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
+
+ return NDIS_STATUS_FAILURE;
+ }
+ else
+ {
+ InsertTailQueue(&pAd->TxSwQueue[QueIdx], PACKET_TO_QUEUE_ENTRY(pPacket));
+ }
+ RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
+
+#ifdef DOT11_N_SUPPORT
+ if ((pAd->CommonCfg.BACapability.field.AutoBA == TRUE)&&
+ (pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE))
+ {
+ if (((pEntry->TXBAbitmap & (1<<UserPriority)) == 0) &&
+ ((pEntry->BADeclineBitmap & (1<<UserPriority)) == 0) &&
+ (pEntry->PortSecured == WPA_802_1X_PORT_SECURED)
+ // For IOT compatibility, if
+ // 1. It is Ralink chip or
+ // 2. It is OPEN or AES mode,
+ // then BA session can be bulit.
+ && ((pEntry->ValidAsCLI && pAd->MlmeAux.APRalinkIe != 0x0) ||
+ (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11Encryption3Enabled))
+ )
+ {
+ BAOriSessionSetUp(pAd, pEntry, 0, 0, 10, FALSE);
+ }
+ }
+#endif // DOT11_N_SUPPORT //
+
+ pAd->RalinkCounters.OneSecOsTxCount[QueIdx]++; // TODO: for debug only. to be removed
+ return NDIS_STATUS_SUCCESS;
+}
+
+
+/*
+ ========================================================================
+
+ Routine Description:
+ This subroutine will scan through releative ring descriptor to find
+ out avaliable free ring descriptor and compare with request size.
+
+ Arguments:
+ pAd Pointer to our adapter
+ QueIdx Selected TX Ring
+
+ Return Value:
+ NDIS_STATUS_FAILURE Not enough free descriptor
+ NDIS_STATUS_SUCCESS Enough free descriptor
+
+ IRQL = PASSIVE_LEVEL
+ IRQL = DISPATCH_LEVEL
+
+ Note:
+
+ ========================================================================
+*/
+#ifdef RT2860
+NDIS_STATUS RTMPFreeTXDRequest(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR QueIdx,
+ IN UCHAR NumberRequired,
+ IN PUCHAR FreeNumberIs)
+{
+ ULONG FreeNumber = 0;
+ NDIS_STATUS Status = NDIS_STATUS_FAILURE;
+
+ switch (QueIdx)
+ {
+ case QID_AC_BK:
+ case QID_AC_BE:
+ case QID_AC_VI:
+ case QID_AC_VO:
+ case QID_HCCA:
+ if (pAd->TxRing[QueIdx].TxSwFreeIdx > pAd->TxRing[QueIdx].TxCpuIdx)
+ FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx - pAd->TxRing[QueIdx].TxCpuIdx - 1;
+ else
+ FreeNumber = pAd->TxRing[QueIdx].TxSwFreeIdx + TX_RING_SIZE - pAd->TxRing[QueIdx].TxCpuIdx - 1;
+
+ if (FreeNumber >= NumberRequired)
+ Status = NDIS_STATUS_SUCCESS;
+ break;
+
+ case QID_MGMT:
+ if (pAd->MgmtRing.TxSwFreeIdx > pAd->MgmtRing.TxCpuIdx)
+ FreeNumber = pAd->MgmtRing.TxSwFreeIdx - pAd->MgmtRing.TxCpuIdx - 1;
+ else
+ FreeNumber = pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - pAd->MgmtRing.TxCpuIdx - 1;
+
+ if (FreeNumber >= NumberRequired)
+ Status = NDIS_STATUS_SUCCESS;
+ break;
+
+ default:
+ DBGPRINT(RT_DEBUG_ERROR,("RTMPFreeTXDRequest::Invalid QueIdx(=%d)\n", QueIdx));
+ break;
+ }
+ *FreeNumberIs = (UCHAR)FreeNumber;
+
+ return (Status);
+}
+#endif // RT2860 //
+
+
+
+VOID RTMPSendDisassociationFrame(
+ IN PRTMP_ADAPTER pAd)
+{
+}
+
+VOID RTMPSendNullFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR TxRate,
+ IN BOOLEAN bQosNull)
+{
+ UCHAR NullFrame[48];
+ ULONG Length;
+ PHEADER_802_11 pHeader_802_11;
+
+
+#ifdef RALINK_ATE
+ if(ATE_ON(pAd))
+ {
+ return;
+ }
+#endif // RALINK_ATE //
+
+ // WPA 802.1x secured port control
+ if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) ||
+ (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
+#ifdef WPA_SUPPLICANT_SUPPORT
+ || (pAd->StaCfg.IEEE8021X == TRUE)
+#endif
+ ) &&
+ (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+ {
+ return;
+ }
+
+ NdisZeroMemory(NullFrame, 48);
+ Length = sizeof(HEADER_802_11);
+
+ pHeader_802_11 = (PHEADER_802_11) NullFrame;
+
+ pHeader_802_11->FC.Type = BTYPE_DATA;
+ pHeader_802_11->FC.SubType = SUBTYPE_NULL_FUNC;
+ pHeader_802_11->FC.ToDs = 1;
+ COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
+ COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
+
+ if (pAd->CommonCfg.bAPSDForcePowerSave)
+ {
+ pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+ }
+ else
+ {
+ pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE) ? 1: 0;
+ }
+ pHeader_802_11->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14);
+
+ pAd->Sequence++;
+ pHeader_802_11->Sequence = pAd->Sequence;
+
+ // Prepare QosNull function frame
+ if (bQosNull)
+ {
+ pHeader_802_11->FC.SubType = SUBTYPE_QOS_NULL;
+
+ // copy QOS control bytes
+ NullFrame[Length] = 0;
+ NullFrame[Length+1] = 0;
+ Length += 2;// if pad with 2 bytes for alignment, APSD will fail
+ }
+
+ HAL_KickOutNullFrameTx(pAd, 0, NullFrame, Length);
+
+}
+
+// IRQL = DISPATCH_LEVEL
+VOID RTMPSendRTSFrame(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pDA,
+ IN unsigned int NextMpduSize,
+ IN UCHAR TxRate,
+ IN UCHAR RTSRate,
+ IN USHORT AckDuration,
+ IN UCHAR QueIdx,
+ IN UCHAR FrameGap)
+{
+}
+
+
+
+// --------------------------------------------------------
+// FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM
+// Find the WPA key, either Group or Pairwise Key
+// LEAP + TKIP also use WPA key.
+// --------------------------------------------------------
+// Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst
+// In Cisco CCX 2.0 Leap Authentication
+// WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey
+// Instead of the SharedKey, SharedKey Length may be Zero.
+VOID STAFindCipherAlgorithm(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk)
+{
+ NDIS_802_11_ENCRYPTION_STATUS Cipher; // To indicate cipher used for this packet
+ UCHAR CipherAlg = CIPHER_NONE; // cipher alogrithm
+ UCHAR KeyIdx = 0xff;
+ PUCHAR pSrcBufVA;
+ PCIPHER_KEY pKey = NULL;
+
+ pSrcBufVA = GET_OS_PKT_DATAPTR(pTxBlk->pPacket);
+
+ {
+ // Select Cipher
+ if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
+ Cipher = pAd->StaCfg.GroupCipher; // Cipher for Multicast or Broadcast
+ else
+ Cipher = pAd->StaCfg.PairCipher; // Cipher for Unicast
+
+ if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket))
+ {
+ ASSERT(pAd->SharedKey[BSS0][0].CipherAlg <= CIPHER_CKIP128);
+
+ // 4-way handshaking frame must be clear
+ if (!(TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) && (pAd->SharedKey[BSS0][0].CipherAlg) &&
+ (pAd->SharedKey[BSS0][0].KeyLen))
+ {
+ CipherAlg = pAd->SharedKey[BSS0][0].CipherAlg;
+ KeyIdx = 0;
+ }
+ }
+ else if (Cipher == Ndis802_11Encryption1Enabled)
+ {
+#ifdef LEAP_SUPPORT
+ if (pAd->StaCfg.CkipFlag & 0x10) // Cisco CKIP KP is on
+ {
+ if (LEAP_CCKM_ON(pAd))
+ {
+ if (((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))))
+ KeyIdx = 1;
+ else
+ KeyIdx = 0;
+ }
+ else
+ KeyIdx = pAd->StaCfg.DefaultKeyId;
+ }
+ else if (pAd->StaCfg.CkipFlag & 0x08) // only CKIP CMIC
+ KeyIdx = pAd->StaCfg.DefaultKeyId;
+ else if (LEAP_CCKM_ON(pAd))
+ {
+ if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd)))
+ KeyIdx = 1;
+ else
+ KeyIdx = 0;
+ }
+ else // standard WEP64 or WEP128
+#endif // LEAP_SUPPORT //
+ KeyIdx = pAd->StaCfg.DefaultKeyId;
+ }
+ else if ((Cipher == Ndis802_11Encryption2Enabled) ||
+ (Cipher == Ndis802_11Encryption3Enabled))
+ {
+ if ((*pSrcBufVA & 0x01) && (ADHOC_ON(pAd))) // multicast
+ KeyIdx = pAd->StaCfg.DefaultKeyId;
+ else if (pAd->SharedKey[BSS0][0].KeyLen)
+ KeyIdx = 0;
+ else
+ KeyIdx = pAd->StaCfg.DefaultKeyId;
+ }
+
+ if (KeyIdx == 0xff)
+ CipherAlg = CIPHER_NONE;
+ else if ((Cipher == Ndis802_11EncryptionDisabled) || (pAd->SharedKey[BSS0][KeyIdx].KeyLen == 0))
+ CipherAlg = CIPHER_NONE;
+#ifdef WPA_SUPPLICANT_SUPPORT
+ else if ( pAd->StaCfg.WpaSupplicantUP &&
+ (Cipher == Ndis802_11Encryption1Enabled) &&
+ (pAd->StaCfg.IEEE8021X == TRUE) &&
+ (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED))
+ CipherAlg = CIPHER_NONE;
+#endif // WPA_SUPPLICANT_SUPPORT //
+ else
+ {
+ //Header_802_11.FC.Wep = 1;
+ CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
+ pKey = &pAd->SharedKey[BSS0][KeyIdx];
+ }
+ }
+
+ pTxBlk->CipherAlg = CipherAlg;
+ pTxBlk->pKey = pKey;
+}
+
+
+VOID STABuildCommon802_11Header(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk)
+{
+
+ HEADER_802_11 *pHeader_802_11;
+#ifdef QOS_DLS_SUPPORT
+ BOOLEAN bDLSFrame = FALSE;
+ INT DlsEntryIndex = 0;
+#endif // QOS_DLS_SUPPORT //
+
+ //
+ // MAKE A COMMON 802.11 HEADER
+ //
+
+ // normal wlan header size : 24 octets
+ pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
+
+ pHeader_802_11 = (HEADER_802_11 *) &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+
+ NdisZeroMemory(pHeader_802_11, sizeof(HEADER_802_11));
+
+ pHeader_802_11->FC.FrDs = 0;
+ pHeader_802_11->FC.Type = BTYPE_DATA;
+ pHeader_802_11->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA);
+
+#ifdef QOS_DLS_SUPPORT
+ if (INFRA_ON(pAd))
+ {
+ // Check if the frame can be sent through DLS direct link interface
+ // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
+ DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
+ if (DlsEntryIndex >= 0)
+ bDLSFrame = TRUE;
+ else
+ bDLSFrame = FALSE;
+ }
+#endif // QOS_DLS_SUPPORT //
+
+ if (pTxBlk->pMacEntry)
+ {
+ if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bForceNonQoS))
+ {
+ pHeader_802_11->Sequence = pTxBlk->pMacEntry->NonQosDataSeq;
+ pTxBlk->pMacEntry->NonQosDataSeq = (pTxBlk->pMacEntry->NonQosDataSeq+1) & MAXSEQ;
+ }
+ else
+ {
+#ifdef QOS_DLS_SUPPORT
+ if (bDLSFrame)
+ {
+ pHeader_802_11->Sequence = pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence;
+ pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence = (pAd->StaCfg.DLSEntry[DlsEntryIndex].Sequence+1) & MAXSEQ;
+ }
+ else
+#endif // QOS_DLS_SUPPORT //
+ {
+ pHeader_802_11->Sequence = pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority];
+ pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority] = (pTxBlk->pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
+ }
+ }
+ }
+ else
+ {
+ pHeader_802_11->Sequence = pAd->Sequence;
+ pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; // next sequence
+ }
+
+ pHeader_802_11->Frag = 0;
+
+ pHeader_802_11->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
+
+ {
+ if (INFRA_ON(pAd))
+ {
+#ifdef QOS_DLS_SUPPORT
+ if (bDLSFrame)
+ {
+ COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
+ COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
+ pHeader_802_11->FC.ToDs = 0;
+ }
+ else
+#endif // QOS_DLS_SUPPORT //
+ {
+ COPY_MAC_ADDR(pHeader_802_11->Addr1, pAd->CommonCfg.Bssid);
+ COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pHeader_802_11->Addr3, pTxBlk->pSrcBufHeader);
+ pHeader_802_11->FC.ToDs = 1;
+ }
+ }
+ else if (ADHOC_ON(pAd))
+ {
+ COPY_MAC_ADDR(pHeader_802_11->Addr1, pTxBlk->pSrcBufHeader);
+ COPY_MAC_ADDR(pHeader_802_11->Addr2, pAd->CurrentAddress);
+ COPY_MAC_ADDR(pHeader_802_11->Addr3, pAd->CommonCfg.Bssid);
+ pHeader_802_11->FC.ToDs = 0;
+ }
+ }
+
+ if (pTxBlk->CipherAlg != CIPHER_NONE)
+ pHeader_802_11->FC.Wep = 1;
+
+ // -----------------------------------------------------------------
+ // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
+ // -----------------------------------------------------------------
+ if (pAd->CommonCfg.bAPSDForcePowerSave)
+ pHeader_802_11->FC.PwrMgmt = PWR_SAVE;
+ else
+ pHeader_802_11->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
+}
+
+#ifdef DOT11_N_SUPPORT
+VOID STABuildCache802_11Header(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk,
+ IN UCHAR *pHeader)
+{
+ MAC_TABLE_ENTRY *pMacEntry;
+ PHEADER_802_11 pHeader80211;
+
+ pHeader80211 = (PHEADER_802_11)pHeader;
+ pMacEntry = pTxBlk->pMacEntry;
+
+ //
+ // Update the cached 802.11 HEADER
+ //
+
+ // normal wlan header size : 24 octets
+ pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11);
+
+ // More Bit
+ pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData);
+
+ // Sequence
+ pHeader80211->Sequence = pMacEntry->TxSeq[pTxBlk->UserPriority];
+ pMacEntry->TxSeq[pTxBlk->UserPriority] = (pMacEntry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ;
+
+ {
+ // Check if the frame can be sent through DLS direct link interface
+ // If packet can be sent through DLS, then force aggregation disable. (Hard to determine peer STA's capability)
+#ifdef QOS_DLS_SUPPORT
+ BOOLEAN bDLSFrame = FALSE;
+ INT DlsEntryIndex = 0;
+
+ DlsEntryIndex = RTMPCheckDLSFrame(pAd, pTxBlk->pSrcBufHeader);
+ if (DlsEntryIndex >= 0)
+ bDLSFrame = TRUE;
+ else
+ bDLSFrame = FALSE;
+#endif // QOS_DLS_SUPPORT //
+
+ // The addr3 of normal packet send from DS is Dest Mac address.
+#ifdef QOS_DLS_SUPPORT
+ if (bDLSFrame)
+ {
+ COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pSrcBufHeader);
+ COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
+ pHeader80211->FC.ToDs = 0;
+ }
+ else
+#endif // QOS_DLS_SUPPORT //
+ if (ADHOC_ON(pAd))
+ COPY_MAC_ADDR(pHeader80211->Addr3, pAd->CommonCfg.Bssid);
+ else
+ COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader);
+ }
+
+ // -----------------------------------------------------------------
+ // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. Fill sequence later.
+ // -----------------------------------------------------------------
+ if (pAd->CommonCfg.bAPSDForcePowerSave)
+ pHeader80211->FC.PwrMgmt = PWR_SAVE;
+ else
+ pHeader80211->FC.PwrMgmt = (pAd->StaCfg.Psm == PWR_SAVE);
+}
+#endif // DOT11_N_SUPPORT //
+
+static inline PUCHAR STA_Build_ARalink_Frame_Header(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk)
+{
+ PUCHAR pHeaderBufPtr;
+ HEADER_802_11 *pHeader_802_11;
+ PNDIS_PACKET pNextPacket;
+ UINT32 nextBufLen;
+ PQUEUE_ENTRY pQEntry;
+
+ STAFindCipherAlgorithm(pAd, pTxBlk);
+ STABuildCommon802_11Header(pAd, pTxBlk);
+
+
+ pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+ pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+ // steal "order" bit to mark "aggregation"
+ pHeader_802_11->FC.Order = 1;
+
+ // skip common header
+ pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+ if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
+ {
+ //
+ // build QOS Control bytes
+ //
+ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+
+ *(pHeaderBufPtr+1) = 0;
+ pHeaderBufPtr +=2;
+ pTxBlk->MpduHeaderLen += 2;
+ }
+
+ // padding at front of LLC header. LLC header should at 4-bytes aligment.
+ pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+ pHeaderBufPtr = (PCHAR)ROUND_UP(pHeaderBufPtr, 4);
+ pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+ // For RA Aggregation,
+ // put the 2nd MSDU length(extra 2-byte field) after QOS_CONTROL in little endian format
+ pQEntry = pTxBlk->TxPacketList.Head;
+ pNextPacket = QUEUE_ENTRY_TO_PKT(pQEntry);
+ nextBufLen = GET_OS_PKT_LEN(pNextPacket);
+ if (RTMP_GET_PACKET_VLAN(pNextPacket))
+ nextBufLen -= LENGTH_802_1Q;
+
+ *pHeaderBufPtr = (UCHAR)nextBufLen & 0xff;
+ *(pHeaderBufPtr+1) = (UCHAR)(nextBufLen >> 8);
+
+ pHeaderBufPtr += 2;
+ pTxBlk->MpduHeaderLen += 2;
+
+ return pHeaderBufPtr;
+
+}
+
+#ifdef DOT11_N_SUPPORT
+static inline PUCHAR STA_Build_AMSDU_Frame_Header(
+ IN RTMP_ADAPTER *pAd,
+ IN TX_BLK *pTxBlk)
+{
+ PUCHAR pHeaderBufPtr;//, pSaveBufPtr;
+ HEADER_802_11 *pHeader_802_11;
+
+
+ STAFindCipherAlgorithm(pAd, pTxBlk);
+ STABuildCommon802_11Header(pAd, pTxBlk);
+
+ pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+ pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+ // skip common header
+ pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+ //
+ // build QOS Control bytes
+ //
+ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+
+ //
+ // A-MSDU packet
+ //
+ *pHeaderBufPtr |= 0x80;
+
+ *(pHeaderBufPtr+1) = 0;
+ pHeaderBufPtr +=2;
+ pTxBlk->MpduHeaderLen += 2;
+
+ //pSaveBufPtr = pHeaderBufPtr;
+
+ //
+ // padding at front of LLC header
+ // LLC header should locate at 4-octets aligment
+ //
+ // @@@ MpduHeaderLen excluding padding @@@
+ //
+ pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+ pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
+ pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+ return pHeaderBufPtr;
+
+}
+
+
+VOID STA_AMPDU_Frame_Tx(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk)
+{
+ HEADER_802_11 *pHeader_802_11;
+ PUCHAR pHeaderBufPtr;
+ USHORT FreeNumber;
+ MAC_TABLE_ENTRY *pMacEntry;
+ BOOLEAN bVLANPkt;
+ PQUEUE_ENTRY pQEntry;
+
+ ASSERT(pTxBlk);
+
+ while(pTxBlk->TxPacketList.Head)
+ {
+ pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+ pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+ if ( RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+ {
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+ continue;
+ }
+
+ bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+ pMacEntry = pTxBlk->pMacEntry;
+ if (pMacEntry->isCached)
+ {
+ // NOTE: Please make sure the size of pMacEntry->CachedBuf[] is smaller than pTxBlk->HeaderBuf[]!!!!
+ NdisMoveMemory((PUCHAR)&pTxBlk->HeaderBuf[TXINFO_SIZE], (PUCHAR)&pMacEntry->CachedBuf[0], TXWI_SIZE + sizeof(HEADER_802_11));
+ pHeaderBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE]);
+ STABuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr);
+ }
+ else
+ {
+ STAFindCipherAlgorithm(pAd, pTxBlk);
+ STABuildCommon802_11Header(pAd, pTxBlk);
+
+ pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+ }
+
+
+ pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+ // skip common header
+ pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+ //
+ // build QOS Control bytes
+ //
+ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+ *(pHeaderBufPtr+1) = 0;
+ pHeaderBufPtr +=2;
+ pTxBlk->MpduHeaderLen += 2;
+
+ //
+ // build HTC+
+ // HTC control filed following QoS field
+ //
+ if ((pAd->CommonCfg.bRdg == TRUE) && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE))
+ {
+ if (pMacEntry->isCached == FALSE)
+ {
+ // mark HTC bit
+ pHeader_802_11->FC.Order = 1;
+
+ NdisZeroMemory(pHeaderBufPtr, 4);
+ *(pHeaderBufPtr+3) |= 0x80;
+ }
+ pHeaderBufPtr += 4;
+ pTxBlk->MpduHeaderLen += 4;
+ }
+
+ //pTxBlk->MpduHeaderLen = pHeaderBufPtr - pTxBlk->HeaderBuf - TXWI_SIZE - TXINFO_SIZE;
+ ASSERT(pTxBlk->MpduHeaderLen >= 24);
+
+ // skip 802.3 header
+ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+ pTxBlk->SrcBufLen -= LENGTH_802_3;
+
+ // skip vlan tag
+ if (bVLANPkt)
+ {
+ pTxBlk->pSrcBufData += LENGTH_802_1Q;
+ pTxBlk->SrcBufLen -= LENGTH_802_1Q;
+ }
+
+ //
+ // padding at front of LLC header
+ // LLC header should locate at 4-octets aligment
+ //
+ // @@@ MpduHeaderLen excluding padding @@@
+ //
+ pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+ pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
+ pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+ {
+
+ //
+ // Insert LLC-SNAP encapsulation - 8 octets
+ //
+ EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
+ if (pTxBlk->pExtraLlcSnapEncap)
+ {
+ NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+ pHeaderBufPtr += 6;
+ // get 2 octets (TypeofLen)
+ NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
+ pHeaderBufPtr += 2;
+ pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+ }
+
+ }
+
+ if (pMacEntry->isCached)
+ {
+ RTMPWriteTxWI_Cache(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+ }
+ else
+ {
+ RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+
+ NdisZeroMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), sizeof(pMacEntry->CachedBuf));
+ NdisMoveMemory((PUCHAR)(&pMacEntry->CachedBuf[0]), (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (pHeaderBufPtr - (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE])));
+ pMacEntry->isCached = TRUE;
+ }
+
+ // calculate Transmitted AMPDU count and ByteCount
+ {
+ pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++;
+ pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen;
+ }
+
+ //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
+
+ HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
+
+ //
+ // Kick out Tx
+ //
+ HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+
+ pAd->RalinkCounters.KickTxCount++;
+ pAd->RalinkCounters.OneSecTxDoneCount++;
+ }
+
+}
+
+
+VOID STA_AMSDU_Frame_Tx(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk)
+{
+ PUCHAR pHeaderBufPtr;
+ USHORT FreeNumber;
+ USHORT subFramePayloadLen = 0; // AMSDU Subframe length without AMSDU-Header / Padding.
+ USHORT totalMPDUSize=0;
+ UCHAR *subFrameHeader;
+ UCHAR padding = 0;
+ USHORT FirstTx = 0, LastTxIdx = 0;
+ BOOLEAN bVLANPkt;
+ int frameNum = 0;
+ PQUEUE_ENTRY pQEntry;
+
+
+ ASSERT(pTxBlk);
+
+ ASSERT((pTxBlk->TxPacketList.Number > 1));
+
+ while(pTxBlk->TxPacketList.Head)
+ {
+ pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+ pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+ if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+ {
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+ continue;
+ }
+
+ bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+ // skip 802.3 header
+ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+ pTxBlk->SrcBufLen -= LENGTH_802_3;
+
+ // skip vlan tag
+ if (bVLANPkt)
+ {
+ pTxBlk->pSrcBufData += LENGTH_802_1Q;
+ pTxBlk->SrcBufLen -= LENGTH_802_1Q;
+ }
+
+ if (frameNum == 0)
+ {
+ pHeaderBufPtr = STA_Build_AMSDU_Frame_Header(pAd, pTxBlk);
+
+ // NOTE: TxWI->MPDUtotalByteCount will be updated after final frame was handled.
+ RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+ }
+ else
+ {
+ pHeaderBufPtr = &pTxBlk->HeaderBuf[0];
+ padding = ROUND_UP(LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen, 4) - (LENGTH_AMSDU_SUBFRAMEHEAD + subFramePayloadLen);
+ NdisZeroMemory(pHeaderBufPtr, padding + LENGTH_AMSDU_SUBFRAMEHEAD);
+ pHeaderBufPtr += padding;
+ pTxBlk->MpduHeaderLen = padding;
+ }
+
+ //
+ // A-MSDU subframe
+ // DA(6)+SA(6)+Length(2) + LLC/SNAP Encap
+ //
+ subFrameHeader = pHeaderBufPtr;
+ subFramePayloadLen = pTxBlk->SrcBufLen;
+
+ NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12);
+
+
+ pHeaderBufPtr += LENGTH_AMSDU_SUBFRAMEHEAD;
+ pTxBlk->MpduHeaderLen += LENGTH_AMSDU_SUBFRAMEHEAD;
+
+
+ //
+ // Insert LLC-SNAP encapsulation - 8 octets
+ //
+ EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
+
+ subFramePayloadLen = pTxBlk->SrcBufLen;
+
+ if (pTxBlk->pExtraLlcSnapEncap)
+ {
+ NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+ pHeaderBufPtr += 6;
+ // get 2 octets (TypeofLen)
+ NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData-2, 2);
+ pHeaderBufPtr += 2;
+ pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+ subFramePayloadLen += LENGTH_802_1_H;
+ }
+
+ // update subFrame Length field
+ subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8;
+ subFrameHeader[13] = subFramePayloadLen & 0xFF;
+
+ totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen;
+
+ if (frameNum ==0)
+ FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
+ else
+ LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &FreeNumber);
+
+ frameNum++;
+
+ pAd->RalinkCounters.KickTxCount++;
+ pAd->RalinkCounters.OneSecTxDoneCount++;
+
+ // calculate Transmitted AMSDU Count and ByteCount
+ {
+ pAd->RalinkCounters.TransmittedAMSDUCount.u.LowPart ++;
+ pAd->RalinkCounters.TransmittedOctetsInAMSDU.QuadPart += totalMPDUSize;
+ }
+
+ }
+
+ HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx);
+ HAL_LastTxIdx(pAd, pTxBlk->QueIdx, LastTxIdx);
+
+ //
+ // Kick out Tx
+ //
+ HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+}
+#endif // DOT11_N_SUPPORT //
+
+VOID STA_Legacy_Frame_Tx(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk)
+{
+ HEADER_802_11 *pHeader_802_11;
+ PUCHAR pHeaderBufPtr;
+ USHORT FreeNumber;
+ BOOLEAN bVLANPkt;
+ PQUEUE_ENTRY pQEntry;
+
+ ASSERT(pTxBlk);
+
+
+ pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+ pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+ if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+ {
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+ return;
+ }
+
+ if (pTxBlk->TxFrameType == TX_MCAST_FRAME)
+ {
+ INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount);
+ }
+
+ if (RTMP_GET_PACKET_RTS(pTxBlk->pPacket))
+ TX_BLK_SET_FLAG(pTxBlk, fTX_bRtsRequired);
+ else
+ TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bRtsRequired);
+
+ bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+ if (pTxBlk->TxRate < pAd->CommonCfg.MinTxRate)
+ pTxBlk->TxRate = pAd->CommonCfg.MinTxRate;
+
+ STAFindCipherAlgorithm(pAd, pTxBlk);
+ STABuildCommon802_11Header(pAd, pTxBlk);
+
+
+ // skip 802.3 header
+ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+ pTxBlk->SrcBufLen -= LENGTH_802_3;
+
+ // skip vlan tag
+ if (bVLANPkt)
+ {
+ pTxBlk->pSrcBufData += LENGTH_802_1Q;
+ pTxBlk->SrcBufLen -= LENGTH_802_1Q;
+ }
+
+ pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWI_SIZE];
+ pHeader_802_11 = (HEADER_802_11 *) pHeaderBufPtr;
+
+ // skip common header
+ pHeaderBufPtr += pTxBlk->MpduHeaderLen;
+
+ if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM))
+ {
+ //
+ // build QOS Control bytes
+ //
+ *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F);
+ *(pHeaderBufPtr+1) = 0;
+ pHeaderBufPtr +=2;
+ pTxBlk->MpduHeaderLen += 2;
+ }
+
+ // The remaining content of MPDU header should locate at 4-octets aligment
+ pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr;
+ pHeaderBufPtr = (PCHAR) ROUND_UP(pHeaderBufPtr, 4);
+ pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen);
+
+ {
+
+ //
+ // Insert LLC-SNAP encapsulation - 8 octets
+ //
+ //
+ // if original Ethernet frame contains no LLC/SNAP,
+ // then an extra LLC/SNAP encap is required
+ //
+ EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, pTxBlk->pExtraLlcSnapEncap);
+ if (pTxBlk->pExtraLlcSnapEncap)
+ {
+ UCHAR vlan_size;
+
+ NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+ pHeaderBufPtr += 6;
+ // skip vlan tag
+ vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0;
+ // get 2 octets (TypeofLen)
+ NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufHeader+12+vlan_size, 2);
+ pHeaderBufPtr += 2;
+ pTxBlk->MpduHeaderLen += LENGTH_802_1_H;
+ }
+
+ }
+
+ //
+ // prepare for TXWI
+ // use Wcid as Key Index
+ //
+
+ RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+
+ //FreeNumber = GET_TXRING_FREENO(pAd, QueIdx);
+
+ HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber);
+
+ pAd->RalinkCounters.KickTxCount++;
+ pAd->RalinkCounters.OneSecTxDoneCount++;
+
+ //
+ // Kick out Tx
+ //
+ HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx);
+}
+
+
+VOID STA_ARalink_Frame_Tx(
+ IN PRTMP_ADAPTER pAd,
+ IN TX_BLK *pTxBlk)
+{
+ PUCHAR pHeaderBufPtr;
+ USHORT FreeNumber;
+ USHORT totalMPDUSize=0;
+ USHORT FirstTx, LastTxIdx;
+ int frameNum = 0;
+ BOOLEAN bVLANPkt;
+ PQUEUE_ENTRY pQEntry;
+
+
+ ASSERT(pTxBlk);
+
+ ASSERT((pTxBlk->TxPacketList.Number== 2));
+
+
+ FirstTx = LastTxIdx = 0; // Is it ok init they as 0?
+ while(pTxBlk->TxPacketList.Head)
+ {
+ pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList);
+ pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
+
+ if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE)
+ {
+ RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE);
+ continue;
+ }
+
+ bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE);
+
+ // skip 802.3 header
+ pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3;
+ pTxBlk->SrcBufLen -= LENGTH_802_3;
+
+ // skip vlan tag
+ if (bVLANPkt)
+ {
+ pTxBlk->pSrcBufData += LENGTH_802_1Q;
+ pTxBlk->SrcBufLen -= LENGTH_802_1Q;
+ }
+
+ if (frameNum == 0)
+ { // For first frame, we need to create the 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header
+
+ pHeaderBufPtr = STA_Build_ARalink_Frame_Header(pAd, pTxBlk);
+
+ // It's ok write the TxWI here, because the TxWI->MPDUtotalByteCount
+ // will be updated after final frame was handled.
+ RTMPWriteTxWI_Data(pAd, (PTXWI_STRUC)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), pTxBlk);
+
+
+ //
+ // Insert LLC-SNAP encapsulation - 8 octets
+ //
+ EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData-2, pTxBlk->pExtraLlcSnapEncap);
+
+ if (pTxBlk->pExtraLlcSnapEncap)
+ {
+ NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6);
+ pHeaderBufPtr += 6;